diff -Nru ffmpeg-4.2.2/Changelog ffmpeg-4.4/Changelog --- ffmpeg-4.2.2/Changelog 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/Changelog 2021-04-08 21:28:39.000000000 +0000 @@ -1,303 +1,165 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. -version 4.2.2 -- cbs_mpeg2: Fix parsing the last unit -- cbs_mpeg2: Rearrange start code search -- cbs_mpeg2: Decompose Sequence End -- cbs_mpeg2: Fix parsing of picture and slice headers -- cbs: Remove useless initializations -- mpeg2_metadata, cbs_mpeg2: Fix handling of colour_description -- lavc/cbs_h2645_syntax_template: Fix memleak -- avcodec/cbs: Fix potential overflow -- avcodec/cbs: Factor out common code for writing units -- avcodec/ffwavesynth: Fix undefined overflow in wavesynth_synth_sample() -- avcodec/ffwavesynth: Fix undefined overflow in wavesynth_synth_sample() -- avcodec/cook: Use 3 stage VLC decoding for channel_coupling -- avcodec/wmalosslessdec: Fixes undefined overflow in dequantization in decode_subframe() -- avcodec/sonic: Check e in get_symbol() -- avcodec/twinvqdec: Correct overflow in block align check -- avcodec/vc1dec: Fix "return -1" cases -- avcodec/vc1dec: Free sprite_output_frame on error -- avcodec/atrac9dec: Clamp band_ext_data to max that can be read if skipped. -- avcodec/agm: Include block size in the MV check for flags == 3 -- avcodec/wmadec: Keep track of exponent initialization per channel -- avcodec/iff: Check that video_size is large enough for the read parameters -- avcodec/cbs_vp9: Check data_size -- avcodec/cbs_vp9: Check index_size -- avcodec/adpcm: Clip predictor for APC -- avcodec/targa: Check colors vs. available space -- avcodec/dstdec: Use get_ur_golomb_jpegls() -- avcodec/wmavoice: Check remaining input in parse_packet_header() -- avcodec/wmalosslessdec: Fix 2 overflows in mclms -- avcodec/wmaprodec: Fixes integer overflow with 32bit samples -- avcodec/adpcm: Fix invalid shift in xa_decode() -- avcodec/wmalosslessdec: Fix several integer issues -- avcodec/wmalosslessdec: Check that padding bits is not more than sample bits -- avcodec/iff: Skip overflowing runs in decode_delta_d() -- avcodec/pnm: Check that the header is not truncated -- avcodec/mp3_header_decompress_bsf: Check sample_rate_index -- avcodec/cbs_av1_syntax_template: Check num_y_points -- avformat/rmdec: Initialize and sanity check offset in ivr_read_header() -- avcodec/agm: Do not allow MVs out of the picture area as no edge is allocated -- avcodec/apedec: Fix 2 integer overflows -- avformat/id3v2: Fix double-free on error -- avcodec/wmaprodec: Set packet_loss when we error out on a sanity check -- avcodec/wmaprodec: Check offset -- avcodec/truemotion2: Fix 2 integer overflows in tm2_low_res_block() -- avcodec/wmaprodec: Check if the channel sum of all internal contexts match the external -- avcodec/atrac9dec: Check q_unit_cnt more completely before using it to access at9_tab_band_ext_group -- avcodec/fitsdec: Use lrint() -- avcodec/g729dec: Avoid using buf_size -- avcodec/g729dec: Factor block_size out -- avcodec/g729dec: require buf_size to be non 0 -- avcodec/alac: Fix integer overflow in lpc_prediction() with sign -- avcodec/wmaprodec: Fix buflen computation in save_bits() -- avcodec/vc1_block: Fix integer overflow in AC rescaling in vc1_decode_i_block_adv() -- avcodec/vmdaudio: Check chunk counts to avoid integer overflow -- avformat/mxfdec: Clear metadata_sets_count in mxf_read_close() -- avcodec/nuv: Use ff_set_dimensions() -- avformat/vividas: Error out on audio packets in the absence of audio streams -- avformat/vividas: Check and require 1 video stream -- avcodec/ffwavesynth: Fix integer overflow with pink_ts_cur/next -- avcodec/ralf: Fix integer overflows with the filter coefficient in decode_channel() -- avcodec/g729dec: Use 64bit and clip in scalar product -- avcodec/mxpegdec: Check for multiple SOF -- avcodec/nuv: Move comptype check up -- avcodec/wmavoice: Fix integer overflow in synth_frame() -- avcodec/rawdec: Check bits_per_coded_sample more pedantically for 16bit cases -- avutil/lfg: Correct index increment type to avoid undefined behavior -- avcodec/cngdec: Remove AV_CODEC_CAP_DELAY -- avcodec/iff: Move index use after check in decodeplane8() -- avcodec/atrac3: Check for huge block aligns -- avcodec/ralf: use multiply instead of shift to avoid undefined behavior in decode_block() -- avcodec/wmadec: Require previous exponents for reuse -- avcodec/vc1_block: Fix undefined behavior in ac prediction rescaling -- avcodec/qdm2: The smallest header seems to have 2 bytes so treat 1 as invalid -- avcodec/apedec: Fixes integer overflow of res+*data in do_apply_filter() -- avcodec/sonic: Fix integer overflow in predictor_calc_error() -- avformat/vividas: Add EOF check in val_1 loop in track_header() -- avcodec/atrac9dec: Check precision_fine/coarse -- avformat/mp3dec: Check that the frame fits within the probe buffer -- vcodec/agm: Alloc based on coded dimensions -- avcodec/wmaprodec: get frame during frame decode -- avcodec/interplayacm: Fix overflow of last unused value -- avcodec/adpcm: Fix undefined behavior with negative predictions in IMA OKI -- avcodec/cook: Move up and extend block_align check -- avcodec/sbcdec: Fix integer overflows in sbc_synthesize_four() -- avcodec/twinvq: Check block_align -- avcodec/cook: Enlarge gain table -- avcodec/cook: Check samples_per_channel earlier -- avcodec/atrac3plus: Check split point in fill mode 3 -- avcodec/wmavoice: Check sample_rate -- avcodec/xsubdec: fix overflow in alpha handling -- avcodec/iff: Check available space before entering loop in decode_long_vertical_delta2() / decode_long_vertical_delta() -- avcodec/apedec: Fix integer overflow in filter_3800() -- avutil/lfg: Document the AVLFG struct -- avcodec/ffv1dec: Use a different error message for the slice level CRC -- avcodec/apedec: Fix undefined integer overflow in long_filter_ehigh_3830() -- avcodec/dstdec: Check that AC probabilities are within range -- avcodec/dstdec: Check read_table() for failure -- avformat/vividas: Fix n_sb_blocks Check -- avcodec/snowenc: Set mb_num to avoid ratecontrol floating point divisions by 0.0 -- avcodec/snowenc: Fix 2 undefined shifts -- avformat/nutenc: Do not pass NULL to memcmp() in get_needed_flags() -- avcodec/aptx: Check the number of channels -- avcodec/aacdec_template: Check samplerate -- avcodec/truemotion2: Fix several integer overflows in tm2_low_res_block() -- avcodec/utils: Check block_align -- avcodec/wmalosslessdec: Fix some integer anomalies -- avcodec/adpcm: Fix invalid shifts in ADPCM DTK -- avcodec/apedec: Only clear the needed buffer space, instead of all -- avcodec/libvorbisdec: Fix insufficient input checks leading to out of array reads -- avcodec/g723_1dec: fix invalid shift with negative sid_gain -- avcodec/vp5: Check render_x/y -- avcodec/hcom: Check the root entry and the right entries -- avcodec/qdrw: Check input for header/skiped space before get_buffer() -- avcodec/ralf: Skip initializing unused filter variables -- avcodec/takdec: Fix overflow with large sample rates -- avcodec/atrac9dec: Set channels -- avcodec/alsdec: Check that input space for header exists in read_diff_float_data() -- avformat/pjsdec: Check duration for overflow -- avcodec/agm: Check for reference frame earlier -- avcodec/ptx: Check that the input contains at least one line -- avcodec/alac: Fix integer overflow in LPC -- avcodec/smacker: Fix integer overflows in pred[] in smka_decode_frame() -- avcodec/aliaspixdec: Check input size against minimal picture size -- avcodec/ffwavesynth: Fix integer overflows in pink noise addition -- avcodec/vc1_block: Fixes integer overflow in vc1_decode_i_block_adv() -- avcodec/wmalosslessdec: Check block_align -- avcodec/g729dec: Avoid computing invalid temporary pointers for ff_acelp_weighted_vector_sum() -- avcodec/g729postfilter: Fix left shift of negative value -- avcodec/binkaudio: Check sample rate -- avcodec/sbcdec: Fix integer overflows in sbc_synthesize_eight() -- avcodec/adpcm: Check initial predictor for ADPCM_IMA_EA_EACS -- avcodec/g723_1dec: Fix overflow in shift -- avcodec/apedec: Fix integer overflow in predictor_update_3930() -- avcodec/g729postfilter: Fix undefined intermediate pointers -- avcodec/g729postfilter: Fix undefined shifts -- avcodec/lsp: Fix undefined shifts in lsp2poly() -- avcodec/adpcm: Fix left shifts in AV_CODEC_ID_ADPCM_EA -- avformat/shortendec: Check k in probe -- avfilter/vf_geq: Use av_clipd() instead of av_clipf() -- avcodec/wmaprodec: Check that the streams channels do not exceed the overall channels -- avcodec/qdmc: Check input space in qdmc_get_vlc() -- avcodec/wmaprodec: Fix cleanup on error -- avcodec/pcm: Check bits_per_coded_sample -- avcodec/exr: Allow duplicate use of channel indexes -- avcodec/fitsdec: Fail on 0 naxisn -- avcodec/dxv: Subtract 12 earlier in dxv_decompress_cocg() -- libavcodec/dxv: Remove redundant seek -- avcodec/ituh263dec: Check input for minimal frame size -- avcodec/truemotion1: Check that the input has enough space for a minimal index_stream -- avformat/mpsubdec: Clear queue on error -- avcodec/sunrast: Check that the input is large enough for the maximally compressed image -- avcodec/sunrast: Check for availability of maplength before allocating image -- avformat/subtitles: Check nb_subs in ff_subtitles_queue_finalize() -- avcodec/vc1_block: Fix invalid left shift in vc1_decode_p_mb() -- avcodec/wmaprodec: Check if there is a stream -- avcodec/g2meet: Check for end of input in jpg_decode_block() -- avcodec/g2meet: Check if adjusted pixel was on the stack -- avformat/electronicarts: If no packet has been read at the end do not treat it as if theres a packet -- avcodec/dxv: Check op_offset in dxv_decompress_yo() -- avcodec/utils: Check sample_rate before opening the decoder -- avcodec/aptx: Fix multiple shift anomalies -- avcodec/fitsdec: fix use of uninitialised values -- avcodec/motionpixels: Mark 2 functions as always_inline -- avcodec/ituh263dec: Make the condition for the studio slice start code match between ff_h263_resync() and ff_mpeg4_decode_studio_slice_header() -- avcodec/ralf: Fix integer overflow in decode_channel() -- vcodec/vc1: compute rangex/y only for P/B frames -- avcodec/vc1_pred: Fix invalid shifts in scaleforopp() -- avcodec/vc1_block: Fix invalid shift with rangeredfrm -- avcodec/vc1: Check for excessive resolution -- avcodec/vc1: check REFDIST -- avcodec/apedec: Fix several integer overflows in predictor_update_filter() and do_apply_filter() -- avcodec/hevc_cabac: Tighten the limit on k in ff_hevc_cu_qp_delta_abs() -- avcodec/4xm: Check index in decode_i_block() also in the path where its not used. -- avcodec/loco: Check for end of input in the first line -- avcodec/atrac3: Check block_align -- avcodec/alsdec: Avoid dereferencing context pointer in inner interleave loop -- avcodec/hcom: Check that there are dictionary entries -- avcodec/fitsdec: Prevent division by 0 with huge data_max -- avcodec/dstdec: Fix integer overflow in samples_per_frame computation -- avcodec/g729_parser: Check block_size -- avcodec/sbcdec: Initialize number of channels -- avcodec/utils: Optimize ff_color_frame() using memcpy() -- avcodec/aacdec: Check if we run out of input in read_stream_mux_config() -- avcodec/utils: Use av_memcpy_backptr() in ff_color_frame() -- avcodec/smacker: Fix integer overflow in signed int multiply in SMK_BLK_FILL -- avcodec/alac: Fix invalid shifts in 20/24 bps -- avcodec/alac: fix undefined behavior with INT_MIN in lpc_prediction() -- avcodec/ffwavesynth: Fix integer overflow in timestamps -- avformat/vividas: Test size and packet numbers a bit more -- avformat/vividas: Check n_sb_blocks against input space -- avcodec/dxv: Check op_offset in both directions -- avcodec/adpcm: Check number of channels for MTAF -- avcodec/sunrast: Fix indention -- avcodec/sunrast: Fix return type for "unsupported (compression) type" -- avcodec/utils: Check channels fully earlier -- avformat/mov: Check for EOF in mov_read_meta() -- avcodec/hevcdec: Fix memleak of a53_caption -- avformat/vividas: Remove align offset which is always masked off -- avformat/vividas: remove dead assignment -- avformat/cdxl: Fix integer overflow in intermediate -- avcodec/hevcdec: repeat character in skiped -- repeat an even number of characters in occured -- avcodec/gdv: Replace assert() checking bitstream by if() -- libavcodec/utils: Free threads on init failure -- avcodec/htmlsubtitles: Avoid locale dependant isdigit() -- avcodec/alsdec: Check k from being outside what our implementation can handle -- avcodec/takdec: Fix integer overflow in decorrelate() -- avcodec/aacps: Fix integer overflows in hybrid_synthesis() -- avcodec/mpeg4videodec: Fix integer overflow in mpeg4_decode_studio_block() -- avcodec/vp56rac: delay signaling an error on truncated input -- avcodec/pnm_parser: Use memchr() in pnm_parse() -- tests: Fix bash errors in lavf_container tests. -- avformat/matroskadec: Fix use-after-free when demuxing ProRes -- avformat/matroskadec: Fix demuxing ProRes -- avcodec/cbs_av1: fix array size for ar_coeffs_cb_plus_128 and ar_coeffs_cr_plus_128 -- avcodec/cbs_av1: avoid reading trailing bits when obu type is OBU_TILE_LIST -- lavc/cbs_h2645: Fix incorrect max size of nalu unit -- avcodec/extract_extradata_bsf: Don't unref uninitialized buffers -- avformat/av1: Fix leak of dynamic buffer in case of parsing failure -- libavformat/rtsp: return error if rtsp_hd_out is null instead of crash -- cbs_h264: Fix missing inferred colour description fields -- avcodec/cbs_av1: keep separate reference frame state for reading and writing -- avcodec/cbs_av1: fix reading reference order hint in skip_mode_params() -- avcodec/amfnec: allocate packets using av_new_packet() -- avcodec/nvenc: make sure newly allocated packets are refcounted -- lavc/mpeg4audio: add chan_config check to avoid indeterminate channels -- aformat/movenc: add missing padding to output track extradata -- avcodec/nvenc: add driver version info for SDK 9.1 -- avcodec/bsf: check that AVBSFInternal was allocated before dereferencing it +version : +- AudioToolbox output device +- MacCaption demuxer +- PGX decoder +- chromanr video filter +- VDPAU accelerated HEVC 10/12bit decoding +- ADPCM IMA Ubisoft APM encoder +- Rayman 2 APM muxer +- AV1 encoding support SVT-AV1 +- Cineform HD encoder +- ADPCM Argonaut Games encoder +- Argonaut Games ASF muxer +- AV1 Low overhead bitstream format demuxer +- RPZA video encoder +- ADPCM IMA MOFLEX decoder +- MobiClip FastAudio decoder +- MobiClip video decoder +- MOFLEX demuxer +- MODS demuxer +- PhotoCD decoder +- MCA demuxer +- AV1 decoder (Hardware acceleration used only) +- SVS demuxer +- Argonaut Games BRP demuxer +- DAT demuxer +- aax demuxer +- IPU decoder, parser and demuxer +- Intel QSV-accelerated AV1 decoding +- Argonaut Games Video decoder +- libwavpack encoder removed +- ACE demuxer +- AVS3 demuxer +- AVS3 video decoder via libuavs3d +- Cintel RAW decoder +- VDPAU accelerated VP9 10/12bit decoding +- afreqshift and aphaseshift filters +- High Voltage Software ADPCM encoder +- LEGO Racers ALP (.tun & .pcm) muxer +- AV1 VAAPI decoder +- adenorm filter +- ADPCM IMA AMV encoder +- AMV muxer +- NVDEC AV1 hwaccel +- DXVA2/D3D11VA hardware accelerated AV1 decoding +- speechnorm filter +- SpeedHQ encoder +- asupercut filter +- asubcut filter +- Microsoft Paint (MSP) version 2 decoder +- Microsoft Paint (MSP) demuxer +- AV1 monochrome encoding support via libaom >= 2.0.1 +- asuperpass and asuperstop filter +- shufflepixels filter +- tmidequalizer filter +- estdif filter +- epx filter +- Dolby E parser +- shear filter +- kirsch filter +- colortemperature filter +- colorcontrast filter +- PFM encoder +- colorcorrect filter +- binka demuxer +- XBM parser +- xbm_pipe demuxer +- colorize filter +- CRI parser +- aexciter audio filter +- exposure video filter +- monochrome video filter +- setts bitstream filter +- vif video filter +- OpenEXR image encoder +- Simbiosis IMX decoder +- Simbiosis IMX demuxer +- Digital Pictures SGA demuxer and decoders +- TTML subtitle encoder and muxer +- identity video filter +- msad video filter +- gophers protocol +- RIST protocol via librist + + +version 4.3: +- v360 filter +- Intel QSV-accelerated MJPEG decoding +- Intel QSV-accelerated VP9 decoding +- Support for TrueHD in mp4 +- Support AMD AMF encoder on Linux (via Vulkan) +- IMM5 video decoder +- ZeroMQ protocol +- support Sipro ACELP.KELVIN decoding +- streamhash muxer +- sierpinski video source +- scroll video filter +- photosensitivity filter +- anlms filter +- arnndn filter +- bilateral filter +- maskedmin and maskedmax filters +- VDPAU VP9 hwaccel +- median filter +- QSV-accelerated VP9 encoding +- AV1 encoding support via librav1e +- AV1 frame merge bitstream filter +- AV1 Annex B demuxer +- axcorrelate filter +- mvdv decoder +- mvha decoder +- MPEG-H 3D Audio support in mp4 +- thistogram filter +- freezeframes filter +- Argonaut Games ADPCM decoder +- Argonaut Games ASF demuxer +- xfade video filter +- xfade_opencl filter +- afirsrc audio filter source +- pad_opencl filter +- Simon & Schuster Interactive ADPCM decoder +- Real War KVAG demuxer +- CDToons video decoder +- siren audio decoder +- Rayman 2 ADPCM decoder +- Rayman 2 APM demuxer +- cas video filter +- High Voltage Software ADPCM decoder +- LEGO Racers ALP (.tun & .pcm) demuxer +- AMQP 0-9-1 protocol (RabbitMQ) +- Vulkan support +- avgblur_vulkan, overlay_vulkan, scale_vulkan and chromaber_vulkan filters +- ADPCM IMA MTF decoder +- FWSE demuxer +- DERF DPCM decoder +- DERF demuxer +- CRI HCA decoder +- CRI HCA demuxer +- overlay_cuda filter +- switch from AvxSynth to AviSynth+ on Linux +- mv30 decoder +- Expanded styling support for 3GPP Timed Text Subtitles (movtext) +- WebP parser +- tmedian filter +- maskedthreshold filter +- Support for muxing pcm and pgs in m2ts +- Cunning Developments ADPCM decoder +- asubboost filter +- Pro Pinball Series Soundbank demuxer +- pcm_rechunk bitstream filter +- scdet filter +- NotchLC decoder +- gradients source video filter +- MediaFoundation encoder wrapper +- untile filter +- Simon & Schuster Interactive ADPCM encoder +- PFM decoder +- dblur video filter +- Real War KVAG muxer -version 4.2.1: -- avformat/vividas: check for tiny blocks using alignment -- avcodec/vc1_pred: Fix refdist in scaleforopp() -- avcodec/vorbisdec: fix FASTDIV usage for vr_type == 2 -- avcodec/iff: Check for overlap in cmap_read_palette() -- avcodec/apedec: Fix 32bit int overflow in do_apply_filter() -- lavf/rawenc: Only accept the appropriate stream type for raw muxers. -- avformat/matroskadec: use av_fast_realloc to reallocate ebml list arrays -- avformat/matroskadec: use proper types for some EbmlSyntax fields -- avcodec/ralf: fix undefined shift in extend_code() -- avcodec/ralf: fix undefined shift -- avcodec/bgmc: Check input space in ff_bgmc_decode_init() -- avcodec/vp3: Check for end of input in 2 places of vp4_unpack_macroblocks() -- avcodec/truemotion2: Fix multiple integer overflows in tm2_null_res_block() -- avcodec/vc1_block: Check the return code from vc1_decode_p_block() -- avcodec/vc1dec: Require res_sprite for wmv3images -- avcodec/vc1_block: Check for double escapes -- avcodec/vorbisdec: Check get_vlc2() failure -- avcodec/tta: Fix integer overflow in prediction -- avcodec/vb: Check input packet size to be large enough to contain flags -- avcodec/cavsdec: Limit the number of access units per packet to 2 -- avcodec/atrac9dec: Check block_align -- avcodec/alac: Check for bps of 0 -- avcodec/alac: Fix multiple integer overflows in lpc_prediction() -- avcodec/rl2: set dimensions -- avcodec/aacdec: Add FF_CODEC_CAP_INIT_CLEANUP -- avcodec/idcinvideo: Add 320x240 default maximum resolution -- avformat/realtextdec: free queue on error -- avcodec/vp5/6/8: use vpX_rac_is_end() -- avformat/vividas: Check av_xiphlacing() return value before use -- avcodec/alsdec: Fix integer overflow in decode_var_block_data() -- avcodec/alsdec: Limit maximum channels to 512 -- avcodec/anm: Check input size for a frame with just a stop code -- avcodec/flicvideo: Optimize and Simplify FLI_COPY in flic_decode_frame_24BPP() by using bytestream2_get_buffer() -- avcodec/loco: Check left column value -- avcodec/ffwavesynth: Fixes invalid shift with pink noise seeking -- avcodec/ffwavesynth: Fix integer overflow for some corner case values -- avcodec/indeo2: Check remaining input more often -- avcodec/diracdec: Check that slices are fewer than pixels -- avcodec/vp56: Consider the alpha start as end of the prior header -- avcodec/4xm: Check for end of input in decode_p_block() -- avcodec/hevcdec: Check delta_luma_weight_l0/1 -- avcodec/hnm4video: Optimize postprocess_current_frame() -- avcodec/hevc_refs: Optimize 16bit generate_missing_ref() -- avcodec/scpr: Use av_memcpy_backptr() in type 17 and 33 -- avcodec/tiff: Enforce increasing offsets -- avcodec/dds: Use ff_set_dimensions() -- avformat/vividas: Fix another infinite loop -- avformat/vividas: Fix infinite loop in header parser -- avcodec/mpc8: Fix 32bit mask/enum -- avcodec/alsdec: Fix integer overflows of raw_samples in decode_var_block_data() -- avcodec/alsdec: Fix integer overflow of raw_samples in decode_blocks() -- avcodec/alsdec: fix mantisse shift -- avcodec/pngdec: consider chunk size in minimal size check -- avcodec/vc1_block: Fix invalid shifts in vc1_decode_i_blocks() -- avcodec/vc1_block: fix invalid shift in vc1_decode_p_mb() -- avcodec/aacdec_template: fix integer overflow in imdct_and_windowing() -- avformat/mpegts: Check if ready on SCTE reception -- avcodec/omx: fix xFramerate calculation -- avformat/avidec: add support for recognizing HEVC fourcc when demuxing -- avformat/mpegts: fix teletext PTS when selecting teletext streams only -- avcodec/h2645_parse: zero initialize the rbsp buffer -- avcodec/omx: Fix handling of fragmented buffers -- avcodec/omx: ensure zerocopy mode can be disabled on rpi builds -- avformat/mxfdec: do not ignore bad size errors -- avformat/matroskadec: Fix seeking -- ffplay: properly detect all window size changes version 4.2: - tpad filter diff -Nru ffmpeg-4.2.2/compat/avisynth/avisynth_c.h ffmpeg-4.4/compat/avisynth/avisynth_c.h --- ffmpeg-4.2.2/compat/avisynth/avisynth_c.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/compat/avisynth/avisynth_c.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,1264 +0,0 @@ -// Avisynth C Interface Version 0.20 -// Copyright 2003 Kevin Atkinson - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that 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 this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA, or visit -// http://www.gnu.org/copyleft/gpl.html . -// -// As a special exception, I give you permission to link to the -// Avisynth C interface with independent modules that communicate with -// the Avisynth C interface solely through the interfaces defined in -// avisynth_c.h, regardless of the license terms of these independent -// modules, and to copy and distribute the resulting combined work -// under terms of your choice, provided that every copy of the -// combined work is accompanied by a complete copy of the source code -// of the Avisynth C interface and Avisynth itself (with the version -// used to produce the combined work), being distributed under the -// terms of the GNU General Public License plus this exception. An -// independent module is a module which is not derived from or based -// on Avisynth C Interface, such as 3rd-party filters, import and -// export plugins, or graphical user interfaces. - -// NOTE: this is a partial update of the Avisynth C interface to recognize -// new color spaces added in Avisynth 2.60. By no means is this document -// completely Avisynth 2.60 compliant. -// 170103: added new CPU constants (FMA4, AVX512xx) -// 171102: define SIZETMOD. do not use yet, experimental. Offsets are size_t instead of int. Affects x64. -// 171106: avs_get_row_size calls into avs_get_row_size_p, instead of direct field access -// 171106: avs_get_height calls into avs_get_row_size_p, instead of direct field access -// 180524: AVSC_EXPORT to dllexport in capi.h for avisynth_c_plugin_init -// 180524: avs_is_same_colorspace VideoInfo parameters to const -// 181230: Readability: functions regrouped to mix less AVSC_API and AVSC_INLINE, put together Avisynth+ specific stuff -// 181230: use #ifndef AVSC_NO_DECLSPEC for AVSC_INLINE functions which are calling API functions -// 181230: comments on avs_load_library (helper for loading API entries dynamically into a struct using AVSC_NO_DECLSPEC define) -// 181230: define alias AVS_FRAME_ALIGN as FRAME_ALIGN -// 181230: remove unused form of avs_get_rowsize and avs_get_height (kept earlier for reference) -// 190104: avs_load_library: smart fallback mechanism for Avisynth+ specific functions: -// if they are not loadable, they will work in a classic Avisynth compatible mode -// Example#1: e.g. avs_is_444 will call the existing avs_is_yv24 instead -// Example#2: avs_bits_per_component will return 8 for all colorspaces (Classic Avisynth supports only 8 bits/pixel) -// Thus the Avisynth+ specific API functions are safely callable even when connected to classic Avisynth DLL - -#ifndef __AVISYNTH_C__ -#define __AVISYNTH_C__ - -#include "avs/config.h" -#include "avs/capi.h" -#include "avs/types.h" - -#define AVS_FRAME_ALIGN FRAME_ALIGN -///////////////////////////////////////////////////////////////////// -// -// Constants -// - -#ifndef __AVISYNTH_6_H__ -enum { AVISYNTH_INTERFACE_VERSION = 6 }; -#endif - -enum {AVS_SAMPLE_INT8 = 1<<0, - AVS_SAMPLE_INT16 = 1<<1, - AVS_SAMPLE_INT24 = 1<<2, - AVS_SAMPLE_INT32 = 1<<3, - AVS_SAMPLE_FLOAT = 1<<4}; - -enum {AVS_PLANAR_Y=1<<0, - AVS_PLANAR_U=1<<1, - AVS_PLANAR_V=1<<2, - AVS_PLANAR_ALIGNED=1<<3, - AVS_PLANAR_Y_ALIGNED=AVS_PLANAR_Y|AVS_PLANAR_ALIGNED, - AVS_PLANAR_U_ALIGNED=AVS_PLANAR_U|AVS_PLANAR_ALIGNED, - AVS_PLANAR_V_ALIGNED=AVS_PLANAR_V|AVS_PLANAR_ALIGNED, - AVS_PLANAR_A=1<<4, - AVS_PLANAR_R=1<<5, - AVS_PLANAR_G=1<<6, - AVS_PLANAR_B=1<<7, - AVS_PLANAR_A_ALIGNED=AVS_PLANAR_A|AVS_PLANAR_ALIGNED, - AVS_PLANAR_R_ALIGNED=AVS_PLANAR_R|AVS_PLANAR_ALIGNED, - AVS_PLANAR_G_ALIGNED=AVS_PLANAR_G|AVS_PLANAR_ALIGNED, - AVS_PLANAR_B_ALIGNED=AVS_PLANAR_B|AVS_PLANAR_ALIGNED}; - - // Colorspace properties. -enum { - AVS_CS_YUVA = 1 << 27, - AVS_CS_BGR = 1 << 28, - AVS_CS_YUV = 1 << 29, - AVS_CS_INTERLEAVED = 1 << 30, - AVS_CS_PLANAR = 1 << 31, - - AVS_CS_SHIFT_SUB_WIDTH = 0, - AVS_CS_SHIFT_SUB_HEIGHT = 8, - AVS_CS_SHIFT_SAMPLE_BITS = 16, - - AVS_CS_SUB_WIDTH_MASK = 7 << AVS_CS_SHIFT_SUB_WIDTH, - AVS_CS_SUB_WIDTH_1 = 3 << AVS_CS_SHIFT_SUB_WIDTH, // YV24 - AVS_CS_SUB_WIDTH_2 = 0 << AVS_CS_SHIFT_SUB_WIDTH, // YV12, I420, YV16 - AVS_CS_SUB_WIDTH_4 = 1 << AVS_CS_SHIFT_SUB_WIDTH, // YUV9, YV411 - - AVS_CS_VPLANEFIRST = 1 << 3, // YV12, YV16, YV24, YV411, YUV9 - AVS_CS_UPLANEFIRST = 1 << 4, // I420 - - AVS_CS_SUB_HEIGHT_MASK = 7 << AVS_CS_SHIFT_SUB_HEIGHT, - AVS_CS_SUB_HEIGHT_1 = 3 << AVS_CS_SHIFT_SUB_HEIGHT, // YV16, YV24, YV411 - AVS_CS_SUB_HEIGHT_2 = 0 << AVS_CS_SHIFT_SUB_HEIGHT, // YV12, I420 - AVS_CS_SUB_HEIGHT_4 = 1 << AVS_CS_SHIFT_SUB_HEIGHT, // YUV9 - - AVS_CS_SAMPLE_BITS_MASK = 7 << AVS_CS_SHIFT_SAMPLE_BITS, - AVS_CS_SAMPLE_BITS_8 = 0 << AVS_CS_SHIFT_SAMPLE_BITS, - AVS_CS_SAMPLE_BITS_10 = 5 << AVS_CS_SHIFT_SAMPLE_BITS, - AVS_CS_SAMPLE_BITS_12 = 6 << AVS_CS_SHIFT_SAMPLE_BITS, - AVS_CS_SAMPLE_BITS_14 = 7 << AVS_CS_SHIFT_SAMPLE_BITS, - AVS_CS_SAMPLE_BITS_16 = 1 << AVS_CS_SHIFT_SAMPLE_BITS, - AVS_CS_SAMPLE_BITS_32 = 2 << AVS_CS_SHIFT_SAMPLE_BITS, - - AVS_CS_PLANAR_MASK = AVS_CS_PLANAR | AVS_CS_INTERLEAVED | AVS_CS_YUV | AVS_CS_BGR | AVS_CS_YUVA | AVS_CS_SAMPLE_BITS_MASK | AVS_CS_SUB_HEIGHT_MASK | AVS_CS_SUB_WIDTH_MASK, - AVS_CS_PLANAR_FILTER = ~(AVS_CS_VPLANEFIRST | AVS_CS_UPLANEFIRST), - - AVS_CS_RGB_TYPE = 1 << 0, - AVS_CS_RGBA_TYPE = 1 << 1, - - AVS_CS_GENERIC_YUV420 = AVS_CS_PLANAR | AVS_CS_YUV | AVS_CS_VPLANEFIRST | AVS_CS_SUB_HEIGHT_2 | AVS_CS_SUB_WIDTH_2, // 4:2:0 planar - AVS_CS_GENERIC_YUV422 = AVS_CS_PLANAR | AVS_CS_YUV | AVS_CS_VPLANEFIRST | AVS_CS_SUB_HEIGHT_1 | AVS_CS_SUB_WIDTH_2, // 4:2:2 planar - AVS_CS_GENERIC_YUV444 = AVS_CS_PLANAR | AVS_CS_YUV | AVS_CS_VPLANEFIRST | AVS_CS_SUB_HEIGHT_1 | AVS_CS_SUB_WIDTH_1, // 4:4:4 planar - AVS_CS_GENERIC_Y = AVS_CS_PLANAR | AVS_CS_INTERLEAVED | AVS_CS_YUV, // Y only (4:0:0) - AVS_CS_GENERIC_RGBP = AVS_CS_PLANAR | AVS_CS_BGR | AVS_CS_RGB_TYPE, // planar RGB - AVS_CS_GENERIC_RGBAP = AVS_CS_PLANAR | AVS_CS_BGR | AVS_CS_RGBA_TYPE, // planar RGBA - AVS_CS_GENERIC_YUVA420 = AVS_CS_PLANAR | AVS_CS_YUVA | AVS_CS_VPLANEFIRST | AVS_CS_SUB_HEIGHT_2 | AVS_CS_SUB_WIDTH_2, // 4:2:0:A planar - AVS_CS_GENERIC_YUVA422 = AVS_CS_PLANAR | AVS_CS_YUVA | AVS_CS_VPLANEFIRST | AVS_CS_SUB_HEIGHT_1 | AVS_CS_SUB_WIDTH_2, // 4:2:2:A planar - AVS_CS_GENERIC_YUVA444 = AVS_CS_PLANAR | AVS_CS_YUVA | AVS_CS_VPLANEFIRST | AVS_CS_SUB_HEIGHT_1 | AVS_CS_SUB_WIDTH_1 }; // 4:4:4:A planar - - - // Specific color formats -enum { - AVS_CS_UNKNOWN = 0, - AVS_CS_BGR24 = AVS_CS_RGB_TYPE | AVS_CS_BGR | AVS_CS_INTERLEAVED, - AVS_CS_BGR32 = AVS_CS_RGBA_TYPE | AVS_CS_BGR | AVS_CS_INTERLEAVED, - AVS_CS_YUY2 = 1<<2 | AVS_CS_YUV | AVS_CS_INTERLEAVED, - // AVS_CS_YV12 = 1<<3 Reserved - // AVS_CS_I420 = 1<<4 Reserved - AVS_CS_RAW32 = 1<<5 | AVS_CS_INTERLEAVED, - - AVS_CS_YV24 = AVS_CS_GENERIC_YUV444 | AVS_CS_SAMPLE_BITS_8, // YUV 4:4:4 planar - AVS_CS_YV16 = AVS_CS_GENERIC_YUV422 | AVS_CS_SAMPLE_BITS_8, // YUV 4:2:2 planar - AVS_CS_YV12 = AVS_CS_GENERIC_YUV420 | AVS_CS_SAMPLE_BITS_8, // YUV 4:2:0 planar - AVS_CS_I420 = AVS_CS_PLANAR | AVS_CS_YUV | AVS_CS_SAMPLE_BITS_8 | AVS_CS_UPLANEFIRST | AVS_CS_SUB_HEIGHT_2 | AVS_CS_SUB_WIDTH_2, // YUV 4:2:0 planar - AVS_CS_IYUV = AVS_CS_I420, - AVS_CS_YV411 = AVS_CS_PLANAR | AVS_CS_YUV | AVS_CS_SAMPLE_BITS_8 | AVS_CS_VPLANEFIRST | AVS_CS_SUB_HEIGHT_1 | AVS_CS_SUB_WIDTH_4, // YUV 4:1:1 planar - AVS_CS_YUV9 = AVS_CS_PLANAR | AVS_CS_YUV | AVS_CS_SAMPLE_BITS_8 | AVS_CS_VPLANEFIRST | AVS_CS_SUB_HEIGHT_4 | AVS_CS_SUB_WIDTH_4, // YUV 4:1:0 planar - AVS_CS_Y8 = AVS_CS_GENERIC_Y | AVS_CS_SAMPLE_BITS_8, // Y 4:0:0 planar - - //------------------------- - // AVS16: new planar constants go live! Experimental PF 160613 - // 10-12-14-16 bit + planar RGB + BGR48/64 160725 - AVS_CS_YUV444P10 = AVS_CS_GENERIC_YUV444 | AVS_CS_SAMPLE_BITS_10, // YUV 4:4:4 10bit samples - AVS_CS_YUV422P10 = AVS_CS_GENERIC_YUV422 | AVS_CS_SAMPLE_BITS_10, // YUV 4:2:2 10bit samples - AVS_CS_YUV420P10 = AVS_CS_GENERIC_YUV420 | AVS_CS_SAMPLE_BITS_10, // YUV 4:2:0 10bit samples - AVS_CS_Y10 = AVS_CS_GENERIC_Y | AVS_CS_SAMPLE_BITS_10, // Y 4:0:0 10bit samples - - AVS_CS_YUV444P12 = AVS_CS_GENERIC_YUV444 | AVS_CS_SAMPLE_BITS_12, // YUV 4:4:4 12bit samples - AVS_CS_YUV422P12 = AVS_CS_GENERIC_YUV422 | AVS_CS_SAMPLE_BITS_12, // YUV 4:2:2 12bit samples - AVS_CS_YUV420P12 = AVS_CS_GENERIC_YUV420 | AVS_CS_SAMPLE_BITS_12, // YUV 4:2:0 12bit samples - AVS_CS_Y12 = AVS_CS_GENERIC_Y | AVS_CS_SAMPLE_BITS_12, // Y 4:0:0 12bit samples - - AVS_CS_YUV444P14 = AVS_CS_GENERIC_YUV444 | AVS_CS_SAMPLE_BITS_14, // YUV 4:4:4 14bit samples - AVS_CS_YUV422P14 = AVS_CS_GENERIC_YUV422 | AVS_CS_SAMPLE_BITS_14, // YUV 4:2:2 14bit samples - AVS_CS_YUV420P14 = AVS_CS_GENERIC_YUV420 | AVS_CS_SAMPLE_BITS_14, // YUV 4:2:0 14bit samples - AVS_CS_Y14 = AVS_CS_GENERIC_Y | AVS_CS_SAMPLE_BITS_14, // Y 4:0:0 14bit samples - - AVS_CS_YUV444P16 = AVS_CS_GENERIC_YUV444 | AVS_CS_SAMPLE_BITS_16, // YUV 4:4:4 16bit samples - AVS_CS_YUV422P16 = AVS_CS_GENERIC_YUV422 | AVS_CS_SAMPLE_BITS_16, // YUV 4:2:2 16bit samples - AVS_CS_YUV420P16 = AVS_CS_GENERIC_YUV420 | AVS_CS_SAMPLE_BITS_16, // YUV 4:2:0 16bit samples - AVS_CS_Y16 = AVS_CS_GENERIC_Y | AVS_CS_SAMPLE_BITS_16, // Y 4:0:0 16bit samples - - // 32 bit samples (float) - AVS_CS_YUV444PS = AVS_CS_GENERIC_YUV444 | AVS_CS_SAMPLE_BITS_32, // YUV 4:4:4 32bit samples - AVS_CS_YUV422PS = AVS_CS_GENERIC_YUV422 | AVS_CS_SAMPLE_BITS_32, // YUV 4:2:2 32bit samples - AVS_CS_YUV420PS = AVS_CS_GENERIC_YUV420 | AVS_CS_SAMPLE_BITS_32, // YUV 4:2:0 32bit samples - AVS_CS_Y32 = AVS_CS_GENERIC_Y | AVS_CS_SAMPLE_BITS_32, // Y 4:0:0 32bit samples - - // RGB packed - AVS_CS_BGR48 = AVS_CS_RGB_TYPE | AVS_CS_BGR | AVS_CS_INTERLEAVED | AVS_CS_SAMPLE_BITS_16, // BGR 3x16 bit - AVS_CS_BGR64 = AVS_CS_RGBA_TYPE | AVS_CS_BGR | AVS_CS_INTERLEAVED | AVS_CS_SAMPLE_BITS_16, // BGR 4x16 bit - // no packed 32 bit (float) support for these legacy types - - // RGB planar - AVS_CS_RGBP = AVS_CS_GENERIC_RGBP | AVS_CS_SAMPLE_BITS_8, // Planar RGB 8 bit samples - AVS_CS_RGBP10 = AVS_CS_GENERIC_RGBP | AVS_CS_SAMPLE_BITS_10, // Planar RGB 10bit samples - AVS_CS_RGBP12 = AVS_CS_GENERIC_RGBP | AVS_CS_SAMPLE_BITS_12, // Planar RGB 12bit samples - AVS_CS_RGBP14 = AVS_CS_GENERIC_RGBP | AVS_CS_SAMPLE_BITS_14, // Planar RGB 14bit samples - AVS_CS_RGBP16 = AVS_CS_GENERIC_RGBP | AVS_CS_SAMPLE_BITS_16, // Planar RGB 16bit samples - AVS_CS_RGBPS = AVS_CS_GENERIC_RGBP | AVS_CS_SAMPLE_BITS_32, // Planar RGB 32bit samples - - // RGBA planar - AVS_CS_RGBAP = AVS_CS_GENERIC_RGBAP | AVS_CS_SAMPLE_BITS_8, // Planar RGBA 8 bit samples - AVS_CS_RGBAP10 = AVS_CS_GENERIC_RGBAP | AVS_CS_SAMPLE_BITS_10, // Planar RGBA 10bit samples - AVS_CS_RGBAP12 = AVS_CS_GENERIC_RGBAP | AVS_CS_SAMPLE_BITS_12, // Planar RGBA 12bit samples - AVS_CS_RGBAP14 = AVS_CS_GENERIC_RGBAP | AVS_CS_SAMPLE_BITS_14, // Planar RGBA 14bit samples - AVS_CS_RGBAP16 = AVS_CS_GENERIC_RGBAP | AVS_CS_SAMPLE_BITS_16, // Planar RGBA 16bit samples - AVS_CS_RGBAPS = AVS_CS_GENERIC_RGBAP | AVS_CS_SAMPLE_BITS_32, // Planar RGBA 32bit samples - - // Planar YUVA - AVS_CS_YUVA444 = AVS_CS_GENERIC_YUVA444 | AVS_CS_SAMPLE_BITS_8, // YUVA 4:4:4 8bit samples - AVS_CS_YUVA422 = AVS_CS_GENERIC_YUVA422 | AVS_CS_SAMPLE_BITS_8, // YUVA 4:2:2 8bit samples - AVS_CS_YUVA420 = AVS_CS_GENERIC_YUVA420 | AVS_CS_SAMPLE_BITS_8, // YUVA 4:2:0 8bit samples - - AVS_CS_YUVA444P10 = AVS_CS_GENERIC_YUVA444 | AVS_CS_SAMPLE_BITS_10, // YUVA 4:4:4 10bit samples - AVS_CS_YUVA422P10 = AVS_CS_GENERIC_YUVA422 | AVS_CS_SAMPLE_BITS_10, // YUVA 4:2:2 10bit samples - AVS_CS_YUVA420P10 = AVS_CS_GENERIC_YUVA420 | AVS_CS_SAMPLE_BITS_10, // YUVA 4:2:0 10bit samples - - AVS_CS_YUVA444P12 = AVS_CS_GENERIC_YUVA444 | AVS_CS_SAMPLE_BITS_12, // YUVA 4:4:4 12bit samples - AVS_CS_YUVA422P12 = AVS_CS_GENERIC_YUVA422 | AVS_CS_SAMPLE_BITS_12, // YUVA 4:2:2 12bit samples - AVS_CS_YUVA420P12 = AVS_CS_GENERIC_YUVA420 | AVS_CS_SAMPLE_BITS_12, // YUVA 4:2:0 12bit samples - - AVS_CS_YUVA444P14 = AVS_CS_GENERIC_YUVA444 | AVS_CS_SAMPLE_BITS_14, // YUVA 4:4:4 14bit samples - AVS_CS_YUVA422P14 = AVS_CS_GENERIC_YUVA422 | AVS_CS_SAMPLE_BITS_14, // YUVA 4:2:2 14bit samples - AVS_CS_YUVA420P14 = AVS_CS_GENERIC_YUVA420 | AVS_CS_SAMPLE_BITS_14, // YUVA 4:2:0 14bit samples - - AVS_CS_YUVA444P16 = AVS_CS_GENERIC_YUVA444 | AVS_CS_SAMPLE_BITS_16, // YUVA 4:4:4 16bit samples - AVS_CS_YUVA422P16 = AVS_CS_GENERIC_YUVA422 | AVS_CS_SAMPLE_BITS_16, // YUVA 4:2:2 16bit samples - AVS_CS_YUVA420P16 = AVS_CS_GENERIC_YUVA420 | AVS_CS_SAMPLE_BITS_16, // YUVA 4:2:0 16bit samples - - AVS_CS_YUVA444PS = AVS_CS_GENERIC_YUVA444 | AVS_CS_SAMPLE_BITS_32, // YUVA 4:4:4 32bit samples - AVS_CS_YUVA422PS = AVS_CS_GENERIC_YUVA422 | AVS_CS_SAMPLE_BITS_32, // YUVA 4:2:2 32bit samples - AVS_CS_YUVA420PS = AVS_CS_GENERIC_YUVA420 | AVS_CS_SAMPLE_BITS_32, // YUVA 4:2:0 32bit samples - -}; - -enum { - AVS_IT_BFF = 1<<0, - AVS_IT_TFF = 1<<1, - AVS_IT_FIELDBASED = 1<<2}; - -enum { - AVS_FILTER_TYPE=1, - AVS_FILTER_INPUT_COLORSPACE=2, - AVS_FILTER_OUTPUT_TYPE=9, - AVS_FILTER_NAME=4, - AVS_FILTER_AUTHOR=5, - AVS_FILTER_VERSION=6, - AVS_FILTER_ARGS=7, - AVS_FILTER_ARGS_INFO=8, - AVS_FILTER_ARGS_DESCRIPTION=10, - AVS_FILTER_DESCRIPTION=11}; - -enum { //SUBTYPES - AVS_FILTER_TYPE_AUDIO=1, - AVS_FILTER_TYPE_VIDEO=2, - AVS_FILTER_OUTPUT_TYPE_SAME=3, - AVS_FILTER_OUTPUT_TYPE_DIFFERENT=4}; - -enum { - // New 2.6 explicitly defined cache hints. - AVS_CACHE_NOTHING=10, // Do not cache video. - AVS_CACHE_WINDOW=11, // Hard protect up to X frames within a range of X from the current frame N. - AVS_CACHE_GENERIC=12, // LRU cache up to X frames. - AVS_CACHE_FORCE_GENERIC=13, // LRU cache up to X frames, override any previous CACHE_WINDOW. - - AVS_CACHE_GET_POLICY=30, // Get the current policy. - AVS_CACHE_GET_WINDOW=31, // Get the current window h_span. - AVS_CACHE_GET_RANGE=32, // Get the current generic frame range. - - AVS_CACHE_AUDIO=50, // Explicitly do cache audio, X byte cache. - AVS_CACHE_AUDIO_NOTHING=51, // Explicitly do not cache audio. - AVS_CACHE_AUDIO_NONE=52, // Audio cache off (auto mode), X byte initial cache. - AVS_CACHE_AUDIO_AUTO=53, // Audio cache on (auto mode), X byte initial cache. - - AVS_CACHE_GET_AUDIO_POLICY=70, // Get the current audio policy. - AVS_CACHE_GET_AUDIO_SIZE=71, // Get the current audio cache size. - - AVS_CACHE_PREFETCH_FRAME=100, // Queue request to prefetch frame N. - AVS_CACHE_PREFETCH_GO=101, // Action video prefetches. - - AVS_CACHE_PREFETCH_AUDIO_BEGIN=120, // Begin queue request transaction to prefetch audio (take critical section). - AVS_CACHE_PREFETCH_AUDIO_STARTLO=121, // Set low 32 bits of start. - AVS_CACHE_PREFETCH_AUDIO_STARTHI=122, // Set high 32 bits of start. - AVS_CACHE_PREFETCH_AUDIO_COUNT=123, // Set low 32 bits of length. - AVS_CACHE_PREFETCH_AUDIO_COMMIT=124, // Enqueue request transaction to prefetch audio (release critical section). - AVS_CACHE_PREFETCH_AUDIO_GO=125, // Action audio prefetches. - - AVS_CACHE_GETCHILD_CACHE_MODE=200, // Cache ask Child for desired video cache mode. - AVS_CACHE_GETCHILD_CACHE_SIZE=201, // Cache ask Child for desired video cache size. - AVS_CACHE_GETCHILD_AUDIO_MODE=202, // Cache ask Child for desired audio cache mode. - AVS_CACHE_GETCHILD_AUDIO_SIZE=203, // Cache ask Child for desired audio cache size. - - AVS_CACHE_GETCHILD_COST=220, // Cache ask Child for estimated processing cost. - AVS_CACHE_COST_ZERO=221, // Child response of zero cost (ptr arithmetic only). - AVS_CACHE_COST_UNIT=222, // Child response of unit cost (less than or equal 1 full frame blit). - AVS_CACHE_COST_LOW=223, // Child response of light cost. (Fast) - AVS_CACHE_COST_MED=224, // Child response of medium cost. (Real time) - AVS_CACHE_COST_HI=225, // Child response of heavy cost. (Slow) - - AVS_CACHE_GETCHILD_THREAD_MODE=240, // Cache ask Child for thread safety. - AVS_CACHE_THREAD_UNSAFE=241, // Only 1 thread allowed for all instances. 2.5 filters default! - AVS_CACHE_THREAD_CLASS=242, // Only 1 thread allowed for each instance. 2.6 filters default! - AVS_CACHE_THREAD_SAFE=243, // Allow all threads in any instance. - AVS_CACHE_THREAD_OWN=244, // Safe but limit to 1 thread, internally threaded. - - AVS_CACHE_GETCHILD_ACCESS_COST=260, // Cache ask Child for preferred access pattern. - AVS_CACHE_ACCESS_RAND=261, // Filter is access order agnostic. - AVS_CACHE_ACCESS_SEQ0=262, // Filter prefers sequential access (low cost) - AVS_CACHE_ACCESS_SEQ1=263, // Filter needs sequential access (high cost) - }; - -#ifdef BUILDING_AVSCORE -AVSValue create_c_video_filter(AVSValue args, void * user_data, IScriptEnvironment * e0); - -struct AVS_ScriptEnvironment { - IScriptEnvironment * env; - const char * error; - AVS_ScriptEnvironment(IScriptEnvironment * e = 0) - : env(e), error(0) {} -}; -#endif - -typedef struct AVS_Clip AVS_Clip; -typedef struct AVS_ScriptEnvironment AVS_ScriptEnvironment; - -///////////////////////////////////////////////////////////////////// -// -// AVS_VideoInfo -// - -// AVS_VideoInfo is laid out identically to VideoInfo -typedef struct AVS_VideoInfo { - int width, height; // width=0 means no video - unsigned fps_numerator, fps_denominator; - int num_frames; - - int pixel_type; - - int audio_samples_per_second; // 0 means no audio - int sample_type; - INT64 num_audio_samples; - int nchannels; - - // Image type properties - - int image_type; -} AVS_VideoInfo; - -// useful functions of the above -AVSC_INLINE int avs_has_video(const AVS_VideoInfo * p) - { return (p->width!=0); } - -AVSC_INLINE int avs_has_audio(const AVS_VideoInfo * p) - { return (p->audio_samples_per_second!=0); } - -AVSC_INLINE int avs_is_rgb(const AVS_VideoInfo * p) - { return !!(p->pixel_type&AVS_CS_BGR); } - -AVSC_INLINE int avs_is_rgb24(const AVS_VideoInfo * p) - { return ((p->pixel_type&AVS_CS_BGR24)==AVS_CS_BGR24) && ((p->pixel_type & AVS_CS_SAMPLE_BITS_MASK) == AVS_CS_SAMPLE_BITS_8); } - -AVSC_INLINE int avs_is_rgb32(const AVS_VideoInfo * p) - { return ((p->pixel_type&AVS_CS_BGR32)==AVS_CS_BGR32) && ((p->pixel_type & AVS_CS_SAMPLE_BITS_MASK) == AVS_CS_SAMPLE_BITS_8); } - -AVSC_INLINE int avs_is_yuv(const AVS_VideoInfo * p) - { return !!(p->pixel_type&AVS_CS_YUV ); } - -AVSC_INLINE int avs_is_yuy2(const AVS_VideoInfo * p) - { return (p->pixel_type & AVS_CS_YUY2) == AVS_CS_YUY2; } - -AVSC_API(int, avs_is_yv24)(const AVS_VideoInfo * p); // avs+: for generic 444 check, use avs_is_yuv444 - -AVSC_API(int, avs_is_yv16)(const AVS_VideoInfo * p); // avs+: for generic 422 check, use avs_is_yuv422 - -AVSC_API(int, avs_is_yv12)(const AVS_VideoInfo * p) ; // avs+: for generic 420 check, use avs_is_yuv420 - -AVSC_API(int, avs_is_yv411)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_is_y8)(const AVS_VideoInfo * p); // avs+: for generic grayscale, use avs_is_y - -AVSC_API(int, avs_get_plane_width_subsampling)(const AVS_VideoInfo * p, int plane); - -AVSC_API(int, avs_get_plane_height_subsampling)(const AVS_VideoInfo * p, int plane); - -AVSC_API(int, avs_bits_per_pixel)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_bytes_from_pixels)(const AVS_VideoInfo * p, int pixels); - -AVSC_API(int, avs_row_size)(const AVS_VideoInfo * p, int plane); - -AVSC_API(int, avs_bmp_size)(const AVS_VideoInfo * vi); - -AVSC_API(int, avs_is_color_space)(const AVS_VideoInfo * p, int c_space); - -// no API for these, inline helper functions -AVSC_INLINE int avs_is_property(const AVS_VideoInfo * p, int property) -{ - return ((p->image_type & property) == property); -} - -AVSC_INLINE int avs_is_planar(const AVS_VideoInfo * p) -{ - return !!(p->pixel_type & AVS_CS_PLANAR); -} - -AVSC_INLINE int avs_is_field_based(const AVS_VideoInfo * p) -{ - return !!(p->image_type & AVS_IT_FIELDBASED); -} - -AVSC_INLINE int avs_is_parity_known(const AVS_VideoInfo * p) -{ - return ((p->image_type & AVS_IT_FIELDBASED) && (p->image_type & (AVS_IT_BFF | AVS_IT_TFF))); -} - -AVSC_INLINE int avs_is_bff(const AVS_VideoInfo * p) -{ - return !!(p->image_type & AVS_IT_BFF); -} - -AVSC_INLINE int avs_is_tff(const AVS_VideoInfo * p) -{ - return !!(p->image_type & AVS_IT_TFF); -} - -AVSC_INLINE int avs_samples_per_second(const AVS_VideoInfo * p) - { return p->audio_samples_per_second; } - -AVSC_INLINE int avs_bytes_per_channel_sample(const AVS_VideoInfo * p) -{ - switch (p->sample_type) { - case AVS_SAMPLE_INT8: return sizeof(signed char); - case AVS_SAMPLE_INT16: return sizeof(signed short); - case AVS_SAMPLE_INT24: return 3; - case AVS_SAMPLE_INT32: return sizeof(signed int); - case AVS_SAMPLE_FLOAT: return sizeof(float); - default: return 0; - } -} - -AVSC_INLINE int avs_bytes_per_audio_sample(const AVS_VideoInfo * p) - { return p->nchannels*avs_bytes_per_channel_sample(p);} - -AVSC_INLINE INT64 avs_audio_samples_from_frames(const AVS_VideoInfo * p, INT64 frames) - { return ((INT64)(frames) * p->audio_samples_per_second * p->fps_denominator / p->fps_numerator); } - -AVSC_INLINE int avs_frames_from_audio_samples(const AVS_VideoInfo * p, INT64 samples) - { return (int)(samples * (INT64)p->fps_numerator / (INT64)p->fps_denominator / (INT64)p->audio_samples_per_second); } - -AVSC_INLINE INT64 avs_audio_samples_from_bytes(const AVS_VideoInfo * p, INT64 bytes) - { return bytes / avs_bytes_per_audio_sample(p); } - -AVSC_INLINE INT64 avs_bytes_from_audio_samples(const AVS_VideoInfo * p, INT64 samples) - { return samples * avs_bytes_per_audio_sample(p); } - -AVSC_INLINE int avs_audio_channels(const AVS_VideoInfo * p) - { return p->nchannels; } - -AVSC_INLINE int avs_sample_type(const AVS_VideoInfo * p) - { return p->sample_type;} - -// useful mutator -AVSC_INLINE void avs_set_property(AVS_VideoInfo * p, int property) - { p->image_type|=property; } - -AVSC_INLINE void avs_clear_property(AVS_VideoInfo * p, int property) - { p->image_type&=~property; } - -AVSC_INLINE void avs_set_field_based(AVS_VideoInfo * p, int isfieldbased) - { if (isfieldbased) p->image_type|=AVS_IT_FIELDBASED; else p->image_type&=~AVS_IT_FIELDBASED; } - -AVSC_INLINE void avs_set_fps(AVS_VideoInfo * p, unsigned numerator, unsigned denominator) -{ - unsigned x=numerator, y=denominator; - while (y) { // find gcd - unsigned t = x%y; x = y; y = t; - } - p->fps_numerator = numerator/x; - p->fps_denominator = denominator/x; -} - -#ifndef AVSC_NO_DECLSPEC -// this inline function is calling an API function -AVSC_INLINE int avs_is_same_colorspace(const AVS_VideoInfo * x, const AVS_VideoInfo * y) -{ - return (x->pixel_type == y->pixel_type) - || (avs_is_yv12(x) && avs_is_yv12(y)); -} -#endif - -// Avisynth+ extensions -AVSC_API(int, avs_is_rgb48)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_is_rgb64)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_is_yuv444p16)(const AVS_VideoInfo * p); // obsolete, use avs_is_yuv444 - -AVSC_API(int, avs_is_yuv422p16)(const AVS_VideoInfo * p); // obsolete, use avs_is_yuv422 - -AVSC_API(int, avs_is_yuv420p16)(const AVS_VideoInfo * p); // obsolete, use avs_is_yuv420 - -AVSC_API(int, avs_is_y16)(const AVS_VideoInfo * p); // obsolete, use avs_is_y - -AVSC_API(int, avs_is_yuv444ps)(const AVS_VideoInfo * p); // obsolete, use avs_is_yuv444 - -AVSC_API(int, avs_is_yuv422ps)(const AVS_VideoInfo * p); // obsolete, use avs_is_yuv422 - -AVSC_API(int, avs_is_yuv420ps)(const AVS_VideoInfo * p); // obsolete, use avs_is_yuv420 - -AVSC_API(int, avs_is_y32)(const AVS_VideoInfo * p); // obsolete, use avs_is_y - -AVSC_API(int, avs_is_444)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_is_422)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_is_420)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_is_y)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_is_yuva)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_is_planar_rgb)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_is_planar_rgba)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_num_components)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_component_size)(const AVS_VideoInfo * p); - -AVSC_API(int, avs_bits_per_component)(const AVS_VideoInfo * p); -// end of Avisynth+ specific - -///////////////////////////////////////////////////////////////////// -// -// AVS_VideoFrame -// - -// VideoFrameBuffer holds information about a memory block which is used -// for video data. For efficiency, instances of this class are not deleted -// when the refcount reaches zero; instead they're stored in a linked list -// to be reused. The instances are deleted when the corresponding AVS -// file is closed. - -// AVS_VideoFrameBuffer is laid out identically to VideoFrameBuffer -// DO NOT USE THIS STRUCTURE DIRECTLY -typedef struct AVS_VideoFrameBuffer { - BYTE * data; -#ifdef SIZETMOD - size_t data_size; -#else - int data_size; -#endif - // sequence_number is incremented every time the buffer is changed, so - // that stale views can tell they're no longer valid. - volatile long sequence_number; - - volatile long refcount; -} AVS_VideoFrameBuffer; - -// VideoFrame holds a "window" into a VideoFrameBuffer. - -// AVS_VideoFrame is laid out identically to IVideoFrame -// DO NOT USE THIS STRUCTURE DIRECTLY -typedef struct AVS_VideoFrame { - volatile long refcount; - AVS_VideoFrameBuffer * vfb; -#ifdef SIZETMOD - size_t offset; -#else - int offset; -#endif - int pitch, row_size, height; -#ifdef SIZETMOD - size_t offsetU, offsetV; -#else - int offsetU, offsetV; -#endif - int pitchUV; // U&V offsets are from top of picture. - int row_sizeUV, heightUV; // for Planar RGB offsetU, offsetV is for the 2nd and 3rd Plane. - // for Planar RGB pitchUV and row_sizeUV = 0, because when no VideoInfo (MakeWriteable) - // the decision on existence of UV is checked by zero pitch - // AVS+ extension, avisynth.h: class does not break plugins if appended here -#ifdef SIZETMOD - size_t offsetA; -#else - int offsetA; -#endif - int pitchA, row_sizeA; // 4th alpha plane support, pitch and row_size is 0 is none -} AVS_VideoFrame; - -// Access functions for AVS_VideoFrame -AVSC_API(int, avs_get_pitch_p)(const AVS_VideoFrame * p, int plane); - -AVSC_API(int, avs_get_row_size_p)(const AVS_VideoFrame * p, int plane); - -AVSC_API(int, avs_get_height_p)(const AVS_VideoFrame * p, int plane); - -AVSC_API(const BYTE *, avs_get_read_ptr_p)(const AVS_VideoFrame * p, int plane); - -AVSC_API(int, avs_is_writable)(const AVS_VideoFrame * p); - -AVSC_API(BYTE *, avs_get_write_ptr_p)(const AVS_VideoFrame * p, int plane); - -AVSC_API(void, avs_release_video_frame)(AVS_VideoFrame *); -// makes a shallow copy of a video frame -AVSC_API(AVS_VideoFrame *, avs_copy_video_frame)(AVS_VideoFrame *); - -// no API for these, inline helper functions -#ifndef AVSC_NO_DECLSPEC -// this inline function is calling an API function -AVSC_INLINE int avs_get_pitch(const AVS_VideoFrame * p) { - return avs_get_pitch_p(p, 0); -} -#endif - -#ifndef AVSC_NO_DECLSPEC -// this inline function is calling an API function -AVSC_INLINE int avs_get_row_size(const AVS_VideoFrame * p) { - return avs_get_row_size_p(p, 0); } -#endif - - -#ifndef AVSC_NO_DECLSPEC -// this inline function is calling an API function -AVSC_INLINE int avs_get_height(const AVS_VideoFrame * p) { - return avs_get_height_p(p, 0); -} -#endif - -#ifndef AVSC_NO_DECLSPEC -// this inline function is calling an API function -AVSC_INLINE const BYTE* avs_get_read_ptr(const AVS_VideoFrame * p) { - return avs_get_read_ptr_p(p, 0);} -#endif - -#ifndef AVSC_NO_DECLSPEC -// this inline function is calling an API function -AVSC_INLINE BYTE* avs_get_write_ptr(const AVS_VideoFrame * p) { - return avs_get_write_ptr_p(p, 0);} -#endif - -#ifndef AVSC_NO_DECLSPEC -// this inline function is calling an API function -AVSC_INLINE void avs_release_frame(AVS_VideoFrame * f) - {avs_release_video_frame(f);} -#endif - -#ifndef AVSC_NO_DECLSPEC -// this inline function is calling an API function -AVSC_INLINE AVS_VideoFrame * avs_copy_frame(AVS_VideoFrame * f) - {return avs_copy_video_frame(f);} -#endif - -///////////////////////////////////////////////////////////////////// -// -// AVS_Value -// - -// Treat AVS_Value as a fat pointer. That is use avs_copy_value -// and avs_release_value appropriately as you would if AVS_Value was -// a pointer. - -// To maintain source code compatibility with future versions of the -// avisynth_c API don't use the AVS_Value directly. Use the helper -// functions below. - -// AVS_Value is laid out identically to AVSValue -typedef struct AVS_Value AVS_Value; -struct AVS_Value { - short type; // 'a'rray, 'c'lip, 'b'ool, 'i'nt, 'f'loat, 's'tring, 'v'oid, or 'l'ong - // for some function e'rror - short array_size; - union { - void * clip; // do not use directly, use avs_take_clip - char boolean; - int integer; - float floating_pt; - const char * string; - const AVS_Value * array; - } d; -}; - -// AVS_Value should be initialized with avs_void. -// Should also set to avs_void after the value is released -// with avs_copy_value. Consider it the equivalent of setting -// a pointer to NULL -static const AVS_Value avs_void = {'v'}; - -AVSC_API(void, avs_copy_value)(AVS_Value * dest, AVS_Value src); -AVSC_API(void, avs_release_value)(AVS_Value); -AVSC_API(AVS_Clip *, avs_take_clip)(AVS_Value, AVS_ScriptEnvironment *); -AVSC_API(void, avs_set_to_clip)(AVS_Value *, AVS_Clip *); - - -// no API for these, inline helper functions -AVSC_INLINE int avs_defined(AVS_Value v) { return v.type != 'v'; } -AVSC_INLINE int avs_is_clip(AVS_Value v) { return v.type == 'c'; } -AVSC_INLINE int avs_is_bool(AVS_Value v) { return v.type == 'b'; } -AVSC_INLINE int avs_is_int(AVS_Value v) { return v.type == 'i'; } -AVSC_INLINE int avs_is_float(AVS_Value v) { return v.type == 'f' || v.type == 'i'; } -AVSC_INLINE int avs_is_string(AVS_Value v) { return v.type == 's'; } -AVSC_INLINE int avs_is_array(AVS_Value v) { return v.type == 'a'; } -AVSC_INLINE int avs_is_error(AVS_Value v) { return v.type == 'e'; } - -AVSC_INLINE int avs_as_bool(AVS_Value v) - { return v.d.boolean; } -AVSC_INLINE int avs_as_int(AVS_Value v) - { return v.d.integer; } -AVSC_INLINE const char * avs_as_string(AVS_Value v) - { return avs_is_error(v) || avs_is_string(v) ? v.d.string : 0; } -AVSC_INLINE double avs_as_float(AVS_Value v) - { return avs_is_int(v) ? v.d.integer : v.d.floating_pt; } -AVSC_INLINE const char * avs_as_error(AVS_Value v) - { return avs_is_error(v) ? v.d.string : 0; } -AVSC_INLINE const AVS_Value * avs_as_array(AVS_Value v) - { return v.d.array; } -AVSC_INLINE int avs_array_size(AVS_Value v) - { return avs_is_array(v) ? v.array_size : 1; } -AVSC_INLINE AVS_Value avs_array_elt(AVS_Value v, int index) - { return avs_is_array(v) ? v.d.array[index] : v; } - -// only use these functions on an AVS_Value that does not already have -// an active value. Remember, treat AVS_Value as a fat pointer. -AVSC_INLINE AVS_Value avs_new_value_bool(int v0) - { AVS_Value v; v.type = 'b'; v.d.boolean = v0 == 0 ? 0 : 1; return v; } -AVSC_INLINE AVS_Value avs_new_value_int(int v0) - { AVS_Value v; v.type = 'i'; v.d.integer = v0; return v; } -AVSC_INLINE AVS_Value avs_new_value_string(const char * v0) - { AVS_Value v; v.type = 's'; v.d.string = v0; return v; } -AVSC_INLINE AVS_Value avs_new_value_float(float v0) - { AVS_Value v; v.type = 'f'; v.d.floating_pt = v0; return v;} -AVSC_INLINE AVS_Value avs_new_value_error(const char * v0) - { AVS_Value v; v.type = 'e'; v.d.string = v0; return v; } -#ifndef AVSC_NO_DECLSPEC -// this inline function is calling an API function -AVSC_INLINE AVS_Value avs_new_value_clip(AVS_Clip * v0) - { AVS_Value v; avs_set_to_clip(&v, v0); return v; } -#endif -AVSC_INLINE AVS_Value avs_new_value_array(AVS_Value * v0, int size) - { AVS_Value v; v.type = 'a'; v.d.array = v0; v.array_size = (short)size; return v; } -// end of inline helper functions - -///////////////////////////////////////////////////////////////////// -// -// AVS_Clip -// - -AVSC_API(void, avs_release_clip)(AVS_Clip *); -AVSC_API(AVS_Clip *, avs_copy_clip)(AVS_Clip *); - -AVSC_API(const char *, avs_clip_get_error)(AVS_Clip *); // return 0 if no error - -AVSC_API(const AVS_VideoInfo *, avs_get_video_info)(AVS_Clip *); - -AVSC_API(int, avs_get_version)(AVS_Clip *); - -AVSC_API(AVS_VideoFrame *, avs_get_frame)(AVS_Clip *, int n); -// The returned video frame must be released with avs_release_video_frame - -AVSC_API(int, avs_get_parity)(AVS_Clip *, int n); -// return field parity if field_based, else parity of first field in frame - -AVSC_API(int, avs_get_audio)(AVS_Clip *, void * buf, - INT64 start, INT64 count); -// start and count are in samples - -AVSC_API(int, avs_set_cache_hints)(AVS_Clip *, - int cachehints, int frame_range); - -// This is the callback type used by avs_add_function -typedef AVS_Value (AVSC_CC * AVS_ApplyFunc) - (AVS_ScriptEnvironment *, AVS_Value args, void * user_data); - -typedef struct AVS_FilterInfo AVS_FilterInfo; -struct AVS_FilterInfo -{ - // these members should not be modified outside of the AVS_ApplyFunc callback - AVS_Clip * child; - AVS_VideoInfo vi; - AVS_ScriptEnvironment * env; - AVS_VideoFrame * (AVSC_CC * get_frame)(AVS_FilterInfo *, int n); - int (AVSC_CC * get_parity)(AVS_FilterInfo *, int n); - int (AVSC_CC * get_audio)(AVS_FilterInfo *, void * buf, - INT64 start, INT64 count); - int (AVSC_CC * set_cache_hints)(AVS_FilterInfo *, int cachehints, - int frame_range); - void (AVSC_CC * free_filter)(AVS_FilterInfo *); - - // Should be set when ever there is an error to report. - // It is cleared before any of the above methods are called - const char * error; - // this is to store whatever and may be modified at will - void * user_data; -}; - -// Create a new filter -// fi is set to point to the AVS_FilterInfo so that you can -// modify it once it is initialized. -// store_child should generally be set to true. If it is not -// set than ALL methods (the function pointers) must be defined -// If it is set than you do not need to worry about freeing the child -// clip. -AVSC_API(AVS_Clip *, avs_new_c_filter)(AVS_ScriptEnvironment * e, - AVS_FilterInfo * * fi, - AVS_Value child, int store_child); - -///////////////////////////////////////////////////////////////////// -// -// AVS_ScriptEnvironment -// - -// For GetCPUFlags. These are backwards-compatible with those in VirtualDub. -enum { - /* slowest CPU to support extension */ - AVS_CPU_FORCE = 0x01, // N/A - AVS_CPU_FPU = 0x02, // 386/486DX - AVS_CPU_MMX = 0x04, // P55C, K6, PII - AVS_CPU_INTEGER_SSE = 0x08, // PIII, Athlon - AVS_CPU_SSE = 0x10, // PIII, Athlon XP/MP - AVS_CPU_SSE2 = 0x20, // PIV, Hammer - AVS_CPU_3DNOW = 0x40, // K6-2 - AVS_CPU_3DNOW_EXT = 0x80, // Athlon - AVS_CPU_X86_64 = 0xA0, // Hammer (note: equiv. to 3DNow + SSE2, - // which only Hammer will have anyway) - AVS_CPUF_SSE3 = 0x100, // PIV+, K8 Venice - AVS_CPUF_SSSE3 = 0x200, // Core 2 - AVS_CPUF_SSE4 = 0x400, // Penryn, Wolfdale, Yorkfield - AVS_CPUF_SSE4_1 = 0x400, - AVS_CPUF_AVX = 0x800, // Sandy Bridge, Bulldozer - AVS_CPUF_SSE4_2 = 0x1000, // Nehalem - // AVS+ - AVS_CPUF_AVX2 = 0x2000, // Haswell - AVS_CPUF_FMA3 = 0x4000, - AVS_CPUF_F16C = 0x8000, - AVS_CPUF_MOVBE = 0x10000, // Big Endian Move - AVS_CPUF_POPCNT = 0x20000, - AVS_CPUF_AES = 0x40000, - AVS_CPUF_FMA4 = 0x80000, - - AVS_CPUF_AVX512F = 0x100000, // AVX-512 Foundation. - AVS_CPUF_AVX512DQ = 0x200000, // AVX-512 DQ (Double/Quad granular) Instructions - AVS_CPUF_AVX512PF = 0x400000, // AVX-512 Prefetch - AVS_CPUF_AVX512ER = 0x800000, // AVX-512 Exponential and Reciprocal - AVS_CPUF_AVX512CD = 0x1000000, // AVX-512 Conflict Detection - AVS_CPUF_AVX512BW = 0x2000000, // AVX-512 BW (Byte/Word granular) Instructions - AVS_CPUF_AVX512VL = 0x4000000, // AVX-512 VL (128/256 Vector Length) Extensions - AVS_CPUF_AVX512IFMA = 0x8000000, // AVX-512 IFMA integer 52 bit - AVS_CPUF_AVX512VBMI = 0x10000000 // AVX-512 VBMI -}; - - -AVSC_API(const char *, avs_get_error)(AVS_ScriptEnvironment *); // return 0 if no error - -AVSC_API(int, avs_get_cpu_flags)(AVS_ScriptEnvironment *); -AVSC_API(int, avs_check_version)(AVS_ScriptEnvironment *, int version); - -AVSC_API(char *, avs_save_string)(AVS_ScriptEnvironment *, const char* s, int length); -AVSC_API(char *, avs_sprintf)(AVS_ScriptEnvironment *, const char * fmt, ...); - -AVSC_API(char *, avs_vsprintf)(AVS_ScriptEnvironment *, const char * fmt, void* val); - // note: val is really a va_list; I hope everyone typedefs va_list to a pointer - -AVSC_API(int, avs_add_function)(AVS_ScriptEnvironment *, - const char * name, const char * params, - AVS_ApplyFunc apply, void * user_data); - -AVSC_API(int, avs_function_exists)(AVS_ScriptEnvironment *, const char * name); - -AVSC_API(AVS_Value, avs_invoke)(AVS_ScriptEnvironment *, const char * name, - AVS_Value args, const char** arg_names); -// The returned value must be be released with avs_release_value - -AVSC_API(AVS_Value, avs_get_var)(AVS_ScriptEnvironment *, const char* name); -// The returned value must be be released with avs_release_value - -AVSC_API(int, avs_set_var)(AVS_ScriptEnvironment *, const char* name, AVS_Value val); - -AVSC_API(int, avs_set_global_var)(AVS_ScriptEnvironment *, const char* name, const AVS_Value val); - -//void avs_push_context(AVS_ScriptEnvironment *, int level=0); -//void avs_pop_context(AVS_ScriptEnvironment *); - -AVSC_API(AVS_VideoFrame *, avs_new_video_frame_a)(AVS_ScriptEnvironment *, - const AVS_VideoInfo * vi, int align); -// align should be at least 16 for classic Avisynth -// Avisynth+: any value, Avs+ ensures a minimum alignment if too small align is provided - -// no API for these, inline helper functions -#ifndef AVSC_NO_DECLSPEC -// this inline function is calling an API function -AVSC_INLINE AVS_VideoFrame * avs_new_video_frame(AVS_ScriptEnvironment * env, - const AVS_VideoInfo * vi) - {return avs_new_video_frame_a(env,vi,AVS_FRAME_ALIGN);} - -// an older compatibility alias -// this inline function is calling an API function -AVSC_INLINE AVS_VideoFrame * avs_new_frame(AVS_ScriptEnvironment * env, - const AVS_VideoInfo * vi) - {return avs_new_video_frame_a(env,vi,AVS_FRAME_ALIGN);} -#endif -// end of inline helper functions - -AVSC_API(int, avs_make_writable)(AVS_ScriptEnvironment *, AVS_VideoFrame * * pvf); - -AVSC_API(void, avs_bit_blt)(AVS_ScriptEnvironment *, BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height); - -typedef void (AVSC_CC *AVS_ShutdownFunc)(void* user_data, AVS_ScriptEnvironment * env); -AVSC_API(void, avs_at_exit)(AVS_ScriptEnvironment *, AVS_ShutdownFunc function, void * user_data); - -AVSC_API(AVS_VideoFrame *, avs_subframe)(AVS_ScriptEnvironment *, AVS_VideoFrame * src, int rel_offset, int new_pitch, int new_row_size, int new_height); -// The returned video frame must be be released - -AVSC_API(int, avs_set_memory_max)(AVS_ScriptEnvironment *, int mem); - -AVSC_API(int, avs_set_working_dir)(AVS_ScriptEnvironment *, const char * newdir); - -// avisynth.dll exports this; it's a way to use it as a library, without -// writing an AVS script or without going through AVIFile. -AVSC_API(AVS_ScriptEnvironment *, avs_create_script_environment)(int version); - -// this symbol is the entry point for the plugin and must -// be defined -AVSC_EXPORT -const char * AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env); - - -AVSC_API(void, avs_delete_script_environment)(AVS_ScriptEnvironment *); - - -AVSC_API(AVS_VideoFrame *, avs_subframe_planar)(AVS_ScriptEnvironment *, AVS_VideoFrame * src, int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int new_pitchUV); -// The returned video frame must be be released - -#ifdef AVSC_NO_DECLSPEC -// This part uses LoadLibrary and related functions to dynamically load Avisynth instead of declspec(dllimport) -// When AVSC_NO_DECLSPEC is defined, you can use avs_load_library to populate API functions into a struct -// AVSC_INLINE functions which call onto an API functions should be treated specially (todo) - -/* - The following functions needs to have been declared, probably from windows.h - - void* malloc(size_t) - void free(void*); - - HMODULE LoadLibrary(const char*); - void* GetProcAddress(HMODULE, const char*); - FreeLibrary(HMODULE); -*/ - - -typedef struct AVS_Library AVS_Library; - -#define AVSC_DECLARE_FUNC(name) name##_func name - -// AVSC_DECLARE_FUNC helps keeping naming convention: type is xxxxx_func, function name is xxxxx -// e.g. "AVSC_DECLARE_FUNC(avs_add_function);" -// is a shortcut for "avs_add_function_func avs_add_function;" - -// Note: AVSC_INLINE functions which call into API, -// are guarded by #ifndef AVSC_NO_DECLSPEC -// They should call the appropriate library-> API entry - -struct AVS_Library { - HMODULE handle; - - AVSC_DECLARE_FUNC(avs_add_function); - AVSC_DECLARE_FUNC(avs_at_exit); - AVSC_DECLARE_FUNC(avs_bit_blt); - AVSC_DECLARE_FUNC(avs_check_version); - AVSC_DECLARE_FUNC(avs_clip_get_error); - AVSC_DECLARE_FUNC(avs_copy_clip); - AVSC_DECLARE_FUNC(avs_copy_value); - AVSC_DECLARE_FUNC(avs_copy_video_frame); - AVSC_DECLARE_FUNC(avs_create_script_environment); - AVSC_DECLARE_FUNC(avs_delete_script_environment); - AVSC_DECLARE_FUNC(avs_function_exists); - AVSC_DECLARE_FUNC(avs_get_audio); - AVSC_DECLARE_FUNC(avs_get_cpu_flags); - AVSC_DECLARE_FUNC(avs_get_frame); - AVSC_DECLARE_FUNC(avs_get_parity); - AVSC_DECLARE_FUNC(avs_get_var); - AVSC_DECLARE_FUNC(avs_get_version); - AVSC_DECLARE_FUNC(avs_get_video_info); - AVSC_DECLARE_FUNC(avs_invoke); - AVSC_DECLARE_FUNC(avs_make_writable); - AVSC_DECLARE_FUNC(avs_new_c_filter); - AVSC_DECLARE_FUNC(avs_new_video_frame_a); - AVSC_DECLARE_FUNC(avs_release_clip); - AVSC_DECLARE_FUNC(avs_release_value); - AVSC_DECLARE_FUNC(avs_release_video_frame); - AVSC_DECLARE_FUNC(avs_save_string); - AVSC_DECLARE_FUNC(avs_set_cache_hints); - AVSC_DECLARE_FUNC(avs_set_global_var); - AVSC_DECLARE_FUNC(avs_set_memory_max); - AVSC_DECLARE_FUNC(avs_set_to_clip); - AVSC_DECLARE_FUNC(avs_set_var); - AVSC_DECLARE_FUNC(avs_set_working_dir); - AVSC_DECLARE_FUNC(avs_sprintf); - AVSC_DECLARE_FUNC(avs_subframe); - AVSC_DECLARE_FUNC(avs_subframe_planar); - AVSC_DECLARE_FUNC(avs_take_clip); - AVSC_DECLARE_FUNC(avs_vsprintf); - - AVSC_DECLARE_FUNC(avs_get_error); - AVSC_DECLARE_FUNC(avs_is_yv24); - AVSC_DECLARE_FUNC(avs_is_yv16); - AVSC_DECLARE_FUNC(avs_is_yv12); - AVSC_DECLARE_FUNC(avs_is_yv411); - AVSC_DECLARE_FUNC(avs_is_y8); - AVSC_DECLARE_FUNC(avs_is_color_space); - - AVSC_DECLARE_FUNC(avs_get_plane_width_subsampling); - AVSC_DECLARE_FUNC(avs_get_plane_height_subsampling); - AVSC_DECLARE_FUNC(avs_bits_per_pixel); - AVSC_DECLARE_FUNC(avs_bytes_from_pixels); - AVSC_DECLARE_FUNC(avs_row_size); - AVSC_DECLARE_FUNC(avs_bmp_size); - AVSC_DECLARE_FUNC(avs_get_pitch_p); - AVSC_DECLARE_FUNC(avs_get_row_size_p); - AVSC_DECLARE_FUNC(avs_get_height_p); - AVSC_DECLARE_FUNC(avs_get_read_ptr_p); - AVSC_DECLARE_FUNC(avs_is_writable); - AVSC_DECLARE_FUNC(avs_get_write_ptr_p); - - // Avisynth+ specific - // Note: these functions are simulated/use fallback to existing functions - AVSC_DECLARE_FUNC(avs_is_rgb48); - AVSC_DECLARE_FUNC(avs_is_rgb64); - AVSC_DECLARE_FUNC(avs_is_yuv444p16); - AVSC_DECLARE_FUNC(avs_is_yuv422p16); - AVSC_DECLARE_FUNC(avs_is_yuv420p16); - AVSC_DECLARE_FUNC(avs_is_y16); - AVSC_DECLARE_FUNC(avs_is_yuv444ps); - AVSC_DECLARE_FUNC(avs_is_yuv422ps); - AVSC_DECLARE_FUNC(avs_is_yuv420ps); - AVSC_DECLARE_FUNC(avs_is_y32); - AVSC_DECLARE_FUNC(avs_is_444); - AVSC_DECLARE_FUNC(avs_is_422); - AVSC_DECLARE_FUNC(avs_is_420); - AVSC_DECLARE_FUNC(avs_is_y); - AVSC_DECLARE_FUNC(avs_is_yuva); - AVSC_DECLARE_FUNC(avs_is_planar_rgb); - AVSC_DECLARE_FUNC(avs_is_planar_rgba); - AVSC_DECLARE_FUNC(avs_num_components); - AVSC_DECLARE_FUNC(avs_component_size); - AVSC_DECLARE_FUNC(avs_bits_per_component); - // end of Avisynth+ specific - -}; - -#undef AVSC_DECLARE_FUNC - -// Helper functions for fallback simulation -// Avisynth+ extensions do not exist in classic Avisynth so they are simulated -AVSC_INLINE int avs_is_xx_fallback_return_false(const AVS_VideoInfo * p) -{ - return 0; -} - -// Avisynth+ extensions do not exist in classic Avisynth so they are simulated -AVSC_INLINE int avs_num_components_fallback(const AVS_VideoInfo * p) -{ - switch (p->pixel_type) { - case AVS_CS_UNKNOWN: - return 0; - case AVS_CS_RAW32: - case AVS_CS_Y8: - return 1; - case AVS_CS_BGR32: - return 4; // not planar but return the count - default: - return 3; - } -} - -// Avisynth+ extensions do not exist in classic Avisynth so they are simulated -AVSC_INLINE int avs_component_size_fallback(const AVS_VideoInfo * p) -{ - return 1; -} - -// Avisynth+ extensions do not exist in classic Avisynth so they are simulated -AVSC_INLINE int avs_bits_per_component_fallback(const AVS_VideoInfo * p) -{ - return 8; -} -// End of helper functions for fallback simulation - -// avs_load_library() allocates an array for API procedure entries -// reads and fills the entries with live procedure addresses. -// AVSC_INLINE helpers which are calling into API procedures are not treated here (todo) - -AVSC_INLINE AVS_Library * avs_load_library() { - AVS_Library *library = (AVS_Library *)malloc(sizeof(AVS_Library)); - if (library == NULL) - return NULL; - library->handle = LoadLibrary("avisynth"); - if (library->handle == NULL) - goto fail; - -#define __AVSC_STRINGIFY(x) #x -#define AVSC_STRINGIFY(x) __AVSC_STRINGIFY(x) -#define AVSC_LOAD_FUNC(name) {\ - library->name = (name##_func) GetProcAddress(library->handle, AVSC_STRINGIFY(name));\ - if (library->name == NULL)\ - goto fail;\ -} - -#if 0 -// FFmpeg-specific: we don't use the FALLBACK stuff, and it causes build errors, -// so ifdef it out on our side. - -// When an API function is not loadable, let's try a replacement -// Missing Avisynth+ functions will be substituted with classic Avisynth compatible methods -/* -Avisynth+ When method is missing (classic Avisynth) -avs_is_rgb48 constant false -avs_is_rgb64 constant false -avs_is_yuv444p16 constant false -avs_is_yuv422p16 constant false -avs_is_yuv420p16 constant false -avs_is_y16 constant false -avs_is_yuv444ps constant false -avs_is_yuv422ps constant false -avs_is_yuv420ps constant false -avs_is_y32 constant false -avs_is_444 avs_is_yv24 -avs_is_422 avs_is_yv16 -avs_is_420 avs_is_yv12 -avs_is_y avs_is_y8 -avs_is_yuva constant false -avs_is_planar_rgb constant false -avs_is_planar_rgba constant false -avs_num_components special: avs_num_components_fake Y8:1 RGB32:4 else 3 -avs_component_size constant 1 (1 bytes/component) -avs_bits_per_component constant 8 (8 bits/component) -*/ - - // try to load an alternative function -#define AVSC_LOAD_FUNC_FALLBACK(name,name2) {\ - library->name = (name##_func) GetProcAddress(library->handle, AVSC_STRINGIFY(name));\ - if (library->name == NULL)\ - library->name = (name##_func) GetProcAddress(library->handle, AVSC_STRINGIFY(name2));\ - if (library->name == NULL)\ - goto fail;\ -} - - // try to assign a replacement function -#define AVSC_LOAD_FUNC_FALLBACK_SIMULATED(name,name2) {\ - library->name = (name##_func) GetProcAddress(library->handle, AVSC_STRINGIFY(name));\ - if (library->name == NULL)\ - library->name = name2;\ - if (library->name == NULL)\ - goto fail;\ -} -#endif - - AVSC_LOAD_FUNC(avs_add_function); - AVSC_LOAD_FUNC(avs_at_exit); - AVSC_LOAD_FUNC(avs_bit_blt); - AVSC_LOAD_FUNC(avs_check_version); - AVSC_LOAD_FUNC(avs_clip_get_error); - AVSC_LOAD_FUNC(avs_copy_clip); - AVSC_LOAD_FUNC(avs_copy_value); - AVSC_LOAD_FUNC(avs_copy_video_frame); - AVSC_LOAD_FUNC(avs_create_script_environment); - AVSC_LOAD_FUNC(avs_delete_script_environment); - AVSC_LOAD_FUNC(avs_function_exists); - AVSC_LOAD_FUNC(avs_get_audio); - AVSC_LOAD_FUNC(avs_get_cpu_flags); - AVSC_LOAD_FUNC(avs_get_frame); - AVSC_LOAD_FUNC(avs_get_parity); - AVSC_LOAD_FUNC(avs_get_var); - AVSC_LOAD_FUNC(avs_get_version); - AVSC_LOAD_FUNC(avs_get_video_info); - AVSC_LOAD_FUNC(avs_invoke); - AVSC_LOAD_FUNC(avs_make_writable); - AVSC_LOAD_FUNC(avs_new_c_filter); - AVSC_LOAD_FUNC(avs_new_video_frame_a); - AVSC_LOAD_FUNC(avs_release_clip); - AVSC_LOAD_FUNC(avs_release_value); - AVSC_LOAD_FUNC(avs_release_video_frame); - AVSC_LOAD_FUNC(avs_save_string); - AVSC_LOAD_FUNC(avs_set_cache_hints); - AVSC_LOAD_FUNC(avs_set_global_var); - AVSC_LOAD_FUNC(avs_set_memory_max); - AVSC_LOAD_FUNC(avs_set_to_clip); - AVSC_LOAD_FUNC(avs_set_var); - AVSC_LOAD_FUNC(avs_set_working_dir); - AVSC_LOAD_FUNC(avs_sprintf); - AVSC_LOAD_FUNC(avs_subframe); - AVSC_LOAD_FUNC(avs_subframe_planar); - AVSC_LOAD_FUNC(avs_take_clip); - AVSC_LOAD_FUNC(avs_vsprintf); - - AVSC_LOAD_FUNC(avs_get_error); - AVSC_LOAD_FUNC(avs_is_yv24); - AVSC_LOAD_FUNC(avs_is_yv16); - AVSC_LOAD_FUNC(avs_is_yv12); - AVSC_LOAD_FUNC(avs_is_yv411); - AVSC_LOAD_FUNC(avs_is_y8); - AVSC_LOAD_FUNC(avs_is_color_space); - - AVSC_LOAD_FUNC(avs_get_plane_width_subsampling); - AVSC_LOAD_FUNC(avs_get_plane_height_subsampling); - AVSC_LOAD_FUNC(avs_bits_per_pixel); - AVSC_LOAD_FUNC(avs_bytes_from_pixels); - AVSC_LOAD_FUNC(avs_row_size); - AVSC_LOAD_FUNC(avs_bmp_size); - AVSC_LOAD_FUNC(avs_get_pitch_p); - AVSC_LOAD_FUNC(avs_get_row_size_p); - AVSC_LOAD_FUNC(avs_get_height_p); - AVSC_LOAD_FUNC(avs_get_read_ptr_p); - AVSC_LOAD_FUNC(avs_is_writable); - AVSC_LOAD_FUNC(avs_get_write_ptr_p); - -#if 0 - // Avisynth+ specific but made them callable for classic Avisynth hosts - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_rgb48, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_rgb64, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_yuv444p16, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_yuv422p16, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_yuv420p16, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_y16, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_yuv444ps, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_yuv422ps, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_yuv420ps, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_y32, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK(avs_is_444, avs_is_yv24); - AVSC_LOAD_FUNC_FALLBACK(avs_is_422, avs_is_yv16); - AVSC_LOAD_FUNC_FALLBACK(avs_is_420, avs_is_yv12); - AVSC_LOAD_FUNC_FALLBACK(avs_is_y, avs_is_y8); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_yuva, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_planar_rgb, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_is_planar_rgba, avs_is_xx_fallback_return_false); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_num_components, avs_num_components_fallback); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_component_size, avs_component_size_fallback); - AVSC_LOAD_FUNC_FALLBACK_SIMULATED(avs_bits_per_component, avs_bits_per_component_fallback); -#endif - -#undef __AVSC_STRINGIFY -#undef AVSC_STRINGIFY -#undef AVSC_LOAD_FUNC -#undef AVSC_LOAD_FUNC_FALLBACK -#undef AVSC_LOAD_FUNC_FALLBACK_SIMULATED - - return library; - -fail: - free(library); - return NULL; -} - -AVSC_INLINE void avs_free_library(AVS_Library *library) { - if (library == NULL) - return; - FreeLibrary(library->handle); - free(library); -} -#endif - -#endif diff -Nru ffmpeg-4.2.2/compat/avisynth/avs/capi.h ffmpeg-4.4/compat/avisynth/avs/capi.h --- ffmpeg-4.2.2/compat/avisynth/avs/capi.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/compat/avisynth/avs/capi.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -// Avisynth C Interface Version 0.20 -// Copyright 2003 Kevin Atkinson - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that 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 this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit -// http://www.gnu.org/copyleft/gpl.html . -// -// As a special exception, I give you permission to link to the -// Avisynth C interface with independent modules that communicate with -// the Avisynth C interface solely through the interfaces defined in -// avisynth_c.h, regardless of the license terms of these independent -// modules, and to copy and distribute the resulting combined work -// under terms of your choice, provided that every copy of the -// combined work is accompanied by a complete copy of the source code -// of the Avisynth C interface and Avisynth itself (with the version -// used to produce the combined work), being distributed under the -// terms of the GNU General Public License plus this exception. An -// independent module is a module which is not derived from or based -// on Avisynth C Interface, such as 3rd-party filters, import and -// export plugins, or graphical user interfaces. - -#ifndef AVS_CAPI_H -#define AVS_CAPI_H - -#ifdef __cplusplus -# define EXTERN_C extern "C" -#else -# define EXTERN_C -#endif - -#ifdef BUILDING_AVSCORE -# if defined(GCC) && defined(X86_32) -# define AVSC_CC -# else // MSVC builds and 64-bit GCC -# ifndef AVSC_USE_STDCALL -# define AVSC_CC __cdecl -# else -# define AVSC_CC __stdcall -# endif -# endif -#else // needed for programs that talk to AviSynth+ -# ifndef AVSC_WIN32_GCC32 // see comment below -# ifndef AVSC_USE_STDCALL -# define AVSC_CC __cdecl -# else -# define AVSC_CC __stdcall -# endif -# else -# define AVSC_CC -# endif -#endif - -// On 64-bit Windows, there's only one calling convention, -// so there is no difference between MSVC and GCC. On 32-bit, -// this isn't true. The convention that GCC needs to use to -// even build AviSynth+ as 32-bit makes anything that uses -// it incompatible with 32-bit MSVC builds of AviSynth+. -// The AVSC_WIN32_GCC32 define is meant to provide a user -// switchable way to make builds of FFmpeg to test 32-bit -// GCC builds of AviSynth+ without having to screw around -// with alternate headers, while still default to the usual -// situation of using 32-bit MSVC builds of AviSynth+. - -// Hopefully, this situation will eventually be resolved -// and a broadly compatible solution will arise so the -// same 32-bit FFmpeg build can handle either MSVC or GCC -// builds of AviSynth+. - -#define AVSC_INLINE static __inline - -#ifdef BUILDING_AVSCORE -# define AVSC_EXPORT __declspec(dllexport) -# define AVSC_API(ret, name) EXTERN_C AVSC_EXPORT ret AVSC_CC name -#else -# define AVSC_EXPORT EXTERN_C __declspec(dllexport) -# ifndef AVSC_NO_DECLSPEC -# define AVSC_API(ret, name) EXTERN_C __declspec(dllimport) ret AVSC_CC name -# else -# define AVSC_API(ret, name) typedef ret (AVSC_CC *name##_func) -# endif -#endif - -#endif //AVS_CAPI_H diff -Nru ffmpeg-4.2.2/compat/avisynth/avs/config.h ffmpeg-4.4/compat/avisynth/avs/config.h --- ffmpeg-4.2.2/compat/avisynth/avs/config.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/compat/avisynth/avs/config.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -// Avisynth C Interface Version 0.20 -// Copyright 2003 Kevin Atkinson - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that 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 this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit -// http://www.gnu.org/copyleft/gpl.html . -// -// As a special exception, I give you permission to link to the -// Avisynth C interface with independent modules that communicate with -// the Avisynth C interface solely through the interfaces defined in -// avisynth_c.h, regardless of the license terms of these independent -// modules, and to copy and distribute the resulting combined work -// under terms of your choice, provided that every copy of the -// combined work is accompanied by a complete copy of the source code -// of the Avisynth C interface and Avisynth itself (with the version -// used to produce the combined work), being distributed under the -// terms of the GNU General Public License plus this exception. An -// independent module is a module which is not derived from or based -// on Avisynth C Interface, such as 3rd-party filters, import and -// export plugins, or graphical user interfaces. - -#ifndef AVS_CONFIG_H -#define AVS_CONFIG_H - -// Undefine this to get cdecl calling convention -#define AVSC_USE_STDCALL 1 - -// NOTE TO PLUGIN AUTHORS: -// Because FRAME_ALIGN can be substantially higher than the alignment -// a plugin actually needs, plugins should not use FRAME_ALIGN to check for -// alignment. They should always request the exact alignment value they need. -// This is to make sure that plugins work over the widest range of AviSynth -// builds possible. -#define FRAME_ALIGN 64 - -#if defined(_M_AMD64) || defined(__x86_64) -# define X86_64 -#elif defined(_M_IX86) || defined(__i386__) -# define X86_32 -#else -# error Unsupported CPU architecture. -#endif - -#if defined(_MSC_VER) -# define MSVC -#elif defined(__GNUC__) -# define GCC -#elif defined(__clang__) -# define CLANG -#else -# error Unsupported compiler. -#endif - -#if defined(GCC) -# undef __forceinline -# define __forceinline inline -#endif - -#endif //AVS_CONFIG_H diff -Nru ffmpeg-4.2.2/compat/avisynth/avs/types.h ffmpeg-4.4/compat/avisynth/avs/types.h --- ffmpeg-4.2.2/compat/avisynth/avs/types.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/compat/avisynth/avs/types.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -// Avisynth C Interface Version 0.20 -// Copyright 2003 Kevin Atkinson - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that 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 this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit -// http://www.gnu.org/copyleft/gpl.html . -// -// As a special exception, I give you permission to link to the -// Avisynth C interface with independent modules that communicate with -// the Avisynth C interface solely through the interfaces defined in -// avisynth_c.h, regardless of the license terms of these independent -// modules, and to copy and distribute the resulting combined work -// under terms of your choice, provided that every copy of the -// combined work is accompanied by a complete copy of the source code -// of the Avisynth C interface and Avisynth itself (with the version -// used to produce the combined work), being distributed under the -// terms of the GNU General Public License plus this exception. An -// independent module is a module which is not derived from or based -// on Avisynth C Interface, such as 3rd-party filters, import and -// export plugins, or graphical user interfaces. - -#ifndef AVS_TYPES_H -#define AVS_TYPES_H - -// Define all types necessary for interfacing with avisynth.dll - -#ifdef __cplusplus - #include -#else - #include -#endif - -// Raster types used by VirtualDub & Avisynth -typedef unsigned int Pixel32; -typedef unsigned char BYTE; - -// Audio Sample information -typedef float SFLOAT; - -#ifdef __GNUC__ -typedef long long int INT64; -#else -typedef __int64 INT64; -#endif - -#endif //AVS_TYPES_H diff -Nru ffmpeg-4.2.2/compat/avisynth/avxsynth_c.h ffmpeg-4.4/compat/avisynth/avxsynth_c.h --- ffmpeg-4.2.2/compat/avisynth/avxsynth_c.h 2017-12-31 22:35:45.000000000 +0000 +++ ffmpeg-4.4/compat/avisynth/avxsynth_c.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,728 +0,0 @@ -// Avisynth C Interface Version 0.20 -// Copyright 2003 Kevin Atkinson - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that 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 this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -// MA 02110-1301 USA, or visit -// http://www.gnu.org/copyleft/gpl.html . -// -// As a special exception, I give you permission to link to the -// Avisynth C interface with independent modules that communicate with -// the Avisynth C interface solely through the interfaces defined in -// avisynth_c.h, regardless of the license terms of these independent -// modules, and to copy and distribute the resulting combined work -// under terms of your choice, provided that every copy of the -// combined work is accompanied by a complete copy of the source code -// of the Avisynth C interface and Avisynth itself (with the version -// used to produce the combined work), being distributed under the -// terms of the GNU General Public License plus this exception. An -// independent module is a module which is not derived from or based -// on Avisynth C Interface, such as 3rd-party filters, import and -// export plugins, or graphical user interfaces. - -#ifndef __AVXSYNTH_C__ -#define __AVXSYNTH_C__ - -#include "windowsPorts/windows2linux.h" -#include - -#ifdef __cplusplus -# define EXTERN_C extern "C" -#else -# define EXTERN_C -#endif - -#define AVSC_USE_STDCALL 1 - -#ifndef AVSC_USE_STDCALL -# define AVSC_CC __cdecl -#else -# define AVSC_CC __stdcall -#endif - -#define AVSC_INLINE static __inline - -#ifdef AVISYNTH_C_EXPORTS -# define AVSC_EXPORT EXTERN_C -# define AVSC_API(ret, name) EXTERN_C __declspec(dllexport) ret AVSC_CC name -#else -# define AVSC_EXPORT EXTERN_C __declspec(dllexport) -# ifndef AVSC_NO_DECLSPEC -# define AVSC_API(ret, name) EXTERN_C __declspec(dllimport) ret AVSC_CC name -# else -# define AVSC_API(ret, name) typedef ret (AVSC_CC *name##_func) -# endif -#endif - -#ifdef __GNUC__ -typedef long long int INT64; -#else -typedef __int64 INT64; -#endif - - -///////////////////////////////////////////////////////////////////// -// -// Constants -// - -#ifndef __AVXSYNTH_H__ -enum { AVISYNTH_INTERFACE_VERSION = 3 }; -#endif - -enum {AVS_SAMPLE_INT8 = 1<<0, - AVS_SAMPLE_INT16 = 1<<1, - AVS_SAMPLE_INT24 = 1<<2, - AVS_SAMPLE_INT32 = 1<<3, - AVS_SAMPLE_FLOAT = 1<<4}; - -enum {AVS_PLANAR_Y=1<<0, - AVS_PLANAR_U=1<<1, - AVS_PLANAR_V=1<<2, - AVS_PLANAR_ALIGNED=1<<3, - AVS_PLANAR_Y_ALIGNED=AVS_PLANAR_Y|AVS_PLANAR_ALIGNED, - AVS_PLANAR_U_ALIGNED=AVS_PLANAR_U|AVS_PLANAR_ALIGNED, - AVS_PLANAR_V_ALIGNED=AVS_PLANAR_V|AVS_PLANAR_ALIGNED}; - - // Colorspace properties. -enum {AVS_CS_BGR = 1<<28, - AVS_CS_YUV = 1<<29, - AVS_CS_INTERLEAVED = 1<<30, - AVS_CS_PLANAR = 1<<31}; - - // Specific colorformats -enum { - AVS_CS_UNKNOWN = 0, - AVS_CS_BGR24 = 1<<0 | AVS_CS_BGR | AVS_CS_INTERLEAVED, - AVS_CS_BGR32 = 1<<1 | AVS_CS_BGR | AVS_CS_INTERLEAVED, - AVS_CS_YUY2 = 1<<2 | AVS_CS_YUV | AVS_CS_INTERLEAVED, - AVS_CS_YV12 = 1<<3 | AVS_CS_YUV | AVS_CS_PLANAR, // y-v-u, planar - AVS_CS_I420 = 1<<4 | AVS_CS_YUV | AVS_CS_PLANAR, // y-u-v, planar - AVS_CS_IYUV = 1<<4 | AVS_CS_YUV | AVS_CS_PLANAR // same as above -}; - -enum { - AVS_IT_BFF = 1<<0, - AVS_IT_TFF = 1<<1, - AVS_IT_FIELDBASED = 1<<2}; - -enum { - AVS_FILTER_TYPE=1, - AVS_FILTER_INPUT_COLORSPACE=2, - AVS_FILTER_OUTPUT_TYPE=9, - AVS_FILTER_NAME=4, - AVS_FILTER_AUTHOR=5, - AVS_FILTER_VERSION=6, - AVS_FILTER_ARGS=7, - AVS_FILTER_ARGS_INFO=8, - AVS_FILTER_ARGS_DESCRIPTION=10, - AVS_FILTER_DESCRIPTION=11}; - -enum { //SUBTYPES - AVS_FILTER_TYPE_AUDIO=1, - AVS_FILTER_TYPE_VIDEO=2, - AVS_FILTER_OUTPUT_TYPE_SAME=3, - AVS_FILTER_OUTPUT_TYPE_DIFFERENT=4}; - -enum { - AVS_CACHE_NOTHING=0, - AVS_CACHE_RANGE=1, - AVS_CACHE_ALL=2, - AVS_CACHE_AUDIO=3, - AVS_CACHE_AUDIO_NONE=4, - AVS_CACHE_AUDIO_AUTO=5 -}; - -#define AVS_FRAME_ALIGN 16 - -typedef struct AVS_Clip AVS_Clip; -typedef struct AVS_ScriptEnvironment AVS_ScriptEnvironment; - -///////////////////////////////////////////////////////////////////// -// -// AVS_VideoInfo -// - -// AVS_VideoInfo is layed out identicly to VideoInfo -typedef struct AVS_VideoInfo { - int width, height; // width=0 means no video - unsigned fps_numerator, fps_denominator; - int num_frames; - - int pixel_type; - - int audio_samples_per_second; // 0 means no audio - int sample_type; - INT64 num_audio_samples; - int nchannels; - - // Imagetype properties - - int image_type; -} AVS_VideoInfo; - -// useful functions of the above -AVSC_INLINE int avs_has_video(const AVS_VideoInfo * p) - { return (p->width!=0); } - -AVSC_INLINE int avs_has_audio(const AVS_VideoInfo * p) - { return (p->audio_samples_per_second!=0); } - -AVSC_INLINE int avs_is_rgb(const AVS_VideoInfo * p) - { return !!(p->pixel_type&AVS_CS_BGR); } - -AVSC_INLINE int avs_is_rgb24(const AVS_VideoInfo * p) - { return (p->pixel_type&AVS_CS_BGR24)==AVS_CS_BGR24; } // Clear out additional properties - -AVSC_INLINE int avs_is_rgb32(const AVS_VideoInfo * p) - { return (p->pixel_type & AVS_CS_BGR32) == AVS_CS_BGR32 ; } - -AVSC_INLINE int avs_is_yuv(const AVS_VideoInfo * p) - { return !!(p->pixel_type&AVS_CS_YUV ); } - -AVSC_INLINE int avs_is_yuy2(const AVS_VideoInfo * p) - { return (p->pixel_type & AVS_CS_YUY2) == AVS_CS_YUY2; } - -AVSC_INLINE int avs_is_yv12(const AVS_VideoInfo * p) - { return ((p->pixel_type & AVS_CS_YV12) == AVS_CS_YV12)||((p->pixel_type & AVS_CS_I420) == AVS_CS_I420); } - -AVSC_INLINE int avs_is_color_space(const AVS_VideoInfo * p, int c_space) - { return ((p->pixel_type & c_space) == c_space); } - -AVSC_INLINE int avs_is_property(const AVS_VideoInfo * p, int property) - { return ((p->pixel_type & property)==property ); } - -AVSC_INLINE int avs_is_planar(const AVS_VideoInfo * p) - { return !!(p->pixel_type & AVS_CS_PLANAR); } - -AVSC_INLINE int avs_is_field_based(const AVS_VideoInfo * p) - { return !!(p->image_type & AVS_IT_FIELDBASED); } - -AVSC_INLINE int avs_is_parity_known(const AVS_VideoInfo * p) - { return ((p->image_type & AVS_IT_FIELDBASED)&&(p->image_type & (AVS_IT_BFF | AVS_IT_TFF))); } - -AVSC_INLINE int avs_is_bff(const AVS_VideoInfo * p) - { return !!(p->image_type & AVS_IT_BFF); } - -AVSC_INLINE int avs_is_tff(const AVS_VideoInfo * p) - { return !!(p->image_type & AVS_IT_TFF); } - -AVSC_INLINE int avs_bits_per_pixel(const AVS_VideoInfo * p) -{ - switch (p->pixel_type) { - case AVS_CS_BGR24: return 24; - case AVS_CS_BGR32: return 32; - case AVS_CS_YUY2: return 16; - case AVS_CS_YV12: - case AVS_CS_I420: return 12; - default: return 0; - } -} -AVSC_INLINE int avs_bytes_from_pixels(const AVS_VideoInfo * p, int pixels) - { return pixels * (avs_bits_per_pixel(p)>>3); } // Will work on planar images, but will return only luma planes - -AVSC_INLINE int avs_row_size(const AVS_VideoInfo * p) - { return avs_bytes_from_pixels(p,p->width); } // Also only returns first plane on planar images - -AVSC_INLINE int avs_bmp_size(const AVS_VideoInfo * vi) - { if (avs_is_planar(vi)) {int p = vi->height * ((avs_row_size(vi)+3) & ~3); p+=p>>1; return p; } return vi->height * ((avs_row_size(vi)+3) & ~3); } - -AVSC_INLINE int avs_samples_per_second(const AVS_VideoInfo * p) - { return p->audio_samples_per_second; } - - -AVSC_INLINE int avs_bytes_per_channel_sample(const AVS_VideoInfo * p) -{ - switch (p->sample_type) { - case AVS_SAMPLE_INT8: return sizeof(signed char); - case AVS_SAMPLE_INT16: return sizeof(signed short); - case AVS_SAMPLE_INT24: return 3; - case AVS_SAMPLE_INT32: return sizeof(signed int); - case AVS_SAMPLE_FLOAT: return sizeof(float); - default: return 0; - } -} -AVSC_INLINE int avs_bytes_per_audio_sample(const AVS_VideoInfo * p) - { return p->nchannels*avs_bytes_per_channel_sample(p);} - -AVSC_INLINE INT64 avs_audio_samples_from_frames(const AVS_VideoInfo * p, INT64 frames) - { return ((INT64)(frames) * p->audio_samples_per_second * p->fps_denominator / p->fps_numerator); } - -AVSC_INLINE int avs_frames_from_audio_samples(const AVS_VideoInfo * p, INT64 samples) - { return (int)(samples * (INT64)p->fps_numerator / (INT64)p->fps_denominator / (INT64)p->audio_samples_per_second); } - -AVSC_INLINE INT64 avs_audio_samples_from_bytes(const AVS_VideoInfo * p, INT64 bytes) - { return bytes / avs_bytes_per_audio_sample(p); } - -AVSC_INLINE INT64 avs_bytes_from_audio_samples(const AVS_VideoInfo * p, INT64 samples) - { return samples * avs_bytes_per_audio_sample(p); } - -AVSC_INLINE int avs_audio_channels(const AVS_VideoInfo * p) - { return p->nchannels; } - -AVSC_INLINE int avs_sample_type(const AVS_VideoInfo * p) - { return p->sample_type;} - -// useful mutator -AVSC_INLINE void avs_set_property(AVS_VideoInfo * p, int property) - { p->image_type|=property; } - -AVSC_INLINE void avs_clear_property(AVS_VideoInfo * p, int property) - { p->image_type&=~property; } - -AVSC_INLINE void avs_set_field_based(AVS_VideoInfo * p, int isfieldbased) - { if (isfieldbased) p->image_type|=AVS_IT_FIELDBASED; else p->image_type&=~AVS_IT_FIELDBASED; } - -AVSC_INLINE void avs_set_fps(AVS_VideoInfo * p, unsigned numerator, unsigned denominator) -{ - unsigned x=numerator, y=denominator; - while (y) { // find gcd - unsigned t = x%y; x = y; y = t; - } - p->fps_numerator = numerator/x; - p->fps_denominator = denominator/x; -} - -AVSC_INLINE int avs_is_same_colorspace(AVS_VideoInfo * x, AVS_VideoInfo * y) -{ - return (x->pixel_type == y->pixel_type) - || (avs_is_yv12(x) && avs_is_yv12(y)); -} - -///////////////////////////////////////////////////////////////////// -// -// AVS_VideoFrame -// - -// VideoFrameBuffer holds information about a memory block which is used -// for video data. For efficiency, instances of this class are not deleted -// when the refcount reaches zero; instead they're stored in a linked list -// to be reused. The instances are deleted when the corresponding AVS -// file is closed. - -// AVS_VideoFrameBuffer is layed out identicly to VideoFrameBuffer -// DO NOT USE THIS STRUCTURE DIRECTLY -typedef struct AVS_VideoFrameBuffer { - unsigned char * data; - int data_size; - // sequence_number is incremented every time the buffer is changed, so - // that stale views can tell they're no longer valid. - long sequence_number; - - long refcount; -} AVS_VideoFrameBuffer; - -// VideoFrame holds a "window" into a VideoFrameBuffer. - -// AVS_VideoFrame is layed out identicly to IVideoFrame -// DO NOT USE THIS STRUCTURE DIRECTLY -typedef struct AVS_VideoFrame { - int refcount; - AVS_VideoFrameBuffer * vfb; - int offset, pitch, row_size, height, offsetU, offsetV, pitchUV; // U&V offsets are from top of picture. -} AVS_VideoFrame; - -// Access functions for AVS_VideoFrame -AVSC_INLINE int avs_get_pitch(const AVS_VideoFrame * p) { - return p->pitch;} - -AVSC_INLINE int avs_get_pitch_p(const AVS_VideoFrame * p, int plane) { - switch (plane) { - case AVS_PLANAR_U: case AVS_PLANAR_V: return p->pitchUV;} - return p->pitch;} - -AVSC_INLINE int avs_get_row_size(const AVS_VideoFrame * p) { - return p->row_size; } - -AVSC_INLINE int avs_get_row_size_p(const AVS_VideoFrame * p, int plane) { - int r; - switch (plane) { - case AVS_PLANAR_U: case AVS_PLANAR_V: - if (p->pitchUV) return p->row_size>>1; - else return 0; - case AVS_PLANAR_U_ALIGNED: case AVS_PLANAR_V_ALIGNED: - if (p->pitchUV) { - r = ((p->row_size+AVS_FRAME_ALIGN-1)&(~(AVS_FRAME_ALIGN-1)) )>>1; // Aligned rowsize - if (r < p->pitchUV) - return r; - return p->row_size>>1; - } else return 0; - case AVS_PLANAR_Y_ALIGNED: - r = (p->row_size+AVS_FRAME_ALIGN-1)&(~(AVS_FRAME_ALIGN-1)); // Aligned rowsize - if (r <= p->pitch) - return r; - return p->row_size; - } - return p->row_size; -} - -AVSC_INLINE int avs_get_height(const AVS_VideoFrame * p) { - return p->height;} - -AVSC_INLINE int avs_get_height_p(const AVS_VideoFrame * p, int plane) { - switch (plane) { - case AVS_PLANAR_U: case AVS_PLANAR_V: - if (p->pitchUV) return p->height>>1; - return 0; - } - return p->height;} - -AVSC_INLINE const unsigned char* avs_get_read_ptr(const AVS_VideoFrame * p) { - return p->vfb->data + p->offset;} - -AVSC_INLINE const unsigned char* avs_get_read_ptr_p(const AVS_VideoFrame * p, int plane) -{ - switch (plane) { - case AVS_PLANAR_U: return p->vfb->data + p->offsetU; - case AVS_PLANAR_V: return p->vfb->data + p->offsetV; - default: return p->vfb->data + p->offset;} -} - -AVSC_INLINE int avs_is_writable(const AVS_VideoFrame * p) { - return (p->refcount == 1 && p->vfb->refcount == 1);} - -AVSC_INLINE unsigned char* avs_get_write_ptr(const AVS_VideoFrame * p) -{ - if (avs_is_writable(p)) { - ++p->vfb->sequence_number; - return p->vfb->data + p->offset; - } else - return 0; -} - -AVSC_INLINE unsigned char* avs_get_write_ptr_p(const AVS_VideoFrame * p, int plane) -{ - if (plane==AVS_PLANAR_Y && avs_is_writable(p)) { - ++p->vfb->sequence_number; - return p->vfb->data + p->offset; - } else if (plane==AVS_PLANAR_Y) { - return 0; - } else { - switch (plane) { - case AVS_PLANAR_U: return p->vfb->data + p->offsetU; - case AVS_PLANAR_V: return p->vfb->data + p->offsetV; - default: return p->vfb->data + p->offset; - } - } -} - -#if defined __cplusplus -extern "C" -{ -#endif // __cplusplus -AVSC_API(void, avs_release_video_frame)(AVS_VideoFrame *); -// makes a shallow copy of a video frame -AVSC_API(AVS_VideoFrame *, avs_copy_video_frame)(AVS_VideoFrame *); -#if defined __cplusplus -} -#endif // __cplusplus - -#ifndef AVSC_NO_DECLSPEC -AVSC_INLINE void avs_release_frame(AVS_VideoFrame * f) - {avs_release_video_frame(f);} -AVSC_INLINE AVS_VideoFrame * avs_copy_frame(AVS_VideoFrame * f) - {return avs_copy_video_frame(f);} -#endif - -///////////////////////////////////////////////////////////////////// -// -// AVS_Value -// - -// Treat AVS_Value as a fat pointer. That is use avs_copy_value -// and avs_release_value appropiaty as you would if AVS_Value was -// a pointer. - -// To maintain source code compatibility with future versions of the -// avisynth_c API don't use the AVS_Value directly. Use the helper -// functions below. - -// AVS_Value is layed out identicly to AVSValue -typedef struct AVS_Value AVS_Value; -struct AVS_Value { - short type; // 'a'rray, 'c'lip, 'b'ool, 'i'nt, 'f'loat, 's'tring, 'v'oid, or 'l'ong - // for some function e'rror - short array_size; - union { - void * clip; // do not use directly, use avs_take_clip - char boolean; - int integer; - INT64 integer64; // match addition of __int64 to avxplugin.h - float floating_pt; - const char * string; - const AVS_Value * array; - } d; -}; - -// AVS_Value should be initilized with avs_void. -// Should also set to avs_void after the value is released -// with avs_copy_value. Consider it the equalvent of setting -// a pointer to NULL -static const AVS_Value avs_void = {'v'}; - -AVSC_API(void, avs_copy_value)(AVS_Value * dest, AVS_Value src); -AVSC_API(void, avs_release_value)(AVS_Value); - -AVSC_INLINE int avs_defined(AVS_Value v) { return v.type != 'v'; } -AVSC_INLINE int avs_is_clip(AVS_Value v) { return v.type == 'c'; } -AVSC_INLINE int avs_is_bool(AVS_Value v) { return v.type == 'b'; } -AVSC_INLINE int avs_is_int(AVS_Value v) { return v.type == 'i'; } -AVSC_INLINE int avs_is_float(AVS_Value v) { return v.type == 'f' || v.type == 'i'; } -AVSC_INLINE int avs_is_string(AVS_Value v) { return v.type == 's'; } -AVSC_INLINE int avs_is_array(AVS_Value v) { return v.type == 'a'; } -AVSC_INLINE int avs_is_error(AVS_Value v) { return v.type == 'e'; } - -#if defined __cplusplus -extern "C" -{ -#endif // __cplusplus -AVSC_API(AVS_Clip *, avs_take_clip)(AVS_Value, AVS_ScriptEnvironment *); -AVSC_API(void, avs_set_to_clip)(AVS_Value *, AVS_Clip *); -#if defined __cplusplus -} -#endif // __cplusplus - -AVSC_INLINE int avs_as_bool(AVS_Value v) - { return v.d.boolean; } -AVSC_INLINE int avs_as_int(AVS_Value v) - { return v.d.integer; } -AVSC_INLINE const char * avs_as_string(AVS_Value v) - { return avs_is_error(v) || avs_is_string(v) ? v.d.string : 0; } -AVSC_INLINE double avs_as_float(AVS_Value v) - { return avs_is_int(v) ? v.d.integer : v.d.floating_pt; } -AVSC_INLINE const char * avs_as_error(AVS_Value v) - { return avs_is_error(v) ? v.d.string : 0; } -AVSC_INLINE const AVS_Value * avs_as_array(AVS_Value v) - { return v.d.array; } -AVSC_INLINE int avs_array_size(AVS_Value v) - { return avs_is_array(v) ? v.array_size : 1; } -AVSC_INLINE AVS_Value avs_array_elt(AVS_Value v, int index) - { return avs_is_array(v) ? v.d.array[index] : v; } - -// only use these functions on am AVS_Value that does not already have -// an active value. Remember, treat AVS_Value as a fat pointer. -AVSC_INLINE AVS_Value avs_new_value_bool(int v0) - { AVS_Value v = {0}; v.type = 'b'; v.d.boolean = v0 == 0 ? 0 : 1; return v; } -AVSC_INLINE AVS_Value avs_new_value_int(int v0) - { AVS_Value v = {0}; v.type = 'i'; v.d.integer = v0; return v; } -AVSC_INLINE AVS_Value avs_new_value_string(const char * v0) - { AVS_Value v = {0}; v.type = 's'; v.d.string = v0; return v; } -AVSC_INLINE AVS_Value avs_new_value_float(float v0) - { AVS_Value v = {0}; v.type = 'f'; v.d.floating_pt = v0; return v;} -AVSC_INLINE AVS_Value avs_new_value_error(const char * v0) - { AVS_Value v = {0}; v.type = 'e'; v.d.string = v0; return v; } -#ifndef AVSC_NO_DECLSPEC -AVSC_INLINE AVS_Value avs_new_value_clip(AVS_Clip * v0) - { AVS_Value v = {0}; avs_set_to_clip(&v, v0); return v; } -#endif -AVSC_INLINE AVS_Value avs_new_value_array(AVS_Value * v0, int size) - { AVS_Value v = {0}; v.type = 'a'; v.d.array = v0; v.array_size = size; return v; } - -///////////////////////////////////////////////////////////////////// -// -// AVS_Clip -// -#if defined __cplusplus -extern "C" -{ -#endif // __cplusplus -AVSC_API(void, avs_release_clip)(AVS_Clip *); -AVSC_API(AVS_Clip *, avs_copy_clip)(AVS_Clip *); - -AVSC_API(const char *, avs_clip_get_error)(AVS_Clip *); // return 0 if no error - -AVSC_API(const AVS_VideoInfo *, avs_get_video_info)(AVS_Clip *); - -AVSC_API(int, avs_get_version)(AVS_Clip *); - -AVSC_API(AVS_VideoFrame *, avs_get_frame)(AVS_Clip *, int n); -// The returned video frame must be released with avs_release_video_frame - -AVSC_API(int, avs_get_parity)(AVS_Clip *, int n); -// return field parity if field_based, else parity of first field in frame - -AVSC_API(int, avs_get_audio)(AVS_Clip *, void * buf, - INT64 start, INT64 count); -// start and count are in samples - -AVSC_API(int, avs_set_cache_hints)(AVS_Clip *, - int cachehints, size_t frame_range); -#if defined __cplusplus -} -#endif // __cplusplus - -// This is the callback type used by avs_add_function -typedef AVS_Value (AVSC_CC * AVS_ApplyFunc) - (AVS_ScriptEnvironment *, AVS_Value args, void * user_data); - -typedef struct AVS_FilterInfo AVS_FilterInfo; -struct AVS_FilterInfo -{ - // these members should not be modified outside of the AVS_ApplyFunc callback - AVS_Clip * child; - AVS_VideoInfo vi; - AVS_ScriptEnvironment * env; - AVS_VideoFrame * (AVSC_CC * get_frame)(AVS_FilterInfo *, int n); - int (AVSC_CC * get_parity)(AVS_FilterInfo *, int n); - int (AVSC_CC * get_audio)(AVS_FilterInfo *, void * buf, - INT64 start, INT64 count); - int (AVSC_CC * set_cache_hints)(AVS_FilterInfo *, int cachehints, - int frame_range); - void (AVSC_CC * free_filter)(AVS_FilterInfo *); - - // Should be set when ever there is an error to report. - // It is cleared before any of the above methods are called - const char * error; - // this is to store whatever and may be modified at will - void * user_data; -}; - -// Create a new filter -// fi is set to point to the AVS_FilterInfo so that you can -// modify it once it is initilized. -// store_child should generally be set to true. If it is not -// set than ALL methods (the function pointers) must be defined -// If it is set than you do not need to worry about freeing the child -// clip. -#if defined __cplusplus -extern "C" -{ -#endif // __cplusplus -AVSC_API(AVS_Clip *, avs_new_c_filter)(AVS_ScriptEnvironment * e, - AVS_FilterInfo * * fi, - AVS_Value child, int store_child); -#if defined __cplusplus -} -#endif // __cplusplus - - -///////////////////////////////////////////////////////////////////// -// -// AVS_ScriptEnvironment -// - -// For GetCPUFlags. These are backwards-compatible with those in VirtualDub. -enum { - /* slowest CPU to support extension */ - AVS_CPU_FORCE = 0x01, // N/A - AVS_CPU_FPU = 0x02, // 386/486DX - AVS_CPU_MMX = 0x04, // P55C, K6, PII - AVS_CPU_INTEGER_SSE = 0x08, // PIII, Athlon - AVS_CPU_SSE = 0x10, // PIII, Athlon XP/MP - AVS_CPU_SSE2 = 0x20, // PIV, Hammer - AVS_CPU_3DNOW = 0x40, // K6-2 - AVS_CPU_3DNOW_EXT = 0x80, // Athlon - AVS_CPU_X86_64 = 0xA0, // Hammer (note: equiv. to 3DNow + SSE2, - // which only Hammer will have anyway) -}; - -#if defined __cplusplus -extern "C" -{ -#endif // __cplusplus -AVSC_API(const char *, avs_get_error)(AVS_ScriptEnvironment *); // return 0 if no error - -AVSC_API(long, avs_get_cpu_flags)(AVS_ScriptEnvironment *); -AVSC_API(int, avs_check_version)(AVS_ScriptEnvironment *, int version); - -AVSC_API(char *, avs_save_string)(AVS_ScriptEnvironment *, const char* s, int length); -AVSC_API(char *, avs_sprintf)(AVS_ScriptEnvironment *, const char * fmt, ...); - -AVSC_API(char *, avs_vsprintf)(AVS_ScriptEnvironment *, const char * fmt, va_list val); - // note: val is really a va_list; I hope everyone typedefs va_list to a pointer - -AVSC_API(int, avs_add_function)(AVS_ScriptEnvironment *, - const char * name, const char * params, - AVS_ApplyFunc apply, void * user_data); - -AVSC_API(int, avs_function_exists)(AVS_ScriptEnvironment *, const char * name); - -AVSC_API(AVS_Value, avs_invoke)(AVS_ScriptEnvironment *, const char * name, - AVS_Value args, const char** arg_names); -// The returned value must be be released with avs_release_value - -AVSC_API(AVS_Value, avs_get_var)(AVS_ScriptEnvironment *, const char* name); -// The returned value must be be released with avs_release_value - -AVSC_API(int, avs_set_var)(AVS_ScriptEnvironment *, const char* name, AVS_Value val); - -AVSC_API(int, avs_set_global_var)(AVS_ScriptEnvironment *, const char* name, const AVS_Value val); - -//void avs_push_context(AVS_ScriptEnvironment *, int level=0); -//void avs_pop_context(AVS_ScriptEnvironment *); - -AVSC_API(AVS_VideoFrame *, avs_new_video_frame_a)(AVS_ScriptEnvironment *, - const AVS_VideoInfo * vi, int align); -// align should be at least 16 -#if defined __cplusplus -} -#endif // __cplusplus - -#ifndef AVSC_NO_DECLSPEC -AVSC_INLINE -AVS_VideoFrame * avs_new_video_frame(AVS_ScriptEnvironment * env, - const AVS_VideoInfo * vi) - {return avs_new_video_frame_a(env,vi,AVS_FRAME_ALIGN);} - -AVSC_INLINE -AVS_VideoFrame * avs_new_frame(AVS_ScriptEnvironment * env, - const AVS_VideoInfo * vi) - {return avs_new_video_frame_a(env,vi,AVS_FRAME_ALIGN);} -#endif - -#if defined __cplusplus -extern "C" -{ -#endif // __cplusplus -AVSC_API(int, avs_make_writable)(AVS_ScriptEnvironment *, AVS_VideoFrame * * pvf); - -AVSC_API(void, avs_bit_blt)(AVS_ScriptEnvironment *, unsigned char* dstp, int dst_pitch, const unsigned char* srcp, int src_pitch, int row_size, int height); - -typedef void (AVSC_CC *AVS_ShutdownFunc)(void* user_data, AVS_ScriptEnvironment * env); -AVSC_API(void, avs_at_exit)(AVS_ScriptEnvironment *, AVS_ShutdownFunc function, void * user_data); - -AVSC_API(AVS_VideoFrame *, avs_subframe)(AVS_ScriptEnvironment *, AVS_VideoFrame * src, int rel_offset, int new_pitch, int new_row_size, int new_height); -// The returned video frame must be be released - -AVSC_API(int, avs_set_memory_max)(AVS_ScriptEnvironment *, int mem); - -AVSC_API(int, avs_set_working_dir)(AVS_ScriptEnvironment *, const char * newdir); - -// avisynth.dll exports this; it's a way to use it as a library, without -// writing an AVS script or without going through AVIFile. -AVSC_API(AVS_ScriptEnvironment *, avs_create_script_environment)(int version); -#if defined __cplusplus -} -#endif // __cplusplus - -// this symbol is the entry point for the plugin and must -// be defined -AVSC_EXPORT -const char * AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env); - - -#if defined __cplusplus -extern "C" -{ -#endif // __cplusplus -AVSC_API(void, avs_delete_script_environment)(AVS_ScriptEnvironment *); - - -AVSC_API(AVS_VideoFrame *, avs_subframe_planar)(AVS_ScriptEnvironment *, AVS_VideoFrame * src, int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int new_pitchUV); -// The returned video frame must be be released -#if defined __cplusplus -} -#endif // __cplusplus - -#endif //__AVXSYNTH_C__ diff -Nru ffmpeg-4.2.2/compat/avisynth/windowsPorts/basicDataTypeConversions.h ffmpeg-4.4/compat/avisynth/windowsPorts/basicDataTypeConversions.h --- ffmpeg-4.2.2/compat/avisynth/windowsPorts/basicDataTypeConversions.h 2016-03-29 02:25:07.000000000 +0000 +++ ffmpeg-4.4/compat/avisynth/windowsPorts/basicDataTypeConversions.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -#ifndef __DATA_TYPE_CONVERSIONS_H__ -#define __DATA_TYPE_CONVERSIONS_H__ - -#include -#include - -#ifdef __cplusplus -namespace avxsynth { -#endif // __cplusplus - -typedef int64_t __int64; -typedef int32_t __int32; -#ifdef __cplusplus -typedef bool BOOL; -#else -typedef uint32_t BOOL; -#endif // __cplusplus -typedef void* HMODULE; -typedef void* LPVOID; -typedef void* PVOID; -typedef PVOID HANDLE; -typedef HANDLE HWND; -typedef HANDLE HINSTANCE; -typedef void* HDC; -typedef void* HBITMAP; -typedef void* HICON; -typedef void* HFONT; -typedef void* HGDIOBJ; -typedef void* HBRUSH; -typedef void* HMMIO; -typedef void* HACMSTREAM; -typedef void* HACMDRIVER; -typedef void* HIC; -typedef void* HACMOBJ; -typedef HACMSTREAM* LPHACMSTREAM; -typedef void* HACMDRIVERID; -typedef void* LPHACMDRIVER; -typedef unsigned char BYTE; -typedef BYTE* LPBYTE; -typedef char TCHAR; -typedef TCHAR* LPTSTR; -typedef const TCHAR* LPCTSTR; -typedef char* LPSTR; -typedef LPSTR LPOLESTR; -typedef const char* LPCSTR; -typedef LPCSTR LPCOLESTR; -typedef wchar_t WCHAR; -typedef unsigned short WORD; -typedef unsigned int UINT; -typedef UINT MMRESULT; -typedef uint32_t DWORD; -typedef DWORD COLORREF; -typedef DWORD FOURCC; -typedef DWORD HRESULT; -typedef DWORD* LPDWORD; -typedef DWORD* DWORD_PTR; -typedef int32_t LONG; -typedef int32_t* LONG_PTR; -typedef LONG_PTR LRESULT; -typedef uint32_t ULONG; -typedef uint32_t* ULONG_PTR; -//typedef __int64_t intptr_t; -typedef uint64_t _fsize_t; - - -// -// Structures -// - -typedef struct _GUID { - DWORD Data1; - WORD Data2; - WORD Data3; - BYTE Data4[8]; -} GUID; - -typedef GUID REFIID; -typedef GUID CLSID; -typedef CLSID* LPCLSID; -typedef GUID IID; - -#ifdef __cplusplus -}; // namespace avxsynth -#endif // __cplusplus -#endif // __DATA_TYPE_CONVERSIONS_H__ diff -Nru ffmpeg-4.2.2/compat/avisynth/windowsPorts/windows2linux.h ffmpeg-4.4/compat/avisynth/windowsPorts/windows2linux.h --- ffmpeg-4.2.2/compat/avisynth/windowsPorts/windows2linux.h 2017-12-31 22:35:45.000000000 +0000 +++ ffmpeg-4.4/compat/avisynth/windowsPorts/windows2linux.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -#ifndef __WINDOWS2LINUX_H__ -#define __WINDOWS2LINUX_H__ - -/* - * LINUX SPECIFIC DEFINITIONS -*/ -// -// Data types conversions -// -#include -#include -#include "basicDataTypeConversions.h" - -#ifdef __cplusplus -namespace avxsynth { -#endif // __cplusplus -// -// purposefully define the following MSFT definitions -// to mean nothing (as they do not mean anything on Linux) -// -#define __stdcall -#define __cdecl -#define noreturn -#define __declspec(x) -#define STDAPI extern "C" HRESULT -#define STDMETHODIMP HRESULT __stdcall -#define STDMETHODIMP_(x) x __stdcall - -#define STDMETHOD(x) virtual HRESULT x -#define STDMETHOD_(a, x) virtual a x - -#ifndef TRUE -#define TRUE true -#endif - -#ifndef FALSE -#define FALSE false -#endif - -#define S_OK (0x00000000) -#define S_FALSE (0x00000001) -#define E_NOINTERFACE (0X80004002) -#define E_POINTER (0x80004003) -#define E_FAIL (0x80004005) -#define E_OUTOFMEMORY (0x8007000E) - -#define INVALID_HANDLE_VALUE ((HANDLE)((LONG_PTR)-1)) -#define FAILED(hr) ((hr) & 0x80000000) -#define SUCCEEDED(hr) (!FAILED(hr)) - - -// -// Functions -// -#define MAKEDWORD(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) -#define MAKEWORD(a,b) (((a) << 8) | (b)) - -#define lstrlen strlen -#define lstrcpy strcpy -#define lstrcmpi strcasecmp -#define _stricmp strcasecmp -#define InterlockedIncrement(x) __sync_fetch_and_add((x), 1) -#define InterlockedDecrement(x) __sync_fetch_and_sub((x), 1) -// Windows uses (new, old) ordering but GCC has (old, new) -#define InterlockedCompareExchange(x,y,z) __sync_val_compare_and_swap(x,z,y) - -#define UInt32x32To64(a, b) ( (uint64_t) ( ((uint64_t)((uint32_t)(a))) * ((uint32_t)(b)) ) ) -#define Int64ShrlMod32(a, b) ( (uint64_t) ( (uint64_t)(a) >> (b) ) ) -#define Int32x32To64(a, b) ((__int64)(((__int64)((long)(a))) * ((long)(b)))) - -#define MulDiv(nNumber, nNumerator, nDenominator) (int32_t) (((int64_t) (nNumber) * (int64_t) (nNumerator) + (int64_t) ((nDenominator)/2)) / (int64_t) (nDenominator)) - -#ifdef __cplusplus -}; // namespace avxsynth -#endif // __cplusplus - -#endif // __WINDOWS2LINUX_H__ diff -Nru ffmpeg-4.2.2/compat/cuda/cuda_runtime.h ffmpeg-4.4/compat/cuda/cuda_runtime.h --- ffmpeg-4.2.2/compat/cuda/cuda_runtime.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/compat/cuda/cuda_runtime.h 2021-04-08 21:28:39.000000000 +0000 @@ -1,7 +1,7 @@ /* * Minimum CUDA compatibility definitions header * - * Copyright (c) 2019 Rodger Combs + * Copyright (c) 2019 rcombs * * This file is part of FFmpeg. * @@ -49,18 +49,23 @@ unsigned short x, y; } ushort2; -typedef struct __device_builtin__ uint3 +typedef struct __device_builtin__ __align__(8) float2 { - unsigned int x, y, z; -} uint3; - -typedef struct uint3 dim3; + float x, y; +} float2; typedef struct __device_builtin__ __align__(8) int2 { int x, y; } int2; +typedef struct __device_builtin__ uint3 +{ + unsigned int x, y, z; +} uint3; + +typedef struct uint3 dim3; + typedef struct __device_builtin__ __align__(4) uchar4 { unsigned char x, y, z, w; @@ -68,7 +73,7 @@ typedef struct __device_builtin__ __align__(8) ushort4 { - unsigned char x, y, z, w; + unsigned short x, y, z, w; } ushort4; typedef struct __device_builtin__ __align__(16) int4 @@ -76,6 +81,11 @@ int x, y, z, w; } int4; +typedef struct __device_builtin__ __align__(16) float4 +{ + float x, y, z, w; +} float4; + // Accessors for special registers #define GETCOMP(reg, comp) \ asm("mov.u32 %0, %%" #reg "." #comp ";" : "=r"(tmp)); \ @@ -100,24 +110,31 @@ #define threadIdx (getThreadIdx()) // Basic initializers (simple macros rather than inline functions) +#define make_int2(a, b) ((int2){.x = a, .y = b}) #define make_uchar2(a, b) ((uchar2){.x = a, .y = b}) #define make_ushort2(a, b) ((ushort2){.x = a, .y = b}) +#define make_float2(a, b) ((float2){.x = a, .y = b}) +#define make_int4(a, b, c, d) ((int4){.x = a, .y = b, .z = c, .w = d}) #define make_uchar4(a, b, c, d) ((uchar4){.x = a, .y = b, .z = c, .w = d}) #define make_ushort4(a, b, c, d) ((ushort4){.x = a, .y = b, .z = c, .w = d}) +#define make_float4(a, b, c, d) ((float4){.x = a, .y = b, .z = c, .w = d}) // Conversions from the tex instruction's 4-register output to various types #define TEX2D(type, ret) static inline __device__ void conv(type* out, unsigned a, unsigned b, unsigned c, unsigned d) {*out = (ret);} TEX2D(unsigned char, a & 0xFF) TEX2D(unsigned short, a & 0xFFFF) +TEX2D(float, a) TEX2D(uchar2, make_uchar2(a & 0xFF, b & 0xFF)) TEX2D(ushort2, make_ushort2(a & 0xFFFF, b & 0xFFFF)) +TEX2D(float2, make_float2(a, b)) TEX2D(uchar4, make_uchar4(a & 0xFF, b & 0xFF, c & 0xFF, d & 0xFF)) TEX2D(ushort4, make_ushort4(a & 0xFFFF, b & 0xFFFF, c & 0xFFFF, d & 0xFFFF)) +TEX2D(float4, make_float4(a, b, c, d)) // Template calling tex instruction and converting the output to the selected type -template -static inline __device__ T tex2D(cudaTextureObject_t texObject, float x, float y) +template +inline __device__ T tex2D(cudaTextureObject_t texObject, float x, float y) { T ret; unsigned ret1, ret2, ret3, ret4; @@ -128,4 +145,44 @@ return ret; } +template<> +inline __device__ float4 tex2D(cudaTextureObject_t texObject, float x, float y) +{ + float4 ret; + asm("tex.2d.v4.f32.f32 {%0, %1, %2, %3}, [%4, {%5, %6}];" : + "=r"(ret.x), "=r"(ret.y), "=r"(ret.z), "=r"(ret.w) : + "l"(texObject), "f"(x), "f"(y)); + return ret; +} + +template<> +inline __device__ float tex2D(cudaTextureObject_t texObject, float x, float y) +{ + return tex2D(texObject, x, y).x; +} + +template<> +inline __device__ float2 tex2D(cudaTextureObject_t texObject, float x, float y) +{ + float4 ret = tex2D(texObject, x, y); + return make_float2(ret.x, ret.y); +} + +// Math helper functions +static inline __device__ float floorf(float a) { return __builtin_floorf(a); } +static inline __device__ float floor(float a) { return __builtin_floorf(a); } +static inline __device__ double floor(double a) { return __builtin_floor(a); } +static inline __device__ float ceilf(float a) { return __builtin_ceilf(a); } +static inline __device__ float ceil(float a) { return __builtin_ceilf(a); } +static inline __device__ double ceil(double a) { return __builtin_ceil(a); } +static inline __device__ float truncf(float a) { return __builtin_truncf(a); } +static inline __device__ float trunc(float a) { return __builtin_truncf(a); } +static inline __device__ double trunc(double a) { return __builtin_trunc(a); } +static inline __device__ float fabsf(float a) { return __builtin_fabsf(a); } +static inline __device__ float fabs(float a) { return __builtin_fabsf(a); } +static inline __device__ double fabs(double a) { return __builtin_fabs(a); } + +static inline __device__ float __sinf(float a) { return __nvvm_sin_approx_f(a); } +static inline __device__ float __cosf(float a) { return __nvvm_cos_approx_f(a); } + #endif /* COMPAT_CUDA_CUDA_RUNTIME_H */ diff -Nru ffmpeg-4.2.2/compat/cuda/ptx2c.sh ffmpeg-4.4/compat/cuda/ptx2c.sh --- ffmpeg-4.2.2/compat/cuda/ptx2c.sh 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/compat/cuda/ptx2c.sh 2020-07-11 10:39:30.000000000 +0000 @@ -27,10 +27,8 @@ NAME="$(basename "$IN" | sed 's/\..*//')" printf "const char %s_ptx[] = \\" "$NAME" > "$OUT" -while IFS= read -r LINE -do - printf "\n\t\"%s\\\n\"" "$(printf "%s" "$LINE" | sed -e 's/\r//g' -e 's/["\\]/\\&/g')" >> "$OUT" -done < "$IN" -printf ";\n" >> "$OUT" +echo >> "$OUT" +sed -e "$(printf 's/\r//g')" -e 's/["\\]/\\&/g' -e "$(printf 's/^/\t"/')" -e 's/$/\\n"/' < "$IN" >> "$OUT" +echo ";" >> "$OUT" exit 0 diff -Nru ffmpeg-4.2.2/compat/os2threads.h ffmpeg-4.4/compat/os2threads.h --- ffmpeg-4.2.2/compat/os2threads.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/compat/os2threads.h 2020-07-11 10:39:30.000000000 +0000 @@ -27,15 +27,19 @@ #define COMPAT_OS2THREADS_H #define INCL_DOS +#define INCL_DOSERRORS #include #undef __STRICT_ANSI__ /* for _beginthread() */ #include +#include #include #include #include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/time.h" typedef struct { TID tid; @@ -163,6 +167,28 @@ return 0; } +static av_always_inline int pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + int64_t abs_milli = abstime->tv_sec * 1000LL + abstime->tv_nsec / 1000000; + ULONG t = av_clip64(abs_milli - av_gettime() / 1000, 0, ULONG_MAX); + + __atomic_increment(&cond->wait_count); + + pthread_mutex_unlock(mutex); + + APIRET ret = DosWaitEventSem(cond->event_sem, t); + + __atomic_decrement(&cond->wait_count); + + DosPostEventSem(cond->ack_sem); + + pthread_mutex_lock(mutex); + + return (ret == ERROR_TIMEOUT) ? ETIMEDOUT : 0; +} + static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { diff -Nru ffmpeg-4.2.2/compat/w32pthreads.h ffmpeg-4.4/compat/w32pthreads.h --- ffmpeg-4.2.2/compat/w32pthreads.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/compat/w32pthreads.h 2020-07-11 10:39:30.000000000 +0000 @@ -38,11 +38,13 @@ #define WIN32_LEAN_AND_MEAN #include #include +#include #include "libavutil/attributes.h" #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/mem.h" +#include "libavutil/time.h" typedef struct pthread_t { void *handle; @@ -61,6 +63,9 @@ #define InitializeCriticalSection(x) InitializeCriticalSectionEx(x, 0, 0) #define WaitForSingleObject(a, b) WaitForSingleObjectEx(a, b, FALSE) +#define PTHREAD_CANCEL_ENABLE 1 +#define PTHREAD_CANCEL_DISABLE 0 + static av_unused unsigned __stdcall attribute_align_arg win32thread_worker(void *arg) { pthread_t *h = (pthread_t*)arg; @@ -156,10 +161,31 @@ return 0; } +static inline int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + int64_t abs_milli = abstime->tv_sec * 1000LL + abstime->tv_nsec / 1000000; + DWORD t = av_clip64(abs_milli - av_gettime() / 1000, 0, UINT32_MAX); + + if (!SleepConditionVariableSRW(cond, mutex, t, 0)) { + DWORD err = GetLastError(); + if (err == ERROR_TIMEOUT) + return ETIMEDOUT; + else + return EINVAL; + } + return 0; +} + static inline int pthread_cond_signal(pthread_cond_t *cond) { WakeConditionVariable(cond); return 0; } +static inline int pthread_setcancelstate(int state, int *oldstate) +{ + return 0; +} + #endif /* COMPAT_W32PTHREADS_H */ diff -Nru ffmpeg-4.2.2/configure ffmpeg-4.4/configure --- ffmpeg-4.2.2/configure 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/configure 2021-04-08 21:28:39.000000000 +0000 @@ -190,9 +190,9 @@ Using any of the following switches will allow FFmpeg to link to the corresponding external library. All the components depending on that library will become enabled, if all their other dependencies are met and they are not - explicitly disabled. E.g. --enable-libwavpack will enable linking to - libwavpack and allow the libwavpack encoder to be built, unless it is - specifically disabled with --disable-encoder=libwavpack. + explicitly disabled. E.g. --enable-libopus will enable linking to + libopus and allow the libopus encoder to be built, unless it is + specifically disabled with --disable-encoder=libopus. Note that only the system libraries are auto-detected. All the other external libraries must be explicitly enabled. @@ -236,6 +236,7 @@ --enable-libfontconfig enable libfontconfig, useful for drawtext filter [no] --enable-libfreetype enable libfreetype, needed for drawtext filter [no] --enable-libfribidi enable libfribidi, improves drawtext filter [no] + --enable-libglslang enable GLSL->SPIRV compilation via libglslang [no] --enable-libgme enable Game Music Emu via libgme [no] --enable-libgsm enable GSM de/encoding via libgsm [no] --enable-libiec61883 enable iec61883 via libiec61883 [no] @@ -252,8 +253,13 @@ --enable-libopenh264 enable H.264 encoding via OpenH264 [no] --enable-libopenjpeg enable JPEG 2000 de/encoding via OpenJPEG [no] --enable-libopenmpt enable decoding tracked files via libopenmpt [no] + --enable-libopenvino enable OpenVINO as a DNN module backend + for DNN based filters like dnn_processing [no] --enable-libopus enable Opus de/encoding via libopus [no] --enable-libpulse enable Pulseaudio input via libpulse [no] + --enable-librabbitmq enable RabbitMQ library [no] + --enable-librav1e enable AV1 encoding via rav1e [no] + --enable-librist enable RIST via librist [no] --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] @@ -264,6 +270,7 @@ --enable-libspeex enable Speex de/encoding via libspeex [no] --enable-libsrt enable Haivision SRT protocol via libsrt [no] --enable-libssh enable SFTP protocol via libssh [no] + --enable-libsvtav1 enable AV1 encoding via SVT [no] --enable-libtensorflow enable TensorFlow as a DNN module backend for DNN based filters like sr [no] --enable-libtesseract enable Tesseract, needed for ocr filter [no] @@ -271,6 +278,7 @@ --enable-libtls enable LibreSSL (via libtls), needed for https support if openssl, gnutls or mbedtls is not used [no] --enable-libtwolame enable MP2 encoding via libtwolame [no] + --enable-libuavs3d enable AVS3 decoding via libuavs3d [no] --enable-libv4l2 enable libv4l2/v4l-utils [no] --enable-libvidstab enable video stabilization using vid.stab [no] --enable-libvmaf enable vmaf filter via libvmaf [no] @@ -278,7 +286,6 @@ --enable-libvorbis enable Vorbis en/decoding via libvorbis, native implementation exists [no] --enable-libvpx enable VP8 and VP9 de/encoding via libvpx [no] - --enable-libwavpack enable wavpack encoding via libwavpack [no] --enable-libwebp enable WebP encoding via libwebp [no] --enable-libx264 enable H.264 encoding via x264 [no] --enable-libx265 enable HEVC encoding via x265 [no] @@ -301,6 +308,7 @@ --enable-mbedtls enable mbedTLS, needed for https support if openssl, gnutls or libtls is not used [no] --enable-mediacodec enable Android MediaCodec support [no] + --enable-mediafoundation enable encoding via MediaFoundation [auto] --enable-libmysofa enable libmysofa, needed for sofalizer filter [no] --enable-openal enable OpenAL 1.1 capture support [no] --enable-opencl enable OpenCL processing [no] @@ -315,6 +323,7 @@ --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-xlib disable xlib [autodetect] --disable-zlib disable zlib [autodetect] @@ -481,6 +490,7 @@ --ignore-tests=TESTS comma-separated list (without "fate-" prefix in the name) of tests whose result is ignored --enable-linux-perf enable Linux Performance Monitor API + --disable-large-tests disable tests that use a large amount of memory NOTE: Object files are built at the place where configure is launched. EOF @@ -1547,11 +1557,11 @@ } require_cpp(){ - name="$1" - headers="$2" - classes="$3" - shift 3 - check_lib_cpp "$headers" "$classes" "$@" || die "ERROR: $name not found" + log require_cpp "$@" + name_version="$1" + name="${1%% *}" + shift + check_lib_cpp "$name" "$@" || die "ERROR: $name_version not found" } require_headers(){ @@ -1662,7 +1672,7 @@ " EXAMPLE_LIST=" - avio_dir_cmd_example + avio_list_dir_example avio_reading_example decode_audio_example decode_video_example @@ -1699,6 +1709,7 @@ libxcb_shape libxcb_xfixes lzma + mediafoundation schannel sdl2 securetransport @@ -1734,7 +1745,6 @@ liblensfun libopencore_amrnb libopencore_amrwb - libvmaf libvo_amrwbenc mbedtls rkmpp @@ -1768,6 +1778,7 @@ libfontconfig libfreetype libfribidi + libglslang libgme libgsm libiec61883 @@ -1782,8 +1793,12 @@ libopenh264 libopenjpeg libopenmpt + libopenvino libopus libpulse + librabbitmq + librav1e + librist librsvg librtmp libshine @@ -1793,14 +1808,16 @@ libspeex libsrt libssh + libsvtav1 libtensorflow libtesseract libtheora libtwolame + libuavs3d libv4l2 + libvmaf libvorbis libvpx - libwavpack libwebp libxml2 libzimg @@ -1851,6 +1868,7 @@ mmal omx opencl + vulkan " DOCUMENT_LIST=" @@ -1929,6 +1947,7 @@ $SUBSYSTEM_LIST autodetect fontconfig + large_tests linux_perf memory_poisoning neon_clobber_test @@ -2108,6 +2127,7 @@ ES2_gl_h gsm_h io_h + linux_dma_buf_h linux_perf_event_h machine_ioctl_bt848_h machine_ioctl_meteor_h @@ -2192,10 +2212,12 @@ getaddrinfo gethrtime getopt + GetModuleHandle GetProcessAffinityMask GetProcessMemoryInfo GetProcessTimes getrusage + GetStdHandle GetSystemTimeAsFileTime gettimeofday glob @@ -2221,6 +2243,7 @@ SecItemImport SetConsoleTextAttribute SetConsoleCtrlHandler + SetDllDirectory setmode setrlimit Sleep @@ -2267,7 +2290,11 @@ TYPES_LIST=" kCMVideoCodecType_HEVC + kCMVideoCodecType_HEVCWithAlpha kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange + kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ + kCVImageBufferTransferFunction_ITU_R_2100_HLG + kCVImageBufferTransferFunction_Linear socklen_t struct_addrinfo struct_group_source_req @@ -2302,6 +2329,7 @@ $THREADS_LIST $TOOLCHAIN_FEATURES $TYPES_LIST + libdrm_getfb2 makeinfo makeinfo_html opencl_d3d11 @@ -2320,6 +2348,7 @@ aandcttables ac3dsp adts_header + atsc_a53 audio_frame_queue audiodsp blockdsp @@ -2533,7 +2562,7 @@ mipsfpu_deps="mips" mipsdsp_deps="mips" mipsdspr2_deps="mips" -mmi_deps="mips" +mmi_deps_any="loongson2 loongson3" msa_deps="mipsfpu" msa2_deps="msa" @@ -2602,14 +2631,15 @@ cbs_vp9_select="cbs" dct_select="rdft" dirac_parse_select="golomb" -dnn_suggest="libtensorflow" +dnn_suggest="libtensorflow libopenvino" +dnn_deps="swscale" error_resilience_select="me_cmp" faandct_deps="faan" faandct_select="fdctdsp" faanidct_deps="faan" faanidct_select="idctdsp" h264dsp_select="startcode" -hevcparse_select="golomb" +hevcparse_select="atsc_a53 golomb" frame_thread_encoder_deps="encoders threads" intrax8_select="blockdsp idctdsp" mdct_select="fft" @@ -2625,13 +2655,14 @@ # decoders / encoders aac_decoder_select="adts_header mdct15 mdct sinewin" -aac_fixed_decoder_select="adts_header mdct sinewin" +aac_fixed_decoder_select="adts_header mdct" 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" ac3_fixed_decoder_select="ac3_parser ac3dsp bswapdsp mdct" ac3_encoder_select="ac3dsp audiodsp mdct me_cmp" ac3_fixed_encoder_select="ac3dsp audiodsp mdct me_cmp" +acelp_kelvin_decoder_select="audiodsp" adpcm_g722_decoder_select="g722dsp" adpcm_g722_encoder_select="g722dsp" aic_decoder_select="golomb idctdsp" @@ -2655,9 +2686,11 @@ asv2_encoder_select="aandcttables bswapdsp fdctdsp pixblockdsp" atrac1_decoder_select="mdct sinewin" atrac3_decoder_select="mdct" +atrac3al_decoder_select="mdct" atrac3p_decoder_select="mdct sinewin" +atrac3pal_decoder_select="mdct sinewin" atrac9_decoder_select="mdct" -avrn_decoder_select="exif jpegtables" +av1_decoder_select="cbs_av1" bink_decoder_select="blockdsp hpeldsp" binkaudio_dct_decoder_select="mdct rdft dct sinewin wma_freqs" binkaudio_rdft_decoder_select="mdct rdft sinewin wma_freqs" @@ -2669,6 +2702,7 @@ cscd_decoder_select="lzo" cscd_decoder_suggest="zlib" dca_decoder_select="mdct" +dca_encoder_select="mdct" dds_decoder_select="texturedsp" dirac_decoder_select="dirac_parse dwt golomb videodsp mpegvideoenc" dnxhd_decoder_select="blockdsp idctdsp" @@ -2684,6 +2718,7 @@ eatgq_decoder_select="aandcttables" eatqi_decoder_select="aandcttables blockdsp bswapdsp idctdsp" exr_decoder_deps="zlib" +exr_encoder_deps="zlib" ffv1_decoder_select="rangecoder" ffv1_encoder_select="rangecoder" ffvhuff_decoder_select="huffyuv_decoder" @@ -2709,17 +2744,19 @@ h263i_decoder_select="h263_decoder" h263p_decoder_select="h263_decoder" h263p_encoder_select="h263_encoder" -h264_decoder_select="cabac golomb h264chroma h264dsp h264parse h264pred h264qpel videodsp" +h264_decoder_select="atsc_a53 cabac golomb h264chroma h264dsp h264parse h264pred h264qpel videodsp" h264_decoder_suggest="error_resilience" hap_decoder_select="snappy texturedsp" hap_encoder_deps="libsnappy" hap_encoder_select="texturedspenc" -hevc_decoder_select="bswapdsp cabac golomb hevcparse videodsp" +hevc_decoder_select="atsc_a53 bswapdsp cabac golomb hevcparse videodsp" huffyuv_decoder_select="bswapdsp huffyuvdsp llviddsp" huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp llvidencdsp" hymt_decoder_select="huffyuv_decoder" iac_decoder_select="imc_decoder" imc_decoder_select="bswapdsp fft mdct sinewin" +imm4_decoder_select="bswapdsp" +imm5_decoder_select="h264_decoder hevc_decoder" indeo3_decoder_select="hpeldsp" indeo4_decoder_select="ividsp" indeo5_decoder_select="ividsp" @@ -2727,11 +2764,11 @@ jpegls_decoder_select="mjpeg_decoder" jv_decoder_select="blockdsp" lagarith_decoder_select="llviddsp" -ljpeg_encoder_select="idctdsp jpegtables mpegvideoenc" +ljpeg_encoder_select="idctdsp jpegtables" lscr_decoder_deps="zlib" magicyuv_decoder_select="llviddsp" magicyuv_encoder_select="llvidencdsp" -mdec_decoder_select="blockdsp idctdsp mpegvideo" +mdec_decoder_select="blockdsp bswapdsp idctdsp mpegvideo" metasound_decoder_select="lsp mdct sinewin" mimic_decoder_select="blockdsp bswapdsp hpeldsp idctdsp" mjpeg_decoder_select="blockdsp hpeldsp exif idctdsp jpegtables" @@ -2739,6 +2776,7 @@ mjpegb_decoder_select="mjpeg_decoder" mlp_decoder_select="mlp_parser" mlp_encoder_select="lpc audio_frame_queue" +mobiclip_decoder_select="bswapdsp golomb" motionpixels_decoder_select="bswapdsp" mp1_decoder_select="mpegaudio" mp1float_decoder_select="mpegaudio" @@ -2767,11 +2805,15 @@ msmpeg4v3_decoder_select="h263_decoder" msmpeg4v3_encoder_select="h263_encoder" mss2_decoder_select="mpegvideo qpeldsp vc1_decoder" -mts2_decoder_select="mss34dsp" +mts2_decoder_select="jpegtables mss34dsp" +mv30_decoder_select="aandcttables blockdsp" +mvha_decoder_deps="zlib" +mvha_decoder_select="llviddsp" mwsc_decoder_deps="zlib" mxpeg_decoder_select="mjpeg_decoder" nellymoser_decoder_select="mdct sinewin" nellymoser_encoder_select="audio_frame_queue mdct sinewin" +notchlc_decoder_select="lzf" nuv_decoder_select="idctdsp lzo" on2avc_decoder_select="mdct" opus_decoder_deps="swresample" @@ -2800,6 +2842,7 @@ screenpresso_decoder_deps="zlib" shorten_decoder_select="bswapdsp" sipr_decoder_select="lsp" +smvjpeg_decoder_select="mjpeg_decoder" snow_decoder_select="dwt h264qpel hpeldsp me_cmp rangecoder videodsp" snow_encoder_select="dwt h264qpel hpeldsp me_cmp mpegvideoenc rangecoder" sonic_decoder_select="golomb rangecoder" @@ -2807,6 +2850,7 @@ sonic_ls_encoder_select="golomb rangecoder" sp5x_decoder_select="mjpeg_decoder" speedhq_decoder_select="mpegvideo" +speedhq_encoder_select="mpegvideoenc" srgc_decoder_deps="zlib" svq1_decoder_select="hpeldsp" svq1_encoder_select="hpeldsp me_cmp mpegvideoenc" @@ -2817,6 +2861,7 @@ tdsc_decoder_select="mjpeg_decoder" theora_decoder_select="vp3_decoder" thp_decoder_select="mjpeg_decoder" +tiff_decoder_select="mjpeg_decoder" tiff_decoder_suggest="zlib lzma" tiff_encoder_suggest="zlib" truehd_decoder_select="mlp_parser" @@ -2859,6 +2904,7 @@ wmv3image_decoder_select="wmv3_decoder" xma1_decoder_select="wmapro_decoder" xma2_decoder_select="wmapro_decoder" +ylc_decoder_select="bswapdsp" zerocodec_decoder_deps="zlib" zlib_decoder_deps="zlib" zlib_encoder_deps="zlib" @@ -2878,6 +2924,16 @@ videotoolbox_hwaccel_extralibs="-framework QuartzCore" xvmc_deps="X11_extensions_XvMClib_h" +av1_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_AV1" +av1_d3d11va_hwaccel_select="av1_decoder" +av1_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_AV1" +av1_d3d11va2_hwaccel_select="av1_decoder" +av1_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_AV1" +av1_dxva2_hwaccel_select="av1_decoder" +av1_nvdec_hwaccel_deps="nvdec CUVIDAV1PICPARAMS" +av1_nvdec_hwaccel_select="av1_decoder" +av1_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferAV1_bit_depth_idx" +av1_vaapi_hwaccel_select="av1_decoder" h263_vaapi_hwaccel_deps="vaapi" h263_vaapi_hwaccel_select="h263_decoder" h263_videotoolbox_hwaccel_deps="videotoolbox" @@ -2974,6 +3030,8 @@ vp9_nvdec_hwaccel_select="vp9_decoder" 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" wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel" wmv3_d3d11va2_hwaccel_select="vc1_d3d11va2_hwaccel" wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel" @@ -2982,6 +3040,8 @@ wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" # hardware-accelerated codecs +mediafoundation_deps="mftransform_h MFCreateAlignedMemoryBuffer" +mediafoundation_extralibs="-lmfplat -lmfuuid -lole32 -lstrmiids" omx_deps="libdl pthreads" omx_rpi_select="omx" qsv_deps="libmfx" @@ -2998,12 +3058,17 @@ thumbnail_cuda_filter_deps="ffnvcodec" thumbnail_cuda_filter_deps_any="cuda_nvcc cuda_llvm" transpose_npp_filter_deps="ffnvcodec libnpp" +overlay_cuda_filter_deps="ffnvcodec" +overlay_cuda_filter_deps_any="cuda_nvcc cuda_llvm" amf_deps_any="libdl LoadLibrary" nvenc_deps="ffnvcodec" nvenc_deps_any="libdl LoadLibrary" nvenc_encoder_deps="nvenc" +aac_mf_encoder_deps="mediafoundation" +ac3_mf_encoder_deps="mediafoundation" +av1_cuvid_decoder_deps="cuvid CUVIDAV1PICPARAMS" h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m" h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m" h264_amf_encoder_deps="amf" @@ -3012,11 +3077,13 @@ h264_cuvid_decoder_select="h264_mp4toannexb_bsf" h264_mediacodec_decoder_deps="mediacodec" h264_mediacodec_decoder_select="h264_mp4toannexb_bsf h264_parser" +h264_mf_encoder_deps="mediafoundation" h264_mmal_decoder_deps="mmal" h264_nvenc_encoder_deps="nvenc" +h264_nvenc_encoder_select="atsc_a53" h264_omx_encoder_deps="omx" -h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec" -h264_qsv_encoder_select="qsvenc" +h264_qsv_decoder_select="h264_mp4toannexb_bsf qsvdec" +h264_qsv_encoder_select="atsc_a53 qsvenc" h264_rkmpp_decoder_deps="rkmpp" h264_rkmpp_decoder_select="h264_mp4toannexb_bsf" h264_vaapi_encoder_select="cbs_h264 vaapi_encode" @@ -3028,8 +3095,10 @@ hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" hevc_mediacodec_decoder_deps="mediacodec" hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser" +hevc_mf_encoder_deps="mediafoundation" hevc_nvenc_encoder_deps="nvenc" -hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser qsvdec" +hevc_nvenc_encoder_select="atsc_a53" +hevc_qsv_decoder_select="hevc_mp4toannexb_bsf qsvdec" hevc_qsv_encoder_select="hevcparse qsvenc" hevc_rkmpp_decoder_deps="rkmpp" hevc_rkmpp_decoder_select="hevc_mp4toannexb_bsf" @@ -3039,17 +3108,19 @@ hevc_v4l2m2m_decoder_select="hevc_mp4toannexb_bsf" hevc_v4l2m2m_encoder_deps="v4l2_m2m hevc_v4l2_m2m" mjpeg_cuvid_decoder_deps="cuvid" +mjpeg_qsv_decoder_select="qsvdec" mjpeg_qsv_encoder_deps="libmfx" mjpeg_qsv_encoder_select="qsvenc" mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG" mjpeg_vaapi_encoder_select="cbs_jpeg jpegtables vaapi_encode" +mp3_mf_encoder_deps="mediafoundation" mpeg1_cuvid_decoder_deps="cuvid" mpeg1_v4l2m2m_decoder_deps="v4l2_m2m mpeg1_v4l2_m2m" mpeg2_crystalhd_decoder_select="crystalhd" mpeg2_cuvid_decoder_deps="cuvid" mpeg2_mmal_decoder_deps="mmal" mpeg2_mediacodec_decoder_deps="mediacodec" -mpeg2_qsv_decoder_select="qsvdec mpegvideo_parser" +mpeg2_qsv_decoder_select="qsvdec" mpeg2_qsv_encoder_select="qsvenc" mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode" mpeg2_v4l2m2m_decoder_deps="v4l2_m2m mpeg2_v4l2_m2m" @@ -3066,11 +3137,11 @@ vc1_crystalhd_decoder_select="crystalhd" vc1_cuvid_decoder_deps="cuvid" vc1_mmal_decoder_deps="mmal" -vc1_qsv_decoder_select="qsvdec vc1_parser" +vc1_qsv_decoder_select="qsvdec" vc1_v4l2m2m_decoder_deps="v4l2_m2m vc1_v4l2_m2m" vp8_cuvid_decoder_deps="cuvid" vp8_mediacodec_decoder_deps="mediacodec" -vp8_qsv_decoder_select="qsvdec vp8_parser" +vp8_qsv_decoder_select="qsvdec" vp8_rkmpp_decoder_deps="rkmpp" vp8_vaapi_encoder_deps="VAEncPictureParameterBufferVP8" vp8_vaapi_encoder_select="vaapi_encode" @@ -3078,16 +3149,20 @@ vp8_v4l2m2m_encoder_deps="v4l2_m2m vp8_v4l2_m2m" vp9_cuvid_decoder_deps="cuvid" vp9_mediacodec_decoder_deps="mediacodec" +vp9_qsv_decoder_select="qsvdec" vp9_rkmpp_decoder_deps="rkmpp" vp9_vaapi_encoder_deps="VAEncPictureParameterBufferVP9" vp9_vaapi_encoder_select="vaapi_encode" +vp9_qsv_encoder_deps="libmfx MFX_CODEC_VP9" +vp9_qsv_encoder_select="qsvenc" vp9_v4l2m2m_decoder_deps="v4l2_m2m vp9_v4l2_m2m" wmv3_crystalhd_decoder_select="crystalhd" +av1_qsv_decoder_select="qsvdec" # parsers aac_parser_select="adts_header" av1_parser_select="cbs_av1" -h264_parser_select="golomb h264dsp h264parse" +h264_parser_select="atsc_a53 golomb h264dsp h264parse" hevc_parser_select="hevcparse" mpegaudio_parser_select="mpegaudioheader" mpegvideo_parser_select="mpegvideo" @@ -3096,6 +3171,7 @@ # bitstream_filters aac_adtstoasc_bsf_select="adts_header" +av1_frame_merge_bsf_select="cbs_av1" av1_frame_split_bsf_select="cbs_av1" av1_metadata_bsf_select="cbs_av1" eac3_core_bsf_select="ac3_parser" @@ -3132,6 +3208,7 @@ mp3_at_decoder_select="mpegaudioheader" pcm_alaw_at_decoder_deps="audiotoolbox" pcm_mulaw_at_decoder_deps="audiotoolbox" +qdmc_decoder_select="fft" qdmc_at_decoder_deps="audiotoolbox" qdm2_at_decoder_deps="audiotoolbox" aac_at_encoder_deps="audiotoolbox" @@ -3146,9 +3223,9 @@ pcm_mulaw_at_encoder_select="audio_frame_queue" chromaprint_muxer_deps="chromaprint" h264_videotoolbox_encoder_deps="pthreads" -h264_videotoolbox_encoder_select="videotoolbox_encoder" +h264_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder" hevc_videotoolbox_encoder_deps="pthreads" -hevc_videotoolbox_encoder_select="videotoolbox_encoder" +hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder" libaom_av1_decoder_deps="libaom" libaom_av1_encoder_deps="libaom" libaom_av1_encoder_select="extract_extradata_bsf" @@ -3157,6 +3234,7 @@ libcodec2_decoder_deps="libcodec2" libcodec2_encoder_deps="libcodec2" libdav1d_decoder_deps="libdav1d" +libdav1d_decoder_select="atsc_a53" libdavs2_decoder_deps="libdavs2" libfdk_aac_decoder_deps="libfdk_aac" libfdk_aac_encoder_deps="libfdk_aac" @@ -3185,14 +3263,18 @@ libopus_decoder_deps="libopus" libopus_encoder_deps="libopus" libopus_encoder_select="audio_frame_queue" +librav1e_encoder_deps="librav1e" +librav1e_encoder_select="extract_extradata_bsf" librsvg_decoder_deps="librsvg" libshine_encoder_deps="libshine" libshine_encoder_select="audio_frame_queue" libspeex_decoder_deps="libspeex" libspeex_encoder_deps="libspeex" libspeex_encoder_select="audio_frame_queue" +libsvtav1_encoder_deps="libsvtav1" libtheora_encoder_deps="libtheora" libtwolame_encoder_deps="libtwolame" +libuavs3d_decoder_deps="libuavs3d" libvo_amrwbenc_encoder_deps="libvo_amrwbenc" libvorbis_decoder_deps="libvorbis" libvorbis_encoder_deps="libvorbis libvorbisenc" @@ -3201,12 +3283,11 @@ libvpx_vp8_encoder_deps="libvpx" libvpx_vp9_decoder_deps="libvpx" libvpx_vp9_encoder_deps="libvpx" -libwavpack_encoder_deps="libwavpack" -libwavpack_encoder_select="audio_frame_queue" libwebp_encoder_deps="libwebp" libwebp_anim_encoder_deps="libwebp" libx262_encoder_deps="libx262" libx264_encoder_deps="libx264" +libx264_encoder_select="atsc_a53" libx264rgb_encoder_deps="libx264 x264_csp_bgr" libx264rgb_encoder_select="libx264_encoder" libx265_encoder_deps="libx265" @@ -3221,14 +3302,16 @@ # demuxers / muxers ac3_demuxer_select="ac3_parser" +act_demuxer_select="riffdec" aiff_muxer_select="iso_media" asf_demuxer_select="riffdec" asf_o_demuxer_select="riffdec" asf_muxer_select="riffenc" asf_stream_muxer_select="asf_muxer" -avi_demuxer_select="iso_media riffdec exif" +av1_demuxer_select="av1_frame_merge_bsf av1_parser" +avi_demuxer_select="riffdec exif" avi_muxer_select="riffenc" -caf_demuxer_select="iso_media riffdec" +caf_demuxer_select="iso_media" caf_muxer_select="iso_media" dash_muxer_select="mp4_muxer" dash_demuxer_deps="libxml2" @@ -3242,6 +3325,8 @@ f4v_muxer_select="mov_muxer" fifo_muxer_deps="threads" flac_demuxer_select="flac_parser" +flv_muxer_select="aac_adtstoasc_bsf" +gxf_muxer_select="pcm_rechunk_bsf" hds_muxer_select="flv_muxer" hls_muxer_select="mpegts_muxer" hls_muxer_suggest="gcrypt openssl" @@ -3250,31 +3335,36 @@ 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" matroska_audio_muxer_select="matroska_muxer" -matroska_demuxer_select="iso_media riffdec" +matroska_demuxer_select="riffdec" matroska_demuxer_suggest="bzlib lzo zlib" -matroska_muxer_select="iso_media riffenc" +matroska_muxer_select="riffenc vp9_superframe_bsf aac_adtstoasc_bsf" +mlp_demuxer_select="mlp_parser" mmf_muxer_select="riffenc" mov_demuxer_select="iso_media riffdec" mov_demuxer_suggest="zlib" -mov_muxer_select="iso_media riffenc rtpenc_chain" +mov_muxer_select="iso_media riffenc rtpenc_chain vp9_superframe_bsf aac_adtstoasc_bsf" mp3_demuxer_select="mpegaudio_parser" mp3_muxer_select="mpegaudioheader" mp4_muxer_select="mov_muxer" mpegts_demuxer_select="iso_media" -mpegts_muxer_select="adts_muxer latm_muxer" +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_d10_muxer_select="mxf_muxer" mxf_opatom_muxer_select="mxf_muxer" nut_muxer_select="riffenc" nuv_demuxer_select="riffdec" +obu_demuxer_select="av1_frame_merge_bsf av1_parser" oga_muxer_select="ogg_muxer" ogg_demuxer_select="dirac_parse" ogv_muxer_select="ogg_muxer" opus_muxer_select="ogg_muxer" psp_muxer_select="mov_muxer" rtp_demuxer_select="sdp_demuxer" -rtp_muxer_select="golomb" +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" rtsp_demuxer_select="http_protocol rtpdec" rtsp_muxer_select="rtp_muxer http_protocol rtp_protocol rtpenc_chain" @@ -3287,6 +3377,7 @@ spx_muxer_select="ogg_muxer" swf_demuxer_suggest="zlib" tak_demuxer_select="tak_parser" +truehd_demuxer_select="mlp_parser" tg2_muxer_select="mov_muxer" tgp_muxer_select="mov_muxer" vobsub_demuxer_select="mpegps_demuxer" @@ -3294,7 +3385,8 @@ w64_muxer_select="wav_muxer" wav_demuxer_select="riffdec" wav_muxer_select="riffenc" -webm_muxer_select="iso_media 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" @@ -3309,6 +3401,8 @@ avfoundation_indev_deps="avfoundation corevideo coremedia pthreads" avfoundation_indev_suggest="coregraphics applicationservices" avfoundation_indev_extralibs="-framework Foundation" +audiotoolbox_outdev_deps="audiotoolbox pthreads" +audiotoolbox_outdev_extralibs="-framework AudioToolbox -framework CoreAudio" bktr_indev_deps_any="dev_bktr_ioctl_bt848_h machine_ioctl_bt848_h dev_video_bktr_ioctl_bt848_h dev_ic_bt8xx_h" caca_outdev_deps="libcaca" decklink_deps_any="libdl LoadLibrary" @@ -3359,7 +3453,8 @@ ffrtmphttp_protocol_conflict="librtmp_protocol" ffrtmphttp_protocol_select="http_protocol" ftp_protocol_select="tcp_protocol" -gopher_protocol_select="network" +gopher_protocol_select="tcp_protocol" +gophers_protocol_select="tls_protocol" http_protocol_select="tcp_protocol" http_protocol_suggest="zlib" httpproxy_protocol_select="tcp_protocol" @@ -3398,6 +3493,10 @@ unix_protocol_select="network" # external library protocols +libamqp_protocol_deps="librabbitmq" +libamqp_protocol_select="network" +librist_protocol_deps="librist" +librist_protocol_select="network" librtmp_protocol_deps="librtmp" librtmpe_protocol_deps="librtmp" librtmps_protocol_deps="librtmp" @@ -3408,6 +3507,8 @@ libsrt_protocol_select="network" libssh_protocol_deps="libssh" libtls_conflict="openssl gnutls mbedtls" +libzmq_protocol_deps="libzmq" +libzmq_protocol_select="network" # filters afftdn_filter_deps="avcodec" @@ -3415,14 +3516,16 @@ afftfilt_filter_deps="avcodec" afftfilt_filter_select="fft" afir_filter_deps="avcodec" -afir_filter_select="fft" +afir_filter_select="rdft" amovie_filter_deps="avcodec avformat" aresample_filter_deps="swresample" +asoftclip_filter_deps="swresample" asr_filter_deps="pocketsphinx" ass_filter_deps="libass" atempo_filter_deps="avcodec" atempo_filter_select="rdft" avgblur_opencl_filter_deps="opencl" +avgblur_vulkan_filter_deps="vulkan libglslang" azmq_filter_deps="libzmq" blackframe_filter_deps="gpl" bm3d_filter_deps="avcodec" @@ -3430,6 +3533,7 @@ boxblur_filter_deps="gpl" boxblur_opencl_filter_deps="opencl gpl" bs2b_filter_deps="libbs2b" +chromaber_vulkan_filter_deps="vulkan libglslang" colorkey_opencl_filter_deps="opencl" colormatrix_filter_deps="gpl" convolution_opencl_filter_deps="opencl" @@ -3449,7 +3553,9 @@ denoise_vaapi_filter_deps="vaapi" derain_filter_select="dnn" deshake_filter_select="pixelutils" +deshake_opencl_filter_deps="opencl" dilation_opencl_filter_deps="opencl" +dnn_processing_filter_select="dnn" drawtext_filter_deps="libfreetype" drawtext_filter_suggest="libfontconfig libfribidi" elbg_filter_deps="avcodec" @@ -3468,7 +3574,7 @@ frei0r_filter_deps="frei0r libdl" frei0r_src_filter_deps="frei0r libdl" fspp_filter_deps="gpl" -geq_filter_deps="gpl" +headphone_filter_select="fft" histeq_filter_deps="gpl" hqdn3d_filter_deps="gpl" interlace_filter_deps="gpl" @@ -3491,7 +3597,9 @@ overlay_opencl_filter_deps="opencl" overlay_qsv_filter_deps="libmfx" overlay_qsv_filter_select="qsvvpp" +overlay_vulkan_filter_deps="vulkan libglslang" owdenoise_filter_deps="gpl" +pad_opencl_filter_deps="opencl" pan_filter_deps="swresample" perspective_filter_deps="gpl" phase_filter_deps="gpl" @@ -3510,6 +3618,7 @@ scale2ref_filter_deps="swscale" scale_filter_deps="swscale" scale_qsv_filter_deps="libmfx" +scdet_filter_select="scene_sad" select_filter_select="scene_sad" sharpness_vaapi_filter_deps="vaapi" showcqt_filter_deps="avcodec avformat swscale" @@ -3517,11 +3626,13 @@ showcqt_filter_select="fft" showfreqs_filter_deps="avcodec" showfreqs_filter_select="fft" +showspatial_filter_select="fft" showspectrum_filter_deps="avcodec" showspectrum_filter_select="fft" showspectrumpic_filter_deps="avcodec" showspectrumpic_filter_select="fft" signature_filter_deps="gpl avcodec avformat" +sinc_filter_select="rdft" smartblur_filter_deps="gpl swscale" sobel_opencl_filter_deps="opencl" sofalizer_filter_deps="libmysofa avcodec" @@ -3536,10 +3647,13 @@ subtitles_filter_deps="avformat avcodec libass" super2xsai_filter_deps="gpl" pixfmts_super2xsai_test_deps="super2xsai_filter" +superequalizer_filter_select="rdft" +surround_filter_select="rdft" tinterlace_filter_deps="gpl" tinterlace_merge_test_deps="tinterlace_filter" tinterlace_pad_test_deps="tinterlace_filter" tonemap_filter_deps="const_nan" +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" @@ -3553,13 +3667,15 @@ zoompan_filter_deps="swscale" zscale_filter_deps="libzimg const_nan" scale_vaapi_filter_deps="vaapi" +scale_vulkan_filter_deps="vulkan libglslang" 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" # examples -avio_dir_cmd_deps="avformat avutil" +avio_list_dir_deps="avformat avutil" avio_reading_deps="avformat avcodec avutil" decode_audio_example_deps="avcodec avutil" decode_video_example_deps="avcodec avutil" @@ -3599,7 +3715,7 @@ avformat_suggest="libm network zlib" avresample_deps="avutil" avresample_suggest="libm" -avutil_suggest="clock_gettime ffnvcodec libm libdrm libmfx opencl user32 vaapi videotoolbox corefoundation corevideo coremedia bcrypt" +avutil_suggest="clock_gettime ffnvcodec libm libdrm libmfx opencl user32 vaapi vulkan videotoolbox corefoundation corevideo coremedia bcrypt" postproc_deps="avutil gpl" postproc_suggest="libm" swresample_deps="avutil" @@ -3688,6 +3804,7 @@ enable debug enable doc enable faan faandct faanidct +enable large_tests enable optimizations enable runtime_cpudetect enable safe_bitstream_reader @@ -4158,7 +4275,7 @@ ld_default="$source_path/compat/windows/mslink" nm_default="dumpbin.exe -symbols" ar_default="lib.exe" - case "$arch" in + case "${arch:-$arch_default}" in aarch64|arm64) as_default="armasm64.exe" ;; @@ -4363,7 +4480,7 @@ # generic catch all at the bottom will print the original flag. -Wall) ;; -Wextra) ;; - -std=c99) ;; + -std=c*) ;; # Common flags -fomit-frame-pointer) ;; -g) echo -Z7 ;; @@ -4379,6 +4496,7 @@ -l*) echo ${flag#-l}.lib ;; -LARGEADDRESSAWARE) echo $flag ;; -L*) echo -libpath:${flag#-L} ;; + -Wl,*) ;; *) echo $flag ;; esac done @@ -4606,7 +4724,11 @@ _ld_path='-libpath:' elif $_cc -nologo- 2>&1 | grep -q Microsoft || { $_cc -v 2>&1 | grep -q clang && $_cc -? > /dev/null 2>&1; }; then _type=msvc - _ident=$($_cc 2>&1 | head -n1 | tr -d '\r') + if $_cc -nologo- 2>&1 | grep -q Microsoft; then + _ident=$($_cc 2>&1 | head -n1 | tr -d '\r') + else + _ident=$($_cc --version 2>/dev/null | head -n1 | tr -d '\r') + fi _DEPCMD='$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>&1 | awk '\''/including/ { sub(/^.*file: */, ""); gsub(/\\/, "/"); if (!match($$0, / /)) print "$@:", $$0 }'\'' > $(@:.o=.d)' _DEPFLAGS='$(CPPFLAGS) $(CFLAGS) -showIncludes -Zs' _cflags_speed="-O2" @@ -4734,7 +4856,7 @@ if test "$cpu" = host; then enabled cross_compile && - die "--cpu=host makes no sense when cross-compiling." + warn "--cpu=host makes no sense when cross-compiling." case "$cc_type" in gcc|llvm_gcc) @@ -4917,8 +5039,6 @@ elif enabled mips; then - cpuflags="-march=$cpu" - if [ "$cpu" != "generic" ]; then disable mips32r2 disable mips32r5 @@ -4927,19 +5047,53 @@ disable mips64r6 disable loongson2 disable loongson3 + disable mipsdsp + disable mipsdspr2 + + cpuflags="-march=$cpu" case $cpu in - 24kc|24kf*|24kec|34kc|1004kc|24kef*|34kf*|1004kf*|74kc|74kf) + # General ISA levels + mips1|mips3) + ;; + mips32r2) enable mips32r2 - disable msa ;; - p5600|i6400|p6600) - disable mipsdsp - disable mipsdspr2 + mips32r5) + enable mips32r2 + enable mips32r5 ;; - loongson*) - enable loongson2 + mips64r2|mips64r5) + enable mips64r2 enable loongson3 + ;; + # Cores from MIPS(MTI) + 24kc) + disable mipsfpu + enable mips32r2 + ;; + 24kf*|24kec|34kc|74Kc|1004kc) + enable mips32r2 + ;; + 24kef*|34kf*|1004kf*) + enable mipsdsp + enable mips32r2 + ;; + p5600) + enable mips32r2 + enable mips32r5 + check_cflags "-mtune=p5600" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" + ;; + i6400) + enable mips64r6 + check_cflags "-mtune=i6400 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64" + ;; + p6600) + enable mips64r6 + check_cflags "-mtune=p6600 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64" + ;; + # Cores from Loongson + loongson2e|loongson2f|loongson3*) enable local_aligned enable simd_align_16 enable fast_64bit @@ -4947,75 +5101,42 @@ enable fast_cmov enable fast_unaligned disable aligned_stack - disable mipsdsp - disable mipsdspr2 # When gcc version less than 5.3.0, add -fno-expensive-optimizations flag. - if [ $cc == gcc ]; then - gcc_version=$(gcc -dumpversion) - if [ "$(echo "$gcc_version 5.3.0" | tr " " "\n" | sort -rV | head -n 1)" == "$gcc_version" ]; then - expensive_optimization_flag="" - else + if test "$cc_type" = "gcc"; then + case $gcc_basever in + 2|2.*|3.*|4.*|5.0|5.1|5.2) expensive_optimization_flag="-fno-expensive-optimizations" - fi + ;; + *) + expensive_optimization_flag="" + ;; + esac fi + case $cpu in loongson3*) + enable loongson3 cpuflags="-march=loongson3a -mhard-float $expensive_optimization_flag" ;; loongson2e) + enable loongson2 cpuflags="-march=loongson2e -mhard-float $expensive_optimization_flag" ;; loongson2f) + enable loongson2 cpuflags="-march=loongson2f -mhard-float $expensive_optimization_flag" ;; esac ;; *) - # Unknown CPU. Disable everything. - warn "unknown CPU. Disabling all MIPS optimizations." - disable mipsfpu - disable mipsdsp - disable mipsdspr2 - disable msa - disable mmi + warn "unknown MIPS CPU" ;; esac - case $cpu in - 24kc) - disable mipsfpu - disable mipsdsp - disable mipsdspr2 - ;; - 24kf*) - disable mipsdsp - disable mipsdspr2 - ;; - 24kec|34kc|1004kc) - disable mipsfpu - disable mipsdspr2 - ;; - 24kef*|34kf*|1004kf*) - disable mipsdspr2 - ;; - 74kc) - disable mipsfpu - ;; - p5600) - enable mips32r5 - check_cflags "-mtune=p5600" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" - ;; - i6400) - enable mips64r6 - check_cflags "-mtune=i6400 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64" - ;; - p6600) - enable mips64r6 - check_cflags "-mtune=p6600 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64" - ;; - esac else - # We do not disable anything. Is up to the user to disable the unwanted features. + disable mipsdsp + disable mipsdspr2 + # Disable DSP stuff for generic CPU, it can't be detected at runtime. warn 'generic cpu selected' fi @@ -5253,6 +5374,7 @@ ;; openbsd|bitrig) disable symver + enable section_data_rel_ro striptype="" SHFLAGS='-shared' SLIB_INSTALL_NAME='$(SLIBNAME).$(LIBMAJOR).$(LIBMINOR)' @@ -5291,6 +5413,11 @@ fi version_script='-exported_symbols_list' VERSION_SCRIPT_POSTPROCESS_CMD='tr " " "\n" | sed -n /global:/,/local:/p | grep ";" | tr ";" "\n" | sed -E "s/(.+)/_\1/g" | sed -E "s/(.+[^*])$$$$/\1*/"' + # Workaround for Xcode 11 -fstack-check bug + if enabled clang; then + clang_version=$($cc -dumpversion) + test ${clang_version%%.*} -eq 11 && add_cflags -fno-stack-check + fi ;; msys*) die "Native MSYS builds are discouraged, please use the MINGW environment." @@ -5756,28 +5883,42 @@ elif enabled mips; then - enabled loongson2 && check_inline_asm loongson2 '"dmult.g $8, $9, $10"' - enabled loongson3 && check_inline_asm loongson3 '"gsldxc1 $f0, 0($2, $3)"' - enabled mmi && check_inline_asm mmi '"punpcklhw $f0, $f0, $f0"' - - # Enable minimum ISA based on selected options + # Check toolchain ISA level if enabled mips64; then - enabled mips64r6 && check_inline_asm_flags mips64r6 '"dlsa $0, $0, $0, 1"' '-mips64r6' - enabled mips64r2 && check_inline_asm_flags mips64r2 '"dext $0, $0, 0, 1"' '-mips64r2' - disabled mips64r6 && disabled mips64r2 && check_inline_asm_flags mips64r1 '"daddi $0, $0, 0"' '-mips64' + enabled mips64r6 && check_inline_asm mips64r6 '"dlsa $0, $0, $0, 1"' && + disable mips64r2 + + enabled mips64r2 && check_inline_asm mips64r2 '"dext $0, $0, 0, 1"' + + disable mips32r6 && disable mips32r5 && disable mips32r2 else - enabled mips32r6 && check_inline_asm_flags mips32r6 '"aui $0, $0, 0"' '-mips32r6' - enabled mips32r5 && check_inline_asm_flags mips32r5 '"eretnc"' '-mips32r5' - enabled mips32r2 && check_inline_asm_flags mips32r2 '"ext $0, $0, 0, 1"' '-mips32r2' - disabled mips32r6 && disabled mips32r5 && disabled mips32r2 && check_inline_asm_flags mips32r1 '"addi $0, $0, 0"' '-mips32' + enabled mips32r6 && check_inline_asm mips32r6 '"aui $0, $0, 0"' && + disable mips32r5 && disable mips32r2 + + enabled mips32r5 && check_inline_asm mips32r5 '"eretnc"' + enabled mips32r2 && check_inline_asm mips32r2 '"ext $0, $0, 0, 1"' + + disable mips64r6 && disable mips64r5 && disable mips64r2 fi - enabled mipsfpu && check_inline_asm_flags mipsfpu '"cvt.d.l $f0, $f2"' '-mhard-float' + enabled mipsfpu && check_inline_asm mipsfpu '"cvt.d.l $f0, $f2"' enabled mipsfpu && (enabled mips32r5 || enabled mips32r6 || enabled mips64r6) && check_inline_asm_flags mipsfpu '"cvt.d.l $f0, $f1"' '-mfp64' - enabled mipsfpu && enabled msa && check_inline_asm_flags msa '"addvi.b $w0, $w1, 1"' '-mmsa' && check_headers msa.h || disable msa + enabled mipsdsp && check_inline_asm_flags mipsdsp '"addu.qb $t0, $t1, $t2"' '-mdsp' enabled mipsdspr2 && check_inline_asm_flags mipsdspr2 '"absq_s.qb $t0, $t1"' '-mdspr2' - enabled msa && enabled msa2 && check_inline_asm_flags msa2 '"nxbits.any.b $w0, $w0"' '-mmsa2' && check_headers msa2.h || disable msa2 + + # MSA and MSA2 can be detected at runtime so we supply extra flags here + enabled mipsfpu && enabled msa && check_inline_asm msa '"addvi.b $w0, $w1, 1"' '-mmsa' && append MSAFLAGS '-mmsa' + enabled msa && enabled msa2 && check_inline_asm msa2 '"nxbits.any.b $w0, $w0"' '-mmsa2' && append MSAFLAGS '-mmsa2' + + # loongson2 have no switch cflag so we can only probe toolchain ability + enabled loongson2 && check_inline_asm loongson2 '"dmult.g $8, $9, $10"' && disable loongson3 + + # loongson3 is paired with MMI + enabled loongson3 && check_inline_asm loongson3 '"gsldxc1 $f0, 0($2, $3)"' '-mloongson-ext' && append MMIFLAGS '-mloongson-ext' + + # MMI can be detected at runtime too + enabled mmi && check_inline_asm mmi '"punpcklhw $f0, $f0, $f0"' '-mloongson-mmi' && append MMIFLAGS '-mloongson-mmi' if enabled bigendian && enabled msa; then disable msa @@ -5883,10 +6024,10 @@ elf*) enabled debug && append X86ASMFLAGS $x86asm_debug ;; esac - check_x86asm avx512_external "vmovdqa32 [eax]{k1}{z}, zmm0" - check_x86asm avx2_external "vextracti128 xmm0, ymm0, 0" - check_x86asm xop_external "vpmacsdd xmm0, xmm1, xmm2, xmm3" - check_x86asm fma4_external "vfmaddps ymm0, ymm1, ymm2, ymm3" + enabled avx512 && check_x86asm avx512_external "vmovdqa32 [eax]{k1}{z}, zmm0" + enabled avx2 && check_x86asm avx2_external "vextracti128 xmm0, ymm0, 0" + enabled xop && check_x86asm xop_external "vpmacsdd xmm0, xmm1, xmm2, xmm3" + enabled fma4 && check_x86asm fma4_external "vfmaddps ymm0, ymm1, ymm2, ymm3" check_x86asm cpunop "CPU amdnop" fi @@ -5996,14 +6137,17 @@ check_func_headers stdlib.h getenv check_func_headers sys/stat.h lstat +check_func_headers windows.h GetModuleHandle check_func_headers windows.h GetProcessAffinityMask check_func_headers windows.h GetProcessTimes +check_func_headers windows.h GetStdHandle check_func_headers windows.h GetSystemTimeAsFileTime check_func_headers windows.h LoadLibrary check_func_headers windows.h MapViewOfFile check_func_headers windows.h PeekNamedPipe check_func_headers windows.h SetConsoleTextAttribute check_func_headers windows.h SetConsoleCtrlHandler +check_func_headers windows.h SetDllDirectory check_func_headers windows.h Sleep check_func_headers windows.h VirtualAlloc check_func_headers glob.h glob @@ -6016,9 +6160,13 @@ check_headers dxva.h check_headers dxva2api.h -D_WIN32_WINNT=0x0600 check_headers io.h +enabled libdrm && + check_headers linux/dma-buf.h + check_headers linux/perf_event.h check_headers libcrystalhd/libcrystalhd_if.h check_headers malloc.h +check_headers mftransform.h check_headers net/udplite.h check_headers poll.h check_headers sys/param.h @@ -6059,6 +6207,7 @@ check_apple_framework CoreFoundation check_apple_framework CoreMedia check_apple_framework CoreVideo +check_apple_framework CoreAudio enabled avfoundation && { disable coregraphics applicationservices @@ -6068,18 +6217,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 CoreVideo/CVPixelBuffer.h kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange "-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_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 check_type "windows.h dxva.h" "DXVA_PicParams_HEVC" -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -D_CRT_BUILD_DESKTOP_APP=0 check_type "windows.h dxva.h" "DXVA_PicParams_VP9" -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -D_CRT_BUILD_DESKTOP_APP=0 check_type "windows.h d3d11.h" "ID3D11VideoDecoder" check_type "windows.h d3d11.h" "ID3D11VideoContext" check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602 +check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC" +check_type "vdpau/vdpau.h" "VdpPictureInfoVP9" if [ -z "$nvccflags" ]; then nvccflags=$nvccflags_default @@ -6094,16 +6250,16 @@ if enabled cuda_nvcc; then nvccflags="$nvccflags -ptx" else - nvccflags="$nvccflags -S -nocudalib -nocudainc --cuda-device-only -include ${source_link}/compat/cuda/cuda_runtime.h" + nvccflags="$nvccflags -S -nocudalib -nocudainc --cuda-device-only -Wno-c++11-narrowing -include ${source_link}/compat/cuda/cuda_runtime.h" check_nvcc cuda_llvm fi if ! disabled ffnvcodec; then ffnv_hdr_list="ffnvcodec/nvEncodeAPI.h ffnvcodec/dynlink_cuda.h ffnvcodec/dynlink_cuviddec.h ffnvcodec/dynlink_nvcuvid.h" - check_pkg_config ffnvcodec "ffnvcodec >= 9.0.18.0" "$ffnv_hdr_list" "" || \ - check_pkg_config ffnvcodec "ffnvcodec >= 8.2.15.8 ffnvcodec < 8.3" "$ffnv_hdr_list" "" || \ - check_pkg_config ffnvcodec "ffnvcodec >= 8.1.24.9 ffnvcodec < 8.2" "$ffnv_hdr_list" "" || \ - check_pkg_config ffnvcodec "ffnvcodec >= 8.0.14.9 ffnvcodec < 8.1" "$ffnv_hdr_list" "" + check_pkg_config ffnvcodec "ffnvcodec >= 9.1.23.1" "$ffnv_hdr_list" "" || \ + check_pkg_config ffnvcodec "ffnvcodec >= 9.0.18.3 ffnvcodec < 9.1" "$ffnv_hdr_list" "" || \ + check_pkg_config ffnvcodec "ffnvcodec >= 8.2.15.10 ffnvcodec < 8.3" "$ffnv_hdr_list" "" || \ + check_pkg_config ffnvcodec "ffnvcodec >= 8.1.24.11 ffnvcodec < 8.2" "$ffnv_hdr_list" "" fi check_cpp_condition winrt windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)" @@ -6173,10 +6329,11 @@ done # these are off by default, so fail if requested and not available +enabled avisynth && require_headers "avisynth/avisynth_c.h" enabled cuda_nvcc && { check_nvcc cuda_nvcc || die "ERROR: failed checking for nvcc."; } enabled chromaprint && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint enabled decklink && { require_headers DeckLinkAPI.h && - { test_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a090500" || die "ERROR: Decklink API version must be >= 10.9.5."; } } + { test_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a0a0000" || die "ERROR: Decklink API version must be >= 10.10"; } } enabled frei0r && require_headers "frei0r.h dlfcn.h" enabled gmp && require gmp gmp.h mpz_export -lgmp enabled gnutls && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init @@ -6196,7 +6353,7 @@ die "ERROR: libcelt must be installed and version must be >= 0.11.0."; } enabled libcaca && require_pkg_config libcaca caca caca.h caca_create_canvas enabled libcodec2 && require libcodec2 codec2/codec2.h codec2_create -lcodec2 -enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.2.1" "dav1d/dav1d.h" dav1d_version +enabled libdav1d && require_pkg_config libdav1d "dav1d >= 0.5.0" "dav1d/dav1d.h" dav1d_version enabled libdavs2 && require_pkg_config libdavs2 "davs2 >= 1.6.0" davs2.h davs2_decoder_open enabled libdc1394 && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new enabled libdrm && require_pkg_config libdrm libdrm xf86drm.h drmGetVersion @@ -6209,6 +6366,7 @@ 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 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 @@ -6226,10 +6384,14 @@ # can find the libraries and headers through other means. enabled libmfx && { check_pkg_config libmfx libmfx "mfx/mfxvideo.h" MFXInit || { require libmfx "mfx/mfxvideo.h" MFXInit "-llibmfx $advapi32_extralibs" && warn "using libmfx without pkg-config"; } } +if enabled libmfx; then + check_cc MFX_CODEC_VP9 "mfx/mfxvp9.h mfx/mfxstructures.h" "MFX_CODEC_VP9" +fi + enabled libmodplug && require_pkg_config libmodplug libmodplug libmodplug/modplug.h ModPlug_Load enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame $libm_extralibs -enabled libmysofa && { check_pkg_config libmysofa libmysofa mysofa.h mysofa_load || - require libmysofa mysofa.h mysofa_load -lmysofa $zlib_extralibs; } +enabled libmysofa && { check_pkg_config libmysofa libmysofa mysofa.h mysofa_neighborhood_init_withstepdefine || + require libmysofa mysofa.h mysofa_neighborhood_init_withstepdefine -lmysofa $zlib_extralibs; } enabled libnpp && { check_lib libnpp npp.h nppGetLibVersion -lnppig -lnppicc -lnppc -lnppidei || check_lib libnpp npp.h nppGetLibVersion -lnppi -lnppc -lnppidei || die "ERROR: libnpp not found"; } @@ -6243,6 +6405,7 @@ enabled libopenjpeg && { check_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version || { require_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } } enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create -lstdc++ && append libopenmpt_extralibs "-lstdc++" +enabled libopenvino && require libopenvino c_api/ie_c_api.h ie_c_api_version -linference_engine_c_api enabled libopus && { enabled libopus_decoder && { require_pkg_config libopus opus opus_multistream.h opus_multistream_decoder_create @@ -6252,6 +6415,9 @@ } } enabled libpulse && require_pkg_config libpulse libpulse pulse/pulseaudio.h pa_context_new +enabled librabbitmq && require_pkg_config librabbitmq "librabbitmq >= 0.7.1" amqp.h amqp_new_connection +enabled librav1e && require_pkg_config librav1e "rav1e >= 0.4.0" rav1e.h rav1e_context_new +enabled librist && require_pkg_config librist "librist >= 0.2" librist/librist.h rist_receiver_create enabled 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++" @@ -6263,6 +6429,7 @@ enabled libssh && require_pkg_config libssh libssh libssh/sftp.h sftp_init enabled libspeex && require_pkg_config libspeex speex speex/speex.h speex_decoder_init enabled libsrt && require_pkg_config libsrt "srt >= 1.3.0" srt/srt.h srt_socket +enabled libsvtav1 && require_pkg_config libsvtav1 "SvtAv1Enc >= 0.8.4" EbSvtAv1Enc.h svt_av1_enc_init_handle enabled libtensorflow && require libtensorflow tensorflow/c/c_api.h TF_Version -ltensorflow enabled libtesseract && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg @@ -6270,9 +6437,10 @@ enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame && { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame || die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; } +enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode enabled libv4l2 && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit -enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.3.9" libvmaf.h compute_vmaf +enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 1.5.2" libvmaf.h compute_vmaf enabled libvo_amrwbenc && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc enabled libvorbis && require_pkg_config libvorbis vorbis vorbis/codec.h vorbis_info_init && require_pkg_config libvorbisenc vorbisenc vorbis/vorbisenc.h vorbis_encode_init @@ -6299,7 +6467,6 @@ fi } -enabled libwavpack && require libwavpack wavpack/wavpack.h WavpackOpenFileOutput -lwavpack enabled libwebp && { enabled libwebp_encoder && require_pkg_config libwebp "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion enabled libwebp_anim_encoder && check_pkg_config libwebp_anim_encoder "libwebpmux >= 0.4.0" webp/mux.h WebPAnimEncoderOptionsInit; } @@ -6309,12 +6476,12 @@ require_cpp_condition libx264 x264.h "X264_BUILD >= 118" && check_cpp_condition libx262 x264.h "X264_MPEG2" enabled libx265 && require_pkg_config libx265 x265 x265.h x265_api_get && - require_cpp_condition libx265 x265.h "X265_BUILD >= 68" + require_cpp_condition libx265 x265.h "X265_BUILD >= 70" enabled libxavs && require libxavs "stdint.h xavs.h" xavs_encoder_encode "-lxavs $pthreads_extralibs $libm_extralibs" enabled libxavs2 && require_pkg_config libxavs2 "xavs2 >= 1.3.0" "stdint.h xavs2.h" xavs2_api_get enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore enabled libzimg && require_pkg_config libzimg "zimg >= 2.7.0" zimg.h zimg_get_api_version -enabled libzmq && require_pkg_config libzmq libzmq zmq.h zmq_ctx_new +enabled libzmq && require_pkg_config libzmq "libzmq >= 4.2.1" zmq.h zmq_ctx_new enabled libzvbi && require_pkg_config libzvbi zvbi-0.2 libzvbi.h vbi_decoder_new && { test_cpp_condition libzvbi.h "VBI_VERSION_MAJOR > 0 || VBI_VERSION_MINOR > 2 || VBI_VERSION_MINOR == 2 && VBI_VERSION_MICRO >= 28" || enabled gpl || die "ERROR: libzvbi requires version 0.2.28 or --enable-gpl."; } @@ -6349,12 +6516,16 @@ check_lib opengl ES2/gl.h glGetError "-isysroot=${sysroot} -Wl,-framework,OpenGLES" || die "ERROR: opengl not found." } +enabled omx_rpi && { test_code cc OMX_Core.h OMX_IndexConfigBrcmVideoRequestIFrame || + { ! enabled cross_compile && + add_cflags -isystem/opt/vc/include/IL && + test_code cc OMX_Core.h OMX_IndexConfigBrcmVideoRequestIFrame; } || + die "ERROR: OpenMAX IL headers from raspberrypi/firmware not found"; } && + enable omx enabled omx && require_headers OMX_Core.h -enabled omx_rpi && { check_headers OMX_Core.h || - { ! enabled cross_compile && add_cflags -isystem/opt/vc/include/IL && check_headers OMX_Core.h ; } || - die "ERROR: OpenMAX IL headers not found"; } && enable omx enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OPENSSL_init_ssl || check_pkg_config openssl openssl openssl/ssl.h SSL_library_init || + check_lib openssl openssl/ssl.h OPENSSL_init_ssl -lssl -lcrypto || check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto || check_lib openssl openssl/ssl.h SSL_library_init -lssl32 -leay32 || check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 || @@ -6430,19 +6601,21 @@ rsync --help 2> /dev/null | grep -q 'contimeout' && enable rsync_contimeout || disable rsync_contimeout # check V4L2 codecs available in the API -check_headers linux/fb.h -check_headers linux/videodev2.h -test_code cc linux/videodev2.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete -check_cc v4l2_m2m linux/videodev2.h "int i = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_VIDEO_M2M | V4L2_BUF_FLAG_LAST;" -check_cc vc1_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VC1_ANNEX_G;" -check_cc mpeg1_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG1;" -check_cc mpeg2_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2;" -check_cc mpeg4_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG4;" -check_cc hevc_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC;" -check_cc h263_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_H263;" -check_cc h264_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_H264;" -check_cc vp8_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP8;" -check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;" +if enabled v4l2_m2m; then + check_headers linux/fb.h + check_headers linux/videodev2.h + test_code cc linux/videodev2.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete + check_cc v4l2_m2m linux/videodev2.h "int i = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_VIDEO_M2M | V4L2_BUF_FLAG_LAST;" + check_cc vc1_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VC1_ANNEX_G;" + check_cc mpeg1_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG1;" + check_cc mpeg2_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG2;" + check_cc mpeg4_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_MPEG4;" + check_cc hevc_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_HEVC;" + check_cc h263_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_H263;" + check_cc h264_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_H264;" + check_cc vp8_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP8;" + check_cc vp9_v4l2_m2m linux/videodev2.h "int i = V4L2_PIX_FMT_VP9;" +fi check_headers sys/videoio.h test_code cc sys/videoio.h "struct v4l2_frmsizeenum vfse; vfse.discrete.width = 0;" && enable_sanitized struct_v4l2_frmivalenum_discrete @@ -6470,8 +6643,8 @@ EOF fi -enabled alsa && check_pkg_config alsa alsa "alsa/asoundlib.h" snd_pcm_htimestamp || - check_lib alsa alsa/asoundlib.h snd_pcm_htimestamp -lasound +enabled alsa && { check_pkg_config alsa alsa "alsa/asoundlib.h" snd_pcm_htimestamp || + check_lib alsa alsa/asoundlib.h snd_pcm_htimestamp -lasound; } enabled libjack && require_pkg_config libjack jack jack/jack.h jack_port_get_latency_range @@ -6512,6 +6685,9 @@ #endif EOF +enabled libdrm && + check_pkg_config libdrm_getfb2 libdrm "xf86drmMode.h" drmModeGetFB2 + enabled vaapi && check_pkg_config vaapi "libva >= 0.35.0" "va/va.h" vaInitialize @@ -6526,6 +6702,8 @@ check_type "va/va.h va/va_dec_hevc.h" "VAPictureParameterBufferHEVC" check_struct "va/va.h" "VADecPictureParameterBufferVP9" bit_depth + check_struct "va/va.h" "VADecPictureParameterBufferAV1" bit_depth_idx + check_type "va/va.h va/va_vpp.h" "VAProcFilterParameterBufferHDRToneMapping" check_struct "va/va.h va/va_vpp.h" "VAProcPipelineCaps" rotation_flags check_type "va/va.h va/va_enc_hevc.h" "VAEncPictureParameterBufferHEVC" check_type "va/va.h va/va_enc_jpeg.h" "VAEncPictureParameterBufferJPEG" @@ -6567,6 +6745,9 @@ enabled crystalhd && check_lib crystalhd "stdint.h libcrystalhd/libcrystalhd_if.h" DtsCrystalHDVersion -lcrystalhd +enabled vulkan && + require_pkg_config vulkan "vulkan >= 1.1.97" "vulkan/vulkan.h" vkCreateInstance + if enabled x86; then case $target_os in mingw32*|mingw64*|win32|win64|linux|cygwin*) @@ -6575,7 +6756,7 @@ disable ffnvcodec cuvid nvdec nvenc ;; esac -elif enabled ppc64 && ! enabled bigendian; then +elif enabled_any aarch64 ppc64 && ! enabled bigendian; then case $target_os in linux) ;; @@ -6597,9 +6778,13 @@ int main(void) { return 0; } EOF +if enabled_any nvdec cuvid; then + check_type "ffnvcodec/dynlink_cuda.h ffnvcodec/dynlink_cuviddec.h" "CUVIDAV1PICPARAMS" +fi + enabled amf && check_cpp_condition amf "AMF/core/Version.h" \ - "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400040001" + "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400090000" # Funny iconv installations are not unusual, so check it after all flags have been set if enabled libc_iconv; then @@ -7324,6 +7509,8 @@ SHFLAGS=$(echo $($ldflags_filter $SHFLAGS)) ASMSTRIPFLAGS=$ASMSTRIPFLAGS X86ASMFLAGS=$X86ASMFLAGS +MSAFLAGS=$MSAFLAGS +MMIFLAGS=$MMIFLAGS BUILDSUF=$build_suffix PROGSSUF=$progs_suffix FULLNAME=$FULLNAME @@ -7397,10 +7584,11 @@ #define FFMPEG_CONFIG_H #define FFMPEG_CONFIGURATION "$(c_escape $FFMPEG_CONFIGURATION)" #define FFMPEG_LICENSE "$(c_escape $license)" -#define CONFIG_THIS_YEAR 2019 +#define CONFIG_THIS_YEAR 2021 #define FFMPEG_DATADIR "$(eval c_escape $datadir)" #define AVCONV_DATADIR "$(eval c_escape $datadir)" #define CC_IDENT "$(c_escape ${cc_ident:-Unknown compiler})" +#define OS_NAME $target_os #define av_restrict $restrict_keyword #define EXTERN_PREFIX "${extern_prefix}" #define EXTERN_ASM ${extern_prefix} diff -Nru ffmpeg-4.2.2/debian/changelog ffmpeg-4.4/debian/changelog --- ffmpeg-4.2.2/debian/changelog 2020-03-07 08:39:35.000000000 +0000 +++ ffmpeg-4.4/debian/changelog 2021-05-25 10:09:41.000000000 +0000 @@ -1,84 +1,68 @@ -ffmpeg (7:4.2.2-1ubuntu1) focal; urgency=medium +ffmpeg (7:4.4-1ppa1) focal; urgency=high - * Build with external nv-codec-headers for NVENC accelerated video - encoding. (LP: #1810649) - - debian/control: - + Add B-D libffmpeg-nvenc-dev - - debian/rules: - + Add --enable-nvenc for amd64 only + * Update to 4.4. + * Add VMAF support. + * Add SVT-AV1 support. + * Only enable dav1d in amd64. + * Only enable avisynth+ in amd64. + * Only enable fdk-aac in amd64. + * Remove pocketsphinx. + * Set pocketsphinx BDs. + * Disable pocketsphinx at some platform. + * Set libpocketsphinx-dev BDs. + * Set opencl-dev BDs. + * Set libsrt-gnutls-dev BDs. + * Set librabbitmq-dev BDs. + * Set libmfx-dev BDs. + * Set lib{dav1d,zimg}-dev BDs. + * switch from AvxSynth to AviSynth+. + * libwavpack was removed. + + -- Hung-Yi Chen Tue, 25 May 2021 18:09:41 +0800 - -- Martin Wimpress Sat, 07 Mar 2020 08:39:35 +0000 +ffmpeg (7:4.3.1-1ppa1) focal; urgency=high -ffmpeg (7:4.2.2-1build1) focal; urgency=medium + * Update to 4.3.1. + + -- Hung-Yi Chen Tue, 11 Aug 2020 02:55:01 +0800 - * No-change rebuild for libmysofa soname change. +ffmpeg (7:4.2.1-1ppa1) focal; urgency=high - -- Matthias Klose Thu, 13 Feb 2020 02:12:37 +0100 + * Update to 4.2.1. + + -- Hung-Yi Chen Wed, 18 Sep 2019 03:13:53 +0800 -ffmpeg (7:4.2.2-1) unstable; urgency=medium +ffmpeg (7:4.2-2) focal; urgency=high - [ James Cowgill ] - * New upstream release. + * Update to 4.2. + + -- Hung-Yi Chen Wed, 18 Sep 2019 00:47:22 +0800 + +ffmpeg (7:4.1.4-5) focal; urgency=high - * d/control: - - Change lib*-extra packages to arch any. - - Tighten dependencies from libav*-extra packages. - - Bump standards version to 4.5.0. - * d/rules: Enable opencl (Closes: #944005) + * Build with --enable-hardcoded-tables. - [ Steve Langasek ] - * d/tests: Make autopkgtests cross-test-friendly. (Closes: #946241) + -- Hung-Yi Chen Tue, 17 Sep 2019 23:26:30 +0800 - -- James Cowgill Sat, 25 Jan 2020 16:22:32 +0000 +ffmpeg (7:4.1.4-4) focal; urgency=high -ffmpeg (7:4.2.1-2) unstable; urgency=medium + * Enable AAC audio encoding via Fraunhofer FDK. + * Allow use of nonfree code. - * d/patches: - - avcodec/libtwolame: fix mono default bitrate. (Closes: #943900) - * d/tests: - - Replace remaining occurrences of ADTTMP. + -- Hung-Yi Chen Tue, 17 Sep 2019 17:22:57 +0800 - -- James Cowgill Sat, 02 Nov 2019 01:17:31 +0000 -ffmpeg (7:4.2.1-1) unstable; urgency=medium +ffmpeg (7:4.1.4-3) focal; urgency=high - * New upstream release. - - avcodec/vqavideo: Set video size. (CVE-2019-17542) - - avcodec/utils: Check close before calling it. (CVE-2019-17539) + * Update to 4.1.4. - * d/copyright: Various copyright updates for 4.2. - * d/patches: Add patch to fix sbcenc segfault on armhf. - * d/rules: - - Enable libartbb24. - - Disable MSA2. - - Update list of non-enabled libraries. - * d/*.symbols: Updates for 4.2. - * d/tests: Update encdec lists with 4.2 additions. + -- Hung-Yi Chen Mon, 12 Aug 2019 23:10:31 +0800 - -- James Cowgill Mon, 28 Oct 2019 18:14:56 +0000 +ffmpeg (7:4.1.3-1) focal; urgency=high -ffmpeg (7:4.1.4-1) unstable; urgency=medium + * Backport from Eoan. - [ James Cowgill ] - * New upstream release. (LP: #1837480) - - avformat/aadec: Check for scanf() failure (CVE-2019-12730) - (Closes: #932469) - - * d/copyright: Remove paragraph containing license files. - * d/control: Bump standards version to 4.4.0. - * d/ffmpeg-doc.doc-base*: - - Move API docs to Programming/C section. - - Index the main manual pages as well. - Thanks to 積丹尼 Dan Jacobson for the suggestion. (Closes: #924528) - * d/rules: - - Disable crystalhd. (Closes: #917292) - - Generate index.html file for the HTML manual pages. - - [ Ondřej Nový ] - * d/control: - - Use debhelper-compat instead of debian/compat. - - -- James Cowgill Sat, 27 Jul 2019 11:24:18 +0100 + -- Hung-Yi Chen Tue, 18 Jun 2019 03:07:45 +0800 ffmpeg (7:4.1.3-1) unstable; urgency=high diff -Nru ffmpeg-4.2.2/debian/control ffmpeg-4.4/debian/control --- ffmpeg-4.2.2/debian/control 2020-01-29 09:14:32.000000000 +0000 +++ ffmpeg-4.4/debian/control 2021-05-25 10:09:41.000000000 +0000 @@ -1,13 +1,7 @@ Source: ffmpeg Section: video Priority: optional -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Debian Multimedia Maintainers -Uploaders: Andreas Cadhalpun , - Alexander Strasser , - Reinhard Tartler , - Balint Reczey , - James Cowgill +Maintainer: Hung-Yi Chen Rules-Requires-Root: no Homepage: https://ffmpeg.org/ Standards-Version: 4.5.0 @@ -24,7 +18,7 @@ tree, Build-Depends: # needed for dh - debhelper-compat (= 11), + debhelper-compat (= 12), # for build-profile support dpkg-dev (>= 1.17.14), # --enable-libflite @@ -41,6 +35,8 @@ libass-dev, # --enable-libbluray libbluray-dev, +# TODO: drop when declared by libfreetype-dev (see bug#964185) + libbrotli-dev, # --enable-libbs2b libbs2b-dev, # autodetected: external library 'bzlib' @@ -53,12 +49,14 @@ libchromaprint-dev , # --enable-libcodec2 libcodec2-dev, +# autodetected 'crystalhd' + libcrystalhd-dev [amd64 i386], +# --enable-libdav1d + libdav1d-dev [!i386], # --enable-libdc1394 libdc1394-22-dev [linux-any], # --enable-libdrm libdrm-dev [linux-any], -# --enable-nvenc - libffmpeg-nvenc-dev, # --enable-libfontconfig libfontconfig1-dev, # --enable-libfreetype @@ -85,6 +83,8 @@ liblilv-dev, # autodetected for the tiff decoder liblzma-dev, +# --enable-libmfx + libmfx-dev [amd64], # --enable-libmp3lame libmp3lame-dev, # --enable-libmysofa @@ -105,6 +105,8 @@ libopus-dev, # --enable-libpulse libpulse-dev, +# --enable-librabbitmq + librabbitmq-dev, # --enable-librubberband librubberband-dev, # --enable-librsvg @@ -121,6 +123,8 @@ libsoxr-dev, # --enable-libspeex libspeex-dev, +# --enable-libsrt + libsrt-gnutls-dev, # --enable-libssh libssh-gcrypt-dev, # --enable-libtesseract (used only in -extra flavor) @@ -144,8 +148,6 @@ libvorbis-dev, # --enable-libvpx libvpx-dev, -# --enable-libwavpack - libwavpack-dev, # --enable-libwebp libwebp-dev, # --enable-libx264 @@ -166,11 +168,14 @@ libxvidcore-dev, # autodetected: decoder 'mpeg_xvmc'; outdev 'xv' libxvmc-dev, +# --enable-libzimg + libzimg-dev [!i386], # --enable-libzmq libzmq3-dev, # --enable-libzvbi libzvbi-dev, -# --enable-opencl +# The opencl API is considered experimental. +# # --enable-opencl ocl-icd-opencl-dev | opencl-dev, # used to detect libraries pkg-config, @@ -178,8 +183,11 @@ texinfo, # assembler optimizations nasm, + pkg-kde-tools, # autodetected zlib - zlib1g-dev + zlib1g-dev, + libfdk-aac-dev [!i386], avisynth+-dev [!i386], avisynth+ [!i386], + libsvtav1-dev [amd64], libvmaf-dev [amd64] Package: ffmpeg Architecture: any @@ -254,7 +262,9 @@ Section: libs Multi-Arch: same Conflicts: libavcodec58 -Provides: libavcodec58 (= ${binary:Version}) +Provides: + libavcodec58 (= ${binary:Version}), + libavcodec-extra Pre-Depends: ${misc:Pre-Depends} Depends: @@ -277,7 +287,6 @@ This package replaces the libavcodec58 package and contains the following additional codecs: . - * ARIB STD-B24 Captions (Subtitle Decoder) * OpenCORE Adaptive Multi-Rate (AMR) Narrow-Band (Encoder/Decoder) * OpenCORE Adaptive Multi-Rate (AMR) Wide-Band (Decoder) * Android VisualOn Adaptive Multi-Rate (AMR) Wide-Band (Encoder) @@ -287,11 +296,11 @@ GPL version 3 or later. Package: libavcodec-extra -Architecture: any +Architecture: all Section: metapackages -Multi-Arch: same +Multi-Arch: foreign Depends: - libavcodec-extra58 (= ${binary:Version}), + libavcodec-extra58, ${misc:Depends} Description: FFmpeg library with extra codecs (metapackage) FFmpeg is the leading multimedia framework, able to decode, encode, transcode, @@ -401,7 +410,9 @@ Section: libs Multi-Arch: same Conflicts: libavfilter7 -Provides: libavfilter7 (= ${binary:Version}) +Provides: + libavfilter7 (= ${binary:Version}), + libavfilter-extra Pre-Depends: ${misc:Pre-Depends} Depends: @@ -428,11 +439,11 @@ GPL version 3 or later. Package: libavfilter-extra -Architecture: any +Architecture: all Section: metapackages -Multi-Arch: same +Multi-Arch: foreign Depends: - libavfilter-extra7 (= ${binary:Version}), + libavfilter-extra7, ${misc:Depends} Description: FFmpeg library with extra filters (metapackage) FFmpeg is the leading multimedia framework, able to decode, encode, transcode, diff -Nru ffmpeg-4.2.2/debian/copyright ffmpeg-4.4/debian/copyright --- ffmpeg-4.2.2/debian/copyright 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/copyright 2021-05-25 10:09:41.000000000 +0000 @@ -178,7 +178,7 @@ 2007-2015, Collabora Ltd 2007-2015, Edward Hervey 2007-2016, David Robillard - 2007-2016, Nicolas George + 2007-2016,2020, Nicolas George 2007-2018, Ronald S. Bultje 2008, Affine Systems, Inc (Michael Sullivan, Bobby Impollonia) 2008, Alessandro Sappia @@ -225,7 +225,7 @@ 2009-2015, James Darnley 2009-2016, Thilo Borgmann 2009-2018, Kostya Shishkov - 2009-2019, Martin Storsjo + 2009-2020, Martin Storsjo 2010, Adrian Daerr 2010, Amanda, Y.N. Wu 2010, Andrzej Szombierski @@ -279,10 +279,10 @@ 2011-2012, Michael Bradshaw 2011-2012, Smartjog S.A.S, Clément Bœsch 2011-2013, Daniel Kang - 2011-2015, Derek Buitenhuis + 2011-2015,2019, Derek Buitenhuis 2011-2016, Kieran Kunhya 2011-2018, Clément Bœsch - 2011-2019, Paul B Mahol + 2011-2020, Paul B Mahol 2012, Aleksi Nurmi 2012, Andrew D'Addesio 2012, Antti Seppälä @@ -298,6 +298,7 @@ 2012, Samuel Pitoiset 2012, Sebastien Zwickert 2012, Steven Robertson + 2012, Youness Alaoui 2012, Vitaliy E Sugrobov 2012-2013, Andrey Utkin 2012-2013, Aneesh Dogra (lionaneesh) @@ -340,7 +341,7 @@ 2013-2016, Vittorio Giovara 2013-2018, Andreas Unterweger 2013-2018, Calvin Walton - 2013-2018, Marton Balint + 2013-2018,2020, Marton Balint 2014, Aman Gupta 2014, Daniel Oberhoff 2014, Dave Rice @dericed @@ -396,7 +397,7 @@ 2015-2017, Matthieu Bouron 2015-2017, Rostislav Pehlivanov 2015-2018, Henrik Gramner - 2015-2018, Loongson Technology Corporation Limited + 2015-2019, Loongson Technology Corporation Limited 2015-2019, Rodger Combs 2016, Davinder Singh (DSM_) 2016, Floris Sluiter @@ -412,6 +413,7 @@ 2016, William Ma, Sofia Kim, Dustin Woo 2016, foo86 2016-2018, Jokyo Images + 2016-2019, Jai Luthra 2017, Felix Matouschek 2017, Maksym Veremeyenko 2017, Meng Wang @@ -435,19 +437,24 @@ 2018, Yingming Fan 2018, Yiqun Xu 2018-2019, Shiyou Yin + 2019, Eugene Lyapustin 2019, Guo Yejun + 2019, Leo Zhang 2019, Lynne + 2019, Manoj Gupta Bonda 2019, Swaraj Hota + 2019, Vladimir Panteleev 2019, Xuewei Meng + 2019-2020, Andriy Gelman + 2020, Alyssa Milburn + 2020, David Bryant + 2020, Gautam Ramakrishnan + 2020, Jun Zhao + 2020, Vacing Fang + 2020, Yaroslav Pogrebnyak + 2020, Zane van Iperen (zane@zanevaniperen.com) License: LGPL-2.1+ Comment: - You should have received a copy of the GNU Lesser General Public - License along with FFmpeg; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - . - On Debian systems, the full text of the GNU Lesser General Public License - version 2.1 can be found in the file `/usr/share/common-licenses/LGPL-2.1'. - . The copyright details for Joseph Artsimovich and UAB "DKD" were extracted from the referenced source: . @@ -461,13 +468,6 @@ 2011, Mina Nagy Zaki 2015, Paul B Mahol License: LGPL-2.1+ and Sundry -Comment: - On Debian systems, the full text of the GNU Lesser General Public License - version 2.1 can be found in the file `/usr/share/common-licenses/LGPL-2.1'. - . - You should have received a copy of the GNU Lesser General Public - License along with FFmpeg; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Files: doc/texi2pod.pl @@ -487,7 +487,6 @@ libavfilter/vf_find_rect.c libavfilter/vf_fspp.c libavfilter/vf_fspp.h - libavfilter/vf_geq.c libavfilter/vf_histeq.c libavfilter/vf_hqdn3d.c libavfilter/vf_hqdn3d.h @@ -515,7 +514,8 @@ libavfilter/vf_uspp.c libavfilter/vf_vaguedenoiser.c libavfilter/vsrc_mptestsrc.c - libavfilter/x86/vf_eq.c + libavfilter/x86/vf_eq.asm + libavfilter/x86/vf_eq_init.c libavfilter/x86/vf_fspp.asm libavfilter/x86/vf_fspp_init.c libavfilter/x86/vf_hqdn3d_init.c @@ -555,12 +555,15 @@ tests/checkasm/hevc_idct.c tests/checkasm/jpeg2000dsp.c tests/checkasm/llviddsp.c + tests/checkasm/opusdsp.c tests/checkasm/pixblockdsp.c tests/checkasm/sbrdsp.c + tests/checkasm/sw_scale.c tests/checkasm/synth_filter.c tests/checkasm/v210dec.c tests/checkasm/v210enc.c tests/checkasm/vf_blend.c + tests/checkasm/vf_eq.c tests/checkasm/videodsp.c tests/checkasm/vp8dsp.c tests/checkasm/vp9dsp.c @@ -610,7 +613,7 @@ 2015-2016, Tiancheng "Timothy" Gu 2015-2017, James Almer 2017, Gerion Entrup -License: GPL-2+ +License-Grant: 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 @@ -620,53 +623,7 @@ 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. -Comment: - On Debian systems, the full text of the GNU General Public License - version 2 can be found in the file `/usr/share/common-licenses/GPL-2'. - . - 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 - -Files: - compat/avisynth/avisynth_c.h - compat/avisynth/avs/capi.h - compat/avisynth/avs/config.h - compat/avisynth/avs/types.h - compat/avisynth/avxsynth_c.h -Copyright: 2003, Kevin Atkinson -License: GPL-2+ with Avisynth exception - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - . - This program is distributed in the hope that 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. - . - As a special exception, I give you permission to link to the - Avisynth C interface with independent modules that communicate with - the Avisynth C interface solely through the interfaces defined in - avisynth_c.h, regardless of the license terms of these independent - modules, and to copy and distribute the resulting combined work - under terms of your choice, provided that every copy of the - combined work is accompanied by a complete copy of the source code - of the Avisynth C interface and Avisynth itself (with the version - used to produce the combined work), being distributed under the - terms of the GNU General Public License plus this exception. An - independent module is a module which is not derived from or based - on Avisynth C Interface, such as 3rd-party filters, import and - export plugins, or graphical user interfaces. -Comment: - On Debian systems, the full text of the GNU General Public License - version 2 can be found in the file `/usr/share/common-licenses/GPL-2'. - . - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA, - or visit . +License: GPL-2+ Files: compat/solaris/make_sunver.pl @@ -678,7 +635,7 @@ 2014, Andreas Cadhalpun 2014, Tiancheng "Timothy" Gu 2018, Stephen Seo -License: GPL-3+ +License-Grant: 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 3 of the License, or @@ -688,18 +645,12 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -Comment: - On Debian systems, the full text of the GNU General Public License - version 3 can be found in the file `/usr/share/common-licenses/GPL-3'. - . - 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 +License: GPL-3+ Files: compat/cuda/ptx2c.sh doc/bootstrap.min.css - doc/examples/avio_dir_cmd.c + doc/examples/avio_list_dir.c doc/examples/avio_reading.c doc/examples/decode_audio.c doc/examples/decode_video.c @@ -732,6 +683,7 @@ libavcodec/x86/vc1dsp_mmx.c libavfilter/af_deesser.c libavfilter/vf_avgblur.c + libavfilter/vf_bilateral.c libavfilter/vf_bm3d.c libavfilter/vf_deband.c libavfilter/vf_scale_cuda.c @@ -784,8 +736,9 @@ 2015, Niklas Haas 2015, Stephan Holljes 2015, Vittorio Giovara - 2015-2018, Paul B Mahol + 2015-2019, Paul B Mahol 2015-2016, mawen1250 + 2017, Ming Yang 2018, Chris Johnson License: Expat @@ -823,29 +776,27 @@ libavcodec/mips/mpegaudiodsp_mips_fixed.c libavcodec/mips/mpegaudiodsp_mips_float.c libavcodec/mips/sbrdsp_mips.c + libavfilter/opencl/deshake.cl + libavfilter/vf_deshake_opencl.c libavutil/fixed_dsp.c libavutil/fixed_dsp.h libavutil/mips/float_dsp_mips.c libavutil/mips/libm_mips.h libavutil/softfloat_tables.h Copyright: + 2000-2008, Intel Corporation 2005-2006, Oded Shimon 2006-2007, Maxim Gavrilov 2008-2009, Robert Swain + 2009, Willow Garage Inc. 2009-2010, Alex Converse 2010, Google Inc 2010, Rob Clark 2011, Mans Rullgard 2012-2013, MIPS Technologies, Inc., California 2013, The WebRTC project authors + 2013, OpenCV Foundation License: LGPL-2.1+ and BSD-3-clause -Comment: - On Debian systems, the full text of the GNU Lesser General Public License - version 2.1 can be found in the file `/usr/share/common-licenses/LGPL-2.1'. - . - You should have received a copy of the GNU Lesser General Public - License along with FFmpeg; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Files: tools/cws2fws.c @@ -973,11 +924,18 @@ License: LGPL-2.1+ and Expat Files: + libavfilter/af_arnndn.c libavfilter/gblur.h libavfilter/vf_gblur.c Copyright: + 2005-2009 Xiph.Org Foundation + 2007-2008 CSIRO + 2008-2011 Octasic Inc. 2011, Pascal Getreuer - 2016, Paul B Mahol + 2016,2019, Paul B Mahol + 2017 Mozilla + 2018 Gregor Richards + Jean-Marc Valin License: BSD-2-clause Files: libavformat/aadec.c @@ -1007,7 +965,7 @@ Copyright: 2005-2012, Wolfram Gloger 2013, Marton Balint -License: LGPL-2+ +License-Grant: This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -1017,13 +975,7 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -Comment: - On Debian systems, the full text of the GNU Lesser General Public License - version 2 can be found in the file `/usr/share/common-licenses/GPL-2'. - . - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +License: LGPL-2+ Files: libswresample/resample.c Copyright: @@ -1036,14 +988,14 @@ 2014-2017, Andreas Cadhalpun 2016, Sebastian Ramacher 2017-2018, James Cowgill + 2020, Jonas Smedegaard + 2021, Hung-Yi Chen License: LGPL-2.1+ -Comment: - On Debian systems, the full text of the GNU Lesser General Public License - version 2.1 can be found in the file `/usr/share/common-licenses/LGPL-2.1'. - . - You should have received a copy of the GNU Lesser General Public - License along with this packaging; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Files: debian/copyright-check +Copyright: + 2016-2020, Jonas Smedegaard +License: GPL-3+ Files: debian/missing-sources/ffmpeg-web/src/less/style.less Copyright: 2014, Barbara Lepage @@ -1148,16 +1100,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +License: GPL-2+ +License-Reference: /usr/share/common-licenses/GPL-2 + +License: GPL-3+ +License-Reference: /usr/share/common-licenses/GPL-3 + +License: LGPL-2+ +License-Reference: /usr/share/common-licenses/LGPL-2 + License: LGPL-2.1+ - FFmpeg is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - . - FFmpeg is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. +License-Reference: /usr/share/common-licenses/LGPL-2.1 License: Sundry This source code is freely redistributable and may be used for diff -Nru ffmpeg-4.2.2/debian/gbp.conf ffmpeg-4.4/debian/gbp.conf --- ffmpeg-4.2.2/debian/gbp.conf 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/gbp.conf 2021-05-25 10:09:12.000000000 +0000 @@ -1,4 +1,4 @@ [DEFAULT] pristine-tar = True -debian-branch = debian/master +debian-branch = debian/buster upstream-branch = upstream/latest diff -Nru ffmpeg-4.2.2/debian/libavcodec58.symbols ffmpeg-4.4/debian/libavcodec58.symbols --- ffmpeg-4.2.2/debian/libavcodec58.symbols 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/libavcodec58.symbols 2021-05-25 10:09:41.000000000 +0000 @@ -1,6 +1,8 @@ +# SymbolsHelper-Confirmed: 7:4.2 amd64 libavcodec.so.58 libavcodec58 #MINVER# * Build-Depends-Package: libavcodec-dev LIBAVCODEC_58@LIBAVCODEC_58 7:4.0 + (optional|regex)^avpriv_ 0 av_ac3_parse_header@LIBAVCODEC_58 7:4.0 av_adts_header_parse@LIBAVCODEC_58 7:4.0 av_alloc_vdpaucontext@LIBAVCODEC_58 7:4.0 @@ -151,6 +153,7 @@ avcodec_default_execute2@LIBAVCODEC_58 7:4.0 avcodec_default_execute@LIBAVCODEC_58 7:4.0 avcodec_default_get_buffer2@LIBAVCODEC_58 7:4.0 + avcodec_default_get_encode_buffer@LIBAVCODEC_58 7:4.4 avcodec_default_get_format@LIBAVCODEC_58 7:4.0 avcodec_descriptor_get@LIBAVCODEC_58 7:4.0 avcodec_descriptor_get_by_name@LIBAVCODEC_58 7:4.0 @@ -203,6 +206,3 @@ avpicture_get_size@LIBAVCODEC_58 7:4.0 avpicture_layout@LIBAVCODEC_58 7:4.0 avsubtitle_free@LIBAVCODEC_58 7:4.0 -# Symbols starting with avpriv_ are not public and other packages must not use -# them. Intra-library ABI is ensured by manual dependencies in d/control. - (optional|regex)^avpriv_ 0 diff -Nru ffmpeg-4.2.2/debian/libavcodec-extra58.symbols ffmpeg-4.4/debian/libavcodec-extra58.symbols --- ffmpeg-4.2.2/debian/libavcodec-extra58.symbols 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/libavcodec-extra58.symbols 1970-01-01 00:00:00.000000000 +0000 @@ -1,208 +0,0 @@ -libavcodec.so.58 libavcodec58 #MINVER# -* Build-Depends-Package: libavcodec-dev - LIBAVCODEC_58@LIBAVCODEC_58 7:4.0 - av_ac3_parse_header@LIBAVCODEC_58 7:4.0 - av_adts_header_parse@LIBAVCODEC_58 7:4.0 - av_alloc_vdpaucontext@LIBAVCODEC_58 7:4.0 - av_bitstream_filter_close@LIBAVCODEC_58 7:4.0 - av_bitstream_filter_filter@LIBAVCODEC_58 7:4.0 - av_bitstream_filter_init@LIBAVCODEC_58 7:4.0 - av_bitstream_filter_next@LIBAVCODEC_58 7:4.0 - av_bsf_alloc@LIBAVCODEC_58 7:4.0 - av_bsf_flush@LIBAVCODEC_58 7:4.1 - av_bsf_free@LIBAVCODEC_58 7:4.0 - av_bsf_get_by_name@LIBAVCODEC_58 7:4.0 - av_bsf_get_class@LIBAVCODEC_58 7:4.0 - av_bsf_get_null_filter@LIBAVCODEC_58 7:4.0 - av_bsf_init@LIBAVCODEC_58 7:4.0 - av_bsf_iterate@LIBAVCODEC_58 7:4.0 - av_bsf_list_alloc@LIBAVCODEC_58 7:4.0 - av_bsf_list_append2@LIBAVCODEC_58 7:4.0 - av_bsf_list_append@LIBAVCODEC_58 7:4.0 - av_bsf_list_finalize@LIBAVCODEC_58 7:4.0 - av_bsf_list_free@LIBAVCODEC_58 7:4.0 - av_bsf_list_parse_str@LIBAVCODEC_58 7:4.0 - av_bsf_next@LIBAVCODEC_58 7:4.0 - av_bsf_receive_packet@LIBAVCODEC_58 7:4.0 - av_bsf_send_packet@LIBAVCODEC_58 7:4.0 - av_codec_ffversion@LIBAVCODEC_58 7:4.0 - av_codec_get_chroma_intra_matrix@LIBAVCODEC_58 7:4.0 - av_codec_get_codec_descriptor@LIBAVCODEC_58 7:4.0 - av_codec_get_codec_properties@LIBAVCODEC_58 7:4.0 - av_codec_get_lowres@LIBAVCODEC_58 7:4.0 - av_codec_get_max_lowres@LIBAVCODEC_58 7:4.0 - av_codec_get_pkt_timebase@LIBAVCODEC_58 7:4.0 - av_codec_get_seek_preroll@LIBAVCODEC_58 7:4.0 - av_codec_is_decoder@LIBAVCODEC_58 7:4.0 - av_codec_is_encoder@LIBAVCODEC_58 7:4.0 - av_codec_iterate@LIBAVCODEC_58 7:4.0 - av_codec_next@LIBAVCODEC_58 7:4.0 - av_codec_set_chroma_intra_matrix@LIBAVCODEC_58 7:4.0 - av_codec_set_codec_descriptor@LIBAVCODEC_58 7:4.0 - av_codec_set_lowres@LIBAVCODEC_58 7:4.0 - av_codec_set_pkt_timebase@LIBAVCODEC_58 7:4.0 - av_codec_set_seek_preroll@LIBAVCODEC_58 7:4.0 - av_copy_packet@LIBAVCODEC_58 7:4.0 - av_copy_packet_side_data@LIBAVCODEC_58 7:4.0 - av_cpb_properties_alloc@LIBAVCODEC_58 7:4.0 - av_d3d11va_alloc_context@LIBAVCODEC_58 7:4.0 - av_dct_calc@LIBAVCODEC_58 7:4.0 - av_dct_end@LIBAVCODEC_58 7:4.0 - av_dct_init@LIBAVCODEC_58 7:4.0 - av_dirac_parse_sequence_header@LIBAVCODEC_58 7:4.0 - av_dup_packet@LIBAVCODEC_58 7:4.0 - av_dv_codec_profile2@LIBAVCODEC_58 7:4.0 - av_dv_codec_profile@LIBAVCODEC_58 7:4.0 - av_dv_frame_profile@LIBAVCODEC_58 7:4.0 - av_fast_padded_malloc@LIBAVCODEC_58 7:4.0 - av_fast_padded_mallocz@LIBAVCODEC_58 7:4.0 - av_fft_calc@LIBAVCODEC_58 7:4.0 - av_fft_end@LIBAVCODEC_58 7:4.0 - av_fft_init@LIBAVCODEC_58 7:4.0 - av_fft_permute@LIBAVCODEC_58 7:4.0 - av_free_packet@LIBAVCODEC_58 7:4.0 - av_get_audio_frame_duration2@LIBAVCODEC_58 7:4.0 - av_get_audio_frame_duration@LIBAVCODEC_58 7:4.0 - av_get_bits_per_sample@LIBAVCODEC_58 7:4.0 - av_get_codec_tag_string@LIBAVCODEC_58 7:4.0 - av_get_exact_bits_per_sample@LIBAVCODEC_58 7:4.0 - av_get_pcm_codec@LIBAVCODEC_58 7:4.0 - av_get_profile_name@LIBAVCODEC_58 7:4.0 - av_grow_packet@LIBAVCODEC_58 7:4.0 - av_hwaccel_next@LIBAVCODEC_58 7:4.0 - av_imdct_calc@LIBAVCODEC_58 7:4.0 - av_imdct_half@LIBAVCODEC_58 7:4.0 - av_init_packet@LIBAVCODEC_58 7:4.0 - av_jni_get_java_vm@LIBAVCODEC_58 7:4.0 - av_jni_set_java_vm@LIBAVCODEC_58 7:4.0 - av_lockmgr_register@LIBAVCODEC_58 7:4.0 - av_mdct_calc@LIBAVCODEC_58 7:4.0 - av_mdct_end@LIBAVCODEC_58 7:4.0 - av_mdct_init@LIBAVCODEC_58 7:4.0 - av_mediacodec_alloc_context@LIBAVCODEC_58 7:4.0 - av_mediacodec_default_free@LIBAVCODEC_58 7:4.0 - av_mediacodec_default_init@LIBAVCODEC_58 7:4.0 - av_mediacodec_release_buffer@LIBAVCODEC_58 7:4.0 - av_mediacodec_render_buffer_at_time@LIBAVCODEC_58 7:4.1 - av_new_packet@LIBAVCODEC_58 7:4.0 - av_packet_add_side_data@LIBAVCODEC_58 7:4.0 - av_packet_alloc@LIBAVCODEC_58 7:4.0 - av_packet_clone@LIBAVCODEC_58 7:4.0 - av_packet_copy_props@LIBAVCODEC_58 7:4.0 - av_packet_free@LIBAVCODEC_58 7:4.0 - av_packet_free_side_data@LIBAVCODEC_58 7:4.0 - av_packet_from_data@LIBAVCODEC_58 7:4.0 - av_packet_get_side_data@LIBAVCODEC_58 7:4.0 - av_packet_make_refcounted@LIBAVCODEC_58 7:4.0 - av_packet_make_writable@LIBAVCODEC_58 7:4.0 - av_packet_merge_side_data@LIBAVCODEC_58 7:4.0 - av_packet_move_ref@LIBAVCODEC_58 7:4.0 - av_packet_new_side_data@LIBAVCODEC_58 7:4.0 - av_packet_pack_dictionary@LIBAVCODEC_58 7:4.0 - av_packet_ref@LIBAVCODEC_58 7:4.0 - av_packet_rescale_ts@LIBAVCODEC_58 7:4.0 - av_packet_shrink_side_data@LIBAVCODEC_58 7:4.0 - av_packet_side_data_name@LIBAVCODEC_58 7:4.0 - av_packet_split_side_data@LIBAVCODEC_58 7:4.0 - av_packet_unpack_dictionary@LIBAVCODEC_58 7:4.0 - av_packet_unref@LIBAVCODEC_58 7:4.0 - av_parser_change@LIBAVCODEC_58 7:4.0 - av_parser_close@LIBAVCODEC_58 7:4.0 - av_parser_init@LIBAVCODEC_58 7:4.0 - av_parser_iterate@LIBAVCODEC_58 7:4.0 - av_parser_next@LIBAVCODEC_58 7:4.0 - av_parser_parse2@LIBAVCODEC_58 7:4.0 - av_picture_copy@LIBAVCODEC_58 7:4.0 - av_picture_crop@LIBAVCODEC_58 7:4.0 - av_picture_pad@LIBAVCODEC_58 7:4.0 - av_qsv_alloc_context@LIBAVCODEC_58 7:4.0 - av_rdft_calc@LIBAVCODEC_58 7:4.0 - av_rdft_end@LIBAVCODEC_58 7:4.0 - av_rdft_init@LIBAVCODEC_58 7:4.0 - av_register_bitstream_filter@LIBAVCODEC_58 7:4.0 - av_register_codec_parser@LIBAVCODEC_58 7:4.0 - av_register_hwaccel@LIBAVCODEC_58 7:4.0 - av_shrink_packet@LIBAVCODEC_58 7:4.0 - av_vdpau_alloc_context@LIBAVCODEC_58 7:4.0 - av_vdpau_bind_context@LIBAVCODEC_58 7:4.0 - av_vdpau_get_profile@LIBAVCODEC_58 7:4.0 - av_vdpau_get_surface_parameters@LIBAVCODEC_58 7:4.0 - av_vdpau_hwaccel_get_render2@LIBAVCODEC_58 7:4.0 - av_vdpau_hwaccel_set_render2@LIBAVCODEC_58 7:4.0 - av_vorbis_parse_frame@LIBAVCODEC_58 7:4.0 - av_vorbis_parse_frame_flags@LIBAVCODEC_58 7:4.0 - av_vorbis_parse_free@LIBAVCODEC_58 7:4.0 - av_vorbis_parse_init@LIBAVCODEC_58 7:4.0 - av_vorbis_parse_reset@LIBAVCODEC_58 7:4.0 - av_xiphlacing@LIBAVCODEC_58 7:4.0 - avcodec_align_dimensions2@LIBAVCODEC_58 7:4.0 - avcodec_align_dimensions@LIBAVCODEC_58 7:4.0 - avcodec_alloc_context3@LIBAVCODEC_58 7:4.2 - avcodec_chroma_pos_to_enum@LIBAVCODEC_58 7:4.0 - avcodec_close@LIBAVCODEC_58 7:4.0 - avcodec_configuration@LIBAVCODEC_58 7:4.0 - avcodec_copy_context@LIBAVCODEC_58 7:4.0 - avcodec_dct_alloc@LIBAVCODEC_58 7:4.0 - avcodec_dct_get_class@LIBAVCODEC_58 7:4.0 - avcodec_dct_init@LIBAVCODEC_58 7:4.0 - avcodec_decode_audio4@LIBAVCODEC_58 7:4.0 - avcodec_decode_subtitle2@LIBAVCODEC_58 7:4.0 - avcodec_decode_video2@LIBAVCODEC_58 7:4.0 - avcodec_default_execute2@LIBAVCODEC_58 7:4.0 - avcodec_default_execute@LIBAVCODEC_58 7:4.0 - avcodec_default_get_buffer2@LIBAVCODEC_58 7:4.0 - avcodec_default_get_format@LIBAVCODEC_58 7:4.0 - avcodec_descriptor_get@LIBAVCODEC_58 7:4.0 - avcodec_descriptor_get_by_name@LIBAVCODEC_58 7:4.0 - avcodec_descriptor_next@LIBAVCODEC_58 7:4.0 - avcodec_encode_audio2@LIBAVCODEC_58 7:4.0 - avcodec_encode_subtitle@LIBAVCODEC_58 7:4.0 - avcodec_encode_video2@LIBAVCODEC_58 7:4.0 - avcodec_enum_to_chroma_pos@LIBAVCODEC_58 7:4.0 - avcodec_fill_audio_frame@LIBAVCODEC_58 7:4.0 - avcodec_find_best_pix_fmt2@LIBAVCODEC_58 7:4.0 - avcodec_find_best_pix_fmt_of_2@LIBAVCODEC_58 7:4.0 - avcodec_find_best_pix_fmt_of_list@LIBAVCODEC_58 7:4.0 - avcodec_find_decoder@LIBAVCODEC_58 7:4.0 - avcodec_find_decoder_by_name@LIBAVCODEC_58 7:4.0 - avcodec_find_encoder@LIBAVCODEC_58 7:4.0 - avcodec_find_encoder_by_name@LIBAVCODEC_58 7:4.0 - avcodec_flush_buffers@LIBAVCODEC_58 7:4.0 - avcodec_free_context@LIBAVCODEC_58 7:4.0 - avcodec_get_chroma_sub_sample@LIBAVCODEC_58 7:4.0 - avcodec_get_class@LIBAVCODEC_58 7:4.0 - avcodec_get_context_defaults3@LIBAVCODEC_58 7:4.0 - avcodec_get_frame_class@LIBAVCODEC_58 7:4.0 - avcodec_get_hw_config@LIBAVCODEC_58 7:4.0 - avcodec_get_hw_frames_parameters@LIBAVCODEC_58 7:4.0 - avcodec_get_name@LIBAVCODEC_58 7:4.0 - avcodec_get_pix_fmt_loss@LIBAVCODEC_58 7:4.0 - avcodec_get_subtitle_rect_class@LIBAVCODEC_58 7:4.0 - avcodec_get_type@LIBAVCODEC_58 7:4.0 - avcodec_is_open@LIBAVCODEC_58 7:4.0 - avcodec_license@LIBAVCODEC_58 7:4.0 - avcodec_open2@LIBAVCODEC_58 7:4.0 - avcodec_parameters_alloc@LIBAVCODEC_58 7:4.0 - avcodec_parameters_copy@LIBAVCODEC_58 7:4.0 - avcodec_parameters_free@LIBAVCODEC_58 7:4.0 - avcodec_parameters_from_context@LIBAVCODEC_58 7:4.0 - avcodec_parameters_to_context@LIBAVCODEC_58 7:4.0 - avcodec_pix_fmt_to_codec_tag@LIBAVCODEC_58 7:4.0 - avcodec_profile_name@LIBAVCODEC_58 7:4.0 - avcodec_receive_frame@LIBAVCODEC_58 7:4.2 - avcodec_receive_packet@LIBAVCODEC_58 7:4.0 - avcodec_register@LIBAVCODEC_58 7:4.0 - avcodec_register_all@LIBAVCODEC_58 7:4.0 - avcodec_send_frame@LIBAVCODEC_58 7:4.0 - avcodec_send_packet@LIBAVCODEC_58 7:4.0 - avcodec_string@LIBAVCODEC_58 7:4.0 - avcodec_version@LIBAVCODEC_58 7:4.0 - avpicture_alloc@LIBAVCODEC_58 7:4.0 - avpicture_fill@LIBAVCODEC_58 7:4.0 - avpicture_free@LIBAVCODEC_58 7:4.0 - avpicture_get_size@LIBAVCODEC_58 7:4.0 - avpicture_layout@LIBAVCODEC_58 7:4.0 - avsubtitle_free@LIBAVCODEC_58 7:4.0 -# Symbols starting with avpriv_ are not public and other packages must not use -# them. Intra-library ABI is ensured by manual dependencies in d/control. - (optional|regex)^avpriv_ 0 diff -Nru ffmpeg-4.2.2/debian/libavfilter7.symbols ffmpeg-4.4/debian/libavfilter7.symbols --- ffmpeg-4.2.2/debian/libavfilter7.symbols 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/libavfilter7.symbols 2021-05-25 10:09:13.000000000 +0000 @@ -1,3 +1,4 @@ +# SymbolsHelper-Confirmed: 7:4.3 amd64 libavfilter.so.7 libavfilter7 #MINVER# * Build-Depends-Package: libavfilter-dev LIBAVFILTER_7@LIBAVFILTER_7 7:4.0 @@ -28,13 +29,11 @@ av_filter_ffversion@LIBAVFILTER_7 7:4.0 av_filter_iterate@LIBAVFILTER_7 7:4.0 avfilter_add_matrix@LIBAVFILTER_7 7:4.0 - avfilter_all_channel_layouts@LIBAVFILTER_7 7:4.0 avfilter_config_links@LIBAVFILTER_7 7:4.0 avfilter_configuration@LIBAVFILTER_7 7:4.0 avfilter_free@LIBAVFILTER_7 7:4.0 avfilter_get_by_name@LIBAVFILTER_7 7:4.0 avfilter_get_class@LIBAVFILTER_7 7:4.0 - avfilter_get_matrix@LIBAVFILTER_7 7:4.0 avfilter_graph_alloc@LIBAVFILTER_7 7:4.0 avfilter_graph_alloc_filter@LIBAVFILTER_7 7:4.0 avfilter_graph_config@LIBAVFILTER_7 7:4.0 diff -Nru ffmpeg-4.2.2/debian/libavfilter-extra7.symbols ffmpeg-4.4/debian/libavfilter-extra7.symbols --- ffmpeg-4.2.2/debian/libavfilter-extra7.symbols 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/libavfilter-extra7.symbols 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -libavfilter.so.7 libavfilter7 #MINVER# -* Build-Depends-Package: libavfilter-dev - LIBAVFILTER_7@LIBAVFILTER_7 7:4.0 - av_abuffersink_params_alloc@LIBAVFILTER_7 7:4.0 - av_buffersink_get_channel_layout@LIBAVFILTER_7 7:4.0 - av_buffersink_get_channels@LIBAVFILTER_7 7:4.0 - av_buffersink_get_format@LIBAVFILTER_7 7:4.0 - av_buffersink_get_frame@LIBAVFILTER_7 7:4.0 - av_buffersink_get_frame_flags@LIBAVFILTER_7 7:4.0 - av_buffersink_get_frame_rate@LIBAVFILTER_7 7:4.0 - av_buffersink_get_h@LIBAVFILTER_7 7:4.0 - av_buffersink_get_hw_frames_ctx@LIBAVFILTER_7 7:4.0 - av_buffersink_get_sample_aspect_ratio@LIBAVFILTER_7 7:4.0 - av_buffersink_get_sample_rate@LIBAVFILTER_7 7:4.0 - av_buffersink_get_samples@LIBAVFILTER_7 7:4.0 - av_buffersink_get_time_base@LIBAVFILTER_7 7:4.0 - av_buffersink_get_type@LIBAVFILTER_7 7:4.0 - av_buffersink_get_w@LIBAVFILTER_7 7:4.0 - av_buffersink_params_alloc@LIBAVFILTER_7 7:4.0 - av_buffersink_set_frame_size@LIBAVFILTER_7 7:4.0 - av_buffersrc_add_frame@LIBAVFILTER_7 7:4.0 - av_buffersrc_add_frame_flags@LIBAVFILTER_7 7:4.0 - av_buffersrc_close@LIBAVFILTER_7 7:4.0 - av_buffersrc_get_nb_failed_requests@LIBAVFILTER_7 7:4.0 - av_buffersrc_parameters_alloc@LIBAVFILTER_7 7:4.0 - av_buffersrc_parameters_set@LIBAVFILTER_7 7:4.0 - av_buffersrc_write_frame@LIBAVFILTER_7 7:4.0 - av_filter_ffversion@LIBAVFILTER_7 7:4.0 - av_filter_iterate@LIBAVFILTER_7 7:4.0 - avfilter_add_matrix@LIBAVFILTER_7 7:4.0 - avfilter_all_channel_layouts@LIBAVFILTER_7 7:4.0 - avfilter_config_links@LIBAVFILTER_7 7:4.0 - avfilter_configuration@LIBAVFILTER_7 7:4.0 - avfilter_free@LIBAVFILTER_7 7:4.0 - avfilter_get_by_name@LIBAVFILTER_7 7:4.0 - avfilter_get_class@LIBAVFILTER_7 7:4.0 - avfilter_get_matrix@LIBAVFILTER_7 7:4.0 - avfilter_graph_alloc@LIBAVFILTER_7 7:4.0 - avfilter_graph_alloc_filter@LIBAVFILTER_7 7:4.0 - avfilter_graph_config@LIBAVFILTER_7 7:4.0 - avfilter_graph_create_filter@LIBAVFILTER_7 7:4.0 - avfilter_graph_dump@LIBAVFILTER_7 7:4.0 - avfilter_graph_free@LIBAVFILTER_7 7:4.0 - avfilter_graph_get_filter@LIBAVFILTER_7 7:4.0 - avfilter_graph_parse2@LIBAVFILTER_7 7:4.0 - avfilter_graph_parse@LIBAVFILTER_7 7:4.0 - avfilter_graph_parse_ptr@LIBAVFILTER_7 7:4.0 - avfilter_graph_queue_command@LIBAVFILTER_7 7:4.0 - avfilter_graph_request_oldest@LIBAVFILTER_7 7:4.0 - avfilter_graph_send_command@LIBAVFILTER_7 7:4.0 - avfilter_graph_set_auto_convert@LIBAVFILTER_7 7:4.0 - avfilter_init_dict@LIBAVFILTER_7 7:4.0 - avfilter_init_str@LIBAVFILTER_7 7:4.0 - avfilter_inout_alloc@LIBAVFILTER_7 7:4.0 - avfilter_inout_free@LIBAVFILTER_7 7:4.0 - avfilter_insert_filter@LIBAVFILTER_7 7:4.0 - avfilter_license@LIBAVFILTER_7 7:4.0 - avfilter_link@LIBAVFILTER_7 7:4.0 - avfilter_link_free@LIBAVFILTER_7 7:4.0 - avfilter_link_get_channels@LIBAVFILTER_7 7:4.0 - avfilter_link_set_closed@LIBAVFILTER_7 7:4.0 - avfilter_make_format64_list@LIBAVFILTER_7 7:4.0 - avfilter_mul_matrix@LIBAVFILTER_7 7:4.0 - avfilter_next@LIBAVFILTER_7 7:4.0 - avfilter_pad_count@LIBAVFILTER_7 7:4.0 - avfilter_pad_get_name@LIBAVFILTER_7 7:4.0 - avfilter_pad_get_type@LIBAVFILTER_7 7:4.0 - avfilter_process_command@LIBAVFILTER_7 7:4.0 - avfilter_register@LIBAVFILTER_7 7:4.0 - avfilter_register_all@LIBAVFILTER_7 7:4.0 - avfilter_sub_matrix@LIBAVFILTER_7 7:4.0 - avfilter_transform@LIBAVFILTER_7 7:4.0 - avfilter_version@LIBAVFILTER_7 7:4.0 diff -Nru ffmpeg-4.2.2/debian/libavformat58.symbols ffmpeg-4.4/debian/libavformat58.symbols --- ffmpeg-4.2.2/debian/libavformat58.symbols 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/libavformat58.symbols 2021-05-25 10:09:13.000000000 +0000 @@ -1,6 +1,8 @@ +# SymbolsHelper-Confirmed: 7:4.3 amd64 libavformat.so.58 libavformat58 #MINVER# * Build-Depends-Package: libavformat-dev LIBAVFORMAT_58@LIBAVFORMAT_58 7:4.0 + (optional|regex)^avpriv_ 0 av_add_index_entry@LIBAVFORMAT_58 7:4.0 av_append_packet@LIBAVFORMAT_58 7:4.0 av_apply_bitstream_filters@LIBAVFORMAT_58 7:4.0 @@ -132,7 +134,9 @@ avio_open_dir@LIBAVFORMAT_58 7:4.0 avio_open_dyn_buf@LIBAVFORMAT_58 7:4.0 avio_pause@LIBAVFORMAT_58 7:4.0 + avio_print_string_array@LIBAVFORMAT_58 7:4.3 avio_printf@LIBAVFORMAT_58 7:4.0 + avio_protocol_get_class@LIBAVFORMAT_58 7:4.3 avio_put_str16be@LIBAVFORMAT_58 7:4.0 avio_put_str16le@LIBAVFORMAT_58 7:4.0 avio_put_str@LIBAVFORMAT_58 7:4.0 @@ -164,6 +168,3 @@ avio_wl64@LIBAVFORMAT_58 7:4.0 avio_write@LIBAVFORMAT_58 7:4.0 avio_write_marker@LIBAVFORMAT_58 7:4.0 -# Symbols starting with avpriv_ are not public and other packages must not use -# them. Intra-library ABI is ensured by manual dependencies in d/control. - (optional|regex)^avpriv_ 0 diff -Nru ffmpeg-4.2.2/debian/libavutil56.symbols ffmpeg-4.4/debian/libavutil56.symbols --- ffmpeg-4.2.2/debian/libavutil56.symbols 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/libavutil56.symbols 2021-05-25 10:09:41.000000000 +0000 @@ -1,6 +1,8 @@ +# SymbolsHelper-Confirmed: 7:4.3 amd64 libavutil.so.56 libavutil56 #MINVER# * Build-Depends-Package: libavutil-dev LIBAVUTIL_56@LIBAVUTIL_56 7:4.0 + (optional|regex)^avpriv_ 0 av_add_i@LIBAVUTIL_56 7:4.0 av_add_q@LIBAVUTIL_56 7:4.0 av_add_stable@LIBAVUTIL_56 7:4.0 @@ -59,12 +61,14 @@ av_buffer_get_ref_count@LIBAVUTIL_56 7:4.0 av_buffer_is_writable@LIBAVUTIL_56 7:4.0 av_buffer_make_writable@LIBAVUTIL_56 7:4.0 + av_buffer_pool_buffer_get_opaque@LIBAVUTIL_56 7:4.3 av_buffer_pool_get@LIBAVUTIL_56 7:4.0 av_buffer_pool_init2@LIBAVUTIL_56 7:4.0 av_buffer_pool_init@LIBAVUTIL_56 7:4.0 av_buffer_pool_uninit@LIBAVUTIL_56 7:4.0 av_buffer_realloc@LIBAVUTIL_56 7:4.0 av_buffer_ref@LIBAVUTIL_56 7:4.0 + av_buffer_replace@LIBAVUTIL_56 7:4.4 av_buffer_unref@LIBAVUTIL_56 7:4.0 av_calloc@LIBAVUTIL_56 7:4.0 av_camellia_alloc@LIBAVUTIL_56 7:4.0 @@ -119,6 +123,7 @@ av_display_rotation_set@LIBAVUTIL_56 7:4.0 av_div_i@LIBAVUTIL_56 7:4.0 av_div_q@LIBAVUTIL_56 7:4.0 + av_dovi_alloc@LIBAVUTIL_56 7:4.3 av_downmix_info_update_side_data@LIBAVUTIL_56 7:4.0 av_dynamic_hdr_plus_alloc@LIBAVUTIL_56 7:4.2 av_dynamic_hdr_plus_create_side_data@LIBAVUTIL_56 7:4.2 @@ -135,6 +140,8 @@ av_encryption_init_info_free@LIBAVUTIL_56 7:4.0 av_encryption_init_info_get_side_data@LIBAVUTIL_56 7:4.1 av_escape@LIBAVUTIL_56 7:4.0 + av_expr_count_func@LIBAVUTIL_56 7:4.3 + av_expr_count_vars@LIBAVUTIL_56 7:4.3 av_expr_eval@LIBAVUTIL_56 7:4.0 av_expr_free@LIBAVUTIL_56 7:4.0 av_expr_parse@LIBAVUTIL_56 7:4.0 @@ -158,6 +165,8 @@ av_fifo_space@LIBAVUTIL_56 7:4.0 av_file_map@LIBAVUTIL_56 7:4.0 av_file_unmap@LIBAVUTIL_56 7:4.0 + av_film_grain_params_alloc@LIBAVUTIL_56 7:4.4 + av_film_grain_params_create_side_data@LIBAVUTIL_56 7:4.4 av_find_best_pix_fmt_of_2@LIBAVUTIL_56 7:4.0 av_find_info_tag@LIBAVUTIL_56 7:4.0 av_find_nearest_q_idx@LIBAVUTIL_56 7:4.0 @@ -209,6 +218,7 @@ av_free@LIBAVUTIL_56 7:4.0 av_freep@LIBAVUTIL_56 7:4.0 av_gcd@LIBAVUTIL_56 7:4.0 + av_gcd_q@LIBAVUTIL_56 7:4.3 av_get_alt_sample_fmt@LIBAVUTIL_56 7:4.0 av_get_bits_per_pixel@LIBAVUTIL_56 7:4.0 av_get_bytes_per_sample@LIBAVUTIL_56 7:4.0 @@ -262,6 +272,7 @@ av_hwdevice_ctx_alloc@LIBAVUTIL_56 7:4.0 av_hwdevice_ctx_create@LIBAVUTIL_56 7:4.0 av_hwdevice_ctx_create_derived@LIBAVUTIL_56 7:4.0 + av_hwdevice_ctx_create_derived_opts@LIBAVUTIL_56 7:4.3 av_hwdevice_ctx_init@LIBAVUTIL_56 7:4.0 av_hwdevice_find_type_by_name@LIBAVUTIL_56 7:4.0 av_hwdevice_get_hwframe_constraints@LIBAVUTIL_56 7:4.0 @@ -289,6 +300,7 @@ av_image_fill_black@LIBAVUTIL_56 7:4.0 av_image_fill_linesizes@LIBAVUTIL_56 7:4.0 av_image_fill_max_pixsteps@LIBAVUTIL_56 7:4.0 + av_image_fill_plane_sizes@LIBAVUTIL_56 7:4.4 av_image_fill_pointers@LIBAVUTIL_56 7:4.0 av_image_get_buffer_size@LIBAVUTIL_56 7:4.0 av_image_get_linesize@LIBAVUTIL_56 7:4.0 @@ -305,6 +317,7 @@ av_log_format_line@LIBAVUTIL_56 7:4.0 av_log_get_flags@LIBAVUTIL_56 7:4.0 av_log_get_level@LIBAVUTIL_56 7:4.0 + av_log_once@LIBAVUTIL_56 7:4.3 av_log_set_callback@LIBAVUTIL_56 7:4.0 av_log_set_flags@LIBAVUTIL_56 7:4.0 av_log_set_level@LIBAVUTIL_56 7:4.0 @@ -335,6 +348,7 @@ av_murmur3_init_seeded@LIBAVUTIL_56 7:4.0 av_murmur3_update@LIBAVUTIL_56 7:4.0 av_nearer_q@LIBAVUTIL_56 7:4.0 + av_opt_child_class_iterate@LIBAVUTIL_56 7:4.4 av_opt_child_class_next@LIBAVUTIL_56 7:4.0 av_opt_child_next@LIBAVUTIL_56 7:4.0 av_opt_copy@LIBAVUTIL_56 7:4.0 @@ -483,10 +497,13 @@ av_thread_message_queue_set_free_func@LIBAVUTIL_56 7:4.0 av_timecode_adjust_ntsc_framenum2@LIBAVUTIL_56 7:4.0 av_timecode_check_frame_rate@LIBAVUTIL_56 7:4.0 + av_timecode_get_smpte@LIBAVUTIL_56 7:4.4 av_timecode_get_smpte_from_framenum@LIBAVUTIL_56 7:4.0 av_timecode_init@LIBAVUTIL_56 7:4.0 + av_timecode_init_from_components@LIBAVUTIL_56 7:4.4 av_timecode_init_from_string@LIBAVUTIL_56 7:4.0 av_timecode_make_mpeg_tc_string@LIBAVUTIL_56 7:4.0 + av_timecode_make_smpte_tc_string2@LIBAVUTIL_56 7:4.4 av_timecode_make_smpte_tc_string@LIBAVUTIL_56 7:4.0 av_timecode_make_string@LIBAVUTIL_56 7:4.0 av_timegm@LIBAVUTIL_56 7:4.0 @@ -507,6 +524,8 @@ av_util_ffversion@LIBAVUTIL_56 7:4.0 av_vbprintf@LIBAVUTIL_56 7:4.0 av_version_info@LIBAVUTIL_56 7:4.0 + av_video_enc_params_alloc@LIBAVUTIL_56 7:4.3 + av_video_enc_params_create_side_data@LIBAVUTIL_56 7:4.3 av_vlog@LIBAVUTIL_56 7:4.0 av_write_image_line2@LIBAVUTIL_56 7:4.1 av_write_image_line@LIBAVUTIL_56 7:4.0 @@ -518,6 +537,3 @@ avutil_configuration@LIBAVUTIL_56 7:4.0 avutil_license@LIBAVUTIL_56 7:4.0 avutil_version@LIBAVUTIL_56 7:4.0 -# Symbols starting with avpriv_ are not public and other packages must not use -# them. Intra-library ABI is ensured by manual dependencies in d/control. - (optional|regex)^avpriv_ 0 diff -Nru ffmpeg-4.2.2/debian/patches/0002-avcodec-libtwolame-fix-mono-default-bitrate.patch ffmpeg-4.4/debian/patches/0002-avcodec-libtwolame-fix-mono-default-bitrate.patch --- ffmpeg-4.2.2/debian/patches/0002-avcodec-libtwolame-fix-mono-default-bitrate.patch 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/patches/0002-avcodec-libtwolame-fix-mono-default-bitrate.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -From bb718d11ed992f4d12ad683e310b53bf1c519322 Mon Sep 17 00:00:00 2001 -From: James Cowgill -Date: Fri, 1 Nov 2019 08:51:07 +0000 -Subject: [PATCH] avcodec/libtwolame: fix mono default bitrate - -As of libtwolame 0.4.0, 384 kbps is not accepted as a valid bitrate -for encoding mono audio and the maximum bitrate is now halved to 192 -kbps to comply with the MP2 standard. Example error: - - twolame_init_params(): 384kbps is an invalid bitrate for mono encoding. - -Adjust the default bitrate calculation to take this into account. - -Signed-off-by: James Cowgill ---- - libavcodec/libtwolame.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/libavcodec/libtwolame.c b/libavcodec/libtwolame.c -index 030f88868f..5ceb3d9f3f 100644 ---- a/libavcodec/libtwolame.c -+++ b/libavcodec/libtwolame.c -@@ -78,8 +78,12 @@ static av_cold int twolame_encode_init(AVCodecContext *avctx) - twolame_set_in_samplerate(s->glopts, avctx->sample_rate); - twolame_set_out_samplerate(s->glopts, avctx->sample_rate); - -- if (!avctx->bit_rate) -- avctx->bit_rate = avctx->sample_rate < 28000 ? 160000 : 384000; -+ if (!avctx->bit_rate) { -+ if ((s->mode == TWOLAME_AUTO_MODE && avctx->channels == 1) || s->mode == TWOLAME_MONO) -+ avctx->bit_rate = avctx->sample_rate < 28000 ? 80000 : 192000; -+ else -+ avctx->bit_rate = avctx->sample_rate < 28000 ? 160000 : 384000; -+ } - - if (avctx->flags & AV_CODEC_FLAG_QSCALE || !avctx->bit_rate) { - twolame_set_VBR(s->glopts, TRUE); --- -2.24.0.rc1 - diff -Nru ffmpeg-4.2.2/debian/patches/0002_doxygen.diff ffmpeg-4.4/debian/patches/0002_doxygen.diff --- ffmpeg-4.2.2/debian/patches/0002_doxygen.diff 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/debian/patches/0002_doxygen.diff 2021-05-25 10:09:41.000000000 +0000 @@ -0,0 +1,12 @@ +--- a/doc/Doxyfile ++++ b/doc/Doxyfile +@@ -805,7 +805,8 @@ EXCLUDE_SYMLINKS = NO + # exclude all test directories for example use the pattern */test/* + + EXCLUDE_PATTERNS = *.git \ +- *.d ++ *.d \ ++ debian + + # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names + # (namespaces, classes, functions, etc.) that should be excluded from the diff -Nru ffmpeg-4.2.2/debian/patches/revert-lensfun-update-part1.patch ffmpeg-4.4/debian/patches/revert-lensfun-update-part1.patch --- ffmpeg-4.2.2/debian/patches/revert-lensfun-update-part1.patch 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/debian/patches/revert-lensfun-update-part1.patch 2021-05-25 10:09:41.000000000 +0000 @@ -0,0 +1,66 @@ +From: Rob Savoury +Date: Wed, 03 Mar 2021 16:32:08 -0800 +Subject: Reverse lensfun update part1 + +Reverse two lensfun commits (evidently for compatibility with 0.3.95 alpha +rather than the still widely used 0.3.2). Below is the reverse commit. +--- +commit d16293e76cf8b53b8bef589e69823f7864ee14f4 +Author: Paul B Mahol +Date: Fri Feb 5 15:26:10 2021 +0100 + + avfilter/vf_lensfun: display list of possible values if user supplied none + +diff --git a/libavfilter/vf_lensfun.c b/libavfilter/vf_lensfun.c +index 430daa941b..95f00e8c10 100644 +--- a/libavfilter/vf_lensfun.c ++++ b/libavfilter/vf_lensfun.c +@@ -136,36 +136,27 @@ static av_cold int init(AVFilterContext *ctx) + const lfCamera **cameras; + const lfLens **lenses; + +- db = lf_db_create(); +- if (lf_db_load(db) != LF_NO_ERROR) { +- lf_db_destroy(db); +- av_log(ctx, AV_LOG_FATAL, "Failed to load lensfun database\n"); +- return AVERROR_INVALIDDATA; +- } +- +- if (!lensfun->make || !lensfun->model) { +- const lfCamera *const *cameras = lf_db_get_cameras(db); +- +- av_log(ctx, AV_LOG_FATAL, "Option \"make\" or option \"model\" not specified\n"); +- av_log(ctx, AV_LOG_INFO, "Available values for \"make\" and \"model\":\n"); +- for (int i = 0; cameras && cameras[i]; i++) +- av_log(ctx, AV_LOG_INFO, "\t%s\t%s\n", cameras[i]->Maker, cameras[i]->Model); +- lf_db_destroy(db); ++ if (!lensfun->make) { ++ av_log(ctx, AV_LOG_FATAL, "Option \"make\" not specified\n"); ++ return AVERROR(EINVAL); ++ } else if (!lensfun->model) { ++ av_log(ctx, AV_LOG_FATAL, "Option \"model\" not specified\n"); + return AVERROR(EINVAL); + } else if (!lensfun->lens_model) { +- const lfLens *const *lenses = lf_db_get_lenses(db); +- + av_log(ctx, AV_LOG_FATAL, "Option \"lens_model\" not specified\n"); +- av_log(ctx, AV_LOG_INFO, "Available values for \"lens_model\":\n"); +- for (int i = 0; lenses && lenses[i]; i++) +- av_log(ctx, AV_LOG_INFO, "\t%s\t(make %s)\n", lenses[i]->Model, lenses[i]->Maker); +- lf_db_destroy(db); + return AVERROR(EINVAL); + } + + lensfun->lens = lf_lens_create(); + lensfun->camera = lf_camera_create(); + ++ db = lf_db_create(); ++ if (lf_db_load(db) != LF_NO_ERROR) { ++ lf_db_destroy(db); ++ av_log(ctx, AV_LOG_FATAL, "Failed to load lensfun database\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ + cameras = lf_db_find_cameras(db, lensfun->make, lensfun->model); + if (cameras && *cameras) { + lf_camera_copy(lensfun->camera, *cameras); diff -Nru ffmpeg-4.2.2/debian/patches/revert-lensfun-update-part2.patch ffmpeg-4.4/debian/patches/revert-lensfun-update-part2.patch --- ffmpeg-4.2.2/debian/patches/revert-lensfun-update-part2.patch 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/debian/patches/revert-lensfun-update-part2.patch 2021-05-25 10:09:41.000000000 +0000 @@ -0,0 +1,83 @@ +From: Rob Savoury +Date: Wed, 03 Mar 2021 16:38:36 -0800 +Subject: Reverse lensfun update part2 + +Reverse two lensfun commits (evidently for compatibility with 0.3.95 alpha +rather than the still widely used 0.3.2). Below is the reverse commit. +--- +commit 8b78eb312de948c408c2437674e6ebf8971857c4 +Author: Paul B Mahol +Date: Fri Feb 5 14:28:57 2021 +0100 + + avfilter/vf_lensfun: replace deprecated calls + +diff --git a/libavfilter/vf_lensfun.c b/libavfilter/vf_lensfun.c +index 95f00e8c10..089121ed08 100644 +--- a/libavfilter/vf_lensfun.c ++++ b/libavfilter/vf_lensfun.c +@@ -147,10 +147,10 @@ static av_cold int init(AVFilterContext *ctx) + return AVERROR(EINVAL); + } + +- lensfun->lens = lf_lens_create(); +- lensfun->camera = lf_camera_create(); ++ lensfun->lens = lf_lens_new(); ++ lensfun->camera = lf_camera_new(); + +- db = lf_db_create(); ++ db = lf_db_new(); + if (lf_db_load(db) != LF_NO_ERROR) { + lf_db_destroy(db); + av_log(ctx, AV_LOG_FATAL, "Failed to load lensfun database\n"); +@@ -169,7 +169,7 @@ static av_cold int init(AVFilterContext *ctx) + } + lf_free(cameras); + +- lenses = lf_db_find_lenses(db, lensfun->camera, NULL, lensfun->lens_model, 0); ++ lenses = lf_db_find_lenses_hd(db, lensfun->camera, NULL, lensfun->lens_model, 0); + if (lenses && *lenses) { + lf_lens_copy(lensfun->lens, *lenses); + av_log(ctx, AV_LOG_INFO, "Using lens %s\n", lensfun->lens->Model); +@@ -210,23 +210,30 @@ static int config_props(AVFilterLink *inlink) + LensfunContext *lensfun = ctx->priv; + int index; + float a; ++ int lensfun_mode = 0; + + if (!lensfun->modifier) { + if (lensfun->camera && lensfun->lens) { +- lensfun->modifier = lf_modifier_create(lensfun->lens, +- lensfun->focal_length, +- lensfun->camera->CropFactor, +- inlink->w, +- inlink->h, LF_PF_U8, lensfun->reverse); ++ lensfun->modifier = lf_modifier_new(lensfun->lens, ++ lensfun->camera->CropFactor, ++ inlink->w, ++ inlink->h); + if (lensfun->mode & VIGNETTING) +- lf_modifier_enable_vignetting_correction(lensfun->modifier, lensfun->aperture, lensfun->focus_distance); +- if (lensfun->mode & GEOMETRY_DISTORTION) { +- lf_modifier_enable_distortion_correction(lensfun->modifier); +- lf_modifier_enable_projection_transform(lensfun->modifier, lensfun->target_geometry); +- lf_modifier_enable_scaling(lensfun->modifier, lensfun->scale); +- } ++ lensfun_mode |= LF_MODIFY_VIGNETTING; ++ if (lensfun->mode & GEOMETRY_DISTORTION) ++ lensfun_mode |= LF_MODIFY_DISTORTION | LF_MODIFY_GEOMETRY | LF_MODIFY_SCALE; + if (lensfun->mode & SUBPIXEL_DISTORTION) +- lf_modifier_enable_tca_correction(lensfun->modifier); ++ lensfun_mode |= LF_MODIFY_TCA; ++ lf_modifier_initialize(lensfun->modifier, ++ lensfun->lens, ++ LF_PF_U8, ++ lensfun->focal_length, ++ lensfun->aperture, ++ lensfun->focus_distance, ++ lensfun->scale, ++ lensfun->target_geometry, ++ lensfun_mode, ++ lensfun->reverse); + } else { + // lensfun->camera and lensfun->lens should have been initialized + return AVERROR_BUG; diff -Nru ffmpeg-4.2.2/debian/patches/series ffmpeg-4.4/debian/patches/series --- ffmpeg-4.2.2/debian/patches/series 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/patches/series 2021-05-25 10:09:41.000000000 +0000 @@ -1,2 +1,4 @@ 0001-avcodec-arm-sbcenc-avoid-callee-preserved-vfp-regist.patch -0002-avcodec-libtwolame-fix-mono-default-bitrate.patch +0002_doxygen.diff +revert-lensfun-update-part1.patch +revert-lensfun-update-part2.patch diff -Nru ffmpeg-4.2.2/debian/rules ffmpeg-4.4/debian/rules --- ffmpeg-4.2.2/debian/rules 2020-03-07 08:39:35.000000000 +0000 +++ ffmpeg-4.4/debian/rules 2021-05-25 10:09:41.000000000 +0000 @@ -21,21 +21,23 @@ # Enable as many features as possible, as long as the result is still GPLv2+ (a GPLv3+ variant is built as libavcodec-extra/libavfilter-extra flavor). # The following flags (and build-dependencies) are not added, because they would require a libavformat-extra flavor: +# --enable-libglslang (glslang-dev) # --enable-libsmbclient (libsmbclient-dev [!hurd-i386 !m68k !sparc64]) +# --enable-vulkan (libvulkan-dev) # The following flags are not added, because the necessary libraries are not in Debian: -# --enable-decklink +# --enable-avisynth (should link with AviSynth+, embedded avisynth code dropped upstream) +# --enable-decklink (see #839941 for discussion of freeness) # --enable-libcelt (see #676592: removed from Debian as abandoned upstream, replaced by opus) -# --enable-libdav1d # --enable-libdavs2 (only in experimental) # --enable-libilbc (see #675959 for the RFP bug) # --enable-libklvanc # --enable-libkvazaar -# --enable-libmfx # --enable-libopenh264 -# --enable-libtensorflow +# --enable-librav1e (see #920842 for the RFP bug) +# --enable-libtensorflow (see #959765 for the RFP bug) # --enable-libvmaf -# --enable-libxavs2 -# --enable-libxavs (only in experimental) +# --enable-libxavs +# --enable-libxavs2 (only in experimental) # --enable-libzimg (see #864888 for the RFP bug) # --enable-vapoursynth (see #833942 for the RFP bug) # The following flags are not added for various reasons: @@ -43,11 +45,10 @@ # --enable-librtmp ffmpeg has better built-in RTMP support with listen mode. # --enable-mbedtls Already using gnutls as TLS implementation # --enable-libmodplug see #849840: replaced with libopenmpt -# --enable-libsrt see #933180: links against OpenSSL (license incompatibility) # --enable-libv4l2 This is only needed for very old devices and may cause problems for others. # Should anyone need it, using LD_PRELOAD pointing on libv4l2 has the same effect. -# --enable-opencv Does not build with OpenCV >= 3.4 -# --enable-pocketsphinx see #941377: package dependencies are slightly broken +# --enable-opencl This is considered an experimental API. +# --enable-opencv Does not build with OpenCV >= 3.4 - see CONFIG := --prefix=/usr \ --extra-version="$(DEB_REVISION)" \ --toolchain=hardened \ @@ -57,8 +58,8 @@ --enable-gpl \ --disable-stripping \ --enable-avresample --disable-filter=resample \ - --enable-avisynth \ --enable-gnutls \ + --enable-hardcoded-tables \ --enable-ladspa \ --enable-libaom \ --enable-libass \ @@ -80,19 +81,20 @@ --enable-libopenmpt \ --enable-libopus \ --enable-libpulse \ + --enable-librabbitmq \ --enable-librsvg \ --enable-librubberband \ --enable-libshine \ --enable-libsnappy \ --enable-libsoxr \ --enable-libspeex \ + --enable-libsrt \ --enable-libssh \ --enable-libtheora \ --enable-libtwolame \ --enable-libvidstab \ --enable-libvorbis \ --enable-libvpx \ - --enable-libwavpack \ --enable-libwebp \ --enable-libx265 \ --enable-libxml2 \ @@ -100,12 +102,22 @@ --enable-libzmq \ --enable-libzvbi \ --enable-lv2 \ + --enable-nonfree \ --enable-omx \ --enable-openal \ --enable-opencl \ --enable-opengl \ --enable-sdl2 +ifeq ($(DEB_HOST_ARCH),amd64) +CONFIG += --enable-libmfx \ + --enable-avisynth \ + --enable-libdav1d \ + --enable-libfdk-aac \ + --enable-libsvtav1 \ + --enable-libvmaf +endif + # The standard configuration only uses the shared CONFIG. CONFIG_standard = --enable-shared @@ -147,11 +159,6 @@ --enable-libiec61883 endif -# Enable nvenc on amd64 only; not supported on other architectures. -ifeq ($(DEB_HOST_ARCH),amd64) - CONFIG += --enable-nvenc -endif - # ffmpeg is involved in build-dependency cycles with x264 and chromaprint, so disable them in stage one. # Also disable frei0r, which build-depends on opencv. ifneq ($(filter pkg.ffmpeg.stage1,$(DEB_BUILD_PROFILES)),) @@ -183,8 +190,6 @@ CONFIG += --disable-asm endif - - # Disable some optimizations on mips*, because they are not always available on these architectures ifneq (,$(filter mips%r6 mips%r6el, $(DEB_HOST_ARCH))) MIPS_R2_R6_CONFIG = --disable-mips32r2 \ @@ -224,16 +229,18 @@ # Use the default debhelper scripts, where possible. %: - dh $@ + dh $@ --with pkgkde_symbolshelper # Add configuration options: -override_dh_auto_configure: - $(foreach flavor,$(FLAVORS),mkdir -p debian/$(flavor);) - $(foreach flavor,$(FLAVORS),set -e; echo " *** $(flavor) ***"; cd debian/$(flavor); ../../configure $(CONFIG) $(CONFIG_$(flavor)) || (cat ffbuild/config.log && exit 1); cd ../.. ;) +override_dh_auto_configure: $(patsubst %,configure_%,$(FLAVORS)) +configure_%: + $(info $() debian/rules $@) + mkdir -p debian/$* + cd debian/$* && ../../configure $(strip $(CONFIG) $(CONFIG_$*)) || (cat ffbuild/config.log && exit 1) # Remove the subdirectories generated for the flavors. override_dh_auto_clean: - $(foreach flavor,$(FLAVORS),[ ! -d debian/$(flavor) ] || rm -r debian/$(flavor);) + rm -rf $(patsubst %,debian/%,$(FLAVORS)) # Create doxygen documentation: override_dh_auto_build-indep: @@ -245,25 +252,30 @@ # See: #895154 (lessc debian/missing-sources/ffmpeg-web/src/less/style.less | cleancss > debian/standard/doc/style.min.css) 2>&1 | cat >&2 -override_dh_auto_build-arch: - # Copy built object files to avoid building them again for the extra flavor. - # Build qt-faststart here, to make it possible to build with 'nocheck'. - set -e && for flavor in $(FLAVORS); do \ - echo " *** $$flavor ***"; \ - if echo "$$flavor" | grep -q "extra"; then \ - subdir=`[ "$$flavor" = "extra" ] && echo "debian/standard/" || echo "debian/altivec/"`; \ - for dir in `cd ./$$subdir; find libavcodec libavdevice libavfilter libavformat libavresample libavutil libpostproc libswscale libswresample -type d`; do \ - mkdir -p debian/"$$flavor"/"$$dir"; \ - echo "$$subdir$$dir"/*.o | grep -q '*' || cp "$$subdir$$dir"/*.o debian/"$$flavor"/"$$dir"; \ - done; \ - rm debian/"$$flavor"/libavcodec/allcodecs.o; \ - rm debian/"$$flavor"/libavfilter/allfilters.o; \ - fi; \ - if [ "$$flavor" = "standard" ]; then \ - $(MAKE) -C debian/standard tools/qt-faststart; \ - fi; \ - dh_auto_build -a --sourcedirectory=debian/"$$flavor" || (cat debian/"$$flavor"/config.log && exit 1); \ - done +override_dh_auto_build-arch: $(patsubst %,build_%,$(FLAVORS)) + +# noop fallback for below more specific targets +prebuild_%: + : + +# Copy built object files to avoid building them again for the extra flavor. +$(patsubst %,prebuild_%,$(filter %extra,$(FLAVORS))): prebuild_%: build_standard + $(info $() debian/rules $@) + $(eval subdir = debian/$(subst extra,standard,$(subst -extra,,$*))) + cd $(subdir) && find libavcodec libavdevice libavfilter libavformat libavresample libavutil libpostproc libswscale libswresample \ + -type f -name '*.o' \ + -exec install -m 644 -D -T '{}' '../$*/{}' ';' + rm debian/$*/libavcodec/allcodecs.o + rm debian/$*/libavfilter/allfilters.o + +# Build qt-faststart here, to make it possible to build with 'nocheck'. +prebuild_standard: + $(info $() debian/rules $@) + $(MAKE) -C debian/standard tools/qt-faststart + +build_%: prebuild_% + $(info $() debian/rules $@) + dh_auto_build -a --sourcedirectory=debian/$* || (cat debian/$*/config.log && exit 1) # Set the library path for the dynamic linker, because the tests otherwise don't find the libraries. override_dh_auto_test-arch: @@ -304,11 +316,14 @@ ver=${DEB_VERSION}; \ echo "$$lib $$abi $$pkg (= $$ver)" >> debian/shlibs.local; \ done - dh_shlibdeps - -override_dh_missing: - dh_missing --list-missing + set -e && for pkg in $(EXTRA_PKGS); do \ + mainpkg=`echo $$pkg | sed 's/-extra//'`; \ + cp -f debian/$$mainpkg.symbols debian/$$pkg.symbols; \ + dh_shlibdeps -p$$pkg; \ + rm -f debian/$$pkg.symbols; \ + done + dh_shlibdeps --remaining-packages -# Don't compress the example source code files. -override_dh_compress: - dh_compress -Xexamples +# avoid error: Unknown DWARF DW_OP_0 +override_dh_dwz: + dh_dwz -Xlibavcodec -Xlibavfilter -Xlibavresample -Xlibavutil -Xlibswresample -Xlibswscale diff -Nru ffmpeg-4.2.2/debian/tests/encdec ffmpeg-4.4/debian/tests/encdec --- ffmpeg-4.2.2/debian/tests/encdec 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/tests/encdec 2021-05-25 10:09:13.000000000 +0000 @@ -237,7 +237,7 @@ } echo "TEST: $TEST_NAME" -echo -e "AUTOPKGTEST_TMP directory: $AUTOPKGTEST_TMP\n\n" +echo -e "ADTTMP directory: $AUTOPKGTEST_TMP\n\n" mkdir -p "$TEST_DIR" diff -Nru ffmpeg-4.2.2/debian/tests/encdec_list.txt ffmpeg-4.4/debian/tests/encdec_list.txt --- ffmpeg-4.2.2/debian/tests/encdec_list.txt 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/tests/encdec_list.txt 2021-05-25 10:09:13.000000000 +0000 @@ -11,7 +11,7 @@ avi; v=amv|1 v=asv1|1 v=asv2|1 v=av1:libaom-av1|1 v=ayuv|1 v=cinepak|1 v=cljr|1 v=dirac:vc2|1 v=dpx|1 v=dvvideo|1 v=ffv1|1 v=ffvhuff|1 v=flashsv|1 v=flv1:flv|1 v=h261|1 v=h263:h263|1 v=h264:libx264|1 v=h264:libx264rgb|1 v=hap|1 v=huffyuv|1 v=jpeg2000:jpeg2000|1 v=jpeg2000:libopenjpeg|1 v=jpegls|1 v=magicyuv|1 v=mjpeg:mjpeg|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 v=msmpeg4v2|1 v=msmpeg4v3:msmpeg4|1 v=msvideo1|1 v=png|1 v=prores:prores|1 v=prores:prores_aw|1 v=prores:prores_ks|1 v=r10k|1 v=r210|1 v=snow|1 v=svq1|1 v=targa|1 v=theora:libtheora|1 v=utvideo|1 v=v210|1 v=v308|1 v=v408|1 v=v410|1 v=vp8:libvpx|1 v=vp9:libvpx-vp9|1 v=wmv1|1 v=wmv2|1 v=y41p|1 v=yuv4|1 v=zlib|1 v=zmbv|1 a=aac|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=adpcm_g722:g722|1 a=adpcm_g726:g726|1 a=adpcm_ima_wav|1 a=adpcm_ms|1 a=adpcm_swf|1 a=adpcm_yamaha|1 a=dts:dca|1 a=eac3|1 a=flac|1 a=g723_1|1 a=gsm_ms:libgsm_ms|1 a=mp2:mp2|1 a=mp2:mp2fixed|1 a=mp2:libtwolame|1 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=pcm_alaw|1 a=pcm_f32le|1 a=pcm_f64le|1 a=pcm_mulaw|1 a=pcm_s16le|1 a=pcm_s24le|1 a=pcm_s32le|1 a=pcm_s64le|1 a=pcm_u8|1 a=sonic|1 a=speex:libspeex|1 a=vorbis:vorbis|1 a=vorbis:libvorbis|1 a=wmav1|1 a=wmav2|1 caf; a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=adpcm_ima_qt|1 a=adpcm_ima_wav|1 a=adpcm_ms|1 a=alac|1 a=gsm:libgsm|1 a=gsm_ms:libgsm_ms|1 a=mp2:mp2|1 a=mp2:mp2fixed|1 a=mp2:libtwolame|1 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=opus:opus|1 a=opus:libopus|1 a=pcm_alaw|1 a=pcm_f32be|1 a=pcm_f32le|1 a=pcm_f64be|1 a=pcm_f64le|1 a=pcm_mulaw|1 a=pcm_s16be|1 a=pcm_s16le|1 a=pcm_s24be|1 a=pcm_s24le|1 a=pcm_s32be|1 a=pcm_s32le|1 a=pcm_s8|1 codec2; a=codec2:libcodec2|1 -dash; v=av1:libaom-av1|1 v=dirac:vc2|0 v=h264:libx264|1 v=h264:libx264rgb|1 v=hevc:libx265|1 v=jpeg2000:jpeg2000|1 v=jpeg2000:libopenjpeg|1 v=mjpeg:mjpeg|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 v=png|1 v=vp8:libvpx|1 v=vp9:libvpx-vp9|1 a=aac|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=dts:dca|1 a=eac3|1 a=flac|0 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=opus:opus|1 a=opus:libopus|1 a=vorbis:vorbis|1 a=vorbis:libvorbis|1 +dash; v=av1:libaom-av1|1 v=dirac:vc2|0 v=h264:libx264|1 v=h264:libx264rgb|1 v=hevc:libx265|1 v=jpeg2000:jpeg2000|1 v=jpeg2000:libopenjpeg|1 v=mjpeg:mjpeg|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 v=png|1 v=vp9:libvpx-vp9|1 a=aac|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=dts:dca|1 a=eac3|1 a=flac|0 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=opus:opus|0 a=opus:libopus|0 a=vorbis:vorbis|1 a=vorbis:libvorbis|1 dirac; v=dirac:vc2|1 dnxhd; v=dnxhd|1 dts; a=dts:dca|1 @@ -23,7 +23,7 @@ flv; v=flashsv|1 v=flashsv2|1 v=flv1:flv|1 v=h263:h263|0 v=h264:libx264|1 v=h264:libx264rgb|1 a=aac|1 a=adpcm_swf|1 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=nellymoser|1 a=pcm_alaw|1 a=pcm_mulaw|1 a=pcm_s16le|1 a=pcm_u8|1 g722; a=adpcm_g722:g722|1 g723_1; a=g723_1|1 -gif; v=gif|1 +gif; v=gif|0 gsm; a=gsm:libgsm|1 gxf; v=dvvideo|1 h261; v=h261|1 @@ -34,18 +34,18 @@ ircam; a=pcm_alaw|1 a=pcm_f32le|1 a=pcm_f64le|1 a=pcm_mulaw|1 a=pcm_s16le|1 a=pcm_s24le|1 a=pcm_s32le|1 a=pcm_s8|1 ivf; v=av1:libaom-av1|1 v=vp8:libvpx|1 v=vp9:libvpx-vp9|1 m4v; v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 -matroska; v=amv|1 v=asv1|1 v=asv2|1 v=av1:libaom-av1|1 v=avrp|1 v=ayuv|1 v=cinepak|1 v=cljr|1 v=dirac:vc2|1 v=dnxhd|1 v=dpx|1 v=dvvideo|1 v=ffv1|1 v=ffvhuff|1 v=flashsv|1 v=flv1:flv|1 v=gif|1 v=h261|1 v=h263:h263|1 v=h264:libx264|1 v=h264:libx264rgb|1 v=hap|1 v=hevc:libx265|1 v=huffyuv|1 v=jpeg2000:jpeg2000|1 v=jpeg2000:libopenjpeg|1 v=jpegls|1 v=magicyuv|1 v=mjpeg:mjpeg|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 v=msmpeg4v2|1 v=msmpeg4v3:msmpeg4|1 v=msvideo1|1 v=png|1 v=prores:prores|1 v=prores:prores_aw|1 v=prores:prores_ks|1 v=r10k|1 v=r210|1 v=rawvideo|0 v=sgi|1 v=snow|1 v=svq1|1 v=targa|1 v=theora:libtheora|1 v=tiff|1 v=utvideo|1 v=v210|1 v=v308|1 v=v408|1 v=v410|1 v=vp8:libvpx|1 v=vp9:libvpx-vp9|1 v=wmv1|1 v=wmv2|1 v=y41p|1 v=yuv4|1 v=zlib|1 v=zmbv|1 a=aac|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=adpcm_g722:g722|1 a=adpcm_g726:g726|1 a=adpcm_ima_wav|1 a=adpcm_ms|1 a=adpcm_swf|1 a=adpcm_yamaha|1 a=alac|1 a=dts:dca|1 a=eac3|1 a=flac|1 a=g723_1|1 a=gsm_ms:libgsm_ms|1 a=mlp|1 a=mp2:mp2|1 a=mp2:mp2fixed|1 a=mp2:libtwolame|1 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=opus:opus|1 a=opus:libopus|1 a=pcm_alaw|1 a=pcm_f32le|1 a=pcm_f64le|1 a=pcm_mulaw|1 a=pcm_s16be|1 a=pcm_s16le|1 a=pcm_s24be|1 a=pcm_s24le|1 a=pcm_s32be|1 a=pcm_s32le|1 a=pcm_s64le|1 a=pcm_u8|1 a=ra_144:real_144|1 a=sonic|1 a=speex:libspeex|1 a=truehd|1 a=tta|1 a=vorbis:vorbis|1 a=vorbis:libvorbis|1 a=wavpack:wavpack|1 a=wavpack:libwavpack|1 a=wmav1|1 a=wmav2|1 +matroska; v=amv|1 v=asv1|1 v=asv2|1 v=av1:libaom-av1|1 v=avrp|1 v=ayuv|1 v=cinepak|1 v=cljr|1 v=dirac:vc2|1 v=dnxhd|1 v=dpx|1 v=dvvideo|1 v=ffv1|1 v=ffvhuff|1 v=flashsv|1 v=flv1:flv|1 v=h261|1 v=h263:h263|1 v=h264:libx264|1 v=h264:libx264rgb|1 v=hap|1 v=hevc:libx265|1 v=huffyuv|1 v=jpeg2000:jpeg2000|1 v=jpeg2000:libopenjpeg|1 v=jpegls|1 v=magicyuv|1 v=mjpeg:mjpeg|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 v=msmpeg4v2|1 v=msmpeg4v3:msmpeg4|1 v=msvideo1|1 v=png|1 v=prores:prores|1 v=prores:prores_aw|1 v=prores:prores_ks|1 v=r10k|1 v=r210|1 v=rawvideo|0 v=sgi|1 v=snow|1 v=svq1|1 v=targa|1 v=theora:libtheora|1 v=tiff|1 v=utvideo|1 v=v210|1 v=v308|1 v=v408|1 v=v410|1 v=vp8:libvpx|1 v=vp9:libvpx-vp9|1 v=wmv1|1 v=wmv2|1 v=y41p|1 v=yuv4|1 v=zlib|1 v=zmbv|1 a=aac|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=adpcm_g722:g722|1 a=adpcm_g726:g726|1 a=adpcm_ima_wav|1 a=adpcm_ms|1 a=adpcm_swf|1 a=adpcm_yamaha|1 a=alac|1 a=dts:dca|1 a=eac3|1 a=flac|1 a=g723_1|1 a=gsm_ms:libgsm_ms|1 a=mlp|1 a=mp2:mp2|1 a=mp2:mp2fixed|1 a=mp2:libtwolame|1 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=opus:opus|1 a=opus:libopus|1 a=pcm_alaw|1 a=pcm_f32le|1 a=pcm_f64le|1 a=pcm_mulaw|1 a=pcm_s16be|1 a=pcm_s16le|1 a=pcm_s24be|1 a=pcm_s24le|1 a=pcm_s32be|1 a=pcm_s32le|1 a=pcm_s64le|1 a=pcm_u8|1 a=ra_144:real_144|1 a=sonic|1 a=speex:libspeex|1 a=truehd|1 a=tta|1 a=vorbis:vorbis|1 a=vorbis:libvorbis|1 a=wavpack:wavpack|1 a=wavpack:libwavpack|1 a=wmav1|1 a=wmav2|1 mjpeg; v=mjpeg:mjpeg|1 mlp; a=mlp|1 mmf; a=adpcm_yamaha|1 -mov; v=amv|1 v=asv1|1 v=asv2|1 v=avrp|1 v=avui|1 v=ayuv|1 v=cinepak|1 v=cljr|1 v=dirac:vc2|1 v=dnxhd|1 v=dpx|1 v=dvvideo|1 v=ffv1|1 v=ffvhuff|1 v=flashsv|1 v=flv1:flv|1 v=gif|1 v=h261|1 v=h263:h263|1 v=h264:libx264|1 v=h264:libx264rgb|1 v=hap|1 v=hevc:libx265|1 v=huffyuv|1 v=jpeg2000:jpeg2000|1 v=jpeg2000:libopenjpeg|1 v=jpegls|1 v=magicyuv|1 v=mjpeg:mjpeg|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 v=msmpeg4v2|1 v=msmpeg4v3:msmpeg4|1 v=msvideo1|1 v=png|1 v=prores:prores|1 v=prores:prores_aw|1 v=prores:prores_ks|1 v=qtrle|1 v=r10k|1 v=r210|1 v=sgi|1 v=snow|1 v=svq1|1 v=targa|1 v=theora:libtheora|1 v=tiff|1 v=utvideo|1 v=v210|1 v=v308|1 v=v408|1 v=v410|1 v=wmv1|1 v=wmv2|1 v=y41p|1 v=yuv4|1 v=zlib|1 v=zmbv|0 a=aac|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=adpcm_g722:g722|1 a=adpcm_g726:g726|1 a=adpcm_ima_qt|1 a=adpcm_ima_wav|0 a=adpcm_ms|0 a=adpcm_swf|1 a=adpcm_yamaha|1 a=alac|1 a=dts:dca|1 a=eac3|1 a=g723_1|1 a=gsm:libgsm|1 a=gsm_ms:libgsm_ms|1 a=mp2:mp2|1 a=mp2:mp2fixed|1 a=mp2:libtwolame|1 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=nellymoser|1 a=pcm_alaw|1 a=pcm_f32be|1 a=pcm_f32le|1 a=pcm_f64be|1 a=pcm_f64le|1 a=pcm_mulaw|1 a=pcm_s16be|1 a=pcm_s16le|1 a=pcm_s24be|1 a=pcm_s24le|1 a=pcm_s32be|1 a=pcm_s32le|1 a=pcm_s8|1 a=pcm_u8|1 a=sonic|1 a=speex:libspeex|1 a=vorbis:vorbis|1 a=vorbis:libvorbis|1 +mov; v=amv|1 v=asv1|1 v=asv2|1 v=avrp|1 v=avui|1 v=ayuv|1 v=cinepak|1 v=cljr|1 v=dirac:vc2|1 v=dnxhd|1 v=dpx|1 v=dvvideo|1 v=ffv1|1 v=ffvhuff|1 v=flashsv|1 v=flv1:flv|1 v=h261|1 v=h263:h263|1 v=h264:libx264|1 v=h264:libx264rgb|1 v=hap|1 v=hevc:libx265|1 v=huffyuv|1 v=jpeg2000:jpeg2000|1 v=jpeg2000:libopenjpeg|1 v=jpegls|1 v=magicyuv|1 v=mjpeg:mjpeg|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 v=msmpeg4v2|1 v=msmpeg4v3:msmpeg4|1 v=msvideo1|1 v=png|1 v=prores:prores|1 v=prores:prores_aw|1 v=prores:prores_ks|1 v=qtrle|1 v=r10k|1 v=r210|1 v=sgi|1 v=snow|1 v=svq1|1 v=targa|1 v=theora:libtheora|1 v=tiff|1 v=utvideo|1 v=v210|1 v=v308|1 v=v408|1 v=v410|1 v=wmv1|1 v=wmv2|1 v=y41p|1 v=yuv4|1 v=zlib|1 v=zmbv|0 a=aac|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=adpcm_g722:g722|1 a=adpcm_g726:g726|1 a=adpcm_ima_qt|1 a=adpcm_ima_wav|0 a=adpcm_ms|0 a=adpcm_swf|1 a=adpcm_yamaha|1 a=alac|1 a=dts:dca|1 a=eac3|1 a=g723_1|1 a=gsm:libgsm|1 a=gsm_ms:libgsm_ms|1 a=mp2:mp2|1 a=mp2:mp2fixed|1 a=mp2:libtwolame|1 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=nellymoser|1 a=pcm_alaw|1 a=pcm_f32be|1 a=pcm_f32le|1 a=pcm_f64be|1 a=pcm_f64le|1 a=pcm_mulaw|1 a=pcm_s16be|1 a=pcm_s16le|1 a=pcm_s24be|1 a=pcm_s24le|1 a=pcm_s32be|1 a=pcm_s32le|1 a=pcm_s8|1 a=pcm_u8|1 a=sonic|1 a=speex:libspeex|1 a=vorbis:vorbis|1 a=vorbis:libvorbis|1 mp3; a=mp3:libmp3lame|1 a=mp3:libshine|1 mp4; v=av1:libaom-av1|1 v=dirac:vc2|1 v=h264:libx264|1 v=h264:libx264rgb|1 v=hevc:libx265|1 v=jpeg2000:jpeg2000|1 v=jpeg2000:libopenjpeg|1 v=mjpeg:mjpeg|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 v=png|1 v=vp9:libvpx-vp9|1 a=aac|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=dts:dca|1 a=eac3|1 a=flac|0 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=opus:opus|0 a=opus:libopus|0 a=vorbis:vorbis|1 a=vorbis:libvorbis|1 -mpeg; v=h264:libx264|1 v=h264:libx264rgb|1 v=hevc:libx265|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=dts:dca|1 a=mp2:mp2|1 a=mp2:mp2fixed|1 a=mp2:libtwolame|1 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=pcm_dvd|1 +mpeg; v=h264:libx264|1 v=h264:libx264rgb|1 v=hevc:libx265|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=dts:dca|1 a=mp2:mp2|1 a=mp2:mp2fixed|1 a=mp2:libtwolame|1 a=mp3:libmp3lame|1 a=mp3:libshine|1 mpegts; v=dirac:vc2|1 v=h264:libx264|1 v=h264:libx264rgb|1 v=hevc:libx265|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 a=aac|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=dts:dca|1 a=eac3|1 a=mp2:mp2|1 a=mp2:mp2fixed|1 a=mp2:libtwolame|1 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=opus:opus|1 a=opus:libopus|1 a=s302m|1 mpjpeg; v=mjpeg:mjpeg|1 -mxf; v=dnxhd|1 v=dvvideo|1 v=h264:libx264|1 v=h264:libx264rgb|1 v=jpeg2000:jpeg2000|1 v=jpeg2000:libopenjpeg|1 v=mpeg2video:mpeg2video|1 v=prores:prores|1 v=prores:prores_aw|1 -nut; v=amv|1 v=asv1|1 v=asv2|1 v=av1:libaom-av1|1 v=ayuv|1 v=cinepak|1 v=cljr|1 v=dirac:vc2|0 v=dpx|1 v=dvvideo|1 v=ffv1|1 v=ffvhuff|1 v=flashsv|1 v=flv1:flv|1 v=gif|1 v=h261|1 v=h263:h263|1 v=h264:libx264|1 v=h264:libx264rgb|1 v=hap|1 v=hevc:libx265|1 v=huffyuv|1 v=jpeg2000:jpeg2000|1 v=jpeg2000:libopenjpeg|1 v=jpegls|1 v=magicyuv|1 v=mjpeg:mjpeg|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 v=msmpeg4v2|1 v=msmpeg4v3:msmpeg4|1 v=msvideo1|1 v=png|1 v=prores:prores|1 v=prores:prores_aw|1 v=prores:prores_ks|1 v=r10k|1 v=r210|1 v=rawvideo|1 v=snow|1 v=svq1|1 v=targa|1 v=theora:libtheora|1 v=utvideo|1 v=v210|1 v=v308|1 v=v408|1 v=v410|1 v=vp8:libvpx|1 v=vp9:libvpx-vp9|1 v=wmv1|1 v=wmv2|1 v=xface|1 v=y41p|1 v=yuv4|1 v=zlib|1 v=zmbv|1 a=aac|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=adpcm_g722:g722|1 a=adpcm_ima_wav|1 a=adpcm_ms|1 a=adpcm_swf|1 a=adpcm_yamaha|1 a=dts:dca|1 a=flac|1 a=g723_1|1 a=gsm_ms:libgsm_ms|1 a=mp2:mp2|1 a=mp2:mp2fixed|1 a=mp2:libtwolame|1 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=opus:opus|1 a=opus:libopus|1 a=pcm_alaw|1 a=pcm_f32be|1 a=pcm_f32le|1 a=pcm_f64be|1 a=pcm_f64le|1 a=pcm_mulaw|1 a=pcm_s16be|1 a=pcm_s16be_planar|1 a=pcm_s16le|1 a=pcm_s16le_planar|1 a=pcm_s24be|1 a=pcm_s24le|1 a=pcm_s24le_planar|1 a=pcm_s32be|1 a=pcm_s32le|1 a=pcm_s32le_planar|1 a=pcm_s8|1 a=pcm_s8_planar|1 a=pcm_u16be|1 a=pcm_u16le|1 a=pcm_u24be|1 a=pcm_u24le|1 a=pcm_u32be|1 a=pcm_u32le|1 a=pcm_u8|1 a=sonic|1 a=speex:libspeex|1 a=vorbis:vorbis|1 a=vorbis:libvorbis|1 a=wavpack:wavpack|1 a=wavpack:libwavpack|1 +mxf; v=dnxhd|1 v=dvvideo|1 v=h264:libx264|1 v=h264:libx264rgb|1 v=jpeg2000:jpeg2000|1 v=jpeg2000:libopenjpeg|1 v=mpeg2video:mpeg2video|1 +nut; v=amv|1 v=asv1|1 v=asv2|1 v=av1:libaom-av1|1 v=ayuv|1 v=cinepak|1 v=cljr|1 v=dirac:vc2|0 v=dpx|1 v=dvvideo|1 v=ffv1|1 v=ffvhuff|1 v=flashsv|1 v=flv1:flv|1 v=h261|1 v=h263:h263|1 v=h264:libx264|1 v=h264:libx264rgb|1 v=hap|1 v=hevc:libx265|1 v=huffyuv|1 v=jpeg2000:jpeg2000|1 v=jpeg2000:libopenjpeg|1 v=jpegls|1 v=magicyuv|1 v=mjpeg:mjpeg|1 v=mpeg1video|1 v=mpeg2video:mpeg2video|1 v=mpeg4:mpeg4|1 v=mpeg4:libxvid|1 v=msmpeg4v2|1 v=msmpeg4v3:msmpeg4|1 v=msvideo1|1 v=png|1 v=prores:prores|1 v=prores:prores_aw|1 v=prores:prores_ks|1 v=r10k|1 v=r210|1 v=rawvideo|1 v=snow|1 v=svq1|1 v=targa|1 v=theora:libtheora|1 v=utvideo|1 v=v210|1 v=v308|1 v=v408|1 v=v410|1 v=vp8:libvpx|1 v=vp9:libvpx-vp9|1 v=wmv1|1 v=wmv2|1 v=xface|1 v=y41p|1 v=yuv4|1 v=zlib|1 v=zmbv|1 a=aac|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=adpcm_g722:g722|1 a=adpcm_ima_wav|1 a=adpcm_ms|1 a=adpcm_swf|1 a=adpcm_yamaha|1 a=dts:dca|1 a=flac|1 a=g723_1|1 a=gsm_ms:libgsm_ms|1 a=mp2:mp2|1 a=mp2:mp2fixed|1 a=mp2:libtwolame|1 a=mp3:libmp3lame|1 a=mp3:libshine|1 a=opus:opus|1 a=opus:libopus|1 a=pcm_alaw|1 a=pcm_f32be|1 a=pcm_f32le|1 a=pcm_f64be|1 a=pcm_f64le|1 a=pcm_mulaw|1 a=pcm_s16be|1 a=pcm_s16be_planar|1 a=pcm_s16le|1 a=pcm_s16le_planar|1 a=pcm_s24be|1 a=pcm_s24le|1 a=pcm_s24le_planar|1 a=pcm_s32be|1 a=pcm_s32le|1 a=pcm_s32le_planar|1 a=pcm_s8|1 a=pcm_s8_planar|1 a=pcm_u16be|1 a=pcm_u16le|1 a=pcm_u24be|1 a=pcm_u24le|1 a=pcm_u32be|1 a=pcm_u32le|1 a=pcm_u8|1 a=sonic|1 a=speex:libspeex|1 a=vorbis:vorbis|1 a=vorbis:libvorbis|1 a=wavpack:wavpack|1 a=wavpack:libwavpack|1 ogg; v=theora:libtheora|1 v=vp8:libvpx|1 a=flac|1 a=opus:opus|1 a=opus:libopus|1 a=speex:libspeex|1 a=vorbis:vorbis|1 a=vorbis:libvorbis|1 rm; v=rv10|1 v=rv20|1 a=aac|1 a=ac3:ac3|1 a=ac3:ac3_fixed|1 a=ra_144:real_144|1 roq; v=roq:roqvideo|0 a=roq_dpcm|1 diff -Nru ffmpeg-4.2.2/debian/tests/examples ffmpeg-4.4/debian/tests/examples --- ffmpeg-4.2.2/debian/tests/examples 2020-01-25 16:22:32.000000000 +0000 +++ ffmpeg-4.4/debian/tests/examples 2021-05-25 10:09:13.000000000 +0000 @@ -4,17 +4,12 @@ # build the examples -echo "AUTOPKGTEST_TMP directory: $AUTOPKGTEST_TMP" +echo "ADTTMP directory: $AUTOPKGTEST_TMP" cd "$AUTOPKGTEST_TMP" cp -r /usr/share/doc/ffmpeg/examples ./ cd examples -if [ -n "$DEB_HOST_MULTIARCH" ]; then - export CC="$DEB_HOST_GNU_TYPE-gcc" - export PKG_CONFIG_PATH="/usr/lib/$DEB_HOST_MULTIARCH/pkgconfig" -fi - echo "building the examples..." ret=0 make -k all 2>&1 diff -Nru ffmpeg-4.2.2/doc/APIchanges ffmpeg-4.4/doc/APIchanges --- ffmpeg-4.2.2/doc/APIchanges 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/APIchanges 2021-04-08 21:28:39.000000000 +0000 @@ -15,6 +15,251 @@ API changes, most recent first: +-------- 8< --------- FFmpeg 4.4 was cut here -------- 8< --------- + +2021-03-19 - e8c0bca6bd - lavu 56.69.100 - adler32.h + Added a typedef for the type of the Adler-32 checksums + used by av_adler32_update(). It will be changed to uint32_t + at the next major bump. + The type of the parameter for the length of the input buffer + will also be changed to size_t at the next major bump. + +2021-03-19 - e318438f2f - lavf 58.75.100 - avformat.h + AVChapter.id will be changed from int to int64_t + on the next major version bump. + +2021-03-17 - f7db77bd87 - lavc 58.133.100 - codec.h + Deprecated av_init_packet(). Once removed, sizeof(AVPacket) will + no longer be a part of the public ABI. + Deprecated AVPacketList. + +2021-03-16 - 7d09579190 - lavc 58.132.100 - codec.h + Add AV_CODEC_CAP_OTHER_THREADS as a new name for + AV_CODEC_CAP_AUTO_THREADS. AV_CODEC_CAP_AUTO_THREADS + is now deprecated. + +2021-03-12 - 6e7e3a3820 - lavc 58.131.100 - avcodec.h codec.h + Add a get_encode_buffer callback to AVCodecContext, similar to + get_buffer2 but for encoders. + Add avcodec_default_get_encode_buffer(). + Add AV_GET_ENCODE_BUFFER_FLAG_REF. + Encoders may now be flagged as AV_CODEC_CAP_DR1 capable. + +2021-03-10 - 42e68fe015 - lavf 58.72.100 - avformat.h + Change AVBufferRef related AVStream function and struct size + parameter and fields type to size_t at next major bump. + +2021-03-10 - d79e0fe65c - lavc 58.130.100 - packet.h + Change AVBufferRef related AVPacket function and struct size + parameter and fields type to size_t at next major bump. + +2021-03-10 - 14040a1d91 - lavu 56.68.100 - buffer.h frame.h + Change AVBufferRef and relevant AVFrame function and struct size + parameter and fields type to size_t at next major bump. + +2021-03-04 - a0eec776b6 - lavc 58.128.101 - avcodec.h + Enable err_recognition to be set for encoders. + +2021-03-03 - 2ff40b98ec - lavf 58.70.100 - avformat.h + Deprecate AVFMT_FLAG_PRIV_OPT. It will do nothing + as soon as av_demuxer_open() is removed. + +2021-02-27 - dd9227e48f - lavc 58.126.100 - avcodec.h + Deprecated avcodec_get_frame_class(). + +2021-02-21 - 5ca40d6d94 - lavu 56.66.100 - tx.h + Add enum AVTXFlags and AVTXFlags.AV_TX_INPLACE + +2021-02-14 - 4f49ca7bbc - lavd 58.12.100 - avdevice.h + Deprecated avdevice_capabilities_create() and + avdevice_capabilities_free(). + +2021-02-10 - 1bda9bb68a - lavu 56.65.100 - common.h + Add FFABS64U() + +2021-01-26 - 5dd9567080 - lavu 56.64.100 - common.h + Add FFABSU() + +2021-01-25 - 56709ca8aa - lavc 58.119.100 - avcodec.h + Deprecate AVCodecContext.debug_mv, FF_DEBUG_VIS_MV_P_FOR, FF_DEBUG_VIS_MV_B_FOR, + FF_DEBUG_VIS_MV_B_BACK + +2021-01-11 - ebdd33086a - lavc 58.116.100 - avcodec.h + Add FF_PROFILE_VVC_MAIN_10 and FF_PROFILE_VVC_MAIN_10_444. + +2020-01-01 - baecaa16c1 - lavu 56.63.100 - video_enc_params.h + Add AV_VIDEO_ENC_PARAMS_MPEG2 + +2020-12-03 - eca12f4d5a - lavu 56.62.100 - timecode.h + Add av_timecode_init_from_components. + +2020-11-27 - a83098ab03 - lavc 58.114.100 - avcodec.h + Deprecate AVCodecContext.thread_safe_callbacks. Starting with + LIBAVCODEC_VERSION_MAJOR=60, user callbacks must always be + thread-safe when frame threading is used. + +2020-11-25 - d243dd540a - lavc 58.113.100 - avcodec.h + Adds a new flag AV_CODEC_EXPORT_DATA_FILM_GRAIN for export_side_data. + +2020-11-25 - 4f9ee87253 - lavu 56.61.100 - film_grain_params.h + Adds a new API for extracting codec film grain parameters as side data. + Adds a new AVFrameSideDataType entry AV_FRAME_DATA_FILM_GRAIN_PARAMS for it. + +2020-10-28 - f95d9510ff - lavf 58.64.100 - avformat.h + Add AVSTREAM_EVENT_FLAG_NEW_PACKETS. + +2020-09-28 - 68918d3b7f - lavu 56.60.100 - buffer.h + Add a av_buffer_replace() convenience function. + +2020-09-13 - 837b6eb90e - lavu 56.59.100 - timecode.h + Add av_timecode_make_smpte_tc_string2. + +2020-08-21 - 06f2651204 - lavu 56.58.100 - avstring.h + Deprecate av_d2str(). Use av_asprintf() instead. + +2020-08-04 - 34de0abbe7 - lavu 56.58.100 - channel_layout.h + Add AV_CH_LAYOUT_22POINT2 together with its newly required pieces: + AV_CH_TOP_SIDE_LEFT, AV_CH_TOP_SIDE_RIGHT, AV_CH_BOTTOM_FRONT_CENTER, + AV_CH_BOTTOM_FRONT_LEFT, AV_CH_BOTTOM_FRONT_RIGHT. + +2020-07-23 - 84655b7101 - lavu 56.57.100 - cpu.h + Add AV_CPU_FLAG_MMI and AV_CPU_FLAG_MSA. + +2020-07-22 - 3a8e927176 - lavu 56.56.100 - imgutils.h + Add av_image_fill_plane_sizes(). + +2020-07-15 - 448a9aaa78 - lavc 58.96.100 - packet.h + Add AV_PKT_DATA_S12M_TIMECODE. + +2020-06-12 - b09fb030c1 - lavu 56.55.100 - pixdesc.h + Add AV_PIX_FMT_X2RGB10. + +2020-06-11 - bc8ab084fb - lavu 56.54.100 - frame.h + Add AV_FRAME_DATA_SEI_UNREGISTERED. + +2020-06-10 - 1b4a98b029 - lavu 56.53.100 - log.h opt.h + Add av_opt_child_class_iterate() and AVClass.child_class_iterate(). + Deprecate av_opt_child_class_next() and AVClass.child_class_next(). + +-------- 8< --------- FFmpeg 4.3 was cut here -------- 8< --------- + +2020-06-05 - ec39c2276a - lavu 56.50.100 - buffer.h + Passing NULL as alloc argument to av_buffer_pool_init2() is now allowed. + +2020-05-27 - ba6cada92e - lavc 58.88.100 - avcodec.h codec.h + Move AVCodec-related public API to new header codec.h. + +2020-05-23 - 064b875e89 - lavu 56.49.100 - video_enc_params.h + Add AV_VIDEO_ENC_PARAMS_H264. + +2020-05-23 - 2e08b39444 - lavu 56.48.100 - hwcontext.h + Add av_hwdevice_ctx_create_derived_opts. + +2020-05-23 - 6b65c4ec54 - lavu 56.47.100 - rational.h + Add av_gcd_q(). + +2020-05-22 - af9e622776 - lavu 56.46.101 - opt.h + Add AV_OPT_FLAG_CHILD_CONSTS. + +2020-05-22 - 9d443c3e68 - lavc 58.87.100 - avcodec.h codec_par.h + Move AVBitstreamFilter-related public API to new header bsf.h. + Move AVCodecParameters-related public API to new header codec_par.h. + +2020-05-21 - 13b1bbff0b - lavc 58.86.101 - avcodec.h + Deprecated AV_CODEC_CAP_INTRA_ONLY and AV_CODEC_CAP_LOSSLESS. + +2020-05-17 - 84af196c65 - lavu 56.46.100 - common.h + Add av_sat_add64() and av_sat_sub64() + +2020-05-12 - 991d417692 - lavu 56.45.100 - video_enc_params.h + lavc 58.84.100 - avcodec.h + Add a new API for exporting video encoding information. + Replaces the deprecated API for exporting QP tables from decoders. + Add AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS to request this information from + decoders. + +2020-05-10 - dccd07f66d - lavu 56.44.100 - hwcontext_vulkan.h + Add enabled_inst_extensions, num_enabled_inst_extensions, enabled_dev_extensions + and num_enabled_dev_extensions fields to AVVulkanDeviceContext + +2020-04-22 - 0e1db79e37 - lavc 58.81.100 - packet.h + - lavu 56.43.100 - dovi_meta.h + Add AV_PKT_DATA_DOVI_CONF and AVDOVIDecoderConfigurationRecord. + +2020-04-15 - 22b25b3ea5 - lavc 58.79.100 - avcodec.h + Add formal support for calling avcodec_flush_buffers() on encoders. + Encoders that set the cap AV_CODEC_CAP_ENCODER_FLUSH will be flushed. + For all other encoders, the call is now a no-op rather than undefined + behaviour. + +2020-04-10 - 672946c7fe - lavc 58.78.100 - avcodec.h codec_desc.h codec_id.h packet.h + Move AVCodecDesc-related public API to new header codec_desc.h. + Move AVCodecID enum to new header codec_id.h. + Move AVPacket-related public API to new header packet.h. + +2020-03-29 - 4cb0dda555 - lavf 58.42.100 - avformat.h + av_read_frame() now guarantees to handle uninitialized input packets + and to return refcounted packets on success. + +2020-03-27 - c52ec0367d - lavc 58.77.100 - avcodec.h + av_packet_ref() now guarantees to return the destination packet + in a blank state on error. + +2020-03-10 - 05d27f342b - lavc 58.75.100 - avcodec.h + Add AV_PKT_DATA_ICC_PROFILE. + +2020-02-21 - d005a7cdfd - lavc 58.73.101 - avcodec.h + Add AV_CODEC_EXPORT_DATA_PRFT. + +2020-02-21 - c666689491 - lavc 58.73.100 - avcodec.h + Add AVCodecContext.export_side_data and AV_CODEC_EXPORT_DATA_MVS. + +2020-02-13 - e8f054b095 - lavu 56.41.100 - tx.h + Add AV_TX_INT32_FFT and AV_TX_INT32_MDCT + +2020-02-12 - 3182114f88 - lavu 56.40.100 - log.h + Add av_log_once(). + +2020-02-04 - a88449ffb2 - lavu 56.39.100 - hwcontext.h + Add AV_PIX_FMT_VULKAN + Add AV_HWDEVICE_TYPE_VULKAN and implementation. + +2020-01-30 - 27529eeb27 - lavf 58.37.100 - avio.h + Add avio_protocol_get_class(). + +2020-01-15 - 717b2074ec - lavc 58.66.100 - avcodec.h + Add AV_PKT_DATA_PRFT and AVProducerReferenceTime. + +2019-12-27 - 45259a0ee4 - lavu 56.38.100 - eval.h + Add av_expr_count_func(). + +2019-12-26 - 16685114d5 - lavu 56.37.100 - buffer.h + Add av_buffer_pool_buffer_get_opaque(). + +2019-11-17 - 1c23abc88f - lavu 56.36.100 - eval API + Add av_expr_count_vars(). + +2019-10-14 - f3746d31f9 - lavu 56.35.101 - opt.h + Add AV_OPT_FLAG_RUNTIME_PARAM. + +2019-09-25 - f8406ab4b9 - lavc 58.59.100 - avcodec.h + Add max_samples + +2019-09-04 - 2a9d461abc - lavu 56.35.100 - hwcontext_videotoolbox.h + Add av_map_videotoolbox_format_from_pixfmt2() for full range pixfmt + +2019-09-01 - 8821d1f56e - lavu 56.34.100 - pixfmt.h + Add EBU Tech. 3213-E AVColorPrimaries value + +2019-08-17 - 95fa73a2b4 - lavf 58.31.101 - avio.h + 4K limit removed from avio_printf. + +2019-08-17 - a82f8f2f10 - lavf 58.31.100 - avio.h + Add avio_print_string_array and avio_print. + +2019-07-27 - 42e2319ba9 - lavu 56.33.100 - tx.h + Add AV_TX_DOUBLE_FFT and AV_TX_DOUBLE_MDCT + -------- 8< --------- FFmpeg 4.2 was cut here -------- 8< --------- 2019-06-21 - a30e44098a - lavu 56.30.100 - frame.h diff -Nru ffmpeg-4.2.2/doc/bitstream_filters.texi ffmpeg-4.4/doc/bitstream_filters.texi --- ffmpeg-4.2.2/doc/bitstream_filters.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/bitstream_filters.texi 2021-04-08 21:28:39.000000000 +0000 @@ -224,6 +224,10 @@ @item sample_aspect_ratio Set the sample aspect ratio of the stream in the VUI parameters. +@item overscan_appropriate_flag +Set whether the stream is suitable for display using overscan +or not (see H.264 section E.2.1). + @item video_format @item video_full_range_flag Set the video format in the stream (see H.264 section E.2.1 and @@ -544,6 +548,36 @@ @section null This bitstream filter passes the packets through unchanged. +@section pcm_rechunk + +Repacketize PCM audio to a fixed number of samples per packet or a fixed packet +rate per second. This is similar to the @ref{asetnsamples,,asetnsamples audio +filter,ffmpeg-filters} but works on audio packets instead of audio frames. + +@table @option +@item nb_out_samples, n +Set the number of samples per each output audio packet. The number is intended +as the number of samples @emph{per each channel}. Default value is 1024. + +@item pad, p +If set to 1, the filter will pad the last audio packet with silence, so that it +will contain the same number of samples (or roughly the same number of samples, +see @option{frame_rate}) as the previous ones. Default value is 1. + +@item frame_rate, r +This option makes the filter output a fixed number of packets per second instead +of a fixed number of samples per packet. If the audio sample rate is not +divisible by the frame rate then the number of samples will not be constant but +will vary slightly so that each packet will start as close to the frame +boundary as possible. Using this option has precedence over @option{nb_out_samples}. +@end table + +You can generate the well known 1602-1601-1602-1601-1602 pattern of 48kHz audio +for NTSC frame rate using the @option{frame_rate} option. +@example +ffmpeg -f lavfi -i sine=r=48000:d=1 -c pcm_s16le -bsf pcm_rechunk=r=30000/1001 -f framecrc - +@end example + @section prores_metadata Modify color property metadata embedded in prores stream. @@ -585,6 +619,10 @@ @item unknown @item bt709 BT 601, BT 709, BT 2020 +@item smpte2084 +SMPTE ST 2084 +@item arib-std-b67 +ARIB STD-B67 @end table @@ -594,7 +632,7 @@ @table @samp @item auto -Keep the same transfer characteristics property (default). +Keep the same colorspace property (default). @item unknown @item bt709 @@ -610,6 +648,11 @@ ffmpeg -i INPUT -c copy -bsf:v prores_metadata=color_primaries=bt709:color_trc=bt709:colorspace=bt709 output.mov @end example +Set Hybrid Log-Gamma parameters for each frame of the file +@example +ffmpeg -i INPUT -c copy -bsf:v prores_metadata=color_primaries=bt2020:color_trc=arib-std-b67:colorspace=bt2020nc output.mov +@end example + @section remove_extra Remove extradata from packets. @@ -632,6 +675,63 @@ @end table @end table +@section setts +Set PTS and DTS in packets. + +It accepts the following parameters: +@table @option +@item ts +@item pts +@item dts +Set expressions for PTS, DTS or both. +@end table + +The expressions are evaluated through the eval API and can contain the following +constants: + +@table @option +@item N +The count of the input packet. Starting from 0. + +@item TS +The demux timestamp in input in case of @code{ts} or @code{dts} option or presentation +timestamp in case of @code{pts} option. + +@item POS +The original position in the file of the packet, or undefined if undefined +for the current packet + +@item DTS +The demux timestamp in input. + +@item PTS +The presentation timestamp in input. + +@item STARTDTS +The DTS of the first packet. + +@item STARTPTS +The PTS of the first packet. + +@item PREV_INDTS +The previous input DTS. + +@item PREV_INPTS +The previous input PTS. + +@item PREV_OUTDTS +The previous output DTS. + +@item PREV_OUTPTS +The previous output PTS. + +@item TB +The timebase of stream packet belongs. + +@item SR +The sample rate of stream packet belongs. +@end table + @anchor{text2movsub} @section text2movsub @@ -659,7 +759,9 @@ @table @option @item color_space -Set the color space value in the frame header. +Set the color space value in the frame header. Note that any frame +set to RGB will be implicitly set to PC range and that RGB is +incompatible with profiles 0 and 2. @table @samp @item unknown @item bt601 @@ -671,8 +773,8 @@ @end table @item color_range -Set the color range value in the frame header. Note that this cannot -be set in RGB streams. +Set the color range value in the frame header. Note that any value +imposed by the color space will take precedence over this value. @table @samp @item tv @item pc diff -Nru ffmpeg-4.2.2/doc/build_system.txt ffmpeg-4.4/doc/build_system.txt --- ffmpeg-4.2.2/doc/build_system.txt 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/build_system.txt 2020-07-11 10:39:30.000000000 +0000 @@ -48,6 +48,8 @@ tools/target_dec__fuzzer Build fuzzer to fuzz the specified decoder. +tools/target_bsf__fuzzer + Build fuzzer to fuzz the specified bitstream filter. Useful standard make commands: make -t diff -Nru ffmpeg-4.2.2/doc/codecs.texi ffmpeg-4.4/doc/codecs.texi --- ffmpeg-4.2.2/doc/codecs.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/codecs.texi 2021-04-08 21:28:39.000000000 +0000 @@ -50,11 +50,10 @@ Use internal 2pass ratecontrol in second pass mode. @item gray Only decode/encode grayscale. -@item emu_edge -Do not draw edges. @item psnr Set error[?] variables during encoding. @item truncated +Input bitstream might be randomly truncated. @item drop_changed Don't output frames whose parameters differ from first decoded frame in stream. Error AVERROR_INPUT_CHANGED is returned when a frame is dropped. @@ -71,50 +70,14 @@ platforms. Its primary use is for regression testing. @item aic Apply H263 advanced intra coding / mpeg4 ac prediction. -@item cbp -Deprecated, use mpegvideo private options instead. -@item qprd -Deprecated, use mpegvideo private options instead. @item ilme Apply interlaced motion estimation. @item cgop Use closed gop. +@item output_corrupt +Output even potentially corrupted frames. @end table -@item me_method @var{integer} (@emph{encoding,video}) -Set motion estimation method. - -Possible values: -@table @samp -@item zero -zero motion estimation (fastest) -@item full -full motion estimation (slowest) -@item epzs -EPZS motion estimation (default) -@item esa -esa motion estimation (alias for full) -@item tesa -tesa motion estimation -@item dia -dia motion estimation (alias for epzs) -@item log -log motion estimation -@item phods -phods motion estimation -@item x1 -X1 motion estimation -@item hex -hex motion estimation -@item umh -umh motion estimation -@item iter -iter motion estimation -@end table - -@item extradata_size @var{integer} -Set extradata size. - @item time_base @var{rational number} Set codec time base. @@ -181,9 +144,6 @@ @item b_qfactor @var{float} (@emph{encoding,video}) Set qp factor between P and B frames. -@item rc_strategy @var{integer} (@emph{encoding,video}) -Set ratecontrol method. - @item b_strategy @var{integer} (@emph{encoding,video}) Set strategy to choose between I/P/B-frames. @@ -207,8 +167,6 @@ @table @samp @item autodetect -@item old_msmpeg4 -some old lavc generated msmpeg4v3 files (no autodetection) @item xvid_ilace Xvid interlacing bug (autodetected if fourcc==XVIX) @item ump4 @@ -217,8 +175,6 @@ padding bug (autodetected) @item amv -@item ac_vlc -illegal vlc bug (autodetected per fourcc) @item qpel_chroma @item std_qpel @@ -239,14 +195,6 @@ trancated frames @end table -@item lelim @var{integer} (@emph{encoding,video}) -Set single coefficient elimination threshold for luminance (negative -values also consider DC coefficient). - -@item celim @var{integer} (@emph{encoding,video}) -Set single coefficient elimination threshold for chrominance (negative -values also consider dc coefficient) - @item strict @var{integer} (@emph{decoding/encoding,audio,video}) Specify how strictly to follow the standards. @@ -303,26 +251,8 @@ @item mpeg_quant @var{integer} (@emph{encoding,video}) Use MPEG quantizers instead of H.263. -@item qsquish @var{float} (@emph{encoding,video}) -How to keep quantizer between qmin and qmax (0 = clip, 1 = use -differentiable function). - -@item rc_qmod_amp @var{float} (@emph{encoding,video}) -Set experimental quantizer modulation. - -@item rc_qmod_freq @var{integer} (@emph{encoding,video}) -Set experimental quantizer modulation. - @item rc_override_count @var{integer} -@item rc_eq @var{string} (@emph{encoding,video}) -Set rate control equation. When computing the expression, besides the -standard functions defined in the section 'Expression Evaluation', the -following functions are available: bits2qp(bits), qp2bits(qp). Also -the following constants are available: iTex pTex tex mv fCode iCount -mcVar var isI isP isB avgQP qComp avgIITex avgPITex avgPPTex avgBPTex -avgTex. - @item maxrate @var{integer} (@emph{encoding,audio,video}) Set max bitrate tolerance (in bits/s). Requires bufsize to be set. @@ -333,18 +263,12 @@ @item bufsize @var{integer} (@emph{encoding,audio,video}) Set ratecontrol buffer size (in bits). -@item rc_buf_aggressivity @var{float} (@emph{encoding,video}) -Currently useless. - @item i_qfactor @var{float} (@emph{encoding,video}) Set QP factor between P and I frames. @item i_qoffset @var{float} (@emph{encoding,video}) Set QP offset between P and I frames. -@item rc_init_cplx @var{float} (@emph{encoding,video}) -Set initial complexity for 1-pass encoding. - @item dct @var{integer} (@emph{encoding,video}) Set DCT algorithm. @@ -409,11 +333,7 @@ @item simpleneon -@item simplealpha - -@item ipp - -@item xvidmmx +@item xvid @item faani floating point AAN IDCT @@ -643,6 +563,24 @@ @item dia_size @var{integer} (@emph{encoding,video}) Set diamond type & size for motion estimation. +@table @samp +@item (1024, INT_MAX) +full motion estimation(slowest) +@item (768, 1024] +umh motion estimation +@item (512, 768] +hex motion estimation +@item (256, 512] +l2s diamond motion estimation +@item [2,256] +var diamond motion estimation +@item (-1, 2) +small diamond motion estimation +@item -1 +funny diamond motion estimation +@item (INT_MIN, -1) +sab diamond motion estimation +@end table @item last_pred @var{integer} (@emph{encoding,video}) Set amount of motion predictors from the previous frame. @@ -693,19 +631,9 @@ @item subq @var{integer} (@emph{encoding,video}) Set sub pel motion estimation quality. -@item dtg_active_format @var{integer} - @item me_range @var{integer} (@emph{encoding,video}) Set limit motion vectors range (1023 for DivX player). -@item ibias @var{integer} (@emph{encoding,video}) -Set intra quant bias. - -@item pbias @var{integer} (@emph{encoding,video}) -Set inter quant bias. - -@item color_table_id @var{integer} - @item global_quality @var{integer} (@emph{encoding,audio,video}) @item coder @var{integer} (@emph{encoding,video}) @@ -720,8 +648,6 @@ raw (no encoding) @item rle run-length coder -@item deflate -deflate-based coder @end table @item context @var{integer} (@emph{encoding,video}) @@ -742,17 +668,9 @@ use best rate distortion @end table -@item stream_codec_tag @var{integer} - @item sc_threshold @var{integer} (@emph{encoding,video}) Set scene change threshold. -@item lmin @var{integer} (@emph{encoding,video}) -Set min lagrange factor (VBR). - -@item lmax @var{integer} (@emph{encoding,video}) -Set max lagrange factor (VBR). - @item nr @var{integer} (@emph{encoding,video}) Set noise reduction. @@ -760,14 +678,12 @@ Set number of bits which should be loaded into the rc buffer before decoding starts. -@item flags2 @var{flags} (@emph{decoding/encoding,audio,video}) +@item flags2 @var{flags} (@emph{decoding/encoding,audio,video,subtitles}) Possible values: @table @samp @item fast Allow non spec compliant speedup tricks. -@item sgop -Deprecated, use mpegvideo private options instead. @item noout Skip bitstream encoding. @item ignorecrop @@ -781,12 +697,29 @@ @item export_mvs Export motion vectors into frame side-data (see @code{AV_FRAME_DATA_MOTION_VECTORS}) for codecs that support it. See also @file{doc/examples/export_mvs.c}. +@item skip_manual +Do not skip samples and export skip information as frame side data. +@item ass_ro_flush_noop +Do not reset ASS ReadOrder field on flush. @end table -@item error @var{integer} (@emph{encoding,video}) +@item export_side_data @var{flags} (@emph{decoding/encoding,audio,video,subtitles}) -@item qns @var{integer} (@emph{encoding,video}) -Deprecated, use mpegvideo private options instead. +Possible values: +@table @samp +@item mvs +Export motion vectors into frame side-data (see @code{AV_FRAME_DATA_MOTION_VECTORS}) +for codecs that support it. See also @file{doc/examples/export_mvs.c}. +@item prft +Export encoder Producer Reference Time into packet side-data (see @code{AV_PKT_DATA_PRFT}) +for codecs that support it. +@item venc_params +Export video encoding parameters through frame side data (see @code{AV_FRAME_DATA_VIDEO_ENC_PARAMS}) +for codecs that support it. At present, those are H.264 and VP9. +@item film_grain +Export film grain parameters through frame side data (see @code{AV_FRAME_DATA_FILM_GRAIN_PARAMS}). +Supported at present by AV1 decoders. +@end table @item threads @var{integer} (@emph{decoding/encoding,video}) Set the number of threads to be used, in case the selected codec @@ -800,12 +733,6 @@ Default value is @samp{auto}. -@item me_threshold @var{integer} (@emph{encoding,video}) -Set motion estimation threshold. - -@item mb_threshold @var{integer} (@emph{encoding,video}) -Set macroblock threshold. - @item dc @var{integer} (@emph{encoding,video}) Set intra_dc_precision. @@ -820,49 +747,8 @@ @item profile @var{integer} (@emph{encoding,audio,video}) -Possible values: -@table @samp -@item unknown - -@item aac_main - -@item aac_low - -@item aac_ssr - -@item aac_ltp - -@item aac_he - -@item aac_he_v2 - -@item aac_ld - -@item aac_eld - -@item mpeg2_aac_low - -@item mpeg2_aac_he - -@item mpeg4_sp - -@item mpeg4_core - -@item mpeg4_main - -@item mpeg4_asp - -@item dts - -@item dts_es - -@item dts_96_24 - -@item dts_hd_hra - -@item dts_hd_ma - -@end table +Set encoder codec profile. Default value is @samp{unknown}. Encoder specific +profiles are documented in the relevant encoder documentation. @item level @var{integer} (@emph{encoding,audio,video}) @@ -924,9 +810,6 @@ @end table -@item border_mask @var{float} (@emph{encoding,video}) -Increase the quantizer for macroblocks close to borders. - @item mblmin @var{integer} (@emph{encoding,video}) Set min macroblock lagrange factor (VBR). @@ -1000,9 +883,6 @@ @item timecode_frame_start @var{integer} (@emph{encoding,video}) Set GOP timecode frame start number, in non drop frame format. -@item request_channels @var{integer} (@emph{decoding,audio}) -Set desired number of audio channels. - @item bits_per_raw_sample @var{integer} @item channel_layout @var{integer} (@emph{decoding/encoding,audio}) @@ -1116,6 +996,12 @@ BT.2020 CL @item smpte2085 SMPTE 2085 +@item chroma-derived-nc +Chroma-derived NCL +@item chroma-derived-c +Chroma-derived CL +@item ictcp +ICtCp @end table @item color_range @var{integer} (@emph{decoding/encoding,video}) diff -Nru ffmpeg-4.2.2/doc/decoders.texi ffmpeg-4.4/doc/decoders.texi --- ffmpeg-4.2.2/doc/decoders.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/decoders.texi 2021-04-08 21:28:39.000000000 +0000 @@ -25,6 +25,19 @@ A description of some of the currently available video decoders follows. +@section av1 + +AOMedia Video 1 (AV1) decoder. + +@subsection Options + +@table @option + +@item operating_point +Select an operating point of a scalable AV1 bitstream (0 - 31). Default is 0. + +@end table + @section rawvideo Raw video decoder. @@ -57,7 +70,7 @@ @subsection Options -The following option is supported by the libdav1d wrapper. +The following options are supported by the libdav1d wrapper. @table @option @@ -68,8 +81,15 @@ Set amount of tile threads to use during decoding. The default value is 0 (autodetect). @item filmgrain -Apply film grain to the decoded video if present in the bitstream. The default value -is true. +Apply film grain to the decoded video if present in the bitstream. Defaults to the +internal default of the library. + +@item oppoint +Select an operating point of a scalable AV1 bitstream (0 - 31). Defaults to the +internal default of the library. + +@item alllayers +Output all spatial layers of a scalable AV1 bitstream. The default value is false. @end table @@ -81,6 +101,27 @@ @c man end VIDEO DECODERS +@section libuavs3d + +AVS3-P2/IEEE1857.10 video decoder. + +libuavs3d allows libavcodec to decode AVS3 streams. +Requires the presence of the libuavs3d headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libuavs3d}. + +@subsection Options + +The following option is supported by the libuavs3d wrapper. + +@table @option + +@item frame_threads +Set amount of frame threads to use during decoding. The default value is 0 (autodetect). + +@end table + +@c man end VIDEO DECODERS + @chapter Audio Decoders @c man begin AUDIO DECODERS @@ -100,7 +141,7 @@ @item -drc_scale @var{value} Dynamic Range Scale Factor. The factor to apply to dynamic range values -from the AC-3 stream. This factor is applied exponentially. +from the AC-3 stream. This factor is applied exponentially. The default value is 1. There are 3 notable scale factor ranges: @table @option @item drc_scale == 0 @@ -280,7 +321,7 @@ from dumped VOB files. The format for this option is a string containing 16 24-bits hexadecimal -numbers (without 0x prefix) separated by comas, for example @code{0d00ee, +numbers (without 0x prefix) separated by commas, for example @code{0d00ee, ee450d, 101010, eaeaea, 0ce60b, ec14ed, ebff0b, 0d617a, 7b7b7b, d1d1d1, 7b2a0e, 0d950c, 0f007b, cf0dec, cfa80c, 7c127b}. @@ -309,6 +350,11 @@ list are dropped. You may use the special @code{*} string to match all pages, or @code{subtitle} to match all subtitle pages. Default value is *. +@item txt_default_region +Set default character set used for decoding, a value between 0 and 87 (see +ETS 300 706, Section 15, Table 32). Default value is -1, which does not +override the libzvbi default. This option is needed for some legacy level 1.0 +transmissions which cannot signal the proper charset. @item txt_chop_top Discards the top teletext line. Default value is 1. @item txt_format diff -Nru ffmpeg-4.2.2/doc/demuxers.texi ffmpeg-4.4/doc/demuxers.texi --- ffmpeg-4.2.2/doc/demuxers.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/demuxers.texi 2020-07-11 10:39:30.000000000 +0000 @@ -331,6 +331,10 @@ Maximum number of times a insufficient list is attempted to be reloaded. Default value is 1000. +@item m3u8_hold_counters +The maximum number of times to load m3u8 when it refreshes without new segments. +Default value is 1000. + @item http_persistent Use persistent HTTP connections. Applicable only for HTTP streams. Enabled by default. @@ -338,6 +342,10 @@ @item http_multiple Use multiple HTTP connections for downloading HTTP segments. Enabled by default for HTTP/1.1 servers. + +@item http_seekable +Use HTTP partial requests for downloading HTTP segments. +0 = disable, 1 = enable, -1 = auto, Default is auto. @end table @section image2 @@ -448,6 +456,17 @@ @item video_size Set the video size of the images to read. If not specified the video size is guessed from the first image file in the sequence. +@item export_path_metadata +If set to 1, will add two extra fields to the metadata found in input, making them +also available for other filters (see @var{drawtext} filter for examples). Default +value is 0. The extra fields are described below: +@table @option +@item lavf.image2dec.source_path +Corresponds to the full path to the input file being read. +@item lavf.image2dec.source_basename +Corresponds to the name of the file being read. +@end table + @end table @subsection Examples @@ -585,9 +604,13 @@ Range is from 1000 to INT_MAX. The value default is 48000. @end table -@section mov/mp4/3gp/QuickTime +@section mov/mp4/3gp + +Demuxer for Quicktime File Format & ISO/IEC Base Media File Format (ISO/IEC 14496-12 or MPEG-4 Part 12, ISO/IEC 15444-12 or JPEG 2000 Part 12). -QuickTime / MP4 demuxer. +Registered extensions: mov, mp4, m4a, 3gp, 3g2, mj2, psp, m4b, ism, ismv, isma, f4v + +@subsection Options This demuxer accepts the following options: @table @option @@ -598,10 +621,73 @@ @item use_absolute_path Allows loading of external tracks via absolute paths, disabled by default. Enabling this poses a security risk. It should only be enabled if the source -is known to be non malicious. +is known to be non-malicious. + +@item seek_streams_individually +When seeking, identify the closest point in each stream individually and demux packets in +that stream from identified point. This can lead to a different sequence of packets compared +to demuxing linearly from the beginning. Default is true. + +@item ignore_editlist +Ignore any edit list atoms. The demuxer, by default, modifies the stream index to reflect the +timeline described by the edit list. Default is false. + +@item advanced_editlist +Modify the stream index to reflect the timeline described by the edit list. @code{ignore_editlist} +must be set to false for this option to be effective. +If both @code{ignore_editlist} and this option are set to false, then only the +start of the stream index is modified to reflect initial dwell time or starting timestamp +described by the edit list. Default is true. + +@item ignore_chapters +Don't parse chapters. This includes GoPro 'HiLight' tags/moments. Note that chapters are +only parsed when input is seekable. Default is false. + +@item use_mfra_for +For seekable fragmented input, set fragment's starting timestamp from media fragment random access box, if present. + +Following options are available: +@table @samp +@item auto +Auto-detect whether to set mfra timestamps as PTS or DTS @emph{(default)} +@item dts +Set mfra timestamps as DTS + +@item pts +Set mfra timestamps as PTS + +@item 0 +Don't use mfra box to set timestamps +@end table + +@item export_all +Export unrecognized boxes within the @var{udta} box as metadata entries. The first four +characters of the box type are set as the key. Default is false. + +@item export_xmp +Export entire contents of @var{XMP_} box and @var{uuid} box as a string with key @code{xmp}. Note that +if @code{export_all} is set and this option isn't, the contents of @var{XMP_} box are still exported +but with key @code{XMP_}. Default is false. + +@item activation_bytes +4-byte key required to decrypt Audible AAX and AAX+ files. See Audible AAX subsection below. + +@item audible_fixed_key +Fixed key used for handling Audible AAX/AAX+ files. It has been pre-set so should not be necessary to +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). @end table +@subsection Audible AAX + +Audible AAX files are encrypted M4B files, and they can be decrypted by specifying a 4 byte activation secret. +@example +ffmpeg -activation_bytes 1CEB00DA -i test.aax -vn -c:a copy output.mp4 +@end example + @section mpegts MPEG-2 transport stream demuxer. diff -Nru ffmpeg-4.2.2/doc/dev_community/community.md ffmpeg-4.4/doc/dev_community/community.md --- ffmpeg-4.2.2/doc/dev_community/community.md 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/doc/dev_community/community.md 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,79 @@ +# FFmpeg project + +## Organisation + +The FFmpeg project is organized through a community working on global consensus. + +Decisions are taken by the ensemble of active members, through voting and +are aided by two committees. + +## General Assembly + +The ensemble of active members is called the General Assembly (GA). + +The General Assembly is sovereign and legitimate for all its decisions +regarding the FFmpeg project. + +The General Assembly is made up of active contributors. + +Contributors are considered "active contributors" if they have pushed more +than 20 patches in the last 36 months in the main FFmpeg repository, or +if they have been voted in by the GA. + +Additional members are added to the General Assembly through a vote after +proposal by a member of the General Assembly. +They are part of the GA for two years, after which they need a confirmation by +the GA. + +## Voting + +Voting is done using a ranked voting system, currently running on https://vote.ffmpeg.org/ . + +Majority vote means more than 50% of the expressed ballots. + +## Technical Committee + +The Technical Committee (TC) is here to arbitrate and make decisions when +technical conflicts occur in the project. +They will consider the merits of all the positions, judge them and make a +decision. + +The TC resolves technical conflicts but is not a technical steering committee. + +Decisions by the TC are binding for all the contributors. + +Decisions made by the TC can be re-opened after 1 year or by a majority vote +of the General Assembly, requested by one of the member of the GA. + +The TC is elected by the General Assembly for a duration of 1 year, and +is composed of 5 members. +Members can be re-elected if they wish. A majority vote in the General Assembly +can trigger a new election of the TC. + +The members of the TC can be elected from outside of the GA. +Candidates for election can either be suggested or self-nominated. + +The conflict resolution process is detailed in the [resolution process](resolution_process.md) document. + +## Community committee + +The Community Committee (CC) is here to arbitrage and make decisions when +inter-personal conflicts occur in the project. It will decide quickly and +take actions, for the sake of the project. + +The CC can remove privileges of offending members, including removal of +commit access and temporary ban from the community. + +Decisions made by the CC can be re-opened after 1 year or by a majority vote +of the General Assembly. Indefinite bans from the community must be confirmed +by the General Assembly, in a majority vote. + +The CC is elected by the General Assembly for a duration of 1 year, and is +composed of 5 members. +Members can be re-elected if they wish. A majority vote in the General Assembly +can trigger a new election of the CC. + +The members of the CC can be elected from outside of the GA. +Candidates for election can either be suggested or self-nominated. + +The CC is governed by and responsible for enforcing the Code of Conduct. diff -Nru ffmpeg-4.2.2/doc/dev_community/resolution_process.md ffmpeg-4.4/doc/dev_community/resolution_process.md --- ffmpeg-4.2.2/doc/dev_community/resolution_process.md 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/doc/dev_community/resolution_process.md 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,91 @@ +# Technical Committee + +_This document only makes sense with the rules from [the community document](community)_. + +The Technical Committee (**TC**) is here to arbitrate and make decisions when +technical conflicts occur in the project. + +The TC main role is to resolve technical conflicts. +It is therefore not a technical steering committee, but it is understood that +some decisions might impact the future of the project. + +# Process + +## Seizing + +The TC can take possession of any technical matter that it sees fit. + +To involve the TC in a matter, email tc@ or CC them on an ongoing discussion. + +As members of TC are developers, they also can email tc@ to raise an issue. + +## Announcement + +The TC, once seized, must announce itself on the main mailing list, with a _[TC]_ tag. + +The TC has 2 modes of operation: a RFC one and an internal one. + +If the TC thinks it needs the input from the larger community, the TC can call +for a RFC. Else, it can decide by itself. + +If the disagreement involves a member of the TC, that member should recuse +themselves from the decision. + +The decision to use a RFC process or an internal discussion is a discretionary +decision of the TC. + +The TC can also reject a seizure for a few reasons such as: +the matter was not discussed enough previously; it lacks expertise to reach a +beneficial decision on the matter; or the matter is too trivial. + +### RFC call + +In the RFC mode, one person from the TC posts on the mailing list the +technical question and will request input from the community. + +The mail will have the following specification: +* a precise title +* a specific tag [TC RFC] +* a top-level email +* contain a precise question that does not exceed 100 words and that is answerable by developers +* may have an extra description, or a link to a previous discussion, if deemed necessary, +* contain a precise end date for the answers. + +The answers from the community must be on the main mailing list and must have +the following specification: +* keep the tag and the title unchanged +* limited to 400 words +* a first-level, answering directly to the main email +* answering to the question. + +Further replies to answers are permitted, as long as they conform to the +community standards of politeness, they are limited to 100 words, and are not +nested more than once. (max-depth=2) + +After the end-date, mails on the thread will be ignored. + +Violations of those rules will be escalated through the Community Committee. + +After all the emails are in, the TC has 96 hours to give its final decision. +Exceptionally, the TC can request an extra delay, that will be notified on the +mailing list. + +### Within TC + +In the internal case, the TC has 96 hours to give its final decision. +Exceptionally, the TC can request an extra delay. + + +## Decisions + +The decisions from the TC will be sent on the mailing list, with the _[TC]_ tag. + +Internally, the TC should take decisions with a majority, or using +ranked-choice voting. + +The decision from the TC should be published with a summary of the reasons that +lead to this decision. + +The decisions from the TC are final, until the matters are reopened after +no less than one year. + diff -Nru ffmpeg-4.2.2/doc/developer.texi ffmpeg-4.4/doc/developer.texi --- ffmpeg-4.2.2/doc/developer.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/developer.texi 2020-07-11 10:39:30.000000000 +0000 @@ -132,6 +132,9 @@ for loops with variable definition (@samp{for (int i = 0; i < 8; i++)}); @item +Variadic macros (@samp{#define ARRAY(nb, ...) (int[nb + 1])@{ nb, __VA_ARGS__ @}}); + +@item Implementation defined behavior for signed integers is assumed to match the expected behavior for two's complement. Non representable values in integer casts are binary truncated. Shift right of signed values uses sign extension. @@ -622,7 +625,7 @@ If the patch fixes a bug, did you provide enough information, including a sample, so the bug can be reproduced and the fix can be verified? Note please do not attach samples >100k to mails but rather provide a -URL, you can upload to ftp://upload.ffmpeg.org. +URL, you can upload to @url{https://streams.videolan.org/upload/}. @item Did you provide a verbose summary about what the patch does change? diff -Nru ffmpeg-4.2.2/doc/Doxyfile ffmpeg-4.4/doc/Doxyfile --- ffmpeg-4.2.2/doc/Doxyfile 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/doc/Doxyfile 2021-04-08 21:28:39.000000000 +0000 @@ -38,7 +38,7 @@ # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.2.2 +PROJECT_NUMBER = 4.4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff -Nru ffmpeg-4.2.2/doc/encoders.texi ffmpeg-4.4/doc/encoders.texi --- ffmpeg-4.2.2/doc/encoders.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/encoders.texi 2021-04-08 21:28:39.000000000 +0000 @@ -30,11 +30,7 @@ Advanced Audio Coding (AAC) encoder. -This encoder is the default AAC encoder, natively implemented into FFmpeg. Its -quality is on par or better than libfdk_aac at the default bitrate of 128kbps. -This encoder also implements more options, profiles and samplerates than -other encoders (with only the AAC-HE profile pending to be implemented) so this -encoder has become the default and is the recommended choice. +This encoder is the default AAC encoder, natively implemented into FFmpeg. @subsection Options @@ -155,10 +151,9 @@ The @var{ac3} encoder uses floating-point math, while the @var{ac3_fixed} encoder only uses fixed-point integer math. This does not mean that one is always faster, just that one or the other may be better suited to a -particular system. The floating-point encoder will generally produce better -quality audio for a given bitrate. The @var{ac3_fixed} encoder is not the -default codec for any of the output formats, so it must be specified explicitly -using the option @code{-acodec ac3_fixed} in order to use it. +particular system. The @var{ac3_fixed} encoder is not the default codec for +any of the output formats, so it must be specified explicitly using the option +@code{-acodec ac3_fixed} in order to use it. @subsection AC-3 Metadata @@ -651,10 +646,7 @@ so if you allow the use of GPL, you should configure with @code{--enable-gpl --enable-nonfree --enable-libfdk-aac}. -This encoder is considered to produce output on par or worse at 128kbps to the -@ref{aacenc,,the native FFmpeg AAC encoder} but can often produce better -sounding audio at identical or lower bitrates and has support for the -AAC-HE profiles. +This encoder has support for the AAC-HE profiles. VBR encoding, enabled through the @option{vbr} or @option{flags +qscale} options, is experimental and only works with some @@ -960,6 +952,11 @@ @item packet_loss (@emph{expect-loss}) Set expected packet loss percentage. The default is 0. +@item fec (@emph{n/a}) +Enable inband forward error correction. @option{packet_loss} must be non-zero +to take advantage - frequency of FEC 'side-data' is proportional to expected packet loss. +Default is disabled. + @item application (N.A.) Set intended application type. Valid options are listed below: @@ -1187,53 +1184,6 @@ @end table -@anchor{libwavpack} -@section libwavpack - -A wrapper providing WavPack encoding through libwavpack. - -Only lossless mode using 32-bit integer samples is supported currently. - -Requires the presence of the libwavpack headers and library during -configuration. You need to explicitly configure the build with -@code{--enable-libwavpack}. - -Note that a libavcodec-native encoder for the WavPack codec exists so users can -encode audios with this codec without using this encoder. See @ref{wavpackenc}. - -@subsection Options - -@command{wavpack} command line utility's corresponding options are listed in -parentheses, if any. - -@table @option -@item frame_size (@emph{--blocksize}) -Default is 32768. - -@item compression_level -Set speed vs. compression tradeoff. Acceptable arguments are listed below: - -@table @samp -@item 0 (@emph{-f}) -Fast mode. - -@item 1 -Normal (default) settings. - -@item 2 (@emph{-h}) -High quality. - -@item 3 (@emph{-hh}) -Very high quality. - -@item 4-8 (@emph{-hh -x}@var{EXTRAPROC}) -Same as @samp{3}, but with extra processing enabled. - -@samp{4} is the same as @option{-x2} and @samp{8} is the same as @option{-x6}. - -@end table -@end table - @anchor{mjpegenc} @section mjpeg @@ -1260,11 +1210,6 @@ WavPack lossless audio encoder. -This is a libavcodec-native WavPack encoder. There is also an encoder based on -libwavpack, but there is virtually no reason to use that encoder. - -See also @ref{libwavpack}. - @subsection Options The equivalent options for @command{wavpack} command line utility are listed in @@ -1285,7 +1230,6 @@ @file{libavcodec/wavpackenc.c}. @item compression_level (@emph{-f}, @emph{-h}, @emph{-hh}, and @emph{-x}) -This option's syntax is consistent with @ref{libwavpack}'s. @end table @subsubsection Private options @@ -1324,6 +1268,44 @@ A description of some of the currently available video encoders follows. +@section GIF + +GIF image/animation encoder. + +@subsection Options + +@table @option +@item gifflags @var{integer} +Sets the flags used for GIF encoding. + +@table @option +@item offsetting +Enables picture offsetting. + +Default is enabled. + +@item transdiff +Enables transparency detection between frames. + +Default is enabled. + +@end table + +@item gifimage @var{integer} +Enables encoding one full GIF image per frame, rather than an animated GIF. + +Default value is @option{0}. + +@item global_palette @var{integer} +Writes a palette to the global GIF header where feasible. + +If disabled, every frame will always have a palette written, even if there +is a global palette supplied. + +Default value is @option{1}. + +@end table + @section Hap Vidvox Hap video encoder. @@ -1372,10 +1354,101 @@ @subsection Options @table @option -@item format +@item format @var{integer} Can be set to either @code{j2k} or @code{jp2} (the default) that makes it possible to store non-rgb pix_fmts. +@item tile_width @var{integer} +Sets tile width. Range is 1 to 1073741824. Default is 256. + +@item tile_height @var{integer} +Sets tile height. Range is 1 to 1073741824. Default is 256. + +@item pred @var{integer} +Allows setting the discrete wavelet transform (DWT) type +@table @option +@item dwt97int (Lossy) +@item dwt53 (Lossless) +@end table +Default is @code{dwt97int} + +@item sop @var{boolean} +Enable this to add SOP marker at the start of each packet. Disabled by default. + +@item eph @var{boolean} +Enable this to add EPH marker at the end of each packet header. Disabled by default. + +@item prog @var{integer} +Sets the progression order to be used by the encoder. +Possible values are: +@table @option +@item lrcp +@item rlcp +@item rpcl +@item pcrl +@item cprl +@end table +Set to @code{lrcp} by default. + +@item layer_rates @var{string} +By default, when this option is not used, compression is done using the quality metric. +This option allows for compression using compression ratio. The compression ratio for each +level could be specified. The compression ratio of a layer @code{l} species the what ratio of +total file size is contained in the first @code{l} layers. + +Example usage: + +@example +ffmpeg -i input.bmp -c:v jpeg2000 -layer_rates "100,10,1" output.j2k +@end example + +This would compress the image to contain 3 layers, where the data contained in the +first layer would be compressed by 1000 times, compressed by 100 in the first two layers, +and shall contain all data while using all 3 layers. + +@end table + +@section librav1e + +rav1e AV1 encoder wrapper. + +Requires the presence of the rav1e headers and library during configuration. +You need to explicitly configure the build with @code{--enable-librav1e}. + +@subsection Options + +@table @option +@item qmax +Sets the maximum quantizer to use when using bitrate mode. + +@item qmin +Sets the minimum quantizer to use when using bitrate mode. + +@item qp +Uses quantizer mode to encode at the given quantizer (0-255). + +@item speed +Selects the speed preset (0-10) to encode with. + +@item tiles +Selects how many tiles to encode with. + +@item tile-rows +Selects how many rows of tiles to encode with. + +@item tile-columns +Selects how many columns of tiles to encode with. + +@item rav1e-params +Set rav1e options using a list of @var{key}=@var{value} pairs separated +by ":". See @command{rav1e --help} for a list of options. + +For example to specify librav1e encoding options with @option{-rav1e-params}: + +@example +ffmpeg -i input -c:v librav1e -b:v 500K -rav1e-params speed=5:low_latency=true output.mp4 +@end example + @end table @section libaom-av1 @@ -1465,6 +1538,15 @@ Cyclic refresh. @end table +@item tune (@emph{tune}) +Set the distortion metric the encoder is tuned with. Default is @code{psnr}. + +@table @samp +@item psnr (@emph{0}) + +@item ssim (@emph{1}) +@end table + @item lag-in-frames Set the maximum number of frames which the encoder may keep in flight at any one time for lookahead purposes. Defaults to the internal @@ -1544,6 +1626,9 @@ Enable Constrained Directional Enhancement Filter. The libaom-av1 encoder enables CDEF by default. +@item enable-restoration (@emph{boolean}) +Enable Loop Restoration Filter. Default is true for libaom-av1. + @item enable-global-motion (@emph{boolean}) Enable the use of global motion for block prediction. Default is true. @@ -1551,6 +1636,165 @@ Enable block copy mode for intra block prediction. This mode is useful for screen content. Default is true. +@item enable-rect-partitions (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable rectangular partitions. Default is true. + +@item enable-1to4-partitions (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable 1:4/4:1 partitions. Default is true. + +@item enable-ab-partitions (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable AB shape partitions. Default is true. + +@item enable-angle-delta (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable angle delta intra prediction. Default is true. + +@item enable-cfl-intra (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable chroma predicted from luma intra prediction. Default is true. + +@item enable-filter-intra (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable filter intra predictor. Default is true. + +@item enable-intra-edge-filter (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable intra edge filter. Default is true. + +@item enable-smooth-intra (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable smooth intra prediction mode. Default is true. + +@item enable-paeth-intra (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable paeth predictor in intra prediction. Default is true. + +@item enable-palette (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable palette prediction mode. Default is true. + +@item enable-flip-idtx (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable extended transform type, including FLIPADST_DCT, DCT_FLIPADST, +FLIPADST_FLIPADST, ADST_FLIPADST, FLIPADST_ADST, IDTX, V_DCT, H_DCT, +V_ADST, H_ADST, V_FLIPADST, H_FLIPADST. Default is true. + +@item enable-tx64 (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable 64-pt transform. Default is true. + +@item reduced-tx-type-set (@emph{boolean}) (Requires libaom >= v2.0.0) +Use reduced set of transform types. Default is false. + +@item use-intra-dct-only (@emph{boolean}) (Requires libaom >= v2.0.0) +Use DCT only for INTRA modes. Default is false. + +@item use-inter-dct-only (@emph{boolean}) (Requires libaom >= v2.0.0) +Use DCT only for INTER modes. Default is false. + +@item use-intra-default-tx-only (@emph{boolean}) (Requires libaom >= v2.0.0) +Use Default-transform only for INTRA modes. Default is false. + +@item enable-ref-frame-mvs (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable temporal mv prediction. Default is true. + +@item enable-reduced-reference-set (@emph{boolean}) (Requires libaom >= v2.0.0) +Use reduced set of single and compound references. Default is false. + +@item enable-obmc (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable obmc. Default is true. + +@item enable-dual-filter (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable dual filter. Default is true. + +@item enable-diff-wtd-comp (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable difference-weighted compound. Default is true. + +@item enable-dist-wtd-comp (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable distance-weighted compound. Default is true. + +@item enable-onesided-comp (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable one sided compound. Default is true. + +@item enable-interinter-wedge (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable interinter wedge compound. Default is true. + +@item enable-interintra-wedge (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable interintra wedge compound. Default is true. + +@item enable-masked-comp (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable masked compound. Default is true. + +@item enable-interintra-comp (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable interintra compound. Default is true. + +@item enable-smooth-interintra (@emph{boolean}) (Requires libaom >= v2.0.0) +Enable smooth interintra mode. Default is true. + +@item aom-params +Set libaom options using a list of @var{key}=@var{value} pairs separated +by ":". For a list of supported options, see @command{aomenc --help} under the +section "AV1 Specific Options". + +For example to specify libaom encoding options with @option{-aom-params}: + +@example +ffmpeg -i input -c:v libaom-av1 -b:v 500K -aom-params tune=psnr:enable-tpl-model=1 output.mp4 +@end example + +@end table + +@section libsvtav1 + +SVT-AV1 encoder wrapper. + +Requires the presence of the SVT-AV1 headers and library during configuration. +You need to explicitly configure the build with @code{--enable-libsvtav1}. + +@subsection Options + +@table @option +@item profile +Set the encoding profile. + +@item level +Set the operating point level. + +@item tier +Set the operating point tier. + +@item rc +Set the rate control mode to use. + +Possible modes: +@table @option +@item cqp +Constant quantizer: use fixed values of qindex (dependent on the frame type) +throughout the stream. This mode is the default. + +@item vbr +Variable bitrate: use a target bitrate for the whole stream. + +@item cvbr +Constrained variable bitrate: use a target bitrate for each GOP. +@end table + +@item qmax +Set the maximum quantizer to use when using a bitrate mode. + +@item qmin +Set the minimum quantizer to use when using a bitrate mode. + +@item qp +Set the quantizer used in cqp rate control mode (0-63). + +@item sc_detection +Enable scene change detection. + +@item la_depth +Set number of frames to look ahead (0-120). + +@item preset +Set the quality-speed tradeoff, in the range 0 to 8. Higher values are +faster but lower quality. Defaults to 8 (highest speed). + +@item tile_rows +Set log2 of the number of rows of tiles to use (0-6). + +@item tile_columns +Set log2 of the number of columns of tiles to use (0-4). + @end table @section libkvazaar @@ -1842,16 +2086,14 @@ Increase sharpness at the expense of lower PSNR. The valid range is [0, 7]. -@item VP8-specific options -@table @option @item ts-parameters Sets the temporal scalability configuration using a :-separated list of key=value pairs. For example, to specify temporal scalability parameters with @code{ffmpeg}: @example ffmpeg -i INPUT -c:v libvpx -ts-parameters ts_number_layers=3:\ -ts_target_bitrate=250000,500000,1000000:ts_rate_decimator=4,2,1:\ -ts_periodicity=4:ts_layer_id=0,2,1,2 OUTPUT +ts_target_bitrate=250,500,1000:ts_rate_decimator=4,2,1:\ +ts_periodicity=4:ts_layer_id=0,2,1,2:ts_layering_mode=3 OUTPUT @end example Below is a brief explanation of each of the parameters, please refer to @code{struct vpx_codec_enc_cfg} in @code{vpx/vpx_encoder.h} for more @@ -1860,13 +2102,38 @@ @item ts_number_layers Number of temporal coding layers. @item ts_target_bitrate -Target bitrate for each temporal layer. +Target bitrate for each temporal layer (in kbps). +(bitrate should be inclusive of the lower temporal layer). @item ts_rate_decimator Frame rate decimation factor for each temporal layer. @item ts_periodicity Length of the sequence defining frame temporal layer membership. @item ts_layer_id Template defining the membership of frames to temporal layers. +@item ts_layering_mode +(optional) Selecting the temporal structure from a set of pre-defined temporal layering modes. +Currently supports the following options. +@table @option +@item 0 +No temporal layering flags are provided internally, +relies on flags being passed in using @code{metadata} field in @code{AVFrame} +with following keys. +@table @option +@item vp8-flags +Sets the flags passed into the encoder to indicate the referencing scheme for +the current frame. +Refer to function @code{vpx_codec_encode} in @code{vpx/vpx_encoder.h} for more +details. +@item temporal_id +Explicitly sets the temporal id of the current frame to encode. +@end table +@item 2 +Two temporal layers. 0-1... +@item 3 +Three temporal layers. 0-2-1-2...; with single reference frame. +@item 4 +Same as option "3", except there is a dependency between +the two temporal layer 2 frames within the temporal period. @end table @end table @@ -1910,6 +2177,38 @@ The valid range is [0, 10000]. 0 (default) uses standard VBR. @item enable-tpl @var{boolean} Enable temporal dependency model. +@item ref-frame-config +Using per-frame metadata, set members of the structure @code{vpx_svc_ref_frame_config_t} in @code{vpx/vp8cx.h} to fine-control referencing schemes and frame buffer management. +@*Use a :-separated list of key=value pairs. +For example, +@example +av_dict_set(&av_frame->metadata, "ref-frame-config", \ +"rfc_update_buffer_slot=7:rfc_lst_fb_idx=0:rfc_gld_fb_idx=1:rfc_alt_fb_idx=2:rfc_reference_last=0:rfc_reference_golden=0:rfc_reference_alt_ref=0"); +@end example +@table @option +@item rfc_update_buffer_slot +Indicates the buffer slot number to update +@item rfc_update_last +Indicates whether to update the LAST frame +@item rfc_update_golden +Indicates whether to update GOLDEN frame +@item rfc_update_alt_ref +Indicates whether to update ALT_REF frame +@item rfc_lst_fb_idx +LAST frame buffer index +@item rfc_gld_fb_idx +GOLDEN frame buffer index +@item rfc_alt_fb_idx +ALT_REF frame buffer index +@item rfc_reference_last +Indicates whether to reference LAST frame +@item rfc_reference_golden +Indicates whether to reference GOLDEN frame +@item rfc_reference_alt_ref +Indicates whether to reference ALT_REF frame +@item rfc_reference_duration +Indicates frame duration +@end table @end table @end table @@ -2006,9 +2305,7 @@ @subsection Supported Pixel Formats x264 supports 8- to 10-bit color spaces. The exact bit depth is controlled at -x264's configure time. FFmpeg only supports one bit depth in one particular -build. In other words, it is not possible to build one FFmpeg with multiple -versions of x264 with different bit depths. +x264's configure time. @subsection Options @@ -2371,6 +2668,20 @@ @subsection Options @table @option +@item b +Sets target video bitrate. + +@item bf + +@item g +Set the GOP size. + +@item keyint_min +Minimum GOP size. + +@item refs +Number of reference frames each P-frame can use. The range is from @var{1-16}. + @item preset Set the x265 preset. @@ -2383,6 +2694,28 @@ @item crf Set the quality for constant quality mode. +@item qp +Set constant quantization rate control method parameter. + +@item qmin +Minimum quantizer scale. + +@item qmax +Maximum quantizer scale. + +@item qdiff +Maximum difference between quantizer scales. + +@item qblur +Quantizer curve blur + +@item qcomp +Quantizer curve compression factor + +@item i_qfactor + +@item b_qfactor + @item forced-idr Normally, when forcing a I-frame type, the encoder can select any type of I-frame. This option forces it to choose an IDR-frame. @@ -2618,6 +2951,14 @@ @end table +@section MediaFoundation + +This provides wrappers to encoders (both audio and video) in the +MediaFoundation framework. It can access both SW and HW encoders. +Video encoders can take input in either of nv12 or yuv420p form +(some encoders support both, some support only either - in practice, +nv12 is the safer choice, especially among HW encoders). + @section mpeg2 MPEG-2 video encoder. @@ -2625,6 +2966,30 @@ @subsection Options @table @option +@item profile +Select the mpeg2 profile to encode: + +@table @samp +@item 422 +@item high +@item ss +Spatially Scalable +@item snr +SNR Scalable +@item main +@item simple +@end table + +@item level +Select the mpeg2 level to encode: + +@table @samp +@item high +@item high1440 +@item main +@item low +@end table + @item seq_disp_ext @var{integer} Specifies if the encoder should write a sequence_display_extension to the output. @@ -2733,7 +3098,7 @@ @section QSV encoders -The family of Intel QuickSync Video encoders (MPEG-2, H.264 and HEVC) +The family of Intel QuickSync Video encoders (MPEG-2, H.264, HEVC, JPEG/MJPEG and VP9) The ratecontrol method is selected as follows: @@ -2986,6 +3351,11 @@ messages). @end table +@item tiles +Set the number of tiles to encode the input video with, as columns x rows. +Larger numbers allow greater parallelism in both encoding and decoding, but +may decrease coding efficiency. + @end table @item mjpeg_vaapi @@ -3116,6 +3486,14 @@ @subsection Options @table @option +@item palette +Specify the global palette used by the bitmaps. + +The format for this option is a string containing 16 24-bits hexadecimal +numbers (without 0x prefix) separated by commas, for example @code{0d00ee, +ee450d, 101010, eaeaea, 0ce60b, ec14ed, ebff0b, 0d617a, 7b7b7b, d1d1d1, +7b2a0e, 0d950c, 0f007b, cf0dec, cfa80c, 7c127b}. + @item even_rows_fix When set to 1, enable a work-around that makes the number of pixel rows even in all subtitles. This fixes a problem with some players that diff -Nru ffmpeg-4.2.2/doc/examples/avio_dir_cmd.c ffmpeg-4.4/doc/examples/avio_dir_cmd.c --- ffmpeg-4.2.2/doc/examples/avio_dir_cmd.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/examples/avio_dir_cmd.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2014 Lukasz Marek - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -static const char *type_string(int type) -{ - switch (type) { - case AVIO_ENTRY_DIRECTORY: - return ""; - case AVIO_ENTRY_FILE: - return ""; - case AVIO_ENTRY_BLOCK_DEVICE: - return ""; - case AVIO_ENTRY_CHARACTER_DEVICE: - return ""; - case AVIO_ENTRY_NAMED_PIPE: - return ""; - case AVIO_ENTRY_SYMBOLIC_LINK: - return ""; - case AVIO_ENTRY_SOCKET: - return ""; - case AVIO_ENTRY_SERVER: - return ""; - case AVIO_ENTRY_SHARE: - return ""; - case AVIO_ENTRY_WORKGROUP: - return ""; - case AVIO_ENTRY_UNKNOWN: - default: - break; - } - return ""; -} - -static int list_op(const char *input_dir) -{ - AVIODirEntry *entry = NULL; - AVIODirContext *ctx = NULL; - int cnt, ret; - char filemode[4], uid_and_gid[20]; - - if ((ret = avio_open_dir(&ctx, input_dir, NULL)) < 0) { - av_log(NULL, AV_LOG_ERROR, "Cannot open directory: %s.\n", av_err2str(ret)); - goto fail; - } - - cnt = 0; - for (;;) { - if ((ret = avio_read_dir(ctx, &entry)) < 0) { - av_log(NULL, AV_LOG_ERROR, "Cannot list directory: %s.\n", av_err2str(ret)); - goto fail; - } - if (!entry) - break; - if (entry->filemode == -1) { - snprintf(filemode, 4, "???"); - } else { - snprintf(filemode, 4, "%3"PRIo64, entry->filemode); - } - snprintf(uid_and_gid, 20, "%"PRId64"(%"PRId64")", entry->user_id, entry->group_id); - if (cnt == 0) - av_log(NULL, AV_LOG_INFO, "%-9s %12s %30s %10s %s %16s %16s %16s\n", - "TYPE", "SIZE", "NAME", "UID(GID)", "UGO", "MODIFIED", - "ACCESSED", "STATUS_CHANGED"); - av_log(NULL, AV_LOG_INFO, "%-9s %12"PRId64" %30s %10s %s %16"PRId64" %16"PRId64" %16"PRId64"\n", - type_string(entry->type), - entry->size, - entry->name, - uid_and_gid, - filemode, - entry->modification_timestamp, - entry->access_timestamp, - entry->status_change_timestamp); - avio_free_directory_entry(&entry); - cnt++; - }; - - fail: - avio_close_dir(&ctx); - return ret; -} - -static int del_op(const char *url) -{ - int ret = avpriv_io_delete(url); - if (ret < 0) - av_log(NULL, AV_LOG_ERROR, "Cannot delete '%s': %s.\n", url, av_err2str(ret)); - return ret; -} - -static int move_op(const char *src, const char *dst) -{ - int ret = avpriv_io_move(src, dst); - if (ret < 0) - av_log(NULL, AV_LOG_ERROR, "Cannot move '%s' into '%s': %s.\n", src, dst, av_err2str(ret)); - return ret; -} - - -static void usage(const char *program_name) -{ - fprintf(stderr, "usage: %s OPERATION entry1 [entry2]\n" - "API example program to show how to manipulate resources " - "accessed through AVIOContext.\n" - "OPERATIONS:\n" - "list list content of the directory\n" - "move rename content in directory\n" - "del delete content in directory\n", - program_name); -} - -int main(int argc, char *argv[]) -{ - const char *op = NULL; - int ret; - - av_log_set_level(AV_LOG_DEBUG); - - if (argc < 2) { - usage(argv[0]); - return 1; - } - - avformat_network_init(); - - op = argv[1]; - if (strcmp(op, "list") == 0) { - if (argc < 3) { - av_log(NULL, AV_LOG_INFO, "Missing argument for list operation.\n"); - ret = AVERROR(EINVAL); - } else { - ret = list_op(argv[2]); - } - } else if (strcmp(op, "del") == 0) { - if (argc < 3) { - av_log(NULL, AV_LOG_INFO, "Missing argument for del operation.\n"); - ret = AVERROR(EINVAL); - } else { - ret = del_op(argv[2]); - } - } else if (strcmp(op, "move") == 0) { - if (argc < 4) { - av_log(NULL, AV_LOG_INFO, "Missing argument for move operation.\n"); - ret = AVERROR(EINVAL); - } else { - ret = move_op(argv[2], argv[3]); - } - } else { - av_log(NULL, AV_LOG_INFO, "Invalid operation %s\n", op); - ret = AVERROR(EINVAL); - } - - avformat_network_deinit(); - - return ret < 0 ? 1 : 0; -} diff -Nru ffmpeg-4.2.2/doc/examples/avio_list_dir.c ffmpeg-4.4/doc/examples/avio_list_dir.c --- ffmpeg-4.2.2/doc/examples/avio_list_dir.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/doc/examples/avio_list_dir.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2014 Lukasz Marek + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +static const char *type_string(int type) +{ + switch (type) { + case AVIO_ENTRY_DIRECTORY: + return ""; + case AVIO_ENTRY_FILE: + return ""; + case AVIO_ENTRY_BLOCK_DEVICE: + return ""; + case AVIO_ENTRY_CHARACTER_DEVICE: + return ""; + case AVIO_ENTRY_NAMED_PIPE: + return ""; + case AVIO_ENTRY_SYMBOLIC_LINK: + return ""; + case AVIO_ENTRY_SOCKET: + return ""; + case AVIO_ENTRY_SERVER: + return ""; + case AVIO_ENTRY_SHARE: + return ""; + case AVIO_ENTRY_WORKGROUP: + return ""; + case AVIO_ENTRY_UNKNOWN: + default: + break; + } + return ""; +} + +static int list_op(const char *input_dir) +{ + AVIODirEntry *entry = NULL; + AVIODirContext *ctx = NULL; + int cnt, ret; + char filemode[4], uid_and_gid[20]; + + if ((ret = avio_open_dir(&ctx, input_dir, NULL)) < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot open directory: %s.\n", av_err2str(ret)); + goto fail; + } + + cnt = 0; + for (;;) { + if ((ret = avio_read_dir(ctx, &entry)) < 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot list directory: %s.\n", av_err2str(ret)); + goto fail; + } + if (!entry) + break; + if (entry->filemode == -1) { + snprintf(filemode, 4, "???"); + } else { + snprintf(filemode, 4, "%3"PRIo64, entry->filemode); + } + snprintf(uid_and_gid, 20, "%"PRId64"(%"PRId64")", entry->user_id, entry->group_id); + if (cnt == 0) + av_log(NULL, AV_LOG_INFO, "%-9s %12s %30s %10s %s %16s %16s %16s\n", + "TYPE", "SIZE", "NAME", "UID(GID)", "UGO", "MODIFIED", + "ACCESSED", "STATUS_CHANGED"); + av_log(NULL, AV_LOG_INFO, "%-9s %12"PRId64" %30s %10s %s %16"PRId64" %16"PRId64" %16"PRId64"\n", + type_string(entry->type), + entry->size, + entry->name, + uid_and_gid, + filemode, + entry->modification_timestamp, + entry->access_timestamp, + entry->status_change_timestamp); + avio_free_directory_entry(&entry); + cnt++; + }; + + fail: + avio_close_dir(&ctx); + return ret; +} + +static void usage(const char *program_name) +{ + fprintf(stderr, "usage: %s input_dir\n" + "API example program to show how to list files in directory " + "accessed through AVIOContext.\n", program_name); +} + +int main(int argc, char *argv[]) +{ + int ret; + + av_log_set_level(AV_LOG_DEBUG); + + if (argc < 2) { + usage(argv[0]); + return 1; + } + + avformat_network_init(); + + ret = list_op(argv[1]); + + avformat_network_deinit(); + + return ret < 0 ? 1 : 0; +} diff -Nru ffmpeg-4.2.2/doc/examples/decode_audio.c ffmpeg-4.4/doc/examples/decode_audio.c --- ffmpeg-4.2.2/doc/examples/decode_audio.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/examples/decode_audio.c 2020-07-11 10:39:30.000000000 +0000 @@ -39,6 +39,35 @@ #define AUDIO_INBUF_SIZE 20480 #define AUDIO_REFILL_THRESH 4096 +static int get_format_from_sample_fmt(const char **fmt, + enum AVSampleFormat sample_fmt) +{ + int i; + struct sample_fmt_entry { + enum AVSampleFormat sample_fmt; const char *fmt_be, *fmt_le; + } sample_fmt_entries[] = { + { AV_SAMPLE_FMT_U8, "u8", "u8" }, + { AV_SAMPLE_FMT_S16, "s16be", "s16le" }, + { AV_SAMPLE_FMT_S32, "s32be", "s32le" }, + { AV_SAMPLE_FMT_FLT, "f32be", "f32le" }, + { AV_SAMPLE_FMT_DBL, "f64be", "f64le" }, + }; + *fmt = NULL; + + for (i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) { + struct sample_fmt_entry *entry = &sample_fmt_entries[i]; + if (sample_fmt == entry->sample_fmt) { + *fmt = AV_NE(entry->fmt_be, entry->fmt_le); + return 0; + } + } + + fprintf(stderr, + "sample format %s is not supported as output format\n", + av_get_sample_fmt_name(sample_fmt)); + return -1; +} + static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile) { @@ -86,6 +115,9 @@ size_t data_size; AVPacket *pkt; AVFrame *decoded_frame = NULL; + enum AVSampleFormat sfmt; + int n_channels = 0; + const char *fmt; if (argc <= 2) { fprintf(stderr, "Usage: %s \n", argv[0]); @@ -172,6 +204,26 @@ pkt->size = 0; decode(c, pkt, decoded_frame, outfile); + /* print output pcm infomations, because there have no metadata of pcm */ + sfmt = c->sample_fmt; + + if (av_sample_fmt_is_planar(sfmt)) { + const char *packed = av_get_sample_fmt_name(sfmt); + printf("Warning: the sample format the decoder produced is planar " + "(%s). This example will output the first channel only.\n", + packed ? packed : "?"); + sfmt = av_get_packed_sample_fmt(sfmt); + } + + n_channels = c->channels; + if ((ret = get_format_from_sample_fmt(&fmt, sfmt)) < 0) + goto end; + + printf("Play the output audio file with the command:\n" + "ffplay -f %s -ac %d -ar %d %s\n", + fmt, n_channels, c->sample_rate, + outfilename); +end: fclose(outfile); fclose(f); diff -Nru ffmpeg-4.2.2/doc/examples/decode_video.c ffmpeg-4.4/doc/examples/decode_video.c --- ffmpeg-4.2.2/doc/examples/decode_video.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/examples/decode_video.c 2021-04-08 21:28:39.000000000 +0000 @@ -41,7 +41,7 @@ FILE *f; int i; - f = fopen(filename,"w"); + f = fopen(filename,"wb"); fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); for (i = 0; i < ysize; i++) fwrite(buf + i * wrap, 1, xsize, f); @@ -95,7 +95,8 @@ AVPacket *pkt; if (argc <= 2) { - fprintf(stderr, "Usage: %s \n", argv[0]); + fprintf(stderr, "Usage: %s \n" + "And check your input file is encoded by mpeg1video please.\n", argv[0]); exit(0); } filename = argv[1]; diff -Nru ffmpeg-4.2.2/doc/examples/demuxing_decoding.c ffmpeg-4.4/doc/examples/demuxing_decoding.c --- ffmpeg-4.2.2/doc/examples/demuxing_decoding.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/examples/demuxing_decoding.c 2021-04-08 21:28:39.000000000 +0000 @@ -51,99 +51,97 @@ static int video_stream_idx = -1, audio_stream_idx = -1; static AVFrame *frame = NULL; -static AVPacket pkt; +static AVPacket *pkt = NULL; static int video_frame_count = 0; static int audio_frame_count = 0; -/* Enable or disable frame reference counting. You are not supposed to support - * both paths in your application but pick the one most appropriate to your - * needs. Look for the use of refcount in this example to see what are the - * differences of API usage between them. */ -static int refcount = 0; +static int output_video_frame(AVFrame *frame) +{ + if (frame->width != width || frame->height != height || + frame->format != pix_fmt) { + /* To handle this change, one could call av_image_alloc again and + * decode the following frames into another rawvideo file. */ + fprintf(stderr, "Error: Width, height and pixel format have to be " + "constant in a rawvideo file, but the width, height or " + "pixel format of the input video changed:\n" + "old: width = %d, height = %d, format = %s\n" + "new: width = %d, height = %d, format = %s\n", + width, height, av_get_pix_fmt_name(pix_fmt), + frame->width, frame->height, + av_get_pix_fmt_name(frame->format)); + return -1; + } + + printf("video_frame n:%d coded_n:%d\n", + video_frame_count++, frame->coded_picture_number); + + /* copy decoded frame to destination buffer: + * this is required since rawvideo expects non aligned data */ + av_image_copy(video_dst_data, video_dst_linesize, + (const uint8_t **)(frame->data), frame->linesize, + pix_fmt, width, height); + + /* write to rawvideo file */ + fwrite(video_dst_data[0], 1, video_dst_bufsize, video_dst_file); + return 0; +} + +static int output_audio_frame(AVFrame *frame) +{ + size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format); + printf("audio_frame n:%d nb_samples:%d pts:%s\n", + audio_frame_count++, frame->nb_samples, + av_ts2timestr(frame->pts, &audio_dec_ctx->time_base)); + + /* Write the raw audio data samples of the first plane. This works + * fine for packed formats (e.g. AV_SAMPLE_FMT_S16). However, + * most audio decoders output planar audio, which uses a separate + * plane of audio samples for each channel (e.g. AV_SAMPLE_FMT_S16P). + * In other words, this code will write only the first audio channel + * in these cases. + * You should use libswresample or libavfilter to convert the frame + * to packed data. */ + fwrite(frame->extended_data[0], 1, unpadded_linesize, audio_dst_file); + + return 0; +} -static int decode_packet(int *got_frame, int cached) +static int decode_packet(AVCodecContext *dec, const AVPacket *pkt) { int ret = 0; - int decoded = pkt.size; - *got_frame = 0; + // submit the packet to the decoder + ret = avcodec_send_packet(dec, pkt); + if (ret < 0) { + fprintf(stderr, "Error submitting a packet for decoding (%s)\n", av_err2str(ret)); + return ret; + } - if (pkt.stream_index == video_stream_idx) { - /* decode video frame */ - ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt); + // get all the available frames from the decoder + while (ret >= 0) { + ret = avcodec_receive_frame(dec, frame); if (ret < 0) { - fprintf(stderr, "Error decoding video frame (%s)\n", av_err2str(ret)); + // those two return values are special and mean there is no output + // frame available, but there were no errors during decoding + if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) + return 0; + + fprintf(stderr, "Error during decoding (%s)\n", av_err2str(ret)); return ret; } - if (*got_frame) { - - if (frame->width != width || frame->height != height || - frame->format != pix_fmt) { - /* To handle this change, one could call av_image_alloc again and - * decode the following frames into another rawvideo file. */ - fprintf(stderr, "Error: Width, height and pixel format have to be " - "constant in a rawvideo file, but the width, height or " - "pixel format of the input video changed:\n" - "old: width = %d, height = %d, format = %s\n" - "new: width = %d, height = %d, format = %s\n", - width, height, av_get_pix_fmt_name(pix_fmt), - frame->width, frame->height, - av_get_pix_fmt_name(frame->format)); - return -1; - } - - printf("video_frame%s n:%d coded_n:%d\n", - cached ? "(cached)" : "", - video_frame_count++, frame->coded_picture_number); - - /* copy decoded frame to destination buffer: - * this is required since rawvideo expects non aligned data */ - av_image_copy(video_dst_data, video_dst_linesize, - (const uint8_t **)(frame->data), frame->linesize, - pix_fmt, width, height); + // write the frame data to output file + if (dec->codec->type == AVMEDIA_TYPE_VIDEO) + ret = output_video_frame(frame); + else + ret = output_audio_frame(frame); - /* write to rawvideo file */ - fwrite(video_dst_data[0], 1, video_dst_bufsize, video_dst_file); - } - } else if (pkt.stream_index == audio_stream_idx) { - /* decode audio frame */ - ret = avcodec_decode_audio4(audio_dec_ctx, frame, got_frame, &pkt); - if (ret < 0) { - fprintf(stderr, "Error decoding audio frame (%s)\n", av_err2str(ret)); + av_frame_unref(frame); + if (ret < 0) return ret; - } - /* Some audio decoders decode only part of the packet, and have to be - * called again with the remainder of the packet data. - * Sample: fate-suite/lossless-audio/luckynight-partial.shn - * Also, some decoders might over-read the packet. */ - decoded = FFMIN(ret, pkt.size); - - if (*got_frame) { - size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format); - printf("audio_frame%s n:%d nb_samples:%d pts:%s\n", - cached ? "(cached)" : "", - audio_frame_count++, frame->nb_samples, - av_ts2timestr(frame->pts, &audio_dec_ctx->time_base)); - - /* Write the raw audio data samples of the first plane. This works - * fine for packed formats (e.g. AV_SAMPLE_FMT_S16). However, - * most audio decoders output planar audio, which uses a separate - * plane of audio samples for each channel (e.g. AV_SAMPLE_FMT_S16P). - * In other words, this code will write only the first audio channel - * in these cases. - * You should use libswresample or libavfilter to convert the frame - * to packed data. */ - fwrite(frame->extended_data[0], 1, unpadded_linesize, audio_dst_file); - } } - /* If we use frame reference counting, we own the data and need - * to de-reference it when we don't use it anymore */ - if (*got_frame && refcount) - av_frame_unref(frame); - - return decoded; + return 0; } static int open_codec_context(int *stream_idx, @@ -186,8 +184,7 @@ return ret; } - /* Init the decoders, with or without reference counting */ - av_dict_set(&opts, "refcounted_frames", refcount ? "1" : "0", 0); + /* Init the decoders */ if ((ret = avcodec_open2(*dec_ctx, dec, &opts)) < 0) { fprintf(stderr, "Failed to open %s codec\n", av_get_media_type_string(type)); @@ -230,24 +227,17 @@ int main (int argc, char **argv) { - int ret = 0, got_frame; + int ret = 0; - if (argc != 4 && argc != 5) { - fprintf(stderr, "usage: %s [-refcount] input_file video_output_file audio_output_file\n" + if (argc != 4) { + fprintf(stderr, "usage: %s input_file video_output_file audio_output_file\n" "API example program to show how to read frames from an input file.\n" "This program reads frames from a file, decodes them, and writes decoded\n" "video frames to a rawvideo file named video_output_file, and decoded\n" - "audio frames to a rawaudio file named audio_output_file.\n\n" - "If the -refcount option is specified, the program use the\n" - "reference counting frame system which allows keeping a copy of\n" - "the data for longer than one decode call.\n" - "\n", argv[0]); + "audio frames to a rawaudio file named audio_output_file.\n", + argv[0]); exit(1); } - if (argc == 5 && !strcmp(argv[1], "-refcount")) { - refcount = 1; - argv++; - } src_filename = argv[1]; video_dst_filename = argv[2]; audio_dst_filename = argv[3]; @@ -313,10 +303,12 @@ goto end; } - /* initialize packet, set data to NULL, let the demuxer fill it */ - av_init_packet(&pkt); - pkt.data = NULL; - pkt.size = 0; + pkt = av_packet_alloc(); + if (!pkt) { + fprintf(stderr, "Could not allocate packet\n"); + ret = AVERROR(ENOMEM); + goto end; + } if (video_stream) printf("Demuxing video from file '%s' into '%s'\n", src_filename, video_dst_filename); @@ -324,24 +316,23 @@ printf("Demuxing audio from file '%s' into '%s'\n", src_filename, audio_dst_filename); /* read frames from the file */ - while (av_read_frame(fmt_ctx, &pkt) >= 0) { - AVPacket orig_pkt = pkt; - do { - ret = decode_packet(&got_frame, 0); - if (ret < 0) - break; - pkt.data += ret; - pkt.size -= ret; - } while (pkt.size > 0); - av_packet_unref(&orig_pkt); - } - - /* flush cached frames */ - pkt.data = NULL; - pkt.size = 0; - do { - decode_packet(&got_frame, 1); - } while (got_frame); + while (av_read_frame(fmt_ctx, pkt) >= 0) { + // check if the packet belongs to a stream we are interested in, otherwise + // skip it + if (pkt->stream_index == video_stream_idx) + ret = decode_packet(video_dec_ctx, pkt); + else if (pkt->stream_index == audio_stream_idx) + ret = decode_packet(audio_dec_ctx, pkt); + av_packet_unref(pkt); + if (ret < 0) + break; + } + + /* flush the decoders */ + if (video_dec_ctx) + decode_packet(video_dec_ctx, NULL); + if (audio_dec_ctx) + decode_packet(audio_dec_ctx, NULL); printf("Demuxing succeeded.\n"); @@ -383,6 +374,7 @@ fclose(video_dst_file); if (audio_dst_file) fclose(audio_dst_file); + av_packet_free(&pkt); av_frame_free(&frame); av_free(video_dst_data[0]); diff -Nru ffmpeg-4.2.2/doc/examples/encode_video.c ffmpeg-4.4/doc/examples/encode_video.c --- ffmpeg-4.2.2/doc/examples/encode_video.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/examples/encode_video.c 2020-07-11 10:39:30.000000000 +0000 @@ -145,7 +145,7 @@ frame->width = c->width; frame->height = c->height; - ret = av_frame_get_buffer(frame, 32); + ret = av_frame_get_buffer(frame, 0); if (ret < 0) { fprintf(stderr, "Could not allocate the video frame data\n"); exit(1); @@ -186,7 +186,8 @@ encode(c, NULL, pkt, f); /* add sequence end code to have a real MPEG file */ - fwrite(endcode, 1, sizeof(endcode), f); + if (codec->id == AV_CODEC_ID_MPEG1VIDEO || codec->id == AV_CODEC_ID_MPEG2VIDEO) + fwrite(endcode, 1, sizeof(endcode), f); fclose(f); avcodec_free_context(&c); diff -Nru ffmpeg-4.2.2/doc/examples/hw_decode.c ffmpeg-4.4/doc/examples/hw_decode.c --- ffmpeg-4.2.2/doc/examples/hw_decode.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/examples/hw_decode.c 2021-04-08 21:28:39.000000000 +0000 @@ -223,7 +223,7 @@ } /* open the file to dump raw data */ - output_file = fopen(argv[3], "w+"); + output_file = fopen(argv[3], "w+b"); /* actual decoding and dump the raw data */ while (ret >= 0) { diff -Nru ffmpeg-4.2.2/doc/examples/Makefile ffmpeg-4.4/doc/examples/Makefile --- ffmpeg-4.2.2/doc/examples/Makefile 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/examples/Makefile 2020-07-11 10:39:30.000000000 +0000 @@ -1,4 +1,4 @@ -EXAMPLES-$(CONFIG_AVIO_DIR_CMD_EXAMPLE) += avio_dir_cmd +EXAMPLES-$(CONFIG_AVIO_LIST_DIR_EXAMPLE) += avio_list_dir EXAMPLES-$(CONFIG_AVIO_READING_EXAMPLE) += avio_reading EXAMPLES-$(CONFIG_DECODE_AUDIO_EXAMPLE) += decode_audio EXAMPLES-$(CONFIG_DECODE_VIDEO_EXAMPLE) += decode_video diff -Nru ffmpeg-4.2.2/doc/examples/Makefile.example ffmpeg-4.4/doc/examples/Makefile.example --- ffmpeg-4.2.2/doc/examples/Makefile.example 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/doc/examples/Makefile.example 2020-07-11 10:39:30.000000000 +0000 @@ -11,7 +11,7 @@ CFLAGS := $(shell pkg-config --cflags $(FFMPEG_LIBS)) $(CFLAGS) LDLIBS := $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS) -EXAMPLES= avio_dir_cmd \ +EXAMPLES= avio_list_dir \ avio_reading \ decode_audio \ decode_video \ diff -Nru ffmpeg-4.2.2/doc/examples/muxing.c ffmpeg-4.4/doc/examples/muxing.c --- ffmpeg-4.2.2/doc/examples/muxing.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/examples/muxing.c 2021-04-08 21:28:39.000000000 +0000 @@ -78,15 +78,45 @@ pkt->stream_index); } -static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt) +static int write_frame(AVFormatContext *fmt_ctx, AVCodecContext *c, + AVStream *st, AVFrame *frame) { - /* rescale output packet timestamp values from codec to stream timebase */ - av_packet_rescale_ts(pkt, *time_base, st->time_base); - pkt->stream_index = st->index; - - /* Write the compressed frame to the media file. */ - log_packet(fmt_ctx, pkt); - return av_interleaved_write_frame(fmt_ctx, pkt); + int ret; + + // send the frame to the encoder + ret = avcodec_send_frame(c, frame); + if (ret < 0) { + fprintf(stderr, "Error sending a frame to the encoder: %s\n", + av_err2str(ret)); + exit(1); + } + + while (ret >= 0) { + AVPacket pkt = { 0 }; + + ret = avcodec_receive_packet(c, &pkt); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + break; + else if (ret < 0) { + fprintf(stderr, "Error encoding a frame: %s\n", av_err2str(ret)); + exit(1); + } + + /* rescale output packet timestamp values from codec to stream timebase */ + av_packet_rescale_ts(&pkt, c->time_base, st->time_base); + pkt.stream_index = st->index; + + /* Write the compressed frame to the media file. */ + log_packet(fmt_ctx, &pkt); + ret = av_interleaved_write_frame(fmt_ctx, &pkt); + av_packet_unref(&pkt); + if (ret < 0) { + fprintf(stderr, "Error while writing output packet: %s\n", av_err2str(ret)); + exit(1); + } + } + + return ret == AVERROR_EOF ? 1 : 0; } /* Add an output stream. */ @@ -170,7 +200,7 @@ * the motion of the chroma plane does not match the luma plane. */ c->mb_decision = 2; } - break; + break; default: break; @@ -254,25 +284,25 @@ } /* create resampler context */ - ost->swr_ctx = swr_alloc(); - if (!ost->swr_ctx) { - fprintf(stderr, "Could not allocate resampler context\n"); - exit(1); - } + ost->swr_ctx = swr_alloc(); + if (!ost->swr_ctx) { + fprintf(stderr, "Could not allocate resampler context\n"); + exit(1); + } - /* set options */ - av_opt_set_int (ost->swr_ctx, "in_channel_count", c->channels, 0); - av_opt_set_int (ost->swr_ctx, "in_sample_rate", c->sample_rate, 0); - av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); - av_opt_set_int (ost->swr_ctx, "out_channel_count", c->channels, 0); - av_opt_set_int (ost->swr_ctx, "out_sample_rate", c->sample_rate, 0); - av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt", c->sample_fmt, 0); - - /* initialize the resampling context */ - if ((ret = swr_init(ost->swr_ctx)) < 0) { - fprintf(stderr, "Failed to initialize the resampling context\n"); - exit(1); - } + /* set options */ + av_opt_set_int (ost->swr_ctx, "in_channel_count", c->channels, 0); + av_opt_set_int (ost->swr_ctx, "in_sample_rate", c->sample_rate, 0); + av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); + av_opt_set_int (ost->swr_ctx, "out_channel_count", c->channels, 0); + av_opt_set_int (ost->swr_ctx, "out_sample_rate", c->sample_rate, 0); + av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt", c->sample_fmt, 0); + + /* initialize the resampling context */ + if ((ret = swr_init(ost->swr_ctx)) < 0) { + fprintf(stderr, "Failed to initialize the resampling context\n"); + exit(1); + } } /* Prepare a 16 bit dummy audio frame of 'frame_size' samples and @@ -285,7 +315,7 @@ /* check if we want to generate more frames */ if (av_compare_ts(ost->next_pts, ost->enc->time_base, - STREAM_DURATION, (AVRational){ 1, 1 }) >= 0) + STREAM_DURATION, (AVRational){ 1, 1 }) > 0) return NULL; for (j = 0; j nb_samples; j++) { @@ -309,23 +339,20 @@ static int write_audio_frame(AVFormatContext *oc, OutputStream *ost) { AVCodecContext *c; - AVPacket pkt = { 0 }; // data and size must be 0; AVFrame *frame; int ret; - int got_packet; int dst_nb_samples; - av_init_packet(&pkt); c = ost->enc; frame = get_audio_frame(ost); if (frame) { /* convert samples from native format to destination codec format, using the resampler */ - /* compute destination number of samples */ - dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples, - c->sample_rate, c->sample_rate, AV_ROUND_UP); - av_assert0(dst_nb_samples == frame->nb_samples); + /* compute destination number of samples */ + dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples, + c->sample_rate, c->sample_rate, AV_ROUND_UP); + av_assert0(dst_nb_samples == frame->nb_samples); /* when we pass a frame to the encoder, it may keep a reference to it * internally; @@ -349,22 +376,7 @@ ost->samples_count += dst_nb_samples; } - ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet); - if (ret < 0) { - fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret)); - exit(1); - } - - if (got_packet) { - ret = write_frame(oc, &c->time_base, ost->st, &pkt); - if (ret < 0) { - fprintf(stderr, "Error while writing audio frame: %s\n", - av_err2str(ret)); - exit(1); - } - } - - return (frame || got_packet) ? 0 : 1; + return write_frame(oc, c, ost->st, frame); } /**************************************************************/ @@ -384,7 +396,7 @@ picture->height = height; /* allocate the buffers for the frame data */ - ret = av_frame_get_buffer(picture, 32); + ret = av_frame_get_buffer(picture, 0); if (ret < 0) { fprintf(stderr, "Could not allocate frame data.\n"); exit(1); @@ -464,7 +476,7 @@ /* check if we want to generate more frames */ if (av_compare_ts(ost->next_pts, c->time_base, - STREAM_DURATION, (AVRational){ 1, 1 }) >= 0) + STREAM_DURATION, (AVRational){ 1, 1 }) > 0) return NULL; /* when we pass a frame to the encoder, it may keep a reference to it @@ -506,37 +518,7 @@ */ static int write_video_frame(AVFormatContext *oc, OutputStream *ost) { - int ret; - AVCodecContext *c; - AVFrame *frame; - int got_packet = 0; - AVPacket pkt = { 0 }; - - c = ost->enc; - - frame = get_video_frame(ost); - - av_init_packet(&pkt); - - /* encode the image */ - ret = avcodec_encode_video2(c, &pkt, frame, &got_packet); - if (ret < 0) { - fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret)); - exit(1); - } - - if (got_packet) { - ret = write_frame(oc, &c->time_base, ost->st, &pkt); - } else { - ret = 0; - } - - if (ret < 0) { - fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret)); - exit(1); - } - - return (frame || got_packet) ? 0 : 1; + return write_frame(oc, ost->enc, ost->st, get_video_frame(ost)); } static void close_stream(AVFormatContext *oc, OutputStream *ost) diff -Nru ffmpeg-4.2.2/doc/examples/transcode_aac.c ffmpeg-4.4/doc/examples/transcode_aac.c --- ffmpeg-4.2.2/doc/examples/transcode_aac.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/examples/transcode_aac.c 2021-04-08 21:28:39.000000000 +0000 @@ -245,14 +245,16 @@ /** * Initialize one data packet for reading or writing. - * @param packet Packet to be initialized + * @param[out] packet Packet to be initialized + * @return Error code (0 if successful) */ -static void init_packet(AVPacket *packet) +static int init_packet(AVPacket **packet) { - av_init_packet(packet); - /* Set the packet data and size so that it is recognized as being empty. */ - packet->data = NULL; - packet->size = 0; + if (!(*packet = av_packet_alloc())) { + fprintf(stderr, "Could not allocate packet\n"); + return AVERROR(ENOMEM); + } + return 0; } /** @@ -371,28 +373,31 @@ int *data_present, int *finished) { /* Packet used for temporary storage. */ - AVPacket input_packet; + AVPacket *input_packet; int error; - init_packet(&input_packet); + + error = init_packet(&input_packet); + if (error < 0) + return error; /* Read one audio frame from the input file into a temporary packet. */ - if ((error = av_read_frame(input_format_context, &input_packet)) < 0) { + if ((error = av_read_frame(input_format_context, input_packet)) < 0) { /* If we are at the end of the file, flush the decoder below. */ if (error == AVERROR_EOF) *finished = 1; else { fprintf(stderr, "Could not read frame (error '%s')\n", av_err2str(error)); - return error; + goto cleanup; } } /* Send the audio frame stored in the temporary packet to the decoder. * The input audio stream decoder is used to do this. */ - if ((error = avcodec_send_packet(input_codec_context, &input_packet)) < 0) { + if ((error = avcodec_send_packet(input_codec_context, input_packet)) < 0) { fprintf(stderr, "Could not send packet for decoding (error '%s')\n", av_err2str(error)); - return error; + goto cleanup; } /* Receive one frame from the decoder. */ @@ -418,7 +423,7 @@ } cleanup: - av_packet_unref(&input_packet); + av_packet_free(&input_packet); return error; } @@ -661,9 +666,12 @@ int *data_present) { /* Packet used for temporary storage. */ - AVPacket output_packet; + AVPacket *output_packet; int error; - init_packet(&output_packet); + + error = init_packet(&output_packet); + if (error < 0) + return error; /* Set a timestamp based on the sample rate for the container. */ if (frame) { @@ -681,11 +689,11 @@ } else if (error < 0) { fprintf(stderr, "Could not send packet for encoding (error '%s')\n", av_err2str(error)); - return error; + goto cleanup; } /* Receive one encoded frame from the encoder. */ - error = avcodec_receive_packet(output_codec_context, &output_packet); + error = avcodec_receive_packet(output_codec_context, output_packet); /* If the encoder asks for more data to be able to provide an * encoded frame, return indicating that no data is present. */ if (error == AVERROR(EAGAIN)) { @@ -706,14 +714,14 @@ /* Write one audio frame from the temporary packet to the output file. */ if (*data_present && - (error = av_write_frame(output_format_context, &output_packet)) < 0) { + (error = av_write_frame(output_format_context, output_packet)) < 0) { fprintf(stderr, "Could not write frame (error '%s')\n", av_err2str(error)); goto cleanup; } cleanup: - av_packet_unref(&output_packet); + av_packet_free(&output_packet); return error; } diff -Nru ffmpeg-4.2.2/doc/examples/transcoding.c ffmpeg-4.4/doc/examples/transcoding.c --- ffmpeg-4.2.2/doc/examples/transcoding.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/examples/transcoding.c 2021-04-08 21:28:39.000000000 +0000 @@ -41,12 +41,17 @@ AVFilterContext *buffersink_ctx; AVFilterContext *buffersrc_ctx; AVFilterGraph *filter_graph; + + AVPacket *enc_pkt; + AVFrame *filtered_frame; } FilteringContext; static FilteringContext *filter_ctx; typedef struct StreamContext { AVCodecContext *dec_ctx; AVCodecContext *enc_ctx; + + AVFrame *dec_frame; } StreamContext; static StreamContext *stream_ctx; @@ -102,6 +107,10 @@ } } stream_ctx[i].dec_ctx = codec_ctx; + + stream_ctx[i].dec_frame = av_frame_alloc(); + if (!stream_ctx[i].dec_frame) + return AVERROR(ENOMEM); } av_dump_format(ifmt_ctx, 0, filename, 0); @@ -398,54 +407,63 @@ stream_ctx[i].enc_ctx, filter_spec); if (ret) return ret; + + filter_ctx[i].enc_pkt = av_packet_alloc(); + if (!filter_ctx[i].enc_pkt) + return AVERROR(ENOMEM); + + filter_ctx[i].filtered_frame = av_frame_alloc(); + if (!filter_ctx[i].filtered_frame) + return AVERROR(ENOMEM); } return 0; } -static int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame) { +static int encode_write_frame(unsigned int stream_index, int flush) +{ + StreamContext *stream = &stream_ctx[stream_index]; + FilteringContext *filter = &filter_ctx[stream_index]; + AVFrame *filt_frame = flush ? NULL : filter->filtered_frame; + AVPacket *enc_pkt = filter->enc_pkt; int ret; - int got_frame_local; - AVPacket enc_pkt; - int (*enc_func)(AVCodecContext *, AVPacket *, const AVFrame *, int *) = - (ifmt_ctx->streams[stream_index]->codecpar->codec_type == - AVMEDIA_TYPE_VIDEO) ? avcodec_encode_video2 : avcodec_encode_audio2; - - if (!got_frame) - got_frame = &got_frame_local; av_log(NULL, AV_LOG_INFO, "Encoding frame\n"); /* encode filtered frame */ - enc_pkt.data = NULL; - enc_pkt.size = 0; - av_init_packet(&enc_pkt); - ret = enc_func(stream_ctx[stream_index].enc_ctx, &enc_pkt, - filt_frame, got_frame); - av_frame_free(&filt_frame); + av_packet_unref(enc_pkt); + + ret = avcodec_send_frame(stream->enc_ctx, filt_frame); + if (ret < 0) return ret; - if (!(*got_frame)) - return 0; - /* prepare packet for muxing */ - enc_pkt.stream_index = stream_index; - av_packet_rescale_ts(&enc_pkt, - stream_ctx[stream_index].enc_ctx->time_base, - ofmt_ctx->streams[stream_index]->time_base); - - av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n"); - /* mux encoded frame */ - ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt); + while (ret >= 0) { + ret = avcodec_receive_packet(stream->enc_ctx, enc_pkt); + + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + return 0; + + /* prepare packet for muxing */ + enc_pkt->stream_index = stream_index; + av_packet_rescale_ts(enc_pkt, + stream->enc_ctx->time_base, + ofmt_ctx->streams[stream_index]->time_base); + + av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n"); + /* mux encoded frame */ + ret = av_interleaved_write_frame(ofmt_ctx, enc_pkt); + } + return ret; } static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index) { + FilteringContext *filter = &filter_ctx[stream_index]; int ret; - AVFrame *filt_frame; av_log(NULL, AV_LOG_INFO, "Pushing decoded frame to filters\n"); /* push the decoded frame into the filtergraph */ - ret = av_buffersrc_add_frame_flags(filter_ctx[stream_index].buffersrc_ctx, + ret = av_buffersrc_add_frame_flags(filter->buffersrc_ctx, frame, 0); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n"); @@ -454,14 +472,9 @@ /* pull filtered frames from the filtergraph */ while (1) { - filt_frame = av_frame_alloc(); - if (!filt_frame) { - ret = AVERROR(ENOMEM); - break; - } av_log(NULL, AV_LOG_INFO, "Pulling filtered frame from filters\n"); - ret = av_buffersink_get_frame(filter_ctx[stream_index].buffersink_ctx, - filt_frame); + ret = av_buffersink_get_frame(filter->buffersink_ctx, + filter->filtered_frame); if (ret < 0) { /* if no more frames for output - returns AVERROR(EAGAIN) * if flushed and no more frames for output - returns AVERROR_EOF @@ -469,12 +482,12 @@ */ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) ret = 0; - av_frame_free(&filt_frame); break; } - filt_frame->pict_type = AV_PICTURE_TYPE_NONE; - ret = encode_write_frame(filt_frame, stream_index, NULL); + filter->filtered_frame->pict_type = AV_PICTURE_TYPE_NONE; + ret = encode_write_frame(stream_index, 0); + av_frame_unref(filter->filtered_frame); if (ret < 0) break; } @@ -484,34 +497,20 @@ static int flush_encoder(unsigned int stream_index) { - int ret; - int got_frame; - if (!(stream_ctx[stream_index].enc_ctx->codec->capabilities & AV_CODEC_CAP_DELAY)) return 0; - while (1) { - av_log(NULL, AV_LOG_INFO, "Flushing stream #%u encoder\n", stream_index); - ret = encode_write_frame(NULL, stream_index, &got_frame); - if (ret < 0) - break; - if (!got_frame) - return 0; - } - return ret; + av_log(NULL, AV_LOG_INFO, "Flushing stream #%u encoder\n", stream_index); + return encode_write_frame(stream_index, 1); } int main(int argc, char **argv) { int ret; - AVPacket packet = { .data = NULL, .size = 0 }; - AVFrame *frame = NULL; - enum AVMediaType type; + AVPacket *packet = NULL; unsigned int stream_index; unsigned int i; - int got_frame; - int (*dec_func)(AVCodecContext *, AVFrame *, int *, const AVPacket *); if (argc != 3) { av_log(NULL, AV_LOG_ERROR, "Usage: %s \n", argv[0]); @@ -524,56 +523,54 @@ goto end; if ((ret = init_filters()) < 0) goto end; + if (!(packet = av_packet_alloc())) + goto end; /* read all packets */ while (1) { - if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0) + if ((ret = av_read_frame(ifmt_ctx, packet)) < 0) break; - stream_index = packet.stream_index; - type = ifmt_ctx->streams[packet.stream_index]->codecpar->codec_type; + stream_index = packet->stream_index; av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n", stream_index); if (filter_ctx[stream_index].filter_graph) { + StreamContext *stream = &stream_ctx[stream_index]; + av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n"); - frame = av_frame_alloc(); - if (!frame) { - ret = AVERROR(ENOMEM); - break; - } - av_packet_rescale_ts(&packet, + + av_packet_rescale_ts(packet, ifmt_ctx->streams[stream_index]->time_base, - stream_ctx[stream_index].dec_ctx->time_base); - dec_func = (type == AVMEDIA_TYPE_VIDEO) ? avcodec_decode_video2 : - avcodec_decode_audio4; - ret = dec_func(stream_ctx[stream_index].dec_ctx, frame, - &got_frame, &packet); + stream->dec_ctx->time_base); + ret = avcodec_send_packet(stream->dec_ctx, packet); if (ret < 0) { - av_frame_free(&frame); av_log(NULL, AV_LOG_ERROR, "Decoding failed\n"); break; } - if (got_frame) { - frame->pts = frame->best_effort_timestamp; - ret = filter_encode_write_frame(frame, stream_index); - av_frame_free(&frame); + while (ret >= 0) { + ret = avcodec_receive_frame(stream->dec_ctx, stream->dec_frame); + if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) + break; + else if (ret < 0) + goto end; + + stream->dec_frame->pts = stream->dec_frame->best_effort_timestamp; + ret = filter_encode_write_frame(stream->dec_frame, stream_index); if (ret < 0) goto end; - } else { - av_frame_free(&frame); } } else { /* remux this frame without reencoding */ - av_packet_rescale_ts(&packet, + av_packet_rescale_ts(packet, ifmt_ctx->streams[stream_index]->time_base, ofmt_ctx->streams[stream_index]->time_base); - ret = av_interleaved_write_frame(ofmt_ctx, &packet); + ret = av_interleaved_write_frame(ofmt_ctx, packet); if (ret < 0) goto end; } - av_packet_unref(&packet); + av_packet_unref(packet); } /* flush filters and encoders */ @@ -597,14 +594,18 @@ av_write_trailer(ofmt_ctx); end: - av_packet_unref(&packet); - av_frame_free(&frame); + av_packet_free(&packet); for (i = 0; i < ifmt_ctx->nb_streams; i++) { avcodec_free_context(&stream_ctx[i].dec_ctx); if (ofmt_ctx && ofmt_ctx->nb_streams > i && ofmt_ctx->streams[i] && stream_ctx[i].enc_ctx) avcodec_free_context(&stream_ctx[i].enc_ctx); - if (filter_ctx && filter_ctx[i].filter_graph) + if (filter_ctx && filter_ctx[i].filter_graph) { avfilter_graph_free(&filter_ctx[i].filter_graph); + av_packet_free(&filter_ctx[i].enc_pkt); + av_frame_free(&filter_ctx[i].filtered_frame); + } + + av_frame_free(&stream_ctx[i].dec_frame); } av_free(filter_ctx); av_free(stream_ctx); diff -Nru ffmpeg-4.2.2/doc/examples/vaapi_encode.c ffmpeg-4.4/doc/examples/vaapi_encode.c --- ffmpeg-4.2.2/doc/examples/vaapi_encode.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/examples/vaapi_encode.c 2021-04-08 21:28:39.000000000 +0000 @@ -74,27 +74,27 @@ static int encode_write(AVCodecContext *avctx, AVFrame *frame, FILE *fout) { int ret = 0; - AVPacket enc_pkt; + AVPacket *enc_pkt; - av_init_packet(&enc_pkt); - enc_pkt.data = NULL; - enc_pkt.size = 0; + if (!(enc_pkt = av_packet_alloc())) + return AVERROR(ENOMEM); if ((ret = avcodec_send_frame(avctx, frame)) < 0) { fprintf(stderr, "Error code: %s\n", av_err2str(ret)); goto end; } while (1) { - ret = avcodec_receive_packet(avctx, &enc_pkt); + ret = avcodec_receive_packet(avctx, enc_pkt); if (ret) break; - enc_pkt.stream_index = 0; - ret = fwrite(enc_pkt.data, enc_pkt.size, 1, fout); - av_packet_unref(&enc_pkt); + enc_pkt->stream_index = 0; + ret = fwrite(enc_pkt->data, enc_pkt->size, 1, fout); + av_packet_unref(enc_pkt); } end: + av_packet_free(&enc_pkt); ret = ((ret == AVERROR(EAGAIN)) ? 0 : -1); return ret; } @@ -172,7 +172,7 @@ sw_frame->width = width; sw_frame->height = height; sw_frame->format = AV_PIX_FMT_NV12; - if ((err = av_frame_get_buffer(sw_frame, 32)) < 0) + if ((err = av_frame_get_buffer(sw_frame, 0)) < 0) goto close; if ((err = fread((uint8_t*)(sw_frame->data[0]), size, 1, fin)) <= 0) break; diff -Nru ffmpeg-4.2.2/doc/examples/vaapi_transcode.c ffmpeg-4.4/doc/examples/vaapi_transcode.c --- ffmpeg-4.2.2/doc/examples/vaapi_transcode.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/examples/vaapi_transcode.c 2021-04-08 21:28:39.000000000 +0000 @@ -109,28 +109,25 @@ return ret; } -static int encode_write(AVFrame *frame) +static int encode_write(AVPacket *enc_pkt, AVFrame *frame) { int ret = 0; - AVPacket enc_pkt; - av_init_packet(&enc_pkt); - enc_pkt.data = NULL; - enc_pkt.size = 0; + av_packet_unref(enc_pkt); if ((ret = avcodec_send_frame(encoder_ctx, frame)) < 0) { fprintf(stderr, "Error during encoding. Error code: %s\n", av_err2str(ret)); goto end; } while (1) { - ret = avcodec_receive_packet(encoder_ctx, &enc_pkt); + ret = avcodec_receive_packet(encoder_ctx, enc_pkt); if (ret) break; - enc_pkt.stream_index = 0; - av_packet_rescale_ts(&enc_pkt, ifmt_ctx->streams[video_stream]->time_base, + enc_pkt->stream_index = 0; + av_packet_rescale_ts(enc_pkt, ifmt_ctx->streams[video_stream]->time_base, ofmt_ctx->streams[0]->time_base); - ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt); + ret = av_interleaved_write_frame(ofmt_ctx, enc_pkt); if (ret < 0) { fprintf(stderr, "Error during writing data to output file. " "Error code: %s\n", av_err2str(ret)); @@ -216,7 +213,7 @@ initialized = 1; } - if ((ret = encode_write(frame)) < 0) + if ((ret = encode_write(pkt, frame)) < 0) fprintf(stderr, "Error during encoding and writing.\n"); fail: @@ -230,7 +227,7 @@ int main(int argc, char **argv) { int ret = 0; - AVPacket dec_pkt; + AVPacket *dec_pkt; AVCodec *enc_codec; if (argc != 4) { @@ -246,6 +243,12 @@ return -1; } + dec_pkt = av_packet_alloc(); + if (!dec_pkt) { + fprintf(stderr, "Failed to allocate decode packet\n"); + goto end; + } + if ((ret = open_input_file(argv[1])) < 0) goto end; @@ -275,23 +278,21 @@ /* read all packets and only transcoding video */ while (ret >= 0) { - if ((ret = av_read_frame(ifmt_ctx, &dec_pkt)) < 0) + if ((ret = av_read_frame(ifmt_ctx, dec_pkt)) < 0) break; - if (video_stream == dec_pkt.stream_index) - ret = dec_enc(&dec_pkt, enc_codec); + if (video_stream == dec_pkt->stream_index) + ret = dec_enc(dec_pkt, enc_codec); - av_packet_unref(&dec_pkt); + av_packet_unref(dec_pkt); } /* flush decoder */ - dec_pkt.data = NULL; - dec_pkt.size = 0; - ret = dec_enc(&dec_pkt, enc_codec); - av_packet_unref(&dec_pkt); + av_packet_unref(dec_pkt); + ret = dec_enc(dec_pkt, enc_codec); /* flush encoder */ - ret = encode_write(NULL); + ret = encode_write(dec_pkt, NULL); /* write the trailer for output stream */ av_write_trailer(ofmt_ctx); @@ -302,5 +303,6 @@ avcodec_free_context(&decoder_ctx); avcodec_free_context(&encoder_ctx); av_buffer_unref(&hw_device_ctx); + av_packet_free(&dec_pkt); return ret; } diff -Nru ffmpeg-4.2.2/doc/fate.texi ffmpeg-4.4/doc/fate.texi --- ffmpeg-4.2.2/doc/fate.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/fate.texi 2020-07-11 10:39:30.000000000 +0000 @@ -149,6 +149,8 @@ @chapter Uploading new samples to the fate suite +If you need a sample uploaded send a mail to samples-request. + This is for developers who have an account on the fate suite server. If you upload new samples, please make sure they are as small as possible, space on each client, network bandwidth and so on benefit from smaller test cases. @@ -157,6 +159,8 @@ break older checkouts or releases. Also all needed samples for a commit should be uploaded, ideally 24 hours, before the push. +If you need an account for frequently uploading samples or you wish to help +others by doing that send a mail to ffmpeg-devel. @example #First update your local samples copy: diff -Nru ffmpeg-4.2.2/doc/ffmpeg.texi ffmpeg-4.4/doc/ffmpeg.texi --- ffmpeg-4.2.2/doc/ffmpeg.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/ffmpeg.texi 2021-04-08 21:28:39.000000000 +0000 @@ -617,6 +617,102 @@ ffmpeg -i myfile.avi -target vcd -bf 2 /tmp/vcd.mpg @end example +The parameters set for each target are as follows. + +@strong{VCD} +@example +@var{pal}: +-f vcd -muxrate 1411200 -muxpreload 0.44 -packetsize 2324 +-s 352x288 -r 25 +-codec:v mpeg1video -g 15 -b:v 1150k -maxrate:v 1150v -minrate:v 1150k -bufsize:v 327680 +-ar 44100 -ac 2 +-codec:a mp2 -b:a 224k + +@var{ntsc}: +-f vcd -muxrate 1411200 -muxpreload 0.44 -packetsize 2324 +-s 352x240 -r 30000/1001 +-codec:v mpeg1video -g 18 -b:v 1150k -maxrate:v 1150v -minrate:v 1150k -bufsize:v 327680 +-ar 44100 -ac 2 +-codec:a mp2 -b:a 224k + +@var{film}: +-f vcd -muxrate 1411200 -muxpreload 0.44 -packetsize 2324 +-s 352x240 -r 24000/1001 +-codec:v mpeg1video -g 18 -b:v 1150k -maxrate:v 1150v -minrate:v 1150k -bufsize:v 327680 +-ar 44100 -ac 2 +-codec:a mp2 -b:a 224k +@end example + +@strong{SVCD} +@example +@var{pal}: +-f svcd -packetsize 2324 +-s 480x576 -pix_fmt yuv420p -r 25 +-codec:v mpeg2video -g 15 -b:v 2040k -maxrate:v 2516k -minrate:v 0 -bufsize:v 1835008 -scan_offset 1 +-ar 44100 +-codec:a mp2 -b:a 224k + +@var{ntsc}: +-f svcd -packetsize 2324 +-s 480x480 -pix_fmt yuv420p -r 30000/1001 +-codec:v mpeg2video -g 18 -b:v 2040k -maxrate:v 2516k -minrate:v 0 -bufsize:v 1835008 -scan_offset 1 +-ar 44100 +-codec:a mp2 -b:a 224k + +@var{film}: +-f svcd -packetsize 2324 +-s 480x480 -pix_fmt yuv420p -r 24000/1001 +-codec:v mpeg2video -g 18 -b:v 2040k -maxrate:v 2516k -minrate:v 0 -bufsize:v 1835008 -scan_offset 1 +-ar 44100 +-codec:a mp2 -b:a 224k +@end example + +@strong{DVD} +@example +@var{pal}: +-f dvd -muxrate 10080k -packetsize 2048 +-s 720x576 -pix_fmt yuv420p -r 25 +-codec:v mpeg2video -g 15 -b:v 6000k -maxrate:v 9000k -minrate:v 0 -bufsize:v 1835008 +-ar 48000 +-codec:a ac3 -b:a 448k + +@var{ntsc}: +-f dvd -muxrate 10080k -packetsize 2048 +-s 720x480 -pix_fmt yuv420p -r 30000/1001 +-codec:v mpeg2video -g 18 -b:v 6000k -maxrate:v 9000k -minrate:v 0 -bufsize:v 1835008 +-ar 48000 +-codec:a ac3 -b:a 448k + +@var{film}: +-f dvd -muxrate 10080k -packetsize 2048 +-s 720x480 -pix_fmt yuv420p -r 24000/1001 +-codec:v mpeg2video -g 18 -b:v 6000k -maxrate:v 9000k -minrate:v 0 -bufsize:v 1835008 +-ar 48000 +-codec:a ac3 -b:a 448k +@end example + +@strong{DV} +@example +@var{pal}: +-f dv +-s 720x576 -pix_fmt yuv420p -r 25 +-ar 48000 -ac 2 + +@var{ntsc}: +-f dv +-s 720x480 -pix_fmt yuv411p -r 30000/1001 +-ar 48000 -ac 2 + +@var{film}: +-f dv +-s 720x480 -pix_fmt yuv411p -r 24000/1001 +-ar 48000 -ac 2 +@end example +The @code{dv50} target is identical to the @code{dv} target except that the pixel format set is @code{yuv422p} for all three standards. + +Any user-set value for a parameter above will override the target preset value. In that case, the output may +not comply with the target standard. + @item -dn (@emph{input/output}) As an input option, blocks all data streams of a file from being filtered or being automatically selected or mapped for any output. See @code{-discard} @@ -675,14 +771,19 @@ Print encoding progress/statistics. It is on by default, to explicitly disable it you need to specify @code{-nostats}. +@item -stats_period @var{time} (@emph{global}) +Set period at which encoding progress/statistics are updated. Default is 0.5 seconds. + @item -progress @var{url} (@emph{global}) Send program-friendly progress information to @var{url}. -Progress information is written approximately every second and at the end of +Progress information is written periodically and at the end of the encoding process. It is made of "@var{key}=@var{value}" lines. @var{key} consists of only alphanumeric characters. The last key of a sequence of progress information is always "progress". +The update period is set using @code{-stats_period}. + @anchor{stdin option} @item -stdin Enable interaction on standard input. On by default unless standard input is @@ -734,10 +835,6 @@ Technical note -- attachments are implemented as codec extradata, so this option can actually be used to extract extradata from any stream, not just attachments. - -@item -noautorotate -Disable automatically rotating video based on file metadata. - @end table @section Video Options @@ -758,6 +855,13 @@ As an output option, duplicate or drop input frames to achieve constant output frame rate @var{fps}. +@item -fpsmax[:@var{stream_specifier}] @var{fps} (@emph{output,per-stream}) +Set maximum frame rate (Hz value, fraction or abbreviation). + +Clamps output frame rate when output framerate is auto-set and is higher than this value. +Useful in batch processing or when input framerate is wrongly detected as very high. +It cannot be set together with @code{-r}. It is ignored during streamcopy. + @item -s[:@var{stream_specifier}] @var{size} (@emph{input/output,per-stream}) Set frame size. @@ -819,6 +923,18 @@ filter the stream. This is an alias for @code{-filter:v}, see the @ref{filter_option,,-filter option}. + +@item -autorotate +Automatically rotate the video according to file metadata. Enabled by +default, use @option{-noautorotate} to disable it. + +@item -autoscale +Automatically scale the video according to the resolution of first frame. +Enabled by default, use @option{-noautoscale} to disable it. When autoscale is +disabled, all output frames of filter graph might not be in the same resolution +and may be inadequate for some encoder/muxer. Therefore, it is not recommended +to disable it unless you really know what you are doing. +Disable autoscale at your own risk. @end table @section Advanced Video options @@ -848,8 +964,8 @@ Force interlacing support in encoder (MPEG-2 and MPEG-4 only). Use this option if your input file is interlaced and you want to keep the interlaced format for minimum losses. -The alternative is to deinterlace the input stream with -@option{-deinterlace}, but deinterlacing introduces losses. +The alternative is to deinterlace the input stream by use of a filter +such as @code{yadif} or @code{bwdif}, but deinterlacing introduces losses. @item -psnr Calculate PSNR of compressed frames. @item -vstats @@ -879,12 +995,19 @@ @item -force_key_frames[:@var{stream_specifier}] @var{time}[,@var{time}...] (@emph{output,per-stream}) @item -force_key_frames[:@var{stream_specifier}] expr:@var{expr} (@emph{output,per-stream}) -Force key frames at the specified timestamps, more precisely at the first -frames after each specified time. +@item -force_key_frames[:@var{stream_specifier}] source (@emph{output,per-stream}) -If the argument is prefixed with @code{expr:}, the string @var{expr} -is interpreted like an expression and is evaluated for each frame. A -key frame is forced in case the evaluation is non-zero. +@var{force_key_frames} can take arguments of the following form: + +@table @option + +@item @var{time}[,@var{time}...] +If the argument consists of timestamps, ffmpeg will round the specified times to the nearest +output timestamp as per the encoder time base and force a keyframe at the first frame having +timestamp equal or greater than the computed timestamp. Note that if the encoder time base is too +coarse, then the keyframes may be forced on frames with timestamps lower than the specified time. +The default encoder time base is the inverse of the output framerate but may be set otherwise +via @code{-enc_time_base}. If one of the times is "@code{chapters}[@var{delta}]", it is expanded into the time of the beginning of all chapters in the file, shifted by @@ -898,6 +1021,11 @@ -force_key_frames 0:05:00,chapters-0.1 @end example +@item expr:@var{expr} +If the argument is prefixed with @code{expr:}, the string @var{expr} +is interpreted like an expression and is evaluated for each frame. A +key frame is forced in case the evaluation is non-zero. + The expression in @var{expr} can contain the following constants: @table @option @item n @@ -925,6 +1053,12 @@ -force_key_frames expr:if(isnan(prev_forced_t),gte(t,13),gte(t,prev_forced_t+5)) @end example +@item source +If the argument is @code{source}, ffmpeg will force a key frame if +the current frame being encoded is marked as a key frame in its source. + +@end table + Note that forcing too many keyframes is very harmful for the lookahead algorithms of certain encoders: using fixed-GOP options or similar would be more efficient. @@ -1011,6 +1145,35 @@ extension. @end table +@item vulkan +If @var{device} is an integer, it selects the device by its index in a +system-dependent list of devices. If @var{device} is any other string, it +selects the first device with a name containing that string as a substring. + +The following options are recognized: +@table @option +@item debug +If set to 1, enables the validation layer, if installed. +@item linear_images +If set to 1, images allocated by the hwcontext will be linear and locally mappable. +@item instance_extensions +A plus separated list of additional instance extensions to enable. +@item device_extensions +A plus separated list of additional device extensions to enable. +@end table + +Examples: +@table @emph +@item -init_hw_device vulkan:1 +Choose the second device on the system. + +@item -init_hw_device vulkan:RADV +Choose the first device with a name containing the string @emph{RADV}. + +@item -init_hw_device vulkan:0,instance_extensions=VK_KHR_wayland_surface+VK_KHR_xcb_surface +Choose the first device and enable the Wayland and XCB instance extensions. +@end table + @end table @item -init_hw_device @var{type}[=@var{name}]@@@var{source} @@ -1383,7 +1546,7 @@ Show benchmarking information during the encode. Shows real, system and user time used in various steps (audio/video encode/decode). @item -timelimit @var{duration} (@emph{global}) -Exit after ffmpeg has been running for @var{duration} seconds. +Exit after ffmpeg has been running for @var{duration} seconds in CPU user time. @item -dump (@emph{global}) Dump each input packet to stderr. @item -hex (@emph{global}) @@ -1445,6 +1608,17 @@ This option has been deprecated. Use the @code{aresample} audio filter instead. +@item -adrift_threshold @var{time} +Set the minimum difference between timestamps and audio data (in seconds) to trigger +adding/dropping samples to make it match the timestamps. This option effectively is +a threshold to select between hard (add/drop) and soft (squeeze/stretch) compensation. +@code{-async} must be set to a positive value. + +@item -apad @var{parameters} (@emph{output,per-stream}) +Pad the output audio stream(s). This is the same as applying @code{-af apad}. +Argument is a string of filter parameters composed the same as with the @code{apad} filter. +@code{-shortest} must be set for this output for the option to take effect. + @item -copyts Do not process input timestamps, but keep their values without trying to sanitize them. In particular, do not remove the initial start time @@ -1515,6 +1689,10 @@ Finish encoding when the shortest input stream ends. @item -dts_delta_threshold Timestamp discontinuity delta threshold. +@item -dts_error_threshold @var{seconds} +Timestamp error delta threshold. This threshold use to discard crazy/damaged +timestamps and the default is 30 hours which is arbitrarily picked and quite +conservative. @item -muxdelay @var{seconds} (@emph{output}) Set the maximum demux-decode delay. @item -muxpreload @var{seconds} (@emph{output}) @@ -1595,6 +1773,22 @@ ffmpeg -i video.mkv -i image.png -filter_complex 'overlay' out.mkv @end example +As a special exception, you can use a bitmap subtitle stream as input: it +will be converted into a video with the same size as the largest video in +the file, or 720x576 if no video is present. Note that this is an +experimental and temporary solution. It will be removed once libavfilter has +proper support for subtitles. + +For example, to hardcode subtitles on top of a DVB-T recording stored in +MPEG-TS format, delaying the subtitles by 1 second: +@example +ffmpeg -i input.ts -filter_complex \ + '[#0x2ef] setpts=PTS+1/TB [sub] ; [#0x2d0] [sub] overlay' \ + -sn -map '#0x2dc' output.mkv +@end example +(0x2d0, 0x2dc and 0x2ef are the MPEG-TS PIDs of respectively the video, +audio and subtitles streams; 0:0, 0:3 and 0:7 would have worked too) + To generate 5 seconds of pure red video using lavfi @code{color} source: @example ffmpeg -filter_complex 'color=c=red' -t 5 out.mkv @@ -1630,8 +1824,9 @@ @item -thread_queue_size @var{size} (@emph{input}) This option sets the maximum number of queued packets when reading from the file or device. With low latency / high rate live streams, packets may be -discarded if they are not read in a timely manner; raising this value can -avoid it. +discarded if they are not read in a timely manner; setting this value can +force ffmpeg to use a separate input thread and read packets as soon as they +arrive. By default ffmpeg only do this if multiple inputs are specified. @item -sdp_file @var{file} (@emph{global}) Print sdp information for an output stream to @var{file}. @@ -1670,8 +1865,15 @@ @table @option @item empty_output No packets were passed to the muxer, the output is empty. +@item empty_output_stream +No packets were passed to the muxer in some of the output streams. @end table +@item -max_error_rate (@emph{global}) +Set fraction of decoding frame failures across all inputs which when crossed +ffmpeg will return exit code 69. Crossing this threshold does not terminate +processing. Range is a floating-point number between 0 to 1. Default is 2/3. + @item -xerror (@emph{global}) Stop and exit on error @@ -1684,23 +1886,22 @@ The default value of this option should be high enough for most uses, so only touch this option if you are sure that you need it. -@end table +@item -muxing_queue_data_threshold @var{bytes} (@emph{output,per-stream}) +This is a minimum threshold until which the muxing queue size is not taken into +account. Defaults to 50 megabytes per stream, and is based on the overall size +of packets passed to the muxer. + +@item -auto_conversion_filters (@emph{global}) +Enable automatically inserting format conversion filters in all filter +graphs, including those defined by @option{-vf}, @option{-af}, +@option{-filter_complex} and @option{-lavfi}. If filter format negotiation +requires a conversion, the initialization of the filters will fail. +Conversions can still be performed by inserting the relevant conversion +filter (scale, aresample) in the graph. +On by default, to explicitly disable it you need to specify +@code{-noauto_conversion_filters}. -As a special exception, you can use a bitmap subtitle stream as input: it -will be converted into a video with the same size as the largest video in -the file, or 720x576 if no video is present. Note that this is an -experimental and temporary solution. It will be removed once libavfilter has -proper support for subtitles. - -For example, to hardcode subtitles on top of a DVB-T recording stored in -MPEG-TS format, delaying the subtitles by 1 second: -@example -ffmpeg -i input.ts -filter_complex \ - '[#0x2ef] setpts=PTS+1/TB [sub] ; [#0x2d0] [sub] overlay' \ - -sn -map '#0x2dc' output.mkv -@end example -(0x2d0, 0x2dc and 0x2ef are the MPEG-TS PIDs of respectively the video, -audio and subtitles streams; 0:0, 0:3 and 0:7 would have worked too) +@end table @section Preset files A preset file contains a sequence of @var{option}=@var{value} pairs, @@ -1978,6 +2179,7 @@ @ifset config-avfilter @include filters.texi @end ifset +@include general_contents.texi @end ifset @chapter See Also diff -Nru ffmpeg-4.2.2/doc/ffplay.texi ffmpeg-4.4/doc/ffplay.texi --- ffmpeg-4.2.2/doc/ffplay.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/ffplay.texi 2021-04-08 21:28:39.000000000 +0000 @@ -133,8 +133,9 @@ @item -stats Print several playback statistics, in particular show the stream duration, the codec parameters, the current position in the stream and -the audio/video synchronisation drift. It is on by default, to -explicitly disable it you need to specify @code{-nostats}. +the audio/video synchronisation drift. It is shown by default, unless the +log level is lower than @code{info}. Its display can be forced by manually +specifying this option. To disable it, you need to specify @code{-nostats}. @item -fast Non-spec-compliant optimizations. @@ -294,6 +295,7 @@ @ifset config-avfilter @include filters.texi @end ifset +@include general_contents.texi @end ifset @chapter See Also diff -Nru ffmpeg-4.2.2/doc/ffprobe.texi ffmpeg-4.4/doc/ffprobe.texi --- ffmpeg-4.2.2/doc/ffprobe.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/ffprobe.texi 2021-04-08 21:28:39.000000000 +0000 @@ -642,6 +642,7 @@ @ifset config-avfilter @include filters.texi @end ifset +@include general_contents.texi @end ifset @chapter See Also diff -Nru ffmpeg-4.2.2/doc/ffprobe.xsd ffmpeg-4.4/doc/ffprobe.xsd --- ffmpeg-4.2.2/doc/ffprobe.xsd 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/ffprobe.xsd 2021-04-08 21:28:39.000000000 +0000 @@ -61,8 +61,6 @@ - - @@ -215,7 +213,6 @@ - @@ -226,6 +223,7 @@ + @@ -237,7 +235,6 @@ - @@ -357,7 +354,6 @@ - diff -Nru ffmpeg-4.2.2/doc/fftools-common-opts.texi ffmpeg-4.4/doc/fftools-common-opts.texi --- ffmpeg-4.2.2/doc/fftools-common-opts.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/fftools-common-opts.texi 2021-04-08 21:28:39.000000000 +0000 @@ -107,17 +107,24 @@ @option{-formats} option to get a list of all muxers and demuxers. @item filter=@var{filter_name} -Print detailed information about the filter name @var{filter_name}. Use the +Print detailed information about the filter named @var{filter_name}. Use the @option{-filters} option to get a list of all filters. @item bsf=@var{bitstream_filter_name} -Print detailed information about the bitstream filter name @var{bitstream_filter_name}. +Print detailed information about the bitstream filter named @var{bitstream_filter_name}. Use the @option{-bsfs} option to get a list of all bitstream filters. + +@item protocol=@var{protocol_name} +Print detailed information about the protocol named @var{protocol_name}. +Use the @option{-protocols} option to get a list of all protocols. @end table @item -version Show version. +@item -buildconf +Show the build configuration, one option per line. + @item -formats Show available formats (including devices). @@ -236,13 +243,11 @@ By default the program logs to stderr. If coloring is supported by the terminal, colors are used to mark errors and warnings. Log coloring can be disabled setting the environment variable -@env{AV_LOG_FORCE_NOCOLOR} or @env{NO_COLOR}, or can be forced setting +@env{AV_LOG_FORCE_NOCOLOR}, or can be forced setting the environment variable @env{AV_LOG_FORCE_COLOR}. -The use of the environment variable @env{NO_COLOR} is deprecated and -will be dropped in a future FFmpeg version. @item -report -Dump full command line and console output to a file named +Dump full command line and log output to a file named @code{@var{program}-@var{YYYYMMDD}-@var{HHMMSS}.log} in the current directory. This file can be useful for bug reports. @@ -347,6 +352,12 @@ @item k8 @end table @end table + +@item -max_alloc @var{bytes} +Set the maximum size limit for allocating a block on the heap by ffmpeg's +family of malloc functions. Exercise @strong{extreme caution} when using +this option. Don't use if you do not understand the full consequence of doing so. +Default is INT_MAX. @end table @section AVOptions diff -Nru ffmpeg-4.2.2/doc/filters.texi ffmpeg-4.4/doc/filters.texi --- ffmpeg-4.2.2/doc/filters.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/filters.texi 2021-04-08 21:28:39.000000000 +0000 @@ -312,6 +312,15 @@ @c man end FILTERGRAPH DESCRIPTION +@anchor{commands} +@chapter Changing options at runtime with a command + +Some options can be changed during the operation of the filter using +a command. These options are marked 'T' on the output of +@command{ffmpeg} @option{-h filter=}. +The name of the command is the name of the option and the argument is +the new value. + @anchor{framesync} @chapter Options for filters with several inputs (framesync) @c man begin OPTIONS FOR FILTERS WITH SEVERAL INPUTS @@ -434,6 +443,10 @@ Range is between 0 and 1. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section acontrast Simple audio dynamic range compression/expansion filter. @@ -510,10 +523,65 @@ Set split frequencies. Those must be positive and increasing. @item order -Set filter order, can be @var{2nd}, @var{4th} or @var{8th}. +Set filter order for each band split. This controls filter roll-off or steepness +of filter transfer function. +Available values are: + +@table @samp +@item 2nd +12 dB per octave. +@item 4th +24 dB per octave. +@item 6th +36 dB per octave. +@item 8th +48 dB per octave. +@item 10th +60 dB per octave. +@item 12th +72 dB per octave. +@item 14th +84 dB per octave. +@item 16th +96 dB per octave. +@item 18th +108 dB per octave. +@item 20th +120 dB per octave. +@end table + Default is @var{4th}. + +@item level +Set input gain level. Allowed range is from 0 to 1. Default value is 1. + +@item gains +Set output gain for each band. Default value is 1 for all bands. @end table +@subsection Examples + +@itemize +@item +Split input audio stream into two bands (low and high) with split frequency of 1500 Hz, +each band will be in separate stream: +@example +ffmpeg -i in.flac -filter_complex 'acrossover=split=1500[LOW][HIGH]' -map '[LOW]' low.wav -map '[HIGH]' high.wav +@end example + +@item +Same as above, but with higher filter order: +@example +ffmpeg -i in.flac -filter_complex 'acrossover=split=1500:order=8th[LOW][HIGH]' -map '[LOW]' low.wav -map '[HIGH]' high.wav +@end example + +@item +Same as above, but also with additional middle band (frequencies between 1500 and 8000): +@example +ffmpeg -i in.flac -filter_complex 'acrossover=split=1500 8000:order=8th[LOW][MID][HIGH]' -map '[LOW]' low.wav -map '[MID]' mid.wav -map '[HIGH]' high.wav +@end example +@end itemize + @section acrusher Reduce audio bit resolution. @@ -572,6 +640,10 @@ Set LFO rate. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section acue Delay audio filtering until a given wallclock timestamp. See the @ref{cue} @@ -584,44 +656,44 @@ autoregressive modelling. @table @option -@item w +@item window, w Set window size, in milliseconds. Allowed range is from @code{10} to @code{100}. Default value is @code{55} milliseconds. This sets size of window which will be processed at once. -@item o +@item overlap, o Set window overlap, in percentage of window size. Allowed range is from @code{50} to @code{95}. Default value is @code{75} percent. Setting this to a very high value increases impulsive noise removal but makes whole process much slower. -@item a +@item arorder, a Set autoregression order, in percentage of window size. Allowed range is from @code{0} to @code{25}. Default value is @code{2} percent. This option also controls quality of interpolated samples using neighbour good samples. -@item t +@item threshold, t Set threshold value. Allowed range is from @code{1} to @code{100}. Default value is @code{2}. This controls the strength of impulsive noise which is going to be removed. The lower value, the more samples will be detected as impulsive noise. -@item b +@item burst, b Set burst fusion, in percentage of window size. Allowed range is @code{0} to @code{10}. Default value is @code{2}. If any two samples detected as noise are spaced less than this value then any sample between those two samples will be also detected as noise. -@item m +@item method, m Set overlap method. It accepts the following values: @table @option -@item a +@item add, a Select overlap-add method. Even not interpolated samples are slightly changed with this method. -@item s +@item save, s Select overlap-save method. Not interpolated samples remain unchanged. @end table @@ -635,38 +707,38 @@ autoregressive modelling. @table @option -@item w +@item window, w Set window size, in milliseconds. Allowed range is from @code{10} to @code{100}. Default value is @code{55} milliseconds. This sets size of window which will be processed at once. -@item o +@item overlap, o Set window overlap, in percentage of window size. Allowed range is from @code{50} to @code{95}. Default value is @code{75} percent. -@item a +@item arorder, a Set autoregression order, in percentage of window size. Allowed range is from @code{0} to @code{25}. Default value is @code{8} percent. This option also controls quality of interpolated samples using neighbour good samples. -@item t +@item threshold, t Set threshold value. Allowed range is from @code{1} to @code{100}. Default value is @code{10}. Higher values make clip detection less aggressive. -@item n +@item hsize, n Set size of histogram used to detect clips. Allowed range is from @code{100} to @code{9999}. Default value is @code{1000}. Higher values make clip detection less aggressive. -@item m +@item method, m Set overlap method. It accepts the following values: @table @option -@item a +@item add, a Select overlap-add method. Even not interpolated samples are slightly changed with this method. -@item s +@item save, s Select overlap-save method. Not interpolated samples remain unchanged. @end table @@ -688,6 +760,10 @@ smaller than number of channels all remaining channels will not be delayed. If you want to delay exact number of samples, append 'S' to number. If you want instead to delay in seconds, append 's' to number. + +@item all +Use last set delay for all remaining channels. By default is disabled. +This option if enabled changes how option @code{delays} is interpreted. @end table @subsection Examples @@ -706,8 +782,47 @@ @example adelay=0|500S|700S @end example + +@item +Delay all channels by same number of samples: +@example +adelay=delays=64S:all=1 +@end example @end itemize +@section adenorm +Remedy denormals in audio by adding extremely low-level noise. + +This filter shall be placed before any filter that can produce denormals. + +A description of the accepted parameters follows. + +@table @option +@item level +Set level of added noise in dB. Default is @code{-351}. +Allowed range is from -451 to -90. + +@item type +Set type of added noise. + +@table @option +@item dc +Add DC signal. +@item ac +Add AC signal. +@item square +Add square signal. +@item pulse +Add pulse signal. +@end table + +Default is @code{dc}. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section aderivative, aintegral Compute derivative/integral of audio stream. @@ -756,7 +871,7 @@ @end example @item -If delay is very short, then it sound like a (metallic) robot playing music: +If delay is very short, then it sounds like a (metallic) robot playing music: @example aecho=0.8:0.88:6:0.4 @end example @@ -820,6 +935,10 @@ @end table @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section aeval Modify an audio signal according to the specified expressions. @@ -884,6 +1003,62 @@ @end example @end itemize +@section aexciter + +An exciter is used to produce high sound that is not present in the +original signal. This is done by creating harmonic distortions of the +signal which are restricted in range and added to the original signal. +An Exciter raises the upper end of an audio signal without simply raising +the higher frequencies like an equalizer would do to create a more +"crisp" or "brilliant" sound. + +The filter accepts the following options: + +@table @option +@item level_in +Set input level prior processing of signal. +Allowed range is from 0 to 64. +Default value is 1. + +@item level_out +Set output level after processing of signal. +Allowed range is from 0 to 64. +Default value is 1. + +@item amount +Set the amount of harmonics added to original signal. +Allowed range is from 0 to 64. +Default value is 1. + +@item drive +Set the amount of newly created harmonics. +Allowed range is from 0.1 to 10. +Default value is 8.5. + +@item blend +Set the octave of newly created harmonics. +Allowed range is from -10 to 10. +Default value is 0. + +@item freq +Set the lower frequency limit of producing harmonics in Hz. +Allowed range is from 2000 to 12000 Hz. +Default is 7500 Hz. + +@item ceil +Set the upper frequency limit of producing harmonics. +Allowed range is from 9999 to 20000 Hz. +If value is lower than 10000 Hz no limit is applied. + +@item listen +Mute the original signal and output only added harmonics. +By default is disabled. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @anchor{afade} @section afade @@ -962,11 +1137,19 @@ select double-exponential sigmoid @item losi select logistic sigmoid +@item sinc +select sine cardinal function +@item isinc +select inverted sine cardinal function @item nofade no fade applied @end table @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @subsection Examples @itemize @@ -1143,12 +1326,24 @@ @example afftfilt="'real=re * (1-clip((b/nb)*b,0,1))':imag='im * (1-clip((b/nb)*b,0,1))'" @end example + +@item +Apply robotize effect: +@example +afftfilt="real='hypot(re,im)*sin(0)':imag='hypot(re,im)*cos(0)':win_size=512:overlap=0.75" +@end example + +@item +Apply whisper effect: +@example +afftfilt="real='hypot(re,im)*cos((random(0)*2-1)*2*3.14)':imag='hypot(re,im)*sin((random(1)*2-1)*2*3.14)':win_size=128:overlap=0.8" +@end example @end itemize @anchor{afir} @section afir -Apply an arbitrary Frequency Impulse Response filter. +Apply an arbitrary Finite Impulse Response filter. This filter is designed for applying long FIR filters, up to 60 seconds long. @@ -1157,11 +1352,11 @@ room equalization, cross talk cancellation, wavefield synthesis, auralization, ambiophonics, ambisonics and spatialization. -This filter uses second stream as FIR coefficients. -If second stream holds single channel, it will be used -for all input channels in first stream, otherwise -number of channels in second stream must be same as -number of channels in first stream. +This filter uses the streams higher than first one as FIR coefficients. +If the non-first stream holds a single channel, it will be used +for all input channels in the first stream, otherwise +the number of channels in the non-first stream must be same as +the number of channels in the first stream. It accepts the following parameters: @@ -1222,13 +1417,22 @@ @item minp Set minimal partition size used for convolution. Default is @var{8192}. -Allowed range is from @var{8} to @var{32768}. +Allowed range is from @var{1} to @var{32768}. Lower values decreases latency at cost of higher CPU usage. @item maxp Set maximal partition size used for convolution. Default is @var{8192}. Allowed range is from @var{8} to @var{32768}. Lower values may increase CPU usage. + +@item nbirs +Set number of input impulse responses streams which will be switchable at runtime. +Allowed range is from @var{1} to @var{32}. Default is @var{1}. + +@item ir +Set IR stream which will be used for convolution, starting from @var{0}, should always be +lower than supplied value by @code{nbirs} option. Default is @var{0}. +This option can be changed at runtime via @ref{commands}. @end table @subsection Examples @@ -1250,13 +1454,13 @@ It accepts the following parameters: @table @option -@item sample_fmts +@item sample_fmts, f A '|'-separated list of requested sample formats. -@item sample_rates +@item sample_rates, r A '|'-separated list of requested sample rates. -@item channel_layouts +@item channel_layouts, cl A '|'-separated list of requested channel layouts. See @ref{channel layout syntax,,the Channel Layout section in the ffmpeg-utils(1) manual,ffmpeg-utils} @@ -1270,6 +1474,25 @@ aformat=sample_fmts=u8|s16:channel_layouts=stereo @end example +@section afreqshift +Apply frequency shift to input audio samples. + +The filter accepts the following options: + +@table @option +@item shift +Specify frequency shift. Allowed range is -INT_MAX to INT_MAX. +Default value is 0.0. + +@item level +Set output gain applied to final output. Allowed range is from 0.0 to 1.0. +Default value is 1.0. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section agate A gate is mainly used to reduce lower parts of a signal. This kind of signal @@ -1338,6 +1561,10 @@ Default is @code{average}. Can be @code{average} or @code{maximum}. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section aiir Apply an arbitrary Infinite Impulse Response filter. @@ -1345,13 +1572,13 @@ It accepts the following parameters: @table @option -@item z -Set numerator/zeros coefficients. +@item zeros, z +Set B/numerator/zeros/reflection coefficients. -@item p -Set denominator/poles coefficients. +@item poles, p +Set A/denominator/poles/ladder coefficients. -@item k +@item gains, k Set channels gains. @item dry_gain @@ -1360,25 +1587,39 @@ @item wet_gain Set output gain. -@item f +@item format, f Set coefficients format. @table @samp +@item ll +lattice-ladder function +@item sf +analog transfer function @item tf -transfer function +digital transfer function @item zp Z-plane zeros/poles, cartesian (default) @item pr Z-plane zeros/poles, polar radians @item pd Z-plane zeros/poles, polar degrees +@item sp +S-plane zeros/poles @end table -@item r -Set kind of processing. -Can be @code{d} - direct or @code{s} - serial cascading. Default is @code{s}. +@item process, r +Set type of processing. -@item e +@table @samp +@item d +direct processing +@item s +serial processing +@item p +parallel processing +@end table + +@item precision, e Set filtering precision. @table @samp @@ -1392,6 +1633,10 @@ 16-bit integers @end table +@item normalize, n +Normalize filter coefficients, by default is enabled. +Enabling it will normalize magnitude response at DC to 0dB. + @item mix How much to use filtered signal in output. Default is 1. Range is between 0 and 1. @@ -1408,7 +1653,7 @@ Set video stream size. This option is used only when @var{response} is enabled. @end table -Coefficients in @code{tf} format are separated by spaces and are in ascending +Coefficients in @code{tf} and @code{sf} format are separated by spaces and are in ascending order. Coefficients in @code{zp} format are separated by spaces and order of coefficients @@ -1433,6 +1678,12 @@ @example aiir=k=0.79575848078096756:z=0.80918701+0.58773007i 0.80918701-0.58773007i 0.80884700+0.58784055i 0.80884700-0.58784055i:p=0.63892345+0.59951235i 0.63892345-0.59951235i 0.79582691+0.44198673i 0.79582691-0.44198673i:f=zp:r=s @end example + +@item +Apply 3-rd order analog normalized Butterworth low-pass filter, using analog transfer function format: +@example +aiir=z=1.3057 0 0 0:p=1.3057 2.3892 2.1860 1:f=sf:r=d +@end example @end itemize @section alimiter @@ -1516,6 +1767,37 @@ @item channels, c Specify which channels to filter, by default all available are filtered. + +@item normalize, n +Normalize biquad coefficients, by default is disabled. +Enabling it will normalize magnitude response at DC to 0dB. + +@item order, o +Set the filter order, can be 1 or 2. Default is 2. + +@item transform, a +Set transform type of IIR filter. +@table @option +@item di +@item dii +@item tdii +@item latt +@end table + +@item precision, r +Set precison of filtering. +@table @option +@item auto +Pick automatic sample format depending on surround filters. +@item s16 +Always use signed 16-bit. +@item s32 +Always use signed 32-bit. +@item f32 +Always use float 32-bit. +@item f64 +Always use float 64-bit. +@end table @end table @subsection Commands @@ -1653,6 +1935,20 @@ @item weights Specify weight of each input audio stream as sequence. Each weight is separated by space. By default all inputs have same weight. + +@item normalize +Always scale inputs instead of only doing summation of samples. +Beware of heavy clipping if inputs are not normalized prior or after filtering +by this filter if this option is disabled. By default is enabled. +@end table + +@subsection Commands + +This filter supports the following commands: +@table @option +@item weights +@item sum +Syntax is same as option with same name. @end table @section amultiply @@ -1686,7 +1982,7 @@ If input doesn't have that frequency the entry is ignored. @item w -Set band width in hertz. +Set band width in Hertz. @item g Set band gain in dB. @@ -1751,7 +2047,7 @@ @var{fN} is existing filter number, starting from 0, if no such filter is available error is returned. @var{freq} set new frequency parameter. -@var{width} set new width parameter in herz. +@var{width} set new width parameter in Hertz. @var{gain} set new gain parameter in dB. Full filter invocation with asendcmd may look like this: @@ -1766,7 +2062,7 @@ context similarity is defined by comparing their surrounding patches of size @option{p}. Patches are searched in an area of @option{r} around the sample. -The filter accepts the following options. +The filter accepts the following options: @table @option @item s @@ -1803,17 +2099,64 @@ @subsection Commands -This filter supports the following commands: +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. + +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, +2nd input audio stream and the actual signal, the 1st input audio stream). + +A description of the accepted options follows. + @table @option -@item s -Change denoise strength. Argument is single float number. -Syntax for the command is : "@var{s}" +@item order +Set filter order. + +@item mu +Set filter mu. + +@item eps +Set the filter eps. + +@item leakage +Set the filter leakage. + +@item out_mode +It accepts the following values: +@table @option +@item i +Pass the 1st input. + +@item d +Pass the 2nd input. @item o -Change output mode. -Syntax for the command is : "i", "o" or "n" string. +Pass filtered samples. + +@item n +Pass difference between desired and filtered samples. + +Default value is @var{o}. +@end table @end table +@subsection Examples + +@itemize +@item +One of many usages of this filter is noise reduction, input audio is filtered +with same samples that are delayed by fixed amount, one such example for stereo audio is: +@example +asplit[a][b],[a]adelay=32S|32S[a],[b][a]anlms=order=128:leakage=0.0005:mu=.5:out_mode=o +@end example +@end itemize + +@subsection Commands + +This filter supports the same commands as options, excluding option @code{order}. + @section anull Pass the audio source unchanged to the output. @@ -1919,6 +2262,25 @@ @end table @end table +@section aphaseshift +Apply phase shift to input audio samples. + +The filter accepts the following options: + +@table @option +@item shift +Specify phase shift. Allowed range is from -1.0 to 1.0. +Default value is 0.0. + +@item level +Set output gain applied to final output. Allowed range is from 0.0 to 1.0. +Default value is 1.0. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section apulsator Audio pulsator is something between an autopanner and a tremolo. @@ -2029,6 +2391,28 @@ @end example @end itemize +@section arnndn + +Reduce noise from speech using Recurrent Neural Networks. + +This filter accepts the following options: + +@table @option +@item model, m +Set train model file to load. This option is always required. + +@item mix +Set how much to mix filtered samples into final output. +Allowed range is from -1 to 1. Default value is 1. +Negative values are special, they set how much to keep filtered noise +in the final filter output. Set this option to -1 to hear actual +noise removed from input signal. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section asetnsamples Set the number of samples per each output audio frame. @@ -2129,6 +2513,7 @@ It accepts the following values: @table @option +@item hard @item tanh @item atan @item cubic @@ -2136,12 +2521,26 @@ @item alg @item quintic @item sin +@item erf @end table +@item threshold +Set threshold from where to start clipping. Default value is 0dB or 1. + +@item output +Set gain applied to output. Default value is 0dB or 1. + @item param Set additional parameter which controls sigmoid function. + +@item oversample +Set oversampling factor. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section asr Automatic Speech Recognition @@ -2210,6 +2609,8 @@ Crest_factor Flat_factor Peak_count +Noise_floor +Noise_floor_count Bit_depth Dynamic_range Zero_crossings @@ -2232,6 +2633,8 @@ RMS_trough Flat_factor Peak_count +Noise_floor +Noise_floor_count Bit_depth Number_of_samples Number_of_NaNs @@ -2303,6 +2706,13 @@ Number of occasions (not the number of samples) that the signal attained either @var{Min level} or @var{Max level}. +@item Noise floor dB +Minimum local peak measured in dBFS over a short window. + +@item Noise floor count +Number of occasions (not the number of samples) that the signal attained +@var{Noise floor}. + @item Bit depth Overall bit depth of audio. Number of bits used for each sample. @@ -2316,23 +2726,160 @@ Rate of Zero crossings and number of audio samples. @end table -@section atempo +@section asubboost +Boost subwoofer frequencies. -Adjust audio tempo. +The filter accepts the following options: -The filter accepts exactly one parameter, the audio tempo. If not -specified then the filter will assume nominal 1.0 tempo. Tempo must -be in the [0.5, 100.0] range. +@table @option +@item dry +Set dry gain, how much of original signal is kept. Allowed range is from 0 to 1. +Default value is 0.7. -Note that tempo greater than 2 will skip some samples rather than -blend them in. If for any reason this is a concern it is always -possible to daisy-chain several instances of atempo to achieve the -desired product tempo. +@item wet +Set wet gain, how much of filtered signal is kept. Allowed range is from 0 to 1. +Default value is 0.7. -@subsection Examples +@item decay +Set delay line decay gain value. Allowed range is from 0 to 1. +Default value is 0.7. -@itemize -@item +@item feedback +Set delay line feedback gain value. Allowed range is from 0 to 1. +Default value is 0.9. + +@item cutoff +Set cutoff frequency in Hertz. Allowed range is 50 to 900. +Default value is 100. + +@item slope +Set slope amount for cutoff frequency. Allowed range is 0.0001 to 1. +Default value is 0.5. + +@item delay +Set delay. Allowed range is from 1 to 100. +Default value is 20. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section asubcut +Cut subwoofer frequencies. + +This filter allows to set custom, steeper +roll off than highpass filter, and thus is able to more attenuate +frequency content in stop-band. + +The filter accepts the following options: + +@table @option +@item cutoff +Set cutoff frequency in Hertz. Allowed range is 2 to 200. +Default value is 20. + +@item order +Set filter order. Available values are from 3 to 20. +Default value is 10. + +@item level +Set input gain level. Allowed range is from 0 to 1. Default value is 1. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section asupercut +Cut super frequencies. + +The filter accepts the following options: + +@table @option +@item cutoff +Set cutoff frequency in Hertz. Allowed range is 20000 to 192000. +Default value is 20000. + +@item order +Set filter order. Available values are from 3 to 20. +Default value is 10. + +@item level +Set input gain level. Allowed range is from 0 to 1. Default value is 1. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section asuperpass +Apply high order Butterworth band-pass filter. + +The filter accepts the following options: + +@table @option +@item centerf +Set center frequency in Hertz. Allowed range is 2 to 999999. +Default value is 1000. + +@item order +Set filter order. Available values are from 4 to 20. +Default value is 4. + +@item qfactor +Set Q-factor. Allowed range is from 0.01 to 100. Default value is 1. + +@item level +Set input gain level. Allowed range is from 0 to 2. Default value is 1. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section asuperstop +Apply high order Butterworth band-stop filter. + +The filter accepts the following options: + +@table @option +@item centerf +Set center frequency in Hertz. Allowed range is 2 to 999999. +Default value is 1000. + +@item order +Set filter order. Available values are from 4 to 20. +Default value is 4. + +@item qfactor +Set Q-factor. Allowed range is from 0.01 to 100. Default value is 1. + +@item level +Set input gain level. Allowed range is from 0 to 2. Default value is 1. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section atempo + +Adjust audio tempo. + +The filter accepts exactly one parameter, the audio tempo. If not +specified then the filter will assume nominal 1.0 tempo. Tempo must +be in the [0.5, 100.0] range. + +Note that tempo greater than 2 will skip some samples rather than +blend them in. If for any reason this is a concern it is always +possible to daisy-chain several instances of atempo to achieve the +desired product tempo. + +@subsection Examples + +@itemize +@item Slow down audio to 80% tempo: @example atempo=0.8 @@ -2351,6 +2898,15 @@ @end example @end itemize +@subsection Commands + +This filter supports the following commands: +@table @option +@item tempo +Change filter tempo scale factor. +Syntax for the command is : "@var{tempo}" +@end table + @section atrim Trim the input so that the output contains one continuous subpart of the input. @@ -2420,6 +2976,39 @@ @end itemize +@section axcorrelate +Calculate normalized cross-correlation between two input audio streams. + +Resulted samples are always between -1 and 1 inclusive. +If result is 1 it means two input samples are highly correlated in that selected segment. +Result 0 means they are not correlated at all. +If result is -1 it means two input samples are out of phase, which means they cancel each +other. + +The filter accepts the following options: + +@table @option +@item size +Set size of segment over which cross-correlation is calculated. +Default is 256. Allowed range is from 2 to 131072. + +@item algo +Set algorithm for cross-correlation. Can be @code{slow} or @code{fast}. +Default is @code{slow}. Fast algorithm assumes mean values over any given segment +are always zero and thus need much less calculations to make. +This is generally not true, but is valid for typical audio streams. +@end table + +@subsection Examples + +@itemize +@item +Calculate correlation between channels in stereo audio stream: +@example +ffmpeg -i stereo.wav -af channelsplit,axcorrelate=size=1024:algo=fast correlation.wav +@end example +@end itemize + @section bandpass Apply a two-pole Butterworth band-pass filter with central @@ -2461,6 +3050,34 @@ @item channels, c Specify which channels to filter, by default all available are filtered. + +@item normalize, n +Normalize biquad coefficients, by default is disabled. +Enabling it will normalize magnitude response at DC to 0dB. + +@item transform, a +Set transform type of IIR filter. +@table @option +@item di +@item dii +@item tdii +@item latt +@end table + +@item precision, r +Set precison of filtering. +@table @option +@item auto +Pick automatic sample format depending on surround filters. +@item s16 +Always use signed 16-bit. +@item s32 +Always use signed 32-bit. +@item f32 +Always use float 32-bit. +@item f64 +Always use float 64-bit. +@end table @end table @subsection Commands @@ -2520,6 +3137,34 @@ @item channels, c Specify which channels to filter, by default all available are filtered. + +@item normalize, n +Normalize biquad coefficients, by default is disabled. +Enabling it will normalize magnitude response at DC to 0dB. + +@item transform, a +Set transform type of IIR filter. +@table @option +@item di +@item dii +@item tdii +@item latt +@end table + +@item precision, r +Set precison of filtering. +@table @option +@item auto +Pick automatic sample format depending on surround filters. +@item s16 +Always use signed 16-bit. +@item s32 +Always use signed 32-bit. +@item f32 +Always use float 32-bit. +@item f64 +Always use float 64-bit. +@end table @end table @subsection Commands @@ -2580,12 +3225,43 @@ @item width, w Determine how steep is the filter's shelf transition. +@item poles, p +Set number of poles. Default is 2. + @item mix, m How much to use filtered signal in output. Default is 1. Range is between 0 and 1. @item channels, c Specify which channels to filter, by default all available are filtered. + +@item normalize, n +Normalize biquad coefficients, by default is disabled. +Enabling it will normalize magnitude response at DC to 0dB. + +@item transform, a +Set transform type of IIR filter. +@table @option +@item di +@item dii +@item tdii +@item latt +@end table + +@item precision, r +Set precison of filtering. +@table @option +@item auto +Pick automatic sample format depending on surround filters. +@item s16 +Always use signed 16-bit. +@item s32 +Always use signed 32-bit. +@item f32 +Always use float 32-bit. +@item f64 +Always use float 64-bit. +@end table @end table @subsection Commands @@ -2637,6 +3313,37 @@ @item mix, m How much to use filtered signal in output. Default is 1. Range is between 0 and 1. + +@item channels, c +Specify which channels to filter, by default all available are filtered. + +@item normalize, n +Normalize biquad coefficients, by default is disabled. +Enabling it will normalize magnitude response at DC to 0dB. + +@item transform, a +Set transform type of IIR filter. +@table @option +@item di +@item dii +@item tdii +@item latt +@end table + +@item precision, r +Set precison of filtering. +@table @option +@item auto +Pick automatic sample format depending on surround filters. +@item s16 +Always use signed 16-bit. +@item s32 +Always use signed 32-bit. +@item f32 +Always use float 32-bit. +@item f64 +Always use float 64-bit. +@end table @end table @section bs2b @@ -2965,12 +3672,12 @@ positions of microphones or speakers. For example, you have recorded guitar with two microphones placed in -different location. Because the front of sound wave has fixed speed in +different locations. Because the front of sound wave has fixed speed in normal conditions, the phasing of microphones can vary and depends on their location and interposition. The best sound mix can be achieved when -these microphones are in phase (synchronized). Note that distance of -~30 cm between microphones makes one microphone to capture signal in -antiphase to another microphone. That makes the final mix sounding moody. +these microphones are in phase (synchronized). Note that a distance of +~30 cm between microphones makes one microphone capture the signal in +antiphase to the other microphone. That makes the final mix sound moody. This filter helps to solve phasing problems by adding different delays to each microphone track and make them synchronized. @@ -2979,7 +3686,7 @@ Remember that synchronization/delay tolerance depends on sample rate, too. Higher sample rates will give more tolerance. -It accepts the following parameters: +The filter accepts the following parameters: @table @option @item mm @@ -3003,7 +3710,7 @@ Default is 1. @item temp -Set temperature degree in Celsius. This is the temperature of the environment. +Set temperature in degrees Celsius. This is the temperature of the environment. Default is 20. @end table @@ -3029,6 +3736,10 @@ This sets cut off frequency of low shelf filter. Default is cut off near 1550 Hz. With range set to 1 cut off frequency is set to 2100 Hz. +@item slope +Set curve slope of low shelf filter. Default is 0.5. +Allowed range is from 0.01 to 1. + @item level_in Set input gain. Default is 0.9. @@ -3036,20 +3747,31 @@ Set output gain. Default is 1. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section crystalizer -Simple algorithm to expand audio dynamic range. +Simple algorithm for audio noise sharpening. + +This filter linearly increases differences betweeen each audio sample. The filter accepts the following options: @table @option @item i -Sets the intensity of effect (default: 2.0). Must be in range between 0.0 +Sets the intensity of effect (default: 2.0). Must be in range between -10.0 to 0 (unchanged sound) to 10.0 (maximum effect). +To inverse filtering use negative value. @item c Enable clipping. By default is enabled. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section dcshift Apply a DC shift to the audio. @@ -3135,7 +3857,7 @@ of the dynamic range *within* each section of the audio file. @table @option -@item f +@item framelen, f Set the frame length in milliseconds. In range from 10 to 8000 milliseconds. Default is 500 milliseconds. The Dynamic Audio Normalizer processes the input audio in small chunks, @@ -3150,7 +3872,7 @@ Note that the exact frame length, in number of samples, will be determined automatically, based on the sampling rate of the individual input audio file. -@item g +@item gausssize, g Set the Gaussian filter window size. In range from 3 to 301, must be odd number. Default is 31. Probably the most important parameter of the Dynamic Audio Normalizer is the @@ -3167,7 +3889,7 @@ contrary, the more you decrease this value, the more the Dynamic Audio Normalizer will behave like a dynamic range compressor. -@item p +@item peak, p Set the target peak value. This specifies the highest permissible magnitude level for the normalized audio input. This filter will try to approach the target peak magnitude as closely as possible, but at the same time it also @@ -3176,7 +3898,7 @@ magnitude. The default value is 0.95 and thus leaves a headroom of 5%*. It is not recommended to go above this value. -@item m +@item maxgain, m Set the maximum gain factor. In range from 1.0 to 100.0. Default is 10.0. The Dynamic Audio Normalizer determines the maximum possible (local) gain factor for each input frame, i.e. the maximum gain factor that does not @@ -3194,7 +3916,7 @@ gain factors will smoothly approach the threshold value, but never exceed that value. -@item r +@item targetrms, r Set the target RMS. In range from 0.0 to 1.0. Default is 0.0 - disabled. By default, the Dynamic Audio Normalizer performs "peak" normalization. This means that the maximum local gain factor for each frame is defined @@ -3212,7 +3934,7 @@ Note, however, that the maximum local gain factor is still restricted by the frame's highest magnitude sample, in order to prevent clipping. -@item n +@item coupling, n Enable channels coupling. By default is enabled. By default, the Dynamic Audio Normalizer will amplify all channels by the same amount. This means the same gain factor will be applied to all channels, i.e. @@ -3224,7 +3946,7 @@ only on the individual channel's highest magnitude sample. This allows for harmonizing the volume of the different channels. -@item c +@item correctdc, c Enable DC bias correction. By default is disabled. An audio signal (in the time domain) is a sequence of sample values. In the Dynamic Audio Normalizer these sample values are represented in the @@ -3243,7 +3965,7 @@ boundaries, the DC correction offset values will be interpolated smoothly between neighbouring frames. -@item b +@item altboundary, b Enable alternative boundary mode. By default is disabled. The Dynamic Audio Normalizer takes into account a certain neighbourhood around each frame. This includes the preceding frames as well as the @@ -3258,7 +3980,7 @@ of exactly 1.0 for the missing frames, resulting in a smooth "fade in" and "fade out" at the beginning and at the end of the input, respectively. -@item s +@item compress, s Set the compress factor. In range from 0.0 to 30.0. Default is 0.0. By default, the Dynamic Audio Normalizer does not apply "traditional" compression. This means that signal peaks will not be pruned and thus the @@ -3275,8 +3997,20 @@ frame. In general, smaller parameters result in stronger compression, and vice versa. Values below 3.0 are not recommended, because audible distortion may appear. + +@item threshold, t +Set the target threshold value. This specifies the lowest permissible +magnitude level for the audio input which will be normalized. +If input frame volume is above this value frame will be normalized. +Otherwise frame may not be normalized at all. The default value is set +to 0, which means all input frames will be normalized. +This option is mostly useful if digital noise is not wanted to be amplified. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section earwax Make audio easier to listen to on headphones. @@ -3332,6 +4066,34 @@ @item channels, c Specify which channels to filter, by default all available are filtered. + +@item normalize, n +Normalize biquad coefficients, by default is disabled. +Enabling it will normalize magnitude response at DC to 0dB. + +@item transform, a +Set transform type of IIR filter. +@table @option +@item di +@item dii +@item tdii +@item latt +@end table + +@item precision, r +Set precison of filtering. +@table @option +@item auto +Pick automatic sample format depending on surround filters. +@item s16 +Always use signed 16-bit. +@item s32 +Always use signed 32-bit. +@item f32 +Always use float 32-bit. +@item f64 +Always use float 64-bit. +@end table @end table @subsection Examples @@ -3391,6 +4153,10 @@ Enable clipping. By default is enabled. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section firequalizer Apply FIR Equalization using arbitrary frequency response. @@ -3801,6 +4567,34 @@ @item channels, c Specify which channels to filter, by default all available are filtered. + +@item normalize, n +Normalize biquad coefficients, by default is disabled. +Enabling it will normalize magnitude response at DC to 0dB. + +@item transform, a +Set transform type of IIR filter. +@table @option +@item di +@item dii +@item tdii +@item latt +@end table + +@item precision, r +Set precison of filtering. +@table @option +@item auto +Pick automatic sample format depending on surround filters. +@item s16 +Always use signed 16-bit. +@item s32 +Always use signed 32-bit. +@item f32 +Always use float 32-bit. +@item f64 +Always use float 64-bit. +@end table @end table @subsection Commands @@ -3914,6 +4708,9 @@ supposed to be generated forever. Only used if plugin have zero inputs. +@item latency, l +Enable latency compensation, by default is disabled. +Only used if plugin have inputs. @end table @subsection Examples @@ -4019,8 +4816,8 @@ EBU R128 loudness normalization. Includes both dynamic and linear normalization modes. Support for both single pass (livestreams, files) and double pass (files) modes. -This algorithm can target IL, LRA, and maximum true peak. To accurately detect true peaks, -the audio stream will be upsampled to 192 kHz unless the normalization mode is linear. +This algorithm can target IL, LRA, and maximum true peak. In dynamic mode, to accurately +detect true peaks, the audio stream will be upsampled to 192 kHz. Use the @code{-ar} option or @code{aresample} filter to explicitly set an output sample rate. The filter accepts the following options: @@ -4059,10 +4856,13 @@ Range is -99.0 - +99.0. Default is +0.0. @item linear -Normalize linearly if possible. -measured_I, measured_LRA, measured_TP, and measured_thresh must also -to be specified in order to use this mode. -Options are true or false. Default is true. +Normalize by linearly scaling the source audio. +@code{measured_I}, @code{measured_LRA}, @code{measured_TP}, +and @code{measured_thresh} must all be specified. Target LRA shouldn't +be lower than source LRA and the change in integrated loudness shouldn't +result in a true peak which exceeds the target TP. If any of these +conditions aren't met, normalization mode will revert to @var{dynamic}. +Options are @code{true} or @code{false}. Default is @code{true}. @item dual_mono Treat mono input files as "dual-mono". If a mono file is intended for playback @@ -4117,6 +4917,34 @@ @item channels, c Specify which channels to filter, by default all available are filtered. + +@item normalize, n +Normalize biquad coefficients, by default is disabled. +Enabling it will normalize magnitude response at DC to 0dB. + +@item transform, a +Set transform type of IIR filter. +@table @option +@item di +@item dii +@item tdii +@item latt +@end table + +@item precision, r +Set precison of filtering. +@table @option +@item auto +Pick automatic sample format depending on surround filters. +@item s16 +Always use signed 16-bit. +@item s32 +Always use signed 32-bit. +@item f32 +Always use float 32-bit. +@item f64 +Always use float 64-bit. +@end table @end table @subsection Examples @@ -4410,6 +5238,19 @@ @end table @end table +@subsection Commands + +This filter supports the following commands: +@table @option +@item tempo +Change filter tempo scale factor. +Syntax for the command is : "@var{tempo}" + +@item pitch +Change filter pitch scale factor. +Syntax for the command is : "@var{pitch}" +@end table + @section sidechaincompress This filter acts like normal compressor but has the ability to compress @@ -4472,6 +5313,10 @@ Range is between 0 and 1. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @subsection Examples @itemize @@ -4555,6 +5400,10 @@ Set sidechain gain. Default is 1. Range is from 0.015625 to 64. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section silencedetect Detect silence in an audio stream. @@ -4563,7 +5412,16 @@ or equal to a noise tolerance value for a duration greater or equal to the minimum detected noise duration. -The printed times and duration are expressed in seconds. +The printed times and duration are expressed in seconds. The +@code{lavfi.silence_start} or @code{lavfi.silence_start.X} metadata key +is set on the first frame whose timestamp equals or exceeds the detection +duration and it contains the timestamp of the first frame of the silence. + +The @code{lavfi.silence_duration} or @code{lavfi.silence_duration.X} +and @code{lavfi.silence_end} or @code{lavfi.silence_end.X} metadata +keys are set on the first frame after the silence. If @option{mono} is +enabled, and each channel is evaluated separately, the @code{.X} +suffixed keys are used, and @code{X} corresponds to the channel number. The filter accepts the following options: @@ -4573,7 +5431,9 @@ specified value) or amplitude ratio. Default is -60dB, or 0.001. @item duration, d -Set silence duration until notification (default is 2 seconds). +Set silence duration until notification (default is 2 seconds). See +@ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils} +for the accepted syntax. @item mono, m Process each channel separately, instead of combined. By default is disabled. @@ -4699,6 +5559,14 @@ @example silenceremove=stop_periods=-1:stop_duration=1:stop_threshold=-90dB @end example + +@item +Trim all digital silence samples, using peak detection, from beginning to end +where there is more than 0 samples of digital silence in audio and digital +silence is detected in all channels at same positions in stream: +@example +silenceremove=window=0:detection=peak:stop_mode=all:start_mode=all:stop_periods=-1:stop_threshold=0 +@end example @end itemize @section sofalizer @@ -4797,6 +5665,69 @@ @end example @end itemize +@section speechnorm +Speech Normalizer. + +This filter expands or compresses each half-cycle of audio samples +(local set of samples all above or all below zero and between two nearest zero crossings) depending +on threshold value, so audio reaches target peak value under conditions controlled by below options. + +The filter accepts the following options: + +@table @option +@item peak, p +Set the expansion target peak value. This specifies the highest allowed absolute amplitude +level for the normalized audio input. Default value is 0.95. Allowed range is from 0.0 to 1.0. + +@item expansion, e +Set the maximum expansion factor. Allowed range is from 1.0 to 50.0. Default value is 2.0. +This option controls maximum local half-cycle of samples expansion. The maximum expansion +would be such that local peak value reaches target peak value but never to surpass it and that +ratio between new and previous peak value does not surpass this option value. + +@item compression, c +Set the maximum compression factor. Allowed range is from 1.0 to 50.0. Default value is 2.0. +This option controls maximum local half-cycle of samples compression. This option is used +only if @option{threshold} option is set to value greater than 0.0, then in such cases +when local peak is lower or same as value set by @option{threshold} all samples belonging to +that peak's half-cycle will be compressed by current compression factor. + +@item threshold, t +Set the threshold value. Default value is 0.0. Allowed range is from 0.0 to 1.0. +This option specifies which half-cycles of samples will be compressed and which will be expanded. +Any half-cycle samples with their local peak value below or same as this option value will be +compressed by current compression factor, otherwise, if greater than threshold value they will be +expanded with expansion factor so that it could reach peak target value but never surpass it. + +@item raise, r +Set the expansion raising amount per each half-cycle of samples. Default value is 0.001. +Allowed range is from 0.0 to 1.0. This controls how fast expansion factor is raised per +each new half-cycle until it reaches @option{expansion} value. +Setting this options too high may lead to distortions. + +@item fall, f +Set the compression raising amount per each half-cycle of samples. Default value is 0.001. +Allowed range is from 0.0 to 1.0. This controls how fast compression factor is raised per +each new half-cycle until it reaches @option{compression} value. + +@item channels, h +Specify which channels to filter, by default all available channels are filtered. + +@item invert, i +Enable inverted filtering, by default is disabled. This inverts interpretation of @option{threshold} +option. When enabled any half-cycle of samples with their local peak value below or same as +@option{threshold} option will be expanded otherwise it will be compressed. + +@item link, l +Link channels when calculating gain applied to each filtered channel sample, by default is disabled. +When disabled each filtered channel gain calculation is independent, otherwise when this option +is enabled the minimum of all possible gains for each filtered channel is used. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section stereotools This filter has some handy utilities to manage stereo signals, for converting @@ -4868,6 +5799,12 @@ @item ms>rr Mid/Side to Right/Right. + +@item ms>rl +Mid/Side to Right/Left. + +@item lr>l-r +Left/Right to Left - Right. @end table @item slev @@ -4917,6 +5854,10 @@ @end table @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @subsection Examples @itemize @@ -4960,6 +5901,10 @@ Set level of input signal of original channel. Default is 0.8. @end table +@subsection Commands + +This filter supports the all above options except @code{delay} as @ref{commands}. + @section superequalizer Apply 18 band equalizer. @@ -5187,12 +6132,43 @@ @item width, w Determine how steep is the filter's shelf transition. +@item poles, p +Set number of poles. Default is 2. + @item mix, m How much to use filtered signal in output. Default is 1. Range is between 0 and 1. @item channels, c Specify which channels to filter, by default all available are filtered. + +@item normalize, n +Normalize biquad coefficients, by default is disabled. +Enabling it will normalize magnitude response at DC to 0dB. + +@item transform, a +Set transform type of IIR filter. +@table @option +@item di +@item dii +@item tdii +@item latt +@end table + +@item precision, r +Set precison of filtering. +@table @option +@item auto +Pick automatic sample format depending on surround filters. +@item s16 +Always use signed 16-bit. +@item s32 +Always use signed 32-bit. +@item f32 +Always use float 32-bit. +@item f64 +Always use float 64-bit. +@end table @end table @subsection Commands @@ -5311,6 +6287,11 @@ Default value for @var{replaygain_preamp} is 0.0. +@item replaygain_noclip +Prevent clipping by limiting the gain applied. + +Default value for @var{replaygain_noclip} is 1. + @item eval Set when the volume expression is evaluated. @@ -5370,12 +6351,7 @@ If the specified expression is not valid, it is kept at its current value. -@item replaygain_noclip -Prevent clipping by limiting the gain applied. - -Default value for @var{replaygain_noclip} is 1. - -@end table +@end table @subsection Examples @@ -5461,7 +6437,7 @@ Buffer audio frames, and make them available to the filter chain. This source is mainly intended for a programmatic use, in particular -through the interface defined in @file{libavfilter/asrc_abuffer.h}. +through the interface defined in @file{libavfilter/buffersrc.h}. It accepts the following parameters: @table @option @@ -5602,6 +6578,44 @@ @end itemize +@section afirsrc + +Generate a FIR coefficients using frequency sampling method. + +The resulting stream can be used with @ref{afir} filter for filtering the audio signal. + +The filter accepts the following options: + +@table @option +@item taps, t +Set number of filter coefficents in output audio stream. +Default value is 1025. + +@item frequency, f +Set frequency points from where magnitude and phase are set. +This must be in non decreasing order, and first element must be 0, while last element +must be 1. Elements are separated by white spaces. + +@item magnitude, m +Set magnitude value for every frequency point set by @option{frequency}. +Number of values must be same as number of frequency points. +Values are separated by white spaces. + +@item phase, p +Set phase value for every frequency point set by @option{frequency}. +Number of values must be same as number of frequency points. +Values are separated by white spaces. + +@item sample_rate, r +Set sample rate, default is 44100. + +@item nb_samples, n +Set number of samples per each frame. Default is 1024. + +@item win_func, w +Set window function. Default is blackman. +@end table + @section anullsrc The null audio source, return unprocessed audio frames. It is mainly useful @@ -5629,6 +6643,13 @@ @item nb_samples, n Set the number of samples per requested frames. +@item duration, d +Set the duration of the sourced audio. See +@ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils} +for the accepted syntax. + +If not specified, or the expressed duration is negative, the audio is +supposed to be generated forever. @end table @subsection Examples @@ -5733,7 +6754,7 @@ @item color, colour, c Specify the color of noise. Available noise colors are white, pink, brown, -blue and violet. Default color is white. +blue, violet and velvet. Default color is white. @item seed, s Specify a value used to seed the PRNG. @@ -5931,6 +6952,79 @@ Below is a description of the currently available video filters. +@section addroi + +Mark a region of interest in a video frame. + +The frame data is passed through unchanged, but metadata is attached +to the frame indicating regions of interest which can affect the +behaviour of later encoding. Multiple regions can be marked by +applying the filter multiple times. + +@table @option +@item x +Region distance in pixels from the left edge of the frame. +@item y +Region distance in pixels from the top edge of the frame. +@item w +Region width in pixels. +@item h +Region height in pixels. + +The parameters @var{x}, @var{y}, @var{w} and @var{h} are expressions, +and may contain the following variables: +@table @option +@item iw +Width of the input frame. +@item ih +Height of the input frame. +@end table + +@item qoffset +Quantisation offset to apply within the region. + +This must be a real value in the range -1 to +1. A value of zero +indicates no quality change. A negative value asks for better quality +(less quantisation), while a positive value asks for worse quality +(greater quantisation). + +The range is calibrated so that the extreme values indicate the +largest possible offset - if the rest of the frame is encoded with the +worst possible quality, an offset of -1 indicates that this region +should be encoded with the best possible quality anyway. Intermediate +values are then interpolated in some codec-dependent way. + +For example, in 10-bit H.264 the quantisation parameter varies between +-12 and 51. A typical qoffset value of -1/10 therefore indicates that +this region should be encoded with a QP around one-tenth of the full +range better than the rest of the frame. So, if most of the frame +were to be encoded with a QP of around 30, this region would get a QP +of around 24 (an offset of approximately -1/10 * (51 - -12) = -6.3). +An extreme value of -1 would indicate that this region should be +encoded with the best possible quality regardless of the treatment of +the rest of the frame - that is, should be encoded at a QP of -12. +@item clear +If set to true, remove any existing regions of interest marked on the +frame before adding the new one. +@end table + +@subsection Examples + +@itemize +@item +Mark the centre quarter of the frame as interesting. +@example +addroi=iw/4:ih/4:iw/2:ih/2:-1/10 +@end example +@item +Mark the 100-pixel-wide region on the left edge of the frame as very +uninteresting (to be encoded at much lower quality than the rest of +the frame). +@example +addroi=0:0:100:ih:+1/5 +@end example +@end itemize + @section alphaextract Extract the alpha component from the input as a grayscale video. This @@ -5950,12 +7044,6 @@ movie=in_alpha.mkv [alpha]; [in][alpha] alphamerge [out] @end example -Since this filter is designed for reconstruction, it operates on frame -sequences without considering timestamps, and terminates when either -input reaches end of stream. This will cause problems if your encoding -pipeline drops frames. If you're trying to apply an image as an -overlay to a video stream, consider the @var{overlay} filter instead. - @section amplify Amplify differences between current pixel and pixels of adjacent frames in @@ -5993,6 +7081,18 @@ Set which planes to filter. Default is all. Allowed range is from 0 to 15. @end table +@subsection Commands + +This filter supports the following @ref{commands} that corresponds to option of same name: +@table @option +@item factor +@item threshold +@item tolerance +@item low +@item high +@item planes +@end table + @section ass Same as the @ref{subtitles} filter, except that it doesn't require libavcodec @@ -6058,8 +7158,29 @@ @item p Set what planes of frame filter will use for averaging. Default is all. + +@item a +Set what variant of algorithm filter will use for averaging. Default is @code{p} parallel. +Alternatively can be set to @code{s} serial. + +Parallel can be faster then serial, while other way around is never true. +Parallel will abort early on first change being greater then thresholds, while serial +will continue processing other side of frames if they are equal or below thresholds. + +@item 0s +@item 1s +@item 2s +Set sigma for 1st plane, 2nd plane or 3rd plane. Default is 32767. +Valid range is from 0 to 32767. +This options controls weight for each pixel in radius defined by size. +Default value means every pixel have same weight. +Setting this option to 0 effectively disables filtering. @end table +@subsection Commands +This filter supports same @ref{commands} as options except option @code{s}. +The command accepts the same syntax of the corresponding option. + @section avgblur Apply average blur filter. @@ -6078,6 +7199,13 @@ Default is @code{0}. @end table +@subsection Commands +This filter supports same commands as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + @section bbox Compute the bounding box for the non-black pixels in the input frame @@ -6095,6 +7223,31 @@ Set the minimal luminance value. Default is @code{16}. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section bilateral +Apply bilateral filter, spatial smoothing while preserving edges. + +The filter accepts the following options: +@table @option +@item sigmaS +Set sigma of gaussian function to calculate spatial weight. +Allowed range is 0 to 512. Default is 0.1. + +@item sigmaR +Set sigma of gaussian function to calculate range weight. +Allowed range is 0 to 1. Default is 0.1. + +@item planes +Set planes to filter. Default is first only. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section bitplanenoise Show and measure bit plane noise. @@ -6114,11 +7267,20 @@ Detect video intervals that are (almost) completely black. Can be useful to detect chapter transitions, commercials, or invalid -recordings. Output lines contains the time for the start, end and -duration of the detected black interval expressed in seconds. +recordings. -In order to display the output lines, you need to set the loglevel at -least to the AV_LOG_INFO value. +The filter outputs its detection analysis to both the log as well as +frame metadata. If a black segment of at least the specified minimum +duration is found, a line with the start and end timestamps as well +as duration is printed to the log with level @code{info}. In addition, +a log line with level @code{debug} is printed per frame showing the +black amount detected for that frame. + +The filter also attaches metadata to the first frame of a black +segment with key @code{lavfi.black_start} and to the first frame +after the black segment ends with key @code{lavfi.black_end}. The +value is the frame's timestamp. This metadata is added regardless +of the minimum duration specified. The filter accepts the following options: @@ -6190,7 +7352,8 @@ @end table -@section blend, tblend +@anchor{blend} +@section blend Blend two video frames into each other. @@ -6352,6 +7515,9 @@ @end example @end itemize +@subsection Commands +This filter supports same @ref{commands} as options. + @section bm3d Denoise frames using Block-Matching 3D algorithm. @@ -6565,7 +7731,7 @@ top field first will be assumed. @item deint -Specify which frames to deinterlace. Accept one of the following +Specify which frames to deinterlace. Accepts one of the following values: @table @option @@ -6578,6 +7744,24 @@ The default value is @code{all}. @end table +@section cas + +Apply Contrast Adaptive Sharpen filter to video stream. + +The filter accepts the following options: + +@table @option +@item strength +Set the sharpening strength. Default value is 0. + +@item planes +Set planes to filter. Default value is to filter all +planes except alpha plane. +@end table + +@subsection Commands +This filter supports same @ref{commands} as options. + @section chromahold Remove all color information for all colors except for certain one. @@ -6603,6 +7787,13 @@ This can be used to pass exact YUV values as hexadecimal numbers. @end table +@subsection Commands +This filter supports same @ref{commands} as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + @section chromakey YUV colorspace color/chroma keying. @@ -6632,6 +7823,13 @@ This can be used to pass exact YUV values as hexadecimal numbers. @end table +@subsection Commands +This filter supports same @ref{commands} as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + @subsection Examples @itemize @@ -6648,6 +7846,60 @@ @end example @end itemize +@section chromanr +Reduce chrominance noise. + +The filter accepts the following options: + +@table @option +@item thres +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 200. + +@item sizew +Set horizontal radius of rectangle used for averaging. +Allowed range is from 1 to 100. Default value is 5. + +@item sizeh +Set vertical radius of rectangle used for averaging. +Allowed range is from 1 to 100. Default value is 5. + +@item stepw +Set horizontal step when averaging. Default value is 1. +Allowed range is from 1 to 50. +Mostly useful to speed-up filtering. + +@item steph +Set vertical step when averaging. Default value is 1. +Allowed range is from 1 to 50. +Mostly useful to speed-up filtering. + +@item threy +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 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 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 200. Allowed range is from 1 to 200. +@end table + +@subsection Commands +This filter supports same @ref{commands} as options. +The command accepts the same syntax of the corresponding option. + @section chromashift Shift chroma pixels horizontally and/or vertically. @@ -6665,6 +7917,10 @@ Set edge mode, can be @var{smear}, default, or @var{warp}. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section ciescope Display CIE color diagram with pixels overlaid onto it. @@ -6685,6 +7941,7 @@ @item cie1931 @item rec709, hdtv @item uhdtv, rec2020 +@item dcip3 @end table @item cie @@ -6819,6 +8076,9 @@ Adjust red, green and blue highlights (brightest pixels). Allowed ranges for options are @code{[-1.0, 1.0]}. Defaults are @code{0}. + +@item pl +Preserve lightness when changing color balance. Default is disabled. @end table @subsection Examples @@ -6831,131 +8091,72 @@ @end example @end itemize -@section colorkey -RGB colorspace color keying. - -The filter accepts the following options: - -@table @option -@item color -The color which will be replaced with transparency. - -@item similarity -Similarity percentage with the key color. - -0.01 matches only the exact key color, while 1.0 matches everything. +@subsection Commands -@item blend -Blend percentage. +This filter supports the all above options as @ref{commands}. -0.0 makes pixels either fully transparent, or not transparent at all. +@section colorcontrast -Higher values result in semi-transparent pixels, with a higher transparency -the more similar the pixels color is to the key color. -@end table +Adjust color contrast between RGB components. -@subsection Examples +The filter accepts the following options: -@itemize -@item -Make every green pixel in the input image transparent: -@example -ffmpeg -i input.png -vf colorkey=green out.png -@end example +@table @option +@item rc +Set the red-cyan contrast. Defaults is 0.0. Allowed range is from -1.0 to 1.0. -@item -Overlay a greenscreen-video on top of a static background image. -@example -ffmpeg -i background.png -i video.mp4 -filter_complex "[1:v]colorkey=0x3BBD1E:0.3:0.2[ckout];[0:v][ckout]overlay[out]" -map "[out]" output.flv -@end example -@end itemize +@item gm +Set the green-magenta contrast. Defaults is 0.0. Allowed range is from -1.0 to 1.0. -@section colorhold -Remove all color information for all RGB colors except for certain one. +@item by +Set the blue-yellow contrast. Defaults is 0.0. Allowed range is from -1.0 to 1.0. -The filter accepts the following options: +@item rcw +@item gmw +@item byw +Set the weight of each @code{rc}, @code{gm}, @code{by} option value. Default value is 0.0. +Allowed range is from 0.0 to 1.0. If all weights are 0.0 filtering is disabled. -@table @option -@item color -The color which will not be replaced with neutral gray. +@item pl +Set the amount of preserving lightness. Default value is 0.0. Allowed range is from 0.0 to 1.0. +@end table -@item similarity -Similarity percentage with the above color. -0.01 matches only the exact key color, while 1.0 matches everything. +@subsection Commands -@item blend -Blend percentage. 0.0 makes pixels fully gray. -Higher values result in more preserved color. -@end table +This filter supports the all above options as @ref{commands}. -@section colorlevels +@section colorcorrect -Adjust video input frames using levels. +Adjust color white balance selectively for blacks and whites. +This filter operates in YUV colorspace. The filter accepts the following options: @table @option -@item rimin -@item gimin -@item bimin -@item aimin -Adjust red, green, blue and alpha input black point. -Allowed ranges for options are @code{[-1.0, 1.0]}. Defaults are @code{0}. - -@item rimax -@item gimax -@item bimax -@item aimax -Adjust red, green, blue and alpha input white point. -Allowed ranges for options are @code{[-1.0, 1.0]}. Defaults are @code{1}. +@item rl +Set the red shadow spot. Allowed range is from -1.0 to 1.0. +Default value is 0. -Input levels are used to lighten highlights (bright tones), darken shadows -(dark tones), change the balance of bright and dark tones. +@item bl +Set the blue shadow spot. Allowed range is from -1.0 to 1.0. +Default value is 0. -@item romin -@item gomin -@item bomin -@item aomin -Adjust red, green, blue and alpha output black point. -Allowed ranges for options are @code{[0, 1.0]}. Defaults are @code{0}. +@item rh +Set the red highlight spot. Allowed range is from -1.0 to 1.0. +Default value is 0. -@item romax -@item gomax -@item bomax -@item aomax -Adjust red, green, blue and alpha output white point. -Allowed ranges for options are @code{[0, 1.0]}. Defaults are @code{1}. +@item bh +Set the red highlight spot. Allowed range is from -1.0 to 1.0. +Default value is 0. -Output levels allows manual selection of a constrained output level range. +@item saturation +Set the amount of saturation. Allowed range is from -3.0 to 3.0. +Default value is 1. @end table -@subsection Examples - -@itemize -@item -Make video output darker: -@example -colorlevels=rimin=0.058:gimin=0.058:bimin=0.058 -@end example - -@item -Increase contrast: -@example -colorlevels=rimin=0.039:gimin=0.039:bimin=0.039:rimax=0.96:gimax=0.96:bimax=0.96 -@end example - -@item -Make video output lighter: -@example -colorlevels=rimax=0.902:gimax=0.902:bimax=0.902 -@end example +@subsection Commands -@item -Increase brightness: -@example -colorlevels=romin=0.5:gomin=0.5:bomin=0.5 -@end example -@end itemize +This filter supports the all above options as @ref{commands}. @section colorchannelmixer @@ -7000,6 +8201,10 @@ Default is @code{1} for @var{aa}, and @code{0} for @var{ar}, @var{ag} and @var{ab}. Allowed ranges for options are @code{[-2.0, 2.0]}. + +@item pl +Preserve lightness when changing colors. Allowed range is from @code{[0.0, 1.0]}. +Default is @code{0.0}, thus disabled. @end table @subsection Examples @@ -7017,6 +8222,181 @@ @end example @end itemize +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section colorize +Overlay a solid color on the video stream. + +The filter accepts the following options: + +@table @option +@item hue +Set the color hue. Allowed range is from 0 to 360. +Default value is 0. + +@item saturation +Set the color saturation. Allowed range is from 0 to 1. +Default value is 0.5. + +@item lightness +Set the color lightness. Allowed range is from 0 to 1. +Default value is 0.5. + +@item mix +Set the mix of source lightness. By default is set to 1.0. +Allowed range is from 0.0 to 1.0. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section colorkey +RGB colorspace color keying. + +The filter accepts the following options: + +@table @option +@item color +The color which will be replaced with transparency. + +@item similarity +Similarity percentage with the key color. + +0.01 matches only the exact key color, while 1.0 matches everything. + +@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. +@end table + +@subsection Examples + +@itemize +@item +Make every green pixel in the input image transparent: +@example +ffmpeg -i input.png -vf colorkey=green out.png +@end example + +@item +Overlay a greenscreen-video on top of a static background image. +@example +ffmpeg -i background.png -i video.mp4 -filter_complex "[1:v]colorkey=0x3BBD1E:0.3:0.2[ckout];[0:v][ckout]overlay[out]" -map "[out]" output.flv +@end example +@end itemize + +@subsection Commands +This filter supports same @ref{commands} as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + +@section colorhold +Remove all color information for all RGB colors except for certain one. + +The filter accepts the following options: + +@table @option +@item color +The color which will not be replaced with neutral gray. + +@item similarity +Similarity percentage with the above color. +0.01 matches only the exact key color, while 1.0 matches everything. + +@item blend +Blend percentage. 0.0 makes pixels fully gray. +Higher values result in more preserved color. +@end table + +@subsection Commands +This filter supports same @ref{commands} as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + +@section colorlevels + +Adjust video input frames using levels. + +The filter accepts the following options: + +@table @option +@item rimin +@item gimin +@item bimin +@item aimin +Adjust red, green, blue and alpha input black point. +Allowed ranges for options are @code{[-1.0, 1.0]}. Defaults are @code{0}. + +@item rimax +@item gimax +@item bimax +@item aimax +Adjust red, green, blue and alpha input white point. +Allowed ranges for options are @code{[-1.0, 1.0]}. Defaults are @code{1}. + +Input levels are used to lighten highlights (bright tones), darken shadows +(dark tones), change the balance of bright and dark tones. + +@item romin +@item gomin +@item bomin +@item aomin +Adjust red, green, blue and alpha output black point. +Allowed ranges for options are @code{[0, 1.0]}. Defaults are @code{0}. + +@item romax +@item gomax +@item bomax +@item aomax +Adjust red, green, blue and alpha output white point. +Allowed ranges for options are @code{[0, 1.0]}. Defaults are @code{1}. + +Output levels allows manual selection of a constrained output level range. +@end table + +@subsection Examples + +@itemize +@item +Make video output darker: +@example +colorlevels=rimin=0.058:gimin=0.058:bimin=0.058 +@end example + +@item +Increase contrast: +@example +colorlevels=rimin=0.039:gimin=0.039:bimin=0.039:rimax=0.96:gimax=0.96:bimax=0.96 +@end example + +@item +Make video output lighter: +@example +colorlevels=rimax=0.902:gimax=0.902:bimax=0.902 +@end example + +@item +Increase brightness: +@example +colorlevels=romin=0.5:gomin=0.5:bomin=0.5 +@end example +@end itemize + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section colormatrix Convert color matrix. @@ -7333,6 +8713,28 @@ colorspace=smpte240m @end example +@section colortemperature +Adjust color temperature in video to simulate variations in ambient color temperature. + +The filter accepts the following options: + +@table @option +@item temperature +Set the temperature in Kelvin. Allowed range is from 1000 to 40000. +Default value is 6500 K. + +@item mix +Set mixing with filtered output. Allowed range is from 0 to 1. +Default value is 1. + +@item pl +Set the amount of preserving lightness. Allowed range is from 0 to 1. +Default value is 0. +@end table + +@subsection Commands +This filter supports same @ref{commands} as options. + @section convolution Apply convolution of 3x3, 5x5, 7x7 or horizontal/vertical up to 49 elements. @@ -7370,6 +8772,10 @@ Default is @var{square}. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @subsection Examples @itemize @@ -7538,6 +8944,40 @@ @end example @end itemize +@section cover_rect + +Cover a rectangular object + +It accepts the following options: + +@table @option +@item cover +Filepath of the optional cover image, needs to be in yuv420. + +@item mode +Set covering mode. + +It accepts the following values: +@table @samp +@item cover +cover it by the supplied image +@item blur +cover it by interpolating the surrounding pixels +@end table + +Default value is @var{blur}. +@end table + +@subsection Examples + +@itemize +@item +Cover a rectangular object by the supplied image of a given video using @command{ffmpeg}: +@example +ffmpeg -i file.ts -vf find_rect=newref.pgm,cover_rect=cover.jpg:mode=cover new.mkv +@end example +@end itemize + @section crop Crop the input video to given dimensions. @@ -7759,6 +9199,10 @@ get only even dimensions (needed for 4:2:2 video). 16 is best when encoding to most video codecs. +@item skip +Set the number of initial frames for which evaluation is skipped. +Default is 2. Range is 0 to INT_MAX. + @item reset_count, reset Set the counter that determines after how many frames cropdetect will reset the previously detected largest video area and start over to @@ -7869,6 +9313,10 @@ To avoid some filtergraph syntax conflicts, each key points list need to be defined using the following syntax: @code{x0/y0 x1/y1 x2/y2 ...}. +@subsection Commands + +This filter supports same @ref{commands} as options. + @subsection Examples @itemize @@ -7958,8 +9406,41 @@ @item opacity Set background opacity. + +@item format +Set display number format. Can be @code{hex}, or @code{dec}. Default is @code{hex}. + +@item components +Set pixel components to display. By default all pixel components are displayed. +@end table + +@subsection Commands + +This filter supports same @ref{commands} as options excluding @code{size} option. + +@section dblur +Apply Directional blur filter. + +The filter accepts the following options: + +@table @option +@item angle +Set angle of directional blur. Default is @code{45}. + +@item radius +Set radius of directional blur. Default is @code{5}. + +@item planes +Set which planes to filter. By default all planes are filtered. @end table +@subsection Commands +This filter supports same @ref{commands} as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + @section dctdnoiz Denoise frames using 2D DCT (frequency domain filtering). @@ -8069,6 +9550,10 @@ The default is disabled. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section deblock Remove blocking artifacts from input video. @@ -8128,6 +9613,10 @@ @end example @end itemize +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @anchor{decimate} @section decimate @@ -8233,6 +9722,10 @@ If 0, plane will remain unchanged. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section deflicker Remove temporal frame luminance variations. @@ -8325,12 +9818,6 @@ Specify the width and height of the logo to clear. They must be specified. -@item band, t -Specify the thickness of the fuzzy edge of the rectangle (added to -@var{w} and @var{h}). The default value is 1. This option is -deprecated, setting higher values should no longer be necessary and -is not recommended. - @item show When set to 1, a green rectangle is drawn on the screen to simplify finding the right @var{x}, @var{y}, @var{w}, and @var{h} parameters. @@ -8348,13 +9835,14 @@ @itemize @item Set a rectangle covering the area with top left corner coordinates 0,0 -and size 100x77, and a band of size 10: +and size 100x77: @example -delogo=x=0:y=0:w=100:h=77:band=10 +delogo=x=0:y=0:w=100:h=77 @end example @end itemize +@anchor{derain} @section derain Remove the rain in the input image/video by applying the derain methods based on @@ -8366,29 +9854,51 @@ See @url{http://openaccess.thecvf.com/content_ECCV_2018/papers/Xia_Li_Recurrent_Squeeze-and-Excitation_Context_ECCV_2018_paper.pdf}. @end itemize -Training scripts as well as scripts for model generation are provided in +Training as well as model generation scripts are provided in the repository at @url{https://github.com/XueweiMeng/derain_filter.git}. +Native model files (.model) can be generated from TensorFlow model +files (.pb) by using tools/python/convert.py + The filter accepts the following options: @table @option -@item dnn_backend -Specify which DNN backend to use for model loading and execution. This option accepts +@item filter_type +Specify which filter to use. This option accepts the following values: + +@table @samp +@item derain +Derain filter. To conduct derain filter, you need to use a derain model. + +@item dehaze +Dehaze filter. To conduct dehaze filter, you need to use a dehaze model. +@end table +Default value is @samp{derain}. + +@item dnn_backend +Specify which DNN backend to use for model loading and execution. This option accepts the following values: @table @samp @item native Native implementation of DNN loading and execution. + +@item tensorflow +TensorFlow backend. To enable this backend you +need to install the TensorFlow for C library (see +@url{https://www.tensorflow.org/install/install_c}) and configure FFmpeg with +@code{--enable-libtensorflow} @end table Default value is @samp{native}. @item model Set path to model file specifying network architecture and its parameters. -Note that different backends use different file formats. TensorFlow backend -can load files for both formats, while native backend can load files for only -its format. +Note that different backends use different file formats. TensorFlow and native +backend can load files for only its format. @end table +It can also be finished with @ref{dnn_processing} filter. + @section deshake Attempt to fix small changes in horizontal and/or vertical shift. This @@ -8500,6 +10010,10 @@ Modify alpha from generated spillmap. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section detelecine Apply an exact inverse of the telecine operation. It requires a predefined @@ -8554,6 +10068,10 @@ 6 7 8 @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section displace Displace pixels as indicated by second and third input stream. @@ -8609,6 +10127,88 @@ @end example @end itemize +@anchor{dnn_processing} +@section dnn_processing + +Do image processing with deep neural networks. It works together with another filter +which converts the pixel format of the Frame to what the dnn network requires. + +The filter accepts the following options: + +@table @option +@item dnn_backend +Specify which DNN backend to use for model loading and execution. This option accepts +the following values: + +@table @samp +@item native +Native implementation of DNN loading and execution. + +@item tensorflow +TensorFlow backend. To enable this backend you +need to install the TensorFlow for C library (see +@url{https://www.tensorflow.org/install/install_c}) and configure FFmpeg with +@code{--enable-libtensorflow} + +@item openvino +OpenVINO backend. To enable this backend you +need to build and install the OpenVINO for C library (see +@url{https://github.com/openvinotoolkit/openvino/blob/master/build-instruction.md}) and configure FFmpeg with +@code{--enable-libopenvino} (--extra-cflags=-I... --extra-ldflags=-L... might +be needed if the header files and libraries are not installed into system path) + +@end table + +Default value is @samp{native}. + +@item model +Set path to model file specifying network architecture and its parameters. +Note that different backends use different file formats. TensorFlow, OpenVINO and native +backend can load files for only its format. + +Native model file (.model) can be generated from TensorFlow model file (.pb) by using tools/python/convert.py + +@item input +Set the input name of the dnn network. + +@item output +Set the output name of the dnn network. + +@item async +use DNN async execution if set (default: set), +roll back to sync execution if the backend does not support async. + +@end table + +@subsection Examples + +@itemize +@item +Remove rain in rgb24 frame with can.pb (see @ref{derain} filter): +@example +./ffmpeg -i rain.jpg -vf format=rgb24,dnn_processing=dnn_backend=tensorflow:model=can.pb:input=x:output=y derain.jpg +@end example + +@item +Halve the pixel value of the frame with format gray32f: +@example +ffmpeg -i input.jpg -vf format=grayf32,dnn_processing=model=halve_gray_float.model:input=dnn_in:output=dnn_out:dnn_backend=native -y out.native.png +@end example + +@item +Handle the Y channel with srcnn.pb (see @ref{sr} filter) for frame with yuv420p (planar YUV formats supported): +@example +./ffmpeg -i 480p.jpg -vf format=yuv420p,scale=w=iw*2:h=ih*2,dnn_processing=dnn_backend=tensorflow:model=srcnn.pb:input=x:output=y -y srcnn.jpg +@end example + +@item +Handle the Y channel with espcn.pb (see @ref{sr} filter), which changes frame size, for format yuv420p (planar YUV formats supported): +@example +./ffmpeg -i 480p.jpg -vf format=yuv420p,dnn_processing=dnn_backend=tensorflow:model=espcn.pb:input=x:output=y -y tmp.espcn.jpg +@end example + +@end itemize + @section drawbox Draw a colored box on the input image. @@ -8711,6 +10311,121 @@ @end example @end itemize +@subsection Commands +This filter supports same commands as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + +@anchor{drawgraph} +@section drawgraph +Draw a graph using input video metadata. + +It accepts the following parameters: + +@table @option +@item m1 +Set 1st frame metadata key from which metadata values will be used to draw a graph. + +@item fg1 +Set 1st foreground color expression. + +@item m2 +Set 2nd frame metadata key from which metadata values will be used to draw a graph. + +@item fg2 +Set 2nd foreground color expression. + +@item m3 +Set 3rd frame metadata key from which metadata values will be used to draw a graph. + +@item fg3 +Set 3rd foreground color expression. + +@item m4 +Set 4th frame metadata key from which metadata values will be used to draw a graph. + +@item fg4 +Set 4th foreground color expression. + +@item min +Set minimal value of metadata value. + +@item max +Set maximal value of metadata value. + +@item bg +Set graph background color. Default is white. + +@item mode +Set graph mode. + +Available values for mode is: +@table @samp +@item bar +@item dot +@item line +@end table + +Default is @code{line}. + +@item slide +Set slide mode. + +Available values for slide is: +@table @samp +@item frame +Draw new frame when right border is reached. + +@item replace +Replace old columns with new ones. + +@item scroll +Scroll from right to left. + +@item rscroll +Scroll from left to right. + +@item picture +Draw single picture. +@end table + +Default is @code{frame}. + +@item size +Set size of graph video. For the syntax of this option, check the +@ref{video size syntax,,"Video size" section in the ffmpeg-utils manual,ffmpeg-utils}. +The default value is @code{900x256}. + +@item rate, r +Set the output frame rate. Default value is @code{25}. + +The foreground color expressions can use the following variables: +@table @option +@item MIN +Minimal value of metadata value. + +@item MAX +Maximal value of metadata value. + +@item VAL +Current metadata key value. +@end table + +The color is defined as 0xAABBGGRR. +@end table + +Example using metadata from @ref{signalstats} filter: +@example +signalstats,drawgraph=lavfi.signalstats.YAVG:min=0:max=255 +@end example + +Example using metadata from @ref{ebur128} filter: +@example +ebur128=metadata=1,adrawgraph=lavfi.r128.M:min=-120:max=5 +@end example + @section drawgrid Draw a grid on the input image. @@ -8796,6 +10511,13 @@ @end example @end itemize +@subsection Commands +This filter supports same commands as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + @anchor{drawtext} @section drawtext @@ -9266,6 +10988,12 @@ @end example @item +Draw "Test Text" with font size dependent on height of the video. +@example +drawtext="text='Test Text': fontsize=h/30: x=(w-text_w)/2: y=(h-text_h*2)" +@end example + +@item Print the date of a real-time encoding (see strftime(3)): @example drawtext='fontfile=FreeSans.ttf:text=%@{localtime\:%a %b %d %Y@}' @@ -9290,6 +11018,15 @@ drawtext=fontfile=FreeSans.ttf:text=cow:fontsize=24:x=80:y=20+24-max_glyph_a @end example +@item +Plot special @var{lavf.image2dec.source_basename} metadata onto each frame if +such metadata exists. Otherwise, plot the string "NA". Note that image2 demuxer +must have option @option{-export_path_metadata 1} for the special metadata fields +to be available for filters. +@example +drawtext="fontsize=20:fontcolor=white:fontfile=FreeSans.ttf:text='%@{metadata\:lavf.image2dec.source_basename\:NA@}':x=10:y=10" +@end example + @end itemize For more information about libfreetype, check: @@ -9358,6 +11095,62 @@ @end example @end itemize +@section elbg + +Apply a posterize effect using the ELBG (Enhanced LBG) algorithm. + +For each input image, the filter will compute the optimal mapping from +the input to the output given the codebook length, that is the number +of distinct output colors. + +This filter accepts the following options. + +@table @option +@item codebook_length, l +Set codebook length. The value must be a positive integer, and +represents the number of distinct output colors. Default value is 256. + +@item nb_steps, n +Set the maximum number of iterations to apply for computing the optimal +mapping. The higher the value the better the result and the higher the +computation time. Default value is 1. + +@item seed, s +Set a random seed, must be an integer included between 0 and +UINT32_MAX. If not specified, or if explicitly set to -1, the filter +will try to use a good random seed on a best effort basis. + +@item pal8 +Set pal8 output pixel format. This option does not work with codebook +length greater than 256. +@end table + +@section entropy + +Measure graylevel entropy in histogram of color channels of video frames. + +It accepts the following parameters: + +@table @option +@item mode +Can be either @var{normal} or @var{diff}. Default is @var{normal}. + +@var{diff} mode measures entropy of histogram delta values, absolute differences +between neighbour histogram values. +@end table + +@section epx +Apply the EPX magnification filter which is designed for pixel art. + +It accepts the following option: + +@table @option +@item n +Set the scaling dimension: @code{2} for @code{2xEPX}, @code{3} for +@code{3xEPX}. +Default is @code{3}. +@end table + @section eq Set brightness, contrast, saturation and approximate gamma adjustment. @@ -9366,7 +11159,7 @@ @table @option @item contrast Set the contrast expression. The value must be a float value in range -@code{-2.0} to @code{2.0}. The default value is "1". +@code{-1000.0} to @code{1000.0}. The default value is "1". @item brightness Set the brightness expression. The value must be a float value in @@ -9495,7 +11288,107 @@ 6 7 8 @end table -@section extractplanes +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section estdif + +Deinterlace the input video ("estdif" stands for "Edge Slope +Tracing Deinterlacing Filter"). + +Spatial only filter that uses edge slope tracing algorithm +to interpolate missing lines. +It accepts the following parameters: + +@table @option +@item mode +The interlacing mode to adopt. It accepts one of the following values: + +@table @option +@item frame +Output one frame for each frame. +@item field +Output one frame for each field. +@end table + +The default value is @code{field}. + +@item parity +The picture field parity assumed for the input interlaced video. It accepts one +of the following values: + +@table @option +@item tff +Assume the top field is first. +@item bff +Assume the bottom field is first. +@item auto +Enable automatic detection of field parity. +@end table + +The default value is @code{auto}. +If the interlacing is unknown or the decoder does not export this information, +top field first will be assumed. + +@item deint +Specify which frames to deinterlace. Accepts one of the following +values: + +@table @option +@item all +Deinterlace all frames. +@item interlaced +Only deinterlace frames marked as interlaced. +@end table + +The default value is @code{all}. + +@item rslope +Specify the search radius for edge slope tracing. Default value is 1. +Allowed range is from 1 to 15. + +@item redge +Specify the search radius for best edge matching. Default value is 2. +Allowed range is from 0 to 15. + +@item interp +Specify the interpolation used. Default is 4-point interpolation. It accepts one +of the following values: + +@table @option +@item 2p +Two-point interpolation. +@item 4p +Four-point interpolation. +@item 6p +Six-point interpolation. +@end table +@end table + +@subsection Commands +This filter supports same @ref{commands} as options. + +@section exposure +Adjust exposure of the video stream. + +The filter accepts the following options: + +@table @option +@item exposure +Set the exposure correction in EV. Allowed range is from -3.0 to 3.0 EV +Default value is 0 EV. + +@item black +Set the black level correction. Allowed range is from -1.0 to 1.0. +Default value is 0. +@end table + +@subsection Commands + +This filter supports same @ref{commands} as options. + +@section extractplanes Extract color channel components from input video stream into separate grayscale video streams. @@ -9533,50 +11426,6 @@ @end example @end itemize -@section elbg - -Apply a posterize effect using the ELBG (Enhanced LBG) algorithm. - -For each input image, the filter will compute the optimal mapping from -the input to the output given the codebook length, that is the number -of distinct output colors. - -This filter accepts the following options. - -@table @option -@item codebook_length, l -Set codebook length. The value must be a positive integer, and -represents the number of distinct output colors. Default value is 256. - -@item nb_steps, n -Set the maximum number of iterations to apply for computing the optimal -mapping. The higher the value the better the result and the higher the -computation time. Default value is 1. - -@item seed, s -Set a random seed, must be an integer included between 0 and -UINT32_MAX. If not specified, or if explicitly set to -1, the filter -will try to use a good random seed on a best effort basis. - -@item pal8 -Set pal8 output pixel format. This option does not work with codebook -length greater than 256. -@end table - -@section entropy - -Measure graylevel entropy in histogram of color channels of video frames. - -It accepts the following parameters: - -@table @option -@item mode -Can be either @var{normal} or @var{diff}. Default is @var{normal}. - -@var{diff} mode measures entropy of histogram delta values, absolute differences -between neighbour histogram values. -@end table - @section fade Apply a fade-in/out effect to the input video. @@ -9668,6 +11517,40 @@ @end itemize +@section fftdnoiz +Denoise frames using 3D FFT (frequency domain filtering). + +The filter accepts the following options: + +@table @option +@item sigma +Set the noise sigma constant. This sets denoising strength. +Default value is 1. Allowed range is from 0 to 30. +Using very high sigma with low overlap may give blocking artifacts. + +@item amount +Set amount of denoising. By default all detected noise is reduced. +Default value is 1. Allowed range is from 0 to 1. + +@item block +Set size of block, Default is 4, can be 3, 4, 5 or 6. +Actual size of block in pixels is 2 to power of @var{block}, so by default +block size in pixels is 2^4 which is 16. + +@item overlap +Set block overlap. Default is 0.5. Allowed range is from 0.2 to 0.8. + +@item prev +Set number of previous frames to use for denoising. By default is set to 0. + +@item next +Set number of next frames to to use for denoising. By default is set to 0. + +@item planes +Set planes which will be filtered, by default are all available filtered +except alpha. +@end table + @section fftfilt Apply arbitrary expressions to samples in frequency domain @@ -9752,40 +11635,6 @@ @end itemize -@section fftdnoiz -Denoise frames using 3D FFT (frequency domain filtering). - -The filter accepts the following options: - -@table @option -@item sigma -Set the noise sigma constant. This sets denoising strength. -Default value is 1. Allowed range is from 0 to 30. -Using very high sigma with low overlap may give blocking artifacts. - -@item amount -Set amount of denoising. By default all detected noise is reduced. -Default value is 1. Allowed range is from 0 to 1. - -@item block -Set size of block, Default is 4, can be 3, 4, 5 or 6. -Actual size of block in pixels is 2 to power of @var{block}, so by default -block size in pixels is 2^4 which is 16. - -@item overlap -Set block overlap. Default is 0.5. Allowed range is from 0.2 to 0.8. - -@item prev -Set number of previous frames to use for denoising. By default is set to 0. - -@item next -Set number of next frames to to use for denoising. By default is set to 0. - -@item planes -Set planes which will be filtered, by default are all available filtered -except alpha. -@end table - @section field Extract a single field from an interlaced image using stride @@ -9820,6 +11669,8 @@ If optionally followed by @code{+} output frame will be marked as interlaced, else if followed by @code{-} output frame will be marked as progressive, else it will be marked same as input frame. +If optionally followed by @code{t} output frame will use only top field, or in +case of @code{b} it will use only bottom field. If line starts with @code{#} or @code{;} that line is skipped. @item mode @@ -10242,18 +12093,34 @@ fill pixels using outermost pixels @item mirror -fill pixels using mirroring +fill pixels using mirroring (half sample symmetric) @item fixed fill pixels with constant value + +@item reflect +fill pixels using reflecting (whole sample symmetric) + +@item wrap +fill pixels using wrapping + +@item fade +fade pixels to constant value @end table Default is @var{smear}. @item color -Set color for pixels in fixed mode. Default is @var{black}. +Set color for pixels in fixed or fade mode. Default is @var{black}. @end table +@subsection Commands +This filter supports same @ref{commands} as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + @section find_rect Find a rectangular object @@ -10284,40 +12151,6 @@ @end example @end itemize -@section cover_rect - -Cover a rectangular object - -It accepts the following options: - -@table @option -@item cover -Filepath of the optional cover image, needs to be in yuv420. - -@item mode -Set covering mode. - -It accepts the following values: -@table @samp -@item cover -cover it by the supplied image -@item blur -cover it by interpolating the surrounding pixels -@end table - -Default value is @var{blur}. -@end table - -@subsection Examples - -@itemize -@item -Cover a rectangular object by the supplied image of a given video using @command{ffmpeg}: -@example -ffmpeg -i file.ts -vf find_rect=newref.pgm,cover_rect=cover.jpg:mode=cover new.mkv -@end example -@end itemize - @section floodfill Flood area with values of same pixel components with another values. @@ -10589,6 +12422,25 @@ Set freeze duration until notification (default is 2 seconds). @end table +@section freezeframes + +Freeze video frames. + +This filter freezes video frames using frame from 2nd input. + +The filter accepts the following options: + +@table @option +@item first +Set number of first frame from which to start freeze. + +@item last +Set number of last frame from which to end freeze. + +@item replace +Set number of frame from 2nd input which will be used instead of replaced frames. +@end table + @anchor{frei0r} @section frei0r @@ -10653,6 +12505,10 @@ For more information, see @url{http://frei0r.dyne.org} +@subsection Commands + +This filter supports the @option{filter_params} option as @ref{commands}. + @section fspp Apply fast and simple postprocessing. It is a faster version of @ref{spp}. @@ -10705,6 +12561,13 @@ Default is @code{-1}. @end table +@subsection Commands +This filter supports same commands as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + @section geq Apply generic equation to each pixel. @@ -10789,11 +12652,28 @@ @item alpha(x, y) Return the value of the pixel at location (@var{x},@var{y}) of the alpha plane. Return 0 if there is no such plane. + +@item psum(x,y), lumsum(x, y), cbsum(x,y), crsum(x,y), rsum(x,y), gsum(x,y), bsum(x,y), alphasum(x,y) +Sum of sample values in the rectangle from (0,0) to (x,y), this allows obtaining +sums of samples within a rectangle. See the functions without the sum postfix. + +@item interpolation +Set one of interpolation methods: +@table @option +@item nearest, n +@item bilinear, b +@end table +Default is bilinear. @end table For functions, if @var{x} and @var{y} are outside the area, the value will be automatically clipped to the closer edge. +Please note that this filter can use multiple threads in which case each slice +will have its own expression state. If you want to use only a single expression +state because your expressions depend on previous state then you should limit +the number of filter threads to 1. + @subsection Examples @itemize @@ -10886,7 +12766,8 @@ @end itemize -@section graphmonitor, agraphmonitor +@anchor{graphmonitor} +@section graphmonitor Show various filtergraph stats. With this filter one can debug complete filtergraph. @@ -10936,6 +12817,9 @@ @item rate Display video frame rate or sample rate in case of audio used by filter link. + +@item eof +Display link output status. @end table @item rate, r @@ -11011,6 +12895,10 @@ More information about the Hald CLUT can be found on Eskil Steenberg's website (Hald CLUT author) at @url{http://www.quelsolaar.com/technology/clut.html}. +@subsection Commands + +This filter supports the @code{interp} option as @ref{commands}. + @subsection Workflow examples @subsubsection Hald CLUT video stream @@ -11101,6 +12989,7 @@ @code{strong}. It defaults to @code{none}. @end table +@anchor{histogram} @section histogram Compute and draw a color distribution histogram for the input video. @@ -11195,6 +13084,13 @@ @var{luma_tmp}*@var{chroma_spatial}/@var{luma_spatial}. @end table +@subsection Commands +This filter supports same @ref{commands} as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + @anchor{hwdownload} @section hwdownload @@ -11293,7 +13189,18 @@ The device to upload to must be supplied when the filter is initialised. If using ffmpeg, select the appropriate device with the @option{-filter_hw_device} -option. +option or with the @option{derive_device} option. The input and output devices +must be of different types and compatible - the exact meaning of this is +system-dependent, but typically it means that they must refer to the same +underlying hardware context (for example, refer to the same graphics card). + +The following additional parameters are accepted: + +@table @option +@item derive_device @var{type} +Rather than using the device supplied at initialisation, instead derive a new +device of type @var{type} from the device the input frames exist on. +@end table @anchor{hwupload_cuda} @section hwupload_cuda @@ -11329,7 +13236,7 @@ Note that this filter is faster than using @ref{overlay} and @ref{pad} filter to create same output. -The filter accept the following option: +The filter accepts the following option: @table @option @item inputs @@ -11467,6 +13374,30 @@ By default value is 0. @end table +The @code{hysteresis} filter also supports the @ref{framesync} options. + +@section identity + +Obtain the identity score between two input videos. + +This filter takes two input videos. + +Both input videos must have the same resolution and pixel format for +this filter to work correctly. Also it assumes that both inputs +have the same number of frames, which are compared one by one. + +The obtained per component, average, min and max identity score is printed through +the logging system. + +The filter stores the calculated identity scores of each frame in frame metadata. + +In the below example the input file @file{main.mpg} being processed is compared +with the reference file @file{ref.mpg}. + +@example +ffmpeg -i main.mpg -i ref.mpg -lavfi identity -f null - +@end example + @section idet Detect video interlacing type. @@ -11588,6 +13519,10 @@ Swap luma/chroma/alpha fields. Exchange even & odd lines. Default value is @code{0}. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section inflate Apply inflate effect to the video. @@ -11606,6 +13541,10 @@ If 0, plane will remain unchanged. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section interlace Simple interlacing filter from progressive contents. This interleaves upper (or @@ -11701,6 +13640,27 @@ @end example @end itemize +@section kirsch +Apply kirsch operator to input video stream. + +The filter accepts the following option: + +@table @option +@item planes +Set which planes will be processed, unprocessed planes will be copied. +By default value 0xf, all planes will be processed. + +@item scale +Set value which will be multiplied with filtered result. + +@item delta +Set value which will be added to filtered result. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section lagfun Slowly update darker pixels. @@ -11716,6 +13676,10 @@ Set which planes to filter. Default is all. Allowed range is from 0 to 15. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section lenscorrection Correct radial lens distortion @@ -11754,6 +13718,13 @@ @item k2 Coefficient of the double quadratic correction term. This value has a range [-1,1]. 0 means no correction. Default is 0. +@item i +Set interpolation type. Can be @code{nearest} or @code{bilinear}. +Default is @code{nearest}. +@item fc +Specify the color of the unmapped pixels. For the syntax of this option, +check the @ref{color syntax,,"Color" section in the ffmpeg-utils +manual,ffmpeg-utils}. Default color is @code{black@@0}. @end table The formula that generates the correction is: @@ -11763,6 +13734,10 @@ where @var{r_0} is halve of the image diagonal and @var{r_src} and @var{r_tgt} are the distances from the focal point in the source and target images, respectively. +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section lensfun Apply lens correction via the lensfun library (@url{http://lensfun.sourceforge.net/}). @@ -11899,7 +13874,7 @@ It requires Netflix's vmaf library (libvmaf) as a pre-requisite. After installing the library it can be enabled using: -@code{./configure --enable-libvmaf --enable-version3}. +@code{./configure --enable-libvmaf}. If no model path is specified it uses the default model: @code{vmaf_v0.6.1.pkl}. The filter has following options: @@ -11907,13 +13882,13 @@ @table @option @item model_path Set the model path which is to be used for SVM. -Default value: @code{"vmaf_v0.6.1.pkl"} +Default value: @code{"/usr/local/share/model/vmaf_v0.6.1.pkl"} @item log_path Set the file path to be used to store logs. @item log_fmt -Set the format of the log file (xml or json). +Set the format of the log file (csv, json or xml). @item enable_transform This option can enable/disable the @code{score_transform} applied to the final predicted VMAF score, @@ -11923,31 +13898,42 @@ @item phone_model Invokes the phone model which will generate VMAF scores higher than in the regular model, which is more suitable for laptop, TV, etc. viewing conditions. +Default value: @code{false} @item psnr Enables computing psnr along with vmaf. +Default value: @code{false} @item ssim Enables computing ssim along with vmaf. +Default value: @code{false} @item ms_ssim Enables computing ms_ssim along with vmaf. +Default value: @code{false} @item pool -Set the pool method (mean, min or harmonic mean) to be used for computing vmaf. +Set the pool method to be used for computing vmaf. +Options are @code{min}, @code{harmonic_mean} or @code{mean} (default). @item n_threads Set number of threads to be used when computing vmaf. +Default value: @code{0}, which makes use of all available logical processors. @item n_subsample Set interval for frame subsampling used when computing vmaf. +Default value: @code{1} @item enable_conf_interval Enables confidence interval. +Default value: @code{false} @end table This filter also supports the @ref{framesync} options. +@subsection Examples +@itemize +@item On the below examples the input file @file{main.mpg} being processed is compared with the reference file @file{ref.mpg}. @@ -11955,11 +13941,19 @@ ffmpeg -i main.mpg -i ref.mpg -lavfi libvmaf -f null - @end example +@item Example with options: @example ffmpeg -i main.mpg -i ref.mpg -lavfi libvmaf="psnr=1:log_fmt=json" -f null - @end example +@item +Example with options and different containers: +@example +ffmpeg -i main.mpg -i ref.mkv -lavfi "[0:v]settb=AVTB,setpts=PTS-STARTPTS[main];[1:v]settb=AVTB,setpts=PTS-STARTPTS[ref];[main][ref]libvmaf=psnr=1:log_fmt=json" -f null - +@end example +@end itemize + @section limiter Limits the pixel components values to the specified range [min, max]. @@ -11977,6 +13971,10 @@ Specify which planes will be processed. Defaults to all available. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section loop Loop video frames. @@ -12054,6 +14052,10 @@ @end table @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @anchor{lut3d} @section lut3d @@ -12090,9 +14092,17 @@ Interpolate values using the 8 points defining a cube. @item tetrahedral Interpolate values using a tetrahedron. +@item pyramid +Interpolate values using a pyramid. +@item prism +Interpolate values using a prism. @end table @end table +@subsection Commands + +This filter supports the @code{interp} option as @ref{commands}. + @section lumakey Turn certain luma values into transparency. @@ -12106,13 +14116,20 @@ @item tolerance Set the range of luma values to be keyed out. -Default value is @code{0}. +Default value is @code{0.01}. @item softness Set the range of softness. Default value is @code{0}. Use this to control gradual transition from zero to full transparency. @end table +@subsection Commands +This filter supports same @ref{commands} as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + @section lut, lutrgb, lutyuv Compute a look-up table for binding each pixel component input value @@ -12196,6 +14213,10 @@ All expressions default to "val". +@subsection Commands + +This filter supports same @ref{commands} as options. + @subsection Examples @itemize @@ -12285,6 +14306,8 @@ which means bit depth is automatically picked from first input format. @end table +The @code{lut2} filter also supports the @ref{framesync} options. + Each of them specifies the expression to use for computing the lookup table for the corresponding pixel component values. @@ -12313,6 +14336,10 @@ All expressions default to "x". +@subsection Commands + +This filter supports the all above options as @ref{commands} except option @code{d}. + @subsection Examples @itemize @@ -12356,6 +14383,30 @@ By default value 0xf, all planes will be processed. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section maskedmax + +Merge the second and third input stream into output stream using absolute differences +between second input stream and first input stream and absolute difference between +third input stream and first input stream. The picked value will be from second input +stream if second absolute difference is greater than first one or from third input stream +otherwise. + +This filter accepts the following options: +@table @option +@item planes +Set which planes will be processed as bitmap, unprocessed planes will be +copied from first stream. +By default value 0xf, all planes will be processed. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section maskedmerge Merge the first input stream with the second input stream using per pixel @@ -12375,6 +14426,55 @@ By default value 0xf, all planes will be processed. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section maskedmin + +Merge the second and third input stream into output stream using absolute differences +between second input stream and first input stream and absolute difference between +third input stream and first input stream. The picked value will be from second input +stream if second absolute difference is less than first one or from third input stream +otherwise. + +This filter accepts the following options: +@table @option +@item planes +Set which planes will be processed as bitmap, unprocessed planes will be +copied from first stream. +By default value 0xf, all planes will be processed. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section maskedthreshold +Pick pixels comparing absolute difference of two video streams with fixed +threshold. + +If absolute difference between pixel component of first and second video +stream is equal or lower than user supplied threshold than pixel component +from first video stream is picked, otherwise pixel component from second +video stream is picked. + +This filter accepts the following options: +@table @option +@item threshold +Set threshold used when picking pixels from absolute difference from two input +video streams. + +@item planes +Set which planes will be processed as bitmap, unprocessed planes will be +copied from second stream. +By default value 0xf, all planes will be processed. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section maskfun Create mask from input video. @@ -12402,6 +14502,10 @@ Typically useful for scene changes when used in combination with @code{tblend} filter. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section mcdeint Apply motion-compensation deinterlacing. @@ -12446,6 +14550,38 @@ optimal individual vectors. Default value is 1. @end table +@section median + +Pick median pixel from certain rectangle defined by radius. + +This filter accepts the following options: + +@table @option +@item radius +Set horizontal radius size. Default value is @code{1}. +Allowed range is integer from 1 to 127. + +@item planes +Set which planes to process. Default is @code{15}, which is all available planes. + +@item radiusV +Set vertical radius size. Default value is @code{0}. +Allowed range is integer from 0 to 127. +If it is 0, value will be picked from horizontal @code{radius} option. + +@item percentile +Set median percentile. Default value is @code{0.5}. +Default value of @code{0.5} will pick always median values, while @code{0} will pick +minimum values, and @code{1} maximum values. +@end table + +@subsection Commands +This filter supports same @ref{commands} as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + @section mergeplanes Merge color channel components from several video streams. @@ -12649,7 +14785,7 @@ Default method is @samp{fdiff}. @item scd_threshold -Scene change detection threshold. Default is @code{5.0}. +Scene change detection threshold. Default is @code{10.}. @end table @section mix @@ -12687,6 +14823,42 @@ @end table @end table +@subsection Commands + +This filter supports the following commands: +@table @option +@item weights +@item scale +Syntax is same as option with same name. +@end table + +@section monochrome +Convert video to gray using custom color filter. + +A description of the accepted options follows. + +@table @option +@item cb +Set the chroma blue spot. Allowed range is from -1 to 1. +Default value is 0. + +@item cr +Set the chroma red spot. Allowed range is from -1 to 1. +Default value is 0. + +@item size +Set the color filter size. Allowed range is from .1 to 10. +Default value is 1. + +@item high +Set the highlights strength. Allowed range is from 0 to 1. +Default value is 0. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section mpdecimate Drop frames that do not differ greatly from the previous frame in @@ -12725,6 +14897,27 @@ 64*5, and default value for @option{frac} is 0.33. @end table +@section msad + +Obtain the MSAD (Mean Sum of Absolute Differences) between two input videos. + +This filter takes two input videos. + +Both input videos must have the same resolution and pixel format for +this filter to work correctly. Also it assumes that both inputs +have the same number of frames, which are compared one by one. + +The obtained per component, average, min and max MSAD is printed through +the logging system. + +The filter stores the calculated MSAD of each frame in frame metadata. + +In the below example the input file @file{main.mpg} being processed is compared +with the reference file @file{ref.mpg}. + +@example +ffmpeg -i main.mpg -i ref.mpg -lavfi msad -f null - +@end example @section negate @@ -12738,6 +14931,10 @@ With value 1, it negates the alpha component, if present. Default value is 0. @end table +@subsection Commands + +This filter supports same @ref{commands} as options. + @anchor{nlmeans} @section nlmeans @@ -12851,9 +15048,9 @@ Can be one of the following: @table @samp -@item a +@item a, abs weights trained to minimize absolute error -@item s +@item s, mse weights trained to minimize squared error @end table @@ -12875,14 +15072,16 @@ @item none @item original @item new +@item new2 +@item new3 @end table Default is @code{new}. - -@item fapprox -Set various debugging flags. @end table +@subsection Commands +This filter supports same @ref{commands} as options, excluding @var{weights} option. + @section noformat Force libavfilter not to use any of the specified pixel formats for the @@ -13014,6 +15213,13 @@ @end table +@subsection Commands +This filter supports same @ref{commands} as options, excluding @var{smoothing} option. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + @subsection Examples Stretch video contrast to use the full dynamic range, with no temporal @@ -13168,7 +15374,7 @@ or "bilateral". The default value is "gaussian". The meaning of @var{param1}, @var{param2}, @var{param3}, and @var{param4} -depend on the smooth type. @var{param1} and +depends on the smooth type. @var{param1} and @var{param2} accept integer positive values or 0. @var{param3} and @var{param4} accept floating point values. @@ -13227,6 +15433,13 @@ Draw scope. By default is enabled. @end table +@subsection Commands +This filter supports same @ref{commands} as options. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. + @subsection Examples @itemize @@ -13305,9 +15518,15 @@ @item yuv420 force YUV420 output +@item yuv420p10 +force YUV420p10 output + @item yuv422 force YUV422 output +@item yuv422p10 +force YUV422p10 output + @item yuv444 force YUV444 output @@ -13481,27 +15700,59 @@ @end itemize -@section owdenoise +@anchor{overlay_cuda} +@section overlay_cuda -Apply Overcomplete Wavelet denoiser. +Overlay one video on top of another. -The filter accepts the following options: +This is the CUDA variant of the @ref{overlay} filter. +It only accepts CUDA frames. The underlying input pixel formats have to match. -@table @option -@item depth -Set depth. +It takes two inputs and has one output. The first input is the "main" +video on which the second input is overlaid. -Larger depth values will denoise lower frequency components more, but -slow down filtering. +It accepts the following parameters: -Must be an int in the range 8-16, default is @code{8}. +@table @option +@item x +@item y +Set the x and y coordinates of the overlaid video on the main video. +Default value is "0" for both expressions. -@item luma_strength, ls -Set luma strength. +@item eof_action +See @ref{framesync}. -Must be a double value in the range 0-1000, default is @code{1.0}. +@item shortest +See @ref{framesync}. -@item chroma_strength, cs +@item repeatlast +See @ref{framesync}. + +@end table + +This filter also supports the @ref{framesync} options. + +@section owdenoise + +Apply Overcomplete Wavelet denoiser. + +The filter accepts the following options: + +@table @option +@item depth +Set depth. + +Larger depth values will denoise lower frequency components more, but +slow down filtering. + +Must be an int in the range 8-16, default is @code{8}. + +@item luma_strength, ls +Set luma strength. + +Must be a double value in the range 0-1000, default is @code{1.0}. + +@item chroma_strength, cs Set chroma strength. Must be a double value in the range 0-1000, default is @code{1.0}. @@ -13938,6 +16189,30 @@ @end table @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section photosensitivity +Reduce various flashes in video, so to help users with epilepsy. + +It accepts the following options: +@table @option +@item frames, f +Set how many frames to use when filtering. Default is 30. + +@item threshold, t +Set detection threshold factor. Default is 1. +Lower is stricter. + +@item skip +Set how many pixels to skip when sampling frames. Default is 1. +Allowed range is from 1 to 1024. + +@item bypass +Leave frames unchanged. Default is disabled. +@end table + @section pixdesctest Pixel format descriptor test filter, mainly useful for internal @@ -13980,6 +16255,10 @@ Set window Y position, relative offset on Y axis. @end table +@subsection Commands + +This filter supports same @ref{commands} as options. + @section pp Enable the specified chain of postprocessing subfilters using libpostproc. This @@ -14215,141 +16494,15 @@ Set value which will be added to filtered result. @end table -@anchor{program_opencl} -@section program_opencl - -Filter video using an OpenCL program. - -@table @option - -@item source -OpenCL program source file. - -@item kernel -Kernel name in program. - -@item inputs -Number of inputs to the filter. Defaults to 1. - -@item size, s -Size of output frames. Defaults to the same as the first input. - -@end table - -The program source file must contain a kernel function with the given name, -which will be run once for each plane of the output. Each run on a plane -gets enqueued as a separate 2D global NDRange with one work-item for each -pixel to be generated. The global ID offset for each work-item is therefore -the coordinates of a pixel in the destination image. - -The kernel function needs to take the following arguments: -@itemize -@item -Destination image, @var{__write_only image2d_t}. - -This image will become the output; the kernel should write all of it. -@item -Frame index, @var{unsigned int}. - -This is a counter starting from zero and increasing by one for each frame. -@item -Source images, @var{__read_only image2d_t}. - -These are the most recent images on each input. The kernel may read from -them to generate the output, but they can't be written to. -@end itemize - -Example programs: - -@itemize -@item -Copy the input to the output (output must be the same size as the input). -@verbatim -__kernel void copy(__write_only image2d_t destination, - unsigned int index, - __read_only image2d_t source) -{ - const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE; - - int2 location = (int2)(get_global_id(0), get_global_id(1)); - - float4 value = read_imagef(source, sampler, location); - - write_imagef(destination, location, value); -} -@end verbatim - -@item -Apply a simple transformation, rotating the input by an amount increasing -with the index counter. Pixel values are linearly interpolated by the -sampler, and the output need not have the same dimensions as the input. -@verbatim -__kernel void rotate_image(__write_only image2d_t dst, - unsigned int index, - __read_only image2d_t src) -{ - const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | - CLK_FILTER_LINEAR); - - float angle = (float)index / 100.0f; - - float2 dst_dim = convert_float2(get_image_dim(dst)); - float2 src_dim = convert_float2(get_image_dim(src)); - - float2 dst_cen = dst_dim / 2.0f; - float2 src_cen = src_dim / 2.0f; - - int2 dst_loc = (int2)(get_global_id(0), get_global_id(1)); - - float2 dst_pos = convert_float2(dst_loc) - dst_cen; - float2 src_pos = { - cos(angle) * dst_pos.x - sin(angle) * dst_pos.y, - sin(angle) * dst_pos.x + cos(angle) * dst_pos.y - }; - src_pos = src_pos * src_dim / dst_dim; - - float2 src_loc = src_pos + src_cen; - - if (src_loc.x < 0.0f || src_loc.y < 0.0f || - src_loc.x > src_dim.x || src_loc.y > src_dim.y) - write_imagef(dst, dst_loc, 0.5f); - else - write_imagef(dst, dst_loc, read_imagef(src, sampler, src_loc)); -} -@end verbatim - -@item -Blend two inputs together, with the amount of each input used varying -with the index counter. -@verbatim -__kernel void blend_images(__write_only image2d_t dst, - unsigned int index, - __read_only image2d_t src1, - __read_only image2d_t src2) -{ - const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | - CLK_FILTER_LINEAR); - - float blend = (cos((float)index / 50.0f) + 1.0f) / 2.0f; - - int2 dst_loc = (int2)(get_global_id(0), get_global_id(1)); - int2 src1_loc = dst_loc * get_image_dim(src1) / get_image_dim(dst); - int2 src2_loc = dst_loc * get_image_dim(src2) / get_image_dim(dst); - - float4 val1 = read_imagef(src1, sampler, src1_loc); - float4 val2 = read_imagef(src2, sampler, src2_loc); - - write_imagef(dst, dst_loc, val1 * blend + val2 * (1.0f - blend)); -} -@end verbatim +@subsection Commands -@end itemize +This filter supports the all above options as @ref{commands}. @section pseudocolor Alter frame colors in video with pseudocolors. -This filter accept the following options: +This filter accepts the following options: @table @option @item c0 @@ -14364,12 +16517,33 @@ @item c3 set pixel fourth component expression, corresponds to the alpha component -@item i +@item index, i set component to use as base for altering colors + +@item preset, p +Pick one of built-in LUTs. By default is set to none. + +Available LUTs: +@table @samp +@item magma +@item inferno +@item plasma +@item viridis +@item turbo +@item cividis +@item range1 +@item range2 +@item shadows +@item highlights @end table -Each of them specifies the expression to use for computing the lookup table for -the corresponding pixel component values. +@item opacity +Set opacity of output colors. Allowed range is from 0 to 1. +Default value is set to 1. +@end table + +Each of the expression options specifies the expression to use for computing +the lookup table for the corresponding pixel component values. The expressions can contain the following constants and functions: @@ -14390,6 +16564,10 @@ All expressions default to "val". +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @subsection Examples @itemize @@ -14489,6 +16667,9 @@ channels. @end table +@subsection Examples +@itemize +@item For example: @example movie=ref_movie.mpg, setpts=PTS-STARTPTS [main]; @@ -14499,6 +16680,13 @@ reference file @file{ref_movie.mpg}. The PSNR of each individual frame is stored in @file{stats.log}. +@item +Another example with different containers: +@example +ffmpeg -i main.mpg -i ref.mkv -lavfi "[0:v]settb=AVTB,setpts=PTS-STARTPTS[main];[1:v]settb=AVTB,setpts=PTS-STARTPTS[ref];[main][ref]psnr" -f null - +@end example +@end itemize + @anchor{pullup} @section pullup @@ -14639,44 +16827,22 @@ @item scan_max Set the line to end scanning for EIA-608 data. Default is @code{29}. -@item mac -Set minimal acceptable amplitude change for sync codes detection. -Default is @code{0.2}. Allowed range is @code{[0.001 - 1]}. - @item spw Set the ratio of width reserved for sync code detection. -Default is @code{0.27}. Allowed range is @code{[0.01 - 0.7]}. - -@item mhd -Set the max peaks height difference for sync code detection. -Default is @code{0.1}. Allowed range is @code{[0.0 - 0.5]}. - -@item mpd -Set max peaks period difference for sync code detection. -Default is @code{0.1}. Allowed range is @code{[0.0 - 0.5]}. - -@item msd -Set the first two max start code bits differences. -Default is @code{0.02}. Allowed range is @code{[0.0 - 0.5]}. - -@item bhd -Set the minimum ratio of bits height compared to 3rd start code bit. -Default is @code{0.75}. Allowed range is @code{[0.01 - 1]}. - -@item th_w -Set the white color threshold. Default is @code{0.35}. Allowed range is @code{[0.1 - 1]}. - -@item th_b -Set the black color threshold. Default is @code{0.15}. Allowed range is @code{[0.0 - 0.5]}. +Default is @code{0.27}. Allowed range is @code{[0.1 - 0.7]}. @item chp Enable checking the parity bit. In the event of a parity error, the filter will output @code{0x00} for that character. Default is false. @item lp -Lowpass lines prior further proccessing. Default is disabled. +Lowpass lines prior to further processing. Default is enabled. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @subsection Examples @itemize @@ -14740,6 +16906,11 @@ @item format Specify pixel format of output from this filter. Can be @code{color} or @code{gray}. Default is @code{color}. + +@item fill +Specify the color of the unmapped pixels. For the syntax of this option, +check the @ref{color syntax,,"Color" section in the ffmpeg-utils +manual,ffmpeg-utils}. Default color is @code{black}. @end table @section removegrain @@ -14923,6 +17094,10 @@ Set edge mode, can be @var{smear}, default, or @var{warp}. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section roberts Apply roberts cross operator to input video stream. @@ -14940,6 +17115,10 @@ Set value which will be added to filtered result. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section rotate Rotate video by an arbitrary angle expressed in radians. @@ -15295,6 +17474,19 @@ or @option{h}, you still need to specify the output resolution for this option to work. +@item force_divisible_by +Ensures that both the output dimensions, width and height, are divisible by the +given integer when used together with @option{force_original_aspect_ratio}. This +works similar to using @code{-n} in the @option{w} and @option{h} options. + +This option respects the value set for @option{force_original_aspect_ratio}, +increasing or decreasing the resolution accordingly. The video's aspect ratio +may be slightly modified. + +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. + @end table The values of the @option{w} and @option{h} options are expressions @@ -15335,6 +17527,19 @@ @item ovsub horizontal and vertical output chroma subsample values. For example for the pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1. + +@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 @subsection Examples @@ -15487,6 +17692,46 @@ @item lanczos @end table +@item force_original_aspect_ratio +Enable decreasing or increasing output video width or height if necessary to +keep the original aspect ratio. Possible values: + +@table @samp +@item disable +Scale the video as specified and disable this feature. + +@item decrease +The output video dimensions will automatically be decreased if needed. + +@item increase +The output video dimensions will automatically be increased if needed. + +@end table + +One useful instance of this option is that when you know a specific device's +maximum allowed resolution, you can use this to limit the output video to +that, while retaining the aspect ratio. For example, device A allows +1280x720 playback, and your video is 1920x800. Using this option (set it to +decrease) and specifying 1280x720 to the command line makes the output +1280x533. + +Please note that this is a different thing than specifying -1 for @option{w} +or @option{h}, you still need to specify the output resolution for this option +to work. + +@item force_divisible_by +Ensures that both the output dimensions, width and height, are divisible by the +given integer when used together with @option{force_original_aspect_ratio}. This +works similar to using @code{-n} in the @option{w} and @option{h} options. + +This option respects the value set for @option{force_original_aspect_ratio}, +increasing or decreasing the resolution accordingly. The video's aspect ratio +may be slightly modified. + +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. + @end table @section scale2ref @@ -15518,6 +17763,19 @@ The main input video's horizontal and vertical chroma subsample values. For example for the pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1. + +@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 @@ -15536,10 +17794,88 @@ @end example @end itemize -@anchor{selectivecolor} -@section selectivecolor +@subsection Commands -Adjust cyan, magenta, yellow and black (CMYK) to certain ranges of colors (such +This filter supports the following commands: +@table @option +@item width, w +@item height, h +Set the output video dimension expression. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. +@end table + +@section scroll +Scroll input video horizontally and/or vertically by constant speed. + +The filter accepts the following options: +@table @option +@item horizontal, h +Set the horizontal scrolling speed. Default is 0. Allowed range is from -1 to 1. +Negative values changes scrolling direction. + +@item vertical, v +Set the vertical scrolling speed. Default is 0. Allowed range is from -1 to 1. +Negative values changes scrolling direction. + +@item hpos +Set the initial horizontal scrolling position. Default is 0. Allowed range is from 0 to 1. + +@item vpos +Set the initial vertical scrolling position. Default is 0. Allowed range is from 0 to 1. +@end table + +@subsection Commands + +This filter supports the following @ref{commands}: +@table @option +@item horizontal, h +Set the horizontal scrolling speed. +@item vertical, v +Set the vertical scrolling speed. +@end table + +@anchor{scdet} +@section scdet + +Detect video scene change. + +This filter sets frame metadata with mafd between frame, the scene score, and +forward the frame to the next filter, so they can use these metadata to detect +scene change or others. + +In addition, this filter logs a message and sets frame metadata when it detects +a scene change by @option{threshold}. + +@code{lavfi.scd.mafd} metadata keys are set with mafd for every frame. + +@code{lavfi.scd.score} metadata keys are set with scene change score for every frame +to detect scene change. + +@code{lavfi.scd.time} metadata keys are set with current filtered frame time which +detect scene change with @option{threshold}. + +The filter accepts the following options: + +@table @option +@item threshold, t +Set the scene change detection threshold as a percentage of maximum change. Good +values are in the @code{[8.0, 14.0]} range. The range for @option{threshold} is +@code{[0., 100.]}. + +Default value is @code{10.}. + +@item sc_pass, s +Set the flag to pass scene change frames to the next filter. Default value is @code{0} +You can enable it if you want to get snapshot of scene change frames only. +@end table + +@anchor{selectivecolor} +@section selectivecolor + +Adjust cyan, magenta, yellow and black (CMYK) to certain ranges of colors (such as "reds", "yellows", "greens", "cyans", ...). The adjustment range is defined by the "purity" of the color (that is, how saturated it already is). @@ -15866,6 +18202,37 @@ @end table @end table +@section shear +Apply shear transform to input video. + +This filter supports the following options: + +@table @option +@item shx +Shear factor in X-direction. Default value is 0. +Allowed range is from -2 to 2. + +@item shy +Shear factor in Y-direction. Default value is 0. +Allowed range is from -2 to 2. + +@item fillcolor, c +Set the color used to fill the output area not covered by the transformed +video. For the general syntax of this option, check the +@ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. +If the special value "none" is selected then no +background is printed (useful for example if the background is never shown). + +Default value is "black". + +@item interp +Set interpolation type. Can be @code{bilinear} or @code{nearest}. Default is @code{bilinear}. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section showinfo Show a line containing various information for each input video frame. @@ -15930,6 +18297,15 @@ @item plane_checksum The Adler-32 checksum (printed in hexadecimal) of each plane of the input frame, expressed in the form "[@var{c0} @var{c1} @var{c2} @var{c3}]". + +@item mean +The mean value of pixels in each plane of the input frame, expressed in the form +"[@var{mean0} @var{mean1} @var{mean2} @var{mean3}]". + +@item stdev +The standard deviation of pixel values in each plane of the input frame, expressed +in the form "[@var{stdev0} @var{stdev1} @var{stdev2} @var{stdev3}]". + @end table @section showpalette @@ -15977,6 +18353,33 @@ @end example @end itemize +@section shufflepixels + +Reorder pixels in video frames. + +This filter accepts the following options: + +@table @option +@item direction, d +Set shuffle direction. Can be forward or inverse direction. +Default direction is forward. + +@item mode, m +Set shuffle mode. Can be horizontal, vertical or block mode. + +@item width, w +@item height, h +Set shuffle block_size. In case of horizontal shuffle mode only width +part of size is used, and in case of vertical shuffle mode only height +part of size is used. + +@item seed, s +Set random seed used with shuffling pixels. Mainly useful to set to be able +to reverse filtering process to get original input. +For example, to reverse forward shuffle you need to use same parameters +and exact same seed and to set direction to inverse. +@end table + @section shuffleplanes Reorder and/or duplicate video planes. @@ -16343,6 +18746,130 @@ If a chroma option is not explicitly set, the corresponding luma value is set. +@section sobel +Apply sobel operator to input video stream. + +The filter accepts the following option: + +@table @option +@item planes +Set which planes will be processed, unprocessed planes will be copied. +By default value 0xf, all planes will be processed. + +@item scale +Set value which will be multiplied with filtered result. + +@item delta +Set value which will be added to filtered result. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@anchor{spp} +@section spp + +Apply a simple postprocessing filter that compresses and decompresses the image +at several (or - in the case of @option{quality} level @code{6} - all) shifts +and average the results. + +The filter accepts the following options: + +@table @option +@item quality +Set quality. This option defines the number of levels for averaging. It accepts +an integer in the range 0-6. If set to @code{0}, the filter will have no +effect. A value of @code{6} means the higher quality. For each increment of +that value the speed drops by a factor of approximately 2. Default value is +@code{3}. + +@item qp +Force a constant quantization parameter. If not set, the filter will use the QP +from the video stream (if available). + +@item mode +Set thresholding mode. Available modes are: + +@table @samp +@item hard +Set hard thresholding (default). +@item soft +Set soft thresholding (better de-ringing effect, but likely blurrier). +@end table + +@item use_bframe_qp +Enable the use of the QP from the B-Frames if set to @code{1}. Using this +option may cause flicker since the B-Frames have often larger QP. Default is +@code{0} (not enabled). +@end table + +@subsection Commands + +This filter supports the following commands: +@table @option +@item quality, level +Set quality level. The value @code{max} can be used to set the maximum level, +currently @code{6}. +@end table + +@anchor{sr} +@section sr + +Scale the input by applying one of the super-resolution methods based on +convolutional neural networks. Supported models: + +@itemize +@item +Super-Resolution Convolutional Neural Network model (SRCNN). +See @url{https://arxiv.org/abs/1501.00092}. + +@item +Efficient Sub-Pixel Convolutional Neural Network model (ESPCN). +See @url{https://arxiv.org/abs/1609.05158}. +@end itemize + +Training scripts as well as scripts for model file (.pb) saving can be found at +@url{https://github.com/XueweiMeng/sr/tree/sr_dnn_native}. Original repository +is at @url{https://github.com/HighVoltageRocknRoll/sr.git}. + +Native model files (.model) can be generated from TensorFlow model +files (.pb) by using tools/python/convert.py + +The filter accepts the following options: + +@table @option +@item dnn_backend +Specify which DNN backend to use for model loading and execution. This option accepts +the following values: + +@table @samp +@item native +Native implementation of DNN loading and execution. + +@item tensorflow +TensorFlow backend. To enable this backend you +need to install the TensorFlow for C library (see +@url{https://www.tensorflow.org/install/install_c}) and configure FFmpeg with +@code{--enable-libtensorflow} +@end table + +Default value is @samp{native}. + +@item model +Set path to model file specifying network architecture and its parameters. +Note that different backends use different file formats. TensorFlow backend +can load files for both formats, while native backend can load files for only +its format. + +@item scale_factor +Set scale factor for SRCNN model. Allowed values are @code{2}, @code{3} and @code{4}. +Default value is @code{2}. Scale factor is necessary for SRCNN model, because it accepts +input upscaled using bicubic upscaling with proper scale factor. +@end table + +This feature can also be finished with @ref{dnn_processing} filter. + @section ssim Obtain the SSIM (Structural SImilarity Metric) between two input videos. @@ -16389,6 +18916,9 @@ This filter also supports the @ref{framesync} options. +@subsection Examples +@itemize +@item For example: @example movie=ref_movie.mpg, setpts=PTS-STARTPTS [main]; @@ -16399,11 +18929,19 @@ reference file @file{ref_movie.mpg}. The SSIM of each individual frame is stored in @file{stats.log}. +@item Another example with both psnr and ssim at same time: @example ffmpeg -i main.mpg -i ref.mpg -lavfi "ssim;[0:v][1:v]psnr" -f null - @end example +@item +Another example with different containers: +@example +ffmpeg -i main.mpg -i ref.mkv -lavfi "[0:v]settb=AVTB,setpts=PTS-STARTPTS[main];[1:v]settb=AVTB,setpts=PTS-STARTPTS[ref];[main][ref]ssim" -f null - +@end example +@end itemize + @section stereo3d Convert between different stereoscopic image formats. @@ -16431,16 +18969,20 @@ (right eye left, left eye right) @item abl +@item tbl above-below (left eye above, right eye below) @item abr +@item tbr above-below (right eye above, left eye below) @item ab2l +@item tb2l above-below with half height resolution (left eye above, right eye below) @item ab2r +@item tb2r above-below with half height resolution (right eye above, left eye below) @@ -16484,16 +19026,20 @@ (right eye left, left eye right) @item abl +@item tbl above-below (left eye above, right eye below) @item abr +@item tbr above-below (right eye above, left eye below) @item ab2l +@item tb2l above-below with half height resolution (left eye above, right eye below) @item ab2r +@item tb2r above-below with half height resolution (right eye above, left eye below) @@ -16645,140 +19191,32 @@ @end example @end itemize -@section sobel -Apply sobel operator to input video stream. - -The filter accepts the following option: - -@table @option -@item planes -Set which planes will be processed, unprocessed planes will be copied. -By default value 0xf, all planes will be processed. - -@item scale -Set value which will be multiplied with filtered result. - -@item delta -Set value which will be added to filtered result. -@end table +@anchor{subtitles} +@section subtitles -@anchor{spp} -@section spp +Draw subtitles on top of input video using the libass library. -Apply a simple postprocessing filter that compresses and decompresses the image -at several (or - in the case of @option{quality} level @code{6} - all) shifts -and average the results. +To enable compilation of this filter you need to configure FFmpeg with +@code{--enable-libass}. This filter also requires a build with libavcodec and +libavformat to convert the passed subtitles file to ASS (Advanced Substation +Alpha) subtitles format. The filter accepts the following options: @table @option -@item quality -Set quality. This option defines the number of levels for averaging. It accepts -an integer in the range 0-6. If set to @code{0}, the filter will have no -effect. A value of @code{6} means the higher quality. For each increment of -that value the speed drops by a factor of approximately 2. Default value is -@code{3}. +@item filename, f +Set the filename of the subtitle file to read. It must be specified. -@item qp -Force a constant quantization parameter. If not set, the filter will use the QP -from the video stream (if available). +@item original_size +Specify the size of the original video, the video for which the ASS file +was composed. For the syntax of this option, check the +@ref{video size syntax,,"Video size" section in the ffmpeg-utils manual,ffmpeg-utils}. +Due to a misdesign in ASS aspect ratio arithmetic, this is necessary to +correctly scale the fonts if the aspect ratio has been changed. -@item mode -Set thresholding mode. Available modes are: - -@table @samp -@item hard -Set hard thresholding (default). -@item soft -Set soft thresholding (better de-ringing effect, but likely blurrier). -@end table - -@item use_bframe_qp -Enable the use of the QP from the B-Frames if set to @code{1}. Using this -option may cause flicker since the B-Frames have often larger QP. Default is -@code{0} (not enabled). -@end table - -@section sr - -Scale the input by applying one of the super-resolution methods based on -convolutional neural networks. Supported models: - -@itemize -@item -Super-Resolution Convolutional Neural Network model (SRCNN). -See @url{https://arxiv.org/abs/1501.00092}. - -@item -Efficient Sub-Pixel Convolutional Neural Network model (ESPCN). -See @url{https://arxiv.org/abs/1609.05158}. -@end itemize - -Training scripts as well as scripts for model file (.pb) saving can be found at -@url{https://github.com/XueweiMeng/sr/tree/sr_dnn_native}. Original repository -is at @url{https://github.com/HighVoltageRocknRoll/sr.git}. - -Native model files (.model) can be generated from TensorFlow model -files (.pb) by using tools/python/convert.py - -The filter accepts the following options: - -@table @option -@item dnn_backend -Specify which DNN backend to use for model loading and execution. This option accepts -the following values: - -@table @samp -@item native -Native implementation of DNN loading and execution. - -@item tensorflow -TensorFlow backend. To enable this backend you -need to install the TensorFlow for C library (see -@url{https://www.tensorflow.org/install/install_c}) and configure FFmpeg with -@code{--enable-libtensorflow} -@end table - -Default value is @samp{native}. - -@item model -Set path to model file specifying network architecture and its parameters. -Note that different backends use different file formats. TensorFlow backend -can load files for both formats, while native backend can load files for only -its format. - -@item scale_factor -Set scale factor for SRCNN model. Allowed values are @code{2}, @code{3} and @code{4}. -Default value is @code{2}. Scale factor is necessary for SRCNN model, because it accepts -input upscaled using bicubic upscaling with proper scale factor. -@end table - -@anchor{subtitles} -@section subtitles - -Draw subtitles on top of input video using the libass library. - -To enable compilation of this filter you need to configure FFmpeg with -@code{--enable-libass}. This filter also requires a build with libavcodec and -libavformat to convert the passed subtitles file to ASS (Advanced Substation -Alpha) subtitles format. - -The filter accepts the following options: - -@table @option -@item filename, f -Set the filename of the subtitle file to read. It must be specified. - -@item original_size -Specify the size of the original video, the video for which the ASS file -was composed. For the syntax of this option, check the -@ref{video size syntax,,"Video size" section in the ffmpeg-utils manual,ffmpeg-utils}. -Due to a misdesign in ASS aspect ratio arithmetic, this is necessary to -correctly scale the fonts if the aspect ratio has been changed. - -@item fontsdir -Set a directory path containing fonts that can be used by the filter. -These fonts will be used in addition to whatever the font provider uses. +@item fontsdir +Set a directory path containing fonts that can be used by the filter. +These fonts will be used in addition to whatever the font provider uses. @item alpha Process alpha channel, by default alpha channel is untouched. @@ -16822,7 +19260,7 @@ To make the subtitles stream from @file{sub.srt} appear in 80% transparent blue @code{DejaVu Serif}, use: @example -subtitles=sub.srt:force_style='FontName=DejaVu Serif,PrimaryColour=&HCCFF0000' +subtitles=sub.srt:force_style='Fontname=DejaVu Serif,PrimaryColour=&HCCFF0000' @end example @section super2xsai @@ -16886,9 +19324,18 @@ the position in the file of the input frame, NAN if unknown @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section swapuv Swap U & V plane. +@section tblend +Blend successive video frames. + +See @ref{blend} + @section telecine Apply telecine process to the video. @@ -16928,6 +19375,84 @@ 16p: 33333334 @end example +@section thistogram + +Compute and draw a color distribution histogram for the input video across time. + +Unlike @ref{histogram} video filter which only shows histogram of single input frame +at certain time, this filter shows also past histograms of number of frames defined +by @code{width} option. + +The computed histogram is a representation of the color component +distribution in an image. + +The filter accepts the following options: + +@table @option +@item width, w +Set width of single color component output. Default value is @code{0}. +Value of @code{0} means width will be picked from input video. +This also set number of passed histograms to keep. +Allowed range is [0, 8192]. + +@item display_mode, d +Set display mode. +It accepts the following values: +@table @samp +@item stack +Per color component graphs are placed below each other. + +@item parade +Per color component graphs are placed side by side. + +@item overlay +Presents information identical to that in the @code{parade}, except +that the graphs representing color components are superimposed directly +over one another. +@end table +Default is @code{stack}. + +@item levels_mode, m +Set mode. Can be either @code{linear}, or @code{logarithmic}. +Default is @code{linear}. + +@item components, c +Set what color components to display. +Default is @code{7}. + +@item bgopacity, b +Set background opacity. Default is @code{0.9}. + +@item envelope, e +Show envelope. Default is disabled. + +@item ecolor, ec +Set envelope color. Default is @code{gold}. + +@item slide +Set slide mode. + +Available values for slide is: +@table @samp +@item frame +Draw new frame when right border is reached. + +@item replace +Replace old columns with new ones. + +@item scroll +Scroll from right to left. + +@item rscroll +Scroll from left to right. + +@item picture +Draw single picture. +@end table + +Default is @code{replace}. +@end table + @section threshold Apply threshold effect to video stream. @@ -17016,10 +19541,13 @@ @end example @end itemize +@anchor{tile} @section tile Tile several successive frames together. +The @ref{untile} filter can do the reverse. + The filter accepts the following options: @table @option @@ -17307,11 +19835,58 @@ This will slightly less reduce interlace 'twitter' and Moire patterning but better retain detail and subjective sharpness impression. +@item bypass_il +Bypass already interlaced frames, only adjust the frame rate. +@end table + +Vertical low-pass filtering and bypassing already interlaced frames can only be +enabled for @option{mode} @var{interleave_top} and @var{interleave_bottom}. + +@end table + +@section tmedian +Pick median pixels from several successive input video frames. + +The filter accepts the following options: + +@table @option +@item radius +Set radius of median filter. +Default is 1. Allowed range is from 1 to 127. + +@item planes +Set which planes to filter. Default value is @code{15}, by which all planes are processed. + +@item percentile +Set median percentile. Default value is @code{0.5}. +Default value of @code{0.5} will pick always median values, while @code{0} will pick +minimum values, and @code{1} maximum values. @end table -Vertical low-pass filtering can only be enabled for @option{mode} -@var{interleave_top} and @var{interleave_bottom}. +@subsection Commands + +This filter supports all above options as @ref{commands}, excluding option @code{radius}. + +@section tmidequalizer + +Apply Temporal Midway Video Equalization effect. + +Midway Video Equalization adjusts a sequence of video frames to have the same +histograms, while maintaining their dynamics as much as possible. It's +useful for e.g. matching exposures from a video frames sequence. + +This filter accepts the following option: + +@table @option +@item radius +Set filtering radius. Default is @code{5}. Allowed range is from 1 to 127. + +@item sigma +Set filtering sigma. Default is @code{0.5}. This controls strength of filtering. +Setting this option to 0 effectively does nothing. +@item planes +Set which planes to process. Default is @code{15}, which is all available planes. @end table @section tmix @@ -17358,6 +19933,15 @@ @end example @end itemize +@subsection Commands + +This filter supports the following commands: +@table @option +@item weights +@item scale +Syntax is same as option with same name. +@end table + @anchor{tonemap} @section tonemap Tone map colors from different dynamic ranges. @@ -17474,29 +20058,31 @@ @table @option @item start -Specify number of delay frames before input video stream. +Specify number of delay frames before input video stream. Default is 0. @item stop Specify number of padding frames after input video stream. -Set to -1 to pad indefinitely. +Set to -1 to pad indefinitely. Default is 0. @item start_mode Set kind of frames added to beginning of stream. Can be either @var{add} or @var{clone}. With @var{add} frames of solid-color are added. With @var{clone} frames are clones of first frame. +Default is @var{add}. @item stop_mode Set kind of frames added to end of stream. Can be either @var{add} or @var{clone}. With @var{add} frames of solid-color are added. With @var{clone} frames are clones of last frame. +Default is @var{add}. @item start_duration, stop_duration Specify the duration of the start/stop delay. See @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils} for the accepted syntax. -These options override @var{start} and @var{stop}. +These options override @var{start} and @var{stop}. Default is 0. @item color Specify the color of the padded area. For the syntax of this option, @@ -17780,6 +20366,37 @@ @end example @end itemize +@anchor{untile} +@section untile + +Decompose a video made of tiled images into the individual images. + +The frame rate of the output video is the frame rate of the input video +multiplied by the number of tiles. + +This filter does the reverse of @ref{tile}. + +The filter accepts the following options: + +@table @option + +@item layout +Set the grid size (i.e. the number of lines and columns). For the syntax of +this option, check the +@ref{video size syntax,,"Video size" section in the ffmpeg-utils manual,ffmpeg-utils}. +@end table + +@subsection Examples + +@itemize +@item +Produce a 1-second video from a still image file made of 25 frames stacked +vertically, like an analogic film reel: +@example +ffmpeg -r 1 -i image.jpg -vf untile=1x25 movie.mkv +@end example +@end itemize + @section uspp Apply ultra slow/simple postprocessing filter that compresses and decompresses @@ -17805,53 +20422,470 @@ from the video stream (if available). @end table -@section vaguedenoiser - -Apply a wavelet based denoiser. +@section v360 -It transforms each frame from the video input into the wavelet domain, -using Cohen-Daubechies-Feauveau 9/7. Then it applies some filtering to -the obtained coefficients. It does an inverse wavelet transform after. -Due to wavelet properties, it should give a nice smoothed result, and -reduced noise, without blurring picture features. +Convert 360 videos between various formats. -This filter accepts the following options: +The filter accepts the following options: @table @option -@item threshold -The filtering strength. The higher, the more filtered the video will be. -Hard thresholding can use a higher threshold than soft thresholding -before the video looks overfiltered. Default value is 2. -@item method -The filtering method the filter will use. +@item input +@item output +Set format of the input/output video. + +Available formats: -It accepts the following values: @table @samp -@item hard -All values under the threshold will be zeroed. -@item soft -All values under the threshold will be zeroed. All values above will be -reduced by the threshold. +@item e +@item equirect +Equirectangular projection. -@item garrote -Scales or nullifies coefficients - intermediary between (more) soft and -(less) hard thresholding. -@end table +@item c3x2 +@item c6x1 +@item c1x6 +Cubemap with 3x2/6x1/1x6 layout. -Default is garrote. +Format specific options: -@item nsteps -Number of times, the wavelet will decompose the picture. Picture can't -be decomposed beyond a particular point (typically, 8 for a 640x480 -frame - as 2^9 = 512 > 480). Valid values are integers between 1 and 32. Default value is 6. +@table @option +@item in_pad +@item out_pad +Set padding proportion for the input/output cubemap. Values in decimals. -@item percent -Partial of full denoising (limited coefficients shrinking), from 0 to 100. Default value is 85. +Example values: +@table @samp +@item 0 +No padding. +@item 0.01 +1% of face is padding. For example, with 1920x1280 resolution face size would be 640x640 and padding would be 3 pixels from each side. (640 * 0.01 = 6 pixels) +@end table + +Default value is @b{@samp{0}}. +Maximum value is @b{@samp{0.1}}. + +@item fin_pad +@item fout_pad +Set fixed padding for the input/output cubemap. Values in pixels. + +Default value is @b{@samp{0}}. If greater than zero it overrides other padding options. + +@item in_forder +@item out_forder +Set order of faces for the input/output cubemap. Choose one direction for each position. + +Designation of directions: +@table @samp +@item r +right +@item l +left +@item u +up +@item d +down +@item f +forward +@item b +back +@end table + +Default value is @b{@samp{rludfb}}. + +@item in_frot +@item out_frot +Set rotation of faces for the input/output cubemap. Choose one angle for each position. + +Designation of angles: +@table @samp +@item 0 +0 degrees clockwise +@item 1 +90 degrees clockwise +@item 2 +180 degrees clockwise +@item 3 +270 degrees clockwise +@end table + +Default value is @b{@samp{000000}}. +@end table + +@item eac +Equi-Angular Cubemap. + +@item flat +@item gnomonic +@item rectilinear +Regular video. + +Format specific options: +@table @option +@item h_fov +@item v_fov +@item d_fov +Set output horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. + +@item ih_fov +@item iv_fov +@item id_fov +Set input horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. +@end table + +@item dfisheye +Dual fisheye. + +Format specific options: +@table @option +@item h_fov +@item v_fov +@item d_fov +Set output horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. + +@item ih_fov +@item iv_fov +@item id_fov +Set input horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. +@end table + +@item barrel +@item fb +@item barrelsplit +Facebook's 360 formats. + +@item sg +Stereographic format. + +Format specific options: +@table @option +@item h_fov +@item v_fov +@item d_fov +Set output horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. + +@item ih_fov +@item iv_fov +@item id_fov +Set input horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. +@end table + +@item mercator +Mercator format. + +@item ball +Ball format, gives significant distortion toward the back. + +@item hammer +Hammer-Aitoff map projection format. + +@item sinusoidal +Sinusoidal map projection format. + +@item fisheye +Fisheye projection. + +Format specific options: +@table @option +@item h_fov +@item v_fov +@item d_fov +Set output horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. + +@item ih_fov +@item iv_fov +@item id_fov +Set input horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. +@end table + +@item pannini +Pannini projection. + +Format specific options: +@table @option +@item h_fov +Set output pannini parameter. + +@item ih_fov +Set input pannini parameter. +@end table + +@item cylindrical +Cylindrical projection. + +Format specific options: +@table @option +@item h_fov +@item v_fov +@item d_fov +Set output horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. + +@item ih_fov +@item iv_fov +@item id_fov +Set input horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. +@end table + +@item perspective +Perspective projection. @i{(output only)} + +Format specific options: +@table @option +@item v_fov +Set perspective parameter. +@end table + +@item tetrahedron +Tetrahedron projection. + +@item tsp +Truncated square pyramid projection. + +@item he +@item hequirect +Half equirectangular projection. + +@item equisolid +Equisolid format. + +Format specific options: +@table @option +@item h_fov +@item v_fov +@item d_fov +Set output horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. + +@item ih_fov +@item iv_fov +@item id_fov +Set input horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. +@end table + +@item og +Orthographic format. + +Format specific options: +@table @option +@item h_fov +@item v_fov +@item d_fov +Set output horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. + +@item ih_fov +@item iv_fov +@item id_fov +Set input horizontal/vertical/diagonal field of view. Values in degrees. + +If diagonal field of view is set it overrides horizontal and vertical field of view. +@end table + +@item octahedron +Octahedron projection. +@end table + +@item interp +Set interpolation method.@* +@i{Note: more complex interpolation methods require much more memory to run.} + +Available methods: + +@table @samp +@item near +@item nearest +Nearest neighbour. +@item line +@item linear +Bilinear interpolation. +@item lagrange9 +Lagrange9 interpolation. +@item cube +@item cubic +Bicubic interpolation. +@item lanc +@item lanczos +Lanczos interpolation. +@item sp16 +@item spline16 +Spline16 interpolation. +@item gauss +@item gaussian +Gaussian interpolation. +@item mitchell +Mitchell interpolation. +@end table + +Default value is @b{@samp{line}}. + +@item w +@item h +Set the output video resolution. + +Default resolution depends on formats. + +@item in_stereo +@item out_stereo +Set the input/output stereo format. + +@table @samp +@item 2d +2D mono +@item sbs +Side by side +@item tb +Top bottom +@end table + +Default value is @b{@samp{2d}} for input and output format. + +@item yaw +@item pitch +@item roll +Set rotation for the output video. Values in degrees. + +@item rorder +Set rotation order for the output video. Choose one item for each position. + +@table @samp +@item y, Y +yaw +@item p, P +pitch +@item r, R +roll +@end table + +Default value is @b{@samp{ypr}}. + +@item h_flip +@item v_flip +@item d_flip +Flip the output video horizontally(swaps left-right)/vertically(swaps up-down)/in-depth(swaps back-forward). Boolean values. + +@item ih_flip +@item iv_flip +Set if input video is flipped horizontally/vertically. Boolean values. + +@item in_trans +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 alpha_mask +Build mask in alpha plane for all unmapped pixels by marking them fully transparent. Boolean value, by default disabled. +@end table + +@subsection Examples + +@itemize +@item +Convert equirectangular video to cubemap with 3x2 layout and 1% padding using bicubic interpolation: +@example +ffmpeg -i input.mkv -vf v360=e:c3x2:cubic:out_pad=0.01 output.mkv +@end example +@item +Extract back view of Equi-Angular Cubemap: +@example +ffmpeg -i input.mkv -vf v360=eac:flat:yaw=180 output.mkv +@end example +@item +Convert transposed and horizontally flipped Equi-Angular Cubemap in side-by-side stereo format to equirectangular top-bottom stereo format: +@example +v360=eac:equirect:in_stereo=sbs:in_trans=1:ih_flip=1:out_stereo=tb +@end example +@end itemize + +@subsection Commands + +This filter supports subset of above options as @ref{commands}. + +@section vaguedenoiser + +Apply a wavelet based denoiser. + +It transforms each frame from the video input into the wavelet domain, +using Cohen-Daubechies-Feauveau 9/7. Then it applies some filtering to +the obtained coefficients. It does an inverse wavelet transform after. +Due to wavelet properties, it should give a nice smoothed result, and +reduced noise, without blurring picture features. + +This filter accepts the following options: + +@table @option +@item threshold +The filtering strength. The higher, the more filtered the video will be. +Hard thresholding can use a higher threshold than soft thresholding +before the video looks overfiltered. Default value is 2. + +@item method +The filtering method the filter will use. + +It accepts the following values: +@table @samp +@item hard +All values under the threshold will be zeroed. + +@item soft +All values under the threshold will be zeroed. All values above will be +reduced by the threshold. + +@item garrote +Scales or nullifies coefficients - intermediary between (more) soft and +(less) hard thresholding. +@end table + +Default is garrote. + +@item nsteps +Number of times, the wavelet will decompose the picture. Picture can't +be decomposed beyond a particular point (typically, 8 for a 640x480 +frame - as 2^9 = 512 > 480). Valid values are integers between 1 and 32. Default value is 6. + +@item percent +Partial of full denoising (limited coefficients shrinking), from 0 to 100. Default value is 85. @item planes A list of the planes to process. By default all planes are processed. + +@item type +The threshold type the filter will use. + +It accepts the following values: +@table @samp +@item universal +Threshold used is same for all decompositions. + +@item bayes +Threshold used depends also on each decomposition coefficients. +@end table + +Default is universal. @end table @section vectorscope @@ -17868,6 +20902,7 @@ It accepts the following values: @table @samp @item gray +@item tint Gray values are displayed on graph, higher brightness means more pixels have same component color value on location in graph. This is the default mode. @@ -17926,6 +20961,7 @@ @item none @item green @item color +@item invert @end table @item opacity, o @@ -17970,6 +21006,11 @@ @item 709 @end table Default is auto. + +@item tint0, t0 +@item tint1, t1 +Set color tint for gray/tint vectorscope mode. By default both options are zero. +This means no tint, and output will remain gray. @end table @anchor{vidstabdetect} @@ -18222,8 +21263,8 @@ At end it will output number of frames detected as having variable delta pts, and ones with constant delta pts. -If there was frames with variable delta, than it will also show min and max delta -encountered. +If there was frames with variable delta, than it will also show min, max and +average delta encountered. @section vibrance @@ -18258,6 +21299,31 @@ otherwise colors will be less saturated, more towards gray. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section vif + +Obtain the average VIF (Visual Information Fidelity) between two input videos. + +This filter takes two input videos. + +Both input videos must have the same resolution and pixel format for +this filter to work correctly. Also it assumes that both inputs +have the same number of frames, which are compared one by one. + +The obtained average VIF score is printed through the logging system. + +The filter stores the calculated VIF score of each frame. + +In the below example the input file @file{main.mpg} being processed is compared +with the reference file @file{ref.mpg}. + +@example +ffmpeg -i main.mpg -i ref.mpg -lavfi vif -f null - +@end example + @anchor{vignette} @section vignette @@ -18371,16 +21437,23 @@ @section vmafmotion -Obtain the average vmaf motion score of a video. -It is one of the component filters of VMAF. +Obtain the average VMAF motion score of a video. +It is one of the component metrics of VMAF. The obtained average motion score is printed through the logging system. -In the below example the input file @file{ref.mpg} is being processed and score -is computed. +The filter accepts the following options: + +@table @option +@item stats_file +If specified, the filter will use the named file to save the motion score of +each frame with respect to the previous frame. +When filename equals "-" the data is sent to standard output. +@end table +Example: @example -ffmpeg -i ref.mpg -lavfi vmafmotion -f null - +ffmpeg -i ref.mpg -vf vmafmotion -f null - @end example @section vstack @@ -18391,7 +21464,7 @@ Note that this filter is faster than using @ref{overlay} and @ref{pad} filter to create same output. -The filter accept the following option: +The filter accepts the following options: @table @option @item inputs @@ -18412,11 +21485,11 @@ Easterbrook for BBC R&D, the Weston 3 field deinterlacing filter uses filter coefficients calculated by BBC R&D. -This filter use field-dominance information in frame to decide which +This filter uses field-dominance information in frame to decide which of each pair of fields to place first in the output. If it gets it wrong use @ref{setfield} filter before @code{w3fdif} filter. -There are two sets of filter coefficients, so called "simple": +There are two sets of filter coefficients, so called "simple" and "complex". Which set of filter coefficients is used can be set by passing an optional parameter: @@ -18432,25 +21505,57 @@ @end table Default value is @samp{complex}. -@item deint -Specify which frames to deinterlace. Accept one of the following values: - -@table @samp -@item all -Deinterlace all frames, -@item interlaced -Only deinterlace frames marked as interlaced. -@end table +@item mode +The interlacing mode to adopt. It accepts one of the following values: -Default value is @samp{all}. +@table @option +@item frame +Output one frame for each frame. +@item field +Output one frame for each field. @end table -@section waveform -Video waveform monitor. +The default value is @code{field}. -The waveform monitor plots color component intensity. By default luminance -only. Each column of the waveform corresponds to a column of pixels in the -source video. +@item parity +The picture field parity assumed for the input interlaced video. It accepts one +of the following values: + +@table @option +@item tff +Assume the top field is first. +@item bff +Assume the bottom field is first. +@item auto +Enable automatic detection of field parity. +@end table + +The default value is @code{auto}. +If the interlacing is unknown or the decoder does not export this information, +top field first will be assumed. + +@item deint +Specify which frames to deinterlace. Accepts one of the following values: + +@table @samp +@item all +Deinterlace all frames, +@item interlaced +Only deinterlace frames marked as interlaced. +@end table + +Default value is @samp{all}. +@end table + +@subsection Commands +This filter supports same @ref{commands} as options. + +@section waveform +Video waveform monitor. + +The waveform monitor plots color component intensity. By default luminance +only. Each column of the waveform corresponds to a column of pixels in the +source video. It accepts the following options: @@ -18538,6 +21643,9 @@ @item xflat Similar as above, but use different colors. +@item yflat +Similar as above, but again with different colors. + @item chroma Displays only chroma. @@ -18560,6 +21668,9 @@ @item orange Display orange graticule showing legal broadcast ranges. + +@item invert +Display invert graticule showing legal broadcast ranges. @end table @item opacity, o @@ -18588,6 +21699,12 @@ @item bgopacity, b Set background opacity. + +@item tint0, t0 +@item tint1, t1 +Set tint for output. +Only used with lowpass filter and when display is not overlay and input +pixel formats are not RGB. @end table @section weave, doubleweave @@ -18638,10 +21755,130 @@ Default is @code{3}. @end table +@section xfade + +Apply cross fade from one input video stream to another input video stream. +The cross fade is applied for specified duration. + +The filter accepts the following options: + +@table @option +@item transition +Set one of available transition effects: + +@table @samp +@item custom +@item fade +@item wipeleft +@item wiperight +@item wipeup +@item wipedown +@item slideleft +@item slideright +@item slideup +@item slidedown +@item circlecrop +@item rectcrop +@item distance +@item fadeblack +@item fadewhite +@item radial +@item smoothleft +@item smoothright +@item smoothup +@item smoothdown +@item circleopen +@item circleclose +@item vertopen +@item vertclose +@item horzopen +@item horzclose +@item dissolve +@item pixelize +@item diagtl +@item diagtr +@item diagbl +@item diagbr +@item hlslice +@item hrslice +@item vuslice +@item vdslice +@item hblur +@item fadegrays +@item wipetl +@item wipetr +@item wipebl +@item wipebr +@item squeezeh +@item squeezev +@end table +Default transition effect is fade. + +@item duration +Set cross fade duration in seconds. +Default duration is 1 second. + +@item offset +Set cross fade start relative to first input stream in seconds. +Default offset is 0. + +@item expr +Set expression for custom transition effect. + +The expressions can use the following variables and functions: + +@table @option +@item X +@item Y +The coordinates of the current sample. + +@item W +@item H +The width and height of the image. + +@item P +Progress of transition effect. + +@item PLANE +Currently processed plane. + +@item A +Return value of first input at current location and plane. + +@item B +Return value of second input at current location and plane. + +@item a0(x, y) +@item a1(x, y) +@item a2(x, y) +@item a3(x, y) +Return the value of the pixel at location (@var{x},@var{y}) of the +first/second/third/fourth component of first input. + +@item b0(x, y) +@item b1(x, y) +@item b2(x, y) +@item b3(x, y) +Return the value of the pixel at location (@var{x},@var{y}) of the +first/second/third/fourth component of second input. +@end table +@end table + +@subsection Examples + +@itemize +@item +Cross fade from one input video to another input video, with fade transition and duration of transition +of 2 seconds starting at offset of 5 seconds: +@example +ffmpeg -i first.mp4 -i second.mp4 -filter_complex xfade=transition=fade:duration=2:offset=5 output.mp4 +@end example +@end itemize + @section xmedian Pick median pixels from several input videos. -The filter accept the following options: +The filter accepts the following options: @table @option @item inputs @@ -18651,14 +21888,23 @@ @item planes Set which planes to filter. Default value is @code{15}, by which all planes are processed. + +@item percentile +Set median percentile. Default value is @code{0.5}. +Default value of @code{0.5} will pick always median values, while @code{0} will pick +minimum values, and @code{1} maximum values. @end table +@subsection Commands + +This filter supports all above options as @ref{commands}, excluding option @code{inputs}. + @section xstack Stack video inputs into custom layout. All streams must be of same pixel format. -The filter accept the following option: +The filter accepts the following options: @table @option @item inputs @@ -18675,40 +21921,92 @@ Multiple values can be used when separated by '+'. In such case values are summed together. +Note that if inputs are of different sizes gaps may appear, as not all of +the output video frame will be filled. Similarly, videos can overlap each +other if their position doesn't leave enough space for the full frame of +adjoining videos. + For 2 inputs, a default layout of @code{0_0|w0_0} is set. In all other cases, a layout must be set by the user. @item shortest If set to 1, force the output to terminate when the shortest input terminates. Default value is 0. + +@item fill +If set to valid color, all unused pixels will be filled with that color. +By default fill is set to none, so it is disabled. @end table @subsection Examples @itemize @item -Display 4 inputs into 2x2 grid, -note that if inputs are of different sizes unused gaps might appear, -as not all of output video is used. +Display 4 inputs into 2x2 grid. + +Layout: +@example +input1(0, 0) | input3(w0, 0) +input2(0, h0) | input4(w0, h0) +@end example + @example xstack=inputs=4:layout=0_0|0_h0|w0_0|w0_h0 @end example +Note that if inputs are of different sizes, gaps or overlaps may occur. + @item -Display 4 inputs into 1x4 grid, -note that if inputs are of different sizes unused gaps might appear, -as not all of output video is used. +Display 4 inputs into 1x4 grid. + +Layout: +@example +input1(0, 0) +input2(0, h0) +input3(0, h0+h1) +input4(0, h0+h1+h2) +@end example + @example xstack=inputs=4:layout=0_0|0_h0|0_h0+h1|0_h0+h1+h2 @end example +Note that if inputs are of different widths, unused space will appear. + +@item +Display 9 inputs into 3x3 grid. + +Layout: +@example +input1(0, 0) | input4(w0, 0) | input7(w0+w3, 0) +input2(0, h0) | input5(w0, h0) | input8(w0+w3, h0) +input3(0, h0+h1) | input6(w0, h0+h1) | input9(w0+w3, h0+h1) +@end example + +@example +xstack=inputs=9:layout=0_0|0_h0|0_h0+h1|w0_0|w0_h0|w0_h0+h1|w0+w3_0|w0+w3_h0|w0+w3_h0+h1 +@end example + +Note that if inputs are of different sizes, gaps or overlaps may occur. + @item -Display 9 inputs into 3x3 grid, -note that if inputs are of different sizes unused gaps might appear, -as not all of output video is used. +Display 16 inputs into 4x4 grid. + +Layout: @example -xstack=inputs=9:layout=w3_0|w3_h0+h2|w3_h0|0_h4|0_0|w3+w1_0|0_h1+h2|w3+w1_h0|w3+w1_h1+h2 +input1(0, 0) | input5(w0, 0) | input9 (w0+w4, 0) | input13(w0+w4+w8, 0) +input2(0, h0) | input6(w0, h0) | input10(w0+w4, h0) | input14(w0+w4+w8, h0) +input3(0, h0+h1) | input7(w0, h0+h1) | input11(w0+w4, h0+h1) | input15(w0+w4+w8, h0+h1) +input4(0, h0+h1+h2)| input8(w0, h0+h1+h2)| input12(w0+w4, h0+h1+h2)| input16(w0+w4+w8, h0+h1+h2) @end example + +@example +xstack=inputs=16:layout=0_0|0_h0|0_h0+h1|0_h0+h1+h2|w0_0|w0_h0|w0_h0+h1|w0_h0+h1+h2|w0+w4_0| +w0+w4_h0|w0+w4_h0+h1|w0+w4_h0+h1+h2|w0+w4+w8_0|w0+w4+w8_h0|w0+w4+w8_h0+h1|w0+w4+w8_h0+h1+h2 +@end example + +Note that if inputs are of different sizes, gaps or overlaps may occur. + @end itemize @anchor{yadif} @@ -18756,7 +22054,7 @@ top field first will be assumed. @item deint -Specify which frames to deinterlace. Accept one of the following +Specify which frames to deinterlace. Accepts one of the following values: @table @option @@ -18814,7 +22112,7 @@ top field first will be assumed. @item deint -Specify which frames to deinterlace. Accept one of the following +Specify which frames to deinterlace. Accepts one of the following values: @table @option @@ -18827,6 +22125,28 @@ The default value is @code{all}. @end table +@section yaepblur + +Apply blur filter while preserving edges ("yaepblur" means "yet another edge preserving blur filter"). +The algorithm is described in +"J. S. Lee, Digital image enhancement and noise filtering by use of local statistics, IEEE Trans. Pattern Anal. Mach. Intell. PAMI-2, 1980." + +It accepts the following parameters: + +@table @option +@item radius, r +Set the window radius. Default value is 3. + +@item planes, p +Set which planes to filter. Default is only the first plane. + +@item sigma, s +Set blur strength. Default value is 128. +@end table + +@subsection Commands +This filter supports same @ref{commands} as options. + @section zoompan Apply Zoom & Pan effect. @@ -18844,7 +22164,7 @@ @item d Set the duration expression in number of frames. This sets for how many number of frames effect will last for -single input image. +single input image. Default is 90. @item s Set the output image size, default is 'hd720'. @@ -18874,6 +22194,12 @@ @item on Output frame count. +@item in_time, it +The input timestamp expressed in seconds. It's NAN if the input timestamp is unknown. + +@item out_time, time, ot +The output timestamp expressed in seconds. + @item x @item y Last calculated 'x' and 'y' position from 'x' and 'y' expression @@ -18912,13 +22238,13 @@ @itemize @item -Zoom-in up to 1.5 and pan at same time to some spot near center of picture: +Zoom in up to 1.5x and pan at same time to some spot near center of picture: @example zoompan=z='min(zoom+0.0015,1.5)':d=700:x='if(gte(zoom,1.5),x,x+1/a)':y='if(gte(zoom,1.5),y,y+1)':s=640x360 @end example @item -Zoom-in up to 1.5 and pan always at center of picture: +Zoom in up to 1.5x and pan always at center of picture: @example zoompan=z='min(zoom+0.0015,1.5)':d=700:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)' @end example @@ -18928,6 +22254,13 @@ @example zoompan=z='min(max(zoom,pzoom)+0.0015,1.5)':d=1:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)' @end example + +@item +Zoom in 2x into center of picture only for the first second of the input video: +@example +zoompan=z='if(between(in_time,0,1),2,1)':d=1:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)' +@end example + @end itemize @anchor{zscale} @@ -19149,6 +22482,13 @@ @item npl Set the nominal peak luminance. + +@item param_a +Parameter A for scaling filters. Parameter "b" for bicubic, and the number of +filter taps for lanczos. + +@item param_b +Parameter B for scaling filters. Parameter "c" for bicubic. @end table The values of the @option{w} and @option{h} options are expressions @@ -19191,7 +22531,17 @@ pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1. @end table +@subsection Commands + +This filter supports the following commands: @table @option +@item width, w +@item height, h +Set the output video dimension expression. +The command accepts the same syntax of the corresponding option. + +If the specified expression is not valid, it is kept at its current +value. @end table @c man end VIDEO FILTERS @@ -19346,6 +22696,39 @@ @end example @end itemize +@section colorkey_opencl +RGB colorspace color keying. + +The filter accepts the following options: + +@table @option +@item color +The color which will be replaced with transparency. + +@item similarity +Similarity percentage with the key color. + +0.01 matches only the exact key color, while 1.0 matches everything. + +@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. +@end table + +@subsection Examples + +@itemize +@item +Make every semi-green pixel in the input transparent with some slight blending: +@example +-i INPUT -vf "hwupload, colorkey_opencl=green:0.3:0.1, hwdownload" OUTPUT +@end example +@end itemize + @section convolution_opencl Apply convolution of 3x3, 5x5, 7x7 matrix. @@ -19419,11 +22802,11 @@ @end example @end itemize -@section dilation_opencl +@section erosion_opencl -Apply dilation effect to the video. +Apply erosion effect to the video. -This filter replaces the pixel by the local(3x3) maximum. +This filter replaces the pixel by the local(3x3) minimum. It accepts the following options: @@ -19452,17 +22835,86 @@ @itemize @item -Apply dilation filter with threshold0 set to 30, threshold1 set 40, threshold2 set to 50 and coordinates set to 231, setting each pixel of the output to the local maximum between pixels: 1, 2, 3, 6, 7, 8 of the 3x3 region centered on it in the input. If the difference between input pixel and local maximum is more then threshold of the corresponding plane, output pixel will be set to input pixel + threshold of corresponding plane. +Apply erosion filter with threshold0 set to 30, threshold1 set 40, threshold2 set to 50 and coordinates set to 231, setting each pixel of the output to the local minimum between pixels: 1, 2, 3, 6, 7, 8 of the 3x3 region centered on it in the input. If the difference between input pixel and local minimum is more then threshold of the corresponding plane, output pixel will be set to input pixel - threshold of corresponding plane. @example --i INPUT -vf "hwupload, dilation_opencl=30:40:50:coordinates=231, hwdownload" OUTPUT +-i INPUT -vf "hwupload, erosion_opencl=30:40:50:coordinates=231, hwdownload" OUTPUT @end example @end itemize -@section erosion_opencl +@section deshake_opencl +Feature-point based video stabilization filter. -Apply erosion effect to the video. +The filter accepts the following options: -This filter replaces the pixel by the local(3x3) minimum. +@table @option +@item tripod +Simulates a tripod by preventing any camera movement whatsoever from the original frame. Defaults to @code{0}. + +@item debug +Whether or not additional debug info should be displayed, both in the processed output and in the console. + +Note that in order to see console debug output you will also need to pass @code{-v verbose} to ffmpeg. + +Viewing point matches in the output video is only supported for RGB input. + +Defaults to @code{0}. + +@item adaptive_crop +Whether or not to do a tiny bit of cropping at the borders to cut down on the amount of mirrored pixels. + +Defaults to @code{1}. + +@item refine_features +Whether or not feature points should be refined at a sub-pixel level. + +This can be turned off for a slight performance gain at the cost of precision. + +Defaults to @code{1}. + +@item smooth_strength +The strength of the smoothing applied to the camera path from @code{0.0} to @code{1.0}. + +@code{1.0} is the maximum smoothing strength while values less than that result in less smoothing. + +@code{0.0} causes the filter to adaptively choose a smoothing strength on a per-frame basis. + +Defaults to @code{0.0}. + +@item smooth_window_multiplier +Controls the size of the smoothing window (the number of frames buffered to determine motion information from). + +The size of the smoothing window is determined by multiplying the framerate of the video by this number. + +Acceptable values range from @code{0.1} to @code{10.0}. + +Larger values increase the amount of motion data available for determining how to smooth the camera path, +potentially improving smoothness, but also increase latency and memory usage. + +Defaults to @code{2.0}. + +@end table + +@subsection Examples + +@itemize +@item +Stabilize a video with a fixed, medium smoothing strength: +@example +-i INPUT -vf "hwupload, deshake_opencl=smooth_strength=0.5, hwdownload" OUTPUT +@end example + +@item +Stabilize a video with debugging (both in console and in rendered video): +@example +-i INPUT -filter_complex "[0:v]format=rgba, hwupload, deshake_opencl=debug=1, hwdownload, format=rgba, format=yuv420p" -v verbose OUTPUT +@end example +@end itemize + +@section dilation_opencl + +Apply dilation effect to the video. + +This filter replaces the pixel by the local(3x3) maximum. It accepts the following options: @@ -19491,55 +22943,22 @@ @itemize @item -Apply erosion filter with threshold0 set to 30, threshold1 set 40, threshold2 set to 50 and coordinates set to 231, setting each pixel of the output to the local minimum between pixels: 1, 2, 3, 6, 7, 8 of the 3x3 region centered on it in the input. If the difference between input pixel and local minimum is more then threshold of the corresponding plane, output pixel will be set to input pixel - threshold of corresponding plane. +Apply dilation filter with threshold0 set to 30, threshold1 set 40, threshold2 set to 50 and coordinates set to 231, setting each pixel of the output to the local maximum between pixels: 1, 2, 3, 6, 7, 8 of the 3x3 region centered on it in the input. If the difference between input pixel and local maximum is more then threshold of the corresponding plane, output pixel will be set to input pixel + threshold of corresponding plane. @example --i INPUT -vf "hwupload, erosion_opencl=30:40:50:coordinates=231, hwdownload" OUTPUT +-i INPUT -vf "hwupload, dilation_opencl=30:40:50:coordinates=231, hwdownload" OUTPUT @end example @end itemize -@section colorkey_opencl -RGB colorspace color keying. +@section nlmeans_opencl -The filter accepts the following options: +Non-local Means denoise filter through OpenCL, this filter accepts same options as @ref{nlmeans}. -@table @option -@item color -The color which will be replaced with transparency. +@section overlay_opencl -@item similarity -Similarity percentage with the key color. +Overlay one video on top of another. -0.01 matches only the exact key color, while 1.0 matches everything. - -@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. -@end table - -@subsection Examples - -@itemize -@item -Make every semi-green pixel in the input transparent with some slight blending: -@example --i INPUT -vf "hwupload, colorkey_opencl=green:0.3:0.1, hwdownload" OUTPUT -@end example -@end itemize - -@section nlmeans_opencl - -Non-local Means denoise filter through OpenCL, this filter accepts same options as @ref{nlmeans}. - -@section overlay_opencl - -Overlay one video on top of another. - -It takes two inputs and has one output. The first input is the "main" video on which the second input is overlaid. -This filter requires same memory layout for all the inputs. So, format conversion may be needed. +It takes two inputs and has one output. The first input is the "main" video on which the second input is overlaid. +This filter requires same memory layout for all the inputs. So, format conversion may be needed. The filter accepts the following options: @@ -19550,7 +22969,7 @@ Default value is @code{0}. @item y -Set the x coordinate of the overlaid video on the main video. +Set the y coordinate of the overlaid video on the main video. Default value is @code{0}. @end table @@ -19571,6 +22990,83 @@ @end itemize +@section pad_opencl + +Add paddings to the input image, and place the original input at the +provided @var{x}, @var{y} coordinates. + +It accepts the following options: + +@table @option +@item width, w +@item height, h +Specify an expression for the size of the output image with the +paddings added. If the value for @var{width} or @var{height} is 0, the +corresponding input size is used for the output. + +The @var{width} expression can reference the value set by the +@var{height} expression, and vice versa. + +The default value of @var{width} and @var{height} is 0. + +@item x +@item y +Specify the offsets to place the input image at within the padded area, +with respect to the top/left border of the output image. + +The @var{x} expression can reference the value set by the @var{y} +expression, and vice versa. + +The default value of @var{x} and @var{y} is 0. + +If @var{x} or @var{y} evaluate to a negative number, they'll be changed +so the input image is centered on the padded area. + +@item color +Specify the color of the padded area. For the syntax of this option, +check the @ref{color syntax,,"Color" section in the ffmpeg-utils +manual,ffmpeg-utils}. + +@item aspect +Pad to an aspect instead to a resolution. +@end table + +The value for the @var{width}, @var{height}, @var{x}, and @var{y} +options are expressions containing the following constants: + +@table @option +@item in_w +@item in_h +The input video 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 width and height (the size of the padded area), as +specified by the @var{width} and @var{height} expressions. + +@item ow +@item oh +These are the same as @var{out_w} and @var{out_h}. + +@item x +@item y +The x and y offsets as specified by the @var{x} and @var{y} +expressions, or NAN if not yet specified. + +@item a +same as @var{iw} / @var{ih} + +@item sar +input sample aspect ratio + +@item dar +input display aspect ratio, it is the same as (@var{iw} / @var{ih}) * @var{sar} +@end table + @section prewitt_opencl Apply the Prewitt operator (@url{https://en.wikipedia.org/wiki/Prewitt_operator}) to input video stream. @@ -19600,6 +23096,138 @@ @end example @end itemize +@anchor{program_opencl} +@section program_opencl + +Filter video using an OpenCL program. + +@table @option + +@item source +OpenCL program source file. + +@item kernel +Kernel name in program. + +@item inputs +Number of inputs to the filter. Defaults to 1. + +@item size, s +Size of output frames. Defaults to the same as the first input. + +@end table + +The @code{program_opencl} filter also supports the @ref{framesync} options. + +The program source file must contain a kernel function with the given name, +which will be run once for each plane of the output. Each run on a plane +gets enqueued as a separate 2D global NDRange with one work-item for each +pixel to be generated. The global ID offset for each work-item is therefore +the coordinates of a pixel in the destination image. + +The kernel function needs to take the following arguments: +@itemize +@item +Destination image, @var{__write_only image2d_t}. + +This image will become the output; the kernel should write all of it. +@item +Frame index, @var{unsigned int}. + +This is a counter starting from zero and increasing by one for each frame. +@item +Source images, @var{__read_only image2d_t}. + +These are the most recent images on each input. The kernel may read from +them to generate the output, but they can't be written to. +@end itemize + +Example programs: + +@itemize +@item +Copy the input to the output (output must be the same size as the input). +@verbatim +__kernel void copy(__write_only image2d_t destination, + unsigned int index, + __read_only image2d_t source) +{ + const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE; + + int2 location = (int2)(get_global_id(0), get_global_id(1)); + + float4 value = read_imagef(source, sampler, location); + + write_imagef(destination, location, value); +} +@end verbatim + +@item +Apply a simple transformation, rotating the input by an amount increasing +with the index counter. Pixel values are linearly interpolated by the +sampler, and the output need not have the same dimensions as the input. +@verbatim +__kernel void rotate_image(__write_only image2d_t dst, + unsigned int index, + __read_only image2d_t src) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_LINEAR); + + float angle = (float)index / 100.0f; + + float2 dst_dim = convert_float2(get_image_dim(dst)); + float2 src_dim = convert_float2(get_image_dim(src)); + + float2 dst_cen = dst_dim / 2.0f; + float2 src_cen = src_dim / 2.0f; + + int2 dst_loc = (int2)(get_global_id(0), get_global_id(1)); + + float2 dst_pos = convert_float2(dst_loc) - dst_cen; + float2 src_pos = { + cos(angle) * dst_pos.x - sin(angle) * dst_pos.y, + sin(angle) * dst_pos.x + cos(angle) * dst_pos.y + }; + src_pos = src_pos * src_dim / dst_dim; + + float2 src_loc = src_pos + src_cen; + + if (src_loc.x < 0.0f || src_loc.y < 0.0f || + src_loc.x > src_dim.x || src_loc.y > src_dim.y) + write_imagef(dst, dst_loc, 0.5f); + else + write_imagef(dst, dst_loc, read_imagef(src, sampler, src_loc)); +} +@end verbatim + +@item +Blend two inputs together, with the amount of each input used varying +with the index counter. +@verbatim +__kernel void blend_images(__write_only image2d_t dst, + unsigned int index, + __read_only image2d_t src1, + __read_only image2d_t src2) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_LINEAR); + + float blend = (cos((float)index / 50.0f) + 1.0f) / 2.0f; + + int2 dst_loc = (int2)(get_global_id(0), get_global_id(1)); + int2 src1_loc = dst_loc * get_image_dim(src1) / get_image_dim(dst); + int2 src2_loc = dst_loc * get_image_dim(src2) / get_image_dim(dst); + + float4 val1 = read_imagef(src1, sampler, src1_loc); + float4 val2 = read_imagef(src2, sampler, src2_loc); + + write_imagef(dst, dst_loc, val1 * blend + val2 * (1.0f - blend)); +} +@end verbatim + +@end itemize + @section roberts_opencl Apply the Roberts cross operator (@url{https://en.wikipedia.org/wiki/Roberts_cross}) to input video stream. @@ -19778,39 +23406,195 @@ Set the chroma matrix horizontal size. Range is @code{[1, 23]} and default value is @code{5}. -@item chroma_msize_y, cy -Set the chroma matrix vertical size. -Range is @code{[1, 23]} and default value is @code{5}. +@item chroma_msize_y, cy +Set the chroma matrix vertical size. +Range is @code{[1, 23]} and default value is @code{5}. + +@item chroma_amount, ca +Set the chroma effect strength. +Range is @code{[-10, 10]} and default value is @code{0.0}. + +Negative values will blur the input video, while positive values will +sharpen it, a value of zero will disable the effect. + +@end table + +All parameters are optional and default to the equivalent of the +string '5:5:1.0:5:5:0.0'. + +@subsection Examples + +@itemize +@item +Apply strong luma sharpen effect: +@example +-i INPUT -vf "hwupload, unsharp_opencl=luma_msize_x=7:luma_msize_y=7:luma_amount=2.5, hwdownload" OUTPUT +@end example + +@item +Apply a strong blur of both luma and chroma parameters: +@example +-i INPUT -vf "hwupload, unsharp_opencl=7:7:-2:7:7:-2, hwdownload" OUTPUT +@end example +@end itemize + +@section xfade_opencl + +Cross fade two videos with custom transition effect by using OpenCL. + +It accepts the following options: + +@table @option +@item transition +Set one of possible transition effects. + +@table @option +@item custom +Select custom transition effect, the actual transition description +will be picked from source and kernel options. + +@item fade +@item wipeleft +@item wiperight +@item wipeup +@item wipedown +@item slideleft +@item slideright +@item slideup +@item slidedown + +Default transition is fade. +@end table + +@item source +OpenCL program source file for custom transition. + +@item kernel +Set name of kernel to use for custom transition from program source file. + +@item duration +Set duration of video transition. + +@item offset +Set time of start of transition relative to first video. +@end table + +The program source file must contain a kernel function with the given name, +which will be run once for each plane of the output. Each run on a plane +gets enqueued as a separate 2D global NDRange with one work-item for each +pixel to be generated. The global ID offset for each work-item is therefore +the coordinates of a pixel in the destination image. + +The kernel function needs to take the following arguments: +@itemize +@item +Destination image, @var{__write_only image2d_t}. + +This image will become the output; the kernel should write all of it. + +@item +First Source image, @var{__read_only image2d_t}. +Second Source image, @var{__read_only image2d_t}. + +These are the most recent images on each input. The kernel may read from +them to generate the output, but they can't be written to. + +@item +Transition progress, @var{float}. This value is always between 0 and 1 inclusive. +@end itemize + +Example programs: + +@itemize +@item +Apply dots curtain transition effect: +@verbatim +__kernel void blend_images(__write_only image2d_t dst, + __read_only image2d_t src1, + __read_only image2d_t src2, + float progress) +{ + const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_LINEAR); + int2 p = (int2)(get_global_id(0), get_global_id(1)); + float2 rp = (float2)(get_global_id(0), get_global_id(1)); + float2 dim = (float2)(get_image_dim(src1).x, get_image_dim(src1).y); + rp = rp / dim; + + float2 dots = (float2)(20.0, 20.0); + float2 center = (float2)(0,0); + float2 unused; + + float4 val1 = read_imagef(src1, sampler, p); + float4 val2 = read_imagef(src2, sampler, p); + bool next = distance(fract(rp * dots, &unused), (float2)(0.5, 0.5)) < (progress / distance(rp, center)); + + write_imagef(dst, p, next ? val1 : val2); +} +@end verbatim + +@end itemize + +@c man end OPENCL VIDEO FILTERS + +@chapter VAAPI Video Filters +@c man begin VAAPI VIDEO FILTERS + +VAAPI Video filters are usually used with VAAPI decoder and VAAPI encoder. Below is a description of VAAPI video filters. + +To enable compilation of these filters you need to configure FFmpeg with +@code{--enable-vaapi}. + +To use vaapi filters, you need to setup the vaapi device correctly. For more information, please read @url{https://trac.ffmpeg.org/wiki/Hardware/VAAPI} + +@section tonemap_vaapi + +Perform HDR(High Dynamic Range) to SDR(Standard Dynamic Range) conversion with tone-mapping. +It maps the dynamic range of HDR10 content to the SDR content. +It currently only accepts HDR10 as input. + +It accepts the following parameters: + +@table @option +@item format +Specify the output pixel format. + +Currently supported formats are: +@table @var +@item p010 +@item nv12 +@end table + +Default is nv12. + +@item primaries, p +Set the output color primaries. + +Default is same as input. + +@item transfer, t +Set the output transfer characteristics. + +Default is bt709. -@item chroma_amount, ca -Set the chroma effect strength. -Range is @code{[-10, 10]} and default value is @code{0.0}. +@item matrix, m +Set the output colorspace matrix. -Negative values will blur the input video, while positive values will -sharpen it, a value of zero will disable the effect. +Default is same as input. @end table -All parameters are optional and default to the equivalent of the -string '5:5:1.0:5:5:0.0'. - -@subsection Examples +@subsection Example @itemize @item -Apply strong luma sharpen effect: -@example --i INPUT -vf "hwupload, unsharp_opencl=luma_msize_x=7:luma_msize_y=7:luma_amount=2.5, hwdownload" OUTPUT -@end example - -@item -Apply a strong blur of both luma and chroma parameters: +Convert HDR(HDR10) video to bt2020-transfer-characteristic p010 format @example --i INPUT -vf "hwupload, unsharp_opencl=7:7:-2:7:7:-2, hwdownload" OUTPUT +tonemap_vaapi=format=p010:t=bt2020-10 @end example @end itemize -@c man end OPENCL VIDEO FILTERS +@c man end VAAPI VIDEO FILTERS @chapter Video Sources @c man begin VIDEO SOURCES @@ -19822,7 +23606,7 @@ Buffer video frames, and make them available to the filter chain. This source is mainly intended for a programmatic use, in particular -through the interface defined in @file{libavfilter/vsrc_buffer.h}. +through the interface defined in @file{libavfilter/buffersrc.h}. It accepts the following parameters: @@ -19854,9 +23638,9 @@ The sample (pixel) aspect ratio of the input video. @item sws_param -Specify the optional parameters to be used for the scale filter which -is automatically inserted when an input change is detected in the -input size or format. +This option is deprecated and ignored. Prepend @code{sws_flags=@var{flags};} +to the filtergraph description to specify swscale flags for automatically +inserted scalers. See @ref{Filtergraph syntax}. @item hw_frames_ctx When using a hardware pixel format, this should be a reference to an @@ -19881,7 +23665,7 @@ Alternatively, the options can be specified as a flat string, but this syntax is deprecated: -@var{width}:@var{height}:@var{pix_fmt}:@var{time_base.num}:@var{time_base.den}:@var{pixel_aspect.num}:@var{pixel_aspect.den}[:@var{sws_param}] +@var{width}:@var{height}:@var{pix_fmt}:@var{time_base.num}:@var{time_base.den}:@var{pixel_aspect.num}:@var{pixel_aspect.den} @section cellauto @@ -20058,6 +23842,44 @@ @end itemize +@section gradients +Generate several gradients. + +@table @option +@item size, s +Set frame size. For the syntax of this option, check the @ref{video size syntax,,"Video +size" section in the ffmpeg-utils manual,ffmpeg-utils}. Default value is "640x480". + +@item rate, r +Set frame rate, expressed as number of frames per second. Default +value is "25". + +@item c0, c1, c2, c3, c4, c5, c6, c7 +Set 8 colors. Default values for colors is to pick random one. + +@item x0, y0, y0, y1 +Set gradient line source and destination points. If negative or out of range, random ones +are picked. + +@item nb_colors, n +Set number of colors to use at once. Allowed range is from 2 to 8. Default value is 2. + +@item seed +Set seed for picking gradient line points. + +@item duration, d +Set the duration of the sourced video. See +@ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils} +for the accepted syntax. + +If not specified, or the expressed duration is negative, the video is +supposed to be generated forever. + +@item speed +Set speed of gradients rotation. +@end table + + @section mandelbrot Generate a Mandelbrot set fractal, and progressively zoom towards the @@ -20172,6 +23994,9 @@ @item ring2 @item all +@item max_frames, m +Set the maximum number of frames generated for each test, default value is 30. + @end table Default value is "all", which will cycle through the list of all tests. @@ -20441,6 +24266,10 @@ If not specified, or the expressed duration is negative, the video is supposed to be generated forever. +Since the frame rate is used as time base, all frames including the last one +will have their full duration. If the specified duration is not a multiple +of the frame duration, it will be rounded up. + @item sar Set the sample aspect ratio of the sourced video. @@ -20567,6 +24396,31 @@ @end itemize +@section sierpinski + +Generate a Sierpinski carpet/triangle fractal, and randomly pan around. + +This source accepts the following options: + +@table @option +@item size, s +Set frame size. For the syntax of this option, check the @ref{video size syntax,,"Video +size" section in the ffmpeg-utils manual,ffmpeg-utils}. Default value is "640x480". + +@item rate, r +Set frame rate, expressed as number of frames per second. Default +value is "25". + +@item seed +Set seed which is used for random panning. + +@item jump +Set max jump for single pan destination. Allowed range is from 1 to 10000. + +@item type +Set fractal type, can be default @code{carpet} or @code{triangle}. +@end table + @c man end VIDEO SOURCES @chapter Video Sinks @@ -20622,6 +24476,15 @@ by white color. @end table +@section adrawgraph +Draw a graph using input audio metadata. + +See @ref{drawgraph} + +@section agraphmonitor + +See @ref{graphmonitor}. + @section ahistogram Convert input audio to a video output, displaying the volume histogram. @@ -20736,13 +24599,46 @@ Enable video output. Default is enabled. @end table +@subsection phasing detection + +The filter also detects out of phase and mono sequences in stereo streams. +It logs the sequence start, end and duration when it lasts longer or as long as the minimum set. + +The filter accepts the following options for this detection: + +@table @option +@item phasing +Enable mono and out of phase detection. Default is disabled. + +@item tolerance, t +Set phase tolerance for mono detection, in amplitude ratio. Default is @code{0}. +Allowed range is @code{[0, 1]}. + +@item angle, a +Set angle threshold for out of phase detection, in degree. Default is @code{170}. +Allowed range is @code{[90, 180]}. + +@item duration, d +Set mono or out of phase duration until notification, expressed in seconds. Default is @code{2}. +@end table + +@subsection Examples + +@itemize +@item +Complete example with @command{ffmpeg} to detect 1 second of mono with 0.001 phase tolerance: +@example +ffmpeg -i stereo.wav -af aphasemeter=video=0:phasing=1:duration=1:tolerance=0.001 -f null - +@end example +@end itemize + @section avectorscope Convert input audio to a video output, representing the audio vector scope. The filter is used to measure the difference between channels of stereo -audio stream. A monoaural signal, consisting of identical left and right +audio stream. A monaural signal, consisting of identical left and right signal, results in straight vertical line. Any stereo separation is visible as a deviation from this line, creating a Lissajous figure. If the straight (or deviation from it) but horizontal line appears this @@ -20983,111 +24879,6 @@ Close the current segment and step to the next one @end table -@section drawgraph, adrawgraph - -Draw a graph using input video or audio metadata. - -It accepts the following parameters: - -@table @option -@item m1 -Set 1st frame metadata key from which metadata values will be used to draw a graph. - -@item fg1 -Set 1st foreground color expression. - -@item m2 -Set 2nd frame metadata key from which metadata values will be used to draw a graph. - -@item fg2 -Set 2nd foreground color expression. - -@item m3 -Set 3rd frame metadata key from which metadata values will be used to draw a graph. - -@item fg3 -Set 3rd foreground color expression. - -@item m4 -Set 4th frame metadata key from which metadata values will be used to draw a graph. - -@item fg4 -Set 4th foreground color expression. - -@item min -Set minimal value of metadata value. - -@item max -Set maximal value of metadata value. - -@item bg -Set graph background color. Default is white. - -@item mode -Set graph mode. - -Available values for mode is: -@table @samp -@item bar -@item dot -@item line -@end table - -Default is @code{line}. - -@item slide -Set slide mode. - -Available values for slide is: -@table @samp -@item frame -Draw new frame when right border is reached. - -@item replace -Replace old columns with new ones. - -@item scroll -Scroll from right to left. - -@item rscroll -Scroll from left to right. - -@item picture -Draw single picture. -@end table - -Default is @code{frame}. - -@item size -Set size of graph video. For the syntax of this option, check the -@ref{video size syntax,,"Video size" section in the ffmpeg-utils manual,ffmpeg-utils}. -The default value is @code{900x256}. - -The foreground color expressions can use the following variables: -@table @option -@item MIN -Minimal value of metadata value. - -@item MAX -Maximal value of metadata value. - -@item VAL -Current metadata key value. -@end table - -The color is defined as 0xAABBGGRR. -@end table - -Example using metadata from @ref{signalstats} filter: -@example -signalstats,drawgraph=lavfi.signalstats.YAVG:min=0:max=255 -@end example - -Example using metadata from @ref{ebur128} filter: -@example -ebur128=metadata=1,adrawgraph=lavfi.r128.M:min=-120:max=5 -@end example - @anchor{ebur128} @section ebur128 @@ -21252,6 +25043,21 @@ @table @option @item nb_inputs, n Set the number of different inputs, it is 2 by default. + +@item duration +How to determine the end-of-stream. + +@table @option +@item longest +The duration of the longest input. (default) + +@item shortest +The duration of the shortest input. + +@item first +The duration of the first input. +@end table + @end table @subsection Examples @@ -21337,6 +25143,10 @@ @item expr Values are interpreted as floats, returns true if expression from option @code{expr} evaluates to true. + +@item ends_with +Values are interpreted as strings, returns true if metadata value ends with +the @code{value} option string. @end table @item expr @@ -21358,6 +25168,9 @@ for standard output. If @code{file} option is not set, output is written to the log with AV_LOG_INFO loglevel. +@item direct +Reduces buffering in print mode when output is written to a URL set using @var{file}. + @end table @subsection Examples @@ -21725,6 +25538,38 @@ specified interval. In other words, the command is sent when the previous frame timestamp was in the given interval, and the current is not. + +@item expr +The command @var{ARG} is interpreted as expression and result of +expression is passed as @var{ARG}. + +The expression is evaluated through the eval API and can contain the following +constants: + +@table @option +@item POS +Original position in the file of the frame, or undefined if undefined +for the current frame. + +@item PTS +The presentation timestamp in input. + +@item N +The count of the input frame for video or audio, starting from 0. + +@item T +The time in seconds of the current frame. + +@item TS +The start time in seconds of the current command interval. + +@item TE +The end time in seconds of the current command interval. + +@item TI +The interpolated time of the current command interval, TI = (T - TS) / (TE - TS). +@end table + @end table If @var{FLAGS} is not specified, a default value of @code{[enter]} is @@ -22148,8 +25993,9 @@ option instead. @item font -Specify fontconfig pattern. This has lower priority than @var{fontfile}. -The : in the pattern may be replaced by | to avoid unnecessary escaping. +Specify fontconfig pattern. This has lower priority than @var{fontfile}. The +@code{:} in the pattern may be replaced by @code{|} to avoid unnecessary +escaping. @item fontcolor Specify font color expression. This is arithmetic expression that should return @@ -22410,6 +26256,16 @@ @item minamp Set minimum amplitude used in @code{log} amplitude scaler. +@item data +Set data display mode. + +It accepts the following values: +@table @samp +@item magnitude +@item phase +@item delay +@end table +Default is @code{magnitude}. @end table @section showspatial @@ -23060,6 +26916,20 @@ @end table Default value is @code{scale}. + +@item filter +Set the filter mode. + +Available values are: +@table @samp +@item average +Use average samples values for each drawn sample. + +@item peak +Use peak samples values for each drawn sample. +@end table + +Default value is @code{average}. @end table @subsection Examples @@ -23105,7 +26975,7 @@ @section spectrumsynth -Sythesize audio from 2 input video spectrums, first input stream represents +Synthesize audio from 2 input video spectrums, first input stream represents magnitude across time and second represents phase across time. The filter will transform from frequency domain as displayed in videos back to time domain as presented in audio output. diff -Nru ffmpeg-4.2.2/doc/formats.texi ffmpeg-4.4/doc/formats.texi --- ffmpeg-4.2.2/doc/formats.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/formats.texi 2020-07-11 10:39:30.000000000 +0000 @@ -27,6 +27,10 @@ information in case it is dispersed into the stream, but will increase latency. Must be an integer not lesser than 32. It is 5000000 by default. +@item max_probe_packets @var{integer} (@emph{input}) +Set the maximum number of buffered packets when probing a codec. +Default is 2500 packets. + @item packetsize @var{integer} (@emph{output}) Set packet size. @@ -139,7 +143,7 @@ @item max_interleave_delta @var{integer} (@emph{output}) Set maximum buffering duration for interleaving. The duration is -expressed in microseconds, and defaults to 1000000 (1 second). +expressed in microseconds, and defaults to 10000000 (10 seconds). To ensure all the streams are interleaved correctly, libavformat will wait until it has at least one packet for each stream before actually diff -Nru ffmpeg-4.2.2/doc/general_contents.texi ffmpeg-4.4/doc/general_contents.texi --- ffmpeg-4.2.2/doc/general_contents.texi 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/doc/general_contents.texi 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,1440 @@ +@chapter External libraries + +FFmpeg can be hooked up with a number of external libraries to add support +for more formats. None of them are used by default, their use has to be +explicitly requested by passing the appropriate flags to +@command{./configure}. + +@section Alliance for Open Media (AOM) + +FFmpeg can make use of the AOM library for AV1 decoding and encoding. + +Go to @url{http://aomedia.org/} and follow the instructions for +installing the library. Then pass @code{--enable-libaom} to configure to +enable it. + +@section AMD AMF/VCE + +FFmpeg can use the AMD Advanced Media Framework library +for accelerated H.264 and HEVC(only windows) encoding on hardware with Video Coding Engine (VCE). + +To enable support you must obtain the AMF framework header files(version 1.4.9+) from +@url{https://github.com/GPUOpen-LibrariesAndSDKs/AMF.git}. + +Create an @code{AMF/} directory in the system include path. +Copy the contents of @code{AMF/amf/public/include/} into that directory. +Then configure FFmpeg with @code{--enable-amf}. + +Initialization of amf encoder occurs in this order: +1) trying to initialize through dx11(only windows) +2) trying to initialize through dx9(only windows) +3) trying to initialize through vulkan + +To use h.264(AMD VCE) encoder on linux amdgru-pro version 19.20+ and amf-amdgpu-pro +package(amdgru-pro contains, but does not install automatically) are required. + +This driver can be installed using amdgpu-pro-install script in official amd driver archive. + +@section AviSynth + +FFmpeg can read AviSynth scripts as input. To enable support, pass +@code{--enable-avisynth} to configure after installing the headers +provided by @url{https://github.com/AviSynth/AviSynthPlus, AviSynth+}. +AviSynth+ can be configured to install only the headers by either +passing @code{-DHEADERS_ONLY:bool=on} to the normal CMake-based build +system, or by using the supplied @code{GNUmakefile}. + +For Windows, supported AviSynth variants are +@url{http://avisynth.nl, AviSynth 2.6 RC1 or higher} for 32-bit builds and +@url{http://avisynth.nl/index.php/AviSynth+, AviSynth+ r1718 or higher} for 32-bit and 64-bit builds. + +For Linux, macOS, and BSD, the only supported AviSynth variant is +@url{https://github.com/AviSynth/AviSynthPlus, AviSynth+}, starting with version 3.5. + +@float NOTE +In 2016, AviSynth+ added support for building with GCC. However, due to +the eccentricities of Windows' calling conventions, 32-bit GCC builds +of AviSynth+ are not compatible with typical 32-bit builds of FFmpeg. + +By default, FFmpeg assumes compatibility with 32-bit MSVC builds of +AviSynth+ since that is the most widely-used and entrenched build +configuration. Users can override this and enable support for 32-bit +GCC builds of AviSynth+ by passing @code{-DAVSC_WIN32_GCC32} to +@code{--extra-cflags} when configuring FFmpeg. + +64-bit builds of FFmpeg are not affected, and can use either MSVC or +GCC builds of AviSynth+ without any special flags. +@end float + +@float NOTE +AviSynth(+) is loaded dynamically. Distributors can build FFmpeg +with @code{--enable-avisynth}, and the binaries will work regardless +of the end user having AviSynth installed. If/when an end user +would like to use AviSynth scripts, then they can install AviSynth(+) +and FFmpeg will be able to find and use it to open scripts. +@end float + +@section Chromaprint + +FFmpeg can make use of the Chromaprint library for generating audio fingerprints. +Pass @code{--enable-chromaprint} to configure to +enable it. See @url{https://acoustid.org/chromaprint}. + +@section codec2 + +FFmpeg can make use of the codec2 library for codec2 decoding and encoding. +There is currently no native decoder, so libcodec2 must be used for decoding. + +Go to @url{http://freedv.org/}, download "Codec 2 source archive". +Build and install using CMake. Debian users can install the libcodec2-dev package instead. +Once libcodec2 is installed you can pass @code{--enable-libcodec2} to configure to enable it. + +The easiest way to use codec2 is with .c2 files, since they contain the mode information required for decoding. +To encode such a file, use a .c2 file extension and give the libcodec2 encoder the -mode option: +@code{ffmpeg -i input.wav -mode 700C output.c2}. +Playback is as simple as @code{ffplay output.c2}. +For a list of supported modes, run @code{ffmpeg -h encoder=libcodec2}. +Raw codec2 files are also supported. +To make sense of them the mode in use needs to be specified as a format option: +@code{ffmpeg -f codec2raw -mode 1300 -i input.raw output.wav}. + +@section dav1d + +FFmpeg can make use of the dav1d library for AV1 video decoding. + +Go to @url{https://code.videolan.org/videolan/dav1d} and follow the instructions for +installing the library. Then pass @code{--enable-libdav1d} to configure to enable it. + +@section davs2 + +FFmpeg can make use of the davs2 library for AVS2-P2/IEEE1857.4 video decoding. + +Go to @url{https://github.com/pkuvcl/davs2} and follow the instructions for +installing the library. Then pass @code{--enable-libdavs2} to configure to +enable it. + +@float NOTE +libdavs2 is under the GNU Public License Version 2 or later +(see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for +details), you must upgrade FFmpeg's license to GPL in order to use it. +@end float + +@section uavs3d + +FFmpeg can make use of the uavs3d library for AVS3-P2/IEEE1857.10 video decoding. + +Go to @url{https://github.com/uavs3/uavs3d} and follow the instructions for +installing the library. Then pass @code{--enable-libuavs3d} to configure to +enable it. + +@section Game Music Emu + +FFmpeg can make use of the Game Music Emu library to read audio from supported video game +music file formats. Pass @code{--enable-libgme} to configure to +enable it. See @url{https://bitbucket.org/mpyne/game-music-emu/overview}. + +@section Intel QuickSync Video + +FFmpeg can use Intel QuickSync Video (QSV) for accelerated decoding and encoding +of multiple codecs. To use QSV, FFmpeg must be linked against the @code{libmfx} +dispatcher, which loads the actual decoding libraries. + +The dispatcher is open source and can be downloaded from +@url{https://github.com/lu-zero/mfx_dispatch.git}. FFmpeg needs to be configured +with the @code{--enable-libmfx} option and @code{pkg-config} needs to be able to +locate the dispatcher's @code{.pc} files. + +@section Kvazaar + +FFmpeg can make use of the Kvazaar library for HEVC encoding. + +Go to @url{https://github.com/ultravideo/kvazaar} and follow the +instructions for installing the library. Then pass +@code{--enable-libkvazaar} to configure to enable it. + +@section LAME + +FFmpeg can make use of the LAME library for MP3 encoding. + +Go to @url{http://lame.sourceforge.net/} and follow the +instructions for installing the library. +Then pass @code{--enable-libmp3lame} to configure to enable it. + +@section libilbc + +iLBC is a narrowband speech codec that has been made freely available +by Google as part of the WebRTC project. libilbc is a packaging friendly +copy of the iLBC codec. FFmpeg can make use of the libilbc library for +iLBC decoding and encoding. + +Go to @url{https://github.com/TimothyGu/libilbc} and follow the instructions for +installing the library. Then pass @code{--enable-libilbc} to configure to +enable it. + +@section libvpx + +FFmpeg can make use of the libvpx library for VP8/VP9 decoding and encoding. + +Go to @url{http://www.webmproject.org/} and follow the instructions for +installing the library. Then pass @code{--enable-libvpx} to configure to +enable it. + +@section ModPlug + +FFmpeg can make use of this library, originating in Modplug-XMMS, to read from MOD-like music files. +See @url{https://github.com/Konstanty/libmodplug}. Pass @code{--enable-libmodplug} to configure to +enable it. + +@section OpenCORE, VisualOn, and Fraunhofer libraries + +Spun off Google Android sources, OpenCore, VisualOn and Fraunhofer +libraries provide encoders for a number of audio codecs. + +@float NOTE +OpenCORE and VisualOn libraries are under the Apache License 2.0 +(see @url{http://www.apache.org/licenses/LICENSE-2.0} for details), which is +incompatible to the LGPL version 2.1 and GPL version 2. You have to +upgrade FFmpeg's license to LGPL version 3 (or if you have enabled +GPL components, GPL version 3) by passing @code{--enable-version3} to configure in +order to use it. + +The license of the Fraunhofer AAC library is incompatible with the GPL. +Therefore, for GPL builds, you have to pass @code{--enable-nonfree} to +configure in order to use it. To the best of our knowledge, it is +compatible with the LGPL. +@end float + +@subsection OpenCORE AMR + +FFmpeg can make use of the OpenCORE libraries for AMR-NB +decoding/encoding and AMR-WB decoding. + +Go to @url{http://sourceforge.net/projects/opencore-amr/} and follow the +instructions for installing the libraries. +Then pass @code{--enable-libopencore-amrnb} and/or +@code{--enable-libopencore-amrwb} to configure to enable them. + +@subsection VisualOn AMR-WB encoder library + +FFmpeg can make use of the VisualOn AMR-WBenc library for AMR-WB encoding. + +Go to @url{http://sourceforge.net/projects/opencore-amr/} and follow the +instructions for installing the library. +Then pass @code{--enable-libvo-amrwbenc} to configure to enable it. + +@subsection Fraunhofer AAC library + +FFmpeg can make use of the Fraunhofer AAC library for AAC decoding & encoding. + +Go to @url{http://sourceforge.net/projects/opencore-amr/} and follow the +instructions for installing the library. +Then pass @code{--enable-libfdk-aac} to configure to enable it. + +@section OpenH264 + +FFmpeg can make use of the OpenH264 library for H.264 decoding and encoding. + +Go to @url{http://www.openh264.org/} and follow the instructions for +installing the library. Then pass @code{--enable-libopenh264} to configure to +enable it. + +For decoding, this library is much more limited than the built-in decoder +in libavcodec; currently, this library lacks support for decoding B-frames +and some other main/high profile features. (It currently only supports +constrained baseline profile and CABAC.) Using it is mostly useful for +testing and for taking advantage of Cisco's patent portfolio license +(@url{http://www.openh264.org/BINARY_LICENSE.txt}). + +@section OpenJPEG + +FFmpeg can use the OpenJPEG libraries for decoding/encoding J2K videos. Go to +@url{http://www.openjpeg.org/} to get the libraries and follow the installation +instructions. To enable using OpenJPEG in FFmpeg, pass @code{--enable-libopenjpeg} to +@file{./configure}. + +@section rav1e + +FFmpeg can make use of rav1e (Rust AV1 Encoder) via its C bindings to encode videos. +Go to @url{https://github.com/xiph/rav1e/} and follow the instructions to build +the C library. To enable using rav1e in FFmpeg, pass @code{--enable-librav1e} +to @file{./configure}. + +@section SVT-AV1 + +FFmpeg can make use of the Scalable Video Technology for AV1 library for AV1 encoding. + +Go to @url{https://github.com/OpenVisualCloud/SVT-AV1/} and follow the instructions +for installing the library. Then pass @code{--enable-libsvtav1} to configure to +enable it. + +@section TwoLAME + +FFmpeg can make use of the TwoLAME library for MP2 encoding. + +Go to @url{http://www.twolame.org/} and follow the +instructions for installing the library. +Then pass @code{--enable-libtwolame} to configure to enable it. + +@section VapourSynth + +FFmpeg can read VapourSynth scripts as input. To enable support, pass +@code{--enable-vapoursynth} to configure. Vapoursynth is detected via +@code{pkg-config}. Versions 42 or greater supported. +See @url{http://www.vapoursynth.com/}. + +Due to security concerns, Vapoursynth scripts will not +be autodetected so the input format has to be forced. For ff* CLI tools, +add @code{-f vapoursynth} before the input @code{-i yourscript.vpy}. + +@section x264 + +FFmpeg can make use of the x264 library for H.264 encoding. + +Go to @url{http://www.videolan.org/developers/x264.html} and follow the +instructions for installing the library. Then pass @code{--enable-libx264} to +configure to enable it. + +@float NOTE +x264 is under the GNU Public License Version 2 or later +(see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for +details), you must upgrade FFmpeg's license to GPL in order to use it. +@end float + +@section x265 + +FFmpeg can make use of the x265 library for HEVC encoding. + +Go to @url{http://x265.org/developers.html} and follow the instructions +for installing the library. Then pass @code{--enable-libx265} to configure +to enable it. + +@float NOTE +x265 is under the GNU Public License Version 2 or later +(see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for +details), you must upgrade FFmpeg's license to GPL in order to use it. +@end float + +@section xavs + +FFmpeg can make use of the xavs library for AVS encoding. + +Go to @url{http://xavs.sf.net/} and follow the instructions for +installing the library. Then pass @code{--enable-libxavs} to configure to +enable it. + +@section xavs2 + +FFmpeg can make use of the xavs2 library for AVS2-P2/IEEE1857.4 video encoding. + +Go to @url{https://github.com/pkuvcl/xavs2} and follow the instructions for +installing the library. Then pass @code{--enable-libxavs2} to configure to +enable it. + +@float NOTE +libxavs2 is under the GNU Public License Version 2 or later +(see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for +details), you must upgrade FFmpeg's license to GPL in order to use it. +@end float + +@section ZVBI + +ZVBI is a VBI decoding library which can be used by FFmpeg to decode DVB +teletext pages and DVB teletext subtitles. + +Go to @url{http://sourceforge.net/projects/zapping/} and follow the instructions for +installing the library. Then pass @code{--enable-libzvbi} to configure to +enable it. + +@chapter Supported File Formats, Codecs or Features + +You can use the @code{-formats} and @code{-codecs} options to have an exhaustive list. + +@section File Formats + +FFmpeg supports the following file formats through the @code{libavformat} +library: + +@multitable @columnfractions .4 .1 .1 .4 +@item Name @tab Encoding @tab Decoding @tab Comments +@item 3dostr @tab @tab X +@item 4xm @tab @tab X + @tab 4X Technologies format, used in some games. +@item 8088flex TMV @tab @tab X +@item AAX @tab @tab X + @tab Audible Enhanced Audio format, used in audiobooks. +@item AA @tab @tab X + @tab Audible Format 2, 3, and 4, used in audiobooks. +@item ACT Voice @tab @tab X + @tab contains G.729 audio +@item Adobe Filmstrip @tab X @tab X +@item Audio IFF (AIFF) @tab X @tab X +@item American Laser Games MM @tab @tab X + @tab Multimedia format used in games like Mad Dog McCree. +@item 3GPP AMR @tab X @tab X +@item Amazing Studio Packed Animation File @tab @tab X + @tab Multimedia format used in game Heart Of Darkness. +@item Apple HTTP Live Streaming @tab @tab X +@item Artworx Data Format @tab @tab X +@item Interplay ACM @tab @tab X + @tab Audio only format used in some Interplay games. +@item ADP @tab @tab X + @tab Audio format used on the Nintendo Gamecube. +@item AFC @tab @tab X + @tab Audio format used on the Nintendo Gamecube. +@item ADS/SS2 @tab @tab X + @tab Audio format used on the PS2. +@item APNG @tab X @tab X +@item ASF @tab X @tab X + @tab Advanced / Active Streaming Format. +@item AST @tab X @tab X + @tab Audio format used on the Nintendo Wii. +@item AVI @tab X @tab X +@item AviSynth @tab @tab X +@item AVR @tab @tab X + @tab Audio format used on Mac. +@item AVS @tab @tab X + @tab Multimedia format used by the Creature Shock game. +@item Beam Software SIFF @tab @tab X + @tab Audio and video format used in some games by Beam Software. +@item Bethesda Softworks VID @tab @tab X + @tab Used in some games from Bethesda Softworks. +@item Binary text @tab @tab X +@item Bink @tab @tab X + @tab Multimedia format used by many games. +@item Bink Audio @tab @tab X + @tab Audio only multimedia format used by some games. +@item Bitmap Brothers JV @tab @tab X + @tab Used in Z and Z95 games. +@item BRP @tab @tab X + @tab Argonaut Games format. +@item Brute Force & Ignorance @tab @tab X + @tab Used in the game Flash Traffic: City of Angels. +@item BFSTM @tab @tab X + @tab Audio format used on the Nintendo WiiU (based on BRSTM). +@item BRSTM @tab @tab X + @tab Audio format used on the Nintendo Wii. +@item BW64 @tab @tab X + @tab Broadcast Wave 64bit. +@item BWF @tab X @tab X +@item codec2 (raw) @tab X @tab X + @tab Must be given -mode format option to decode correctly. +@item codec2 (.c2 files) @tab X @tab X + @tab Contains header with version and mode info, simplifying playback. +@item CRI ADX @tab X @tab X + @tab Audio-only format used in console video games. +@item CRI AIX @tab @tab X +@item CRI HCA @tab @tab X + @tab Audio-only format used in console video games. +@item Discworld II BMV @tab @tab X +@item Interplay C93 @tab @tab X + @tab Used in the game Cyberia from Interplay. +@item Delphine Software International CIN @tab @tab X + @tab Multimedia format used by Delphine Software games. +@item Digital Speech Standard (DSS) @tab @tab X +@item CD+G @tab @tab X + @tab Video format used by CD+G karaoke disks +@item Phantom Cine @tab @tab X +@item Commodore CDXL @tab @tab X + @tab Amiga CD video format +@item Core Audio Format @tab X @tab X + @tab Apple Core Audio Format +@item CRC testing format @tab X @tab +@item Creative Voice @tab X @tab X + @tab Created for the Sound Blaster Pro. +@item CRYO APC @tab @tab X + @tab Audio format used in some games by CRYO Interactive Entertainment. +@item D-Cinema audio @tab X @tab X +@item Deluxe Paint Animation @tab @tab X +@item DCSTR @tab @tab X +@item DFA @tab @tab X + @tab This format is used in Chronomaster game +@item DirectDraw Surface @tab @tab X +@item DSD Stream File (DSF) @tab @tab X +@item DV video @tab X @tab X +@item DXA @tab @tab X + @tab This format is used in the non-Windows version of the Feeble Files + game and different game cutscenes repacked for use with ScummVM. +@item Electronic Arts cdata @tab @tab X +@item Electronic Arts Multimedia @tab @tab X + @tab Used in various EA games; files have extensions like WVE and UV2. +@item Ensoniq Paris Audio File @tab @tab X +@item FFM (FFserver live feed) @tab X @tab X +@item Flash (SWF) @tab X @tab X +@item Flash 9 (AVM2) @tab X @tab X + @tab Only embedded audio is decoded. +@item FLI/FLC/FLX animation @tab @tab X + @tab .fli/.flc files +@item Flash Video (FLV) @tab X @tab X + @tab Macromedia Flash video files +@item framecrc testing format @tab X @tab +@item FunCom ISS @tab @tab X + @tab Audio format used in various games from FunCom like The Longest Journey. +@item G.723.1 @tab X @tab X +@item G.726 @tab @tab X @tab Both left- and right-justified. +@item G.729 BIT @tab X @tab X +@item G.729 raw @tab @tab X +@item GENH @tab @tab X + @tab Audio format for various games. +@item GIF Animation @tab X @tab X +@item GXF @tab X @tab X + @tab General eXchange Format SMPTE 360M, used by Thomson Grass Valley + playout servers. +@item HNM @tab @tab X + @tab Only version 4 supported, used in some games from Cryo Interactive +@item iCEDraw File @tab @tab X +@item ICO @tab X @tab X + @tab Microsoft Windows ICO +@item id Quake II CIN video @tab @tab X +@item id RoQ @tab X @tab X + @tab Used in Quake III, Jedi Knight 2 and other computer games. +@item IEC61937 encapsulation @tab X @tab X +@item IFF @tab @tab X + @tab Interchange File Format +@item IFV @tab @tab X + @tab A format used by some old CCTV DVRs. +@item iLBC @tab X @tab X +@item Interplay MVE @tab @tab X + @tab Format used in various Interplay computer games. +@item Iterated Systems ClearVideo @tab @tab X + @tab I-frames only +@item IV8 @tab @tab X + @tab A format generated by IndigoVision 8000 video server. +@item IVF (On2) @tab X @tab X + @tab A format used by libvpx +@item Internet Video Recording @tab @tab X +@item IRCAM @tab X @tab X +@item LATM @tab X @tab X +@item LMLM4 @tab @tab X + @tab Used by Linux Media Labs MPEG-4 PCI boards +@item LOAS @tab @tab X + @tab contains LATM multiplexed AAC audio +@item LRC @tab X @tab X +@item LVF @tab @tab X +@item LXF @tab @tab X + @tab VR native stream format, used by Leitch/Harris' video servers. +@item Magic Lantern Video (MLV) @tab @tab X +@item Matroska @tab X @tab X +@item Matroska audio @tab X @tab +@item FFmpeg metadata @tab X @tab X + @tab Metadata in text format. +@item MAXIS XA @tab @tab X + @tab Used in Sim City 3000; file extension .xa. +@item MCA @tab @tab X + @tab Used in some games from Capcom; file extension .mca. +@item MD Studio @tab @tab X +@item Metal Gear Solid: The Twin Snakes @tab @tab X +@item Megalux Frame @tab @tab X + @tab Used by Megalux Ultimate Paint +@item Mobotix .mxg @tab @tab X +@item Monkey's Audio @tab @tab X +@item Motion Pixels MVI @tab @tab X +@item MOV/QuickTime/MP4 @tab X @tab X + @tab 3GP, 3GP2, PSP, iPod variants supported +@item MP2 @tab X @tab X +@item MP3 @tab X @tab X +@item MPEG-1 System @tab X @tab X + @tab muxed audio and video, VCD format supported +@item MPEG-PS (program stream) @tab X @tab X + @tab also known as @code{VOB} file, SVCD and DVD format supported +@item MPEG-TS (transport stream) @tab X @tab X + @tab also known as DVB Transport Stream +@item MPEG-4 @tab X @tab X + @tab MPEG-4 is a variant of QuickTime. +@item MSF @tab @tab X + @tab Audio format used on the PS3. +@item Mirillis FIC video @tab @tab X + @tab No cursor rendering. +@item MIDI Sample Dump Standard @tab @tab X +@item MIME multipart JPEG @tab X @tab +@item MSN TCP webcam @tab @tab X + @tab Used by MSN Messenger webcam streams. +@item MTV @tab @tab X +@item Musepack @tab @tab X +@item Musepack SV8 @tab @tab X +@item Material eXchange Format (MXF) @tab X @tab X + @tab SMPTE 377M, used by D-Cinema, broadcast industry. +@item Material eXchange Format (MXF), D-10 Mapping @tab X @tab X + @tab SMPTE 386M, D-10/IMX Mapping. +@item NC camera feed @tab @tab X + @tab NC (AVIP NC4600) camera streams +@item NIST SPeech HEader REsources @tab @tab X +@item Computerized Speech Lab NSP @tab @tab X +@item NTT TwinVQ (VQF) @tab @tab X + @tab Nippon Telegraph and Telephone Corporation TwinVQ. +@item Nullsoft Streaming Video @tab @tab X +@item NuppelVideo @tab @tab X +@item NUT @tab X @tab X + @tab NUT Open Container Format +@item Ogg @tab X @tab X +@item Playstation Portable PMP @tab @tab X +@item Portable Voice Format @tab @tab X +@item TechnoTrend PVA @tab @tab X + @tab Used by TechnoTrend DVB PCI boards. +@item QCP @tab @tab X +@item raw ADTS (AAC) @tab X @tab X +@item raw AC-3 @tab X @tab X +@item raw AMR-NB @tab @tab X +@item raw AMR-WB @tab @tab X +@item raw aptX @tab X @tab X +@item raw aptX HD @tab X @tab X +@item raw Chinese AVS video @tab X @tab X +@item raw Dirac @tab X @tab X +@item raw DNxHD @tab X @tab X +@item raw DTS @tab X @tab X +@item raw DTS-HD @tab @tab X +@item raw E-AC-3 @tab X @tab X +@item raw FLAC @tab X @tab X +@item raw GSM @tab @tab X +@item raw H.261 @tab X @tab X +@item raw H.263 @tab X @tab X +@item raw H.264 @tab X @tab X +@item raw HEVC @tab X @tab X +@item raw Ingenient MJPEG @tab @tab X +@item raw MJPEG @tab X @tab X +@item raw MLP @tab @tab X +@item raw MPEG @tab @tab X +@item raw MPEG-1 @tab @tab X +@item raw MPEG-2 @tab @tab X +@item raw MPEG-4 @tab X @tab X +@item raw NULL @tab X @tab +@item raw video @tab X @tab X +@item raw id RoQ @tab X @tab +@item raw SBC @tab X @tab X +@item raw Shorten @tab @tab X +@item raw TAK @tab @tab X +@item raw TrueHD @tab X @tab X +@item raw VC-1 @tab X @tab X +@item raw PCM A-law @tab X @tab X +@item raw PCM mu-law @tab X @tab X +@item raw PCM Archimedes VIDC @tab X @tab X +@item raw PCM signed 8 bit @tab X @tab X +@item raw PCM signed 16 bit big-endian @tab X @tab X +@item raw PCM signed 16 bit little-endian @tab X @tab X +@item raw PCM signed 24 bit big-endian @tab X @tab X +@item raw PCM signed 24 bit little-endian @tab X @tab X +@item raw PCM signed 32 bit big-endian @tab X @tab X +@item raw PCM signed 32 bit little-endian @tab X @tab X +@item raw PCM signed 64 bit big-endian @tab X @tab X +@item raw PCM signed 64 bit little-endian @tab X @tab X +@item raw PCM unsigned 8 bit @tab X @tab X +@item raw PCM unsigned 16 bit big-endian @tab X @tab X +@item raw PCM unsigned 16 bit little-endian @tab X @tab X +@item raw PCM unsigned 24 bit big-endian @tab X @tab X +@item raw PCM unsigned 24 bit little-endian @tab X @tab X +@item raw PCM unsigned 32 bit big-endian @tab X @tab X +@item raw PCM unsigned 32 bit little-endian @tab X @tab X +@item raw PCM 16.8 floating point little-endian @tab @tab X +@item raw PCM 24.0 floating point little-endian @tab @tab X +@item raw PCM floating-point 32 bit big-endian @tab X @tab X +@item raw PCM floating-point 32 bit little-endian @tab X @tab X +@item raw PCM floating-point 64 bit big-endian @tab X @tab X +@item raw PCM floating-point 64 bit little-endian @tab X @tab X +@item RDT @tab @tab X +@item REDCODE R3D @tab @tab X + @tab File format used by RED Digital cameras, contains JPEG 2000 frames and PCM audio. +@item RealMedia @tab X @tab X +@item Redirector @tab @tab X +@item RedSpark @tab @tab X +@item Renderware TeXture Dictionary @tab @tab X +@item Resolume DXV @tab @tab X +@item RF64 @tab @tab X +@item RL2 @tab @tab X + @tab Audio and video format used in some games by Entertainment Software Partners. +@item RPL/ARMovie @tab @tab X +@item Lego Mindstorms RSO @tab X @tab X +@item RSD @tab @tab X +@item RTMP @tab X @tab X + @tab Output is performed by publishing stream to RTMP server +@item RTP @tab X @tab X +@item RTSP @tab X @tab X +@item Sample Dump eXchange @tab @tab X +@item SAP @tab X @tab X +@item SBG @tab @tab X +@item SDP @tab @tab X +@item SER @tab @tab X +@item Sega FILM/CPK @tab X @tab X + @tab Used in many Sega Saturn console games. +@item Silicon Graphics Movie @tab @tab X +@item Sierra SOL @tab @tab X + @tab .sol files used in Sierra Online games. +@item Sierra VMD @tab @tab X + @tab Used in Sierra CD-ROM games. +@item Smacker @tab @tab X + @tab Multimedia format used by many games. +@item SMJPEG @tab X @tab X + @tab Used in certain Loki game ports. +@item SMPTE 337M encapsulation @tab @tab X +@item Smush @tab @tab X + @tab Multimedia format used in some LucasArts games. +@item Sony OpenMG (OMA) @tab X @tab X + @tab Audio format used in Sony Sonic Stage and Sony Vegas. +@item Sony PlayStation STR @tab @tab X +@item Sony Wave64 (W64) @tab X @tab X +@item SoX native format @tab X @tab X +@item SUN AU format @tab X @tab X +@item SUP raw PGS subtitles @tab X @tab X +@item SVAG @tab @tab X + @tab Audio format used in Konami PS2 games. +@item TDSC @tab @tab X +@item Text files @tab @tab X +@item THP @tab @tab X + @tab Used on the Nintendo GameCube. +@item Tiertex Limited SEQ @tab @tab X + @tab Tiertex .seq files used in the DOS CD-ROM version of the game Flashback. +@item True Audio @tab X @tab X +@item VAG @tab @tab X + @tab Audio format used in many Sony PS2 games. +@item VC-1 test bitstream @tab X @tab X +@item Vidvox Hap @tab X @tab X +@item Vivo @tab @tab X +@item VPK @tab @tab X + @tab Audio format used in Sony PS games. +@item WAV @tab X @tab X +@item WavPack @tab X @tab X +@item WebM @tab X @tab X +@item Windows Televison (WTV) @tab X @tab X +@item Wing Commander III movie @tab @tab X + @tab Multimedia format used in Origin's Wing Commander III computer game. +@item Westwood Studios audio @tab @tab X + @tab Multimedia format used in Westwood Studios games. +@item Westwood Studios VQA @tab @tab X + @tab Multimedia format used in Westwood Studios games. +@item Wideband Single-bit Data (WSD) @tab @tab X +@item WVE @tab @tab X +@item XMV @tab @tab X + @tab Microsoft video container used in Xbox games. +@item XVAG @tab @tab X + @tab Audio format used on the PS3. +@item xWMA @tab @tab X + @tab Microsoft audio container used by XAudio 2. +@item eXtended BINary text (XBIN) @tab @tab X +@item YUV4MPEG pipe @tab X @tab X +@item Psygnosis YOP @tab @tab X +@end multitable + +@code{X} means that the feature in that column (encoding / decoding) is supported. + +@section Image Formats + +FFmpeg can read and write images for each frame of a video sequence. The +following image formats are supported: + +@multitable @columnfractions .4 .1 .1 .4 +@item Name @tab Encoding @tab Decoding @tab Comments +@item .Y.U.V @tab X @tab X + @tab one raw file per component +@item Alias PIX @tab X @tab X + @tab Alias/Wavefront PIX image format +@item animated GIF @tab X @tab X +@item APNG @tab X @tab X + @tab Animated Portable Network Graphics +@item BMP @tab X @tab X + @tab Microsoft BMP image +@item BRender PIX @tab @tab X + @tab Argonaut BRender 3D engine image format. +@item CRI @tab @tab X + @tab Cintel RAW +@item DPX @tab X @tab X + @tab Digital Picture Exchange +@item EXR @tab @tab X + @tab OpenEXR +@item FITS @tab X @tab X + @tab Flexible Image Transport System +@item JPEG @tab X @tab X + @tab Progressive JPEG is not supported. +@item JPEG 2000 @tab X @tab X +@item JPEG-LS @tab X @tab X +@item LJPEG @tab X @tab + @tab Lossless JPEG +@item MSP @tab @tab X + @tab Microsoft Paint image +@item PAM @tab X @tab X + @tab PAM is a PNM extension with alpha support. +@item PBM @tab X @tab X + @tab Portable BitMap image +@item PCD @tab @tab X + @tab PhotoCD +@item PCX @tab X @tab X + @tab PC Paintbrush +@item PFM @tab X @tab X + @tab Portable FloatMap image +@item PGM @tab X @tab X + @tab Portable GrayMap image +@item PGMYUV @tab X @tab X + @tab PGM with U and V components in YUV 4:2:0 +@item PGX @tab @tab X + @tab PGX file decoder +@item PIC @tab @tab X + @tab Pictor/PC Paint +@item PNG @tab X @tab X + @tab Portable Network Graphics image +@item PPM @tab X @tab X + @tab Portable PixelMap image +@item PSD @tab @tab X + @tab Photoshop +@item PTX @tab @tab X + @tab V.Flash PTX format +@item SGI @tab X @tab X + @tab SGI RGB image format +@item Sun Rasterfile @tab X @tab X + @tab Sun RAS image format +@item TIFF @tab X @tab X + @tab YUV, JPEG and some extension is not supported yet. +@item Truevision Targa @tab X @tab X + @tab Targa (.TGA) image format +@item WebP @tab E @tab X + @tab WebP image format, encoding supported through external library libwebp +@item XBM @tab X @tab X + @tab X BitMap image format +@item XFace @tab X @tab X + @tab X-Face image format +@item XPM @tab @tab X + @tab X PixMap image format +@item XWD @tab X @tab X + @tab X Window Dump image format +@end multitable + +@code{X} means that the feature in that column (encoding / decoding) is supported. + +@code{E} means that support is provided through an external library. + +@section Video Codecs + +@multitable @columnfractions .4 .1 .1 .4 +@item Name @tab Encoding @tab Decoding @tab Comments +@item 4X Movie @tab @tab X + @tab Used in certain computer games. +@item 8088flex TMV @tab @tab X +@item A64 multicolor @tab X @tab + @tab Creates video suitable to be played on a commodore 64 (multicolor mode). +@item Amazing Studio PAF Video @tab @tab X +@item American Laser Games MM @tab @tab X + @tab Used in games like Mad Dog McCree. +@item Amuse Graphics Movie @tab @tab X +@item AMV Video @tab X @tab X + @tab Used in Chinese MP3 players. +@item ANSI/ASCII art @tab @tab X +@item Apple Intermediate Codec @tab @tab X +@item Apple MJPEG-B @tab @tab X +@item Apple Pixlet @tab @tab X +@item Apple ProRes @tab X @tab X + @tab fourcc: apch,apcn,apcs,apco,ap4h,ap4x +@item Apple QuickDraw @tab @tab X + @tab fourcc: qdrw +@item Argonaut Video @tab @tab X + @tab Used in some Argonaut games. +@item Asus v1 @tab X @tab X + @tab fourcc: ASV1 +@item Asus v2 @tab X @tab X + @tab fourcc: ASV2 +@item ATI VCR1 @tab @tab X + @tab fourcc: VCR1 +@item ATI VCR2 @tab @tab X + @tab fourcc: VCR2 +@item Auravision Aura @tab @tab X +@item Auravision Aura 2 @tab @tab X +@item Autodesk Animator Flic video @tab @tab X +@item Autodesk RLE @tab @tab X + @tab fourcc: AASC +@item AV1 @tab E @tab E + @tab Supported through external libraries libaom, libdav1d, librav1e and libsvtav1 +@item Avid 1:1 10-bit RGB Packer @tab X @tab X + @tab fourcc: AVrp +@item AVS (Audio Video Standard) video @tab @tab X + @tab Video encoding used by the Creature Shock game. +@item AVS2-P2/IEEE1857.4 @tab E @tab E + @tab Supported through external libraries libxavs2 and libdavs2 +@item AVS3-P2/IEEE1857.10 @tab @tab E + @tab Supported through external library libuavs3d +@item AYUV @tab X @tab X + @tab Microsoft uncompressed packed 4:4:4:4 +@item Beam Software VB @tab @tab X +@item Bethesda VID video @tab @tab X + @tab Used in some games from Bethesda Softworks. +@item Bink Video @tab @tab X +@item BitJazz SheerVideo @tab @tab X +@item Bitmap Brothers JV video @tab @tab X +@item y41p Brooktree uncompressed 4:1:1 12-bit @tab X @tab X +@item Brooktree ProSumer Video @tab @tab X + @tab fourcc: BT20 +@item Brute Force & Ignorance @tab @tab X + @tab Used in the game Flash Traffic: City of Angels. +@item C93 video @tab @tab X + @tab Codec used in Cyberia game. +@item CamStudio @tab @tab X + @tab fourcc: CSCD +@item CD+G @tab @tab X + @tab Video codec for CD+G karaoke disks +@item CDXL @tab @tab X + @tab Amiga CD video codec +@item Chinese AVS video @tab E @tab X + @tab AVS1-P2, JiZhun profile, encoding through external library libxavs +@item Delphine Software International CIN video @tab @tab X + @tab Codec used in Delphine Software International games. +@item Discworld II BMV Video @tab @tab X +@item CineForm HD @tab X @tab X +@item Canopus HQ @tab @tab X +@item Canopus HQA @tab @tab X +@item Canopus HQX @tab @tab X +@item Canopus Lossless Codec @tab @tab X +@item CDToons @tab @tab X + @tab Codec used in various Broderbund games. +@item Cinepak @tab @tab X +@item Cirrus Logic AccuPak @tab X @tab X + @tab fourcc: CLJR +@item CPiA Video Format @tab @tab X +@item Creative YUV (CYUV) @tab @tab X +@item DFA @tab @tab X + @tab Codec used in Chronomaster game. +@item Dirac @tab E @tab X + @tab supported though the native vc2 (Dirac Pro) encoder +@item Deluxe Paint Animation @tab @tab X +@item DNxHD @tab X @tab X + @tab aka SMPTE VC3 +@item Duck TrueMotion 1.0 @tab @tab X + @tab fourcc: DUCK +@item Duck TrueMotion 2.0 @tab @tab X + @tab fourcc: TM20 +@item Duck TrueMotion 2.0 RT @tab @tab X + @tab fourcc: TR20 +@item DV (Digital Video) @tab X @tab X +@item Dxtory capture format @tab @tab X +@item Feeble Files/ScummVM DXA @tab @tab X + @tab Codec originally used in Feeble Files game. +@item Electronic Arts CMV video @tab @tab X + @tab Used in NHL 95 game. +@item Electronic Arts Madcow video @tab @tab X +@item Electronic Arts TGV video @tab @tab X +@item Electronic Arts TGQ video @tab @tab X +@item Electronic Arts TQI video @tab @tab X +@item Escape 124 @tab @tab X +@item Escape 130 @tab @tab X +@item FFmpeg video codec #1 @tab X @tab X + @tab lossless codec (fourcc: FFV1) +@item Flash Screen Video v1 @tab X @tab X + @tab fourcc: FSV1 +@item Flash Screen Video v2 @tab X @tab X +@item Flash Video (FLV) @tab X @tab X + @tab Sorenson H.263 used in Flash +@item FM Screen Capture Codec @tab @tab X +@item Forward Uncompressed @tab @tab X +@item Fraps @tab @tab X +@item Go2Meeting @tab @tab X + @tab fourcc: G2M2, G2M3 +@item Go2Webinar @tab @tab X + @tab fourcc: G2M4 +@item Gremlin Digital Video @tab @tab X +@item H.261 @tab X @tab X +@item H.263 / H.263-1996 @tab X @tab X +@item H.263+ / H.263-1998 / H.263 version 2 @tab X @tab X +@item H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 @tab E @tab X + @tab encoding supported through external library libx264 and OpenH264 +@item HEVC @tab X @tab X + @tab encoding supported through external library libx265 and libkvazaar +@item HNM version 4 @tab @tab X +@item HuffYUV @tab X @tab X +@item HuffYUV FFmpeg variant @tab X @tab X +@item IBM Ultimotion @tab @tab X + @tab fourcc: ULTI +@item id Cinematic video @tab @tab X + @tab Used in Quake II. +@item id RoQ video @tab X @tab X + @tab Used in Quake III, Jedi Knight 2, other computer games. +@item IFF ILBM @tab @tab X + @tab IFF interleaved bitmap +@item IFF ByteRun1 @tab @tab X + @tab IFF run length encoded bitmap +@item Infinity IMM4 @tab @tab X +@item Intel H.263 @tab @tab X +@item Intel Indeo 2 @tab @tab X +@item Intel Indeo 3 @tab @tab X +@item Intel Indeo 4 @tab @tab X +@item Intel Indeo 5 @tab @tab X +@item Interplay C93 @tab @tab X + @tab Used in the game Cyberia from Interplay. +@item Interplay MVE video @tab @tab X + @tab Used in Interplay .MVE files. +@item J2K @tab X @tab X +@item Karl Morton's video codec @tab @tab X + @tab Codec used in Worms games. +@item Kega Game Video (KGV1) @tab @tab X + @tab Kega emulator screen capture codec. +@item Lagarith @tab @tab X +@item LCL (LossLess Codec Library) MSZH @tab @tab X +@item LCL (LossLess Codec Library) ZLIB @tab E @tab E +@item LOCO @tab @tab X +@item LucasArts SANM/Smush @tab @tab X + @tab Used in LucasArts games / SMUSH animations. +@item lossless MJPEG @tab X @tab X +@item MagicYUV Video @tab X @tab X +@item Mandsoft Screen Capture Codec @tab @tab X +@item Microsoft ATC Screen @tab @tab X + @tab Also known as Microsoft Screen 3. +@item Microsoft Expression Encoder Screen @tab @tab X + @tab Also known as Microsoft Titanium Screen 2. +@item Microsoft RLE @tab @tab X +@item Microsoft Screen 1 @tab @tab X + @tab Also known as Windows Media Video V7 Screen. +@item Microsoft Screen 2 @tab @tab X + @tab Also known as Windows Media Video V9 Screen. +@item Microsoft Video 1 @tab @tab X +@item Mimic @tab @tab X + @tab Used in MSN Messenger Webcam streams. +@item Miro VideoXL @tab @tab X + @tab fourcc: VIXL +@item MJPEG (Motion JPEG) @tab X @tab X +@item Mobotix MxPEG video @tab @tab X +@item Motion Pixels video @tab @tab X +@item MPEG-1 video @tab X @tab X +@item MPEG-2 video @tab X @tab X +@item MPEG-4 part 2 @tab X @tab X + @tab libxvidcore can be used alternatively for encoding. +@item MPEG-4 part 2 Microsoft variant version 1 @tab @tab X +@item MPEG-4 part 2 Microsoft variant version 2 @tab X @tab X +@item MPEG-4 part 2 Microsoft variant version 3 @tab X @tab X +@item Newtek SpeedHQ @tab X @tab X +@item Nintendo Gamecube THP video @tab @tab X +@item NotchLC @tab @tab X +@item NuppelVideo/RTjpeg @tab @tab X + @tab Video encoding used in NuppelVideo files. +@item On2 VP3 @tab @tab X + @tab still experimental +@item On2 VP4 @tab @tab X + @tab fourcc: VP40 +@item On2 VP5 @tab @tab X + @tab fourcc: VP50 +@item On2 VP6 @tab @tab X + @tab fourcc: VP60,VP61,VP62 +@item On2 VP7 @tab @tab X + @tab fourcc: VP70,VP71 +@item VP8 @tab E @tab X + @tab fourcc: VP80, encoding supported through external library libvpx +@item VP9 @tab E @tab X + @tab encoding supported through external library libvpx +@item Pinnacle TARGA CineWave YUV16 @tab @tab X + @tab fourcc: Y216 +@item Q-team QPEG @tab @tab X + @tab fourccs: QPEG, Q1.0, Q1.1 +@item QuickTime 8BPS video @tab @tab X +@item QuickTime Animation (RLE) video @tab X @tab X + @tab fourcc: 'rle ' +@item QuickTime Graphics (SMC) @tab @tab X + @tab fourcc: 'smc ' +@item QuickTime video (RPZA) @tab X @tab X + @tab fourcc: rpza +@item R10K AJA Kona 10-bit RGB Codec @tab X @tab X +@item R210 Quicktime Uncompressed RGB 10-bit @tab X @tab X +@item Raw Video @tab X @tab X +@item RealVideo 1.0 @tab X @tab X +@item RealVideo 2.0 @tab X @tab X +@item RealVideo 3.0 @tab @tab X + @tab still far from ideal +@item RealVideo 4.0 @tab @tab X +@item Renderware TXD (TeXture Dictionary) @tab @tab X + @tab Texture dictionaries used by the Renderware Engine. +@item RL2 video @tab @tab X + @tab used in some games by Entertainment Software Partners +@item ScreenPressor @tab @tab X +@item Screenpresso @tab @tab X +@item Screen Recorder Gold Codec @tab @tab X +@item Sierra VMD video @tab @tab X + @tab Used in Sierra VMD files. +@item Silicon Graphics Motion Video Compressor 1 (MVC1) @tab @tab X +@item Silicon Graphics Motion Video Compressor 2 (MVC2) @tab @tab X +@item Silicon Graphics RLE 8-bit video @tab @tab X +@item Smacker video @tab @tab X + @tab Video encoding used in Smacker. +@item SMPTE VC-1 @tab @tab X +@item Snow @tab X @tab X + @tab experimental wavelet codec (fourcc: SNOW) +@item Sony PlayStation MDEC (Motion DECoder) @tab @tab X +@item Sorenson Vector Quantizer 1 @tab X @tab X + @tab fourcc: SVQ1 +@item Sorenson Vector Quantizer 3 @tab @tab X + @tab fourcc: SVQ3 +@item Sunplus JPEG (SP5X) @tab @tab X + @tab fourcc: SP5X +@item TechSmith Screen Capture Codec @tab @tab X + @tab fourcc: TSCC +@item TechSmith Screen Capture Codec 2 @tab @tab X + @tab fourcc: TSC2 +@item Theora @tab E @tab X + @tab encoding supported through external library libtheora +@item Tiertex Limited SEQ video @tab @tab X + @tab Codec used in DOS CD-ROM FlashBack game. +@item Ut Video @tab X @tab X +@item v210 QuickTime uncompressed 4:2:2 10-bit @tab X @tab X +@item v308 QuickTime uncompressed 4:4:4 @tab X @tab X +@item v408 QuickTime uncompressed 4:4:4:4 @tab X @tab X +@item v410 QuickTime uncompressed 4:4:4 10-bit @tab X @tab X +@item VBLE Lossless Codec @tab @tab X +@item VMware Screen Codec / VMware Video @tab @tab X + @tab Codec used in videos captured by VMware. +@item Westwood Studios VQA (Vector Quantized Animation) video @tab @tab X +@item Windows Media Image @tab @tab X +@item Windows Media Video 7 @tab X @tab X +@item Windows Media Video 8 @tab X @tab X +@item Windows Media Video 9 @tab @tab X + @tab not completely working +@item Wing Commander III / Xan @tab @tab X + @tab Used in Wing Commander III .MVE files. +@item Wing Commander IV / Xan @tab @tab X + @tab Used in Wing Commander IV. +@item Winnov WNV1 @tab @tab X +@item WMV7 @tab X @tab X +@item YAMAHA SMAF @tab X @tab X +@item Psygnosis YOP Video @tab @tab X +@item yuv4 @tab X @tab X + @tab libquicktime uncompressed packed 4:2:0 +@item ZeroCodec Lossless Video @tab @tab X +@item ZLIB @tab X @tab X + @tab part of LCL, encoder experimental +@item Zip Motion Blocks Video @tab X @tab X + @tab Encoder works only in PAL8. +@end multitable + +@code{X} means that the feature in that column (encoding / decoding) is supported. + +@code{E} means that support is provided through an external library. + +@section Audio Codecs + +@multitable @columnfractions .4 .1 .1 .4 +@item Name @tab Encoding @tab Decoding @tab Comments +@item 8SVX exponential @tab @tab X +@item 8SVX fibonacci @tab @tab X +@item AAC @tab EX @tab X + @tab encoding supported through internal encoder and external library libfdk-aac +@item AAC+ @tab E @tab IX + @tab encoding supported through external library libfdk-aac +@item AC-3 @tab IX @tab IX +@item ACELP.KELVIN @tab @tab X +@item ADPCM 4X Movie @tab @tab X +@item ADPCM Yamaha AICA @tab @tab X +@item ADPCM AmuseGraphics Movie @tab @tab X +@item ADPCM Argonaut Games @tab X @tab X +@item ADPCM CDROM XA @tab @tab X +@item ADPCM Creative Technology @tab @tab X + @tab 16 -> 4, 8 -> 4, 8 -> 3, 8 -> 2 +@item ADPCM Electronic Arts @tab @tab X + @tab Used in various EA titles. +@item ADPCM Electronic Arts Maxis CDROM XS @tab @tab X + @tab Used in Sim City 3000. +@item ADPCM Electronic Arts R1 @tab @tab X +@item ADPCM Electronic Arts R2 @tab @tab X +@item ADPCM Electronic Arts R3 @tab @tab X +@item ADPCM Electronic Arts XAS @tab @tab X +@item ADPCM G.722 @tab X @tab X +@item ADPCM G.726 @tab X @tab X +@item ADPCM IMA AMV @tab X @tab X + @tab Used in AMV files +@item ADPCM IMA Cunning Developments @tab @tab X +@item ADPCM IMA Electronic Arts EACS @tab @tab X +@item ADPCM IMA Electronic Arts SEAD @tab @tab X +@item ADPCM IMA Funcom @tab @tab X +@item ADPCM IMA High Voltage Software ALP @tab X @tab X +@item ADPCM IMA QuickTime @tab X @tab X +@item ADPCM IMA Simon & Schuster Interactive @tab X @tab X +@item ADPCM IMA Ubisoft APM @tab X @tab X +@item ADPCM IMA Loki SDL MJPEG @tab @tab X +@item ADPCM IMA WAV @tab X @tab X +@item ADPCM IMA Westwood @tab @tab X +@item ADPCM ISS IMA @tab @tab X + @tab Used in FunCom games. +@item ADPCM IMA Dialogic @tab @tab X +@item ADPCM IMA Duck DK3 @tab @tab X + @tab Used in some Sega Saturn console games. +@item ADPCM IMA Duck DK4 @tab @tab X + @tab Used in some Sega Saturn console games. +@item ADPCM IMA Radical @tab @tab X +@item ADPCM Microsoft @tab X @tab X +@item ADPCM MS IMA @tab X @tab X +@item ADPCM Nintendo Gamecube AFC @tab @tab X +@item ADPCM Nintendo Gamecube DTK @tab @tab X +@item ADPCM Nintendo THP @tab @tab X +@item ADPCM Playstation @tab @tab X +@item ADPCM QT IMA @tab X @tab X +@item ADPCM SEGA CRI ADX @tab X @tab X + @tab Used in Sega Dreamcast games. +@item ADPCM Shockwave Flash @tab X @tab X +@item ADPCM Sound Blaster Pro 2-bit @tab @tab X +@item ADPCM Sound Blaster Pro 2.6-bit @tab @tab X +@item ADPCM Sound Blaster Pro 4-bit @tab @tab X +@item ADPCM VIMA @tab @tab X + @tab Used in LucasArts SMUSH animations. +@item ADPCM Westwood Studios IMA @tab @tab X + @tab Used in Westwood Studios games like Command and Conquer. +@item ADPCM Yamaha @tab X @tab X +@item ADPCM Zork @tab @tab X +@item AMR-NB @tab E @tab X + @tab encoding supported through external library libopencore-amrnb +@item AMR-WB @tab E @tab X + @tab encoding supported through external library libvo-amrwbenc +@item Amazing Studio PAF Audio @tab @tab X +@item Apple lossless audio @tab X @tab X + @tab QuickTime fourcc 'alac' +@item aptX @tab X @tab X + @tab Used in Bluetooth A2DP +@item aptX HD @tab X @tab X + @tab Used in Bluetooth A2DP +@item ATRAC1 @tab @tab X +@item ATRAC3 @tab @tab X +@item ATRAC3+ @tab @tab X +@item ATRAC9 @tab @tab X +@item Bink Audio @tab @tab X + @tab Used in Bink and Smacker files in many games. +@item CELT @tab @tab E + @tab decoding supported through external library libcelt +@item codec2 @tab E @tab E + @tab en/decoding supported through external library libcodec2 +@item CRI HCA @tab @tab X +@item Delphine Software International CIN audio @tab @tab X + @tab Codec used in Delphine Software International games. +@item Digital Speech Standard - Standard Play mode (DSS SP) @tab @tab X +@item Discworld II BMV Audio @tab @tab X +@item COOK @tab @tab X + @tab All versions except 5.1 are supported. +@item DCA (DTS Coherent Acoustics) @tab X @tab X + @tab supported extensions: XCh, XXCH, X96, XBR, XLL, LBR (partially) +@item Dolby E @tab @tab X +@item DPCM Gremlin @tab @tab X +@item DPCM id RoQ @tab X @tab X + @tab Used in Quake III, Jedi Knight 2 and other computer games. +@item DPCM Interplay @tab @tab X + @tab Used in various Interplay computer games. +@item DPCM Squareroot-Delta-Exact @tab @tab X + @tab Used in various games. +@item DPCM Sierra Online @tab @tab X + @tab Used in Sierra Online game audio files. +@item DPCM Sol @tab @tab X +@item DPCM Xan @tab @tab X + @tab Used in Origin's Wing Commander IV AVI files. +@item DPCM Xilam DERF @tab @tab X +@item DSD (Direct Stream Digital), least significant bit first @tab @tab X +@item DSD (Direct Stream Digital), most significant bit first @tab @tab X +@item DSD (Direct Stream Digital), least significant bit first, planar @tab @tab X +@item DSD (Direct Stream Digital), most significant bit first, planar @tab @tab X +@item DSP Group TrueSpeech @tab @tab X +@item DST (Direct Stream Transfer) @tab @tab X +@item DV audio @tab @tab X +@item Enhanced AC-3 @tab X @tab X +@item EVRC (Enhanced Variable Rate Codec) @tab @tab X +@item FLAC (Free Lossless Audio Codec) @tab X @tab IX +@item G.723.1 @tab X @tab X +@item G.729 @tab @tab X +@item GSM @tab E @tab X + @tab encoding supported through external library libgsm +@item GSM Microsoft variant @tab E @tab X + @tab encoding supported through external library libgsm +@item IAC (Indeo Audio Coder) @tab @tab X +@item iLBC (Internet Low Bitrate Codec) @tab E @tab E + @tab encoding and decoding supported through external library libilbc +@item IMC (Intel Music Coder) @tab @tab X +@item Interplay ACM @tab @tab X +@item MACE (Macintosh Audio Compression/Expansion) 3:1 @tab @tab X +@item MACE (Macintosh Audio Compression/Expansion) 6:1 @tab @tab X +@item MLP (Meridian Lossless Packing) @tab X @tab X + @tab Used in DVD-Audio discs. +@item Monkey's Audio @tab @tab X +@item MP1 (MPEG audio layer 1) @tab @tab IX +@item MP2 (MPEG audio layer 2) @tab IX @tab IX + @tab encoding supported also through external library TwoLAME +@item MP3 (MPEG audio layer 3) @tab E @tab IX + @tab encoding supported through external library LAME, ADU MP3 and MP3onMP4 also supported +@item MPEG-4 Audio Lossless Coding (ALS) @tab @tab X +@item Musepack SV7 @tab @tab X +@item Musepack SV8 @tab @tab X +@item Nellymoser Asao @tab X @tab X +@item On2 AVC (Audio for Video Codec) @tab @tab X +@item Opus @tab E @tab X + @tab encoding supported through external library libopus +@item PCM A-law @tab X @tab X +@item PCM mu-law @tab X @tab X +@item PCM Archimedes VIDC @tab X @tab X +@item PCM signed 8-bit planar @tab X @tab X +@item PCM signed 16-bit big-endian planar @tab X @tab X +@item PCM signed 16-bit little-endian planar @tab X @tab X +@item PCM signed 24-bit little-endian planar @tab X @tab X +@item PCM signed 32-bit little-endian planar @tab X @tab X +@item PCM 32-bit floating point big-endian @tab X @tab X +@item PCM 32-bit floating point little-endian @tab X @tab X +@item PCM 64-bit floating point big-endian @tab X @tab X +@item PCM 64-bit floating point little-endian @tab X @tab X +@item PCM D-Cinema audio signed 24-bit @tab X @tab X +@item PCM signed 8-bit @tab X @tab X +@item PCM signed 16-bit big-endian @tab X @tab X +@item PCM signed 16-bit little-endian @tab X @tab X +@item PCM signed 24-bit big-endian @tab X @tab X +@item PCM signed 24-bit little-endian @tab X @tab X +@item PCM signed 32-bit big-endian @tab X @tab X +@item PCM signed 32-bit little-endian @tab X @tab X +@item PCM signed 16/20/24-bit big-endian in MPEG-TS @tab @tab X +@item PCM unsigned 8-bit @tab X @tab X +@item PCM unsigned 16-bit big-endian @tab X @tab X +@item PCM unsigned 16-bit little-endian @tab X @tab X +@item PCM unsigned 24-bit big-endian @tab X @tab X +@item PCM unsigned 24-bit little-endian @tab X @tab X +@item PCM unsigned 32-bit big-endian @tab X @tab X +@item PCM unsigned 32-bit little-endian @tab X @tab X +@item QCELP / PureVoice @tab @tab X +@item QDesign Music Codec 1 @tab @tab X +@item QDesign Music Codec 2 @tab @tab X + @tab There are still some distortions. +@item RealAudio 1.0 (14.4K) @tab X @tab X + @tab Real 14400 bit/s codec +@item RealAudio 2.0 (28.8K) @tab @tab X + @tab Real 28800 bit/s codec +@item RealAudio 3.0 (dnet) @tab IX @tab X + @tab Real low bitrate AC-3 codec +@item RealAudio Lossless @tab @tab X +@item RealAudio SIPR / ACELP.NET @tab @tab X +@item SBC (low-complexity subband codec) @tab X @tab X + @tab Used in Bluetooth A2DP +@item Shorten @tab @tab X +@item Sierra VMD audio @tab @tab X + @tab Used in Sierra VMD files. +@item Smacker audio @tab @tab X +@item SMPTE 302M AES3 audio @tab X @tab X +@item Sonic @tab X @tab X + @tab experimental codec +@item Sonic lossless @tab X @tab X + @tab experimental codec +@item Speex @tab E @tab E + @tab supported through external library libspeex +@item TAK (Tom's lossless Audio Kompressor) @tab @tab X +@item True Audio (TTA) @tab X @tab X +@item TrueHD @tab X @tab X + @tab Used in HD-DVD and Blu-Ray discs. +@item TwinVQ (VQF flavor) @tab @tab X +@item VIMA @tab @tab X + @tab Used in LucasArts SMUSH animations. +@item Vorbis @tab E @tab X + @tab A native but very primitive encoder exists. +@item Voxware MetaSound @tab @tab X +@item WavPack @tab X @tab X +@item Westwood Audio (SND1) @tab @tab X +@item Windows Media Audio 1 @tab X @tab X +@item Windows Media Audio 2 @tab X @tab X +@item Windows Media Audio Lossless @tab @tab X +@item Windows Media Audio Pro @tab @tab X +@item Windows Media Audio Voice @tab @tab X +@item Xbox Media Audio 1 @tab @tab X +@item Xbox Media Audio 2 @tab @tab X +@end multitable + +@code{X} means that the feature in that column (encoding / decoding) is supported. + +@code{E} means that support is provided through an external library. + +@code{I} means that an integer-only version is available, too (ensures high +performance on systems without hardware floating point support). + +@section Subtitle Formats + +@multitable @columnfractions .4 .1 .1 .1 .1 +@item Name @tab Muxing @tab Demuxing @tab Encoding @tab Decoding +@item 3GPP Timed Text @tab @tab @tab X @tab X +@item AQTitle @tab @tab X @tab @tab X +@item DVB @tab X @tab X @tab X @tab X +@item DVB teletext @tab @tab X @tab @tab E +@item DVD @tab X @tab X @tab X @tab X +@item JACOsub @tab X @tab X @tab @tab X +@item MicroDVD @tab X @tab X @tab @tab X +@item MPL2 @tab @tab X @tab @tab X +@item MPsub (MPlayer) @tab @tab X @tab @tab X +@item PGS @tab @tab @tab @tab X +@item PJS (Phoenix) @tab @tab X @tab @tab X +@item RealText @tab @tab X @tab @tab X +@item SAMI @tab @tab X @tab @tab X +@item Spruce format (STL) @tab @tab X @tab @tab X +@item SSA/ASS @tab X @tab X @tab X @tab X +@item SubRip (SRT) @tab X @tab X @tab X @tab X +@item SubViewer v1 @tab @tab X @tab @tab X +@item SubViewer @tab @tab X @tab @tab X +@item TED Talks captions @tab @tab X @tab @tab X +@item TTML @tab X @tab @tab X @tab +@item VobSub (IDX+SUB) @tab @tab X @tab @tab X +@item VPlayer @tab @tab X @tab @tab X +@item WebVTT @tab X @tab X @tab X @tab X +@item XSUB @tab @tab @tab X @tab X +@end multitable + +@code{X} means that the feature is supported. + +@code{E} means that support is provided through an external library. + +@section Network Protocols + +@multitable @columnfractions .4 .1 +@item Name @tab Support +@item AMQP @tab E +@item file @tab X +@item FTP @tab X +@item Gopher @tab X +@item Gophers @tab X +@item HLS @tab X +@item HTTP @tab X +@item HTTPS @tab X +@item Icecast @tab X +@item MMSH @tab X +@item MMST @tab X +@item pipe @tab X +@item Pro-MPEG FEC @tab X +@item RTMP @tab X +@item RTMPE @tab X +@item RTMPS @tab X +@item RTMPT @tab X +@item RTMPTE @tab X +@item RTMPTS @tab X +@item RTP @tab X +@item SAMBA @tab E +@item SCTP @tab X +@item SFTP @tab E +@item TCP @tab X +@item TLS @tab X +@item UDP @tab X +@item ZMQ @tab E +@end multitable + +@code{X} means that the protocol is supported. + +@code{E} means that support is provided through an external library. + + +@section Input/Output Devices + +@multitable @columnfractions .4 .1 .1 +@item Name @tab Input @tab Output +@item ALSA @tab X @tab X +@item BKTR @tab X @tab +@item caca @tab @tab X +@item DV1394 @tab X @tab +@item Lavfi virtual device @tab X @tab +@item Linux framebuffer @tab X @tab X +@item JACK @tab X @tab +@item LIBCDIO @tab X +@item LIBDC1394 @tab X @tab +@item OpenAL @tab X +@item OpenGL @tab @tab X +@item OSS @tab X @tab X +@item PulseAudio @tab X @tab X +@item SDL @tab @tab X +@item Video4Linux2 @tab X @tab X +@item VfW capture @tab X @tab +@item X11 grabbing @tab X @tab +@item Win32 grabbing @tab X @tab +@end multitable + +@code{X} means that input/output is supported. + +@section Timecode + +@multitable @columnfractions .4 .1 .1 +@item Codec/format @tab Read @tab Write +@item AVI @tab X @tab X +@item DV @tab X @tab X +@item GXF @tab X @tab X +@item MOV @tab X @tab X +@item MPEG1/2 @tab X @tab X +@item MXF @tab X @tab X +@end multitable diff -Nru ffmpeg-4.2.2/doc/general.texi ffmpeg-4.4/doc/general.texi --- ffmpeg-4.2.2/doc/general.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/general.texi 2021-04-08 21:28:39.000000000 +0000 @@ -10,1368 +10,6 @@ @contents -@chapter External libraries - -FFmpeg can be hooked up with a number of external libraries to add support -for more formats. None of them are used by default, their use has to be -explicitly requested by passing the appropriate flags to -@command{./configure}. - -@section Alliance for Open Media (AOM) - -FFmpeg can make use of the AOM library for AV1 decoding and encoding. - -Go to @url{http://aomedia.org/} and follow the instructions for -installing the library. Then pass @code{--enable-libaom} to configure to -enable it. - -@section AMD AMF/VCE - -FFmpeg can use the AMD Advanced Media Framework library under Windows -for accelerated H.264 and HEVC encoding on hardware with Video Coding Engine (VCE). - -To enable support you must obtain the AMF framework header files from -@url{https://github.com/GPUOpen-LibrariesAndSDKs/AMF.git}. - -Create an @code{AMF/} directory in the system include path. -Copy the contents of @code{AMF/amf/public/include/} into that directory. -Then configure FFmpeg with @code{--enable-amf}. - -@section AviSynth - -FFmpeg can read AviSynth scripts as input. To enable support, pass -@code{--enable-avisynth} to configure. The correct headers are -included in compat/avisynth/, which allows the user to enable support -without needing to search for these headers themselves. - -For Windows, supported AviSynth variants are -@url{http://avisynth.nl, AviSynth 2.6 RC1 or higher} for 32-bit builds and -@url{http://avisynth.nl/index.php/AviSynth+, AviSynth+ r1718 or higher} for 32-bit and 64-bit builds. - -For Linux and OS X, the supported AviSynth variant is -@url{https://github.com/avxsynth/avxsynth, AvxSynth}. - -@float NOTE -In 2016, AviSynth+ added support for building with GCC. However, due to -the eccentricities of Windows' calling conventions, 32-bit GCC builds -of AviSynth+ are not compatible with typical 32-bit builds of FFmpeg. - -By default, FFmpeg assumes compatibility with 32-bit MSVC builds of -AviSynth+ since that is the most widely-used and entrenched build -configuration. Users can override this and enable support for 32-bit -GCC builds of AviSynth+ by passing @code{-DAVSC_WIN32_GCC32} to -@code{--extra-cflags} when configuring FFmpeg. - -64-bit builds of FFmpeg are not affected, and can use either MSVC or -GCC builds of AviSynth+ without any special flags. -@end float - -@float NOTE -AviSynth and AvxSynth are loaded dynamically. Distributors can build FFmpeg -with @code{--enable-avisynth}, and the binaries will work regardless of the -end user having AviSynth or AvxSynth installed - they'll only need to be -installed to use AviSynth scripts (obviously). -@end float - -@section Chromaprint - -FFmpeg can make use of the Chromaprint library for generating audio fingerprints. -Pass @code{--enable-chromaprint} to configure to -enable it. See @url{https://acoustid.org/chromaprint}. - -@section codec2 - -FFmpeg can make use of the codec2 library for codec2 decoding and encoding. -There is currently no native decoder, so libcodec2 must be used for decoding. - -Go to @url{http://freedv.org/}, download "Codec 2 source archive". -Build and install using CMake. Debian users can install the libcodec2-dev package instead. -Once libcodec2 is installed you can pass @code{--enable-libcodec2} to configure to enable it. - -The easiest way to use codec2 is with .c2 files, since they contain the mode information required for decoding. -To encode such a file, use a .c2 file extension and give the libcodec2 encoder the -mode option: -@code{ffmpeg -i input.wav -mode 700C output.c2}. -Playback is as simple as @code{ffplay output.c2}. -For a list of supported modes, run @code{ffmpeg -h encoder=libcodec2}. -Raw codec2 files are also supported. -To make sense of them the mode in use needs to be specified as a format option: -@code{ffmpeg -f codec2raw -mode 1300 -i input.raw output.wav}. - -@section dav1d - -FFmpeg can make use of the dav1d library for AV1 video decoding. - -Go to @url{https://code.videolan.org/videolan/dav1d} and follow the instructions for -installing the library. Then pass @code{--enable-libdav1d} to configure to enable it. - -@section davs2 - -FFmpeg can make use of the davs2 library for AVS2-P2/IEEE1857.4 video decoding. - -Go to @url{https://github.com/pkuvcl/davs2} and follow the instructions for -installing the library. Then pass @code{--enable-libdavs2} to configure to -enable it. - -@float NOTE -libdavs2 is under the GNU Public License Version 2 or later -(see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for -details), you must upgrade FFmpeg's license to GPL in order to use it. -@end float - -@section Game Music Emu - -FFmpeg can make use of the Game Music Emu library to read audio from supported video game -music file formats. Pass @code{--enable-libgme} to configure to -enable it. See @url{https://bitbucket.org/mpyne/game-music-emu/overview}. - -@section Intel QuickSync Video - -FFmpeg can use Intel QuickSync Video (QSV) for accelerated decoding and encoding -of multiple codecs. To use QSV, FFmpeg must be linked against the @code{libmfx} -dispatcher, which loads the actual decoding libraries. - -The dispatcher is open source and can be downloaded from -@url{https://github.com/lu-zero/mfx_dispatch.git}. FFmpeg needs to be configured -with the @code{--enable-libmfx} option and @code{pkg-config} needs to be able to -locate the dispatcher's @code{.pc} files. - -@section Kvazaar - -FFmpeg can make use of the Kvazaar library for HEVC encoding. - -Go to @url{https://github.com/ultravideo/kvazaar} and follow the -instructions for installing the library. Then pass -@code{--enable-libkvazaar} to configure to enable it. - -@section LAME - -FFmpeg can make use of the LAME library for MP3 encoding. - -Go to @url{http://lame.sourceforge.net/} and follow the -instructions for installing the library. -Then pass @code{--enable-libmp3lame} to configure to enable it. - -@section libilbc - -iLBC is a narrowband speech codec that has been made freely available -by Google as part of the WebRTC project. libilbc is a packaging friendly -copy of the iLBC codec. FFmpeg can make use of the libilbc library for -iLBC decoding and encoding. - -Go to @url{https://github.com/TimothyGu/libilbc} and follow the instructions for -installing the library. Then pass @code{--enable-libilbc} to configure to -enable it. - -@section libvpx - -FFmpeg can make use of the libvpx library for VP8/VP9 decoding and encoding. - -Go to @url{http://www.webmproject.org/} and follow the instructions for -installing the library. Then pass @code{--enable-libvpx} to configure to -enable it. - -@section ModPlug - -FFmpeg can make use of this library, originating in Modplug-XMMS, to read from MOD-like music files. -See @url{https://github.com/Konstanty/libmodplug}. Pass @code{--enable-libmodplug} to configure to -enable it. - -@section OpenCORE, VisualOn, and Fraunhofer libraries - -Spun off Google Android sources, OpenCore, VisualOn and Fraunhofer -libraries provide encoders for a number of audio codecs. - -@float NOTE -OpenCORE and VisualOn libraries are under the Apache License 2.0 -(see @url{http://www.apache.org/licenses/LICENSE-2.0} for details), which is -incompatible to the LGPL version 2.1 and GPL version 2. You have to -upgrade FFmpeg's license to LGPL version 3 (or if you have enabled -GPL components, GPL version 3) by passing @code{--enable-version3} to configure in -order to use it. - -The license of the Fraunhofer AAC library is incompatible with the GPL. -Therefore, for GPL builds, you have to pass @code{--enable-nonfree} to -configure in order to use it. To the best of our knowledge, it is -compatible with the LGPL. -@end float - -@subsection OpenCORE AMR - -FFmpeg can make use of the OpenCORE libraries for AMR-NB -decoding/encoding and AMR-WB decoding. - -Go to @url{http://sourceforge.net/projects/opencore-amr/} and follow the -instructions for installing the libraries. -Then pass @code{--enable-libopencore-amrnb} and/or -@code{--enable-libopencore-amrwb} to configure to enable them. - -@subsection VisualOn AMR-WB encoder library - -FFmpeg can make use of the VisualOn AMR-WBenc library for AMR-WB encoding. - -Go to @url{http://sourceforge.net/projects/opencore-amr/} and follow the -instructions for installing the library. -Then pass @code{--enable-libvo-amrwbenc} to configure to enable it. - -@subsection Fraunhofer AAC library - -FFmpeg can make use of the Fraunhofer AAC library for AAC decoding & encoding. - -Go to @url{http://sourceforge.net/projects/opencore-amr/} and follow the -instructions for installing the library. -Then pass @code{--enable-libfdk-aac} to configure to enable it. - -@section OpenH264 - -FFmpeg can make use of the OpenH264 library for H.264 decoding and encoding. - -Go to @url{http://www.openh264.org/} and follow the instructions for -installing the library. Then pass @code{--enable-libopenh264} to configure to -enable it. - -For decoding, this library is much more limited than the built-in decoder -in libavcodec; currently, this library lacks support for decoding B-frames -and some other main/high profile features. (It currently only supports -constrained baseline profile and CABAC.) Using it is mostly useful for -testing and for taking advantage of Cisco's patent portfolio license -(@url{http://www.openh264.org/BINARY_LICENSE.txt}). - -@section OpenJPEG - -FFmpeg can use the OpenJPEG libraries for decoding/encoding J2K videos. Go to -@url{http://www.openjpeg.org/} to get the libraries and follow the installation -instructions. To enable using OpenJPEG in FFmpeg, pass @code{--enable-libopenjpeg} to -@file{./configure}. - -@section TwoLAME - -FFmpeg can make use of the TwoLAME library for MP2 encoding. - -Go to @url{http://www.twolame.org/} and follow the -instructions for installing the library. -Then pass @code{--enable-libtwolame} to configure to enable it. - -@section VapourSynth - -FFmpeg can read VapourSynth scripts as input. To enable support, pass -@code{--enable-vapoursynth} to configure. Vapoursynth is detected via -@code{pkg-config}. Versions 42 or greater supported. -See @url{http://www.vapoursynth.com/}. - -Due to security concerns, Vapoursynth scripts will not -be autodetected so the input format has to be forced. For ff* CLI tools, -add @code{-f vapoursynth} before the input @code{-i yourscript.vpy}. - -@section WavPack - -FFmpeg can make use of the libwavpack library for WavPack encoding. - -Go to @url{http://www.wavpack.com/} and follow the instructions for -installing the library. Then pass @code{--enable-libwavpack} to configure to -enable it. - -@section x264 - -FFmpeg can make use of the x264 library for H.264 encoding. - -Go to @url{http://www.videolan.org/developers/x264.html} and follow the -instructions for installing the library. Then pass @code{--enable-libx264} to -configure to enable it. - -@float NOTE -x264 is under the GNU Public License Version 2 or later -(see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for -details), you must upgrade FFmpeg's license to GPL in order to use it. -@end float - -@section x265 - -FFmpeg can make use of the x265 library for HEVC encoding. - -Go to @url{http://x265.org/developers.html} and follow the instructions -for installing the library. Then pass @code{--enable-libx265} to configure -to enable it. - -@float NOTE -x265 is under the GNU Public License Version 2 or later -(see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for -details), you must upgrade FFmpeg's license to GPL in order to use it. -@end float - -@section xavs - -FFmpeg can make use of the xavs library for AVS encoding. - -Go to @url{http://xavs.sf.net/} and follow the instructions for -installing the library. Then pass @code{--enable-libxavs} to configure to -enable it. - -@section xavs2 - -FFmpeg can make use of the xavs2 library for AVS2-P2/IEEE1857.4 video encoding. - -Go to @url{https://github.com/pkuvcl/xavs2} and follow the instructions for -installing the library. Then pass @code{--enable-libxavs2} to configure to -enable it. - -@float NOTE -libxavs2 is under the GNU Public License Version 2 or later -(see @url{http://www.gnu.org/licenses/old-licenses/gpl-2.0.html} for -details), you must upgrade FFmpeg's license to GPL in order to use it. -@end float - -@section ZVBI - -ZVBI is a VBI decoding library which can be used by FFmpeg to decode DVB -teletext pages and DVB teletext subtitles. - -Go to @url{http://sourceforge.net/projects/zapping/} and follow the instructions for -installing the library. Then pass @code{--enable-libzvbi} to configure to -enable it. - -@chapter Supported File Formats, Codecs or Features - -You can use the @code{-formats} and @code{-codecs} options to have an exhaustive list. - -@section File Formats - -FFmpeg supports the following file formats through the @code{libavformat} -library: - -@multitable @columnfractions .4 .1 .1 .4 -@item Name @tab Encoding @tab Decoding @tab Comments -@item 3dostr @tab @tab X -@item 4xm @tab @tab X - @tab 4X Technologies format, used in some games. -@item 8088flex TMV @tab @tab X -@item AAX @tab @tab X - @tab Audible Enhanced Audio format, used in audiobooks. -@item AA @tab @tab X - @tab Audible Format 2, 3, and 4, used in audiobooks. -@item ACT Voice @tab @tab X - @tab contains G.729 audio -@item Adobe Filmstrip @tab X @tab X -@item Audio IFF (AIFF) @tab X @tab X -@item American Laser Games MM @tab @tab X - @tab Multimedia format used in games like Mad Dog McCree. -@item 3GPP AMR @tab X @tab X -@item Amazing Studio Packed Animation File @tab @tab X - @tab Multimedia format used in game Heart Of Darkness. -@item Apple HTTP Live Streaming @tab @tab X -@item Artworx Data Format @tab @tab X -@item Interplay ACM @tab @tab X - @tab Audio only format used in some Interplay games. -@item ADP @tab @tab X - @tab Audio format used on the Nintendo Gamecube. -@item AFC @tab @tab X - @tab Audio format used on the Nintendo Gamecube. -@item ADS/SS2 @tab @tab X - @tab Audio format used on the PS2. -@item APNG @tab X @tab X -@item ASF @tab X @tab X -@item AST @tab X @tab X - @tab Audio format used on the Nintendo Wii. -@item AVI @tab X @tab X -@item AviSynth @tab @tab X -@item AVR @tab @tab X - @tab Audio format used on Mac. -@item AVS @tab @tab X - @tab Multimedia format used by the Creature Shock game. -@item Beam Software SIFF @tab @tab X - @tab Audio and video format used in some games by Beam Software. -@item Bethesda Softworks VID @tab @tab X - @tab Used in some games from Bethesda Softworks. -@item Binary text @tab @tab X -@item Bink @tab @tab X - @tab Multimedia format used by many games. -@item Bitmap Brothers JV @tab @tab X - @tab Used in Z and Z95 games. -@item Brute Force & Ignorance @tab @tab X - @tab Used in the game Flash Traffic: City of Angels. -@item BFSTM @tab @tab X - @tab Audio format used on the Nintendo WiiU (based on BRSTM). -@item BRSTM @tab @tab X - @tab Audio format used on the Nintendo Wii. -@item BWF @tab X @tab X -@item codec2 (raw) @tab X @tab X - @tab Must be given -mode format option to decode correctly. -@item codec2 (.c2 files) @tab X @tab X - @tab Contains header with version and mode info, simplifying playback. -@item CRI ADX @tab X @tab X - @tab Audio-only format used in console video games. -@item Discworld II BMV @tab @tab X -@item Interplay C93 @tab @tab X - @tab Used in the game Cyberia from Interplay. -@item Delphine Software International CIN @tab @tab X - @tab Multimedia format used by Delphine Software games. -@item Digital Speech Standard (DSS) @tab @tab X -@item Canopus HQ @tab @tab X -@item Canopus HQA @tab @tab X -@item Canopus HQX @tab @tab X -@item CD+G @tab @tab X - @tab Video format used by CD+G karaoke disks -@item Phantom Cine @tab @tab X -@item Cineform HD @tab @tab X -@item Commodore CDXL @tab @tab X - @tab Amiga CD video format -@item Core Audio Format @tab X @tab X - @tab Apple Core Audio Format -@item CRC testing format @tab X @tab -@item Creative Voice @tab X @tab X - @tab Created for the Sound Blaster Pro. -@item CRYO APC @tab @tab X - @tab Audio format used in some games by CRYO Interactive Entertainment. -@item D-Cinema audio @tab X @tab X -@item Deluxe Paint Animation @tab @tab X -@item DCSTR @tab @tab X -@item DFA @tab @tab X - @tab This format is used in Chronomaster game -@item DirectDraw Surface @tab @tab X -@item DSD Stream File (DSF) @tab @tab X -@item DV video @tab X @tab X -@item DXA @tab @tab X - @tab This format is used in the non-Windows version of the Feeble Files - game and different game cutscenes repacked for use with ScummVM. -@item Electronic Arts cdata @tab @tab X -@item Electronic Arts Multimedia @tab @tab X - @tab Used in various EA games; files have extensions like WVE and UV2. -@item Ensoniq Paris Audio File @tab @tab X -@item FFM (FFserver live feed) @tab X @tab X -@item Flash (SWF) @tab X @tab X -@item Flash 9 (AVM2) @tab X @tab X - @tab Only embedded audio is decoded. -@item FLI/FLC/FLX animation @tab @tab X - @tab .fli/.flc files -@item Flash Video (FLV) @tab X @tab X - @tab Macromedia Flash video files -@item framecrc testing format @tab X @tab -@item FunCom ISS @tab @tab X - @tab Audio format used in various games from FunCom like The Longest Journey. -@item G.723.1 @tab X @tab X -@item G.726 @tab @tab X @tab Both left- and right-justified. -@item G.729 BIT @tab X @tab X -@item G.729 raw @tab @tab X -@item GENH @tab @tab X - @tab Audio format for various games. -@item GIF Animation @tab X @tab X -@item GXF @tab X @tab X - @tab General eXchange Format SMPTE 360M, used by Thomson Grass Valley - playout servers. -@item HNM @tab @tab X - @tab Only version 4 supported, used in some games from Cryo Interactive -@item iCEDraw File @tab @tab X -@item ICO @tab X @tab X - @tab Microsoft Windows ICO -@item id Quake II CIN video @tab @tab X -@item id RoQ @tab X @tab X - @tab Used in Quake III, Jedi Knight 2 and other computer games. -@item IEC61937 encapsulation @tab X @tab X -@item IFF @tab @tab X - @tab Interchange File Format -@item IFV @tab @tab X - @tab A format used by some old CCTV DVRs. -@item iLBC @tab X @tab X -@item Interplay MVE @tab @tab X - @tab Format used in various Interplay computer games. -@item Iterated Systems ClearVideo @tab @tab X - @tab I-frames only -@item IV8 @tab @tab X - @tab A format generated by IndigoVision 8000 video server. -@item IVF (On2) @tab X @tab X - @tab A format used by libvpx -@item Internet Video Recording @tab @tab X -@item IRCAM @tab X @tab X -@item LATM @tab X @tab X -@item LMLM4 @tab @tab X - @tab Used by Linux Media Labs MPEG-4 PCI boards -@item LOAS @tab @tab X - @tab contains LATM multiplexed AAC audio -@item LRC @tab X @tab X -@item LVF @tab @tab X -@item LXF @tab @tab X - @tab VR native stream format, used by Leitch/Harris' video servers. -@item Magic Lantern Video (MLV) @tab @tab X -@item Matroska @tab X @tab X -@item Matroska audio @tab X @tab -@item FFmpeg metadata @tab X @tab X - @tab Metadata in text format. -@item MAXIS XA @tab @tab X - @tab Used in Sim City 3000; file extension .xa. -@item MD Studio @tab @tab X -@item Metal Gear Solid: The Twin Snakes @tab @tab X -@item Megalux Frame @tab @tab X - @tab Used by Megalux Ultimate Paint -@item Mobotix .mxg @tab @tab X -@item Monkey's Audio @tab @tab X -@item Motion Pixels MVI @tab @tab X -@item MOV/QuickTime/MP4 @tab X @tab X - @tab 3GP, 3GP2, PSP, iPod variants supported -@item MP2 @tab X @tab X -@item MP3 @tab X @tab X -@item MPEG-1 System @tab X @tab X - @tab muxed audio and video, VCD format supported -@item MPEG-PS (program stream) @tab X @tab X - @tab also known as @code{VOB} file, SVCD and DVD format supported -@item MPEG-TS (transport stream) @tab X @tab X - @tab also known as DVB Transport Stream -@item MPEG-4 @tab X @tab X - @tab MPEG-4 is a variant of QuickTime. -@item MSF @tab @tab X - @tab Audio format used on the PS3. -@item Mirillis FIC video @tab @tab X - @tab No cursor rendering. -@item MIDI Sample Dump Standard @tab @tab X -@item MIME multipart JPEG @tab X @tab -@item MSN TCP webcam @tab @tab X - @tab Used by MSN Messenger webcam streams. -@item MTV @tab @tab X -@item Musepack @tab @tab X -@item Musepack SV8 @tab @tab X -@item Material eXchange Format (MXF) @tab X @tab X - @tab SMPTE 377M, used by D-Cinema, broadcast industry. -@item Material eXchange Format (MXF), D-10 Mapping @tab X @tab X - @tab SMPTE 386M, D-10/IMX Mapping. -@item NC camera feed @tab @tab X - @tab NC (AVIP NC4600) camera streams -@item NIST SPeech HEader REsources @tab @tab X -@item Computerized Speech Lab NSP @tab @tab X -@item NTT TwinVQ (VQF) @tab @tab X - @tab Nippon Telegraph and Telephone Corporation TwinVQ. -@item Nullsoft Streaming Video @tab @tab X -@item NuppelVideo @tab @tab X -@item NUT @tab X @tab X - @tab NUT Open Container Format -@item Ogg @tab X @tab X -@item Playstation Portable PMP @tab @tab X -@item Portable Voice Format @tab @tab X -@item TechnoTrend PVA @tab @tab X - @tab Used by TechnoTrend DVB PCI boards. -@item QCP @tab @tab X -@item raw ADTS (AAC) @tab X @tab X -@item raw AC-3 @tab X @tab X -@item raw AMR-NB @tab @tab X -@item raw AMR-WB @tab @tab X -@item raw aptX @tab X @tab X -@item raw aptX HD @tab X @tab X -@item raw Chinese AVS video @tab X @tab X -@item raw CRI ADX @tab X @tab X -@item raw Dirac @tab X @tab X -@item raw DNxHD @tab X @tab X -@item raw DTS @tab X @tab X -@item raw DTS-HD @tab @tab X -@item raw E-AC-3 @tab X @tab X -@item raw FLAC @tab X @tab X -@item raw GSM @tab @tab X -@item raw H.261 @tab X @tab X -@item raw H.263 @tab X @tab X -@item raw H.264 @tab X @tab X -@item raw HEVC @tab X @tab X -@item raw Ingenient MJPEG @tab @tab X -@item raw MJPEG @tab X @tab X -@item raw MLP @tab @tab X -@item raw MPEG @tab @tab X -@item raw MPEG-1 @tab @tab X -@item raw MPEG-2 @tab @tab X -@item raw MPEG-4 @tab X @tab X -@item raw NULL @tab X @tab -@item raw video @tab X @tab X -@item raw id RoQ @tab X @tab -@item raw SBC @tab X @tab X -@item raw Shorten @tab @tab X -@item raw TAK @tab @tab X -@item raw TrueHD @tab X @tab X -@item raw VC-1 @tab X @tab X -@item raw PCM A-law @tab X @tab X -@item raw PCM mu-law @tab X @tab X -@item raw PCM Archimedes VIDC @tab X @tab X -@item raw PCM signed 8 bit @tab X @tab X -@item raw PCM signed 16 bit big-endian @tab X @tab X -@item raw PCM signed 16 bit little-endian @tab X @tab X -@item raw PCM signed 24 bit big-endian @tab X @tab X -@item raw PCM signed 24 bit little-endian @tab X @tab X -@item raw PCM signed 32 bit big-endian @tab X @tab X -@item raw PCM signed 32 bit little-endian @tab X @tab X -@item raw PCM signed 64 bit big-endian @tab X @tab X -@item raw PCM signed 64 bit little-endian @tab X @tab X -@item raw PCM unsigned 8 bit @tab X @tab X -@item raw PCM unsigned 16 bit big-endian @tab X @tab X -@item raw PCM unsigned 16 bit little-endian @tab X @tab X -@item raw PCM unsigned 24 bit big-endian @tab X @tab X -@item raw PCM unsigned 24 bit little-endian @tab X @tab X -@item raw PCM unsigned 32 bit big-endian @tab X @tab X -@item raw PCM unsigned 32 bit little-endian @tab X @tab X -@item raw PCM 16.8 floating point little-endian @tab @tab X -@item raw PCM 24.0 floating point little-endian @tab @tab X -@item raw PCM floating-point 32 bit big-endian @tab X @tab X -@item raw PCM floating-point 32 bit little-endian @tab X @tab X -@item raw PCM floating-point 64 bit big-endian @tab X @tab X -@item raw PCM floating-point 64 bit little-endian @tab X @tab X -@item RDT @tab @tab X -@item REDCODE R3D @tab @tab X - @tab File format used by RED Digital cameras, contains JPEG 2000 frames and PCM audio. -@item RealMedia @tab X @tab X -@item Redirector @tab @tab X -@item RedSpark @tab @tab X -@item Renderware TeXture Dictionary @tab @tab X -@item Resolume DXV @tab @tab X -@item RL2 @tab @tab X - @tab Audio and video format used in some games by Entertainment Software Partners. -@item RPL/ARMovie @tab @tab X -@item Lego Mindstorms RSO @tab X @tab X -@item RSD @tab @tab X -@item RTMP @tab X @tab X - @tab Output is performed by publishing stream to RTMP server -@item RTP @tab X @tab X -@item RTSP @tab X @tab X -@item Sample Dump eXchange @tab @tab X -@item SAP @tab X @tab X -@item SBG @tab @tab X -@item SDP @tab @tab X -@item SER @tab @tab X -@item Sega FILM/CPK @tab X @tab X - @tab Used in many Sega Saturn console games. -@item Silicon Graphics Movie @tab @tab X -@item Sierra SOL @tab @tab X - @tab .sol files used in Sierra Online games. -@item Sierra VMD @tab @tab X - @tab Used in Sierra CD-ROM games. -@item Smacker @tab @tab X - @tab Multimedia format used by many games. -@item SMJPEG @tab X @tab X - @tab Used in certain Loki game ports. -@item SMPTE 337M encapsulation @tab @tab X -@item Smush @tab @tab X - @tab Multimedia format used in some LucasArts games. -@item Sony OpenMG (OMA) @tab X @tab X - @tab Audio format used in Sony Sonic Stage and Sony Vegas. -@item Sony PlayStation STR @tab @tab X -@item Sony Wave64 (W64) @tab X @tab X -@item SoX native format @tab X @tab X -@item SUN AU format @tab X @tab X -@item SUP raw PGS subtitles @tab X @tab X -@item SVAG @tab @tab X - @tab Audio format used in Konami PS2 games. -@item TDSC @tab @tab X -@item Text files @tab @tab X -@item THP @tab @tab X - @tab Used on the Nintendo GameCube. -@item Tiertex Limited SEQ @tab @tab X - @tab Tiertex .seq files used in the DOS CD-ROM version of the game Flashback. -@item True Audio @tab X @tab X -@item VAG @tab @tab X - @tab Audio format used in many Sony PS2 games. -@item VC-1 test bitstream @tab X @tab X -@item Vidvox Hap @tab X @tab X -@item Vivo @tab @tab X -@item VPK @tab @tab X - @tab Audio format used in Sony PS games. -@item WAV @tab X @tab X -@item WavPack @tab X @tab X -@item WebM @tab X @tab X -@item Windows Televison (WTV) @tab X @tab X -@item Wing Commander III movie @tab @tab X - @tab Multimedia format used in Origin's Wing Commander III computer game. -@item Westwood Studios audio @tab @tab X - @tab Multimedia format used in Westwood Studios games. -@item Westwood Studios VQA @tab @tab X - @tab Multimedia format used in Westwood Studios games. -@item Wideband Single-bit Data (WSD) @tab @tab X -@item WVE @tab @tab X -@item XMV @tab @tab X - @tab Microsoft video container used in Xbox games. -@item XVAG @tab @tab X - @tab Audio format used on the PS3. -@item xWMA @tab @tab X - @tab Microsoft audio container used by XAudio 2. -@item eXtended BINary text (XBIN) @tab @tab X -@item YUV4MPEG pipe @tab X @tab X -@item Psygnosis YOP @tab @tab X -@end multitable - -@code{X} means that the feature in that column (encoding / decoding) is supported. - -@section Image Formats - -FFmpeg can read and write images for each frame of a video sequence. The -following image formats are supported: - -@multitable @columnfractions .4 .1 .1 .4 -@item Name @tab Encoding @tab Decoding @tab Comments -@item .Y.U.V @tab X @tab X - @tab one raw file per component -@item Alias PIX @tab X @tab X - @tab Alias/Wavefront PIX image format -@item animated GIF @tab X @tab X -@item APNG @tab X @tab X -@item BMP @tab X @tab X - @tab Microsoft BMP image -@item BRender PIX @tab @tab X - @tab Argonaut BRender 3D engine image format. -@item DPX @tab X @tab X - @tab Digital Picture Exchange -@item EXR @tab @tab X - @tab OpenEXR -@item FITS @tab X @tab X - @tab Flexible Image Transport System -@item JPEG @tab X @tab X - @tab Progressive JPEG is not supported. -@item JPEG 2000 @tab X @tab X -@item JPEG-LS @tab X @tab X -@item LJPEG @tab X @tab - @tab Lossless JPEG -@item PAM @tab X @tab X - @tab PAM is a PNM extension with alpha support. -@item PBM @tab X @tab X - @tab Portable BitMap image -@item PCX @tab X @tab X - @tab PC Paintbrush -@item PGM @tab X @tab X - @tab Portable GrayMap image -@item PGMYUV @tab X @tab X - @tab PGM with U and V components in YUV 4:2:0 -@item PIC @tab @tab X - @tab Pictor/PC Paint -@item PNG @tab X @tab X -@item PPM @tab X @tab X - @tab Portable PixelMap image -@item PSD @tab @tab X - @tab Photoshop -@item PTX @tab @tab X - @tab V.Flash PTX format -@item SGI @tab X @tab X - @tab SGI RGB image format -@item Sun Rasterfile @tab X @tab X - @tab Sun RAS image format -@item TIFF @tab X @tab X - @tab YUV, JPEG and some extension is not supported yet. -@item Truevision Targa @tab X @tab X - @tab Targa (.TGA) image format -@item WebP @tab E @tab X - @tab WebP image format, encoding supported through external library libwebp -@item XBM @tab X @tab X - @tab X BitMap image format -@item XFace @tab X @tab X - @tab X-Face image format -@item XPM @tab @tab X - @tab X PixMap image format -@item XWD @tab X @tab X - @tab X Window Dump image format -@end multitable - -@code{X} means that the feature in that column (encoding / decoding) is supported. - -@code{E} means that support is provided through an external library. - -@section Video Codecs - -@multitable @columnfractions .4 .1 .1 .4 -@item Name @tab Encoding @tab Decoding @tab Comments -@item 4X Movie @tab @tab X - @tab Used in certain computer games. -@item 8088flex TMV @tab @tab X -@item A64 multicolor @tab X @tab - @tab Creates video suitable to be played on a commodore 64 (multicolor mode). -@item Amazing Studio PAF Video @tab @tab X -@item American Laser Games MM @tab @tab X - @tab Used in games like Mad Dog McCree. -@item AMV Video @tab X @tab X - @tab Used in Chinese MP3 players. -@item ANSI/ASCII art @tab @tab X -@item Apple Intermediate Codec @tab @tab X -@item Apple MJPEG-B @tab @tab X -@item Apple Pixlet @tab @tab X -@item Apple ProRes @tab X @tab X -@item Apple QuickDraw @tab @tab X - @tab fourcc: qdrw -@item Asus v1 @tab X @tab X - @tab fourcc: ASV1 -@item Asus v2 @tab X @tab X - @tab fourcc: ASV2 -@item ATI VCR1 @tab @tab X - @tab fourcc: VCR1 -@item ATI VCR2 @tab @tab X - @tab fourcc: VCR2 -@item Auravision Aura @tab @tab X -@item Auravision Aura 2 @tab @tab X -@item Autodesk Animator Flic video @tab @tab X -@item Autodesk RLE @tab @tab X - @tab fourcc: AASC -@item AV1 @tab E @tab E - @tab Supported through external libraries libaom and libdav1d -@item Avid 1:1 10-bit RGB Packer @tab X @tab X - @tab fourcc: AVrp -@item AVS (Audio Video Standard) video @tab @tab X - @tab Video encoding used by the Creature Shock game. -@item AYUV @tab X @tab X - @tab Microsoft uncompressed packed 4:4:4:4 -@item Beam Software VB @tab @tab X -@item Bethesda VID video @tab @tab X - @tab Used in some games from Bethesda Softworks. -@item Bink Video @tab @tab X -@item BitJazz SheerVideo @tab @tab X -@item Bitmap Brothers JV video @tab @tab X -@item y41p Brooktree uncompressed 4:1:1 12-bit @tab X @tab X -@item Brute Force & Ignorance @tab @tab X - @tab Used in the game Flash Traffic: City of Angels. -@item C93 video @tab @tab X - @tab Codec used in Cyberia game. -@item CamStudio @tab @tab X - @tab fourcc: CSCD -@item CD+G @tab @tab X - @tab Video codec for CD+G karaoke disks -@item CDXL @tab @tab X - @tab Amiga CD video codec -@item Chinese AVS video @tab E @tab X - @tab AVS1-P2, JiZhun profile, encoding through external library libxavs -@item Delphine Software International CIN video @tab @tab X - @tab Codec used in Delphine Software International games. -@item Discworld II BMV Video @tab @tab X -@item Canopus Lossless Codec @tab @tab X -@item Cinepak @tab @tab X -@item Cirrus Logic AccuPak @tab X @tab X - @tab fourcc: CLJR -@item CPiA Video Format @tab @tab X -@item Creative YUV (CYUV) @tab @tab X -@item DFA @tab @tab X - @tab Codec used in Chronomaster game. -@item Dirac @tab E @tab X - @tab supported though the native vc2 (Dirac Pro) encoder -@item Deluxe Paint Animation @tab @tab X -@item DNxHD @tab X @tab X - @tab aka SMPTE VC3 -@item Duck TrueMotion 1.0 @tab @tab X - @tab fourcc: DUCK -@item Duck TrueMotion 2.0 @tab @tab X - @tab fourcc: TM20 -@item Duck TrueMotion 2.0 RT @tab @tab X - @tab fourcc: TR20 -@item DV (Digital Video) @tab X @tab X -@item Dxtory capture format @tab @tab X -@item Feeble Files/ScummVM DXA @tab @tab X - @tab Codec originally used in Feeble Files game. -@item Electronic Arts CMV video @tab @tab X - @tab Used in NHL 95 game. -@item Electronic Arts Madcow video @tab @tab X -@item Electronic Arts TGV video @tab @tab X -@item Electronic Arts TGQ video @tab @tab X -@item Electronic Arts TQI video @tab @tab X -@item Escape 124 @tab @tab X -@item Escape 130 @tab @tab X -@item FFmpeg video codec #1 @tab X @tab X - @tab lossless codec (fourcc: FFV1) -@item Flash Screen Video v1 @tab X @tab X - @tab fourcc: FSV1 -@item Flash Screen Video v2 @tab X @tab X -@item Flash Video (FLV) @tab X @tab X - @tab Sorenson H.263 used in Flash -@item FM Screen Capture Codec @tab @tab X -@item Forward Uncompressed @tab @tab X -@item Fraps @tab @tab X -@item Go2Meeting @tab @tab X - @tab fourcc: G2M2, G2M3 -@item Go2Webinar @tab @tab X - @tab fourcc: G2M4 -@item Gremlin Digital Video @tab @tab X -@item H.261 @tab X @tab X -@item H.263 / H.263-1996 @tab X @tab X -@item H.263+ / H.263-1998 / H.263 version 2 @tab X @tab X -@item H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 @tab E @tab X - @tab encoding supported through external library libx264 and OpenH264 -@item HEVC @tab X @tab X - @tab encoding supported through external library libx265 and libkvazaar -@item HNM version 4 @tab @tab X -@item HuffYUV @tab X @tab X -@item HuffYUV FFmpeg variant @tab X @tab X -@item IBM Ultimotion @tab @tab X - @tab fourcc: ULTI -@item id Cinematic video @tab @tab X - @tab Used in Quake II. -@item id RoQ video @tab X @tab X - @tab Used in Quake III, Jedi Knight 2, other computer games. -@item IFF ILBM @tab @tab X - @tab IFF interleaved bitmap -@item IFF ByteRun1 @tab @tab X - @tab IFF run length encoded bitmap -@item Infinity IMM4 @tab @tab X -@item Intel H.263 @tab @tab X -@item Intel Indeo 2 @tab @tab X -@item Intel Indeo 3 @tab @tab X -@item Intel Indeo 4 @tab @tab X -@item Intel Indeo 5 @tab @tab X -@item Interplay C93 @tab @tab X - @tab Used in the game Cyberia from Interplay. -@item Interplay MVE video @tab @tab X - @tab Used in Interplay .MVE files. -@item J2K @tab X @tab X -@item Karl Morton's video codec @tab @tab X - @tab Codec used in Worms games. -@item Kega Game Video (KGV1) @tab @tab X - @tab Kega emulator screen capture codec. -@item Lagarith @tab @tab X -@item LCL (LossLess Codec Library) MSZH @tab @tab X -@item LCL (LossLess Codec Library) ZLIB @tab E @tab E -@item LOCO @tab @tab X -@item LucasArts SANM/Smush @tab @tab X - @tab Used in LucasArts games / SMUSH animations. -@item lossless MJPEG @tab X @tab X -@item MagicYUV Video @tab X @tab X -@item Mandsoft Screen Capture Codec @tab @tab X -@item Microsoft ATC Screen @tab @tab X - @tab Also known as Microsoft Screen 3. -@item Microsoft Expression Encoder Screen @tab @tab X - @tab Also known as Microsoft Titanium Screen 2. -@item Microsoft RLE @tab @tab X -@item Microsoft Screen 1 @tab @tab X - @tab Also known as Windows Media Video V7 Screen. -@item Microsoft Screen 2 @tab @tab X - @tab Also known as Windows Media Video V9 Screen. -@item Microsoft Video 1 @tab @tab X -@item Mimic @tab @tab X - @tab Used in MSN Messenger Webcam streams. -@item Miro VideoXL @tab @tab X - @tab fourcc: VIXL -@item MJPEG (Motion JPEG) @tab X @tab X -@item Mobotix MxPEG video @tab @tab X -@item Motion Pixels video @tab @tab X -@item MPEG-1 video @tab X @tab X -@item MPEG-2 video @tab X @tab X -@item MPEG-4 part 2 @tab X @tab X - @tab libxvidcore can be used alternatively for encoding. -@item MPEG-4 part 2 Microsoft variant version 1 @tab @tab X -@item MPEG-4 part 2 Microsoft variant version 2 @tab X @tab X -@item MPEG-4 part 2 Microsoft variant version 3 @tab X @tab X -@item Newtek SpeedHQ @tab @tab X -@item Nintendo Gamecube THP video @tab @tab X -@item NuppelVideo/RTjpeg @tab @tab X - @tab Video encoding used in NuppelVideo files. -@item On2 VP3 @tab @tab X - @tab still experimental -@item On2 VP4 @tab @tab X - @tab fourcc: VP40 -@item On2 VP5 @tab @tab X - @tab fourcc: VP50 -@item On2 VP6 @tab @tab X - @tab fourcc: VP60,VP61,VP62 -@item On2 VP7 @tab @tab X - @tab fourcc: VP70,VP71 -@item VP8 @tab E @tab X - @tab fourcc: VP80, encoding supported through external library libvpx -@item VP9 @tab E @tab X - @tab encoding supported through external library libvpx -@item Pinnacle TARGA CineWave YUV16 @tab @tab X - @tab fourcc: Y216 -@item Prores @tab @tab X - @tab fourcc: apch,apcn,apcs,apco -@item Q-team QPEG @tab @tab X - @tab fourccs: QPEG, Q1.0, Q1.1 -@item QuickTime 8BPS video @tab @tab X -@item QuickTime Animation (RLE) video @tab X @tab X - @tab fourcc: 'rle ' -@item QuickTime Graphics (SMC) @tab @tab X - @tab fourcc: 'smc ' -@item QuickTime video (RPZA) @tab @tab X - @tab fourcc: rpza -@item R10K AJA Kona 10-bit RGB Codec @tab X @tab X -@item R210 Quicktime Uncompressed RGB 10-bit @tab X @tab X -@item Raw Video @tab X @tab X -@item RealVideo 1.0 @tab X @tab X -@item RealVideo 2.0 @tab X @tab X -@item RealVideo 3.0 @tab @tab X - @tab still far from ideal -@item RealVideo 4.0 @tab @tab X -@item Renderware TXD (TeXture Dictionary) @tab @tab X - @tab Texture dictionaries used by the Renderware Engine. -@item RL2 video @tab @tab X - @tab used in some games by Entertainment Software Partners -@item ScreenPressor @tab @tab X -@item Screenpresso @tab @tab X -@item Screen Recorder Gold Codec @tab @tab X -@item Sierra VMD video @tab @tab X - @tab Used in Sierra VMD files. -@item Silicon Graphics Motion Video Compressor 1 (MVC1) @tab @tab X -@item Silicon Graphics Motion Video Compressor 2 (MVC2) @tab @tab X -@item Silicon Graphics RLE 8-bit video @tab @tab X -@item Smacker video @tab @tab X - @tab Video encoding used in Smacker. -@item SMPTE VC-1 @tab @tab X -@item Snow @tab X @tab X - @tab experimental wavelet codec (fourcc: SNOW) -@item Sony PlayStation MDEC (Motion DECoder) @tab @tab X -@item Sorenson Vector Quantizer 1 @tab X @tab X - @tab fourcc: SVQ1 -@item Sorenson Vector Quantizer 3 @tab @tab X - @tab fourcc: SVQ3 -@item Sunplus JPEG (SP5X) @tab @tab X - @tab fourcc: SP5X -@item TechSmith Screen Capture Codec @tab @tab X - @tab fourcc: TSCC -@item TechSmith Screen Capture Codec 2 @tab @tab X - @tab fourcc: TSC2 -@item Theora @tab E @tab X - @tab encoding supported through external library libtheora -@item Tiertex Limited SEQ video @tab @tab X - @tab Codec used in DOS CD-ROM FlashBack game. -@item Ut Video @tab X @tab X -@item v210 QuickTime uncompressed 4:2:2 10-bit @tab X @tab X -@item v308 QuickTime uncompressed 4:4:4 @tab X @tab X -@item v408 QuickTime uncompressed 4:4:4:4 @tab X @tab X -@item v410 QuickTime uncompressed 4:4:4 10-bit @tab X @tab X -@item VBLE Lossless Codec @tab @tab X -@item VMware Screen Codec / VMware Video @tab @tab X - @tab Codec used in videos captured by VMware. -@item Westwood Studios VQA (Vector Quantized Animation) video @tab @tab X -@item Windows Media Image @tab @tab X -@item Windows Media Video 7 @tab X @tab X -@item Windows Media Video 8 @tab X @tab X -@item Windows Media Video 9 @tab @tab X - @tab not completely working -@item Wing Commander III / Xan @tab @tab X - @tab Used in Wing Commander III .MVE files. -@item Wing Commander IV / Xan @tab @tab X - @tab Used in Wing Commander IV. -@item Winnov WNV1 @tab @tab X -@item WMV7 @tab X @tab X -@item YAMAHA SMAF @tab X @tab X -@item Psygnosis YOP Video @tab @tab X -@item yuv4 @tab X @tab X - @tab libquicktime uncompressed packed 4:2:0 -@item ZeroCodec Lossless Video @tab @tab X -@item ZLIB @tab X @tab X - @tab part of LCL, encoder experimental -@item Zip Motion Blocks Video @tab X @tab X - @tab Encoder works only in PAL8. -@end multitable - -@code{X} means that the feature in that column (encoding / decoding) is supported. - -@code{E} means that support is provided through an external library. - -@section Audio Codecs - -@multitable @columnfractions .4 .1 .1 .4 -@item Name @tab Encoding @tab Decoding @tab Comments -@item 8SVX exponential @tab @tab X -@item 8SVX fibonacci @tab @tab X -@item AAC @tab EX @tab X - @tab encoding supported through internal encoder and external library libfdk-aac -@item AAC+ @tab E @tab IX - @tab encoding supported through external library libfdk-aac -@item AC-3 @tab IX @tab IX -@item ADPCM 4X Movie @tab @tab X -@item APDCM Yamaha AICA @tab @tab X -@item ADPCM CDROM XA @tab @tab X -@item ADPCM Creative Technology @tab @tab X - @tab 16 -> 4, 8 -> 4, 8 -> 3, 8 -> 2 -@item ADPCM Electronic Arts @tab @tab X - @tab Used in various EA titles. -@item ADPCM Electronic Arts Maxis CDROM XS @tab @tab X - @tab Used in Sim City 3000. -@item ADPCM Electronic Arts R1 @tab @tab X -@item ADPCM Electronic Arts R2 @tab @tab X -@item ADPCM Electronic Arts R3 @tab @tab X -@item ADPCM Electronic Arts XAS @tab @tab X -@item ADPCM G.722 @tab X @tab X -@item ADPCM G.726 @tab X @tab X -@item ADPCM IMA AMV @tab @tab X - @tab Used in AMV files -@item ADPCM IMA Electronic Arts EACS @tab @tab X -@item ADPCM IMA Electronic Arts SEAD @tab @tab X -@item ADPCM IMA Funcom @tab @tab X -@item ADPCM IMA QuickTime @tab X @tab X -@item ADPCM IMA Loki SDL MJPEG @tab @tab X -@item ADPCM IMA WAV @tab X @tab X -@item ADPCM IMA Westwood @tab @tab X -@item ADPCM ISS IMA @tab @tab X - @tab Used in FunCom games. -@item ADPCM IMA Dialogic @tab @tab X -@item ADPCM IMA Duck DK3 @tab @tab X - @tab Used in some Sega Saturn console games. -@item ADPCM IMA Duck DK4 @tab @tab X - @tab Used in some Sega Saturn console games. -@item ADPCM IMA Radical @tab @tab X -@item ADPCM Microsoft @tab X @tab X -@item ADPCM MS IMA @tab X @tab X -@item ADPCM Nintendo Gamecube AFC @tab @tab X -@item ADPCM Nintendo Gamecube DTK @tab @tab X -@item ADPCM Nintendo THP @tab @tab X -@item APDCM Playstation @tab @tab X -@item ADPCM QT IMA @tab X @tab X -@item ADPCM SEGA CRI ADX @tab X @tab X - @tab Used in Sega Dreamcast games. -@item ADPCM Shockwave Flash @tab X @tab X -@item ADPCM Sound Blaster Pro 2-bit @tab @tab X -@item ADPCM Sound Blaster Pro 2.6-bit @tab @tab X -@item ADPCM Sound Blaster Pro 4-bit @tab @tab X -@item ADPCM VIMA @tab @tab X - @tab Used in LucasArts SMUSH animations. -@item ADPCM Westwood Studios IMA @tab @tab X - @tab Used in Westwood Studios games like Command and Conquer. -@item ADPCM Yamaha @tab X @tab X -@item AMR-NB @tab E @tab X - @tab encoding supported through external library libopencore-amrnb -@item AMR-WB @tab E @tab X - @tab encoding supported through external library libvo-amrwbenc -@item Amazing Studio PAF Audio @tab @tab X -@item Apple lossless audio @tab X @tab X - @tab QuickTime fourcc 'alac' -@item aptX @tab X @tab X - @tab Used in Bluetooth A2DP -@item aptX HD @tab X @tab X - @tab Used in Bluetooth A2DP -@item ATRAC1 @tab @tab X -@item ATRAC3 @tab @tab X -@item ATRAC3+ @tab @tab X -@item ATRAC9 @tab @tab X -@item Bink Audio @tab @tab X - @tab Used in Bink and Smacker files in many games. -@item CELT @tab @tab E - @tab decoding supported through external library libcelt -@item codec2 @tab E @tab E - @tab en/decoding supported through external library libcodec2 -@item Delphine Software International CIN audio @tab @tab X - @tab Codec used in Delphine Software International games. -@item Digital Speech Standard - Standard Play mode (DSS SP) @tab @tab X -@item Discworld II BMV Audio @tab @tab X -@item COOK @tab @tab X - @tab All versions except 5.1 are supported. -@item DCA (DTS Coherent Acoustics) @tab X @tab X - @tab supported extensions: XCh, XXCH, X96, XBR, XLL, LBR (partially) -@item Dolby E @tab @tab X -@item DPCM id RoQ @tab X @tab X - @tab Used in Quake III, Jedi Knight 2 and other computer games. -@item DPCM Interplay @tab @tab X - @tab Used in various Interplay computer games. -@item DPCM Squareroot-Delta-Exact @tab @tab X - @tab Used in various games. -@item DPCM Sierra Online @tab @tab X - @tab Used in Sierra Online game audio files. -@item DPCM Sol @tab @tab X -@item DPCM Xan @tab @tab X - @tab Used in Origin's Wing Commander IV AVI files. -@item DSD (Direct Stream Digital), least significant bit first @tab @tab X -@item DSD (Direct Stream Digital), most significant bit first @tab @tab X -@item DSD (Direct Stream Digital), least significant bit first, planar @tab @tab X -@item DSD (Direct Stream Digital), most significant bit first, planar @tab @tab X -@item DSP Group TrueSpeech @tab @tab X -@item DST (Direct Stream Transfer) @tab @tab X -@item DV audio @tab @tab X -@item Enhanced AC-3 @tab X @tab X -@item EVRC (Enhanced Variable Rate Codec) @tab @tab X -@item FLAC (Free Lossless Audio Codec) @tab X @tab IX -@item G.723.1 @tab X @tab X -@item G.729 @tab @tab X -@item GSM @tab E @tab X - @tab encoding supported through external library libgsm -@item GSM Microsoft variant @tab E @tab X - @tab encoding supported through external library libgsm -@item IAC (Indeo Audio Coder) @tab @tab X -@item iLBC (Internet Low Bitrate Codec) @tab E @tab E - @tab encoding and decoding supported through external library libilbc -@item IMC (Intel Music Coder) @tab @tab X -@item Interplay ACM @tab @tab X -@item MACE (Macintosh Audio Compression/Expansion) 3:1 @tab @tab X -@item MACE (Macintosh Audio Compression/Expansion) 6:1 @tab @tab X -@item MLP (Meridian Lossless Packing) @tab X @tab X - @tab Used in DVD-Audio discs. -@item Monkey's Audio @tab @tab X -@item MP1 (MPEG audio layer 1) @tab @tab IX -@item MP2 (MPEG audio layer 2) @tab IX @tab IX - @tab encoding supported also through external library TwoLAME -@item MP3 (MPEG audio layer 3) @tab E @tab IX - @tab encoding supported through external library LAME, ADU MP3 and MP3onMP4 also supported -@item MPEG-4 Audio Lossless Coding (ALS) @tab @tab X -@item Musepack SV7 @tab @tab X -@item Musepack SV8 @tab @tab X -@item Nellymoser Asao @tab X @tab X -@item On2 AVC (Audio for Video Codec) @tab @tab X -@item Opus @tab E @tab X - @tab encoding supported through external library libopus -@item PCM A-law @tab X @tab X -@item PCM mu-law @tab X @tab X -@item PCM Archimedes VIDC @tab X @tab X -@item PCM signed 8-bit planar @tab X @tab X -@item PCM signed 16-bit big-endian planar @tab X @tab X -@item PCM signed 16-bit little-endian planar @tab X @tab X -@item PCM signed 24-bit little-endian planar @tab X @tab X -@item PCM signed 32-bit little-endian planar @tab X @tab X -@item PCM 32-bit floating point big-endian @tab X @tab X -@item PCM 32-bit floating point little-endian @tab X @tab X -@item PCM 64-bit floating point big-endian @tab X @tab X -@item PCM 64-bit floating point little-endian @tab X @tab X -@item PCM D-Cinema audio signed 24-bit @tab X @tab X -@item PCM signed 8-bit @tab X @tab X -@item PCM signed 16-bit big-endian @tab X @tab X -@item PCM signed 16-bit little-endian @tab X @tab X -@item PCM signed 24-bit big-endian @tab X @tab X -@item PCM signed 24-bit little-endian @tab X @tab X -@item PCM signed 32-bit big-endian @tab X @tab X -@item PCM signed 32-bit little-endian @tab X @tab X -@item PCM signed 16/20/24-bit big-endian in MPEG-TS @tab @tab X -@item PCM unsigned 8-bit @tab X @tab X -@item PCM unsigned 16-bit big-endian @tab X @tab X -@item PCM unsigned 16-bit little-endian @tab X @tab X -@item PCM unsigned 24-bit big-endian @tab X @tab X -@item PCM unsigned 24-bit little-endian @tab X @tab X -@item PCM unsigned 32-bit big-endian @tab X @tab X -@item PCM unsigned 32-bit little-endian @tab X @tab X -@item PCM Zork @tab @tab X -@item QCELP / PureVoice @tab @tab X -@item QDesign Music Codec 1 @tab @tab X -@item QDesign Music Codec 2 @tab @tab X - @tab There are still some distortions. -@item RealAudio 1.0 (14.4K) @tab X @tab X - @tab Real 14400 bit/s codec -@item RealAudio 2.0 (28.8K) @tab @tab X - @tab Real 28800 bit/s codec -@item RealAudio 3.0 (dnet) @tab IX @tab X - @tab Real low bitrate AC-3 codec -@item RealAudio Lossless @tab @tab X -@item RealAudio SIPR / ACELP.NET @tab @tab X -@item SBC (low-complexity subband codec) @tab X @tab X - @tab Used in Bluetooth A2DP -@item Shorten @tab @tab X -@item Sierra VMD audio @tab @tab X - @tab Used in Sierra VMD files. -@item Smacker audio @tab @tab X -@item SMPTE 302M AES3 audio @tab X @tab X -@item Sonic @tab X @tab X - @tab experimental codec -@item Sonic lossless @tab X @tab X - @tab experimental codec -@item Speex @tab E @tab E - @tab supported through external library libspeex -@item TAK (Tom's lossless Audio Kompressor) @tab @tab X -@item True Audio (TTA) @tab X @tab X -@item TrueHD @tab X @tab X - @tab Used in HD-DVD and Blu-Ray discs. -@item TwinVQ (VQF flavor) @tab @tab X -@item VIMA @tab @tab X - @tab Used in LucasArts SMUSH animations. -@item Vorbis @tab E @tab X - @tab A native but very primitive encoder exists. -@item Voxware MetaSound @tab @tab X -@item WavPack @tab X @tab X -@item Westwood Audio (SND1) @tab @tab X -@item Windows Media Audio 1 @tab X @tab X -@item Windows Media Audio 2 @tab X @tab X -@item Windows Media Audio Lossless @tab @tab X -@item Windows Media Audio Pro @tab @tab X -@item Windows Media Audio Voice @tab @tab X -@item Xbox Media Audio 1 @tab @tab X -@item Xbox Media Audio 2 @tab @tab X -@end multitable - -@code{X} means that the feature in that column (encoding / decoding) is supported. - -@code{E} means that support is provided through an external library. - -@code{I} means that an integer-only version is available, too (ensures high -performance on systems without hardware floating point support). - -@section Subtitle Formats - -@multitable @columnfractions .4 .1 .1 .1 .1 -@item Name @tab Muxing @tab Demuxing @tab Encoding @tab Decoding -@item 3GPP Timed Text @tab @tab @tab X @tab X -@item AQTitle @tab @tab X @tab @tab X -@item DVB @tab X @tab X @tab X @tab X -@item DVB teletext @tab @tab X @tab @tab E -@item DVD @tab X @tab X @tab X @tab X -@item JACOsub @tab X @tab X @tab @tab X -@item MicroDVD @tab X @tab X @tab @tab X -@item MPL2 @tab @tab X @tab @tab X -@item MPsub (MPlayer) @tab @tab X @tab @tab X -@item PGS @tab @tab @tab @tab X -@item PJS (Phoenix) @tab @tab X @tab @tab X -@item RealText @tab @tab X @tab @tab X -@item SAMI @tab @tab X @tab @tab X -@item Spruce format (STL) @tab @tab X @tab @tab X -@item SSA/ASS @tab X @tab X @tab X @tab X -@item SubRip (SRT) @tab X @tab X @tab X @tab X -@item SubViewer v1 @tab @tab X @tab @tab X -@item SubViewer @tab @tab X @tab @tab X -@item TED Talks captions @tab @tab X @tab @tab X -@item VobSub (IDX+SUB) @tab @tab X @tab @tab X -@item VPlayer @tab @tab X @tab @tab X -@item WebVTT @tab X @tab X @tab X @tab X -@item XSUB @tab @tab @tab X @tab X -@end multitable - -@code{X} means that the feature is supported. - -@code{E} means that support is provided through an external library. - -@section Network Protocols - -@multitable @columnfractions .4 .1 -@item Name @tab Support -@item file @tab X -@item FTP @tab X -@item Gopher @tab X -@item HLS @tab X -@item HTTP @tab X -@item HTTPS @tab X -@item Icecast @tab X -@item MMSH @tab X -@item MMST @tab X -@item pipe @tab X -@item Pro-MPEG FEC @tab X -@item RTMP @tab X -@item RTMPE @tab X -@item RTMPS @tab X -@item RTMPT @tab X -@item RTMPTE @tab X -@item RTMPTS @tab X -@item RTP @tab X -@item SAMBA @tab E -@item SCTP @tab X -@item SFTP @tab E -@item TCP @tab X -@item TLS @tab X -@item UDP @tab X -@end multitable - -@code{X} means that the protocol is supported. - -@code{E} means that support is provided through an external library. - - -@section Input/Output Devices - -@multitable @columnfractions .4 .1 .1 -@item Name @tab Input @tab Output -@item ALSA @tab X @tab X -@item BKTR @tab X @tab -@item caca @tab @tab X -@item DV1394 @tab X @tab -@item Lavfi virtual device @tab X @tab -@item Linux framebuffer @tab X @tab X -@item JACK @tab X @tab -@item LIBCDIO @tab X -@item LIBDC1394 @tab X @tab -@item OpenAL @tab X -@item OpenGL @tab @tab X -@item OSS @tab X @tab X -@item PulseAudio @tab X @tab X -@item SDL @tab @tab X -@item Video4Linux2 @tab X @tab X -@item VfW capture @tab X @tab -@item X11 grabbing @tab X @tab -@item Win32 grabbing @tab X @tab -@end multitable - -@code{X} means that input/output is supported. - -@section Timecode - -@multitable @columnfractions .4 .1 .1 -@item Codec/format @tab Read @tab Write -@item AVI @tab X @tab X -@item DV @tab X @tab X -@item GXF @tab X @tab X -@item MOV @tab X @tab X -@item MPEG1/2 @tab X @tab X -@item MXF @tab X @tab X -@end multitable +@include general_contents.texi @bye diff -Nru ffmpeg-4.2.2/doc/indevs.texi ffmpeg-4.4/doc/indevs.texi --- ffmpeg-4.2.2/doc/indevs.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/indevs.texi 2021-04-08 21:28:39.000000000 +0000 @@ -277,8 +277,8 @@ @item list_devices If set to @option{true}, print a list of devices and exit. -Defaults to @option{false}. Alternatively you can use the @code{-sources} -option of ffmpeg to list the available input devices. +Defaults to @option{false}. This option is deprecated, please use the +@code{-sources} option of ffmpeg to list the available input devices. @item list_formats If set to @option{true}, print a list of supported formats and exit. @@ -292,25 +292,35 @@ Default behavior is autodetection of the input video format, if the hardware supports it. -@item bm_v210 -This is a deprecated option, you can use @option{raw_format} instead. -If set to @samp{1}, video is captured in 10 bit v210 instead -of uyvy422. Not all Blackmagic devices support this option. - @item raw_format Set the pixel format of the captured video. Available values are: @table @samp +@item auto + +This is the default which means 8-bit YUV 422 or 8-bit ARGB if format +autodetection is used, 8-bit YUV 422 otherwise. + @item uyvy422 +8-bit YUV 422. + @item yuv422p10 +10-bit YUV 422. + @item argb +8-bit RGB. + @item bgra +8-bit RGB. + @item rgb10 +10-bit RGB. + @end table @item teletext_lines @@ -340,8 +350,13 @@ @item timecode_format Timecode type to include in the frame and video stream metadata. Must be @samp{none}, @samp{rp188vitc}, @samp{rp188vitc2}, @samp{rp188ltc}, -@samp{rp188any}, @samp{vitc}, @samp{vitc2}, or @samp{serial}. Defaults to -@samp{none} (not included). +@samp{rp188hfr}, @samp{rp188any}, @samp{vitc}, @samp{vitc2}, or @samp{serial}. +Defaults to @samp{none} (not included). + +In order to properly support 50/60 fps timecodes, the ordering of the queried +timecode types for @samp{rp188any} is HFR, VITC1, VITC2 and LTC for >30 fps +content. Note that this is slightly different to the ordering used by the +DeckLink API, which is HFR, VITC1, LTC, VITC2. @item video_input Sets the video input source. Must be @samp{unset}, @samp{sdi}, @samp{hdmi}, @@ -395,6 +410,20 @@ @option{timestamp_align} seconds. Defaults to @samp{0}. +@item wait_for_tc (@emph{bool}) +Drop frames till a frame with timecode is received. Sometimes serial timecode +isn't received with the first input frame. If that happens, the stored stream +timecode will be inaccurate. If this option is set to @option{true}, input frames +are dropped till a frame with timecode is received. +Option @var{timecode_format} must be specified. +Defaults to @option{false}. + +@item enable_klv(@emph{bool}) +If set to @option{true}, extracts KLV data from VANC and outputs KLV packets. +KLV VANC packets are joined based on MID and PSC fields and aggregated into +one KLV packet. +Defaults to @option{false}. + @end table @subsection Examples @@ -404,7 +433,7 @@ @item List input devices: @example -ffmpeg -f decklink -list_devices 1 -i dummy +ffmpeg -sources decklink @end example @item @@ -422,7 +451,7 @@ @item Capture video clip at 1080i50 10 bit: @example -ffmpeg -bm_v210 1 -format_code Hi50 -f decklink -i 'UltraStudio Mini Recorder' -c:a copy -c:v copy output.avi +ffmpeg -raw_format yuv422p10 -format_code Hi50 -f decklink -i 'UltraStudio Mini Recorder' -c:a copy -c:v copy output.avi @end example @item @@ -880,11 +909,15 @@ DRM device to capture on. Defaults to @option{/dev/dri/card0}. @item format -Pixel format of the framebuffer. Defaults to @option{bgr0}. +Pixel format of the framebuffer. This can be autodetected if you are running Linux 5.7 +or later, but needs to be provided for earlier versions. Defaults to @option{bgr0}, +which is the most common format used by the Linux console and Xorg X server. @item format_modifier Format modifier to signal on output frames. This is necessary to import correctly into -some APIs, but can't be autodetected. See the libdrm documentation for possible values. +some APIs. It can be autodetected if you are running Linux 5.7 or later, but will need +to be provided explicitly when needed in earlier versions. See the libdrm documentation +for possible values. @item crtc_id KMS CRTC ID to define the capture source. The first active plane on the given CRTC @@ -1475,6 +1508,14 @@ @subsection Options @table @option +@item select_region +Specify whether to select the grabbing area graphically using the pointer. +A value of @code{1} prompts the user to select the grabbing area graphically +by clicking and dragging. A single click with no dragging will select the +whole screen. A region with zero width or height will also select the whole +screen. This option overwrites the @var{video_size}, @var{grab_x}, and +@var{grab_y} options. Default value is @code{0}. + @item draw_mouse Specify whether to draw the mouse pointer. A value of @code{0} specifies not to draw the pointer. Default value is @code{1}. @@ -1523,8 +1564,21 @@ ffmpeg -f x11grab -follow_mouse centered -show_region 1 -framerate 25 -video_size cif -i :0.0 out.mpg @end example +@item window_id +Grab this window, instead of the whole screen. Default value is 0, which maps to +the whole screen (root window). + +The id of a window can be found using the @command{xwininfo} program, possibly with options -tree and +-root. + +If the window is later enlarged, the new area is not recorded. Video ends when +the window is closed, unmapped (i.e., iconified) or shrunk beyond the video +size (which defaults to the initial window size). + +This option disables options @option{follow_mouse} and @option{select_region}. + @item video_size -Set the video frame size. Default value is @code{vga}. +Set the video frame size. Default is the full desktop or window. @item grab_x @item grab_y diff -Nru ffmpeg-4.2.2/doc/multithreading.txt ffmpeg-4.4/doc/multithreading.txt --- ffmpeg-4.2.2/doc/multithreading.txt 2017-12-31 22:35:45.000000000 +0000 +++ ffmpeg-4.4/doc/multithreading.txt 2021-04-08 21:28:39.000000000 +0000 @@ -20,8 +20,7 @@ Frame threading - * Restrictions with slice threading also apply. -* For best performance, the client should set thread_safe_callbacks if it - provides a thread-safe get_buffer() callback. +* Custom get_buffer2() and get_format() callbacks must be thread-safe. * There is one frame of delay added for every thread beyond the first one. Clients must be able to handle this; the pkt_dts and pkt_pts fields in AVFrame will work as usual. @@ -51,16 +50,14 @@ some code can't be moved, have update_thread_context() run it in the next thread. -If the codec allocates writable tables in its init(), add an init_thread_copy() -which re-allocates them for other threads. - Add AV_CODEC_CAP_FRAME_THREADS to the codec capabilities. There will be very little speed gain at this point but it should work. If there are inter-frame dependencies, so the codec calls -ff_thread_report/await_progress(), set AVCodecInternal.allocate_progress. The +ff_thread_report/await_progress(), set FF_CODEC_CAP_ALLOCATE_PROGRESS in +AVCodec.caps_internal and use ff_thread_get_buffer() to allocate frames. The frames must then be freed with ff_thread_release_buffer(). -Otherwise leave it at zero and decode directly into the user-supplied frames. +Otherwise decode directly into the user-supplied frames. Call ff_thread_report_progress() after some part of the current picture has decoded. A good place to put this is where draw_horiz_band() is called - add this if it isn't diff -Nru ffmpeg-4.2.2/doc/muxers.texi ffmpeg-4.4/doc/muxers.texi --- ffmpeg-4.2.2/doc/muxers.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/muxers.texi 2021-04-08 21:28:39.000000000 +0000 @@ -89,6 +89,12 @@ compatibility with software that only supports a single audio stream in AVI (see @ref{amerge,,the "amerge" section in the ffmpeg-filters manual,ffmpeg-filters}). +@item flipped_raw_rgb +If set to true, store positive height for raw RGB bitmaps, which indicates +bitmap is stored bottom-up. Note that this option does not flip the bitmap +which has to be done manually beforehand, e.g. by using the vflip filter. +Default is @var{false} and indicates bitmap is stored top down. + @end table @anchor{chromaprint} @@ -105,12 +111,14 @@ @table @option @item silence_threshold -Threshold for detecting silence, ranges from -1 to 32767. -1 disables silence detection and -is required for use with the AcoustID service. Default is -1. +Threshold for detecting silence. Range is from -1 to 32767, where -1 disables +silence detection. Silence detection can only be used with version 3 of the +algorithm. +Silence detection must be disabled for use with the AcoustID service. Default is -1. @item algorithm -Version of algorithm to fingerprint with. Range is 0 to 4. Version 2 requires that silence -detection be enabled. Default is 1. +Version of algorithm to fingerprint with. Range is 0 to 4. +Version 3 enables silence detection. Default is 1. @item fp_format Format to output the fingerprint as. Accepts the following options: @@ -236,6 +244,10 @@ treated as average segment duration when @var{use_template} is enabled and @var{use_timeline} is disabled and as minimum segment duration for all the other use cases. +@item frag_duration @var{duration} +Set the length in seconds of fragments within segments (fractional value can be set). +@item frag_type @var{type} +Set the type of interval for fragmentation. @item window_size @var{size} Set the maximum number of segments kept in the manifest. @item extra_window_size @var{size} @@ -263,8 +275,10 @@ @item http_persistent @var{http_persistent} Use persistent HTTP connections. Applicable only for HTTP output. @item hls_playlist @var{hls_playlist} -Generate HLS playlist files as well. The master playlist is generated with the filename master.m3u8. +Generate HLS playlist files as well. The master playlist is generated with the filename @var{hls_master_name}. One media playlist file is generated for each stream with filenames media_0.m3u8, media_1.m3u8, etc. +@item hls_master_name @var{file_name} +HLS master playlist name. Default is "master.m3u8". @item streaming @var{streaming} Enable (1) or disable (0) chunk streaming mode of output. In chunk streaming mode, each frame will be a moof fragment which forms a chunk. @@ -275,6 +289,15 @@ To map all video (or audio) streams to an AdaptationSet, "v" (or "a") can be used as stream identifier instead of IDs. When no assignment is defined, this defaults to an AdaptationSet for each stream. + +Optional syntax is "id=x,seg_duration=x,frag_duration=x,frag_type=type,descriptor=descriptor_string,streams=a,b,c id=y,seg_duration=y,frag_type=type,streams=d,e" and so on, +descriptor is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015. +For example, -adaptation_sets "id=0,descriptor=,streams=v". +Please note that descriptor string should be a self-closing xml tag. +seg_duration, frag_duration and frag_type override the global option values for each adaptation set. +For example, -adaptation_sets "id=0,seg_duration=2,frag_duration=1,frag_type=duration,streams=v id=1,seg_duration=2,frag_type=none,streams=a" +type_id marks an adaptation set as containing streams meant to be used for Trick Mode for the referenced adaptation set. +For example, -adaptation_sets "id=0,seg_duration=2,frag_type=none,streams=0 id=1,seg_duration=10,frag_type=none,trick_id=0,streams=1" @item timeout @var{timeout} Set timeout for socket I/O operations. Applicable only for HTTP output. @item index_correction @var{index_correction} @@ -320,9 +343,41 @@ Applicable only when @var{streaming} and @var{hls_playlist} options are enabled. This is an experimental feature. +@item ldash @var{ldash} +Enable Low-latency Dash by constraining the presence and values of some elements. + @item master_m3u8_publish_rate @var{master_m3u8_publish_rate} Publish master playlist repeatedly every after specified number of segment intervals. +@item write_prft @var{write_prft} +Write Producer Reference Time elements on supported streams. This also enables writing +prft boxes in the underlying muxer. Applicable only when the @var{utc_url} option is enabled. +It's set to auto by default, in which case the muxer will attempt to enable it only in modes +that require it. + +@item mpd_profile @var{mpd_profile} +Set one or more manifest profiles. + +@item http_opts @var{http_opts} +A :-separated list of key=value options to pass to the underlying HTTP +protocol. Applicable only for HTTP output. + +@item target_latency @var{target_latency} +Set an intended target latency in seconds (fractional value can be set) for serving. Applicable only when @var{streaming} and @var{write_prft} options are enabled. +This is an informative fields clients can use to measure the latency of the service. + +@item min_playback_rate @var{min_playback_rate} +Set the minimum playback rate indicated as appropriate for the purposes of automatically +adjusting playback latency and buffer occupancy during normal playback by clients. + +@item max_playback_rate @var{max_playback_rate} +Set the maximum playback rate indicated as appropriate for the purposes of automatically +adjusting playback latency and buffer occupancy during normal playback by clients. + +@item update_period @var{update_period} + Set the mpd update period ,for dynamic content. + The unit is second. + @end table @anchor{framecrc} @@ -556,14 +611,21 @@ This muxer supports the following options: @table @option -@item hls_init_time @var{seconds} -Set the initial target segment length in seconds. Default value is @var{0}. +@item hls_init_time @var{duration} +Set the initial target segment length. Default value is @var{0}. + +@var{duration} must be a time duration specification, +see @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils}. + Segment will be cut on the next key frame after this time has passed on the first m3u8 list. After the initial playlist is filled @command{ffmpeg} will cut segments at duration equal to @code{hls_time} -@item hls_time @var{seconds} -Set the target segment length in seconds. Default value is 2. +@item hls_time @var{duration} +Set the target segment length. Default value is 2. + +@var{duration} must be a time duration specification, +see @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils}. Segment will be cut on the next key frame after this time has passed. @item hls_list_size @var{size} @@ -607,6 +669,9 @@ @item epoch The start number will be the seconds since epoch (1970-01-01 00:00:00) +@item epoch_us +The start number will be the microseconds since epoch (1970-01-01 00:00:00) + @item datetime The start number will be based on the current date/time as YYYYmmddHHMMSS. e.g. 20161231235759. @@ -775,7 +840,7 @@ is saved as @var{playlist name}.key. @item -hls_enc_key @var{key} -Hex-coded 16byte key to encrypt the segments, by default it +16-octet key to encrypt the segments, by default it is randomly generated. @item -hls_enc_key_url @var{keyurl} @@ -783,7 +848,7 @@ in the playlist. @item -hls_enc_iv @var{iv} -Hex-coded 16byte initialization vector for every segment instead +16-octet initialization vector for every segment instead of the autogenerated ones. @item hls_segment_type @var{flags} @@ -803,6 +868,16 @@ @item hls_fmp4_init_filename @var{filename} Set filename to the fragment files header file, default filename is @file{init.mp4}. +Use @code{-strftime 1} on @var{filename} to expand the segment filename with localtime. +@example +ffmpeg -i in.nut -hls_segment_type fmp4 -strftime 1 -hls_fmp4_init_filename "%s_init.mp4" out.m3u8 +@end example +This will produce init like this +@file{1602678741_init.mp4} + +@item hls_fmp4_init_resend +Resend init file after m3u8 file refresh every time, default is @var{0}. + When @code{var_stream_map} is set with two or more variant streams, the @var{filename} pattern must contain the string "%v", this string specifies the position of variant stream index in the generated init file names. @@ -898,8 +973,8 @@ before they have been added to the m3u8 playlist. This flag also affects how m3u8 playlist files are created. If this flag is set, all playlist files will written into temporary file and renamed after they are complete, similarly as segments are handled. But playlists with @code{file} protocol and with type (@code{hls_playlist_type}) other than @code{vod} -are always written into temporary file regardles of this flag. Master playlist files (@code{master_pl_name}), if any, with @code{file} protocol, -are always written into temporary file regardles of this flag if @code{master_pl_publish_rate} value is other than zero. +are always written into temporary file regardless of this flag. Master playlist files (@code{master_pl_name}), if any, with @code{file} protocol, +are always written into temporary file regardless of this flag if @code{master_pl_publish_rate} value is other than zero. @end table @@ -1029,6 +1104,21 @@ By default, a single hls variant containing all the encoded streams is created. +@example +ffmpeg -y -i input_with_subtitle.mkv \ + -b:v:0 5250k -c:v h264 -pix_fmt yuv420p -profile:v main -level 4.1 \ + -b:a:0 256k \ + -c:s webvtt -c:a mp2 -ar 48000 -ac 2 -map 0:v -map 0:a:0 -map 0:s:0 \ + -f hls -var_stream_map "v:0,a:0,s:0,sgroup:subtitle" \ + -master_pl_name master.m3u8 -t 300 -hls_time 10 -hls_init_time 4 -hls_list_size \ + 10 -master_pl_publish_rate 10 -hls_flags \ + delete_segments+discont_start+split_by_time ./tmp/video.m3u8 +@end example + +This example adds @code{#EXT-X-MEDIA} tag with @code{TYPE=SUBTITLES} in +the master playlist with webvtt subtitle group name 'subtitle'. Please make sure +the input file has one text subtitle stream at least. + @item cc_stream_map Map string which specifies different closed captions groups and their attributes. The closed captions stream groups are separated by space. @@ -1163,6 +1253,37 @@ form @file{img%-1.jpg}, @file{img%-2.jpg}, ..., @file{img%-10.jpg}, etc. +The image muxer supports the .Y.U.V image file format. This format is +special in that that each image frame consists of three files, for +each of the YUV420P components. To read or write this image file format, +specify the name of the '.Y' file. The muxer will automatically open the +'.U' and '.V' files as required. + +@subsection Options + +@table @option +@item frame_pts +If set to 1, expand the filename with pts from pkt->pts. +Default value is 0. + +@item start_number +Start the sequence from the specified number. Default value is 1. + +@item update +If set to 1, the filename will always be interpreted as just a +filename, not a pattern, and the corresponding file will be continuously +overwritten with new images. Default value is 0. + +@item strftime +If set to 1, expand the filename with date and time information from +@code{strftime()}. Default value is 0. + +@item protocol_opts @var{options_list} +Set protocol options as a :-separated list of key=value parameters. Values +containing the @code{:} special character must be escaped. + +@end table + @subsection Examples The following example shows how to use @command{ffmpeg} for creating a @@ -1203,31 +1324,11 @@ ffmpeg -f v4l2 -r 1 -i /dev/video0 -copyts -f image2 -frame_pts true %d.jpg" @end example -@subsection Options - -@table @option -@item frame_pts -If set to 1, expand the filename with pts from pkt->pts. -Default value is 0. - -@item start_number -Start the sequence from the specified number. Default value is 1. - -@item update -If set to 1, the filename will always be interpreted as just a -filename, not a pattern, and the corresponding file will be continuously -overwritten with new images. Default value is 0. - -@item strftime -If set to 1, expand the filename with date and time information from -@code{strftime()}. Default value is 0. -@end table - -The image muxer supports the .Y.U.V image file format. This format is -special in that that each image frame consists of three files, for -each of the YUV420P components. To read or write this image file format, -specify the name of the '.Y' file. The muxer will automatically open the -'.U' and '.V' files as required. +A more complex example is to publish contents of your desktop directly to a +WebDAV server every second: +@example +ffmpeg -f x11grab -framerate 1 -i :0.0 -q:v 6 -update 1 -protocol_opts method=PUT http://example.com/desktop.jpg +@end example @section matroska @@ -1241,7 +1342,8 @@ @table @option @item title -Set title name provided to a single track. +Set title name provided to a single track. This gets mapped to +the FileDescription element for a stream written as attachment. @item language Specify the language of the track in the Matroska languages form. @@ -1308,11 +1410,38 @@ If this option is set to a non-zero value, the muxer will reserve a given amount of space in the file header and then try to write the cues there when the muxing -finishes. If the available space does not suffice, muxing will fail. A safe size -for most use cases should be about 50kB per hour of video. +finishes. If the reserved space does not suffice, no Cues will be written, the +file will be finalized and writing the trailer will return an error. +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 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 +is @samp{infer}. +@table @samp +@item infer +In this mode, for each type of track (audio, video or subtitle), if there is +a track with disposition default of this type, then the first such track +(i.e. the one with the lowest index) will be marked as default; if no such +track exists, the first track of this type will be marked as default instead +(if existing). This ensures that the default flag is set in a sensible way even +if the input originated from containers that lack the concept of default tracks. +@item infer_no_subs +This mode is the same as infer except that if no subtitle track with +disposition default exists, no subtitle track will be marked as default. +@item passthrough +In this mode the FlagDefault is set if and only if the AV_DISPOSITION_DEFAULT +flag is set in the disposition of the corresponding stream. +@end table + +@item flipped_raw_rgb +If set to true, store positive height for raw RGB bitmaps, which indicates +bitmap is stored bottom-up. Note that this option does not flip the bitmap +which has to be done manually beforehand, e.g. by using the vflip filter. +Default is @var{false} and indicates bitmap is stored top down. + @end table @anchor{md5} @@ -1462,13 +1591,6 @@ ffmpeg -re @var{} -movflags isml+frag_keyframe -f ismv http://server/publishingpoint.isml/Streams(Encoder1) @end example -@subsection Audible AAX - -Audible AAX files are encrypted M4B files, and they can be decrypted by specifying a 4 byte activation secret. -@example -ffmpeg -activation_bytes 1CEB00DA -i test.aax -vn -c:a copy output.mp4 -@end example - @section mp3 The MP3 muxer writes a raw MP3 stream with the following optional features: @@ -1576,11 +1698,14 @@ @end table @item mpegts_pmt_start_pid @var{integer} -Set the first PID for PMT. Default is @code{0x1000}. Max is @code{0x1f00}. +Set the first PID for PMTs. Default is @code{0x1000}, minimum is @code{0x0020}, +maximum is @code{0x1ffa}. This option has no effect in m2ts mode where the PMT +PID is fixed @code{0x0100}. @item mpegts_start_pid @var{integer} -Set the first PID for data packets. Default is @code{0x0100}. Max is -@code{0x0f00}. +Set the first PID for elementary streams. Default is @code{0x0100}, minimum is +@code{0x0020}, maximum is @code{0x1ffa}. This option has no effect in m2ts mode +where the elementary stream PIDs are fixed. @item mpegts_m2ts_mode @var{boolean} Enable m2ts mode if set to @code{1}. Default value is @code{-1} which @@ -1607,10 +1732,6 @@ Mark the initial packet of each stream as discontinuity. @end table -@item resend_headers @var{integer} -Reemit PAT/PMT before writing the next packet. This option is deprecated: -use @option{mpegts_flags} instead. - @item mpegts_copyts @var{boolean} Preserve original timestamps, if value is set to @code{1}. Default value is @code{-1}, which results in shifting timestamps so that they start from 0. @@ -1619,14 +1740,16 @@ Omit the PES packet length for video packets. Default is @code{1} (true). @item pcr_period @var{integer} -Override the default PCR retransmission time in milliseconds. Ignored if -variable muxrate is selected. Default is @code{20}. +Override the default PCR retransmission time in milliseconds. Default is +@code{-1} which means that the PCR interval will be determined automatically: +20 ms is used for CBR streams, the highest multiple of the frame duration which +is less than 100 ms is used for VBR streams. -@item pat_period @var{double} -Maximum time in seconds between PAT/PMT tables. +@item pat_period @var{duration} +Maximum time in seconds between PAT/PMT tables. Default is @code{0.1}. -@item sdt_period @var{double} -Maximum time in seconds between SDT tables. +@item sdt_period @var{duration} +Maximum time in seconds between SDT tables. Default is @code{0.5}. @item tables_version @var{integer} Set PAT, PMT and SDT version (default @code{0}, valid values are from 0 to 31, inclusively). @@ -2062,6 +2185,53 @@ @end table +@anchor{streamhash} +@section streamhash + +Per stream hash testing format. + +This muxer computes and prints a cryptographic hash of all the input frames, +on a per-stream basis. This can be used for equality checks without having +to do a complete binary comparison. + +By default audio frames are converted to signed 16-bit raw audio and +video frames to raw video before computing the hash, but the output +of explicit conversions to other codecs can also be used. Timestamps +are ignored. It uses the SHA-256 cryptographic hash function by default, +but supports several other algorithms. + +The output of the muxer consists of one line per stream of the form: +@var{streamindex},@var{streamtype},@var{algo}=@var{hash}, where +@var{streamindex} is the index of the mapped stream, @var{streamtype} is a +single character indicating the type of stream, @var{algo} is a short string +representing the hash function used, and @var{hash} is a hexadecimal number +representing the computed hash. + +@table @option +@item hash @var{algorithm} +Use the cryptographic hash function specified by the string @var{algorithm}. +Supported values include @code{MD5}, @code{murmur3}, @code{RIPEMD128}, +@code{RIPEMD160}, @code{RIPEMD256}, @code{RIPEMD320}, @code{SHA160}, +@code{SHA224}, @code{SHA256} (default), @code{SHA512/224}, @code{SHA512/256}, +@code{SHA384}, @code{SHA512}, @code{CRC32} and @code{adler32}. + +@end table + +@subsection Examples + +To compute the SHA-256 hash of the input converted to raw audio and +video, and store it in the file @file{out.sha256}: +@example +ffmpeg -i INPUT -f streamhash out.sha256 +@end example + +To print an MD5 hash to stdout use the command: +@example +ffmpeg -i INPUT -f streamhash -hash md5 - +@end example + +See also the @ref{hash} and @ref{framehash} muxers. + @anchor{fifo} @section fifo @@ -2140,6 +2310,11 @@ Specify whether to wait for the keyframe after recovering from queue overflow or failure. This option is set to 0 (false) by default. +@item timeshift @var{duration} +Buffer the specified amount of packets and delay writing the output. Note that +@var{queue_size} must be big enough to store the packets for timeshift. At the +end of the input the fifo buffer is flushed at realtime speed. + @end table @subsection Examples diff -Nru ffmpeg-4.2.2/doc/outdevs.texi ffmpeg-4.4/doc/outdevs.texi --- ffmpeg-4.2.2/doc/outdevs.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/outdevs.texi 2021-04-08 21:28:39.000000000 +0000 @@ -38,6 +38,52 @@ @end example @end itemize +@section AudioToolbox + +AudioToolbox output device. + +Allows native output to CoreAudio devices on OSX. + +The output filename can be empty (or @code{-}) to refer to the default system output device or a number that refers to the device index as shown using: @code{-list_devices true}. + +Alternatively, the audio input device can be chosen by index using the +@option{ + -audio_device_index +} +, overriding any device name or index given in the input filename. + +All available devices can be enumerated by using @option{-list_devices true}, listing +all device names, UIDs and corresponding indices. + +@subsection Options + +AudioToolbox supports the following options: + +@table @option + +@item -audio_device_index +Specify the audio device by its index. Overrides anything given in the output filename. + +@end table + +@subsection Examples + +@itemize + +@item +Print the list of supported devices and output a sine wave to the default device: +@example +$ ffmpeg -f lavfi -i sine=r=44100 -f audiotoolbox -list_devices true - +@end example + +@item +Output a sine wave to the device with the index 2, overriding any output filename: +@example +$ ffmpeg -f lavfi -i sine=r=44100 -f audiotoolbox -audio_device_index 2 - +@end example + +@end itemize + @section caca CACA output device. @@ -140,8 +186,8 @@ @item list_devices If set to @option{true}, print a list of devices and exit. -Defaults to @option{false}. Alternatively you can use the @code{-sinks} -option of ffmpeg to list the available output devices. +Defaults to @option{false}. This option is deprecated, please use the +@code{-sinks} option of ffmpeg to list the available output devices. @item list_formats If set to @option{true}, print a list of supported formats and exit. @@ -168,7 +214,7 @@ @item List output devices: @example -ffmpeg -i test.avi -f decklink -list_devices 1 dummy +ffmpeg -sinks decklink @end example @item @@ -329,6 +375,8 @@ SDL (Simple DirectMedia Layer) output device. +"sdl2" can be used as alias for "sdl". + This output device allows one to show a video stream in an SDL window. Only one SDL window is allowed per application, so you can have only one instance of this output device in an application. diff -Nru ffmpeg-4.2.2/doc/protocols.texi ffmpeg-4.4/doc/protocols.texi --- ffmpeg-4.2.2/doc/protocols.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/protocols.texi 2021-04-08 21:28:39.000000000 +0000 @@ -51,6 +51,82 @@ A description of the currently available protocols follows. +@section amqp + +Advanced Message Queueing Protocol (AMQP) version 0-9-1 is a broker based +publish-subscribe communication protocol. + +FFmpeg must be compiled with --enable-librabbitmq to support AMQP. A separate +AMQP broker must also be run. An example open-source AMQP broker is RabbitMQ. + +After starting the broker, an FFmpeg client may stream data to the broker using +the command: + +@example +ffmpeg -re -i input -f mpegts amqp://[[user]:[password]@@]hostname[:port][/vhost] +@end example + +Where hostname and port (default is 5672) is the address of the broker. The +client may also set a user/password for authentication. The default for both +fields is "guest". Name of virtual host on broker can be set with vhost. The +default value is "/". + +Muliple subscribers may stream from the broker using the command: +@example +ffplay amqp://[[user]:[password]@@]hostname[:port][/vhost] +@end example + +In RabbitMQ all data published to the broker flows through a specific exchange, +and each subscribing client has an assigned queue/buffer. When a packet arrives +at an exchange, it may be copied to a client's queue depending on the exchange +and routing_key fields. + +The following options are supported: + +@table @option + +@item exchange +Sets the exchange to use on the broker. RabbitMQ has several predefined +exchanges: "amq.direct" is the default exchange, where the publisher and +subscriber must have a matching routing_key; "amq.fanout" is the same as a +broadcast operation (i.e. the data is forwarded to all queues on the fanout +exchange independent of the routing_key); and "amq.topic" is similar to +"amq.direct", but allows for more complex pattern matching (refer to the RabbitMQ +documentation). + +@item routing_key +Sets the routing key. The default value is "amqp". The routing key is used on +the "amq.direct" and "amq.topic" exchanges to decide whether packets are written +to the queue of a subscriber. + +@item pkt_size +Maximum size of each packet sent/received to the broker. Default is 131072. +Minimum is 4096 and max is any large value (representable by an int). When +receiving packets, this sets an internal buffer size in FFmpeg. It should be +equal to or greater than the size of the published packets to the broker. Otherwise +the received message may be truncated causing decoding errors. + +@item connection_timeout +The timeout in seconds during the initial connection to the broker. The +default value is rw_timeout, or 5 seconds if rw_timeout is not set. + +@item delivery_mode @var{mode} +Sets the delivery mode of each message sent to broker. +The following values are accepted: +@table @samp +@item persistent +Delivery mode set to "persistent" (2). This is the default value. +Messages may be written to the broker's disk depending on its setup. + +@item non-persistent +Delivery mode set to "non-persistent" (1). +Messages will stay in broker's memory unless the broker is under memory +pressure. + +@end table + +@end table + @section async Asynchronous data filling wrapper for input stream. @@ -99,6 +175,16 @@ Cache the input stream to temporary file. It brings seeking capability to live streams. +The accepted options are: +@table @option + +@item read_ahead_limit +Amount in bytes that may be read ahead when seeking isn't supported. Range is -1 to INT_MAX. +-1 for unlimited. Default is 65536. + +@end table + +URL Syntax is @example cache:@var{URL} @end example @@ -228,6 +314,14 @@ operation. By default it is set to -1, which means that the timeout is not specified. +@item ftp-user +Set a user to be used for authenticating to the FTP server. This is overridden by the +user in the FTP URL. + +@item ftp-password +Set a password to be used for authenticating to the FTP server. This is overridden by +the password in the FTP URL, or by @option{ftp-anonymous-password} if no user is set. + @item ftp-anonymous-password Password used when login as anonymous user. Typically an e-mail address should be used. @@ -247,6 +341,12 @@ Gopher protocol. +@section gophers + +Gophers protocol. + +The Gopher protocol with TLS encapsulation. + @section hls Read Apple HTTP Live Streaming compliant segmented stream as @@ -309,11 +409,6 @@ @item user-agent This is a deprecated option, you can use user_agent instead it. -@item timeout -Set timeout in microseconds of socket I/O operations used by the underlying low level -operation. By default it is set to -1, which means that the timeout is -not specified. - @item reconnect_at_eof If set then eof is treated like an error and causes reconnection, this is useful for live / endless streams. @@ -321,6 +416,13 @@ @item reconnect_streamed If set then even streamed/non seekable streams will be reconnected on errors. +@item reconnect_on_network_error +Reconnect automatically in case of TCP/TLS errors during connect. + +@item reconnect_on_http_error +A comma separated list of HTTP status codes to reconnect on. The list can +include specific status codes (e.g. '503') or the strings '4xx' / '5xx'. + @item reconnect_delay_max Sets the maximum delay in seconds after which to give up reconnecting @@ -398,6 +500,28 @@ to 0 it won't, if set to -1 it will try to send if it is applicable. Default value is -1. +@item auth_type + +Set HTTP authentication type. No option for Digest, since this method requires +getting nonce parameters from the server first and can't be used straight away like +Basic. + +@table @option +@item none +Choose the HTTP authentication type automatically. This is the default. +@item basic + +Choose the HTTP basic authentication. + +Basic authentication sends a Base64-encoded string that contains a user name and password +for the client. Base64 is not a form of encryption and should be considered the same as +sending the user name and password in clear text (Base64 is a reversible encoding). +If a resource needs to be protected, strongly consider using an authentication scheme +other than basic authentication. HTTPS/TLS should be used with basic authentication. +Without these additional security enhancements, basic authentication should not be used +to protect sensitive or valuable information. +@end table + @end table @subsection HTTP Cookies @@ -452,6 +576,9 @@ This enables support for Icecast versions < 2.4.0, that do not support the HTTP PUT method but the SOURCE method. +@item tls +Establish a TLS (HTTPS) connection to Icecast. + @end table @example @@ -569,6 +696,42 @@ -f rtp_mpegts -fec prompeg=l=8:d=4 rtp://@var{hostname}:@var{port} @end example +@section rist + +Reliable Internet Streaming Transport protocol + +The accepted options are: +@table @option +@item rist_profile +Supported values: +@table @samp +@item simple +@item main +This one is default. +@item advanced +@end table + +@item buffer_size +Set internal RIST buffer size in milliseconds for retransmission of data. +Default value is 0 which means the librist default (1 sec). Maximum value is 30 +seconds. + +@item pkt_size +Set maximum packet size for sending data. 1316 by default. + +@item log_level +Set loglevel for RIST logging messages. You only need to set this if you +explicitly want to enable debug level messages or packet loss simulation, +otherwise the regular loglevel is respected. + +@item secret +Set override of encryption secret, by default is unset. + +@item encryption +Set encryption type, by default is disabled. +Acceptable values are 128 and 256. +@end table + @section rtmp Real-Time Messaging Protocol. @@ -870,6 +1033,9 @@ @item pkt_size=@var{n} Set max packet size (in bytes) to @var{n}. +@item buffer_size=@var{size} +Set the maximum UDP socket buffer size in bytes. + @item connect=0|1 Do a @code{connect()} on the UDP socket (if set to 1) or not (if set to 0). @@ -887,6 +1053,9 @@ @item localport=@var{n} Set the local RTP port to @var{n}. +@item timeout=@var{n} +Set timeout (in microseconds) of socket I/O operations to @var{n}. + This is a deprecated option. Instead, @option{localrtpport} should be used. @@ -1187,7 +1356,7 @@ This protocol accepts the following options. @table @option -@item connect_timeout +@item connect_timeout=@var{milliseconds} Connection timeout; SRT cannot connect for RTT > 1500 msec (2 handshake exchanges) with the default connect timeout of 3 seconds. This option applies to the caller and rendezvous @@ -1218,7 +1387,7 @@ @item ipttl=@var{ttl} IP Time To Live. Applies to sender only. Default value is 64. -@item latency +@item latency=@var{microseconds} Timestamp-based Packet Delivery Delay. Used to absorb bursts of missed packet retransmissions. This flag sets both @option{rcvlatency} and @option{peerlatency} @@ -1229,7 +1398,7 @@ when side is receiver, and the bidirectional stream sending is not supported. -@item listen_timeout +@item listen_timeout=@var{microseconds} Set socket listen timeout. @item maxbw=@var{bytes/seconds} @@ -1274,6 +1443,26 @@ the receiver only if the received data is encrypted. The configured passphrase cannot be recovered (write-only). +@item enforced_encryption=@var{1|0} +If true, both connection parties must have the same password +set (including empty, that is, with no encryption). If the +password doesn't match or only one side is unencrypted, +the connection is rejected. Default is true. + +@item kmrefreshrate=@var{packets} +The number of packets to be transmitted after which the +encryption key is switched to a new key. Default is -1. +-1 means auto (0x1000000 in srt library). The range for +this option is integers in the 0 - @code{INT_MAX}. + +@item kmpreannounce=@var{packets} +The interval between when a new encryption key is sent and +when switchover occurs. This value also applies to the +subsequent interval between when switchover occurs and +when the old encryption key is decommissioned. Default is -1. +-1 means auto (0x1000 in srt library). The range for +this option is integers in the 0 - @code{INT_MAX}. + @item payload_size=@var{bytes} Sets the maximum declared size of a packet transferred during the single call to the sending function in Live @@ -1289,7 +1478,7 @@ @item pkt_size=@var{bytes} Alias for @samp{payload_size}. -@item peerlatency +@item peerlatency=@var{microseconds} The latency value (as described in @option{rcvlatency}) that is set by the sender side as a minimum value for the receiver. @@ -1301,7 +1490,7 @@ key size obtained from sender in HaiCrypt handshake. Default value is 0. -@item rcvlatency +@item rcvlatency=@var{microseconds} The time that should elapse since the moment when the packet was sent and the moment when it's delivered to the receiver application in the receiving function. @@ -1319,12 +1508,10 @@ @item send_buffer_size=@var{bytes} Set UDP send buffer size, expressed in bytes. -@item rw_timeout -Set raise error timeout for read/write optations. - -This option is only relevant in read mode: -if no data arrived in more than this time -interval, raise error. +@item timeout=@var{microseconds} +Set raise error timeouts for read, write and connect operations. Note that the +SRT library has internal timeouts which can be controlled separately, the +value set here is only a cap on those. @item tlpktdrop=@var{1|0} Too-late Packet Drop. When enabled on receiver, it skips @@ -1418,6 +1605,12 @@ file: Set options as for non-live transmission. See @option{messageapi} for further explanations +@item linger=@var{seconds} +The number of seconds that the socket waits for unsent data when closing. +Default is -1. -1 means auto (off with 0 seconds in live mode, on with 180 +seconds in file mode). The range for this option is integers in the +0 - @code{INT_MAX}. + @end table For more information see: @url{https://github.com/Haivision/srt}. @@ -1504,8 +1697,9 @@ The list of supported options follows. @table @option -@item listen=@var{1|0} -Listen for an incoming connection. Default value is 0. +@item listen=@var{2|1|0} +Listen for an incoming connection. 0 disables listen, 1 enables listen in +single client mode, 2 enables listen in multi-client mode. Default value is 0. @item timeout=@var{microseconds} Set raise error timeout, expressed in microseconds. @@ -1581,6 +1775,10 @@ If enabled, listen for connections on the provided port, and assume the server role in the handshake instead of the client role. +@item http_proxy +The HTTP proxy to tunnel through, e.g. @code{http://example.com:1234}. +The proxy must support the CONNECT method. + @end table Example command lines: @@ -1619,7 +1817,7 @@ @item buffer_size=@var{size} Set the UDP maximum socket buffer size in bytes. This is used to set either the receive or send buffer size, depending on what the socket is used for. -Default is 64KB. See also @var{fifo_size}. +Default is 32 KB for output, 384 KB for input. See also @var{fifo_size}. @item bitrate=@var{bitrate} If set to nonzero, the output will have the specified constant bitrate if the @@ -1728,4 +1926,51 @@ Create the Unix socket in listening mode. @end table +@section zmq + +ZeroMQ asynchronous messaging using the libzmq library. + +This library supports unicast streaming to multiple clients without relying on +an external server. + +The required syntax for streaming or connecting to a stream is: +@example +zmq:tcp://ip-address:port +@end example + +Example: +Create a localhost stream on port 5555: +@example +ffmpeg -re -i input -f mpegts zmq:tcp://127.0.0.1:5555 +@end example + +Multiple clients may connect to the stream using: +@example +ffplay zmq:tcp://127.0.0.1:5555 +@end example + +Streaming to multiple clients is implemented using a ZeroMQ Pub-Sub pattern. +The server side binds to a port and publishes data. Clients connect to the +server (via IP address/port) and subscribe to the stream. The order in which +the server and client start generally does not matter. + +ffmpeg must be compiled with the --enable-libzmq option to support +this protocol. + +Options can be set on the @command{ffmpeg}/@command{ffplay} command +line. The following options are supported: + +@table @option + +@item pkt_size +Forces the maximum packet size for sending/receiving data. The default value is +131,072 bytes. On the server side, this sets the maximum size of sent packets +via ZeroMQ. On the clients, it sets an internal buffer size for receiving +packets. Note that pkt_size on the clients should be equal to or greater than +pkt_size on the server. Otherwise the received message may be truncated causing +decoding errors. + +@end table + + @c man end PROTOCOLS diff -Nru ffmpeg-4.2.2/doc/texi2pod.pl ffmpeg-4.4/doc/texi2pod.pl --- ffmpeg-4.2.2/doc/texi2pod.pl 2017-12-31 22:35:45.000000000 +0000 +++ ffmpeg-4.4/doc/texi2pod.pl 2021-04-08 21:28:39.000000000 +0000 @@ -172,6 +172,9 @@ } elsif ($ended =~ /^(?:itemize|enumerate|(?:multi|[fv])?table)$/) { $_ = "\n=back\n"; $ic = pop @icstack; + } elsif ($ended =~ /^float$/) { + $_ = "\n=back\n"; + $ic = pop @icstack; } else { die "unknown command \@end $ended at line $.\n"; } @@ -297,6 +300,12 @@ $_ = ""; # need a paragraph break }; + /^\@(float)\s+\w+/ and do { + push @endwstack, $endw; + $endw = $1; + $_ = "\n=over 4\n"; + }; + /^\@item\s+(.*\S)\s*$/ and $endw eq "multitable" and do { my $columns = $1; $columns =~ s/\@tab/ : /; diff -Nru ffmpeg-4.2.2/doc/utils.texi ffmpeg-4.4/doc/utils.texi --- ffmpeg-4.2.2/doc/utils.texi 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/doc/utils.texi 2021-04-08 21:28:39.000000000 +0000 @@ -110,11 +110,13 @@ @emph{or} @example -[-]@var{S}+[.@var{m}...] +[-]@var{S}+[.@var{m}...][s|ms|us] @end example @var{S} expresses the number of seconds, with the optional decimal part -@var{m}. +@var{m}. The optional literal suffixes @samp{s}, @samp{ms} or @samp{us} +indicate to interpret the value as seconds, milliseconds or microseconds, +respectively. In both expressions, the optional @samp{-} indicates negative duration. @@ -126,6 +128,15 @@ @item 55 55 seconds +@item 0.2 +0.2 seconds + +@item 200ms +200 milliseconds, that's 0.2s + +@item 200000us +200000 microseconds, that's 0.2s + @item 12:03:45 12 hours, 03 minutes and 45 seconds @@ -704,6 +715,8 @@ FL+FR+FC+LFE+FLC+FRC+SL+SR @item octagonal FL+FR+FC+BL+BR+BC+SL+SR +@item hexadecagonal +FL+FR+FC+BL+BR+BC+SL+SR+WL+WR+TBL+TBR+TBC+TFC+TFL+TFR @item downmix DL+DR @end table @@ -920,6 +933,9 @@ @item round(expr) Round the value of expression @var{expr} to the nearest integer. For example, "round(1.5)" is "2.0". +@item sgn(x) +Compute sign of @var{x}. + @item sin(x) Compute sine of @var{x}. diff -Nru ffmpeg-4.2.2/ffbuild/common.mak ffmpeg-4.4/ffbuild/common.mak --- ffmpeg-4.2.2/ffbuild/common.mak 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/ffbuild/common.mak 2021-04-08 21:28:39.000000000 +0000 @@ -44,7 +44,7 @@ define COMPILE $(call $(1)DEP,$(1)) - $($(1)) $($(1)FLAGS) $($(1)_DEPFLAGS) $($(1)_C) $($(1)_O) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) + $($(1)) $($(1)FLAGS) $($(2)) $($(1)_DEPFLAGS) $($(1)_C) $($(1)_O) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) endef COMPILE_C = $(call COMPILE,CC) @@ -54,6 +54,14 @@ COMPILE_X86ASM = $(call COMPILE,X86ASM) COMPILE_HOSTC = $(call COMPILE,HOSTCC) COMPILE_NVCC = $(call COMPILE,NVCC) +COMPILE_MMI = $(call COMPILE,CC,MMIFLAGS) +COMPILE_MSA = $(call COMPILE,CC,MSAFLAGS) + +%_mmi.o: %_mmi.c + $(COMPILE_MMI) + +%_msa.o: %_msa.c + $(COMPILE_MSA) %.o: %.c $(COMPILE_C) @@ -99,7 +107,7 @@ %.c %.h %.pc %.ver %.version: TAG = GEN # Dummy rule to stop make trying to rebuild removed or renamed headers -%.h: +%.h %_template.c: @: # Disable suffix rules. Most of the builtin rules are suffix rules, @@ -162,7 +170,7 @@ OUTDIRS := $(OUTDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(SLIBOBJS) $(TESTOBJS)) -CLEANSUFFIXES = *.d *.gcda *.gcno *.h.c *.ho *.map *.o *.pc *.ptx *.ptx.c *.ver *.version *$(DEFAULT_X86ASMD).asm *~ +CLEANSUFFIXES = *.d *.gcda *.gcno *.h.c *.ho *.map *.o *.pc *.ptx *.ptx.c *.ver *.version *$(DEFAULT_X86ASMD).asm *~ *.ilk *.pdb LIBSUFFIXES = *.a *.lib *.so *.so.* *.dylib *.dll *.def *.dll.a define RULES diff -Nru ffmpeg-4.2.2/fftools/cmdutils.c ffmpeg-4.4/fftools/cmdutils.c --- ffmpeg-4.2.2/fftools/cmdutils.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/fftools/cmdutils.c 2021-04-08 21:28:39.000000000 +0000 @@ -55,9 +55,6 @@ #include "libavutil/ffversion.h" #include "libavutil/version.h" #include "cmdutils.h" -#if CONFIG_NETWORK -#include "libavformat/network.h" -#endif #if HAVE_SYS_RESOURCE_H #include #include @@ -119,7 +116,7 @@ void init_dynload(void) { -#ifdef _WIN32 +#if HAVE_SETDLLDIRECTORY && defined(_WIN32) /* Calling SetDllDirectory with the empty string (but not NULL) removes the * current working directory from the DLL search path as a security pre-caution. */ SetDllDirectory(""); @@ -182,7 +179,7 @@ first = 1; for (po = options; po->name; po++) { - char buf[64]; + char buf[128]; if (((po->flags & req_flags) != req_flags) || (alt_flags && !(po->flags & alt_flags)) || @@ -205,23 +202,22 @@ void show_help_children(const AVClass *class, int flags) { - const AVClass *child = NULL; + void *iter = NULL; + const AVClass *child; if (class->option) { av_opt_show2(&class, NULL, flags, 0); printf("\n"); } - while (child = av_opt_child_class_next(class, child)) + while (child = av_opt_child_class_iterate(class, &iter)) show_help_children(child, flags); } static const OptionDef *find_option(const OptionDef *po, const char *name) { - const char *p = strchr(name, ':'); - int len = p ? p - name : strlen(name); - while (po->name) { - if (!strncmp(name, po->name, len) && strlen(po->name) == len) + const char *end; + if (av_strstart(name, po->name, &end) && (!*end || *end == ':')) break; po++; } @@ -848,8 +844,8 @@ } if (octx->cur_group.nb_opts || codec_opts || format_opts || resample_opts) - av_log(NULL, AV_LOG_WARNING, "Trailing options were found on the " - "commandline.\n"); + av_log(NULL, AV_LOG_WARNING, "Trailing option(s) found in the " + "command: may be ignored.\n"); av_log(NULL, AV_LOG_DEBUG, "Finished splitting the commandline.\n"); @@ -980,6 +976,7 @@ char *filename_template = NULL; char *key, *val; int ret, count = 0; + int prog_loglevel, envlevel = 0; time_t now; struct tm *tm; AVBPrint filename; @@ -1011,6 +1008,7 @@ av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n"); exit_program(1); } + envlevel = 1; } else { av_log(NULL, AV_LOG_ERROR, "Unknown key '%s' in FFREPORT\n", key); } @@ -1027,6 +1025,10 @@ return AVERROR(ENOMEM); } + prog_loglevel = av_log_get_level(); + if (!envlevel) + report_file_level = FFMAX(report_file_level, prog_loglevel); + report_file = fopen(filename.str, "w"); if (!report_file) { int ret = AVERROR(errno); @@ -1037,16 +1039,17 @@ av_log_set_callback(log_callback_report); av_log(NULL, AV_LOG_INFO, "%s started on %04d-%02d-%02d at %02d:%02d:%02d\n" - "Report written to \"%s\"\n", + "Report written to \"%s\"\n" + "Log level: %d\n", program_name, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, - filename.str); + filename.str, report_file_level); av_bprint_finalize(&filename, NULL); return 0; } -int opt_report(const char *opt) +int opt_report(void *optctx, const char *opt, const char *arg) { return init_report(NULL); } @@ -1160,13 +1163,13 @@ // Change all the ' --' strings to '~--' so that // they can be identified as tokens. while ((conflist = strstr(str, " --")) != NULL) { - strncpy(conflist, "~--", 3); + conflist[0] = '~'; } // Compensate for the weirdness this would cause // when passing 'pkg-config --static'. while ((remove_tilde = strstr(str, "pkg-config~")) != NULL) { - strncpy(remove_tilde, "pkg-config ", 11); + remove_tilde[sizeof("pkg-config~") - 2] = ' '; } splitconf = strtok(str, "~"); @@ -1412,14 +1415,10 @@ printf("variable "); if (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS | - AV_CODEC_CAP_AUTO_THREADS)) + AV_CODEC_CAP_OTHER_THREADS)) printf("threads "); if (c->capabilities & AV_CODEC_CAP_AVOID_PROBING) printf("avoidprobe "); - if (c->capabilities & AV_CODEC_CAP_INTRA_ONLY) - printf("intraonly "); - if (c->capabilities & AV_CODEC_CAP_LOSSLESS) - printf("lossless "); if (c->capabilities & AV_CODEC_CAP_HARDWARE) printf("hardware "); if (c->capabilities & AV_CODEC_CAP_HYBRID) @@ -1433,12 +1432,12 @@ printf(" Threading capabilities: "); switch (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS | - AV_CODEC_CAP_AUTO_THREADS)) { + AV_CODEC_CAP_OTHER_THREADS)) { case AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS: printf("frame and slice"); break; case AV_CODEC_CAP_FRAME_THREADS: printf("frame"); break; case AV_CODEC_CAP_SLICE_THREADS: printf("slice"); break; - case AV_CODEC_CAP_AUTO_THREADS : printf("auto"); break; + case AV_CODEC_CAP_OTHER_THREADS: printf("other"); break; default: printf("none"); break; } printf("\n"); @@ -1493,13 +1492,14 @@ } } -static const AVCodec *next_codec_for_id(enum AVCodecID id, const AVCodec *prev, +static const AVCodec *next_codec_for_id(enum AVCodecID id, void **iter, int encoder) { - while ((prev = av_codec_next(prev))) { - if (prev->id == id && - (encoder ? av_codec_is_encoder(prev) : av_codec_is_decoder(prev))) - return prev; + const AVCodec *c; + while ((c = av_codec_iterate(iter))) { + if (c->id == id && + (encoder ? av_codec_is_encoder(c) : av_codec_is_decoder(c))) + return c; } return NULL; } @@ -1536,11 +1536,12 @@ static void print_codecs_for_id(enum AVCodecID id, int encoder) { - const AVCodec *codec = NULL; + void *iter = NULL; + const AVCodec *codec; printf(" (%s: ", encoder ? "encoders" : "decoders"); - while ((codec = next_codec_for_id(id, codec, encoder))) + while ((codec = next_codec_for_id(id, &iter, encoder))) printf("%s ", codec->name); printf(")"); @@ -1563,7 +1564,8 @@ " -------\n"); for (i = 0; i < nb_codecs; i++) { const AVCodecDescriptor *desc = codecs[i]; - const AVCodec *codec = NULL; + const AVCodec *codec; + void *iter = NULL; if (strstr(desc->name, "_deprecated")) continue; @@ -1581,14 +1583,14 @@ /* print decoders/encoders when there's more than one or their * names are different from codec name */ - while ((codec = next_codec_for_id(desc->id, codec, 0))) { + while ((codec = next_codec_for_id(desc->id, &iter, 0))) { if (strcmp(codec->name, desc->name)) { print_codecs_for_id(desc->id, 0); break; } } - codec = NULL; - while ((codec = next_codec_for_id(desc->id, codec, 1))) { + iter = NULL; + while ((codec = next_codec_for_id(desc->id, &iter, 1))) { if (strcmp(codec->name, desc->name)) { print_codecs_for_id(desc->id, 1); break; @@ -1619,9 +1621,10 @@ encoder ? "Encoders" : "Decoders"); for (i = 0; i < nb_codecs; i++) { const AVCodecDescriptor *desc = codecs[i]; - const AVCodec *codec = NULL; + const AVCodec *codec; + void *iter = NULL; - while ((codec = next_codec_for_id(desc->id, codec, encoder))) { + while ((codec = next_codec_for_id(desc->id, &iter, encoder))) { printf(" %c", get_media_type_char(desc->type)); printf((codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? "F" : "."); printf((codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? "S" : "."); @@ -1826,9 +1829,10 @@ if (codec) print_codec(codec); else if ((desc = avcodec_descriptor_get_by_name(name))) { + void *iter = NULL; int printed = 0; - while ((codec = next_codec_for_id(desc->id, codec, encoder))) { + while ((codec = next_codec_for_id(desc->id, &iter, encoder))) { printed = 1; print_codec(codec); } @@ -1863,6 +1867,24 @@ show_help_children(fmt->priv_class, AV_OPT_FLAG_DECODING_PARAM); } +static void show_help_protocol(const char *name) +{ + const AVClass *proto_class; + + if (!name) { + av_log(NULL, AV_LOG_ERROR, "No protocol name specified.\n"); + return; + } + + proto_class = avio_protocol_get_class(name); + if (!proto_class) { + av_log(NULL, AV_LOG_ERROR, "Unknown protocol '%s'.\n", name); + return; + } + + show_help_children(proto_class, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM); +} + static void show_help_muxer(const char *name) { const AVCodecDescriptor *desc; @@ -1993,6 +2015,8 @@ show_help_demuxer(par); } else if (!strcmp(topic, "muxer")) { show_help_muxer(par); + } else if (!strcmp(topic, "protocol")) { + show_help_protocol(par); #if CONFIG_AVFILTER } else if (!strcmp(topic, "filter")) { show_help_filter(par); @@ -2032,7 +2056,7 @@ av_strlcpy(filename, preset_name, filename_size); f = fopen(filename, "r"); } else { -#ifdef _WIN32 +#if HAVE_GETMODULEHANDLE && defined(_WIN32) char datadir[MAX_PATH], *ls; base[2] = NULL; @@ -2077,7 +2101,7 @@ } AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, - AVFormatContext *s, AVStream *st, AVCodec *codec) + AVFormatContext *s, AVStream *st, const AVCodec *codec) { AVDictionary *ret = NULL; AVDictionaryEntry *t = NULL; @@ -2106,6 +2130,7 @@ } while (t = av_dict_get(opts, "", t, AV_DICT_IGNORE_SUFFIX)) { + const AVClass *priv_class; char *p = strchr(t->key, ':'); /* check stream specification in opt name */ @@ -2118,8 +2143,8 @@ if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) || !codec || - (codec->priv_class && - av_opt_find(&codec->priv_class, t->key, NULL, flags, + ((priv_class = codec->priv_class) && + av_opt_find(&priv_class, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ))) av_dict_set(&ret, t->key, t->value, 0); else if (t->key[0] == prefix && @@ -2185,7 +2210,7 @@ if (fabs(theta - 90*round(theta/90)) > 2) av_log(NULL, AV_LOG_WARNING, "Odd rotation angle.\n" "If you want to help, upload a sample " - "of this file to ftp://upload.ffmpeg.org/incoming/ " + "of this file to https://streams.videolan.org/upload/ " "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)"); return theta; @@ -2282,7 +2307,7 @@ int ret = 0; int error_level = av_log_get_level(); - av_log_set_level(AV_LOG_ERROR); + av_log_set_level(AV_LOG_WARNING); if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0) goto fail; @@ -2320,7 +2345,7 @@ int ret = 0; int error_level = av_log_get_level(); - av_log_set_level(AV_LOG_ERROR); + av_log_set_level(AV_LOG_WARNING); if ((ret = show_sinks_sources_parse_arg(arg, &dev, &opts)) < 0) goto fail; diff -Nru ffmpeg-4.2.2/fftools/cmdutils.h ffmpeg-4.4/fftools/cmdutils.h --- ffmpeg-4.2.2/fftools/cmdutils.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/fftools/cmdutils.h 2021-04-08 21:28:39.000000000 +0000 @@ -99,7 +99,7 @@ */ int opt_loglevel(void *optctx, const char *opt, const char *arg); -int opt_report(const char *opt); +int opt_report(void *optctx, const char *opt, const char *arg); int opt_max_alloc(void *optctx, const char *opt, const char *arg); @@ -236,7 +236,7 @@ { "colors", OPT_EXIT, { .func_arg = show_colors }, "show available color names" }, \ { "loglevel", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \ { "v", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \ - { "report", 0, { (void*)opt_report }, "generate a report" }, \ + { "report", 0, { .func_arg = opt_report }, "generate a report" }, \ { "max_alloc", HAS_ARG, { .func_arg = opt_max_alloc }, "set maximum size of a single allocated block", "bytes" }, \ { "cpuflags", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" }, \ { "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, \ @@ -414,7 +414,7 @@ * @return a pointer to the created dictionary */ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, - AVFormatContext *s, AVStream *st, AVCodec *codec); + AVFormatContext *s, AVStream *st, const AVCodec *codec); /** * Setup AVCodecContext options for avformat_find_stream_info(). diff -Nru ffmpeg-4.2.2/fftools/ffmpeg.c ffmpeg-4.4/fftools/ffmpeg.c --- ffmpeg-4.2.2/fftools/ffmpeg.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/fftools/ffmpeg.c 2021-04-08 21:28:39.000000000 +0000 @@ -136,6 +136,7 @@ static unsigned dup_warning = 1000; static int nb_frames_drop = 0; static int64_t decode_error_stat[2]; +static unsigned nb_output_dumped = 0; static int want_sdp = 1; @@ -182,7 +183,7 @@ ist->sub2video.frame->width = ist->dec_ctx->width ? ist->dec_ctx->width : ist->sub2video.w; ist->sub2video.frame->height = ist->dec_ctx->height ? ist->dec_ctx->height : ist->sub2video.h; ist->sub2video.frame->format = AV_PIX_FMT_RGB32; - if ((ret = av_frame_get_buffer(frame, 32)) < 0) + if ((ret = av_frame_get_buffer(frame, 0)) < 0) return ret; memset(frame->data[0], 0, frame->height * frame->linesize[0]); return 0; @@ -237,7 +238,7 @@ } } -void sub2video_update(InputStream *ist, AVSubtitle *sub) +void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub) { AVFrame *frame = ist->sub2video.frame; int8_t *dst; @@ -254,7 +255,12 @@ AV_TIME_BASE_Q, ist->st->time_base); num_rects = sub->num_rects; } else { - pts = ist->sub2video.end_pts; + /* If we are initializing the system, utilize current heartbeat + PTS as the start time, and show until the following subpicture + is received. Otherwise, utilize the previous subpicture's end time + as the fall-back value. */ + pts = ist->sub2video.initialize ? + heartbeat_pts : ist->sub2video.end_pts; end_pts = INT64_MAX; num_rects = 0; } @@ -269,6 +275,7 @@ sub2video_copy_rect(dst, dst_linesize, frame->width, frame->height, sub->rects[i]); sub2video_push_ref(ist, pts); ist->sub2video.end_pts = end_pts; + ist->sub2video.initialize = 0; } static void sub2video_heartbeat(InputStream *ist, int64_t pts) @@ -291,9 +298,11 @@ /* do not send the heartbeat frame if the subtitle is already ahead */ if (pts2 <= ist2->sub2video.last_pts) continue; - if (pts2 >= ist2->sub2video.end_pts || - (!ist2->sub2video.frame->data[0] && ist2->sub2video.end_pts < INT64_MAX)) - sub2video_update(ist2, NULL); + if (pts2 >= ist2->sub2video.end_pts || ist2->sub2video.initialize) + /* if we have hit the end of the current displayed subpicture, + or if we need to initialize the system, update the + overlayed subpicture and its start/end times */ + sub2video_update(ist2, pts2 + 1, NULL); for (j = 0, nb_reqs = 0; j < ist2->nb_filters; j++) nb_reqs += av_buffersrc_get_nb_failed_requests(ist2->filters[j]->filter); if (nb_reqs) @@ -307,7 +316,7 @@ int ret; if (ist->sub2video.end_pts < INT64_MAX) - sub2video_update(ist, NULL); + sub2video_update(ist, INT64_MAX, NULL); for (i = 0; i < ist->nb_filters; i++) { ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL); if (ret != AVERROR_EOF && ret < 0) @@ -336,6 +345,7 @@ static atomic_int transcode_init_done = ATOMIC_VAR_INIT(0); static volatile int ffmpeg_exited = 0; static int main_return_code = 0; +static int64_t copy_ts_first_pts = AV_NOPTS_VALUE; static void sigterm_handler(int sig) @@ -384,8 +394,30 @@ } #endif +#ifdef __linux__ +#define SIGNAL(sig, func) \ + do { \ + action.sa_handler = func; \ + sigaction(sig, &action, NULL); \ + } while (0) +#else +#define SIGNAL(sig, func) \ + signal(sig, func) +#endif + void term_init(void) { +#if defined __linux__ + struct sigaction action = {0}; + action.sa_handler = sigterm_handler; + + /* block other interrupts while processing this one */ + sigfillset(&action.sa_mask); + + /* restart interruptible functions (i.e. don't fail with EINTR) */ + action.sa_flags = SA_RESTART; +#endif + #if HAVE_TERMIOS_H if (!run_as_daemon && stdin_interaction) { struct termios tty; @@ -404,14 +436,14 @@ tcsetattr (0, TCSANOW, &tty); } - signal(SIGQUIT, sigterm_handler); /* Quit (POSIX). */ + SIGNAL(SIGQUIT, sigterm_handler); /* Quit (POSIX). */ } #endif - signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */ - signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */ + SIGNAL(SIGINT , sigterm_handler); /* Interrupt (ANSI). */ + SIGNAL(SIGTERM, sigterm_handler); /* Termination (ANSI). */ #ifdef SIGXCPU - signal(SIGXCPU, sigterm_handler); + SIGNAL(SIGXCPU, sigterm_handler); #endif #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); /* Broken pipe (POSIX). */ @@ -493,32 +525,38 @@ FilterGraph *fg = filtergraphs[i]; avfilter_graph_free(&fg->graph); for (j = 0; j < fg->nb_inputs; j++) { - while (av_fifo_size(fg->inputs[j]->frame_queue)) { + InputFilter *ifilter = fg->inputs[j]; + struct InputStream *ist = ifilter->ist; + + while (av_fifo_size(ifilter->frame_queue)) { AVFrame *frame; - av_fifo_generic_read(fg->inputs[j]->frame_queue, &frame, + av_fifo_generic_read(ifilter->frame_queue, &frame, sizeof(frame), NULL); av_frame_free(&frame); } - av_fifo_freep(&fg->inputs[j]->frame_queue); - if (fg->inputs[j]->ist->sub2video.sub_queue) { - while (av_fifo_size(fg->inputs[j]->ist->sub2video.sub_queue)) { + av_fifo_freep(&ifilter->frame_queue); + if (ist->sub2video.sub_queue) { + while (av_fifo_size(ist->sub2video.sub_queue)) { AVSubtitle sub; - av_fifo_generic_read(fg->inputs[j]->ist->sub2video.sub_queue, + av_fifo_generic_read(ist->sub2video.sub_queue, &sub, sizeof(sub), NULL); avsubtitle_free(&sub); } - av_fifo_freep(&fg->inputs[j]->ist->sub2video.sub_queue); + av_fifo_freep(&ist->sub2video.sub_queue); } - av_buffer_unref(&fg->inputs[j]->hw_frames_ctx); - av_freep(&fg->inputs[j]->name); + av_buffer_unref(&ifilter->hw_frames_ctx); + av_freep(&ifilter->name); av_freep(&fg->inputs[j]); } av_freep(&fg->inputs); for (j = 0; j < fg->nb_outputs; j++) { - av_freep(&fg->outputs[j]->name); - av_freep(&fg->outputs[j]->formats); - av_freep(&fg->outputs[j]->channel_layouts); - av_freep(&fg->outputs[j]->sample_rates); + OutputFilter *ofilter = fg->outputs[j]; + + 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); @@ -550,12 +588,11 @@ if (!ost) continue; - for (j = 0; j < ost->nb_bitstream_filters; j++) - av_bsf_free(&ost->bsf_ctx[j]); - av_freep(&ost->bsf_ctx); + av_bsf_free(&ost->bsf_ctx); av_frame_free(&ost->filtered_frame); av_frame_free(&ost->last_frame); + av_packet_free(&ost->pkt); av_dict_free(&ost->encoder_opts); av_freep(&ost->forced_keyframes); @@ -567,15 +604,16 @@ ost->audio_channels_mapped = 0; av_dict_free(&ost->sws_dict); + av_dict_free(&ost->swr_opts); avcodec_free_context(&ost->enc_ctx); avcodec_parameters_free(&ost->ref_par); if (ost->muxing_queue) { while (av_fifo_size(ost->muxing_queue)) { - AVPacket pkt; + AVPacket *pkt; av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL); - av_packet_unref(&pkt); + av_packet_free(&pkt); } av_fifo_freep(&ost->muxing_queue); } @@ -587,6 +625,7 @@ #endif for (i = 0; i < nb_input_files; i++) { avformat_close_input(&input_files[i]->ctx); + av_packet_free(&input_files[i]->pkt); av_freep(&input_files[i]); } for (i = 0; i < nb_input_streams; i++) { @@ -594,6 +633,7 @@ 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); av_frame_free(&ist->sub2video.frame); @@ -651,7 +691,7 @@ } } -static void abort_codec_experimental(AVCodec *c, int encoder) +static void abort_codec_experimental(const AVCodec *c, int encoder) { exit_program(1); } @@ -709,11 +749,16 @@ } if (!of->header_written) { - AVPacket tmp_pkt = {0}; + AVPacket *tmp_pkt; /* the muxer is not initialized yet, buffer the packet */ if (!av_fifo_space(ost->muxing_queue)) { - int new_size = FFMIN(2 * av_fifo_size(ost->muxing_queue), - ost->max_muxing_queue_size); + 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); + if (new_size <= av_fifo_size(ost->muxing_queue)) { av_log(NULL, AV_LOG_ERROR, "Too many packets buffered for output stream %d:%d.\n", @@ -727,7 +772,11 @@ ret = av_packet_make_refcounted(pkt); if (ret < 0) exit_program(1); - av_packet_move_ref(&tmp_pkt, pkt); + tmp_pkt = av_packet_alloc(); + if (!tmp_pkt) + exit_program(1); + av_packet_move_ref(tmp_pkt, pkt); + ost->muxing_queue_data_size += tmp_pkt->size; av_fifo_generic_write(ost->muxing_queue, &tmp_pkt, sizeof(tmp_pkt), NULL); return; } @@ -779,6 +828,8 @@ int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT); if (pkt->dts < max) { int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; + if (exit_on_error) + loglevel = AV_LOG_ERROR; av_log(s, loglevel, "Non-monotonous DTS in output stream " "%d:%d; previous: %"PRId64", current: %"PRId64"; ", ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts); @@ -848,40 +899,15 @@ { int ret = 0; - /* apply the output bitstream filters, if any */ - if (ost->nb_bitstream_filters) { - int idx; - - ret = av_bsf_send_packet(ost->bsf_ctx[0], eof ? NULL : pkt); + /* apply the output bitstream filters */ + if (ost->bsf_ctx) { + ret = av_bsf_send_packet(ost->bsf_ctx, eof ? NULL : pkt); if (ret < 0) goto finish; - - eof = 0; - idx = 1; - while (idx) { - /* get a packet from the previous filter up the chain */ - ret = av_bsf_receive_packet(ost->bsf_ctx[idx - 1], pkt); - if (ret == AVERROR(EAGAIN)) { - ret = 0; - idx--; - continue; - } else if (ret == AVERROR_EOF) { - eof = 1; - } else if (ret < 0) - goto finish; - - /* send it to the next filter down the chain or to the muxer */ - if (idx < ost->nb_bitstream_filters) { - ret = av_bsf_send_packet(ost->bsf_ctx[idx], eof ? NULL : pkt); - if (ret < 0) - goto finish; - idx++; - eof = 0; - } else if (eof) - goto finish; - else - write_packet(of, pkt, ost, 0); - } + while ((ret = av_bsf_receive_packet(ost->bsf_ctx, pkt)) >= 0) + write_packet(of, pkt, ost, 0); + if (ret == AVERROR(EAGAIN)) + ret = 0; } else if (!eof) write_packet(of, pkt, ost, 0); @@ -907,16 +933,82 @@ return 1; } +static double adjust_frame_pts_to_encoder_tb(OutputFile *of, OutputStream *ost, + AVFrame *frame) +{ + double float_pts = AV_NOPTS_VALUE; // this is identical to frame.pts but with higher precision + AVCodecContext *enc = ost->enc_ctx; + if (!frame || frame->pts == AV_NOPTS_VALUE || + !enc || !ost->filter || !ost->filter->graph->graph) + goto early_exit; + + { + AVFilterContext *filter = ost->filter->filter; + + int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; + AVRational filter_tb = av_buffersink_get_time_base(filter); + AVRational tb = enc->time_base; + int extra_bits = av_clip(29 - av_log2(tb.den), 0, 16); + + tb.den <<= extra_bits; + float_pts = + av_rescale_q(frame->pts, filter_tb, tb) - + av_rescale_q(start_time, AV_TIME_BASE_Q, tb); + float_pts /= 1 << extra_bits; + // avoid exact midoints to reduce the chance of rounding differences, this can be removed in case the fps code is changed to work with integers + float_pts += FFSIGN(float_pts) * 1.0 / (1<<17); + + frame->pts = + av_rescale_q(frame->pts, filter_tb, enc->time_base) - + av_rescale_q(start_time, AV_TIME_BASE_Q, enc->time_base); + } + +early_exit: + + if (debug_ts) { + av_log(NULL, AV_LOG_INFO, "filter -> pts:%s pts_time:%s exact:%f time_base:%d/%d\n", + frame ? av_ts2str(frame->pts) : "NULL", + frame ? av_ts2timestr(frame->pts, &enc->time_base) : "NULL", + float_pts, + enc ? enc->time_base.num : -1, + enc ? enc->time_base.den : -1); + } + + return float_pts; +} + +static int init_output_stream(OutputStream *ost, AVFrame *frame, + char *error, int error_len); + +static int init_output_stream_wrapper(OutputStream *ost, AVFrame *frame, + unsigned int fatal) +{ + int ret = AVERROR_BUG; + char error[1024] = {0}; + + if (ost->initialized) + return 0; + + ret = init_output_stream(ost, frame, error, sizeof(error)); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n", + ost->file_index, ost->index, error); + + if (fatal) + exit_program(1); + } + + return ret; +} + static void do_audio_out(OutputFile *of, OutputStream *ost, AVFrame *frame) { AVCodecContext *enc = ost->enc_ctx; - AVPacket pkt; + AVPacket *pkt = ost->pkt; int ret; - av_init_packet(&pkt); - pkt.data = NULL; - pkt.size = 0; + adjust_frame_pts_to_encoder_tb(of, ost, frame); if (!check_recording_time(ost)) return; @@ -927,7 +1019,6 @@ ost->samples_encoded += frame->nb_samples; ost->frames_encoded++; - av_assert0(pkt.size || !pkt.data); update_benchmark(NULL); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder <- type:audio " @@ -941,7 +1032,8 @@ goto error; while (1) { - ret = avcodec_receive_packet(enc, &pkt); + av_packet_unref(pkt); + ret = avcodec_receive_packet(enc, pkt); if (ret == AVERROR(EAGAIN)) break; if (ret < 0) @@ -949,16 +1041,16 @@ update_benchmark("encode_audio %d.%d", ost->file_index, ost->index); - av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase); + av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:audio " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &enc->time_base), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &enc->time_base)); + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base)); } - output_packet(of, &pkt, ost, 0); + output_packet(of, pkt, ost, 0); } return; @@ -974,7 +1066,7 @@ int subtitle_out_max_size = 1024 * 1024; int subtitle_out_size, nb, i; AVCodecContext *enc; - AVPacket pkt; + AVPacket *pkt = ost->pkt; int64_t pts; if (sub->pts == AV_NOPTS_VALUE) { @@ -1032,41 +1124,43 @@ exit_program(1); } - av_init_packet(&pkt); - pkt.data = subtitle_out; - pkt.size = subtitle_out_size; - pkt.pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->mux_timebase); - pkt.duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); + av_packet_unref(pkt); + pkt->data = subtitle_out; + pkt->size = subtitle_out_size; + pkt->pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->mux_timebase); + pkt->duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE) { /* XXX: the pts correction is handled here. Maybe handling it in the codec would be better */ if (i == 0) - pkt.pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); + pkt->pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); else - pkt.pts += av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); + pkt->pts += av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); } - pkt.dts = pkt.pts; - output_packet(of, &pkt, ost, 0); + pkt->dts = pkt->pts; + output_packet(of, pkt, ost, 0); } } static void do_video_out(OutputFile *of, OutputStream *ost, - AVFrame *next_picture, - double sync_ipts) + AVFrame *next_picture) { int ret, format_video_sync; - AVPacket pkt; + AVPacket *pkt = ost->pkt; AVCodecContext *enc = ost->enc_ctx; - AVCodecParameters *mux_par = ost->st->codecpar; AVRational frame_rate; int nb_frames, nb0_frames, i; double delta, delta0; double duration = 0; + double sync_ipts = AV_NOPTS_VALUE; int frame_size = 0; InputStream *ist = NULL; AVFilterContext *filter = ost->filter->filter; + init_output_stream_wrapper(ost, next_picture, 1); + sync_ipts = adjust_frame_pts_to_encoder_tb(of, ost, next_picture); + if (ost->source_index >= 0) ist = input_streams[ost->source_index]; @@ -1136,7 +1230,7 @@ av_log(NULL, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0)); delta = duration; delta0 = 0; - ost->sync_opts = lrint(sync_ipts); + ost->sync_opts = llrint(sync_ipts); } case VSYNC_CFR: // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c @@ -1147,18 +1241,18 @@ else if (delta > 1.1) { nb_frames = lrintf(delta); if (delta0 > 1.1) - nb0_frames = lrintf(delta0 - 0.6); + nb0_frames = llrintf(delta0 - 0.6); } break; case VSYNC_VFR: if (delta <= -0.6) nb_frames = 0; else if (delta > 0.6) - ost->sync_opts = lrint(sync_ipts); + ost->sync_opts = llrint(sync_ipts); break; case VSYNC_DROP: case VSYNC_PASSTHROUGH: - ost->sync_opts = lrint(sync_ipts); + ost->sync_opts = llrint(sync_ipts); break; default: av_assert0(0); @@ -1199,9 +1293,6 @@ AVFrame *in_picture; int forced_keyframe = 0; double pts_time; - av_init_packet(&pkt); - pkt.data = NULL; - pkt.size = 0; if (i < nb0_frames && ost->last_frame) { in_picture = ost->last_frame; @@ -1216,18 +1307,6 @@ if (!check_recording_time(ost)) return; - if (enc->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && - ost->top_field_first >= 0) - in_picture->top_field_first = !!ost->top_field_first; - - if (in_picture->interlaced_frame) { - if (enc->codec->id == AV_CODEC_ID_MJPEG) - mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; - else - mux_par->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; - } else - mux_par->field_order = AV_FIELD_PROGRESSIVE; - in_picture->quality = enc->global_quality; in_picture->pict_type = 0; @@ -1265,7 +1344,8 @@ ost->forced_keyframes_expr_const_values[FKF_N] += 1; } else if ( ost->forced_keyframes && !strncmp(ost->forced_keyframes, "source", 6) - && in_picture->key_frame==1) { + && in_picture->key_frame==1 + && !i) { forced_keyframe = 1; } @@ -1291,7 +1371,8 @@ av_frame_remove_side_data(in_picture, AV_FRAME_DATA_A53_CC); while (1) { - ret = avcodec_receive_packet(enc, &pkt); + av_packet_unref(pkt); + ret = avcodec_receive_packet(enc, pkt); update_benchmark("encode_video %d.%d", ost->file_index, ost->index); if (ret == AVERROR(EAGAIN)) break; @@ -1301,24 +1382,24 @@ if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:video " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &enc->time_base), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &enc->time_base)); + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base)); } - if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & AV_CODEC_CAP_DELAY)) - pkt.pts = ost->sync_opts; + if (pkt->pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & AV_CODEC_CAP_DELAY)) + pkt->pts = ost->sync_opts; - av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase); + av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:video " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ost->mux_timebase), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->mux_timebase)); + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->mux_timebase), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->mux_timebase)); } - frame_size = pkt.size; - output_packet(of, &pkt, ost, 0); + frame_size = pkt->size; + output_packet(of, pkt, ost, 0); /* if two pass, output log */ if (ost->logfile && enc->stats_out) { @@ -1399,8 +1480,6 @@ } } -static int init_output_stream(OutputStream *ost, char *error, int error_len); - static void finish_output_stream(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; @@ -1437,23 +1516,27 @@ continue; filter = ost->filter->filter; - if (!ost->initialized) { - char error[1024] = ""; - ret = init_output_stream(ost, error, sizeof(error)); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n", - ost->file_index, ost->index, error); - exit_program(1); - } - } + /* + * Unlike video, with audio the audio frame size matters. + * Currently we are fully reliant on the lavfi filter chain to + * do the buffering deed for us, and thus the frame size parameter + * needs to be set accordingly. Where does one get the required + * frame size? From the initialized AVCodecContext of an audio + * encoder. Thus, if we have gotten to an audio stream, initialize + * the encoder earlier than receiving the first AVFrame. + */ + if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_AUDIO) + init_output_stream_wrapper(ost, NULL, 1); + if (!ost->pkt && !(ost->pkt = av_packet_alloc())) { + return AVERROR(ENOMEM); + } if (!ost->filtered_frame && !(ost->filtered_frame = av_frame_alloc())) { return AVERROR(ENOMEM); } filtered_frame = ost->filtered_frame; while (1) { - double float_pts = AV_NOPTS_VALUE; // this is identical to filtered_frame.pts but with higher precision ret = av_buffersink_get_frame_flags(filter, filtered_frame, AV_BUFFERSINK_FLAG_NO_REQUEST); if (ret < 0) { @@ -1462,7 +1545,7 @@ "Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret)); } else if (flush && ret == AVERROR_EOF) { if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_VIDEO) - do_video_out(of, ost, NULL, AV_NOPTS_VALUE); + do_video_out(of, ost, NULL); } break; } @@ -1470,38 +1553,13 @@ av_frame_unref(filtered_frame); continue; } - if (filtered_frame->pts != AV_NOPTS_VALUE) { - int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; - AVRational filter_tb = av_buffersink_get_time_base(filter); - AVRational tb = enc->time_base; - int extra_bits = av_clip(29 - av_log2(tb.den), 0, 16); - - tb.den <<= extra_bits; - float_pts = - av_rescale_q(filtered_frame->pts, filter_tb, tb) - - av_rescale_q(start_time, AV_TIME_BASE_Q, tb); - float_pts /= 1 << extra_bits; - // avoid exact midoints to reduce the chance of rounding differences, this can be removed in case the fps code is changed to work with integers - float_pts += FFSIGN(float_pts) * 1.0 / (1<<17); - - filtered_frame->pts = - av_rescale_q(filtered_frame->pts, filter_tb, enc->time_base) - - av_rescale_q(start_time, AV_TIME_BASE_Q, enc->time_base); - } switch (av_buffersink_get_type(filter)) { case AVMEDIA_TYPE_VIDEO: if (!ost->frame_aspect_ratio.num) enc->sample_aspect_ratio = filtered_frame->sample_aspect_ratio; - if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "filter -> pts:%s pts_time:%s exact:%f time_base:%d/%d\n", - av_ts2str(filtered_frame->pts), av_ts2timestr(filtered_frame->pts, &enc->time_base), - float_pts, - enc->time_base.num, enc->time_base.den); - } - - do_video_out(of, ost, filtered_frame, float_pts); + do_video_out(of, ost, filtered_frame); break; case AVMEDIA_TYPE_AUDIO: if (!(enc->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) && @@ -1653,6 +1711,7 @@ double speed; int64_t pts = INT64_MIN + 1; static int64_t last_time = -1; + static int first_report = 1; static int qp_histogram[52]; int hours, mins, secs, us; const char *hours_sign; @@ -1665,9 +1724,9 @@ if (!is_last_report) { if (last_time == -1) { last_time = cur_time; - return; } - if ((cur_time - last_time) < 500000) + if (((cur_time - last_time) < stats_period && !first_report) || + (first_report && nb_output_dumped < nb_output_files)) return; last_time = cur_time; } @@ -1750,9 +1809,17 @@ vid = 1; } /* compute min output value */ - if (av_stream_get_end_pts(ost->st) != AV_NOPTS_VALUE) + if (av_stream_get_end_pts(ost->st) != AV_NOPTS_VALUE) { pts = FFMAX(pts, av_rescale_q(av_stream_get_end_pts(ost->st), ost->st->time_base, AV_TIME_BASE_Q)); + if (copy_ts) { + if (copy_ts_first_pts == AV_NOPTS_VALUE && pts > 1) + copy_ts_first_pts = pts; + if (copy_ts_first_pts != AV_NOPTS_VALUE) + pts -= copy_ts_first_pts; + } + } + if (is_last_report) nb_frames_drop += ost->last_dropped; } @@ -1836,6 +1903,8 @@ } } + first_report = 0; + if (is_last_report) print_final_stats(total_size); } @@ -1869,7 +1938,6 @@ // Maybe we should just let encoding fail instead. if (!ost->initialized) { FilterGraph *fg = ost->filter->graph; - char error[1024] = ""; av_log(NULL, AV_LOG_WARNING, "Finishing stream %d:%d without any data written to it.\n", @@ -1895,23 +1963,15 @@ finish_output_stream(ost); } - ret = init_output_stream(ost, error, sizeof(error)); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n", - ost->file_index, ost->index, error); - exit_program(1); - } + init_output_stream_wrapper(ost, NULL, 1); } - if (enc->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1) - continue; - if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO) continue; for (;;) { const char *desc = NULL; - AVPacket pkt; + AVPacket *pkt = ost->pkt; int pkt_size; switch (enc->codec_type) { @@ -1925,13 +1985,10 @@ av_assert0(0); } - av_init_packet(&pkt); - pkt.data = NULL; - pkt.size = 0; - update_benchmark(NULL); - while ((ret = avcodec_receive_packet(enc, &pkt)) == AVERROR(EAGAIN)) { + av_packet_unref(pkt); + while ((ret = avcodec_receive_packet(enc, pkt)) == AVERROR(EAGAIN)) { ret = avcodec_send_frame(enc, NULL); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n", @@ -1952,16 +2009,16 @@ fprintf(ost->logfile, "%s", enc->stats_out); } if (ret == AVERROR_EOF) { - output_packet(of, &pkt, ost, 1); + output_packet(of, pkt, ost, 1); break; } if (ost->finished & MUXER_FINISHED) { - av_packet_unref(&pkt); + av_packet_unref(pkt); continue; } - av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase); - pkt_size = pkt.size; - output_packet(of, &pkt, ost, 0); + av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); + pkt_size = pkt->size; + output_packet(of, pkt, ost, 0); if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) { do_video_stats(ost, pkt_size); } @@ -1995,13 +2052,12 @@ InputFile *f = input_files [ist->file_index]; int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); - AVPacket opkt = { 0 }; - - av_init_packet(&opkt); + AVPacket *opkt = ost->pkt; + av_packet_unref(opkt); // EOF: flush output bitstream filters. if (!pkt) { - output_packet(of, &opkt, ost, 1); + output_packet(of, opkt, ost, 1); return; } @@ -2039,41 +2095,30 @@ if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) ost->sync_opts++; - if (pkt->pts != AV_NOPTS_VALUE) - opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->mux_timebase) - ost_tb_start_time; - else - opkt.pts = AV_NOPTS_VALUE; + if (av_packet_ref(opkt, pkt) < 0) + exit_program(1); - if (pkt->dts == AV_NOPTS_VALUE) - opkt.dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->mux_timebase); - else - opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->mux_timebase); - opkt.dts -= ost_tb_start_time; + if (pkt->pts != AV_NOPTS_VALUE) + opkt->pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->mux_timebase) - ost_tb_start_time; - if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) { + if (pkt->dts == AV_NOPTS_VALUE) { + opkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->mux_timebase); + } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { int duration = av_get_audio_frame_duration(ist->dec_ctx, pkt->size); if(!duration) duration = ist->dec_ctx->frame_size; - opkt.dts = opkt.pts = av_rescale_delta(ist->st->time_base, pkt->dts, - (AVRational){1, ist->dec_ctx->sample_rate}, duration, &ist->filter_in_rescale_delta_last, - ost->mux_timebase) - ost_tb_start_time; - } - - opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); - - opkt.flags = pkt->flags; + opkt->dts = av_rescale_delta(ist->st->time_base, pkt->dts, + (AVRational){1, ist->dec_ctx->sample_rate}, duration, + &ist->filter_in_rescale_delta_last, ost->mux_timebase); + /* dts will be set immediately afterwards to what pts is now */ + opkt->pts = opkt->dts - ost_tb_start_time; + } else + opkt->dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->mux_timebase); + opkt->dts -= ost_tb_start_time; - if (pkt->buf) { - opkt.buf = av_buffer_ref(pkt->buf); - if (!opkt.buf) - exit_program(1); - } - opkt.data = pkt->data; - opkt.size = pkt->size; - - av_copy_packet_side_data(&opkt, pkt); + opkt->duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); - output_packet(of, &opkt, ost, 0); + output_packet(of, opkt, ost, 0); } int guess_input_channel_layout(InputStream *ist) @@ -2348,7 +2393,6 @@ int i, ret = 0, err = 0; int64_t best_effort_timestamp; int64_t dts = AV_NOPTS_VALUE; - AVPacket avpkt; // With fate-indeo3-2, we're getting 0-sized packets before EOF for some // reason. This seems like a semi-critical bug. Don't trigger EOF, and @@ -2364,8 +2408,7 @@ if (ist->dts != AV_NOPTS_VALUE) dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base); if (pkt) { - avpkt = *pkt; - avpkt.dts = dts; // ffmpeg.c probably shouldn't do this + pkt->dts = dts; // ffmpeg.c probably shouldn't do this } // The old code used to set dts on the drain packet, which does not work @@ -2379,7 +2422,7 @@ } update_benchmark(NULL); - ret = decode(ist->dec_ctx, decoded_frame, got_output, pkt ? &avpkt : NULL); + ret = decode(ist->dec_ctx, decoded_frame, got_output, pkt); update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index); if (ret < 0) *decode_failed = 1; @@ -2393,7 +2436,7 @@ av_log(ist->dec_ctx, AV_LOG_WARNING, "video_delay is larger in decoder than demuxer %d > %d.\n" "If you want to help, upload a sample " - "of this file to ftp://upload.ffmpeg.org/incoming/ " + "of this file to https://streams.videolan.org/upload/ " "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)\n", ist->dec_ctx->has_b_frames, ist->st->codecpar->video_delay); @@ -2515,7 +2558,7 @@ return ret; if (ist->sub2video.frame) { - sub2video_update(ist, &subtitle); + sub2video_update(ist, INT64_MIN, &subtitle); } else if (ist->nb_filters) { if (!ist->sub2video.sub_queue) ist->sub2video.sub_queue = av_fifo_alloc(8 * sizeof(AVSubtitle)); @@ -2538,6 +2581,8 @@ for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; + if (!ost->pkt && !(ost->pkt = av_packet_alloc())) + exit_program(1); if (!check_output_constraints(ist, ost) || !ost->encoding_needed || ost->enc->type != AVMEDIA_TYPE_SUBTITLE) continue; @@ -2573,7 +2618,12 @@ int repeating = 0; int eof_reached = 0; - AVPacket avpkt; + AVPacket *avpkt; + + if (!ist->pkt && !(ist->pkt = av_packet_alloc())) + return AVERROR(ENOMEM); + avpkt = ist->pkt; + if (!ist->saw_first_ts) { ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; ist->pts = 0; @@ -2589,13 +2639,11 @@ if (ist->next_pts == AV_NOPTS_VALUE) ist->next_pts = ist->pts; - if (!pkt) { - /* EOF handling */ - av_init_packet(&avpkt); - avpkt.data = NULL; - avpkt.size = 0; - } else { - avpkt = *pkt; + if (pkt) { + av_packet_unref(avpkt); + ret = av_packet_ref(avpkt, pkt); + if (ret < 0) + return ret; } if (pkt && pkt->dts != AV_NOPTS_VALUE) { @@ -2616,11 +2664,12 @@ switch (ist->dec_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: - ret = decode_audio (ist, repeating ? NULL : &avpkt, &got_output, + ret = decode_audio (ist, repeating ? NULL : avpkt, &got_output, &decode_failed); + av_packet_unref(avpkt); break; case AVMEDIA_TYPE_VIDEO: - ret = decode_video (ist, repeating ? NULL : &avpkt, &got_output, &duration_pts, !pkt, + ret = decode_video (ist, repeating ? NULL : avpkt, &got_output, &duration_pts, !pkt, &decode_failed); if (!repeating || !pkt || got_output) { if (pkt && pkt->duration) { @@ -2645,13 +2694,15 @@ ist->next_pts += duration_dts; } } + av_packet_unref(avpkt); break; case AVMEDIA_TYPE_SUBTITLE: if (repeating) break; - ret = transcode_subtitles(ist, &avpkt, &got_output, &decode_failed); + ret = transcode_subtitles(ist, avpkt, &got_output, &decode_failed); if (!pkt && ret >= 0) ret = AVERROR_EOF; + av_packet_unref(avpkt); break; default: return -1; @@ -2740,6 +2791,8 @@ for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; + if (!ost->pkt && !(ost->pkt = av_packet_alloc())) + exit_program(1); if (!check_output_constraints(ist, ost) || ost->encoding_needed) continue; @@ -2784,7 +2837,7 @@ if (avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL) < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename); } else { - avio_printf(sdp_pb, "SDP:\n%s", sdp); + avio_print(sdp_pb, sdp); avio_closep(&sdp_pb); av_freep(&sdp_filename); } @@ -2896,7 +2949,7 @@ InputStream *ist = input_streams[ist_index]; if (ist->decoding_needed) { - AVCodec *codec = ist->dec; + const AVCodec *codec = ist->dec; if (!codec) { snprintf(error, error_len, "Decoder (codec %s) not found for input stream #%d:%d", avcodec_get_name(ist->dec_ctx->codec_id), ist->file_index, ist->st->index); @@ -2906,9 +2959,10 @@ ist->dec_ctx->opaque = ist; ist->dec_ctx->get_format = get_format; ist->dec_ctx->get_buffer2 = get_buffer; +#if LIBAVCODEC_VERSION_MAJOR < 60 ist->dec_ctx->thread_safe_callbacks = 1; +#endif - av_opt_set_int(ist->dec_ctx, "refcounted_frames", 1, 0); if (ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE && (ist->decoding_needed & DECODING_FOR_OST)) { av_dict_set(&ist->decoder_opts, "compute_edt", "1", AV_DICT_DONT_OVERWRITE); @@ -2992,6 +3046,7 @@ of->header_written = 1; av_dump_format(of->ctx, file_index, of->ctx->url, 1); + nb_output_dumped++; if (sdp_filename || want_sdp) print_sdp(); @@ -3005,9 +3060,11 @@ ost->mux_timebase = ost->st->time_base; while (av_fifo_size(ost->muxing_queue)) { - AVPacket pkt; + AVPacket *pkt; av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL); - write_packet(of, &pkt, ost, 1); + ost->muxing_queue_data_size -= pkt->size; + write_packet(of, pkt, ost, 1); + av_packet_free(&pkt); } } @@ -3016,35 +3073,28 @@ static int init_output_bsfs(OutputStream *ost) { - AVBSFContext *ctx; - int i, ret; + AVBSFContext *ctx = ost->bsf_ctx; + int ret; - if (!ost->nb_bitstream_filters) + if (!ctx) return 0; - for (i = 0; i < ost->nb_bitstream_filters; i++) { - ctx = ost->bsf_ctx[i]; - - ret = avcodec_parameters_copy(ctx->par_in, - i ? ost->bsf_ctx[i - 1]->par_out : ost->st->codecpar); - if (ret < 0) - return ret; + ret = avcodec_parameters_copy(ctx->par_in, ost->st->codecpar); + if (ret < 0) + return ret; - ctx->time_base_in = i ? ost->bsf_ctx[i - 1]->time_base_out : ost->st->time_base; + ctx->time_base_in = ost->st->time_base; - ret = av_bsf_init(ctx); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n", - ost->bsf_ctx[i]->filter->name); - return ret; - } + ret = av_bsf_init(ctx); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error initializing bitstream filter: %s\n", + ctx->filter->name); + return ret; } - ctx = ost->bsf_ctx[ost->nb_bitstream_filters - 1]; ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out); if (ret < 0) return ret; - ost->st->time_base = ctx->time_base_out; return 0; @@ -3292,7 +3342,7 @@ enc_ctx->time_base = default_time_base; } -static int init_output_stream_encode(OutputStream *ost) +static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) { InputStream *ist = get_input_stream(ost); AVCodecContext *enc_ctx = ost->enc_ctx; @@ -3332,7 +3382,7 @@ 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) { + if (ist && !ost->frame_rate.num && !ost->max_frame_rate.num) { ost->frame_rate = (AVRational){25, 1}; av_log(NULL, AV_LOG_WARNING, "No information " @@ -3342,6 +3392,11 @@ ost->file_index, ost->index); } + if (ost->max_frame_rate.num && + (av_q2d(ost->frame_rate) > av_q2d(ost->max_frame_rate) || + !ost->frame_rate.den)) + ost->frame_rate = ost->max_frame_rate; + if (ost->enc->supported_framerates && !ost->force_fps) { int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates); ost->frame_rate = ost->enc->supported_framerates[idx]; @@ -3376,10 +3431,6 @@ av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n" "Please consider specifying a lower framerate, a different muxer or -vsync 2\n"); } - for (j = 0; j < ost->forced_kf_count; j++) - ost->forced_kf_pts[j] = av_rescale_q(ost->forced_kf_pts[j], - AV_TIME_BASE_Q, - enc_ctx->time_base); enc_ctx->width = av_buffersink_get_w(ost->filter->filter); enc_ctx->height = av_buffersink_get_h(ost->filter->filter); @@ -3393,6 +3444,14 @@ 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); + if (frame) { + enc_ctx->color_range = frame->color_range; + enc_ctx->color_primaries = frame->color_primaries; + enc_ctx->color_trc = frame->color_trc; + enc_ctx->colorspace = frame->colorspace; + enc_ctx->chroma_sample_location = frame->chroma_location; + } + enc_ctx->framerate = ost->frame_rate; ost->st->avg_frame_rate = ost->frame_rate; @@ -3410,6 +3469,20 @@ enc_ctx->field_order = AV_FIELD_TT; } + if (frame) { + if (enc_ctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && + ost->top_field_first >= 0) + frame->top_field_first = !!ost->top_field_first; + + if (frame->interlaced_frame) { + if (enc_ctx->codec->id == AV_CODEC_ID_MJPEG) + enc_ctx->field_order = frame->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; + else + enc_ctx->field_order = frame->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; + } else + enc_ctx->field_order = AV_FIELD_PROGRESSIVE; + } + if (ost->forced_keyframes) { if (!strncmp(ost->forced_keyframes, "expr:", 5)) { ret = av_expr_parse(&ost->forced_keyframes_pexpr, ost->forced_keyframes+5, @@ -3450,16 +3523,17 @@ return 0; } -static int init_output_stream(OutputStream *ost, char *error, int error_len) +static int init_output_stream(OutputStream *ost, AVFrame *frame, + char *error, int error_len) { int ret = 0; if (ost->encoding_needed) { - AVCodec *codec = ost->enc; + const AVCodec *codec = ost->enc; AVCodecContext *dec = NULL; InputStream *ist; - ret = init_output_stream_encode(ost); + ret = init_output_stream_encode(ost, frame); if (ret < 0) return ret; @@ -3481,21 +3555,14 @@ !av_dict_get(ost->encoder_opts, "ab", NULL, 0)) av_dict_set(&ost->encoder_opts, "b", "128000", 0); - if (ost->filter && av_buffersink_get_hw_frames_ctx(ost->filter->filter) && - ((AVHWFramesContext*)av_buffersink_get_hw_frames_ctx(ost->filter->filter)->data)->format == - av_buffersink_get_format(ost->filter->filter)) { - ost->enc_ctx->hw_frames_ctx = av_buffer_ref(av_buffersink_get_hw_frames_ctx(ost->filter->filter)); - if (!ost->enc_ctx->hw_frames_ctx) - return AVERROR(ENOMEM); - } else { - ret = hw_device_setup_for_encode(ost); - if (ret < 0) { - snprintf(error, error_len, "Device setup failed for " - "encoder on output stream #%d:%d : %s", + ret = hw_device_setup_for_encode(ost); + if (ret < 0) { + snprintf(error, error_len, "Device setup failed for " + "encoder on output stream #%d:%d : %s", ost->file_index, ost->index, av_err2str(ret)); - return ret; - } + return ret; } + if (ist && ist->dec->type == AVMEDIA_TYPE_SUBTITLE && ost->enc->type == AVMEDIA_TYPE_SUBTITLE) { int input_props = 0, output_props = 0; AVCodecDescriptor const *input_descriptor = @@ -3539,12 +3606,6 @@ "Error initializing the output stream codec context.\n"); exit_program(1); } - /* - * FIXME: ost->st->codec should't be needed here anymore. - */ - ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx); - if (ret < 0) - return ret; if (ost->enc_ctx->nb_coded_side_data) { int i; @@ -3571,12 +3632,14 @@ int i; for (i = 0; i < ist->st->nb_side_data; i++) { AVPacketSideData *sd = &ist->st->side_data[i]; - uint8_t *dst = av_stream_new_side_data(ost->st, sd->type, sd->size); - if (!dst) - return AVERROR(ENOMEM); - memcpy(dst, sd->data, sd->size); - if (ist->autorotate && sd->type == AV_PKT_DATA_DISPLAYMATRIX) - av_display_rotation_set((uint32_t *)dst, 0); + if (sd->type != AV_PKT_DATA_CPB_PROPERTIES) { + uint8_t *dst = av_stream_new_side_data(ost->st, sd->type, sd->size); + if (!dst) + return AVERROR(ENOMEM); + memcpy(dst, sd->data, sd->size); + if (ist->autorotate && sd->type == AV_PKT_DATA_DISPLAYMATRIX) + av_display_rotation_set((uint32_t *)dst, 0); + } } } @@ -3587,8 +3650,6 @@ // copy estimated duration as a hint to the muxer if (ost->st->duration <= 0 && ist && ist->st->duration > 0) ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base); - - ost->st->codec->codec= ost->enc_ctx->codec; } else if (ost->stream_copy) { ret = init_output_stream_streamcopy(ost); if (ret < 0) @@ -3701,13 +3762,22 @@ goto dump_format; } - /* open each encoder */ + /* + * initialize stream copy and subtitle/data streams. + * Encoded AVFrame based streams will get initialized as follows: + * - when the first AVFrame is received in do_video_out + * - just before the first AVFrame is received in either transcode_step + * or reap_filters due to us requiring the filter chain buffer sink + * to be configured with the correct audio frame size, which is only + * known after the encoder is initialized. + */ for (i = 0; i < nb_output_streams; i++) { - // skip streams fed from filtergraphs until we have a frame for them - if (output_streams[i]->filter) + if (!output_streams[i]->stream_copy && + (output_streams[i]->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO || + output_streams[i]->enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO)) continue; - ret = init_output_stream(output_streams[i], error, sizeof(error)); + ret = init_output_stream_wrapper(output_streams[i], NULL, 0); if (ret < 0) goto dump_format; } @@ -3971,13 +4041,9 @@ if (key == 'd' || key == 'D'){ int debug=0; if(key == 'D') { - debug = input_streams[0]->st->codec->debug<<1; + debug = input_streams[0]->dec_ctx->debug << 1; if(!debug) debug = 1; - while(debug & (FF_DEBUG_DCT_COEFF -#if FF_API_DEBUG_MV - |FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE -#endif - )) //unsupported, would just crash + while (debug & FF_DEBUG_DCT_COEFF) //unsupported, would just crash debug += debug; }else{ char buf[32]; @@ -3994,7 +4060,7 @@ fprintf(stderr,"error parsing debug value\n"); } for(i=0;ist->codec->debug = debug; + input_streams[i]->dec_ctx->debug = debug; } for(i=0;ipkt, *queue_pkt; unsigned flags = f->non_blocking ? AV_THREAD_MESSAGE_NONBLOCK : 0; int ret = 0; while (1) { - AVPacket pkt; - ret = av_read_frame(f->ctx, &pkt); + ret = av_read_frame(f->ctx, pkt); if (ret == AVERROR(EAGAIN)) { av_usleep(10000); @@ -4038,10 +4104,17 @@ av_thread_message_queue_set_err_recv(f->in_thread_queue, ret); break; } - ret = av_thread_message_queue_send(f->in_thread_queue, &pkt, flags); + queue_pkt = av_packet_alloc(); + if (!queue_pkt) { + av_packet_unref(pkt); + av_thread_message_queue_set_err_recv(f->in_thread_queue, AVERROR(ENOMEM)); + break; + } + av_packet_move_ref(queue_pkt, pkt); + ret = av_thread_message_queue_send(f->in_thread_queue, &queue_pkt, flags); if (flags && ret == AVERROR(EAGAIN)) { flags = 0; - ret = av_thread_message_queue_send(f->in_thread_queue, &pkt, flags); + ret = av_thread_message_queue_send(f->in_thread_queue, &queue_pkt, flags); av_log(f->ctx, AV_LOG_WARNING, "Thread message queue blocking; consider raising the " "thread_queue_size option (current value: %d)\n", @@ -4052,7 +4125,7 @@ av_log(f->ctx, AV_LOG_ERROR, "Unable to send packet to main thread: %s\n", av_err2str(ret)); - av_packet_unref(&pkt); + av_packet_free(&queue_pkt); av_thread_message_queue_set_err_recv(f->in_thread_queue, ret); break; } @@ -4064,13 +4137,13 @@ static void free_input_thread(int i) { InputFile *f = input_files[i]; - AVPacket pkt; + AVPacket *pkt; if (!f || !f->in_thread_queue) return; av_thread_message_queue_set_err_send(f->in_thread_queue, AVERROR_EOF); while (av_thread_message_queue_recv(f->in_thread_queue, &pkt, 0) >= 0) - av_packet_unref(&pkt); + av_packet_free(&pkt); pthread_join(f->thread, NULL); f->joined = 1; @@ -4090,14 +4163,16 @@ int ret; InputFile *f = input_files[i]; - if (nb_input_files == 1) + if (f->thread_queue_size < 0) + f->thread_queue_size = (nb_input_files > 1 ? 8 : 0); + if (!f->thread_queue_size) return 0; if (f->ctx->pb ? !f->ctx->pb->seekable : strcmp(f->ctx->iformat->name, "lavfi")) f->non_blocking = 1; ret = av_thread_message_queue_alloc(&f->in_thread_queue, - f->thread_queue_size, sizeof(AVPacket)); + f->thread_queue_size, sizeof(f->pkt)); if (ret < 0) return ret; @@ -4122,7 +4197,7 @@ return 0; } -static int get_input_packet_mt(InputFile *f, AVPacket *pkt) +static int get_input_packet_mt(InputFile *f, AVPacket **pkt) { return av_thread_message_queue_recv(f->in_thread_queue, pkt, f->non_blocking ? @@ -4130,7 +4205,7 @@ } #endif -static int get_input_packet(InputFile *f, AVPacket *pkt) +static int get_input_packet(InputFile *f, AVPacket **pkt) { if (f->rate_emu) { int i; @@ -4144,10 +4219,11 @@ } #if HAVE_THREADS - if (nb_input_files > 1) + if (f->thread_queue_size) return get_input_packet_mt(f, pkt); #endif - return av_read_frame(f->ctx, pkt); + *pkt = f->pkt; + return av_read_frame(f->ctx, *pkt); } static int got_eagain(void) @@ -4195,7 +4271,7 @@ int i, ret, has_audio = 0; int64_t duration = 0; - ret = av_seek_frame(is, -1, is->start_time, 0); + ret = avformat_seek_file(is, -1, INT64_MIN, is->start_time, is->start_time, 0); if (ret < 0) return ret; @@ -4235,7 +4311,8 @@ ifile->time_base = ist->st->time_base; /* the total duration of the stream, max_pts - min_pts is * the duration of the stream without the last frame */ - duration += ist->max_pts - ist->min_pts; + if (ist->max_pts > ist->min_pts && ist->max_pts - (uint64_t)ist->min_pts < INT64_MAX - duration) + duration += ist->max_pts - ist->min_pts; ifile->time_base = duration_max(duration, &ifile->duration, ist->st->time_base, ifile->time_base); } @@ -4258,10 +4335,11 @@ InputFile *ifile = input_files[file_index]; AVFormatContext *is; InputStream *ist; - AVPacket pkt; + AVPacket *pkt; int ret, thread_ret, i, j; int64_t duration; int64_t pkt_dts; + int disable_discontinuity_correction = copy_ts; is = ifile->ctx; ret = get_input_packet(ifile, &pkt); @@ -4332,27 +4410,27 @@ reset_eagain(); if (do_pkt_dump) { - av_pkt_dump_log2(NULL, AV_LOG_INFO, &pkt, do_hex_dump, - is->streams[pkt.stream_index]); + av_pkt_dump_log2(NULL, AV_LOG_INFO, pkt, do_hex_dump, + is->streams[pkt->stream_index]); } /* the following test is needed in case new streams appear dynamically in stream : we ignore them */ - if (pkt.stream_index >= ifile->nb_streams) { - report_new_stream(file_index, &pkt); + if (pkt->stream_index >= ifile->nb_streams) { + report_new_stream(file_index, pkt); goto discard_packet; } - ist = input_streams[ifile->ist_index + pkt.stream_index]; + ist = input_streams[ifile->ist_index + pkt->stream_index]; - ist->data_size += pkt.size; + ist->data_size += pkt->size; ist->nb_packets++; if (ist->discard) goto discard_packet; - if (pkt.flags & AV_PKT_FLAG_CORRUPT) { + if (pkt->flags & AV_PKT_FLAG_CORRUPT) { av_log(NULL, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, - "%s: corrupt input packet in stream %d\n", is->url, pkt.stream_index); + "%s: corrupt input packet in stream %d\n", is->url, pkt->stream_index); if (exit_on_error) exit_program(1); } @@ -4360,11 +4438,11 @@ if (debug_ts) { av_log(NULL, AV_LOG_INFO, "demuxer -> ist_index:%d type:%s " "next_dts:%s next_dts_time:%s next_pts:%s next_pts_time:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n", - ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), + ifile->ist_index + pkt->stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), av_ts2str(ist->next_dts), av_ts2timestr(ist->next_dts, &AV_TIME_BASE_Q), av_ts2str(ist->next_pts), av_ts2timestr(ist->next_pts, &AV_TIME_BASE_Q), - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base), + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), av_ts2str(input_files[ist->file_index]->ts_offset), av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q)); } @@ -4394,12 +4472,12 @@ stime2= stime + (1ULL<st->pts_wrap_bits); ist->wrap_correction_done = 1; - if(stime2 > stime && pkt.dts != AV_NOPTS_VALUE && pkt.dts > stime + (1LL<<(ist->st->pts_wrap_bits-1))) { - pkt.dts -= 1ULL<st->pts_wrap_bits; + if(stime2 > stime && pkt->dts != AV_NOPTS_VALUE && pkt->dts > stime + (1LL<<(ist->st->pts_wrap_bits-1))) { + pkt->dts -= 1ULL<st->pts_wrap_bits; ist->wrap_correction_done = 0; } - if(stime2 > stime && pkt.pts != AV_NOPTS_VALUE && pkt.pts > stime + (1LL<<(ist->st->pts_wrap_bits-1))) { - pkt.pts -= 1ULL<st->pts_wrap_bits; + if(stime2 > stime && pkt->pts != AV_NOPTS_VALUE && pkt->pts > stime + (1LL<<(ist->st->pts_wrap_bits-1))) { + pkt->pts -= 1ULL<st->pts_wrap_bits; ist->wrap_correction_done = 0; } } @@ -4413,10 +4491,10 @@ if (src_sd->type == AV_PKT_DATA_DISPLAYMATRIX) continue; - if (av_packet_get_side_data(&pkt, src_sd->type, NULL)) + if (av_packet_get_side_data(pkt, src_sd->type, NULL)) continue; - dst_data = av_packet_new_side_data(&pkt, src_sd->type, src_sd->size); + dst_data = av_packet_new_side_data(pkt, src_sd->type, src_sd->size); if (!dst_data) exit_program(1); @@ -4424,17 +4502,17 @@ } } - if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); - - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts *= ist->ts_scale; - if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts *= ist->ts_scale; + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); - pkt_dts = av_rescale_q_rnd(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts *= ist->ts_scale; + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts *= ist->ts_scale; + + pkt_dts = av_rescale_q_rnd(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); if ((ist->dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO || ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) && pkt_dts != AV_NOPTS_VALUE && ist->next_dts == AV_NOPTS_VALUE && !copy_ts @@ -4446,27 +4524,37 @@ av_log(NULL, AV_LOG_DEBUG, "Inter stream timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", delta, ifile->ts_offset); - pkt.dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); } } duration = av_rescale_q(ifile->duration, ifile->time_base, ist->st->time_base); - if (pkt.pts != AV_NOPTS_VALUE) { - pkt.pts += duration; - ist->max_pts = FFMAX(pkt.pts, ist->max_pts); - ist->min_pts = FFMIN(pkt.pts, ist->min_pts); + if (pkt->pts != AV_NOPTS_VALUE) { + pkt->pts += duration; + ist->max_pts = FFMAX(pkt->pts, ist->max_pts); + ist->min_pts = FFMIN(pkt->pts, ist->min_pts); + } + + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts += duration; + + pkt_dts = av_rescale_q_rnd(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + + if (copy_ts && pkt_dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && + (is->iformat->flags & AVFMT_TS_DISCONT) && ist->st->pts_wrap_bits < 60) { + int64_t wrap_dts = av_rescale_q_rnd(pkt->dts + (1LL<st->pts_wrap_bits), + ist->st->time_base, AV_TIME_BASE_Q, + AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + if (FFABS(wrap_dts - ist->next_dts) < FFABS(pkt_dts - ist->next_dts)/10) + disable_discontinuity_correction = 0; } - if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts += duration; - - pkt_dts = av_rescale_q_rnd(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); if ((ist->dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO || ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) && pkt_dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && - !copy_ts) { + !disable_discontinuity_correction) { int64_t delta = pkt_dts - ist->next_dts; if (is->iformat->flags & AVFMT_TS_DISCONT) { if (delta < -1LL*dts_delta_threshold*AV_TIME_BASE || @@ -4479,46 +4567,51 @@ ist->file_index, ist->st->index, ist->st->id, av_get_media_type_string(ist->dec_ctx->codec_type), delta, ifile->ts_offset); - pkt.dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); } } else { if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || delta > 1LL*dts_error_threshold*AV_TIME_BASE) { - av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt.dts, ist->next_dts, pkt.stream_index); - pkt.dts = AV_NOPTS_VALUE; + av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt->dts, ist->next_dts, pkt->stream_index); + pkt->dts = AV_NOPTS_VALUE; } - if (pkt.pts != AV_NOPTS_VALUE){ - int64_t pkt_pts = av_rescale_q(pkt.pts, ist->st->time_base, AV_TIME_BASE_Q); + if (pkt->pts != AV_NOPTS_VALUE){ + int64_t pkt_pts = av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q); delta = pkt_pts - ist->next_dts; if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || delta > 1LL*dts_error_threshold*AV_TIME_BASE) { - av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt.pts, ist->next_dts, pkt.stream_index); - pkt.pts = AV_NOPTS_VALUE; + av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt->pts, ist->next_dts, pkt->stream_index); + pkt->pts = AV_NOPTS_VALUE; } } } } - if (pkt.dts != AV_NOPTS_VALUE) - ifile->last_ts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); + if (pkt->dts != AV_NOPTS_VALUE) + ifile->last_ts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n", - ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base), + ifile->ist_index + pkt->stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), av_ts2str(input_files[ist->file_index]->ts_offset), av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q)); } - sub2video_heartbeat(ist, pkt.pts); + sub2video_heartbeat(ist, pkt->pts); - process_input_packet(ist, &pkt, 0); + process_input_packet(ist, pkt, 0); discard_packet: - av_packet_unref(&pkt); +#if HAVE_THREADS + if (ifile->thread_queue_size) + av_packet_free(&pkt); + else +#endif + av_packet_unref(pkt); return 0; } @@ -4604,15 +4697,30 @@ } if (ost->filter && ost->filter->graph->graph) { - if (!ost->initialized) { - char error[1024] = {0}; - ret = init_output_stream(ost, error, sizeof(error)); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n", - ost->file_index, ost->index, error); - exit_program(1); - } - } + /* + * Similar case to the early audio initialization in reap_filters. + * Audio is special in ffmpeg.c currently as we depend on lavfi's + * audio frame buffering/creation to get the output audio frame size + * in samples correct. The audio frame size for the filter chain is + * configured during the output stream initialization. + * + * Apparently avfilter_graph_request_oldest (called in + * transcode_from_filter just down the line) peeks. Peeking already + * puts one frame "ready to be given out", which means that any + * update in filter buffer sink configuration afterwards will not + * help us. And yes, even if it would be utilized, + * av_buffersink_get_samples is affected, as it internally utilizes + * the same early exit for peeked frames. + * + * In other words, if avfilter_graph_request_oldest would not make + * further filter chain configuration or usage of + * av_buffersink_get_samples useless (by just causing the return + * of the peeked AVFrame as-is), we could get rid of this additional + * early encoder initialization. + */ + if (av_buffersink_get_type(ost->filter->filter) == AVMEDIA_TYPE_AUDIO) + init_output_stream_wrapper(ost, NULL, 1); + if ((ret = transcode_from_filter(ost->filter->graph, &ist)) < 0) return ret; if (!ist) @@ -4740,6 +4848,10 @@ av_freep(&ost->enc_ctx->stats_in); } total_packets_written += ost->packets_written; + if (!ost->packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM)) { + av_log(NULL, AV_LOG_FATAL, "Empty output on stream %d.\n", i); + exit_program(1); + } } if (!total_packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT)) { @@ -4757,7 +4869,6 @@ } } - av_buffer_unref(&hw_device_ctx); hw_device_free_all(); /* finished ! */ diff -Nru ffmpeg-4.2.2/fftools/ffmpeg_cuvid.c ffmpeg-4.4/fftools/ffmpeg_cuvid.c --- ffmpeg-4.2.2/fftools/ffmpeg_cuvid.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/fftools/ffmpeg_cuvid.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/hwcontext.h" -#include "libavutil/pixdesc.h" - -#include "ffmpeg.h" - -static void cuvid_uninit(AVCodecContext *avctx) -{ - InputStream *ist = avctx->opaque; - av_buffer_unref(&ist->hw_frames_ctx); -} - -int cuvid_init(AVCodecContext *avctx) -{ - InputStream *ist = avctx->opaque; - AVHWFramesContext *frames_ctx; - int ret; - - av_log(avctx, AV_LOG_VERBOSE, "Initializing cuvid hwaccel\n"); - - if (!hw_device_ctx) { - ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_CUDA, - ist->hwaccel_device, NULL, 0); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Error creating a CUDA device\n"); - return ret; - } - } - - av_buffer_unref(&ist->hw_frames_ctx); - ist->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx); - if (!ist->hw_frames_ctx) { - av_log(avctx, AV_LOG_ERROR, "Error creating a CUDA frames context\n"); - return AVERROR(ENOMEM); - } - - frames_ctx = (AVHWFramesContext*)ist->hw_frames_ctx->data; - - frames_ctx->format = AV_PIX_FMT_CUDA; - frames_ctx->sw_format = avctx->sw_pix_fmt; - frames_ctx->width = avctx->width; - frames_ctx->height = avctx->height; - - av_log(avctx, AV_LOG_DEBUG, "Initializing CUDA frames context: sw_format = %s, width = %d, height = %d\n", - av_get_pix_fmt_name(frames_ctx->sw_format), frames_ctx->width, frames_ctx->height); - - ret = av_hwframe_ctx_init(ist->hw_frames_ctx); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Error initializing a CUDA frame pool\n"); - return ret; - } - - ist->hwaccel_uninit = cuvid_uninit; - - return 0; -} diff -Nru ffmpeg-4.2.2/fftools/ffmpeg_filter.c ffmpeg-4.4/fftools/ffmpeg_filter.c --- ffmpeg-4.2.2/fftools/ffmpeg_filter.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/fftools/ffmpeg_filter.c 2021-04-08 21:28:39.000000000 +0000 @@ -60,7 +60,8 @@ } } -enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *enc_ctx, AVCodec *codec, enum AVPixelFormat target) +static enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *enc_ctx, + const AVCodec *codec, enum AVPixelFormat target) { if (codec && codec->pix_fmts) { const enum AVPixelFormat *p = codec->pix_fmts; @@ -73,7 +74,7 @@ p = get_compliance_unofficial_pix_fmts(enc_ctx->codec_id, p); } for (; *p != AV_PIX_FMT_NONE; p++) { - best= avcodec_find_best_pix_fmt_of_2(best, *p, target, has_alpha, NULL); + best = av_find_best_pix_fmt_of_2(best, *p, target, has_alpha, NULL); if (*p == target) break; } @@ -90,28 +91,6 @@ return target; } -void choose_sample_fmt(AVStream *st, AVCodec *codec) -{ - if (codec && codec->sample_fmts) { - const enum AVSampleFormat *p = codec->sample_fmts; - for (; *p != -1; p++) { - if (*p == st->codecpar->format) - break; - } - if (*p == -1) { - if((codec->capabilities & AV_CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codecpar->format) > av_get_sample_fmt_name(codec->sample_fmts[0])) - av_log(NULL, AV_LOG_ERROR, "Conversion will not be lossless.\n"); - if(av_get_sample_fmt_name(st->codecpar->format)) - av_log(NULL, AV_LOG_WARNING, - "Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n", - av_get_sample_fmt_name(st->codecpar->format), - codec->name, - av_get_sample_fmt_name(codec->sample_fmts[0])); - st->codecpar->format = codec->sample_fmts[0]; - } - } -} - static char *choose_pix_fmts(OutputFilter *ofilter) { OutputStream *ost = ofilter->ost; @@ -469,7 +448,7 @@ if (ret < 0) return ret; - if (ofilter->width || ofilter->height) { + if ((ofilter->width || ofilter->height) && ofilter->ost->autoscale) { char args[255]; AVFilterContext *filter; AVDictionaryEntry *e = NULL; @@ -639,13 +618,6 @@ pad_idx = 0; } - if (audio_volume != 256 && 0) { - char args[256]; - - snprintf(args, sizeof(args), "%f", audio_volume / 256.); - AUTO_INSERT_FILTER("-vol", "volume", args); - } - if (ost->apad && of->shortest) { char args[256]; int i; @@ -673,7 +645,8 @@ return 0; } -int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) +static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, + AVFilterInOut *out) { if (!ofilter->ost) { av_log(NULL, AV_LOG_FATAL, "Filter %s has an unconnected output\n", ofilter->name); @@ -740,6 +713,12 @@ return AVERROR(ENOMEM); ist->sub2video.last_pts = INT64_MIN; ist->sub2video.end_pts = INT64_MIN; + + /* sub2video structure has been (re-)initialized. + Mark it as such so that the system will be + initialized with the first received heartbeat. */ + ist->sub2video.initialize = 1; + return 0; } @@ -786,10 +765,9 @@ av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC); av_bprintf(&args, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:" - "pixel_aspect=%d/%d:sws_param=flags=%d", + "pixel_aspect=%d/%d", ifilter->width, ifilter->height, ifilter->format, - tb.num, tb.den, sar.num, sar.den, - SWS_BILINEAR + ((ist->dec_ctx->flags&AV_CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0)); + tb.num, tb.den, sar.num, sar.den); if (fr.num && fr.den) av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den); snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, @@ -1056,17 +1034,9 @@ if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) goto fail; - if (filter_hw_device || hw_device_ctx) { - AVBufferRef *device = filter_hw_device ? filter_hw_device->device_ref - : hw_device_ctx; - for (i = 0; i < fg->graph->nb_filters; i++) { - fg->graph->filters[i]->hw_device_ctx = av_buffer_ref(device); - if (!fg->graph->filters[i]->hw_device_ctx) { - ret = AVERROR(ENOMEM); - goto fail; - } - } - } + ret = hw_device_setup_for_filter(fg); + if (ret < 0) + goto fail; if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { const char *num_inputs; @@ -1106,6 +1076,8 @@ configure_output_filter(fg, fg->outputs[i], cur); avfilter_inout_free(&outputs); + if (!auto_conversion_filters) + avfilter_graph_set_auto_convert(fg->graph, AVFILTER_AUTO_CONVERT_NONE); if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) goto fail; @@ -1169,7 +1141,7 @@ while (av_fifo_size(ist->sub2video.sub_queue)) { AVSubtitle tmp; av_fifo_generic_read(ist->sub2video.sub_queue, &tmp, sizeof(tmp), NULL); - sub2video_update(ist, &tmp); + sub2video_update(ist, INT64_MIN, &tmp); avsubtitle_free(&tmp); } } @@ -1205,15 +1177,6 @@ return 0; } -int ist_in_filtergraph(FilterGraph *fg, InputStream *ist) -{ - int i; - for (i = 0; i < fg->nb_inputs; i++) - if (fg->inputs[i]->ist == ist) - return 1; - return 0; -} - int filtergraph_is_simple(FilterGraph *fg) { return !fg->graph_desc; diff -Nru ffmpeg-4.2.2/fftools/ffmpeg.h ffmpeg-4.4/fftools/ffmpeg.h --- ffmpeg-4.2.2/fftools/ffmpeg.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/fftools/ffmpeg.h 2021-04-08 21:28:39.000000000 +0000 @@ -61,7 +61,6 @@ HWACCEL_GENERIC, HWACCEL_VIDEOTOOLBOX, HWACCEL_QSV, - HWACCEL_CUVID, }; typedef struct HWAccel { @@ -109,6 +108,8 @@ int nb_audio_sample_rate; SpecifierOpt *frame_rates; int nb_frame_rates; + SpecifierOpt *max_frame_rates; + int nb_max_frame_rates; SpecifierOpt *frame_sizes; int nb_frame_sizes; SpecifierOpt *frame_pix_fmts; @@ -216,6 +217,8 @@ int nb_passlogfiles; SpecifierOpt *max_muxing_queue_size; int nb_max_muxing_queue_size; + SpecifierOpt *muxing_queue_data_threshold; + int nb_muxing_queue_data_threshold; SpecifierOpt *guess_layout_max; int nb_guess_layout_max; SpecifierOpt *apad; @@ -230,6 +233,8 @@ int nb_time_bases; SpecifierOpt *enc_time_bases; int nb_enc_time_bases; + SpecifierOpt *autoscale; + int nb_autoscale; } OptionsContext; typedef struct InputFilter { @@ -302,9 +307,10 @@ #define DECODING_FOR_FILTER 2 AVCodecContext *dec_ctx; - AVCodec *dec; + const AVCodec *dec; AVFrame *decoded_frame; AVFrame *filter_frame; /* a ref of decoded_frame, to be sent to filters */ + AVPacket *pkt; int64_t start; /* time when read started */ /* predicted dts of the next packet read for this stream or (when there are @@ -349,6 +355,7 @@ AVFifoBuffer *sub_queue; ///< queue of AVSubtitle* before filter init AVFrame *frame; int w, h; + unsigned int initialize; ///< marks if sub2video_update should force an initialization } sub2video; int dr1; @@ -412,6 +419,8 @@ int rate_emu; int accurate_seek; + AVPacket *pkt; + #if HAVE_THREADS AVThreadMessageQueue *in_thread_queue; pthread_t thread; /* thread reading from this file */ @@ -430,7 +439,8 @@ FKF_NB }; -#define ABORT_ON_FLAG_EMPTY_OUTPUT (1 << 0) +#define ABORT_ON_FLAG_EMPTY_OUTPUT (1 << 0) +#define ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM (1 << 1) extern const char *const forced_keyframes_const_names[]; @@ -459,15 +469,15 @@ AVRational mux_timebase; AVRational enc_timebase; - int nb_bitstream_filters; - AVBSFContext **bsf_ctx; + AVBSFContext *bsf_ctx; AVCodecContext *enc_ctx; AVCodecParameters *ref_par; /* associated input codec parameters with encoders options applied */ - AVCodec *enc; + const AVCodec *enc; int64_t max_frames; AVFrame *filtered_frame; AVFrame *last_frame; + AVPacket *pkt; int last_dropped; int last_nb0_frames[3]; @@ -475,10 +485,12 @@ /* video only */ AVRational frame_rate; + AVRational max_frame_rate; int is_cfr; int force_fps; int top_field_first; int rotate_overridden; + int autoscale; double rotate_override_value; AVRational frame_aspect_ratio; @@ -544,6 +556,15 @@ /* the packets are buffered here until the muxer is ready to be initialized */ AVFifoBuffer *muxing_queue; + /* + * The size of the AVPackets' buffers in queue. + * Updated when a packet is either pushed or pulled from the queue. + */ + size_t muxing_queue_data_size; + + /* Threshold after which max_muxing_queue_size will be in effect */ + size_t muxing_queue_data_threshold; + /* packet picture type */ int pict_type; @@ -600,6 +621,7 @@ extern int exit_on_error; extern int abort_on_flags; extern int print_stats; +extern int64_t stats_period; extern int qp_hist; extern int stdin_interaction; extern int frame_bits_per_raw_sample; @@ -610,12 +632,12 @@ extern int filter_nbthreads; extern int filter_complex_nbthreads; extern int vstats_version; +extern int auto_conversion_filters; extern const AVIOInterruptCB int_cb; extern const OptionDef options[]; extern const HWAccel hwaccels[]; -extern AVBufferRef *hw_device_ctx; #if CONFIG_QSV extern char *qsv_device; #endif @@ -625,28 +647,20 @@ void term_init(void); void term_exit(void); -void reset_options(OptionsContext *o, int is_input); void show_usage(void); -void opt_output_file(void *optctx, const char *filename); - void remove_avoptions(AVDictionary **a, AVDictionary *b); void assert_avoptions(AVDictionary *m); int guess_input_channel_layout(InputStream *ist); -enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *avctx, AVCodec *codec, enum AVPixelFormat target); -void choose_sample_fmt(AVStream *st, AVCodec *codec); - int configure_filtergraph(FilterGraph *fg); -int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out); void check_filter_outputs(void); -int ist_in_filtergraph(FilterGraph *fg, InputStream *ist); int filtergraph_is_simple(FilterGraph *fg); int init_simple_filtergraph(InputStream *ist, OutputStream *ost); int init_complex_filtergraph(FilterGraph *fg); -void sub2video_update(InputStream *ist, AVSubtitle *sub); +void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitle *sub); int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame); @@ -654,7 +668,6 @@ int videotoolbox_init(AVCodecContext *s); int qsv_init(AVCodecContext *s); -int cuvid_init(AVCodecContext *s); HWDevice *hw_device_get_by_name(const char *name); int hw_device_init_from_string(const char *arg, HWDevice **dev); @@ -662,6 +675,7 @@ int hw_device_setup_for_decode(InputStream *ist); int hw_device_setup_for_encode(OutputStream *ost); +int hw_device_setup_for_filter(FilterGraph *fg); int hwaccel_decode_init(AVCodecContext *avctx); diff -Nru ffmpeg-4.2.2/fftools/ffmpeg_hw.c ffmpeg-4.4/fftools/ffmpeg_hw.c --- ffmpeg-4.2.2/fftools/ffmpeg_hw.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/fftools/ffmpeg_hw.c 2020-07-11 10:39:30.000000000 +0000 @@ -19,6 +19,8 @@ #include #include "libavutil/avstring.h" +#include "libavutil/pixdesc.h" +#include "libavfilter/buffersink.h" #include "ffmpeg.h" @@ -416,18 +418,57 @@ int hw_device_setup_for_encode(OutputStream *ost) { - HWDevice *dev; + const AVCodecHWConfig *config; + HWDevice *dev = NULL; + AVBufferRef *frames_ref = NULL; + int i; + + if (ost->filter) { + frames_ref = av_buffersink_get_hw_frames_ctx(ost->filter->filter); + if (frames_ref && + ((AVHWFramesContext*)frames_ref->data)->format == + ost->enc_ctx->pix_fmt) { + // Matching format, will try to use hw_frames_ctx. + } else { + frames_ref = NULL; + } + } + + for (i = 0;; i++) { + config = avcodec_get_hw_config(ost->enc, i); + if (!config) + break; + + if (frames_ref && + config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX && + (config->pix_fmt == AV_PIX_FMT_NONE || + config->pix_fmt == ost->enc_ctx->pix_fmt)) { + av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using input " + "frames context (format %s) with %s encoder.\n", + av_get_pix_fmt_name(ost->enc_ctx->pix_fmt), + ost->enc->name); + ost->enc_ctx->hw_frames_ctx = av_buffer_ref(frames_ref); + if (!ost->enc_ctx->hw_frames_ctx) + return AVERROR(ENOMEM); + return 0; + } + + if (!dev && + config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) + dev = hw_device_get_by_type(config->device_type); + } - dev = hw_device_match_by_codec(ost->enc); if (dev) { + av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using device %s " + "(type %s) with %s encoder.\n", dev->name, + av_hwdevice_get_type_name(dev->type), ost->enc->name); ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); if (!ost->enc_ctx->hw_device_ctx) return AVERROR(ENOMEM); - return 0; } else { // No device required, or no device available. - return 0; } + return 0; } static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input) @@ -480,3 +521,31 @@ return 0; } + +int hw_device_setup_for_filter(FilterGraph *fg) +{ + HWDevice *dev; + int i; + + // If the user has supplied exactly one hardware device then just + // give it straight to every filter for convenience. If more than + // one device is available then the user needs to pick one explcitly + // with the filter_hw_device option. + if (filter_hw_device) + dev = filter_hw_device; + else if (nb_hw_devices == 1) + dev = hw_devices[0]; + else + dev = NULL; + + if (dev) { + for (i = 0; i < fg->graph->nb_filters; i++) { + fg->graph->filters[i]->hw_device_ctx = + av_buffer_ref(dev->device_ref); + if (!fg->graph->filters[i]->hw_device_ctx) + return AVERROR(ENOMEM); + } + } + + return 0; +} diff -Nru ffmpeg-4.2.2/fftools/ffmpeg_opt.c ffmpeg-4.4/fftools/ffmpeg_opt.c --- ffmpeg-4.2.2/fftools/ffmpeg_opt.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/fftools/ffmpeg_opt.c 2021-04-08 21:28:39.000000000 +0000 @@ -1,3 +1,4 @@ + /* * ffmpeg option parsing * @@ -43,16 +44,83 @@ #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass" +#define SPECIFIER_OPT_FMT_str "%s" +#define SPECIFIER_OPT_FMT_i "%i" +#define SPECIFIER_OPT_FMT_i64 "%"PRId64 +#define SPECIFIER_OPT_FMT_ui64 "%"PRIu64 +#define SPECIFIER_OPT_FMT_f "%f" +#define SPECIFIER_OPT_FMT_dbl "%lf" + +static const char *const opt_name_codec_names[] = {"c", "codec", "acodec", "vcodec", "scodec", "dcodec", NULL}; +static const char *const opt_name_audio_channels[] = {"ac", NULL}; +static const char *const opt_name_audio_sample_rate[] = {"ar", NULL}; +static const char *const opt_name_frame_rates[] = {"r", NULL}; +static const char *const opt_name_max_frame_rates[] = {"fpsmax", NULL}; +static const char *const opt_name_frame_sizes[] = {"s", NULL}; +static const char *const opt_name_frame_pix_fmts[] = {"pix_fmt", NULL}; +static const char *const opt_name_ts_scale[] = {"itsscale", NULL}; +static const char *const opt_name_hwaccels[] = {"hwaccel", NULL}; +static const char *const opt_name_hwaccel_devices[] = {"hwaccel_device", NULL}; +static const char *const opt_name_hwaccel_output_formats[] = {"hwaccel_output_format", NULL}; +static const char *const opt_name_autorotate[] = {"autorotate", NULL}; +static const char *const opt_name_autoscale[] = {"autoscale", NULL}; +static const char *const opt_name_max_frames[] = {"frames", "aframes", "vframes", "dframes", NULL}; +static const char *const opt_name_bitstream_filters[] = {"bsf", "absf", "vbsf", NULL}; +static const char *const opt_name_codec_tags[] = {"tag", "atag", "vtag", "stag", NULL}; +static const char *const opt_name_sample_fmts[] = {"sample_fmt", NULL}; +static const char *const opt_name_qscale[] = {"q", "qscale", NULL}; +static const char *const opt_name_forced_key_frames[] = {"forced_key_frames", NULL}; +static const char *const opt_name_force_fps[] = {"force_fps", NULL}; +static const char *const opt_name_frame_aspect_ratios[] = {"aspect", NULL}; +static const char *const opt_name_rc_overrides[] = {"rc_override", NULL}; +static const char *const opt_name_intra_matrices[] = {"intra_matrix", NULL}; +static const char *const opt_name_inter_matrices[] = {"inter_matrix", NULL}; +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_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}; +static const char *const opt_name_reinit_filters[] = {"reinit_filter", NULL}; +static const char *const opt_name_fix_sub_duration[] = {"fix_sub_duration", NULL}; +static const char *const opt_name_canvas_sizes[] = {"canvas_size", NULL}; +static const char *const opt_name_pass[] = {"pass", NULL}; +static const char *const opt_name_passlogfiles[] = {"passlogfile", NULL}; +static const char *const opt_name_max_muxing_queue_size[] = {"max_muxing_queue_size", NULL}; +static const char *const opt_name_muxing_queue_data_threshold[] = {"muxing_queue_data_threshold", NULL}; +static const char *const opt_name_guess_layout_max[] = {"guess_layout_max", NULL}; +static const char *const opt_name_apad[] = {"apad", NULL}; +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}; + +#define WARN_MULTIPLE_OPT_USAGE(name, type, so, st)\ +{\ + char namestr[128] = "";\ + const char *spec = so->specifier && so->specifier[0] ? so->specifier : "";\ + for (i = 0; opt_name_##name[i]; i++)\ + av_strlcatf(namestr, sizeof(namestr), "-%s%s", opt_name_##name[i], opt_name_##name[i+1] ? (opt_name_##name[i+2] ? ", " : " or ") : "");\ + av_log(NULL, AV_LOG_WARNING, "Multiple %s options specified for stream %d, only the last option '-%s%s%s "SPECIFIER_OPT_FMT_##type"' will be used.\n",\ + namestr, st->index, opt_name_##name[0], spec[0] ? ":" : "", spec, so->u.type);\ +} + #define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\ {\ - int i, ret;\ + int i, ret, matches = 0;\ + SpecifierOpt *so;\ for (i = 0; i < o->nb_ ## name; i++) {\ char *spec = o->name[i].specifier;\ - if ((ret = check_stream_specifier(fmtctx, st, spec)) > 0)\ + if ((ret = check_stream_specifier(fmtctx, st, spec)) > 0) {\ outvar = o->name[i].u.type;\ - else if (ret < 0)\ + so = &o->name[i];\ + matches++;\ + } else if (ret < 0)\ exit_program(1);\ }\ + if (matches > 1)\ + WARN_MULTIPLE_OPT_USAGE(name, type, so, st);\ } #define MATCH_PER_TYPE_OPT(name, type, outvar, fmtctx, mediatype)\ @@ -72,12 +140,8 @@ #if CONFIG_LIBMFX { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV }, #endif -#if CONFIG_CUVID - { "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA }, -#endif { 0 }, }; -AVBufferRef *hw_device_ctx; HWDevice *filter_hw_device; char *vstats_filename; @@ -110,6 +174,8 @@ int filter_nbthreads = 0; int filter_complex_nbthreads = 0; int vstats_version = 2; +int auto_conversion_filters = 1; +int64_t stats_period = 500000; static int intra_only = 0; @@ -166,19 +232,17 @@ o->limit_filesize = UINT64_MAX; o->chapters_input_file = INT_MAX; o->accurate_seek = 1; + o->thread_queue_size = -1; } static int show_hwaccels(void *optctx, const char *opt, const char *arg) { enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE; - int i; printf("Hardware acceleration methods:\n"); while ((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE) printf("%s\n", av_hwdevice_get_type_name(type)); - for (i = 0; hwaccels[i].name; i++) - printf("%s\n", hwaccels[i].name); printf("\n"); return 0; } @@ -204,8 +268,9 @@ static int opt_abort_on(void *optctx, const char *opt, const char *arg) { static const AVOption opts[] = { - { "abort_on" , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" }, - { "empty_output" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = ABORT_ON_FLAG_EMPTY_OUTPUT }, .unit = "flags" }, + { "abort_on" , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" }, + { "empty_output" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = ABORT_ON_FLAG_EMPTY_OUTPUT }, .unit = "flags" }, + { "empty_output_stream", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = ABORT_ON_FLAG_EMPTY_OUTPUT_STREAM }, .unit = "flags" }, { NULL }, }; static const AVClass class = { @@ -219,6 +284,21 @@ return av_opt_eval_flags(&pclass, &opts[0], arg, &abort_on_flags); } +static int opt_stats_period(void *optctx, const char *opt, const char *arg) +{ + int64_t user_stats_period = parse_time_or_die(opt, arg, 1); + + if (user_stats_period <= 0) { + av_log(NULL, AV_LOG_ERROR, "stats_period %s must be positive.\n", arg); + return AVERROR(EINVAL); + } + + stats_period = user_stats_period; + av_log(NULL, AV_LOG_INFO, "ffmpeg stats and -progress period set to %s.\n", 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. " @@ -477,21 +557,15 @@ #if CONFIG_VAAPI static int opt_vaapi_device(void *optctx, const char *opt, const char *arg) { - HWDevice *dev; const char *prefix = "vaapi:"; char *tmp; int err; tmp = av_asprintf("%s%s", prefix, arg); if (!tmp) return AVERROR(ENOMEM); - err = hw_device_init_from_string(tmp, &dev); + err = hw_device_init_from_string(tmp, NULL); av_free(tmp); - if (err < 0) - return err; - hw_device_ctx = av_buffer_ref(dev->device_ref); - if (!hw_device_ctx) - return AVERROR(ENOMEM); - return 0; + return err; } #endif @@ -692,13 +766,13 @@ return codec; } -static AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *st) +static const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *st) { char *codec_name = NULL; MATCH_PER_STREAM_OPT(codec_names, str, codec_name, s, st); if (codec_name) { - AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0); + const AVCodec *codec = find_codec_or_die(codec_name, st->codecpar->codec_type, 0); st->codecpar->codec_id = codec->id; return codec; } else @@ -794,15 +868,6 @@ case AVMEDIA_TYPE_VIDEO: if(!ist->dec) ist->dec = avcodec_find_decoder(par->codec_id); -#if FF_API_LOWRES - if (st->codec->lowres) { - ist->dec_ctx->lowres = st->codec->lowres; - ist->dec_ctx->width = st->codec->width; - ist->dec_ctx->height = st->codec->height; - ist->dec_ctx->coded_width = st->codec->coded_width; - ist->dec_ctx->coded_height = st->codec->coded_height; - } -#endif // avformat_find_stream_info() doesn't set this for us anymore. ist->dec_ctx->framerate = st->avg_frame_rate; @@ -819,9 +884,28 @@ MATCH_PER_STREAM_OPT(top_field_first, i, ist->top_field_first, ic, st); MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st); + MATCH_PER_STREAM_OPT(hwaccel_output_formats, str, + hwaccel_output_format, ic, st); + + if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "cuvid")) { + av_log(NULL, AV_LOG_WARNING, + "WARNING: defaulting hwaccel_output_format to cuda for compatibility " + "with old commandlines. This behaviour is DEPRECATED and will be removed " + "in the future. Please explicitly set \"-hwaccel_output_format cuda\".\n"); + ist->hwaccel_output_format = AV_PIX_FMT_CUDA; + } else if (hwaccel_output_format) { + ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format); + if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) { + av_log(NULL, AV_LOG_FATAL, "Unrecognised hwaccel output " + "format: %s", hwaccel_output_format); + } + } else { + ist->hwaccel_output_format = AV_PIX_FMT_NONE; + } + if (hwaccel) { // The NVDEC hwaccels use a CUDA device, so remap the name here. - if (!strcmp(hwaccel, "nvdec")) + if (!strcmp(hwaccel, "nvdec") || !strcmp(hwaccel, "cuvid")) hwaccel = "cuda"; if (!strcmp(hwaccel, "none")) @@ -855,8 +939,6 @@ AV_HWDEVICE_TYPE_NONE) av_log(NULL, AV_LOG_FATAL, "%s ", av_hwdevice_get_type_name(type)); - for (i = 0; hwaccels[i].name; i++) - av_log(NULL, AV_LOG_FATAL, "%s ", hwaccels[i].name); av_log(NULL, AV_LOG_FATAL, "\n"); exit_program(1); } @@ -870,18 +952,6 @@ exit_program(1); } - MATCH_PER_STREAM_OPT(hwaccel_output_formats, str, - hwaccel_output_format, ic, st); - if (hwaccel_output_format) { - ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format); - if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) { - av_log(NULL, AV_LOG_FATAL, "Unrecognised hwaccel output " - "format: %s", hwaccel_output_format); - } - } else { - ist->hwaccel_output_format = AV_PIX_FMT_NONE; - } - ist->hwaccel_pix_fmt = AV_PIX_FMT_NONE; break; @@ -931,7 +1001,7 @@ if (!file_overwrite) { if (proto_name && !strcmp(proto_name, "file") && avio_check(filename, 0) == 0) { if (stdin_interaction && !no_file_overwrite) { - fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename); + fprintf(stderr,"File '%s' already exists. Overwrite? [y/N] ", filename); fflush(stderr); term_exit(); signal(SIGINT, SIG_DFL); @@ -1210,8 +1280,11 @@ f->loop = o->loop; f->duration = 0; f->time_base = (AVRational){ 1, 1 }; + f->pkt = av_packet_alloc(); + if (!f->pkt) + exit_program(1); #if HAVE_THREADS - f->thread_queue_size = o->thread_queue_size > 0 ? o->thread_queue_size : 8; + f->thread_queue_size = o->thread_queue_size; #endif /* check if all codec options have been used */ @@ -1404,6 +1477,8 @@ ost->encoder_opts = filter_codec_opts(o->g->codec_opts, ost->enc->id, oc, st, ost->enc); MATCH_PER_STREAM_OPT(presets, str, preset, oc, st); + 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)))) { do { buf = get_line(s); @@ -1471,54 +1546,12 @@ MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st); MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st); - while (bsfs && *bsfs) { - const AVBitStreamFilter *filter; - char *bsf, *bsf_options_str, *bsf_name; - - bsf = av_get_token(&bsfs, ","); - if (!bsf) - exit_program(1); - bsf_name = av_strtok(bsf, "=", &bsf_options_str); - if (!bsf_name) - exit_program(1); - - filter = av_bsf_get_by_name(bsf_name); - if (!filter) { - av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", bsf_name); - exit_program(1); - } - - ost->bsf_ctx = av_realloc_array(ost->bsf_ctx, - ost->nb_bitstream_filters + 1, - sizeof(*ost->bsf_ctx)); - if (!ost->bsf_ctx) - exit_program(1); - - ret = av_bsf_alloc(filter, &ost->bsf_ctx[ost->nb_bitstream_filters]); + if (bsfs && *bsfs) { + ret = av_bsf_list_parse_str(bsfs, &ost->bsf_ctx); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error allocating a bitstream filter context\n"); + av_log(NULL, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s': %s\n", bsfs, av_err2str(ret)); exit_program(1); } - - ost->nb_bitstream_filters++; - - if (bsf_options_str && filter->priv_class) { - const AVOption *opt = av_opt_next(ost->bsf_ctx[ost->nb_bitstream_filters-1]->priv_data, NULL); - const char * shorthand[2] = {NULL}; - - if (opt) - shorthand[0] = opt->name; - - ret = av_opt_set_from_string(ost->bsf_ctx[ost->nb_bitstream_filters-1]->priv_data, bsf_options_str, shorthand, "=", ":"); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error parsing options for bitstream filter %s\n", bsf_name); - exit_program(1); - } - } - av_freep(&bsf); - - if (*bsfs) - bsfs++; } MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, oc, st); @@ -1541,7 +1574,12 @@ ost->max_muxing_queue_size = 128; MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st); - ost->max_muxing_queue_size *= sizeof(AVPacket); + ost->max_muxing_queue_size *= sizeof(ost->pkt); + + ost->muxing_queue_data_size = 0; + + ost->muxing_queue_data_threshold = 50*1024*1024; + MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ost->muxing_queue_data_threshold, oc, st); if (oc->oformat->flags & AVFMT_GLOBALHEADER) ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; @@ -1654,7 +1692,7 @@ AVStream *st; OutputStream *ost; AVCodecContext *video_enc; - char *frame_rate = NULL, *frame_aspect_ratio = NULL; + char *frame_rate = NULL, *max_frame_rate = NULL, *frame_aspect_ratio = NULL; ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO, source_index); st = ost->st; @@ -1665,8 +1703,21 @@ av_log(NULL, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate); exit_program(1); } - if (frame_rate && video_sync_method == VSYNC_PASSTHROUGH) - av_log(NULL, AV_LOG_ERROR, "Using -vsync 0 and -r can produce invalid output files\n"); + + MATCH_PER_STREAM_OPT(max_frame_rates, str, max_frame_rate, oc, st); + if (max_frame_rate && av_parse_video_rate(&ost->max_frame_rate, max_frame_rate) < 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid maximum framerate value: %s\n", max_frame_rate); + exit_program(1); + } + + if (frame_rate && max_frame_rate) { + av_log(NULL, AV_LOG_ERROR, "Only one of -fpsmax and -r can be set for a stream.\n"); + exit_program(1); + } + + 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"); MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); if (frame_aspect_ratio) { @@ -1681,8 +1732,6 @@ MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); - if (o->nb_filters > 1) - av_log(NULL, AV_LOG_ERROR, "Only '-vf %s' read, ignoring remaining -vf options: Use ',' to separate filters\n", ost->filters); if (!ost->stream_copy) { const char *p = NULL; @@ -1864,8 +1913,6 @@ MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); - if (o->nb_filters > 1) - av_log(NULL, AV_LOG_ERROR, "Only '-af %s' read, ignoring remaining -af options: Use ',' to separate filters\n", ost->filters); if (!ost->stream_copy) { char *sample_fmt = NULL; @@ -2193,22 +2240,23 @@ /* video: highest resolution */ if (!o->video_disable && av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_VIDEO) != AV_CODEC_ID_NONE) { - int area = 0, idx = -1; + int best_score = 0, idx = -1; int qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0); for (i = 0; i < nb_input_streams; i++) { - int new_area; + int score; ist = input_streams[i]; - new_area = ist->st->codecpar->width * ist->st->codecpar->height + 100000000*!!ist->st->codec_info_nb_frames + score = ist->st->codecpar->width * ist->st->codecpar->height + + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); if (ist->user_set_discard == AVDISCARD_ALL) continue; if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) - new_area = 1; + score = 1; if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && - new_area > area) { + score > best_score) { if((qcr==MKTAG('A', 'P', 'I', 'C')) && !(ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)) continue; - area = new_area; + best_score = score; idx = i; } } @@ -2372,12 +2420,14 @@ o->attachments[i]); exit_program(1); } - if (!(attachment = av_malloc(len))) { - av_log(NULL, AV_LOG_FATAL, "Attachment %s too large to fit into memory.\n", + if (len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE || + !(attachment = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE))) { + av_log(NULL, AV_LOG_FATAL, "Attachment %s too large.\n", o->attachments[i]); exit_program(1); } avio_read(pb, attachment, len); + memset(attachment + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); ost = new_attachment_stream(o, oc, -1); ost->stream_copy = 0; @@ -2608,6 +2658,9 @@ if(o->recording_time != INT64_MAX) av_dict_set(&oc->metadata, "duration", NULL, 0); av_dict_set(&oc->metadata, "creation_time", NULL, 0); + av_dict_set(&oc->metadata, "company_name", NULL, 0); + av_dict_set(&oc->metadata, "product_name", NULL, 0); + av_dict_set(&oc->metadata, "product_version", NULL, 0); } if (!o->metadata_streams_manual) for (i = of->ost_index; i < nb_output_streams; i++) { @@ -2769,13 +2822,14 @@ } else { /* Try to determine PAL/NTSC by peeking in the input files */ if (nb_input_files) { - int i, j, fr; + int i, j; for (j = 0; j < nb_input_files; j++) { for (i = 0; i < input_files[j]->nb_streams; i++) { AVStream *st = input_files[j]->ctx->streams[i]; + int64_t fr; if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) continue; - fr = st->time_base.den * 1000 / st->time_base.num; + fr = st->time_base.den * 1000LL / st->time_base.num; if (fr == 25000) { norm = PAL; break; @@ -3005,8 +3059,11 @@ static int opt_old2new(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; + int ret; char *s = av_asprintf("%s:%c", opt + 1, *opt); - int ret = parse_option(o, s, arg, options); + if (!s) + return AVERROR(ENOMEM); + ret = parse_option(o, s, arg, options); av_free(s); return ret; } @@ -3037,6 +3094,8 @@ return parse_option(o, "q:v", arg, options); } s = av_asprintf("q%s", opt + 6); + if (!s) + return AVERROR(ENOMEM); ret = parse_option(o, s, arg, options); av_free(s); return ret; @@ -3081,8 +3140,11 @@ static int opt_timecode(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; + int ret; char *tcr = av_asprintf("timecode=%s", arg); - int ret = parse_option(o, "metadata:g", tcr, options); + if (!tcr) + return AVERROR(ENOMEM); + ret = parse_option(o, "metadata:g", tcr, options); if (ret >= 0) ret = av_dict_set(&o->g->codec_opts, "gop_timecode", arg, 0); av_free(tcr); @@ -3184,7 +3246,7 @@ " -h -- print basic options\n" " -h long -- print more options\n" " -h full -- print all options (including all format and codec specific options, very long)\n" - " -h type=name -- print all options for the named decoder/encoder/demuxer/muxer/filter/bsf\n" + " -h type=name -- print all options for the named decoder/encoder/demuxer/muxer/filter/bsf/protocol\n" " See man %s for detailed description of the options.\n" "\n", program_name); @@ -3192,7 +3254,7 @@ OPT_EXIT, 0, 0); show_help_options(options, "Global options (affect whole program " - "instead of just one file:", + "instead of just one file):", 0, per_file | OPT_EXIT | OPT_EXPERT, 0); if (show_advanced) show_help_options(options, "Advanced global options:", OPT_EXPERT, @@ -3268,6 +3330,7 @@ if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error parsing options for %s file " "%s.\n", inout, g->arg); + uninit_options(&o); return ret; } @@ -3441,7 +3504,7 @@ { "stdin", OPT_BOOL | OPT_EXPERT, { &stdin_interaction }, "enable or disable interaction on standard input" }, { "timelimit", HAS_ARG | OPT_EXPERT, { .func_arg = opt_timelimit }, - "set max runtime in seconds", "limit" }, + "set max runtime in seconds in CPU user time", "limit" }, { "dump", OPT_BOOL | OPT_EXPERT, { &do_pkt_dump }, "dump each input packet" }, { "hex", OPT_BOOL | OPT_EXPERT, { &do_hex_dump }, @@ -3517,8 +3580,12 @@ "create a complex filtergraph", "graph_description" }, { "filter_complex_script", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex_script }, "read complex filtergraph description from a file", "filename" }, + { "auto_conversion_filters", OPT_BOOL | OPT_EXPERT, { &auto_conversion_filters }, + "enable automatic conversion filters globally" }, { "stats", OPT_BOOL, { &print_stats }, "print progress report during encoding", }, + { "stats_period", HAS_ARG | OPT_EXPERT, { .func_arg = opt_stats_period }, + "set the period at which ffmpeg updates stats and -progress output", "time" }, { "attach", HAS_ARG | OPT_PERFILE | OPT_EXPERT | OPT_OUTPUT, { .func_arg = opt_attach }, "add an attachment to the output file", "filename" }, @@ -3530,7 +3597,7 @@ { "debug_ts", OPT_BOOL | OPT_EXPERT, { &debug_ts }, "print timestamp debugging info" }, { "max_error_rate", HAS_ARG | OPT_FLOAT, { &max_error_rate }, - "ratio of errors (0.0: no errors, 1.0: 100% errors) above which ffmpeg returns an error instead of success.", "maximum error rate" }, + "ratio of decoding errors (0.0: no errors, 1.0: 100% errors) above which ffmpeg returns an error instead of success.", "maximum error rate" }, { "discard", OPT_STRING | HAS_ARG | OPT_SPEC | OPT_INPUT, { .off = OFFSET(discard) }, "discard", "" }, @@ -3549,6 +3616,9 @@ { "r", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_rates) }, "set frame rate (Hz value, fraction or abbreviation)", "rate" }, + { "fpsmax", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(max_frame_rates) }, + "set max frame rate (Hz value, fraction or abbreviation)", "rate" }, { "s", OPT_VIDEO | HAS_ARG | OPT_SUBTITLE | OPT_STRING | OPT_SPEC | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_sizes) }, "set frame size (WxH or abbreviation)", "size" }, @@ -3640,6 +3710,9 @@ { "autorotate", HAS_ARG | OPT_BOOL | OPT_SPEC | OPT_EXPERT | OPT_INPUT, { .off = OFFSET(autorotate) }, "automatically insert correct rotate filters" }, + { "autoscale", HAS_ARG | OPT_BOOL | OPT_SPEC | + OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(autoscale) }, + "automatically insert a scale filter at the end of the filter graph" }, /* audio options */ { "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames }, @@ -3726,6 +3799,8 @@ { "max_muxing_queue_size", HAS_ARG | OPT_INT | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(max_muxing_queue_size) }, "maximum number of packets that can be buffered while waiting for all streams to initialize", "packets" }, + { "muxing_queue_data_threshold", HAS_ARG | OPT_INT | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(muxing_queue_data_threshold) }, + "set the threshold after which max_muxing_queue_size is taken into account", "bytes" }, /* data codec support */ { "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_data_codec }, diff -Nru ffmpeg-4.2.2/fftools/ffmpeg_qsv.c ffmpeg-4.4/fftools/ffmpeg_qsv.c --- ffmpeg-4.2.2/fftools/ffmpeg_qsv.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/fftools/ffmpeg_qsv.c 2020-07-11 10:39:30.000000000 +0000 @@ -28,6 +28,7 @@ #include "ffmpeg.h" +static AVBufferRef *hw_device_ctx; char *qsv_device = NULL; static int qsv_get_buffer(AVCodecContext *s, AVFrame *frame, int flags) diff -Nru ffmpeg-4.2.2/fftools/ffmpeg_videotoolbox.c ffmpeg-4.4/fftools/ffmpeg_videotoolbox.c --- ffmpeg-4.2.2/fftools/ffmpeg_videotoolbox.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/fftools/ffmpeg_videotoolbox.c 2020-07-11 10:39:30.000000000 +0000 @@ -51,10 +51,12 @@ 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: vt->tmp_frame->format = AV_PIX_FMT_NV12; break; + case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: + case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: vt->tmp_frame->format = AV_PIX_FMT_NV12; break; #endif #if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE - case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange: vt->tmp_frame->format = AV_PIX_FMT_P010; break; + case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange: + case kCVPixelFormatType_420YpCbCr10BiPlanarFullRange: vt->tmp_frame->format = AV_PIX_FMT_P010; break; #endif default: av_log(NULL, AV_LOG_ERROR, @@ -65,7 +67,7 @@ vt->tmp_frame->width = frame->width; vt->tmp_frame->height = frame->height; - ret = av_frame_get_buffer(vt->tmp_frame, 32); + ret = av_frame_get_buffer(vt->tmp_frame, 0); if (ret < 0) return ret; diff -Nru ffmpeg-4.2.2/fftools/ffplay.c ffmpeg-4.4/fftools/ffplay.c --- ffmpeg-4.2.2/fftools/ffplay.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/fftools/ffplay.c 2021-04-08 21:28:39.000000000 +0000 @@ -36,10 +36,12 @@ #include "libavutil/pixdesc.h" #include "libavutil/imgutils.h" #include "libavutil/dict.h" +#include "libavutil/fifo.h" #include "libavutil/parseutils.h" #include "libavutil/samplefmt.h" #include "libavutil/avassert.h" #include "libavutil/time.h" +#include "libavutil/bprint.h" #include "libavformat/avformat.h" #include "libavdevice/avdevice.h" #include "libswscale/swscale.h" @@ -110,13 +112,12 @@ static unsigned sws_flags = SWS_BICUBIC; typedef struct MyAVPacketList { - AVPacket pkt; - struct MyAVPacketList *next; + AVPacket *pkt; int serial; } MyAVPacketList; typedef struct PacketQueue { - MyAVPacketList *first_pkt, *last_pkt; + AVFifoBuffer *pkt_list; int nb_packets; int size; int64_t duration; @@ -186,7 +187,7 @@ }; typedef struct Decoder { - AVPacket pkt; + AVPacket *pkt; PacketQueue *queue; AVCodecContext *avctx; int pkt_serial; @@ -326,7 +327,7 @@ static int borderless; static int alwaysontop; static int startup_volume = 100; -static int show_status = 1; +static int show_status = -1; static int av_sync_type = AV_SYNC_AUDIO_MASTER; static int64_t start_time = AV_NOPTS_VALUE; static int64_t duration = AV_NOPTS_VALUE; @@ -360,8 +361,6 @@ static int is_full_screen; static int64_t audio_callback_time; -static AVPacket flush_pkt; - #define FF_QUIT_EVENT (SDL_USEREVENT + 2) static SDL_Window *window; @@ -426,28 +425,23 @@ static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt) { - MyAVPacketList *pkt1; + MyAVPacketList pkt1; if (q->abort_request) return -1; - pkt1 = av_malloc(sizeof(MyAVPacketList)); - if (!pkt1) - return -1; - pkt1->pkt = *pkt; - pkt1->next = NULL; - if (pkt == &flush_pkt) - q->serial++; - pkt1->serial = q->serial; + if (av_fifo_space(q->pkt_list) < sizeof(pkt1)) { + if (av_fifo_grow(q->pkt_list, sizeof(pkt1)) < 0) + return -1; + } - if (!q->last_pkt) - q->first_pkt = pkt1; - else - q->last_pkt->next = pkt1; - q->last_pkt = pkt1; + pkt1.pkt = pkt; + pkt1.serial = q->serial; + + av_fifo_generic_write(q->pkt_list, &pkt1, sizeof(pkt1), NULL); q->nb_packets++; - q->size += pkt1->pkt.size + sizeof(*pkt1); - q->duration += pkt1->pkt.duration; + q->size += pkt1.pkt->size + sizeof(pkt1); + q->duration += pkt1.pkt->duration; /* XXX: should duplicate packet data in DV case */ SDL_CondSignal(q->cond); return 0; @@ -455,24 +449,28 @@ static int packet_queue_put(PacketQueue *q, AVPacket *pkt) { + AVPacket *pkt1; int ret; + pkt1 = av_packet_alloc(); + if (!pkt1) { + av_packet_unref(pkt); + return -1; + } + av_packet_move_ref(pkt1, pkt); + SDL_LockMutex(q->mutex); - ret = packet_queue_put_private(q, pkt); + ret = packet_queue_put_private(q, pkt1); SDL_UnlockMutex(q->mutex); - if (pkt != &flush_pkt && ret < 0) - av_packet_unref(pkt); + if (ret < 0) + av_packet_free(&pkt1); return ret; } -static int packet_queue_put_nullpacket(PacketQueue *q, int stream_index) +static int packet_queue_put_nullpacket(PacketQueue *q, AVPacket *pkt, int stream_index) { - AVPacket pkt1, *pkt = &pkt1; - av_init_packet(pkt); - pkt->data = NULL; - pkt->size = 0; pkt->stream_index = stream_index; return packet_queue_put(q, pkt); } @@ -481,6 +479,9 @@ static int packet_queue_init(PacketQueue *q) { memset(q, 0, sizeof(PacketQueue)); + q->pkt_list = av_fifo_alloc(sizeof(MyAVPacketList)); + if (!q->pkt_list) + return AVERROR(ENOMEM); q->mutex = SDL_CreateMutex(); if (!q->mutex) { av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); @@ -497,25 +498,24 @@ static void packet_queue_flush(PacketQueue *q) { - MyAVPacketList *pkt, *pkt1; + MyAVPacketList pkt1; SDL_LockMutex(q->mutex); - for (pkt = q->first_pkt; pkt; pkt = pkt1) { - pkt1 = pkt->next; - av_packet_unref(&pkt->pkt); - av_freep(&pkt); + while (av_fifo_size(q->pkt_list) >= sizeof(pkt1)) { + av_fifo_generic_read(q->pkt_list, &pkt1, sizeof(pkt1), NULL); + av_packet_free(&pkt1.pkt); } - q->last_pkt = NULL; - q->first_pkt = NULL; q->nb_packets = 0; q->size = 0; q->duration = 0; + q->serial++; SDL_UnlockMutex(q->mutex); } static void packet_queue_destroy(PacketQueue *q) { packet_queue_flush(q); + av_fifo_freep(&q->pkt_list); SDL_DestroyMutex(q->mutex); SDL_DestroyCond(q->cond); } @@ -535,14 +535,14 @@ { SDL_LockMutex(q->mutex); q->abort_request = 0; - packet_queue_put_private(q, &flush_pkt); + q->serial++; SDL_UnlockMutex(q->mutex); } /* return < 0 if aborted, 0 if no packet and > 0 if packet. */ static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial) { - MyAVPacketList *pkt1; + MyAVPacketList pkt1; int ret; SDL_LockMutex(q->mutex); @@ -553,18 +553,15 @@ break; } - pkt1 = q->first_pkt; - if (pkt1) { - q->first_pkt = pkt1->next; - if (!q->first_pkt) - q->last_pkt = NULL; + if (av_fifo_size(q->pkt_list) >= sizeof(pkt1)) { + av_fifo_generic_read(q->pkt_list, &pkt1, sizeof(pkt1), NULL); q->nb_packets--; - q->size -= pkt1->pkt.size + sizeof(*pkt1); - q->duration -= pkt1->pkt.duration; - *pkt = pkt1->pkt; + q->size -= pkt1.pkt->size + sizeof(pkt1); + q->duration -= pkt1.pkt->duration; + av_packet_move_ref(pkt, pkt1.pkt); if (serial) - *serial = pkt1->serial; - av_free(pkt1); + *serial = pkt1.serial; + av_packet_free(&pkt1.pkt); ret = 1; break; } else if (!block) { @@ -578,21 +575,23 @@ return ret; } -static void decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond) { +static int decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond) { memset(d, 0, sizeof(Decoder)); + d->pkt = av_packet_alloc(); + if (!d->pkt) + return AVERROR(ENOMEM); d->avctx = avctx; d->queue = queue; d->empty_queue_cond = empty_queue_cond; d->start_pts = AV_NOPTS_VALUE; d->pkt_serial = -1; + return 0; } static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) { int ret = AVERROR(EAGAIN); for (;;) { - AVPacket pkt; - if (d->queue->serial == d->pkt_serial) { do { if (d->queue->abort_request) @@ -638,46 +637,48 @@ if (d->queue->nb_packets == 0) SDL_CondSignal(d->empty_queue_cond); if (d->packet_pending) { - av_packet_move_ref(&pkt, &d->pkt); d->packet_pending = 0; } else { - if (packet_queue_get(d->queue, &pkt, 1, &d->pkt_serial) < 0) + int old_serial = d->pkt_serial; + if (packet_queue_get(d->queue, d->pkt, 1, &d->pkt_serial) < 0) return -1; + if (old_serial != d->pkt_serial) { + avcodec_flush_buffers(d->avctx); + d->finished = 0; + d->next_pts = d->start_pts; + d->next_pts_tb = d->start_pts_tb; + } } - } while (d->queue->serial != d->pkt_serial); + if (d->queue->serial == d->pkt_serial) + break; + av_packet_unref(d->pkt); + } while (1); - if (pkt.data == flush_pkt.data) { - avcodec_flush_buffers(d->avctx); - d->finished = 0; - d->next_pts = d->start_pts; - d->next_pts_tb = d->start_pts_tb; - } else { - if (d->avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { - int got_frame = 0; - ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, &pkt); - if (ret < 0) { - ret = AVERROR(EAGAIN); - } else { - if (got_frame && !pkt.data) { - d->packet_pending = 1; - av_packet_move_ref(&d->pkt, &pkt); - } - ret = got_frame ? 0 : (pkt.data ? AVERROR(EAGAIN) : AVERROR_EOF); - } + if (d->avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { + int got_frame = 0; + ret = avcodec_decode_subtitle2(d->avctx, sub, &got_frame, d->pkt); + if (ret < 0) { + ret = AVERROR(EAGAIN); } else { - if (avcodec_send_packet(d->avctx, &pkt) == AVERROR(EAGAIN)) { - av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n"); + if (got_frame && !d->pkt->data) { d->packet_pending = 1; - av_packet_move_ref(&d->pkt, &pkt); } + ret = got_frame ? 0 : (d->pkt->data ? AVERROR(EAGAIN) : AVERROR_EOF); + } + av_packet_unref(d->pkt); + } else { + if (avcodec_send_packet(d->avctx, d->pkt) == AVERROR(EAGAIN)) { + av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n"); + d->packet_pending = 1; + } else { + av_packet_unref(d->pkt); } - av_packet_unref(&pkt); } } } static void decoder_destroy(Decoder *d) { - av_packet_unref(&d->pkt); + av_packet_free(&d->pkt); avcodec_free_context(&d->avctx); } @@ -1147,6 +1148,8 @@ if (realloc_texture(&s->vis_texture, SDL_PIXELFORMAT_ARGB8888, s->width, s->height, SDL_BLENDMODE_NONE, 1) < 0) return; + if (s->xpos >= s->width) + s->xpos = 0; nb_display_channels= FFMIN(nb_display_channels, 2); if (rdft_bits != s->rdft_bits) { av_rdft_end(s->rdft); @@ -1196,8 +1199,6 @@ } if (!s->paused) s->xpos++; - if (s->xpos >= s->width) - s->xpos= s->xleft; } } @@ -1643,37 +1644,37 @@ } if (is->subtitle_st) { - while (frame_queue_nb_remaining(&is->subpq) > 0) { - sp = frame_queue_peek(&is->subpq); - - if (frame_queue_nb_remaining(&is->subpq) > 1) - sp2 = frame_queue_peek_next(&is->subpq); - else - sp2 = NULL; + while (frame_queue_nb_remaining(&is->subpq) > 0) { + sp = frame_queue_peek(&is->subpq); - if (sp->serial != is->subtitleq.serial - || (is->vidclk.pts > (sp->pts + ((float) sp->sub.end_display_time / 1000))) - || (sp2 && is->vidclk.pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000)))) - { - if (sp->uploaded) { - int i; - for (i = 0; i < sp->sub.num_rects; i++) { - AVSubtitleRect *sub_rect = sp->sub.rects[i]; - uint8_t *pixels; - int pitch, j; - - if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) { - for (j = 0; j < sub_rect->h; j++, pixels += pitch) - memset(pixels, 0, sub_rect->w << 2); - SDL_UnlockTexture(is->sub_texture); - } + if (frame_queue_nb_remaining(&is->subpq) > 1) + sp2 = frame_queue_peek_next(&is->subpq); + else + sp2 = NULL; + + if (sp->serial != is->subtitleq.serial + || (is->vidclk.pts > (sp->pts + ((float) sp->sub.end_display_time / 1000))) + || (sp2 && is->vidclk.pts > (sp2->pts + ((float) sp2->sub.start_display_time / 1000)))) + { + if (sp->uploaded) { + int i; + for (i = 0; i < sp->sub.num_rects; i++) { + AVSubtitleRect *sub_rect = sp->sub.rects[i]; + uint8_t *pixels; + int pitch, j; + + if (!SDL_LockTexture(is->sub_texture, (SDL_Rect *)sub_rect, (void **)&pixels, &pitch)) { + for (j = 0; j < sub_rect->h; j++, pixels += pitch) + memset(pixels, 0, sub_rect->w << 2); + SDL_UnlockTexture(is->sub_texture); } } - frame_queue_next(&is->subpq); - } else { - break; } + frame_queue_next(&is->subpq); + } else { + break; } + } } frame_queue_next(&is->pictq); @@ -1689,6 +1690,7 @@ } is->force_refresh = 0; if (show_status) { + AVBPrint buf; static int64_t last_time; int64_t cur_time; int aqsize, vqsize, sqsize; @@ -1712,18 +1714,28 @@ av_diff = get_master_clock(is) - get_clock(&is->vidclk); else if (is->audio_st) av_diff = get_master_clock(is) - get_clock(&is->audclk); - av_log(NULL, AV_LOG_INFO, - "%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r", - get_master_clock(is), - (is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : " ")), - av_diff, - is->frame_drops_early + is->frame_drops_late, - aqsize / 1024, - vqsize / 1024, - sqsize, - is->video_st ? is->viddec.avctx->pts_correction_num_faulty_dts : 0, - is->video_st ? is->viddec.avctx->pts_correction_num_faulty_pts : 0); - fflush(stdout); + + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC); + av_bprintf(&buf, + "%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r", + get_master_clock(is), + (is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : " ")), + av_diff, + is->frame_drops_early + is->frame_drops_late, + aqsize / 1024, + vqsize / 1024, + sqsize, + is->video_st ? is->viddec.avctx->pts_correction_num_faulty_dts : 0, + is->video_st ? is->viddec.avctx->pts_correction_num_faulty_pts : 0); + + if (show_status == 1 && AV_LOG_INFO > av_log_get_level()) + fprintf(stderr, "%s", buf.str); + else + av_log(NULL, AV_LOG_INFO, "%s", buf.str); + + fflush(stderr); + av_bprint_finalize(&buf, NULL); + last_time = cur_time; } } @@ -1993,7 +2005,7 @@ if (force_output_format) { channel_layouts[0] = is->audio_tgt.channel_layout; - channels [0] = is->audio_tgt.channels; + channels [0] = is->audio_tgt.channel_layout ? -1 : is->audio_tgt.channels; sample_rates [0] = is->audio_tgt.freq; if ((ret = av_opt_set_int(filt_asink, "all_channel_counts", 0, AV_OPT_SEARCH_CHILDREN)) < 0) goto end; @@ -2561,7 +2573,7 @@ { AVFormatContext *ic = is->ic; AVCodecContext *avctx; - AVCodec *codec; + const AVCodec *codec; const char *forced_codec_name = NULL; AVDictionary *opts = NULL; AVDictionaryEntry *t = NULL; @@ -2616,8 +2628,6 @@ av_dict_set(&opts, "threads", "auto", 0); if (stream_lowres) av_dict_set_int(&opts, "lowres", stream_lowres, 0); - if (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO) - av_dict_set(&opts, "refcounted_frames", "1", 0); if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) { goto fail; } @@ -2670,7 +2680,8 @@ is->audio_stream = stream_index; is->audio_st = ic->streams[stream_index]; - decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread); + if ((ret = decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread)) < 0) + goto fail; if ((is->ic->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)) && !is->ic->iformat->read_seek) { is->auddec.start_pts = is->audio_st->start_time; is->auddec.start_pts_tb = is->audio_st->time_base; @@ -2683,7 +2694,8 @@ is->video_stream = stream_index; is->video_st = ic->streams[stream_index]; - decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread); + if ((ret = decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread)) < 0) + goto fail; if ((ret = decoder_start(&is->viddec, video_thread, "video_decoder", is)) < 0) goto out; is->queue_attachments_req = 1; @@ -2692,7 +2704,8 @@ is->subtitle_stream = stream_index; is->subtitle_st = ic->streams[stream_index]; - decoder_init(&is->subdec, avctx, &is->subtitleq, is->continue_read_thread); + if ((ret = decoder_init(&is->subdec, avctx, &is->subtitleq, is->continue_read_thread)) < 0) + goto fail; if ((ret = decoder_start(&is->subdec, subtitle_thread, "subtitle_decoder", is)) < 0) goto out; break; @@ -2745,7 +2758,7 @@ AVFormatContext *ic = NULL; int err, i, ret; int st_index[AVMEDIA_TYPE_NB]; - AVPacket pkt1, *pkt = &pkt1; + AVPacket *pkt = NULL; int64_t stream_start_time; int pkt_in_play_range = 0; AVDictionaryEntry *t; @@ -2760,11 +2773,14 @@ } memset(st_index, -1, sizeof(st_index)); - is->last_video_stream = is->video_stream = -1; - is->last_audio_stream = is->audio_stream = -1; - is->last_subtitle_stream = is->subtitle_stream = -1; is->eof = 0; + pkt = av_packet_alloc(); + if (!pkt) { + av_log(NULL, AV_LOG_FATAL, "Could not allocate packet.\n"); + ret = AVERROR(ENOMEM); + goto fail; + } ic = avformat_alloc_context(); if (!ic) { av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n"); @@ -2948,18 +2964,12 @@ av_log(NULL, AV_LOG_ERROR, "%s: error while seeking\n", is->ic->url); } else { - if (is->audio_stream >= 0) { + if (is->audio_stream >= 0) packet_queue_flush(&is->audioq); - packet_queue_put(&is->audioq, &flush_pkt); - } - if (is->subtitle_stream >= 0) { + if (is->subtitle_stream >= 0) packet_queue_flush(&is->subtitleq); - packet_queue_put(&is->subtitleq, &flush_pkt); - } - if (is->video_stream >= 0) { + if (is->video_stream >= 0) packet_queue_flush(&is->videoq); - packet_queue_put(&is->videoq, &flush_pkt); - } if (is->seek_flags & AVSEEK_FLAG_BYTE) { set_clock(&is->extclk, NAN, 0); } else { @@ -2974,11 +2984,10 @@ } if (is->queue_attachments_req) { if (is->video_st && is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC) { - AVPacket copy = { 0 }; - if ((ret = av_packet_ref(©, &is->video_st->attached_pic)) < 0) + if ((ret = av_packet_ref(pkt, &is->video_st->attached_pic)) < 0) goto fail; - packet_queue_put(&is->videoq, ©); - packet_queue_put_nullpacket(&is->videoq, is->video_stream); + packet_queue_put(&is->videoq, pkt); + packet_queue_put_nullpacket(&is->videoq, pkt, is->video_stream); } is->queue_attachments_req = 0; } @@ -3009,15 +3018,19 @@ if (ret < 0) { if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) { if (is->video_stream >= 0) - packet_queue_put_nullpacket(&is->videoq, is->video_stream); + packet_queue_put_nullpacket(&is->videoq, pkt, is->video_stream); if (is->audio_stream >= 0) - packet_queue_put_nullpacket(&is->audioq, is->audio_stream); + packet_queue_put_nullpacket(&is->audioq, pkt, is->audio_stream); if (is->subtitle_stream >= 0) - packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream); + packet_queue_put_nullpacket(&is->subtitleq, pkt, is->subtitle_stream); is->eof = 1; } - if (ic->pb && ic->pb->error) - break; + if (ic->pb && ic->pb->error) { + if (autoexit) + goto fail; + else + break; + } SDL_LockMutex(wait_mutex); SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10); SDL_UnlockMutex(wait_mutex); @@ -3050,6 +3063,7 @@ if (ic && !is->ic) avformat_close_input(&ic); + av_packet_free(&pkt); if (ret != 0) { SDL_Event event; @@ -3068,6 +3082,9 @@ is = av_mallocz(sizeof(VideoState)); if (!is) return NULL; + is->last_video_stream = is->video_stream = -1; + is->last_audio_stream = is->audio_stream = -1; + is->last_subtitle_stream = is->subtitle_stream = -1; is->filename = av_strdup(filename); if (!is->filename) goto fail; @@ -3719,9 +3736,6 @@ SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE); SDL_EventState(SDL_USEREVENT, SDL_IGNORE); - av_init_packet(&flush_pkt); - flush_pkt.data = (uint8_t *)&flush_pkt; - if (!display_disable) { int flags = SDL_WINDOW_HIDDEN; if (alwaysontop) diff -Nru ffmpeg-4.2.2/fftools/ffprobe.c ffmpeg-4.4/fftools/ffprobe.c --- ffmpeg-4.2.2/fftools/ffprobe.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/fftools/ffprobe.c 2021-04-08 21:28:39.000000000 +0000 @@ -35,7 +35,9 @@ #include "libavutil/bprint.h" #include "libavutil/display.h" #include "libavutil/hash.h" +#include "libavutil/hdr_dynamic_metadata.h" #include "libavutil/mastering_display_metadata.h" +#include "libavutil/dovi_meta.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/spherical.h" @@ -254,6 +256,7 @@ /* FFprobe context */ static const char *input_filename; +static const char *print_input_filename; static AVInputFormat *iformat = NULL; static struct AVHashContext *hash; @@ -1083,12 +1086,12 @@ #define OFFSET(x) offsetof(CompactContext, x) static const AVOption compact_options[]= { - {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, CHAR_MIN, CHAR_MAX }, - {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, CHAR_MIN, CHAR_MAX }, + {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 }, + {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 }, {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 }, {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 }, - {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, CHAR_MIN, CHAR_MAX }, - {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, CHAR_MIN, CHAR_MAX }, + {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 }, + {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 }, {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 }, {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 }, {NULL}, @@ -1199,12 +1202,12 @@ #define OFFSET(x) offsetof(CompactContext, x) static const AVOption csv_options[] = { - {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, CHAR_MIN, CHAR_MAX }, - {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, CHAR_MIN, CHAR_MAX }, + {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 }, + {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 }, {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 }, {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 }, - {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, CHAR_MIN, CHAR_MAX }, - {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, CHAR_MIN, CHAR_MAX }, + {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 }, + {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 }, {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 }, {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 }, {NULL}, @@ -1237,8 +1240,8 @@ #define OFFSET(x) offsetof(FlatContext, x) static const AVOption flat_options[]= { - {"sep_char", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, CHAR_MIN, CHAR_MAX }, - {"s", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, CHAR_MIN, CHAR_MAX }, + {"sep_char", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 }, + {"s", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 }, {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 }, {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 }, {NULL}, @@ -1535,7 +1538,7 @@ if (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES) { if (!json->compact) JSON_INDENT(); - printf("\"type\": \"%s\"%s", section->name, json->item_sep); + printf("\"type\": \"%s\"", section->name); } } av_bprint_finalize(&buf, NULL); @@ -1579,8 +1582,10 @@ static void json_print_str(WriterContext *wctx, const char *key, const char *value) { JSONContext *json = wctx->priv; + const struct section *parent_section = wctx->level ? + wctx->section[wctx->level-1] : NULL; - if (wctx->nb_item[wctx->level]) + if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES)) printf("%s", json->item_sep); if (!json->compact) JSON_INDENT(); @@ -1590,9 +1595,11 @@ static void json_print_int(WriterContext *wctx, const char *key, long long int value) { JSONContext *json = wctx->priv; + const struct section *parent_section = wctx->level ? + wctx->section[wctx->level-1] : NULL; AVBPrint buf; - if (wctx->nb_item[wctx->level]) + if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES)) printf("%s", json->item_sep); if (!json->compact) JSON_INDENT(); @@ -1665,24 +1672,6 @@ return 0; } -static const char *xml_escape_str(AVBPrint *dst, const char *src, void *log_ctx) -{ - const char *p; - - for (p = src; *p; p++) { - switch (*p) { - case '&' : av_bprintf(dst, "%s", "&"); break; - case '<' : av_bprintf(dst, "%s", "<"); break; - case '>' : av_bprintf(dst, "%s", ">"); break; - case '"' : av_bprintf(dst, "%s", """); break; - case '\'': av_bprintf(dst, "%s", "'"); break; - default: av_bprint_chars(dst, *p, 1); - } - } - - return dst->str; -} - #define XML_INDENT() printf("%*c", xml->indent_level * 4, ' ') static void xml_print_section_header(WriterContext *wctx) @@ -1754,14 +1743,22 @@ if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) { XML_INDENT(); + av_bprint_escape(&buf, key, NULL, + AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES); printf("<%s key=\"%s\"", - section->element_name, xml_escape_str(&buf, key, wctx)); + section->element_name, buf.str); av_bprint_clear(&buf); - printf(" value=\"%s\"/>\n", xml_escape_str(&buf, value, wctx)); + + av_bprint_escape(&buf, value, NULL, + AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES); + printf(" value=\"%s\"/>\n", buf.str); } else { if (wctx->nb_item[wctx->level]) printf(" "); - printf("%s=\"%s\"", key, xml_escape_str(&buf, value, wctx)); + + av_bprint_escape(&buf, value, NULL, + AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES); + printf("%s=\"%s\"", key, buf.str); } av_bprint_finalize(&buf, NULL); @@ -1854,6 +1851,105 @@ return ret; } +static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *metadata) +{ + if (!metadata) + return; + print_int("application version", metadata->application_version); + print_int("num_windows", metadata->num_windows); + for (int n = 1; n < metadata->num_windows; n++) { + const AVHDRPlusColorTransformParams *params = &metadata->params[n]; + print_q("window_upper_left_corner_x", + params->window_upper_left_corner_x,'/'); + print_q("window_upper_left_corner_y", + params->window_upper_left_corner_y,'/'); + print_q("window_lower_right_corner_x", + params->window_lower_right_corner_x,'/'); + print_q("window_lower_right_corner_y", + params->window_lower_right_corner_y,'/'); + print_q("window_upper_left_corner_x", + params->window_upper_left_corner_x,'/'); + print_q("window_upper_left_corner_y", + params->window_upper_left_corner_y,'/'); + print_int("center_of_ellipse_x", + params->center_of_ellipse_x ) ; + print_int("center_of_ellipse_y", + params->center_of_ellipse_y ); + print_int("rotation_angle", + params->rotation_angle); + print_int("semimajor_axis_internal_ellipse", + params->semimajor_axis_internal_ellipse); + print_int("semimajor_axis_external_ellipse", + params->semimajor_axis_external_ellipse); + print_int("semiminor_axis_external_ellipse", + params->semiminor_axis_external_ellipse); + print_int("overlap_process_option", + params->overlap_process_option); + } + print_q("targeted_system_display_maximum_luminance", + metadata->targeted_system_display_maximum_luminance,'/'); + if (metadata->targeted_system_display_actual_peak_luminance_flag) { + print_int("num_rows_targeted_system_display_actual_peak_luminance", + metadata->num_rows_targeted_system_display_actual_peak_luminance); + print_int("num_cols_targeted_system_display_actual_peak_luminance", + metadata->num_cols_targeted_system_display_actual_peak_luminance); + for (int i = 0; i < metadata->num_rows_targeted_system_display_actual_peak_luminance; i++) { + for (int j = 0; j < metadata->num_cols_targeted_system_display_actual_peak_luminance; j++) { + print_q("targeted_system_display_actual_peak_luminance", + metadata->targeted_system_display_actual_peak_luminance[i][j],'/'); + } + } + } + for (int n = 0; n < metadata->num_windows; n++) { + const AVHDRPlusColorTransformParams *params = &metadata->params[n]; + for (int i = 0; i < 3; i++) { + print_q("maxscl",params->maxscl[i],'/'); + } + print_q("average_maxrgb", + params->average_maxrgb,'/'); + print_int("num_distribution_maxrgb_percentiles", + params->num_distribution_maxrgb_percentiles); + for (int i = 0; i < params->num_distribution_maxrgb_percentiles; i++) { + print_int("distribution_maxrgb_percentage", + params->distribution_maxrgb[i].percentage); + print_q("distribution_maxrgb_percentile", + params->distribution_maxrgb[i].percentile,'/'); + } + print_q("fraction_bright_pixels", + params->fraction_bright_pixels,'/'); + } + if (metadata->mastering_display_actual_peak_luminance_flag) { + print_int("num_rows_mastering_display_actual_peak_luminance", + metadata->num_rows_mastering_display_actual_peak_luminance); + print_int("num_cols_mastering_display_actual_peak_luminance", + metadata->num_cols_mastering_display_actual_peak_luminance); + for (int i = 0; i < metadata->num_rows_mastering_display_actual_peak_luminance; i++) { + for (int j = 0; j < metadata->num_cols_mastering_display_actual_peak_luminance; j++) { + print_q("mastering_display_actual_peak_luminance", + metadata->mastering_display_actual_peak_luminance[i][j],'/'); + } + } + } + + for (int n = 0; n < metadata->num_windows; n++) { + const AVHDRPlusColorTransformParams *params = &metadata->params[n]; + if (params->tone_mapping_flag) { + print_q("knee_point_x", params->knee_point_x,'/'); + print_q("knee_point_y", params->knee_point_y,'/'); + print_int("num_bezier_curve_anchors", + params->num_bezier_curve_anchors ); + for (int i = 0; i < params->num_bezier_curve_anchors; i++) { + print_q("bezier_curve_anchors", + params->bezier_curve_anchors[i],'/'); + } + } + if (params->color_saturation_mapping_flag) { + print_q("color_saturation_weight", + params->color_saturation_weight,'/'); + } + } +} + static void print_pkt_side_data(WriterContext *w, AVCodecParameters *par, const AVPacketSideData *side_data, @@ -1923,6 +2019,16 @@ AVContentLightMetadata *metadata = (AVContentLightMetadata *)sd->data; print_int("max_content", metadata->MaxCLL); print_int("max_average", metadata->MaxFALL); + } else if (sd->type == AV_PKT_DATA_DOVI_CONF) { + AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *)sd->data; + print_int("dv_version_major", dovi->dv_version_major); + print_int("dv_version_minor", dovi->dv_version_minor); + print_int("dv_profile", dovi->dv_profile); + print_int("dv_level", dovi->dv_level); + print_int("rpu_present_flag", dovi->rpu_present_flag); + print_int("el_present_flag", dovi->el_present_flag); + print_int("bl_present_flag", dovi->bl_present_flag); + print_int("dv_bl_signal_compatibility_id", dovi->dv_bl_signal_compatibility_id); } writer_print_section_footer(w); } @@ -2052,8 +2158,6 @@ print_time("dts_time", pkt->dts, &st->time_base); print_duration_ts("duration", pkt->duration); print_duration_time("duration_time", pkt->duration, &st->time_base); - print_duration_ts("convergence_duration", pkt->convergence_duration); - print_duration_time("convergence_duration_time", pkt->convergence_duration, &st->time_base); print_val("size", pkt->size, unit_byte_str); if (pkt->pos != -1) print_fmt ("pos", "%"PRId64, pkt->pos); else print_str_opt("pos", "N/A"); @@ -2209,7 +2313,7 @@ writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST); for (int j = 1; j <= m ; j++) { char tcbuf[AV_TIMECODE_STR_SIZE]; - av_timecode_make_smpte_tc_string(tcbuf, tc[j], 0); + av_timecode_make_smpte_tc_string2(tcbuf, stream->avg_frame_rate, tc[j], 0, 0); writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_TIMECODE); print_str("value", tcbuf); writer_print_section_footer(w); @@ -2234,6 +2338,9 @@ print_q("min_luminance", metadata->min_luminance, '/'); print_q("max_luminance", metadata->max_luminance, '/'); } + } else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_PLUS) { + AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data; + print_dynamic_hdr10_plus(w, metadata); } else if (sd->type == AV_FRAME_DATA_CONTENT_LIGHT_LEVEL) { AVContentLightMetadata *metadata = (AVContentLightMetadata *)sd->data; print_int("max_content", metadata->MaxCLL); @@ -2346,14 +2453,12 @@ const ReadInterval *interval, int64_t *cur_ts) { AVFormatContext *fmt_ctx = ifile->fmt_ctx; - AVPacket pkt; + AVPacket *pkt = NULL; AVFrame *frame = NULL; int ret = 0, i = 0, frame_count = 0; int64_t start = -INT64_MAX, end = interval->end; int has_start = 0, has_end = interval->has_end && !interval->end_is_offset; - av_init_packet(&pkt); - av_log(NULL, AV_LOG_VERBOSE, "Processing read interval "); log_read_interval(interval, NULL, AV_LOG_VERBOSE); @@ -2386,18 +2491,23 @@ ret = AVERROR(ENOMEM); goto end; } - while (!av_read_frame(fmt_ctx, &pkt)) { + pkt = av_packet_alloc(); + if (!pkt) { + ret = AVERROR(ENOMEM); + goto end; + } + while (!av_read_frame(fmt_ctx, pkt)) { if (fmt_ctx->nb_streams > nb_streams) { REALLOCZ_ARRAY_STREAM(nb_streams_frames, nb_streams, fmt_ctx->nb_streams); REALLOCZ_ARRAY_STREAM(nb_streams_packets, nb_streams, fmt_ctx->nb_streams); REALLOCZ_ARRAY_STREAM(selected_streams, nb_streams, fmt_ctx->nb_streams); nb_streams = fmt_ctx->nb_streams; } - if (selected_streams[pkt.stream_index]) { - AVRational tb = ifile->streams[pkt.stream_index].st->time_base; + if (selected_streams[pkt->stream_index]) { + AVRational tb = ifile->streams[pkt->stream_index].st->time_base; - if (pkt.pts != AV_NOPTS_VALUE) - *cur_ts = av_rescale_q(pkt.pts, tb, AV_TIME_BASE_Q); + if (pkt->pts != AV_NOPTS_VALUE) + *cur_ts = av_rescale_q(pkt->pts, tb, AV_TIME_BASE_Q); if (!has_start && *cur_ts != AV_NOPTS_VALUE) { start = *cur_ts; @@ -2419,26 +2529,27 @@ frame_count++; if (do_read_packets) { if (do_show_packets) - show_packet(w, ifile, &pkt, i++); - nb_streams_packets[pkt.stream_index]++; + show_packet(w, ifile, pkt, i++); + nb_streams_packets[pkt->stream_index]++; } if (do_read_frames) { int packet_new = 1; - while (process_frame(w, ifile, frame, &pkt, &packet_new) > 0); + while (process_frame(w, ifile, frame, pkt, &packet_new) > 0); } } - av_packet_unref(&pkt); + av_packet_unref(pkt); } - av_packet_unref(&pkt); + av_packet_unref(pkt); //Flush remaining frames that are cached in the decoder for (i = 0; i < fmt_ctx->nb_streams; i++) { - pkt.stream_index = i; + pkt->stream_index = i; if (do_read_frames) - while (process_frame(w, ifile, frame, &pkt, &(int){1}) > 0); + while (process_frame(w, ifile, frame, pkt, &(int){1}) > 0); } end: av_frame_free(&frame); + av_packet_free(&pkt); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Could not read packets in interval "); log_read_interval(interval, NULL, AV_LOG_ERROR); @@ -2514,10 +2625,6 @@ s = av_get_media_type_string(par->codec_type); if (s) print_str ("codec_type", s); else print_str_opt("codec_type", "unknown"); -#if FF_API_LAVF_AVCTX - if (dec_ctx) - print_q("codec_time_base", dec_ctx->time_base, '/'); -#endif /* print AVI/FourCC tag */ print_str("codec_tag_string", av_fourcc2str(par->codec_tag)); @@ -2527,12 +2634,11 @@ case AVMEDIA_TYPE_VIDEO: print_int("width", par->width); print_int("height", par->height); -#if FF_API_LAVF_AVCTX if (dec_ctx) { print_int("coded_width", dec_ctx->coded_width); print_int("coded_height", dec_ctx->coded_height); + print_int("closed_captions", !!(dec_ctx->properties & FF_CODEC_PROPERTY_CLOSED_CAPTIONS)); } -#endif print_int("has_b_frames", par->video_delay); sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL); if (sar.num) { @@ -2570,15 +2676,6 @@ else print_str_opt("field_order", "unknown"); -#if FF_API_PRIVATE_OPT - if (dec_ctx && dec_ctx->timecode_frame_start >= 0) { - char tcbuf[AV_TIMECODE_STR_SIZE]; - av_timecode_make_mpeg_tc_string(tcbuf, dec_ctx->timecode_frame_start); - print_str("timecode", tcbuf); - } else { - print_str_opt("timecode", "N/A"); - } -#endif if (dec_ctx) print_int("refs", dec_ctx->refs); break; @@ -2636,10 +2733,10 @@ print_time("duration", stream->duration, &stream->time_base); if (par->bit_rate > 0) print_val ("bit_rate", par->bit_rate, unit_bit_per_second_str); else print_str_opt("bit_rate", "N/A"); -#if FF_API_LAVF_AVCTX - if (stream->codec->rc_max_rate > 0) print_val ("max_bit_rate", stream->codec->rc_max_rate, unit_bit_per_second_str); - else print_str_opt("max_bit_rate", "N/A"); -#endif + if (dec_ctx && dec_ctx->rc_max_rate > 0) + print_val ("max_bit_rate", dec_ctx->rc_max_rate, unit_bit_per_second_str); + else + print_str_opt("max_bit_rate", "N/A"); if (dec_ctx && dec_ctx->bits_per_raw_sample > 0) print_fmt("bits_per_raw_sample", "%d", dec_ctx->bits_per_raw_sample); else print_str_opt("bits_per_raw_sample", "N/A"); if (stream->nb_frames) print_fmt ("nb_frames", "%"PRId64, stream->nb_frames); @@ -2832,11 +2929,12 @@ writer_print_section_footer(w); } -static int open_input_file(InputFile *ifile, const char *filename) +static int open_input_file(InputFile *ifile, const char *filename, + const char *print_filename) { int err, i; AVFormatContext *fmt_ctx = NULL; - AVDictionaryEntry *t; + AVDictionaryEntry *t = NULL; int scan_all_pmts_set = 0; fmt_ctx = avformat_alloc_context(); @@ -2854,13 +2952,15 @@ print_error(filename, err); return err; } + if (print_filename) { + av_freep(&fmt_ctx->url); + fmt_ctx->url = av_strdup(print_filename); + } ifile->fmt_ctx = fmt_ctx; if (scan_all_pmts_set) av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE); - if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) { - av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key); - return AVERROR_OPTION_NOT_FOUND; - } + while ((t = av_dict_get(format_opts, "", t, AV_DICT_IGNORE_SUFFIX))) + av_log(NULL, AV_LOG_WARNING, "Option %s skipped - not known to demuxer.\n", t->key); if (find_stream_info) { AVDictionary **opts = setup_find_stream_info_opts(fmt_ctx, codec_opts); @@ -2890,7 +2990,7 @@ for (i = 0; i < fmt_ctx->nb_streams; i++) { InputStream *ist = &ifile->streams[i]; AVStream *stream = fmt_ctx->streams[i]; - AVCodec *codec; + const AVCodec *codec; ist->st = stream; @@ -2928,11 +3028,6 @@ } ist->dec_ctx->pkt_timebase = stream->time_base; - ist->dec_ctx->framerate = stream->avg_frame_rate; -#if FF_API_LAVF_AVCTX - ist->dec_ctx->coded_width = stream->codec->coded_width; - ist->dec_ctx->coded_height = stream->codec->coded_height; -#endif if (avcodec_open2(ist->dec_ctx, codec, &opts) < 0) { av_log(NULL, AV_LOG_WARNING, "Could not open codec for input stream %d\n", @@ -2967,7 +3062,8 @@ avformat_close_input(&ifile->fmt_ctx); } -static int probe_file(WriterContext *wctx, const char *filename) +static int probe_file(WriterContext *wctx, const char *filename, + const char *print_filename) { InputFile ifile = { 0 }; int ret, i; @@ -2976,7 +3072,7 @@ do_read_frames = do_show_frames || do_count_frames; do_read_packets = do_show_packets || do_count_packets; - ret = open_input_file(&ifile, filename); + ret = open_input_file(&ifile, filename, print_filename); if (ret < 0) goto end; @@ -3132,9 +3228,6 @@ PRINT_PIX_FMT_FLAG(HWACCEL, "hwaccel"); PRINT_PIX_FMT_FLAG(PLANAR, "planar"); PRINT_PIX_FMT_FLAG(RGB, "rgb"); -#if FF_API_PSEUDOPAL - PRINT_PIX_FMT_FLAG(PSEUDOPAL, "pseudopal"); -#endif PRINT_PIX_FMT_FLAG(ALPHA, "alpha"); writer_print_section_footer(w); } @@ -3282,6 +3375,12 @@ return 0; } +static int opt_print_filename(void *optctx, const char *opt, const char *arg) +{ + print_input_filename = arg; + return 0; +} + void show_help_default(const char *opt, const char *arg) { av_log_set_callback(log_callback_help); @@ -3471,7 +3570,7 @@ return 0; } -static int opt_show_versions(const char *opt, const char *arg) +static int opt_show_versions(void *optctx, const char *opt, const char *arg) { mark_section_show_entries(SECTION_ID_PROGRAM_VERSION, 1, NULL); mark_section_show_entries(SECTION_ID_LIBRARY_VERSION, 1, NULL); @@ -3479,7 +3578,7 @@ } #define DEFINE_OPT_SHOW_SECTION(section, target_section_id) \ - static int opt_show_##section(const char *opt, const char *arg) \ + static int opt_show_##section(void *optctx, const char *opt, const char *arg) \ { \ mark_section_show_entries(SECTION_ID_##target_section_id, 1, NULL); \ return 0; \ @@ -3507,39 +3606,40 @@ "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" }, { "pretty", 0, {.func_arg = opt_pretty}, "prettify the format of displayed values, make it more human readable" }, - { "print_format", OPT_STRING | HAS_ARG, {(void*)&print_format}, + { "print_format", OPT_STRING | HAS_ARG, { &print_format }, "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", "format" }, - { "of", OPT_STRING | HAS_ARG, {(void*)&print_format}, "alias for -print_format", "format" }, - { "select_streams", OPT_STRING | HAS_ARG, {(void*)&stream_specifier}, "select the specified streams", "stream_specifier" }, + { "of", OPT_STRING | HAS_ARG, { &print_format }, "alias for -print_format", "format" }, + { "select_streams", OPT_STRING | HAS_ARG, { &stream_specifier }, "select the specified streams", "stream_specifier" }, { "sections", OPT_EXIT, {.func_arg = opt_sections}, "print sections structure and section information, and exit" }, - { "show_data", OPT_BOOL, {(void*)&do_show_data}, "show packets data" }, - { "show_data_hash", OPT_STRING | HAS_ARG, {(void*)&show_data_hash}, "show packets data hash" }, - { "show_error", 0, {(void*)&opt_show_error}, "show probing error" }, - { "show_format", 0, {(void*)&opt_show_format}, "show format/container info" }, - { "show_frames", 0, {(void*)&opt_show_frames}, "show frames info" }, + { "show_data", OPT_BOOL, { &do_show_data }, "show packets data" }, + { "show_data_hash", OPT_STRING | HAS_ARG, { &show_data_hash }, "show packets data hash" }, + { "show_error", 0, { .func_arg = &opt_show_error }, "show probing error" }, + { "show_format", 0, { .func_arg = &opt_show_format }, "show format/container info" }, + { "show_frames", 0, { .func_arg = &opt_show_frames }, "show frames info" }, { "show_format_entry", HAS_ARG, {.func_arg = opt_show_format_entry}, "show a particular entry from the format/container info", "entry" }, { "show_entries", HAS_ARG, {.func_arg = opt_show_entries}, "show a set of specified entries", "entry_list" }, #if HAVE_THREADS - { "show_log", OPT_INT|HAS_ARG, {(void*)&do_show_log}, "show log" }, + { "show_log", OPT_INT|HAS_ARG, { &do_show_log }, "show log" }, #endif - { "show_packets", 0, {(void*)&opt_show_packets}, "show packets info" }, - { "show_programs", 0, {(void*)&opt_show_programs}, "show programs info" }, - { "show_streams", 0, {(void*)&opt_show_streams}, "show streams info" }, - { "show_chapters", 0, {(void*)&opt_show_chapters}, "show chapters info" }, - { "count_frames", OPT_BOOL, {(void*)&do_count_frames}, "count the number of frames per stream" }, - { "count_packets", OPT_BOOL, {(void*)&do_count_packets}, "count the number of packets per stream" }, - { "show_program_version", 0, {(void*)&opt_show_program_version}, "show ffprobe version" }, - { "show_library_versions", 0, {(void*)&opt_show_library_versions}, "show library versions" }, - { "show_versions", 0, {(void*)&opt_show_versions}, "show program and library versions" }, - { "show_pixel_formats", 0, {(void*)&opt_show_pixel_formats}, "show pixel format descriptions" }, - { "show_private_data", OPT_BOOL, {(void*)&show_private_data}, "show private data" }, - { "private", OPT_BOOL, {(void*)&show_private_data}, "same as show_private_data" }, + { "show_packets", 0, { .func_arg = &opt_show_packets }, "show packets info" }, + { "show_programs", 0, { .func_arg = &opt_show_programs }, "show programs info" }, + { "show_streams", 0, { .func_arg = &opt_show_streams }, "show streams info" }, + { "show_chapters", 0, { .func_arg = &opt_show_chapters }, "show chapters info" }, + { "count_frames", OPT_BOOL, { &do_count_frames }, "count the number of frames per stream" }, + { "count_packets", OPT_BOOL, { &do_count_packets }, "count the number of packets per stream" }, + { "show_program_version", 0, { .func_arg = &opt_show_program_version }, "show ffprobe version" }, + { "show_library_versions", 0, { .func_arg = &opt_show_library_versions }, "show library versions" }, + { "show_versions", 0, { .func_arg = &opt_show_versions }, "show program and library versions" }, + { "show_pixel_formats", 0, { .func_arg = &opt_show_pixel_formats }, "show pixel format descriptions" }, + { "show_private_data", OPT_BOOL, { &show_private_data }, "show private data" }, + { "private", OPT_BOOL, { &show_private_data }, "same as show_private_data" }, { "bitexact", OPT_BOOL, {&do_bitexact}, "force bitexact output" }, { "read_intervals", HAS_ARG, {.func_arg = opt_read_intervals}, "set read intervals", "read_intervals" }, { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {.func_arg = opt_default}, "generic catch all option", "" }, { "i", HAS_ARG, {.func_arg = opt_input_file_i}, "read specified file", "input_file"}, + { "print_filename", HAS_ARG, {.func_arg = opt_print_filename}, "override the printed input filename", "print_file"}, { "find_stream_info", OPT_BOOL | OPT_INPUT | OPT_EXPERT, { &find_stream_info }, "read and decode the streams to fill missing information with heuristics" }, { NULL, }, @@ -3688,7 +3788,7 @@ av_log(NULL, AV_LOG_ERROR, "Use -h to get full help or, even better, run 'man %s'.\n", program_name); ret = AVERROR(EINVAL); } else if (input_filename) { - ret = probe_file(wctx, input_filename); + ret = probe_file(wctx, input_filename, print_input_filename); if (ret < 0 && do_show_error) show_error(wctx, ret); } diff -Nru ffmpeg-4.2.2/fftools/Makefile ffmpeg-4.4/fftools/Makefile --- ffmpeg-4.2.2/fftools/Makefile 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/fftools/Makefile 2020-07-11 10:39:30.000000000 +0000 @@ -10,7 +10,6 @@ ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF)) OBJS-ffmpeg += fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o -OBJS-ffmpeg-$(CONFIG_CUVID) += fftools/ffmpeg_cuvid.o OBJS-ffmpeg-$(CONFIG_LIBMFX) += fftools/ffmpeg_qsv.o ifndef CONFIG_VIDEOTOOLBOX OBJS-ffmpeg-$(CONFIG_VDA) += fftools/ffmpeg_videotoolbox.o diff -Nru ffmpeg-4.2.2/.gitattributes ffmpeg-4.4/.gitattributes --- ffmpeg-4.2.2/.gitattributes 2019-07-08 17:45:24.000000000 +0000 +++ ffmpeg-4.4/.gitattributes 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -*.pnm -diff -text -tests/ref/fate/sub-scc eol=crlf diff -Nru ffmpeg-4.2.2/libavcodec/4xm.c ffmpeg-4.4/libavcodec/4xm.c --- ffmpeg-4.2.2/libavcodec/4xm.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/4xm.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/frame.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "blockdsp.h" #include "bswapdsp.h" @@ -498,8 +499,8 @@ { int code, i, j, level, val; - if (get_bits_left(&f->gb) < 2){ - av_log(f->avctx, AV_LOG_ERROR, "%d bits left before decode_i_block()\n", get_bits_left(&f->gb)); + if (get_bits_left(&f->pre_gb) < 2) { + av_log(f->avctx, AV_LOG_ERROR, "%d bits left before decode_i_block()\n", get_bits_left(&f->pre_gb)); return AVERROR_INVALIDDATA; } diff -Nru ffmpeg-4.2.2/libavcodec/8bps.c ffmpeg-4.4/libavcodec/8bps.c --- ffmpeg-4.2.2/libavcodec/8bps.c 2018-11-01 18:34:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/8bps.c 2021-04-08 21:28:39.000000000 +0000 @@ -122,7 +122,7 @@ } if (avctx->bits_per_coded_sample <= 8) { - int size; + buffer_size_t size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size); diff -Nru ffmpeg-4.2.2/libavcodec/8svx.c ffmpeg-4.4/libavcodec/8svx.c --- ffmpeg-4.2.2/libavcodec/8svx.c 2017-12-31 22:35:45.000000000 +0000 +++ ffmpeg-4.4/libavcodec/8svx.c 2020-07-11 10:39:30.000000000 +0000 @@ -164,8 +164,7 @@ case AV_CODEC_ID_8SVX_FIB: esc->table = fibonacci; break; case AV_CODEC_ID_8SVX_EXP: esc->table = exponential; break; default: - av_log(avctx, AV_LOG_ERROR, "Invalid codec id %d.\n", avctx->codec->id); - return AVERROR_INVALIDDATA; + av_assert1(0); } avctx->sample_fmt = AV_SAMPLE_FMT_U8P; diff -Nru ffmpeg-4.2.2/libavcodec/a64multienc.c ffmpeg-4.4/libavcodec/a64multienc.c --- ffmpeg-4.2.2/libavcodec/a64multienc.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/a64multienc.c 2021-04-08 21:28:39.000000000 +0000 @@ -107,13 +107,16 @@ uint8_t pix; int lowdiff, highdiff; int *best_cb = c->mc_best_cb; - static uint8_t index1[256]; - static uint8_t index2[256]; - static uint8_t dither[256]; + uint8_t index1[256]; + uint8_t index2[256]; + uint8_t dither[256]; int i; int distance; - /* generate lookup-tables for dither and index before looping */ + /* Generate lookup-tables for dither and index before looping. + * This code relies on c->mc_luma_vals[c->mc_pal_size - 1] being + * the maximum of all the mc_luma_vals values and on the minimum + * being zero; this ensures that dither is properly initialized. */ i = 0; for (a=0; a < 256; a++) { if(i < c->mc_pal_size -1 && a == c->mc_luma_vals[i + 1]) { @@ -407,6 +410,7 @@ .close = a64multi_close_encoder, .pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_A64MULTI5_ENCODER @@ -421,5 +425,6 @@ .close = a64multi_close_encoder, .pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, .capabilities = AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/aac_ac3_parser.c ffmpeg-4.4/libavcodec/aac_ac3_parser.c --- ffmpeg-4.2.2/libavcodec/aac_ac3_parser.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aac_ac3_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -89,7 +89,7 @@ the frame). */ if (avctx->codec_id != AV_CODEC_ID_AAC) { avctx->sample_rate = s->sample_rate; - if (avctx->codec_id != AV_CODEC_ID_EAC3) { + if (!CONFIG_EAC3_DECODER || avctx->codec_id != AV_CODEC_ID_EAC3) { avctx->channels = s->channels; avctx->channel_layout = s->channel_layout; } @@ -97,8 +97,12 @@ avctx->audio_service_type = s->service_type; } - if (avctx->codec_id != AV_CODEC_ID_EAC3) - avctx->bit_rate = s->bit_rate; + /* Calculate the average bit rate */ + s->frame_number++; + if (!CONFIG_EAC3_DECODER || avctx->codec_id != AV_CODEC_ID_EAC3) { + avctx->bit_rate += + (s->bit_rate - avctx->bit_rate) / s->frame_number; + } } return i; diff -Nru ffmpeg-4.2.2/libavcodec/aac_ac3_parser.h ffmpeg-4.4/libavcodec/aac_ac3_parser.h --- ffmpeg-4.2.2/libavcodec/aac_ac3_parser.h 2016-03-29 02:25:09.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aac_ac3_parser.h 2021-04-08 21:28:39.000000000 +0000 @@ -55,6 +55,7 @@ uint64_t state; int need_next_header; + int frame_number; enum AVCodecID codec_id; } AACAC3ParseContext; diff -Nru ffmpeg-4.2.2/libavcodec/aac_adtstoasc_bsf.c ffmpeg-4.4/libavcodec/aac_adtstoasc_bsf.c --- ffmpeg-4.2.2/libavcodec/aac_adtstoasc_bsf.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aac_adtstoasc_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -21,8 +21,8 @@ #include "adts_header.h" #include "adts_parser.h" -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "put_bits.h" #include "get_bits.h" #include "mpeg4audio.h" @@ -134,8 +134,8 @@ /* Validate the extradata if the stream is already MPEG-4 AudioSpecificConfig */ if (ctx->par_in->extradata) { MPEG4AudioConfig mp4ac; - int ret = avpriv_mpeg4audio_get_config(&mp4ac, ctx->par_in->extradata, - ctx->par_in->extradata_size * 8, 1); + int ret = avpriv_mpeg4audio_get_config2(&mp4ac, ctx->par_in->extradata, + ctx->par_in->extradata_size, 1, ctx); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Error parsing AudioSpecificConfig extradata!\n"); return ret; diff -Nru ffmpeg-4.2.2/libavcodec/aacdec.c ffmpeg-4.4/libavcodec/aacdec.c --- ffmpeg-4.2.2/libavcodec/aacdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -69,6 +69,11 @@ # include "mips/aacdec_mips.h" #endif +DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME(sine_120))[120]; +DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME(sine_960))[960]; +DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME(aac_kbd_long_960))[960]; +DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME(aac_kbd_short_120))[120]; + static av_always_inline void reset_predict_state(PredictorState *ps) { ps->r0 = 0.0f; diff -Nru ffmpeg-4.2.2/libavcodec/aacdec_fixed.c ffmpeg-4.4/libavcodec/aacdec_fixed.c --- ffmpeg-4.2.2/libavcodec/aacdec_fixed.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacdec_fixed.c 2021-04-08 21:28:39.000000000 +0000 @@ -70,7 +70,7 @@ #include "fft.h" #include "lpc.h" #include "kbdwin.h" -#include "sinewin.h" +#include "sinewin_fixed_tablegen.h" #include "aac.h" #include "aactab.h" @@ -86,6 +86,9 @@ #include #include +DECLARE_ALIGNED(32, static int, AAC_RENAME2(aac_kbd_long_1024))[1024]; +DECLARE_ALIGNED(32, static int, AAC_RENAME2(aac_kbd_short_128))[128]; + static av_always_inline void reset_predict_state(PredictorState *ps) { ps->r0.mant = 0; @@ -155,9 +158,9 @@ for (i=0; i -static const int8_t tags_per_config[16] = { 0, 1, 1, 2, 3, 3, 4, 5, 0, 0, 0, 4, 5, 0, 5, 0 }; +static const int8_t tags_per_config[16] = { 0, 1, 1, 2, 3, 3, 4, 5, 0, 0, 0, 4, 5, 16, 5, 0 }; -static const uint8_t aac_channel_layout_map[16][5][3] = { +static const uint8_t aac_channel_layout_map[16][16][3] = { { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, }, { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, }, { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, }, @@ -50,6 +50,24 @@ { { 0, } }, { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, }, { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_SIDE }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, }, + { + { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, // SCE1 = FC, + { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, // CPE1 = FLc and FRc, + { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, // CPE2 = FL and FR, + { TYPE_CPE, 2, AAC_CHANNEL_SIDE }, // CPE3 = SiL and SiR, + { TYPE_CPE, 3, AAC_CHANNEL_BACK }, // CPE4 = BL and BR, + { TYPE_SCE, 1, AAC_CHANNEL_BACK }, // SCE2 = BC, + { TYPE_LFE, 0, AAC_CHANNEL_LFE }, // LFE1 = LFE1, + { TYPE_LFE, 1, AAC_CHANNEL_LFE }, // LFE2 = LFE2, + { TYPE_SCE, 2, AAC_CHANNEL_FRONT }, // SCE3 = TpFC, + { TYPE_CPE, 4, AAC_CHANNEL_FRONT }, // CPE5 = TpFL and TpFR, + { TYPE_CPE, 5, AAC_CHANNEL_SIDE }, // CPE6 = TpSiL and TpSiR, + { TYPE_SCE, 3, AAC_CHANNEL_FRONT }, // SCE4 = TpC, + { TYPE_CPE, 6, AAC_CHANNEL_BACK }, // CPE7 = TpBL and TpBR, + { TYPE_SCE, 4, AAC_CHANNEL_BACK }, // SCE5 = TpBC, + { TYPE_SCE, 5, AAC_CHANNEL_FRONT }, // SCE6 = BtFC, + { TYPE_CPE, 7, AAC_CHANNEL_FRONT }, // CPE8 = BtFL and BtFR + }, { { 0, } }, /* TODO: Add 7+1 TOP configuration */ }; @@ -67,6 +85,7 @@ 0, AV_CH_LAYOUT_6POINT1, AV_CH_LAYOUT_7POINT1, + AV_CH_LAYOUT_22POINT2, 0, /* AV_CH_LAYOUT_7POINT1_TOP, */ }; diff -Nru ffmpeg-4.2.2/libavcodec/aacdec_template.c ffmpeg-4.4/libavcodec/aacdec_template.c --- ffmpeg-4.2.2/libavcodec/aacdec_template.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacdec_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -198,7 +198,7 @@ static int assign_pair(struct elem_to_channel e2c_vec[MAX_ELEM_ID], uint8_t (*layout_map)[3], int offset, uint64_t left, - uint64_t right, int pos) + uint64_t right, int pos, uint64_t *layout) { if (layout_map[offset][0] == TYPE_CPE) { e2c_vec[offset] = (struct elem_to_channel) { @@ -207,6 +207,9 @@ .elem_id = layout_map[offset][1], .aac_position = pos }; + if (e2c_vec[offset].av_position != UINT64_MAX) + *layout |= e2c_vec[offset].av_position; + return 1; } else { e2c_vec[offset] = (struct elem_to_channel) { @@ -221,6 +224,12 @@ .elem_id = layout_map[offset + 1][1], .aac_position = pos }; + if (left != UINT64_MAX) + *layout |= left; + + if (right != UINT64_MAX) + *layout |= right; + return 2; } } @@ -257,12 +266,13 @@ return num_pos_channels; } +#define PREFIX_FOR_22POINT2 (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_LOW_FREQUENCY_2) static uint64_t sniff_channel_order(uint8_t (*layout_map)[3], int tags) { int i, n, total_non_cc_elements; struct elem_to_channel e2c_vec[4 * MAX_ELEM_ID] = { { 0 } }; int num_front_channels, num_side_channels, num_back_channels; - uint64_t layout; + uint64_t layout = 0; if (FF_ARRAY_ELEMS(e2c_vec) < tags) return 0; @@ -294,6 +304,7 @@ .elem_id = layout_map[i][1], .aac_position = AAC_CHANNEL_FRONT }; + layout |= e2c_vec[i].av_position; i++; num_front_channels--; } @@ -301,21 +312,21 @@ i += assign_pair(e2c_vec, layout_map, i, AV_CH_FRONT_LEFT_OF_CENTER, AV_CH_FRONT_RIGHT_OF_CENTER, - AAC_CHANNEL_FRONT); + AAC_CHANNEL_FRONT, &layout); num_front_channels -= 2; } if (num_front_channels >= 2) { i += assign_pair(e2c_vec, layout_map, i, AV_CH_FRONT_LEFT, AV_CH_FRONT_RIGHT, - AAC_CHANNEL_FRONT); + AAC_CHANNEL_FRONT, &layout); num_front_channels -= 2; } while (num_front_channels >= 2) { i += assign_pair(e2c_vec, layout_map, i, UINT64_MAX, UINT64_MAX, - AAC_CHANNEL_FRONT); + AAC_CHANNEL_FRONT, &layout); num_front_channels -= 2; } @@ -323,14 +334,14 @@ i += assign_pair(e2c_vec, layout_map, i, AV_CH_SIDE_LEFT, AV_CH_SIDE_RIGHT, - AAC_CHANNEL_FRONT); + AAC_CHANNEL_FRONT, &layout); num_side_channels -= 2; } while (num_side_channels >= 2) { i += assign_pair(e2c_vec, layout_map, i, UINT64_MAX, UINT64_MAX, - AAC_CHANNEL_SIDE); + AAC_CHANNEL_SIDE, &layout); num_side_channels -= 2; } @@ -338,14 +349,14 @@ i += assign_pair(e2c_vec, layout_map, i, UINT64_MAX, UINT64_MAX, - AAC_CHANNEL_BACK); + AAC_CHANNEL_BACK, &layout); num_back_channels -= 2; } if (num_back_channels >= 2) { i += assign_pair(e2c_vec, layout_map, i, AV_CH_BACK_LEFT, AV_CH_BACK_RIGHT, - AAC_CHANNEL_BACK); + AAC_CHANNEL_BACK, &layout); num_back_channels -= 2; } if (num_back_channels) { @@ -355,6 +366,7 @@ .elem_id = layout_map[i][1], .aac_position = AAC_CHANNEL_BACK }; + layout |= e2c_vec[i].av_position; i++; num_back_channels--; } @@ -366,6 +378,17 @@ .elem_id = layout_map[i][1], .aac_position = AAC_CHANNEL_LFE }; + layout |= e2c_vec[i].av_position; + i++; + } + if (i < tags && layout_map[i][2] == AAC_CHANNEL_LFE) { + e2c_vec[i] = (struct elem_to_channel) { + .av_position = AV_CH_LOW_FREQUENCY_2, + .syn_ele = TYPE_LFE, + .elem_id = layout_map[i][1], + .aac_position = AAC_CHANNEL_LFE + }; + layout |= e2c_vec[i].av_position; i++; } while (i < tags && layout_map[i][2] == AAC_CHANNEL_LFE) { @@ -378,26 +401,95 @@ i++; } - // Must choose a stable sort + // The previous checks would end up at 8 at this point for 22.2 + if (layout == PREFIX_FOR_22POINT2 && tags == 16 && i == 8) { + const uint8_t (*reference_layout_map)[3] = aac_channel_layout_map[12]; + for (int j = 0; j < tags; j++) { + if (layout_map[j][0] != reference_layout_map[j][0] || + layout_map[j][2] != reference_layout_map[j][2]) + goto end_of_layout_definition; + } + + e2c_vec[i] = (struct elem_to_channel) { + .av_position = AV_CH_TOP_FRONT_CENTER, + .syn_ele = layout_map[i][0], + .elem_id = layout_map[i][1], + .aac_position = layout_map[i][2] + }; layout |= e2c_vec[i].av_position; i++; + i += assign_pair(e2c_vec, layout_map, i, + AV_CH_TOP_FRONT_LEFT, + AV_CH_TOP_FRONT_RIGHT, + AAC_CHANNEL_FRONT, + &layout); + i += assign_pair(e2c_vec, layout_map, i, + AV_CH_TOP_SIDE_LEFT, + AV_CH_TOP_SIDE_RIGHT, + AAC_CHANNEL_SIDE, + &layout); + e2c_vec[i] = (struct elem_to_channel) { + .av_position = AV_CH_TOP_CENTER, + .syn_ele = layout_map[i][0], + .elem_id = layout_map[i][1], + .aac_position = layout_map[i][2] + }; layout |= e2c_vec[i].av_position; i++; + i += assign_pair(e2c_vec, layout_map, i, + AV_CH_TOP_BACK_LEFT, + AV_CH_TOP_BACK_RIGHT, + AAC_CHANNEL_BACK, + &layout); + e2c_vec[i] = (struct elem_to_channel) { + .av_position = AV_CH_TOP_BACK_CENTER, + .syn_ele = layout_map[i][0], + .elem_id = layout_map[i][1], + .aac_position = layout_map[i][2] + }; layout |= e2c_vec[i].av_position; i++; + e2c_vec[i] = (struct elem_to_channel) { + .av_position = AV_CH_BOTTOM_FRONT_CENTER, + .syn_ele = layout_map[i][0], + .elem_id = layout_map[i][1], + .aac_position = layout_map[i][2] + }; layout |= e2c_vec[i].av_position; i++; + i += assign_pair(e2c_vec, layout_map, i, + AV_CH_BOTTOM_FRONT_LEFT, + AV_CH_BOTTOM_FRONT_RIGHT, + AAC_CHANNEL_FRONT, + &layout); + } + +end_of_layout_definition: + total_non_cc_elements = n = i; - do { - int next_n = 0; - for (i = 1; i < n; i++) - if (e2c_vec[i - 1].av_position > e2c_vec[i].av_position) { - FFSWAP(struct elem_to_channel, e2c_vec[i - 1], e2c_vec[i]); - next_n = i; - } - n = next_n; - } while (n > 0); - layout = 0; + if (layout == AV_CH_LAYOUT_22POINT2) { + // For 22.2 reorder the result as needed + FFSWAP(struct elem_to_channel, e2c_vec[2], e2c_vec[0]); // FL & FR first (final), FC third + FFSWAP(struct elem_to_channel, e2c_vec[2], e2c_vec[1]); // FC second (final), FLc & FRc third + FFSWAP(struct elem_to_channel, e2c_vec[6], e2c_vec[2]); // LFE1 third (final), FLc & FRc seventh + FFSWAP(struct elem_to_channel, e2c_vec[4], e2c_vec[3]); // BL & BR fourth (final), SiL & SiR fifth + FFSWAP(struct elem_to_channel, e2c_vec[6], e2c_vec[4]); // FLc & FRc fifth (final), SiL & SiR seventh + FFSWAP(struct elem_to_channel, e2c_vec[7], e2c_vec[6]); // LFE2 seventh (final), SiL & SiR eight (final) + FFSWAP(struct elem_to_channel, e2c_vec[9], e2c_vec[8]); // TpFL & TpFR ninth (final), TFC tenth (final) + FFSWAP(struct elem_to_channel, e2c_vec[11], e2c_vec[10]); // TC eleventh (final), TpSiL & TpSiR twelth + FFSWAP(struct elem_to_channel, e2c_vec[12], e2c_vec[11]); // TpBL & TpBR twelth (final), TpSiL & TpSiR thirteenth (final) + } else { + // For everything else, utilize the AV channel position define as a + // stable sort. + do { + int next_n = 0; + for (i = 1; i < n; i++) + if (e2c_vec[i - 1].av_position > e2c_vec[i].av_position) { + FFSWAP(struct elem_to_channel, e2c_vec[i - 1], e2c_vec[i]); + next_n = i; + } + n = next_n; + } while (n > 0); + + } + for (i = 0; i < total_non_cc_elements; i++) { layout_map[i][0] = e2c_vec[i].syn_ele; layout_map[i][1] = e2c_vec[i].elem_id; layout_map[i][2] = e2c_vec[i].aac_position; - if (e2c_vec[i].av_position != UINT64_MAX) { - layout |= e2c_vec[i].av_position; - } } return layout; @@ -520,13 +612,13 @@ * * @return Returns error status. 0 - OK, !0 - error */ -static int set_default_channel_config(AVCodecContext *avctx, +static int set_default_channel_config(AACContext *ac, AVCodecContext *avctx, uint8_t (*layout_map)[3], int *tags, int channel_config) { if (channel_config < 1 || (channel_config > 7 && channel_config < 11) || - channel_config > 12) { + channel_config > 13) { av_log(avctx, AV_LOG_ERROR, "invalid default channel configuration (%d)\n", channel_config); @@ -548,10 +640,13 @@ * 7.1 layout was intended. */ if (channel_config == 7 && avctx->strict_std_compliance < FF_COMPLIANCE_STRICT) { - av_log(avctx, AV_LOG_INFO, "Assuming an incorrectly encoded 7.1 channel layout" - " instead of a spec-compliant 7.1(wide) layout, use -strict %d to decode" - " according to the specification instead.\n", FF_COMPLIANCE_STRICT); layout_map[2][2] = AAC_CHANNEL_SIDE; + + if (!ac || !ac->warned_71_wide++) { + av_log(avctx, AV_LOG_INFO, "Assuming an incorrectly encoded 7.1 channel layout" + " instead of a spec-compliant 7.1(wide) layout, use -strict %d to decode" + " according to the specification instead.\n", FF_COMPLIANCE_STRICT); + } } return 0; @@ -573,7 +668,7 @@ av_log(ac->avctx, AV_LOG_DEBUG, "mono with CPE\n"); - if (set_default_channel_config(ac->avctx, layout_map, + if (set_default_channel_config(ac, ac->avctx, layout_map, &layout_map_tags, 2) < 0) return NULL; if (output_configure(ac, layout_map, layout_map_tags, @@ -592,7 +687,7 @@ av_log(ac->avctx, AV_LOG_DEBUG, "stereo with SCE\n"); - if (set_default_channel_config(ac->avctx, layout_map, + if (set_default_channel_config(ac, ac->avctx, layout_map, &layout_map_tags, 1) < 0) return NULL; if (output_configure(ac, layout_map, layout_map_tags, @@ -606,6 +701,13 @@ /* For indexed channel configurations map the channels solely based * on position. */ switch (ac->oc[1].m4ac.chan_config) { + case 13: + if (ac->tags_mapped > 3 && ((type == TYPE_CPE && elem_id < 8) || + (type == TYPE_SCE && elem_id < 6) || + (type == TYPE_LFE && elem_id < 2))) { + ac->tags_mapped++; + return ac->tag_che_map[type][elem_id] = ac->che[type][elem_id]; + } case 12: case 7: if (ac->tags_mapped == 3 && type == TYPE_CPE) { @@ -841,7 +943,7 @@ if (tags < 0) return tags; } else { - if ((ret = set_default_channel_config(avctx, layout_map, + if ((ret = set_default_channel_config(ac, avctx, layout_map, &tags, channel_config))) return ret; } @@ -937,7 +1039,7 @@ skip_bits_long(gb, 8 * len); } - if ((ret = set_default_channel_config(avctx, layout_map, + if ((ret = set_default_channel_config(ac, avctx, layout_map, &tags, channel_config))) return ret; @@ -975,7 +1077,7 @@ int i, ret; GetBitContext gbc = *gb; - if ((i = ff_mpeg4audio_get_config_gb(m4ac, &gbc, sync_extension)) < 0) + if ((i = ff_mpeg4audio_get_config_gb(m4ac, &gbc, sync_extension, avctx)) < 0) return AVERROR_INVALIDDATA; if (m4ac->sampling_index > 12) { @@ -1096,29 +1198,25 @@ reset_predict_state(&ps[i]); } -#define AAC_INIT_VLC_STATIC(num, size) \ - INIT_VLC_STATIC(&vlc_spectral[num], 8, ff_aac_spectral_sizes[num], \ - ff_aac_spectral_bits[num], sizeof(ff_aac_spectral_bits[num][0]), \ - sizeof(ff_aac_spectral_bits[num][0]), \ - ff_aac_spectral_codes[num], sizeof(ff_aac_spectral_codes[num][0]), \ - sizeof(ff_aac_spectral_codes[num][0]), \ - size); - static void aacdec_init(AACContext *ac); static av_cold void aac_static_table_init(void) { - AAC_INIT_VLC_STATIC( 0, 304); - AAC_INIT_VLC_STATIC( 1, 270); - AAC_INIT_VLC_STATIC( 2, 550); - AAC_INIT_VLC_STATIC( 3, 300); - AAC_INIT_VLC_STATIC( 4, 328); - AAC_INIT_VLC_STATIC( 5, 294); - AAC_INIT_VLC_STATIC( 6, 306); - AAC_INIT_VLC_STATIC( 7, 268); - AAC_INIT_VLC_STATIC( 8, 510); - AAC_INIT_VLC_STATIC( 9, 366); - AAC_INIT_VLC_STATIC(10, 462); + static VLC_TYPE vlc_buf[304 + 270 + 550 + 300 + 328 + + 294 + 306 + 268 + 510 + 366 + 462][2]; + for (unsigned i = 0, offset = 0; i < 11; i++) { + vlc_spectral[i].table = &vlc_buf[offset]; + vlc_spectral[i].table_allocated = FF_ARRAY_ELEMS(vlc_buf) - offset; + ff_init_vlc_sparse(&vlc_spectral[i], 8, ff_aac_spectral_sizes[i], + ff_aac_spectral_bits[i], sizeof(ff_aac_spectral_bits[i][0]), + sizeof(ff_aac_spectral_bits[i][0]), + ff_aac_spectral_codes[i], sizeof(ff_aac_spectral_codes[i][0]), + sizeof(ff_aac_spectral_codes[i][0]), + ff_aac_codebook_vector_idx[i], sizeof(ff_aac_codebook_vector_idx[i][0]), + sizeof(ff_aac_codebook_vector_idx[i][0]), + INIT_VLC_STATIC_OVERLONG); + offset += vlc_spectral[i].table_size; + } AAC_RENAME(ff_aac_sbr_init)(); @@ -1135,17 +1233,18 @@ 352); // window initialization - AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(ff_aac_kbd_long_1024), 4.0, 1024); - AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(ff_aac_kbd_short_128), 6.0, 128); #if !USE_FIXED - AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(ff_aac_kbd_long_960), 4.0, 960); - AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(ff_aac_kbd_short_120), 6.0, 120); - AAC_RENAME(ff_sine_window_init)(AAC_RENAME(ff_sine_960), 960); - AAC_RENAME(ff_sine_window_init)(AAC_RENAME(ff_sine_120), 120); + AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(aac_kbd_long_960), 4.0, 960); + AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(aac_kbd_short_120), 6.0, 120); + AAC_RENAME(ff_sine_window_init)(AAC_RENAME(sine_960), 960); + AAC_RENAME(ff_sine_window_init)(AAC_RENAME(sine_120), 120); + AAC_RENAME(ff_init_ff_sine_windows)(9); + ff_aac_float_common_init(); +#else + AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_long_1024), 4.0, 1024); + AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_short_128), 6.0, 128); + init_sine_windows_fixed(); #endif - AAC_RENAME(ff_init_ff_sine_windows)(10); - AAC_RENAME(ff_init_ff_sine_windows)( 9); - AAC_RENAME(ff_init_ff_sine_windows)( 7); AAC_RENAME(ff_cbrt_tableinit)(); } @@ -1200,7 +1299,7 @@ ac->oc[1].m4ac.chan_config = i; if (ac->oc[1].m4ac.chan_config) { - int ret = set_default_channel_config(avctx, layout_map, + int ret = set_default_channel_config(ac, avctx, layout_map, &layout_map_tags, ac->oc[1].m4ac.chan_config); if (!ret) output_configure(ac, layout_map, layout_map_tags, @@ -1703,7 +1802,6 @@ #if !USE_FIXED const float *vq = ff_aac_codebook_vector_vals[cbt_m1]; #endif /* !USE_FIXED */ - const uint16_t *cb_vector_idx = ff_aac_codebook_vector_idx[cbt_m1]; VLC_TYPE (*vlc_tab)[2] = vlc_spectral[cbt_m1].table; OPEN_READER(re, gb); @@ -1719,7 +1817,7 @@ UPDATE_CACHE(re, gb); GET_VLC(code, re, gb, vlc_tab, 8, 2); - cb_idx = cb_vector_idx[code]; + cb_idx = code; #if USE_FIXED cf = DEC_SQUAD(cf, cb_idx); #else @@ -1742,7 +1840,7 @@ UPDATE_CACHE(re, gb); GET_VLC(code, re, gb, vlc_tab, 8, 2); - cb_idx = cb_vector_idx[code]; + cb_idx = code; nnz = cb_idx >> 8 & 15; bits = nnz ? GET_CACHE(re, gb) : 0; LAST_SKIP_BITS(re, gb, nnz); @@ -1766,7 +1864,7 @@ UPDATE_CACHE(re, gb); GET_VLC(code, re, gb, vlc_tab, 8, 2); - cb_idx = cb_vector_idx[code]; + cb_idx = code; #if USE_FIXED cf = DEC_SPAIR(cf, cb_idx); #else @@ -1790,7 +1888,7 @@ UPDATE_CACHE(re, gb); GET_VLC(code, re, gb, vlc_tab, 8, 2); - cb_idx = cb_vector_idx[code]; + cb_idx = code; nnz = cb_idx >> 8 & 15; sign = nnz ? SHOW_UBITS(re, gb, nnz) << (cb_idx >> 12) : 0; LAST_SKIP_BITS(re, gb, nnz); @@ -1823,14 +1921,14 @@ UPDATE_CACHE(re, gb); GET_VLC(code, re, gb, vlc_tab, 8, 2); + cb_idx = code; - if (!code) { + if (cb_idx == 0x0000) { *icf++ = 0; *icf++ = 0; continue; } - cb_idx = cb_vector_idx[code]; nnz = cb_idx >> 12; nzt = cb_idx >> 8; bits = SHOW_UBITS(re, gb, nnz) << (32-nnz); @@ -2548,10 +2646,10 @@ static void windowing_and_mdct_ltp(AACContext *ac, INTFLOAT *out, INTFLOAT *in, IndividualChannelStream *ics) { - const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME(ff_aac_kbd_long_1024) : AAC_RENAME(ff_sine_1024); - const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME(ff_aac_kbd_short_128) : AAC_RENAME(ff_sine_128); - const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME(ff_aac_kbd_long_1024) : AAC_RENAME(ff_sine_1024); - const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME(ff_aac_kbd_short_128) : AAC_RENAME(ff_sine_128); + const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024); + const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128); + const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024); + const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128); if (ics->window_sequence[0] != LONG_STOP_SEQUENCE) { ac->fdsp->vector_fmul(in, in, lwindow_prev, 1024); @@ -2608,8 +2706,8 @@ IndividualChannelStream *ics = &sce->ics; INTFLOAT *saved = sce->saved; INTFLOAT *saved_ltp = sce->coeffs; - const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME(ff_aac_kbd_long_1024) : AAC_RENAME(ff_sine_1024); - const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME(ff_aac_kbd_short_128) : AAC_RENAME(ff_sine_128); + const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024); + const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128); int i; if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) { @@ -2647,9 +2745,9 @@ INTFLOAT *in = sce->coeffs; INTFLOAT *out = sce->ret; INTFLOAT *saved = sce->saved; - const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME(ff_aac_kbd_short_128) : AAC_RENAME(ff_sine_128); - const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME(ff_aac_kbd_long_1024) : AAC_RENAME(ff_sine_1024); - const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME(ff_aac_kbd_short_128) : AAC_RENAME(ff_sine_128); + const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128); + const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024); + const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128); INTFLOAT *buf = ac->buf_mdct; INTFLOAT *temp = ac->temp; int i; @@ -2716,9 +2814,9 @@ INTFLOAT *in = sce->coeffs; INTFLOAT *out = sce->ret; INTFLOAT *saved = sce->saved; - const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME(ff_aac_kbd_short_120) : AAC_RENAME(ff_sine_120); - const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME(ff_aac_kbd_long_960) : AAC_RENAME(ff_sine_960); - const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME(ff_aac_kbd_short_120) : AAC_RENAME(ff_sine_120); + const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME(aac_kbd_short_120) : AAC_RENAME(sine_120); + const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_long_960) : AAC_RENAME(sine_960); + const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_short_120) : AAC_RENAME(sine_120); INTFLOAT *buf = ac->buf_mdct; INTFLOAT *temp = ac->temp; int i; @@ -2795,10 +2893,10 @@ if (ics->use_kb_window[1]) { // AAC LD uses a low overlap sine window instead of a KBD window memcpy(out, saved, 192 * sizeof(*out)); - ac->fdsp->vector_fmul_window(out + 192, saved + 192, buf, AAC_RENAME(ff_sine_128), 64); + ac->fdsp->vector_fmul_window(out + 192, saved + 192, buf, AAC_RENAME2(sine_128), 64); memcpy( out + 320, buf + 64, 192 * sizeof(*out)); } else { - ac->fdsp->vector_fmul_window(out, saved, buf, AAC_RENAME(ff_sine_512), 256); + ac->fdsp->vector_fmul_window(out, saved, buf, AAC_RENAME2(sine_512), 256); } // buffer update @@ -2807,7 +2905,7 @@ static void imdct_and_windowing_eld(AACContext *ac, SingleChannelElement *sce) { - INTFLOAT *in = sce->coeffs; + UINTFLOAT *in = sce->coeffs; INTFLOAT *out = sce->ret; INTFLOAT *saved = sce->saved; INTFLOAT *buf = ac->buf_mdct; @@ -3002,7 +3100,7 @@ push_output_configuration(ac); if (hdr_info.chan_config) { ac->oc[1].m4ac.chan_config = hdr_info.chan_config; - if ((ret = set_default_channel_config(ac->avctx, + if ((ret = set_default_channel_config(ac, ac->avctx, layout_map, &layout_map_tags, hdr_info.chan_config)) < 0) @@ -3118,7 +3216,8 @@ } static int aac_decode_frame_int(AVCodecContext *avctx, void *data, - int *got_frame_ptr, GetBitContext *gb, AVPacket *avpkt) + int *got_frame_ptr, GetBitContext *gb, + const AVPacket *avpkt) { AACContext *ac = avctx->priv_data; ChannelElement *che = NULL, *che_prev = NULL; @@ -3213,7 +3312,7 @@ break; case TYPE_PCE: { - uint8_t layout_map[MAX_ELEM_ID*4][3]; + uint8_t layout_map[MAX_ELEM_ID*4][3] = {{0}}; int tags; int pushed = push_output_configuration(ac); @@ -3249,9 +3348,15 @@ err = AVERROR_INVALIDDATA; goto fail; } - while (elem_id > 0) - elem_id -= decode_extension_payload(ac, gb, elem_id, che_prev, che_prev_type); - err = 0; /* FIXME */ + err = 0; + while (elem_id > 0) { + int ret = decode_extension_payload(ac, gb, elem_id, che_prev, che_prev_type); + if (ret < 0) { + err = ret; + break; + } + elem_id -= ret; + } break; default: @@ -3332,11 +3437,11 @@ int buf_consumed; int buf_offset; int err; - int new_extradata_size; + buffer_size_t new_extradata_size; const uint8_t *new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &new_extradata_size); - int jp_dualmono_size; + buffer_size_t jp_dualmono_size; const uint8_t *jp_dualmono = av_packet_get_side_data(avpkt, AV_PKT_DATA_JP_DUALMONO, &jp_dualmono_size); diff -Nru ffmpeg-4.2.2/libavcodec/aac_defines.h ffmpeg-4.4/libavcodec/aac_defines.h --- ffmpeg-4.2.2/libavcodec/aac_defines.h 2018-11-01 18:34:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aac_defines.h 2021-04-08 21:28:39.000000000 +0000 @@ -34,6 +34,7 @@ #define AAC_RENAME(x) x ## _fixed #define AAC_RENAME_32(x) x ## _fixed_32 +#define AAC_RENAME2(x) x ## _fixed typedef int INTFLOAT; typedef unsigned UINTFLOAT; ///< Equivalent to INTFLOAT, Used as temporal cast to avoid undefined sign overflow operations. typedef int64_t INT64FLOAT; @@ -83,6 +84,7 @@ #define AAC_RENAME(x) x #define AAC_RENAME_32(x) x +#define AAC_RENAME2(x) ff_ ## x typedef float INTFLOAT; typedef float UINTFLOAT; typedef float INT64FLOAT; diff -Nru ffmpeg-4.2.2/libavcodec/aacenc.c ffmpeg-4.4/libavcodec/aacenc.c --- ffmpeg-4.2.2/libavcodec/aacenc.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,15 +30,14 @@ ***********************************/ #include "libavutil/libm.h" -#include "libavutil/thread.h" #include "libavutil/float_dsp.h" #include "libavutil/opt.h" #include "avcodec.h" #include "put_bits.h" #include "internal.h" #include "mpeg4audio.h" -#include "kbdwin.h" #include "sinewin.h" +#include "profiles.h" #include "aac.h" #include "aactab.h" @@ -48,8 +47,6 @@ #include "psymodel.h" -static AVOnce aac_table_init = AV_ONCE_INIT; - static void put_pce(PutBitContext *pb, AVCodecContext *avctx) { int i, j; @@ -82,9 +79,9 @@ } } - avpriv_align_put_bits(pb); + align_put_bits(pb); put_bits(pb, 8, strlen(aux_data)); - avpriv_put_string(pb, aux_data, 0); + ff_put_string(pb, aux_data, 0); } /** @@ -521,7 +518,7 @@ put_bits(&s->pb, 8, namelen - 14); put_bits(&s->pb, 4, 0); //extension type - filler padbits = -put_bits_count(&s->pb) & 7; - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); for (i = 0; i < namelen - 2; i++) put_bits(&s->pb, 8, name[i]); put_bits(&s->pb, 12 - padbits, 0); @@ -924,10 +921,7 @@ return AVERROR(ENOMEM); // window init - ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024); - ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128); - ff_init_ff_sine_windows(10); - ff_init_ff_sine_windows(7); + ff_aac_float_common_init(); if ((ret = ff_mdct_init(&s->mdct1024, 11, 0, 32768.0)) < 0) return ret; @@ -940,20 +934,14 @@ static av_cold int alloc_buffers(AVCodecContext *avctx, AACEncContext *s) { int ch; - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->buffer.samples, s->channels, 3 * 1024 * sizeof(s->buffer.samples[0]), alloc_fail); - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->cpe, s->chan_map[0], sizeof(ChannelElement), alloc_fail); + if (!FF_ALLOCZ_TYPED_ARRAY(s->buffer.samples, s->channels * 3 * 1024) || + !FF_ALLOCZ_TYPED_ARRAY(s->cpe, s->chan_map[0])) + return AVERROR(ENOMEM); for(ch = 0; ch < s->channels; ch++) s->planar_samples[ch] = s->buffer.samples + 3 * 1024 * ch; return 0; -alloc_fail: - return AVERROR(ENOMEM); -} - -static av_cold void aac_encode_init_tables(void) -{ - ff_aac_tableinit(); } static av_cold int aac_encode_init(AVCodecContext *avctx) @@ -1077,13 +1065,13 @@ s->options.mid_side = 0; if ((ret = dsp_init(avctx, s)) < 0) - goto fail; + return ret; if ((ret = alloc_buffers(avctx, s)) < 0) - goto fail; + return ret; if ((ret = put_audio_specific_config(avctx))) - goto fail; + return ret; sizes[0] = ff_aac_swb_size_1024[s->samplerate_index]; sizes[1] = ff_aac_swb_size_128[s->samplerate_index]; @@ -1093,7 +1081,7 @@ grouping[i] = s->chan_map[i + 1] == TYPE_CPE; if ((ret = ff_psy_init(&s->psy, avctx, 2, sizes, lengths, s->chan_map[0], grouping)) < 0) - goto fail; + return ret; s->psypp = ff_psy_preprocess_init(avctx); ff_lpc_init(&s->lpc, 2*avctx->frame_size, TNS_MAX_ORDER, FF_LPC_TYPE_LEVINSON); s->random_state = 0x1f2e3d4c; @@ -1107,15 +1095,10 @@ if (HAVE_MIPSDSP) ff_aac_coder_init_mips(s); - if ((ret = ff_thread_once(&aac_table_init, &aac_encode_init_tables)) != 0) - return AVERROR_UNKNOWN; - ff_af_queue_init(avctx, &s->afq); + ff_aac_tableinit(); return 0; -fail: - aac_encode_end(avctx); - return ret; } #define AACENC_FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM @@ -1131,6 +1114,7 @@ {"aac_ltp", "Long term prediction", offsetof(AACEncContext, options.ltp), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS}, {"aac_pred", "AAC-Main prediction", offsetof(AACEncContext, options.pred), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS}, {"aac_pce", "Forces the use of PCEs", offsetof(AACEncContext, options.pce), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS}, + FF_AAC_PROFILE_OPTS {NULL} }; @@ -1157,7 +1141,7 @@ .close = aac_encode_end, .defaults = aac_encode_defaults, .supported_samplerates = mpeg4audio_sample_rates, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .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, AV_SAMPLE_FMT_NONE }, diff -Nru ffmpeg-4.2.2/libavcodec/aacenc.h ffmpeg-4.4/libavcodec/aacenc.h --- ffmpeg-4.2.2/libavcodec/aacenc.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacenc.h 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,8 @@ #define AVCODEC_AACENC_H #include "libavutil/float_dsp.h" +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "put_bits.h" diff -Nru ffmpeg-4.2.2/libavcodec/aacenctab.c ffmpeg-4.4/libavcodec/aacenctab.c --- ffmpeg-4.2.2/libavcodec/aacenctab.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacenctab.c 2021-04-08 21:28:39.000000000 +0000 @@ -88,7 +88,7 @@ 32, 36, 36, 40, 44, 48, 52, 56, 60, 64, 80 }; -const uint8_t *ff_aac_swb_size_128[] = { +const uint8_t *const ff_aac_swb_size_128[] = { swb_size_128_96, swb_size_128_96, swb_size_128_64, swb_size_128_48, swb_size_128_48, swb_size_128_48, swb_size_128_24, swb_size_128_24, swb_size_128_16, @@ -96,7 +96,7 @@ swb_size_128_8 }; -const uint8_t *ff_aac_swb_size_1024[] = { +const uint8_t *const ff_aac_swb_size_1024[] = { swb_size_1024_96, swb_size_1024_96, swb_size_1024_64, swb_size_1024_48, swb_size_1024_48, swb_size_1024_32, swb_size_1024_24, swb_size_1024_24, swb_size_1024_16, diff -Nru ffmpeg-4.2.2/libavcodec/aacenctab.h ffmpeg-4.4/libavcodec/aacenctab.h --- ffmpeg-4.2.2/libavcodec/aacenctab.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacenctab.h 2021-04-08 21:28:39.000000000 +0000 @@ -38,9 +38,9 @@ #define AAC_MAX_CHANNELS 16 -extern const uint8_t *ff_aac_swb_size_1024[]; +extern const uint8_t *const ff_aac_swb_size_1024[]; extern const int ff_aac_swb_size_1024_len; -extern const uint8_t *ff_aac_swb_size_128[]; +extern const uint8_t *const ff_aac_swb_size_128[]; extern const int ff_aac_swb_size_128_len; /* Supported layouts without using a PCE */ diff -Nru ffmpeg-4.2.2/libavcodec/aac.h ffmpeg-4.4/libavcodec/aac.h --- ffmpeg-4.2.2/libavcodec/aac.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aac.h 2021-04-08 21:28:39.000000000 +0000 @@ -34,6 +34,7 @@ #include "aac_defines.h" #include "libavutil/float_dsp.h" #include "libavutil/fixed_dsp.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #if !USE_FIXED #include "mdct15.h" @@ -356,7 +357,7 @@ OutputConfiguration oc[2]; int warned_num_aac_frames; int warned_960_sbr; - + unsigned warned_71_wide; int warned_gain_control; /* aacdec functions pointers */ diff -Nru ffmpeg-4.2.2/libavcodec/aacps.c ffmpeg-4.4/libavcodec/aacps.c --- ffmpeg-4.2.2/libavcodec/aacps.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacps.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,8 +25,8 @@ #include #include "libavutil/common.h" #include "libavutil/mathematics.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" -#include "get_bits.h" #include "aacps.h" #if USE_FIXED #include "aacps_fixed_tablegen.h" @@ -34,118 +34,12 @@ #include "libavutil/internal.h" #include "aacps_tablegen.h" #endif /* USE_FIXED */ -#include "aacpsdata.c" -#define PS_BASELINE 0 ///< Operate in Baseline PS mode - ///< Baseline implies 10 or 20 stereo bands, - ///< mixing mode A, and no ipd/opd - -#define numQMFSlots 32 //numTimeSlots * RATE - -static const int8_t num_env_tab[2][4] = { - { 0, 1, 2, 4, }, - { 1, 2, 3, 4, }, -}; - -static const int8_t nr_iidicc_par_tab[] = { - 10, 20, 34, 10, 20, 34, -}; - -static const int8_t nr_iidopd_par_tab[] = { - 5, 11, 17, 5, 11, 17, +static const INTFLOAT g1_Q2[] = { + Q31(0.0f), Q31(0.01899487526049f), Q31(0.0f), Q31(-0.07293139167538f), + Q31(0.0f), Q31(0.30596630545168f), Q31(0.5f) }; -enum { - huff_iid_df1, - huff_iid_dt1, - huff_iid_df0, - huff_iid_dt0, - huff_icc_df, - huff_icc_dt, - huff_ipd_df, - huff_ipd_dt, - huff_opd_df, - huff_opd_dt, -}; - -static const int huff_iid[] = { - huff_iid_df0, - huff_iid_df1, - huff_iid_dt0, - huff_iid_dt1, -}; - -static VLC vlc_ps[10]; - -#define READ_PAR_DATA(PAR, OFFSET, MASK, ERR_CONDITION) \ -/** \ - * Read Inter-channel Intensity Difference/Inter-Channel Coherence/ \ - * Inter-channel Phase Difference/Overall Phase Difference parameters from the \ - * bitstream. \ - * \ - * @param avctx contains the current codec context \ - * @param gb pointer to the input bitstream \ - * @param ps pointer to the Parametric Stereo context \ - * @param PAR pointer to the parameter to be read \ - * @param e envelope to decode \ - * @param dt 1: time delta-coded, 0: frequency delta-coded \ - */ \ -static int read_ ## PAR ## _data(AVCodecContext *avctx, GetBitContext *gb, PSContext *ps, \ - int8_t (*PAR)[PS_MAX_NR_IIDICC], int table_idx, int e, int dt) \ -{ \ - int b, num = ps->nr_ ## PAR ## _par; \ - VLC_TYPE (*vlc_table)[2] = vlc_ps[table_idx].table; \ - if (dt) { \ - int e_prev = e ? e - 1 : ps->num_env_old - 1; \ - e_prev = FFMAX(e_prev, 0); \ - for (b = 0; b < num; b++) { \ - int val = PAR[e_prev][b] + get_vlc2(gb, vlc_table, 9, 3) - OFFSET; \ - if (MASK) val &= MASK; \ - PAR[e][b] = val; \ - if (ERR_CONDITION) \ - goto err; \ - } \ - } else { \ - int val = 0; \ - for (b = 0; b < num; b++) { \ - val += get_vlc2(gb, vlc_table, 9, 3) - OFFSET; \ - if (MASK) val &= MASK; \ - PAR[e][b] = val; \ - if (ERR_CONDITION) \ - goto err; \ - } \ - } \ - return 0; \ -err: \ - av_log(avctx, AV_LOG_ERROR, "illegal "#PAR"\n"); \ - return AVERROR_INVALIDDATA; \ -} - -READ_PAR_DATA(iid, huff_offset[table_idx], 0, FFABS(ps->iid_par[e][b]) > 7 + 8 * ps->iid_quant) -READ_PAR_DATA(icc, huff_offset[table_idx], 0, ps->icc_par[e][b] > 7U) -READ_PAR_DATA(ipdopd, 0, 0x07, 0) - -static int ps_read_extension_data(GetBitContext *gb, PSContext *ps, int ps_extension_id) -{ - int e; - int count = get_bits_count(gb); - - if (ps_extension_id) - return 0; - - ps->enable_ipdopd = get_bits1(gb); - if (ps->enable_ipdopd) { - for (e = 0; e < ps->num_env; e++) { - int dt = get_bits1(gb); - read_ipdopd_data(NULL, gb, ps, ps->ipd_par, dt ? huff_ipd_dt : huff_ipd_df, e, dt); - dt = get_bits1(gb); - read_ipdopd_data(NULL, gb, ps, ps->opd_par, dt ? huff_opd_dt : huff_opd_df, e, dt); - } - } - skip_bits1(gb); //reserved_ps - return get_bits_count(gb) - count; -} - static void ipdopd_reset(int8_t *ipd_hist, int8_t *opd_hist) { int i; @@ -155,163 +49,6 @@ } } -int AAC_RENAME(ff_ps_read_data)(AVCodecContext *avctx, GetBitContext *gb_host, PSContext *ps, int bits_left) -{ - int e; - int bit_count_start = get_bits_count(gb_host); - int header; - int bits_consumed; - GetBitContext gbc = *gb_host, *gb = &gbc; - - header = get_bits1(gb); - if (header) { //enable_ps_header - ps->enable_iid = get_bits1(gb); - if (ps->enable_iid) { - int iid_mode = get_bits(gb, 3); - if (iid_mode > 5) { - av_log(avctx, AV_LOG_ERROR, "iid_mode %d is reserved.\n", - iid_mode); - goto err; - } - ps->nr_iid_par = nr_iidicc_par_tab[iid_mode]; - ps->iid_quant = iid_mode > 2; - ps->nr_ipdopd_par = nr_iidopd_par_tab[iid_mode]; - } - ps->enable_icc = get_bits1(gb); - if (ps->enable_icc) { - ps->icc_mode = get_bits(gb, 3); - if (ps->icc_mode > 5) { - av_log(avctx, AV_LOG_ERROR, "icc_mode %d is reserved.\n", - ps->icc_mode); - goto err; - } - ps->nr_icc_par = nr_iidicc_par_tab[ps->icc_mode]; - } - ps->enable_ext = get_bits1(gb); - } - - ps->frame_class = get_bits1(gb); - ps->num_env_old = ps->num_env; - ps->num_env = num_env_tab[ps->frame_class][get_bits(gb, 2)]; - - ps->border_position[0] = -1; - if (ps->frame_class) { - for (e = 1; e <= ps->num_env; e++) { - ps->border_position[e] = get_bits(gb, 5); - if (ps->border_position[e] < ps->border_position[e-1]) { - av_log(avctx, AV_LOG_ERROR, "border_position non monotone.\n"); - goto err; - } - } - } else - for (e = 1; e <= ps->num_env; e++) - ps->border_position[e] = (e * numQMFSlots >> ff_log2_tab[ps->num_env]) - 1; - - if (ps->enable_iid) { - for (e = 0; e < ps->num_env; e++) { - int dt = get_bits1(gb); - if (read_iid_data(avctx, gb, ps, ps->iid_par, huff_iid[2*dt+ps->iid_quant], e, dt)) - goto err; - } - } else - memset(ps->iid_par, 0, sizeof(ps->iid_par)); - - if (ps->enable_icc) - for (e = 0; e < ps->num_env; e++) { - int dt = get_bits1(gb); - if (read_icc_data(avctx, gb, ps, ps->icc_par, dt ? huff_icc_dt : huff_icc_df, e, dt)) - goto err; - } - else - memset(ps->icc_par, 0, sizeof(ps->icc_par)); - - if (ps->enable_ext) { - int cnt = get_bits(gb, 4); - if (cnt == 15) { - cnt += get_bits(gb, 8); - } - cnt *= 8; - while (cnt > 7) { - int ps_extension_id = get_bits(gb, 2); - cnt -= 2 + ps_read_extension_data(gb, ps, ps_extension_id); - } - if (cnt < 0) { - av_log(avctx, AV_LOG_ERROR, "ps extension overflow %d\n", cnt); - goto err; - } - skip_bits(gb, cnt); - } - - ps->enable_ipdopd &= !PS_BASELINE; - - //Fix up envelopes - if (!ps->num_env || ps->border_position[ps->num_env] < numQMFSlots - 1) { - //Create a fake envelope - int source = ps->num_env ? ps->num_env - 1 : ps->num_env_old - 1; - int b; - if (source >= 0 && source != ps->num_env) { - if (ps->enable_iid) { - memcpy(ps->iid_par+ps->num_env, ps->iid_par+source, sizeof(ps->iid_par[0])); - } - if (ps->enable_icc) { - memcpy(ps->icc_par+ps->num_env, ps->icc_par+source, sizeof(ps->icc_par[0])); - } - if (ps->enable_ipdopd) { - memcpy(ps->ipd_par+ps->num_env, ps->ipd_par+source, sizeof(ps->ipd_par[0])); - memcpy(ps->opd_par+ps->num_env, ps->opd_par+source, sizeof(ps->opd_par[0])); - } - } - if (ps->enable_iid){ - for (b = 0; b < ps->nr_iid_par; b++) { - if (FFABS(ps->iid_par[ps->num_env][b]) > 7 + 8 * ps->iid_quant) { - av_log(avctx, AV_LOG_ERROR, "iid_par invalid\n"); - goto err; - } - } - } - if (ps->enable_icc){ - for (b = 0; b < ps->nr_iid_par; b++) { - if (ps->icc_par[ps->num_env][b] > 7U) { - av_log(avctx, AV_LOG_ERROR, "icc_par invalid\n"); - goto err; - } - } - } - ps->num_env++; - ps->border_position[ps->num_env] = numQMFSlots - 1; - } - - - ps->is34bands_old = ps->is34bands; - if (!PS_BASELINE && (ps->enable_iid || ps->enable_icc)) - ps->is34bands = (ps->enable_iid && ps->nr_iid_par == 34) || - (ps->enable_icc && ps->nr_icc_par == 34); - - //Baseline - if (!ps->enable_ipdopd) { - memset(ps->ipd_par, 0, sizeof(ps->ipd_par)); - memset(ps->opd_par, 0, sizeof(ps->opd_par)); - } - - if (header) - ps->start = 1; - - bits_consumed = get_bits_count(gb) - bit_count_start; - if (bits_consumed <= bits_left) { - skip_bits_long(gb_host, bits_consumed); - return bits_consumed; - } - av_log(avctx, AV_LOG_ERROR, "Expected to read %d PS bits actually read %d.\n", bits_left, bits_consumed); -err: - ps->start = 0; - skip_bits_long(gb_host, bits_left); - memset(ps->iid_par, 0, sizeof(ps->iid_par)); - memset(ps->icc_par, 0, sizeof(ps->icc_par)); - memset(ps->ipd_par, 0, sizeof(ps->ipd_par)); - memset(ps->opd_par, 0, sizeof(ps->opd_par)); - return bits_left; -} - /** Split one subband into 2 subsubbands with a symmetric real filter. * The filter must have its non-center even coefficients equal to zero. */ static void hybrid2_re(INTFLOAT (*in)[2], INTFLOAT (*out)[32][2], const INTFLOAT filter[8], int len, int reverse) @@ -672,14 +409,14 @@ const float transient_impact = 1.5f; const float a_smooth = 0.25f; ///< Smoothing coefficient #endif /* USE_FIXED */ - const int8_t *k_to_i = is34 ? k_to_i_34 : k_to_i_20; + const int8_t *const k_to_i = is34 ? ff_k_to_i_34 : ff_k_to_i_20; int i, k, m, n; int n0 = 0, nL = 32; const INTFLOAT peak_decay_factor = Q31(0.76592833836465f); memset(power, 0, 34 * sizeof(*power)); - if (is34 != ps->is34bands_old) { + if (is34 != ps->common.is34bands_old) { memset(ps->peak_decay_nrg, 0, sizeof(ps->peak_decay_nrg)); memset(ps->power_smooth, 0, sizeof(ps->power_smooth)); memset(ps->peak_decay_diff_smooth, 0, sizeof(ps->peak_decay_diff_smooth)); @@ -821,6 +558,7 @@ { int e, b, k; + PSCommonContext *const ps2 = &ps->common; INTFLOAT (*H11)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H11; INTFLOAT (*H12)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H12; INTFLOAT (*H21)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H21; @@ -835,29 +573,29 @@ int8_t (*icc_mapped)[PS_MAX_NR_IIDICC] = icc_mapped_buf; int8_t (*ipd_mapped)[PS_MAX_NR_IIDICC] = ipd_mapped_buf; int8_t (*opd_mapped)[PS_MAX_NR_IIDICC] = opd_mapped_buf; - const int8_t *k_to_i = is34 ? k_to_i_34 : k_to_i_20; - TABLE_CONST INTFLOAT (*H_LUT)[8][4] = (PS_BASELINE || ps->icc_mode < 3) ? HA : HB; + const int8_t *const k_to_i = is34 ? ff_k_to_i_34 : ff_k_to_i_20; + TABLE_CONST INTFLOAT (*H_LUT)[8][4] = (PS_BASELINE || ps2->icc_mode < 3) ? HA : HB; //Remapping - if (ps->num_env_old) { - memcpy(H11[0][0], H11[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H11[0][0][0])); - memcpy(H11[1][0], H11[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H11[1][0][0])); - memcpy(H12[0][0], H12[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H12[0][0][0])); - memcpy(H12[1][0], H12[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H12[1][0][0])); - memcpy(H21[0][0], H21[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H21[0][0][0])); - memcpy(H21[1][0], H21[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H21[1][0][0])); - memcpy(H22[0][0], H22[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H22[0][0][0])); - memcpy(H22[1][0], H22[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H22[1][0][0])); + if (ps2->num_env_old) { + memcpy(H11[0][0], H11[0][ps2->num_env_old], sizeof(H11[0][0])); + memcpy(H11[1][0], H11[1][ps2->num_env_old], sizeof(H11[1][0])); + memcpy(H12[0][0], H12[0][ps2->num_env_old], sizeof(H12[0][0])); + memcpy(H12[1][0], H12[1][ps2->num_env_old], sizeof(H12[1][0])); + memcpy(H21[0][0], H21[0][ps2->num_env_old], sizeof(H21[0][0])); + memcpy(H21[1][0], H21[1][ps2->num_env_old], sizeof(H21[1][0])); + memcpy(H22[0][0], H22[0][ps2->num_env_old], sizeof(H22[0][0])); + memcpy(H22[1][0], H22[1][ps2->num_env_old], sizeof(H22[1][0])); } if (is34) { - remap34(&iid_mapped, ps->iid_par, ps->nr_iid_par, ps->num_env, 1); - remap34(&icc_mapped, ps->icc_par, ps->nr_icc_par, ps->num_env, 1); - if (ps->enable_ipdopd) { - remap34(&ipd_mapped, ps->ipd_par, ps->nr_ipdopd_par, ps->num_env, 0); - remap34(&opd_mapped, ps->opd_par, ps->nr_ipdopd_par, ps->num_env, 0); + remap34(&iid_mapped, ps2->iid_par, ps2->nr_iid_par, ps2->num_env, 1); + remap34(&icc_mapped, ps2->icc_par, ps2->nr_icc_par, ps2->num_env, 1); + if (ps2->enable_ipdopd) { + remap34(&ipd_mapped, ps2->ipd_par, ps2->nr_ipdopd_par, ps2->num_env, 0); + remap34(&opd_mapped, ps2->opd_par, ps2->nr_ipdopd_par, ps2->num_env, 0); } - if (!ps->is34bands_old) { + if (!ps2->is34bands_old) { map_val_20_to_34(H11[0][0]); map_val_20_to_34(H11[1][0]); map_val_20_to_34(H12[0][0]); @@ -869,13 +607,13 @@ ipdopd_reset(ipd_hist, opd_hist); } } else { - remap20(&iid_mapped, ps->iid_par, ps->nr_iid_par, ps->num_env, 1); - remap20(&icc_mapped, ps->icc_par, ps->nr_icc_par, ps->num_env, 1); - if (ps->enable_ipdopd) { - remap20(&ipd_mapped, ps->ipd_par, ps->nr_ipdopd_par, ps->num_env, 0); - remap20(&opd_mapped, ps->opd_par, ps->nr_ipdopd_par, ps->num_env, 0); + remap20(&iid_mapped, ps2->iid_par, ps2->nr_iid_par, ps2->num_env, 1); + remap20(&icc_mapped, ps2->icc_par, ps2->nr_icc_par, ps2->num_env, 1); + if (ps2->enable_ipdopd) { + remap20(&ipd_mapped, ps2->ipd_par, ps2->nr_ipdopd_par, ps2->num_env, 0); + remap20(&opd_mapped, ps2->opd_par, ps2->nr_ipdopd_par, ps2->num_env, 0); } - if (ps->is34bands_old) { + if (ps2->is34bands_old) { map_val_34_to_20(H11[0][0]); map_val_34_to_20(H11[1][0]); map_val_34_to_20(H12[0][0]); @@ -889,15 +627,15 @@ } //Mixing - for (e = 0; e < ps->num_env; e++) { + for (e = 0; e < ps2->num_env; e++) { for (b = 0; b < NR_PAR_BANDS[is34]; b++) { INTFLOAT h11, h12, h21, h22; - h11 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][0]; - h12 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][1]; - h21 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][2]; - h22 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][3]; + h11 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps2->iid_quant][icc_mapped[e][b]][0]; + h12 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps2->iid_quant][icc_mapped[e][b]][1]; + h21 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps2->iid_quant][icc_mapped[e][b]][2]; + h22 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps2->iid_quant][icc_mapped[e][b]][3]; - if (!PS_BASELINE && ps->enable_ipdopd && b < NR_IPDOPD_BANDS[is34]) { + if (!PS_BASELINE && ps2->enable_ipdopd && b < NR_IPDOPD_BANDS[is34]) { //The spec say says to only run this smoother when enable_ipdopd //is set but the reference decoder appears to run it constantly INTFLOAT h11i, h12i, h21i, h22i; @@ -934,8 +672,8 @@ for (k = 0; k < NR_BANDS[is34]; k++) { LOCAL_ALIGNED_16(INTFLOAT, h, [2], [4]); LOCAL_ALIGNED_16(INTFLOAT, h_step, [2], [4]); - int start = ps->border_position[e]; - int stop = ps->border_position[e+1]; + int start = ps2->border_position[e]; + int stop = ps2->border_position[e+1]; INTFLOAT width = Q30(1.f) / ((stop - start) ? (stop - start) : 1); #if USE_FIXED width = FFMIN(2U*width, INT_MAX); @@ -945,7 +683,7 @@ h[0][1] = H12[0][e][b]; h[0][2] = H21[0][e][b]; h[0][3] = H22[0][e][b]; - if (!PS_BASELINE && ps->enable_ipdopd) { + if (!PS_BASELINE && ps2->enable_ipdopd) { //Is this necessary? ps_04_new seems unchanged if ((is34 && k <= 13 && k >= 9) || (!is34 && k <= 1)) { h[1][0] = -H11[1][e][b]; @@ -964,14 +702,14 @@ h_step[0][1] = AAC_MSUB31_V3(H12[0][e+1][b], h[0][1], width); h_step[0][2] = AAC_MSUB31_V3(H21[0][e+1][b], h[0][2], width); h_step[0][3] = AAC_MSUB31_V3(H22[0][e+1][b], h[0][3], width); - if (!PS_BASELINE && ps->enable_ipdopd) { + if (!PS_BASELINE && ps2->enable_ipdopd) { h_step[1][0] = AAC_MSUB31_V3(H11[1][e+1][b], h[1][0], width); h_step[1][1] = AAC_MSUB31_V3(H12[1][e+1][b], h[1][1], width); h_step[1][2] = AAC_MSUB31_V3(H21[1][e+1][b], h[1][2], width); h_step[1][3] = AAC_MSUB31_V3(H22[1][e+1][b], h[1][3], width); } if (stop - start) - ps->dsp.stereo_interpolate[!PS_BASELINE && ps->enable_ipdopd]( + ps->dsp.stereo_interpolate[!PS_BASELINE && ps2->enable_ipdopd]( l[k] + 1 + start, r[k] + 1 + start, h, h_step, stop - start); } @@ -983,7 +721,7 @@ INTFLOAT (*Lbuf)[32][2] = ps->Lbuf; INTFLOAT (*Rbuf)[32][2] = ps->Rbuf; const int len = 32; - int is34 = ps->is34bands; + int is34 = ps->common.is34bands; top += NR_BANDS[is34] - 64; memset(ps->delay+top, 0, (NR_BANDS[is34] - top)*sizeof(ps->delay[0])); @@ -999,45 +737,9 @@ return 0; } -#define PS_INIT_VLC_STATIC(num, size) \ - INIT_VLC_STATIC(&vlc_ps[num], 9, ps_tmp[num].table_size / ps_tmp[num].elem_size, \ - ps_tmp[num].ps_bits, 1, 1, \ - ps_tmp[num].ps_codes, ps_tmp[num].elem_size, ps_tmp[num].elem_size, \ - size); - -#define PS_VLC_ROW(name) \ - { name ## _codes, name ## _bits, sizeof(name ## _codes), sizeof(name ## _codes[0]) } - av_cold void AAC_RENAME(ff_ps_init)(void) { - // Syntax initialization - static const struct { - const void *ps_codes, *ps_bits; - const unsigned int table_size, elem_size; - } ps_tmp[] = { - PS_VLC_ROW(huff_iid_df1), - PS_VLC_ROW(huff_iid_dt1), - PS_VLC_ROW(huff_iid_df0), - PS_VLC_ROW(huff_iid_dt0), - PS_VLC_ROW(huff_icc_df), - PS_VLC_ROW(huff_icc_dt), - PS_VLC_ROW(huff_ipd_df), - PS_VLC_ROW(huff_ipd_dt), - PS_VLC_ROW(huff_opd_df), - PS_VLC_ROW(huff_opd_dt), - }; - - PS_INIT_VLC_STATIC(0, 1544); - PS_INIT_VLC_STATIC(1, 832); - PS_INIT_VLC_STATIC(2, 1024); - PS_INIT_VLC_STATIC(3, 1036); - PS_INIT_VLC_STATIC(4, 544); - PS_INIT_VLC_STATIC(5, 544); - PS_INIT_VLC_STATIC(6, 512); - PS_INIT_VLC_STATIC(7, 512); - PS_INIT_VLC_STATIC(8, 512); - PS_INIT_VLC_STATIC(9, 512); - ps_tableinit(); + ff_ps_init_common(); } av_cold void AAC_RENAME(ff_ps_ctx_init)(PSContext *ps) diff -Nru ffmpeg-4.2.2/libavcodec/aacps_common.c ffmpeg-4.4/libavcodec/aacps_common.c --- ffmpeg-4.2.2/libavcodec/aacps_common.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacps_common.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,336 @@ +/* + * Functions common to fixed/float MPEG-4 Parametric Stereo decoding + * Copyright (c) 2010 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 +#include "libavutil/common.h" +#include "libavutil/thread.h" +#include "aacps.h" +#include "get_bits.h" +#include "aacpsdata.c" + +static const int8_t num_env_tab[2][4] = { + { 0, 1, 2, 4, }, + { 1, 2, 3, 4, }, +}; + +static const int8_t nr_iidicc_par_tab[] = { + 10, 20, 34, 10, 20, 34, +}; + +static const int8_t nr_iidopd_par_tab[] = { + 5, 11, 17, 5, 11, 17, +}; + +enum { + huff_iid_df1, + huff_iid_dt1, + huff_iid_df0, + huff_iid_dt0, + huff_icc_df, + huff_icc_dt, + huff_ipd_df, + huff_ipd_dt, + huff_opd_df, + huff_opd_dt, +}; + +static const int huff_iid[] = { + huff_iid_df0, + huff_iid_df1, + huff_iid_dt0, + huff_iid_dt1, +}; + +static VLC vlc_ps[10]; + +#define READ_PAR_DATA(PAR, OFFSET, MASK, ERR_CONDITION, NB_BITS, MAX_DEPTH) \ +/** \ + * Read Inter-channel Intensity Difference/Inter-Channel Coherence/ \ + * Inter-channel Phase Difference/Overall Phase Difference parameters from the \ + * bitstream. \ + * \ + * @param avctx contains the current codec context \ + * @param gb pointer to the input bitstream \ + * @param ps pointer to the Parametric Stereo context \ + * @param PAR pointer to the parameter to be read \ + * @param e envelope to decode \ + * @param dt 1: time delta-coded, 0: frequency delta-coded \ + */ \ +static int read_ ## PAR ## _data(AVCodecContext *avctx, GetBitContext *gb, PSCommonContext *ps, \ + int8_t (*PAR)[PS_MAX_NR_IIDICC], int table_idx, int e, int dt) \ +{ \ + int b, num = ps->nr_ ## PAR ## _par; \ + VLC_TYPE (*vlc_table)[2] = vlc_ps[table_idx].table; \ + if (dt) { \ + int e_prev = e ? e - 1 : ps->num_env_old - 1; \ + e_prev = FFMAX(e_prev, 0); \ + for (b = 0; b < num; b++) { \ + int val = PAR[e_prev][b] + get_vlc2(gb, vlc_table, NB_BITS, MAX_DEPTH) - OFFSET; \ + if (MASK) val &= MASK; \ + PAR[e][b] = val; \ + if (ERR_CONDITION) \ + goto err; \ + } \ + } else { \ + int val = 0; \ + for (b = 0; b < num; b++) { \ + val += get_vlc2(gb, vlc_table, NB_BITS, MAX_DEPTH) - OFFSET; \ + if (MASK) val &= MASK; \ + PAR[e][b] = val; \ + if (ERR_CONDITION) \ + goto err; \ + } \ + } \ + return 0; \ +err: \ + av_log(avctx, AV_LOG_ERROR, "illegal "#PAR"\n"); \ + return AVERROR_INVALIDDATA; \ +} + +READ_PAR_DATA(iid, huff_offset[table_idx], 0, FFABS(ps->iid_par[e][b]) > 7 + 8 * ps->iid_quant, 9, 3) +READ_PAR_DATA(icc, huff_offset[table_idx], 0, ps->icc_par[e][b] > 7U, 9, 2) +READ_PAR_DATA(ipdopd, 0, 0x07, 0, 5, 1) + +static int ps_read_extension_data(GetBitContext *gb, PSCommonContext *ps, + int ps_extension_id) +{ + int e; + int count = get_bits_count(gb); + + if (ps_extension_id) + return 0; + + ps->enable_ipdopd = get_bits1(gb); + if (ps->enable_ipdopd) { + for (e = 0; e < ps->num_env; e++) { + int dt = get_bits1(gb); + read_ipdopd_data(NULL, gb, ps, ps->ipd_par, dt ? huff_ipd_dt : huff_ipd_df, e, dt); + dt = get_bits1(gb); + read_ipdopd_data(NULL, gb, ps, ps->opd_par, dt ? huff_opd_dt : huff_opd_df, e, dt); + } + } + skip_bits1(gb); //reserved_ps + return get_bits_count(gb) - count; +} + +int ff_ps_read_data(AVCodecContext *avctx, GetBitContext *gb_host, + PSCommonContext *ps, int bits_left) +{ + int e; + int bit_count_start = get_bits_count(gb_host); + int header; + int bits_consumed; + GetBitContext gbc = *gb_host, *gb = &gbc; + + header = get_bits1(gb); + if (header) { //enable_ps_header + ps->enable_iid = get_bits1(gb); + if (ps->enable_iid) { + int iid_mode = get_bits(gb, 3); + if (iid_mode > 5) { + av_log(avctx, AV_LOG_ERROR, "iid_mode %d is reserved.\n", + iid_mode); + goto err; + } + ps->nr_iid_par = nr_iidicc_par_tab[iid_mode]; + ps->iid_quant = iid_mode > 2; + ps->nr_ipdopd_par = nr_iidopd_par_tab[iid_mode]; + } + ps->enable_icc = get_bits1(gb); + if (ps->enable_icc) { + ps->icc_mode = get_bits(gb, 3); + if (ps->icc_mode > 5) { + av_log(avctx, AV_LOG_ERROR, "icc_mode %d is reserved.\n", + ps->icc_mode); + goto err; + } + ps->nr_icc_par = nr_iidicc_par_tab[ps->icc_mode]; + } + ps->enable_ext = get_bits1(gb); + } + + ps->frame_class = get_bits1(gb); + ps->num_env_old = ps->num_env; + ps->num_env = num_env_tab[ps->frame_class][get_bits(gb, 2)]; + + ps->border_position[0] = -1; + if (ps->frame_class) { + for (e = 1; e <= ps->num_env; e++) { + ps->border_position[e] = get_bits(gb, 5); + if (ps->border_position[e] < ps->border_position[e-1]) { + av_log(avctx, AV_LOG_ERROR, "border_position non monotone.\n"); + goto err; + } + } + } else + for (e = 1; e <= ps->num_env; e++) + ps->border_position[e] = (e * numQMFSlots >> ff_log2_tab[ps->num_env]) - 1; + + if (ps->enable_iid) { + for (e = 0; e < ps->num_env; e++) { + int dt = get_bits1(gb); + if (read_iid_data(avctx, gb, ps, ps->iid_par, huff_iid[2*dt+ps->iid_quant], e, dt)) + goto err; + } + } else + memset(ps->iid_par, 0, sizeof(ps->iid_par)); + + if (ps->enable_icc) + for (e = 0; e < ps->num_env; e++) { + int dt = get_bits1(gb); + if (read_icc_data(avctx, gb, ps, ps->icc_par, dt ? huff_icc_dt : huff_icc_df, e, dt)) + goto err; + } + else + memset(ps->icc_par, 0, sizeof(ps->icc_par)); + + if (ps->enable_ext) { + int cnt = get_bits(gb, 4); + if (cnt == 15) { + cnt += get_bits(gb, 8); + } + cnt *= 8; + while (cnt > 7) { + int ps_extension_id = get_bits(gb, 2); + cnt -= 2 + ps_read_extension_data(gb, ps, ps_extension_id); + } + if (cnt < 0) { + av_log(avctx, AV_LOG_ERROR, "ps extension overflow %d\n", cnt); + goto err; + } + skip_bits(gb, cnt); + } + + ps->enable_ipdopd &= !PS_BASELINE; + + //Fix up envelopes + if (!ps->num_env || ps->border_position[ps->num_env] < numQMFSlots - 1) { + //Create a fake envelope + int source = ps->num_env ? ps->num_env - 1 : ps->num_env_old - 1; + int b; + if (source >= 0 && source != ps->num_env) { + if (ps->enable_iid) { + memcpy(ps->iid_par+ps->num_env, ps->iid_par+source, sizeof(ps->iid_par[0])); + } + if (ps->enable_icc) { + memcpy(ps->icc_par+ps->num_env, ps->icc_par+source, sizeof(ps->icc_par[0])); + } + if (ps->enable_ipdopd) { + memcpy(ps->ipd_par+ps->num_env, ps->ipd_par+source, sizeof(ps->ipd_par[0])); + memcpy(ps->opd_par+ps->num_env, ps->opd_par+source, sizeof(ps->opd_par[0])); + } + } + if (ps->enable_iid){ + for (b = 0; b < ps->nr_iid_par; b++) { + if (FFABS(ps->iid_par[ps->num_env][b]) > 7 + 8 * ps->iid_quant) { + av_log(avctx, AV_LOG_ERROR, "iid_par invalid\n"); + goto err; + } + } + } + if (ps->enable_icc){ + for (b = 0; b < ps->nr_iid_par; b++) { + if (ps->icc_par[ps->num_env][b] > 7U) { + av_log(avctx, AV_LOG_ERROR, "icc_par invalid\n"); + goto err; + } + } + } + ps->num_env++; + ps->border_position[ps->num_env] = numQMFSlots - 1; + } + + + ps->is34bands_old = ps->is34bands; + if (!PS_BASELINE && (ps->enable_iid || ps->enable_icc)) + ps->is34bands = (ps->enable_iid && ps->nr_iid_par == 34) || + (ps->enable_icc && ps->nr_icc_par == 34); + + //Baseline + if (!ps->enable_ipdopd) { + memset(ps->ipd_par, 0, sizeof(ps->ipd_par)); + memset(ps->opd_par, 0, sizeof(ps->opd_par)); + } + + if (header) + ps->start = 1; + + bits_consumed = get_bits_count(gb) - bit_count_start; + if (bits_consumed <= bits_left) { + skip_bits_long(gb_host, bits_consumed); + return bits_consumed; + } + av_log(avctx, AV_LOG_ERROR, "Expected to read %d PS bits actually read %d.\n", bits_left, bits_consumed); +err: + ps->start = 0; + skip_bits_long(gb_host, bits_left); + memset(ps->iid_par, 0, sizeof(ps->iid_par)); + memset(ps->icc_par, 0, sizeof(ps->icc_par)); + memset(ps->ipd_par, 0, sizeof(ps->ipd_par)); + memset(ps->opd_par, 0, sizeof(ps->opd_par)); + return bits_left; +} + +#define PS_INIT_VLC_STATIC(num, nb_bits, size) \ + INIT_VLC_STATIC(&vlc_ps[num], nb_bits, ps_tmp[num].table_size / ps_tmp[num].elem_size, \ + ps_tmp[num].ps_bits, 1, 1, \ + ps_tmp[num].ps_codes, ps_tmp[num].elem_size, ps_tmp[num].elem_size, \ + size); + +#define PS_VLC_ROW(name) \ + { name ## _codes, name ## _bits, sizeof(name ## _codes), sizeof(name ## _codes[0]) } + +static av_cold void ps_init_common(void) +{ + // Syntax initialization + static const struct { + const void *ps_codes, *ps_bits; + const unsigned int table_size, elem_size; + } ps_tmp[] = { + PS_VLC_ROW(huff_iid_df1), + PS_VLC_ROW(huff_iid_dt1), + PS_VLC_ROW(huff_iid_df0), + PS_VLC_ROW(huff_iid_dt0), + PS_VLC_ROW(huff_icc_df), + PS_VLC_ROW(huff_icc_dt), + PS_VLC_ROW(huff_ipd_df), + PS_VLC_ROW(huff_ipd_dt), + PS_VLC_ROW(huff_opd_df), + PS_VLC_ROW(huff_opd_dt), + }; + + PS_INIT_VLC_STATIC(0, 9, 1544); + PS_INIT_VLC_STATIC(1, 9, 832); + PS_INIT_VLC_STATIC(2, 9, 1024); + PS_INIT_VLC_STATIC(3, 9, 1036); + PS_INIT_VLC_STATIC(4, 9, 544); + PS_INIT_VLC_STATIC(5, 9, 544); + PS_INIT_VLC_STATIC(6, 5, 32); + PS_INIT_VLC_STATIC(7, 5, 32); + PS_INIT_VLC_STATIC(8, 5, 32); + PS_INIT_VLC_STATIC(9, 5, 32); +} + +av_cold void ff_ps_init_common(void) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, ps_init_common); +} diff -Nru ffmpeg-4.2.2/libavcodec/aacpsdata.c ffmpeg-4.4/libavcodec/aacpsdata.c --- ffmpeg-4.2.2/libavcodec/aacpsdata.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacpsdata.c 2021-04-08 21:28:39.000000000 +0000 @@ -142,22 +142,17 @@ }; ///Table 8.48 -static const int8_t k_to_i_20[] = { +const int8_t ff_k_to_i_20[] = { 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19 }; ///Table 8.49 -static const int8_t k_to_i_34[] = { +const int8_t ff_k_to_i_34[] = { 0, 1, 2, 3, 4, 5, 6, 6, 7, 2, 1, 0, 10, 10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 9, 14, 11, 12, 13, 14, 15, 16, 13, 16, 17, 18, 19, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33 }; - -static const INTFLOAT g1_Q2[] = { - Q31(0.0f), Q31(0.01899487526049f), Q31(0.0f), Q31(-0.07293139167538f), - Q31(0.0f), Q31(0.30596630545168f), Q31(0.5f) -}; diff -Nru ffmpeg-4.2.2/libavcodec/aacps_fixed_tablegen.h ffmpeg-4.4/libavcodec/aacps_fixed_tablegen.h --- ffmpeg-4.2.2/libavcodec/aacps_fixed_tablegen.h 2018-07-17 09:27:39.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacps_fixed_tablegen.h 2021-04-08 21:28:39.000000000 +0000 @@ -36,7 +36,12 @@ #else #include "libavutil/common.h" #include "libavutil/mathematics.h" -#include "libavutil/mem.h" +#ifdef BUILD_TABLES +#undef DECLARE_ALIGNED +#define DECLARE_ALIGNED(align, type, variable) type variable +#else +#include "libavutil/mem_internal.h" +#endif #include "aac_defines.h" #include "libavutil/softfloat.h" diff -Nru ffmpeg-4.2.2/libavcodec/aacps.h ffmpeg-4.4/libavcodec/aacps.h --- ffmpeg-4.2.2/libavcodec/aacps.h 2018-07-17 09:27:39.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacps.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,8 @@ #include +#include "libavutil/mem_internal.h" + #include "aacpsdsp.h" #include "avcodec.h" #include "get_bits.h" @@ -37,8 +39,13 @@ #define PS_MAX_DELAY 14 #define PS_AP_LINKS 3 #define PS_MAX_AP_DELAY 5 +#define PS_BASELINE 0 ///< Operate in Baseline PS mode + ///< Baseline implies 10 or 20 stereo bands, + ///< mixing mode A, and no ipd/opd -typedef struct PSContext { +#define numQMFSlots 32 //numTimeSlots * RATE + +typedef struct PSCommonContext { int start; int enable_iid; int iid_quant; @@ -60,6 +67,10 @@ int8_t opd_par[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; ///< Overall Phase Difference Parameters int is34bands; int is34bands_old; +} PSCommonContext; + +typedef struct PSContext { + PSCommonContext common; DECLARE_ALIGNED(16, INTFLOAT, in_buf)[5][44][2]; DECLARE_ALIGNED(16, INTFLOAT, delay)[PS_MAX_SSB][PS_QMF_TIME_SLOTS + PS_MAX_DELAY][2]; @@ -78,9 +89,14 @@ PSDSPContext dsp; } PSContext; +extern const int8_t ff_k_to_i_20[]; +extern const int8_t ff_k_to_i_34[]; + +void ff_ps_init_common(void); void AAC_RENAME(ff_ps_init)(void); void AAC_RENAME(ff_ps_ctx_init)(PSContext *ps); -int AAC_RENAME(ff_ps_read_data)(AVCodecContext *avctx, GetBitContext *gb, PSContext *ps, int bits_left); +int ff_ps_read_data(AVCodecContext *avctx, GetBitContext *gb, + PSCommonContext *ps, int bits_left); int AAC_RENAME(ff_ps_apply)(AVCodecContext *avctx, PSContext *ps, INTFLOAT L[2][38][64], INTFLOAT R[2][38][64], int top); #endif /* AVCODEC_AACPS_H */ diff -Nru ffmpeg-4.2.2/libavcodec/aacps_tablegen_template.c ffmpeg-4.4/libavcodec/aacps_tablegen_template.c --- ffmpeg-4.2.2/libavcodec/aacps_tablegen_template.c 2018-07-17 09:27:39.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacps_tablegen_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,7 @@ */ #include +#define BUILD_TABLES #define CONFIG_HARDCODED_TABLES 0 #include "aac_defines.h" diff -Nru ffmpeg-4.2.2/libavcodec/aacsbr.c ffmpeg-4.4/libavcodec/aacsbr.c --- ffmpeg-4.2.2/libavcodec/aacsbr.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacsbr.c 2021-04-08 21:28:39.000000000 +0000 @@ -31,7 +31,6 @@ #include "sbr.h" #include "aacsbr.h" #include "aacsbrdata.h" -#include "aacsbr_tablegen.h" #include "fft.h" #include "internal.h" #include "aacps.h" @@ -39,6 +38,7 @@ #include "libavutil/internal.h" #include "libavutil/libm.h" #include "libavutil/avassert.h" +#include "libavutil/mem_internal.h" #include #include diff -Nru ffmpeg-4.2.2/libavcodec/aacsbrdata.h ffmpeg-4.4/libavcodec/aacsbrdata.h --- ffmpeg-4.2.2/libavcodec/aacsbrdata.h 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacsbrdata.h 2021-04-08 21:28:39.000000000 +0000 @@ -29,7 +29,7 @@ #define AVCODEC_AACSBRDATA_H #include -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "aac_defines.h" ///< Huffman tables for SBR @@ -532,4 +532,171 @@ {Q31(-0.01053049862020f), Q31(-0.66959058036166f)}, {Q31(-0.91266367957293f), Q31(-0.11522938140034f)}, }; +///< window coefficients for analysis/synthesis QMF banks +static DECLARE_ALIGNED(32, INTFLOAT, sbr_qmf_window_ds)[320]; +/* This table contains redundancy: It is symmetric about the entry #320 + * with the exception of entries 384 and 512 which are negated. */ +static const DECLARE_ALIGNED(32, INTFLOAT, sbr_qmf_window_us)[640] = { + Q31( 0.0000000000f), Q31(-0.0005525286f), Q31(-0.0005617692f), Q31(-0.0004947518f), + Q31(-0.0004875227f), Q31(-0.0004893791f), Q31(-0.0005040714f), Q31(-0.0005226564f), + Q31(-0.0005466565f), Q31(-0.0005677802f), Q31(-0.0005870930f), Q31(-0.0006132747f), + Q31(-0.0006312493f), Q31(-0.0006540333f), Q31(-0.0006777690f), Q31(-0.0006941614f), + Q31(-0.0007157736f), Q31(-0.0007255043f), Q31(-0.0007440941f), Q31(-0.0007490598f), + Q31(-0.0007681371f), Q31(-0.0007724848f), Q31(-0.0007834332f), Q31(-0.0007779869f), + Q31(-0.0007803664f), Q31(-0.0007801449f), Q31(-0.0007757977f), Q31(-0.0007630793f), + Q31(-0.0007530001f), Q31(-0.0007319357f), Q31(-0.0007215391f), Q31(-0.0006917937f), + Q31(-0.0006650415f), Q31(-0.0006341594f), Q31(-0.0005946118f), Q31(-0.0005564576f), + Q31(-0.0005145572f), Q31(-0.0004606325f), Q31(-0.0004095121f), Q31(-0.0003501175f), + Q31(-0.0002896981f), Q31(-0.0002098337f), Q31(-0.0001446380f), Q31(-0.0000617334f), + Q31( 0.0000134949f), Q31( 0.0001094383f), Q31( 0.0002043017f), Q31( 0.0002949531f), + Q31( 0.0004026540f), Q31( 0.0005107388f), Q31( 0.0006239376f), Q31( 0.0007458025f), + Q31( 0.0008608443f), Q31( 0.0009885988f), Q31( 0.0011250155f), Q31( 0.0012577884f), + Q31( 0.0013902494f), Q31( 0.0015443219f), Q31( 0.0016868083f), Q31( 0.0018348265f), + Q31( 0.0019841140f), Q31( 0.0021461583f), Q31( 0.0023017254f), Q31( 0.0024625616f), + Q31( 0.0026201758f), Q31( 0.0027870464f), Q31( 0.0029469447f), Q31( 0.0031125420f), + Q31( 0.0032739613f), Q31( 0.0034418874f), Q31( 0.0036008268f), Q31( 0.0037603922f), + Q31( 0.0039207432f), Q31( 0.0040819753f), Q31( 0.0042264269f), Q31( 0.0043730719f), + Q31( 0.0045209852f), Q31( 0.0046606460f), Q31( 0.0047932560f), Q31( 0.0049137603f), + Q31( 0.0050393022f), Q31( 0.0051407353f), Q31( 0.0052461166f), Q31( 0.0053471681f), + Q31( 0.0054196775f), Q31( 0.0054876040f), Q31( 0.0055475714f), Q31( 0.0055938023f), + Q31( 0.0056220643f), Q31( 0.0056455196f), Q31( 0.0056389199f), Q31( 0.0056266114f), + Q31( 0.0055917128f), Q31( 0.0055404363f), Q31( 0.0054753783f), Q31( 0.0053838975f), + Q31( 0.0052715758f), Q31( 0.0051382275f), Q31( 0.0049839687f), Q31( 0.0048109469f), + Q31( 0.0046039530f), Q31( 0.0043801861f), Q31( 0.0041251642f), Q31( 0.0038456408f), + Q31( 0.0035401246f), Q31( 0.0032091885f), Q31( 0.0028446757f), Q31( 0.0024508540f), + Q31( 0.0020274176f), Q31( 0.0015784682f), Q31( 0.0010902329f), Q31( 0.0005832264f), + Q31( 0.0000276045f), Q31(-0.0005464280f), Q31(-0.0011568135f), Q31(-0.0018039472f), + Q31(-0.0024826723f), Q31(-0.0031933778f), Q31(-0.0039401124f), Q31(-0.0047222596f), + Q31(-0.0055337211f), Q31(-0.0063792293f), Q31(-0.0072615816f), Q31(-0.0081798233f), + Q31(-0.0091325329f), Q31(-0.0101150215f), Q31(-0.0111315548f), Q31(-0.0121849995f), + Q31( 0.0132718220f), Q31( 0.0143904666f), Q31( 0.0155405553f), Q31( 0.0167324712f), + Q31( 0.0179433381f), Q31( 0.0191872431f), Q31( 0.0204531793f), Q31( 0.0217467550f), + Q31( 0.0230680169f), Q31( 0.0244160992f), Q31( 0.0257875847f), Q31( 0.0271859429f), + Q31( 0.0286072173f), Q31( 0.0300502657f), Q31( 0.0315017608f), Q31( 0.0329754081f), + Q31( 0.0344620948f), Q31( 0.0359697560f), Q31( 0.0374812850f), Q31( 0.0390053679f), + Q31( 0.0405349170f), Q31( 0.0420649094f), Q31( 0.0436097542f), Q31( 0.0451488405f), + Q31( 0.0466843027f), Q31( 0.0482165720f), Q31( 0.0497385755f), Q31( 0.0512556155f), + Q31( 0.0527630746f), Q31( 0.0542452768f), Q31( 0.0557173648f), Q31( 0.0571616450f), + Q31( 0.0585915683f), Q31( 0.0599837480f), Q31( 0.0613455171f), Q31( 0.0626857808f), + Q31( 0.0639715898f), Q31( 0.0652247106f), Q31( 0.0664367512f), Q31( 0.0676075985f), + Q31( 0.0687043828f), Q31( 0.0697630244f), Q31( 0.0707628710f), Q31( 0.0717002673f), + Q31( 0.0725682583f), Q31( 0.0733620255f), Q31( 0.0741003642f), Q31( 0.0747452558f), + Q31( 0.0753137336f), Q31( 0.0758008358f), Q31( 0.0761992479f), Q31( 0.0764992170f), + Q31( 0.0767093490f), Q31( 0.0768173975f), Q31( 0.0768230011f), Q31( 0.0767204924f), + Q31( 0.0765050718f), Q31( 0.0761748321f), Q31( 0.0757305756f), Q31( 0.0751576255f), + Q31( 0.0744664394f), Q31( 0.0736406005f), Q31( 0.0726774642f), Q31( 0.0715826364f), + Q31( 0.0703533073f), Q31( 0.0689664013f), Q31( 0.0674525021f), Q31( 0.0657690668f), + Q31( 0.0639444805f), Q31( 0.0619602779f), Q31( 0.0598166570f), Q31( 0.0575152691f), + Q31( 0.0550460034f), Q31( 0.0524093821f), Q31( 0.0495978676f), Q31( 0.0466303305f), + Q31( 0.0434768782f), Q31( 0.0401458278f), Q31( 0.0366418116f), Q31( 0.0329583930f), + Q31( 0.0290824006f), Q31( 0.0250307561f), Q31( 0.0207997072f), Q31( 0.0163701258f), + Q31( 0.0117623832f), Q31( 0.0069636862f), Q31( 0.0019765601f), Q31(-0.0032086896f), + Q31(-0.0085711749f), Q31(-0.0141288827f), Q31(-0.0198834129f), Q31(-0.0258227288f), + Q31(-0.0319531274f), Q31(-0.0382776572f), Q31(-0.0447806821f), Q31(-0.0514804176f), + Q31(-0.0583705326f), Q31(-0.0654409853f), Q31(-0.0726943300f), Q31(-0.0801372934f), + Q31(-0.0877547536f), Q31(-0.0955533352f), Q31(-0.1035329531f), Q31(-0.1116826931f), + Q31(-0.1200077984f), Q31(-0.1285002850f), Q31(-0.1371551761f), Q31(-0.1459766491f), + Q31(-0.1549607071f), Q31(-0.1640958855f), Q31(-0.1733808172f), Q31(-0.1828172548f), + Q31(-0.1923966745f), Q31(-0.2021250176f), Q31(-0.2119735853f), Q31(-0.2219652696f), + Q31(-0.2320690870f), Q31(-0.2423016884f), Q31(-0.2526480309f), Q31(-0.2631053299f), + Q31(-0.2736634040f), Q31(-0.2843214189f), Q31(-0.2950716717f), Q31(-0.3059098575f), + Q31(-0.3168278913f), Q31(-0.3278113727f), Q31(-0.3388722693f), Q31(-0.3499914122f), + Q31( 0.3611589903f), Q31( 0.3723795546f), Q31( 0.3836350013f), Q31( 0.3949211761f), + Q31( 0.4062317676f), Q31( 0.4175696896f), Q31( 0.4289119920f), Q31( 0.4402553754f), + Q31( 0.4515996535f), Q31( 0.4629308085f), Q31( 0.4742453214f), Q31( 0.4855253091f), + Q31( 0.4967708254f), Q31( 0.5079817500f), Q31( 0.5191234970f), Q31( 0.5302240895f), + Q31( 0.5412553448f), Q31( 0.5522051258f), Q31( 0.5630789140f), Q31( 0.5738524131f), + Q31( 0.5845403235f), Q31( 0.5951123086f), Q31( 0.6055783538f), Q31( 0.6159109932f), + Q31( 0.6261242695f), Q31( 0.6361980107f), Q31( 0.6461269695f), Q31( 0.6559016302f), + Q31( 0.6655139880f), Q31( 0.6749663190f), Q31( 0.6842353293f), Q31( 0.6933282376f), + Q31( 0.7022388719f), Q31( 0.7109410426f), Q31( 0.7194462634f), Q31( 0.7277448900f), + Q31( 0.7358211758f), Q31( 0.7436827863f), Q31( 0.7513137456f), Q31( 0.7587080760f), + Q31( 0.7658674865f), Q31( 0.7727780881f), Q31( 0.7794287519f), Q31( 0.7858353120f), + Q31( 0.7919735841f), Q31( 0.7978466413f), Q31( 0.8034485751f), Q31( 0.8087695004f), + Q31( 0.8138191270f), Q31( 0.8185776004f), Q31( 0.8230419890f), Q31( 0.8272275347f), + Q31( 0.8311038457f), Q31( 0.8346937361f), Q31( 0.8379717337f), Q31( 0.8409541392f), + Q31( 0.8436238281f), Q31( 0.8459818469f), Q31( 0.8480315777f), Q31( 0.8497805198f), + Q31( 0.8511971524f), Q31( 0.8523047035f), Q31( 0.8531020949f), Q31( 0.8535720573f), + Q31( 0.8537385600f), Q31( 0.8535720573f), Q31( 0.8531020949f), Q31( 0.8523047035f), + Q31( 0.8511971524f), Q31( 0.8497805198f), Q31( 0.8480315777f), Q31( 0.8459818469f), + Q31( 0.8436238281f), Q31( 0.8409541392f), Q31( 0.8379717337f), Q31( 0.8346937361f), + Q31( 0.8311038457f), Q31( 0.8272275347f), Q31( 0.8230419890f), Q31( 0.8185776004f), + Q31( 0.8138191270f), Q31( 0.8087695004f), Q31( 0.8034485751f), Q31( 0.7978466413f), + Q31( 0.7919735841f), Q31( 0.7858353120f), Q31( 0.7794287519f), Q31( 0.7727780881f), + Q31( 0.7658674865f), Q31( 0.7587080760f), Q31( 0.7513137456f), Q31( 0.7436827863f), + Q31( 0.7358211758f), Q31( 0.7277448900f), Q31( 0.7194462634f), Q31( 0.7109410426f), + Q31( 0.7022388719f), Q31( 0.6933282376f), Q31( 0.6842353293f), Q31( 0.6749663190f), + Q31( 0.6655139880f), Q31( 0.6559016302f), Q31( 0.6461269695f), Q31( 0.6361980107f), + Q31( 0.6261242695f), Q31( 0.6159109932f), Q31( 0.6055783538f), Q31( 0.5951123086f), + Q31( 0.5845403235f), Q31( 0.5738524131f), Q31( 0.5630789140f), Q31( 0.5522051258f), + Q31( 0.5412553448f), Q31( 0.5302240895f), Q31( 0.5191234970f), Q31( 0.5079817500f), + Q31( 0.4967708254f), Q31( 0.4855253091f), Q31( 0.4742453214f), Q31( 0.4629308085f), + Q31( 0.4515996535f), Q31( 0.4402553754f), Q31( 0.4289119920f), Q31( 0.4175696896f), + Q31( 0.4062317676f), Q31( 0.3949211761f), Q31( 0.3836350013f), Q31( 0.3723795546f), + -Q31( 0.3611589903f), Q31(-0.3499914122f), Q31(-0.3388722693f), Q31(-0.3278113727f), + Q31(-0.3168278913f), Q31(-0.3059098575f), Q31(-0.2950716717f), Q31(-0.2843214189f), + Q31(-0.2736634040f), Q31(-0.2631053299f), Q31(-0.2526480309f), Q31(-0.2423016884f), + Q31(-0.2320690870f), Q31(-0.2219652696f), Q31(-0.2119735853f), Q31(-0.2021250176f), + Q31(-0.1923966745f), Q31(-0.1828172548f), Q31(-0.1733808172f), Q31(-0.1640958855f), + Q31(-0.1549607071f), Q31(-0.1459766491f), Q31(-0.1371551761f), Q31(-0.1285002850f), + Q31(-0.1200077984f), Q31(-0.1116826931f), Q31(-0.1035329531f), Q31(-0.0955533352f), + Q31(-0.0877547536f), Q31(-0.0801372934f), Q31(-0.0726943300f), Q31(-0.0654409853f), + Q31(-0.0583705326f), Q31(-0.0514804176f), Q31(-0.0447806821f), Q31(-0.0382776572f), + Q31(-0.0319531274f), Q31(-0.0258227288f), Q31(-0.0198834129f), Q31(-0.0141288827f), + Q31(-0.0085711749f), Q31(-0.0032086896f), Q31( 0.0019765601f), Q31( 0.0069636862f), + Q31( 0.0117623832f), Q31( 0.0163701258f), Q31( 0.0207997072f), Q31( 0.0250307561f), + Q31( 0.0290824006f), Q31( 0.0329583930f), Q31( 0.0366418116f), Q31( 0.0401458278f), + Q31( 0.0434768782f), Q31( 0.0466303305f), Q31( 0.0495978676f), Q31( 0.0524093821f), + Q31( 0.0550460034f), Q31( 0.0575152691f), Q31( 0.0598166570f), Q31( 0.0619602779f), + Q31( 0.0639444805f), Q31( 0.0657690668f), Q31( 0.0674525021f), Q31( 0.0689664013f), + Q31( 0.0703533073f), Q31( 0.0715826364f), Q31( 0.0726774642f), Q31( 0.0736406005f), + Q31( 0.0744664394f), Q31( 0.0751576255f), Q31( 0.0757305756f), Q31( 0.0761748321f), + Q31( 0.0765050718f), Q31( 0.0767204924f), Q31( 0.0768230011f), Q31( 0.0768173975f), + Q31( 0.0767093490f), Q31( 0.0764992170f), Q31( 0.0761992479f), Q31( 0.0758008358f), + Q31( 0.0753137336f), Q31( 0.0747452558f), Q31( 0.0741003642f), Q31( 0.0733620255f), + Q31( 0.0725682583f), Q31( 0.0717002673f), Q31( 0.0707628710f), Q31( 0.0697630244f), + Q31( 0.0687043828f), Q31( 0.0676075985f), Q31( 0.0664367512f), Q31( 0.0652247106f), + Q31( 0.0639715898f), Q31( 0.0626857808f), Q31( 0.0613455171f), Q31( 0.0599837480f), + Q31( 0.0585915683f), Q31( 0.0571616450f), Q31( 0.0557173648f), Q31( 0.0542452768f), + Q31( 0.0527630746f), Q31( 0.0512556155f), Q31( 0.0497385755f), Q31( 0.0482165720f), + Q31( 0.0466843027f), Q31( 0.0451488405f), Q31( 0.0436097542f), Q31( 0.0420649094f), + Q31( 0.0405349170f), Q31( 0.0390053679f), Q31( 0.0374812850f), Q31( 0.0359697560f), + Q31( 0.0344620948f), Q31( 0.0329754081f), Q31( 0.0315017608f), Q31( 0.0300502657f), + Q31( 0.0286072173f), Q31( 0.0271859429f), Q31( 0.0257875847f), Q31( 0.0244160992f), + Q31( 0.0230680169f), Q31( 0.0217467550f), Q31( 0.0204531793f), Q31( 0.0191872431f), + Q31( 0.0179433381f), Q31( 0.0167324712f), Q31( 0.0155405553f), Q31( 0.0143904666f), + -Q31( 0.0132718220f), Q31(-0.0121849995f), Q31(-0.0111315548f), Q31(-0.0101150215f), + Q31(-0.0091325329f), Q31(-0.0081798233f), Q31(-0.0072615816f), Q31(-0.0063792293f), + Q31(-0.0055337211f), Q31(-0.0047222596f), Q31(-0.0039401124f), Q31(-0.0031933778f), + Q31(-0.0024826723f), Q31(-0.0018039472f), Q31(-0.0011568135f), Q31(-0.0005464280f), + Q31( 0.0000276045f), Q31( 0.0005832264f), Q31( 0.0010902329f), Q31( 0.0015784682f), + Q31( 0.0020274176f), Q31( 0.0024508540f), Q31( 0.0028446757f), Q31( 0.0032091885f), + Q31( 0.0035401246f), Q31( 0.0038456408f), Q31( 0.0041251642f), Q31( 0.0043801861f), + Q31( 0.0046039530f), Q31( 0.0048109469f), Q31( 0.0049839687f), Q31( 0.0051382275f), + Q31( 0.0052715758f), Q31( 0.0053838975f), Q31( 0.0054753783f), Q31( 0.0055404363f), + Q31( 0.0055917128f), Q31( 0.0056266114f), Q31( 0.0056389199f), Q31( 0.0056455196f), + Q31( 0.0056220643f), Q31( 0.0055938023f), Q31( 0.0055475714f), Q31( 0.0054876040f), + Q31( 0.0054196775f), Q31( 0.0053471681f), Q31( 0.0052461166f), Q31( 0.0051407353f), + Q31( 0.0050393022f), Q31( 0.0049137603f), Q31( 0.0047932560f), Q31( 0.0046606460f), + Q31( 0.0045209852f), Q31( 0.0043730719f), Q31( 0.0042264269f), Q31( 0.0040819753f), + Q31( 0.0039207432f), Q31( 0.0037603922f), Q31( 0.0036008268f), Q31( 0.0034418874f), + Q31( 0.0032739613f), Q31( 0.0031125420f), Q31( 0.0029469447f), Q31( 0.0027870464f), + Q31( 0.0026201758f), Q31( 0.0024625616f), Q31( 0.0023017254f), Q31( 0.0021461583f), + Q31( 0.0019841140f), Q31( 0.0018348265f), Q31( 0.0016868083f), Q31( 0.0015443219f), + Q31( 0.0013902494f), Q31( 0.0012577884f), Q31( 0.0011250155f), Q31( 0.0009885988f), + Q31( 0.0008608443f), Q31( 0.0007458025f), Q31( 0.0006239376f), Q31( 0.0005107388f), + Q31( 0.0004026540f), Q31( 0.0002949531f), Q31( 0.0002043017f), Q31( 0.0001094383f), + Q31( 0.0000134949f), Q31(-0.0000617334f), Q31(-0.0001446380f), Q31(-0.0002098337f), + Q31(-0.0002896981f), Q31(-0.0003501175f), Q31(-0.0004095121f), Q31(-0.0004606325f), + Q31(-0.0005145572f), Q31(-0.0005564576f), Q31(-0.0005946118f), Q31(-0.0006341594f), + Q31(-0.0006650415f), Q31(-0.0006917937f), Q31(-0.0007215391f), Q31(-0.0007319357f), + Q31(-0.0007530001f), Q31(-0.0007630793f), Q31(-0.0007757977f), Q31(-0.0007801449f), + Q31(-0.0007803664f), Q31(-0.0007779869f), Q31(-0.0007834332f), Q31(-0.0007724848f), + Q31(-0.0007681371f), Q31(-0.0007490598f), Q31(-0.0007440941f), Q31(-0.0007255043f), + Q31(-0.0007157736f), Q31(-0.0006941614f), Q31(-0.0006777690f), Q31(-0.0006540333f), + Q31(-0.0006312493f), Q31(-0.0006132747f), Q31(-0.0005870930f), Q31(-0.0005677802f), + Q31(-0.0005466565f), Q31(-0.0005226564f), Q31(-0.0005040714f), Q31(-0.0004893791f), + Q31(-0.0004875227f), Q31(-0.0004947518f), Q31(-0.0005617692f), Q31(-0.0005525286f), +}; + #endif /* AVCODEC_AACSBRDATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/aacsbr_fixed.c ffmpeg-4.4/libavcodec/aacsbr_fixed.c --- ffmpeg-4.2.2/libavcodec/aacsbr_fixed.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacsbr_fixed.c 2021-04-08 21:28:39.000000000 +0000 @@ -60,7 +60,6 @@ #include "sbr.h" #include "aacsbr.h" #include "aacsbrdata.h" -#include "aacsbr_fixed_tablegen.h" #include "fft.h" #include "aacps.h" #include "sbrdsp.h" diff -Nru ffmpeg-4.2.2/libavcodec/aacsbr_fixed_tablegen.h ffmpeg-4.4/libavcodec/aacsbr_fixed_tablegen.h --- ffmpeg-4.2.2/libavcodec/aacsbr_fixed_tablegen.h 2018-07-17 09:27:39.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacsbr_fixed_tablegen.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -/* - * Header file for hardcoded AAC SBR windows - * - * Copyright (c) 2014 Reimar Döffinger - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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_AACSBR_FIXED_TABLEGEN_H -#define AVCODEC_AACSBR_FIXED_TABLEGEN_H - -#include "aacsbr_tablegen_common.h" - -#endif /* AVCODEC_AACSBR_FIXED_TABLEGEN_H */ diff -Nru ffmpeg-4.2.2/libavcodec/aacsbr_tablegen_common.h ffmpeg-4.4/libavcodec/aacsbr_tablegen_common.h --- ffmpeg-4.2.2/libavcodec/aacsbr_tablegen_common.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacsbr_tablegen_common.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -/* - * Header file for hardcoded AAC SBR windows - * - * Copyright (c) 2014 Reimar Döffinger - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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_AACSBR_TABLEGEN_COMMON_H -#define AVCODEC_AACSBR_TABLEGEN_COMMON_H -#include "aac_defines.h" -#include "libavutil/mem.h" - -///< window coefficients for analysis/synthesis QMF banks -static DECLARE_ALIGNED(32, INTFLOAT, sbr_qmf_window_ds)[320]; -static DECLARE_ALIGNED(32, INTFLOAT, sbr_qmf_window_us)[640] = { - Q31( 0.0000000000f), Q31(-0.0005525286f), Q31(-0.0005617692f), Q31(-0.0004947518f), - Q31(-0.0004875227f), Q31(-0.0004893791f), Q31(-0.0005040714f), Q31(-0.0005226564f), - Q31(-0.0005466565f), Q31(-0.0005677802f), Q31(-0.0005870930f), Q31(-0.0006132747f), - Q31(-0.0006312493f), Q31(-0.0006540333f), Q31(-0.0006777690f), Q31(-0.0006941614f), - Q31(-0.0007157736f), Q31(-0.0007255043f), Q31(-0.0007440941f), Q31(-0.0007490598f), - Q31(-0.0007681371f), Q31(-0.0007724848f), Q31(-0.0007834332f), Q31(-0.0007779869f), - Q31(-0.0007803664f), Q31(-0.0007801449f), Q31(-0.0007757977f), Q31(-0.0007630793f), - Q31(-0.0007530001f), Q31(-0.0007319357f), Q31(-0.0007215391f), Q31(-0.0006917937f), - Q31(-0.0006650415f), Q31(-0.0006341594f), Q31(-0.0005946118f), Q31(-0.0005564576f), - Q31(-0.0005145572f), Q31(-0.0004606325f), Q31(-0.0004095121f), Q31(-0.0003501175f), - Q31(-0.0002896981f), Q31(-0.0002098337f), Q31(-0.0001446380f), Q31(-0.0000617334f), - Q31( 0.0000134949f), Q31( 0.0001094383f), Q31( 0.0002043017f), Q31( 0.0002949531f), - Q31( 0.0004026540f), Q31( 0.0005107388f), Q31( 0.0006239376f), Q31( 0.0007458025f), - Q31( 0.0008608443f), Q31( 0.0009885988f), Q31( 0.0011250155f), Q31( 0.0012577884f), - Q31( 0.0013902494f), Q31( 0.0015443219f), Q31( 0.0016868083f), Q31( 0.0018348265f), - Q31( 0.0019841140f), Q31( 0.0021461583f), Q31( 0.0023017254f), Q31( 0.0024625616f), - Q31( 0.0026201758f), Q31( 0.0027870464f), Q31( 0.0029469447f), Q31( 0.0031125420f), - Q31( 0.0032739613f), Q31( 0.0034418874f), Q31( 0.0036008268f), Q31( 0.0037603922f), - Q31( 0.0039207432f), Q31( 0.0040819753f), Q31( 0.0042264269f), Q31( 0.0043730719f), - Q31( 0.0045209852f), Q31( 0.0046606460f), Q31( 0.0047932560f), Q31( 0.0049137603f), - Q31( 0.0050393022f), Q31( 0.0051407353f), Q31( 0.0052461166f), Q31( 0.0053471681f), - Q31( 0.0054196775f), Q31( 0.0054876040f), Q31( 0.0055475714f), Q31( 0.0055938023f), - Q31( 0.0056220643f), Q31( 0.0056455196f), Q31( 0.0056389199f), Q31( 0.0056266114f), - Q31( 0.0055917128f), Q31( 0.0055404363f), Q31( 0.0054753783f), Q31( 0.0053838975f), - Q31( 0.0052715758f), Q31( 0.0051382275f), Q31( 0.0049839687f), Q31( 0.0048109469f), - Q31( 0.0046039530f), Q31( 0.0043801861f), Q31( 0.0041251642f), Q31( 0.0038456408f), - Q31( 0.0035401246f), Q31( 0.0032091885f), Q31( 0.0028446757f), Q31( 0.0024508540f), - Q31( 0.0020274176f), Q31( 0.0015784682f), Q31( 0.0010902329f), Q31( 0.0005832264f), - Q31( 0.0000276045f), Q31(-0.0005464280f), Q31(-0.0011568135f), Q31(-0.0018039472f), - Q31(-0.0024826723f), Q31(-0.0031933778f), Q31(-0.0039401124f), Q31(-0.0047222596f), - Q31(-0.0055337211f), Q31(-0.0063792293f), Q31(-0.0072615816f), Q31(-0.0081798233f), - Q31(-0.0091325329f), Q31(-0.0101150215f), Q31(-0.0111315548f), Q31(-0.0121849995f), - Q31( 0.0132718220f), Q31( 0.0143904666f), Q31( 0.0155405553f), Q31( 0.0167324712f), - Q31( 0.0179433381f), Q31( 0.0191872431f), Q31( 0.0204531793f), Q31( 0.0217467550f), - Q31( 0.0230680169f), Q31( 0.0244160992f), Q31( 0.0257875847f), Q31( 0.0271859429f), - Q31( 0.0286072173f), Q31( 0.0300502657f), Q31( 0.0315017608f), Q31( 0.0329754081f), - Q31( 0.0344620948f), Q31( 0.0359697560f), Q31( 0.0374812850f), Q31( 0.0390053679f), - Q31( 0.0405349170f), Q31( 0.0420649094f), Q31( 0.0436097542f), Q31( 0.0451488405f), - Q31( 0.0466843027f), Q31( 0.0482165720f), Q31( 0.0497385755f), Q31( 0.0512556155f), - Q31( 0.0527630746f), Q31( 0.0542452768f), Q31( 0.0557173648f), Q31( 0.0571616450f), - Q31( 0.0585915683f), Q31( 0.0599837480f), Q31( 0.0613455171f), Q31( 0.0626857808f), - Q31( 0.0639715898f), Q31( 0.0652247106f), Q31( 0.0664367512f), Q31( 0.0676075985f), - Q31( 0.0687043828f), Q31( 0.0697630244f), Q31( 0.0707628710f), Q31( 0.0717002673f), - Q31( 0.0725682583f), Q31( 0.0733620255f), Q31( 0.0741003642f), Q31( 0.0747452558f), - Q31( 0.0753137336f), Q31( 0.0758008358f), Q31( 0.0761992479f), Q31( 0.0764992170f), - Q31( 0.0767093490f), Q31( 0.0768173975f), Q31( 0.0768230011f), Q31( 0.0767204924f), - Q31( 0.0765050718f), Q31( 0.0761748321f), Q31( 0.0757305756f), Q31( 0.0751576255f), - Q31( 0.0744664394f), Q31( 0.0736406005f), Q31( 0.0726774642f), Q31( 0.0715826364f), - Q31( 0.0703533073f), Q31( 0.0689664013f), Q31( 0.0674525021f), Q31( 0.0657690668f), - Q31( 0.0639444805f), Q31( 0.0619602779f), Q31( 0.0598166570f), Q31( 0.0575152691f), - Q31( 0.0550460034f), Q31( 0.0524093821f), Q31( 0.0495978676f), Q31( 0.0466303305f), - Q31( 0.0434768782f), Q31( 0.0401458278f), Q31( 0.0366418116f), Q31( 0.0329583930f), - Q31( 0.0290824006f), Q31( 0.0250307561f), Q31( 0.0207997072f), Q31( 0.0163701258f), - Q31( 0.0117623832f), Q31( 0.0069636862f), Q31( 0.0019765601f), Q31(-0.0032086896f), - Q31(-0.0085711749f), Q31(-0.0141288827f), Q31(-0.0198834129f), Q31(-0.0258227288f), - Q31(-0.0319531274f), Q31(-0.0382776572f), Q31(-0.0447806821f), Q31(-0.0514804176f), - Q31(-0.0583705326f), Q31(-0.0654409853f), Q31(-0.0726943300f), Q31(-0.0801372934f), - Q31(-0.0877547536f), Q31(-0.0955533352f), Q31(-0.1035329531f), Q31(-0.1116826931f), - Q31(-0.1200077984f), Q31(-0.1285002850f), Q31(-0.1371551761f), Q31(-0.1459766491f), - Q31(-0.1549607071f), Q31(-0.1640958855f), Q31(-0.1733808172f), Q31(-0.1828172548f), - Q31(-0.1923966745f), Q31(-0.2021250176f), Q31(-0.2119735853f), Q31(-0.2219652696f), - Q31(-0.2320690870f), Q31(-0.2423016884f), Q31(-0.2526480309f), Q31(-0.2631053299f), - Q31(-0.2736634040f), Q31(-0.2843214189f), Q31(-0.2950716717f), Q31(-0.3059098575f), - Q31(-0.3168278913f), Q31(-0.3278113727f), Q31(-0.3388722693f), Q31(-0.3499914122f), - Q31( 0.3611589903f), Q31( 0.3723795546f), Q31( 0.3836350013f), Q31( 0.3949211761f), - Q31( 0.4062317676f), Q31( 0.4175696896f), Q31( 0.4289119920f), Q31( 0.4402553754f), - Q31( 0.4515996535f), Q31( 0.4629308085f), Q31( 0.4742453214f), Q31( 0.4855253091f), - Q31( 0.4967708254f), Q31( 0.5079817500f), Q31( 0.5191234970f), Q31( 0.5302240895f), - Q31( 0.5412553448f), Q31( 0.5522051258f), Q31( 0.5630789140f), Q31( 0.5738524131f), - Q31( 0.5845403235f), Q31( 0.5951123086f), Q31( 0.6055783538f), Q31( 0.6159109932f), - Q31( 0.6261242695f), Q31( 0.6361980107f), Q31( 0.6461269695f), Q31( 0.6559016302f), - Q31( 0.6655139880f), Q31( 0.6749663190f), Q31( 0.6842353293f), Q31( 0.6933282376f), - Q31( 0.7022388719f), Q31( 0.7109410426f), Q31( 0.7194462634f), Q31( 0.7277448900f), - Q31( 0.7358211758f), Q31( 0.7436827863f), Q31( 0.7513137456f), Q31( 0.7587080760f), - Q31( 0.7658674865f), Q31( 0.7727780881f), Q31( 0.7794287519f), Q31( 0.7858353120f), - Q31( 0.7919735841f), Q31( 0.7978466413f), Q31( 0.8034485751f), Q31( 0.8087695004f), - Q31( 0.8138191270f), Q31( 0.8185776004f), Q31( 0.8230419890f), Q31( 0.8272275347f), - Q31( 0.8311038457f), Q31( 0.8346937361f), Q31( 0.8379717337f), Q31( 0.8409541392f), - Q31( 0.8436238281f), Q31( 0.8459818469f), Q31( 0.8480315777f), Q31( 0.8497805198f), - Q31( 0.8511971524f), Q31( 0.8523047035f), Q31( 0.8531020949f), Q31( 0.8535720573f), - Q31( 0.8537385600f), -}; - -#endif /* AVCODEC_AACSBR_TABLEGEN_COMMON_H */ diff -Nru ffmpeg-4.2.2/libavcodec/aacsbr_tablegen.h ffmpeg-4.4/libavcodec/aacsbr_tablegen.h --- ffmpeg-4.2.2/libavcodec/aacsbr_tablegen.h 2018-07-17 09:27:39.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacsbr_tablegen.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -/* - * Header file for hardcoded AAC SBR windows - * - * Copyright (c) 2014 Reimar Döffinger - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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_AACSBR_TABLEGEN_H -#define AVCODEC_AACSBR_TABLEGEN_H - -#include "aacsbr_tablegen_common.h" - -#endif /* AVCODEC_AACSBR_TABLEGEN_H */ diff -Nru ffmpeg-4.2.2/libavcodec/aacsbr_template.c ffmpeg-4.4/libavcodec/aacsbr_template.c --- ffmpeg-4.2.2/libavcodec/aacsbr_template.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aacsbr_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -37,10 +37,6 @@ static av_cold void aacsbr_tableinit(void) { int n; - for (n = 1; n < 320; n++) - sbr_qmf_window_us[320 + n] = sbr_qmf_window_us[320 - n]; - sbr_qmf_window_us[384] = -sbr_qmf_window_us[384]; - sbr_qmf_window_us[512] = -sbr_qmf_window_us[512]; for (n = 0; n < 320; n++) sbr_qmf_window_ds[n] = sbr_qmf_window_us[2*n]; @@ -957,7 +953,7 @@ skip_bits_long(gb, *num_bits_left); // bs_fill_bits *num_bits_left = 0; } else { - *num_bits_left -= AAC_RENAME(ff_ps_read_data)(ac->avctx, gb, &sbr->ps, *num_bits_left); + *num_bits_left -= ff_ps_read_data(ac->avctx, gb, &sbr->ps.common, *num_bits_left); ac->avctx->profile = FF_PROFILE_AAC_HE_V2; } break; @@ -1548,7 +1544,7 @@ } if (ac->oc[1].m4ac.ps == 1) { - if (sbr->ps.start) { + if (sbr->ps.common.start) { AAC_RENAME(ff_ps_apply)(ac->avctx, &sbr->ps, sbr->X[0], sbr->X[1], sbr->kx[1] + sbr->m[1]); } else { memcpy(sbr->X[1], sbr->X[0], sizeof(sbr->X[0])); diff -Nru ffmpeg-4.2.2/libavcodec/aactab.c ffmpeg-4.4/libavcodec/aactab.c --- ffmpeg-4.2.2/libavcodec/aactab.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aactab.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,20 +27,39 @@ * @author Maxim Gavrilov ( maxim.gavrilov gmail com ) */ +#include "config.h" #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" +#include "libavutil/thread.h" #include "aac.h" +#include "aactab.h" #include float ff_aac_pow2sf_tab[428]; float ff_aac_pow34sf_tab[428]; +#if CONFIG_AAC_ENCODER || CONFIG_AAC_DECODER +#include "kbdwin.h" +#include "sinewin.h" + DECLARE_ALIGNED(32, float, ff_aac_kbd_long_1024)[1024]; DECLARE_ALIGNED(32, float, ff_aac_kbd_short_128)[128]; -DECLARE_ALIGNED(32, float, ff_aac_kbd_long_960)[960]; -DECLARE_ALIGNED(32, float, ff_aac_kbd_short_120)[120]; -DECLARE_ALIGNED(32, int, ff_aac_kbd_long_1024_fixed)[1024]; -DECLARE_ALIGNED(32, int, ff_aac_kbd_short_128_fixed)[128]; + +static av_cold void aac_float_common_init(void) +{ + ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024); + ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128); + ff_init_ff_sine_windows(10); + ff_init_ff_sine_windows(7); +} + +av_cold void ff_aac_float_common_init(void) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, aac_float_common_init); +} +#endif const uint8_t ff_aac_num_swb_1024[] = { 41, 41, 47, 49, 49, 51, 47, 47, 43, 43, 43, 40, 40 @@ -3280,3 +3299,53 @@ 0xffecff1c, 0xffed391e, 0xffed740c, 0xffedafb1, 0xffedebe1, 0xffee287d, 0xffee654e, 0xffeea23f, }; + +static void aac_tableinit(void) +{ + /* 2^(i/16) for 0 <= i <= 15 */ + static const float exp2_lut[] = { + 1.00000000000000000000, + 1.04427378242741384032, + 1.09050773266525765921, + 1.13878863475669165370, + 1.18920711500272106672, + 1.24185781207348404859, + 1.29683955465100966593, + 1.35425554693689272830, + 1.41421356237309504880, + 1.47682614593949931139, + 1.54221082540794082361, + 1.61049033194925430818, + 1.68179283050742908606, + 1.75625216037329948311, + 1.83400808640934246349, + 1.91520656139714729387, + }; + float t1 = 8.8817841970012523233890533447265625e-16; // 2^(-50) + float t2 = 3.63797880709171295166015625e-12; // 2^(-38) + int t1_inc_cur, t2_inc_cur; + int t1_inc_prev = 0; + int t2_inc_prev = 8; + + for (int i = 0; i < 428; i++) { + t1_inc_cur = 4 * (i % 4); + t2_inc_cur = (8 + 3*i) % 16; + if (t1_inc_cur < t1_inc_prev) + t1 *= 2; + if (t2_inc_cur < t2_inc_prev) + t2 *= 2; + // A much more efficient and accurate way of doing: + // ff_aac_pow2sf_tab[i] = pow(2, (i - POW_SF2_ZERO) / 4.0); + // ff_aac_pow34sf_tab[i] = pow(ff_aac_pow2sf_tab[i], 3.0/4.0); + ff_aac_pow2sf_tab[i] = t1 * exp2_lut[t1_inc_cur]; + ff_aac_pow34sf_tab[i] = t2 * exp2_lut[t2_inc_cur]; + t1_inc_prev = t1_inc_cur; + t2_inc_prev = t2_inc_cur; + } +} + +void ff_aac_tableinit(void) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, aac_tableinit); +} diff -Nru ffmpeg-4.2.2/libavcodec/aactab.h ffmpeg-4.4/libavcodec/aactab.h --- ffmpeg-4.2.2/libavcodec/aactab.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aactab.h 2021-04-08 21:28:39.000000000 +0000 @@ -30,7 +30,7 @@ #ifndef AVCODEC_AACTAB_H #define AVCODEC_AACTAB_H -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "aac.h" #include @@ -42,51 +42,7 @@ extern float ff_aac_pow2sf_tab[428]; extern float ff_aac_pow34sf_tab[428]; -static inline void ff_aac_tableinit(void) -{ - int i; - - /* 2^(i/16) for 0 <= i <= 15 */ - static const float exp2_lut[] = { - 1.00000000000000000000, - 1.04427378242741384032, - 1.09050773266525765921, - 1.13878863475669165370, - 1.18920711500272106672, - 1.24185781207348404859, - 1.29683955465100966593, - 1.35425554693689272830, - 1.41421356237309504880, - 1.47682614593949931139, - 1.54221082540794082361, - 1.61049033194925430818, - 1.68179283050742908606, - 1.75625216037329948311, - 1.83400808640934246349, - 1.91520656139714729387, - }; - float t1 = 8.8817841970012523233890533447265625e-16; // 2^(-50) - float t2 = 3.63797880709171295166015625e-12; // 2^(-38) - int t1_inc_cur, t2_inc_cur; - int t1_inc_prev = 0; - int t2_inc_prev = 8; - - for (i = 0; i < 428; i++) { - t1_inc_cur = 4 * (i % 4); - t2_inc_cur = (8 + 3*i) % 16; - if (t1_inc_cur < t1_inc_prev) - t1 *= 2; - if (t2_inc_cur < t2_inc_prev) - t2 *= 2; - // A much more efficient and accurate way of doing: - // ff_aac_pow2sf_tab[i] = pow(2, (i - POW_SF2_ZERO) / 4.0); - // ff_aac_pow34sf_tab[i] = pow(ff_aac_pow2sf_tab[i], 3.0/4.0); - ff_aac_pow2sf_tab[i] = t1 * exp2_lut[t1_inc_cur]; - ff_aac_pow34sf_tab[i] = t2 * exp2_lut[t2_inc_cur]; - t1_inc_prev = t1_inc_cur; - t2_inc_prev = t2_inc_cur; - } -} +void ff_aac_tableinit(void); /* @name ltp_coef * Table of the LTP coefficients @@ -136,17 +92,15 @@ */ DECLARE_ALIGNED(32, extern float, ff_aac_kbd_long_1024)[1024]; DECLARE_ALIGNED(32, extern float, ff_aac_kbd_short_128)[128]; -DECLARE_ALIGNED(32, extern float, ff_aac_kbd_long_960)[960]; -DECLARE_ALIGNED(32, extern float, ff_aac_kbd_short_120)[120]; -DECLARE_ALIGNED(32, extern int, ff_aac_kbd_long_1024_fixed)[1024]; -DECLARE_ALIGNED(32, extern int, ff_aac_kbd_long_512_fixed)[512]; -DECLARE_ALIGNED(32, extern int, ff_aac_kbd_short_128_fixed)[128]; DECLARE_ALIGNED(32, extern const float, ff_aac_eld_window_512)[1920]; DECLARE_ALIGNED(32, extern const int, ff_aac_eld_window_512_fixed)[1920]; DECLARE_ALIGNED(32, extern const float, ff_aac_eld_window_480)[1800]; DECLARE_ALIGNED(32, extern const int, ff_aac_eld_window_480_fixed)[1800]; // @} +/* Initializes data shared between float decoder and encoder. */ +void ff_aac_float_common_init(void); + /* @name number of scalefactor window bands for long and short transform windows respectively * @{ */ @@ -167,9 +121,9 @@ extern const uint8_t * const ff_aac_spectral_bits [11]; extern const uint16_t ff_aac_spectral_sizes[11]; -extern const float *ff_aac_codebook_vectors[]; -extern const float *ff_aac_codebook_vector_vals[]; -extern const uint16_t *ff_aac_codebook_vector_idx[]; +extern const float *const ff_aac_codebook_vectors[]; +extern const float *const ff_aac_codebook_vector_vals[]; +extern const uint16_t *const ff_aac_codebook_vector_idx[]; extern const uint16_t * const ff_swb_offset_1024[13]; extern const uint16_t * const ff_swb_offset_960 [13]; diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/hevcdsp_idct_neon.S ffmpeg-4.4/libavcodec/aarch64/hevcdsp_idct_neon.S --- ffmpeg-4.2.2/libavcodec/aarch64/hevcdsp_idct_neon.S 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/hevcdsp_idct_neon.S 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,621 @@ +/* + * ARM NEON optimised IDCT functions for HEVC decoding + * Copyright (c) 2014 Seppo Tomperi + * Copyright (c) 2017 Alexandra Hájková + * + * Ported from arm/hevcdsp_idct_neon.S by + * Copyright (c) 2020 Reimar Döffinger + * Copyright (c) 2020 Josh Dekker + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +const trans, align=4 + .short 64, 83, 64, 36 + .short 89, 75, 50, 18 + .short 90, 87, 80, 70 + .short 57, 43, 25, 9 + .short 90, 90, 88, 85 + .short 82, 78, 73, 67 + .short 61, 54, 46, 38 + .short 31, 22, 13, 4 +endconst + +.macro clip10 in1, in2, c1, c2 + smax \in1, \in1, \c1 + smax \in2, \in2, \c1 + smin \in1, \in1, \c2 + smin \in2, \in2, \c2 +.endm + +function ff_hevc_add_residual_4x4_8_neon, export=1 + ld1 {v0.8h-v1.8h}, [x1] + ld1 {v2.s}[0], [x0], x2 + ld1 {v2.s}[1], [x0], x2 + ld1 {v2.s}[2], [x0], x2 + ld1 {v2.s}[3], [x0], x2 + sub x0, x0, x2, lsl #2 + uxtl v6.8h, v2.8b + uxtl2 v7.8h, v2.16b + sqadd v0.8h, v0.8h, v6.8h + sqadd v1.8h, v1.8h, v7.8h + sqxtun v0.8b, v0.8h + sqxtun2 v0.16b, v1.8h + st1 {v0.s}[0], [x0], x2 + st1 {v0.s}[1], [x0], x2 + st1 {v0.s}[2], [x0], x2 + st1 {v0.s}[3], [x0], x2 + ret +endfunc + +function ff_hevc_add_residual_4x4_10_neon, export=1 + mov x12, x0 + ld1 {v0.8h-v1.8h}, [x1] + ld1 {v2.d}[0], [x12], x2 + ld1 {v2.d}[1], [x12], x2 + ld1 {v3.d}[0], [x12], x2 + sqadd v0.8h, v0.8h, v2.8h + ld1 {v3.d}[1], [x12], x2 + movi v4.8h, #0 + sqadd v1.8h, v1.8h, v3.8h + mvni v5.8h, #0xFC, lsl #8 // movi #0x3FF + clip10 v0.8h, v1.8h, v4.8h, v5.8h + st1 {v0.d}[0], [x0], x2 + st1 {v0.d}[1], [x0], x2 + st1 {v1.d}[0], [x0], x2 + st1 {v1.d}[1], [x0], x2 + ret +endfunc + +function ff_hevc_add_residual_8x8_8_neon, export=1 + add x12, x0, x2 + add x2, x2, x2 + mov x3, #8 +1: subs x3, x3, #2 + ld1 {v2.d}[0], [x0] + ld1 {v2.d}[1], [x12] + uxtl v3.8h, v2.8b + ld1 {v0.8h-v1.8h}, [x1], #32 + uxtl2 v2.8h, v2.16b + sqadd v0.8h, v0.8h, v3.8h + sqadd v1.8h, v1.8h, v2.8h + sqxtun v0.8b, v0.8h + sqxtun2 v0.16b, v1.8h + st1 {v0.d}[0], [x0], x2 + st1 {v0.d}[1], [x12], x2 + bne 1b + ret +endfunc + +function ff_hevc_add_residual_8x8_10_neon, export=1 + add x12, x0, x2 + add x2, x2, x2 + mov x3, #8 + movi v4.8h, #0 + mvni v5.8h, #0xFC, lsl #8 // movi #0x3FF +1: subs x3, x3, #2 + ld1 {v0.8h-v1.8h}, [x1], #32 + ld1 {v2.8h}, [x0] + sqadd v0.8h, v0.8h, v2.8h + ld1 {v3.8h}, [x12] + sqadd v1.8h, v1.8h, v3.8h + clip10 v0.8h, v1.8h, v4.8h, v5.8h + st1 {v0.8h}, [x0], x2 + st1 {v1.8h}, [x12], x2 + bne 1b + ret +endfunc + +function ff_hevc_add_residual_16x16_8_neon, export=1 + mov x3, #16 + add x12, x0, x2 + add x2, x2, x2 +1: subs x3, x3, #2 + ld1 {v16.16b}, [x0] + ld1 {v0.8h-v3.8h}, [x1], #64 + ld1 {v19.16b}, [x12] + uxtl v17.8h, v16.8b + uxtl2 v18.8h, v16.16b + uxtl v20.8h, v19.8b + uxtl2 v21.8h, v19.16b + sqadd v0.8h, v0.8h, v17.8h + sqadd v1.8h, v1.8h, v18.8h + sqadd v2.8h, v2.8h, v20.8h + sqadd v3.8h, v3.8h, v21.8h + sqxtun v0.8b, v0.8h + sqxtun2 v0.16b, v1.8h + sqxtun v1.8b, v2.8h + sqxtun2 v1.16b, v3.8h + st1 {v0.16b}, [x0], x2 + st1 {v1.16b}, [x12], x2 + bne 1b + ret +endfunc + +function ff_hevc_add_residual_16x16_10_neon, export=1 + mov x3, #16 + movi v20.8h, #0 + mvni v21.8h, #0xFC, lsl #8 // movi #0x3FF + add x12, x0, x2 + add x2, x2, x2 +1: subs x3, x3, #2 + ld1 {v16.8h-v17.8h}, [x0] + ld1 {v0.8h-v3.8h}, [x1], #64 + sqadd v0.8h, v0.8h, v16.8h + ld1 {v18.8h-v19.8h}, [x12] + sqadd v1.8h, v1.8h, v17.8h + sqadd v2.8h, v2.8h, v18.8h + sqadd v3.8h, v3.8h, v19.8h + clip10 v0.8h, v1.8h, v20.8h, v21.8h + clip10 v2.8h, v3.8h, v20.8h, v21.8h + st1 {v0.8h-v1.8h}, [x0], x2 + st1 {v2.8h-v3.8h}, [x12], x2 + bne 1b + ret +endfunc + +function ff_hevc_add_residual_32x32_8_neon, export=1 + add x12, x0, x2 + add x2, x2, x2 + mov x3, #32 +1: subs x3, x3, #2 + ld1 {v20.16b, v21.16b}, [x0] + uxtl v16.8h, v20.8b + uxtl2 v17.8h, v20.16b + ld1 {v22.16b, v23.16b}, [x12] + uxtl v18.8h, v21.8b + uxtl2 v19.8h, v21.16b + uxtl v20.8h, v22.8b + ld1 {v0.8h-v3.8h}, [x1], #64 + ld1 {v4.8h-v7.8h}, [x1], #64 + uxtl2 v21.8h, v22.16b + uxtl v22.8h, v23.8b + uxtl2 v23.8h, v23.16b + sqadd v0.8h, v0.8h, v16.8h + sqadd v1.8h, v1.8h, v17.8h + sqadd v2.8h, v2.8h, v18.8h + sqadd v3.8h, v3.8h, v19.8h + sqadd v4.8h, v4.8h, v20.8h + sqadd v5.8h, v5.8h, v21.8h + sqadd v6.8h, v6.8h, v22.8h + sqadd v7.8h, v7.8h, v23.8h + sqxtun v0.8b, v0.8h + sqxtun2 v0.16b, v1.8h + sqxtun v1.8b, v2.8h + sqxtun2 v1.16b, v3.8h + sqxtun v2.8b, v4.8h + sqxtun2 v2.16b, v5.8h + st1 {v0.16b, v1.16b}, [x0], x2 + sqxtun v3.8b, v6.8h + sqxtun2 v3.16b, v7.8h + st1 {v2.16b, v3.16b}, [x12], x2 + bne 1b + ret +endfunc + +function ff_hevc_add_residual_32x32_10_neon, export=1 + mov x3, #32 + movi v20.8h, #0 + mvni v21.8h, #0xFC, lsl #8 // movi #0x3FF +1: subs x3, x3, #1 + ld1 {v0.8h-v3.8h}, [x1], #64 + ld1 {v16.8h-v19.8h}, [x0] + sqadd v0.8h, v0.8h, v16.8h + sqadd v1.8h, v1.8h, v17.8h + sqadd v2.8h, v2.8h, v18.8h + sqadd v3.8h, v3.8h, v19.8h + clip10 v0.8h, v1.8h, v20.8h, v21.8h + clip10 v2.8h, v3.8h, v20.8h, v21.8h + st1 {v0.8h-v3.8h}, [x0], x2 + bne 1b + ret +endfunc + +.macro sum_sub out, in, c, op, p + .ifc \op, + + smlal\p \out, \in, \c + .else + smlsl\p \out, \in, \c + .endif +.endm + +.macro fixsqrshrn d, dt, n, m + .ifc \dt, .8h + sqrshrn2 \d\dt, \n\().4s, \m + .else + sqrshrn \n\().4h, \n\().4s, \m + mov \d\().d[0], \n\().d[0] + .endif +.endm + +// uses and clobbers v28-v31 as temp registers +.macro tr_4x4_8 in0, in1, in2, in3, out0, out1, out2, out3, p1, p2 + sshll\p1 v28.4s, \in0, #6 + mov v29.16b, v28.16b + smull\p1 v30.4s, \in1, v0.h[1] + smull\p1 v31.4s, \in1, v0.h[3] + smlal\p2 v28.4s, \in2, v0.h[0] //e0 + smlsl\p2 v29.4s, \in2, v0.h[0] //e1 + smlal\p2 v30.4s, \in3, v0.h[3] //o0 + smlsl\p2 v31.4s, \in3, v0.h[1] //o1 + + add \out0, v28.4s, v30.4s + add \out1, v29.4s, v31.4s + sub \out2, v29.4s, v31.4s + sub \out3, v28.4s, v30.4s +.endm + +.macro transpose8_4x4 r0, r1, r2, r3 + trn1 v2.8h, \r0\().8h, \r1\().8h + trn2 v3.8h, \r0\().8h, \r1\().8h + trn1 v4.8h, \r2\().8h, \r3\().8h + trn2 v5.8h, \r2\().8h, \r3\().8h + trn1 \r0\().4s, v2.4s, v4.4s + trn2 \r2\().4s, v2.4s, v4.4s + trn1 \r1\().4s, v3.4s, v5.4s + trn2 \r3\().4s, v3.4s, v5.4s +.endm + +.macro transpose_8x8 r0, r1, r2, r3, r4, r5, r6, r7 + transpose8_4x4 \r0, \r1, \r2, \r3 + transpose8_4x4 \r4, \r5, \r6, \r7 +.endm + +.macro tr_8x4 shift, in0,in0t, in1,in1t, in2,in2t, in3,in3t, in4,in4t, in5,in5t, in6,in6t, in7,in7t, p1, p2 + tr_4x4_8 \in0\in0t, \in2\in2t, \in4\in4t, \in6\in6t, v24.4s, v25.4s, v26.4s, v27.4s, \p1, \p2 + + smull\p1 v30.4s, \in1\in1t, v0.h[6] + smull\p1 v28.4s, \in1\in1t, v0.h[4] + smull\p1 v29.4s, \in1\in1t, v0.h[5] + sum_sub v30.4s, \in3\in3t, v0.h[4], -, \p1 + sum_sub v28.4s, \in3\in3t, v0.h[5], +, \p1 + sum_sub v29.4s, \in3\in3t, v0.h[7], -, \p1 + + sum_sub v30.4s, \in5\in5t, v0.h[7], +, \p2 + sum_sub v28.4s, \in5\in5t, v0.h[6], +, \p2 + sum_sub v29.4s, \in5\in5t, v0.h[4], -, \p2 + + sum_sub v30.4s, \in7\in7t, v0.h[5], +, \p2 + sum_sub v28.4s, \in7\in7t, v0.h[7], +, \p2 + sum_sub v29.4s, \in7\in7t, v0.h[6], -, \p2 + + add v31.4s, v26.4s, v30.4s + sub v26.4s, v26.4s, v30.4s + fixsqrshrn \in2,\in2t, v31, \shift + + + smull\p1 v31.4s, \in1\in1t, v0.h[7] + sum_sub v31.4s, \in3\in3t, v0.h[6], -, \p1 + sum_sub v31.4s, \in5\in5t, v0.h[5], +, \p2 + sum_sub v31.4s, \in7\in7t, v0.h[4], -, \p2 + fixsqrshrn \in5,\in5t, v26, \shift + + + add v26.4s, v24.4s, v28.4s + sub v24.4s, v24.4s, v28.4s + add v28.4s, v25.4s, v29.4s + sub v25.4s, v25.4s, v29.4s + add v30.4s, v27.4s, v31.4s + sub v27.4s, v27.4s, v31.4s + + fixsqrshrn \in0,\in0t, v26, \shift + fixsqrshrn \in7,\in7t, v24, \shift + fixsqrshrn \in1,\in1t, v28, \shift + fixsqrshrn \in6,\in6t, v25, \shift + fixsqrshrn \in3,\in3t, v30, \shift + fixsqrshrn \in4,\in4t, v27, \shift +.endm + +.macro idct_8x8 bitdepth +function ff_hevc_idct_8x8_\bitdepth\()_neon, export=1 +//x0 - coeffs + mov x1, x0 + ld1 {v16.8h-v19.8h}, [x1], #64 + ld1 {v20.8h-v23.8h}, [x1] + + movrel x1, trans + ld1 {v0.8h}, [x1] + + tr_8x4 7, v16,.4h, v17,.4h, v18,.4h, v19,.4h, v20,.4h, v21,.4h, v22,.4h, v23,.4h + tr_8x4 7, v16,.8h, v17,.8h, v18,.8h, v19,.8h, v20,.8h, v21,.8h, v22,.8h, v23,.8h, 2, 2 + + transpose_8x8 v16, v17, v18, v19, v20, v21, v22, v23 + + tr_8x4 20 - \bitdepth, v16,.4h, v17,.4h, v18,.4h, v19,.4h, v16,.8h, v17,.8h, v18,.8h, v19,.8h, , 2 + tr_8x4 20 - \bitdepth, v20,.4h, v21,.4h, v22,.4h, v23,.4h, v20,.8h, v21,.8h, v22,.8h, v23,.8h, , 2 + + transpose_8x8 v16, v17, v18, v19, v20, v21, v22, v23 + + mov x1, x0 + st1 {v16.8h-v19.8h}, [x1], #64 + st1 {v20.8h-v23.8h}, [x1] + + ret +endfunc +.endm + +.macro butterfly e, o, tmp_p, tmp_m + add \tmp_p, \e, \o + sub \tmp_m, \e, \o +.endm + +.macro tr16_8x4 in0, in1, in2, in3, offset + tr_4x4_8 \in0\().4h, \in1\().4h, \in2\().4h, \in3\().4h, v24.4s, v25.4s, v26.4s, v27.4s + + smull2 v28.4s, \in0\().8h, v0.h[4] + smull2 v29.4s, \in0\().8h, v0.h[5] + smull2 v30.4s, \in0\().8h, v0.h[6] + smull2 v31.4s, \in0\().8h, v0.h[7] + sum_sub v28.4s, \in1\().8h, v0.h[5], +, 2 + sum_sub v29.4s, \in1\().8h, v0.h[7], -, 2 + sum_sub v30.4s, \in1\().8h, v0.h[4], -, 2 + sum_sub v31.4s, \in1\().8h, v0.h[6], -, 2 + + sum_sub v28.4s, \in2\().8h, v0.h[6], +, 2 + sum_sub v29.4s, \in2\().8h, v0.h[4], -, 2 + sum_sub v30.4s, \in2\().8h, v0.h[7], +, 2 + sum_sub v31.4s, \in2\().8h, v0.h[5], +, 2 + + sum_sub v28.4s, \in3\().8h, v0.h[7], +, 2 + sum_sub v29.4s, \in3\().8h, v0.h[6], -, 2 + sum_sub v30.4s, \in3\().8h, v0.h[5], +, 2 + sum_sub v31.4s, \in3\().8h, v0.h[4], -, 2 + + butterfly v24.4s, v28.4s, v16.4s, v23.4s + butterfly v25.4s, v29.4s, v17.4s, v22.4s + butterfly v26.4s, v30.4s, v18.4s, v21.4s + butterfly v27.4s, v31.4s, v19.4s, v20.4s + add x4, sp, #\offset + st1 {v16.4s-v19.4s}, [x4], #64 + st1 {v20.4s-v23.4s}, [x4] +.endm + +.macro load16 in0, in1, in2, in3 + ld1 {\in0}[0], [x1], x2 + ld1 {\in0}[1], [x3], x2 + ld1 {\in1}[0], [x1], x2 + ld1 {\in1}[1], [x3], x2 + ld1 {\in2}[0], [x1], x2 + ld1 {\in2}[1], [x3], x2 + ld1 {\in3}[0], [x1], x2 + ld1 {\in3}[1], [x3], x2 +.endm + +.macro add_member in, t0, t1, t2, t3, t4, t5, t6, t7, op0, op1, op2, op3, op4, op5, op6, op7, p + sum_sub v21.4s, \in, \t0, \op0, \p + sum_sub v22.4s, \in, \t1, \op1, \p + sum_sub v23.4s, \in, \t2, \op2, \p + sum_sub v24.4s, \in, \t3, \op3, \p + sum_sub v25.4s, \in, \t4, \op4, \p + sum_sub v26.4s, \in, \t5, \op5, \p + sum_sub v27.4s, \in, \t6, \op6, \p + sum_sub v28.4s, \in, \t7, \op7, \p +.endm + +.macro butterfly16 in0, in1, in2, in3, in4, in5, in6, in7 + add v20.4s, \in0, \in1 + sub \in0, \in0, \in1 + add \in1, \in2, \in3 + sub \in2, \in2, \in3 + add \in3, \in4, \in5 + sub \in4, \in4, \in5 + add \in5, \in6, \in7 + sub \in6, \in6, \in7 +.endm + +.macro store16 in0, in1, in2, in3, rx + st1 {\in0}[0], [x1], x2 + st1 {\in0}[1], [x3], \rx + st1 {\in1}[0], [x1], x2 + st1 {\in1}[1], [x3], \rx + st1 {\in2}[0], [x1], x2 + st1 {\in2}[1], [x3], \rx + st1 {\in3}[0], [x1], x2 + st1 {\in3}[1], [x3], \rx +.endm + +.macro scale out0, out1, out2, out3, in0, in1, in2, in3, in4, in5, in6, in7, shift + sqrshrn \out0\().4h, \in0, \shift + sqrshrn2 \out0\().8h, \in1, \shift + sqrshrn \out1\().4h, \in2, \shift + sqrshrn2 \out1\().8h, \in3, \shift + sqrshrn \out2\().4h, \in4, \shift + sqrshrn2 \out2\().8h, \in5, \shift + sqrshrn \out3\().4h, \in6, \shift + sqrshrn2 \out3\().8h, \in7, \shift +.endm + +.macro transpose16_4x4_2 r0, r1, r2, r3 + // lower halves + trn1 v2.4h, \r0\().4h, \r1\().4h + trn2 v3.4h, \r0\().4h, \r1\().4h + trn1 v4.4h, \r2\().4h, \r3\().4h + trn2 v5.4h, \r2\().4h, \r3\().4h + trn1 v6.2s, v2.2s, v4.2s + trn2 v7.2s, v2.2s, v4.2s + trn1 v2.2s, v3.2s, v5.2s + trn2 v4.2s, v3.2s, v5.2s + mov \r0\().d[0], v6.d[0] + mov \r2\().d[0], v7.d[0] + mov \r1\().d[0], v2.d[0] + mov \r3\().d[0], v4.d[0] + + // upper halves in reverse order + trn1 v2.8h, \r3\().8h, \r2\().8h + trn2 v3.8h, \r3\().8h, \r2\().8h + trn1 v4.8h, \r1\().8h, \r0\().8h + trn2 v5.8h, \r1\().8h, \r0\().8h + trn1 v6.4s, v2.4s, v4.4s + trn2 v7.4s, v2.4s, v4.4s + trn1 v2.4s, v3.4s, v5.4s + trn2 v4.4s, v3.4s, v5.4s + mov \r3\().d[1], v6.d[1] + mov \r1\().d[1], v7.d[1] + mov \r2\().d[1], v2.d[1] + mov \r0\().d[1], v4.d[1] +.endm + +.macro tr_16x4 name, shift, offset, step +function func_tr_16x4_\name + mov x1, x5 + add x3, x5, #(\step * 64) + mov x2, #(\step * 128) + load16 v16.d, v17.d, v18.d, v19.d + movrel x1, trans + ld1 {v0.8h}, [x1] + + tr16_8x4 v16, v17, v18, v19, \offset + + add x1, x5, #(\step * 32) + add x3, x5, #(\step * 3 *32) + mov x2, #(\step * 128) + load16 v20.d, v17.d, v18.d, v19.d + movrel x1, trans, 16 + ld1 {v1.8h}, [x1] + smull v21.4s, v20.4h, v1.h[0] + smull v22.4s, v20.4h, v1.h[1] + smull v23.4s, v20.4h, v1.h[2] + smull v24.4s, v20.4h, v1.h[3] + smull v25.4s, v20.4h, v1.h[4] + smull v26.4s, v20.4h, v1.h[5] + smull v27.4s, v20.4h, v1.h[6] + smull v28.4s, v20.4h, v1.h[7] + + add_member v20.8h, v1.h[1], v1.h[4], v1.h[7], v1.h[5], v1.h[2], v1.h[0], v1.h[3], v1.h[6], +, +, +, -, -, -, -, -, 2 + add_member v17.4h, v1.h[2], v1.h[7], v1.h[3], v1.h[1], v1.h[6], v1.h[4], v1.h[0], v1.h[5], +, +, -, -, -, +, +, + + add_member v17.8h, v1.h[3], v1.h[5], v1.h[1], v1.h[7], v1.h[0], v1.h[6], v1.h[2], v1.h[4], +, -, -, +, +, +, -, -, 2 + add_member v18.4h, v1.h[4], v1.h[2], v1.h[6], v1.h[0], v1.h[7], v1.h[1], v1.h[5], v1.h[3], +, -, -, +, -, -, +, + + add_member v18.8h, v1.h[5], v1.h[0], v1.h[4], v1.h[6], v1.h[1], v1.h[3], v1.h[7], v1.h[2], +, -, +, +, -, +, +, -, 2 + add_member v19.4h, v1.h[6], v1.h[3], v1.h[0], v1.h[2], v1.h[5], v1.h[7], v1.h[4], v1.h[1], +, -, +, -, +, +, -, + + add_member v19.8h, v1.h[7], v1.h[6], v1.h[5], v1.h[4], v1.h[3], v1.h[2], v1.h[1], v1.h[0], +, -, +, -, +, -, +, -, 2 + + add x4, sp, #\offset + ld1 {v16.4s-v19.4s}, [x4], #64 + + butterfly16 v16.4s, v21.4s, v17.4s, v22.4s, v18.4s, v23.4s, v19.4s, v24.4s + scale v29, v30, v31, v24, v20.4s, v16.4s, v21.4s, v17.4s, v22.4s, v18.4s, v23.4s, v19.4s, \shift + transpose16_4x4_2 v29, v30, v31, v24 + mov x1, x6 + add x3, x6, #(24 +3*32) + mov x2, #32 + mov x4, #-32 + store16 v29.d, v30.d, v31.d, v24.d, x4 + + add x4, sp, #(\offset + 64) + ld1 {v16.4s-v19.4s}, [x4] + butterfly16 v16.4s, v25.4s, v17.4s, v26.4s, v18.4s, v27.4s, v19.4s, v28.4s + scale v29, v30, v31, v20, v20.4s, v16.4s, v25.4s, v17.4s, v26.4s, v18.4s, v27.4s, v19.4s, \shift + transpose16_4x4_2 v29, v30, v31, v20 + + add x1, x6, #8 + add x3, x6, #(16 + 3 * 32) + mov x2, #32 + mov x4, #-32 + store16 v29.d, v30.d, v31.d, v20.d, x4 + + ret +endfunc +.endm + +.macro idct_16x16 bitdepth +function ff_hevc_idct_16x16_\bitdepth\()_neon, export=1 +//r0 - coeffs + mov x15, x30 + + // allocate a temp buffer + sub sp, sp, #640 + +.irp i, 0, 1, 2, 3 + add x5, x0, #(8 * \i) + add x6, sp, #(8 * \i * 16) + bl func_tr_16x4_firstpass +.endr + +.irp i, 0, 1, 2, 3 + add x5, sp, #(8 * \i) + add x6, x0, #(8 * \i * 16) + bl func_tr_16x4_secondpass_\bitdepth +.endr + + add sp, sp, #640 + + mov x30, x15 + ret +endfunc +.endm + +idct_8x8 8 +idct_8x8 10 + +tr_16x4 firstpass, 7, 512, 1 +tr_16x4 secondpass_8, 20 - 8, 512, 1 +tr_16x4 secondpass_10, 20 - 10, 512, 1 + +idct_16x16 8 +idct_16x16 10 + +// void ff_hevc_idct_NxN_dc_DEPTH_neon(int16_t *coeffs) +.macro idct_dc size, bitdepth +function ff_hevc_idct_\size\()x\size\()_dc_\bitdepth\()_neon, export=1 + movi v1.8h, #((1 << (14 - \bitdepth))+1) + ld1r {v4.8h}, [x0] + add v4.8h, v4.8h, v1.8h + sshr v0.8h, v4.8h, #(15 - \bitdepth) + sshr v1.8h, v4.8h, #(15 - \bitdepth) +.if \size > 4 + sshr v2.8h, v4.8h, #(15 - \bitdepth) + sshr v3.8h, v4.8h, #(15 - \bitdepth) +.if \size > 16 /* dc 32x32 */ + mov x2, #4 +1: + subs x2, x2, #1 +.endif + add x12, x0, #64 + mov x13, #128 +.if \size > 8 /* dc 16x16 */ + st1 {v0.8h-v3.8h}, [x0], x13 + st1 {v0.8h-v3.8h}, [x12], x13 + st1 {v0.8h-v3.8h}, [x0], x13 + st1 {v0.8h-v3.8h}, [x12], x13 + st1 {v0.8h-v3.8h}, [x0], x13 + st1 {v0.8h-v3.8h}, [x12], x13 +.endif /* dc 8x8 */ + st1 {v0.8h-v3.8h}, [x0], x13 + st1 {v0.8h-v3.8h}, [x12], x13 +.if \size > 16 /* dc 32x32 */ + bne 1b +.endif +.else /* dc 4x4 */ + st1 {v0.8h-v1.8h}, [x0] +.endif + ret +endfunc +.endm + +idct_dc 4, 8 +idct_dc 4, 10 + +idct_dc 8, 8 +idct_dc 8, 10 + +idct_dc 16, 8 +idct_dc 16, 10 + +idct_dc 32, 8 +idct_dc 32, 10 diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/hevcdsp_init_aarch64.c ffmpeg-4.4/libavcodec/aarch64/hevcdsp_init_aarch64.c --- ffmpeg-4.2.2/libavcodec/aarch64/hevcdsp_init_aarch64.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/hevcdsp_init_aarch64.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2020 Reimar Döffinger + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/aarch64/cpu.h" +#include "libavcodec/hevcdsp.h" + +void ff_hevc_add_residual_4x4_8_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); +void ff_hevc_add_residual_4x4_10_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); +void ff_hevc_add_residual_8x8_8_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); +void ff_hevc_add_residual_8x8_10_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); +void ff_hevc_add_residual_16x16_8_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); +void ff_hevc_add_residual_16x16_10_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); +void ff_hevc_add_residual_32x32_8_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); +void ff_hevc_add_residual_32x32_10_neon(uint8_t *_dst, int16_t *coeffs, + ptrdiff_t stride); +void ff_hevc_idct_8x8_8_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_8x8_10_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_16x16_8_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_16x16_10_neon(int16_t *coeffs, int col_limit); +void ff_hevc_idct_4x4_dc_8_neon(int16_t *coeffs); +void ff_hevc_idct_8x8_dc_8_neon(int16_t *coeffs); +void ff_hevc_idct_16x16_dc_8_neon(int16_t *coeffs); +void ff_hevc_idct_32x32_dc_8_neon(int16_t *coeffs); +void ff_hevc_idct_4x4_dc_10_neon(int16_t *coeffs); +void ff_hevc_idct_8x8_dc_10_neon(int16_t *coeffs); +void ff_hevc_idct_16x16_dc_10_neon(int16_t *coeffs); +void ff_hevc_idct_32x32_dc_10_neon(int16_t *coeffs); +void ff_hevc_sao_band_filter_8x8_8_neon(uint8_t *_dst, uint8_t *_src, + ptrdiff_t stride_dst, ptrdiff_t stride_src, + int16_t *sao_offset_val, int sao_left_class, + int width, int height); + + + +av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) +{ + if (!have_neon(av_get_cpu_flags())) return; + + if (bit_depth == 8) { + c->add_residual[0] = ff_hevc_add_residual_4x4_8_neon; + c->add_residual[1] = ff_hevc_add_residual_8x8_8_neon; + c->add_residual[2] = ff_hevc_add_residual_16x16_8_neon; + c->add_residual[3] = ff_hevc_add_residual_32x32_8_neon; + c->idct[1] = ff_hevc_idct_8x8_8_neon; + c->idct[2] = ff_hevc_idct_16x16_8_neon; + c->idct_dc[0] = ff_hevc_idct_4x4_dc_8_neon; + c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_neon; + c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_neon; + c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_neon; + 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; + c->add_residual[1] = ff_hevc_add_residual_8x8_10_neon; + c->add_residual[2] = ff_hevc_add_residual_16x16_10_neon; + c->add_residual[3] = ff_hevc_add_residual_32x32_10_neon; + c->idct[1] = ff_hevc_idct_8x8_10_neon; + c->idct[2] = ff_hevc_idct_16x16_10_neon; + c->idct_dc[0] = ff_hevc_idct_4x4_dc_10_neon; + c->idct_dc[1] = ff_hevc_idct_8x8_dc_10_neon; + c->idct_dc[2] = ff_hevc_idct_16x16_dc_10_neon; + c->idct_dc[3] = ff_hevc_idct_32x32_dc_10_neon; + } +} diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/hevcdsp_sao_neon.S ffmpeg-4.4/libavcodec/aarch64/hevcdsp_sao_neon.S --- ffmpeg-4.2.2/libavcodec/aarch64/hevcdsp_sao_neon.S 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/hevcdsp_sao_neon.S 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,87 @@ +/* -*-arm64-*- + * vim: syntax=arm64asm + * + * AArch64 NEON optimised SAO functions for HEVC decoding + * + * Copyright (c) 2020 Josh Dekker + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +// void sao_band_filter(uint8_t *_dst, uint8_t *_src, +// ptrdiff_t stride_dst, ptrdiff_t stride_src, +// int16_t *sao_offset_val, int sao_left_class, +// int width, int height) +function ff_hevc_sao_band_filter_8x8_8_neon, export=1 + sub sp, sp, #64 + stp xzr, xzr, [sp] + stp xzr, xzr, [sp, #16] + stp xzr, xzr, [sp, #32] + stp xzr, xzr, [sp, #48] + mov w8, #4 +0: + ldrsh x9, [x4, x8, lsl #1] // x9 = sao_offset_val[k+1] + subs w8, w8, #1 + add w10, w8, w5 // x10 = 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 + // with 8bit LUT. + // + // 00 01 02 03 04 05 06 07 + // +-----------------------------------> + // |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 + bne 2b + // finished line + subs w7, w7, #1 + add x0, x0, x2 // dst += stride_dst + add x1, x1, x3 // src += stride_src + bne 1b + ret +endfunc diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/idctdsp_init_aarch64.c ffmpeg-4.4/libavcodec/aarch64/idctdsp_init_aarch64.c --- ffmpeg-4.2.2/libavcodec/aarch64/idctdsp_init_aarch64.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/idctdsp_init_aarch64.c 2020-07-11 10:39:30.000000000 +0000 @@ -21,6 +21,8 @@ */ #include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" #include "libavcodec/avcodec.h" #include "libavcodec/idctdsp.h" #include "idct.h" @@ -28,7 +30,9 @@ av_cold void ff_idctdsp_init_aarch64(IDCTDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth) { - if (!avctx->lowres && !high_bit_depth) { + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags) && !avctx->lowres && !high_bit_depth) { if (avctx->idct_algo == FF_IDCT_AUTO || avctx->idct_algo == FF_IDCT_SIMPLEAUTO || avctx->idct_algo == FF_IDCT_SIMPLENEON) { diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/Makefile ffmpeg-4.4/libavcodec/aarch64/Makefile --- ffmpeg-4.2.2/libavcodec/aarch64/Makefile 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/Makefile 2021-04-08 21:28:39.000000000 +0000 @@ -6,8 +6,10 @@ OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_init.o OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_init_aarch64.o OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_init_aarch64.o +OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_init_aarch64.o OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_init.o OBJS-$(CONFIG_NEON_CLOBBER_TEST) += aarch64/neontest.o +OBJS-$(CONFIG_PIXBLOCKDSP) += aarch64/pixblockdsp_init_aarch64.o OBJS-$(CONFIG_VIDEODSP) += aarch64/videodsp_init.o OBJS-$(CONFIG_VP8DSP) += aarch64/vp8dsp_init_aarch64.o @@ -21,6 +23,7 @@ OBJS-$(CONFIG_VORBIS_DECODER) += aarch64/vorbisdsp_init.o OBJS-$(CONFIG_VP9_DECODER) += aarch64/vp9dsp_init_10bpp_aarch64.o \ aarch64/vp9dsp_init_12bpp_aarch64.o \ + aarch64/vp9mc_aarch64.o \ aarch64/vp9dsp_init_aarch64.o # ARMv8 optimizations @@ -41,10 +44,10 @@ NEON-OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_neon.o \ aarch64/hpeldsp_neon.o NEON-OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_neon.o -NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_init_aarch64.o \ - aarch64/simple_idct_neon.o +NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/simple_idct_neon.o NEON-OBJS-$(CONFIG_MDCT) += aarch64/mdct_neon.o NEON-OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_neon.o +NEON-OBJS-$(CONFIG_PIXBLOCKDSP) += aarch64/pixblockdsp_neon.o NEON-OBJS-$(CONFIG_VP8DSP) += aarch64/vp8dsp_neon.o # decoders/encoders @@ -58,3 +61,6 @@ aarch64/vp9lpf_neon.o \ aarch64/vp9mc_16bpp_neon.o \ aarch64/vp9mc_neon.o +NEON-OBJS-$(CONFIG_HEVC_DECODER) += aarch64/hevcdsp_idct_neon.o \ + aarch64/hevcdsp_init_aarch64.o \ + aarch64/hevcdsp_sao_neon.o diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/neontest.c ffmpeg-4.4/libavcodec/aarch64/neontest.c --- ffmpeg-4.2.2/libavcodec/aarch64/neontest.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/neontest.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,7 @@ testneonclobbers(avcodec_open2, avctx, codec, options); } +#if FF_API_OLD_ENCDEC wrap(avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, @@ -47,15 +48,6 @@ got_picture_ptr, avpkt); } -wrap(avcodec_decode_subtitle2(AVCodecContext *avctx, - AVSubtitle *sub, - int *got_sub_ptr, - AVPacket *avpkt)) -{ - testneonclobbers(avcodec_decode_subtitle2, avctx, sub, - got_sub_ptr, avpkt); -} - wrap(avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, @@ -65,6 +57,22 @@ got_packet_ptr); } +wrap(avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr)) +{ + testneonclobbers(avcodec_encode_video2, avctx, avpkt, frame, got_packet_ptr); +} +#endif + +wrap(avcodec_decode_subtitle2(AVCodecContext *avctx, + AVSubtitle *sub, + int *got_sub_ptr, + AVPacket *avpkt)) +{ + testneonclobbers(avcodec_decode_subtitle2, avctx, sub, + got_sub_ptr, avpkt); +} + wrap(avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, const AVSubtitle *sub)) @@ -72,12 +80,6 @@ testneonclobbers(avcodec_encode_subtitle, avctx, buf, buf_size, sub); } -wrap(avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, - const AVFrame *frame, int *got_packet_ptr)) -{ - testneonclobbers(avcodec_encode_video2, avctx, avpkt, frame, got_packet_ptr); -} - wrap(avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)) { testneonclobbers(avcodec_send_packet, avctx, avpkt); diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/opusdsp_neon.S ffmpeg-4.4/libavcodec/aarch64/opusdsp_neon.S --- ffmpeg-4.2.2/libavcodec/aarch64/opusdsp_neon.S 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/opusdsp_neon.S 2020-07-11 10:39:30.000000000 +0000 @@ -95,16 +95,16 @@ fmla v3.4s, v7.4s, v2.4s fadd v6.4s, v6.4s, v4.4s - ld1 {v8.4s}, [x0] - fmla v8.4s, v5.4s, v0.4s + ld1 {v4.4s}, [x0] + fmla v4.4s, v5.4s, v0.4s fmul v6.4s, v6.4s, v1.4s fadd v6.4s, v6.4s, v3.4s - fadd v8.4s, v8.4s, v6.4s + fadd v4.4s, v4.4s, v6.4s fmul v3.4s, v7.4s, v2.4s - st1 {v8.4s}, [x0], #16 + st1 {v4.4s}, [x0], #16 subs w3, w3, #4 b.gt 1b diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/pixblockdsp_init_aarch64.c ffmpeg-4.4/libavcodec/aarch64/pixblockdsp_init_aarch64.c --- ffmpeg-4.2.2/libavcodec/aarch64/pixblockdsp_init_aarch64.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/pixblockdsp_init_aarch64.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,46 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/aarch64/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/pixblockdsp.h" + +void ff_get_pixels_neon(int16_t *block, const uint8_t *pixels, + ptrdiff_t stride); +void ff_diff_pixels_neon(int16_t *block, const uint8_t *s1, + const uint8_t *s2, ptrdiff_t stride); + +av_cold void ff_pixblockdsp_init_aarch64(PixblockDSPContext *c, + AVCodecContext *avctx, + unsigned high_bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + if (!high_bit_depth) { + c->get_pixels_unaligned = + c->get_pixels = ff_get_pixels_neon; + } + c->diff_pixels_unaligned = + c->diff_pixels = ff_diff_pixels_neon; + } +} diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/pixblockdsp_neon.S ffmpeg-4.4/libavcodec/aarch64/pixblockdsp_neon.S --- ffmpeg-4.2.2/libavcodec/aarch64/pixblockdsp_neon.S 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/pixblockdsp_neon.S 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020 Martin Storsjo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +function ff_get_pixels_neon, export=1 + mov w3, #8 +1: + ld1 {v0.8b}, [x1], x2 + subs w3, w3, #2 + ld1 {v1.8b}, [x1], x2 + uxtl v0.8h, v0.8b + uxtl v1.8h, v1.8b + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 1b + + ret +endfunc + +function ff_diff_pixels_neon, export=1 + mov w4, #8 +1: + ld1 {v0.8b}, [x1], x3 + ld1 {v1.8b}, [x2], x3 + subs w4, w4, #2 + ld1 {v2.8b}, [x1], x3 + usubl v0.8h, v0.8b, v1.8b + ld1 {v3.8b}, [x2], x3 + usubl v1.8h, v2.8b, v3.8b + st1 {v0.8h, v1.8h}, [x0], #32 + b.gt 1b + + ret +endfunc diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/vp9dsp_init_16bpp_aarch64_template.c ffmpeg-4.4/libavcodec/aarch64/vp9dsp_init_16bpp_aarch64_template.c --- ffmpeg-4.2.2/libavcodec/aarch64/vp9dsp_init_16bpp_aarch64_template.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/vp9dsp_init_16bpp_aarch64_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "libavutil/attributes.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/aarch64/cpu.h" #include "vp9dsp_init.h" diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/vp9dsp_init_aarch64.c ffmpeg-4.4/libavcodec/aarch64/vp9dsp_init_aarch64.c --- ffmpeg-4.2.2/libavcodec/aarch64/vp9dsp_init_aarch64.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/vp9dsp_init_aarch64.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "libavutil/attributes.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/aarch64/cpu.h" #include "libavcodec/vp9dsp.h" #include "vp9dsp_init.h" diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/vp9mc_16bpp_neon.S ffmpeg-4.4/libavcodec/aarch64/vp9mc_16bpp_neon.S --- ffmpeg-4.2.2/libavcodec/aarch64/vp9mc_16bpp_neon.S 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/vp9mc_16bpp_neon.S 2020-07-11 10:39:30.000000000 +0000 @@ -25,31 +25,6 @@ // const uint8_t *ref, ptrdiff_t ref_stride, // int h, int mx, int my); -function ff_vp9_copy128_aarch64, export=1 -1: - ldp x5, x6, [x2] - ldp x7, x8, [x2, #16] - stp x5, x6, [x0] - ldp x9, x10, [x2, #32] - stp x7, x8, [x0, #16] - subs w4, w4, #1 - ldp x11, x12, [x2, #48] - stp x9, x10, [x0, #32] - stp x11, x12, [x0, #48] - ldp x5, x6, [x2, #64] - ldp x7, x8, [x2, #80] - stp x5, x6, [x0, #64] - ldp x9, x10, [x2, #96] - stp x7, x8, [x0, #80] - ldp x11, x12, [x2, #112] - stp x9, x10, [x0, #96] - stp x11, x12, [x0, #112] - add x2, x2, x3 - add x0, x0, x1 - b.ne 1b - ret -endfunc - function ff_vp9_avg64_16_neon, export=1 mov x5, x0 sub x1, x1, #64 diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/vp9mc_aarch64.S ffmpeg-4.4/libavcodec/aarch64/vp9mc_aarch64.S --- ffmpeg-4.2.2/libavcodec/aarch64/vp9mc_aarch64.S 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/vp9mc_aarch64.S 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016 Google Inc. + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +// All public functions in this file have the following signature: +// typedef void (*vp9_mc_func)(uint8_t *dst, ptrdiff_t dst_stride, +// const uint8_t *ref, ptrdiff_t ref_stride, +// int h, int mx, int my); + +function ff_vp9_copy128_aarch64, export=1 +1: + ldp x5, x6, [x2] + ldp x7, x8, [x2, #16] + stp x5, x6, [x0] + ldp x9, x10, [x2, #32] + stp x7, x8, [x0, #16] + subs w4, w4, #1 + ldp x11, x12, [x2, #48] + stp x9, x10, [x0, #32] + stp x11, x12, [x0, #48] + ldp x5, x6, [x2, #64] + ldp x7, x8, [x2, #80] + stp x5, x6, [x0, #64] + ldp x9, x10, [x2, #96] + stp x7, x8, [x0, #80] + ldp x11, x12, [x2, #112] + stp x9, x10, [x0, #96] + stp x11, x12, [x0, #112] + add x2, x2, x3 + add x0, x0, x1 + b.ne 1b + ret +endfunc + +function ff_vp9_copy64_aarch64, export=1 +1: + ldp x5, x6, [x2] + ldp x7, x8, [x2, #16] + stp x5, x6, [x0] + ldp x9, x10, [x2, #32] + stp x7, x8, [x0, #16] + subs w4, w4, #1 + ldp x11, x12, [x2, #48] + stp x9, x10, [x0, #32] + stp x11, x12, [x0, #48] + add x2, x2, x3 + add x0, x0, x1 + b.ne 1b + ret +endfunc + +function ff_vp9_copy32_aarch64, export=1 +1: + ldp x5, x6, [x2] + ldp x7, x8, [x2, #16] + stp x5, x6, [x0] + subs w4, w4, #1 + stp x7, x8, [x0, #16] + add x2, x2, x3 + add x0, x0, x1 + b.ne 1b + ret +endfunc diff -Nru ffmpeg-4.2.2/libavcodec/aarch64/vp9mc_neon.S ffmpeg-4.4/libavcodec/aarch64/vp9mc_neon.S --- ffmpeg-4.2.2/libavcodec/aarch64/vp9mc_neon.S 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aarch64/vp9mc_neon.S 2020-07-11 10:39:30.000000000 +0000 @@ -25,23 +25,6 @@ // const uint8_t *ref, ptrdiff_t ref_stride, // int h, int mx, int my); -function ff_vp9_copy64_aarch64, export=1 -1: - ldp x5, x6, [x2] - ldp x7, x8, [x2, #16] - stp x5, x6, [x0] - ldp x9, x10, [x2, #32] - stp x7, x8, [x0, #16] - subs w4, w4, #1 - ldp x11, x12, [x2, #48] - stp x9, x10, [x0, #32] - stp x11, x12, [x0, #48] - add x2, x2, x3 - add x0, x0, x1 - b.ne 1b - ret -endfunc - function ff_vp9_avg64_neon, export=1 mov x5, x0 1: @@ -63,19 +46,6 @@ b.ne 1b ret endfunc - -function ff_vp9_copy32_aarch64, export=1 -1: - ldp x5, x6, [x2] - ldp x7, x8, [x2, #16] - stp x5, x6, [x0] - subs w4, w4, #1 - stp x7, x8, [x0, #16] - add x2, x2, x3 - add x0, x0, x1 - b.ne 1b - ret -endfunc function ff_vp9_avg32_neon, export=1 1: diff -Nru ffmpeg-4.2.2/libavcodec/aasc.c ffmpeg-4.4/libavcodec/aasc.c --- ffmpeg-4.2.2/libavcodec/aasc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aasc.c 2020-07-11 10:39:30.000000000 +0000 @@ -91,7 +91,7 @@ return AVERROR_INVALIDDATA; } - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; compr = AV_RL32(buf); diff -Nru ffmpeg-4.2.2/libavcodec/ac3dec.c ffmpeg-4.4/libavcodec/ac3dec.c --- ffmpeg-4.2.2/libavcodec/ac3dec.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,6 +33,7 @@ #include "libavutil/crc.h" #include "libavutil/downmix_info.h" #include "libavutil/opt.h" +#include "libavutil/thread.h" #include "bswapdsp.h" #include "internal.h" #include "aac_ac3_parser.h" @@ -183,23 +184,26 @@ */ static av_cold int ac3_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; AC3DecodeContext *s = avctx->priv_data; - int i; + int i, ret; s->avctx = avctx; - ac3_tables_init(); - ff_mdct_init(&s->imdct_256, 8, 1, 1.0); - ff_mdct_init(&s->imdct_512, 9, 1, 1.0); + if ((ret = ff_mdct_init(&s->imdct_256, 8, 1, 1.0)) < 0 || + (ret = ff_mdct_init(&s->imdct_512, 9, 1, 1.0)) < 0) + return ret; AC3_RENAME(ff_kbd_window_init)(s->window, 5.0, 256); ff_bswapdsp_init(&s->bdsp); #if (USE_FIXED) s->fdsp = avpriv_alloc_fixed_dsp(avctx->flags & AV_CODEC_FLAG_BITEXACT); #else - s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); ff_fmt_convert_init(&s->fmt_conv, avctx); + s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); #endif + if (!s->fdsp) + return AVERROR(ENOMEM); ff_ac3dsp_init(&s->ac3dsp, avctx->flags & AV_CODEC_FLAG_BITEXACT); av_lfg_init(&s->dith_state, 0); @@ -223,6 +227,8 @@ s->dlyptr[i] = s->delay[i]; } + ff_thread_once(&init_static_once, ac3_tables_init); + return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/ac3dec_fixed.c ffmpeg-4.4/libavcodec/ac3dec_fixed.c --- ffmpeg-4.2.2/libavcodec/ac3dec_fixed.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3dec_fixed.c 2021-04-08 21:28:39.000000000 +0000 @@ -107,30 +107,17 @@ } } else { shift = -shift; + mul <<= shift; for (i=0; i>= 1; - for (i = 0; i < len; i += 8) { - src32[i ] = (src32[i ] << shift) & mask; - src32[i+1] = (src32[i+1] << shift) & mask; - src32[i+2] = (src32[i+2] << shift) & mask; - src32[i+3] = (src32[i+3] << shift) & mask; - src32[i+4] = (src32[i+4] << shift) & mask; - src32[i+5] = (src32[i+5] << shift) & mask; - src32[i+6] = (src32[i+6] << shift) & mask; - src32[i+7] = (src32[i+7] << shift) & mask; - } -} - -static void ac3_rshift_int32_c(int32_t *src, unsigned int len, - unsigned int shift) -{ - do { - *src++ >>= shift; - *src++ >>= shift; - *src++ >>= shift; - *src++ >>= shift; - *src++ >>= shift; - *src++ >>= shift; - *src++ >>= shift; - *src++ >>= shift; - len -= 8; - } while (len > 0); -} - static void float_to_fixed24_c(int32_t *dst, const float *src, unsigned int len) { const float scale = 1 << 24; @@ -374,19 +333,6 @@ ac3_downmix_c_fixed(samples, matrix, out_ch, in_ch, len); } -static void apply_window_int16_c(int16_t *output, const int16_t *input, - const int16_t *window, unsigned int len) -{ - int i; - int len2 = len >> 1; - - for (i = 0; i < len2; i++) { - int16_t w = window[i]; - output[i] = (MUL16(input[i], w) + (1 << 14)) >> 15; - output[len-i-1] = (MUL16(input[len-i-1], w) + (1 << 14)) >> 15; - } -} - void ff_ac3dsp_downmix(AC3DSPContext *c, float **samples, float **matrix, int out_ch, int in_ch, int len) { @@ -422,9 +368,6 @@ av_cold void ff_ac3dsp_init(AC3DSPContext *c, int bit_exact) { c->ac3_exponent_min = ac3_exponent_min_c; - c->ac3_max_msb_abs_int16 = ac3_max_msb_abs_int16_c; - c->ac3_lshift_int16 = ac3_lshift_int16_c; - c->ac3_rshift_int32 = ac3_rshift_int32_c; c->float_to_fixed24 = float_to_fixed24_c; c->bit_alloc_calc_bap = ac3_bit_alloc_calc_bap_c; c->update_bap_counts = ac3_update_bap_counts_c; @@ -436,7 +379,6 @@ c->out_channels = 0; c->downmix = NULL; c->downmix_fixed = NULL; - c->apply_window_int16 = apply_window_int16_c; if (ARCH_ARM) ff_ac3dsp_init_arm(c, bit_exact); diff -Nru ffmpeg-4.2.2/libavcodec/ac3dsp.h ffmpeg-4.4/libavcodec/ac3dsp.h --- ffmpeg-4.2.2/libavcodec/ac3dsp.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3dsp.h 2021-04-08 21:28:39.000000000 +0000 @@ -43,39 +43,6 @@ void (*ac3_exponent_min)(uint8_t *exp, int num_reuse_blocks, int nb_coefs); /** - * Calculate the maximum MSB of the absolute value of each element in an - * array of int16_t. - * @param src input array - * constraints: align 16. values must be in range [-32767,32767] - * @param len number of values in the array - * constraints: multiple of 16 greater than 0 - * @return a value with the same MSB as max(abs(src[])) - */ - int (*ac3_max_msb_abs_int16)(const int16_t *src, int len); - - /** - * Left-shift each value in an array of int16_t by a specified amount. - * @param src input array - * constraints: align 16 - * @param len number of values in the array - * constraints: multiple of 32 greater than 0 - * @param shift left shift amount - * constraints: range [0,15] - */ - void (*ac3_lshift_int16)(int16_t *src, unsigned int len, unsigned int shift); - - /** - * Right-shift each value in an array of int32_t by a specified amount. - * @param src input array - * constraints: align 16 - * @param len number of values in the array - * constraints: multiple of 16 greater than 0 - * @param shift right shift amount - * constraints: range [0,31] - */ - void (*ac3_rshift_int32)(int32_t *src, unsigned int len, unsigned int shift); - - /** * Convert an array of float in range [-1.0,1.0] to int32_t with range * [-(1<<24),(1<<24)] * @@ -136,20 +103,6 @@ int in_channels; void (*downmix)(float **samples, float **matrix, int len); void (*downmix_fixed)(int32_t **samples, int16_t **matrix, int len); - - /** - * Apply symmetric window in 16-bit fixed-point. - * @param output destination array - * constraints: 16-byte aligned - * @param input source array - * constraints: 16-byte aligned - * @param window window array - * constraints: 16-byte aligned, at least len/2 elements - * @param len full window length - * constraints: multiple of ? greater than zero - */ - void (*apply_window_int16)(int16_t *output, const int16_t *input, - const int16_t *window, unsigned int len); } AC3DSPContext; void ff_ac3dsp_init (AC3DSPContext *c, int bit_exact); diff -Nru ffmpeg-4.2.2/libavcodec/ac3enc.c ffmpeg-4.4/libavcodec/ac3enc.c --- ffmpeg-4.2.2/libavcodec/ac3enc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,7 +34,9 @@ #include "libavutil/channel_layout.h" #include "libavutil/crc.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "internal.h" #include "me_cmp.h" @@ -63,10 +65,69 @@ #define EXTMIXLEV_NUM_OPTIONS 8 static const float extmixlev_options[EXTMIXLEV_NUM_OPTIONS] = { - LEVEL_PLUS_3DB, LEVEL_PLUS_1POINT5DB, LEVEL_ONE, LEVEL_MINUS_4POINT5DB, + LEVEL_PLUS_3DB, LEVEL_PLUS_1POINT5DB, LEVEL_ONE, LEVEL_MINUS_1POINT5DB, LEVEL_MINUS_3DB, LEVEL_MINUS_4POINT5DB, LEVEL_MINUS_6DB, LEVEL_ZERO }; +/* The first two options apply only to the AC-3 encoders; + * the rest is also valid for EAC-3. When modifying it, + * it might be necessary to adapt said offset in eac3enc.c. */ +#define OFFSET(param) offsetof(AC3EncodeContext, options.param) +#define AC3ENC_PARAM (AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) +const AVOption ff_ac3_enc_options[] = { +/* AC-3 downmix levels */ +{"center_mixlev", "Center Mix Level", OFFSET(center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_4POINT5DB }, 0.0, 1.0, AC3ENC_PARAM}, +{"surround_mixlev", "Surround Mix Level", OFFSET(surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_6DB }, 0.0, 1.0, AC3ENC_PARAM}, +/* audio production information */ +{"mixing_level", "Mixing Level", OFFSET(mixing_level), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 111, AC3ENC_PARAM}, +{"room_type", "Room Type", OFFSET(room_type), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_SMALL_ROOM, AC3ENC_PARAM, "room_type"}, + {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"}, + {"large", "Large Room", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_LARGE_ROOM }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"}, + {"small", "Small Room", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_SMALL_ROOM }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"}, +/* Metadata Options */ +{"per_frame_metadata", "Allow Changing Metadata Per-Frame", OFFSET(allow_per_frame_metadata), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, AC3ENC_PARAM}, +{"copyright", "Copyright Bit", OFFSET(copyright), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM}, +{"dialnorm", "Dialogue Level (dB)", OFFSET(dialogue_level), AV_OPT_TYPE_INT, {.i64 = -31 }, -31, -1, AC3ENC_PARAM}, +{"dsur_mode", "Dolby Surround Mode", OFFSET(dolby_surround_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, "dsur_mode"}, + {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"}, + {"on", "Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"}, + {"off", "Not Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"}, +{"original", "Original Bit Stream", OFFSET(original), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM}, +/* extended bitstream information */ +{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DOWNMIX_DPLII, AC3ENC_PARAM, "dmix_mode"}, + {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, + {"ltrt", "Lt/Rt Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LTRT }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, + {"loro", "Lo/Ro Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LORO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, + {"dplii", "Dolby Pro Logic II Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_DPLII }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, +{"ltrt_cmixlev", "Lt/Rt Center Mix Level", OFFSET(ltrt_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, +{"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, +{"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, +{"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, +{"dsurex_mode", "Dolby Surround EX Mode", OFFSET(dolby_surround_ex_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DSUREX_DPLIIZ, AC3ENC_PARAM, "dsurex_mode"}, + {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, + {"on", "Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, + {"off", "Not Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, + {"dpliiz", "Dolby Pro Logic IIz-encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DSUREX_DPLIIZ }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, +{"dheadphone_mode", "Dolby Headphone Mode", OFFSET(dolby_headphone_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, "dheadphone_mode"}, + {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"}, + {"on", "Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"}, + {"off", "Not Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"}, +{"ad_conv_type", "A/D Converter Type", OFFSET(ad_converter_type), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_ADCONV_HDCD, AC3ENC_PARAM, "ad_conv_type"}, + {"standard", "Standard (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_ADCONV_STANDARD }, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"}, + {"hdcd", "HDCD", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_ADCONV_HDCD }, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"}, +/* Other Encoding Options */ +{"stereo_rematrixing", "Stereo Rematrixing", OFFSET(stereo_rematrixing), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, AC3ENC_PARAM}, +{"channel_coupling", "Channel Coupling", OFFSET(channel_coupling), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_AUTO }, AC3ENC_OPT_AUTO, AC3ENC_OPT_ON, AC3ENC_PARAM, "channel_coupling"}, + {"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "channel_coupling"}, +{"cpl_start_band", "Coupling Start Band", OFFSET(cpl_start), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_AUTO }, AC3ENC_OPT_AUTO, 15, AC3ENC_PARAM, "cpl_start_band"}, + {"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "cpl_start_band"}, +{NULL} +}; + +const AVCodecDefault ff_ac3_enc_defaults[] = { + { "b", "0" }, + { NULL } +}; /** * LUT for number of exponent groups. @@ -100,6 +161,15 @@ 0 }; +/** + * Table to remap channels from SMPTE order to AC-3 order. + * [channel_mode][lfe][ch] + */ +static const uint8_t ac3_enc_channel_map[8][2][6] = { + COMMON_CHANNEL_MAP + { { 0, 1, 2, 3, }, { 0, 1, 3, 4, 2, } }, + { { 0, 2, 1, 3, 4, }, { 0, 2, 1, 4, 5, 3 } }, +}; /** * LUT to select the bandwidth code based on the bit rate, sample rate, and @@ -269,7 +339,7 @@ * * @param s AC-3 encoder private context */ -void ff_ac3_apply_rematrixing(AC3EncodeContext *s) +static void ac3_apply_rematrixing(AC3EncodeContext *s) { int nb_coefs; int blk, bnd, i; @@ -303,7 +373,7 @@ /* * Initialize exponent tables. */ -static av_cold void exponent_init(AC3EncodeContext *s) +static av_cold void exponent_init(void) { int expstr, i, grpsize; @@ -316,9 +386,6 @@ } /* LFE */ exponent_group_tab[0][0][7] = 2; - - if (CONFIG_EAC3_ENCODER && s->eac3) - ff_eac3_exponent_init(); } @@ -576,7 +643,7 @@ * * @param s AC-3 encoder private context */ -void ff_ac3_group_exponents(AC3EncodeContext *s) +static void ac3_group_exponents(AC3EncodeContext *s) { int blk, ch, i, cpl; int group_size, nb_groups; @@ -634,7 +701,7 @@ * * @param s AC-3 encoder private context */ -void ff_ac3_process_exponents(AC3EncodeContext *s) +static void ac3_process_exponents(AC3EncodeContext *s) { extract_exponents(s); @@ -1065,7 +1132,7 @@ { int blk, ch; - snr_offset = (snr_offset - 240) << 2; + snr_offset = (snr_offset - 240) * 4; reset_block_bap(s); for (blk = 0; blk < s->num_blocks; blk++) { @@ -1143,7 +1210,7 @@ * frame size. Output is the SNR offset and a set of bit allocation pointers * used to quantize the mantissas. */ -int ff_ac3_compute_bit_allocation(AC3EncodeContext *s) +static int ac3_compute_bit_allocation(AC3EncodeContext *s) { count_frame_bits(s); @@ -1297,7 +1364,7 @@ * * @param s AC-3 encoder private context */ -void ff_ac3_quantize_mantissas(AC3EncodeContext *s) +static void ac3_quantize_mantissas(AC3EncodeContext *s) { int blk, ch, ch0=0, got_cpl; @@ -1658,11 +1725,11 @@ * @param s AC-3 encoder private context * @param frame output data buffer */ -void ff_ac3_output_frame(AC3EncodeContext *s, unsigned char *frame) +static void ac3_output_frame(AC3EncodeContext *s, unsigned char *frame) { int blk; - init_put_bits(&s->pb, frame, AC3_MAX_CODED_FRAME_SIZE); + init_put_bits(&s->pb, frame, s->frame_size); s->output_frame_header(s); @@ -1672,6 +1739,36 @@ output_frame_end(s); } +int ff_ac3_encode_frame_common_end(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + AC3EncodeContext *const s = avctx->priv_data; + int ret; + + ac3_apply_rematrixing(s); + + ac3_process_exponents(s); + + ret = ac3_compute_bit_allocation(s); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Bit allocation failed. Try increasing the bitrate.\n"); + return ret; + } + + ac3_group_exponents(s); + + ac3_quantize_mantissas(s); + + if ((ret = ff_alloc_packet2(avctx, avpkt, s->frame_size, 0)) < 0) + return ret; + ac3_output_frame(s, avpkt->data); + + if (frame->pts != AV_NOPTS_VALUE) + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding); + + *got_packet_ptr = 1; + return 0; +} static void dprint_options(AC3EncodeContext *s) { @@ -1993,12 +2090,11 @@ /* set bitstream id for alternate bitstream syntax */ if (!s->eac3 && (opt->extended_bsi_1 || opt->extended_bsi_2)) { if (s->bitstream_id > 8 && s->bitstream_id < 11) { - static int warn_once = 1; - if (warn_once) { + if (!s->warned_alternate_bitstream) { av_log(avctx, AV_LOG_WARNING, "alternate bitstream syntax is " "not compatible with reduced samplerates. writing of " "extended bitstream information will be disabled.\n"); - warn_once = 0; + s->warned_alternate_bitstream = 1; } } else { s->bitstream_id = 6; @@ -2019,6 +2115,7 @@ int blk, ch; AC3EncodeContext *s = avctx->priv_data; + av_freep(&s->mdct_window); av_freep(&s->windowed_samples); if (s->planar_samples) for (ch = 0; ch < s->channels; ch++) @@ -2096,7 +2193,7 @@ s->has_center = (s->channel_mode & 0x01) && s->channel_mode != AC3_CHMODE_MONO; s->has_surround = s->channel_mode & 0x04; - s->channel_map = ff_ac3_enc_channel_map[s->channel_mode][s->lfe_on]; + s->channel_map = ac3_enc_channel_map[s->channel_mode][s->lfe_on]; *channel_layout = ch_layout; if (s->lfe_on) *channel_layout |= AV_CH_LOW_FREQUENCY; @@ -2322,60 +2419,46 @@ static av_cold int allocate_buffers(AC3EncodeContext *s) { - AVCodecContext *avctx = s->avctx; int blk, ch; int channels = s->channels + 1; /* includes coupling channel */ int channel_blocks = channels * s->num_blocks; int total_coefs = AC3_MAX_COEFS * channel_blocks; if (s->allocate_sample_buffers(s)) - goto alloc_fail; + return AVERROR(ENOMEM); + + if (!FF_ALLOC_TYPED_ARRAY(s->bap_buffer, total_coefs) || + !FF_ALLOC_TYPED_ARRAY(s->bap1_buffer, total_coefs) || + !FF_ALLOCZ_TYPED_ARRAY(s->mdct_coef_buffer, total_coefs) || + !FF_ALLOC_TYPED_ARRAY(s->exp_buffer, total_coefs) || + !FF_ALLOC_TYPED_ARRAY(s->grouped_exp_buffer, channel_blocks * 128) || + !FF_ALLOC_TYPED_ARRAY(s->psd_buffer, total_coefs) || + !FF_ALLOC_TYPED_ARRAY(s->band_psd_buffer, channel_blocks * 64) || + !FF_ALLOC_TYPED_ARRAY(s->mask_buffer, channel_blocks * 64) || + !FF_ALLOC_TYPED_ARRAY(s->qmant_buffer, total_coefs)) + return AVERROR(ENOMEM); - FF_ALLOC_ARRAY_OR_GOTO(avctx, s->bap_buffer, total_coefs, - sizeof(*s->bap_buffer), alloc_fail); - FF_ALLOC_ARRAY_OR_GOTO(avctx, s->bap1_buffer, total_coefs, - sizeof(*s->bap1_buffer), alloc_fail); - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->mdct_coef_buffer, total_coefs, - sizeof(*s->mdct_coef_buffer), alloc_fail); - FF_ALLOC_ARRAY_OR_GOTO(avctx, s->exp_buffer, total_coefs, - sizeof(*s->exp_buffer), alloc_fail); - FF_ALLOC_ARRAY_OR_GOTO(avctx, s->grouped_exp_buffer, channel_blocks, 128 * - sizeof(*s->grouped_exp_buffer), alloc_fail); - FF_ALLOC_ARRAY_OR_GOTO(avctx, s->psd_buffer, total_coefs, - sizeof(*s->psd_buffer), alloc_fail); - FF_ALLOC_ARRAY_OR_GOTO(avctx, s->band_psd_buffer, channel_blocks, 64 * - sizeof(*s->band_psd_buffer), alloc_fail); - FF_ALLOC_ARRAY_OR_GOTO(avctx, s->mask_buffer, channel_blocks, 64 * - sizeof(*s->mask_buffer), alloc_fail); - FF_ALLOC_ARRAY_OR_GOTO(avctx, s->qmant_buffer, total_coefs, - sizeof(*s->qmant_buffer), alloc_fail); if (s->cpl_enabled) { - FF_ALLOC_ARRAY_OR_GOTO(avctx, s->cpl_coord_exp_buffer, channel_blocks, 16 * - sizeof(*s->cpl_coord_exp_buffer), alloc_fail); - FF_ALLOC_ARRAY_OR_GOTO(avctx, s->cpl_coord_mant_buffer, channel_blocks, 16 * - sizeof(*s->cpl_coord_mant_buffer), alloc_fail); + if (!FF_ALLOC_TYPED_ARRAY(s->cpl_coord_exp_buffer, channel_blocks * 16) || + !FF_ALLOC_TYPED_ARRAY(s->cpl_coord_mant_buffer, channel_blocks * 16)) + return AVERROR(ENOMEM); } for (blk = 0; blk < s->num_blocks; blk++) { AC3Block *block = &s->blocks[blk]; - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, block->mdct_coef, channels, sizeof(*block->mdct_coef), - alloc_fail); - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, block->exp, channels, sizeof(*block->exp), - alloc_fail); - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, block->grouped_exp, channels, sizeof(*block->grouped_exp), - alloc_fail); - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, block->psd, channels, sizeof(*block->psd), - alloc_fail); - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, block->band_psd, channels, sizeof(*block->band_psd), - alloc_fail); - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, block->mask, channels, sizeof(*block->mask), - alloc_fail); - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, block->qmant, channels, sizeof(*block->qmant), - alloc_fail); + + if (!FF_ALLOCZ_TYPED_ARRAY(block->mdct_coef, channels) || + !FF_ALLOCZ_TYPED_ARRAY(block->exp, channels) || + !FF_ALLOCZ_TYPED_ARRAY(block->grouped_exp, channels) || + !FF_ALLOCZ_TYPED_ARRAY(block->psd, channels) || + !FF_ALLOCZ_TYPED_ARRAY(block->band_psd, channels) || + !FF_ALLOCZ_TYPED_ARRAY(block->mask, channels) || + !FF_ALLOCZ_TYPED_ARRAY(block->qmant, channels)) + return AVERROR(ENOMEM); + if (s->cpl_enabled) { - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, block->cpl_coord_exp, channels, sizeof(*block->cpl_coord_exp), - alloc_fail); - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, block->cpl_coord_mant, channels, sizeof(*block->cpl_coord_mant), - alloc_fail); + if (!FF_ALLOCZ_TYPED_ARRAY(block->cpl_coord_exp, channels) || + !FF_ALLOCZ_TYPED_ARRAY(block->cpl_coord_mant, channels)) + return AVERROR(ENOMEM); } for (ch = 0; ch < channels; ch++) { @@ -2397,33 +2480,32 @@ } if (!s->fixed_point) { - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->fixed_coef_buffer, total_coefs, - sizeof(*s->fixed_coef_buffer), alloc_fail); + if (!FF_ALLOCZ_TYPED_ARRAY(s->fixed_coef_buffer, total_coefs)) + return AVERROR(ENOMEM); for (blk = 0; blk < s->num_blocks; blk++) { AC3Block *block = &s->blocks[blk]; - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, block->fixed_coef, channels, - sizeof(*block->fixed_coef), alloc_fail); + if (!FF_ALLOCZ_TYPED_ARRAY(block->fixed_coef, channels)) + return AVERROR(ENOMEM); for (ch = 0; ch < channels; ch++) block->fixed_coef[ch] = &s->fixed_coef_buffer[AC3_MAX_COEFS * (s->num_blocks * ch + blk)]; } } else { for (blk = 0; blk < s->num_blocks; blk++) { AC3Block *block = &s->blocks[blk]; - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, block->fixed_coef, channels, - sizeof(*block->fixed_coef), alloc_fail); + if (!FF_ALLOCZ_TYPED_ARRAY(block->fixed_coef, channels)) + return AVERROR(ENOMEM); for (ch = 0; ch < channels; ch++) block->fixed_coef[ch] = (int32_t *)block->mdct_coef[ch]; } } return 0; -alloc_fail: - return AVERROR(ENOMEM); } av_cold int ff_ac3_encode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; AC3EncodeContext *s = avctx->priv_data; int ret, frame_size_58; @@ -2453,34 +2535,24 @@ s->crc_inv[1] = pow_poly((CRC16_POLY >> 1), (8 * frame_size_58) - 16, CRC16_POLY); } - /* set function pointers */ - if (CONFIG_AC3_FIXED_ENCODER && s->fixed_point) { - s->mdct_end = ff_ac3_fixed_mdct_end; - s->mdct_init = ff_ac3_fixed_mdct_init; - s->allocate_sample_buffers = ff_ac3_fixed_allocate_sample_buffers; - } else if (CONFIG_AC3_ENCODER || CONFIG_EAC3_ENCODER) { - s->mdct_end = ff_ac3_float_mdct_end; - s->mdct_init = ff_ac3_float_mdct_init; - s->allocate_sample_buffers = ff_ac3_float_allocate_sample_buffers; - } - if (CONFIG_EAC3_ENCODER && s->eac3) + if (CONFIG_EAC3_ENCODER && s->eac3) { + static AVOnce init_static_once_eac3 = AV_ONCE_INIT; + ff_thread_once(&init_static_once_eac3, ff_eac3_exponent_init); s->output_frame_header = ff_eac3_output_frame_header; - else + } else s->output_frame_header = ac3_output_frame_header; set_bandwidth(s); - exponent_init(s); - bit_alloc_init(s); ret = s->mdct_init(s); if (ret) - goto init_fail; + return ret; ret = allocate_buffers(s); if (ret) - goto init_fail; + return ret; ff_audiodsp_init(&s->adsp); ff_me_cmp_init(&s->mecc, avctx); @@ -2488,8 +2560,7 @@ dprint_options(s); + ff_thread_once(&init_static_once, exponent_init); + return 0; -init_fail: - ff_ac3_encode_close(avctx); - return ret; } diff -Nru ffmpeg-4.2.2/libavcodec/ac3enc_fixed.c ffmpeg-4.4/libavcodec/ac3enc_fixed.c --- ffmpeg-4.2.2/libavcodec/ac3enc_fixed.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3enc_fixed.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,54 +26,22 @@ * fixed-point AC-3 encoder. */ +#define AC3ENC_FLOAT 0 #define FFT_FLOAT 0 -#undef CONFIG_AC3ENC_FLOAT +#define FFT_FIXED_32 1 #include "internal.h" #include "audiodsp.h" #include "ac3enc.h" #include "eac3enc.h" - -#define AC3ENC_TYPE AC3ENC_TYPE_AC3_FIXED -#include "ac3enc_opts_template.c" +#include "kbdwin.h" static const AVClass ac3enc_class = { .class_name = "Fixed-Point AC-3 Encoder", .item_name = av_default_item_name, - .option = ac3_options, + .option = ff_ac3_enc_options, .version = LIBAVUTIL_VERSION_INT, }; -/* - * Normalize the input samples to use the maximum available precision. - * This assumes signed 16-bit input samples. - */ -static int normalize_samples(AC3EncodeContext *s) -{ - int v = s->ac3dsp.ac3_max_msb_abs_int16(s->windowed_samples, AC3_WINDOW_SIZE); - v = 14 - av_log2(v); - if (v > 0) - s->ac3dsp.ac3_lshift_int16(s->windowed_samples, AC3_WINDOW_SIZE, v); - /* +6 to right-shift from 31-bit to 25-bit */ - return v + 6; -} - - -/* - * Scale MDCT coefficients to 25-bit signed fixed-point. - */ -static void scale_coefficients(AC3EncodeContext *s) -{ - int blk, ch; - - for (blk = 0; blk < s->num_blocks; blk++) { - AC3Block *block = &s->blocks[blk]; - for (ch = 1; ch <= s->channels; ch++) { - s->ac3dsp.ac3_rshift_int32(block->mdct_coef[ch], AC3_MAX_COEFS, - block->coeff_shift[ch]); - } - } -} - static void sum_square_butterfly(AC3EncodeContext *s, int64_t sum[4], const int32_t *coef0, const int32_t *coef1, int len) @@ -115,23 +83,36 @@ * * @param s AC-3 encoder private context */ -av_cold void ff_ac3_fixed_mdct_end(AC3EncodeContext *s) +static av_cold void ac3_fixed_mdct_end(AC3EncodeContext *s) { ff_mdct_end(&s->mdct); } - /** * Initialize MDCT tables. * * @param s AC-3 encoder private context * @return 0 on success, negative error code on failure */ -av_cold int ff_ac3_fixed_mdct_init(AC3EncodeContext *s) +static av_cold int ac3_fixed_mdct_init(AC3EncodeContext *s) { - int ret = ff_mdct_init(&s->mdct, 9, 0, -1.0); - s->mdct_window = ff_ac3_window; - return ret; + float fwin[AC3_BLOCK_SIZE]; + + int32_t *iwin = av_malloc_array(AC3_BLOCK_SIZE, sizeof(*iwin)); + if (!iwin) + return AVERROR(ENOMEM); + + ff_kbd_window_init(fwin, 5.0, AC3_BLOCK_SIZE); + for (int i = 0; i < AC3_BLOCK_SIZE; i++) + iwin[i] = lrintf(fwin[i] * (1 << 22)); + + s->mdct_window = iwin; + + s->fdsp = avpriv_alloc_fixed_dsp(s->avctx->flags & AV_CODEC_FLAG_BITEXACT); + if (!s->fdsp) + return AVERROR(ENOMEM); + + return ff_mdct_init(&s->mdct, 9, 0, -1.0); } @@ -139,6 +120,9 @@ { AC3EncodeContext *s = avctx->priv_data; s->fixed_point = 1; + s->mdct_end = ac3_fixed_mdct_end; + s->mdct_init = ac3_fixed_mdct_init; + s->allocate_sample_buffers = allocate_sample_buffers; return ff_ac3_encode_init(avctx); } @@ -152,9 +136,11 @@ .init = ac3_fixed_encode_init, .encode2 = ff_ac3_fixed_encode_frame, .close = ff_ac3_encode_close, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16P, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, .priv_class = &ac3enc_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .supported_samplerates = ff_ac3_sample_rate_tab, .channel_layouts = ff_ac3_channel_layouts, - .defaults = ac3_defaults, + .defaults = ff_ac3_enc_defaults, }; diff -Nru ffmpeg-4.2.2/libavcodec/ac3enc_float.c ffmpeg-4.4/libavcodec/ac3enc_float.c --- ffmpeg-4.2.2/libavcodec/ac3enc_float.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3enc_float.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,7 +26,7 @@ * floating-point AC-3 encoder. */ -#define CONFIG_AC3ENC_FLOAT 1 +#define AC3ENC_FLOAT 1 #include "internal.h" #include "audiodsp.h" #include "ac3enc.h" @@ -34,12 +34,10 @@ #include "kbdwin.h" -#define AC3ENC_TYPE AC3ENC_TYPE_AC3 -#include "ac3enc_opts_template.c" static const AVClass ac3enc_class = { .class_name = "AC-3 Encoder", .item_name = av_default_item_name, - .option = ac3_options, + .option = ff_ac3_enc_options, .version = LIBAVUTIL_VERSION_INT, }; @@ -94,10 +92,9 @@ * * @param s AC-3 encoder private context */ -av_cold void ff_ac3_float_mdct_end(AC3EncodeContext *s) +static av_cold void ac3_float_mdct_end(AC3EncodeContext *s) { ff_mdct_end(&s->mdct); - av_freep(&s->mdct_window); } @@ -107,31 +104,27 @@ * @param s AC-3 encoder private context * @return 0 on success, negative error code on failure */ -av_cold int ff_ac3_float_mdct_init(AC3EncodeContext *s) +static av_cold int ac3_float_mdct_init(AC3EncodeContext *s) { - float *window; - int i, n, n2; - - n = 1 << 9; - n2 = n >> 1; - - window = av_malloc_array(n, sizeof(*window)); + float *window = av_malloc_array(AC3_BLOCK_SIZE, sizeof(*window)); if (!window) { av_log(s->avctx, AV_LOG_ERROR, "Cannot allocate memory.\n"); return AVERROR(ENOMEM); } - ff_kbd_window_init(window, 5.0, n2); - for (i = 0; i < n2; i++) - window[n-1-i] = window[i]; + + ff_kbd_window_init(window, 5.0, AC3_BLOCK_SIZE); s->mdct_window = window; - return ff_mdct_init(&s->mdct, 9, 0, -2.0 / n); + return ff_mdct_init(&s->mdct, 9, 0, -2.0 / AC3_WINDOW_SIZE); } av_cold int ff_ac3_float_encode_init(AVCodecContext *avctx) { AC3EncodeContext *s = avctx->priv_data; + s->mdct_end = ac3_float_mdct_end; + s->mdct_init = ac3_float_mdct_init; + s->allocate_sample_buffers = allocate_sample_buffers; s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); if (!s->fdsp) return AVERROR(ENOMEM); @@ -150,6 +143,8 @@ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .priv_class = &ac3enc_class, + .supported_samplerates = ff_ac3_sample_rate_tab, .channel_layouts = ff_ac3_channel_layouts, - .defaults = ac3_defaults, + .defaults = ff_ac3_enc_defaults, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/ac3enc.h ffmpeg-4.4/libavcodec/ac3enc.h --- ffmpeg-4.2.2/libavcodec/ac3enc.h 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3enc.h 2021-04-08 21:28:39.000000000 +0000 @@ -30,8 +30,6 @@ #include -#include "libavutil/float_dsp.h" - #include "ac3.h" #include "ac3dsp.h" #include "avcodec.h" @@ -41,18 +39,12 @@ #include "put_bits.h" #include "audiodsp.h" -#ifndef CONFIG_AC3ENC_FLOAT -#define CONFIG_AC3ENC_FLOAT 0 +#ifndef AC3ENC_FLOAT +#define AC3ENC_FLOAT 0 #endif -#define OFFSET(param) offsetof(AC3EncodeContext, options.param) -#define AC3ENC_PARAM (AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) - -#define AC3ENC_TYPE_AC3_FIXED 0 -#define AC3ENC_TYPE_AC3 1 -#define AC3ENC_TYPE_EAC3 2 - -#if CONFIG_AC3ENC_FLOAT +#if AC3ENC_FLOAT +#include "libavutil/float_dsp.h" #define AC3_NAME(x) ff_ac3_float_ ## x #define MAC_COEF(d,a,b) ((d)+=(a)*(b)) #define COEF_MIN (-16777215.0/16777216.0) @@ -62,12 +54,13 @@ typedef float CoefType; typedef float CoefSumType; #else +#include "libavutil/fixed_dsp.h" #define AC3_NAME(x) ff_ac3_fixed_ ## x #define MAC_COEF(d,a,b) MAC64(d,a,b) #define COEF_MIN -16777215 #define COEF_MAX 16777215 #define NEW_CPL_COORD_THRESHOLD 503317 -typedef int16_t SampleType; +typedef int32_t SampleType; typedef int32_t CoefType; typedef int64_t CoefSumType; #endif @@ -141,7 +134,6 @@ uint16_t **qmant; ///< quantized mantissas uint8_t **cpl_coord_exp; ///< coupling coord exponents (cplcoexp) uint8_t **cpl_coord_mant; ///< coupling coord mantissas (cplcomant) - uint8_t coeff_shift[AC3_MAX_CHANNELS]; ///< fixed-point coefficient shift values uint8_t new_rematrixing_strategy; ///< send new rematrixing flags in this block int num_rematrixing_bands; ///< number of rematrixing bands uint8_t rematrixing_flags[4]; ///< rematrixing flags @@ -165,7 +157,11 @@ AVCodecContext *avctx; ///< parent AVCodecContext PutBitContext pb; ///< bitstream writer context AudioDSPContext adsp; +#if AC3ENC_FLOAT AVFloatDSPContext *fdsp; +#else + AVFixedDSPContext *fdsp; +#endif MECmpContext mecc; AC3DSPContext ac3dsp; ///< AC-3 optimized functions FFTContext mdct; ///< FFT context for MDCT calculation @@ -255,6 +251,8 @@ uint8_t *ref_bap [AC3_MAX_CHANNELS][AC3_MAX_BLOCKS]; ///< bit allocation pointers (bap) int ref_bap_set; ///< indicates if ref_bap pointers have been set + int warned_alternate_bitstream; + /* fixed vs. float function pointers */ void (*mdct_end)(struct AC3EncodeContext *s); int (*mdct_init)(struct AC3EncodeContext *s); @@ -268,6 +266,8 @@ extern const uint64_t ff_ac3_channel_layouts[19]; +extern const AVOption ff_ac3_enc_options[]; +extern const AVCodecDefault ff_ac3_enc_defaults[]; int ff_ac3_encode_init(AVCodecContext *avctx); int ff_ac3_float_encode_init(AVCodecContext *avctx); @@ -280,33 +280,11 @@ void ff_ac3_compute_coupling_strategy(AC3EncodeContext *s); -void ff_ac3_apply_rematrixing(AC3EncodeContext *s); - -void ff_ac3_process_exponents(AC3EncodeContext *s); - -int ff_ac3_compute_bit_allocation(AC3EncodeContext *s); - -void ff_ac3_group_exponents(AC3EncodeContext *s); - -void ff_ac3_quantize_mantissas(AC3EncodeContext *s); - -void ff_ac3_output_frame(AC3EncodeContext *s, unsigned char *frame); - - -/* prototypes for functions in ac3enc_fixed.c and ac3enc_float.c */ - -void ff_ac3_fixed_mdct_end(AC3EncodeContext *s); -void ff_ac3_float_mdct_end(AC3EncodeContext *s); - -int ff_ac3_fixed_mdct_init(AC3EncodeContext *s); -int ff_ac3_float_mdct_init(AC3EncodeContext *s); - +int ff_ac3_encode_frame_common_end(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr); /* prototypes for functions in ac3enc_template.c */ -int ff_ac3_fixed_allocate_sample_buffers(AC3EncodeContext *s); -int ff_ac3_float_allocate_sample_buffers(AC3EncodeContext *s); - int ff_ac3_fixed_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr); int ff_ac3_float_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, diff -Nru ffmpeg-4.2.2/libavcodec/ac3enc_opts_template.c ffmpeg-4.4/libavcodec/ac3enc_opts_template.c --- ffmpeg-4.2.2/libavcodec/ac3enc_opts_template.c 2018-07-17 09:27:39.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3enc_opts_template.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -/* - * AC-3 encoder options - * Copyright (c) 2011 Justin Ruggles - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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 "internal.h" -#include "ac3.h" - -static const AVOption ac3_options[] = { -/* Metadata Options */ -{"per_frame_metadata", "Allow Changing Metadata Per-Frame", OFFSET(allow_per_frame_metadata), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, AC3ENC_PARAM}, -#if AC3ENC_TYPE != AC3ENC_TYPE_EAC3 -/* AC-3 downmix levels */ -{"center_mixlev", "Center Mix Level", OFFSET(center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_4POINT5DB }, 0.0, 1.0, AC3ENC_PARAM}, -{"surround_mixlev", "Surround Mix Level", OFFSET(surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_6DB }, 0.0, 1.0, AC3ENC_PARAM}, -#endif -/* audio production information */ -{"mixing_level", "Mixing Level", OFFSET(mixing_level), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 111, AC3ENC_PARAM}, -{"room_type", "Room Type", OFFSET(room_type), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_SMALL_ROOM, AC3ENC_PARAM, "room_type"}, - {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"}, - {"large", "Large Room", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_LARGE_ROOM }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"}, - {"small", "Small Room", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_SMALL_ROOM }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"}, -/* other metadata options */ -{"copyright", "Copyright Bit", OFFSET(copyright), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM}, -{"dialnorm", "Dialogue Level (dB)", OFFSET(dialogue_level), AV_OPT_TYPE_INT, {.i64 = -31 }, -31, -1, AC3ENC_PARAM}, -{"dsur_mode", "Dolby Surround Mode", OFFSET(dolby_surround_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, "dsur_mode"}, - {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"}, - {"on", "Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"}, - {"off", "Not Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"}, -{"original", "Original Bit Stream", OFFSET(original), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM}, -/* extended bitstream information */ -{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DOWNMIX_DPLII, AC3ENC_PARAM, "dmix_mode"}, - {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, - {"ltrt", "Lt/Rt Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LTRT }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, - {"loro", "Lo/Ro Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LORO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, - {"dplii", "Dolby Pro Logic II Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_DPLII }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, -{"ltrt_cmixlev", "Lt/Rt Center Mix Level", OFFSET(ltrt_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, -{"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, -{"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, -{"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, -{"dsurex_mode", "Dolby Surround EX Mode", OFFSET(dolby_surround_ex_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DSUREX_DPLIIZ, AC3ENC_PARAM, "dsurex_mode"}, - {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, - {"on", "Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, - {"off", "Not Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, - {"dpliiz", "Dolby Pro Logic IIz-encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DSUREX_DPLIIZ }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, -{"dheadphone_mode", "Dolby Headphone Mode", OFFSET(dolby_headphone_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, "dheadphone_mode"}, - {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"}, - {"on", "Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"}, - {"off", "Not Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"}, -{"ad_conv_type", "A/D Converter Type", OFFSET(ad_converter_type), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_ADCONV_HDCD, AC3ENC_PARAM, "ad_conv_type"}, - {"standard", "Standard (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_ADCONV_STANDARD }, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"}, - {"hdcd", "HDCD", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_ADCONV_HDCD }, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"}, -/* Other Encoding Options */ -{"stereo_rematrixing", "Stereo Rematrixing", OFFSET(stereo_rematrixing), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, AC3ENC_PARAM}, -{"channel_coupling", "Channel Coupling", OFFSET(channel_coupling), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_AUTO }, AC3ENC_OPT_AUTO, AC3ENC_OPT_ON, AC3ENC_PARAM, "channel_coupling"}, - {"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "channel_coupling"}, -{"cpl_start_band", "Coupling Start Band", OFFSET(cpl_start), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_AUTO }, AC3ENC_OPT_AUTO, 15, AC3ENC_PARAM, "cpl_start_band"}, - {"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "cpl_start_band"}, -{NULL} -}; - -static const AVCodecDefault ac3_defaults[] = { - { "b", "0" }, - { NULL } -}; diff -Nru ffmpeg-4.2.2/libavcodec/ac3enc_template.c ffmpeg-4.4/libavcodec/ac3enc_template.c --- ffmpeg-4.2.2/libavcodec/ac3enc_template.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3enc_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/attributes.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "audiodsp.h" #include "internal.h" @@ -37,23 +38,20 @@ #include "eac3enc.h" -int AC3_NAME(allocate_sample_buffers)(AC3EncodeContext *s) +static int allocate_sample_buffers(AC3EncodeContext *s) { int ch; - FF_ALLOC_OR_GOTO(s->avctx, s->windowed_samples, AC3_WINDOW_SIZE * - sizeof(*s->windowed_samples), alloc_fail); - FF_ALLOC_ARRAY_OR_GOTO(s->avctx, s->planar_samples, s->channels, sizeof(*s->planar_samples), - alloc_fail); + if (!FF_ALLOC_TYPED_ARRAY(s->windowed_samples, AC3_WINDOW_SIZE) || + !FF_ALLOCZ_TYPED_ARRAY(s->planar_samples, s->channels)) + return AVERROR(ENOMEM); + for (ch = 0; ch < s->channels; ch++) { - FF_ALLOCZ_OR_GOTO(s->avctx, s->planar_samples[ch], - (AC3_FRAME_SIZE+AC3_BLOCK_SIZE) * sizeof(**s->planar_samples), - alloc_fail); + if (!(s->planar_samples[ch] = av_mallocz((AC3_FRAME_SIZE + AC3_BLOCK_SIZE) * + sizeof(**s->planar_samples)))) + return AVERROR(ENOMEM); } - return 0; -alloc_fail: - return AVERROR(ENOMEM); } @@ -93,19 +91,14 @@ AC3Block *block = &s->blocks[blk]; const SampleType *input_samples = &s->planar_samples[ch][blk * AC3_BLOCK_SIZE]; -#if CONFIG_AC3ENC_FLOAT s->fdsp->vector_fmul(s->windowed_samples, input_samples, - s->mdct_window, AC3_WINDOW_SIZE); -#else - s->ac3dsp.apply_window_int16(s->windowed_samples, input_samples, - s->mdct_window, AC3_WINDOW_SIZE); - - if (s->fixed_point) - block->coeff_shift[ch+1] = normalize_samples(s); -#endif + s->mdct_window, AC3_BLOCK_SIZE); + s->fdsp->vector_fmul_reverse(s->windowed_samples + AC3_BLOCK_SIZE, + &input_samples[AC3_BLOCK_SIZE], + s->mdct_window, AC3_BLOCK_SIZE); - s->mdct.mdct_calcw(&s->mdct, block->mdct_coef[ch+1], - s->windowed_samples); + s->mdct.mdct_calc(&s->mdct, block->mdct_coef[ch+1], + s->windowed_samples); } } } @@ -117,7 +110,7 @@ static void apply_channel_coupling(AC3EncodeContext *s) { LOCAL_ALIGNED_16(CoefType, cpl_coords, [AC3_MAX_BLOCKS], [AC3_MAX_CHANNELS][16]); -#if CONFIG_AC3ENC_FLOAT +#if AC3ENC_FLOAT LOCAL_ALIGNED_16(int32_t, fixed_cpl_coords, [AC3_MAX_BLOCKS], [AC3_MAX_CHANNELS][16]); #else int32_t (*fixed_cpl_coords)[AC3_MAX_CHANNELS][16] = cpl_coords; @@ -127,7 +120,7 @@ int cpl_start, num_cpl_coefs; memset(cpl_coords, 0, AC3_MAX_BLOCKS * sizeof(*cpl_coords)); -#if CONFIG_AC3ENC_FLOAT +#if AC3ENC_FLOAT memset(fixed_cpl_coords, 0, AC3_MAX_BLOCKS * sizeof(*cpl_coords)); #endif @@ -268,7 +261,7 @@ if (!block->cpl_in_use) continue; -#if CONFIG_AC3ENC_FLOAT +#if AC3ENC_FLOAT s->ac3dsp.float_to_fixed24(fixed_cpl_coords[blk][1], cpl_coords[blk][1], s->fbw_channels * 16); @@ -314,7 +307,7 @@ } } - if (CONFIG_EAC3_ENCODER && s->eac3) + if (AC3ENC_FLOAT && CONFIG_EAC3_ENCODER && s->eac3) ff_eac3_set_cpl_states(s); } @@ -386,19 +379,13 @@ return ret; } - if (s->bit_alloc.sr_code == 1 || s->eac3) + if (s->bit_alloc.sr_code == 1 || (AC3ENC_FLOAT && s->eac3)) ff_ac3_adjust_frame_size(s); copy_input_samples(s, (SampleType **)frame->extended_data); apply_mdct(s); - if (s->fixed_point) - scale_coefficients(s); - - clip_coefficients(&s->adsp, s->blocks[0].mdct_coef[1], - AC3_MAX_COEFS * s->num_blocks * s->channels); - s->cpl_on = s->cpl_enabled; ff_ac3_compute_coupling_strategy(s); @@ -407,30 +394,9 @@ compute_rematrixing_strategy(s); - if (!s->fixed_point) - scale_coefficients(s); - - ff_ac3_apply_rematrixing(s); - - ff_ac3_process_exponents(s); - - ret = ff_ac3_compute_bit_allocation(s); - if (ret) { - av_log(avctx, AV_LOG_ERROR, "Bit allocation failed. Try increasing the bitrate.\n"); - return ret; - } - - ff_ac3_group_exponents(s); - - ff_ac3_quantize_mantissas(s); - - if ((ret = ff_alloc_packet2(avctx, avpkt, s->frame_size, 0)) < 0) - return ret; - ff_ac3_output_frame(s, avpkt->data); - - if (frame->pts != AV_NOPTS_VALUE) - avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding); +#if AC3ENC_FLOAT + scale_coefficients(s); +#endif - *got_packet_ptr = 1; - return 0; + return ff_ac3_encode_frame_common_end(avctx, avpkt, frame, got_packet_ptr); } diff -Nru ffmpeg-4.2.2/libavcodec/ac3.h ffmpeg-4.4/libavcodec/ac3.h --- ffmpeg-4.2.2/libavcodec/ac3.h 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3.h 2021-04-08 21:28:39.000000000 +0000 @@ -27,7 +27,6 @@ #ifndef AVCODEC_AC3_H #define AVCODEC_AC3_H -#define AC3_MAX_CODED_FRAME_SIZE 3840 /* in bytes */ #define EAC3_MAX_CHANNELS 16 /**< maximum number of channels in EAC3 */ #define AC3_MAX_CHANNELS 7 /**< maximum number of channels, including coupling channel */ #define CPL_CH 0 /**< coupling channel index */ diff -Nru ffmpeg-4.2.2/libavcodec/ac3_parser.c ffmpeg-4.4/libavcodec/ac3_parser.c --- ffmpeg-4.2.2/libavcodec/ac3_parser.c 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3_parser.c 2020-07-11 10:39:30.000000000 +0000 @@ -201,6 +201,12 @@ AC3HeaderInfo hdr; GetBitContext gbc; + if (tmp.u8[1] == 0x77 && tmp.u8[2] == 0x0b) { + FFSWAP(uint8_t, tmp.u8[1], tmp.u8[2]); + FFSWAP(uint8_t, tmp.u8[3], tmp.u8[4]); + FFSWAP(uint8_t, tmp.u8[5], tmp.u8[6]); + } + init_get_bits(&gbc, tmp.u8+8-AC3_HEADER_SIZE, 54); err = ff_ac3_parse_header(&gbc, &hdr); diff -Nru ffmpeg-4.2.2/libavcodec/ac3tab.c ffmpeg-4.4/libavcodec/ac3tab.c --- ffmpeg-4.2.2/libavcodec/ac3tab.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3tab.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,7 +25,7 @@ */ #include "libavutil/channel_layout.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "ac3tab.h" @@ -97,24 +97,6 @@ AV_CH_LAYOUT_5POINT0 }; -#define COMMON_CHANNEL_MAP \ - { { 0, 1, }, { 0, 1, 2, } },\ - { { 0, }, { 0, 1, } },\ - { { 0, 1, }, { 0, 1, 2, } },\ - { { 0, 2, 1, }, { 0, 2, 1, 3, } },\ - { { 0, 1, 2, }, { 0, 1, 3, 2, } },\ - { { 0, 2, 1, 3, }, { 0, 2, 1, 4, 3, } }, - -/** - * Table to remap channels from SMPTE order to AC-3 order. - * [channel_mode][lfe][ch] - */ -const uint8_t ff_ac3_enc_channel_map[8][2][6] = { - COMMON_CHANNEL_MAP - { { 0, 1, 2, 3, }, { 0, 1, 3, 4, 2, } }, - { { 0, 2, 1, 3, 4, }, { 0, 2, 1, 4, 5, 3 } }, -}; - /** * Table to remap channels from AC-3 order to SMPTE order. * [channel_mode][lfe][ch] @@ -126,7 +108,7 @@ }; /* possible frequencies */ -const uint16_t ff_ac3_sample_rate_tab[3] = { 48000, 44100, 32000 }; +const int ff_ac3_sample_rate_tab[] = { 48000, 44100, 32000, 0 }; /* possible bitrates */ const uint16_t ff_ac3_bitrate_tab[19] = { @@ -147,44 +129,6 @@ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1 }; -/* AC-3 MDCT window */ - -/* MDCT window */ -DECLARE_ALIGNED(16, const int16_t, ff_ac3_window)[AC3_WINDOW_SIZE/2] = { - 4, 7, 12, 16, 21, 28, 34, 42, - 51, 61, 72, 84, 97, 111, 127, 145, - 164, 184, 207, 231, 257, 285, 315, 347, - 382, 419, 458, 500, 544, 591, 641, 694, - 750, 810, 872, 937, 1007, 1079, 1155, 1235, - 1318, 1406, 1497, 1593, 1692, 1796, 1903, 2016, - 2132, 2253, 2379, 2509, 2644, 2783, 2927, 3076, - 3230, 3389, 3552, 3721, 3894, 4072, 4255, 4444, - 4637, 4835, 5038, 5246, 5459, 5677, 5899, 6127, - 6359, 6596, 6837, 7083, 7334, 7589, 7848, 8112, - 8380, 8652, 8927, 9207, 9491, 9778,10069,10363, -10660,10960,11264,11570,11879,12190,12504,12820, -13138,13458,13780,14103,14427,14753,15079,15407, -15735,16063,16392,16720,17049,17377,17705,18032, -18358,18683,19007,19330,19651,19970,20287,20602, -20914,21225,21532,21837,22139,22438,22733,23025, -23314,23599,23880,24157,24430,24699,24964,25225, -25481,25732,25979,26221,26459,26691,26919,27142, -27359,27572,27780,27983,28180,28373,28560,28742, -28919,29091,29258,29420,29577,29729,29876,30018, -30155,30288,30415,30538,30657,30771,30880,30985, -31086,31182,31274,31363,31447,31528,31605,31678, -31747,31814,31877,31936,31993,32046,32097,32145, -32190,32232,32272,32310,32345,32378,32409,32438, -32465,32490,32513,32535,32556,32574,32592,32608, -32623,32636,32649,32661,32671,32681,32690,32698, -32705,32712,32718,32724,32729,32733,32737,32741, -32744,32747,32750,32752,32754,32756,32757,32759, -32760,32761,32762,32763,32764,32764,32765,32765, -32766,32766,32766,32766,32767,32767,32767,32767, -32767,32767,32767,32767,32767,32767,32767,32767, -32767,32767,32767,32767,32767,32767,32767,32767, -}; - const uint8_t ff_ac3_log_add_tab[260]= { 0x40,0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x37, 0x36,0x35,0x34,0x34,0x33,0x32,0x31,0x30,0x2f,0x2f, @@ -301,19 +245,6 @@ 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400, }; -/** - * Default channel map for a dependent substream defined by acmod - */ -const uint16_t ff_eac3_default_chmap[8] = { - AC3_CHMAP_L | AC3_CHMAP_R, // FIXME Ch1+Ch2 - AC3_CHMAP_C, - AC3_CHMAP_L | AC3_CHMAP_R, - AC3_CHMAP_L | AC3_CHMAP_C | AC3_CHMAP_R, - AC3_CHMAP_L | AC3_CHMAP_R | AC3_CHMAP_C_SUR, - AC3_CHMAP_L | AC3_CHMAP_C | AC3_CHMAP_R | AC3_CHMAP_C_SUR, - AC3_CHMAP_L | AC3_CHMAP_R | AC3_CHMAP_L_SUR | AC3_CHMAP_R_SUR, - AC3_CHMAP_L | AC3_CHMAP_C | AC3_CHMAP_R | AC3_CHMAP_L_SUR | AC3_CHMAP_R_SUR -}; const uint64_t ff_eac3_custom_channel_map_locations[16][2] = { { 1, AV_CH_FRONT_LEFT }, { 1, AV_CH_FRONT_CENTER }, diff -Nru ffmpeg-4.2.2/libavcodec/ac3tab.h ffmpeg-4.4/libavcodec/ac3tab.h --- ffmpeg-4.2.2/libavcodec/ac3tab.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ac3tab.h 2021-04-08 21:28:39.000000000 +0000 @@ -31,13 +31,11 @@ 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 uint8_t ff_ac3_enc_channel_map[8][2][6]; extern const uint8_t ff_ac3_dec_channel_map[8][2][6]; -extern const uint16_t ff_ac3_sample_rate_tab[3]; +extern const int ff_ac3_sample_rate_tab[]; extern const uint16_t ff_ac3_bitrate_tab[19]; extern const uint8_t ff_ac3_rematrix_band_tab[5]; extern const uint8_t ff_eac3_default_cpl_band_struct[18]; -extern const int16_t ff_ac3_window[AC3_WINDOW_SIZE/2]; extern const uint8_t ff_ac3_log_add_tab[260]; extern const uint16_t ff_ac3_hearing_threshold_tab[AC3_CRITICAL_BANDS][3]; extern const uint8_t ff_ac3_bap_tab[64]; @@ -47,7 +45,6 @@ extern const uint16_t ff_ac3_db_per_bit_tab[4]; extern const int16_t ff_ac3_floor_tab[8]; extern const uint16_t ff_ac3_fast_gain_tab[8]; -extern const uint16_t ff_eac3_default_chmap[8]; extern const uint8_t ff_ac3_band_start_tab[AC3_CRITICAL_BANDS+1]; extern const uint8_t ff_ac3_bin_to_band_tab[253]; extern const uint64_t ff_eac3_custom_channel_map_locations[16][2]; @@ -68,4 +65,12 @@ AC3_CHMAP_LFE = 1<<(15-15) }; +#define COMMON_CHANNEL_MAP \ + { { 0, 1, }, { 0, 1, 2, } },\ + { { 0, }, { 0, 1, } },\ + { { 0, 1, }, { 0, 1, 2, } },\ + { { 0, 2, 1, }, { 0, 2, 1, 3, } },\ + { { 0, 1, 2, }, { 0, 1, 3, 2, } },\ + { { 0, 2, 1, 3, }, { 0, 2, 1, 4, 3, } }, + #endif /* AVCODEC_AC3TAB_H */ diff -Nru ffmpeg-4.2.2/libavcodec/acelp_pitch_delay.c ffmpeg-4.4/libavcodec/acelp_pitch_delay.c --- ffmpeg-4.2.2/libavcodec/acelp_pitch_delay.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/acelp_pitch_delay.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,47 +29,6 @@ #include "celp_math.h" #include "audiodsp.h" -int ff_acelp_decode_8bit_to_1st_delay3(int ac_index) -{ - ac_index += 58; - if(ac_index > 254) - ac_index = 3 * ac_index - 510; - return ac_index; -} - -int ff_acelp_decode_4bit_to_2nd_delay3( - int ac_index, - int pitch_delay_min) -{ - if(ac_index < 4) - return 3 * (ac_index + pitch_delay_min); - else if(ac_index < 12) - return 3 * pitch_delay_min + ac_index + 6; - else - return 3 * (ac_index + pitch_delay_min) - 18; -} - -int ff_acelp_decode_5_6_bit_to_2nd_delay3( - int ac_index, - int pitch_delay_min) -{ - return 3 * pitch_delay_min + ac_index - 2; -} - -int ff_acelp_decode_9bit_to_1st_delay6(int ac_index) -{ - if(ac_index < 463) - return ac_index + 105; - else - return 6 * (ac_index - 368); -} -int ff_acelp_decode_6bit_to_2nd_delay6( - int ac_index, - int pitch_delay_min) -{ - return 6 * pitch_delay_min + ac_index - 3; -} - void ff_acelp_update_past_gain( int16_t* quant_energy, int gain_corr_factor, diff -Nru ffmpeg-4.2.2/libavcodec/acelp_pitch_delay.h ffmpeg-4.4/libavcodec/acelp_pitch_delay.h --- ffmpeg-4.2.2/libavcodec/acelp_pitch_delay.h 2016-03-29 02:25:10.000000000 +0000 +++ ffmpeg-4.4/libavcodec/acelp_pitch_delay.h 2021-04-08 21:28:39.000000000 +0000 @@ -41,7 +41,13 @@ * with 1/3 resolution, 19 < pitch_delay < 85 * integers only, 85 <= pitch_delay <= 143 */ -int ff_acelp_decode_8bit_to_1st_delay3(int ac_index); +static inline int ff_acelp_decode_8bit_to_1st_delay3(int ac_index) +{ + ac_index += 58; + if (ac_index > 254) + ac_index = 3 * ac_index - 510; + return ac_index; +} /** * @brief Decode pitch delay of the second subframe encoded by 5 or 6 bits @@ -58,9 +64,11 @@ * @remark The routine is used in G.729 @@8k, AMR @@10.2k, AMR @@7.95k, * AMR @@7.4k for the second subframe. */ -int ff_acelp_decode_5_6_bit_to_2nd_delay3( - int ac_index, - int pitch_delay_min); +static inline int ff_acelp_decode_5_6_bit_to_2nd_delay3(int ac_index, + int pitch_delay_min) +{ + return 3 * pitch_delay_min + ac_index - 2; +} /** * @brief Decode pitch delay with 1/3 precision. @@ -78,9 +86,16 @@ * @remark The routine is used in G.729 @@6.4k, AMR @@6.7k, AMR @@5.9k, * AMR @@5.15k, AMR @@4.75k for the second subframe. */ -int ff_acelp_decode_4bit_to_2nd_delay3( - int ac_index, - int pitch_delay_min); +static inline int ff_acelp_decode_4bit_to_2nd_delay3(int ac_index, + int pitch_delay_min) +{ + if (ac_index < 4) + return 3 * (ac_index + pitch_delay_min); + else if (ac_index < 12) + return 3 * pitch_delay_min + ac_index + 6; + else + return 3 * (ac_index + pitch_delay_min) - 18; +} /** * @brief Decode pitch delay of the first subframe encoded by 9 bits @@ -95,7 +110,13 @@ * * @remark The routine is used in AMR @@12.2k for the first and third subframes. */ -int ff_acelp_decode_9bit_to_1st_delay6(int ac_index); +static inline int ff_acelp_decode_9bit_to_1st_delay6(int ac_index) +{ + if (ac_index < 463) + return ac_index + 105; + else + return 6 * (ac_index - 368); +} /** * @brief Decode pitch delay of the second subframe encoded by 6 bits @@ -111,9 +132,11 @@ * * @remark The routine is used in AMR @@12.2k for the second and fourth subframes. */ -int ff_acelp_decode_6bit_to_2nd_delay6( - int ac_index, - int pitch_delay_min); +static inline int ff_acelp_decode_6bit_to_2nd_delay6(int ac_index, + int pitch_delay_min) +{ + return 6 * pitch_delay_min + ac_index - 3; +} /** * @brief Update past quantized energies diff -Nru ffmpeg-4.2.2/libavcodec/acelp_vectors.c ffmpeg-4.4/libavcodec/acelp_vectors.c --- ffmpeg-4.2.2/libavcodec/acelp_vectors.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/acelp_vectors.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,17 +28,6 @@ #include "avcodec.h" #include "acelp_vectors.h" -const uint8_t ff_fc_2pulses_9bits_track1[16] = -{ - 1, 3, - 6, 8, - 11, 13, - 16, 18, - 21, 23, - 26, 28, - 31, 33, - 36, 38 -}; const uint8_t ff_fc_2pulses_9bits_track1_gray[16] = { 1, 3, diff -Nru ffmpeg-4.2.2/libavcodec/acelp_vectors.h ffmpeg-4.4/libavcodec/acelp_vectors.h --- ffmpeg-4.2.2/libavcodec/acelp_vectors.h 2016-03-29 02:25:10.000000000 +0000 +++ ffmpeg-4.4/libavcodec/acelp_vectors.h 2021-04-08 21:28:39.000000000 +0000 @@ -102,7 +102,6 @@ * * Used in G.729 @@6.4k (with gray coding), AMR @@5.9k (without gray coding) */ -extern const uint8_t ff_fc_2pulses_9bits_track1[16]; extern const uint8_t ff_fc_2pulses_9bits_track1_gray[16]; /** diff -Nru ffmpeg-4.2.2/libavcodec/adpcm.c ffmpeg-4.4/libavcodec/adpcm.c --- ffmpeg-4.2.2/libavcodec/adpcm.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/adpcm.c 2021-04-08 21:28:39.000000000 +0000 @@ -12,6 +12,11 @@ * EA ADPCM XAS decoder by Peter Ross (pross@xvid.org) * MAXIS EA ADPCM decoder by Robert Marston (rmarston@gmail.com) * THP ADPCM decoder by Marco Gerards (mgerards@xs4all.nl) + * Argonaut Games ADPCM decoder by Zane van Iperen (zane@zanevaniperen.com) + * Simon & Schuster Interactive ADPCM decoder by Zane van Iperen (zane@zanevaniperen.com) + * Ubisoft ADPCM decoder by Zane van Iperen (zane@zanevaniperen.com) + * High Voltage Software ALP decoder by Zane van Iperen (zane@zanevaniperen.com) + * Cunning Developments decoder by Zane van Iperen (zane@zanevaniperen.com) * * This file is part of FFmpeg. * @@ -81,12 +86,21 @@ /*5*/ { -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16 } }; +static const int8_t zork_index_table[8] = { + -1, -1, -1, 1, 4, 7, 10, 12, +}; + +static const int8_t mtf_index_table[16] = { + 8, 6, 4, 2, -1, -1, -1, -1, + -1, -1, -1, -1, 2, 4, 6, 8, +}; + /* end of tables */ typedef struct ADPCMDecodeContext { ADPCMChannelStatus status[14]; int vqa_version; /**< VQA version. Used for ADPCM_IMA_WS */ - int has_status; + int has_status; /**< Status flag. Reset to 0 after a flush. */ } ADPCMDecodeContext; static av_cold int adpcm_decode_init(AVCodecContext * avctx) @@ -96,6 +110,9 @@ unsigned int max_channels = 2; switch(avctx->codec->id) { + case AV_CODEC_ID_ADPCM_IMA_AMV: + max_channels = 1; + break; case AV_CODEC_ID_ADPCM_DTK: case AV_CODEC_ID_ADPCM_EA: min_channels = 2; @@ -105,18 +122,21 @@ case AV_CODEC_ID_ADPCM_EA_R2: case AV_CODEC_ID_ADPCM_EA_R3: case AV_CODEC_ID_ADPCM_EA_XAS: + case AV_CODEC_ID_ADPCM_MS: max_channels = 6; break; case AV_CODEC_ID_ADPCM_MTAF: min_channels = 2; max_channels = 8; if (avctx->channels & 1) { - avpriv_request_sample(avctx, "channel count %d\n", avctx->channels); + avpriv_request_sample(avctx, "channel count %d", avctx->channels); return AVERROR_PATCHWELCOME; } break; case AV_CODEC_ID_ADPCM_PSX: max_channels = 8; + if (avctx->channels <= 0 || avctx->block_align % (16 * avctx->channels)) + return AVERROR_INVALIDDATA; break; case AV_CODEC_ID_ADPCM_IMA_DAT4: case AV_CODEC_ID_ADPCM_THP: @@ -143,39 +163,69 @@ c->status[1].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 4), 18); } break; + case AV_CODEC_ID_ADPCM_IMA_APM: + if (avctx->extradata) { + if (avctx->extradata_size >= 28) { + c->status[0].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 16), 18); + c->status[0].step_index = av_clip(AV_RL32(avctx->extradata + 20), 0, 88); + c->status[1].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 4), 18); + c->status[1].step_index = av_clip(AV_RL32(avctx->extradata + 8), 0, 88); + } else if (avctx->extradata_size >= 16) { + c->status[0].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 0), 18); + c->status[0].step_index = av_clip(AV_RL32(avctx->extradata + 4), 0, 88); + c->status[1].predictor = av_clip_intp2(AV_RL32(avctx->extradata + 8), 18); + c->status[1].step_index = av_clip(AV_RL32(avctx->extradata + 12), 0, 88); + } + } + break; case AV_CODEC_ID_ADPCM_IMA_WS: if (avctx->extradata && avctx->extradata_size >= 2) c->vqa_version = AV_RL16(avctx->extradata); break; + case AV_CODEC_ID_ADPCM_ARGO: + if (avctx->bits_per_coded_sample != 4 || avctx->block_align != 17 * avctx->channels) + return AVERROR_INVALIDDATA; + break; + case AV_CODEC_ID_ADPCM_ZORK: + if (avctx->bits_per_coded_sample != 8) + return AVERROR_INVALIDDATA; + break; default: break; } - switch(avctx->codec->id) { - case AV_CODEC_ID_ADPCM_AICA: - case AV_CODEC_ID_ADPCM_IMA_DAT4: - case AV_CODEC_ID_ADPCM_IMA_QT: - case AV_CODEC_ID_ADPCM_IMA_WAV: - case AV_CODEC_ID_ADPCM_4XM: - case AV_CODEC_ID_ADPCM_XA: - case AV_CODEC_ID_ADPCM_EA_R1: - case AV_CODEC_ID_ADPCM_EA_R2: - case AV_CODEC_ID_ADPCM_EA_R3: - case AV_CODEC_ID_ADPCM_EA_XAS: - case AV_CODEC_ID_ADPCM_THP: - case AV_CODEC_ID_ADPCM_THP_LE: - case AV_CODEC_ID_ADPCM_AFC: - case AV_CODEC_ID_ADPCM_DTK: - case AV_CODEC_ID_ADPCM_PSX: - case AV_CODEC_ID_ADPCM_MTAF: - avctx->sample_fmt = AV_SAMPLE_FMT_S16P; - break; - case AV_CODEC_ID_ADPCM_IMA_WS: - avctx->sample_fmt = c->vqa_version == 3 ? AV_SAMPLE_FMT_S16P : - AV_SAMPLE_FMT_S16; - break; - default: - avctx->sample_fmt = AV_SAMPLE_FMT_S16; + switch (avctx->codec->id) { + case AV_CODEC_ID_ADPCM_AICA: + case AV_CODEC_ID_ADPCM_IMA_CUNNING: + case AV_CODEC_ID_ADPCM_IMA_DAT4: + case AV_CODEC_ID_ADPCM_IMA_QT: + case AV_CODEC_ID_ADPCM_IMA_WAV: + case AV_CODEC_ID_ADPCM_4XM: + case AV_CODEC_ID_ADPCM_XA: + case AV_CODEC_ID_ADPCM_EA_R1: + case AV_CODEC_ID_ADPCM_EA_R2: + case AV_CODEC_ID_ADPCM_EA_R3: + case AV_CODEC_ID_ADPCM_EA_XAS: + case AV_CODEC_ID_ADPCM_THP: + case AV_CODEC_ID_ADPCM_THP_LE: + case AV_CODEC_ID_ADPCM_AFC: + case AV_CODEC_ID_ADPCM_DTK: + case AV_CODEC_ID_ADPCM_PSX: + case AV_CODEC_ID_ADPCM_MTAF: + case AV_CODEC_ID_ADPCM_ARGO: + case AV_CODEC_ID_ADPCM_IMA_MOFLEX: + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + break; + case AV_CODEC_ID_ADPCM_IMA_WS: + avctx->sample_fmt = c->vqa_version == 3 ? AV_SAMPLE_FMT_S16P : + AV_SAMPLE_FMT_S16; + break; + case AV_CODEC_ID_ADPCM_MS: + avctx->sample_fmt = avctx->channels > 2 ? AV_SAMPLE_FMT_S16P : + AV_SAMPLE_FMT_S16; + break; + default: + avctx->sample_fmt = AV_SAMPLE_FMT_S16; } return 0; @@ -251,6 +301,65 @@ return (int16_t)c->predictor; } +static inline int16_t adpcm_ima_alp_expand_nibble(ADPCMChannelStatus *c, int8_t nibble, int shift) +{ + int step_index; + int predictor; + int sign, delta, diff, step; + + step = ff_adpcm_step_table[c->step_index]; + step_index = c->step_index + ff_adpcm_index_table[(unsigned)nibble]; + step_index = av_clip(step_index, 0, 88); + + sign = nibble & 8; + delta = nibble & 7; + diff = (delta * step) >> shift; + predictor = c->predictor; + if (sign) predictor -= diff; + else predictor += diff; + + c->predictor = av_clip_int16(predictor); + c->step_index = step_index; + + return (int16_t)c->predictor; +} + +static inline int16_t adpcm_ima_mtf_expand_nibble(ADPCMChannelStatus *c, int nibble) +{ + int step_index, step, delta, predictor; + + step = ff_adpcm_step_table[c->step_index]; + + delta = step * (2 * nibble - 15); + predictor = c->predictor + delta; + + step_index = c->step_index + mtf_index_table[(unsigned)nibble]; + c->predictor = av_clip_int16(predictor >> 4); + c->step_index = av_clip(step_index, 0, 88); + + return (int16_t)c->predictor; +} + +static inline int16_t adpcm_ima_cunning_expand_nibble(ADPCMChannelStatus *c, int8_t nibble) +{ + int step_index; + int predictor; + int step; + + nibble = sign_extend(nibble & 0xF, 4); + + step = ff_adpcm_ima_cunning_step_table[c->step_index]; + step_index = c->step_index + ff_adpcm_ima_cunning_index_table[abs(nibble)]; + step_index = av_clip(step_index, 0, 60); + + predictor = c->predictor + step * nibble; + + c->predictor = av_clip_int16(predictor); + c->step_index = step_index; + + return c->predictor; +} + static inline int16_t adpcm_ima_wav_expand_nibble(ADPCMChannelStatus *c, GetBitContext *gb, int bps) { int nibble, step_index, predictor, sign, delta, diff, step, shift; @@ -274,7 +383,7 @@ return (int16_t)c->predictor; } -static inline int adpcm_ima_qt_expand_nibble(ADPCMChannelStatus *c, int nibble, int shift) +static inline int adpcm_ima_qt_expand_nibble(ADPCMChannelStatus *c, int nibble) { int step_index; int predictor; @@ -404,6 +513,41 @@ return c->predictor; } +static inline int16_t adpcm_zork_expand_nibble(ADPCMChannelStatus *c, uint8_t nibble) +{ + int16_t index = c->step_index; + uint32_t lookup_sample = ff_adpcm_step_table[index]; + int32_t sample = 0; + + if (nibble & 0x40) + sample += lookup_sample; + if (nibble & 0x20) + sample += lookup_sample >> 1; + if (nibble & 0x10) + sample += lookup_sample >> 2; + if (nibble & 0x08) + sample += lookup_sample >> 3; + if (nibble & 0x04) + sample += lookup_sample >> 4; + if (nibble & 0x02) + sample += lookup_sample >> 5; + if (nibble & 0x01) + sample += lookup_sample >> 6; + if (nibble & 0x80) + sample = -sample; + + sample += c->predictor; + sample = av_clip_int16(sample); + + index += zork_index_table[(nibble >> 4) & 7]; + index = av_clip(index, 0, 88); + + c->predictor = sample; + c->step_index = index; + + return sample; +} + static int xa_decode(AVCodecContext *avctx, int16_t *out0, int16_t *out1, const uint8_t *in, ADPCMChannelStatus *left, ADPCMChannelStatus *right, int channels, int sample_offset) @@ -426,6 +570,10 @@ avpriv_request_sample(avctx, "unknown XA-ADPCM filter %d", filter); filter=0; } + if (shift < 0) { + avpriv_request_sample(avctx, "unknown XA-ADPCM shift %d", shift); + shift = 0; + } f0 = xa_adpcm_table[filter][0]; f1 = xa_adpcm_table[filter][1]; @@ -451,10 +599,14 @@ shift = 12 - (in[5+i*2] & 15); filter = in[5+i*2] >> 4; - if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table)) { + if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table) || shift < 0) { avpriv_request_sample(avctx, "unknown XA-ADPCM filter %d", filter); filter=0; } + if (shift < 0) { + avpriv_request_sample(avctx, "unknown XA-ADPCM shift %d", shift); + shift = 0; + } f0 = xa_adpcm_table[filter][0]; f1 = xa_adpcm_table[filter][1]; @@ -541,8 +693,25 @@ } } +int16_t ff_adpcm_argo_expand_nibble(ADPCMChannelStatus *cs, int nibble, int shift, int flag) +{ + int sample = sign_extend(nibble, 4) * (1 << shift); + + if (flag) + sample += (8 * cs->sample1) - (4 * cs->sample2); + else + sample += 4 * cs->sample1; + + sample = av_clip_int16(sample >> 2); + + cs->sample2 = cs->sample1; + cs->sample1 = sample; + + return sample; +} + /** - * Get the number of samples that will be decoded from the packet. + * Get the number of samples (per channel) that will be decoded from the packet. * In one case, this is actually the maximum number of samples possible to * decode with the given buf_size. * @@ -582,11 +751,16 @@ /* simple 4-bit adpcm */ case AV_CODEC_ID_ADPCM_CT: case AV_CODEC_ID_ADPCM_IMA_APC: + case AV_CODEC_ID_ADPCM_IMA_CUNNING: case AV_CODEC_ID_ADPCM_IMA_EA_SEAD: case AV_CODEC_ID_ADPCM_IMA_OKI: case AV_CODEC_ID_ADPCM_IMA_WS: case AV_CODEC_ID_ADPCM_YAMAHA: case AV_CODEC_ID_ADPCM_AICA: + case AV_CODEC_ID_ADPCM_IMA_SSI: + case AV_CODEC_ID_ADPCM_IMA_APM: + case AV_CODEC_ID_ADPCM_IMA_ALP: + case AV_CODEC_ID_ADPCM_IMA_MTF: nb_samples = buf_size * 2 / ch; break; } @@ -599,8 +773,8 @@ case AV_CODEC_ID_ADPCM_4XM: case AV_CODEC_ID_ADPCM_AGM: case AV_CODEC_ID_ADPCM_IMA_DAT4: + case AV_CODEC_ID_ADPCM_IMA_MOFLEX: case AV_CODEC_ID_ADPCM_IMA_ISS: header_size = 4 * ch; break; - case AV_CODEC_ID_ADPCM_IMA_AMV: header_size = 8; break; case AV_CODEC_ID_ADPCM_IMA_SMJPEG: header_size = 4 * ch; break; } if (header_size > 0) @@ -608,6 +782,13 @@ /* more complex formats */ switch (avctx->codec->id) { + case AV_CODEC_ID_ADPCM_IMA_AMV: + bytestream2_skip(gb, 4); + has_coded_samples = 1; + *coded_samples = bytestream2_get_le32u(gb); + nb_samples = FFMIN((buf_size - 8) * 2, *coded_samples); + bytestream2_seek(gb, -8, SEEK_CUR); + break; case AV_CODEC_ID_ADPCM_EA: has_coded_samples = 1; *coded_samples = bytestream2_get_le32(gb); @@ -745,6 +926,12 @@ case AV_CODEC_ID_ADPCM_PSX: nb_samples = buf_size / (16 * ch) * 28; break; + case AV_CODEC_ID_ADPCM_ARGO: + nb_samples = buf_size / avctx->block_align * 32; + break; + case AV_CODEC_ID_ADPCM_ZORK: + nb_samples = buf_size / ch; + break; } /* validate coded sample count */ @@ -831,8 +1018,8 @@ for (m = 0; m < 64; m += 2) { int byte = bytestream2_get_byteu(&gb); - samples[m ] = adpcm_ima_qt_expand_nibble(cs, byte & 0x0F, 3); - samples[m + 1] = adpcm_ima_qt_expand_nibble(cs, byte >> 4 , 3); + samples[m ] = adpcm_ima_qt_expand_nibble(cs, byte & 0x0F); + samples[m + 1] = adpcm_ima_qt_expand_nibble(cs, byte >> 4 ); } } break; @@ -928,42 +1115,66 @@ { int block_predictor; - block_predictor = bytestream2_get_byteu(&gb); - if (block_predictor > 6) { - av_log(avctx, AV_LOG_ERROR, "ERROR: block_predictor[0] = %d\n", - block_predictor); - return AVERROR_INVALIDDATA; - } - c->status[0].coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; - c->status[0].coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; - if (st) { + if (avctx->channels > 2) { + for (channel = 0; channel < avctx->channels; channel++) { + samples = samples_p[channel]; + block_predictor = bytestream2_get_byteu(&gb); + if (block_predictor > 6) { + av_log(avctx, AV_LOG_ERROR, "ERROR: block_predictor[%d] = %d\n", + channel, block_predictor); + return AVERROR_INVALIDDATA; + } + c->status[channel].coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; + c->status[channel].coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; + c->status[channel].idelta = sign_extend(bytestream2_get_le16u(&gb), 16); + c->status[channel].sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); + c->status[channel].sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); + *samples++ = c->status[channel].sample2; + *samples++ = c->status[channel].sample1; + for(n = (nb_samples - 2) >> 1; n > 0; n--) { + int byte = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ms_expand_nibble(&c->status[channel], byte >> 4 ); + *samples++ = adpcm_ms_expand_nibble(&c->status[channel], byte & 0x0F); + } + } + } else { block_predictor = bytestream2_get_byteu(&gb); if (block_predictor > 6) { - av_log(avctx, AV_LOG_ERROR, "ERROR: block_predictor[1] = %d\n", + av_log(avctx, AV_LOG_ERROR, "ERROR: block_predictor[0] = %d\n", block_predictor); return AVERROR_INVALIDDATA; } - c->status[1].coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; - c->status[1].coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; - } - c->status[0].idelta = sign_extend(bytestream2_get_le16u(&gb), 16); - if (st){ - c->status[1].idelta = sign_extend(bytestream2_get_le16u(&gb), 16); - } - - c->status[0].sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); - if (st) c->status[1].sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); - c->status[0].sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); - if (st) c->status[1].sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); - - *samples++ = c->status[0].sample2; - if (st) *samples++ = c->status[1].sample2; - *samples++ = c->status[0].sample1; - if (st) *samples++ = c->status[1].sample1; - for(n = (nb_samples - 2) >> (1 - st); n > 0; n--) { - int byte = bytestream2_get_byteu(&gb); - *samples++ = adpcm_ms_expand_nibble(&c->status[0 ], byte >> 4 ); - *samples++ = adpcm_ms_expand_nibble(&c->status[st], byte & 0x0F); + c->status[0].coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; + c->status[0].coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; + if (st) { + block_predictor = bytestream2_get_byteu(&gb); + if (block_predictor > 6) { + av_log(avctx, AV_LOG_ERROR, "ERROR: block_predictor[1] = %d\n", + block_predictor); + return AVERROR_INVALIDDATA; + } + c->status[1].coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; + c->status[1].coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; + } + c->status[0].idelta = sign_extend(bytestream2_get_le16u(&gb), 16); + if (st){ + c->status[1].idelta = sign_extend(bytestream2_get_le16u(&gb), 16); + } + + c->status[0].sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); + if (st) c->status[1].sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); + c->status[0].sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); + if (st) c->status[1].sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); + + *samples++ = c->status[0].sample2; + if (st) *samples++ = c->status[1].sample2; + *samples++ = c->status[0].sample1; + if (st) *samples++ = c->status[1].sample1; + for(n = (nb_samples - 2) >> (1 - st); n > 0; n--) { + int byte = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ms_expand_nibble(&c->status[0 ], byte >> 4 ); + *samples++ = adpcm_ms_expand_nibble(&c->status[st], byte & 0x0F); + } } break; } @@ -1096,6 +1307,29 @@ *samples++ = adpcm_ima_expand_nibble(&c->status[st], v2, 3); } break; + case AV_CODEC_ID_ADPCM_IMA_MOFLEX: + for (channel = 0; channel < avctx->channels; channel++) { + cs = &c->status[channel]; + cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16); + cs->predictor = sign_extend(bytestream2_get_le16u(&gb), 16); + if (cs->step_index > 88u){ + av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n", + channel, cs->step_index); + return AVERROR_INVALIDDATA; + } + } + + for (int subframe = 0; subframe < nb_samples / 256; subframe++) { + for (channel = 0; channel < avctx->channels; channel++) { + samples = samples_p[channel] + 256 * subframe; + for (n = 0; n < 256; n += 2) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_expand_nibble(&c->status[channel], v & 0x0F, 3); + *samples++ = adpcm_ima_expand_nibble(&c->status[channel], v >> 4 , 3); + } + } + } + break; case AV_CODEC_ID_ADPCM_IMA_DAT4: for (channel = 0; channel < avctx->channels; channel++) { cs = &c->status[channel]; @@ -1109,14 +1343,51 @@ } break; case AV_CODEC_ID_ADPCM_IMA_APC: - while (bytestream2_get_bytes_left(&gb) > 0) { + for (n = nb_samples >> (1 - st); n > 0; n--) { int v = bytestream2_get_byteu(&gb); *samples++ = adpcm_ima_expand_nibble(&c->status[0], v >> 4 , 3); *samples++ = adpcm_ima_expand_nibble(&c->status[st], v & 0x0F, 3); } break; + case AV_CODEC_ID_ADPCM_IMA_SSI: + for (n = nb_samples >> (1 - st); n > 0; n--) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_qt_expand_nibble(&c->status[0], v >> 4 ); + *samples++ = adpcm_ima_qt_expand_nibble(&c->status[st], v & 0x0F); + } + break; + case AV_CODEC_ID_ADPCM_IMA_APM: + for (n = nb_samples / 2; n > 0; n--) { + for (channel = 0; channel < avctx->channels; channel++) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_qt_expand_nibble(&c->status[channel], v >> 4 ); + samples[st] = adpcm_ima_qt_expand_nibble(&c->status[channel], v & 0x0F); + } + samples += avctx->channels; + } + break; + case AV_CODEC_ID_ADPCM_IMA_ALP: + for (n = nb_samples / 2; n > 0; n--) { + for (channel = 0; channel < avctx->channels; channel++) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_alp_expand_nibble(&c->status[channel], v >> 4 , 2); + samples[st] = adpcm_ima_alp_expand_nibble(&c->status[channel], v & 0x0F, 2); + } + samples += avctx->channels; + } + break; + case AV_CODEC_ID_ADPCM_IMA_CUNNING: + for (channel = 0; channel < avctx->channels; channel++) { + int16_t *smp = samples_p[channel]; + for (n = 0; n < nb_samples / 2; n++) { + int v = bytestream2_get_byteu(&gb); + *smp++ = adpcm_ima_cunning_expand_nibble(&c->status[channel], v & 0x0F); + *smp++ = adpcm_ima_cunning_expand_nibble(&c->status[channel], v >> 4); + } + } + break; case AV_CODEC_ID_ADPCM_IMA_OKI: - while (bytestream2_get_bytes_left(&gb) > 0) { + for (n = nb_samples >> (1 - st); n > 0; n--) { int v = bytestream2_get_byteu(&gb); *samples++ = adpcm_ima_oki_expand_nibble(&c->status[0], v >> 4 ); *samples++ = adpcm_ima_oki_expand_nibble(&c->status[st], v & 0x0F); @@ -1204,7 +1475,7 @@ } for (i=0; i<=st; i++) { c->status[i].predictor = bytestream2_get_le32u(&gb); - if (FFABS(c->status[i].predictor) > (1<<16)) + if (FFABS((int64_t)c->status[i].predictor) > (1<<16)) return AVERROR_INVALIDDATA; } @@ -1253,8 +1524,8 @@ for (count2 = 0; count2 < 28; count2++) { byte = bytestream2_get_byteu(&gb); - next_left_sample = sign_extend(byte >> 4, 4) << shift_left; - next_right_sample = sign_extend(byte, 4) << shift_right; + next_left_sample = sign_extend(byte >> 4, 4) * (1 << shift_left); + next_right_sample = sign_extend(byte, 4) * (1 << shift_right); next_left_sample = (next_left_sample + (current_left_sample * coeff1l) + @@ -1293,7 +1564,7 @@ if (st) byte[1] = bytestream2_get_byteu(&gb); for(i = 4; i >= 0; i-=4) { /* Pairwise samples LL RR (st) or LL LL (mono) */ for(channel = 0; channel < avctx->channels; channel++) { - int sample = sign_extend(byte[channel] >> i, 4) << shift[channel]; + int sample = sign_extend(byte[channel] >> i, 4) * (1 << shift[channel]); sample = (sample + c->status[channel].sample1 * coeff[channel][0] + c->status[channel].sample2 * coeff[channel][1] + 0x80) >> 8; @@ -1408,11 +1679,11 @@ int level, pred; int byte = bytestream2_get_byteu(&gb); - level = sign_extend(byte >> 4, 4) << shift[n]; + level = sign_extend(byte >> 4, 4) * (1 << shift[n]); pred = s[-1] * coeff[0][n] + s[-2] * coeff[1][n]; s[0] = av_clip_int16((level + pred + 0x80) >> 8); - level = sign_extend(byte, 4) << shift[n]; + level = sign_extend(byte, 4) * (1 << shift[n]); pred = s[0] * coeff[0][n] + s[-1] * coeff[1][n]; s[1] = av_clip_int16((level + pred + 0x80) >> 8); } @@ -1420,6 +1691,18 @@ } break; case AV_CODEC_ID_ADPCM_IMA_AMV: + av_assert0(avctx->channels == 1); + + /* + * Header format: + * int16_t predictor; + * uint8_t step_index; + * uint8_t reserved; + * uint32_t frame_size; + * + * Some implementations have step_index as 16-bits, but others + * only use the lower 8 and store garbage in the upper 8. + */ c->status[0].predictor = sign_extend(bytestream2_get_le16u(&gb), 16); c->status[0].step_index = bytestream2_get_byteu(&gb); bytestream2_skipu(&gb, 5); @@ -1429,12 +1712,23 @@ return AVERROR_INVALIDDATA; } - for (n = nb_samples >> (1 - st); n > 0; n--) { + for (n = nb_samples >> 1; n > 0; n--) { int v = bytestream2_get_byteu(&gb); *samples++ = adpcm_ima_expand_nibble(&c->status[0], v >> 4, 3); *samples++ = adpcm_ima_expand_nibble(&c->status[0], v & 0xf, 3); } + + if (nb_samples & 1) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_expand_nibble(&c->status[0], v >> 4, 3); + + if (v & 0x0F) { + /* Holds true on all the http://samples.mplayerhq.hu/amv samples. */ + av_log(avctx, AV_LOG_WARNING, "Last nibble set on packet with odd sample count.\n"); + av_log(avctx, AV_LOG_WARNING, "Sample will be skipped.\n"); + } + } break; case AV_CODEC_ID_ADPCM_IMA_SMJPEG: for (i = 0; i < avctx->channels; i++) { @@ -1451,8 +1745,8 @@ for (n = nb_samples >> (1 - st); n > 0; n--) { int v = bytestream2_get_byteu(&gb); - *samples++ = adpcm_ima_qt_expand_nibble(&c->status[0 ], v >> 4, 3); - *samples++ = adpcm_ima_qt_expand_nibble(&c->status[st], v & 0xf, 3); + *samples++ = adpcm_ima_qt_expand_nibble(&c->status[0 ], v >> 4 ); + *samples++ = adpcm_ima_qt_expand_nibble(&c->status[st], v & 0xf); } break; case AV_CODEC_ID_ADPCM_CT: @@ -1517,11 +1811,6 @@ } break; case AV_CODEC_ID_ADPCM_AICA: - if (!c->has_status) { - for (channel = 0; channel < avctx->channels; channel++) - c->status[channel].step = 0; - c->has_status = 1; - } for (channel = 0; channel < avctx->channels; channel++) { samples = samples_p[channel]; for (n = nb_samples >> 1; n > 0; n--) { @@ -1569,8 +1858,8 @@ sampledat = sign_extend(byte >> 4, 4); } - sampledat = ((prev1 * factor1 + prev2 * factor2) + - ((sampledat * scale) << 11)) >> 11; + sampledat = ((prev1 * factor1 + prev2 * factor2) >> 11) + + sampledat * scale; *samples = av_clip_int16(sampledat); prev2 = prev1; prev1 = *samples++; @@ -1632,8 +1921,8 @@ int byte = bytestream2_get_byteu(&gb); int index = (byte >> 4) & 7; unsigned int exp = byte & 0x0F; - int factor1 = table[ch][index * 2]; - int factor2 = table[ch][index * 2 + 1]; + int64_t factor1 = table[ch][index * 2]; + int64_t factor2 = table[ch][index * 2 + 1]; /* Decode 14 samples. */ for (n = 0; n < 14 && (i * 14 + n < nb_samples); n++) { @@ -1647,7 +1936,7 @@ } sampledat = ((c->status[ch].sample1 * factor1 - + c->status[ch].sample2 * factor2) >> 11) + (sampledat << exp); + + c->status[ch].sample2 * factor2) >> 11) + sampledat * (1 << exp); *samples = av_clip_int16(sampledat); c->status[ch].sample2 = c->status[ch].sample1; c->status[ch].sample1 = *samples++; @@ -1705,43 +1994,99 @@ } break; case AV_CODEC_ID_ADPCM_PSX: - for (channel = 0; channel < avctx->channels; channel++) { - samples = samples_p[channel]; - - /* Read in every sample for this channel. */ - for (i = 0; i < nb_samples / 28; i++) { - int filter, shift, flag, byte; + for (int block = 0; block < avpkt->size / FFMAX(avctx->block_align, 16 * avctx->channels); block++) { + int nb_samples_per_block = 28 * FFMAX(avctx->block_align, 16 * avctx->channels) / (16 * avctx->channels); + for (channel = 0; channel < avctx->channels; channel++) { + samples = samples_p[channel] + block * nb_samples_per_block; + av_assert0((block + 1) * nb_samples_per_block <= nb_samples); - filter = bytestream2_get_byteu(&gb); - shift = filter & 0xf; - filter = filter >> 4; - if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table)) - return AVERROR_INVALIDDATA; - flag = bytestream2_get_byteu(&gb); + /* Read in every sample for this channel. */ + for (i = 0; i < nb_samples_per_block / 28; i++) { + int filter, shift, flag, byte; + + filter = bytestream2_get_byteu(&gb); + shift = filter & 0xf; + filter = filter >> 4; + if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table)) + return AVERROR_INVALIDDATA; + flag = bytestream2_get_byteu(&gb); + + /* Decode 28 samples. */ + for (n = 0; n < 28; n++) { + int sample = 0, scale; + + if (flag < 0x07) { + if (n & 1) { + scale = sign_extend(byte >> 4, 4); + } else { + byte = bytestream2_get_byteu(&gb); + scale = sign_extend(byte, 4); + } - /* Decode 28 samples. */ - for (n = 0; n < 28; n++) { - int sample = 0, scale; - - if (flag < 0x07) { - if (n & 1) { - scale = sign_extend(byte >> 4, 4); - } else { - byte = bytestream2_get_byteu(&gb); - scale = sign_extend(byte, 4); + scale = scale * (1 << 12); + sample = (int)((scale >> shift) + (c->status[channel].sample1 * xa_adpcm_table[filter][0] + c->status[channel].sample2 * xa_adpcm_table[filter][1]) / 64); } - - scale = scale << 12; - sample = (int)((scale >> shift) + (c->status[channel].sample1 * xa_adpcm_table[filter][0] + c->status[channel].sample2 * xa_adpcm_table[filter][1]) / 64); + *samples++ = av_clip_int16(sample); + c->status[channel].sample2 = c->status[channel].sample1; + c->status[channel].sample1 = sample; } - *samples++ = av_clip_int16(sample); - c->status[channel].sample2 = c->status[channel].sample1; - c->status[channel].sample1 = sample; } } } break; + case AV_CODEC_ID_ADPCM_ARGO: + /* + * The format of each block: + * uint8_t left_control; + * uint4_t left_samples[nb_samples]; + * ---- and if stereo ---- + * uint8_t right_control; + * uint4_t right_samples[nb_samples]; + * + * Format of the control byte: + * MSB [SSSSRDRR] LSB + * S = (Shift Amount - 2) + * D = Decoder flag. + * R = Reserved + * + * Each block relies on the previous two samples of each channel. + * They should be 0 initially. + */ + for (int block = 0; block < avpkt->size / avctx->block_align; block++) { + for (channel = 0; channel < avctx->channels; channel++) { + int control, shift; + + samples = samples_p[channel] + block * 32; + cs = c->status + channel; + /* Get the control byte and decode the samples, 2 at a time. */ + control = bytestream2_get_byteu(&gb); + shift = (control >> 4) + 2; + + for (n = 0; n < 16; n++) { + int sample = bytestream2_get_byteu(&gb); + *samples++ = ff_adpcm_argo_expand_nibble(cs, sample >> 4, shift, control & 0x04); + *samples++ = ff_adpcm_argo_expand_nibble(cs, sample >> 0, shift, control & 0x04); + } + } + } + break; + case AV_CODEC_ID_ADPCM_ZORK: + for (n = 0; n < nb_samples * avctx->channels; n++) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_zork_expand_nibble(&c->status[n % avctx->channels], v); + } + break; + case AV_CODEC_ID_ADPCM_IMA_MTF: + for (n = nb_samples / 2; n > 0; n--) { + for (channel = 0; channel < avctx->channels; channel++) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_mtf_expand_nibble(&c->status[channel], v >> 4); + samples[st] = adpcm_ima_mtf_expand_nibble(&c->status[channel], v & 0x0F); + } + samples += avctx->channels; + } + break; default: av_assert0(0); // unsupported codec_id should not happen } @@ -1764,7 +2109,37 @@ static void adpcm_flush(AVCodecContext *avctx) { ADPCMDecodeContext *c = avctx->priv_data; - c->has_status = 0; + + switch(avctx->codec_id) { + case AV_CODEC_ID_ADPCM_AICA: + for (int channel = 0; channel < avctx->channels; channel++) + c->status[channel].step = 0; + break; + + case AV_CODEC_ID_ADPCM_ARGO: + for (int channel = 0; channel < avctx->channels; channel++) { + c->status[channel].sample1 = 0; + c->status[channel].sample2 = 0; + } + break; + + case AV_CODEC_ID_ADPCM_IMA_ALP: + case AV_CODEC_ID_ADPCM_IMA_CUNNING: + case AV_CODEC_ID_ADPCM_IMA_SSI: + case AV_CODEC_ID_ADPCM_ZORK: + for (int channel = 0; channel < avctx->channels; channel++) { + c->status[channel].predictor = 0; + c->status[channel].step_index = 0; + } + break; + + default: + /* Other codecs may want to handle this during decoding. */ + c->has_status = 0; + return; + } + + c->has_status = 1; } @@ -1788,6 +2163,7 @@ .flush = adpcm_flush, \ .capabilities = AV_CODEC_CAP_DR1, \ .sample_fmts = sample_fmts_, \ + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \ } /* Note: Do not forget to add new entries to the Makefile as well. */ @@ -1795,6 +2171,7 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_AFC, sample_fmts_s16p, adpcm_afc, "ADPCM Nintendo Gamecube AFC"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_AGM, sample_fmts_s16, adpcm_agm, "ADPCM AmuseGraphics Movie"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_AICA, sample_fmts_s16p, adpcm_aica, "ADPCM Yamaha AICA"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_ARGO, sample_fmts_s16p, adpcm_argo, "ADPCM Argonaut Games"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_CT, sample_fmts_s16, adpcm_ct, "ADPCM Creative Technology"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_DTK, sample_fmts_s16p, adpcm_dtk, "ADPCM Nintendo Gamecube DTK"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA, sample_fmts_s16, adpcm_ea, "ADPCM Electronic Arts"); @@ -1805,19 +2182,25 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_XAS, sample_fmts_s16p, adpcm_ea_xas, "ADPCM Electronic Arts XAS"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_AMV, sample_fmts_s16, adpcm_ima_amv, "ADPCM IMA AMV"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_APC, sample_fmts_s16, adpcm_ima_apc, "ADPCM IMA CRYO APC"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_APM, sample_fmts_s16, adpcm_ima_apm, "ADPCM IMA Ubisoft APM"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_CUNNING, sample_fmts_s16p, adpcm_ima_cunning, "ADPCM IMA Cunning Developments"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DAT4, sample_fmts_s16, adpcm_ima_dat4, "ADPCM IMA Eurocom DAT4"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK3, sample_fmts_s16, adpcm_ima_dk3, "ADPCM IMA Duck DK3"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK4, sample_fmts_s16, adpcm_ima_dk4, "ADPCM IMA Duck DK4"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_EACS, sample_fmts_s16, adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_SEAD, sample_fmts_s16, adpcm_ima_ea_sead, "ADPCM IMA Electronic Arts SEAD"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_ISS, sample_fmts_s16, adpcm_ima_iss, "ADPCM IMA Funcom ISS"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_MOFLEX, sample_fmts_s16p, adpcm_ima_moflex, "ADPCM IMA MobiClip MOFLEX"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_MTF, sample_fmts_s16, adpcm_ima_mtf, "ADPCM IMA Capcom's MT Framework"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_OKI, sample_fmts_s16, adpcm_ima_oki, "ADPCM IMA Dialogic OKI"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_QT, sample_fmts_s16p, adpcm_ima_qt, "ADPCM IMA QuickTime"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_RAD, sample_fmts_s16, adpcm_ima_rad, "ADPCM IMA Radical"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_SSI, sample_fmts_s16, adpcm_ima_ssi, "ADPCM IMA Simon & Schuster Interactive"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_SMJPEG, sample_fmts_s16, adpcm_ima_smjpeg, "ADPCM IMA Loki SDL MJPEG"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_ALP, sample_fmts_s16, adpcm_ima_alp, "ADPCM IMA High Voltage Software ALP"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WAV, sample_fmts_s16p, adpcm_ima_wav, "ADPCM IMA WAV"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WS, sample_fmts_both, adpcm_ima_ws, "ADPCM IMA Westwood"); -ADPCM_DECODER(AV_CODEC_ID_ADPCM_MS, sample_fmts_s16, adpcm_ms, "ADPCM Microsoft"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_MS, sample_fmts_both, adpcm_ms, "ADPCM Microsoft"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_MTAF, sample_fmts_s16p, adpcm_mtaf, "ADPCM MTAF"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_PSX, sample_fmts_s16p, adpcm_psx, "ADPCM Playstation"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_SBPRO_2, sample_fmts_s16, adpcm_sbpro_2, "ADPCM Sound Blaster Pro 2-bit"); @@ -1828,3 +2211,4 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_THP, sample_fmts_s16p, adpcm_thp, "ADPCM Nintendo THP"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_XA, sample_fmts_s16p, adpcm_xa, "ADPCM CDROM XA"); ADPCM_DECODER(AV_CODEC_ID_ADPCM_YAMAHA, sample_fmts_s16, adpcm_yamaha, "ADPCM Yamaha"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_ZORK, sample_fmts_s16, adpcm_zork, "ADPCM Zork"); diff -Nru ffmpeg-4.2.2/libavcodec/adpcm_data.c ffmpeg-4.4/libavcodec/adpcm_data.c --- ffmpeg-4.2.2/libavcodec/adpcm_data.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/adpcm_data.c 2021-04-08 21:28:39.000000000 +0000 @@ -177,3 +177,28 @@ { 424, 1273, 2121, 2970, 3819, 4668, 5516, 6365, -424, -1273, -2121, -2970, -3819, -4668, -5516, -6365, }, }; + +/* + * Dumped from the binaries: + * - FantasticJourney.exe - 0x794D2, DGROUP:0x47A4D2 + * - BigRaceUSA.exe - 0x9B8AA, DGROUP:0x49C4AA + * - Timeshock!.exe - 0x8506A, DGROUP:0x485C6A + */ +const int8_t ff_adpcm_ima_cunning_index_table[9] = { + -1, -1, -1, -1, 1, 2, 3, 4, -1 +}; + +/* + * Dumped from the binaries: + * - FantasticJourney.exe - 0x79458, DGROUP:0x47A458 + * - BigRaceUSA.exe - 0x9B830, DGROUP:0x49C430 + * - Timeshock!.exe - 0x84FF0, DGROUP:0x485BF0 + */ +const int16_t ff_adpcm_ima_cunning_step_table[61] = { + 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, + 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, + 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, + 192, 224, 256, 320, 384, 448, 512, 640, 768, 896, + 1024, 1280, 1536, 1792, 2048, 2560, 3072, 3584, 4096, 5120, + 6144, 7168, 8192, 10240, 12288, 14336, 16384, 20480, 24576, 28672, 0 +}; diff -Nru ffmpeg-4.2.2/libavcodec/adpcm_data.h ffmpeg-4.4/libavcodec/adpcm_data.h --- ffmpeg-4.2.2/libavcodec/adpcm_data.h 2018-11-01 18:34:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/adpcm_data.h 2020-07-11 10:39:30.000000000 +0000 @@ -42,5 +42,7 @@ extern const int8_t ff_adpcm_yamaha_difflookup[]; extern const int16_t ff_adpcm_afc_coeffs[2][16]; extern const int16_t ff_adpcm_mtaf_stepsize[32][16]; +extern const int8_t ff_adpcm_ima_cunning_index_table[9]; +extern const int16_t ff_adpcm_ima_cunning_step_table[61]; #endif /* AVCODEC_ADPCM_DATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/adpcmenc.c ffmpeg-4.4/libavcodec/adpcmenc.c --- ffmpeg-4.2.2/libavcodec/adpcmenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/adpcmenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/opt.h" + #include "avcodec.h" #include "put_bits.h" #include "bytestream.h" @@ -49,6 +51,9 @@ } TrellisNode; typedef struct ADPCMEncodeContext { + AVClass *class; + int block_size; + ADPCMChannelStatus status[6]; TrellisPath *paths; TrellisNode *node_buf; @@ -58,36 +63,53 @@ #define FREEZE_INTERVAL 128 -static av_cold int adpcm_encode_close(AVCodecContext *avctx); - static av_cold int adpcm_encode_init(AVCodecContext *avctx) { ADPCMEncodeContext *s = avctx->priv_data; uint8_t *extradata; int i; - int ret = AVERROR(ENOMEM); if (avctx->channels > 2) { av_log(avctx, AV_LOG_ERROR, "only stereo or mono is supported\n"); return AVERROR(EINVAL); } - if (avctx->trellis && (unsigned)avctx->trellis > 16U) { - av_log(avctx, AV_LOG_ERROR, "invalid trellis size\n"); + /* + * AMV's block size has to match that of the corresponding video + * stream. Relax the POT requirement. + */ + if (avctx->codec->id != AV_CODEC_ID_ADPCM_IMA_AMV && + (s->block_size & (s->block_size - 1))) { + av_log(avctx, AV_LOG_ERROR, "block size must be power of 2\n"); return AVERROR(EINVAL); } if (avctx->trellis) { - int frontier = 1 << avctx->trellis; - int max_paths = frontier * FREEZE_INTERVAL; - FF_ALLOC_OR_GOTO(avctx, s->paths, - max_paths * sizeof(*s->paths), error); - FF_ALLOC_OR_GOTO(avctx, s->node_buf, - 2 * frontier * sizeof(*s->node_buf), error); - FF_ALLOC_OR_GOTO(avctx, s->nodep_buf, - 2 * frontier * sizeof(*s->nodep_buf), error); - FF_ALLOC_OR_GOTO(avctx, s->trellis_hash, - 65536 * sizeof(*s->trellis_hash), error); + int frontier, max_paths; + + if ((unsigned)avctx->trellis > 16U) { + av_log(avctx, AV_LOG_ERROR, "invalid trellis size\n"); + return AVERROR(EINVAL); + } + + if (avctx->codec->id == AV_CODEC_ID_ADPCM_IMA_SSI || + avctx->codec->id == AV_CODEC_ID_ADPCM_IMA_APM || + avctx->codec->id == AV_CODEC_ID_ADPCM_ARGO) { + /* + * The current trellis implementation doesn't work for extended + * runs of samples without periodic resets. Disallow it. + */ + av_log(avctx, AV_LOG_ERROR, "trellis not supported\n"); + return AVERROR_PATCHWELCOME; + } + + frontier = 1 << avctx->trellis; + max_paths = frontier * FREEZE_INTERVAL; + if (!FF_ALLOC_TYPED_ARRAY(s->paths, max_paths) || + !FF_ALLOC_TYPED_ARRAY(s->node_buf, 2 * frontier) || + !FF_ALLOC_TYPED_ARRAY(s->nodep_buf, 2 * frontier) || + !FF_ALLOC_TYPED_ARRAY(s->trellis_hash, 65536)) + return AVERROR(ENOMEM); } avctx->bits_per_coded_sample = av_get_bits_per_sample(avctx->codec->id); @@ -96,11 +118,11 @@ case AV_CODEC_ID_ADPCM_IMA_WAV: /* each 16 bits sample gives one nibble and we have 4 bytes per channel overhead */ - avctx->frame_size = (BLKSIZE - 4 * avctx->channels) * 8 / + avctx->frame_size = (s->block_size - 4 * avctx->channels) * 8 / (4 * avctx->channels) + 1; /* seems frame_size isn't taken into account... have to buffer the samples :-( */ - avctx->block_align = BLKSIZE; + avctx->block_align = s->block_size; avctx->bits_per_coded_sample = 4; break; case AV_CODEC_ID_ADPCM_IMA_QT: @@ -110,11 +132,11 @@ case AV_CODEC_ID_ADPCM_MS: /* each 16 bits sample gives one nibble and we have 7 bytes per channel overhead */ - avctx->frame_size = (BLKSIZE - 7 * avctx->channels) * 2 / avctx->channels + 2; + avctx->frame_size = (s->block_size - 7 * avctx->channels) * 2 / avctx->channels + 2; avctx->bits_per_coded_sample = 4; - avctx->block_align = BLKSIZE; + avctx->block_align = s->block_size; if (!(avctx->extradata = av_malloc(32 + AV_INPUT_BUFFER_PADDING_SIZE))) - goto error; + return AVERROR(ENOMEM); avctx->extradata_size = 32; extradata = avctx->extradata; bytestream_put_le16(&extradata, avctx->frame_size); @@ -125,8 +147,8 @@ } break; case AV_CODEC_ID_ADPCM_YAMAHA: - avctx->frame_size = BLKSIZE * 2 / avctx->channels; - avctx->block_align = BLKSIZE; + avctx->frame_size = s->block_size * 2 / avctx->channels; + avctx->block_align = s->block_size; break; case AV_CODEC_ID_ADPCM_SWF: if (avctx->sample_rate != 11025 && @@ -134,20 +156,47 @@ avctx->sample_rate != 44100) { av_log(avctx, AV_LOG_ERROR, "Sample rate must be 11025, " "22050 or 44100\n"); - ret = AVERROR(EINVAL); - goto error; + return AVERROR(EINVAL); } - avctx->frame_size = 512 * (avctx->sample_rate / 11025); + avctx->frame_size = 4096; /* Hardcoded according to the SWF spec. */ + avctx->block_align = (2 + avctx->channels * (22 + 4 * (avctx->frame_size - 1)) + 7) / 8; + break; + case AV_CODEC_ID_ADPCM_IMA_SSI: + case AV_CODEC_ID_ADPCM_IMA_ALP: + avctx->frame_size = s->block_size * 2 / avctx->channels; + avctx->block_align = s->block_size; + break; + case AV_CODEC_ID_ADPCM_IMA_AMV: + if (avctx->sample_rate != 22050) { + av_log(avctx, AV_LOG_ERROR, "Sample rate must be 22050\n"); + return AVERROR(EINVAL); + } + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "Only mono is supported\n"); + return AVERROR(EINVAL); + } + + avctx->frame_size = s->block_size; + avctx->block_align = 8 + (FFALIGN(avctx->frame_size, 2) / 2); + break; + case AV_CODEC_ID_ADPCM_IMA_APM: + avctx->frame_size = s->block_size * 2 / avctx->channels; + avctx->block_align = s->block_size; + + if (!(avctx->extradata = av_mallocz(28 + AV_INPUT_BUFFER_PADDING_SIZE))) + return AVERROR(ENOMEM); + avctx->extradata_size = 28; + break; + case AV_CODEC_ID_ADPCM_ARGO: + avctx->frame_size = 32; + avctx->block_align = 17 * avctx->channels; break; default: - ret = AVERROR(EINVAL); - goto error; + return AVERROR(EINVAL); } return 0; -error: - adpcm_encode_close(avctx); - return ret; } static av_cold int adpcm_encode_close(AVCodecContext *avctx) @@ -175,6 +224,25 @@ return nibble; } +static inline uint8_t adpcm_ima_alp_compress_sample(ADPCMChannelStatus *c, int16_t sample) +{ + const int delta = sample - c->prev_sample; + const int step = ff_adpcm_step_table[c->step_index]; + const int sign = (delta < 0) * 8; + + int nibble = FFMIN(abs(delta) * 4 / step, 7); + int diff = (step * nibble) >> 2; + if (sign) + diff = -diff; + + nibble = sign | nibble; + + c->prev_sample += diff; + c->prev_sample = av_clip_int16(c->prev_sample); + c->step_index = av_clip(c->step_index + ff_adpcm_index_table[nibble], 0, 88); + return nibble; +} + static inline uint8_t adpcm_ima_qt_compress_sample(ADPCMChannelStatus *c, int16_t sample) { @@ -289,6 +357,7 @@ nodes[0]->sample2 = c->sample2; if (version == AV_CODEC_ID_ADPCM_IMA_WAV || version == AV_CODEC_ID_ADPCM_IMA_QT || + version == AV_CODEC_ID_ADPCM_IMA_AMV || version == AV_CODEC_ID_ADPCM_SWF) nodes[0]->sample1 = c->prev_sample; if (version == AV_CODEC_ID_ADPCM_MS) @@ -393,6 +462,7 @@ } } else if (version == AV_CODEC_ID_ADPCM_IMA_WAV || version == AV_CODEC_ID_ADPCM_IMA_QT || + version == AV_CODEC_ID_ADPCM_IMA_AMV || version == AV_CODEC_ID_ADPCM_SWF) { #define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)\ const int predictor = nodes[j]->sample1;\ @@ -468,6 +538,46 @@ c->idelta = nodes[0]->step; } +static inline int adpcm_argo_compress_nibble(const ADPCMChannelStatus *cs, int16_t s, + int shift, int flag) +{ + int nibble; + + if (flag) + nibble = 4 * s - 8 * cs->sample1 + 4 * cs->sample2; + else + nibble = 4 * s - 4 * cs->sample1; + + return (nibble >> shift) & 0x0F; +} + +static int64_t adpcm_argo_compress_block(ADPCMChannelStatus *cs, PutBitContext *pb, + const int16_t *samples, int nsamples, + int shift, int flag) +{ + int64_t error = 0; + + if (pb) { + put_bits(pb, 4, shift - 2); + put_bits(pb, 1, 0); + put_bits(pb, 1, !!flag); + put_bits(pb, 2, 0); + } + + for (int n = 0; n < nsamples; n++) { + /* Compress the nibble, then expand it to see how much precision we've lost. */ + int nibble = adpcm_argo_compress_nibble(cs, samples[n], shift, flag); + int16_t sample = ff_adpcm_argo_expand_nibble(cs, nibble, shift, flag); + + error += abs(samples[n] - sample); + + if (pb) + put_bits(pb, 4, nibble); + } + + return error; +} + static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { @@ -482,8 +592,10 @@ samples_p = (int16_t **)frame->extended_data; st = avctx->channels == 2; - if (avctx->codec_id == AV_CODEC_ID_ADPCM_SWF) - pkt_size = (2 + avctx->channels * (22 + 4 * (frame->nb_samples - 1)) + 7) / 8; + if (avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_SSI || + avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_ALP || + avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_APM) + pkt_size = (frame->nb_samples * avctx->channels) / 2; else pkt_size = avctx->block_align; if ((ret = ff_alloc_packet2(avctx, avpkt, pkt_size, 0)) < 0) @@ -509,7 +621,8 @@ /* stereo: 4 bytes (8 samples) for left, 4 bytes for right */ if (avctx->trellis > 0) { - FF_ALLOC_ARRAY_OR_GOTO(avctx, buf, avctx->channels, blocks * 8, error); + if (!FF_ALLOC_TYPED_ARRAY(buf, avctx->channels * blocks * 8)) + return AVERROR(ENOMEM); for (ch = 0; ch < avctx->channels; ch++) { adpcm_compress_trellis(avctx, &samples_p[ch][1], buf + ch * blocks * 8, &c->status[ch], @@ -568,6 +681,40 @@ flush_put_bits(&pb); break; } + case AV_CODEC_ID_ADPCM_IMA_SSI: + { + PutBitContext pb; + init_put_bits(&pb, dst, pkt_size); + + av_assert0(avctx->trellis == 0); + + for (i = 0; i < frame->nb_samples; i++) { + for (ch = 0; ch < avctx->channels; ch++) { + put_bits(&pb, 4, adpcm_ima_qt_compress_sample(c->status + ch, *samples++)); + } + } + + flush_put_bits(&pb); + break; + } + case AV_CODEC_ID_ADPCM_IMA_ALP: + { + PutBitContext pb; + init_put_bits(&pb, dst, pkt_size); + + av_assert0(avctx->trellis == 0); + + for (n = frame->nb_samples / 2; n > 0; n--) { + for (ch = 0; ch < avctx->channels; ch++) { + put_bits(&pb, 4, adpcm_ima_alp_compress_sample(c->status + ch, *samples++)); + put_bits(&pb, 4, adpcm_ima_alp_compress_sample(c->status + ch, samples[st])); + } + samples += avctx->channels; + } + + flush_put_bits(&pb); + break; + } case AV_CODEC_ID_ADPCM_SWF: { PutBitContext pb; @@ -588,7 +735,8 @@ } if (avctx->trellis > 0) { - FF_ALLOC_OR_GOTO(avctx, buf, 2 * n, error); + if (!(buf = av_malloc(2 * n))) + return AVERROR(ENOMEM); adpcm_compress_trellis(avctx, samples + avctx->channels, buf, &c->status[0], n, avctx->channels); if (avctx->channels == 2) @@ -636,7 +784,8 @@ if (avctx->trellis > 0) { n = avctx->block_align - 7 * avctx->channels; - FF_ALLOC_OR_GOTO(avctx, buf, 2 * n, error); + if (!(buf = av_malloc(2 * n))) + return AVERROR(ENOMEM); if (avctx->channels == 1) { adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n, avctx->channels); @@ -663,7 +812,8 @@ case AV_CODEC_ID_ADPCM_YAMAHA: n = frame->nb_samples / 2; if (avctx->trellis > 0) { - FF_ALLOC_OR_GOTO(avctx, buf, 2 * n * 2, error); + if (!(buf = av_malloc(2 * n * 2))) + return AVERROR(ENOMEM); n *= 2; if (avctx->channels == 1) { adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n, @@ -687,6 +837,97 @@ *dst++ = nibble; } break; + case AV_CODEC_ID_ADPCM_IMA_APM: + { + PutBitContext pb; + init_put_bits(&pb, dst, pkt_size); + + av_assert0(avctx->trellis == 0); + + for (n = frame->nb_samples / 2; n > 0; n--) { + for (ch = 0; ch < avctx->channels; ch++) { + put_bits(&pb, 4, adpcm_ima_qt_compress_sample(c->status + ch, *samples++)); + put_bits(&pb, 4, adpcm_ima_qt_compress_sample(c->status + ch, samples[st])); + } + samples += avctx->channels; + } + + flush_put_bits(&pb); + break; + } + case AV_CODEC_ID_ADPCM_IMA_AMV: + { + av_assert0(avctx->channels == 1); + + c->status[0].prev_sample = *samples; + bytestream_put_le16(&dst, c->status[0].prev_sample); + bytestream_put_byte(&dst, c->status[0].step_index); + bytestream_put_byte(&dst, 0); + bytestream_put_le32(&dst, avctx->frame_size); + + if (avctx->trellis > 0) { + n = frame->nb_samples >> 1; + + if (!(buf = av_malloc(2 * n))) + return AVERROR(ENOMEM); + + adpcm_compress_trellis(avctx, samples, buf, &c->status[0], 2 * n, avctx->channels); + for (i = 0; i < n; i++) + bytestream_put_byte(&dst, (buf[2 * i] << 4) | buf[2 * i + 1]); + + samples += 2 * n; + av_free(buf); + } else for (n = frame->nb_samples >> 1; n > 0; n--) { + int nibble; + nibble = adpcm_ima_compress_sample(&c->status[0], *samples++) << 4; + nibble |= adpcm_ima_compress_sample(&c->status[0], *samples++) & 0x0F; + bytestream_put_byte(&dst, nibble); + } + + if (avctx->frame_size & 1) { + int nibble = adpcm_ima_compress_sample(&c->status[0], *samples++) << 4; + bytestream_put_byte(&dst, nibble); + } + break; + } + case AV_CODEC_ID_ADPCM_ARGO: + { + PutBitContext pb; + init_put_bits(&pb, dst, pkt_size); + + av_assert0(frame->nb_samples == 32); + + for (ch = 0; ch < avctx->channels; ch++) { + int64_t error = INT64_MAX, tmperr = INT64_MAX; + int shift = 2, flag = 0; + int saved1 = c->status[ch].sample1; + int saved2 = c->status[ch].sample2; + + /* Find the optimal coefficients, bail early if we find a perfect result. */ + for (int s = 2; s < 18 && tmperr != 0; s++) { + for (int f = 0; f < 2 && tmperr != 0; f++) { + c->status[ch].sample1 = saved1; + c->status[ch].sample2 = saved2; + tmperr = adpcm_argo_compress_block(c->status + ch, NULL, samples_p[ch], + frame->nb_samples, s, f); + if (tmperr < error) { + shift = s; + flag = f; + error = tmperr; + } + } + } + + /* Now actually do the encode. */ + c->status[ch].sample1 = saved1; + c->status[ch].sample2 = saved2; + adpcm_argo_compress_block(c->status + ch, &pb, samples_p[ch], + frame->nb_samples, shift, flag); + } + + flush_put_bits(&pb); + break; + } default: return AVERROR(EINVAL); } @@ -694,8 +935,6 @@ avpkt->size = pkt_size; *got_packet_ptr = 1; return 0; -error: - return AVERROR(ENOMEM); } static const enum AVSampleFormat sample_fmts[] = { @@ -706,21 +945,50 @@ AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }; -#define ADPCM_ENCODER(id_, name_, sample_fmts_, long_name_) \ -AVCodec ff_ ## name_ ## _encoder = { \ - .name = #name_, \ - .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ - .type = AVMEDIA_TYPE_AUDIO, \ - .id = id_, \ - .priv_data_size = sizeof(ADPCMEncodeContext), \ - .init = adpcm_encode_init, \ - .encode2 = adpcm_encode_frame, \ - .close = adpcm_encode_close, \ - .sample_fmts = sample_fmts_, \ -} - -ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, sample_fmts_p, "ADPCM IMA QuickTime"); -ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav, sample_fmts_p, "ADPCM IMA WAV"); -ADPCM_ENCODER(AV_CODEC_ID_ADPCM_MS, adpcm_ms, sample_fmts, "ADPCM Microsoft"); -ADPCM_ENCODER(AV_CODEC_ID_ADPCM_SWF, adpcm_swf, sample_fmts, "ADPCM Shockwave Flash"); -ADPCM_ENCODER(AV_CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha, sample_fmts, "ADPCM Yamaha"); +static const AVOption options[] = { + { + .name = "block_size", + .help = "set the block size", + .offset = offsetof(ADPCMEncodeContext, block_size), + .type = AV_OPT_TYPE_INT, + .default_val = {.i64 = 1024}, + .min = 32, + .max = 8192, /* Is this a reasonable upper limit? */ + .flags = AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM + }, + { NULL } +}; + +#define ADPCM_ENCODER(id_, name_, sample_fmts_, capabilities_, long_name_) \ +static const AVClass name_ ## _encoder_class = { \ + .class_name = #name_, \ + .item_name = av_default_item_name, \ + .option = options, \ + .version = LIBAVUTIL_VERSION_INT, \ +}; \ + \ +AVCodec ff_ ## name_ ## _encoder = { \ + .name = #name_, \ + .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ + .type = AVMEDIA_TYPE_AUDIO, \ + .id = id_, \ + .priv_data_size = sizeof(ADPCMEncodeContext), \ + .init = adpcm_encode_init, \ + .encode2 = adpcm_encode_frame, \ + .close = adpcm_encode_close, \ + .sample_fmts = sample_fmts_, \ + .capabilities = capabilities_, \ + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, \ + .priv_class = &name_ ## _encoder_class, \ +} + +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_ARGO, adpcm_argo, sample_fmts_p, 0, "ADPCM Argonaut Games"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_AMV, adpcm_ima_amv, sample_fmts, 0, "ADPCM IMA AMV"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_APM, adpcm_ima_apm, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Ubisoft APM"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_ALP, adpcm_ima_alp, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA High Voltage Software ALP"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, sample_fmts_p, 0, "ADPCM IMA QuickTime"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_SSI, adpcm_ima_ssi, sample_fmts, AV_CODEC_CAP_SMALL_LAST_FRAME, "ADPCM IMA Simon & Schuster Interactive"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav, sample_fmts_p, 0, "ADPCM IMA WAV"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_MS, adpcm_ms, sample_fmts, 0, "ADPCM Microsoft"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_SWF, adpcm_swf, sample_fmts, 0, "ADPCM Shockwave Flash"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha, sample_fmts, 0, "ADPCM Yamaha"); diff -Nru ffmpeg-4.2.2/libavcodec/adpcm.h ffmpeg-4.4/libavcodec/adpcm.h --- ffmpeg-4.2.2/libavcodec/adpcm.h 2018-11-01 18:34:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/adpcm.h 2021-04-08 21:28:39.000000000 +0000 @@ -28,8 +28,6 @@ #include -#define BLKSIZE 1024 - typedef struct ADPCMChannelStatus { int predictor; int16_t step_index; @@ -45,4 +43,6 @@ int idelta; } ADPCMChannelStatus; +int16_t ff_adpcm_argo_expand_nibble(ADPCMChannelStatus *cs, int nibble, int shift, int flag); + #endif /* AVCODEC_ADPCM_H */ diff -Nru ffmpeg-4.2.2/libavcodec/adxdec.c ffmpeg-4.4/libavcodec/adxdec.c --- ffmpeg-4.2.2/libavcodec/adxdec.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/adxdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -81,7 +81,7 @@ s2 = prev->s2; for (i = 0; i < BLOCK_SAMPLES; i++) { d = get_sbits(&gb, 4); - s0 = ((d * (1 << COEFF_BITS)) * scale + c->coeff[0] * s1 + c->coeff[1] * s2) >> COEFF_BITS; + s0 = d * scale + ((c->coeff[0] * s1 + c->coeff[1] * s2) >> COEFF_BITS); s2 = s1; s1 = av_clip_int16(s0); *out++ = s1; @@ -103,6 +103,22 @@ const uint8_t *buf = avpkt->data; const uint8_t *buf_end = buf + avpkt->size; int num_blocks, ch, ret; + buffer_size_t new_extradata_size; + uint8_t *new_extradata; + + new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, + &new_extradata_size); + if (new_extradata && new_extradata_size > 0) { + int header_size; + if ((ret = ff_adx_decode_header(avctx, new_extradata, + new_extradata_size, &header_size, + c->coeff)) < 0) { + av_log(avctx, AV_LOG_ERROR, "error parsing new ADX extradata\n"); + return AVERROR_INVALIDDATA; + } + + c->eof = 0; + } if (c->eof) { *got_frame_ptr = 0; @@ -183,7 +199,8 @@ .init = adx_decode_init, .decode = adx_decode_frame, .flush = adx_decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, }; diff -Nru ffmpeg-4.2.2/libavcodec/adxenc.c ffmpeg-4.4/libavcodec/adxenc.c --- ffmpeg-4.2.2/libavcodec/adxenc.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/adxenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -48,7 +48,7 @@ s2 = prev->s2; for (i = 0, j = 0; j < 32; i += channels, j++) { s0 = wav[i]; - d = ((s0 << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS; + d = s0 + ((-c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS); if (max < d) max = d; if (min > d) @@ -79,13 +79,13 @@ s1 = prev->s1; s2 = prev->s2; for (i = 0, j = 0; j < 32; i += channels, j++) { - d = ((wav[i] << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS; + d = wav[i] + ((-c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS); d = av_clip_intp2(ROUNDED_DIV(d, scale), 3); put_sbits(&pb, 4, d); - s0 = ((d << COEFF_BITS) * scale + c->coeff[0] * s1 + c->coeff[1] * s2) >> COEFF_BITS; + s0 = d * scale + ((c->coeff[0] * s1 + c->coeff[1] * s2) >> COEFF_BITS); s2 = s1; s1 = s0; } @@ -141,10 +141,26 @@ const AVFrame *frame, int *got_packet_ptr) { ADXContext *c = avctx->priv_data; - const int16_t *samples = (const int16_t *)frame->data[0]; + const int16_t *samples = frame ? (const int16_t *)frame->data[0] : NULL; uint8_t *dst; int ch, out_size, ret; + if (!samples) { + if (c->eof) + return 0; + if ((ret = ff_alloc_packet2(avctx, avpkt, 18, 0)) < 0) + return ret; + c->eof = 1; + dst = avpkt->data; + bytestream_put_be16(&dst, 0x8001); + bytestream_put_be16(&dst, 0x000E); + bytestream_put_be64(&dst, 0x0); + bytestream_put_be32(&dst, 0x0); + bytestream_put_be16(&dst, 0x0); + *got_packet_ptr = 1; + return 0; + } + out_size = BLOCK_SIZE * avctx->channels + !c->header_parsed * HEADER_SIZE; if ((ret = ff_alloc_packet2(avctx, avpkt, out_size, 0)) < 0) return ret; @@ -165,6 +181,8 @@ dst += BLOCK_SIZE; } + avpkt->pts = frame->pts; + avpkt->duration = frame->nb_samples; *got_packet_ptr = 1; return 0; } @@ -177,6 +195,7 @@ .priv_data_size = sizeof(ADXContext), .init = adx_encode_init, .encode2 = adx_encode_frame, + .capabilities = AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, }; diff -Nru ffmpeg-4.2.2/libavcodec/agm.c ffmpeg-4.4/libavcodec/agm.c --- ffmpeg-4.2.2/libavcodec/agm.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/agm.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,8 @@ #define BITSTREAM_READER_LE +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "bytestream.h" #include "copy_block.h" @@ -423,8 +425,8 @@ int map = s->map[x]; if (orig_mv_x >= -32) { - if (y * 8 + mv_y < 0 || y * 8 + mv_y + 8 >= h || - x * 8 + mv_x < 0 || x * 8 + mv_x + 8 >= w) + if (y * 8 + mv_y < 0 || y * 8 + mv_y + 8 > h || + x * 8 + mv_x < 0 || x * 8 + mv_x + 8 > w) return AVERROR_INVALIDDATA; copy_block8(frame->data[plane] + (s->blocks_h - 1 - y) * 8 * frame->linesize[plane] + x * 8, @@ -573,13 +575,16 @@ uint8_t *dst = frame->data[0] + (avctx->height - 1) * frame->linesize[0]; uint8_t r = 0, g = 0, b = 0; + if (bytestream2_get_bytes_left(gbyte) < 3 * avctx->width * avctx->height) + return AVERROR_INVALIDDATA; + for (int y = 0; y < avctx->height; y++) { for (int x = 0; x < avctx->width; x++) { - dst[x*3+0] = bytestream2_get_byte(gbyte) + r; + dst[x*3+0] = bytestream2_get_byteu(gbyte) + r; r = dst[x*3+0]; - dst[x*3+1] = bytestream2_get_byte(gbyte) + g; + dst[x*3+1] = bytestream2_get_byteu(gbyte) + g; g = dst[x*3+1]; - dst[x*3+2] = bytestream2_get_byte(gbyte) + b; + dst[x*3+2] = bytestream2_get_byteu(gbyte) + b; b = dst[x*3+2]; } dst -= frame->linesize[0]; @@ -588,7 +593,7 @@ return 0; } -static int fill_pixels(uint8_t **y0, uint8_t **y1, +av_always_inline static int fill_pixels(uint8_t **y0, uint8_t **y1, uint8_t **u, uint8_t **v, int ylinesize, int ulinesize, int vlinesize, uint8_t *fill, @@ -1239,6 +1244,11 @@ s->dct = avctx->codec_tag != MKTAG('A', 'G', 'M', '4') && avctx->codec_tag != MKTAG('A', 'G', 'M', '5'); + if (!s->rgb && !s->dct) { + if ((avctx->width & 1) || (avctx->height & 1)) + return AVERROR_INVALIDDATA; + } + avctx->idct_algo = FF_IDCT_SIMPLE; ff_idctdsp_init(&s->idsp, avctx); ff_init_scantable(s->idsp.idct_permutation, &s->scantable, ff_zigzag_direct); diff -Nru ffmpeg-4.2.2/libavcodec/aic.c ffmpeg-4.4/libavcodec/aic.c --- ffmpeg-4.2.2/libavcodec/aic.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aic.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,8 @@ #include +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "bytestream.h" #include "internal.h" @@ -504,6 +506,5 @@ .close = aic_decode_close, .decode = aic_decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(aic_decode_init), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/alac.c ffmpeg-4.4/libavcodec/alac.c --- ffmpeg-4.2.2/libavcodec/alac.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/alac.c 2021-04-08 21:28:39.000000000 +0000 @@ -228,7 +228,7 @@ sign = sign_only(val) * error_sign; lpc_coefs[j] -= sign; val *= (unsigned)sign; - error_val -= (val >> lpc_quant) * (j + 1); + error_val -= (val >> lpc_quant) * (j + 1U); } } } @@ -302,6 +302,9 @@ decorr_shift = get_bits(&alac->gb, 8); decorr_left_weight = get_bits(&alac->gb, 8); + if (channels == 2 && decorr_left_weight && decorr_shift > 31) + return AVERROR_INVALIDDATA; + for (ch = 0; ch < channels; ch++) { prediction_type[ch] = get_bits(&alac->gb, 4); lpc_quant[ch] = get_bits(&alac->gb, 4); @@ -397,13 +400,13 @@ case 20: { for (ch = 0; ch < channels; ch++) { for (i = 0; i < alac->nb_samples; i++) - alac->output_samples_buffer[ch][i] *= 1 << 12; + alac->output_samples_buffer[ch][i] *= 1U << 12; }} break; case 24: { for (ch = 0; ch < channels; ch++) { for (i = 0; i < alac->nb_samples; i++) - alac->output_samples_buffer[ch][i] *= 1 << 8; + alac->output_samples_buffer[ch][i] *= 1U << 8; }} break; } @@ -489,6 +492,7 @@ { int ch; unsigned buf_size = alac->max_samples_per_frame * sizeof(int32_t); + unsigned extra_buf_size = buf_size + AV_INPUT_BUFFER_PADDING_SIZE; for (ch = 0; ch < 2; ch++) { alac->predict_error_buffer[ch] = NULL; @@ -497,22 +501,19 @@ } for (ch = 0; ch < FFMIN(alac->channels, 2); ch++) { - FF_ALLOC_OR_GOTO(alac->avctx, alac->predict_error_buffer[ch], - buf_size, buf_alloc_fail); + if (!(alac->predict_error_buffer[ch] = av_malloc(buf_size))) + return AVERROR(ENOMEM); alac->direct_output = alac->sample_size > 16; if (!alac->direct_output) { - FF_ALLOC_OR_GOTO(alac->avctx, alac->output_samples_buffer[ch], - buf_size + AV_INPUT_BUFFER_PADDING_SIZE, buf_alloc_fail); + if (!(alac->output_samples_buffer[ch] = av_malloc(extra_buf_size))) + return AVERROR(ENOMEM); } - FF_ALLOC_OR_GOTO(alac->avctx, alac->extra_bits_buffer[ch], - buf_size + AV_INPUT_BUFFER_PADDING_SIZE, buf_alloc_fail); + if (!(alac->extra_bits_buffer[ch] = av_malloc(extra_buf_size))) + return AVERROR(ENOMEM); } return 0; -buf_alloc_fail: - alac_decode_close(alac->avctx); - return AVERROR(ENOMEM); } static int alac_set_info(ALACContext *alac) @@ -601,15 +602,6 @@ return 0; } -#if HAVE_THREADS -static int init_thread_copy(AVCodecContext *avctx) -{ - ALACContext *alac = avctx->priv_data; - alac->avctx = avctx; - return allocate_buffers(alac); -} -#endif - static const AVOption options[] = { { "extra_bits_bug", "Force non-standard decoding process", offsetof(ALACContext, extra_bit_bug), AV_OPT_TYPE_BOOL, { .i64 = 0 }, @@ -633,7 +625,7 @@ .init = alac_decode_init, .close = alac_decode_close, .decode = alac_decode_frame, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(init_thread_copy), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .priv_class = &alac_class }; diff -Nru ffmpeg-4.2.2/libavcodec/alacdsp.c ffmpeg-4.4/libavcodec/alacdsp.c --- ffmpeg-4.2.2/libavcodec/alacdsp.c 2018-07-17 09:27:39.000000000 +0000 +++ ffmpeg-4.4/libavcodec/alacdsp.c 2020-07-09 09:17:46.000000000 +0000 @@ -49,7 +49,7 @@ for (ch = 0; ch < channels; ch++) for (i = 0; i < nb_samples; i++) - buffer[ch][i] = (buffer[ch][i] << extra_bits) | extra_bits_buffer[ch][i]; + buffer[ch][i] = ((unsigned)buffer[ch][i] << extra_bits) | extra_bits_buffer[ch][i]; } av_cold void ff_alacdsp_init(ALACDSPContext *c) diff -Nru ffmpeg-4.2.2/libavcodec/alacenc.c ffmpeg-4.4/libavcodec/alacenc.c --- ffmpeg-4.2.2/libavcodec/alacenc.c 2018-11-01 18:34:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/alacenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -498,8 +498,6 @@ { AlacEncodeContext *s = avctx->priv_data; ff_lpc_end(&s->lpc_ctx); - av_freep(&avctx->extradata); - avctx->extradata_size = 0; return 0; } @@ -537,10 +535,8 @@ avctx->bits_per_raw_sample); avctx->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); - if (!avctx->extradata) { - ret = AVERROR(ENOMEM); - goto error; - } + if (!avctx->extradata) + return AVERROR(ENOMEM); avctx->extradata_size = ALAC_EXTRADATA_SIZE; alac_extradata = avctx->extradata; @@ -568,8 +564,7 @@ avctx->min_prediction_order > ALAC_MAX_LPC_ORDER) { av_log(avctx, AV_LOG_ERROR, "invalid min prediction order: %d\n", avctx->min_prediction_order); - ret = AVERROR(EINVAL); - goto error; + return AVERROR(EINVAL); } s->min_prediction_order = avctx->min_prediction_order; @@ -580,8 +575,7 @@ avctx->max_prediction_order > ALAC_MAX_LPC_ORDER) { av_log(avctx, AV_LOG_ERROR, "invalid max prediction order: %d\n", avctx->max_prediction_order); - ret = AVERROR(EINVAL); - goto error; + return AVERROR(EINVAL); } s->max_prediction_order = avctx->max_prediction_order; @@ -593,8 +587,7 @@ av_log(avctx, AV_LOG_ERROR, "invalid prediction orders: min=%d max=%d\n", s->min_prediction_order, s->max_prediction_order); - ret = AVERROR(EINVAL); - goto error; + return AVERROR(EINVAL); } s->avctx = avctx; @@ -602,13 +595,10 @@ if ((ret = ff_lpc_init(&s->lpc_ctx, avctx->frame_size, s->max_prediction_order, FF_LPC_TYPE_LEVINSON)) < 0) { - goto error; + return ret; } return 0; -error: - alac_encode_close(avctx); - return ret; } static int alac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, diff -Nru ffmpeg-4.2.2/libavcodec/allcodecs.c ffmpeg-4.4/libavcodec/allcodecs.c --- ffmpeg-4.2.2/libavcodec/allcodecs.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/allcodecs.c 2021-04-08 21:28:39.000000000 +0000 @@ -43,6 +43,7 @@ extern AVCodec ff_apng_encoder; extern AVCodec ff_apng_decoder; extern AVCodec ff_arbc_decoder; +extern AVCodec ff_argo_decoder; extern AVCodec ff_asv1_encoder; extern AVCodec ff_asv1_decoder; extern AVCodec ff_asv2_encoder; @@ -68,7 +69,9 @@ extern AVCodec ff_c93_decoder; extern AVCodec ff_cavs_decoder; extern AVCodec ff_cdgraphics_decoder; +extern AVCodec ff_cdtoons_decoder; extern AVCodec ff_cdxl_decoder; +extern AVCodec ff_cfhd_encoder; extern AVCodec ff_cfhd_decoder; extern AVCodec ff_cinepak_encoder; extern AVCodec ff_cinepak_decoder; @@ -79,6 +82,7 @@ extern AVCodec ff_comfortnoise_encoder; extern AVCodec ff_comfortnoise_decoder; extern AVCodec ff_cpia_decoder; +extern AVCodec ff_cri_decoder; extern AVCodec ff_cscd_decoder; extern AVCodec ff_cyuv_decoder; extern AVCodec ff_dds_decoder; @@ -105,6 +109,7 @@ extern AVCodec ff_eightsvx_fib_decoder; extern AVCodec ff_escape124_decoder; extern AVCodec ff_escape130_decoder; +extern AVCodec ff_exr_encoder; extern AVCodec ff_exr_decoder; extern AVCodec ff_ffv1_encoder; extern AVCodec ff_ffv1_decoder; @@ -158,11 +163,13 @@ extern AVCodec ff_idcin_decoder; extern AVCodec ff_iff_ilbm_decoder; extern AVCodec ff_imm4_decoder; +extern AVCodec ff_imm5_decoder; extern AVCodec ff_indeo2_decoder; extern AVCodec ff_indeo3_decoder; extern AVCodec ff_indeo4_decoder; extern AVCodec ff_indeo5_decoder; extern AVCodec ff_interplay_video_decoder; +extern AVCodec ff_ipu_decoder; extern AVCodec ff_jpeg2000_encoder; extern AVCodec ff_jpeg2000_decoder; extern AVCodec ff_jpegls_encoder; @@ -183,6 +190,7 @@ extern AVCodec ff_mjpeg_decoder; extern AVCodec ff_mjpegb_decoder; extern AVCodec ff_mmvideo_decoder; +extern AVCodec ff_mobiclip_decoder; extern AVCodec ff_motionpixels_decoder; extern AVCodec ff_mpeg1video_encoder; extern AVCodec ff_mpeg1video_decoder; @@ -208,6 +216,7 @@ extern AVCodec ff_msmpeg4v3_encoder; extern AVCodec ff_msmpeg4v3_decoder; extern AVCodec ff_msmpeg4_crystalhd_decoder; +extern AVCodec ff_msp2_decoder; extern AVCodec ff_msrle_decoder; extern AVCodec ff_mss1_decoder; extern AVCodec ff_mss2_decoder; @@ -215,10 +224,14 @@ extern AVCodec ff_msvideo1_decoder; extern AVCodec ff_mszh_decoder; extern AVCodec ff_mts2_decoder; +extern AVCodec ff_mv30_decoder; extern AVCodec ff_mvc1_decoder; extern AVCodec ff_mvc2_decoder; +extern AVCodec ff_mvdv_decoder; +extern AVCodec ff_mvha_decoder; extern AVCodec ff_mwsc_decoder; extern AVCodec ff_mxpeg_decoder; +extern AVCodec ff_notchlc_decoder; extern AVCodec ff_nuv_decoder; extern AVCodec ff_paf_video_decoder; extern AVCodec ff_pam_encoder; @@ -227,10 +240,14 @@ extern AVCodec ff_pbm_decoder; extern AVCodec ff_pcx_encoder; extern AVCodec ff_pcx_decoder; +extern AVCodec ff_pfm_encoder; +extern AVCodec ff_pfm_decoder; extern AVCodec ff_pgm_encoder; extern AVCodec ff_pgm_decoder; extern AVCodec ff_pgmyuv_encoder; extern AVCodec ff_pgmyuv_decoder; +extern AVCodec ff_pgx_decoder; +extern AVCodec ff_photocd_decoder; extern AVCodec ff_pictor_decoder; extern AVCodec ff_pixlet_decoder; extern AVCodec ff_png_encoder; @@ -258,6 +275,7 @@ extern AVCodec ff_rl2_decoder; extern AVCodec ff_roq_encoder; extern AVCodec ff_roq_decoder; +extern AVCodec ff_rpza_encoder; extern AVCodec ff_rpza_decoder; extern AVCodec ff_rscc_decoder; extern AVCodec ff_rv10_encoder; @@ -271,11 +289,12 @@ extern AVCodec ff_sanm_decoder; extern AVCodec ff_scpr_decoder; extern AVCodec ff_screenpresso_decoder; -extern AVCodec ff_sdx2_dpcm_decoder; +extern AVCodec ff_sga_decoder; extern AVCodec ff_sgi_encoder; extern AVCodec ff_sgi_decoder; extern AVCodec ff_sgirle_decoder; extern AVCodec ff_sheervideo_decoder; +extern AVCodec ff_simbiosis_imx_decoder; extern AVCodec ff_smacker_decoder; extern AVCodec ff_smc_decoder; extern AVCodec ff_smvjpeg_decoder; @@ -283,6 +302,7 @@ extern AVCodec ff_snow_decoder; extern AVCodec ff_sp5x_decoder; extern AVCodec ff_speedhq_decoder; +extern AVCodec ff_speedhq_encoder; extern AVCodec ff_srgc_decoder; extern AVCodec ff_sunrast_encoder; extern AVCodec ff_sunrast_decoder; @@ -387,6 +407,7 @@ extern AVCodec ff_ac3_decoder; extern AVCodec ff_ac3_fixed_encoder; extern AVCodec ff_ac3_fixed_decoder; +extern AVCodec ff_acelp_kelvin_decoder; extern AVCodec ff_alac_encoder; extern AVCodec ff_alac_decoder; extern AVCodec ff_als_decoder; @@ -420,6 +441,7 @@ extern AVCodec ff_eac3_encoder; extern AVCodec ff_eac3_decoder; extern AVCodec ff_evrc_decoder; +extern AVCodec ff_fastaudio_decoder; extern AVCodec ff_ffwavesynth_decoder; extern AVCodec ff_flac_encoder; extern AVCodec ff_flac_decoder; @@ -428,6 +450,7 @@ extern AVCodec ff_g729_decoder; extern AVCodec ff_gsm_decoder; extern AVCodec ff_gsm_ms_decoder; +extern AVCodec ff_hca_decoder; extern AVCodec ff_hcom_decoder; extern AVCodec ff_iac_decoder; extern AVCodec ff_ilbc_decoder; @@ -469,6 +492,7 @@ extern AVCodec ff_sbc_decoder; extern AVCodec ff_shorten_decoder; extern AVCodec ff_sipr_decoder; +extern AVCodec ff_siren_decoder; extern AVCodec ff_smackaud_decoder; extern AVCodec ff_sonic_encoder; extern AVCodec ff_sonic_decoder; @@ -545,6 +569,7 @@ extern AVCodec ff_pcm_s64be_decoder; extern AVCodec ff_pcm_s64le_encoder; extern AVCodec ff_pcm_s64le_decoder; +extern AVCodec ff_pcm_sga_decoder; extern AVCodec ff_pcm_u8_encoder; extern AVCodec ff_pcm_u8_decoder; extern AVCodec ff_pcm_u16be_encoder; @@ -561,13 +586,14 @@ extern AVCodec ff_pcm_u32le_decoder; extern AVCodec ff_pcm_vidc_encoder; extern AVCodec ff_pcm_vidc_decoder; -extern AVCodec ff_pcm_zork_decoder; /* DPCM codecs */ +extern AVCodec ff_derf_dpcm_decoder; extern AVCodec ff_gremlin_dpcm_decoder; extern AVCodec ff_interplay_dpcm_decoder; extern AVCodec ff_roq_dpcm_encoder; extern AVCodec ff_roq_dpcm_decoder; +extern AVCodec ff_sdx2_dpcm_decoder; extern AVCodec ff_sol_dpcm_decoder; extern AVCodec ff_xan_dpcm_decoder; @@ -578,6 +604,8 @@ extern AVCodec ff_adpcm_afc_decoder; extern AVCodec ff_adpcm_agm_decoder; extern AVCodec ff_adpcm_aica_decoder; +extern AVCodec ff_adpcm_argo_decoder; +extern AVCodec ff_adpcm_argo_encoder; extern AVCodec ff_adpcm_ct_decoder; extern AVCodec ff_adpcm_dtk_decoder; extern AVCodec ff_adpcm_ea_decoder; @@ -593,17 +621,27 @@ extern AVCodec ff_adpcm_g726le_encoder; extern AVCodec ff_adpcm_g726le_decoder; extern AVCodec ff_adpcm_ima_amv_decoder; +extern AVCodec ff_adpcm_ima_amv_encoder; +extern AVCodec ff_adpcm_ima_alp_decoder; +extern AVCodec ff_adpcm_ima_alp_encoder; extern AVCodec ff_adpcm_ima_apc_decoder; +extern AVCodec ff_adpcm_ima_apm_decoder; +extern AVCodec ff_adpcm_ima_apm_encoder; +extern AVCodec ff_adpcm_ima_cunning_decoder; extern AVCodec ff_adpcm_ima_dat4_decoder; extern AVCodec ff_adpcm_ima_dk3_decoder; extern AVCodec ff_adpcm_ima_dk4_decoder; extern AVCodec ff_adpcm_ima_ea_eacs_decoder; extern AVCodec ff_adpcm_ima_ea_sead_decoder; extern AVCodec ff_adpcm_ima_iss_decoder; +extern AVCodec ff_adpcm_ima_moflex_decoder; +extern AVCodec ff_adpcm_ima_mtf_decoder; extern AVCodec ff_adpcm_ima_oki_decoder; extern AVCodec ff_adpcm_ima_qt_encoder; extern AVCodec ff_adpcm_ima_qt_decoder; extern AVCodec ff_adpcm_ima_rad_decoder; +extern AVCodec ff_adpcm_ima_ssi_decoder; +extern AVCodec ff_adpcm_ima_ssi_encoder; extern AVCodec ff_adpcm_ima_smjpeg_decoder; extern AVCodec ff_adpcm_ima_wav_encoder; extern AVCodec ff_adpcm_ima_wav_decoder; @@ -623,6 +661,7 @@ extern AVCodec ff_adpcm_xa_decoder; extern AVCodec ff_adpcm_yamaha_encoder; extern AVCodec ff_adpcm_yamaha_decoder; +extern AVCodec ff_adpcm_zork_decoder; /* subtitles */ extern AVCodec ff_ssa_encoder; @@ -652,6 +691,7 @@ extern AVCodec ff_subviewer1_decoder; extern AVCodec ff_text_encoder; extern AVCodec ff_text_decoder; +extern AVCodec ff_ttml_encoder; extern AVCodec ff_vplayer_decoder; extern AVCodec ff_webvtt_encoder; extern AVCodec ff_webvtt_decoder; @@ -679,7 +719,6 @@ extern AVCodec ff_pcm_mulaw_at_decoder; extern AVCodec ff_qdmc_at_decoder; extern AVCodec ff_qdm2_at_decoder; -extern AVCodec ff_libaom_av1_decoder; extern AVCodec ff_libaom_av1_encoder; extern AVCodec ff_libaribb24_decoder; extern AVCodec ff_libcelt_decoder; @@ -703,12 +742,15 @@ extern AVCodec ff_libopenjpeg_decoder; extern AVCodec ff_libopus_encoder; extern AVCodec ff_libopus_decoder; +extern AVCodec ff_librav1e_encoder; extern AVCodec ff_librsvg_decoder; extern AVCodec ff_libshine_encoder; extern AVCodec ff_libspeex_encoder; extern AVCodec ff_libspeex_decoder; +extern AVCodec ff_libsvtav1_encoder; extern AVCodec ff_libtheora_encoder; extern AVCodec ff_libtwolame_encoder; +extern AVCodec ff_libuavs3d_decoder; extern AVCodec ff_libvo_amrwbenc_encoder; extern AVCodec ff_libvorbis_encoder; extern AVCodec ff_libvorbis_decoder; @@ -716,7 +758,6 @@ extern AVCodec ff_libvpx_vp8_decoder; extern AVCodec ff_libvpx_vp9_encoder; extern AVCodec ff_libvpx_vp9_decoder; -extern AVCodec ff_libwavpack_encoder; /* preferred over libwebp */ extern AVCodec ff_libwebp_anim_encoder; extern AVCodec ff_libwebp_encoder; @@ -736,11 +777,19 @@ /* external libraries, that shouldn't be used by default if one of the * above is available */ +extern AVCodec ff_aac_mf_encoder; +extern AVCodec ff_ac3_mf_encoder; extern AVCodec ff_h263_v4l2m2m_encoder; +extern AVCodec ff_libaom_av1_decoder; +/* hwaccel hooks only, so prefer external decoders */ +extern AVCodec ff_av1_decoder; +extern AVCodec ff_av1_cuvid_decoder; +extern AVCodec ff_av1_qsv_decoder; extern AVCodec ff_libopenh264_encoder; extern AVCodec ff_libopenh264_decoder; extern AVCodec ff_h264_amf_encoder; extern AVCodec ff_h264_cuvid_decoder; +extern AVCodec ff_h264_mf_encoder; extern AVCodec ff_h264_nvenc_encoder; extern AVCodec ff_h264_omx_encoder; extern AVCodec ff_h264_qsv_encoder; @@ -755,6 +804,7 @@ extern AVCodec ff_hevc_amf_encoder; extern AVCodec ff_hevc_cuvid_decoder; extern AVCodec ff_hevc_mediacodec_decoder; +extern AVCodec ff_hevc_mf_encoder; extern AVCodec ff_hevc_nvenc_encoder; extern AVCodec ff_hevc_qsv_encoder; extern AVCodec ff_hevc_v4l2m2m_encoder; @@ -763,13 +813,16 @@ extern AVCodec ff_libkvazaar_encoder; extern AVCodec ff_mjpeg_cuvid_decoder; extern AVCodec ff_mjpeg_qsv_encoder; +extern AVCodec ff_mjpeg_qsv_decoder; extern AVCodec ff_mjpeg_vaapi_encoder; +extern AVCodec ff_mp3_mf_encoder; extern AVCodec ff_mpeg1_cuvid_decoder; extern AVCodec ff_mpeg2_cuvid_decoder; extern AVCodec ff_mpeg2_qsv_encoder; extern AVCodec ff_mpeg2_vaapi_encoder; extern AVCodec ff_mpeg4_cuvid_decoder; extern AVCodec ff_mpeg4_mediacodec_decoder; +extern AVCodec ff_mpeg4_omx_encoder; extern AVCodec ff_mpeg4_v4l2m2m_encoder; extern AVCodec ff_vc1_cuvid_decoder; extern AVCodec ff_vp8_cuvid_decoder; @@ -779,12 +832,15 @@ extern AVCodec ff_vp8_vaapi_encoder; extern AVCodec ff_vp9_cuvid_decoder; extern AVCodec ff_vp9_mediacodec_decoder; +extern AVCodec ff_vp9_qsv_decoder; extern AVCodec ff_vp9_vaapi_encoder; +extern AVCodec ff_vp9_qsv_encoder; // The iterate API is not usable with ossfuzz due to the excessive size of binaries created #if CONFIG_OSSFUZZ AVCodec * codec_list[] = { NULL, + NULL, NULL }; #else diff -Nru ffmpeg-4.2.2/libavcodec/alsdec.c ffmpeg-4.4/libavcodec/alsdec.c --- ffmpeg-4.2.2/libavcodec/alsdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/alsdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -236,6 +236,7 @@ int **raw_mantissa; ///< decoded mantissa bits of the difference signal unsigned char *larray; ///< buffer to store the output of masked lz decompression int *nbits; ///< contains the number of bits to read for masked lz decompression for all samples + int highest_decoded_channel; } ALSDecContext; @@ -302,8 +303,8 @@ if ((ret = init_get_bits8(&gb, avctx->extradata, avctx->extradata_size)) < 0) return ret; - config_offset = avpriv_mpeg4audio_get_config(&m4ac, avctx->extradata, - avctx->extradata_size * 8, 1); + config_offset = avpriv_mpeg4audio_get_config2(&m4ac, avctx->extradata, + avctx->extradata_size, 1, avctx); if (config_offset < 0) return AVERROR_INVALIDDATA; @@ -349,7 +350,7 @@ return AVERROR_INVALIDDATA; if (avctx->channels > FF_SANE_NB_CHANNELS) { - avpriv_request_sample(avctx, "Huge number of channels\n"); + avpriv_request_sample(avctx, "Huge number of channels"); return AVERROR_PATCHWELCOME; } @@ -761,7 +762,7 @@ } for (k = 2; k < opt_order; k++) - quant_cof[k] = (quant_cof[k] * (1 << 14)) + (add_base << 13); + quant_cof[k] = (quant_cof[k] * (1U << 14)) + (add_base << 13); } } @@ -1015,6 +1016,10 @@ ALSSpecificConfig *sconf = &ctx->sconf; *bd->shift_lsbs = 0; + + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; + // read block type flag and read the samples accordingly if (get_bits1(gb)) { ret = read_var_block_data(ctx, bd); @@ -1678,6 +1683,7 @@ memmove(ctx->raw_samples[c] - sconf->max_order, ctx->raw_samples[c] - sconf->max_order + sconf->frame_length, sizeof(*ctx->raw_samples[c]) * sconf->max_order); + ctx->highest_decoded_channel = c; } } else { // multi-channel coding ALSBlockData bd = { 0 }; @@ -1746,6 +1752,8 @@ if ((ret = decode_block(ctx, &bd)) < 0) return ret; + + ctx->highest_decoded_channel = FFMAX(ctx->highest_decoded_channel, c); } memset(reverted_channels, 0, avctx->channels * sizeof(*reverted_channels)); @@ -1802,11 +1810,15 @@ else ctx->cur_frame_length = sconf->frame_length; + ctx->highest_decoded_channel = 0; // decode the frame data if ((invalid_frame = read_frame_data(ctx, ra_frame)) < 0) av_log(ctx->avctx, AV_LOG_WARNING, "Reading frame data failed. Skipping RA unit.\n"); + if (ctx->highest_decoded_channel == 0) + return AVERROR_INVALIDDATA; + ctx->frame_id++; /* get output buffer */ @@ -1819,16 +1831,17 @@ { \ int##bps##_t *dest = (int##bps##_t*)frame->data[0]; \ int channels = avctx->channels; \ - int32_t **raw_samples = ctx->raw_samples; \ + int32_t *raw_samples = ctx->raw_samples[0]; \ + int raw_step = channels > 1 ? ctx->raw_samples[1] - raw_samples : 1; \ shift = bps - ctx->avctx->bits_per_raw_sample; \ if (!ctx->cs_switch) { \ for (sample = 0; sample < ctx->cur_frame_length; sample++) \ for (c = 0; c < channels; c++) \ - *dest++ = raw_samples[c][sample] * (1U << shift); \ + *dest++ = raw_samples[c*raw_step + sample] * (1U << shift); \ } else { \ for (sample = 0; sample < ctx->cur_frame_length; sample++) \ for (c = 0; c < channels; c++) \ - *dest++ = raw_samples[sconf->chan_pos[c]][sample] * (1U << shift);\ + *dest++ = raw_samples[sconf->chan_pos[c]*raw_step + sample] * (1U << shift);\ } \ } @@ -2170,6 +2183,6 @@ .close = decode_end, .decode = decode_frame, .flush = flush, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/amfenc.c ffmpeg-4.4/libavcodec/amfenc.c --- ffmpeg-4.2.2/libavcodec/amfenc.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/amfenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,6 +33,7 @@ #include "libavutil/time.h" #include "amfenc.h" +#include "encode.h" #include "internal.h" #if CONFIG_D3D11VA @@ -213,6 +214,7 @@ static int amf_init_context(AVCodecContext *avctx) { AmfContext *ctx = avctx->priv_data; + AMFContext1 *context1 = NULL; AMF_RESULT res; av_unused int ret; @@ -311,8 +313,20 @@ if (res == AMF_OK) { av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D9.\n"); } else { - av_log(avctx, AV_LOG_ERROR, "AMF initialisation failed via D3D9: error %d.\n", res); - return AVERROR(ENOSYS); + AMFGuid guid = IID_AMFContext1(); + res = ctx->context->pVtbl->QueryInterface(ctx->context, &guid, (void**)&context1); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res); + + res = context1->pVtbl->InitVulkan(context1, NULL); + context1->pVtbl->Release(context1); + if (res != AMF_OK) { + if (res == AMF_NOT_SUPPORTED) + av_log(avctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n"); + else + av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on the given Vulkan device: %d.\n", res); + return AVERROR(ENOSYS); + } + av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via Vulkan.\n"); } } } @@ -438,7 +452,7 @@ int64_t timestamp = AV_NOPTS_VALUE; int64_t size = buffer->pVtbl->GetSize(buffer); - if ((ret = av_new_packet(pkt, size)) < 0) { + if ((ret = ff_get_encode_buffer(avctx, pkt, size, 0)) < 0) { return ret; } memcpy(pkt->data, buffer->pVtbl->GetNative(buffer), size); @@ -575,17 +589,27 @@ frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer); } -int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame) +int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) { AmfContext *ctx = avctx->priv_data; AMFSurface *surface; AMF_RESULT res; int ret; + AMF_RESULT res_query; + AMFData *data = NULL; + AVFrame *frame = ctx->delayed_frame; + int block_and_wait; if (!ctx->encoder) return AVERROR(EINVAL); - if (!frame) { // submit drain + if (!frame->buf[0]) { + ret = ff_encode_get_frame(avctx, frame); + if (ret < 0 && ret != AVERROR_EOF) + return ret; + } + + if (!frame->buf[0]) { // submit drain if (!ctx->eof) { // submit drain one time only if (ctx->delayed_surface != NULL) { ctx->delayed_drain = 1; // input queue is full: resubmit Drain() in ff_amf_receive_packet @@ -600,15 +624,10 @@ AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Drain() failed with error %d\n", res); } } - } else{ - return AVERROR_EOF; } - } else { // submit frame + } else if (!ctx->delayed_surface) { // submit frame int hw_surface = 0; - if (ctx->delayed_surface != NULL) { - return AVERROR(EAGAIN); // should not happen when called from ffmpeg, other clients may resubmit - } // prepare surface from frame switch (frame->format) { #if CONFIG_D3D11VA @@ -680,38 +699,23 @@ break; } - // submit surface res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)surface); if (res == AMF_INPUT_FULL) { // handle full queue //store surface for later submission ctx->delayed_surface = surface; - if (surface->pVtbl->GetMemoryType(surface) == AMF_MEMORY_DX11) { - av_frame_ref(ctx->delayed_frame, frame); - } } else { + int64_t pts = frame->pts; surface->pVtbl->Release(surface); AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res); - if ((ret = timestamp_queue_enqueue(avctx, frame->pts)) < 0) { + av_frame_unref(frame); + if ((ret = timestamp_queue_enqueue(avctx, pts)) < 0) { return ret; } - } } - return 0; -} -int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) -{ - int ret; - AMF_RESULT res; - AMF_RESULT res_query; - AmfContext *ctx = avctx->priv_data; - AMFData *data = NULL; - int block_and_wait; - if (!ctx->encoder) - return AVERROR(EINVAL); do { block_and_wait = 0; @@ -778,3 +782,15 @@ } return ret; } + +const AVCodecHWConfigInternal *const ff_amfenc_hw_configs[] = { +#if CONFIG_D3D11VA + HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11VA), + HW_CONFIG_ENCODER_DEVICE(NONE, D3D11VA), +#endif +#if CONFIG_DXVA2 + HW_CONFIG_ENCODER_FRAMES(DXVA2_VLD, DXVA2), + HW_CONFIG_ENCODER_DEVICE(NONE, DXVA2), +#endif + NULL, +}; diff -Nru ffmpeg-4.2.2/libavcodec/amfenc.h ffmpeg-4.4/libavcodec/amfenc.h --- ffmpeg-4.2.2/libavcodec/amfenc.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/amfenc.h 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ #include "libavutil/fifo.h" #include "avcodec.h" +#include "hwconfig.h" /** @@ -117,6 +118,8 @@ int tier; } AmfContext; +extern const AVCodecHWConfigInternal *const ff_amfenc_hw_configs[]; + /** * Common encoder initization function */ @@ -129,8 +132,6 @@ /** * Ecoding one frame - common function for all AMF encoders */ - -int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame); int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); /** diff -Nru ffmpeg-4.2.2/libavcodec/amfenc_h264.c ffmpeg-4.4/libavcodec/amfenc_h264.c --- ffmpeg-4.2.2/libavcodec/amfenc_h264.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/amfenc_h264.c 2021-04-08 21:28:39.000000000 +0000 @@ -366,6 +366,7 @@ { "b", "2M" }, { "g", "250" }, { "slices", "1" }, + { "flags", "+loop"}, { NULL }, }; @@ -382,14 +383,15 @@ .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, .init = amf_encode_init_h264, - .send_frame = ff_amf_send_frame, .receive_packet = ff_amf_receive_packet, .close = ff_amf_encode_close, .priv_data_size = sizeof(AmfContext), .priv_class = &h264_amf_class, .defaults = defaults, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = ff_amf_pix_fmts, .wrapper_name = "amf", + .hw_configs = ff_amfenc_hw_configs, }; diff -Nru ffmpeg-4.2.2/libavcodec/amfenc_hevc.c ffmpeg-4.4/libavcodec/amfenc_hevc.c --- ffmpeg-4.2.2/libavcodec/amfenc_hevc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/amfenc_hevc.c 2021-04-08 21:28:39.000000000 +0000 @@ -69,7 +69,7 @@ { "gop", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, "hdrmode" }, { "idr", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED }, 0, 0, VE, "hdrmode" }, - { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 60 }, 0, INT_MAX, VE }, + { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, VE }, { "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, { "vbaq", "Enable VBAQ", OFFSET(enable_vbaq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, @@ -136,7 +136,7 @@ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TIER, ctx->tier); profile_level = avctx->level; - if (profile_level == 0) { + if (profile_level == FF_LEVEL_UNKNOWN) { profile_level = ctx->level; } if (profile_level != 0) { @@ -144,7 +144,7 @@ } AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET, ctx->quality); // Maximum Reference Frames - if (avctx->refs != 0) { + if (avctx->refs != -1) { AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_NUM_REFRAMES, avctx->refs); } // Aspect Ratio @@ -254,10 +254,10 @@ } if (ctx->qp_p != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_I, ctx->qp_p); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_P, ctx->qp_p); } if (ctx->qp_i != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_P, ctx->qp_i); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_I, ctx->qp_i); } AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_SKIP_FRAME_ENABLE, ctx->skip_frame); @@ -298,6 +298,8 @@ { "b", "2M" }, { "g", "250" }, { "slices", "1" }, + { "qmin", "-1" }, + { "qmax", "-1" }, { NULL }, }; static const AVClass hevc_amf_class = { @@ -313,14 +315,15 @@ .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, .init = amf_encode_init_hevc, - .send_frame = ff_amf_send_frame, .receive_packet = ff_amf_receive_packet, .close = ff_amf_encode_close, .priv_data_size = sizeof(AmfContext), .priv_class = &hevc_amf_class, .defaults = defaults, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = ff_amf_pix_fmts, .wrapper_name = "amf", + .hw_configs = ff_amfenc_hw_configs, }; diff -Nru ffmpeg-4.2.2/libavcodec/amrnbdata.h ffmpeg-4.4/libavcodec/amrnbdata.h --- ffmpeg-4.2.2/libavcodec/amrnbdata.h 2016-03-29 02:25:10.000000000 +0000 +++ ffmpeg-4.4/libavcodec/amrnbdata.h 2021-04-08 21:28:39.000000000 +0000 @@ -1424,11 +1424,6 @@ // fixed tables -/** - * number of pulses per mode - */ -static const uint8_t pulses_nb_per_mode[] = {2, 2, 2, 3, 4, 4, 8, 10}; - /** track start positions for algebraic code book routines */ static const uint8_t track_position[16] = { 0, 2, 0, 3, 0, 2, 0, 3, 1, 3, 2, 4, 1, 4, 1, 4 diff -Nru ffmpeg-4.2.2/libavcodec/amrnbdec.c ffmpeg-4.4/libavcodec/amrnbdec.c --- ffmpeg-4.2.2/libavcodec/amrnbdec.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/amrnbdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -1088,7 +1088,7 @@ .priv_data_size = sizeof(AMRContext), .init = amrnb_decode_init, .decode = amrnb_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, }; diff -Nru ffmpeg-4.2.2/libavcodec/amrwbdata.h ffmpeg-4.4/libavcodec/amrwbdata.h --- ffmpeg-4.2.2/libavcodec/amrwbdata.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/amrwbdata.h 2020-07-11 10:39:30.000000000 +0000 @@ -1884,7 +1884,7 @@ /** Core frame sizes in each mode */ static const uint16_t cf_sizes_wb[] = { 132, 177, 253, 285, 317, 365, 397, 461, 477, - 40 /// SID/comfort noise frame + 40, 0, 0, 0, 0, 0, 0 }; #endif /* AVCODEC_AMRWBDATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/amrwbdec.c ffmpeg-4.4/libavcodec/amrwbdec.c --- ffmpeg-4.2.2/libavcodec/amrwbdec.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/amrwbdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -1119,12 +1119,23 @@ buf_out = (float *)frame->data[0]; header_size = decode_mime_header(ctx, buf); + expected_fr_size = ((cf_sizes_wb[ctx->fr_cur_mode] + 7) >> 3) + 1; + + if (!ctx->fr_quality) + av_log(avctx, AV_LOG_ERROR, "Encountered a bad or corrupted frame\n"); + + if (ctx->fr_cur_mode == NO_DATA || !ctx->fr_quality) { + /* The specification suggests a "random signal" and + "a muting technique" to "gradually decrease the output level". */ + av_samples_set_silence(&frame->data[0], 0, frame->nb_samples, 1, AV_SAMPLE_FMT_FLT); + *got_frame_ptr = 1; + return expected_fr_size; + } if (ctx->fr_cur_mode > MODE_SID) { av_log(avctx, AV_LOG_ERROR, "Invalid mode %d\n", ctx->fr_cur_mode); return AVERROR_INVALIDDATA; } - expected_fr_size = ((cf_sizes_wb[ctx->fr_cur_mode] + 7) >> 3) + 1; if (buf_size < expected_fr_size) { av_log(avctx, AV_LOG_ERROR, @@ -1133,9 +1144,6 @@ return AVERROR_INVALIDDATA; } - if (!ctx->fr_quality || ctx->fr_cur_mode > MODE_SID) - av_log(avctx, AV_LOG_ERROR, "Encountered a bad or corrupted frame\n"); - if (ctx->fr_cur_mode == MODE_SID) { /* Comfort noise frame */ avpriv_request_sample(avctx, "SID mode"); return AVERROR_PATCHWELCOME; @@ -1275,7 +1283,7 @@ .priv_data_size = sizeof(AMRWBContext), .init = amrwb_decode_init, .decode = amrwb_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, }; diff -Nru ffmpeg-4.2.2/libavcodec/anm.c ffmpeg-4.4/libavcodec/anm.c --- ffmpeg-4.2.2/libavcodec/anm.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/anm.c 2020-07-11 10:39:30.000000000 +0000 @@ -31,30 +31,27 @@ typedef struct AnmContext { AVFrame *frame; int palette[AVPALETTE_COUNT]; - GetByteContext gb; - int x; ///< x coordinate position } AnmContext; static av_cold int decode_init(AVCodecContext *avctx) { AnmContext *s = avctx->priv_data; + GetByteContext gb; int i; + if (avctx->extradata_size < 16 * 8 + 4 * 256) + return AVERROR_INVALIDDATA; + avctx->pix_fmt = AV_PIX_FMT_PAL8; s->frame = av_frame_alloc(); if (!s->frame) return AVERROR(ENOMEM); - bytestream2_init(&s->gb, avctx->extradata, avctx->extradata_size); - if (bytestream2_get_bytes_left(&s->gb) < 16 * 8 + 4 * 256) { - av_frame_free(&s->frame); - return AVERROR_INVALIDDATA; - } - - bytestream2_skipu(&s->gb, 16 * 8); + bytestream2_init(&gb, avctx->extradata, avctx->extradata_size); + bytestream2_skipu(&gb, 16 * 8); for (i = 0; i < 256; i++) - s->palette[i] = (0xFFU << 24) | bytestream2_get_le32u(&s->gb); + s->palette[i] = (0xFFU << 24) | bytestream2_get_le32u(&gb); return 0; } @@ -117,47 +114,47 @@ AnmContext *s = avctx->priv_data; const int buf_size = avpkt->size; uint8_t *dst, *dst_end; - int count, ret; + GetByteContext gb; + int count, ret, x = 0; if (buf_size < 7) return AVERROR_INVALIDDATA; - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; dst = s->frame->data[0]; dst_end = s->frame->data[0] + s->frame->linesize[0]*avctx->height; - bytestream2_init(&s->gb, avpkt->data, buf_size); + bytestream2_init(&gb, avpkt->data, buf_size); - if (bytestream2_get_byte(&s->gb) != 0x42) { + if (bytestream2_get_byte(&gb) != 0x42) { avpriv_request_sample(avctx, "Unknown record type"); return AVERROR_INVALIDDATA; } - if (bytestream2_get_byte(&s->gb)) { + if (bytestream2_get_byte(&gb)) { avpriv_request_sample(avctx, "Padding bytes"); return AVERROR_PATCHWELCOME; } - bytestream2_skip(&s->gb, 2); + bytestream2_skip(&gb, 2); - s->x = 0; do { /* if statements are ordered by probability */ #define OP(gb, pixel, count) \ - op(&dst, dst_end, (gb), (pixel), (count), &s->x, avctx->width, s->frame->linesize[0]) + op(&dst, dst_end, (gb), (pixel), (count), &x, avctx->width, s->frame->linesize[0]) - int type = bytestream2_get_byte(&s->gb); + int type = bytestream2_get_byte(&gb); count = type & 0x7F; type >>= 7; if (count) { - if (OP(type ? NULL : &s->gb, -1, count)) break; + if (OP(type ? NULL : &gb, -1, count)) break; } else if (!type) { int pixel; - count = bytestream2_get_byte(&s->gb); /* count==0 gives nop */ - pixel = bytestream2_get_byte(&s->gb); + count = bytestream2_get_byte(&gb); /* count==0 gives nop */ + pixel = bytestream2_get_byte(&gb); if (OP(NULL, pixel, count)) break; } else { int pixel; - type = bytestream2_get_le16(&s->gb); + type = bytestream2_get_le16(&gb); count = type & 0x3FFF; type >>= 14; if (!count) { @@ -169,11 +166,11 @@ } continue; } - pixel = type == 3 ? bytestream2_get_byte(&s->gb) : -1; + pixel = type == 3 ? bytestream2_get_byte(&gb) : -1; if (type == 1) count += 0x4000; - if (OP(type == 2 ? &s->gb : NULL, pixel, count)) break; + if (OP(type == 2 ? &gb : NULL, pixel, count)) break; } - } while (bytestream2_get_bytes_left(&s->gb) > 0); + } while (bytestream2_get_bytes_left(&gb) > 0); memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE); diff -Nru ffmpeg-4.2.2/libavcodec/ansi.c ffmpeg-4.4/libavcodec/ansi.c --- ffmpeg-4.2.2/libavcodec/ansi.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ansi.c 2021-02-20 20:27:47.000000000 +0000 @@ -34,6 +34,7 @@ #define ATTR_BOLD 0x01 /**< Bold/Bright-foreground (mode 1) */ #define ATTR_FAINT 0x02 /**< Faint (mode 2) */ +#define ATTR_ITALICS 0x04 /**< Italics (mode 3) */ #define ATTR_UNDERLINE 0x08 /**< Underline (mode 4) */ #define ATTR_BLINK 0x10 /**< Blink/Bright-background (mode 5) */ #define ATTR_REVERSE 0x40 /**< Reverse (mode 7) */ @@ -308,7 +309,7 @@ s->attributes = 0; s->fg = DEFAULT_FG_COLOR; s->bg = DEFAULT_BG_COLOR; - } else if (m == 1 || m == 2 || m == 4 || m == 5 || m == 7 || m == 8) { + } else if (m == 1 || m == 2 || m == 3 || m == 4 || m == 5 || m == 7 || m == 8) { s->attributes |= 1 << (m - 1); } else if (m >= 30 && m <= 37) { s->fg = ansi_to_cga[m - 30]; @@ -362,7 +363,7 @@ const uint8_t *buf_end = buf+buf_size; int ret, i, count; - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; if (!avctx->frame_number) { for (i=0; iheight; i++) @@ -430,7 +431,8 @@ s->args[s->nb_args] = FFMAX(s->args[s->nb_args], 0) * 10 + buf[0] - '0'; break; case ';': - s->nb_args++; + if (s->nb_args < MAX_NB_ARGS) + s->nb_args++; if (s->nb_args < MAX_NB_ARGS) s->args[s->nb_args] = 0; break; @@ -473,6 +475,11 @@ return 0; } +static const AVCodecDefault ansi_defaults[] = { + { "max_pixels", "640*480" }, + { NULL }, +}; + AVCodec ff_ansi_decoder = { .name = "ansi", .long_name = NULL_IF_CONFIG_SMALL("ASCII/ANSI art"), @@ -484,4 +491,5 @@ .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .defaults = ansi_defaults, }; diff -Nru ffmpeg-4.2.2/libavcodec/apedec.c ffmpeg-4.4/libavcodec/apedec.c --- ffmpeg-4.2.2/libavcodec/apedec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/apedec.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" +#include "libavutil/crc.h" #include "libavutil/opt.h" #include "lossless_audiodsp.h" #include "avcodec.h" @@ -125,13 +126,28 @@ int32_t filterA[2]; int32_t filterB[2]; - int32_t coeffsA[2][4]; ///< adaption coefficients - int32_t coeffsB[2][5]; ///< adaption coefficients + uint32_t coeffsA[2][4]; ///< adaption coefficients + uint32_t coeffsB[2][5]; ///< adaption coefficients int32_t historybuffer[HISTORY_SIZE + PREDICTOR_SIZE]; unsigned int sample_pos; } APEPredictor; +typedef struct APEPredictor64 { + int64_t *buf; + + int64_t lastA[2]; + + int64_t filterA[2]; + int64_t filterB[2]; + + uint64_t coeffsA[2][4]; ///< adaption coefficients + uint64_t coeffsB[2][5]; ///< adaption coefficients + int64_t historybuffer[HISTORY_SIZE + PREDICTOR_SIZE]; + + unsigned int sample_pos; +} APEPredictor64; + /** Decoder context */ typedef struct APEContext { AVClass *class; ///< class for AVOptions @@ -147,9 +163,11 @@ int fset; ///< which filter set to use (calculated from compression level) int flags; ///< global decoder flags - uint32_t CRC; ///< frame CRC + uint32_t CRC; ///< signalled frame CRC + uint32_t CRC_state; ///< accumulated CRC int frameflags; ///< frame flags APEPredictor predictor; ///< predictor used for final reconstruction + APEPredictor64 predictor64; ///< 64bit predictor used for final reconstruction int32_t *decoded_buffer; int decoded_size; @@ -225,6 +243,7 @@ av_log(avctx, AV_LOG_ERROR, "Only mono and stereo is supported\n"); return AVERROR(EINVAL); } + avctx->bits_per_raw_sample = s->bps = avctx->bits_per_coded_sample; switch (s->bps) { case 8: @@ -260,9 +279,8 @@ for (i = 0; i < APE_FILTER_LEVELS; i++) { if (!ape_filter_orders[s->fset][i]) break; - FF_ALLOC_OR_GOTO(avctx, s->filterbuf[i], - (ape_filter_orders[s->fset][i] * 3 + HISTORY_SIZE) * 4, - filter_alloc_fail); + if (!(s->filterbuf[i] = av_malloc((ape_filter_orders[s->fset][i] * 3 + HISTORY_SIZE) * 4))) + return AVERROR(ENOMEM); } if (s->fileversion < 3860) { @@ -298,9 +316,6 @@ avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; return 0; -filter_alloc_fail: - ape_decode_close(avctx); - return AVERROR(ENOMEM); } /** @@ -496,6 +511,7 @@ x = (overflow << rice->k) + get_bits(gb, rice->k); } else { av_log(ctx->avctx, AV_LOG_ERROR, "Too many bits: %"PRIu32"\n", rice->k); + ctx->error = 1; return AVERROR_INVALIDDATA; } rice->ksum += x - (rice->ksum + 8 >> 4); @@ -544,12 +560,10 @@ static inline int ape_decode_value_3990(APEContext *ctx, APERice *rice) { - unsigned int x, overflow; - int base, pivot; + unsigned int x, overflow, pivot; + int base; - pivot = rice->ksum >> 5; - if (pivot == 0) - pivot = 1; + pivot = FFMAX(rice->ksum >> 5, 1); overflow = range_get_symbol(ctx, counts_3980, counts_diff_3980); @@ -585,6 +599,11 @@ return ((x >> 1) ^ ((x & 1) - 1)) + 1; } +static int get_k(int ksum) +{ + return av_log2(ksum) + !!ksum; +} + static void decode_array_0000(APEContext *ctx, GetBitContext *gb, int32_t *out, APERice *rice, int blockstodecode) { @@ -596,21 +615,34 @@ out[i] = get_rice_ook(&ctx->gb, 10); rice->ksum += out[i]; } - rice->k = av_log2(rice->ksum / 10) + 1; + + if (blockstodecode <= 5) + goto end; + + rice->k = get_k(rice->ksum / 10); if (rice->k >= 24) return; for (; i < FFMIN(blockstodecode, 64); i++) { out[i] = get_rice_ook(&ctx->gb, rice->k); rice->ksum += out[i]; - rice->k = av_log2(rice->ksum / ((i + 1) * 2)) + 1; + rice->k = get_k(rice->ksum / ((i + 1) * 2)); if (rice->k >= 24) return; } + + if (blockstodecode <= 64) + goto end; + + rice->k = get_k(rice->ksum >> 7); ksummax = 1 << rice->k + 7; ksummin = rice->k ? (1 << rice->k + 6) : 0; for (; i < blockstodecode; i++) { + if (get_bits_left(&ctx->gb) < 1) { + ctx->error = 1; + return; + } out[i] = get_rice_ook(&ctx->gb, rice->k); - rice->ksum += out[i] - out[i - 64]; + rice->ksum += out[i] - (unsigned)out[i - 64]; while (rice->ksum < ksummin) { rice->k--; ksummin = rice->k ? ksummin >> 1 : 0; @@ -625,6 +657,7 @@ } } +end: for (i = 0; i < blockstodecode; i++) out[i] = ((out[i] >> 1) ^ ((out[i] & 1) - 1)) + 1; } @@ -730,6 +763,7 @@ /* Read the frame flags if they exist */ ctx->frameflags = 0; + ctx->CRC_state = UINT32_MAX; if ((ctx->fileversion > 3820) && (ctx->CRC & 0x80000000)) { ctx->CRC &= ~0x80000000; @@ -770,13 +804,20 @@ 360, 317, -109, 98 }; +static const int64_t initial_coeffs_3930_64bit[4] = { + 360, 317, -109, 98 +}; + static void init_predictor_decoder(APEContext *ctx) { APEPredictor *p = &ctx->predictor; + APEPredictor64 *p64 = &ctx->predictor64; /* Zero the history buffers */ memset(p->historybuffer, 0, PREDICTOR_SIZE * sizeof(*p->historybuffer)); + memset(p64->historybuffer, 0, PREDICTOR_SIZE * sizeof(*p64->historybuffer)); p->buf = p->historybuffer; + p64->buf = p64->historybuffer; /* Initialize and zero the coefficients */ if (ctx->fileversion < 3930) { @@ -794,8 +835,11 @@ } else { memcpy(p->coeffsA[0], initial_coeffs_3930, sizeof(initial_coeffs_3930)); memcpy(p->coeffsA[1], initial_coeffs_3930, sizeof(initial_coeffs_3930)); + memcpy(p64->coeffsA[0], initial_coeffs_3930_64bit, sizeof(initial_coeffs_3930_64bit)); + memcpy(p64->coeffsA[1], initial_coeffs_3930_64bit, sizeof(initial_coeffs_3930_64bit)); } memset(p->coeffsB, 0, sizeof(p->coeffsB)); + memset(p64->coeffsB, 0, sizeof(p64->coeffsB)); if (ctx->fileversion < 3930) { memcpy(p->coeffsB[0], initial_coeffs_b_3800, sizeof(initial_coeffs_b_3800)); @@ -807,7 +851,13 @@ p->filterB[0] = p->filterB[1] = 0; p->lastA[0] = p->lastA[1] = 0; + p64->filterA[0] = p64->filterA[1] = 0; + p64->filterB[0] = p64->filterB[1] = 0; + p64->lastA[0] = p64->lastA[1] = 0; + p->sample_pos = 0; + + p64->sample_pos = 0; } /** Get inverse sign of integer (-1 for positive, 1 for negative and 0 for zero) */ @@ -828,8 +878,8 @@ return decoded; } - predictionA = p->buf[delayA] * 2 - p->buf[delayA - 1]; - p->lastA[filter] = decoded + (predictionA * p->coeffsA[filter][0] >> 9); + predictionA = p->buf[delayA] * 2U - p->buf[delayA - 1]; + p->lastA[filter] = decoded + ((int32_t)(predictionA * p->coeffsA[filter][0]) >> 9); if ((decoded ^ predictionA) > 0) p->coeffsA[filter][0]++; @@ -842,7 +892,7 @@ } static av_always_inline int filter_3800(APEPredictor *p, - const int decoded, const int filter, + const unsigned decoded, const int filter, const int delayA, const int delayB, const int start, const int shift) { @@ -1113,16 +1163,17 @@ } } -static av_always_inline int predictor_update_filter(APEPredictor *p, +static av_always_inline int predictor_update_filter(APEPredictor64 *p, const int decoded, const int filter, const int delayA, const int delayB, const int adaptA, const int adaptB) { - int32_t predictionA, predictionB, sign; + int64_t predictionA, predictionB; + int32_t sign; p->buf[delayA] = p->lastA[filter]; p->buf[adaptA] = APESIGN(p->buf[delayA]); - p->buf[delayA - 1] = p->buf[delayA] - (unsigned)p->buf[delayA - 1]; + p->buf[delayA - 1] = p->buf[delayA] - (uint64_t)p->buf[delayA - 1]; p->buf[adaptA - 1] = APESIGN(p->buf[delayA - 1]); predictionA = p->buf[delayA ] * p->coeffsA[filter][0] + @@ -1131,9 +1182,9 @@ p->buf[delayA - 3] * p->coeffsA[filter][3]; /* Apply a scaled first-order filter compression */ - p->buf[delayB] = p->filterA[filter ^ 1] - ((int)(p->filterB[filter] * 31U) >> 5); + p->buf[delayB] = p->filterA[filter ^ 1] - ((int64_t)(p->filterB[filter] * 31ULL) >> 5); p->buf[adaptB] = APESIGN(p->buf[delayB]); - p->buf[delayB - 1] = p->buf[delayB] - (unsigned)p->buf[delayB - 1]; + p->buf[delayB - 1] = p->buf[delayB] - (uint64_t)p->buf[delayB - 1]; p->buf[adaptB - 1] = APESIGN(p->buf[delayB - 1]); p->filterB[filter] = p->filterA[filter ^ 1]; @@ -1143,8 +1194,8 @@ p->buf[delayB - 3] * p->coeffsB[filter][3] + p->buf[delayB - 4] * p->coeffsB[filter][4]; - p->lastA[filter] = decoded + ((int)((unsigned)predictionA + (predictionB >> 1)) >> 10); - p->filterA[filter] = p->lastA[filter] + ((int)(p->filterA[filter] * 31U) >> 5); + p->lastA[filter] = decoded + ((int64_t)((uint64_t)predictionA + (predictionB >> 1)) >> 10); + p->filterA[filter] = p->lastA[filter] + ((int64_t)(p->filterA[filter] * 31ULL) >> 5); sign = APESIGN(decoded); p->coeffsA[filter][0] += p->buf[adaptA ] * sign; @@ -1162,7 +1213,7 @@ static void predictor_decode_stereo_3950(APEContext *ctx, int count) { - APEPredictor *p = &ctx->predictor; + APEPredictor64 *p = &ctx->predictor64; int32_t *decoded0 = ctx->decoded[0]; int32_t *decoded1 = ctx->decoded[1]; @@ -1191,7 +1242,7 @@ static void predictor_decode_mono_3950(APEContext *ctx, int count) { - APEPredictor *p = &ctx->predictor; + APEPredictor64 *p = &ctx->predictor64; int32_t *decoded0 = ctx->decoded[0]; int32_t predictionA, currentA, A, sign; @@ -1203,14 +1254,14 @@ A = *decoded0; p->buf[YDELAYA] = currentA; - p->buf[YDELAYA - 1] = p->buf[YDELAYA] - p->buf[YDELAYA - 1]; + p->buf[YDELAYA - 1] = p->buf[YDELAYA] - (uint64_t)p->buf[YDELAYA - 1]; predictionA = p->buf[YDELAYA ] * p->coeffsA[0][0] + p->buf[YDELAYA - 1] * p->coeffsA[0][1] + p->buf[YDELAYA - 2] * p->coeffsA[0][2] + p->buf[YDELAYA - 3] * p->coeffsA[0][3]; - currentA = A + (predictionA >> 10); + currentA = A + (uint64_t)(predictionA >> 10); p->buf[YADAPTCOEFFSA] = APESIGN(p->buf[YDELAYA ]); p->buf[YADAPTCOEFFSA - 1] = APESIGN(p->buf[YDELAYA - 1]); @@ -1230,7 +1281,7 @@ p->buf = p->historybuffer; } - p->filterA[0] = currentA + (unsigned)((int)(p->filterA[0] * 31U) >> 5); + p->filterA[0] = currentA + (uint64_t)((int64_t)(p->filterA[0] * 31U) >> 5); *(decoded0++) = p->filterA[0]; } @@ -1259,7 +1310,7 @@ int32_t *data, int count, int order, int fracbits) { int res; - int absres; + unsigned absres; while (count--) { /* round fixedpoint scalar product */ @@ -1267,7 +1318,7 @@ f->delay - order, f->adaptcoeffs - order, order, APESIGN(*data)); - res = (int)(res + (1U << (fracbits - 1))) >> fracbits; + res = (int64_t)(res + (1LL << (fracbits - 1))) >> fracbits; res += (unsigned)*data; *data++ = res; @@ -1283,7 +1334,7 @@ /* Version 3.98 and later files */ /* Update the adaption coefficients */ - absres = res < 0 ? -(unsigned)res : res; + absres = FFABSU(res); if (absres) *f->adaptcoeffs = APESIGN(res) * (8 << ((absres > f->avg * 3) + (absres > f->avg * 4 / 3))); @@ -1365,6 +1416,8 @@ } ctx->entropy_decode_mono(ctx, count); + if (ctx->error) + return; /* Now apply the predictor decoding */ ctx->predictor_decode_mono(ctx, count); @@ -1388,6 +1441,8 @@ } ctx->entropy_decode_stereo(ctx, count); + if (ctx->error) + return; /* Now apply the predictor decoding */ ctx->predictor_decode_stereo(ctx, count); @@ -1498,6 +1553,14 @@ /* reallocate decoded sample buffer if needed */ decoded_buffer_size = 2LL * FFALIGN(blockstodecode, 8) * sizeof(*s->decoded_buffer); av_assert0(decoded_buffer_size <= INT_MAX); + + /* get output buffer */ + frame->nb_samples = blockstodecode; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { + s->samples=0; + return ret; + } + av_fast_malloc(&s->decoded_buffer, &s->decoded_size, decoded_buffer_size); if (!s->decoded_buffer) return AVERROR(ENOMEM); @@ -1505,11 +1568,6 @@ s->decoded[0] = s->decoded_buffer; s->decoded[1] = s->decoded_buffer + FFALIGN(blockstodecode, 8); - /* get output buffer */ - frame->nb_samples = blockstodecode; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; - s->error=0; if ((s->channels == 1) || (s->frameflags & APE_FRAMECODE_PSEUDO_STEREO)) @@ -1543,13 +1601,34 @@ for (ch = 0; ch < s->channels; ch++) { sample24 = (int32_t *)frame->data[ch]; for (i = 0; i < blockstodecode; i++) - *sample24++ = s->decoded[ch][i] << 8; + *sample24++ = s->decoded[ch][i] * 256U; } break; } s->samples -= blockstodecode; + if (avctx->err_recognition & AV_EF_CRCCHECK && + s->fileversion >= 3900 && s->bps < 24) { + uint32_t crc = s->CRC_state; + const AVCRC *crc_tab = av_crc_get_table(AV_CRC_32_IEEE_LE); + for (i = 0; i < blockstodecode; i++) { + for (ch = 0; ch < s->channels; ch++) { + uint8_t *smp = frame->data[ch] + (i*(s->bps >> 3)); + crc = av_crc(crc_tab, crc, smp, s->bps >> 3); + } + } + + if (!s->samples && (~crc >> 1) ^ s->CRC) { + av_log(avctx, AV_LOG_ERROR, "CRC mismatch! Previously decoded " + "frames may have been affected as well.\n"); + if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + } + + s->CRC_state = crc; + } + *got_frame_ptr = 1; return !s->samples ? avpkt->size : 0; @@ -1587,6 +1666,7 @@ .decode = ape_decode_frame, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .flush = ape_flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, diff -Nru ffmpeg-4.2.2/libavcodec/aptx.c ffmpeg-4.4/libavcodec/aptx.c --- ffmpeg-4.2.2/libavcodec/aptx.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aptx.c 2020-07-11 10:39:30.000000000 +0000 @@ -20,81 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/intreadwrite.h" -#include "avcodec.h" -#include "internal.h" -#include "mathops.h" -#include "audio_frame_queue.h" - - -enum channels { - LEFT, - RIGHT, - NB_CHANNELS -}; - -enum subbands { - LF, // Low Frequency (0-5.5 kHz) - MLF, // Medium-Low Frequency (5.5-11kHz) - MHF, // Medium-High Frequency (11-16.5kHz) - HF, // High Frequency (16.5-22kHz) - NB_SUBBANDS -}; - -#define NB_FILTERS 2 -#define FILTER_TAPS 16 - -typedef struct { - int pos; - int32_t buffer[2*FILTER_TAPS]; -} FilterSignal; - -typedef struct { - FilterSignal outer_filter_signal[NB_FILTERS]; - FilterSignal inner_filter_signal[NB_FILTERS][NB_FILTERS]; -} QMFAnalysis; - -typedef struct { - int32_t quantized_sample; - int32_t quantized_sample_parity_change; - int32_t error; -} Quantize; - -typedef struct { - int32_t quantization_factor; - int32_t factor_select; - int32_t reconstructed_difference; -} InvertQuantize; - -typedef struct { - int32_t prev_sign[2]; - int32_t s_weight[2]; - int32_t d_weight[24]; - int32_t pos; - int32_t reconstructed_differences[48]; - int32_t previous_reconstructed_sample; - int32_t predicted_difference; - int32_t predicted_sample; -} Prediction; - -typedef struct { - int32_t codeword_history; - int32_t dither_parity; - int32_t dither[NB_SUBBANDS]; - - QMFAnalysis qmf; - Quantize quantize[NB_SUBBANDS]; - InvertQuantize invert_quantize[NB_SUBBANDS]; - Prediction prediction[NB_SUBBANDS]; -} Channel; - -typedef struct { - int hd; - int block_size; - int32_t sync_idx; - Channel channels[NB_CHANNELS]; - AudioFrameQueue afq; -} AptXContext; +#include "aptx.h" static const int32_t quantize_intervals_LF[65] = { @@ -383,17 +309,7 @@ 70, 90, 115, 147, 192, 264, 398, 521, 521, }; -typedef const struct { - const int32_t *quantize_intervals; - const int32_t *invert_quantize_dither_factors; - const int32_t *quantize_dither_factors; - const int16_t *quantize_factor_select_offset; - int tables_size; - int32_t factor_max; - int32_t prediction_order; -} ConstTables; - -static ConstTables tables[2][NB_SUBBANDS] = { +ConstTables ff_aptx_quant_tables[2][NB_SUBBANDS] = { { [LF] = { quantize_intervals_LF, invert_quantize_dither_factors_LF, @@ -456,24 +372,6 @@ }; -/* Rounded right shift with optionnal clipping */ -#define RSHIFT_SIZE(size) \ -av_always_inline \ -static int##size##_t rshift##size(int##size##_t value, int shift) \ -{ \ - int##size##_t rounding = (int##size##_t)1 << (shift - 1); \ - int##size##_t mask = ((int##size##_t)1 << (shift + 1)) - 1; \ - return ((value + rounding) >> shift) - ((value & mask) == rounding); \ -} \ -av_always_inline \ -static int##size##_t rshift##size##_clip24(int##size##_t value, int shift) \ -{ \ - return av_clip_intp2(rshift##size(value, shift), 23); \ -} -RSHIFT_SIZE(32) -RSHIFT_SIZE(64) - - av_always_inline static void aptx_update_codeword_history(Channel *channel) { @@ -483,7 +381,7 @@ channel->codeword_history = (cw << 8) + ((unsigned)channel->codeword_history << 4); } -static void aptx_generate_dither(Channel *channel) +void ff_aptx_generate_dither(Channel *channel) { int subband; int64_t m; @@ -498,256 +396,6 @@ channel->dither_parity = (d >> 25) & 1; } -/* - * Convolution filter coefficients for the outer QMF of the QMF tree. - * The 2 sets are a mirror of each other. - */ -static const int32_t aptx_qmf_outer_coeffs[NB_FILTERS][FILTER_TAPS] = { - { - 730, -413, -9611, 43626, -121026, 269973, -585547, 2801966, - 697128, -160481, 27611, 8478, -10043, 3511, 688, -897, - }, - { - -897, 688, 3511, -10043, 8478, 27611, -160481, 697128, - 2801966, -585547, 269973, -121026, 43626, -9611, -413, 730, - }, -}; - -/* - * Convolution filter coefficients for the inner QMF of the QMF tree. - * The 2 sets are a mirror of each other. - */ -static const int32_t aptx_qmf_inner_coeffs[NB_FILTERS][FILTER_TAPS] = { - { - 1033, -584, -13592, 61697, -171156, 381799, -828088, 3962579, - 985888, -226954, 39048, 11990, -14203, 4966, 973, -1268, - }, - { - -1268, 973, 4966, -14203, 11990, 39048, -226954, 985888, - 3962579, -828088, 381799, -171156, 61697, -13592, -584, 1033, - }, -}; - -/* - * Push one sample into a circular signal buffer. - */ -av_always_inline -static void aptx_qmf_filter_signal_push(FilterSignal *signal, int32_t sample) -{ - signal->buffer[signal->pos ] = sample; - signal->buffer[signal->pos+FILTER_TAPS] = sample; - signal->pos = (signal->pos + 1) & (FILTER_TAPS - 1); -} - -/* - * Compute the convolution of the signal with the coefficients, and reduce - * to 24 bits by applying the specified right shifting. - */ -av_always_inline -static int32_t aptx_qmf_convolution(FilterSignal *signal, - const int32_t coeffs[FILTER_TAPS], - int shift) -{ - int32_t *sig = &signal->buffer[signal->pos]; - int64_t e = 0; - int i; - - for (i = 0; i < FILTER_TAPS; i++) - e += MUL64(sig[i], coeffs[i]); - - return rshift64_clip24(e, shift); -} - -/* - * Half-band QMF analysis filter realized with a polyphase FIR filter. - * Split into 2 subbands and downsample by 2. - * So for each pair of samples that goes in, one sample goes out, - * split into 2 separate subbands. - */ -av_always_inline -static void aptx_qmf_polyphase_analysis(FilterSignal signal[NB_FILTERS], - const int32_t coeffs[NB_FILTERS][FILTER_TAPS], - int shift, - int32_t samples[NB_FILTERS], - int32_t *low_subband_output, - int32_t *high_subband_output) -{ - int32_t subbands[NB_FILTERS]; - int i; - - for (i = 0; i < NB_FILTERS; i++) { - aptx_qmf_filter_signal_push(&signal[i], samples[NB_FILTERS-1-i]); - subbands[i] = aptx_qmf_convolution(&signal[i], coeffs[i], shift); - } - - *low_subband_output = av_clip_intp2(subbands[0] + subbands[1], 23); - *high_subband_output = av_clip_intp2(subbands[0] - subbands[1], 23); -} - -/* - * Two stage QMF analysis tree. - * Split 4 input samples into 4 subbands and downsample by 4. - * So for each group of 4 samples that goes in, one sample goes out, - * split into 4 separate subbands. - */ -static void aptx_qmf_tree_analysis(QMFAnalysis *qmf, - int32_t samples[4], - int32_t subband_samples[4]) -{ - int32_t intermediate_samples[4]; - int i; - - /* Split 4 input samples into 2 intermediate subbands downsampled to 2 samples */ - for (i = 0; i < 2; i++) - aptx_qmf_polyphase_analysis(qmf->outer_filter_signal, - aptx_qmf_outer_coeffs, 23, - &samples[2*i], - &intermediate_samples[0+i], - &intermediate_samples[2+i]); - - /* Split 2 intermediate subband samples into 4 final subbands downsampled to 1 sample */ - for (i = 0; i < 2; i++) - aptx_qmf_polyphase_analysis(qmf->inner_filter_signal[i], - aptx_qmf_inner_coeffs, 23, - &intermediate_samples[2*i], - &subband_samples[2*i+0], - &subband_samples[2*i+1]); -} - -/* - * Half-band QMF synthesis filter realized with a polyphase FIR filter. - * Join 2 subbands and upsample by 2. - * So for each 2 subbands sample that goes in, a pair of samples goes out. - */ -av_always_inline -static void aptx_qmf_polyphase_synthesis(FilterSignal signal[NB_FILTERS], - const int32_t coeffs[NB_FILTERS][FILTER_TAPS], - int shift, - int32_t low_subband_input, - int32_t high_subband_input, - int32_t samples[NB_FILTERS]) -{ - int32_t subbands[NB_FILTERS]; - int i; - - subbands[0] = low_subband_input + high_subband_input; - subbands[1] = low_subband_input - high_subband_input; - - for (i = 0; i < NB_FILTERS; i++) { - aptx_qmf_filter_signal_push(&signal[i], subbands[1-i]); - samples[i] = aptx_qmf_convolution(&signal[i], coeffs[i], shift); - } -} - -/* - * Two stage QMF synthesis tree. - * Join 4 subbands and upsample by 4. - * So for each 4 subbands sample that goes in, a group of 4 samples goes out. - */ -static void aptx_qmf_tree_synthesis(QMFAnalysis *qmf, - int32_t subband_samples[4], - int32_t samples[4]) -{ - int32_t intermediate_samples[4]; - int i; - - /* Join 4 subbands into 2 intermediate subbands upsampled to 2 samples. */ - for (i = 0; i < 2; i++) - aptx_qmf_polyphase_synthesis(qmf->inner_filter_signal[i], - aptx_qmf_inner_coeffs, 22, - subband_samples[2*i+0], - subband_samples[2*i+1], - &intermediate_samples[2*i]); - - /* Join 2 samples from intermediate subbands upsampled to 4 samples. */ - for (i = 0; i < 2; i++) - aptx_qmf_polyphase_synthesis(qmf->outer_filter_signal, - aptx_qmf_outer_coeffs, 21, - intermediate_samples[0+i], - intermediate_samples[2+i], - &samples[2*i]); -} - - -av_always_inline -static int32_t aptx_bin_search(int32_t value, int32_t factor, - const int32_t *intervals, int32_t nb_intervals) -{ - int32_t idx = 0; - int i; - - for (i = nb_intervals >> 1; i > 0; i >>= 1) - if (MUL64(factor, intervals[idx + i]) <= ((int64_t)value << 24)) - idx += i; - - return idx; -} - -static void aptx_quantize_difference(Quantize *quantize, - int32_t sample_difference, - int32_t dither, - int32_t quantization_factor, - ConstTables *tables) -{ - const int32_t *intervals = tables->quantize_intervals; - int32_t quantized_sample, dithered_sample, parity_change; - int32_t d, mean, interval, inv, sample_difference_abs; - int64_t error; - - sample_difference_abs = FFABS(sample_difference); - sample_difference_abs = FFMIN(sample_difference_abs, (1 << 23) - 1); - - quantized_sample = aptx_bin_search(sample_difference_abs >> 4, - quantization_factor, - intervals, tables->tables_size); - - d = rshift32_clip24(MULH(dither, dither), 7) - (1 << 23); - d = rshift64(MUL64(d, tables->quantize_dither_factors[quantized_sample]), 23); - - intervals += quantized_sample; - mean = (intervals[1] + intervals[0]) / 2; - interval = (intervals[1] - intervals[0]) * (-(sample_difference < 0) | 1); - - dithered_sample = rshift64_clip24(MUL64(dither, interval) + ((int64_t)av_clip_intp2(mean + d, 23) << 32), 32); - error = ((int64_t)sample_difference_abs << 20) - MUL64(dithered_sample, quantization_factor); - quantize->error = FFABS(rshift64(error, 23)); - - parity_change = quantized_sample; - if (error < 0) - quantized_sample--; - else - parity_change--; - - inv = -(sample_difference < 0); - quantize->quantized_sample = quantized_sample ^ inv; - quantize->quantized_sample_parity_change = parity_change ^ inv; -} - -static void aptx_encode_channel(Channel *channel, int32_t samples[4], int hd) -{ - int32_t subband_samples[4]; - int subband; - aptx_qmf_tree_analysis(&channel->qmf, samples, subband_samples); - aptx_generate_dither(channel); - for (subband = 0; subband < NB_SUBBANDS; subband++) { - int32_t diff = av_clip_intp2(subband_samples[subband] - channel->prediction[subband].predicted_sample, 23); - aptx_quantize_difference(&channel->quantize[subband], diff, - channel->dither[subband], - channel->invert_quantize[subband].quantization_factor, - &tables[hd][subband]); - } -} - -static void aptx_decode_channel(Channel *channel, int32_t samples[4]) -{ - int32_t subband_samples[4]; - int subband; - for (subband = 0; subband < NB_SUBBANDS; subband++) - subband_samples[subband] = channel->prediction[subband].previous_reconstructed_sample; - aptx_qmf_tree_synthesis(&channel->qmf, subband_samples, samples); -} - - static void aptx_invert_quantization(InvertQuantize *invert_quantize, int32_t quantized_sample, int32_t dither, ConstTables *tables) @@ -845,7 +493,7 @@ tables->prediction_order); } -static void aptx_invert_quantize_and_prediction(Channel *channel, int hd) +void ff_aptx_invert_quantize_and_prediction(Channel *channel, int hd) { int subband; for (subband = 0; subband < NB_SUBBANDS; subband++) @@ -853,138 +501,10 @@ &channel->prediction[subband], channel->quantize[subband].quantized_sample, channel->dither[subband], - &tables[hd][subband]); -} - -static int32_t aptx_quantized_parity(Channel *channel) -{ - int32_t parity = channel->dither_parity; - int subband; - - for (subband = 0; subband < NB_SUBBANDS; subband++) - parity ^= channel->quantize[subband].quantized_sample; - - return parity & 1; -} - -/* For each sample, ensure that the parity of all subbands of all channels - * is 0 except once every 8 samples where the parity is forced to 1. */ -static int aptx_check_parity(Channel channels[NB_CHANNELS], int32_t *idx) -{ - int32_t parity = aptx_quantized_parity(&channels[LEFT]) - ^ aptx_quantized_parity(&channels[RIGHT]); - - int eighth = *idx == 7; - *idx = (*idx + 1) & 7; - - return parity ^ eighth; -} - -static void aptx_insert_sync(Channel channels[NB_CHANNELS], int32_t *idx) -{ - if (aptx_check_parity(channels, idx)) { - int i; - Channel *c; - static const int map[] = { 1, 2, 0, 3 }; - Quantize *min = &channels[NB_CHANNELS-1].quantize[map[0]]; - for (c = &channels[NB_CHANNELS-1]; c >= channels; c--) - for (i = 0; i < NB_SUBBANDS; i++) - if (c->quantize[map[i]].error < min->error) - min = &c->quantize[map[i]]; - - /* Forcing the desired parity is done by offsetting by 1 the quantized - * sample from the subband featuring the smallest quantization error. */ - min->quantized_sample = min->quantized_sample_parity_change; - } -} - -static uint16_t aptx_pack_codeword(Channel *channel) -{ - int32_t parity = aptx_quantized_parity(channel); - return (((channel->quantize[3].quantized_sample & 0x06) | parity) << 13) - | (((channel->quantize[2].quantized_sample & 0x03) ) << 11) - | (((channel->quantize[1].quantized_sample & 0x0F) ) << 7) - | (((channel->quantize[0].quantized_sample & 0x7F) ) << 0); -} - -static uint32_t aptxhd_pack_codeword(Channel *channel) -{ - int32_t parity = aptx_quantized_parity(channel); - return (((channel->quantize[3].quantized_sample & 0x01E) | parity) << 19) - | (((channel->quantize[2].quantized_sample & 0x00F) ) << 15) - | (((channel->quantize[1].quantized_sample & 0x03F) ) << 9) - | (((channel->quantize[0].quantized_sample & 0x1FF) ) << 0); -} - -static void aptx_unpack_codeword(Channel *channel, uint16_t codeword) -{ - channel->quantize[0].quantized_sample = sign_extend(codeword >> 0, 7); - channel->quantize[1].quantized_sample = sign_extend(codeword >> 7, 4); - channel->quantize[2].quantized_sample = sign_extend(codeword >> 11, 2); - channel->quantize[3].quantized_sample = sign_extend(codeword >> 13, 3); - channel->quantize[3].quantized_sample = (channel->quantize[3].quantized_sample & ~1) - | aptx_quantized_parity(channel); + &ff_aptx_quant_tables[hd][subband]); } -static void aptxhd_unpack_codeword(Channel *channel, uint32_t codeword) -{ - channel->quantize[0].quantized_sample = sign_extend(codeword >> 0, 9); - channel->quantize[1].quantized_sample = sign_extend(codeword >> 9, 6); - channel->quantize[2].quantized_sample = sign_extend(codeword >> 15, 4); - channel->quantize[3].quantized_sample = sign_extend(codeword >> 19, 5); - channel->quantize[3].quantized_sample = (channel->quantize[3].quantized_sample & ~1) - | aptx_quantized_parity(channel); -} - -static void aptx_encode_samples(AptXContext *ctx, - int32_t samples[NB_CHANNELS][4], - uint8_t *output) -{ - int channel; - for (channel = 0; channel < NB_CHANNELS; channel++) - aptx_encode_channel(&ctx->channels[channel], samples[channel], ctx->hd); - - aptx_insert_sync(ctx->channels, &ctx->sync_idx); - - for (channel = 0; channel < NB_CHANNELS; channel++) { - aptx_invert_quantize_and_prediction(&ctx->channels[channel], ctx->hd); - if (ctx->hd) - AV_WB24(output + 3*channel, - aptxhd_pack_codeword(&ctx->channels[channel])); - else - AV_WB16(output + 2*channel, - aptx_pack_codeword(&ctx->channels[channel])); - } -} - -static int aptx_decode_samples(AptXContext *ctx, - const uint8_t *input, - int32_t samples[NB_CHANNELS][4]) -{ - int channel, ret; - - for (channel = 0; channel < NB_CHANNELS; channel++) { - aptx_generate_dither(&ctx->channels[channel]); - - if (ctx->hd) - aptxhd_unpack_codeword(&ctx->channels[channel], - AV_RB24(input + 3*channel)); - else - aptx_unpack_codeword(&ctx->channels[channel], - AV_RB16(input + 2*channel)); - aptx_invert_quantize_and_prediction(&ctx->channels[channel], ctx->hd); - } - - ret = aptx_check_parity(ctx->channels, &ctx->sync_idx); - - for (channel = 0; channel < NB_CHANNELS; channel++) - aptx_decode_channel(&ctx->channels[channel], samples[channel]); - - return ret; -} - - -static av_cold int aptx_init(AVCodecContext *avctx) +av_cold int ff_aptx_init(AVCodecContext *avctx) { AptXContext *s = avctx->priv_data; int chan, subband; @@ -1016,150 +536,3 @@ ff_af_queue_init(avctx, &s->afq); return 0; } - -static int aptx_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame_ptr, AVPacket *avpkt) -{ - AptXContext *s = avctx->priv_data; - AVFrame *frame = data; - int pos, opos, channel, sample, ret; - - if (avpkt->size < s->block_size) { - av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); - return AVERROR_INVALIDDATA; - } - - /* get output buffer */ - frame->channels = NB_CHANNELS; - frame->format = AV_SAMPLE_FMT_S32P; - frame->nb_samples = 4 * avpkt->size / s->block_size; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; - - for (pos = 0, opos = 0; opos < frame->nb_samples; pos += s->block_size, opos += 4) { - int32_t samples[NB_CHANNELS][4]; - - if (aptx_decode_samples(s, &avpkt->data[pos], samples)) { - av_log(avctx, AV_LOG_ERROR, "Synchronization error\n"); - return AVERROR_INVALIDDATA; - } - - for (channel = 0; channel < NB_CHANNELS; channel++) - for (sample = 0; sample < 4; sample++) - AV_WN32A(&frame->data[channel][4*(opos+sample)], - samples[channel][sample] * 256); - } - - *got_frame_ptr = 1; - return s->block_size * frame->nb_samples / 4; -} - -static int aptx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, - const AVFrame *frame, int *got_packet_ptr) -{ - AptXContext *s = avctx->priv_data; - int pos, ipos, channel, sample, output_size, ret; - - if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) - return ret; - - output_size = s->block_size * frame->nb_samples/4; - if ((ret = ff_alloc_packet2(avctx, avpkt, output_size, 0)) < 0) - return ret; - - for (pos = 0, ipos = 0; pos < output_size; pos += s->block_size, ipos += 4) { - int32_t samples[NB_CHANNELS][4]; - - for (channel = 0; channel < NB_CHANNELS; channel++) - for (sample = 0; sample < 4; sample++) - samples[channel][sample] = (int32_t)AV_RN32A(&frame->data[channel][4*(ipos+sample)]) >> 8; - - aptx_encode_samples(s, samples, avpkt->data + pos); - } - - ff_af_queue_remove(&s->afq, frame->nb_samples, &avpkt->pts, &avpkt->duration); - *got_packet_ptr = 1; - return 0; -} - -static av_cold int aptx_close(AVCodecContext *avctx) -{ - AptXContext *s = avctx->priv_data; - ff_af_queue_close(&s->afq); - return 0; -} - - -#if CONFIG_APTX_DECODER -AVCodec ff_aptx_decoder = { - .name = "aptx", - .long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_APTX, - .priv_data_size = sizeof(AptXContext), - .init = aptx_init, - .decode = aptx_decode_frame, - .close = aptx_close, - .capabilities = AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, - .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, - AV_SAMPLE_FMT_NONE }, -}; -#endif - -#if CONFIG_APTX_HD_DECODER -AVCodec ff_aptx_hd_decoder = { - .name = "aptx_hd", - .long_name = NULL_IF_CONFIG_SMALL("aptX HD (Audio Processing Technology for Bluetooth)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_APTX_HD, - .priv_data_size = sizeof(AptXContext), - .init = aptx_init, - .decode = aptx_decode_frame, - .close = aptx_close, - .capabilities = AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, - .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, - AV_SAMPLE_FMT_NONE }, -}; -#endif - -#if CONFIG_APTX_ENCODER -AVCodec ff_aptx_encoder = { - .name = "aptx", - .long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_APTX, - .priv_data_size = sizeof(AptXContext), - .init = aptx_init, - .encode2 = aptx_encode_frame, - .close = aptx_close, - .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, - .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, - AV_SAMPLE_FMT_NONE }, - .supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0}, -}; -#endif - -#if CONFIG_APTX_HD_ENCODER -AVCodec ff_aptx_hd_encoder = { - .name = "aptx_hd", - .long_name = NULL_IF_CONFIG_SMALL("aptX HD (Audio Processing Technology for Bluetooth)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_APTX_HD, - .priv_data_size = sizeof(AptXContext), - .init = aptx_init, - .encode2 = aptx_encode_frame, - .close = aptx_close, - .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, - .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, - AV_SAMPLE_FMT_NONE }, - .supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0}, -}; -#endif diff -Nru ffmpeg-4.2.2/libavcodec/aptxdec.c ffmpeg-4.4/libavcodec/aptxdec.c --- ffmpeg-4.2.2/libavcodec/aptxdec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aptxdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,204 @@ +/* + * Audio Processing Technology codec for Bluetooth (aptX) + * + * Copyright (C) 2017 Aurelien Jacobs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "aptx.h" + +/* + * Half-band QMF synthesis filter realized with a polyphase FIR filter. + * Join 2 subbands and upsample by 2. + * So for each 2 subbands sample that goes in, a pair of samples goes out. + */ +av_always_inline +static void aptx_qmf_polyphase_synthesis(FilterSignal signal[NB_FILTERS], + const int32_t coeffs[NB_FILTERS][FILTER_TAPS], + int shift, + int32_t low_subband_input, + int32_t high_subband_input, + int32_t samples[NB_FILTERS]) +{ + int32_t subbands[NB_FILTERS]; + int i; + + subbands[0] = low_subband_input + high_subband_input; + subbands[1] = low_subband_input - high_subband_input; + + for (i = 0; i < NB_FILTERS; i++) { + aptx_qmf_filter_signal_push(&signal[i], subbands[1-i]); + samples[i] = aptx_qmf_convolution(&signal[i], coeffs[i], shift); + } +} + +/* + * Two stage QMF synthesis tree. + * Join 4 subbands and upsample by 4. + * So for each 4 subbands sample that goes in, a group of 4 samples goes out. + */ +static void aptx_qmf_tree_synthesis(QMFAnalysis *qmf, + int32_t subband_samples[4], + int32_t samples[4]) +{ + int32_t intermediate_samples[4]; + int i; + + /* Join 4 subbands into 2 intermediate subbands upsampled to 2 samples. */ + for (i = 0; i < 2; i++) + aptx_qmf_polyphase_synthesis(qmf->inner_filter_signal[i], + aptx_qmf_inner_coeffs, 22, + subband_samples[2*i+0], + subband_samples[2*i+1], + &intermediate_samples[2*i]); + + /* Join 2 samples from intermediate subbands upsampled to 4 samples. */ + for (i = 0; i < 2; i++) + aptx_qmf_polyphase_synthesis(qmf->outer_filter_signal, + aptx_qmf_outer_coeffs, 21, + intermediate_samples[0+i], + intermediate_samples[2+i], + &samples[2*i]); +} + + +static void aptx_decode_channel(Channel *channel, int32_t samples[4]) +{ + int32_t subband_samples[4]; + int subband; + for (subband = 0; subband < NB_SUBBANDS; subband++) + subband_samples[subband] = channel->prediction[subband].previous_reconstructed_sample; + aptx_qmf_tree_synthesis(&channel->qmf, subband_samples, samples); +} + +static void aptx_unpack_codeword(Channel *channel, uint16_t codeword) +{ + channel->quantize[0].quantized_sample = sign_extend(codeword >> 0, 7); + channel->quantize[1].quantized_sample = sign_extend(codeword >> 7, 4); + channel->quantize[2].quantized_sample = sign_extend(codeword >> 11, 2); + channel->quantize[3].quantized_sample = sign_extend(codeword >> 13, 3); + channel->quantize[3].quantized_sample = (channel->quantize[3].quantized_sample & ~1) + | aptx_quantized_parity(channel); +} + +static void aptxhd_unpack_codeword(Channel *channel, uint32_t codeword) +{ + channel->quantize[0].quantized_sample = sign_extend(codeword >> 0, 9); + channel->quantize[1].quantized_sample = sign_extend(codeword >> 9, 6); + channel->quantize[2].quantized_sample = sign_extend(codeword >> 15, 4); + channel->quantize[3].quantized_sample = sign_extend(codeword >> 19, 5); + channel->quantize[3].quantized_sample = (channel->quantize[3].quantized_sample & ~1) + | aptx_quantized_parity(channel); +} + +static int aptx_decode_samples(AptXContext *ctx, + const uint8_t *input, + int32_t samples[NB_CHANNELS][4]) +{ + int channel, ret; + + for (channel = 0; channel < NB_CHANNELS; channel++) { + ff_aptx_generate_dither(&ctx->channels[channel]); + + if (ctx->hd) + aptxhd_unpack_codeword(&ctx->channels[channel], + AV_RB24(input + 3*channel)); + else + aptx_unpack_codeword(&ctx->channels[channel], + AV_RB16(input + 2*channel)); + ff_aptx_invert_quantize_and_prediction(&ctx->channels[channel], ctx->hd); + } + + ret = aptx_check_parity(ctx->channels, &ctx->sync_idx); + + for (channel = 0; channel < NB_CHANNELS; channel++) + aptx_decode_channel(&ctx->channels[channel], samples[channel]); + + return ret; +} + +static int aptx_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AptXContext *s = avctx->priv_data; + AVFrame *frame = data; + int pos, opos, channel, sample, ret; + + if (avpkt->size < s->block_size) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->channels = NB_CHANNELS; + frame->format = AV_SAMPLE_FMT_S32P; + frame->nb_samples = 4 * avpkt->size / s->block_size; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (pos = 0, opos = 0; opos < frame->nb_samples; pos += s->block_size, opos += 4) { + int32_t samples[NB_CHANNELS][4]; + + if (aptx_decode_samples(s, &avpkt->data[pos], samples)) { + av_log(avctx, AV_LOG_ERROR, "Synchronization error\n"); + return AVERROR_INVALIDDATA; + } + + for (channel = 0; channel < NB_CHANNELS; channel++) + for (sample = 0; sample < 4; sample++) + AV_WN32A(&frame->data[channel][4*(opos+sample)], + samples[channel][sample] * 256); + } + + *got_frame_ptr = 1; + return s->block_size * frame->nb_samples / 4; +} + +#if CONFIG_APTX_DECODER +AVCodec ff_aptx_decoder = { + .name = "aptx", + .long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_APTX, + .priv_data_size = sizeof(AptXContext), + .init = ff_aptx_init, + .decode = aptx_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_NONE }, +}; +#endif + +#if CONFIG_APTX_HD_DECODER +AVCodec ff_aptx_hd_decoder = { + .name = "aptx_hd", + .long_name = NULL_IF_CONFIG_SMALL("aptX HD (Audio Processing Technology for Bluetooth)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_APTX_HD, + .priv_data_size = sizeof(AptXContext), + .init = ff_aptx_init, + .decode = aptx_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_NONE }, +}; +#endif diff -Nru ffmpeg-4.2.2/libavcodec/aptxenc.c ffmpeg-4.4/libavcodec/aptxenc.c --- ffmpeg-4.2.2/libavcodec/aptxenc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aptxenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,278 @@ +/* + * Audio Processing Technology codec for Bluetooth (aptX) + * + * Copyright (C) 2017 Aurelien Jacobs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "aptx.h" + +/* + * Half-band QMF analysis filter realized with a polyphase FIR filter. + * Split into 2 subbands and downsample by 2. + * So for each pair of samples that goes in, one sample goes out, + * split into 2 separate subbands. + */ +av_always_inline +static void aptx_qmf_polyphase_analysis(FilterSignal signal[NB_FILTERS], + const int32_t coeffs[NB_FILTERS][FILTER_TAPS], + int shift, + int32_t samples[NB_FILTERS], + int32_t *low_subband_output, + int32_t *high_subband_output) +{ + int32_t subbands[NB_FILTERS]; + int i; + + for (i = 0; i < NB_FILTERS; i++) { + aptx_qmf_filter_signal_push(&signal[i], samples[NB_FILTERS-1-i]); + subbands[i] = aptx_qmf_convolution(&signal[i], coeffs[i], shift); + } + + *low_subband_output = av_clip_intp2(subbands[0] + subbands[1], 23); + *high_subband_output = av_clip_intp2(subbands[0] - subbands[1], 23); +} + +/* + * Two stage QMF analysis tree. + * Split 4 input samples into 4 subbands and downsample by 4. + * So for each group of 4 samples that goes in, one sample goes out, + * split into 4 separate subbands. + */ +static void aptx_qmf_tree_analysis(QMFAnalysis *qmf, + int32_t samples[4], + int32_t subband_samples[4]) +{ + int32_t intermediate_samples[4]; + int i; + + /* Split 4 input samples into 2 intermediate subbands downsampled to 2 samples */ + for (i = 0; i < 2; i++) + aptx_qmf_polyphase_analysis(qmf->outer_filter_signal, + aptx_qmf_outer_coeffs, 23, + &samples[2*i], + &intermediate_samples[0+i], + &intermediate_samples[2+i]); + + /* Split 2 intermediate subband samples into 4 final subbands downsampled to 1 sample */ + for (i = 0; i < 2; i++) + aptx_qmf_polyphase_analysis(qmf->inner_filter_signal[i], + aptx_qmf_inner_coeffs, 23, + &intermediate_samples[2*i], + &subband_samples[2*i+0], + &subband_samples[2*i+1]); +} + +av_always_inline +static int32_t aptx_bin_search(int32_t value, int32_t factor, + const int32_t *intervals, int32_t nb_intervals) +{ + int32_t idx = 0; + int i; + + for (i = nb_intervals >> 1; i > 0; i >>= 1) + if (MUL64(factor, intervals[idx + i]) <= ((int64_t)value << 24)) + idx += i; + + return idx; +} + +static void aptx_quantize_difference(Quantize *quantize, + int32_t sample_difference, + int32_t dither, + int32_t quantization_factor, + ConstTables *tables) +{ + const int32_t *intervals = tables->quantize_intervals; + int32_t quantized_sample, dithered_sample, parity_change; + int32_t d, mean, interval, inv, sample_difference_abs; + int64_t error; + + sample_difference_abs = FFABS(sample_difference); + sample_difference_abs = FFMIN(sample_difference_abs, (1 << 23) - 1); + + quantized_sample = aptx_bin_search(sample_difference_abs >> 4, + quantization_factor, + intervals, tables->tables_size); + + d = rshift32_clip24(MULH(dither, dither), 7) - (1 << 23); + d = rshift64(MUL64(d, tables->quantize_dither_factors[quantized_sample]), 23); + + intervals += quantized_sample; + mean = (intervals[1] + intervals[0]) / 2; + interval = (intervals[1] - intervals[0]) * (-(sample_difference < 0) | 1); + + dithered_sample = rshift64_clip24(MUL64(dither, interval) + ((int64_t)av_clip_intp2(mean + d, 23) << 32), 32); + error = ((int64_t)sample_difference_abs << 20) - MUL64(dithered_sample, quantization_factor); + quantize->error = FFABS(rshift64(error, 23)); + + parity_change = quantized_sample; + if (error < 0) + quantized_sample--; + else + parity_change--; + + inv = -(sample_difference < 0); + quantize->quantized_sample = quantized_sample ^ inv; + quantize->quantized_sample_parity_change = parity_change ^ inv; +} + +static void aptx_encode_channel(Channel *channel, int32_t samples[4], int hd) +{ + int32_t subband_samples[4]; + int subband; + aptx_qmf_tree_analysis(&channel->qmf, samples, subband_samples); + ff_aptx_generate_dither(channel); + for (subband = 0; subband < NB_SUBBANDS; subband++) { + int32_t diff = av_clip_intp2(subband_samples[subband] - channel->prediction[subband].predicted_sample, 23); + aptx_quantize_difference(&channel->quantize[subband], diff, + channel->dither[subband], + channel->invert_quantize[subband].quantization_factor, + &ff_aptx_quant_tables[hd][subband]); + } +} + +static void aptx_insert_sync(Channel channels[NB_CHANNELS], int32_t *idx) +{ + if (aptx_check_parity(channels, idx)) { + int i; + Channel *c; + static const int map[] = { 1, 2, 0, 3 }; + Quantize *min = &channels[NB_CHANNELS-1].quantize[map[0]]; + for (c = &channels[NB_CHANNELS-1]; c >= channels; c--) + for (i = 0; i < NB_SUBBANDS; i++) + if (c->quantize[map[i]].error < min->error) + min = &c->quantize[map[i]]; + + /* Forcing the desired parity is done by offsetting by 1 the quantized + * sample from the subband featuring the smallest quantization error. */ + min->quantized_sample = min->quantized_sample_parity_change; + } +} + +static uint16_t aptx_pack_codeword(Channel *channel) +{ + int32_t parity = aptx_quantized_parity(channel); + return (((channel->quantize[3].quantized_sample & 0x06) | parity) << 13) + | (((channel->quantize[2].quantized_sample & 0x03) ) << 11) + | (((channel->quantize[1].quantized_sample & 0x0F) ) << 7) + | (((channel->quantize[0].quantized_sample & 0x7F) ) << 0); +} + +static uint32_t aptxhd_pack_codeword(Channel *channel) +{ + int32_t parity = aptx_quantized_parity(channel); + return (((channel->quantize[3].quantized_sample & 0x01E) | parity) << 19) + | (((channel->quantize[2].quantized_sample & 0x00F) ) << 15) + | (((channel->quantize[1].quantized_sample & 0x03F) ) << 9) + | (((channel->quantize[0].quantized_sample & 0x1FF) ) << 0); +} + +static void aptx_encode_samples(AptXContext *ctx, + int32_t samples[NB_CHANNELS][4], + uint8_t *output) +{ + int channel; + for (channel = 0; channel < NB_CHANNELS; channel++) + aptx_encode_channel(&ctx->channels[channel], samples[channel], ctx->hd); + + aptx_insert_sync(ctx->channels, &ctx->sync_idx); + + for (channel = 0; channel < NB_CHANNELS; channel++) { + ff_aptx_invert_quantize_and_prediction(&ctx->channels[channel], ctx->hd); + if (ctx->hd) + AV_WB24(output + 3*channel, + aptxhd_pack_codeword(&ctx->channels[channel])); + else + AV_WB16(output + 2*channel, + aptx_pack_codeword(&ctx->channels[channel])); + } +} + +static int aptx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + AptXContext *s = avctx->priv_data; + int pos, ipos, channel, sample, output_size, ret; + + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) + return ret; + + output_size = s->block_size * frame->nb_samples/4; + if ((ret = ff_alloc_packet2(avctx, avpkt, output_size, 0)) < 0) + return ret; + + for (pos = 0, ipos = 0; pos < output_size; pos += s->block_size, ipos += 4) { + int32_t samples[NB_CHANNELS][4]; + + for (channel = 0; channel < NB_CHANNELS; channel++) + for (sample = 0; sample < 4; sample++) + samples[channel][sample] = (int32_t)AV_RN32A(&frame->data[channel][4*(ipos+sample)]) >> 8; + + aptx_encode_samples(s, samples, avpkt->data + pos); + } + + ff_af_queue_remove(&s->afq, frame->nb_samples, &avpkt->pts, &avpkt->duration); + *got_packet_ptr = 1; + return 0; +} + +static av_cold int aptx_close(AVCodecContext *avctx) +{ + AptXContext *s = avctx->priv_data; + ff_af_queue_close(&s->afq); + return 0; +} + +#if CONFIG_APTX_ENCODER +AVCodec ff_aptx_encoder = { + .name = "aptx", + .long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_APTX, + .priv_data_size = sizeof(AptXContext), + .init = ff_aptx_init, + .encode2 = aptx_encode_frame, + .close = aptx_close, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_NONE }, + .supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0}, +}; +#endif + +#if CONFIG_APTX_HD_ENCODER +AVCodec ff_aptx_hd_encoder = { + .name = "aptx_hd", + .long_name = NULL_IF_CONFIG_SMALL("aptX HD (Audio Processing Technology for Bluetooth)"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_APTX_HD, + .priv_data_size = sizeof(AptXContext), + .init = ff_aptx_init, + .encode2 = aptx_encode_frame, + .close = aptx_close, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_NONE }, + .supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0}, +}; +#endif diff -Nru ffmpeg-4.2.2/libavcodec/aptx.h ffmpeg-4.4/libavcodec/aptx.h --- ffmpeg-4.2.2/libavcodec/aptx.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/aptx.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,220 @@ +/* + * Audio Processing Technology codec for Bluetooth (aptX) + * + * Copyright (C) 2017 Aurelien Jacobs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_APTX_H +#define AVCODEC_APTX_H + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" +#include "mathops.h" +#include "audio_frame_queue.h" + + +enum channels { + LEFT, + RIGHT, + NB_CHANNELS +}; + +enum subbands { + LF, // Low Frequency (0-5.5 kHz) + MLF, // Medium-Low Frequency (5.5-11kHz) + MHF, // Medium-High Frequency (11-16.5kHz) + HF, // High Frequency (16.5-22kHz) + NB_SUBBANDS +}; + +#define NB_FILTERS 2 +#define FILTER_TAPS 16 + +typedef struct { + int pos; + int32_t buffer[2*FILTER_TAPS]; +} FilterSignal; + +typedef struct { + FilterSignal outer_filter_signal[NB_FILTERS]; + FilterSignal inner_filter_signal[NB_FILTERS][NB_FILTERS]; +} QMFAnalysis; + +typedef struct { + int32_t quantized_sample; + int32_t quantized_sample_parity_change; + int32_t error; +} Quantize; + +typedef struct { + int32_t quantization_factor; + int32_t factor_select; + int32_t reconstructed_difference; +} InvertQuantize; + +typedef struct { + int32_t prev_sign[2]; + int32_t s_weight[2]; + int32_t d_weight[24]; + int32_t pos; + int32_t reconstructed_differences[48]; + int32_t previous_reconstructed_sample; + int32_t predicted_difference; + int32_t predicted_sample; +} Prediction; + +typedef struct { + int32_t codeword_history; + int32_t dither_parity; + int32_t dither[NB_SUBBANDS]; + + QMFAnalysis qmf; + Quantize quantize[NB_SUBBANDS]; + InvertQuantize invert_quantize[NB_SUBBANDS]; + Prediction prediction[NB_SUBBANDS]; +} Channel; + +typedef struct { + int hd; + int block_size; + int32_t sync_idx; + Channel channels[NB_CHANNELS]; + AudioFrameQueue afq; +} AptXContext; + +typedef const struct { + const int32_t *quantize_intervals; + const int32_t *invert_quantize_dither_factors; + const int32_t *quantize_dither_factors; + const int16_t *quantize_factor_select_offset; + int tables_size; + int32_t factor_max; + int32_t prediction_order; +} ConstTables; + +extern ConstTables ff_aptx_quant_tables[2][NB_SUBBANDS]; + +/* Rounded right shift with optionnal clipping */ +#define RSHIFT_SIZE(size) \ +av_always_inline \ +static int##size##_t rshift##size(int##size##_t value, int shift) \ +{ \ + int##size##_t rounding = (int##size##_t)1 << (shift - 1); \ + int##size##_t mask = ((int##size##_t)1 << (shift + 1)) - 1; \ + return ((value + rounding) >> shift) - ((value & mask) == rounding); \ +} \ +av_always_inline \ +static int##size##_t rshift##size##_clip24(int##size##_t value, int shift) \ +{ \ + return av_clip_intp2(rshift##size(value, shift), 23); \ +} +RSHIFT_SIZE(32) +RSHIFT_SIZE(64) + +/* + * Convolution filter coefficients for the outer QMF of the QMF tree. + * The 2 sets are a mirror of each other. + */ +static const int32_t aptx_qmf_outer_coeffs[NB_FILTERS][FILTER_TAPS] = { + { + 730, -413, -9611, 43626, -121026, 269973, -585547, 2801966, + 697128, -160481, 27611, 8478, -10043, 3511, 688, -897, + }, + { + -897, 688, 3511, -10043, 8478, 27611, -160481, 697128, + 2801966, -585547, 269973, -121026, 43626, -9611, -413, 730, + }, +}; + +/* + * Convolution filter coefficients for the inner QMF of the QMF tree. + * The 2 sets are a mirror of each other. + */ +static const int32_t aptx_qmf_inner_coeffs[NB_FILTERS][FILTER_TAPS] = { + { + 1033, -584, -13592, 61697, -171156, 381799, -828088, 3962579, + 985888, -226954, 39048, 11990, -14203, 4966, 973, -1268, + }, + { + -1268, 973, 4966, -14203, 11990, 39048, -226954, 985888, + 3962579, -828088, 381799, -171156, 61697, -13592, -584, 1033, + }, +}; + +/* + * Push one sample into a circular signal buffer. + */ +av_always_inline +static void aptx_qmf_filter_signal_push(FilterSignal *signal, int32_t sample) +{ + signal->buffer[signal->pos ] = sample; + signal->buffer[signal->pos+FILTER_TAPS] = sample; + signal->pos = (signal->pos + 1) & (FILTER_TAPS - 1); +} + +/* + * Compute the convolution of the signal with the coefficients, and reduce + * to 24 bits by applying the specified right shifting. + */ +av_always_inline +static int32_t aptx_qmf_convolution(FilterSignal *signal, + const int32_t coeffs[FILTER_TAPS], + int shift) +{ + int32_t *sig = &signal->buffer[signal->pos]; + int64_t e = 0; + int i; + + for (i = 0; i < FILTER_TAPS; i++) + e += MUL64(sig[i], coeffs[i]); + + return rshift64_clip24(e, shift); +} + +static inline int32_t aptx_quantized_parity(Channel *channel) +{ + int32_t parity = channel->dither_parity; + int subband; + + for (subband = 0; subband < NB_SUBBANDS; subband++) + parity ^= channel->quantize[subband].quantized_sample; + + return parity & 1; +} + +/* For each sample, ensure that the parity of all subbands of all channels + * is 0 except once every 8 samples where the parity is forced to 1. */ +static inline int aptx_check_parity(Channel channels[NB_CHANNELS], int32_t *idx) +{ + int32_t parity = aptx_quantized_parity(&channels[LEFT]) + ^ aptx_quantized_parity(&channels[RIGHT]); + + int eighth = *idx == 7; + *idx = (*idx + 1) & 7; + + return parity ^ eighth; +} + +void ff_aptx_invert_quantize_and_prediction(Channel *channel, int hd); +void ff_aptx_generate_dither(Channel *channel); + +int ff_aptx_init(AVCodecContext *avctx); + +#endif /* AVCODEC_APTX_H */ diff -Nru ffmpeg-4.2.2/libavcodec/argo.c ffmpeg-4.4/libavcodec/argo.c --- ffmpeg-4.2.2/libavcodec/argo.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/argo.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,740 @@ +/* + * Argonaut Games Video decoder + * Copyright (c) 2020 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 + +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct ArgoContext { + GetByteContext gb; + + int bpp; + int key; + int mv0[128][2]; + int mv1[16][2]; + uint32_t pal[256]; + AVFrame *frame; +} ArgoContext; + +static int decode_pal8(AVCodecContext *avctx, uint32_t *pal) +{ + ArgoContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + int start, count; + + start = bytestream2_get_le16(gb); + count = bytestream2_get_le16(gb); + + if (start + count > 256) + return AVERROR_INVALIDDATA; + + if (bytestream2_get_bytes_left(gb) < 3 * count) + return AVERROR_INVALIDDATA; + + for (int i = 0; i < count; i++) + pal[start + i] = (0xFF << 24U) | bytestream2_get_be24u(gb); + + return 0; +} + +static int decode_avcf(AVCodecContext *avctx, AVFrame *frame) +{ + ArgoContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + const int l = frame->linesize[0]; + const uint8_t *map = gb->buffer; + uint8_t *dst = frame->data[0]; + + if (bytestream2_get_bytes_left(gb) < 1024 + (frame->width / 2) * (frame->height / 2)) + return AVERROR_INVALIDDATA; + + bytestream2_skipu(gb, 1024); + for (int y = 0; y < frame->height; y += 2) { + for (int x = 0; x < frame->width; x += 2) { + int index = bytestream2_get_byteu(gb); + const uint8_t *block = map + index * 4; + + dst[x+0] = block[0]; + dst[x+1] = block[1]; + dst[x+l] = block[2]; + dst[x+l+1] = block[3]; + } + + dst += frame->linesize[0] * 2; + } + + return 0; +} + +static int decode_alcd(AVCodecContext *avctx, AVFrame *frame) +{ + ArgoContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + GetByteContext sb; + const int l = frame->linesize[0]; + const uint8_t *map = gb->buffer; + uint8_t *dst = frame->data[0]; + uint8_t codes = 0; + int count = 0; + + if (bytestream2_get_bytes_left(gb) < 1024 + (((frame->width / 2) * (frame->height / 2) + 7) >> 3)) + return AVERROR_INVALIDDATA; + + bytestream2_skipu(gb, 1024); + sb = *gb; + bytestream2_skipu(gb, ((frame->width / 2) * (frame->height / 2) + 7) >> 3); + + for (int y = 0; y < frame->height; y += 2) { + for (int x = 0; x < frame->width; x += 2) { + const uint8_t *block; + int index; + + if (count == 0) { + codes = bytestream2_get_byteu(&sb); + count = 8; + } + + if (codes & 0x80) { + index = bytestream2_get_byte(gb); + block = map + index * 4; + + dst[x+0] = block[0]; + dst[x+1] = block[1]; + dst[x+l] = block[2]; + dst[x+l+1] = block[3]; + } + + codes <<= 1; + count--; + } + + dst += frame->linesize[0] * 2; + } + + return 0; +} + +static int decode_mad1(AVCodecContext *avctx, AVFrame *frame) +{ + ArgoContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + const int w = frame->width; + const int h = frame->height; + const int l = frame->linesize[0]; + + while (bytestream2_get_bytes_left(gb) > 0) { + int size, type, pos, dy; + uint8_t *dst; + + type = bytestream2_get_byte(gb); + if (type == 0xFF) + break; + + switch (type) { + case 8: + dst = frame->data[0]; + for (int y = 0; y < h; y += 8) { + for (int x = 0; x < w; x += 8) { + int fill = bytestream2_get_byte(gb); + uint8_t *ddst = dst + x; + + for (int by = 0; by < 8; by++) { + memset(ddst, fill, 8); + ddst += l; + } + } + + dst += 8 * l; + } + break; + case 7: + while (bytestream2_get_bytes_left(gb) > 0) { + int bsize = bytestream2_get_byte(gb); + uint8_t *src; + int count; + + if (!bsize) + break; + + count = bytestream2_get_be16(gb); + while (count > 0) { + int mvx, mvy, a, b, c, mx, my; + int bsize_w, bsize_h; + + bsize_w = bsize_h = bsize; + if (bytestream2_get_bytes_left(gb) < 4) + return AVERROR_INVALIDDATA; + mvx = bytestream2_get_byte(gb) * bsize; + mvy = bytestream2_get_byte(gb) * bsize; + a = bytestream2_get_byte(gb); + b = bytestream2_get_byte(gb); + c = ((a & 0x3F) << 8) + b; + mx = mvx + (c & 0x7F) - 64; + my = mvy + (c >> 7) - 64; + + if (mvy < 0 || mvy >= h) + return AVERROR_INVALIDDATA; + + if (mvx < 0 || mvx >= w) + return AVERROR_INVALIDDATA; + + if (my < 0 || my >= h) + return AVERROR_INVALIDDATA; + + if (mx < 0 || mx >= w) + return AVERROR_INVALIDDATA; + + dst = frame->data[0] + mvx + l * mvy; + src = frame->data[0] + mx + l * my; + + bsize_w = FFMIN3(bsize_w, w - mvx, w - mx); + bsize_h = FFMIN3(bsize_h, h - mvy, h - my); + + if (mvy >= my && (mvy != my || mvx >= mx)) { + src += (bsize_h - 1) * l; + dst += (bsize_h - 1) * l; + for (int by = 0; by < bsize_h; by++) { + memmove(dst, src, bsize_w); + src -= l; + dst -= l; + } + } else { + for (int by = 0; by < bsize_h; by++) { + memmove(dst, src, bsize_w); + src += l; + dst += l; + } + } + + count--; + } + } + break; + case 6: + dst = frame->data[0]; + if (bytestream2_get_bytes_left(gb) < w * h) + return AVERROR_INVALIDDATA; + for (int y = 0; y < h; y++) { + bytestream2_get_bufferu(gb, dst, w); + dst += l; + } + break; + case 5: + dst = frame->data[0]; + for (int y = 0; y < h; y += 2) { + for (int x = 0; x < w; x += 2) { + int fill = bytestream2_get_byte(gb); + uint8_t *ddst = dst + x; + + fill = (fill << 8) | fill; + for (int by = 0; by < 2; by++) { + AV_WN16(ddst, fill); + + ddst += l; + } + } + + dst += 2 * l; + } + break; + case 3: + size = bytestream2_get_le16(gb); + if (size > 0) { + int x = bytestream2_get_byte(gb) * 4; + int y = bytestream2_get_byte(gb) * 4; + int count = bytestream2_get_byte(gb); + int fill = bytestream2_get_byte(gb); + + av_log(avctx, AV_LOG_DEBUG, "%d %d %d %d\n", x, y, count, fill); + for (int i = 0; i < count; i++) + ; + return AVERROR_PATCHWELCOME; + } + break; + case 2: + dst = frame->data[0]; + pos = 0; + dy = 0; + while (bytestream2_get_bytes_left(gb) > 0) { + int count = bytestream2_get_byteu(gb); + int skip = count & 0x3F; + + count = count >> 6; + if (skip == 0x3F) { + pos += 0x3E; + while (pos >= w) { + pos -= w; + dst += l; + dy++; + if (dy >= h) + return 0; + } + } else { + pos += skip; + while (pos >= w) { + pos -= w; + dst += l; + dy++; + if (dy >= h) + return 0; + } + while (count >= 0) { + int bits = bytestream2_get_byte(gb); + + for (int i = 0; i < 4; i++) { + switch (bits & 3) { + case 0: + break; + case 1: + if (dy < 1 && !pos) + return AVERROR_INVALIDDATA; + else + dst[pos] = pos ? dst[pos - 1] : dst[-l + w - 1]; + break; + case 2: + if (dy < 1) + return AVERROR_INVALIDDATA; + dst[pos] = dst[pos - l]; + break; + case 3: + dst[pos] = bytestream2_get_byte(gb); + break; + } + + pos++; + if (pos >= w) { + pos -= w; + dst += l; + dy++; + if (dy >= h) + return 0; + } + bits >>= 2; + } + count--; + } + } + } + break; + default: + return AVERROR_INVALIDDATA; + } + } + + return 0; +} + +static int decode_mad1_24(AVCodecContext *avctx, AVFrame *frame) +{ + ArgoContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + const int w = frame->width; + const int h = frame->height; + const int l = frame->linesize[0] / 4; + + while (bytestream2_get_bytes_left(gb) > 0) { + int osize, type, pos, dy, di, bcode, value, v14; + const uint8_t *bits; + uint32_t *dst; + + type = bytestream2_get_byte(gb); + if (type == 0xFF) + return 0; + + switch (type) { + case 8: + dst = (uint32_t *)frame->data[0]; + for (int y = 0; y + 12 <= h; y += 12) { + for (int x = 0; x + 12 <= w; x += 12) { + int fill = bytestream2_get_be24(gb); + uint32_t *dstp = dst + x; + + for (int by = 0; by < 12; by++) { + for (int bx = 0; bx < 12; bx++) + dstp[bx] = fill; + + dstp += l; + } + } + + dst += 12 * l; + } + break; + case 7: + while (bytestream2_get_bytes_left(gb) > 0) { + int bsize = bytestream2_get_byte(gb); + uint32_t *src; + int count; + + if (!bsize) + break; + + count = bytestream2_get_be16(gb); + while (count > 0) { + int mvx, mvy, a, b, c, mx, my; + int bsize_w, bsize_h; + + bsize_w = bsize_h = bsize; + if (bytestream2_get_bytes_left(gb) < 4) + return AVERROR_INVALIDDATA; + mvx = bytestream2_get_byte(gb) * bsize; + mvy = bytestream2_get_byte(gb) * bsize; + a = bytestream2_get_byte(gb); + b = bytestream2_get_byte(gb); + c = ((a & 0x3F) << 8) + b; + mx = mvx + (c & 0x7F) - 64; + my = mvy + (c >> 7) - 64; + + if (mvy < 0 || mvy >= h) + return AVERROR_INVALIDDATA; + + if (mvx < 0 || mvx >= w) + return AVERROR_INVALIDDATA; + + if (my < 0 || my >= h) + return AVERROR_INVALIDDATA; + + if (mx < 0 || mx >= w) + return AVERROR_INVALIDDATA; + + dst = (uint32_t *)frame->data[0] + mvx + l * mvy; + src = (uint32_t *)frame->data[0] + mx + l * my; + + bsize_w = FFMIN3(bsize_w, w - mvx, w - mx); + bsize_h = FFMIN3(bsize_h, h - mvy, h - my); + + if (mvy >= my && (mvy != my || mvx >= mx)) { + src += (bsize_h - 1) * l; + dst += (bsize_h - 1) * l; + for (int by = 0; by < bsize_h; by++) { + memmove(dst, src, bsize_w * 4); + src -= l; + dst -= l; + } + } else { + for (int by = 0; by < bsize_h; by++) { + memmove(dst, src, bsize_w * 4); + src += l; + dst += l; + } + } + + count--; + } + } + break; + case 12: + osize = ((h + 3) / 4) * ((w + 3) / 4) + 7; + bits = gb->buffer; + di = 0; + bcode = v14 = 0; + if (bytestream2_get_bytes_left(gb) < osize >> 3) + return AVERROR_INVALIDDATA; + bytestream2_skip(gb, osize >> 3); + for (int x = 0; x < w; x += 4) { + for (int y = 0; y < h; y += 4) { + int astate = 0; + + if (bits[di >> 3] & (1 << (di & 7))) { + int codes = bytestream2_get_byte(gb); + + for (int count = 0; count < 4; count++) { + uint32_t *src = (uint32_t *)frame->data[0]; + size_t src_size = l * (h - 1) + (w - 1); + int nv, v, code = codes & 3; + + pos = x; + dy = y + count; + dst = (uint32_t *)frame->data[0] + pos + dy * l; + if (code & 1) + bcode = bytestream2_get_byte(gb); + if (code == 3) { + for (int j = 0; j < 4; j++) { + switch (bcode & 3) { + case 0: + break; + case 1: + if (dy < 1 && !pos) + return AVERROR_INVALIDDATA; + dst[0] = dst[-1]; + break; + case 2: + if (dy < 1) + return AVERROR_INVALIDDATA; + dst[0] = dst[-l]; + break; + case 3: + if (astate) { + nv = value >> 4; + } else { + value = bytestream2_get_byte(gb); + nv = value & 0xF; + } + astate ^= 1; + dst[0] = src[av_clip(l * (dy + s->mv1[nv][1]) + pos + + s->mv1[nv][0], 0, src_size)]; + break; + } + + bcode >>= 2; + dst++; + pos++; + } + } else if (code) { + if (code == 1) + v14 = bcode; + else + bcode = v14; + for (int j = 0; j < 4; j++) { + switch (bcode & 3) { + case 0: + break; + case 1: + if (dy < 1 && !pos) + return AVERROR_INVALIDDATA; + dst[0] = dst[-1]; + break; + case 2: + if (dy < 1) + return AVERROR_INVALIDDATA; + dst[0] = dst[-l]; + break; + case 3: + v = bytestream2_get_byte(gb); + if (v < 128) { + dst[0] = src[av_clip(l * (dy + s->mv0[v][1]) + pos + + s->mv0[v][0], 0, src_size)]; + } else { + dst[0] = ((v & 0x7F) << 17) | bytestream2_get_be16(gb); + } + break; + } + + bcode >>= 2; + dst++; + pos++; + } + } + + codes >>= 2; + } + } + + di++; + } + } + break; + default: + return AVERROR_INVALIDDATA; + } + } + + return AVERROR_INVALIDDATA; +} + +static int decode_rle(AVCodecContext *avctx, AVFrame *frame) +{ + ArgoContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + const int w = frame->width; + const int h = frame->height; + const int l = frame->linesize[0]; + uint8_t *dst = frame->data[0]; + int pos = 0, y = 0; + + while (bytestream2_get_bytes_left(gb) > 0) { + int count = bytestream2_get_byte(gb); + int pixel = bytestream2_get_byte(gb); + + if (!count) { + pos += pixel; + while (pos >= w) { + pos -= w; + y++; + if (y >= h) + return 0; + } + } else { + while (count > 0) { + dst[pos + y * l] = pixel; + count--; + pos++; + if (pos >= w) { + pos = 0; + y++; + if (y >= h) + return 0; + } + } + } + } + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + ArgoContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + AVFrame *frame = s->frame; + uint32_t chunk; + int ret; + + bytestream2_init(gb, avpkt->data, avpkt->size); + + if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0) + return ret; + + chunk = bytestream2_get_be32(gb); + switch (chunk) { + case MKBETAG('P', 'A', 'L', '8'): + for (int y = 0; y < frame->height; y++) + memset(frame->data[0] + y * frame->linesize[0], 0, frame->width * s->bpp); + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) + memset(frame->data[1], 0, AVPALETTE_SIZE); + return decode_pal8(avctx, s->pal); + case MKBETAG('M', 'A', 'D', '1'): + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) + ret = decode_mad1(avctx, frame); + else + ret = decode_mad1_24(avctx, frame); + break; + case MKBETAG('A', 'V', 'C', 'F'): + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + s->key = 1; + ret = decode_avcf(avctx, frame); + break; + } + case MKBETAG('A', 'L', 'C', 'D'): + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + s->key = 0; + ret = decode_alcd(avctx, frame); + break; + } + case MKBETAG('R', 'L', 'E', 'F'): + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + s->key = 1; + ret = decode_rle(avctx, frame); + break; + } + case MKBETAG('R', 'L', 'E', 'D'): + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + s->key = 0; + ret = decode_rle(avctx, frame); + break; + } + default: + av_log(avctx, AV_LOG_DEBUG, "unknown chunk 0x%X\n", chunk); + break; + } + + if (ret < 0) + return ret; + + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) + memcpy(frame->data[1], s->pal, AVPALETTE_SIZE); + + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; + + frame->pict_type = s->key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + frame->key_frame = s->key; + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + ArgoContext *s = avctx->priv_data; + + switch (avctx->bits_per_raw_sample) { + case 8: s->bpp = 1; + avctx->pix_fmt = AV_PIX_FMT_PAL8; break; + case 24: s->bpp = 4; + avctx->pix_fmt = AV_PIX_FMT_BGR0; break; + default: avpriv_request_sample(s, "depth == %u", avctx->bits_per_raw_sample); + return AVERROR_PATCHWELCOME; + } + + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + + for (int n = 0, i = -4; i < 4; i++) { + for (int j = -14; j < 2; j++) { + s->mv0[n][0] = j; + s->mv0[n++][1] = i; + } + } + + for (int n = 0, i = -5; i <= 1; i += 2) { + int j = -5; + + while (j <= 1) { + s->mv1[n][0] = j; + s->mv1[n++][1] = i; + j += 2; + } + } + + return 0; +} + +static void decode_flush(AVCodecContext *avctx) +{ + ArgoContext *s = avctx->priv_data; + + av_frame_unref(s->frame); +} + +static av_cold int decode_close(AVCodecContext *avctx) +{ + ArgoContext *s = avctx->priv_data; + + av_frame_free(&s->frame); + + return 0; +} + +AVCodec ff_argo_decoder = { + .name = "argo", + .long_name = NULL_IF_CONFIG_SMALL("Argonaut Games Video"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ARGO, + .priv_data_size = sizeof(ArgoContext), + .init = decode_init, + .decode = decode_frame, + .flush = decode_flush, + .close = decode_close, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +}; diff -Nru ffmpeg-4.2.2/libavcodec/arm/ac3dsp_init_arm.c ffmpeg-4.4/libavcodec/arm/ac3dsp_init_arm.c --- ffmpeg-4.2.2/libavcodec/arm/ac3dsp_init_arm.c 2016-03-29 02:25:10.000000000 +0000 +++ ffmpeg-4.4/libavcodec/arm/ac3dsp_init_arm.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,13 +26,8 @@ #include "config.h" void ff_ac3_exponent_min_neon(uint8_t *exp, int num_reuse_blocks, int nb_coefs); -int ff_ac3_max_msb_abs_int16_neon(const int16_t *src, int len); -void ff_ac3_lshift_int16_neon(int16_t *src, unsigned len, unsigned shift); -void ff_ac3_rshift_int32_neon(int32_t *src, unsigned len, unsigned shift); void ff_float_to_fixed24_neon(int32_t *dst, const float *src, unsigned int len); void ff_ac3_extract_exponents_neon(uint8_t *exp, int32_t *coef, int nb_coefs); -void ff_apply_window_int16_neon(int16_t *dst, const int16_t *src, - const int16_t *window, unsigned n); void ff_ac3_sum_square_butterfly_int32_neon(int64_t sum[4], const int32_t *coef0, const int32_t *coef1, @@ -61,12 +56,8 @@ if (have_neon(cpu_flags)) { c->ac3_exponent_min = ff_ac3_exponent_min_neon; - c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_neon; - c->ac3_lshift_int16 = ff_ac3_lshift_int16_neon; - c->ac3_rshift_int32 = ff_ac3_rshift_int32_neon; c->float_to_fixed24 = ff_float_to_fixed24_neon; c->extract_exponents = ff_ac3_extract_exponents_neon; - c->apply_window_int16 = ff_apply_window_int16_neon; c->sum_square_butterfly_int32 = ff_ac3_sum_square_butterfly_int32_neon; c->sum_square_butterfly_float = ff_ac3_sum_square_butterfly_float_neon; } diff -Nru ffmpeg-4.2.2/libavcodec/arm/fft_fixed_init_arm.c ffmpeg-4.4/libavcodec/arm/fft_fixed_init_arm.c --- ffmpeg-4.2.2/libavcodec/arm/fft_fixed_init_arm.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/arm/fft_fixed_init_arm.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2009 Mans Rullgard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/attributes.h" -#include "libavutil/cpu.h" -#include "libavutil/arm/cpu.h" - -#define FFT_FLOAT 0 -#include "libavcodec/fft.h" - -void ff_fft_fixed_calc_neon(FFTContext *s, FFTComplex *z); -void ff_mdct_fixed_calc_neon(FFTContext *s, FFTSample *o, const FFTSample *i); -void ff_mdct_fixed_calcw_neon(FFTContext *s, FFTDouble *o, const FFTSample *i); - -av_cold void ff_fft_fixed_init_arm(FFTContext *s) -{ - int cpu_flags = av_get_cpu_flags(); - - if (have_neon(cpu_flags)) { - s->fft_permutation = FF_FFT_PERM_SWAP_LSBS; -#if CONFIG_FFT - s->fft_calc = ff_fft_fixed_calc_neon; -#endif - -#if CONFIG_MDCT - if (!s->inverse && s->nbits >= 3) { - s->mdct_permutation = FF_MDCT_PERM_INTERLEAVE; - s->mdct_calc = ff_mdct_fixed_calc_neon; - s->mdct_calcw = ff_mdct_fixed_calcw_neon; - } -#endif - } -} diff -Nru ffmpeg-4.2.2/libavcodec/arm/fft_fixed_neon.S ffmpeg-4.4/libavcodec/arm/fft_fixed_neon.S --- ffmpeg-4.2.2/libavcodec/arm/fft_fixed_neon.S 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/arm/fft_fixed_neon.S 1970-01-01 00:00:00.000000000 +0000 @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2011 Mans Rullgard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/arm/asm.S" - -.macro bflies d0, d1, r0, r1 - vrev64.32 \r0, \d1 @ t5, t6, t1, t2 - vhsub.s16 \r1, \d1, \r0 @ t1-t5, t2-t6, t5-t1, t6-t2 - vhadd.s16 \r0, \d1, \r0 @ t1+t5, t2+t6, t5+t1, t6+t2 - vext.16 \r1, \r1, \r1, #1 @ t2-t6, t5-t1, t6-t2, t1-t5 - vtrn.32 \r0, \r1 @ t1+t5, t2+t6, t2-t6, t5-t1 - @ t5, t6, t4, t3 - vhsub.s16 \d1, \d0, \r0 - vhadd.s16 \d0, \d0, \r0 -.endm - -.macro transform01 q0, q1, d3, c0, c1, r0, w0, w1 - vrev32.16 \r0, \d3 - vmull.s16 \w0, \d3, \c0 - vmlal.s16 \w0, \r0, \c1 - vshrn.s32 \d3, \w0, #15 - bflies \q0, \q1, \w0, \w1 -.endm - -.macro transform2 d0, d1, d2, d3, q0, q1, c0, c1, c2, c3, \ - r0, r1, w0, w1 - vrev32.16 \r0, \d1 - vrev32.16 \r1, \d3 - vmull.s16 \w0, \d1, \c0 - vmlal.s16 \w0, \r0, \c1 - vmull.s16 \w1, \d3, \c2 - vmlal.s16 \w1, \r1, \c3 - vshrn.s32 \d1, \w0, #15 - vshrn.s32 \d3, \w1, #15 - bflies \q0, \q1, \w0, \w1 -.endm - -.macro fft4 d0, d1, r0, r1 - vhsub.s16 \r0, \d0, \d1 @ t3, t4, t8, t7 - vhsub.s16 \r1, \d1, \d0 - vhadd.s16 \d0, \d0, \d1 @ t1, t2, t6, t5 - vmov.i64 \d1, #0xffff00000000 - vbit \r0, \r1, \d1 - vrev64.16 \r1, \r0 @ t7, t8, t4, t3 - vtrn.32 \r0, \r1 @ t3, t4, t7, t8 - vtrn.32 \d0, \r0 @ t1, t2, t3, t4, t6, t5, t8, t7 - vhsub.s16 \d1, \d0, \r0 @ r2, i2, r3, i1 - vhadd.s16 \d0, \d0, \r0 @ r0, i0, r1, i3 -.endm - -.macro fft8 d0, d1, d2, d3, q0, q1, c0, c1, r0, r1, w0, w1 - fft4 \d0, \d1, \r0, \r1 - vtrn.32 \d0, \d1 @ z0, z2, z1, z3 - vhadd.s16 \r0, \d2, \d3 @ t1, t2, t3, t4 - vhsub.s16 \d3, \d2, \d3 @ z5, z7 - vmov \d2, \r0 - transform01 \q0, \q1, \d3, \c0, \c1, \r0, \w0, \w1 -.endm - -function fft4_neon - vld1.16 {d0-d1}, [r0] - fft4 d0, d1, d2, d3 - vst1.16 {d0-d1}, [r0] - bx lr -endfunc - -function fft8_neon - vld1.16 {d0-d3}, [r0,:128] - movrel r1, coefs - vld1.16 {d30}, [r1,:64] - vdup.16 d31, d30[0] - fft8 d0, d1, d2, d3, q0, q1, d31, d30, d20, d21, q8, q9 - vtrn.32 d0, d1 - vtrn.32 d2, d3 - vst1.16 {d0-d3}, [r0,:128] - bx lr -endfunc - -function fft16_neon - vld1.16 {d0-d3}, [r0,:128]! - vld1.16 {d4-d7}, [r0,:128] - movrel r1, coefs - sub r0, r0, #32 - vld1.16 {d28-d31},[r1,:128] - vdup.16 d31, d28[0] - fft8 d0, d1, d2, d3, q0, q1, d31, d28, d20, d21, q8, q9 - vswp d5, d6 - fft4 q2, q3, q8, q9 - vswp d5, d6 - vtrn.32 q0, q1 @ z0, z4, z2, z6, z1, z5, z3, z7 - vtrn.32 q2, q3 @ z8, z12,z10,z14,z9, z13,z11,z15 - vswp d1, d2 - vdup.16 d31, d28[0] - transform01 q0, q2, d5, d31, d28, d20, q8, q9 - vdup.16 d26, d29[0] - vdup.16 d27, d30[0] - transform2 d2, d6, d3, d7, q1, q3, d26, d30, d27, d29, \ - d20, d21, q8, q9 - vtrn.32 q0, q1 - vtrn.32 q2, q3 - vst1.16 {d0-d3}, [r0,:128]! - vst1.16 {d4-d7}, [r0,:128] - bx lr -endfunc - -function fft_pass_neon - push {r4,lr} - movrel lr, coefs + 24 - vld1.16 {d30}, [lr,:64] - lsl r12, r2, #3 - vmov d31, d30 - add r3, r1, r2, lsl #2 - mov lr, #-8 - sub r3, r3, #2 - mov r4, r0 - vld1.16 {d27[]}, [r3,:16] - sub r3, r3, #6 - vld1.16 {q0}, [r4,:128], r12 - vld1.16 {q1}, [r4,:128], r12 - vld1.16 {q2}, [r4,:128], r12 - vld1.16 {q3}, [r4,:128], r12 - vld1.16 {d28}, [r1,:64]! - vld1.16 {d29}, [r3,:64], lr - vswp d1, d2 - vswp d5, d6 - vtrn.32 d0, d1 - vtrn.32 d4, d5 - vdup.16 d25, d28[1] - vmul.s16 d27, d27, d31 - transform01 q0, q2, d5, d25, d27, d20, q8, q9 - b 2f -1: - mov r4, r0 - vdup.16 d26, d29[0] - vld1.16 {q0}, [r4,:128], r12 - vld1.16 {q1}, [r4,:128], r12 - vld1.16 {q2}, [r4,:128], r12 - vld1.16 {q3}, [r4,:128], r12 - vld1.16 {d28}, [r1,:64]! - vld1.16 {d29}, [r3,:64], lr - vswp d1, d2 - vswp d5, d6 - vtrn.32 d0, d1 - vtrn.32 d4, d5 - vdup.16 d24, d28[0] - vdup.16 d25, d28[1] - vdup.16 d27, d29[3] - vmul.s16 q13, q13, q15 - transform2 d0, d4, d1, d5, q0, q2, d24, d26, d25, d27, \ - d16, d17, q9, q10 -2: - vtrn.32 d2, d3 - vtrn.32 d6, d7 - vdup.16 d24, d28[2] - vdup.16 d26, d29[2] - vdup.16 d25, d28[3] - vdup.16 d27, d29[1] - vmul.s16 q13, q13, q15 - transform2 d2, d6, d3, d7, q1, q3, d24, d26, d25, d27, \ - d16, d17, q9, q10 - vtrn.32 d0, d1 - vtrn.32 d2, d3 - vtrn.32 d4, d5 - vtrn.32 d6, d7 - vswp d1, d2 - vswp d5, d6 - mov r4, r0 - vst1.16 {q0}, [r4,:128], r12 - vst1.16 {q1}, [r4,:128], r12 - vst1.16 {q2}, [r4,:128], r12 - vst1.16 {q3}, [r4,:128], r12 - add r0, r0, #16 - subs r2, r2, #2 - bgt 1b - pop {r4,pc} -endfunc - -#define F_SQRT1_2 23170 -#define F_COS_16_1 30274 -#define F_COS_16_3 12540 - -const coefs, align=4 - .short F_SQRT1_2, -F_SQRT1_2, -F_SQRT1_2, F_SQRT1_2 - .short F_COS_16_1,-F_COS_16_1,-F_COS_16_1, F_COS_16_1 - .short F_COS_16_3,-F_COS_16_3,-F_COS_16_3, F_COS_16_3 - .short 1, -1, -1, 1 -endconst - -.macro def_fft n, n2, n4 -function fft\n\()_neon - push {r4, lr} - mov r4, r0 - bl fft\n2\()_neon - add r0, r4, #\n4*2*4 - bl fft\n4\()_neon - add r0, r4, #\n4*3*4 - bl fft\n4\()_neon - mov r0, r4 - pop {r4, lr} - movrelx r1, X(ff_cos_\n\()_fixed) - mov r2, #\n4/2 - b fft_pass_neon -endfunc -.endm - - def_fft 32, 16, 8 - def_fft 64, 32, 16 - def_fft 128, 64, 32 - def_fft 256, 128, 64 - def_fft 512, 256, 128 - def_fft 1024, 512, 256 - def_fft 2048, 1024, 512 - def_fft 4096, 2048, 1024 - def_fft 8192, 4096, 2048 - def_fft 16384, 8192, 4096 - def_fft 32768, 16384, 8192 - def_fft 65536, 32768, 16384 - -function ff_fft_fixed_calc_neon, export=1 - ldr r2, [r0] - sub r2, r2, #2 - movrel r3, fft_fixed_tab_neon - ldr r3, [r3, r2, lsl #2] - mov r0, r1 - bx r3 -endfunc - -const fft_fixed_tab_neon, relocate=1 - .word fft4_neon - .word fft8_neon - .word fft16_neon - .word fft32_neon - .word fft64_neon - .word fft128_neon - .word fft256_neon - .word fft512_neon - .word fft1024_neon - .word fft2048_neon - .word fft4096_neon - .word fft8192_neon - .word fft16384_neon - .word fft32768_neon - .word fft65536_neon -endconst diff -Nru ffmpeg-4.2.2/libavcodec/arm/hevcdsp_sao_neon.S ffmpeg-4.4/libavcodec/arm/hevcdsp_sao_neon.S --- ffmpeg-4.2.2/libavcodec/arm/hevcdsp_sao_neon.S 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/arm/hevcdsp_sao_neon.S 2020-07-11 10:39:30.000000000 +0000 @@ -35,10 +35,10 @@ vmov.u16 q15, #1 vmov.u8 q14, #32 0: pld [r1] - vld1.8 {d16}, [r1], r3 cmp r5, #4 beq 4f 8: subs r4, #1 + vld1.8 {d16}, [r1], r3 vshr.u8 d17, d16, #3 // index = [src>>3] vshll.u8 q9, d17, #1 // lowIndex = 2*index vadd.u16 q11, q9, q15 // highIndex = (2*index+1) << 8 @@ -54,7 +54,6 @@ vaddw.u8 q13, q12, d16 vqmovun.s16 d8, q13 vst1.8 d8, [r0], r2 - vld1.8 {d16}, [r1], r3 bne 8b subs r5, #8 beq 99f @@ -65,6 +64,7 @@ mov r1, r7 b 0b 4: subs r4, #1 + vld1.32 {d16[0]}, [r1], r3 vshr.u8 d17, d16, #3 // src>>3 vshll.u8 q9, d17, #1 // lowIndex = 2*index vadd.u16 q11, q9, q15 // highIndex = (2*index+1) << 8 @@ -80,7 +80,6 @@ vaddw.u8 q13, q12, d16 vqmovun.s16 d14, q13 vst1.32 d14[0], [r0], r2 - vld1.32 {d16[0]}, [r1], r3 bne 4b b 99f 99: @@ -110,12 +109,12 @@ mov r11, r1 add r11, r9 // src[x + b_stride] pld [r1] - vld1.8 {d16}, [r1], r3 // src[x] 8x8bit - vld1.8 {d17}, [r10], r3 // src[x + a_stride] - vld1.8 {d18}, [r11], r3 // src[x + b_stride] cmp r5, #4 beq 4f 8: subs r4, #1 + vld1.8 {d16}, [r1], r3 // src[x] 8x8bit + vld1.8 {d17}, [r10], r3 // src[x + a_stride] + vld1.8 {d18}, [r11], r3 // src[x + b_stride] vcgt.u8 d8, d16, d17 vshr.u8 d9, d8, #7 vclt.u8 d8, d16, d17 @@ -136,9 +135,6 @@ vaddw.u8 q12, q11, d16 vqmovun.s16 d26, q12 vst1.8 d26, [r0], r2 - vld1.8 {d16}, [r1], r3 // src[x] 8x8bit - vld1.8 {d17}, [r10], r3 // src[x + a_stride] - vld1.8 {d18}, [r11], r3 // src[x + b_stride] bne 8b subs r5, #8 beq 99f @@ -149,6 +145,9 @@ mov r1, r7 b 0b 4: subs r4, #1 + vld1.32 {d16[0]}, [r1], r3 + vld1.32 {d17[0]}, [r10], r3 // src[x + a_stride] + vld1.32 {d18[0]}, [r11], r3 // src[x + b_stride] vcgt.u8 d8, d16, d17 vshr.u8 d9, d8, #7 vclt.u8 d8, d16, d17 @@ -169,9 +168,6 @@ vaddw.u8 q12, q11, d16 vqmovun.s16 d26, q12 vst1.32 d26[0], [r0], r2 - vld1.32 {d16[0]}, [r1], r3 - vld1.32 {d17[0]}, [r10], r3 // src[x + a_stride] - vld1.32 {d18[0]}, [r11], r3 // src[x + b_stride] bne 4b b 99f 99: diff -Nru ffmpeg-4.2.2/libavcodec/arm/Makefile ffmpeg-4.4/libavcodec/arm/Makefile --- ffmpeg-4.2.2/libavcodec/arm/Makefile 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/arm/Makefile 2021-04-08 21:28:39.000000000 +0000 @@ -5,8 +5,7 @@ arm/ac3dsp_arm.o OBJS-$(CONFIG_AUDIODSP) += arm/audiodsp_init_arm.o OBJS-$(CONFIG_BLOCKDSP) += arm/blockdsp_init_arm.o -OBJS-$(CONFIG_FFT) += arm/fft_init_arm.o \ - arm/fft_fixed_init_arm.o +OBJS-$(CONFIG_FFT) += arm/fft_init_arm.o OBJS-$(CONFIG_FLACDSP) += arm/flacdsp_init_arm.o \ arm/flacdsp_arm.o OBJS-$(CONFIG_FMTCONVERT) += arm/fmtconvert_init_arm.o @@ -43,6 +42,7 @@ OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_init_arm.o OBJS-$(CONFIG_RV40_DECODER) += arm/rv40dsp_init_arm.o OBJS-$(CONFIG_SBC_ENCODER) += arm/sbcdsp_init_arm.o +OBJS-$(CONFIG_TRUEHD_DECODER) += arm/mlpdsp_init_arm.o OBJS-$(CONFIG_VORBIS_DECODER) += arm/vorbisdsp_init_arm.o OBJS-$(CONFIG_VP6_DECODER) += arm/vp6dsp_init_arm.o OBJS-$(CONFIG_VP9_DECODER) += arm/vp9dsp_init_10bpp_arm.o \ @@ -61,6 +61,7 @@ # decoders/encoders ARMV5TE-OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_armv5te.o +ARMV5TE-OBJS-$(CONFIG_TRUEHD_DECODER) += arm/mlpdsp_armv5te.o # ARMv6 optimizations @@ -83,6 +84,7 @@ # decoders/encoders ARMV6-OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_armv6.o ARMV6-OBJS-$(CONFIG_SBC_ENCODER) += arm/sbcdsp_armv6.o +ARMV6-OBJS-$(CONFIG_TRUEHD_DECODER) += arm/mlpdsp_armv6.o # VFP optimizations @@ -105,8 +107,7 @@ arm/int_neon.o NEON-OBJS-$(CONFIG_BLOCKDSP) += arm/blockdsp_init_neon.o \ arm/blockdsp_neon.o -NEON-OBJS-$(CONFIG_FFT) += arm/fft_neon.o \ - arm/fft_fixed_neon.o +NEON-OBJS-$(CONFIG_FFT) += arm/fft_neon.o NEON-OBJS-$(CONFIG_FMTCONVERT) += arm/fmtconvert_neon.o NEON-OBJS-$(CONFIG_G722DSP) += arm/g722dsp_neon.o NEON-OBJS-$(CONFIG_H264CHROMA) += arm/h264cmc_neon.o @@ -120,9 +121,9 @@ NEON-OBJS-$(CONFIG_IDCTDSP) += arm/idctdsp_init_neon.o \ arm/idctdsp_neon.o \ arm/simple_idct_neon.o -NEON-OBJS-$(CONFIG_MDCT) += arm/mdct_neon.o \ - arm/mdct_fixed_neon.o +NEON-OBJS-$(CONFIG_MDCT) += arm/mdct_neon.o NEON-OBJS-$(CONFIG_MPEGVIDEO) += arm/mpegvideo_neon.o +NEON-OBJS-$(CONFIG_PIXBLOCKDSP) += arm/pixblockdsp_neon.o NEON-OBJS-$(CONFIG_RDFT) += arm/rdft_neon.o NEON-OBJS-$(CONFIG_VC1DSP) += arm/vc1dsp_init_neon.o \ arm/vc1dsp_neon.o diff -Nru ffmpeg-4.2.2/libavcodec/arm/mdct_fixed_neon.S ffmpeg-4.4/libavcodec/arm/mdct_fixed_neon.S --- ffmpeg-4.2.2/libavcodec/arm/mdct_fixed_neon.S 2016-03-29 02:25:11.000000000 +0000 +++ ffmpeg-4.4/libavcodec/arm/mdct_fixed_neon.S 1970-01-01 00:00:00.000000000 +0000 @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2011 Mans Rullgard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/arm/asm.S" - -.macro prerot dst, rt - lsr r3, r6, #2 @ n4 - add \rt, r4, r6, lsr #1 @ revtab + n4 - add r9, r3, r3, lsl #1 @ n3 - add r8, r7, r6 @ tcos + n4 - add r3, r2, r6, lsr #1 @ in + n4 - add r9, r2, r9, lsl #1 @ in + n3 - sub r8, r8, #16 - sub r10, r3, #16 - sub r11, r9, #16 - mov r12, #-16 -1: - vld2.16 {d0,d1}, [r9, :128]! - vld2.16 {d2,d3}, [r11,:128], r12 - vld2.16 {d4,d5}, [r3, :128]! - vld2.16 {d6,d7}, [r10,:128], r12 - vld2.16 {d16,d17},[r7, :128]! @ cos, sin - vld2.16 {d18,d19},[r8, :128], r12 - vrev64.16 q1, q1 - vrev64.16 q3, q3 - vrev64.16 q9, q9 - vneg.s16 d0, d0 - vneg.s16 d2, d2 - vneg.s16 d16, d16 - vneg.s16 d18, d18 - vhsub.s16 d0, d0, d3 @ re - vhsub.s16 d4, d7, d4 @ im - vhsub.s16 d6, d6, d5 - vhsub.s16 d2, d2, d1 - vmull.s16 q10, d0, d16 - vmlsl.s16 q10, d4, d17 - vmull.s16 q11, d0, d17 - vmlal.s16 q11, d4, d16 - vmull.s16 q12, d6, d18 - vmlsl.s16 q12, d2, d19 - vmull.s16 q13, d6, d19 - vmlal.s16 q13, d2, d18 - vshrn.s32 d0, q10, #15 - vshrn.s32 d1, q11, #15 - vshrn.s32 d2, q12, #15 - vshrn.s32 d3, q13, #15 - vzip.16 d0, d1 - vzip.16 d2, d3 - ldrh lr, [r4], #2 - ldrh r2, [\rt, #-2]! - add lr, \dst, lr, lsl #2 - add r2, \dst, r2, lsl #2 - vst1.32 {d0[0]}, [lr,:32] - vst1.32 {d2[0]}, [r2,:32] - ldrh lr, [r4], #2 - ldrh r2, [\rt, #-2]! - add lr, \dst, lr, lsl #2 - add r2, \dst, r2, lsl #2 - vst1.32 {d0[1]}, [lr,:32] - vst1.32 {d2[1]}, [r2,:32] - ldrh lr, [r4], #2 - ldrh r2, [\rt, #-2]! - add lr, \dst, lr, lsl #2 - add r2, \dst, r2, lsl #2 - vst1.32 {d1[0]}, [lr,:32] - vst1.32 {d3[0]}, [r2,:32] - ldrh lr, [r4], #2 - ldrh r2, [\rt, #-2]! - add lr, \dst, lr, lsl #2 - add r2, \dst, r2, lsl #2 - vst1.32 {d1[1]}, [lr,:32] - vst1.32 {d3[1]}, [r2,:32] - subs r6, r6, #32 - bgt 1b -.endm - -function ff_mdct_fixed_calc_neon, export=1 - push {r1,r4-r11,lr} - - ldr r4, [r0, #8] @ revtab - ldr r6, [r0, #16] @ mdct_size; n - ldr r7, [r0, #24] @ tcos - - prerot r1, r5 - - mov r4, r0 - bl X(ff_fft_fixed_calc_neon) - - pop {r5} - mov r12, #-16 - ldr r6, [r4, #16] @ mdct_size; n - ldr r7, [r4, #24] @ tcos - add r5, r5, r6, lsr #1 - add r7, r7, r6, lsr #1 - sub r1, r5, #16 - sub r2, r7, #16 -1: - vld2.16 {d4,d5}, [r7,:128]! - vld2.16 {d6,d7}, [r2,:128], r12 - vld2.16 {d0,d1}, [r5,:128] - vld2.16 {d2,d3}, [r1,:128] - vrev64.16 q3, q3 - vrev64.16 q1, q1 - vneg.s16 q3, q3 - vneg.s16 q2, q2 - vmull.s16 q11, d2, d6 - vmlal.s16 q11, d3, d7 - vmull.s16 q8, d0, d5 - vmlsl.s16 q8, d1, d4 - vmull.s16 q9, d0, d4 - vmlal.s16 q9, d1, d5 - vmull.s16 q10, d2, d7 - vmlsl.s16 q10, d3, d6 - vshrn.s32 d0, q11, #15 - vshrn.s32 d1, q8, #15 - vshrn.s32 d2, q9, #15 - vshrn.s32 d3, q10, #15 - vrev64.16 q0, q0 - vst2.16 {d2,d3}, [r5,:128]! - vst2.16 {d0,d1}, [r1,:128], r12 - subs r6, r6, #32 - bgt 1b - - pop {r4-r11,pc} -endfunc - -function ff_mdct_fixed_calcw_neon, export=1 - push {r1,r4-r11,lr} - - ldrd r4, r5, [r0, #8] @ revtab, tmp_buf - ldr r6, [r0, #16] @ mdct_size; n - ldr r7, [r0, #24] @ tcos - - prerot r5, r1 - - mov r4, r0 - mov r1, r5 - bl X(ff_fft_fixed_calc_neon) - - pop {r7} - mov r12, #-16 - ldr r6, [r4, #16] @ mdct_size; n - ldr r9, [r4, #24] @ tcos - add r5, r5, r6, lsr #1 - add r7, r7, r6 - add r9, r9, r6, lsr #1 - sub r3, r5, #16 - sub r1, r7, #16 - sub r2, r9, #16 -1: - vld2.16 {d4,d5}, [r9,:128]! - vld2.16 {d6,d7}, [r2,:128], r12 - vld2.16 {d0,d1}, [r5,:128]! - vld2.16 {d2,d3}, [r3,:128], r12 - vrev64.16 q3, q3 - vrev64.16 q1, q1 - vneg.s16 q3, q3 - vneg.s16 q2, q2 - vmull.s16 q8, d2, d6 - vmlal.s16 q8, d3, d7 - vmull.s16 q9, d0, d5 - vmlsl.s16 q9, d1, d4 - vmull.s16 q10, d0, d4 - vmlal.s16 q10, d1, d5 - vmull.s16 q11, d2, d7 - vmlsl.s16 q11, d3, d6 - vrev64.32 q8, q8 - vrev64.32 q9, q9 - vst2.32 {q10,q11},[r7,:128]! - vst2.32 {d16,d18},[r1,:128], r12 - vst2.32 {d17,d19},[r1,:128], r12 - subs r6, r6, #32 - bgt 1b - - pop {r4-r11,pc} -endfunc diff -Nru ffmpeg-4.2.2/libavcodec/arm/neontest.c ffmpeg-4.4/libavcodec/arm/neontest.c --- ffmpeg-4.2.2/libavcodec/arm/neontest.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/arm/neontest.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,7 @@ testneonclobbers(avcodec_open2, avctx, codec, options); } +#if FF_API_OLD_ENCDEC wrap(avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, @@ -47,15 +48,6 @@ got_picture_ptr, avpkt); } -wrap(avcodec_decode_subtitle2(AVCodecContext *avctx, - AVSubtitle *sub, - int *got_sub_ptr, - AVPacket *avpkt)) -{ - testneonclobbers(avcodec_decode_subtitle2, avctx, sub, - got_sub_ptr, avpkt); -} - wrap(avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, @@ -65,6 +57,22 @@ got_packet_ptr); } +wrap(avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr)) +{ + testneonclobbers(avcodec_encode_video2, avctx, avpkt, frame, got_packet_ptr); +} +#endif + +wrap(avcodec_decode_subtitle2(AVCodecContext *avctx, + AVSubtitle *sub, + int *got_sub_ptr, + AVPacket *avpkt)) +{ + testneonclobbers(avcodec_decode_subtitle2, avctx, sub, + got_sub_ptr, avpkt); +} + wrap(avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, const AVSubtitle *sub)) @@ -72,12 +80,6 @@ testneonclobbers(avcodec_encode_subtitle, avctx, buf, buf_size, sub); } -wrap(avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, - const AVFrame *frame, int *got_packet_ptr)) -{ - testneonclobbers(avcodec_encode_video2, avctx, avpkt, frame, got_packet_ptr); -} - wrap(avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)) { testneonclobbers(avcodec_send_packet, avctx, avpkt); diff -Nru ffmpeg-4.2.2/libavcodec/arm/pixblockdsp_init_arm.c ffmpeg-4.4/libavcodec/arm/pixblockdsp_init_arm.c --- ffmpeg-4.2.2/libavcodec/arm/pixblockdsp_init_arm.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/arm/pixblockdsp_init_arm.c 2020-07-11 10:39:30.000000000 +0000 @@ -29,6 +29,15 @@ void ff_diff_pixels_armv6(int16_t *block, const uint8_t *s1, const uint8_t *s2, ptrdiff_t stride); +void ff_get_pixels_neon(int16_t *block, const uint8_t *pixels, + ptrdiff_t stride); +void ff_get_pixels_unaligned_neon(int16_t *block, const uint8_t *pixels, + ptrdiff_t stride); +void ff_diff_pixels_neon(int16_t *block, const uint8_t *s1, + const uint8_t *s2, ptrdiff_t stride); +void ff_diff_pixels_unaligned_neon(int16_t *block, const uint8_t *s1, + const uint8_t *s2, ptrdiff_t stride); + av_cold void ff_pixblockdsp_init_arm(PixblockDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth) @@ -40,4 +49,13 @@ c->get_pixels = ff_get_pixels_armv6; c->diff_pixels = ff_diff_pixels_armv6; } + + if (have_neon(cpu_flags)) { + if (!high_bit_depth) { + c->get_pixels_unaligned = ff_get_pixels_unaligned_neon; + c->get_pixels = ff_get_pixels_neon; + } + c->diff_pixels_unaligned = ff_diff_pixels_unaligned_neon; + c->diff_pixels = ff_diff_pixels_neon; + } } diff -Nru ffmpeg-4.2.2/libavcodec/arm/pixblockdsp_neon.S ffmpeg-4.4/libavcodec/arm/pixblockdsp_neon.S --- ffmpeg-4.2.2/libavcodec/arm/pixblockdsp_neon.S 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/arm/pixblockdsp_neon.S 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020 Martin Storsjo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +.macro vld1_8 dst, src, incr, aligned +.if \aligned + vld1.8 {\dst}, [\src, :64], \incr +.else + vld1.8 {\dst}, [\src], \incr +.endif +.endm + +.macro get_pixels suffix, aligned +function ff_get_pixels\suffix\()_neon, export=1 + mov r3, #8 +1: + vld1_8 d0, r1, r2, \aligned + subs r3, r3, #2 + vld1_8 d2, r1, r2, \aligned + vmovl.u8 q0, d0 + vmovl.u8 q1, d2 + vst1.16 {q0, q1}, [r0, :128]! + bgt 1b + + bx lr +endfunc +.endm + +get_pixels , aligned=1 +get_pixels _unaligned, aligned=0 + +.macro diff_pixels suffix, aligned=0 +function ff_diff_pixels\suffix\()_neon, export=1 + mov r12, #8 +1: + vld1_8 d0, r1, r3, \aligned + vld1_8 d1, r2, r3, \aligned + subs r12, r12, #2 + vld1_8 d2, r1, r3, \aligned + vsubl.u8 q0, d0, d1 + vld1_8 d3, r2, r3, \aligned + vsubl.u8 q1, d2, d3 + vst1.16 {q0, q1}, [r0]! + bgt 1b + + bx lr +endfunc +.endm + +diff_pixels , aligned=1 +diff_pixels _unaligned, aligned=0 diff -Nru ffmpeg-4.2.2/libavcodec/arm/sbcdsp_init_arm.c ffmpeg-4.4/libavcodec/arm/sbcdsp_init_arm.c --- ffmpeg-4.2.2/libavcodec/arm/sbcdsp_init_arm.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/arm/sbcdsp_init_arm.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,7 @@ */ #include "libavutil/cpu.h" +#include "libavutil/mem_internal.h" #include "libavutil/arm/cpu.h" #include "libavcodec/sbcdsp.h" diff -Nru ffmpeg-4.2.2/libavcodec/arm/vp9dsp_init_16bpp_arm_template.c ffmpeg-4.4/libavcodec/arm/vp9dsp_init_16bpp_arm_template.c --- ffmpeg-4.2.2/libavcodec/arm/vp9dsp_init_16bpp_arm_template.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/arm/vp9dsp_init_16bpp_arm_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "libavutil/attributes.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/arm/cpu.h" #include "vp9dsp_init.h" diff -Nru ffmpeg-4.2.2/libavcodec/arm/vp9dsp_init_arm.c ffmpeg-4.4/libavcodec/arm/vp9dsp_init_arm.c --- ffmpeg-4.2.2/libavcodec/arm/vp9dsp_init_arm.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/arm/vp9dsp_init_arm.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "libavutil/attributes.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/arm/cpu.h" #include "libavcodec/vp9dsp.h" #include "vp9dsp_init.h" diff -Nru ffmpeg-4.2.2/libavcodec/ass.c ffmpeg-4.4/libavcodec/ass.c --- ffmpeg-4.2.2/libavcodec/ass.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ass.c 2020-07-11 10:39:30.000000000 +0000 @@ -26,11 +26,13 @@ #include "libavutil/bprint.h" #include "libavutil/common.h" -int ff_ass_subtitle_header(AVCodecContext *avctx, - const char *font, int font_size, - int color, int back_color, - int bold, int italic, int underline, - int border_style, int alignment) +int ff_ass_subtitle_header_full(AVCodecContext *avctx, + int play_res_x, int play_res_y, + const char *font, int font_size, + int primary_color, int secondary_color, + int outline_color, int back_color, + int bold, int italic, int underline, + int border_style, int alignment) { avctx->subtitle_header = av_asprintf( "[Script Info]\r\n" @@ -38,6 +40,7 @@ "ScriptType: v4.00+\r\n" "PlayResX: %d\r\n" "PlayResY: %d\r\n" + "ScaledBorderAndShadow: yes\r\n" "\r\n" "[V4+ Styles]\r\n" @@ -67,8 +70,8 @@ "[Events]\r\n" "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\n", !(avctx->flags & AV_CODEC_FLAG_BITEXACT) ? AV_STRINGIFY(LIBAVCODEC_VERSION) : "", - ASS_DEFAULT_PLAYRESX, ASS_DEFAULT_PLAYRESY, - font, font_size, color, color, back_color, back_color, + play_res_x, play_res_y, font, font_size, + primary_color, secondary_color, outline_color, back_color, -bold, -italic, -underline, border_style, alignment); if (!avctx->subtitle_header) @@ -77,6 +80,20 @@ return 0; } +int ff_ass_subtitle_header(AVCodecContext *avctx, + const char *font, int font_size, + int color, int back_color, + int bold, int italic, int underline, + int border_style, int alignment) +{ + return ff_ass_subtitle_header_full(avctx, + ASS_DEFAULT_PLAYRESX, ASS_DEFAULT_PLAYRESY, + font, font_size, color, color, + back_color, back_color, + bold, italic, underline, + border_style, alignment); +} + int ff_ass_subtitle_header_default(AVCodecContext *avctx) { return ff_ass_subtitle_header(avctx, ASS_DEFAULT_FONT, @@ -105,7 +122,7 @@ char *ass_str; AVSubtitleRect **rects; - rects = av_realloc_array(sub->rects, (sub->num_rects+1), sizeof(*sub->rects)); + rects = av_realloc_array(sub->rects, sub->num_rects+1, sizeof(*sub->rects)); if (!rects) return AVERROR(ENOMEM); sub->rects = rects; diff -Nru ffmpeg-4.2.2/libavcodec/assenc.c ffmpeg-4.4/libavcodec/assenc.c --- ffmpeg-4.2.2/libavcodec/assenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/assenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -93,7 +93,7 @@ if (len > bufsize-total_len-1) { av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); - return AVERROR(EINVAL); + return AVERROR_BUFFER_TOO_SMALL; } total_len += len; diff -Nru ffmpeg-4.2.2/libavcodec/ass.h ffmpeg-4.4/libavcodec/ass.h --- ffmpeg-4.2.2/libavcodec/ass.h 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ass.h 2020-07-11 10:39:30.000000000 +0000 @@ -49,6 +49,34 @@ /** * Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS. + * Can specify all fields explicitly + * + * @param avctx pointer to the AVCodecContext + * @param play_res_x subtitle frame width + * @param play_res_y subtitle frame height + * @param font name of the default font face to use + * @param font_size default font size to use + * @param primary_color default text color to use (ABGR) + * @param secondary_color default secondary text color to use (ABGR) + * @param outline_color default outline color to use (ABGR) + * @param back_color default background color to use (ABGR) + * @param bold 1 for bold text, 0 for normal text + * @param italic 1 for italic text, 0 for normal text + * @param underline 1 for underline text, 0 for normal text + * @param border_style 1 for outline, 3 for opaque box + * @param alignment position of the text (left, center, top...), defined after + * the layout of the numpad (1-3 sub, 4-6 mid, 7-9 top) + * @return >= 0 on success otherwise an error code <0 + */ +int ff_ass_subtitle_header_full(AVCodecContext *avctx, + int play_res_x, int play_res_y, + const char *font, int font_size, + int primary_color, int secondary_color, + int outline_color, int back_color, + int bold, int italic, int underline, + int border_style, int alignment); +/** + * Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS. * * @param avctx pointer to the AVCodecContext * @param font name of the default font face to use diff -Nru ffmpeg-4.2.2/libavcodec/ass_split.c ffmpeg-4.4/libavcodec/ass_split.c --- ffmpeg-4.2.2/libavcodec/ass_split.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ass_split.c 2021-04-08 21:28:39.000000000 +0000 @@ -376,6 +376,8 @@ ASSSplitContext *ctx = av_mallocz(sizeof(*ctx)); if (!ctx) return NULL; + if (buf && !strncmp(buf, "\xef\xbb\xbf", 3)) // Skip UTF-8 BOM header + buf += 3; ctx->current_section = -1; if (ass_split(ctx, buf) < 0) { ff_ass_split_free(ctx); diff -Nru ffmpeg-4.2.2/libavcodec/asv.c ffmpeg-4.4/libavcodec/asv.c --- ffmpeg-4.2.2/libavcodec/asv.c 2016-03-29 02:25:11.000000000 +0000 +++ ffmpeg-4.4/libavcodec/asv.c 2021-04-08 21:28:39.000000000 +0000 @@ -53,31 +53,37 @@ }; const uint8_t ff_asv_dc_ccp_tab[8][2] = { - { 0x1, 2 }, { 0xD, 4 }, { 0xF, 4 }, { 0xC, 4 }, - { 0x5, 3 }, { 0xE, 4 }, { 0x4, 3 }, { 0x0, 2 }, + { 0x2, 2 }, { 0xB, 4 }, { 0xF, 4 }, { 0x3, 4 }, + { 0x5, 3 }, { 0x7, 4 }, { 0x1, 3 }, { 0x0, 2 }, }; const uint8_t ff_asv_ac_ccp_tab[16][2] = { - { 0x00, 2 }, { 0x3B, 6 }, { 0x0A, 4 }, { 0x3A, 6 }, - { 0x02, 3 }, { 0x39, 6 }, { 0x3C, 6 }, { 0x38, 6 }, - { 0x03, 3 }, { 0x3D, 6 }, { 0x08, 4 }, { 0x1F, 5 }, - { 0x09, 4 }, { 0x0B, 4 }, { 0x0D, 4 }, { 0x0C, 4 }, + { 0x00, 2 }, { 0x37, 6 }, { 0x05, 4 }, { 0x17, 6 }, + { 0x02, 3 }, { 0x27, 6 }, { 0x0F, 6 }, { 0x07, 6 }, + { 0x06, 3 }, { 0x2F, 6 }, { 0x01, 4 }, { 0x1F, 5 }, + { 0x09, 4 }, { 0x0D, 4 }, { 0x0B, 4 }, { 0x03, 4 }, }; -const uint8_t ff_asv2_level_tab[63][2] = { - { 0x3F, 10 }, { 0x2F, 10 }, { 0x37, 10 }, { 0x27, 10 }, { 0x3B, 10 }, { 0x2B, 10 }, { 0x33, 10 }, { 0x23, 10 }, - { 0x3D, 10 }, { 0x2D, 10 }, { 0x35, 10 }, { 0x25, 10 }, { 0x39, 10 }, { 0x29, 10 }, { 0x31, 10 }, { 0x21, 10 }, - { 0x1F, 8 }, { 0x17, 8 }, { 0x1B, 8 }, { 0x13, 8 }, { 0x1D, 8 }, { 0x15, 8 }, { 0x19, 8 }, { 0x11, 8 }, - { 0x0F, 6 }, { 0x0B, 6 }, { 0x0D, 6 }, { 0x09, 6 }, - { 0x07, 4 }, { 0x05, 4 }, - { 0x03, 2 }, - { 0x00, 5 }, - { 0x02, 2 }, - { 0x04, 4 }, { 0x06, 4 }, - { 0x08, 6 }, { 0x0C, 6 }, { 0x0A, 6 }, { 0x0E, 6 }, - { 0x10, 8 }, { 0x18, 8 }, { 0x14, 8 }, { 0x1C, 8 }, { 0x12, 8 }, { 0x1A, 8 }, { 0x16, 8 }, { 0x1E, 8 }, - { 0x20, 10 }, { 0x30, 10 }, { 0x28, 10 }, { 0x38, 10 }, { 0x24, 10 }, { 0x34, 10 }, { 0x2C, 10 }, { 0x3C, 10 }, - { 0x22, 10 }, { 0x32, 10 }, { 0x2A, 10 }, { 0x3A, 10 }, { 0x26, 10 }, { 0x36, 10 }, { 0x2E, 10 }, { 0x3E, 10 }, +const uint16_t ff_asv2_level_tab[63][2] = { + { 0x3F0, 10 }, { 0x3D0, 10 }, { 0x3B0, 10 }, { 0x390, 10 }, { 0x370, 10 }, + { 0x350, 10 }, { 0x330, 10 }, { 0x310, 10 }, { 0x2F0, 10 }, { 0x2D0, 10 }, + { 0x2B0, 10 }, { 0x290, 10 }, { 0x270, 10 }, { 0x250, 10 }, { 0x230, 10 }, + { 0x210, 10 }, + { 0x0F8, 8 }, { 0x0E8, 8 }, { 0x0D8, 8 }, { 0x0C8, 8 }, { 0x0B8, 8 }, + { 0x0A8, 8 }, { 0x098, 8 }, { 0x088, 8 }, + { 0x03C, 6 }, { 0x034, 6 }, { 0x02C, 6 }, { 0x024, 6 }, + { 0x00E, 4 }, { 0x00A, 4 }, + { 0x003, 2 }, + { 0x000, 5 }, + { 0x001, 2 }, + { 0x002, 4 }, { 0x006, 4 }, + { 0x004, 6 }, { 0x00C, 6 }, { 0x014, 6 }, { 0x01C, 6 }, + { 0x008, 8 }, { 0x018, 8 }, { 0x028, 8 }, { 0x038, 8 }, { 0x048, 8 }, + { 0x058, 8 }, { 0x068, 8 }, { 0x078, 8 }, + { 0x010, 10 }, { 0x030, 10 }, { 0x050, 10 }, { 0x070, 10 }, { 0x090, 10 }, + { 0x0B0, 10 }, { 0x0D0, 10 }, { 0x0F0, 10 }, { 0x110, 10 }, { 0x130, 10 }, + { 0x150, 10 }, { 0x170, 10 }, { 0x190, 10 }, { 0x1B0, 10 }, { 0x1D0, 10 }, + { 0x1F0, 10 } }; av_cold void ff_asv_common_init(AVCodecContext *avctx) diff -Nru ffmpeg-4.2.2/libavcodec/asvdec.c ffmpeg-4.4/libavcodec/asvdec.c --- ffmpeg-4.2.2/libavcodec/asvdec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/asvdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,16 +25,19 @@ #include "libavutil/attributes.h" #include "libavutil/mem.h" +#include "libavutil/thread.h" #include "asv.h" #include "avcodec.h" #include "blockdsp.h" #include "idctdsp.h" #include "internal.h" -#include "mathops.h" #include "mpeg12data.h" -#define VLC_BITS 6 +#define CCP_VLC_BITS 5 +#define DC_CCP_VLC_BITS 4 +#define AC_CCP_VLC_BITS 6 +#define ASV1_LEVEL_VLC_BITS 4 #define ASV2_LEVEL_VLC_BITS 10 static VLC ccp_vlc; @@ -43,40 +46,28 @@ static VLC ac_ccp_vlc; static VLC asv2_level_vlc; -static av_cold void init_vlcs(ASV1Context *a) +static av_cold void init_vlcs(void) { - static int done = 0; - - if (!done) { - done = 1; - - INIT_VLC_STATIC(&ccp_vlc, VLC_BITS, 17, - &ff_asv_ccp_tab[0][1], 2, 1, - &ff_asv_ccp_tab[0][0], 2, 1, 64); - INIT_VLC_STATIC(&dc_ccp_vlc, VLC_BITS, 8, - &ff_asv_dc_ccp_tab[0][1], 2, 1, - &ff_asv_dc_ccp_tab[0][0], 2, 1, 64); - INIT_VLC_STATIC(&ac_ccp_vlc, VLC_BITS, 16, - &ff_asv_ac_ccp_tab[0][1], 2, 1, - &ff_asv_ac_ccp_tab[0][0], 2, 1, 64); - INIT_VLC_STATIC(&level_vlc, VLC_BITS, 7, - &ff_asv_level_tab[0][1], 2, 1, - &ff_asv_level_tab[0][0], 2, 1, 64); - INIT_VLC_STATIC(&asv2_level_vlc, ASV2_LEVEL_VLC_BITS, 63, - &ff_asv2_level_tab[0][1], 2, 1, - &ff_asv2_level_tab[0][0], 2, 1, 1024); - } -} - -// FIXME write a reversed bitstream reader to avoid the double reverse -static inline int asv2_get_bits(GetBitContext *gb, int n) -{ - return ff_reverse[get_bits(gb, n) << (8 - n)]; + INIT_VLC_STATIC(&ccp_vlc, CCP_VLC_BITS, 17, + &ff_asv_ccp_tab[0][1], 2, 1, + &ff_asv_ccp_tab[0][0], 2, 1, 32); + INIT_LE_VLC_STATIC(&dc_ccp_vlc, DC_CCP_VLC_BITS, 8, + &ff_asv_dc_ccp_tab[0][1], 2, 1, + &ff_asv_dc_ccp_tab[0][0], 2, 1, 16); + INIT_LE_VLC_STATIC(&ac_ccp_vlc, AC_CCP_VLC_BITS, 16, + &ff_asv_ac_ccp_tab[0][1], 2, 1, + &ff_asv_ac_ccp_tab[0][0], 2, 1, 64); + INIT_VLC_STATIC(&level_vlc, ASV1_LEVEL_VLC_BITS, 7, + &ff_asv_level_tab[0][1], 2, 1, + &ff_asv_level_tab[0][0], 2, 1, 16); + INIT_LE_VLC_STATIC(&asv2_level_vlc, ASV2_LEVEL_VLC_BITS, 63, + &ff_asv2_level_tab[0][1], 4, 2, + &ff_asv2_level_tab[0][0], 4, 2, 1024); } static inline int asv1_get_level(GetBitContext *gb) { - int code = get_vlc2(gb, level_vlc.table, VLC_BITS, 1); + int code = get_vlc2(gb, level_vlc.table, ASV1_LEVEL_VLC_BITS, 1); if (code == 3) return get_sbits(gb, 8); @@ -84,12 +75,31 @@ return code - 3; } +// get_vlc2() is big-endian in this file +static inline int asv2_get_vlc2(GetBitContext *gb, VLC_TYPE (*table)[2], int bits) +{ + unsigned int index; + int code, n; + + OPEN_READER(re, gb); + UPDATE_CACHE_LE(re, gb); + + index = SHOW_UBITS_LE(re, gb, bits); + code = table[index][0]; + n = table[index][1]; + LAST_SKIP_BITS(re, gb, n); + + CLOSE_READER(re, gb); + + return code; +} + static inline int asv2_get_level(GetBitContext *gb) { - int code = get_vlc2(gb, asv2_level_vlc.table, ASV2_LEVEL_VLC_BITS, 1); + int code = asv2_get_vlc2(gb, asv2_level_vlc.table, ASV2_LEVEL_VLC_BITS); if (code == 31) - return (int8_t) asv2_get_bits(gb, 8); + return (int8_t) get_bits_le(gb, 8); else return code - 31; } @@ -101,7 +111,7 @@ block[0] = 8 * get_bits(&a->gb, 8); for (i = 0; i < 11; i++) { - const int ccp = get_vlc2(&a->gb, ccp_vlc.table, VLC_BITS, 1); + const int ccp = get_vlc2(&a->gb, ccp_vlc.table, CCP_VLC_BITS, 1); if (ccp) { if (ccp == 16) @@ -129,11 +139,11 @@ { int i, count, ccp; - count = asv2_get_bits(&a->gb, 4); + count = get_bits_le(&a->gb, 4); - block[0] = 8 * asv2_get_bits(&a->gb, 8); + block[0] = 8 * get_bits_le(&a->gb, 8); - ccp = get_vlc2(&a->gb, dc_ccp_vlc.table, VLC_BITS, 1); + ccp = asv2_get_vlc2(&a->gb, dc_ccp_vlc.table, DC_CCP_VLC_BITS); if (ccp) { if (ccp & 4) block[a->scantable.permutated[1]] = (asv2_get_level(&a->gb) * a->intra_matrix[1]) >> 4; @@ -144,7 +154,7 @@ } for (i = 1; i < count + 1; i++) { - const int ccp = get_vlc2(&a->gb, ac_ccp_vlc.table, VLC_BITS, 1); + const int ccp = asv2_get_vlc2(&a->gb, ac_ccp_vlc.table, AC_CCP_VLC_BITS); if (ccp) { if (ccp & 8) @@ -218,21 +228,20 @@ p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; - av_fast_padded_malloc(&a->bitstream_buffer, &a->bitstream_buffer_size, - buf_size); - if (!a->bitstream_buffer) - return AVERROR(ENOMEM); - if (avctx->codec_id == AV_CODEC_ID_ASV1) { + av_fast_padded_malloc(&a->bitstream_buffer, &a->bitstream_buffer_size, + buf_size); + if (!a->bitstream_buffer) + return AVERROR(ENOMEM); + a->bbdsp.bswap_buf((uint32_t *) a->bitstream_buffer, (const uint32_t *) buf, buf_size / 4); + ret = init_get_bits8(&a->gb, a->bitstream_buffer, buf_size); } else { - int i; - for (i = 0; i < buf_size; i++) - a->bitstream_buffer[i] = ff_reverse[buf[i]]; + ret = init_get_bits8_le(&a->gb, buf, buf_size); } - - init_get_bits(&a->gb, a->bitstream_buffer, buf_size * 8); + if (ret < 0) + return ret; for (mb_y = 0; mb_y < a->mb_height2; mb_y++) { for (mb_x = 0; mb_x < a->mb_width2; mb_x++) { @@ -272,6 +281,7 @@ static av_cold int decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; ASV1Context *const a = avctx->priv_data; const int scale = avctx->codec_id == AV_CODEC_ID_ASV1 ? 1 : 2; int i; @@ -283,7 +293,6 @@ ff_asv_common_init(avctx); ff_blockdsp_init(&a->bdsp, avctx); ff_idctdsp_init(&a->idsp, avctx); - init_vlcs(a); ff_init_scantable(a->idsp.idct_permutation, &a->scantable, ff_asv_scantab); avctx->pix_fmt = AV_PIX_FMT_YUV420P; @@ -302,6 +311,8 @@ a->inv_qscale; } + ff_thread_once(&init_static_once, init_vlcs); + return 0; } @@ -326,6 +337,7 @@ .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif @@ -337,8 +349,8 @@ .id = AV_CODEC_ID_ASV2, .priv_data_size = sizeof(ASV1Context), .init = decode_init, - .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/asvenc.c ffmpeg-4.4/libavcodec/asvenc.c --- ffmpeg-4.2.2/libavcodec/asvenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/asvenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,14 +32,8 @@ #include "dct.h" #include "fdctdsp.h" #include "internal.h" -#include "mathops.h" #include "mpeg12data.h" -static inline void asv2_put_bits(PutBitContext *pb, int n, int v) -{ - put_bits(pb, n, ff_reverse[v << (8 - n)]); -} - static inline void asv1_put_level(PutBitContext *pb, int level) { unsigned int index = level + 3; @@ -47,7 +41,7 @@ if (index <= 6) { put_bits(pb, ff_asv_level_tab[index][1], ff_asv_level_tab[index][0]); } else { - put_bits(pb, ff_asv_level_tab[3][1], ff_asv_level_tab[3][0]); + put_bits(pb, 3, 0); /* Escape code */ put_sbits(pb, 8, level); } } @@ -57,14 +51,14 @@ unsigned int index = level + 31; if (index <= 62) { - put_bits(pb, ff_asv2_level_tab[index][1], ff_asv2_level_tab[index][0]); + put_bits_le(pb, ff_asv2_level_tab[index][1], ff_asv2_level_tab[index][0]); } else { - put_bits(pb, ff_asv2_level_tab[31][1], ff_asv2_level_tab[31][0]); + put_bits_le(pb, 5, 0); /* Escape code */ if (level < -128 || level > 127) { av_log(a->avctx, AV_LOG_WARNING, "Clipping level %d, increase qscale\n", level); level = av_clip_int8(level); } - asv2_put_bits(pb, 8, level & 0xFF); + put_bits_le(pb, 8, level & 0xFF); } } @@ -95,7 +89,7 @@ if (ccp) { for (; nc_count; nc_count--) - put_bits(&a->pb, ff_asv_ccp_tab[0][1], ff_asv_ccp_tab[0][0]); + put_bits(&a->pb, 2, 2); /* Skip */ put_bits(&a->pb, ff_asv_ccp_tab[ccp][1], ff_asv_ccp_tab[ccp][0]); @@ -111,7 +105,7 @@ nc_count++; } } - put_bits(&a->pb, ff_asv_ccp_tab[16][1], ff_asv_ccp_tab[16][0]); + put_bits(&a->pb, 5, 0xF); /* End of block */ } static inline void asv2_encode_block(ASV1Context *a, int16_t block[64]) @@ -127,8 +121,8 @@ count >>= 2; - asv2_put_bits(&a->pb, 4, count); - asv2_put_bits(&a->pb, 8, (block[0] + 32) >> 6); + put_bits_le(&a->pb, 4, count); + put_bits_le(&a->pb, 8, (block[0] + 32) >> 6); block[0] = 0; for (i = 0; i <= count; i++) { @@ -150,9 +144,9 @@ av_assert2(i || ccp < 8); if (i) - put_bits(&a->pb, ff_asv_ac_ccp_tab[ccp][1], ff_asv_ac_ccp_tab[ccp][0]); + put_bits_le(&a->pb, ff_asv_ac_ccp_tab[ccp][1], ff_asv_ac_ccp_tab[ccp][0]); else - put_bits(&a->pb, ff_asv_dc_ccp_tab[ccp][1], ff_asv_dc_ccp_tab[ccp][0]); + put_bits_le(&a->pb, ff_asv_dc_ccp_tab[ccp][1], ff_asv_dc_ccp_tab[ccp][0]); if (ccp) { if (ccp & 8) @@ -228,7 +222,7 @@ clone->format = pict->format; clone->width = FFALIGN(pict->width, 16); clone->height = FFALIGN(pict->height, 16); - ret = av_frame_get_buffer(clone, 32); + ret = av_frame_get_buffer(clone, 0); if (ret < 0) { av_frame_free(&clone); return ret; @@ -291,19 +285,16 @@ } emms_c(); - avpriv_align_put_bits(&a->pb); - while (put_bits_count(&a->pb) & 31) - put_bits(&a->pb, 8, 0); - - size = put_bits_count(&a->pb) / 32; + if (avctx->codec_id == AV_CODEC_ID_ASV1) + flush_put_bits(&a->pb); + else + flush_put_bits_le(&a->pb); + AV_WN32(put_bits_ptr(&a->pb), 0); + size = (put_bits_count(&a->pb) + 31) / 32; if (avctx->codec_id == AV_CODEC_ID_ASV1) { a->bbdsp.bswap_buf((uint32_t *) pkt->data, (uint32_t *) pkt->data, size); - } else { - int i; - for (i = 0; i < 4 * size; i++) - pkt->data[i] = ff_reverse[pkt->data[i]]; } pkt->size = size * 4; diff -Nru ffmpeg-4.2.2/libavcodec/asv.h ffmpeg-4.4/libavcodec/asv.h --- ffmpeg-4.2.2/libavcodec/asv.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/asv.h 2021-04-08 21:28:39.000000000 +0000 @@ -28,7 +28,7 @@ #include -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "blockdsp.h" @@ -66,7 +66,7 @@ extern const uint8_t ff_asv_level_tab[7][2]; extern const uint8_t ff_asv_dc_ccp_tab[8][2]; extern const uint8_t ff_asv_ac_ccp_tab[16][2]; -extern const uint8_t ff_asv2_level_tab[63][2]; +extern const uint16_t ff_asv2_level_tab[63][2]; void ff_asv_common_init(AVCodecContext *avctx); diff -Nru ffmpeg-4.2.2/libavcodec/atrac1.c ffmpeg-4.4/libavcodec/atrac1.c --- ffmpeg-4.2.2/libavcodec/atrac1.c 2018-07-17 09:27:39.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atrac1.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,6 +33,8 @@ #include #include "libavutil/float_dsp.h" +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "get_bits.h" #include "fft.h" @@ -80,7 +82,8 @@ DECLARE_ALIGNED(32, float, high)[512]; float* bands[3]; FFTContext mdct_ctx[3]; - AVFloatDSPContext *fdsp; + void (*vector_fmul_window)(float *dst, const float *src0, + const float *src1, const float *win, int len); } AT1Ctx; /** size of the transform in samples in the long mode for each QMF band */ @@ -140,8 +143,8 @@ at1_imdct(q, &q->spec[pos], &su->spectrum[0][ref_pos + start_pos], nbits, band_num); /* overlap and window */ - q->fdsp->vector_fmul_window(&q->bands[band_num][start_pos], prev_buf, - &su->spectrum[0][ref_pos + start_pos], ff_sine_32, 16); + q->vector_fmul_window(&q->bands[band_num][start_pos], prev_buf, + &su->spectrum[0][ref_pos + start_pos], ff_sine_32, 16); prev_buf = &su->spectrum[0][ref_pos+start_pos + 16]; start_pos += block_size; @@ -324,8 +327,6 @@ ff_mdct_end(&q->mdct_ctx[1]); ff_mdct_end(&q->mdct_ctx[2]); - av_freep(&q->fdsp); - return 0; } @@ -333,6 +334,7 @@ static av_cold int atrac1_decode_init(AVCodecContext *avctx) { AT1Ctx *q = avctx->priv_data; + AVFloatDSPContext *fdsp; int ret; avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; @@ -353,7 +355,6 @@ (ret = ff_mdct_init(&q->mdct_ctx[1], 8, 1, -1.0/ (1 << 15))) || (ret = ff_mdct_init(&q->mdct_ctx[2], 9, 1, -1.0/ (1 << 15)))) { av_log(avctx, AV_LOG_ERROR, "Error initializing MDCT\n"); - atrac1_decode_end(avctx); return ret; } @@ -361,7 +362,11 @@ ff_atrac_generate_tables(); - q->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); + fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); + if (!fdsp) + return AVERROR(ENOMEM); + q->vector_fmul_window = fdsp->vector_fmul_window; + av_free(fdsp); q->bands[0] = q->low; q->bands[1] = q->mid; @@ -389,4 +394,5 @@ .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/atrac3.c ffmpeg-4.4/libavcodec/atrac3.c --- ffmpeg-4.2.2/libavcodec/atrac3.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atrac3.c 2021-04-08 21:28:39.000000000 +0000 @@ -39,6 +39,9 @@ #include "libavutil/attributes.h" #include "libavutil/float_dsp.h" #include "libavutil/libm.h" +#include "libavutil/mem_internal.h" +#include "libavutil/thread.h" + #include "avcodec.h" #include "bytestream.h" #include "fft.h" @@ -58,6 +61,8 @@ #define SAMPLES_PER_FRAME 1024 #define MDCT_SIZE 512 +#define ATRAC3_VLC_BITS 8 + typedef struct GainBlock { AtracGainInfo g_block[4]; } GainBlock; @@ -111,11 +116,12 @@ AtracGCContext gainc_ctx; FFTContext mdct_ctx; - AVFloatDSPContext *fdsp; + void (*vector_fmul)(float *dst, const float *src0, const float *src1, + int len); } ATRAC3Context; static DECLARE_ALIGNED(32, float, mdct_window)[MDCT_SIZE]; -static VLC_TYPE atrac3_vlc_table[4096][2]; +static VLC_TYPE atrac3_vlc_table[7 * 1 << ATRAC3_VLC_BITS][2]; static VLC spectral_coeff_tab[7]; /** @@ -144,7 +150,7 @@ q->mdct_ctx.imdct_calc(&q->mdct_ctx, output, input); /* Perform windowing on the output. */ - q->fdsp->vector_fmul(output, output, mdct_window, MDCT_SIZE); + q->vector_fmul(output, output, mdct_window, MDCT_SIZE); } /* @@ -194,7 +200,6 @@ av_freep(&q->units); av_freep(&q->decoded_bytes_buffer); - av_freep(&q->fdsp); ff_mdct_end(&q->mdct_ctx); @@ -244,18 +249,13 @@ /* variable length coding (VLC) */ if (selector != 1) { for (i = 0; i < num_codes; i++) { - huff_symb = get_vlc2(gb, spectral_coeff_tab[selector-1].table, - spectral_coeff_tab[selector-1].bits, 3); - huff_symb += 1; - code = huff_symb >> 1; - if (huff_symb & 1) - code = -code; - mantissas[i] = code; + mantissas[i] = get_vlc2(gb, spectral_coeff_tab[selector-1].table, + ATRAC3_VLC_BITS, 1); } } else { for (i = 0; i < num_codes; i++) { huff_symb = get_vlc2(gb, spectral_coeff_tab[selector - 1].table, - spectral_coeff_tab[selector - 1].bits, 3); + ATRAC3_VLC_BITS, 1); mantissas[i * 2 ] = mantissa_vlc_tab[huff_symb * 2 ]; mantissas[i * 2 + 1] = mantissa_vlc_tab[huff_symb * 2 + 1]; } @@ -851,6 +851,8 @@ static av_cold void atrac3_init_static_data(void) { + VLC_TYPE (*table)[2] = atrac3_vlc_table; + const uint8_t (*hufftabs)[2] = atrac3_hufftabs; int i; init_imdct_window(); @@ -858,32 +860,31 @@ /* Initialize the VLC tables. */ for (i = 0; i < 7; i++) { - spectral_coeff_tab[i].table = &atrac3_vlc_table[atrac3_vlc_offs[i]]; - spectral_coeff_tab[i].table_allocated = atrac3_vlc_offs[i + 1] - - atrac3_vlc_offs[i ]; - init_vlc(&spectral_coeff_tab[i], 9, huff_tab_sizes[i], - huff_bits[i], 1, 1, - huff_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + spectral_coeff_tab[i].table = table; + spectral_coeff_tab[i].table_allocated = 256; + ff_init_vlc_from_lengths(&spectral_coeff_tab[i], ATRAC3_VLC_BITS, huff_tab_sizes[i], + &hufftabs[0][1], 2, + &hufftabs[0][0], 2, 1, + -31, INIT_VLC_USE_NEW_STATIC, NULL); + hufftabs += huff_tab_sizes[i]; + table += 256; } } static av_cold int atrac3_decode_init(AVCodecContext *avctx) { - static int static_init_done; + static AVOnce init_static_once = AV_ONCE_INIT; int i, js_pair, ret; int version, delay, samples_per_frame, frame_factor; const uint8_t *edata_ptr = avctx->extradata; ATRAC3Context *q = avctx->priv_data; + AVFloatDSPContext *fdsp; if (avctx->channels < MIN_CHANNELS || avctx->channels > MAX_CHANNELS) { av_log(avctx, AV_LOG_ERROR, "Channel configuration error!\n"); return AVERROR(EINVAL); } - if (!static_init_done) - atrac3_init_static_data(); - static_init_done = 1; - /* Take care of the codec-specific extradata. */ if (avctx->codec_id == AV_CODEC_ID_ATRAC3AL) { version = 4; @@ -964,7 +965,7 @@ return AVERROR_INVALIDDATA; } - if (avctx->block_align > 1024 || avctx->block_align <= 0) + if (avctx->block_align > 4096 || avctx->block_align <= 0) return AVERROR(EINVAL); q->decoded_bytes_buffer = av_mallocz(FFALIGN(avctx->block_align, 4) + @@ -977,7 +978,6 @@ /* initialize the MDCT transform */ if ((ret = ff_mdct_init(&q->mdct_ctx, 9, 1, 1.0 / 32768)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error initializing MDCT\n"); - av_freep(&q->decoded_bytes_buffer); return ret; } @@ -998,13 +998,17 @@ } ff_atrac_init_gain_compensation(&q->gainc_ctx, 4, 3); - q->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); + fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); + if (!fdsp) + return AVERROR(ENOMEM); + q->vector_fmul = fdsp->vector_fmul; + av_free(fdsp); q->units = av_mallocz_array(avctx->channels, sizeof(*q->units)); - if (!q->units || !q->fdsp) { - atrac3_decode_close(avctx); + if (!q->units) return AVERROR(ENOMEM); - } + + ff_thread_once(&init_static_once, atrac3_init_static_data); return 0; } @@ -1021,6 +1025,7 @@ .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; AVCodec ff_atrac3al_decoder = { @@ -1035,4 +1040,5 @@ .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/atrac3data.h ffmpeg-4.4/libavcodec/atrac3data.h --- ffmpeg-4.2.2/libavcodec/atrac3data.h 2016-03-29 02:25:11.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atrac3data.h 2021-04-08 21:28:39.000000000 +0000 @@ -32,81 +32,47 @@ /* VLC tables */ -static const uint8_t huffcode1[9] = { - 0x0, 0x4, 0x5, 0xC, 0xD, 0x1C, 0x1D, 0x1E, 0x1F -}; - -static const uint8_t huffbits1[9] = { 1, 3, 3, 4, 4, 5, 5, 5, 5 }; - -static const uint8_t huffcode2[5] = { 0x0, 0x4, 0x5, 0x6, 0x7 }; - -static const uint8_t huffbits2[5] = { 1, 3, 3, 3, 3 }; - -static const uint8_t huffcode3[7] = { 0x0, 0x4, 0x5, 0xC, 0xD, 0xE, 0xF }; - -static const uint8_t huffbits3[7] = { 1, 3, 3, 4, 4, 4, 4 }; - -static const uint8_t huffcode4[9] = { - 0x0, 0x4, 0x5, 0xC, 0xD, 0x1C, 0x1D, 0x1E, 0x1F -}; - -static const uint8_t huffbits4[9] = { 1, 3, 3, 4, 4, 5, 5, 5, 5 }; - -static const uint8_t huffcode5[15] = { - 0x00, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B, 0x1C, - 0x1D, 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x0D -}; - -static const uint8_t huffbits5[15] = { - 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 4, 4 -}; - -static const uint8_t huffcode6[31] = { - 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x14, - 0x15, 0x16, 0x17, 0x18, 0x19, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x78, 0x79, 0x7A, - 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x08, 0x09 -}; - -static const uint8_t huffbits6[31] = { - 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, - 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4 -}; - -static const uint8_t huffcode7[63] = { - 0x00, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, - 0x0F, 0x10, 0x11, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, - 0x31, 0x32, 0x33, 0x68, 0x69, 0x6A, 0x6B, 0x6C, - 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, - 0x75, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, - 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, - 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x02, 0x03 -}; - -static const uint8_t huffbits7[63] = { - 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4 +static const uint8_t atrac3_hufftabs[][2] = { + /* Spectral coefficient 1 - 9 entries */ + { 31, 1 }, { 32, 3 }, { 33, 3 }, { 34, 4 }, { 35, 4 }, + { 36, 5 }, { 37, 5 }, { 38, 5 }, { 39, 5 }, + /* Spectral coefficient 2 - 5 entries */ + { 31, 1 }, { 32, 3 }, { 30, 3 }, { 33, 3 }, { 29, 3 }, + /* Spectral coefficient 3 - 7 entries */ + { 31, 1 }, { 32, 3 }, { 30, 3 }, { 33, 4 }, + { 29, 4 }, { 34, 4 }, { 28, 4 }, + /* Spectral coefficient 4 - 9 entries */ + { 31, 1 }, { 32, 3 }, { 30, 3 }, { 33, 4 }, { 29, 4 }, + { 34, 5 }, { 28, 5 }, { 35, 5 }, { 27, 5 }, + /* Spectral coefficient 5 - 15 entries */ + { 31, 2 }, { 32, 3 }, { 30, 3 }, { 33, 4 }, { 29, 4 }, + { 34, 4 }, { 28, 4 }, { 38, 4 }, { 24, 4 }, { 35, 5 }, + { 27, 5 }, { 36, 6 }, { 26, 6 }, { 37, 6 }, { 25, 6 }, + /* Spectral coefficient 6 - 31 entries */ + { 31, 3 }, { 32, 4 }, { 30, 4 }, { 33, 4 }, { 29, 4 }, { 34, 4 }, + { 28, 4 }, { 46, 4 }, { 16, 4 }, { 35, 5 }, { 27, 5 }, { 36, 5 }, + { 26, 5 }, { 37, 5 }, { 25, 5 }, { 38, 6 }, { 24, 6 }, { 39, 6 }, + { 23, 6 }, { 40, 6 }, { 22, 6 }, { 41, 6 }, { 21, 6 }, { 42, 7 }, + { 20, 7 }, { 43, 7 }, { 19, 7 }, { 44, 7 }, { 18, 7 }, { 45, 7 }, + { 17, 7 }, + /* Spectral coefficient 7 - 63 entries */ + { 31, 3 }, { 62, 4 }, { 0, 4 }, { 32, 5 }, { 30, 5 }, { 33, 5 }, + { 29, 5 }, { 34, 5 }, { 28, 5 }, { 35, 5 }, { 27, 5 }, { 36, 5 }, + { 26, 5 }, { 37, 6 }, { 25, 6 }, { 38, 6 }, { 24, 6 }, { 39, 6 }, + { 23, 6 }, { 40, 6 }, { 22, 6 }, { 41, 6 }, { 21, 6 }, { 42, 6 }, + { 20, 6 }, { 43, 6 }, { 19, 6 }, { 44, 6 }, { 18, 6 }, { 45, 7 }, + { 17, 7 }, { 46, 7 }, { 16, 7 }, { 47, 7 }, { 15, 7 }, { 48, 7 }, + { 14, 7 }, { 49, 7 }, { 13, 7 }, { 50, 7 }, { 12, 7 }, { 51, 7 }, + { 11, 7 }, { 52, 8 }, { 10, 8 }, { 53, 8 }, { 9, 8 }, { 54, 8 }, + { 8, 8 }, { 55, 8 }, { 7, 8 }, { 56, 8 }, { 6, 8 }, { 57, 8 }, + { 5, 8 }, { 58, 8 }, { 4, 8 }, { 59, 8 }, { 3, 8 }, { 60, 8 }, + { 2, 8 }, { 61, 8 }, { 1, 8 }, }; static const uint8_t huff_tab_sizes[7] = { 9, 5, 7, 9, 15, 31, 63, }; -static const uint8_t* const huff_codes[7] = { - huffcode1, huffcode2, huffcode3, huffcode4, huffcode5, huffcode6, huffcode7 -}; - -static const uint8_t* const huff_bits[7] = { - huffbits1, huffbits2, huffbits3, huffbits4, huffbits5, huffbits6, huffbits7, -}; - -static const uint16_t atrac3_vlc_offs[9] = { - 0, 512, 1024, 1536, 2048, 2560, 3072, 3584, 4096 -}; - /* selector tables */ static const uint8_t clc_length_tab[8] = { 0, 4, 3, 3, 4, 4, 5, 6 }; diff -Nru ffmpeg-4.2.2/libavcodec/atrac3plus.c ffmpeg-4.4/libavcodec/atrac3plus.c --- ffmpeg-4.2.2/libavcodec/atrac3plus.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atrac3plus.c 2021-04-08 21:28:39.000000000 +0000 @@ -43,170 +43,75 @@ * Generate canonical VLC table from given descriptor. * * @param[in] cb ptr to codebook descriptor - * @param[in] xlat ptr to translation table or NULL + * @param[in,out] xlat ptr to ptr to translation table * @param[in,out] tab_offset starting offset to the generated vlc table * @param[out] out_vlc ptr to vlc table to be generated */ -static av_cold void build_canonical_huff(const uint8_t *cb, const uint8_t *xlat, +static av_cold void build_canonical_huff(const uint8_t *cb, const uint8_t **xlat, int *tab_offset, VLC *out_vlc) { - int i, b; - uint16_t codes[256]; + int i, max_len; uint8_t bits[256]; - unsigned code = 0; int index = 0; - int min_len = *cb++; // get shortest codeword length - int max_len = *cb++; // get longest codeword length - for (b = min_len; b <= max_len; b++) { + for (int b = 1; b <= 12; b++) { for (i = *cb++; i > 0; i--) { av_assert0(index < 256); bits[index] = b; - codes[index] = code++; index++; } - code <<= 1; } + max_len = bits[index - 1]; out_vlc->table = &tables_data[*tab_offset]; out_vlc->table_allocated = 1 << max_len; - ff_init_vlc_sparse(out_vlc, max_len, index, bits, 1, 1, codes, 2, 2, - xlat, 1, 1, INIT_VLC_USE_NEW_STATIC); + ff_init_vlc_from_lengths(out_vlc, max_len, index, bits, 1, + *xlat, 1, 1, 0, INIT_VLC_USE_NEW_STATIC, NULL); *tab_offset += 1 << max_len; + *xlat += index; } av_cold void ff_atrac3p_init_vlcs(void) { - int i, wl_vlc_offs, ct_vlc_offs, sf_vlc_offs, tab_offset; + int i, tab_offset = 0; + const uint8_t *xlats; - static const uint8_t wl_nb_bits[4] = { 2, 3, 5, 5 }; - static const uint8_t wl_nb_codes[4] = { 3, 5, 8, 8 }; - static const uint8_t * const wl_bits[4] = { - atrac3p_wl_huff_bits1, atrac3p_wl_huff_bits2, - atrac3p_wl_huff_bits3, atrac3p_wl_huff_bits4 - }; - static const uint8_t * const wl_codes[4] = { - atrac3p_wl_huff_code1, atrac3p_wl_huff_code2, - atrac3p_wl_huff_code3, atrac3p_wl_huff_code4 - }; - static const uint8_t * const wl_xlats[4] = { - atrac3p_wl_huff_xlat1, atrac3p_wl_huff_xlat2, NULL, NULL - }; - - static const uint8_t ct_nb_bits[4] = { 3, 4, 4, 4 }; - static const uint8_t ct_nb_codes[4] = { 4, 8, 8, 8 }; - static const uint8_t * const ct_bits[4] = { - atrac3p_ct_huff_bits1, atrac3p_ct_huff_bits2, - atrac3p_ct_huff_bits2, atrac3p_ct_huff_bits3 - }; - static const uint8_t * const ct_codes[4] = { - atrac3p_ct_huff_code1, atrac3p_ct_huff_code2, - atrac3p_ct_huff_code2, atrac3p_ct_huff_code3 - }; - static const uint8_t * const ct_xlats[4] = { - NULL, NULL, atrac3p_ct_huff_xlat1, NULL - }; - - static const uint8_t sf_nb_bits[8] = { 9, 9, 9, 9, 6, 6, 7, 7 }; - static const uint8_t sf_nb_codes[8] = { 64, 64, 64, 64, 16, 16, 16, 16 }; - static const uint8_t * const sf_bits[8] = { - atrac3p_sf_huff_bits1, atrac3p_sf_huff_bits1, atrac3p_sf_huff_bits2, - atrac3p_sf_huff_bits3, atrac3p_sf_huff_bits4, atrac3p_sf_huff_bits4, - atrac3p_sf_huff_bits5, atrac3p_sf_huff_bits6 - }; - static const uint16_t * const sf_codes[8] = { - atrac3p_sf_huff_code1, atrac3p_sf_huff_code1, atrac3p_sf_huff_code2, - atrac3p_sf_huff_code3, atrac3p_sf_huff_code4, atrac3p_sf_huff_code4, - atrac3p_sf_huff_code5, atrac3p_sf_huff_code6 - }; - static const uint8_t * const sf_xlats[8] = { - atrac3p_sf_huff_xlat1, atrac3p_sf_huff_xlat2, NULL, NULL, - atrac3p_sf_huff_xlat4, atrac3p_sf_huff_xlat5, NULL, NULL - }; - - static const uint8_t * const gain_cbs[11] = { - atrac3p_huff_gain_npoints1_cb, atrac3p_huff_gain_npoints1_cb, - atrac3p_huff_gain_lev1_cb, atrac3p_huff_gain_lev2_cb, - atrac3p_huff_gain_lev3_cb, atrac3p_huff_gain_lev4_cb, - atrac3p_huff_gain_loc3_cb, atrac3p_huff_gain_loc1_cb, - atrac3p_huff_gain_loc4_cb, atrac3p_huff_gain_loc2_cb, - atrac3p_huff_gain_loc5_cb - }; - static const uint8_t * const gain_xlats[11] = { - NULL, atrac3p_huff_gain_npoints2_xlat, atrac3p_huff_gain_lev1_xlat, - atrac3p_huff_gain_lev2_xlat, atrac3p_huff_gain_lev3_xlat, - atrac3p_huff_gain_lev4_xlat, atrac3p_huff_gain_loc3_xlat, - atrac3p_huff_gain_loc1_xlat, atrac3p_huff_gain_loc4_xlat, - atrac3p_huff_gain_loc2_xlat, atrac3p_huff_gain_loc5_xlat - }; - - static const uint8_t * const tone_cbs[7] = { - atrac3p_huff_tonebands_cb, atrac3p_huff_numwavs1_cb, - atrac3p_huff_numwavs2_cb, atrac3p_huff_wav_ampsf1_cb, - atrac3p_huff_wav_ampsf2_cb, atrac3p_huff_wav_ampsf3_cb, - atrac3p_huff_freq_cb - }; - static const uint8_t * const tone_xlats[7] = { - NULL, NULL, atrac3p_huff_numwavs2_xlat, atrac3p_huff_wav_ampsf1_xlat, - atrac3p_huff_wav_ampsf2_xlat, atrac3p_huff_wav_ampsf3_xlat, - atrac3p_huff_freq_xlat - }; - - for (i = 0, wl_vlc_offs = 0, ct_vlc_offs = 2508; i < 4; i++) { - wl_vlc_tabs[i].table = &tables_data[wl_vlc_offs]; - wl_vlc_tabs[i].table_allocated = 1 << wl_nb_bits[i]; - ct_vlc_tabs[i].table = &tables_data[ct_vlc_offs]; - ct_vlc_tabs[i].table_allocated = 1 << ct_nb_bits[i]; - - ff_init_vlc_sparse(&wl_vlc_tabs[i], wl_nb_bits[i], wl_nb_codes[i], - wl_bits[i], 1, 1, - wl_codes[i], 1, 1, - wl_xlats[i], 1, 1, - INIT_VLC_USE_NEW_STATIC); - - ff_init_vlc_sparse(&ct_vlc_tabs[i], ct_nb_bits[i], ct_nb_codes[i], - ct_bits[i], 1, 1, - ct_codes[i], 1, 1, - ct_xlats[i], 1, 1, - INIT_VLC_USE_NEW_STATIC); - - wl_vlc_offs += wl_vlc_tabs[i].table_allocated; - ct_vlc_offs += ct_vlc_tabs[i].table_allocated; - } - - for (i = 0, sf_vlc_offs = 76; i < 8; i++) { - sf_vlc_tabs[i].table = &tables_data[sf_vlc_offs]; - sf_vlc_tabs[i].table_allocated = 1 << sf_nb_bits[i]; - - ff_init_vlc_sparse(&sf_vlc_tabs[i], sf_nb_bits[i], sf_nb_codes[i], - sf_bits[i], 1, 1, - sf_codes[i], 2, 2, - sf_xlats[i], 1, 1, - INIT_VLC_USE_NEW_STATIC); - sf_vlc_offs += sf_vlc_tabs[i].table_allocated; + xlats = atrac3p_wl_ct_xlats; + for (int i = 0; i < 4; i++) { + build_canonical_huff(atrac3p_wl_cbs[i], &xlats, + &tab_offset, &wl_vlc_tabs[i]); + build_canonical_huff(atrac3p_ct_cbs[i], &xlats, + &tab_offset, &ct_vlc_tabs[i]); } - tab_offset = 2564; + xlats = atrac3p_sf_xlats; + for (int i = 0; i < 8; i++) + build_canonical_huff(atrac3p_sf_cbs[i], &xlats, + &tab_offset, &sf_vlc_tabs[i]); /* build huffman tables for spectrum decoding */ + xlats = atrac3p_spectra_xlats; for (i = 0; i < 112; i++) { - if (atrac3p_spectra_tabs[i].cb) - build_canonical_huff(atrac3p_spectra_tabs[i].cb, - atrac3p_spectra_tabs[i].xlat, - &tab_offset, &spec_vlc_tabs[i]); - else - spec_vlc_tabs[i].table = 0; + if (atrac3p_spectra_cbs[i][0] >= 0) + build_canonical_huff(atrac3p_spectra_cbs[i], + &xlats, &tab_offset, &spec_vlc_tabs[i]); + else /* Reuse already initialized VLC table */ + spec_vlc_tabs[i] = spec_vlc_tabs[-atrac3p_spectra_cbs[i][0]]; } /* build huffman tables for gain data decoding */ + xlats = atrac3p_gain_xlats; for (i = 0; i < 11; i++) - build_canonical_huff(gain_cbs[i], gain_xlats[i], &tab_offset, &gain_vlc_tabs[i]); + build_canonical_huff(atrac3p_gain_cbs[i], &xlats, + &tab_offset, &gain_vlc_tabs[i]); /* build huffman tables for tone decoding */ + xlats = atrac3p_tone_xlats; for (i = 0; i < 7; i++) - build_canonical_huff(tone_cbs[i], tone_xlats[i], &tab_offset, &tone_vlc_tabs[i]); + build_canonical_huff(atrac3p_tone_cbs[i], &xlats, + &tab_offset, &tone_vlc_tabs[i]); } /** @@ -880,10 +785,6 @@ tab_index = (chan->table_type * 8 + codetab) * 7 + wordlen - 1; tab = &atrac3p_spectra_tabs[tab_index]; - /* this allows reusing VLC tables */ - if (tab->redirect >= 0) - tab_index = tab->redirect; - decode_qu_spectra(gb, tab, &spec_vlc_tabs[tab_index], &chan->spectrum[ff_atrac3p_qu_to_spec_pos[qu]], num_specs); diff -Nru ffmpeg-4.2.2/libavcodec/atrac3plus_data.h ffmpeg-4.4/libavcodec/atrac3plus_data.h --- ffmpeg-4.2.2/libavcodec/atrac3plus_data.h 2016-03-29 02:25:11.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atrac3plus_data.h 2021-04-08 21:28:39.000000000 +0000 @@ -27,149 +27,83 @@ #include /** VLC tables for wordlen */ -static const uint8_t atrac3p_wl_huff_code1[3] = { 0, 2, 3 }; - -static const uint8_t atrac3p_wl_huff_bits1[3] = { 1, 2, 2 }; - -static const uint8_t atrac3p_wl_huff_xlat1[3] = { 0, 1, 7 }; - -static const uint8_t atrac3p_wl_huff_code2[5] = { 0, 4, 5, 6, 7 }; - -static const uint8_t atrac3p_wl_huff_bits2[5] = { 1, 3, 3, 3, 3 }; - -static const uint8_t atrac3p_wl_huff_xlat2[5] = { 0, 1, 2, 6, 7 }; - -static const uint8_t atrac3p_wl_huff_code3[8] = { - 0, 4, 0xC, 0x1E, 0x1F, 0xD, 0xE, 5 +static const uint8_t atrac3p_wl_cbs[][12] = { + { 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0 }, }; -static const uint8_t atrac3p_wl_huff_bits3[8] = { 1, 3, 4, 5, 5, 4, 4, 3 }; - -static const uint8_t atrac3p_wl_huff_code4[8] = { - 0, 4, 0xC, 0xD, 0x1E, 0x1F, 0xE, 5 +/** VLC tables for code table indexes */ +static const uint8_t atrac3p_ct_cbs[][12] = { + { 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, +}; +/* Symbols for wordlen interleaved with symbols for code table */ +static const uint8_t atrac3p_wl_ct_xlats[] = { + /* wordlen table 1 - 3 entries */ + 0, 1, 7, + /* code table 1 - 4 entries */ + 0, 1, 2, 3, + /* wordlen table 2 - 5 entries */ + 0, 1, 2, 6, 7, + /* code table 2 - 8 entries */ + 0, 1, 2, 3, 4, 5, 6, 7, + /* wordlen table 3 - 8 entries */ + 0, 1, 7, 2, 5, 6, 3, 4, + /* code table 3 - 8 entries */ + 0, 1, 2, 3, 6, 7, 4, 5, + /* wordlen table 4 - 8 entries */ + 0, 1, 7, 2, 3, 6, 4, 5, + /* code table 4 - 8 entries */ + 0, 1, 2, 3, 4, 5, 6, 7, }; -static const uint8_t atrac3p_wl_huff_bits4[8] = { 1, 3, 4, 4, 5, 5, 4, 3 }; - /** VLC tables for scale factor indexes */ -static const uint16_t atrac3p_sf_huff_code1[64] = { - 0, 2, 3, 4, 5, 0xC, 0xD, 0xE0, - 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0x1CE, 0x1CF, - 0x1D0, 0x1D1, 0x1D2, 0x1D3, 0x1D4, 0x1D5, 0x1D6, 0x1D7, - 0x1D8, 0x1D9, 0x1DA, 0x1DB, 0x1DC, 0x1DD, 0x1DE, 0x1DF, - 0x1E0, 0x1E1, 0x1E2, 0x1E3, 0x1E4, 0x1E5, 0x1E6, 0x1E7, - 0x1E8, 0x1E9, 0x1EA, 0x1EB, 0x1EC, 0x1ED, 0x1EE, 0x1EF, - 0x1F0, 0x1F1, 0x1F2, 0x1F3, 0x1F4, 0x1F5, 0x1F6, 0x1F7, - 0x1F8, 0x1F9, 0x1FA, 0x1FB, 0x1FC, 0x1FD, 0x1FE, 0x1FF +static const uint8_t atrac3p_sf_cbs[][12] = { + { 0, 1, 4, 2, 0, 0, 0, 7, 50, 0, 0, 0 }, + { 0, 1, 4, 2, 0, 0, 0, 7, 50, 0, 0, 0 }, + { 1, 0, 2, 0, 4, 0, 2, 1, 54, 0, 0, 0 }, + { 0, 1, 4, 0, 4, 0, 3, 0, 52, 0, 0, 0 }, + { 0, 1, 4, 2, 0, 8, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 4, 2, 0, 8, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 2, 2, 2, 0, 8, 0, 0, 0, 0, 0 }, + { 0, 1, 4, 2, 2, 2, 4, 0, 0, 0, 0, 0 }, }; -static const uint8_t atrac3p_sf_huff_bits1[64] = { - 2, 3, 3, 3, 3, 4, 4, 8, 8, 8, 8, 8, 8, 8, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 -}; - -static const uint8_t atrac3p_sf_huff_xlat1[64] = { +static const uint8_t atrac3p_sf_xlats[] = { + /* Scale factor index 1 - 64 entries */ 0, 1, 61, 62, 63, 2, 60, 3, 4, 5, 6, 57, 58, 59, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 -}; - -static const uint8_t atrac3p_sf_huff_xlat2[64] = { - 0, 1, 2, 62, 63, 3, 61, 4, 5, 6, 57, 58, 59, 60, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* Scale factor index 2 - 64 entries */ + 0, 1, 2, 62, 63, 3, 61, 4, 5, 6, 57, 58, 59, 60, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 -}; - -static const uint16_t atrac3p_sf_huff_code2[64] = { - 0, 4, 0x18, 0x19, 0x70, 0x1CA, 0x1CB, 0x1CC, - 0x1CD, 0x1CE, 0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3, 0x1D4, - 0x1D5, 0x1D6, 0x1D7, 0x1D8, 0x1D9, 0x1DA, 0x1DB, 0x1DC, - 0x1DD, 0x1DE, 0x1DF, 0x1E0, 0x1E1, 0x1E2, 0x1E3, 0x1E4, - 0x1E5, 0x1E6, 0x1E7, 0x1E8, 0x1E9, 0x1EA, 0x1EB, 0x1EC, - 0x1ED, 0x1EE, 0x1EF, 0x1F0, 0x1F1, 0x1F2, 0x1F3, 0x1F4, - 0x1F5, 0x1F6, 0x1F7, 0x1F8, 0x1F9, 0x1FA, 0x1FB, 0x1FC, - 0x1FD, 0x1FE, 0x1FF, 0xE4, 0x71, 0x1A, 0x1B, 5 -}; - -static const uint8_t atrac3p_sf_huff_bits2[64] = { - 1, 3, 5, 5, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 5, 5, 3 -}; - -static const uint16_t atrac3p_sf_huff_code3[64] = { - 0, 2, 3, 0x18, 0x19, 0x70, 0x1CC, 0x1CD, - 0x1CE, 0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3, 0x1D4, 0x1D5, - 0x1D6, 0x1D7, 0x1D8, 0x1D9, 0x1DA, 0x1DB, 0x1DC, 0x1DD, - 0x1DE, 0x1DF, 0x1E0, 0x1E1, 0x1E2, 0x1E3, 0x1E4, 0x1E5, - 0x1E6, 0x1E7, 0x1E8, 0x1E9, 0x1EA, 0x1EB, 0x1EC, 0x1ED, - 0x1EE, 0x1EF, 0x1F0, 0x1F1, 0x1F2, 0x1F3, 0x1F4, 0x1F5, - 0x1F6, 0x1F7, 0x1F8, 0x1F9, 0x1FA, 0x1FB, 0x1FC, 0x1FD, - 0x1FE, 0x1FF, 0x71, 0x72, 0x1A, 0x1B, 4, 5 -}; - -static const uint8_t atrac3p_sf_huff_bits3[64] = { - 2, 3, 3, 5, 5, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 5, 5, 3, 3 -}; - -static const uint16_t atrac3p_sf_huff_code4[16] = { - 0, 2, 3, 4, 5, 0xC, 0xD, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0, 0x3D, 0x3E, 0x3F -}; - -static const uint8_t atrac3p_sf_huff_bits4[16] = { - 2, 3, 3, 3, 3, 4, 4, 6, 6, 6, 6, 6, 0, 6, 6, 6 -}; - -static const uint8_t atrac3p_sf_huff_xlat4[16] = { - 0, 1, 13, 14, 15, 2, 12, 3, 4, 5, 6, 7, 8, 9, 10, 11 -}; - -static const uint8_t atrac3p_sf_huff_xlat5[16] = { - 0, 1, 2, 14, 15, 3, 13, 4, 5, 6, 7, 9, 8, 10, 11, 12 -}; - -static const uint16_t atrac3p_sf_huff_code5[16] = { - 0, 4, 0xC, 0x1C, 0x78, 0x79, 0x7A, 0x7B, - 0, 0x7C, 0x7D, 0x7E, 0x7F, 0x1D, 0xD, 5 -}; - -static const uint8_t atrac3p_sf_huff_bits5[16] = { - 1, 3, 4, 5, 7, 7, 7, 7, 0, 7, 7, 7, 7, 5, 4, 3 -}; - -static const uint16_t atrac3p_sf_huff_code6[16] = { - 0, 2, 3, 0xC, 0x1C, 0x3C, 0x7C, 0x7D, 0, 0x7E, 0x7F, 0x3D, 0x1D, 0xD, 4, 5 -}; - -static const uint8_t atrac3p_sf_huff_bits6[16] = { - 2, 3, 3, 4, 5, 6, 7, 7, 0, 7, 7, 6, 5, 4, 3, 3 -}; - -/** VLC tables for code table indexes */ -static const uint8_t atrac3p_ct_huff_code1[4] = { 0, 2, 6, 7 }; - -static const uint8_t atrac3p_ct_huff_bits1[4] = { 1, 2, 3, 3 }; - -static const uint8_t atrac3p_ct_huff_code2[8] = { 0, 2, 3, 4, 5, 6, 0xE, 0xF }; - -static const uint8_t atrac3p_ct_huff_bits2[8] = { 2, 3, 3, 3, 3, 3, 4, 4 }; - -static const uint8_t atrac3p_ct_huff_xlat1[8] = { 0, 1, 2, 3, 6, 7, 4, 5 }; - -static const uint8_t atrac3p_ct_huff_code3[8] = { - 0, 4, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* Scale factor index 3 - 64 entries */ + 0, 1, 63, 2, 3, 61, 62, 4, 60, 59, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + /* Scale factor index 4 - 64 entries */ + 0, 1, 2, 62, 63, 3, 4, 60, 61, 5, 58, 59, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + /* Scale factor index 5 - 15 entries */ + 0, 1, 13, 14, 15, 2, 12, 3, 4, 5, 6, 7, 9, 10, 11, + /* Scale factor index 6 - 15 entries */ + 0, 1, 2, 14, 15, 3, 13, 4, 5, 6, 7, 9, 10, 11, 12, + /* Scale factor index 7 - 15 entries */ + 0, 1, 15, 2, 14, 3, 13, 4, 5, 6, 7, 9, 10, 11, 12, + /* Scale factor index 8 - 15 entries */ + 0, 1, 2, 14, 15, 3, 13, 4, 12, 5, 11, 6, 7, 9, 10, }; -static const uint8_t atrac3p_ct_huff_bits3[8] = { 1, 3, 4, 4, 4, 4, 4, 4 }; - /* weights for quantized word lengths */ static const int8_t atrac3p_wl_weights[6][32] = { { 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, @@ -437,52 +371,150 @@ }; /** Tables for spectrum coding */ -static const uint8_t huff_a01_cb[14] = { - 1, 12, 1, 0, 0, 1, 7, 0, 19, 5, 13, 21, 6, 8 + +/* If the first entry of a subtable is negative, it means + * that another VLC is to be reused. */ +static const int8_t atrac3p_spectra_cbs[][12] = { + { 1, 0, 0, 1, 7, 0, 19, 5, 13, 21, 6, 8 }, + { 0, 1, 0, 4, 11, 0, 1, 29, 6, 20, 7, 2 }, + { 0, 0, 1, 8, 0, 13, 18, 7, 2, 0, 0, 0 }, + { 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 1, 3, 5, 8, 12, 23, 72, 68, 31, 2 }, + { 0, 1, 3, 2, 6, 4, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 2, 2, 2, 6, 14, 21, 13, 2, 0, 0 }, + { 1, 0, 0, 0, 8, 1, 18, 9, 22, 10, 12, 0 }, + { 0, 0, 0, 0, 16, 11, 32, 19, 1, 2, 0, 0 }, + { 1, 0, 0, 4, 2, 2, 9, 15, 12, 4, 0, 0 }, + { 0, 1, 0, 4, 3, 5, 16, 28, 34, 26, 4, 0 }, + { 0, 0, 0, 0, 9, 12, 16, 44, 98, 42, 4, 0 }, + { 0, 1, 1, 2, 2, 5, 7, 21, 54, 85, 62, 16 }, + { 0, 0, 3, 2, 5, 7, 17, 23, 6, 0, 0, 0 }, + { 1, 0, 0, 2, 6, 0, 7, 21, 15, 17, 8, 4 }, + { 0, 1, 4, 0, 4, 3, 8, 3, 2, 0, 0, 0 }, + { 0, 0, 5, 0, 4, 6, 10, 16, 8, 0, 0, 0 }, + { 0, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 3, 4, 12, 15, 34, 83, 75, 30, 0 }, + { 0, 0, 0, 3, 14, 10, 20, 16, 0, 0, 0, 0 }, + { 1, 0, 3, 1, 0, 4, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 0, 2, 2, 6, 12, 18, 19, 15, 6, 0 }, + { 0, 0, 1, 1, 13, 1, 14, 28, 33, 81, 32, 52 }, + { 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 2, 3, 6, 19, 9, 75, 110, 0, 0 }, + { 0, 0, 1, 3, 5, 5, 13, 27, 69, 96, 35, 2 }, + { 0, 0, 0, 7, 6, 8, 22, 20, 0, 0, 0, 0 }, + { 1, 0, 0, 6, 2, 0, 0, 0, 19, 9, 24, 20 }, + { 0, 0, 1, 2, 13, 1, 31, 13, 16, 4, 0, 0 }, + { 0, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 5, 4, 12, 17, 47, 24, 12, 0, 0 }, + { 0, 2, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 1, 16, 31, 36, 172, 0, 0, 0 }, + { 0, 0, 0, 5, 12, 9, 12, 15, 10, 0, 0, 0 }, + { 0, 1, 0, 6, 2, 6, 18, 4, 26, 6, 12, 0 }, + { 1, 0, 2, 2, 0, 4, 3, 8, 3, 2, 0, 0 }, + { 0, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 4, 7, 12, 19, 21, 58, 0, 0, 0 }, + { 1, 1, 1, 0, 3, 2, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 1, 8, 6, 8, 8, 0, 0, 0, 0, 0 }, + { 0, 0, 1, 5, 7, 8, 16, 22, 4, 0, 0, 0 }, + { 0, 1, 0, 8, 0, 1, 16, 10, 29, 12, 4, 0 }, + { 0, 0, 5, 2, 2, 9, 5, 2, 0, 0, 0, 0 }, + { 0, 0, 1, 1, 10, 4, 16, 29, 46, 75, 74, 0 }, + { 0, 0, 0, 1, 7, 12, 36, 63, 2, 0, 0, 0 }, + { 0, 3, 0, 1, 3, 4, 4, 0, 0, 0, 0, 0 }, + { 0, 1, 2, 2, 6, 8, 6, 3, 1, 2, 0, 0 }, + { 0, 1, 1, 3, 4, 6, 13, 25, 10, 0, 0, 0 }, + { 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 4, 8, 3, 8, 24, 17, 12, 4, 0 }, + { 0, 1, 1, 5, 2, 8, 7, 13, 8, 4, 0, 0 }, + { 1, 0, 0, 4, 0, 4, 5, 9, 30, 45, 21, 2 }, + { 0, 1, 3, 3, 4, 4, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 1, 3, 4, 8, 10, 36, 60, 78, 48, 8 }, + { -6 }, + { 1, 0, 0, 2, 6, 0, 11, 13, 12, 24, 4, 8 }, + { 1, 0, 0, 4, 0, 8, 4, 9, 19, 13, 13, 10 }, + { 1, 0, 0, 4, 0, 5, 12, 13, 14, 0, 0, 0 }, + { 0, 1, 0, 4, 4, 5, 9, 30, 45, 21, 2, 0 }, + { 0, 0, 1, 4, 4, 4, 12, 30, 73, 75, 22, 0 }, + { -5 }, + { 0, 0, 3, 2, 4, 8, 23, 13, 10, 0, 0, 0 }, + { -14 }, + { 0, 0, 1, 3, 12, 0, 30, 9, 18, 8, 0, 0 }, + { -9 }, + { 1, 0, 0, 4, 0, 3, 5, 16, 28, 34, 26, 4 }, + { -11 }, + { 0, 0, 0, 4, 4, 9, 13, 37, 76, 72, 39, 2 }, + { -6 }, + { -28 }, + { -22 }, + { -2 }, + { -31 }, + { -60 }, + { 0, 0, 2, 2, 4, 5, 11, 26, 67, 78, 51, 10 }, + { -6 }, + { -35 }, + { 0, 1, 0, 4, 6, 7, 10, 22, 11, 16, 4, 0 }, + { 0, 1, 0, 0, 4, 11, 8, 28, 92, 97, 13, 2 }, + { -59 }, + { 1, 0, 0, 0, 4, 6, 6, 14, 42, 63, 59, 30 }, + { -75 }, + { 1, 0, 2, 0, 2, 2, 6, 17, 14, 13, 6, 0 }, + { 1, 0, 0, 1, 7, 0, 20, 4, 10, 24, 2, 12 }, + { 1, 0, 1, 3, 2, 3, 7, 4, 4, 0, 0, 0 }, + { 0, 1, 1, 3, 4, 9, 15, 12, 4, 0, 0, 0 }, + { -66 }, + { -32 }, + { -12 }, + { 0, 1, 1, 3, 4, 6, 14, 22, 12, 0, 0, 0 }, + { -42 }, + { 1, 0, 1, 3, 2, 3, 7, 4, 4, 0, 0, 0 }, + { 1, 1, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0 }, + { -17 }, + { -39 }, + { 1, 0, 2, 0, 2, 4, 11, 9, 2, 0, 0, 0 }, + { -62 }, + { -28 }, + { 1, 0, 0, 2, 3, 5, 12, 14, 18, 15, 9, 2 }, + { 1, 1, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 0, 2, 2, 2, 6, 12, 34, 92, 54, 20 }, + { 1, 0, 0, 3, 0, 3, 3, 10, 40, 85, 61, 50 }, + { 0, 1, 2, 1, 4, 7, 10, 26, 12, 0, 0, 0 }, + { 1, 0, 0, 1, 7, 0, 19, 5, 13, 23, 0, 12 }, + { -78 }, + { 1, 0, 0, 0, 1, 4, 9, 4, 103, 110, 24, 0 }, + { 1, 0, 2, 2, 2, 4, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 4, 0, 0, 0, 8, 11, 24, 53, 64, 60 }, + { -47 }, + { 0, 1, 0, 4, 6, 10, 12, 7, 15, 4, 4, 0 }, }; -static const uint8_t huff_a01_xlat[81] = { +static const uint8_t atrac3p_spectra_xlats[] = { + /* Table set A, code table 0, wordlen 1 - 81 entries */ 0x00, 0x03, 0x40, 0xC0, 0x10, 0x30, 0x04, 0x0C, 0x01, 0x50, 0xD0, 0x70, 0xF0, 0xC4, 0x14, 0x34, 0x4C, 0x1C, 0x3C, 0x41, 0xC1, 0x31, 0x05, 0x0D, 0xC3, 0x13, 0x07, 0x0F, 0x44, 0xCC, 0x11, 0x43, 0x33, 0x54, 0x74, 0xDC, 0xFC, 0x71, 0x15, 0x4D, 0xCD, 0x1D, 0xD3, 0xC7, 0x37, 0x3F, 0xD4, 0xF4, 0x5C, 0x7C, 0x51, 0xD1, 0xF1, 0x45, 0xC5, 0x35, 0xDD, 0x3D, 0x53, 0x73, 0xF3, 0x47, 0x17, 0x77, 0x4F, 0xCF, 0x1F, 0x55, 0xF5, 0x7D, 0xD7, 0x5F, - 0xFF, 0xD5, 0x75, 0x5D, 0xFD, 0x57, 0xF7, 0xDF, 0x7F -}; - -static const uint8_t huff_a02_cb[13] = { - 2, 12, 1, 0, 4, 11, 0, 1, 29, 6, 20, 7, 2 -}; - -static const uint8_t huff_a02_xlat[81] = { + 0xFF, 0xD5, 0x75, 0x5D, 0xFD, 0x57, 0xF7, 0xDF, 0x7F, + /* Table set A, code table 0, wordlen 2 - 81 entries */ 0x00, 0x40, 0x10, 0x04, 0x01, 0x50, 0x44, 0x14, 0x54, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55, 0x90, 0x80, 0x20, 0x60, 0x84, 0x94, 0x24, 0x64, 0x08, 0x48, 0x18, 0x58, 0x81, 0x91, 0x21, 0x85, 0x95, 0x65, 0x09, 0x49, 0x19, 0x59, 0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56, 0x88, 0x61, 0x25, 0x29, 0x69, 0x5A, 0xA0, 0xA4, 0x98, 0x28, 0x68, 0xA1, 0xA5, 0x89, 0x99, 0xA9, 0x82, 0x92, 0x22, 0x62, 0x96, 0x26, 0x66, 0x0A, 0x4A, 0x1A, - 0xA8, 0x86, 0xA6, 0x8A, 0x9A, 0x2A, 0x6A, 0xA2, 0xAA -}; - -static const uint8_t huff_a03_cb[9] = { 3, 9, 1, 8, 0, 13, 18, 7, 2 }; - -static const uint8_t huff_a03_xlat[49] = { + 0xA8, 0x86, 0xA6, 0x8A, 0x9A, 0x2A, 0x6A, 0xA2, 0xAA, + /* Table set A, code table 0, wordlen 3 - 49 entries */ 0x00, 0x08, 0x38, 0x01, 0x09, 0x39, 0x07, 0x0F, 0x3F, 0x10, 0x30, 0x11, 0x31, 0x02, 0x0A, 0x3A, 0x05, 0x06, 0x0E, 0x3E, 0x17, 0x37, 0x18, 0x28, 0x19, 0x29, 0x2A, 0x32, 0x03, 0x0B, 0x33, 0x3B, 0x0D, 0x15, 0x3D, 0x16, 0x1E, 0x36, 0x1F, 0x2F, 0x12, 0x1A, 0x13, 0x2B, 0x1D, 0x35, 0x2E, 0x1B, - 0x2D -}; - -static const uint8_t huff_a04_cb[4] = { 2, 3, 2, 4 }; -static const uint8_t huff_a04_xlat[6] = { 1, 2, 0, 3, 4, 5 }; - -static const uint8_t huff_a05_cb[12] = { - 3, 12, 1, 3, 5, 8, 12, 23, 72, 68, 31, 2 -}; - -static const uint8_t huff_a05_xlat[225] = { + 0x2D, + /* Table set A, code table 0, wordlen 4 - 6 entries */ + 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, + /* Table set A, code table 0, wordlen 5 - 225 entries */ 0x00, 0x10, 0xF0, 0x01, 0x11, 0xF1, 0x0F, 0x1F, 0xFF, 0x20, 0xE0, 0xE1, 0x02, 0xF2, 0x0E, 0x1E, 0x2F, 0x30, 0xD0, 0x21, 0x12, 0x22, 0xE2, 0x03, 0x0D, 0x2E, 0xEE, 0xFE, 0xEF, 0x40, 0xC0, 0x31, 0xC1, 0xD1, 0x32, 0xD2, @@ -501,71 +533,40 @@ 0x9C, 0xAC, 0xCC, 0x5D, 0x6D, 0x7D, 0x9D, 0xAD, 0xBD, 0x5E, 0x9E, 0xBE, 0x54, 0x45, 0x55, 0x65, 0x75, 0x95, 0xB5, 0x56, 0x66, 0x76, 0x96, 0xA6, 0x57, 0x67, 0x97, 0xA7, 0x69, 0x79, 0xA9, 0xB9, 0x6A, 0x7A, 0x9A, 0xAA, - 0xBA, 0x5B, 0x9B, 0xAB, 0xBB, 0xCB, 0xBC, 0x77, 0x99 -}; - -static const uint8_t huff_a06_cb[7] = { - 2, 6, 1, 3, 2, 6, 4 -}; - -static const uint8_t huff_a06_xlat[16] = { - 1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 13, 14, 10, 11, 12, 15 -}; - -static const uint8_t huff_a07_cb[11] = { - 2, 10, 1, 2, 2, 2, 6, 14, 21, 13, 2 -}; - -static const uint8_t huff_a07_xlat[63] = { - 0, 1, 63, 2, 62, 3, 61, 4, 5, 6, 58, 59, 60, 7, 8, 9, - 10, 26, 27, 28, 36, 37, 38, 54, 55, 56, 57, 11, 12, 13, 14, 15, - 16, 25, 29, 30, 31, 33, 34, 35, 39, 47, 48, 49, 50, 51, 52, 53, - 17, 18, 19, 20, 21, 22, 23, 41, 42, 43, 44, 45, 46, 24, 40 -}; - -static const uint8_t huff_a11_cb[13] = { - 1, 11, 1, 0, 0, 0, 8, 1, 18, 9, 22, 10, 12 -}; - -static const uint8_t huff_a11_xlat[81] = { + 0xBA, 0x5B, 0x9B, 0xAB, 0xBB, 0xCB, 0xBC, 0x77, 0x99, + /* Table set A, code table 0, wordlen 6 - 16 entries */ + 0x01, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0D, 0x0E, + 0x0A, 0x0B, 0x0C, 0x0F, + /* Table set A, code table 0, wordlen 7 - 63 entries */ + 0x00, 0x01, 0x3F, 0x02, 0x3E, 0x03, 0x3D, 0x04, 0x05, 0x06, 0x3A, 0x3B, + 0x3C, 0x07, 0x08, 0x09, 0x0A, 0x1A, 0x1B, 0x1C, 0x24, 0x25, 0x26, 0x36, + 0x37, 0x38, 0x39, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x19, 0x1D, 0x1E, + 0x1F, 0x21, 0x22, 0x23, 0x27, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, + 0x2E, 0x18, 0x28, + /* Table set A, code table 1, wordlen 1 - 81 entries */ 0x00, 0x40, 0xC0, 0x10, 0x30, 0x04, 0x0C, 0x01, 0x03, 0xD0, 0x50, 0x70, 0xF0, 0xC4, 0x34, 0x4C, 0xCC, 0x1C, 0x41, 0xC1, 0x31, 0x05, 0x0D, 0x43, 0xC3, 0x13, 0x07, 0x0F, 0x44, 0x14, 0x74, 0xDC, 0x3C, 0x11, 0x1D, 0x33, 0x37, 0x54, 0xD4, 0xF4, 0x5C, 0x7C, 0xFC, 0xD1, 0x71, 0xF1, 0x15, 0x35, 0x4D, 0xCD, 0xDD, 0x3D, 0xD3, 0x73, 0x47, 0xC7, 0x17, 0x77, 0x3F, 0x51, 0x45, 0xC5, 0x55, 0x53, 0xF3, 0x4F, 0xCF, 0x1F, 0xFF, 0xD5, 0x75, 0xF5, - 0x5D, 0x7D, 0xFD, 0x57, 0xD7, 0xF7, 0x5F, 0xDF, 0x7F -}; - -static const uint8_t huff_a12_cb[8] = { 5, 10, 16, 11, 32, 19, 1, 2 }; - -static const uint8_t huff_a12_xlat[81] = { + 0x5D, 0x7D, 0xFD, 0x57, 0xD7, 0xF7, 0x5F, 0xDF, 0x7F, + /* Table set A, code table 1, wordlen 2 - 81 entries */ 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55, 0x90, 0x94, 0x58, 0x91, 0x95, 0x19, 0x59, 0x06, 0x46, 0x16, 0x56, 0x80, 0x60, 0x84, 0x24, 0x64, 0xA4, 0x08, 0x48, 0x18, 0x68, 0x81, 0x21, 0x61, 0xA1, 0x85, 0x25, 0x65, 0xA5, 0x09, 0x49, 0x99, 0x69, 0xA9, 0x02, 0x42, 0x12, 0x52, 0x96, 0x26, 0x66, 0x1A, 0x5A, 0x20, 0xA0, 0x88, 0x98, 0x28, 0xA8, 0x89, 0x29, 0x82, 0x92, 0x22, 0x62, 0x86, - 0xA6, 0x0A, 0x4A, 0x9A, 0x6A, 0xAA, 0xA2, 0x8A, 0x2A -}; - -static const uint8_t huff_a13_cb[12] = { - 1, 10, 1, 0, 0, 4, 2, 2, 9, 15, 12, 4 -}; - -static const uint8_t huff_a13_xlat[49] = { + 0xA6, 0x0A, 0x4A, 0x9A, 0x6A, 0xAA, 0xA2, 0x8A, 0x2A, + /* Table set A, code table 1, wordlen 3 - 49 entries */ 0x00, 0x08, 0x38, 0x01, 0x07, 0x39, 0x0F, 0x09, 0x3F, 0x10, 0x30, 0x31, 0x02, 0x3A, 0x06, 0x0E, 0x3E, 0x17, 0x18, 0x28, 0x11, 0x29, 0x0A, 0x32, 0x03, 0x0B, 0x3B, 0x05, 0x0D, 0x3D, 0x16, 0x1F, 0x37, 0x19, 0x12, 0x1A, 0x2A, 0x13, 0x33, 0x15, 0x35, 0x1E, 0x2E, 0x36, 0x2F, 0x1B, 0x2B, 0x1D, - 0x2D -}; - -static const uint8_t huff_a14_cb[12] = { - 2, 11, 1, 0, 4, 3, 5, 16, 28, 34, 26, 4 -}; - -static const uint8_t huff_a14_xlat[121] = { + 0x2D, + /* Table set A, code table 1, wordlen 4 - 121 entries */ 0x00, 0x10, 0xF0, 0x01, 0x0F, 0xF1, 0x1F, 0xFF, 0x20, 0xE0, 0x11, 0x02, 0x0E, 0x30, 0x50, 0xB0, 0xD0, 0x21, 0xE1, 0x12, 0xF2, 0x03, 0x05, 0x0B, 0x0D, 0x1E, 0xFE, 0x2F, 0xEF, 0x40, 0xC0, 0x31, 0x51, 0xB1, 0xC1, 0xD1, @@ -576,12 +577,8 @@ 0xED, 0x3E, 0x4E, 0xBE, 0xDE, 0x4F, 0xCF, 0xC2, 0x33, 0x43, 0xC3, 0xD3, 0x34, 0x44, 0x54, 0xB4, 0xD4, 0x45, 0x55, 0xC5, 0x4B, 0xCB, 0x3C, 0x4C, 0x5C, 0xCC, 0xDC, 0x3D, 0x4D, 0x5D, 0xCD, 0xDD, 0xCE, 0xC4, 0xB5, 0x5B, - 0xBB -}; - -static const uint8_t huff_a15_cb[9] = { 5, 11, 9, 12, 16, 44, 98, 42, 4 }; - -static const uint8_t huff_a15_xlat[225] = { + 0xBB, + /* Table set A, code table 1, wordlen 5 - 225 entries */ 0x00, 0x10, 0xF0, 0x01, 0x11, 0xF1, 0x0F, 0x1F, 0xFF, 0x20, 0xE0, 0x21, 0xE1, 0x02, 0x12, 0xF2, 0x0E, 0x1E, 0xFE, 0x2F, 0xEF, 0x30, 0xD0, 0x31, 0xD1, 0x22, 0xE2, 0x03, 0x13, 0xF3, 0x0D, 0x1D, 0xFD, 0x2E, 0xEE, 0x3F, @@ -600,14 +597,8 @@ 0x54, 0x74, 0x94, 0xB4, 0x45, 0x55, 0x65, 0x75, 0x95, 0xA5, 0xB5, 0xC5, 0x56, 0x66, 0x76, 0x96, 0xA6, 0xB6, 0x47, 0x57, 0x67, 0xA7, 0xB7, 0x49, 0x59, 0x69, 0xA9, 0xB9, 0x6A, 0x7A, 0x9A, 0xAA, 0xBA, 0x4B, 0x5B, 0x6B, - 0x7B, 0x9B, 0xAB, 0xBB, 0x5C, 0x77, 0x97, 0x79, 0x99 -}; - -static const uint8_t huff_a16_cb[13] = { - 2, 12, 1, 1, 2, 2, 5, 7, 21, 54, 85, 62, 16 -}; - -static const uint8_t huff_a16_xlat[256] = { + 0x7B, 0x9B, 0xAB, 0xBB, 0x5C, 0x77, 0x97, 0x79, 0x99, + /* Table set A, code table 1, wordlen 6 - 256 entries */ 0x00, 0x01, 0x10, 0x11, 0x21, 0x12, 0x20, 0x31, 0x02, 0x22, 0x13, 0x30, 0x41, 0x32, 0x03, 0x23, 0x14, 0x24, 0x40, 0x51, 0x61, 0xD1, 0xE1, 0x42, 0x52, 0xD2, 0x33, 0x43, 0xD3, 0x04, 0x34, 0x05, 0x15, 0x25, 0x16, 0x1D, @@ -629,59 +620,37 @@ 0x6B, 0xCB, 0x4C, 0x5C, 0x6C, 0x7C, 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xFC, 0xDD, 0xED, 0xFD, 0xDE, 0xEE, 0xFE, 0x9F, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF, 0xB0, 0xA7, 0xB7, 0xA8, 0xB8, 0xA9, 0xB9, 0x8A, 0x9A, 0xAA, 0xBA, 0x7B, - 0x8B, 0x9B, 0xAB, 0xBB -}; - -static const uint8_t huff_a17_cb[9] = { 3, 9, 3, 2, 5, 7, 17, 23, 6 }; - -static const uint8_t huff_a17_xlat[63] = { - 0, 1, 63, 2, 62, 3, 4, 59, 60, 61, 5, 6, 7, 8, 56, 57, - 58, 9, 10, 11, 12, 13, 14, 26, 27, 36, 37, 38, 50, 51, 52, 53, - 54, 55, 15, 16, 17, 18, 19, 20, 21, 25, 28, 29, 30, 31, 33, 34, - 35, 39, 43, 44, 45, 46, 47, 48, 49, 22, 23, 24, 40, 41, 42 -}; - -static const uint8_t huff_a21_cb[14] = { - 1, 12, 1, 0, 0, 2, 6, 0, 7, 21, 15, 17, 8, 4 -}; - -static const uint8_t huff_a21_xlat[81] = { + 0x8B, 0x9B, 0xAB, 0xBB, + /* Table set A, code table 1, wordlen 7 - 63 entries */ + 0x00, 0x01, 0x3F, 0x02, 0x3E, 0x03, 0x04, 0x3B, 0x3C, 0x3D, 0x05, 0x06, + 0x07, 0x08, 0x38, 0x39, 0x3A, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x1A, + 0x1B, 0x24, 0x25, 0x26, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x0F, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x19, 0x1C, 0x1D, 0x1E, 0x1F, 0x21, 0x22, + 0x23, 0x27, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x16, 0x17, 0x18, + 0x28, 0x29, 0x2A, + /* Table set A, code table 2, wordlen 1 - 81 entries */ 0x00, 0x40, 0xC0, 0x10, 0x30, 0x04, 0x0C, 0x01, 0x03, 0xD0, 0x70, 0x34, 0x1C, 0x0D, 0x13, 0x07, 0x50, 0xF0, 0x44, 0xC4, 0x14, 0x74, 0x4C, 0xCC, 0xDC, 0x3C, 0x41, 0xC1, 0x11, 0x31, 0x05, 0x1D, 0x43, 0xC3, 0x33, 0x37, 0x0F, 0x54, 0xF4, 0xFC, 0xD1, 0x71, 0x15, 0x4D, 0xCD, 0xDD, 0xD3, 0x73, 0x47, 0xC7, 0x77, 0x3F, 0xD4, 0x5C, 0x7C, 0x51, 0xF1, 0x45, 0xC5, 0x55, 0x35, 0x3D, 0x53, 0xF3, 0x17, 0x4F, 0xCF, 0x1F, 0xFF, 0x75, 0xF5, 0x5D, - 0x7D, 0xD7, 0xF7, 0x5F, 0xDF, 0xD5, 0xFD, 0x57, 0x7F -}; - -static const uint8_t huff_a22_cb[10] = { 2, 9, 1, 4, 0, 4, 3, 8, 3, 2 }; - -static const uint8_t huff_a22_xlat[25] = { + 0x7D, 0xD7, 0xF7, 0x5F, 0xDF, 0xD5, 0xFD, 0x57, 0x7F, + /* Table set A, code table 2, wordlen 2 - 25 entries */ 0x00, 0x08, 0x38, 0x01, 0x07, 0x09, 0x39, 0x0F, 0x3F, 0x10, 0x02, 0x06, 0x30, 0x11, 0x31, 0x0A, 0x3A, 0x0E, 0x17, 0x37, 0x32, 0x16, 0x3E, 0x12, - 0x36 -}; - -static const uint8_t huff_a23_cb[9] = { 3, 9, 5, 0, 4, 6, 10, 16, 8 }; - -static const uint8_t huff_a23_xlat[49] = { + 0x36, + /* Table set A, code table 2, wordlen 3 - 49 entries */ 0x00, 0x08, 0x38, 0x01, 0x07, 0x09, 0x39, 0x0F, 0x3F, 0x10, 0x30, 0x02, 0x3A, 0x06, 0x0E, 0x18, 0x28, 0x11, 0x31, 0x0A, 0x03, 0x05, 0x3E, 0x17, 0x37, 0x19, 0x29, 0x12, 0x2A, 0x32, 0x0B, 0x33, 0x3B, 0x0D, 0x15, 0x3D, 0x16, 0x1E, 0x36, 0x1F, 0x2F, 0x1A, 0x13, 0x1B, 0x2B, 0x1D, 0x2D, 0x35, - 0x2E -}; - -static const uint8_t huff_a24_cb[5] = { 2, 4, 3, 1, 2 }; - -static const uint8_t huff_a25_cb[5] = { 2, 4, 1, 5, 2 }; - -static const uint8_t huff_a25_xlat[8] = { 1, 0, 2, 3, 4, 5, 6, 7 }; - -static const uint8_t huff_a26_cb[10] = { 4, 11, 3, 4, 12, 15, 34, 83, 75, 30 }; - -static const uint8_t huff_a26_xlat[256] = { + 0x2E, + /* Table set A, code table 2, wordlen 4 - 6 entries */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + /* Table set A, code table 2, wordlen 5 - 8 entries */ + 0x01, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + /* Table set A, code table 2, wordlen 6 - 256 entries */ 0x00, 0x01, 0x11, 0x10, 0x21, 0x12, 0x22, 0x20, 0x30, 0x31, 0x41, 0x02, 0x32, 0x03, 0x13, 0x23, 0x33, 0x14, 0x24, 0x40, 0x51, 0x61, 0x42, 0x52, 0x43, 0x53, 0x04, 0x34, 0x44, 0x15, 0x25, 0x35, 0x16, 0x26, 0x50, 0x60, @@ -703,43 +672,25 @@ 0x8E, 0x9E, 0xAE, 0xBE, 0x0F, 0x6F, 0x7F, 0x8F, 0x9F, 0xAF, 0xB8, 0xA9, 0xB9, 0x9A, 0xAA, 0xBA, 0xCA, 0x9B, 0xAB, 0xBB, 0xCB, 0xEB, 0xFB, 0xAC, 0xBC, 0xCC, 0xEC, 0xFC, 0xDD, 0xED, 0xFD, 0xCE, 0xDE, 0xEE, 0xFE, 0xBF, - 0xCF, 0xDF, 0xEF, 0xFF -}; - -static const uint8_t huff_a27_cb[7] = { 4, 8, 3, 14, 10, 20, 16 }; - -static const uint8_t huff_a27_xlat[63] = { - 0, 2, 3, 1, 5, 6, 7, 9, 54, 55, 56, 58, 59, 60, 61, 62, - 63, 4, 8, 10, 11, 12, 14, 49, 52, 53, 57, 13, 15, 16, 17, 18, - 19, 22, 23, 25, 26, 30, 39, 43, 44, 45, 46, 47, 48, 50, 51, 20, - 21, 24, 27, 28, 29, 31, 33, 34, 35, 36, 37, 38, 40, 41, 42 -}; - -static const uint8_t huff_a31_cb[8] = { 1, 6, 1, 0, 3, 1, 0, 4 }; - -static const uint8_t huff_a31_xlat[9] = { - 0x00, 0x04, 0x0C, 0x01, 0x03, 0x05, 0x0D, 0x07, 0x0F -}; - -static const uint8_t huff_a32_cb[13] = { - 1, 11, 1, 0, 0, 2, 2, 6, 12, 18, 19, 15, 6 -}; - -static const uint8_t huff_a32_xlat[81] = { + 0xCF, 0xDF, 0xEF, 0xFF, + /* Table set A, code table 2, wordlen 7 - 63 entries */ + 0x00, 0x02, 0x03, 0x01, 0x05, 0x06, 0x07, 0x09, 0x36, 0x37, 0x38, 0x3A, + 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x04, 0x08, 0x0A, 0x0B, 0x0C, 0x0E, 0x31, + 0x34, 0x35, 0x39, 0x0D, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x19, + 0x1A, 0x1E, 0x27, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x32, 0x33, 0x14, + 0x15, 0x18, 0x1B, 0x1C, 0x1D, 0x1F, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x28, 0x29, 0x2A, + /* Table set A, code table 3, wordlen 1 - 9 entries */ + 0x00, 0x04, 0x0C, 0x01, 0x03, 0x05, 0x0D, 0x07, 0x0F, + /* Table set A, code table 3, wordlen 2 - 81 entries */ 0x00, 0x40, 0x01, 0x10, 0x04, 0x80, 0x50, 0x20, 0x14, 0x05, 0x02, 0x90, 0x60, 0x44, 0x54, 0x24, 0x08, 0x18, 0x41, 0x11, 0x15, 0x09, 0x06, 0xA0, 0x84, 0x94, 0x64, 0xA4, 0x48, 0x58, 0x28, 0x51, 0x21, 0x45, 0x55, 0x25, 0x19, 0x12, 0x16, 0x0A, 0x1A, 0x68, 0xA8, 0x81, 0x91, 0x61, 0xA1, 0x85, 0x95, 0x65, 0xA5, 0x49, 0x59, 0x29, 0x69, 0x42, 0x52, 0x46, 0x56, 0x2A, 0x88, 0x98, 0x89, 0x99, 0xA9, 0x82, 0x92, 0x22, 0x62, 0x86, 0x26, 0x66, - 0x4A, 0x5A, 0x6A, 0xA2, 0x96, 0xA6, 0x8A, 0x9A, 0xAA -}; - -static const uint8_t huff_a33_cb[12] = { - 3, 12, 1, 1, 13, 1, 14, 28, 33, 81, 32, 52 -}; - -static const uint8_t huff_a33_xlat[256] = { + 0x4A, 0x5A, 0x6A, 0xA2, 0x96, 0xA6, 0x8A, 0x9A, 0xAA, + /* Table set A, code table 3, wordlen 3 - 256 entries */ 0x00, 0x10, 0x40, 0x50, 0x04, 0x44, 0x14, 0x54, 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55, 0x90, 0x20, 0x94, 0x64, 0x18, 0x21, 0x95, 0x19, 0x69, 0x02, 0x52, 0x06, 0x46, 0x16, 0x80, 0x60, 0x84, 0xD4, 0x24, 0x08, @@ -761,16 +712,10 @@ 0xF6, 0xCA, 0x3A, 0x7A, 0xCE, 0xDE, 0xAE, 0x3E, 0x7E, 0xBE, 0xFE, 0xD3, 0xA3, 0xE3, 0x33, 0x73, 0xF3, 0x87, 0xC7, 0xD7, 0x27, 0x67, 0xE7, 0x77, 0xF7, 0xCB, 0xDB, 0x2B, 0xAB, 0x3B, 0xBB, 0xFB, 0x8F, 0xCF, 0xDF, 0x6F, - 0xAF, 0xEF, 0x7F, 0xFF -}; - -static const uint8_t huff_a34_cb[7] = { 1, 5, 1, 1, 1, 1, 2 }; - -static const uint8_t huff_a34_xlat[6] = { 1, 0, 2, 3, 4, 5 }; - -static const uint8_t huff_a35_cb[11] = { 2, 10, 1, 0, 2, 3, 6, 19, 9, 75, 110 }; - -static const uint8_t huff_a35_xlat[225] = { + 0xAF, 0xEF, 0x7F, 0xFF, + /* Table set A, code table 3, wordlen 4 - 6 entries */ + 0x01, 0x00, 0x02, 0x03, 0x04, 0x05, + /* Table set A, code table 3, wordlen 5 - 225 entries */ 0x00, 0xF0, 0x0F, 0x10, 0x01, 0xFF, 0x20, 0xE0, 0x11, 0xF1, 0x0E, 0x1F, 0x30, 0x40, 0xD0, 0x21, 0xE1, 0x02, 0x12, 0x22, 0xE2, 0xF2, 0x03, 0x13, 0x1E, 0x2E, 0x3E, 0xEE, 0xFE, 0x2F, 0xEF, 0xD2, 0x43, 0xF3, 0x04, 0x0D, @@ -789,14 +734,8 @@ 0xB9, 0xC9, 0xD9, 0xE9, 0x1A, 0x5A, 0x6A, 0x7A, 0x9A, 0xAA, 0xBA, 0xCA, 0x1B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, 0x9B, 0xBB, 0xCB, 0xDB, 0x6C, 0x7C, 0x9C, 0xAC, 0xBC, 0xEC, 0x5D, 0x7D, 0x9D, 0xAD, 0xDD, 0x5E, 0x7E, 0x9E, - 0xAE, 0xBE, 0x4F, 0x5F, 0x6F, 0x9F, 0xAF, 0xBF, 0xCF -}; - -static const uint8_t huff_a36_cb[12] = { - 3, 12, 1, 3, 5, 5, 13, 27, 69, 96, 35, 2 -}; - -static const uint8_t huff_a36_xlat[256] = { + 0xAE, 0xBE, 0x4F, 0x5F, 0x6F, 0x9F, 0xAF, 0xBF, 0xCF, + /* Table set A, code table 3, wordlen 6 - 256 entries */ 0x00, 0x10, 0x01, 0x11, 0x20, 0x21, 0x02, 0x12, 0x22, 0x31, 0x41, 0x32, 0x13, 0x23, 0x30, 0x40, 0x51, 0x42, 0x03, 0x33, 0x43, 0x04, 0x14, 0x24, 0x34, 0x15, 0x25, 0x50, 0x61, 0x71, 0xD1, 0x52, 0x62, 0x72, 0xD2, 0x53, @@ -818,51 +757,33 @@ 0x8F, 0x9F, 0xAF, 0xB0, 0xB6, 0xB7, 0xA8, 0xB8, 0x99, 0xA9, 0xB9, 0xC9, 0x7A, 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0x0B, 0x6B, 0x7B, 0x8B, 0x9B, 0xCB, 0xAC, 0xBC, 0xCC, 0xFC, 0xFD, 0xCE, 0xDE, 0xEE, 0xFE, 0xBF, 0xCF, 0xDF, - 0xEF, 0xFF, 0xAB, 0xBB -}; - -static const uint8_t huff_a37_cb[7] = { 4, 8, 7, 6, 8, 22, 20 }; - -static const uint8_t huff_a37_xlat[63] = { - 0, 1, 2, 3, 61, 62, 63, 4, 5, 6, 58, 59, 60, 7, 8, 9, - 10, 54, 55, 56, 57, 11, 12, 13, 14, 15, 16, 25, 26, 27, 28, 29, - 30, 35, 36, 37, 38, 48, 49, 50, 51, 52, 53, 17, 18, 19, 20, 21, - 22, 23, 24, 31, 33, 34, 39, 40, 41, 42, 43, 44, 45, 46, 47 -}; - -static const uint8_t huff_a41_cb[14] = { - 1, 12, 1, 0, 0, 6, 2, 0, 0, 0, 19, 9, 24, 20 -}; - -static const uint8_t huff_a41_xlat[81] = { + 0xEF, 0xFF, 0xAB, 0xBB, + /* Table set A, code table 3, wordlen 7 - 63 entries */ + 0x00, 0x01, 0x02, 0x03, 0x3D, 0x3E, 0x3F, 0x04, 0x05, 0x06, 0x3A, 0x3B, + 0x3C, 0x07, 0x08, 0x09, 0x0A, 0x36, 0x37, 0x38, 0x39, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x23, 0x24, 0x25, + 0x26, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x1F, 0x21, 0x22, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, + 0x2D, 0x2E, 0x2F, + /* Table set A, code table 4, wordlen 1 - 81 entries */ 0x00, 0x40, 0xC0, 0x10, 0x30, 0x04, 0x0C, 0x01, 0x03, 0x50, 0xD0, 0x70, 0xF0, 0xC4, 0x34, 0x4C, 0xCC, 0x1C, 0x41, 0xC1, 0x31, 0x05, 0x0D, 0x43, 0xC3, 0x13, 0x07, 0x0F, 0x44, 0x14, 0x74, 0xDC, 0x3C, 0x11, 0x1D, 0x33, 0x37, 0x54, 0xD4, 0xF4, 0x5C, 0x7C, 0xFC, 0xD1, 0x71, 0xF1, 0xC5, 0x15, 0x35, 0x4D, 0xCD, 0xDD, 0x3D, 0xD3, 0x73, 0x47, 0xC7, 0x17, 0x77, 0x1F, 0x3F, 0x51, 0x45, 0x55, 0xD5, 0x75, 0xF5, 0x5D, 0x7D, 0xFD, 0x53, 0xF3, - 0x57, 0xD7, 0xF7, 0x4F, 0xCF, 0x5F, 0xDF, 0x7F, 0xFF -}; - -static const uint8_t huff_a42_cb[10] = { 3, 10, 1, 2, 13, 1, 31, 13, 16, 4 }; - -static const uint8_t huff_a42_xlat[81] = { + 0x57, 0xD7, 0xF7, 0x4F, 0xCF, 0x5F, 0xDF, 0x7F, 0xFF, + /* Table set A, code table 4, wordlen 2 - 81 entries */ 0x00, 0x40, 0x01, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55, 0x59, 0x80, 0x90, 0x20, 0x60, 0x84, 0x94, 0x24, 0x64, 0x08, 0x48, 0x18, 0x58, 0x81, 0x91, 0x21, 0x61, 0x85, 0x95, 0x25, 0x65, 0x09, 0x49, 0x19, 0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56, 0xA0, 0xA4, 0x68, 0xA1, 0xA5, 0x99, 0x29, 0x69, 0x96, 0x66, 0x4A, 0x1A, 0x5A, 0x88, 0x98, 0x28, 0x89, 0xA9, 0x82, 0x92, 0x22, 0x62, 0x86, 0x26, - 0xA6, 0x0A, 0x9A, 0x2A, 0x6A, 0xA8, 0xA2, 0x8A, 0xAA -}; - -static const uint8_t huff_a43_cb[5] = { 2, 4, 2, 3, 2 }; - -static const uint8_t huff_a43_xlat[7] = { 0, 7, 1, 2, 6, 3, 5 }; - -static const uint8_t huff_a44_cb[9] = { 4, 10, 5, 4, 12, 17, 47, 24, 12 }; - -static const uint8_t huff_a44_xlat[121] = { + 0xA6, 0x0A, 0x9A, 0x2A, 0x6A, 0xA8, 0xA2, 0x8A, 0xAA, + /* Table set A, code table 4, wordlen 3 - 7 entries */ + 0x00, 0x07, 0x01, 0x02, 0x06, 0x03, 0x05, + /* Table set A, code table 4, wordlen 4 - 121 entries */ 0x00, 0x10, 0xF0, 0x01, 0x0F, 0x11, 0xF1, 0x1F, 0xFF, 0x20, 0xE0, 0x21, 0xE1, 0x02, 0x12, 0xF2, 0x0E, 0x1E, 0xFE, 0x2F, 0xEF, 0x30, 0x50, 0xD0, 0xD1, 0x22, 0xE2, 0x03, 0x13, 0xF3, 0x0D, 0x1D, 0x2D, 0xFD, 0x2E, 0xEE, @@ -873,16 +794,10 @@ 0xCF, 0x42, 0x52, 0x33, 0x53, 0xC3, 0x24, 0xB4, 0xD4, 0x25, 0x35, 0xC5, 0x4B, 0xCB, 0xDB, 0x3C, 0x4C, 0x5C, 0xDC, 0xEC, 0x4D, 0xBD, 0xCD, 0xDD, 0xCE, 0x43, 0x34, 0x44, 0x54, 0xC4, 0x45, 0x55, 0xB5, 0x5B, 0xBB, 0xBC, - 0xCC -}; - -static const uint8_t huff_a45_cb[5] = { 2, 4, 2, 2, 4 }; - -static const uint8_t huff_a45_xlat[8] = { 1, 2, 0, 3, 4, 5, 6, 7 }; - -static const uint8_t huff_a46_cb[7] = { 5, 9, 1, 16, 31, 36, 172 }; - -static const uint8_t huff_a46_xlat[256] = { + 0xCC, + /* Table set A, code table 4, wordlen 5 - 8 entries */ + 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, 0x06, 0x07, + /* Table set A, code table 4, wordlen 6 - 256 entries */ 0x02, 0x00, 0x30, 0x21, 0x31, 0x41, 0x61, 0x12, 0x22, 0x42, 0x62, 0x43, 0x53, 0x24, 0x45, 0x26, 0x27, 0x10, 0x40, 0xB0, 0x01, 0x11, 0x81, 0x32, 0x52, 0x72, 0x92, 0x03, 0x13, 0x33, 0x63, 0x14, 0x34, 0x54, 0x64, 0x74, @@ -904,45 +819,29 @@ 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, 0x8F, 0x9F, 0xAF, 0xBF, - 0xCF, 0xDF, 0xEF, 0xFF -}; - -static const uint8_t huff_a47_cb[8] = { 4, 9, 5, 12, 9, 12, 15, 10 }; - -static const uint8_t huff_a47_xlat[63] = { - 0, 1, 2, 62, 63, 3, 4, 5, 6, 8, 54, 56, 57, 58, 59, 60, - 61, 7, 9, 10, 11, 12, 13, 14, 53, 55, 15, 16, 17, 18, 19, 20, - 21, 36, 37, 39, 42, 52, 22, 25, 28, 35, 38, 40, 41, 43, 45, 46, - 47, 48, 49, 50, 51, 23, 24, 26, 27, 29, 30, 31, 33, 34, 44 -}; - -static const uint8_t huff_a51_cb[12] = { - 2, 11, 1, 0, 6, 2, 6, 18, 4, 26, 6, 12 -}; - -static const uint8_t huff_a51_xlat[81] = { + 0xCF, 0xDF, 0xEF, 0xFF, + /* Table set A, code table 4, wordlen 7 - 63 entries */ + 0x00, 0x01, 0x02, 0x3E, 0x3F, 0x03, 0x04, 0x05, 0x06, 0x08, 0x36, 0x38, + 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x35, 0x37, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x24, 0x25, 0x27, + 0x2A, 0x34, 0x16, 0x19, 0x1C, 0x23, 0x26, 0x28, 0x29, 0x2B, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x17, 0x18, 0x1A, 0x1B, 0x1D, 0x1E, 0x1F, + 0x21, 0x22, 0x2C, + /* Table set A, code table 5, wordlen 1 - 81 entries */ 0x00, 0x40, 0xC0, 0x30, 0x04, 0x01, 0x03, 0x10, 0x0C, 0xD0, 0x70, 0x34, 0x1C, 0x0D, 0x07, 0x50, 0xF0, 0x44, 0xC4, 0x14, 0x4C, 0xCC, 0x3C, 0x41, 0xC1, 0x11, 0x31, 0x05, 0x43, 0xC3, 0x13, 0x33, 0x0F, 0x74, 0xDC, 0x1D, 0x37, 0x54, 0xD4, 0xF4, 0x5C, 0x7C, 0xFC, 0xD1, 0x71, 0xF1, 0xC5, 0x15, 0x35, 0x4D, 0xCD, 0xDD, 0x3D, 0x53, 0xD3, 0x73, 0x47, 0xC7, 0x17, 0x77, 0x4F, 0x1F, 0x3F, 0x51, 0x45, 0x55, 0xF3, 0xCF, 0xFF, 0xD5, 0x75, 0xF5, - 0x5D, 0x7D, 0xFD, 0x57, 0xD7, 0xF7, 0x5F, 0xDF, 0x7F -}; - -static const uint8_t huff_a52_cb[12] = { 1, 10, 1, 0, 2, 2, 0, 4, 3, 8, 3, 2 }; - -static const uint8_t huff_a52_xlat[25] = { + 0x5D, 0x7D, 0xFD, 0x57, 0xD7, 0xF7, 0x5F, 0xDF, 0x7F, + /* Table set A, code table 5, wordlen 2 - 25 entries */ 0x00, 0x08, 0x38, 0x01, 0x07, 0x09, 0x39, 0x0F, 0x3F, 0x10, 0x02, 0x06, 0x30, 0x11, 0x31, 0x0A, 0x3A, 0x0E, 0x17, 0x37, 0x32, 0x16, 0x3E, 0x12, - 0x36 -}; - -static const uint8_t huff_a53_xlat[7] = { 0, 1, 2, 6, 7, 3, 5 }; - -static const uint8_t huff_a54_cb[8] = { 4, 9, 4, 7, 12, 19, 21, 58 }; - -static const uint8_t huff_a54_xlat[121] = { + 0x36, + /* Table set A, code table 5, wordlen 3 - 7 entries */ + 0x00, 0x01, 0x02, 0x06, 0x07, 0x03, 0x05, + /* Table set A, code table 5, wordlen 4 - 121 entries */ 0x00, 0x01, 0x0F, 0x1F, 0x10, 0xE0, 0xF0, 0x11, 0xF1, 0x2F, 0xFF, 0x20, 0x21, 0xE1, 0x02, 0x12, 0xF2, 0x03, 0xF3, 0x0E, 0x2E, 0xFE, 0x3F, 0x30, 0x40, 0xD0, 0xC1, 0xD1, 0x22, 0xC2, 0x33, 0xE3, 0x0C, 0xCC, 0x0D, 0x1D, @@ -953,58 +852,33 @@ 0xE4, 0xF4, 0x05, 0x15, 0x25, 0x35, 0x55, 0xB5, 0xC5, 0xD5, 0xE5, 0x0B, 0x1B, 0x2B, 0x3B, 0xBB, 0xCB, 0xDB, 0xEB, 0x2C, 0x3C, 0x4C, 0x5C, 0xBC, 0xDC, 0xEC, 0xFC, 0x4D, 0x5D, 0xCD, 0xED, 0x4E, 0xBE, 0xCE, 0xDE, 0x4F, - 0x5F -}; - -static const uint8_t huff_a55_cb[8] = { 1, 6, 1, 1, 1, 0, 3, 2 }; - -static const uint8_t huff_a55_xlat[8] = { 0, 1, 2, 3, 6, 7, 4, 5 }; - -static const uint8_t huff_a56_cb[7] = { 3, 7, 1, 8, 6, 8, 8 }; - -static const uint8_t huff_a56_xlat[31] = { - 4, 0, 1, 2, 3, 28, 29, 30, 31, 5, 6, 7, 24, 25, 27, 8, - 9, 14, 19, 21, 22, 23, 26, 10, 11, 12, 13, 15, 17, 18, 20 -}; - -static const uint8_t huff_a57_cb[9] = { 3, 9, 1, 5, 7, 8, 16, 22, 4 }; - -static const uint8_t huff_a57_xlat[63] = { - 0, 1, 2, 61, 62, 63, 3, 4, 5, 6, 58, 59, - 60, 7, 8, 9, 10, 54, 55, 56, 57, 11, 12, 13, - 14, 15, 26, 27, 28, 36, 37, 38, 49, 50, 51, 52, - 53, 16, 17, 18, 19, 20, 21, 23, 24, 25, 29, 30, - 31, 33, 34, 35, 39, 43, 44, 45, 46, 47, 48, 22, - 40, 41, 42 -}; - -static const uint8_t huff_a61_cb[12] = { - 2, 11, 1, 0, 8, 0, 1, 16, 10, 29, 12, 4 -}; - -static const uint8_t huff_a61_xlat[81] = { + 0x5F, + /* Table set A, code table 5, wordlen 5 - 8 entries */ + 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05, + /* Table set A, code table 5, wordlen 6 - 31 entries */ + 0x04, 0x00, 0x01, 0x02, 0x03, 0x1C, 0x1D, 0x1E, 0x1F, 0x05, 0x06, 0x07, + 0x18, 0x19, 0x1B, 0x08, 0x09, 0x0E, 0x13, 0x15, 0x16, 0x17, 0x1A, 0x0A, + 0x0B, 0x0C, 0x0D, 0x0F, 0x11, 0x12, 0x14, + /* Table set A, code table 5, wordlen 7 - 63 entries */ + 0x00, 0x01, 0x02, 0x3D, 0x3E, 0x3F, 0x03, 0x04, 0x05, 0x06, 0x3A, 0x3B, + 0x3C, 0x07, 0x08, 0x09, 0x0A, 0x36, 0x37, 0x38, 0x39, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x1A, 0x1B, 0x1C, 0x24, 0x25, 0x26, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x17, 0x18, 0x19, 0x1D, 0x1E, + 0x1F, 0x21, 0x22, 0x23, 0x27, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x16, + 0x28, 0x29, 0x2A, + /* Table set A, code table 6, wordlen 1 - 81 entries */ 0x00, 0x40, 0xC0, 0x10, 0x30, 0x04, 0x0C, 0x01, 0x03, 0x70, 0x50, 0xD0, 0xF0, 0x44, 0xC4, 0x14, 0x34, 0x4C, 0x1C, 0x3C, 0x31, 0x05, 0x0D, 0x13, 0x07, 0x0F, 0x74, 0xCC, 0xDC, 0xFC, 0x41, 0xC1, 0x11, 0x43, 0xC3, 0x33, 0x54, 0xD4, 0xF4, 0x5C, 0x7C, 0x51, 0xD1, 0x71, 0xF1, 0x45, 0xC5, 0x15, 0x35, 0x4D, 0xCD, 0x1D, 0x3D, 0x53, 0xD3, 0x73, 0xF3, 0x47, 0xC7, 0x17, 0x37, 0x4F, 0xCF, 0x1F, 0x3F, 0x55, 0xD5, 0x75, 0xF5, 0x5D, 0xDD, 0xFD, - 0x57, 0xD7, 0x77, 0xF7, 0xFF, 0x7D, 0x5F, 0xDF, 0x7F -}; - -static const uint8_t huff_a62_cb[8] = { 3, 8, 5, 2, 2, 9, 5, 2 }; - -static const uint8_t huff_a62_xlat[25] = { + 0x57, 0xD7, 0x77, 0xF7, 0xFF, 0x7D, 0x5F, 0xDF, 0x7F, + /* Table set A, code table 6, wordlen 2 - 25 entries */ 0x00, 0x08, 0x38, 0x01, 0x07, 0x39, 0x0F, 0x09, 0x3F, 0x10, 0x30, 0x31, 0x02, 0x3A, 0x06, 0x0E, 0x17, 0x37, 0x11, 0x0A, 0x32, 0x16, 0x3E, 0x12, - 0x36 -}; - -static const uint8_t huff_a63_cb[11] = { - 3, 11, 1, 1, 10, 4, 16, 29, 46, 75, 74 -}; - -static const uint8_t huff_a63_xlat[256] = { + 0x36, + /* Table set A, code table 6, wordlen 3 - 256 entries */ 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x01, 0x41, 0x05, 0x45, 0x55, 0x54, 0x11, 0x51, 0x15, 0x80, 0x90, 0x60, 0x24, 0x64, 0xA4, 0x48, 0x61, 0x95, 0x25, 0xA5, 0x02, 0x42, 0x52, 0x16, 0x56, 0x20, 0x84, 0x94, 0x18, @@ -1026,12 +900,8 @@ 0xBA, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xAE, 0xEE, 0x3E, 0xC3, 0x93, 0xD3, 0xE3, 0x33, 0x73, 0xF3, 0xC7, 0x67, 0xA7, 0xE7, 0x37, 0xB7, 0xF7, 0xCB, 0xDB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, 0x0F, 0x4F, 0x8F, 0x5F, 0xDF, 0x6F, - 0xAF, 0xEF, 0x3F, 0xFF -}; - -static const uint8_t huff_a64_cb[8] = { 4, 9, 1, 7, 12, 36, 63, 2 }; - -static const uint8_t huff_a64_xlat[121] = { + 0xAF, 0xEF, 0x3F, 0xFF, + /* Table set A, code table 6, wordlen 4 - 121 entries */ 0x00, 0x10, 0x20, 0xE0, 0xF0, 0x02, 0x0E, 0xEF, 0x30, 0x01, 0x11, 0x21, 0x31, 0xF1, 0x12, 0xF2, 0x1E, 0xEE, 0xDF, 0xFF, 0x40, 0xC0, 0xD0, 0xD1, 0xE1, 0x22, 0x32, 0x42, 0xD2, 0xE2, 0x03, 0x13, 0x23, 0xB3, 0xC3, 0xE3, @@ -1042,62 +912,38 @@ 0xB5, 0xC5, 0xD5, 0xE5, 0x0B, 0x1B, 0x3B, 0x4B, 0x5B, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0xBC, 0xCC, 0xDC, 0xEC, 0x0D, 0x3D, 0x4D, 0x5D, 0xCD, 0xED, 0x3E, 0x5E, 0xBE, 0xCE, 0x4F, 0xCF, 0x5F, - 0xBF -}; - -static const uint8_t huff_a65_cb[8] = { 2, 7, 3, 0, 1, 3, 4, 4 }; - -static const uint8_t huff_a65_xlat[15] = { - 0, 1, 15, 14, 2, 3, 13, 4, 6, 10, 12, 5, 7, 9, 11 -}; - -static const uint8_t huff_a66_cb[11] = { 2, 10, 1, 2, 2, 6, 8, 6, 3, 1, 2 }; - -static const uint8_t huff_a66_xlat[31] = { - 0, 1, 31, 2, 30, 3, 4, 15, 17, 28, 29, 5, 6, 7, 8, 24, - 25, 26, 27, 9, 10, 11, 21, 22, 23, 12, 19, 20, 13, 14, 18 -}; - -static const uint8_t huff_a67_cb[10] = { 2, 9, 1, 1, 3, 4, 6, 13, 25, 10 }; - -static const uint8_t huff_a67_xlat[63] = { - 0, 1, 2, 62, 63, 3, 4, 60, 61, 5, 6, 7, 57, 58, 59, 8, - 9, 10, 11, 12, 13, 26, 38, 52, 53, 54, 55, 56, 14, 15, 16, 17, - 18, 19, 25, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 39, 45, 46, - 47, 48, 49, 50, 51, 20, 21, 22, 23, 24, 40, 41, 42, 43, 44 -}; - -static const uint8_t huff_a71_cb[5] = { 1, 3, 1, 1, 2 }; - -static const uint8_t huff_a72_cb[12] = { - 2, 11, 1, 0, 4, 8, 3, 8, 24, 17, 12, 4 -}; - -static const uint8_t huff_a72_xlat[81] = { + 0xBF, + /* Table set A, code table 6, wordlen 5 - 15 entries */ + 0x00, 0x01, 0x0F, 0x0E, 0x02, 0x03, 0x0D, 0x04, 0x06, 0x0A, 0x0C, 0x05, + 0x07, 0x09, 0x0B, + /* Table set A, code table 6, wordlen 6 - 31 entries */ + 0x00, 0x01, 0x1F, 0x02, 0x1E, 0x03, 0x04, 0x0F, 0x11, 0x1C, 0x1D, 0x05, + 0x06, 0x07, 0x08, 0x18, 0x19, 0x1A, 0x1B, 0x09, 0x0A, 0x0B, 0x15, 0x16, + 0x17, 0x0C, 0x13, 0x14, 0x0D, 0x0E, 0x12, + /* Table set A, code table 6, wordlen 7 - 63 entries */ + 0x00, 0x01, 0x02, 0x3E, 0x3F, 0x03, 0x04, 0x3C, 0x3D, 0x05, 0x06, 0x07, + 0x39, 0x3A, 0x3B, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x1A, 0x26, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x19, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x14, 0x15, 0x16, 0x17, 0x18, 0x28, 0x29, + 0x2A, 0x2B, 0x2C, + /* Table set A, code table 7, wordlen 1 - 4 entries */ + 0x00, 0x01, 0x02, 0x03, + /* Table set A, code table 7, wordlen 2 - 81 entries */ 0x00, 0x40, 0x10, 0x04, 0x01, 0x50, 0x44, 0x14, 0x54, 0x41, 0x11, 0x05, 0x15, 0x51, 0x45, 0x55, 0x80, 0x90, 0x20, 0x64, 0x08, 0x19, 0x02, 0x06, 0x60, 0x84, 0x94, 0x24, 0x48, 0x18, 0x58, 0x81, 0x91, 0x21, 0x61, 0x85, 0x95, 0x25, 0x65, 0x09, 0x49, 0x59, 0x42, 0x12, 0x52, 0x46, 0x16, 0x56, 0xA0, 0xA4, 0x98, 0x28, 0x68, 0xA1, 0xA5, 0x99, 0x29, 0x69, 0x96, 0x26, 0x66, 0x0A, 0x4A, 0x1A, 0x5A, 0x88, 0xA8, 0x89, 0xA9, 0x82, 0x92, 0x22, - 0x62, 0x86, 0xA6, 0x2A, 0x6A, 0xA2, 0x8A, 0x9A, 0xAA -}; - -static const uint8_t huff_a73_cb[11] = { 2, 10, 1, 1, 5, 2, 8, 7, 13, 8, 4 }; - -static const uint8_t huff_a73_xlat[49] = { + 0x62, 0x86, 0xA6, 0x2A, 0x6A, 0xA2, 0x8A, 0x9A, 0xAA, + /* Table set A, code table 7, wordlen 3 - 49 entries */ 0x00, 0x08, 0x38, 0x01, 0x39, 0x07, 0x0F, 0x09, 0x3F, 0x10, 0x30, 0x31, 0x02, 0x3A, 0x06, 0x0E, 0x17, 0x11, 0x0A, 0x32, 0x0D, 0x16, 0x3E, 0x37, 0x18, 0x28, 0x19, 0x29, 0x12, 0x2A, 0x03, 0x3B, 0x05, 0x15, 0x1E, 0x1F, 0x2F, 0x1A, 0x0B, 0x2B, 0x33, 0x35, 0x3D, 0x2E, 0x36, 0x13, 0x1B, 0x1D, - 0x2D -}; - -static const uint8_t huff_a74_cb[14] = { - 1, 12, 1, 0, 0, 4, 0, 4, 5, 9, 30, 45, 21, 2 -}; - -static const uint8_t huff_a74_xlat[121] = { + 0x2D, + /* Table set A, code table 7, wordlen 4 - 121 entries */ 0x00, 0x10, 0xF0, 0x01, 0x0F, 0x11, 0xF1, 0x1F, 0xFF, 0x20, 0xE0, 0x02, 0xF2, 0x0E, 0x21, 0xE1, 0x12, 0xE2, 0x1E, 0x2E, 0xFE, 0x2F, 0xEF, 0x30, 0x50, 0xB0, 0xC0, 0xD0, 0x31, 0xB1, 0xD1, 0x22, 0xD2, 0x03, 0x13, 0xE3, @@ -1108,20 +954,11 @@ 0xEC, 0xFC, 0x3D, 0x5D, 0xDD, 0xED, 0x4E, 0x5E, 0xBE, 0xCE, 0xDE, 0x4F, 0xBF, 0xCF, 0x43, 0x53, 0x34, 0x54, 0xB4, 0xC4, 0x35, 0x45, 0x55, 0xB5, 0x4B, 0x5B, 0xCB, 0xDB, 0x4C, 0xBC, 0xCC, 0xDC, 0x4D, 0xBD, 0xCD, 0x44, - 0xBB -}; - -static const uint8_t huff_a75_cb[7] = { 2, 6, 1, 3, 3, 4, 4 }; - -static const uint8_t huff_a75_xlat[15] = { - 0, 1, 14, 15, 2, 3, 13, 4, 6, 10, 12, 5, 7, 9, 11 -}; - -static const uint8_t huff_a76_cb[12] = { - 3, 12, 1, 3, 4, 8, 10, 36, 60, 78, 48, 8 -}; - -static const uint8_t huff_a76_xlat[256] = { + 0xBB, + /* Table set A, code table 7, wordlen 5 - 15 entries */ + 0x00, 0x01, 0x0E, 0x0F, 0x02, 0x03, 0x0D, 0x04, 0x06, 0x0A, 0x0C, 0x05, + 0x07, 0x09, 0x0B, + /* Table set A, code table 7, wordlen 6 - 256 entries */ 0x00, 0x10, 0x01, 0x11, 0x20, 0x21, 0x02, 0x12, 0x30, 0x31, 0x41, 0x22, 0x03, 0x13, 0x23, 0x14, 0x40, 0x51, 0x61, 0x32, 0x42, 0x33, 0x04, 0x24, 0x15, 0x16, 0x50, 0x60, 0xD0, 0x71, 0x81, 0xD1, 0xE1, 0xF1, 0x52, 0x62, @@ -1143,52 +980,30 @@ 0xC9, 0x6A, 0x7A, 0x8A, 0x9A, 0xAA, 0xCA, 0xFA, 0x5B, 0x6B, 0x7B, 0x8B, 0xCB, 0xEB, 0xFB, 0x7C, 0x8C, 0x9C, 0xAC, 0xBC, 0xEC, 0xFC, 0xDD, 0xED, 0xFD, 0xCE, 0xDE, 0xEE, 0xFE, 0xBF, 0xCF, 0xDF, 0xB7, 0xBA, 0x9B, 0xAB, - 0xBB, 0xCC, 0xEF, 0xFF -}; - -static const uint8_t huff_b01_cb[14] = { - 1, 12, 1, 0, 0, 2, 6, 0, 11, 13, 12, 24, 4, 8 -}; - -static const uint8_t huff_b01_xlat[81] = { + 0xBB, 0xCC, 0xEF, 0xFF, + /* Table set B, code table 0, wordlen 1 - 81 entries */ 0x00, 0x01, 0x03, 0x40, 0xC0, 0x10, 0x30, 0x04, 0x0C, 0x50, 0xD0, 0x70, 0xF0, 0x34, 0x1C, 0x05, 0x0D, 0x13, 0x07, 0x0F, 0x44, 0xC4, 0x14, 0x4C, 0xCC, 0x3C, 0x41, 0xC1, 0x11, 0x31, 0x43, 0xC3, 0x33, 0x54, 0x74, 0xDC, 0xFC, 0x71, 0x15, 0x4D, 0x1D, 0xD3, 0xC7, 0x37, 0x3F, 0xD4, 0xF4, 0x5C, 0x7C, 0x51, 0xD1, 0xF1, 0x45, 0xC5, 0x55, 0x35, 0xCD, 0xDD, 0x3D, 0x53, 0x73, 0xF3, 0x47, 0x17, 0x77, 0x4F, 0xCF, 0x1F, 0xFF, 0xF5, 0x7D, 0xD7, - 0x5F, 0xD5, 0x75, 0x5D, 0xFD, 0x57, 0xF7, 0xDF, 0x7F -}; - -static const uint8_t huff_b02_cb[14] = { - 1, 12, 1, 0, 0, 4, 0, 8, 4, 9, 19, 13, 13, 10 -}; - -static const uint8_t huff_b02_xlat[81] = { + 0x5F, 0xD5, 0x75, 0x5D, 0xFD, 0x57, 0xF7, 0xDF, 0x7F, + /* Table set B, code table 0, wordlen 2 - 81 entries */ 0x00, 0x40, 0x10, 0x04, 0x01, 0x50, 0x44, 0x14, 0x54, 0x41, 0x11, 0x05, 0x15, 0x80, 0x51, 0x45, 0x55, 0x90, 0x20, 0x60, 0x24, 0x08, 0x18, 0x09, 0x02, 0x06, 0x84, 0x94, 0x64, 0x48, 0x58, 0x81, 0x91, 0x21, 0x61, 0x95, 0x25, 0x65, 0x19, 0x59, 0x42, 0x12, 0x46, 0x16, 0x56, 0xA0, 0xA4, 0x28, 0x68, 0x85, 0xA5, 0x49, 0x29, 0x69, 0x52, 0x0A, 0x1A, 0x5A, 0x88, 0x98, 0xA1, 0x89, 0x99, 0xA9, 0x22, 0x62, 0x96, 0x26, 0x66, 0x4A, 0x6A, 0xA8, - 0x82, 0x92, 0xA2, 0x86, 0xA6, 0x8A, 0x9A, 0x2A, 0xAA -}; - -static const uint8_t huff_b03_cb[11] = { 1, 9, 1, 0, 0, 4, 0, 5, 12, 13, 14 }; - -static const uint8_t huff_b03_xlat[49] = { + 0x82, 0x92, 0xA2, 0x86, 0xA6, 0x8A, 0x9A, 0x2A, 0xAA, + /* Table set B, code table 0, wordlen 3 - 49 entries */ 0x00, 0x08, 0x38, 0x01, 0x07, 0x30, 0x09, 0x39, 0x0F, 0x3F, 0x10, 0x18, 0x28, 0x31, 0x02, 0x3A, 0x03, 0x05, 0x06, 0x0E, 0x17, 0x37, 0x11, 0x19, 0x29, 0x0A, 0x32, 0x0B, 0x3B, 0x0D, 0x15, 0x3D, 0x3E, 0x1F, 0x2F, 0x12, 0x1A, 0x2A, 0x13, 0x1B, 0x2B, 0x33, 0x1D, 0x2D, 0x35, 0x16, 0x1E, 0x2E, - 0x36 -}; - -static const uint8_t huff_b04_cb[12] = { - 2, 11, 1, 0, 4, 4, 5, 9, 30, 45, 21, 2 -}; - -static const uint8_t huff_b04_xlat[121] = { + 0x36, + /* Table set B, code table 0, wordlen 4 - 121 entries */ 0x00, 0x10, 0xF0, 0x01, 0x0F, 0x11, 0xF1, 0x1F, 0xFF, 0x20, 0xE0, 0x02, 0xF2, 0x0E, 0x21, 0xE1, 0x12, 0xE2, 0x1E, 0x2E, 0xFE, 0x2F, 0xEF, 0x30, 0x50, 0xB0, 0xC0, 0xD0, 0x31, 0xB1, 0xD1, 0x22, 0xD2, 0x03, 0x13, 0xE3, @@ -1199,14 +1014,8 @@ 0xEC, 0xFC, 0x3D, 0x5D, 0xDD, 0xED, 0x4E, 0x5E, 0xBE, 0xCE, 0xDE, 0x4F, 0xBF, 0xCF, 0x43, 0x53, 0x34, 0x54, 0xB4, 0xC4, 0x35, 0x45, 0x55, 0xB5, 0x4B, 0x5B, 0xCB, 0xDB, 0x4C, 0xBC, 0xCC, 0xDC, 0x4D, 0xBD, 0xCD, 0x44, - 0xBB -}; - -static const uint8_t huff_b05_cb[11] = { - 3, 11, 1, 4, 4, 4, 12, 30, 73, 75, 22 -}; - -static const uint8_t huff_b05_xlat[225] = { + 0xBB, + /* Table set B, code table 0, wordlen 5 - 225 entries */ 0x00, 0x10, 0xF0, 0x01, 0x0F, 0x11, 0xF1, 0x1F, 0xFF, 0x20, 0xE0, 0x02, 0x0E, 0x30, 0xD0, 0x21, 0xE1, 0x12, 0xF2, 0x03, 0x0D, 0x1E, 0xFE, 0x2F, 0xEF, 0x40, 0x60, 0x70, 0x90, 0xA0, 0xC0, 0x31, 0xD1, 0x22, 0x32, 0xD2, @@ -1225,35 +1034,23 @@ 0x3B, 0x6B, 0x7B, 0x9B, 0xAB, 0xDB, 0xEB, 0x3C, 0x4C, 0x6C, 0x7C, 0x9C, 0xAC, 0xCC, 0xDC, 0x4D, 0x5D, 0x6D, 0xAD, 0xBD, 0xCD, 0x5E, 0xBE, 0x54, 0x45, 0x55, 0xB5, 0xC5, 0x76, 0x96, 0x67, 0x77, 0x97, 0xA7, 0x79, 0x99, - 0xA9, 0x7A, 0x9A, 0x4B, 0x5B, 0xBB, 0xCB, 0x5C, 0xBC -}; - -static const uint8_t huff_b07_cb[9] = { 3, 9, 3, 2, 4, 8, 23, 13, 10 }; - -static const uint8_t huff_b07_xlat[63] = { - 0, 1, 63, 2, 62, 3, 4, 60, 61, 5, 6, 7, 8, 56, 57, 58, - 59, 9, 10, 11, 12, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, - 37, 38, 39, 51, 52, 53, 54, 55, 13, 14, 15, 16, 17, 18, 19, 45, - 46, 47, 48, 49, 50, 20, 21, 22, 23, 24, 40, 41, 42, 43, 44 -}; - -static const uint8_t huff_b12_cb[10] = { 3, 10, 1, 3, 12, 0, 30, 9, 18, 8 }; - -static const uint8_t huff_b12_xlat[81] = { + 0xA9, 0x7A, 0x9A, 0x4B, 0x5B, 0xBB, 0xCB, 0x5C, 0xBC, + /* Table set B, code table 0, wordlen 7 - 63 entries */ + 0x00, 0x01, 0x3F, 0x02, 0x3E, 0x03, 0x04, 0x3C, 0x3D, 0x05, 0x06, 0x07, + 0x08, 0x38, 0x39, 0x3A, 0x3B, 0x09, 0x0A, 0x0B, 0x0C, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x2D, + 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x14, 0x15, 0x16, 0x17, 0x18, 0x28, 0x29, + 0x2A, 0x2B, 0x2C, + /* Table set B, code table 1, wordlen 2 - 81 entries */ 0x00, 0x40, 0x04, 0x01, 0x10, 0x50, 0x44, 0x14, 0x54, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55, 0x80, 0x90, 0x20, 0x60, 0x84, 0x94, 0x24, 0x64, 0x08, 0x48, 0x18, 0x81, 0x91, 0x61, 0x85, 0x95, 0x25, 0x65, 0x09, 0x49, 0x19, 0x59, 0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56, 0xA4, 0x58, 0x68, 0x21, 0xA5, 0x29, 0x69, 0x1A, 0x5A, 0xA0, 0x88, 0x98, 0x28, 0xA1, 0x89, 0x99, 0xA9, 0x92, 0x22, 0x62, 0x86, 0x96, 0x26, 0x66, 0x0A, 0x4A, - 0x6A, 0xA8, 0x82, 0xA2, 0xA6, 0x8A, 0x9A, 0x2A, 0xAA -}; - -static const uint8_t huff_b14_cb[14] = { - 1, 12, 1, 0, 0, 4, 0, 3, 5, 16, 28, 34, 26, 4 -}; - -static const uint8_t huff_b14_xlat[121] = { + 0x6A, 0xA8, 0x82, 0xA2, 0xA6, 0x8A, 0x9A, 0x2A, 0xAA, + /* Table set B, code table 1, wordlen 4 - 121 entries */ 0x00, 0x10, 0xF0, 0x01, 0x0F, 0xF1, 0x1F, 0xFF, 0x20, 0xE0, 0x11, 0x02, 0x0E, 0x30, 0x50, 0xB0, 0xD0, 0x21, 0xE1, 0x12, 0xF2, 0x03, 0x05, 0x0B, 0x0D, 0x1E, 0xFE, 0x2F, 0xEF, 0x40, 0xC0, 0x31, 0x51, 0xB1, 0xC1, 0xD1, @@ -1264,14 +1061,8 @@ 0xED, 0x3E, 0x4E, 0xBE, 0xDE, 0x4F, 0xCF, 0xC2, 0x33, 0x43, 0xC3, 0xD3, 0x34, 0x44, 0x54, 0xB4, 0xD4, 0x45, 0x55, 0xC5, 0x4B, 0xCB, 0x3C, 0x4C, 0x5C, 0xCC, 0xDC, 0x3D, 0x4D, 0x5D, 0xCD, 0xDD, 0xCE, 0xC4, 0xB5, 0x5B, - 0xBB -}; - -static const uint8_t huff_b16_cb[11] = { - 4, 12, 4, 4, 9, 13, 37, 76, 72, 39, 2 -}; - -static const uint8_t huff_b16_xlat[256] = { + 0xBB, + /* Table set B, code table 1, wordlen 6 - 256 entries */ 0x00, 0x10, 0x01, 0x11, 0x20, 0x21, 0x02, 0x12, 0x30, 0x31, 0x41, 0x22, 0x32, 0x03, 0x13, 0x23, 0x14, 0x40, 0x51, 0x61, 0x42, 0x52, 0x33, 0x43, 0x04, 0x24, 0x34, 0x15, 0x25, 0x16, 0x50, 0x60, 0x70, 0x71, 0x81, 0xD1, @@ -1293,14 +1084,8 @@ 0xA8, 0xB8, 0xC8, 0x99, 0xA9, 0xB9, 0xC9, 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xFA, 0x6B, 0x7B, 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xFB, 0x9C, 0xAC, 0xBC, 0xCC, 0xEC, 0xFC, 0xDD, 0xED, 0xFD, 0xCE, 0xDE, 0xEE, 0xFE, 0xAF, 0xBF, - 0xCF, 0xDF, 0xEF, 0xFF -}; - -static const uint8_t huff_b26_cb[12] = { - 3, 12, 2, 2, 4, 5, 11, 26, 67, 78, 51, 10 -}; - -static const uint8_t huff_b26_xlat[256] = { + 0xCF, 0xDF, 0xEF, 0xFF, + /* Table set B, code table 2, wordlen 6 - 256 entries */ 0x00, 0x01, 0x10, 0x11, 0x20, 0x21, 0x02, 0x12, 0x30, 0x31, 0x22, 0x03, 0x13, 0x40, 0x41, 0x51, 0x32, 0x42, 0x23, 0x33, 0x04, 0x14, 0x24, 0x15, 0x50, 0x61, 0x71, 0xD1, 0xE1, 0x52, 0x62, 0xD2, 0x43, 0x53, 0xD3, 0x34, @@ -1322,28 +1107,16 @@ 0x5A, 0x6A, 0x7A, 0x9A, 0xCA, 0xFA, 0x4B, 0x5B, 0x6B, 0x7B, 0xCB, 0xFB, 0x7C, 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xEC, 0xFC, 0xDD, 0xED, 0xFD, 0xDE, 0xEE, 0xFE, 0xBF, 0xCF, 0xDF, 0xEF, 0xB8, 0xB9, 0x8A, 0xAA, 0xBA, 0x8B, - 0x9B, 0xAB, 0xBB, 0xFF -}; - -static const uint8_t huff_b32_cb[12] = { - 2, 11, 1, 0, 4, 6, 7, 10, 22, 11, 16, 4 -}; - -static const uint8_t huff_b32_xlat[81] = { + 0x9B, 0xAB, 0xBB, 0xFF, + /* Table set B, code table 3, wordlen 2 - 81 entries */ 0x00, 0x40, 0x10, 0x04, 0x01, 0x50, 0x44, 0x14, 0x41, 0x11, 0x05, 0x80, 0x54, 0x51, 0x45, 0x15, 0x55, 0x02, 0x90, 0x20, 0x60, 0x84, 0x24, 0x08, 0x18, 0x09, 0x12, 0x06, 0xA0, 0x94, 0x64, 0x48, 0x58, 0x81, 0x91, 0x21, 0x61, 0x85, 0x95, 0x25, 0x65, 0x49, 0x19, 0x59, 0x42, 0x52, 0x46, 0x16, 0x56, 0x0A, 0xA4, 0x28, 0x68, 0xA1, 0xA5, 0x29, 0x69, 0x26, 0x4A, 0x1A, 0x5A, 0x88, 0x98, 0xA8, 0x89, 0x99, 0xA9, 0x82, 0x92, 0x22, 0x62, 0x86, - 0x96, 0x66, 0x9A, 0x2A, 0x6A, 0xA2, 0xA6, 0x8A, 0xAA -}; - -static const uint8_t huff_b33_cb[13] = { - 2, 12, 1, 0, 0, 4, 11, 8, 28, 92, 97, 13, 2 -}; - -static const uint8_t huff_b33_xlat[256] = { + 0x96, 0x66, 0x9A, 0x2A, 0x6A, 0xA2, 0xA6, 0x8A, 0xAA, + /* Table set B, code table 3, wordlen 3 - 256 entries */ 0x00, 0x40, 0x10, 0x04, 0x01, 0x50, 0x44, 0x14, 0x54, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55, 0x20, 0x95, 0x65, 0x49, 0x59, 0x52, 0x46, 0x16, 0x80, 0x90, 0x60, 0x84, 0x94, 0x24, 0x64, 0xA4, 0x08, 0x48, 0x18, 0x58, @@ -1365,14 +1138,8 @@ 0x93, 0xD3, 0x23, 0x63, 0xA3, 0xE3, 0x73, 0xB3, 0xF3, 0x07, 0x47, 0x87, 0xC7, 0x27, 0x37, 0x4B, 0x8B, 0xCB, 0x1B, 0x2B, 0x3B, 0x4F, 0x8F, 0xCF, 0x1F, 0x70, 0xB0, 0xF0, 0x8C, 0xCC, 0x2C, 0x3C, 0xC2, 0x32, 0xC3, 0x0F, - 0x2F, 0x3F, 0x33, 0x0B -}; - -static const uint8_t huff_b35_cb[14] = { - 1, 12, 1, 0, 0, 0, 4, 6, 6, 14, 42, 63, 59, 30 -}; - -static const uint8_t huff_b35_xlat[225] = { + 0x2F, 0x3F, 0x33, 0x0B, + /* Table set B, code table 3, wordlen 5 - 225 entries */ 0x00, 0x10, 0xF0, 0x01, 0x0F, 0x11, 0xF1, 0x02, 0x0E, 0x1F, 0xFF, 0x20, 0xE0, 0x21, 0xF2, 0xFE, 0xEF, 0x30, 0xD0, 0xE1, 0x12, 0x22, 0xE2, 0x03, 0x0D, 0x1D, 0x1E, 0x2E, 0xEE, 0x2F, 0xDF, 0x40, 0x60, 0x70, 0x90, 0xA0, @@ -1391,107 +1158,62 @@ 0xDB, 0xEB, 0x3C, 0x6C, 0x9C, 0xAC, 0xCC, 0xDC, 0x5D, 0x9D, 0xAD, 0xBD, 0xCD, 0xBE, 0xBF, 0x53, 0x54, 0xB4, 0xC4, 0x45, 0x55, 0xB5, 0xC5, 0xD5, 0x56, 0x67, 0x77, 0x97, 0x49, 0x69, 0x79, 0x99, 0x5A, 0x7A, 0x9A, 0xAA, - 0xBA, 0x4B, 0x5B, 0x7B, 0xBB, 0xCB, 0x4C, 0x5C, 0xBC -}; - -static const uint8_t huff_b37_cb[13] = { - 1, 11, 1, 0, 2, 0, 2, 2, 6, 17, 14, 13, 6 -}; - -static const uint8_t huff_b37_xlat[63] = { - 0, 1, 63, 2, 62, 3, 61, 4, 5, 6, 58, 59, 60, 7, 8, 9, - 10, 25, 26, 27, 28, 29, 34, 35, 37, 38, 39, 55, 56, 57, 11, 13, - 14, 15, 30, 31, 33, 36, 49, 50, 51, 52, 53, 54, 12, 16, 17, 18, - 19, 21, 41, 43, 44, 45, 46, 47, 48, 20, 22, 23, 24, 40, 42 -}; - -static const uint8_t huff_b41_cb[14] = { - 1, 12, 1, 0, 0, 1, 7, 0, 20, 4, 10, 24, 2, 12 -}; - -static const uint8_t huff_b41_xlat[81] = { + 0xBA, 0x4B, 0x5B, 0x7B, 0xBB, 0xCB, 0x4C, 0x5C, 0xBC, + /* Table set B, code table 3, wordlen 7 - 63 entries */ + 0x00, 0x01, 0x3F, 0x02, 0x3E, 0x03, 0x3D, 0x04, 0x05, 0x06, 0x3A, 0x3B, + 0x3C, 0x07, 0x08, 0x09, 0x0A, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x22, 0x23, + 0x25, 0x26, 0x27, 0x37, 0x38, 0x39, 0x0B, 0x0D, 0x0E, 0x0F, 0x1E, 0x1F, + 0x21, 0x24, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x0C, 0x10, 0x11, 0x12, + 0x13, 0x15, 0x29, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x14, 0x16, 0x17, + 0x18, 0x28, 0x2A, + /* Table set B, code table 4, wordlen 1 - 81 entries */ 0x00, 0x01, 0x40, 0xC0, 0x10, 0x30, 0x04, 0x0C, 0x03, 0x50, 0xD0, 0x70, 0xF0, 0xC4, 0x14, 0x34, 0x4C, 0x1C, 0x3C, 0xC1, 0x11, 0x31, 0x05, 0x0D, 0xC3, 0x13, 0x33, 0x07, 0x0F, 0x44, 0xCC, 0x41, 0x43, 0x54, 0x74, 0xDC, 0xFC, 0x71, 0x15, 0x4D, 0x1D, 0x37, 0x3F, 0xD4, 0xF4, 0x5C, 0x7C, 0x51, 0xD1, 0xF1, 0x45, 0xC5, 0x35, 0xCD, 0xDD, 0x3D, 0x53, 0xD3, 0x73, 0xF3, 0x47, 0xC7, 0x17, 0x77, 0x4F, 0xCF, 0x1F, 0x55, 0xFF, 0xD5, 0x75, 0xF5, - 0x5D, 0x7D, 0xFD, 0x57, 0xD7, 0xF7, 0x5F, 0xDF, 0x7F -}; - -static const uint8_t huff_b42_cb[11] = { 1, 9, 1, 0, 1, 3, 2, 3, 7, 4, 4 }; - -static const uint8_t huff_b42_xlat[25] = { + 0x5D, 0x7D, 0xFD, 0x57, 0xD7, 0xF7, 0x5F, 0xDF, 0x7F, + /* Table set B, code table 4, wordlen 2 - 25 entries */ 0x00, 0x07, 0x08, 0x38, 0x01, 0x39, 0x0F, 0x10, 0x09, 0x3F, 0x30, 0x31, 0x02, 0x3A, 0x06, 0x0E, 0x17, 0x11, 0x0A, 0x3E, 0x37, 0x12, 0x32, 0x16, - 0x36 -}; - -static const uint8_t huff_b43_cb[10] = { 2, 9, 1, 1, 3, 4, 9, 15, 12, 4 }; - -static const uint8_t huff_b43_xlat[49] = { + 0x36, + /* Table set B, code table 4, wordlen 3 - 49 entries */ 0x00, 0x07, 0x08, 0x38, 0x01, 0x09, 0x39, 0x0F, 0x3F, 0x10, 0x30, 0x31, 0x02, 0x3A, 0x06, 0x0E, 0x17, 0x37, 0x18, 0x28, 0x11, 0x19, 0x29, 0x0A, 0x03, 0x0B, 0x3B, 0x05, 0x0D, 0x3D, 0x3E, 0x1F, 0x2F, 0x12, 0x1A, 0x2A, 0x32, 0x13, 0x33, 0x15, 0x35, 0x16, 0x1E, 0x2E, 0x36, 0x1B, 0x2B, 0x1D, - 0x2D -}; - -static const uint8_t huff_b47_cb[10] = { 2, 9, 1, 1, 3, 4, 6, 14, 22, 12 }; - -static const uint8_t huff_b47_xlat[63] = { - 0, 1, 2, 62, 63, 3, 4, 60, 61, 5, 6, 7, 57, 58, 59, 8, - 9, 10, 11, 12, 26, 27, 37, 38, 52, 53, 54, 55, 56, 13, 14, 15, - 16, 17, 18, 25, 28, 29, 30, 31, 33, 34, 35, 36, 39, 46, 47, 48, - 49, 50, 51, 19, 20, 21, 22, 23, 24, 40, 41, 42, 43, 44, 45 -}; - -static const uint8_t huff_b52_cb[11] = { 1, 9, 1, 0, 1, 3, 2, 3, 7, 4, 4 }; - -static const uint8_t huff_b52_xlat[25] = { + 0x2D, + /* Table set B, code table 4, wordlen 7 - 63 entries */ + 0x00, 0x01, 0x02, 0x3E, 0x3F, 0x03, 0x04, 0x3C, 0x3D, 0x05, 0x06, 0x07, + 0x39, 0x3A, 0x3B, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x1A, 0x1B, 0x25, 0x26, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x19, + 0x1C, 0x1D, 0x1E, 0x1F, 0x21, 0x22, 0x23, 0x24, 0x27, 0x2E, 0x2F, 0x30, + 0x31, 0x32, 0x33, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x28, 0x29, 0x2A, + 0x2B, 0x2C, 0x2D, + /* Table set B, code table 5, wordlen 2 - 25 entries */ 0x00, 0x01, 0x08, 0x38, 0x07, 0x39, 0x0F, 0x30, 0x09, 0x3F, 0x10, 0x31, 0x02, 0x3A, 0x06, 0x0E, 0x17, 0x11, 0x0A, 0x3E, 0x37, 0x12, 0x32, 0x16, - 0x36 -}; - -static const uint8_t huff_b53_cb[7] = { 1, 5, 1, 1, 1, 0, 4 }; // same as b63!!! - -static const uint8_t huff_b53_xlat[7] = { 0, 7, 1, 2, 3, 5, 6 }; - -static const uint8_t huff_b56_cb[11] = { 1, 9, 1, 0, 2, 0, 2, 4, 11, 9, 2 }; - -static const uint8_t huff_b56_xlat[31] = { - 0, 1, 31, 2, 30, 3, 4, 13, 29, 5, 6, 7, 14, 15, 17, 18, - 19, 26, 27, 28, 8, 9, 12, 20, 21, 22, 23, 24, 25, 10, 11 -}; - -static const uint8_t huff_b62_cb[14] = { - 1, 12, 1, 0, 0, 2, 3, 5, 12, 14, 18, 15, 9, 2 -}; - -static const uint8_t huff_b62_xlat[81] = { + 0x36, + /* Table set B, code table 5, wordlen 3 - 7 entries */ + 0x00, 0x07, 0x01, 0x02, 0x03, 0x05, 0x06, + /* Table set B, code table 5, wordlen 6 - 31 entries */ + 0x00, 0x01, 0x1F, 0x02, 0x1E, 0x03, 0x04, 0x0D, 0x1D, 0x05, 0x06, 0x07, + 0x0E, 0x0F, 0x11, 0x12, 0x13, 0x1A, 0x1B, 0x1C, 0x08, 0x09, 0x0C, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x0A, 0x0B, + /* Table set B, code table 6, wordlen 2 - 81 entries */ 0x00, 0x40, 0x01, 0x10, 0x04, 0x02, 0x80, 0x50, 0x90, 0x05, 0x06, 0x20, 0x60, 0x44, 0x14, 0x54, 0x24, 0x08, 0x18, 0x41, 0x11, 0x15, 0x09, 0xA0, 0x84, 0x94, 0x64, 0xA4, 0x28, 0x51, 0x45, 0x55, 0x19, 0x12, 0x16, 0x0A, 0x1A, 0x48, 0x58, 0x68, 0x81, 0x91, 0x21, 0x61, 0x85, 0x95, 0x25, 0x65, 0x49, 0x59, 0x29, 0x69, 0x42, 0x46, 0x56, 0x88, 0x98, 0xA8, 0xA1, 0xA5, 0x99, 0xA9, 0x52, 0x22, 0x26, 0x66, 0x4A, 0x5A, 0x2A, 0x6A, 0x89, 0x82, - 0x92, 0x62, 0x86, 0x96, 0xA6, 0x8A, 0xAA, 0xA2, 0x9A -}; - -static const uint8_t huff_b63_cb[7] = { 1, 5, 1, 1, 1, 0, 4 }; - -static const uint8_t huff_b63_xlat[7] = { 0, 1, 7, 2, 3, 5, 6 }; - -static const uint8_t huff_b64_cb[7] = { 1, 5, 1, 1, 1, 1, 2 }; - -static const uint8_t huff_b64_xlat[6] = { 1, 0, 2, 5, 3, 4 }; - -static const uint8_t huff_b65_cb[14] = { - 1, 12, 1, 0, 0, 2, 2, 2, 6, 12, 34, 92, 54, 20 -}; - -static const uint8_t huff_b65_xlat[225] = { + 0x92, 0x62, 0x86, 0x96, 0xA6, 0x8A, 0xAA, 0xA2, 0x9A, + /* Table set B, code table 6, wordlen 3 - 7 entries */ + 0x00, 0x01, 0x07, 0x02, 0x03, 0x05, 0x06, + /* Table set B, code table 6, wordlen 4 - 6 entries */ + 0x01, 0x00, 0x02, 0x05, 0x03, 0x04, + /* Table set B, code table 6, wordlen 5 - 225 entries */ 0x00, 0xF0, 0x01, 0x10, 0x0F, 0x11, 0xF1, 0x20, 0xE0, 0x02, 0x0E, 0x1F, 0xFF, 0xD0, 0x21, 0xE1, 0x12, 0xF2, 0x07, 0x0A, 0x0D, 0x1E, 0xFE, 0x2F, 0xEF, 0x30, 0x70, 0x90, 0xA0, 0xC0, 0x71, 0x91, 0xC1, 0xD1, 0x32, 0x92, @@ -1510,14 +1232,8 @@ 0xAA, 0xBA, 0x2B, 0x4B, 0x7B, 0x9B, 0xAB, 0xDB, 0x3C, 0x4C, 0x7C, 0x9C, 0xAC, 0xBC, 0xCC, 0x3D, 0x5D, 0x7D, 0xBD, 0xCD, 0x5E, 0xBE, 0xDE, 0xBF, 0xCF, 0x53, 0x64, 0xB4, 0xC4, 0x35, 0x55, 0xC5, 0xD5, 0x97, 0xB7, 0xC7, - 0x79, 0x99, 0x5B, 0xBB, 0xCB, 0x5C, 0xDC, 0x7F, 0xAF -}; - -static const uint8_t huff_b66_cb[14] = { - 1, 12, 1, 0, 0, 3, 0, 3, 3, 10, 40, 85, 61, 50 -}; - -static const uint8_t huff_b66_xlat[256] = { + 0x79, 0x99, 0x5B, 0xBB, 0xCB, 0x5C, 0xDC, 0x7F, 0xAF, + /* Table set B, code table 6, wordlen 6 - 256 entries */ 0x00, 0x10, 0x01, 0x11, 0x21, 0x02, 0x12, 0x20, 0x22, 0x13, 0x30, 0x31, 0x41, 0xD1, 0xE1, 0x32, 0x52, 0x03, 0x23, 0x2D, 0x40, 0x50, 0x60, 0x80, 0xD0, 0xE0, 0x51, 0x61, 0xF1, 0x42, 0x62, 0xD2, 0xE2, 0xF2, 0x33, 0x43, @@ -1539,37 +1255,23 @@ 0x47, 0x87, 0xB7, 0xC7, 0x58, 0x68, 0x78, 0xA8, 0xB8, 0xC8, 0x39, 0x69, 0x89, 0xA9, 0xB9, 0xC9, 0xD9, 0x2A, 0x5A, 0x6A, 0x7A, 0x9A, 0xAA, 0x3B, 0x4B, 0x5B, 0x6B, 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0x6C, 0x9C, 0xDC, 0xFC, - 0xCD, 0xED, 0xAE, 0xDE -}; - -static const uint8_t huff_b67_cb[10] = { 2, 9, 1, 2, 1, 4, 7, 10, 26, 12 }; - -static const uint8_t huff_b67_xlat[63] = { - 0, 1, 63, 62, 2, 3, 60, 61, 4, 5, 6, 7, 57, 58, 59, 8, - 9, 10, 11, 12, 52, 53, 54, 55, 56, 13, 14, 15, 16, 17, 18, 25, - 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 46, 47, 48, - 49, 50, 51, 19, 20, 21, 22, 23, 24, 40, 41, 42, 43, 44, 45 -}; - -static const uint8_t huff_b71_cb[14] = { - 1, 12, 1, 0, 0, 1, 7, 0, 19, 5, 13, 23, 0, 12 -}; - -static const uint8_t huff_b71_xlat[81] = { + 0xCD, 0xED, 0xAE, 0xDE, + /* Table set B, code table 6, wordlen 7 - 63 entries */ + 0x00, 0x01, 0x3F, 0x3E, 0x02, 0x03, 0x3C, 0x3D, 0x04, 0x05, 0x06, 0x07, + 0x39, 0x3A, 0x3B, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, + 0x1E, 0x1F, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2E, 0x2F, 0x30, + 0x31, 0x32, 0x33, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x28, 0x29, 0x2A, + 0x2B, 0x2C, 0x2D, + /* Table set B, code table 7, wordlen 1 - 81 entries */ 0x00, 0x03, 0x40, 0xC0, 0x10, 0x30, 0x04, 0x0C, 0x01, 0x50, 0xD0, 0x70, 0xF0, 0xC4, 0x14, 0x34, 0x4C, 0x1C, 0x3C, 0xC1, 0x11, 0x31, 0x05, 0x0D, 0x13, 0x33, 0x07, 0x0F, 0x44, 0xCC, 0x41, 0x43, 0xC3, 0x54, 0x74, 0xDC, 0xFC, 0xF1, 0xC5, 0x15, 0x1D, 0x53, 0xC7, 0x37, 0x4F, 0x3F, 0xD4, 0xF4, 0x5C, 0x7C, 0x51, 0xD1, 0x71, 0x45, 0x55, 0x35, 0x4D, 0xCD, 0xDD, 0x3D, 0xD3, 0x73, 0xF3, 0x47, 0x17, 0x77, 0xCF, 0x1F, 0xFF, 0xD5, 0x75, 0xF5, - 0x5D, 0x7D, 0xFD, 0x57, 0xD7, 0xF7, 0x5F, 0xDF, 0x7F -}; - -static const uint8_t huff_b73_cb[13] = { - 1, 11, 1, 0, 0, 0, 1, 4, 9, 4, 103, 110, 24 -}; - -static const uint8_t huff_b73_xlat[256] = { + 0x5D, 0x7D, 0xFD, 0x57, 0xD7, 0xF7, 0x5F, 0xDF, 0x7F, + /* Table set B, code table 7, wordlen 3 - 256 entries */ 0x00, 0x40, 0x10, 0x04, 0x01, 0x05, 0x50, 0x14, 0x54, 0x41, 0x11, 0x51, 0x45, 0x15, 0x55, 0x44, 0x95, 0x6A, 0x03, 0x80, 0xC0, 0x90, 0xD0, 0x94, 0xD4, 0x24, 0x64, 0x58, 0x91, 0xA1, 0x85, 0xD5, 0x25, 0x65, 0xA5, 0xE5, @@ -1591,20 +1293,10 @@ 0x27, 0x37, 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x2B, 0x3B, 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x2F, 0x3F, 0xA0, 0xE0, 0x30, 0x34, 0x48, 0xC8, 0x28, 0x38, 0x0C, 0x4C, 0x8C, 0xCC, 0x2C, 0xC1, 0x31, 0x82, 0xC2, 0x12, 0x32, 0x43, - 0x83, 0xC3, 0x23, 0x33 -}; - -static const uint8_t huff_b74_cb[8] = { 1, 6, 1, 0, 2, 2, 2, 4 }; - -static const uint8_t huff_b74_xlat[11] = { - 0, 1, 15, 2, 14, 5, 13, 3, 4, 11, 12 -}; - -static const uint8_t huff_b75_cb[13] = { - 2, 12, 1, 4, 0, 0, 0, 8, 11, 24, 53, 64, 60 -}; - -static const uint8_t huff_b75_xlat[225] = { + 0x83, 0xC3, 0x23, 0x33, + /* Table set B, code table 7, wordlen 4 - 11 entries */ + 0x00, 0x01, 0x0F, 0x02, 0x0E, 0x05, 0x0D, 0x03, 0x04, 0x0B, 0x0C, + /* Table set B, code table 7, wordlen 5 - 225 entries */ 0x00, 0x10, 0xF0, 0x01, 0x0F, 0x20, 0xE0, 0x11, 0xF1, 0x02, 0x0E, 0x1F, 0xFF, 0xD0, 0x21, 0xE1, 0x12, 0xF2, 0x03, 0x0D, 0x1E, 0xFE, 0x2F, 0xEF, 0x30, 0x40, 0x60, 0x70, 0x90, 0xA0, 0xC0, 0x31, 0xD1, 0x22, 0xE2, 0x13, @@ -1623,18 +1315,92 @@ 0xD5, 0x46, 0x56, 0x66, 0x76, 0x96, 0xA6, 0xB6, 0xC6, 0x57, 0x67, 0x77, 0x97, 0xA7, 0xB7, 0x49, 0x69, 0x79, 0x99, 0xA9, 0x4A, 0x5A, 0x7A, 0x9A, 0xAA, 0xBA, 0xCA, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, 0xBB, 0xCB, 0xDB, 0x3C, - 0x4C, 0x5C, 0xBC, 0xCC, 0xDC, 0x5D, 0xCD, 0xBE, 0xBF -}; - -static const uint8_t huff_b77_cb[12] = { - 2, 11, 1, 0, 4, 6, 10, 12, 7, 15, 4, 4 -}; - -static const uint8_t huff_b77_xlat[63] = { - 0, 1, 2, 62, 63, 3, 4, 5, 59, 60, 61, 6, 7, 8, 9, 10, - 54, 55, 56, 57, 58, 11, 12, 13, 14, 15, 16, 47, 49, 50, 51, 52, - 53, 17, 18, 19, 20, 45, 46, 48, 21, 22, 23, 24, 25, 26, 27, 37, - 38, 39, 40, 41, 42, 43, 44, 28, 29, 30, 35, 31, 33, 34, 36 + 0x4C, 0x5C, 0xBC, 0xCC, 0xDC, 0x5D, 0xCD, 0xBE, 0xBF, + /* Table set B, code table 7, wordlen 7 - 63 entries */ + 0x00, 0x01, 0x02, 0x3E, 0x3F, 0x03, 0x04, 0x05, 0x3B, 0x3C, 0x3D, 0x06, + 0x07, 0x08, 0x09, 0x0A, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x2F, 0x31, 0x32, 0x33, 0x34, 0x35, 0x11, 0x12, 0x13, + 0x14, 0x2D, 0x2E, 0x30, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x25, + 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x1C, 0x1D, 0x1E, 0x23, 0x1F, + 0x21, 0x22, 0x24, + /* Table set B, code table 7, wordlen 7 - 8 entries */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + /* Table set B, code table 7, wordlen 7 - 8 entries */ + 0x00, 0x01, 0x07, 0x02, 0x06, 0x03, 0x04, 0x05, + /* Table set B, code table 7, wordlen 7 - 16 entries */ + 0x07, 0x05, 0x08, 0x06, 0x09, 0x04, 0x0A, 0x0B, 0x00, 0x01, 0x02, 0x03, + 0x0C, 0x0D, 0x0E, 0x0F, + /* Table set B, code table 7, wordlen 7 - 15 entries */ + 0x0F, 0x0E, 0x01, 0x0D, 0x02, 0x03, 0x0C, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, + /* Table set B, code table 7, wordlen 7 - 16 entries */ + 0x00, 0x01, 0x0E, 0x0F, 0x02, 0x0D, 0x03, 0x0C, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, + /* Table set B, code table 7, wordlen 7 - 16 entries */ + 0x00, 0x01, 0x0F, 0x0E, 0x02, 0x0D, 0x03, 0x0C, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, + /* Table set B, code table 7, wordlen 7 - 32 entries */ + 0x00, 0x01, 0x1F, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x1A, 0x1B, 0x1C, + 0x1D, 0x1E, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + /* Table set B, code table 7, wordlen 7 - 31 entries */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + /* Table set B, code table 7, wordlen 7 - 32 entries */ + 0x00, 0x1C, 0x1D, 0x01, 0x02, 0x03, 0x04, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1E, 0x1F, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, + /* Table set B, code table 7, wordlen 7 - 31 entries */ + 0x02, 0x03, 0x04, 0x05, 0x06, 0x01, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + /* Table set B, code table 7, wordlen 7 - 32 entries */ + 0x00, 0x01, 0x02, 0x1F, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x1D, 0x1E, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, + /* Table set B, code table 7, wordlen 7 - 16 entries */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, + /* Table set B, code table 7, wordlen 7 - 8 entries */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + /* Table set B, code table 7, wordlen 7 - 8 entries */ + 0x00, 0x01, 0x07, 0x02, 0x03, 0x04, 0x05, 0x06, + /* Table set B, code table 7, wordlen 7 - 32 entries */ + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x05, 0x06, + 0x07, 0x12, 0x13, 0x14, 0x15, 0x16, 0x04, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x00, 0x01, 0x02, 0x03, 0x1C, 0x1D, 0x1E, 0x1F, + /* Table set B, code table 7, wordlen 7 - 32 entries */ + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x0E, + 0x0F, 0x10, 0x11, 0x1D, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x1E, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x1F, 0x00, 0x01, 0x02, 0x03, + /* Table set B, code table 7, wordlen 7 - 32 entries */ + 0x00, 0x01, 0x02, 0x1F, 0x03, 0x1D, 0x1E, 0x04, 0x05, 0x06, 0x1B, 0x1C, + 0x07, 0x18, 0x19, 0x1A, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + /* Table set B, code table 7, wordlen 7 - 256 entries */ + 0x00, 0x01, 0xFF, 0x02, 0xFE, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xFB, + 0xFC, 0xFD, 0x09, 0x0A, 0x0B, 0x0C, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, + 0x26, 0xF3, 0xF4, 0xF5, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, + 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, + 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0xC2, + 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, + 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, + 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, + 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, + 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, + 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, + 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, + 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, + 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, + 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, + 0xBE, 0xBF, 0xC0, 0xC1, }; /** Tables for spectrum coding. */ @@ -1643,272 +1409,251 @@ uint8_t num_coeffs; ///< 1 - map index to a single value, > 1 - map index to a vector of values uint8_t bits; ///< number of bits a single coefficient occupy uint8_t is_signed; ///< 1 - values in that table are signed ones, otherwise - absolute ones - - int redirect; ///< if >= 0: tells which huffman table must be reused - const uint8_t *cb; ///< pointer to the codebook descriptor - const uint8_t *xlat; ///< pointer to the translation table or NULL if none } Atrac3pSpecCodeTab; static const Atrac3pSpecCodeTab atrac3p_spectra_tabs[112] = { /* table set = A */ /* code table = 0 */ - { 1, 4, 2, 1, -1, huff_a01_cb, huff_a01_xlat }, // wordlen = 1 - { 1, 4, 2, 0, -1, huff_a02_cb, huff_a02_xlat }, // wordlen = 2 - { 1, 2, 3, 1, -1, huff_a03_cb, huff_a03_xlat }, // wordlen = 3 - { 1, 1, 3, 0, -1, huff_a04_cb, huff_a04_xlat }, // wordlen = 4 - { 1, 2, 4, 1, -1, huff_a05_cb, huff_a05_xlat }, // wordlen = 5 - { 1, 1, 4, 0, -1, huff_a06_cb, huff_a06_xlat }, // wordlen = 6 - { 1, 1, 6, 1, -1, huff_a07_cb, huff_a07_xlat }, // wordlen = 7 + { 1, 4, 2, 1 }, // wordlen = 1 + { 1, 4, 2, 0 }, // wordlen = 2 + { 1, 2, 3, 1 }, // wordlen = 3 + { 1, 1, 3, 0 }, // wordlen = 4 + { 1, 2, 4, 1 }, // wordlen = 5 + { 1, 1, 4, 0 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 /* code table = 1 */ - { 4, 4, 2, 1, -1, huff_a11_cb, huff_a11_xlat }, // wordlen = 1 - { 1, 4, 2, 0, -1, huff_a12_cb, huff_a12_xlat }, // wordlen = 2 - { 1, 2, 3, 1, -1, huff_a13_cb, huff_a13_xlat }, // wordlen = 3 - { 1, 2, 4, 1, -1, huff_a14_cb, huff_a14_xlat }, // wordlen = 4 - { 1, 2, 4, 1, -1, huff_a15_cb, huff_a15_xlat }, // wordlen = 5 - { 1, 2, 4, 0, -1, huff_a16_cb, huff_a16_xlat }, // wordlen = 6 - { 1, 1, 6, 1, -1, huff_a17_cb, huff_a17_xlat }, // wordlen = 7 + { 4, 4, 2, 1 }, // wordlen = 1 + { 1, 4, 2, 0 }, // wordlen = 2 + { 1, 2, 3, 1 }, // wordlen = 3 + { 1, 2, 4, 1 }, // wordlen = 4 + { 1, 2, 4, 1 }, // wordlen = 5 + { 1, 2, 4, 0 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 /* code table = 2 */ - { 1, 4, 2, 1, -1, huff_a21_cb, huff_a21_xlat }, // wordlen = 1 - { 1, 2, 3, 1, -1, huff_a22_cb, huff_a22_xlat }, // wordlen = 2 - { 1, 2, 3, 1, -1, huff_a23_cb, huff_a23_xlat }, // wordlen = 3 - { 1, 1, 3, 0, -1, huff_a24_cb, NULL }, // wordlen = 4 - { 1, 1, 3, 0, -1, huff_a25_cb, huff_a25_xlat }, // wordlen = 5 - { 1, 2, 4, 0, -1, huff_a26_cb, huff_a26_xlat }, // wordlen = 6 - { 1, 1, 6, 1, -1, huff_a27_cb, huff_a27_xlat }, // wordlen = 7 + { 1, 4, 2, 1 }, // wordlen = 1 + { 1, 2, 3, 1 }, // wordlen = 2 + { 1, 2, 3, 1 }, // wordlen = 3 + { 1, 1, 3, 0 }, // wordlen = 4 + { 1, 1, 3, 0 }, // wordlen = 5 + { 1, 2, 4, 0 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 /* code table = 3 */ - { 1, 2, 2, 1, -1, huff_a31_cb, huff_a31_xlat }, // wordlen = 1 - { 1, 4, 2, 0, -1, huff_a32_cb, huff_a32_xlat }, // wordlen = 2 - { 1, 4, 2, 0, -1, huff_a33_cb, huff_a33_xlat }, // wordlen = 3 - { 1, 1, 3, 0, -1, huff_a34_cb, huff_a34_xlat }, // wordlen = 4 - { 1, 2, 4, 1, -1, huff_a35_cb, huff_a35_xlat }, // wordlen = 5 - { 1, 2, 4, 0, -1, huff_a36_cb, huff_a36_xlat }, // wordlen = 6 - { 1, 1, 6, 1, -1, huff_a37_cb, huff_a37_xlat }, // wordlen = 7 + { 1, 2, 2, 1 }, // wordlen = 1 + { 1, 4, 2, 0 }, // wordlen = 2 + { 1, 4, 2, 0 }, // wordlen = 3 + { 1, 1, 3, 0 }, // wordlen = 4 + { 1, 2, 4, 1 }, // wordlen = 5 + { 1, 2, 4, 0 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 /* code table = 4 */ - { 1, 4, 2, 1, -1, huff_a41_cb, huff_a41_xlat }, // wordlen = 1 - { 1, 4, 2, 0, -1, huff_a42_cb, huff_a42_xlat }, // wordlen = 2 - { 1, 1, 3, 1, -1, huff_a43_cb, huff_a43_xlat }, // wordlen = 3 - { 1, 2, 4, 1, -1, huff_a44_cb, huff_a44_xlat }, // wordlen = 4 - { 1, 1, 3, 0, -1, huff_a45_cb, huff_a45_xlat }, // wordlen = 5 - { 1, 2, 4, 0, -1, huff_a46_cb, huff_a46_xlat }, // wordlen = 6 - { 1, 1, 6, 1, -1, huff_a47_cb, huff_a47_xlat }, // wordlen = 7 + { 1, 4, 2, 1 }, // wordlen = 1 + { 1, 4, 2, 0 }, // wordlen = 2 + { 1, 1, 3, 1 }, // wordlen = 3 + { 1, 2, 4, 1 }, // wordlen = 4 + { 1, 1, 3, 0 }, // wordlen = 5 + { 1, 2, 4, 0 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 /* code table = 5 */ - { 1, 4, 2, 1, -1, huff_a51_cb, huff_a51_xlat }, // wordlen = 1 - { 1, 2, 3, 1, -1, huff_a52_cb, huff_a52_xlat }, // wordlen = 2 - { 1, 1, 3, 1, -1, huff_a43_cb, huff_a53_xlat }, // wordlen = 3 - { 1, 2, 4, 1, -1, huff_a54_cb, huff_a54_xlat }, // wordlen = 4 - { 1, 1, 3, 0, -1, huff_a55_cb, huff_a55_xlat }, // wordlen = 5 - { 1, 1, 5, 1, -1, huff_a56_cb, huff_a56_xlat }, // wordlen = 6 - { 1, 1, 6, 1, -1, huff_a57_cb, huff_a57_xlat }, // wordlen = 7 + { 1, 4, 2, 1 }, // wordlen = 1 + { 1, 2, 3, 1 }, // wordlen = 2 + { 1, 1, 3, 1 }, // wordlen = 3 + { 1, 2, 4, 1 }, // wordlen = 4 + { 1, 1, 3, 0 }, // wordlen = 5 + { 1, 1, 5, 1 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 /* code table = 6 */ - { 2, 4, 2, 1, -1, huff_a61_cb, huff_a61_xlat }, // wordlen = 1 - { 1, 2, 3, 1, -1, huff_a62_cb, huff_a62_xlat }, // wordlen = 2 - { 1, 4, 2, 0, -1, huff_a63_cb, huff_a63_xlat }, // wordlen = 3 - { 1, 2, 4, 1, -1, huff_a64_cb, huff_a64_xlat }, // wordlen = 4 - { 1, 1, 4, 1, -1, huff_a65_cb, huff_a65_xlat }, // wordlen = 5 - { 1, 1, 5, 1, -1, huff_a66_cb, huff_a66_xlat }, // wordlen = 6 - { 1, 1, 6, 1, -1, huff_a67_cb, huff_a67_xlat }, // wordlen = 7 + { 2, 4, 2, 1 }, // wordlen = 1 + { 1, 2, 3, 1 }, // wordlen = 2 + { 1, 4, 2, 0 }, // wordlen = 3 + { 1, 2, 4, 1 }, // wordlen = 4 + { 1, 1, 4, 1 }, // wordlen = 5 + { 1, 1, 5, 1 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 /* code table = 7 */ - { 1, 2, 1, 0, -1, huff_a71_cb, NULL }, // wordlen = 1 - { 2, 4, 2, 0, -1, huff_a72_cb, huff_a72_xlat }, // wordlen = 2 - { 1, 2, 3, 1, -1, huff_a73_cb, huff_a73_xlat }, // wordlen = 3 - { 1, 2, 4, 1, -1, huff_a74_cb, huff_a74_xlat }, // wordlen = 4 - { 1, 1, 4, 1, -1, huff_a75_cb, huff_a75_xlat }, // wordlen = 5 - { 2, 2, 4, 0, -1, huff_a76_cb, huff_a76_xlat }, // wordlen = 6 - { 4, 1, 6, 1, 6, NULL, NULL }, // wordlen = 7 + { 1, 2, 1, 0 }, // wordlen = 1 + { 2, 4, 2, 0 }, // wordlen = 2 + { 1, 2, 3, 1 }, // wordlen = 3 + { 1, 2, 4, 1 }, // wordlen = 4 + { 1, 1, 4, 1 }, // wordlen = 5 + { 2, 2, 4, 0 }, // wordlen = 6 + { 4, 1, 6, 1 }, // wordlen = 7 /* table set = B */ /* code table = 0 */ - { 4, 4, 2, 1, -1, huff_b01_cb, huff_b01_xlat }, // wordlen = 1 - { 1, 4, 2, 0, -1, huff_b02_cb, huff_b02_xlat }, // wordlen = 2 - { 4, 2, 3, 1, -1, huff_b03_cb, huff_b03_xlat }, // wordlen = 3 - { 1, 2, 4, 1, -1, huff_b04_cb, huff_b04_xlat }, // wordlen = 4 - { 1, 2, 4, 1, -1, huff_b05_cb, huff_b05_xlat }, // wordlen = 5 - { 1, 1, 4, 0, 5, NULL, NULL }, // wordlen = 6 - { 1, 1, 6, 1, -1, huff_b07_cb, huff_b07_xlat }, // wordlen = 7 + { 4, 4, 2, 1 }, // wordlen = 1 + { 1, 4, 2, 0 }, // wordlen = 2 + { 4, 2, 3, 1 }, // wordlen = 3 + { 1, 2, 4, 1 }, // wordlen = 4 + { 1, 2, 4, 1 }, // wordlen = 5 + { 1, 1, 4, 0 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 /* code table = 1 */ - { 1, 4, 2, 1, 14, NULL, NULL }, // wordlen = 1 - { 1, 4, 2, 0, -1, huff_b12_cb, huff_b12_xlat }, // wordlen = 2 - { 1, 2, 3, 1, 9, NULL, NULL }, // wordlen = 3 - { 1, 2, 4, 1, -1, huff_b14_cb, huff_b14_xlat }, // wordlen = 4 - { 1, 2, 4, 1, 11, NULL, NULL }, // wordlen = 5 - { 1, 2, 4, 0, -1, huff_b16_cb, huff_b16_xlat }, // wordlen = 6 - { 1, 1, 6, 1, 6, NULL, NULL }, // wordlen = 7 + { 1, 4, 2, 1 }, // wordlen = 1 + { 1, 4, 2, 0 }, // wordlen = 2 + { 1, 2, 3, 1 }, // wordlen = 3 + { 1, 2, 4, 1 }, // wordlen = 4 + { 1, 2, 4, 1 }, // wordlen = 5 + { 1, 2, 4, 0 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 /* code table = 2 */ - { 4, 4, 2, 1, 28, NULL, NULL }, // wordlen = 1 - { 4, 4, 2, 0, 22, NULL, NULL }, // wordlen = 2 - { 1, 2, 3, 1, 2, NULL, NULL }, // wordlen = 3 - { 1, 2, 4, 1, 31, NULL, NULL }, // wordlen = 4 - { 2, 2, 4, 1, 60, NULL, NULL }, // wordlen = 5 - { 2, 2, 4, 0, -1, huff_b26_cb, huff_b26_xlat }, // wordlen = 6 - { 4, 1, 6, 1, 6, NULL, NULL }, // wordlen = 7 + { 4, 4, 2, 1 }, // wordlen = 1 + { 4, 4, 2, 0 }, // wordlen = 2 + { 1, 2, 3, 1 }, // wordlen = 3 + { 1, 2, 4, 1 }, // wordlen = 4 + { 2, 2, 4, 1 }, // wordlen = 5 + { 2, 2, 4, 0 }, // wordlen = 6 + { 4, 1, 6, 1 }, // wordlen = 7 /* code table = 3 */ - { 1, 4, 2, 1, 35, NULL, NULL }, // wordlen = 1 - { 1, 4, 2, 0, -1, huff_b32_cb, huff_b32_xlat }, // wordlen = 2 - { 1, 4, 2, 0, -1, huff_b33_cb, huff_b33_xlat }, // wordlen = 3 - { 2, 2, 4, 1, 59, NULL, NULL }, // wordlen = 4 - { 1, 2, 4, 1, -1, huff_b35_cb, huff_b35_xlat }, // wordlen = 5 - { 1, 2, 4, 0, 75, NULL, NULL }, // wordlen = 6 - { 1, 1, 6, 1, -1, huff_b37_cb, huff_b37_xlat }, // wordlen = 7 + { 1, 4, 2, 1 }, // wordlen = 1 + { 1, 4, 2, 0 }, // wordlen = 2 + { 1, 4, 2, 0 }, // wordlen = 3 + { 2, 2, 4, 1 }, // wordlen = 4 + { 1, 2, 4, 1 }, // wordlen = 5 + { 1, 2, 4, 0 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 /* code table = 4 */ - { 1, 4, 2, 1, -1, huff_b41_cb, huff_b41_xlat }, // wordlen = 1 - { 4, 2, 3, 1, -1, huff_b42_cb, huff_b42_xlat }, // wordlen = 2 - { 1, 2, 3, 1, -1, huff_b43_cb, huff_b43_xlat }, // wordlen = 3 - { 4, 2, 4, 1, 66, NULL, NULL }, // wordlen = 4 - { 1, 1, 3, 0, 32, NULL, NULL }, // wordlen = 5 - { 1, 2, 4, 0, 12, NULL, NULL }, // wordlen = 6 - { 1, 1, 6, 1, -1, huff_b47_cb, huff_b47_xlat }, // wordlen = 7 + { 1, 4, 2, 1 }, // wordlen = 1 + { 4, 2, 3, 1 }, // wordlen = 2 + { 1, 2, 3, 1 }, // wordlen = 3 + { 4, 2, 4, 1 }, // wordlen = 4 + { 1, 1, 3, 0 }, // wordlen = 5 + { 1, 2, 4, 0 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 /* code table = 5 */ - { 2, 4, 2, 1, 42, NULL, NULL }, // wordlen = 1 - { 1, 2, 3, 1, -1, huff_b52_cb, huff_b52_xlat }, // wordlen = 2 - { 4, 1, 3, 1, -1, huff_b53_cb, huff_b53_xlat }, // wordlen = 3 - { 1, 1, 3, 0, 17, NULL, NULL }, // wordlen = 4 - { 1, 1, 3, 0, 39, NULL, NULL }, // wordlen = 5 - { 1, 1, 5, 1, -1, huff_b56_cb, huff_b56_xlat }, // wordlen = 6 - { 2, 1, 6, 1, 62, NULL, NULL }, // wordlen = 7 + { 2, 4, 2, 1 }, // wordlen = 1 + { 1, 2, 3, 1 }, // wordlen = 2 + { 4, 1, 3, 1 }, // wordlen = 3 + { 1, 1, 3, 0 }, // wordlen = 4 + { 1, 1, 3, 0 }, // wordlen = 5 + { 1, 1, 5, 1 }, // wordlen = 6 + { 2, 1, 6, 1 }, // wordlen = 7 /* code table = 6 */ - { 1, 4, 2, 1, 28, NULL, NULL }, // wordlen = 1 - { 1, 4, 2, 0, -1, huff_b62_cb, huff_b62_xlat }, // wordlen = 2 - { 1, 1, 3, 1, -1, huff_b63_cb, huff_b63_xlat }, // wordlen = 3 - { 1, 1, 3, 0, -1, huff_b64_cb, huff_b64_xlat }, // wordlen = 4 - { 4, 2, 4, 1, -1, huff_b65_cb, huff_b65_xlat }, // wordlen = 5 - { 1, 2, 4, 0, -1, huff_b66_cb, huff_b66_xlat }, // wordlen = 6 - { 1, 1, 6, 1, -1, huff_b67_cb, huff_b67_xlat }, // wordlen = 7 + { 1, 4, 2, 1 }, // wordlen = 1 + { 1, 4, 2, 0 }, // wordlen = 2 + { 1, 1, 3, 1 }, // wordlen = 3 + { 1, 1, 3, 0 }, // wordlen = 4 + { 4, 2, 4, 1 }, // wordlen = 5 + { 1, 2, 4, 0 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 /* code table = 7 */ - { 1, 4, 2, 1, -1, huff_b71_cb, huff_b71_xlat }, // wordlen = 1 - { 4, 4, 2, 0, 78, NULL, NULL }, // wordlen = 2 - { 4, 4, 2, 0, -1, huff_b73_cb, huff_b73_xlat }, // wordlen = 3 - { 1, 1, 4, 1, -1, huff_b74_cb, huff_b74_xlat }, // wordlen = 4 - { 1, 2, 4, 1, -1, huff_b75_cb, huff_b75_xlat }, // wordlen = 5 - { 1, 1, 5, 1, 47, NULL, NULL }, // wordlen = 6 - { 1, 1, 6, 1, -1, huff_b77_cb, huff_b77_xlat }, // wordlen = 7 + { 1, 4, 2, 1 }, // wordlen = 1 + { 4, 4, 2, 0 }, // wordlen = 2 + { 4, 4, 2, 0 }, // wordlen = 3 + { 1, 1, 4, 1 }, // wordlen = 4 + { 1, 2, 4, 1 }, // wordlen = 5 + { 1, 1, 5, 1 }, // wordlen = 6 + { 1, 1, 6, 1 }, // wordlen = 7 }; /* Huffman tables for gain control data. */ -static const uint8_t atrac3p_huff_gain_npoints1_cb[9] = { - 1, 7, 1, 1, 1, 1, 1, 1, 2 -}; - -static const uint8_t atrac3p_huff_gain_npoints2_xlat[8] = { - 0, 1, 7, 2, 6, 3, 4, 5 -}; - -static const uint8_t atrac3p_huff_gain_lev1_cb[9] = { 1, 7, 1, 0, 2, 2, 1, 2, 8 }; -static const uint8_t atrac3p_huff_gain_lev1_xlat[16] = { - 7, 5, 8, 6, 9, 4, 10, 11, 0, 1, 2, 3, 12, 13, 14, 15 -}; - -static const uint8_t atrac3p_huff_gain_lev2_cb[11] = { - 1, 9, 1, 1, 1, 1, 1, 0, 2, 0, 8 -}; - -static const uint8_t atrac3p_huff_gain_lev2_xlat[15] = { - 15, 14, 1, 13, 2, 3, 12, 4, 5, 6, 7, 8, 9, 10, 11 -}; - -static const uint8_t atrac3p_huff_gain_lev3_cb[11] = { - 1, 9, 1, 0, 3, 1, 1, 0, 2, 0, 8 -}; - -static const uint8_t atrac3p_huff_gain_lev3_xlat[16] = { - 0, 1, 14, 15, 2, 13, 3, 12, 4, 5, 6, 7, 8, 9, 10, 11 -}; - -static const uint8_t atrac3p_huff_gain_lev4_cb[11] = { - 1, 9, 1, 1, 1, 1, 1, 0, 1, 2, 8 -}; - -static const uint8_t atrac3p_huff_gain_lev4_xlat[16] = { - 0, 1, 15, 14, 2, 13, 3, 12, 4, 5, 6, 7, 8, 9, 10, 11 -}; - -static const uint8_t atrac3p_huff_gain_loc1_cb[9] = { 2, 8, 1, 2, 4, 4, 4, 0, 16 }; -static const uint8_t atrac3p_huff_gain_loc1_xlat[31] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 -}; - -static const uint8_t atrac3p_huff_gain_loc2_cb[8] = { 3, 8, 5, 3, 2, 3, 2, 16 }; -static const uint8_t atrac3p_huff_gain_loc2_xlat[31] = { - 2, 3, 4, 5, 6, 1, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 -}; - -static const uint8_t atrac3p_huff_gain_loc3_cb[7] = { 2, 6, 1, 0, 2, 11, 18 }; -static const uint8_t atrac3p_huff_gain_loc3_xlat[32] = { - 0, 1, 31, 2, 3, 4, 5, 6, 7, 26, 27, 28, 29, 30, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 -}; - -static const uint8_t atrac3p_huff_gain_loc4_cb[5] = { 4, 6, 3, 23, 6 }; -static const uint8_t atrac3p_huff_gain_loc4_xlat[32] = { - 0, 28, 29, 1, 2, 3, 4, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 30, 31, 5, 6, 7, 8, 9, 10 -}; - -static const uint8_t atrac3p_huff_gain_loc5_cb[9] = { 1, 7, 1, 0, 0, 3, 2, 6, 20 }; -static const uint8_t atrac3p_huff_gain_loc5_xlat[32] = { - 0, 1, 2, 31, 3, 4, 5, 6, 7, 8, 29, 30, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 +static const uint8_t atrac3p_gain_cbs[][12] = { + { 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0 }, + { 1, 0, 2, 2, 1, 2, 8, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 1, 0, 2, 0, 8, 0, 0, 0 }, + { 1, 0, 3, 1, 1, 0, 2, 0, 8, 0, 0, 0 }, + { 1, 1, 1, 1, 1, 0, 1, 2, 8, 0, 0, 0 }, + { 0, 1, 0, 2, 11, 18, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 2, 4, 4, 4, 0, 16, 0, 0, 0, 0 }, + { 0, 0, 0, 3, 23, 6, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 5, 3, 2, 3, 2, 16, 0, 0, 0, 0 }, + { 1, 0, 0, 3, 2, 6, 20, 0, 0, 0, 0, 0 }, +}; + +static const uint8_t atrac3p_gain_xlats[] = { + /* Number of gain control points 1 - 8 entries */ + 0, 1, 2, 3, 4, 5, 6, 7, + /* Number of gain control points 2 - 8 entries */ + 0, 1, 7, 2, 6, 3, 4, 5, + /* Gain compensation level 1 - 16 entries */ + 7, 5, 8, 6, 9, 4, 10, 11, 0, 1, 2, 3, 12, 13, 14, 15, + /* Gain compensation level 2 - 15 entries */ + 15, 14, 1, 13, 2, 3, 12, 4, 5, 6, 7, 8, 9, 10, 11, + /* Gain compensation level 3 - 16 entries */ + 0, 1, 14, 15, 2, 13, 3, 12, 4, 5, 6, 7, 8, 9, 10, 11, + /* Gain compensation level 4 - 16 entries */ + 0, 1, 15, 14, 2, 13, 3, 12, 4, 5, 6, 7, 8, 9, 10, 11, + /* Gain compensation location 3 - 32 entries */ + 0, 1, 31, 2, 3, 4, 5, 6, 7, 26, 27, 28, 29, 30, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + /* Gain compensation location 1 - 31 entries */ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + /* Gain compensation location 4 - 32 entries */ + 0, 28, 29, 1, 2, 3, 4, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 30, 31, 5, 6, 7, 8, 9, 10, + /* Gain compensation location 2 - 31 entries */ + 2, 3, 4, 5, 6, 1, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + /* Gain compensation location 5 - 32 entries */ + 0, 1, 2, 31, 3, 4, 5, 6, 7, 8, 29, 30, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, }; /* Huffman tables for GHA waves data. */ -static const uint8_t atrac3p_huff_tonebands_cb[8] = { 1, 6, 1, 0, 1, 2, 4, 8 }; -static const uint8_t atrac3p_huff_numwavs1_cb[9] = { 1, 7, 1, 1, 1, 1, 1, 1, 2 }; -static const uint8_t atrac3p_huff_numwavs2_cb[8] = { 1, 6, 1, 1, 1, 1, 0, 4 }; -static const uint8_t atrac3p_huff_numwavs2_xlat[8] = { 0, 1, 7, 2, 3, 4, 5, 6 }; -static const uint8_t atrac3p_huff_wav_ampsf1_cb[7] = { 4, 8, 10, 8, 6, 0, 8 }; -static const uint8_t atrac3p_huff_wav_ampsf1_xlat[32] = { - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 5, 6, 7, 18, 19, 20, - 21, 22, 4, 23, 24, 25, 26, 27, 0, 1, 2, 3, 28, 29, 30, 31 -}; - -static const uint8_t atrac3p_huff_wav_ampsf2_cb[7] = { 4, 8, 11, 5, 6, 6, 4 }; -static const uint8_t atrac3p_huff_wav_ampsf2_xlat[32] = { - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 14, 15, 16, 17, 29, - 9, 10, 11, 12, 13, 30, 4, 5, 6, 7, 8, 31, 0, 1, 2, 3 -}; - -static const uint8_t atrac3p_huff_wav_ampsf3_cb[9] = { 2, 8, 1, 3, 3, 1, 4, 4, 16 }; -static const uint8_t atrac3p_huff_wav_ampsf3_xlat[32] = { - 0, 1, 2, 31, 3, 29, 30, 4, 5, 6, 27, 28, 7, 24, 25, 26, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 -}; - -static const uint8_t atrac3p_huff_freq_cb[13] = { - 1, 11, 1, 0, 0, 2, 2, 0, 9, 9, 29, 104, 100 -}; - -static const uint8_t atrac3p_huff_freq_xlat[256] = { - 0, 1, 255, 2, 254, 3, 4, 5, 6, 7, 8, 251, 252, 253, 9, 10, - 11, 12, 246, 247, 248, 249, 250, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 243, 244, 245, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 194, 195, 196, 197, 198, - 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193 +static const uint8_t atrac3p_tone_cbs[][12] = { + { 1, 0, 1, 2, 4, 8, 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 0, 4, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 10, 8, 6, 0, 8, 0, 0, 0, 0 }, + { 0, 0, 0, 11, 5, 6, 6, 4, 0, 0, 0, 0 }, + { 0, 1, 3, 3, 1, 4, 4, 16, 0, 0, 0, 0 }, + { 1, 0, 0, 2, 2, 0, 9, 9, 29,104, 100, 0 }, +}; + +static const uint8_t atrac3p_tone_xlats[] = { + /* Number of tone bands - 16 entries */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, + /* Number of tones 1 - 8 entries */ + 0, 1, 2, 3, 4, 5, 6, 7, + /* Number of tones 2 - 8 entries */ + 0, 1, 7, 2, 3, 4, 5, 6, + /* Amplitude information 1 - 32 entries */ + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 5, 6, 7, 18, 19, + 20, 21, 22, 4, 23, 24, 25, 26, 27, 0, 1, 2, 3, 28, 29, + 30, 31, + /* Amplitude information 2 - 32 entries */ + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 14, 15, 16, 17, + 29, 9, 10, 11, 12, 13, 30, 4, 5, 6, 7, 8, 31, 0, 1, + 2, 3, + /* Amplitude information 3 - 32 entries */ + 0, 1, 2, 31, 3, 29, 30, 4, 5, 6, 27, 28, 7, 24, 25, + 26, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, + /* Frequencies - 256 entries */ + 0, 1, 255, 2, 254, 3, 4, 5, 6, 7, 8, 251, 252, 253, 9, + 10, 11, 12, 246, 247, 248, 249, 250, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 243, 244, 245, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 239, 240, 241, 242, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, + 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, + 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, + 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, }; #endif /* AVCODEC_ATRAC3PLUS_DATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/atrac3plusdec.c ffmpeg-4.4/libavcodec/atrac3plusdec.c --- ffmpeg-4.2.2/libavcodec/atrac3plusdec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atrac3plusdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -39,6 +39,8 @@ #include "libavutil/channel_layout.h" #include "libavutil/float_dsp.h" +#include "libavutil/mem_internal.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "get_bits.h" #include "internal.h" @@ -144,8 +146,15 @@ return 0; } +static av_cold void atrac3p_init_static(void) +{ + ff_atrac3p_init_vlcs(); + ff_atrac3p_init_dsp_static(); +} + static av_cold int atrac3p_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; ATRAC3PContext *ctx = avctx->priv_data; int i, ch, ret; @@ -154,8 +163,6 @@ return AVERROR(EINVAL); } - ff_atrac3p_init_vlcs(); - /* initialize IPQF */ ff_mdct_init(&ctx->ipqf_dct_ctx, 5, 1, 32.0 / 32768.0); @@ -163,8 +170,6 @@ ff_atrac_init_gain_compensation(&ctx->gainc_ctx, 6, 2); - ff_atrac3p_init_wave_synth(); - if ((ret = set_channel_params(ctx, avctx)) < 0) return ret; @@ -174,7 +179,6 @@ ctx->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); if (!ctx->ch_units || !ctx->fdsp) { - atrac3p_decode_close(avctx); return AVERROR(ENOMEM); } @@ -195,6 +199,8 @@ avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + ff_thread_once(&init_static_once, atrac3p_init_static); + return 0; } @@ -393,6 +399,7 @@ .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_ATRAC3P, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .priv_data_size = sizeof(ATRAC3PContext), .init = atrac3p_decode_init, .close = atrac3p_decode_close, @@ -405,6 +412,7 @@ .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_ATRAC3PAL, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .priv_data_size = sizeof(ATRAC3PContext), .init = atrac3p_decode_init, .close = atrac3p_decode_close, diff -Nru ffmpeg-4.2.2/libavcodec/atrac3plusdsp.c ffmpeg-4.4/libavcodec/atrac3plusdsp.c --- ffmpeg-4.2.2/libavcodec/atrac3plusdsp.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atrac3plusdsp.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,8 @@ #include "libavutil/float_dsp.h" #include "libavutil/libm.h" +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "sinewin.h" #include "fft.h" @@ -79,9 +81,6 @@ av_cold void ff_atrac3p_init_imdct(AVCodecContext *avctx, FFTContext *mdct_ctx) { - ff_init_ff_sine_windows(7); - ff_init_ff_sine_windows(6); - /* Initialize the MDCT transform. */ ff_mdct_init(mdct_ctx, 8, 1, -1.0); } @@ -94,7 +93,7 @@ static DECLARE_ALIGNED(32, float, hann_window)[256]; ///< Hann windowing function static float amp_sf_tab[64]; ///< scalefactors for quantized amplitudes -av_cold void ff_atrac3p_init_wave_synth(void) +av_cold void ff_atrac3p_init_dsp_static(void) { int i; @@ -109,6 +108,9 @@ /* generate amplitude scalefactors table */ for (i = 0; i < 64; i++) amp_sf_tab[i] = exp2f((i - 3) / 4.0f); + + ff_init_ff_sine_windows(7); + ff_init_ff_sine_windows(6); } /** diff -Nru ffmpeg-4.2.2/libavcodec/atrac3plus.h ffmpeg-4.4/libavcodec/atrac3plus.h --- ffmpeg-4.2.2/libavcodec/atrac3plus.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atrac3plus.h 2021-04-08 21:28:39.000000000 +0000 @@ -31,6 +31,8 @@ #include #include "libavutil/float_dsp.h" +#include "libavutil/mem_internal.h" + #include "atrac.h" #include "avcodec.h" #include "fft.h" @@ -179,9 +181,9 @@ void ff_atrac3p_init_imdct(AVCodecContext *avctx, FFTContext *mdct_ctx); /** - * Initialize sine waves synthesizer. + * Initialize sine waves synthesizer and ff_sine_* tables. */ -void ff_atrac3p_init_wave_synth(void); +void ff_atrac3p_init_dsp_static(void); /** * Synthesize sine waves for a particular subband. diff -Nru ffmpeg-4.2.2/libavcodec/atrac9dec.c ffmpeg-4.4/libavcodec/atrac9dec.c --- ffmpeg-4.2.2/libavcodec/atrac9dec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atrac9dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,12 +19,18 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/thread.h" + #include "internal.h" #include "get_bits.h" #include "fft.h" #include "atrac9tab.h" #include "libavutil/lfg.h" #include "libavutil/float_dsp.h" +#include "libavutil/mem_internal.h" + +#define ATRAC9_SF_VLC_BITS 8 +#define ATRAC9_COEFF_VLC_BITS 9 typedef struct ATRAC9ChannelData { int band_ext; @@ -90,14 +96,15 @@ const ATRAC9BlockConfig *block_config; /* Generated on init */ - VLC sf_vlc[2][8]; /* Signed/unsigned, length */ - VLC coeff_vlc[2][8][4]; /* Cookbook, precision, cookbook index */ uint8_t alloc_curve[48][48]; DECLARE_ALIGNED(32, float, imdct_win)[256]; DECLARE_ALIGNED(32, float, temp)[256]; } ATRAC9Context; +static VLC sf_vlc[2][8]; /* Signed/unsigned, length */ +static VLC coeff_vlc[2][8][4]; /* Cookbook, precision, cookbook index */ + static inline int parse_gradient(ATRAC9Context *s, ATRAC9BlockData *b, GetBitContext *gb) { @@ -124,9 +131,6 @@ if (grad_range[0] >= grad_range[1] || grad_range[1] > 31) return AVERROR_INVALIDDATA; - if (grad_value[0] > 31 || grad_value[1] > 31) - return AVERROR_INVALIDDATA; - if (b->grad_boundary > b->q_unit_cnt) return AVERROR_INVALIDDATA; @@ -270,12 +274,13 @@ const uint8_t *sf_weights = at9_tab_sf_weights[get_bits(gb, 3)]; const int base = get_bits(gb, 5); const int len = get_bits(gb, 2) + 3; - const VLC *tab = &s->sf_vlc[0][len]; + const VLC *tab = &sf_vlc[0][len]; c->scalefactors[0] = get_bits(gb, len); for (int i = 1; i < b->band_ext_q_unit; i++) { - int val = c->scalefactors[i - 1] + get_vlc2(gb, tab->table, 9, 2); + int val = c->scalefactors[i - 1] + get_vlc2(gb, tab->table, + ATRAC9_SF_VLC_BITS, 1); c->scalefactors[i] = val & ((1 << len) - 1); } @@ -302,10 +307,10 @@ const int len = get_bits(gb, 2) + 2; const int unit_cnt = FFMIN(b->band_ext_q_unit, baseline_len); - const VLC *tab = &s->sf_vlc[1][len]; + const VLC *tab = &sf_vlc[1][len]; for (int i = 0; i < unit_cnt; i++) { - int dist = get_vlc2(gb, tab->table, 9, 2); + int dist = get_vlc2(gb, tab->table, ATRAC9_SF_VLC_BITS, 1); c->scalefactors[i] = baseline[i] + dist; } @@ -323,12 +328,13 @@ const int base = get_bits(gb, 5) - (1 << (5 - 1)); const int len = get_bits(gb, 2) + 1; const int unit_cnt = FFMIN(b->band_ext_q_unit, baseline_len); - const VLC *tab = &s->sf_vlc[0][len]; + const VLC *tab = &sf_vlc[0][len]; c->scalefactors[0] = get_bits(gb, len); for (int i = 1; i < unit_cnt; i++) { - int val = c->scalefactors[i - 1] + get_vlc2(gb, tab->table, 9, 2); + int val = c->scalefactors[i - 1] + get_vlc2(gb, tab->table, + ATRAC9_SF_VLC_BITS, 1); c->scalefactors[i] = val & ((1 << len) - 1); } @@ -409,12 +415,12 @@ if (prec <= max_prec) { const int cb = c->codebookset[i]; const int cbi = at9_q_unit_to_codebookidx[i]; - const VLC *tab = &s->coeff_vlc[cb][prec][cbi]; + const VLC *tab = &coeff_vlc[cb][prec][cbi]; const HuffmanCodebook *huff = &at9_huffman_coeffs[cb][prec][cbi]; const int groups = bands >> huff->value_cnt_pow; for (int j = 0; j < groups; j++) { - uint16_t val = get_vlc2(gb, tab->table, 9, huff->max_bit_size); + uint16_t val = get_vlc2(gb, tab->table, ATRAC9_COEFF_VLC_BITS, 2); for (int k = 0; k < huff->value_cnt; k++) { coeffs[k] = sign_extend(val, huff->value_bits); @@ -827,23 +833,69 @@ { ATRAC9Context *s = avctx->priv_data; - for (int i = 1; i < 7; i++) - ff_free_vlc(&s->sf_vlc[0][i]); - for (int i = 2; i < 6; i++) - ff_free_vlc(&s->sf_vlc[1][i]); - for (int i = 0; i < 2; i++) - for (int j = 0; j < 8; j++) - for (int k = 0; k < 4; k++) - ff_free_vlc(&s->coeff_vlc[i][j][k]); - ff_mdct_end(&s->imdct); - av_free(s->fdsp); + av_freep(&s->fdsp); return 0; } +static av_cold void atrac9_init_vlc(VLC *vlc, int nb_bits, int nb_codes, + const uint8_t (**tab)[2], + unsigned *buf_offset, int offset) +{ + static VLC_TYPE vlc_buf[24812][2]; + + vlc->table = &vlc_buf[*buf_offset]; + vlc->table_allocated = FF_ARRAY_ELEMS(vlc_buf) - *buf_offset; + ff_init_vlc_from_lengths(vlc, nb_bits, nb_codes, + &(*tab)[0][1], 2, &(*tab)[0][0], 2, 1, + offset, INIT_VLC_STATIC_OVERLONG, NULL); + *buf_offset += vlc->table_size; + *tab += nb_codes; +} + +static av_cold void atrac9_init_static(void) +{ + const uint8_t (*tab)[2]; + unsigned offset = 0; + + /* Unsigned scalefactor VLCs */ + tab = at9_sfb_a_tab; + for (int i = 1; i < 7; i++) { + const HuffmanCodebook *hf = &at9_huffman_sf_unsigned[i]; + + atrac9_init_vlc(&sf_vlc[0][i], ATRAC9_SF_VLC_BITS, + hf->size, &tab, &offset, 0); + } + + /* Signed scalefactor VLCs */ + tab = at9_sfb_b_tab; + for (int i = 2; i < 6; i++) { + const HuffmanCodebook *hf = &at9_huffman_sf_signed[i]; + + /* The symbols are signed integers in the range -16..15; + * the values in the source table are offset by 16 to make + * them fit into an uint8_t; the -16 reverses this shift. */ + atrac9_init_vlc(&sf_vlc[1][i], ATRAC9_SF_VLC_BITS, + hf->size, &tab, &offset, -16); + } + + /* Coefficient VLCs */ + tab = at9_coeffs_tab; + for (int i = 0; i < 2; i++) { + for (int j = 2; j < 8; j++) { + for (int k = i; k < 4; k++) { + const HuffmanCodebook *hf = &at9_huffman_coeffs[i][j][k]; + atrac9_init_vlc(&coeff_vlc[i][j][k], ATRAC9_COEFF_VLC_BITS, + hf->size, &tab, &offset, 0); + } + } + } +} + static av_cold int atrac9_decode_init(AVCodecContext *avctx) { + static AVOnce static_table_init = AV_ONCE_INIT; GetBitContext gb; ATRAC9Context *s = avctx->priv_data; int version, block_config_idx, superframe_idx, alloc_c_len; @@ -929,37 +981,7 @@ for (int j = 0; j < i; j++) s->alloc_curve[i - 1][j] = at9_tab_b_dist[(j * alloc_c_len) / i]; - /* Unsigned scalefactor VLCs */ - for (int i = 1; i < 7; i++) { - const HuffmanCodebook *hf = &at9_huffman_sf_unsigned[i]; - - init_vlc(&s->sf_vlc[0][i], 9, hf->size, hf->bits, 1, 1, hf->codes, - 2, 2, 0); - } - - /* Signed scalefactor VLCs */ - for (int i = 2; i < 6; i++) { - const HuffmanCodebook *hf = &at9_huffman_sf_signed[i]; - - int nums = hf->size; - int16_t sym[32]; - for (int j = 0; j < nums; j++) - sym[j] = sign_extend(j, hf->value_bits); - - ff_init_vlc_sparse(&s->sf_vlc[1][i], 9, hf->size, hf->bits, 1, 1, - hf->codes, 2, 2, sym, sizeof(*sym), sizeof(*sym), 0); - } - - /* Coefficient VLCs */ - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 8; j++) { - for (int k = 0; k < 4; k++) { - const HuffmanCodebook *hf = &at9_huffman_coeffs[i][j][k]; - init_vlc(&s->coeff_vlc[i][j][k], 9, hf->size, hf->bits, 1, 1, - hf->codes, 2, 2, 0); - } - } - } + ff_thread_once(&static_table_init, atrac9_init_static); return 0; } @@ -975,5 +997,5 @@ .decode = atrac9_decode_frame, .flush = atrac9_decode_flush, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; diff -Nru ffmpeg-4.2.2/libavcodec/atrac9tab.h ffmpeg-4.4/libavcodec/atrac9tab.h --- ffmpeg-4.2.2/libavcodec/atrac9tab.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atrac9tab.h 2021-04-08 21:28:39.000000000 +0000 @@ -41,61 +41,48 @@ static const ATRAC9BlockConfig at9_block_layout[] = { { /* Mono */ - AV_CH_LAYOUT_MONO, - { - ATRAC9_BLOCK_TYPE_SCE, - }, - { { 0 }, }, - 1, + .channel_layout = AV_CH_LAYOUT_MONO, + .type = { ATRAC9_BLOCK_TYPE_SCE, }, + .count = 1, }, { /* Dual Mono */ - AV_CH_LAYOUT_STEREO, - { - ATRAC9_BLOCK_TYPE_SCE, - ATRAC9_BLOCK_TYPE_SCE, - }, - { { 0 }, { 1 }, }, - 2, + .channel_layout = AV_CH_LAYOUT_STEREO, + .type = { ATRAC9_BLOCK_TYPE_SCE, + ATRAC9_BLOCK_TYPE_SCE, }, + .plane_map = { { 0 }, { 1 }, }, + .count = 2, }, { /* Stereo */ - AV_CH_LAYOUT_STEREO, - { - ATRAC9_BLOCK_TYPE_CPE, - }, - { { 0, 1 }, }, - 1, + .channel_layout = AV_CH_LAYOUT_STEREO, + .type = { ATRAC9_BLOCK_TYPE_CPE, }, + .plane_map = { { 0, 1 }, }, + .count = 1, }, { /* 5.1 */ - AV_CH_LAYOUT_5POINT1, - { - ATRAC9_BLOCK_TYPE_CPE, - ATRAC9_BLOCK_TYPE_SCE, - ATRAC9_BLOCK_TYPE_LFE, - ATRAC9_BLOCK_TYPE_CPE, - }, - { { 0, 1 }, { 2 }, { 3 }, { 4, 5 }, }, - 4, - }, - { /* 5.1 */ - AV_CH_LAYOUT_7POINT1, - { - ATRAC9_BLOCK_TYPE_CPE, - ATRAC9_BLOCK_TYPE_SCE, - ATRAC9_BLOCK_TYPE_LFE, - ATRAC9_BLOCK_TYPE_CPE, - ATRAC9_BLOCK_TYPE_CPE, - }, - { { 0, 1 }, { 2 }, { 3 }, { 4, 5 }, { 6, 7 }, }, - 5, + .channel_layout = AV_CH_LAYOUT_5POINT1, + .type = { ATRAC9_BLOCK_TYPE_CPE, + ATRAC9_BLOCK_TYPE_SCE, + ATRAC9_BLOCK_TYPE_LFE, + ATRAC9_BLOCK_TYPE_CPE, }, + .plane_map = { { 0, 1 }, { 2 }, { 3 }, { 4, 5 }, }, + .count = 4, + }, + { /* 7.1 */ + .channel_layout = AV_CH_LAYOUT_7POINT1, + .type = { ATRAC9_BLOCK_TYPE_CPE, + ATRAC9_BLOCK_TYPE_SCE, + ATRAC9_BLOCK_TYPE_LFE, + ATRAC9_BLOCK_TYPE_CPE, + ATRAC9_BLOCK_TYPE_CPE, }, + .plane_map = { { 0, 1 }, { 2 }, { 3 }, { 4, 5 }, { 6, 7 }, }, + .count = 5, }, { /* Quad */ - AV_CH_LAYOUT_QUAD, - { - ATRAC9_BLOCK_TYPE_CPE, - ATRAC9_BLOCK_TYPE_CPE, - }, - { { 0, 1 }, { 2, 3 }, }, - 2, + .channel_layout = AV_CH_LAYOUT_QUAD, + .type = { ATRAC9_BLOCK_TYPE_CPE, + ATRAC9_BLOCK_TYPE_CPE, }, + .plane_map = { { 0, 1 }, { 2, 3 }, }, + .count = 2, }, }; @@ -117,7 +104,7 @@ 72, 80, 88, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256 }; -const uint8_t at9_q_unit_to_codebookidx[] = { +static const uint8_t at9_q_unit_to_codebookidx[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, }; @@ -386,1165 +373,921 @@ 27, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, }; -static const uint8_t huff_sfb_a1_bits[] = { - 1, 1, -}; - -static const uint16_t huff_sfb_a1_codes[] = { - 0x00, 0x01, -}; - -static const uint8_t huff_sfb_a2_bits[] = { - 1, 3, 3, 2, -}; - -static const uint16_t huff_sfb_a2_codes[] = { - 0x00, 0x06, 0x07, 0x02, -}; - -static const uint8_t huff_sfb_a3_bits[] = { - 2, 2, 4, 6, 6, 5, 3, 2, -}; - -static const uint16_t huff_sfb_a3_codes[] = { - 0x00, 0x01, 0x0E, 0x3E, 0x3F, 0x1E, 0x06, 0x02, -}; - -static const uint8_t huff_sfb_a4_bits[] = { - 2, 2, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 6, 5, 4, 2, -}; - -static const uint16_t huff_sfb_a4_codes[] = { - 0x01, 0x02, 0x00, 0x06, 0x0F, 0x13, 0x23, 0x24, - 0x25, 0x22, 0x21, 0x20, 0x0E, 0x05, 0x01, 0x03, -}; - -static const uint8_t huff_sfb_a5_bits[] = { - 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 6, 5, 5, 4, 3, -}; - -static const uint16_t huff_sfb_a5_codes[] = { - 0x02, 0x01, 0x07, 0x0D, 0x0C, 0x18, 0x1B, 0x21, 0x3F, 0x6A, 0x6B, 0x68, - 0x73, 0x79, 0x7C, 0x7D, 0x7A, 0x7B, 0x78, 0x72, 0x44, 0x45, 0x47, 0x46, - 0x69, 0x38, 0x20, 0x1D, 0x19, 0x09, 0x05, 0x00, -}; - -static const uint8_t huff_sfb_a6_bits[] = { - 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 4, 4, 4, -}; - -static const uint16_t huff_sfb_a6_codes[] = { - 0x00, 0x01, 0x04, 0x05, 0x12, 0x13, 0x2E, 0x2F, 0x30, 0x66, 0x67, 0xD6, - 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, - 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, - 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, - 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x68, 0x69, 0x6A, 0x31, 0x32, 0x14, 0x15, - 0x16, 0x06, 0x07, 0x08, -}; - -static const uint8_t huff_sfb_b2_bits[] = { - 1, 2, 0, 2, -}; - -static const uint16_t huff_sfb_b2_codes[] = { - 0x00, 0x03, 0x00, 0x02, -}; - -static const uint8_t huff_sfb_b3_bits[] = { - 1, 3, 5, 6, 0, 6, 4, 2, -}; - -static const uint16_t huff_sfb_b3_codes[] = { - 0x01, 0x00, 0x04, 0x0B, 0x00, 0x0A, 0x03, 0x01, -}; - -static const uint8_t huff_sfb_b4_bits[] = { - 1, 3, 4, 5, 5, 7, 8, 8, 0, 8, 8, 7, 6, 6, 4, 3, -}; - -static const uint16_t huff_sfb_b4_codes[] = { - 0x01, 0x01, 0x04, 0x0E, 0x0F, 0x2C, 0x5A, 0x5D, 0x00, 0x5C, 0x5B, 0x2F, - 0x15, 0x14, 0x06, 0x00, -}; - -static const uint8_t huff_sfb_b5_bits[] = { - 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 7, 7, 8, 8, - 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 3, -}; - -static const uint16_t huff_sfb_b5_codes[] = { - 0x00, 0x05, 0x07, 0x0C, 0x04, 0x02, 0x03, 0x05, 0x09, 0x10, 0x23, 0x33, - 0x36, 0x6E, 0x60, 0x65, 0x62, 0x61, 0x63, 0x64, 0x6F, 0x6D, 0x6C, 0x6B, - 0x6A, 0x68, 0x69, 0x45, 0x44, 0x37, 0x1A, 0x07, +static const uint8_t at9_sfb_a_tab[][2] = { + /* Unsigned scalefactor table 1 - 2 entries */ + { 0, 1 }, { 1, 1 }, + /* Unsigned scalefactor table 2 - 4 entries */ + { 0, 1 }, { 3, 2 }, { 1, 3 }, { 2, 3 }, + /* Unsigned scalefactor table 3 - 8 entries */ + { 0, 2 }, { 1, 2 }, { 7, 2 }, { 6, 3 }, { 2, 4 }, { 5, 5 }, { 3, 6 }, + { 4, 6 }, + /* Unsigned scalefactor table 4 - 16 entries */ + { 2, 4 }, { 14, 4 }, { 11, 8 }, { 10, 8 }, { 9, 8 }, { 6, 8 }, { 7, 8 }, + { 8, 8 }, { 5, 7 }, { 13, 5 }, { 3, 5 }, { 12, 6 }, { 4, 6 }, { 0, 2 }, + { 1, 2 }, { 15, 2 }, + /* Unsigned scalefactor table 5 - 32 entries */ + { 31, 3 }, { 1, 3 }, { 26, 7 }, { 7, 7 }, { 20, 8 }, { 21, 8 }, { 23, 8 }, + { 22, 8 }, { 29, 5 }, { 30, 4 }, { 4, 5 }, { 11, 8 }, { 24, 8 }, { 9, 8 }, + { 10, 8 }, { 6, 6 }, { 25, 7 }, { 19, 8 }, { 12, 8 }, { 27, 6 }, { 18, 8 }, + { 13, 8 }, { 16, 8 }, { 17, 8 }, { 14, 8 }, { 15, 8 }, { 8, 7 }, { 0, 2 }, + { 5, 5 }, { 28, 5 }, { 3, 4 }, { 2, 3 }, + /* Unsigned scalefactor table 6 - 64 entries */ + { 0, 3 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 61, 4 }, { 62, 4 }, { 63, 4 }, + { 4, 5 }, { 5, 5 }, { 58, 5 }, { 59, 5 }, { 60, 5 }, { 6, 6 }, { 7, 6 }, + { 8, 6 }, { 56, 6 }, { 57, 6 }, { 9, 7 }, { 10, 7 }, { 53, 7 }, { 54, 7 }, + { 55, 7 }, { 11, 8 }, { 12, 8 }, { 13, 8 }, { 14, 8 }, { 15, 8 }, { 16, 8 }, + { 17, 8 }, { 18, 8 }, { 19, 8 }, { 20, 8 }, { 21, 8 }, { 22, 8 }, { 23, 8 }, + { 24, 8 }, { 25, 8 }, { 26, 8 }, { 27, 8 }, { 28, 8 }, { 29, 8 }, { 30, 8 }, + { 31, 8 }, { 32, 8 }, { 33, 8 }, { 34, 8 }, { 35, 8 }, { 36, 8 }, { 37, 8 }, + { 38, 8 }, { 39, 8 }, { 40, 8 }, { 41, 8 }, { 42, 8 }, { 43, 8 }, { 44, 8 }, + { 45, 8 }, { 46, 8 }, { 47, 8 }, { 48, 8 }, { 49, 8 }, { 50, 8 }, { 51, 8 }, + { 52, 8 }, +}; + +static const uint8_t at9_sfb_b_tab[][2] = { + /* Signed scalefactor table 2 - 3 entries */ + { 16, 1 }, { 15, 2 }, { 17, 2 }, + /* Signed scalefactor table 3 - 7 entries */ + { 17, 3 }, { 18, 5 }, { 13, 6 }, { 19, 6 }, { 14, 4 }, { 15, 2 }, { 16, 1 }, + /* Signed scalefactor table 4 - 15 entries */ + { 15, 3 }, { 17, 3 }, { 18, 4 }, { 13, 6 }, { 12, 6 }, { 21, 7 }, { 22, 8 }, + { 10, 8 }, { 9, 8 }, { 23, 8 }, { 11, 7 }, { 14, 4 }, { 19, 5 }, { 20, 5 }, + { 16, 1 }, + /* Signed scalefactor table 5 - 32 entries */ + { 16, 3 }, { 21, 4 }, { 22, 4 }, { 20, 4 }, { 23, 4 }, { 30, 8 }, { 1, 8 }, + { 0, 8 }, { 2, 8 }, { 3, 8 }, { 31, 8 }, { 27, 7 }, { 14, 6 }, { 28, 7 }, + { 13, 7 }, { 18, 4 }, { 25, 5 }, { 12, 7 }, { 11, 7 }, { 26, 6 }, { 24, 4 }, + { 17, 3 }, { 19, 4 }, { 9, 7 }, { 10, 7 }, { 8, 7 }, { 7, 7 }, { 6, 7 }, + { 5, 7 }, { 29, 7 }, { 4, 7 }, { 15, 3 }, }; typedef struct HuffmanCodebook { - const uint8_t *bits; - const uint16_t *codes; const int size; const int value_cnt; const int value_cnt_pow; const int value_bits; - const int max_bit_size; } HuffmanCodebook; static const HuffmanCodebook at9_huffman_sf_unsigned[] = { { 0 }, - { huff_sfb_a1_bits, huff_sfb_a1_codes, 2, 1, 0, 1, 1, }, - { huff_sfb_a2_bits, huff_sfb_a2_codes, 4, 1, 0, 2, 3, }, - { huff_sfb_a3_bits, huff_sfb_a3_codes, 8, 1, 0, 3, 6, }, - { huff_sfb_a4_bits, huff_sfb_a4_codes, 16, 1, 0, 4, 8, }, - { huff_sfb_a5_bits, huff_sfb_a5_codes, 32, 1, 0, 5, 8, }, - { huff_sfb_a6_bits, huff_sfb_a6_codes, 64, 1, 0, 6, 8, }, + { 2, 1, 0, 1 }, + { 4, 1, 0, 2 }, + { 8, 1, 0, 3 }, + { 16, 1, 0, 4 }, + { 32, 1, 0, 5 }, + { 64, 1, 0, 6 }, }; static const HuffmanCodebook at9_huffman_sf_signed[] = { { 0 }, { 0 }, - { huff_sfb_b2_bits, huff_sfb_b2_codes, 4, 1, 0, 2, 2, }, - { huff_sfb_b3_bits, huff_sfb_b3_codes, 8, 1, 0, 3, 6, }, - { huff_sfb_b4_bits, huff_sfb_b4_codes, 16, 1, 0, 4, 8, }, - { huff_sfb_b5_bits, huff_sfb_b5_codes, 32, 1, 0, 5, 8, }, -}; - -static const uint8_t huff_spec_a21_bits[] = { - 0, 3, 0, 3, 3, 3, 0, 3, 0, 0, 0, 0, 3, 3, 0, 3, -}; - -static const uint16_t huff_spec_a21_codes[] = { - 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x06, -}; - -static const uint8_t huff_spec_a22_bits[] = { - 0, 4, 0, 4, 5, 6, 0, 6, 0, 0, 0, 0, 5, 6, 0, 6, - 5, 6, 0, 6, 6, 7, 0, 7, 0, 0, 0, 0, 6, 7, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 6, 6, 7, 0, 7, 0, 0, 0, 0, 6, 7, 0, 7, - 5, 6, 0, 6, 7, 7, 0, 7, 0, 0, 0, 0, 6, 7, 0, 7, - 6, 7, 0, 7, 7, 8, 0, 8, 0, 0, 0, 0, 7, 8, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 7, 0, 7, 7, 8, 0, 8, 0, 0, 0, 0, 7, 7, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 6, 6, 7, 0, 7, 0, 0, 0, 0, 7, 7, 0, 7, - 6, 7, 0, 7, 7, 8, 0, 7, 0, 0, 0, 0, 7, 8, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 7, 0, 7, 7, 7, 0, 8, 0, 0, 0, 0, 7, 8, 0, 8, -}; - -static const uint16_t huff_spec_a22_codes[] = { - 0x00, 0x02, 0x00, 0x03, 0x10, 0x3C, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x11, 0x3E, 0x00, 0x3D, - 0x0E, 0x00, 0x00, 0x39, 0x18, 0x26, 0x00, 0x75, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x24, 0x00, 0x6D, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x38, 0x00, 0x01, 0x1A, 0x6C, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x19, 0x74, 0x00, 0x27, - 0x16, 0x14, 0x00, 0x17, 0x76, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x35, 0x64, 0x00, 0x6F, - 0x26, 0x04, 0x00, 0x63, 0x22, 0xA2, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x67, 0xA0, 0x00, 0x0D, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2B, 0x52, 0x00, 0x0B, 0x20, 0x92, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x00, 0x95, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x17, 0x16, 0x00, 0x15, 0x34, 0x6E, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x77, 0x08, 0x00, 0x07, - 0x2A, 0x0A, 0x00, 0x53, 0x60, 0x94, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x21, 0x90, 0x00, 0x93, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x27, 0x62, 0x00, 0x05, 0x66, 0x0C, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x23, 0x96, 0x00, 0xA3, -}; - -static const uint8_t huff_spec_a23_bits[] = { - 3, 4, 0, 4, 5, 6, 0, 6, 0, 0, 0, 0, 5, 6, 0, 6, - 5, 7, 0, 6, 6, 8, 0, 7, 0, 0, 0, 0, 6, 8, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 7, 6, 7, 0, 8, 0, 0, 0, 0, 6, 7, 0, 8, - 5, 6, 0, 6, 7, 8, 0, 8, 0, 0, 0, 0, 6, 7, 0, 7, - 6, 8, 0, 7, 8, 9, 0, 9, 0, 0, 0, 0, 7, 9, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 8, 0, 8, 8, 9, 0, 9, 0, 0, 0, 0, 7, 8, 0, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 6, 6, 7, 0, 7, 0, 0, 0, 0, 7, 8, 0, 8, - 6, 8, 0, 8, 7, 9, 0, 8, 0, 0, 0, 0, 8, 9, 0, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 7, 0, 8, 7, 8, 0, 9, 0, 0, 0, 0, 8, 9, 0, 9, -}; - -static const uint16_t huff_spec_a23_codes[] = { - 0x006, 0x002, 0x000, 0x003, 0x016, 0x01E, 0x000, 0x021, 0x000, 0x000, 0x000, 0x000, - 0x017, 0x020, 0x000, 0x01F, 0x01C, 0x054, 0x000, 0x027, 0x010, 0x0A6, 0x000, 0x027, - 0x000, 0x000, 0x000, 0x000, 0x015, 0x0A4, 0x000, 0x02D, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x01D, 0x026, 0x000, 0x055, 0x014, 0x02C, 0x000, 0x0A5, 0x000, 0x000, 0x000, 0x000, - 0x011, 0x026, 0x000, 0x0A7, 0x01E, 0x000, 0x000, 0x003, 0x04A, 0x074, 0x000, 0x071, - 0x000, 0x000, 0x000, 0x000, 0x023, 0x00A, 0x000, 0x009, 0x018, 0x072, 0x000, 0x00D, - 0x0A2, 0x15A, 0x000, 0x123, 0x000, 0x000, 0x000, 0x000, 0x00F, 0x158, 0x000, 0x05D, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x01B, 0x0AE, 0x000, 0x077, 0x092, 0x140, 0x000, 0x121, - 0x000, 0x000, 0x000, 0x000, 0x025, 0x05E, 0x000, 0x143, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x01F, 0x002, 0x000, 0x001, 0x022, 0x008, 0x000, 0x00B, 0x000, 0x000, 0x000, 0x000, - 0x04B, 0x070, 0x000, 0x075, 0x01A, 0x076, 0x000, 0x0AF, 0x024, 0x142, 0x000, 0x05F, - 0x000, 0x000, 0x000, 0x000, 0x093, 0x120, 0x000, 0x141, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x019, 0x00C, 0x000, 0x073, 0x00E, 0x05C, 0x000, 0x159, 0x000, 0x000, 0x000, 0x000, - 0x0A3, 0x122, 0x000, 0x15B, -}; - -static const uint8_t huff_spec_a24_bits[] = { - 2, 4, 0, 4, 5, 6, 0, 6, 0, 0, 0, 0, 5, 6, 0, 6, - 5, 7, 0, 6, 6, 8, 0, 8, 0, 0, 0, 0, 6, 8, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 6, 0, 7, 6, 8, 0, 8, 0, 0, 0, 0, 6, 8, 0, 8, - 5, 7, 0, 7, 7, 9, 0, 9, 0, 0, 0, 0, 6, 8, 0, 8, - 6, 9, 0, 8, 8, 10, 0, 10, 0, 0, 0, 0, 8, 10, 0, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 8, 0, 9, 9, 10, 0, 10, 0, 0, 0, 0, 8, 9, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 7, 0, 7, 6, 8, 0, 8, 0, 0, 0, 0, 7, 9, 0, 9, - 6, 9, 0, 8, 8, 10, 0, 9, 0, 0, 0, 0, 9, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 8, 0, 9, 8, 9, 0, 10, 0, 0, 0, 0, 8, 10, 0, 10, -}; - -static const uint16_t huff_spec_a24_codes[] = { - 0x002, 0x002, 0x000, 0x003, 0x01E, 0x010, 0x000, 0x013, 0x000, 0x000, 0x000, 0x000, - 0x01F, 0x012, 0x000, 0x011, 0x01A, 0x030, 0x000, 0x01B, 0x000, 0x064, 0x000, 0x0C1, - 0x000, 0x000, 0x000, 0x000, 0x003, 0x052, 0x000, 0x07D, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x01B, 0x01A, 0x000, 0x031, 0x002, 0x07C, 0x000, 0x053, 0x000, 0x000, 0x000, 0x000, - 0x001, 0x0C0, 0x000, 0x065, 0x01C, 0x062, 0x000, 0x065, 0x02A, 0x198, 0x000, 0x19B, - 0x000, 0x000, 0x000, 0x000, 0x017, 0x078, 0x000, 0x07B, 0x004, 0x0FE, 0x000, 0x077, - 0x050, 0x33A, 0x000, 0x1F9, 0x000, 0x000, 0x000, 0x000, 0x073, 0x338, 0x000, 0x0E1, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x007, 0x066, 0x000, 0x187, 0x19E, 0x308, 0x000, 0x30B, - 0x000, 0x000, 0x000, 0x000, 0x075, 0x0E2, 0x000, 0x1FB, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x01D, 0x064, 0x000, 0x063, 0x016, 0x07A, 0x000, 0x079, 0x000, 0x000, 0x000, 0x000, - 0x02B, 0x19A, 0x000, 0x199, 0x006, 0x186, 0x000, 0x067, 0x074, 0x1FA, 0x000, 0x0E3, - 0x000, 0x000, 0x000, 0x000, 0x19F, 0x30A, 0x000, 0x309, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x005, 0x076, 0x000, 0x0FF, 0x072, 0x0E0, 0x000, 0x339, 0x000, 0x000, 0x000, 0x000, - 0x051, 0x1F8, 0x000, 0x33B, -}; - -static const uint8_t huff_spec_a31_bits[] = { - 0, 0, 4, 5, 0, 5, 4, 0, 0, 0, 5, 5, 0, 5, 5, 0, - 5, 5, 6, 6, 0, 6, 5, 5, 5, 6, 6, 7, 0, 7, 6, 6, - 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 6, 7, 0, 7, 6, 6, - 5, 5, 5, 6, 0, 6, 6, 5, 0, 0, 5, 5, 0, 5, 5, 0, -}; - -static const uint16_t huff_spec_a31_codes[] = { - 0x00, 0x00, 0x02, 0x18, 0x00, 0x19, 0x03, 0x00, 0x00, 0x00, 0x12, 0x02, 0x00, 0x09, 0x15, 0x00, - 0x1A, 0x0A, 0x3E, 0x2C, 0x00, 0x2F, 0x01, 0x0D, 0x0E, 0x38, 0x20, 0x78, 0x00, 0x7B, 0x23, 0x3B, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x3A, 0x22, 0x7A, 0x00, 0x79, 0x21, 0x39, - 0x1B, 0x0C, 0x00, 0x2E, 0x00, 0x2D, 0x3F, 0x0B, 0x00, 0x00, 0x14, 0x08, 0x00, 0x03, 0x13, 0x00, -}; - -static const uint8_t huff_spec_a32_bits[] = { - 4, 5, 5, 6, 0, 6, 5, 5, 5, 6, 5, 6, 0, 6, 5, 5, - 5, 5, 6, 7, 0, 7, 6, 5, 6, 6, 7, 7, 0, 7, 7, 6, - 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 7, 7, 0, 7, 7, 6, - 5, 5, 6, 7, 0, 7, 6, 5, 5, 5, 5, 6, 0, 6, 5, 6, -}; - -static const uint16_t huff_spec_a32_codes[] = { - 0x0D, 0x18, 0x16, 0x3A, 0x00, 0x3B, 0x17, 0x19, 0x12, 0x3E, 0x08, 0x1C, 0x00, 0x1B, 0x07, 0x01, - 0x10, 0x02, 0x28, 0x78, 0x00, 0x7B, 0x1F, 0x05, 0x2A, 0x16, 0x72, 0x2A, 0x00, 0x29, 0x71, 0x19, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x18, 0x70, 0x28, 0x00, 0x2B, 0x73, 0x17, - 0x11, 0x04, 0x1E, 0x7A, 0x00, 0x79, 0x29, 0x03, 0x13, 0x00, 0x06, 0x1A, 0x00, 0x1D, 0x09, 0x3F, -}; - -static const uint8_t huff_spec_a33_bits[] = { - 3, 4, 5, 6, 0, 6, 5, 4, 4, 5, 6, 7, 0, 7, 6, 5, - 5, 6, 6, 7, 0, 7, 6, 6, 6, 7, 8, 8, 0, 8, 8, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 8, 0, 8, 8, 7, - 5, 6, 6, 7, 0, 7, 6, 6, 4, 5, 6, 7, 0, 7, 6, 5, -}; - -static const uint16_t huff_spec_a33_codes[] = { - 0x05, 0x06, 0x10, 0x08, 0x00, 0x09, 0x11, 0x07, 0x04, 0x12, 0x3E, 0x6A, 0x00, 0x6D, 0x3D, 0x19, - 0x06, 0x3A, 0x06, 0x02, 0x00, 0x01, 0x05, 0x39, 0x02, 0x16, 0xDC, 0x2A, 0x00, 0x29, 0xDF, 0x69, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x68, 0xDE, 0x28, 0x00, 0x2B, 0xDD, 0x17, - 0x07, 0x38, 0x04, 0x00, 0x00, 0x03, 0x07, 0x3B, 0x05, 0x18, 0x3C, 0x6C, 0x00, 0x6B, 0x3F, 0x13, -}; - -static const uint8_t huff_spec_a34_bits[] = { - 2, 4, 5, 7, 0, 7, 5, 4, 4, 5, 6, 8, 0, 8, 6, 5, - 5, 6, 7, 8, 0, 8, 7, 6, 7, 8, 8, 10, 0, 10, 9, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 0, 10, 8, 8, - 5, 6, 7, 8, 0, 8, 7, 6, 4, 5, 6, 8, 0, 8, 6, 5, -}; - -static const uint16_t huff_spec_a34_codes[] = { - 0x000, 0x00A, 0x00A, 0x034, 0x000, 0x035, 0x00B, 0x00B, 0x008, 0x01C, 0x032, 0x0DA, - 0x000, 0x0DD, 0x035, 0x01F, 0x008, 0x01E, 0x03A, 0x06C, 0x000, 0x063, 0x039, 0x031, - 0x032, 0x06E, 0x060, 0x37A, 0x000, 0x379, 0x1BF, 0x0D9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x033, 0x0D8, 0x1BE, 0x378, 0x000, 0x37B, 0x061, 0x06F, - 0x009, 0x030, 0x038, 0x062, 0x000, 0x06D, 0x03B, 0x01F, 0x009, 0x01E, 0x034, 0x0DC, - 0x000, 0x0DB, 0x033, 0x01D, -}; - -static const uint8_t huff_spec_a41_bits[] = { - 0, 0, 0, 0, 6, 6, 7, 7, 0, 7, 7, 6, 6, 0, 0, 0, - 0, 0, 0, 0, 7, 7, 7, 7, 0, 7, 7, 7, 6, 0, 0, 0, - 0, 0, 0, 0, 7, 7, 7, 8, 0, 8, 7, 7, 7, 0, 0, 0, - 0, 0, 0, 0, 7, 7, 8, 8, 0, 8, 8, 7, 7, 0, 0, 0, - 7, 7, 7, 8, 7, 8, 8, 8, 0, 8, 8, 8, 7, 8, 7, 7, - 7, 7, 7, 7, 8, 8, 8, 9, 0, 8, 8, 8, 8, 7, 7, 7, - 7, 7, 8, 8, 8, 8, 9, 9, 0, 9, 8, 8, 8, 8, 8, 7, - 8, 8, 8, 8, 8, 9, 9, 9, 0, 9, 9, 9, 8, 8, 8, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8, 8, 8, 8, 8, 9, 9, 9, 0, 9, 9, 9, 8, 8, 8, 8, - 7, 7, 8, 8, 8, 8, 8, 9, 0, 9, 9, 8, 8, 8, 8, 7, - 7, 7, 7, 7, 8, 8, 8, 8, 0, 9, 8, 8, 8, 7, 7, 7, - 7, 7, 7, 8, 7, 8, 8, 8, 0, 8, 8, 8, 7, 8, 7, 7, - 0, 0, 0, 0, 7, 7, 8, 8, 0, 8, 8, 7, 7, 0, 0, 0, - 0, 0, 0, 0, 7, 7, 7, 8, 0, 8, 7, 7, 7, 0, 0, 0, - 0, 0, 0, 0, 6, 7, 7, 7, 0, 7, 7, 7, 7, 0, 0, 0, -}; - -static const uint16_t huff_spec_a41_codes[] = { - 0x000, 0x000, 0x000, 0x000, 0x018, 0x00E, 0x05E, 0x028, 0x000, 0x029, 0x05F, 0x00F, - 0x019, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x076, 0x06E, 0x03E, 0x004, - 0x000, 0x017, 0x045, 0x07B, 0x013, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x04A, 0x048, 0x010, 0x0CE, 0x000, 0x0E1, 0x023, 0x055, 0x053, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x008, 0x018, 0x0D6, 0x09E, 0x000, 0x09D, 0x0E5, 0x02B, - 0x01B, 0x000, 0x000, 0x000, 0x07C, 0x05C, 0x038, 0x0FC, 0x002, 0x0D2, 0x09A, 0x05C, - 0x000, 0x06B, 0x0A3, 0x0D9, 0x00F, 0x0FF, 0x03D, 0x061, 0x074, 0x056, 0x036, 0x000, - 0x0CC, 0x08C, 0x058, 0x1E2, 0x000, 0x00F, 0x05F, 0x0A1, 0x0D5, 0x00D, 0x03B, 0x059, - 0x040, 0x014, 0x0DA, 0x0B6, 0x084, 0x040, 0x1E0, 0x196, 0x000, 0x1A1, 0x00D, 0x043, - 0x087, 0x0C7, 0x0E3, 0x00B, 0x0F2, 0x0C4, 0x08E, 0x05A, 0x024, 0x1CC, 0x194, 0x168, - 0x000, 0x16B, 0x1A3, 0x1CF, 0x027, 0x069, 0x099, 0x0C9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x0F3, 0x0C8, 0x098, 0x068, 0x026, 0x1CE, 0x1A2, 0x16A, 0x000, 0x169, 0x195, 0x1CD, - 0x025, 0x05B, 0x08F, 0x0C5, 0x041, 0x00A, 0x0E2, 0x0C6, 0x086, 0x042, 0x00C, 0x1A0, - 0x000, 0x197, 0x1E1, 0x041, 0x085, 0x0B7, 0x0DB, 0x015, 0x075, 0x058, 0x03A, 0x00C, - 0x0D4, 0x0A0, 0x05E, 0x00E, 0x000, 0x1E3, 0x059, 0x08D, 0x0CD, 0x001, 0x037, 0x057, - 0x07D, 0x060, 0x03C, 0x0FE, 0x00E, 0x0D8, 0x0A2, 0x06A, 0x000, 0x05D, 0x09B, 0x0D3, - 0x003, 0x0FD, 0x039, 0x05D, 0x000, 0x000, 0x000, 0x000, 0x01A, 0x02A, 0x0E4, 0x09C, - 0x000, 0x09F, 0x0D7, 0x019, 0x009, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x052, 0x054, 0x022, 0x0E0, 0x000, 0x0CF, 0x011, 0x049, 0x04B, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x012, 0x07A, 0x044, 0x016, 0x000, 0x005, 0x03F, 0x06F, - 0x077, 0x000, 0x000, 0x000, -}; - -static const uint8_t huff_spec_a42_bits[] = { - 5, 6, 7, 7, 7, 7, 8, 8, 0, 8, 8, 7, 7, 7, 7, 6, - 6, 7, 7, 8, 7, 7, 8, 8, 0, 8, 8, 7, 7, 8, 7, 7, - 7, 7, 8, 8, 7, 8, 8, 9, 0, 9, 8, 8, 7, 8, 8, 7, - 8, 8, 8, 8, 8, 8, 8, 9, 0, 9, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 8, 8, 8, 9, 9, 0, 9, 9, 8, 8, 8, 7, 7, - 7, 7, 8, 8, 8, 9, 9, 9, 0, 9, 9, 9, 8, 8, 8, 7, - 8, 8, 8, 8, 9, 9, 9, 10, 0, 10, 9, 9, 9, 8, 8, 8, - 8, 8, 9, 9, 9, 9, 10, 10, 0, 10, 10, 9, 9, 9, 9, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8, 9, 9, 9, 9, 9, 10, 10, 0, 10, 10, 9, 9, 9, 9, 8, - 8, 8, 8, 8, 9, 9, 9, 10, 0, 10, 9, 9, 9, 8, 8, 8, - 7, 7, 8, 8, 8, 9, 9, 9, 0, 9, 9, 9, 8, 8, 8, 7, - 7, 7, 7, 8, 8, 8, 9, 9, 0, 9, 9, 8, 8, 8, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 9, 0, 9, 8, 8, 8, 8, 8, 8, - 7, 7, 8, 8, 7, 8, 8, 9, 0, 9, 8, 8, 7, 8, 8, 7, - 6, 7, 7, 8, 7, 7, 8, 8, 0, 8, 8, 7, 7, 8, 7, 7, -}; - -static const uint16_t huff_spec_a42_codes[] = { - 0x003, 0x018, 0x058, 0x000, 0x066, 0x03C, 0x0D6, 0x07C, 0x000, 0x07D, 0x0D7, 0x03D, - 0x067, 0x001, 0x059, 0x019, 0x002, 0x064, 0x036, 0x0DA, 0x04C, 0x01C, 0x0BE, 0x02C, - 0x000, 0x037, 0x0C5, 0x029, 0x04B, 0x0E7, 0x03B, 0x069, 0x044, 0x02E, 0x0FA, 0x092, - 0x020, 0x0F8, 0x086, 0x1FC, 0x000, 0x1E7, 0x07F, 0x0F5, 0x023, 0x0AD, 0x0FD, 0x02D, - 0x0F6, 0x0DC, 0x09C, 0x03E, 0x0F0, 0x0B6, 0x026, 0x186, 0x000, 0x18D, 0x02F, 0x0B5, - 0x0E1, 0x03D, 0x0AF, 0x0D9, 0x054, 0x040, 0x014, 0x0EC, 0x0BC, 0x054, 0x1C6, 0x108, - 0x000, 0x10B, 0x1C5, 0x069, 0x0B9, 0x0DF, 0x019, 0x047, 0x026, 0x008, 0x0E4, 0x0A2, - 0x056, 0x1DC, 0x142, 0x06A, 0x000, 0x091, 0x123, 0x1DF, 0x04B, 0x0A7, 0x0EB, 0x00B, - 0x0C0, 0x09E, 0x06A, 0x022, 0x1AA, 0x140, 0x092, 0x3CA, 0x000, 0x3A7, 0x04B, 0x121, - 0x18F, 0x007, 0x071, 0x0A5, 0x020, 0x004, 0x1A8, 0x174, 0x0E4, 0x068, 0x3A4, 0x2EE, - 0x000, 0x2ED, 0x3C9, 0x049, 0x0E7, 0x185, 0x1D1, 0x1FF, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x021, 0x1FE, 0x1D0, 0x184, 0x0E6, 0x048, 0x3C8, 0x2EC, 0x000, 0x2EF, 0x3A5, 0x069, - 0x0E5, 0x175, 0x1A9, 0x005, 0x0C1, 0x0A4, 0x070, 0x006, 0x18E, 0x120, 0x04A, 0x3A6, - 0x000, 0x3CB, 0x093, 0x141, 0x1AB, 0x023, 0x06B, 0x09F, 0x027, 0x00A, 0x0EA, 0x0A6, - 0x04A, 0x1DE, 0x122, 0x090, 0x000, 0x06B, 0x143, 0x1DD, 0x057, 0x0A3, 0x0E5, 0x009, - 0x055, 0x046, 0x018, 0x0DE, 0x0B8, 0x068, 0x1C4, 0x10A, 0x000, 0x109, 0x1C7, 0x055, - 0x0BD, 0x0ED, 0x015, 0x041, 0x0F7, 0x0D8, 0x0AE, 0x03C, 0x0E0, 0x0B4, 0x02E, 0x18C, - 0x000, 0x187, 0x027, 0x0B7, 0x0F1, 0x03F, 0x09D, 0x0DD, 0x045, 0x02C, 0x0FC, 0x0AC, - 0x022, 0x0F4, 0x07E, 0x1E6, 0x000, 0x1FD, 0x087, 0x0F9, 0x021, 0x093, 0x0FB, 0x02F, - 0x003, 0x068, 0x03A, 0x0E6, 0x04A, 0x028, 0x0C4, 0x036, 0x000, 0x02D, 0x0BF, 0x01D, - 0x04D, 0x0DB, 0x037, 0x065, -}; - -static const uint8_t huff_spec_a43_bits[] = { - 4, 6, 6, 7, 7, 8, 8, 9, 0, 9, 8, 8, 7, 7, 6, 6, - 5, 6, 7, 7, 7, 8, 8, 9, 0, 9, 8, 8, 7, 7, 7, 6, - 6, 7, 7, 7, 8, 8, 9, 9, 0, 9, 9, 8, 8, 7, 7, 7, - 7, 7, 7, 8, 8, 8, 9, 10, 0, 10, 9, 9, 8, 8, 7, 7, - 7, 7, 8, 8, 8, 9, 10, 10, 0, 10, 10, 9, 8, 8, 8, 7, - 8, 8, 8, 9, 9, 9, 10, 10, 0, 10, 10, 9, 9, 9, 8, 8, - 8, 9, 9, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 9, 9, - 9, 9, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 9, 9, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, - 8, 9, 9, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 9, 9, - 8, 8, 8, 9, 9, 9, 10, 10, 0, 10, 10, 9, 9, 9, 8, 8, - 7, 7, 8, 8, 8, 9, 10, 10, 0, 10, 10, 9, 8, 8, 8, 7, - 7, 7, 7, 8, 8, 9, 9, 10, 0, 10, 9, 8, 8, 8, 7, 7, - 6, 7, 7, 7, 8, 8, 9, 9, 0, 9, 9, 8, 8, 7, 7, 7, - 5, 6, 7, 7, 7, 8, 8, 9, 0, 9, 8, 8, 7, 7, 7, 6, -}; - -static const uint16_t huff_spec_a43_codes[] = { - 0x002, 0x03E, 0x016, 0x060, 0x04E, 0x0DC, 0x04A, 0x130, 0x000, 0x131, 0x04B, 0x0DD, - 0x04F, 0x061, 0x017, 0x03F, 0x002, 0x02C, 0x076, 0x042, 0x034, 0x0CE, 0x002, 0x0E8, - 0x000, 0x0CF, 0x001, 0x0D1, 0x037, 0x045, 0x07B, 0x02F, 0x014, 0x072, 0x052, 0x01A, - 0x0E0, 0x080, 0x198, 0x01E, 0x000, 0x01D, 0x19B, 0x083, 0x0DF, 0x019, 0x055, 0x079, - 0x050, 0x03C, 0x004, 0x0C4, 0x096, 0x00C, 0x0EA, 0x34A, 0x000, 0x34F, 0x0ED, 0x1D7, - 0x095, 0x0AF, 0x003, 0x03F, 0x046, 0x026, 0x0D6, 0x092, 0x046, 0x15A, 0x3A8, 0x108, - 0x000, 0x10F, 0x3A3, 0x135, 0x039, 0x091, 0x0D9, 0x031, 0x0D4, 0x0CA, 0x072, 0x1C6, - 0x136, 0x090, 0x2B2, 0x104, 0x000, 0x103, 0x111, 0x08B, 0x133, 0x1D3, 0x071, 0x0C9, - 0x03E, 0x1B4, 0x18C, 0x0CC, 0x38A, 0x2B0, 0x106, 0x0F2, 0x000, 0x0EF, 0x101, 0x113, - 0x3A1, 0x0CB, 0x18F, 0x1B7, 0x0EE, 0x092, 0x388, 0x348, 0x10A, 0x0F4, 0x0F0, 0x0EA, - 0x000, 0x0E9, 0x0ED, 0x0F7, 0x10D, 0x34D, 0x3AB, 0x0C9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x0EF, 0x0C8, 0x3AA, 0x34C, 0x10C, 0x0F6, 0x0EC, 0x0E8, 0x000, 0x0EB, 0x0F1, 0x0F5, - 0x10B, 0x349, 0x389, 0x093, 0x03F, 0x1B6, 0x18E, 0x0CA, 0x3A0, 0x112, 0x100, 0x0EE, - 0x000, 0x0F3, 0x107, 0x2B1, 0x38B, 0x0CD, 0x18D, 0x1B5, 0x0D5, 0x0C8, 0x070, 0x1D2, - 0x132, 0x08A, 0x110, 0x102, 0x000, 0x105, 0x2B3, 0x091, 0x137, 0x1C7, 0x073, 0x0CB, - 0x047, 0x030, 0x0D8, 0x090, 0x038, 0x134, 0x3A2, 0x10E, 0x000, 0x109, 0x3A9, 0x15B, - 0x047, 0x093, 0x0D7, 0x027, 0x051, 0x03E, 0x002, 0x0AE, 0x094, 0x1D6, 0x0EC, 0x34E, - 0x000, 0x34B, 0x0EB, 0x00D, 0x097, 0x0C5, 0x005, 0x03D, 0x015, 0x078, 0x054, 0x018, - 0x0DE, 0x082, 0x19A, 0x01C, 0x000, 0x01F, 0x199, 0x081, 0x0E1, 0x01B, 0x053, 0x073, - 0x003, 0x02E, 0x07A, 0x044, 0x036, 0x0D0, 0x000, 0x0CE, 0x000, 0x0E9, 0x003, 0x0CF, - 0x035, 0x043, 0x077, 0x02D, -}; - -static const uint8_t huff_spec_a44_bits[] = { - 4, 5, 6, 7, 7, 8, 9, 10, 0, 10, 9, 8, 7, 7, 6, 5, - 5, 6, 6, 7, 7, 8, 9, 10, 0, 10, 9, 8, 7, 7, 6, 6, - 6, 6, 7, 7, 8, 9, 10, 10, 0, 10, 10, 9, 8, 7, 7, 6, - 7, 7, 7, 8, 8, 9, 10, 10, 0, 10, 10, 9, 8, 8, 7, 7, - 7, 8, 8, 8, 9, 10, 10, 10, 0, 10, 10, 10, 9, 8, 8, 7, - 8, 8, 9, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 9, 8, - 9, 9, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 9, 9, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, - 8, 8, 9, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 9, 8, - 7, 7, 8, 8, 9, 10, 10, 10, 0, 10, 10, 10, 9, 8, 8, 8, - 7, 7, 7, 8, 8, 9, 10, 10, 0, 10, 10, 9, 8, 8, 7, 7, - 6, 6, 7, 7, 8, 9, 10, 10, 0, 10, 10, 9, 8, 7, 7, 6, - 5, 6, 6, 7, 7, 8, 9, 10, 0, 10, 9, 8, 7, 7, 6, 6, -}; - -static const uint16_t huff_spec_a44_codes[] = { - 0x00A, 0x012, 0x030, 0x06E, 0x024, 0x074, 0x0EC, 0x07E, 0x000, 0x07F, 0x0ED, 0x075, - 0x025, 0x06F, 0x031, 0x013, 0x010, 0x03C, 0x018, 0x05A, 0x002, 0x046, 0x09E, 0x07C, - 0x000, 0x079, 0x0E5, 0x04D, 0x007, 0x065, 0x01B, 0x03F, 0x02E, 0x016, 0x072, 0x01A, - 0x0D6, 0x1C6, 0x3B4, 0x066, 0x000, 0x06B, 0x3B7, 0x1D9, 0x0D5, 0x021, 0x075, 0x015, - 0x06C, 0x03E, 0x01E, 0x0CC, 0x044, 0x0F2, 0x082, 0x05C, 0x000, 0x05F, 0x087, 0x0F5, - 0x031, 0x0CF, 0x017, 0x059, 0x01C, 0x0EE, 0x0D0, 0x024, 0x1C0, 0x08E, 0x06E, 0x048, - 0x000, 0x04D, 0x06D, 0x089, 0x0F7, 0x033, 0x0D3, 0x001, 0x070, 0x028, 0x1C2, 0x0F0, - 0x08A, 0x074, 0x054, 0x040, 0x000, 0x043, 0x053, 0x073, 0x099, 0x0EF, 0x1C5, 0x02B, - 0x0E6, 0x04E, 0x08C, 0x080, 0x068, 0x058, 0x046, 0x02A, 0x000, 0x029, 0x045, 0x051, - 0x065, 0x085, 0x09B, 0x09D, 0x07A, 0x076, 0x060, 0x056, 0x04E, 0x02C, 0x024, 0x022, - 0x000, 0x021, 0x027, 0x02F, 0x04B, 0x05B, 0x063, 0x071, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x07B, 0x070, 0x062, 0x05A, 0x04A, 0x02E, 0x026, 0x020, 0x000, 0x023, 0x025, 0x02D, - 0x04F, 0x057, 0x061, 0x077, 0x0E7, 0x09C, 0x09A, 0x084, 0x064, 0x050, 0x044, 0x028, - 0x000, 0x02B, 0x047, 0x059, 0x069, 0x081, 0x08D, 0x04F, 0x071, 0x02A, 0x1C4, 0x0EE, - 0x098, 0x072, 0x052, 0x042, 0x000, 0x041, 0x055, 0x075, 0x08B, 0x0F1, 0x1C3, 0x029, - 0x01D, 0x000, 0x0D2, 0x032, 0x0F6, 0x088, 0x06C, 0x04C, 0x000, 0x049, 0x06F, 0x08F, - 0x1C1, 0x025, 0x0D1, 0x0EF, 0x06D, 0x058, 0x016, 0x0CE, 0x030, 0x0F4, 0x086, 0x05E, - 0x000, 0x05D, 0x083, 0x0F3, 0x045, 0x0CD, 0x01F, 0x03F, 0x02F, 0x014, 0x074, 0x020, - 0x0D4, 0x1D8, 0x3B6, 0x06A, 0x000, 0x067, 0x3B5, 0x1C7, 0x0D7, 0x01B, 0x073, 0x017, - 0x011, 0x03E, 0x01A, 0x064, 0x006, 0x04C, 0x0E4, 0x078, 0x000, 0x07D, 0x09F, 0x047, - 0x003, 0x05B, 0x019, 0x03D, -}; - -static const uint8_t huff_spec_a51_bits[] = { - 5, 5, 5, 5, 5, 6, 6, 6, 4, 4, 5, 5, 5, 5, 5, 5, - 0, 5, 5, 5, 5, 5, 5, 4, 4, 6, 6, 6, 5, 5, 5, 5, -}; - -static const uint16_t huff_spec_a51_codes[] = { - 0x19, 0x16, 0x12, 0x0E, 0x06, 0x3A, 0x38, 0x30, 0x00, 0x04, 0x1E, 0x1A, - 0x14, 0x10, 0x0C, 0x04, 0x00, 0x05, 0x0D, 0x11, 0x15, 0x1B, 0x1F, 0x05, - 0x01, 0x31, 0x39, 0x3B, 0x07, 0x0F, 0x13, 0x17, -}; - -static const uint8_t huff_spec_a52_bits[] = { - 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, - 0, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, -}; - -static const uint16_t huff_spec_a52_codes[] = { - 0x09, 0x04, 0x00, 0x1E, 0x1A, 0x14, 0x0C, 0x06, 0x18, 0x16, 0x0E, 0x04, - 0x3A, 0x38, 0x22, 0x20, 0x00, 0x21, 0x23, 0x39, 0x3B, 0x05, 0x0F, 0x17, - 0x19, 0x07, 0x0D, 0x15, 0x1B, 0x1F, 0x01, 0x05, -}; - -static const uint8_t huff_spec_a53_bits[] = { - 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 7, - 0, 7, 7, 7, 7, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4, -}; - -static const uint16_t huff_spec_a53_codes[] = { - 0x00, 0x0C, 0x08, 0x04, 0x1E, 0x16, 0x14, 0x06, 0x0C, 0x04, 0x38, 0x1E, - 0x76, 0x74, 0x3A, 0x38, 0x00, 0x39, 0x3B, 0x75, 0x77, 0x1F, 0x39, 0x05, - 0x0D, 0x07, 0x15, 0x17, 0x1F, 0x05, 0x09, 0x0D, -}; - -static const uint8_t huff_spec_a54_bits[] = { - 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, - 0, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, -}; - -static const uint16_t huff_spec_a54_codes[] = { - 0x02, 0x0E, 0x0A, 0x08, 0x02, 0x1A, 0x0E, 0x02, 0x00, 0x30, 0x18, 0x66, - 0x36, 0x34, 0xCA, 0xC8, 0x00, 0xC9, 0xCB, 0x35, 0x37, 0x67, 0x19, 0x31, - 0x01, 0x03, 0x0F, 0x1B, 0x03, 0x09, 0x0B, 0x0F, -}; - -static const uint8_t huff_spec_a61_bits[] = { - 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, - 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, - 5, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, -}; - -static const uint16_t huff_spec_a61_codes[] = { - 0x35, 0x30, 0x2A, 0x28, 0x24, 0x20, 0x18, 0x0E, 0x0C, 0x7E, 0x7C, 0x72, - 0x70, 0x68, 0x5E, 0x5C, 0x04, 0x0E, 0x08, 0x00, 0x3C, 0x3A, 0x36, 0x32, - 0x2C, 0x26, 0x22, 0x1A, 0x16, 0x14, 0x06, 0x04, 0x00, 0x05, 0x07, 0x15, - 0x17, 0x1B, 0x23, 0x27, 0x2D, 0x33, 0x37, 0x3B, 0x3D, 0x01, 0x09, 0x0F, - 0x05, 0x5D, 0x5F, 0x69, 0x71, 0x73, 0x7D, 0x7F, 0x0D, 0x0F, 0x19, 0x21, - 0x25, 0x29, 0x2B, 0x31, -}; - -static const uint8_t huff_spec_a62_bits[] = { - 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, - 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, -}; - -static const uint16_t huff_spec_a62_codes[] = { - 0x14, 0x0E, 0x08, 0x04, 0x02, 0x3E, 0x3C, 0x38, 0x34, 0x30, 0x2A, 0x24, - 0x1A, 0x18, 0x0E, 0x02, 0x32, 0x36, 0x2C, 0x26, 0x20, 0x16, 0x0C, 0x00, - 0x76, 0x74, 0x5E, 0x5C, 0x46, 0x44, 0x2A, 0x28, 0x00, 0x29, 0x2B, 0x45, - 0x47, 0x5D, 0x5F, 0x75, 0x77, 0x01, 0x0D, 0x17, 0x21, 0x27, 0x2D, 0x37, - 0x33, 0x03, 0x0F, 0x19, 0x1B, 0x25, 0x2B, 0x31, 0x35, 0x39, 0x3D, 0x3F, - 0x03, 0x05, 0x09, 0x0F, -}; - -static const uint8_t huff_spec_a63_bits[] = { - 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, - 0, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, -}; - -static const uint16_t huff_spec_a63_codes[] = { - 0x00, 0x1C, 0x18, 0x14, 0x10, 0x0A, 0x08, 0x02, 0x3E, 0x36, 0x2E, 0x2C, - 0x24, 0x1C, 0x0E, 0x08, 0x1E, 0x1A, 0x0C, 0x7A, 0x6A, 0x68, 0x4C, 0x32, - 0x16, 0x14, 0xF2, 0xF0, 0x9E, 0x9C, 0x62, 0x60, 0x00, 0x61, 0x63, 0x9D, - 0x9F, 0xF1, 0xF3, 0x15, 0x17, 0x33, 0x4D, 0x69, 0x6B, 0x7B, 0x0D, 0x1B, - 0x1F, 0x09, 0x0F, 0x1D, 0x25, 0x2D, 0x2F, 0x37, 0x3F, 0x03, 0x09, 0x0B, - 0x11, 0x15, 0x19, 0x1D, -}; - -static const uint8_t huff_spec_a64_bits[] = { - 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, - 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, - 6, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4, -}; - -static const uint16_t huff_spec_a64_codes[] = { - 0x006, 0x002, 0x01C, 0x01A, 0x016, 0x012, 0x00E, 0x00A, 0x002, 0x03E, - 0x032, 0x02A, 0x022, 0x020, 0x010, 0x07A, 0x000, 0x078, 0x060, 0x050, - 0x024, 0x006, 0x0C6, 0x0C4, 0x0A4, 0x04E, 0x00A, 0x008, 0x14E, 0x14C, - 0x09A, 0x098, 0x000, 0x099, 0x09B, 0x14D, 0x14F, 0x009, 0x00B, 0x04F, - 0x0A5, 0x0C5, 0x0C7, 0x007, 0x025, 0x051, 0x061, 0x079, 0x001, 0x07B, - 0x011, 0x021, 0x023, 0x02B, 0x033, 0x03F, 0x003, 0x00B, 0x00F, 0x013, - 0x017, 0x01B, 0x01D, 0x003, -}; - -static const uint8_t huff_spec_a71_bits[] = { - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, - 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, -}; - -static const uint16_t huff_spec_a71_codes[] = { - 0x6C, 0x66, 0x62, 0x5C, 0x56, 0x50, 0x52, 0x4E, 0x48, 0x3E, 0x36, 0x34, 0x2A, 0x26, 0x1E, 0x16, - 0x0E, 0x08, 0x00, 0xF6, 0xF4, 0xEE, 0xEC, 0xE2, 0xE0, 0xDA, 0xD2, 0xD0, 0xBE, 0xBC, 0xB2, 0xB0, - 0x0C, 0x20, 0x1C, 0x16, 0x10, 0x08, 0x02, 0x7E, 0x7C, 0x78, 0x74, 0x72, 0x6E, 0x6A, 0x64, 0x60, - 0x5A, 0x54, 0x4C, 0x4A, 0x46, 0x44, 0x3C, 0x32, 0x30, 0x28, 0x24, 0x1C, 0x14, 0x0C, 0x0A, 0x02, - 0x00, 0x03, 0x0B, 0x0D, 0x15, 0x1D, 0x25, 0x29, 0x31, 0x33, 0x3D, 0x45, 0x47, 0x4B, 0x4D, 0x55, - 0x5B, 0x61, 0x65, 0x6B, 0x6F, 0x73, 0x75, 0x79, 0x7D, 0x7F, 0x03, 0x09, 0x11, 0x17, 0x1D, 0x21, - 0x0D, 0xB1, 0xB3, 0xBD, 0xBF, 0xD1, 0xD3, 0xDB, 0xE1, 0xE3, 0xED, 0xEF, 0xF5, 0xF7, 0x01, 0x09, - 0x0F, 0x17, 0x1F, 0x27, 0x2B, 0x35, 0x37, 0x3F, 0x49, 0x4F, 0x53, 0x51, 0x57, 0x5D, 0x63, 0x67, -}; - -static const uint8_t huff_spec_a72_bits[] = { - 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, -}; - -static const uint16_t huff_spec_a72_codes[] = { - 0x2A, 0x24, 0x1C, 0x18, 0x12, 0x0E, 0x0A, 0x06, 0x02, 0x7E, 0x7C, 0x7A, 0x76, 0x72, 0x70, 0x6A, - 0x68, 0x62, 0x5C, 0x5A, 0x52, 0x4E, 0x46, 0x42, 0x3C, 0x34, 0x2A, 0x28, 0x20, 0x12, 0x10, 0x08, - 0x66, 0x74, 0x6C, 0x64, 0x5E, 0x58, 0x50, 0x44, 0x40, 0x36, 0x2C, 0x22, 0x1A, 0x0A, 0x02, 0x00, - 0xF2, 0xF0, 0xDE, 0xDC, 0xC2, 0xC0, 0xAE, 0xAC, 0x9A, 0x98, 0x7E, 0x7C, 0x5E, 0x5C, 0x32, 0x30, - 0x00, 0x31, 0x33, 0x5D, 0x5F, 0x7D, 0x7F, 0x99, 0x9B, 0xAD, 0xAF, 0xC1, 0xC3, 0xDD, 0xDF, 0xF1, - 0xF3, 0x01, 0x03, 0x0B, 0x1B, 0x23, 0x2D, 0x37, 0x41, 0x45, 0x51, 0x59, 0x5F, 0x65, 0x6D, 0x75, - 0x67, 0x09, 0x11, 0x13, 0x21, 0x29, 0x2B, 0x35, 0x3D, 0x43, 0x47, 0x4F, 0x53, 0x5B, 0x5D, 0x63, - 0x69, 0x6B, 0x71, 0x73, 0x77, 0x7B, 0x7D, 0x7F, 0x03, 0x07, 0x0B, 0x0F, 0x13, 0x19, 0x1D, 0x25, -}; - -static const uint8_t huff_spec_a73_bits[] = { - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, -}; - -static const uint16_t huff_spec_a73_codes[] = { - 0x003, 0x03E, 0x038, 0x034, 0x030, 0x02C, 0x028, 0x024, 0x020, 0x01C, 0x016, 0x014, - 0x00E, 0x00A, 0x004, 0x000, 0x07A, 0x076, 0x06E, 0x06C, 0x064, 0x05E, 0x056, 0x04E, - 0x04C, 0x044, 0x036, 0x030, 0x022, 0x018, 0x012, 0x004, 0x03C, 0x03E, 0x032, 0x024, - 0x020, 0x010, 0x0F2, 0x0F0, 0x0E8, 0x0CE, 0x0BA, 0x0B8, 0x0A8, 0x08C, 0x06A, 0x04E, - 0x04C, 0x034, 0x00E, 0x00C, 0x1D6, 0x1D4, 0x19A, 0x198, 0x156, 0x154, 0x11E, 0x11C, - 0x0D2, 0x0D0, 0x06E, 0x06C, 0x000, 0x06D, 0x06F, 0x0D1, 0x0D3, 0x11D, 0x11F, 0x155, - 0x157, 0x199, 0x19B, 0x1D5, 0x1D7, 0x00D, 0x00F, 0x035, 0x04D, 0x04F, 0x06B, 0x08D, - 0x0A9, 0x0B9, 0x0BB, 0x0CF, 0x0E9, 0x0F1, 0x0F3, 0x011, 0x021, 0x025, 0x033, 0x03F, - 0x03D, 0x005, 0x013, 0x019, 0x023, 0x031, 0x037, 0x045, 0x04D, 0x04F, 0x057, 0x05F, - 0x065, 0x06D, 0x06F, 0x077, 0x07B, 0x001, 0x005, 0x00B, 0x00F, 0x015, 0x017, 0x01D, - 0x021, 0x025, 0x029, 0x02D, 0x031, 0x035, 0x039, 0x03F, -}; - -static const uint8_t huff_spec_a74_bits[] = { - 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, - 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, -}; - -static const uint16_t huff_spec_a74_codes[] = { - 0x00D, 0x00A, 0x004, 0x000, 0x03A, 0x036, 0x032, 0x030, 0x02C, 0x028, 0x026, 0x022, - 0x01E, 0x018, 0x012, 0x00E, 0x006, 0x07E, 0x07A, 0x070, 0x06A, 0x05E, 0x056, 0x054, - 0x048, 0x040, 0x038, 0x022, 0x01A, 0x00A, 0x0F8, 0x0E6, 0x008, 0x0FA, 0x0F0, 0x0D2, - 0x0BA, 0x0B8, 0x094, 0x084, 0x074, 0x042, 0x032, 0x1E6, 0x1CA, 0x1C8, 0x1A2, 0x12E, - 0x10E, 0x10C, 0x0EC, 0x082, 0x062, 0x060, 0x3CA, 0x3C8, 0x342, 0x340, 0x25A, 0x258, - 0x1DE, 0x1DC, 0x102, 0x100, 0x000, 0x101, 0x103, 0x1DD, 0x1DF, 0x259, 0x25B, 0x341, - 0x343, 0x3C9, 0x3CB, 0x061, 0x063, 0x083, 0x0ED, 0x10D, 0x10F, 0x12F, 0x1A3, 0x1C9, - 0x1CB, 0x1E7, 0x033, 0x043, 0x075, 0x085, 0x095, 0x0B9, 0x0BB, 0x0D3, 0x0F1, 0x0FB, - 0x009, 0x0E7, 0x0F9, 0x00B, 0x01B, 0x023, 0x039, 0x041, 0x049, 0x055, 0x057, 0x05F, - 0x06B, 0x071, 0x07B, 0x07F, 0x007, 0x00F, 0x013, 0x019, 0x01F, 0x023, 0x027, 0x029, - 0x02D, 0x031, 0x033, 0x037, 0x03B, 0x001, 0x005, 0x00B, -}; - -static const uint8_t huff_spec_b22_bits[] = { - 0, 4, 0, 4, 4, 5, 0, 5, 0, 0, 0, 0, 4, 5, 0, 5, - 4, 7, 0, 6, 6, 9, 0, 7, 0, 0, 0, 0, 6, 9, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 6, 0, 7, 6, 7, 0, 9, 0, 0, 0, 0, 6, 7, 0, 9, - 4, 8, 0, 8, 8, 10, 0, 10, 0, 0, 0, 0, 6, 9, 0, 9, - 5, 10, 0, 9, 9, 10, 0, 10, 0, 0, 0, 0, 7, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 9, 0, 10, 9, 10, 0, 10, 0, 0, 0, 0, 7, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 8, 0, 8, 6, 9, 0, 9, 0, 0, 0, 0, 8, 10, 0, 10, - 6, 10, 0, 9, 7, 10, 0, 10, 0, 0, 0, 0, 9, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 9, 0, 10, 7, 10, 0, 10, 0, 0, 0, 0, 9, 10, 0, 10, -}; - -static const uint16_t huff_spec_b22_codes[] = { - 0x000, 0x00E, 0x000, 0x00F, 0x008, 0x006, 0x000, 0x00B, 0x000, 0x000, 0x000, 0x000, - 0x009, 0x00A, 0x000, 0x007, 0x006, 0x00A, 0x000, 0x029, 0x006, 0x158, 0x000, 0x023, - 0x000, 0x000, 0x000, 0x000, 0x013, 0x174, 0x000, 0x021, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x007, 0x028, 0x000, 0x00B, 0x012, 0x020, 0x000, 0x175, 0x000, 0x000, 0x000, 0x000, - 0x007, 0x022, 0x000, 0x159, 0x00C, 0x0BC, 0x000, 0x0BF, 0x022, 0x2B8, 0x000, 0x2BB, - 0x000, 0x000, 0x000, 0x000, 0x00B, 0x170, 0x000, 0x15B, 0x000, 0x04E, 0x000, 0x15F, - 0x042, 0x04A, 0x000, 0x041, 0x000, 0x000, 0x000, 0x000, 0x055, 0x044, 0x000, 0x04D, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x02D, 0x172, 0x000, 0x2ED, 0x040, 0x042, 0x000, 0x047, - 0x000, 0x000, 0x000, 0x000, 0x013, 0x2EE, 0x000, 0x049, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x00D, 0x0BE, 0x000, 0x0BD, 0x00A, 0x15A, 0x000, 0x171, 0x000, 0x000, 0x000, 0x000, - 0x023, 0x2BA, 0x000, 0x2B9, 0x02C, 0x2EC, 0x000, 0x173, 0x012, 0x048, 0x000, 0x2EF, - 0x000, 0x000, 0x000, 0x000, 0x041, 0x046, 0x000, 0x043, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x001, 0x15E, 0x000, 0x04F, 0x054, 0x04C, 0x000, 0x045, 0x000, 0x000, 0x000, 0x000, - 0x043, 0x040, 0x000, 0x04B, -}; - -static const uint8_t huff_spec_b23_bits[] = { - 2, 4, 0, 4, 4, 6, 0, 6, 0, 0, 0, 0, 4, 6, 0, 6, - 4, 9, 0, 7, 7, 9, 0, 8, 0, 0, 0, 0, 7, 9, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 7, 0, 9, 7, 8, 0, 9, 0, 0, 0, 0, 7, 8, 0, 9, - 4, 8, 0, 8, 9, 10, 0, 10, 0, 0, 0, 0, 7, 10, 0, 10, - 7, 10, 0, 10, 10, 10, 0, 10, 0, 0, 0, 0, 9, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 10, 0, 10, 10, 10, 0, 10, 0, 0, 0, 0, 8, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 4, 8, 0, 8, 7, 10, 0, 10, 0, 0, 0, 0, 9, 10, 0, 10, - 7, 10, 0, 10, 8, 10, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 10, 0, 10, 9, 10, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10, -}; - -static const uint16_t huff_spec_b23_codes[] = { - 0x003, 0x008, 0x000, 0x009, 0x002, 0x018, 0x000, 0x01B, 0x000, 0x000, 0x000, 0x000, - 0x003, 0x01A, 0x000, 0x019, 0x000, 0x17C, 0x000, 0x055, 0x056, 0x0E8, 0x000, 0x07D, - 0x000, 0x000, 0x000, 0x000, 0x059, 0x0F6, 0x000, 0x07F, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x001, 0x054, 0x000, 0x17D, 0x058, 0x07E, 0x000, 0x0F7, 0x000, 0x000, 0x000, 0x000, - 0x057, 0x07C, 0x000, 0x0E9, 0x004, 0x0A2, 0x000, 0x0A1, 0x17A, 0x1DA, 0x000, 0x1D9, - 0x000, 0x000, 0x000, 0x000, 0x053, 0x1E8, 0x000, 0x2F3, 0x05C, 0x1D6, 0x000, 0x1E7, - 0x1EA, 0x1E2, 0x000, 0x1CF, 0x000, 0x000, 0x000, 0x000, 0x17F, 0x1CA, 0x000, 0x1DD, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x05B, 0x2F0, 0x000, 0x1DF, 0x1E4, 0x1CC, 0x000, 0x1D5, - 0x000, 0x000, 0x000, 0x000, 0x071, 0x1E0, 0x000, 0x1C9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x005, 0x0A0, 0x000, 0x0A3, 0x052, 0x2F2, 0x000, 0x1E9, 0x000, 0x000, 0x000, 0x000, - 0x17B, 0x1D8, 0x000, 0x1DB, 0x05A, 0x1DE, 0x000, 0x2F1, 0x070, 0x1C8, 0x000, 0x1E1, - 0x000, 0x000, 0x000, 0x000, 0x1E5, 0x1D4, 0x000, 0x1CD, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x05D, 0x1E6, 0x000, 0x1D7, 0x17E, 0x1DC, 0x000, 0x1CB, 0x000, 0x000, 0x000, 0x000, - 0x1EB, 0x1CE, 0x000, 0x1E3, -}; - -static const uint8_t huff_spec_b24_bits[] = { - 1, 4, 0, 4, 5, 7, 0, 7, 0, 0, 0, 0, 5, 7, 0, 7, - 5, 9, 0, 7, 8, 10, 0, 9, 0, 0, 0, 0, 7, 10, 0, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 7, 0, 9, 7, 9, 0, 10, 0, 0, 0, 0, 8, 9, 0, 10, - 5, 9, 0, 8, 9, 10, 0, 10, 0, 0, 0, 0, 7, 10, 0, 10, - 7, 10, 0, 10, 10, 10, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 10, 0, 10, 10, 10, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 5, 8, 0, 9, 7, 10, 0, 10, 0, 0, 0, 0, 9, 10, 0, 10, - 7, 10, 0, 10, 10, 10, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, 10, 0, 10, 10, 10, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10, -}; - -static const uint16_t huff_spec_b24_codes[] = { - 0x001, 0x000, 0x000, 0x001, 0x00A, 0x01C, 0x000, 0x033, 0x000, 0x000, 0x000, 0x000, - 0x00B, 0x032, 0x000, 0x01D, 0x008, 0x0D8, 0x000, 0x031, 0x06E, 0x0FA, 0x000, 0x0D7, - 0x000, 0x000, 0x000, 0x000, 0x011, 0x0F4, 0x000, 0x0D5, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x009, 0x030, 0x000, 0x0D9, 0x010, 0x0D4, 0x000, 0x0F5, 0x000, 0x000, 0x000, 0x000, - 0x06F, 0x0D6, 0x000, 0x0FB, 0x00E, 0x0DA, 0x000, 0x025, 0x0D2, 0x0D4, 0x000, 0x0DB, - 0x000, 0x000, 0x000, 0x000, 0x017, 0x0FE, 0x000, 0x0FD, 0x014, 0x0DC, 0x000, 0x0F9, - 0x0F2, 0x0D6, 0x000, 0x09B, 0x000, 0x000, 0x000, 0x000, 0x1A3, 0x09C, 0x000, 0x0D3, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x019, 0x0F6, 0x000, 0x0D9, 0x0F0, 0x09E, 0x000, 0x0D1, - 0x000, 0x000, 0x000, 0x000, 0x1A1, 0x0DE, 0x000, 0x099, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x00F, 0x024, 0x000, 0x0DB, 0x016, 0x0FC, 0x000, 0x0FF, 0x000, 0x000, 0x000, 0x000, - 0x0D3, 0x0DA, 0x000, 0x0D5, 0x018, 0x0D8, 0x000, 0x0F7, 0x1A0, 0x098, 0x000, 0x0DF, - 0x000, 0x000, 0x000, 0x000, 0x0F1, 0x0D0, 0x000, 0x09F, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x015, 0x0F8, 0x000, 0x0DD, 0x1A2, 0x0D2, 0x000, 0x09D, 0x000, 0x000, 0x000, 0x000, - 0x0F3, 0x09A, 0x000, 0x0D7 -}; - -static const uint8_t huff_spec_b32_bits[] = { - 2, 4, 5, 6, 0, 6, 5, 4, 5, 6, 6, 7, 0, 6, 5, 6, - 5, 6, 7, 7, 0, 8, 7, 6, 6, 7, 8, 9, 0, 9, 8, 7, - 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 8, 9, 0, 9, 8, 7, - 5, 6, 7, 8, 0, 7, 7, 6, 5, 6, 5, 6, 0, 7, 6, 6, -}; - -static const uint16_t huff_spec_b32_codes[] = { - 0x001, 0x002, 0x01E, 0x02A, 0x000, 0x02B, 0x01F, 0x003, 0x016, 0x020, 0x03A, 0x064, - 0x000, 0x005, 0x001, 0x023, 0x01A, 0x026, 0x070, 0x00C, 0x000, 0x0CF, 0x073, 0x031, - 0x024, 0x00E, 0x0CC, 0x146, 0x000, 0x145, 0x0A1, 0x053, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x025, 0x052, 0x0A0, 0x144, 0x000, 0x147, 0x0CD, 0x00F, - 0x01B, 0x030, 0x072, 0x0CE, 0x000, 0x00D, 0x071, 0x027, 0x017, 0x022, 0x000, 0x004, - 0x000, 0x065, 0x03B, 0x021, -}; - -static const uint8_t huff_spec_b33_bits[] = { - 2, 4, 5, 7, 0, 7, 5, 4, 4, 5, 6, 8, 0, 7, 6, 5, - 5, 6, 7, 9, 0, 8, 7, 6, 7, 8, 9, 10, 0, 10, 9, 8, - 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 0, 10, 9, 8, - 5, 6, 7, 8, 0, 9, 7, 6, 4, 5, 6, 7, 0, 8, 6, 5, -}; - -static const uint16_t huff_spec_b33_codes[] = { - 0x003, 0x008, 0x014, 0x05E, 0x000, 0x05F, 0x015, 0x009, 0x004, 0x002, 0x01C, 0x0BA, - 0x000, 0x011, 0x01F, 0x001, 0x00C, 0x00C, 0x014, 0x166, 0x000, 0x02D, 0x013, 0x00F, - 0x05A, 0x0B0, 0x05E, 0x0B8, 0x000, 0x0BB, 0x165, 0x0B9, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x05B, 0x0B8, 0x164, 0x0BA, 0x000, 0x0B9, 0x05F, 0x0B1, - 0x00D, 0x00E, 0x012, 0x02C, 0x000, 0x167, 0x015, 0x00D, 0x005, 0x000, 0x01E, 0x010, - 0x000, 0x0BB, 0x01D, 0x003 -}; - -static const uint8_t huff_spec_b34_bits[] = { - 1, 4, 6, 8, 0, 8, 6, 4, 4, 6, 7, 9, 0, 8, 7, 6, - 6, 7, 8, 10, 0, 10, 8, 7, 8, 9, 10, 10, 0, 10, 10, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 10, 10, 0, 10, 10, 9, - 6, 7, 8, 10, 0, 10, 8, 7, 4, 6, 7, 8, 0, 9, 7, 6, -}; - -static const uint16_t huff_spec_b34_codes[] = { - 0x000, 0x00A, 0x038, 0x0EE, 0x000, 0x0EF, 0x039, 0x00B, 0x008, 0x03C, 0x06E, 0x1D8, - 0x000, 0x0C1, 0x075, 0x03F, 0x032, 0x068, 0x0C4, 0x358, 0x000, 0x30F, 0x0C7, 0x06D, - 0x0D4, 0x1AE, 0x30C, 0x308, 0x000, 0x30B, 0x35B, 0x1DB, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x0D5, 0x1DA, 0x35A, 0x30A, 0x000, 0x309, 0x30D, 0x1AF, - 0x033, 0x06C, 0x0C6, 0x30E, 0x000, 0x359, 0x0C5, 0x069, 0x009, 0x03E, 0x074, 0x0C0, - 0x000, 0x1D9, 0x06F, 0x03D, -}; - -static const uint8_t huff_spec_b42_bits[] = { - 4, 5, 6, 8, 6, 7, 8, 8, 0, 8, 8, 7, 6, 8, 6, 5, - 5, 6, 7, 8, 7, 7, 8, 9, 0, 8, 8, 7, 7, 8, 7, 6, - 7, 7, 8, 9, 7, 8, 9, 9, 0, 9, 9, 8, 7, 9, 8, 7, - 8, 9, 9, 10, 8, 8, 9, 10, 0, 10, 9, 8, 8, 10, 9, 8, - 6, 7, 8, 8, 9, 9, 10, 10, 0, 10, 10, 9, 9, 8, 8, 7, - 7, 7, 8, 9, 9, 10, 10, 10, 0, 10, 10, 10, 9, 9, 8, 7, - 8, 8, 9, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 9, 8, - 8, 9, 9, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 9, 9, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8, 9, 9, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 9, 9, - 8, 8, 9, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 9, 8, - 7, 7, 8, 9, 9, 10, 10, 10, 0, 10, 10, 10, 9, 9, 8, 7, - 6, 7, 8, 8, 9, 9, 10, 10, 0, 10, 10, 9, 9, 8, 8, 7, - 8, 8, 9, 10, 8, 8, 9, 10, 0, 10, 9, 8, 8, 10, 9, 9, - 7, 7, 8, 9, 7, 8, 9, 9, 0, 9, 9, 8, 7, 9, 8, 7, - 5, 6, 7, 8, 7, 7, 8, 8, 0, 9, 8, 7, 7, 8, 7, 6, -}; - -static const uint16_t huff_spec_b42_codes[] = { - 0x00E, 0x018, 0x010, 0x0F0, 0x024, 0x05A, 0x0F6, 0x078, 0x000, 0x079, 0x0F7, 0x05B, - 0x025, 0x0F1, 0x011, 0x019, 0x00C, 0x014, 0x01C, 0x036, 0x05C, 0x012, 0x09E, 0x1E4, - 0x000, 0x00B, 0x0A9, 0x03B, 0x05F, 0x071, 0x019, 0x017, 0x06E, 0x000, 0x03E, 0x114, - 0x002, 0x0B0, 0x1AA, 0x07A, 0x000, 0x099, 0x1E7, 0x0B3, 0x00B, 0x131, 0x07F, 0x00D, - 0x0D8, 0x1FE, 0x112, 0x22E, 0x086, 0x010, 0x134, 0x35C, 0x000, 0x35F, 0x133, 0x013, - 0x081, 0x22D, 0x119, 0x07B, 0x00A, 0x050, 0x0F8, 0x04E, 0x1B4, 0x154, 0x3EC, 0x0D2, - 0x000, 0x0D7, 0x3D7, 0x137, 0x1FD, 0x073, 0x0FD, 0x057, 0x052, 0x010, 0x08E, 0x1E8, - 0x11A, 0x3EE, 0x0F2, 0x03C, 0x000, 0x03F, 0x0F1, 0x3D5, 0x111, 0x1F5, 0x09D, 0x025, - 0x0D2, 0x082, 0x1A0, 0x0F8, 0x36E, 0x0D4, 0x072, 0x03A, 0x000, 0x027, 0x071, 0x07D, - 0x36D, 0x0FB, 0x1AD, 0x085, 0x00C, 0x1A8, 0x03C, 0x346, 0x0D0, 0x076, 0x024, 0x020, - 0x000, 0x023, 0x039, 0x075, 0x07F, 0x345, 0x09B, 0x157, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x00D, 0x156, 0x09A, 0x344, 0x07E, 0x074, 0x038, 0x022, 0x000, 0x021, 0x025, 0x077, - 0x0D1, 0x347, 0x03D, 0x1A9, 0x0D3, 0x084, 0x1AC, 0x0FA, 0x36C, 0x07C, 0x070, 0x026, - 0x000, 0x03B, 0x073, 0x0D5, 0x36F, 0x0F9, 0x1A1, 0x083, 0x053, 0x024, 0x09C, 0x1F4, - 0x110, 0x3D4, 0x0F0, 0x03E, 0x000, 0x03D, 0x0F3, 0x3EF, 0x11B, 0x1E9, 0x08F, 0x011, - 0x00B, 0x056, 0x0FC, 0x072, 0x1FC, 0x136, 0x3D6, 0x0D6, 0x000, 0x0D3, 0x3ED, 0x155, - 0x1B5, 0x04F, 0x0F9, 0x051, 0x0D9, 0x07A, 0x118, 0x22C, 0x080, 0x012, 0x132, 0x35E, - 0x000, 0x35D, 0x135, 0x011, 0x087, 0x22F, 0x113, 0x1FF, 0x06F, 0x00C, 0x07E, 0x130, - 0x00A, 0x0B2, 0x1E6, 0x098, 0x000, 0x07B, 0x1AB, 0x0B1, 0x003, 0x115, 0x03F, 0x001, - 0x00D, 0x016, 0x018, 0x070, 0x05E, 0x03A, 0x0A8, 0x00A, 0x000, 0x1E5, 0x09F, 0x013, - 0x05D, 0x037, 0x01D, 0x015, -}; - -static const uint8_t huff_spec_b43_bits[] = { - 2, 5, 6, 7, 7, 8, 8, 9, 0, 9, 8, 8, 7, 7, 6, 5, - 5, 6, 7, 8, 7, 8, 9, 10, 0, 10, 9, 8, 7, 8, 7, 6, - 6, 7, 8, 9, 8, 9, 10, 10, 0, 10, 10, 9, 8, 9, 8, 7, - 7, 8, 9, 10, 9, 9, 10, 10, 0, 10, 10, 10, 9, 10, 9, 8, - 7, 8, 8, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 8, 7, - 8, 8, 9, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 9, 8, - 9, 9, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 9, 9, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 9, - 8, 8, 9, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 9, 8, - 7, 7, 8, 9, 10, 10, 10, 10, 0, 10, 10, 10, 10, 9, 8, 8, - 7, 8, 9, 10, 9, 10, 10, 10, 0, 10, 10, 9, 9, 10, 9, 8, - 6, 7, 8, 9, 8, 9, 10, 10, 0, 10, 10, 9, 8, 9, 8, 7, - 5, 6, 7, 8, 7, 8, 9, 10, 0, 10, 9, 8, 7, 8, 7, 6, -}; - -static const uint16_t huff_spec_b43_codes[] = { - 0x001, 0x01E, 0x022, 0x018, 0x064, 0x0EC, 0x008, 0x100, 0x000, 0x101, 0x009, 0x0ED, - 0x065, 0x019, 0x023, 0x01F, 0x01A, 0x030, 0x056, 0x09A, 0x00A, 0x090, 0x12C, 0x0A6, - 0x000, 0x0A9, 0x12F, 0x093, 0x00F, 0x09F, 0x059, 0x039, 0x00E, 0x054, 0x0BC, 0x19E, - 0x082, 0x176, 0x0AC, 0x088, 0x000, 0x08B, 0x0AF, 0x19D, 0x095, 0x1D1, 0x0BF, 0x051, - 0x002, 0x098, 0x1D4, 0x0B8, 0x170, 0x046, 0x090, 0x060, 0x000, 0x067, 0x095, 0x0BD, - 0x173, 0x0B5, 0x1D3, 0x09D, 0x052, 0x0EE, 0x034, 0x174, 0x0BA, 0x09C, 0x080, 0x044, - 0x000, 0x047, 0x06D, 0x099, 0x0BF, 0x16F, 0x085, 0x001, 0x0CC, 0x036, 0x16C, 0x0B0, - 0x09A, 0x084, 0x04E, 0x03E, 0x000, 0x037, 0x04B, 0x06B, 0x0A1, 0x0B3, 0x16B, 0x087, - 0x1D6, 0x102, 0x0A4, 0x092, 0x068, 0x04C, 0x034, 0x030, 0x000, 0x02D, 0x03D, 0x049, - 0x083, 0x097, 0x0AB, 0x169, 0x0B6, 0x09E, 0x06E, 0x064, 0x040, 0x038, 0x02E, 0x02A, - 0x000, 0x029, 0x033, 0x03B, 0x043, 0x063, 0x087, 0x0A3, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x0B7, 0x0A2, 0x086, 0x062, 0x042, 0x03A, 0x032, 0x028, 0x000, 0x02B, 0x02F, 0x039, - 0x041, 0x065, 0x06F, 0x09F, 0x1D7, 0x168, 0x0AA, 0x096, 0x082, 0x048, 0x03C, 0x02C, - 0x000, 0x031, 0x035, 0x04D, 0x069, 0x093, 0x0A5, 0x103, 0x0CD, 0x086, 0x16A, 0x0B2, - 0x0A0, 0x06A, 0x04A, 0x036, 0x000, 0x03F, 0x04F, 0x085, 0x09B, 0x0B1, 0x16D, 0x037, - 0x053, 0x000, 0x084, 0x16E, 0x0BE, 0x098, 0x06C, 0x046, 0x000, 0x045, 0x081, 0x09D, - 0x0BB, 0x175, 0x035, 0x0EF, 0x003, 0x09C, 0x1D2, 0x0B4, 0x172, 0x0BC, 0x094, 0x066, - 0x000, 0x061, 0x091, 0x047, 0x171, 0x0B9, 0x1D5, 0x099, 0x00F, 0x050, 0x0BE, 0x1D0, - 0x094, 0x19C, 0x0AE, 0x08A, 0x000, 0x089, 0x0AD, 0x177, 0x083, 0x19F, 0x0BD, 0x055, - 0x01B, 0x038, 0x058, 0x09E, 0x00E, 0x092, 0x12E, 0x0A8, 0x000, 0x0A7, 0x12D, 0x091, - 0x00B, 0x09B, 0x057, 0x031, -}; - -static const uint8_t huff_spec_b44_bits[] = { - 2, 4, 6, 7, 7, 8, 10, 10, 0, 10, 10, 8, 7, 7, 6, 4, - 5, 5, 7, 8, 8, 10, 10, 10, 0, 10, 10, 10, 8, 8, 7, 5, - 6, 7, 8, 9, 9, 10, 10, 10, 0, 10, 10, 10, 10, 9, 8, 7, - 8, 8, 9, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 8, - 8, 8, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 8, - 9, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 9, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 8, - 8, 8, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 9, 8, - 6, 7, 8, 9, 10, 10, 10, 10, 0, 10, 10, 10, 9, 9, 8, 7, - 5, 5, 7, 8, 8, 10, 10, 10, 0, 10, 10, 10, 8, 8, 7, 5, -}; - -static const uint16_t huff_spec_b44_codes[] = { - 0x002, 0x002, 0x030, 0x000, 0x002, 0x00C, 0x1D2, 0x1AE, 0x000, 0x1AF, 0x1D3, 0x00D, - 0x003, 0x001, 0x031, 0x003, 0x01E, 0x002, 0x070, 0x0C8, 0x07E, 0x1E8, 0x1C0, 0x176, - 0x000, 0x17F, 0x1C3, 0x1EB, 0x0CF, 0x0D3, 0x073, 0x009, 0x018, 0x06A, 0x0EC, 0x1DE, - 0x1A2, 0x1CA, 0x1AA, 0x164, 0x000, 0x16D, 0x1AD, 0x1D1, 0x1EF, 0x1DD, 0x0EB, 0x06D, - 0x0E8, 0x0CA, 0x1BE, 0x1CE, 0x1DA, 0x1B6, 0x170, 0x154, 0x000, 0x153, 0x173, 0x1B1, - 0x1D7, 0x1D5, 0x343, 0x0CD, 0x0DC, 0x078, 0x340, 0x1CC, 0x1BA, 0x1A8, 0x156, 0x148, - 0x000, 0x145, 0x15F, 0x1A1, 0x1BD, 0x1D9, 0x1ED, 0x07D, 0x1BC, 0x1DC, 0x1C4, 0x1B2, - 0x17C, 0x15A, 0x14A, 0x03A, 0x000, 0x039, 0x147, 0x16B, 0x17B, 0x1B5, 0x1C9, 0x1DF, - 0x1C6, 0x1B8, 0x1A2, 0x168, 0x160, 0x14C, 0x02E, 0x024, 0x000, 0x027, 0x03D, 0x151, - 0x15D, 0x16F, 0x1A7, 0x1BF, 0x1A4, 0x174, 0x162, 0x14E, 0x140, 0x02C, 0x02A, 0x022, - 0x000, 0x021, 0x029, 0x03F, 0x143, 0x159, 0x167, 0x179, 0x000, 0x000, 0x000, 0x000, - 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, - 0x1A5, 0x178, 0x166, 0x158, 0x142, 0x03E, 0x028, 0x020, 0x000, 0x023, 0x02B, 0x02D, - 0x141, 0x14F, 0x163, 0x175, 0x1C7, 0x1BE, 0x1A6, 0x16E, 0x15C, 0x150, 0x03C, 0x026, - 0x000, 0x025, 0x02F, 0x14D, 0x161, 0x169, 0x1A3, 0x1B9, 0x1BD, 0x1DE, 0x1C8, 0x1B4, - 0x17A, 0x16A, 0x146, 0x038, 0x000, 0x03B, 0x14B, 0x15B, 0x17D, 0x1B3, 0x1C5, 0x1DD, - 0x0DD, 0x07C, 0x1EC, 0x1D8, 0x1BC, 0x1A0, 0x15E, 0x144, 0x000, 0x149, 0x157, 0x1A9, - 0x1BB, 0x1CD, 0x341, 0x079, 0x0E9, 0x0CC, 0x342, 0x1D4, 0x1D6, 0x1B0, 0x172, 0x152, - 0x000, 0x155, 0x171, 0x1B7, 0x1DB, 0x1CF, 0x1BF, 0x0CB, 0x019, 0x06C, 0x0EA, 0x1DC, - 0x1EE, 0x1D0, 0x1AC, 0x16C, 0x000, 0x165, 0x1AB, 0x1CB, 0x1A3, 0x1DF, 0x0ED, 0x06B, - 0x01F, 0x008, 0x072, 0x0D2, 0x0CE, 0x1EA, 0x1C2, 0x17E, 0x000, 0x177, 0x1C1, 0x1E9, - 0x07F, 0x0C9, 0x071, 0x003, -}; - -static const uint8_t huff_spec_b52_bits[] = { - 3, 4, 4, 4, 5, 5, 6, 6, 5, 5, 5, 6, 6, 6, 7, 7, - 0, 7, 7, 6, 6, 6, 5, 5, 5, 6, 6, 5, 5, 4, 4, 4, -}; - -static const uint16_t huff_spec_b52_codes[] = { - 0x06, 0x0E, 0x06, 0x00, 0x0A, 0x04, 0x2C, 0x12, 0x14, 0x10, 0x06, 0x2E, 0x24, 0x10, 0x4E, 0x4C, - 0x00, 0x4D, 0x4F, 0x11, 0x25, 0x2F, 0x07, 0x11, 0x15, 0x13, 0x2D, 0x05, 0x0B, 0x01, 0x07, 0x0F, -}; - -static const uint8_t huff_spec_b53_bits[] = { - 2, 3, 4, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 8, 8, - 0, 8, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 4, 3, -}; - -static const uint16_t huff_spec_b53_codes[] = { - 0x02, 0x00, 0x06, 0x1C, 0x18, 0x3E, 0x16, 0x10, 0x3C, 0x36, 0x14, 0x6A, 0x26, 0x24, 0xD2, 0xD0, - 0x00, 0xD1, 0xD3, 0x25, 0x27, 0x6B, 0x15, 0x37, 0x3D, 0x11, 0x17, 0x3F, 0x19, 0x1D, 0x07, 0x01, -}; - -static const uint8_t huff_spec_b54_bits[] = { - 2, 3, 4, 4, 5, 6, 6, 7, 6, 6, 7, 8, 8, 8, 9, 9, - 0, 9, 9, 8, 8, 8, 7, 6, 6, 7, 6, 6, 5, 4, 4, 3, -}; - -static const uint16_t huff_spec_b54_codes[] = { - 0x003, 0x002, 0x008, 0x000, 0x014, 0x02E, 0x00E, 0x05A, 0x00A, 0x008, 0x01A, 0x0B2, - 0x032, 0x030, 0x162, 0x160, 0x000, 0x161, 0x163, 0x031, 0x033, 0x0B3, 0x01B, 0x009, - 0x00B, 0x05B, 0x00F, 0x02F, 0x015, 0x001, 0x009, 0x003, -}; - -static const uint8_t huff_spec_b62_bits[] = { - 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, - 0, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, - 6, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, -}; - -static const uint16_t huff_spec_b62_codes[] = { - 0x0D, 0x06, 0x1C, 0x14, 0x0A, 0x04, 0x3E, 0x2E, 0x22, 0x0E, 0x06, 0x00, 0x5A, 0x4E, 0x40, 0x20, - 0x30, 0x32, 0x24, 0x12, 0x0C, 0x02, 0x78, 0x58, 0x42, 0x22, 0x0A, 0x08, 0xF6, 0xF4, 0x9A, 0x98, - 0x00, 0x99, 0x9B, 0xF5, 0xF7, 0x09, 0x0B, 0x23, 0x43, 0x59, 0x79, 0x03, 0x0D, 0x13, 0x25, 0x33, - 0x31, 0x21, 0x41, 0x4F, 0x5B, 0x01, 0x07, 0x0F, 0x23, 0x2F, 0x3F, 0x05, 0x0B, 0x15, 0x1D, 0x07, -}; - -static const uint8_t huff_spec_b63_bits[] = { - 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, - 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, - 6, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, -}; - -static const uint16_t huff_spec_b63_codes[] = { - 0x006, 0x00E, 0x004, 0x014, 0x010, 0x006, 0x000, 0x026, 0x01C, 0x018, 0x004, 0x05C, - 0x04A, 0x03C, 0x016, 0x0BC, 0x006, 0x008, 0x058, 0x03E, 0x036, 0x014, 0x0B6, 0x0B4, - 0x090, 0x068, 0x17E, 0x17C, 0x126, 0x124, 0x0D6, 0x0D4, 0x000, 0x0D5, 0x0D7, 0x125, - 0x127, 0x17D, 0x17F, 0x069, 0x091, 0x0B5, 0x0B7, 0x015, 0x037, 0x03F, 0x059, 0x009, - 0x007, 0x0BD, 0x017, 0x03D, 0x04B, 0x05D, 0x005, 0x019, 0x01D, 0x027, 0x001, 0x007, - 0x011, 0x015, 0x005, 0x00F, -}; - -static const uint8_t huff_spec_b64_bits[] = { - 3, 3, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, - 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, - 0, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, 8, 7, 7, - 7, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 3, -}; - -static const uint16_t huff_spec_b64_codes[] = { - 0x007, 0x000, 0x008, 0x01A, 0x014, 0x00C, 0x032, 0x02E, 0x01E, 0x014, 0x062, 0x05A, - 0x03A, 0x026, 0x020, 0x0B2, 0x038, 0x02C, 0x022, 0x0C0, 0x05E, 0x04A, 0x186, 0x184, - 0x160, 0x0BA, 0x092, 0x090, 0x2C6, 0x2C4, 0x172, 0x170, 0x000, 0x171, 0x173, 0x2C5, - 0x2C7, 0x091, 0x093, 0x0BB, 0x161, 0x185, 0x187, 0x04B, 0x05F, 0x0C1, 0x023, 0x02D, - 0x039, 0x0B3, 0x021, 0x027, 0x03B, 0x05B, 0x063, 0x015, 0x01F, 0x02F, 0x033, 0x00D, - 0x015, 0x01B, 0x009, 0x001, -}; - -static const uint8_t huff_spec_b72_bits[] = { - 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, -}; - -static const uint16_t huff_spec_b72_codes[] = { - 0x01E, 0x016, 0x00C, 0x000, 0x038, 0x032, 0x028, 0x022, 0x01C, 0x012, 0x00E, 0x006, - 0x076, 0x06C, 0x060, 0x04E, 0x03E, 0x02A, 0x022, 0x01A, 0x012, 0x00A, 0x0FC, 0x0DC, - 0x0C6, 0x0A8, 0x094, 0x086, 0x058, 0x042, 0x040, 0x02A, 0x068, 0x07C, 0x06A, 0x056, - 0x048, 0x040, 0x02E, 0x028, 0x016, 0x010, 0x008, 0x0EA, 0x0DE, 0x0AA, 0x09A, 0x096, - 0x07A, 0x078, 0x05A, 0x032, 0x030, 0x028, 0x1FE, 0x1FC, 0x1D2, 0x1D0, 0x18A, 0x188, - 0x132, 0x130, 0x10A, 0x108, 0x000, 0x109, 0x10B, 0x131, 0x133, 0x189, 0x18B, 0x1D1, - 0x1D3, 0x1FD, 0x1FF, 0x029, 0x031, 0x033, 0x05B, 0x079, 0x07B, 0x097, 0x09B, 0x0AB, - 0x0DF, 0x0EB, 0x009, 0x011, 0x017, 0x029, 0x02F, 0x041, 0x049, 0x057, 0x06B, 0x07D, - 0x069, 0x02B, 0x041, 0x043, 0x059, 0x087, 0x095, 0x0A9, 0x0C7, 0x0DD, 0x0FD, 0x00B, - 0x013, 0x01B, 0x023, 0x02B, 0x03F, 0x04F, 0x061, 0x06D, 0x077, 0x007, 0x00F, 0x013, - 0x01D, 0x023, 0x029, 0x033, 0x039, 0x001, 0x00D, 0x017, -}; - -static const uint8_t huff_spec_b73_bits[] = { - 3, 4, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, - 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 7, - 8, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 4, -}; - -static const uint16_t huff_spec_b73_codes[] = { - 0x000, 0x006, 0x018, 0x010, 0x004, 0x03A, 0x034, 0x02A, 0x026, 0x014, 0x010, 0x07E, - 0x072, 0x06E, 0x05C, 0x052, 0x04A, 0x02C, 0x024, 0x018, 0x0F4, 0x0E0, 0x0DA, 0x0B6, - 0x0B2, 0x0A0, 0x05E, 0x04E, 0x038, 0x034, 0x1E6, 0x1B2, 0x0FA, 0x01E, 0x0F8, 0x0F0, - 0x0BE, 0x0B4, 0x0A2, 0x090, 0x04C, 0x03A, 0x1EE, 0x1E4, 0x1C6, 0x1B0, 0x178, 0x162, - 0x126, 0x124, 0x0B8, 0x06C, 0x3DA, 0x3D8, 0x38A, 0x388, 0x2F6, 0x2F4, 0x2C2, 0x2C0, - 0x176, 0x174, 0x0DC, 0x0DE, 0x000, 0x0DF, 0x0DD, 0x175, 0x177, 0x2C1, 0x2C3, 0x2F5, - 0x2F7, 0x389, 0x38B, 0x3D9, 0x3DB, 0x06D, 0x0B9, 0x125, 0x127, 0x163, 0x179, 0x1B1, - 0x1C7, 0x1E5, 0x1EF, 0x03B, 0x04D, 0x091, 0x0A3, 0x0B5, 0x0BF, 0x0F1, 0x0F9, 0x01F, - 0x0FB, 0x1B3, 0x1E7, 0x035, 0x039, 0x04F, 0x05F, 0x0A1, 0x0B3, 0x0B7, 0x0DB, 0x0E1, - 0x0F5, 0x019, 0x025, 0x02D, 0x04B, 0x053, 0x05D, 0x06F, 0x073, 0x07F, 0x011, 0x015, - 0x027, 0x02B, 0x035, 0x03B, 0x005, 0x011, 0x019, 0x007, -}; - -static const uint8_t huff_spec_b74_bits[] = { - 3, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, - 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, - 8, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, - 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, -}; - -static const uint16_t huff_spec_b74_codes[] = { - 0x001, 0x008, 0x01E, 0x018, 0x00C, 0x002, 0x03A, 0x034, 0x02C, 0x01E, 0x016, 0x012, - 0x072, 0x06E, 0x05E, 0x056, 0x050, 0x038, 0x022, 0x004, 0x0E2, 0x0DA, 0x0BA, 0x0A8, - 0x076, 0x054, 0x050, 0x002, 0x000, 0x1C0, 0x1B0, 0x156, 0x0A4, 0x0A6, 0x074, 0x052, - 0x004, 0x1C2, 0x1B2, 0x170, 0x154, 0x0AE, 0x0AC, 0x086, 0x2E6, 0x2E4, 0x10A, 0x108, - 0x106, 0x104, 0x102, 0x100, 0x03E, 0x03A, 0x03C, 0x038, 0x036, 0x034, 0x032, 0x030, - 0x01E, 0x01A, 0x01C, 0x018, 0x000, 0x019, 0x01D, 0x01B, 0x01F, 0x031, 0x033, 0x035, - 0x037, 0x039, 0x03D, 0x03B, 0x03F, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x2E5, - 0x2E7, 0x087, 0x0AD, 0x0AF, 0x155, 0x171, 0x1B3, 0x1C3, 0x005, 0x053, 0x075, 0x0A7, - 0x0A5, 0x157, 0x1B1, 0x1C1, 0x001, 0x003, 0x051, 0x055, 0x077, 0x0A9, 0x0BB, 0x0DB, - 0x0E3, 0x005, 0x023, 0x039, 0x051, 0x057, 0x05F, 0x06F, 0x073, 0x013, 0x017, 0x01F, - 0x02D, 0x035, 0x03B, 0x003, 0x00D, 0x019, 0x01F, 0x009, + { 3, 1, 0, 2 }, + { 7, 1, 0, 3 }, + { 15, 1, 0, 4 }, + { 32, 1, 0, 5 }, +}; + +static const uint8_t at9_coeffs_tab[][2] = { + /* Coefficient table A.2.1 - 8 entries */ + { 1, 3 }, { 3, 3 }, { 12, 3 }, { 4, 3 }, { 7, 3 }, + { 13, 3 }, { 15, 3 }, { 5, 3 }, + /* Coefficient table A.2.2 - 80 entries */ + { 17, 6 }, { 51, 6 }, { 81, 7 }, { 243, 7 }, { 69, 7 }, + { 207, 7 }, { 205, 7 }, { 71, 7 }, { 209, 7 }, { 115, 7 }, + { 245, 7 }, { 95, 7 }, { 125, 7 }, { 215, 7 }, { 1, 4 }, + { 3, 4 }, { 116, 7 }, { 220, 7 }, { 84, 7 }, { 252, 7 }, + { 29, 7 }, { 55, 7 }, { 21, 7 }, { 63, 7 }, { 65, 6 }, + { 195, 6 }, { 193, 6 }, { 67, 6 }, { 20, 6 }, { 60, 6 }, + { 52, 6 }, { 28, 6 }, { 16, 5 }, { 48, 5 }, { 4, 5 }, + { 12, 5 }, { 221, 8 }, { 119, 8 }, { 117, 8 }, { 223, 8 }, + { 213, 8 }, { 127, 8 }, { 253, 8 }, { 87, 8 }, { 80, 6 }, + { 240, 6 }, { 93, 8 }, { 247, 8 }, { 85, 8 }, { 255, 8 }, + { 113, 7 }, { 211, 7 }, { 208, 6 }, { 112, 6 }, { 64, 5 }, + { 192, 5 }, { 212, 7 }, { 124, 7 }, { 241, 7 }, { 83, 7 }, + { 77, 7 }, { 199, 7 }, { 244, 7 }, { 92, 7 }, { 196, 6 }, + { 76, 6 }, { 53, 7 }, { 31, 7 }, { 197, 7 }, { 79, 7 }, + { 49, 6 }, { 19, 6 }, { 61, 7 }, { 23, 7 }, { 68, 7 }, + { 204, 7 }, { 5, 6 }, { 15, 6 }, { 13, 6 }, { 7, 6 }, + /* Coefficient table A.2.3 - 81 entries */ + { 65, 6 }, { 195, 6 }, { 193, 6 }, { 67, 6 }, { 197, 7 }, + { 79, 7 }, { 77, 7 }, { 199, 7 }, { 241, 7 }, { 83, 7 }, + { 244, 7 }, { 92, 7 }, { 1, 4 }, { 3, 4 }, { 20, 6 }, + { 60, 6 }, { 212, 7 }, { 124, 7 }, { 61, 7 }, { 23, 7 }, + { 52, 6 }, { 28, 6 }, { 53, 7 }, { 31, 7 }, { 245, 8 }, + { 95, 8 }, { 125, 8 }, { 215, 8 }, { 80, 6 }, { 240, 6 }, + { 208, 6 }, { 112, 6 }, { 205, 8 }, { 71, 8 }, { 81, 8 }, + { 243, 8 }, { 69, 8 }, { 207, 8 }, { 209, 8 }, { 115, 8 }, + { 5, 6 }, { 15, 6 }, { 13, 6 }, { 7, 6 }, { 196, 6 }, + { 76, 6 }, { 221, 9 }, { 119, 9 }, { 253, 9 }, { 87, 9 }, + { 116, 8 }, { 220, 8 }, { 68, 7 }, { 204, 7 }, { 49, 6 }, + { 19, 6 }, { 117, 9 }, { 223, 9 }, { 213, 9 }, { 127, 9 }, + { 84, 8 }, { 252, 8 }, { 29, 8 }, { 55, 8 }, { 21, 8 }, + { 63, 8 }, { 17, 7 }, { 51, 7 }, { 93, 9 }, { 247, 9 }, + { 85, 9 }, { 255, 9 }, { 113, 8 }, { 211, 8 }, { 4, 5 }, + { 12, 5 }, { 0, 3 }, { 16, 5 }, { 48, 5 }, { 64, 5 }, + { 192, 5 }, + /* Coefficient table A.2.4 - 81 entries */ + { 20, 6 }, { 60, 6 }, { 52, 6 }, { 28, 6 }, { 80, 6 }, + { 240, 6 }, { 208, 6 }, { 112, 6 }, { 1, 4 }, { 3, 4 }, + { 5, 6 }, { 15, 6 }, { 13, 6 }, { 7, 6 }, { 84, 8 }, + { 252, 8 }, { 29, 8 }, { 55, 8 }, { 68, 7 }, { 204, 7 }, + { 196, 6 }, { 76, 6 }, { 17, 7 }, { 51, 7 }, { 21, 8 }, + { 63, 8 }, { 113, 8 }, { 211, 8 }, { 49, 6 }, { 19, 6 }, + { 245, 9 }, { 95, 9 }, { 125, 9 }, { 215, 9 }, { 244, 8 }, + { 92, 8 }, { 212, 8 }, { 124, 8 }, { 241, 8 }, { 83, 8 }, + { 77, 8 }, { 199, 8 }, { 197, 8 }, { 79, 8 }, { 53, 8 }, + { 31, 8 }, { 253, 10 }, { 87, 10 }, { 213, 10 }, { 127, 10 }, + { 81, 9 }, { 243, 9 }, { 0, 2 }, { 61, 8 }, { 23, 8 }, + { 117, 10 }, { 223, 10 }, { 221, 10 }, { 119, 10 }, { 209, 9 }, + { 115, 9 }, { 65, 7 }, { 195, 7 }, { 193, 7 }, { 67, 7 }, + { 69, 9 }, { 207, 9 }, { 205, 9 }, { 71, 9 }, { 93, 10 }, + { 247, 10 }, { 85, 10 }, { 255, 10 }, { 116, 9 }, { 220, 9 }, + { 16, 5 }, { 48, 5 }, { 64, 5 }, { 192, 5 }, { 4, 5 }, + { 12, 5 }, + /* Coefficient table A.3.1 - 40 entries */ + { 50, 5 }, { 22, 5 }, { 11, 5 }, { 61, 5 }, { 2, 4 }, + { 6, 4 }, { 59, 5 }, { 13, 5 }, { 17, 5 }, { 55, 5 }, + { 49, 5 }, { 23, 5 }, { 24, 5 }, { 40, 5 }, { 26, 6 }, + { 46, 6 }, { 42, 6 }, { 30, 6 }, { 10, 5 }, { 62, 5 }, + { 58, 5 }, { 14, 5 }, { 19, 6 }, { 53, 6 }, { 51, 6 }, + { 21, 6 }, { 3, 5 }, { 5, 5 }, { 16, 5 }, { 48, 5 }, + { 25, 6 }, { 47, 6 }, { 41, 6 }, { 31, 6 }, { 27, 7 }, + { 45, 7 }, { 43, 7 }, { 29, 7 }, { 18, 6 }, { 54, 6 }, + /* Coefficient table A.3.2 - 49 entries */ + { 57, 5 }, { 15, 5 }, { 17, 5 }, { 55, 5 }, { 49, 5 }, + { 23, 5 }, { 58, 5 }, { 14, 5 }, { 10, 5 }, { 62, 5 }, + { 43, 7 }, { 29, 7 }, { 27, 7 }, { 45, 7 }, { 25, 6 }, + { 47, 6 }, { 41, 6 }, { 31, 6 }, { 59, 6 }, { 13, 6 }, + { 11, 6 }, { 61, 6 }, { 50, 6 }, { 22, 6 }, { 16, 5 }, + { 48, 5 }, { 8, 5 }, { 56, 5 }, { 18, 6 }, { 54, 6 }, + { 24, 6 }, { 40, 6 }, { 2, 5 }, { 6, 5 }, { 1, 5 }, + { 7, 5 }, { 0, 4 }, { 42, 7 }, { 30, 7 }, { 26, 7 }, + { 46, 7 }, { 3, 6 }, { 5, 6 }, { 19, 7 }, { 53, 7 }, + { 51, 7 }, { 21, 7 }, { 9, 6 }, { 63, 6 }, + /* Coefficient table A.3.3 - 49 entries */ + { 51, 7 }, { 21, 7 }, { 19, 7 }, { 53, 7 }, { 24, 6 }, + { 40, 6 }, { 50, 6 }, { 22, 6 }, { 18, 6 }, { 54, 6 }, + { 3, 6 }, { 5, 6 }, { 43, 8 }, { 29, 8 }, { 27, 8 }, + { 45, 8 }, { 25, 7 }, { 47, 7 }, { 16, 5 }, { 48, 5 }, + { 8, 4 }, { 56, 4 }, { 1, 4 }, { 7, 4 }, { 2, 5 }, + { 6, 5 }, { 9, 5 }, { 63, 5 }, { 0, 3 }, { 57, 5 }, + { 15, 5 }, { 41, 7 }, { 31, 7 }, { 11, 7 }, { 61, 7 }, + { 59, 7 }, { 13, 7 }, { 26, 8 }, { 46, 8 }, { 42, 8 }, + { 30, 8 }, { 49, 6 }, { 23, 6 }, { 17, 6 }, { 55, 6 }, + { 58, 6 }, { 14, 6 }, { 10, 6 }, { 62, 6 }, + /* Coefficient table A.3.4 - 49 entries */ + { 0, 2 }, { 16, 5 }, { 48, 5 }, { 2, 5 }, { 6, 5 }, + { 26, 8 }, { 46, 8 }, { 51, 8 }, { 21, 8 }, { 24, 7 }, + { 40, 7 }, { 3, 7 }, { 5, 7 }, { 19, 8 }, { 53, 8 }, + { 25, 8 }, { 47, 8 }, { 50, 7 }, { 22, 7 }, { 18, 7 }, + { 54, 7 }, { 17, 6 }, { 55, 6 }, { 8, 4 }, { 56, 4 }, + { 1, 4 }, { 7, 4 }, { 49, 6 }, { 23, 6 }, { 10, 6 }, + { 62, 6 }, { 58, 6 }, { 14, 6 }, { 41, 8 }, { 31, 8 }, + { 11, 8 }, { 61, 8 }, { 59, 8 }, { 13, 8 }, { 43, 10 }, + { 29, 10 }, { 27, 10 }, { 45, 10 }, { 42, 9 }, { 30, 9 }, + { 9, 5 }, { 63, 5 }, { 57, 5 }, { 15, 5 }, + /* Coefficient table A.4.1 - 176 entries */ + { 83, 7 }, { 189, 7 }, { 68, 7 }, { 204, 7 }, { 23, 7 }, + { 249, 7 }, { 166, 8 }, { 106, 8 }, { 183, 8 }, { 89, 8 }, + { 52, 7 }, { 220, 7 }, { 161, 7 }, { 111, 7 }, { 179, 7 }, + { 93, 7 }, { 196, 7 }, { 76, 7 }, { 38, 7 }, { 234, 7 }, + { 116, 8 }, { 156, 8 }, { 148, 8 }, { 124, 8 }, { 97, 7 }, + { 175, 7 }, { 247, 7 }, { 25, 7 }, { 53, 7 }, { 219, 7 }, + { 212, 7 }, { 60, 7 }, { 5, 6 }, { 11, 6 }, { 101, 8 }, + { 171, 8 }, { 165, 8 }, { 107, 8 }, { 230, 7 }, { 42, 7 }, + { 244, 6 }, { 28, 6 }, { 7, 7 }, { 9, 7 }, { 213, 7 }, + { 59, 7 }, { 86, 8 }, { 186, 8 }, { 115, 8 }, { 157, 8 }, + { 71, 8 }, { 201, 8 }, { 182, 8 }, { 90, 8 }, { 4, 6 }, + { 12, 6 }, { 147, 8 }, { 125, 8 }, { 199, 8 }, { 73, 8 }, + { 82, 7 }, { 190, 7 }, { 66, 7 }, { 206, 7 }, { 178, 7 }, + { 94, 7 }, { 194, 7 }, { 78, 7 }, { 22, 7 }, { 250, 7 }, + { 96, 7 }, { 160, 7 }, { 100, 8 }, { 172, 8 }, { 164, 8 }, + { 108, 8 }, { 246, 7 }, { 26, 7 }, { 85, 8 }, { 187, 8 }, + { 114, 8 }, { 158, 8 }, { 37, 7 }, { 235, 7 }, { 36, 7 }, + { 236, 7 }, { 146, 8 }, { 126, 8 }, { 70, 8 }, { 202, 8 }, + { 215, 8 }, { 57, 8 }, { 55, 8 }, { 217, 8 }, { 181, 8 }, + { 91, 8 }, { 198, 8 }, { 74, 8 }, { 228, 7 }, { 44, 7 }, + { 229, 7 }, { 43, 7 }, { 81, 7 }, { 191, 7 }, { 177, 7 }, + { 95, 7 }, { 119, 9 }, { 153, 9 }, { 151, 9 }, { 121, 9 }, + { 99, 8 }, { 173, 8 }, { 65, 7 }, { 207, 7 }, { 6, 7 }, + { 10, 7 }, { 193, 7 }, { 79, 7 }, { 113, 8 }, { 159, 8 }, + { 163, 8 }, { 109, 8 }, { 145, 8 }, { 127, 8 }, { 118, 9 }, + { 154, 9 }, { 103, 9 }, { 169, 9 }, { 84, 8 }, { 188, 8 }, + { 39, 8 }, { 233, 8 }, { 167, 9 }, { 105, 9 }, { 150, 9 }, + { 122, 9 }, { 69, 8 }, { 203, 8 }, { 180, 8 }, { 92, 8 }, + { 54, 8 }, { 218, 8 }, { 197, 8 }, { 75, 8 }, { 98, 8 }, + { 174, 8 }, { 21, 7 }, { 251, 7 }, { 231, 8 }, { 41, 8 }, + { 162, 8 }, { 110, 8 }, { 214, 8 }, { 58, 8 }, { 117, 9 }, + { 155, 9 }, { 149, 9 }, { 123, 9 }, { 80, 7 }, { 176, 7 }, + { 20, 7 }, { 252, 7 }, { 102, 9 }, { 170, 9 }, { 87, 9 }, + { 185, 9 }, { 112, 8 }, { 144, 8 }, { 245, 7 }, { 27, 7 }, + { 64, 7 }, { 192, 7 }, { 67, 8 }, { 205, 8 }, { 195, 8 }, + { 77, 8 }, + /* Coefficient table A.4.2 - 225 entries */ + { 3, 7 }, { 13, 7 }, { 113, 8 }, { 159, 8 }, { 163, 8 }, + { 109, 8 }, { 16, 6 }, { 240, 6 }, { 81, 7 }, { 191, 7 }, + { 177, 7 }, { 95, 7 }, { 0, 5 }, { 112, 8 }, { 144, 8 }, + { 99, 8 }, { 173, 8 }, { 149, 9 }, { 123, 9 }, { 166, 9 }, + { 106, 9 }, { 54, 8 }, { 218, 8 }, { 66, 7 }, { 206, 7 }, + { 23, 8 }, { 249, 8 }, { 214, 8 }, { 58, 8 }, { 194, 7 }, + { 78, 7 }, { 117, 9 }, { 155, 9 }, { 87, 9 }, { 185, 9 }, + { 247, 8 }, { 25, 8 }, { 21, 7 }, { 251, 7 }, { 211, 8 }, + { 61, 8 }, { 51, 8 }, { 221, 8 }, { 36, 7 }, { 236, 7 }, + { 228, 7 }, { 44, 7 }, { 183, 9 }, { 89, 9 }, { 102, 9 }, + { 170, 9 }, { 180, 8 }, { 92, 8 }, { 80, 7 }, { 176, 7 }, + { 245, 7 }, { 27, 7 }, { 69, 8 }, { 203, 8 }, { 84, 8 }, + { 188, 8 }, { 225, 7 }, { 47, 7 }, { 33, 7 }, { 239, 7 }, + { 1, 6 }, { 15, 6 }, { 197, 8 }, { 75, 8 }, { 98, 8 }, + { 174, 8 }, { 18, 7 }, { 254, 7 }, { 162, 8 }, { 110, 8 }, + { 116, 9 }, { 156, 9 }, { 148, 9 }, { 124, 9 }, { 242, 7 }, + { 30, 7 }, { 5, 7 }, { 11, 7 }, { 7, 8 }, { 9, 8 }, + { 230, 8 }, { 42, 8 }, { 65, 7 }, { 207, 7 }, { 71, 9 }, + { 201, 9 }, { 199, 9 }, { 73, 9 }, { 38, 8 }, { 234, 8 }, + { 32, 7 }, { 224, 7 }, { 193, 7 }, { 79, 7 }, { 165, 9 }, + { 107, 9 }, { 182, 9 }, { 90, 9 }, { 35, 8 }, { 237, 8 }, + { 244, 7 }, { 28, 7 }, { 20, 7 }, { 252, 7 }, { 50, 8 }, + { 222, 8 }, { 97, 8 }, { 175, 8 }, { 101, 9 }, { 171, 9 }, + { 86, 9 }, { 186, 9 }, { 83, 8 }, { 189, 8 }, { 161, 8 }, + { 111, 8 }, { 179, 8 }, { 93, 8 }, { 64, 7 }, { 192, 7 }, + { 227, 8 }, { 45, 8 }, { 210, 8 }, { 62, 8 }, { 2, 7 }, + { 14, 7 }, { 213, 8 }, { 59, 8 }, { 53, 8 }, { 219, 8 }, + { 196, 8 }, { 76, 8 }, { 115, 9 }, { 157, 9 }, { 151, 10 }, + { 121, 10 }, { 119, 10 }, { 153, 10 }, { 68, 8 }, { 204, 8 }, + { 22, 8 }, { 250, 8 }, { 96, 8 }, { 160, 8 }, { 147, 9 }, + { 125, 9 }, { 55, 9 }, { 217, 9 }, { 246, 8 }, { 26, 8 }, + { 215, 9 }, { 57, 9 }, { 164, 9 }, { 108, 9 }, { 17, 7 }, + { 255, 7 }, { 4, 7 }, { 12, 7 }, { 241, 7 }, { 31, 7 }, + { 114, 9 }, { 158, 9 }, { 100, 9 }, { 172, 9 }, { 6, 8 }, + { 10, 8 }, { 209, 8 }, { 63, 8 }, { 19, 8 }, { 253, 8 }, + { 49, 8 }, { 223, 8 }, { 195, 8 }, { 77, 8 }, { 212, 8 }, + { 60, 8 }, { 198, 9 }, { 74, 9 }, { 70, 9 }, { 202, 9 }, + { 82, 8 }, { 190, 8 }, { 243, 8 }, { 29, 8 }, { 146, 9 }, + { 126, 9 }, { 118, 10 }, { 154, 10 }, { 167, 10 }, { 105, 10 }, + { 178, 8 }, { 94, 8 }, { 67, 8 }, { 205, 8 }, { 85, 9 }, + { 187, 9 }, { 181, 9 }, { 91, 9 }, { 52, 8 }, { 220, 8 }, + { 150, 10 }, { 122, 10 }, { 103, 10 }, { 169, 10 }, { 231, 9 }, + { 41, 9 }, { 229, 8 }, { 43, 8 }, { 48, 8 }, { 208, 8 }, + { 37, 8 }, { 235, 8 }, { 34, 8 }, { 238, 8 }, { 226, 8 }, + { 46, 8 }, { 39, 9 }, { 233, 9 }, { 145, 9 }, { 127, 9 }, + /* Coefficient table A.4.3 - 225 entries */ + { 246, 8 }, { 26, 8 }, { 22, 8 }, { 250, 8 }, { 210, 7 }, + { 62, 7 }, { 50, 7 }, { 222, 7 }, { 53, 8 }, { 219, 8 }, + { 231, 9 }, { 41, 9 }, { 39, 9 }, { 233, 9 }, { 16, 5 }, + { 240, 5 }, { 0, 4 }, { 227, 7 }, { 45, 7 }, { 35, 7 }, + { 237, 7 }, { 196, 8 }, { 76, 8 }, { 151, 10 }, { 121, 10 }, + { 119, 10 }, { 153, 10 }, { 150, 10 }, { 122, 10 }, { 167, 10 }, + { 105, 10 }, { 118, 10 }, { 154, 10 }, { 103, 10 }, { 169, 10 }, + { 117, 10 }, { 155, 10 }, { 149, 10 }, { 123, 10 }, { 96, 8 }, + { 160, 8 }, { 166, 10 }, { 106, 10 }, { 183, 10 }, { 89, 10 }, + { 87, 10 }, { 185, 10 }, { 102, 10 }, { 170, 10 }, { 71, 10 }, + { 201, 10 }, { 116, 10 }, { 156, 10 }, { 148, 10 }, { 124, 10 }, + { 199, 10 }, { 73, 10 }, { 182, 10 }, { 90, 10 }, { 165, 10 }, + { 107, 10 }, { 181, 9 }, { 91, 9 }, { 68, 8 }, { 204, 8 }, + { 85, 9 }, { 187, 9 }, { 113, 9 }, { 159, 9 }, { 6, 8 }, + { 10, 8 }, { 65, 7 }, { 207, 7 }, { 32, 6 }, { 224, 6 }, + { 2, 6 }, { 14, 6 }, { 193, 7 }, { 79, 7 }, { 145, 9 }, + { 127, 9 }, { 163, 9 }, { 109, 9 }, { 99, 9 }, { 173, 9 }, + { 247, 9 }, { 25, 9 }, { 20, 7 }, { 252, 7 }, { 244, 7 }, + { 28, 7 }, { 178, 8 }, { 94, 8 }, { 82, 8 }, { 190, 8 }, + { 23, 9 }, { 249, 9 }, { 54, 9 }, { 218, 9 }, { 214, 9 }, + { 58, 9 }, { 112, 9 }, { 144, 9 }, { 49, 7 }, { 223, 7 }, + { 209, 7 }, { 63, 7 }, { 37, 8 }, { 235, 8 }, { 229, 8 }, + { 43, 8 }, { 19, 7 }, { 253, 7 }, { 243, 7 }, { 29, 7 }, + { 64, 7 }, { 192, 7 }, { 195, 8 }, { 77, 8 }, { 67, 8 }, + { 205, 8 }, { 212, 8 }, { 60, 8 }, { 52, 8 }, { 220, 8 }, + { 7, 9 }, { 9, 9 }, { 180, 9 }, { 92, 9 }, { 197, 9 }, + { 75, 9 }, { 84, 9 }, { 188, 9 }, { 4, 7 }, { 12, 7 }, + { 48, 7 }, { 208, 7 }, { 34, 7 }, { 238, 7 }, { 226, 7 }, + { 46, 7 }, { 101, 10 }, { 171, 10 }, { 86, 10 }, { 186, 10 }, + { 69, 9 }, { 203, 9 }, { 211, 8 }, { 61, 8 }, { 17, 6 }, + { 255, 6 }, { 241, 6 }, { 31, 6 }, { 3, 7 }, { 13, 7 }, + { 51, 8 }, { 221, 8 }, { 98, 9 }, { 174, 9 }, { 162, 9 }, + { 110, 9 }, { 177, 8 }, { 95, 8 }, { 81, 8 }, { 191, 8 }, + { 38, 9 }, { 234, 9 }, { 230, 9 }, { 42, 9 }, { 21, 8 }, + { 251, 8 }, { 245, 8 }, { 27, 8 }, { 115, 10 }, { 157, 10 }, + { 55, 10 }, { 217, 10 }, { 147, 10 }, { 125, 10 }, { 215, 10 }, + { 57, 10 }, { 80, 8 }, { 176, 8 }, { 66, 8 }, { 206, 8 }, + { 194, 8 }, { 78, 8 }, { 97, 9 }, { 175, 9 }, { 161, 9 }, + { 111, 9 }, { 5, 8 }, { 11, 8 }, { 228, 8 }, { 44, 8 }, + { 36, 8 }, { 236, 8 }, { 114, 10 }, { 158, 10 }, { 100, 10 }, + { 172, 10 }, { 83, 9 }, { 189, 9 }, { 33, 7 }, { 239, 7 }, + { 164, 10 }, { 108, 10 }, { 198, 10 }, { 74, 10 }, { 179, 9 }, + { 93, 9 }, { 70, 10 }, { 202, 10 }, { 146, 10 }, { 126, 10 }, + { 213, 9 }, { 59, 9 }, { 18, 7 }, { 254, 7 }, { 225, 7 }, + { 47, 7 }, { 242, 7 }, { 30, 7 }, { 1, 6 }, { 15, 6 }, + /* Coefficient table A.4.4 - 225 entries */ + { 193, 7 }, { 79, 7 }, { 20, 7 }, { 252, 7 }, { 151, 10 }, + { 121, 10 }, { 119, 10 }, { 153, 10 }, { 118, 10 }, { 154, 10 }, + { 150, 10 }, { 122, 10 }, { 167, 10 }, { 105, 10 }, { 103, 10 }, + { 169, 10 }, { 117, 10 }, { 155, 10 }, { 149, 10 }, { 123, 10 }, + { 244, 7 }, { 28, 7 }, { 87, 10 }, { 185, 10 }, { 183, 10 }, + { 89, 10 }, { 166, 10 }, { 106, 10 }, { 102, 10 }, { 170, 10 }, + { 71, 10 }, { 201, 10 }, { 148, 10 }, { 124, 10 }, { 199, 10 }, + { 73, 10 }, { 116, 10 }, { 156, 10 }, { 165, 10 }, { 107, 10 }, + { 182, 10 }, { 90, 10 }, { 86, 10 }, { 186, 10 }, { 115, 10 }, + { 157, 10 }, { 101, 10 }, { 171, 10 }, { 147, 10 }, { 125, 10 }, + { 55, 10 }, { 217, 10 }, { 215, 10 }, { 57, 10 }, { 114, 10 }, + { 158, 10 }, { 146, 10 }, { 126, 10 }, { 164, 10 }, { 108, 10 }, + { 39, 10 }, { 233, 10 }, { 100, 10 }, { 172, 10 }, { 231, 10 }, + { 41, 10 }, { 198, 10 }, { 74, 10 }, { 70, 10 }, { 202, 10 }, + { 145, 10 }, { 127, 10 }, { 181, 10 }, { 91, 10 }, { 85, 10 }, + { 187, 10 }, { 113, 10 }, { 159, 10 }, { 247, 10 }, { 25, 10 }, + { 112, 10 }, { 144, 10 }, { 23, 10 }, { 249, 10 }, { 7, 10 }, + { 9, 10 }, { 99, 10 }, { 173, 10 }, { 54, 10 }, { 218, 10 }, + { 163, 10 }, { 109, 10 }, { 214, 10 }, { 58, 10 }, { 197, 10 }, + { 75, 10 }, { 84, 10 }, { 188, 10 }, { 98, 10 }, { 174, 10 }, + { 69, 10 }, { 203, 10 }, { 67, 8 }, { 205, 8 }, { 180, 10 }, + { 92, 10 }, { 162, 10 }, { 110, 10 }, { 97, 9 }, { 175, 9 }, + { 81, 8 }, { 191, 8 }, { 177, 8 }, { 95, 8 }, { 210, 7 }, + { 62, 7 }, { 212, 8 }, { 60, 8 }, { 195, 8 }, { 77, 8 }, + { 35, 7 }, { 237, 7 }, { 64, 7 }, { 192, 7 }, { 50, 7 }, + { 222, 7 }, { 227, 7 }, { 45, 7 }, { 52, 8 }, { 220, 8 }, + { 21, 8 }, { 251, 8 }, { 4, 7 }, { 12, 7 }, { 245, 8 }, + { 27, 8 }, { 161, 9 }, { 111, 9 }, { 22, 9 }, { 250, 9 }, + { 225, 6 }, { 47, 6 }, { 33, 6 }, { 239, 6 }, { 18, 6 }, + { 254, 6 }, { 242, 6 }, { 30, 6 }, { 80, 8 }, { 176, 8 }, + { 246, 9 }, { 26, 9 }, { 96, 9 }, { 160, 9 }, { 5, 8 }, + { 11, 8 }, { 6, 9 }, { 10, 9 }, { 179, 9 }, { 93, 9 }, + { 83, 9 }, { 189, 9 }, { 53, 9 }, { 219, 9 }, { 213, 9 }, + { 59, 9 }, { 196, 9 }, { 76, 9 }, { 49, 7 }, { 223, 7 }, + { 16, 5 }, { 240, 5 }, { 1, 5 }, { 15, 5 }, { 0, 4 }, + { 209, 7 }, { 63, 7 }, { 19, 7 }, { 253, 7 }, { 32, 6 }, + { 224, 6 }, { 2, 6 }, { 14, 6 }, { 243, 7 }, { 29, 7 }, + { 51, 8 }, { 221, 8 }, { 211, 8 }, { 61, 8 }, { 66, 8 }, + { 206, 8 }, { 194, 8 }, { 78, 8 }, { 228, 8 }, { 44, 8 }, + { 36, 8 }, { 236, 8 }, { 48, 7 }, { 208, 7 }, { 3, 7 }, + { 13, 7 }, { 68, 9 }, { 204, 9 }, { 82, 9 }, { 190, 9 }, + { 178, 9 }, { 94, 9 }, { 37, 9 }, { 235, 9 }, { 34, 7 }, + { 238, 7 }, { 226, 7 }, { 46, 7 }, { 229, 9 }, { 43, 9 }, + { 38, 10 }, { 234, 10 }, { 230, 10 }, { 42, 10 }, { 65, 8 }, + { 207, 8 }, { 17, 6 }, { 255, 6 }, { 241, 6 }, { 31, 6 }, + /* Coefficient table A.5.1 - 31 entries */ + { 8, 4 }, { 24, 4 }, { 15, 5 }, { 17, 5 }, { 4, 5 }, + { 28, 5 }, { 9, 4 }, { 23, 4 }, { 14, 5 }, { 18, 5 }, + { 3, 5 }, { 29, 5 }, { 13, 5 }, { 19, 5 }, { 2, 5 }, + { 30, 5 }, { 12, 5 }, { 20, 5 }, { 1, 5 }, { 31, 5 }, + { 7, 6 }, { 25, 6 }, { 0, 5 }, { 11, 5 }, { 21, 5 }, + { 6, 6 }, { 26, 6 }, { 5, 6 }, { 27, 6 }, { 10, 5 }, + { 22, 5 }, + /* Coefficient table A.5.2 - 31 entries */ + { 2, 4 }, { 30, 4 }, { 11, 5 }, { 21, 5 }, { 7, 5 }, + { 25, 5 }, { 1, 4 }, { 31, 4 }, { 6, 5 }, { 26, 5 }, + { 10, 5 }, { 22, 5 }, { 15, 6 }, { 17, 6 }, { 14, 6 }, + { 18, 6 }, { 0, 4 }, { 5, 5 }, { 27, 5 }, { 9, 5 }, + { 23, 5 }, { 8, 5 }, { 24, 5 }, { 4, 5 }, { 28, 5 }, + { 13, 6 }, { 19, 6 }, { 12, 6 }, { 20, 6 }, { 3, 5 }, + { 29, 5 }, + /* Coefficient table A.5.3 - 31 entries */ + { 0, 3 }, { 9, 5 }, { 23, 5 }, { 7, 5 }, { 25, 5 }, + { 3, 4 }, { 29, 4 }, { 8, 5 }, { 24, 5 }, { 15, 7 }, + { 17, 7 }, { 14, 7 }, { 18, 7 }, { 11, 6 }, { 21, 6 }, + { 2, 4 }, { 30, 4 }, { 6, 5 }, { 26, 5 }, { 5, 5 }, + { 27, 5 }, { 1, 4 }, { 31, 4 }, { 10, 6 }, { 22, 6 }, + { 13, 7 }, { 19, 7 }, { 12, 7 }, { 20, 7 }, { 4, 5 }, + { 28, 5 }, + /* Coefficient table A.5.4 - 31 entries */ + { 8, 5 }, { 24, 5 }, { 7, 5 }, { 25, 5 }, { 4, 4 }, + { 28, 4 }, { 0, 3 }, { 10, 6 }, { 22, 6 }, { 13, 7 }, + { 19, 7 }, { 12, 7 }, { 20, 7 }, { 6, 5 }, { 26, 5 }, + { 3, 4 }, { 29, 4 }, { 2, 4 }, { 30, 4 }, { 9, 6 }, + { 23, 6 }, { 15, 8 }, { 17, 8 }, { 14, 8 }, { 18, 8 }, + { 11, 7 }, { 21, 7 }, { 5, 5 }, { 27, 5 }, { 1, 4 }, + { 31, 4 }, + /* Coefficient table A.6.1 - 63 entries */ + { 19, 5 }, { 45, 5 }, { 31, 6 }, { 33, 6 }, { 30, 6 }, + { 34, 6 }, { 16, 5 }, { 48, 5 }, { 8, 6 }, { 56, 6 }, + { 7, 6 }, { 57, 6 }, { 18, 5 }, { 46, 5 }, { 29, 6 }, + { 35, 6 }, { 28, 6 }, { 36, 6 }, { 6, 6 }, { 58, 6 }, + { 27, 6 }, { 37, 6 }, { 17, 5 }, { 47, 5 }, { 5, 6 }, + { 59, 6 }, { 26, 6 }, { 38, 6 }, { 4, 6 }, { 60, 6 }, + { 25, 6 }, { 39, 6 }, { 3, 6 }, { 61, 6 }, { 2, 6 }, + { 62, 6 }, { 24, 6 }, { 40, 6 }, { 15, 7 }, { 49, 7 }, + { 14, 7 }, { 50, 7 }, { 1, 6 }, { 63, 6 }, { 23, 6 }, + { 41, 6 }, { 13, 7 }, { 51, 7 }, { 0, 6 }, { 22, 6 }, + { 42, 6 }, { 12, 7 }, { 52, 7 }, { 11, 7 }, { 53, 7 }, + { 21, 6 }, { 43, 6 }, { 20, 6 }, { 44, 6 }, { 10, 7 }, + { 54, 7 }, { 9, 7 }, { 55, 7 }, + /* Coefficient table A.6.2 - 63 entries */ + { 23, 6 }, { 41, 6 }, { 15, 6 }, { 49, 6 }, { 4, 5 }, + { 60, 5 }, { 3, 5 }, { 61, 5 }, { 22, 6 }, { 42, 6 }, + { 14, 6 }, { 50, 6 }, { 2, 5 }, { 62, 5 }, { 31, 7 }, + { 33, 7 }, { 30, 7 }, { 34, 7 }, { 21, 6 }, { 43, 6 }, + { 13, 6 }, { 51, 6 }, { 12, 6 }, { 52, 6 }, { 1, 5 }, + { 63, 5 }, { 20, 6 }, { 44, 6 }, { 29, 7 }, { 35, 7 }, + { 28, 7 }, { 36, 7 }, { 11, 6 }, { 53, 6 }, { 19, 6 }, + { 45, 6 }, { 0, 5 }, { 10, 6 }, { 54, 6 }, { 18, 6 }, + { 46, 6 }, { 27, 7 }, { 37, 7 }, { 26, 7 }, { 38, 7 }, + { 9, 6 }, { 55, 6 }, { 16, 6 }, { 48, 6 }, { 8, 6 }, + { 56, 6 }, { 17, 6 }, { 47, 6 }, { 7, 6 }, { 57, 6 }, + { 25, 7 }, { 39, 7 }, { 24, 7 }, { 40, 7 }, { 6, 6 }, + { 58, 6 }, { 5, 6 }, { 59, 6 }, + /* Coefficient table A.6.3 - 63 entries */ + { 0, 4 }, { 7, 5 }, { 57, 5 }, { 15, 6 }, { 49, 6 }, + { 25, 7 }, { 39, 7 }, { 24, 7 }, { 40, 7 }, { 18, 6 }, + { 46, 6 }, { 14, 6 }, { 50, 6 }, { 6, 5 }, { 58, 5 }, + { 5, 5 }, { 59, 5 }, { 31, 8 }, { 33, 8 }, { 30, 8 }, + { 34, 8 }, { 23, 7 }, { 41, 7 }, { 17, 6 }, { 47, 6 }, + { 13, 6 }, { 51, 6 }, { 16, 6 }, { 48, 6 }, { 4, 5 }, + { 60, 5 }, { 12, 6 }, { 52, 6 }, { 22, 7 }, { 42, 7 }, + { 29, 8 }, { 35, 8 }, { 28, 8 }, { 36, 8 }, { 3, 5 }, + { 61, 5 }, { 11, 6 }, { 53, 6 }, { 10, 6 }, { 54, 6 }, + { 2, 5 }, { 62, 5 }, { 21, 7 }, { 43, 7 }, { 20, 7 }, + { 44, 7 }, { 9, 6 }, { 55, 6 }, { 1, 5 }, { 63, 5 }, + { 27, 8 }, { 37, 8 }, { 26, 8 }, { 38, 8 }, { 19, 7 }, + { 45, 7 }, { 8, 6 }, { 56, 6 }, + /* Coefficient table A.6.4 - 63 entries */ + { 16, 6 }, { 48, 6 }, { 27, 8 }, { 37, 8 }, { 26, 8 }, + { 38, 8 }, { 21, 7 }, { 43, 7 }, { 8, 5 }, { 56, 5 }, + { 1, 4 }, { 63, 4 }, { 14, 6 }, { 50, 6 }, { 20, 7 }, + { 44, 7 }, { 31, 9 }, { 33, 9 }, { 30, 9 }, { 34, 9 }, + { 25, 8 }, { 39, 8 }, { 7, 5 }, { 57, 5 }, { 0, 4 }, + { 6, 5 }, { 58, 5 }, { 13, 6 }, { 51, 6 }, { 12, 6 }, + { 52, 6 }, { 5, 5 }, { 59, 5 }, { 19, 7 }, { 45, 7 }, + { 24, 8 }, { 40, 8 }, { 29, 9 }, { 35, 9 }, { 28, 9 }, + { 36, 9 }, { 11, 6 }, { 53, 6 }, { 4, 5 }, { 60, 5 }, + { 18, 7 }, { 46, 7 }, { 23, 8 }, { 41, 8 }, { 22, 8 }, + { 42, 8 }, { 10, 6 }, { 54, 6 }, { 3, 5 }, { 61, 5 }, + { 2, 5 }, { 62, 5 }, { 17, 7 }, { 47, 7 }, { 15, 7 }, + { 49, 7 }, { 9, 6 }, { 55, 6 }, + /* Coefficient table A.7.1 - 127 entries */ + { 18, 7 }, { 110, 7 }, { 63, 7 }, { 65, 7 }, { 38, 6 }, + { 90, 6 }, { 17, 7 }, { 111, 7 }, { 62, 7 }, { 66, 7 }, + { 61, 7 }, { 67, 7 }, { 16, 7 }, { 112, 7 }, { 37, 6 }, + { 91, 6 }, { 60, 7 }, { 68, 7 }, { 15, 7 }, { 113, 7 }, + { 32, 6 }, { 96, 6 }, { 59, 7 }, { 69, 7 }, { 14, 7 }, + { 114, 7 }, { 36, 6 }, { 92, 6 }, { 58, 7 }, { 70, 7 }, + { 13, 7 }, { 115, 7 }, { 57, 7 }, { 71, 7 }, { 12, 7 }, + { 116, 7 }, { 35, 6 }, { 93, 6 }, { 56, 7 }, { 72, 7 }, + { 55, 7 }, { 73, 7 }, { 11, 7 }, { 117, 7 }, { 10, 7 }, + { 118, 7 }, { 34, 6 }, { 94, 6 }, { 54, 7 }, { 74, 7 }, + { 9, 7 }, { 119, 7 }, { 33, 6 }, { 95, 6 }, { 53, 7 }, + { 75, 7 }, { 52, 7 }, { 76, 7 }, { 8, 7 }, { 120, 7 }, + { 51, 7 }, { 77, 7 }, { 50, 7 }, { 78, 7 }, { 7, 7 }, + { 121, 7 }, { 5, 7 }, { 123, 7 }, { 6, 7 }, { 122, 7 }, + { 49, 7 }, { 79, 7 }, { 4, 7 }, { 124, 7 }, { 31, 8 }, + { 97, 8 }, { 30, 8 }, { 98, 8 }, { 48, 7 }, { 80, 7 }, + { 3, 7 }, { 125, 7 }, { 29, 8 }, { 99, 8 }, { 28, 8 }, + { 100, 8 }, { 47, 7 }, { 81, 7 }, { 2, 7 }, { 126, 7 }, + { 46, 7 }, { 82, 7 }, { 1, 7 }, { 127, 7 }, { 27, 8 }, + { 101, 8 }, { 26, 8 }, { 102, 8 }, { 45, 7 }, { 83, 7 }, + { 0, 7 }, { 25, 8 }, { 103, 8 }, { 44, 7 }, { 84, 7 }, + { 24, 8 }, { 104, 8 }, { 23, 8 }, { 105, 8 }, { 43, 7 }, + { 85, 7 }, { 42, 7 }, { 86, 7 }, { 22, 8 }, { 106, 8 }, + { 21, 8 }, { 107, 8 }, { 41, 7 }, { 87, 7 }, { 20, 8 }, + { 108, 8 }, { 19, 8 }, { 109, 8 }, { 40, 7 }, { 88, 7 }, + { 39, 7 }, { 89, 7 }, + /* Coefficient table A.7.2 - 127 entries */ + { 47, 7 }, { 81, 7 }, { 46, 7 }, { 82, 7 }, { 8, 6 }, + { 120, 6 }, { 31, 7 }, { 97, 7 }, { 45, 7 }, { 83, 7 }, + { 7, 6 }, { 121, 6 }, { 30, 7 }, { 98, 7 }, { 29, 7 }, + { 99, 7 }, { 6, 6 }, { 122, 6 }, { 63, 8 }, { 65, 8 }, + { 62, 8 }, { 66, 8 }, { 44, 7 }, { 84, 7 }, { 5, 6 }, + { 123, 6 }, { 28, 7 }, { 100, 7 }, { 43, 7 }, { 85, 7 }, + { 4, 6 }, { 124, 6 }, { 27, 7 }, { 101, 7 }, { 26, 7 }, + { 102, 7 }, { 42, 7 }, { 86, 7 }, { 61, 8 }, { 67, 8 }, + { 60, 8 }, { 68, 8 }, { 3, 6 }, { 125, 6 }, { 25, 7 }, + { 103, 7 }, { 41, 7 }, { 87, 7 }, { 2, 6 }, { 126, 6 }, + { 24, 7 }, { 104, 7 }, { 59, 8 }, { 69, 8 }, { 58, 8 }, + { 70, 8 }, { 40, 7 }, { 88, 7 }, { 23, 7 }, { 105, 7 }, + { 39, 7 }, { 89, 7 }, { 22, 7 }, { 106, 7 }, { 1, 6 }, + { 127, 6 }, { 57, 8 }, { 71, 8 }, { 56, 8 }, { 72, 8 }, + { 21, 7 }, { 107, 7 }, { 38, 7 }, { 90, 7 }, { 20, 7 }, + { 108, 7 }, { 0, 6 }, { 55, 8 }, { 73, 8 }, { 54, 8 }, + { 74, 8 }, { 37, 7 }, { 91, 7 }, { 19, 7 }, { 109, 7 }, + { 18, 7 }, { 110, 7 }, { 36, 7 }, { 92, 7 }, { 53, 8 }, + { 75, 8 }, { 52, 8 }, { 76, 8 }, { 17, 7 }, { 111, 7 }, + { 35, 7 }, { 93, 7 }, { 32, 7 }, { 96, 7 }, { 16, 7 }, + { 112, 7 }, { 15, 7 }, { 113, 7 }, { 34, 7 }, { 94, 7 }, + { 51, 8 }, { 77, 8 }, { 50, 8 }, { 78, 8 }, { 14, 7 }, + { 114, 7 }, { 13, 7 }, { 115, 7 }, { 33, 7 }, { 95, 7 }, + { 12, 7 }, { 116, 7 }, { 49, 8 }, { 79, 8 }, { 48, 8 }, + { 80, 8 }, { 11, 7 }, { 117, 7 }, { 10, 7 }, { 118, 7 }, + { 9, 7 }, { 119, 7 }, + /* Coefficient table A.7.3 - 127 entries */ + { 15, 6 }, { 113, 6 }, { 31, 7 }, { 97, 7 }, { 51, 8 }, + { 77, 8 }, { 50, 8 }, { 78, 8 }, { 14, 6 }, { 114, 6 }, + { 0, 5 }, { 37, 7 }, { 91, 7 }, { 30, 7 }, { 98, 7 }, + { 13, 6 }, { 115, 6 }, { 29, 7 }, { 99, 7 }, { 49, 8 }, + { 79, 8 }, { 63, 9 }, { 65, 9 }, { 62, 9 }, { 66, 9 }, + { 12, 6 }, { 116, 6 }, { 36, 7 }, { 92, 7 }, { 28, 7 }, + { 100, 7 }, { 35, 7 }, { 93, 7 }, { 48, 8 }, { 80, 8 }, + { 47, 8 }, { 81, 8 }, { 11, 6 }, { 117, 6 }, { 10, 6 }, + { 118, 6 }, { 27, 7 }, { 101, 7 }, { 34, 7 }, { 94, 7 }, + { 61, 9 }, { 67, 9 }, { 60, 9 }, { 68, 9 }, { 46, 8 }, + { 82, 8 }, { 26, 7 }, { 102, 7 }, { 9, 6 }, { 119, 6 }, + { 32, 7 }, { 96, 7 }, { 33, 7 }, { 95, 7 }, { 8, 6 }, + { 120, 6 }, { 25, 7 }, { 103, 7 }, { 45, 8 }, { 83, 8 }, + { 59, 9 }, { 69, 9 }, { 58, 9 }, { 70, 9 }, { 7, 6 }, + { 121, 6 }, { 24, 7 }, { 104, 7 }, { 23, 7 }, { 105, 7 }, + { 6, 6 }, { 122, 6 }, { 44, 8 }, { 84, 8 }, { 57, 9 }, + { 71, 9 }, { 56, 9 }, { 72, 9 }, { 22, 7 }, { 106, 7 }, + { 5, 6 }, { 123, 6 }, { 43, 8 }, { 85, 8 }, { 42, 8 }, + { 86, 8 }, { 21, 7 }, { 107, 7 }, { 4, 6 }, { 124, 6 }, + { 20, 7 }, { 108, 7 }, { 55, 9 }, { 73, 9 }, { 54, 9 }, + { 74, 9 }, { 41, 8 }, { 87, 8 }, { 3, 6 }, { 125, 6 }, + { 19, 7 }, { 109, 7 }, { 18, 7 }, { 110, 7 }, { 2, 6 }, + { 126, 6 }, { 40, 8 }, { 88, 8 }, { 53, 9 }, { 75, 9 }, + { 52, 9 }, { 76, 9 }, { 17, 7 }, { 111, 7 }, { 39, 8 }, + { 89, 8 }, { 38, 8 }, { 90, 8 }, { 16, 7 }, { 112, 7 }, + { 1, 6 }, { 127, 6 }, + /* Coefficient table A.7.4 - 127 entries */ + { 3, 5 }, { 125, 5 }, { 32, 7 }, { 96, 7 }, { 29, 7 }, + { 99, 7 }, { 16, 6 }, { 112, 6 }, { 2, 5 }, { 126, 5 }, + { 53, 9 }, { 75, 9 }, { 52, 9 }, { 76, 9 }, { 42, 8 }, + { 86, 8 }, { 28, 7 }, { 100, 7 }, { 15, 6 }, { 113, 6 }, + { 63, 10 }, { 65, 10 }, { 62, 10 }, { 66, 10 }, { 51, 9 }, + { 77, 9 }, { 41, 8 }, { 87, 8 }, { 27, 7 }, { 101, 7 }, + { 14, 6 }, { 114, 6 }, { 1, 5 }, { 127, 5 }, { 13, 6 }, + { 115, 6 }, { 0, 5 }, { 26, 7 }, { 102, 7 }, { 40, 8 }, + { 88, 8 }, { 50, 9 }, { 78, 9 }, { 61, 10 }, { 67, 10 }, + { 60, 10 }, { 68, 10 }, { 12, 6 }, { 116, 6 }, { 25, 7 }, + { 103, 7 }, { 39, 8 }, { 89, 8 }, { 49, 9 }, { 79, 9 }, + { 48, 9 }, { 80, 9 }, { 11, 6 }, { 117, 6 }, { 24, 7 }, + { 104, 7 }, { 38, 8 }, { 90, 8 }, { 59, 10 }, { 69, 10 }, + { 58, 10 }, { 70, 10 }, { 47, 9 }, { 81, 9 }, { 10, 6 }, + { 118, 6 }, { 9, 6 }, { 119, 6 }, { 23, 7 }, { 105, 7 }, + { 22, 7 }, { 106, 7 }, { 8, 6 }, { 120, 6 }, { 37, 8 }, + { 91, 8 }, { 36, 8 }, { 92, 8 }, { 21, 7 }, { 107, 7 }, + { 7, 6 }, { 121, 6 }, { 6, 6 }, { 122, 6 }, { 57, 10 }, + { 71, 10 }, { 56, 10 }, { 72, 10 }, { 46, 9 }, { 82, 9 }, + { 35, 8 }, { 93, 8 }, { 20, 7 }, { 108, 7 }, { 5, 6 }, + { 123, 6 }, { 19, 7 }, { 109, 7 }, { 45, 9 }, { 83, 9 }, + { 44, 9 }, { 84, 9 }, { 31, 8 }, { 97, 8 }, { 4, 6 }, + { 124, 6 }, { 34, 8 }, { 94, 8 }, { 55, 10 }, { 73, 10 }, + { 54, 10 }, { 74, 10 }, { 43, 9 }, { 85, 9 }, { 18, 7 }, + { 110, 7 }, { 30, 8 }, { 98, 8 }, { 33, 8 }, { 95, 8 }, + { 17, 7 }, { 111, 7 }, + /* Coefficient table B.2.2 - 80 entries */ + { 80, 5 }, { 240, 5 }, { 253, 10 }, { 87, 10 }, { 117, 10 }, + { 223, 10 }, { 93, 10 }, { 247, 10 }, { 221, 10 }, { 119, 10 }, + { 213, 10 }, { 127, 10 }, { 85, 10 }, { 255, 10 }, { 245, 10 }, + { 95, 10 }, { 81, 10 }, { 243, 10 }, { 17, 7 }, { 51, 7 }, + { 20, 6 }, { 60, 6 }, { 116, 9 }, { 220, 9 }, { 84, 9 }, + { 252, 9 }, { 68, 8 }, { 204, 8 }, { 212, 7 }, { 124, 7 }, + { 196, 6 }, { 76, 6 }, { 5, 5 }, { 15, 5 }, { 53, 7 }, + { 31, 7 }, { 61, 7 }, { 23, 7 }, { 52, 6 }, { 28, 6 }, + { 13, 5 }, { 7, 5 }, { 16, 4 }, { 48, 4 }, { 4, 4 }, + { 12, 4 }, { 49, 6 }, { 19, 6 }, { 244, 7 }, { 92, 7 }, + { 21, 9 }, { 63, 9 }, { 197, 9 }, { 79, 9 }, { 69, 10 }, + { 207, 10 }, { 205, 10 }, { 71, 10 }, { 241, 9 }, { 83, 9 }, + { 208, 6 }, { 112, 6 }, { 77, 9 }, { 199, 9 }, { 113, 9 }, + { 211, 9 }, { 29, 9 }, { 55, 9 }, { 209, 10 }, { 115, 10 }, + { 125, 10 }, { 215, 10 }, { 65, 8 }, { 195, 8 }, { 193, 8 }, + { 67, 8 }, { 64, 4 }, { 192, 4 }, { 1, 4 }, { 3, 4 }, + /* Coefficient table B.2.3 - 81 entries */ + { 16, 4 }, { 48, 4 }, { 4, 4 }, { 12, 4 }, { 64, 4 }, + { 192, 4 }, { 5, 6 }, { 15, 6 }, { 13, 6 }, { 7, 6 }, + { 212, 8 }, { 124, 8 }, { 213, 10 }, { 127, 10 }, { 93, 10 }, + { 247, 10 }, { 117, 10 }, { 223, 10 }, { 253, 10 }, { 87, 10 }, + { 21, 9 }, { 63, 9 }, { 221, 10 }, { 119, 10 }, { 81, 10 }, + { 243, 10 }, { 205, 10 }, { 71, 10 }, { 69, 10 }, { 207, 10 }, + { 245, 10 }, { 95, 10 }, { 209, 10 }, { 115, 10 }, { 125, 10 }, + { 215, 10 }, { 85, 10 }, { 255, 10 }, { 116, 10 }, { 220, 10 }, + { 241, 10 }, { 83, 10 }, { 77, 10 }, { 199, 10 }, { 84, 10 }, + { 252, 10 }, { 29, 9 }, { 55, 9 }, { 61, 8 }, { 23, 8 }, + { 53, 8 }, { 31, 8 }, { 1, 4 }, { 3, 4 }, { 193, 8 }, + { 67, 8 }, { 65, 8 }, { 195, 8 }, { 196, 7 }, { 76, 7 }, + { 49, 7 }, { 19, 7 }, { 20, 7 }, { 60, 7 }, { 52, 7 }, + { 28, 7 }, { 208, 7 }, { 112, 7 }, { 80, 7 }, { 240, 7 }, + { 113, 10 }, { 211, 10 }, { 197, 10 }, { 79, 10 }, { 68, 9 }, + { 204, 9 }, { 17, 9 }, { 51, 9 }, { 244, 9 }, { 92, 9 }, + { 0, 2 }, + /* Coefficient table B.2.4 - 81 entries */ + { 1, 4 }, { 3, 4 }, { 52, 7 }, { 28, 7 }, { 193, 8 }, + { 67, 8 }, { 213, 10 }, { 127, 10 }, { 253, 10 }, { 87, 10 }, + { 93, 10 }, { 247, 10 }, { 117, 10 }, { 223, 10 }, { 80, 7 }, + { 240, 7 }, { 196, 7 }, { 76, 7 }, { 208, 7 }, { 112, 7 }, + { 221, 10 }, { 119, 10 }, { 245, 10 }, { 95, 10 }, { 69, 10 }, + { 207, 10 }, { 85, 10 }, { 255, 10 }, { 209, 10 }, { 115, 10 }, + { 205, 10 }, { 71, 10 }, { 81, 10 }, { 243, 10 }, { 125, 10 }, + { 215, 10 }, { 5, 7 }, { 15, 7 }, { 116, 10 }, { 220, 10 }, + { 84, 10 }, { 252, 10 }, { 29, 10 }, { 55, 10 }, { 113, 10 }, + { 211, 10 }, { 241, 10 }, { 83, 10 }, { 21, 10 }, { 63, 10 }, + { 197, 10 }, { 79, 10 }, { 77, 10 }, { 199, 10 }, { 16, 5 }, + { 48, 5 }, { 4, 5 }, { 12, 5 }, { 49, 7 }, { 19, 7 }, + { 13, 7 }, { 7, 7 }, { 212, 10 }, { 124, 10 }, { 244, 10 }, + { 92, 10 }, { 68, 9 }, { 204, 9 }, { 53, 9 }, { 31, 9 }, + { 61, 9 }, { 23, 9 }, { 17, 9 }, { 51, 9 }, { 65, 9 }, + { 195, 9 }, { 20, 8 }, { 60, 8 }, { 64, 5 }, { 192, 5 }, + { 0, 1 }, + /* Coefficient table B.3.2 - 49 entries */ + { 58, 5 }, { 14, 5 }, { 59, 6 }, { 13, 6 }, { 19, 7 }, + { 53, 7 }, { 25, 7 }, { 47, 7 }, { 1, 4 }, { 7, 4 }, + { 0, 2 }, { 9, 6 }, { 63, 6 }, { 57, 6 }, { 15, 6 }, + { 24, 6 }, { 40, 6 }, { 17, 6 }, { 55, 6 }, { 42, 8 }, + { 30, 8 }, { 43, 9 }, { 29, 9 }, { 27, 9 }, { 45, 9 }, + { 41, 7 }, { 31, 7 }, { 3, 6 }, { 5, 6 }, { 8, 5 }, + { 56, 5 }, { 49, 6 }, { 23, 6 }, { 11, 7 }, { 61, 7 }, + { 26, 8 }, { 46, 8 }, { 51, 8 }, { 21, 8 }, { 16, 5 }, + { 48, 5 }, { 18, 7 }, { 54, 7 }, { 50, 7 }, { 22, 7 }, + { 10, 6 }, { 62, 6 }, { 2, 5 }, { 6, 5 }, + /* Coefficient table B.3.3 - 49 entries */ + { 57, 5 }, { 15, 5 }, { 9, 5 }, { 63, 5 }, { 59, 7 }, + { 13, 7 }, { 50, 7 }, { 22, 7 }, { 18, 7 }, { 54, 7 }, + { 51, 8 }, { 21, 8 }, { 27, 10 }, { 45, 10 }, { 43, 10 }, + { 29, 10 }, { 26, 9 }, { 46, 9 }, { 17, 6 }, { 55, 6 }, + { 49, 6 }, { 23, 6 }, { 8, 4 }, { 56, 4 }, { 16, 5 }, + { 48, 5 }, { 10, 6 }, { 62, 6 }, { 58, 6 }, { 14, 6 }, + { 1, 4 }, { 7, 4 }, { 2, 5 }, { 6, 5 }, { 25, 8 }, + { 47, 8 }, { 42, 9 }, { 30, 9 }, { 19, 9 }, { 53, 9 }, + { 24, 7 }, { 40, 7 }, { 41, 8 }, { 31, 8 }, { 11, 8 }, + { 61, 8 }, { 3, 7 }, { 5, 7 }, { 0, 2 }, + /* Coefficient table B.3.4 - 49 entries */ + { 0, 1 }, { 8, 4 }, { 56, 4 }, { 1, 4 }, { 7, 4 }, + { 59, 8 }, { 13, 8 }, { 27, 10 }, { 45, 10 }, { 43, 10 }, + { 29, 10 }, { 26, 10 }, { 46, 10 }, { 51, 10 }, { 21, 10 }, + { 18, 8 }, { 54, 8 }, { 50, 8 }, { 22, 8 }, { 16, 6 }, + { 48, 6 }, { 17, 7 }, { 55, 7 }, { 24, 8 }, { 40, 8 }, + { 19, 10 }, { 53, 10 }, { 42, 10 }, { 30, 10 }, { 25, 9 }, + { 47, 9 }, { 49, 7 }, { 23, 7 }, { 10, 7 }, { 62, 7 }, + { 2, 6 }, { 6, 6 }, { 58, 7 }, { 14, 7 }, { 11, 9 }, + { 61, 9 }, { 41, 9 }, { 31, 9 }, { 3, 8 }, { 5, 8 }, + { 9, 6 }, { 63, 6 }, { 57, 6 }, { 15, 6 }, + /* Coefficient table B.4.2 - 225 entries */ + { 33, 7 }, { 239, 7 }, { 36, 7 }, { 236, 7 }, { 119, 10 }, + { 153, 10 }, { 151, 10 }, { 121, 10 }, { 118, 10 }, { 154, 10 }, + { 167, 10 }, { 105, 10 }, { 247, 8 }, { 25, 8 }, { 112, 8 }, + { 144, 8 }, { 150, 10 }, { 122, 10 }, { 103, 10 }, { 169, 10 }, + { 87, 10 }, { 185, 10 }, { 183, 10 }, { 89, 10 }, { 53, 8 }, + { 219, 8 }, { 213, 8 }, { 59, 8 }, { 228, 7 }, { 44, 7 }, + { 225, 7 }, { 47, 7 }, { 166, 10 }, { 106, 10 }, { 102, 10 }, + { 170, 10 }, { 149, 10 }, { 123, 10 }, { 117, 10 }, { 155, 10 }, + { 114, 9 }, { 158, 9 }, { 165, 10 }, { 107, 10 }, { 148, 10 }, + { 124, 10 }, { 81, 7 }, { 191, 7 }, { 21, 7 }, { 251, 7 }, + { 64, 6 }, { 192, 6 }, { 242, 7 }, { 30, 7 }, { 116, 10 }, + { 156, 10 }, { 71, 10 }, { 201, 10 }, { 101, 10 }, { 171, 10 }, + { 199, 10 }, { 73, 10 }, { 19, 8 }, { 253, 8 }, { 18, 7 }, + { 254, 7 }, { 182, 10 }, { 90, 10 }, { 86, 10 }, { 186, 10 }, + { 39, 9 }, { 233, 9 }, { 34, 8 }, { 238, 8 }, { 2, 6 }, + { 14, 6 }, { 177, 7 }, { 95, 7 }, { 231, 9 }, { 41, 9 }, + { 146, 9 }, { 126, 9 }, { 67, 8 }, { 205, 8 }, { 17, 6 }, + { 255, 6 }, { 241, 6 }, { 31, 6 }, { 16, 5 }, { 240, 5 }, + { 243, 8 }, { 29, 8 }, { 195, 8 }, { 77, 8 }, { 245, 7 }, + { 27, 7 }, { 7, 8 }, { 9, 8 }, { 209, 8 }, { 63, 8 }, + { 99, 9 }, { 173, 9 }, { 163, 9 }, { 109, 9 }, { 226, 8 }, + { 46, 8 }, { 212, 8 }, { 60, 8 }, { 97, 8 }, { 175, 8 }, + { 161, 8 }, { 111, 8 }, { 52, 8 }, { 220, 8 }, { 180, 9 }, + { 92, 9 }, { 50, 9 }, { 222, 9 }, { 35, 9 }, { 237, 9 }, + { 211, 10 }, { 61, 10 }, { 51, 10 }, { 221, 10 }, { 210, 9 }, + { 62, 9 }, { 84, 9 }, { 188, 9 }, { 82, 8 }, { 190, 8 }, + { 4, 6 }, { 12, 6 }, { 227, 9 }, { 45, 9 }, { 214, 9 }, + { 58, 9 }, { 54, 9 }, { 218, 9 }, { 197, 9 }, { 75, 9 }, + { 178, 8 }, { 94, 8 }, { 22, 8 }, { 250, 8 }, { 65, 7 }, + { 207, 7 }, { 80, 7 }, { 176, 7 }, { 246, 8 }, { 26, 8 }, + { 69, 9 }, { 203, 9 }, { 145, 9 }, { 127, 9 }, { 193, 7 }, + { 79, 7 }, { 37, 8 }, { 235, 8 }, { 229, 8 }, { 43, 8 }, + { 5, 7 }, { 11, 7 }, { 20, 7 }, { 252, 7 }, { 244, 7 }, + { 28, 7 }, { 1, 5 }, { 15, 5 }, { 98, 9 }, { 174, 9 }, + { 147, 10 }, { 125, 10 }, { 115, 10 }, { 157, 10 }, { 96, 8 }, + { 160, 8 }, { 113, 9 }, { 159, 9 }, { 38, 9 }, { 234, 9 }, + { 162, 9 }, { 110, 9 }, { 55, 10 }, { 217, 10 }, { 215, 10 }, + { 57, 10 }, { 48, 8 }, { 208, 8 }, { 68, 9 }, { 204, 9 }, + { 164, 10 }, { 108, 10 }, { 100, 10 }, { 172, 10 }, { 32, 7 }, + { 224, 7 }, { 0, 4 }, { 3, 8 }, { 13, 8 }, { 23, 9 }, + { 249, 9 }, { 230, 9 }, { 42, 9 }, { 83, 9 }, { 189, 9 }, + { 181, 10 }, { 91, 10 }, { 198, 10 }, { 74, 10 }, { 6, 8 }, + { 10, 8 }, { 66, 8 }, { 206, 8 }, { 179, 9 }, { 93, 9 }, + { 70, 10 }, { 202, 10 }, { 85, 10 }, { 187, 10 }, { 194, 8 }, + { 78, 8 }, { 196, 9 }, { 76, 9 }, { 49, 9 }, { 223, 9 }, + /* Coefficient table B.4.3 - 225 entries */ + { 193, 7 }, { 79, 7 }, { 48, 7 }, { 208, 7 }, { 6, 8 }, + { 10, 8 }, { 151, 10 }, { 121, 10 }, { 119, 10 }, { 153, 10 }, + { 167, 10 }, { 105, 10 }, { 118, 10 }, { 154, 10 }, { 103, 10 }, + { 169, 10 }, { 150, 10 }, { 122, 10 }, { 102, 10 }, { 170, 10 }, + { 183, 10 }, { 89, 10 }, { 117, 10 }, { 155, 10 }, { 149, 10 }, + { 123, 10 }, { 166, 10 }, { 106, 10 }, { 87, 10 }, { 185, 10 }, + { 116, 10 }, { 156, 10 }, { 148, 10 }, { 124, 10 }, { 71, 10 }, + { 201, 10 }, { 199, 10 }, { 73, 10 }, { 165, 10 }, { 107, 10 }, + { 182, 10 }, { 90, 10 }, { 101, 10 }, { 171, 10 }, { 86, 10 }, + { 186, 10 }, { 20, 7 }, { 252, 7 }, { 55, 10 }, { 217, 10 }, + { 147, 10 }, { 125, 10 }, { 115, 10 }, { 157, 10 }, { 215, 10 }, + { 57, 10 }, { 100, 10 }, { 172, 10 }, { 181, 10 }, { 91, 10 }, + { 198, 10 }, { 74, 10 }, { 114, 10 }, { 158, 10 }, { 244, 7 }, + { 28, 7 }, { 70, 10 }, { 202, 10 }, { 164, 10 }, { 108, 10 }, + { 85, 10 }, { 187, 10 }, { 146, 10 }, { 126, 10 }, { 39, 10 }, + { 233, 10 }, { 231, 10 }, { 41, 10 }, { 53, 9 }, { 219, 9 }, + { 54, 10 }, { 218, 10 }, { 99, 10 }, { 173, 10 }, { 214, 10 }, + { 58, 10 }, { 163, 10 }, { 109, 10 }, { 197, 10 }, { 75, 10 }, + { 84, 10 }, { 188, 10 }, { 69, 10 }, { 203, 10 }, { 113, 10 }, + { 159, 10 }, { 180, 10 }, { 92, 10 }, { 145, 10 }, { 127, 10 }, + { 98, 10 }, { 174, 10 }, { 23, 10 }, { 249, 10 }, { 247, 10 }, + { 25, 10 }, { 162, 10 }, { 110, 10 }, { 38, 10 }, { 234, 10 }, + { 230, 10 }, { 42, 10 }, { 83, 10 }, { 189, 10 }, { 179, 10 }, + { 93, 10 }, { 211, 10 }, { 61, 10 }, { 112, 10 }, { 144, 10 }, + { 51, 10 }, { 221, 10 }, { 68, 10 }, { 204, 10 }, { 213, 10 }, + { 59, 10 }, { 196, 10 }, { 76, 10 }, { 3, 7 }, { 13, 7 }, + { 66, 8 }, { 206, 8 }, { 81, 8 }, { 191, 8 }, { 32, 6 }, + { 224, 6 }, { 0, 2 }, { 7, 9 }, { 9, 9 }, { 97, 9 }, + { 175, 9 }, { 36, 8 }, { 236, 8 }, { 194, 8 }, { 78, 8 }, + { 177, 8 }, { 95, 8 }, { 2, 6 }, { 14, 6 }, { 21, 8 }, + { 251, 8 }, { 245, 8 }, { 27, 8 }, { 228, 8 }, { 44, 8 }, + { 22, 9 }, { 250, 9 }, { 246, 9 }, { 26, 9 }, { 49, 8 }, + { 223, 8 }, { 19, 8 }, { 253, 8 }, { 209, 8 }, { 63, 8 }, + { 243, 8 }, { 29, 8 }, { 225, 7 }, { 47, 7 }, { 64, 7 }, + { 192, 7 }, { 33, 7 }, { 239, 7 }, { 18, 7 }, { 254, 7 }, + { 242, 7 }, { 30, 7 }, { 161, 9 }, { 111, 9 }, { 178, 9 }, + { 94, 9 }, { 82, 9 }, { 190, 9 }, { 195, 9 }, { 77, 9 }, + { 52, 9 }, { 220, 9 }, { 212, 9 }, { 60, 9 }, { 67, 9 }, + { 205, 9 }, { 37, 9 }, { 235, 9 }, { 34, 8 }, { 238, 8 }, + { 226, 8 }, { 46, 8 }, { 17, 6 }, { 255, 6 }, { 4, 7 }, + { 12, 7 }, { 80, 8 }, { 176, 8 }, { 229, 9 }, { 43, 9 }, + { 35, 9 }, { 237, 9 }, { 16, 5 }, { 240, 5 }, { 241, 6 }, + { 31, 6 }, { 227, 9 }, { 45, 9 }, { 210, 9 }, { 62, 9 }, + { 50, 9 }, { 222, 9 }, { 96, 9 }, { 160, 9 }, { 5, 8 }, + { 11, 8 }, { 65, 8 }, { 207, 8 }, { 1, 5 }, { 15, 5 }, + /* Coefficient table B.4.4 - 225 entries */ + { 3, 7 }, { 13, 7 }, { 4, 7 }, { 12, 7 }, { 151, 10 }, + { 121, 10 }, { 119, 10 }, { 153, 10 }, { 103, 10 }, { 169, 10 }, + { 167, 10 }, { 105, 10 }, { 150, 10 }, { 122, 10 }, { 118, 10 }, + { 154, 10 }, { 117, 10 }, { 155, 10 }, { 102, 10 }, { 170, 10 }, + { 5, 8 }, { 11, 8 }, { 183, 10 }, { 89, 10 }, { 87, 10 }, + { 185, 10 }, { 166, 10 }, { 106, 10 }, { 149, 10 }, { 123, 10 }, + { 17, 5 }, { 255, 5 }, { 1, 4 }, { 15, 4 }, { 241, 5 }, + { 31, 5 }, { 116, 10 }, { 156, 10 }, { 148, 10 }, { 124, 10 }, + { 199, 10 }, { 73, 10 }, { 182, 10 }, { 90, 10 }, { 71, 10 }, + { 201, 10 }, { 86, 10 }, { 186, 10 }, { 101, 10 }, { 171, 10 }, + { 115, 10 }, { 157, 10 }, { 165, 10 }, { 107, 10 }, { 215, 10 }, + { 57, 10 }, { 55, 10 }, { 217, 10 }, { 70, 10 }, { 202, 10 }, + { 147, 10 }, { 125, 10 }, { 85, 10 }, { 187, 10 }, { 164, 10 }, + { 108, 10 }, { 198, 10 }, { 74, 10 }, { 100, 10 }, { 172, 10 }, + { 114, 10 }, { 158, 10 }, { 39, 10 }, { 233, 10 }, { 146, 10 }, + { 126, 10 }, { 99, 10 }, { 173, 10 }, { 181, 10 }, { 91, 10 }, + { 231, 10 }, { 41, 10 }, { 163, 10 }, { 109, 10 }, { 54, 10 }, + { 218, 10 }, { 214, 10 }, { 58, 10 }, { 113, 10 }, { 159, 10 }, + { 23, 10 }, { 249, 10 }, { 145, 10 }, { 127, 10 }, { 180, 10 }, + { 92, 10 }, { 84, 10 }, { 188, 10 }, { 247, 10 }, { 25, 10 }, + { 32, 6 }, { 224, 6 }, { 197, 10 }, { 75, 10 }, { 98, 10 }, + { 174, 10 }, { 112, 10 }, { 144, 10 }, { 162, 10 }, { 110, 10 }, + { 69, 10 }, { 203, 10 }, { 38, 10 }, { 234, 10 }, { 230, 10 }, + { 42, 10 }, { 7, 10 }, { 9, 10 }, { 213, 10 }, { 59, 10 }, + { 83, 10 }, { 189, 10 }, { 179, 10 }, { 93, 10 }, { 53, 10 }, + { 219, 10 }, { 97, 10 }, { 175, 10 }, { 68, 10 }, { 204, 10 }, + { 196, 10 }, { 76, 10 }, { 161, 10 }, { 111, 10 }, { 22, 10 }, + { 250, 10 }, { 246, 10 }, { 26, 10 }, { 82, 10 }, { 190, 10 }, + { 96, 10 }, { 160, 10 }, { 178, 10 }, { 94, 10 }, { 37, 10 }, + { 235, 10 }, { 67, 10 }, { 205, 10 }, { 51, 10 }, { 221, 10 }, + { 229, 10 }, { 43, 10 }, { 6, 10 }, { 10, 10 }, { 211, 10 }, + { 61, 10 }, { 212, 10 }, { 60, 10 }, { 195, 10 }, { 77, 10 }, + { 52, 10 }, { 220, 10 }, { 81, 10 }, { 191, 10 }, { 177, 10 }, + { 95, 10 }, { 65, 8 }, { 207, 8 }, { 21, 10 }, { 251, 10 }, + { 245, 10 }, { 27, 10 }, { 194, 10 }, { 78, 10 }, { 228, 10 }, + { 44, 10 }, { 193, 8 }, { 79, 8 }, { 20, 8 }, { 252, 8 }, + { 0, 2 }, { 2, 6 }, { 14, 6 }, { 19, 8 }, { 253, 8 }, + { 49, 8 }, { 223, 8 }, { 209, 8 }, { 63, 8 }, { 244, 8 }, + { 28, 8 }, { 66, 10 }, { 206, 10 }, { 210, 10 }, { 62, 10 }, + { 36, 9 }, { 236, 9 }, { 243, 8 }, { 29, 8 }, { 33, 7 }, + { 239, 7 }, { 225, 7 }, { 47, 7 }, { 64, 8 }, { 192, 8 }, + { 80, 9 }, { 176, 9 }, { 50, 9 }, { 222, 9 }, { 18, 7 }, + { 254, 7 }, { 242, 7 }, { 30, 7 }, { 48, 8 }, { 208, 8 }, + { 226, 8 }, { 46, 8 }, { 34, 8 }, { 238, 8 }, { 227, 9 }, + { 45, 9 }, { 35, 9 }, { 237, 9 }, { 16, 5 }, { 240, 5 }, + /* Coefficient table B.5.2 - 31 entries */ + { 3, 4 }, { 29, 4 }, { 5, 5 }, { 27, 5 }, { 10, 5 }, + { 22, 5 }, { 13, 6 }, { 19, 6 }, { 7, 6 }, { 25, 6 }, + { 4, 5 }, { 28, 5 }, { 2, 4 }, { 30, 4 }, { 9, 5 }, + { 23, 5 }, { 12, 6 }, { 20, 6 }, { 15, 7 }, { 17, 7 }, + { 14, 7 }, { 18, 7 }, { 8, 5 }, { 24, 5 }, { 6, 6 }, + { 26, 6 }, { 11, 6 }, { 21, 6 }, { 0, 3 }, { 1, 4 }, + { 31, 4 }, + /* Coefficient table B.5.3 - 31 entries */ + { 1, 3 }, { 31, 3 }, { 7, 6 }, { 25, 6 }, { 13, 7 }, + { 19, 7 }, { 12, 7 }, { 20, 7 }, { 10, 6 }, { 22, 6 }, + { 6, 6 }, { 26, 6 }, { 2, 4 }, { 30, 4 }, { 0, 2 }, + { 4, 5 }, { 28, 5 }, { 15, 8 }, { 17, 8 }, { 14, 8 }, + { 18, 8 }, { 11, 7 }, { 21, 7 }, { 9, 6 }, { 23, 6 }, + { 3, 5 }, { 29, 5 }, { 8, 6 }, { 24, 6 }, { 5, 6 }, + { 27, 6 }, + /* Coefficient table B.5.4 - 31 entries */ + { 3, 4 }, { 29, 4 }, { 9, 6 }, { 23, 6 }, { 8, 6 }, + { 24, 6 }, { 13, 8 }, { 19, 8 }, { 12, 8 }, { 20, 8 }, + { 10, 7 }, { 22, 7 }, { 6, 6 }, { 26, 6 }, { 1, 3 }, + { 31, 3 }, { 2, 4 }, { 30, 4 }, { 4, 5 }, { 28, 5 }, + { 15, 9 }, { 17, 9 }, { 14, 9 }, { 18, 9 }, { 11, 8 }, + { 21, 8 }, { 7, 7 }, { 25, 7 }, { 5, 6 }, { 27, 6 }, + { 0, 2 }, + /* Coefficient table B.6.2 - 63 entries */ + { 11, 6 }, { 53, 6 }, { 21, 6 }, { 43, 6 }, { 27, 7 }, + { 37, 7 }, { 26, 7 }, { 38, 7 }, { 10, 6 }, { 54, 6 }, + { 5, 5 }, { 59, 5 }, { 20, 6 }, { 44, 6 }, { 9, 6 }, + { 55, 6 }, { 15, 7 }, { 49, 7 }, { 25, 7 }, { 39, 7 }, + { 19, 6 }, { 45, 6 }, { 4, 5 }, { 60, 5 }, { 1, 4 }, + { 63, 4 }, { 14, 7 }, { 50, 7 }, { 24, 7 }, { 40, 7 }, + { 8, 6 }, { 56, 6 }, { 18, 6 }, { 46, 6 }, { 31, 8 }, + { 33, 8 }, { 30, 8 }, { 34, 8 }, { 13, 7 }, { 51, 7 }, + { 3, 5 }, { 61, 5 }, { 23, 7 }, { 41, 7 }, { 12, 7 }, + { 52, 7 }, { 7, 6 }, { 57, 6 }, { 16, 6 }, { 48, 6 }, + { 17, 6 }, { 47, 6 }, { 0, 4 }, { 2, 5 }, { 62, 5 }, + { 22, 7 }, { 42, 7 }, { 29, 8 }, { 35, 8 }, { 28, 8 }, + { 36, 8 }, { 6, 6 }, { 58, 6 }, + /* Coefficient table B.6.3 - 63 entries */ + { 6, 5 }, { 58, 5 }, { 10, 6 }, { 54, 6 }, { 16, 6 }, + { 48, 6 }, { 17, 6 }, { 47, 6 }, { 21, 7 }, { 43, 7 }, + { 14, 7 }, { 50, 7 }, { 5, 5 }, { 59, 5 }, { 2, 4 }, + { 62, 4 }, { 9, 6 }, { 55, 6 }, { 25, 8 }, { 39, 8 }, + { 31, 9 }, { 33, 9 }, { 30, 9 }, { 34, 9 }, { 20, 7 }, + { 44, 7 }, { 8, 6 }, { 56, 6 }, { 13, 7 }, { 51, 7 }, + { 19, 7 }, { 45, 7 }, { 4, 5 }, { 60, 5 }, { 24, 8 }, + { 40, 8 }, { 29, 9 }, { 35, 9 }, { 28, 9 }, { 36, 9 }, + { 12, 7 }, { 52, 7 }, { 7, 6 }, { 57, 6 }, { 3, 5 }, + { 61, 5 }, { 18, 7 }, { 46, 7 }, { 23, 8 }, { 41, 8 }, + { 22, 8 }, { 42, 8 }, { 11, 7 }, { 53, 7 }, { 15, 8 }, + { 49, 8 }, { 27, 9 }, { 37, 9 }, { 26, 9 }, { 38, 9 }, + { 0, 3 }, { 1, 4 }, { 63, 4 }, + /* Coefficient table B.6.4 - 63 entries */ + { 1, 3 }, { 63, 3 }, { 14, 7 }, { 50, 7 }, { 18, 7 }, + { 46, 7 }, { 27, 9 }, { 37, 9 }, { 26, 9 }, { 38, 9 }, + { 21, 8 }, { 43, 8 }, { 13, 7 }, { 51, 7 }, { 9, 6 }, + { 55, 6 }, { 17, 7 }, { 47, 7 }, { 31, 10 }, { 33, 10 }, + { 30, 10 }, { 34, 10 }, { 25, 9 }, { 39, 9 }, { 20, 8 }, + { 44, 8 }, { 5, 5 }, { 59, 5 }, { 16, 7 }, { 48, 7 }, + { 12, 7 }, { 52, 7 }, { 8, 6 }, { 56, 6 }, { 2, 4 }, + { 62, 4 }, { 4, 5 }, { 60, 5 }, { 24, 9 }, { 40, 9 }, + { 29, 10 }, { 35, 10 }, { 28, 10 }, { 36, 10 }, { 15, 8 }, + { 49, 8 }, { 11, 7 }, { 53, 7 }, { 7, 6 }, { 57, 6 }, + { 19, 8 }, { 45, 8 }, { 23, 9 }, { 41, 9 }, { 22, 9 }, + { 42, 9 }, { 10, 7 }, { 54, 7 }, { 6, 6 }, { 58, 6 }, + { 3, 5 }, { 61, 5 }, { 0, 3 }, + /* Coefficient table B.7.2 - 127 entries */ + { 3, 5 }, { 125, 5 }, { 42, 7 }, { 86, 7 }, { 21, 7 }, + { 107, 7 }, { 11, 6 }, { 117, 6 }, { 41, 7 }, { 87, 7 }, + { 20, 7 }, { 108, 7 }, { 53, 8 }, { 75, 8 }, { 31, 8 }, + { 97, 8 }, { 40, 7 }, { 88, 7 }, { 52, 8 }, { 76, 8 }, + { 51, 8 }, { 77, 8 }, { 19, 7 }, { 109, 7 }, { 10, 6 }, + { 118, 6 }, { 30, 8 }, { 98, 8 }, { 29, 8 }, { 99, 8 }, + { 18, 7 }, { 110, 7 }, { 9, 6 }, { 119, 6 }, { 39, 7 }, + { 89, 7 }, { 17, 7 }, { 111, 7 }, { 28, 8 }, { 100, 8 }, + { 50, 8 }, { 78, 8 }, { 38, 7 }, { 90, 7 }, { 2, 5 }, + { 126, 5 }, { 8, 6 }, { 120, 6 }, { 49, 8 }, { 79, 8 }, + { 48, 8 }, { 80, 8 }, { 16, 7 }, { 112, 7 }, { 37, 7 }, + { 91, 7 }, { 63, 9 }, { 65, 9 }, { 62, 9 }, { 66, 9 }, + { 27, 8 }, { 101, 8 }, { 7, 6 }, { 121, 6 }, { 36, 7 }, + { 92, 7 }, { 26, 8 }, { 102, 8 }, { 47, 8 }, { 81, 8 }, + { 61, 9 }, { 67, 9 }, { 60, 9 }, { 68, 9 }, { 46, 8 }, + { 82, 8 }, { 15, 7 }, { 113, 7 }, { 6, 6 }, { 122, 6 }, + { 25, 8 }, { 103, 8 }, { 45, 8 }, { 83, 8 }, { 35, 7 }, + { 93, 7 }, { 1, 5 }, { 127, 5 }, { 14, 7 }, { 114, 7 }, + { 59, 9 }, { 69, 9 }, { 58, 9 }, { 70, 9 }, { 24, 8 }, + { 104, 8 }, { 5, 6 }, { 123, 6 }, { 32, 7 }, { 96, 7 }, + { 34, 7 }, { 94, 7 }, { 13, 7 }, { 115, 7 }, { 23, 8 }, + { 105, 8 }, { 44, 8 }, { 84, 8 }, { 4, 6 }, { 124, 6 }, + { 57, 9 }, { 71, 9 }, { 56, 9 }, { 72, 9 }, { 43, 8 }, + { 85, 8 }, { 12, 7 }, { 116, 7 }, { 0, 5 }, { 33, 7 }, + { 95, 7 }, { 22, 8 }, { 106, 8 }, { 55, 9 }, { 73, 9 }, + { 54, 9 }, { 74, 9 }, + /* Coefficient table B.7.3 - 127 entries */ + { 0, 3 }, { 4, 5 }, { 124, 5 }, { 19, 7 }, { 109, 7 }, + { 29, 8 }, { 99, 8 }, { 51, 9 }, { 77, 9 }, { 62, 10 }, + { 66, 10 }, { 63, 10 }, { 65, 10 }, { 28, 8 }, { 100, 8 }, + { 41, 8 }, { 87, 8 }, { 33, 7 }, { 95, 7 }, { 10, 6 }, + { 118, 6 }, { 18, 7 }, { 110, 7 }, { 40, 8 }, { 88, 8 }, + { 27, 8 }, { 101, 8 }, { 9, 6 }, { 119, 6 }, { 17, 7 }, + { 111, 7 }, { 50, 9 }, { 78, 9 }, { 61, 10 }, { 67, 10 }, + { 60, 10 }, { 68, 10 }, { 26, 8 }, { 102, 8 }, { 1, 4 }, + { 127, 4 }, { 3, 5 }, { 125, 5 }, { 39, 8 }, { 89, 8 }, + { 49, 9 }, { 79, 9 }, { 48, 9 }, { 80, 9 }, { 16, 7 }, + { 112, 7 }, { 8, 6 }, { 120, 6 }, { 25, 8 }, { 103, 8 }, + { 38, 8 }, { 90, 8 }, { 15, 7 }, { 113, 7 }, { 7, 6 }, + { 121, 6 }, { 59, 10 }, { 69, 10 }, { 58, 10 }, { 70, 10 }, + { 47, 9 }, { 81, 9 }, { 24, 8 }, { 104, 8 }, { 37, 8 }, + { 91, 8 }, { 23, 8 }, { 105, 8 }, { 14, 7 }, { 114, 7 }, + { 46, 9 }, { 82, 9 }, { 57, 10 }, { 71, 10 }, { 56, 10 }, + { 72, 10 }, { 36, 8 }, { 92, 8 }, { 2, 5 }, { 126, 5 }, + { 6, 6 }, { 122, 6 }, { 45, 9 }, { 83, 9 }, { 31, 9 }, + { 97, 9 }, { 22, 8 }, { 106, 8 }, { 13, 7 }, { 115, 7 }, + { 21, 8 }, { 107, 8 }, { 55, 10 }, { 73, 10 }, { 54, 10 }, + { 74, 10 }, { 44, 9 }, { 84, 9 }, { 12, 7 }, { 116, 7 }, + { 5, 6 }, { 123, 6 }, { 35, 8 }, { 93, 8 }, { 43, 9 }, + { 85, 9 }, { 30, 9 }, { 98, 9 }, { 20, 8 }, { 108, 8 }, + { 53, 10 }, { 75, 10 }, { 52, 10 }, { 76, 10 }, { 42, 9 }, + { 86, 9 }, { 34, 8 }, { 94, 8 }, { 32, 8 }, { 96, 8 }, + { 11, 7 }, { 117, 7 }, + /* Coefficient table B.7.4 - 127 entries */ + { 28, 8 }, { 100, 8 }, { 27, 8 }, { 101, 8 }, { 36, 8 }, + { 92, 8 }, { 63, 10 }, { 65, 10 }, { 61, 10 }, { 67, 10 }, + { 62, 10 }, { 66, 10 }, { 60, 10 }, { 68, 10 }, { 19, 7 }, + { 109, 7 }, { 59, 10 }, { 69, 10 }, { 58, 10 }, { 70, 10 }, + { 57, 10 }, { 71, 10 }, { 56, 10 }, { 72, 10 }, { 55, 10 }, + { 73, 10 }, { 53, 10 }, { 75, 10 }, { 54, 10 }, { 74, 10 }, + { 52, 10 }, { 76, 10 }, { 5, 5 }, { 123, 5 }, { 0, 3 }, + { 51, 10 }, { 77, 10 }, { 50, 10 }, { 78, 10 }, { 49, 10 }, + { 79, 10 }, { 48, 10 }, { 80, 10 }, { 47, 10 }, { 81, 10 }, + { 46, 10 }, { 82, 10 }, { 43, 9 }, { 85, 9 }, { 18, 7 }, + { 110, 7 }, { 11, 6 }, { 117, 6 }, { 26, 8 }, { 102, 8 }, + { 35, 8 }, { 93, 8 }, { 25, 8 }, { 103, 8 }, { 42, 9 }, + { 86, 9 }, { 41, 9 }, { 87, 9 }, { 10, 6 }, { 118, 6 }, + { 4, 5 }, { 124, 5 }, { 17, 7 }, { 111, 7 }, { 34, 8 }, + { 94, 8 }, { 24, 8 }, { 104, 8 }, { 9, 6 }, { 119, 6 }, + { 1, 4 }, { 127, 4 }, { 16, 7 }, { 112, 7 }, { 32, 8 }, + { 96, 8 }, { 33, 8 }, { 95, 8 }, { 23, 8 }, { 105, 8 }, + { 40, 9 }, { 88, 9 }, { 31, 9 }, { 97, 9 }, { 15, 7 }, + { 113, 7 }, { 8, 6 }, { 120, 6 }, { 39, 9 }, { 89, 9 }, + { 45, 10 }, { 83, 10 }, { 44, 10 }, { 84, 10 }, { 22, 8 }, + { 106, 8 }, { 14, 7 }, { 114, 7 }, { 3, 5 }, { 125, 5 }, + { 7, 6 }, { 121, 6 }, { 30, 9 }, { 98, 9 }, { 38, 9 }, + { 90, 9 }, { 21, 8 }, { 107, 8 }, { 13, 7 }, { 115, 7 }, + { 29, 9 }, { 99, 9 }, { 37, 9 }, { 91, 9 }, { 20, 8 }, + { 108, 8 }, { 12, 7 }, { 116, 7 }, { 6, 6 }, { 122, 6 }, + { 2, 5 }, { 126, 5 }, }; static const HuffmanCodebook at9_huffman_coeffs[][8][4] = { @@ -1552,40 +1295,40 @@ { { 0 } }, { { 0 } }, { - { huff_spec_a21_bits, huff_spec_a21_codes, 16, 2, 1, 2, 3, }, - { huff_spec_a22_bits, huff_spec_a22_codes, 256, 4, 2, 2, 8, }, - { huff_spec_a23_bits, huff_spec_a23_codes, 256, 4, 2, 2, 9, }, - { huff_spec_a24_bits, huff_spec_a24_codes, 256, 4, 2, 2, 10, }, + { 8, 2, 1, 2 }, + { 80, 4, 2, 2 }, + { 81, 4, 2, 2 }, + { 81, 4, 2, 2 }, }, { - { huff_spec_a31_bits, huff_spec_a31_codes, 64, 2, 1, 3, 7, }, - { huff_spec_a32_bits, huff_spec_a32_codes, 64, 2, 1, 3, 7, }, - { huff_spec_a33_bits, huff_spec_a33_codes, 64, 2, 1, 3, 8, }, - { huff_spec_a34_bits, huff_spec_a34_codes, 64, 2, 1, 3, 10, }, + { 40, 2, 1, 3 }, + { 49, 2, 1, 3 }, + { 49, 2, 1, 3 }, + { 49, 2, 1, 3 }, }, { - { huff_spec_a41_bits, huff_spec_a41_codes, 256, 2, 1, 4, 9, }, - { huff_spec_a42_bits, huff_spec_a42_codes, 256, 2, 1, 4, 10, }, - { huff_spec_a43_bits, huff_spec_a43_codes, 256, 2, 1, 4, 10, }, - { huff_spec_a44_bits, huff_spec_a44_codes, 256, 2, 1, 4, 10, }, + { 176, 2, 1, 4 }, + { 225, 2, 1, 4 }, + { 225, 2, 1, 4 }, + { 225, 2, 1, 4 }, }, { - { huff_spec_a51_bits, huff_spec_a51_codes, 32, 1, 0, 5, 6, }, - { huff_spec_a52_bits, huff_spec_a52_codes, 32, 1, 0, 5, 6, }, - { huff_spec_a53_bits, huff_spec_a53_codes, 32, 1, 0, 5, 7, }, - { huff_spec_a54_bits, huff_spec_a54_codes, 32, 1, 0, 5, 8, }, + { 31, 1, 0, 5 }, + { 31, 1, 0, 5 }, + { 31, 1, 0, 5 }, + { 31, 1, 0, 5 }, }, { - { huff_spec_a61_bits, huff_spec_a61_codes, 64, 1, 0, 6, 7, }, - { huff_spec_a62_bits, huff_spec_a62_codes, 64, 1, 0, 6, 7, }, - { huff_spec_a63_bits, huff_spec_a63_codes, 64, 1, 0, 6, 8, }, - { huff_spec_a64_bits, huff_spec_a64_codes, 64, 1, 0, 6, 9, }, + { 63, 1, 0, 6 }, + { 63, 1, 0, 6 }, + { 63, 1, 0, 6 }, + { 63, 1, 0, 6 }, }, { - { huff_spec_a71_bits, huff_spec_a71_codes, 128, 1, 0, 7, 8, }, - { huff_spec_a72_bits, huff_spec_a72_codes, 128, 1, 0, 7, 8, }, - { huff_spec_a73_bits, huff_spec_a73_codes, 128, 1, 0, 7, 9, }, - { huff_spec_a74_bits, huff_spec_a74_codes, 128, 1, 0, 7, 10, }, + { 127, 1, 0, 7 }, + { 127, 1, 0, 7 }, + { 127, 1, 0, 7 }, + { 127, 1, 0, 7 }, }, }, { @@ -1593,39 +1336,39 @@ { { 0 } }, { { 0 }, - { huff_spec_b22_bits, huff_spec_b22_codes, 256, 4, 2, 2, 10, }, - { huff_spec_b23_bits, huff_spec_b23_codes, 256, 4, 2, 2, 10, }, - { huff_spec_b24_bits, huff_spec_b24_codes, 256, 4, 2, 2, 10, }, + { 80, 4, 2, 2 }, + { 81, 4, 2, 2 }, + { 81, 4, 2, 2 }, }, { { 0 }, - { huff_spec_b32_bits, huff_spec_b32_codes, 64, 2, 1, 3, 9, }, - { huff_spec_b33_bits, huff_spec_b33_codes, 64, 2, 1, 3, 10, }, - { huff_spec_b34_bits, huff_spec_b34_codes, 64, 2, 1, 3, 10, }, + { 49, 2, 1, 3 }, + { 49, 2, 1, 3 }, + { 49, 2, 1, 3 }, }, { { 0 }, - { huff_spec_b42_bits, huff_spec_b42_codes, 256, 2, 1, 4, 10, }, - { huff_spec_b43_bits, huff_spec_b43_codes, 256, 2, 1, 4, 10, }, - { huff_spec_b44_bits, huff_spec_b44_codes, 256, 2, 1, 4, 10, }, + { 225, 2, 1, 4 }, + { 225, 2, 1, 4 }, + { 225, 2, 1, 4 }, }, { { 0 }, - { huff_spec_b52_bits, huff_spec_b52_codes, 32, 1, 0, 5, 7, }, - { huff_spec_b53_bits, huff_spec_b53_codes, 32, 1, 0, 5, 8, }, - { huff_spec_b54_bits, huff_spec_b54_codes, 32, 1, 0, 5, 9, }, + { 31, 1, 0, 5 }, + { 31, 1, 0, 5 }, + { 31, 1, 0, 5 }, }, { { 0 }, - { huff_spec_b62_bits, huff_spec_b62_codes, 64, 1, 0, 6, 8, }, - { huff_spec_b63_bits, huff_spec_b63_codes, 64, 1, 0, 6, 9, }, - { huff_spec_b64_bits, huff_spec_b64_codes, 64, 1, 0, 6, 10, }, + { 63, 1, 0, 6 }, + { 63, 1, 0, 6 }, + { 63, 1, 0, 6 }, }, { { 0 }, - { huff_spec_b72_bits, huff_spec_b72_codes, 128, 1, 0, 7, 9, }, - { huff_spec_b73_bits, huff_spec_b73_codes, 128, 1, 0, 7, 10, }, - { huff_spec_b74_bits, huff_spec_b74_codes, 128, 1, 0, 7, 10, }, + { 127, 1, 0, 7 }, + { 127, 1, 0, 7 }, + { 127, 1, 0, 7 }, }, }, }; diff -Nru ffmpeg-4.2.2/libavcodec/atrac.c ffmpeg-4.4/libavcodec/atrac.c --- ffmpeg-4.2.2/libavcodec/atrac.c 2016-03-29 02:25:11.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atrac.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,8 @@ #include #include +#include "libavutil/thread.h" + #include "avcodec.h" #include "atrac.h" @@ -45,22 +47,23 @@ -0.043596379, -0.099384367, 0.13207909, 0.46424159 }; -av_cold void ff_atrac_generate_tables(void) +static av_cold void atrac_generate_tables(void) { - int i; - float s; - /* Generate scale factors */ - if (!ff_atrac_sf_table[63]) - for (i=0 ; i<64 ; i++) - ff_atrac_sf_table[i] = pow(2.0, (i - 15) / 3.0); + for (int i = 0; i < 64; i++) + ff_atrac_sf_table[i] = pow(2.0, (i - 15) / 3.0); /* Generate the QMF window. */ - if (!qmf_window[47]) - for (i=0 ; i<24; i++) { - s = qmf_48tap_half[i] * 2.0; - qmf_window[i] = qmf_window[47 - i] = s; - } + for (int i = 0; i < 24; i++) { + float s = qmf_48tap_half[i] * 2.0; + qmf_window[i] = qmf_window[47 - i] = s; + } +} + +av_cold void ff_atrac_generate_tables(void) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, atrac_generate_tables); } av_cold void ff_atrac_init_gain_compensation(AtracGCContext *gctx, int id2exp_offset, diff -Nru ffmpeg-4.2.2/libavcodec/atsc_a53.c ffmpeg-4.4/libavcodec/atsc_a53.c --- ffmpeg-4.2.2/libavcodec/atsc_a53.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atsc_a53.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,119 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "atsc_a53.h" +#include "get_bits.h" + +int ff_alloc_a53_sei(const AVFrame *frame, size_t prefix_len, + void **data, size_t *sei_size) +{ + AVFrameSideData *side_data = NULL; + uint8_t *sei_data; + + if (frame) + side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC); + + if (!side_data) { + *data = NULL; + return 0; + } + + *sei_size = side_data->size + 11; + *data = av_mallocz(*sei_size + prefix_len); + if (!*data) + return AVERROR(ENOMEM); + sei_data = (uint8_t*)*data + prefix_len; + + // country code + sei_data[0] = 181; + sei_data[1] = 0; + sei_data[2] = 49; + + /** + * 'GA94' is standard in North America for ATSC, but hard coding + * this style may not be the right thing to do -- other formats + * do exist. This information is not available in the side_data + * so we are going with this right now. + */ + AV_WL32(sei_data + 3, MKTAG('G', 'A', '9', '4')); + sei_data[7] = 3; + sei_data[8] = ((side_data->size/3) & 0x1f) | 0x40; + sei_data[9] = 0; + + memcpy(sei_data + 10, side_data->data, side_data->size); + + sei_data[side_data->size+10] = 255; + + return 0; +} + +int ff_parse_a53_cc(AVBufferRef **pbuf, const uint8_t *data, int size) +{ + AVBufferRef *buf = *pbuf; + GetBitContext gb; + size_t new_size, old_size = buf ? buf->size : 0; + int ret, cc_count; + + if (size < 3) + return AVERROR(EINVAL); + + ret = init_get_bits8(&gb, data, size); + if (ret < 0) + return ret; + + if (get_bits(&gb, 8) != 0x3) // user_data_type_code + return 0; + + skip_bits(&gb, 1); // reserved + if (!get_bits(&gb, 1)) // process_cc_data_flag + return 0; + + skip_bits(&gb, 1); // zero bit + cc_count = get_bits(&gb, 5); + if (!cc_count) + return 0; + + skip_bits(&gb, 8); // reserved + + /* 3 bytes per CC plus one byte marker_bits at the end */ + if (cc_count * 3 >= (get_bits_left(&gb) >> 3)) + return AVERROR(EINVAL); + + new_size = (old_size + cc_count * 3); + + if (new_size > INT_MAX) + return AVERROR(EINVAL); + + /* Allow merging of the cc data from two fields. */ + ret = av_buffer_realloc(pbuf, new_size); + if (ret < 0) + return ret; + + buf = *pbuf; + /* Use of av_buffer_realloc assumes buffer is writeable */ + for (int i = 0; i < cc_count; i++) { + buf->data[old_size++] = get_bits(&gb, 8); + buf->data[old_size++] = get_bits(&gb, 8); + buf->data[old_size++] = get_bits(&gb, 8); + } + + return cc_count; +} diff -Nru ffmpeg-4.2.2/libavcodec/atsc_a53.h ffmpeg-4.4/libavcodec/atsc_a53.h --- ffmpeg-4.2.2/libavcodec/atsc_a53.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/atsc_a53.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,56 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_ATSC_A53_H +#define AVCODEC_ATSC_A53_H + +#include +#include + +#include "libavutil/buffer.h" +#include "libavutil/frame.h" + +/** + * Check AVFrame for A53 side data and allocate and fill SEI message with A53 info + * + * @param frame Raw frame to get A53 side data from + * @param prefix_len Number of bytes to allocate before SEI message + * @param data Pointer to a variable to store allocated memory + * Upon return the variable will hold NULL on error or if frame has no A53 info. + * Otherwise it will point to prefix_len uninitialized bytes followed by + * *sei_size SEI message + * @param sei_size Pointer to a variable to store generated SEI message length + * @return Zero on success, negative error code on failure + */ +int ff_alloc_a53_sei(const AVFrame *frame, size_t prefix_len, + void **data, size_t *sei_size); + +/** + * Parse a data array for ATSC A53 Part 4 Closed Captions and store them in an AVBufferRef. + * + * @param pbuf Pointer to an AVBufferRef to append the closed captions. *pbuf may be NULL, in + * which case a new buffer will be allocated and put in it. + * @param data The data array containing the raw A53 data. + * @param size Size of the data array in bytes. + * + * @return Number of closed captions parsed on success, negative error code on failure. + * If no Closed Captions are parsed, *pbuf is untouched. + */ +int ff_parse_a53_cc(AVBufferRef **pbuf, const uint8_t *data, int size); + +#endif /* AVCODEC_ATSC_A53_H */ diff -Nru ffmpeg-4.2.2/libavcodec/audiodsp.c ffmpeg-4.4/libavcodec/audiodsp.c --- ffmpeg-4.2.2/libavcodec/audiodsp.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/audiodsp.c 2020-07-09 09:17:46.000000000 +0000 @@ -79,7 +79,7 @@ static int32_t scalarproduct_int16_c(const int16_t *v1, const int16_t *v2, int order) { - int res = 0; + unsigned res = 0; while (order--) res += *v1++ **v2++; diff -Nru ffmpeg-4.2.2/libavcodec/audiotoolboxdec.c ffmpeg-4.4/libavcodec/audiotoolboxdec.c --- ffmpeg-4.2.2/libavcodec/audiotoolboxdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/audiotoolboxdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -1,7 +1,7 @@ /* * Audio Toolbox system codecs * - * copyright (c) 2016 Rodger Combs + * copyright (c) 2016 rcombs * * This file is part of FFmpeg. * @@ -296,7 +296,8 @@ return 0; } -static av_cold int ffat_create_decoder(AVCodecContext *avctx, AVPacket *pkt) +static av_cold int ffat_create_decoder(AVCodecContext *avctx, + const AVPacket *pkt) { ATDecodeContext *at = avctx->priv_data; OSStatus status; @@ -483,7 +484,7 @@ if (avctx->codec_id == AV_CODEC_ID_AAC) { if (!at->extradata_size) { uint8_t *side_data; - int side_data_size = 0; + buffer_size_t side_data_size; side_data = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &side_data_size); @@ -595,7 +596,7 @@ .flush = ffat_decode_flush, \ .priv_class = &ffat_##NAME##_dec_class, \ .bsfs = bsf_name, \ - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, \ + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF, \ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, \ .wrapper_name = "at", \ }; diff -Nru ffmpeg-4.2.2/libavcodec/audiotoolboxenc.c ffmpeg-4.4/libavcodec/audiotoolboxenc.c --- ffmpeg-4.2.2/libavcodec/audiotoolboxenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/audiotoolboxenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -1,7 +1,7 @@ /* * Audio Toolbox system codecs * - * copyright (c) 2016 Rodger Combs + * copyright (c) 2016 rcombs * * This file is part of FFmpeg. * @@ -627,7 +627,8 @@ .encode2 = ffat_encode, \ .flush = ffat_encode_flush, \ .priv_class = &ffat_##NAME##_enc_class, \ - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY __VA_ARGS__, \ + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | \ + AV_CODEC_CAP_ENCODER_FLUSH __VA_ARGS__, \ .sample_fmts = (const enum AVSampleFormat[]) { \ AV_SAMPLE_FMT_S16, \ AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NONE \ @@ -655,7 +656,7 @@ FFAT_ENC(aac, AV_CODEC_ID_AAC, aac_profiles, , .channel_layouts = aac_at_channel_layouts) //FFAT_ENC(adpcm_ima_qt, AV_CODEC_ID_ADPCM_IMA_QT, NULL) -FFAT_ENC(alac, AV_CODEC_ID_ALAC, NULL, | AV_CODEC_CAP_VARIABLE_FRAME_SIZE | AV_CODEC_CAP_LOSSLESS) +FFAT_ENC(alac, AV_CODEC_ID_ALAC, NULL, | AV_CODEC_CAP_VARIABLE_FRAME_SIZE) FFAT_ENC(ilbc, AV_CODEC_ID_ILBC, NULL) FFAT_ENC(pcm_alaw, AV_CODEC_ID_PCM_ALAW, NULL) FFAT_ENC(pcm_mulaw, AV_CODEC_ID_PCM_MULAW, NULL) diff -Nru ffmpeg-4.2.2/libavcodec/av1dec.c ffmpeg-4.4/libavcodec/av1dec.c --- ffmpeg-4.2.2/libavcodec/av1dec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/av1dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,1158 @@ +/* + * AV1 video decoder + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/film_grain_params.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "av1dec.h" +#include "bytestream.h" +#include "hwconfig.h" +#include "internal.h" +#include "profiles.h" + +static uint32_t inverse_recenter(int r, uint32_t v) +{ + if (v > 2 * r) + return v; + else if (v & 1) + return r - ((v + 1) >> 1); + else + return r + (v >> 1); +} + +static uint32_t decode_unsigned_subexp_with_ref(uint32_t sub_exp, + int mx, int r) +{ + if ((r << 1) <= mx) { + return inverse_recenter(r, sub_exp); + } else { + return mx - 1 - inverse_recenter(mx - 1 - r, sub_exp); + } +} + +static int32_t decode_signed_subexp_with_ref(uint32_t sub_exp, int low, + int high, int r) +{ + int32_t x = decode_unsigned_subexp_with_ref(sub_exp, high - low, r - low); + return x + low; +} + +static void read_global_param(AV1DecContext *s, int type, int ref, int idx) +{ + uint8_t primary_frame, prev_frame; + uint32_t abs_bits, prec_bits, round, prec_diff, sub, mx; + int32_t r, prev_gm_param; + + primary_frame = s->raw_frame_header->primary_ref_frame; + prev_frame = s->raw_frame_header->ref_frame_idx[primary_frame]; + abs_bits = AV1_GM_ABS_ALPHA_BITS; + prec_bits = AV1_GM_ALPHA_PREC_BITS; + + /* setup_past_independence() sets PrevGmParams to default values. We can + * simply point to the current's frame gm_params as they will be initialized + * with defaults at this point. + */ + if (s->raw_frame_header->primary_ref_frame == AV1_PRIMARY_REF_NONE) + prev_gm_param = s->cur_frame.gm_params[ref][idx]; + else + prev_gm_param = s->ref[prev_frame].gm_params[ref][idx]; + + if (idx < 2) { + if (type == AV1_WARP_MODEL_TRANSLATION) { + abs_bits = AV1_GM_ABS_TRANS_ONLY_BITS - + !s->raw_frame_header->allow_high_precision_mv; + prec_bits = AV1_GM_TRANS_ONLY_PREC_BITS - + !s->raw_frame_header->allow_high_precision_mv; + } else { + abs_bits = AV1_GM_ABS_TRANS_BITS; + prec_bits = AV1_GM_TRANS_PREC_BITS; + } + } + round = (idx % 3) == 2 ? (1 << AV1_WARPEDMODEL_PREC_BITS) : 0; + prec_diff = AV1_WARPEDMODEL_PREC_BITS - prec_bits; + sub = (idx % 3) == 2 ? (1 << prec_bits) : 0; + mx = 1 << abs_bits; + r = (prev_gm_param >> prec_diff) - sub; + + s->cur_frame.gm_params[ref][idx] = + (decode_signed_subexp_with_ref(s->raw_frame_header->gm_params[ref][idx], + -mx, mx + 1, r) << prec_diff) + round; +} + +/** +* update gm type/params, since cbs already implemented part of this funcation, +* so we don't need to full implement spec. +*/ +static void global_motion_params(AV1DecContext *s) +{ + const AV1RawFrameHeader *header = s->raw_frame_header; + int type, ref; + + for (ref = AV1_REF_FRAME_LAST; ref <= AV1_REF_FRAME_ALTREF; ref++) { + s->cur_frame.gm_type[ref] = AV1_WARP_MODEL_IDENTITY; + for (int i = 0; i < 6; i++) + s->cur_frame.gm_params[ref][i] = (i % 3 == 2) ? + 1 << AV1_WARPEDMODEL_PREC_BITS : 0; + } + if (header->frame_type == AV1_FRAME_KEY || + header->frame_type == AV1_FRAME_INTRA_ONLY) + return; + + for (ref = AV1_REF_FRAME_LAST; ref <= AV1_REF_FRAME_ALTREF; ref++) { + if (header->is_global[ref]) { + if (header->is_rot_zoom[ref]) { + type = AV1_WARP_MODEL_ROTZOOM; + } else { + type = header->is_translation[ref] ? AV1_WARP_MODEL_TRANSLATION + : AV1_WARP_MODEL_AFFINE; + } + } else { + type = AV1_WARP_MODEL_IDENTITY; + } + s->cur_frame.gm_type[ref] = type; + + if (type >= AV1_WARP_MODEL_ROTZOOM) { + read_global_param(s, type, ref, 2); + read_global_param(s, type, ref, 3); + if (type == AV1_WARP_MODEL_AFFINE) { + read_global_param(s, type, ref, 4); + read_global_param(s, type, ref, 5); + } else { + s->cur_frame.gm_params[ref][4] = -s->cur_frame.gm_params[ref][3]; + s->cur_frame.gm_params[ref][5] = s->cur_frame.gm_params[ref][2]; + } + } + if (type >= AV1_WARP_MODEL_TRANSLATION) { + read_global_param(s, type, ref, 0); + read_global_param(s, type, ref, 1); + } + } +} + +static int get_relative_dist(const AV1RawSequenceHeader *seq, + unsigned int a, unsigned int b) +{ + unsigned int diff = a - b; + unsigned int m = 1 << seq->order_hint_bits_minus_1; + return (diff & (m - 1)) - (diff & m); +} + +static void skip_mode_params(AV1DecContext *s) +{ + const AV1RawFrameHeader *header = s->raw_frame_header; + const AV1RawSequenceHeader *seq = s->raw_seq; + + int forward_idx, backward_idx; + int forward_hint, backward_hint; + int second_forward_idx, second_forward_hint; + int ref_hint, dist, i; + + if (!header->skip_mode_present) + return; + + forward_idx = -1; + backward_idx = -1; + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + ref_hint = s->ref[header->ref_frame_idx[i]].raw_frame_header->order_hint; + dist = get_relative_dist(seq, ref_hint, header->order_hint); + if (dist < 0) { + if (forward_idx < 0 || + get_relative_dist(seq, ref_hint, forward_hint) > 0) { + forward_idx = i; + forward_hint = ref_hint; + } + } else if (dist > 0) { + if (backward_idx < 0 || + get_relative_dist(seq, ref_hint, backward_hint) < 0) { + backward_idx = i; + backward_hint = ref_hint; + } + } + } + + if (forward_idx < 0) { + return; + } else if (backward_idx >= 0) { + s->cur_frame.skip_mode_frame_idx[0] = + AV1_REF_FRAME_LAST + FFMIN(forward_idx, backward_idx); + s->cur_frame.skip_mode_frame_idx[1] = + AV1_REF_FRAME_LAST + FFMAX(forward_idx, backward_idx); + return; + } + + second_forward_idx = -1; + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + ref_hint = s->ref[header->ref_frame_idx[i]].raw_frame_header->order_hint; + if (get_relative_dist(seq, ref_hint, forward_hint) < 0) { + if (second_forward_idx < 0 || + get_relative_dist(seq, ref_hint, second_forward_hint) > 0) { + second_forward_idx = i; + second_forward_hint = ref_hint; + } + } + } + + if (second_forward_idx < 0) + return; + + s->cur_frame.skip_mode_frame_idx[0] = + AV1_REF_FRAME_LAST + FFMIN(forward_idx, second_forward_idx); + s->cur_frame.skip_mode_frame_idx[1] = + AV1_REF_FRAME_LAST + FFMAX(forward_idx, second_forward_idx); +} + +static void coded_lossless_param(AV1DecContext *s) +{ + const AV1RawFrameHeader *header = s->raw_frame_header; + int i; + + if (header->delta_q_y_dc || header->delta_q_u_ac || + header->delta_q_u_dc || header->delta_q_v_ac || + header->delta_q_v_dc) { + s->cur_frame.coded_lossless = 0; + return; + } + + s->cur_frame.coded_lossless = 1; + for (i = 0; i < AV1_MAX_SEGMENTS; i++) { + int qindex; + if (header->feature_enabled[i][AV1_SEG_LVL_ALT_Q]) { + qindex = (header->base_q_idx + + header->feature_value[i][AV1_SEG_LVL_ALT_Q]); + } else { + qindex = header->base_q_idx; + } + qindex = av_clip_uintp2(qindex, 8); + + if (qindex) { + s->cur_frame.coded_lossless = 0; + return; + } + } +} + +static void load_grain_params(AV1DecContext *s) +{ + const AV1RawFrameHeader *header = s->raw_frame_header; + const AV1RawFilmGrainParams *film_grain = &header->film_grain, *src; + AV1RawFilmGrainParams *dst = &s->cur_frame.film_grain; + + if (!film_grain->apply_grain) + return; + + if (film_grain->update_grain) { + memcpy(dst, film_grain, sizeof(*dst)); + return; + } + + src = &s->ref[film_grain->film_grain_params_ref_idx].film_grain; + + memcpy(dst, src, sizeof(*dst)); + dst->grain_seed = film_grain->grain_seed; +} + +static int init_tile_data(AV1DecContext *s) + +{ + int cur_tile_num = + s->raw_frame_header->tile_cols * s->raw_frame_header->tile_rows; + if (s->tile_num < cur_tile_num) { + int ret = av_reallocp_array(&s->tile_group_info, cur_tile_num, + sizeof(TileGroupInfo)); + if (ret < 0) { + s->tile_num = 0; + return ret; + } + } + s->tile_num = cur_tile_num; + + return 0; +} + +static int get_tiles_info(AVCodecContext *avctx, const AV1RawTileGroup *tile_group) +{ + AV1DecContext *s = avctx->priv_data; + GetByteContext gb; + uint16_t tile_num, tile_row, tile_col; + uint32_t size = 0, size_bytes = 0; + + bytestream2_init(&gb, tile_group->tile_data.data, + tile_group->tile_data.data_size); + s->tg_start = tile_group->tg_start; + s->tg_end = tile_group->tg_end; + + for (tile_num = tile_group->tg_start; tile_num <= tile_group->tg_end; tile_num++) { + tile_row = tile_num / s->raw_frame_header->tile_cols; + tile_col = tile_num % s->raw_frame_header->tile_cols; + + if (tile_num == tile_group->tg_end) { + s->tile_group_info[tile_num].tile_size = bytestream2_get_bytes_left(&gb); + s->tile_group_info[tile_num].tile_offset = bytestream2_tell(&gb); + s->tile_group_info[tile_num].tile_row = tile_row; + s->tile_group_info[tile_num].tile_column = tile_col; + return 0; + } + size_bytes = s->raw_frame_header->tile_size_bytes_minus1 + 1; + if (bytestream2_get_bytes_left(&gb) < size_bytes) + return AVERROR_INVALIDDATA; + size = 0; + for (int i = 0; i < size_bytes; i++) + size |= bytestream2_get_byteu(&gb) << 8 * i; + if (bytestream2_get_bytes_left(&gb) <= size) + return AVERROR_INVALIDDATA; + size++; + + s->tile_group_info[tile_num].tile_size = size; + s->tile_group_info[tile_num].tile_offset = bytestream2_tell(&gb); + s->tile_group_info[tile_num].tile_row = tile_row; + s->tile_group_info[tile_num].tile_column = tile_col; + + bytestream2_skipu(&gb, size); + } + + return 0; + +} + +static int get_pixel_format(AVCodecContext *avctx) +{ + AV1DecContext *s = avctx->priv_data; + const AV1RawSequenceHeader *seq = s->raw_seq; + uint8_t bit_depth; + int ret; + enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE; +#define HWACCEL_MAX (CONFIG_AV1_DXVA2_HWACCEL + \ + CONFIG_AV1_D3D11VA_HWACCEL * 2 + \ + CONFIG_AV1_NVDEC_HWACCEL + \ + CONFIG_AV1_VAAPI_HWACCEL) + enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; + + if (seq->seq_profile == 2 && seq->color_config.high_bitdepth) + bit_depth = seq->color_config.twelve_bit ? 12 : 10; + else if (seq->seq_profile <= 2) + bit_depth = seq->color_config.high_bitdepth ? 10 : 8; + else { + av_log(avctx, AV_LOG_ERROR, + "Unknown AV1 profile %d.\n", seq->seq_profile); + return -1; + } + + if (!seq->color_config.mono_chrome) { + // 4:4:4 x:0 y:0, 4:2:2 x:1 y:0, 4:2:0 x:1 y:1 + if (seq->color_config.subsampling_x == 0 && + seq->color_config.subsampling_y == 0) { + if (bit_depth == 8) + pix_fmt = AV_PIX_FMT_YUV444P; + else if (bit_depth == 10) + pix_fmt = AV_PIX_FMT_YUV444P10; + else if (bit_depth == 12) + pix_fmt = AV_PIX_FMT_YUV444P12; + else + av_log(avctx, AV_LOG_WARNING, "Unknown AV1 pixel format.\n"); + } else if (seq->color_config.subsampling_x == 1 && + seq->color_config.subsampling_y == 0) { + if (bit_depth == 8) + pix_fmt = AV_PIX_FMT_YUV422P; + else if (bit_depth == 10) + pix_fmt = AV_PIX_FMT_YUV422P10; + else if (bit_depth == 12) + pix_fmt = AV_PIX_FMT_YUV422P12; + else + av_log(avctx, AV_LOG_WARNING, "Unknown AV1 pixel format.\n"); + } else if (seq->color_config.subsampling_x == 1 && + seq->color_config.subsampling_y == 1) { + if (bit_depth == 8) + pix_fmt = AV_PIX_FMT_YUV420P; + else if (bit_depth == 10) + pix_fmt = AV_PIX_FMT_YUV420P10; + else if (bit_depth == 12) + pix_fmt = AV_PIX_FMT_YUV420P12; + else + av_log(avctx, AV_LOG_WARNING, "Unknown AV1 pixel format.\n"); + } + } else { + if (bit_depth == 8) + pix_fmt = AV_PIX_FMT_GRAY8; + else if (bit_depth == 10) + pix_fmt = AV_PIX_FMT_GRAY10; + else if (bit_depth == 12) + pix_fmt = AV_PIX_FMT_GRAY12; + else + av_log(avctx, AV_LOG_WARNING, "Unknown AV1 pixel format.\n"); + } + + av_log(avctx, AV_LOG_DEBUG, "AV1 decode get format: %s.\n", + av_get_pix_fmt_name(pix_fmt)); + + if (pix_fmt == AV_PIX_FMT_NONE) + return -1; + s->pix_fmt = pix_fmt; + + switch (s->pix_fmt) { + case AV_PIX_FMT_YUV420P: +#if CONFIG_AV1_DXVA2_HWACCEL + *fmtp++ = AV_PIX_FMT_DXVA2_VLD; +#endif +#if CONFIG_AV1_D3D11VA_HWACCEL + *fmtp++ = AV_PIX_FMT_D3D11VA_VLD; + *fmtp++ = AV_PIX_FMT_D3D11; +#endif +#if CONFIG_AV1_NVDEC_HWACCEL + *fmtp++ = AV_PIX_FMT_CUDA; +#endif +#if CONFIG_AV1_VAAPI_HWACCEL + *fmtp++ = AV_PIX_FMT_VAAPI; +#endif + break; + case AV_PIX_FMT_YUV420P10: +#if CONFIG_AV1_DXVA2_HWACCEL + *fmtp++ = AV_PIX_FMT_DXVA2_VLD; +#endif +#if CONFIG_AV1_D3D11VA_HWACCEL + *fmtp++ = AV_PIX_FMT_D3D11VA_VLD; + *fmtp++ = AV_PIX_FMT_D3D11; +#endif +#if CONFIG_AV1_NVDEC_HWACCEL + *fmtp++ = AV_PIX_FMT_CUDA; +#endif +#if CONFIG_AV1_VAAPI_HWACCEL + *fmtp++ = AV_PIX_FMT_VAAPI; +#endif + break; + case AV_PIX_FMT_GRAY8: +#if CONFIG_AV1_NVDEC_HWACCEL + *fmtp++ = AV_PIX_FMT_CUDA; +#endif + break; + case AV_PIX_FMT_GRAY10: +#if CONFIG_AV1_NVDEC_HWACCEL + *fmtp++ = AV_PIX_FMT_CUDA; +#endif + break; + } + + *fmtp++ = s->pix_fmt; + *fmtp = AV_PIX_FMT_NONE; + + ret = ff_thread_get_format(avctx, pix_fmts); + if (ret < 0) + return ret; + + /** + * check if the HW accel is inited correctly. If not, return un-implemented. + * Since now the av1 decoder doesn't support native decode, if it will be + * implemented in the future, need remove this check. + */ + if (!avctx->hwaccel) { + av_log(avctx, AV_LOG_ERROR, "Your platform doesn't suppport" + " hardware accelerated AV1 decoding.\n"); + return AVERROR(ENOSYS); + } + + avctx->pix_fmt = ret; + + return 0; +} + +static void av1_frame_unref(AVCodecContext *avctx, AV1Frame *f) +{ + ff_thread_release_buffer(avctx, &f->tf); + av_buffer_unref(&f->hwaccel_priv_buf); + f->hwaccel_picture_private = NULL; + av_buffer_unref(&f->header_ref); + f->raw_frame_header = NULL; + f->spatial_id = f->temporal_id = 0; + memset(f->skip_mode_frame_idx, 0, + 2 * sizeof(uint8_t)); + memset(&f->film_grain, 0, sizeof(f->film_grain)); + f->coded_lossless = 0; +} + +static int av1_frame_ref(AVCodecContext *avctx, AV1Frame *dst, const AV1Frame *src) +{ + int ret; + + ret = ff_thread_ref_frame(&dst->tf, &src->tf); + 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->hwaccel_picture_private) { + dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); + if (!dst->hwaccel_priv_buf) + goto fail; + dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; + } + + dst->spatial_id = src->spatial_id; + dst->temporal_id = src->temporal_id; + memcpy(dst->gm_type, + src->gm_type, + AV1_NUM_REF_FRAMES * sizeof(uint8_t)); + memcpy(dst->gm_params, + src->gm_params, + AV1_NUM_REF_FRAMES * 6 * sizeof(int32_t)); + memcpy(dst->skip_mode_frame_idx, + src->skip_mode_frame_idx, + 2 * sizeof(uint8_t)); + memcpy(&dst->film_grain, + &src->film_grain, + sizeof(dst->film_grain)); + dst->coded_lossless = src->coded_lossless; + + return 0; + +fail: + av1_frame_unref(avctx, dst); + return AVERROR(ENOMEM); +} + +static av_cold int av1_decode_free(AVCodecContext *avctx) +{ + AV1DecContext *s = avctx->priv_data; + + for (int i = 0; i < FF_ARRAY_ELEMS(s->ref); i++) { + av1_frame_unref(avctx, &s->ref[i]); + av_frame_free(&s->ref[i].tf.f); + } + av1_frame_unref(avctx, &s->cur_frame); + av_frame_free(&s->cur_frame.tf.f); + + av_buffer_unref(&s->seq_ref); + av_buffer_unref(&s->header_ref); + av_freep(&s->tile_group_info); + + ff_cbs_fragment_free(&s->current_obu); + ff_cbs_close(&s->cbc); + + return 0; +} + +static int set_context_with_sequence(AVCodecContext *avctx, + const AV1RawSequenceHeader *seq) +{ + int width = seq->max_frame_width_minus_1 + 1; + int height = seq->max_frame_height_minus_1 + 1; + + avctx->profile = seq->seq_profile; + avctx->level = seq->seq_level_idx[0]; + + avctx->color_range = + seq->color_config.color_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + avctx->color_primaries = seq->color_config.color_primaries; + avctx->colorspace = seq->color_config.color_primaries; + avctx->color_trc = seq->color_config.transfer_characteristics; + + switch (seq->color_config.chroma_sample_position) { + case AV1_CSP_VERTICAL: + avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; + break; + case AV1_CSP_COLOCATED: + avctx->chroma_sample_location = AVCHROMA_LOC_TOPLEFT; + break; + } + + if (avctx->width != width || avctx->height != height) { + int ret = ff_set_dimensions(avctx, width, height); + if (ret < 0) + return ret; + } + avctx->sample_aspect_ratio = (AVRational) { 1, 1 }; + + if (seq->timing_info.num_units_in_display_tick && + seq->timing_info.time_scale) { + av_reduce(&avctx->framerate.den, &avctx->framerate.num, + seq->timing_info.num_units_in_display_tick, + seq->timing_info.time_scale, + INT_MAX); + if (seq->timing_info.equal_picture_interval) + avctx->ticks_per_frame = seq->timing_info.num_ticks_per_picture_minus_1 + 1; + } + + return 0; +} + +static int update_context_with_frame_header(AVCodecContext *avctx, + const AV1RawFrameHeader *header) +{ + AVRational aspect_ratio; + int width = header->frame_width_minus_1 + 1; + int height = header->frame_height_minus_1 + 1; + int r_width = header->render_width_minus_1 + 1; + int r_height = header->render_height_minus_1 + 1; + int ret; + + if (avctx->width != width || avctx->height != height) { + ret = ff_set_dimensions(avctx, width, height); + if (ret < 0) + return ret; + } + + av_reduce(&aspect_ratio.num, &aspect_ratio.den, + (int64_t)height * r_width, + (int64_t)width * r_height, + INT_MAX); + + if (av_cmp_q(avctx->sample_aspect_ratio, aspect_ratio)) { + ret = ff_set_sar(avctx, aspect_ratio); + if (ret < 0) + return ret; + } + + return 0; +} + +static av_cold int av1_decode_init(AVCodecContext *avctx) +{ + AV1DecContext *s = avctx->priv_data; + AV1RawSequenceHeader *seq; + int ret; + + s->avctx = avctx; + s->pix_fmt = AV_PIX_FMT_NONE; + + for (int i = 0; i < FF_ARRAY_ELEMS(s->ref); i++) { + s->ref[i].tf.f = av_frame_alloc(); + if (!s->ref[i].tf.f) { + av_log(avctx, AV_LOG_ERROR, + "Failed to allocate reference frame buffer %d.\n", i); + return AVERROR(ENOMEM); + } + } + + s->cur_frame.tf.f = av_frame_alloc(); + if (!s->cur_frame.tf.f) { + av_log(avctx, AV_LOG_ERROR, + "Failed to allocate current frame buffer.\n"); + return AVERROR(ENOMEM); + } + + ret = ff_cbs_init(&s->cbc, AV_CODEC_ID_AV1, avctx); + if (ret < 0) + return ret; + + av_opt_set_int(s->cbc->priv_data, "operating_point", s->operating_point, 0); + + if (avctx->extradata && avctx->extradata_size) { + ret = ff_cbs_read_extradata_from_codec(s->cbc, + &s->current_obu, + avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_WARNING, "Failed to read extradata.\n"); + return ret; + } + + seq = ((CodedBitstreamAV1Context *)(s->cbc->priv_data))->sequence_header; + if (!seq) { + av_log(avctx, AV_LOG_WARNING, "No sequence header available.\n"); + goto end; + } + + ret = set_context_with_sequence(avctx, seq); + if (ret < 0) { + av_log(avctx, AV_LOG_WARNING, "Failed to set decoder context.\n"); + goto end; + } + + end: + ff_cbs_fragment_reset(&s->current_obu); + } + + return ret; +} + +static int av1_frame_alloc(AVCodecContext *avctx, AV1Frame *f) +{ + AV1DecContext *s = avctx->priv_data; + AV1RawFrameHeader *header= s->raw_frame_header; + AVFrame *frame; + int ret; + + ret = update_context_with_frame_header(avctx, header); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to update context with frame header\n"); + 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; + + frame = f->tf.f; + frame->key_frame = header->frame_type == AV1_FRAME_KEY; + + switch (header->frame_type) { + case AV1_FRAME_KEY: + case AV1_FRAME_INTRA_ONLY: + frame->pict_type = AV_PICTURE_TYPE_I; + break; + case AV1_FRAME_INTER: + frame->pict_type = AV_PICTURE_TYPE_P; + break; + case AV1_FRAME_SWITCH: + frame->pict_type = AV_PICTURE_TYPE_SP; + break; + } + + if (avctx->hwaccel) { + const AVHWAccel *hwaccel = avctx->hwaccel; + if (hwaccel->frame_priv_data_size) { + f->hwaccel_priv_buf = + av_buffer_allocz(hwaccel->frame_priv_data_size); + if (!f->hwaccel_priv_buf) { + ret = AVERROR(ENOMEM); + goto fail; + } + f->hwaccel_picture_private = f->hwaccel_priv_buf->data; + } + } + return 0; + +fail: + av1_frame_unref(avctx, f); + return ret; +} + +static int export_film_grain(AVCodecContext *avctx, AVFrame *frame) +{ + AV1DecContext *s = avctx->priv_data; + const AV1RawFilmGrainParams *film_grain = &s->cur_frame.film_grain; + AVFilmGrainParams *fgp; + AVFilmGrainAOMParams *aom; + + if (!film_grain->apply_grain) + return 0; + + fgp = av_film_grain_params_create_side_data(frame); + if (!fgp) + return AVERROR(ENOMEM); + + fgp->type = AV_FILM_GRAIN_PARAMS_AV1; + fgp->seed = film_grain->grain_seed; + + aom = &fgp->codec.aom; + aom->chroma_scaling_from_luma = film_grain->chroma_scaling_from_luma; + aom->scaling_shift = film_grain->grain_scaling_minus_8 + 8; + aom->ar_coeff_lag = film_grain->ar_coeff_lag; + aom->ar_coeff_shift = film_grain->ar_coeff_shift_minus_6 + 6; + aom->grain_scale_shift = film_grain->grain_scale_shift; + aom->overlap_flag = film_grain->overlap_flag; + aom->limit_output_range = film_grain->clip_to_restricted_range; + + aom->num_y_points = film_grain->num_y_points; + for (int i = 0; i < film_grain->num_y_points; i++) { + aom->y_points[i][0] = film_grain->point_y_value[i]; + aom->y_points[i][1] = film_grain->point_y_scaling[i]; + } + aom->num_uv_points[0] = film_grain->num_cb_points; + for (int i = 0; i < film_grain->num_cb_points; i++) { + aom->uv_points[0][i][0] = film_grain->point_cb_value[i]; + aom->uv_points[0][i][1] = film_grain->point_cb_scaling[i]; + } + aom->num_uv_points[1] = film_grain->num_cr_points; + for (int i = 0; i < film_grain->num_cr_points; i++) { + aom->uv_points[1][i][0] = film_grain->point_cr_value[i]; + aom->uv_points[1][i][1] = film_grain->point_cr_scaling[i]; + } + + for (int i = 0; i < 24; i++) { + aom->ar_coeffs_y[i] = film_grain->ar_coeffs_y_plus_128[i] - 128; + } + for (int i = 0; i < 25; i++) { + aom->ar_coeffs_uv[0][i] = film_grain->ar_coeffs_cb_plus_128[i] - 128; + aom->ar_coeffs_uv[1][i] = film_grain->ar_coeffs_cr_plus_128[i] - 128; + } + + aom->uv_mult[0] = film_grain->cb_mult; + aom->uv_mult[1] = film_grain->cr_mult; + aom->uv_mult_luma[0] = film_grain->cb_luma_mult; + aom->uv_mult_luma[1] = film_grain->cr_luma_mult; + aom->uv_offset[0] = film_grain->cb_offset; + aom->uv_offset[1] = film_grain->cr_offset; + + return 0; +} + +static int set_output_frame(AVCodecContext *avctx, AVFrame *frame, + const AVPacket *pkt, int *got_frame) +{ + AV1DecContext *s = avctx->priv_data; + const AVFrame *srcframe = s->cur_frame.tf.f; + int ret; + + // TODO: all layers + if (s->operating_point_idc && + av_log2(s->operating_point_idc >> 8) > s->cur_frame.spatial_id) + return 0; + + ret = av_frame_ref(frame, srcframe); + if (ret < 0) + return ret; + + if (avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) { + ret = export_film_grain(avctx, frame); + if (ret < 0) { + av_frame_unref(frame); + return ret; + } + } + + frame->pts = pkt->pts; + frame->pkt_dts = pkt->dts; + frame->pkt_size = pkt->size; + + *got_frame = 1; + + return 0; +} + +static int update_reference_list(AVCodecContext *avctx) +{ + AV1DecContext *s = avctx->priv_data; + const AV1RawFrameHeader *header = s->raw_frame_header; + int ret; + + 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]); + 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); + return ret; + } + } + } + return 0; +} + +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); + + ret = av1_frame_alloc(avctx, &s->cur_frame); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Failed to allocate space for current frame.\n"); + 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); + load_grain_params(s); + + return ret; +} + +static int av1_decode_frame(AVCodecContext *avctx, void *frame, + int *got_frame, AVPacket *pkt) +{ + AV1DecContext *s = avctx->priv_data; + AV1RawTileGroup *raw_tile_group = NULL; + int ret; + + ret = ff_cbs_read_packet(s->cbc, &s->current_obu, pkt); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to read packet.\n"); + goto end; + } + av_log(avctx, AV_LOG_DEBUG, "Total obu for this frame:%d.\n", + s->current_obu.nb_units); + + for (int i = 0; i < s->current_obu.nb_units; i++) { + CodedBitstreamUnit *unit = &s->current_obu.units[i]; + AV1RawOBU *obu = unit->content; + const AV1RawOBUHeader *header; + + if (!obu) + continue; + + header = &obu->header; + av_log(avctx, AV_LOG_DEBUG, "Obu idx:%d, obu type:%d.\n", i, unit->type); + + switch (unit->type) { + case AV1_OBU_SEQUENCE_HEADER: + av_buffer_unref(&s->seq_ref); + s->seq_ref = av_buffer_ref(unit->content_ref); + if (!s->seq_ref) { + ret = AVERROR(ENOMEM); + goto end; + } + + s->raw_seq = &obu->obu.sequence_header; + + ret = set_context_with_sequence(avctx, s->raw_seq); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to set context.\n"); + s->raw_seq = NULL; + goto end; + } + + s->operating_point_idc = s->raw_seq->operating_point_idc[s->operating_point]; + + if (s->pix_fmt == AV_PIX_FMT_NONE) { + ret = get_pixel_format(avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Failed to get pixel format.\n"); + s->raw_seq = NULL; + goto end; + } + } + + if (avctx->hwaccel && avctx->hwaccel->decode_params) { + ret = avctx->hwaccel->decode_params(avctx, unit->type, unit->data, + unit->data_size); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "HW accel decode params fail.\n"); + s->raw_seq = NULL; + goto end; + } + } + break; + case AV1_OBU_REDUNDANT_FRAME_HEADER: + if (s->raw_frame_header) + break; + // fall-through + case AV1_OBU_FRAME: + case AV1_OBU_FRAME_HEADER: + if (!s->raw_seq) { + av_log(avctx, AV_LOG_ERROR, "Missing Sequence Header.\n"); + ret = AVERROR_INVALIDDATA; + goto end; + } + + av_buffer_unref(&s->header_ref); + s->header_ref = av_buffer_ref(unit->content_ref); + if (!s->header_ref) { + ret = AVERROR(ENOMEM); + goto end; + } + + if (unit->type == AV1_OBU_FRAME) + s->raw_frame_header = &obu->obu.frame.header; + else + 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); + + ret = av1_frame_ref(avctx, &s->cur_frame, + &s->ref[s->raw_frame_header->frame_to_show_map_idx]); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to get reference frame.\n"); + goto end; + } + + ret = update_reference_list(avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to update reference list.\n"); + 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"); + + s->raw_frame_header = NULL; + + goto end; + } + + ret = get_current_frame(avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Get current frame error\n"); + goto end; + } + + s->cur_frame.spatial_id = header->spatial_id; + s->cur_frame.temporal_id = header->temporal_id; + + if (avctx->hwaccel) { + ret = avctx->hwaccel->start_frame(avctx, unit->data, + unit->data_size); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "HW accel start frame fail.\n"); + goto end; + } + } + if (unit->type != AV1_OBU_FRAME) + break; + // fall-through + case AV1_OBU_TILE_GROUP: + if (!s->raw_frame_header) { + av_log(avctx, AV_LOG_ERROR, "Missing Frame Header.\n"); + ret = AVERROR_INVALIDDATA; + goto end; + } + + if (unit->type == AV1_OBU_FRAME) + raw_tile_group = &obu->obu.frame.tile_group; + else + raw_tile_group = &obu->obu.tile_group; + + ret = get_tiles_info(avctx, raw_tile_group); + if (ret < 0) + goto end; + + if (avctx->hwaccel) { + ret = avctx->hwaccel->decode_slice(avctx, + raw_tile_group->tile_data.data, + raw_tile_group->tile_data.data_size); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "HW accel decode slice fail.\n"); + goto end; + } + } + break; + case AV1_OBU_TILE_LIST: + case AV1_OBU_TEMPORAL_DELIMITER: + case AV1_OBU_PADDING: + case AV1_OBU_METADATA: + break; + default: + av_log(avctx, AV_LOG_DEBUG, + "Unknown obu type: %d (%"SIZE_SPECIFIER" bits).\n", + unit->type, unit->data_size); + } + + if (raw_tile_group && (s->tile_num == raw_tile_group->tg_end + 1)) { + if (avctx->hwaccel) { + ret = avctx->hwaccel->end_frame(avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "HW accel end frame fail.\n"); + goto end; + } + } + + ret = update_reference_list(avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to update reference list.\n"); + goto end; + } + + if (s->raw_frame_header->show_frame) { + ret = set_output_frame(avctx, frame, pkt, got_frame); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Set output frame error\n"); + goto end; + } + } + raw_tile_group = NULL; + s->raw_frame_header = NULL; + } + } + +end: + ff_cbs_fragment_reset(&s->current_obu); + if (ret < 0) + s->raw_frame_header = NULL; + return ret; +} + +static void av1_decode_flush(AVCodecContext *avctx) +{ + AV1DecContext *s = avctx->priv_data; + + for (int i = 0; i < FF_ARRAY_ELEMS(s->ref); i++) + av1_frame_unref(avctx, &s->ref[i]); + + av1_frame_unref(avctx, &s->cur_frame); + s->operating_point_idc = 0; + s->raw_frame_header = NULL; + s->raw_seq = NULL; + + ff_cbs_flush(s->cbc); +} + +#define OFFSET(x) offsetof(AV1DecContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption av1_options[] = { + { "operating_point", "Select an operating point of the scalable bitstream", + OFFSET(operating_point), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, AV1_MAX_OPERATING_POINTS - 1, VD }, + { NULL } +}; + +static const AVClass av1_class = { + .class_name = "AV1 decoder", + .item_name = av_default_item_name, + .option = av1_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_av1_decoder = { + .name = "av1", + .long_name = NULL_IF_CONFIG_SMALL("Alliance for Open Media AV1"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .priv_data_size = sizeof(AV1DecContext), + .init = av1_decode_init, + .close = av1_decode_free, + .decode = av1_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_SETS_PKT_DTS, + .flush = av1_decode_flush, + .profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), + .priv_class = &av1_class, + .hw_configs = (const AVCodecHWConfigInternal *const []) { +#if CONFIG_AV1_DXVA2_HWACCEL + HWACCEL_DXVA2(av1), +#endif +#if CONFIG_AV1_D3D11VA_HWACCEL + HWACCEL_D3D11VA(av1), +#endif +#if CONFIG_AV1_D3D11VA2_HWACCEL + HWACCEL_D3D11VA2(av1), +#endif +#if CONFIG_AV1_NVDEC_HWACCEL + HWACCEL_NVDEC(av1), +#endif +#if CONFIG_AV1_VAAPI_HWACCEL + HWACCEL_VAAPI(av1), +#endif + NULL + }, +}; diff -Nru ffmpeg-4.2.2/libavcodec/av1dec.h ffmpeg-4.4/libavcodec/av1dec.h --- ffmpeg-4.2.2/libavcodec/av1dec.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/av1dec.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,88 @@ +/* + * AV1 video decoder + * * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AV1DEC_H +#define AVCODEC_AV1DEC_H + +#include + +#include "libavutil/buffer.h" +#include "libavutil/pixfmt.h" +#include "avcodec.h" +#include "cbs.h" +#include "cbs_av1.h" +#include "thread.h" + +typedef struct AV1Frame { + ThreadFrame tf; + + AVBufferRef *hwaccel_priv_buf; + void *hwaccel_picture_private; + + AVBufferRef *header_ref; + AV1RawFrameHeader *raw_frame_header; + + int temporal_id; + int spatial_id; + + uint8_t gm_type[AV1_NUM_REF_FRAMES]; + int32_t gm_params[AV1_NUM_REF_FRAMES][6]; + + uint8_t skip_mode_frame_idx[2]; + + AV1RawFilmGrainParams film_grain; + + uint8_t coded_lossless; +} AV1Frame; + +typedef struct TileGroupInfo { + uint32_t tile_offset; + uint32_t tile_size; + uint16_t tile_row; + uint16_t tile_column; +} TileGroupInfo; + +typedef struct AV1DecContext { + const AVClass *class; + AVCodecContext *avctx; + + enum AVPixelFormat pix_fmt; + CodedBitstreamContext *cbc; + CodedBitstreamFragment current_obu; + + AVBufferRef *seq_ref; + AV1RawSequenceHeader *raw_seq; + AVBufferRef *header_ref; + AV1RawFrameHeader *raw_frame_header; + TileGroupInfo *tile_group_info; + uint16_t tile_num; + uint16_t tg_start; + uint16_t tg_end; + + int operating_point_idc; + + AV1Frame ref[AV1_NUM_REF_FRAMES]; + AV1Frame cur_frame; + + // AVOptions + int operating_point; +} AV1DecContext; + +#endif /* AVCODEC_AV1DEC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/av1_frame_merge_bsf.c ffmpeg-4.4/libavcodec/av1_frame_merge_bsf.c --- ffmpeg-4.2.2/libavcodec/av1_frame_merge_bsf.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/av1_frame_merge_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2019 James Almer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "bsf.h" +#include "bsf_internal.h" +#include "cbs.h" +#include "cbs_av1.h" + +typedef struct AV1FMergeContext { + CodedBitstreamContext *input; + CodedBitstreamContext *output; + CodedBitstreamFragment frag[2]; + AVPacket *pkt, *in; + int idx; +} AV1FMergeContext; + +static void av1_frame_merge_flush(AVBSFContext *bsf) +{ + AV1FMergeContext *ctx = bsf->priv_data; + + ff_cbs_fragment_reset(&ctx->frag[0]); + ff_cbs_fragment_reset(&ctx->frag[1]); + av_packet_unref(ctx->in); + av_packet_unref(ctx->pkt); +} + +static int av1_frame_merge_filter(AVBSFContext *bsf, AVPacket *out) +{ + AV1FMergeContext *ctx = bsf->priv_data; + CodedBitstreamFragment *frag = &ctx->frag[ctx->idx], *tu = &ctx->frag[!ctx->idx]; + AVPacket *in = ctx->in, *buffer_pkt = ctx->pkt; + int err, i; + + err = ff_bsf_get_packet_ref(bsf, in); + if (err < 0) { + if (err == AVERROR_EOF && tu->nb_units > 0) + goto eof; + return err; + } + + err = ff_cbs_read_packet(ctx->input, frag, in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); + goto fail; + } + + if (frag->nb_units == 0) { + av_log(bsf, AV_LOG_ERROR, "No OBU in packet.\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + + if (tu->nb_units == 0 && frag->units[0].type != AV1_OBU_TEMPORAL_DELIMITER) { + av_log(bsf, AV_LOG_ERROR, "Missing Temporal Delimiter.\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + + for (i = 1; i < frag->nb_units; i++) { + if (frag->units[i].type == AV1_OBU_TEMPORAL_DELIMITER) { + av_log(bsf, AV_LOG_ERROR, "Temporal Delimiter in the middle of a packet.\n"); + err = AVERROR_INVALIDDATA; + goto fail; + } + } + + if (tu->nb_units > 0 && frag->units[0].type == AV1_OBU_TEMPORAL_DELIMITER) { +eof: + err = ff_cbs_write_packet(ctx->output, buffer_pkt, tu); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); + goto fail; + } + av_packet_move_ref(out, buffer_pkt); + + // Swap fragment index, to avoid copying fragment references. + ctx->idx = !ctx->idx; + } else { + for (i = 0; i < frag->nb_units; i++) { + err = ff_cbs_insert_unit_content(tu, -1, frag->units[i].type, + frag->units[i].content, frag->units[i].content_ref); + if (err < 0) + goto fail; + } + + err = AVERROR(EAGAIN); + } + + // Buffer packets with timestamps. There should be at most one per TU, be it split or not. + if (!buffer_pkt->data && in->pts != AV_NOPTS_VALUE) + av_packet_move_ref(buffer_pkt, in); + else + av_packet_unref(in); + + ff_cbs_fragment_reset(&ctx->frag[ctx->idx]); + +fail: + if (err < 0 && err != AVERROR(EAGAIN)) + av1_frame_merge_flush(bsf); + + return err; +} + +static int av1_frame_merge_init(AVBSFContext *bsf) +{ + AV1FMergeContext *ctx = bsf->priv_data; + int err; + + ctx->in = av_packet_alloc(); + ctx->pkt = av_packet_alloc(); + if (!ctx->in || !ctx->pkt) + return AVERROR(ENOMEM); + + err = ff_cbs_init(&ctx->input, AV_CODEC_ID_AV1, bsf); + if (err < 0) + return err; + + return ff_cbs_init(&ctx->output, AV_CODEC_ID_AV1, bsf); +} + +static void av1_frame_merge_close(AVBSFContext *bsf) +{ + AV1FMergeContext *ctx = bsf->priv_data; + + ff_cbs_fragment_free(&ctx->frag[0]); + ff_cbs_fragment_free(&ctx->frag[1]); + av_packet_free(&ctx->in); + av_packet_free(&ctx->pkt); + ff_cbs_close(&ctx->input); + ff_cbs_close(&ctx->output); +} + +static const enum AVCodecID av1_frame_merge_codec_ids[] = { + AV_CODEC_ID_AV1, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_av1_frame_merge_bsf = { + .name = "av1_frame_merge", + .priv_data_size = sizeof(AV1FMergeContext), + .init = av1_frame_merge_init, + .flush = av1_frame_merge_flush, + .close = av1_frame_merge_close, + .filter = av1_frame_merge_filter, + .codec_ids = av1_frame_merge_codec_ids, +}; diff -Nru ffmpeg-4.2.2/libavcodec/av1_frame_split_bsf.c ffmpeg-4.4/libavcodec/av1_frame_split_bsf.c --- ffmpeg-4.2.2/libavcodec/av1_frame_split_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/av1_frame_split_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,8 +32,8 @@ #include "libavutil/avassert.h" -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "cbs.h" #include "cbs_av1.h" @@ -172,7 +172,7 @@ if (s->cur_frame == s->nb_frames) { av_packet_unref(s->buffer_pkt); - ff_cbs_fragment_reset(s->cbc, td); + ff_cbs_fragment_reset(td); } return 0; @@ -187,7 +187,7 @@ av_packet_unref(out); av_packet_unref(s->buffer_pkt); } - ff_cbs_fragment_reset(s->cbc, td); + ff_cbs_fragment_reset(td); return ret; } @@ -214,7 +214,7 @@ if (ret < 0) return ret; - s->cbc->decompose_unit_types = (CodedBitstreamUnitType*)decompose_unit_types; + s->cbc->decompose_unit_types = decompose_unit_types; s->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types); if (!ctx->par_in->extradata_size) @@ -224,7 +224,7 @@ if (ret < 0) av_log(ctx, AV_LOG_WARNING, "Failed to parse extradata.\n"); - ff_cbs_fragment_reset(s->cbc, td); + ff_cbs_fragment_reset(td); return 0; } @@ -234,7 +234,7 @@ AV1FSplitContext *s = ctx->priv_data; av_packet_unref(s->buffer_pkt); - ff_cbs_fragment_reset(s->cbc, &s->temporal_unit); + ff_cbs_fragment_reset(&s->temporal_unit); } static void av1_frame_split_close(AVBSFContext *ctx) @@ -242,7 +242,7 @@ AV1FSplitContext *s = ctx->priv_data; av_packet_free(&s->buffer_pkt); - ff_cbs_fragment_free(s->cbc, &s->temporal_unit); + ff_cbs_fragment_free(&s->temporal_unit); ff_cbs_close(&s->cbc); } diff -Nru ffmpeg-4.2.2/libavcodec/av1.h ffmpeg-4.4/libavcodec/av1.h --- ffmpeg-4.2.2/libavcodec/av1.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/av1.h 2021-04-08 21:28:39.000000000 +0000 @@ -160,4 +160,12 @@ AV1_SCALABILITY_L4T7_KEY_SHIFT = 28, }; +// Frame Restoration types (section 6.10.15) +enum { + AV1_RESTORE_NONE = 0, + AV1_RESTORE_WIENER = 1, + AV1_RESTORE_SGRPROJ = 2, + AV1_RESTORE_SWITCHABLE = 3, +}; + #endif /* AVCODEC_AV1_H */ diff -Nru ffmpeg-4.2.2/libavcodec/av1_metadata_bsf.c ffmpeg-4.4/libavcodec/av1_metadata_bsf.c --- ffmpeg-4.2.2/libavcodec/av1_metadata_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/av1_metadata_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,19 +21,11 @@ #include "bsf.h" #include "cbs.h" +#include "cbs_bsf.h" #include "cbs_av1.h" -enum { - PASS, - INSERT, - REMOVE, -}; - typedef struct AV1MetadataContext { - const AVClass *class; - - CodedBitstreamContext *cbc; - CodedBitstreamFragment access_unit; + CBSBSFContext common; int td; @@ -61,12 +53,7 @@ if (ctx->color_primaries >= 0 || ctx->transfer_characteristics >= 0 || ctx->matrix_coefficients >= 0) { - if (!clc->color_description_present_flag) { - clc->color_description_present_flag = 1; - clc->color_primaries = AVCOL_PRI_UNSPECIFIED; - clc->transfer_characteristics = AVCOL_TRC_UNSPECIFIED; - clc->matrix_coefficients = AVCOL_SPC_UNSPECIFIED; - } + clc->color_description_present_flag = 1; if (ctx->color_primaries >= 0) clc->color_primaries = ctx->color_primaries; @@ -116,138 +103,66 @@ return 0; } -static int av1_metadata_filter(AVBSFContext *bsf, AVPacket *pkt) +static int av1_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt, + CodedBitstreamFragment *frag) { AV1MetadataContext *ctx = bsf->priv_data; - CodedBitstreamFragment *frag = &ctx->access_unit; AV1RawOBU td, *obu; int err, i; - err = ff_bsf_get_packet_ref(bsf, pkt); - if (err < 0) - return err; - - err = ff_cbs_read_packet(ctx->cbc, frag, pkt); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); - goto fail; - } - - if (frag->nb_units == 0) { - av_log(bsf, AV_LOG_ERROR, "No OBU in packet.\n"); - err = AVERROR_INVALIDDATA; - goto fail; - } - for (i = 0; i < frag->nb_units; i++) { if (frag->units[i].type == AV1_OBU_SEQUENCE_HEADER) { obu = frag->units[i].content; err = av1_metadata_update_sequence_header(bsf, &obu->obu.sequence_header); if (err < 0) - goto fail; + return err; } } // If a Temporal Delimiter is present, it must be the first OBU. - if (frag->units[0].type == AV1_OBU_TEMPORAL_DELIMITER) { - if (ctx->td == REMOVE) - ff_cbs_delete_unit(ctx->cbc, frag, 0); - } else if (ctx->td == INSERT) { + if (frag->nb_units && frag->units[0].type == AV1_OBU_TEMPORAL_DELIMITER) { + if (ctx->td == BSF_ELEMENT_REMOVE) + ff_cbs_delete_unit(frag, 0); + } else if (pkt && ctx->td == BSF_ELEMENT_INSERT) { td = (AV1RawOBU) { .header.obu_type = AV1_OBU_TEMPORAL_DELIMITER, }; - err = ff_cbs_insert_unit_content(ctx->cbc, frag, 0, AV1_OBU_TEMPORAL_DELIMITER, + err = ff_cbs_insert_unit_content(frag, 0, AV1_OBU_TEMPORAL_DELIMITER, &td, NULL); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to insert Temporal Delimiter.\n"); - goto fail; + return err; } } if (ctx->delete_padding) { for (i = frag->nb_units - 1; i >= 0; i--) { if (frag->units[i].type == AV1_OBU_PADDING) - ff_cbs_delete_unit(ctx->cbc, frag, i); + ff_cbs_delete_unit(frag, i); } } - err = ff_cbs_write_packet(ctx->cbc, pkt, frag); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); - goto fail; - } - - err = 0; -fail: - ff_cbs_fragment_reset(ctx->cbc, frag); - - if (err < 0) - av_packet_unref(pkt); - - return err; + return 0; } -static int av1_metadata_init(AVBSFContext *bsf) -{ - AV1MetadataContext *ctx = bsf->priv_data; - CodedBitstreamFragment *frag = &ctx->access_unit; - AV1RawOBU *obu; - int err, i; - - err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_AV1, bsf); - if (err < 0) - return err; - - if (bsf->par_in->extradata) { - err = ff_cbs_read_extradata(ctx->cbc, frag, bsf->par_in); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); - goto fail; - } - - for (i = 0; i < frag->nb_units; i++) { - if (frag->units[i].type == AV1_OBU_SEQUENCE_HEADER) { - obu = frag->units[i].content; - err = av1_metadata_update_sequence_header(bsf, &obu->obu.sequence_header); - if (err < 0) - goto fail; - } - } - - err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, frag); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); - goto fail; - } - } - - err = 0; -fail: - ff_cbs_fragment_reset(ctx->cbc, frag); - return err; -} +static const CBSBSFType av1_metadata_type = { + .codec_id = AV_CODEC_ID_AV1, + .fragment_name = "temporal unit", + .unit_name = "OBU", + .update_fragment = &av1_metadata_update_fragment, +}; -static void av1_metadata_close(AVBSFContext *bsf) +static int av1_metadata_init(AVBSFContext *bsf) { - AV1MetadataContext *ctx = bsf->priv_data; - - ff_cbs_fragment_free(ctx->cbc, &ctx->access_unit); - ff_cbs_close(&ctx->cbc); + return ff_cbs_bsf_generic_init(bsf, &av1_metadata_type); } #define OFFSET(x) offsetof(AV1MetadataContext, x) #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) static const AVOption av1_metadata_options[] = { - { "td", "Temporal Delimiter OBU", - OFFSET(td), AV_OPT_TYPE_INT, - { .i64 = PASS }, PASS, REMOVE, FLAGS, "td" }, - { "pass", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = PASS }, .flags = FLAGS, .unit = "td" }, - { "insert", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = INSERT }, .flags = FLAGS, .unit = "td" }, - { "remove", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = REMOVE }, .flags = FLAGS, .unit = "td" }, + BSF_ELEMENT_OPTIONS_PIR("td", "Temporal Delimiter OBU", + td, FLAGS), { "color_primaries", "Set color primaries (section 6.4.2)", OFFSET(color_primaries), AV_OPT_TYPE_INT, @@ -307,7 +222,7 @@ .priv_data_size = sizeof(AV1MetadataContext), .priv_class = &av1_metadata_class, .init = &av1_metadata_init, - .close = &av1_metadata_close, - .filter = &av1_metadata_filter, + .close = &ff_cbs_bsf_generic_close, + .filter = &ff_cbs_bsf_generic_filter, .codec_ids = av1_metadata_codec_ids, }; diff -Nru ffmpeg-4.2.2/libavcodec/av1_parse.c ffmpeg-4.4/libavcodec/av1_parse.c --- ffmpeg-4.2.2/libavcodec/av1_parse.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/av1_parse.c 2020-07-11 10:39:30.000000000 +0000 @@ -66,13 +66,16 @@ if (pkt->obus_allocated < pkt->nb_obus + 1) { int new_size = pkt->obus_allocated + 1; - AV1OBU *tmp = av_realloc_array(pkt->obus, new_size, sizeof(*tmp)); + AV1OBU *tmp; + + if (new_size >= INT_MAX / sizeof(*tmp)) + return AVERROR(ENOMEM); + tmp = av_fast_realloc(pkt->obus, &pkt->obus_allocated_size, new_size * sizeof(*tmp)); if (!tmp) return AVERROR(ENOMEM); pkt->obus = tmp; - memset(pkt->obus + pkt->obus_allocated, 0, - (new_size - pkt->obus_allocated) * sizeof(*tmp)); + memset(pkt->obus + pkt->obus_allocated, 0, sizeof(*pkt->obus)); pkt->obus_allocated = new_size; } obu = &pkt->obus[pkt->nb_obus]; @@ -103,5 +106,5 @@ void ff_av1_packet_uninit(AV1Packet *pkt) { av_freep(&pkt->obus); - pkt->obus_allocated = 0; + pkt->obus_allocated = pkt->obus_allocated_size = 0; } diff -Nru ffmpeg-4.2.2/libavcodec/av1_parse.h ffmpeg-4.4/libavcodec/av1_parse.h --- ffmpeg-4.2.2/libavcodec/av1_parse.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/av1_parse.h 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,9 @@ #include "avcodec.h" #include "get_bits.h" +// OBU header fields + max leb128 length +#define MAX_OBU_HEADER_SIZE (2 + 8) + typedef struct AV1OBU { /** Size of payload */ int size; @@ -56,6 +59,7 @@ AV1OBU *obus; int nb_obus; int obus_allocated; + unsigned obus_allocated_size; } AV1Packet; /** @@ -104,7 +108,7 @@ int ret, extension_flag, has_size_flag; int64_t size; - ret = init_get_bits8(&gb, buf, FFMIN(buf_size, 2 + 8)); // OBU header fields + max leb128 length + ret = init_get_bits8(&gb, buf, FFMIN(buf_size, MAX_OBU_HEADER_SIZE)); if (ret < 0) return ret; @@ -145,7 +149,9 @@ int v; /* There are no trailing bits on these */ - if (type == AV1_OBU_TILE_GROUP || type == AV1_OBU_FRAME) { + if (type == AV1_OBU_TILE_GROUP || + type == AV1_OBU_TILE_LIST || + type == AV1_OBU_FRAME) { if (size > INT_MAX / 8) return AVERROR(ERANGE); else diff -Nru ffmpeg-4.2.2/libavcodec/av1_parser.c ffmpeg-4.4/libavcodec/av1_parser.c --- ffmpeg-4.2.2/libavcodec/av1_parser.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/av1_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ #include "av1_parse.h" #include "cbs.h" #include "cbs_av1.h" +#include "internal.h" #include "parser.h" typedef struct AV1ParseContext { @@ -44,6 +45,10 @@ { AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12 }, }; +static const enum AVPixelFormat pix_fmts_rgb[3] = { + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, +}; + static int av1_parser_parse(AVCodecParserContext *ctx, AVCodecContext *avctx, const uint8_t **out_data, int *out_size, @@ -52,6 +57,8 @@ AV1ParseContext *s = ctx->priv_data; CodedBitstreamFragment *td = &s->temporal_unit; CodedBitstreamAV1Context *av1 = s->cbc->priv_data; + AV1RawSequenceHeader *seq; + AV1RawColorConfig *color; int ret; *out_data = data; @@ -66,12 +73,12 @@ if (avctx->extradata_size && !s->parsed_extradata) { s->parsed_extradata = 1; - ret = ff_cbs_read(s->cbc, td, avctx->extradata, avctx->extradata_size); + ret = ff_cbs_read_extradata_from_codec(s->cbc, td, avctx); if (ret < 0) { av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata.\n"); } - ff_cbs_fragment_reset(s->cbc, td); + ff_cbs_fragment_reset(td); } ret = ff_cbs_read(s->cbc, td, data, size); @@ -85,13 +92,13 @@ goto end; } + seq = av1->sequence_header; + color = &seq->color_config; + for (int i = 0; i < td->nb_units; i++) { CodedBitstreamUnit *unit = &td->units[i]; AV1RawOBU *obu = unit->content; - AV1RawSequenceHeader *seq = av1->sequence_header; - AV1RawColorConfig *color = &seq->color_config; AV1RawFrameHeader *frame; - int frame_type; if (unit->type == AV1_OBU_FRAME) frame = &obu->obu.frame.header; @@ -100,33 +107,18 @@ else continue; - if (frame->show_existing_frame) { - AV1ReferenceFrameState *ref = &av1->ref[frame->frame_to_show_map_idx]; - - if (!ref->valid) { - av_log(avctx, AV_LOG_ERROR, "Invalid reference frame\n"); - goto end; - } - - ctx->width = ref->frame_width; - ctx->height = ref->frame_height; - frame_type = ref->frame_type; + if (obu->header.spatial_id > 0) + continue; - ctx->key_frame = 0; - } else if (!frame->show_frame) { + if (!frame->show_frame && !frame->show_existing_frame) continue; - } else { - ctx->width = av1->frame_width; - ctx->height = av1->frame_height; - frame_type = frame->frame_type; - ctx->key_frame = frame_type == AV1_FRAME_KEY; - } + ctx->width = frame->frame_width_minus_1 + 1; + ctx->height = frame->frame_height_minus_1 + 1; - avctx->profile = seq->seq_profile; - avctx->level = seq->seq_level_idx[0]; + ctx->key_frame = frame->frame_type == AV1_FRAME_KEY && !frame->show_existing_frame; - switch (frame_type) { + switch (frame->frame_type) { case AV1_FRAME_KEY: case AV1_FRAME_INTRA_ONLY: ctx->pict_type = AV_PICTURE_TYPE_I; @@ -139,26 +131,43 @@ break; } ctx->picture_structure = AV_PICTURE_STRUCTURE_FRAME; + } - switch (av1->bit_depth) { - case 8: - ctx->format = color->mono_chrome ? AV_PIX_FMT_GRAY8 - : pix_fmts_8bit [color->subsampling_x][color->subsampling_y]; - break; - case 10: - ctx->format = color->mono_chrome ? AV_PIX_FMT_GRAY10 - : pix_fmts_10bit[color->subsampling_x][color->subsampling_y]; - break; - case 12: - ctx->format = color->mono_chrome ? AV_PIX_FMT_GRAY12 - : pix_fmts_12bit[color->subsampling_x][color->subsampling_y]; - break; - } - av_assert2(ctx->format != AV_PIX_FMT_NONE); + switch (av1->bit_depth) { + case 8: + ctx->format = color->mono_chrome ? AV_PIX_FMT_GRAY8 + : pix_fmts_8bit [color->subsampling_x][color->subsampling_y]; + break; + case 10: + ctx->format = color->mono_chrome ? AV_PIX_FMT_GRAY10 + : pix_fmts_10bit[color->subsampling_x][color->subsampling_y]; + break; + case 12: + ctx->format = color->mono_chrome ? AV_PIX_FMT_GRAY12 + : pix_fmts_12bit[color->subsampling_x][color->subsampling_y]; + break; } + av_assert2(ctx->format != AV_PIX_FMT_NONE); + + if (!color->subsampling_x && !color->subsampling_y && + color->matrix_coefficients == AVCOL_SPC_RGB && + color->color_primaries == AVCOL_PRI_BT709 && + color->transfer_characteristics == AVCOL_TRC_IEC61966_2_1) + ctx->format = pix_fmts_rgb[color->high_bitdepth + color->twelve_bit]; + + avctx->profile = seq->seq_profile; + avctx->level = seq->seq_level_idx[0]; + + avctx->colorspace = (enum AVColorSpace) color->matrix_coefficients; + avctx->color_primaries = (enum AVColorPrimaries) color->color_primaries; + avctx->color_trc = (enum AVColorTransferCharacteristic) color->transfer_characteristics; + avctx->color_range = color->color_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + + if (avctx->framerate.num) + avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); end: - ff_cbs_fragment_reset(s->cbc, td); + ff_cbs_fragment_reset(td); s->cbc->log_ctx = NULL; @@ -182,7 +191,7 @@ if (ret < 0) return ret; - s->cbc->decompose_unit_types = (CodedBitstreamUnitType *)decompose_unit_types; + s->cbc->decompose_unit_types = decompose_unit_types; s->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types); return 0; @@ -192,7 +201,7 @@ { AV1ParseContext *s = ctx->priv_data; - ff_cbs_fragment_free(s->cbc, &s->temporal_unit); + ff_cbs_fragment_free(&s->temporal_unit); ff_cbs_close(&s->cbc); } diff -Nru ffmpeg-4.2.2/libavcodec/avcodec.c ffmpeg-4.4/libavcodec/avcodec.c --- ffmpeg-4.2.2/libavcodec/avcodec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/avcodec.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,851 @@ +/* + * AVCodecContext functions for libavcodec + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * AVCodecContext functions for libavcodec + */ + +#include "config.h" +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/imgutils.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/thread.h" +#include "avcodec.h" +#include "decode.h" +#include "encode.h" +#include "frame_thread_encoder.h" +#include "internal.h" +#include "thread.h" +#if CONFIG_ICONV +# include +#endif + +#include "libavutil/ffversion.h" +const char av_codec_ffversion[] = "FFmpeg version " FFMPEG_VERSION; + +unsigned avcodec_version(void) +{ + av_assert0(AV_CODEC_ID_PCM_S8_PLANAR==65563); + av_assert0(AV_CODEC_ID_ADPCM_G722==69660); + av_assert0(AV_CODEC_ID_SRT==94216); + av_assert0(LIBAVCODEC_VERSION_MICRO >= 100); + + return LIBAVCODEC_VERSION_INT; +} + +const char *avcodec_configuration(void) +{ + return FFMPEG_CONFIGURATION; +} + +const char *avcodec_license(void) +{ +#define LICENSE_PREFIX "libavcodec license: " + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; +} + +int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2), void *arg, int *ret, int count, int size) +{ + int i; + + for (i = 0; i < count; i++) { + int r = func(c, (char *)arg + i * size); + if (ret) + ret[i] = r; + } + emms_c(); + return 0; +} + +int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int jobnr, int threadnr), void *arg, int *ret, int count) +{ + int i; + + for (i = 0; i < count; i++) { + int r = func(c, arg, i, 0); + if (ret) + ret[i] = r; + } + emms_c(); + return 0; +} + +static AVMutex codec_mutex = AV_MUTEX_INITIALIZER; + +static void lock_avcodec(const AVCodec *codec) +{ + if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) + ff_mutex_lock(&codec_mutex); +} + +static void unlock_avcodec(const AVCodec *codec) +{ + if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) + ff_mutex_unlock(&codec_mutex); +} + +#if FF_API_LOCKMGR +int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) +{ + return 0; +} +#endif + +static int64_t get_bit_rate(AVCodecContext *ctx) +{ + int64_t bit_rate; + int bits_per_sample; + + switch (ctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + case AVMEDIA_TYPE_DATA: + case AVMEDIA_TYPE_SUBTITLE: + case AVMEDIA_TYPE_ATTACHMENT: + bit_rate = ctx->bit_rate; + break; + case AVMEDIA_TYPE_AUDIO: + bits_per_sample = av_get_bits_per_sample(ctx->codec_id); + if (bits_per_sample) { + bit_rate = ctx->sample_rate * (int64_t)ctx->channels; + if (bit_rate > INT64_MAX / bits_per_sample) { + bit_rate = 0; + } else + bit_rate *= bits_per_sample; + } else + bit_rate = ctx->bit_rate; + break; + default: + bit_rate = 0; + break; + } + return bit_rate; +} + +int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options) +{ + int ret = 0; + int codec_init_ok = 0; + AVDictionary *tmp = NULL; + AVCodecInternal *avci; + + if (avcodec_is_open(avctx)) + return 0; + + if (!codec && !avctx->codec) { + av_log(avctx, AV_LOG_ERROR, "No codec provided to avcodec_open2()\n"); + return AVERROR(EINVAL); + } + if (codec && avctx->codec && codec != avctx->codec) { + av_log(avctx, AV_LOG_ERROR, "This AVCodecContext was allocated for %s, " + "but %s passed to avcodec_open2()\n", avctx->codec->name, codec->name); + return AVERROR(EINVAL); + } + if (!codec) + codec = avctx->codec; + + if (avctx->extradata_size < 0 || avctx->extradata_size >= FF_MAX_EXTRADATA_SIZE) + return AVERROR(EINVAL); + + if (options) + av_dict_copy(&tmp, *options, 0); + + lock_avcodec(codec); + + avci = av_mallocz(sizeof(*avci)); + if (!avci) { + ret = AVERROR(ENOMEM); + goto end; + } + avctx->internal = avci; + +#if FF_API_OLD_ENCDEC + avci->to_free = av_frame_alloc(); + avci->compat_decode_frame = av_frame_alloc(); + avci->compat_encode_packet = av_packet_alloc(); + if (!avci->to_free || !avci->compat_decode_frame || !avci->compat_encode_packet) { + ret = AVERROR(ENOMEM); + goto free_and_end; + } +#endif + 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->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->last_pkt_props || !avci->pkt_props) { + ret = AVERROR(ENOMEM); + goto free_and_end; + } + + avci->skip_samples_multiplier = 1; + + if (codec->priv_data_size > 0) { + if (!avctx->priv_data) { + avctx->priv_data = av_mallocz(codec->priv_data_size); + if (!avctx->priv_data) { + ret = AVERROR(ENOMEM); + goto free_and_end; + } + if (codec->priv_class) { + *(const AVClass **)avctx->priv_data = codec->priv_class; + av_opt_set_defaults(avctx->priv_data); + } + } + if (codec->priv_class && (ret = av_opt_set_dict(avctx->priv_data, &tmp)) < 0) + goto free_and_end; + } else { + avctx->priv_data = NULL; + } + if ((ret = av_opt_set_dict(avctx, &tmp)) < 0) + goto free_and_end; + + if (avctx->codec_whitelist && av_match_list(codec->name, avctx->codec_whitelist, ',') <= 0) { + av_log(avctx, AV_LOG_ERROR, "Codec (%s) not on whitelist \'%s\'\n", codec->name, avctx->codec_whitelist); + ret = AVERROR(EINVAL); + goto free_and_end; + } + + // only call ff_set_dimensions() for non H.264/VP6F/DXV codecs so as not to overwrite previously setup dimensions + if (!(avctx->coded_width && avctx->coded_height && avctx->width && avctx->height && + (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_VP6F || avctx->codec_id == AV_CODEC_ID_DXV))) { + if (avctx->coded_width && avctx->coded_height) + ret = ff_set_dimensions(avctx, avctx->coded_width, avctx->coded_height); + else if (avctx->width && avctx->height) + ret = ff_set_dimensions(avctx, avctx->width, avctx->height); + if (ret < 0) + goto free_and_end; + } + + if ((avctx->coded_width || avctx->coded_height || avctx->width || avctx->height) + && ( av_image_check_size2(avctx->coded_width, avctx->coded_height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0 + || av_image_check_size2(avctx->width, avctx->height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0)) { + av_log(avctx, AV_LOG_WARNING, "Ignoring invalid width/height values\n"); + ff_set_dimensions(avctx, 0, 0); + } + + if (avctx->width > 0 && avctx->height > 0) { + if (av_image_check_sar(avctx->width, avctx->height, + avctx->sample_aspect_ratio) < 0) { + av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\n", + avctx->sample_aspect_ratio.num, + avctx->sample_aspect_ratio.den); + avctx->sample_aspect_ratio = (AVRational){ 0, 1 }; + } + } + + if (avctx->channels > FF_SANE_NB_CHANNELS || avctx->channels < 0) { + av_log(avctx, AV_LOG_ERROR, "Too many or invalid channels: %d\n", avctx->channels); + ret = AVERROR(EINVAL); + goto free_and_end; + } + if (av_codec_is_decoder(codec) && + codec->type == AVMEDIA_TYPE_AUDIO && + !(codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF) && + avctx->channels == 0) { + av_log(avctx, AV_LOG_ERROR, "Decoder requires channel count but channels not set\n"); + ret = AVERROR(EINVAL); + goto free_and_end; + } + + if (avctx->sample_rate < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid sample rate: %d\n", avctx->sample_rate); + ret = AVERROR(EINVAL); + goto free_and_end; + } + if (avctx->block_align < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid block align: %d\n", avctx->block_align); + ret = AVERROR(EINVAL); + goto free_and_end; + } + + avctx->codec = codec; + if ((avctx->codec_type == AVMEDIA_TYPE_UNKNOWN || avctx->codec_type == codec->type) && + avctx->codec_id == AV_CODEC_ID_NONE) { + avctx->codec_type = codec->type; + avctx->codec_id = codec->id; + } + if (avctx->codec_id != codec->id || (avctx->codec_type != codec->type + && avctx->codec_type != AVMEDIA_TYPE_ATTACHMENT)) { + av_log(avctx, AV_LOG_ERROR, "Codec type or id mismatches\n"); + ret = AVERROR(EINVAL); + goto free_and_end; + } + avctx->frame_number = 0; + avctx->codec_descriptor = avcodec_descriptor_get(avctx->codec_id); + + if ((avctx->codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) && + avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + const char *codec_string = av_codec_is_encoder(codec) ? "encoder" : "decoder"; + const AVCodec *codec2; + av_log(avctx, AV_LOG_ERROR, + "The %s '%s' is experimental but experimental codecs are not enabled, " + "add '-strict %d' if you want to use it.\n", + codec_string, codec->name, FF_COMPLIANCE_EXPERIMENTAL); + codec2 = av_codec_is_encoder(codec) ? avcodec_find_encoder(codec->id) : avcodec_find_decoder(codec->id); + if (!(codec2->capabilities & AV_CODEC_CAP_EXPERIMENTAL)) + av_log(avctx, AV_LOG_ERROR, "Alternatively use the non experimental %s '%s'.\n", + codec_string, codec2->name); + ret = AVERROR_EXPERIMENTAL; + goto free_and_end; + } + + if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && + (!avctx->time_base.num || !avctx->time_base.den)) { + avctx->time_base.num = 1; + avctx->time_base.den = avctx->sample_rate; + } + + if (av_codec_is_encoder(avctx->codec)) + ret = ff_encode_preinit(avctx); + else + ret = ff_decode_preinit(avctx); + if (ret < 0) + goto free_and_end; + + if (!HAVE_THREADS) + av_log(avctx, AV_LOG_WARNING, "Warning: not compiled with thread support, using thread emulation\n"); + + if (CONFIG_FRAME_THREAD_ENCODER && av_codec_is_encoder(avctx->codec)) { + unlock_avcodec(codec); //we will instantiate a few encoders thus kick the counter to prevent false detection of a problem + ret = ff_frame_thread_encoder_init(avctx, options ? *options : NULL); + lock_avcodec(codec); + if (ret < 0) + goto free_and_end; + } + + if (HAVE_THREADS + && !(avci->frame_thread_encoder && (avctx->active_thread_type&FF_THREAD_FRAME))) { + ret = ff_thread_init(avctx); + if (ret < 0) { + goto free_and_end; + } + } + if (!HAVE_THREADS && !(codec->caps_internal & FF_CODEC_CAP_AUTO_THREADS)) + avctx->thread_count = 1; + + if ( avctx->codec->init && (!(avctx->active_thread_type&FF_THREAD_FRAME) + || avci->frame_thread_encoder)) { + ret = avctx->codec->init(avctx); + if (ret < 0) { + codec_init_ok = -1; + goto free_and_end; + } + codec_init_ok = 1; + } + + ret=0; + + if (av_codec_is_decoder(avctx->codec)) { + if (!avctx->bit_rate) + avctx->bit_rate = get_bit_rate(avctx); + /* validate channel layout from the decoder */ + if (avctx->channel_layout) { + int channels = av_get_channel_layout_nb_channels(avctx->channel_layout); + if (!avctx->channels) + avctx->channels = channels; + else if (channels != avctx->channels) { + char buf[512]; + av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); + av_log(avctx, AV_LOG_WARNING, + "Channel layout '%s' with %d channels does not match specified number of channels %d: " + "ignoring specified channel layout\n", + buf, channels, avctx->channels); + avctx->channel_layout = 0; + } + } + if (avctx->channels && avctx->channels < 0 || + avctx->channels > FF_SANE_NB_CHANNELS) { + ret = AVERROR(EINVAL); + goto free_and_end; + } + if (avctx->bits_per_coded_sample < 0) { + ret = AVERROR(EINVAL); + goto free_and_end; + } + if (avctx->sub_charenc) { + if (avctx->codec_type != AVMEDIA_TYPE_SUBTITLE) { + av_log(avctx, AV_LOG_ERROR, "Character encoding is only " + "supported with subtitles codecs\n"); + ret = AVERROR(EINVAL); + goto free_and_end; + } else if (avctx->codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB) { + av_log(avctx, AV_LOG_WARNING, "Codec '%s' is bitmap-based, " + "subtitles character encoding will be ignored\n", + avctx->codec_descriptor->name); + avctx->sub_charenc_mode = FF_SUB_CHARENC_MODE_DO_NOTHING; + } else { + /* input character encoding is set for a text based subtitle + * codec at this point */ + if (avctx->sub_charenc_mode == FF_SUB_CHARENC_MODE_AUTOMATIC) + avctx->sub_charenc_mode = FF_SUB_CHARENC_MODE_PRE_DECODER; + + if (avctx->sub_charenc_mode == FF_SUB_CHARENC_MODE_PRE_DECODER) { +#if CONFIG_ICONV + iconv_t cd = iconv_open("UTF-8", avctx->sub_charenc); + if (cd == (iconv_t)-1) { + ret = AVERROR(errno); + av_log(avctx, AV_LOG_ERROR, "Unable to open iconv context " + "with input character encoding \"%s\"\n", avctx->sub_charenc); + goto free_and_end; + } + iconv_close(cd); +#else + av_log(avctx, AV_LOG_ERROR, "Character encoding subtitles " + "conversion needs a libavcodec built with iconv support " + "for this codec\n"); + ret = AVERROR(ENOSYS); + goto free_and_end; +#endif + } + } + } + +#if FF_API_AVCTX_TIMEBASE + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) + avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); +#endif + } + if (codec->priv_data_size > 0 && avctx->priv_data && codec->priv_class) { + av_assert0(*(const AVClass **)avctx->priv_data == codec->priv_class); + } + +end: + unlock_avcodec(codec); + if (options) { + av_dict_free(options); + *options = tmp; + } + + return ret; +free_and_end: + if (avctx->codec && avctx->codec->close && + (codec_init_ok > 0 || (codec_init_ok < 0 && + avctx->codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP))) + avctx->codec->close(avctx); + + if (HAVE_THREADS && avci->thread_ctx) + ff_thread_free(avctx); + + if (codec->priv_class && avctx->priv_data) + av_opt_free(avctx->priv_data); + av_opt_free(avctx); + + if (av_codec_is_encoder(avctx->codec)) { +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + av_frame_free(&avctx->coded_frame); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + av_freep(&avctx->extradata); + avctx->extradata_size = 0; + } + + av_dict_free(&tmp); + av_freep(&avctx->priv_data); + av_freep(&avctx->subtitle_header); + +#if FF_API_OLD_ENCDEC + av_frame_free(&avci->to_free); + av_frame_free(&avci->compat_decode_frame); + av_packet_free(&avci->compat_encode_packet); +#endif + av_frame_free(&avci->buffer_frame); + av_packet_free(&avci->buffer_pkt); + av_packet_free(&avci->last_pkt_props); + av_fifo_freep(&avci->pkt_props); + + av_packet_free(&avci->ds.in_pkt); + av_frame_free(&avci->es.in_frame); + av_bsf_free(&avci->bsf); + + av_buffer_unref(&avci->pool); + av_freep(&avci); + avctx->internal = NULL; + avctx->codec = NULL; + goto end; +} + +void avcodec_flush_buffers(AVCodecContext *avctx) +{ + AVCodecInternal *avci = avctx->internal; + + if (av_codec_is_encoder(avctx->codec)) { + int caps = avctx->codec->capabilities; + + if (!(caps & AV_CODEC_CAP_ENCODER_FLUSH)) { + // Only encoders that explicitly declare support for it can be + // flushed. Otherwise, this is a no-op. + av_log(avctx, AV_LOG_WARNING, "Ignoring attempt to flush encoder " + "that doesn't support it\n"); + return; + } + + // We haven't implemented flushing for frame-threaded encoders. + av_assert0(!(caps & AV_CODEC_CAP_FRAME_THREADS)); + } + + avci->draining = 0; + avci->draining_done = 0; + avci->nb_draining_errors = 0; + av_frame_unref(avci->buffer_frame); +#if FF_API_OLD_ENCDEC + av_frame_unref(avci->compat_decode_frame); + av_packet_unref(avci->compat_encode_packet); +#endif + av_packet_unref(avci->buffer_pkt); + + av_packet_unref(avci->last_pkt_props); + while (av_fifo_size(avci->pkt_props) >= sizeof(*avci->last_pkt_props)) { + av_fifo_generic_read(avci->pkt_props, + avci->last_pkt_props, sizeof(*avci->last_pkt_props), + NULL); + av_packet_unref(avci->last_pkt_props); + } + av_fifo_reset(avci->pkt_props); + + av_frame_unref(avci->es.in_frame); + av_packet_unref(avci->ds.in_pkt); + + if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) + ff_thread_flush(avctx); + else if (avctx->codec->flush) + avctx->codec->flush(avctx); + + avctx->pts_correction_last_pts = + avctx->pts_correction_last_dts = INT64_MIN; + + if (av_codec_is_decoder(avctx->codec)) + av_bsf_flush(avci->bsf); + +#if FF_API_OLD_ENCDEC +FF_DISABLE_DEPRECATION_WARNINGS + if (!avctx->refcounted_frames) + av_frame_unref(avci->to_free); +FF_ENABLE_DEPRECATION_WARNINGS +#endif +} + +void avsubtitle_free(AVSubtitle *sub) +{ + int i; + + for (i = 0; i < sub->num_rects; i++) { + av_freep(&sub->rects[i]->data[0]); + av_freep(&sub->rects[i]->data[1]); + av_freep(&sub->rects[i]->data[2]); + av_freep(&sub->rects[i]->data[3]); + av_freep(&sub->rects[i]->text); + av_freep(&sub->rects[i]->ass); + av_freep(&sub->rects[i]); + } + + av_freep(&sub->rects); + + memset(sub, 0, sizeof(*sub)); +} + +av_cold int avcodec_close(AVCodecContext *avctx) +{ + int i; + + if (!avctx) + return 0; + + if (avcodec_is_open(avctx)) { + if (CONFIG_FRAME_THREAD_ENCODER && + avctx->internal->frame_thread_encoder && avctx->thread_count > 1) { + ff_frame_thread_encoder_free(avctx); + } + if (HAVE_THREADS && avctx->internal->thread_ctx) + ff_thread_free(avctx); + if (avctx->codec && avctx->codec->close) + avctx->codec->close(avctx); + avctx->internal->byte_buffer_size = 0; + av_freep(&avctx->internal->byte_buffer); +#if FF_API_OLD_ENCDEC + av_frame_free(&avctx->internal->to_free); + av_frame_free(&avctx->internal->compat_decode_frame); + av_packet_free(&avctx->internal->compat_encode_packet); +#endif + av_frame_free(&avctx->internal->buffer_frame); + av_packet_free(&avctx->internal->buffer_pkt); + av_packet_unref(avctx->internal->last_pkt_props); + while (av_fifo_size(avctx->internal->pkt_props) >= + sizeof(*avctx->internal->last_pkt_props)) { + av_fifo_generic_read(avctx->internal->pkt_props, + avctx->internal->last_pkt_props, + sizeof(*avctx->internal->last_pkt_props), + NULL); + av_packet_unref(avctx->internal->last_pkt_props); + } + av_packet_free(&avctx->internal->last_pkt_props); + av_fifo_freep(&avctx->internal->pkt_props); + + av_packet_free(&avctx->internal->ds.in_pkt); + av_frame_free(&avctx->internal->es.in_frame); + + av_buffer_unref(&avctx->internal->pool); + + if (avctx->hwaccel && avctx->hwaccel->uninit) + avctx->hwaccel->uninit(avctx); + av_freep(&avctx->internal->hwaccel_priv_data); + + av_bsf_free(&avctx->internal->bsf); + + av_freep(&avctx->internal); + } + + for (i = 0; i < avctx->nb_coded_side_data; i++) + av_freep(&avctx->coded_side_data[i].data); + av_freep(&avctx->coded_side_data); + avctx->nb_coded_side_data = 0; + + av_buffer_unref(&avctx->hw_frames_ctx); + av_buffer_unref(&avctx->hw_device_ctx); + + if (avctx->priv_data && avctx->codec && avctx->codec->priv_class) + av_opt_free(avctx->priv_data); + av_opt_free(avctx); + av_freep(&avctx->priv_data); + if (av_codec_is_encoder(avctx->codec)) { + av_freep(&avctx->extradata); +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + av_frame_free(&avctx->coded_frame); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + } + avctx->codec = NULL; + avctx->active_thread_type = 0; + + return 0; +} + +static const char *unknown_if_null(const char *str) +{ + return str ? str : "unknown"; +} + +void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) +{ + const char *codec_type; + const char *codec_name; + const char *profile = NULL; + int64_t bitrate; + int new_line = 0; + AVRational display_aspect_ratio; + const char *separator = enc->dump_separator ? (const char *)enc->dump_separator : ", "; + const char *str; + + if (!buf || buf_size <= 0) + return; + codec_type = av_get_media_type_string(enc->codec_type); + codec_name = avcodec_get_name(enc->codec_id); + profile = avcodec_profile_name(enc->codec_id, enc->profile); + + snprintf(buf, buf_size, "%s: %s", codec_type ? codec_type : "unknown", + codec_name); + buf[0] ^= 'a' ^ 'A'; /* first letter in uppercase */ + + if (enc->codec && strcmp(enc->codec->name, codec_name)) + snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", enc->codec->name); + + if (profile) + snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", profile); + if ( enc->codec_type == AVMEDIA_TYPE_VIDEO + && av_log_get_level() >= AV_LOG_VERBOSE + && enc->refs) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %d reference frame%s", + enc->refs, enc->refs > 1 ? "s" : ""); + + if (enc->codec_tag) + snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s / 0x%04X)", + av_fourcc2str(enc->codec_tag), enc->codec_tag); + + switch (enc->codec_type) { + case AVMEDIA_TYPE_VIDEO: + { + char detail[256] = "("; + + av_strlcat(buf, separator, buf_size); + + snprintf(buf + strlen(buf), buf_size - strlen(buf), + "%s", enc->pix_fmt == AV_PIX_FMT_NONE ? "none" : + unknown_if_null(av_get_pix_fmt_name(enc->pix_fmt))); + if (enc->bits_per_raw_sample && enc->pix_fmt != AV_PIX_FMT_NONE && + enc->bits_per_raw_sample < av_pix_fmt_desc_get(enc->pix_fmt)->comp[0].depth) + av_strlcatf(detail, sizeof(detail), "%d bpc, ", enc->bits_per_raw_sample); + if (enc->color_range != AVCOL_RANGE_UNSPECIFIED && + (str = av_color_range_name(enc->color_range))) + av_strlcatf(detail, sizeof(detail), "%s, ", str); + + if (enc->colorspace != AVCOL_SPC_UNSPECIFIED || + enc->color_primaries != AVCOL_PRI_UNSPECIFIED || + enc->color_trc != AVCOL_TRC_UNSPECIFIED) { + const char *col = unknown_if_null(av_color_space_name(enc->colorspace)); + const char *pri = unknown_if_null(av_color_primaries_name(enc->color_primaries)); + const char *trc = unknown_if_null(av_color_transfer_name(enc->color_trc)); + if (strcmp(col, pri) || strcmp(col, trc)) { + new_line = 1; + av_strlcatf(detail, sizeof(detail), "%s/%s/%s, ", + col, pri, trc); + } else + av_strlcatf(detail, sizeof(detail), "%s, ", col); + } + + if (enc->field_order != AV_FIELD_UNKNOWN) { + const char *field_order = "progressive"; + if (enc->field_order == AV_FIELD_TT) + field_order = "top first"; + else if (enc->field_order == AV_FIELD_BB) + field_order = "bottom first"; + else if (enc->field_order == AV_FIELD_TB) + field_order = "top coded first (swapped)"; + else if (enc->field_order == AV_FIELD_BT) + field_order = "bottom coded first (swapped)"; + + av_strlcatf(detail, sizeof(detail), "%s, ", field_order); + } + + if (av_log_get_level() >= AV_LOG_VERBOSE && + enc->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED && + (str = av_chroma_location_name(enc->chroma_sample_location))) + av_strlcatf(detail, sizeof(detail), "%s, ", str); + + if (strlen(detail) > 1) { + detail[strlen(detail) - 2] = 0; + av_strlcatf(buf, buf_size, "%s)", detail); + } + } + + if (enc->width) { + av_strlcat(buf, new_line ? separator : ", ", buf_size); + + snprintf(buf + strlen(buf), buf_size - strlen(buf), + "%dx%d", + enc->width, enc->height); + + if (av_log_get_level() >= AV_LOG_VERBOSE && + (enc->width != enc->coded_width || + enc->height != enc->coded_height)) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + " (%dx%d)", enc->coded_width, enc->coded_height); + + if (enc->sample_aspect_ratio.num) { + av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den, + enc->width * (int64_t)enc->sample_aspect_ratio.num, + enc->height * (int64_t)enc->sample_aspect_ratio.den, + 1024 * 1024); + snprintf(buf + strlen(buf), buf_size - strlen(buf), + " [SAR %d:%d DAR %d:%d]", + enc->sample_aspect_ratio.num, enc->sample_aspect_ratio.den, + display_aspect_ratio.num, display_aspect_ratio.den); + } + if (av_log_get_level() >= AV_LOG_DEBUG) { + int g = av_gcd(enc->time_base.num, enc->time_base.den); + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %d/%d", + enc->time_base.num / g, enc->time_base.den / g); + } + } + if (encode) { + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", q=%d-%d", enc->qmin, enc->qmax); + } else { + if (enc->properties & FF_CODEC_PROPERTY_CLOSED_CAPTIONS) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", Closed Captions"); + if (enc->properties & FF_CODEC_PROPERTY_LOSSLESS) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", lossless"); + } + break; + case AVMEDIA_TYPE_AUDIO: + av_strlcat(buf, separator, buf_size); + + if (enc->sample_rate) { + snprintf(buf + strlen(buf), buf_size - strlen(buf), + "%d Hz, ", enc->sample_rate); + } + av_get_channel_layout_string(buf + strlen(buf), buf_size - strlen(buf), enc->channels, enc->channel_layout); + if (enc->sample_fmt != AV_SAMPLE_FMT_NONE && + (str = av_get_sample_fmt_name(enc->sample_fmt))) { + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %s", str); + } + if ( enc->bits_per_raw_sample > 0 + && enc->bits_per_raw_sample != av_get_bytes_per_sample(enc->sample_fmt) * 8) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + " (%d bit)", enc->bits_per_raw_sample); + if (av_log_get_level() >= AV_LOG_VERBOSE) { + if (enc->initial_padding) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", delay %d", enc->initial_padding); + if (enc->trailing_padding) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", padding %d", enc->trailing_padding); + } + break; + case AVMEDIA_TYPE_DATA: + if (av_log_get_level() >= AV_LOG_DEBUG) { + int g = av_gcd(enc->time_base.num, enc->time_base.den); + if (g) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %d/%d", + enc->time_base.num / g, enc->time_base.den / g); + } + break; + case AVMEDIA_TYPE_SUBTITLE: + if (enc->width) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %dx%d", enc->width, enc->height); + break; + default: + return; + } + if (encode) { + if (enc->flags & AV_CODEC_FLAG_PASS1) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", pass 1"); + if (enc->flags & AV_CODEC_FLAG_PASS2) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", pass 2"); + } + bitrate = get_bit_rate(enc); + if (bitrate != 0) { + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %"PRId64" kb/s", bitrate / 1000); + } else if (enc->rc_max_rate > 0) { + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", max. %"PRId64" kb/s", enc->rc_max_rate / 1000); + } +} + +int avcodec_is_open(AVCodecContext *s) +{ + return !!s->internal; +} diff -Nru ffmpeg-4.2.2/libavcodec/avcodec.h ffmpeg-4.4/libavcodec/avcodec.h --- ffmpeg-4.2.2/libavcodec/avcodec.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/avcodec.h 2021-04-08 21:28:39.000000000 +0000 @@ -41,6 +41,12 @@ #include "libavutil/pixfmt.h" #include "libavutil/rational.h" +#include "bsf.h" +#include "codec.h" +#include "codec_desc.h" +#include "codec_par.h" +#include "codec_id.h" +#include "packet.h" #include "version.h" /** @@ -92,6 +98,7 @@ * compressed data in an AVPacket. * - For encoding, call avcodec_send_frame() to give the encoder an AVFrame * containing uncompressed audio or video. + * * In both cases, it is recommended that AVPackets and AVFrames are * refcounted, or libavcodec might have to copy the input data. (libavformat * always returns refcounted AVPackets, and av_frame_get_buffer() allocates @@ -102,6 +109,7 @@ * an AVFrame containing uncompressed audio or video data. * - For encoding, call avcodec_receive_packet(). On success, it will return * an AVPacket with a compressed frame. + * * Repeat this call until it returns AVERROR(EAGAIN) or an error. The * AVERROR(EAGAIN) return value means that new input data is required to * return new output. In this case, continue with sending input. For each @@ -196,589 +204,6 @@ * @{ */ - -/** - * Identify the syntax and semantics of the bitstream. - * The principle is roughly: - * Two decoders with the same ID can decode the same streams. - * Two encoders with the same ID can encode compatible streams. - * There may be slight deviations from the principle due to implementation - * details. - * - * If you add a codec ID to this list, add it so that - * 1. no value of an existing codec ID changes (that would break ABI), - * 2. it is as close as possible to similar codecs - * - * After adding new codec IDs, do not forget to add an entry to the codec - * descriptor list and bump libavcodec minor version. - */ -enum AVCodecID { - AV_CODEC_ID_NONE, - - /* video codecs */ - AV_CODEC_ID_MPEG1VIDEO, - AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding - AV_CODEC_ID_H261, - AV_CODEC_ID_H263, - AV_CODEC_ID_RV10, - AV_CODEC_ID_RV20, - AV_CODEC_ID_MJPEG, - AV_CODEC_ID_MJPEGB, - AV_CODEC_ID_LJPEG, - AV_CODEC_ID_SP5X, - AV_CODEC_ID_JPEGLS, - AV_CODEC_ID_MPEG4, - AV_CODEC_ID_RAWVIDEO, - AV_CODEC_ID_MSMPEG4V1, - AV_CODEC_ID_MSMPEG4V2, - AV_CODEC_ID_MSMPEG4V3, - AV_CODEC_ID_WMV1, - AV_CODEC_ID_WMV2, - AV_CODEC_ID_H263P, - AV_CODEC_ID_H263I, - AV_CODEC_ID_FLV1, - AV_CODEC_ID_SVQ1, - AV_CODEC_ID_SVQ3, - AV_CODEC_ID_DVVIDEO, - AV_CODEC_ID_HUFFYUV, - AV_CODEC_ID_CYUV, - AV_CODEC_ID_H264, - AV_CODEC_ID_INDEO3, - AV_CODEC_ID_VP3, - AV_CODEC_ID_THEORA, - AV_CODEC_ID_ASV1, - AV_CODEC_ID_ASV2, - AV_CODEC_ID_FFV1, - AV_CODEC_ID_4XM, - AV_CODEC_ID_VCR1, - AV_CODEC_ID_CLJR, - AV_CODEC_ID_MDEC, - AV_CODEC_ID_ROQ, - AV_CODEC_ID_INTERPLAY_VIDEO, - AV_CODEC_ID_XAN_WC3, - AV_CODEC_ID_XAN_WC4, - AV_CODEC_ID_RPZA, - AV_CODEC_ID_CINEPAK, - AV_CODEC_ID_WS_VQA, - AV_CODEC_ID_MSRLE, - AV_CODEC_ID_MSVIDEO1, - AV_CODEC_ID_IDCIN, - AV_CODEC_ID_8BPS, - AV_CODEC_ID_SMC, - AV_CODEC_ID_FLIC, - AV_CODEC_ID_TRUEMOTION1, - AV_CODEC_ID_VMDVIDEO, - AV_CODEC_ID_MSZH, - AV_CODEC_ID_ZLIB, - AV_CODEC_ID_QTRLE, - AV_CODEC_ID_TSCC, - AV_CODEC_ID_ULTI, - AV_CODEC_ID_QDRAW, - AV_CODEC_ID_VIXL, - AV_CODEC_ID_QPEG, - AV_CODEC_ID_PNG, - AV_CODEC_ID_PPM, - AV_CODEC_ID_PBM, - AV_CODEC_ID_PGM, - AV_CODEC_ID_PGMYUV, - AV_CODEC_ID_PAM, - AV_CODEC_ID_FFVHUFF, - AV_CODEC_ID_RV30, - AV_CODEC_ID_RV40, - AV_CODEC_ID_VC1, - AV_CODEC_ID_WMV3, - AV_CODEC_ID_LOCO, - AV_CODEC_ID_WNV1, - AV_CODEC_ID_AASC, - AV_CODEC_ID_INDEO2, - AV_CODEC_ID_FRAPS, - AV_CODEC_ID_TRUEMOTION2, - AV_CODEC_ID_BMP, - AV_CODEC_ID_CSCD, - AV_CODEC_ID_MMVIDEO, - AV_CODEC_ID_ZMBV, - AV_CODEC_ID_AVS, - AV_CODEC_ID_SMACKVIDEO, - AV_CODEC_ID_NUV, - AV_CODEC_ID_KMVC, - AV_CODEC_ID_FLASHSV, - AV_CODEC_ID_CAVS, - AV_CODEC_ID_JPEG2000, - AV_CODEC_ID_VMNC, - AV_CODEC_ID_VP5, - AV_CODEC_ID_VP6, - AV_CODEC_ID_VP6F, - AV_CODEC_ID_TARGA, - AV_CODEC_ID_DSICINVIDEO, - AV_CODEC_ID_TIERTEXSEQVIDEO, - AV_CODEC_ID_TIFF, - AV_CODEC_ID_GIF, - AV_CODEC_ID_DXA, - AV_CODEC_ID_DNXHD, - AV_CODEC_ID_THP, - AV_CODEC_ID_SGI, - AV_CODEC_ID_C93, - AV_CODEC_ID_BETHSOFTVID, - AV_CODEC_ID_PTX, - AV_CODEC_ID_TXD, - AV_CODEC_ID_VP6A, - AV_CODEC_ID_AMV, - AV_CODEC_ID_VB, - AV_CODEC_ID_PCX, - AV_CODEC_ID_SUNRAST, - AV_CODEC_ID_INDEO4, - AV_CODEC_ID_INDEO5, - AV_CODEC_ID_MIMIC, - AV_CODEC_ID_RL2, - AV_CODEC_ID_ESCAPE124, - AV_CODEC_ID_DIRAC, - AV_CODEC_ID_BFI, - AV_CODEC_ID_CMV, - AV_CODEC_ID_MOTIONPIXELS, - AV_CODEC_ID_TGV, - AV_CODEC_ID_TGQ, - AV_CODEC_ID_TQI, - AV_CODEC_ID_AURA, - AV_CODEC_ID_AURA2, - AV_CODEC_ID_V210X, - AV_CODEC_ID_TMV, - AV_CODEC_ID_V210, - AV_CODEC_ID_DPX, - AV_CODEC_ID_MAD, - AV_CODEC_ID_FRWU, - AV_CODEC_ID_FLASHSV2, - AV_CODEC_ID_CDGRAPHICS, - AV_CODEC_ID_R210, - AV_CODEC_ID_ANM, - AV_CODEC_ID_BINKVIDEO, - AV_CODEC_ID_IFF_ILBM, -#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM - AV_CODEC_ID_KGV1, - AV_CODEC_ID_YOP, - AV_CODEC_ID_VP8, - AV_CODEC_ID_PICTOR, - AV_CODEC_ID_ANSI, - AV_CODEC_ID_A64_MULTI, - AV_CODEC_ID_A64_MULTI5, - AV_CODEC_ID_R10K, - AV_CODEC_ID_MXPEG, - AV_CODEC_ID_LAGARITH, - AV_CODEC_ID_PRORES, - AV_CODEC_ID_JV, - AV_CODEC_ID_DFA, - AV_CODEC_ID_WMV3IMAGE, - AV_CODEC_ID_VC1IMAGE, - AV_CODEC_ID_UTVIDEO, - AV_CODEC_ID_BMV_VIDEO, - AV_CODEC_ID_VBLE, - AV_CODEC_ID_DXTORY, - AV_CODEC_ID_V410, - AV_CODEC_ID_XWD, - AV_CODEC_ID_CDXL, - AV_CODEC_ID_XBM, - AV_CODEC_ID_ZEROCODEC, - AV_CODEC_ID_MSS1, - AV_CODEC_ID_MSA1, - AV_CODEC_ID_TSCC2, - AV_CODEC_ID_MTS2, - AV_CODEC_ID_CLLC, - AV_CODEC_ID_MSS2, - AV_CODEC_ID_VP9, - AV_CODEC_ID_AIC, - AV_CODEC_ID_ESCAPE130, - AV_CODEC_ID_G2M, - AV_CODEC_ID_WEBP, - AV_CODEC_ID_HNM4_VIDEO, - AV_CODEC_ID_HEVC, -#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC - AV_CODEC_ID_FIC, - AV_CODEC_ID_ALIAS_PIX, - AV_CODEC_ID_BRENDER_PIX, - AV_CODEC_ID_PAF_VIDEO, - AV_CODEC_ID_EXR, - AV_CODEC_ID_VP7, - AV_CODEC_ID_SANM, - AV_CODEC_ID_SGIRLE, - AV_CODEC_ID_MVC1, - AV_CODEC_ID_MVC2, - AV_CODEC_ID_HQX, - AV_CODEC_ID_TDSC, - AV_CODEC_ID_HQ_HQA, - AV_CODEC_ID_HAP, - AV_CODEC_ID_DDS, - AV_CODEC_ID_DXV, - AV_CODEC_ID_SCREENPRESSO, - AV_CODEC_ID_RSCC, - AV_CODEC_ID_AVS2, - - AV_CODEC_ID_Y41P = 0x8000, - AV_CODEC_ID_AVRP, - AV_CODEC_ID_012V, - AV_CODEC_ID_AVUI, - AV_CODEC_ID_AYUV, - AV_CODEC_ID_TARGA_Y216, - AV_CODEC_ID_V308, - AV_CODEC_ID_V408, - AV_CODEC_ID_YUV4, - AV_CODEC_ID_AVRN, - AV_CODEC_ID_CPIA, - AV_CODEC_ID_XFACE, - AV_CODEC_ID_SNOW, - AV_CODEC_ID_SMVJPEG, - AV_CODEC_ID_APNG, - AV_CODEC_ID_DAALA, - AV_CODEC_ID_CFHD, - AV_CODEC_ID_TRUEMOTION2RT, - AV_CODEC_ID_M101, - AV_CODEC_ID_MAGICYUV, - AV_CODEC_ID_SHEERVIDEO, - AV_CODEC_ID_YLC, - AV_CODEC_ID_PSD, - AV_CODEC_ID_PIXLET, - AV_CODEC_ID_SPEEDHQ, - AV_CODEC_ID_FMVC, - AV_CODEC_ID_SCPR, - AV_CODEC_ID_CLEARVIDEO, - AV_CODEC_ID_XPM, - AV_CODEC_ID_AV1, - AV_CODEC_ID_BITPACKED, - AV_CODEC_ID_MSCC, - AV_CODEC_ID_SRGC, - AV_CODEC_ID_SVG, - AV_CODEC_ID_GDV, - AV_CODEC_ID_FITS, - AV_CODEC_ID_IMM4, - AV_CODEC_ID_PROSUMER, - AV_CODEC_ID_MWSC, - AV_CODEC_ID_WCMV, - AV_CODEC_ID_RASC, - AV_CODEC_ID_HYMT, - AV_CODEC_ID_ARBC, - AV_CODEC_ID_AGM, - AV_CODEC_ID_LSCR, - AV_CODEC_ID_VP4, - - /* various PCM "codecs" */ - AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs - AV_CODEC_ID_PCM_S16LE = 0x10000, - AV_CODEC_ID_PCM_S16BE, - AV_CODEC_ID_PCM_U16LE, - AV_CODEC_ID_PCM_U16BE, - AV_CODEC_ID_PCM_S8, - AV_CODEC_ID_PCM_U8, - AV_CODEC_ID_PCM_MULAW, - AV_CODEC_ID_PCM_ALAW, - AV_CODEC_ID_PCM_S32LE, - AV_CODEC_ID_PCM_S32BE, - AV_CODEC_ID_PCM_U32LE, - AV_CODEC_ID_PCM_U32BE, - AV_CODEC_ID_PCM_S24LE, - AV_CODEC_ID_PCM_S24BE, - AV_CODEC_ID_PCM_U24LE, - AV_CODEC_ID_PCM_U24BE, - AV_CODEC_ID_PCM_S24DAUD, - AV_CODEC_ID_PCM_ZORK, - AV_CODEC_ID_PCM_S16LE_PLANAR, - AV_CODEC_ID_PCM_DVD, - AV_CODEC_ID_PCM_F32BE, - AV_CODEC_ID_PCM_F32LE, - AV_CODEC_ID_PCM_F64BE, - AV_CODEC_ID_PCM_F64LE, - AV_CODEC_ID_PCM_BLURAY, - AV_CODEC_ID_PCM_LXF, - AV_CODEC_ID_S302M, - AV_CODEC_ID_PCM_S8_PLANAR, - AV_CODEC_ID_PCM_S24LE_PLANAR, - AV_CODEC_ID_PCM_S32LE_PLANAR, - AV_CODEC_ID_PCM_S16BE_PLANAR, - - AV_CODEC_ID_PCM_S64LE = 0x10800, - AV_CODEC_ID_PCM_S64BE, - AV_CODEC_ID_PCM_F16LE, - AV_CODEC_ID_PCM_F24LE, - AV_CODEC_ID_PCM_VIDC, - - /* various ADPCM codecs */ - AV_CODEC_ID_ADPCM_IMA_QT = 0x11000, - AV_CODEC_ID_ADPCM_IMA_WAV, - AV_CODEC_ID_ADPCM_IMA_DK3, - AV_CODEC_ID_ADPCM_IMA_DK4, - AV_CODEC_ID_ADPCM_IMA_WS, - AV_CODEC_ID_ADPCM_IMA_SMJPEG, - AV_CODEC_ID_ADPCM_MS, - AV_CODEC_ID_ADPCM_4XM, - AV_CODEC_ID_ADPCM_XA, - AV_CODEC_ID_ADPCM_ADX, - AV_CODEC_ID_ADPCM_EA, - AV_CODEC_ID_ADPCM_G726, - AV_CODEC_ID_ADPCM_CT, - AV_CODEC_ID_ADPCM_SWF, - AV_CODEC_ID_ADPCM_YAMAHA, - AV_CODEC_ID_ADPCM_SBPRO_4, - AV_CODEC_ID_ADPCM_SBPRO_3, - AV_CODEC_ID_ADPCM_SBPRO_2, - AV_CODEC_ID_ADPCM_THP, - AV_CODEC_ID_ADPCM_IMA_AMV, - AV_CODEC_ID_ADPCM_EA_R1, - AV_CODEC_ID_ADPCM_EA_R3, - AV_CODEC_ID_ADPCM_EA_R2, - AV_CODEC_ID_ADPCM_IMA_EA_SEAD, - AV_CODEC_ID_ADPCM_IMA_EA_EACS, - AV_CODEC_ID_ADPCM_EA_XAS, - AV_CODEC_ID_ADPCM_EA_MAXIS_XA, - AV_CODEC_ID_ADPCM_IMA_ISS, - AV_CODEC_ID_ADPCM_G722, - AV_CODEC_ID_ADPCM_IMA_APC, - AV_CODEC_ID_ADPCM_VIMA, - - AV_CODEC_ID_ADPCM_AFC = 0x11800, - AV_CODEC_ID_ADPCM_IMA_OKI, - AV_CODEC_ID_ADPCM_DTK, - AV_CODEC_ID_ADPCM_IMA_RAD, - AV_CODEC_ID_ADPCM_G726LE, - AV_CODEC_ID_ADPCM_THP_LE, - AV_CODEC_ID_ADPCM_PSX, - AV_CODEC_ID_ADPCM_AICA, - AV_CODEC_ID_ADPCM_IMA_DAT4, - AV_CODEC_ID_ADPCM_MTAF, - AV_CODEC_ID_ADPCM_AGM, - - /* AMR */ - AV_CODEC_ID_AMR_NB = 0x12000, - AV_CODEC_ID_AMR_WB, - - /* RealAudio codecs*/ - AV_CODEC_ID_RA_144 = 0x13000, - AV_CODEC_ID_RA_288, - - /* various DPCM codecs */ - AV_CODEC_ID_ROQ_DPCM = 0x14000, - AV_CODEC_ID_INTERPLAY_DPCM, - AV_CODEC_ID_XAN_DPCM, - AV_CODEC_ID_SOL_DPCM, - - AV_CODEC_ID_SDX2_DPCM = 0x14800, - AV_CODEC_ID_GREMLIN_DPCM, - - /* audio codecs */ - AV_CODEC_ID_MP2 = 0x15000, - AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 - AV_CODEC_ID_AAC, - AV_CODEC_ID_AC3, - AV_CODEC_ID_DTS, - AV_CODEC_ID_VORBIS, - AV_CODEC_ID_DVAUDIO, - AV_CODEC_ID_WMAV1, - AV_CODEC_ID_WMAV2, - AV_CODEC_ID_MACE3, - AV_CODEC_ID_MACE6, - AV_CODEC_ID_VMDAUDIO, - AV_CODEC_ID_FLAC, - AV_CODEC_ID_MP3ADU, - AV_CODEC_ID_MP3ON4, - AV_CODEC_ID_SHORTEN, - AV_CODEC_ID_ALAC, - AV_CODEC_ID_WESTWOOD_SND1, - AV_CODEC_ID_GSM, ///< as in Berlin toast format - AV_CODEC_ID_QDM2, - AV_CODEC_ID_COOK, - AV_CODEC_ID_TRUESPEECH, - AV_CODEC_ID_TTA, - AV_CODEC_ID_SMACKAUDIO, - AV_CODEC_ID_QCELP, - AV_CODEC_ID_WAVPACK, - AV_CODEC_ID_DSICINAUDIO, - AV_CODEC_ID_IMC, - AV_CODEC_ID_MUSEPACK7, - AV_CODEC_ID_MLP, - AV_CODEC_ID_GSM_MS, /* as found in WAV */ - AV_CODEC_ID_ATRAC3, - AV_CODEC_ID_APE, - AV_CODEC_ID_NELLYMOSER, - AV_CODEC_ID_MUSEPACK8, - AV_CODEC_ID_SPEEX, - AV_CODEC_ID_WMAVOICE, - AV_CODEC_ID_WMAPRO, - AV_CODEC_ID_WMALOSSLESS, - AV_CODEC_ID_ATRAC3P, - AV_CODEC_ID_EAC3, - AV_CODEC_ID_SIPR, - AV_CODEC_ID_MP1, - AV_CODEC_ID_TWINVQ, - AV_CODEC_ID_TRUEHD, - AV_CODEC_ID_MP4ALS, - AV_CODEC_ID_ATRAC1, - AV_CODEC_ID_BINKAUDIO_RDFT, - AV_CODEC_ID_BINKAUDIO_DCT, - AV_CODEC_ID_AAC_LATM, - AV_CODEC_ID_QDMC, - AV_CODEC_ID_CELT, - AV_CODEC_ID_G723_1, - AV_CODEC_ID_G729, - AV_CODEC_ID_8SVX_EXP, - AV_CODEC_ID_8SVX_FIB, - AV_CODEC_ID_BMV_AUDIO, - AV_CODEC_ID_RALF, - AV_CODEC_ID_IAC, - AV_CODEC_ID_ILBC, - AV_CODEC_ID_OPUS, - AV_CODEC_ID_COMFORT_NOISE, - AV_CODEC_ID_TAK, - AV_CODEC_ID_METASOUND, - AV_CODEC_ID_PAF_AUDIO, - AV_CODEC_ID_ON2AVC, - AV_CODEC_ID_DSS_SP, - AV_CODEC_ID_CODEC2, - - AV_CODEC_ID_FFWAVESYNTH = 0x15800, - AV_CODEC_ID_SONIC, - AV_CODEC_ID_SONIC_LS, - AV_CODEC_ID_EVRC, - AV_CODEC_ID_SMV, - AV_CODEC_ID_DSD_LSBF, - AV_CODEC_ID_DSD_MSBF, - AV_CODEC_ID_DSD_LSBF_PLANAR, - AV_CODEC_ID_DSD_MSBF_PLANAR, - AV_CODEC_ID_4GV, - AV_CODEC_ID_INTERPLAY_ACM, - AV_CODEC_ID_XMA1, - AV_CODEC_ID_XMA2, - AV_CODEC_ID_DST, - AV_CODEC_ID_ATRAC3AL, - AV_CODEC_ID_ATRAC3PAL, - AV_CODEC_ID_DOLBY_E, - AV_CODEC_ID_APTX, - AV_CODEC_ID_APTX_HD, - AV_CODEC_ID_SBC, - AV_CODEC_ID_ATRAC9, - AV_CODEC_ID_HCOM, - - /* subtitle codecs */ - AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. - AV_CODEC_ID_DVD_SUBTITLE = 0x17000, - AV_CODEC_ID_DVB_SUBTITLE, - AV_CODEC_ID_TEXT, ///< raw UTF-8 text - AV_CODEC_ID_XSUB, - AV_CODEC_ID_SSA, - AV_CODEC_ID_MOV_TEXT, - AV_CODEC_ID_HDMV_PGS_SUBTITLE, - AV_CODEC_ID_DVB_TELETEXT, - AV_CODEC_ID_SRT, - - AV_CODEC_ID_MICRODVD = 0x17800, - AV_CODEC_ID_EIA_608, - AV_CODEC_ID_JACOSUB, - AV_CODEC_ID_SAMI, - AV_CODEC_ID_REALTEXT, - AV_CODEC_ID_STL, - AV_CODEC_ID_SUBVIEWER1, - AV_CODEC_ID_SUBVIEWER, - AV_CODEC_ID_SUBRIP, - AV_CODEC_ID_WEBVTT, - AV_CODEC_ID_MPL2, - AV_CODEC_ID_VPLAYER, - AV_CODEC_ID_PJS, - AV_CODEC_ID_ASS, - AV_CODEC_ID_HDMV_TEXT_SUBTITLE, - AV_CODEC_ID_TTML, - AV_CODEC_ID_ARIB_CAPTION, - - /* other specific kind of codecs (generally used for attachments) */ - AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. - AV_CODEC_ID_TTF = 0x18000, - - AV_CODEC_ID_SCTE_35, ///< Contain timestamp estimated through PCR of program stream. - AV_CODEC_ID_BINTEXT = 0x18800, - AV_CODEC_ID_XBIN, - AV_CODEC_ID_IDF, - AV_CODEC_ID_OTF, - AV_CODEC_ID_SMPTE_KLV, - AV_CODEC_ID_DVD_NAV, - AV_CODEC_ID_TIMED_ID3, - AV_CODEC_ID_BIN_DATA, - - - AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it - - AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS - * stream (only used by libavformat) */ - AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems - * stream (only used by libavformat) */ - AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. - AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket -}; - -/** - * This struct describes the properties of a single codec described by an - * AVCodecID. - * @see avcodec_descriptor_get() - */ -typedef struct AVCodecDescriptor { - enum AVCodecID id; - enum AVMediaType type; - /** - * Name of the codec described by this descriptor. It is non-empty and - * unique for each codec descriptor. It should contain alphanumeric - * characters and '_' only. - */ - const char *name; - /** - * A more descriptive name for this codec. May be NULL. - */ - const char *long_name; - /** - * Codec properties, a combination of AV_CODEC_PROP_* flags. - */ - int props; - /** - * MIME type(s) associated with the codec. - * May be NULL; if not, a NULL-terminated array of MIME types. - * The first item is always non-NULL and is the preferred MIME type. - */ - const char *const *mime_types; - /** - * If non-NULL, an array of profiles recognized for this codec. - * Terminated with FF_PROFILE_UNKNOWN. - */ - const struct AVProfile *profiles; -} AVCodecDescriptor; - -/** - * Codec uses only intra compression. - * Video and audio codecs only. - */ -#define AV_CODEC_PROP_INTRA_ONLY (1 << 0) -/** - * Codec supports lossy compression. Audio and video codecs only. - * @note a codec may support both lossy and lossless - * compression modes - */ -#define AV_CODEC_PROP_LOSSY (1 << 1) -/** - * Codec supports lossless compression. Audio and video codecs only. - */ -#define AV_CODEC_PROP_LOSSLESS (1 << 2) -/** - * Codec supports frame reordering. That is, the coded order (the order in which - * the encoded packets are output by the encoders / stored / input to the - * decoders) may be different from the presentation order of the corresponding - * frames. - * - * For codecs that do not have this property set, PTS and DTS should always be - * equal. - */ -#define AV_CODEC_PROP_REORDER (1 << 3) -/** - * Subtitle codec is bitmap based - * Decoded AVSubtitle data can be read from the AVSubtitleRect->pict field. - */ -#define AV_CODEC_PROP_BITMAP_SUB (1 << 16) -/** - * Subtitle codec is text based. - * Decoded AVSubtitle data can be read from the AVSubtitleRect->ass field. - */ -#define AV_CODEC_PROP_TEXT_SUB (1 << 17) - /** * @ingroup lavc_decoding * Required number of additionally allocated bytes at the end of the input bitstream for decoding. @@ -969,127 +394,27 @@ /* /Fx */ /* codec capabilities */ +/* Exported side data. + These flags can be passed in AVCodecContext.export_side_data before initialization. +*/ /** - * Decoder can use draw_horiz_band callback. - */ -#define AV_CODEC_CAP_DRAW_HORIZ_BAND (1 << 0) -/** - * Codec uses get_buffer() for allocating buffers and supports custom allocators. - * If not set, it might not use get_buffer() at all or use operations that - * assume the buffer was allocated by avcodec_default_get_buffer. - */ -#define AV_CODEC_CAP_DR1 (1 << 1) -#define AV_CODEC_CAP_TRUNCATED (1 << 3) -/** - * Encoder or decoder requires flushing with NULL input at the end in order to - * give the complete and correct output. - * - * NOTE: If this flag is not set, the codec is guaranteed to never be fed with - * with NULL data. The user can still send NULL data to the public encode - * or decode function, but libavcodec will not pass it along to the codec - * unless this flag is set. - * - * Decoders: - * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, - * avpkt->size=0 at the end to get the delayed data until the decoder no longer - * returns frames. - * - * Encoders: - * The encoder needs to be fed with NULL data at the end of encoding until the - * encoder no longer returns data. - * - * NOTE: For encoders implementing the AVCodec.encode2() function, setting this - * flag also means that the encoder must set the pts and duration for - * each output packet. If this flag is not set, the pts and duration will - * be determined by libavcodec from the input frame. - */ -#define AV_CODEC_CAP_DELAY (1 << 5) -/** - * Codec can be fed a final frame with a smaller size. - * This can be used to prevent truncation of the last audio samples. - */ -#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6) - -/** - * Codec can output multiple frames per AVPacket - * Normally demuxers return one frame at a time, demuxers which do not do - * are connected to a parser to split what they return into proper frames. - * This flag is reserved to the very rare category of codecs which have a - * bitstream that cannot be split into frames without timeconsuming - * operations like full decoding. Demuxers carrying such bitstreams thus - * may return multiple frames in a packet. This has many disadvantages like - * prohibiting stream copy in many cases thus it should only be considered - * as a last resort. - */ -#define AV_CODEC_CAP_SUBFRAMES (1 << 8) -/** - * Codec is experimental and is thus avoided in favor of non experimental - * encoders - */ -#define AV_CODEC_CAP_EXPERIMENTAL (1 << 9) -/** - * Codec should fill in channel configuration and samplerate instead of container - */ -#define AV_CODEC_CAP_CHANNEL_CONF (1 << 10) -/** - * Codec supports frame-level multithreading. - */ -#define AV_CODEC_CAP_FRAME_THREADS (1 << 12) -/** - * Codec supports slice-based (or partition-based) multithreading. - */ -#define AV_CODEC_CAP_SLICE_THREADS (1 << 13) -/** - * Codec supports changed parameters at any point. - */ -#define AV_CODEC_CAP_PARAM_CHANGE (1 << 14) -/** - * Codec supports avctx->thread_count == 0 (auto). - */ -#define AV_CODEC_CAP_AUTO_THREADS (1 << 15) -/** - * Audio encoder supports receiving a different number of samples in each call. - */ -#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16) -/** - * Decoder is not a preferred choice for probing. - * This indicates that the decoder is not a good choice for probing. - * It could for example be an expensive to spin up hardware decoder, - * or it could simply not provide a lot of useful information about - * the stream. - * A decoder marked with this flag should only be used as last resort - * choice for probing. - */ -#define AV_CODEC_CAP_AVOID_PROBING (1 << 17) -/** - * Codec is intra only. - */ -#define AV_CODEC_CAP_INTRA_ONLY 0x40000000 -/** - * Codec is lossless. + * Export motion vectors through frame side data */ -#define AV_CODEC_CAP_LOSSLESS 0x80000000 - +#define AV_CODEC_EXPORT_DATA_MVS (1 << 0) /** - * Codec is backed by a hardware implementation. Typically used to - * identify a non-hwaccel hardware decoder. For information about hwaccels, use - * avcodec_get_hw_config() instead. + * Export encoder Producer Reference Time through packet side data */ -#define AV_CODEC_CAP_HARDWARE (1 << 18) - +#define AV_CODEC_EXPORT_DATA_PRFT (1 << 1) /** - * Codec is potentially backed by a hardware implementation, but not - * necessarily. This is used instead of AV_CODEC_CAP_HARDWARE, if the - * implementation provides some sort of internal fallback. + * Decoding only. + * Export the AVVideoEncParams structure through frame side data. */ -#define AV_CODEC_CAP_HYBRID (1 << 19) - +#define AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS (1 << 2) /** - * This codec takes the reordered_opaque field from input AVFrames - * and returns it in the corresponding field in AVCodecContext after - * encoding. + * Decoding only. + * Do not apply film grain, export it instead. */ -#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE (1 << 20) +#define AV_CODEC_EXPORT_DATA_FILM_GRAIN (1 << 3) /** * Pan Scan area. @@ -1171,384 +496,30 @@ } AVCPBProperties; /** - * The decoder will keep a reference to the frame and may reuse it later. - */ -#define AV_GET_BUFFER_FLAG_REF (1 << 0) - -/** - * @defgroup lavc_packet AVPacket - * - * Types and functions for working with AVPacket. - * @{ - */ -enum AVPacketSideDataType { - /** - * An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE - * bytes worth of palette. This side data signals that a new palette is - * present. - */ - AV_PKT_DATA_PALETTE, - - /** - * The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format - * that the extradata buffer was changed and the receiving side should - * act upon it appropriately. The new extradata is embedded in the side - * data buffer and should be immediately used for processing the current - * frame or packet. - */ - AV_PKT_DATA_NEW_EXTRADATA, - - /** - * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows: - * @code - * u32le param_flags - * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) - * s32le channel_count - * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) - * u64le channel_layout - * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) - * s32le sample_rate - * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) - * s32le width - * s32le height - * @endcode - */ - AV_PKT_DATA_PARAM_CHANGE, - - /** - * An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of - * structures with info about macroblocks relevant to splitting the - * packet into smaller packets on macroblock edges (e.g. as for RFC 2190). - * That is, it does not necessarily contain info about all macroblocks, - * as long as the distance between macroblocks in the info is smaller - * than the target payload size. - * Each MB info structure is 12 bytes, and is laid out as follows: - * @code - * u32le bit offset from the start of the packet - * u8 current quantizer at the start of the macroblock - * u8 GOB number - * u16le macroblock address within the GOB - * u8 horizontal MV predictor - * u8 vertical MV predictor - * u8 horizontal MV predictor for block number 3 - * u8 vertical MV predictor for block number 3 - * @endcode - */ - AV_PKT_DATA_H263_MB_INFO, - - /** - * This side data should be associated with an audio stream and contains - * ReplayGain information in form of the AVReplayGain struct. - */ - AV_PKT_DATA_REPLAYGAIN, - - /** - * This side data contains a 3x3 transformation matrix describing an affine - * transformation that needs to be applied to the decoded video frames for - * correct presentation. - * - * See libavutil/display.h for a detailed description of the data. - */ - AV_PKT_DATA_DISPLAYMATRIX, - - /** - * This side data should be associated with a video stream and contains - * Stereoscopic 3D information in form of the AVStereo3D struct. - */ - AV_PKT_DATA_STEREO3D, - - /** - * This side data should be associated with an audio stream and corresponds - * to enum AVAudioServiceType. - */ - AV_PKT_DATA_AUDIO_SERVICE_TYPE, - - /** - * This side data contains quality related information from the encoder. - * @code - * u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad). - * u8 picture type - * u8 error count - * u16 reserved - * u64le[error count] sum of squared differences between encoder in and output - * @endcode - */ - AV_PKT_DATA_QUALITY_STATS, - - /** - * This side data contains an integer value representing the stream index - * of a "fallback" track. A fallback track indicates an alternate - * track to use when the current track can not be decoded for some reason. - * e.g. no decoder available for codec. - */ - AV_PKT_DATA_FALLBACK_TRACK, - - /** - * This side data corresponds to the AVCPBProperties struct. - */ - AV_PKT_DATA_CPB_PROPERTIES, - - /** - * Recommmends skipping the specified number of samples - * @code - * u32le number of samples to skip from start of this packet - * u32le number of samples to skip from end of this packet - * u8 reason for start skip - * u8 reason for end skip (0=padding silence, 1=convergence) - * @endcode - */ - AV_PKT_DATA_SKIP_SAMPLES, - - /** - * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that - * the packet may contain "dual mono" audio specific to Japanese DTV - * and if it is true, recommends only the selected channel to be used. - * @code - * u8 selected channels (0=mail/left, 1=sub/right, 2=both) - * @endcode - */ - AV_PKT_DATA_JP_DUALMONO, - - /** - * A list of zero terminated key/value strings. There is no end marker for - * the list, so it is required to rely on the side data size to stop. - */ - AV_PKT_DATA_STRINGS_METADATA, - - /** - * Subtitle event position - * @code - * u32le x1 - * u32le y1 - * u32le x2 - * u32le y2 - * @endcode - */ - AV_PKT_DATA_SUBTITLE_POSITION, - - /** - * Data found in BlockAdditional element of matroska container. There is - * no end marker for the data, so it is required to rely on the side data - * size to recognize the end. 8 byte id (as found in BlockAddId) followed - * by data. - */ - AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, - - /** - * The optional first identifier line of a WebVTT cue. - */ - AV_PKT_DATA_WEBVTT_IDENTIFIER, - - /** - * The optional settings (rendering instructions) that immediately - * follow the timestamp specifier of a WebVTT cue. - */ - AV_PKT_DATA_WEBVTT_SETTINGS, - - /** - * A list of zero terminated key/value strings. There is no end marker for - * the list, so it is required to rely on the side data size to stop. This - * side data includes updated metadata which appeared in the stream. - */ - AV_PKT_DATA_METADATA_UPDATE, - - /** - * MPEGTS stream ID as uint8_t, this is required to pass the stream ID - * information from the demuxer to the corresponding muxer. - */ - AV_PKT_DATA_MPEGTS_STREAM_ID, - - /** - * Mastering display metadata (based on SMPTE-2086:2014). This metadata - * should be associated with a video stream and contains data in the form - * of the AVMasteringDisplayMetadata struct. - */ - AV_PKT_DATA_MASTERING_DISPLAY_METADATA, - - /** - * This side data should be associated with a video stream and corresponds - * to the AVSphericalMapping structure. - */ - AV_PKT_DATA_SPHERICAL, - - /** - * Content light level (based on CTA-861.3). This metadata should be - * associated with a video stream and contains data in the form of the - * AVContentLightMetadata struct. - */ - AV_PKT_DATA_CONTENT_LIGHT_LEVEL, - - /** - * ATSC A53 Part 4 Closed Captions. This metadata should be associated with - * a video stream. A53 CC bitstream is stored as uint8_t in AVPacketSideData.data. - * The number of bytes of CC data is AVPacketSideData.size. - */ - AV_PKT_DATA_A53_CC, - - /** - * This side data is encryption initialization data. - * The format is not part of ABI, use av_encryption_init_info_* methods to - * access. - */ - AV_PKT_DATA_ENCRYPTION_INIT_INFO, - - /** - * This side data contains encryption info for how to decrypt the packet. - * The format is not part of ABI, use av_encryption_info_* methods to access. - */ - AV_PKT_DATA_ENCRYPTION_INFO, - - /** - * Active Format Description data consisting of a single byte as specified - * in ETSI TS 101 154 using AVActiveFormatDescription enum. - */ - AV_PKT_DATA_AFD, - - /** - * The number of side data types. - * This is not part of the public API/ABI in the sense that it may - * change when new side data types are added. - * This must stay the last enum value. - * If its value becomes huge, some code using it - * needs to be updated as it assumes it to be smaller than other limits. - */ - AV_PKT_DATA_NB -}; - -#define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED - -typedef struct AVPacketSideData { - uint8_t *data; - int size; - enum AVPacketSideDataType type; -} AVPacketSideData; - -/** - * This structure stores compressed data. It is typically exported by demuxers - * and then passed as input to decoders, or received as output from encoders and - * then passed to muxers. - * - * For video, it should typically contain one compressed frame. For audio it may - * contain several compressed frames. Encoders are allowed to output empty - * packets, with no compressed data, containing only side data - * (e.g. to update some stream parameters at the end of encoding). - * - * AVPacket is one of the few structs in FFmpeg, whose size is a part of public - * ABI. Thus it may be allocated on stack and no new fields can be added to it - * without libavcodec and libavformat major bump. - * - * The semantics of data ownership depends on the buf field. - * If it is set, the packet data is dynamically allocated and is - * valid indefinitely until a call to av_packet_unref() reduces the - * reference count to 0. - * - * If the buf field is not set av_packet_ref() would make a copy instead - * of increasing the reference count. - * - * The side data is always allocated with av_malloc(), copied by - * av_packet_ref() and freed by av_packet_unref(). - * - * @see av_packet_ref - * @see av_packet_unref + * This structure supplies correlation between a packet timestamp and a wall clock + * production time. The definition follows the Producer Reference Time ('prft') + * as defined in ISO/IEC 14496-12 */ -typedef struct AVPacket { - /** - * A reference to the reference-counted buffer where the packet data is - * stored. - * May be NULL, then the packet data is not reference-counted. - */ - AVBufferRef *buf; - /** - * Presentation timestamp in AVStream->time_base units; the time at which - * the decompressed packet will be presented to the user. - * Can be AV_NOPTS_VALUE if it is not stored in the file. - * pts MUST be larger or equal to dts as presentation cannot happen before - * decompression, unless one wants to view hex dumps. Some formats misuse - * the terms dts and pts/cts to mean something different. Such timestamps - * must be converted to true pts/dts before they are stored in AVPacket. - */ - int64_t pts; - /** - * Decompression timestamp in AVStream->time_base units; the time at which - * the packet is decompressed. - * Can be AV_NOPTS_VALUE if it is not stored in the file. - */ - int64_t dts; - uint8_t *data; - int size; - int stream_index; - /** - * A combination of AV_PKT_FLAG values - */ - int flags; - /** - * Additional packet data that can be provided by the container. - * Packet can contain several types of side information. - */ - AVPacketSideData *side_data; - int side_data_elems; - +typedef struct AVProducerReferenceTime { /** - * Duration of this packet in AVStream->time_base units, 0 if unknown. - * Equals next_pts - this_pts in presentation order. + * A UTC timestamp, in microseconds, since Unix epoch (e.g, av_gettime()). */ - int64_t duration; - - int64_t pos; ///< byte position in stream, -1 if unknown + int64_t wallclock; + int flags; +} AVProducerReferenceTime; -#if FF_API_CONVERGENCE_DURATION - /** - * @deprecated Same as the duration field, but as int64_t. This was required - * for Matroska subtitles, whose duration values could overflow when the - * duration field was still an int. - */ - attribute_deprecated - int64_t convergence_duration; -#endif -} AVPacket; -#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe -#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted -/** - * Flag is used to discard packets which are required to maintain valid - * decoder state but are not required for output and should be dropped - * after decoding. - **/ -#define AV_PKT_FLAG_DISCARD 0x0004 -/** - * The packet comes from a trusted source. - * - * Otherwise-unsafe constructs such as arbitrary pointers to data - * outside the packet may be followed. - */ -#define AV_PKT_FLAG_TRUSTED 0x0008 /** - * Flag is used to indicate packets that contain frames that can - * be discarded by the decoder. I.e. Non-reference frames. + * The decoder will keep a reference to the frame and may reuse it later. */ -#define AV_PKT_FLAG_DISPOSABLE 0x0010 - +#define AV_GET_BUFFER_FLAG_REF (1 << 0) -enum AVSideDataParamChangeFlags { - AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, - AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002, - AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004, - AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008, -}; /** - * @} + * The encoder will keep a reference to the packet and may reuse it later. */ +#define AV_GET_ENCODE_BUFFER_FLAG_REF (1 << 0) struct AVCodecInternal; -enum AVFieldOrder { - AV_FIELD_UNKNOWN, - AV_FIELD_PROGRESSIVE, - AV_FIELD_TT, //< Top coded_first, top displayed first - AV_FIELD_BB, //< Bottom coded first, bottom displayed first - AV_FIELD_TB, //< Top coded first, bottom displayed first - AV_FIELD_BT, //< Bottom coded first, top displayed first -}; - /** * main external API structure. * New fields can be added to the end with minor version bumps. @@ -2353,9 +1324,9 @@ * * Some decoders do not support linesizes changing between frames. * - * If frame multithreading is used and thread_safe_callbacks is set, - * this callback may be called from a different thread, but not from more - * than one at once. Does not need to be reentrant. + * If frame multithreading is used, this callback may be called from a + * different thread, but not from more than one at once. Does not need to be + * reentrant. * * @see avcodec_align_dimensions2() * @@ -2379,6 +1350,7 @@ */ int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags); +#if FF_API_OLD_ENCDEC /** * If non-zero, the decoded audio and video frames returned from * avcodec_decode_video2() and avcodec_decode_audio4() are reference-counted @@ -2394,6 +1366,7 @@ */ attribute_deprecated int refcounted_frames; +#endif /* - encoding parameters */ float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0) @@ -2653,42 +1626,20 @@ #define FF_DEBUG_BITSTREAM 4 #define FF_DEBUG_MB_TYPE 8 #define FF_DEBUG_QP 16 -#if FF_API_DEBUG_MV -/** - * @deprecated this option does nothing - */ -#define FF_DEBUG_MV 32 -#endif #define FF_DEBUG_DCT_COEFF 0x00000040 #define FF_DEBUG_SKIP 0x00000080 #define FF_DEBUG_STARTCODE 0x00000100 #define FF_DEBUG_ER 0x00000400 #define FF_DEBUG_MMCO 0x00000800 #define FF_DEBUG_BUGS 0x00001000 -#if FF_API_DEBUG_MV -#define FF_DEBUG_VIS_QP 0x00002000 -#define FF_DEBUG_VIS_MB_TYPE 0x00004000 -#endif #define FF_DEBUG_BUFFERS 0x00008000 #define FF_DEBUG_THREADS 0x00010000 #define FF_DEBUG_GREEN_MD 0x00800000 #define FF_DEBUG_NOMC 0x01000000 -#if FF_API_DEBUG_MV - /** - * debug - * - encoding: Set by user. - * - decoding: Set by user. - */ - int debug_mv; -#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 // visualize forward predicted MVs of P-frames -#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 // visualize forward predicted MVs of B-frames -#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 // visualize backward predicted MVs of B-frames -#endif - /** * Error recognition; may misdetect some more or less valid parts as errors. - * - encoding: unused + * - encoding: Set by user. * - decoding: Set by user. */ int err_recognition; @@ -2795,14 +1746,12 @@ */ int bits_per_raw_sample; -#if FF_API_LOWRES /** * low resolution decoding, 1-> 1/2 size, 2->1/4 size * - encoding: unused * - decoding: Set by user. */ int lowres; -#endif #if FF_API_CODED_FRAME /** @@ -2842,6 +1791,7 @@ */ int active_thread_type; +#if FF_API_THREAD_SAFE_CALLBACKS /** * Set by the client if its custom get_buffer() callback can be called * synchronously from another thread, which allows faster multithreaded decoding. @@ -2849,8 +1799,18 @@ * Ignored if the default get_buffer() is used. * - encoding: Set by user. * - decoding: Set by user. + * + * @deprecated the custom get_buffer2() callback should always be + * thread-safe. Thread-unsafe get_buffer2() implementations will be + * invalid starting with LIBAVCODEC_VERSION_MAJOR=60; in other words, + * libavcodec will behave as if this field was always set to 1. + * Callers that want to be forward compatible with future libavcodec + * versions should wrap access to this field in + * #if LIBAVCODEC_VERSION_MAJOR < 60 */ + attribute_deprecated int thread_safe_callbacks; +#endif /** * The codec may call this to execute several independent things. @@ -2988,6 +1948,9 @@ #define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 #define FF_PROFILE_HEVC_REXT 4 +#define FF_PROFILE_VVC_MAIN_10 1 +#define FF_PROFILE_VVC_MAIN_10_444 33 + #define FF_PROFILE_AV1_MAIN 0 #define FF_PROFILE_AV1_HIGH 1 #define FF_PROFILE_AV1_PROFESSIONAL 2 @@ -3010,6 +1973,9 @@ #define FF_PROFILE_ARIB_PROFILE_A 0 #define FF_PROFILE_ARIB_PROFILE_C 1 +#define FF_PROFILE_KLVA_SYNC 0 +#define FF_PROFILE_KLVA_ASYNC 1 + /** * level * - encoding: Set by user. @@ -3125,15 +2091,6 @@ */ const AVCodecDescriptor *codec_descriptor; -#if !FF_API_LOWRES - /** - * low resolution decoding, 1-> 1/2 size, 2->1/4 size - * - encoding: unused - * - decoding: Set by user. - */ - int lowres; -#endif - /** * Current statistics for PTS correction. * - decoding: maintained and used by libavcodec, not intended to be used by user apps @@ -3184,12 +2141,11 @@ */ int seek_preroll; -#if !FF_API_DEBUG_MV +#if FF_API_DEBUG_MV /** - * debug motion vectors - * - encoding: Set by user. - * - decoding: Set by user. + * @deprecated unused */ + attribute_deprecated int debug_mv; #define FF_DEBUG_VIS_MV_P_FOR 0x00000001 //visualize forward predicted MVs of P frames #define FF_DEBUG_VIS_MV_B_FOR 0x00000002 //visualize forward predicted MVs of B frames @@ -3370,32 +2326,86 @@ * - encoding: unused */ int discard_damaged_percentage; -} AVCodecContext; - -#if FF_API_CODEC_GET_SET -/** - * Accessors for some AVCodecContext fields. These used to be provided for ABI - * compatibility, and do not need to be used anymore. - */ -attribute_deprecated -AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); -attribute_deprecated -void av_codec_set_pkt_timebase (AVCodecContext *avctx, AVRational val); -attribute_deprecated -const AVCodecDescriptor *av_codec_get_codec_descriptor(const AVCodecContext *avctx); -attribute_deprecated + /** + * The number of samples per frame to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_samples; + + /** + * Bit set of AV_CODEC_EXPORT_DATA_* flags, which affects the kind of + * metadata exported in frame, packet, or coded stream side data by + * decoders and encoders. + * + * - decoding: set by user + * - encoding: set by user + */ + int export_side_data; + + /** + * This callback is called at the beginning of each packet to get a data + * buffer for it. + * + * The following field will be set in the packet before this callback is + * called: + * - size + * This callback must use the above value to calculate the required buffer size, + * which must padded by at least AV_INPUT_BUFFER_PADDING_SIZE bytes. + * + * This callback must fill the following fields in the packet: + * - data: alignment requirements for AVPacket apply, if any. Some architectures and + * encoders may benefit from having aligned data. + * - buf: must contain a pointer to an AVBufferRef structure. The packet's + * data pointer must be contained in it. See: av_buffer_create(), av_buffer_alloc(), + * and av_buffer_ref(). + * + * If AV_CODEC_CAP_DR1 is not set then get_encode_buffer() must call + * avcodec_default_get_encode_buffer() instead of providing a buffer allocated by + * some other means. + * + * The flags field may contain a combination of AV_GET_ENCODE_BUFFER_FLAG_ flags. + * They may be used for example to hint what use the buffer may get after being + * created. + * Implementations of this callback may ignore flags they don't understand. + * If AV_GET_ENCODE_BUFFER_FLAG_REF is set in flags then the packet may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * This callback must be thread-safe, as when frame threading is used, it may + * be called from multiple threads simultaneously. + * + * @see avcodec_default_get_encode_buffer() + * + * - encoding: Set by libavcodec, user can override. + * - decoding: unused + */ + int (*get_encode_buffer)(struct AVCodecContext *s, AVPacket *pkt, int flags); +} AVCodecContext; + +#if FF_API_CODEC_GET_SET +/** + * Accessors for some AVCodecContext fields. These used to be provided for ABI + * compatibility, and do not need to be used anymore. + */ +attribute_deprecated +AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); +attribute_deprecated +void av_codec_set_pkt_timebase (AVCodecContext *avctx, AVRational val); + +attribute_deprecated +const AVCodecDescriptor *av_codec_get_codec_descriptor(const AVCodecContext *avctx); +attribute_deprecated void av_codec_set_codec_descriptor(AVCodecContext *avctx, const AVCodecDescriptor *desc); attribute_deprecated unsigned av_codec_get_codec_properties(const AVCodecContext *avctx); -#if FF_API_LOWRES attribute_deprecated int av_codec_get_lowres(const AVCodecContext *avctx); attribute_deprecated void av_codec_set_lowres(AVCodecContext *avctx, int val); -#endif attribute_deprecated int av_codec_get_seek_preroll(const AVCodecContext *avctx); @@ -3408,220 +2418,8 @@ void av_codec_set_chroma_intra_matrix(AVCodecContext *avctx, uint16_t *val); #endif -/** - * AVProfile. - */ -typedef struct AVProfile { - int profile; - const char *name; ///< short name for the profile -} AVProfile; - -enum { - /** - * The codec supports this format via the hw_device_ctx interface. - * - * When selecting this format, AVCodecContext.hw_device_ctx should - * have been set to a device of the specified type before calling - * avcodec_open2(). - */ - AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01, - /** - * The codec supports this format via the hw_frames_ctx interface. - * - * When selecting this format for a decoder, - * AVCodecContext.hw_frames_ctx should be set to a suitable frames - * context inside the get_format() callback. The frames context - * must have been created on a device of the specified type. - */ - AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02, - /** - * The codec supports this format by some internal method. - * - * This format can be selected without any additional configuration - - * no device or frames context is required. - */ - AV_CODEC_HW_CONFIG_METHOD_INTERNAL = 0x04, - /** - * The codec supports this format by some ad-hoc method. - * - * Additional settings and/or function calls are required. See the - * codec-specific documentation for details. (Methods requiring - * this sort of configuration are deprecated and others should be - * used in preference.) - */ - AV_CODEC_HW_CONFIG_METHOD_AD_HOC = 0x08, -}; - -typedef struct AVCodecHWConfig { - /** - * A hardware pixel format which the codec can use. - */ - enum AVPixelFormat pix_fmt; - /** - * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible - * setup methods which can be used with this configuration. - */ - int methods; - /** - * The device type associated with the configuration. - * - * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and - * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused. - */ - enum AVHWDeviceType device_type; -} AVCodecHWConfig; - -typedef struct AVCodecDefault AVCodecDefault; - struct AVSubtitle; -/** - * AVCodec. - */ -typedef struct AVCodec { - /** - * Name of the codec implementation. - * The name is globally unique among encoders and among decoders (but an - * encoder and a decoder can share the same name). - * This is the primary way to find a codec from the user perspective. - */ - const char *name; - /** - * Descriptive name for the codec, meant to be more human readable than name. - * You should use the NULL_IF_CONFIG_SMALL() macro to define it. - */ - const char *long_name; - enum AVMediaType type; - enum AVCodecID id; - /** - * Codec capabilities. - * see AV_CODEC_CAP_* - */ - int capabilities; - const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} - const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 - const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 - const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 - const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 - uint8_t max_lowres; ///< maximum value for lowres supported by the decoder - const AVClass *priv_class; ///< AVClass for the private context - const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN} - - /** - * Group name of the codec implementation. - * This is a short symbolic name of the wrapper backing this codec. A - * wrapper uses some kind of external implementation for the codec, such - * as an external library, or a codec implementation provided by the OS or - * the hardware. - * If this field is NULL, this is a builtin, libavcodec native codec. - * If non-NULL, this will be the suffix in AVCodec.name in most cases - * (usually AVCodec.name will be of the form "_"). - */ - const char *wrapper_name; - - /***************************************************************** - * No fields below this line are part of the public API. They - * may not be used outside of libavcodec and can be changed and - * removed at will. - * New public fields should be added right above. - ***************************************************************** - */ - int priv_data_size; - struct AVCodec *next; - /** - * @name Frame-level threading support functions - * @{ - */ - /** - * If defined, called on thread contexts when they are created. - * If the codec allocates writable tables in init(), re-allocate them here. - * priv_data will be set to a copy of the original. - */ - int (*init_thread_copy)(AVCodecContext *); - /** - * Copy necessary context variables from a previous thread context to the current one. - * If not defined, the next thread will start automatically; otherwise, the codec - * must call ff_thread_finish_setup(). - * - * dst and src will (rarely) point to the same context, in which case memcpy should be skipped. - */ - int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src); - /** @} */ - - /** - * Private codec-specific defaults. - */ - const AVCodecDefault *defaults; - - /** - * Initialize codec static data, called from avcodec_register(). - * - * This is not intended for time consuming operations as it is - * run for every codec regardless of that codec being used. - */ - void (*init_static_data)(struct AVCodec *codec); - - int (*init)(AVCodecContext *); - int (*encode_sub)(AVCodecContext *, uint8_t *buf, int buf_size, - const struct AVSubtitle *sub); - /** - * Encode data to an AVPacket. - * - * @param avctx codec context - * @param avpkt output AVPacket (may contain a user-provided buffer) - * @param[in] frame AVFrame containing the raw data to be encoded - * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a - * non-empty packet was returned in avpkt. - * @return 0 on success, negative error code on failure - */ - int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, - int *got_packet_ptr); - int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt); - int (*close)(AVCodecContext *); - /** - * Encode API with decoupled packet/frame dataflow. The API is the - * same as the avcodec_ prefixed APIs (avcodec_send_frame() etc.), except - * that: - * - never called if the codec is closed or the wrong type, - * - if AV_CODEC_CAP_DELAY is not set, drain frames are never sent, - * - only one drain frame is ever passed down, - */ - int (*send_frame)(AVCodecContext *avctx, const AVFrame *frame); - int (*receive_packet)(AVCodecContext *avctx, AVPacket *avpkt); - - /** - * Decode API with decoupled packet/frame dataflow. This function is called - * to get one output frame. It should call ff_decode_get_packet() to obtain - * input data. - */ - int (*receive_frame)(AVCodecContext *avctx, AVFrame *frame); - /** - * Flush buffers. - * Will be called when seeking - */ - void (*flush)(AVCodecContext *); - /** - * Internal codec capabilities. - * See FF_CODEC_CAP_* in internal.h - */ - int caps_internal; - - /** - * Decoding only, a comma-separated list of bitstream filters to apply to - * packets before decoding. - */ - const char *bsfs; - - /** - * Array of pointers to hardware configurations supported by the codec, - * or NULL if no hardware supported. The array is terminated by a NULL - * pointer. - * - * The user can only access this field via avcodec_get_hw_config(). - */ - const struct AVCodecHWConfigInternal **hw_configs; -} AVCodec; - #if FF_API_CODEC_GET_SET attribute_deprecated int av_codec_get_max_lowres(const AVCodec *codec); @@ -3630,15 +2428,6 @@ struct MpegEncContext; /** - * Retrieve supported hardware configurations for a codec. - * - * Values of index from zero to some maximum return the indexed configuration - * descriptor; all other values return NULL. If the codec does not support - * any hardware configurations then it will always return NULL. - */ -const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index); - -/** * @defgroup lavc_hwaccel AVHWAccel * * @note Nothing in this structure should be accessed by the user. At some @@ -3939,175 +2728,6 @@ int64_t pts; ///< Same as packet pts, in AV_TIME_BASE } AVSubtitle; -/** - * This struct describes the properties of an encoded stream. - * - * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must - * be allocated with avcodec_parameters_alloc() and freed with - * avcodec_parameters_free(). - */ -typedef struct AVCodecParameters { - /** - * General type of the encoded data. - */ - enum AVMediaType codec_type; - /** - * Specific type of the encoded data (the codec used). - */ - enum AVCodecID codec_id; - /** - * Additional information about the codec (corresponds to the AVI FOURCC). - */ - uint32_t codec_tag; - - /** - * Extra binary data needed for initializing the decoder, codec-dependent. - * - * Must be allocated with av_malloc() and will be freed by - * avcodec_parameters_free(). The allocated size of extradata must be at - * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding - * bytes zeroed. - */ - uint8_t *extradata; - /** - * Size of the extradata content in bytes. - */ - int extradata_size; - - /** - * - video: the pixel format, the value corresponds to enum AVPixelFormat. - * - audio: the sample format, the value corresponds to enum AVSampleFormat. - */ - int format; - - /** - * The average bitrate of the encoded data (in bits per second). - */ - int64_t bit_rate; - - /** - * The number of bits per sample in the codedwords. - * - * This is basically the bitrate per sample. It is mandatory for a bunch of - * formats to actually decode them. It's the number of bits for one sample in - * the actual coded bitstream. - * - * This could be for example 4 for ADPCM - * For PCM formats this matches bits_per_raw_sample - * Can be 0 - */ - int bits_per_coded_sample; - - /** - * This is the number of valid bits in each output sample. If the - * sample format has more bits, the least significant bits are additional - * padding bits, which are always 0. Use right shifts to reduce the sample - * to its actual size. For example, audio formats with 24 bit samples will - * have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32. - * To get the original sample use "(int32_t)sample >> 8"." - * - * For ADPCM this might be 12 or 16 or similar - * Can be 0 - */ - int bits_per_raw_sample; - - /** - * Codec-specific bitstream restrictions that the stream conforms to. - */ - int profile; - int level; - - /** - * Video only. The dimensions of the video frame in pixels. - */ - int width; - int height; - - /** - * Video only. The aspect ratio (width / height) which a single pixel - * should have when displayed. - * - * When the aspect ratio is unknown / undefined, the numerator should be - * set to 0 (the denominator may have any value). - */ - AVRational sample_aspect_ratio; - - /** - * Video only. The order of the fields in interlaced video. - */ - enum AVFieldOrder field_order; - - /** - * Video only. Additional colorspace characteristics. - */ - enum AVColorRange color_range; - enum AVColorPrimaries color_primaries; - enum AVColorTransferCharacteristic color_trc; - enum AVColorSpace color_space; - enum AVChromaLocation chroma_location; - - /** - * Video only. Number of delayed frames. - */ - int video_delay; - - /** - * Audio only. The channel layout bitmask. May be 0 if the channel layout is - * unknown or unspecified, otherwise the number of bits set must be equal to - * the channels field. - */ - uint64_t channel_layout; - /** - * Audio only. The number of audio channels. - */ - int channels; - /** - * Audio only. The number of audio samples per second. - */ - int sample_rate; - /** - * Audio only. The number of bytes per coded audio frame, required by some - * formats. - * - * Corresponds to nBlockAlign in WAVEFORMATEX. - */ - int block_align; - /** - * Audio only. Audio frame size, if known. Required by some formats to be static. - */ - int frame_size; - - /** - * Audio only. The amount of padding (in samples) inserted by the encoder at - * the beginning of the audio. I.e. this number of leading decoded samples - * must be discarded by the caller to get the original audio without leading - * padding. - */ - int initial_padding; - /** - * Audio only. The amount of padding (in samples) appended by the encoder to - * the end of the audio. I.e. this number of decoded samples must be - * discarded by the caller from the end of the stream to get the original - * audio without any trailing padding. - */ - int trailing_padding; - /** - * Audio only. Number of samples to skip after a discontinuity. - */ - int seek_preroll; -} AVCodecParameters; - -/** - * Iterate over all registered codecs. - * - * @param opaque a pointer where libavcodec will store the iteration state. Must - * point to NULL to start the iteration. - * - * @return the next registered codec or NULL when the iteration is - * finished - */ -const AVCodec *av_codec_iterate(void **opaque); - #if FF_API_NEXT /** * If c is NULL, returns the first registered codec, @@ -4135,25 +2755,13 @@ #if FF_API_NEXT /** - * Register the codec codec and initialize libavcodec. - * - * @warning either this function or avcodec_register_all() must be called - * before any other libavcodec functions. - * - * @see avcodec_register_all() + * @deprecated Calling this function is unnecessary. */ attribute_deprecated void avcodec_register(AVCodec *codec); /** - * Register all the codecs, parsers and bitstream filters which were enabled at - * configuration time. If you do not call this function you can select exactly - * which formats you want to support, by using the individual registration - * functions. - * - * @see avcodec_register - * @see av_register_codec_parser - * @see av_register_bitstream_filter + * @deprecated Calling this function is unnecessary. */ attribute_deprecated void avcodec_register_all(void); @@ -4197,14 +2805,13 @@ */ const AVClass *avcodec_get_class(void); -#if FF_API_COPY_CONTEXT +#if FF_API_GET_FRAME_CLASS /** - * Get the AVClass for AVFrame. It can be used in combination with - * AV_OPT_SEARCH_FAKE_OBJ for examining options. - * - * @see av_opt_find(). + * @deprecated This function should not be used. */ +attribute_deprecated const AVClass *avcodec_get_frame_class(void); +#endif /** * Get the AVClass for AVSubtitleRect. It can be used in combination with @@ -4214,6 +2821,7 @@ */ const AVClass *avcodec_get_subtitle_rect_class(void); +#if FF_API_COPY_CONTEXT /** * Copy the settings of the source AVCodecContext into the destination * AVCodecContext. The resulting destination codec context will be @@ -4236,27 +2844,6 @@ #endif /** - * Allocate a new AVCodecParameters and set its fields to default values - * (unknown/invalid/0). The returned struct must be freed with - * avcodec_parameters_free(). - */ -AVCodecParameters *avcodec_parameters_alloc(void); - -/** - * Free an AVCodecParameters instance and everything associated with it and - * write NULL to the supplied pointer. - */ -void avcodec_parameters_free(AVCodecParameters **par); - -/** - * Copy the contents of src to dst. Any allocated fields in dst are freed and - * replaced with newly allocated duplicates of the corresponding fields in src. - * - * @return >= 0 on success, a negative AVERROR code on failure. - */ -int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src); - -/** * Fill the parameters struct based on the values from the supplied codec * context. Any allocated fields in par are freed and replaced with duplicates * of the corresponding fields in codec. @@ -4264,390 +2851,79 @@ * @return >= 0 on success, a negative AVERROR code on failure */ int avcodec_parameters_from_context(AVCodecParameters *par, - const AVCodecContext *codec); - -/** - * Fill the codec context based on the values from the supplied codec - * parameters. Any allocated fields in codec that have a corresponding field in - * par are freed and replaced with duplicates of the corresponding field in par. - * Fields in codec that do not have a counterpart in par are not touched. - * - * @return >= 0 on success, a negative AVERROR code on failure. - */ -int avcodec_parameters_to_context(AVCodecContext *codec, - const AVCodecParameters *par); - -/** - * Initialize the AVCodecContext to use the given AVCodec. Prior to using this - * function the context has to be allocated with avcodec_alloc_context3(). - * - * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), - * 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()). - * - * @code - * avcodec_register_all(); - * av_dict_set(&opts, "b", "2.5M", 0); - * codec = avcodec_find_decoder(AV_CODEC_ID_H264); - * if (!codec) - * exit(1); - * - * context = avcodec_alloc_context3(codec); - * - * if (avcodec_open2(context, codec, opts) < 0) - * exit(1); - * @endcode - * - * @param avctx The context to initialize. - * @param codec The codec to open this context for. If a non-NULL codec has been - * previously passed to avcodec_alloc_context3() or - * for this context, then this parameter MUST be either NULL or - * equal to the previously passed codec. - * @param options A dictionary filled with AVCodecContext and codec-private options. - * On return this object will be filled with options that were not found. - * - * @return zero on success, a negative value on error - * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), - * av_dict_set(), av_opt_find(). - */ -int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); - -/** - * Close a given AVCodecContext and free all the data associated with it - * (but not the AVCodecContext itself). - * - * Calling this function on an AVCodecContext that hasn't been opened will free - * the codec-specific data allocated in avcodec_alloc_context3() with a non-NULL - * codec. Subsequent calls will do nothing. - * - * @note Do not use this function. Use avcodec_free_context() to destroy a - * codec context (either open or closed). Opening and closing a codec context - * multiple times is not supported anymore -- use multiple codec contexts - * instead. - */ -int avcodec_close(AVCodecContext *avctx); - -/** - * Free all allocated data in the given subtitle struct. - * - * @param sub AVSubtitle to free. - */ -void avsubtitle_free(AVSubtitle *sub); - -/** - * @} - */ - -/** - * @addtogroup lavc_packet - * @{ - */ - -/** - * Allocate an AVPacket and set its fields to default values. The resulting - * struct must be freed using av_packet_free(). - * - * @return An AVPacket filled with default values or NULL on failure. - * - * @note this only allocates the AVPacket itself, not the data buffers. Those - * must be allocated through other means such as av_new_packet. - * - * @see av_new_packet - */ -AVPacket *av_packet_alloc(void); - -/** - * Create a new packet that references the same data as src. - * - * This is a shortcut for av_packet_alloc()+av_packet_ref(). - * - * @return newly created AVPacket on success, NULL on error. - * - * @see av_packet_alloc - * @see av_packet_ref - */ -AVPacket *av_packet_clone(const AVPacket *src); - -/** - * Free the packet, if the packet is reference counted, it will be - * unreferenced first. - * - * @param pkt packet to be freed. The pointer will be set to NULL. - * @note passing NULL is a no-op. - */ -void av_packet_free(AVPacket **pkt); - -/** - * Initialize optional fields of a packet with default values. - * - * Note, this does not touch the data and size members, which have to be - * initialized separately. - * - * @param pkt packet - */ -void av_init_packet(AVPacket *pkt); - -/** - * Allocate the payload of a packet and initialize its fields with - * default values. - * - * @param pkt packet - * @param size wanted payload size - * @return 0 if OK, AVERROR_xxx otherwise - */ -int av_new_packet(AVPacket *pkt, int size); - -/** - * Reduce packet size, correctly zeroing padding - * - * @param pkt packet - * @param size new size - */ -void av_shrink_packet(AVPacket *pkt, int size); - -/** - * Increase packet size, correctly zeroing padding - * - * @param pkt packet - * @param grow_by number of bytes by which to increase the size of the packet - */ -int av_grow_packet(AVPacket *pkt, int grow_by); - -/** - * Initialize a reference-counted packet from av_malloc()ed data. - * - * @param pkt packet to be initialized. This function will set the data, size, - * and buf fields, all others are left untouched. - * @param data Data allocated by av_malloc() to be used as packet data. If this - * function returns successfully, the data is owned by the underlying AVBuffer. - * The caller may not access the data through other means. - * @param size size of data in bytes, without the padding. I.e. the full buffer - * size is assumed to be size + AV_INPUT_BUFFER_PADDING_SIZE. - * - * @return 0 on success, a negative AVERROR on error - */ -int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size); - -#if FF_API_AVPACKET_OLD_API -/** - * @warning This is a hack - the packet memory allocation stuff is broken. The - * packet is allocated if it was not really allocated. - * - * @deprecated Use av_packet_ref or av_packet_make_refcounted - */ -attribute_deprecated -int av_dup_packet(AVPacket *pkt); -/** - * Copy packet, including contents - * - * @return 0 on success, negative AVERROR on fail - * - * @deprecated Use av_packet_ref - */ -attribute_deprecated -int av_copy_packet(AVPacket *dst, const AVPacket *src); - -/** - * Copy packet side data - * - * @return 0 on success, negative AVERROR on fail - * - * @deprecated Use av_packet_copy_props - */ -attribute_deprecated -int av_copy_packet_side_data(AVPacket *dst, const AVPacket *src); - -/** - * Free a packet. - * - * @deprecated Use av_packet_unref - * - * @param pkt packet to free - */ -attribute_deprecated -void av_free_packet(AVPacket *pkt); -#endif -/** - * Allocate new information of a packet. - * - * @param pkt packet - * @param type side information type - * @param size side information size - * @return pointer to fresh allocated data or NULL otherwise - */ -uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, - int size); - -/** - * Wrap an existing array as a packet side data. - * - * @param pkt packet - * @param type side information type - * @param data the side data array. It must be allocated with the av_malloc() - * family of functions. The ownership of the data is transferred to - * pkt. - * @param size side information size - * @return a non-negative number on success, a negative AVERROR code on - * failure. On failure, the packet is unchanged and the data remains - * owned by the caller. - */ -int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, - uint8_t *data, size_t size); - -/** - * Shrink the already allocated side data buffer - * - * @param pkt packet - * @param type side information type - * @param size new side information size - * @return 0 on success, < 0 on failure - */ -int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, - int size); - -/** - * Get side information from packet. - * - * @param pkt packet - * @param type desired side information type - * @param size pointer for side information size to store (optional) - * @return pointer to data if present or NULL otherwise - */ -uint8_t* av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, - int *size); - -#if FF_API_MERGE_SD_API -attribute_deprecated -int av_packet_merge_side_data(AVPacket *pkt); - -attribute_deprecated -int av_packet_split_side_data(AVPacket *pkt); -#endif - -const char *av_packet_side_data_name(enum AVPacketSideDataType type); - -/** - * Pack a dictionary for use in side_data. - * - * @param dict The dictionary to pack. - * @param size pointer to store the size of the returned data - * @return pointer to data if successful, NULL otherwise - */ -uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size); -/** - * Unpack a dictionary from side_data. - * - * @param data data from side_data - * @param size size of the data - * @param dict the metadata storage dictionary - * @return 0 on success, < 0 on failure - */ -int av_packet_unpack_dictionary(const uint8_t *data, int size, AVDictionary **dict); - - -/** - * Convenience function to free all the side data stored. - * All the other fields stay untouched. - * - * @param pkt packet - */ -void av_packet_free_side_data(AVPacket *pkt); - -/** - * Setup a new reference to the data described by a given packet - * - * If src is reference-counted, setup dst as a new reference to the - * buffer in src. Otherwise allocate a new buffer in dst and copy the - * data from src into it. - * - * All the other fields are copied from src. - * - * @see av_packet_unref - * - * @param dst Destination packet - * @param src Source packet - * - * @return 0 on success, a negative AVERROR on error. - */ -int av_packet_ref(AVPacket *dst, const AVPacket *src); - -/** - * Wipe the packet. - * - * Unreference the buffer referenced by the packet and reset the - * remaining packet fields to their default values. - * - * @param pkt The packet to be unreferenced. - */ -void av_packet_unref(AVPacket *pkt); + const AVCodecContext *codec); /** - * Move every field in src to dst and reset src. - * - * @see av_packet_unref + * Fill the codec context based on the values from the supplied codec + * parameters. Any allocated fields in codec that have a corresponding field in + * par are freed and replaced with duplicates of the corresponding field in par. + * Fields in codec that do not have a counterpart in par are not touched. * - * @param src Source packet, will be reset - * @param dst Destination packet + * @return >= 0 on success, a negative AVERROR code on failure. */ -void av_packet_move_ref(AVPacket *dst, AVPacket *src); +int avcodec_parameters_to_context(AVCodecContext *codec, + const AVCodecParameters *par); /** - * Copy only "properties" fields from src to dst. + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated with avcodec_alloc_context3(). * - * Properties for the purpose of this function are all the fields - * beside those related to the packet data (buf, data, size) + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. * - * @param dst Destination packet - * @param src Source packet + * @warning This function is not thread safe! * - * @return 0 on success AVERROR on failure. - */ -int av_packet_copy_props(AVPacket *dst, const AVPacket *src); - -/** - * Ensure the data described by a given packet is reference counted. + * @note Always call this function before using decoding routines (such as + * @ref avcodec_receive_frame()). + * + * @code + * av_dict_set(&opts, "b", "2.5M", 0); + * codec = avcodec_find_decoder(AV_CODEC_ID_H264); + * if (!codec) + * exit(1); * - * @note This function does not ensure that the reference will be writable. - * Use av_packet_make_writable instead for that purpose. + * context = avcodec_alloc_context3(codec); * - * @see av_packet_ref - * @see av_packet_make_writable + * if (avcodec_open2(context, codec, opts) < 0) + * exit(1); + * @endcode * - * @param pkt packet whose data should be made reference counted. + * @param avctx The context to initialize. + * @param codec The codec to open this context for. If a non-NULL codec has been + * previously passed to avcodec_alloc_context3() or + * for this context, then this parameter MUST be either NULL or + * equal to the previously passed codec. + * @param options A dictionary filled with AVCodecContext and codec-private options. + * On return this object will be filled with options that were not found. * - * @return 0 on success, a negative AVERROR on error. On failure, the - * packet is unchanged. + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), + * av_dict_set(), av_opt_find(). */ -int av_packet_make_refcounted(AVPacket *pkt); +int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); /** - * Create a writable reference for the data described by a given packet, - * avoiding data copy if possible. + * Close a given AVCodecContext and free all the data associated with it + * (but not the AVCodecContext itself). * - * @param pkt Packet whose data should be made writable. + * Calling this function on an AVCodecContext that hasn't been opened will free + * the codec-specific data allocated in avcodec_alloc_context3() with a non-NULL + * codec. Subsequent calls will do nothing. * - * @return 0 on success, a negative AVERROR on failure. On failure, the - * packet is unchanged. + * @note Do not use this function. Use avcodec_free_context() to destroy a + * codec context (either open or closed). Opening and closing a codec context + * multiple times is not supported anymore -- use multiple codec contexts + * instead. */ -int av_packet_make_writable(AVPacket *pkt); +int avcodec_close(AVCodecContext *avctx); /** - * Convert valid timing fields (timestamps / durations) in a packet from one - * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be - * ignored. + * Free all allocated data in the given subtitle struct. * - * @param pkt packet on which the conversion will be performed - * @param tb_src source timebase, in which the timing fields in pkt are - * expressed - * @param tb_dst destination timebase, to which the timing fields will be - * converted + * @param sub AVSubtitle to free. */ -void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst); +void avsubtitle_free(AVSubtitle *sub); /** * @} @@ -4659,22 +2935,6 @@ */ /** - * Find a registered decoder with a matching codec ID. - * - * @param id AVCodecID of the requested decoder - * @return A decoder if one was found, NULL otherwise. - */ -AVCodec *avcodec_find_decoder(enum AVCodecID id); - -/** - * Find a registered decoder with the specified name. - * - * @param name name of the requested decoder - * @return A decoder if one was found, NULL otherwise. - */ -AVCodec *avcodec_find_decoder_by_name(const char *name); - -/** * The default callback for AVCodecContext.get_buffer2(). It is made public so * it can be called by custom get_buffer2() implementations for decoders without * AV_CODEC_CAP_DR1 set. @@ -4682,6 +2942,13 @@ int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags); /** + * The default callback for AVCodecContext.get_encode_buffer(). It is made public so + * it can be called by custom get_encode_buffer() implementations for encoders without + * AV_CODEC_CAP_DR1 set. + */ +int avcodec_default_get_encode_buffer(AVCodecContext *s, AVPacket *pkt, int flags); + +/** * Modify width and height values so that they will result in a memory * buffer that is acceptable for the codec if you do not use any horizontal * padding. @@ -4722,6 +2989,7 @@ */ enum AVChromaLocation avcodec_chroma_pos_to_enum(int xpos, int ypos); +#if FF_API_OLD_ENCDEC /** * Decode the audio frame of size avpkt->size from avpkt->data into frame. * @@ -4828,6 +3096,7 @@ int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt); +#endif /** * Decode a subtitle message. @@ -4835,7 +3104,7 @@ * If no subtitle could be decompressed, got_sub_ptr is zero. * Otherwise, the subtitle is stored in *sub. * Note that AV_CODEC_CAP_DR1 is not available for subtitle codecs. This is for - * simplicity, because the performance difference is expect to be negligible + * simplicity, because the performance difference is expected to be negligible * and reusing a get_buffer written for video codecs would probably perform badly * due to a potentially very different allocation pattern. * @@ -4851,7 +3120,7 @@ * before packets may be fed to the decoder. * * @param avctx the codec context - * @param[out] sub The Preallocated AVSubtitle in which the decoded subtitle will be stored, + * @param[out] sub The preallocated AVSubtitle in which the decoded subtitle will be stored, * must be freed with avsubtitle_free if *got_sub_ptr is set. * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. * @param[in] avpkt The input AVPacket containing the input buffer. @@ -4968,7 +3237,7 @@ * AVERROR(EINVAL): codec not opened, refcounted_frames not set, it is a * decoder, or requires flush * AVERROR(ENOMEM): failed to add packet to internal queue, or similar - * other errors: legitimate decoding errors + * other errors: legitimate encoding errors */ int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); @@ -4978,14 +3247,14 @@ * @param avctx codec context * @param avpkt This will be set to a reference-counted packet allocated by the * encoder. Note that the function will always call - * av_frame_unref(frame) before doing anything else. + * av_packet_unref(avpkt) before doing anything else. * @return 0 on success, otherwise negative error code: * AVERROR(EAGAIN): output is not available in the current state - user * must try to send input * AVERROR_EOF: the encoder has been fully flushed, and there will be * no more output packets - * AVERROR(EINVAL): codec not opened, or it is an encoder - * other errors: legitimate decoding errors + * AVERROR(EINVAL): codec not opened, or it is a decoder + * other errors: legitimate encoding errors */ int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); @@ -5284,7 +3553,10 @@ const uint8_t *buf, int buf_size); void (*parser_close)(AVCodecParserContext *s); int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size); +#if FF_API_NEXT + attribute_deprecated struct AVCodecParser *next; +#endif } AVCodecParser; /** @@ -5298,11 +3570,13 @@ */ const AVCodecParser *av_parser_iterate(void **opaque); +#if FF_API_NEXT attribute_deprecated AVCodecParser *av_parser_next(const AVCodecParser *c); attribute_deprecated void av_register_codec_parser(AVCodecParser *parser); +#endif AVCodecParserContext *av_parser_init(int codec_id); /** @@ -5343,14 +3617,18 @@ int64_t pts, int64_t dts, int64_t pos); +#if FF_API_PARSER_CHANGE /** * @return 0 if the output buffer is a subset of the input, 1 if it is allocated and must be freed - * @deprecated use AVBitStreamFilter + * @deprecated Use dump_extradata, remove_extra or extract_extradata + * bitstream filters instead. */ +attribute_deprecated int av_parser_change(AVCodecParserContext *s, AVCodecContext *avctx, uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size, int keyframe); +#endif void av_parser_close(AVCodecParserContext *s); /** @@ -5363,22 +3641,7 @@ * @{ */ -/** - * Find a registered encoder with a matching codec ID. - * - * @param id AVCodecID of the requested encoder - * @return An encoder if one was found, NULL otherwise. - */ -AVCodec *avcodec_find_encoder(enum AVCodecID id); - -/** - * Find a registered encoder with the specified name. - * - * @param name name of the requested encoder - * @return An encoder if one was found, NULL otherwise. - */ -AVCodec *avcodec_find_encoder_by_name(const char *name); - +#if FF_API_OLD_ENCDEC /** * Encode a frame of audio. * @@ -5417,7 +3680,9 @@ * not be used. * @return 0 on success, negative error code on failure * - * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead + * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead. + * If allowed and required, set AVCodecContext.get_encode_buffer to + * a custom function to pass user supplied output buffers. */ attribute_deprecated int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, @@ -5456,11 +3721,14 @@ * not be used. * @return 0 on success, negative error code on failure * - * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead + * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead. + * If allowed and required, set AVCodecContext.get_encode_buffer to + * a custom function to pass user supplied output buffers. */ attribute_deprecated int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr); +#endif int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, const AVSubtitle *sub); @@ -5568,12 +3836,6 @@ unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt); /** - * @deprecated see av_get_pix_fmt_loss() - */ -int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt, - int has_alpha); - -/** * Find the best pixel format to convert to given a certain source pixel * format. When converting from one pixel format to another, information loss * may occur. For example, when converting from RGB24 to GRAY, the color @@ -5594,15 +3856,24 @@ enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); +#if FF_API_AVCODEC_PIX_FMT +/** + * @deprecated see av_get_pix_fmt_loss() + */ +attribute_deprecated +int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt, + int has_alpha); /** * @deprecated see av_find_best_pix_fmt_of_2() */ +attribute_deprecated enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); attribute_deprecated enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); +#endif enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat * fmt); @@ -5682,13 +3953,21 @@ int buf_size, int align); /** - * Reset the internal decoder state / flush internal buffers. Should be called + * Reset the internal codec state / flush internal buffers. Should be called * e.g. when seeking or when switching to a different stream. * - * @note when refcounted frames are not used (i.e. avctx->refcounted_frames is 0), - * this invalidates the frames previously returned from the decoder. When - * refcounted frames are used, the decoder just releases any references it might - * keep internally, but the caller's reference remains valid. + * @note for decoders, when refcounted frames are not used + * (i.e. avctx->refcounted_frames is 0), this invalidates the frames previously + * returned from the decoder. When refcounted frames are used, the decoder just + * releases any references it might keep internally, but the caller's reference + * remains valid. + * + * @note for encoders, this function will only do something if the encoder + * declares support for AV_CODEC_CAP_ENCODER_FLUSH. When called, the encoder + * will drain any remaining packets, and can then be re-used for a different + * stream (as opposed to sending a null frame which will leave the encoder + * in a permanent EOF state after draining). This can be desirable if the + * cost of tearing down and replacing the encoder instance is high. */ void avcodec_flush_buffers(AVCodecContext *avctx); @@ -5746,106 +4025,7 @@ */ char *args; } AVBitStreamFilterContext; -#endif - -typedef struct AVBSFInternal AVBSFInternal; - -/** - * The bitstream filter state. - * - * This struct must be allocated with av_bsf_alloc() and freed with - * av_bsf_free(). - * - * The fields in the struct will only be changed (by the caller or by the - * filter) as described in their documentation, and are to be considered - * immutable otherwise. - */ -typedef struct AVBSFContext { - /** - * A class for logging and AVOptions - */ - const AVClass *av_class; - - /** - * The bitstream filter this context is an instance of. - */ - const struct AVBitStreamFilter *filter; - - /** - * Opaque libavcodec internal data. Must not be touched by the caller in any - * way. - */ - AVBSFInternal *internal; - - /** - * Opaque filter-specific private data. If filter->priv_class is non-NULL, - * this is an AVOptions-enabled struct. - */ - void *priv_data; - - /** - * Parameters of the input stream. This field is allocated in - * av_bsf_alloc(), it needs to be filled by the caller before - * av_bsf_init(). - */ - AVCodecParameters *par_in; - - /** - * Parameters of the output stream. This field is allocated in - * av_bsf_alloc(), it is set by the filter in av_bsf_init(). - */ - AVCodecParameters *par_out; - /** - * The timebase used for the timestamps of the input packets. Set by the - * caller before av_bsf_init(). - */ - AVRational time_base_in; - - /** - * The timebase used for the timestamps of the output packets. Set by the - * filter in av_bsf_init(). - */ - AVRational time_base_out; -} AVBSFContext; - -typedef struct AVBitStreamFilter { - const char *name; - - /** - * A list of codec ids supported by the filter, terminated by - * AV_CODEC_ID_NONE. - * May be NULL, in that case the bitstream filter works with any codec id. - */ - const enum AVCodecID *codec_ids; - - /** - * A class for the private data, used to declare bitstream filter private - * AVOptions. This field is NULL for bitstream filters that do not declare - * any options. - * - * If this field is non-NULL, the first member of the filter private data - * must be a pointer to AVClass, which will be set by libavcodec generic - * code to this class. - */ - const AVClass *priv_class; - - /***************************************************************** - * No fields below this line are part of the public API. They - * may not be used outside of libavcodec and can be changed and - * removed at will. - * New public fields should be added right above. - ***************************************************************** - */ - - int priv_data_size; - int (*init)(AVBSFContext *ctx); - int (*filter)(AVBSFContext *ctx, AVPacket *pkt); - void (*close)(AVBSFContext *ctx); - void (*flush)(AVBSFContext *ctx); -} AVBitStreamFilter; - -#if FF_API_OLD_BSF /** * @deprecated the old bitstream filtering API (using AVBitStreamFilterContext) * is deprecated. Use the new bitstream filtering API (using AVBSFContext). @@ -5885,194 +4065,11 @@ const AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f); #endif -/** - * @return a bitstream filter with the specified name or NULL if no such - * bitstream filter exists. - */ -const AVBitStreamFilter *av_bsf_get_by_name(const char *name); - -/** - * Iterate over all registered bitstream filters. - * - * @param opaque a pointer where libavcodec will store the iteration state. Must - * point to NULL to start the iteration. - * - * @return the next registered bitstream filter or NULL when the iteration is - * finished - */ -const AVBitStreamFilter *av_bsf_iterate(void **opaque); #if FF_API_NEXT attribute_deprecated const AVBitStreamFilter *av_bsf_next(void **opaque); #endif -/** - * Allocate a context for a given bitstream filter. The caller must fill in the - * context parameters as described in the documentation and then call - * av_bsf_init() before sending any data to the filter. - * - * @param filter the filter for which to allocate an instance. - * @param ctx a pointer into which the pointer to the newly-allocated context - * will be written. It must be freed with av_bsf_free() after the - * filtering is done. - * - * @return 0 on success, a negative AVERROR code on failure - */ -int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx); - -/** - * Prepare the filter for use, after all the parameters and options have been - * set. - */ -int av_bsf_init(AVBSFContext *ctx); - -/** - * Submit a packet for filtering. - * - * After sending each packet, the filter must be completely drained by calling - * av_bsf_receive_packet() repeatedly until it returns AVERROR(EAGAIN) or - * AVERROR_EOF. - * - * @param pkt the packet to filter. The bitstream filter will take ownership of - * the packet and reset the contents of pkt. pkt is not touched if an error occurs. - * This parameter may be NULL, which signals the end of the stream (i.e. no more - * packets will be sent). That will cause the filter to output any packets it - * may have buffered internally. - * - * @return 0 on success, a negative AVERROR on error. - */ -int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt); - -/** - * Retrieve a filtered packet. - * - * @param[out] pkt this struct will be filled with the contents of the filtered - * packet. It is owned by the caller and must be freed using - * av_packet_unref() when it is no longer needed. - * This parameter should be "clean" (i.e. freshly allocated - * with av_packet_alloc() or unreffed with av_packet_unref()) - * when this function is called. If this function returns - * successfully, the contents of pkt will be completely - * overwritten by the returned data. On failure, pkt is not - * touched. - * - * @return 0 on success. AVERROR(EAGAIN) if more packets need to be sent to the - * filter (using av_bsf_send_packet()) to get more output. AVERROR_EOF if there - * will be no further output from the filter. Another negative AVERROR value if - * an error occurs. - * - * @note one input packet may result in several output packets, so after sending - * a packet with av_bsf_send_packet(), this function needs to be called - * repeatedly until it stops returning 0. It is also possible for a filter to - * output fewer packets than were sent to it, so this function may return - * AVERROR(EAGAIN) immediately after a successful av_bsf_send_packet() call. - */ -int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt); - -/** - * Reset the internal bitstream filter state / flush internal buffers. - */ -void av_bsf_flush(AVBSFContext *ctx); - -/** - * Free a bitstream filter context and everything associated with it; write NULL - * into the supplied pointer. - */ -void av_bsf_free(AVBSFContext **ctx); - -/** - * Get the AVClass for AVBSFContext. It can be used in combination with - * AV_OPT_SEARCH_FAKE_OBJ for examining options. - * - * @see av_opt_find(). - */ -const AVClass *av_bsf_get_class(void); - -/** - * Structure for chain/list of bitstream filters. - * Empty list can be allocated by av_bsf_list_alloc(). - */ -typedef struct AVBSFList AVBSFList; - -/** - * Allocate empty list of bitstream filters. - * The list must be later freed by av_bsf_list_free() - * or finalized by av_bsf_list_finalize(). - * - * @return Pointer to @ref AVBSFList on success, NULL in case of failure - */ -AVBSFList *av_bsf_list_alloc(void); - -/** - * Free list of bitstream filters. - * - * @param lst Pointer to pointer returned by av_bsf_list_alloc() - */ -void av_bsf_list_free(AVBSFList **lst); - -/** - * Append bitstream filter to the list of bitstream filters. - * - * @param lst List to append to - * @param bsf Filter context to be appended - * - * @return >=0 on success, negative AVERROR in case of failure - */ -int av_bsf_list_append(AVBSFList *lst, AVBSFContext *bsf); - -/** - * Construct new bitstream filter context given it's name and options - * and append it to the list of bitstream filters. - * - * @param lst List to append to - * @param bsf_name Name of the bitstream filter - * @param options Options for the bitstream filter, can be set to NULL - * - * @return >=0 on success, negative AVERROR in case of failure - */ -int av_bsf_list_append2(AVBSFList *lst, const char * bsf_name, AVDictionary **options); -/** - * Finalize list of bitstream filters. - * - * This function will transform @ref AVBSFList to single @ref AVBSFContext, - * so the whole chain of bitstream filters can be treated as single filter - * freshly allocated by av_bsf_alloc(). - * If the call is successful, @ref AVBSFList structure is freed and lst - * will be set to NULL. In case of failure, caller is responsible for - * freeing the structure by av_bsf_list_free() - * - * @param lst Filter list structure to be transformed - * @param[out] bsf Pointer to be set to newly created @ref AVBSFContext structure - * representing the chain of bitstream filters - * - * @return >=0 on success, negative AVERROR in case of failure - */ -int av_bsf_list_finalize(AVBSFList **lst, AVBSFContext **bsf); - -/** - * Parse string describing list of bitstream filters and create single - * @ref AVBSFContext describing the whole chain of bitstream filters. - * Resulting @ref AVBSFContext can be treated as any other @ref AVBSFContext freshly - * allocated by av_bsf_alloc(). - * - * @param str String describing chain of bitstream filters in format - * `bsf1[=opt1=val1:opt2=val2][,bsf2]` - * @param[out] bsf Pointer to be set to newly created @ref AVBSFContext structure - * representing the chain of bitstream filters - * - * @return >=0 on success, negative AVERROR in case of failure - */ -int av_bsf_list_parse_str(const char *str, AVBSFContext **bsf); - -/** - * Get null/pass-through bitstream filter. - * - * @param[out] bsf Pointer to be set to new instance of pass-through bitstream filter - * - * @return - */ -int av_bsf_get_null_filter(AVBSFContext **bsf); - /* memory */ /** @@ -6164,53 +4161,12 @@ #endif /** - * Get the type of the given codec. - */ -enum AVMediaType avcodec_get_type(enum AVCodecID codec_id); - -/** - * Get the name of a codec. - * @return a static string identifying the codec; never NULL - */ -const char *avcodec_get_name(enum AVCodecID id); - -/** * @return a positive value if s is open (i.e. avcodec_open2() was called on it * with no corresponding avcodec_close()), 0 otherwise. */ int avcodec_is_open(AVCodecContext *s); /** - * @return a non-zero number if codec is an encoder, zero otherwise - */ -int av_codec_is_encoder(const AVCodec *codec); - -/** - * @return a non-zero number if codec is a decoder, zero otherwise - */ -int av_codec_is_decoder(const AVCodec *codec); - -/** - * @return descriptor for given codec ID or NULL if no descriptor exists. - */ -const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id); - -/** - * Iterate over all codec descriptors known to libavcodec. - * - * @param prev previous descriptor. NULL to get the first descriptor. - * - * @return next descriptor or NULL after the last descriptor - */ -const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); - -/** - * @return codec descriptor with the given name or NULL if no such descriptor - * exists. - */ -const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); - -/** * Allocate a CPB properties structure and initialize its fields to default * values. * diff -Nru ffmpeg-4.2.2/libavcodec/avdct.c ffmpeg-4.4/libavcodec/avdct.c --- ffmpeg-4.2.2/libavcodec/avdct.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/avdct.c 2020-07-11 10:39:30.000000000 +0000 @@ -100,7 +100,7 @@ #if CONFIG_IDCTDSP { - IDCTDSPContext idsp; + IDCTDSPContext idsp = {0}; ff_idctdsp_init(&idsp, avctx); COPY(idsp, idct); COPY(idsp, idct_permutation); @@ -120,6 +120,7 @@ PixblockDSPContext pdsp; ff_pixblockdsp_init(&pdsp, avctx); COPY(pdsp, get_pixels); + COPY(pdsp, get_pixels_unaligned); } #endif diff -Nru ffmpeg-4.2.2/libavcodec/avdct.h ffmpeg-4.4/libavcodec/avdct.h --- ffmpeg-4.2.2/libavcodec/avdct.h 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/avdct.h 2020-07-11 10:39:30.000000000 +0000 @@ -67,6 +67,10 @@ ptrdiff_t line_size); int bits_per_sample; + + void (*get_pixels_unaligned)(int16_t *block /* align 16 */, + const uint8_t *pixels, + ptrdiff_t line_size); } AVDCT; /** diff -Nru ffmpeg-4.2.2/libavcodec/avpacket.c ffmpeg-4.4/libavcodec/avpacket.c --- ffmpeg-4.2.2/libavcodec/avpacket.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/avpacket.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,10 +26,13 @@ #include "libavutil/internal.h" #include "libavutil/mathematics.h" #include "libavutil/mem.h" -#include "avcodec.h" + #include "bytestream.h" #include "internal.h" +#include "packet.h" +#include "packet_internal.h" +#if FF_API_INIT_PACKET void av_init_packet(AVPacket *pkt) { pkt->pts = AV_NOPTS_VALUE; @@ -47,6 +50,16 @@ pkt->side_data = NULL; pkt->side_data_elems = 0; } +#endif + +static void get_packet_defaults(AVPacket *pkt) +{ + memset(pkt, 0, sizeof(*pkt)); + + pkt->pts = AV_NOPTS_VALUE; + pkt->dts = AV_NOPTS_VALUE; + pkt->pos = -1; +} AVPacket *av_packet_alloc(void) { @@ -54,7 +67,7 @@ if (!pkt) return pkt; - av_packet_unref(pkt); + get_packet_defaults(pkt); return pkt; } @@ -90,7 +103,7 @@ if (ret < 0) return ret; - av_init_packet(pkt); + get_packet_defaults(pkt); pkt->buf = buf; pkt->data = buf->data; pkt->size = size; @@ -127,7 +140,8 @@ return AVERROR(ENOMEM); } - if (new_size + data_offset > pkt->buf->size) { + 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); if (ret < 0) { pkt->data = old_data; @@ -327,12 +341,16 @@ uint8_t *av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, - int size) + buffer_size_t size) { int ret; uint8_t *data; +#if FF_API_BUFFER_SIZE_T if ((unsigned)size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) +#else + if (size > SIZE_MAX - AV_INPUT_BUFFER_PADDING_SIZE) +#endif return NULL; data = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!data) @@ -348,7 +366,7 @@ } uint8_t *av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, - int *size) + buffer_size_t *size) { int i; @@ -394,6 +412,10 @@ case AV_PKT_DATA_ENCRYPTION_INIT_INFO: return "Encryption initialization data"; case AV_PKT_DATA_ENCRYPTION_INFO: return "Encryption info"; case AV_PKT_DATA_AFD: return "Active Format Description data"; + case AV_PKT_DATA_PRFT: return "Producer Reference Time"; + case AV_PKT_DATA_ICC_PROFILE: return "ICC Profile"; + case AV_PKT_DATA_DOVI_CONF: return "DOVI configuration record"; + case AV_PKT_DATA_S12M_TIMECODE: return "SMPTE ST 12-1:2014 timecode"; } return NULL; } @@ -485,48 +507,61 @@ } #endif +#if FF_API_BUFFER_SIZE_T uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size) +#else +uint8_t *av_packet_pack_dictionary(AVDictionary *dict, size_t *size) +#endif { - AVDictionaryEntry *t = NULL; uint8_t *data = NULL; *size = 0; if (!dict) return NULL; - while ((t = av_dict_get(dict, "", t, AV_DICT_IGNORE_SUFFIX))) { - const size_t keylen = strlen(t->key); - const size_t valuelen = strlen(t->value); - const size_t new_size = *size + keylen + 1 + valuelen + 1; - uint8_t *const new_data = av_realloc(data, new_size); - - if (!new_data) - goto fail; - data = new_data; - if (new_size > INT_MAX) - goto fail; - - memcpy(data + *size, t->key, keylen + 1); - memcpy(data + *size + keylen + 1, t->value, valuelen + 1); - - *size = new_size; + for (int pass = 0; pass < 2; pass++) { + const AVDictionaryEntry *t = NULL; + size_t total_length = 0; + + while ((t = av_dict_get(dict, "", t, AV_DICT_IGNORE_SUFFIX))) { + for (int i = 0; i < 2; i++) { + const char *str = i ? t->value : t->key; + const size_t len = strlen(str) + 1; + + if (pass) + memcpy(data + total_length, str, len); +#if FF_API_BUFFER_SIZE_T + else if (len > INT_MAX - total_length) +#else + else if (len > SIZE_MAX - total_length) +#endif + return NULL; + total_length += len; + } + } + if (pass) + break; + data = av_malloc(total_length); + if (!data) + return NULL; + *size = total_length; } return data; - -fail: - av_freep(&data); - *size = 0; - return NULL; } +#if FF_API_BUFFER_SIZE_T int av_packet_unpack_dictionary(const uint8_t *data, int size, AVDictionary **dict) +#else +int av_packet_unpack_dictionary(const uint8_t *data, size_t size, + AVDictionary **dict) +#endif { const uint8_t *end; - int ret = 0; + int ret; if (!dict || !data || !size) - return ret; + return 0; end = data + size; if (size && end[-1]) return AVERROR_INVALIDDATA; @@ -539,15 +574,15 @@ ret = av_dict_set(dict, key, val, 0); if (ret < 0) - break; + return ret; data = val + strlen(val) + 1; } - return ret; + return 0; } int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, - int size) + buffer_size_t size) { int i; @@ -582,7 +617,7 @@ dst->side_data_elems = 0; for (i = 0; i < src->side_data_elems; i++) { enum AVPacketSideDataType type = src->side_data[i].type; - int size = src->side_data[i].size; + buffer_size_t size = src->side_data[i].size; uint8_t *src_data = src->side_data[i].data; uint8_t *dst_data = av_packet_new_side_data(dst, type, size); @@ -600,18 +635,18 @@ { av_packet_free_side_data(pkt); av_buffer_unref(&pkt->buf); - av_init_packet(pkt); - pkt->data = NULL; - pkt->size = 0; + get_packet_defaults(pkt); } int av_packet_ref(AVPacket *dst, const AVPacket *src) { int ret; + dst->buf = NULL; + ret = av_packet_copy_props(dst, src); if (ret < 0) - return ret; + goto fail; if (!src->buf) { ret = packet_alloc(&dst->buf, src->size); @@ -635,7 +670,7 @@ return 0; fail: - av_packet_free_side_data(dst); + av_packet_unref(dst); return ret; } @@ -655,9 +690,7 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src) { *dst = *src; - av_init_packet(src); - src->data = NULL; - src->size = 0; + get_packet_defaults(src); } int av_packet_make_refcounted(AVPacket *pkt) @@ -717,10 +750,77 @@ #endif } +int avpriv_packet_list_put(PacketList **packet_buffer, + PacketList **plast_pktl, + AVPacket *pkt, + int (*copy)(AVPacket *dst, const AVPacket *src), + int flags) +{ + PacketList *pktl = av_mallocz(sizeof(PacketList)); + int ret; + + if (!pktl) + return AVERROR(ENOMEM); + + if (copy) { + ret = copy(&pktl->pkt, pkt); + if (ret < 0) { + av_free(pktl); + return ret; + } + } else { + ret = av_packet_make_refcounted(pkt); + if (ret < 0) { + av_free(pktl); + return ret; + } + av_packet_move_ref(&pktl->pkt, pkt); + } + + if (*packet_buffer) + (*plast_pktl)->next = pktl; + else + *packet_buffer = pktl; + + /* Add the packet in the buffered packet list. */ + *plast_pktl = pktl; + return 0; +} + +int avpriv_packet_list_get(PacketList **pkt_buffer, + PacketList **pkt_buffer_end, + AVPacket *pkt) +{ + PacketList *pktl; + if (!*pkt_buffer) + return AVERROR(EAGAIN); + pktl = *pkt_buffer; + *pkt = pktl->pkt; + *pkt_buffer = pktl->next; + if (!pktl->next) + *pkt_buffer_end = NULL; + av_freep(&pktl); + return 0; +} + +void avpriv_packet_list_free(PacketList **pkt_buf, PacketList **pkt_buf_end) +{ + PacketList *tmp = *pkt_buf; + + while (tmp) { + PacketList *pktl = tmp; + tmp = pktl->next; + av_packet_unref(&pktl->pkt); + av_freep(&pktl); + } + *pkt_buf = NULL; + *pkt_buf_end = NULL; +} + int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type) { uint8_t *side_data; - int side_data_size; + buffer_size_t side_data_size; int i; side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, &side_data_size); @@ -741,3 +841,25 @@ return 0; } + +int ff_side_data_set_prft(AVPacket *pkt, int64_t timestamp) +{ + AVProducerReferenceTime *prft; + uint8_t *side_data; + buffer_size_t side_data_size; + + side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &side_data_size); + if (!side_data) { + side_data_size = sizeof(AVProducerReferenceTime); + side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_PRFT, side_data_size); + } + + if (!side_data || side_data_size < sizeof(AVProducerReferenceTime)) + return AVERROR(ENOMEM); + + prft = (AVProducerReferenceTime *)side_data; + prft->wallclock = timestamp; + prft->flags = 0; + + return 0; +} diff -Nru ffmpeg-4.2.2/libavcodec/avrndec.c ffmpeg-4.4/libavcodec/avrndec.c --- ffmpeg-4.2.2/libavcodec/avrndec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/avrndec.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,13 +21,9 @@ #include "avcodec.h" #include "internal.h" -#include "mjpeg.h" -#include "mjpegdec.h" #include "libavutil/imgutils.h" typedef struct { - AVCodecContext *mjpeg_avctx; - int is_mjpeg; int interlace; int tff; } AVRnContext; @@ -37,40 +33,6 @@ AVRnContext *a = avctx->priv_data; int ret; - // Support "Resolution 1:1" for Avid AVI Codec - a->is_mjpeg = avctx->extradata_size < 31 || memcmp(&avctx->extradata[28], "1:1", 3); - - if(!a->is_mjpeg && avctx->lowres) { - av_log(avctx, AV_LOG_ERROR, "lowres is not possible with rawvideo\n"); - return AVERROR(EINVAL); - } - - if(a->is_mjpeg) { - AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG); - AVDictionary *thread_opt = NULL; - if (!codec) { - av_log(avctx, AV_LOG_ERROR, "MJPEG codec not found\n"); - return AVERROR_DECODER_NOT_FOUND; - } - - a->mjpeg_avctx = avcodec_alloc_context3(codec); - - av_dict_set(&thread_opt, "threads", "1", 0); // Is this needed ? - a->mjpeg_avctx->refcounted_frames = 1; - a->mjpeg_avctx->flags = avctx->flags; - a->mjpeg_avctx->idct_algo = avctx->idct_algo; - a->mjpeg_avctx->lowres = avctx->lowres; - a->mjpeg_avctx->width = avctx->width; - a->mjpeg_avctx->height = avctx->height; - - if ((ret = ff_codec_open2_recursive(a->mjpeg_avctx, codec, &thread_opt)) < 0) { - av_log(avctx, AV_LOG_ERROR, "MJPEG codec failed to open\n"); - } - av_dict_free(&thread_opt); - - return ret; - } - if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0) return ret; @@ -87,16 +49,6 @@ return 0; } -static av_cold int end(AVCodecContext *avctx) -{ - AVRnContext *a = avctx->priv_data; - - avcodec_close(a->mjpeg_avctx); - av_freep(&a->mjpeg_avctx); - - return 0; -} - static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { @@ -106,28 +58,6 @@ int buf_size = avpkt->size; int y, ret, true_height; - if(a->is_mjpeg) { - ret = avcodec_decode_video2(a->mjpeg_avctx, data, got_frame, avpkt); - - if (ret >= 0 && *got_frame && avctx->width <= p->width && avctx->height <= p->height) { - int shift = p->height - avctx->height; - int subsample_h, subsample_v; - - av_pix_fmt_get_chroma_sub_sample(p->format, &subsample_h, &subsample_v); - - p->data[0] += p->linesize[0] * shift; - if (p->data[2]) { - p->data[1] += p->linesize[1] * (shift>>subsample_v); - p->data[2] += p->linesize[2] * (shift>>subsample_v); - } - - p->width = avctx->width; - p->height = avctx->height; - } - avctx->pix_fmt = a->mjpeg_avctx->pix_fmt; - return ret; - } - true_height = buf_size / (2*avctx->width); if(buf_size < 2*avctx->width * avctx->height) { @@ -166,8 +96,7 @@ .id = AV_CODEC_ID_AVRN, .priv_data_size = sizeof(AVRnContext), .init = init, - .close = end, .decode = decode_frame, - .max_lowres = 3, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/avs2_parser.c ffmpeg-4.4/libavcodec/avs2_parser.c --- ffmpeg-4.2.2/libavcodec/avs2_parser.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/avs2_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,10 +21,10 @@ #include "parser.h" -#define SLICE_MAX_START_CODE 0x000001af +#define AVS2_SLICE_MAX_START_CODE 0x000001AF -#define ISPIC(x) ((x) == 0xB3 || (x) == 0xB6) -#define ISUNIT(x) ((x) == 0xB0 || (x) == 0xB1 || (x) == 0xB2 || ISPIC(x)) +#define AVS2_ISPIC(x) ((x) == 0xB3 || (x) == 0xB6) +#define AVS2_ISUNIT(x) ((x) == 0xB0 || (x) == 0xB1 || (x) == 0xB2 || AVS2_ISPIC(x)) static int avs2_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) { @@ -34,9 +34,9 @@ if (!pic_found) { for (; cur < buf_size; ++cur) { - state = (state<<8) | buf[cur]; - if (ISUNIT(buf[cur])){ - ++cur; + state = (state << 8) | buf[cur]; + if (AVS2_ISUNIT(buf[cur])){ + cur++; pic_found = 1; break; } @@ -46,9 +46,9 @@ if (pic_found) { if (!buf_size) return END_NOT_FOUND; - for (; cur < buf_size; ++cur) { + for (; cur < buf_size; cur++) { state = (state << 8) | buf[cur]; - if ((state & 0xFFFFFF00) == 0x100 && state > SLICE_MAX_START_CODE) { + if ((state & 0xFFFFFF00) == 0x100 && state > AVS2_SLICE_MAX_START_CODE) { pc->frame_start_found = 0; pc->state = -1; return cur - 3; diff -Nru ffmpeg-4.2.2/libavcodec/avs3.h ffmpeg-4.4/libavcodec/avs3.h --- ffmpeg-4.2.2/libavcodec/avs3.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/avs3.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,118 @@ +/* + * AVS3 related definitions + * + * Copyright (C) 2020 Huiwen Ren, + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_AVS3_H +#define AVCODEC_AVS3_H + +#define AVS3_NAL_START_CODE 0x010000 +#define AVS3_SEQ_START_CODE 0xB0 +#define AVS3_SEQ_END_CODE 0xB1 +#define AVS3_USER_DATA_START_CODE 0xB2 +#define AVS3_INTRA_PIC_START_CODE 0xB3 +#define AVS3_UNDEF_START_CODE 0xB4 +#define AVS3_EXTENSION_START_CODE 0xB5 +#define AVS3_INTER_PIC_START_CODE 0xB6 +#define AVS3_VIDEO_EDIT_CODE 0xB7 +#define AVS3_FIRST_SLICE_START_CODE 0x00 +#define AVS3_PROFILE_BASELINE_MAIN 0x20 +#define AVS3_PROFILE_BASELINE_MAIN10 0x22 + +#define AVS3_ISPIC(x) ((x) == AVS3_INTRA_PIC_START_CODE || (x) == AVS3_INTER_PIC_START_CODE) +#define AVS3_ISUNIT(x) ((x) == AVS3_SEQ_START_CODE || AVS3_ISPIC(x)) + +#include "libavutil/avutil.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +static const AVRational ff_avs3_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; + +static const int ff_avs3_color_primaries_tab[10] = { + AVCOL_PRI_RESERVED0 , // 0 + AVCOL_PRI_BT709 , // 1 + AVCOL_PRI_UNSPECIFIED , // 2 + AVCOL_PRI_RESERVED , // 3 + AVCOL_PRI_BT470M , // 4 + AVCOL_PRI_BT470BG , // 5 + AVCOL_PRI_SMPTE170M , // 6 + AVCOL_PRI_SMPTE240M , // 7 + AVCOL_PRI_FILM , // 8 + AVCOL_PRI_BT2020 // 9 +}; + +static const int ff_avs3_color_transfer_tab[15] = { + AVCOL_TRC_RESERVED0 , // 0 + AVCOL_TRC_BT709 , // 1 + AVCOL_TRC_UNSPECIFIED , // 2 + AVCOL_TRC_RESERVED , // 3 + AVCOL_TRC_GAMMA22 , // 4 + AVCOL_TRC_GAMMA28 , // 5 + AVCOL_TRC_SMPTE170M , // 6 + AVCOL_TRC_SMPTE240M , // 7 + AVCOL_TRC_LINEAR , // 8 + AVCOL_TRC_LOG , // 9 + AVCOL_TRC_LOG_SQRT , // 10 + AVCOL_TRC_BT2020_12 , // 11 + AVCOL_TRC_SMPTE2084 , // 12 + AVCOL_TRC_UNSPECIFIED , // 13 + AVCOL_TRC_ARIB_STD_B67 // 14 +}; + +static const int ff_avs3_color_matrix_tab[12] = { + AVCOL_SPC_RESERVED , // 0 + AVCOL_SPC_BT709 , // 1 + AVCOL_SPC_UNSPECIFIED , // 2 + AVCOL_SPC_RESERVED , // 3 + AVCOL_SPC_FCC , // 4 + AVCOL_SPC_BT470BG , // 5 + AVCOL_SPC_SMPTE170M , // 6 + AVCOL_SPC_SMPTE240M , // 7 + AVCOL_SPC_BT2020_NCL , // 8 + AVCOL_SPC_BT2020_CL , // 9 + AVCOL_SPC_UNSPECIFIED , // 10 + AVCOL_SPC_UNSPECIFIED // 11 +}; + +static const enum AVPictureType ff_avs3_image_type[4] = { + AV_PICTURE_TYPE_NONE, + AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_P, + AV_PICTURE_TYPE_B +}; + +#endif /* AVCODEC_AVS3_H */ diff -Nru ffmpeg-4.2.2/libavcodec/avs3_parser.c ffmpeg-4.4/libavcodec/avs3_parser.c --- ffmpeg-4.2.2/libavcodec/avs3_parser.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/avs3_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,179 @@ +/* + * AVS3-P2/IEEE1857.10 video parser. + * Copyright (c) 2020 Zhenyu Wang + * Bingjie Han + * Huiwen Ren + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "avs3.h" +#include "get_bits.h" +#include "parser.h" + +static int avs3_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) +{ + int pic_found = pc->frame_start_found; + uint32_t state = pc->state; + int cur = 0; + + if (!pic_found) { + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if (AVS3_ISPIC(buf[cur])){ + cur++; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) + return END_NOT_FOUND; + for (; cur < buf_size; ++cur) { + state = (state << 8) | buf[cur]; + if ((state & 0xFFFFFF00) == 0x100 && AVS3_ISUNIT(state & 0xFF)) { + pc->frame_start_found = 0; + pc->state = -1; + return cur - 3; + } + } + } + + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) { + return; + } + + if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { + if (buf[3] == AVS3_SEQ_START_CODE) { + GetBitContext gb; + int profile, ratecode; + + init_get_bits(&gb, buf + 4, buf_size - 4); + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = get_bits(&gb, 8); + // Skip bits: level(8) + // progressive(1) + // field(1) + // library(2) + // resv(1) + // width(14) + // resv(1) + // height(14) + // chroma(2) + // sampe_precision(3) + skip_bits(&gb, 47); + + if (profile == AVS3_PROFILE_BASELINE_MAIN10) { + int sample_precision = get_bits(&gb, 3); + if (sample_precision == 1) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + } else if (sample_precision == 2) { + avctx->pix_fmt = AV_PIX_FMT_YUV420P10LE; + } else { + avctx->pix_fmt = AV_PIX_FMT_NONE; + } + } + + // Skip bits: resv(1) + // aspect(4) + skip_bits(&gb, 5); + + ratecode = get_bits(&gb, 4); + + // Skip bits: resv(1) + // bitrate_low(18) + // resv(1) + // bitrate_high(12) + skip_bits(&gb, 32); + + avctx->has_b_frames = !get_bits(&gb, 1); + + avctx->framerate.num = avctx->time_base.den = ff_avs3_frame_rate_tab[ratecode].num; + avctx->framerate.den = avctx->time_base.num = ff_avs3_frame_rate_tab[ratecode].den; + + s->width = s->coded_width = avctx->width; + s->height = s->coded_height = avctx->height; + + av_log(avctx, AV_LOG_DEBUG, + "AVS3 parse seq HDR: profile %d; coded size: %dx%d; frame rate code: %d\n", + profile, avctx->width, avctx->height, ratecode); + + } else if (buf[3] == AVS3_INTRA_PIC_START_CODE) { + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + } else if (buf[3] == AVS3_INTER_PIC_START_CODE){ + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1 || pic_code_type == 3) { + s->pict_type = AV_PICTURE_TYPE_P; + } else { + s->pict_type = AV_PICTURE_TYPE_B; + } + } + } + } +} + + +static int avs3_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = avs3_find_frame_end(pc, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + parse_avs3_nal_units(s, buf, buf_size, avctx); + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_avs3_parser = { + .codec_ids = { AV_CODEC_ID_AVS3 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = avs3_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff -Nru ffmpeg-4.2.2/libavcodec/avs.c ffmpeg-4.4/libavcodec/avs.c --- ffmpeg-4.2.2/libavcodec/avs.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/avs.c 2020-07-11 10:39:30.000000000 +0000 @@ -59,7 +59,7 @@ AvsBlockType type; GetBitContext change_map = {0}; //init to silence warning - if ((ret = ff_reget_buffer(avctx, p)) < 0) + if ((ret = ff_reget_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_P; p->key_frame = 0; diff -Nru ffmpeg-4.2.2/libavcodec/avuienc.c ffmpeg-4.4/libavcodec/avuienc.c --- ffmpeg-4.2.2/libavcodec/avuienc.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/avuienc.c 2020-07-11 10:39:30.000000000 +0000 @@ -98,6 +98,6 @@ .id = AV_CODEC_ID_AVUI, .init = avui_encode_init, .encode2 = avui_encode_frame, - .capabilities = AV_CODEC_CAP_EXPERIMENTAL | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_EXPERIMENTAL, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_UYVY422, AV_PIX_FMT_NONE }, }; diff -Nru ffmpeg-4.2.2/libavcodec/bethsoftvideo.c ffmpeg-4.4/libavcodec/bethsoftvideo.c --- ffmpeg-4.2.2/libavcodec/bethsoftvideo.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/bethsoftvideo.c 2020-07-11 10:39:30.000000000 +0000 @@ -79,7 +79,7 @@ int code, ret; int yoffset; - if ((ret = ff_reget_buffer(avctx, vid->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, vid->frame, 0)) < 0) return ret; wrap_to_next_line = vid->frame->linesize[0] - avctx->width; diff -Nru ffmpeg-4.2.2/libavcodec/bgmc.c ffmpeg-4.4/libavcodec/bgmc.c --- ffmpeg-4.2.2/libavcodec/bgmc.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/bgmc.c 2020-07-11 10:39:30.000000000 +0000 @@ -493,7 +493,7 @@ *h = TOP_VALUE; *l = 0; - *v = get_bits_long(gb, VALUE_BITS); + *v = get_bits(gb, VALUE_BITS); return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/binkaudio.c ffmpeg-4.4/libavcodec/binkaudio.c --- ffmpeg-4.2.2/libavcodec/binkaudio.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/binkaudio.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/intfloat.h" +#include "libavutil/mem_internal.h" #define BITSTREAM_READER_LE #include "avcodec.h" @@ -40,8 +41,6 @@ #include "rdft.h" #include "wma_freqs.h" -static float quant_table[96]; - #define MAX_CHANNELS 2 #define BINK_BLOCK_MAX_SIZE (MAX_CHANNELS << 11) @@ -54,10 +53,10 @@ int overlap_len; ///< overlap size (samples) int block_size; int num_bands; - unsigned int *bands; float root; - DECLARE_ALIGNED(32, FFTSample, coeffs)[BINK_BLOCK_MAX_SIZE]; + unsigned int bands[26]; float previous[MAX_CHANNELS][BINK_BLOCK_MAX_SIZE / 16]; ///< coeffs from previous audio block + float quant_table[96]; AVPacket *pkt; union { RDFTContext rdft; @@ -71,7 +70,7 @@ BinkAudioContext *s = avctx->priv_data; int sample_rate = avctx->sample_rate; int sample_rate_half; - int i; + int i, ret; int frame_len_bits; /* determine frame length */ @@ -109,14 +108,14 @@ s->frame_len = 1 << frame_len_bits; s->overlap_len = s->frame_len / 16; s->block_size = (s->frame_len - s->overlap_len) * s->channels; - sample_rate_half = (sample_rate + 1) / 2; + sample_rate_half = (sample_rate + 1LL) / 2; if (avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT) s->root = 2.0 / (sqrt(s->frame_len) * 32768.0); else s->root = s->frame_len / (sqrt(s->frame_len) * 32768.0); for (i = 0; i < 96; i++) { /* constant is result of 0.066399999/log10(M_E) */ - quant_table[i] = expf(i * 0.15289164787221953823f) * s->root; + s->quant_table[i] = expf(i * 0.15289164787221953823f) * s->root; } /* calculate number of bands */ @@ -124,10 +123,6 @@ if (sample_rate_half <= ff_wma_critical_freqs[s->num_bands - 1]) break; - s->bands = av_malloc((s->num_bands + 1) * sizeof(*s->bands)); - if (!s->bands) - return AVERROR(ENOMEM); - /* populate bands data */ s->bands[0] = 2; for (i = 1; i < s->num_bands; i++) @@ -137,11 +132,13 @@ s->first = 1; if (CONFIG_BINKAUDIO_RDFT_DECODER && avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT) - ff_rdft_init(&s->trans.rdft, frame_len_bits, DFT_C2R); + ret = ff_rdft_init(&s->trans.rdft, frame_len_bits, DFT_C2R); else if (CONFIG_BINKAUDIO_DCT_DECODER) - ff_dct_init(&s->trans.dct, frame_len_bits, DCT_III); + ret = ff_dct_init(&s->trans.dct, frame_len_bits, DCT_III); else av_assert0(0); + if (ret < 0) + return ret; s->pkt = av_packet_alloc(); if (!s->pkt) @@ -153,7 +150,7 @@ static float get_float(GetBitContext *gb) { int power = get_bits(gb, 5); - float f = ldexpf(get_bits_long(gb, 23), power - 23); + float f = ldexpf(get_bits(gb, 23), power - 23); if (get_bits1(gb)) f = -f; return f; @@ -197,7 +194,7 @@ return AVERROR_INVALIDDATA; for (i = 0; i < s->num_bands; i++) { int value = get_bits(gb, 8); - quant[i] = quant_table[FFMIN(value, 95)]; + quant[i] = s->quant_table[FFMIN(value, 95)]; } k = 0; @@ -275,7 +272,6 @@ static av_cold int decode_end(AVCodecContext *avctx) { BinkAudioContext * s = avctx->priv_data; - av_freep(&s->bands); if (CONFIG_BINKAUDIO_RDFT_DECODER && avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT) ff_rdft_end(&s->trans.rdft); else if (CONFIG_BINKAUDIO_DCT_DECODER) @@ -351,6 +347,7 @@ .close = decode_end, .receive_frame = binkaudio_receive_frame, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; AVCodec ff_binkaudio_dct_decoder = { @@ -363,4 +360,5 @@ .close = decode_end, .receive_frame = binkaudio_receive_frame, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/bink.c ffmpeg-4.4/libavcodec/bink.c --- ffmpeg-4.2.2/libavcodec/bink.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/bink.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/attributes.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #define BITSTREAM_READER_LE #include "avcodec.h" @@ -114,7 +115,7 @@ typedef struct BinkContext { AVCodecContext *avctx; BlockDSPContext bdsp; - HpelDSPContext hdsp; + op_pixels_func put_pixels_tab; BinkDSPContext binkdsp; AVFrame *last; int version; ///< internal Bink file version @@ -178,17 +179,20 @@ static av_cold int init_bundles(BinkContext *c) { int bw, bh, blocks; + uint8_t *tmp; int i; bw = (c->avctx->width + 7) >> 3; bh = (c->avctx->height + 7) >> 3; blocks = bw * bh; + tmp = av_calloc(blocks, 64 * BINKB_NB_SRC); + if (!tmp) + return AVERROR(ENOMEM); for (i = 0; i < BINKB_NB_SRC; i++) { - c->bundle[i].data = av_mallocz(blocks * 64); - if (!c->bundle[i].data) - return AVERROR(ENOMEM); - c->bundle[i].data_end = c->bundle[i].data + blocks * 64; + c->bundle[i].data = tmp; + tmp += blocks * 64; + c->bundle[i].data_end = tmp; } return 0; @@ -201,9 +205,7 @@ */ static av_cold void free_bundles(BinkContext *c) { - int i; - for (i = 0; i < BINKB_NB_SRC; i++) - av_freep(&c->bundle[i].data); + av_freep(&c->bundle[0].data); } /** @@ -241,16 +243,19 @@ * @param gb context for reading bits * @param tree pointer for storing tree data */ -static void read_tree(GetBitContext *gb, Tree *tree) +static int read_tree(GetBitContext *gb, Tree *tree) { uint8_t tmp1[16] = { 0 }, tmp2[16], *in = tmp1, *out = tmp2; int i, t, len; + if (get_bits_left(gb) < 4) + return AVERROR_INVALIDDATA; + tree->vlc_num = get_bits(gb, 4); if (!tree->vlc_num) { for (i = 0; i < 16; i++) tree->syms[i] = i; - return; + return 0; } if (get_bits1(gb)) { len = get_bits(gb, 3); @@ -273,6 +278,7 @@ } memcpy(tree->syms, in, 16); } + return 0; } /** @@ -282,19 +288,27 @@ * @param c decoder context * @param bundle_num number of the bundle to initialize */ -static void read_bundle(GetBitContext *gb, BinkContext *c, int bundle_num) +static int read_bundle(GetBitContext *gb, BinkContext *c, int bundle_num) { int i; if (bundle_num == BINK_SRC_COLORS) { - for (i = 0; i < 16; i++) - read_tree(gb, &c->col_high[i]); + for (i = 0; i < 16; i++) { + int ret = read_tree(gb, &c->col_high[i]); + if (ret < 0) + return ret; + } c->col_lastval = 0; } - if (bundle_num != BINK_SRC_INTRA_DC && bundle_num != BINK_SRC_INTER_DC) - read_tree(gb, &c->bundle[bundle_num].tree); + if (bundle_num != BINK_SRC_INTRA_DC && bundle_num != BINK_SRC_INTER_DC) { + int ret = read_tree(gb, &c->bundle[bundle_num].tree); + if (ret < 0) + return ret; + } c->bundle[bundle_num].cur_dec = c->bundle[bundle_num].cur_ptr = c->bundle[bundle_num].data; + + return 0; } /** @@ -324,6 +338,8 @@ av_log(avctx, AV_LOG_ERROR, "Run value went out of bounds\n"); return AVERROR_INVALIDDATA; } + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; if (get_bits1(gb)) { v = get_bits(gb, 4); memset(b->cur_dec, v, t); @@ -346,6 +362,8 @@ av_log(avctx, AV_LOG_ERROR, "Too many motion values\n"); return AVERROR_INVALIDDATA; } + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; if (get_bits1(gb)) { v = get_bits(gb, 4); if (v) { @@ -389,6 +407,8 @@ av_log(avctx, AV_LOG_ERROR, "Too many block type values\n"); return AVERROR_INVALIDDATA; } + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; if (get_bits1(gb)) { v = get_bits(gb, 4); memset(b->cur_dec, v, t); @@ -424,6 +444,8 @@ return AVERROR_INVALIDDATA; } while (b->cur_dec < dec_end) { + if (get_bits_left(gb) < 2) + return AVERROR_INVALIDDATA; v = GET_HUFF(gb, b->tree); v |= GET_HUFF(gb, b->tree) << 4; *b->cur_dec++ = v; @@ -443,6 +465,8 @@ av_log(c->avctx, AV_LOG_ERROR, "Too many color values\n"); return AVERROR_INVALIDDATA; } + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; if (get_bits1(gb)) { c->col_lastval = GET_HUFF(gb, c->col_high[c->col_lastval]); v = GET_HUFF(gb, b->tree); @@ -456,6 +480,8 @@ b->cur_dec += t; } else { while (b->cur_dec < dec_end) { + if (get_bits_left(gb) < 2) + return AVERROR_INVALIDDATA; c->col_lastval = GET_HUFF(gb, c->col_high[c->col_lastval]); v = GET_HUFF(gb, b->tree); v = (c->col_lastval << 4) | v; @@ -481,6 +507,8 @@ int16_t *dst_end = (int16_t*)b->data_end; CHECK_READ_VAL(gb, b, len); + if (get_bits_left(gb) < start_bits - has_sign) + return AVERROR_INVALIDDATA; v = get_bits(gb, start_bits - has_sign); if (v && has_sign) { sign = -get_bits1(gb); @@ -620,6 +648,9 @@ int coef_count = 0; int quant_idx; + if (get_bits_left(gb) < 4) + return AVERROR_INVALIDDATA; + coef_list[list_end] = 4; mode_list[list_end++] = 0; coef_list[list_end] = 24; mode_list[list_end++] = 0; coef_list[list_end] = 44; mode_list[list_end++] = 0; @@ -897,7 +928,7 @@ if (ref < ref_start || ref + 8*stride > ref_end) { av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n"); } else if (ref + 8*stride < dst || ref >= dst + 8*stride) { - c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + c->put_pixels_tab(dst, ref, stride, 8); } else { put_pixels8x8_overlapped(dst, ref, stride); } @@ -913,7 +944,7 @@ if (ref < ref_start || ref + 8 * stride > ref_end) { av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n"); } else if (ref + 8*stride < dst || ref >= dst + 8*stride) { - c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + c->put_pixels_tab(dst, ref, stride, 8); } else { put_pixels8x8_overlapped(dst, ref, stride); } @@ -945,7 +976,7 @@ if (ref < ref_start || ref + 8 * stride > ref_end) { av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n"); } else if (ref + 8*stride < dst || ref >= dst + 8*stride) { - c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + c->put_pixels_tab(dst, ref, stride, 8); } else { put_pixels8x8_overlapped(dst, ref, stride); } @@ -980,7 +1011,7 @@ xoff, yoff); return AVERROR_INVALIDDATA; } - c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + c->put_pixels_tab(dst, ref, stride, 8); return 0; } @@ -1015,8 +1046,11 @@ } init_lengths(c, FFMAX(width, 8), bw); - for (i = 0; i < BINK_NB_SRC; i++) - read_bundle(gb, c, i); + for (i = 0; i < BINK_NB_SRC; i++) { + ret = read_bundle(gb, c, i); + if (ret < 0) + return ret; + } ref_start = c->last->data[plane_idx] ? c->last->data[plane_idx] : frame->data[plane_idx]; @@ -1060,12 +1094,14 @@ } switch (blk) { case SKIP_BLOCK: - c->hdsp.put_pixels_tab[1][0](dst, prev, stride, 8); + c->put_pixels_tab(dst, prev, stride, 8); break; case SCALED_BLOCK: blk = get_value(c, BINK_SRC_SUB_BLOCK_TYPES); switch (blk) { case RUN_BLOCK: + if (get_bits_left(gb) < 4) + return AVERROR_INVALIDDATA; scan = bink_patterns[get_bits(gb, 4)]; i = 0; do { @@ -1227,7 +1263,7 @@ if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; } else { - if ((ret = ff_reget_buffer(avctx, c->last)) < 0) + if ((ret = ff_reget_buffer(avctx, c->last, 0)) < 0) return ret; if ((ret = av_frame_ref(frame, c->last)) < 0) return ret; @@ -1310,6 +1346,7 @@ BinkContext * const c = avctx->priv_data; static VLC_TYPE table[16 * 128][2]; static int binkb_initialised = 0; + HpelDSPContext hdsp; int i, ret; int flags; @@ -1344,13 +1381,12 @@ avctx->color_range = c->version == 'k' ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; ff_blockdsp_init(&c->bdsp, avctx); - ff_hpeldsp_init(&c->hdsp, avctx->flags); + ff_hpeldsp_init(&hdsp, avctx->flags); + c->put_pixels_tab = hdsp.put_pixels_tab[1][0]; ff_binkdsp_init(&c->binkdsp); - if ((ret = init_bundles(c)) < 0) { - free_bundles(c); + if ((ret = init_bundles(c)) < 0) return ret; - } if (c->version == 'b') { if (!binkb_initialised) { @@ -1390,4 +1426,5 @@ .decode = decode_frame, .flush = flush, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/bitpacked.c ffmpeg-4.4/libavcodec/bitpacked.c --- ffmpeg-4.2.2/libavcodec/bitpacked.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/bitpacked.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,12 +33,12 @@ struct BitpackedContext { int (*decode)(AVCodecContext *avctx, AVFrame *frame, - AVPacket *pkt); + const AVPacket *pkt); }; /* For this format, it's a simple passthrough */ static int bitpacked_decode_uyvy422(AVCodecContext *avctx, AVFrame *frame, - AVPacket *avpkt) + const AVPacket *avpkt) { int ret; @@ -56,7 +56,7 @@ } static int bitpacked_decode_yuv422p10(AVCodecContext *avctx, AVFrame *frame, - AVPacket *avpkt) + const AVPacket *avpkt) { uint64_t frame_size = (uint64_t)avctx->width * (uint64_t)avctx->height * 20; uint64_t packet_size = (uint64_t)avpkt->size * 8; @@ -146,4 +146,8 @@ .init = bitpacked_init_decoder, .decode = bitpacked_decode, .capabilities = AV_CODEC_CAP_EXPERIMENTAL, + .codec_tags = (const uint32_t []){ + MKTAG('U', 'Y', 'V', 'Y'), + FF_CODEC_TAGS_END, + }, }; diff -Nru ffmpeg-4.2.2/libavcodec/bitstream.c ffmpeg-4.4/libavcodec/bitstream.c --- ffmpeg-4.2.2/libavcodec/bitstream.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/bitstream.c 2021-04-08 21:28:39.000000000 +0000 @@ -45,13 +45,18 @@ 24, }; +#if FF_API_AVPRIV_PUT_BITS void avpriv_align_put_bits(PutBitContext *s) { - put_bits(s, s->bit_left & 7, 0); + align_put_bits(s); } +void avpriv_copy_bits(PutBitContext *pb, const uint8_t *src, int length) +{ + ff_copy_bits(pb, src, length); +} +#endif -void avpriv_put_string(PutBitContext *pb, const char *string, - int terminate_string) +void ff_put_string(PutBitContext *pb, const char *string, int terminate_string) { while (*string) { put_bits(pb, 8, *string); @@ -61,7 +66,7 @@ put_bits(pb, 8, 0); } -void avpriv_copy_bits(PutBitContext *pb, const uint8_t *src, int length) +void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length) { int words = length >> 4; int bits = length & 15; @@ -99,10 +104,10 @@ v = *(const uint16_t *)ptr; \ break; \ case 4: \ + default: \ + av_assert1(size == 4); \ v = *(const uint32_t *)ptr; \ break; \ - default: \ - av_assert1(0); \ } \ } @@ -127,14 +132,41 @@ return index; } +#define LOCALBUF_ELEMS 1500 // the maximum currently needed is 1296 by rv34 + typedef struct VLCcode { uint8_t bits; - uint16_t symbol; + VLC_TYPE symbol; /** codeword, with the first bit-to-be-read in the msb * (even if intended for a little-endian bitstream reader) */ uint32_t code; } VLCcode; +static int vlc_common_init(VLC *vlc_arg, int nb_bits, int nb_codes, + VLC **vlc, VLC *localvlc, VLCcode **buf, + int flags) +{ + *vlc = vlc_arg; + (*vlc)->bits = nb_bits; + if (flags & INIT_VLC_USE_NEW_STATIC) { + av_assert0(nb_codes <= LOCALBUF_ELEMS); + *localvlc = *vlc_arg; + *vlc = localvlc; + (*vlc)->table_size = 0; + } else { + (*vlc)->table = NULL; + (*vlc)->table_allocated = 0; + (*vlc)->table_size = 0; + } + if (nb_codes > LOCALBUF_ELEMS) { + *buf = av_malloc_array(nb_codes, sizeof(VLCcode)); + if (!*buf) + return AVERROR(ENOMEM); + } + + return 0; +} + static int compare_vlcspec(const void *a, const void *b) { const VLCcode *sa = a, *sb = b; @@ -162,9 +194,9 @@ uint32_t code; volatile VLC_TYPE (* volatile table)[2]; // the double volatile is needed to prevent an internal compiler error in gcc 4.2 - table_size = 1 << table_nb_bits; if (table_nb_bits > 30) return AVERROR(EINVAL); + table_size = 1 << table_nb_bits; table_index = alloc_table(vlc, table_size, flags & INIT_VLC_USE_NEW_STATIC); ff_dlog(NULL, "new table index=%d size=%d\n", table_index, table_size); if (table_index < 0) @@ -182,7 +214,7 @@ j = code >> (32 - table_nb_bits); nb = 1 << (table_nb_bits - n); inc = 1; - if (flags & INIT_VLC_LE) { + if (flags & INIT_VLC_OUTPUT_LE) { j = bitswap_32(code); inc = 1 << n; } @@ -217,7 +249,7 @@ subtable_bits = FFMAX(subtable_bits, n); } subtable_bits = FFMIN(subtable_bits, table_nb_bits); - j = (flags & INIT_VLC_LE) ? bitswap_32(code_prefix) >> (32 - table_nb_bits) : code_prefix; + j = (flags & INIT_VLC_OUTPUT_LE) ? bitswap_32(code_prefix) >> (32 - table_nb_bits) : code_prefix; table[j][1] = -subtable_bits; ff_dlog(NULL, "%4x: n=%d (subtable)\n", j, codes[i].bits + table_nb_bits); @@ -243,6 +275,27 @@ return table_index; } +static int vlc_common_end(VLC *vlc, int nb_bits, int nb_codes, VLCcode *codes, + int flags, VLC *vlc_arg, VLCcode localbuf[LOCALBUF_ELEMS]) +{ + int ret = build_table(vlc, nb_bits, nb_codes, codes, flags); + + if (flags & INIT_VLC_USE_NEW_STATIC) { + if (vlc->table_size != vlc->table_allocated && + !(flags & (INIT_VLC_STATIC_OVERLONG & ~INIT_VLC_USE_NEW_STATIC))) + av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", vlc->table_size, vlc->table_allocated); + av_assert0(ret >= 0); + *vlc_arg = *vlc; + } else { + if (codes != localbuf) + av_free(codes); + if (ret < 0) { + av_freep(&vlc->table); + return ret; + } + } + return 0; +} /* Build VLC decoding tables suitable for use with get_vlc(). @@ -266,9 +319,6 @@ 'wrap' and 'size' make it possible to use any memory configuration and types (byte/word/long) to store the 'bits', 'codes', and 'symbols' tables. - - 'use_static' should be set to 1 for tables, which should be freed - with av_free_static(), 0 if ff_free_vlc() will be used. */ int ff_init_vlc_sparse(VLC *vlc_arg, int nb_bits, int nb_codes, const void *bits, int bits_wrap, int bits_size, @@ -276,52 +326,39 @@ const void *symbols, int symbols_wrap, int symbols_size, int flags) { - VLCcode *buf; + VLCcode localbuf[LOCALBUF_ELEMS], *buf = localbuf; int i, j, ret; - VLCcode localbuf[1500]; // the maximum currently needed is 1296 by rv34 VLC localvlc, *vlc; - vlc = vlc_arg; - vlc->bits = nb_bits; - if (flags & INIT_VLC_USE_NEW_STATIC) { - av_assert0(nb_codes + 1 <= FF_ARRAY_ELEMS(localbuf)); - buf = localbuf; - localvlc = *vlc_arg; - vlc = &localvlc; - vlc->table_size = 0; - } else { - vlc->table = NULL; - vlc->table_allocated = 0; - vlc->table_size = 0; - - buf = av_malloc_array((nb_codes + 1), sizeof(VLCcode)); - if (!buf) - return AVERROR(ENOMEM); - } - + ret = vlc_common_init(vlc_arg, nb_bits, nb_codes, &vlc, &localvlc, + &buf, flags); + if (ret < 0) + return ret; av_assert0(symbols_size <= 2 || !symbols); j = 0; #define COPY(condition)\ for (i = 0; i < nb_codes; i++) { \ - GET_DATA(buf[j].bits, bits, i, bits_wrap, bits_size); \ + unsigned len; \ + GET_DATA(len, bits, i, bits_wrap, bits_size); \ if (!(condition)) \ continue; \ - if (buf[j].bits > 3*nb_bits || buf[j].bits>32) { \ - av_log(NULL, AV_LOG_ERROR, "Too long VLC (%d) in init_vlc\n", buf[j].bits);\ - if (!(flags & INIT_VLC_USE_NEW_STATIC)) \ + if (len > 3*nb_bits || len > 32) { \ + av_log(NULL, AV_LOG_ERROR, "Too long VLC (%u) in init_vlc\n", len);\ + if (buf != localbuf) \ av_free(buf); \ return AVERROR(EINVAL); \ } \ + buf[j].bits = len; \ GET_DATA(buf[j].code, codes, i, codes_wrap, codes_size); \ if (buf[j].code >= (1LL< nb_bits); + COPY(len > nb_bits); // qsort is the slowest part of init_vlc, and could probably be improved or avoided AV_QSORT(buf, j, struct VLCcode, compare_vlcspec); - COPY(buf[j].bits && buf[j].bits <= nb_bits); + COPY(len && len <= nb_bits); nb_codes = j; - ret = build_table(vlc, nb_bits, nb_codes, buf, flags); + return vlc_common_end(vlc, nb_bits, nb_codes, buf, + flags, vlc_arg, localbuf); +} - if (flags & INIT_VLC_USE_NEW_STATIC) { - if(vlc->table_size != vlc->table_allocated) - av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", vlc->table_size, vlc->table_allocated); +int ff_init_vlc_from_lengths(VLC *vlc_arg, int nb_bits, int nb_codes, + const int8_t *lens, int lens_wrap, + const void *symbols, int symbols_wrap, int symbols_size, + int offset, int flags, void *logctx) +{ + VLCcode localbuf[LOCALBUF_ELEMS], *buf = localbuf; + VLC localvlc, *vlc; + uint64_t code; + int ret, j, len_max = FFMIN(32, 3 * nb_bits); - av_assert0(ret >= 0); - *vlc_arg = *vlc; - } else { - av_free(buf); - if (ret < 0) { - av_freep(&vlc->table); - return ret; + ret = vlc_common_init(vlc_arg, nb_bits, nb_codes, &vlc, &localvlc, + &buf, flags); + if (ret < 0) + return ret; + + j = code = 0; + for (int i = 0; i < nb_codes; i++, lens += lens_wrap) { + int len = *lens; + if (len > 0) { + unsigned sym; + + buf[j].bits = len; + if (symbols) + GET_DATA(sym, symbols, i, symbols_wrap, symbols_size) + else + sym = i; + buf[j].symbol = sym + offset; + buf[j++].code = code; + } else if (len < 0) { + len = -len; + } else + continue; + if (len > len_max || code & ((1U << (32 - len)) - 1)) { + av_log(logctx, AV_LOG_ERROR, "Invalid VLC (length %u)\n", len); + goto fail; + } + code += 1U << (32 - len); + if (code > UINT32_MAX + 1ULL) { + av_log(logctx, AV_LOG_ERROR, "Overdetermined VLC tree\n"); + goto fail; } } - return 0; + return vlc_common_end(vlc, nb_bits, j, buf, + flags, vlc_arg, localbuf); +fail: + if (buf != localbuf) + av_free(buf); + return AVERROR_INVALIDDATA; } - void ff_free_vlc(VLC *vlc) { av_freep(&vlc->table); diff -Nru ffmpeg-4.2.2/libavcodec/bitstream_filters.c ffmpeg-4.4/libavcodec/bitstream_filters.c --- ffmpeg-4.2.2/libavcodec/bitstream_filters.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/bitstream_filters.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,9 +22,10 @@ #include "libavutil/log.h" #include "avcodec.h" -#include "bsf.h" +#include "bsf_internal.h" extern const AVBitStreamFilter ff_aac_adtstoasc_bsf; +extern const AVBitStreamFilter ff_av1_frame_merge_bsf; extern const AVBitStreamFilter ff_av1_frame_split_bsf; extern const AVBitStreamFilter ff_av1_metadata_bsf; extern const AVBitStreamFilter ff_chomp_bsf; @@ -48,8 +49,11 @@ extern const AVBitStreamFilter ff_mov2textsub_bsf; extern const AVBitStreamFilter ff_noise_bsf; extern const AVBitStreamFilter ff_null_bsf; +extern const AVBitStreamFilter ff_opus_metadata_bsf; +extern const AVBitStreamFilter ff_pcm_rechunk_bsf; extern const AVBitStreamFilter ff_prores_metadata_bsf; extern const AVBitStreamFilter ff_remove_extradata_bsf; +extern const AVBitStreamFilter ff_setts_bsf; extern const AVBitStreamFilter ff_text2movsub_bsf; extern const AVBitStreamFilter ff_trace_headers_bsf; extern const AVBitStreamFilter ff_truehd_core_bsf; @@ -93,6 +97,7 @@ return NULL; } +#if FF_API_CHILD_CLASS_NEXT const AVClass *ff_bsf_child_class_next(const AVClass *prev) { const AVBitStreamFilter *f = NULL; @@ -110,5 +115,18 @@ if (f->priv_class) return f->priv_class; } + return NULL; +} +#endif + +const AVClass *ff_bsf_child_class_iterate(void **opaque) +{ + const AVBitStreamFilter *f; + + /* find next filter with priv options */ + while ((f = av_bsf_iterate(opaque))) { + if (f->priv_class) + return f->priv_class; + } return NULL; } diff -Nru ffmpeg-4.2.2/libavcodec/bmp_parser.c ffmpeg-4.4/libavcodec/bmp_parser.c --- ffmpeg-4.2.2/libavcodec/bmp_parser.c 2017-12-31 02:32:05.000000000 +0000 +++ ffmpeg-4.4/libavcodec/bmp_parser.c 2020-07-11 10:39:30.000000000 +0000 @@ -45,6 +45,7 @@ int i = 0; *poutbuf_size = 0; + *poutbuf = NULL; restart: if (bpc->pc.frame_start_found <= 2+4+4) { diff -Nru ffmpeg-4.2.2/libavcodec/bmvaudio.c ffmpeg-4.4/libavcodec/bmvaudio.c --- ffmpeg-4.2.2/libavcodec/bmvaudio.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/bmvaudio.c 2021-04-08 21:28:39.000000000 +0000 @@ -85,5 +85,5 @@ .id = AV_CODEC_ID_BMV_AUDIO, .init = bmv_aud_decode_init, .decode = bmv_aud_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; diff -Nru ffmpeg-4.2.2/libavcodec/bsf.c ffmpeg-4.4/libavcodec/bsf.c --- ffmpeg-4.2.2/libavcodec/bsf.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,14 +18,19 @@ #include +#include "libavutil/avassert.h" #include "libavutil/log.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" +#include "codec_desc.h" +#include "codec_par.h" + +#define IS_EMPTY(pkt) (!(pkt)->data && !(pkt)->side_data_elems) struct AVBSFInternal { AVPacket *buffer_pkt; @@ -40,16 +45,15 @@ return; ctx = *pctx; - if (ctx->filter->close) - ctx->filter->close(ctx); + if (ctx->internal) { + if (ctx->filter->close) + ctx->filter->close(ctx); + av_packet_free(&ctx->internal->buffer_pkt); + av_freep(&ctx->internal); + } if (ctx->filter->priv_class && ctx->priv_data) av_opt_free(ctx->priv_data); - av_opt_free(ctx); - - if (ctx->internal) - av_packet_free(&ctx->internal->buffer_pkt); - av_freep(&ctx->internal); av_freep(&ctx->priv_data); avcodec_parameters_free(&ctx->par_in); @@ -66,12 +70,21 @@ return NULL; } +static const char *bsf_to_name(void *bsf) +{ + return ((AVBSFContext *)bsf)->filter->name; +} + static const AVClass bsf_class = { .class_name = "AVBSFContext", - .item_name = av_default_item_name, + .item_name = bsf_to_name, .version = LIBAVUTIL_VERSION_INT, .child_next = bsf_child_next, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = ff_bsf_child_class_next, +#endif + .child_class_iterate = ff_bsf_child_class_iterate, + .category = AV_CLASS_CATEGORY_BITSTREAM_FILTER, }; const AVClass *av_bsf_get_class(void) @@ -82,6 +95,7 @@ int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx) { AVBSFContext *ctx; + AVBSFInternal *bsfi; int ret; ctx = av_mallocz(sizeof(*ctx)); @@ -97,21 +111,6 @@ ret = AVERROR(ENOMEM); goto fail; } - - ctx->internal = av_mallocz(sizeof(*ctx->internal)); - if (!ctx->internal) { - ret = AVERROR(ENOMEM); - goto fail; - } - - ctx->internal->buffer_pkt = av_packet_alloc(); - if (!ctx->internal->buffer_pkt) { - ret = AVERROR(ENOMEM); - goto fail; - } - - av_opt_set_defaults(ctx); - /* allocate priv data and init private options */ if (filter->priv_data_size) { ctx->priv_data = av_mallocz(filter->priv_data_size); @@ -124,6 +123,20 @@ av_opt_set_defaults(ctx->priv_data); } } + /* Allocate AVBSFInternal; must happen after priv_data has been allocated + * so that a filter->close needing priv_data is never called without. */ + bsfi = av_mallocz(sizeof(*bsfi)); + if (!bsfi) { + ret = AVERROR(ENOMEM); + goto fail; + } + ctx->internal = bsfi; + + bsfi->buffer_pkt = av_packet_alloc(); + if (!bsfi->buffer_pkt) { + ret = AVERROR(ENOMEM); + goto fail; + } *pctx = ctx; return 0; @@ -175,9 +188,11 @@ void av_bsf_flush(AVBSFContext *ctx) { - ctx->internal->eof = 0; + AVBSFInternal *bsfi = ctx->internal; - av_packet_unref(ctx->internal->buffer_pkt); + bsfi->eof = 0; + + av_packet_unref(bsfi->buffer_pkt); if (ctx->filter->flush) ctx->filter->flush(ctx); @@ -185,26 +200,26 @@ int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt) { + AVBSFInternal *bsfi = ctx->internal; int ret; - if (!pkt || (!pkt->data && !pkt->side_data_elems)) { - ctx->internal->eof = 1; + if (!pkt || IS_EMPTY(pkt)) { + bsfi->eof = 1; return 0; } - if (ctx->internal->eof) { + if (bsfi->eof) { av_log(ctx, AV_LOG_ERROR, "A non-NULL packet sent after an EOF.\n"); return AVERROR(EINVAL); } - if (ctx->internal->buffer_pkt->data || - ctx->internal->buffer_pkt->side_data_elems) + if (!IS_EMPTY(bsfi->buffer_pkt)) return AVERROR(EAGAIN); ret = av_packet_make_refcounted(pkt); if (ret < 0) return ret; - av_packet_move_ref(ctx->internal->buffer_pkt, pkt); + av_packet_move_ref(bsfi->buffer_pkt, pkt); return 0; } @@ -216,38 +231,36 @@ int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt) { - AVBSFInternal *in = ctx->internal; + AVBSFInternal *bsfi = ctx->internal; AVPacket *tmp_pkt; - if (in->eof) + if (bsfi->eof) return AVERROR_EOF; - if (!ctx->internal->buffer_pkt->data && - !ctx->internal->buffer_pkt->side_data_elems) + if (IS_EMPTY(bsfi->buffer_pkt)) return AVERROR(EAGAIN); tmp_pkt = av_packet_alloc(); if (!tmp_pkt) return AVERROR(ENOMEM); - *pkt = ctx->internal->buffer_pkt; - ctx->internal->buffer_pkt = tmp_pkt; + *pkt = bsfi->buffer_pkt; + bsfi->buffer_pkt = tmp_pkt; return 0; } int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt) { - AVBSFInternal *in = ctx->internal; + AVBSFInternal *bsfi = ctx->internal; - if (in->eof) + if (bsfi->eof) return AVERROR_EOF; - if (!ctx->internal->buffer_pkt->data && - !ctx->internal->buffer_pkt->side_data_elems) + if (IS_EMPTY(bsfi->buffer_pkt)) return AVERROR(EAGAIN); - av_packet_move_ref(pkt, ctx->internal->buffer_pkt); + av_packet_move_ref(pkt, bsfi->buffer_pkt); return 0; } @@ -259,7 +272,6 @@ int nb_bsfs; unsigned idx; // index of currently processed BSF - unsigned flushed_idx; // index of BSF being flushed char * item_name; } BSFListContext; @@ -297,58 +309,43 @@ static int bsf_list_filter(AVBSFContext *bsf, AVPacket *out) { BSFListContext *lst = bsf->priv_data; - int ret; + int ret, eof = 0; if (!lst->nb_bsfs) return ff_bsf_get_packet_ref(bsf, out); while (1) { - if (lst->idx > lst->flushed_idx) { + /* get a packet from the previous filter up the chain */ + if (lst->idx) ret = av_bsf_receive_packet(lst->bsfs[lst->idx-1], out); - if (ret == AVERROR(EAGAIN)) { - /* no more packets from idx-1, try with previous */ - ret = 0; - lst->idx--; - continue; - } else if (ret == AVERROR_EOF) { - /* filter idx-1 is done, continue with idx...nb_bsfs */ - lst->flushed_idx = lst->idx; - continue; - }else if (ret < 0) { - /* filtering error */ - break; - } - } else { + else ret = ff_bsf_get_packet_ref(bsf, out); - if (ret == AVERROR_EOF) { - lst->idx = lst->flushed_idx; - } else if (ret < 0) - break; - } + if (ret == AVERROR(EAGAIN)) { + if (!lst->idx) + return ret; + lst->idx--; + continue; + } else if (ret == AVERROR_EOF) { + eof = 1; + } else if (ret < 0) + return ret; + /* send it to the next filter down the chain */ if (lst->idx < lst->nb_bsfs) { - AVPacket *pkt; - if (ret == AVERROR_EOF && lst->idx == lst->flushed_idx) { - /* ff_bsf_get_packet_ref returned EOF and idx is first - * filter of yet not flushed filter chain */ - pkt = NULL; - } else { - pkt = out; + ret = av_bsf_send_packet(lst->bsfs[lst->idx], eof ? NULL : out); + av_assert1(ret != AVERROR(EAGAIN)); + if (ret < 0) { + av_packet_unref(out); + return ret; } - ret = av_bsf_send_packet(lst->bsfs[lst->idx], pkt); - if (ret < 0) - break; lst->idx++; + eof = 0; + } else if (eof) { + return ret; } else { - /* The end of filter chain, break to return result */ - break; + return 0; } } - - if (ret < 0) - av_packet_unref(out); - - return ret; } static void bsf_list_flush(AVBSFContext *bsf) @@ -357,7 +354,7 @@ for (int i = 0; i < lst->nb_bsfs; i++) av_bsf_flush(lst->bsfs[i]); - lst->idx = lst->flushed_idx = 0; + lst->idx = 0; } static void bsf_list_close(AVBSFContext *bsf) @@ -440,7 +437,7 @@ return av_dynarray_add_nofree(&lst->bsfs, &lst->nb_bsfs, bsf); } -int av_bsf_list_append2(AVBSFList *lst, const char *bsf_name, AVDictionary ** options) +static int bsf_list_append_internal(AVBSFList *lst, const char *bsf_name, const char *options, AVDictionary ** options_dict) { int ret; const AVBitStreamFilter *filter; @@ -454,8 +451,20 @@ if (ret < 0) return ret; - if (options) { - ret = av_opt_set_dict2(bsf, options, AV_OPT_SEARCH_CHILDREN); + if (options && filter->priv_class) { + const AVOption *opt = av_opt_next(bsf->priv_data, NULL); + const char * shorthand[2] = {NULL}; + + if (opt) + shorthand[0] = opt->name; + + ret = av_opt_set_from_string(bsf->priv_data, options, shorthand, "=", ":"); + if (ret < 0) + goto end; + } + + if (options_dict) { + ret = av_opt_set_dict2(bsf, options_dict, AV_OPT_SEARCH_CHILDREN); if (ret < 0) goto end; } @@ -469,6 +478,11 @@ return ret; } +int av_bsf_list_append2(AVBSFList *lst, const char *bsf_name, AVDictionary ** options) +{ + return bsf_list_append_internal(lst, bsf_name, NULL, options); +} + int av_bsf_list_finalize(AVBSFList **lst, AVBSFContext **bsf) { int ret = 0; @@ -495,33 +509,15 @@ return ret; } -static int bsf_parse_single(const char *str, AVBSFList *bsf_lst) +static int bsf_parse_single(char *str, AVBSFList *bsf_lst) { - char *bsf_name, *bsf_options_str, *buf; - AVDictionary *bsf_options = NULL; - int ret = 0; - - if (!(buf = av_strdup(str))) - return AVERROR(ENOMEM); - - bsf_name = av_strtok(buf, "=", &bsf_options_str); - if (!bsf_name) { - ret = AVERROR(EINVAL); - goto end; - } - - if (bsf_options_str) { - ret = av_dict_parse_string(&bsf_options, bsf_options_str, "=", ":", 0); - if (ret < 0) - goto end; - } + char *bsf_name, *bsf_options_str; - ret = av_bsf_list_append2(bsf_lst, bsf_name, &bsf_options); + bsf_name = av_strtok(str, "=", &bsf_options_str); + if (!bsf_name) + return AVERROR(EINVAL); - av_dict_free(&bsf_options); -end: - av_free(buf); - return ret; + return bsf_list_append_internal(bsf_lst, bsf_name, bsf_options_str, NULL); } int av_bsf_list_parse_str(const char *str, AVBSFContext **bsf_lst) @@ -542,11 +538,7 @@ goto end; } - while (1) { - bsf_str = av_strtok(buf, ",", &saveptr); - if (!bsf_str) - break; - + while (bsf_str = av_strtok(buf, ",", &saveptr)) { ret = bsf_parse_single(bsf_str, lst); if (ret < 0) goto end; diff -Nru ffmpeg-4.2.2/libavcodec/bsf.h ffmpeg-4.4/libavcodec/bsf.h --- ffmpeg-4.2.2/libavcodec/bsf.h 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/bsf.h 2021-04-08 21:28:39.000000000 +0000 @@ -1,4 +1,6 @@ /* + * Bitstream filters public API + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -19,26 +21,305 @@ #ifndef AVCODEC_BSF_H #define AVCODEC_BSF_H -#include "avcodec.h" +#include "libavutil/dict.h" +#include "libavutil/log.h" +#include "libavutil/rational.h" + +#include "codec_id.h" +#include "codec_par.h" +#include "packet.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +typedef struct AVBSFInternal AVBSFInternal; + +/** + * The bitstream filter state. + * + * This struct must be allocated with av_bsf_alloc() and freed with + * av_bsf_free(). + * + * The fields in the struct will only be changed (by the caller or by the + * filter) as described in their documentation, and are to be considered + * immutable otherwise. + */ +typedef struct AVBSFContext { + /** + * A class for logging and AVOptions + */ + const AVClass *av_class; + + /** + * The bitstream filter this context is an instance of. + */ + const struct AVBitStreamFilter *filter; + + /** + * Opaque libavcodec internal data. Must not be touched by the caller in any + * way. + */ + AVBSFInternal *internal; + + /** + * Opaque filter-specific private data. If filter->priv_class is non-NULL, + * this is an AVOptions-enabled struct. + */ + void *priv_data; + + /** + * Parameters of the input stream. This field is allocated in + * av_bsf_alloc(), it needs to be filled by the caller before + * av_bsf_init(). + */ + AVCodecParameters *par_in; + + /** + * Parameters of the output stream. This field is allocated in + * av_bsf_alloc(), it is set by the filter in av_bsf_init(). + */ + AVCodecParameters *par_out; + + /** + * The timebase used for the timestamps of the input packets. Set by the + * caller before av_bsf_init(). + */ + AVRational time_base_in; + + /** + * The timebase used for the timestamps of the output packets. Set by the + * filter in av_bsf_init(). + */ + AVRational time_base_out; +} AVBSFContext; + +typedef struct AVBitStreamFilter { + const char *name; + + /** + * A list of codec ids supported by the filter, terminated by + * AV_CODEC_ID_NONE. + * May be NULL, in that case the bitstream filter works with any codec id. + */ + const enum AVCodecID *codec_ids; + + /** + * A class for the private data, used to declare bitstream filter private + * AVOptions. This field is NULL for bitstream filters that do not declare + * any options. + * + * If this field is non-NULL, the first member of the filter private data + * must be a pointer to AVClass, which will be set by libavcodec generic + * code to this class. + */ + const AVClass *priv_class; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavcodec and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + + int priv_data_size; + int (*init)(AVBSFContext *ctx); + int (*filter)(AVBSFContext *ctx, AVPacket *pkt); + void (*close)(AVBSFContext *ctx); + void (*flush)(AVBSFContext *ctx); +} AVBitStreamFilter; /** - * Called by the bitstream filters to get the next packet for filtering. - * The filter is responsible for either freeing the packet or passing it to the - * caller. + * @return a bitstream filter with the specified name or NULL if no such + * bitstream filter exists. */ -int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt); +const AVBitStreamFilter *av_bsf_get_by_name(const char *name); /** - * Called by bitstream filters to get packet for filtering. - * The reference to packet is moved to provided packet structure. + * Iterate over all registered bitstream filters. * - * @param ctx pointer to AVBSFContext of filter - * @param pkt pointer to packet to move reference to + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. * - * @return 0>= on success, negative AVERROR in case of failure + * @return the next registered bitstream filter or NULL when the iteration is + * finished + */ +const AVBitStreamFilter *av_bsf_iterate(void **opaque); + +/** + * Allocate a context for a given bitstream filter. The caller must fill in the + * context parameters as described in the documentation and then call + * av_bsf_init() before sending any data to the filter. + * + * @param filter the filter for which to allocate an instance. + * @param ctx a pointer into which the pointer to the newly-allocated context + * will be written. It must be freed with av_bsf_free() after the + * filtering is done. + * + * @return 0 on success, a negative AVERROR code on failure + */ +int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx); + +/** + * Prepare the filter for use, after all the parameters and options have been + * set. + */ +int av_bsf_init(AVBSFContext *ctx); + +/** + * Submit a packet for filtering. + * + * After sending each packet, the filter must be completely drained by calling + * av_bsf_receive_packet() repeatedly until it returns AVERROR(EAGAIN) or + * AVERROR_EOF. + * + * @param pkt the packet to filter. The bitstream filter will take ownership of + * the packet and reset the contents of pkt. pkt is not touched if an error occurs. + * If pkt is empty (i.e. NULL, or pkt->data is NULL and pkt->side_data_elems zero), + * it signals the end of the stream (i.e. no more non-empty packets will be sent; + * sending more empty packets does nothing) and will cause the filter to output + * any packets it may have buffered internally. + * + * @return 0 on success. AVERROR(EAGAIN) if packets need to be retrieved from the + * filter (using av_bsf_receive_packet()) before new input can be consumed. Another + * negative AVERROR value if an error occurs. + */ +int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt); + +/** + * Retrieve a filtered packet. + * + * @param[out] pkt this struct will be filled with the contents of the filtered + * packet. It is owned by the caller and must be freed using + * av_packet_unref() when it is no longer needed. + * This parameter should be "clean" (i.e. freshly allocated + * with av_packet_alloc() or unreffed with av_packet_unref()) + * when this function is called. If this function returns + * successfully, the contents of pkt will be completely + * overwritten by the returned data. On failure, pkt is not + * touched. + * + * @return 0 on success. AVERROR(EAGAIN) if more packets need to be sent to the + * filter (using av_bsf_send_packet()) to get more output. AVERROR_EOF if there + * will be no further output from the filter. Another negative AVERROR value if + * an error occurs. + * + * @note one input packet may result in several output packets, so after sending + * a packet with av_bsf_send_packet(), this function needs to be called + * repeatedly until it stops returning 0. It is also possible for a filter to + * output fewer packets than were sent to it, so this function may return + * AVERROR(EAGAIN) immediately after a successful av_bsf_send_packet() call. + */ +int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt); + +/** + * Reset the internal bitstream filter state. Should be called e.g. when seeking. */ -int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt); +void av_bsf_flush(AVBSFContext *ctx); -const AVClass *ff_bsf_child_class_next(const AVClass *prev); +/** + * Free a bitstream filter context and everything associated with it; write NULL + * into the supplied pointer. + */ +void av_bsf_free(AVBSFContext **ctx); + +/** + * Get the AVClass for AVBSFContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *av_bsf_get_class(void); + +/** + * Structure for chain/list of bitstream filters. + * Empty list can be allocated by av_bsf_list_alloc(). + */ +typedef struct AVBSFList AVBSFList; + +/** + * Allocate empty list of bitstream filters. + * The list must be later freed by av_bsf_list_free() + * or finalized by av_bsf_list_finalize(). + * + * @return Pointer to @ref AVBSFList on success, NULL in case of failure + */ +AVBSFList *av_bsf_list_alloc(void); + +/** + * Free list of bitstream filters. + * + * @param lst Pointer to pointer returned by av_bsf_list_alloc() + */ +void av_bsf_list_free(AVBSFList **lst); + +/** + * Append bitstream filter to the list of bitstream filters. + * + * @param lst List to append to + * @param bsf Filter context to be appended + * + * @return >=0 on success, negative AVERROR in case of failure + */ +int av_bsf_list_append(AVBSFList *lst, AVBSFContext *bsf); + +/** + * Construct new bitstream filter context given it's name and options + * and append it to the list of bitstream filters. + * + * @param lst List to append to + * @param bsf_name Name of the bitstream filter + * @param options Options for the bitstream filter, can be set to NULL + * + * @return >=0 on success, negative AVERROR in case of failure + */ +int av_bsf_list_append2(AVBSFList *lst, const char * bsf_name, AVDictionary **options); +/** + * Finalize list of bitstream filters. + * + * This function will transform @ref AVBSFList to single @ref AVBSFContext, + * so the whole chain of bitstream filters can be treated as single filter + * freshly allocated by av_bsf_alloc(). + * If the call is successful, @ref AVBSFList structure is freed and lst + * will be set to NULL. In case of failure, caller is responsible for + * freeing the structure by av_bsf_list_free() + * + * @param lst Filter list structure to be transformed + * @param[out] bsf Pointer to be set to newly created @ref AVBSFContext structure + * representing the chain of bitstream filters + * + * @return >=0 on success, negative AVERROR in case of failure + */ +int av_bsf_list_finalize(AVBSFList **lst, AVBSFContext **bsf); + +/** + * Parse string describing list of bitstream filters and create single + * @ref AVBSFContext describing the whole chain of bitstream filters. + * Resulting @ref AVBSFContext can be treated as any other @ref AVBSFContext freshly + * allocated by av_bsf_alloc(). + * + * @param str String describing chain of bitstream filters in format + * `bsf1[=opt1=val1:opt2=val2][,bsf2]` + * @param[out] bsf Pointer to be set to newly created @ref AVBSFContext structure + * representing the chain of bitstream filters + * + * @return >=0 on success, negative AVERROR in case of failure + */ +int av_bsf_list_parse_str(const char *str, AVBSFContext **bsf); + +/** + * Get null/pass-through bitstream filter. + * + * @param[out] bsf Pointer to be set to new instance of pass-through bitstream filter + * + * @return + */ +int av_bsf_get_null_filter(AVBSFContext **bsf); + +/** + * @} + */ -#endif /* AVCODEC_BSF_H */ +#endif // AVCODEC_BSF_H diff -Nru ffmpeg-4.2.2/libavcodec/bsf_internal.h ffmpeg-4.4/libavcodec/bsf_internal.h --- ffmpeg-4.2.2/libavcodec/bsf_internal.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/bsf_internal.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,51 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_BSF_INTERNAL_H +#define AVCODEC_BSF_INTERNAL_H + +#include "libavutil/log.h" + +#include "bsf.h" +#include "packet.h" + +/** + * Called by the bitstream filters to get the next packet for filtering. + * The filter is responsible for either freeing the packet or passing it to the + * caller. + */ +int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt); + +/** + * Called by bitstream filters to get packet for filtering. + * The reference to packet is moved to provided packet structure. + * + * @param ctx pointer to AVBSFContext of filter + * @param pkt pointer to packet to move reference to + * + * @return 0 on success, negative AVERROR in case of failure + */ +int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt); + +#if FF_API_CHILD_CLASS_NEXT +const AVClass *ff_bsf_child_class_next(const AVClass *prev); +#endif + +const AVClass *ff_bsf_child_class_iterate(void **opaque); + +#endif /* AVCODEC_BSF_INTERNAL_H */ diff -Nru ffmpeg-4.2.2/libavcodec/bytestream.h ffmpeg-4.4/libavcodec/bytestream.h --- ffmpeg-4.2.2/libavcodec/bytestream.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/bytestream.h 2021-04-08 21:28:39.000000000 +0000 @@ -77,11 +77,15 @@ } \ return bytestream2_get_ ## name ## u(g); \ } \ +static av_always_inline type bytestream2_peek_ ## name ## u(GetByteContext *g) \ +{ \ + return read(g->buffer); \ +} \ static av_always_inline type bytestream2_peek_ ## name(GetByteContext *g) \ { \ if (g->buffer_end - g->buffer < bytes) \ return 0; \ - return read(g->buffer); \ + return bytestream2_peek_ ## name ## u(g); \ } DEF(uint64_t, le64, 8, AV_RL64, AV_WL64) @@ -151,12 +155,12 @@ p->eof = 0; } -static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g) +static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g) { return g->buffer_end - g->buffer; } -static av_always_inline unsigned int bytestream2_get_bytes_left_p(PutByteContext *p) +static av_always_inline int bytestream2_get_bytes_left_p(PutByteContext *p) { return p->buffer_end - p->buffer; } diff -Nru ffmpeg-4.2.2/libavcodec/c93.c ffmpeg-4.4/libavcodec/c93.c --- ffmpeg-4.2.2/libavcodec/c93.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/c93.c 2021-04-08 21:28:39.000000000 +0000 @@ -63,10 +63,8 @@ s->pictures[0] = av_frame_alloc(); s->pictures[1] = av_frame_alloc(); - if (!s->pictures[0] || !s->pictures[1]) { - decode_end(avctx); + if (!s->pictures[0] || !s->pictures[1]) return AVERROR(ENOMEM); - } return 0; } @@ -138,7 +136,7 @@ c93->currentpic ^= 1; - if ((ret = ff_reget_buffer(avctx, newpic)) < 0) + if ((ret = ff_reget_buffer(avctx, newpic, 0)) < 0) return ret; stride = newpic->linesize[0]; @@ -269,5 +267,5 @@ .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/cabac.c ffmpeg-4.4/libavcodec/cabac.c --- ffmpeg-4.2.2/libavcodec/cabac.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cabac.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,7 +27,7 @@ #include #include "libavutil/common.h" -#include "libavutil/timer.h" +#include "libavutil/mem_internal.h" #include "cabac.h" #include "cabac_functions.h" @@ -159,18 +159,6 @@ }; /** - * @param buf_size size of buf in bits - */ -void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size){ - init_put_bits(&c->pb, buf, buf_size); - - c->low= 0; - c->range= 0x1FE; - c->outstanding_count= 0; - c->pb.bit_left++; //avoids firstBitFlag -} - -/** * * @param buf_size size of buf in bits */ diff -Nru ffmpeg-4.2.2/libavcodec/cabac_functions.h ffmpeg-4.4/libavcodec/cabac_functions.h --- ffmpeg-4.2.2/libavcodec/cabac_functions.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cabac_functions.h 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ #ifndef AVCODEC_CABAC_FUNCTIONS_H #define AVCODEC_CABAC_FUNCTIONS_H +#include #include #include "cabac.h" diff -Nru ffmpeg-4.2.2/libavcodec/cabac.h ffmpeg-4.4/libavcodec/cabac.h --- ffmpeg-4.2.2/libavcodec/cabac.h 2018-07-17 09:27:39.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cabac.h 2021-04-08 21:28:39.000000000 +0000 @@ -29,8 +29,6 @@ #include -#include "put_bits.h" - extern const uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63]; #define H264_NORM_SHIFT_OFFSET 0 #define H264_LPS_RANGE_OFFSET 512 @@ -43,14 +41,11 @@ typedef struct CABACContext{ int low; int range; - int outstanding_count; const uint8_t *bytestream_start; const uint8_t *bytestream; const uint8_t *bytestream_end; - PutBitContext pb; }CABACContext; -void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size); int ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size); #endif /* AVCODEC_CABAC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/cavs.c ffmpeg-4.4/libavcodec/cavs.c --- ffmpeg-4.2.2/libavcodec/cavs.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cavs.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,6 +25,8 @@ * @author Stefan Gehrer */ +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "get_bits.h" #include "golomb.h" diff -Nru ffmpeg-4.2.2/libavcodec/cavsdec.c ffmpeg-4.4/libavcodec/cavsdec.c --- ffmpeg-4.2.2/libavcodec/cavsdec.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cavsdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -676,7 +676,7 @@ } h->pred_mode_Y[pos] = predpred; } - pred_mode_uv = get_ue_golomb(gb); + pred_mode_uv = get_ue_golomb_31(gb); if (pred_mode_uv > 6) { av_log(h->avctx, AV_LOG_ERROR, "illegal intra chroma pred mode\n"); return AVERROR_INVALIDDATA; @@ -1101,11 +1101,20 @@ do { if (check_for_slice(h)) skip_count = -1; - if (h->skip_mode_flag && (skip_count < 0)) + if (h->skip_mode_flag && (skip_count < 0)) { + if (get_bits_left(&h->gb) < 1) { + ret = AVERROR_INVALIDDATA; + break; + } skip_count = get_ue_golomb(&h->gb); + } if (h->skip_mode_flag && skip_count--) { decode_mb_p(h, P_SKIP); } else { + if (get_bits_left(&h->gb) < 1) { + ret = AVERROR_INVALIDDATA; + break; + } mb_type = get_ue_golomb(&h->gb) + P_SKIP + h->skip_mode_flag; if (mb_type > P_8X8) ret = decode_mb_i(h, mb_type - P_8X8 - 1); @@ -1119,11 +1128,20 @@ do { if (check_for_slice(h)) skip_count = -1; - if (h->skip_mode_flag && (skip_count < 0)) + if (h->skip_mode_flag && (skip_count < 0)) { + if (get_bits_left(&h->gb) < 1) { + ret = AVERROR_INVALIDDATA; + break; + } skip_count = get_ue_golomb(&h->gb); + } if (h->skip_mode_flag && skip_count--) { ret = decode_mb_b(h, B_SKIP); } else { + if (get_bits_left(&h->gb) < 1) { + ret = AVERROR_INVALIDDATA; + break; + } mb_type = get_ue_golomb(&h->gb) + B_SKIP + h->skip_mode_flag; if (mb_type > B_8X8) ret = decode_mb_i(h, mb_type - B_8X8 - 1); diff -Nru ffmpeg-4.2.2/libavcodec/cavsdsp.c ffmpeg-4.4/libavcodec/cavsdsp.c --- ffmpeg-4.2.2/libavcodec/cavsdsp.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cavsdsp.c 2020-07-09 09:17:46.000000000 +0000 @@ -201,20 +201,20 @@ src[0][0] += 8; for( i = 0; i < 8; i++ ) { - const int a0 = 3*src[i][1] - (src[i][7]<<1); - const int a1 = 3*src[i][3] + (src[i][5]<<1); - const int a2 = (src[i][3]<<1) - 3*src[i][5]; - const int a3 = (src[i][1]<<1) + 3*src[i][7]; - - const int b4 = ((a0 + a1 + a3)<<1) + a1; - const int b5 = ((a0 - a1 + a2)<<1) + a0; - const int b6 = ((a3 - a2 - a1)<<1) + a3; - const int b7 = ((a0 - a2 - a3)<<1) - a2; - - const int a7 = (src[i][2]<<2) - 10*src[i][6]; - const int a6 = (src[i][6]<<2) + 10*src[i][2]; - const int a5 = ((src[i][0] - src[i][4]) << 3) + 4; - const int a4 = ((src[i][0] + src[i][4]) << 3) + 4; + const int a0 = 3 * src[i][1] - 2 * src[i][7]; + const int a1 = 3 * src[i][3] + 2 * src[i][5]; + const int a2 = 2 * src[i][3] - 3 * src[i][5]; + const int a3 = 2 * src[i][1] + 3 * src[i][7]; + + const int b4 = 2 * (a0 + a1 + a3) + a1; + const int b5 = 2 * (a0 - a1 + a2) + a0; + const int b6 = 2 * (a3 - a2 - a1) + a3; + const int b7 = 2 * (a0 - a2 - a3) - a2; + + const int a7 = 4 * src[i][2] - 10 * src[i][6]; + const int a6 = 4 * src[i][6] + 10 * src[i][2]; + const int a5 = 8 * (src[i][0] - src[i][4]) + 4; + const int a4 = 8 * (src[i][0] + src[i][4]) + 4; const int b0 = a4 + a6; const int b1 = a5 + a7; @@ -231,20 +231,20 @@ src[i][7] = (b0 - b4) >> 3; } for( i = 0; i < 8; i++ ) { - const int a0 = 3*src[1][i] - (src[7][i]<<1); - const int a1 = 3*src[3][i] + (src[5][i]<<1); - const int a2 = (src[3][i]<<1) - 3*src[5][i]; - const int a3 = (src[1][i]<<1) + 3*src[7][i]; - - const int b4 = ((a0 + a1 + a3)<<1) + a1; - const int b5 = ((a0 - a1 + a2)<<1) + a0; - const int b6 = ((a3 - a2 - a1)<<1) + a3; - const int b7 = ((a0 - a2 - a3)<<1) - a2; - - const int a7 = (src[2][i]<<2) - 10*src[6][i]; - const int a6 = (src[6][i]<<2) + 10*src[2][i]; - const int a5 = (src[0][i] - src[4][i]) << 3; - const int a4 = (src[0][i] + src[4][i]) << 3; + const int a0 = 3 * src[1][i] - 2 * src[7][i]; + const int a1 = 3 * src[3][i] + 2 * src[5][i]; + const int a2 = 2 * src[3][i] - 3 * src[5][i]; + const int a3 = 2 * src[1][i] + 3 * src[7][i]; + + const int b4 = 2 * (a0 + a1 + a3) + a1; + const int b5 = 2 * (a0 - a1 + a2) + a0; + const int b6 = 2 * (a3 - a2 - a1) + a3; + const int b7 = 2 * (a0 - a2 - a3) - a2; + + const int a7 = 4 * src[2][i] - 10 * src[6][i]; + const int a6 = 4 * src[6][i] + 10 * src[2][i]; + const int a5 = 8 * (src[0][i] - src[4][i]); + const int a4 = 8 * (src[0][i] + src[4][i]); const int b0 = a4 + a6; const int b1 = a5 + a7; diff -Nru ffmpeg-4.2.2/libavcodec/cavs.h ffmpeg-4.4/libavcodec/cavs.h --- ffmpeg-4.2.2/libavcodec/cavs.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cavs.h 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,8 @@ #ifndef AVCODEC_CAVS_H #define AVCODEC_CAVS_H +#include "libavutil/mem_internal.h" + #include "cavsdsp.h" #include "blockdsp.h" #include "h264chroma.h" diff -Nru ffmpeg-4.2.2/libavcodec/cbs_av1.c ffmpeg-4.4/libavcodec/cbs_av1.c --- ffmpeg-4.2.2/libavcodec/cbs_av1.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_av1.c 2021-04-08 21:28:39.000000000 +0000 @@ -17,6 +17,7 @@ */ #include "libavutil/avassert.h" +#include "libavutil/opt.h" #include "libavutil/pixfmt.h" #include "cbs.h" @@ -120,15 +121,11 @@ if (ctx->trace_enable) position = put_bits_count(pbc); - if (value == 0) { - zeroes = 0; - put_bits(pbc, 1, 1); - } else { - zeroes = av_log2(value + 1); - v = value - (1 << zeroes) + 1; - put_bits(pbc, zeroes + 1, 1); - put_bits(pbc, zeroes, v); - } + zeroes = av_log2(value + 1); + v = value - (1U << zeroes) + 1; + put_bits(pbc, zeroes, 0); + put_bits(pbc, 1, 1); + put_bits(pbc, zeroes, v); if (ctx->trace_enable) { char bits[65]; @@ -170,6 +167,9 @@ break; } + if (value > UINT32_MAX) + return AVERROR_INVALIDDATA; + if (ctx->trace_enable) ff_cbs_trace_syntax_element(ctx, position, name, NULL, "", value); @@ -211,8 +211,8 @@ uint32_t n, const char *name, const int *subscripts, uint32_t *write_to) { - uint32_t w, m, v, extra_bit, value; - int position; + uint32_t m, v, extra_bit, value; + int position, w; av_assert0(n > 0); @@ -547,12 +547,12 @@ #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL) #define fb(width, name) \ - xf(width, name, current->name, 0, MAX_UINT_BITS(width), 0) + xf(width, name, current->name, 0, MAX_UINT_BITS(width), 0, ) #define fc(width, name, range_min, range_max) \ - xf(width, name, current->name, range_min, range_max, 0) + xf(width, name, current->name, range_min, range_max, 0, ) #define flag(name) fb(1, name) #define su(width, name) \ - xsu(width, name, current->name, 0) + xsu(width, name, current->name, 0, ) #define fbs(width, name, subs, ...) \ xf(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__) @@ -565,7 +565,7 @@ #define fixed(width, name, value) do { \ av_unused uint32_t fixed_value = value; \ - xf(width, name, fixed_value, value, value, 0); \ + xf(width, name, fixed_value, value, value, 0, ); \ } while (0) @@ -620,9 +620,9 @@ #define delta_q(name) do { \ uint8_t delta_coded; \ int8_t delta_q; \ - xf(1, name.delta_coded, delta_coded, 0, 1, 0); \ + xf(1, name.delta_coded, delta_coded, 0, 1, 0, ); \ if (delta_coded) \ - xsu(1 + 6, name.delta_q, delta_q, 0); \ + xsu(1 + 6, name.delta_q, delta_q, 0, ); \ else \ delta_q = 0; \ current->name = delta_q; \ @@ -697,9 +697,9 @@ } while (0) #define delta_q(name) do { \ - xf(1, name.delta_coded, current->name != 0, 0, 1, 0); \ + xf(1, name.delta_coded, current->name != 0, 0, 1, 0, ); \ if (current->name) \ - xsu(1 + 6, name.delta_q, current->name, 0); \ + xsu(1 + 6, name.delta_q, current->name, 0, ); \ } while (0) #define leb128(name) do { \ @@ -708,10 +708,11 @@ #define infer(name, value) do { \ if (current->name != (value)) { \ - av_log(ctx->log_ctx, AV_LOG_WARNING, "Warning: " \ + av_log(ctx->log_ctx, AV_LOG_ERROR, \ "%s does not match inferred value: " \ "%"PRId64", but should be %"PRId64".\n", \ #name, (int64_t)current->name, (int64_t)(value)); \ + return AVERROR_INVALIDDATA; \ } \ } while (0) @@ -758,6 +759,39 @@ goto fail; } + if (header && size && data[0] & 0x80) { + // first bit is nonzero, the extradata does not consist purely of + // OBUs. Expect MP4/Matroska AV1CodecConfigurationRecord + int config_record_version = data[0] & 0x7f; + + if (config_record_version != 1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Unknown version %d of AV1CodecConfigurationRecord " + "found!\n", + config_record_version); + err = AVERROR_INVALIDDATA; + goto fail; + } + + if (size <= 4) { + if (size < 4) { + av_log(ctx->log_ctx, AV_LOG_WARNING, + "Undersized AV1CodecConfigurationRecord v%d found!\n", + config_record_version); + err = AVERROR_INVALIDDATA; + goto fail; + } + + goto success; + } + + // In AV1CodecConfigurationRecord v1, actual OBUs start after + // four bytes. Thus set the offset as required for properly + // parsing them. + data += 4; + size -= 4; + } + while (size > 0) { AV1RawOBUHeader header; uint64_t obu_size; @@ -768,14 +802,13 @@ if (err < 0) goto fail; - if (get_bits_left(&gbc) < 8) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid OBU: fragment " - "too short (%"SIZE_SPECIFIER" bytes).\n", size); - err = AVERROR_INVALIDDATA; - goto fail; - } - if (header.obu_has_size_field) { + if (get_bits_left(&gbc) < 8) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid OBU: fragment " + "too short (%"SIZE_SPECIFIER" bytes).\n", size); + err = AVERROR_INVALIDDATA; + goto fail; + } err = cbs_av1_read_leb128(ctx, &gbc, "obu_size", &obu_size); if (err < 0) goto fail; @@ -795,7 +828,7 @@ goto fail; } - err = ff_cbs_insert_unit_data(ctx, frag, -1, header.obu_type, + err = ff_cbs_insert_unit_data(frag, -1, header.obu_type, data, obu_length, frag->data_ref); if (err < 0) goto fail; @@ -804,56 +837,13 @@ size -= obu_length; } +success: err = 0; fail: ctx->trace_enable = trace; return err; } -static void cbs_av1_free_tile_data(AV1RawTileData *td) -{ - av_buffer_unref(&td->data_ref); -} - -static void cbs_av1_free_padding(AV1RawPadding *pd) -{ - av_buffer_unref(&pd->payload_ref); -} - -static void cbs_av1_free_metadata(AV1RawMetadata *md) -{ - switch (md->metadata_type) { - case AV1_METADATA_TYPE_ITUT_T35: - av_buffer_unref(&md->metadata.itut_t35.payload_ref); - break; - } -} - -static void cbs_av1_free_obu(void *unit, uint8_t *content) -{ - AV1RawOBU *obu = (AV1RawOBU*)content; - - switch (obu->header.obu_type) { - case AV1_OBU_TILE_GROUP: - cbs_av1_free_tile_data(&obu->obu.tile_group.tile_data); - break; - case AV1_OBU_FRAME: - cbs_av1_free_tile_data(&obu->obu.frame.tile_group.tile_data); - break; - case AV1_OBU_TILE_LIST: - cbs_av1_free_tile_data(&obu->obu.tile_list.tile_data); - break; - case AV1_OBU_METADATA: - cbs_av1_free_metadata(&obu->obu.metadata); - break; - case AV1_OBU_PADDING: - cbs_av1_free_padding(&obu->obu.padding); - break; - } - - av_freep(&obu); -} - static int cbs_av1_ref_tile_data(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit, GetBitContext *gbc, @@ -888,8 +878,7 @@ GetBitContext gbc; int err, start_pos, end_pos; - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*obu), - &cbs_av1_free_obu); + err = ff_cbs_alloc_unit_content2(ctx, unit); if (err < 0) return err; obu = unit->content; @@ -921,9 +910,6 @@ start_pos = get_bits_count(&gbc); if (obu->header.obu_extension_flag) { - priv->temporal_id = obu->header.temporal_id; - priv->spatial_id = obu->header.spatial_id; - if (obu->header.obu_type != AV1_OBU_SEQUENCE_HEADER && obu->header.obu_type != AV1_OBU_TEMPORAL_DELIMITER && priv->operating_point_idc) { @@ -932,16 +918,11 @@ int in_spatial_layer = (priv->operating_point_idc >> (priv->spatial_id + 8)) & 1; if (!in_temporal_layer || !in_spatial_layer) { - // Decoding will drop this OBU at this operating point. + return AVERROR(EAGAIN); // drop_obu() } } - } else { - priv->temporal_id = 0; - priv->spatial_id = 0; } - priv->ref = (AV1ReferenceFrameState *)&priv->read_ref; - switch (obu->header.obu_type) { case AV1_OBU_SEQUENCE_HEADER: { @@ -950,6 +931,18 @@ if (err < 0) return err; + if (priv->operating_point >= 0) { + AV1RawSequenceHeader *sequence_header = &obu->obu.sequence_header; + + if (priv->operating_point > sequence_header->operating_points_cnt_minus_1) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid Operating Point %d requested. " + "Must not be higher than %u.\n", + priv->operating_point, sequence_header->operating_points_cnt_minus_1); + return AVERROR(EINVAL); + } + priv->operating_point_idc = sequence_header->operating_point_idc[priv->operating_point]; + } + av_buffer_unref(&priv->sequence_header_ref); priv->sequence_header = NULL; @@ -1085,8 +1078,6 @@ td = NULL; start_pos = put_bits_count(pbc); - priv->ref = (AV1ReferenceFrameState *)&priv->write_ref; - switch (obu->header.obu_type) { case AV1_OBU_SEQUENCE_HEADER: { @@ -1098,6 +1089,10 @@ av_buffer_unref(&priv->sequence_header_ref); priv->sequence_header = NULL; + err = ff_cbs_make_unit_refcounted(ctx, unit); + if (err < 0) + return err; + priv->sequence_header_ref = av_buffer_ref(unit->content_ref); if (!priv->sequence_header_ref) return AVERROR(ENOMEM); @@ -1250,6 +1245,20 @@ return 0; } +static void cbs_av1_flush(CodedBitstreamContext *ctx) +{ + CodedBitstreamAV1Context *priv = ctx->priv_data; + + av_buffer_unref(&priv->frame_header_ref); + priv->sequence_header = NULL; + priv->frame_header = NULL; + + memset(priv->ref, 0, sizeof(priv->ref)); + priv->operating_point_idc = 0; + priv->seen_frame_header = 0; + priv->tile_num = 0; +} + static void cbs_av1_close(CodedBitstreamContext *ctx) { CodedBitstreamAV1Context *priv = ctx->priv_data; @@ -1258,15 +1267,70 @@ av_buffer_unref(&priv->frame_header_ref); } +static void cbs_av1_free_metadata(void *unit, uint8_t *content) +{ + AV1RawOBU *obu = (AV1RawOBU*)content; + AV1RawMetadata *md; + + av_assert0(obu->header.obu_type == AV1_OBU_METADATA); + md = &obu->obu.metadata; + + switch (md->metadata_type) { + case AV1_METADATA_TYPE_ITUT_T35: + av_buffer_unref(&md->metadata.itut_t35.payload_ref); + break; + } + av_free(content); +} + +static const CodedBitstreamUnitTypeDescriptor cbs_av1_unit_types[] = { + CBS_UNIT_TYPE_POD(AV1_OBU_SEQUENCE_HEADER, AV1RawOBU), + CBS_UNIT_TYPE_POD(AV1_OBU_TEMPORAL_DELIMITER, AV1RawOBU), + CBS_UNIT_TYPE_POD(AV1_OBU_FRAME_HEADER, AV1RawOBU), + CBS_UNIT_TYPE_POD(AV1_OBU_REDUNDANT_FRAME_HEADER, AV1RawOBU), + + CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_TILE_GROUP, AV1RawOBU, + obu.tile_group.tile_data.data), + CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_FRAME, AV1RawOBU, + obu.frame.tile_group.tile_data.data), + CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_TILE_LIST, AV1RawOBU, + obu.tile_list.tile_data.data), + CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_PADDING, AV1RawOBU, + obu.padding.payload), + + CBS_UNIT_TYPE_COMPLEX(AV1_OBU_METADATA, AV1RawOBU, + &cbs_av1_free_metadata), + + CBS_UNIT_TYPE_END_OF_LIST +}; + +#define OFFSET(x) offsetof(CodedBitstreamAV1Context, x) +static const AVOption cbs_av1_options[] = { + { "operating_point", "Set operating point to select layers to parse from a scalable bitstream", + OFFSET(operating_point), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AV1_MAX_OPERATING_POINTS - 1, 0 }, + { NULL } +}; + +static const AVClass cbs_av1_class = { + .class_name = "cbs_av1", + .item_name = av_default_item_name, + .option = cbs_av1_options, + .version = LIBAVUTIL_VERSION_INT, +}; + const CodedBitstreamType ff_cbs_type_av1 = { .codec_id = AV_CODEC_ID_AV1, + .priv_class = &cbs_av1_class, .priv_data_size = sizeof(CodedBitstreamAV1Context), + .unit_types = cbs_av1_unit_types, + .split_fragment = &cbs_av1_split_fragment, .read_unit = &cbs_av1_read_unit, .write_unit = &cbs_av1_write_obu, .assemble_fragment = &cbs_av1_assemble_fragment, + .flush = &cbs_av1_flush, .close = &cbs_av1_close, }; diff -Nru ffmpeg-4.2.2/libavcodec/cbs_av1.h ffmpeg-4.4/libavcodec/cbs_av1.h --- ffmpeg-4.2.2/libavcodec/cbs_av1.h 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_av1.h 2021-04-08 21:28:39.000000000 +0000 @@ -105,7 +105,7 @@ uint8_t use_128x128_superblock; uint8_t enable_filter_intra; uint8_t enable_intra_edge_filter; - uint8_t enable_intraintra_compound; + uint8_t enable_interintra_compound; uint8_t enable_masked_compound; uint8_t enable_warped_motion; uint8_t enable_dual_filter; @@ -130,6 +130,38 @@ uint8_t film_grain_params_present; } AV1RawSequenceHeader; +typedef struct AV1RawFilmGrainParams { + uint8_t apply_grain; + uint16_t grain_seed; + uint8_t update_grain; + uint8_t film_grain_params_ref_idx; + uint8_t num_y_points; + uint8_t point_y_value[14]; + uint8_t point_y_scaling[14]; + uint8_t chroma_scaling_from_luma; + uint8_t num_cb_points; + uint8_t point_cb_value[10]; + uint8_t point_cb_scaling[10]; + uint8_t num_cr_points; + uint8_t point_cr_value[10]; + uint8_t point_cr_scaling[10]; + uint8_t grain_scaling_minus_8; + uint8_t ar_coeff_lag; + uint8_t ar_coeffs_y_plus_128[24]; + uint8_t ar_coeffs_cb_plus_128[25]; + uint8_t ar_coeffs_cr_plus_128[25]; + uint8_t ar_coeff_shift_minus_6; + uint8_t grain_scale_shift; + uint8_t cb_mult; + uint8_t cb_luma_mult; + uint16_t cb_offset; + uint8_t cr_mult; + uint8_t cr_luma_mult; + uint16_t cr_offset; + uint8_t overlap_flag; + uint8_t clip_to_restricted_range; +} AV1RawFilmGrainParams; + typedef struct AV1RawFrameHeader { uint8_t show_existing_frame; uint8_t frame_to_show_map_idx; @@ -158,8 +190,8 @@ uint8_t use_superres; uint8_t coded_denom; uint8_t render_and_frame_size_different; - uint8_t render_width_minus_1; - uint8_t render_height_minus_1; + uint16_t render_width_minus_1; + uint16_t render_height_minus_1; uint8_t found_ref[AV1_REFS_PER_FRAME]; @@ -251,41 +283,13 @@ //AV1RawSubexp gm_params[AV1_TOTAL_REFS_PER_FRAME][6]; uint32_t gm_params[AV1_TOTAL_REFS_PER_FRAME][6]; - uint8_t apply_grain; - uint16_t grain_seed; - uint8_t update_grain; - uint8_t film_grain_params_ref_idx; - uint8_t num_y_points; - uint8_t point_y_value[14]; - uint8_t point_y_scaling[14]; - uint8_t chroma_scaling_from_luma; - uint8_t num_cb_points; - uint8_t point_cb_value[16]; - uint8_t point_cb_scaling[16]; - uint8_t num_cr_points; - uint8_t point_cr_value[16]; - uint8_t point_cr_scaling[16]; - uint8_t grain_scaling_minus_8; - uint8_t ar_coeff_lag; - uint8_t ar_coeffs_y_plus_128[24]; - uint8_t ar_coeffs_cb_plus_128[25]; - uint8_t ar_coeffs_cr_plus_128[25]; - uint8_t ar_coeff_shift_minus_6; - uint8_t grain_scale_shift; - uint8_t cb_mult; - uint8_t cb_luma_mult; - uint16_t cb_offset; - uint8_t cr_mult; - uint8_t cr_luma_mult; - uint16_t cr_offset; - uint8_t overlap_flag; - uint8_t clip_to_restricted_range; + AV1RawFilmGrainParams film_grain; } AV1RawFrameHeader; typedef struct AV1RawTileData { uint8_t *data; - size_t data_size; AVBufferRef *data_ref; + size_t data_size; } AV1RawTileData; typedef struct AV1RawTileGroup { @@ -346,8 +350,8 @@ uint8_t itu_t_t35_country_code_extension_byte; uint8_t *payload; - size_t payload_size; AVBufferRef *payload_ref; + size_t payload_size; } AV1RawMetadataITUTT35; typedef struct AV1RawMetadataTimecode { @@ -379,8 +383,8 @@ typedef struct AV1RawPadding { uint8_t *payload; - size_t payload_size; AVBufferRef *payload_ref; + size_t payload_size; } AV1RawPadding; @@ -413,9 +417,16 @@ int subsampling_y; // RefSubsamplingY int bit_depth; // RefBitDepth int order_hint; // RefOrderHint + + int8_t loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME]; + int8_t loop_filter_mode_deltas[2]; + uint8_t feature_enabled[AV1_MAX_SEGMENTS][AV1_SEG_LVL_MAX]; + int16_t feature_value[AV1_MAX_SEGMENTS][AV1_SEG_LVL_MAX]; } AV1ReferenceFrameState; typedef struct CodedBitstreamAV1Context { + const AVClass *class; + AV1RawSequenceHeader *sequence_header; AVBufferRef *sequence_header_ref; @@ -429,6 +440,7 @@ int operating_point_idc; int bit_depth; + int order_hint; int frame_width; int frame_height; int upscaled_width; @@ -440,10 +452,12 @@ int all_lossless; int tile_cols; int tile_rows; + int tile_num; + + AV1ReferenceFrameState ref[AV1_NUM_REF_FRAMES]; - AV1ReferenceFrameState *ref; - AV1ReferenceFrameState read_ref[AV1_NUM_REF_FRAMES]; - AV1ReferenceFrameState write_ref[AV1_NUM_REF_FRAMES]; + // AVOptions + int operating_point; } CodedBitstreamAV1Context; diff -Nru ffmpeg-4.2.2/libavcodec/cbs_av1_syntax_template.c ffmpeg-4.4/libavcodec/cbs_av1_syntax_template.c --- ffmpeg-4.2.2/libavcodec/cbs_av1_syntax_template.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_av1_syntax_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,8 +19,8 @@ static int FUNC(obu_header)(CodedBitstreamContext *ctx, RWContext *rw, AV1RawOBUHeader *current) { + CodedBitstreamAV1Context *priv = ctx->priv_data; int err; - av_unused int zero = 0; HEADER("OBU header"); @@ -36,8 +36,14 @@ fb(3, temporal_id); fb(2, spatial_id); fc(3, extension_header_reserved_3bits, 0, 0); + } else { + infer(temporal_id, 0); + infer(spatial_id, 0); } + priv->temporal_id = current->temporal_id; + priv->spatial_id = current->spatial_id; + return 0; } @@ -268,7 +274,7 @@ flag(enable_intra_edge_filter); if (current->reduced_still_picture_header) { - infer(enable_intraintra_compound, 0); + infer(enable_interintra_compound, 0); infer(enable_masked_compound, 0); infer(enable_warped_motion, 0); infer(enable_dual_filter, 0); @@ -281,7 +287,7 @@ infer(seq_force_integer_mv, AV1_SELECT_INTEGER_MV); } else { - flag(enable_intraintra_compound); + flag(enable_interintra_compound); flag(enable_masked_compound); flag(enable_warped_motion); flag(enable_dual_filter); @@ -339,6 +345,117 @@ return 0; } +static int FUNC(set_frame_refs)(CodedBitstreamContext *ctx, RWContext *rw, + AV1RawFrameHeader *current) +{ + CodedBitstreamAV1Context *priv = ctx->priv_data; + const AV1RawSequenceHeader *seq = priv->sequence_header; + static const uint8_t ref_frame_list[AV1_NUM_REF_FRAMES - 2] = { + AV1_REF_FRAME_LAST2, AV1_REF_FRAME_LAST3, AV1_REF_FRAME_BWDREF, + AV1_REF_FRAME_ALTREF2, AV1_REF_FRAME_ALTREF + }; + int8_t ref_frame_idx[AV1_REFS_PER_FRAME], used_frame[AV1_NUM_REF_FRAMES]; + int8_t shifted_order_hints[AV1_NUM_REF_FRAMES]; + int cur_frame_hint, latest_order_hint, earliest_order_hint, ref; + int i, j; + + for (i = 0; i < AV1_REFS_PER_FRAME; i++) + ref_frame_idx[i] = -1; + ref_frame_idx[AV1_REF_FRAME_LAST - AV1_REF_FRAME_LAST] = current->last_frame_idx; + ref_frame_idx[AV1_REF_FRAME_GOLDEN - AV1_REF_FRAME_LAST] = current->golden_frame_idx; + + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) + used_frame[i] = 0; + used_frame[current->last_frame_idx] = 1; + used_frame[current->golden_frame_idx] = 1; + + cur_frame_hint = 1 << (seq->order_hint_bits_minus_1); + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) + shifted_order_hints[i] = cur_frame_hint + + cbs_av1_get_relative_dist(seq, priv->ref[i].order_hint, + priv->order_hint); + + latest_order_hint = shifted_order_hints[current->last_frame_idx]; + earliest_order_hint = shifted_order_hints[current->golden_frame_idx]; + + ref = -1; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + int hint = shifted_order_hints[i]; + if (!used_frame[i] && hint >= cur_frame_hint && + (ref < 0 || hint >= latest_order_hint)) { + ref = i; + latest_order_hint = hint; + } + } + if (ref >= 0) { + ref_frame_idx[AV1_REF_FRAME_ALTREF - AV1_REF_FRAME_LAST] = ref; + used_frame[ref] = 1; + } + + ref = -1; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + int hint = shifted_order_hints[i]; + if (!used_frame[i] && hint >= cur_frame_hint && + (ref < 0 || hint < earliest_order_hint)) { + ref = i; + earliest_order_hint = hint; + } + } + if (ref >= 0) { + ref_frame_idx[AV1_REF_FRAME_BWDREF - AV1_REF_FRAME_LAST] = ref; + used_frame[ref] = 1; + } + + ref = -1; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + int hint = shifted_order_hints[i]; + if (!used_frame[i] && hint >= cur_frame_hint && + (ref < 0 || hint < earliest_order_hint)) { + ref = i; + earliest_order_hint = hint; + } + } + if (ref >= 0) { + ref_frame_idx[AV1_REF_FRAME_ALTREF2 - AV1_REF_FRAME_LAST] = ref; + used_frame[ref] = 1; + } + + for (i = 0; i < AV1_REFS_PER_FRAME - 2; i++) { + int ref_frame = ref_frame_list[i]; + if (ref_frame_idx[ref_frame - AV1_REF_FRAME_LAST] < 0 ) { + ref = -1; + for (j = 0; j < AV1_NUM_REF_FRAMES; j++) { + int hint = shifted_order_hints[j]; + if (!used_frame[j] && hint < cur_frame_hint && + (ref < 0 || hint >= latest_order_hint)) { + ref = j; + latest_order_hint = hint; + } + } + if (ref >= 0) { + ref_frame_idx[ref_frame - AV1_REF_FRAME_LAST] = ref; + used_frame[ref] = 1; + } + } + } + + ref = -1; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + int hint = shifted_order_hints[i]; + if (ref < 0 || hint < earliest_order_hint) { + ref = i; + earliest_order_hint = hint; + } + } + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + if (ref_frame_idx[i] < 0) + ref_frame_idx[i] = ref; + infer(ref_frame_idx[i], ref_frame_idx[i]); + } + + return 0; +} + static int FUNC(superres_params)(CodedBitstreamContext *ctx, RWContext *rw, AV1RawFrameHeader *current) { @@ -375,14 +492,14 @@ if (current->frame_size_override_flag) { fb(seq->frame_width_bits_minus_1 + 1, frame_width_minus_1); fb(seq->frame_height_bits_minus_1 + 1, frame_height_minus_1); - - priv->frame_width = current->frame_width_minus_1 + 1; - priv->frame_height = current->frame_height_minus_1 + 1; } else { - priv->frame_width = seq->max_frame_width_minus_1 + 1; - priv->frame_height = seq->max_frame_height_minus_1 + 1; + infer(frame_width_minus_1, seq->max_frame_width_minus_1); + infer(frame_height_minus_1, seq->max_frame_height_minus_1); } + priv->frame_width = current->frame_width_minus_1 + 1; + priv->frame_height = current->frame_height_minus_1 + 1; + CHECK(FUNC(superres_params)(ctx, rw, current)); return 0; @@ -399,14 +516,14 @@ if (current->render_and_frame_size_different) { fb(16, render_width_minus_1); fb(16, render_height_minus_1); - - priv->render_width = current->render_width_minus_1 + 1; - priv->render_height = current->render_height_minus_1 + 1; } else { - priv->render_width = priv->upscaled_width; - priv->render_height = priv->frame_height; + infer(render_width_minus_1, current->frame_width_minus_1); + infer(render_height_minus_1, current->frame_height_minus_1); } + priv->render_width = current->render_width_minus_1 + 1; + priv->render_height = current->render_height_minus_1 + 1; + return 0; } @@ -419,20 +536,24 @@ for (i = 0; i < AV1_REFS_PER_FRAME; i++) { flags(found_ref[i], 1, i); if (current->found_ref[i]) { - AV1ReferenceFrameState *ref; + AV1ReferenceFrameState *ref = + &priv->ref[current->ref_frame_idx[i]]; - if (current->ref_frame_idx[i] < 0 || - !priv->ref[current->ref_frame_idx[i]].valid) { + if (!ref->valid) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Missing reference frame needed for frame size " "(ref = %d, ref_frame_idx = %d).\n", i, current->ref_frame_idx[i]); return AVERROR_INVALIDDATA; } - ref = &priv->ref[current->ref_frame_idx[i]]; + + infer(frame_width_minus_1, ref->upscaled_width - 1); + infer(frame_height_minus_1, ref->frame_height - 1); + infer(render_width_minus_1, ref->render_width - 1); + infer(render_height_minus_1, ref->render_height - 1); priv->upscaled_width = ref->upscaled_width; - priv->frame_width = ref->frame_width; + priv->frame_width = priv->upscaled_width; priv->frame_height = ref->frame_height; priv->render_width = ref->render_width; priv->render_height = ref->render_height; @@ -515,6 +636,15 @@ current->tile_rows_log2; current->tile_rows = (sb_rows + tile_height_sb - 1) / tile_height_sb; + for (i = 0; i < current->tile_cols - 1; i++) + infer(width_in_sbs_minus_1[i], tile_width_sb - 1); + infer(width_in_sbs_minus_1[i], + sb_cols - (current->tile_cols - 1) * tile_width_sb - 1); + for (i = 0; i < current->tile_rows - 1; i++) + infer(height_in_sbs_minus_1[i], tile_height_sb - 1); + infer(height_in_sbs_minus_1[i], + sb_rows - (current->tile_rows - 1) * tile_height_sb - 1); + } else { int widest_tile_sb, start_sb, size_sb, max_width, max_height; @@ -613,8 +743,11 @@ static int FUNC(segmentation_params)(CodedBitstreamContext *ctx, RWContext *rw, AV1RawFrameHeader *current) { + CodedBitstreamAV1Context *priv = ctx->priv_data; static const uint8_t bits[AV1_SEG_LVL_MAX] = { 8, 6, 6, 6, 6, 3, 0, 0 }; static const uint8_t sign[AV1_SEG_LVL_MAX] = { 1, 1, 1, 1, 1, 0, 0, 0 }; + static const uint8_t default_feature_enabled[AV1_SEG_LVL_MAX] = { 0 }; + static const int16_t default_feature_value[AV1_SEG_LVL_MAX] = { 0 }; int i, j, err; flag(segmentation_enabled); @@ -633,9 +766,22 @@ flag(segmentation_update_data); } - if (current->segmentation_update_data) { - for (i = 0; i < AV1_MAX_SEGMENTS; i++) { - for (j = 0; j < AV1_SEG_LVL_MAX; j++) { + for (i = 0; i < AV1_MAX_SEGMENTS; i++) { + const uint8_t *ref_feature_enabled; + const int16_t *ref_feature_value; + + if (current->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + ref_feature_enabled = default_feature_enabled; + ref_feature_value = default_feature_value; + } else { + ref_feature_enabled = + priv->ref[current->ref_frame_idx[current->primary_ref_frame]].feature_enabled[i]; + ref_feature_value = + priv->ref[current->ref_frame_idx[current->primary_ref_frame]].feature_value[i]; + } + + for (j = 0; j < AV1_SEG_LVL_MAX; j++) { + if (current->segmentation_update_data) { flags(feature_enabled[i][j], 2, i, j); if (current->feature_enabled[i][j] && bits[j] > 0) { @@ -646,6 +792,9 @@ } else { infer(feature_value[i][j], 0); } + } else { + infer(feature_enabled[i][j], ref_feature_enabled[j]); + infer(feature_value[i][j], ref_feature_value[j]); } } } @@ -707,6 +856,9 @@ AV1RawFrameHeader *current) { CodedBitstreamAV1Context *priv = ctx->priv_data; + static const int8_t default_loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME] = + { 1, 0, 0, 0, -1, 0, -1, -1 }; + static const int8_t default_loop_filter_mode_deltas[2] = { 0, 0 }; int i, err; if (priv->coded_lossless || current->allow_intrabc) { @@ -740,19 +892,44 @@ flag(loop_filter_delta_enabled); if (current->loop_filter_delta_enabled) { + const int8_t *ref_loop_filter_ref_deltas, *ref_loop_filter_mode_deltas; + + if (current->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + ref_loop_filter_ref_deltas = default_loop_filter_ref_deltas; + ref_loop_filter_mode_deltas = default_loop_filter_mode_deltas; + } else { + ref_loop_filter_ref_deltas = + priv->ref[current->ref_frame_idx[current->primary_ref_frame]].loop_filter_ref_deltas; + ref_loop_filter_mode_deltas = + priv->ref[current->ref_frame_idx[current->primary_ref_frame]].loop_filter_mode_deltas; + } + flag(loop_filter_delta_update); - if (current->loop_filter_delta_update) { - for (i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) { + for (i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) { + if (current->loop_filter_delta_update) flags(update_ref_delta[i], 1, i); - if (current->update_ref_delta[i]) - sus(1 + 6, loop_filter_ref_deltas[i], 1, i); - } - for (i = 0; i < 2; i++) { + else + infer(update_ref_delta[i], 0); + if (current->update_ref_delta[i]) + sus(1 + 6, loop_filter_ref_deltas[i], 1, i); + else + infer(loop_filter_ref_deltas[i], ref_loop_filter_ref_deltas[i]); + } + for (i = 0; i < 2; i++) { + if (current->loop_filter_delta_update) flags(update_mode_delta[i], 1, i); - if (current->update_mode_delta[i]) - sus(1 + 6, loop_filter_mode_deltas[i], 1, i); - } + else + infer(update_mode_delta[i], 0); + if (current->update_mode_delta[i]) + sus(1 + 6, loop_filter_mode_deltas[i], 1, i); + else + infer(loop_filter_mode_deltas[i], ref_loop_filter_mode_deltas[i]); } + } else { + for (i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) + infer(loop_filter_ref_deltas[i], default_loop_filter_ref_deltas[i]); + for (i = 0; i < 2; i++) + infer(loop_filter_mode_deltas[i], default_loop_filter_mode_deltas[i]); } return 0; @@ -810,7 +987,7 @@ for (i = 0; i < priv->num_planes; i++) { fbs(2, lr_type[i], 1, i); - if (current->lr_type[i] != 0) { + if (current->lr_type[i] != AV1_RESTORE_NONE) { uses_lr = 1; if (i > 0) uses_chroma_lr = 1; @@ -884,7 +1061,7 @@ for (i = 0; i < AV1_REFS_PER_FRAME; i++) { ref_hint = priv->ref[current->ref_frame_idx[i]].order_hint; dist = cbs_av1_get_relative_dist(seq, ref_hint, - current->order_hint); + priv->order_hint); if (dist < 0) { if (forward_idx < 0 || cbs_av1_get_relative_dist(seq, ref_hint, @@ -1017,7 +1194,8 @@ } static int FUNC(film_grain_params)(CodedBitstreamContext *ctx, RWContext *rw, - AV1RawFrameHeader *current) + AV1RawFilmGrainParams *current, + AV1RawFrameHeader *frame_header) { CodedBitstreamAV1Context *priv = ctx->priv_data; const AV1RawSequenceHeader *seq = priv->sequence_header; @@ -1025,7 +1203,7 @@ int i, err; if (!seq->film_grain_params_present || - (!current->show_frame && !current->showable_frame)) + (!frame_header->show_frame && !frame_header->showable_frame)) return 0; flag(apply_grain); @@ -1035,7 +1213,7 @@ fb(16, grain_seed); - if (current->frame_type == AV1_FRAME_INTER) + if (frame_header->frame_type == AV1_FRAME_INTER) flag(update_grain); else infer(update_grain, 1); @@ -1047,7 +1225,10 @@ fc(4, num_y_points, 0, 14); for (i = 0; i < current->num_y_points; i++) { - fbs(8, point_y_value[i], 1, i); + fcs(8, point_y_value[i], + i ? current->point_y_value[i - 1] + 1 : 0, + MAX_UINT_BITS(8) - (current->num_y_points - i - 1), + 1, i); fbs(8, point_y_scaling[i], 1, i); } @@ -1064,14 +1245,20 @@ infer(num_cb_points, 0); infer(num_cr_points, 0); } else { - fb(4, num_cb_points); + fc(4, num_cb_points, 0, 10); for (i = 0; i < current->num_cb_points; i++) { - fbs(8, point_cb_value[i], 1, i); + fcs(8, point_cb_value[i], + i ? current->point_cb_value[i - 1] + 1 : 0, + MAX_UINT_BITS(8) - (current->num_cb_points - i - 1), + 1, i); fbs(8, point_cb_scaling[i], 1, i); } - fb(4, num_cr_points); + fc(4, num_cr_points, 0, 10); for (i = 0; i < current->num_cr_points; i++) { - fbs(8, point_cr_value[i], 1, i); + fcs(8, point_cr_value[i], + i ? current->point_cr_value[i - 1] + 1 : 0, + MAX_UINT_BITS(8) - (current->num_cr_points - i - 1), + 1, i); fbs(8, point_cr_scaling[i], 1, i); } } @@ -1143,10 +1330,17 @@ flag(show_existing_frame); if (current->show_existing_frame) { - AV1ReferenceFrameState *frame; + AV1ReferenceFrameState *ref; fb(3, frame_to_show_map_idx); - frame = &priv->ref[current->frame_to_show_map_idx]; + ref = &priv->ref[current->frame_to_show_map_idx]; + + if (!ref->valid) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Missing reference frame needed for " + "show_existing_frame (frame_to_show_map_idx = %d).\n", + current->frame_to_show_map_idx); + return AVERROR_INVALIDDATA; + } if (seq->decoder_model_info_present_flag && !seq->timing_info.equal_picture_interval) { @@ -1157,12 +1351,29 @@ if (seq->frame_id_numbers_present_flag) fb(id_len, display_frame_id); - if (frame->frame_type == AV1_FRAME_KEY) + infer(frame_type, ref->frame_type); + if (current->frame_type == AV1_FRAME_KEY) { infer(refresh_frame_flags, all_frames); - else + + // Section 7.21 + infer(current_frame_id, ref->frame_id); + priv->upscaled_width = ref->upscaled_width; + priv->frame_width = ref->frame_width; + priv->frame_height = ref->frame_height; + priv->render_width = ref->render_width; + priv->render_height = ref->render_height; + priv->bit_depth = ref->bit_depth; + priv->order_hint = ref->order_hint; + } else infer(refresh_frame_flags, 0); - return 0; + infer(frame_width_minus_1, ref->upscaled_width - 1); + infer(frame_height_minus_1, ref->frame_height - 1); + infer(render_width_minus_1, ref->render_width - 1); + infer(render_height_minus_1, ref->render_height - 1); + + // Section 7.20 + goto update_refs; } fb(2, frame_type); @@ -1248,6 +1459,7 @@ fb(order_hint_bits, order_hint); else infer(order_hint, 0); + priv->order_hint = current->order_hint; if (frame_is_intra || current->error_resilient_mode) infer(primary_ref_frame, AV1_PRIMARY_REF_NONE); @@ -1263,7 +1475,7 @@ int in_temporal_layer = (op_pt_idc >> priv->temporal_id ) & 1; int in_spatial_layer = (op_pt_idc >> (priv->spatial_id + 8)) & 1; if (seq->operating_point_idc[i] == 0 || - in_temporal_layer || in_spatial_layer) { + (in_temporal_layer && in_spatial_layer)) { fbs(seq->decoder_model_info.buffer_removal_time_length_minus_1 + 1, buffer_removal_time[i], 1, i); } @@ -1279,9 +1491,12 @@ fb(8, refresh_frame_flags); if (!frame_is_intra || current->refresh_frame_flags != all_frames) { - if (current->error_resilient_mode && seq->enable_order_hint) { + if (seq->enable_order_hint) { for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { - fbs(order_hint_bits, ref_order_hint[i], 1, i); + if (current->error_resilient_mode) + fbs(order_hint_bits, ref_order_hint[i], 1, i); + else + infer(ref_order_hint[i], priv->ref[i].order_hint); if (current->ref_order_hint[i] != priv->ref[i].order_hint) priv->ref[i].valid = 0; } @@ -1307,16 +1522,7 @@ if (current->frame_refs_short_signaling) { fb(3, last_frame_idx); fb(3, golden_frame_idx); - - for (i = 0; i < AV1_REFS_PER_FRAME; i++) { - if (i == 0) - infer(ref_frame_idx[i], current->last_frame_idx); - else if (i == AV1_REF_FRAME_GOLDEN - - AV1_REF_FRAME_LAST) - infer(ref_frame_idx[i], current->golden_frame_idx); - else - infer(ref_frame_idx[i], -1); - } + CHECK(FUNC(set_frame_refs)(ctx, rw, current)); } } @@ -1430,8 +1636,18 @@ CHECK(FUNC(global_motion_params)(ctx, rw, current)); - CHECK(FUNC(film_grain_params)(ctx, rw, current)); + CHECK(FUNC(film_grain_params)(ctx, rw, ¤t->film_grain, current)); + + av_log(ctx->log_ctx, AV_LOG_DEBUG, "Frame %d: size %dx%d " + "upscaled %d render %dx%d subsample %dx%d " + "bitdepth %d tiles %dx%d.\n", priv->order_hint, + priv->frame_width, priv->frame_height, priv->upscaled_width, + priv->render_width, priv->render_height, + seq->color_config.subsampling_x + 1, + seq->color_config.subsampling_y + 1, priv->bit_depth, + priv->tile_rows, priv->tile_cols); +update_refs: for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { if (current->refresh_frame_flags & (1 << i)) { priv->ref[i] = (AV1ReferenceFrameState) { @@ -1446,20 +1662,19 @@ .subsampling_x = seq->color_config.subsampling_x, .subsampling_y = seq->color_config.subsampling_y, .bit_depth = priv->bit_depth, - .order_hint = current->order_hint, + .order_hint = priv->order_hint, }; + memcpy(priv->ref[i].loop_filter_ref_deltas, current->loop_filter_ref_deltas, + sizeof(current->loop_filter_ref_deltas)); + memcpy(priv->ref[i].loop_filter_mode_deltas, current->loop_filter_mode_deltas, + sizeof(current->loop_filter_mode_deltas)); + memcpy(priv->ref[i].feature_enabled, current->feature_enabled, + sizeof(current->feature_enabled)); + memcpy(priv->ref[i].feature_value, current->feature_value, + sizeof(current->feature_value)); } } - av_log(ctx->log_ctx, AV_LOG_DEBUG, "Frame %d: size %dx%d " - "upscaled %d render %dx%d subsample %dx%d " - "bitdepth %d tiles %dx%d.\n", current->order_hint, - priv->frame_width, priv->frame_height, priv->upscaled_width, - priv->render_width, priv->render_height, - seq->color_config.subsampling_x + 1, - seq->color_config.subsampling_y + 1, priv->bit_depth, - priv->tile_rows, priv->tile_cols); - return 0; } @@ -1500,8 +1715,6 @@ else HEADER("Frame Header"); - priv->seen_frame_header = 1; - #ifdef READ start_pos = get_bits_count(rw); #else @@ -1510,6 +1723,8 @@ CHECK(FUNC(uncompressed_header)(ctx, rw, current)); + priv->tile_num = 0; + if (current->show_existing_frame) { priv->seen_frame_header = 0; } else { @@ -1575,10 +1790,12 @@ } else { tile_bits = cbs_av1_tile_log2(1, priv->tile_cols) + cbs_av1_tile_log2(1, priv->tile_rows); - fb(tile_bits, tg_start); - fb(tile_bits, tg_end); + fc(tile_bits, tg_start, priv->tile_num, num_tiles - 1); + fc(tile_bits, tg_end, current->tg_start, num_tiles - 1); } + priv->tile_num = current->tg_end + 1; + CHECK(FUNC(byte_alignment)(ctx, rw)); // Reset header for next frame. diff -Nru ffmpeg-4.2.2/libavcodec/cbs_bsf.c ffmpeg-4.4/libavcodec/cbs_bsf.c --- ffmpeg-4.2.2/libavcodec/cbs_bsf.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,159 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "bsf_internal.h" +#include "cbs_bsf.h" + +static int cbs_bsf_update_side_data(AVBSFContext *bsf, AVPacket *pkt) +{ + CBSBSFContext *ctx = bsf->priv_data; + CodedBitstreamFragment *frag = &ctx->fragment; + uint8_t *side_data; + buffer_size_t side_data_size; + int err; + + side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, + &side_data_size); + if (!side_data_size) + return 0; + + err = ff_cbs_read(ctx->input, frag, side_data, side_data_size); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, + "Failed to read extradata from packet side data.\n"); + return err; + } + + err = ctx->type->update_fragment(bsf, NULL, frag); + if (err < 0) + return err; + + err = ff_cbs_write_fragment_data(ctx->output, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, + "Failed to write extradata into packet side data.\n"); + return err; + } + + side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, + frag->data_size); + if (!side_data) + return AVERROR(ENOMEM); + memcpy(side_data, frag->data, frag->data_size); + + ff_cbs_fragment_reset(frag); + return 0; +} + +int ff_cbs_bsf_generic_filter(AVBSFContext *bsf, AVPacket *pkt) +{ + CBSBSFContext *ctx = bsf->priv_data; + CodedBitstreamFragment *frag = &ctx->fragment; + int err; + + err = ff_bsf_get_packet_ref(bsf, pkt); + if (err < 0) + return err; + + err = cbs_bsf_update_side_data(bsf, pkt); + if (err < 0) + goto fail; + + err = ff_cbs_read_packet(ctx->input, frag, pkt); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read %s from packet.\n", + ctx->type->fragment_name); + goto fail; + } + + if (frag->nb_units == 0) { + av_log(bsf, AV_LOG_ERROR, "No %s found in packet.\n", + ctx->type->unit_name); + err = AVERROR_INVALIDDATA; + goto fail; + } + + err = ctx->type->update_fragment(bsf, pkt, frag); + if (err < 0) + goto fail; + + err = ff_cbs_write_packet(ctx->output, pkt, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write %s into packet.\n", + ctx->type->fragment_name); + goto fail; + } + + err = 0; +fail: + ff_cbs_fragment_reset(frag); + + if (err < 0) + av_packet_unref(pkt); + + return err; +} + +int ff_cbs_bsf_generic_init(AVBSFContext *bsf, const CBSBSFType *type) +{ + CBSBSFContext *ctx = bsf->priv_data; + CodedBitstreamFragment *frag = &ctx->fragment; + int err; + + ctx->type = type; + + err = ff_cbs_init(&ctx->input, type->codec_id, bsf); + if (err < 0) + return err; + + err = ff_cbs_init(&ctx->output, type->codec_id, bsf); + if (err < 0) + return err; + + if (bsf->par_in->extradata) { + err = ff_cbs_read_extradata(ctx->input, frag, bsf->par_in); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); + goto fail; + } + + err = type->update_fragment(bsf, NULL, frag); + if (err < 0) + goto fail; + + err = ff_cbs_write_extradata(ctx->output, bsf->par_out, frag); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); + goto fail; + } + } + + err = 0; +fail: + ff_cbs_fragment_reset(frag); + return err; +} + +void ff_cbs_bsf_generic_close(AVBSFContext *bsf) +{ + CBSBSFContext *ctx = bsf->priv_data; + + ff_cbs_fragment_free(&ctx->fragment); + ff_cbs_close(&ctx->input); + ff_cbs_close(&ctx->output); +} diff -Nru ffmpeg-4.2.2/libavcodec/cbs_bsf.h ffmpeg-4.4/libavcodec/cbs_bsf.h --- ffmpeg-4.2.2/libavcodec/cbs_bsf.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_bsf.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,131 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_BSF_H +#define AVCODEC_CBS_BSF_H + +#include "cbs.h" + + +typedef struct CBSBSFType { + enum AVCodecID codec_id; + + // Name of a frame fragment in this codec (e.g. "access unit", + // "temporal unit"). + const char *fragment_name; + + // Name of a unit for this BSF, for use in error messages (e.g. + // "NAL unit", "OBU"). + const char *unit_name; + + // Update the content of a fragment with whatever metadata changes + // are desired. The associated AVPacket is provided so that any side + // data associated with the fragment can be inspected or edited. If + // pkt is NULL, then an extradata header fragment is being updated. + int (*update_fragment)(AVBSFContext *bsf, AVPacket *pkt, + CodedBitstreamFragment *frag); +} CBSBSFType; + +// Common structure for all generic CBS BSF users. An instance of this +// structure must be the first member of the BSF private context (to be +// pointed to by AVBSFContext.priv_data). +typedef struct CBSBSFContext { + const AVClass *class; + const CBSBSFType *type; + + CodedBitstreamContext *input; + CodedBitstreamContext *output; + CodedBitstreamFragment fragment; +} CBSBSFContext; + +/** + * Initialise generic CBS BSF setup. + * + * Creates the input and output CBS instances, and applies the filter to + * the extradata on the input codecpar if any is present. + * + * Since it calls the update_fragment() function immediately to deal with + * extradata, this should be called after any codec-specific setup is done + * (probably at the end of the AVBitStreamFilter.init function). + */ +int ff_cbs_bsf_generic_init(AVBSFContext *bsf, const CBSBSFType *type); + +/** + * Close a generic CBS BSF instance. + * + * If no other deinitialisation is required then this function can be used + * directly as AVBitStreamFilter.close. + */ +void ff_cbs_bsf_generic_close(AVBSFContext *bsf); + +/** + * Filter operation for CBS BSF. + * + * Reads the input packet into a CBS fragment, calls update_fragment() on + * it, then writes the result to an output packet. If the input packet + * has AV_PKT_DATA_NEW_EXTRADATA side-data associated with it then it does + * the same thing to that new extradata to form the output side-data first. + * + * If the BSF does not do anything else then this function can be used + * directly as AVBitStreamFilter.filter. + */ +int ff_cbs_bsf_generic_filter(AVBSFContext *bsf, AVPacket *pkt); + + +// Options for element manipulation. +enum { + // Pass this element through unchanged. + BSF_ELEMENT_PASS, + // Insert this element, replacing any existing instances of it. + // Associated values may be provided explicitly (as addtional options) + // or implicitly (either as side data or deduced from other parts of + // the stream). + BSF_ELEMENT_INSERT, + // Remove this element if it appears in the stream. + BSF_ELEMENT_REMOVE, + // Extract this element to side data, so that further manipulation + // can happen elsewhere. + BSF_ELEMENT_EXTRACT, +}; + +#define BSF_ELEMENT_OPTIONS_PIR(name, help, field, opt_flags) \ + { name, help, OFFSET(field), AV_OPT_TYPE_INT, \ + { .i64 = BSF_ELEMENT_PASS }, \ + BSF_ELEMENT_PASS, BSF_ELEMENT_REMOVE, opt_flags, name }, \ + { "pass", NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = BSF_ELEMENT_PASS }, .flags = opt_flags, .unit = name }, \ + { "insert", NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = BSF_ELEMENT_INSERT }, .flags = opt_flags, .unit = name }, \ + { "remove", NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = BSF_ELEMENT_REMOVE }, .flags = opt_flags, .unit = name } + +#define BSF_ELEMENT_OPTIONS_PIRE(name, help, field, opt_flags) \ + { name, help, OFFSET(field), AV_OPT_TYPE_INT, \ + { .i64 = BSF_ELEMENT_PASS }, \ + BSF_ELEMENT_PASS, BSF_ELEMENT_EXTRACT, opt_flags, name }, \ + { "pass", NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = BSF_ELEMENT_PASS }, .flags = opt_flags, .unit = name }, \ + { "insert", NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = BSF_ELEMENT_INSERT }, .flags = opt_flags, .unit = name }, \ + { "remove", NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = BSF_ELEMENT_REMOVE }, .flags = opt_flags, .unit = name }, \ + { "extract", NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = BSF_ELEMENT_EXTRACT }, .flags = opt_flags, .unit = name } \ + + +#endif /* AVCODEC_CBS_BSF_H */ diff -Nru ffmpeg-4.2.2/libavcodec/cbs.c ffmpeg-4.4/libavcodec/cbs.c --- ffmpeg-4.2.2/libavcodec/cbs.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,12 +23,13 @@ #include "libavutil/avassert.h" #include "libavutil/buffer.h" #include "libavutil/common.h" +#include "libavutil/opt.h" #include "cbs.h" #include "cbs_internal.h" -static const CodedBitstreamType *cbs_type_table[] = { +static const CodedBitstreamType *const cbs_type_table[] = { #if CONFIG_CBS_AV1 &ff_cbs_type_av1, #endif @@ -93,7 +94,7 @@ return AVERROR(ENOMEM); ctx->log_ctx = log_ctx; - ctx->codec = type; + ctx->codec = type; /* Must be before any error */ if (type->priv_data_size) { ctx->priv_data = av_mallocz(ctx->codec->priv_data_size); @@ -101,6 +102,10 @@ av_freep(&ctx); return AVERROR(ENOMEM); } + if (type->priv_class) { + *(const AVClass **)ctx->priv_data = type->priv_class; + av_opt_set_defaults(ctx->priv_data); + } } ctx->decompose_unit_types = NULL; @@ -112,6 +117,12 @@ return 0; } +void ff_cbs_flush(CodedBitstreamContext *ctx) +{ + if (ctx->codec->flush) + ctx->codec->flush(ctx); +} + void ff_cbs_close(CodedBitstreamContext **ctx_ptr) { CodedBitstreamContext *ctx = *ctx_ptr; @@ -119,16 +130,19 @@ if (!ctx) return; - if (ctx->codec && ctx->codec->close) + if (ctx->codec->close) ctx->codec->close(ctx); av_freep(&ctx->write_buffer); + + if (ctx->codec->priv_class && ctx->priv_data) + av_opt_free(ctx->priv_data); + av_freep(&ctx->priv_data); av_freep(ctx_ptr); } -static void cbs_unit_uninit(CodedBitstreamContext *ctx, - CodedBitstreamUnit *unit) +static void cbs_unit_uninit(CodedBitstreamUnit *unit) { av_buffer_unref(&unit->content_ref); unit->content = NULL; @@ -139,13 +153,12 @@ unit->data_bit_padding = 0; } -void ff_cbs_fragment_reset(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag) +void ff_cbs_fragment_reset(CodedBitstreamFragment *frag) { int i; for (i = 0; i < frag->nb_units; i++) - cbs_unit_uninit(ctx, &frag->units[i]); + cbs_unit_uninit(&frag->units[i]); frag->nb_units = 0; av_buffer_unref(&frag->data_ref); @@ -154,10 +167,9 @@ frag->data_bit_padding = 0; } -void ff_cbs_fragment_free(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag) +void ff_cbs_fragment_free(CodedBitstreamFragment *frag) { - ff_cbs_fragment_reset(ctx, frag); + ff_cbs_fragment_reset(frag); av_freep(&frag->units); frag->nb_units_allocated = 0; @@ -190,6 +202,12 @@ av_log(ctx->log_ctx, AV_LOG_VERBOSE, "Decomposition unimplemented for unit %d " "(type %"PRIu32").\n", i, unit->type); + } else if (err == AVERROR(EAGAIN)) { + av_log(ctx->log_ctx, AV_LOG_VERBOSE, + "Skipping decomposition of unit %d " + "(type %"PRIu32").\n", i, unit->type); + av_buffer_unref(&unit->content_ref); + unit->content = NULL; } else if (err < 0) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d " "(type %"PRIu32").\n", i, unit->type); @@ -200,8 +218,7 @@ return 0; } -static int cbs_fill_fragment_data(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag, +static int cbs_fill_fragment_data(CodedBitstreamFragment *frag, const uint8_t *data, size_t size) { av_assert0(!frag->data && !frag->data_ref); @@ -221,66 +238,67 @@ return 0; } -int ff_cbs_read_extradata(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag, - const AVCodecParameters *par) -{ - int err; - - err = cbs_fill_fragment_data(ctx, frag, par->extradata, - par->extradata_size); - if (err < 0) - return err; - - err = ctx->codec->split_fragment(ctx, frag, 1); - if (err < 0) - return err; - - return cbs_read_fragment_content(ctx, frag); -} - -int ff_cbs_read_packet(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag, - const AVPacket *pkt) +static int cbs_read_data(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + AVBufferRef *buf, + const uint8_t *data, size_t size, + int header) { int err; - if (pkt->buf) { - frag->data_ref = av_buffer_ref(pkt->buf); + if (buf) { + frag->data_ref = av_buffer_ref(buf); if (!frag->data_ref) return AVERROR(ENOMEM); - frag->data = pkt->data; - frag->data_size = pkt->size; + frag->data = (uint8_t *)data; + frag->data_size = size; } else { - err = cbs_fill_fragment_data(ctx, frag, pkt->data, pkt->size); + err = cbs_fill_fragment_data(frag, data, size); if (err < 0) return err; } - err = ctx->codec->split_fragment(ctx, frag, 0); + err = ctx->codec->split_fragment(ctx, frag, header); if (err < 0) return err; return cbs_read_fragment_content(ctx, frag); } -int ff_cbs_read(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag, - const uint8_t *data, size_t size) +int ff_cbs_read_extradata(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const AVCodecParameters *par) { - int err; + return cbs_read_data(ctx, frag, NULL, + par->extradata, + par->extradata_size, 1); +} - err = cbs_fill_fragment_data(ctx, frag, data, size); - if (err < 0) - return err; +int ff_cbs_read_extradata_from_codec(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const AVCodecContext *avctx) +{ + return cbs_read_data(ctx, frag, NULL, + avctx->extradata, + avctx->extradata_size, 1); +} - err = ctx->codec->split_fragment(ctx, frag, 0); - if (err < 0) - return err; +int ff_cbs_read_packet(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const AVPacket *pkt) +{ + return cbs_read_data(ctx, frag, pkt->buf, + pkt->data, pkt->size, 0); +} - return cbs_read_fragment_content(ctx, frag); +int ff_cbs_read(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const uint8_t *data, size_t size) +{ + return cbs_read_data(ctx, frag, NULL, + data, size, 0); } static int cbs_write_unit_data(CodedBitstreamContext *ctx, @@ -328,7 +346,7 @@ flush_put_bits(&pbc); - ret = ff_cbs_alloc_unit_data(ctx, unit, put_bits_count(&pbc) / 8); + ret = ff_cbs_alloc_unit_data(unit, put_bits_count(&pbc) / 8); if (ret < 0) return ret; @@ -641,8 +659,7 @@ } -int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx, - CodedBitstreamUnit *unit, +int ff_cbs_alloc_unit_content(CodedBitstreamUnit *unit, size_t size, void (*free)(void *opaque, uint8_t *data)) { @@ -653,7 +670,7 @@ return AVERROR(ENOMEM); unit->content_ref = av_buffer_create(unit->content, size, - free, ctx, 0); + free, NULL, 0); if (!unit->content_ref) { av_freep(&unit->content); return AVERROR(ENOMEM); @@ -662,8 +679,7 @@ return 0; } -int ff_cbs_alloc_unit_data(CodedBitstreamContext *ctx, - CodedBitstreamUnit *unit, +int ff_cbs_alloc_unit_data(CodedBitstreamUnit *unit, size_t size) { av_assert0(!unit->data && !unit->data_ref); @@ -680,8 +696,7 @@ return 0; } -static int cbs_insert_unit(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag, +static int cbs_insert_unit(CodedBitstreamFragment *frag, int position) { CodedBitstreamUnit *units; @@ -693,11 +708,11 @@ memmove(units + position + 1, units + position, (frag->nb_units - position) * sizeof(*units)); } else { - units = av_malloc_array(frag->nb_units + 1, sizeof(*units)); + units = av_malloc_array(frag->nb_units*2 + 1, sizeof(*units)); if (!units) return AVERROR(ENOMEM); - ++frag->nb_units_allocated; + frag->nb_units_allocated = 2*frag->nb_units_allocated + 1; if (position > 0) memcpy(units, frag->units, position * sizeof(*units)); @@ -719,8 +734,7 @@ return 0; } -int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag, +int ff_cbs_insert_unit_content(CodedBitstreamFragment *frag, int position, CodedBitstreamUnitType type, void *content, @@ -742,7 +756,7 @@ content_ref = NULL; } - err = cbs_insert_unit(ctx, frag, position); + err = cbs_insert_unit(frag, position); if (err < 0) { av_buffer_unref(&content_ref); return err; @@ -756,8 +770,7 @@ return 0; } -int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag, +int ff_cbs_insert_unit_data(CodedBitstreamFragment *frag, int position, CodedBitstreamUnitType type, uint8_t *data, size_t data_size, @@ -775,10 +788,13 @@ data_ref = av_buffer_ref(data_buf); else data_ref = av_buffer_create(data, data_size, NULL, NULL, 0); - if (!data_ref) + if (!data_ref) { + if (!data_buf) + av_free(data); return AVERROR(ENOMEM); + } - err = cbs_insert_unit(ctx, frag, position); + err = cbs_insert_unit(frag, position); if (err < 0) { av_buffer_unref(&data_ref); return err; @@ -793,14 +809,13 @@ return 0; } -void ff_cbs_delete_unit(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag, +void ff_cbs_delete_unit(CodedBitstreamFragment *frag, int position) { av_assert0(0 <= position && position < frag->nb_units && "Unit to be deleted not in fragment."); - cbs_unit_uninit(ctx, &frag->units[position]); + cbs_unit_uninit(&frag->units[position]); --frag->nb_units; @@ -809,3 +824,235 @@ frag->units + position + 1, (frag->nb_units - position) * sizeof(*frag->units)); } + +static void cbs_default_free_unit_content(void *opaque, uint8_t *data) +{ + const CodedBitstreamUnitTypeDescriptor *desc = opaque; + if (desc->content_type == CBS_CONTENT_TYPE_INTERNAL_REFS) { + int i; + for (i = 0; i < desc->nb_ref_offsets; i++) { + void **ptr = (void**)(data + desc->ref_offsets[i]); + av_buffer_unref((AVBufferRef**)(ptr + 1)); + } + } + av_free(data); +} + +static const CodedBitstreamUnitTypeDescriptor + *cbs_find_unit_type_desc(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + const CodedBitstreamUnitTypeDescriptor *desc; + int i, j; + + if (!ctx->codec->unit_types) + return NULL; + + for (i = 0;; i++) { + desc = &ctx->codec->unit_types[i]; + if (desc->nb_unit_types == 0) + break; + if (desc->nb_unit_types == CBS_UNIT_TYPE_RANGE) { + if (unit->type >= desc->unit_type_range_start && + unit->type <= desc->unit_type_range_end) + return desc; + } else { + for (j = 0; j < desc->nb_unit_types; j++) { + if (desc->unit_types[j] == unit->type) + return desc; + } + } + } + return NULL; +} + +int ff_cbs_alloc_unit_content2(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + const CodedBitstreamUnitTypeDescriptor *desc; + + av_assert0(!unit->content && !unit->content_ref); + + desc = cbs_find_unit_type_desc(ctx, unit); + if (!desc) + return AVERROR(ENOSYS); + + unit->content = av_mallocz(desc->content_size); + if (!unit->content) + return AVERROR(ENOMEM); + + unit->content_ref = + av_buffer_create(unit->content, desc->content_size, + desc->content_free ? desc->content_free + : cbs_default_free_unit_content, + (void*)desc, 0); + if (!unit->content_ref) { + av_freep(&unit->content); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int cbs_clone_unit_content(AVBufferRef **clone_ref, + CodedBitstreamUnit *unit, + const CodedBitstreamUnitTypeDescriptor *desc) +{ + uint8_t *src, *copy; + uint8_t **src_ptr, **copy_ptr; + AVBufferRef **src_buf, **copy_buf; + int err, i; + + av_assert0(unit->content); + src = unit->content; + + copy = av_memdup(src, desc->content_size); + if (!copy) + return AVERROR(ENOMEM); + + for (i = 0; i < desc->nb_ref_offsets; i++) { + src_ptr = (uint8_t**)(src + desc->ref_offsets[i]); + src_buf = (AVBufferRef**)(src_ptr + 1); + copy_ptr = (uint8_t**)(copy + desc->ref_offsets[i]); + copy_buf = (AVBufferRef**)(copy_ptr + 1); + + if (!*src_ptr) { + av_assert0(!*src_buf); + continue; + } + if (!*src_buf) { + // We can't handle a non-refcounted pointer here - we don't + // have enough information to handle whatever structure lies + // at the other end of it. + err = AVERROR(EINVAL); + goto fail; + } + + // src_ptr is required to point somewhere inside src_buf. If it + // doesn't, there is a bug somewhere. + av_assert0(*src_ptr >= (*src_buf)->data && + *src_ptr < (*src_buf)->data + (*src_buf)->size); + + *copy_buf = av_buffer_ref(*src_buf); + if (!*copy_buf) { + err = AVERROR(ENOMEM); + goto fail; + } + *copy_ptr = (*copy_buf)->data + (*src_ptr - (*src_buf)->data); + } + + *clone_ref = av_buffer_create(copy, desc->content_size, + desc->content_free ? desc->content_free : + cbs_default_free_unit_content, + (void*)desc, 0); + if (!*clone_ref) { + err = AVERROR(ENOMEM); + goto fail; + } + + return 0; + +fail: + for (--i; i >= 0; i--) + av_buffer_unref((AVBufferRef**)(copy + desc->ref_offsets[i])); + av_freep(©); + *clone_ref = NULL; + return err; +} + +int ff_cbs_make_unit_refcounted(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + const CodedBitstreamUnitTypeDescriptor *desc; + AVBufferRef *ref; + int err; + + av_assert0(unit->content); + if (unit->content_ref) { + // Already refcounted, nothing to do. + return 0; + } + + desc = cbs_find_unit_type_desc(ctx, unit); + if (!desc) + return AVERROR(ENOSYS); + + switch (desc->content_type) { + case CBS_CONTENT_TYPE_POD: + ref = av_buffer_alloc(desc->content_size); + if (!ref) + return AVERROR(ENOMEM); + memcpy(ref->data, unit->content, desc->content_size); + err = 0; + break; + + case CBS_CONTENT_TYPE_INTERNAL_REFS: + err = cbs_clone_unit_content(&ref, unit, desc); + break; + + case CBS_CONTENT_TYPE_COMPLEX: + if (!desc->content_clone) + return AVERROR_PATCHWELCOME; + err = desc->content_clone(&ref, unit); + break; + + default: + av_assert0(0 && "Invalid content type."); + } + + if (err < 0) + return err; + + unit->content_ref = ref; + unit->content = ref->data; + return 0; +} + +int ff_cbs_make_unit_writable(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + const CodedBitstreamUnitTypeDescriptor *desc; + AVBufferRef *ref; + int err; + + // This can only be applied to refcounted units. + err = ff_cbs_make_unit_refcounted(ctx, unit); + if (err < 0) + return err; + av_assert0(unit->content && unit->content_ref); + + if (av_buffer_is_writable(unit->content_ref)) + return 0; + + desc = cbs_find_unit_type_desc(ctx, unit); + if (!desc) + return AVERROR(ENOSYS); + + switch (desc->content_type) { + case CBS_CONTENT_TYPE_POD: + err = av_buffer_make_writable(&unit->content_ref); + break; + + case CBS_CONTENT_TYPE_INTERNAL_REFS: + err = cbs_clone_unit_content(&ref, unit, desc); + break; + + case CBS_CONTENT_TYPE_COMPLEX: + if (!desc->content_clone) + return AVERROR_PATCHWELCOME; + err = desc->content_clone(&ref, unit); + break; + + default: + av_assert0(0 && "Invalid content type."); + } + if (err < 0) + return err; + + if (desc->content_type != CBS_CONTENT_TYPE_POD) { + av_buffer_unref(&unit->content_ref); + unit->content_ref = ref; + } + unit->content = unit->content_ref->data; + return 0; +} diff -Nru ffmpeg-4.2.2/libavcodec/cbs.h ffmpeg-4.4/libavcodec/cbs.h --- ffmpeg-4.2.2/libavcodec/cbs.h 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs.h 2021-04-08 21:28:39.000000000 +0000 @@ -45,8 +45,10 @@ /** * The codec-specific type of a bitstream unit. * + * AV1: obu_type * H.264 / AVC: nal_unit_type * H.265 / HEVC: nal_unit_type + * JPEG: marker value (without 0xff prefix) * MPEG-2: start code value (without prefix) * VP9: unused, set to zero (every unit is a frame) */ @@ -194,7 +196,7 @@ * Types not in this list will be available in bitstream form only. * If NULL, all supported types will be decomposed. */ - CodedBitstreamUnitType *decompose_unit_types; + const CodedBitstreamUnitType *decompose_unit_types; /** * Length of the decompose_unit_types array. */ @@ -235,6 +237,11 @@ enum AVCodecID codec_id, void *log_ctx); /** + * Reset all internal state in a context. + */ +void ff_cbs_flush(CodedBitstreamContext *ctx); + +/** * Close a context and free all internal state. */ void ff_cbs_close(CodedBitstreamContext **ctx); @@ -256,6 +263,17 @@ const AVCodecParameters *par); /** + * Read the extradata bitstream found in a codec context into a + * fragment, then split into units and decompose. + * + * This acts identical to ff_cbs_read_extradata() for the case where + * you already have a codec context. + */ +int ff_cbs_read_extradata_from_codec(CodedBitstreamContext *ctx, + CodedBitstreamFragment *frag, + const AVCodecContext *avctx); + +/** * Read the data bitstream from a packet into a fragment, then * split into units and decompose. * @@ -330,33 +348,38 @@ * Free the units contained in a fragment as well as the fragment's * own data buffer, but not the units array itself. */ -void ff_cbs_fragment_reset(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag); +void ff_cbs_fragment_reset(CodedBitstreamFragment *frag); /** * Free the units array of a fragment in addition to what * ff_cbs_fragment_reset does. */ -void ff_cbs_fragment_free(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag); +void ff_cbs_fragment_free(CodedBitstreamFragment *frag); /** * Allocate a new internal content buffer of the given size in the unit. * * The content will be zeroed. */ -int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx, - CodedBitstreamUnit *unit, +int ff_cbs_alloc_unit_content(CodedBitstreamUnit *unit, size_t size, - void (*free)(void *unit, uint8_t *content)); + void (*free)(void *opaque, uint8_t *content)); + +/** + * Allocate a new internal content buffer matching the type of the unit. + * + * The content will be zeroed. + */ +int ff_cbs_alloc_unit_content2(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit); + /** * Allocate a new internal data buffer of the given size in the unit. * * The data buffer will have input padding. */ -int ff_cbs_alloc_unit_data(CodedBitstreamContext *ctx, - CodedBitstreamUnit *unit, +int ff_cbs_alloc_unit_data(CodedBitstreamUnit *unit, size_t size); /** @@ -365,8 +388,7 @@ * The content structure continues to be owned by the caller if * content_buf is not supplied. */ -int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag, +int ff_cbs_insert_unit_content(CodedBitstreamFragment *frag, int position, CodedBitstreamUnitType type, void *content, @@ -376,10 +398,10 @@ * Insert a new unit into a fragment with the given data bitstream. * * If data_buf is not supplied then data must have been allocated with - * av_malloc() and will become owned by the unit after this call. + * av_malloc() and will on success become owned by the unit after this + * call or freed on error. */ -int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag, +int ff_cbs_insert_unit_data(CodedBitstreamFragment *frag, int position, CodedBitstreamUnitType type, uint8_t *data, size_t data_size, @@ -390,9 +412,37 @@ * * Requires position to be >= 0 and < frag->nb_units. */ -void ff_cbs_delete_unit(CodedBitstreamContext *ctx, - CodedBitstreamFragment *frag, +void ff_cbs_delete_unit(CodedBitstreamFragment *frag, int position); +/** + * Make the content of a unit refcounted. + * + * If the unit is not refcounted, this will do a deep copy of the unit + * content to new refcounted buffers. + * + * It is not valid to call this function on a unit which does not have + * decomposed content. + */ +int ff_cbs_make_unit_refcounted(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit); + +/** + * Make the content of a unit writable so that internal fields can be + * modified. + * + * If it is known that there are no other references to the content of + * the unit, does nothing and returns success. Otherwise (including the + * case where the unit content is not refcounted), it does a full clone + * of the content (including any internal buffers) to make a new copy, + * and replaces the existing references inside the unit with that. + * + * It is not valid to call this function on a unit which does not have + * decomposed content. + */ +int ff_cbs_make_unit_writable(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit); + + #endif /* AVCODEC_CBS_H */ diff -Nru ffmpeg-4.2.2/libavcodec/cbs_h2645.c ffmpeg-4.4/libavcodec/cbs_h2645.c --- ffmpeg-4.2.2/libavcodec/cbs_h2645.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_h2645.c 2021-04-08 21:28:39.000000000 +0000 @@ -233,6 +233,16 @@ return 0; } +// payload_extension_present() - true if we are before the last 1-bit +// in the payload structure, which must be in the last byte. +static int cbs_h265_payload_extension_present(GetBitContext *gbc, uint32_t payload_size, + int cur_pos) +{ + int bits_left = payload_size * 8 - cur_pos; + return (bits_left > 0 && + (bits_left > 7 || show_bits(gbc, bits_left) & MAX_UINT_BITS(bits_left - 1))); +} + #define HEADER(name) do { \ ff_cbs_trace_header(ctx, name); \ } while (0) @@ -243,25 +253,27 @@ return err; \ } while (0) -#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name -#define FUNC_H264(rw, name) FUNC_NAME(rw, h264, name) -#define FUNC_H265(rw, name) FUNC_NAME(rw, h265, name) +#define FUNC_NAME2(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name +#define FUNC_NAME1(rw, codec, name) FUNC_NAME2(rw, codec, name) +#define FUNC_H264(name) FUNC_NAME1(READWRITE, h264, name) +#define FUNC_H265(name) FUNC_NAME1(READWRITE, h265, name) +#define FUNC_SEI(name) FUNC_NAME1(READWRITE, sei, name) #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL) #define u(width, name, range_min, range_max) \ - xu(width, name, current->name, range_min, range_max, 0) + xu(width, name, current->name, range_min, range_max, 0, ) #define ub(width, name) \ - xu(width, name, current->name, 0, MAX_UINT_BITS(width), 0) + xu(width, name, current->name, 0, MAX_UINT_BITS(width), 0, ) #define flag(name) ub(1, name) #define ue(name, range_min, range_max) \ - xue(name, current->name, range_min, range_max, 0) + xue(name, current->name, range_min, range_max, 0, ) #define i(width, name, range_min, range_max) \ - xi(width, name, current->name, range_min, range_max, 0) + xi(width, name, current->name, range_min, range_max, 0, ) #define ib(width, name) \ - xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), 0) + xi(width, name, current->name, MIN_INT_BITS(width), MAX_INT_BITS(width), 0, ) #define se(name, range_min, range_max) \ - xse(name, current->name, range_min, range_max, 0) + xse(name, current->name, range_min, range_max, 0, ) #define us(width, name, range_min, range_max, subs, ...) \ xu(width, name, current->name, range_min, range_max, subs, __VA_ARGS__) @@ -280,7 +292,7 @@ #define fixed(width, name, value) do { \ av_unused uint32_t fixed_value = value; \ - xu(width, name, fixed_value, value, value, 0); \ + xu(width, name, fixed_value, value, value, 0, ); \ } while (0) @@ -336,6 +348,7 @@ #define more_rbsp_data(var) ((var) = cbs_h2645_read_more_rbsp_data(rw)) +#define bit_position(rw) (get_bits_count(rw)) #define byte_alignment(rw) (get_bits_count(rw) % 8) #define allocate(name, size) do { \ @@ -346,11 +359,15 @@ name = name ## _ref->data; \ } while (0) -#define FUNC(name) FUNC_H264(READWRITE, name) +#define FUNC(name) FUNC_SEI(name) +#include "cbs_sei_syntax_template.c" +#undef FUNC + +#define FUNC(name) FUNC_H264(name) #include "cbs_h264_syntax_template.c" #undef FUNC -#define FUNC(name) FUNC_H265(READWRITE, name) +#define FUNC(name) FUNC_H265(name) #include "cbs_h265_syntax_template.c" #undef FUNC @@ -363,6 +380,7 @@ #undef xse #undef infer #undef more_rbsp_data +#undef bit_position #undef byte_alignment #undef allocate @@ -398,15 +416,17 @@ #define infer(name, value) do { \ if (current->name != (value)) { \ - av_log(ctx->log_ctx, AV_LOG_WARNING, "Warning: " \ + av_log(ctx->log_ctx, AV_LOG_ERROR, \ "%s does not match inferred value: " \ "%"PRId64", but should be %"PRId64".\n", \ #name, (int64_t)current->name, (int64_t)(value)); \ + return AVERROR_INVALIDDATA; \ } \ } while (0) #define more_rbsp_data(var) (var) +#define bit_position(rw) (put_bits_count(rw)) #define byte_alignment(rw) (put_bits_count(rw) % 8) #define allocate(name, size) do { \ @@ -417,11 +437,15 @@ } \ } while (0) -#define FUNC(name) FUNC_H264(READWRITE, name) +#define FUNC(name) FUNC_SEI(name) +#include "cbs_sei_syntax_template.c" +#undef FUNC + +#define FUNC(name) FUNC_H264(name) #include "cbs_h264_syntax_template.c" #undef FUNC -#define FUNC(name) FUNC_H265(READWRITE, name) +#define FUNC(name) FUNC_H265(name) #include "cbs_h265_syntax_template.c" #undef FUNC @@ -439,121 +463,11 @@ #undef se #undef infer #undef more_rbsp_data +#undef bit_position #undef byte_alignment #undef allocate -static void cbs_h264_free_pps(void *unit, uint8_t *content) -{ - H264RawPPS *pps = (H264RawPPS*)content; - av_buffer_unref(&pps->slice_group_id_ref); - av_freep(&content); -} - -static void cbs_h264_free_sei_payload(H264RawSEIPayload *payload) -{ - switch (payload->payload_type) { - case H264_SEI_TYPE_BUFFERING_PERIOD: - case H264_SEI_TYPE_PIC_TIMING: - case H264_SEI_TYPE_PAN_SCAN_RECT: - case H264_SEI_TYPE_RECOVERY_POINT: - case H264_SEI_TYPE_DISPLAY_ORIENTATION: - case H264_SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME: - case H264_SEI_TYPE_ALTERNATIVE_TRANSFER: - break; - case H264_SEI_TYPE_USER_DATA_REGISTERED: - av_buffer_unref(&payload->payload.user_data_registered.data_ref); - break; - case H264_SEI_TYPE_USER_DATA_UNREGISTERED: - av_buffer_unref(&payload->payload.user_data_unregistered.data_ref); - break; - default: - av_buffer_unref(&payload->payload.other.data_ref); - break; - } -} - -static void cbs_h264_free_sei(void *unit, uint8_t *content) -{ - H264RawSEI *sei = (H264RawSEI*)content; - int i; - for (i = 0; i < sei->payload_count; i++) - cbs_h264_free_sei_payload(&sei->payload[i]); - av_freep(&content); -} - -static void cbs_h264_free_slice(void *unit, uint8_t *content) -{ - H264RawSlice *slice = (H264RawSlice*)content; - av_buffer_unref(&slice->data_ref); - av_freep(&content); -} - -static void cbs_h265_free_vps(void *unit, uint8_t *content) -{ - H265RawVPS *vps = (H265RawVPS*)content; - av_buffer_unref(&vps->extension_data.data_ref); - av_freep(&content); -} - -static void cbs_h265_free_sps(void *unit, uint8_t *content) -{ - H265RawSPS *sps = (H265RawSPS*)content; - av_buffer_unref(&sps->extension_data.data_ref); - av_freep(&content); -} - -static void cbs_h265_free_pps(void *unit, uint8_t *content) -{ - H265RawPPS *pps = (H265RawPPS*)content; - av_buffer_unref(&pps->extension_data.data_ref); - av_freep(&content); -} - -static void cbs_h265_free_slice(void *unit, uint8_t *content) -{ - H265RawSlice *slice = (H265RawSlice*)content; - av_buffer_unref(&slice->data_ref); - av_freep(&content); -} - -static void cbs_h265_free_sei_payload(H265RawSEIPayload *payload) -{ - switch (payload->payload_type) { - case HEVC_SEI_TYPE_BUFFERING_PERIOD: - case HEVC_SEI_TYPE_PICTURE_TIMING: - case HEVC_SEI_TYPE_PAN_SCAN_RECT: - case HEVC_SEI_TYPE_RECOVERY_POINT: - case HEVC_SEI_TYPE_DISPLAY_ORIENTATION: - case HEVC_SEI_TYPE_ACTIVE_PARAMETER_SETS: - case HEVC_SEI_TYPE_DECODED_PICTURE_HASH: - case HEVC_SEI_TYPE_TIME_CODE: - case HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO: - case HEVC_SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO: - case HEVC_SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS: - case HEVC_SEI_TYPE_ALPHA_CHANNEL_INFO: - break; - case HEVC_SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35: - av_buffer_unref(&payload->payload.user_data_registered.data_ref); - break; - case HEVC_SEI_TYPE_USER_DATA_UNREGISTERED: - av_buffer_unref(&payload->payload.user_data_unregistered.data_ref); - break; - default: - av_buffer_unref(&payload->payload.other.data_ref); - break; - } -} - -static void cbs_h265_free_sei(void *unit, uint8_t *content) -{ - H265RawSEI *sei = (H265RawSEI*)content; - int i; - for (i = 0; i < sei->payload_count; i++) - cbs_h265_free_sei_payload(&sei->payload[i]); - av_freep(&content); -} - static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, const H2645Packet *packet) @@ -565,15 +479,21 @@ AVBufferRef *ref; size_t size = nal->size; + if (nal->nuh_layer_id > 0) + continue; + // Remove trailing zeroes. while (size > 0 && nal->data[size - 1] == 0) --size; - av_assert0(size > 0); + if (size == 0) { + av_log(ctx->log_ctx, AV_LOG_VERBOSE, "Discarding empty 0 NAL unit\n"); + continue; + } ref = (nal->data == nal->raw_data) ? frag->data_ref : packet->rbsp.rbsp_buffer_ref; - err = ff_cbs_insert_unit_data(ctx, frag, -1, nal->type, + err = ff_cbs_insert_unit_data(frag, -1, nal->type, (uint8_t*)nal->data, size, ref); if (err < 0) return err; @@ -610,7 +530,7 @@ version = bytestream2_get_byte(&gbc); if (version != 1) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid AVCC header: " - "first byte %u.", version); + "first byte %u.\n", version); return AVERROR_INVALIDDATA; } @@ -685,7 +605,7 @@ version = bytestream2_get_byte(&gbc); if (version != 1) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid HVCC header: " - "first byte %u.", version); + "first byte %u.\n", version); return AVERROR_INVALIDDATA; } @@ -748,23 +668,23 @@ CodedBitstreamH26 ## h26n ## Context *priv = ctx->priv_data; \ H26 ## h26n ## Raw ## ps_name *ps_var = unit->content; \ unsigned int id = ps_var->id_element; \ - if (id > FF_ARRAY_ELEMS(priv->ps_var)) { \ + int err; \ + if (id >= FF_ARRAY_ELEMS(priv->ps_var)) { \ av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid " #ps_name \ " id : %d.\n", id); \ return AVERROR_INVALIDDATA; \ } \ + err = ff_cbs_make_unit_refcounted(ctx, unit); \ + if (err < 0) \ + return err; \ if (priv->ps_var[id] == priv->active_ ## ps_var) \ priv->active_ ## ps_var = NULL ; \ av_buffer_unref(&priv->ps_var ## _ref[id]); \ - if (unit->content_ref) \ - priv->ps_var ## _ref[id] = av_buffer_ref(unit->content_ref); \ - else \ - priv->ps_var ## _ref[id] = av_buffer_alloc(sizeof(*ps_var)); \ + av_assert0(unit->content_ref); \ + priv->ps_var ## _ref[id] = av_buffer_ref(unit->content_ref); \ if (!priv->ps_var ## _ref[id]) \ return AVERROR(ENOMEM); \ priv->ps_var[id] = (H26 ## h26n ## Raw ## ps_name *)priv->ps_var ## _ref[id]->data; \ - if (!unit->content_ref) \ - memcpy(priv->ps_var[id], ps_var, sizeof(*ps_var)); \ return 0; \ } @@ -784,15 +704,14 @@ if (err < 0) return err; + err = ff_cbs_alloc_unit_content2(ctx, unit); + if (err < 0) + return err; + switch (unit->type) { case H264_NAL_SPS: { - H264RawSPS *sps; - - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*sps), NULL); - if (err < 0) - return err; - sps = unit->content; + H264RawSPS *sps = unit->content; err = cbs_h264_read_sps(ctx, &gbc, sps); if (err < 0) @@ -806,12 +725,6 @@ case H264_NAL_SPS_EXT: { - err = ff_cbs_alloc_unit_content(ctx, unit, - sizeof(H264RawSPSExtension), - NULL); - if (err < 0) - return err; - err = cbs_h264_read_sps_extension(ctx, &gbc, unit->content); if (err < 0) return err; @@ -820,13 +733,7 @@ case H264_NAL_PPS: { - H264RawPPS *pps; - - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*pps), - &cbs_h264_free_pps); - if (err < 0) - return err; - pps = unit->content; + H264RawPPS *pps = unit->content; err = cbs_h264_read_pps(ctx, &gbc, pps); if (err < 0) @@ -842,28 +749,18 @@ case H264_NAL_IDR_SLICE: case H264_NAL_AUXILIARY_SLICE: { - H264RawSlice *slice; + H264RawSlice *slice = unit->content; int pos, len; - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*slice), - &cbs_h264_free_slice); - if (err < 0) - return err; - slice = unit->content; - err = cbs_h264_read_slice_header(ctx, &gbc, &slice->header); if (err < 0) return err; + if (!cbs_h2645_read_more_rbsp_data(&gbc)) + return AVERROR_INVALIDDATA; + pos = get_bits_count(&gbc); len = unit->data_size; - if (!unit->data[len - 1]) { - int z; - for (z = 0; z < len && !unit->data[len - z - 1]; z++); - av_log(ctx->log_ctx, AV_LOG_DEBUG, "Deleted %d trailing zeroes " - "from slice data.\n", z); - len -= z; - } slice->data_size = len - pos / 8; slice->data_ref = av_buffer_ref(unit->data_ref); @@ -876,11 +773,6 @@ case H264_NAL_AUD: { - err = ff_cbs_alloc_unit_content(ctx, unit, - sizeof(H264RawAUD), NULL); - if (err < 0) - return err; - err = cbs_h264_read_aud(ctx, &gbc, unit->content); if (err < 0) return err; @@ -889,11 +781,6 @@ case H264_NAL_SEI: { - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(H264RawSEI), - &cbs_h264_free_sei); - if (err < 0) - return err; - err = cbs_h264_read_sei(ctx, &gbc, unit->content); if (err < 0) return err; @@ -902,11 +789,6 @@ case H264_NAL_FILLER_DATA: { - err = ff_cbs_alloc_unit_content(ctx, unit, - sizeof(H264RawFiller), NULL); - if (err < 0) - return err; - err = cbs_h264_read_filler(ctx, &gbc, unit->content); if (err < 0) return err; @@ -916,12 +798,6 @@ case H264_NAL_END_SEQUENCE: case H264_NAL_END_STREAM: { - err = ff_cbs_alloc_unit_content(ctx, unit, - sizeof(H264RawNALUnitHeader), - NULL); - if (err < 0) - return err; - err = (unit->type == H264_NAL_END_SEQUENCE ? cbs_h264_read_end_of_sequence : cbs_h264_read_end_of_stream)(ctx, &gbc, unit->content); @@ -947,16 +823,14 @@ if (err < 0) return err; + err = ff_cbs_alloc_unit_content2(ctx, unit); + if (err < 0) + return err; + switch (unit->type) { case HEVC_NAL_VPS: { - H265RawVPS *vps; - - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*vps), - &cbs_h265_free_vps); - if (err < 0) - return err; - vps = unit->content; + H265RawVPS *vps = unit->content; err = cbs_h265_read_vps(ctx, &gbc, vps); if (err < 0) @@ -969,13 +843,7 @@ break; case HEVC_NAL_SPS: { - H265RawSPS *sps; - - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*sps), - &cbs_h265_free_sps); - if (err < 0) - return err; - sps = unit->content; + H265RawSPS *sps = unit->content; err = cbs_h265_read_sps(ctx, &gbc, sps); if (err < 0) @@ -989,13 +857,7 @@ case HEVC_NAL_PPS: { - H265RawPPS *pps; - - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*pps), - &cbs_h265_free_pps); - if (err < 0) - return err; - pps = unit->content; + H265RawPPS *pps = unit->content; err = cbs_h265_read_pps(ctx, &gbc, pps); if (err < 0) @@ -1024,28 +886,18 @@ case HEVC_NAL_IDR_N_LP: case HEVC_NAL_CRA_NUT: { - H265RawSlice *slice; + H265RawSlice *slice = unit->content; int pos, len; - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*slice), - &cbs_h265_free_slice); - if (err < 0) - return err; - slice = unit->content; - err = cbs_h265_read_slice_segment_header(ctx, &gbc, &slice->header); if (err < 0) return err; + if (!cbs_h2645_read_more_rbsp_data(&gbc)) + return AVERROR_INVALIDDATA; + pos = get_bits_count(&gbc); len = unit->data_size; - if (!unit->data[len - 1]) { - int z; - for (z = 0; z < len && !unit->data[len - z - 1]; z++); - av_log(ctx->log_ctx, AV_LOG_DEBUG, "Deleted %d trailing zeroes " - "from slice data.\n", z); - len -= z; - } slice->data_size = len - pos / 8; slice->data_ref = av_buffer_ref(unit->data_ref); @@ -1058,11 +910,6 @@ case HEVC_NAL_AUD: { - err = ff_cbs_alloc_unit_content(ctx, unit, - sizeof(H265RawAUD), NULL); - if (err < 0) - return err; - err = cbs_h265_read_aud(ctx, &gbc, unit->content); if (err < 0) return err; @@ -1072,12 +919,6 @@ case HEVC_NAL_SEI_PREFIX: case HEVC_NAL_SEI_SUFFIX: { - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(H265RawSEI), - &cbs_h265_free_sei); - - if (err < 0) - return err; - err = cbs_h265_read_sei(ctx, &gbc, unit->content, unit->type == HEVC_NAL_SEI_PREFIX); @@ -1380,6 +1221,22 @@ return 0; } +static int cbs_h2645_unit_requires_zero_byte(enum AVCodecID codec_id, + CodedBitstreamUnitType type, + int nal_unit_index) +{ + // Section B.1.2 in H.264, section B.2.2 in H.265. + if (nal_unit_index == 0) { + // Assume that this is the first NAL unit in an access unit. + return 1; + } + if (codec_id == AV_CODEC_ID_H264) + return type == H264_NAL_SPS || type == H264_NAL_PPS; + if (codec_id == AV_CODEC_ID_HEVC) + return type == HEVC_NAL_VPS || type == HEVC_NAL_SPS || type == HEVC_NAL_PPS; + return 0; +} + static int cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag) { @@ -1398,7 +1255,7 @@ max_size += 4 + frag->units[i].data_size * 3 / 2; } - data = av_malloc(max_size + AV_INPUT_BUFFER_PADDING_SIZE); + data = av_realloc(NULL, max_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!data) return AVERROR(ENOMEM); @@ -1414,14 +1271,7 @@ frag->data_bit_padding = unit->data_bit_padding; } - if ((ctx->codec->codec_id == AV_CODEC_ID_H264 && - (unit->type == H264_NAL_SPS || - unit->type == H264_NAL_PPS)) || - (ctx->codec->codec_id == AV_CODEC_ID_HEVC && - (unit->type == HEVC_NAL_VPS || - unit->type == HEVC_NAL_SPS || - unit->type == HEVC_NAL_PPS)) || - i == 0 /* (Assume this is the start of an access unit.) */) { + if (cbs_h2645_unit_requires_zero_byte(ctx->codec->codec_id, unit->type, i)) { // zero_byte data[dp++] = 0; } @@ -1467,6 +1317,24 @@ return 0; } +static void cbs_h264_flush(CodedBitstreamContext *ctx) +{ + CodedBitstreamH264Context *h264 = ctx->priv_data; + + for (int i = 0; i < FF_ARRAY_ELEMS(h264->sps); i++) { + av_buffer_unref(&h264->sps_ref[i]); + h264->sps[i] = NULL; + } + for (int i = 0; i < FF_ARRAY_ELEMS(h264->pps); i++) { + av_buffer_unref(&h264->pps_ref[i]); + h264->pps[i] = NULL; + } + + h264->active_sps = NULL; + h264->active_pps = NULL; + h264->last_slice_nal_unit_type = 0; +} + static void cbs_h264_close(CodedBitstreamContext *ctx) { CodedBitstreamH264Context *h264 = ctx->priv_data; @@ -1480,6 +1348,28 @@ av_buffer_unref(&h264->pps_ref[i]); } +static void cbs_h265_flush(CodedBitstreamContext *ctx) +{ + CodedBitstreamH265Context *h265 = ctx->priv_data; + + for (int i = 0; i < FF_ARRAY_ELEMS(h265->vps); i++) { + av_buffer_unref(&h265->vps_ref[i]); + h265->vps[i] = NULL; + } + for (int i = 0; i < FF_ARRAY_ELEMS(h265->sps); i++) { + av_buffer_unref(&h265->sps_ref[i]); + h265->sps[i] = NULL; + } + for (int i = 0; i < FF_ARRAY_ELEMS(h265->pps); i++) { + av_buffer_unref(&h265->pps_ref[i]); + h265->pps[i] = NULL; + } + + h265->active_vps = NULL; + h265->active_sps = NULL; + h265->active_pps = NULL; +} + static void cbs_h265_close(CodedBitstreamContext *ctx) { CodedBitstreamH265Context *h265 = ctx->priv_data; @@ -1495,16 +1385,107 @@ av_buffer_unref(&h265->pps_ref[i]); } +static void cbs_h264_free_sei(void *opaque, uint8_t *content) +{ + H264RawSEI *sei = (H264RawSEI*)content; + ff_cbs_sei_free_message_list(&sei->message_list); + av_free(content); +} + +static const CodedBitstreamUnitTypeDescriptor cbs_h264_unit_types[] = { + CBS_UNIT_TYPE_POD(H264_NAL_SPS, H264RawSPS), + CBS_UNIT_TYPE_POD(H264_NAL_SPS_EXT, H264RawSPSExtension), + + CBS_UNIT_TYPE_INTERNAL_REF(H264_NAL_PPS, H264RawPPS, slice_group_id), + + { + .nb_unit_types = 3, + .unit_types = { + H264_NAL_IDR_SLICE, + H264_NAL_SLICE, + H264_NAL_AUXILIARY_SLICE, + }, + .content_type = CBS_CONTENT_TYPE_INTERNAL_REFS, + .content_size = sizeof(H264RawSlice), + .nb_ref_offsets = 1, + .ref_offsets = { offsetof(H264RawSlice, data) }, + }, + + CBS_UNIT_TYPE_POD(H264_NAL_AUD, H264RawAUD), + CBS_UNIT_TYPE_POD(H264_NAL_FILLER_DATA, H264RawFiller), + CBS_UNIT_TYPE_POD(H264_NAL_END_SEQUENCE, H264RawNALUnitHeader), + CBS_UNIT_TYPE_POD(H264_NAL_END_STREAM, H264RawNALUnitHeader), + + CBS_UNIT_TYPE_COMPLEX(H264_NAL_SEI, H264RawSEI, &cbs_h264_free_sei), + + CBS_UNIT_TYPE_END_OF_LIST +}; + +static void cbs_h265_free_sei(void *opaque, uint8_t *content) +{ + H265RawSEI *sei = (H265RawSEI*)content; + ff_cbs_sei_free_message_list(&sei->message_list); + av_free(content); +} + +static const CodedBitstreamUnitTypeDescriptor cbs_h265_unit_types[] = { + CBS_UNIT_TYPE_INTERNAL_REF(HEVC_NAL_VPS, H265RawVPS, extension_data.data), + CBS_UNIT_TYPE_INTERNAL_REF(HEVC_NAL_SPS, H265RawSPS, extension_data.data), + CBS_UNIT_TYPE_INTERNAL_REF(HEVC_NAL_PPS, H265RawPPS, extension_data.data), + + CBS_UNIT_TYPE_POD(HEVC_NAL_AUD, H265RawAUD), + + { + // Slices of non-IRAP pictures. + .nb_unit_types = CBS_UNIT_TYPE_RANGE, + .unit_type_range_start = HEVC_NAL_TRAIL_N, + .unit_type_range_end = HEVC_NAL_RASL_R, + + .content_type = CBS_CONTENT_TYPE_INTERNAL_REFS, + .content_size = sizeof(H265RawSlice), + .nb_ref_offsets = 1, + .ref_offsets = { offsetof(H265RawSlice, data) }, + }, + + { + // Slices of IRAP pictures. + .nb_unit_types = CBS_UNIT_TYPE_RANGE, + .unit_type_range_start = HEVC_NAL_BLA_W_LP, + .unit_type_range_end = HEVC_NAL_CRA_NUT, + + .content_type = CBS_CONTENT_TYPE_INTERNAL_REFS, + .content_size = sizeof(H265RawSlice), + .nb_ref_offsets = 1, + .ref_offsets = { offsetof(H265RawSlice, data) }, + }, + + { + .nb_unit_types = 2, + .unit_types = { + HEVC_NAL_SEI_PREFIX, + HEVC_NAL_SEI_SUFFIX + }, + .content_type = CBS_CONTENT_TYPE_COMPLEX, + .content_size = sizeof(H265RawSEI), + .content_free = &cbs_h265_free_sei, + }, + + CBS_UNIT_TYPE_END_OF_LIST +}; + const CodedBitstreamType ff_cbs_type_h264 = { .codec_id = AV_CODEC_ID_H264, .priv_data_size = sizeof(CodedBitstreamH264Context), + .unit_types = cbs_h264_unit_types, + .split_fragment = &cbs_h2645_split_fragment, .read_unit = &cbs_h264_read_nal_unit, .write_unit = &cbs_h264_write_nal_unit, .assemble_fragment = &cbs_h2645_assemble_fragment, + .flush = &cbs_h264_flush, .close = &cbs_h264_close, }; @@ -1513,102 +1494,175 @@ .priv_data_size = sizeof(CodedBitstreamH265Context), + .unit_types = cbs_h265_unit_types, + .split_fragment = &cbs_h2645_split_fragment, .read_unit = &cbs_h265_read_nal_unit, .write_unit = &cbs_h265_write_nal_unit, .assemble_fragment = &cbs_h2645_assemble_fragment, + .flush = &cbs_h265_flush, .close = &cbs_h265_close, }; -int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx, - CodedBitstreamFragment *au, - const H264RawSEIPayload *payload) -{ - H264RawSEI *sei; - CodedBitstreamUnit *nal = NULL; - int err, i; - - // Find an existing SEI NAL unit to add to. - for (i = 0; i < au->nb_units; i++) { - if (au->units[i].type == H264_NAL_SEI) { - nal = &au->units[i]; - break; - } - } - if (nal) { - sei = nal->content; - - } else { - // Need to make a new SEI NAL unit. Insert it before the first - // slice data NAL unit; if no slice data, add at the end. - AVBufferRef *sei_ref; - - sei = av_mallocz(sizeof(*sei)); - if (!sei) - return AVERROR(ENOMEM); +static const SEIMessageTypeDescriptor cbs_sei_common_types[] = { + { + SEI_TYPE_FILLER_PAYLOAD, + 1, 1, + sizeof(SEIRawFillerPayload), + SEI_MESSAGE_RW(sei, filler_payload), + }, + { + SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35, + 1, 1, + sizeof(SEIRawUserDataRegistered), + SEI_MESSAGE_RW(sei, user_data_registered), + }, + { + SEI_TYPE_USER_DATA_UNREGISTERED, + 1, 1, + sizeof(SEIRawUserDataUnregistered), + SEI_MESSAGE_RW(sei, user_data_unregistered), + }, + { + SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME, + 1, 0, + sizeof(SEIRawMasteringDisplayColourVolume), + SEI_MESSAGE_RW(sei, mastering_display_colour_volume), + }, + { + SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO, + 1, 0, + sizeof(SEIRawContentLightLevelInfo), + SEI_MESSAGE_RW(sei, content_light_level_info), + }, + { + SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS, + 1, 0, + sizeof(SEIRawAlternativeTransferCharacteristics), + SEI_MESSAGE_RW(sei, alternative_transfer_characteristics), + }, + SEI_MESSAGE_TYPE_END, +}; - sei->nal_unit_header.nal_unit_type = H264_NAL_SEI; - sei->nal_unit_header.nal_ref_idc = 0; +static const SEIMessageTypeDescriptor cbs_sei_h264_types[] = { + { + SEI_TYPE_BUFFERING_PERIOD, + 1, 0, + sizeof(H264RawSEIBufferingPeriod), + SEI_MESSAGE_RW(h264, sei_buffering_period), + }, + { + SEI_TYPE_PIC_TIMING, + 1, 0, + sizeof(H264RawSEIPicTiming), + SEI_MESSAGE_RW(h264, sei_pic_timing), + }, + { + SEI_TYPE_PAN_SCAN_RECT, + 1, 0, + sizeof(H264RawSEIPanScanRect), + SEI_MESSAGE_RW(h264, sei_pan_scan_rect), + }, + { + SEI_TYPE_RECOVERY_POINT, + 1, 0, + sizeof(H264RawSEIRecoveryPoint), + SEI_MESSAGE_RW(h264, sei_recovery_point), + }, + { + SEI_TYPE_DISPLAY_ORIENTATION, + 1, 0, + sizeof(H264RawSEIDisplayOrientation), + SEI_MESSAGE_RW(h264, sei_display_orientation), + }, + SEI_MESSAGE_TYPE_END +}; - sei_ref = av_buffer_create((uint8_t*)sei, sizeof(*sei), - &cbs_h264_free_sei, ctx, 0); - if (!sei_ref) { - av_freep(&sei); - return AVERROR(ENOMEM); - } +static const SEIMessageTypeDescriptor cbs_sei_h265_types[] = { + { + SEI_TYPE_BUFFERING_PERIOD, + 1, 0, + sizeof(H265RawSEIBufferingPeriod), + SEI_MESSAGE_RW(h265, sei_buffering_period), + }, + { + SEI_TYPE_PIC_TIMING, + 1, 0, + sizeof(H265RawSEIPicTiming), + SEI_MESSAGE_RW(h265, sei_pic_timing), + }, + { + SEI_TYPE_PAN_SCAN_RECT, + 1, 0, + sizeof(H265RawSEIPanScanRect), + SEI_MESSAGE_RW(h265, sei_pan_scan_rect), + }, + { + SEI_TYPE_RECOVERY_POINT, + 1, 0, + sizeof(H265RawSEIRecoveryPoint), + SEI_MESSAGE_RW(h265, sei_recovery_point), + }, + { + SEI_TYPE_DISPLAY_ORIENTATION, + 1, 0, + sizeof(H265RawSEIDisplayOrientation), + SEI_MESSAGE_RW(h265, sei_display_orientation), + }, + { + SEI_TYPE_ACTIVE_PARAMETER_SETS, + 1, 0, + sizeof(H265RawSEIActiveParameterSets), + SEI_MESSAGE_RW(h265, sei_active_parameter_sets), + }, + { + SEI_TYPE_DECODED_PICTURE_HASH, + 0, 1, + sizeof(H265RawSEIDecodedPictureHash), + SEI_MESSAGE_RW(h265, sei_decoded_picture_hash), + }, + { + SEI_TYPE_TIME_CODE, + 1, 0, + sizeof(H265RawSEITimeCode), + SEI_MESSAGE_RW(h265, sei_time_code), + }, + { + SEI_TYPE_ALPHA_CHANNEL_INFO, + 1, 0, + sizeof(H265RawSEIAlphaChannelInfo), + SEI_MESSAGE_RW(h265, sei_alpha_channel_info), + }, + SEI_MESSAGE_TYPE_END +}; - for (i = 0; i < au->nb_units; i++) { - if (au->units[i].type == H264_NAL_SLICE || - au->units[i].type == H264_NAL_IDR_SLICE) - break; - } +const SEIMessageTypeDescriptor *ff_cbs_sei_find_type(CodedBitstreamContext *ctx, + int payload_type) +{ + const SEIMessageTypeDescriptor *codec_list; + int i; - err = ff_cbs_insert_unit_content(ctx, au, i, H264_NAL_SEI, - sei, sei_ref); - av_buffer_unref(&sei_ref); - if (err < 0) - return err; + for (i = 0; cbs_sei_common_types[i].type >= 0; i++) { + if (cbs_sei_common_types[i].type == payload_type) + return &cbs_sei_common_types[i]; } - if (sei->payload_count >= H264_MAX_SEI_PAYLOADS) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many payloads in " - "SEI NAL unit.\n"); - return AVERROR(EINVAL); + switch (ctx->codec->codec_id) { + case AV_CODEC_ID_H264: + codec_list = cbs_sei_h264_types; + break; + case AV_CODEC_ID_H265: + codec_list = cbs_sei_h265_types; + break; + default: + return NULL; } - memcpy(&sei->payload[sei->payload_count], payload, sizeof(*payload)); - ++sei->payload_count; - - return 0; -} - -void ff_cbs_h264_delete_sei_message(CodedBitstreamContext *ctx, - CodedBitstreamFragment *au, - CodedBitstreamUnit *nal, - int position) -{ - H264RawSEI *sei = nal->content; - - av_assert0(nal->type == H264_NAL_SEI); - av_assert0(position >= 0 && position < sei->payload_count); - - if (position == 0 && sei->payload_count == 1) { - // Deleting NAL unit entirely. - int i; - - for (i = 0; i < au->nb_units; i++) { - if (&au->units[i] == nal) - break; - } - - ff_cbs_delete_unit(ctx, au, i); - } else { - cbs_h264_free_sei_payload(&sei->payload[position]); - - --sei->payload_count; - memmove(sei->payload + position, - sei->payload + position + 1, - (sei->payload_count - position) * sizeof(*sei->payload)); + for (i = 0; codec_list[i].type >= 0; i++) { + if (codec_list[i].type == payload_type) + return &codec_list[i]; } + + return NULL; } diff -Nru ffmpeg-4.2.2/libavcodec/cbs_h264.h ffmpeg-4.4/libavcodec/cbs_h264.h --- ffmpeg-4.2.2/libavcodec/cbs_h264.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_h264.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,19 +24,10 @@ #include "cbs.h" #include "cbs_h2645.h" +#include "cbs_sei.h" #include "h264.h" -enum { - // This limit is arbitrary - it is sufficient for one message of each - // type plus some repeats, and will therefore easily cover all sane - // streams. However, it is possible to make technically-valid streams - // for which it will fail (for example, by including a large number of - // user-data-unregistered messages). - H264_MAX_SEI_PAYLOADS = 64, -}; - - typedef struct H264RawNALUnitHeader { uint8_t nal_ref_idc; uint8_t nal_unit_type; @@ -274,21 +265,6 @@ uint16_t pan_scan_rect_repetition_period; } H264RawSEIPanScanRect; -typedef struct H264RawSEIUserDataRegistered { - uint8_t itu_t_t35_country_code; - uint8_t itu_t_t35_country_code_extension_byte; - uint8_t *data; - size_t data_length; - AVBufferRef *data_ref; -} H264RawSEIUserDataRegistered; - -typedef struct H264RawSEIUserDataUnregistered { - uint8_t uuid_iso_iec_11578[16]; - uint8_t *data; - size_t data_length; - AVBufferRef *data_ref; -} H264RawSEIUserDataUnregistered; - typedef struct H264RawSEIRecoveryPoint { uint16_t recovery_frame_cnt; uint8_t exact_match_flag; @@ -305,47 +281,9 @@ uint8_t display_orientation_extension_flag; } H264RawSEIDisplayOrientation; -typedef struct H264RawSEIMasteringDisplayColourVolume { - uint16_t display_primaries_x[3]; - uint16_t display_primaries_y[3]; - uint16_t white_point_x; - uint16_t white_point_y; - uint32_t max_display_mastering_luminance; - uint32_t min_display_mastering_luminance; -} H264RawSEIMasteringDisplayColourVolume; - -typedef struct H264RawSEIAlternativeTransferCharacteristics { - uint8_t preferred_transfer_characteristics; -} H264RawSEIAlternativeTransferCharacteristics; - -typedef struct H264RawSEIPayload { - uint32_t payload_type; - uint32_t payload_size; - union { - H264RawSEIBufferingPeriod buffering_period; - H264RawSEIPicTiming pic_timing; - H264RawSEIPanScanRect pan_scan_rect; - // H264RawSEIFiller filler -> no fields. - H264RawSEIUserDataRegistered user_data_registered; - H264RawSEIUserDataUnregistered user_data_unregistered; - H264RawSEIRecoveryPoint recovery_point; - H264RawSEIDisplayOrientation display_orientation; - H264RawSEIMasteringDisplayColourVolume mastering_display_colour_volume; - H264RawSEIAlternativeTransferCharacteristics - alternative_transfer_characteristics; - struct { - uint8_t *data; - size_t data_length; - AVBufferRef *data_ref; - } other; - } payload; -} H264RawSEIPayload; - typedef struct H264RawSEI { H264RawNALUnitHeader nal_unit_header; - - H264RawSEIPayload payload[H264_MAX_SEI_PAYLOADS]; - uint8_t payload_count; + SEIRawMessageList message_list; } H264RawSEI; typedef struct H264RawSliceHeader { @@ -429,10 +367,10 @@ typedef struct H264RawSlice { H264RawSliceHeader header; - uint8_t *data; - size_t data_size; - int data_bit_start; + uint8_t *data; AVBufferRef *data_ref; + size_t data_size; + int data_bit_start; } H264RawSlice; typedef struct H264RawFiller { @@ -465,26 +403,4 @@ uint8_t last_slice_nal_unit_type; } CodedBitstreamH264Context; - -/** - * Add an SEI message to an access unit. - */ -int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx, - CodedBitstreamFragment *access_unit, - const H264RawSEIPayload *payload); - -/** - * Delete an SEI message from an access unit. - * - * Deletes from nal_unit, which must be an SEI NAL unit. If this is the - * last message in nal_unit, also deletes it from access_unit. - * - * Requires nal_unit to be a unit in access_unit and position to be >= 0 - * and < the payload count of the SEI nal_unit. - */ -void ff_cbs_h264_delete_sei_message(CodedBitstreamContext *ctx, - CodedBitstreamFragment *access_unit, - CodedBitstreamUnit *nal_unit, - int position); - #endif /* AVCODEC_CBS_H264_H */ diff -Nru ffmpeg-4.2.2/libavcodec/cbs_h264_syntax_template.c ffmpeg-4.4/libavcodec/cbs_h264_syntax_template.c --- ffmpeg-4.2.2/libavcodec/cbs_h264_syntax_template.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_h264_syntax_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -511,7 +511,8 @@ } static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw, - H264RawSEIBufferingPeriod *current) + H264RawSEIBufferingPeriod *current, + SEIMessageState *sei) { CodedBitstreamH264Context *h264 = ctx->priv_data; const H264RawSPS *sps; @@ -604,7 +605,8 @@ } static int FUNC(sei_pic_timing)(CodedBitstreamContext *ctx, RWContext *rw, - H264RawSEIPicTiming *current) + H264RawSEIPicTiming *current, + SEIMessageState *sei) { CodedBitstreamH264Context *h264 = ctx->priv_data; const H264RawSPS *sps; @@ -675,7 +677,8 @@ } static int FUNC(sei_pan_scan_rect)(CodedBitstreamContext *ctx, RWContext *rw, - H264RawSEIPanScanRect *current) + H264RawSEIPanScanRect *current, + SEIMessageState *sei) { int err, i; @@ -700,72 +703,9 @@ return 0; } -static int FUNC(sei_user_data_registered)(CodedBitstreamContext *ctx, RWContext *rw, - H264RawSEIUserDataRegistered *current, - uint32_t *payload_size) -{ - int err, i, j; - - HEADER("User Data Registered ITU-T T.35"); - - u(8, itu_t_t35_country_code, 0x00, 0xff); - if (current->itu_t_t35_country_code != 0xff) - i = 1; - else { - u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff); - i = 2; - } - -#ifdef READ - if (*payload_size < i) { - av_log(ctx->log_ctx, AV_LOG_ERROR, - "Invalid SEI user data registered payload.\n"); - return AVERROR_INVALIDDATA; - } - current->data_length = *payload_size - i; -#else - *payload_size = i + current->data_length; -#endif - - allocate(current->data, current->data_length); - for (j = 0; j < current->data_length; j++) - xu(8, itu_t_t35_payload_byte[i], current->data[j], 0x00, 0xff, 1, i + j); - - return 0; -} - -static int FUNC(sei_user_data_unregistered)(CodedBitstreamContext *ctx, RWContext *rw, - H264RawSEIUserDataUnregistered *current, - uint32_t *payload_size) -{ - int err, i; - - HEADER("User Data Unregistered"); - -#ifdef READ - if (*payload_size < 16) { - av_log(ctx->log_ctx, AV_LOG_ERROR, - "Invalid SEI user data unregistered payload.\n"); - return AVERROR_INVALIDDATA; - } - current->data_length = *payload_size - 16; -#else - *payload_size = 16 + current->data_length; -#endif - - for (i = 0; i < 16; i++) - us(8, uuid_iso_iec_11578[i], 0x00, 0xff, 1, i); - - allocate(current->data, current->data_length); - - for (i = 0; i < current->data_length; i++) - xu(8, user_data_payload_byte[i], current->data[i], 0x00, 0xff, 1, i); - - return 0; -} - static int FUNC(sei_recovery_point)(CodedBitstreamContext *ctx, RWContext *rw, - H264RawSEIRecoveryPoint *current) + H264RawSEIRecoveryPoint *current, + SEIMessageState *sei) { int err; @@ -780,7 +720,8 @@ } static int FUNC(sei_display_orientation)(CodedBitstreamContext *ctx, RWContext *rw, - H264RawSEIDisplayOrientation *current) + H264RawSEIDisplayOrientation *current, + SEIMessageState *sei) { int err; @@ -798,205 +739,17 @@ return 0; } -static int FUNC(sei_mastering_display_colour_volume)(CodedBitstreamContext *ctx, RWContext *rw, - H264RawSEIMasteringDisplayColourVolume *current) -{ - int err, c; - - HEADER("Mastering Display Colour Volume"); - - for (c = 0; c < 3; c++) { - us(16, display_primaries_x[c], 0, 50000, 1, c); - us(16, display_primaries_y[c], 0, 50000, 1, c); - } - - u(16, white_point_x, 0, 50000); - u(16, white_point_y, 0, 50000); - - u(32, max_display_mastering_luminance, 1, MAX_UINT_BITS(32)); - u(32, min_display_mastering_luminance, 0, current->max_display_mastering_luminance - 1); - - return 0; -} - -static int FUNC(sei_alternative_transfer_characteristics)(CodedBitstreamContext *ctx, - RWContext *rw, - H264RawSEIAlternativeTransferCharacteristics *current) -{ - int err; - - HEADER("Alternative Transfer Characteristics"); - - ub(8, preferred_transfer_characteristics); - - return 0; -} - -static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw, - H264RawSEIPayload *current) -{ - int err, i; - int start_position, end_position; - -#ifdef READ - start_position = get_bits_count(rw); -#else - start_position = put_bits_count(rw); -#endif - - switch (current->payload_type) { - case H264_SEI_TYPE_BUFFERING_PERIOD: - CHECK(FUNC(sei_buffering_period) - (ctx, rw, ¤t->payload.buffering_period)); - break; - case H264_SEI_TYPE_PIC_TIMING: - CHECK(FUNC(sei_pic_timing) - (ctx, rw, ¤t->payload.pic_timing)); - break; - case H264_SEI_TYPE_PAN_SCAN_RECT: - CHECK(FUNC(sei_pan_scan_rect) - (ctx, rw, ¤t->payload.pan_scan_rect)); - break; - case H264_SEI_TYPE_FILLER_PAYLOAD: - { - for (i = 0; i < current->payload_size; i++) - fixed(8, ff_byte, 0xff); - } - break; - case H264_SEI_TYPE_USER_DATA_REGISTERED: - CHECK(FUNC(sei_user_data_registered) - (ctx, rw, ¤t->payload.user_data_registered, ¤t->payload_size)); - break; - case H264_SEI_TYPE_USER_DATA_UNREGISTERED: - CHECK(FUNC(sei_user_data_unregistered) - (ctx, rw, ¤t->payload.user_data_unregistered, ¤t->payload_size)); - break; - case H264_SEI_TYPE_RECOVERY_POINT: - CHECK(FUNC(sei_recovery_point) - (ctx, rw, ¤t->payload.recovery_point)); - break; - case H264_SEI_TYPE_DISPLAY_ORIENTATION: - CHECK(FUNC(sei_display_orientation) - (ctx, rw, ¤t->payload.display_orientation)); - break; - case H264_SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME: - CHECK(FUNC(sei_mastering_display_colour_volume) - (ctx, rw, ¤t->payload.mastering_display_colour_volume)); - break; - case H264_SEI_TYPE_ALTERNATIVE_TRANSFER: - CHECK(FUNC(sei_alternative_transfer_characteristics) - (ctx, rw, ¤t->payload.alternative_transfer_characteristics)); - break; - default: - { -#ifdef READ - current->payload.other.data_length = current->payload_size; -#endif - allocate(current->payload.other.data, current->payload.other.data_length); - for (i = 0; i < current->payload.other.data_length; i++) - xu(8, payload_byte[i], current->payload.other.data[i], 0, 255, 1, i); - } - } - - if (byte_alignment(rw)) { - fixed(1, bit_equal_to_one, 1); - while (byte_alignment(rw)) - fixed(1, bit_equal_to_zero, 0); - } - -#ifdef READ - end_position = get_bits_count(rw); - if (end_position < start_position + 8 * current->payload_size) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Incorrect SEI payload length: " - "header %"PRIu32" bits, actually %d bits.\n", - 8 * current->payload_size, - end_position - start_position); - return AVERROR_INVALIDDATA; - } -#else - end_position = put_bits_count(rw); - current->payload_size = (end_position - start_position) / 8; -#endif - - return 0; -} - static int FUNC(sei)(CodedBitstreamContext *ctx, RWContext *rw, H264RawSEI *current) { - int err, k; + int err; HEADER("Supplemental Enhancement Information"); CHECK(FUNC(nal_unit_header)(ctx, rw, ¤t->nal_unit_header, 1 << H264_NAL_SEI)); -#ifdef READ - for (k = 0; k < H264_MAX_SEI_PAYLOADS; k++) { - uint32_t payload_type = 0; - uint32_t payload_size = 0; - uint32_t tmp; - - while (show_bits(rw, 8) == 0xff) { - fixed(8, ff_byte, 0xff); - payload_type += 255; - } - xu(8, last_payload_type_byte, tmp, 0, 254, 0); - payload_type += tmp; - - while (show_bits(rw, 8) == 0xff) { - fixed(8, ff_byte, 0xff); - payload_size += 255; - } - xu(8, last_payload_size_byte, tmp, 0, 254, 0); - payload_size += tmp; - - current->payload[k].payload_type = payload_type; - current->payload[k].payload_size = payload_size; - - current->payload_count++; - CHECK(FUNC(sei_payload)(ctx, rw, ¤t->payload[k])); - - if (!cbs_h2645_read_more_rbsp_data(rw)) - break; - } - if (k >= H264_MAX_SEI_PAYLOADS) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many payloads in " - "SEI message: found %d.\n", k); - return AVERROR_INVALIDDATA; - } -#else - for (k = 0; k < current->payload_count; k++) { - PutBitContext start_state; - uint32_t tmp; - int need_size, i; - - // Somewhat clumsy: we write the payload twice when - // we don't know the size in advance. This will mess - // with trace output, but is otherwise harmless. - start_state = *rw; - need_size = !current->payload[k].payload_size; - for (i = 0; i < 1 + need_size; i++) { - *rw = start_state; - - tmp = current->payload[k].payload_type; - while (tmp >= 255) { - fixed(8, ff_byte, 0xff); - tmp -= 255; - } - xu(8, last_payload_type_byte, tmp, 0, 254, 0); - - tmp = current->payload[k].payload_size; - while (tmp >= 255) { - fixed(8, ff_byte, 0xff); - tmp -= 255; - } - xu(8, last_payload_size_byte, tmp, 0, 254, 0); - - CHECK(FUNC(sei_payload)(ctx, rw, ¤t->payload[k])); - } - } -#endif + CHECK(FUNC_SEI(message_list)(ctx, rw, ¤t->message_list, 1)); CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); @@ -1366,7 +1119,7 @@ (sps->pic_height_in_map_units_minus1 + 1); max = (pic_size + pps->slice_group_change_rate_minus1) / (pps->slice_group_change_rate_minus1 + 1); - bits = av_log2(2 * max - 1); + bits = av_ceil_log2(max + 1); u(bits, slice_group_change_cycle, 0, max); } diff -Nru ffmpeg-4.2.2/libavcodec/cbs_h265.h ffmpeg-4.4/libavcodec/cbs_h265.h --- ffmpeg-4.2.2/libavcodec/cbs_h265.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_h265.h 2021-04-08 21:28:39.000000000 +0000 @@ -23,17 +23,9 @@ #include #include "cbs_h2645.h" +#include "cbs_sei.h" #include "hevc.h" -enum { - // This limit is arbitrary - it is sufficient for one message of each - // type plus some repeats, and will therefore easily cover all sane - // streams. However, it is possible to make technically-valid streams - // for which it will fail (for example, by including a large number of - // user-data-unregistered messages). - H265_MAX_SEI_PAYLOADS = 64, -}; - typedef struct H265RawNALUnitHeader { uint8_t nal_unit_type; uint8_t nuh_layer_id; @@ -182,11 +174,11 @@ uint8_t log2_max_mv_length_vertical; } H265RawVUI; -typedef struct H265RawPSExtensionData { - uint8_t *data; - size_t bit_length; +typedef struct H265RawExtensionData { + uint8_t *data; AVBufferRef *data_ref; -} H265RawPSExtensionData; + size_t bit_length; +} H265RawExtensionData; typedef struct H265RawVPS { H265RawNALUnitHeader nal_unit_header; @@ -221,7 +213,7 @@ H265RawHRDParameters hrd_parameters[HEVC_MAX_LAYER_SETS]; uint8_t vps_extension_flag; - H265RawPSExtensionData extension_data; + H265RawExtensionData extension_data; } H265RawVPS; typedef struct H265RawSTRefPicSet { @@ -325,7 +317,7 @@ uint8_t sps_scc_extension_flag; uint8_t sps_extension_4bits; - H265RawPSExtensionData extension_data; + H265RawExtensionData extension_data; // Range extension. uint8_t transform_skip_rotation_enabled_flag; @@ -413,7 +405,7 @@ uint8_t pps_scc_extension_flag; uint8_t pps_extension_4bits; - H265RawPSExtensionData extension_data; + H265RawExtensionData extension_data; // Range extension. uint8_t log2_max_transform_skip_block_size_minus2; @@ -541,10 +533,10 @@ typedef struct H265RawSlice { H265RawSliceHeader header; - uint8_t *data; - size_t data_size; - int data_bit_start; + uint8_t *data; AVBufferRef *data_ref; + size_t data_size; + int data_bit_start; } H265RawSlice; @@ -596,21 +588,6 @@ uint16_t pan_scan_rect_persistence_flag; } H265RawSEIPanScanRect; -typedef struct H265RawSEIUserDataRegistered { - uint8_t itu_t_t35_country_code; - uint8_t itu_t_t35_country_code_extension_byte; - uint8_t *data; - size_t data_length; - AVBufferRef *data_ref; -} H265RawSEIUserDataRegistered; - -typedef struct H265RawSEIUserDataUnregistered { - uint8_t uuid_iso_iec_11578[16]; - uint8_t *data; - size_t data_length; - AVBufferRef *data_ref; -} H265RawSEIUserDataUnregistered; - typedef struct H265RawSEIRecoveryPoint { int16_t recovery_poc_cnt; uint8_t exact_match_flag; @@ -661,24 +638,6 @@ int32_t time_offset_value[3]; } H265RawSEITimeCode; -typedef struct H265RawSEIMasteringDisplayColourVolume { - uint16_t display_primaries_x[3]; - uint16_t display_primaries_y[3]; - uint16_t white_point_x; - uint16_t white_point_y; - uint32_t max_display_mastering_luminance; - uint32_t min_display_mastering_luminance; -} H265RawSEIMasteringDisplayColourVolume; - -typedef struct H265RawSEIContentLightLevelInfo { - uint16_t max_content_light_level; - uint16_t max_pic_average_light_level; -} H265RawSEIContentLightLevelInfo; - -typedef struct H265RawSEIAlternativeTransferCharacteristics { - uint8_t preferred_transfer_characteristics; -} H265RawSEIAlternativeTransferCharacteristics; - typedef struct H265RawSEIAlphaChannelInfo { uint8_t alpha_channel_cancel_flag; uint8_t alpha_channel_use_idc; @@ -690,38 +649,9 @@ uint8_t alpha_channel_clip_type_flag; } H265RawSEIAlphaChannelInfo; -typedef struct H265RawSEIPayload { - uint32_t payload_type; - uint32_t payload_size; - union { - H265RawSEIBufferingPeriod buffering_period; - H265RawSEIPicTiming pic_timing; - H265RawSEIPanScanRect pan_scan_rect; - H265RawSEIUserDataRegistered user_data_registered; - H265RawSEIUserDataUnregistered user_data_unregistered; - H265RawSEIRecoveryPoint recovery_point; - H265RawSEIDisplayOrientation display_orientation; - H265RawSEIActiveParameterSets active_parameter_sets; - H265RawSEIDecodedPictureHash decoded_picture_hash; - H265RawSEITimeCode time_code; - H265RawSEIMasteringDisplayColourVolume mastering_display; - H265RawSEIContentLightLevelInfo content_light_level; - H265RawSEIAlternativeTransferCharacteristics - alternative_transfer_characteristics; - H265RawSEIAlphaChannelInfo alpha_channel_info; - struct { - uint8_t *data; - size_t data_length; - AVBufferRef *data_ref; - } other; - } payload; -} H265RawSEIPayload; - typedef struct H265RawSEI { H265RawNALUnitHeader nal_unit_header; - - H265RawSEIPayload payload[H265_MAX_SEI_PAYLOADS]; - uint8_t payload_count; + SEIRawMessageList message_list; } H265RawSEI; typedef struct CodedBitstreamH265Context { diff -Nru ffmpeg-4.2.2/libavcodec/cbs_h265_syntax_template.c ffmpeg-4.4/libavcodec/cbs_h265_syntax_template.c --- ffmpeg-4.2.2/libavcodec/cbs_h265_syntax_template.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_h265_syntax_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -59,7 +59,7 @@ } static int FUNC(extension_data)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawPSExtensionData *current) + H265RawExtensionData *current) { int err; size_t k; @@ -80,7 +80,7 @@ } #else for (k = 0; k < current->bit_length; k++) - xu(1, extension_data, current->data[k / 8] >> (7 - k % 8), 0, 1, 0); + xu(1, extension_data, current->data[k / 8] >> (7 - k % 8) & 1, 0, 1, 0); #endif return 0; } @@ -522,7 +522,7 @@ infer(inter_ref_pic_set_prediction_flag, 0); if (current->inter_ref_pic_set_prediction_flag) { - unsigned int ref_rps_idx, num_delta_pocs; + unsigned int ref_rps_idx, num_delta_pocs, num_ref_pics; const H265RawSTRefPicSet *ref; int delta_rps, d_poc; int ref_delta_poc_s0[HEVC_MAX_REFS], ref_delta_poc_s1[HEVC_MAX_REFS]; @@ -538,18 +538,28 @@ ref_rps_idx = st_rps_idx - (current->delta_idx_minus1 + 1); ref = &sps->st_ref_pic_set[ref_rps_idx]; num_delta_pocs = ref->num_negative_pics + ref->num_positive_pics; + av_assert0(num_delta_pocs < HEVC_MAX_DPB_SIZE); flag(delta_rps_sign); ue(abs_delta_rps_minus1, 0, INT16_MAX); delta_rps = (1 - 2 * current->delta_rps_sign) * (current->abs_delta_rps_minus1 + 1); + num_ref_pics = 0; for (j = 0; j <= num_delta_pocs; j++) { flags(used_by_curr_pic_flag[j], 1, j); if (!current->used_by_curr_pic_flag[j]) flags(use_delta_flag[j], 1, j); else infer(use_delta_flag[j], 1); + if (current->use_delta_flag[j]) + ++num_ref_pics; + } + if (num_ref_pics >= HEVC_MAX_DPB_SIZE) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid stream: " + "short-term ref pic set %d " + "contains too many pictures.\n", st_rps_idx); + return AVERROR_INVALIDDATA; } // Since the stored form of an RPS here is actually the delta-step @@ -734,6 +744,32 @@ return 0; } +static int FUNC(vui_parameters_default)(CodedBitstreamContext *ctx, + RWContext *rw, H265RawVUI *current, + H265RawSPS *sps) +{ + infer(aspect_ratio_idc, 0); + + infer(video_format, 5); + infer(video_full_range_flag, 0); + infer(colour_primaries, 2); + infer(transfer_characteristics, 2); + infer(matrix_coefficients, 2); + + infer(chroma_sample_loc_type_top_field, 0); + infer(chroma_sample_loc_type_bottom_field, 0); + + infer(tiles_fixed_structure_flag, 0); + infer(motion_vectors_over_pic_boundaries_flag, 1); + infer(min_spatial_segmentation_idc, 0); + infer(max_bytes_per_pic_denom, 2); + infer(max_bits_per_min_cu_denom, 1); + infer(log2_max_mv_length_horizontal, 15); + infer(log2_max_mv_length_vertical, 15); + + return 0; +} + static int FUNC(sps)(CodedBitstreamContext *ctx, RWContext *rw, H265RawSPS *current) { @@ -898,6 +934,8 @@ flag(vui_parameters_present_flag); if (current->vui_parameters_present_flag) CHECK(FUNC(vui_parameters)(ctx, rw, ¤t->vui, current)); + else + CHECK(FUNC(vui_parameters_default)(ctx, rw, ¤t->vui, current)); flag(sps_extension_present_flag); if (current->sps_extension_present_flag) { @@ -1275,7 +1313,7 @@ flag(first_slice_segment_in_pic_flag); if (current->nal_unit_header.nal_unit_type >= HEVC_NAL_BLA_W_LP && - current->nal_unit_header.nal_unit_type <= HEVC_NAL_IRAP_VCL23) + current->nal_unit_header.nal_unit_type <= HEVC_NAL_RSV_IRAP_VCL23) flag(no_output_of_prior_pics_flag); ue(slice_pic_parameter_set_id, 0, 63); @@ -1331,6 +1369,7 @@ if (current->nal_unit_header.nal_unit_type != HEVC_NAL_IDR_W_RADL && current->nal_unit_header.nal_unit_type != HEVC_NAL_IDR_N_LP) { const H265RawSTRefPicSet *rps; + int dpb_slots_remaining; ub(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, slice_pic_order_cnt_lsb); @@ -1349,6 +1388,22 @@ rps = &sps->st_ref_pic_set[0]; } + dpb_slots_remaining = HEVC_MAX_DPB_SIZE - 1 - + rps->num_negative_pics - rps->num_positive_pics; + if (pps->pps_curr_pic_ref_enabled_flag && + (sps->sample_adaptive_offset_enabled_flag || + !pps->pps_deblocking_filter_disabled_flag || + pps->deblocking_filter_override_enabled_flag)) { + // This picture will occupy two DPB slots. + if (dpb_slots_remaining == 0) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid stream: " + "short-term ref pic set contains too many pictures " + "to use with current picture reference enabled.\n"); + return AVERROR_INVALIDDATA; + } + --dpb_slots_remaining; + } + num_pic_total_curr = 0; for (i = 0; i < rps->num_negative_pics; i++) if (rps->used_by_curr_pic_s0_flag[i]) @@ -1361,13 +1416,15 @@ unsigned int idx_size; if (sps->num_long_term_ref_pics_sps > 0) { - ue(num_long_term_sps, 0, sps->num_long_term_ref_pics_sps); + ue(num_long_term_sps, 0, FFMIN(sps->num_long_term_ref_pics_sps, + dpb_slots_remaining)); idx_size = av_log2(sps->num_long_term_ref_pics_sps - 1) + 1; + dpb_slots_remaining -= current->num_long_term_sps; } else { infer(num_long_term_sps, 0); idx_size = 0; } - ue(num_long_term_pics, 0, HEVC_MAX_LONG_TERM_REF_PICS); + ue(num_long_term_pics, 0, dpb_slots_remaining); for (i = 0; i < current->num_long_term_sps + current->num_long_term_pics; i++) { @@ -1558,9 +1615,9 @@ return 0; } -static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIBufferingPeriod *current, - uint32_t *payload_size) +static int FUNC(sei_buffering_period) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIBufferingPeriod *current, SEIMessageState *sei) { CodedBitstreamH265Context *h265 = ctx->priv_data; const H265RawSPS *sps; @@ -1568,7 +1625,7 @@ int err, i, length; #ifdef READ - int start_pos, end_pos, bits_left; + int start_pos, end_pos; start_pos = get_bits_count(rw); #endif @@ -1647,25 +1704,30 @@ } #ifdef READ - // payload_extension_present() - true if we are before the last 1-bit - // in the payload structure, which must be in the last byte. end_pos = get_bits_count(rw); - bits_left = *payload_size * 8 - (end_pos - start_pos); - if (bits_left > 0 && - (bits_left > 7 || ff_ctz(show_bits(rw, bits_left)) < bits_left - 1)) + if (cbs_h265_payload_extension_present(rw, sei->payload_size, + end_pos - start_pos)) flag(use_alt_cpb_params_flag); else infer(use_alt_cpb_params_flag, 0); #else - if (current->use_alt_cpb_params_flag) + // If unknown extension data exists, then use_alt_cpb_params_flag is + // coded in the bitstream and must be written even if it's 0. + if (current->use_alt_cpb_params_flag || sei->extension_present) { flag(use_alt_cpb_params_flag); + // Ensure this bit is not the last in the payload by making the + // more_data_in_payload() check evaluate to true, so it may not + // be mistaken as something else by decoders. + sei->extension_present = 1; + } #endif return 0; } -static int FUNC(sei_pic_timing)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIPicTiming *current) +static int FUNC(sei_pic_timing) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIPicTiming *current, SEIMessageState *sei) { CodedBitstreamH265Context *h265 = ctx->priv_data; const H265RawSPS *sps; @@ -1739,8 +1801,9 @@ return 0; } -static int FUNC(sei_pan_scan_rect)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIPanScanRect *current) +static int FUNC(sei_pan_scan_rect) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIPanScanRect *current, SEIMessageState *sei) { int err, i; @@ -1765,72 +1828,9 @@ return 0; } -static int FUNC(sei_user_data_registered)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIUserDataRegistered *current, - uint32_t *payload_size) -{ - int err, i, j; - - HEADER("User Data Registered ITU-T T.35"); - - u(8, itu_t_t35_country_code, 0x00, 0xff); - if (current->itu_t_t35_country_code != 0xff) - i = 1; - else { - u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff); - i = 2; - } - -#ifdef READ - if (*payload_size < i) { - av_log(ctx->log_ctx, AV_LOG_ERROR, - "Invalid SEI user data registered payload.\n"); - return AVERROR_INVALIDDATA; - } - current->data_length = *payload_size - i; -#else - *payload_size = i + current->data_length; -#endif - - allocate(current->data, current->data_length); - for (j = 0; j < current->data_length; j++) - xu(8, itu_t_t35_payload_byte[i], current->data[j], 0x00, 0xff, 1, i + j); - - return 0; -} - -static int FUNC(sei_user_data_unregistered)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIUserDataUnregistered *current, - uint32_t *payload_size) -{ - int err, i; - - HEADER("User Data Unregistered"); - -#ifdef READ - if (*payload_size < 16) { - av_log(ctx->log_ctx, AV_LOG_ERROR, - "Invalid SEI user data unregistered payload.\n"); - return AVERROR_INVALIDDATA; - } - current->data_length = *payload_size - 16; -#else - *payload_size = 16 + current->data_length; -#endif - - for (i = 0; i < 16; i++) - us(8, uuid_iso_iec_11578[i], 0x00, 0xff, 1, i); - - allocate(current->data, current->data_length); - - for (i = 0; i < current->data_length; i++) - xu(8, user_data_payload_byte[i], current->data[i], 0x00, 0xff, 1, i); - - return 0; -} - -static int FUNC(sei_recovery_point)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIRecoveryPoint *current) +static int FUNC(sei_recovery_point) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIRecoveryPoint *current, SEIMessageState *sei) { int err; @@ -1844,8 +1844,9 @@ return 0; } -static int FUNC(sei_display_orientation)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIDisplayOrientation *current) +static int FUNC(sei_display_orientation) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIDisplayOrientation *current, SEIMessageState *sei) { int err; @@ -1862,8 +1863,9 @@ return 0; } -static int FUNC(sei_active_parameter_sets)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIActiveParameterSets *current) +static int FUNC(sei_active_parameter_sets) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIActiveParameterSets *current, SEIMessageState *sei) { CodedBitstreamH265Context *h265 = ctx->priv_data; const H265RawVPS *vps; @@ -1898,8 +1900,9 @@ return 0; } -static int FUNC(sei_decoded_picture_hash)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIDecodedPictureHash *current) +static int FUNC(sei_decoded_picture_hash) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIDecodedPictureHash *current, SEIMessageState *sei) { CodedBitstreamH265Context *h265 = ctx->priv_data; const H265RawSPS *sps = h265->active_sps; @@ -1929,8 +1932,9 @@ return 0; } -static int FUNC(sei_time_code)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEITimeCode *current) +static int FUNC(sei_time_code) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEITimeCode *current, SEIMessageState *sei) { int err, i; @@ -1979,58 +1983,9 @@ return 0; } -static int FUNC(sei_mastering_display)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIMasteringDisplayColourVolume *current) -{ - int err, c; - - HEADER("Mastering Display Colour Volume"); - - for (c = 0; c < 3; c++) { - us(16, display_primaries_x[c], 0, 50000, 1, c); - us(16, display_primaries_y[c], 0, 50000, 1, c); - } - - u(16, white_point_x, 0, 50000); - u(16, white_point_y, 0, 50000); - - u(32, max_display_mastering_luminance, - 1, MAX_UINT_BITS(32)); - u(32, min_display_mastering_luminance, - 0, current->max_display_mastering_luminance - 1); - - return 0; -} - -static int FUNC(sei_content_light_level)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIContentLightLevelInfo *current) -{ - int err; - - HEADER("Content Light Level"); - - ub(16, max_content_light_level); - ub(16, max_pic_average_light_level); - - return 0; -} - -static int FUNC(sei_alternative_transfer_characteristics)(CodedBitstreamContext *ctx, - RWContext *rw, - H265RawSEIAlternativeTransferCharacteristics *current) -{ - int err; - - HEADER("Alternative Transfer Characteristics"); - - ub(8, preferred_transfer_characteristics); - - return 0; -} - -static int FUNC(sei_alpha_channel_info)(CodedBitstreamContext *ctx, - RWContext *rw, - H265RawSEIAlphaChannelInfo *current) +static int FUNC(sei_alpha_channel_info) + (CodedBitstreamContext *ctx, RWContext *rw, + H265RawSEIAlphaChannelInfo *current, SEIMessageState *sei) { int err, length; @@ -2056,101 +2011,10 @@ return 0; } -static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw, - H265RawSEIPayload *current, int prefix) -{ - int err, i; - int start_position, end_position; - -#ifdef READ - start_position = get_bits_count(rw); -#else - start_position = put_bits_count(rw); -#endif - - switch (current->payload_type) { -#define SEI_TYPE_CHECK_VALID(name, prefix_valid, suffix_valid) do { \ - if (prefix && !prefix_valid) { \ - av_log(ctx->log_ctx, AV_LOG_ERROR, "SEI type %s invalid " \ - "as prefix SEI!\n", #name); \ - return AVERROR_INVALIDDATA; \ - } \ - if (!prefix && !suffix_valid) { \ - av_log(ctx->log_ctx, AV_LOG_ERROR, "SEI type %s invalid " \ - "as suffix SEI!\n", #name); \ - return AVERROR_INVALIDDATA; \ - } \ - } while (0) -#define SEI_TYPE_N(type, prefix_valid, suffix_valid, name) \ - case HEVC_SEI_TYPE_ ## type: \ - SEI_TYPE_CHECK_VALID(name, prefix_valid, suffix_valid); \ - CHECK(FUNC(sei_ ## name)(ctx, rw, ¤t->payload.name)); \ - break -#define SEI_TYPE_S(type, prefix_valid, suffix_valid, name) \ - case HEVC_SEI_TYPE_ ## type: \ - SEI_TYPE_CHECK_VALID(name, prefix_valid, suffix_valid); \ - CHECK(FUNC(sei_ ## name)(ctx, rw, ¤t->payload.name, \ - ¤t->payload_size)); \ - break - - SEI_TYPE_S(BUFFERING_PERIOD, 1, 0, buffering_period); - SEI_TYPE_N(PICTURE_TIMING, 1, 0, pic_timing); - SEI_TYPE_N(PAN_SCAN_RECT, 1, 0, pan_scan_rect); - SEI_TYPE_S(USER_DATA_REGISTERED_ITU_T_T35, - 1, 1, user_data_registered); - SEI_TYPE_S(USER_DATA_UNREGISTERED, 1, 1, user_data_unregistered); - SEI_TYPE_N(RECOVERY_POINT, 1, 0, recovery_point); - SEI_TYPE_N(DISPLAY_ORIENTATION, 1, 0, display_orientation); - SEI_TYPE_N(ACTIVE_PARAMETER_SETS, 1, 0, active_parameter_sets); - SEI_TYPE_N(DECODED_PICTURE_HASH, 0, 1, decoded_picture_hash); - SEI_TYPE_N(TIME_CODE, 1, 0, time_code); - SEI_TYPE_N(MASTERING_DISPLAY_INFO, 1, 0, mastering_display); - SEI_TYPE_N(CONTENT_LIGHT_LEVEL_INFO, 1, 0, content_light_level); - SEI_TYPE_N(ALTERNATIVE_TRANSFER_CHARACTERISTICS, - 1, 0, alternative_transfer_characteristics); - SEI_TYPE_N(ALPHA_CHANNEL_INFO, 1, 0, alpha_channel_info); - -#undef SEI_TYPE - default: - { -#ifdef READ - current->payload.other.data_length = current->payload_size; -#endif - allocate(current->payload.other.data, current->payload.other.data_length); - - for (i = 0; i < current->payload_size; i++) - xu(8, payload_byte[i], current->payload.other.data[i], 0, 255, - 1, i); - } - } - - if (byte_alignment(rw)) { - fixed(1, bit_equal_to_one, 1); - while (byte_alignment(rw)) - fixed(1, bit_equal_to_zero, 0); - } - -#ifdef READ - end_position = get_bits_count(rw); - if (end_position < start_position + 8 * current->payload_size) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Incorrect SEI payload length: " - "header %"PRIu32" bits, actually %d bits.\n", - 8 * current->payload_size, - end_position - start_position); - return AVERROR_INVALIDDATA; - } -#else - end_position = put_bits_count(rw); - current->payload_size = (end_position - start_position) >> 3; -#endif - - return 0; -} - static int FUNC(sei)(CodedBitstreamContext *ctx, RWContext *rw, H265RawSEI *current, int prefix) { - int err, k; + int err; if (prefix) HEADER("Prefix Supplemental Enhancement Information"); @@ -2161,72 +2025,7 @@ prefix ? HEVC_NAL_SEI_PREFIX : HEVC_NAL_SEI_SUFFIX)); -#ifdef READ - for (k = 0; k < H265_MAX_SEI_PAYLOADS; k++) { - uint32_t payload_type = 0; - uint32_t payload_size = 0; - uint32_t tmp; - - while (show_bits(rw, 8) == 0xff) { - fixed(8, ff_byte, 0xff); - payload_type += 255; - } - xu(8, last_payload_type_byte, tmp, 0, 254, 0); - payload_type += tmp; - - while (show_bits(rw, 8) == 0xff) { - fixed(8, ff_byte, 0xff); - payload_size += 255; - } - xu(8, last_payload_size_byte, tmp, 0, 254, 0); - payload_size += tmp; - - current->payload[k].payload_type = payload_type; - current->payload[k].payload_size = payload_size; - - current->payload_count++; - CHECK(FUNC(sei_payload)(ctx, rw, ¤t->payload[k], prefix)); - - if (!cbs_h2645_read_more_rbsp_data(rw)) - break; - } - if (k >= H265_MAX_SEI_PAYLOADS) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many payloads in " - "SEI message: found %d.\n", k); - return AVERROR_INVALIDDATA; - } -#else - for (k = 0; k < current->payload_count; k++) { - PutBitContext start_state; - uint32_t tmp; - int need_size, i; - - // Somewhat clumsy: we write the payload twice when - // we don't know the size in advance. This will mess - // with trace output, but is otherwise harmless. - start_state = *rw; - need_size = !current->payload[k].payload_size; - for (i = 0; i < 1 + need_size; i++) { - *rw = start_state; - - tmp = current->payload[k].payload_type; - while (tmp >= 255) { - fixed(8, ff_byte, 0xff); - tmp -= 255; - } - xu(8, last_payload_type_byte, tmp, 0, 254, 0); - - tmp = current->payload[k].payload_size; - while (tmp >= 255) { - fixed(8, ff_byte, 0xff); - tmp -= 255; - } - xu(8, last_payload_size_byte, tmp, 0, 254, 0); - - CHECK(FUNC(sei_payload)(ctx, rw, ¤t->payload[k], prefix)); - } - } -#endif + CHECK(FUNC_SEI(message_list)(ctx, rw, ¤t->message_list, prefix)); CHECK(FUNC(rbsp_trailing_bits)(ctx, rw)); diff -Nru ffmpeg-4.2.2/libavcodec/cbs_internal.h ffmpeg-4.4/libavcodec/cbs_internal.h --- ffmpeg-4.2.2/libavcodec/cbs_internal.h 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_internal.h 2021-04-08 21:28:39.000000000 +0000 @@ -25,11 +25,79 @@ #include "put_bits.h" +enum CBSContentType { + // Unit content is a simple structure. + CBS_CONTENT_TYPE_POD, + // Unit content contains some references to other structures, but all + // managed via buffer reference counting. The descriptor defines the + // structure offsets of every buffer reference. + CBS_CONTENT_TYPE_INTERNAL_REFS, + // Unit content is something more complex. The descriptor defines + // special functions to manage the content. + CBS_CONTENT_TYPE_COMPLEX, +}; + +enum { + // Maximum number of unit types described by the same unit type + // descriptor. + CBS_MAX_UNIT_TYPES = 3, + // Maximum number of reference buffer offsets in any one unit. + CBS_MAX_REF_OFFSETS = 2, + // Special value used in a unit type descriptor to indicate that it + // applies to a large range of types rather than a set of discrete + // values. + CBS_UNIT_TYPE_RANGE = -1, +}; + +typedef const struct CodedBitstreamUnitTypeDescriptor { + // Number of entries in the unit_types array, or the special value + // CBS_UNIT_TYPE_RANGE to indicate that the range fields should be + // used instead. + int nb_unit_types; + + // Array of unit types that this entry describes. + const CodedBitstreamUnitType unit_types[CBS_MAX_UNIT_TYPES]; + + // Start and end of unit type range, used if nb_unit_types is + // CBS_UNIT_TYPE_RANGE. + const CodedBitstreamUnitType unit_type_range_start; + const CodedBitstreamUnitType unit_type_range_end; + + // The type of content described. + enum CBSContentType content_type; + // The size of the structure which should be allocated to contain + // the decomposed content of this type of unit. + size_t content_size; + + // Number of entries in the ref_offsets array. Only used if the + // content_type is CBS_CONTENT_TYPE_INTERNAL_REFS. + int nb_ref_offsets; + // The structure must contain two adjacent elements: + // type *field; + // AVBufferRef *field_ref; + // where field points to something in the buffer referred to by + // field_ref. This offset is then set to offsetof(struct, field). + size_t ref_offsets[CBS_MAX_REF_OFFSETS]; + + void (*content_free)(void *opaque, uint8_t *data); + int (*content_clone)(AVBufferRef **ref, CodedBitstreamUnit *unit); +} CodedBitstreamUnitTypeDescriptor; + typedef struct CodedBitstreamType { enum AVCodecID codec_id; + // A class for the private data, used to declare private AVOptions. + // This field is NULL for types that do not declare any options. + // If this field is non-NULL, the first member of the filter private data + // must be a pointer to AVClass. + const AVClass *priv_class; + size_t priv_data_size; + // List of unit type descriptors for this codec. + // Terminated by a descriptor with nb_unit_types equal to zero. + const CodedBitstreamUnitTypeDescriptor *unit_types; + // Split frag->data into coded bitstream units, creating the // frag->units array. Fill data but not content on each unit. // The header argument should be set if the fragment came from @@ -55,6 +123,9 @@ int (*assemble_fragment)(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag); + // Reset the codec internal state. + void (*flush)(CodedBitstreamContext *ctx); + // Free the codec internal state. void (*close)(CodedBitstreamContext *ctx); } CodedBitstreamType; @@ -106,6 +177,30 @@ #define MIN_INT_BITS(length) (-(INT64_C(1) << ((length) - 1))) +#define CBS_UNIT_TYPE_POD(type, structure) { \ + .nb_unit_types = 1, \ + .unit_types = { type }, \ + .content_type = CBS_CONTENT_TYPE_POD, \ + .content_size = sizeof(structure), \ + } +#define CBS_UNIT_TYPE_INTERNAL_REF(type, structure, ref_field) { \ + .nb_unit_types = 1, \ + .unit_types = { type }, \ + .content_type = CBS_CONTENT_TYPE_INTERNAL_REFS, \ + .content_size = sizeof(structure), \ + .nb_ref_offsets = 1, \ + .ref_offsets = { offsetof(structure, ref_field) }, \ + } +#define CBS_UNIT_TYPE_COMPLEX(type, structure, free_func) { \ + .nb_unit_types = 1, \ + .unit_types = { type }, \ + .content_type = CBS_CONTENT_TYPE_COMPLEX, \ + .content_size = sizeof(structure), \ + .content_free = free_func, \ + } +#define CBS_UNIT_TYPE_END_OF_LIST { .nb_unit_types = 0 } + + extern const CodedBitstreamType ff_cbs_type_av1; extern const CodedBitstreamType ff_cbs_type_h264; extern const CodedBitstreamType ff_cbs_type_h265; diff -Nru ffmpeg-4.2.2/libavcodec/cbs_jpeg.c ffmpeg-4.4/libavcodec/cbs_jpeg.c --- ffmpeg-4.2.2/libavcodec/cbs_jpeg.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_jpeg.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,7 +34,7 @@ #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL) #define u(width, name, range_min, range_max) \ - xu(width, name, range_min, range_max, 0) + xu(width, name, range_min, range_max, 0, ) #define us(width, name, sub, range_min, range_max) \ xu(width, name, range_min, range_max, 1, sub) @@ -82,21 +82,21 @@ #undef xu -static void cbs_jpeg_free_application_data(void *unit, uint8_t *content) +static void cbs_jpeg_free_application_data(void *opaque, uint8_t *content) { JPEGRawApplicationData *ad = (JPEGRawApplicationData*)content; av_buffer_unref(&ad->Ap_ref); av_freep(&content); } -static void cbs_jpeg_free_comment(void *unit, uint8_t *content) +static void cbs_jpeg_free_comment(void *opaque, uint8_t *content) { JPEGRawComment *comment = (JPEGRawComment*)content; av_buffer_unref(&comment->Cm_ref); av_freep(&content); } -static void cbs_jpeg_free_scan(void *unit, uint8_t *content) +static void cbs_jpeg_free_scan(void *opaque, uint8_t *content) { JPEGRawScan *scan = (JPEGRawScan*)content; av_buffer_unref(&scan->data_ref); @@ -148,15 +148,15 @@ if (marker == JPEG_MARKER_EOI) { break; } else if (marker == JPEG_MARKER_SOS) { + next_marker = -1; + end = start; for (i = start; i + 1 < frag->data_size; i++) { if (frag->data[i] != 0xff) continue; end = i; for (++i; i + 1 < frag->data_size && frag->data[i] == 0xff; i++); - if (i + 1 >= frag->data_size) { - next_marker = -1; - } else { + if (i + 1 < frag->data_size) { if (frag->data[i] == 0x00) continue; next_marker = frag->data[i]; @@ -197,6 +197,9 @@ if (marker == JPEG_MARKER_SOS) { length = AV_RB16(frag->data + start); + if (length > end - start) + return AVERROR_INVALIDDATA; + data_ref = NULL; data = av_malloc(end - start + AV_INPUT_BUFFER_PADDING_SIZE); @@ -223,13 +226,10 @@ data_ref = frag->data_ref; } - err = ff_cbs_insert_unit_data(ctx, frag, unit, marker, + err = ff_cbs_insert_unit_data(frag, unit, marker, data, data_size, data_ref); - if (err < 0) { - if (!data_ref) - av_freep(&data); + if (err < 0) return err; - } if (next_marker == -1) break; @@ -252,7 +252,7 @@ if (unit->type >= JPEG_MARKER_SOF0 && unit->type <= JPEG_MARKER_SOF3) { - err = ff_cbs_alloc_unit_content(ctx, unit, + err = ff_cbs_alloc_unit_content(unit, sizeof(JPEGRawFrameHeader), NULL); if (err < 0) @@ -264,7 +264,7 @@ } else if (unit->type >= JPEG_MARKER_APPN && unit->type <= JPEG_MARKER_APPN + 15) { - err = ff_cbs_alloc_unit_content(ctx, unit, + err = ff_cbs_alloc_unit_content(unit, sizeof(JPEGRawApplicationData), &cbs_jpeg_free_application_data); if (err < 0) @@ -278,7 +278,7 @@ JPEGRawScan *scan; int pos; - err = ff_cbs_alloc_unit_content(ctx, unit, + err = ff_cbs_alloc_unit_content(unit, sizeof(JPEGRawScan), &cbs_jpeg_free_scan); if (err < 0) @@ -304,7 +304,7 @@ #define SEGMENT(marker, type, func, free) \ case JPEG_MARKER_ ## marker: \ { \ - err = ff_cbs_alloc_unit_content(ctx, unit, \ + err = ff_cbs_alloc_unit_content(unit, \ sizeof(type), free); \ if (err < 0) \ return err; \ @@ -330,7 +330,7 @@ PutBitContext *pbc) { JPEGRawScan *scan = unit->content; - int i, err; + int err; err = cbs_jpeg_write_scan_header(ctx, pbc, &scan->header); if (err < 0) @@ -340,8 +340,12 @@ if (scan->data_size * 8 > put_bits_left(pbc)) return AVERROR(ENOSPC); - for (i = 0; i < scan->data_size; i++) - put_bits(pbc, 8, scan->data[i]); + av_assert0(put_bits_count(pbc) % 8 == 0); + + flush_put_bits(pbc); + + memcpy(put_bits_ptr(pbc), scan->data, scan->data_size); + skip_put_bytes(pbc, scan->data_size); } return 0; diff -Nru ffmpeg-4.2.2/libavcodec/cbs_jpeg.h ffmpeg-4.4/libavcodec/cbs_jpeg.h --- ffmpeg-4.2.2/libavcodec/cbs_jpeg.h 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_jpeg.h 2021-04-08 21:28:39.000000000 +0000 @@ -80,8 +80,8 @@ typedef struct JPEGRawScan { JPEGRawScanHeader header; uint8_t *data; - size_t data_size; AVBufferRef *data_ref; + size_t data_size; } JPEGRawScan; typedef struct JPEGRawQuantisationTable { diff -Nru ffmpeg-4.2.2/libavcodec/cbs_jpeg_syntax_template.c ffmpeg-4.4/libavcodec/cbs_jpeg_syntax_template.c --- ffmpeg-4.2.2/libavcodec/cbs_jpeg_syntax_template.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_jpeg_syntax_template.c 2020-07-09 09:17:46.000000000 +0000 @@ -89,6 +89,8 @@ ij = 0; for (i = 0; i < 16; i++) { for (j = 0; j < current->L[i]; j++) { + if (ij >= 224) + return AVERROR_INVALIDDATA; us(8, V[ij], ij, 0, 255); ++ij; } @@ -108,6 +110,9 @@ n = 2; for (i = 0; n < current->Lh; i++) { + if (i >= 8) + return AVERROR_INVALIDDATA; + CHECK(FUNC(huffman_table)(ctx, rw, ¤t->table[i])); ++n; diff -Nru ffmpeg-4.2.2/libavcodec/cbs_mpeg2.c ffmpeg-4.4/libavcodec/cbs_mpeg2.c --- ffmpeg-4.2.2/libavcodec/cbs_mpeg2.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_mpeg2.c 2021-04-08 21:28:39.000000000 +0000 @@ -41,9 +41,9 @@ #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL) #define ui(width, name) \ - xui(width, name, current->name, 0, MAX_UINT_BITS(width), 0) + xui(width, name, current->name, 0, MAX_UINT_BITS(width), 0, ) #define uir(width, name) \ - xui(width, name, current->name, 1, MAX_UINT_BITS(width), 0) + xui(width, name, current->name, 1, MAX_UINT_BITS(width), 0, ) #define uis(width, name, subs, ...) \ xui(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__) #define uirs(width, name, subs, ...) \ @@ -57,7 +57,7 @@ bit("marker_bit", 1) #define bit(string, value) do { \ av_unused uint32_t bit = value; \ - xuia(1, string, bit, value, value, 0); \ + xuia(1, string, bit, value, value, 0, ); \ } while (0) @@ -140,28 +140,6 @@ #undef infer -static void cbs_mpeg2_free_picture_header(void *unit, uint8_t *content) -{ - MPEG2RawPictureHeader *picture = (MPEG2RawPictureHeader*)content; - av_buffer_unref(&picture->extra_information_picture.extra_information_ref); - av_freep(&content); -} - -static void cbs_mpeg2_free_user_data(void *unit, uint8_t *content) -{ - MPEG2RawUserData *user = (MPEG2RawUserData*)content; - av_buffer_unref(&user->user_data_ref); - av_freep(&content); -} - -static void cbs_mpeg2_free_slice(void *unit, uint8_t *content) -{ - MPEG2RawSlice *slice = (MPEG2RawSlice*)content; - av_buffer_unref(&slice->header.extra_information_slice.extra_information_ref); - av_buffer_unref(&slice->data_ref); - av_freep(&content); -} - static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, int header) @@ -207,7 +185,7 @@ final = 1; } - err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type, (uint8_t*)start, + err = ff_cbs_insert_unit_data(frag, i, unit_type, (uint8_t*)start, unit_size, frag->data_ref); if (err < 0) return err; @@ -231,20 +209,21 @@ if (err < 0) return err; + err = ff_cbs_alloc_unit_content2(ctx, unit); + if (err < 0) + return err; + if (MPEG2_START_IS_SLICE(unit->type)) { - MPEG2RawSlice *slice; + MPEG2RawSlice *slice = unit->content; int pos, len; - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*slice), - &cbs_mpeg2_free_slice); - if (err < 0) - return err; - slice = unit->content; - err = cbs_mpeg2_read_slice_header(ctx, &gbc, &slice->header); if (err < 0) return err; + if (!get_bits_left(&gbc)) + return AVERROR_INVALIDDATA; + pos = get_bits_count(&gbc); len = unit->data_size; @@ -261,12 +240,7 @@ #define START(start_code, type, read_func, free_func) \ case start_code: \ { \ - type *header; \ - err = ff_cbs_alloc_unit_content(ctx, unit, \ - sizeof(*header), free_func); \ - if (err < 0) \ - return err; \ - header = unit->content; \ + type *header = unit->content; \ err = cbs_mpeg2_read_ ## read_func(ctx, &gbc, header); \ if (err < 0) \ return err; \ @@ -417,11 +391,40 @@ return 0; } +static const CodedBitstreamUnitTypeDescriptor cbs_mpeg2_unit_types[] = { + CBS_UNIT_TYPE_INTERNAL_REF(MPEG2_START_PICTURE, MPEG2RawPictureHeader, + extra_information_picture.extra_information), + + { + .nb_unit_types = CBS_UNIT_TYPE_RANGE, + .unit_type_range_start = 0x01, + .unit_type_range_end = 0xaf, + + .content_type = CBS_CONTENT_TYPE_INTERNAL_REFS, + .content_size = sizeof(MPEG2RawSlice), + .nb_ref_offsets = 2, + .ref_offsets = { offsetof(MPEG2RawSlice, header.extra_information_slice.extra_information), + offsetof(MPEG2RawSlice, data) }, + }, + + CBS_UNIT_TYPE_INTERNAL_REF(MPEG2_START_USER_DATA, MPEG2RawUserData, + user_data), + + CBS_UNIT_TYPE_POD(MPEG2_START_SEQUENCE_HEADER, MPEG2RawSequenceHeader), + CBS_UNIT_TYPE_POD(MPEG2_START_EXTENSION, MPEG2RawExtensionData), + CBS_UNIT_TYPE_POD(MPEG2_START_SEQUENCE_END, MPEG2RawSequenceEnd), + CBS_UNIT_TYPE_POD(MPEG2_START_GROUP, MPEG2RawGroupOfPicturesHeader), + + CBS_UNIT_TYPE_END_OF_LIST +}; + const CodedBitstreamType ff_cbs_type_mpeg2 = { .codec_id = AV_CODEC_ID_MPEG2VIDEO, .priv_data_size = sizeof(CodedBitstreamMPEG2Context), + .unit_types = cbs_mpeg2_unit_types, + .split_fragment = &cbs_mpeg2_split_fragment, .read_unit = &cbs_mpeg2_read_unit, .write_unit = &cbs_mpeg2_write_unit, diff -Nru ffmpeg-4.2.2/libavcodec/cbs_mpeg2.h ffmpeg-4.4/libavcodec/cbs_mpeg2.h --- ffmpeg-4.2.2/libavcodec/cbs_mpeg2.h 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_mpeg2.h 2021-04-08 21:28:39.000000000 +0000 @@ -76,9 +76,9 @@ typedef struct MPEG2RawUserData { uint8_t user_data_start_code; - uint8_t *user_data; - size_t user_data_length; + uint8_t *user_data; AVBufferRef *user_data_ref; + size_t user_data_length; } MPEG2RawUserData; typedef struct MPEG2RawSequenceExtension { @@ -206,10 +206,10 @@ typedef struct MPEG2RawSlice { MPEG2RawSliceHeader header; - uint8_t *data; - size_t data_size; - int data_bit_start; + uint8_t *data; AVBufferRef *data_ref; + size_t data_size; + int data_bit_start; } MPEG2RawSlice; typedef struct MPEG2RawSequenceEnd { diff -Nru ffmpeg-4.2.2/libavcodec/cbs_sei.c ffmpeg-4.4/libavcodec/cbs_sei.c --- ffmpeg-4.2.2/libavcodec/cbs_sei.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_sei.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,369 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "cbs.h" +#include "cbs_internal.h" +#include "cbs_h264.h" +#include "cbs_h265.h" +#include "cbs_sei.h" + +static void cbs_free_user_data_registered(void *opaque, uint8_t *data) +{ + SEIRawUserDataRegistered *udr = (SEIRawUserDataRegistered*)data; + av_buffer_unref(&udr->data_ref); + av_free(udr); +} + +static void cbs_free_user_data_unregistered(void *opaque, uint8_t *data) +{ + SEIRawUserDataUnregistered *udu = (SEIRawUserDataUnregistered*)data; + av_buffer_unref(&udu->data_ref); + av_free(udu); +} + +int ff_cbs_sei_alloc_message_payload(SEIRawMessage *message, + const SEIMessageTypeDescriptor *desc) +{ + void (*free_func)(void*, uint8_t*); + + av_assert0(message->payload == NULL && + message->payload_ref == NULL); + message->payload_type = desc->type; + + if (desc->type == SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35) + free_func = &cbs_free_user_data_registered; + else if (desc->type == SEI_TYPE_USER_DATA_UNREGISTERED) + free_func = &cbs_free_user_data_unregistered; + else + free_func = NULL; + + if (free_func) { + message->payload = av_mallocz(desc->size); + if (!message->payload) + return AVERROR(ENOMEM); + message->payload_ref = + av_buffer_create(message->payload, desc->size, + free_func, NULL, 0); + } else { + message->payload_ref = av_buffer_alloc(desc->size); + } + if (!message->payload_ref) { + av_freep(&message->payload); + return AVERROR(ENOMEM); + } + message->payload = message->payload_ref->data; + + return 0; +} + +int ff_cbs_sei_list_add(SEIRawMessageList *list) +{ + void *ptr; + int old_count = list->nb_messages_allocated; + + av_assert0(list->nb_messages <= old_count); + if (list->nb_messages + 1 > old_count) { + int new_count = 2 * old_count + 1; + + ptr = av_realloc_array(list->messages, + new_count, sizeof(*list->messages)); + if (!ptr) + return AVERROR(ENOMEM); + + list->messages = ptr; + list->nb_messages_allocated = new_count; + + // Zero the newly-added entries. + memset(list->messages + old_count, 0, + (new_count - old_count) * sizeof(*list->messages)); + } + ++list->nb_messages; + return 0; +} + +void ff_cbs_sei_free_message_list(SEIRawMessageList *list) +{ + for (int i = 0; i < list->nb_messages; i++) { + SEIRawMessage *message = &list->messages[i]; + av_buffer_unref(&message->payload_ref); + av_buffer_unref(&message->extension_data_ref); + } + av_free(list->messages); +} + +static int cbs_sei_get_unit(CodedBitstreamContext *ctx, + CodedBitstreamFragment *au, + int prefix, + CodedBitstreamUnit **sei_unit) +{ + CodedBitstreamUnit *unit; + int sei_type, highest_vcl_type, err, i, position; + + switch (ctx->codec->codec_id) { + case AV_CODEC_ID_H264: + // (We can ignore auxiliary slices because we only have prefix + // SEI in H.264 and an auxiliary picture must always follow a + // primary picture.) + highest_vcl_type = H264_NAL_IDR_SLICE; + if (prefix) + sei_type = H264_NAL_SEI; + else + return AVERROR(EINVAL); + break; + case AV_CODEC_ID_H265: + highest_vcl_type = HEVC_NAL_RSV_VCL31; + if (prefix) + sei_type = HEVC_NAL_SEI_PREFIX; + else + sei_type = HEVC_NAL_SEI_SUFFIX; + break; + default: + return AVERROR(EINVAL); + } + + // Find an existing SEI NAL unit of the right type. + unit = NULL; + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == sei_type) { + unit = &au->units[i]; + break; + } + } + + if (unit) { + *sei_unit = unit; + return 0; + } + + // Need to add a new SEI NAL unit ... + if (prefix) { + // ... before the first VCL NAL unit. + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type < highest_vcl_type) + break; + } + position = i; + } else { + // ... after the last VCL NAL unit. + for (i = au->nb_units - 1; i >= 0; i--) { + if (au->units[i].type < highest_vcl_type) + break; + } + if (i < 0) { + // No VCL units; just put it at the end. + position = au->nb_units; + } else { + position = i + 1; + } + } + + err = ff_cbs_insert_unit_content(au, position, sei_type, + NULL, NULL); + if (err < 0) + return err; + unit = &au->units[position]; + unit->type = sei_type; + + err = ff_cbs_alloc_unit_content2(ctx, unit); + if (err < 0) + return err; + + switch (ctx->codec->codec_id) { + case AV_CODEC_ID_H264: + { + H264RawSEI sei = { + .nal_unit_header = { + .nal_ref_idc = 0, + .nal_unit_type = sei_type, + }, + }; + memcpy(unit->content, &sei, sizeof(sei)); + } + break; + case AV_CODEC_ID_H265: + { + H265RawSEI sei = { + .nal_unit_header = { + .nal_unit_type = sei_type, + .nuh_layer_id = 0, + .nuh_temporal_id_plus1 = 1, + }, + }; + memcpy(unit->content, &sei, sizeof(sei)); + } + break; + default: + av_assert0(0); + } + + *sei_unit = unit; + return 0; +} + +static int cbs_sei_get_message_list(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit, + SEIRawMessageList **list) +{ + switch (ctx->codec->codec_id) { + case AV_CODEC_ID_H264: + { + H264RawSEI *sei = unit->content; + if (unit->type != H264_NAL_SEI) + return AVERROR(EINVAL); + *list = &sei->message_list; + } + break; + case AV_CODEC_ID_H265: + { + H265RawSEI *sei = unit->content; + if (unit->type != HEVC_NAL_SEI_PREFIX && + unit->type != HEVC_NAL_SEI_SUFFIX) + return AVERROR(EINVAL); + *list = &sei->message_list; + } + break; + default: + return AVERROR(EINVAL); + } + + return 0; +} + +int ff_cbs_sei_add_message(CodedBitstreamContext *ctx, + CodedBitstreamFragment *au, + int prefix, + uint32_t payload_type, + void *payload_data, + AVBufferRef *payload_buf) +{ + const SEIMessageTypeDescriptor *desc; + CodedBitstreamUnit *unit; + SEIRawMessageList *list; + SEIRawMessage *message; + AVBufferRef *payload_ref; + int err; + + desc = ff_cbs_sei_find_type(ctx, payload_type); + if (!desc) + return AVERROR(EINVAL); + + // Find an existing SEI unit or make a new one to add to. + err = cbs_sei_get_unit(ctx, au, prefix, &unit); + if (err < 0) + return err; + + // Find the message list inside the codec-dependent unit. + err = cbs_sei_get_message_list(ctx, unit, &list); + if (err < 0) + return err; + + // Add a new message to the message list. + err = ff_cbs_sei_list_add(list); + if (err < 0) + return err; + + if (payload_buf) { + payload_ref = av_buffer_ref(payload_buf); + if (!payload_ref) + return AVERROR(ENOMEM); + } else { + payload_ref = NULL; + } + + message = &list->messages[list->nb_messages - 1]; + + message->payload_type = payload_type; + message->payload = payload_data; + message->payload_ref = payload_ref; + + return 0; +} + +int ff_cbs_sei_find_message(CodedBitstreamContext *ctx, + CodedBitstreamFragment *au, + uint32_t payload_type, + SEIRawMessage **iter) +{ + int err, i, j, found; + + found = 0; + for (i = 0; i < au->nb_units; i++) { + CodedBitstreamUnit *unit = &au->units[i]; + SEIRawMessageList *list; + + err = cbs_sei_get_message_list(ctx, unit, &list); + if (err < 0) + continue; + + for (j = 0; j < list->nb_messages; j++) { + SEIRawMessage *message = &list->messages[j]; + + if (message->payload_type == payload_type) { + if (!*iter || found) { + *iter = message; + return 0; + } + if (message == *iter) + found = 1; + } + } + } + + return AVERROR(ENOENT); +} + +static void cbs_sei_delete_message(SEIRawMessageList *list, + int position) +{ + SEIRawMessage *message; + + av_assert0(0 <= position && position < list->nb_messages); + + message = &list->messages[position]; + av_buffer_unref(&message->payload_ref); + av_buffer_unref(&message->extension_data_ref); + + --list->nb_messages; + + if (list->nb_messages > 0) { + memmove(list->messages + position, + list->messages + position + 1, + (list->nb_messages - position) * sizeof(*list->messages)); + } +} + +void ff_cbs_sei_delete_message_type(CodedBitstreamContext *ctx, + CodedBitstreamFragment *au, + uint32_t payload_type) +{ + int err, i, j; + + for (i = 0; i < au->nb_units; i++) { + CodedBitstreamUnit *unit = &au->units[i]; + SEIRawMessageList *list; + + err = cbs_sei_get_message_list(ctx, unit, &list); + if (err < 0) + continue; + + for (j = list->nb_messages - 1; j >= 0; j--) { + if (list->messages[j].payload_type == payload_type) + cbs_sei_delete_message(list, j); + } + } +} diff -Nru ffmpeg-4.2.2/libavcodec/cbs_sei.h ffmpeg-4.4/libavcodec/cbs_sei.h --- ffmpeg-4.2.2/libavcodec/cbs_sei.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_sei.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,199 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CBS_SEI_H +#define AVCODEC_CBS_SEI_H + +#include +#include + +#include "libavutil/buffer.h" + +#include "cbs.h" +#include "sei.h" + + +typedef struct SEIRawFillerPayload { + uint32_t payload_size; +} SEIRawFillerPayload; + +typedef struct SEIRawUserDataRegistered { + uint8_t itu_t_t35_country_code; + uint8_t itu_t_t35_country_code_extension_byte; + uint8_t *data; + AVBufferRef *data_ref; + size_t data_length; +} SEIRawUserDataRegistered; + +typedef struct SEIRawUserDataUnregistered { + uint8_t uuid_iso_iec_11578[16]; + uint8_t *data; + AVBufferRef *data_ref; + size_t data_length; +} SEIRawUserDataUnregistered; + +typedef struct SEIRawMasteringDisplayColourVolume { + uint16_t display_primaries_x[3]; + uint16_t display_primaries_y[3]; + uint16_t white_point_x; + uint16_t white_point_y; + uint32_t max_display_mastering_luminance; + uint32_t min_display_mastering_luminance; +} SEIRawMasteringDisplayColourVolume; + +typedef struct SEIRawContentLightLevelInfo { + uint16_t max_content_light_level; + uint16_t max_pic_average_light_level; +} SEIRawContentLightLevelInfo; + +typedef struct SEIRawAlternativeTransferCharacteristics { + uint8_t preferred_transfer_characteristics; +} SEIRawAlternativeTransferCharacteristics; + +typedef struct SEIRawMessage { + uint32_t payload_type; + uint32_t payload_size; + void *payload; + AVBufferRef *payload_ref; + uint8_t *extension_data; + AVBufferRef *extension_data_ref; + size_t extension_bit_length; +} SEIRawMessage; + +typedef struct SEIRawMessageList { + SEIRawMessage *messages; + int nb_messages; + int nb_messages_allocated; +} SEIRawMessageList; + + +typedef struct SEIMessageState { + // The type of the payload being written. + uint32_t payload_type; + // When reading, contains the size of the payload to allow finding the + // end of variable-length fields (such as user_data_payload_byte[]). + // (When writing, the size will be derived from the total number of + // bytes actually written.) + uint32_t payload_size; + // When writing, indicates that payload extension data is present so + // all extended fields must be written. May be updated by the writer + // to indicate that extended fields have been written, so the extension + // end bits must be written too. + uint8_t extension_present; +} SEIMessageState; + +struct GetBitContext; +struct PutBitContext; + +typedef int (*SEIMessageReadFunction)(CodedBitstreamContext *ctx, + struct GetBitContext *rw, + void *current, + SEIMessageState *sei); + +typedef int (*SEIMessageWriteFunction)(CodedBitstreamContext *ctx, + struct PutBitContext *rw, + void *current, + SEIMessageState *sei); + +typedef struct SEIMessageTypeDescriptor { + // Payload type for the message. (-1 in this field ends a list.) + int type; + // Valid in a prefix SEI NAL unit (always for H.264). + uint8_t prefix; + // Valid in a suffix SEI NAL unit (never for H.264). + uint8_t suffix; + // Size of the decomposed structure. + size_t size; + // Read bitstream into SEI message. + SEIMessageReadFunction read; + // Write bitstream from SEI message. + SEIMessageWriteFunction write; +} SEIMessageTypeDescriptor; + +// Macro for the read/write pair. The clumsy cast is needed because the +// current pointer is typed in all of the read/write functions but has to +// be void here to fit all cases. +#define SEI_MESSAGE_RW(codec, name) \ + .read = (SEIMessageReadFunction) cbs_ ## codec ## _read_ ## name, \ + .write = (SEIMessageWriteFunction)cbs_ ## codec ## _write_ ## name + +// End-of-list sentinel element. +#define SEI_MESSAGE_TYPE_END { .type = -1 } + + +/** + * Find the type descriptor for the given payload type. + * + * Returns NULL if the payload type is not known. + */ +const SEIMessageTypeDescriptor *ff_cbs_sei_find_type(CodedBitstreamContext *ctx, + int payload_type); + +/** + * Allocate a new payload for the given SEI message. + */ +int ff_cbs_sei_alloc_message_payload(SEIRawMessage *message, + const SEIMessageTypeDescriptor *desc); + +/** + * Allocate a new empty SEI message in a message list. + * + * The new message is in place nb_messages - 1. + */ +int ff_cbs_sei_list_add(SEIRawMessageList *list); + +/** + * Free all SEI messages in a message list. + */ +void ff_cbs_sei_free_message_list(SEIRawMessageList *list); + +/** + * Add an SEI message to an access unit. + * + * Will add to an existing SEI NAL unit, or create a new one for the + * message if there is no suitable existing one. + * + * Takes a new reference to payload_buf, if set. If payload_buf is + * NULL then the new message will not be reference counted. + */ +int ff_cbs_sei_add_message(CodedBitstreamContext *ctx, + CodedBitstreamFragment *au, + int prefix, + uint32_t payload_type, + void *payload_data, + AVBufferRef *payload_buf); + +/** + * Iterate over messages with the given payload type in an access unit. + * + * Set message to NULL in the first call. Returns 0 while more messages + * are available, AVERROR(ENOENT) when all messages have been found. + */ +int ff_cbs_sei_find_message(CodedBitstreamContext *ctx, + CodedBitstreamFragment *au, + uint32_t payload_type, + SEIRawMessage **message); + +/** + * Delete all messages with the given payload type from an access unit. + */ +void ff_cbs_sei_delete_message_type(CodedBitstreamContext *ctx, + CodedBitstreamFragment *au, + uint32_t payload_type); + +#endif /* AVCODEC_CBS_SEI_H */ diff -Nru ffmpeg-4.2.2/libavcodec/cbs_sei_syntax_template.c ffmpeg-4.4/libavcodec/cbs_sei_syntax_template.c --- ffmpeg-4.2.2/libavcodec/cbs_sei_syntax_template.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_sei_syntax_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,322 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static int FUNC(filler_payload) + (CodedBitstreamContext *ctx, RWContext *rw, + SEIRawFillerPayload *current, SEIMessageState *state) +{ + int err, i; + + HEADER("Filler Payload"); + +#ifdef READ + current->payload_size = state->payload_size; +#endif + + for (i = 0; i < current->payload_size; i++) + fixed(8, ff_byte, 0xff); + + return 0; +} + +static int FUNC(user_data_registered) + (CodedBitstreamContext *ctx, RWContext *rw, + SEIRawUserDataRegistered *current, SEIMessageState *state) +{ + int err, i, j; + + HEADER("User Data Registered ITU-T T.35"); + + u(8, itu_t_t35_country_code, 0x00, 0xff); + if (current->itu_t_t35_country_code != 0xff) + i = 1; + else { + u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff); + i = 2; + } + +#ifdef READ + if (state->payload_size < i) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Invalid SEI user data registered payload.\n"); + return AVERROR_INVALIDDATA; + } + current->data_length = state->payload_size - i; +#endif + + allocate(current->data, current->data_length); + for (j = 0; j < current->data_length; j++) + xu(8, itu_t_t35_payload_byte[], current->data[j], 0x00, 0xff, 1, i + j); + + return 0; +} + +static int FUNC(user_data_unregistered) + (CodedBitstreamContext *ctx, RWContext *rw, + SEIRawUserDataUnregistered *current, SEIMessageState *state) +{ + int err, i; + + HEADER("User Data Unregistered"); + +#ifdef READ + if (state->payload_size < 16) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Invalid SEI user data unregistered payload.\n"); + return AVERROR_INVALIDDATA; + } + current->data_length = state->payload_size - 16; +#endif + + for (i = 0; i < 16; i++) + us(8, uuid_iso_iec_11578[i], 0x00, 0xff, 1, i); + + allocate(current->data, current->data_length); + + for (i = 0; i < current->data_length; i++) + xu(8, user_data_payload_byte[i], current->data[i], 0x00, 0xff, 1, i); + + return 0; +} + +static int FUNC(mastering_display_colour_volume) + (CodedBitstreamContext *ctx, RWContext *rw, + SEIRawMasteringDisplayColourVolume *current, SEIMessageState *state) +{ + int err, c; + + HEADER("Mastering Display Colour Volume"); + + for (c = 0; c < 3; c++) { + ubs(16, display_primaries_x[c], 1, c); + ubs(16, display_primaries_y[c], 1, c); + } + + ub(16, white_point_x); + ub(16, white_point_y); + + ub(32, max_display_mastering_luminance); + ub(32, min_display_mastering_luminance); + + return 0; +} + +static int FUNC(content_light_level_info) + (CodedBitstreamContext *ctx, RWContext *rw, + SEIRawContentLightLevelInfo *current, SEIMessageState *state) +{ + int err; + + HEADER("Content Light Level Information"); + + ub(16, max_content_light_level); + ub(16, max_pic_average_light_level); + + return 0; +} + +static int FUNC(alternative_transfer_characteristics) + (CodedBitstreamContext *ctx, RWContext *rw, + SEIRawAlternativeTransferCharacteristics *current, + SEIMessageState *state) +{ + int err; + + HEADER("Alternative Transfer Characteristics"); + + ub(8, preferred_transfer_characteristics); + + return 0; +} + +static int FUNC(message)(CodedBitstreamContext *ctx, RWContext *rw, + SEIRawMessage *current) +{ + const SEIMessageTypeDescriptor *desc; + int err, i; + + desc = ff_cbs_sei_find_type(ctx, current->payload_type); + if (desc) { + SEIMessageState state = { + .payload_type = current->payload_type, + .payload_size = current->payload_size, + .extension_present = current->extension_bit_length > 0, + }; + int start_position, current_position, bits_written; + +#ifdef READ + CHECK(ff_cbs_sei_alloc_message_payload(current, desc)); +#endif + + start_position = bit_position(rw); + + CHECK(desc->READWRITE(ctx, rw, current->payload, &state)); + + current_position = bit_position(rw); + bits_written = current_position - start_position; + + if (byte_alignment(rw) || state.extension_present || + bits_written < 8 * current->payload_size) { + size_t bits_left; + +#ifdef READ + GetBitContext tmp = *rw; + int trailing_bits, trailing_zero_bits; + + bits_left = 8 * current->payload_size - bits_written; + if (bits_left > 8) + skip_bits_long(&tmp, bits_left - 8); + trailing_bits = get_bits(&tmp, FFMIN(bits_left, 8)); + if (trailing_bits == 0) { + // The trailing bits must contain a bit_equal_to_one, so + // they can't all be zero. + return AVERROR_INVALIDDATA; + } + trailing_zero_bits = ff_ctz(trailing_bits); + current->extension_bit_length = + bits_left - 1 - trailing_zero_bits; +#endif + + if (current->extension_bit_length > 0) { + allocate(current->extension_data, + (current->extension_bit_length + 7) / 8); + + bits_left = current->extension_bit_length; + for (i = 0; bits_left > 0; i++) { + int length = FFMIN(bits_left, 8); + xu(length, reserved_payload_extension_data, + current->extension_data[i], + 0, MAX_UINT_BITS(length), 0); + bits_left -= length; + } + } + + fixed(1, bit_equal_to_one, 1); + while (byte_alignment(rw)) + fixed(1, bit_equal_to_zero, 0); + } + +#ifdef WRITE + current->payload_size = (put_bits_count(rw) - start_position) / 8; +#endif + } else { + uint8_t *data; + + allocate(current->payload, current->payload_size); + data = current->payload; + + for (i = 0; i < current->payload_size; i++) + xu(8, payload_byte[i], data[i], 0, 255, 1, i); + } + + return 0; +} + +static int FUNC(message_list)(CodedBitstreamContext *ctx, RWContext *rw, + SEIRawMessageList *current, int prefix) +{ + SEIRawMessage *message; + int err, k; + +#ifdef READ + for (k = 0;; k++) { + uint32_t payload_type = 0; + uint32_t payload_size = 0; + uint32_t tmp; + GetBitContext payload_gbc; + + while (show_bits(rw, 8) == 0xff) { + fixed(8, ff_byte, 0xff); + payload_type += 255; + } + xu(8, last_payload_type_byte, tmp, 0, 254, 0); + payload_type += tmp; + + while (show_bits(rw, 8) == 0xff) { + fixed(8, ff_byte, 0xff); + payload_size += 255; + } + xu(8, last_payload_size_byte, tmp, 0, 254, 0); + payload_size += tmp; + + // There must be space remaining for both the payload and + // the trailing bits on the SEI NAL unit. + if (payload_size + 1 > get_bits_left(rw) / 8) { + av_log(ctx->log_ctx, AV_LOG_ERROR, + "Invalid SEI message: payload_size too large " + "(%"PRIu32" bytes).\n", payload_size); + return AVERROR_INVALIDDATA; + } + CHECK(init_get_bits(&payload_gbc, rw->buffer, + get_bits_count(rw) + 8 * payload_size)); + skip_bits_long(&payload_gbc, get_bits_count(rw)); + + CHECK(ff_cbs_sei_list_add(current)); + message = ¤t->messages[k]; + + message->payload_type = payload_type; + message->payload_size = payload_size; + + CHECK(FUNC(message)(ctx, &payload_gbc, message)); + + skip_bits_long(rw, 8 * payload_size); + + if (!cbs_h2645_read_more_rbsp_data(rw)) + break; + } +#else + for (k = 0; k < current->nb_messages; k++) { + PutBitContext start_state; + uint32_t tmp; + int trace, i; + + message = ¤t->messages[k]; + + // We write the payload twice in order to find the size. Trace + // output is switched off for the first write. + trace = ctx->trace_enable; + ctx->trace_enable = 0; + + start_state = *rw; + for (i = 0; i < 2; i++) { + *rw = start_state; + + tmp = message->payload_type; + while (tmp >= 255) { + fixed(8, ff_byte, 0xff); + tmp -= 255; + } + xu(8, last_payload_type_byte, tmp, 0, 254, 0); + + tmp = message->payload_size; + while (tmp >= 255) { + fixed(8, ff_byte, 0xff); + tmp -= 255; + } + xu(8, last_payload_size_byte, tmp, 0, 254, 0); + + err = FUNC(message)(ctx, rw, message); + ctx->trace_enable = trace; + if (err < 0) + return err; + } + } +#endif + + return 0; +} diff -Nru ffmpeg-4.2.2/libavcodec/cbs_vp9.c ffmpeg-4.4/libavcodec/cbs_vp9.c --- ffmpeg-4.2.2/libavcodec/cbs_vp9.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_vp9.c 2021-04-08 21:28:39.000000000 +0000 @@ -253,15 +253,14 @@ #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL) #define f(width, name) \ - xf(width, name, current->name, 0) + xf(width, name, current->name, 0, ) #define s(width, name) \ - xs(width, name, current->name, 0) + xs(width, name, current->name, 0, ) #define fs(width, name, subs, ...) \ xf(width, name, current->name, subs, __VA_ARGS__) #define ss(width, name, subs, ...) \ xs(width, name, current->name, subs, __VA_ARGS__) - #define READ #define READWRITE read #define RWContext GetBitContext @@ -295,9 +294,9 @@ #define delta_q(name) do { \ uint8_t delta_coded; \ int8_t delta_q; \ - xf(1, name.delta_coded, delta_coded, 0); \ + xf(1, name.delta_coded, delta_coded, 0, ); \ if (delta_coded) \ - xs(4, name.delta_q, delta_q, 0); \ + xs(4, name.delta_q, delta_q, 0, ); \ else \ delta_q = 0; \ current->name = delta_q; \ @@ -366,9 +365,9 @@ } while (0) #define delta_q(name) do { \ - xf(1, name.delta_coded, !!current->name, 0); \ + xf(1, name.delta_coded, !!current->name, 0, ); \ if (current->name) \ - xs(4, name.delta_q, current->name, 0); \ + xs(4, name.delta_q, current->name, 0, ); \ } while (0) #define prob(name, subs, ...) do { \ @@ -452,7 +451,7 @@ return AVERROR_INVALIDDATA; } - err = ff_cbs_insert_unit_data(ctx, frag, -1, 0, + err = ff_cbs_insert_unit_data(frag, -1, 0, frag->data + pos, sfi.frame_sizes[i], frag->data_ref); @@ -470,7 +469,7 @@ return 0; } else { - err = ff_cbs_insert_unit_data(ctx, frag, -1, 0, + err = ff_cbs_insert_unit_data(frag, -1, 0, frag->data, frag->data_size, frag->data_ref); if (err < 0) @@ -480,13 +479,6 @@ return 0; } -static void cbs_vp9_free_frame(void *unit, uint8_t *content) -{ - VP9RawFrame *frame = (VP9RawFrame*)content; - av_buffer_unref(&frame->data_ref); - av_freep(&frame); -} - static int cbs_vp9_read_unit(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit) { @@ -498,8 +490,7 @@ if (err < 0) return err; - err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*frame), - &cbs_vp9_free_frame); + err = ff_cbs_alloc_unit_content2(ctx, unit); if (err < 0) return err; frame = unit->content; @@ -643,13 +634,30 @@ return 0; } +static void cbs_vp9_flush(CodedBitstreamContext *ctx) +{ + CodedBitstreamVP9Context *vp9 = ctx->priv_data; + + memset(vp9->ref, 0, sizeof(vp9->ref)); +} + +static const CodedBitstreamUnitTypeDescriptor cbs_vp9_unit_types[] = { + CBS_UNIT_TYPE_INTERNAL_REF(0, VP9RawFrame, data), + CBS_UNIT_TYPE_END_OF_LIST +}; + const CodedBitstreamType ff_cbs_type_vp9 = { .codec_id = AV_CODEC_ID_VP9, .priv_data_size = sizeof(CodedBitstreamVP9Context), + .unit_types = cbs_vp9_unit_types, + .split_fragment = &cbs_vp9_split_fragment, .read_unit = &cbs_vp9_read_unit, .write_unit = &cbs_vp9_write_unit, + + .flush = &cbs_vp9_flush, + .assemble_fragment = &cbs_vp9_assemble_fragment, }; diff -Nru ffmpeg-4.2.2/libavcodec/cbs_vp9.h ffmpeg-4.4/libavcodec/cbs_vp9.h --- ffmpeg-4.2.2/libavcodec/cbs_vp9.h 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_vp9.h 2021-04-08 21:28:39.000000000 +0000 @@ -165,8 +165,8 @@ VP9RawFrameHeader header; uint8_t *data; - size_t data_size; AVBufferRef *data_ref; + size_t data_size; } VP9RawFrame; typedef struct VP9RawSuperframeIndex { diff -Nru ffmpeg-4.2.2/libavcodec/cbs_vp9_syntax_template.c ffmpeg-4.4/libavcodec/cbs_vp9_syntax_template.c --- ffmpeg-4.2.2/libavcodec/cbs_vp9_syntax_template.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cbs_vp9_syntax_template.c 2020-07-11 10:39:30.000000000 +0000 @@ -19,23 +19,11 @@ static int FUNC(frame_sync_code)(CodedBitstreamContext *ctx, RWContext *rw, VP9RawFrameHeader *current) { - uint8_t frame_sync_byte_0 = VP9_FRAME_SYNC_0; - uint8_t frame_sync_byte_1 = VP9_FRAME_SYNC_1; - uint8_t frame_sync_byte_2 = VP9_FRAME_SYNC_2; int err; - xf(8, frame_sync_byte_0, frame_sync_byte_0, 0); - xf(8, frame_sync_byte_1, frame_sync_byte_1, 0); - xf(8, frame_sync_byte_2, frame_sync_byte_2, 0); - - if (frame_sync_byte_0 != VP9_FRAME_SYNC_0 || - frame_sync_byte_1 != VP9_FRAME_SYNC_1 || - frame_sync_byte_2 != VP9_FRAME_SYNC_2) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid frame sync code: " - "%02x %02x %02x.\n", frame_sync_byte_0, - frame_sync_byte_1, frame_sync_byte_2); - return AVERROR_INVALIDDATA; - } + fixed(8, frame_sync_byte_0, VP9_FRAME_SYNC_0); + fixed(8, frame_sync_byte_1, VP9_FRAME_SYNC_1); + fixed(8, frame_sync_byte_2, VP9_FRAME_SYNC_2); return 0; } @@ -396,9 +384,8 @@ static int FUNC(trailing_bits)(CodedBitstreamContext *ctx, RWContext *rw) { int err; - av_unused int zero = 0; while (byte_alignment(rw) != 0) - xf(1, zero_bit, zero, 0); + fixed(1, zero_bit, 0); return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/ccaption_dec.c ffmpeg-4.4/libavcodec/ccaption_dec.c --- ffmpeg-4.2.2/libavcodec/ccaption_dec.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ccaption_dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,10 +32,6 @@ static const AVRational ms_tb = {1, 1000}; -/* - * TODO list - * 1) handle font and color completely - */ enum cc_mode { CCMODE_POPON, CCMODE_PAINTON, @@ -173,6 +169,18 @@ }, }; +static const unsigned char bg_attribs[8] = // Color +{ + CCCOL_WHITE, + CCCOL_GREEN, + CCCOL_BLUE, + CCCOL_CYAN, + CCCOL_RED, + CCCOL_YELLOW, + CCCOL_MAGENTA, + CCCOL_BLACK, +}; + static const unsigned char pac2_attribs[32][3] = // Color, font, ident { { CCCOL_WHITE, CCFONT_REGULAR, 0 }, // 0x40 || 0x60 @@ -215,6 +223,7 @@ uint8_t characters[SCREEN_ROWS+1][SCREEN_COLUMNS+1]; uint8_t charsets[SCREEN_ROWS+1][SCREEN_COLUMNS+1]; uint8_t colors[SCREEN_ROWS+1][SCREEN_COLUMNS+1]; + uint8_t bgs[SCREEN_ROWS+1][SCREEN_COLUMNS+1]; uint8_t fonts[SCREEN_ROWS+1][SCREEN_COLUMNS+1]; /* * Bitmask of used rows; if a bit is not set, the @@ -228,39 +237,37 @@ typedef struct CCaptionSubContext { AVClass *class; int real_time; + int data_field; struct Screen screen[2]; int active_screen; uint8_t cursor_row; uint8_t cursor_column; uint8_t cursor_color; + uint8_t bg_color; uint8_t cursor_font; uint8_t cursor_charset; - AVBPrint buffer; + AVBPrint buffer[2]; + int buffer_index; int buffer_changed; int rollup; enum cc_mode mode; - int64_t start_time; - /* visible screen time */ - int64_t startv_time; - int64_t end_time; + int64_t buffer_time[2]; int screen_touched; int64_t last_real_time; - char prev_cmd[2]; - /* buffer to store pkt data */ - uint8_t *pktbuf; - int pktbuf_size; + uint8_t prev_cmd[2]; int readorder; } CCaptionSubContext; - static av_cold int init_decoder(AVCodecContext *avctx) { int ret; CCaptionSubContext *ctx = avctx->priv_data; - av_bprint_init(&ctx->buffer, 0, AV_BPRINT_SIZE_UNLIMITED); + av_bprint_init(&ctx->buffer[0], 0, AV_BPRINT_SIZE_UNLIMITED); + av_bprint_init(&ctx->buffer[1], 0, AV_BPRINT_SIZE_UNLIMITED); /* taking by default roll up to 2 */ ctx->mode = CCMODE_ROLLUP; + ctx->bg_color = CCCOL_BLACK; ctx->rollup = 2; ctx->cursor_row = 10; ret = ff_ass_subtitle_header(avctx, "Monospace", @@ -282,9 +289,8 @@ static av_cold int close_decoder(AVCodecContext *avctx) { CCaptionSubContext *ctx = avctx->priv_data; - av_bprint_finalize(&ctx->buffer, NULL); - av_freep(&ctx->pktbuf); - ctx->pktbuf_size = 0; + av_bprint_finalize(&ctx->buffer[0], NULL); + av_bprint_finalize(&ctx->buffer[1], NULL); return 0; } @@ -301,6 +307,7 @@ ctx->cursor_column = 0; ctx->cursor_font = 0; ctx->cursor_color = 0; + ctx->bg_color = CCCOL_BLACK; ctx->cursor_charset = 0; ctx->active_screen = 0; ctx->last_real_time = 0; @@ -308,7 +315,8 @@ ctx->buffer_changed = 0; if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP)) ctx->readorder = 0; - av_bprint_clear(&ctx->buffer); + av_bprint_clear(&ctx->buffer[0]); + av_bprint_clear(&ctx->buffer[1]); } /** @@ -319,11 +327,15 @@ uint8_t col = ctx->cursor_column; char *row = screen->characters[ctx->cursor_row]; char *font = screen->fonts[ctx->cursor_row]; + char *color = screen->colors[ctx->cursor_row]; + char *bg = screen->bgs[ctx->cursor_row]; char *charset = screen->charsets[ctx->cursor_row]; if (col < SCREEN_COLUMNS) { row[col] = ch; font[col] = ctx->cursor_font; + color[col] = ctx->cursor_color; + bg[col] = ctx->bg_color; charset[col] = ctx->cursor_charset; ctx->cursor_charset = CCSET_BASIC_AMERICAN; if (ch) ctx->cursor_column++; @@ -347,11 +359,13 @@ * If the second byte doesn't pass parity, it returns INVALIDDATA * user can ignore the whole pair and pass the other pair. */ -static int validate_cc_data_pair(uint8_t *cc_data_pair) +static int validate_cc_data_pair(const uint8_t *cc_data_pair, uint8_t *hi) { uint8_t cc_valid = (*cc_data_pair & 4) >>2; uint8_t cc_type = *cc_data_pair & 3; + *hi = cc_data_pair[1]; + if (!cc_valid) return AVERROR_INVALIDDATA; @@ -361,7 +375,7 @@ return AVERROR_INVALIDDATA; } if (!av_parity(cc_data_pair[1])) { - cc_data_pair[1]=0x7F; + *hi = 0x7F; } } @@ -374,10 +388,6 @@ if (cc_type == 3 || cc_type == 2) return AVERROR_PATCHWELCOME; - /* remove parity bit */ - cc_data_pair[1] &= 0x7F; - cc_data_pair[2] &= 0x7F; - return 0; } @@ -423,6 +433,7 @@ memcpy(screen->characters[i_row], screen->characters[i_row+1], SCREEN_COLUMNS); memcpy(screen->colors[i_row], screen->colors[i_row+1], SCREEN_COLUMNS); + memcpy(screen->bgs[i_row], screen->bgs[i_row+1], SCREEN_COLUMNS); memcpy(screen->fonts[i_row], screen->fonts[i_row+1], SCREEN_COLUMNS); memcpy(screen->charsets[i_row], screen->charsets[i_row+1], SCREEN_COLUMNS); if (CHECK_FLAG(screen->row_used, i_row + 1)) @@ -437,7 +448,11 @@ int i, j, tab = 0; struct Screen *screen = ctx->screen + ctx->active_screen; enum cc_font prev_font = CCFONT_REGULAR; - av_bprint_clear(&ctx->buffer); + enum cc_color_code prev_color = CCCOL_WHITE; + enum cc_color_code prev_bg_color = CCCOL_BLACK; + const int bidx = ctx->buffer_index; + + av_bprint_clear(&ctx->buffer[bidx]); for (i = 0; screen->row_used && i < SCREEN_ROWS; i++) { @@ -457,6 +472,8 @@ if (CHECK_FLAG(screen->row_used, i)) { const char *row = screen->characters[i]; const char *font = screen->fonts[i]; + const char *bg = screen->bgs[i]; + const char *color = screen->colors[i]; const char *charset = screen->charsets[i]; const char *override; int x, y, seen_char = 0; @@ -468,10 +485,10 @@ x = ASS_DEFAULT_PLAYRESX * (0.1 + 0.0250 * j); y = ASS_DEFAULT_PLAYRESY * (0.1 + 0.0533 * i); - av_bprintf(&ctx->buffer, "{\\an7}{\\pos(%d,%d)}", x, y); + av_bprintf(&ctx->buffer[bidx], "{\\an7}{\\pos(%d,%d)}", x, y); for (; j < SCREEN_COLUMNS; j++) { - const char *e_tag = "", *s_tag = ""; + const char *e_tag = "", *s_tag = "", *c_tag = "", *b_tag = ""; if (row[j] == 0) break; @@ -500,38 +517,99 @@ break; } } + if (prev_color != color[j]) { + switch (color[j]) { + case CCCOL_WHITE: + c_tag = "{\\c&HFFFFFF&}"; + break; + case CCCOL_GREEN: + c_tag = "{\\c&H00FF00&}"; + break; + case CCCOL_BLUE: + c_tag = "{\\c&HFF0000&}"; + break; + case CCCOL_CYAN: + c_tag = "{\\c&HFFFF00&}"; + break; + case CCCOL_RED: + c_tag = "{\\c&H0000FF&}"; + break; + case CCCOL_YELLOW: + c_tag = "{\\c&H00FFFF&}"; + break; + case CCCOL_MAGENTA: + c_tag = "{\\c&HFF00FF&}"; + break; + } + } + if (prev_bg_color != bg[j]) { + switch (bg[j]) { + case CCCOL_WHITE: + b_tag = "{\\3c&HFFFFFF&}"; + break; + case CCCOL_GREEN: + b_tag = "{\\3c&H00FF00&}"; + break; + case CCCOL_BLUE: + b_tag = "{\\3c&HFF0000&}"; + break; + case CCCOL_CYAN: + b_tag = "{\\3c&HFFFF00&}"; + break; + case CCCOL_RED: + b_tag = "{\\3c&H0000FF&}"; + break; + case CCCOL_YELLOW: + b_tag = "{\\3c&H00FFFF&}"; + break; + case CCCOL_MAGENTA: + b_tag = "{\\3c&HFF00FF&}"; + break; + case CCCOL_BLACK: + b_tag = "{\\3c&H000000&}"; + break; + } + } + prev_font = font[j]; + prev_color = color[j]; + prev_bg_color = bg[j]; override = charset_overrides[(int)charset[j]][(int)row[j]]; if (override) { - av_bprintf(&ctx->buffer, "%s%s%s", e_tag, s_tag, override); + av_bprintf(&ctx->buffer[bidx], "%s%s%s%s%s", e_tag, s_tag, c_tag, b_tag, override); seen_char = 1; } else if (row[j] == ' ' && !seen_char) { - av_bprintf(&ctx->buffer, "%s%s\\h", e_tag, s_tag); + av_bprintf(&ctx->buffer[bidx], "%s%s%s%s\\h", e_tag, s_tag, c_tag, b_tag); } else { - av_bprintf(&ctx->buffer, "%s%s%c", e_tag, s_tag, row[j]); + av_bprintf(&ctx->buffer[bidx], "%s%s%s%s%c", e_tag, s_tag, c_tag, b_tag, row[j]); seen_char = 1; } } - av_bprintf(&ctx->buffer, "\\N"); + av_bprintf(&ctx->buffer[bidx], "\\N"); } } - if (!av_bprint_is_complete(&ctx->buffer)) + if (!av_bprint_is_complete(&ctx->buffer[bidx])) return AVERROR(ENOMEM); - if (screen->row_used && ctx->buffer.len >= 2) { - ctx->buffer.len -= 2; - ctx->buffer.str[ctx->buffer.len] = 0; + if (screen->row_used && ctx->buffer[bidx].len >= 2) { + ctx->buffer[bidx].len -= 2; + ctx->buffer[bidx].str[ctx->buffer[bidx].len] = 0; } ctx->buffer_changed = 1; return 0; } -static int reap_screen(CCaptionSubContext *ctx, int64_t pts) +static void update_time(CCaptionSubContext *ctx, int64_t pts) +{ + ctx->buffer_time[0] = ctx->buffer_time[1]; + ctx->buffer_time[1] = pts; +} + +static void handle_bgattr(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo) { - ctx->start_time = ctx->startv_time; - ctx->startv_time = pts; - ctx->end_time = pts; - return capture_screen(ctx); + const int i = (lo & 0xf) >> 1; + + ctx->bg_color = bg_attribs[i]; } static void handle_textattr(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo) @@ -576,49 +654,55 @@ } } -/** - * @param pts it is required to set end time - */ -static void handle_edm(CCaptionSubContext *ctx, int64_t pts) +static int handle_edm(CCaptionSubContext *ctx) { struct Screen *screen = ctx->screen + ctx->active_screen; + int ret; // In buffered mode, keep writing to screen until it is wiped. // Before wiping the display, capture contents to emit subtitle. if (!ctx->real_time) - reap_screen(ctx, pts); + ret = capture_screen(ctx); screen->row_used = 0; + ctx->bg_color = CCCOL_BLACK; // In realtime mode, emit an empty caption so the last one doesn't // stay on the screen. if (ctx->real_time) - reap_screen(ctx, pts); + ret = capture_screen(ctx); + + return ret; } -static void handle_eoc(CCaptionSubContext *ctx, int64_t pts) +static int handle_eoc(CCaptionSubContext *ctx) { + int ret; + + ctx->active_screen = !ctx->active_screen; + // In buffered mode, we wait til the *next* EOC and - // reap what was already on the screen since the last EOC. + // capture what was already on the screen since the last EOC. if (!ctx->real_time) - handle_edm(ctx,pts); + ret = handle_edm(ctx); - ctx->active_screen = !ctx->active_screen; ctx->cursor_column = 0; // In realtime mode, we display the buffered contents (after // flipping the buffer to active above) as soon as EOC arrives. if (ctx->real_time) - reap_screen(ctx, pts); + ret = capture_screen(ctx); + + return ret; } -static void handle_delete_end_of_row(CCaptionSubContext *ctx, char hi, char lo) +static void handle_delete_end_of_row(CCaptionSubContext *ctx) { struct Screen *screen = get_writing_screen(ctx); write_char(ctx, screen, 0); } -static void handle_char(CCaptionSubContext *ctx, char hi, char lo, int64_t pts) +static void handle_char(CCaptionSubContext *ctx, char hi, char lo) { struct Screen *screen = get_writing_screen(ctx); @@ -658,11 +742,12 @@ ff_dlog(ctx, "(%c)\n", hi); } -static void process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint8_t lo) +static int process_cc608(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo) { + int ret = 0; + if (hi == ctx->prev_cmd[0] && lo == ctx->prev_cmd[1]) { - /* ignore redundant command */ - return; + return 0; } /* set prev command */ @@ -675,6 +760,8 @@ } else if ( ( hi == 0x11 && lo >= 0x20 && lo <= 0x2f ) || ( hi == 0x17 && lo >= 0x2e && lo <= 0x2f) ) { handle_textattr(ctx, hi, lo); + } else if ((hi == 0x10 && lo >= 0x20 && lo <= 0x2f)) { + handle_bgattr(ctx, hi, lo); } else if (hi == 0x14 || hi == 0x15 || hi == 0x1c) { switch (lo) { case 0x20: @@ -682,7 +769,7 @@ ctx->mode = CCMODE_POPON; break; case 0x24: - handle_delete_end_of_row(ctx, hi, lo); + handle_delete_end_of_row(ctx); break; case 0x25: case 0x26: @@ -700,13 +787,13 @@ break; case 0x2c: /* erase display memory */ - handle_edm(ctx, pts); + handle_edm(ctx); break; case 0x2d: /* carriage return */ ff_dlog(ctx, "carriage return\n"); if (!ctx->real_time) - reap_screen(ctx, pts); + ret = capture_screen(ctx); roll_up(ctx); ctx->cursor_column = 0; break; @@ -722,7 +809,7 @@ case 0x2f: /* end of caption */ ff_dlog(ctx, "handle_eoc\n"); - handle_eoc(ctx, pts); + ret = handle_eoc(ctx); break; default: ff_dlog(ctx, "Unknown command 0x%hhx 0x%hhx\n", hi, lo); @@ -730,73 +817,93 @@ } } else if (hi >= 0x11 && hi <= 0x13) { /* Special characters */ - handle_char(ctx, hi, lo, pts); + handle_char(ctx, hi, lo); } else if (hi >= 0x20) { /* Standard characters (always in pairs) */ - handle_char(ctx, hi, lo, pts); + handle_char(ctx, hi, lo); ctx->prev_cmd[0] = ctx->prev_cmd[1] = 0; } else if (hi == 0x17 && lo >= 0x21 && lo <= 0x23) { int i; /* Tab offsets (spacing) */ for (i = 0; i < lo - 0x20; i++) { - handle_char(ctx, ' ', 0, pts); + handle_char(ctx, ' ', 0); } } else { /* Ignoring all other non data code */ ff_dlog(ctx, "Unknown command 0x%hhx 0x%hhx\n", hi, lo); } + + return ret; } static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avpkt) { CCaptionSubContext *ctx = avctx->priv_data; AVSubtitle *sub = data; - const int64_t start_time = sub->pts; - uint8_t *bptr = NULL; + int64_t in_time = sub->pts; + int64_t start_time; + int64_t end_time; + int bidx = ctx->buffer_index; + const uint8_t *bptr = avpkt->data; int len = avpkt->size; int ret = 0; int i; - av_fast_padded_malloc(&ctx->pktbuf, &ctx->pktbuf_size, len); - if (!ctx->pktbuf) { - av_log(ctx, AV_LOG_WARNING, "Insufficient Memory of %d truncated to %d\n", len, ctx->pktbuf_size); - return AVERROR(ENOMEM); - } - memcpy(ctx->pktbuf, avpkt->data, len); - bptr = ctx->pktbuf; + for (i = 0; i < len; i += 3) { + uint8_t hi, cc_type = bptr[i] & 1; + + if (ctx->data_field < 0) + ctx->data_field = cc_type; - for (i = 0; i < len; i += 3) { - uint8_t cc_type = *(bptr + i) & 3; - if (validate_cc_data_pair(bptr + i)) + if (validate_cc_data_pair(bptr + i, &hi)) continue; - /* ignoring data field 1 */ - if(cc_type == 1) + + if (cc_type != ctx->data_field) continue; - else - process_cc608(ctx, start_time, *(bptr + i + 1) & 0x7f, *(bptr + i + 2) & 0x7f); + + ret = process_cc608(ctx, hi & 0x7f, bptr[i + 2] & 0x7f); + if (ret < 0) + return ret; if (!ctx->buffer_changed) continue; ctx->buffer_changed = 0; - if (*ctx->buffer.str || ctx->real_time) - { - ff_dlog(ctx, "cdp writing data (%s)\n",ctx->buffer.str); - ret = ff_ass_add_rect(sub, ctx->buffer.str, ctx->readorder++, 0, NULL, NULL); - if (ret < 0) - return ret; - sub->pts = ctx->start_time; + if (!ctx->real_time && ctx->mode == CCMODE_POPON) + ctx->buffer_index = bidx = !ctx->buffer_index; + + update_time(ctx, in_time); + + if (ctx->buffer[bidx].str[0] || ctx->real_time) { + ff_dlog(ctx, "cdp writing data (%s)\n", ctx->buffer[bidx].str); + start_time = ctx->buffer_time[0]; + sub->pts = start_time; + end_time = ctx->buffer_time[1]; if (!ctx->real_time) - sub->end_display_time = av_rescale_q(ctx->end_time - ctx->start_time, + sub->end_display_time = av_rescale_q(end_time - start_time, AV_TIME_BASE_Q, ms_tb); else sub->end_display_time = -1; - ctx->buffer_changed = 0; + ret = ff_ass_add_rect(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL); + if (ret < 0) + return ret; ctx->last_real_time = sub->pts; ctx->screen_touched = 0; } } + if (!bptr && !ctx->real_time && ctx->buffer[!ctx->buffer_index].str[0]) { + bidx = !ctx->buffer_index; + ret = ff_ass_add_rect(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL); + if (ret < 0) + return ret; + sub->pts = ctx->buffer_time[1]; + sub->end_display_time = av_rescale_q(ctx->buffer_time[1] - ctx->buffer_time[0], + AV_TIME_BASE_Q, ms_tb); + if (sub->end_display_time == 0) + sub->end_display_time = ctx->buffer[bidx].len * 20; + } + if (ctx->real_time && ctx->screen_touched && sub->pts > ctx->last_real_time + av_rescale_q(200, ms_tb, AV_TIME_BASE_Q)) { ctx->last_real_time = sub->pts; @@ -805,7 +912,7 @@ capture_screen(ctx); ctx->buffer_changed = 0; - ret = ff_ass_add_rect(sub, ctx->buffer.str, ctx->readorder++, 0, NULL, NULL); + ret = ff_ass_add_rect(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL); if (ret < 0) return ret; sub->end_display_time = -1; @@ -819,6 +926,10 @@ #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { { "real_time", "emit subtitle events as they are decoded for real-time display", OFFSET(real_time), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, SD }, + { "data_field", "select data field", OFFSET(data_field), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, SD, "data_field" }, + { "auto", "pick first one that appears", 0, AV_OPT_TYPE_CONST, { .i64 =-1 }, 0, 0, SD, "data_field" }, + { "first", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, SD, "data_field" }, + { "second", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, SD, "data_field" }, {NULL} }; @@ -840,4 +951,5 @@ .flush = flush_decoder, .decode = decode, .priv_class = &ccaption_dec_class, + .capabilities = AV_CODEC_CAP_DELAY, }; diff -Nru ffmpeg-4.2.2/libavcodec/cdgraphics.c ffmpeg-4.4/libavcodec/cdgraphics.c --- ffmpeg-4.2.2/libavcodec/cdgraphics.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cdgraphics.c 2021-04-08 21:28:39.000000000 +0000 @@ -283,7 +283,7 @@ bytestream2_init(&gb, avpkt->data, avpkt->size); - if ((ret = ff_reget_buffer(avctx, cc->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, cc->frame, 0)) < 0) return ret; if (!cc->cleared) { memset(cc->frame->data[0], 0, cc->frame->linesize[0] * avctx->height); @@ -365,6 +365,18 @@ return avpkt->size; } +static void cdg_decode_flush(AVCodecContext *avctx) +{ + CDGraphicsContext *cc = avctx->priv_data; + + if (!cc->frame->data[0]) + return; + + memset(cc->frame->data[0], 0, cc->frame->linesize[0] * avctx->height); + if (!avctx->frame_number) + memset(cc->frame->data[1], 0, AVPALETTE_SIZE); +} + static av_cold int cdg_decode_end(AVCodecContext *avctx) { CDGraphicsContext *cc = avctx->priv_data; @@ -383,5 +395,6 @@ .init = cdg_decode_init, .close = cdg_decode_end, .decode = cdg_decode_frame, + .flush = cdg_decode_flush, .capabilities = AV_CODEC_CAP_DR1, }; diff -Nru ffmpeg-4.2.2/libavcodec/cdtoons.c ffmpeg-4.4/libavcodec/cdtoons.c --- ffmpeg-4.2.2/libavcodec/cdtoons.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cdtoons.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,457 @@ +/* + * CDToons video decoder + * Copyright (C) 2020 Alyssa Milburn + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * CDToons video decoder + * @author Alyssa Milburn + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/internal.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#define CDTOONS_HEADER_SIZE 44 +#define CDTOONS_MAX_SPRITES 1200 + +typedef struct CDToonsSprite { + uint16_t flags; + uint16_t owner_frame; + uint16_t start_frame; + uint16_t end_frame; + unsigned int alloc_size; + uint32_t size; + uint8_t *data; + int active; +} CDToonsSprite; + +typedef struct CDToonsContext { + AVFrame *frame; + + uint16_t last_pal_id; ///< The index of the active palette sprite. + uint32_t pal[256]; ///< The currently-used palette data. + CDToonsSprite sprites[CDTOONS_MAX_SPRITES]; +} CDToonsContext; + +static int cdtoons_render_sprite(AVCodecContext *avctx, const uint8_t *data, + uint32_t data_size, + int dst_x, int dst_y, int width, int height) +{ + CDToonsContext *c = avctx->priv_data; + const uint8_t *next_line = data; + const uint8_t *end = data + data_size; + uint16_t line_size; + uint8_t *dest; + int skip = 0, to_skip, x; + + if (dst_x + width > avctx->width) + width = avctx->width - dst_x; + if (dst_y + height > avctx->height) + height = avctx->height - dst_y; + + if (dst_x < 0) { + /* we need to skip the start of the scanlines */ + skip = -dst_x; + if (width <= skip) + return 0; + dst_x = 0; + } + + for (int y = 0; y < height; y++) { + /* one scanline at a time, size is provided */ + data = next_line; + if (end - data < 2) + return 1; + line_size = bytestream_get_be16(&data); + if (end - data < line_size) + return 1; + next_line = data + line_size; + if (dst_y + y < 0) + continue; + + dest = c->frame->data[0] + (dst_y + y) * c->frame->linesize[0] + dst_x; + + to_skip = skip; + x = 0; + while (x < width - skip) { + int raw, size, step; + uint8_t val; + + if (data >= end) + return 1; + + val = bytestream_get_byte(&data); + raw = !(val & 0x80); + size = (int)(val & 0x7F) + 1; + + /* skip the start of a scanline if it is off-screen */ + if (to_skip >= size) { + to_skip -= size; + if (raw) { + step = size; + } else { + step = 1; + } + if (next_line - data < step) + return 1; + data += step; + continue; + } else if (to_skip) { + size -= to_skip; + if (raw) { + if (next_line - data < to_skip) + return 1; + data += to_skip; + } + to_skip = 0; + } + + if (x + size >= width - skip) + size = width - skip - x; + + /* either raw data, or a run of a single color */ + if (raw) { + if (next_line - data < size) + return 1; + memcpy(dest + x, data, size); + data += size; + } else { + uint8_t color = bytestream_get_byte(&data); + /* ignore transparent runs */ + if (color) + memset(dest + x, color, size); + } + x += size; + } + } + + return 0; +} + +static int cdtoons_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + CDToonsContext *c = avctx->priv_data; + const uint8_t *buf = avpkt->data; + const uint8_t *eod = avpkt->data + avpkt->size; + const int buf_size = avpkt->size; + uint16_t frame_id; + uint8_t background_color; + uint16_t sprite_count, sprite_offset; + uint8_t referenced_count; + uint16_t palette_id; + uint8_t palette_set; + int ret; + int saw_embedded_sprites = 0; + + if (buf_size < CDTOONS_HEADER_SIZE) + return AVERROR_INVALIDDATA; + + if ((ret = ff_reget_buffer(avctx, c->frame, 0)) < 0) + return ret; + + /* a lot of the header is useless junk in the absence of + * dirty rectangling etc */ + buf += 2; /* version? (always 9?) */ + frame_id = bytestream_get_be16(&buf); + buf += 2; /* blocks_valid_until */ + buf += 1; + background_color = bytestream_get_byte(&buf); + buf += 16; /* clip rect, dirty rect */ + buf += 4; /* flags */ + sprite_count = bytestream_get_be16(&buf); + sprite_offset = bytestream_get_be16(&buf); + buf += 2; /* max block id? */ + referenced_count = bytestream_get_byte(&buf); + buf += 1; + palette_id = bytestream_get_be16(&buf); + palette_set = bytestream_get_byte(&buf); + buf += 5; + + if (sprite_offset > buf_size) + return AVERROR_INVALIDDATA; + + /* read new sprites introduced in this frame */ + buf = avpkt->data + sprite_offset; + while (sprite_count--) { + uint32_t size; + uint16_t sprite_id; + + if (buf + 14 > eod) + return AVERROR_INVALIDDATA; + + sprite_id = bytestream_get_be16(&buf); + if (sprite_id >= CDTOONS_MAX_SPRITES) { + av_log(avctx, AV_LOG_ERROR, + "Sprite ID %d is too high.\n", sprite_id); + return AVERROR_INVALIDDATA; + } + if (c->sprites[sprite_id].active) { + av_log(avctx, AV_LOG_ERROR, + "Sprite ID %d is a duplicate.\n", sprite_id); + return AVERROR_INVALIDDATA; + } + + c->sprites[sprite_id].flags = bytestream_get_be16(&buf); + size = bytestream_get_be32(&buf); + if (size < 14) { + av_log(avctx, AV_LOG_ERROR, + "Sprite only has %d bytes of data.\n", size); + return AVERROR_INVALIDDATA; + } + size -= 14; + c->sprites[sprite_id].size = size; + c->sprites[sprite_id].owner_frame = frame_id; + c->sprites[sprite_id].start_frame = bytestream_get_be16(&buf); + c->sprites[sprite_id].end_frame = bytestream_get_be16(&buf); + buf += 2; + + if (size > buf_size || buf + size > eod) + return AVERROR_INVALIDDATA; + + av_fast_padded_malloc(&c->sprites[sprite_id].data, &c->sprites[sprite_id].alloc_size, size); + if (!c->sprites[sprite_id].data) + return AVERROR(ENOMEM); + + c->sprites[sprite_id].active = 1; + + bytestream_get_buffer(&buf, c->sprites[sprite_id].data, size); + } + + /* render any embedded sprites */ + while (buf < eod) { + uint32_t tag, size; + if (buf + 8 > eod) { + av_log(avctx, AV_LOG_WARNING, "Ran (seriously) out of data for embedded sprites.\n"); + return AVERROR_INVALIDDATA; + } + tag = bytestream_get_be32(&buf); + size = bytestream_get_be32(&buf); + if (tag == MKBETAG('D', 'i', 'f', 'f')) { + uint16_t diff_count; + if (buf + 10 > eod) { + av_log(avctx, AV_LOG_WARNING, "Ran (seriously) out of data for Diff frame.\n"); + return AVERROR_INVALIDDATA; + } + diff_count = bytestream_get_be16(&buf); + buf += 8; /* clip rect? */ + for (int i = 0; i < diff_count; i++) { + int16_t top, left; + uint16_t diff_size, width, height; + + if (buf + 16 > eod) { + av_log(avctx, AV_LOG_WARNING, "Ran (seriously) out of data for Diff frame header.\n"); + return AVERROR_INVALIDDATA; + } + + top = bytestream_get_be16(&buf); + left = bytestream_get_be16(&buf); + buf += 4; /* bottom, right */ + diff_size = bytestream_get_be32(&buf); + width = bytestream_get_be16(&buf); + height = bytestream_get_be16(&buf); + if (diff_size < 8 || diff_size - 4 > eod - buf) { + av_log(avctx, AV_LOG_WARNING, "Ran (seriously) out of data for Diff frame data.\n"); + return AVERROR_INVALIDDATA; + } + if (cdtoons_render_sprite(avctx, buf + 4, diff_size - 8, + left, top, width, height)) { + av_log(avctx, AV_LOG_WARNING, "Ran beyond end of sprite while rendering.\n"); + } + buf += diff_size - 4; + } + saw_embedded_sprites = 1; + } else { + /* we don't care about any other entries */ + if (size < 8 || size - 8 > eod - buf) { + av_log(avctx, AV_LOG_WARNING, "Ran out of data for ignored entry (size %X, %d left).\n", size, (int)(eod - buf)); + return AVERROR_INVALIDDATA; + } + buf += (size - 8); + } + } + + /* was an intra frame? */ + if (saw_embedded_sprites) + goto done; + + /* render any referenced sprites */ + buf = avpkt->data + CDTOONS_HEADER_SIZE; + eod = avpkt->data + sprite_offset; + for (int i = 0; i < referenced_count; i++) { + const uint8_t *block_data; + uint16_t sprite_id, width, height; + int16_t top, left, right; + + if (buf + 10 > eod) { + av_log(avctx, AV_LOG_WARNING, "Ran (seriously) out of data when rendering.\n"); + return AVERROR_INVALIDDATA; + } + + sprite_id = bytestream_get_be16(&buf); + top = bytestream_get_be16(&buf); + left = bytestream_get_be16(&buf); + buf += 2; /* bottom */ + right = bytestream_get_be16(&buf); + + if ((i == 0) && (sprite_id == 0)) { + /* clear background */ + memset(c->frame->data[0], background_color, + c->frame->linesize[0] * avctx->height); + } + + if (!right) + continue; + if (sprite_id >= CDTOONS_MAX_SPRITES) { + av_log(avctx, AV_LOG_ERROR, + "Sprite ID %d is too high.\n", sprite_id); + return AVERROR_INVALIDDATA; + } + + block_data = c->sprites[sprite_id].data; + if (!c->sprites[sprite_id].active) { + /* this can happen when seeking around */ + av_log(avctx, AV_LOG_WARNING, "Sprite %d is missing.\n", sprite_id); + continue; + } + if (c->sprites[sprite_id].size < 14) { + av_log(avctx, AV_LOG_ERROR, "Sprite %d is too small.\n", sprite_id); + continue; + } + + height = bytestream_get_be16(&block_data); + width = bytestream_get_be16(&block_data); + block_data += 10; + if (cdtoons_render_sprite(avctx, block_data, + c->sprites[sprite_id].size - 14, + left, top, width, height)) { + av_log(avctx, AV_LOG_WARNING, "Ran beyond end of sprite while rendering.\n"); + } + } + + if (palette_id && (palette_id != c->last_pal_id)) { + if (palette_id >= CDTOONS_MAX_SPRITES) { + av_log(avctx, AV_LOG_ERROR, + "Palette ID %d is too high.\n", palette_id); + return AVERROR_INVALIDDATA; + } + if (!c->sprites[palette_id].active) { + /* this can happen when seeking around */ + av_log(avctx, AV_LOG_WARNING, + "Palette ID %d is missing.\n", palette_id); + goto done; + } + if (c->sprites[palette_id].size != 256 * 2 * 3) { + av_log(avctx, AV_LOG_ERROR, + "Palette ID %d is wrong size (%d).\n", + palette_id, c->sprites[palette_id].size); + return AVERROR_INVALIDDATA; + } + c->last_pal_id = palette_id; + if (!palette_set) { + uint8_t *palette_data = c->sprites[palette_id].data; + for (int i = 0; i < 256; i++) { + /* QuickTime-ish palette: 16-bit RGB components */ + unsigned r, g, b; + r = *palette_data; + g = *(palette_data + 2); + b = *(palette_data + 4); + c->pal[i] = (0xFFU << 24) | (r << 16) | (g << 8) | b; + palette_data += 6; + } + /* first palette entry indicates transparency */ + c->pal[0] = 0; + c->frame->palette_has_changed = 1; + } + } + +done: + /* discard outdated blocks */ + for (int i = 0; i < CDTOONS_MAX_SPRITES; i++) { + if (c->sprites[i].end_frame > frame_id) + continue; + c->sprites[i].active = 0; + } + + memcpy(c->frame->data[1], c->pal, AVPALETTE_SIZE); + + if ((ret = av_frame_ref(data, c->frame)) < 0) + return ret; + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int cdtoons_decode_init(AVCodecContext *avctx) +{ + CDToonsContext *c = avctx->priv_data; + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + c->last_pal_id = 0; + c->frame = av_frame_alloc(); + if (!c->frame) + return AVERROR(ENOMEM); + + return 0; +} + +static void cdtoons_flush(AVCodecContext *avctx) +{ + CDToonsContext *c = avctx->priv_data; + + c->last_pal_id = 0; + for (int i = 0; i < CDTOONS_MAX_SPRITES; i++) + c->sprites[i].active = 0; +} + +static av_cold int cdtoons_decode_end(AVCodecContext *avctx) +{ + CDToonsContext *c = avctx->priv_data; + + for (int i = 0; i < CDTOONS_MAX_SPRITES; i++) { + av_freep(&c->sprites[i].data); + c->sprites[i].active = 0; + } + + av_frame_free(&c->frame); + + return 0; +} + +AVCodec ff_cdtoons_decoder = { + .name = "cdtoons", + .long_name = NULL_IF_CONFIG_SMALL("CDToons video"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CDTOONS, + .priv_data_size = sizeof(CDToonsContext), + .init = cdtoons_decode_init, + .close = cdtoons_decode_end, + .decode = cdtoons_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, + .flush = cdtoons_flush, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff -Nru ffmpeg-4.2.2/libavcodec/cdxl.c ffmpeg-4.4/libavcodec/cdxl.c --- ffmpeg-4.2.2/libavcodec/cdxl.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cdxl.c 2021-04-08 21:28:39.000000000 +0000 @@ -43,6 +43,7 @@ typedef struct CDXLVideoContext { AVCodecContext *avctx; int bpp; + int type; int format; int padded_bits; const uint8_t *palette; @@ -65,14 +66,19 @@ static void import_palette(CDXLVideoContext *c, uint32_t *new_palette) { - int i; - - for (i = 0; i < c->palette_size / 2; i++) { - unsigned rgb = AV_RB16(&c->palette[i * 2]); - unsigned r = ((rgb >> 8) & 0xF) * 0x11; - unsigned g = ((rgb >> 4) & 0xF) * 0x11; - unsigned b = (rgb & 0xF) * 0x11; - AV_WN32(&new_palette[i], (0xFFU << 24) | (r << 16) | (g << 8) | b); + if (c->type == 1) { + for (int i = 0; i < c->palette_size / 2; i++) { + unsigned rgb = AV_RB16(&c->palette[i * 2]); + unsigned r = ((rgb >> 8) & 0xF) * 0x11; + unsigned g = ((rgb >> 4) & 0xF) * 0x11; + unsigned b = (rgb & 0xF) * 0x11; + AV_WN32(&new_palette[i], (0xFFU << 24) | (r << 16) | (g << 8) | b); + } + } else { + for (int i = 0; i < c->palette_size / 3; i++) { + unsigned rgb = AV_RB24(&c->palette[i * 3]); + AV_WN32(&new_palette[i], (0xFFU << 24) | rgb); + } } } @@ -246,6 +252,7 @@ if (buf_size < 32) return AVERROR_INVALIDDATA; + c->type = buf[0]; encoding = buf[1] & 7; c->format = buf[1] & 0xE0; w = AV_RB16(&buf[14]); @@ -256,7 +263,11 @@ c->video = c->palette + c->palette_size; c->video_size = buf_size - c->palette_size - 32; - if (c->palette_size > 512) + if (c->type > 1) + return AVERROR_INVALIDDATA; + if (c->type == 1 && c->palette_size > 512) + return AVERROR_INVALIDDATA; + if (c->type == 0 && c->palette_size > 768) return AVERROR_INVALIDDATA; if (buf_size < c->palette_size + 32) return AVERROR_INVALIDDATA; @@ -295,6 +306,7 @@ if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; if (encoding) { av_fast_padded_malloc(&c->new_video, &c->new_video_size, @@ -334,4 +346,5 @@ .close = cdxl_decode_end, .decode = cdxl_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/celp_filters.c ffmpeg-4.4/libavcodec/celp_filters.c --- ffmpeg-4.2.2/libavcodec/celp_filters.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/celp_filters.c 2021-02-20 20:27:47.000000000 +0000 @@ -65,11 +65,11 @@ int i,n; for (n = 0; n < buffer_length; n++) { - int sum = -rounder, sum1; + int sum = rounder, sum1; for (i = 1; i <= filter_length; i++) - sum += (unsigned)(filter_coeffs[i-1] * out[n-i]); + sum -= (unsigned)(filter_coeffs[i-1] * out[n-i]); - sum1 = ((-sum >> 12) + in[n]) >> shift; + sum1 = ((sum >> 12) + in[n]) >> shift; sum = av_clip_int16(sum1); if (stop_on_overflow && sum != sum1) diff -Nru ffmpeg-4.2.2/libavcodec/celp_math.c ffmpeg-4.4/libavcodec/celp_math.c --- ffmpeg-4.2.2/libavcodec/celp_math.c 2016-03-29 02:25:12.000000000 +0000 +++ ffmpeg-4.4/libavcodec/celp_math.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,7 @@ #include "celp_math.h" #include "libavutil/common.h" +#ifdef G729_BITEXACT static const uint16_t exp2a[]= { 0, 1435, 2901, 4400, 5931, 7496, 9096, 10730, @@ -54,6 +55,7 @@ result= (result<<3) + ((result*exp2b[(power>>5)&31])>>17); return result + ((result*(power&31)*89)>>22); } +#endif /** * Table used to compute log2(x) diff -Nru ffmpeg-4.2.2/libavcodec/cfhd.c ffmpeg-4.4/libavcodec/cfhd.c --- ffmpeg-4.2.2/libavcodec/cfhd.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cfhd.c 2021-04-08 21:28:39.000000000 +0000 @@ -40,31 +40,33 @@ #define ALPHA_COMPAND_DC_OFFSET 256 #define ALPHA_COMPAND_GAIN 9400 -enum CFHDParam { - ChannelCount = 12, - SubbandCount = 14, - ImageWidth = 20, - ImageHeight = 21, - LowpassPrecision = 35, - SubbandNumber = 48, - Quantization = 53, - ChannelNumber = 62, - SampleFlags = 68, - BitsPerComponent = 101, - ChannelWidth = 104, - ChannelHeight = 105, - PrescaleShift = 109, -}; - - - static av_cold int cfhd_init(AVCodecContext *avctx) { CFHDContext *s = avctx->priv_data; - avctx->bits_per_raw_sample = 10; s->avctx = avctx; + for (int i = 0; i < 64; i++) { + int val = i; + + if (val >= 40) { + if (val >= 54) { + val -= 54; + val <<= 2; + val += 54; + } + + val -= 40; + val <<= 2; + val += 40; + } + + s->lut[0][i] = val; + } + + for (int i = 0; i < 256; i++) + s->lut[1][i] = i + ((768LL * i * i * i) / (256 * 256 * 256)); + return ff_cfhd_init_vlcs(s); } @@ -86,32 +88,28 @@ { s->coded_width = 0; s->coded_height = 0; + s->coded_format = AV_PIX_FMT_YUV422P10; s->cropped_height = 0; s->bpc = 10; - s->channel_cnt = 4; + s->channel_cnt = 3; s->subband_cnt = SUBBAND_COUNT; s->channel_num = 0; s->lowpass_precision = 16; s->quantisation = 1; - s->wavelet_depth = 3; - s->pshift = 1; s->codebook = 0; s->difference_coding = 0; - s->progressive = 0; + s->frame_type = 0; + s->sample_type = 0; + if (s->transform_type != 2) + s->transform_type = -1; init_plane_defaults(s); init_peak_table_defaults(s); } -/* TODO: merge with VLC tables or use LUT */ -static inline int dequant_and_decompand(int level, int quantisation, int codebook) +static inline int dequant_and_decompand(CFHDContext *s, int level, int quantisation, int codebook) { if (codebook == 0 || codebook == 1) { - int64_t abslevel = abs(level); - if (level < 264) - return (abslevel + ((768 * abslevel * abslevel * abslevel) / (255 * 255 * 255))) * - FFSIGN(level) * quantisation; - else - return level * quantisation; + return s->lut[codebook][abs(level)] * FFSIGN(level) * quantisation; } else return level * quantisation; } @@ -150,46 +148,47 @@ } } -static inline void filter(int16_t *output, ptrdiff_t out_stride, - int16_t *low, ptrdiff_t low_stride, - int16_t *high, ptrdiff_t high_stride, - int len, int clip) +static inline void process_bayer(AVFrame *frame, int bpc) { - int16_t tmp; - int i; - - for (i = 0; i < len; i++) { - if (i == 0) { - tmp = (11*low[0*low_stride] - 4*low[1*low_stride] + low[2*low_stride] + 4) >> 3; - output[(2*i+0)*out_stride] = (tmp + high[0*high_stride]) >> 1; - if (clip) - output[(2*i+0)*out_stride] = av_clip_uintp2_c(output[(2*i+0)*out_stride], clip); - - tmp = ( 5*low[0*low_stride] + 4*low[1*low_stride] - low[2*low_stride] + 4) >> 3; - output[(2*i+1)*out_stride] = (tmp - high[0*high_stride]) >> 1; - if (clip) - output[(2*i+1)*out_stride] = av_clip_uintp2_c(output[(2*i+1)*out_stride], clip); - } else if (i == len-1) { - tmp = ( 5*low[i*low_stride] + 4*low[(i-1)*low_stride] - low[(i-2)*low_stride] + 4) >> 3; - output[(2*i+0)*out_stride] = (tmp + high[i*high_stride]) >> 1; - if (clip) - output[(2*i+0)*out_stride] = av_clip_uintp2_c(output[(2*i+0)*out_stride], clip); - - tmp = (11*low[i*low_stride] - 4*low[(i-1)*low_stride] + low[(i-2)*low_stride] + 4) >> 3; - output[(2*i+1)*out_stride] = (tmp - high[i*high_stride]) >> 1; - if (clip) - output[(2*i+1)*out_stride] = av_clip_uintp2_c(output[(2*i+1)*out_stride], clip); - } else { - tmp = (low[(i-1)*low_stride] - low[(i+1)*low_stride] + 4) >> 3; - output[(2*i+0)*out_stride] = (tmp + low[i*low_stride] + high[i*high_stride]) >> 1; - if (clip) - output[(2*i+0)*out_stride] = av_clip_uintp2_c(output[(2*i+0)*out_stride], clip); - - tmp = (low[(i+1)*low_stride] - low[(i-1)*low_stride] + 4) >> 3; - output[(2*i+1)*out_stride] = (tmp + low[i*low_stride] - high[i*high_stride]) >> 1; - if (clip) - output[(2*i+1)*out_stride] = av_clip_uintp2_c(output[(2*i+1)*out_stride], clip); + const int linesize = frame->linesize[0]; + uint16_t *r = (uint16_t *)frame->data[0]; + uint16_t *g1 = (uint16_t *)(frame->data[0] + 2); + uint16_t *g2 = (uint16_t *)(frame->data[0] + frame->linesize[0]); + uint16_t *b = (uint16_t *)(frame->data[0] + frame->linesize[0] + 2); + const int mid = 1 << (bpc - 1); + const int factor = 1 << (16 - bpc); + + for (int y = 0; y < frame->height >> 1; y++) { + for (int x = 0; x < frame->width; x += 2) { + int R, G1, G2, B; + int g, rg, bg, gd; + + g = r[x]; + rg = g1[x]; + bg = g2[x]; + gd = b[x]; + gd -= mid; + + R = (rg - mid) * 2 + g; + G1 = g + gd; + G2 = g - gd; + B = (bg - mid) * 2 + g; + + R = av_clip_uintp2(R * factor, 16); + G1 = av_clip_uintp2(G1 * factor, 16); + G2 = av_clip_uintp2(G2 * factor, 16); + B = av_clip_uintp2(B * factor, 16); + + r[x] = R; + g1[x] = G1; + g2[x] = G2; + b[x] = B; } + + r += linesize; + g1 += linesize; + g2 += linesize; + b += linesize; } } @@ -205,23 +204,16 @@ output[i + linesize] = av_clip_uintp2(odd, 10); } } -static void horiz_filter(int16_t *output, int16_t *low, int16_t *high, - int width) -{ - filter(output, 1, low, 1, high, 1, width, 0); -} -static void horiz_filter_clip(int16_t *output, int16_t *low, int16_t *high, - int width, int clip) +static inline void inverse_temporal_filter(int16_t *low, int16_t *high, int width) { - filter(output, 1, low, 1, high, 1, width, clip); -} + for (int i = 0; i < width; i++) { + int even = (low[i] - high[i]) / 2; + int odd = (low[i] + high[i]) / 2; -static void vert_filter(int16_t *output, ptrdiff_t out_stride, - int16_t *low, ptrdiff_t low_stride, - int16_t *high, ptrdiff_t high_stride, int len) -{ - filter(output, out_stride, low, low_stride, high, high_stride, len, 0); + low[i] = even; + high[i] = odd; + } } static void free_buffers(CFHDContext *s) @@ -229,23 +221,32 @@ int i, j; for (i = 0; i < FF_ARRAY_ELEMS(s->plane); i++) { + Plane *p = &s->plane[i]; av_freep(&s->plane[i].idwt_buf); av_freep(&s->plane[i].idwt_tmp); + s->plane[i].idwt_size = 0; - for (j = 0; j < 9; j++) + for (j = 0; j < SUBBAND_COUNT_3D; j++) s->plane[i].subband[j] = NULL; - for (j = 0; j < 8; j++) + for (j = 0; j < 10; j++) s->plane[i].l_h[j] = NULL; + + for (j = 0; j < DWT_LEVELS_3D; j++) + p->band[j][0].read_ok = + p->band[j][1].read_ok = + p->band[j][2].read_ok = + p->band[j][3].read_ok = 0; } s->a_height = 0; s->a_width = 0; + s->a_transform_type = INT_MIN; } static int alloc_buffers(AVCodecContext *avctx) { CFHDContext *s = avctx->priv_data; - int i, j, ret, planes; + int i, j, ret, planes, bayer = 0; int chroma_x_shift, chroma_y_shift; unsigned k; @@ -253,34 +254,53 @@ return ret; avctx->pix_fmt = s->coded_format; + ff_cfhddsp_init(&s->dsp, s->bpc, avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16); + if ((ret = av_pix_fmt_get_chroma_sub_sample(s->coded_format, &chroma_x_shift, &chroma_y_shift)) < 0) return ret; planes = av_pix_fmt_count_planes(s->coded_format); + if (s->coded_format == AV_PIX_FMT_BAYER_RGGB16) { + planes = 4; + chroma_x_shift = 1; + chroma_y_shift = 1; + bayer = 1; + } for (i = 0; i < planes; i++) { int w8, h8, w4, h4, w2, h2; - int width = i ? avctx->width >> chroma_x_shift : avctx->width; - int height = i ? avctx->height >> chroma_y_shift : avctx->height; - ptrdiff_t stride = FFALIGN(width / 8, 8) * 8; - if (chroma_y_shift) + int width = (i || bayer) ? s->coded_width >> chroma_x_shift : s->coded_width; + int height = (i || bayer) ? s->coded_height >> chroma_y_shift : s->coded_height; + ptrdiff_t stride = (FFALIGN(width / 8, 8) + 64) * 8; + + if (chroma_y_shift && !bayer) height = FFALIGN(height / 8, 2) * 8; s->plane[i].width = width; s->plane[i].height = height; s->plane[i].stride = stride; - w8 = FFALIGN(s->plane[i].width / 8, 8); - h8 = height / 8; + w8 = FFALIGN(s->plane[i].width / 8, 8) + 64; + h8 = FFALIGN(height, 8) / 8; w4 = w8 * 2; h4 = h8 * 2; w2 = w4 * 2; h2 = h4 * 2; - s->plane[i].idwt_buf = - av_mallocz_array(height * stride, sizeof(*s->plane[i].idwt_buf)); - s->plane[i].idwt_tmp = - av_malloc_array(height * stride, sizeof(*s->plane[i].idwt_tmp)); + if (s->transform_type == 0) { + s->plane[i].idwt_size = FFALIGN(height, 8) * stride; + s->plane[i].idwt_buf = + av_mallocz_array(s->plane[i].idwt_size, sizeof(*s->plane[i].idwt_buf)); + s->plane[i].idwt_tmp = + av_malloc_array(s->plane[i].idwt_size, sizeof(*s->plane[i].idwt_tmp)); + } else { + s->plane[i].idwt_size = FFALIGN(height, 8) * stride * 2; + s->plane[i].idwt_buf = + av_mallocz_array(s->plane[i].idwt_size, sizeof(*s->plane[i].idwt_buf)); + s->plane[i].idwt_tmp = + av_malloc_array(s->plane[i].idwt_size, sizeof(*s->plane[i].idwt_tmp)); + } + if (!s->plane[i].idwt_buf || !s->plane[i].idwt_tmp) return AVERROR(ENOMEM); @@ -291,14 +311,39 @@ s->plane[i].subband[4] = s->plane[i].idwt_buf + 2 * w4 * h4; s->plane[i].subband[5] = s->plane[i].idwt_buf + 1 * w4 * h4; s->plane[i].subband[6] = s->plane[i].idwt_buf + 3 * w4 * h4; - s->plane[i].subband[7] = s->plane[i].idwt_buf + 2 * w2 * h2; - s->plane[i].subband[8] = s->plane[i].idwt_buf + 1 * w2 * h2; - s->plane[i].subband[9] = s->plane[i].idwt_buf + 3 * w2 * h2; - - for (j = 0; j < DWT_LEVELS; j++) { - for (k = 0; k < FF_ARRAY_ELEMS(s->plane[i].band[j]); k++) { - s->plane[i].band[j][k].a_width = w8 << j; - s->plane[i].band[j][k].a_height = h8 << j; + if (s->transform_type == 0) { + s->plane[i].subband[7] = s->plane[i].idwt_buf + 2 * w2 * h2; + s->plane[i].subband[8] = s->plane[i].idwt_buf + 1 * w2 * h2; + s->plane[i].subband[9] = s->plane[i].idwt_buf + 3 * w2 * h2; + } else { + int16_t *frame2 = + s->plane[i].subband[7] = s->plane[i].idwt_buf + 4 * w2 * h2; + s->plane[i].subband[8] = frame2 + 2 * w4 * h4; + s->plane[i].subband[9] = frame2 + 1 * w4 * h4; + s->plane[i].subband[10] = frame2 + 3 * w4 * h4; + s->plane[i].subband[11] = frame2 + 2 * w2 * h2; + s->plane[i].subband[12] = frame2 + 1 * w2 * h2; + s->plane[i].subband[13] = frame2 + 3 * w2 * h2; + s->plane[i].subband[14] = s->plane[i].idwt_buf + 2 * w2 * h2; + s->plane[i].subband[15] = s->plane[i].idwt_buf + 1 * w2 * h2; + s->plane[i].subband[16] = s->plane[i].idwt_buf + 3 * w2 * h2; + } + + if (s->transform_type == 0) { + for (j = 0; j < DWT_LEVELS; j++) { + for (k = 0; k < FF_ARRAY_ELEMS(s->plane[i].band[j]); k++) { + s->plane[i].band[j][k].a_width = w8 << j; + s->plane[i].band[j][k].a_height = h8 << j; + } + } + } else { + for (j = 0; j < DWT_LEVELS_3D; j++) { + int t = j < 1 ? 0 : (j < 3 ? 1 : 2); + + for (k = 0; k < FF_ARRAY_ELEMS(s->plane[i].band[j]); k++) { + s->plane[i].band[j][k].a_width = w8 << t; + s->plane[i].band[j][k].a_height = h8 << t; + } } } @@ -311,8 +356,15 @@ // s->plane[i].l_h[5] = ll1; s->plane[i].l_h[6] = s->plane[i].idwt_tmp; s->plane[i].l_h[7] = s->plane[i].idwt_tmp + 2 * w2 * h2; + if (s->transform_type != 0) { + int16_t *frame2 = s->plane[i].idwt_tmp + 4 * w2 * h2; + + s->plane[i].l_h[8] = frame2; + s->plane[i].l_h[9] = frame2 + 2 * w2 * h2; + } } + s->a_transform_type = s->transform_type; s->a_height = s->coded_height; s->a_width = s->coded_width; s->a_format = s->coded_format; @@ -324,19 +376,19 @@ AVPacket *avpkt) { CFHDContext *s = avctx->priv_data; + CFHDDSPContext *dsp = &s->dsp; GetByteContext gb; ThreadFrame frame = { .f = data }; AVFrame *pic = data; - int ret = 0, i, j, planes, plane, got_buffer = 0; + int ret = 0, i, j, plane, got_buffer = 0; int16_t *coeff_data; - s->coded_format = AV_PIX_FMT_YUV422P10; init_frame_defaults(s); - planes = av_pix_fmt_count_planes(s->coded_format); + s->planes = av_pix_fmt_count_planes(s->coded_format); bytestream2_init(&gb, avpkt->data, avpkt->size); - while (bytestream2_get_bytes_left(&gb) > 4) { + while (bytestream2_get_bytes_left(&gb) >= 4) { /* Bit weird but implement the tag parsing as the spec says */ uint16_t tagu = bytestream2_get_be16(&gb); int16_t tag = (int16_t)tagu; @@ -347,214 +399,273 @@ if (abs_tag8 >= 0x60 && abs_tag8 <= 0x6f) { av_log(avctx, AV_LOG_DEBUG, "large len %x\n", ((tagu & 0xff) << 16) | data); } else if (tag == SampleFlags) { - av_log(avctx, AV_LOG_DEBUG, "Progressive?%"PRIu16"\n", data); + av_log(avctx, AV_LOG_DEBUG, "Progressive? %"PRIu16"\n", data); s->progressive = data & 0x0001; + } else if (tag == FrameType) { + s->frame_type = data; + av_log(avctx, AV_LOG_DEBUG, "Frame type %"PRIu16"\n", data); + } else if (abstag == VersionMajor) { + av_log(avctx, AV_LOG_DEBUG, "Version major %"PRIu16"\n", data); + } else if (abstag == VersionMinor) { + av_log(avctx, AV_LOG_DEBUG, "Version minor %"PRIu16"\n", data); + } else if (abstag == VersionRevision) { + av_log(avctx, AV_LOG_DEBUG, "Version revision %"PRIu16"\n", data); + } else if (abstag == VersionEdit) { + av_log(avctx, AV_LOG_DEBUG, "Version edit %"PRIu16"\n", data); + } else if (abstag == Version) { + av_log(avctx, AV_LOG_DEBUG, "Version %"PRIu16"\n", data); } else if (tag == ImageWidth) { av_log(avctx, AV_LOG_DEBUG, "Width %"PRIu16"\n", data); s->coded_width = data; } else if (tag == ImageHeight) { av_log(avctx, AV_LOG_DEBUG, "Height %"PRIu16"\n", data); s->coded_height = data; - } else if (tag == 101) { - av_log(avctx, AV_LOG_DEBUG, "Bits per component: %"PRIu16"\n", data); - if (data < 1 || data > 31) { - av_log(avctx, AV_LOG_ERROR, "Bits per component %d is invalid\n", data); - ret = AVERROR(EINVAL); - break; - } - s->bpc = data; } else if (tag == ChannelCount) { av_log(avctx, AV_LOG_DEBUG, "Channel Count: %"PRIu16"\n", data); s->channel_cnt = data; if (data > 4) { av_log(avctx, AV_LOG_ERROR, "Channel Count of %"PRIu16" is unsupported\n", data); ret = AVERROR_PATCHWELCOME; - break; + goto end; } } else if (tag == SubbandCount) { av_log(avctx, AV_LOG_DEBUG, "Subband Count: %"PRIu16"\n", data); - if (data != SUBBAND_COUNT) { + if (data != SUBBAND_COUNT && data != SUBBAND_COUNT_3D) { av_log(avctx, AV_LOG_ERROR, "Subband Count of %"PRIu16" is unsupported\n", data); ret = AVERROR_PATCHWELCOME; - break; + goto end; } } else if (tag == ChannelNumber) { s->channel_num = data; av_log(avctx, AV_LOG_DEBUG, "Channel number %"PRIu16"\n", data); - if (s->channel_num >= planes) { + if (s->channel_num >= s->planes) { av_log(avctx, AV_LOG_ERROR, "Invalid channel number\n"); ret = AVERROR(EINVAL); - break; + goto end; } init_plane_defaults(s); } else if (tag == SubbandNumber) { - if (s->subband_num != 0 && data == 1) // hack + if (s->subband_num != 0 && data == 1 && (s->transform_type == 0 || s->transform_type == 2)) // hack s->level++; av_log(avctx, AV_LOG_DEBUG, "Subband number %"PRIu16"\n", data); s->subband_num = data; - if (s->level >= DWT_LEVELS) { + if ((s->transform_type == 0 && s->level >= DWT_LEVELS) || + (s->transform_type == 2 && s->level >= DWT_LEVELS_3D)) { av_log(avctx, AV_LOG_ERROR, "Invalid level\n"); ret = AVERROR(EINVAL); - break; + goto end; } if (s->subband_num > 3) { av_log(avctx, AV_LOG_ERROR, "Invalid subband number\n"); ret = AVERROR(EINVAL); - break; + goto end; } - } else if (tag == 51) { + } else if (tag == SubbandBand) { av_log(avctx, AV_LOG_DEBUG, "Subband number actual %"PRIu16"\n", data); - s->subband_num_actual = data; - if (s->subband_num_actual >= 10) { + if ((s->transform_type == 0 && data >= SUBBAND_COUNT) || + (s->transform_type == 2 && data >= SUBBAND_COUNT_3D && data != 255)) { av_log(avctx, AV_LOG_ERROR, "Invalid subband number actual\n"); ret = AVERROR(EINVAL); - break; + goto end; } + if (s->transform_type == 0 || s->transform_type == 2) + s->subband_num_actual = data; + else + av_log(avctx, AV_LOG_WARNING, "Ignoring subband num actual %"PRIu16"\n", data); } else if (tag == LowpassPrecision) av_log(avctx, AV_LOG_DEBUG, "Lowpass precision bits: %"PRIu16"\n", data); else if (tag == Quantization) { s->quantisation = data; av_log(avctx, AV_LOG_DEBUG, "Quantisation: %"PRIu16"\n", data); - } else if (tag == PrescaleShift) { - s->prescale_shift[0] = (data >> 0) & 0x7; - s->prescale_shift[1] = (data >> 3) & 0x7; - s->prescale_shift[2] = (data >> 6) & 0x7; - av_log(avctx, AV_LOG_DEBUG, "Prescale shift (VC-5): %x\n", data); - } else if (tag == 27) { - av_log(avctx, AV_LOG_DEBUG, "Lowpass width %"PRIu16"\n", data); - if (data < 3 || data > s->plane[s->channel_num].band[0][0].a_width) { - av_log(avctx, AV_LOG_ERROR, "Invalid lowpass width\n"); + } else if (tag == PrescaleTable) { + for (i = 0; i < 8; i++) + s->prescale_table[i] = (data >> (14 - i * 2)) & 0x3; + av_log(avctx, AV_LOG_DEBUG, "Prescale table: %x\n", data); + } else if (tag == BandEncoding) { + if (!data || data > 5) { + av_log(avctx, AV_LOG_ERROR, "Invalid band encoding\n"); ret = AVERROR(EINVAL); - break; + goto end; } + s->band_encoding = data; + av_log(avctx, AV_LOG_DEBUG, "Encode Method for Subband %d : %x\n", s->subband_num_actual, data); + } else if (tag == LowpassWidth) { + av_log(avctx, AV_LOG_DEBUG, "Lowpass width %"PRIu16"\n", data); s->plane[s->channel_num].band[0][0].width = data; s->plane[s->channel_num].band[0][0].stride = data; - } else if (tag == 28) { + } else if (tag == LowpassHeight) { av_log(avctx, AV_LOG_DEBUG, "Lowpass height %"PRIu16"\n", data); - if (data < 3 || data > s->plane[s->channel_num].band[0][0].a_height) { - av_log(avctx, AV_LOG_ERROR, "Invalid lowpass height\n"); - ret = AVERROR(EINVAL); - break; - } s->plane[s->channel_num].band[0][0].height = data; - } else if (tag == 1) + } else if (tag == SampleType) { + s->sample_type = data; av_log(avctx, AV_LOG_DEBUG, "Sample type? %"PRIu16"\n", data); - else if (tag == 10) { - if (data != 0) { - avpriv_report_missing_feature(avctx, "Transform type of %"PRIu16, data); + } else if (tag == TransformType) { + if (data > 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid transform type\n"); + ret = AVERROR(EINVAL); + goto end; + } else if (data == 1) { + av_log(avctx, AV_LOG_ERROR, "unsupported transform type\n"); ret = AVERROR_PATCHWELCOME; - break; + goto end; + } + if (s->transform_type == -1) { + s->transform_type = data; + av_log(avctx, AV_LOG_DEBUG, "Transform type %"PRIu16"\n", data); + } else { + av_log(avctx, AV_LOG_DEBUG, "Ignoring additional transform type %"PRIu16"\n", data); } - av_log(avctx, AV_LOG_DEBUG, "Transform-type? %"PRIu16"\n", data); } else if (abstag >= 0x4000 && abstag <= 0x40ff) { if (abstag == 0x4001) s->peak.level = 0; av_log(avctx, AV_LOG_DEBUG, "Small chunk length %d %s\n", data * 4, tag < 0 ? "optional" : "required"); bytestream2_skipu(&gb, data * 4); - } else if (tag == 23) { - av_log(avctx, AV_LOG_DEBUG, "Skip frame\n"); - avpriv_report_missing_feature(avctx, "Skip frame"); - ret = AVERROR_PATCHWELCOME; - break; - } else if (tag == 2) { - av_log(avctx, AV_LOG_DEBUG, "tag=2 header - skipping %i tag/value pairs\n", data); + } else if (tag == FrameIndex) { + av_log(avctx, AV_LOG_DEBUG, "Frame index %"PRIu16"\n", data); + s->frame_index = data; + } else if (tag == SampleIndexTable) { + av_log(avctx, AV_LOG_DEBUG, "Sample index table - skipping %i values\n", data); if (data > bytestream2_get_bytes_left(&gb) / 4) { - av_log(avctx, AV_LOG_ERROR, "too many tag/value pairs (%d)\n", data); + av_log(avctx, AV_LOG_ERROR, "too many values (%d)\n", data); ret = AVERROR_INVALIDDATA; - break; + goto end; } for (i = 0; i < data; i++) { - uint16_t tag2 = bytestream2_get_be16(&gb); - uint16_t val2 = bytestream2_get_be16(&gb); - av_log(avctx, AV_LOG_DEBUG, "Tag/Value = %x %x\n", tag2, val2); + uint32_t offset = bytestream2_get_be32(&gb); + av_log(avctx, AV_LOG_DEBUG, "Offset = %"PRIu32"\n", offset); } - } else if (tag == 41) { + } else if (tag == HighpassWidth) { av_log(avctx, AV_LOG_DEBUG, "Highpass width %i channel %i level %i subband %i\n", data, s->channel_num, s->level, s->subband_num); if (data < 3) { av_log(avctx, AV_LOG_ERROR, "Invalid highpass width\n"); ret = AVERROR(EINVAL); - break; + goto end; } s->plane[s->channel_num].band[s->level][s->subband_num].width = data; s->plane[s->channel_num].band[s->level][s->subband_num].stride = FFALIGN(data, 8); - } else if (tag == 42) { + } else if (tag == HighpassHeight) { av_log(avctx, AV_LOG_DEBUG, "Highpass height %i\n", data); if (data < 3) { av_log(avctx, AV_LOG_ERROR, "Invalid highpass height\n"); ret = AVERROR(EINVAL); - break; + goto end; } s->plane[s->channel_num].band[s->level][s->subband_num].height = data; - } else if (tag == 49) { + } else if (tag == BandWidth) { av_log(avctx, AV_LOG_DEBUG, "Highpass width2 %i\n", data); if (data < 3) { av_log(avctx, AV_LOG_ERROR, "Invalid highpass width2\n"); ret = AVERROR(EINVAL); - break; + goto end; } s->plane[s->channel_num].band[s->level][s->subband_num].width = data; s->plane[s->channel_num].band[s->level][s->subband_num].stride = FFALIGN(data, 8); - } else if (tag == 50) { + } else if (tag == BandHeight) { av_log(avctx, AV_LOG_DEBUG, "Highpass height2 %i\n", data); if (data < 3) { av_log(avctx, AV_LOG_ERROR, "Invalid highpass height2\n"); ret = AVERROR(EINVAL); - break; + goto end; } s->plane[s->channel_num].band[s->level][s->subband_num].height = data; - } else if (tag == 71) { - s->codebook = data; - av_log(avctx, AV_LOG_DEBUG, "Codebook %i\n", s->codebook); - } else if (tag == 72) { + } else if (tag == InputFormat) { + av_log(avctx, AV_LOG_DEBUG, "Input format %i\n", data); + if (s->coded_format == AV_PIX_FMT_NONE || + s->coded_format == AV_PIX_FMT_YUV422P10) { + if (data >= 100 && data <= 105) { + s->coded_format = AV_PIX_FMT_BAYER_RGGB16; + } else if (data >= 122 && data <= 128) { + s->coded_format = AV_PIX_FMT_GBRP12; + } else if (data == 30) { + s->coded_format = AV_PIX_FMT_GBRAP12; + } else { + s->coded_format = AV_PIX_FMT_YUV422P10; + } + s->planes = s->coded_format == AV_PIX_FMT_BAYER_RGGB16 ? 4 : av_pix_fmt_count_planes(s->coded_format); + } + } else if (tag == BandCodingFlags) { s->codebook = data & 0xf; s->difference_coding = (data >> 4) & 1; av_log(avctx, AV_LOG_DEBUG, "Other codebook? %i\n", s->codebook); - } else if (tag == 70) { - av_log(avctx, AV_LOG_DEBUG, "Subsampling or bit-depth flag? %i\n", data); + } else if (tag == Precision) { + av_log(avctx, AV_LOG_DEBUG, "Precision %i\n", data); if (!(data == 10 || data == 12)) { av_log(avctx, AV_LOG_ERROR, "Invalid bits per channel\n"); ret = AVERROR(EINVAL); - break; + goto end; } - s->bpc = data; - } else if (tag == 84) { + avctx->bits_per_raw_sample = s->bpc = data; + } else if (tag == EncodedFormat) { av_log(avctx, AV_LOG_DEBUG, "Sample format? %i\n", data); - if (data == 1) + if (data == 1) { s->coded_format = AV_PIX_FMT_YUV422P10; - else if (data == 3) + } else if (data == 2) { + s->coded_format = AV_PIX_FMT_BAYER_RGGB16; + } else if (data == 3) { s->coded_format = AV_PIX_FMT_GBRP12; - else if (data == 4) + } else if (data == 4) { s->coded_format = AV_PIX_FMT_GBRAP12; - else { + } else { avpriv_report_missing_feature(avctx, "Sample format of %"PRIu16, data); ret = AVERROR_PATCHWELCOME; - break; + goto end; } - planes = av_pix_fmt_count_planes(s->coded_format); - } else if (tag == -85) { + s->planes = data == 2 ? 4 : av_pix_fmt_count_planes(s->coded_format); + } else if (tag == -DisplayHeight) { av_log(avctx, AV_LOG_DEBUG, "Cropped height %"PRIu16"\n", data); s->cropped_height = data; - } else if (tag == -75) { + } else if (tag == -PeakOffsetLow) { s->peak.offset &= ~0xffff; s->peak.offset |= (data & 0xffff); s->peak.base = gb; s->peak.level = 0; - } else if (tag == -76) { + } else if (tag == -PeakOffsetHigh) { s->peak.offset &= 0xffff; s->peak.offset |= (data & 0xffffU)<<16; s->peak.base = gb; s->peak.level = 0; - } else if (tag == -74 && s->peak.offset) { + } else if (tag == -PeakLevel && s->peak.offset) { s->peak.level = data; + if (s->peak.offset < 4 - bytestream2_tell(&s->peak.base) || + s->peak.offset > 4 + bytestream2_get_bytes_left(&s->peak.base) + ) { + ret = AVERROR_INVALIDDATA; + goto end; + } bytestream2_seek(&s->peak.base, s->peak.offset - 4, SEEK_CUR); } else av_log(avctx, AV_LOG_DEBUG, "Unknown tag %i data %x\n", tag, data); - /* Some kind of end of header tag */ - if (tag == 4 && data == 0x1a4a && s->coded_width && s->coded_height && + if (tag == BitstreamMarker && data == 0xf0f && s->coded_format != AV_PIX_FMT_NONE) { + int lowpass_height = s->plane[s->channel_num].band[0][0].height; + int lowpass_width = s->plane[s->channel_num].band[0][0].width; + int factor = s->coded_format == AV_PIX_FMT_BAYER_RGGB16 ? 2 : 1; + + if (s->coded_width) { + s->coded_width *= factor; + } + + if (s->coded_height) { + s->coded_height *= factor; + } + + if (!s->a_width && !s->coded_width) { + s->coded_width = lowpass_width * factor * 8; + } + + if (!s->a_height && !s->coded_height) { + s->coded_height = lowpass_height * factor * 8; + } + + if (s->a_width && !s->coded_width) + s->coded_width = s->a_width; + if (s->a_height && !s->coded_height) + s->coded_height = s->a_height; + if (s->a_width != s->coded_width || s->a_height != s->coded_height || - s->a_format != s->coded_format) { + s->a_format != s->coded_format || + s->transform_type != s->a_transform_type) { free_buffers(s); if ((ret = alloc_buffers(avctx)) < 0) { free_buffers(s); @@ -564,8 +675,12 @@ ret = ff_set_dimensions(avctx, s->coded_width, s->coded_height); if (ret < 0) return ret; - if (s->cropped_height) - avctx->height = s->cropped_height; + if (s->cropped_height) { + unsigned height = s->cropped_height << (avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16); + if (avctx->height < height) + return AVERROR_INVALIDDATA; + avctx->height = height; + } frame.f->width = frame.f->height = 0; @@ -576,15 +691,49 @@ s->coded_height = 0; s->coded_format = AV_PIX_FMT_NONE; got_buffer = 1; + } else if (tag == FrameIndex && data == 1 && s->sample_type == 1 && s->frame_type == 2) { + frame.f->width = + frame.f->height = 0; + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + s->coded_width = 0; + s->coded_height = 0; + s->coded_format = AV_PIX_FMT_NONE; + got_buffer = 1; } + + if (s->subband_num_actual == 255) + goto finish; coeff_data = s->plane[s->channel_num].subband[s->subband_num_actual]; /* Lowpass coefficients */ - if (tag == 4 && data == 0xf0f && s->a_width && s->a_height) { - int lowpass_height = s->plane[s->channel_num].band[0][0].height; - int lowpass_width = s->plane[s->channel_num].band[0][0].width; - int lowpass_a_height = s->plane[s->channel_num].band[0][0].a_height; - int lowpass_a_width = s->plane[s->channel_num].band[0][0].a_width; + if (tag == BitstreamMarker && data == 0xf0f) { + int lowpass_height, lowpass_width, lowpass_a_height, lowpass_a_width; + + if (!s->a_width || !s->a_height) { + ret = AVERROR_INVALIDDATA; + goto end; + } + + lowpass_height = s->plane[s->channel_num].band[0][0].height; + lowpass_width = s->plane[s->channel_num].band[0][0].width; + lowpass_a_height = s->plane[s->channel_num].band[0][0].a_height; + lowpass_a_width = s->plane[s->channel_num].band[0][0].a_width; + + if (lowpass_width < 3 || + lowpass_width > lowpass_a_width) { + av_log(avctx, AV_LOG_ERROR, "Invalid lowpass width\n"); + ret = AVERROR(EINVAL); + goto end; + } + + if (lowpass_height < 3 || + lowpass_height > lowpass_a_height) { + av_log(avctx, AV_LOG_ERROR, "Invalid lowpass height\n"); + ret = AVERROR(EINVAL); + goto end; + } if (!got_buffer) { av_log(avctx, AV_LOG_ERROR, "No end of header tag found\n"); @@ -593,7 +742,7 @@ } if (lowpass_height > lowpass_a_height || lowpass_width > lowpass_a_width || - lowpass_a_width * lowpass_a_height * sizeof(int16_t) > bytestream2_get_bytes_left(&gb)) { + lowpass_width * lowpass_height * sizeof(int16_t) > bytestream2_get_bytes_left(&gb)) { av_log(avctx, AV_LOG_ERROR, "Too many lowpass coefficients\n"); ret = AVERROR(EINVAL); goto end; @@ -617,20 +766,30 @@ lowpass_width * sizeof(*coeff_data)); } + s->plane[s->channel_num].band[0][0].read_ok = 1; + av_log(avctx, AV_LOG_DEBUG, "Lowpass coefficients %d\n", lowpass_width * lowpass_height); } - if (tag == 55 && s->subband_num_actual != 255 && s->a_width && s->a_height) { - int highpass_height = s->plane[s->channel_num].band[s->level][s->subband_num].height; - int highpass_width = s->plane[s->channel_num].band[s->level][s->subband_num].width; - int highpass_a_width = s->plane[s->channel_num].band[s->level][s->subband_num].a_width; - int highpass_a_height = s->plane[s->channel_num].band[s->level][s->subband_num].a_height; - int highpass_stride = s->plane[s->channel_num].band[s->level][s->subband_num].stride; + av_assert0(s->subband_num_actual != 255); + if (tag == BandHeader || tag == BandSecondPass) { + int highpass_height, highpass_width, highpass_a_width, highpass_a_height, highpass_stride, a_expected; int expected; - int a_expected = highpass_a_height * highpass_a_width; int level, run, coeff; int count = 0, bytes; + if (!s->a_width || !s->a_height) { + ret = AVERROR_INVALIDDATA; + goto end; + } + + highpass_height = s->plane[s->channel_num].band[s->level][s->subband_num].height; + highpass_width = s->plane[s->channel_num].band[s->level][s->subband_num].width; + highpass_a_width = s->plane[s->channel_num].band[s->level][s->subband_num].a_width; + highpass_a_height = s->plane[s->channel_num].band[s->level][s->subband_num].a_height; + highpass_stride = s->plane[s->channel_num].band[s->level][s->subband_num].stride; + a_expected = highpass_a_height * highpass_a_width; + if (!got_buffer) { av_log(avctx, AV_LOG_ERROR, "No end of header tag found\n"); ret = AVERROR(EINVAL); @@ -646,9 +805,16 @@ av_log(avctx, AV_LOG_DEBUG, "Start subband coeffs plane %i level %i codebook %i expected %i\n", s->channel_num, s->level, s->codebook, expected); - init_get_bits(&s->gb, gb.buffer, bytestream2_get_bytes_left(&gb) * 8); + ret = init_get_bits8(&s->gb, gb.buffer, bytestream2_get_bytes_left(&gb)); + if (ret < 0) + goto end; { OPEN_READER(re, &s->gb); + + const int lossless = s->band_encoding == 5; + + if (s->codebook == 0 && s->transform_type == 2 && s->subband_num_actual == 7) + s->codebook = 1; if (!s->codebook) { while (1) { UPDATE_CACHE(re, &s->gb); @@ -664,9 +830,21 @@ if (count > expected) break; - coeff = dequant_and_decompand(level, s->quantisation, 0); - for (i = 0; i < run; i++) - *coeff_data++ = coeff; + if (!lossless) + coeff = dequant_and_decompand(s, level, s->quantisation, 0); + else + coeff = level; + if (tag == BandSecondPass) { + const uint16_t q = s->quantisation; + + for (i = 0; i < run; i++) { + *coeff_data |= coeff * 256; + *coeff_data++ *= q; + } + } else { + for (i = 0; i < run; i++) + *coeff_data++ = coeff; + } } } else { while (1) { @@ -683,9 +861,21 @@ if (count > expected) break; - coeff = dequant_and_decompand(level, s->quantisation, s->codebook); - for (i = 0; i < run; i++) - *coeff_data++ = coeff; + if (!lossless) + coeff = dequant_and_decompand(s, level, s->quantisation, s->codebook); + else + coeff = level; + if (tag == BandSecondPass) { + const uint16_t q = s->quantisation; + + for (i = 0; i < run; i++) { + *coeff_data |= coeff * 256; + *coeff_data++ *= q; + } + } else { + for (i = 0; i < run; i++) + *coeff_data++ = coeff; + } } } CLOSE_READER(re, &s->gb); @@ -710,18 +900,23 @@ bytestream2_seek(&gb, bytes, SEEK_CUR); av_log(avctx, AV_LOG_DEBUG, "End subband coeffs %i extra %i\n", count, count - expected); - s->codebook = 0; - - /* Copy last line of coefficients if odd height */ - if (highpass_height & 1) { - memcpy(&coeff_data[highpass_height * highpass_stride], - &coeff_data[(highpass_height - 1) * highpass_stride], - highpass_stride * sizeof(*coeff_data)); - } + s->plane[s->channel_num].band[s->level][s->subband_num].read_ok = 1; +finish: + if (s->subband_num_actual != 255) + s->codebook = 0; } } + s->planes = av_pix_fmt_count_planes(avctx->pix_fmt); + if (avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16) { + s->progressive = 1; + s->planes = 4; + } + + ff_thread_finish_setup(avctx); + if (!s->a_width || !s->a_height || s->a_format == AV_PIX_FMT_NONE || + s->a_transform_type == INT_MIN || s->coded_width || s->coded_height || s->coded_format != AV_PIX_FMT_NONE) { av_log(avctx, AV_LOG_ERROR, "Invalid dimensions\n"); ret = AVERROR(EINVAL); @@ -734,198 +929,470 @@ goto end; } - planes = av_pix_fmt_count_planes(avctx->pix_fmt); - for (plane = 0; plane < planes && !ret; plane++) { - /* level 1 */ - int lowpass_height = s->plane[plane].band[0][0].height; - int lowpass_width = s->plane[plane].band[0][0].width; - int highpass_stride = s->plane[plane].band[0][1].stride; - int act_plane = plane == 1 ? 2 : plane == 2 ? 1 : plane; - int16_t *low, *high, *output, *dst; - - if (lowpass_height > s->plane[plane].band[0][0].a_height || lowpass_width > s->plane[plane].band[0][0].a_width || - !highpass_stride || s->plane[plane].band[0][1].width > s->plane[plane].band[0][1].a_width) { - av_log(avctx, AV_LOG_ERROR, "Invalid plane dimensions\n"); - ret = AVERROR(EINVAL); - goto end; - } - - av_log(avctx, AV_LOG_DEBUG, "Decoding level 1 plane %i %i %i %i\n", plane, lowpass_height, lowpass_width, highpass_stride); - - low = s->plane[plane].subband[0]; - high = s->plane[plane].subband[2]; - output = s->plane[plane].l_h[0]; - for (i = 0; i < lowpass_width; i++) { - vert_filter(output, lowpass_width, low, lowpass_width, high, highpass_stride, lowpass_height); - low++; - high++; - output++; - } - - low = s->plane[plane].subband[1]; - high = s->plane[plane].subband[3]; - output = s->plane[plane].l_h[1]; - - for (i = 0; i < lowpass_width; i++) { - // note the stride of "low" is highpass_stride - vert_filter(output, lowpass_width, low, highpass_stride, high, highpass_stride, lowpass_height); - low++; - high++; - output++; - } - - low = s->plane[plane].l_h[0]; - high = s->plane[plane].l_h[1]; - output = s->plane[plane].subband[0]; - for (i = 0; i < lowpass_height * 2; i++) { - horiz_filter(output, low, high, lowpass_width); - low += lowpass_width; - high += lowpass_width; - output += lowpass_width * 2; + for (plane = 0; plane < s->planes; plane++) { + int o, level; + + for (level = 0; level < (s->transform_type == 0 ? DWT_LEVELS : DWT_LEVELS_3D) ; level++) { + if (s->transform_type == 2) + if (level == 2 || level == 5) + continue; + for (o = !!level; o < 4 ; o++) { + if (!s->plane[plane].band[level][o].read_ok) { + ret = AVERROR_INVALIDDATA; + goto end; + } + } } - if (s->bpc == 12) { + } + + if (s->transform_type == 0 && s->sample_type != 1) { + for (plane = 0; plane < s->planes && !ret; plane++) { + /* level 1 */ + int lowpass_height = s->plane[plane].band[0][0].height; + int output_stride = s->plane[plane].band[0][0].a_width; + int lowpass_width = s->plane[plane].band[0][0].width; + int highpass_stride = s->plane[plane].band[0][1].stride; + int act_plane = plane == 1 ? 2 : plane == 2 ? 1 : plane; + ptrdiff_t dst_linesize; + int16_t *low, *high, *output, *dst; + + if (avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16) { + act_plane = 0; + dst_linesize = pic->linesize[act_plane]; + } else { + dst_linesize = pic->linesize[act_plane] / 2; + } + + if (lowpass_height > s->plane[plane].band[0][0].a_height || lowpass_width > s->plane[plane].band[0][0].a_width || + !highpass_stride || s->plane[plane].band[0][1].width > s->plane[plane].band[0][1].a_width || + lowpass_width < 3 || lowpass_height < 3) { + av_log(avctx, AV_LOG_ERROR, "Invalid plane dimensions\n"); + ret = AVERROR(EINVAL); + goto end; + } + + av_log(avctx, AV_LOG_DEBUG, "Decoding level 1 plane %i %i %i %i\n", plane, lowpass_height, lowpass_width, highpass_stride); + + low = s->plane[plane].subband[0]; + high = s->plane[plane].subband[2]; + output = s->plane[plane].l_h[0]; + dsp->vert_filter(output, output_stride, low, lowpass_width, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].subband[1]; + high = s->plane[plane].subband[3]; + output = s->plane[plane].l_h[1]; + + dsp->vert_filter(output, output_stride, low, highpass_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].l_h[0]; + high = s->plane[plane].l_h[1]; + output = s->plane[plane].subband[0]; + dsp->horiz_filter(output, output_stride, low, output_stride, high, output_stride, lowpass_width, lowpass_height * 2); + if (s->bpc == 12) { + output = s->plane[plane].subband[0]; + for (i = 0; i < lowpass_height * 2; i++) { + for (j = 0; j < lowpass_width * 2; j++) + output[j] *= 4; + + output += output_stride * 2; + } + } + + /* level 2 */ + lowpass_height = s->plane[plane].band[1][1].height; + output_stride = s->plane[plane].band[1][1].a_width; + lowpass_width = s->plane[plane].band[1][1].width; + highpass_stride = s->plane[plane].band[1][1].stride; + + if (lowpass_height > s->plane[plane].band[1][1].a_height || lowpass_width > s->plane[plane].band[1][1].a_width || + !highpass_stride || s->plane[plane].band[1][1].width > s->plane[plane].band[1][1].a_width || + lowpass_width < 3 || lowpass_height < 3) { + av_log(avctx, AV_LOG_ERROR, "Invalid plane dimensions\n"); + ret = AVERROR(EINVAL); + goto end; + } + + av_log(avctx, AV_LOG_DEBUG, "Level 2 plane %i %i %i %i\n", plane, lowpass_height, lowpass_width, highpass_stride); + + low = s->plane[plane].subband[0]; + high = s->plane[plane].subband[5]; + output = s->plane[plane].l_h[3]; + dsp->vert_filter(output, output_stride, low, output_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].subband[4]; + high = s->plane[plane].subband[6]; + output = s->plane[plane].l_h[4]; + dsp->vert_filter(output, output_stride, low, highpass_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].l_h[3]; + high = s->plane[plane].l_h[4]; + output = s->plane[plane].subband[0]; + dsp->horiz_filter(output, output_stride, low, output_stride, high, output_stride, lowpass_width, lowpass_height * 2); + output = s->plane[plane].subband[0]; for (i = 0; i < lowpass_height * 2; i++) { for (j = 0; j < lowpass_width * 2; j++) output[j] *= 4; - output += lowpass_width * 2; + output += output_stride * 2; } - } - /* level 2 */ - lowpass_height = s->plane[plane].band[1][1].height; - lowpass_width = s->plane[plane].band[1][1].width; - highpass_stride = s->plane[plane].band[1][1].stride; + /* level 3 */ + lowpass_height = s->plane[plane].band[2][1].height; + output_stride = s->plane[plane].band[2][1].a_width; + lowpass_width = s->plane[plane].band[2][1].width; + highpass_stride = s->plane[plane].band[2][1].stride; + + if (lowpass_height > s->plane[plane].band[2][1].a_height || lowpass_width > s->plane[plane].band[2][1].a_width || + !highpass_stride || s->plane[plane].band[2][1].width > s->plane[plane].band[2][1].a_width || + lowpass_height < 3 || lowpass_width < 3 || lowpass_width * 2 > s->plane[plane].width) { + av_log(avctx, AV_LOG_ERROR, "Invalid plane dimensions\n"); + ret = AVERROR(EINVAL); + goto end; + } - if (lowpass_height > s->plane[plane].band[1][1].a_height || lowpass_width > s->plane[plane].band[1][1].a_width || - !highpass_stride || s->plane[plane].band[1][1].width > s->plane[plane].band[1][1].a_width) { - av_log(avctx, AV_LOG_ERROR, "Invalid plane dimensions\n"); - ret = AVERROR(EINVAL); - goto end; - } + av_log(avctx, AV_LOG_DEBUG, "Level 3 plane %i %i %i %i\n", plane, lowpass_height, lowpass_width, highpass_stride); + if (s->progressive) { + low = s->plane[plane].subband[0]; + high = s->plane[plane].subband[8]; + output = s->plane[plane].l_h[6]; + dsp->vert_filter(output, output_stride, low, output_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].subband[7]; + high = s->plane[plane].subband[9]; + output = s->plane[plane].l_h[7]; + dsp->vert_filter(output, output_stride, low, highpass_stride, high, highpass_stride, lowpass_width, lowpass_height); + + dst = (int16_t *)pic->data[act_plane]; + if (avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16) { + if (plane & 1) + dst++; + if (plane > 1) + dst += pic->linesize[act_plane] >> 1; + } + low = s->plane[plane].l_h[6]; + high = s->plane[plane].l_h[7]; - av_log(avctx, AV_LOG_DEBUG, "Level 2 plane %i %i %i %i\n", plane, lowpass_height, lowpass_width, highpass_stride); + if (avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16 && + (lowpass_height * 2 > avctx->coded_height / 2 || + lowpass_width * 2 > avctx->coded_width / 2 ) + ) { + ret = AVERROR_INVALIDDATA; + goto end; + } - low = s->plane[plane].subband[0]; - high = s->plane[plane].subband[5]; - output = s->plane[plane].l_h[3]; - for (i = 0; i < lowpass_width; i++) { - vert_filter(output, lowpass_width, low, lowpass_width, high, highpass_stride, lowpass_height); - low++; - high++; - output++; + for (i = 0; i < s->plane[act_plane].height; i++) { + dsp->horiz_filter_clip(dst, low, high, lowpass_width, s->bpc); + if (avctx->pix_fmt == AV_PIX_FMT_GBRAP12 && act_plane == 3) + process_alpha(dst, lowpass_width * 2); + low += output_stride; + high += output_stride; + dst += dst_linesize; + } + } else { + av_log(avctx, AV_LOG_DEBUG, "interlaced frame ? %d", pic->interlaced_frame); + pic->interlaced_frame = 1; + low = s->plane[plane].subband[0]; + high = s->plane[plane].subband[7]; + output = s->plane[plane].l_h[6]; + dsp->horiz_filter(output, output_stride, low, output_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].subband[8]; + high = s->plane[plane].subband[9]; + output = s->plane[plane].l_h[7]; + dsp->horiz_filter(output, output_stride, low, highpass_stride, high, highpass_stride, lowpass_width, lowpass_height); + + dst = (int16_t *)pic->data[act_plane]; + low = s->plane[plane].l_h[6]; + high = s->plane[plane].l_h[7]; + for (i = 0; i < s->plane[act_plane].height / 2; i++) { + interlaced_vertical_filter(dst, low, high, lowpass_width * 2, pic->linesize[act_plane]/2, act_plane); + low += output_stride * 2; + high += output_stride * 2; + dst += pic->linesize[act_plane]; + } + } } + } else if (s->transform_type == 2 && (avctx->internal->is_copy || s->frame_index == 1 || s->sample_type != 1)) { + for (plane = 0; plane < s->planes && !ret; plane++) { + int lowpass_height = s->plane[plane].band[0][0].height; + int output_stride = s->plane[plane].band[0][0].a_width; + int lowpass_width = s->plane[plane].band[0][0].width; + int highpass_stride = s->plane[plane].band[0][1].stride; + int act_plane = plane == 1 ? 2 : plane == 2 ? 1 : plane; + int16_t *low, *high, *output, *dst; + ptrdiff_t dst_linesize; + + if (avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16) { + act_plane = 0; + dst_linesize = pic->linesize[act_plane]; + } else { + dst_linesize = pic->linesize[act_plane] / 2; + } + + if (lowpass_height > s->plane[plane].band[0][0].a_height || lowpass_width > s->plane[plane].band[0][0].a_width || + !highpass_stride || s->plane[plane].band[0][1].width > s->plane[plane].band[0][1].a_width || + lowpass_width < 3 || lowpass_height < 3) { + av_log(avctx, AV_LOG_ERROR, "Invalid plane dimensions\n"); + ret = AVERROR(EINVAL); + goto end; + } - low = s->plane[plane].subband[4]; - high = s->plane[plane].subband[6]; - output = s->plane[plane].l_h[4]; - for (i = 0; i < lowpass_width; i++) { - vert_filter(output, lowpass_width, low, highpass_stride, high, highpass_stride, lowpass_height); - low++; - high++; - output++; - } + av_log(avctx, AV_LOG_DEBUG, "Decoding level 1 plane %i %i %i %i\n", plane, lowpass_height, lowpass_width, highpass_stride); - low = s->plane[plane].l_h[3]; - high = s->plane[plane].l_h[4]; - output = s->plane[plane].subband[0]; - for (i = 0; i < lowpass_height * 2; i++) { - horiz_filter(output, low, high, lowpass_width); - low += lowpass_width; - high += lowpass_width; - output += lowpass_width * 2; - } + low = s->plane[plane].subband[0]; + high = s->plane[plane].subband[2]; + output = s->plane[plane].l_h[0]; + dsp->vert_filter(output, output_stride, low, lowpass_width, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].subband[1]; + high = s->plane[plane].subband[3]; + output = s->plane[plane].l_h[1]; + dsp->vert_filter(output, output_stride, low, highpass_stride, high, highpass_stride, lowpass_width, lowpass_height); - output = s->plane[plane].subband[0]; - for (i = 0; i < lowpass_height * 2; i++) { - for (j = 0; j < lowpass_width * 2; j++) - output[j] *= 4; + low = s->plane[plane].l_h[0]; + high = s->plane[plane].l_h[1]; + output = s->plane[plane].l_h[7]; + dsp->horiz_filter(output, output_stride, low, output_stride, high, output_stride, lowpass_width, lowpass_height * 2); + if (s->bpc == 12) { + output = s->plane[plane].l_h[7]; + for (i = 0; i < lowpass_height * 2; i++) { + for (j = 0; j < lowpass_width * 2; j++) + output[j] *= 4; - output += lowpass_width * 2; - } + output += output_stride * 2; + } + } - /* level 3 */ - lowpass_height = s->plane[plane].band[2][1].height; - lowpass_width = s->plane[plane].band[2][1].width; - highpass_stride = s->plane[plane].band[2][1].stride; + lowpass_height = s->plane[plane].band[1][1].height; + output_stride = s->plane[plane].band[1][1].a_width; + lowpass_width = s->plane[plane].band[1][1].width; + highpass_stride = s->plane[plane].band[1][1].stride; + + if (lowpass_height > s->plane[plane].band[1][1].a_height || lowpass_width > s->plane[plane].band[1][1].a_width || + !highpass_stride || s->plane[plane].band[1][1].width > s->plane[plane].band[1][1].a_width || + lowpass_width < 3 || lowpass_height < 3) { + av_log(avctx, AV_LOG_ERROR, "Invalid plane dimensions\n"); + ret = AVERROR(EINVAL); + goto end; + } - if (lowpass_height > s->plane[plane].band[2][1].a_height || lowpass_width > s->plane[plane].band[2][1].a_width || - !highpass_stride || s->plane[plane].band[2][1].width > s->plane[plane].band[2][1].a_width) { - av_log(avctx, AV_LOG_ERROR, "Invalid plane dimensions\n"); - ret = AVERROR(EINVAL); - goto end; - } + av_log(avctx, AV_LOG_DEBUG, "Level 2 lowpass plane %i %i %i %i\n", plane, lowpass_height, lowpass_width, highpass_stride); - av_log(avctx, AV_LOG_DEBUG, "Level 3 plane %i %i %i %i\n", plane, lowpass_height, lowpass_width, highpass_stride); - if (s->progressive) { - low = s->plane[plane].subband[0]; - high = s->plane[plane].subband[8]; - output = s->plane[plane].l_h[6]; - for (i = 0; i < lowpass_width; i++) { - vert_filter(output, lowpass_width, low, lowpass_width, high, highpass_stride, lowpass_height); - low++; - high++; - output++; - } + low = s->plane[plane].l_h[7]; + high = s->plane[plane].subband[5]; + output = s->plane[plane].l_h[3]; + dsp->vert_filter(output, output_stride, low, output_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].subband[4]; + high = s->plane[plane].subband[6]; + output = s->plane[plane].l_h[4]; + dsp->vert_filter(output, output_stride, low, highpass_stride, high, highpass_stride, lowpass_width, lowpass_height); - low = s->plane[plane].subband[7]; - high = s->plane[plane].subband[9]; + low = s->plane[plane].l_h[3]; + high = s->plane[plane].l_h[4]; output = s->plane[plane].l_h[7]; - for (i = 0; i < lowpass_width; i++) { - vert_filter(output, lowpass_width, low, highpass_stride, high, highpass_stride, lowpass_height); - low++; - high++; - output++; - } + dsp->horiz_filter(output, output_stride, low, output_stride, high, output_stride, lowpass_width, lowpass_height * 2); - dst = (int16_t *)pic->data[act_plane]; - low = s->plane[plane].l_h[6]; - high = s->plane[plane].l_h[7]; + output = s->plane[plane].l_h[7]; for (i = 0; i < lowpass_height * 2; i++) { - horiz_filter_clip(dst, low, high, lowpass_width, s->bpc); - if (avctx->pix_fmt == AV_PIX_FMT_GBRAP12 && act_plane == 3) - process_alpha(dst, lowpass_width * 2); - low += lowpass_width; - high += lowpass_width; - dst += pic->linesize[act_plane] / 2; - } - } else { - av_log(avctx, AV_LOG_DEBUG, "interlaced frame ? %d", pic->interlaced_frame); - pic->interlaced_frame = 1; - low = s->plane[plane].subband[0]; - high = s->plane[plane].subband[7]; - output = s->plane[plane].l_h[6]; - for (i = 0; i < lowpass_height; i++) { - horiz_filter(output, low, high, lowpass_width); - low += lowpass_width; - high += lowpass_width; - output += lowpass_width * 2; + for (j = 0; j < lowpass_width * 2; j++) + output[j] *= 4; + output += output_stride * 2; } - low = s->plane[plane].subband[8]; + low = s->plane[plane].subband[7]; high = s->plane[plane].subband[9]; - output = s->plane[plane].l_h[7]; - for (i = 0; i < lowpass_height; i++) { - horiz_filter(output, low, high, lowpass_width); - low += lowpass_width; - high += lowpass_width; - output += lowpass_width * 2; + output = s->plane[plane].l_h[3]; + dsp->vert_filter(output, output_stride, low, highpass_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].subband[8]; + high = s->plane[plane].subband[10]; + output = s->plane[plane].l_h[4]; + dsp->vert_filter(output, output_stride, low, highpass_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].l_h[3]; + high = s->plane[plane].l_h[4]; + output = s->plane[plane].l_h[9]; + dsp->horiz_filter(output, output_stride, low, output_stride, high, output_stride, lowpass_width, lowpass_height * 2); + + lowpass_height = s->plane[plane].band[4][1].height; + output_stride = s->plane[plane].band[4][1].a_width; + lowpass_width = s->plane[plane].band[4][1].width; + highpass_stride = s->plane[plane].band[4][1].stride; + av_log(avctx, AV_LOG_DEBUG, "temporal level %i %i %i %i\n", plane, lowpass_height, lowpass_width, highpass_stride); + + if (lowpass_height > s->plane[plane].band[4][1].a_height || lowpass_width > s->plane[plane].band[4][1].a_width || + !highpass_stride || s->plane[plane].band[4][1].width > s->plane[plane].band[4][1].a_width || + lowpass_width < 3 || lowpass_height < 3) { + av_log(avctx, AV_LOG_ERROR, "Invalid plane dimensions\n"); + ret = AVERROR(EINVAL); + goto end; } - dst = (int16_t *)pic->data[act_plane]; - low = s->plane[plane].l_h[6]; - high = s->plane[plane].l_h[7]; + low = s->plane[plane].l_h[7]; + high = s->plane[plane].l_h[9]; + output = s->plane[plane].l_h[7]; for (i = 0; i < lowpass_height; i++) { - interlaced_vertical_filter(dst, low, high, lowpass_width * 2, pic->linesize[act_plane]/2, act_plane); - low += lowpass_width * 2; - high += lowpass_width * 2; - dst += pic->linesize[act_plane]; + inverse_temporal_filter(low, high, lowpass_width); + low += output_stride; + high += output_stride; + } + if (s->progressive) { + low = s->plane[plane].l_h[7]; + high = s->plane[plane].subband[15]; + output = s->plane[plane].l_h[6]; + dsp->vert_filter(output, output_stride, low, output_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].subband[14]; + high = s->plane[plane].subband[16]; + output = s->plane[plane].l_h[7]; + dsp->vert_filter(output, output_stride, low, highpass_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].l_h[9]; + high = s->plane[plane].subband[12]; + output = s->plane[plane].l_h[8]; + dsp->vert_filter(output, output_stride, low, output_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].subband[11]; + high = s->plane[plane].subband[13]; + output = s->plane[plane].l_h[9]; + dsp->vert_filter(output, output_stride, low, highpass_stride, high, highpass_stride, lowpass_width, lowpass_height); + + if (s->sample_type == 1) + continue; + + dst = (int16_t *)pic->data[act_plane]; + if (avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16) { + if (plane & 1) + dst++; + if (plane > 1) + dst += pic->linesize[act_plane] >> 1; + } + + if (avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16 && + (lowpass_height * 2 > avctx->coded_height / 2 || + lowpass_width * 2 > avctx->coded_width / 2 ) + ) { + ret = AVERROR_INVALIDDATA; + goto end; + } + + low = s->plane[plane].l_h[6]; + high = s->plane[plane].l_h[7]; + for (i = 0; i < s->plane[act_plane].height; i++) { + dsp->horiz_filter_clip(dst, low, high, lowpass_width, s->bpc); + low += output_stride; + high += output_stride; + dst += dst_linesize; + } + } else { + pic->interlaced_frame = 1; + low = s->plane[plane].l_h[7]; + high = s->plane[plane].subband[14]; + output = s->plane[plane].l_h[6]; + dsp->horiz_filter(output, output_stride, low, output_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].subband[15]; + high = s->plane[plane].subband[16]; + output = s->plane[plane].l_h[7]; + dsp->horiz_filter(output, output_stride, low, highpass_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].l_h[9]; + high = s->plane[plane].subband[11]; + output = s->plane[plane].l_h[8]; + dsp->horiz_filter(output, output_stride, low, output_stride, high, highpass_stride, lowpass_width, lowpass_height); + + low = s->plane[plane].subband[12]; + high = s->plane[plane].subband[13]; + output = s->plane[plane].l_h[9]; + dsp->horiz_filter(output, output_stride, low, highpass_stride, high, highpass_stride, lowpass_width, lowpass_height); + + if (s->sample_type == 1) + continue; + + dst = (int16_t *)pic->data[act_plane]; + low = s->plane[plane].l_h[6]; + high = s->plane[plane].l_h[7]; + for (i = 0; i < s->plane[act_plane].height / 2; i++) { + interlaced_vertical_filter(dst, low, high, lowpass_width * 2, pic->linesize[act_plane]/2, act_plane); + low += output_stride * 2; + high += output_stride * 2; + dst += pic->linesize[act_plane]; + } } } } + if (s->transform_type == 2 && s->sample_type == 1) { + int16_t *low, *high, *dst; + int output_stride, lowpass_height, lowpass_width; + ptrdiff_t dst_linesize; + + for (plane = 0; plane < s->planes; plane++) { + int act_plane = plane == 1 ? 2 : plane == 2 ? 1 : plane; + + if (avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16) { + act_plane = 0; + dst_linesize = pic->linesize[act_plane]; + } else { + dst_linesize = pic->linesize[act_plane] / 2; + } + + lowpass_height = s->plane[plane].band[4][1].height; + output_stride = s->plane[plane].band[4][1].a_width; + lowpass_width = s->plane[plane].band[4][1].width; + + if (lowpass_height > s->plane[plane].band[4][1].a_height || lowpass_width > s->plane[plane].band[4][1].a_width || + s->plane[plane].band[4][1].width > s->plane[plane].band[4][1].a_width || + lowpass_width < 3 || lowpass_height < 3) { + av_log(avctx, AV_LOG_ERROR, "Invalid plane dimensions\n"); + ret = AVERROR(EINVAL); + goto end; + } + + if (s->progressive) { + dst = (int16_t *)pic->data[act_plane]; + low = s->plane[plane].l_h[8]; + high = s->plane[plane].l_h[9]; + + if (avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16) { + if (plane & 1) + dst++; + if (plane > 1) + dst += pic->linesize[act_plane] >> 1; + } + + if (avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16 && + (lowpass_height * 2 > avctx->coded_height / 2 || + lowpass_width * 2 > avctx->coded_width / 2 ) + ) { + ret = AVERROR_INVALIDDATA; + goto end; + } + + for (i = 0; i < s->plane[act_plane].height; i++) { + dsp->horiz_filter_clip(dst, low, high, lowpass_width, s->bpc); + low += output_stride; + high += output_stride; + dst += dst_linesize; + } + } else { + dst = (int16_t *)pic->data[act_plane]; + low = s->plane[plane].l_h[8]; + high = s->plane[plane].l_h[9]; + for (i = 0; i < s->plane[act_plane].height / 2; i++) { + interlaced_vertical_filter(dst, low, high, lowpass_width * 2, pic->linesize[act_plane]/2, act_plane); + low += output_stride * 2; + high += output_stride * 2; + dst += pic->linesize[act_plane]; + } + } + } + } + if (avctx->pix_fmt == AV_PIX_FMT_BAYER_RGGB16) + process_bayer(pic, s->bpc); end: if (ret < 0) return ret; @@ -940,23 +1407,67 @@ free_buffers(s); - if (!avctx->internal->is_copy) { - ff_free_vlc(&s->vlc_9); - ff_free_vlc(&s->vlc_18); + ff_free_vlc(&s->vlc_9); + ff_free_vlc(&s->vlc_18); + + return 0; +} + +#if HAVE_THREADS +static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) +{ + CFHDContext *psrc = src->priv_data; + CFHDContext *pdst = dst->priv_data; + int ret; + + if (dst == src || psrc->transform_type == 0) + return 0; + + if (pdst->plane[0].idwt_size != psrc->plane[0].idwt_size || + pdst->a_format != psrc->a_format || + pdst->a_width != psrc->a_width || + pdst->a_height != psrc->a_height || + pdst->a_transform_type != psrc->a_transform_type) + free_buffers(pdst); + + pdst->a_format = psrc->a_format; + pdst->a_width = psrc->a_width; + pdst->a_height = psrc->a_height; + pdst->a_transform_type = psrc->a_transform_type; + pdst->transform_type = psrc->transform_type; + pdst->progressive = psrc->progressive; + pdst->planes = psrc->planes; + + if (!pdst->plane[0].idwt_buf) { + pdst->coded_width = pdst->a_width; + pdst->coded_height = pdst->a_height; + pdst->coded_format = pdst->a_format; + pdst->transform_type = pdst->a_transform_type; + ret = alloc_buffers(dst); + if (ret < 0) + return ret; + } + + for (int plane = 0; plane < pdst->planes; plane++) { + memcpy(pdst->plane[plane].band, psrc->plane[plane].band, sizeof(pdst->plane[plane].band)); + memcpy(pdst->plane[plane].idwt_buf, psrc->plane[plane].idwt_buf, + pdst->plane[plane].idwt_size * sizeof(int16_t)); } return 0; } +#endif AVCodec ff_cfhd_decoder = { .name = "cfhd", - .long_name = NULL_IF_CONFIG_SMALL("Cineform HD"), + .long_name = NULL_IF_CONFIG_SMALL("GoPro CineForm HD"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_CFHD, .priv_data_size = sizeof(CFHDContext), .init = cfhd_init, .close = cfhd_close, .decode = cfhd_decode, + .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/cfhddsp.c ffmpeg-4.4/libavcodec/cfhddsp.c --- ffmpeg-4.2.2/libavcodec/cfhddsp.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cfhddsp.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015-2016 Kieran Kunhya + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/avassert.h" + +#include "cfhddsp.h" + +static av_always_inline void filter(int16_t *output, ptrdiff_t out_stride, + const int16_t *low, ptrdiff_t low_stride, + const int16_t *high, ptrdiff_t high_stride, + int len, int clip) +{ + int16_t tmp; + int i; + + tmp = (11*low[0*low_stride] - 4*low[1*low_stride] + low[2*low_stride] + 4) >> 3; + output[(2*0+0)*out_stride] = (tmp + high[0*high_stride]) >> 1; + if (clip) + output[(2*0+0)*out_stride] = av_clip_uintp2_c(output[(2*0+0)*out_stride], clip); + + tmp = ( 5*low[0*low_stride] + 4*low[1*low_stride] - low[2*low_stride] + 4) >> 3; + output[(2*0+1)*out_stride] = (tmp - high[0*high_stride]) >> 1; + if (clip) + output[(2*0+1)*out_stride] = av_clip_uintp2_c(output[(2*0+1)*out_stride], clip); + + for (i = 1; i < len - 1; i++) { + tmp = (low[(i-1)*low_stride] - low[(i+1)*low_stride] + 4) >> 3; + output[(2*i+0)*out_stride] = (tmp + low[i*low_stride] + high[i*high_stride]) >> 1; + if (clip) + output[(2*i+0)*out_stride] = av_clip_uintp2_c(output[(2*i+0)*out_stride], clip); + + tmp = (low[(i+1)*low_stride] - low[(i-1)*low_stride] + 4) >> 3; + output[(2*i+1)*out_stride] = (tmp + low[i*low_stride] - high[i*high_stride]) >> 1; + if (clip) + output[(2*i+1)*out_stride] = av_clip_uintp2_c(output[(2*i+1)*out_stride], clip); + } + + tmp = ( 5*low[i*low_stride] + 4*low[(i-1)*low_stride] - low[(i-2)*low_stride] + 4) >> 3; + output[(2*i+0)*out_stride] = (tmp + high[i*high_stride]) >> 1; + if (clip) + output[(2*i+0)*out_stride] = av_clip_uintp2_c(output[(2*i+0)*out_stride], clip); + + tmp = (11*low[i*low_stride] - 4*low[(i-1)*low_stride] + low[(i-2)*low_stride] + 4) >> 3; + output[(2*i+1)*out_stride] = (tmp - high[i*high_stride]) >> 1; + if (clip) + output[(2*i+1)*out_stride] = av_clip_uintp2_c(output[(2*i+1)*out_stride], clip); +} + +static void vert_filter(int16_t *output, ptrdiff_t out_stride, + const int16_t *low, ptrdiff_t low_stride, + const int16_t *high, ptrdiff_t high_stride, + int width, int height) +{ + for (int i = 0; i < width; i++) { + filter(output, out_stride, low, low_stride, high, high_stride, height, 0); + low++; + high++; + output++; + } +} + +static void horiz_filter(int16_t *output, ptrdiff_t ostride, + const int16_t *low, ptrdiff_t lstride, + const int16_t *high, ptrdiff_t hstride, + int width, int height) +{ + for (int i = 0; i < height; i++) { + filter(output, 1, low, 1, high, 1, width, 0); + low += lstride; + high += hstride; + output += ostride * 2; + } +} + +static void horiz_filter_clip(int16_t *output, const int16_t *low, const int16_t *high, + int width, int clip) +{ + filter(output, 1, low, 1, high, 1, width, clip); +} + +static void horiz_filter_clip_bayer(int16_t *output, const int16_t *low, const int16_t *high, + int width, int clip) +{ + filter(output, 2, low, 1, high, 1, width, clip); +} + +av_cold void ff_cfhddsp_init(CFHDDSPContext *c, int depth, int bayer) +{ + c->horiz_filter = horiz_filter; + c->vert_filter = vert_filter; + + if (bayer) + c->horiz_filter_clip = horiz_filter_clip_bayer; + else + c->horiz_filter_clip = horiz_filter_clip; + + if (ARCH_X86) + ff_cfhddsp_init_x86(c, depth, bayer); +} diff -Nru ffmpeg-4.2.2/libavcodec/cfhddsp.h ffmpeg-4.4/libavcodec/cfhddsp.h --- ffmpeg-4.2.2/libavcodec/cfhddsp.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cfhddsp.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_CFHDDSP_H +#define AVCODEC_CFHDDSP_H + +#include +#include + +typedef struct CFHDDSPContext { + void (*horiz_filter)(int16_t *output, ptrdiff_t out_stride, + const int16_t *low, ptrdiff_t low_stride, + const int16_t *high, ptrdiff_t high_stride, + int width, int height); + + void (*vert_filter)(int16_t *output, ptrdiff_t out_stride, + const int16_t *low, ptrdiff_t low_stride, + const int16_t *high, ptrdiff_t high_stride, + int width, int height); + + void (*horiz_filter_clip)(int16_t *output, const int16_t *low, const int16_t *high, + int width, int bpc); +} CFHDDSPContext; + +void ff_cfhddsp_init(CFHDDSPContext *c, int format, int bayer); + +void ff_cfhddsp_init_x86(CFHDDSPContext *c, int format, int bayer); + +#endif /* AVCODEC_CFHDDSP_H */ diff -Nru ffmpeg-4.2.2/libavcodec/cfhdenc.c ffmpeg-4.4/libavcodec/cfhdenc.c --- ffmpeg-4.2.2/libavcodec/cfhdenc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cfhdenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,866 @@ +/* + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Cineform HD video encoder + */ + +#include +#include + +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "cfhd.h" +#include "cfhdencdsp.h" +#include "put_bits.h" +#include "internal.h" +#include "thread.h" + +/* Derived from existing tables from decoder */ +static const unsigned codebook[256][2] = { + { 1, 0x00000000 }, { 2, 0x00000002 }, { 3, 0x00000007 }, { 5, 0x00000019 }, { 6, 0x00000030 }, + { 6, 0x00000036 }, { 7, 0x00000063 }, { 7, 0x0000006B }, { 7, 0x0000006F }, { 8, 0x000000D4 }, + { 8, 0x000000DC }, { 9, 0x00000189 }, { 9, 0x000001A0 }, { 9, 0x000001AB }, {10, 0x00000310 }, + {10, 0x00000316 }, {10, 0x00000354 }, {10, 0x00000375 }, {10, 0x00000377 }, {11, 0x00000623 }, + {11, 0x00000684 }, {11, 0x000006AB }, {11, 0x000006EC }, {12, 0x00000C44 }, {12, 0x00000C5C }, + {12, 0x00000C5E }, {12, 0x00000D55 }, {12, 0x00000DD1 }, {12, 0x00000DD3 }, {12, 0x00000DDB }, + {13, 0x0000188B }, {13, 0x000018BB }, {13, 0x00001AA8 }, {13, 0x00001BA0 }, {13, 0x00001BA4 }, + {13, 0x00001BB5 }, {14, 0x00003115 }, {14, 0x00003175 }, {14, 0x0000317D }, {14, 0x00003553 }, + {14, 0x00003768 }, {15, 0x00006228 }, {15, 0x000062E8 }, {15, 0x000062F8 }, {15, 0x00006AA4 }, + {15, 0x00006E85 }, {15, 0x00006E87 }, {15, 0x00006ED3 }, {16, 0x0000C453 }, {16, 0x0000C5D3 }, + {16, 0x0000C5F3 }, {16, 0x0000DD08 }, {16, 0x0000DD0C }, {16, 0x0000DDA4 }, {17, 0x000188A4 }, + {17, 0x00018BA5 }, {17, 0x00018BE5 }, {17, 0x0001AA95 }, {17, 0x0001AA97 }, {17, 0x0001BA13 }, + {17, 0x0001BB4A }, {17, 0x0001BB4B }, {18, 0x00031748 }, {18, 0x000317C8 }, {18, 0x00035528 }, + {18, 0x0003552C }, {18, 0x00037424 }, {18, 0x00037434 }, {18, 0x00037436 }, {19, 0x00062294 }, + {19, 0x00062E92 }, {19, 0x00062F92 }, {19, 0x0006AA52 }, {19, 0x0006AA5A }, {19, 0x0006E84A }, + {19, 0x0006E86A }, {19, 0x0006E86E }, {20, 0x000C452A }, {20, 0x000C5D27 }, {20, 0x000C5F26 }, + {20, 0x000D54A6 }, {20, 0x000D54B6 }, {20, 0x000DD096 }, {20, 0x000DD0D6 }, {20, 0x000DD0DE }, + {21, 0x00188A56 }, {21, 0x0018BA4D }, {21, 0x0018BE4E }, {21, 0x0018BE4F }, {21, 0x001AA96E }, + {21, 0x001BA12E }, {21, 0x001BA12F }, {21, 0x001BA1AF }, {21, 0x001BA1BF }, {22, 0x00317498 }, + {22, 0x0035529C }, {22, 0x0035529D }, {22, 0x003552DE }, {22, 0x003552DF }, {22, 0x0037435D }, + {22, 0x0037437D }, {23, 0x0062295D }, {23, 0x0062E933 }, {23, 0x006AA53D }, {23, 0x006AA53E }, + {23, 0x006AA53F }, {23, 0x006E86B9 }, {23, 0x006E86F8 }, {24, 0x00C452B8 }, {24, 0x00C5D265 }, + {24, 0x00D54A78 }, {24, 0x00D54A79 }, {24, 0x00DD0D70 }, {24, 0x00DD0D71 }, {24, 0x00DD0DF2 }, + {24, 0x00DD0DF3 }, {26, 0x03114BA2 }, {25, 0x0188A5B1 }, {25, 0x0188A58B }, {25, 0x0188A595 }, + {25, 0x0188A5D6 }, {25, 0x0188A5D7 }, {25, 0x0188A5A8 }, {25, 0x0188A5AE }, {25, 0x0188A5AF }, + {25, 0x0188A5C4 }, {25, 0x0188A5C5 }, {25, 0x0188A587 }, {25, 0x0188A584 }, {25, 0x0188A585 }, + {25, 0x0188A5C6 }, {25, 0x0188A5C7 }, {25, 0x0188A5CC }, {25, 0x0188A5CD }, {25, 0x0188A581 }, + {25, 0x0188A582 }, {25, 0x0188A583 }, {25, 0x0188A5CE }, {25, 0x0188A5CF }, {25, 0x0188A5C2 }, + {25, 0x0188A5C3 }, {25, 0x0188A5C1 }, {25, 0x0188A5B4 }, {25, 0x0188A5B5 }, {25, 0x0188A5E6 }, + {25, 0x0188A5E7 }, {25, 0x0188A5E4 }, {25, 0x0188A5E5 }, {25, 0x0188A5AB }, {25, 0x0188A5E0 }, + {25, 0x0188A5E1 }, {25, 0x0188A5E2 }, {25, 0x0188A5E3 }, {25, 0x0188A5B6 }, {25, 0x0188A5B7 }, + {25, 0x0188A5FD }, {25, 0x0188A57E }, {25, 0x0188A57F }, {25, 0x0188A5EC }, {25, 0x0188A5ED }, + {25, 0x0188A5FE }, {25, 0x0188A5FF }, {25, 0x0188A57D }, {25, 0x0188A59C }, {25, 0x0188A59D }, + {25, 0x0188A5E8 }, {25, 0x0188A5E9 }, {25, 0x0188A5EA }, {25, 0x0188A5EB }, {25, 0x0188A5EF }, + {25, 0x0188A57A }, {25, 0x0188A57B }, {25, 0x0188A578 }, {25, 0x0188A579 }, {25, 0x0188A5BA }, + {25, 0x0188A5BB }, {25, 0x0188A5B8 }, {25, 0x0188A5B9 }, {25, 0x0188A588 }, {25, 0x0188A589 }, + {25, 0x018BA4C8 }, {25, 0x018BA4C9 }, {25, 0x0188A5FA }, {25, 0x0188A5FB }, {25, 0x0188A5BC }, + {25, 0x0188A5BD }, {25, 0x0188A598 }, {25, 0x0188A599 }, {25, 0x0188A5F4 }, {25, 0x0188A5F5 }, + {25, 0x0188A59B }, {25, 0x0188A5DE }, {25, 0x0188A5DF }, {25, 0x0188A596 }, {25, 0x0188A597 }, + {25, 0x0188A5F8 }, {25, 0x0188A5F9 }, {25, 0x0188A5F1 }, {25, 0x0188A58E }, {25, 0x0188A58F }, + {25, 0x0188A5DC }, {25, 0x0188A5DD }, {25, 0x0188A5F2 }, {25, 0x0188A5F3 }, {25, 0x0188A58C }, + {25, 0x0188A58D }, {25, 0x0188A5A4 }, {25, 0x0188A5F0 }, {25, 0x0188A5A5 }, {25, 0x0188A5A6 }, + {25, 0x0188A5A7 }, {25, 0x0188A59A }, {25, 0x0188A5A2 }, {25, 0x0188A5A3 }, {25, 0x0188A58A }, + {25, 0x0188A5B0 }, {25, 0x0188A5A0 }, {25, 0x0188A5A1 }, {25, 0x0188A5DA }, {25, 0x0188A5DB }, + {25, 0x0188A59E }, {25, 0x0188A59F }, {25, 0x0188A5D8 }, {25, 0x0188A5EE }, {25, 0x0188A5D9 }, + {25, 0x0188A5F6 }, {25, 0x0188A5F7 }, {25, 0x0188A57C }, {25, 0x0188A5C8 }, {25, 0x0188A5C9 }, + {25, 0x0188A594 }, {25, 0x0188A5FC }, {25, 0x0188A5CA }, {25, 0x0188A5CB }, {25, 0x0188A5B2 }, + {25, 0x0188A5AA }, {25, 0x0188A5B3 }, {25, 0x0188A572 }, {25, 0x0188A573 }, {25, 0x0188A5C0 }, + {25, 0x0188A5BE }, {25, 0x0188A5BF }, {25, 0x0188A592 }, {25, 0x0188A580 }, {25, 0x0188A593 }, + {25, 0x0188A590 }, {25, 0x0188A591 }, {25, 0x0188A586 }, {25, 0x0188A5A9 }, {25, 0x0188A5D2 }, + {25, 0x0188A5D3 }, {25, 0x0188A5D4 }, {25, 0x0188A5D5 }, {25, 0x0188A5AC }, {25, 0x0188A5AD }, + {25, 0x0188A5D0 }, +}; + +/* Derived by extracting runcodes from existing tables from decoder */ +static const uint16_t runbook[18][3] = { + {1, 0x0000, 1}, {2, 0x0000, 2}, {3, 0x0000, 3}, {4, 0x0000, 4}, + {5, 0x0000, 5}, {6, 0x0000, 6}, {7, 0x0000, 7}, {8, 0x0000, 8}, + {9, 0x0000, 9}, {10, 0x0000, 10}, {11, 0x0000, 11}, + {7, 0x0069, 12}, {8, 0x00D1, 20}, {9, 0x018A, 32}, + {10, 0x0343, 60}, {11, 0x0685, 100}, {13, 0x18BF, 180}, {13, 0x1BA5, 320}, +}; + +/* + * Derived by inspecting various quality encodes + * and adding some more from scratch. + */ +static const uint16_t quantization_per_subband[2][3][13][9] = { + {{ + { 16, 16, 8, 4, 4, 2, 6, 6, 9, }, // film3+ + { 16, 16, 8, 4, 4, 2, 6, 6, 9, }, // film3 + { 16, 16, 8, 4, 4, 2, 7, 7, 10, }, // film2+ + { 16, 16, 8, 4, 4, 2, 8, 8, 12, }, // film2 + { 16, 16, 8, 4, 4, 2, 16, 16, 26, }, // film1++ + { 24, 24, 12, 6, 6, 3, 24, 24, 36, }, // film1+ + { 24, 24, 12, 6, 6, 3, 24, 24, 36, }, // film1 + { 32, 32, 24, 8, 8, 6, 32, 32, 48, }, // high+ + { 32, 32, 24, 8, 8, 6, 32, 32, 48, }, // high + { 48, 48, 32, 12, 12, 8, 64, 64, 96, }, // medium+ + { 48, 48, 32, 12, 12, 8, 64, 64, 96, }, // medium + { 64, 64, 48, 16, 16, 12, 96, 96, 144, }, // low+ + { 64, 64, 48, 16, 16, 12, 128, 128, 192, }, // low + }, + { + { 16, 16, 8, 4, 4, 2, 6, 6, 9, }, // film3+ + { 16, 16, 8, 4, 4, 2, 6, 6, 12, }, // film3 + { 16, 16, 8, 4, 4, 2, 7, 7, 14, }, // film2+ + { 16, 16, 8, 4, 4, 2, 8, 8, 16, }, // film2 + { 16, 16, 8, 4, 4, 2, 16, 16, 26, }, // film1++ + { 24, 24, 12, 6, 6, 3, 24, 24, 36, }, // film1+ + { 24, 24, 12, 6, 6, 3, 24, 24, 48, }, // film1 + { 32, 32, 24, 8, 8, 6, 32, 32, 48, }, // high+ + { 48, 48, 32, 12, 12, 8, 32, 32, 64, }, // high + { 48, 48, 32, 12, 12, 8, 64, 64, 96, }, // medium+ + { 48, 48, 32, 12, 12, 8, 64, 64, 128, }, // medium + { 64, 64, 48, 16, 16, 12, 96, 96, 160, }, // low+ + { 64, 64, 48, 16, 16, 12, 128, 128, 192, }, // low + }, + { + { 16, 16, 8, 4, 4, 2, 6, 6, 9, }, // film3+ + { 16, 16, 8, 4, 4, 2, 6, 6, 12, }, // film3 + { 16, 16, 8, 4, 4, 2, 7, 7, 14, }, // film2+ + { 16, 16, 8, 4, 4, 2, 8, 8, 16, }, // film2 + { 16, 16, 8, 4, 4, 2, 16, 16, 26, }, // film1++ + { 24, 24, 12, 6, 6, 3, 24, 24, 36, }, // film1+ + { 24, 24, 12, 6, 6, 3, 24, 24, 48, }, // film1 + { 32, 32, 24, 8, 8, 6, 32, 32, 48, }, // high+ + { 48, 48, 32, 12, 12, 8, 32, 32, 64, }, // high + { 48, 48, 32, 12, 12, 8, 64, 64, 96, }, // medium+ + { 48, 48, 32, 12, 12, 8, 64, 64, 128, }, // medium + { 64, 64, 48, 16, 16, 12, 96, 96, 160, }, // low+ + { 64, 64, 48, 16, 16, 12, 128, 128, 192, }, // low + }}, + {{ + { 16, 16, 8, 16, 16, 8, 24, 24, 36, }, // film3+ + { 16, 16, 8, 16, 16, 8, 24, 24, 36, }, // film3 + { 16, 16, 8, 16, 16, 8, 32, 32, 48, }, // film2+ + { 16, 16, 8, 16, 16, 8, 32, 32, 48, }, // film2 + { 16, 16, 8, 20, 20, 10, 80, 80, 128, }, // film1++ + { 24, 24, 12, 24, 24, 12, 96, 96, 144, }, // film1+ + { 24, 24, 12, 24, 24, 12, 96, 96, 144, }, // film1 + { 32, 32, 24, 32, 32, 24, 128, 128, 192, }, // high+ + { 32, 32, 24, 32, 32, 24, 128, 128, 192, }, // high + { 48, 48, 32, 48, 48, 32, 256, 256, 384, }, // medium+ + { 48, 48, 32, 48, 48, 32, 256, 256, 384, }, // medium + { 56, 56, 40, 56, 56, 40, 512, 512, 768, }, // low+ + { 64, 64, 48, 64, 64, 48, 512, 512, 768, }, // low + }, + { + { 16, 16, 8, 16, 16, 8, 24, 24, 36, }, // film3+ + { 16, 16, 8, 16, 16, 8, 48, 48, 72, }, // film3 + { 16, 16, 8, 16, 16, 8, 48, 48, 72, }, // film2+ + { 16, 16, 8, 16, 16, 8, 64, 64, 96, }, // film2 + { 16, 16, 8, 20, 20, 10, 80, 80, 128, }, // film1++ + { 24, 24, 12, 24, 24, 12, 96, 96, 144, }, // film1+ + { 24, 24, 12, 24, 24, 12, 192, 192, 288, }, // film1 + { 32, 32, 24, 32, 32, 24, 128, 128, 192, }, // high+ + { 32, 32, 24, 32, 32, 24, 256, 256, 384, }, // high + { 48, 48, 32, 48, 48, 32, 256, 256, 384, }, // medium+ + { 48, 48, 32, 48, 48, 32, 512, 512, 768, }, // medium + { 56, 56, 40, 56, 56, 40, 512, 512, 768, }, // low+ + { 64, 64, 48, 64, 64, 48,1024,1024,1536, }, // low + }, + { + { 16, 16, 8, 16, 16, 8, 24, 24, 36, }, // film3+ + { 16, 16, 8, 16, 16, 8, 48, 48, 72, }, // film3 + { 16, 16, 8, 16, 16, 8, 48, 48, 72, }, // film2+ + { 16, 16, 8, 16, 16, 8, 64, 64, 96, }, // film2 + { 16, 16, 10, 20, 20, 10, 80, 80, 128, }, // film1++ + { 24, 24, 12, 24, 24, 12, 96, 96, 144, }, // film1+ + { 24, 24, 12, 24, 24, 12, 192, 192, 288, }, // film1 + { 32, 32, 24, 32, 32, 24, 128, 128, 192, }, // high+ + { 32, 32, 24, 32, 32, 24, 256, 256, 384, }, // high + { 48, 48, 32, 48, 48, 32, 256, 256, 384, }, // medium+ + { 48, 48, 32, 48, 48, 32, 512, 512, 768, }, // medium + { 56, 56, 40, 56, 56, 40, 512, 512, 768, }, // low+ + { 64, 64, 48, 64, 64, 48,1024,1024,1536, }, // low + }}, +}; + +typedef struct Codebook { + unsigned bits; + unsigned size; +} Codebook; + +typedef struct Runbook { + unsigned size; + unsigned bits; + unsigned run; +} Runbook; + +typedef struct PlaneEnc { + unsigned size; + + int16_t *dwt_buf; + int16_t *dwt_tmp; + + unsigned quantization[SUBBAND_COUNT]; + int16_t *subband[SUBBAND_COUNT]; + int16_t *l_h[8]; + + SubBand band[DWT_LEVELS][4]; +} PlaneEnc; + +typedef struct CFHDEncContext { + const AVClass *class; + + PutBitContext pb; + PutByteContext pby; + + int quality; + int planes; + int chroma_h_shift; + int chroma_v_shift; + PlaneEnc plane[4]; + + uint16_t lut[1024]; + Runbook rb[321]; + Codebook cb[513]; + int16_t *alpha; + + CFHDEncDSPContext dsp; +} CFHDEncContext; + +static av_cold int cfhd_encode_init(AVCodecContext *avctx) +{ + CFHDEncContext *s = avctx->priv_data; + const int sign_mask = 256; + const int twos_complement = -sign_mask; + const int mag_mask = sign_mask - 1; + int ret, last = 0; + + ret = av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, + &s->chroma_h_shift, + &s->chroma_v_shift); + if (ret < 0) + return ret; + + if (avctx->width & 15) { + av_log(avctx, AV_LOG_ERROR, "Width must be multiple of 16.\n"); + return AVERROR_INVALIDDATA; + } + + s->planes = av_pix_fmt_count_planes(avctx->pix_fmt); + + for (int i = 0; i < s->planes; i++) { + int w8, h8, w4, h4, w2, h2; + int width = i ? avctx->width >> s->chroma_h_shift : avctx->width; + int height = i ? FFALIGN(avctx->height >> s->chroma_v_shift, 8) : + FFALIGN(avctx->height >> s->chroma_v_shift, 8); + ptrdiff_t stride = (FFALIGN(width / 8, 8) + 64) * 8; + + w8 = FFALIGN(width / 8, 8) + 64; + h8 = FFALIGN(height, 8) / 8; + w4 = w8 * 2; + h4 = h8 * 2; + w2 = w4 * 2; + h2 = h4 * 2; + + s->plane[i].dwt_buf = + av_mallocz_array(height * stride, sizeof(*s->plane[i].dwt_buf)); + s->plane[i].dwt_tmp = + av_malloc_array(height * stride, sizeof(*s->plane[i].dwt_tmp)); + if (!s->plane[i].dwt_buf || !s->plane[i].dwt_tmp) + return AVERROR(ENOMEM); + + s->plane[i].subband[0] = s->plane[i].dwt_buf; + s->plane[i].subband[1] = s->plane[i].dwt_buf + 2 * w8 * h8; + s->plane[i].subband[2] = s->plane[i].dwt_buf + 1 * w8 * h8; + s->plane[i].subband[3] = s->plane[i].dwt_buf + 3 * w8 * h8; + s->plane[i].subband[4] = s->plane[i].dwt_buf + 2 * w4 * h4; + s->plane[i].subband[5] = s->plane[i].dwt_buf + 1 * w4 * h4; + s->plane[i].subband[6] = s->plane[i].dwt_buf + 3 * w4 * h4; + s->plane[i].subband[7] = s->plane[i].dwt_buf + 2 * w2 * h2; + s->plane[i].subband[8] = s->plane[i].dwt_buf + 1 * w2 * h2; + s->plane[i].subband[9] = s->plane[i].dwt_buf + 3 * w2 * h2; + + for (int j = 0; j < DWT_LEVELS; j++) { + for (int k = 0; k < FF_ARRAY_ELEMS(s->plane[i].band[j]); k++) { + s->plane[i].band[j][k].width = (width / 8) << j; + s->plane[i].band[j][k].height = (height / 8) << j; + s->plane[i].band[j][k].a_width = w8 << j; + s->plane[i].band[j][k].a_height = h8 << j; + } + } + + /* ll2 and ll1 commented out because they are done in-place */ + s->plane[i].l_h[0] = s->plane[i].dwt_tmp; + s->plane[i].l_h[1] = s->plane[i].dwt_tmp + 2 * w8 * h8; + // s->plane[i].l_h[2] = ll2; + s->plane[i].l_h[3] = s->plane[i].dwt_tmp; + s->plane[i].l_h[4] = s->plane[i].dwt_tmp + 2 * w4 * h4; + // s->plane[i].l_h[5] = ll1; + s->plane[i].l_h[6] = s->plane[i].dwt_tmp; + s->plane[i].l_h[7] = s->plane[i].dwt_tmp + 2 * w2 * h2; + } + + for (int i = 0; i < 512; i++) { + int value = (i & sign_mask) ? twos_complement + (i & mag_mask): i; + int mag = FFMIN(FFABS(value), 255); + + if (mag) { + s->cb[i].bits = (codebook[mag][1] << 1) | (value > 0 ? 0 : 1); + s->cb[i].size = codebook[mag][0] + 1; + } else { + s->cb[i].bits = codebook[mag][1]; + s->cb[i].size = codebook[mag][0]; + } + } + + s->cb[512].bits = 0x3114ba3; + s->cb[512].size = 26; + + s->rb[0].run = 0; + + for (int i = 1, j = 0; i < 320 && j < 17; j++) { + int run = runbook[j][2]; + int end = runbook[j+1][2]; + + while (i < end) { + s->rb[i].run = run; + s->rb[i].bits = runbook[j][1]; + s->rb[i++].size = runbook[j][0]; + } + } + + s->rb[320].bits = runbook[17][1]; + s->rb[320].size = runbook[17][0]; + s->rb[320].run = 320; + + for (int i = 0; i < 256; i++) { + int idx = i + ((768LL * i * i * i) / (256 * 256 * 256)); + + s->lut[idx] = i; + } + for (int i = 0; i < 1024; i++) { + if (s->lut[i]) + last = s->lut[i]; + else + s->lut[i] = last; + } + + ff_cfhdencdsp_init(&s->dsp); + + if (s->planes != 4) + return 0; + + s->alpha = av_calloc(avctx->width * avctx->height, sizeof(*s->alpha)); + if (!s->alpha) + return AVERROR(ENOMEM); + + return 0; +} + +static void quantize_band(int16_t *input, int width, int a_width, + int height, unsigned quantization) +{ + const int16_t factor = (uint32_t)(1U << 15) / quantization; + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) + input[j] = av_clip_intp2(((input[j] * factor + 16384 * FFSIGN(input[j])) / 32768), 10); + input += a_width; + } +} + +static int put_runcode(PutBitContext *pb, int count, const Runbook *const rb) +{ + while (count > 0) { + const int index = FFMIN(320, count); + + put_bits(pb, rb[index].size, rb[index].bits); + count -= rb[index].run; + } + + return 0; +} + +static void process_alpha(const int16_t *src, int width, int height, ptrdiff_t stride, int16_t *dst) +{ + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + int alpha = src[j]; + + if (alpha > 0 && alpha < 4080) { + alpha *= 223; + alpha += 128; + alpha >>= 8; + alpha += 256; + } + + dst[j] = av_clip_uintp2(alpha, 12); + } + + src += stride; + dst += width; + } +} + +static int cfhd_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + CFHDEncContext *s = avctx->priv_data; + CFHDEncDSPContext *dsp = &s->dsp; + PutByteContext *pby = &s->pby; + PutBitContext *pb = &s->pb; + const Codebook *const cb = s->cb; + const Runbook *const rb = s->rb; + const uint16_t *lut = s->lut; + unsigned pos; + int ret; + + for (int plane = 0; plane < s->planes; plane++) { + int width = s->plane[plane].band[2][0].width; + int a_width = s->plane[plane].band[2][0].a_width; + int height = s->plane[plane].band[2][0].height; + int act_plane = plane == 1 ? 2 : plane == 2 ? 1 : plane; + int16_t *input = (int16_t *)frame->data[act_plane]; + int16_t *low = s->plane[plane].l_h[6]; + int16_t *high = s->plane[plane].l_h[7]; + ptrdiff_t in_stride = frame->linesize[act_plane] / 2; + int low_stride, high_stride; + + if (plane == 3) { + process_alpha(input, avctx->width, avctx->height, + in_stride, s->alpha); + input = s->alpha; + in_stride = avctx->width; + } + + dsp->horiz_filter(input, low, high, + in_stride, a_width, a_width, + width * 2, height * 2); + + input = s->plane[plane].l_h[7]; + low = s->plane[plane].subband[7]; + low_stride = s->plane[plane].band[2][0].a_width; + high = s->plane[plane].subband[9]; + high_stride = s->plane[plane].band[2][0].a_width; + + dsp->vert_filter(input, low, high, + a_width, low_stride, high_stride, + width, height * 2); + + input = s->plane[plane].l_h[6]; + low = s->plane[plane].l_h[7]; + high = s->plane[plane].subband[8]; + + dsp->vert_filter(input, low, high, + a_width, low_stride, high_stride, + width, height * 2); + + a_width = s->plane[plane].band[1][0].a_width; + width = s->plane[plane].band[1][0].width; + height = s->plane[plane].band[1][0].height; + input = s->plane[plane].l_h[7]; + low = s->plane[plane].l_h[3]; + low_stride = s->plane[plane].band[1][0].a_width; + high = s->plane[plane].l_h[4]; + high_stride = s->plane[plane].band[1][0].a_width; + + for (int i = 0; i < height * 2; i++) { + for (int j = 0; j < width * 2; j++) + input[j] /= 4; + input += a_width * 2; + } + + input = s->plane[plane].l_h[7]; + dsp->horiz_filter(input, low, high, + a_width * 2, low_stride, high_stride, + width * 2, height * 2); + + input = s->plane[plane].l_h[4]; + low = s->plane[plane].subband[4]; + high = s->plane[plane].subband[6]; + + dsp->vert_filter(input, low, high, + a_width, low_stride, high_stride, + width, height * 2); + + input = s->plane[plane].l_h[3]; + low = s->plane[plane].l_h[4]; + high = s->plane[plane].subband[5]; + + dsp->vert_filter(input, low, high, + a_width, low_stride, high_stride, + width, height * 2); + + a_width = s->plane[plane].band[0][0].a_width; + width = s->plane[plane].band[0][0].width; + height = s->plane[plane].band[0][0].height; + input = s->plane[plane].l_h[4]; + low = s->plane[plane].l_h[0]; + low_stride = s->plane[plane].band[0][0].a_width; + high = s->plane[plane].l_h[1]; + high_stride = s->plane[plane].band[0][0].a_width; + + if (avctx->pix_fmt != AV_PIX_FMT_YUV422P10) { + for (int i = 0; i < height * 2; i++) { + for (int j = 0; j < width * 2; j++) + input[j] /= 4; + input += a_width * 2; + } + } + + input = s->plane[plane].l_h[4]; + dsp->horiz_filter(input, low, high, + a_width * 2, low_stride, high_stride, + width * 2, height * 2); + + low = s->plane[plane].subband[1]; + high = s->plane[plane].subband[3]; + input = s->plane[plane].l_h[1]; + + dsp->vert_filter(input, low, high, + a_width, low_stride, high_stride, + width, height * 2); + + low = s->plane[plane].subband[0]; + high = s->plane[plane].subband[2]; + input = s->plane[plane].l_h[0]; + + dsp->vert_filter(input, low, high, + a_width, low_stride, high_stride, + width, height * 2); + } + + ret = ff_alloc_packet2(avctx, pkt, 64LL + s->planes * (2LL * avctx->width * avctx->height + 1000LL), 0); + if (ret < 0) + return ret; + + bytestream2_init_writer(pby, pkt->data, pkt->size); + + bytestream2_put_be16(pby, SampleType); + bytestream2_put_be16(pby, 9); + + bytestream2_put_be16(pby, SampleIndexTable); + bytestream2_put_be16(pby, s->planes); + + for (int i = 0; i < s->planes; i++) + bytestream2_put_be32(pby, 0); + + bytestream2_put_be16(pby, TransformType); + bytestream2_put_be16(pby, 0); + + bytestream2_put_be16(pby, NumFrames); + bytestream2_put_be16(pby, 1); + + bytestream2_put_be16(pby, ChannelCount); + bytestream2_put_be16(pby, s->planes); + + bytestream2_put_be16(pby, EncodedFormat); + bytestream2_put_be16(pby, avctx->pix_fmt == AV_PIX_FMT_YUV422P10 ? 1 : 3 + (s->planes == 4)); + + bytestream2_put_be16(pby, WaveletCount); + bytestream2_put_be16(pby, 3); + + bytestream2_put_be16(pby, SubbandCount); + bytestream2_put_be16(pby, SUBBAND_COUNT); + + bytestream2_put_be16(pby, NumSpatial); + bytestream2_put_be16(pby, 2); + + bytestream2_put_be16(pby, FirstWavelet); + bytestream2_put_be16(pby, 3); + + bytestream2_put_be16(pby, ImageWidth); + bytestream2_put_be16(pby, avctx->width); + + bytestream2_put_be16(pby, ImageHeight); + bytestream2_put_be16(pby, avctx->height); + + bytestream2_put_be16(pby, -FrameNumber); + bytestream2_put_be16(pby, frame->pts & 0xFFFF); + + bytestream2_put_be16(pby, Precision); + bytestream2_put_be16(pby, avctx->pix_fmt == AV_PIX_FMT_YUV422P10 ? 10 : 12); + + bytestream2_put_be16(pby, PrescaleTable); + bytestream2_put_be16(pby, avctx->pix_fmt == AV_PIX_FMT_YUV422P10 ? 0x2000 : 0x2800); + + bytestream2_put_be16(pby, SampleFlags); + bytestream2_put_be16(pby, 1); + + for (int p = 0; p < s->planes; p++) { + int width = s->plane[p].band[0][0].width; + int a_width = s->plane[p].band[0][0].a_width; + int height = s->plane[p].band[0][0].height; + int16_t *data = s->plane[p].subband[0]; + + if (p) { + bytestream2_put_be16(pby, SampleType); + bytestream2_put_be16(pby, 3); + + bytestream2_put_be16(pby, ChannelNumber); + bytestream2_put_be16(pby, p); + } + + bytestream2_put_be16(pby, BitstreamMarker); + bytestream2_put_be16(pby, 0x1a4a); + + pos = bytestream2_tell_p(pby); + + bytestream2_put_be16(pby, LowpassSubband); + bytestream2_put_be16(pby, 0); + + bytestream2_put_be16(pby, NumLevels); + bytestream2_put_be16(pby, 3); + + bytestream2_put_be16(pby, LowpassWidth); + bytestream2_put_be16(pby, width); + + bytestream2_put_be16(pby, LowpassHeight); + bytestream2_put_be16(pby, height); + + bytestream2_put_be16(pby, PixelOffset); + bytestream2_put_be16(pby, 0); + + bytestream2_put_be16(pby, LowpassQuantization); + bytestream2_put_be16(pby, 1); + + bytestream2_put_be16(pby, LowpassPrecision); + bytestream2_put_be16(pby, 16); + + bytestream2_put_be16(pby, BitstreamMarker); + bytestream2_put_be16(pby, 0x0f0f); + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) + bytestream2_put_be16(pby, data[j]); + data += a_width; + } + + bytestream2_put_be16(pby, BitstreamMarker); + bytestream2_put_be16(pby, 0x1b4b); + + for (int l = 0; l < 3; l++) { + for (int i = 0; i < 3; i++) { + s->plane[p].quantization[1 + l * 3 + i] = quantization_per_subband[avctx->pix_fmt != AV_PIX_FMT_YUV422P10][p >= 3 ? 0 : p][s->quality][l * 3 + i]; + } + } + + for (int l = 0; l < 3; l++) { + int a_width = s->plane[p].band[l][0].a_width; + int width = s->plane[p].band[l][0].width; + int stride = FFALIGN(width, 8); + int height = s->plane[p].band[l][0].height; + + bytestream2_put_be16(pby, BitstreamMarker); + bytestream2_put_be16(pby, 0x0d0d); + + bytestream2_put_be16(pby, WaveletType); + bytestream2_put_be16(pby, 3 + 2 * (l == 2)); + + bytestream2_put_be16(pby, WaveletNumber); + bytestream2_put_be16(pby, 3 - l); + + bytestream2_put_be16(pby, WaveletLevel); + bytestream2_put_be16(pby, 3 - l); + + bytestream2_put_be16(pby, NumBands); + bytestream2_put_be16(pby, 4); + + bytestream2_put_be16(pby, HighpassWidth); + bytestream2_put_be16(pby, width); + + bytestream2_put_be16(pby, HighpassHeight); + bytestream2_put_be16(pby, height); + + bytestream2_put_be16(pby, LowpassBorder); + bytestream2_put_be16(pby, 0); + + bytestream2_put_be16(pby, HighpassBorder); + bytestream2_put_be16(pby, 0); + + bytestream2_put_be16(pby, LowpassScale); + bytestream2_put_be16(pby, 1); + + bytestream2_put_be16(pby, LowpassDivisor); + bytestream2_put_be16(pby, 1); + + for (int i = 0; i < 3; i++) { + int16_t *data = s->plane[p].subband[1 + l * 3 + i]; + int count = 0, padd = 0; + + bytestream2_put_be16(pby, BitstreamMarker); + bytestream2_put_be16(pby, 0x0e0e); + + bytestream2_put_be16(pby, SubbandNumber); + bytestream2_put_be16(pby, i + 1); + + bytestream2_put_be16(pby, BandCodingFlags); + bytestream2_put_be16(pby, 1); + + bytestream2_put_be16(pby, BandWidth); + bytestream2_put_be16(pby, width); + + bytestream2_put_be16(pby, BandHeight); + bytestream2_put_be16(pby, height); + + bytestream2_put_be16(pby, SubbandBand); + bytestream2_put_be16(pby, 1 + l * 3 + i); + + bytestream2_put_be16(pby, BandEncoding); + bytestream2_put_be16(pby, 3); + + bytestream2_put_be16(pby, Quantization); + bytestream2_put_be16(pby, s->plane[p].quantization[1 + l * 3 + i]); + + bytestream2_put_be16(pby, BandScale); + bytestream2_put_be16(pby, 1); + + bytestream2_put_be16(pby, BandHeader); + bytestream2_put_be16(pby, 0); + + quantize_band(data, width, a_width, height, + s->plane[p].quantization[1 + l * 3 + i]); + + init_put_bits(pb, pkt->data + bytestream2_tell_p(pby), bytestream2_get_bytes_left_p(pby)); + + for (int m = 0; m < height; m++) { + for (int j = 0; j < stride; j++) { + int16_t index = j >= width ? 0 : FFSIGN(data[j]) * lut[FFABS(data[j])]; + + if (index < 0) + index += 512; + if (index == 0) { + count++; + continue; + } else if (count > 0) { + count = put_runcode(pb, count, rb); + } + + put_bits(pb, cb[index].size, cb[index].bits); + } + + data += a_width; + } + + if (count > 0) { + count = put_runcode(pb, count, rb); + } + + put_bits(pb, cb[512].size, cb[512].bits); + + flush_put_bits(pb); + bytestream2_skip_p(pby, put_bits_count(pb) >> 3); + padd = (4 - (bytestream2_tell_p(pby) & 3)) & 3; + while (padd--) + bytestream2_put_byte(pby, 0); + + bytestream2_put_be16(pby, BandTrailer); + bytestream2_put_be16(pby, 0); + } + + bytestream2_put_be16(pby, BitstreamMarker); + bytestream2_put_be16(pby, 0x0c0c); + } + + s->plane[p].size = bytestream2_tell_p(pby) - pos; + } + + bytestream2_put_be16(pby, GroupTrailer); + bytestream2_put_be16(pby, 0); + + av_shrink_packet(pkt, bytestream2_tell_p(pby)); + + pkt->flags |= AV_PKT_FLAG_KEY; + + bytestream2_seek_p(pby, 8, SEEK_SET); + for (int i = 0; i < s->planes; i++) + bytestream2_put_be32(pby, s->plane[i].size); + + *got_packet = 1; + + return 0; +} + +static av_cold int cfhd_encode_close(AVCodecContext *avctx) +{ + CFHDEncContext *s = avctx->priv_data; + + for (int i = 0; i < s->planes; i++) { + av_freep(&s->plane[i].dwt_buf); + av_freep(&s->plane[i].dwt_tmp); + + for (int j = 0; j < SUBBAND_COUNT; j++) + s->plane[i].subband[j] = NULL; + + for (int j = 0; j < 8; j++) + s->plane[i].l_h[j] = NULL; + } + + av_freep(&s->alpha); + + return 0; +} + +#define OFFSET(x) offsetof(CFHDEncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "quality", "set quality", OFFSET(quality), AV_OPT_TYPE_INT, {.i64= 0}, 0, 12, VE, "q" }, + { "film3+", NULL, 0, AV_OPT_TYPE_CONST, {.i64= 0}, 0, 0, VE, "q" }, + { "film3", NULL, 0, AV_OPT_TYPE_CONST, {.i64= 1}, 0, 0, VE, "q" }, + { "film2+", NULL, 0, AV_OPT_TYPE_CONST, {.i64= 2}, 0, 0, VE, "q" }, + { "film2", NULL, 0, AV_OPT_TYPE_CONST, {.i64= 3}, 0, 0, VE, "q" }, + { "film1.5", NULL, 0, AV_OPT_TYPE_CONST, {.i64= 4}, 0, 0, VE, "q" }, + { "film1+", NULL, 0, AV_OPT_TYPE_CONST, {.i64= 5}, 0, 0, VE, "q" }, + { "film1", NULL, 0, AV_OPT_TYPE_CONST, {.i64= 6}, 0, 0, VE, "q" }, + { "high+", NULL, 0, AV_OPT_TYPE_CONST, {.i64= 7}, 0, 0, VE, "q" }, + { "high", NULL, 0, AV_OPT_TYPE_CONST, {.i64= 8}, 0, 0, VE, "q" }, + { "medium+", NULL, 0, AV_OPT_TYPE_CONST, {.i64= 9}, 0, 0, VE, "q" }, + { "medium", NULL, 0, AV_OPT_TYPE_CONST, {.i64=10}, 0, 0, VE, "q" }, + { "low+", NULL, 0, AV_OPT_TYPE_CONST, {.i64=11}, 0, 0, VE, "q" }, + { "low", NULL, 0, AV_OPT_TYPE_CONST, {.i64=12}, 0, 0, VE, "q" }, + { NULL}, +}; + +static const AVClass cfhd_class = { + .class_name = "cfhd", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_cfhd_encoder = { + .name = "cfhd", + .long_name = NULL_IF_CONFIG_SMALL("GoPro CineForm HD"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CFHD, + .priv_data_size = sizeof(CFHDEncContext), + .priv_class = &cfhd_class, + .init = cfhd_encode_init, + .close = cfhd_encode_close, + .encode2 = cfhd_encode_frame, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_GBRP12, + AV_PIX_FMT_GBRAP12, + AV_PIX_FMT_NONE + }, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +}; diff -Nru ffmpeg-4.2.2/libavcodec/cfhdencdsp.c ffmpeg-4.4/libavcodec/cfhdencdsp.c --- ffmpeg-4.2.2/libavcodec/cfhdencdsp.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cfhdencdsp.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015-2016 Kieran Kunhya + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/avassert.h" + +#include "cfhdencdsp.h" + +static av_always_inline void filter(int16_t *input, ptrdiff_t in_stride, + int16_t *low, ptrdiff_t low_stride, + int16_t *high, ptrdiff_t high_stride, + int len) +{ + low[(0>>1) * low_stride] = av_clip_int16(input[0*in_stride] + input[1*in_stride]); + high[(0>>1) * high_stride] = av_clip_int16((5 * input[0*in_stride] - 11 * input[1*in_stride] + + 4 * input[2*in_stride] + 4 * input[3*in_stride] - + 1 * input[4*in_stride] - 1 * input[5*in_stride] + 4) >> 3); + + for (int i = 2; i < len - 2; i += 2) { + low[(i>>1) * low_stride] = av_clip_int16(input[i*in_stride] + input[(i+1)*in_stride]); + high[(i>>1) * high_stride] = av_clip_int16(((-input[(i-2)*in_stride] - input[(i-1)*in_stride] + + input[(i+2)*in_stride] + input[(i+3)*in_stride] + 4) >> 3) + + input[(i+0)*in_stride] - input[(i+1)*in_stride]); + } + + low[((len-2)>>1) * low_stride] = av_clip_int16(input[((len-2)+0)*in_stride] + input[((len-2)+1)*in_stride]); + high[((len-2)>>1) * high_stride] = av_clip_int16((11* input[((len-2)+0)*in_stride] - 5 * input[((len-2)+1)*in_stride] - + 4 * input[((len-2)-1)*in_stride] - 4 * input[((len-2)-2)*in_stride] + + 1 * input[((len-2)-3)*in_stride] + 1 * input[((len-2)-4)*in_stride] + 4) >> 3); +} + +static void horiz_filter(int16_t *input, int16_t *low, int16_t *high, + ptrdiff_t in_stride, ptrdiff_t low_stride, + ptrdiff_t high_stride, + int width, int height) +{ + for (int i = 0; i < height; i++) { + filter(input, 1, low, 1, high, 1, width); + input += in_stride; + low += low_stride; + high += high_stride; + } +} + +static void vert_filter(int16_t *input, int16_t *low, int16_t *high, + ptrdiff_t in_stride, ptrdiff_t low_stride, + ptrdiff_t high_stride, + int width, int height) +{ + for (int i = 0; i < width; i++) + filter(&input[i], in_stride, &low[i], low_stride, &high[i], high_stride, height); +} + +av_cold void ff_cfhdencdsp_init(CFHDEncDSPContext *c) +{ + c->horiz_filter = horiz_filter; + c->vert_filter = vert_filter; + + if (ARCH_X86) + ff_cfhdencdsp_init_x86(c); +} diff -Nru ffmpeg-4.2.2/libavcodec/cfhdencdsp.h ffmpeg-4.4/libavcodec/cfhdencdsp.h --- ffmpeg-4.2.2/libavcodec/cfhdencdsp.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cfhdencdsp.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,41 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CFHDENCDSP_H +#define AVCODEC_CFHDENCDSP_H + +#include +#include + +typedef struct CFHDEncDSPContext { + void (*horiz_filter)(int16_t *input, int16_t *low, int16_t *high, + ptrdiff_t in_stride, ptrdiff_t low_stride, + ptrdiff_t high_stride, + int width, int height); + + void (*vert_filter)(int16_t *input, int16_t *low, int16_t *high, + ptrdiff_t in_stride, ptrdiff_t low_stride, + ptrdiff_t high_stride, + int width, int height); +} CFHDEncDSPContext; + +void ff_cfhdencdsp_init(CFHDEncDSPContext *c); + +void ff_cfhdencdsp_init_x86(CFHDEncDSPContext *c); + +#endif /* AVCODEC_CFHDENCDSP_H */ diff -Nru ffmpeg-4.2.2/libavcodec/cfhd.h ffmpeg-4.4/libavcodec/cfhd.h --- ffmpeg-4.2.2/libavcodec/cfhd.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cfhd.h 2021-04-08 21:28:39.000000000 +0000 @@ -29,9 +29,75 @@ #include "bytestream.h" #include "get_bits.h" #include "vlc.h" +#include "cfhddsp.h" + +enum CFHDParam { + SampleType = 1, + SampleIndexTable = 2, + BitstreamMarker = 4, + VersionMajor = 5, + VersionMinor = 6, + VersionRevision = 7, + VersionEdit = 8, + TransformType = 10, + NumFrames = 11, + ChannelCount = 12, + WaveletCount = 13, + SubbandCount = 14, + NumSpatial = 15, + FirstWavelet = 16, + GroupTrailer = 18, + FrameType = 19, + ImageWidth = 20, + ImageHeight = 21, + FrameIndex = 23, + LowpassSubband = 25, + NumLevels = 26, + LowpassWidth = 27, + LowpassHeight = 28, + PixelOffset = 33, + LowpassQuantization=34, + LowpassPrecision = 35, + WaveletType = 37, + WaveletNumber = 38, + WaveletLevel = 39, + NumBands = 40, + HighpassWidth = 41, + HighpassHeight = 42, + LowpassBorder = 43, + HighpassBorder = 44, + LowpassScale = 45, + LowpassDivisor = 46, + SubbandNumber = 48, + BandWidth = 49, + BandHeight = 50, + SubbandBand = 51, + BandEncoding = 52, + Quantization = 53, + BandScale = 54, + BandHeader = 55, + BandTrailer = 56, + ChannelNumber = 62, + SampleFlags = 68, + FrameNumber = 69, + Precision = 70, + InputFormat = 71, + BandCodingFlags = 72, + PeakLevel = 74, + PeakOffsetLow = 75, + PeakOffsetHigh = 76, + Version = 79, + BandSecondPass = 82, + PrescaleTable = 83, + EncodedFormat = 84, + DisplayHeight = 85, + ChannelWidth = 104, + ChannelHeight = 105, +}; #define VLC_BITS 9 #define SUBBAND_COUNT 10 +#define SUBBAND_COUNT_3D 17 typedef struct CFHD_RL_VLC_ELEM { int16_t level; @@ -40,18 +106,15 @@ } CFHD_RL_VLC_ELEM; #define DWT_LEVELS 3 +#define DWT_LEVELS_3D 6 typedef struct SubBand { - int level; - int orientation; ptrdiff_t stride; int a_width; int width; int a_height; int height; - int pshift; - int quant; - uint8_t *ibuf; + int8_t read_ok; } SubBand; typedef struct Plane { @@ -61,12 +124,13 @@ int16_t *idwt_buf; int16_t *idwt_tmp; + int idwt_size; /* TODO: merge this into SubBand structure */ - int16_t *subband[SUBBAND_COUNT]; - int16_t *l_h[8]; + int16_t *subband[SUBBAND_COUNT_3D]; + int16_t *l_h[10]; - SubBand band[DWT_LEVELS][4]; + SubBand band[DWT_LEVELS_3D][4]; } Plane; typedef struct Peak { @@ -84,8 +148,15 @@ CFHD_RL_VLC_ELEM table_18_rl_vlc[4572]; VLC vlc_18; + int lut[2][256]; + GetBitContext gb; + int planes; + int frame_type; + int frame_index; + int sample_type; + int transform_type; int coded_width; int coded_height; int cropped_height; @@ -95,15 +166,15 @@ int a_width; int a_height; int a_format; + int a_transform_type; int bpc; // bits per channel/component int channel_cnt; int subband_cnt; + int band_encoding; int channel_num; uint8_t lowpass_precision; uint16_t quantisation; - int wavelet_depth; - int pshift; int codebook; int difference_coding; @@ -111,9 +182,11 @@ int level; int subband_num_actual; - uint8_t prescale_shift[3]; + uint8_t prescale_table[8]; Plane plane[4]; Peak peak; + + CFHDDSPContext dsp; } CFHDContext; int ff_cfhd_init_vlcs(CFHDContext *s); diff -Nru ffmpeg-4.2.2/libavcodec/chomp_bsf.c ffmpeg-4.4/libavcodec/chomp_bsf.c --- ffmpeg-4.2.2/libavcodec/chomp_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/chomp_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -19,9 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avcodec.h" #include "bsf.h" -#include "internal.h" +#include "bsf_internal.h" static int chomp_filter(AVBSFContext *ctx, AVPacket *pkt) { diff -Nru ffmpeg-4.2.2/libavcodec/cinepak.c ffmpeg-4.4/libavcodec/cinepak.c --- ffmpeg-4.2.2/libavcodec/cinepak.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cinepak.c 2021-04-08 21:28:39.000000000 +0000 @@ -473,11 +473,11 @@ return ret; } - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; if (s->palette_video) { - int size; + buffer_size_t size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size); if (pal && size == AVPALETTE_SIZE) { s->frame->palette_has_changed = 1; @@ -522,4 +522,5 @@ .close = cinepak_decode_end, .decode = cinepak_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/cinepakenc.c ffmpeg-4.4/libavcodec/cinepakenc.c --- ffmpeg-4.2.2/libavcodec/cinepakenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cinepakenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -171,22 +171,22 @@ if (!(s->last_frame = av_frame_alloc())) return AVERROR(ENOMEM); if (!(s->best_frame = av_frame_alloc())) - goto enomem; + return AVERROR(ENOMEM); if (!(s->scratch_frame = av_frame_alloc())) - goto enomem; + return AVERROR(ENOMEM); if (avctx->pix_fmt == AV_PIX_FMT_RGB24) if (!(s->input_frame = av_frame_alloc())) - goto enomem; + return AVERROR(ENOMEM); if (!(s->codebook_input = av_malloc_array((avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4) * (avctx->width * avctx->height) >> 2, sizeof(*s->codebook_input)))) - goto enomem; + return AVERROR(ENOMEM); if (!(s->codebook_closest = av_malloc_array((avctx->width * avctx->height) >> 2, sizeof(*s->codebook_closest)))) - goto enomem; + return AVERROR(ENOMEM); for (x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) if (!(s->pict_bufs[x] = av_malloc((avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4) * (avctx->width * avctx->height) >> 2))) - goto enomem; + return AVERROR(ENOMEM); mb_count = avctx->width * avctx->height / MB_AREA; @@ -199,13 +199,13 @@ frame_buf_size = CVID_HEADER_SIZE + s->max_max_strips * strip_buf_size; if (!(s->strip_buf = av_malloc(strip_buf_size))) - goto enomem; + return AVERROR(ENOMEM); if (!(s->frame_buf = av_malloc(frame_buf_size))) - goto enomem; + return AVERROR(ENOMEM); if (!(s->mb = av_malloc_array(mb_count, sizeof(mb_info)))) - goto enomem; + return AVERROR(ENOMEM); av_lfg_init(&s->randctx, 1); s->avctx = avctx; @@ -252,23 +252,6 @@ s->max_strips = s->max_max_strips; return 0; - -enomem: - av_frame_free(&s->last_frame); - av_frame_free(&s->best_frame); - av_frame_free(&s->scratch_frame); - if (avctx->pix_fmt == AV_PIX_FMT_RGB24) - av_frame_free(&s->input_frame); - av_freep(&s->codebook_input); - av_freep(&s->codebook_closest); - av_freep(&s->strip_buf); - av_freep(&s->frame_buf); - av_freep(&s->mb); - - for (x = 0; x < (avctx->pix_fmt == AV_PIX_FMT_RGB24 ? 4 : 3); x++) - av_freep(&s->pict_bufs[x]); - - return AVERROR(ENOMEM); } static int64_t calculate_mode_score(CinepakEncContext *s, int h, @@ -544,8 +527,9 @@ uint8_t *last_data[4], int last_linesize[4], strip_info *info, unsigned char *buf) { - int x, y, z, flags, bits, temp_size, header_ofs, ret = 0, mb_count = s->w * h / MB_AREA; + int x, y, z, bits, temp_size, header_ofs, ret = 0, mb_count = s->w * h / MB_AREA; int needs_extra_bit, should_write_temp; + uint32_t flags; unsigned char temp[64]; // 32/2 = 16 V4 blocks at 4 B each -> 64 B mb_info *mb; uint8_t *sub_scratch_data[4] = { 0 }, *sub_last_data[4] = { 0 }; @@ -599,7 +583,7 @@ flags = 0; for (y = x; y < FFMIN(x + 32, mb_count); y++) if (s->mb[y].best_encoding == ENC_V4) - flags |= 1 << (31 - y + x); + flags |= 1U << (31 - y + x); AV_WB32(&buf[ret], flags); ret += 4; @@ -626,13 +610,13 @@ for (x = 0; x < mb_count; x++) { mb = &s->mb[x]; - flags |= (mb->best_encoding != ENC_SKIP) << (31 - bits++); + flags |= (uint32_t)(mb->best_encoding != ENC_SKIP) << (31 - bits++); needs_extra_bit = 0; should_write_temp = 0; if (mb->best_encoding != ENC_SKIP) { if (bits < 32) - flags |= (mb->best_encoding == ENC_V4) << (31 - bits++); + flags |= (uint32_t)(mb->best_encoding == ENC_V4) << (31 - bits++); else needs_extra_bit = 1; } @@ -651,7 +635,7 @@ } if (needs_extra_bit) { - flags = (mb->best_encoding == ENC_V4) << 31; + flags = (uint32_t)(mb->best_encoding == ENC_V4) << 31; bits = 1; } @@ -1205,4 +1189,5 @@ .close = cinepak_encode_end, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }, .priv_class = &cinepak_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/clearvideo.c ffmpeg-4.4/libavcodec/clearvideo.c --- ffmpeg-4.2.2/libavcodec/clearvideo.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/clearvideo.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,9 @@ * ClearVideo decoder */ +#include "libavutil/mem_internal.h" +#include "libavutil/thread.h" + #include "avcodec.h" #include "bytestream.h" #include "get_bits.h" @@ -32,9 +35,9 @@ #include "mathops.h" #include "clearvideodata.h" +#define CLV_VLC_BITS 9 + typedef struct LevelCodes { - uint16_t mv_esc; - uint16_t bias_esc; VLC flags_cb; VLC mv_cb; VLC bias_cb; @@ -73,13 +76,15 @@ MVInfo mvi; int tile_size; int tile_shift; - VLC dc_vlc, ac_vlc; - LevelCodes ylev[4], ulev[3], vlev[3]; int luma_dc_quant, chroma_dc_quant, ac_quant; DECLARE_ALIGNED(16, int16_t, block)[64]; int top_dc[3], left_dc[4]; } CLVContext; +static VLC dc_vlc, ac_vlc; +static LevelCodes lev[4 + 3 + 3]; // 0..3: Y, 4..6: U, 7..9: V +static VLC_TYPE vlc_buf[16716][2]; + static inline int decode_block(CLVContext *ctx, int16_t *blk, int has_ac, int ac_quant) { @@ -87,16 +92,13 @@ int idx = 1, last = 0, val, skip; memset(blk, 0, sizeof(*blk) * 64); - blk[0] = get_vlc2(gb, ctx->dc_vlc.table, 9, 3); - if (blk[0] < 0) - return AVERROR_INVALIDDATA; - blk[0] -= 63; + blk[0] = get_vlc2(gb, dc_vlc.table, CLV_VLC_BITS, 3); if (!has_ac) return 0; while (idx < 64 && !last) { - val = get_vlc2(gb, ctx->ac_vlc.table, 9, 2); + val = get_vlc2(gb, ac_vlc.table, CLV_VLC_BITS, 2); if (val < 0) return AVERROR_INVALIDDATA; if (val != 0x1BFF) { @@ -359,7 +361,7 @@ } } -static TileInfo* decode_tile_info(GetBitContext *gb, LevelCodes *lc, int level) +static TileInfo *decode_tile_info(GetBitContext *gb, const LevelCodes *lc, int level) { TileInfo *ti; int i, flags = 0; @@ -367,13 +369,13 @@ MV mv = { 0 }; if (lc[level].flags_cb.table) { - flags = get_vlc2(gb, lc[level].flags_cb.table, lc[level].flags_cb.bits, 2); + flags = get_vlc2(gb, lc[level].flags_cb.table, CLV_VLC_BITS, 2); } if (lc[level].mv_cb.table) { - uint16_t mv_code = get_vlc2(gb, lc[level].mv_cb.table, lc[level].mv_cb.bits, 3); + uint16_t mv_code = get_vlc2(gb, lc[level].mv_cb.table, CLV_VLC_BITS, 2); - if (mv_code != lc[level].mv_esc) { + if (mv_code != MV_ESC) { mv.x = (int8_t)(mv_code & 0xff); mv.y = (int8_t)(mv_code >> 8); } else { @@ -383,9 +385,9 @@ } if (lc[level].bias_cb.table) { - uint16_t bias_val = get_vlc2(gb, lc[level].bias_cb.table, lc[level].bias_cb.bits, 2); + uint16_t bias_val = get_vlc2(gb, lc[level].bias_cb.table, CLV_VLC_BITS, 2); - if (bias_val != lc[level].bias_esc) { + if (bias_val != BIAS_ESC) { bias = (int16_t)(bias_val); } else { bias = get_sbits(gb, 16); @@ -524,7 +526,7 @@ return AVERROR_INVALIDDATA; } - if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) + if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) return ret; c->pic->key_frame = 1; @@ -558,7 +560,7 @@ if (c->pmb_width * c->pmb_height > 8LL*(buf_size - bytestream2_tell(&gb))) return AVERROR_INVALIDDATA; - if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) + if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) return ret; ret = av_frame_copy(c->pic, c->prev); @@ -596,7 +598,7 @@ TileInfo *tile; MV mv, cmv; - tile = decode_tile_info(&c->gb, c->ylev, 0); + tile = decode_tile_info(&c->gb, &lev[0], 0); // Y if (!tile) return AVERROR(ENOMEM); mv = mvi_predict(&c->mvi, i, j, tile->mv); @@ -611,14 +613,14 @@ cmv.x /= 2; cmv.y /= 2; av_freep(&tile); - tile = decode_tile_info(&c->gb, c->ulev, 0); + tile = decode_tile_info(&c->gb, &lev[4], 0); // U if (!tile) return AVERROR(ENOMEM); ret = restore_tree(avctx, c->pic, c->prev, 1, x, y, size, tile, cmv); if (ret < 0) mb_ret = ret; av_freep(&tile); - tile = decode_tile_info(&c->gb, c->vlev, 0); + tile = decode_tile_info(&c->gb, &lev[7], 0); // V if (!tile) return AVERROR(ENOMEM); ret = restore_tree(avctx, c->pic, c->prev, 2, x, y, size, tile, cmv); @@ -648,8 +650,63 @@ return mb_ret < 0 ? mb_ret : buf_size; } +static av_cold void build_vlc(VLC *vlc, const uint8_t counts[16], + const uint16_t **syms, unsigned *offset) +{ + uint8_t lens[MAX_VLC_ENTRIES]; + unsigned num = 0; + + for (int i = 0; i < 16; i++) { + unsigned count = counts[i]; + if (count == 255) /* Special case for Y_3 table */ + count = 303; + for (count += num; num < count; num++) + lens[num] = i + 1; + } + vlc->table = &vlc_buf[*offset]; + vlc->table_allocated = FF_ARRAY_ELEMS(vlc_buf) - *offset; + ff_init_vlc_from_lengths(vlc, CLV_VLC_BITS, num, lens, 1, + *syms, 2, 2, 0, INIT_VLC_STATIC_OVERLONG, NULL); + *syms += num; + *offset += vlc->table_size; +} + +static av_cold void clv_init_static(void) +{ + const uint16_t *mv_syms = clv_mv_syms, *bias_syms = clv_bias_syms; + + INIT_VLC_STATIC_FROM_LENGTHS(&dc_vlc, CLV_VLC_BITS, NUM_DC_CODES, + clv_dc_lens, 1, + clv_dc_syms, 1, 1, -63, 0, 1104); + INIT_VLC_STATIC_FROM_LENGTHS(&ac_vlc, CLV_VLC_BITS, NUM_AC_CODES, + clv_ac_bits, 1, + clv_ac_syms, 2, 2, 0, 0, 554); + for (unsigned i = 0, j = 0, k = 0, offset = 0;; i++) { + if (0x36F & (1 << i)) { + build_vlc(&lev[i].mv_cb, clv_mv_len_counts[k], &mv_syms, &offset); + k++; + } + if (i == FF_ARRAY_ELEMS(lev) - 1) + break; + if (0x1B7 & (1 << i)) { + lev[i].flags_cb.table = &vlc_buf[offset]; + lev[i].flags_cb.table_allocated = FF_ARRAY_ELEMS(vlc_buf) - offset; + ff_init_vlc_from_lengths(&lev[i].flags_cb, CLV_VLC_BITS, 16, + clv_flags_bits[j], 1, + clv_flags_syms[j], 1, 1, + 0, INIT_VLC_STATIC_OVERLONG, NULL); + offset += lev[i].flags_cb.table_size; + + build_vlc(&lev[i + 1].bias_cb, clv_bias_len_counts[j], + &bias_syms, &offset); + j++; + } + } +} + static av_cold int clv_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; CLVContext *const c = avctx->priv_data; int ret, w, h; @@ -691,185 +748,8 @@ return AVERROR(ENOMEM); ff_idctdsp_init(&c->idsp, avctx); - ret = init_vlc(&c->dc_vlc, 9, NUM_DC_CODES, - clv_dc_bits, 1, 1, - clv_dc_codes, 1, 1, 0); - if (ret) { - av_log(avctx, AV_LOG_ERROR, "Error initialising DC VLC\n"); - return ret; - } - ret = ff_init_vlc_sparse(&c->ac_vlc, 9, NUM_AC_CODES, - clv_ac_bits, 1, 1, - clv_ac_codes, 1, 1, - clv_ac_syms, 2, 2, 0); - if (ret) { - av_log(avctx, AV_LOG_ERROR, "Error initialising AC VLC\n"); - return ret; - } - - ret = init_vlc(&c->ylev[0].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsy_0_bits), - clv_flagsy_0_bits, 1, 1, - clv_flagsy_0_codes, 2, 2, 0); - if (ret) - return ret; - - ret = init_vlc(&c->ylev[1].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsy_1_bits), - clv_flagsy_1_bits, 1, 1, - clv_flagsy_1_codes, 2, 2, 0); - if (ret) - return ret; - - ret = init_vlc(&c->ylev[2].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsy_2_bits), - clv_flagsy_2_bits, 1, 1, - clv_flagsy_2_codes, 2, 2, 0); - if (ret) - return ret; - - ret = init_vlc(&c->ulev[0].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsu_0_bits), - clv_flagsu_0_bits, 1, 1, - clv_flagsu_0_codes, 2, 2, 0); - if (ret) - return ret; - - ret = init_vlc(&c->ulev[1].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsu_1_bits), - clv_flagsu_1_bits, 1, 1, - clv_flagsu_1_codes, 2, 2, 0); - if (ret) - return ret; - - ret = init_vlc(&c->vlev[0].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsv_0_bits), - clv_flagsv_0_bits, 1, 1, - clv_flagsv_0_codes, 2, 2, 0); - if (ret) - return ret; - - ret = init_vlc(&c->vlev[1].flags_cb, 9, FF_ARRAY_ELEMS(clv_flagsv_1_bits), - clv_flagsv_1_bits, 1, 1, - clv_flagsv_1_codes, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->ylev[0].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvy_0_bits), - clv_mvy_0_bits, 1, 1, - clv_mvy_0_codes, 2, 2, - clv_mvy_0_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->ylev[1].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvy_1_bits), - clv_mvy_1_bits, 1, 1, - clv_mvy_1_codes, 2, 2, - clv_mvy_1_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->ylev[2].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvy_2_bits), - clv_mvy_2_bits, 1, 1, - clv_mvy_2_codes, 2, 2, - clv_mvy_2_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->ylev[3].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvy_3_bits), - clv_mvy_3_bits, 1, 1, - clv_mvy_3_codes, 2, 2, - clv_mvy_3_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->ulev[1].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvu_1_bits), - clv_mvu_1_bits, 1, 1, - clv_mvu_1_codes, 2, 2, - clv_mvu_1_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->ulev[2].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvu_2_bits), - clv_mvu_2_bits, 1, 1, - clv_mvu_2_codes, 2, 2, - clv_mvu_2_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->vlev[1].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvv_1_bits), - clv_mvv_1_bits, 1, 1, - clv_mvv_1_codes, 2, 2, - clv_mvv_1_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->vlev[2].mv_cb, 9, FF_ARRAY_ELEMS(clv_mvv_2_bits), - clv_mvv_2_bits, 1, 1, - clv_mvv_2_codes, 2, 2, - clv_mvv_2_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->ylev[1].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasy_1_bits), - clv_biasy_1_bits, 1, 1, - clv_biasy_1_codes, 2, 2, - clv_biasy_1_syms, 2, 2, 0); - if (ret) - return ret; - ret = ff_init_vlc_sparse(&c->ylev[2].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasy_2_bits), - clv_biasy_2_bits, 1, 1, - clv_biasy_2_codes, 2, 2, - clv_biasy_2_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->ylev[3].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasy_3_bits), - clv_biasy_3_bits, 1, 1, - clv_biasy_3_codes, 2, 2, - clv_biasy_3_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->ulev[1].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasu_1_bits), - clv_biasu_1_bits, 1, 1, - clv_biasu_1_codes, 2, 2, - clv_biasu_1_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->ulev[2].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasu_2_bits), - clv_biasu_2_bits, 1, 1, - clv_biasu_2_codes, 2, 2, - clv_biasu_2_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->vlev[1].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasv_1_bits), - clv_biasv_1_bits, 1, 1, - clv_biasv_1_codes, 2, 2, - clv_biasv_1_syms, 2, 2, 0); - if (ret) - return ret; - - ret = ff_init_vlc_sparse(&c->vlev[2].bias_cb, 9, FF_ARRAY_ELEMS(clv_biasv_2_bits), - clv_biasv_2_bits, 1, 1, - clv_biasv_2_codes, 2, 2, - clv_biasv_2_syms, 2, 2, 0); - if (ret) - return ret; - - c->ylev[0].mv_esc = 0x0909; - c->ylev[1].mv_esc = 0x0A0A; - c->ylev[2].mv_esc = 0x1010; - c->ylev[3].mv_esc = 0x1313; - c->ulev[1].mv_esc = 0x0808; - c->ulev[2].mv_esc = 0x0B0B; - c->vlev[1].mv_esc = 0x0808; - c->vlev[2].mv_esc = 0x0B0B; - - c->ylev[1].bias_esc = 0x100; - c->ylev[2].bias_esc = 0x100; - c->ylev[3].bias_esc = 0x100; - c->ulev[1].bias_esc = 0x100; - c->ulev[2].bias_esc = 0x100; - c->vlev[1].bias_esc = 0x100; - c->vlev[2].bias_esc = 0x100; + ff_thread_once(&init_static_once, clv_init_static); return 0; } @@ -877,29 +757,12 @@ static av_cold int clv_decode_end(AVCodecContext *avctx) { CLVContext *const c = avctx->priv_data; - int i; av_frame_free(&c->prev); av_frame_free(&c->pic); av_freep(&c->mvi.mv); - ff_free_vlc(&c->dc_vlc); - ff_free_vlc(&c->ac_vlc); - for (i = 0; i < 4; i++) { - ff_free_vlc(&c->ylev[i].mv_cb); - ff_free_vlc(&c->ylev[i].flags_cb); - ff_free_vlc(&c->ylev[i].bias_cb); - } - for (i = 0; i < 3; i++) { - ff_free_vlc(&c->ulev[i].mv_cb); - ff_free_vlc(&c->ulev[i].flags_cb); - ff_free_vlc(&c->ulev[i].bias_cb); - ff_free_vlc(&c->vlev[i].mv_cb); - ff_free_vlc(&c->vlev[i].flags_cb); - ff_free_vlc(&c->vlev[i].bias_cb); - } - return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/clearvideodata.h ffmpeg-4.4/libavcodec/clearvideodata.h --- ffmpeg-4.2.2/libavcodec/clearvideodata.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/clearvideodata.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,1809 +24,659 @@ #include "libavutil/common.h" +#define MAX_VLC_ENTRIES 1370 #define NUM_DC_CODES 127 -#define NUM_AC_CODES 103 +#define NUM_AC_CODES 104 -static const uint8_t clv_dc_codes[NUM_DC_CODES] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x07, 0x0B, - 0x0C, 0x08, 0x08, 0x09, 0x04, 0x06, 0x07, 0x05, - 0x04, 0x05, 0x04, 0x06, 0x05, 0x06, 0x07, 0x05, - 0x06, 0x07, 0x06, 0x07, 0x08, 0x06, 0x07, 0x08, - 0x09, 0x0A, 0x0B, 0x07, 0x08, 0x09, 0x07, 0x08, - 0x06, 0x07, 0x08, 0x06, 0x04, 0x05, 0x02, 0x01, - 0x03, 0x06, 0x07, 0x07, 0x09, 0x0A, 0x0B, 0x09, - 0x0A, 0x0B, 0x0A, 0x0B, 0x0C, 0x0D, 0x0C, 0x09, - 0x0D, 0x0A, 0x0B, 0x08, 0x09, 0x0A, 0x0B, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x06, 0x07, 0x06, 0x08, - 0x07, 0x09, 0x0A, 0x0B, 0x09, 0x0A, 0x0B, 0x0C, - 0x14, 0x0D, 0x0D, 0x0E, 0x0F, 0x15, 0x15, 0x16, - 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, - 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, -}; - -static const uint8_t clv_dc_bits[NUM_DC_CODES] = { - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 21, 22, 22, 19, 20, - 20, 19, 18, 18, 15, 17, 17, 16, - 14, 15, 12, 13, 14, 14, 14, 12, - 12, 12, 11, 11, 11, 10, 10, 10, - 10, 10, 10, 9, 9, 9, 8, 8, - 7, 7, 7, 6, 5, 5, 3, 1, - 3, 5, 5, 6, 7, 7, 7, 8, - 8, 8, 9, 9, 9, 9, 10, 11, - 10, 11, 11, 12, 12, 12, 12, 13, - 14, 14, 14, 14, 15, 15, 16, 17, - 16, 17, 18, 18, 19, 19, 19, 19, - 21, 19, 20, 19, 19, 21, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, +static const uint8_t clv_dc_lens[NUM_DC_CODES] = { + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 21, 21, 21, 20, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 19, 18, 18, 18, 18, + 17, 17, 17, 17, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, + 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 10, 10, 10, + 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7, + 7, 7, 7, 7, 6, 6, 5, 5, 5, 5, 3, 3, 1, +}; + +static const uint8_t clv_dc_syms[NUM_DC_CODES] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x14, 0x15, 0x6E, 0x6F, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, + 0x7D, 0x7E, 0x13, 0x68, 0x6D, 0x17, 0x18, 0x6A, 0x16, 0x19, 0x64, 0x65, + 0x66, 0x67, 0x69, 0x6B, 0x6C, 0x1A, 0x1B, 0x62, 0x63, 0x1D, 0x1E, 0x5F, + 0x61, 0x1F, 0x5E, 0x60, 0x1C, 0x21, 0x5C, 0x5D, 0x20, 0x24, 0x25, 0x26, + 0x58, 0x59, 0x5A, 0x5B, 0x23, 0x57, 0x22, 0x27, 0x28, 0x29, 0x53, 0x54, + 0x55, 0x56, 0x2A, 0x2B, 0x2C, 0x4F, 0x51, 0x52, 0x2D, 0x2E, 0x2F, 0x30, + 0x31, 0x32, 0x4E, 0x50, 0x33, 0x34, 0x35, 0x4A, 0x4B, 0x4C, 0x4D, 0x36, + 0x37, 0x47, 0x48, 0x49, 0x38, 0x39, 0x3A, 0x44, 0x45, 0x46, 0x3B, 0x43, + 0x3C, 0x3D, 0x41, 0x42, 0x3E, 0x40, 0x3F, }; static const uint16_t clv_ac_syms[NUM_AC_CODES] = { - 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, - 0x0009, 0x000A, 0x000B, 0x000C, 0x0011, 0x0012, 0x0013, 0x0014, - 0x0015, 0x0016, 0x0021, 0x0022, 0x0023, 0x0024, 0x0031, 0x0032, - 0x0033, 0x0041, 0x0042, 0x0043, 0x0051, 0x0052, 0x0053, 0x0061, - 0x0062, 0x0063, 0x0071, 0x0072, 0x0081, 0x0082, 0x0091, 0x0092, - 0x00A1, 0x00A2, 0x00B1, 0x00C1, 0x00D1, 0x00E1, 0x00F1, 0x0101, - 0x0111, 0x0121, 0x0131, 0x0141, 0x0151, 0x0161, 0x0171, 0x0181, - 0x0191, 0x01A1, 0x1001, 0x1002, 0x1003, 0x1011, 0x1012, 0x1021, - 0x1031, 0x1041, 0x1051, 0x1061, 0x1071, 0x1081, 0x1091, 0x10A1, - 0x10B1, 0x10C1, 0x10D1, 0x10E1, 0x10F1, 0x1101, 0x1111, 0x1121, - 0x1131, 0x1141, 0x1151, 0x1161, 0x1171, 0x1181, 0x1191, 0x11A1, - 0x11B1, 0x11C1, 0x11D1, 0x11E1, 0x11F1, 0x1201, 0x1211, 0x1221, - 0x1231, 0x1241, 0x1251, 0x1261, 0x1271, 0x1281, 0x1BFF, -}; - -static const uint8_t clv_ac_codes[NUM_AC_CODES] = { - 0x02, 0x0F, 0x15, 0x17, 0x1F, 0x25, 0x24, 0x21, - 0x20, 0x07, 0x06, 0x20, 0x06, 0x14, 0x1E, 0x0F, - 0x21, 0x50, 0x0E, 0x1D, 0x0E, 0x51, 0x0D, 0x23, - 0x0D, 0x0C, 0x22, 0x52, 0x0B, 0x0C, 0x53, 0x13, - 0x0B, 0x54, 0x12, 0x0A, 0x11, 0x09, 0x10, 0x08, - 0x16, 0x55, 0x15, 0x14, 0x1C, 0x1B, 0x21, 0x20, - 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x22, 0x23, - 0x56, 0x57, 0x07, 0x19, 0x05, 0x0F, 0x04, 0x0E, - 0x0D, 0x0C, 0x13, 0x12, 0x11, 0x10, 0x1A, 0x19, - 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x18, 0x17, - 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x07, 0x06, - 0x05, 0x04, 0x24, 0x25, 0x26, 0x27, 0x58, 0x59, - 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x03, + 0x0000, 0x1012, 0x1003, 0x000B, 0x000A, 0x11C1, 0x11B1, 0x11A1, 0x1191, + 0x0092, 0x0082, 0x0072, 0x0062, 0x0052, 0x0033, 0x0023, 0x0014, 0x000C, + 0x0015, 0x0171, 0x0181, 0x11D1, 0x11E1, 0x11F1, 0x1201, 0x0016, 0x0024, + 0x0043, 0x0053, 0x0063, 0x00A2, 0x0191, 0x01A1, 0x1211, 0x1221, 0x1231, + 0x1241, 0x1251, 0x1261, 0x1271, 0x1281, 0x1BFF, 0x0009, 0x0008, 0x1181, + 0x1171, 0x1161, 0x1151, 0x1141, 0x1131, 0x1121, 0x1111, 0x1002, 0x0161, + 0x0151, 0x0141, 0x0131, 0x0121, 0x0111, 0x0101, 0x00F1, 0x0042, 0x0032, + 0x0007, 0x0006, 0x1101, 0x10F1, 0x10E1, 0x10D1, 0x10C1, 0x10B1, 0x10A1, + 0x1091, 0x00E1, 0x00D1, 0x0022, 0x0013, 0x0005, 0x1081, 0x1071, 0x1061, + 0x1051, 0x00C1, 0x00B1, 0x00A1, 0x0004, 0x1041, 0x1031, 0x1021, 0x1011, + 0x0091, 0x0081, 0x0071, 0x0061, 0x0012, 0x0003, 0x0051, 0x0041, 0x0031, + 0x1001, 0x0001, 0x0011, 0x0021, 0x0002 }; +/* The -9 refers to an open end in the tree. */ static const uint8_t clv_ac_bits[NUM_AC_CODES] = { - 2, 4, 6, 7, 8, 9, 9, 10, - 10, 11, 11, 11, 3, 6, 8, 10, - 11, 12, 4, 8, 10, 12, 5, 9, - 10, 5, 9, 12, 5, 10, 12, 6, - 10, 12, 6, 10, 6, 10, 6, 10, - 7, 12, 7, 7, 8, 8, 9, 9, - 9, 9, 9, 9, 9, 9, 11, 11, - 12, 12, 4, 9, 11, 6, 11, 6, - 6, 6, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 8, 8, 8, 9, 9, - 9, 9, 9, 9, 9, 9, 10, 10, - 10, 10, 11, 11, 11, 11, 12, 12, - 12, 12, 12, 12, 12, 12, 7, -}; - -static const uint8_t clv_flagsy_0_bits[] = { - 3, 4, 4, 4, 4, 4, 6, 5, 4, 7, 4, 5, 4, 7, 5, 2, -}; - -static const uint16_t clv_flagsy_0_codes[] = { - 0x0002, 0x0009, 0x000B, 0x0006, 0x000C, 0x0007, 0x003E, 0x001C, - 0x000D, 0x007E, 0x000A, 0x001D, 0x0008, 0x007F, 0x001E, 0x0000, -}; - -static const uint8_t clv_flagsy_1_bits[] = { - 2, 4, 4, 3, 4, 4, 7, 6, 4, 6, 4, 6, 4, 8, 8, 3, -}; - -static const uint16_t clv_flagsy_1_codes[] = { - 0x0000, 0x000A, 0x000C, 0x0003, 0x000B, 0x0009, 0x007E, 0x003D, - 0x000D, 0x003E, 0x000E, 0x003C, 0x0008, 0x00FE, 0x00FF, 0x0002, -}; - -static const uint8_t clv_flagsy_2_bits[] = { - 1, 4, 4, 4, 4, 5, 7, 5, 4, 6, 5, 8, 4, 9, 10, 10, -}; - -static const uint16_t clv_flagsy_2_codes[] = { - 0x0000, 0x000C, 0x000B, 0x0008, 0x000A, 0x001C, 0x007E, 0x001D, - 0x000D, 0x003E, 0x001E, 0x00FE, 0x0009, 0x01FE, 0x03FE, 0x03FF, -}; - -static const uint8_t clv_flagsu_0_bits[] = { - 1, 4, 4, 4, 5, 5, 9, 7, 5, 9, 4, 7, 4, 8, 7, 4, -}; - -static const uint16_t clv_flagsu_0_codes[] = { - 0x0000, 0x000B, 0x000D, 0x0009, 0x001D, 0x001C, 0x01FF, 0x007D, - 0x001E, 0x01FE, 0x000C, 0x007C, 0x000A, 0x00FE, 0x007E, 0x0008, -}; - -static const uint8_t clv_flagsu_1_bits[] = { - 1, 4, 4, 4, 4, 4, 8, 6, 4, 8, 5, 8, 4, 10, 9, 10, -}; - -static const uint16_t clv_flagsu_1_codes[] = { - 0x0000, 0x000C, 0x0008, 0x000A, 0x000B, 0x000E, 0x00FD, 0x003E, - 0x000D, 0x00FC, 0x001E, 0x00FE, 0x0009, 0x03FE, 0x01FE, 0x03FF, -}; - -static const uint8_t clv_flagsv_0_bits[] = { - 1, 4, 5, 4, 5, 5, 8, 10, 5, 9, 5, 6, 4, 10, 7, 3, -}; - -static const uint16_t clv_flagsv_0_codes[] = { - 0x0000, 0x000A, 0x001B, 0x000C, 0x001E, 0x001C, 0x00FE, 0x03FE, - 0x001D, 0x01FE, 0x001A, 0x003E, 0x000B, 0x03FF, 0x007E, 0x0004, -}; - -static const uint8_t clv_flagsv_1_bits[] = { - 1, 4, 4, 4, 4, 5, 8, 6, 3, 7, 5, 10, 5, 11, 9, 11, -}; - -static const uint16_t clv_flagsv_1_codes[] = { - 0x0000, 0x000D, 0x000C, 0x000A, 0x000B, 0x001D, 0x00FE, 0x003E, - 0x0004, 0x007E, 0x001E, 0x03FE, 0x001C, 0x07FE, 0x01FE, 0x07FF, -}; - -static const uint8_t clv_mvy_0_bits[] = { - 16, 14, 13, 13, 13, 12, 11, 11, 9, 11, 11, 12, 13, 13, 13, 14, - 16, 15, 14, 14, 14, 13, 13, 12, 10, 7, 10, 12, 13, 13, 14, 14, - 14, 15, 15, 14, 14, 14, 13, 13, 11, 10, 7, 10, 11, 13, 13, 14, - 14, 14, 15, 15, 14, 14, 13, 13, 12, 11, 10, 7, 10, 11, 12, 13, - 13, 14, 14, 15, 16, 15, 14, 12, 12, 12, 11, 10, 6, 10, 11, 12, - 12, 12, 14, 15, 16, 15, 14, 13, 13, 12, 11, 10, 9, 6, 9, 10, - 11, 12, 13, 13, 14, 15, 14, 14, 13, 12, 12, 11, 10, 8, 6, 8, - 10, 11, 12, 12, 13, 14, 14, 14, 13, 13, 13, 11, 11, 9, 7, 4, - 7, 9, 11, 11, 12, 13, 13, 14, 11, 10, 10, 9, 9, 8, 7, 5, - 1, 5, 7, 8, 9, 9, 10, 10, 11, 14, 13, 13, 12, 11, 11, 9, - 7, 4, 7, 9, 11, 11, 13, 13, 13, 14, 14, 14, 13, 12, 12, 11, - 10, 8, 6, 8, 10, 11, 12, 12, 13, 14, 14, 15, 14, 13, 13, 12, - 11, 10, 9, 7, 9, 10, 11, 12, 13, 13, 14, 15, 16, 15, 14, 12, - 12, 12, 11, 10, 6, 10, 11, 12, 12, 12, 14, 15, 16, 15, 14, 14, - 13, 13, 12, 11, 10, 7, 10, 11, 12, 13, 13, 14, 14, 15, 15, 14, - 14, 14, 13, 13, 11, 10, 7, 10, 11, 13, 13, 14, 14, 14, 15, 15, - 14, 14, 14, 13, 13, 12, 10, 7, 10, 12, 13, 13, 14, 14, 14, 15, - 16, 14, 13, 13, 13, 12, 11, 11, 9, 11, 11, 12, 13, 13, 13, 14, - 16, 6, -}; - -static const uint16_t clv_mvy_0_codes[] = { - 0xFFFD, 0x3FE5, 0x1FD8, 0x1FC4, 0x1FBC, 0x0FCB, 0x07CF, 0x07C4, - 0x01D7, 0x07C6, 0x07CE, 0x0FCA, 0x1FBD, 0x1FC2, 0x1FD9, 0x3FE4, - 0xFFFE, 0x7FF0, 0x3FEF, 0x3FD2, 0x3FC9, 0x1FCC, 0x1FC0, 0x0FB6, - 0x03D6, 0x0070, 0x03D7, 0x0FB7, 0x1FC1, 0x1FCD, 0x3FCB, 0x3FD0, - 0x3FED, 0x7FF2, 0x7FFB, 0x3FDC, 0x3FD9, 0x3FD4, 0x1FB6, 0x1FAE, - 0x07C0, 0x03BC, 0x006D, 0x03BD, 0x07C1, 0x1FAF, 0x1FB7, 0x3FD1, - 0x3FDB, 0x3FDF, 0x7FF9, 0x7FEE, 0x3FF0, 0x3FC7, 0x1FC9, 0x1FA7, - 0x0FAD, 0x07D2, 0x03CE, 0x006C, 0x03CF, 0x07D0, 0x0FAF, 0x1FA6, - 0x1FC6, 0x3FC4, 0x3FF1, 0x7FED, 0xFFFB, 0x7FF6, 0x3FE6, 0x0FCC, - 0x0FC4, 0x0FB0, 0x07B0, 0x03C6, 0x0031, 0x03C7, 0x07B1, 0x0FB1, - 0x0FC5, 0x0FCD, 0x3FEA, 0x7FF7, 0xFFF9, 0x7FE9, 0x3FCE, 0x1FCF, - 0x1FB2, 0x0FB8, 0x07BC, 0x03D0, 0x01DA, 0x002F, 0x01DB, 0x03D1, - 0x07BE, 0x0FBA, 0x1FB4, 0x1FD0, 0x3FCD, 0x7FEB, 0x3FE1, 0x3FC1, - 0x1FD3, 0x0FC3, 0x0FBE, 0x07B6, 0x03C4, 0x00E4, 0x002D, 0x00E5, - 0x03C5, 0x07B7, 0x0FBF, 0x0FC1, 0x1FD2, 0x3FC3, 0x3FE2, 0x3FBF, - 0x1FDB, 0x1FAD, 0x1FA5, 0x07CB, 0x07BB, 0x01D5, 0x0068, 0x0008, - 0x0065, 0x01D2, 0x07B8, 0x07C8, 0x0FD0, 0x1FAA, 0x1FDA, 0x3FBC, - 0x07D4, 0x03CA, 0x03C0, 0x01D8, 0x01D0, 0x00E6, 0x0069, 0x0014, - 0x0000, 0x0015, 0x006A, 0x00E7, 0x01D1, 0x01D9, 0x03C1, 0x03CB, - 0x07D5, 0x3FBE, 0x1FDC, 0x1FAB, 0x0FD1, 0x07C9, 0x07B9, 0x01D3, - 0x0066, 0x0009, 0x0067, 0x01D4, 0x07BA, 0x07CA, 0x1FA4, 0x1FAC, - 0x1FDD, 0x3FBD, 0x3FE0, 0x3FC0, 0x1FD5, 0x0FC0, 0x0FBC, 0x07B4, - 0x03C2, 0x00E2, 0x002C, 0x00E3, 0x03C3, 0x07B5, 0x0FBD, 0x0FC2, - 0x1FD7, 0x3FC2, 0x3FE3, 0x7FEA, 0x3FCC, 0x1FCE, 0x1FB3, 0x0FB9, - 0x07BD, 0x03D2, 0x01DC, 0x0064, 0x01DD, 0x03D3, 0x07BF, 0x0FBB, - 0x1FB5, 0x1FD1, 0x3FCF, 0x7FE8, 0xFFFA, 0x7FF4, 0x3FEB, 0x0FCE, - 0x0FC6, 0x0FB2, 0x07B2, 0x03C8, 0x0030, 0x03C9, 0x07B3, 0x0FB3, - 0x0FC7, 0x0FCF, 0x3FE9, 0x7FF5, 0xFFF8, 0x7FF3, 0x3FF3, 0x3FC6, - 0x1FC8, 0x1FA8, 0x0FAC, 0x07D1, 0x03CC, 0x006B, 0x03CD, 0x07D3, - 0x0FAE, 0x1FA9, 0x1FC7, 0x3FC5, 0x3FF2, 0x7FEC, 0x7FFA, 0x3FDE, - 0x3FDA, 0x3FD7, 0x1FB9, 0x1FB0, 0x07C2, 0x03BE, 0x006E, 0x03BF, - 0x07C3, 0x1FB1, 0x1FB8, 0x3FD3, 0x3FD8, 0x3FDD, 0x7FF8, 0x7FEF, - 0x3FEE, 0x3FD6, 0x3FC8, 0x1FCB, 0x1FBE, 0x0FB5, 0x03D4, 0x006F, - 0x03D5, 0x0FB4, 0x1FBF, 0x1FCA, 0x3FCA, 0x3FD5, 0x3FEC, 0x7FF1, - 0xFFFF, 0x3FE8, 0x1FD4, 0x1FC5, 0x1FBA, 0x0FC9, 0x07CD, 0x07C7, - 0x01D6, 0x07C5, 0x07CC, 0x0FC8, 0x1FBB, 0x1FC3, 0x1FD6, 0x3FE7, - 0xFFFC, 0x002E, -}; - -static const uint16_t clv_mvy_0_syms[] = { - 0xF8F8, 0xF9F8, 0xFAF8, 0xFBF8, 0xFCF8, 0xFDF8, 0xFEF8, 0xFFF8, - 0x00F8, 0x01F8, 0x02F8, 0x03F8, 0x04F8, 0x05F8, 0x06F8, 0x07F8, - 0x08F8, 0xF8F9, 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, - 0xFFF9, 0x00F9, 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, - 0x07F9, 0x08F9, 0xF8FA, 0xF9FA, 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, - 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, 0x02FA, 0x03FA, 0x04FA, 0x05FA, - 0x06FA, 0x07FA, 0x08FA, 0xF8FB, 0xF9FB, 0xFAFB, 0xFBFB, 0xFCFB, - 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, 0x03FB, 0x04FB, - 0x05FB, 0x06FB, 0x07FB, 0x08FB, 0xF8FC, 0xF9FC, 0xFAFC, 0xFBFC, - 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, 0x00FC, 0x01FC, 0x02FC, 0x03FC, - 0x04FC, 0x05FC, 0x06FC, 0x07FC, 0x08FC, 0xF8FD, 0xF9FD, 0xFAFD, - 0xFBFD, 0xFCFD, 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, - 0x03FD, 0x04FD, 0x05FD, 0x06FD, 0x07FD, 0x08FD, 0xF8FE, 0xF9FE, - 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, - 0x02FE, 0x03FE, 0x04FE, 0x05FE, 0x06FE, 0x07FE, 0x08FE, 0xF8FF, - 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, 0xFFFF, 0x00FF, - 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, 0x07FF, 0x08FF, - 0xF800, 0xF900, 0xFA00, 0xFB00, 0xFC00, 0xFD00, 0xFE00, 0xFF00, - 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, - 0x0800, 0xF801, 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, - 0xFF01, 0x0001, 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, - 0x0701, 0x0801, 0xF802, 0xF902, 0xFA02, 0xFB02, 0xFC02, 0xFD02, - 0xFE02, 0xFF02, 0x0002, 0x0102, 0x0202, 0x0302, 0x0402, 0x0502, - 0x0602, 0x0702, 0x0802, 0xF803, 0xF903, 0xFA03, 0xFB03, 0xFC03, - 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, 0x0303, 0x0403, - 0x0503, 0x0603, 0x0703, 0x0803, 0xF804, 0xF904, 0xFA04, 0xFB04, - 0xFC04, 0xFD04, 0xFE04, 0xFF04, 0x0004, 0x0104, 0x0204, 0x0304, - 0x0404, 0x0504, 0x0604, 0x0704, 0x0804, 0xF805, 0xF905, 0xFA05, - 0xFB05, 0xFC05, 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, - 0x0305, 0x0405, 0x0505, 0x0605, 0x0705, 0x0805, 0xF806, 0xF906, - 0xFA06, 0xFB06, 0xFC06, 0xFD06, 0xFE06, 0xFF06, 0x0006, 0x0106, - 0x0206, 0x0306, 0x0406, 0x0506, 0x0606, 0x0706, 0x0806, 0xF807, - 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, 0xFF07, 0x0007, - 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, 0x0707, 0x0807, - 0xF808, 0xF908, 0xFA08, 0xFB08, 0xFC08, 0xFD08, 0xFE08, 0xFF08, - 0x0008, 0x0108, 0x0208, 0x0308, 0x0408, 0x0508, 0x0608, 0x0708, - 0x0808, 0x0909, -}; - -static const uint8_t clv_mvy_1_bits[] = { - 15, 15, 15, 15, 14, 14, 13, 13, 11, 9, 11, 13, 13, 14, 14, 15, - 15, 15, 15, 15, 14, 14, 13, 13, 12, 12, 12, 10, 9, 10, 12, 12, - 12, 13, 13, 14, 14, 15, 15, 15, 14, 14, 13, 13, 13, 12, 11, 8, - 11, 12, 13, 13, 13, 14, 14, 15, 15, 14, 14, 14, 14, 13, 12, 12, - 12, 10, 8, 10, 12, 12, 12, 13, 14, 14, 14, 14, 15, 14, 14, 13, - 13, 12, 12, 11, 10, 8, 10, 11, 12, 12, 13, 13, 14, 14, 15, 14, - 14, 13, 13, 13, 12, 12, 11, 9, 7, 9, 11, 12, 12, 13, 13, 13, - 14, 14, 14, 14, 13, 13, 13, 12, 11, 10, 9, 7, 9, 10, 11, 12, - 13, 13, 13, 14, 14, 14, 13, 13, 12, 12, 11, 11, 10, 8, 7, 8, - 10, 11, 11, 12, 12, 13, 13, 14, 13, 13, 13, 12, 11, 11, 10, 9, - 6, 4, 6, 9, 10, 11, 12, 12, 13, 13, 13, 12, 11, 10, 10, 10, - 9, 9, 7, 5, 1, 5, 7, 9, 9, 10, 10, 10, 11, 12, 13, 13, - 13, 12, 11, 11, 10, 9, 6, 4, 6, 9, 10, 11, 11, 12, 13, 13, - 13, 14, 13, 13, 12, 12, 11, 11, 10, 8, 7, 8, 10, 11, 11, 12, - 12, 13, 13, 14, 14, 14, 13, 13, 13, 12, 11, 10, 9, 7, 9, 10, - 11, 12, 13, 13, 13, 14, 14, 14, 14, 13, 13, 13, 12, 12, 11, 9, - 7, 9, 11, 12, 12, 13, 13, 13, 14, 14, 15, 14, 14, 13, 13, 12, - 12, 11, 10, 8, 10, 11, 12, 12, 13, 13, 14, 14, 15, 14, 14, 14, - 14, 13, 12, 12, 12, 10, 8, 10, 12, 12, 12, 13, 14, 14, 14, 14, - 15, 15, 14, 14, 13, 13, 13, 12, 11, 8, 11, 12, 13, 13, 13, 14, - 14, 15, 15, 15, 14, 14, 13, 13, 12, 12, 12, 10, 9, 10, 12, 12, - 12, 13, 13, 14, 14, 15, 15, 15, 15, 15, 14, 14, 13, 13, 11, 9, - 11, 13, 13, 14, 14, 15, 15, 15, 15, 5, -}; - -static const uint16_t clv_mvy_1_codes[] = { - 0x7FF9, 0x7FF6, 0x7FEB, 0x7FE3, 0x3FCF, 0x3FB3, 0x1FBD, 0x1FA1, - 0x07AD, 0x01CE, 0x07AF, 0x1FA0, 0x1FBB, 0x3FB0, 0x3FCC, 0x7FE2, - 0x7FE9, 0x7FF4, 0x7FFB, 0x7FF1, 0x3FE7, 0x3FBD, 0x1FA5, 0x1F9B, - 0x0FB4, 0x0FAF, 0x0FAA, 0x03CC, 0x01CD, 0x03CD, 0x0FAB, 0x0FAD, - 0x0FB1, 0x1F9C, 0x1FA3, 0x3FBE, 0x3FE6, 0x7FF0, 0x7FFC, 0x7FE5, - 0x3FB5, 0x3FAE, 0x1FB4, 0x1FAA, 0x1F97, 0x0F85, 0x07A2, 0x00DD, - 0x07A3, 0x0F86, 0x1F99, 0x1FAD, 0x1FB2, 0x3FAC, 0x3FB7, 0x7FE4, - 0x7FFD, 0x3FEA, 0x3FD8, 0x3FC3, 0x3FBB, 0x1FC9, 0x0FBC, 0x0F97, - 0x0F8F, 0x03B8, 0x00DA, 0x03B9, 0x0F90, 0x0F98, 0x0FB9, 0x1FC6, - 0x3FBA, 0x3FC0, 0x3FD9, 0x3FEB, 0x7FEF, 0x3FEE, 0x3FD7, 0x1FC3, - 0x1F96, 0x0FC0, 0x0FA8, 0x07AA, 0x03BE, 0x00D9, 0x03BF, 0x07AB, - 0x0FA7, 0x0FBF, 0x1F98, 0x1FC5, 0x3FD6, 0x3FEF, 0x7FEE, 0x3FDC, - 0x3FCA, 0x1FBF, 0x1F8B, 0x1F87, 0x0FA2, 0x0F94, 0x07A5, 0x01D4, - 0x0069, 0x01D5, 0x07A6, 0x0F95, 0x0FA3, 0x1F89, 0x1F8D, 0x1FC0, - 0x3FC6, 0x3FDE, 0x3FE0, 0x3FD3, 0x1FB8, 0x1F8F, 0x1F84, 0x0F89, - 0x07BC, 0x03C6, 0x01C6, 0x0067, 0x01C7, 0x03C7, 0x07BD, 0x0F87, - 0x1F82, 0x1F8A, 0x1FB6, 0x3FD1, 0x3FE2, 0x3FC5, 0x1FCE, 0x1FAE, - 0x0FB5, 0x0F8B, 0x07B4, 0x07B0, 0x03B4, 0x00DE, 0x0064, 0x00DF, - 0x03B5, 0x07B1, 0x07B5, 0x0F8C, 0x0FB6, 0x1FAF, 0x1FD1, 0x3FCB, - 0x1FD3, 0x1FCC, 0x1FA7, 0x0F9B, 0x07BE, 0x079C, 0x03C0, 0x01C8, - 0x002E, 0x0008, 0x002F, 0x01C9, 0x03C1, 0x079D, 0x0F82, 0x0F9A, - 0x1FA9, 0x1FCA, 0x1FD4, 0x0F9F, 0x07B6, 0x03C8, 0x03B2, 0x03B0, - 0x01D6, 0x01D0, 0x006A, 0x0014, 0x0000, 0x0015, 0x006B, 0x01D1, - 0x01D7, 0x03B1, 0x03B3, 0x03C9, 0x07B7, 0x0FA0, 0x1FD5, 0x1FCB, - 0x1FAB, 0x0F9C, 0x07BF, 0x079E, 0x03C2, 0x01CA, 0x0030, 0x0009, - 0x0031, 0x01CB, 0x03C3, 0x079F, 0x07C0, 0x0F9D, 0x1FAC, 0x1FCD, - 0x1FD2, 0x3FC8, 0x1FD0, 0x1FB0, 0x0FB7, 0x0F8D, 0x07B8, 0x07B2, - 0x03B6, 0x00E0, 0x0065, 0x00E1, 0x03B7, 0x07B3, 0x07B9, 0x0F8E, - 0x0FB8, 0x1FB1, 0x1FCF, 0x3FC9, 0x3FE1, 0x3FD2, 0x1FB7, 0x1F8E, - 0x1F83, 0x0F88, 0x07BA, 0x03C4, 0x01C4, 0x0066, 0x01C5, 0x03C5, - 0x07BB, 0x0F8A, 0x1F85, 0x1F90, 0x1FB9, 0x3FD0, 0x3FE3, 0x3FDD, - 0x3FC7, 0x1FC1, 0x1F91, 0x1F88, 0x0FA4, 0x0F96, 0x07A7, 0x01D2, - 0x0068, 0x01D3, 0x07A4, 0x0F93, 0x0FA1, 0x1F86, 0x1F8C, 0x1FBE, - 0x3FC4, 0x3FDF, 0x7FED, 0x3FEC, 0x3FD4, 0x1FC4, 0x1F92, 0x0FBD, - 0x0FA5, 0x07A8, 0x03BC, 0x00D8, 0x03BD, 0x07A9, 0x0FA6, 0x0FBE, - 0x1F93, 0x1FC2, 0x3FD5, 0x3FED, 0x7FEC, 0x3FE8, 0x3FDB, 0x3FC1, - 0x3FB9, 0x1FC7, 0x0FBA, 0x0F9E, 0x0F91, 0x03BA, 0x00DB, 0x03BB, - 0x0F92, 0x0F99, 0x0FBB, 0x1FC8, 0x3FB8, 0x3FC2, 0x3FDA, 0x3FE9, - 0x7FFF, 0x7FE7, 0x3FB6, 0x3FAF, 0x1FB3, 0x1FA6, 0x1F94, 0x0F83, - 0x07A0, 0x00DC, 0x07A1, 0x0F84, 0x1F95, 0x1FA8, 0x1FB5, 0x3FAD, - 0x3FB4, 0x7FE6, 0x7FFE, 0x7FF3, 0x3FE5, 0x3FBC, 0x1FA4, 0x1F9D, - 0x0FB2, 0x0FAE, 0x0FA9, 0x03CA, 0x01CC, 0x03CB, 0x0FAC, 0x0FB0, - 0x0FB3, 0x1F9A, 0x1FA2, 0x3FBF, 0x3FE4, 0x7FF2, 0x7FF8, 0x7FF5, - 0x7FEA, 0x7FE0, 0x3FCD, 0x3FB1, 0x1FBA, 0x1F9F, 0x07AE, 0x01CF, - 0x07AC, 0x1F9E, 0x1FBC, 0x3FB2, 0x3FCE, 0x7FE1, 0x7FE8, 0x7FF7, - 0x7FFA, 0x0016, -}; - -static const uint16_t clv_mvy_1_syms[] = { - 0xF7F7, 0xF8F7, 0xF9F7, 0xFAF7, 0xFBF7, 0xFCF7, 0xFDF7, 0xFEF7, - 0xFFF7, 0x00F7, 0x01F7, 0x02F7, 0x03F7, 0x04F7, 0x05F7, 0x06F7, - 0x07F7, 0x08F7, 0x09F7, 0xF7F8, 0xF8F8, 0xF9F8, 0xFAF8, 0xFBF8, - 0xFCF8, 0xFDF8, 0xFEF8, 0xFFF8, 0x00F8, 0x01F8, 0x02F8, 0x03F8, - 0x04F8, 0x05F8, 0x06F8, 0x07F8, 0x08F8, 0x09F8, 0xF7F9, 0xF8F9, - 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, 0xFFF9, 0x00F9, - 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, 0x07F9, 0x08F9, - 0x09F9, 0xF7FA, 0xF8FA, 0xF9FA, 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, - 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, 0x02FA, 0x03FA, 0x04FA, 0x05FA, - 0x06FA, 0x07FA, 0x08FA, 0x09FA, 0xF7FB, 0xF8FB, 0xF9FB, 0xFAFB, - 0xFBFB, 0xFCFB, 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, - 0x03FB, 0x04FB, 0x05FB, 0x06FB, 0x07FB, 0x08FB, 0x09FB, 0xF7FC, - 0xF8FC, 0xF9FC, 0xFAFC, 0xFBFC, 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, - 0x00FC, 0x01FC, 0x02FC, 0x03FC, 0x04FC, 0x05FC, 0x06FC, 0x07FC, - 0x08FC, 0x09FC, 0xF7FD, 0xF8FD, 0xF9FD, 0xFAFD, 0xFBFD, 0xFCFD, - 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, 0x03FD, 0x04FD, - 0x05FD, 0x06FD, 0x07FD, 0x08FD, 0x09FD, 0xF7FE, 0xF8FE, 0xF9FE, - 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, - 0x02FE, 0x03FE, 0x04FE, 0x05FE, 0x06FE, 0x07FE, 0x08FE, 0x09FE, - 0xF7FF, 0xF8FF, 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, - 0xFFFF, 0x00FF, 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, - 0x07FF, 0x08FF, 0x09FF, 0xF700, 0xF800, 0xF900, 0xFA00, 0xFB00, - 0xFC00, 0xFD00, 0xFE00, 0xFF00, 0x0000, 0x0100, 0x0200, 0x0300, - 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, 0x0900, 0xF701, 0xF801, - 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, 0xFF01, 0x0001, - 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, 0x0701, 0x0801, - 0x0901, 0xF702, 0xF802, 0xF902, 0xFA02, 0xFB02, 0xFC02, 0xFD02, - 0xFE02, 0xFF02, 0x0002, 0x0102, 0x0202, 0x0302, 0x0402, 0x0502, - 0x0602, 0x0702, 0x0802, 0x0902, 0xF703, 0xF803, 0xF903, 0xFA03, - 0xFB03, 0xFC03, 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, - 0x0303, 0x0403, 0x0503, 0x0603, 0x0703, 0x0803, 0x0903, 0xF704, - 0xF804, 0xF904, 0xFA04, 0xFB04, 0xFC04, 0xFD04, 0xFE04, 0xFF04, - 0x0004, 0x0104, 0x0204, 0x0304, 0x0404, 0x0504, 0x0604, 0x0704, - 0x0804, 0x0904, 0xF705, 0xF805, 0xF905, 0xFA05, 0xFB05, 0xFC05, - 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, 0x0305, 0x0405, - 0x0505, 0x0605, 0x0705, 0x0805, 0x0905, 0xF706, 0xF806, 0xF906, - 0xFA06, 0xFB06, 0xFC06, 0xFD06, 0xFE06, 0xFF06, 0x0006, 0x0106, - 0x0206, 0x0306, 0x0406, 0x0506, 0x0606, 0x0706, 0x0806, 0x0906, - 0xF707, 0xF807, 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, - 0xFF07, 0x0007, 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, - 0x0707, 0x0807, 0x0907, 0xF708, 0xF808, 0xF908, 0xFA08, 0xFB08, - 0xFC08, 0xFD08, 0xFE08, 0xFF08, 0x0008, 0x0108, 0x0208, 0x0308, - 0x0408, 0x0508, 0x0608, 0x0708, 0x0808, 0x0908, 0xF709, 0xF809, - 0xF909, 0xFA09, 0xFB09, 0xFC09, 0xFD09, 0xFE09, 0xFF09, 0x0009, - 0x0109, 0x0209, 0x0309, 0x0409, 0x0509, 0x0609, 0x0709, 0x0809, - 0x0909, 0x0A0A, -}; - -static const uint8_t clv_mvy_2_bits[] = { - 16, 16, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, 12, 11, - 12, 13, 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, - 15, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13, 13, 11, 10, 11, - 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 15, - 15, 15, 15, 14, 14, 14, 14, 14, 14, 13, 13, 13, 11, 10, 11, 13, - 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 15, 15, - 15, 14, 14, 14, 14, 14, 14, 13, 13, 13, 12, 11, 9, 11, 12, 13, - 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 16, 16, 15, 15, 14, - 14, 13, 13, 13, 13, 13, 13, 13, 12, 11, 11, 9, 11, 11, 12, 13, - 13, 13, 13, 13, 13, 13, 14, 14, 14, 15, 16, 16, 15, 15, 15, 14, - 13, 13, 13, 13, 13, 13, 13, 12, 11, 11, 9, 11, 11, 12, 13, 13, - 13, 13, 13, 13, 13, 14, 15, 15, 15, 16, 16, 15, 15, 15, 15, 14, - 14, 13, 13, 13, 12, 12, 12, 11, 11, 9, 11, 11, 12, 12, 12, 13, - 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 15, 15, 14, 14, 14, 13, - 13, 13, 12, 12, 12, 12, 11, 10, 8, 10, 11, 12, 12, 12, 12, 13, - 13, 13, 14, 14, 14, 15, 15, 16, 16, 15, 14, 14, 14, 13, 13, 13, - 13, 12, 12, 12, 11, 11, 10, 8, 10, 11, 11, 12, 12, 12, 13, 13, - 13, 13, 14, 14, 14, 15, 16, 15, 15, 14, 14, 13, 13, 13, 13, 13, - 12, 12, 12, 11, 10, 9, 8, 9, 10, 11, 12, 12, 12, 13, 13, 13, - 13, 13, 14, 14, 15, 15, 15, 15, 14, 14, 13, 13, 13, 13, 13, 12, - 12, 11, 11, 10, 10, 7, 10, 10, 11, 11, 12, 12, 13, 13, 13, 13, - 13, 14, 14, 15, 15, 14, 14, 14, 14, 13, 13, 12, 12, 12, 12, 12, - 11, 11, 10, 9, 7, 9, 10, 11, 11, 12, 12, 12, 12, 12, 13, 13, - 14, 14, 14, 14, 15, 13, 13, 13, 13, 13, 12, 12, 12, 11, 11, 11, - 11, 10, 8, 7, 8, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, - 13, 13, 15, 14, 14, 14, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, - 9, 8, 6, 8, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 14, - 14, 14, 16, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 9, 9, 8, - 6, 4, 6, 8, 9, 9, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, - 16, 12, 12, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 8, 7, 4, - 2, 4, 7, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, - 16, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 9, 9, 8, 6, 4, - 6, 8, 9, 9, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 16, 14, - 14, 14, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 9, 8, 6, 8, - 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 13, - 13, 13, 13, 13, 12, 12, 12, 11, 11, 11, 11, 10, 8, 7, 8, 10, - 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 13, 15, 14, 14, 14, - 14, 13, 13, 12, 12, 12, 12, 12, 11, 11, 10, 9, 7, 9, 10, 11, - 11, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 14, 14, - 13, 13, 13, 13, 13, 12, 12, 11, 11, 10, 10, 7, 10, 10, 11, 11, - 12, 12, 13, 13, 13, 13, 13, 14, 14, 15, 15, 15, 15, 14, 14, 13, - 13, 13, 13, 13, 12, 12, 12, 11, 10, 9, 8, 9, 10, 11, 12, 12, - 12, 13, 13, 13, 13, 13, 14, 14, 15, 15, 16, 15, 14, 14, 14, 13, - 13, 13, 13, 12, 12, 12, 11, 11, 10, 8, 10, 11, 11, 12, 12, 12, - 13, 13, 13, 13, 14, 14, 14, 15, 16, 16, 15, 15, 14, 14, 14, 13, - 13, 13, 12, 12, 12, 12, 11, 10, 8, 10, 11, 12, 12, 12, 12, 13, - 13, 13, 14, 14, 14, 15, 15, 16, 16, 15, 15, 15, 15, 14, 14, 13, - 13, 13, 12, 12, 12, 11, 11, 9, 11, 11, 12, 12, 12, 13, 13, 13, - 14, 14, 15, 15, 15, 15, 16, 16, 15, 15, 15, 14, 13, 13, 13, 13, - 13, 13, 13, 12, 11, 11, 9, 11, 11, 12, 13, 13, 13, 13, 13, 13, - 13, 14, 15, 15, 15, 16, 16, 15, 15, 14, 14, 13, 13, 13, 13, 13, - 13, 13, 12, 11, 11, 9, 11, 11, 12, 13, 13, 13, 13, 13, 13, 13, - 14, 14, 14, 15, 16, 16, 15, 15, 15, 14, 14, 14, 14, 14, 14, 13, - 13, 13, 12, 11, 9, 11, 12, 13, 13, 13, 14, 14, 14, 14, 14, 14, - 15, 15, 15, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 13, - 13, 13, 11, 10, 11, 13, 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, - 15, 15, 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13, - 13, 12, 10, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, - 15, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, - 12, 11, 12, 13, 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 16, - 16, 7, -}; - -static const uint16_t clv_mvy_2_codes[] = { - 0xFFF5, 0xFFD8, 0x7FE6, 0x7FB9, 0x7FB5, 0x7FB0, 0x7FA0, 0x7F99, - 0x7F93, 0x3FAA, 0x3F9B, 0x3F52, 0x1F76, 0x1EF5, 0x0F0B, 0x06F0, - 0x0F08, 0x1EF0, 0x1F75, 0x3F53, 0x3F9A, 0x3FA8, 0x7F94, 0x7F98, - 0x7F9E, 0x7FAE, 0x7FAF, 0x7FB7, 0x7FE9, 0xFFDB, 0xFFF6, 0xFFFD, - 0x7FD9, 0x7FCC, 0x7FC6, 0x7F9C, 0x7F80, 0x3FA5, 0x3F80, 0x3F6A, - 0x3F31, 0x1F54, 0x1F40, 0x1F11, 0x1F05, 0x075E, 0x0360, 0x075F, - 0x1F07, 0x1F12, 0x1F43, 0x1F56, 0x3F33, 0x3F68, 0x3F83, 0x3FA6, - 0x7F7F, 0x7F9A, 0x7FC9, 0x7FCA, 0x7FDB, 0xFFF8, 0xFFEC, 0x7FDE, - 0x7FE2, 0x7FA6, 0x7F6F, 0x3FA1, 0x3F8D, 0x3F5C, 0x3F39, 0x3F21, - 0x3F18, 0x1F58, 0x1F1E, 0x1EF1, 0x0740, 0x035A, 0x0741, 0x1EF2, - 0x1F1F, 0x1F5A, 0x3F19, 0x3F22, 0x3F3B, 0x3F5E, 0x3F8E, 0x3FA3, - 0x7F6B, 0x7FA2, 0x7FE3, 0x7FE1, 0xFFEE, 0xFFFC, 0x7FC3, 0x7FBC, - 0x7F71, 0x3F96, 0x3F86, 0x3F7A, 0x3F72, 0x3F59, 0x3F46, 0x1F0A, - 0x1EFD, 0x1ED0, 0x0F02, 0x0712, 0x019F, 0x0713, 0x0F03, 0x1ED3, - 0x1EFF, 0x1F09, 0x3F4A, 0x3F5A, 0x3F76, 0x3F7B, 0x3F87, 0x3F97, - 0x7F73, 0x7FBB, 0x7FBF, 0xFFFB, 0xFFEB, 0x7F88, 0x7F5C, 0x3F7C, - 0x3F3C, 0x1F60, 0x1F4C, 0x1F14, 0x1F0C, 0x1F00, 0x1EF9, 0x1ED8, - 0x0F42, 0x075A, 0x0714, 0x0186, 0x0715, 0x075B, 0x0F43, 0x1EDA, - 0x1EFA, 0x1F01, 0x1F0E, 0x1F15, 0x1F4D, 0x1F62, 0x3F3D, 0x3F7D, - 0x3FAC, 0x7F86, 0xFFE8, 0xFFE7, 0x7FA7, 0x7F8C, 0x7F68, 0x3F9C, - 0x1F7C, 0x1F6C, 0x1F69, 0x1EEC, 0x1EE4, 0x1ED5, 0x1ECD, 0x0EF0, - 0x0752, 0x06F6, 0x018C, 0x06F7, 0x0753, 0x0EF1, 0x1ECE, 0x1ED6, - 0x1EE5, 0x1EED, 0x1F6A, 0x1F6E, 0x1F7D, 0x3F9F, 0x7F66, 0x7F8A, - 0x7FA5, 0xFFE6, 0xFFDC, 0x7FDA, 0x7FC0, 0x7FAC, 0x7F61, 0x3F42, - 0x3F0E, 0x1F45, 0x1F2C, 0x1ECA, 0x0F27, 0x0EF6, 0x0EEE, 0x072E, - 0x06F4, 0x0185, 0x06F5, 0x072F, 0x0EEF, 0x0EF7, 0x0F28, 0x1ECB, - 0x1F2F, 0x1F46, 0x3F0F, 0x3F40, 0x7F5F, 0x7FB4, 0x7FC2, 0x7FDC, - 0xFFDA, 0xFFE0, 0x7F72, 0x7F63, 0x3F70, 0x3F1C, 0x3F16, 0x1F82, - 0x1EE2, 0x1EB2, 0x0F4C, 0x0EFC, 0x0EE0, 0x0ED3, 0x0722, 0x036C, - 0x00BF, 0x036D, 0x0723, 0x0ECC, 0x0EE1, 0x0EFF, 0x0F4D, 0x1EB3, - 0x1EE3, 0x1F83, 0x3F17, 0x3F1F, 0x3F75, 0x7F65, 0x7F70, 0xFFE2, - 0xFFD7, 0x7F76, 0x3F2B, 0x3F13, 0x3F0A, 0x1F33, 0x1F23, 0x1EB4, - 0x1EA0, 0x0F46, 0x0F32, 0x0F1A, 0x0756, 0x0728, 0x0356, 0x00B0, - 0x0357, 0x0729, 0x0757, 0x0F1B, 0x0F33, 0x0F47, 0x1EA1, 0x1EB5, - 0x1F20, 0x1F30, 0x3F08, 0x3F10, 0x3F28, 0x7F77, 0xFFD5, 0x7FD5, - 0x7FD1, 0x3F5D, 0x3F25, 0x1F34, 0x1F24, 0x1EE8, 0x1EBC, 0x1EA8, - 0x0F3A, 0x0F2E, 0x0EE2, 0x071C, 0x0374, 0x01A0, 0x00AE, 0x01A1, - 0x0375, 0x071D, 0x0EE3, 0x0F2F, 0x0F3C, 0x1EA9, 0x1EBD, 0x1EE9, - 0x1F25, 0x1F36, 0x3F24, 0x3F61, 0x7FCE, 0x7FD2, 0x7F91, 0x7F7D, - 0x3F6C, 0x3F34, 0x1F72, 0x1F61, 0x1EDD, 0x1EC5, 0x1EA5, 0x0F05, - 0x0ED6, 0x0750, 0x073E, 0x0368, 0x034A, 0x0052, 0x034B, 0x0369, - 0x073F, 0x0751, 0x0ED7, 0x0F07, 0x1EA7, 0x1EC7, 0x1EDF, 0x1F65, - 0x1F70, 0x3F36, 0x3F6F, 0x7F7C, 0x7F8F, 0x3F90, 0x3F66, 0x3F58, - 0x3F4E, 0x1F48, 0x1EBB, 0x0F40, 0x0F18, 0x0F10, 0x0EDA, 0x0ECF, - 0x0732, 0x0704, 0x0354, 0x0190, 0x004F, 0x0191, 0x0355, 0x0705, - 0x0733, 0x0ED0, 0x0EDB, 0x0F11, 0x0F19, 0x0F41, 0x1EB8, 0x1F4B, - 0x3F4F, 0x3F55, 0x3F65, 0x3F92, 0x7F85, 0x1F51, 0x1F39, 0x1F2B, - 0x1F18, 0x1EC2, 0x0F38, 0x0F14, 0x0ECA, 0x074C, 0x0736, 0x0700, - 0x06FC, 0x0350, 0x00BA, 0x004D, 0x00BB, 0x0351, 0x06FD, 0x0701, - 0x0737, 0x074D, 0x0ECB, 0x0F15, 0x0F39, 0x1EC3, 0x1F1B, 0x1F2E, - 0x1F3A, 0x1F53, 0x7F82, 0x3F8A, 0x3F47, 0x3F2E, 0x1F5E, 0x1E9E, - 0x0F24, 0x0F20, 0x0EC6, 0x0746, 0x0726, 0x070E, 0x0370, 0x035E, - 0x018A, 0x00AC, 0x0021, 0x00AD, 0x018B, 0x035F, 0x0371, 0x070F, - 0x0727, 0x0747, 0x0EC7, 0x0F21, 0x0F25, 0x1E9F, 0x1F5F, 0x3F2D, - 0x3F48, 0x3F8B, 0xFFF1, 0x1F78, 0x1F3D, 0x1EAD, 0x0F2B, 0x0EF9, - 0x0EE9, 0x0739, 0x0719, 0x0709, 0x0363, 0x019B, 0x0195, 0x00B3, - 0x0023, 0x0005, 0x0024, 0x00B4, 0x0196, 0x019C, 0x0364, 0x070A, - 0x071A, 0x073A, 0x0EEA, 0x0EFA, 0x0F2C, 0x1EAE, 0x1F3E, 0x1F79, - 0xFFF0, 0x0F0C, 0x0EE6, 0x0EDC, 0x0EC2, 0x0748, 0x0706, 0x0372, - 0x034C, 0x0198, 0x0192, 0x00C0, 0x00BC, 0x00B6, 0x0053, 0x0006, - 0x0000, 0x0007, 0x0054, 0x00B7, 0x00BD, 0x00C1, 0x0193, 0x0199, - 0x034D, 0x0373, 0x0707, 0x0749, 0x0EC3, 0x0EDD, 0x0EE7, 0x0F0D, - 0xFFF2, 0x1F7A, 0x1F3F, 0x1EAF, 0x0F2D, 0x0EFB, 0x0EEB, 0x073B, - 0x071B, 0x070B, 0x0365, 0x019D, 0x0197, 0x00B5, 0x0025, 0x0004, - 0x0022, 0x00B2, 0x0194, 0x019A, 0x0362, 0x0708, 0x0718, 0x0738, - 0x0EE8, 0x0EF8, 0x0F2A, 0x1EAC, 0x1F3C, 0x1F7B, 0xFFF3, 0x3F89, - 0x3F44, 0x3F2F, 0x1F5C, 0x1E9C, 0x0F22, 0x0F1E, 0x0EC4, 0x0744, - 0x0724, 0x070C, 0x036E, 0x035C, 0x0188, 0x00AA, 0x0020, 0x00AB, - 0x0189, 0x035D, 0x036F, 0x070D, 0x0725, 0x0745, 0x0EC5, 0x0F1F, - 0x0F23, 0x1E9D, 0x1F5D, 0x3F2C, 0x3F45, 0x3F88, 0x7F81, 0x1F52, - 0x1F38, 0x1F28, 0x1F19, 0x1EC0, 0x0F36, 0x0F12, 0x0EC8, 0x074A, - 0x0734, 0x06FE, 0x06FA, 0x034E, 0x00B8, 0x004C, 0x00B9, 0x034F, - 0x06FB, 0x06FF, 0x0735, 0x074B, 0x0EC9, 0x0F13, 0x0F37, 0x1EC1, - 0x1F1A, 0x1F29, 0x1F3B, 0x1F50, 0x7F84, 0x3F91, 0x3F64, 0x3F54, - 0x3F4C, 0x1F49, 0x1EB9, 0x0F3B, 0x0F16, 0x0F0E, 0x0ED8, 0x0ECD, - 0x0730, 0x0702, 0x0352, 0x018E, 0x004E, 0x018F, 0x0353, 0x0703, - 0x0731, 0x0ECE, 0x0ED9, 0x0F0F, 0x0F17, 0x0F3D, 0x1EBA, 0x1F4A, - 0x3F4D, 0x3F51, 0x3F67, 0x3F93, 0x7F90, 0x7F7A, 0x3F6E, 0x3F37, - 0x1F71, 0x1F63, 0x1EDC, 0x1EC4, 0x1EA4, 0x0F04, 0x0ED4, 0x074E, - 0x073C, 0x0366, 0x0348, 0x0051, 0x0349, 0x0367, 0x073D, 0x074F, - 0x0ED5, 0x0F06, 0x1EA6, 0x1EC6, 0x1EDE, 0x1F64, 0x1F73, 0x3F35, - 0x3F6D, 0x7F7B, 0x7F8E, 0x7FD4, 0x7FD0, 0x3F5F, 0x3F26, 0x1F35, - 0x1F27, 0x1EEA, 0x1EBE, 0x1EAA, 0x0F3E, 0x0F30, 0x0EE4, 0x071E, - 0x0376, 0x01A2, 0x00AF, 0x01A3, 0x0377, 0x071F, 0x0EE5, 0x0F31, - 0x0F3F, 0x1EAB, 0x1EBF, 0x1EEB, 0x1F26, 0x1F37, 0x3F27, 0x3F62, - 0x7FCF, 0x7FD3, 0xFFD4, 0x7F78, 0x3F29, 0x3F11, 0x3F0B, 0x1F32, - 0x1F22, 0x1EB6, 0x1EA2, 0x0F48, 0x0F34, 0x0F1C, 0x0758, 0x072A, - 0x0358, 0x00B1, 0x0359, 0x072B, 0x0759, 0x0F1D, 0x0F35, 0x0F49, - 0x1EA3, 0x1EB7, 0x1F21, 0x1F31, 0x3F09, 0x3F12, 0x3F2A, 0x7F79, - 0xFFD6, 0xFFE1, 0x7F6D, 0x7F64, 0x3F73, 0x3F1D, 0x3F14, 0x1F81, - 0x1EE0, 0x1EB0, 0x0F4A, 0x0EFD, 0x0EDE, 0x0ED1, 0x0720, 0x036A, - 0x00BE, 0x036B, 0x0721, 0x0ED2, 0x0EDF, 0x0EFE, 0x0F4B, 0x1EB1, - 0x1EE1, 0x1F7E, 0x3F15, 0x3F1E, 0x3F74, 0x7F62, 0x7F75, 0xFFE3, - 0xFFDE, 0x7FDD, 0x7FBE, 0x7FB3, 0x7F60, 0x3F43, 0x3F0C, 0x1F47, - 0x1F2D, 0x1EC8, 0x0F26, 0x0EF4, 0x0EEC, 0x072C, 0x06F2, 0x0184, - 0x06F3, 0x072D, 0x0EED, 0x0EF5, 0x0F29, 0x1EC9, 0x1F2A, 0x1F44, - 0x3F0D, 0x3F41, 0x7F5E, 0x7FB1, 0x7FC1, 0x7FD7, 0xFFDF, 0xFFEA, - 0x7FA3, 0x7F8B, 0x7F69, 0x3F9E, 0x1F7F, 0x1F6D, 0x1F6B, 0x1EEE, - 0x1EE6, 0x1ED4, 0x1ECF, 0x0EF2, 0x0754, 0x06F8, 0x018D, 0x06F9, - 0x0755, 0x0EF3, 0x1ECC, 0x1ED7, 0x1EE7, 0x1EEF, 0x1F68, 0x1F6F, - 0x1F80, 0x3F9D, 0x7F67, 0x7F8D, 0x7FA8, 0xFFE9, 0xFFE5, 0x7F89, - 0x7F5D, 0x3F7F, 0x3F3F, 0x1F67, 0x1F4F, 0x1F17, 0x1F0F, 0x1F02, - 0x1EFB, 0x1ED9, 0x0F45, 0x075C, 0x0716, 0x0187, 0x0717, 0x075D, - 0x0F44, 0x1EDB, 0x1EF8, 0x1F03, 0x1F0D, 0x1F16, 0x1F4E, 0x1F66, - 0x3F3E, 0x3F7E, 0x3FAD, 0x7F87, 0xFFE4, 0xFFF9, 0x7FC4, 0x7FBA, - 0x7F6E, 0x3F95, 0x3F85, 0x3F78, 0x3F77, 0x3F5B, 0x3F49, 0x1F08, - 0x1EFE, 0x1ED2, 0x0F01, 0x0710, 0x019E, 0x0711, 0x0F00, 0x1ED1, - 0x1EFC, 0x1F0B, 0x3F4B, 0x3F57, 0x3F71, 0x3F79, 0x3F84, 0x3F94, - 0x7F74, 0x7FBD, 0x7FC5, 0xFFFE, 0xFFED, 0x7FE0, 0x7FDF, 0x7FA4, - 0x7F6A, 0x3FA0, 0x3F8F, 0x3F63, 0x3F3A, 0x3F23, 0x3F1A, 0x1F59, - 0x1F1D, 0x1EF3, 0x0743, 0x035B, 0x0742, 0x1EF7, 0x1F1C, 0x1F5B, - 0x3F1B, 0x3F20, 0x3F38, 0x3F60, 0x3F8C, 0x3FA2, 0x7F6C, 0x7FA9, - 0x7FE5, 0x7FE4, 0xFFEF, 0xFFFF, 0x7FD6, 0x7FCB, 0x7FC7, 0x7F9B, - 0x7F83, 0x3FA4, 0x3F81, 0x3F69, 0x3F30, 0x1F57, 0x1F41, 0x1F13, - 0x1F06, 0x0EC0, 0x0361, 0x0EC1, 0x1F04, 0x1F10, 0x1F42, 0x1F55, - 0x3F32, 0x3F6B, 0x3F82, 0x3FA7, 0x7F7E, 0x7F9D, 0x7FC8, 0x7FCD, - 0x7FD8, 0xFFFA, 0xFFF7, 0xFFD9, 0x7FE8, 0x7FB6, 0x7FAB, 0x7FAA, - 0x7FA1, 0x7F96, 0x7F95, 0x3FAB, 0x3F98, 0x3F50, 0x1F77, 0x1EF4, - 0x0F0A, 0x06F1, 0x0F09, 0x1EF6, 0x1F74, 0x3F56, 0x3F99, 0x3FA9, - 0x7F92, 0x7F97, 0x7F9F, 0x7FAD, 0x7FB2, 0x7FB8, 0x7FE7, 0xFFDD, - 0xFFF4, 0x0050, -}; - -static const uint16_t clv_mvy_2_syms[] = { - 0xF1F1, 0xF2F1, 0xF3F1, 0xF4F1, 0xF5F1, 0xF6F1, 0xF7F1, 0xF8F1, - 0xF9F1, 0xFAF1, 0xFBF1, 0xFCF1, 0xFDF1, 0xFEF1, 0xFFF1, 0x00F1, - 0x01F1, 0x02F1, 0x03F1, 0x04F1, 0x05F1, 0x06F1, 0x07F1, 0x08F1, - 0x09F1, 0x0AF1, 0x0BF1, 0x0CF1, 0x0DF1, 0x0EF1, 0x0FF1, 0xF1F2, - 0xF2F2, 0xF3F2, 0xF4F2, 0xF5F2, 0xF6F2, 0xF7F2, 0xF8F2, 0xF9F2, - 0xFAF2, 0xFBF2, 0xFCF2, 0xFDF2, 0xFEF2, 0xFFF2, 0x00F2, 0x01F2, - 0x02F2, 0x03F2, 0x04F2, 0x05F2, 0x06F2, 0x07F2, 0x08F2, 0x09F2, - 0x0AF2, 0x0BF2, 0x0CF2, 0x0DF2, 0x0EF2, 0x0FF2, 0xF1F3, 0xF2F3, - 0xF3F3, 0xF4F3, 0xF5F3, 0xF6F3, 0xF7F3, 0xF8F3, 0xF9F3, 0xFAF3, - 0xFBF3, 0xFCF3, 0xFDF3, 0xFEF3, 0xFFF3, 0x00F3, 0x01F3, 0x02F3, - 0x03F3, 0x04F3, 0x05F3, 0x06F3, 0x07F3, 0x08F3, 0x09F3, 0x0AF3, - 0x0BF3, 0x0CF3, 0x0DF3, 0x0EF3, 0x0FF3, 0xF1F4, 0xF2F4, 0xF3F4, - 0xF4F4, 0xF5F4, 0xF6F4, 0xF7F4, 0xF8F4, 0xF9F4, 0xFAF4, 0xFBF4, - 0xFCF4, 0xFDF4, 0xFEF4, 0xFFF4, 0x00F4, 0x01F4, 0x02F4, 0x03F4, - 0x04F4, 0x05F4, 0x06F4, 0x07F4, 0x08F4, 0x09F4, 0x0AF4, 0x0BF4, - 0x0CF4, 0x0DF4, 0x0EF4, 0x0FF4, 0xF1F5, 0xF2F5, 0xF3F5, 0xF4F5, - 0xF5F5, 0xF6F5, 0xF7F5, 0xF8F5, 0xF9F5, 0xFAF5, 0xFBF5, 0xFCF5, - 0xFDF5, 0xFEF5, 0xFFF5, 0x00F5, 0x01F5, 0x02F5, 0x03F5, 0x04F5, - 0x05F5, 0x06F5, 0x07F5, 0x08F5, 0x09F5, 0x0AF5, 0x0BF5, 0x0CF5, - 0x0DF5, 0x0EF5, 0x0FF5, 0xF1F6, 0xF2F6, 0xF3F6, 0xF4F6, 0xF5F6, - 0xF6F6, 0xF7F6, 0xF8F6, 0xF9F6, 0xFAF6, 0xFBF6, 0xFCF6, 0xFDF6, - 0xFEF6, 0xFFF6, 0x00F6, 0x01F6, 0x02F6, 0x03F6, 0x04F6, 0x05F6, - 0x06F6, 0x07F6, 0x08F6, 0x09F6, 0x0AF6, 0x0BF6, 0x0CF6, 0x0DF6, - 0x0EF6, 0x0FF6, 0xF1F7, 0xF2F7, 0xF3F7, 0xF4F7, 0xF5F7, 0xF6F7, - 0xF7F7, 0xF8F7, 0xF9F7, 0xFAF7, 0xFBF7, 0xFCF7, 0xFDF7, 0xFEF7, - 0xFFF7, 0x00F7, 0x01F7, 0x02F7, 0x03F7, 0x04F7, 0x05F7, 0x06F7, - 0x07F7, 0x08F7, 0x09F7, 0x0AF7, 0x0BF7, 0x0CF7, 0x0DF7, 0x0EF7, - 0x0FF7, 0xF1F8, 0xF2F8, 0xF3F8, 0xF4F8, 0xF5F8, 0xF6F8, 0xF7F8, - 0xF8F8, 0xF9F8, 0xFAF8, 0xFBF8, 0xFCF8, 0xFDF8, 0xFEF8, 0xFFF8, - 0x00F8, 0x01F8, 0x02F8, 0x03F8, 0x04F8, 0x05F8, 0x06F8, 0x07F8, - 0x08F8, 0x09F8, 0x0AF8, 0x0BF8, 0x0CF8, 0x0DF8, 0x0EF8, 0x0FF8, - 0xF1F9, 0xF2F9, 0xF3F9, 0xF4F9, 0xF5F9, 0xF6F9, 0xF7F9, 0xF8F9, - 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, 0xFFF9, 0x00F9, - 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, 0x07F9, 0x08F9, - 0x09F9, 0x0AF9, 0x0BF9, 0x0CF9, 0x0DF9, 0x0EF9, 0x0FF9, 0xF1FA, - 0xF2FA, 0xF3FA, 0xF4FA, 0xF5FA, 0xF6FA, 0xF7FA, 0xF8FA, 0xF9FA, - 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, - 0x02FA, 0x03FA, 0x04FA, 0x05FA, 0x06FA, 0x07FA, 0x08FA, 0x09FA, - 0x0AFA, 0x0BFA, 0x0CFA, 0x0DFA, 0x0EFA, 0x0FFA, 0xF1FB, 0xF2FB, - 0xF3FB, 0xF4FB, 0xF5FB, 0xF6FB, 0xF7FB, 0xF8FB, 0xF9FB, 0xFAFB, - 0xFBFB, 0xFCFB, 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, - 0x03FB, 0x04FB, 0x05FB, 0x06FB, 0x07FB, 0x08FB, 0x09FB, 0x0AFB, - 0x0BFB, 0x0CFB, 0x0DFB, 0x0EFB, 0x0FFB, 0xF1FC, 0xF2FC, 0xF3FC, - 0xF4FC, 0xF5FC, 0xF6FC, 0xF7FC, 0xF8FC, 0xF9FC, 0xFAFC, 0xFBFC, - 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, 0x00FC, 0x01FC, 0x02FC, 0x03FC, - 0x04FC, 0x05FC, 0x06FC, 0x07FC, 0x08FC, 0x09FC, 0x0AFC, 0x0BFC, - 0x0CFC, 0x0DFC, 0x0EFC, 0x0FFC, 0xF1FD, 0xF2FD, 0xF3FD, 0xF4FD, - 0xF5FD, 0xF6FD, 0xF7FD, 0xF8FD, 0xF9FD, 0xFAFD, 0xFBFD, 0xFCFD, - 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, 0x03FD, 0x04FD, - 0x05FD, 0x06FD, 0x07FD, 0x08FD, 0x09FD, 0x0AFD, 0x0BFD, 0x0CFD, - 0x0DFD, 0x0EFD, 0x0FFD, 0xF1FE, 0xF2FE, 0xF3FE, 0xF4FE, 0xF5FE, - 0xF6FE, 0xF7FE, 0xF8FE, 0xF9FE, 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, - 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, 0x02FE, 0x03FE, 0x04FE, 0x05FE, - 0x06FE, 0x07FE, 0x08FE, 0x09FE, 0x0AFE, 0x0BFE, 0x0CFE, 0x0DFE, - 0x0EFE, 0x0FFE, 0xF1FF, 0xF2FF, 0xF3FF, 0xF4FF, 0xF5FF, 0xF6FF, - 0xF7FF, 0xF8FF, 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, - 0xFFFF, 0x00FF, 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, - 0x07FF, 0x08FF, 0x09FF, 0x0AFF, 0x0BFF, 0x0CFF, 0x0DFF, 0x0EFF, - 0x0FFF, 0xF100, 0xF200, 0xF300, 0xF400, 0xF500, 0xF600, 0xF700, - 0xF800, 0xF900, 0xFA00, 0xFB00, 0xFC00, 0xFD00, 0xFE00, 0xFF00, - 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, - 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00, 0x0F00, - 0xF101, 0xF201, 0xF301, 0xF401, 0xF501, 0xF601, 0xF701, 0xF801, - 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, 0xFF01, 0x0001, - 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, 0x0701, 0x0801, - 0x0901, 0x0A01, 0x0B01, 0x0C01, 0x0D01, 0x0E01, 0x0F01, 0xF102, - 0xF202, 0xF302, 0xF402, 0xF502, 0xF602, 0xF702, 0xF802, 0xF902, - 0xFA02, 0xFB02, 0xFC02, 0xFD02, 0xFE02, 0xFF02, 0x0002, 0x0102, - 0x0202, 0x0302, 0x0402, 0x0502, 0x0602, 0x0702, 0x0802, 0x0902, - 0x0A02, 0x0B02, 0x0C02, 0x0D02, 0x0E02, 0x0F02, 0xF103, 0xF203, - 0xF303, 0xF403, 0xF503, 0xF603, 0xF703, 0xF803, 0xF903, 0xFA03, - 0xFB03, 0xFC03, 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, - 0x0303, 0x0403, 0x0503, 0x0603, 0x0703, 0x0803, 0x0903, 0x0A03, - 0x0B03, 0x0C03, 0x0D03, 0x0E03, 0x0F03, 0xF104, 0xF204, 0xF304, - 0xF404, 0xF504, 0xF604, 0xF704, 0xF804, 0xF904, 0xFA04, 0xFB04, - 0xFC04, 0xFD04, 0xFE04, 0xFF04, 0x0004, 0x0104, 0x0204, 0x0304, - 0x0404, 0x0504, 0x0604, 0x0704, 0x0804, 0x0904, 0x0A04, 0x0B04, - 0x0C04, 0x0D04, 0x0E04, 0x0F04, 0xF105, 0xF205, 0xF305, 0xF405, - 0xF505, 0xF605, 0xF705, 0xF805, 0xF905, 0xFA05, 0xFB05, 0xFC05, - 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, 0x0305, 0x0405, - 0x0505, 0x0605, 0x0705, 0x0805, 0x0905, 0x0A05, 0x0B05, 0x0C05, - 0x0D05, 0x0E05, 0x0F05, 0xF106, 0xF206, 0xF306, 0xF406, 0xF506, - 0xF606, 0xF706, 0xF806, 0xF906, 0xFA06, 0xFB06, 0xFC06, 0xFD06, - 0xFE06, 0xFF06, 0x0006, 0x0106, 0x0206, 0x0306, 0x0406, 0x0506, - 0x0606, 0x0706, 0x0806, 0x0906, 0x0A06, 0x0B06, 0x0C06, 0x0D06, - 0x0E06, 0x0F06, 0xF107, 0xF207, 0xF307, 0xF407, 0xF507, 0xF607, - 0xF707, 0xF807, 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, - 0xFF07, 0x0007, 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, - 0x0707, 0x0807, 0x0907, 0x0A07, 0x0B07, 0x0C07, 0x0D07, 0x0E07, - 0x0F07, 0xF108, 0xF208, 0xF308, 0xF408, 0xF508, 0xF608, 0xF708, - 0xF808, 0xF908, 0xFA08, 0xFB08, 0xFC08, 0xFD08, 0xFE08, 0xFF08, - 0x0008, 0x0108, 0x0208, 0x0308, 0x0408, 0x0508, 0x0608, 0x0708, - 0x0808, 0x0908, 0x0A08, 0x0B08, 0x0C08, 0x0D08, 0x0E08, 0x0F08, - 0xF109, 0xF209, 0xF309, 0xF409, 0xF509, 0xF609, 0xF709, 0xF809, - 0xF909, 0xFA09, 0xFB09, 0xFC09, 0xFD09, 0xFE09, 0xFF09, 0x0009, - 0x0109, 0x0209, 0x0309, 0x0409, 0x0509, 0x0609, 0x0709, 0x0809, - 0x0909, 0x0A09, 0x0B09, 0x0C09, 0x0D09, 0x0E09, 0x0F09, 0xF10A, - 0xF20A, 0xF30A, 0xF40A, 0xF50A, 0xF60A, 0xF70A, 0xF80A, 0xF90A, - 0xFA0A, 0xFB0A, 0xFC0A, 0xFD0A, 0xFE0A, 0xFF0A, 0x000A, 0x010A, - 0x020A, 0x030A, 0x040A, 0x050A, 0x060A, 0x070A, 0x080A, 0x090A, - 0x0A0A, 0x0B0A, 0x0C0A, 0x0D0A, 0x0E0A, 0x0F0A, 0xF10B, 0xF20B, - 0xF30B, 0xF40B, 0xF50B, 0xF60B, 0xF70B, 0xF80B, 0xF90B, 0xFA0B, - 0xFB0B, 0xFC0B, 0xFD0B, 0xFE0B, 0xFF0B, 0x000B, 0x010B, 0x020B, - 0x030B, 0x040B, 0x050B, 0x060B, 0x070B, 0x080B, 0x090B, 0x0A0B, - 0x0B0B, 0x0C0B, 0x0D0B, 0x0E0B, 0x0F0B, 0xF10C, 0xF20C, 0xF30C, - 0xF40C, 0xF50C, 0xF60C, 0xF70C, 0xF80C, 0xF90C, 0xFA0C, 0xFB0C, - 0xFC0C, 0xFD0C, 0xFE0C, 0xFF0C, 0x000C, 0x010C, 0x020C, 0x030C, - 0x040C, 0x050C, 0x060C, 0x070C, 0x080C, 0x090C, 0x0A0C, 0x0B0C, - 0x0C0C, 0x0D0C, 0x0E0C, 0x0F0C, 0xF10D, 0xF20D, 0xF30D, 0xF40D, - 0xF50D, 0xF60D, 0xF70D, 0xF80D, 0xF90D, 0xFA0D, 0xFB0D, 0xFC0D, - 0xFD0D, 0xFE0D, 0xFF0D, 0x000D, 0x010D, 0x020D, 0x030D, 0x040D, - 0x050D, 0x060D, 0x070D, 0x080D, 0x090D, 0x0A0D, 0x0B0D, 0x0C0D, - 0x0D0D, 0x0E0D, 0x0F0D, 0xF10E, 0xF20E, 0xF30E, 0xF40E, 0xF50E, - 0xF60E, 0xF70E, 0xF80E, 0xF90E, 0xFA0E, 0xFB0E, 0xFC0E, 0xFD0E, - 0xFE0E, 0xFF0E, 0x000E, 0x010E, 0x020E, 0x030E, 0x040E, 0x050E, - 0x060E, 0x070E, 0x080E, 0x090E, 0x0A0E, 0x0B0E, 0x0C0E, 0x0D0E, - 0x0E0E, 0x0F0E, 0xF10F, 0xF20F, 0xF30F, 0xF40F, 0xF50F, 0xF60F, - 0xF70F, 0xF80F, 0xF90F, 0xFA0F, 0xFB0F, 0xFC0F, 0xFD0F, 0xFE0F, - 0xFF0F, 0x000F, 0x010F, 0x020F, 0x030F, 0x040F, 0x050F, 0x060F, - 0x070F, 0x080F, 0x090F, 0x0A0F, 0x0B0F, 0x0C0F, 0x0D0F, 0x0E0F, - 0x0F0F, 0x1010, -}; - -static const uint8_t clv_mvy_3_bits[] = { - 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 13, - 13, 12, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, - 15, 15, 14, 14, 14, 13, 12, 11, 12, 13, 14, 14, 14, 15, 15, 15, - 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, - 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 12, 11, 12, 14, 14, - 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, - 16, 16, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, - 12, 11, 12, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, - 15, 16, 16, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 13, 13, 12, 10, 12, 13, 13, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 15, 15, 15, 15, - 14, 14, 14, 14, 13, 13, 13, 13, 13, 12, 12, 10, 12, 12, 13, 13, - 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 15, 15, - 15, 15, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 11, - 10, 11, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 15, - 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, - 12, 12, 12, 11, 10, 9, 10, 11, 12, 12, 12, 12, 12, 13, 13, 13, - 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, - 12, 12, 12, 12, 12, 12, 12, 11, 11, 10, 9, 10, 11, 11, 12, 12, - 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 15, 16, 15, 15, - 15, 15, 14, 14, 13, 13, 12, 12, 12, 12, 12, 11, 11, 11, 10, 9, - 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 14, 14, 15, 15, 15, - 15, 16, 15, 15, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 12, 12, - 11, 11, 11, 10, 9, 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, - 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, 12, - 12, 12, 12, 12, 12, 11, 11, 11, 10, 8, 10, 11, 11, 11, 12, 12, - 12, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 15, 15, 15, 14, 14, - 14, 14, 13, 13, 12, 12, 12, 12, 12, 11, 11, 11, 10, 10, 8, 10, - 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, - 15, 15, 14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, - 10, 10, 9, 7, 9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, - 13, 14, 14, 14, 14, 15, 15, 14, 14, 14, 14, 13, 13, 13, 12, 12, - 12, 12, 11, 11, 11, 10, 10, 9, 7, 9, 10, 10, 11, 11, 11, 12, - 12, 12, 12, 13, 13, 13, 14, 14, 14, 14, 15, 15, 14, 14, 14, 14, - 13, 13, 12, 12, 12, 12, 11, 11, 11, 11, 10, 9, 9, 7, 9, 9, - 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, - 15, 14, 14, 14, 13, 13, 13, 13, 12, 11, 11, 11, 11, 10, 10, 10, - 9, 8, 6, 8, 9, 10, 10, 10, 11, 11, 11, 11, 12, 13, 13, 13, - 13, 14, 14, 14, 15, 15, 14, 14, 14, 13, 13, 12, 12, 11, 11, 11, - 11, 10, 10, 9, 9, 8, 6, 4, 6, 8, 9, 9, 10, 10, 11, 11, - 11, 11, 12, 12, 13, 13, 14, 14, 14, 15, 13, 13, 13, 12, 12, 12, - 12, 11, 10, 10, 10, 10, 9, 9, 8, 8, 7, 5, 2, 5, 7, 8, - 8, 9, 9, 10, 10, 10, 10, 11, 12, 12, 12, 12, 13, 13, 13, 15, - 14, 14, 14, 13, 13, 12, 12, 11, 11, 11, 11, 10, 10, 9, 9, 8, - 6, 4, 6, 8, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 13, 13, - 14, 14, 14, 15, 15, 14, 14, 14, 13, 13, 13, 13, 12, 11, 11, 11, - 11, 10, 10, 10, 9, 8, 6, 8, 9, 10, 10, 10, 11, 11, 11, 11, - 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, 14, 14, 14, 14, 13, 13, - 12, 12, 12, 12, 11, 11, 11, 11, 10, 9, 9, 7, 9, 9, 10, 11, - 11, 11, 11, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 14, - 14, 14, 14, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 10, 10, 9, - 7, 9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14, 14, - 14, 14, 15, 15, 14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 12, 11, - 11, 11, 10, 10, 9, 7, 9, 10, 10, 11, 11, 11, 12, 12, 12, 12, - 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 14, 14, 14, 14, 13, 13, - 12, 12, 12, 12, 12, 11, 11, 11, 10, 10, 8, 10, 10, 11, 11, 11, - 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, - 14, 14, 14, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 10, 8, - 10, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 15, - 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 12, 12, - 11, 11, 11, 10, 9, 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, - 14, 14, 14, 14, 14, 15, 15, 16, 15, 15, 15, 15, 14, 14, 13, 13, - 12, 12, 12, 12, 12, 11, 11, 11, 10, 9, 10, 11, 11, 11, 12, 12, - 12, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 15, 15, 15, 14, - 14, 14, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 10, 9, 10, - 11, 11, 12, 12, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, - 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 12, - 12, 11, 10, 9, 10, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, - 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, - 13, 13, 13, 13, 13, 13, 13, 11, 10, 11, 13, 13, 13, 13, 13, 13, - 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 15, 15, - 15, 15, 14, 14, 14, 14, 13, 13, 13, 13, 13, 12, 12, 10, 12, 12, - 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, - 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, - 13, 12, 10, 12, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, - 15, 15, 15, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 14, - 14, 14, 14, 14, 13, 13, 12, 11, 12, 13, 13, 14, 14, 14, 14, 14, - 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 15, 15, 15, - 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 12, 11, 12, 14, 14, - 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, - 12, 11, 12, 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, - 15, 14, 14, 13, 13, 12, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, - 15, 15, 16, 16, 16, 16, 16, 16, 16, 7, -}; - -static const uint16_t clv_mvy_3_codes[] = { - 0xFFF6, 0xFFEE, 0xFFDC, 0xFFD7, 0xFFB4, 0xFFAA, 0xFFA0, 0x7FCC, - 0x7F8E, 0x7F7B, 0x7F77, 0x7F13, 0x7F11, 0x3F56, 0x3F48, 0x1F16, - 0x1E94, 0x0F28, 0x06F0, 0x0F2A, 0x1E96, 0x1F1C, 0x3F46, 0x3F58, - 0x7F15, 0x7F0E, 0x7F76, 0x7F80, 0x7F90, 0x7FC8, 0xFFA2, 0xFFA7, - 0xFFB5, 0xFFD8, 0xFFDD, 0xFFEC, 0xFFF5, 0xFFF1, 0xFFEA, 0xFFE4, - 0xFFD1, 0xFFC1, 0xFFA8, 0x7F70, 0x7F5C, 0x7F44, 0x7F40, 0x7F2A, - 0x7F16, 0x7EDF, 0x3ED6, 0x3ECA, 0x3ECC, 0x1EB5, 0x0EDE, 0x06D3, - 0x0EDF, 0x1EB6, 0x3ECE, 0x3ED0, 0x3ED8, 0x7EE5, 0x7F19, 0x7F31, - 0x7F3E, 0x7F45, 0x7F5B, 0x7F6F, 0xFFA9, 0xFFC0, 0xFFCE, 0xFFE5, - 0xFFE8, 0xFFF2, 0xFFFE, 0xFFE2, 0xFFBE, 0x7FBB, 0x7F75, 0x7F6B, - 0x7F58, 0x7EF9, 0x7EDC, 0x3F68, 0x3F27, 0x3F28, 0x3EDF, 0x3ED2, - 0x3EC1, 0x3EA6, 0x3E87, 0x0F0F, 0x06B3, 0x0F10, 0x3E89, 0x3EA8, - 0x3EC3, 0x3ED5, 0x3EE0, 0x3F2B, 0x3F26, 0x3F67, 0x7EDA, 0x7EFB, - 0x7F56, 0x7F6A, 0x7F72, 0x7FC1, 0xFFBC, 0xFFE0, 0xFFFF, 0xFFF8, - 0xFFD3, 0xFFB9, 0x7FAC, 0x7F94, 0x7F8B, 0x7F62, 0x7F4A, 0x7F05, - 0x7EEE, 0x3F44, 0x3EA4, 0x3E78, 0x3E6F, 0x3E54, 0x1EEF, 0x1EA9, - 0x0ED4, 0x06A8, 0x0ED5, 0x1EA8, 0x1EEC, 0x3E51, 0x3E69, 0x3E75, - 0x3EA3, 0x3F43, 0x7EF1, 0x7F04, 0x7F4B, 0x7F5D, 0x7F89, 0x7F95, - 0x7FAA, 0xFFBB, 0xFFC8, 0xFFF9, 0xFFD9, 0xFFCA, 0x7FC3, 0x7F8C, - 0x7F38, 0x7F02, 0x3F5A, 0x3F4A, 0x3F30, 0x3EFF, 0x3EF4, 0x3EE9, - 0x3E95, 0x3E73, 0x3E43, 0x1F08, 0x1E81, 0x0E84, 0x0349, 0x0E85, - 0x1E82, 0x1F07, 0x3E45, 0x3E74, 0x3E96, 0x3EEA, 0x3EF1, 0x3F00, - 0x3F32, 0x3F4F, 0x3F5C, 0x7F01, 0x7F3B, 0x7F8D, 0x7FC2, 0xFFCF, - 0xFFD6, 0xFFC7, 0xFFB1, 0xFFA6, 0x7FA1, 0x7F2F, 0x7F24, 0x7F0A, - 0x3EF6, 0x3E97, 0x3E83, 0x3E7F, 0x1F04, 0x1EE1, 0x1ECB, 0x1EAE, - 0x1E7E, 0x0EBA, 0x0E8C, 0x0333, 0x0E8D, 0x0EBB, 0x1E7F, 0x1EAF, - 0x1ECC, 0x1EE2, 0x1F05, 0x3E80, 0x3E84, 0x3E98, 0x3EF9, 0x7F06, - 0x7F1B, 0x7F2D, 0x7F9F, 0xFFAF, 0xFFB0, 0xFFC6, 0x7FB5, 0x7FB1, - 0x7F36, 0x7F25, 0x3F63, 0x3F3A, 0x3F1B, 0x3EBB, 0x3E63, 0x3E5B, - 0x3E40, 0x1F14, 0x1EF5, 0x1EEB, 0x1EBE, 0x1E92, 0x1E6A, 0x070C, - 0x032D, 0x070D, 0x1E6B, 0x1E93, 0x1EBF, 0x1EE8, 0x1EF3, 0x1F15, - 0x3E3F, 0x3E5C, 0x3E64, 0x3EB9, 0x3F1C, 0x3F3C, 0x3F62, 0x7F22, - 0x7F39, 0x7FAF, 0x7FAE, 0x7FC6, 0x7F7F, 0x7F53, 0x7F32, 0x3F66, - 0x3EF0, 0x3E65, 0x1EDA, 0x1ED3, 0x1E98, 0x1E74, 0x0F20, 0x0F1D, - 0x0EEA, 0x0EA9, 0x0E70, 0x0718, 0x033E, 0x0179, 0x033F, 0x0719, - 0x0E71, 0x0EAB, 0x0EE9, 0x0F1F, 0x0F22, 0x1E76, 0x1E9B, 0x1ED5, - 0x1EDD, 0x3E68, 0x3EF3, 0x3F6C, 0x7F33, 0x7F4E, 0x7F7D, 0x7FCB, - 0x7FBD, 0x7F21, 0x7EF6, 0x3F0C, 0x3EBE, 0x3EAE, 0x1EA3, 0x1E85, - 0x0F0C, 0x0F06, 0x0EEE, 0x0EE6, 0x0ECA, 0x0EA2, 0x0E78, 0x0720, - 0x06BA, 0x0326, 0x015D, 0x0327, 0x06BB, 0x0721, 0x0E79, 0x0EA3, - 0x0ECB, 0x0EE7, 0x0EEF, 0x0F07, 0x0F0D, 0x1E86, 0x1EA4, 0x3EAF, - 0x3EBF, 0x3F0A, 0x7EF8, 0x7F1E, 0x7FBF, 0xFF9F, 0x7FB3, 0x7F96, - 0x7F0B, 0x7EF5, 0x3E85, 0x3E4E, 0x1EB3, 0x1E6E, 0x0F2D, 0x0EBD, - 0x0E97, 0x0E93, 0x0E86, 0x071A, 0x06E4, 0x06BC, 0x0338, 0x015A, - 0x0339, 0x06BD, 0x06E5, 0x071B, 0x0E87, 0x0E94, 0x0E98, 0x0EBE, - 0x0F2E, 0x1E6F, 0x1EB4, 0x3E4F, 0x3E88, 0x7EF4, 0x7F07, 0x7F99, - 0x7FB7, 0xFF9D, 0x7FA8, 0x7EEB, 0x3F5D, 0x3EB2, 0x3EAA, 0x3E5D, - 0x3E49, 0x1EFE, 0x1E89, 0x0F16, 0x0F12, 0x0EE0, 0x0E7A, 0x0E6A, - 0x070E, 0x06FA, 0x06B4, 0x0314, 0x0158, 0x0315, 0x06B5, 0x06FB, - 0x070F, 0x0E6B, 0x0E7B, 0x0EE1, 0x0F13, 0x0F17, 0x1E8A, 0x1EFF, - 0x3E4A, 0x3E5E, 0x3EAB, 0x3EB3, 0x3F59, 0x7EEC, 0x7FA2, 0x7F82, - 0x7F5E, 0x7F28, 0x3EDA, 0x3EC9, 0x3E7A, 0x1ED6, 0x1ECE, 0x0EFC, - 0x0EF0, 0x0E9A, 0x0E7E, 0x0E66, 0x0E5E, 0x0722, 0x06C0, 0x06A0, - 0x02FA, 0x00A8, 0x02FB, 0x06A1, 0x06C1, 0x0723, 0x0E5F, 0x0E67, - 0x0E7F, 0x0E9B, 0x0EF1, 0x0EFD, 0x1ECF, 0x1ED7, 0x3E79, 0x3ECD, - 0x3EDB, 0x7F26, 0x7F5A, 0x7F83, 0x7F54, 0x7EE8, 0x3F54, 0x3F0E, - 0x3EFB, 0x3E47, 0x1EC1, 0x1EB9, 0x0EF9, 0x0EF3, 0x0EC1, 0x0E8F, - 0x0E74, 0x0714, 0x06F4, 0x06B0, 0x0336, 0x030A, 0x009F, 0x030B, - 0x0337, 0x06B1, 0x06F5, 0x0715, 0x0E75, 0x0E91, 0x0EC3, 0x0EF6, - 0x0EFB, 0x1EBB, 0x1EC3, 0x3E41, 0x3EF8, 0x3F10, 0x3F4D, 0x7EE9, - 0x7F52, 0x7F9A, 0x3F3F, 0x3F1F, 0x3F03, 0x3EA0, 0x1F0F, 0x1E72, - 0x1E62, 0x0EDA, 0x0ED2, 0x0EB2, 0x0E64, 0x0708, 0x06EA, 0x06DA, - 0x0346, 0x032A, 0x0176, 0x004B, 0x0177, 0x032B, 0x0347, 0x06DB, - 0x06EB, 0x0709, 0x0E65, 0x0EB3, 0x0ED3, 0x0EDB, 0x1E63, 0x1E6C, - 0x1F0E, 0x3E9E, 0x3F01, 0x3F1D, 0x3F3D, 0x7F9B, 0x7EDE, 0x3F36, - 0x3F2E, 0x3F07, 0x3E99, 0x1F0D, 0x1EA1, 0x1E8C, 0x0EB4, 0x0EAC, - 0x0E5A, 0x0E50, 0x0702, 0x06D4, 0x06C6, 0x032E, 0x0310, 0x0162, - 0x0046, 0x0163, 0x0311, 0x032F, 0x06C7, 0x06D5, 0x0703, 0x0E51, - 0x0E5B, 0x0EAD, 0x0EB5, 0x1E8F, 0x1EA7, 0x1F0C, 0x3E9A, 0x3F02, - 0x3F2D, 0x3F35, 0x7EE0, 0x7F66, 0x3F11, 0x3EE1, 0x3EBC, 0x3E56, - 0x1EC4, 0x1E64, 0x0F04, 0x0EC7, 0x0E56, 0x0E4C, 0x06EC, 0x06DC, - 0x069C, 0x0694, 0x0320, 0x016C, 0x0154, 0x0044, 0x0155, 0x016D, - 0x0321, 0x0695, 0x069D, 0x06DD, 0x06ED, 0x0E4D, 0x0E57, 0x0EC4, - 0x0F05, 0x1E65, 0x1EC5, 0x3E55, 0x3EB7, 0x3EE3, 0x3F13, 0x7F67, - 0x7FA7, 0x3F49, 0x3F22, 0x3EE5, 0x1EF6, 0x1EE5, 0x1E9C, 0x1E78, - 0x0EA4, 0x06F6, 0x06DE, 0x06CE, 0x06AA, 0x0340, 0x0318, 0x02FE, - 0x015E, 0x009A, 0x001C, 0x009B, 0x015F, 0x02FF, 0x0319, 0x0341, - 0x06AB, 0x06CF, 0x06DF, 0x06F7, 0x0EA5, 0x1E79, 0x1E9D, 0x1EE7, - 0x1EF7, 0x3EE6, 0x3F23, 0x3F4B, 0x7FA3, 0x7F49, 0x3F14, 0x3E8D, - 0x3E6B, 0x1F17, 0x1EF8, 0x0F24, 0x0ECC, 0x06FE, 0x06CA, 0x06A4, - 0x0698, 0x030C, 0x0302, 0x0170, 0x0168, 0x00A0, 0x001E, 0x0004, - 0x001F, 0x00A1, 0x0169, 0x0171, 0x0303, 0x030D, 0x0699, 0x06A5, - 0x06CB, 0x06FF, 0x0ECD, 0x0F25, 0x1EF9, 0x1F18, 0x3E6C, 0x3E8E, - 0x3F15, 0x7F46, 0x1EF0, 0x1EDE, 0x1EC8, 0x0F1A, 0x0F00, 0x0E9E, - 0x0E54, 0x06C4, 0x031E, 0x031C, 0x0306, 0x02F8, 0x017A, 0x0166, - 0x00A6, 0x00A4, 0x0048, 0x000C, 0x0000, 0x000D, 0x0049, 0x00A5, - 0x00A7, 0x0167, 0x017B, 0x02F9, 0x0307, 0x031D, 0x031F, 0x06C5, - 0x0E55, 0x0E9F, 0x0F01, 0x0F1B, 0x1EC9, 0x1EDF, 0x1EF1, 0x7F47, - 0x3F12, 0x3E8F, 0x3E6D, 0x1F1B, 0x1EFA, 0x0F26, 0x0ECE, 0x0700, - 0x06CC, 0x06A6, 0x069A, 0x030E, 0x0304, 0x0172, 0x016A, 0x00A2, - 0x0020, 0x0005, 0x0021, 0x00A3, 0x016B, 0x0173, 0x0305, 0x030F, - 0x069B, 0x06A7, 0x06CD, 0x0701, 0x0ECF, 0x0F27, 0x1EFB, 0x1F1D, - 0x3E6E, 0x3E90, 0x3F17, 0x7F48, 0x7FA9, 0x3F50, 0x3F24, 0x3EE7, - 0x1EFC, 0x1EE9, 0x1E9E, 0x1E7A, 0x0EA6, 0x06F8, 0x06E0, 0x06D0, - 0x06AC, 0x0342, 0x031A, 0x0300, 0x0160, 0x009C, 0x001D, 0x009D, - 0x0161, 0x0301, 0x031B, 0x0343, 0x06AD, 0x06D1, 0x06E1, 0x06F9, - 0x0EA7, 0x1E7B, 0x1E9F, 0x1EEA, 0x1EFD, 0x3EE8, 0x3F21, 0x3F52, - 0x7F9E, 0x7F68, 0x3F16, 0x3EE2, 0x3EBA, 0x3E57, 0x1EC6, 0x1E66, - 0x0F08, 0x0EC5, 0x0E58, 0x0E4E, 0x06EE, 0x06E2, 0x069E, 0x0696, - 0x0322, 0x016E, 0x0156, 0x0045, 0x0157, 0x016F, 0x0323, 0x0697, - 0x069F, 0x06E3, 0x06EF, 0x0E4F, 0x0E59, 0x0EC6, 0x0F09, 0x1E67, - 0x1EC7, 0x3E58, 0x3EB8, 0x3EE4, 0x3F18, 0x7F69, 0x7EE2, 0x3F38, - 0x3F33, 0x3F04, 0x3E9C, 0x1F0A, 0x1EA5, 0x1E8D, 0x0EB6, 0x0EAE, - 0x0E5C, 0x0E52, 0x0704, 0x06D6, 0x06C8, 0x0330, 0x0312, 0x0164, - 0x0047, 0x0165, 0x0313, 0x0331, 0x06C9, 0x06D7, 0x0705, 0x0E53, - 0x0E5D, 0x0EAF, 0x0EB7, 0x1E8E, 0x1EA6, 0x1F0B, 0x3E9B, 0x3F05, - 0x3F31, 0x3F39, 0x7EE1, 0x7F9C, 0x3F40, 0x3F1E, 0x3F06, 0x3E9D, - 0x1F10, 0x1E70, 0x1E60, 0x0ED8, 0x0ED0, 0x0EB0, 0x0E62, 0x0706, - 0x06E8, 0x06D8, 0x0344, 0x0328, 0x0174, 0x004A, 0x0175, 0x0329, - 0x0345, 0x06D9, 0x06E9, 0x0707, 0x0E63, 0x0EB1, 0x0ED1, 0x0ED9, - 0x1E61, 0x1E71, 0x1F11, 0x3E9F, 0x3F08, 0x3F20, 0x3F3E, 0x7F9D, - 0x7F4F, 0x7EE6, 0x3F53, 0x3F0D, 0x3EFA, 0x3E46, 0x1EC0, 0x1EB8, - 0x0EF8, 0x0EF2, 0x0EC0, 0x0E8E, 0x0E72, 0x0712, 0x06F2, 0x06AE, - 0x0334, 0x0308, 0x009E, 0x0309, 0x0335, 0x06AF, 0x06F3, 0x0713, - 0x0E73, 0x0E90, 0x0EC2, 0x0EF4, 0x0EFA, 0x1EBA, 0x1EC2, 0x3E48, - 0x3EFC, 0x3F0B, 0x3F51, 0x7EE7, 0x7F51, 0x7F84, 0x7F61, 0x7F27, - 0x3EDC, 0x3EC5, 0x3E7C, 0x1ED8, 0x1ED0, 0x0EFE, 0x0EF5, 0x0E9C, - 0x0E80, 0x0E68, 0x0E60, 0x0724, 0x06C2, 0x06A2, 0x02FC, 0x00A9, - 0x02FD, 0x06A3, 0x06C3, 0x0725, 0x0E61, 0x0E69, 0x0E81, 0x0E9D, - 0x0EF7, 0x0EFF, 0x1ED1, 0x1ED9, 0x3E7B, 0x3ECF, 0x3ED9, 0x7F29, - 0x7F65, 0x7F85, 0x7FA0, 0x7EEA, 0x3F60, 0x3EB4, 0x3EAC, 0x3E5F, - 0x3E4B, 0x1F00, 0x1E8B, 0x0F18, 0x0F14, 0x0EE2, 0x0E7C, 0x0E6C, - 0x0710, 0x06FC, 0x06B6, 0x0316, 0x0159, 0x0317, 0x06B7, 0x06FD, - 0x0711, 0x0E6D, 0x0E7D, 0x0EE3, 0x0F15, 0x0F19, 0x1E88, 0x1F01, - 0x3E4C, 0x3E60, 0x3EA9, 0x3EB1, 0x3F5B, 0x7EED, 0x7FA5, 0xFF9E, - 0x7FBE, 0x7F98, 0x7F0D, 0x7EF3, 0x3E8C, 0x3E50, 0x1EB7, 0x1E73, - 0x0F2F, 0x0EBF, 0x0E99, 0x0E95, 0x0E88, 0x071C, 0x06E6, 0x06BE, - 0x033A, 0x015B, 0x033B, 0x06BF, 0x06E7, 0x071D, 0x0E89, 0x0E92, - 0x0E96, 0x0EBC, 0x0F2C, 0x1E6D, 0x1EB0, 0x3E4D, 0x3E8B, 0x7EF2, - 0x7F08, 0x7F97, 0x7FB0, 0xFF9C, 0x7FB2, 0x7F23, 0x7EFA, 0x3F0F, - 0x3EBD, 0x3EAD, 0x1EA0, 0x1E87, 0x0F0A, 0x0F02, 0x0EED, 0x0EE4, - 0x0EC8, 0x0EA0, 0x0E76, 0x071E, 0x06B8, 0x0324, 0x015C, 0x0325, - 0x06B9, 0x071F, 0x0E77, 0x0EA1, 0x0EC9, 0x0EE5, 0x0EEC, 0x0F03, - 0x0F0B, 0x1E84, 0x1EA2, 0x3EB0, 0x3EC4, 0x3F09, 0x7EF7, 0x7F1D, - 0x7FBC, 0x7FCD, 0x7F81, 0x7F50, 0x7F34, 0x3F65, 0x3EED, 0x3E67, - 0x1EDB, 0x1ED2, 0x1E99, 0x1E77, 0x0F21, 0x0F1C, 0x0EE8, 0x0EA8, - 0x0E6E, 0x0716, 0x033C, 0x0178, 0x033D, 0x0717, 0x0E6F, 0x0EAA, - 0x0EEB, 0x0F1E, 0x0F23, 0x1E75, 0x1E9A, 0x1ED4, 0x1EDC, 0x3E66, - 0x3EEE, 0x3F6B, 0x7F35, 0x7F55, 0x7F7A, 0x7FCA, 0x7FB6, 0x7FB8, - 0x7F37, 0x7F1F, 0x3F61, 0x3F37, 0x3F1A, 0x3EB5, 0x3E62, 0x3E5A, - 0x1F1E, 0x1F13, 0x1EF2, 0x1EE6, 0x1EBC, 0x1E91, 0x1E68, 0x070A, - 0x032C, 0x070B, 0x1E69, 0x1E90, 0x1EBD, 0x1EE4, 0x1EF4, 0x1F12, - 0x3E3E, 0x3E59, 0x3E61, 0x3EB6, 0x3F19, 0x3F3B, 0x3F64, 0x7F1C, - 0x7F3D, 0x7FB4, 0x7FB9, 0xFFC5, 0xFFB6, 0xFFAD, 0x7FA4, 0x7F2C, - 0x7F20, 0x7F09, 0x3EF5, 0x3E93, 0x3E82, 0x3E7E, 0x1F02, 0x1EE3, - 0x1ECA, 0x1EAD, 0x1E7C, 0x0EB8, 0x0E8A, 0x0332, 0x0E8B, 0x0EB9, - 0x1E7D, 0x1EAC, 0x1ECD, 0x1EE0, 0x1F03, 0x3E7D, 0x3E81, 0x3E91, - 0x3EF7, 0x7F0C, 0x7F1A, 0x7F2E, 0x7FA6, 0xFFA4, 0xFFB7, 0xFFC4, - 0xFFD4, 0xFFCC, 0x7FC5, 0x7F8A, 0x7F3C, 0x7EFF, 0x3F5E, 0x3F4E, - 0x3F2F, 0x3EFD, 0x3EEF, 0x3EEB, 0x3E92, 0x3E71, 0x3E42, 0x1F09, - 0x1E83, 0x0E82, 0x0348, 0x0E83, 0x1E80, 0x1F06, 0x3E44, 0x3E72, - 0x3E94, 0x3EEC, 0x3EF2, 0x3EFE, 0x3F34, 0x3F4C, 0x3F5F, 0x7EFE, - 0x7F3A, 0x7F86, 0x7FC4, 0xFFD2, 0xFFD5, 0xFFFA, 0xFFCD, 0xFFBA, - 0x7FAB, 0x7F92, 0x7F87, 0x7F63, 0x7F4C, 0x7F03, 0x7EF0, 0x3F42, - 0x3EA1, 0x3E76, 0x3E6A, 0x3E52, 0x1EEE, 0x1EAB, 0x0ED6, 0x06A9, - 0x0ED7, 0x1EAA, 0x1EED, 0x3E53, 0x3E70, 0x3E77, 0x3EA2, 0x3F41, - 0x7EEF, 0x7F00, 0x7F4D, 0x7F60, 0x7F88, 0x7F93, 0x7FAD, 0xFFB8, - 0xFFCB, 0xFFFB, 0xFFFC, 0xFFE1, 0xFFBF, 0x7FBA, 0x7F73, 0x7F6C, - 0x7F57, 0x7EFC, 0x7EDD, 0x3F6A, 0x3F2A, 0x3F25, 0x3EDD, 0x3ED3, - 0x3EC2, 0x3EA7, 0x3E86, 0x0F11, 0x06B2, 0x0F0E, 0x3E8A, 0x3EA5, - 0x3EC0, 0x3ED1, 0x3EDE, 0x3F2C, 0x3F29, 0x3F69, 0x7EDB, 0x7EFD, - 0x7F59, 0x7F6D, 0x7F74, 0x7FC0, 0xFFC3, 0xFFE3, 0xFFFD, 0xFFF0, - 0xFFE9, 0xFFE7, 0xFFC9, 0xFFBD, 0xFFAE, 0x7F71, 0x7F5F, 0x7F42, - 0x7F41, 0x7F30, 0x7F17, 0x7EE4, 0x3ED7, 0x3EC7, 0x3ECB, 0x1EB1, - 0x0EDC, 0x06D2, 0x0EDD, 0x1EB2, 0x3EC6, 0x3EC8, 0x3ED4, 0x7EE3, - 0x7F18, 0x7F2B, 0x7F3F, 0x7F43, 0x7F64, 0x7F6E, 0xFFAB, 0xFFC2, - 0xFFD0, 0xFFE6, 0xFFEF, 0xFFF3, 0xFFF7, 0xFFEB, 0xFFDE, 0xFFDA, - 0xFFB3, 0xFFAC, 0xFFA3, 0x7FC9, 0x7F8F, 0x7F7C, 0x7F79, 0x7F0F, - 0x7F10, 0x3F55, 0x3F45, 0x1F1A, 0x1E95, 0x0F2B, 0x06F1, 0x0F29, - 0x1E97, 0x1F19, 0x3F47, 0x3F57, 0x7F14, 0x7F12, 0x7F78, 0x7F7E, - 0x7F91, 0x7FC7, 0xFFA1, 0xFFA5, 0xFFB2, 0xFFDB, 0xFFDF, 0xFFED, - 0xFFF4, 0x004C, -}; - -static const uint16_t clv_mvy_3_syms[] = { - 0xEEEE, 0xEFEE, 0xF0EE, 0xF1EE, 0xF2EE, 0xF3EE, 0xF4EE, 0xF5EE, - 0xF6EE, 0xF7EE, 0xF8EE, 0xF9EE, 0xFAEE, 0xFBEE, 0xFCEE, 0xFDEE, - 0xFEEE, 0xFFEE, 0x00EE, 0x01EE, 0x02EE, 0x03EE, 0x04EE, 0x05EE, - 0x06EE, 0x07EE, 0x08EE, 0x09EE, 0x0AEE, 0x0BEE, 0x0CEE, 0x0DEE, - 0x0EEE, 0x0FEE, 0x10EE, 0x11EE, 0x12EE, 0xEEEF, 0xEFEF, 0xF0EF, - 0xF1EF, 0xF2EF, 0xF3EF, 0xF4EF, 0xF5EF, 0xF6EF, 0xF7EF, 0xF8EF, - 0xF9EF, 0xFAEF, 0xFBEF, 0xFCEF, 0xFDEF, 0xFEEF, 0xFFEF, 0x00EF, - 0x01EF, 0x02EF, 0x03EF, 0x04EF, 0x05EF, 0x06EF, 0x07EF, 0x08EF, - 0x09EF, 0x0AEF, 0x0BEF, 0x0CEF, 0x0DEF, 0x0EEF, 0x0FEF, 0x10EF, - 0x11EF, 0x12EF, 0xEEF0, 0xEFF0, 0xF0F0, 0xF1F0, 0xF2F0, 0xF3F0, - 0xF4F0, 0xF5F0, 0xF6F0, 0xF7F0, 0xF8F0, 0xF9F0, 0xFAF0, 0xFBF0, - 0xFCF0, 0xFDF0, 0xFEF0, 0xFFF0, 0x00F0, 0x01F0, 0x02F0, 0x03F0, - 0x04F0, 0x05F0, 0x06F0, 0x07F0, 0x08F0, 0x09F0, 0x0AF0, 0x0BF0, - 0x0CF0, 0x0DF0, 0x0EF0, 0x0FF0, 0x10F0, 0x11F0, 0x12F0, 0xEEF1, - 0xEFF1, 0xF0F1, 0xF1F1, 0xF2F1, 0xF3F1, 0xF4F1, 0xF5F1, 0xF6F1, - 0xF7F1, 0xF8F1, 0xF9F1, 0xFAF1, 0xFBF1, 0xFCF1, 0xFDF1, 0xFEF1, - 0xFFF1, 0x00F1, 0x01F1, 0x02F1, 0x03F1, 0x04F1, 0x05F1, 0x06F1, - 0x07F1, 0x08F1, 0x09F1, 0x0AF1, 0x0BF1, 0x0CF1, 0x0DF1, 0x0EF1, - 0x0FF1, 0x10F1, 0x11F1, 0x12F1, 0xEEF2, 0xEFF2, 0xF0F2, 0xF1F2, - 0xF2F2, 0xF3F2, 0xF4F2, 0xF5F2, 0xF6F2, 0xF7F2, 0xF8F2, 0xF9F2, - 0xFAF2, 0xFBF2, 0xFCF2, 0xFDF2, 0xFEF2, 0xFFF2, 0x00F2, 0x01F2, - 0x02F2, 0x03F2, 0x04F2, 0x05F2, 0x06F2, 0x07F2, 0x08F2, 0x09F2, - 0x0AF2, 0x0BF2, 0x0CF2, 0x0DF2, 0x0EF2, 0x0FF2, 0x10F2, 0x11F2, - 0x12F2, 0xEEF3, 0xEFF3, 0xF0F3, 0xF1F3, 0xF2F3, 0xF3F3, 0xF4F3, - 0xF5F3, 0xF6F3, 0xF7F3, 0xF8F3, 0xF9F3, 0xFAF3, 0xFBF3, 0xFCF3, - 0xFDF3, 0xFEF3, 0xFFF3, 0x00F3, 0x01F3, 0x02F3, 0x03F3, 0x04F3, - 0x05F3, 0x06F3, 0x07F3, 0x08F3, 0x09F3, 0x0AF3, 0x0BF3, 0x0CF3, - 0x0DF3, 0x0EF3, 0x0FF3, 0x10F3, 0x11F3, 0x12F3, 0xEEF4, 0xEFF4, - 0xF0F4, 0xF1F4, 0xF2F4, 0xF3F4, 0xF4F4, 0xF5F4, 0xF6F4, 0xF7F4, - 0xF8F4, 0xF9F4, 0xFAF4, 0xFBF4, 0xFCF4, 0xFDF4, 0xFEF4, 0xFFF4, - 0x00F4, 0x01F4, 0x02F4, 0x03F4, 0x04F4, 0x05F4, 0x06F4, 0x07F4, - 0x08F4, 0x09F4, 0x0AF4, 0x0BF4, 0x0CF4, 0x0DF4, 0x0EF4, 0x0FF4, - 0x10F4, 0x11F4, 0x12F4, 0xEEF5, 0xEFF5, 0xF0F5, 0xF1F5, 0xF2F5, - 0xF3F5, 0xF4F5, 0xF5F5, 0xF6F5, 0xF7F5, 0xF8F5, 0xF9F5, 0xFAF5, - 0xFBF5, 0xFCF5, 0xFDF5, 0xFEF5, 0xFFF5, 0x00F5, 0x01F5, 0x02F5, - 0x03F5, 0x04F5, 0x05F5, 0x06F5, 0x07F5, 0x08F5, 0x09F5, 0x0AF5, - 0x0BF5, 0x0CF5, 0x0DF5, 0x0EF5, 0x0FF5, 0x10F5, 0x11F5, 0x12F5, - 0xEEF6, 0xEFF6, 0xF0F6, 0xF1F6, 0xF2F6, 0xF3F6, 0xF4F6, 0xF5F6, - 0xF6F6, 0xF7F6, 0xF8F6, 0xF9F6, 0xFAF6, 0xFBF6, 0xFCF6, 0xFDF6, - 0xFEF6, 0xFFF6, 0x00F6, 0x01F6, 0x02F6, 0x03F6, 0x04F6, 0x05F6, - 0x06F6, 0x07F6, 0x08F6, 0x09F6, 0x0AF6, 0x0BF6, 0x0CF6, 0x0DF6, - 0x0EF6, 0x0FF6, 0x10F6, 0x11F6, 0x12F6, 0xEEF7, 0xEFF7, 0xF0F7, - 0xF1F7, 0xF2F7, 0xF3F7, 0xF4F7, 0xF5F7, 0xF6F7, 0xF7F7, 0xF8F7, - 0xF9F7, 0xFAF7, 0xFBF7, 0xFCF7, 0xFDF7, 0xFEF7, 0xFFF7, 0x00F7, - 0x01F7, 0x02F7, 0x03F7, 0x04F7, 0x05F7, 0x06F7, 0x07F7, 0x08F7, - 0x09F7, 0x0AF7, 0x0BF7, 0x0CF7, 0x0DF7, 0x0EF7, 0x0FF7, 0x10F7, - 0x11F7, 0x12F7, 0xEEF8, 0xEFF8, 0xF0F8, 0xF1F8, 0xF2F8, 0xF3F8, - 0xF4F8, 0xF5F8, 0xF6F8, 0xF7F8, 0xF8F8, 0xF9F8, 0xFAF8, 0xFBF8, - 0xFCF8, 0xFDF8, 0xFEF8, 0xFFF8, 0x00F8, 0x01F8, 0x02F8, 0x03F8, - 0x04F8, 0x05F8, 0x06F8, 0x07F8, 0x08F8, 0x09F8, 0x0AF8, 0x0BF8, - 0x0CF8, 0x0DF8, 0x0EF8, 0x0FF8, 0x10F8, 0x11F8, 0x12F8, 0xEEF9, - 0xEFF9, 0xF0F9, 0xF1F9, 0xF2F9, 0xF3F9, 0xF4F9, 0xF5F9, 0xF6F9, - 0xF7F9, 0xF8F9, 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, - 0xFFF9, 0x00F9, 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, - 0x07F9, 0x08F9, 0x09F9, 0x0AF9, 0x0BF9, 0x0CF9, 0x0DF9, 0x0EF9, - 0x0FF9, 0x10F9, 0x11F9, 0x12F9, 0xEEFA, 0xEFFA, 0xF0FA, 0xF1FA, - 0xF2FA, 0xF3FA, 0xF4FA, 0xF5FA, 0xF6FA, 0xF7FA, 0xF8FA, 0xF9FA, - 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, - 0x02FA, 0x03FA, 0x04FA, 0x05FA, 0x06FA, 0x07FA, 0x08FA, 0x09FA, - 0x0AFA, 0x0BFA, 0x0CFA, 0x0DFA, 0x0EFA, 0x0FFA, 0x10FA, 0x11FA, - 0x12FA, 0xEEFB, 0xEFFB, 0xF0FB, 0xF1FB, 0xF2FB, 0xF3FB, 0xF4FB, - 0xF5FB, 0xF6FB, 0xF7FB, 0xF8FB, 0xF9FB, 0xFAFB, 0xFBFB, 0xFCFB, - 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, 0x03FB, 0x04FB, - 0x05FB, 0x06FB, 0x07FB, 0x08FB, 0x09FB, 0x0AFB, 0x0BFB, 0x0CFB, - 0x0DFB, 0x0EFB, 0x0FFB, 0x10FB, 0x11FB, 0x12FB, 0xEEFC, 0xEFFC, - 0xF0FC, 0xF1FC, 0xF2FC, 0xF3FC, 0xF4FC, 0xF5FC, 0xF6FC, 0xF7FC, - 0xF8FC, 0xF9FC, 0xFAFC, 0xFBFC, 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, - 0x00FC, 0x01FC, 0x02FC, 0x03FC, 0x04FC, 0x05FC, 0x06FC, 0x07FC, - 0x08FC, 0x09FC, 0x0AFC, 0x0BFC, 0x0CFC, 0x0DFC, 0x0EFC, 0x0FFC, - 0x10FC, 0x11FC, 0x12FC, 0xEEFD, 0xEFFD, 0xF0FD, 0xF1FD, 0xF2FD, - 0xF3FD, 0xF4FD, 0xF5FD, 0xF6FD, 0xF7FD, 0xF8FD, 0xF9FD, 0xFAFD, - 0xFBFD, 0xFCFD, 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, - 0x03FD, 0x04FD, 0x05FD, 0x06FD, 0x07FD, 0x08FD, 0x09FD, 0x0AFD, - 0x0BFD, 0x0CFD, 0x0DFD, 0x0EFD, 0x0FFD, 0x10FD, 0x11FD, 0x12FD, - 0xEEFE, 0xEFFE, 0xF0FE, 0xF1FE, 0xF2FE, 0xF3FE, 0xF4FE, 0xF5FE, - 0xF6FE, 0xF7FE, 0xF8FE, 0xF9FE, 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, - 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, 0x02FE, 0x03FE, 0x04FE, 0x05FE, - 0x06FE, 0x07FE, 0x08FE, 0x09FE, 0x0AFE, 0x0BFE, 0x0CFE, 0x0DFE, - 0x0EFE, 0x0FFE, 0x10FE, 0x11FE, 0x12FE, 0xEEFF, 0xEFFF, 0xF0FF, - 0xF1FF, 0xF2FF, 0xF3FF, 0xF4FF, 0xF5FF, 0xF6FF, 0xF7FF, 0xF8FF, - 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, 0xFFFF, 0x00FF, - 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, 0x07FF, 0x08FF, - 0x09FF, 0x0AFF, 0x0BFF, 0x0CFF, 0x0DFF, 0x0EFF, 0x0FFF, 0x10FF, - 0x11FF, 0x12FF, 0xEE00, 0xEF00, 0xF000, 0xF100, 0xF200, 0xF300, - 0xF400, 0xF500, 0xF600, 0xF700, 0xF800, 0xF900, 0xFA00, 0xFB00, - 0xFC00, 0xFD00, 0xFE00, 0xFF00, 0x0000, 0x0100, 0x0200, 0x0300, - 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0x0B00, - 0x0C00, 0x0D00, 0x0E00, 0x0F00, 0x1000, 0x1100, 0x1200, 0xEE01, - 0xEF01, 0xF001, 0xF101, 0xF201, 0xF301, 0xF401, 0xF501, 0xF601, - 0xF701, 0xF801, 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, - 0xFF01, 0x0001, 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, - 0x0701, 0x0801, 0x0901, 0x0A01, 0x0B01, 0x0C01, 0x0D01, 0x0E01, - 0x0F01, 0x1001, 0x1101, 0x1201, 0xEE02, 0xEF02, 0xF002, 0xF102, - 0xF202, 0xF302, 0xF402, 0xF502, 0xF602, 0xF702, 0xF802, 0xF902, - 0xFA02, 0xFB02, 0xFC02, 0xFD02, 0xFE02, 0xFF02, 0x0002, 0x0102, - 0x0202, 0x0302, 0x0402, 0x0502, 0x0602, 0x0702, 0x0802, 0x0902, - 0x0A02, 0x0B02, 0x0C02, 0x0D02, 0x0E02, 0x0F02, 0x1002, 0x1102, - 0x1202, 0xEE03, 0xEF03, 0xF003, 0xF103, 0xF203, 0xF303, 0xF403, - 0xF503, 0xF603, 0xF703, 0xF803, 0xF903, 0xFA03, 0xFB03, 0xFC03, - 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, 0x0303, 0x0403, - 0x0503, 0x0603, 0x0703, 0x0803, 0x0903, 0x0A03, 0x0B03, 0x0C03, - 0x0D03, 0x0E03, 0x0F03, 0x1003, 0x1103, 0x1203, 0xEE04, 0xEF04, - 0xF004, 0xF104, 0xF204, 0xF304, 0xF404, 0xF504, 0xF604, 0xF704, - 0xF804, 0xF904, 0xFA04, 0xFB04, 0xFC04, 0xFD04, 0xFE04, 0xFF04, - 0x0004, 0x0104, 0x0204, 0x0304, 0x0404, 0x0504, 0x0604, 0x0704, - 0x0804, 0x0904, 0x0A04, 0x0B04, 0x0C04, 0x0D04, 0x0E04, 0x0F04, - 0x1004, 0x1104, 0x1204, 0xEE05, 0xEF05, 0xF005, 0xF105, 0xF205, - 0xF305, 0xF405, 0xF505, 0xF605, 0xF705, 0xF805, 0xF905, 0xFA05, - 0xFB05, 0xFC05, 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, - 0x0305, 0x0405, 0x0505, 0x0605, 0x0705, 0x0805, 0x0905, 0x0A05, - 0x0B05, 0x0C05, 0x0D05, 0x0E05, 0x0F05, 0x1005, 0x1105, 0x1205, - 0xEE06, 0xEF06, 0xF006, 0xF106, 0xF206, 0xF306, 0xF406, 0xF506, - 0xF606, 0xF706, 0xF806, 0xF906, 0xFA06, 0xFB06, 0xFC06, 0xFD06, - 0xFE06, 0xFF06, 0x0006, 0x0106, 0x0206, 0x0306, 0x0406, 0x0506, - 0x0606, 0x0706, 0x0806, 0x0906, 0x0A06, 0x0B06, 0x0C06, 0x0D06, - 0x0E06, 0x0F06, 0x1006, 0x1106, 0x1206, 0xEE07, 0xEF07, 0xF007, - 0xF107, 0xF207, 0xF307, 0xF407, 0xF507, 0xF607, 0xF707, 0xF807, - 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, 0xFF07, 0x0007, - 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, 0x0707, 0x0807, - 0x0907, 0x0A07, 0x0B07, 0x0C07, 0x0D07, 0x0E07, 0x0F07, 0x1007, - 0x1107, 0x1207, 0xEE08, 0xEF08, 0xF008, 0xF108, 0xF208, 0xF308, - 0xF408, 0xF508, 0xF608, 0xF708, 0xF808, 0xF908, 0xFA08, 0xFB08, - 0xFC08, 0xFD08, 0xFE08, 0xFF08, 0x0008, 0x0108, 0x0208, 0x0308, - 0x0408, 0x0508, 0x0608, 0x0708, 0x0808, 0x0908, 0x0A08, 0x0B08, - 0x0C08, 0x0D08, 0x0E08, 0x0F08, 0x1008, 0x1108, 0x1208, 0xEE09, - 0xEF09, 0xF009, 0xF109, 0xF209, 0xF309, 0xF409, 0xF509, 0xF609, - 0xF709, 0xF809, 0xF909, 0xFA09, 0xFB09, 0xFC09, 0xFD09, 0xFE09, - 0xFF09, 0x0009, 0x0109, 0x0209, 0x0309, 0x0409, 0x0509, 0x0609, - 0x0709, 0x0809, 0x0909, 0x0A09, 0x0B09, 0x0C09, 0x0D09, 0x0E09, - 0x0F09, 0x1009, 0x1109, 0x1209, 0xEE0A, 0xEF0A, 0xF00A, 0xF10A, - 0xF20A, 0xF30A, 0xF40A, 0xF50A, 0xF60A, 0xF70A, 0xF80A, 0xF90A, - 0xFA0A, 0xFB0A, 0xFC0A, 0xFD0A, 0xFE0A, 0xFF0A, 0x000A, 0x010A, - 0x020A, 0x030A, 0x040A, 0x050A, 0x060A, 0x070A, 0x080A, 0x090A, - 0x0A0A, 0x0B0A, 0x0C0A, 0x0D0A, 0x0E0A, 0x0F0A, 0x100A, 0x110A, - 0x120A, 0xEE0B, 0xEF0B, 0xF00B, 0xF10B, 0xF20B, 0xF30B, 0xF40B, - 0xF50B, 0xF60B, 0xF70B, 0xF80B, 0xF90B, 0xFA0B, 0xFB0B, 0xFC0B, - 0xFD0B, 0xFE0B, 0xFF0B, 0x000B, 0x010B, 0x020B, 0x030B, 0x040B, - 0x050B, 0x060B, 0x070B, 0x080B, 0x090B, 0x0A0B, 0x0B0B, 0x0C0B, - 0x0D0B, 0x0E0B, 0x0F0B, 0x100B, 0x110B, 0x120B, 0xEE0C, 0xEF0C, - 0xF00C, 0xF10C, 0xF20C, 0xF30C, 0xF40C, 0xF50C, 0xF60C, 0xF70C, - 0xF80C, 0xF90C, 0xFA0C, 0xFB0C, 0xFC0C, 0xFD0C, 0xFE0C, 0xFF0C, - 0x000C, 0x010C, 0x020C, 0x030C, 0x040C, 0x050C, 0x060C, 0x070C, - 0x080C, 0x090C, 0x0A0C, 0x0B0C, 0x0C0C, 0x0D0C, 0x0E0C, 0x0F0C, - 0x100C, 0x110C, 0x120C, 0xEE0D, 0xEF0D, 0xF00D, 0xF10D, 0xF20D, - 0xF30D, 0xF40D, 0xF50D, 0xF60D, 0xF70D, 0xF80D, 0xF90D, 0xFA0D, - 0xFB0D, 0xFC0D, 0xFD0D, 0xFE0D, 0xFF0D, 0x000D, 0x010D, 0x020D, - 0x030D, 0x040D, 0x050D, 0x060D, 0x070D, 0x080D, 0x090D, 0x0A0D, - 0x0B0D, 0x0C0D, 0x0D0D, 0x0E0D, 0x0F0D, 0x100D, 0x110D, 0x120D, - 0xEE0E, 0xEF0E, 0xF00E, 0xF10E, 0xF20E, 0xF30E, 0xF40E, 0xF50E, - 0xF60E, 0xF70E, 0xF80E, 0xF90E, 0xFA0E, 0xFB0E, 0xFC0E, 0xFD0E, - 0xFE0E, 0xFF0E, 0x000E, 0x010E, 0x020E, 0x030E, 0x040E, 0x050E, - 0x060E, 0x070E, 0x080E, 0x090E, 0x0A0E, 0x0B0E, 0x0C0E, 0x0D0E, - 0x0E0E, 0x0F0E, 0x100E, 0x110E, 0x120E, 0xEE0F, 0xEF0F, 0xF00F, - 0xF10F, 0xF20F, 0xF30F, 0xF40F, 0xF50F, 0xF60F, 0xF70F, 0xF80F, - 0xF90F, 0xFA0F, 0xFB0F, 0xFC0F, 0xFD0F, 0xFE0F, 0xFF0F, 0x000F, - 0x010F, 0x020F, 0x030F, 0x040F, 0x050F, 0x060F, 0x070F, 0x080F, - 0x090F, 0x0A0F, 0x0B0F, 0x0C0F, 0x0D0F, 0x0E0F, 0x0F0F, 0x100F, - 0x110F, 0x120F, 0xEE10, 0xEF10, 0xF010, 0xF110, 0xF210, 0xF310, - 0xF410, 0xF510, 0xF610, 0xF710, 0xF810, 0xF910, 0xFA10, 0xFB10, - 0xFC10, 0xFD10, 0xFE10, 0xFF10, 0x0010, 0x0110, 0x0210, 0x0310, - 0x0410, 0x0510, 0x0610, 0x0710, 0x0810, 0x0910, 0x0A10, 0x0B10, - 0x0C10, 0x0D10, 0x0E10, 0x0F10, 0x1010, 0x1110, 0x1210, 0xEE11, - 0xEF11, 0xF011, 0xF111, 0xF211, 0xF311, 0xF411, 0xF511, 0xF611, - 0xF711, 0xF811, 0xF911, 0xFA11, 0xFB11, 0xFC11, 0xFD11, 0xFE11, - 0xFF11, 0x0011, 0x0111, 0x0211, 0x0311, 0x0411, 0x0511, 0x0611, - 0x0711, 0x0811, 0x0911, 0x0A11, 0x0B11, 0x0C11, 0x0D11, 0x0E11, - 0x0F11, 0x1011, 0x1111, 0x1211, 0xEE12, 0xEF12, 0xF012, 0xF112, - 0xF212, 0xF312, 0xF412, 0xF512, 0xF612, 0xF712, 0xF812, 0xF912, - 0xFA12, 0xFB12, 0xFC12, 0xFD12, 0xFE12, 0xFF12, 0x0012, 0x0112, - 0x0212, 0x0312, 0x0412, 0x0512, 0x0612, 0x0712, 0x0812, 0x0912, - 0x0A12, 0x0B12, 0x0C12, 0x0D12, 0x0E12, 0x0F12, 0x1012, 0x1112, - 0x1212, 0x1313, -}; - -static const uint8_t clv_mvu_1_bits[] = { - 16, 14, 14, 14, 13, 12, 12, 10, 12, 12, 13, 14, 14, 14, 16, 15, - 13, 13, 12, 12, 11, 11, 7, 11, 11, 12, 12, 13, 13, 15, 16, 16, - 16, 13, 12, 10, 10, 6, 10, 10, 12, 13, 16, 16, 16, 14, 14, 11, - 11, 11, 11, 9, 7, 9, 11, 11, 11, 11, 14, 14, 15, 13, 13, 12, - 9, 8, 8, 4, 8, 8, 9, 12, 13, 13, 15, 14, 14, 11, 11, 10, - 9, 8, 4, 8, 9, 10, 11, 12, 14, 14, 12, 12, 11, 10, 10, 8, - 6, 3, 6, 8, 10, 10, 11, 12, 12, 11, 10, 9, 6, 6, 6, 5, - 4, 5, 6, 6, 6, 9, 10, 11, 12, 12, 11, 10, 10, 8, 6, 3, - 6, 7, 10, 10, 11, 12, 12, 14, 14, 11, 11, 10, 9, 8, 4, 8, - 9, 10, 11, 11, 14, 14, 15, 13, 13, 12, 9, 8, 8, 4, 8, 8, - 9, 12, 13, 13, 15, 14, 14, 11, 11, 11, 11, 9, 7, 9, 11, 11, - 11, 11, 14, 14, 16, 16, 16, 13, 12, 10, 10, 6, 10, 10, 12, 13, - 16, 16, 16, 15, 13, 13, 12, 12, 11, 11, 7, 11, 11, 12, 12, 13, - 13, 15, 16, 14, 14, 14, 13, 12, 12, 10, 12, 12, 13, 14, 14, 14, - 16, 7, -}; - -static const uint16_t clv_mvu_1_codes[] = { - 0xFFFC, 0x3FED, 0x3FE5, 0x3FE3, 0x1FD9, 0x0FD9, 0x0FD6, 0x03CE, - 0x0FD3, 0x0FD8, 0x1FD6, 0x3FE0, 0x3FE8, 0x3FEC, 0xFFFE, 0x7FF3, - 0x1FE7, 0x1FDA, 0x0FCF, 0x0FCC, 0x07DD, 0x07CC, 0x006B, 0x07CD, - 0x07DE, 0x0FCE, 0x0FD2, 0x1FDD, 0x1FEC, 0x7FF0, 0xFFF6, 0xFFFA, - 0xFFF2, 0x1FDE, 0x0FDB, 0x03D8, 0x03CA, 0x002E, 0x03CB, 0x03D9, - 0x0FDC, 0x1FDF, 0xFFF3, 0xFFF9, 0xFFF5, 0x3FF3, 0x3FDD, 0x07DA, - 0x07D2, 0x07CA, 0x07C2, 0x01DE, 0x0069, 0x01DF, 0x07C3, 0x07CB, - 0x07D3, 0x07DB, 0x3FDF, 0x3FF6, 0x7FF7, 0x1FED, 0x1FE5, 0x0FDF, - 0x01D8, 0x00E3, 0x00DF, 0x0007, 0x00E0, 0x00E4, 0x01D9, 0x0FE0, - 0x1FE3, 0x1FE9, 0x7FF4, 0x3FF5, 0x3FE7, 0x07E4, 0x07C6, 0x03D2, - 0x01E2, 0x00E9, 0x0006, 0x00EA, 0x01E3, 0x03D3, 0x07C7, 0x0FCA, - 0x3FE9, 0x3FF0, 0x0FE8, 0x0FE5, 0x07D5, 0x03DD, 0x03D5, 0x00DC, - 0x002B, 0x0001, 0x002C, 0x00DD, 0x03D6, 0x03DE, 0x07D6, 0x0FE4, - 0x0FE9, 0x07E0, 0x03C8, 0x01D6, 0x0032, 0x0030, 0x0028, 0x0012, - 0x0004, 0x0013, 0x0029, 0x0031, 0x0033, 0x01D7, 0x03C9, 0x07E1, - 0x0FEA, 0x0FE6, 0x07D7, 0x03DF, 0x03D7, 0x00DE, 0x002D, 0x0000, - 0x002A, 0x006D, 0x03D4, 0x03DC, 0x07D4, 0x0FE3, 0x0FE7, 0x3FF1, - 0x3FE4, 0x07E2, 0x07C4, 0x03D0, 0x01E0, 0x00E7, 0x0005, 0x00E8, - 0x01E1, 0x03D1, 0x07C5, 0x07E3, 0x3FEA, 0x3FF7, 0x7FF6, 0x1FE6, - 0x1FE4, 0x0FE1, 0x01DA, 0x00E5, 0x00E1, 0x0008, 0x00E2, 0x00E6, - 0x01DB, 0x0FE2, 0x1FE2, 0x1FEB, 0x7FF5, 0x3FF4, 0x3FDC, 0x07D9, - 0x07D0, 0x07C8, 0x07C0, 0x01DC, 0x0068, 0x01DD, 0x07C1, 0x07C9, - 0x07D1, 0x07D8, 0x3FDE, 0x3FF2, 0xFFFB, 0xFFF4, 0xFFF0, 0x1FE1, - 0x0FDD, 0x03DA, 0x03CC, 0x002F, 0x03CD, 0x03DB, 0x0FDE, 0x1FE0, - 0xFFF1, 0xFFF7, 0xFFF8, 0x7FF2, 0x1FEA, 0x1FDC, 0x0FD1, 0x0FCD, - 0x07DC, 0x07CF, 0x006C, 0x07CE, 0x07DF, 0x0FCB, 0x0FD0, 0x1FDB, - 0x1FE8, 0x7FF1, 0xFFFD, 0x3FEE, 0x3FEB, 0x3FE1, 0x1FD7, 0x0FD7, - 0x0FD5, 0x03CF, 0x0FD4, 0x0FDA, 0x1FD8, 0x3FE2, 0x3FE6, 0x3FEF, - 0xFFFF, 0x006A, -}; - -static const uint16_t clv_mvu_1_syms[] = { - 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, 0xFFF9, 0x00F9, - 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, 0x07F9, 0xF9FA, - 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, - 0x02FA, 0x03FA, 0x04FA, 0x05FA, 0x06FA, 0x07FA, 0xF9FB, 0xFAFB, - 0xFBFB, 0xFCFB, 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, - 0x03FB, 0x04FB, 0x05FB, 0x06FB, 0x07FB, 0xF9FC, 0xFAFC, 0xFBFC, - 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, 0x00FC, 0x01FC, 0x02FC, 0x03FC, - 0x04FC, 0x05FC, 0x06FC, 0x07FC, 0xF9FD, 0xFAFD, 0xFBFD, 0xFCFD, - 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, 0x03FD, 0x04FD, - 0x05FD, 0x06FD, 0x07FD, 0xF9FE, 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, - 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, 0x02FE, 0x03FE, 0x04FE, 0x05FE, - 0x06FE, 0x07FE, 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, - 0xFFFF, 0x00FF, 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, - 0x07FF, 0xF900, 0xFA00, 0xFB00, 0xFC00, 0xFD00, 0xFE00, 0xFF00, - 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, - 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, 0xFF01, 0x0001, - 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, 0x0701, 0xF902, - 0xFA02, 0xFB02, 0xFC02, 0xFD02, 0xFE02, 0xFF02, 0x0002, 0x0102, - 0x0202, 0x0302, 0x0402, 0x0502, 0x0602, 0x0702, 0xF903, 0xFA03, - 0xFB03, 0xFC03, 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, - 0x0303, 0x0403, 0x0503, 0x0603, 0x0703, 0xF904, 0xFA04, 0xFB04, - 0xFC04, 0xFD04, 0xFE04, 0xFF04, 0x0004, 0x0104, 0x0204, 0x0304, - 0x0404, 0x0504, 0x0604, 0x0704, 0xF905, 0xFA05, 0xFB05, 0xFC05, - 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, 0x0305, 0x0405, - 0x0505, 0x0605, 0x0705, 0xF906, 0xFA06, 0xFB06, 0xFC06, 0xFD06, - 0xFE06, 0xFF06, 0x0006, 0x0106, 0x0206, 0x0306, 0x0406, 0x0506, - 0x0606, 0x0706, 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, - 0xFF07, 0x0007, 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, - 0x0707, 0x0808, -}; - -static const uint8_t clv_mvu_2_bits[] = { - 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 15, 15, - 15, 15, 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, - 13, 14, 14, 14, 14, 14, 15, 15, 15, 16, 16, 15, 15, 14, 14, 14, - 14, 14, 14, 13, 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 16, 16, - 15, 15, 14, 13, 13, 13, 13, 13, 12, 12, 12, 13, 13, 13, 13, 13, - 14, 15, 15, 16, 14, 14, 14, 14, 13, 12, 12, 12, 12, 11, 10, 11, - 12, 12, 12, 12, 13, 14, 14, 14, 14, 14, 14, 14, 13, 12, 12, 12, - 12, 11, 10, 9, 10, 11, 12, 12, 12, 12, 13, 14, 14, 14, 15, 14, - 13, 13, 12, 12, 12, 12, 11, 10, 8, 10, 11, 12, 12, 12, 12, 13, - 13, 14, 15, 14, 14, 14, 13, 12, 12, 11, 11, 10, 9, 7, 9, 10, - 11, 11, 12, 12, 13, 14, 14, 14, 14, 14, 13, 12, 12, 11, 11, 10, - 9, 8, 7, 8, 9, 10, 11, 11, 12, 12, 13, 14, 14, 14, 13, 13, - 12, 11, 9, 9, 8, 7, 6, 5, 6, 7, 8, 9, 9, 11, 12, 13, - 13, 14, 14, 13, 13, 13, 11, 11, 10, 8, 7, 4, 1, 4, 7, 8, - 10, 11, 11, 13, 13, 13, 14, 14, 13, 13, 12, 11, 9, 9, 8, 7, - 6, 5, 6, 7, 8, 9, 9, 11, 12, 13, 13, 14, 14, 14, 13, 12, - 11, 11, 11, 9, 9, 8, 7, 8, 9, 10, 11, 11, 12, 12, 13, 14, - 14, 14, 14, 14, 13, 12, 12, 11, 11, 10, 9, 7, 9, 10, 11, 11, - 12, 12, 13, 14, 14, 14, 15, 14, 13, 13, 12, 12, 12, 12, 11, 10, - 9, 10, 11, 12, 12, 12, 12, 13, 13, 14, 15, 14, 14, 14, 13, 12, - 12, 12, 12, 11, 10, 8, 10, 11, 12, 12, 12, 12, 13, 14, 14, 14, - 14, 14, 14, 14, 13, 12, 12, 12, 12, 11, 10, 11, 12, 12, 12, 12, - 13, 14, 14, 14, 14, 16, 15, 15, 14, 13, 13, 13, 13, 13, 12, 12, - 12, 13, 13, 13, 13, 13, 14, 15, 15, 16, 16, 15, 15, 14, 14, 14, - 14, 14, 14, 13, 12, 13, 14, 14, 14, 14, 14, 14, 15, 15, 16, 16, - 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, 14, 14, 14, 14, 14, - 15, 15, 15, 16, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, - 14, 14, 15, 15, 15, 15, 16, 16, 16, 6, -}; - -static const uint16_t clv_mvu_2_codes[] = { - 0xFFF2, 0xFFEF, 0xFFEA, 0x7FEC, 0x7FD5, 0x7FC5, 0x7FCF, 0x3FD3, - 0x3FC9, 0x3FB4, 0x3F72, 0x3FAE, 0x3FDC, 0x3FE1, 0x7FC4, 0x7FC8, - 0x7FD7, 0x7FF0, 0xFFE9, 0xFFEC, 0xFFF8, 0xFFF4, 0x7FF3, 0x7FDE, - 0x7FD3, 0x3FC0, 0x3F99, 0x3FA8, 0x3FAC, 0x3F8E, 0x1FA8, 0x1F79, - 0x1FA2, 0x3F89, 0x3F93, 0x3F95, 0x3F9C, 0x3FB8, 0x7FD2, 0x7FE6, - 0x7FDA, 0xFFF7, 0xFFFE, 0x7FED, 0x7FE2, 0x3FD5, 0x3FD7, 0x3FB3, - 0x3FA2, 0x3F80, 0x3F7A, 0x1F88, 0x1F70, 0x1F8A, 0x3F83, 0x3F84, - 0x3FAA, 0x3FC4, 0x3FDA, 0x3FDF, 0x7FDB, 0x7FE3, 0xFFF1, 0xFFFB, - 0x7FE1, 0x7FC7, 0x3FB0, 0x1FAA, 0x1FAB, 0x1FA3, 0x1F8E, 0x1F81, - 0x0FA7, 0x0F7F, 0x0FA8, 0x1F82, 0x1F8F, 0x1FA4, 0x1FAC, 0x1FAD, - 0x3FB5, 0x7FC6, 0x7FDD, 0xFFF3, 0x3FDD, 0x3FBE, 0x3FB9, 0x3F7C, - 0x1F77, 0x0FB5, 0x0F9D, 0x0F99, 0x0F90, 0x0794, 0x03BE, 0x0795, - 0x0F92, 0x0F9A, 0x0F9E, 0x0FB6, 0x1F78, 0x3F78, 0x3FB2, 0x3FBF, - 0x3FD2, 0x3FA7, 0x3F8C, 0x3F75, 0x1F9E, 0x0F93, 0x0F94, 0x0F7B, - 0x0F73, 0x07B4, 0x03BB, 0x01D9, 0x03BC, 0x07B5, 0x0F74, 0x0F7C, - 0x0F95, 0x0F96, 0x1FA0, 0x3F76, 0x3F8F, 0x3FA5, 0x7FE5, 0x3FC7, - 0x1F95, 0x1F71, 0x0FAB, 0x0FAC, 0x0F9F, 0x0F7D, 0x0796, 0x03BF, - 0x00DE, 0x03C0, 0x0797, 0x0F7E, 0x0FA0, 0x0FAD, 0x0FAE, 0x1F72, - 0x1F97, 0x3FD1, 0x7FD8, 0x3FA9, 0x3FA0, 0x3F6D, 0x1F99, 0x0F87, - 0x0F77, 0x07A8, 0x079C, 0x03C5, 0x01CA, 0x0067, 0x01CB, 0x03C6, - 0x079D, 0x07A9, 0x0F78, 0x0F8A, 0x1F9F, 0x3F6E, 0x3F98, 0x3F9A, - 0x3FCA, 0x3F70, 0x1FAF, 0x0F8D, 0x0F6F, 0x07AC, 0x07A0, 0x03B7, - 0x01CE, 0x00DA, 0x0063, 0x00DB, 0x01CF, 0x03B8, 0x07A1, 0x07AD, - 0x0F70, 0x0F91, 0x1FB2, 0x3F73, 0x3FD6, 0x3F7D, 0x1F91, 0x1F85, - 0x0FA3, 0x07A2, 0x01D4, 0x01D0, 0x00E0, 0x0068, 0x002C, 0x0014, - 0x002D, 0x0069, 0x00E1, 0x01D1, 0x01D5, 0x07A3, 0x0FA4, 0x1F89, - 0x1F92, 0x3F81, 0x3FA6, 0x1F7B, 0x1F7C, 0x1F7D, 0x07B0, 0x07AE, - 0x03C7, 0x00DC, 0x0064, 0x0008, 0x0000, 0x0009, 0x0065, 0x00DD, - 0x03C8, 0x07AF, 0x07B1, 0x1F7E, 0x1F7F, 0x1F80, 0x3F9E, 0x3F85, - 0x1F93, 0x1F8B, 0x0FA5, 0x07A4, 0x01D6, 0x01D2, 0x00E2, 0x006A, - 0x002E, 0x0015, 0x002F, 0x006B, 0x00E3, 0x01D3, 0x01D7, 0x07A5, - 0x0FA6, 0x1F8C, 0x1F94, 0x3F87, 0x3FCE, 0x3F77, 0x1FB4, 0x0F83, - 0x07B6, 0x07AA, 0x079E, 0x01DA, 0x01CC, 0x00D8, 0x0062, 0x00D9, - 0x01CD, 0x03B6, 0x079F, 0x07AB, 0x0F6E, 0x0F84, 0x1FA9, 0x3F6A, - 0x3FCD, 0x3F90, 0x3F92, 0x3F6B, 0x1F96, 0x0F85, 0x0F75, 0x07A6, - 0x079A, 0x03C3, 0x01C8, 0x0066, 0x01C9, 0x03C4, 0x079B, 0x07A7, - 0x0F76, 0x0F86, 0x1F9D, 0x3F6C, 0x3F96, 0x3F97, 0x7FE9, 0x3FD8, - 0x1F98, 0x1F73, 0x0FAF, 0x0FB0, 0x0FA1, 0x0F80, 0x0798, 0x03C1, - 0x01D8, 0x03C2, 0x0799, 0x0F81, 0x0FA2, 0x0FB1, 0x0FB2, 0x1F74, - 0x1F9A, 0x3FE0, 0x7FEE, 0x3F94, 0x3F8B, 0x3F6F, 0x1F9B, 0x0F88, - 0x0F89, 0x0F79, 0x0F71, 0x07B2, 0x03B9, 0x00DF, 0x03BA, 0x07B3, - 0x0F72, 0x0F7A, 0x0F8B, 0x0F8C, 0x1F9C, 0x3F71, 0x3F8A, 0x3F9B, - 0x3FC8, 0x3FBD, 0x3FC5, 0x3F79, 0x1F75, 0x0FB3, 0x0F9C, 0x0F97, - 0x0F8E, 0x0792, 0x03BD, 0x0793, 0x0F8F, 0x0F98, 0x0F9B, 0x0FB4, - 0x1F76, 0x3F82, 0x3FC3, 0x3FBA, 0x3FC6, 0xFFFD, 0x7FDF, 0x7FCC, - 0x3FBB, 0x1FB0, 0x1FAE, 0x1FA1, 0x1F90, 0x1F83, 0x0FAA, 0x0F82, - 0x0FA9, 0x1F84, 0x1F8D, 0x1FA5, 0x1FB1, 0x1FB3, 0x3FC2, 0x7FCA, - 0x7FE8, 0xFFF5, 0xFFFF, 0x7FDC, 0x7FD9, 0x3FCC, 0x3FD9, 0x3FB7, - 0x3F9F, 0x3F7E, 0x3F86, 0x1F86, 0x0FB7, 0x1F87, 0x3F7B, 0x3F7F, - 0x3FA1, 0x3FBC, 0x3FCB, 0x3FD4, 0x7FF1, 0x7FF2, 0xFFFA, 0xFFFC, - 0x7FE4, 0x7FE7, 0x7FD4, 0x3FAF, 0x3FA3, 0x3F91, 0x3F9D, 0x3F88, - 0x1FA6, 0x1F7A, 0x1FA7, 0x3F8D, 0x3FAB, 0x3FAD, 0x3FA4, 0x3FB6, - 0x7FD0, 0x7FE0, 0x7FEB, 0xFFF0, 0xFFF9, 0xFFEB, 0xFFED, 0x7FEA, - 0x7FD6, 0x7FC9, 0x7FCB, 0x3FD0, 0x3FDE, 0x3FB1, 0x3F74, 0x3FC1, - 0x3FCF, 0x3FDB, 0x7FCD, 0x7FCE, 0x7FD1, 0x7FEF, 0xFFE8, 0xFFEE, - 0xFFF6, 0x0030, -}; - -static const uint16_t clv_mvu_2_syms[] = { - 0xF6F6, 0xF7F6, 0xF8F6, 0xF9F6, 0xFAF6, 0xFBF6, 0xFCF6, 0xFDF6, - 0xFEF6, 0xFFF6, 0x00F6, 0x01F6, 0x02F6, 0x03F6, 0x04F6, 0x05F6, - 0x06F6, 0x07F6, 0x08F6, 0x09F6, 0x0AF6, 0xF6F7, 0xF7F7, 0xF8F7, - 0xF9F7, 0xFAF7, 0xFBF7, 0xFCF7, 0xFDF7, 0xFEF7, 0xFFF7, 0x00F7, - 0x01F7, 0x02F7, 0x03F7, 0x04F7, 0x05F7, 0x06F7, 0x07F7, 0x08F7, - 0x09F7, 0x0AF7, 0xF6F8, 0xF7F8, 0xF8F8, 0xF9F8, 0xFAF8, 0xFBF8, - 0xFCF8, 0xFDF8, 0xFEF8, 0xFFF8, 0x00F8, 0x01F8, 0x02F8, 0x03F8, - 0x04F8, 0x05F8, 0x06F8, 0x07F8, 0x08F8, 0x09F8, 0x0AF8, 0xF6F9, - 0xF7F9, 0xF8F9, 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, - 0xFFF9, 0x00F9, 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, - 0x07F9, 0x08F9, 0x09F9, 0x0AF9, 0xF6FA, 0xF7FA, 0xF8FA, 0xF9FA, - 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, - 0x02FA, 0x03FA, 0x04FA, 0x05FA, 0x06FA, 0x07FA, 0x08FA, 0x09FA, - 0x0AFA, 0xF6FB, 0xF7FB, 0xF8FB, 0xF9FB, 0xFAFB, 0xFBFB, 0xFCFB, - 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, 0x03FB, 0x04FB, - 0x05FB, 0x06FB, 0x07FB, 0x08FB, 0x09FB, 0x0AFB, 0xF6FC, 0xF7FC, - 0xF8FC, 0xF9FC, 0xFAFC, 0xFBFC, 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, - 0x00FC, 0x01FC, 0x02FC, 0x03FC, 0x04FC, 0x05FC, 0x06FC, 0x07FC, - 0x08FC, 0x09FC, 0x0AFC, 0xF6FD, 0xF7FD, 0xF8FD, 0xF9FD, 0xFAFD, - 0xFBFD, 0xFCFD, 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, - 0x03FD, 0x04FD, 0x05FD, 0x06FD, 0x07FD, 0x08FD, 0x09FD, 0x0AFD, - 0xF6FE, 0xF7FE, 0xF8FE, 0xF9FE, 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, - 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, 0x02FE, 0x03FE, 0x04FE, 0x05FE, - 0x06FE, 0x07FE, 0x08FE, 0x09FE, 0x0AFE, 0xF6FF, 0xF7FF, 0xF8FF, - 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, 0xFFFF, 0x00FF, - 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, 0x07FF, 0x08FF, - 0x09FF, 0x0AFF, 0xF600, 0xF700, 0xF800, 0xF900, 0xFA00, 0xFB00, - 0xFC00, 0xFD00, 0xFE00, 0xFF00, 0x0000, 0x0100, 0x0200, 0x0300, - 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0xF601, - 0xF701, 0xF801, 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, - 0xFF01, 0x0001, 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, - 0x0701, 0x0801, 0x0901, 0x0A01, 0xF602, 0xF702, 0xF802, 0xF902, - 0xFA02, 0xFB02, 0xFC02, 0xFD02, 0xFE02, 0xFF02, 0x0002, 0x0102, - 0x0202, 0x0302, 0x0402, 0x0502, 0x0602, 0x0702, 0x0802, 0x0902, - 0x0A02, 0xF603, 0xF703, 0xF803, 0xF903, 0xFA03, 0xFB03, 0xFC03, - 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, 0x0303, 0x0403, - 0x0503, 0x0603, 0x0703, 0x0803, 0x0903, 0x0A03, 0xF604, 0xF704, - 0xF804, 0xF904, 0xFA04, 0xFB04, 0xFC04, 0xFD04, 0xFE04, 0xFF04, - 0x0004, 0x0104, 0x0204, 0x0304, 0x0404, 0x0504, 0x0604, 0x0704, - 0x0804, 0x0904, 0x0A04, 0xF605, 0xF705, 0xF805, 0xF905, 0xFA05, - 0xFB05, 0xFC05, 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, - 0x0305, 0x0405, 0x0505, 0x0605, 0x0705, 0x0805, 0x0905, 0x0A05, - 0xF606, 0xF706, 0xF806, 0xF906, 0xFA06, 0xFB06, 0xFC06, 0xFD06, - 0xFE06, 0xFF06, 0x0006, 0x0106, 0x0206, 0x0306, 0x0406, 0x0506, - 0x0606, 0x0706, 0x0806, 0x0906, 0x0A06, 0xF607, 0xF707, 0xF807, - 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, 0xFF07, 0x0007, - 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, 0x0707, 0x0807, - 0x0907, 0x0A07, 0xF608, 0xF708, 0xF808, 0xF908, 0xFA08, 0xFB08, - 0xFC08, 0xFD08, 0xFE08, 0xFF08, 0x0008, 0x0108, 0x0208, 0x0308, - 0x0408, 0x0508, 0x0608, 0x0708, 0x0808, 0x0908, 0x0A08, 0xF609, - 0xF709, 0xF809, 0xF909, 0xFA09, 0xFB09, 0xFC09, 0xFD09, 0xFE09, - 0xFF09, 0x0009, 0x0109, 0x0209, 0x0309, 0x0409, 0x0509, 0x0609, - 0x0709, 0x0809, 0x0909, 0x0A09, 0xF60A, 0xF70A, 0xF80A, 0xF90A, - 0xFA0A, 0xFB0A, 0xFC0A, 0xFD0A, 0xFE0A, 0xFF0A, 0x000A, 0x010A, - 0x020A, 0x030A, 0x040A, 0x050A, 0x060A, 0x070A, 0x080A, 0x090A, - 0x0A0A, 0x0B0B, -}; - -static const uint8_t clv_mvv_1_bits[] = { - 16, 15, 13, 13, 13, 12, 10, 10, 10, 12, 13, 13, 13, 15, 16, 16, - 15, 14, 13, 12, 11, 10, 9, 10, 11, 12, 13, 14, 15, 16, 15, 14, - 13, 13, 11, 10, 10, 5, 10, 10, 11, 13, 13, 14, 15, 12, 12, 12, - 11, 10, 10, 9, 5, 9, 10, 10, 11, 12, 12, 12, 14, 12, 12, 12, - 11, 9, 8, 5, 8, 9, 11, 12, 12, 12, 14, 14, 11, 11, 9, 9, - 9, 7, 5, 7, 9, 9, 9, 11, 11, 14, 13, 12, 11, 10, 10, 8, - 6, 3, 6, 8, 10, 10, 11, 12, 13, 11, 10, 9, 7, 6, 6, 4, - 4, 4, 6, 7, 7, 10, 10, 11, 13, 12, 11, 10, 10, 8, 6, 3, - 6, 8, 10, 10, 11, 12, 13, 14, 11, 11, 9, 9, 9, 7, 5, 7, - 9, 9, 9, 11, 11, 14, 14, 12, 12, 12, 11, 9, 8, 5, 8, 9, - 11, 12, 12, 12, 14, 12, 12, 12, 11, 10, 10, 9, 5, 9, 10, 10, - 11, 12, 12, 12, 15, 14, 13, 13, 11, 10, 10, 5, 10, 10, 11, 13, - 13, 14, 15, 16, 15, 14, 13, 12, 11, 10, 9, 10, 11, 12, 13, 14, - 15, 16, 16, 15, 13, 13, 13, 12, 10, 10, 10, 12, 13, 13, 13, 15, - 16, 7, -}; - -static const uint16_t clv_mvv_1_codes[] = { - 0xFFFD, 0x7FF8, 0x1FF2, 0x1FDC, 0x1FDB, 0x0FD2, 0x03D6, 0x03BF, - 0x03D3, 0x0FD0, 0x1FDA, 0x1FDE, 0x1FF0, 0x7FF9, 0xFFFE, 0xFFFA, - 0x7FFB, 0x3FF3, 0x1FE9, 0x0FD6, 0x07CB, 0x03E1, 0x01C8, 0x03E2, - 0x07CC, 0x0FD9, 0x1FE8, 0x3FF6, 0x7FFA, 0xFFF9, 0x7FF1, 0x3FEE, - 0x1FE4, 0x1FE0, 0x07D4, 0x03DB, 0x03CB, 0x0014, 0x03CC, 0x03DC, - 0x07D6, 0x1FE3, 0x1FE7, 0x3FEC, 0x7FF3, 0x0FEA, 0x0FE0, 0x0FDE, - 0x07DE, 0x03C9, 0x03C3, 0x01DC, 0x0013, 0x01DD, 0x03C4, 0x03CA, - 0x07DF, 0x0FDF, 0x0FE3, 0x0FEB, 0x3FF1, 0x0FE7, 0x0FCF, 0x0FC8, - 0x07D8, 0x01D2, 0x00E0, 0x0010, 0x00E1, 0x01D4, 0x07D9, 0x0FC9, - 0x0FCC, 0x0FE6, 0x3FF5, 0x3FEA, 0x07E2, 0x07D2, 0x01D7, 0x01D0, - 0x01CC, 0x006A, 0x000F, 0x006B, 0x01CD, 0x01D1, 0x01D9, 0x07D3, - 0x07E3, 0x3FEB, 0x1FEE, 0x0FD5, 0x07C7, 0x03D8, 0x03D0, 0x00DD, - 0x002D, 0x0001, 0x002E, 0x00DE, 0x03D1, 0x03D9, 0x07C8, 0x0FD8, - 0x1FEF, 0x07CE, 0x03C5, 0x01DE, 0x006C, 0x0032, 0x0030, 0x0005, - 0x0004, 0x0006, 0x0031, 0x0066, 0x006D, 0x03BE, 0x03C6, 0x07CF, - 0x1FEC, 0x0FDA, 0x07C9, 0x03DA, 0x03D2, 0x00DF, 0x002F, 0x0000, - 0x002C, 0x00DC, 0x03CF, 0x03D7, 0x07C6, 0x0FD4, 0x1FED, 0x3FE9, - 0x07E0, 0x07D0, 0x01D3, 0x01CE, 0x01CA, 0x0068, 0x000E, 0x0069, - 0x01CB, 0x01CF, 0x01D5, 0x07D1, 0x07E1, 0x3FE8, 0x3FF4, 0x0FE4, - 0x0FCD, 0x0FCB, 0x07DA, 0x01D6, 0x00E2, 0x0011, 0x00E3, 0x01D8, - 0x07DB, 0x0FCA, 0x0FCE, 0x0FE5, 0x3FF7, 0x0FE8, 0x0FE1, 0x0FDD, - 0x07DD, 0x03C7, 0x03C1, 0x01DA, 0x0012, 0x01DB, 0x03C2, 0x03C8, - 0x07DC, 0x0FDC, 0x0FE2, 0x0FE9, 0x7FF0, 0x3FEF, 0x1FE5, 0x1FE1, - 0x07D7, 0x03DD, 0x03CD, 0x0015, 0x03CE, 0x03DE, 0x07D5, 0x1FE2, - 0x1FE6, 0x3FED, 0x7FF2, 0xFFF8, 0x7FF4, 0x3FF2, 0x1FEB, 0x0FD7, - 0x07CD, 0x03DF, 0x01C9, 0x03E0, 0x07CA, 0x0FDB, 0x1FEA, 0x3FF0, - 0x7FF5, 0xFFFB, 0xFFFC, 0x7FF6, 0x1FF3, 0x1FDD, 0x1FD9, 0x0FD1, - 0x03D5, 0x03C0, 0x03D4, 0x0FD3, 0x1FD8, 0x1FDF, 0x1FF1, 0x7FF7, - 0xFFFF, 0x0067, -}; - -static const uint16_t clv_mvv_1_syms[] = { - 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, 0xFFF9, 0x00F9, - 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, 0x07F9, 0xF9FA, - 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, - 0x02FA, 0x03FA, 0x04FA, 0x05FA, 0x06FA, 0x07FA, 0xF9FB, 0xFAFB, - 0xFBFB, 0xFCFB, 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, - 0x03FB, 0x04FB, 0x05FB, 0x06FB, 0x07FB, 0xF9FC, 0xFAFC, 0xFBFC, - 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, 0x00FC, 0x01FC, 0x02FC, 0x03FC, - 0x04FC, 0x05FC, 0x06FC, 0x07FC, 0xF9FD, 0xFAFD, 0xFBFD, 0xFCFD, - 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, 0x03FD, 0x04FD, - 0x05FD, 0x06FD, 0x07FD, 0xF9FE, 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, - 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, 0x02FE, 0x03FE, 0x04FE, 0x05FE, - 0x06FE, 0x07FE, 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, - 0xFFFF, 0x00FF, 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, - 0x07FF, 0xF900, 0xFA00, 0xFB00, 0xFC00, 0xFD00, 0xFE00, 0xFF00, - 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, - 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, 0xFF01, 0x0001, - 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, 0x0701, 0xF902, - 0xFA02, 0xFB02, 0xFC02, 0xFD02, 0xFE02, 0xFF02, 0x0002, 0x0102, - 0x0202, 0x0302, 0x0402, 0x0502, 0x0602, 0x0702, 0xF903, 0xFA03, - 0xFB03, 0xFC03, 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, - 0x0303, 0x0403, 0x0503, 0x0603, 0x0703, 0xF904, 0xFA04, 0xFB04, - 0xFC04, 0xFD04, 0xFE04, 0xFF04, 0x0004, 0x0104, 0x0204, 0x0304, - 0x0404, 0x0504, 0x0604, 0x0704, 0xF905, 0xFA05, 0xFB05, 0xFC05, - 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, 0x0305, 0x0405, - 0x0505, 0x0605, 0x0705, 0xF906, 0xFA06, 0xFB06, 0xFC06, 0xFD06, - 0xFE06, 0xFF06, 0x0006, 0x0106, 0x0206, 0x0306, 0x0406, 0x0506, - 0x0606, 0x0706, 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, - 0xFF07, 0x0007, 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, - 0x0707, 0x0808, -}; - -static const uint8_t clv_mvv_2_bits[] = { - 16, 15, 15, 15, 15, 15, 14, 14, 14, 13, 12, 13, 14, 14, 14, 15, - 15, 15, 15, 15, 16, 16, 16, 16, 15, 15, 14, 14, 14, 13, 13, 12, - 12, 13, 14, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 14, 14, 14, - 14, 14, 14, 13, 13, 13, 14, 14, 14, 14, 14, 14, 16, 16, 16, 15, - 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 13, 13, 13, 13, 14, - 14, 14, 15, 15, 16, 14, 14, 14, 13, 12, 12, 12, 10, 10, 10, 10, - 10, 12, 12, 12, 13, 14, 14, 14, 16, 14, 14, 14, 13, 13, 12, 12, - 12, 10, 10, 7, 10, 10, 12, 12, 12, 13, 13, 14, 14, 14, 14, 14, - 13, 12, 12, 12, 12, 10, 9, 8, 7, 8, 9, 10, 12, 12, 12, 12, - 13, 14, 14, 14, 14, 13, 12, 12, 12, 12, 10, 9, 8, 7, 8, 9, - 10, 12, 12, 12, 12, 13, 14, 14, 14, 14, 13, 13, 12, 12, 11, 10, - 9, 8, 7, 8, 9, 10, 11, 12, 12, 13, 13, 14, 14, 14, 13, 13, - 12, 10, 10, 9, 8, 7, 6, 5, 6, 7, 8, 9, 10, 10, 12, 13, - 13, 14, 13, 13, 13, 13, 11, 10, 9, 8, 7, 5, 1, 5, 7, 8, - 9, 10, 11, 13, 13, 13, 13, 14, 13, 13, 12, 10, 10, 9, 8, 7, - 6, 5, 6, 7, 8, 9, 10, 10, 12, 13, 13, 14, 14, 14, 13, 13, - 12, 12, 11, 9, 9, 8, 7, 8, 9, 9, 11, 12, 12, 13, 13, 14, - 14, 14, 14, 13, 12, 12, 12, 12, 10, 9, 8, 7, 8, 9, 10, 12, - 12, 12, 12, 13, 14, 14, 14, 14, 13, 12, 12, 12, 12, 10, 9, 8, - 7, 8, 9, 10, 12, 12, 12, 12, 13, 14, 14, 14, 14, 14, 13, 13, - 12, 12, 12, 10, 10, 7, 10, 10, 12, 12, 12, 13, 13, 14, 14, 14, - 16, 14, 14, 14, 13, 12, 12, 12, 10, 10, 10, 10, 10, 12, 12, 12, - 13, 14, 14, 14, 16, 15, 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, - 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, 16, 14, 14, 14, - 14, 14, 14, 13, 13, 13, 14, 14, 14, 14, 14, 14, 16, 16, 16, 16, - 16, 16, 15, 15, 14, 14, 14, 13, 12, 12, 12, 13, 14, 14, 14, 15, - 15, 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 13, 10, 13, - 14, 14, 14, 15, 15, 15, 15, 15, 16, 6, -}; - -static const uint16_t clv_mvv_2_codes[] = { - 0xFFFF, 0x7FE7, 0x7FD9, 0x7FE6, 0x7FE5, 0x7FCE, 0x3FD6, 0x3FD3, - 0x3F9C, 0x1FB2, 0x0F7A, 0x1FB5, 0x3FA8, 0x3FDD, 0x3FE5, 0x7FD0, - 0x7FEA, 0x7FEC, 0x7FEF, 0x7FDB, 0xFFF3, 0xFFF5, 0xFFE2, 0xFFEB, - 0x7FEB, 0x7FE0, 0x3FA7, 0x3F84, 0x3F79, 0x1FAE, 0x1F70, 0x0F78, - 0x0FAA, 0x1FAA, 0x3F76, 0x3F7E, 0x3FAC, 0x7FE1, 0x7FDD, 0xFFEC, - 0xFFEE, 0xFFF8, 0xFFF9, 0xFFEA, 0xFFE4, 0x3FE1, 0x3FBA, 0x3FC5, - 0x3FB9, 0x3FA1, 0x3FAA, 0x1F8B, 0x1F8D, 0x1F8E, 0x3FA6, 0x3FA9, - 0x3FC4, 0x3FBC, 0x3FC6, 0x3FDB, 0xFFE3, 0xFFE1, 0xFFFB, 0x7FD4, - 0x7FCC, 0x3FCD, 0x3F88, 0x3F7C, 0x1FA1, 0x1FA2, 0x1F95, 0x1F77, - 0x0F95, 0x0F79, 0x0F97, 0x1F78, 0x1F96, 0x1FA3, 0x1FA4, 0x3F7F, - 0x3F8B, 0x3FCB, 0x7FCF, 0x7FD5, 0xFFF6, 0x3FD7, 0x3FE0, 0x3F91, - 0x1F7B, 0x0FB4, 0x0FA5, 0x0FA6, 0x03D5, 0x03CB, 0x03BF, 0x03CC, - 0x03D6, 0x0FA7, 0x0FA8, 0x0FB5, 0x1F7D, 0x3F87, 0x3FD2, 0x3FDF, - 0xFFF0, 0x3F95, 0x3F8A, 0x3F96, 0x1FB7, 0x1F9F, 0x0F9F, 0x0F8F, - 0x0F76, 0x03D1, 0x03BC, 0x0067, 0x03BD, 0x03D2, 0x0F77, 0x0F90, - 0x0FA0, 0x1FA0, 0x1FB9, 0x3F97, 0x3F98, 0x3F99, 0x3FC3, 0x3FAF, - 0x1F81, 0x0FA9, 0x0F91, 0x0F7E, 0x0F68, 0x03B2, 0x01C6, 0x00D4, - 0x0062, 0x00D5, 0x01C7, 0x03B3, 0x0F6A, 0x0F81, 0x0F93, 0x0FAC, - 0x1F83, 0x3FB3, 0x3FB4, 0x3FC7, 0x3FBB, 0x1F86, 0x0FAF, 0x0F98, - 0x0F84, 0x0F6D, 0x03B8, 0x01CC, 0x00DA, 0x0065, 0x00DB, 0x01CD, - 0x03B9, 0x0F6F, 0x0F86, 0x0F9B, 0x0FB1, 0x1F88, 0x3FB8, 0x3FC9, - 0x3FDC, 0x3F80, 0x1FB3, 0x1F93, 0x0F87, 0x0F72, 0x07B0, 0x03B0, - 0x01D4, 0x00E0, 0x0061, 0x00E1, 0x01D5, 0x03B1, 0x07B1, 0x0F73, - 0x0F88, 0x1F94, 0x1FB4, 0x3F81, 0x3FD4, 0x3F9E, 0x1F99, 0x1F73, - 0x0F89, 0x03C4, 0x03C0, 0x01CE, 0x00D0, 0x005C, 0x0028, 0x0010, - 0x0029, 0x005D, 0x00D1, 0x01CF, 0x03C1, 0x03C5, 0x0F8A, 0x1F74, - 0x1F9A, 0x3FA4, 0x1FAC, 0x1F8C, 0x1F7E, 0x1F71, 0x07B2, 0x03CF, - 0x01C4, 0x00DC, 0x005A, 0x0012, 0x0000, 0x0013, 0x005B, 0x00DD, - 0x01C5, 0x03D0, 0x07B3, 0x1F72, 0x1F7F, 0x1F8F, 0x1FAD, 0x3FAB, - 0x1F9B, 0x1F75, 0x0F8B, 0x03C6, 0x03C2, 0x01D0, 0x00D2, 0x005E, - 0x002A, 0x0011, 0x002B, 0x005F, 0x00D3, 0x01D1, 0x03C3, 0x03C7, - 0x0F8C, 0x1F76, 0x1F9C, 0x3FAD, 0x3FCF, 0x3F85, 0x1FBA, 0x1F91, - 0x0F7D, 0x0F70, 0x07AE, 0x01D6, 0x01D2, 0x00DE, 0x0060, 0x00DF, - 0x01D3, 0x01D7, 0x07AF, 0x0F71, 0x0F7F, 0x1F92, 0x1FAF, 0x3F7B, - 0x3FD0, 0x3FC0, 0x3FB1, 0x1F82, 0x0FAB, 0x0F92, 0x0F80, 0x0F69, - 0x03B4, 0x01C8, 0x00D6, 0x0063, 0x00D7, 0x01C9, 0x03B5, 0x0F6B, - 0x0F82, 0x0F94, 0x0FAD, 0x1F84, 0x3FB5, 0x3FC2, 0x3FB6, 0x3FBF, - 0x1F85, 0x0FAE, 0x0F96, 0x0F83, 0x0F6C, 0x03B6, 0x01CA, 0x00D8, - 0x0064, 0x00D9, 0x01CB, 0x03B7, 0x0F6E, 0x0F85, 0x0F99, 0x0FB0, - 0x1F87, 0x3FB0, 0x3FB2, 0x3F93, 0x3F86, 0x3F8E, 0x1FB1, 0x1F9D, - 0x0F9A, 0x0F8D, 0x0F74, 0x03CD, 0x03BA, 0x0066, 0x03BB, 0x03CE, - 0x0F75, 0x0F8E, 0x0F9C, 0x1F9E, 0x1FB0, 0x3F8C, 0x3F94, 0x3F8D, - 0xFFFC, 0x3FCA, 0x3FD5, 0x3F8F, 0x1F79, 0x0FB2, 0x0FA1, 0x0FA2, - 0x03D3, 0x03C9, 0x03BE, 0x03CA, 0x03D4, 0x0FA3, 0x0FA4, 0x0FB3, - 0x1F7A, 0x3F90, 0x3FE3, 0x3FD8, 0xFFF2, 0x7FD7, 0x7FCD, 0x3FE4, - 0x3F92, 0x3F82, 0x1FA6, 0x1FA8, 0x1F98, 0x1F7C, 0x0F9D, 0x0F7B, - 0x0F9E, 0x1F80, 0x1F97, 0x1FA7, 0x1FA5, 0x3F7A, 0x3F89, 0x3FDA, - 0x7FD2, 0x7FD6, 0xFFFE, 0xFFED, 0xFFE8, 0x3FCC, 0x3FBD, 0x3FAE, - 0x3FC1, 0x3F9F, 0x3F9A, 0x1F89, 0x1F90, 0x1F8A, 0x3FA3, 0x3FA0, - 0x3FC8, 0x3FBE, 0x3FB7, 0x3FD1, 0xFFE7, 0xFFE9, 0xFFFD, 0xFFF4, - 0xFFE5, 0xFFEF, 0x7FD8, 0x7FDC, 0x3FA2, 0x3F83, 0x3F78, 0x1FA9, - 0x0FB6, 0x0F7C, 0x0FB7, 0x1FAB, 0x3F77, 0x3F7D, 0x3F9B, 0x7FDE, - 0x7FED, 0xFFE6, 0xFFE0, 0xFFF7, 0xFFF1, 0x7FDA, 0x7FE9, 0x7FE2, - 0x7FE3, 0x7FD1, 0x3FD9, 0x3FE2, 0x3FA5, 0x1FB8, 0x03C8, 0x1FB6, - 0x3F9D, 0x3FDE, 0x3FCE, 0x7FD3, 0x7FEE, 0x7FDF, 0x7FE8, 0x7FE4, - 0xFFFA, 0x002C, -}; - -static const uint16_t clv_mvv_2_syms[] = { - 0xF6F6, 0xF7F6, 0xF8F6, 0xF9F6, 0xFAF6, 0xFBF6, 0xFCF6, 0xFDF6, - 0xFEF6, 0xFFF6, 0x00F6, 0x01F6, 0x02F6, 0x03F6, 0x04F6, 0x05F6, - 0x06F6, 0x07F6, 0x08F6, 0x09F6, 0x0AF6, 0xF6F7, 0xF7F7, 0xF8F7, - 0xF9F7, 0xFAF7, 0xFBF7, 0xFCF7, 0xFDF7, 0xFEF7, 0xFFF7, 0x00F7, - 0x01F7, 0x02F7, 0x03F7, 0x04F7, 0x05F7, 0x06F7, 0x07F7, 0x08F7, - 0x09F7, 0x0AF7, 0xF6F8, 0xF7F8, 0xF8F8, 0xF9F8, 0xFAF8, 0xFBF8, - 0xFCF8, 0xFDF8, 0xFEF8, 0xFFF8, 0x00F8, 0x01F8, 0x02F8, 0x03F8, - 0x04F8, 0x05F8, 0x06F8, 0x07F8, 0x08F8, 0x09F8, 0x0AF8, 0xF6F9, - 0xF7F9, 0xF8F9, 0xF9F9, 0xFAF9, 0xFBF9, 0xFCF9, 0xFDF9, 0xFEF9, - 0xFFF9, 0x00F9, 0x01F9, 0x02F9, 0x03F9, 0x04F9, 0x05F9, 0x06F9, - 0x07F9, 0x08F9, 0x09F9, 0x0AF9, 0xF6FA, 0xF7FA, 0xF8FA, 0xF9FA, - 0xFAFA, 0xFBFA, 0xFCFA, 0xFDFA, 0xFEFA, 0xFFFA, 0x00FA, 0x01FA, - 0x02FA, 0x03FA, 0x04FA, 0x05FA, 0x06FA, 0x07FA, 0x08FA, 0x09FA, - 0x0AFA, 0xF6FB, 0xF7FB, 0xF8FB, 0xF9FB, 0xFAFB, 0xFBFB, 0xFCFB, - 0xFDFB, 0xFEFB, 0xFFFB, 0x00FB, 0x01FB, 0x02FB, 0x03FB, 0x04FB, - 0x05FB, 0x06FB, 0x07FB, 0x08FB, 0x09FB, 0x0AFB, 0xF6FC, 0xF7FC, - 0xF8FC, 0xF9FC, 0xFAFC, 0xFBFC, 0xFCFC, 0xFDFC, 0xFEFC, 0xFFFC, - 0x00FC, 0x01FC, 0x02FC, 0x03FC, 0x04FC, 0x05FC, 0x06FC, 0x07FC, - 0x08FC, 0x09FC, 0x0AFC, 0xF6FD, 0xF7FD, 0xF8FD, 0xF9FD, 0xFAFD, - 0xFBFD, 0xFCFD, 0xFDFD, 0xFEFD, 0xFFFD, 0x00FD, 0x01FD, 0x02FD, - 0x03FD, 0x04FD, 0x05FD, 0x06FD, 0x07FD, 0x08FD, 0x09FD, 0x0AFD, - 0xF6FE, 0xF7FE, 0xF8FE, 0xF9FE, 0xFAFE, 0xFBFE, 0xFCFE, 0xFDFE, - 0xFEFE, 0xFFFE, 0x00FE, 0x01FE, 0x02FE, 0x03FE, 0x04FE, 0x05FE, - 0x06FE, 0x07FE, 0x08FE, 0x09FE, 0x0AFE, 0xF6FF, 0xF7FF, 0xF8FF, - 0xF9FF, 0xFAFF, 0xFBFF, 0xFCFF, 0xFDFF, 0xFEFF, 0xFFFF, 0x00FF, - 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, 0x07FF, 0x08FF, - 0x09FF, 0x0AFF, 0xF600, 0xF700, 0xF800, 0xF900, 0xFA00, 0xFB00, - 0xFC00, 0xFD00, 0xFE00, 0xFF00, 0x0000, 0x0100, 0x0200, 0x0300, - 0x0400, 0x0500, 0x0600, 0x0700, 0x0800, 0x0900, 0x0A00, 0xF601, - 0xF701, 0xF801, 0xF901, 0xFA01, 0xFB01, 0xFC01, 0xFD01, 0xFE01, - 0xFF01, 0x0001, 0x0101, 0x0201, 0x0301, 0x0401, 0x0501, 0x0601, - 0x0701, 0x0801, 0x0901, 0x0A01, 0xF602, 0xF702, 0xF802, 0xF902, - 0xFA02, 0xFB02, 0xFC02, 0xFD02, 0xFE02, 0xFF02, 0x0002, 0x0102, - 0x0202, 0x0302, 0x0402, 0x0502, 0x0602, 0x0702, 0x0802, 0x0902, - 0x0A02, 0xF603, 0xF703, 0xF803, 0xF903, 0xFA03, 0xFB03, 0xFC03, - 0xFD03, 0xFE03, 0xFF03, 0x0003, 0x0103, 0x0203, 0x0303, 0x0403, - 0x0503, 0x0603, 0x0703, 0x0803, 0x0903, 0x0A03, 0xF604, 0xF704, - 0xF804, 0xF904, 0xFA04, 0xFB04, 0xFC04, 0xFD04, 0xFE04, 0xFF04, - 0x0004, 0x0104, 0x0204, 0x0304, 0x0404, 0x0504, 0x0604, 0x0704, - 0x0804, 0x0904, 0x0A04, 0xF605, 0xF705, 0xF805, 0xF905, 0xFA05, - 0xFB05, 0xFC05, 0xFD05, 0xFE05, 0xFF05, 0x0005, 0x0105, 0x0205, - 0x0305, 0x0405, 0x0505, 0x0605, 0x0705, 0x0805, 0x0905, 0x0A05, - 0xF606, 0xF706, 0xF806, 0xF906, 0xFA06, 0xFB06, 0xFC06, 0xFD06, - 0xFE06, 0xFF06, 0x0006, 0x0106, 0x0206, 0x0306, 0x0406, 0x0506, - 0x0606, 0x0706, 0x0806, 0x0906, 0x0A06, 0xF607, 0xF707, 0xF807, - 0xF907, 0xFA07, 0xFB07, 0xFC07, 0xFD07, 0xFE07, 0xFF07, 0x0007, - 0x0107, 0x0207, 0x0307, 0x0407, 0x0507, 0x0607, 0x0707, 0x0807, - 0x0907, 0x0A07, 0xF608, 0xF708, 0xF808, 0xF908, 0xFA08, 0xFB08, - 0xFC08, 0xFD08, 0xFE08, 0xFF08, 0x0008, 0x0108, 0x0208, 0x0308, - 0x0408, 0x0508, 0x0608, 0x0708, 0x0808, 0x0908, 0x0A08, 0xF609, - 0xF709, 0xF809, 0xF909, 0xFA09, 0xFB09, 0xFC09, 0xFD09, 0xFE09, - 0xFF09, 0x0009, 0x0109, 0x0209, 0x0309, 0x0409, 0x0509, 0x0609, - 0x0709, 0x0809, 0x0909, 0x0A09, 0xF60A, 0xF70A, 0xF80A, 0xF90A, - 0xFA0A, 0xFB0A, 0xFC0A, 0xFD0A, 0xFE0A, 0xFF0A, 0x000A, 0x010A, - 0x020A, 0x030A, 0x040A, 0x050A, 0x060A, 0x070A, 0x080A, 0x090A, - 0x0A0A, 0x0B0B, -}; - -static const uint8_t clv_biasy_1_bits[] = { - 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, - 13, 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, - 8, 8, 7, 7, 5, 2, 1, 3, 5, 7, 7, 8, 9, 9, 10, 10, - 10, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, - 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 16, 12, -}; - -static const uint16_t clv_biasy_1_codes[] = { - 0xFFFE, 0x7FFE, 0x7FFC, 0x7FFA, 0x7FF6, 0x7FF7, 0x7FF3, 0x7FF2, - 0x7FEF, 0x7FEE, 0x3FF5, 0x3FF3, 0x3FF1, 0x1FF7, 0x1FF5, 0x1FF2, - 0x1FF0, 0x1FEE, 0x1FEC, 0x1FEA, 0x1FE8, 0x0FF2, 0x0FF0, 0x0FEE, - 0x0FEB, 0x07F4, 0x07F3, 0x07F1, 0x03F7, 0x03F5, 0x03F3, 0x01F7, - 0x00FA, 0x00F8, 0x007A, 0x0078, 0x001C, 0x0002, 0x0000, 0x0006, - 0x001D, 0x0079, 0x007B, 0x00F9, 0x01F6, 0x01F8, 0x03F2, 0x03F4, - 0x03F6, 0x07F0, 0x07F2, 0x0FEA, 0x0FEC, 0x0FEF, 0x0FF1, 0x0FF3, - 0x1FE9, 0x1FEB, 0x1FED, 0x1FEF, 0x1FF1, 0x1FF3, 0x1FF4, 0x1FF6, - 0x3FF0, 0x3FF2, 0x3FF4, 0x3FF6, 0x7FF0, 0x7FF1, 0x7FF4, 0x7FF8, - 0x7FF5, 0x7FF9, 0x7FFB, 0x7FFD, 0xFFFF, 0x0FED, -}; - -static const uint16_t clv_biasy_1_syms[] = { - 0xFF68, 0xFF6C, 0xFF70, 0xFF74, 0xFF78, 0xFF7C, 0xFF80, 0xFF84, - 0xFF88, 0xFF8C, 0xFF90, 0xFF94, 0xFF98, 0xFF9C, 0xFFA0, 0xFFA4, - 0xFFA8, 0xFFAC, 0xFFB0, 0xFFB4, 0xFFB8, 0xFFBC, 0xFFC0, 0xFFC4, - 0xFFC8, 0xFFCC, 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDC, 0xFFE0, 0xFFE4, - 0xFFE8, 0xFFEC, 0xFFF0, 0xFFF4, 0xFFF8, 0xFFFC, 0x0000, 0x0004, - 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, 0x0020, 0x0024, - 0x0028, 0x002C, 0x0030, 0x0034, 0x0038, 0x003C, 0x0040, 0x0044, - 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, 0x0060, 0x0064, - 0x0068, 0x006C, 0x0070, 0x0074, 0x0078, 0x007C, 0x0080, 0x0084, - 0x0088, 0x008C, 0x0090, 0x0094, 0x0098, 0x0100, -}; - -static const uint8_t clv_biasy_2_bits[] = { - 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 14, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 12, 12, 11, - 11, 11, 10, 10, 10, 10, 9, 9, 8, 8, 8, 7, 6, 6, 4, 3, - 1, 3, 4, 6, 6, 7, 8, 8, 8, 9, 9, 10, 10, 10, 10, 11, - 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, - 16, 15, -}; - -static const uint16_t clv_biasy_2_codes[] = { - 0xFFFE, 0xFFFC, 0xFFFA, 0xFFF9, 0xFFF6, 0xFFF5, 0xFFF3, 0x7FF7, - 0x7FF5, 0x7FF1, 0x7FF3, 0x7FF0, 0x7FEE, 0x7FEC, 0x7FE9, 0x7FE6, - 0x7FE4, 0x7FE2, 0x3FEF, 0x3FEE, 0x3FEC, 0x3FEA, 0x1FF2, 0x1FF1, - 0x1FEF, 0x1FED, 0x0FF4, 0x0FF3, 0x0FF1, 0x0FEF, 0x0FED, 0x07F4, - 0x07F3, 0x07F1, 0x03F6, 0x03F4, 0x03F2, 0x03F0, 0x01F6, 0x01F4, - 0x00F8, 0x00F6, 0x00F4, 0x0078, 0x003A, 0x0038, 0x000C, 0x0004, - 0x0000, 0x0005, 0x000D, 0x0039, 0x003B, 0x0079, 0x00F5, 0x00F7, - 0x00F9, 0x01F5, 0x01F7, 0x03F1, 0x03F3, 0x03F5, 0x03F7, 0x07F0, - 0x07F2, 0x07F5, 0x0FEC, 0x0FEE, 0x0FF0, 0x0FF2, 0x0FF5, 0x1FEC, - 0x1FEE, 0x1FF0, 0x1FF3, 0x1FF4, 0x3FEB, 0x3FED, 0x3FF0, 0x7FE3, - 0x7FE5, 0x7FE7, 0x7FEA, 0x7FEB, 0x7FED, 0x7FEF, 0x7FF4, 0x7FF2, - 0x7FF6, 0x7FF8, 0xFFF2, 0xFFF4, 0xFFF7, 0xFFF8, 0xFFFB, 0xFFFD, - 0xFFFF, 0x7FE8, -}; - -static const uint16_t clv_biasy_2_syms[] = { - 0xFF40, 0xFF44, 0xFF48, 0xFF4C, 0xFF50, 0xFF54, 0xFF58, 0xFF5C, - 0xFF60, 0xFF64, 0xFF68, 0xFF6C, 0xFF70, 0xFF74, 0xFF78, 0xFF7C, - 0xFF80, 0xFF84, 0xFF88, 0xFF8C, 0xFF90, 0xFF94, 0xFF98, 0xFF9C, - 0xFFA0, 0xFFA4, 0xFFA8, 0xFFAC, 0xFFB0, 0xFFB4, 0xFFB8, 0xFFBC, - 0xFFC0, 0xFFC4, 0xFFC8, 0xFFCC, 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDC, - 0xFFE0, 0xFFE4, 0xFFE8, 0xFFEC, 0xFFF0, 0xFFF4, 0xFFF8, 0xFFFC, - 0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, - 0x0020, 0x0024, 0x0028, 0x002C, 0x0030, 0x0034, 0x0038, 0x003C, - 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, - 0x0060, 0x0064, 0x0068, 0x006C, 0x0070, 0x0074, 0x0078, 0x007C, - 0x0080, 0x0084, 0x0088, 0x008C, 0x0090, 0x0094, 0x0098, 0x009C, - 0x00A0, 0x00A4, 0x00A8, 0x00AC, 0x00B0, 0x00B4, 0x00B8, 0x00BC, - 0x00C0, 0x0100, -}; - -static const uint8_t clv_biasy_3_bits[] = { - 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, - 14, 14, 13, 13, 13, 13, 12, 12, 12, 11, 11, 11, 11, 10, 10, 10, - 10, 9, 9, 9, 9, 8, 8, 7, 7, 6, 5, 4, 4, 2, 2, 3, - 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, - 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14, 14, 14, 14, 14, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 15, -}; - -static const uint16_t clv_biasy_3_codes[] = { - 0xFFFF, 0xFFFC, 0xFFFA, 0x7FFC, 0x7FF9, 0x7FF6, 0x7FF4, 0x7FF2, - 0x7FF1, 0x7FEF, 0x7FEC, 0x7FEB, 0x7FE9, 0x3FF3, 0x3FF0, 0x3FEE, - 0x3FED, 0x3FEA, 0x1FF3, 0x1FF2, 0x1FF0, 0x1FEE, 0x0FF4, 0x0FF3, - 0x0FF1, 0x07F7, 0x07F5, 0x07F3, 0x07F1, 0x03F7, 0x03F4, 0x03F2, - 0x03F0, 0x01F6, 0x01F4, 0x01F2, 0x01F0, 0x00F6, 0x00F4, 0x0078, - 0x0076, 0x0039, 0x001B, 0x000C, 0x000A, 0x0001, 0x0000, 0x0004, - 0x000B, 0x001A, 0x0038, 0x003A, 0x0077, 0x0079, 0x00F5, 0x00F7, - 0x01F1, 0x01F3, 0x01F5, 0x01F7, 0x03F1, 0x03F3, 0x03F5, 0x03F6, - 0x07F0, 0x07F2, 0x07F4, 0x07F6, 0x0FF0, 0x0FF2, 0x0FF5, 0x0FF6, - 0x1FEF, 0x1FF1, 0x1FF4, 0x3FEB, 0x3FEC, 0x3FEF, 0x3FF1, 0x3FF2, - 0x7FE8, 0x7FEA, 0x7FED, 0x7FEE, 0x7FF0, 0x7FF3, 0x7FF5, 0x7FF7, - 0x7FFA, 0x7FFB, 0xFFFB, 0xFFFD, 0xFFFE, 0x7FF8, -}; - -static const uint16_t clv_biasy_3_syms[] = { - 0xFF48, 0xFF4C, 0xFF50, 0xFF54, 0xFF58, 0xFF5C, 0xFF60, 0xFF64, - 0xFF68, 0xFF6C, 0xFF70, 0xFF74, 0xFF78, 0xFF7C, 0xFF80, 0xFF84, - 0xFF88, 0xFF8C, 0xFF90, 0xFF94, 0xFF98, 0xFF9C, 0xFFA0, 0xFFA4, - 0xFFA8, 0xFFAC, 0xFFB0, 0xFFB4, 0xFFB8, 0xFFBC, 0xFFC0, 0xFFC4, - 0xFFC8, 0xFFCC, 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDC, 0xFFE0, 0xFFE4, - 0xFFE8, 0xFFEC, 0xFFF0, 0xFFF4, 0xFFF8, 0xFFFC, 0x0000, 0x0004, - 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, 0x0020, 0x0024, - 0x0028, 0x002C, 0x0030, 0x0034, 0x0038, 0x003C, 0x0040, 0x0044, - 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, 0x0060, 0x0064, - 0x0068, 0x006C, 0x0070, 0x0074, 0x0078, 0x007C, 0x0080, 0x0084, - 0x0088, 0x008C, 0x0090, 0x0094, 0x0098, 0x009C, 0x00A0, 0x00A4, - 0x00A8, 0x00AC, 0x00B0, 0x00B4, 0x00B8, 0x0100, -}; - -static const uint8_t clv_biasu_1_bits[] = { - 16, 15, 14, 13, 13, 13, 12, 12, 12, 12, 11, 10, 10, 9, 9, 8, - 7, 6, 5, 2, 1, 3, 5, 7, 7, 8, 9, 9, 10, 10, 11, 12, - 12, 12, 12, 13, 13, 13, 14, 15, 15, 16, -}; - -static const uint16_t clv_biasu_1_codes[] = { - 0xFFFE, 0x7FFC, 0x3FFC, 0x1FFC, 0x1FFA, 0x1FF9, 0x0FFA, 0x0FF7, - 0x0FF8, 0x0FF5, 0x07F8, 0x03FA, 0x03F8, 0x01FA, 0x01F9, 0x00FA, - 0x007B, 0x003C, 0x001C, 0x0002, 0x0000, 0x0006, 0x001D, 0x007A, - 0x007C, 0x00FB, 0x01F8, 0x01FB, 0x03F9, 0x03FB, 0x07F9, 0x0FF4, - 0x0FF6, 0x0FF9, 0x0FFB, 0x1FF8, 0x1FFB, 0x1FFD, 0x3FFD, 0x7FFD, - 0x7FFE, 0xFFFF, -}; - -static const uint16_t clv_biasu_1_syms[] = { - 0xFFB0, 0xFFB4, 0xFFB8, 0xFFBC, 0xFFC0, 0xFFC4, 0xFFC8, 0xFFCC, - 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDC, 0xFFE0, 0xFFE4, 0xFFE8, 0xFFEC, - 0xFFF0, 0xFFF4, 0xFFF8, 0xFFFC, 0x0000, 0x0004, 0x0008, 0x000C, - 0x0010, 0x0014, 0x0018, 0x001C, 0x0020, 0x0024, 0x0028, 0x002C, - 0x0030, 0x0034, 0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, - 0x0050, 0x0100, -}; - -static const uint8_t clv_biasu_2_bits[] = { - 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 12, 12, 11, 11, 10, - 10, 9, 9, 8, 8, 7, 6, 5, 4, 3, 1, 3, 4, 6, 6, 7, - 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 14, 14, 15, 15, - 15, 16, 16, 16, 16, 14, -}; - -static const uint16_t clv_biasu_2_codes[] = { - 0xFFFC, 0xFFF8, 0xFFFA, 0xFFFD, 0x7FF8, 0x7FFA, 0x7FF7, 0x3FF6, - 0x3FF7, 0x3FF4, 0x1FF9, 0x0FFB, 0x0FF9, 0x07FB, 0x07F9, 0x03FA, - 0x03F8, 0x01FA, 0x01F9, 0x00FB, 0x00F9, 0x007B, 0x003B, 0x001C, - 0x000C, 0x0004, 0x0000, 0x0005, 0x000D, 0x003A, 0x003C, 0x007A, - 0x00F8, 0x00FA, 0x01F8, 0x01FB, 0x03F9, 0x03FB, 0x07F8, 0x07FA, - 0x0FF8, 0x0FFA, 0x1FF8, 0x3FF5, 0x3FF8, 0x3FF9, 0x7FFB, 0x7FF9, - 0x7FF6, 0xFFF9, 0xFFFF, 0xFFFE, 0xFFFB, 0x3FFA, -}; - -static const uint16_t clv_biasu_2_syms[] = { - 0xFF98, 0xFF9C, 0xFFA0, 0xFFA4, 0xFFA8, 0xFFAC, 0xFFB0, 0xFFB4, - 0xFFB8, 0xFFBC, 0xFFC0, 0xFFC4, 0xFFC8, 0xFFCC, 0xFFD0, 0xFFD4, - 0xFFD8, 0xFFDC, 0xFFE0, 0xFFE4, 0xFFE8, 0xFFEC, 0xFFF0, 0xFFF4, - 0xFFF8, 0xFFFC, 0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, - 0x0018, 0x001C, 0x0020, 0x0024, 0x0028, 0x002C, 0x0030, 0x0034, - 0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, - 0x0058, 0x005C, 0x0060, 0x0064, 0x0068, 0x0100, -}; - -static const uint8_t clv_biasv_1_bits[] = { - 16, 15, 14, 14, 14, 13, 13, 13, 12, 12, 11, 11, 10, 10, 9, 8, - 7, 6, 5, 2, 1, 3, 5, 6, 8, 8, 9, 10, 10, 11, 12, 12, - 12, 13, 13, 13, 14, 14, 15, 15, 16, 14, -}; - -static const uint16_t clv_biasv_1_codes[] = { - 0xFFFF, 0x7FFD, 0x3FFD, 0x3FFB, 0x3FF9, 0x1FFB, 0x1FF8, 0x1FF6, - 0x0FFA, 0x0FF8, 0x07FA, 0x07F8, 0x03FA, 0x03F8, 0x01FB, 0x00FB, - 0x007C, 0x003C, 0x001C, 0x0002, 0x0000, 0x0006, 0x001D, 0x003D, - 0x00FA, 0x00FC, 0x01FA, 0x03F9, 0x03FB, 0x07F9, 0x0FF6, 0x0FF7, - 0x0FF9, 0x1FF7, 0x1FF9, 0x1FFA, 0x3FFA, 0x3FFC, 0x7FFC, 0x7FFE, - 0xFFFE, 0x3FF8, -}; - -static const uint16_t clv_biasv_1_syms[] = { - 0xFFB0, 0xFFB4, 0xFFB8, 0xFFBC, 0xFFC0, 0xFFC4, 0xFFC8, 0xFFCC, - 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDC, 0xFFE0, 0xFFE4, 0xFFE8, 0xFFEC, - 0xFFF0, 0xFFF4, 0xFFF8, 0xFFFC, 0x0000, 0x0004, 0x0008, 0x000C, - 0x0010, 0x0014, 0x0018, 0x001C, 0x0020, 0x0024, 0x0028, 0x002C, - 0x0030, 0x0034, 0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, - 0x0050, 0x0100, -}; - -static const uint8_t clv_biasv_2_bits[] = { - 16, 15, 14, 13, 13, 13, 13, 13, 12, 12, 11, 10, 10, 9, 9, 8, - 7, 6, 5, 4, 3, 1, 3, 4, 5, 7, 7, 8, 9, 9, 10, 10, - 10, 12, 12, 13, 13, 13, 13, 13, 14, 16, 15, 15, -}; - -static const uint16_t clv_biasv_2_codes[] = { - 0xFFFE, 0x7FFD, 0x3FFC, 0x1FFC, 0x1FFB, 0x1FF8, 0x1FF7, 0x1FF4, - 0x0FF8, 0x0FF7, 0x07FA, 0x03FB, 0x03F8, 0x01FA, 0x01F9, 0x00FA, - 0x007B, 0x003C, 0x001C, 0x000C, 0x0004, 0x0000, 0x0005, 0x000D, - 0x001D, 0x007A, 0x007C, 0x00FB, 0x01F8, 0x01FB, 0x03F9, 0x03FA, - 0x03FC, 0x0FF6, 0x0FF9, 0x1FF5, 0x1FF9, 0x1FF6, 0x1FFA, 0x1FFD, - 0x3FFD, 0xFFFF, 0x7FFE, 0x7FFC, -}; - -static const uint16_t clv_biasv_2_syms[] = { - 0xFFAC, 0xFFB0, 0xFFB4, 0xFFB8, 0xFFBC, 0xFFC0, 0xFFC4, 0xFFC8, - 0xFFCC, 0xFFD0, 0xFFD4, 0xFFD8, 0xFFDC, 0xFFE0, 0xFFE4, 0xFFE8, - 0xFFEC, 0xFFF0, 0xFFF4, 0xFFF8, 0xFFFC, 0x0000, 0x0004, 0x0008, - 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, 0x0020, 0x0024, 0x0028, - 0x002C, 0x0030, 0x0034, 0x0038, 0x003C, 0x0040, 0x0044, 0x0048, - 0x004C, 0x0050, 0x0054, 0x0100, + -9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, + 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 7, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 5, 5, 5, 4, 2, 3, 4, 4 +}; + +static const uint8_t clv_flags_bits[][16] = { + { 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 6, 7, 7 }, // Y_0 + { 2, 3, 3, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 7, 8, 8 }, // Y_1 + { 1, 4, 4, 4, 4, 4, 4, 5, 5, 5, 6, 7, 8, 9, 10, 10 }, // Y_2 + { 1, 4, 4, 4, 4, 4, 4, 5, 5, 5, 7, 7, 7, 8, 9, 9 }, // U_0 + { 1, 4, 4, 4, 4, 4, 4, 4, 5, 6, 8, 8, 8, 9, 10, 10 }, // U_1 + { 1, 3, 4, 4, 4, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 10 }, // V_0 + { 1, 3, 4, 4, 4, 4, 5, 5, 5, 6, 7, 8, 9, 10, 11, 11 } // V_1 +}; + +static const uint8_t clv_flags_syms[][16] = { + { 15, 0, 3, 5, 12, 1, 10, 2, 4, 8, 7, 11, 14, 6, 9, 13 }, // Y_0 + { 0, 15, 3, 12, 5, 1, 4, 2, 8, 10, 11, 7, 9, 6, 13, 14 }, // Y_1 + { 0, 3, 12, 4, 2, 1, 8, 5, 7, 10, 9, 6, 11, 13, 14, 15 }, // Y_2 + { 0, 15, 3, 12, 1, 10, 2, 5, 4, 8, 11, 7, 14, 13, 9, 6 }, // U_0 + { 0, 2, 12, 3, 4, 1, 8, 5, 10, 7, 9, 6, 11, 14, 13, 15 }, // U_1 + { 0, 15, 1, 12, 3, 10, 2, 5, 8, 4, 11, 14, 6, 9, 7, 13 }, // V_0 + { 0, 8, 3, 4, 2, 1, 12, 5, 10, 7, 9, 6, 14, 11, 13, 15 } // V_1 +}; + +static const uint8_t clv_mv_len_counts[][16] = { + { 1, 0, 0, 2, 2, 6, 13, 6, 14, 28, 38, 38, 58, 56, 20, 8 }, + { 1, 0, 0, 2, 3, 4, 8, 10, 20, 30, 37, 63, 84, 68, 32, 0 }, + { 0, 1, 0, 4, 0, 6, 9, 24, 32, 48, 112, 142, 232, 166, 142, 44 }, + { 0, 1, 0, 2, 2, 6, 9, 16, 40, 82, 146, 228, 191, 255, 244, 100 }, + { 0, 0, 2, 5, 2, 12, 6, 15, 14, 24, 37, 33, 24, 28, 8, 16 }, + { 1, 0, 0, 2, 2, 5, 10, 12, 19, 19, 37, 74, 69, 120, 48, 24 }, + { 0, 0, 2, 3, 8, 7, 8, 8, 23, 37, 30, 36, 28, 16, 12, 8 }, + { 1, 0, 0, 0, 4, 5, 14, 18, 20, 39, 6, 80, 75, 112, 36, 32 }, +}; + +#define MV_ESC 0x13 +static const uint16_t clv_mv_syms[] = { + /* Y_0 motion vectors - 290 entries */ + 0x0000, 0x00FF, 0x0001, 0xFF00, 0x0100, 0x0002, 0x00FE, MV_ESC, 0x00FD, + 0x0004, 0x00FC, 0x0003, 0x01FF, 0xFF01, 0x0101, 0xFFFF, 0xFE00, 0x0200, + 0x0005, 0x00FB, 0x00FA, 0x0006, 0x0007, 0x00F9, 0xFF02, 0x0102, 0xFFFE, + 0x01FE, 0xFD00, 0x0300, 0xFC00, 0x0400, 0x02FF, 0xFE01, 0x0201, 0xFEFF, + 0x0008, 0x00F8, 0xFB00, 0x0500, 0xFFFD, 0x01FD, 0xFF03, 0x0103, 0xFFFA, + 0x01FA, 0xFF06, 0x0106, 0xFA00, 0x0600, 0xFE02, 0x0202, 0xFEFE, 0x02FE, + 0xFFFC, 0x01FC, 0xFF04, 0x0104, 0xF900, 0x0700, 0xFF05, 0x0105, 0xFFFB, + 0x01FB, 0xFEFD, 0x02FD, 0xFE03, 0x0203, 0xFF07, 0x0107, 0xFFF9, 0x01F9, + 0xFEFC, 0x02FC, 0xFE04, 0x0204, 0xFD02, 0x0302, 0xFDFE, 0x03FE, 0x03FF, + 0xFD01, 0x0301, 0xFDFF, 0xFDFD, 0xFD03, 0x03FD, 0x0303, 0xFEFA, 0x02FA, + 0xFE06, 0x0206, 0xFFF8, 0x0108, 0x01F8, 0xFF08, 0x04FF, 0xFC01, 0x0401, + 0xFCFF, 0x0208, 0xFE08, 0x02F8, 0xFEF8, 0x02FB, 0xFE05, 0xFEFB, 0x0205, + 0xF800, 0x0800, 0xFD05, 0xFDFB, 0x0305, 0x03FB, 0xFDFC, 0x03FC, 0xFD04, + 0x0304, 0x0207, 0xFE07, 0xFEF9, 0x02F9, 0xFCFD, 0xFC03, 0x04FD, 0x0403, + 0xFC02, 0x0402, 0xFCFE, 0x04FE, 0xFB02, 0x05FE, 0x0502, 0xFBFE, 0xFCFC, + 0x04FC, 0xFC04, 0x0404, 0x0308, 0xFD08, 0x03F8, 0xFDF8, 0xFBFC, 0x05FC, + 0xFB04, 0x0504, 0x05FF, 0xFB01, 0x0501, 0xFBFF, 0x04FB, 0xFCFB, 0xFC05, + 0x0405, 0x06FF, 0xFA01, 0x0601, 0xFAFF, 0xFDFA, 0x03FA, 0xFD06, 0x0306, + 0xFBFD, 0xFB03, 0x05FD, 0x0503, 0xFCFA, 0x04FA, 0x0406, 0xFC06, 0xFC08, + 0x0408, 0xFCF8, 0x04F8, 0xFD07, 0x0307, 0xFDF9, 0x03F9, 0x05F8, 0x0508, + 0xFBF8, 0xFB08, 0x05FB, 0x0505, 0xFB05, 0xFBFB, 0x0407, 0xFC07, 0xFCF9, + 0x04F9, 0xFA03, 0xFAFD, 0x06FD, 0x0603, 0x06FE, 0xFAFE, 0xFA08, 0xFA02, + 0x0608, 0x0602, 0xFAF8, 0x06F8, 0x07FF, 0xF9FF, 0xF901, 0x0701, 0x08FF, + 0x0801, 0xF801, 0xF8FF, 0xF902, 0xF9FE, 0x0702, 0x07FE, 0x06FB, 0x0605, + 0xFA05, 0xFAFB, 0xFB07, 0xFBF9, 0x0507, 0x05F9, 0xF903, 0x07FD, 0xF9FD, + 0x0703, 0x06F9, 0x05FA, 0xFAF9, 0x0506, 0xFBFA, 0x0607, 0xFA07, 0xFB06, + 0x0606, 0xFAFA, 0xFA06, 0x06FA, 0xF9FA, 0x0706, 0xF906, 0x07FA, 0xF802, + 0xF8FE, 0x08FE, 0x0802, 0x07F8, 0xF9F8, 0xFAFC, 0x0708, 0xF908, 0x0604, + 0x06FC, 0xFA04, 0x0707, 0x07F9, 0xF907, 0xF9F9, 0xF9FB, 0x07FB, 0x0705, + 0xF905, 0x0803, 0xF8FD, 0xF803, 0x08FD, 0x0805, 0x08FB, 0xF8FB, 0xF807, + 0xF8F9, 0x0807, 0x08F9, 0xF805, 0xF904, 0x0704, 0xF9FC, 0x07FC, 0x0806, + 0x08FA, 0xF806, 0xF8FA, 0x0804, 0x08FC, 0xF804, 0xF8FC, 0x0808, 0xF8F8, + 0x08F8, 0xF808, + /* Y_1 motion vectors - 362 entries */ + 0x0000, 0x00FF, 0x0001, 0xFF00, 0x0100, MV_ESC, 0xFFFF, 0x01FF, 0xFF01, + 0x0101, 0x00FE, 0x0002, 0x0003, 0x00FD, 0x0004, 0x00FC, 0xFE00, 0x0200, + 0x0005, 0x00FB, 0x00FA, 0x0006, 0x0007, 0x00F9, 0xFFFE, 0x01FE, 0xFF02, + 0x0102, 0xFF03, 0x0103, 0xFFFD, 0x01FD, 0xFEFF, 0x02FF, 0xFE01, 0x0201, + 0x0008, 0x00F8, 0x00F7, 0x0009, 0xFD00, 0x0300, 0xFF04, 0x0104, 0xFFFC, + 0x01FC, 0xFC00, 0x0400, 0xFB00, 0x0500, 0xFA00, 0x0600, 0xFEFE, 0x02FE, + 0xFE02, 0x0202, 0xFFFA, 0x01FA, 0xFF06, 0x0106, 0xFF05, 0x0105, 0xFFFB, + 0x01FB, 0xFDFF, 0x03FF, 0xFD01, 0x0301, 0xFE03, 0x0203, 0xFEFD, 0x02FD, + 0xF900, 0x0700, 0xFF08, 0x0108, 0xFFF8, 0x01F8, 0xFCFF, 0x04FF, 0xFC01, + 0x0401, 0xFF07, 0x0107, 0xFFF9, 0x01F9, 0x0204, 0xFEFC, 0x02FC, 0xFE04, + 0xFE05, 0x0205, 0xFEFB, 0x02FB, 0x0109, 0xFFF7, 0xFF09, 0x01F7, 0xFDFE, + 0x03FE, 0xFD02, 0x0302, 0xFCFE, 0x04FE, 0xF800, 0x0800, 0xFC02, 0x0402, + 0xFD03, 0x0303, 0xFDFD, 0x03FD, 0xFBFF, 0xFB01, 0x0501, 0x05FF, 0xFE07, + 0x0207, 0xFEF9, 0x02F9, 0x04FD, 0xFC03, 0xFCFD, 0x0403, 0xFBFE, 0x05FE, + 0xFB02, 0x0502, 0xFEFA, 0x02FA, 0xFE06, 0x0206, 0x0304, 0xFDFC, 0x03FC, + 0xFD04, 0xFDFA, 0x03FA, 0x0306, 0x06FF, 0xFAFF, 0xFA01, 0x0601, 0xFD06, + 0xF700, 0x0900, 0x0404, 0xFCFC, 0x04FC, 0xFC04, 0xFD05, 0x0305, 0x03FB, + 0xFDFB, 0xFE08, 0xFEF8, 0x02F8, 0x0208, 0x03F8, 0xFD08, 0xFDF8, 0x0308, + 0x04F8, 0xFC08, 0x0408, 0xFCF8, 0xFAFE, 0x06FE, 0xFA02, 0x0602, 0x04FA, + 0xFC06, 0x0406, 0xFCFA, 0xFC05, 0x0405, 0x04FB, 0xFCFB, 0x05FD, 0xFB03, + 0xFBFD, 0x0503, 0x0504, 0xFBFC, 0xFB04, 0x05FC, 0x06FD, 0xFAFC, 0x0604, + 0x06FC, 0xFA03, 0xFAFD, 0x0603, 0xFA04, 0xFB05, 0x0505, 0xFD07, 0x0307, + 0xFBFB, 0xFDF9, 0x05FB, 0x03F9, 0x0508, 0xFBF8, 0x05F8, 0xFB08, 0x0209, + 0xFE09, 0x02F7, 0xFEF7, 0x0608, 0x06F8, 0xFA08, 0xFAF8, 0xFC07, 0xF9FF, + 0x0407, 0x07FF, 0xFCF9, 0xF901, 0x0701, 0x04F9, 0xF9FE, 0x07FE, 0xF902, + 0x0702, 0x05F9, 0xFB07, 0xFBF9, 0x0507, 0x07FD, 0xF903, 0xF9FD, 0x0703, + 0xFD09, 0x03F7, 0x0309, 0xFDF7, 0x0704, 0xF9FC, 0x07FC, 0xF904, 0x0605, + 0xFAFB, 0xFA05, 0x06FB, 0x05FA, 0xFB06, 0x0506, 0xFBFA, 0x08FF, 0xF801, + 0xF8FF, 0x0801, 0xF8FE, 0x0802, 0xF802, 0x08FE, 0x0901, 0xF7FF, 0x09FF, + 0xF701, 0x06F9, 0x0607, 0xFAF9, 0xFA07, 0x04F7, 0xFC09, 0x0409, 0xFCF7, + 0x0707, 0xF9F9, 0xF907, 0x07F9, 0x0606, 0xFA06, 0x06FA, 0xFAFA, 0xF908, + 0xF9F8, 0x07F8, 0x0708, 0x07FA, 0xF906, 0x0706, 0xF9FA, 0x0804, 0xF7FE, + 0x08FC, 0xF804, 0xF702, 0x0902, 0xF8FC, 0x09FE, 0x05F7, 0xFB09, 0x0509, + 0xFBF7, 0x0803, 0x08FD, 0xF803, 0xF8FD, 0xF905, 0x0705, 0x07FB, 0xF9FB, + 0xF8FA, 0x08FA, 0x0806, 0xF806, 0xF7FC, 0xF704, 0x09FC, 0x0904, 0xF7FD, + 0xF703, 0x09FD, 0x0903, 0x0808, 0xF808, 0x08F8, 0xF8F8, 0xF706, 0x0906, + 0xF7FA, 0x09FA, 0xF805, 0x0805, 0xF8FB, 0x08FB, 0xFA09, 0x0609, 0x06F7, + 0xFAF7, 0x08F9, 0xF8F9, 0x0807, 0xF807, 0x0709, 0x07F7, 0xF909, 0xF9F7, + 0x0905, 0xF705, 0x09FB, 0xF7FB, 0x09F8, 0xF7F8, 0x0908, 0xF708, 0x08F7, + 0xF809, 0xF8F7, 0x0809, 0xF709, 0xF7F7, 0x0909, 0x09F7, 0xF7F9, 0x09F9, + 0x0907, 0xF707, + /* Y_2 motion vectors - 962 entries */ + 0x0000, 0x0001, 0x00FF, 0xFF00, 0x0100, 0x0002, 0x00FE, 0x0101, 0xFFFF, + 0x01FF, 0xFF01, 0x0003, 0x00FD, 0x0004, 0x00FC, MV_ESC, 0x0005, 0x00FB, + 0xFE00, 0x0200, 0xFF02, 0x0102, 0xFFFE, 0x01FE, 0x00FA, 0x0006, 0x00F9, + 0x0007, 0x0201, 0xFEFF, 0x02FF, 0xFE01, 0xFD00, 0x0300, 0xFF03, 0x0103, + 0xFFFD, 0x01FD, 0xFC00, 0x0400, 0x0008, 0x00F8, 0xFB00, 0x0500, 0x0009, + 0x00F7, 0x00F5, 0x000B, 0xFE02, 0x0202, 0xFEFE, 0x02FE, 0x00F6, 0x000A, + 0xFF04, 0x0104, 0xFFFC, 0x01FC, 0xFA00, 0x0600, 0x0301, 0xFDFF, 0x03FF, + 0xFD01, 0xF900, 0x0700, 0x0401, 0xFCFF, 0x04FF, 0xFC01, 0x000C, 0x00F4, + 0xFFFA, 0x01FA, 0xFF06, 0x0106, 0xFF05, 0x0105, 0xFFFB, 0x01FB, 0xF800, + 0x0800, 0xFE03, 0x0203, 0xFEFD, 0x02FD, 0xFE04, 0x0204, 0xFEFC, 0x02FC, + 0xFFF9, 0x01F9, 0xFF07, 0x0107, 0x00F3, 0x000D, 0xFD02, 0x0302, 0xFDFE, + 0x03FE, 0x00F2, 0x000E, 0x0501, 0xFBFF, 0x05FF, 0xFB01, 0xFE05, 0x0205, + 0xFEFB, 0x02FB, 0xFF08, 0x0108, 0xFFF8, 0x01F8, 0xFC02, 0x0402, 0xFCFE, + 0x04FE, 0xF700, 0x0900, 0xFEFA, 0x02FA, 0xFE06, 0x0206, 0x00F1, 0x000F, + 0xFF09, 0x0109, 0xFFF7, 0x01F7, 0xFFF6, 0x01F6, 0xFF0A, 0x010A, 0xFD03, + 0x0303, 0xFDFD, 0x03FD, 0xFC03, 0x0403, 0xFCFD, 0x04FD, 0xFD04, 0x0304, + 0xFDFC, 0x03FC, 0xF600, 0x0A00, 0x0601, 0xFAFF, 0x06FF, 0xFA01, 0xFB02, + 0x0502, 0xFBFE, 0x05FE, 0xFF0C, 0x010C, 0xFFF4, 0x01F4, 0xFFF5, 0x01F5, + 0xFF0B, 0x010B, 0x0701, 0xF9FF, 0x07FF, 0xF901, 0xFDFA, 0x03FA, 0xFD06, + 0x0306, 0xFE08, 0x0208, 0xFEF8, 0x02F8, 0xFA02, 0x0602, 0xFAFE, 0x06FE, + 0xFEF9, 0x02F9, 0xFE07, 0x0207, 0xFE09, 0x0209, 0xFEF7, 0x02F7, 0xFC04, + 0x0404, 0xFCFC, 0x04FC, 0xFB03, 0x0503, 0xFBFD, 0x05FD, 0x0801, 0xF8FF, + 0x08FF, 0xF801, 0xFD05, 0x0305, 0xFDFB, 0x03FB, 0xFFF3, 0x01F3, 0x010D, + 0xFF0D, 0xF902, 0x0702, 0xF9FE, 0x07FE, 0xF500, 0x0B00, 0xFA03, 0x0603, + 0xFAFD, 0x06FD, 0xFC05, 0x0405, 0xFCFB, 0x04FB, 0xFEF6, 0x02F6, 0xFE0A, + 0x020A, 0xFDF9, 0x03F9, 0xFD07, 0x0307, 0xFEF5, 0x02F5, 0xFE0B, 0x020B, + 0xFFF2, 0x01F2, 0xFF0E, 0x010E, 0xF400, 0x0C00, 0xF802, 0x0802, 0xF8FE, + 0x08FE, 0xF903, 0x0703, 0xF9FD, 0x07FD, 0x03F8, 0xFB04, 0x0504, 0xFBFC, + 0x05FC, 0xFD08, 0x0308, 0xFDF8, 0xFB05, 0x0505, 0xFBFB, 0x05FB, 0xFA04, + 0x0604, 0xFAFC, 0x06FC, 0xF300, 0x0D00, 0xFC08, 0x0408, 0xFCF8, 0x04F8, + 0xFCFA, 0x04FA, 0xFC06, 0x0406, 0xF200, 0x0E00, 0x0901, 0xF7FF, 0x09FF, + 0xF701, 0xFD09, 0x0309, 0xFDF7, 0x03F7, 0xFDF6, 0x03F6, 0xFD0A, 0x030A, + 0xFC09, 0x0409, 0xFCF7, 0x04F7, 0x0A01, 0xF6FF, 0x0AFF, 0xF601, 0xFBF8, + 0xFB08, 0x0508, 0x05F8, 0x020C, 0xFE0C, 0xFEF4, 0x02F4, 0xFA05, 0xFAFB, + 0x0605, 0x06FB, 0x01F1, 0x010F, 0xFF0F, 0xFFF1, 0xF100, 0x0F00, 0xF904, + 0x0704, 0xF9FC, 0x07FC, 0xF803, 0x0803, 0xF8FD, 0x08FD, 0xF804, 0x0804, + 0xF8FC, 0x08FC, 0xFCF9, 0x04F9, 0xFC07, 0x0407, 0xF702, 0x0902, 0xF7FE, + 0x09FE, 0xF602, 0x0A02, 0xF6FE, 0x0AFE, 0xFB09, 0xFBF7, 0x05F7, 0x0509, + 0x0B01, 0xF5FF, 0x0BFF, 0xF501, 0xFBFA, 0x05FA, 0xFB06, 0x0506, 0xFBF9, + 0x05F9, 0xFB07, 0x0507, 0xF703, 0x0903, 0xF7FD, 0x09FD, 0xFAFA, 0xF704, + 0x06FA, 0x0904, 0xFA06, 0x0606, 0xF7FC, 0x09FC, 0xFDF5, 0x03F5, 0x030B, + 0xFD0B, 0xFAF9, 0x06F9, 0xFA07, 0x0607, 0xFA08, 0x0608, 0xFAF8, 0x06F8, + 0xF502, 0x0B02, 0xF5FE, 0x0BFE, 0xF9F9, 0x07F9, 0xF907, 0x0707, 0xF905, + 0xF9FB, 0x0705, 0x07FB, 0xF9FA, 0x07FA, 0xF906, 0x0706, 0x0C01, 0xF4FF, + 0x0CFF, 0xF401, 0xF908, 0x0708, 0xF9F8, 0x07F8, 0xF8F9, 0x08F9, 0xF807, + 0x0807, 0x0AFC, 0xF604, 0x0A04, 0xF6FC, 0xF8FA, 0x08FA, 0xF806, 0x0806, + 0xF603, 0x0A03, 0xF6FD, 0x0AFD, 0xF805, 0xF8FB, 0x0805, 0x08FB, 0xFA09, + 0x0609, 0xFAF7, 0x06F7, 0x040A, 0xFCF6, 0x04F6, 0xFC0A, 0xFDF4, 0x030C, + 0xFD0C, 0x03F4, 0xFB0A, 0xFBF6, 0x05F6, 0x050A, 0xFCF5, 0xFC0B, 0x04F5, + 0x040B, 0xF705, 0xF7FB, 0x0905, 0x09FB, 0xF808, 0x0808, 0xF8F8, 0x08F8, + 0xFAF6, 0x06F6, 0xFA0A, 0x060A, 0xF7FA, 0x09FA, 0xF706, 0x0906, 0xF9F6, + 0x07F6, 0xF90A, 0x070A, 0x02F1, 0xFEF3, 0x02F3, 0xFE0D, 0xFE0F, 0xFEF1, + 0x020F, 0x020D, 0x050B, 0xFBF5, 0x05F5, 0xFB0B, 0x040C, 0xFCF4, 0xFC0C, + 0x04F4, 0xFAF5, 0x06F5, 0xFA0B, 0x060B, 0x020E, 0xFEF2, 0xFE0E, 0x02F2, + 0xFB0C, 0x05F4, 0xFBF4, 0x050C, 0xF9F5, 0x070B, 0x07F5, 0xF90B, 0x030E, + 0xFDF2, 0x03F2, 0xFD0E, 0xF8F5, 0x08F5, 0x080B, 0xF80B, 0xF5FD, 0xF503, + 0x0B03, 0x0BFD, 0x030D, 0xFD0D, 0xFDF3, 0x03F3, 0x09F9, 0x0907, 0xF707, + 0xF7F9, 0xF6FA, 0x0AFA, 0x0A06, 0xF606, 0xF403, 0x0C03, 0x0709, 0xF4FD, + 0xF9F7, 0xF909, 0x0CFD, 0x07F7, 0x0AF9, 0x0A07, 0xF607, 0xF6F9, 0xF5FA, + 0xF506, 0x0BFA, 0x0B06, 0xF303, 0xF3FD, 0x0DFD, 0x0D03, 0x0D01, 0xF3FF, + 0x0DFF, 0xF301, 0xFCF2, 0xFC0E, 0x040E, 0x04F2, 0x0809, 0xF8F7, 0x08F7, + 0xF809, 0xF5FC, 0xF504, 0x0B04, 0x0BFC, 0xF7F5, 0x09F5, 0x090B, 0xF70B, + 0x0E03, 0xF2FD, 0xF203, 0x0EFD, 0xFBF2, 0x050E, 0x05F2, 0xFB0E, 0xFCF3, + 0xFC0D, 0x04F3, 0x040D, 0xF402, 0x0C02, 0xF4FE, 0x0CFE, 0xF6F5, 0xF6FB, + 0x0AF5, 0xF605, 0x0A05, 0x0AFB, 0x0A0B, 0xF60B, 0x080A, 0xF8F6, 0x08F6, + 0xF80A, 0xF7F6, 0xF70A, 0x09F6, 0x090A, 0x0BFB, 0xF505, 0xF5FB, 0x0B05, + 0x030F, 0x03F1, 0xFDF1, 0xFD0F, 0xF2FF, 0x0EFF, 0xF201, 0x0E01, 0xF6F6, + 0x0AF6, 0x0908, 0xF60A, 0x0A0A, 0xF708, 0xF7F8, 0x09F8, 0x0BF9, 0x0B07, + 0xF5F9, 0xF507, 0xF709, 0x0909, 0xF7F7, 0x09F7, 0x0CF9, 0xF407, 0x0C07, + 0xF4F9, 0xF608, 0x0A08, 0xF6F8, 0x0AF8, 0xFBF3, 0x05F3, 0xFB0D, 0x050D, + 0xF5F8, 0xF508, 0x0B08, 0x0BF8, 0x060D, 0xFAF3, 0x06F3, 0xFA0D, 0x0CFA, + 0xF4FA, 0xF406, 0x0C06, 0x0DF9, 0xF307, 0x0D07, 0xF3F9, 0x0D02, 0x0DFE, + 0xF3FE, 0xF302, 0xFA0E, 0xFAF2, 0x060E, 0x06F2, 0xF4FB, 0x0C05, 0x0CFB, + 0xF405, 0x070D, 0xF9F3, 0xF90D, 0x07F3, 0xF5F5, 0x0BF5, 0x0B0B, 0xF50B, + 0x0AF7, 0x0A09, 0xF6F7, 0xF609, 0xF202, 0x0E02, 0xFAF4, 0xF2FE, 0x0EFE, + 0xFA0C, 0x06F4, 0x060C, 0xF404, 0x0C04, 0xF4FC, 0x0CFC, 0xFC0F, 0x0D04, + 0xFCF1, 0x04F1, 0xF304, 0x0DFC, 0x040F, 0x070C, 0xF3FC, 0xF9F4, 0x07F4, + 0xF90C, 0xF8F3, 0xF3FA, 0x08F3, 0xF306, 0x080D, 0x0DFA, 0x0D06, 0xF80D, + 0xF204, 0x0EFC, 0xF2FC, 0x0E04, 0x07F2, 0xF90E, 0xF9F2, 0x070E, 0xF3FB, + 0x0D05, 0xF305, 0x0DFB, 0xF4F8, 0x080C, 0xF8F4, 0xF408, 0x0C08, 0x0CF8, + 0x08F4, 0xF80C, 0xF70C, 0x090C, 0xF7F4, 0x09F4, 0xF4F5, 0x0CF5, 0x0C0B, + 0xF40B, 0xF8F2, 0xF80E, 0x080E, 0x08F2, 0x0A0C, 0xF60C, 0xF6F4, 0x0AF4, + 0x0F02, 0xF102, 0xF1FE, 0x0FFE, 0x090D, 0xF7F3, 0x09F3, 0xF70D, 0xF1FC, + 0xF104, 0x0FFC, 0x0F04, 0x0B0C, 0xF50C, 0xF5F4, 0x0BF4, 0xFB0F, 0x050F, + 0x05F1, 0xFBF1, 0xF5F6, 0x0B0A, 0xF50A, 0x0BF6, 0xF60D, 0xF6F3, 0x0A0D, + 0x0AF3, 0xF70E, 0xF7F2, 0x09F2, 0x090E, 0x06F1, 0x060F, 0xFAF1, 0xFA0F, + 0x0DF5, 0x0D0B, 0xF3F5, 0xF30B, 0x0B09, 0x0BF7, 0xF509, 0xF5F7, 0x0D08, + 0xF3F8, 0xF308, 0x0DF8, 0x0CF6, 0x0C0A, 0xF4F6, 0xF40A, 0xF50D, 0x0BF3, + 0x0B0D, 0xF208, 0xF40C, 0xF5F3, 0x0EF8, 0xF4F4, 0xF2F8, 0x0CF4, 0x0C0C, + 0x0E08, 0xF2F9, 0x0EF9, 0xF207, 0x0E07, 0xF205, 0x0E05, 0x0EFB, 0xF2FB, + 0x0A0E, 0x0AF2, 0xF6F2, 0xF103, 0x0FFD, 0xF60E, 0x0F03, 0xF1FD, 0x0EF5, + 0x0E0B, 0xF2F5, 0xF20B, 0x0DF6, 0xF30A, 0xF3F6, 0x0D0A, 0x0F05, 0x0FFB, + 0xF105, 0xF1FB, 0x070F, 0xF9F1, 0x07F1, 0xF90F, 0xF80F, 0x080F, 0x08F1, + 0xF8F1, 0x0BF2, 0xF50E, 0xF5F2, 0x0B0E, 0x09F1, 0x090F, 0xF7F1, 0xF70F, + 0x0CF3, 0xF20A, 0xF40D, 0x0EF6, 0xF4F3, 0xF2F6, 0x0E0A, 0x0C0D, 0xF60F, + 0xF50F, 0xF4F7, 0x0A0F, 0x0AF1, 0x0BF1, 0xF6F1, 0x0C09, 0x0B0F, 0xF409, + 0x0CF7, 0xF5F1, 0xF40F, 0x0CF1, 0x0C0F, 0xF4F1, 0xF30C, 0x0DF4, 0xF3F4, + 0x0D0C, 0xF309, 0x0EF4, 0xF3F7, 0x0D09, 0x0DF7, 0xF2F4, 0xF20C, 0x0E0C, + 0xF4F2, 0xF40E, 0x0C0E, 0x0CF2, 0x0DF2, 0xF30E, 0xF3F2, 0x0D0E, 0x0EFA, + 0x0E06, 0xF206, 0xF2FA, 0x0FFA, 0x0F06, 0xF106, 0xF1FA, 0xF20E, 0x0E09, + 0x0E0E, 0xF2F2, 0xF2F7, 0x0EF2, 0x0EF7, 0xF209, 0xF2F3, 0xF30D, 0xF20D, + 0x0EF3, 0xF3F3, 0x0DF3, 0x0E0D, 0x0D0D, 0xF3F1, 0x0D0F, 0xF30F, 0x0DF1, + 0xF107, 0x0FF9, 0x0F07, 0xF1F9, 0xF2F1, 0xF20F, 0x0FF7, 0x0EF1, 0xF1F7, + 0x0E0F, 0xF109, 0x0F09, 0xF1F8, 0xF108, 0x0FF8, 0x0F08, 0x0F0B, 0xF10B, + 0x0FF6, 0xF1F6, 0x0FF5, 0x0F0A, 0xF10A, 0xF1F5, 0xF1F3, 0xF10D, 0x0FF3, + 0x0F0D, 0x0FFF, 0xF1FF, 0xF101, 0x0F01, 0x0F0F, 0xF1F1, 0x0FF1, 0xF10F, + 0x0FF2, 0xF10C, 0x0F0E, 0x0FF4, 0xF1F4, 0xF1F2, 0x0F0C, 0xF10E, + /* Y_3 motion vectors - 1370 elements */ + 0x0000, 0x00FF, 0x0001, 0xFF00, 0x0100, 0x00FE, 0x0002, 0xFFFF, 0x01FF, + 0xFF01, 0x0101, 0x00FD, 0x0003, 0x00FC, 0x0004, 0xFE00, 0x0200, 0x0005, + 0x00FB, MV_ESC, 0xFFFE, 0x01FE, 0xFF02, 0x0102, 0x0006, 0x00FA, 0xFEFF, + 0x02FF, 0xFE01, 0x0201, 0xFD00, 0x0300, 0xFC00, 0x0400, 0x00F9, 0x0007, + 0xFFFD, 0x01FD, 0xFF03, 0x0103, 0x00F8, 0x0008, 0x00F7, 0x0009, 0x000A, + 0x00F6, 0xFEFE, 0x02FE, 0xFE02, 0x0202, 0xFFFC, 0x01FC, 0xFF04, 0x0104, + 0xFB00, 0x0500, 0xFDFF, 0x03FF, 0xFD01, 0x0301, 0xFEFD, 0x02FD, 0xFE03, + 0x0203, 0xFCFF, 0x04FF, 0xFC01, 0x0401, 0xFF05, 0x0105, 0xFFFB, 0x01FB, + 0x000B, 0x00F5, 0xFA00, 0x0600, 0xF900, 0x0700, 0xFFF9, 0x01F9, 0xFF07, + 0x0107, 0xFDFE, 0x03FE, 0xFD02, 0x0302, 0xFBFF, 0x05FF, 0xFB01, 0x0501, + 0xF800, 0x0800, 0xFF06, 0x0106, 0xFFFA, 0x01FA, 0xFAFF, 0x06FF, 0xFA01, + 0x0601, 0xFEFC, 0x02FC, 0xFE04, 0x0204, 0xFFF8, 0x01F8, 0xFF08, 0x0108, + 0xFCFE, 0x04FE, 0xFC02, 0x0402, 0xF700, 0x0900, 0xF600, 0x0A00, 0xFDFD, + 0x03FD, 0xFD03, 0x0303, 0xFF0A, 0x010A, 0xFFF6, 0x01F6, 0xFE05, 0x0205, + 0xFEFB, 0x02FB, 0x000C, 0x00F4, 0xFDFC, 0x03FC, 0xFD04, 0x0304, 0x000D, + 0x00F3, 0xFE06, 0x0206, 0xFEFA, 0x02FA, 0xFFF7, 0x01F7, 0xFF09, 0x0109, + 0xFF0B, 0x010B, 0xFFF5, 0x01F5, 0xFBFE, 0x05FE, 0xFB02, 0x0502, 0xFD05, + 0x0305, 0xFDFB, 0x03FB, 0x000E, 0x00F2, 0xFCFD, 0x04FD, 0xFC03, 0x0403, + 0xF9FF, 0x07FF, 0xF901, 0x0701, 0xFBFD, 0x05FD, 0xFB03, 0x0503, 0xFEF9, + 0x02F9, 0xFE07, 0x0207, 0xF8FF, 0x08FF, 0xF801, 0x0801, 0x00F1, 0x000F, + 0xFAFE, 0x06FE, 0xFA02, 0x0602, 0xFD06, 0x0306, 0xFDFA, 0x03FA, 0x0010, + 0x00F0, 0xFEF8, 0x02F8, 0xFE08, 0x0208, 0xFE0A, 0x020A, 0xFEF6, 0x02F6, + 0xFEF7, 0x02F7, 0xFE09, 0x0209, 0xFDF9, 0x03F9, 0xFD07, 0x0307, 0xF500, + 0x0B00, 0xFCFC, 0x04FC, 0xFC04, 0x0404, 0xF7FF, 0x09FF, 0xF701, 0x0901, + 0xF9FE, 0x07FE, 0xF902, 0x0702, 0x0011, 0x00EF, 0xFBFC, 0x05FC, 0xFB04, + 0x0504, 0xFC05, 0x0405, 0xFCFB, 0x04FB, 0xFAFD, 0x06FD, 0xF8FE, 0x08FE, + 0xF802, 0x0802, 0xFA03, 0x0603, 0xFDF7, 0x03F7, 0xFD09, 0x0309, 0xFB05, + 0x0505, 0xFBFB, 0x05FB, 0xF9FD, 0x07FD, 0xF903, 0x0703, 0x00EE, 0x0012, + 0xFC06, 0x0406, 0xFCFA, 0x04FA, 0xF7FE, 0x09FE, 0xF702, 0x0902, 0xFDF8, + 0x03F8, 0xFD08, 0x0308, 0xF6FF, 0x0AFF, 0xF601, 0x0A01, 0xFAFC, 0x06FC, + 0xFA04, 0x0604, 0xFA05, 0x0605, 0xFAFB, 0x06FB, 0xFF0C, 0x010C, 0xFFF4, + 0x01F4, 0xFCF8, 0x04F8, 0xFC08, 0x0408, 0xFB06, 0x0506, 0xFBFA, 0x05FA, + 0xFE0B, 0x020B, 0xFEF5, 0x02F5, 0xFCF7, 0x04F7, 0xFC09, 0x0409, 0xFD0A, + 0x030A, 0xFDF6, 0x03F6, 0xFCF9, 0x04F9, 0xFC07, 0x0407, 0xF8FD, 0x08FD, + 0xF803, 0x0803, 0xF9FC, 0x07FC, 0xF904, 0x0704, 0xF400, 0x0C00, 0xF7FD, + 0x09FD, 0xF703, 0x0903, 0xF8FC, 0x08FC, 0xF804, 0x0804, 0xFBF9, 0x05F9, + 0xFB07, 0x0507, 0xF905, 0x0705, 0xF9FB, 0x07FB, 0xFAF9, 0x06F9, 0xFA07, + 0x0607, 0xFBF8, 0x05F8, 0xFB08, 0x0508, 0xFD0B, 0x030B, 0xFDF5, 0x03F5, + 0xFA06, 0x0606, 0xFAFA, 0x06FA, 0xFC0A, 0x040A, 0xFCF6, 0x04F6, 0xFAF8, + 0x06F8, 0xFA08, 0x0608, 0xF9F9, 0x07F9, 0xF907, 0x0707, 0xFF0E, 0x010E, + 0xFFF2, 0x01F2, 0xFBF7, 0x05F7, 0xFB09, 0x0509, 0xFF0D, 0x010D, 0xFFF3, + 0x01F3, 0xF906, 0xF9FA, 0x0706, 0x07FA, 0x0609, 0xFAF7, 0x06F7, 0xFA09, + 0x0709, 0xF9F7, 0x07F7, 0xF909, 0xF8F9, 0x08F9, 0xF807, 0x0807, 0xF300, + 0x0D00, 0xFB0A, 0x050A, 0xFBF6, 0x05F6, 0xF6FE, 0x0AFE, 0xF602, 0x0A02, + 0xFC0B, 0xFCF5, 0x040B, 0x04F5, 0xF7FC, 0x09FC, 0xF704, 0x0904, 0xF805, + 0x0805, 0xF8FB, 0x08FB, 0xF6FC, 0x0AFC, 0xF604, 0x0A04, 0xFE0D, 0x020D, + 0xFEF3, 0x02F3, 0x0809, 0xF8F7, 0x08F7, 0xF809, 0xF806, 0xF8FA, 0x0806, + 0x08FA, 0x0AFD, 0xF603, 0x0A03, 0xF6FD, 0xFA0A, 0x060A, 0xFAF6, 0x06F6, + 0xF5FF, 0x0BFF, 0xF501, 0x0B01, 0xF705, 0x0905, 0xF7FB, 0x09FB, 0xFFF1, + 0x01F1, 0xFF0F, 0x010F, 0xF605, 0x0A05, 0xF6FB, 0x0AFB, 0xFF11, 0x0111, + 0xFFEF, 0x01EF, 0xF9F8, 0x07F8, 0xF908, 0x0708, 0xF90A, 0x070A, 0xF9F6, + 0x07F6, 0xFB0B, 0x05F5, 0xFBF5, 0x050B, 0x080A, 0xF80A, 0xF8F6, 0x08F6, + 0xF7F9, 0x09F9, 0xF706, 0xF7FA, 0x0906, 0xF707, 0x09FA, 0x0907, 0xF606, + 0xF6FA, 0x0A06, 0x0AFA, 0xF6F9, 0x0AF9, 0xF607, 0x0A07, 0xF200, 0x0E00, + 0xF70A, 0x090A, 0xF5FD, 0x0BFD, 0xF7F6, 0x09F6, 0xF503, 0x0B03, 0xF60A, + 0x0A0A, 0xF6F6, 0x0AF6, 0x0110, 0xFFF0, 0x01F0, 0xFF10, 0xF8F8, 0x08F8, + 0xF808, 0x0808, 0xF7F8, 0x09F8, 0xF708, 0x0908, 0xF100, 0x0F00, 0xFA0B, + 0xFAF5, 0x060B, 0x06F5, 0xF9F5, 0xF90B, 0x07F5, 0x070B, 0xF4FF, 0x0CFF, + 0xF401, 0x0C01, 0xFFEE, 0x0112, 0x01EE, 0xFF12, 0x0909, 0xF7F7, 0x09F7, + 0xF709, 0xF505, 0x0B05, 0xF5FB, 0x0BFB, 0xF4FD, 0x0CFD, 0xF403, 0x0C03, + 0xFE0C, 0x020C, 0xFEF4, 0x02F4, 0x0CFB, 0x0A09, 0xF6F7, 0x0AF7, 0xF405, + 0x0C05, 0xF4FB, 0xF609, 0xF8F5, 0x080B, 0x08F5, 0xF80B, 0xF5FE, 0x0BFE, + 0xF502, 0x0B02, 0xFD0D, 0x030D, 0xFDF3, 0x03F3, 0x020E, 0xFEF2, 0x02F2, + 0xFE0E, 0x0B0A, 0xF5F6, 0x0BF6, 0xF50A, 0x0A08, 0xF6F8, 0x0AF8, 0xF608, + 0xF5FC, 0xF504, 0x0B04, 0x0BFC, 0x030C, 0xFD0C, 0xFDF4, 0x03F4, 0xFEEE, + 0xFE12, 0x02EE, 0x0212, 0xF7F5, 0xF70B, 0x090B, 0x09F5, 0xF4FE, 0x0CFE, + 0xF402, 0x0C02, 0xF40A, 0xF4FC, 0x0C0A, 0xF4F6, 0x0CF6, 0xF404, 0x0C04, + 0x0CFC, 0x02F1, 0xFEF1, 0x020F, 0xFE0F, 0x040D, 0xFC0D, 0xFCF3, 0x04F3, + 0x0B09, 0xFE11, 0x0211, 0xF5F7, 0x0BF7, 0xFEEF, 0x02EF, 0xF509, 0xF506, + 0xF5FA, 0x0B06, 0x0BFA, 0xFC0C, 0x040C, 0xFCF4, 0x04F4, 0xF406, 0xF4FA, + 0x0C06, 0x0CFA, 0xF3FD, 0x0DFD, 0xF303, 0x0D03, 0xF000, 0x1000, 0xFB0D, + 0xFBF3, 0x05F3, 0x050D, 0xF5F9, 0x0BF9, 0xF507, 0x0B07, 0xF60B, 0xF6F5, + 0x0A0B, 0x0AF5, 0xF4F9, 0x0CF9, 0xF407, 0x0C07, 0xF5F5, 0xF50B, 0x0B0B, + 0x0BF5, 0xEF00, 0x1100, 0x060D, 0xFAF3, 0x06F3, 0xFA0D, 0x050C, 0xF3FE, + 0xFB0C, 0x0DFE, 0x05F4, 0xF302, 0x0D02, 0xFBF4, 0x03F1, 0x030F, 0xFD0F, + 0xFDF1, 0xEE00, 0x1200, 0xFA0C, 0x06F4, 0x060C, 0xFAF4, 0xF2FE, 0x0EFE, + 0xF3FF, 0x0DFF, 0xF301, 0x0D01, 0xF202, 0x0E02, 0xF5F8, 0x0BF8, 0xF508, + 0x0B08, 0xF90D, 0x070D, 0xF9F3, 0x07F3, 0x030E, 0x03F2, 0xFDF2, 0xFD0E, + 0xF304, 0x0D04, 0x0DFC, 0xF3FC, 0x0DFB, 0xF3FB, 0xF305, 0x0D05, 0x070C, + 0xF90C, 0xF9F4, 0x07F4, 0xFDEE, 0xF2FF, 0x0EFF, 0x0312, 0xFD12, 0xF201, + 0x03EE, 0x0E01, 0xF80C, 0x080C, 0x08F4, 0xF8F4, 0x0DFA, 0xFC0E, 0xFCF2, + 0x040E, 0x04F2, 0xF306, 0xF3FA, 0x0D06, 0xF4F8, 0x0CF8, 0xF408, 0x0C08, + 0x0C09, 0xF4F7, 0x0CF7, 0xF409, 0x04F1, 0xFC0F, 0x040F, 0xFCF1, 0x0EFD, + 0xF2FD, 0xF203, 0x0E03, 0x090C, 0xF70C, 0xF7F4, 0x09F4, 0xF3F8, 0x0DF8, + 0xF308, 0x0D08, 0x0A0C, 0xF60C, 0xF6F4, 0x0AF4, 0xF4F5, 0x0C0B, 0xF40B, + 0x0CF5, 0x05F1, 0xFB0F, 0xF1FF, 0x0FFF, 0xF101, 0x0F01, 0xFBF1, 0x050F, + 0xFB0E, 0x050E, 0xFBF2, 0x05F2, 0x06F1, 0xFA0F, 0x060F, 0xFAF1, 0x0DF9, + 0xF3F9, 0x0D07, 0xF307, 0x080D, 0xF80D, 0xF8F3, 0x08F3, 0x090D, 0xF70D, + 0xF7F3, 0x09F3, 0xF3F7, 0xFE10, 0xFEF0, 0x0DF7, 0x02F0, 0x0210, 0x0D09, + 0xF309, 0xF0FF, 0x10FF, 0xF001, 0x1001, 0x0A0D, 0xFA0E, 0xF60D, 0x060E, + 0xFAF2, 0x06F2, 0xF6F3, 0x0AF3, 0xF2FC, 0x0EFC, 0x0E04, 0xF204, 0xF205, + 0x0EFB, 0x0E05, 0xF2FB, 0xF90F, 0x070F, 0x07F1, 0xF9F1, 0x0310, 0xFDF0, + 0xFD10, 0x03F0, 0x0E08, 0xF2F8, 0x0EF8, 0xF208, 0xF30A, 0xF3F6, 0x0DF6, + 0x0D0A, 0x0F08, 0xF1F8, 0x0FF8, 0xF108, 0xF50C, 0x0B0C, 0x0FFD, 0x0F03, + 0x0BF4, 0xF103, 0xF5F4, 0xF1FD, 0xF20A, 0xF2F6, 0x0EF6, 0x0410, 0xFCF0, + 0xFC10, 0x04F0, 0x0E0A, 0xF207, 0x0311, 0xFC11, 0x0411, 0xF2F9, 0xFCEF, + 0xFD11, 0xFDEF, 0x0EF9, 0x03EF, 0x0E07, 0x04EF, 0x0510, 0xFBF0, 0xFB10, + 0x0511, 0x05F0, 0xFBEF, 0xFB11, 0x05EF, 0x0F07, 0xF1F9, 0x0FF9, 0xF107, + 0xFA10, 0x0610, 0xFAF0, 0x06F0, 0xF0FD, 0xF003, 0x10FD, 0x1003, 0xF1FE, + 0x0FFE, 0xF102, 0x0F02, 0xF9F2, 0x07F2, 0xF90E, 0x070E, 0xF30B, 0x0D0B, + 0xF80E, 0xF3F5, 0x08F2, 0x080E, 0x0DF5, 0xF8F2, 0xF50D, 0xF5F3, 0x0B0D, + 0x0EFA, 0x0BF3, 0xF206, 0xF2FA, 0x0E06, 0xF70E, 0x090E, 0xF7F2, 0x09F2, + 0x0FFB, 0x0FFC, 0xF1FB, 0xF104, 0x0F04, 0xF105, 0xF1FC, 0x0F05, 0x0F0A, + 0x0FF6, 0x0F06, 0xF1F6, 0xF106, 0xF1FA, 0xF10A, 0x0FFA, 0xEFFD, 0xEF01, + 0x11FD, 0xEFFF, 0x11FF, 0xEF03, 0x1101, 0x1103, 0x0C0C, 0xF40C, 0xF4F4, + 0x0CF4, 0x10FB, 0xF005, 0xF0FB, 0x1005, 0x1002, 0xF0FE, 0x10FE, 0xF002, + 0xF910, 0x08F0, 0xF8F0, 0xF9F0, 0x0810, 0xF810, 0x07F0, 0x0710, 0x10FC, + 0xF0FC, 0xF60E, 0xF6F2, 0x1004, 0x0AF2, 0xF004, 0x0A0E, 0x11FC, 0xEFFC, + 0xF30C, 0xEF04, 0x1104, 0xF3F4, 0x0D0C, 0x0DF4, 0x11FB, 0x1105, 0xEFFB, + 0xEF05, 0x080F, 0xF80F, 0x08F1, 0xF8F1, 0xFC12, 0x04EE, 0x0412, 0xFCEE, + 0xEFFE, 0xF5F2, 0x11FE, 0x0B0E, 0x10FA, 0xF50E, 0x0BF2, 0xEF02, 0x1006, + 0x1102, 0xF006, 0xF0FA, 0xFB12, 0xFBEE, 0x0512, 0x05EE, 0x10F8, 0xF4F2, + 0x1008, 0x0CF2, 0xF0F8, 0xF40E, 0x0C0E, 0xF008, 0xF20C, 0x0EF4, 0xF2F4, + 0x0E0C, 0xF20B, 0xF2F5, 0x09F0, 0xF7F0, 0x0910, 0xF710, 0x0E0B, 0x0EF5, + 0x0AF0, 0x0A10, 0xF6F0, 0xF610, 0xEEFC, 0xFAEF, 0x12FC, 0x1204, 0xEE04, + 0x0611, 0xFA11, 0x06EF, 0xEF06, 0x1106, 0xEFFA, 0x11FA, 0xEF08, 0xEFF8, + 0x11F8, 0x1108, 0xF7F1, 0x090F, 0xF70F, 0x09F1, 0x0E09, 0xF209, 0x0EF7, + 0xF2F7, 0xF0F6, 0x100A, 0x10F6, 0xF5F0, 0xF00A, 0x0BF0, 0xF510, 0x0B10, + 0x0D0E, 0xF30E, 0x0A0F, 0x0DF2, 0xF3F2, 0xF60F, 0x0AF1, 0xF6F1, 0x0CF3, + 0x0FF7, 0x0F09, 0xF40D, 0xF4F3, 0xF1F7, 0x0C0D, 0xF109, 0x07EE, 0xF912, + 0xFA12, 0xFAEE, 0x0712, 0xF9EE, 0x0612, 0x06EE, 0xF9EF, 0xF911, 0x0711, + 0x07EF, 0x0D0D, 0x0DF3, 0x0F0C, 0x110A, 0x11F6, 0xF10C, 0xF30D, 0xEFF6, + 0x0FF4, 0xEF0A, 0xF3F3, 0xF1F4, 0x10F9, 0xF007, 0xF0F9, 0x1007, 0xF8EF, + 0x0811, 0xF20D, 0x0EF3, 0x0E0D, 0xF2F3, 0xF811, 0x08EF, 0xF1F5, 0x0FF5, + 0xF10B, 0x0F0B, 0xF0F4, 0xF00C, 0xF2F2, 0x10F4, 0x0E0E, 0x0EF2, 0xF20E, + 0x100C, 0x09EF, 0x0911, 0xF7EF, 0xF711, 0xF611, 0x0A11, 0xF6EF, 0x0AEF, + 0x12FF, 0xEE01, 0x1201, 0xEEFF, 0xF5F1, 0x0BF1, 0xF50F, 0x0B0F, 0x10F5, + 0xEE06, 0xF00B, 0x1206, 0x12FA, 0xF0F5, 0xEEFA, 0x100B, 0x0CF0, 0xF410, + 0xF4F0, 0x0C10, 0x11F9, 0x0BEF, 0xF5EF, 0x0CF1, 0xEFF9, 0xF511, 0x0C0F, + 0xEF07, 0xF4F1, 0xF40F, 0x0B11, 0x1107, 0xEEFD, 0x12FD, 0xEE03, 0x1203, + 0x0DF0, 0xF3F0, 0xF310, 0x0D10, 0x0C11, 0x0CEF, 0xF4EF, 0xF411, 0x0EF0, + 0xF210, 0x0E10, 0xF2F0, 0x08EE, 0xF8EE, 0x0812, 0xF812, 0x110B, 0xF7EE, + 0xF712, 0x11F5, 0x0912, 0xEFF5, 0x09EE, 0xEF0B, 0xEEF9, 0x12F9, 0xEE07, + 0x1207, 0x0F0E, 0xF30F, 0x0D0F, 0x0DF1, 0xF10E, 0xF3F1, 0xF1F2, 0x0FF2, + 0xF6EE, 0xF612, 0x0AEE, 0x0A12, 0xF20F, 0x0E0F, 0xF2F1, 0x0EF1, 0xF0F7, + 0x1009, 0xF009, 0x10F7, 0xEEFB, 0x12FB, 0xEE05, 0x1205, 0x1202, 0x0FF3, + 0xEE08, 0xF1F3, 0x12F8, 0x12FE, 0xF10D, 0x1208, 0x0F0D, 0xEEFE, 0xEEF8, + 0xEE02, 0x0FF1, 0xF10F, 0xF1F1, 0x0F0F, 0x12F4, 0x11F4, 0x1109, 0xEFF4, + 0xEE0A, 0xEFF7, 0x110C, 0xEEF4, 0xEE0C, 0x11F7, 0xEF0C, 0x120C, 0xF110, + 0xF1F0, 0x120A, 0xEEF6, 0xEF09, 0x12F6, 0x0F10, 0x0FF0, 0x10F2, 0xF0F2, + 0x100E, 0xF00E, 0xEEF5, 0x0B12, 0x0BEE, 0xF512, 0x120B, 0x12F5, 0xF5EE, + 0xEE0B, 0x1209, 0x12F7, 0xEE09, 0xEEF7, 0xF4EE, 0x0C12, 0x0CEE, 0xF412, + 0x100D, 0x0D12, 0xF0F3, 0x0DEE, 0xF3EF, 0x0DEF, 0xF3EE, 0x0D11, 0xF312, + 0xF00D, 0xF311, 0x10F3, 0x11F3, 0xEFF3, 0x0E12, 0xF212, 0xF2EE, 0x0EEE, + 0xEF0D, 0x110D, 0x100F, 0xF0F1, 0xF00F, 0x10F1, 0x10F0, 0xF211, 0xF0F0, + 0xF010, 0x0EEF, 0xF2EF, 0x0E11, 0x1010, 0x120D, 0xEE0D, 0x12F3, 0xEEF3, + 0x11F1, 0xF111, 0xEFF2, 0x110F, 0xEF0E, 0xEF0F, 0x0FEF, 0x11F2, 0x0F11, + 0xF1EF, 0x110E, 0xEFF1, 0xEE0E, 0x120E, 0x12F2, 0xF1EE, 0x0FEE, 0xEEF2, + 0xF112, 0x0F12, 0xF0EE, 0x10EE, 0xF012, 0x1012, 0x11F0, 0xEF10, 0xEFF0, + 0x1110, 0xF0EF, 0x10EF, 0x1011, 0xF011, 0x11EF, 0xEF11, 0xEFEF, 0xEF12, + 0x11EE, 0x1112, 0xEFEE, 0x1111, 0xEE11, 0xEEEF, 0x12EF, 0x1211, 0x1212, + 0x12EE, 0xEEEE, 0xEE12, 0xEEF1, 0x12F1, 0xEE0F, 0x120F, 0xEE10, 0x1210, + 0xEEF0, 0x12F0, + /* U_1 motion vectors - 226 entries */ + 0x0001, 0x00FF, 0x0000, 0x0002, 0x00FE, 0x00FD, 0x0003, 0xFF00, 0x0100, + 0xFE00, 0x0200, 0x0101, 0xFFFF, 0x01FF, 0xFF01, 0x00FB, 0x0005, 0xFD00, + 0x0300, 0xFC00, 0x0400, 0x0004, 0x00FC, MV_ESC, 0x00FA, 0x0006, 0x0201, + 0xFEFF, 0x02FF, 0xFE01, 0xFFFD, 0x01FD, 0xFF03, 0x0103, 0xFEFD, 0x02FD, + 0xFE03, 0x0203, 0xFF02, 0x0102, 0xFFFE, 0x01FE, 0xFB00, 0x0500, 0xFDFD, + 0x03FD, 0xFD03, 0x0303, 0xFF04, 0x0104, 0xFFFC, 0x01FC, 0xFE02, 0x0202, + 0xFEFE, 0x02FE, 0xFA00, 0x0600, 0xFFFB, 0x01FB, 0xFF05, 0x0105, 0x00F9, + 0x0007, 0xFD02, 0x0302, 0xFDFE, 0x03FE, 0x0301, 0xFDFF, 0x03FF, 0xFD01, + 0xFEFB, 0x02FB, 0xFE05, 0x0205, 0x0401, 0xFCFF, 0x04FF, 0xFC01, 0xFE04, + 0x0204, 0xFEFC, 0x02FC, 0xFC02, 0x0402, 0xFCFE, 0x04FE, 0xFD04, 0x0304, + 0xFDFC, 0x03FC, 0xFFFA, 0x01FA, 0x0106, 0xFF06, 0xFC04, 0x0404, 0xFCFC, + 0x04FC, 0x0501, 0xFBFF, 0x05FF, 0xFB01, 0x0504, 0xFB04, 0xFBFC, 0x05FC, + 0xFE06, 0xFEFA, 0x02FA, 0x0206, 0xF900, 0x0700, 0xFB02, 0x0502, 0xFBFE, + 0x05FE, 0x0306, 0xFDFA, 0xFD06, 0x03FA, 0xFCFA, 0x0406, 0xFC06, 0x04FA, + 0x01F9, 0x0107, 0xFF07, 0xFFF9, 0xFE07, 0x02F9, 0xFEF9, 0x0207, 0xFDFB, + 0x03FB, 0xFD05, 0x0305, 0xFCFD, 0x04FD, 0xFC03, 0x0403, 0x0601, 0x06FF, + 0xFAFF, 0xFA01, 0x0701, 0xF9FF, 0x07FF, 0xF901, 0x03F9, 0xFD07, 0x0307, + 0xFDF9, 0xFBFA, 0x0506, 0xFB06, 0x05FA, 0xFCFB, 0x04FB, 0x0405, 0xFC05, + 0x0503, 0x05FD, 0xFB03, 0xFBFD, 0xFA03, 0xFAFA, 0x0606, 0x06FD, 0xFA06, + 0x0603, 0x06FA, 0xFAFD, 0xFA04, 0xFAFC, 0x0604, 0x06FC, 0x04F9, 0xFC07, + 0x0407, 0xFCF9, 0xFA02, 0xFBF9, 0x0507, 0xFAFE, 0x05F9, 0x06FE, 0x0602, + 0xFB07, 0x06F9, 0xFAF9, 0xFA07, 0x0607, 0x07FE, 0xF902, 0x0704, 0xF9FC, + 0xF904, 0xF9FE, 0x07FC, 0x0702, 0x07FA, 0x0706, 0xF906, 0xF9FA, 0x07FD, + 0x0703, 0xF903, 0xF9FD, 0xFB05, 0x0505, 0xFBFB, 0x05FB, 0xFA05, 0x07FB, + 0xF9FB, 0x0605, 0x0705, 0x06FB, 0xFAFB, 0xF905, 0xF9F9, 0xF907, 0x07F9, + 0x0707, + /* U_2 motion vectors - 442 entries */ + 0x0000, 0xFF00, 0x0100, 0x00FF, 0x0001, 0xFFFF, 0x01FF, 0xFF01, 0x0101, + MV_ESC, 0x0002, 0x00FE, 0xFE00, 0x0200, 0x0003, 0x00FD, 0xFEFF, 0x02FF, + 0xFE01, 0x0201, 0xFF02, 0x0102, 0xFFFE, 0x01FE, 0xFD00, 0x0300, 0x00FC, + 0x0005, 0xFDFF, 0x03FF, 0xFD01, 0x0301, 0xFF03, 0x0103, 0xFFFD, 0x01FD, + 0xFE02, 0x0202, 0xFEFE, 0x02FE, 0xFCFF, 0x04FF, 0xFC01, 0x0401, 0xFBFF, + 0x05FF, 0xFB01, 0x0501, 0x0004, 0x00FB, 0xFD02, 0x0302, 0xFDFE, 0x03FE, + 0xFF05, 0x0105, 0xFFFB, 0x01FB, 0x0006, 0x00FA, 0xFFFC, 0x01FC, 0xFF04, + 0x0104, 0xFE03, 0x0203, 0xFEFD, 0x02FD, 0xFC00, 0x0400, 0xFF06, 0x0106, + 0xFFFA, 0x01FA, 0xFEFC, 0x02FC, 0xFE04, 0x0204, 0xFD03, 0x0303, 0xFDFD, + 0x03FD, 0xFC02, 0x0402, 0xFCFE, 0x04FE, 0xFAFF, 0x06FF, 0xFA01, 0x0601, + 0xFC03, 0x0403, 0xFCFD, 0x04FD, 0xFB02, 0x0502, 0xFBFE, 0x05FE, 0xFB00, + 0x0500, 0xFA00, 0x0600, 0xFE05, 0x0205, 0xFEFB, 0x02FB, 0xFA02, 0x0602, + 0xFAFE, 0x06FE, 0xFD05, 0x0305, 0xFDFB, 0x03FB, 0xFB03, 0x0503, 0xFBFD, + 0x05FD, 0xFC05, 0x0405, 0xFCFB, 0x04FB, 0xFDFC, 0x03FC, 0x00F9, 0xFD04, + 0x0304, 0x0007, 0xF902, 0x0702, 0xFA03, 0x0603, 0xFAFD, 0xFA05, 0xFB05, + 0x06FD, 0x0505, 0x0605, 0xF9FE, 0xFE06, 0x0206, 0xFEFA, 0x07FE, 0x02FA, + 0xFAFB, 0xFBFB, 0x05FB, 0x06FB, 0xFD06, 0x0306, 0xFDFA, 0x03FA, 0x0406, + 0xFC06, 0xFCFA, 0x04FA, 0xFCFC, 0x04FC, 0xFC04, 0x0404, 0xF9FF, 0x07FF, + 0xF901, 0x0701, 0xFFF9, 0x01F9, 0x0107, 0xFF07, 0xFAFC, 0xFBFC, 0x05FC, + 0x06FC, 0xFA04, 0xFB04, 0x0504, 0x0604, 0xFB06, 0x0506, 0xFBFA, 0x05FA, + 0x0008, 0x00F8, 0xF9FC, 0x07FC, 0xF904, 0x0704, 0xFA06, 0x0606, 0xFAFA, + 0x06FA, 0x00F7, 0x0009, 0xF700, 0xF800, 0xF900, 0x0700, 0x0800, 0x0900, + 0xFEF9, 0x02F9, 0xFE07, 0x0207, 0xF8FF, 0xFF08, 0x0108, 0xFFF8, 0x08FF, + 0x01F8, 0xF801, 0x0801, 0x0307, 0xFDF9, 0x03F9, 0xFD07, 0xF7FF, 0x09FF, + 0xF701, 0x0901, 0xF8FC, 0xF903, 0x08FC, 0xF804, 0xF9FD, 0x0804, 0xF905, + 0x0705, 0x0703, 0xF9FB, 0x07FD, 0x07FB, 0xFC07, 0x01F7, 0xFCF9, 0x04F9, + 0x0407, 0xFF09, 0x0109, 0xFFF7, 0x0802, 0xFAF9, 0xFBF9, 0x05F9, 0x06F9, + 0xFB07, 0xF8FE, 0xFA07, 0x0507, 0x08FE, 0x0607, 0xF802, 0x0902, 0xF803, + 0x0803, 0xF8FD, 0x08FD, 0xF805, 0xF7FE, 0x0805, 0x00F6, 0x09FE, 0x000A, + 0xF8FB, 0x08FB, 0xF702, 0x07FA, 0xF906, 0xFEF8, 0x0208, 0xF9FA, 0xF6FF, + 0xFD08, 0x0308, 0xFDF8, 0x0AFF, 0x0706, 0x02F8, 0x03F8, 0xF601, 0xFE08, + 0x0A01, 0xFE09, 0x02F7, 0x0905, 0xF705, 0xF7FB, 0x0209, 0xFEF7, 0x09FB, + 0xF603, 0xFC09, 0xF703, 0x03F7, 0xF605, 0x04F7, 0x0903, 0x0A03, 0x09FD, + 0xFBF7, 0x0AFD, 0x0A05, 0x05F7, 0xFD09, 0x0A00, 0xFC08, 0xF7FD, 0x0408, + 0xFCF8, 0xFB09, 0x0509, 0x0AFB, 0xF600, 0xF6FB, 0xFCF7, 0xF6FD, 0x04F8, + 0x0309, 0xFDF7, 0x0409, 0x01F6, 0xFA09, 0xF9F9, 0xFF0A, 0x08FA, 0xFBF8, + 0xFFF6, 0x07F9, 0x0609, 0xFB08, 0x06F7, 0xF8FA, 0x0906, 0xF907, 0x0508, + 0xF706, 0xF7FA, 0x09FA, 0xFAF7, 0x010A, 0x0707, 0x0806, 0x05F8, 0xF806, + 0x0A06, 0xF7FC, 0xF606, 0xFEF6, 0xF6FE, 0x0608, 0xF908, 0x0A02, 0xF602, + 0x020A, 0xFD0A, 0x09FC, 0x0AFA, 0xFDF6, 0x0708, 0xF9F8, 0x0AFE, 0xFAF8, + 0xF704, 0xFA08, 0x06F8, 0x030A, 0x02F6, 0xF6FA, 0xFE0A, 0x07F8, 0x0904, + 0x03F6, 0x04F6, 0xFBF6, 0x08F9, 0xF8F9, 0x05F6, 0xFB0A, 0x0807, 0xFC0A, + 0xF807, 0x040A, 0x050A, 0xFCF6, 0x0709, 0x060A, 0x07F7, 0xF9F7, 0xF909, + 0xFAF6, 0xFA0A, 0x06F6, 0x0AFC, 0xF808, 0x09F7, 0x08F8, 0xF708, 0x09F9, + 0xF8F7, 0xF707, 0x0809, 0xF7F9, 0xF8F8, 0x09F8, 0xF709, 0xF6FC, 0x08F7, + 0xF809, 0x0907, 0xF604, 0xF90A, 0x0909, 0xF9F6, 0xF7F8, 0x0A04, 0x070A, + 0x07F6, 0x0808, 0x0908, 0xF7F7, 0x080A, 0x08F6, 0xF8F6, 0xF70A, 0x09F6, + 0xF80A, 0x090A, 0xF7F6, 0x0A09, 0x0AF8, 0xF6F6, 0x0AF9, 0xF6F7, 0x0A07, + 0x0A0A, 0x0AF7, 0x0AF6, 0xF60A, 0x0A08, 0xF6F9, 0xF609, 0xF607, 0xF6F8, + 0xF608, + /* V_1 motion vectors - 226 entries */ + 0x0001, 0x00FF, 0x0000, 0xFF00, 0x0100, 0x0002, 0x00FE, 0x00FD, 0x0003, + 0x0004, 0x00FC, 0x00FB, 0x0005, 0x0101, 0xFFFF, 0x01FF, 0xFF01, 0xFE00, + 0x0200, 0xFD00, 0x0300, MV_ESC, 0xFF02, 0x0102, 0xFFFE, 0x01FE, 0xFC00, + 0x0400, 0x0201, 0xFEFF, 0x02FF, 0xFE01, 0xFFFD, 0x01FD, 0xFF03, 0x0103, + 0x00FA, 0x0006, 0xFE02, 0x0202, 0xFEFE, 0x02FE, 0xFD02, 0x0302, 0xFDFE, + 0x03FE, 0xFEFD, 0xFC02, 0x02FD, 0x0402, 0xFE03, 0xFCFE, 0x0203, 0x04FE, + 0xFF04, 0x0104, 0xFFFC, 0x01FC, 0xFB00, 0x0500, 0x00F9, 0x0007, 0xFE04, + 0x0204, 0xFEFC, 0x02FC, 0xFA00, 0x0600, 0xFD04, 0x0304, 0xFDFC, 0x03FC, + 0xFFFB, 0x01FB, 0xFF05, 0x0105, 0x0301, 0xFDFF, 0x03FF, 0xFD01, 0x01F9, + 0x0107, 0xFF07, 0xFFF9, 0x0401, 0xFCFF, 0x04FF, 0xFC01, 0xFEFB, 0x02FB, + 0xFE05, 0x0205, 0xFF06, 0x0106, 0xFFFA, 0x01FA, 0x0501, 0xFBFF, 0x05FF, + 0xFB01, 0x0206, 0xFEFA, 0x02FA, 0xFE06, 0xF900, 0x0700, 0xFB02, 0x0502, + 0xFBFE, 0x05FE, 0xFDFB, 0x0305, 0x03FB, 0xFD05, 0xFDFD, 0x03FD, 0xFD03, + 0x0303, 0x0404, 0xFC04, 0xFCFC, 0x04FC, 0xFA02, 0x0602, 0xFAFE, 0x06FE, + 0xFCFD, 0x04FD, 0x0403, 0xFC03, 0x05FD, 0xFB03, 0x0503, 0xFBFD, 0x02F9, + 0xFE07, 0xFEF9, 0x0207, 0x0601, 0xFAFF, 0xFDFA, 0xFD06, 0x06FF, 0x03FA, + 0xFA01, 0x0306, 0x0504, 0xFB04, 0xFBFC, 0x05FC, 0xFAFC, 0xFA04, 0x0604, + 0x06FC, 0xFA03, 0x0603, 0x06FD, 0xFAFD, 0xF904, 0x0704, 0xF9FC, 0x07FC, + 0x0307, 0xFD07, 0x03F9, 0xFDF9, 0xFCF9, 0xFC07, 0x04F9, 0x0407, 0xFCFB, + 0xFC05, 0x0405, 0x04FB, 0xFBFB, 0xFB05, 0x0505, 0x05FB, 0x04FA, 0xFCFA, + 0x0406, 0xFC06, 0xF901, 0x0701, 0xF9FF, 0x07FF, 0x05F9, 0x0507, 0xFBF9, + 0xFB07, 0x0702, 0xF902, 0xF9FE, 0x07FE, 0x06FB, 0x0605, 0xFAFB, 0xFA05, + 0x0506, 0xF9FD, 0xFB06, 0xFBFA, 0xF903, 0x07FD, 0x05FA, 0x0703, 0xF905, + 0xF9FB, 0x0705, 0x07FB, 0xFA06, 0x0606, 0xFA07, 0x0607, 0xFAF9, 0x06F9, + 0x06FA, 0xFAFA, 0xF906, 0x07FA, 0xF9FA, 0x0706, 0xF907, 0xF9F9, 0x07F9, + 0x0707, + /* V_2 motion vectors - 442 elements */ + 0x0000, 0x00FF, 0x0001, 0xFF00, 0x0100, 0xFFFF, 0x01FF, 0xFF01, 0x0101, + MV_ESC, 0xFE00, 0x0200, 0xFEFF, 0x02FF, 0xFE01, 0x0201, 0x0002, 0x00FE, + 0x00FC, 0x0003, 0x0004, 0x00FD, 0x0005, 0x00FB, 0xFDFF, 0x03FF, 0xFD01, + 0x0301, 0xFFFC, 0x01FC, 0xFF03, 0x0103, 0xFF04, 0x0104, 0xFFFD, 0x01FD, + 0xFD00, 0x0300, 0xFF02, 0x0102, 0xFFFE, 0x01FE, 0xFC00, 0x0400, 0xFEFC, + 0x02FC, 0xFE03, 0x0203, 0xFE04, 0x0204, 0xFEFD, 0x02FD, 0xFCFF, 0x04FF, + 0xFC01, 0x0401, 0xFE02, 0x0202, 0xFEFE, 0x02FE, 0xFD02, 0x0302, 0xFDFE, + 0x03FE, 0xFDFC, 0x03FC, 0xFD03, 0x0303, 0xFD04, 0x0304, 0xFDFD, 0x03FD, + 0xFF05, 0x0105, 0xFFFB, 0x01FB, 0x0006, 0x00FA, 0xFBFF, 0x05FF, 0xFB01, + 0x0501, 0xFAFF, 0x06FF, 0xFA01, 0x0601, 0x000A, 0xFF06, 0x0106, 0xFFFA, + 0x01FA, 0xFE05, 0x0205, 0xFB00, 0x0500, 0xFEFB, 0x02FB, 0xFE06, 0x0206, + 0xFEFA, 0x02FA, 0xFC02, 0x0402, 0xFCFE, 0x04FE, 0xFA00, 0x0600, 0xFCFC, + 0xFC03, 0x04FC, 0x0403, 0xFC04, 0xFCFD, 0x0404, 0x04FD, 0xFB02, 0x0502, + 0xFBFE, 0x05FE, 0xFD05, 0x0305, 0xFDFB, 0x03FB, 0x00F7, 0x00F9, 0x00F6, + 0x0007, 0x0009, 0xFA02, 0xFBFC, 0x0602, 0xFB03, 0x05FC, 0x0503, 0xFB04, + 0xFBFD, 0x0504, 0x05FD, 0xFAFE, 0x06FE, 0xF9FF, 0x07FF, 0xF901, 0x0701, + 0xFC05, 0x0405, 0xFCFB, 0x04FB, 0xFAFC, 0xFA03, 0x06FC, 0x0603, 0xFFF9, + 0xFA04, 0x01F9, 0xFAFD, 0x0604, 0xFB05, 0x06FD, 0x0505, 0xFF07, 0x0107, + 0xFBFB, 0x05FB, 0xFC06, 0xFD06, 0x0306, 0x0406, 0xFCFA, 0xFDFA, 0x03FA, + 0x04FA, 0xF9FC, 0x01F7, 0xF903, 0x07FC, 0x0703, 0xF904, 0xF9FD, 0x0704, + 0x07FD, 0xFB06, 0x0506, 0xFBFA, 0x05FA, 0xFF09, 0x0109, 0xFFF7, 0xF900, + 0x0700, 0xF8FF, 0x08FF, 0xF801, 0x0801, 0xFEF9, 0x02F9, 0xFA06, 0x0606, + 0xFAFA, 0xFE07, 0x06FA, 0xF800, 0x0800, 0x0207, 0xF8FC, 0xF803, 0x08FC, + 0x0803, 0xF804, 0xF8FD, 0x0804, 0x08FD, 0xFF08, 0x0108, 0xFFF8, 0xF700, + 0x00F8, 0x01F8, 0x0900, 0x0008, 0xF902, 0x0702, 0xF9FE, 0x07FE, 0xFDF9, + 0x03F9, 0x0307, 0xFD07, 0xF7FF, 0x09FF, 0xF701, 0x0901, 0xFA05, 0x0605, + 0xFAFB, 0x06FB, 0xFBF9, 0xFCF9, 0x04F9, 0x05F9, 0x0507, 0xFB07, 0x0407, + 0xFC07, 0xFE09, 0x02F7, 0x0209, 0xF600, 0x0A00, 0xFEF7, 0x0802, 0x0705, + 0xF905, 0xFFF6, 0xF8FE, 0x08FE, 0x01F6, 0x010A, 0xF9FB, 0xFF0A, 0x07FB, + 0xF802, 0x03F7, 0x0309, 0xFD09, 0xFDF7, 0x0607, 0x0902, 0xFAF9, 0x0409, + 0x04F7, 0x06F9, 0xF7FE, 0x09FE, 0xFA07, 0xFC09, 0xFCF7, 0xF702, 0xF705, + 0x07FA, 0xF9F9, 0x0707, 0xF7FB, 0x07F9, 0x0805, 0x0A05, 0xF805, 0xF906, + 0x0706, 0xF9FA, 0xF907, 0xF605, 0x0905, 0xF6FB, 0xF8FB, 0x08FB, 0x09FB, + 0x0AFB, 0xFE08, 0x0509, 0xFEF6, 0x020A, 0xF6FF, 0xFD08, 0x0308, 0xFDF8, + 0xFB09, 0x0208, 0x0AFF, 0xFE0A, 0x02F8, 0xFBF7, 0x02F6, 0x03F8, 0xFEF8, + 0xF601, 0x05F7, 0x0A01, 0xFB08, 0xF7FC, 0x0904, 0xF703, 0x0A04, 0x09FC, + 0x0AFC, 0x0903, 0xF604, 0x0608, 0x09FD, 0xFCF8, 0xFAF8, 0xF7FD, 0x05F8, + 0xFA08, 0x0508, 0xF704, 0xF603, 0xFC08, 0x0A03, 0xF6FC, 0x04F8, 0xFBF8, + 0x06F8, 0xF6FD, 0x0408, 0x0AFD, 0xF706, 0x08F9, 0xF908, 0xF8F9, 0x040A, + 0xF602, 0x0A02, 0x0708, 0x08FA, 0xFDF6, 0x0AFE, 0xF806, 0xFCF6, 0xF7FA, + 0x0906, 0xFC0A, 0x0807, 0x07F8, 0xF6FE, 0x03F6, 0x030A, 0x09FA, 0xF8FA, + 0xF9F8, 0xFD0A, 0x0806, 0xF807, 0x04F6, 0xF7F9, 0xF707, 0xFBF6, 0x09F9, + 0x05F6, 0xFB0A, 0x0907, 0x050A, 0xF6F9, 0x0AF9, 0x0A07, 0xF607, 0xF909, + 0xF8F6, 0xF70A, 0x09F6, 0xFA09, 0x07F7, 0x0609, 0x070A, 0xFAF7, 0x06F7, + 0xF90A, 0xFA0A, 0x090A, 0xFAF6, 0xF9F6, 0xF7F6, 0x080A, 0xF80A, 0x06F6, + 0xF9F7, 0x07F6, 0x0709, 0x060A, 0x08F6, 0x0909, 0x09F8, 0xF7F7, 0x08F8, + 0xF8F8, 0xF709, 0x0809, 0x0808, 0xF808, 0x0908, 0xF7F8, 0xF8F7, 0x08F7, + 0xF708, 0x09F7, 0xF809, 0x0AFA, 0xF60A, 0x0A06, 0x0AF6, 0xF609, 0xF6F7, + 0xF6FA, 0x0A09, 0x0AF7, 0xF6F8, 0x0A0A, 0x0AF8, 0xF606, 0x0A08, 0xF608, + 0xF6F6, +}; + +static const uint8_t clv_bias_len_counts[][16] = { + { 1, 1, 1, 0, 2, 0, 4, 3, 3, 6, 5, 10, 16, 7, 17, 2 }, + { 1, 0, 2, 2, 0, 4, 2, 6, 4, 8, 6, 10, 9, 7, 23, 14 }, + { 0, 2, 1, 3, 2, 3, 4, 4, 8, 8, 8, 7, 7, 10, 21, 6 }, + { 1, 1, 1, 0, 2, 1, 3, 2, 4, 4, 2, 8, 6, 2, 3, 2 }, + { 1, 0, 2, 2, 1, 3, 2, 4, 4, 4, 4, 4, 2, 7, 6, 8 }, + { 1, 1, 1, 0, 2, 2, 1, 3, 2, 4, 3, 5, 6, 6, 3, 2 }, + { 1, 0, 2, 2, 2, 1, 3, 2, 4, 5, 1, 4, 10, 2, 3, 2 }, +}; + +#define BIAS_ESC 1 +static const uint16_t clv_bias_syms[] = { + /* Y_1 bias values - 78 entries */ + 0x0000, 0xFFFC, 0x0004, 0xFFF8, 0x0008, 0xFFF4, 0x000C, 0xFFF0, 0x0010, + 0xFFEC, 0x0014, 0xFFE8, 0x0018, 0xFFE4, 0x001C, 0x0020, 0xFFE0, 0x0024, + 0xFFDC, 0x0028, 0xFFD8, 0x002C, 0xFFD4, 0x0030, 0xFFD0, 0xFFCC, 0x0034, + 0xFFC8, 0x0038, BIAS_ESC, 0xFFC4, 0x003C, 0xFFC0, 0x0040, 0xFFBC, 0x0044, + 0xFFB8, 0x0048, 0xFFB4, 0x004C, 0xFFB0, 0x0050, 0xFFAC, 0x0054, 0xFFA8, + 0x0058, 0xFFA4, 0x005C, 0x0060, 0xFFA0, 0x0064, 0xFF9C, 0x0068, 0xFF98, + 0x006C, 0xFF94, 0x0070, 0xFF90, 0x0074, 0xFF8C, 0xFF88, 0x0078, 0x007C, + 0xFF84, 0xFF80, 0x0080, 0x0088, 0xFF78, 0xFF7C, 0x0084, 0x008C, 0xFF74, + 0x0090, 0xFF70, 0x0094, 0xFF6C, 0xFF68, 0x0098, + /* Y_2 bias values - 98 entries */ + 0x0000, 0xFFFC, 0x0004, 0xFFF8, 0x0008, 0xFFF4, 0x000C, 0xFFF0, 0x0010, + 0xFFEC, 0x0014, 0xFFE8, 0x0018, 0xFFE4, 0x001C, 0xFFE0, 0x0020, 0xFFDC, + 0x0024, 0xFFD8, 0x0028, 0xFFD4, 0x002C, 0xFFD0, 0x0030, 0xFFCC, 0x0034, + 0xFFC8, 0x0038, 0x003C, 0xFFC4, 0x0040, 0xFFC0, 0xFFBC, 0x0044, 0x0048, + 0xFFB8, 0x004C, 0xFFB4, 0x0050, 0xFFB0, 0x0054, 0xFFAC, 0xFFA8, 0x0058, + 0x005C, 0xFFA4, 0x0060, 0xFFA0, 0x0064, 0xFF9C, 0xFF98, 0x0068, 0x006C, + 0xFF94, 0x0070, 0xFF90, 0x0074, 0xFF8C, 0xFF88, 0x0078, 0xFF84, 0x007C, + 0xFF80, 0x0080, 0xFF7C, 0x0084, BIAS_ESC, 0xFF78, 0x0088, 0x008C, 0xFF74, + 0x0090, 0xFF70, 0x0094, 0xFF6C, 0xFF64, 0x009C, 0xFF68, 0x0098, 0xFF60, + 0x00A0, 0xFF5C, 0x00A4, 0x00A8, 0xFF58, 0x00AC, 0xFF54, 0xFF50, 0x00B0, + 0x00B4, 0xFF4C, 0xFF48, 0x00B8, 0xFF44, 0x00BC, 0xFF40, 0x00C0, + /* Y_3 bias values - 94 entries */ + 0x0000, 0xFFFC, 0x0004, 0xFFF8, 0x0008, 0xFFF4, 0x000C, 0xFFF0, 0x0010, + 0xFFEC, 0x0014, 0xFFE8, 0x0018, 0xFFE4, 0x001C, 0xFFE0, 0x0020, 0xFFDC, + 0x0024, 0xFFD8, 0x0028, 0xFFD4, 0x002C, 0xFFD0, 0x0030, 0xFFCC, 0x0034, + 0xFFC8, 0x0038, 0xFFC4, 0x003C, 0xFFC0, 0x0040, 0x0044, 0xFFBC, 0x0048, + 0xFFB8, 0x004C, 0xFFB4, 0x0050, 0xFFB0, 0x0054, 0xFFAC, 0x0058, 0xFFA8, + 0x005C, 0xFFA4, 0xFFA0, 0x0060, 0x0064, 0xFF9C, 0x0068, 0xFF98, 0x006C, + 0xFF94, 0xFF90, 0x0070, 0xFF8C, 0x0074, 0x0078, 0xFF88, 0xFF84, 0x007C, + 0xFF80, 0x0080, 0x0084, 0xFF7C, 0x0088, 0xFF78, 0x008C, 0xFF74, 0xFF70, + 0x0090, 0x0094, 0xFF6C, 0x0098, 0xFF68, 0xFF64, 0x009C, 0xFF60, 0x00A0, + 0xFF5C, 0x00A4, BIAS_ESC, 0xFF58, 0x00A8, 0x00AC, 0xFF54, 0xFF50, 0x00B0, + 0xFF4C, 0x00B4, 0x00B8, 0xFF48, + /* U_1 bias values - 42 entries */ + 0x0000, 0xFFFC, 0x0004, 0xFFF8, 0x0008, 0xFFF4, 0x000C, 0xFFF0, 0x0010, + 0xFFEC, 0x0014, 0x0018, 0xFFE8, 0xFFE4, 0x001C, 0xFFE0, 0x0020, 0xFFDC, + 0x0024, 0xFFD8, 0x0028, 0x002C, 0xFFD4, 0x0030, 0xFFCC, 0xFFD0, 0x0034, + 0xFFC8, 0x0038, 0x003C, 0xFFC4, 0xFFC0, 0x0040, 0xFFBC, 0x0044, 0xFFB8, + 0x0048, 0xFFB4, 0x004C, 0x0050, 0xFFB0, BIAS_ESC, + /* U_2 bias values - 54 entries */ + 0x0000, 0xFFFC, 0x0004, 0xFFF8, 0x0008, 0xFFF4, 0x000C, 0xFFF0, 0x0010, + 0x0014, 0xFFEC, 0x0018, 0xFFE8, 0x001C, 0xFFE4, 0x0020, 0xFFE0, 0xFFDC, + 0x0024, 0xFFD8, 0x0028, 0xFFD4, 0x002C, 0x0030, 0xFFD0, 0x0034, 0xFFCC, + 0x0038, 0xFFC8, 0x003C, 0xFFC4, 0x0040, 0xFFC0, 0xFFBC, 0x0044, 0xFFB4, + 0xFFB8, 0x0048, 0x004C, BIAS_ESC, 0x0058, 0xFFB0, 0xFFA8, 0x0054, 0xFFAC, + 0x0050, 0xFF9C, 0x005C, 0xFFA0, 0x0068, 0xFF98, 0xFFA4, 0x0064, 0x0060, + /* V_1 bias values - 42 entries */ + 0x0000, 0xFFFC, 0x0004, 0xFFF8, 0x0008, 0xFFF4, 0x000C, 0xFFF0, 0x0010, + 0xFFEC, 0x0014, 0x0018, 0xFFE8, 0xFFE4, 0x001C, 0xFFE0, 0x0020, 0xFFDC, + 0x0024, 0xFFD8, 0x0028, 0x002C, 0xFFD4, 0x0030, 0xFFD0, 0xFFCC, 0x0034, + 0xFFC8, 0x0038, 0x003C, 0xFFC4, BIAS_ESC, 0xFFC0, 0x0040, 0xFFBC, 0x0044, + 0xFFB8, 0x0048, 0xFFB4, 0x004C, 0x0050, 0xFFB0, + /* V_2 bias values - 44 entries */ + 0x0000, 0xFFFC, 0x0004, 0xFFF8, 0x0008, 0xFFF4, 0x000C, 0xFFF0, 0x0010, + 0xFFEC, 0x0014, 0xFFE8, 0x0018, 0x001C, 0xFFE4, 0xFFE0, 0x0020, 0xFFDC, + 0x0024, 0x0028, 0xFFD8, 0x002C, 0xFFD4, 0x0030, 0xFFD0, 0xFFCC, 0x0034, + 0xFFC8, 0x0038, 0x0040, 0xFFC4, 0xFFC0, 0x003C, 0x0044, 0xFFBC, 0xFFB8, + 0x0048, 0xFFB4, 0x004C, BIAS_ESC, 0xFFB0, 0x0054, 0xFFAC, 0x0050 }; #endif /* AVCODEC_CLEARVIDEODATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/cljrdec.c ffmpeg-4.4/libavcodec/cljrdec.c --- ffmpeg-4.2.2/libavcodec/cljrdec.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cljrdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -90,5 +90,6 @@ .init = decode_init, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/cllc.c ffmpeg-4.4/libavcodec/cllc.c --- ffmpeg-4.2.2/libavcodec/cllc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cllc.c 2021-04-08 21:28:39.000000000 +0000 @@ -46,19 +46,15 @@ { uint8_t symbols[256]; uint8_t bits[256]; - uint16_t codes[256]; - int num_lens, num_codes, num_codes_sum, prefix; + int num_lens, num_codes, num_codes_sum; int i, j, count; - prefix = 0; count = 0; num_codes_sum = 0; num_lens = get_bits(gb, 5); if (num_lens > VLC_BITS * VLC_DEPTH) { - vlc->table = NULL; - av_log(ctx->avctx, AV_LOG_ERROR, "To long VLCs %d\n", num_lens); return AVERROR_INVALIDDATA; } @@ -68,8 +64,6 @@ num_codes_sum += num_codes; if (num_codes_sum > 256) { - vlc->table = NULL; - av_log(ctx->avctx, AV_LOG_ERROR, "Too many VLCs (%d) to be read.\n", num_codes_sum); return AVERROR_INVALIDDATA; @@ -78,20 +72,13 @@ for (j = 0; j < num_codes; j++) { symbols[count] = get_bits(gb, 8); bits[count] = i + 1; - codes[count] = prefix++; count++; } - if (prefix > (65535 - 256)/2) { - vlc->table = NULL; - return AVERROR_INVALIDDATA; - } - - prefix <<= 1; } - return ff_init_vlc_sparse(vlc, VLC_BITS, count, bits, 1, 1, - codes, 2, 2, symbols, 1, 1, 0); + return ff_init_vlc_from_lengths(vlc, VLC_BITS, count, bits, 1, + symbols, 1, 1, 0, 0, ctx->avctx); } /* @@ -247,7 +234,7 @@ for (i = 0; i < 4; i++) { ret = read_code_table(ctx, gb, &vlc[i]); if (ret < 0) { - for (j = 0; j <= i; j++) + for (j = 0; j < i; j++) ff_free_vlc(&vlc[j]); av_log(ctx->avctx, AV_LOG_ERROR, @@ -290,7 +277,7 @@ for (i = 0; i < 3; i++) { ret = read_code_table(ctx, gb, &vlc[i]); if (ret < 0) { - for (j = 0; j <= i; j++) + for (j = 0; j < i; j++) ff_free_vlc(&vlc[j]); av_log(ctx->avctx, AV_LOG_ERROR, @@ -343,7 +330,7 @@ for (i = 0; i < 2; i++) { ret = read_code_table(ctx, gb, &vlc[i]); if (ret < 0) { - for (j = 0; j <= i; j++) + for (j = 0; j < i; j++) ff_free_vlc(&vlc[j]); av_log(ctx->avctx, AV_LOG_ERROR, @@ -483,19 +470,6 @@ return avpkt->size; } -#if HAVE_THREADS -static int cllc_init_thread_copy(AVCodecContext *avctx) -{ - CLLCContext *ctx = avctx->priv_data; - - ctx->avctx = avctx; - ctx->swapped_buf = NULL; - ctx->swapped_buf_size = 0; - - return 0; -} -#endif - static av_cold int cllc_decode_close(AVCodecContext *avctx) { CLLCContext *ctx = avctx->priv_data; @@ -526,7 +500,6 @@ .id = AV_CODEC_ID_CLLC, .priv_data_size = sizeof(CLLCContext), .init = cllc_decode_init, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(cllc_init_thread_copy), .decode = cllc_decode_frame, .close = cllc_decode_close, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, diff -Nru ffmpeg-4.2.2/libavcodec/cngdec.c ffmpeg-4.4/libavcodec/cngdec.c --- ffmpeg-4.2.2/libavcodec/cngdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cngdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -173,7 +173,7 @@ .close = cng_decode_close, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/cngenc.c ffmpeg-4.4/libavcodec/cngenc.c --- ffmpeg-4.2.2/libavcodec/cngenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cngenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -37,8 +37,8 @@ { CNGContext *p = avctx->priv_data; ff_lpc_end(&p->lpc); - av_free(p->samples32); - av_free(p->ref_coef); + av_freep(&p->samples32); + av_freep(&p->ref_coef); return 0; } @@ -58,10 +58,8 @@ return ret; p->samples32 = av_malloc_array(avctx->frame_size, sizeof(*p->samples32)); p->ref_coef = av_malloc_array(p->order, sizeof(*p->ref_coef)); - if (!p->samples32 || !p->ref_coef) { - cng_encode_close(avctx); + if (!p->samples32 || !p->ref_coef) return AVERROR(ENOMEM); - } return 0; } @@ -113,4 +111,5 @@ .close = cng_encode_close, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/codec2utils.c ffmpeg-4.4/libavcodec/codec2utils.c --- ffmpeg-4.2.2/libavcodec/codec2utils.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/codec2utils.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ #include "internal.h" #include "libavcodec/codec2utils.h" +#if LIBAVCODEC_VERSION_MAJOR < 59 int avpriv_codec2_mode_bit_rate(void *logctx, int mode) { int frame_size = avpriv_codec2_mode_frame_size(logctx, mode); @@ -37,7 +38,7 @@ int avpriv_codec2_mode_frame_size(void *logctx, int mode) { - int frame_size_table[AVPRIV_CODEC2_MODE_MAX+1] = { + int frame_size_table[CODEC2_MODE_MAX+1] = { 160, // 3200 160, // 2400 320, // 1600 @@ -49,7 +50,7 @@ 320, // 700C }; - if (mode < 0 || mode > AVPRIV_CODEC2_MODE_MAX) { + if (mode < 0 || mode > CODEC2_MODE_MAX) { av_log(logctx, AV_LOG_ERROR, "unknown codec2 mode %i, can't find frame_size\n", mode); return 0; } else { @@ -59,7 +60,7 @@ int avpriv_codec2_mode_block_align(void *logctx, int mode) { - int block_align_table[AVPRIV_CODEC2_MODE_MAX+1] = { + int block_align_table[CODEC2_MODE_MAX+1] = { 8, // 3200 6, // 2400 8, // 1600 @@ -71,10 +72,11 @@ 4, // 700C }; - if (mode < 0 || mode > AVPRIV_CODEC2_MODE_MAX) { + if (mode < 0 || mode > CODEC2_MODE_MAX) { av_log(logctx, AV_LOG_ERROR, "unknown codec2 mode %i, can't find block_align\n", mode); return 0; } else { return block_align_table[mode]; } } +#endif diff -Nru ffmpeg-4.2.2/libavcodec/codec2utils.h ffmpeg-4.4/libavcodec/codec2utils.h --- ffmpeg-4.2.2/libavcodec/codec2utils.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/codec2utils.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,17 +24,19 @@ #include +#include "version.h" + //Highest mode we're willing to use. //Don't want to let users accidentally produce files that can't be decoded in the future. //CODEC2_MODE_WB (9) is experimental/unstable as of 2017-11-23. -#define AVPRIV_CODEC2_MODE_MAX 8 //CODEC2_MODE_700C +#define CODEC2_MODE_MAX 8 //CODEC2_MODE_700C //Used by both codec2raw demuxer and libcodec2 encoder. //The integers match the values in codec2.h, so "3200" -> CODEC2_MODE_3000 = 0 and so on. //It is possible that we're linked to a version of libcodec2 that lacks some of these modes. //For example Debian stretch ships with libcodec2.so.0.4 which lacks CODEC2_MODE_700C. -#define AVPRIV_CODEC2_AVOPTIONS(desc, classname, min_val, default_val, option_flags) \ - { "mode", desc, offsetof(classname, mode), AV_OPT_TYPE_INT, {.i64 = default_val}, min_val, AVPRIV_CODEC2_MODE_MAX, .flags=option_flags, .unit="codec2_mode"},\ +#define CODEC2_AVOPTIONS(desc, classname, min_val, default_val, option_flags) \ + { "mode", desc, offsetof(classname, mode), AV_OPT_TYPE_INT, {.i64 = default_val}, min_val, CODEC2_MODE_MAX, .flags=option_flags, .unit="codec2_mode"},\ { "3200", "3200", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, .flags=option_flags, .unit="codec2_mode"},\ { "2400", "2400", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, .flags=option_flags, .unit="codec2_mode"},\ { "1600", "1600", 0, AV_OPT_TYPE_CONST, {.i64 = 2}, .flags=option_flags, .unit="codec2_mode"},\ @@ -45,6 +47,7 @@ { "700B", "700B", 0, AV_OPT_TYPE_CONST, {.i64 = 7}, .flags=option_flags, .unit="codec2_mode"},\ { "700C", "700C", 0, AV_OPT_TYPE_CONST, {.i64 = 8}, .flags=option_flags, .unit="codec2_mode"} +#if LIBAVCODEC_VERSION_MAJOR < 59 //The three following functions are here to avoid needing libavformat/codec2.c to depend on libcodec2 //Computes bitrate from mode, with frames rounded up to the nearest octet. @@ -58,11 +61,12 @@ //Mimics (codec2_bits_per_frame()+7)/8 int avpriv_codec2_mode_block_align(void *logctx, int mode); +#endif -#define AVPRIV_CODEC2_EXTRADATA_SIZE 4 +#define CODEC2_EXTRADATA_SIZE 4 //Used in codec2raw demuxer and libcodec2 encoder -static inline void avpriv_codec2_make_extradata(uint8_t *ptr, int mode) { +static inline void codec2_make_extradata(uint8_t *ptr, int mode) { //version 0.8 as of 2017-12-23 (r3386) ptr[0] = 0; //major ptr[1] = 8; //minor @@ -70,12 +74,7 @@ ptr[3] = 0; //flags } -//Returns version as a 16-bit value. 0.8 -> 0x0008 -static inline uint16_t avpriv_codec2_version_from_extradata(uint8_t *ptr) { - return (ptr[0] << 8) + ptr[1]; -} - -static inline uint8_t avpriv_codec2_mode_from_extradata(uint8_t *ptr) { +static inline uint8_t codec2_mode_from_extradata(uint8_t *ptr) { return ptr[2]; } diff -Nru ffmpeg-4.2.2/libavcodec/codec_desc.c ffmpeg-4.4/libavcodec/codec_desc.c --- ffmpeg-4.2.2/libavcodec/codec_desc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/codec_desc.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,7 +23,9 @@ #include "libavutil/common.h" #include "libavutil/internal.h" -#include "avcodec.h" + +#include "codec_id.h" +#include "codec_desc.h" #include "profiles.h" #include "version.h" @@ -1404,6 +1406,35 @@ .props = AV_CODEC_PROP_LOSSY, }, { + .id = AV_CODEC_ID_PGX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pgx", + .long_name = NULL_IF_CONFIG_SMALL("PGX (JPEG2000 Test Format)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_AVS3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avs3", + .long_name = NULL_IF_CONFIG_SMALL("AVS3-P2/IEEE1857.10"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MSP2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "msp2", + .long_name = NULL_IF_CONFIG_SMALL("Microsoft Paint (MSP) version 2"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_VVC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vvc", + .long_name = NULL_IF_CONFIG_SMALL("H.266 / VVC (Versatile Video Coding)"), + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, + .profiles = NULL_IF_CONFIG_SMALL(ff_vvc_profiles), + }, + { .id = AV_CODEC_ID_Y41P, .type = AVMEDIA_TYPE_VIDEO, .name = "y41p", @@ -1496,6 +1527,7 @@ .id = AV_CODEC_ID_SMVJPEG, .type = AVMEDIA_TYPE_VIDEO, .name = "smvjpeg", + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, .long_name = NULL_IF_CONFIG_SMALL("Sigmatel Motion Video"), }, { @@ -1517,7 +1549,7 @@ .id = AV_CODEC_ID_CFHD, .type = AVMEDIA_TYPE_VIDEO, .name = "cfhd", - .long_name = NULL_IF_CONFIG_SMALL("Cineform HD"), + .long_name = NULL_IF_CONFIG_SMALL("GoPro CineForm HD"), .props = AV_CODEC_PROP_LOSSY, }, { @@ -1726,6 +1758,104 @@ .long_name = NULL_IF_CONFIG_SMALL("On2 VP4"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_IMM5, + .type = AVMEDIA_TYPE_VIDEO, + .name = "imm5", + .long_name = NULL_IF_CONFIG_SMALL("Infinity IMM5"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MVDV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mvdv", + .long_name = NULL_IF_CONFIG_SMALL("MidiVid VQ"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MVHA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mvha", + .long_name = NULL_IF_CONFIG_SMALL("MidiVid Archive Codec"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_CDTOONS, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cdtoons", + .long_name = NULL_IF_CONFIG_SMALL("CDToons video"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MV30, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mv30", + .long_name = NULL_IF_CONFIG_SMALL("MidiVid 3.0"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_NOTCHLC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "notchlc", + .long_name = NULL_IF_CONFIG_SMALL("NotchLC"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PFM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pfm", + .long_name = NULL_IF_CONFIG_SMALL("PFM (Portable FloatMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MOBICLIP, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mobiclip", + .long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PHOTOCD, + .type = AVMEDIA_TYPE_VIDEO, + .name = "photocd", + .long_name = NULL_IF_CONFIG_SMALL("Kodak Photo CD"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_IPU, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ipu", + .long_name = NULL_IF_CONFIG_SMALL("IPU Video"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ARGO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "argo", + .long_name = NULL_IF_CONFIG_SMALL("Argonaut Games Video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_CRI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cri", + .long_name = NULL_IF_CONFIG_SMALL("Cintel RAW"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_SIMBIOSIS_IMX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "simbiosis_imx", + .long_name = NULL_IF_CONFIG_SMALL("Simbiosis Interactive IMX Video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SGA_VIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sga", + .long_name = NULL_IF_CONFIG_SMALL("Digital Pictures SGA Video"), + .props = AV_CODEC_PROP_LOSSY, + }, /* various PCM "codecs" */ { @@ -1733,252 +1863,252 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s16le", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit little-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S16BE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s16be", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit big-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_U16LE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_u16le", .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 16-bit little-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_U16BE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_u16be", .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 16-bit big-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S8, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s8", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 8-bit"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_U8, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_u8", .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 8-bit"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_MULAW, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_mulaw", .long_name = NULL_IF_CONFIG_SMALL("PCM mu-law / G.711 mu-law"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_PCM_ALAW, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_alaw", .long_name = NULL_IF_CONFIG_SMALL("PCM A-law / G.711 A-law"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_PCM_S32LE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s32le", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 32-bit little-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S32BE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s32be", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 32-bit big-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_U32LE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_u32le", .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 32-bit little-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_U32BE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_u32be", .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 32-bit big-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S24LE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s24le", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 24-bit little-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S24BE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s24be", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 24-bit big-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_U24LE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_u24le", .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 24-bit little-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_U24BE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_u24be", .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 24-bit big-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S24DAUD, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s24daud", .long_name = NULL_IF_CONFIG_SMALL("PCM D-Cinema audio signed 24-bit"), - .props = AV_CODEC_PROP_LOSSLESS, - }, - { - .id = AV_CODEC_ID_PCM_ZORK, - .type = AVMEDIA_TYPE_AUDIO, - .name = "pcm_zork", - .long_name = NULL_IF_CONFIG_SMALL("PCM Zork"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S16LE_PLANAR, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s16le_planar", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit little-endian planar"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_DVD, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_dvd", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 20|24-bit big-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_F32BE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_f32be", .long_name = NULL_IF_CONFIG_SMALL("PCM 32-bit floating point big-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_F32LE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_f32le", .long_name = NULL_IF_CONFIG_SMALL("PCM 32-bit floating point little-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_F64BE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_f64be", .long_name = NULL_IF_CONFIG_SMALL("PCM 64-bit floating point big-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_F64LE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_f64le", .long_name = NULL_IF_CONFIG_SMALL("PCM 64-bit floating point little-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_BLURAY, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_bluray", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_LXF, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_lxf", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 20-bit little-endian planar"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_S302M, .type = AVMEDIA_TYPE_AUDIO, .name = "s302m", .long_name = NULL_IF_CONFIG_SMALL("SMPTE 302M"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S8_PLANAR, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s8_planar", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 8-bit planar"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S24LE_PLANAR, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s24le_planar", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 24-bit little-endian planar"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S32LE_PLANAR, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s32le_planar", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 32-bit little-endian planar"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S16BE_PLANAR, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s16be_planar", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit big-endian planar"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S64LE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s64le", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 64-bit little-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_S64BE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_s64be", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 64-bit big-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_F16LE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_f16le", .long_name = NULL_IF_CONFIG_SMALL("PCM 16.8 floating point little-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_F24LE, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_f24le", .long_name = NULL_IF_CONFIG_SMALL("PCM 24.0 floating point little-endian"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_PCM_VIDC, .type = AVMEDIA_TYPE_AUDIO, .name = "pcm_vidc", .long_name = NULL_IF_CONFIG_SMALL("PCM Archimedes VIDC"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PCM_SGA, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_sga", + .long_name = NULL_IF_CONFIG_SMALL("PCM SGA"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, /* various ADPCM codecs */ @@ -1987,294 +2117,350 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_qt", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA QuickTime"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_WAV, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_wav", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA WAV"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_DK3, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_dk3", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Duck DK3"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_DK4, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_dk4", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Duck DK4"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_WS, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_ws", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Westwood"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_SMJPEG, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_smjpeg", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Loki SDL MJPEG"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_MS, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ms", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Microsoft"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_4XM, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_4xm", .long_name = NULL_IF_CONFIG_SMALL("ADPCM 4X Movie"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_XA, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_xa", .long_name = NULL_IF_CONFIG_SMALL("ADPCM CDROM XA"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_ADX, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_adx", .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_EA, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ea", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Electronic Arts"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_G726, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_g726", .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_CT, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ct", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Creative Technology"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_SWF, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_swf", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Shockwave Flash"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_YAMAHA, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_yamaha", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Yamaha"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_SBPRO_4, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_sbpro_4", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Sound Blaster Pro 4-bit"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_SBPRO_3, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_sbpro_3", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Sound Blaster Pro 2.6-bit"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_SBPRO_2, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_sbpro_2", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Sound Blaster Pro 2-bit"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_THP, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_thp", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Nintendo THP"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_AMV, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_amv", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA AMV"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_EA_R1, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ea_r1", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Electronic Arts R1"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_EA_R3, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ea_r3", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Electronic Arts R3"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_EA_R2, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ea_r2", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Electronic Arts R2"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_EA_SEAD, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_ea_sead", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Electronic Arts SEAD"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_EA_EACS, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_ea_eacs", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Electronic Arts EACS"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_EA_XAS, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ea_xas", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Electronic Arts XAS"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_EA_MAXIS_XA, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ea_maxis_xa", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Electronic Arts Maxis CDROM XA"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_ISS, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_iss", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Funcom ISS"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_G722, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_g722", .long_name = NULL_IF_CONFIG_SMALL("G.722 ADPCM"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_APC, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_apc", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA CRYO APC"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_VIMA, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_vima", .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_AFC, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_afc", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Nintendo Gamecube AFC"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_OKI, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_oki", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Dialogic OKI"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_DTK, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_dtk", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Nintendo Gamecube DTK"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_RAD, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_rad", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Radical"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_G726LE, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_g726le", .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM little-endian"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_THP_LE, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_thp_le", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Nintendo THP (Little-Endian)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_PSX, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_psx", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Playstation"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_AICA, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_aica", .long_name = NULL_IF_CONFIG_SMALL("ADPCM Yamaha AICA"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_IMA_DAT4, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_ima_dat4", .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Eurocom DAT4"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_MTAF, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_mtaf", .long_name = NULL_IF_CONFIG_SMALL("ADPCM MTAF"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ADPCM_AGM, .type = AVMEDIA_TYPE_AUDIO, .name = "adpcm_agm", .long_name = NULL_IF_CONFIG_SMALL("ADPCM AmuseGraphics Movie AGM"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_ARGO, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_argo", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Argonaut Games"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_SSI, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_ssi", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Simon & Schuster Interactive"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_ZORK, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_zork", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Zork"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_APM, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_apm", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Ubisoft APM"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_ALP, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_alp", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA High Voltage Software ALP"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_MTF, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_mtf", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Capcom's MT Framework"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_CUNNING, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_cunning", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Cunning Developments"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_MOFLEX, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_moflex", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA MobiClip MOFLEX"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, /* AMR */ @@ -2283,14 +2469,14 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "amr_nb", .long_name = NULL_IF_CONFIG_SMALL("AMR-NB (Adaptive Multi-Rate NarrowBand)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_AMR_WB, .type = AVMEDIA_TYPE_AUDIO, .name = "amr_wb", .long_name = NULL_IF_CONFIG_SMALL("AMR-WB (Adaptive Multi-Rate WideBand)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, /* RealAudio codecs*/ @@ -2299,14 +2485,14 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "ra_144", .long_name = NULL_IF_CONFIG_SMALL("RealAudio 1.0 (14.4K)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_RA_288, .type = AVMEDIA_TYPE_AUDIO, .name = "ra_288", .long_name = NULL_IF_CONFIG_SMALL("RealAudio 2.0 (28.8K)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, /* various DPCM codecs */ @@ -2315,42 +2501,49 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "roq_dpcm", .long_name = NULL_IF_CONFIG_SMALL("DPCM id RoQ"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_INTERPLAY_DPCM, .type = AVMEDIA_TYPE_AUDIO, .name = "interplay_dpcm", .long_name = NULL_IF_CONFIG_SMALL("DPCM Interplay"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_XAN_DPCM, .type = AVMEDIA_TYPE_AUDIO, .name = "xan_dpcm", .long_name = NULL_IF_CONFIG_SMALL("DPCM Xan"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_SOL_DPCM, .type = AVMEDIA_TYPE_AUDIO, .name = "sol_dpcm", .long_name = NULL_IF_CONFIG_SMALL("DPCM Sol"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_SDX2_DPCM, .type = AVMEDIA_TYPE_AUDIO, .name = "sdx2_dpcm", .long_name = NULL_IF_CONFIG_SMALL("DPCM Squareroot-Delta-Exact"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_GREMLIN_DPCM, .type = AVMEDIA_TYPE_AUDIO, .name = "gremlin_dpcm", .long_name = NULL_IF_CONFIG_SMALL("DPCM Gremlin"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_DERF_DPCM, + .type = AVMEDIA_TYPE_AUDIO, + .name = "derf_dpcm", + .long_name = NULL_IF_CONFIG_SMALL("DPCM Xilam DERF"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, /* audio codecs */ @@ -2359,21 +2552,21 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "mp2", .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_MP3, .type = AVMEDIA_TYPE_AUDIO, .name = "mp3", .long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_AAC, .type = AVMEDIA_TYPE_AUDIO, .name = "aac", .long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, .profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), }, { @@ -2381,14 +2574,14 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "ac3", .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_DTS, .type = AVMEDIA_TYPE_AUDIO, .name = "dts", .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"), - .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, .profiles = NULL_IF_CONFIG_SMALL(ff_dca_profiles), }, { @@ -2396,49 +2589,49 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "vorbis", .long_name = NULL_IF_CONFIG_SMALL("Vorbis"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_DVAUDIO, .type = AVMEDIA_TYPE_AUDIO, .name = "dvaudio", .long_name = NULL_IF_CONFIG_SMALL("DV audio"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_WMAV1, .type = AVMEDIA_TYPE_AUDIO, .name = "wmav1", .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_WMAV2, .type = AVMEDIA_TYPE_AUDIO, .name = "wmav2", .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_MACE3, .type = AVMEDIA_TYPE_AUDIO, .name = "mace3", .long_name = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 3:1"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_MACE6, .type = AVMEDIA_TYPE_AUDIO, .name = "mace6", .long_name = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 6:1"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_VMDAUDIO, .type = AVMEDIA_TYPE_AUDIO, .name = "vmdaudio", .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_FLAC, @@ -2452,21 +2645,21 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "mp3adu", .long_name = NULL_IF_CONFIG_SMALL("ADU (Application Data Unit) MP3 (MPEG audio layer 3)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_MP3ON4, .type = AVMEDIA_TYPE_AUDIO, .name = "mp3on4", .long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_SHORTEN, .type = AVMEDIA_TYPE_AUDIO, .name = "shorten", .long_name = NULL_IF_CONFIG_SMALL("Shorten"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_ALAC, @@ -2480,35 +2673,35 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "westwood_snd1", .long_name = NULL_IF_CONFIG_SMALL("Westwood Audio (SND1)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_GSM, .type = AVMEDIA_TYPE_AUDIO, .name = "gsm", .long_name = NULL_IF_CONFIG_SMALL("GSM"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_QDM2, .type = AVMEDIA_TYPE_AUDIO, .name = "qdm2", .long_name = NULL_IF_CONFIG_SMALL("QDesign Music Codec 2"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_COOK, .type = AVMEDIA_TYPE_AUDIO, .name = "cook", .long_name = NULL_IF_CONFIG_SMALL("Cook / Cooker / Gecko (RealAudio G2)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_TRUESPEECH, .type = AVMEDIA_TYPE_AUDIO, .name = "truespeech", .long_name = NULL_IF_CONFIG_SMALL("DSP Group TrueSpeech"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_TTA, @@ -2522,14 +2715,14 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "smackaudio", .long_name = NULL_IF_CONFIG_SMALL("Smacker audio"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_QCELP, .type = AVMEDIA_TYPE_AUDIO, .name = "qcelp", .long_name = NULL_IF_CONFIG_SMALL("QCELP / PureVoice"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_WAVPACK, @@ -2544,126 +2737,126 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "dsicinaudio", .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_IMC, .type = AVMEDIA_TYPE_AUDIO, .name = "imc", .long_name = NULL_IF_CONFIG_SMALL("IMC (Intel Music Coder)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_MUSEPACK7, .type = AVMEDIA_TYPE_AUDIO, .name = "musepack7", .long_name = NULL_IF_CONFIG_SMALL("Musepack SV7"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_MLP, .type = AVMEDIA_TYPE_AUDIO, .name = "mlp", .long_name = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_GSM_MS, .type = AVMEDIA_TYPE_AUDIO, .name = "gsm_ms", .long_name = NULL_IF_CONFIG_SMALL("GSM Microsoft variant"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ATRAC3, .type = AVMEDIA_TYPE_AUDIO, .name = "atrac3", .long_name = NULL_IF_CONFIG_SMALL("ATRAC3 (Adaptive TRansform Acoustic Coding 3)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_APE, .type = AVMEDIA_TYPE_AUDIO, .name = "ape", .long_name = NULL_IF_CONFIG_SMALL("Monkey's Audio"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_NELLYMOSER, .type = AVMEDIA_TYPE_AUDIO, .name = "nellymoser", .long_name = NULL_IF_CONFIG_SMALL("Nellymoser Asao"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_MUSEPACK8, .type = AVMEDIA_TYPE_AUDIO, .name = "musepack8", .long_name = NULL_IF_CONFIG_SMALL("Musepack SV8"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_SPEEX, .type = AVMEDIA_TYPE_AUDIO, .name = "speex", .long_name = NULL_IF_CONFIG_SMALL("Speex"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_WMAVOICE, .type = AVMEDIA_TYPE_AUDIO, .name = "wmavoice", .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio Voice"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_WMAPRO, .type = AVMEDIA_TYPE_AUDIO, .name = "wmapro", .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_WMALOSSLESS, .type = AVMEDIA_TYPE_AUDIO, .name = "wmalossless", .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio Lossless"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_ATRAC3P, .type = AVMEDIA_TYPE_AUDIO, .name = "atrac3p", .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ (Adaptive TRansform Acoustic Coding 3+)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_EAC3, .type = AVMEDIA_TYPE_AUDIO, .name = "eac3", .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_SIPR, .type = AVMEDIA_TYPE_AUDIO, .name = "sipr", .long_name = NULL_IF_CONFIG_SMALL("RealAudio SIPR / ACELP.NET"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_MP1, .type = AVMEDIA_TYPE_AUDIO, .name = "mp1", .long_name = NULL_IF_CONFIG_SMALL("MP1 (MPEG audio layer 1)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_TWINVQ, .type = AVMEDIA_TYPE_AUDIO, .name = "twinvq", .long_name = NULL_IF_CONFIG_SMALL("VQF TwinVQ"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_TRUEHD, @@ -2677,35 +2870,35 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "mp4als", .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Audio Lossless Coding (ALS)"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_ATRAC1, .type = AVMEDIA_TYPE_AUDIO, .name = "atrac1", .long_name = NULL_IF_CONFIG_SMALL("ATRAC1 (Adaptive TRansform Acoustic Coding)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_BINKAUDIO_RDFT, .type = AVMEDIA_TYPE_AUDIO, .name = "binkaudio_rdft", .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (RDFT)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_BINKAUDIO_DCT, .type = AVMEDIA_TYPE_AUDIO, .name = "binkaudio_dct", .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (DCT)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_AAC_LATM, .type = AVMEDIA_TYPE_AUDIO, .name = "aac_latm", .long_name = NULL_IF_CONFIG_SMALL("AAC LATM (Advanced Audio Coding LATM syntax)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, .profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), }, { @@ -2713,278 +2906,316 @@ .type = AVMEDIA_TYPE_AUDIO, .name = "qdmc", .long_name = NULL_IF_CONFIG_SMALL("QDesign Music"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_CELT, .type = AVMEDIA_TYPE_AUDIO, .name = "celt", .long_name = NULL_IF_CONFIG_SMALL("Constrained Energy Lapped Transform (CELT)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_G723_1, .type = AVMEDIA_TYPE_AUDIO, .name = "g723_1", .long_name = NULL_IF_CONFIG_SMALL("G.723.1"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_G729, .type = AVMEDIA_TYPE_AUDIO, .name = "g729", .long_name = NULL_IF_CONFIG_SMALL("G.729"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_8SVX_EXP, .type = AVMEDIA_TYPE_AUDIO, .name = "8svx_exp", .long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_8SVX_FIB, .type = AVMEDIA_TYPE_AUDIO, .name = "8svx_fib", .long_name = NULL_IF_CONFIG_SMALL("8SVX fibonacci"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_BMV_AUDIO, .type = AVMEDIA_TYPE_AUDIO, .name = "bmv_audio", .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV audio"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_RALF, .type = AVMEDIA_TYPE_AUDIO, .name = "ralf", .long_name = NULL_IF_CONFIG_SMALL("RealAudio Lossless"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_IAC, .type = AVMEDIA_TYPE_AUDIO, .name = "iac", .long_name = NULL_IF_CONFIG_SMALL("IAC (Indeo Audio Coder)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ILBC, .type = AVMEDIA_TYPE_AUDIO, .name = "ilbc", .long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_OPUS, .type = AVMEDIA_TYPE_AUDIO, .name = "opus", .long_name = NULL_IF_CONFIG_SMALL("Opus (Opus Interactive Audio Codec)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_COMFORT_NOISE, .type = AVMEDIA_TYPE_AUDIO, .name = "comfortnoise", .long_name = NULL_IF_CONFIG_SMALL("RFC 3389 Comfort Noise"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_TAK, .type = AVMEDIA_TYPE_AUDIO, .name = "tak", .long_name = NULL_IF_CONFIG_SMALL("TAK (Tom's lossless Audio Kompressor)"), - .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_METASOUND, .type = AVMEDIA_TYPE_AUDIO, .name = "metasound", .long_name = NULL_IF_CONFIG_SMALL("Voxware MetaSound"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_PAF_AUDIO, .type = AVMEDIA_TYPE_AUDIO, .name = "paf_audio", .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ON2AVC, .type = AVMEDIA_TYPE_AUDIO, .name = "avc", .long_name = NULL_IF_CONFIG_SMALL("On2 Audio for Video Codec"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_DSS_SP, .type = AVMEDIA_TYPE_AUDIO, .name = "dss_sp", .long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard - Standard Play mode (DSS SP)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_CODEC2, .type = AVMEDIA_TYPE_AUDIO, .name = "codec2", .long_name = NULL_IF_CONFIG_SMALL("codec2 (very low bitrate speech codec)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_FFWAVESYNTH, .type = AVMEDIA_TYPE_AUDIO, .name = "wavesynth", .long_name = NULL_IF_CONFIG_SMALL("Wave synthesis pseudo-codec"), + .props = AV_CODEC_PROP_INTRA_ONLY, }, { .id = AV_CODEC_ID_SONIC, .type = AVMEDIA_TYPE_AUDIO, .name = "sonic", .long_name = NULL_IF_CONFIG_SMALL("Sonic"), + .props = AV_CODEC_PROP_INTRA_ONLY, }, { .id = AV_CODEC_ID_SONIC_LS, .type = AVMEDIA_TYPE_AUDIO, .name = "sonicls", .long_name = NULL_IF_CONFIG_SMALL("Sonic lossless"), + .props = AV_CODEC_PROP_INTRA_ONLY, }, { .id = AV_CODEC_ID_EVRC, .type = AVMEDIA_TYPE_AUDIO, .name = "evrc", .long_name = NULL_IF_CONFIG_SMALL("EVRC (Enhanced Variable Rate Codec)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_SMV, .type = AVMEDIA_TYPE_AUDIO, .name = "smv", .long_name = NULL_IF_CONFIG_SMALL("SMV (Selectable Mode Vocoder)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_DSD_LSBF, .type = AVMEDIA_TYPE_AUDIO, .name = "dsd_lsbf", .long_name = NULL_IF_CONFIG_SMALL("DSD (Direct Stream Digital), least significant bit first"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_DSD_MSBF, .type = AVMEDIA_TYPE_AUDIO, .name = "dsd_msbf", .long_name = NULL_IF_CONFIG_SMALL("DSD (Direct Stream Digital), most significant bit first"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_DSD_LSBF_PLANAR, .type = AVMEDIA_TYPE_AUDIO, .name = "dsd_lsbf_planar", .long_name = NULL_IF_CONFIG_SMALL("DSD (Direct Stream Digital), least significant bit first, planar"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_DSD_MSBF_PLANAR, .type = AVMEDIA_TYPE_AUDIO, .name = "dsd_msbf_planar", .long_name = NULL_IF_CONFIG_SMALL("DSD (Direct Stream Digital), most significant bit first, planar"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_4GV, .type = AVMEDIA_TYPE_AUDIO, .name = "4gv", .long_name = NULL_IF_CONFIG_SMALL("4GV (Fourth Generation Vocoder)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_INTERPLAY_ACM, .type = AVMEDIA_TYPE_AUDIO, .name = "interplayacm", .long_name = NULL_IF_CONFIG_SMALL("Interplay ACM"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_XMA1, .type = AVMEDIA_TYPE_AUDIO, .name = "xma1", .long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio 1"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_XMA2, .type = AVMEDIA_TYPE_AUDIO, .name = "xma2", .long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio 2"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_DST, .type = AVMEDIA_TYPE_AUDIO, .name = "dst", .long_name = NULL_IF_CONFIG_SMALL("DST (Direct Stream Transfer)"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_ATRAC3AL, .type = AVMEDIA_TYPE_AUDIO, .name = "atrac3al", .long_name = NULL_IF_CONFIG_SMALL("ATRAC3 AL (Adaptive TRansform Acoustic Coding 3 Advanced Lossless)"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_ATRAC3PAL, .type = AVMEDIA_TYPE_AUDIO, .name = "atrac3pal", .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ AL (Adaptive TRansform Acoustic Coding 3+ Advanced Lossless)"), - .props = AV_CODEC_PROP_LOSSLESS, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, }, { .id = AV_CODEC_ID_DOLBY_E, .type = AVMEDIA_TYPE_AUDIO, .name = "dolby_e", .long_name = NULL_IF_CONFIG_SMALL("Dolby E"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_APTX, .type = AVMEDIA_TYPE_AUDIO, .name = "aptx", .long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_APTX_HD, .type = AVMEDIA_TYPE_AUDIO, .name = "aptx_hd", .long_name = NULL_IF_CONFIG_SMALL("aptX HD (Audio Processing Technology for Bluetooth)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_SBC, .type = AVMEDIA_TYPE_AUDIO, .name = "sbc", .long_name = NULL_IF_CONFIG_SMALL("SBC (low-complexity subband codec)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_ATRAC9, .type = AVMEDIA_TYPE_AUDIO, .name = "atrac9", .long_name = NULL_IF_CONFIG_SMALL("ATRAC9 (Adaptive TRansform Acoustic Coding 9)"), - .props = AV_CODEC_PROP_LOSSY, + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, { .id = AV_CODEC_ID_HCOM, .type = AVMEDIA_TYPE_AUDIO, .name = "hcom", .long_name = NULL_IF_CONFIG_SMALL("HCOM Audio"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ACELP_KELVIN, + .type = AVMEDIA_TYPE_AUDIO, + .name = "acelp.kelvin", + .long_name = NULL_IF_CONFIG_SMALL("Sipro ACELP.KELVIN"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MPEGH_3D_AUDIO, + .type = AVMEDIA_TYPE_AUDIO, + .name = "mpegh_3d_audio", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-H 3D Audio"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_SIREN, + .type = AVMEDIA_TYPE_AUDIO, + .name = "siren", + .long_name = NULL_IF_CONFIG_SMALL("Siren"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_HCA, + .type = AVMEDIA_TYPE_AUDIO, + .name = "hca", + .long_name = NULL_IF_CONFIG_SMALL("CRI HCA"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_FASTAUDIO, + .type = AVMEDIA_TYPE_AUDIO, + .name = "fastaudio", + .long_name = NULL_IF_CONFIG_SMALL("MobiClip FastAudio"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, /* subtitle codecs */ { @@ -3185,6 +3416,12 @@ .long_name = NULL_IF_CONFIG_SMALL("SCTE 35 Message Queue"), }, { + .id = AV_CODEC_ID_EPG, + .type = AVMEDIA_TYPE_DATA, + .name = "epg", + .long_name = NULL_IF_CONFIG_SMALL("Electronic Program Guide"), + }, + { .id = AV_CODEC_ID_BINTEXT, .type = AVMEDIA_TYPE_VIDEO, .name = "bintext", @@ -3238,6 +3475,13 @@ .mime_types= MT("application/octet-stream"), }, { + .id = AV_CODEC_ID_MPEG2TS, + .type = AVMEDIA_TYPE_DATA, + .name = "mpegts", + .long_name = NULL_IF_CONFIG_SMALL("raw MPEG-TS stream"), + .mime_types= MT("application/MP2T"), + }, + { .id = AV_CODEC_ID_WRAPPED_AVFRAME, .type = AVMEDIA_TYPE_VIDEO, .name = "wrapped_avframe", diff -Nru ffmpeg-4.2.2/libavcodec/codec_desc.h ffmpeg-4.4/libavcodec/codec_desc.h --- ffmpeg-4.2.2/libavcodec/codec_desc.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/codec_desc.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,128 @@ +/* + * Codec descriptors public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_DESC_H +#define AVCODEC_CODEC_DESC_H + +#include "libavutil/avutil.h" + +#include "codec_id.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * This struct describes the properties of a single codec described by an + * AVCodecID. + * @see avcodec_descriptor_get() + */ +typedef struct AVCodecDescriptor { + enum AVCodecID id; + enum AVMediaType type; + /** + * Name of the codec described by this descriptor. It is non-empty and + * unique for each codec descriptor. It should contain alphanumeric + * characters and '_' only. + */ + const char *name; + /** + * A more descriptive name for this codec. May be NULL. + */ + const char *long_name; + /** + * Codec properties, a combination of AV_CODEC_PROP_* flags. + */ + int props; + /** + * MIME type(s) associated with the codec. + * May be NULL; if not, a NULL-terminated array of MIME types. + * The first item is always non-NULL and is the preferred MIME type. + */ + const char *const *mime_types; + /** + * If non-NULL, an array of profiles recognized for this codec. + * Terminated with FF_PROFILE_UNKNOWN. + */ + const struct AVProfile *profiles; +} AVCodecDescriptor; + +/** + * Codec uses only intra compression. + * Video and audio codecs only. + */ +#define AV_CODEC_PROP_INTRA_ONLY (1 << 0) +/** + * Codec supports lossy compression. Audio and video codecs only. + * @note a codec may support both lossy and lossless + * compression modes + */ +#define AV_CODEC_PROP_LOSSY (1 << 1) +/** + * Codec supports lossless compression. Audio and video codecs only. + */ +#define AV_CODEC_PROP_LOSSLESS (1 << 2) +/** + * Codec supports frame reordering. That is, the coded order (the order in which + * the encoded packets are output by the encoders / stored / input to the + * decoders) may be different from the presentation order of the corresponding + * frames. + * + * For codecs that do not have this property set, PTS and DTS should always be + * equal. + */ +#define AV_CODEC_PROP_REORDER (1 << 3) +/** + * Subtitle codec is bitmap based + * Decoded AVSubtitle data can be read from the AVSubtitleRect->pict field. + */ +#define AV_CODEC_PROP_BITMAP_SUB (1 << 16) +/** + * Subtitle codec is text based. + * Decoded AVSubtitle data can be read from the AVSubtitleRect->ass field. + */ +#define AV_CODEC_PROP_TEXT_SUB (1 << 17) + +/** + * @return descriptor for given codec ID or NULL if no descriptor exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id); + +/** + * Iterate over all codec descriptors known to libavcodec. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); + +/** + * @return codec descriptor with the given name or NULL if no such descriptor + * exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_DESC_H diff -Nru ffmpeg-4.2.2/libavcodec/codec.h ffmpeg-4.4/libavcodec/codec.h --- ffmpeg-4.2.2/libavcodec/codec.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/codec.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,480 @@ +/* + * AVCodec public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_H +#define AVCODEC_CODEC_H + +#include + +#include "libavutil/avutil.h" +#include "libavutil/hwcontext.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" +#include "libavutil/samplefmt.h" + +#include "libavcodec/codec_id.h" +#include "libavcodec/version.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * Decoder can use draw_horiz_band callback. + */ +#define AV_CODEC_CAP_DRAW_HORIZ_BAND (1 << 0) +/** + * Codec uses get_buffer() or get_encode_buffer() for allocating buffers and + * supports custom allocators. + * If not set, it might not use get_buffer() or get_encode_buffer() at all, or + * use operations that assume the buffer was allocated by + * avcodec_default_get_buffer2 or avcodec_default_get_encode_buffer. + */ +#define AV_CODEC_CAP_DR1 (1 << 1) +#define AV_CODEC_CAP_TRUNCATED (1 << 3) +/** + * Encoder or decoder requires flushing with NULL input at the end in order to + * give the complete and correct output. + * + * NOTE: If this flag is not set, the codec is guaranteed to never be fed with + * with NULL data. The user can still send NULL data to the public encode + * or decode function, but libavcodec will not pass it along to the codec + * unless this flag is set. + * + * Decoders: + * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to get the delayed data until the decoder no longer + * returns frames. + * + * Encoders: + * The encoder needs to be fed with NULL data at the end of encoding until the + * encoder no longer returns data. + * + * NOTE: For encoders implementing the AVCodec.encode2() function, setting this + * flag also means that the encoder must set the pts and duration for + * each output packet. If this flag is not set, the pts and duration will + * be determined by libavcodec from the input frame. + */ +#define AV_CODEC_CAP_DELAY (1 << 5) +/** + * Codec can be fed a final frame with a smaller size. + * This can be used to prevent truncation of the last audio samples. + */ +#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6) + +/** + * Codec can output multiple frames per AVPacket + * Normally demuxers return one frame at a time, demuxers which do not do + * are connected to a parser to split what they return into proper frames. + * This flag is reserved to the very rare category of codecs which have a + * bitstream that cannot be split into frames without timeconsuming + * operations like full decoding. Demuxers carrying such bitstreams thus + * may return multiple frames in a packet. This has many disadvantages like + * prohibiting stream copy in many cases thus it should only be considered + * as a last resort. + */ +#define AV_CODEC_CAP_SUBFRAMES (1 << 8) +/** + * Codec is experimental and is thus avoided in favor of non experimental + * encoders + */ +#define AV_CODEC_CAP_EXPERIMENTAL (1 << 9) +/** + * Codec should fill in channel configuration and samplerate instead of container + */ +#define AV_CODEC_CAP_CHANNEL_CONF (1 << 10) +/** + * Codec supports frame-level multithreading. + */ +#define AV_CODEC_CAP_FRAME_THREADS (1 << 12) +/** + * Codec supports slice-based (or partition-based) multithreading. + */ +#define AV_CODEC_CAP_SLICE_THREADS (1 << 13) +/** + * Codec supports changed parameters at any point. + */ +#define AV_CODEC_CAP_PARAM_CHANGE (1 << 14) +/** + * Codec supports multithreading through a method other than slice- or + * frame-level multithreading. Typically this marks wrappers around + * multithreading-capable external libraries. + */ +#define AV_CODEC_CAP_OTHER_THREADS (1 << 15) +#if FF_API_AUTO_THREADS +#define AV_CODEC_CAP_AUTO_THREADS AV_CODEC_CAP_OTHER_THREADS +#endif +/** + * Audio encoder supports receiving a different number of samples in each call. + */ +#define AV_CODEC_CAP_VARIABLE_FRAME_SIZE (1 << 16) +/** + * Decoder is not a preferred choice for probing. + * This indicates that the decoder is not a good choice for probing. + * It could for example be an expensive to spin up hardware decoder, + * or it could simply not provide a lot of useful information about + * the stream. + * A decoder marked with this flag should only be used as last resort + * choice for probing. + */ +#define AV_CODEC_CAP_AVOID_PROBING (1 << 17) + +#if FF_API_UNUSED_CODEC_CAPS +/** + * Deprecated and unused. Use AVCodecDescriptor.props instead + */ +#define AV_CODEC_CAP_INTRA_ONLY 0x40000000 +/** + * Deprecated and unused. Use AVCodecDescriptor.props instead + */ +#define AV_CODEC_CAP_LOSSLESS 0x80000000 +#endif + +/** + * Codec is backed by a hardware implementation. Typically used to + * identify a non-hwaccel hardware decoder. For information about hwaccels, use + * avcodec_get_hw_config() instead. + */ +#define AV_CODEC_CAP_HARDWARE (1 << 18) + +/** + * Codec is potentially backed by a hardware implementation, but not + * necessarily. This is used instead of AV_CODEC_CAP_HARDWARE, if the + * implementation provides some sort of internal fallback. + */ +#define AV_CODEC_CAP_HYBRID (1 << 19) + +/** + * This codec takes the reordered_opaque field from input AVFrames + * and returns it in the corresponding field in AVCodecContext after + * encoding. + */ +#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE (1 << 20) + +/** + * This encoder can be flushed using avcodec_flush_buffers(). If this flag is + * not set, the encoder must be closed and reopened to ensure that no frames + * remain pending. + */ +#define AV_CODEC_CAP_ENCODER_FLUSH (1 << 21) + +/** + * AVProfile. + */ +typedef struct AVProfile { + int profile; + const char *name; ///< short name for the profile +} AVProfile; + +typedef struct AVCodecDefault AVCodecDefault; + +struct AVCodecContext; +struct AVSubtitle; +struct AVPacket; + +/** + * AVCodec. + */ +typedef struct AVCodec { + /** + * Name of the codec implementation. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + * This is the primary way to find a codec from the user perspective. + */ + const char *name; + /** + * Descriptive name for the codec, meant to be more human readable than name. + * You should use the NULL_IF_CONFIG_SMALL() macro to define it. + */ + const char *long_name; + enum AVMediaType type; + enum AVCodecID id; + /** + * Codec capabilities. + * see AV_CODEC_CAP_* + */ + int capabilities; + const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} + const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 + const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 + const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 + const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 + uint8_t max_lowres; ///< maximum value for lowres supported by the decoder + const AVClass *priv_class; ///< AVClass for the private context + const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN} + + /** + * Group name of the codec implementation. + * This is a short symbolic name of the wrapper backing this codec. A + * wrapper uses some kind of external implementation for the codec, such + * as an external library, or a codec implementation provided by the OS or + * the hardware. + * If this field is NULL, this is a builtin, libavcodec native codec. + * If non-NULL, this will be the suffix in AVCodec.name in most cases + * (usually AVCodec.name will be of the form "_"). + */ + const char *wrapper_name; + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavcodec and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + int priv_data_size; +#if FF_API_NEXT + struct AVCodec *next; +#endif + /** + * @name Frame-level threading support functions + * @{ + */ + /** + * Copy necessary context variables from a previous thread context to the current one. + * If not defined, the next thread will start automatically; otherwise, the codec + * must call ff_thread_finish_setup(). + * + * dst and src will (rarely) point to the same context, in which case memcpy should be skipped. + */ + int (*update_thread_context)(struct AVCodecContext *dst, const struct AVCodecContext *src); + /** @} */ + + /** + * Private codec-specific defaults. + */ + const AVCodecDefault *defaults; + + /** + * Initialize codec static data, called from av_codec_iterate(). + * + * This is not intended for time consuming operations as it is + * run for every codec regardless of that codec being used. + */ + void (*init_static_data)(struct AVCodec *codec); + + int (*init)(struct AVCodecContext *); + int (*encode_sub)(struct AVCodecContext *, uint8_t *buf, int buf_size, + const struct AVSubtitle *sub); + /** + * Encode data to an AVPacket. + * + * @param avctx codec context + * @param avpkt output AVPacket + * @param[in] frame AVFrame containing the raw data to be encoded + * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a + * non-empty packet was returned in avpkt. + * @return 0 on success, negative error code on failure + */ + int (*encode2)(struct AVCodecContext *avctx, struct AVPacket *avpkt, + const struct AVFrame *frame, int *got_packet_ptr); + /** + * Decode picture or subtitle data. + * + * @param avctx codec context + * @param outdata codec type dependent output struct + * @param[out] got_frame_ptr decoder sets to 0 or 1 to indicate that a + * non-empty frame or subtitle was returned in + * outdata. + * @param[in] avpkt AVPacket containing the data to be decoded + * @return amount of bytes read from the packet on success, negative error + * code on failure + */ + int (*decode)(struct AVCodecContext *avctx, void *outdata, + int *got_frame_ptr, struct AVPacket *avpkt); + int (*close)(struct AVCodecContext *); + /** + * Encode API with decoupled frame/packet dataflow. This function is called + * to get one output packet. It should call ff_encode_get_frame() to obtain + * input data. + */ + int (*receive_packet)(struct AVCodecContext *avctx, struct AVPacket *avpkt); + + /** + * Decode API with decoupled packet/frame dataflow. This function is called + * to get one output frame. It should call ff_decode_get_packet() to obtain + * input data. + */ + int (*receive_frame)(struct AVCodecContext *avctx, struct AVFrame *frame); + /** + * Flush buffers. + * Will be called when seeking + */ + void (*flush)(struct AVCodecContext *); + /** + * Internal codec capabilities. + * See FF_CODEC_CAP_* in internal.h + */ + int caps_internal; + + /** + * Decoding only, a comma-separated list of bitstream filters to apply to + * packets before decoding. + */ + const char *bsfs; + + /** + * Array of pointers to hardware configurations supported by the codec, + * or NULL if no hardware supported. The array is terminated by a NULL + * pointer. + * + * The user can only access this field via avcodec_get_hw_config(). + */ + const struct AVCodecHWConfigInternal *const *hw_configs; + + /** + * List of supported codec_tags, terminated by FF_CODEC_TAGS_END. + */ + const uint32_t *codec_tags; +} AVCodec; + +/** + * Iterate over all registered codecs. + * + * @param opaque a pointer where libavcodec will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the next registered codec or NULL when the iteration is + * finished + */ +const AVCodec *av_codec_iterate(void **opaque); + +/** + * Find a registered decoder with a matching codec ID. + * + * @param id AVCodecID of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_decoder(enum AVCodecID id); + +/** + * Find a registered decoder with the specified name. + * + * @param name name of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_decoder_by_name(const char *name); + +/** + * Find a registered encoder with a matching codec ID. + * + * @param id AVCodecID of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_encoder(enum AVCodecID id); + +/** + * Find a registered encoder with the specified name. + * + * @param name name of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_encoder_by_name(const char *name); +/** + * @return a non-zero number if codec is an encoder, zero otherwise + */ +int av_codec_is_encoder(const AVCodec *codec); + +/** + * @return a non-zero number if codec is a decoder, zero otherwise + */ +int av_codec_is_decoder(const AVCodec *codec); + +enum { + /** + * The codec supports this format via the hw_device_ctx interface. + * + * When selecting this format, AVCodecContext.hw_device_ctx should + * have been set to a device of the specified type before calling + * avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01, + /** + * The codec supports this format via the hw_frames_ctx interface. + * + * When selecting this format for a decoder, + * AVCodecContext.hw_frames_ctx should be set to a suitable frames + * context inside the get_format() callback. The frames context + * must have been created on a device of the specified type. + * + * When selecting this format for an encoder, + * AVCodecContext.hw_frames_ctx should be set to the context which + * will be used for the input frames before calling avcodec_open2(). + */ + AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02, + /** + * The codec supports this format by some internal method. + * + * This format can be selected without any additional configuration - + * no device or frames context is required. + */ + AV_CODEC_HW_CONFIG_METHOD_INTERNAL = 0x04, + /** + * The codec supports this format by some ad-hoc method. + * + * Additional settings and/or function calls are required. See the + * codec-specific documentation for details. (Methods requiring + * this sort of configuration are deprecated and others should be + * used in preference.) + */ + AV_CODEC_HW_CONFIG_METHOD_AD_HOC = 0x08, +}; + +typedef struct AVCodecHWConfig { + /** + * For decoders, a hardware pixel format which that decoder may be + * able to decode to if suitable hardware is available. + * + * For encoders, a pixel format which the encoder may be able to + * accept. If set to AV_PIX_FMT_NONE, this applies to all pixel + * formats supported by the codec. + */ + enum AVPixelFormat pix_fmt; + /** + * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible + * setup methods which can be used with this configuration. + */ + int methods; + /** + * The device type associated with the configuration. + * + * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and + * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused. + */ + enum AVHWDeviceType device_type; +} AVCodecHWConfig; + +/** + * Retrieve supported hardware configurations for a codec. + * + * Values of index from zero to some maximum return the indexed configuration + * descriptor; all other values return NULL. If the codec does not support + * any hardware configurations then it will always return NULL. + */ +const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index); + +/** + * @} + */ + +#endif /* AVCODEC_CODEC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/codec_id.h ffmpeg-4.4/libavcodec/codec_id.h --- ffmpeg-4.2.2/libavcodec/codec_id.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/codec_id.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,592 @@ +/* + * Codec IDs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_ID_H +#define AVCODEC_CODEC_ID_H + +#include "libavutil/avutil.h" + +/** + * @addtogroup lavc_core + * @{ + */ + +/** + * Identify the syntax and semantics of the bitstream. + * The principle is roughly: + * Two decoders with the same ID can decode the same streams. + * Two encoders with the same ID can encode compatible streams. + * There may be slight deviations from the principle due to implementation + * details. + * + * If you add a codec ID to this list, add it so that + * 1. no value of an existing codec ID changes (that would break ABI), + * 2. it is as close as possible to similar codecs + * + * After adding new codec IDs, do not forget to add an entry to the codec + * descriptor list and bump libavcodec minor version. + */ +enum AVCodecID { + AV_CODEC_ID_NONE, + + /* video codecs */ + AV_CODEC_ID_MPEG1VIDEO, + AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding + AV_CODEC_ID_H261, + AV_CODEC_ID_H263, + AV_CODEC_ID_RV10, + AV_CODEC_ID_RV20, + AV_CODEC_ID_MJPEG, + AV_CODEC_ID_MJPEGB, + AV_CODEC_ID_LJPEG, + AV_CODEC_ID_SP5X, + AV_CODEC_ID_JPEGLS, + AV_CODEC_ID_MPEG4, + AV_CODEC_ID_RAWVIDEO, + AV_CODEC_ID_MSMPEG4V1, + AV_CODEC_ID_MSMPEG4V2, + AV_CODEC_ID_MSMPEG4V3, + AV_CODEC_ID_WMV1, + AV_CODEC_ID_WMV2, + AV_CODEC_ID_H263P, + AV_CODEC_ID_H263I, + AV_CODEC_ID_FLV1, + AV_CODEC_ID_SVQ1, + AV_CODEC_ID_SVQ3, + AV_CODEC_ID_DVVIDEO, + AV_CODEC_ID_HUFFYUV, + AV_CODEC_ID_CYUV, + AV_CODEC_ID_H264, + AV_CODEC_ID_INDEO3, + AV_CODEC_ID_VP3, + AV_CODEC_ID_THEORA, + AV_CODEC_ID_ASV1, + AV_CODEC_ID_ASV2, + AV_CODEC_ID_FFV1, + AV_CODEC_ID_4XM, + AV_CODEC_ID_VCR1, + AV_CODEC_ID_CLJR, + AV_CODEC_ID_MDEC, + AV_CODEC_ID_ROQ, + AV_CODEC_ID_INTERPLAY_VIDEO, + AV_CODEC_ID_XAN_WC3, + AV_CODEC_ID_XAN_WC4, + AV_CODEC_ID_RPZA, + AV_CODEC_ID_CINEPAK, + AV_CODEC_ID_WS_VQA, + AV_CODEC_ID_MSRLE, + AV_CODEC_ID_MSVIDEO1, + AV_CODEC_ID_IDCIN, + AV_CODEC_ID_8BPS, + AV_CODEC_ID_SMC, + AV_CODEC_ID_FLIC, + AV_CODEC_ID_TRUEMOTION1, + AV_CODEC_ID_VMDVIDEO, + AV_CODEC_ID_MSZH, + AV_CODEC_ID_ZLIB, + AV_CODEC_ID_QTRLE, + AV_CODEC_ID_TSCC, + AV_CODEC_ID_ULTI, + AV_CODEC_ID_QDRAW, + AV_CODEC_ID_VIXL, + AV_CODEC_ID_QPEG, + AV_CODEC_ID_PNG, + AV_CODEC_ID_PPM, + AV_CODEC_ID_PBM, + AV_CODEC_ID_PGM, + AV_CODEC_ID_PGMYUV, + AV_CODEC_ID_PAM, + AV_CODEC_ID_FFVHUFF, + AV_CODEC_ID_RV30, + AV_CODEC_ID_RV40, + AV_CODEC_ID_VC1, + AV_CODEC_ID_WMV3, + AV_CODEC_ID_LOCO, + AV_CODEC_ID_WNV1, + AV_CODEC_ID_AASC, + AV_CODEC_ID_INDEO2, + AV_CODEC_ID_FRAPS, + AV_CODEC_ID_TRUEMOTION2, + AV_CODEC_ID_BMP, + AV_CODEC_ID_CSCD, + AV_CODEC_ID_MMVIDEO, + AV_CODEC_ID_ZMBV, + AV_CODEC_ID_AVS, + AV_CODEC_ID_SMACKVIDEO, + AV_CODEC_ID_NUV, + AV_CODEC_ID_KMVC, + AV_CODEC_ID_FLASHSV, + AV_CODEC_ID_CAVS, + AV_CODEC_ID_JPEG2000, + AV_CODEC_ID_VMNC, + AV_CODEC_ID_VP5, + AV_CODEC_ID_VP6, + AV_CODEC_ID_VP6F, + AV_CODEC_ID_TARGA, + AV_CODEC_ID_DSICINVIDEO, + AV_CODEC_ID_TIERTEXSEQVIDEO, + AV_CODEC_ID_TIFF, + AV_CODEC_ID_GIF, + AV_CODEC_ID_DXA, + AV_CODEC_ID_DNXHD, + AV_CODEC_ID_THP, + AV_CODEC_ID_SGI, + AV_CODEC_ID_C93, + AV_CODEC_ID_BETHSOFTVID, + AV_CODEC_ID_PTX, + AV_CODEC_ID_TXD, + AV_CODEC_ID_VP6A, + AV_CODEC_ID_AMV, + AV_CODEC_ID_VB, + AV_CODEC_ID_PCX, + AV_CODEC_ID_SUNRAST, + AV_CODEC_ID_INDEO4, + AV_CODEC_ID_INDEO5, + AV_CODEC_ID_MIMIC, + AV_CODEC_ID_RL2, + AV_CODEC_ID_ESCAPE124, + AV_CODEC_ID_DIRAC, + AV_CODEC_ID_BFI, + AV_CODEC_ID_CMV, + AV_CODEC_ID_MOTIONPIXELS, + AV_CODEC_ID_TGV, + AV_CODEC_ID_TGQ, + AV_CODEC_ID_TQI, + AV_CODEC_ID_AURA, + AV_CODEC_ID_AURA2, + AV_CODEC_ID_V210X, + AV_CODEC_ID_TMV, + AV_CODEC_ID_V210, + AV_CODEC_ID_DPX, + AV_CODEC_ID_MAD, + AV_CODEC_ID_FRWU, + AV_CODEC_ID_FLASHSV2, + AV_CODEC_ID_CDGRAPHICS, + AV_CODEC_ID_R210, + AV_CODEC_ID_ANM, + AV_CODEC_ID_BINKVIDEO, + AV_CODEC_ID_IFF_ILBM, +#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM + AV_CODEC_ID_KGV1, + AV_CODEC_ID_YOP, + AV_CODEC_ID_VP8, + AV_CODEC_ID_PICTOR, + AV_CODEC_ID_ANSI, + AV_CODEC_ID_A64_MULTI, + AV_CODEC_ID_A64_MULTI5, + AV_CODEC_ID_R10K, + AV_CODEC_ID_MXPEG, + AV_CODEC_ID_LAGARITH, + AV_CODEC_ID_PRORES, + AV_CODEC_ID_JV, + AV_CODEC_ID_DFA, + AV_CODEC_ID_WMV3IMAGE, + AV_CODEC_ID_VC1IMAGE, + AV_CODEC_ID_UTVIDEO, + AV_CODEC_ID_BMV_VIDEO, + AV_CODEC_ID_VBLE, + AV_CODEC_ID_DXTORY, + AV_CODEC_ID_V410, + AV_CODEC_ID_XWD, + AV_CODEC_ID_CDXL, + AV_CODEC_ID_XBM, + AV_CODEC_ID_ZEROCODEC, + AV_CODEC_ID_MSS1, + AV_CODEC_ID_MSA1, + AV_CODEC_ID_TSCC2, + AV_CODEC_ID_MTS2, + AV_CODEC_ID_CLLC, + AV_CODEC_ID_MSS2, + AV_CODEC_ID_VP9, + AV_CODEC_ID_AIC, + AV_CODEC_ID_ESCAPE130, + AV_CODEC_ID_G2M, + AV_CODEC_ID_WEBP, + AV_CODEC_ID_HNM4_VIDEO, + AV_CODEC_ID_HEVC, +#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC + AV_CODEC_ID_FIC, + AV_CODEC_ID_ALIAS_PIX, + AV_CODEC_ID_BRENDER_PIX, + AV_CODEC_ID_PAF_VIDEO, + AV_CODEC_ID_EXR, + AV_CODEC_ID_VP7, + AV_CODEC_ID_SANM, + AV_CODEC_ID_SGIRLE, + AV_CODEC_ID_MVC1, + AV_CODEC_ID_MVC2, + AV_CODEC_ID_HQX, + AV_CODEC_ID_TDSC, + AV_CODEC_ID_HQ_HQA, + AV_CODEC_ID_HAP, + AV_CODEC_ID_DDS, + AV_CODEC_ID_DXV, + AV_CODEC_ID_SCREENPRESSO, + AV_CODEC_ID_RSCC, + AV_CODEC_ID_AVS2, + AV_CODEC_ID_PGX, + AV_CODEC_ID_AVS3, + AV_CODEC_ID_MSP2, + AV_CODEC_ID_VVC, +#define AV_CODEC_ID_H266 AV_CODEC_ID_VVC + + AV_CODEC_ID_Y41P = 0x8000, + AV_CODEC_ID_AVRP, + AV_CODEC_ID_012V, + AV_CODEC_ID_AVUI, + AV_CODEC_ID_AYUV, + AV_CODEC_ID_TARGA_Y216, + AV_CODEC_ID_V308, + AV_CODEC_ID_V408, + AV_CODEC_ID_YUV4, + AV_CODEC_ID_AVRN, + AV_CODEC_ID_CPIA, + AV_CODEC_ID_XFACE, + AV_CODEC_ID_SNOW, + AV_CODEC_ID_SMVJPEG, + AV_CODEC_ID_APNG, + AV_CODEC_ID_DAALA, + AV_CODEC_ID_CFHD, + AV_CODEC_ID_TRUEMOTION2RT, + AV_CODEC_ID_M101, + AV_CODEC_ID_MAGICYUV, + AV_CODEC_ID_SHEERVIDEO, + AV_CODEC_ID_YLC, + AV_CODEC_ID_PSD, + AV_CODEC_ID_PIXLET, + AV_CODEC_ID_SPEEDHQ, + AV_CODEC_ID_FMVC, + AV_CODEC_ID_SCPR, + AV_CODEC_ID_CLEARVIDEO, + AV_CODEC_ID_XPM, + AV_CODEC_ID_AV1, + AV_CODEC_ID_BITPACKED, + AV_CODEC_ID_MSCC, + AV_CODEC_ID_SRGC, + AV_CODEC_ID_SVG, + AV_CODEC_ID_GDV, + AV_CODEC_ID_FITS, + AV_CODEC_ID_IMM4, + AV_CODEC_ID_PROSUMER, + AV_CODEC_ID_MWSC, + AV_CODEC_ID_WCMV, + AV_CODEC_ID_RASC, + AV_CODEC_ID_HYMT, + AV_CODEC_ID_ARBC, + AV_CODEC_ID_AGM, + AV_CODEC_ID_LSCR, + AV_CODEC_ID_VP4, + AV_CODEC_ID_IMM5, + AV_CODEC_ID_MVDV, + AV_CODEC_ID_MVHA, + AV_CODEC_ID_CDTOONS, + AV_CODEC_ID_MV30, + AV_CODEC_ID_NOTCHLC, + AV_CODEC_ID_PFM, + AV_CODEC_ID_MOBICLIP, + AV_CODEC_ID_PHOTOCD, + AV_CODEC_ID_IPU, + AV_CODEC_ID_ARGO, + AV_CODEC_ID_CRI, + AV_CODEC_ID_SIMBIOSIS_IMX, + AV_CODEC_ID_SGA_VIDEO, + + /* various PCM "codecs" */ + AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs + AV_CODEC_ID_PCM_S16LE = 0x10000, + AV_CODEC_ID_PCM_S16BE, + AV_CODEC_ID_PCM_U16LE, + AV_CODEC_ID_PCM_U16BE, + AV_CODEC_ID_PCM_S8, + AV_CODEC_ID_PCM_U8, + AV_CODEC_ID_PCM_MULAW, + AV_CODEC_ID_PCM_ALAW, + AV_CODEC_ID_PCM_S32LE, + AV_CODEC_ID_PCM_S32BE, + AV_CODEC_ID_PCM_U32LE, + AV_CODEC_ID_PCM_U32BE, + AV_CODEC_ID_PCM_S24LE, + AV_CODEC_ID_PCM_S24BE, + AV_CODEC_ID_PCM_U24LE, + AV_CODEC_ID_PCM_U24BE, + AV_CODEC_ID_PCM_S24DAUD, + AV_CODEC_ID_PCM_ZORK, + AV_CODEC_ID_PCM_S16LE_PLANAR, + AV_CODEC_ID_PCM_DVD, + AV_CODEC_ID_PCM_F32BE, + AV_CODEC_ID_PCM_F32LE, + AV_CODEC_ID_PCM_F64BE, + AV_CODEC_ID_PCM_F64LE, + AV_CODEC_ID_PCM_BLURAY, + AV_CODEC_ID_PCM_LXF, + AV_CODEC_ID_S302M, + AV_CODEC_ID_PCM_S8_PLANAR, + AV_CODEC_ID_PCM_S24LE_PLANAR, + AV_CODEC_ID_PCM_S32LE_PLANAR, + AV_CODEC_ID_PCM_S16BE_PLANAR, + + AV_CODEC_ID_PCM_S64LE = 0x10800, + AV_CODEC_ID_PCM_S64BE, + AV_CODEC_ID_PCM_F16LE, + AV_CODEC_ID_PCM_F24LE, + AV_CODEC_ID_PCM_VIDC, + AV_CODEC_ID_PCM_SGA, + + /* various ADPCM codecs */ + AV_CODEC_ID_ADPCM_IMA_QT = 0x11000, + AV_CODEC_ID_ADPCM_IMA_WAV, + AV_CODEC_ID_ADPCM_IMA_DK3, + AV_CODEC_ID_ADPCM_IMA_DK4, + AV_CODEC_ID_ADPCM_IMA_WS, + AV_CODEC_ID_ADPCM_IMA_SMJPEG, + AV_CODEC_ID_ADPCM_MS, + AV_CODEC_ID_ADPCM_4XM, + AV_CODEC_ID_ADPCM_XA, + AV_CODEC_ID_ADPCM_ADX, + AV_CODEC_ID_ADPCM_EA, + AV_CODEC_ID_ADPCM_G726, + AV_CODEC_ID_ADPCM_CT, + AV_CODEC_ID_ADPCM_SWF, + AV_CODEC_ID_ADPCM_YAMAHA, + AV_CODEC_ID_ADPCM_SBPRO_4, + AV_CODEC_ID_ADPCM_SBPRO_3, + AV_CODEC_ID_ADPCM_SBPRO_2, + AV_CODEC_ID_ADPCM_THP, + AV_CODEC_ID_ADPCM_IMA_AMV, + AV_CODEC_ID_ADPCM_EA_R1, + AV_CODEC_ID_ADPCM_EA_R3, + AV_CODEC_ID_ADPCM_EA_R2, + AV_CODEC_ID_ADPCM_IMA_EA_SEAD, + AV_CODEC_ID_ADPCM_IMA_EA_EACS, + AV_CODEC_ID_ADPCM_EA_XAS, + AV_CODEC_ID_ADPCM_EA_MAXIS_XA, + AV_CODEC_ID_ADPCM_IMA_ISS, + AV_CODEC_ID_ADPCM_G722, + AV_CODEC_ID_ADPCM_IMA_APC, + AV_CODEC_ID_ADPCM_VIMA, + + AV_CODEC_ID_ADPCM_AFC = 0x11800, + AV_CODEC_ID_ADPCM_IMA_OKI, + AV_CODEC_ID_ADPCM_DTK, + AV_CODEC_ID_ADPCM_IMA_RAD, + AV_CODEC_ID_ADPCM_G726LE, + AV_CODEC_ID_ADPCM_THP_LE, + AV_CODEC_ID_ADPCM_PSX, + AV_CODEC_ID_ADPCM_AICA, + AV_CODEC_ID_ADPCM_IMA_DAT4, + AV_CODEC_ID_ADPCM_MTAF, + AV_CODEC_ID_ADPCM_AGM, + AV_CODEC_ID_ADPCM_ARGO, + AV_CODEC_ID_ADPCM_IMA_SSI, + AV_CODEC_ID_ADPCM_ZORK, + AV_CODEC_ID_ADPCM_IMA_APM, + AV_CODEC_ID_ADPCM_IMA_ALP, + AV_CODEC_ID_ADPCM_IMA_MTF, + AV_CODEC_ID_ADPCM_IMA_CUNNING, + AV_CODEC_ID_ADPCM_IMA_MOFLEX, + + /* AMR */ + AV_CODEC_ID_AMR_NB = 0x12000, + AV_CODEC_ID_AMR_WB, + + /* RealAudio codecs*/ + AV_CODEC_ID_RA_144 = 0x13000, + AV_CODEC_ID_RA_288, + + /* various DPCM codecs */ + AV_CODEC_ID_ROQ_DPCM = 0x14000, + AV_CODEC_ID_INTERPLAY_DPCM, + AV_CODEC_ID_XAN_DPCM, + AV_CODEC_ID_SOL_DPCM, + + AV_CODEC_ID_SDX2_DPCM = 0x14800, + AV_CODEC_ID_GREMLIN_DPCM, + AV_CODEC_ID_DERF_DPCM, + + /* audio codecs */ + AV_CODEC_ID_MP2 = 0x15000, + AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 + AV_CODEC_ID_AAC, + AV_CODEC_ID_AC3, + AV_CODEC_ID_DTS, + AV_CODEC_ID_VORBIS, + AV_CODEC_ID_DVAUDIO, + AV_CODEC_ID_WMAV1, + AV_CODEC_ID_WMAV2, + AV_CODEC_ID_MACE3, + AV_CODEC_ID_MACE6, + AV_CODEC_ID_VMDAUDIO, + AV_CODEC_ID_FLAC, + AV_CODEC_ID_MP3ADU, + AV_CODEC_ID_MP3ON4, + AV_CODEC_ID_SHORTEN, + AV_CODEC_ID_ALAC, + AV_CODEC_ID_WESTWOOD_SND1, + AV_CODEC_ID_GSM, ///< as in Berlin toast format + AV_CODEC_ID_QDM2, + AV_CODEC_ID_COOK, + AV_CODEC_ID_TRUESPEECH, + AV_CODEC_ID_TTA, + AV_CODEC_ID_SMACKAUDIO, + AV_CODEC_ID_QCELP, + AV_CODEC_ID_WAVPACK, + AV_CODEC_ID_DSICINAUDIO, + AV_CODEC_ID_IMC, + AV_CODEC_ID_MUSEPACK7, + AV_CODEC_ID_MLP, + AV_CODEC_ID_GSM_MS, /* as found in WAV */ + AV_CODEC_ID_ATRAC3, + AV_CODEC_ID_APE, + AV_CODEC_ID_NELLYMOSER, + AV_CODEC_ID_MUSEPACK8, + AV_CODEC_ID_SPEEX, + AV_CODEC_ID_WMAVOICE, + AV_CODEC_ID_WMAPRO, + AV_CODEC_ID_WMALOSSLESS, + AV_CODEC_ID_ATRAC3P, + AV_CODEC_ID_EAC3, + AV_CODEC_ID_SIPR, + AV_CODEC_ID_MP1, + AV_CODEC_ID_TWINVQ, + AV_CODEC_ID_TRUEHD, + AV_CODEC_ID_MP4ALS, + AV_CODEC_ID_ATRAC1, + AV_CODEC_ID_BINKAUDIO_RDFT, + AV_CODEC_ID_BINKAUDIO_DCT, + AV_CODEC_ID_AAC_LATM, + AV_CODEC_ID_QDMC, + AV_CODEC_ID_CELT, + AV_CODEC_ID_G723_1, + AV_CODEC_ID_G729, + AV_CODEC_ID_8SVX_EXP, + AV_CODEC_ID_8SVX_FIB, + AV_CODEC_ID_BMV_AUDIO, + AV_CODEC_ID_RALF, + AV_CODEC_ID_IAC, + AV_CODEC_ID_ILBC, + AV_CODEC_ID_OPUS, + AV_CODEC_ID_COMFORT_NOISE, + AV_CODEC_ID_TAK, + AV_CODEC_ID_METASOUND, + AV_CODEC_ID_PAF_AUDIO, + AV_CODEC_ID_ON2AVC, + AV_CODEC_ID_DSS_SP, + AV_CODEC_ID_CODEC2, + + AV_CODEC_ID_FFWAVESYNTH = 0x15800, + AV_CODEC_ID_SONIC, + AV_CODEC_ID_SONIC_LS, + AV_CODEC_ID_EVRC, + AV_CODEC_ID_SMV, + AV_CODEC_ID_DSD_LSBF, + AV_CODEC_ID_DSD_MSBF, + AV_CODEC_ID_DSD_LSBF_PLANAR, + AV_CODEC_ID_DSD_MSBF_PLANAR, + AV_CODEC_ID_4GV, + AV_CODEC_ID_INTERPLAY_ACM, + AV_CODEC_ID_XMA1, + AV_CODEC_ID_XMA2, + AV_CODEC_ID_DST, + AV_CODEC_ID_ATRAC3AL, + AV_CODEC_ID_ATRAC3PAL, + AV_CODEC_ID_DOLBY_E, + AV_CODEC_ID_APTX, + AV_CODEC_ID_APTX_HD, + AV_CODEC_ID_SBC, + AV_CODEC_ID_ATRAC9, + AV_CODEC_ID_HCOM, + AV_CODEC_ID_ACELP_KELVIN, + AV_CODEC_ID_MPEGH_3D_AUDIO, + AV_CODEC_ID_SIREN, + AV_CODEC_ID_HCA, + AV_CODEC_ID_FASTAUDIO, + + /* subtitle codecs */ + AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. + AV_CODEC_ID_DVD_SUBTITLE = 0x17000, + AV_CODEC_ID_DVB_SUBTITLE, + AV_CODEC_ID_TEXT, ///< raw UTF-8 text + AV_CODEC_ID_XSUB, + AV_CODEC_ID_SSA, + AV_CODEC_ID_MOV_TEXT, + AV_CODEC_ID_HDMV_PGS_SUBTITLE, + AV_CODEC_ID_DVB_TELETEXT, + AV_CODEC_ID_SRT, + + AV_CODEC_ID_MICRODVD = 0x17800, + AV_CODEC_ID_EIA_608, + AV_CODEC_ID_JACOSUB, + AV_CODEC_ID_SAMI, + AV_CODEC_ID_REALTEXT, + AV_CODEC_ID_STL, + AV_CODEC_ID_SUBVIEWER1, + AV_CODEC_ID_SUBVIEWER, + AV_CODEC_ID_SUBRIP, + AV_CODEC_ID_WEBVTT, + AV_CODEC_ID_MPL2, + AV_CODEC_ID_VPLAYER, + AV_CODEC_ID_PJS, + AV_CODEC_ID_ASS, + AV_CODEC_ID_HDMV_TEXT_SUBTITLE, + AV_CODEC_ID_TTML, + AV_CODEC_ID_ARIB_CAPTION, + + /* other specific kind of codecs (generally used for attachments) */ + AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. + AV_CODEC_ID_TTF = 0x18000, + + AV_CODEC_ID_SCTE_35, ///< Contain timestamp estimated through PCR of program stream. + AV_CODEC_ID_EPG, + AV_CODEC_ID_BINTEXT = 0x18800, + AV_CODEC_ID_XBIN, + AV_CODEC_ID_IDF, + AV_CODEC_ID_OTF, + AV_CODEC_ID_SMPTE_KLV, + AV_CODEC_ID_DVD_NAV, + AV_CODEC_ID_TIMED_ID3, + AV_CODEC_ID_BIN_DATA, + + + AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it + + AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + * stream (only used by libavformat) */ + AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems + * stream (only used by libavformat) */ + AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. + AV_CODEC_ID_WRAPPED_AVFRAME = 0x21001, ///< Passthrough codec, AVFrames wrapped in AVPacket +}; + +/** + * Get the type of the given codec. + */ +enum AVMediaType avcodec_get_type(enum AVCodecID codec_id); + +/** + * Get the name of a codec. + * @return a static string identifying the codec; never NULL + */ +const char *avcodec_get_name(enum AVCodecID id); + +/** + * @} + */ + +#endif // AVCODEC_CODEC_ID_H diff -Nru ffmpeg-4.2.2/libavcodec/codec_par.c ffmpeg-4.4/libavcodec/codec_par.c --- ffmpeg-4.2.2/libavcodec/codec_par.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/codec_par.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,202 @@ +/* + * AVCodecParameters functions for libavcodec + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * AVCodecParameters functions for libavcodec. + */ + +#include +#include "libavutil/mem.h" +#include "avcodec.h" +#include "codec_par.h" + +static void codec_parameters_reset(AVCodecParameters *par) +{ + av_freep(&par->extradata); + + memset(par, 0, sizeof(*par)); + + par->codec_type = AVMEDIA_TYPE_UNKNOWN; + par->codec_id = AV_CODEC_ID_NONE; + par->format = -1; + par->field_order = AV_FIELD_UNKNOWN; + par->color_range = AVCOL_RANGE_UNSPECIFIED; + par->color_primaries = AVCOL_PRI_UNSPECIFIED; + par->color_trc = AVCOL_TRC_UNSPECIFIED; + par->color_space = AVCOL_SPC_UNSPECIFIED; + par->chroma_location = AVCHROMA_LOC_UNSPECIFIED; + par->sample_aspect_ratio = (AVRational){ 0, 1 }; + par->profile = FF_PROFILE_UNKNOWN; + par->level = FF_LEVEL_UNKNOWN; +} + +AVCodecParameters *avcodec_parameters_alloc(void) +{ + AVCodecParameters *par = av_mallocz(sizeof(*par)); + + if (!par) + return NULL; + codec_parameters_reset(par); + return par; +} + +void avcodec_parameters_free(AVCodecParameters **ppar) +{ + AVCodecParameters *par = *ppar; + + if (!par) + return; + codec_parameters_reset(par); + + av_freep(ppar); +} + +int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src) +{ + codec_parameters_reset(dst); + memcpy(dst, src, sizeof(*dst)); + + dst->extradata = NULL; + dst->extradata_size = 0; + if (src->extradata) { + dst->extradata = av_mallocz(src->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!dst->extradata) + return AVERROR(ENOMEM); + memcpy(dst->extradata, src->extradata, src->extradata_size); + dst->extradata_size = src->extradata_size; + } + + return 0; +} + +int avcodec_parameters_from_context(AVCodecParameters *par, + const AVCodecContext *codec) +{ + codec_parameters_reset(par); + + par->codec_type = codec->codec_type; + par->codec_id = codec->codec_id; + par->codec_tag = codec->codec_tag; + + par->bit_rate = codec->bit_rate; + par->bits_per_coded_sample = codec->bits_per_coded_sample; + par->bits_per_raw_sample = codec->bits_per_raw_sample; + par->profile = codec->profile; + par->level = codec->level; + + switch (par->codec_type) { + case AVMEDIA_TYPE_VIDEO: + par->format = codec->pix_fmt; + par->width = codec->width; + par->height = codec->height; + par->field_order = codec->field_order; + par->color_range = codec->color_range; + par->color_primaries = codec->color_primaries; + par->color_trc = codec->color_trc; + par->color_space = codec->colorspace; + par->chroma_location = codec->chroma_sample_location; + par->sample_aspect_ratio = codec->sample_aspect_ratio; + par->video_delay = codec->has_b_frames; + break; + case AVMEDIA_TYPE_AUDIO: + par->format = codec->sample_fmt; + par->channel_layout = codec->channel_layout; + par->channels = codec->channels; + par->sample_rate = codec->sample_rate; + par->block_align = codec->block_align; + par->frame_size = codec->frame_size; + par->initial_padding = codec->initial_padding; + par->trailing_padding = codec->trailing_padding; + par->seek_preroll = codec->seek_preroll; + break; + case AVMEDIA_TYPE_SUBTITLE: + par->width = codec->width; + par->height = codec->height; + break; + } + + if (codec->extradata) { + par->extradata = av_mallocz(codec->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!par->extradata) + return AVERROR(ENOMEM); + memcpy(par->extradata, codec->extradata, codec->extradata_size); + par->extradata_size = codec->extradata_size; + } + + return 0; +} + +int avcodec_parameters_to_context(AVCodecContext *codec, + const AVCodecParameters *par) +{ + codec->codec_type = par->codec_type; + codec->codec_id = par->codec_id; + codec->codec_tag = par->codec_tag; + + codec->bit_rate = par->bit_rate; + codec->bits_per_coded_sample = par->bits_per_coded_sample; + codec->bits_per_raw_sample = par->bits_per_raw_sample; + codec->profile = par->profile; + codec->level = par->level; + + switch (par->codec_type) { + case AVMEDIA_TYPE_VIDEO: + codec->pix_fmt = par->format; + codec->width = par->width; + codec->height = par->height; + codec->field_order = par->field_order; + codec->color_range = par->color_range; + codec->color_primaries = par->color_primaries; + codec->color_trc = par->color_trc; + codec->colorspace = par->color_space; + codec->chroma_sample_location = par->chroma_location; + codec->sample_aspect_ratio = par->sample_aspect_ratio; + codec->has_b_frames = par->video_delay; + break; + case AVMEDIA_TYPE_AUDIO: + codec->sample_fmt = par->format; + codec->channel_layout = par->channel_layout; + codec->channels = par->channels; + codec->sample_rate = par->sample_rate; + codec->block_align = par->block_align; + codec->frame_size = par->frame_size; + codec->delay = + codec->initial_padding = par->initial_padding; + codec->trailing_padding = par->trailing_padding; + codec->seek_preroll = par->seek_preroll; + break; + case AVMEDIA_TYPE_SUBTITLE: + codec->width = par->width; + codec->height = par->height; + break; + } + + if (par->extradata) { + av_freep(&codec->extradata); + codec->extradata = av_mallocz(par->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!codec->extradata) + return AVERROR(ENOMEM); + memcpy(codec->extradata, par->extradata, par->extradata_size); + codec->extradata_size = par->extradata_size; + } + + return 0; +} diff -Nru ffmpeg-4.2.2/libavcodec/codec_par.h ffmpeg-4.4/libavcodec/codec_par.h --- ffmpeg-4.2.2/libavcodec/codec_par.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/codec_par.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,229 @@ +/* + * Codec parameters public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_CODEC_PAR_H +#define AVCODEC_CODEC_PAR_H + +#include + +#include "libavutil/avutil.h" +#include "libavutil/rational.h" +#include "libavutil/pixfmt.h" + +#include "codec_id.h" + +/** + * @addtogroup lavc_core + */ + +enum AVFieldOrder { + AV_FIELD_UNKNOWN, + AV_FIELD_PROGRESSIVE, + AV_FIELD_TT, //< Top coded_first, top displayed first + AV_FIELD_BB, //< Bottom coded first, bottom displayed first + AV_FIELD_TB, //< Top coded first, bottom displayed first + AV_FIELD_BT, //< Bottom coded first, top displayed first +}; + +/** + * This struct describes the properties of an encoded stream. + * + * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must + * be allocated with avcodec_parameters_alloc() and freed with + * avcodec_parameters_free(). + */ +typedef struct AVCodecParameters { + /** + * General type of the encoded data. + */ + enum AVMediaType codec_type; + /** + * Specific type of the encoded data (the codec used). + */ + enum AVCodecID codec_id; + /** + * Additional information about the codec (corresponds to the AVI FOURCC). + */ + uint32_t codec_tag; + + /** + * Extra binary data needed for initializing the decoder, codec-dependent. + * + * Must be allocated with av_malloc() and will be freed by + * avcodec_parameters_free(). The allocated size of extradata must be at + * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding + * bytes zeroed. + */ + uint8_t *extradata; + /** + * Size of the extradata content in bytes. + */ + int extradata_size; + + /** + * - video: the pixel format, the value corresponds to enum AVPixelFormat. + * - audio: the sample format, the value corresponds to enum AVSampleFormat. + */ + int format; + + /** + * The average bitrate of the encoded data (in bits per second). + */ + int64_t bit_rate; + + /** + * The number of bits per sample in the codedwords. + * + * This is basically the bitrate per sample. It is mandatory for a bunch of + * formats to actually decode them. It's the number of bits for one sample in + * the actual coded bitstream. + * + * This could be for example 4 for ADPCM + * For PCM formats this matches bits_per_raw_sample + * Can be 0 + */ + int bits_per_coded_sample; + + /** + * This is the number of valid bits in each output sample. If the + * sample format has more bits, the least significant bits are additional + * padding bits, which are always 0. Use right shifts to reduce the sample + * to its actual size. For example, audio formats with 24 bit samples will + * have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32. + * To get the original sample use "(int32_t)sample >> 8"." + * + * For ADPCM this might be 12 or 16 or similar + * Can be 0 + */ + int bits_per_raw_sample; + + /** + * Codec-specific bitstream restrictions that the stream conforms to. + */ + int profile; + int level; + + /** + * Video only. The dimensions of the video frame in pixels. + */ + int width; + int height; + + /** + * Video only. The aspect ratio (width / height) which a single pixel + * should have when displayed. + * + * When the aspect ratio is unknown / undefined, the numerator should be + * set to 0 (the denominator may have any value). + */ + AVRational sample_aspect_ratio; + + /** + * Video only. The order of the fields in interlaced video. + */ + enum AVFieldOrder field_order; + + /** + * Video only. Additional colorspace characteristics. + */ + enum AVColorRange color_range; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace color_space; + enum AVChromaLocation chroma_location; + + /** + * Video only. Number of delayed frames. + */ + int video_delay; + + /** + * Audio only. The channel layout bitmask. May be 0 if the channel layout is + * unknown or unspecified, otherwise the number of bits set must be equal to + * the channels field. + */ + uint64_t channel_layout; + /** + * Audio only. The number of audio channels. + */ + int channels; + /** + * Audio only. The number of audio samples per second. + */ + int sample_rate; + /** + * Audio only. The number of bytes per coded audio frame, required by some + * formats. + * + * Corresponds to nBlockAlign in WAVEFORMATEX. + */ + int block_align; + /** + * Audio only. Audio frame size, if known. Required by some formats to be static. + */ + int frame_size; + + /** + * Audio only. The amount of padding (in samples) inserted by the encoder at + * the beginning of the audio. I.e. this number of leading decoded samples + * must be discarded by the caller to get the original audio without leading + * padding. + */ + int initial_padding; + /** + * Audio only. The amount of padding (in samples) appended by the encoder to + * the end of the audio. I.e. this number of decoded samples must be + * discarded by the caller from the end of the stream to get the original + * audio without any trailing padding. + */ + int trailing_padding; + /** + * Audio only. Number of samples to skip after a discontinuity. + */ + int seek_preroll; +} AVCodecParameters; + +/** + * Allocate a new AVCodecParameters and set its fields to default values + * (unknown/invalid/0). The returned struct must be freed with + * avcodec_parameters_free(). + */ +AVCodecParameters *avcodec_parameters_alloc(void); + +/** + * Free an AVCodecParameters instance and everything associated with it and + * write NULL to the supplied pointer. + */ +void avcodec_parameters_free(AVCodecParameters **par); + +/** + * Copy the contents of src to dst. Any allocated fields in dst are freed and + * replaced with newly allocated duplicates of the corresponding fields in src. + * + * @return >= 0 on success, a negative AVERROR code on failure. + */ +int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src); + + +/** + * @} + */ + +#endif // AVCODEC_CODEC_PAR_H diff -Nru ffmpeg-4.2.2/libavcodec/cook.c ffmpeg-4.4/libavcodec/cook.c --- ffmpeg-4.2.2/libavcodec/cook.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cook.c 2021-04-08 21:28:39.000000000 +0000 @@ -44,6 +44,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/lfg.h" +#include "libavutil/mem_internal.h" #include "audiodsp.h" #include "avcodec.h" @@ -60,11 +61,14 @@ #define MONO 0x1000001 #define STEREO 0x1000002 #define JOINT_STEREO 0x1000003 -#define MC_COOK 0x2000000 // multichannel Cook, not supported +#define MC_COOK 0x2000000 #define SUBBAND_SIZE 20 #define MAX_SUBPACKETS 5 +#define QUANT_VLC_BITS 9 +#define COUPLING_VLC_BITS 6 + typedef struct cook_gains { int *now; int *previous; @@ -190,6 +194,21 @@ (1.0 / (double) q->gain_size_factor)); } +static av_cold int build_vlc(VLC *vlc, int nb_bits, const uint8_t counts[16], + const void *syms, int symbol_size, int offset, + void *logctx) +{ + uint8_t lens[MAX_COOK_VLC_ENTRIES]; + unsigned num = 0; + + for (int i = 0; i < 16; i++) + for (unsigned count = num + counts[i]; num < count; num++) + lens[num] = i + 1; + + return ff_init_vlc_from_lengths(vlc, nb_bits, num, lens, 1, + syms, symbol_size, symbol_size, + offset, 0, logctx); +} static av_cold int init_cook_vlc_tables(COOKContext *q) { @@ -197,23 +216,24 @@ result = 0; for (i = 0; i < 13; i++) { - result |= init_vlc(&q->envelope_quant_index[i], 9, 24, - envelope_quant_index_huffbits[i], 1, 1, - envelope_quant_index_huffcodes[i], 2, 2, 0); + result |= build_vlc(&q->envelope_quant_index[i], QUANT_VLC_BITS, + envelope_quant_index_huffcounts[i], + envelope_quant_index_huffsyms[i], 1, -12, q->avctx); } av_log(q->avctx, AV_LOG_DEBUG, "sqvh VLC init\n"); for (i = 0; i < 7; i++) { - result |= init_vlc(&q->sqvh[i], vhvlcsize_tab[i], vhsize_tab[i], - cvh_huffbits[i], 1, 1, - cvh_huffcodes[i], 2, 2, 0); + int sym_size = 1 + (i == 3); + result |= build_vlc(&q->sqvh[i], vhvlcsize_tab[i], + cvh_huffcounts[i], + cvh_huffsyms[i], sym_size, 0, q->avctx); } for (i = 0; i < q->num_subpackets; i++) { if (q->subpacket[i].joint_stereo == 1) { - result |= init_vlc(&q->subpacket[i].channel_coupling, 6, - (1 << q->subpacket[i].js_vlc_bits) - 1, - ccpl_huffbits[q->subpacket[i].js_vlc_bits - 2], 1, 1, - ccpl_huffcodes[q->subpacket[i].js_vlc_bits - 2], 2, 2, 0); + result |= build_vlc(&q->subpacket[i].channel_coupling, COUPLING_VLC_BITS, + ccpl_huffcounts[q->subpacket[i].js_vlc_bits - 2], + ccpl_huffsyms[q->subpacket[i].js_vlc_bits - 2], 1, + 0, q->avctx); av_log(q->avctx, AV_LOG_DEBUG, "subpacket %i Joint-stereo VLC used.\n", i); } } @@ -380,8 +400,8 @@ vlc_index = 13; // the VLC tables >13 are identical to No. 13 j = get_vlc2(&q->gb, q->envelope_quant_index[vlc_index - 1].table, - q->envelope_quant_index[vlc_index - 1].bits, 2); - quant_index_table[i] = quant_index_table[i - 1] + j - 12; // differential encoding + QUANT_VLC_BITS, 2); + quant_index_table[i] = quant_index_table[i - 1] + j; // differential encoding if (quant_index_table[i] > 63 || quant_index_table[i] < -63) { av_log(q->avctx, AV_LOG_ERROR, "Invalid quantizer %d at position %d, outside [-63, 63] range\n", @@ -759,7 +779,7 @@ for (i = 0; i < length; i++) decouple_tab[start + i] = get_vlc2(&q->gb, p->channel_coupling.table, - p->channel_coupling.bits, 3); + COUPLING_VLC_BITS, 3); else for (i = 0; i < length; i++) { int v = get_bits(&q->gb, p->js_vlc_bits); @@ -1084,6 +1104,10 @@ ff_audiodsp_init(&q->adsp); while (bytestream2_get_bytes_left(&gb)) { + if (s >= FFMIN(MAX_SUBPACKETS, avctx->block_align)) { + avpriv_request_sample(avctx, "subpackets > %d", FFMIN(MAX_SUBPACKETS, avctx->block_align)); + return AVERROR_PATCHWELCOME; + } /* 8 for mono, 16 for stereo, ? for multichannel Swap to right endianness so we don't need to care later on. */ q->subpacket[s].cookversion = bytestream2_get_be32(&gb); @@ -1215,10 +1239,6 @@ q->num_subpackets++; s++; - if (s > FFMIN(MAX_SUBPACKETS, avctx->block_align)) { - avpriv_request_sample(avctx, "subpackets > %d", FFMIN(MAX_SUBPACKETS, avctx->block_align)); - return AVERROR_PATCHWELCOME; - } } /* Try to catch some obviously faulty streams, otherwise it might be exploitable */ diff -Nru ffmpeg-4.2.2/libavcodec/cookdata.h ffmpeg-4.4/libavcodec/cookdata.h --- ffmpeg-4.2.2/libavcodec/cookdata.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cookdata.h 2021-04-08 21:28:39.000000000 +0000 @@ -70,436 +70,216 @@ /* VLC data */ -static const int vhsize_tab[7] = { - 191, 97, 48, 607, 246, 230, 32, -}; +#define MAX_COOK_VLC_ENTRIES 520 static const int vhvlcsize_tab[7] = { 8, 7, 7, 10, 9, 9, 6, }; -static const uint8_t envelope_quant_index_huffbits[13][24] = { - { 4, 6, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 5, 7, 8, 9, 11, 11, 12, 12, 12, 12 }, - { 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 7, 9, 11, 12, 13, 15, 15, 15, 16, 16 }, - { 12, 10, 8, 6, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 5, 5, 7, 9, 11, 13, 14, 14 }, - { 13, 10, 9, 9, 7, 7, 5, 5, 4, 3, 3, 3, 3, 3, 4, 4, 4, 5, 7, 9, 11, 13, 13, 13 }, - { 12, 13, 10, 8, 6, 6, 5, 5, 4, 4, 3, 3, 3, 3, 3, 4, 5, 5, 6, 7, 9, 11, 14, 14 }, - { 12, 11, 9, 8, 8, 7, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 5, 7, 8, 10, 13, 14, 14 }, - { 15, 16, 15, 12, 10, 8, 6, 5, 4, 3, 3, 3, 2, 3, 4, 5, 5, 7, 9, 11, 13, 16, 16, 16 }, - { 14, 14, 11, 10, 9, 7, 7, 5, 5, 4, 3, 3, 2, 3, 3, 4, 5, 7, 9, 9, 12, 14, 15, 15 }, - { 9, 9, 9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 13 }, - { 14, 12, 10, 8, 6, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 8, 8, 9, 11, 14, 14, 14 }, - { 13, 10, 9, 8, 6, 6, 5, 4, 4, 4, 3, 3, 2, 3, 4, 5, 6, 8, 9, 9, 11, 12, 14, 14 }, - { 16, 13, 12, 11, 9, 6, 5, 5, 4, 4, 4, 3, 2, 3, 3, 4, 5, 7, 8, 10, 14, 16, 16, 16 }, - { 13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14 }, -}; - -static const uint16_t envelope_quant_index_huffcodes[13][24] = { - {0x0006, 0x003e, 0x001c, 0x001d, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x0000, 0x0001, - 0x0002, 0x000d, 0x001e, 0x007e, 0x00fe, 0x01fe, 0x07fc, 0x07fd, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff}, - {0x03fe, 0x00fe, 0x003e, 0x001c, 0x001d, 0x000c, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, - 0x000d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x0ffe, 0x1ffe, 0x7ffc, 0x7ffd, 0x7ffe, 0xfffe, 0xffff}, - {0x0ffe, 0x03fe, 0x00fe, 0x003e, 0x001c, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x0000, - 0x0001, 0x0002, 0x000c, 0x000d, 0x001d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x1ffe, 0x3ffe, 0x3fff}, - {0x1ffc, 0x03fe, 0x01fc, 0x01fd, 0x007c, 0x007d, 0x001c, 0x001d, 0x000a, 0x0000, 0x0001, 0x0002, - 0x0003, 0x0004, 0x000b, 0x000c, 0x000d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x1ffd, 0x1ffe, 0x1fff}, - {0x0ffe, 0x1ffe, 0x03fe, 0x00fe, 0x003c, 0x003d, 0x001a, 0x001b, 0x000a, 0x000b, 0x0000, 0x0001, - 0x0002, 0x0003, 0x0004, 0x000c, 0x001c, 0x001d, 0x003e, 0x007e, 0x01fe, 0x07fe, 0x3ffe, 0x3fff}, - {0x0ffe, 0x07fe, 0x01fe, 0x00fc, 0x00fd, 0x007c, 0x001c, 0x000a, 0x000b, 0x0000, 0x0001, 0x0002, - 0x0003, 0x0004, 0x000c, 0x000d, 0x001d, 0x001e, 0x007d, 0x00fe, 0x03fe, 0x1ffe, 0x3ffe, 0x3fff}, - {0x7ffc, 0xfffc, 0x7ffd, 0x0ffe, 0x03fe, 0x00fe, 0x003e, 0x001c, 0x000c, 0x0002, 0x0003, 0x0004, - 0x0000, 0x0005, 0x000d, 0x001d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x1ffe, 0xfffd, 0xfffe, 0xffff}, - {0x3ffc, 0x3ffd, 0x07fe, 0x03fe, 0x01fc, 0x007c, 0x007d, 0x001c, 0x001d, 0x000c, 0x0002, 0x0003, - 0x0000, 0x0004, 0x0005, 0x000d, 0x001e, 0x007e, 0x01fd, 0x01fe, 0x0ffe, 0x3ffe, 0x7ffe, 0x7fff}, - {0x01fc, 0x01fd, 0x01fe, 0x00fc, 0x007c, 0x003c, 0x001c, 0x000c, 0x0000, 0x0001, 0x0002, 0x0003, - 0x0004, 0x0005, 0x000d, 0x001d, 0x003d, 0x007d, 0x00fd, 0x03fe, 0x07fe, 0x0ffe, 0x1ffe, 0x1fff}, - {0x3ffc, 0x0ffe, 0x03fe, 0x00fc, 0x003c, 0x003d, 0x001c, 0x000c, 0x0000, 0x0001, 0x0002, 0x0003, - 0x0004, 0x0005, 0x000d, 0x001d, 0x003e, 0x00fd, 0x00fe, 0x01fe, 0x07fe, 0x3ffd, 0x3ffe, 0x3fff}, - {0x1ffe, 0x03fe, 0x01fc, 0x00fc, 0x003c, 0x003d, 0x001c, 0x000a, 0x000b, 0x000c, 0x0002, 0x0003, - 0x0000, 0x0004, 0x000d, 0x001d, 0x003e, 0x00fd, 0x01fd, 0x01fe, 0x07fe, 0x0ffe, 0x3ffe, 0x3fff}, - {0xfffc, 0x1ffe, 0x0ffe, 0x07fe, 0x01fe, 0x003e, 0x001c, 0x001d, 0x000a, 0x000b, 0x000c, 0x0002, - 0x0000, 0x0003, 0x0004, 0x000d, 0x001e, 0x007e, 0x00fe, 0x03fe, 0x3ffe, 0xfffd, 0xfffe, 0xffff}, - {0x1ffc, 0x3ffa, 0x3ffb, 0x3ffc, 0x03fe, 0x00fe, 0x007c, 0x007d, 0x001c, 0x000c, 0x0002, 0x0003, - 0x0000, 0x0004, 0x0005, 0x000d, 0x001d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x3ffd, 0x3ffe, 0x3fff}, -}; - - -static const uint8_t cvh_huffbits0[191] = { - 1, 4, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, - 11, 11, 4, 5, 6, 7, 7, 8, 8, 9, 9, 9, - 9, 10, 11, 11, 5, 6, 7, 8, 8, 9, 9, 9, - 9, 10, 10, 10, 11, 12, 6, 7, 8, 9, 9, 9, - 9, 10, 10, 10, 10, 11, 12, 13, 7, 7, 8, 9, - 9, 9, 10, 10, 10, 10, 11, 11, 12, 13, 8, 8, - 9, 9, 9, 10, 10, 10, 10, 11, 11, 12, 13, 14, - 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, - 13, 15, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, - 12, 13, 14, 15, 9, 9, 9, 10, 10, 10, 11, 11, - 12, 13, 12, 14, 15, 16, 9, 9, 10, 10, 10, 10, - 11, 12, 12, 14, 14, 16, 16, 0, 9, 9, 10, 10, - 11, 11, 12, 13, 13, 14, 14, 15, 0, 0, 10, 10, - 10, 11, 11, 12, 12, 13, 15, 15, 16, 0, 0, 0, - 11, 11, 11, 12, 13, 13, 13, 15, 16, 16, 0, 0, - 0, 0, 11, 11, 12, 13, 13, 14, 15, 16, 16, -}; - -static const uint16_t cvh_huffcodes0[191] = { - 0x0000,0x0008,0x002c,0x002d,0x0062,0x0063,0x00d4,0x00d5,0x00d6,0x01c6,0x01c7,0x03ca, - 0x07d6,0x07d7,0x0009,0x0014,0x002e,0x0064,0x0065,0x00d7,0x00d8,0x01c8,0x01c9,0x01ca, - 0x01cb,0x03cb,0x07d8,0x07d9,0x0015,0x002f,0x0066,0x00d9,0x00da,0x01cc,0x01cd,0x01ce, - 0x01cf,0x03cc,0x03cd,0x03ce,0x07da,0x0fe4,0x0030,0x0067,0x00db,0x01d0,0x01d1,0x01d2, - 0x01d3,0x03cf,0x03d0,0x03d1,0x03d2,0x07db,0x0fe5,0x1fea,0x0068,0x0069,0x00dc,0x01d4, - 0x01d5,0x01d6,0x03d3,0x03d4,0x03d5,0x03d6,0x07dc,0x07dd,0x0fe6,0x1feb,0x00dd,0x00de, - 0x01d7,0x01d8,0x01d9,0x03d7,0x03d8,0x03d9,0x03da,0x07de,0x07df,0x0fe7,0x1fec,0x3ff2, - 0x00df,0x00e0,0x01da,0x01db,0x03db,0x03dc,0x07e0,0x07e1,0x07e2,0x0fe8,0x0fe9,0x1fed, - 0x1fee,0x7ff4,0x00e1,0x00e2,0x01dc,0x01dd,0x03dd,0x03de,0x07e3,0x07e4,0x07e5,0x0fea, - 0x0feb,0x1fef,0x3ff3,0x7ff5,0x01de,0x01df,0x01e0,0x03df,0x03e0,0x03e1,0x07e6,0x07e7, - 0x0fec,0x1ff0,0x0fed,0x3ff4,0x7ff6,0xfff8,0x01e1,0x01e2,0x03e2,0x03e3,0x03e4,0x03e5, - 0x07e8,0x0fee,0x0fef,0x3ff5,0x3ff6,0xfff9,0xfffa,0xfffa,0x01e3,0x01e4,0x03e6,0x03e7, - 0x07e9,0x07ea,0x0ff0,0x1ff1,0x1ff2,0x3ff7,0x3ff8,0x7ff7,0x7ff7,0xfffa,0x03e8,0x03e9, - 0x03ea,0x07eb,0x07ec,0x0ff1,0x0ff2,0x1ff3,0x7ff8,0x7ff9,0xfffb,0x3ff8,0x7ff7,0x7ff7, - 0x07ed,0x07ee,0x07ef,0x0ff3,0x1ff4,0x1ff5,0x1ff6,0x7ffa,0xfffc,0xfffd,0xfffb,0xfffb, - 0x3ff8,0x7ff7,0x07f0,0x07f1,0x0ff4,0x1ff7,0x1ff8,0x3ff9,0x7ffb,0xfffe,0xffff, -}; - - -static const uint8_t cvh_huffbits1[97] = { - 1, 4, 5, 6, 7, 8, 8, 9, 10, 10, 4, 5, - 6, 7, 7, 8, 8, 9, 9, 11, 5, 5, 6, 7, - 8, 8, 9, 9, 10, 11, 6, 6, 7, 8, 8, 9, - 9, 10, 11, 12, 7, 7, 8, 8, 9, 9, 10, 11, - 11, 13, 8, 8, 8, 9, 9, 10, 10, 11, 12, 14, - 8, 8, 8, 9, 10, 11, 11, 12, 13, 15, 9, 9, - 9, 10, 11, 12, 12, 14, 14, 0, 9, 9, 9, 10, - 11, 12, 14, 16, 0, 0, 10, 10, 11, 12, 13, 14, - 16, -}; - - -static const uint16_t cvh_huffcodes1[97] = { - 0x0000,0x0008,0x0014,0x0030,0x006a,0x00e2,0x00e3,0x01e4,0x03ec,0x03ed,0x0009,0x0015, - 0x0031,0x006b,0x006c,0x00e4,0x00e5,0x01e5,0x01e6,0x07f0,0x0016,0x0017,0x0032,0x006d, - 0x00e6,0x00e7,0x01e7,0x01e8,0x03ee,0x07f1,0x0033,0x0034,0x006e,0x00e8,0x00e9,0x01e9, - 0x01ea,0x03ef,0x07f2,0x0ff6,0x006f,0x0070,0x00ea,0x00eb,0x01eb,0x01ec,0x03f0,0x07f3, - 0x07f4,0x1ffa,0x00ec,0x00ed,0x00ee,0x01ed,0x01ee,0x03f1,0x03f2,0x07f5,0x0ff7,0x3ffa, - 0x00ef,0x00f0,0x00f1,0x01ef,0x03f3,0x07f6,0x07f7,0x0ff8,0x1ffb,0x7ffe,0x01f0,0x01f1, - 0x01f2,0x03f4,0x07f8,0x0ff9,0x0ffa,0x3ffb,0x3ffc,0x0000,0x01f3,0x01f4,0x01f5,0x03f5, - 0x07f9,0x0ffb,0x3ffd,0xfffe,0x0000,0x0000,0x03f6,0x03f7,0x07fa,0x0ffc,0x1ffc,0x3ffe, - 0xffff, -}; - -static const uint8_t cvh_huffbits2[48] = { - 1, 4, 5, 7, 8, 9, 10, 3, 4, 5, 7, 8, - 9, 10, 5, 5, 6, 7, 8, 10, 10, 7, 6, 7, - 8, 9, 10, 12, 8, 8, 8, 9, 10, 12, 14, 8, - 9, 9, 10, 11, 15, 16, 9, 10, 11, 12, 13, 16, -}; - -static const uint16_t cvh_huffcodes2[48] = { - 0x0000,0x000a,0x0018,0x0074,0x00f2,0x01f4,0x03f6,0x0004,0x000b,0x0019,0x0075,0x00f3, - 0x01f5,0x03f7,0x001a,0x001b,0x0038,0x0076,0x00f4,0x03f8,0x03f9,0x0077,0x0039,0x0078, - 0x00f5,0x01f6,0x03fa,0x0ffc,0x00f6,0x00f7,0x00f8,0x01f7,0x03fb,0x0ffd,0x3ffe,0x00f9, - 0x01f8,0x01f9,0x03fc,0x07fc,0x7ffe,0xfffe,0x01fa,0x03fd,0x07fd,0x0ffe,0x1ffe,0xffff, -}; - -static const uint8_t cvh_huffbits3[607] = { - 2, 4, 6, 8, 10, 5, 5, 6, 8, 10, 7, 8, - 8, 10, 12, 9, 9, 10, 12, 15, 10, 11, 13, 16, - 16, 5, 6, 8, 10, 11, 5, 6, 8, 10, 12, 7, - 7, 8, 10, 13, 9, 9, 10, 12, 15, 12, 11, 13, - 16, 16, 7, 9, 10, 12, 15, 7, 8, 10, 12, 13, - 9, 9, 11, 13, 16, 11, 11, 12, 14, 16, 12, 12, - 14, 16, 0, 9, 11, 12, 16, 16, 9, 10, 13, 15, - 16, 10, 11, 12, 16, 16, 13, 13, 16, 16, 16, 16, - 16, 15, 16, 0, 11, 13, 16, 16, 15, 11, 13, 15, - 16, 16, 13, 13, 16, 16, 0, 14, 16, 16, 16, 0, - 16, 16, 0, 0, 0, 4, 6, 8, 10, 13, 6, 6, - 8, 10, 13, 9, 8, 10, 12, 16, 10, 10, 11, 15, - 16, 13, 12, 14, 16, 16, 5, 6, 8, 11, 13, 6, - 6, 8, 10, 13, 8, 8, 9, 11, 14, 10, 10, 12, - 12, 16, 13, 12, 13, 15, 16, 7, 8, 9, 12, 16, - 7, 8, 10, 12, 14, 9, 9, 10, 13, 16, 11, 10, - 12, 15, 16, 13, 13, 16, 16, 0, 9, 11, 13, 16, - 16, 9, 10, 12, 15, 16, 10, 11, 13, 16, 16, 13, - 12, 16, 16, 16, 16, 16, 16, 16, 0, 11, 13, 16, - 16, 16, 11, 13, 16, 16, 16, 12, 13, 15, 16, 0, - 16, 16, 16, 16, 0, 16, 16, 0, 0, 0, 6, 8, - 11, 13, 16, 8, 8, 10, 12, 16, 11, 10, 11, 13, - 16, 12, 13, 13, 15, 16, 16, 16, 14, 16, 0, 6, - 8, 10, 13, 16, 8, 8, 10, 12, 16, 10, 10, 11, - 13, 16, 13, 12, 13, 16, 16, 14, 14, 14, 16, 0, - 8, 9, 11, 13, 16, 8, 9, 11, 16, 14, 10, 10, - 12, 15, 16, 12, 12, 13, 16, 16, 15, 16, 16, 16, - 0, 10, 12, 15, 16, 16, 10, 12, 12, 14, 16, 12, - 12, 13, 16, 16, 14, 15, 16, 16, 0, 16, 16, 16, - 0, 0, 12, 15, 15, 16, 0, 13, 13, 16, 16, 0, - 14, 16, 16, 16, 0, 16, 16, 16, 0, 0, 0, 0, - 0, 0, 0, 8, 10, 13, 15, 16, 10, 11, 13, 16, - 16, 13, 13, 14, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 0, 8, 10, 11, 15, 16, 9, 10, 12, - 16, 16, 12, 12, 15, 16, 16, 16, 14, 16, 16, 16, - 16, 16, 16, 16, 0, 9, 11, 14, 16, 16, 10, 11, - 13, 16, 16, 14, 13, 14, 16, 16, 16, 15, 15, 16, - 0, 16, 16, 16, 0, 0, 11, 13, 16, 16, 16, 11, - 13, 15, 16, 16, 13, 16, 16, 16, 0, 16, 16, 16, - 16, 0, 16, 16, 0, 0, 0, 15, 16, 16, 16, 0, - 14, 16, 16, 16, 0, 16, 16, 16, 0, 0, 16, 16, - 0, 0, 0, 0, 0, 0, 0, 0, 9, 13, 16, 16, - 16, 11, 13, 16, 16, 16, 14, 15, 16, 16, 0, 15, - 16, 16, 16, 0, 16, 16, 0, 0, 0, 9, 13, 15, - 15, 16, 12, 13, 14, 16, 16, 16, 15, 16, 16, 0, - 16, 16, 16, 16, 0, 16, 16, 0, 0, 0, 11, 13, - 15, 16, 0, 12, 14, 16, 16, 0, 16, 16, 16, 16, - 0, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 16, - 16, 16, 16, 0, 16, 16, 16, 16, 0, 16, 16, 16, - 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, - 16, 16, 0, 0, 0, 16, 16, -}; - - -static const uint16_t cvh_huffcodes3[607] = { - 0x0000,0x0004,0x0022,0x00c6,0x03b0,0x000c,0x000d,0x0023,0x00c7,0x03b1,0x005c,0x00c8, - 0x00c9,0x03b2,0x0fa4,0x01c2,0x01c3,0x03b3,0x0fa5,0x7f72,0x03b4,0x07b2,0x1f9a,0xff24, - 0xff25,0x000e,0x0024,0x00ca,0x03b5,0x07b3,0x000f,0x0025,0x00cb,0x03b6,0x0fa6,0x005d, - 0x005e,0x00cc,0x03b7,0x1f9b,0x01c4,0x01c5,0x03b8,0x0fa7,0x7f73,0x0fa8,0x07b4,0x1f9c, - 0xff26,0xff27,0x005f,0x01c6,0x03b9,0x0fa9,0x7f74,0x0060,0x00cd,0x03ba,0x0faa,0x1f9d, - 0x01c7,0x01c8,0x07b5,0x1f9e,0xff28,0x07b6,0x07b7,0x0fab,0x3fa2,0xff29,0x0fac,0x0fad, - 0x3fa3,0xff2a,0x3fa2,0x01c9,0x07b8,0x0fae,0xff2b,0xff2c,0x01ca,0x03bb,0x1f9f,0x7f75, - 0xff2d,0x03bc,0x07b9,0x0faf,0xff2e,0xff2f,0x1fa0,0x1fa1,0xff30,0xff31,0xff32,0xff33, - 0xff34,0x7f76,0xff35,0xff31,0x07ba,0x1fa2,0xff36,0xff37,0x7f77,0x07bb,0x1fa3,0x7f78, - 0xff38,0xff39,0x1fa4,0x1fa5,0xff3a,0xff3b,0xff2e,0x3fa4,0xff3c,0xff3d,0xff3e,0xff31, - 0xff3f,0xff40,0xff30,0xff31,0xff31,0x0005,0x0026,0x00ce,0x03bd,0x1fa6,0x0027,0x0028, - 0x00cf,0x03be,0x1fa7,0x01cb,0x00d0,0x03bf,0x0fb0,0xff41,0x03c0,0x03c1,0x07bc,0x7f79, - 0xff42,0x1fa8,0x0fb1,0x3fa5,0xff43,0xff44,0x0010,0x0029,0x00d1,0x07bd,0x1fa9,0x002a, - 0x002b,0x00d2,0x03c2,0x1faa,0x00d3,0x00d4,0x01cc,0x07be,0x3fa6,0x03c3,0x03c4,0x0fb2, - 0x0fb3,0xff45,0x1fab,0x0fb4,0x1fac,0x7f7a,0xff46,0x0061,0x00d5,0x01cd,0x0fb5,0xff47, - 0x0062,0x00d6,0x03c5,0x0fb6,0x3fa7,0x01ce,0x01cf,0x03c6,0x1fad,0xff48,0x07bf,0x03c7, - 0x0fb7,0x7f7b,0xff49,0x1fae,0x1faf,0xff4a,0xff4b,0x7f7b,0x01d0,0x07c0,0x1fb0,0xff4c, - 0xff4d,0x01d1,0x03c8,0x0fb8,0x7f7c,0xff4e,0x03c9,0x07c1,0x1fb1,0xff4f,0xff50,0x1fb2, - 0x0fb9,0xff51,0xff52,0xff53,0xff54,0xff55,0xff56,0xff57,0xff52,0x07c2,0x1fb3,0xff58, - 0xff59,0xff5a,0x07c3,0x1fb4,0xff5b,0xff5c,0xff5d,0x0fba,0x1fb5,0x7f7d,0xff5e,0xff4f, - 0xff5f,0xff60,0xff61,0xff62,0xff52,0xff63,0xff64,0xff51,0xff52,0xff52,0x002c,0x00d7, - 0x07c4,0x1fb6,0xff65,0x00d8,0x00d9,0x03ca,0x0fbb,0xff66,0x07c5,0x03cb,0x07c6,0x1fb7, - 0xff67,0x0fbc,0x1fb8,0x1fb9,0x7f7e,0xff68,0xff69,0xff6a,0x3fa8,0xff6b,0x7f7e,0x002d, - 0x00da,0x03cc,0x1fba,0xff6c,0x00db,0x00dc,0x03cd,0x0fbd,0xff6d,0x03ce,0x03cf,0x07c7, - 0x1fbb,0xff6e,0x1fbc,0x0fbe,0x1fbd,0xff6f,0xff70,0x3fa9,0x3faa,0x3fab,0xff71,0xff6f, - 0x00dd,0x01d2,0x07c8,0x1fbe,0xff72,0x00de,0x01d3,0x07c9,0xff73,0x3fac,0x03d0,0x03d1, - 0x0fbf,0x7f7f,0xff74,0x0fc0,0x0fc1,0x1fbf,0xff75,0xff76,0x7f80,0xff77,0xff78,0xff79, - 0xff75,0x03d2,0x0fc2,0x7f81,0xff7a,0xff7b,0x03d3,0x0fc3,0x0fc4,0x3fad,0xff7c,0x0fc5, - 0x0fc6,0x1fc0,0xff7d,0xff7e,0x3fae,0x7f82,0xff7f,0xff80,0xff80,0xff81,0xff82,0xff83, - 0xff80,0xff80,0x0fc7,0x7f83,0x7f84,0xff84,0xff7a,0x1fc1,0x1fc2,0xff85,0xff86,0x3fad, - 0x3faf,0xff87,0xff88,0xff89,0xff7d,0xff8a,0xff8b,0xff8c,0xff80,0xff80,0x3fae,0x7f82, - 0xff7f,0xff80,0xff80,0x00df,0x03d4,0x1fc3,0x7f85,0xff8d,0x03d5,0x07ca,0x1fc4,0xff8e, - 0xff8f,0x1fc5,0x1fc6,0x3fb0,0xff90,0xff91,0xff92,0xff93,0xff94,0xff95,0xff96,0xff97, - 0xff98,0xff99,0xff9a,0xff95,0x00e0,0x03d6,0x07cb,0x7f86,0xff9b,0x01d4,0x03d7,0x0fc8, - 0xff9c,0xff9d,0x0fc9,0x0fca,0x7f87,0xff9e,0xff9f,0xffa0,0x3fb1,0xffa1,0xffa2,0xffa3, - 0xffa4,0xffa5,0xffa6,0xffa7,0xffa2,0x01d5,0x07cc,0x3fb2,0xffa8,0xffa9,0x03d8,0x07cd, - 0x1fc7,0xffaa,0xffab,0x3fb3,0x1fc8,0x3fb4,0xffac,0xffad,0xffae,0x7f88,0x7f89,0xffaf, - 0xffaf,0xffb0,0xffb1,0xffb2,0xffaf,0xffaf,0x07ce,0x1fc9,0xffb3,0xffb4,0xffb5,0x07cf, - 0x1fca,0x7f8a,0xffb6,0xffb7,0x1fcb,0xffb8,0xffb9,0xffba,0xffba,0xffbb,0xffbc,0xffbd, - 0xffbe,0xffbe,0xffbf,0xffc0,0xffbd,0xffbe,0xffbe,0x7f8b,0xffc1,0xffc2,0xffc3,0xffb4, - 0x3fb5,0xffc4,0xffc5,0xffc6,0xffb6,0xffc7,0xffc8,0xffc9,0xffba,0xffba,0xffca,0xffcb, - 0xffbd,0xffbe,0xffbe,0xffbb,0xffbc,0xffbd,0xffbe,0xffbe,0x01d6,0x1fcc,0xffcc,0xffcd, - 0xffce,0x07d0,0x1fcd,0xffcf,0xffd0,0xffd1,0x3fb6,0x7f8c,0xffd2,0xffd3,0xff90,0x7f8d, - 0xffd4,0xffd5,0xffd6,0xff95,0xffd7,0xffd8,0xff94,0xff95,0xff95,0x01d7,0x1fce,0x7f8e, - 0x7f8f,0xffd9,0x0fcb,0x1fcf,0x3fb7,0xffda,0xffdb,0xffdc,0x7f90,0xffdd,0xffde,0xff9e, - 0xffdf,0xffe0,0xffe1,0xffe2,0xffa2,0xffe3,0xffe4,0xffa1,0xffa2,0xffa2,0x07d1,0x1fd0, - 0x7f91,0xffe5,0xffa8,0x0fcc,0x3fb8,0xffe6,0xffe7,0xffaa,0xffe8,0xffe9,0xffea,0xffeb, - 0xffac,0xffec,0xffed,0xffee,0xffaf,0xffaf,0xffae,0x7f88,0x7f89,0xffaf,0xffaf,0xffef, - 0xfff0,0xfff1,0xfff2,0xffb4,0xfff3,0xfff4,0xfff5,0xfff6,0xffb6,0xfff7,0xfff8,0xfff9, - 0xffba,0xffba,0xfffa,0xfffb,0xffbd,0xffbe,0xffbe,0xffbb,0xffbc,0xffbd,0xffbe,0xffbe, - 0xfffc,0xfffd,0xffb3,0xffb4,0xffb4,0xfffe,0xffff, -}; - -static const uint8_t cvh_huffbits4[246] = { - 2, 4, 7, 10, 4, 5, 7, 10, 7, 8, 10, 14, - 11, 11, 15, 15, 4, 5, 9, 12, 5, 5, 8, 12, - 8, 7, 10, 15, 11, 11, 15, 15, 7, 9, 12, 15, - 8, 8, 12, 15, 10, 10, 13, 15, 14, 14, 15, 0, - 11, 13, 15, 15, 11, 13, 15, 15, 14, 15, 15, 0, - 15, 15, 0, 0, 4, 5, 9, 13, 5, 6, 9, 13, - 9, 9, 11, 15, 14, 13, 15, 15, 4, 6, 9, 12, - 5, 6, 9, 13, 9, 8, 11, 15, 13, 12, 15, 15, - 7, 9, 12, 15, 7, 8, 11, 15, 10, 10, 14, 15, - 14, 15, 15, 0, 10, 12, 15, 15, 11, 13, 15, 15, - 15, 15, 15, 0, 15, 15, 0, 0, 6, 9, 13, 14, - 8, 9, 12, 15, 12, 12, 15, 15, 15, 15, 15, 0, - 7, 9, 13, 15, 8, 9, 12, 15, 11, 12, 15, 15, - 15, 15, 15, 0, 9, 11, 15, 15, 9, 11, 15, 15, - 14, 14, 15, 0, 15, 15, 0, 0, 14, 15, 15, 0, - 14, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 0, - 9, 12, 15, 15, 12, 13, 15, 15, 15, 15, 15, 0, - 15, 15, 0, 0, 10, 12, 15, 15, 12, 14, 15, 15, - 15, 15, 15, 0, 15, 15, 0, 0, 14, 15, 15, 0, - 15, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 0, - 15, 15, 0, 0, 15, 15, -}; - - -static const uint16_t cvh_huffcodes4[246] = { - 0x0000,0x0004,0x006c,0x03e6,0x0005,0x0012,0x006d,0x03e7,0x006e,0x00e8,0x03e8,0x3fc4, - 0x07e0,0x07e1,0x7fa4,0x7fa5,0x0006,0x0013,0x01e2,0x0fda,0x0014,0x0015,0x00e9,0x0fdb, - 0x00ea,0x006f,0x03e9,0x7fa6,0x07e2,0x07e3,0x7fa7,0x7fa8,0x0070,0x01e3,0x0fdc,0x7fa9, - 0x00eb,0x00ec,0x0fdd,0x7faa,0x03ea,0x03eb,0x1fd6,0x7fab,0x3fc5,0x3fc6,0x7fac,0x1fd6, - 0x07e4,0x1fd7,0x7fad,0x7fae,0x07e5,0x1fd8,0x7faf,0x7fb0,0x3fc7,0x7fb1,0x7fb2,0x1fd6, - 0x7fb3,0x7fb4,0x1fd6,0x1fd6,0x0007,0x0016,0x01e4,0x1fd9,0x0017,0x0032,0x01e5,0x1fda, - 0x01e6,0x01e7,0x07e6,0x7fb5,0x3fc8,0x1fdb,0x7fb6,0x7fb7,0x0008,0x0033,0x01e8,0x0fde, - 0x0018,0x0034,0x01e9,0x1fdc,0x01ea,0x00ed,0x07e7,0x7fb8,0x1fdd,0x0fdf,0x7fb9,0x7fba, - 0x0071,0x01eb,0x0fe0,0x7fbb,0x0072,0x00ee,0x07e8,0x7fbc,0x03ec,0x03ed,0x3fc9,0x7fbd, - 0x3fca,0x7fbe,0x7fbf,0x3fc9,0x03ee,0x0fe1,0x7fc0,0x7fc1,0x07e9,0x1fde,0x7fc2,0x7fc3, - 0x7fc4,0x7fc5,0x7fc6,0x3fc9,0x7fc7,0x7fc8,0x3fc9,0x3fc9,0x0035,0x01ec,0x1fdf,0x3fcb, - 0x00ef,0x01ed,0x0fe2,0x7fc9,0x0fe3,0x0fe4,0x7fca,0x7fcb,0x7fcc,0x7fcd,0x7fce,0x7fca, - 0x0073,0x01ee,0x1fe0,0x7fcf,0x00f0,0x01ef,0x0fe5,0x7fd0,0x07ea,0x0fe6,0x7fd1,0x7fd2, - 0x7fd3,0x7fd4,0x7fd5,0x7fd1,0x01f0,0x07eb,0x7fd6,0x7fd7,0x01f1,0x07ec,0x7fd8,0x7fd9, - 0x3fcc,0x3fcd,0x7fda,0x7fda,0x7fdb,0x7fdc,0x7fda,0x7fda,0x3fce,0x7fdd,0x7fde,0x7fd6, - 0x3fcf,0x7fdf,0x7fe0,0x7fd8,0x7fe1,0x7fe2,0x7fda,0x7fda,0x3fcc,0x3fcd,0x7fda,0x7fda, - 0x01f2,0x0fe7,0x7fe3,0x7fe4,0x0fe8,0x1fe1,0x7fe5,0x7fe6,0x7fe7,0x7fe8,0x7fe9,0x7fca, - 0x7fea,0x7feb,0x7fca,0x7fca,0x03ef,0x0fe9,0x7fec,0x7fed,0x0fea,0x3fd0,0x7fee,0x7fef, - 0x7ff0,0x7ff1,0x7ff2,0x7fd1,0x7ff3,0x7ff4,0x7fd1,0x7fd1,0x3fd1,0x7ff5,0x7ff6,0x7fd6, - 0x7ff7,0x7ff8,0x7ff9,0x7fd8,0x7ffa,0x7ffb,0x7fda,0x7fda,0x3fcc,0x3fcd,0x7fda,0x7fda, - 0x7ffc,0x7ffd,0x7fd6,0x7fd6,0x7ffe,0x7fff, -}; - - -static const uint8_t cvh_huffbits5[230] = { - 2, 4, 8, 4, 5, 9, 9, 10, 14, 4, 6, 11, - 5, 6, 12, 10, 11, 15, 9, 11, 15, 10, 13, 15, - 14, 15, 0, 4, 6, 12, 6, 7, 12, 12, 12, 15, - 5, 7, 13, 6, 7, 13, 12, 13, 15, 10, 12, 15, - 11, 13, 15, 15, 15, 0, 8, 13, 15, 11, 12, 15, - 15, 15, 0, 10, 13, 15, 12, 15, 15, 15, 15, 0, - 15, 15, 0, 15, 15, 0, 0, 0, 0, 4, 5, 11, - 5, 7, 12, 11, 12, 15, 6, 7, 13, 7, 8, 14, - 12, 14, 15, 11, 13, 15, 12, 13, 15, 15, 15, 0, - 5, 6, 13, 7, 8, 15, 12, 14, 15, 6, 8, 14, - 7, 8, 15, 14, 15, 15, 12, 12, 15, 12, 13, 15, - 15, 15, 0, 9, 13, 15, 12, 13, 15, 15, 15, 0, - 11, 13, 15, 13, 13, 15, 15, 15, 0, 14, 15, 0, - 15, 15, 0, 0, 0, 0, 8, 10, 15, 11, 12, 15, - 15, 15, 0, 10, 12, 15, 12, 13, 15, 15, 15, 0, - 14, 15, 0, 15, 15, 0, 0, 0, 0, 8, 12, 15, - 12, 13, 15, 15, 15, 0, 11, 13, 15, 13, 15, 15, - 15, 15, 0, 15, 15, 0, 15, 15, 0, 0, 0, 0, - 14, 15, 0, 15, 15, 0, 0, 0, 0, 15, 15, 0, - 15, 15, -}; - - - -static const uint16_t cvh_huffcodes5[230] = { - 0x0000,0x0004,0x00f0,0x0005,0x0012,0x01f0,0x01f1,0x03e8,0x3fce,0x0006,0x0030,0x07de, - 0x0013,0x0031,0x0fd2,0x03e9,0x07df,0x7fb0,0x01f2,0x07e0,0x7fb1,0x03ea,0x1fd2,0x7fb2, - 0x3fcf,0x7fb3,0x0031,0x0007,0x0032,0x0fd3,0x0033,0x0070,0x0fd4,0x0fd5,0x0fd6,0x7fb4, - 0x0014,0x0071,0x1fd3,0x0034,0x0072,0x1fd4,0x0fd7,0x1fd5,0x7fb5,0x03eb,0x0fd8,0x7fb6, - 0x07e1,0x1fd6,0x7fb7,0x7fb8,0x7fb9,0x0072,0x00f1,0x1fd7,0x7fba,0x07e2,0x0fd9,0x7fbb, - 0x7fbc,0x7fbd,0x0070,0x03ec,0x1fd8,0x7fbe,0x0fda,0x7fbf,0x7fc0,0x7fc1,0x7fc2,0x0072, - 0x7fc3,0x7fc4,0x0071,0x7fc5,0x7fc6,0x0072,0x0034,0x0072,0x0072,0x0008,0x0015,0x07e3, - 0x0016,0x0073,0x0fdb,0x07e4,0x0fdc,0x7fc7,0x0035,0x0074,0x1fd9,0x0075,0x00f2,0x3fd0, - 0x0fdd,0x3fd1,0x7fc8,0x07e5,0x1fda,0x7fc9,0x0fde,0x1fdb,0x7fca,0x7fcb,0x7fcc,0x00f2, - 0x0017,0x0036,0x1fdc,0x0076,0x00f3,0x7fcd,0x0fdf,0x3fd2,0x7fce,0x0037,0x00f4,0x3fd3, - 0x0077,0x00f5,0x7fcf,0x3fd4,0x7fd0,0x7fd1,0x0fe0,0x0fe1,0x7fd2,0x0fe2,0x1fdd,0x7fd3, - 0x7fd4,0x7fd5,0x00f5,0x01f3,0x1fde,0x7fd6,0x0fe3,0x1fdf,0x7fd7,0x7fd8,0x7fd9,0x00f3, - 0x07e6,0x1fe0,0x7fda,0x1fe1,0x1fe2,0x7fdb,0x7fdc,0x7fdd,0x00f5,0x3fd5,0x7fde,0x00f4, - 0x7fdf,0x7fe0,0x00f5,0x0077,0x00f5,0x00f5,0x00f6,0x03ed,0x7fe1,0x07e7,0x0fe4,0x7fe2, - 0x7fe3,0x7fe4,0x0073,0x03ee,0x0fe5,0x7fe5,0x0fe6,0x1fe3,0x7fe6,0x7fe7,0x7fe8,0x00f2, - 0x3fd6,0x7fe9,0x0074,0x7fea,0x7feb,0x00f2,0x0075,0x00f2,0x00f2,0x00f7,0x0fe7,0x7fec, - 0x0fe8,0x1fe4,0x7fed,0x7fee,0x7fef,0x00f3,0x07e8,0x1fe5,0x7ff0,0x1fe6,0x7ff1,0x7ff2, - 0x7ff3,0x7ff4,0x00f5,0x7ff5,0x7ff6,0x00f4,0x7ff7,0x7ff8,0x00f5,0x0077,0x00f5,0x00f5, - 0x3fd7,0x7ff9,0x0036,0x7ffa,0x7ffb,0x00f3,0x0076,0x00f3,0x00f3,0x7ffc,0x7ffd,0x0000, - 0x7ffe,0x7fff, -}; - - -static const uint8_t cvh_huffbits6[32] = { - 1, 4, 4, 6, 4, 6, 6, 8, 4, 6, 6, 8, - 6, 9, 8, 10, 4, 6, 7, 8, 6, 9, 8, 11, - 6, 9, 8, 10, 8, 10, 9, 11, -}; - -static const uint16_t cvh_huffcodes6[32] = { - 0x0000,0x0008,0x0009,0x0034,0x000a,0x0035,0x0036,0x00f6,0x000b,0x0037,0x0038,0x00f7, - 0x0039,0x01fa,0x00f8,0x03fc,0x000c,0x003a,0x007a,0x00f9,0x003b,0x01fb,0x00fa,0x07fe, - 0x003c,0x01fc,0x00fb,0x03fd,0x00fc,0x03fe,0x01fd,0x07ff, -}; - -static const uint16_t* const cvh_huffcodes[7] = { - cvh_huffcodes0, cvh_huffcodes1, cvh_huffcodes2, cvh_huffcodes3, - cvh_huffcodes4, cvh_huffcodes5, cvh_huffcodes6, -}; - -static const uint8_t* const cvh_huffbits[7] = { - cvh_huffbits0, cvh_huffbits1, cvh_huffbits2, cvh_huffbits3, - cvh_huffbits4, cvh_huffbits5, cvh_huffbits6, -}; - - -static const uint16_t ccpl_huffcodes2[3] = { - 0x02,0x00,0x03, -}; - -static const uint16_t ccpl_huffcodes3[7] = { - 0x3e,0x1e,0x02,0x00,0x06,0x0e,0x3f, -}; - -static const uint16_t ccpl_huffcodes4[15] = { - 0xfc,0xfd,0x7c,0x3c,0x1c,0x0c,0x04,0x00,0x05,0x0d,0x1d,0x3d, - 0x7d,0xfe,0xff, -}; - -static const uint16_t ccpl_huffcodes5[31] = { - 0x03f8,0x03f9,0x03fa,0x03fb,0x01f8,0x01f9,0x00f8,0x00f9,0x0078,0x0079,0x0038,0x0039, - 0x0018,0x0019,0x0004,0x0000,0x0005,0x001a,0x001b,0x003a,0x003b,0x007a,0x007b,0x00fa, - 0x00fb,0x01fa,0x01fb,0x03fc,0x03fd,0x03fe,0x03ff, -}; - -static const uint16_t ccpl_huffcodes6[63] = { - 0xfffe, 0x7ffe, 0x3ffc, 0x1ffc, 0x0ffc, 0x07f6, 0x07f7, 0x07f8, 0x07f9, - 0x03f2, 0x03f3, 0x03f4, 0x03f5, 0x01f0, 0x01f1, 0x01f2, 0x01f3, 0x01f4, - 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x0070, 0x0071, 0x0072, 0x0073, 0x0034, - 0x0035, 0x0016, 0x0017, 0x0004, 0x0000, 0x000a, 0x0018, 0x0019, 0x0036, - 0x0037, 0x0074, 0x0075, 0x0076, 0x0077, 0x00f4, 0x00f5, 0x00f6, 0x00f7, - 0x01f5, 0x01f6, 0x01f7, 0x01f8, 0x03f6, 0x03f7, 0x03f8, 0x03f9, 0x03fa, - 0x07fa, 0x07fb, 0x07fc, 0x07fd, 0x0ffd, 0x1ffd, 0x3ffd, 0x3ffe, 0xffff -}; - -static const uint8_t ccpl_huffbits2[3] = { - 2,1,2, -}; - -static const uint8_t ccpl_huffbits3[7] = { - 6,5,2,1,3,4,6, -}; - -static const uint8_t ccpl_huffbits4[15] = { - 8,8,7,6,5,4,3,1,3,4,5,6,7,8,8, -}; - -static const uint8_t ccpl_huffbits5[31] = { - 10,10,10,10,9,9,8,8,7,7,6,6, - 5,5,3,1,3,5,5,6,6,7,7,8, - 8,9,9,10,10,10,10, -}; - -static const uint8_t ccpl_huffbits6[63] = { - 16,15,14,13,12,11,11,11,11,10,10,10, - 10,9,9,9,9,9,8,8,8,8,7,7, - 7,7,6,6,5,5,3,1,4,5,5,6, - 6,7,7,7,7,8,8,8,8,9,9,9, - 9,10,10,10,10,10,11,11,11,11,12,13, - 14,14,16, -}; - -static const uint16_t* const ccpl_huffcodes[5] = { - ccpl_huffcodes2,ccpl_huffcodes3, - ccpl_huffcodes4,ccpl_huffcodes5,ccpl_huffcodes6 -}; - -static const uint8_t* const ccpl_huffbits[5] = { - ccpl_huffbits2,ccpl_huffbits3, - ccpl_huffbits4,ccpl_huffbits5,ccpl_huffbits6 +static const uint8_t envelope_quant_index_huffcounts[13][16] = { + { 0, 0, 3, 8, 3, 1, 1, 1, 1, 0, 2, 4, 0, 0, 0, 0 }, + { 0, 0, 6, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 2 }, + { 0, 0, 3, 8, 3, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0 }, + { 0, 0, 5, 4, 3, 0, 3, 0, 3, 1, 1, 0, 4, 0, 0, 0 }, + { 0, 0, 5, 3, 4, 3, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0 }, + { 0, 0, 5, 4, 3, 0, 2, 3, 1, 1, 1, 1, 1, 2, 0, 0 }, + { 0, 1, 4, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 4 }, + { 0, 1, 4, 2, 3, 0, 3, 0, 3, 1, 1, 1, 0, 3, 2, 0 }, + { 0, 0, 6, 2, 2, 2, 2, 2, 3, 1, 1, 1, 2, 0, 0, 0 }, + { 0, 0, 6, 2, 2, 3, 0, 3, 1, 1, 1, 1, 0, 4, 0, 0 }, + { 0, 1, 3, 4, 2, 3, 0, 2, 3, 1, 1, 1, 1, 2, 0, 0 }, + { 0, 1, 3, 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 4 }, + { 0, 1, 4, 2, 3, 0, 3, 1, 1, 1, 1, 0, 1, 6, 0, 0 }, +}; + +static const uint8_t envelope_quant_index_huffsyms[13][24] = { + { 10, 11, 12, 0, 4, 5, 6, 7, 8, 9, 13, 2, + 3, 14, 1, 15, 16, 17, 18, 19, 20, 21, 22, 23 }, + { 6, 7, 8, 9, 10, 11, 5, 12, 3, 4, 13, 2, + 14, 1, 15, 0, 16, 17, 18, 19, 20, 21, 22, 23 }, + { 11, 12, 13, 5, 6, 7, 8, 9, 10, 14, 15, 4, + 16, 17, 3, 18, 2, 19, 1, 20, 0, 21, 22, 23 }, + { 9, 10, 11, 12, 13, 8, 14, 15, 16, 6, 7, 17, + 4, 5, 18, 2, 3, 19, 1, 20, 0, 21, 22, 23 }, + { 10, 11, 12, 13, 14, 8, 9, 15, 6, 7, 16, 17, + 4, 5, 18, 19, 3, 20, 2, 21, 0, 1, 22, 23 }, + { 9, 10, 11, 12, 13, 7, 8, 14, 15, 6, 16, 17, + 5, 18, 3, 4, 19, 2, 20, 1, 0, 21, 22, 23 }, + { 12, 9, 10, 11, 13, 8, 14, 7, 15, 16, 6, 17, + 5, 18, 4, 19, 3, 20, 0, 2, 1, 21, 22, 23 }, + { 12, 10, 11, 13, 14, 9, 15, 7, 8, 16, 5, 6, + 17, 4, 18, 19, 3, 2, 20, 0, 1, 21, 22, 23 }, + { 8, 9, 10, 11, 12, 13, 7, 14, 6, 15, 5, 16, + 4, 17, 3, 18, 0, 1, 2, 19, 20, 21, 22, 23 }, + { 8, 9, 10, 11, 12, 13, 7, 14, 6, 15, 4, 5, + 16, 3, 17, 18, 19, 2, 20, 1, 0, 21, 22, 23 }, + { 12, 10, 11, 13, 7, 8, 9, 14, 6, 15, 4, 5, + 16, 3, 17, 2, 18, 19, 1, 20, 21, 0, 22, 23 }, + { 12, 11, 13, 14, 8, 9, 10, 15, 6, 7, 16, 5, + 17, 18, 4, 19, 3, 2, 1, 20, 0, 21, 22, 23 }, + { 12, 10, 11, 13, 14, 9, 15, 8, 16, 17, 6, 7, + 18, 5, 19, 4, 20, 0, 1, 2, 3, 21, 22, 23 }, +}; + + +static const uint8_t cvh_huffcounts[7][16] = { + { 1, 0, 0, 2, 2, 5, 8, 15, 31, 33, 28, 17, 15, 8, 8, 8 }, + { 1, 0, 0, 2, 4, 5, 7, 16, 18, 12, 11, 7, 3, 5, 1, 2 }, + { 1, 0, 1, 2, 4, 2, 5, 8, 7, 8, 2, 3, 1, 1, 1, 2 }, + { 0, 1, 0, 2, 5, 12, 7, 27, 22, 41, 32, 41, 55, 23, 32, 220 }, + { 0, 1, 0, 5, 7, 4, 8, 9, 17, 10, 13, 17, 12, 14, 92, 0 }, + { 0, 1, 0, 5, 6, 8, 8, 8, 4, 7, 11, 23, 21, 10, 80, 0 }, + { 1, 0, 0, 5, 0, 9, 1, 7, 4, 3, 2, 0, 0, 0, 0, 0 }, +}; + +static const uint8_t cvh_huffsyms0[181] = { + 0, 1, 14, 15, 28, 2, 3, 16, 29, 42, 4, 5, 17, 18, 30, + 43, 56, 57, 6, 7, 8, 19, 20, 31, 32, 44, 58, 70, 71, 84, + 85, 98, 99, 9, 10, 21, 22, 23, 24, 33, 34, 35, 36, 45, 46, + 47, 48, 59, 60, 61, 72, 73, 74, 86, 87, 100, 101, 112, 113, 114, + 126, 127, 140, 141, 11, 25, 37, 38, 39, 49, 50, 51, 52, 62, 63, + 64, 65, 75, 76, 77, 78, 88, 89, 102, 103, 115, 116, 117, 128, 129, + 130, 131, 142, 143, 154, 155, 156, 12, 13, 26, 27, 40, 53, 66, 67, + 79, 80, 90, 91, 92, 104, 105, 106, 118, 119, 132, 144, 145, 157, 158, + 168, 169, 170, 182, 183, 41, 54, 68, 81, 93, 94, 107, 108, 120, 122, + 133, 134, 146, 159, 160, 171, 184, 55, 69, 82, 95, 96, 109, 121, 147, + 148, 161, 172, 173, 174, 185, 186, 83, 110, 123, 135, 136, 149, 150, 187, + 97, 111, 124, 151, 162, 163, 175, 188, 125, 137, 138, 164, 176, 177, 189, + 190, +}; + +static const uint8_t cvh_huffsyms1[94] = { + 0, 1, 10, 2, 11, 20, 21, 3, 12, 22, 30, 31, 4, 13, 14, 23, 32, 40, 41, + 5, 6, 15, 16, 24, 25, 33, 34, 42, 43, 50, 51, 52, 60, 61, 62, 7, 17, 18, + 26, 27, 35, 36, 44, 45, 53, 54, 63, 70, 71, 72, 80, 81, 82, 8, 9, 28, 37, + 46, 55, 56, 64, 73, 83, 90, 91, 19, 29, 38, 47, 48, 57, 65, 66, 74, 84, 92, + 39, 58, 67, 75, 76, 85, 93, 49, 68, 94, 59, 77, 78, 86, 95, 69, 87, 96, +}; + +static const uint8_t cvh_huffsyms2[48] = { + 0, 7, 1, 8, 2, 9, 14, 15, 16, 22, 3, 10, 17, 21, 23, 4, 11, 18, 24, + 28, 29, 30, 35, 5, 12, 25, 31, 36, 37, 42, 6, 13, 19, 20, 26, 32, 38, 43, + 39, 44, 27, 33, 45, 46, 34, 40, 41, 47, +}; + +static const uint16_t cvh_huffsyms3[520] = { + 0, 1, 125, 5, 6, 25, 30, 150, 2, 7, 26, 31, 126, 130, 131, + 151, 155, 156, 250, 275, 10, 35, 36, 50, 55, 175, 180, 3, 8, 11, + 12, 27, 32, 37, 56, 127, 132, 136, 152, 157, 160, 161, 176, 181, 251, + 255, 256, 276, 280, 281, 300, 305, 375, 400, 15, 16, 40, 41, 51, 60, + 61, 75, 80, 135, 162, 177, 185, 186, 200, 205, 301, 306, 405, 425, 500, + 525, 4, 9, 13, 17, 20, 28, 33, 38, 42, 52, 57, 81, 85, 128, + 133, 137, 140, 141, 158, 165, 166, 182, 187, 191, 206, 210, 257, 261, 277, + 282, 285, 286, 310, 311, 325, 330, 376, 380, 401, 406, 430, 21, 29, 46, + 62, 65, 66, 76, 86, 100, 105, 142, 153, 163, 190, 201, 211, 225, 230, + 252, 260, 262, 287, 302, 307, 381, 402, 426, 431, 450, 455, 505, 550, 14, + 18, 34, 43, 45, 53, 58, 67, 70, 71, 77, 87, 138, 146, 167, 168, + 171, 178, 183, 192, 207, 216, 235, 258, 265, 283, 291, 312, 315, 316, 326, + 331, 332, 335, 336, 350, 407, 410, 411, 530, 555, 22, 39, 47, 59, 63, + 82, 90, 91, 101, 106, 110, 111, 129, 134, 145, 154, 159, 170, 172, 188, + 195, 196, 202, 212, 215, 226, 231, 236, 253, 263, 266, 267, 278, 288, 290, + 292, 303, 317, 337, 355, 356, 377, 382, 385, 386, 432, 436, 451, 456, 460, + 501, 506, 526, 531, 551, 68, 72, 115, 147, 164, 184, 272, 295, 296, 297, + 309, 333, 340, 360, 387, 416, 427, 435, 437, 480, 510, 532, 556, 19, 44, + 54, 83, 97, 104, 107, 143, 173, 193, 208, 237, 268, 313, 320, 327, 341, + 351, 352, 378, 403, 412, 441, 442, 457, 475, 511, 515, 527, 528, 536, 552, + 23, 24, 48, 49, 64, 69, 73, 78, 79, 84, 88, 89, 92, 93, 94, + 95, 96, 98, 102, 103, 108, 109, 112, 113, 116, 117, 118, 120, 121, 139, + 144, 148, 149, 169, 174, 179, 189, 194, 197, 198, 203, 204, 209, 213, 214, + 217, 218, 219, 220, 221, 222, 223, 227, 228, 229, 232, 233, 234, 238, 240, + 241, 242, 243, 245, 246, 254, 259, 264, 269, 270, 271, 273, 279, 284, 289, + 293, 294, 298, 304, 308, 314, 318, 319, 321, 322, 323, 328, 329, 334, 338, + 339, 342, 343, 345, 346, 347, 353, 357, 358, 361, 362, 363, 365, 366, 367, + 379, 383, 384, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 404, + 408, 409, 413, 414, 415, 417, 418, 419, 420, 421, 422, 423, 428, 429, 433, + 434, 438, 439, 440, 443, 445, 446, 447, 452, 453, 454, 458, 459, 461, 462, + 463, 465, 466, 467, 468, 470, 471, 476, 477, 478, 481, 482, 483, 485, 486, + 487, 490, 491, 502, 503, 504, 507, 508, 509, 512, 513, 516, 517, 518, 520, + 521, 529, 533, 534, 535, 537, 538, 540, 541, 542, 543, 545, 546, 553, 557, + 558, 560, 561, 562, 563, 565, 566, 567, 575, 576, 577, 578, 580, 581, 582, + 583, 585, 586, 587, 590, 591, 600, 601, 605, 606, +}; + +static const uint8_t cvh_huffsyms4[209] = { + 0, 1, 4, 16, 64, 80, 5, 17, 20, 21, 65, 68, 84, 69, 81, + 85, 128, 2, 6, 8, 25, 32, 96, 100, 144, 9, 22, 24, 36, 37, + 89, 101, 132, 148, 18, 33, 66, 70, 72, 73, 82, 86, 88, 97, 129, + 133, 145, 149, 160, 164, 192, 3, 7, 10, 26, 40, 41, 104, 105, 112, + 208, 12, 13, 28, 29, 48, 52, 74, 90, 102, 116, 152, 161, 165, 19, + 23, 34, 38, 83, 93, 98, 113, 134, 136, 137, 150, 153, 193, 196, 209, + 212, 42, 49, 53, 67, 71, 77, 87, 92, 117, 130, 146, 197, 11, 44, + 45, 56, 76, 106, 108, 131, 168, 169, 176, 180, 213, 224, 14, 15, 27, + 30, 31, 35, 39, 43, 46, 50, 51, 54, 55, 57, 58, 60, 61, 75, + 78, 79, 91, 94, 95, 99, 103, 107, 109, 110, 114, 115, 118, 119, 120, + 121, 122, 124, 125, 135, 138, 139, 140, 141, 142, 147, 151, 154, 155, 156, + 157, 158, 162, 163, 166, 167, 170, 172, 173, 177, 178, 181, 182, 184, 185, + 194, 195, 198, 199, 200, 201, 202, 204, 205, 210, 211, 214, 215, 216, 217, + 218, 220, 221, 225, 226, 228, 229, 230, 232, 233, 240, 241, 244, 245, +}; + +static const uint8_t cvh_huffsyms5[192] = { + 0, 1, 3, 9, 27, 81, 4, 12, 36, 82, 84, 108, 10, 13, 28, + 30, 39, 90, 109, 117, 31, 37, 40, 85, 91, 93, 111, 120, 2, 54, + 94, 112, 118, 121, 162, 189, 5, 6, 18, 135, 7, 15, 21, 45, 63, + 163, 171, 11, 16, 19, 48, 57, 83, 87, 99, 144, 165, 198, 14, 29, + 32, 33, 34, 42, 46, 58, 66, 86, 88, 96, 102, 114, 126, 127, 129, + 138, 166, 172, 174, 190, 192, 22, 38, 41, 43, 49, 55, 64, 92, 100, + 103, 110, 130, 136, 139, 145, 147, 148, 175, 193, 199, 201, 8, 24, 95, + 97, 115, 119, 123, 153, 180, 216, 17, 20, 23, 25, 35, 44, 47, 50, + 51, 52, 56, 59, 60, 61, 65, 67, 68, 69, 70, 72, 73, 75, 76, + 89, 98, 101, 104, 105, 106, 113, 116, 122, 124, 125, 128, 131, 132, 133, + 137, 140, 141, 142, 146, 149, 150, 151, 154, 156, 157, 164, 167, 168, 169, + 173, 176, 177, 178, 181, 183, 184, 191, 194, 195, 196, 200, 202, 203, 204, + 205, 207, 208, 210, 211, 217, 219, 220, 225, 226, 228, 229, +}; + +static const uint8_t cvh_huffsyms6[32] = { + 0, 1, 2, 4, 8, 16, 3, 5, 6, 9, 10, 12, 17, 20, 24, 18, 7, 11, 14, + 19, 22, 26, 28, 13, 21, 25, 30, 15, 27, 29, 23, 31, +}; + +static const void* const cvh_huffsyms[7] = { + cvh_huffsyms0, cvh_huffsyms1, cvh_huffsyms2, cvh_huffsyms3, + cvh_huffsyms4, cvh_huffsyms5, cvh_huffsyms6, +}; + +static const uint8_t ccpl_huffsyms2[3] = { + 1, 0, 2, +}; + +static const uint8_t ccpl_huffsyms3[7] = { + 3, 2, 4, 5, 1, 0, 6, +}; + +static const uint8_t ccpl_huffsyms4[15] = { + 7, 6, 8, 5, 9, 4, 10, 3, 11, 2, 12, 0, 1, 13, 14, +}; + +static const uint8_t ccpl_huffsyms5[31] = { + 15, 14, 16, 12, 13, 17, 18, 10, 11, 19, 20, 8, 9, 21, 22, 6, 7, 23, 24, + 4, 5, 25, 26, 0, 1, 2, 3, 27, 28, 29, 30, +}; + +static const uint8_t ccpl_huffsyms6[63] = { + 31, 30, 32, 28, 29, 33, 34, 26, 27, 35, 36, 22, 23, 24, 25, 37, 38, 39, 40, + 18, 19, 20, 21, 41, 42, 43, 44, 13, 14, 15, 16, 17, 45, 46, 47, 48, 9, 10, + 11, 12, 49, 50, 51, 52, 53, 5, 6, 7, 8, 54, 55, 56, 57, 4, 58, 3, 59, + 2, 60, 61, 1, 0, 62, +}; + +static const uint8_t ccpl_huffcounts[5][16] = { + { 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 2, 2, 2, 2, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 2, 0, 4, 4, 4, 4, 4, 8, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 1, 1, 4, 4, 8, 8, 9, 9, 8, 2, 2, 3, 1, 2 }, +}; + +static const uint8_t *const ccpl_huffsyms[5] = { + ccpl_huffsyms2, ccpl_huffsyms3, + ccpl_huffsyms4, ccpl_huffsyms5, ccpl_huffsyms6 }; - //Coupling tables static const int cplband[51] = { diff -Nru ffmpeg-4.2.2/libavcodec/cpia.c ffmpeg-4.4/libavcodec/cpia.c --- ffmpeg-4.2.2/libavcodec/cpia.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cpia.c 2021-04-08 21:28:39.000000000 +0000 @@ -100,7 +100,7 @@ } // Get buffer filled with previous frame - if ((ret = ff_reget_buffer(avctx, frame)) < 0) + if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0) return ret; @@ -230,4 +230,5 @@ .close = cpia_decode_end, .decode = cpia_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/cri.c ffmpeg-4.4/libavcodec/cri.c --- ffmpeg-4.2.2/libavcodec/cri.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cri.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,438 @@ +/* + * CRI image decoder + * + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Cintel RAW image decoder + */ + +#define BITSTREAM_READER_LE + +#include "libavutil/intfloat.h" +#include "libavutil/display.h" +#include "avcodec.h" +#include "bytestream.h" +#include "get_bits.h" +#include "internal.h" +#include "thread.h" + +typedef struct CRIContext { + AVCodecContext *jpeg_avctx; // wrapper context for MJPEG + AVPacket *jpkt; // encoded JPEG tile + AVFrame *jpgframe; // decoded JPEG tile + + GetByteContext gb; + int color_model; + const uint8_t *data; + unsigned data_size; + uint64_t tile_size[4]; +} CRIContext; + +static av_cold int cri_decode_init(AVCodecContext *avctx) +{ + CRIContext *s = avctx->priv_data; + const AVCodec *codec; + int ret; + + s->jpgframe = av_frame_alloc(); + if (!s->jpgframe) + return AVERROR(ENOMEM); + + s->jpkt = av_packet_alloc(); + if (!s->jpkt) + return AVERROR(ENOMEM); + + codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG); + if (!codec) + return AVERROR_BUG; + s->jpeg_avctx = avcodec_alloc_context3(codec); + if (!s->jpeg_avctx) + return AVERROR(ENOMEM); + s->jpeg_avctx->flags = avctx->flags; + s->jpeg_avctx->flags2 = avctx->flags2; + s->jpeg_avctx->dct_algo = avctx->dct_algo; + s->jpeg_avctx->idct_algo = avctx->idct_algo; + ret = avcodec_open2(s->jpeg_avctx, codec, NULL); + if (ret < 0) + return ret; + + return 0; +} + +static void unpack_10bit(GetByteContext *gb, uint16_t *dst, int shift, + int w, int h, ptrdiff_t stride) +{ + int count = w * h; + int pos = 0; + + while (count > 0) { + uint32_t a0, a1, a2, a3; + if (bytestream2_get_bytes_left(gb) < 4) + break; + a0 = bytestream2_get_le32(gb); + a1 = bytestream2_get_le32(gb); + a2 = bytestream2_get_le32(gb); + a3 = bytestream2_get_le32(gb); + dst[pos] = (((a0 >> 1) & 0xE00) | (a0 & 0x1FF)) << shift; + pos++; + if (pos >= w) { + if (count == 1) + break; + dst += stride; + pos = 0; + } + dst[pos] = (((a0 >> 13) & 0x3F) | ((a0 >> 14) & 0xFC0)) << shift; + pos++; + if (pos >= w) { + if (count == 2) + break; + dst += stride; + pos = 0; + } + dst[pos] = (((a0 >> 26) & 7) | ((a1 & 0x1FF) << 3)) << shift; + pos++; + if (pos >= w) { + if (count == 3) + break; + dst += stride; + pos = 0; + } + dst[pos] = (((a1 >> 10) & 0x1FF) | ((a1 >> 11) & 0xE00)) << shift; + pos++; + if (pos >= w) { + if (count == 4) + break; + dst += stride; + pos = 0; + } + dst[pos] = (((a1 >> 23) & 0x3F) | ((a2 & 0x3F) << 6)) << shift; + pos++; + if (pos >= w) { + if (count == 5) + break; + dst += stride; + pos = 0; + } + dst[pos] = (((a2 >> 7) & 0xFF8) | ((a2 >> 6) & 7)) << shift; + pos++; + if (pos >= w) { + if (count == 6) + break; + dst += stride; + pos = 0; + } + dst[pos] = (((a3 & 7) << 9) | ((a2 >> 20) & 0x1FF)) << shift; + pos++; + if (pos >= w) { + if (count == 7) + break; + dst += stride; + pos = 0; + } + dst[pos] = (((a3 >> 4) & 0xFC0) | ((a3 >> 3) & 0x3F)) << shift; + pos++; + if (pos >= w) { + if (count == 8) + break; + dst += stride; + pos = 0; + } + dst[pos] = (((a3 >> 16) & 7) | ((a3 >> 17) & 0xFF8)) << shift; + pos++; + if (pos >= w) { + if (count == 9) + break; + dst += stride; + pos = 0; + } + + count -= 9; + } +} + +static int cri_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + CRIContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + ThreadFrame frame = { .f = data }; + int ret, bps, hflip = 0, vflip = 0; + AVFrameSideData *rotation; + int compressed = 0; + AVFrame *p = data; + + s->data = NULL; + s->data_size = 0; + + bytestream2_init(gb, avpkt->data, avpkt->size); + + while (bytestream2_get_bytes_left(gb) > 8) { + char codec_name[1024]; + uint32_t key, length; + float framerate; + int width, height; + + key = bytestream2_get_le32(gb); + length = bytestream2_get_le32(gb); + + switch (key) { + case 1: + if (length != 4) + return AVERROR_INVALIDDATA; + + if (bytestream2_get_le32(gb) != MKTAG('D', 'V', 'C', 'C')) + return AVERROR_INVALIDDATA; + break; + case 100: + if (length < 16) + return AVERROR_INVALIDDATA; + width = bytestream2_get_le32(gb); + height = bytestream2_get_le32(gb); + s->color_model = bytestream2_get_le32(gb); + if (bytestream2_get_le32(gb) != 1) + return AVERROR_INVALIDDATA; + ret = ff_set_dimensions(avctx, width, height); + if (ret < 0) + return ret; + length -= 16; + goto skip; + case 101: + if (length != 4) + return AVERROR_INVALIDDATA; + + if (bytestream2_get_le32(gb) != 0) + return AVERROR_INVALIDDATA; + break; + case 102: + bytestream2_get_buffer(gb, codec_name, FFMIN(length, sizeof(codec_name) - 1)); + length -= FFMIN(length, sizeof(codec_name) - 1); + if (strncmp(codec_name, "cintel_craw", FFMIN(length, sizeof(codec_name) - 1))) + return AVERROR_INVALIDDATA; + compressed = 1; + goto skip; + case 103: + if (bytestream2_get_bytes_left(gb) < length) + return AVERROR_INVALIDDATA; + s->data = gb->buffer; + s->data_size = length; + goto skip; + case 105: + hflip = bytestream2_get_byte(gb) != 0; + length--; + goto skip; + case 106: + vflip = bytestream2_get_byte(gb) != 0; + length--; + goto skip; + case 107: + if (length != 4) + return AVERROR_INVALIDDATA; + framerate = av_int2float(bytestream2_get_le32(gb)); + avctx->framerate.num = framerate * 1000; + avctx->framerate.den = 1000; + break; + case 119: + if (length != 32) + return AVERROR_INVALIDDATA; + + for (int i = 0; i < 4; i++) + s->tile_size[i] = bytestream2_get_le64(gb); + break; + default: + av_log(avctx, AV_LOG_DEBUG, "skipping unknown key %u of length %u\n", key, length); +skip: + bytestream2_skip(gb, length); + } + } + + switch (s->color_model) { + case 76: + case 88: + avctx->pix_fmt = AV_PIX_FMT_BAYER_BGGR16; + break; + case 77: + case 89: + avctx->pix_fmt = AV_PIX_FMT_BAYER_GBRG16; + break; + case 78: + case 90: + avctx->pix_fmt = AV_PIX_FMT_BAYER_RGGB16; + break; + case 45: + case 79: + case 91: + avctx->pix_fmt = AV_PIX_FMT_BAYER_GRBG16; + break; + } + + switch (s->color_model) { + case 45: + bps = 10; + break; + case 76: + case 77: + case 78: + case 79: + bps = 12; + break; + case 88: + case 89: + case 90: + case 91: + bps = 16; + break; + default: + return AVERROR_INVALIDDATA; + } + + if (compressed) { + for (int i = 0; i < 4; i++) { + if (s->tile_size[i] >= s->data_size) + return AVERROR_INVALIDDATA; + } + + if (s->tile_size[0] + s->tile_size[1] + s->tile_size[2] + s->tile_size[3] != + s->data_size) + return AVERROR_INVALIDDATA; + } + + if (!s->data || !s->data_size) + return AVERROR_INVALIDDATA; + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + avctx->bits_per_raw_sample = bps; + + if (!compressed && s->color_model == 45) { + uint16_t *dst = (uint16_t *)p->data[0]; + GetByteContext gb; + + bytestream2_init(&gb, s->data, s->data_size); + unpack_10bit(&gb, dst, 4, avctx->width, avctx->height, p->linesize[0] / 2); + } else if (!compressed) { + GetBitContext gbit; + const int shift = 16 - bps; + + ret = init_get_bits8(&gbit, s->data, s->data_size); + if (ret < 0) + return ret; + + for (int y = 0; y < avctx->height; y++) { + uint16_t *dst = (uint16_t *)(p->data[0] + y * p->linesize[0]); + + if (get_bits_left(&gbit) < avctx->width * bps) + break; + + for (int x = 0; x < avctx->width; x++) + dst[x] = get_bits(&gbit, bps) << shift; + } + } else { + unsigned offset = 0; + + for (int tile = 0; tile < 4; tile++) { + av_packet_unref(s->jpkt); + s->jpkt->data = (uint8_t *)s->data + offset; + s->jpkt->size = s->tile_size[tile]; + + ret = avcodec_send_packet(s->jpeg_avctx, s->jpkt); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); + return ret; + } + + ret = avcodec_receive_frame(s->jpeg_avctx, s->jpgframe); + if (ret < 0 || s->jpgframe->format != AV_PIX_FMT_GRAY16 || + s->jpeg_avctx->width * 2 != avctx->width || + s->jpeg_avctx->height * 2 != avctx->height) { + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "JPEG decoding error (%d).\n", ret); + } else { + av_log(avctx, AV_LOG_ERROR, + "JPEG invalid format.\n"); + ret = AVERROR_INVALIDDATA; + } + + /* Normally skip, if error explode */ + if (avctx->err_recognition & AV_EF_EXPLODE) + return ret; + else + return 0; + } + + for (int y = 0; y < s->jpeg_avctx->height; y++) { + const int hw = s->jpgframe->width / 2; + uint16_t *dst = (uint16_t *)(p->data[0] + (y * 2) * p->linesize[0] + tile * hw * 2); + const uint16_t *src = (const uint16_t *)(s->jpgframe->data[0] + y * s->jpgframe->linesize[0]); + + memcpy(dst, src, hw * 2); + src += hw; + dst += p->linesize[0] / 2; + memcpy(dst, src, hw * 2); + } + + av_frame_unref(s->jpgframe); + offset += s->tile_size[tile]; + } + } + + if (hflip || vflip) { + rotation = av_frame_new_side_data(p, AV_FRAME_DATA_DISPLAYMATRIX, + sizeof(int32_t) * 9); + if (rotation) { + av_display_rotation_set((int32_t *)rotation->data, 0.f); + av_display_matrix_flip((int32_t *)rotation->data, hflip, vflip); + } + } + + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + *got_frame = 1; + + return 0; +} + +static av_cold int cri_decode_close(AVCodecContext *avctx) +{ + CRIContext *s = avctx->priv_data; + + av_frame_free(&s->jpgframe); + av_packet_free(&s->jpkt); + avcodec_free_context(&s->jpeg_avctx); + + return 0; +} + +AVCodec ff_cri_decoder = { + .name = "cri", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CRI, + .priv_data_size = sizeof(CRIContext), + .init = cri_decode_init, + .decode = cri_decode_frame, + .close = cri_decode_close, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .long_name = NULL_IF_CONFIG_SMALL("Cintel RAW"), +}; diff -Nru ffmpeg-4.2.2/libavcodec/cri_parser.c ffmpeg-4.4/libavcodec/cri_parser.c --- ffmpeg-4.2.2/libavcodec/cri_parser.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cri_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,105 @@ +/* + * CRI parser + * 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 + */ + +/** + * @file + * CRI parser + */ + +#include "libavutil/bswap.h" +#include "libavutil/common.h" + +#include "parser.h" + +typedef struct CRIParser { + ParseContext pc; + int count; + int chunk; + int read_bytes; + int skip_bytes; +} CRIParser; + +#define KEY (((uint64_t)'\1' << 56) | ((uint64_t)'\0' << 48) | \ + ((uint64_t)'\0' << 40) | ((uint64_t)'\0' << 32) | \ + ((uint64_t)'\4' << 24) | ((uint64_t)'\0' << 16) | \ + ((uint64_t)'\0' << 8) | ((uint64_t)'\0' << 0)) + +static int cri_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + CRIParser *bpc = s->priv_data; + uint64_t state = bpc->pc.state64; + int next = END_NOT_FOUND, i = 0; + + s->pict_type = AV_PICTURE_TYPE_I; + s->key_frame = 1; + s->duration = 1; + + *poutbuf_size = 0; + *poutbuf = NULL; + + for (; i < buf_size; i++) { + state = (state << 8) | buf[i]; + bpc->read_bytes++; + + if (bpc->skip_bytes > 0) { + bpc->skip_bytes--; + if (bpc->skip_bytes == 0) + bpc->read_bytes = 0; + } else { + if (state != KEY) + continue; + } + + if (bpc->skip_bytes == 0 && bpc->read_bytes >= 8) { + bpc->skip_bytes = av_bswap32(state & 0xFFFFFFFF); + bpc->chunk = state >> 32; + bpc->read_bytes = 0; + bpc->count++; + } + + if (bpc->chunk == 0x01000000 && bpc->skip_bytes == 4 && + bpc->read_bytes == 0 && bpc->count > 1) { + next = i - 7; + break; + } + } + + bpc->pc.state64 = state; + if (ff_combine_frame(&bpc->pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_cri_parser = { + .codec_ids = { AV_CODEC_ID_CRI }, + .priv_data_size = sizeof(CRIParser), + .parser_parse = cri_parse, + .parser_close = ff_parse_close, +}; diff -Nru ffmpeg-4.2.2/libavcodec/crystalhd.c ffmpeg-4.4/libavcodec/crystalhd.c --- ffmpeg-4.2.2/libavcodec/crystalhd.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/crystalhd.c 2021-04-08 21:28:39.000000000 +0000 @@ -657,7 +657,6 @@ BC_STATUS bc_ret; CHDContext *priv = avctx->priv_data; HANDLE dev = priv->dev; - AVPacket filtered_packet = { 0 }; int ret = 0; av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: decode_packet\n"); @@ -700,7 +699,6 @@ goto exit; } exit: - av_packet_unref(&filtered_packet); return ret; } diff -Nru ffmpeg-4.2.2/libavcodec/cscd.c ffmpeg-4.4/libavcodec/cscd.c --- ffmpeg-4.2.2/libavcodec/cscd.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cscd.c 2021-02-20 20:27:47.000000000 +0000 @@ -77,7 +77,7 @@ return AVERROR_INVALIDDATA; } - if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) + if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) return ret; // decompress data @@ -93,7 +93,7 @@ case 1: { // zlib compression #if CONFIG_ZLIB unsigned long dlen = c->decomp_size; - if (uncompress(c->decomp_buf, &dlen, &buf[2], buf_size - 2) != Z_OK) { + if (uncompress(c->decomp_buf, &dlen, &buf[2], buf_size - 2) != Z_OK || dlen != c->decomp_size) { av_log(avctx, AV_LOG_ERROR, "error during zlib decompression\n"); return AVERROR_INVALIDDATA; } diff -Nru ffmpeg-4.2.2/libavcodec/cuviddec.c ffmpeg-4.4/libavcodec/cuviddec.c --- ffmpeg-4.2.2/libavcodec/cuviddec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/cuviddec.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,7 +33,7 @@ #include "avcodec.h" #include "decode.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "nvdec.h" #include "internal.h" @@ -42,6 +42,10 @@ #define cudaVideoSurfaceFormat_YUV444_16Bit 3 #endif +#if NVDECAPI_CHECK_VERSION(11, 0) +#define CUVID_HAS_AV1_SUPPORT +#endif + typedef struct CuvidContext { AVClass *avclass; @@ -70,8 +74,6 @@ AVBufferRef *hwdevice; AVBufferRef *hwframe; - AVBSFContext *bsf; - AVFifoBuffer *frame_queue; int deint_mode; @@ -90,7 +92,7 @@ CUVIDDECODECAPS caps8, caps10, caps12; CUVIDPARSERPARAMS cuparseinfo; - CUVIDEOFORMATEX cuparse_ext; + CUVIDEOFORMATEX *cuparse_ext; CudaFunctions *cudl; CuvidFunctions *cvdl; @@ -387,8 +389,6 @@ AVCUDADeviceContext *device_hwctx = device_ctx->hwctx; CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx; CUVIDSOURCEDATAPACKET cupkt; - AVPacket filter_packet = { 0 }; - AVPacket filtered_packet = { 0 }; int ret = 0, eret = 0, is_flush = ctx->decoder_flushing; av_log(avctx, AV_LOG_TRACE, "cuvid_decode_packet\n"); @@ -399,29 +399,8 @@ if (cuvid_is_buffer_full(avctx) && avpkt && avpkt->size) return AVERROR(EAGAIN); - if (ctx->bsf && avpkt && avpkt->size) { - if ((ret = av_packet_ref(&filter_packet, avpkt)) < 0) { - av_log(avctx, AV_LOG_ERROR, "av_packet_ref failed\n"); - return ret; - } - - if ((ret = av_bsf_send_packet(ctx->bsf, &filter_packet)) < 0) { - av_log(avctx, AV_LOG_ERROR, "av_bsf_send_packet failed\n"); - av_packet_unref(&filter_packet); - return ret; - } - - if ((ret = av_bsf_receive_packet(ctx->bsf, &filtered_packet)) < 0) { - av_log(avctx, AV_LOG_ERROR, "av_bsf_receive_packet failed\n"); - return ret; - } - - avpkt = &filtered_packet; - } - ret = CHECK_CU(ctx->cudl->cuCtxPushCurrent(cuda_ctx)); if (ret < 0) { - av_packet_unref(&filtered_packet); return ret; } @@ -445,8 +424,6 @@ ret = CHECK_CU(ctx->cvdl->cuvidParseVideoData(ctx->cuparser, &cupkt)); - av_packet_unref(&filtered_packet); - if (ret < 0) goto error; @@ -576,6 +553,12 @@ tmp_frame->format = AV_PIX_FMT_CUDA; tmp_frame->hw_frames_ctx = av_buffer_ref(ctx->hwframe); + if (!tmp_frame->hw_frames_ctx) { + ret = AVERROR(ENOMEM); + av_frame_free(&tmp_frame); + goto error; + } + tmp_frame->width = avctx->width; tmp_frame->height = avctx->height; @@ -651,6 +634,9 @@ } error: + if (ret < 0) + av_frame_unref(frame); + if (mapped_frame) eret = CHECK_CU(ctx->cvdl->cuvidUnmapVideoFrame(ctx->cudecoder, mapped_frame)); @@ -696,11 +682,13 @@ static av_cold int cuvid_decode_end(AVCodecContext *avctx) { CuvidContext *ctx = avctx->priv_data; + AVHWDeviceContext *device_ctx = (AVHWDeviceContext *)ctx->hwdevice->data; + AVCUDADeviceContext *device_hwctx = device_ctx->hwctx; + CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx; av_fifo_freep(&ctx->frame_queue); - if (ctx->bsf) - av_bsf_free(&ctx->bsf); + ctx->cudl->cuCtxPushCurrent(cuda_ctx); if (ctx->cuparser) ctx->cvdl->cuvidDestroyVideoParser(ctx->cuparser); @@ -708,12 +696,15 @@ if (ctx->cudecoder) ctx->cvdl->cuvidDestroyDecoder(ctx->cudecoder); + ctx->cudl->cuCtxPopCurrent(&dummy); + ctx->cudl = NULL; av_buffer_unref(&ctx->hwframe); av_buffer_unref(&ctx->hwdevice); av_freep(&ctx->key_frame); + av_freep(&ctx->cuparse_ext); cuvid_free_functions(&ctx->cvdl); @@ -823,7 +814,8 @@ CUVIDSOURCEDATAPACKET seq_pkt; CUcontext cuda_ctx = NULL; CUcontext dummy; - const AVBitStreamFilter *bsf; + uint8_t *extradata; + int extradata_size; int ret = 0; enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_CUDA, @@ -920,11 +912,8 @@ ctx->cudl = device_hwctx->internal->cuda_dl; memset(&ctx->cuparseinfo, 0, sizeof(ctx->cuparseinfo)); - memset(&ctx->cuparse_ext, 0, sizeof(ctx->cuparse_ext)); memset(&seq_pkt, 0, sizeof(seq_pkt)); - ctx->cuparseinfo.pExtVideoInfo = &ctx->cuparse_ext; - switch (avctx->codec->id) { #if CONFIG_H264_CUVID_DECODER case AV_CODEC_ID_H264: @@ -971,40 +960,38 @@ ctx->cuparseinfo.CodecType = cudaVideoCodec_VC1; break; #endif +#if CONFIG_AV1_CUVID_DECODER && defined(CUVID_HAS_AV1_SUPPORT) + case AV_CODEC_ID_AV1: + ctx->cuparseinfo.CodecType = cudaVideoCodec_AV1; + break; +#endif default: av_log(avctx, AV_LOG_ERROR, "Invalid CUVID codec!\n"); return AVERROR_BUG; } - if (avctx->codec->id == AV_CODEC_ID_H264 || avctx->codec->id == AV_CODEC_ID_HEVC) { - if (avctx->codec->id == AV_CODEC_ID_H264) - bsf = av_bsf_get_by_name("h264_mp4toannexb"); - else - bsf = av_bsf_get_by_name("hevc_mp4toannexb"); - - if (!bsf) { - ret = AVERROR_BSF_NOT_FOUND; - goto error; - } - if (ret = av_bsf_alloc(bsf, &ctx->bsf)) { - goto error; - } - if (((ret = avcodec_parameters_from_context(ctx->bsf->par_in, avctx)) < 0) || ((ret = av_bsf_init(ctx->bsf)) < 0)) { - av_bsf_free(&ctx->bsf); - goto error; - } + if (avctx->codec->bsfs) { + const AVCodecParameters *par = avctx->internal->bsf->par_out; + extradata = par->extradata; + extradata_size = par->extradata_size; + } else { + extradata = avctx->extradata; + extradata_size = avctx->extradata_size; + } - ctx->cuparse_ext.format.seqhdr_data_length = ctx->bsf->par_out->extradata_size; - memcpy(ctx->cuparse_ext.raw_seqhdr_data, - ctx->bsf->par_out->extradata, - FFMIN(sizeof(ctx->cuparse_ext.raw_seqhdr_data), ctx->bsf->par_out->extradata_size)); - } else if (avctx->extradata_size > 0) { - ctx->cuparse_ext.format.seqhdr_data_length = avctx->extradata_size; - memcpy(ctx->cuparse_ext.raw_seqhdr_data, - avctx->extradata, - FFMIN(sizeof(ctx->cuparse_ext.raw_seqhdr_data), avctx->extradata_size)); + ctx->cuparse_ext = av_mallocz(sizeof(*ctx->cuparse_ext) + + FFMAX(extradata_size - (int)sizeof(ctx->cuparse_ext->raw_seqhdr_data), 0)); + if (!ctx->cuparse_ext) { + ret = AVERROR(ENOMEM); + goto error; } + if (extradata_size > 0) + memcpy(ctx->cuparse_ext->raw_seqhdr_data, extradata, extradata_size); + ctx->cuparse_ext->format.seqhdr_data_length = extradata_size; + + ctx->cuparseinfo.pExtVideoInfo = ctx->cuparse_ext; + ctx->key_frame = av_mallocz(ctx->nb_surfaces * sizeof(int)); if (!ctx->key_frame) { ret = AVERROR(ENOMEM); @@ -1012,7 +999,7 @@ } ctx->cuparseinfo.ulMaxNumDecodeSurfaces = ctx->nb_surfaces; - ctx->cuparseinfo.ulMaxDisplayDelay = 4; + ctx->cuparseinfo.ulMaxDisplayDelay = (avctx->flags & AV_CODEC_FLAG_LOW_DELAY) ? 0 : 4; ctx->cuparseinfo.pUserData = avctx; ctx->cuparseinfo.pfnSequenceCallback = cuvid_handle_video_sequence; ctx->cuparseinfo.pfnDecodePicture = cuvid_handle_picture_decode; @@ -1033,8 +1020,8 @@ if (ret < 0) goto error; - seq_pkt.payload = ctx->cuparse_ext.raw_seqhdr_data; - seq_pkt.payload_size = ctx->cuparse_ext.format.seqhdr_data_length; + seq_pkt.payload = ctx->cuparse_ext->raw_seqhdr_data; + seq_pkt.payload_size = ctx->cuparse_ext->format.seqhdr_data_length; if (seq_pkt.payload && seq_pkt.payload_size) { ret = CHECK_CU(ctx->cvdl->cuvidParseVideoData(ctx->cuparser, &seq_pkt)); @@ -1093,8 +1080,8 @@ if (ret < 0) goto error; - seq_pkt.payload = ctx->cuparse_ext.raw_seqhdr_data; - seq_pkt.payload_size = ctx->cuparse_ext.format.seqhdr_data_length; + seq_pkt.payload = ctx->cuparse_ext->raw_seqhdr_data; + seq_pkt.payload_size = ctx->cuparse_ext->format.seqhdr_data_length; if (seq_pkt.payload && seq_pkt.payload_size) { ret = CHECK_CU(ctx->cvdl->cuvidParseVideoData(ctx->cuparser, &seq_pkt)); @@ -1129,7 +1116,7 @@ { NULL } }; -static const AVCodecHWConfigInternal *cuvid_hw_configs[] = { +static const AVCodecHWConfigInternal *const cuvid_hw_configs[] = { &(const AVCodecHWConfigInternal) { .public = { .pix_fmt = AV_PIX_FMT_CUDA, @@ -1142,7 +1129,7 @@ NULL }; -#define DEFINE_CUVID_CODEC(x, X) \ +#define DEFINE_CUVID_CODEC(x, X, bsf_name) \ static const AVClass x##_cuvid_class = { \ .class_name = #x "_cuvid", \ .item_name = av_default_item_name, \ @@ -1161,6 +1148,7 @@ .decode = cuvid_decode_frame, \ .receive_frame = cuvid_output_frame, \ .flush = cuvid_flush, \ + .bsfs = bsf_name, \ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, \ AV_PIX_FMT_NV12, \ @@ -1171,38 +1159,42 @@ .wrapper_name = "cuvid", \ }; +#if CONFIG_AV1_CUVID_DECODER && defined(CUVID_HAS_AV1_SUPPORT) +DEFINE_CUVID_CODEC(av1, AV1, NULL) +#endif + #if CONFIG_HEVC_CUVID_DECODER -DEFINE_CUVID_CODEC(hevc, HEVC) +DEFINE_CUVID_CODEC(hevc, HEVC, "hevc_mp4toannexb") #endif #if CONFIG_H264_CUVID_DECODER -DEFINE_CUVID_CODEC(h264, H264) +DEFINE_CUVID_CODEC(h264, H264, "h264_mp4toannexb") #endif #if CONFIG_MJPEG_CUVID_DECODER -DEFINE_CUVID_CODEC(mjpeg, MJPEG) +DEFINE_CUVID_CODEC(mjpeg, MJPEG, NULL) #endif #if CONFIG_MPEG1_CUVID_DECODER -DEFINE_CUVID_CODEC(mpeg1, MPEG1VIDEO) +DEFINE_CUVID_CODEC(mpeg1, MPEG1VIDEO, NULL) #endif #if CONFIG_MPEG2_CUVID_DECODER -DEFINE_CUVID_CODEC(mpeg2, MPEG2VIDEO) +DEFINE_CUVID_CODEC(mpeg2, MPEG2VIDEO, NULL) #endif #if CONFIG_MPEG4_CUVID_DECODER -DEFINE_CUVID_CODEC(mpeg4, MPEG4) +DEFINE_CUVID_CODEC(mpeg4, MPEG4, NULL) #endif #if CONFIG_VP8_CUVID_DECODER -DEFINE_CUVID_CODEC(vp8, VP8) +DEFINE_CUVID_CODEC(vp8, VP8, NULL) #endif #if CONFIG_VP9_CUVID_DECODER -DEFINE_CUVID_CODEC(vp9, VP9) +DEFINE_CUVID_CODEC(vp9, VP9, NULL) #endif #if CONFIG_VC1_CUVID_DECODER -DEFINE_CUVID_CODEC(vc1, VC1) +DEFINE_CUVID_CODEC(vc1, VC1, NULL) #endif diff -Nru ffmpeg-4.2.2/libavcodec/dca_core_bsf.c ffmpeg-4.4/libavcodec/dca_core_bsf.c --- ffmpeg-4.2.2/libavcodec/dca_core_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dca_core_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -18,11 +18,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "bytestream.h" #include "dca_syncwords.h" -#include "libavutil/mem.h" static int dca_core_filter(AVBSFContext *ctx, AVPacket *pkt) { diff -Nru ffmpeg-4.2.2/libavcodec/dca_core.h ffmpeg-4.4/libavcodec/dca_core.h --- ffmpeg-4.2.2/libavcodec/dca_core.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dca_core.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,7 +24,7 @@ #include "libavutil/common.h" #include "libavutil/float_dsp.h" #include "libavutil/fixed_dsp.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "internal.h" diff -Nru ffmpeg-4.2.2/libavcodec/dcadata.c ffmpeg-4.4/libavcodec/dcadata.c --- ffmpeg-4.2.2/libavcodec/dcadata.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dcadata.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,7 +22,7 @@ #include -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "dca.h" #include "dcadata.h" diff -Nru ffmpeg-4.2.2/libavcodec/dcadsp.c ffmpeg-4.4/libavcodec/dcadsp.c --- ffmpeg-4.2.2/libavcodec/dcadsp.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dcadsp.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,6 +19,7 @@ */ #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "dcadsp.h" #include "dcamath.h" @@ -328,7 +329,7 @@ int i; for (i = 0; i < len; i++) - dst[i] += mul15(src[i], coeff); + dst[i] += (unsigned)mul15(src[i], coeff); } static void dmix_scale_c(int32_t *dst, int scale, ptrdiff_t len) diff -Nru ffmpeg-4.2.2/libavcodec/dcaenc.c ffmpeg-4.4/libavcodec/dcaenc.c --- ffmpeg-4.2.2/libavcodec/dcaenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dcaenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,6 +28,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "libavutil/ffmath.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "avcodec.h" #include "dca.h" @@ -924,10 +925,10 @@ * But there are no proper value in decoder history, so likely result will be no good. * Bitstream has "Predictor history flag switch", but this flag disables history for all subbands */ - samples[0] = c->adpcm_history[ch][band][0] << 7; - samples[1] = c->adpcm_history[ch][band][1] << 7; - samples[2] = c->adpcm_history[ch][band][2] << 7; - samples[3] = c->adpcm_history[ch][band][3] << 7; + samples[0] = c->adpcm_history[ch][band][0] * (1 << 7); + samples[1] = c->adpcm_history[ch][band][1] * (1 << 7); + samples[2] = c->adpcm_history[ch][band][2] * (1 << 7); + samples[3] = c->adpcm_history[ch][band][3] * (1 << 7); } } } diff -Nru ffmpeg-4.2.2/libavcodec/dca_lbr.c ffmpeg-4.4/libavcodec/dca_lbr.c --- ffmpeg-4.2.2/libavcodec/dca_lbr.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dca_lbr.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,7 @@ #define BITSTREAM_READER_LE #include "libavutil/channel_layout.h" +#include "libavutil/mem_internal.h" #include "dcadec.h" #include "dcadata.h" @@ -154,7 +155,7 @@ step_i = get_bits(&s->gb, 8); if (step_i > step_max) { av_log(s->avctx, AV_LOG_ERROR, "Invalid LFE step size index\n"); - return -1; + return AVERROR_INVALIDDATA; } step = ff_dca_lfe_step_size_24[step_i]; @@ -208,7 +209,7 @@ step_i = get_bits(&s->gb, 8); if (step_i > step_max) { av_log(s->avctx, AV_LOG_ERROR, "Invalid LFE step size index\n"); - return -1; + return AVERROR_INVALIDDATA; } step = ff_dca_lfe_step_size_16[step_i]; @@ -246,14 +247,17 @@ static int parse_lfe_chunk(DCALbrDecoder *s, LBRChunk *chunk) { + int ret; + if (!(s->flags & LBR_FLAG_LFE_PRESENT)) return 0; if (!chunk->len) return 0; - if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0) - return -1; + ret = init_get_bits8(&s->gb, chunk->data, chunk->len); + if (ret < 0) + return ret; // Determine bit depth from chunk size if (chunk->len >= 52) @@ -262,7 +266,7 @@ return parse_lfe_16(s); av_log(s->avctx, AV_LOG_ERROR, "LFE chunk too short\n"); - return -1; + return AVERROR_INVALIDDATA; } static inline int parse_vlc(GetBitContext *s, VLC *vlc, int max_depth) @@ -291,13 +295,13 @@ for (freq = 1;; freq++) { if (get_bits_left(&s->gb) < 1) { av_log(s->avctx, AV_LOG_ERROR, "Tonal group chunk too short\n"); - return -1; + return AVERROR_INVALIDDATA; } diff = parse_vlc(&s->gb, &ff_dca_vlc_tnl_grp[group], 2); if (diff >= FF_ARRAY_ELEMS(ff_dca_fst_amp)) { av_log(s->avctx, AV_LOG_ERROR, "Invalid tonal frequency diff\n"); - return -1; + return AVERROR_INVALIDDATA; } diff = get_bitsz(&s->gb, diff >> 2) + ff_dca_fst_amp[diff]; @@ -307,7 +311,7 @@ freq += diff - 2; if (freq >> (5 - group) > s->nsubbands * 4 - 6) { av_log(s->avctx, AV_LOG_ERROR, "Invalid spectral line offset\n"); - return -1; + return AVERROR_INVALIDDATA; } // Main channel @@ -358,19 +362,21 @@ static int parse_tonal_chunk(DCALbrDecoder *s, LBRChunk *chunk) { - int sb, group; + int sb, group, ret; if (!chunk->len) return 0; - if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0) - return -1; + ret = init_get_bits8(&s->gb, chunk->data, chunk->len); + + if (ret < 0) + return ret; // Scale factors if (chunk->id == LBR_CHUNK_SCF || chunk->id == LBR_CHUNK_TONAL_SCF) { if (get_bits_left(&s->gb) < 36) { av_log(s->avctx, AV_LOG_ERROR, "Tonal scale factor chunk too short\n"); - return -1; + return AVERROR_INVALIDDATA; } for (sb = 0; sb < 6; sb++) s->tonal_scf[sb] = get_bits(&s->gb, 6); @@ -378,20 +384,25 @@ // Tonal groups if (chunk->id == LBR_CHUNK_TONAL || chunk->id == LBR_CHUNK_TONAL_SCF) - for (group = 0; group < 5; group++) - if (parse_tonal(s, group) < 0) - return -1; + for (group = 0; group < 5; group++) { + ret = parse_tonal(s, group); + if (ret < 0) + return ret; + } return 0; } static int parse_tonal_group(DCALbrDecoder *s, LBRChunk *chunk) { + int ret; + if (!chunk->len) return 0; - if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0) - return -1; + ret = init_get_bits8(&s->gb, chunk->data, chunk->len); + if (ret < 0) + return ret; return parse_tonal(s, chunk->id); } @@ -404,7 +415,7 @@ { int left = get_bits_left(s); if (left < 0) - return -1; + return AVERROR_INVALIDDATA; if (left < n) { skip_bits_long(s, left); return 1; @@ -433,7 +444,7 @@ dist = parse_vlc(&s->gb, &ff_dca_vlc_rsd_apprx, 1) + 1; if (dist > 7 - sf) { av_log(s->avctx, AV_LOG_ERROR, "Invalid scale factor distance\n"); - return -1; + return AVERROR_INVALIDDATA; } if (ensure_bits(&s->gb, 20)) @@ -498,22 +509,26 @@ static int parse_grid_1_chunk(DCALbrDecoder *s, LBRChunk *chunk, int ch1, int ch2) { - int ch, sb, sf, nsubbands; + int ch, sb, sf, nsubbands, ret; if (!chunk->len) return 0; - if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0) - return -1; + ret = init_get_bits8(&s->gb, chunk->data, chunk->len); + if (ret < 0) + return ret; // Scale factors nsubbands = ff_dca_scf_to_grid_1[s->nsubbands - 1] + 1; for (sb = 2; sb < nsubbands; sb++) { - if (parse_scale_factors(s, s->grid_1_scf[ch1][sb]) < 0) - return -1; - if (ch1 != ch2 && ff_dca_grid_1_to_scf[sb] < s->min_mono_subband - && parse_scale_factors(s, s->grid_1_scf[ch2][sb]) < 0) - return -1; + ret = parse_scale_factors(s, s->grid_1_scf[ch1][sb]); + if (ret < 0) + return ret; + if (ch1 != ch2 && ff_dca_grid_1_to_scf[sb] < s->min_mono_subband) { + ret = parse_scale_factors(s, s->grid_1_scf[ch2][sb]); + if (ret < 0) + return ret; + } } if (get_bits_left(&s->gb) < 1) @@ -532,7 +547,7 @@ if (get_bits_left(&s->gb) < 0) { av_log(s->avctx, AV_LOG_ERROR, "First grid chunk too short\n"); - return -1; + return AVERROR_INVALIDDATA; } // Stereo image for partial mono mode @@ -562,14 +577,16 @@ static int parse_grid_1_sec_ch(DCALbrDecoder *s, int ch2) { - int sb, nsubbands; + int sb, nsubbands, ret; // Scale factors nsubbands = ff_dca_scf_to_grid_1[s->nsubbands - 1] + 1; for (sb = 2; sb < nsubbands; sb++) { - if (ff_dca_grid_1_to_scf[sb] >= s->min_mono_subband - && parse_scale_factors(s, s->grid_1_scf[ch2][sb]) < 0) - return -1; + if (ff_dca_grid_1_to_scf[sb] >= s->min_mono_subband) { + ret = parse_scale_factors(s, s->grid_1_scf[ch2][sb]); + if (ret < 0) + return ret; + } } // Average values for third grid @@ -709,7 +726,7 @@ s->sb_indices[sb] = sb_reorder; } if (sb_reorder >= s->nsubbands) - return -1; + return AVERROR_INVALIDDATA; // Third grid scale factors if (sb == 12) { @@ -731,7 +748,7 @@ quant_level = s->quant_levels[ch1 / 2][sb]; if (!quant_level) - return -1; + return AVERROR_INVALIDDATA; // Time samples for one or both channels if (sb < s->max_mono_subband && sb_reorder >= s->min_mono_subband) { @@ -792,13 +809,14 @@ static int parse_high_res_grid(DCALbrDecoder *s, LBRChunk *chunk, int ch1, int ch2) { int quant_levels[DCA_LBR_SUBBANDS]; - int sb, ch, ol, st, max_sb, profile; + int sb, ch, ol, st, max_sb, profile, ret; if (!chunk->len) return 0; - if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0) - return -1; + ret = init_get_bits8(&s->gb, chunk->data, chunk->len); + if (ret < 0) + return ret; // Quantizer profile profile = get_bits(&s->gb, 8); @@ -832,18 +850,20 @@ s->quant_levels[ch1 / 2][sb] = quant_levels[sb]; // LPC for the first two subbands - if (parse_lpc(s, ch1, ch2, 0, 2) < 0) - return -1; + ret = parse_lpc(s, ch1, ch2, 0, 2); + if (ret < 0) + return ret; // Time-samples for the first two subbands of main channel - if (parse_ts(s, ch1, ch2, 0, 2, 0) < 0) - return -1; + ret = parse_ts(s, ch1, ch2, 0, 2, 0); + if (ret < 0) + return ret; // First two bands of the first grid for (sb = 0; sb < 2; sb++) for (ch = ch1; ch <= ch2; ch++) - if (parse_scale_factors(s, s->grid_1_scf[ch][sb]) < 0) - return -1; + if ((ret = parse_scale_factors(s, s->grid_1_scf[ch][sb])) < 0) + return ret; return 0; } @@ -892,39 +912,42 @@ static int parse_ts1_chunk(DCALbrDecoder *s, LBRChunk *chunk, int ch1, int ch2) { + int ret; if (!chunk->len) return 0; - if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0) - return -1; - if (parse_lpc(s, ch1, ch2, 2, 3) < 0) - return -1; - if (parse_ts(s, ch1, ch2, 2, 4, 0) < 0) - return -1; - if (parse_grid_2(s, ch1, ch2, 0, 1, 0) < 0) - return -1; - if (parse_ts(s, ch1, ch2, 4, 6, 0) < 0) - return -1; + if ((ret = init_get_bits8(&s->gb, chunk->data, chunk->len)) < 0) + return ret; + if ((ret = parse_lpc(s, ch1, ch2, 2, 3)) < 0) + return ret; + if ((ret = parse_ts(s, ch1, ch2, 2, 4, 0)) < 0) + return ret; + if ((ret = parse_grid_2(s, ch1, ch2, 0, 1, 0)) < 0) + return ret; + if ((ret = parse_ts(s, ch1, ch2, 4, 6, 0)) < 0) + return ret; return 0; } static int parse_ts2_chunk(DCALbrDecoder *s, LBRChunk *chunk, int ch1, int ch2) { + int ret; + if (!chunk->len) return 0; - if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0) - return -1; - if (parse_grid_2(s, ch1, ch2, 1, 3, 0) < 0) - return -1; - if (parse_ts(s, ch1, ch2, 6, s->max_mono_subband, 0) < 0) - return -1; + if ((ret = init_get_bits8(&s->gb, chunk->data, chunk->len)) < 0) + return ret; + if ((ret = parse_grid_2(s, ch1, ch2, 1, 3, 0)) < 0) + return ret; + if ((ret = parse_ts(s, ch1, ch2, 6, s->max_mono_subband, 0)) < 0) + return ret; if (ch1 != ch2) { - if (parse_grid_1_sec_ch(s, ch2) < 0) - return -1; - if (parse_grid_2(s, ch1, ch2, 0, 3, 1) < 0) - return -1; + if ((ret = parse_grid_1_sec_ch(s, ch2)) < 0) + return ret; + if ((ret = parse_grid_2(s, ch1, ch2, 0, 3, 1)) < 0) + return ret; } - if (parse_ts(s, ch1, ch2, s->min_mono_subband, s->nsubbands, 1) < 0) - return -1; + if ((ret = parse_ts(s, ch1, ch2, s->min_mono_subband, s->nsubbands, 1)) < 0) + return ret; return 0; } @@ -932,11 +955,13 @@ { double scale = (-1.0 / (1 << 17)) * sqrt(1 << (2 - s->limited_range)); int i, br_per_ch = s->bit_rate_scaled / s->nchannels_total; + int ret; ff_mdct_end(&s->imdct); - if (ff_mdct_init(&s->imdct, s->freq_range + 6, 1, scale) < 0) - return -1; + ret = ff_mdct_init(&s->imdct, s->freq_range + 6, 1, scale); + if (ret < 0) + return ret; for (i = 0; i < 32 << s->freq_range; i++) s->window[i] = ff_dca_long_window[i << (2 - s->freq_range)]; @@ -975,7 +1000,7 @@ // Reallocate time sample buffer av_fast_mallocz(&s->ts_buffer, &s->ts_size, nsamples * sizeof(float)); if (!s->ts_buffer) - return -1; + return AVERROR(ENOMEM); ptr = s->ts_buffer + DCA_LBR_TIME_HISTORY; for (ch = 0; ch < s->nchannels; ch++) { @@ -1796,7 +1821,7 @@ init_tables(); if (!(s->fdsp = avpriv_float_dsp_alloc(0))) - return -1; + return AVERROR(ENOMEM); s->lbr_rand = 1; return 0; diff -Nru ffmpeg-4.2.2/libavcodec/dca_lbr.h ffmpeg-4.4/libavcodec/dca_lbr.h --- ffmpeg-4.2.2/libavcodec/dca_lbr.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dca_lbr.h 2021-04-08 21:28:39.000000000 +0000 @@ -23,7 +23,7 @@ #include "libavutil/common.h" #include "libavutil/float_dsp.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "internal.h" diff -Nru ffmpeg-4.2.2/libavcodec/dca_xll.h ffmpeg-4.4/libavcodec/dca_xll.h --- ffmpeg-4.2.2/libavcodec/dca_xll.h 2018-07-17 09:27:39.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dca_xll.h 2021-04-08 21:28:39.000000000 +0000 @@ -22,7 +22,7 @@ #define AVCODEC_DCA_XLL_H #include "libavutil/common.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "internal.h" diff -Nru ffmpeg-4.2.2/libavcodec/decode.c ffmpeg-4.4/libavcodec/decode.c --- ffmpeg-4.2.2/libavcodec/decode.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/decode.c 2021-04-08 21:28:39.000000000 +0000 @@ -41,13 +41,33 @@ #include "avcodec.h" #include "bytestream.h" #include "decode.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "internal.h" #include "thread.h" +typedef struct FramePool { + /** + * Pools for each data plane. For audio all the planes have the same size, + * so only pools[0] is used. + */ + AVBufferPool *pools[4]; + + /* + * Pool parameters + */ + int format; + int width, height; + int stride_align[AV_NUM_DATA_POINTERS]; + int linesize[4]; + int planes; + int channels; + int samples; +} FramePool; + static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt) { - int size = 0, ret; + int ret; + buffer_size_t size; const uint8_t *data; uint32_t flags; int64_t val; @@ -123,209 +143,82 @@ return 0; } -static int extract_packet_props(AVCodecInternal *avci, const AVPacket *pkt) +#define IS_EMPTY(pkt) (!(pkt)->data) + +static int copy_packet_props(AVPacket *dst, const AVPacket *src) { - int ret = 0; + int ret = av_packet_copy_props(dst, src); + if (ret < 0) + return ret; - av_packet_unref(avci->last_pkt_props); - if (pkt) { - ret = av_packet_copy_props(avci->last_pkt_props, pkt); - if (!ret) - avci->last_pkt_props->size = pkt->size; // HACK: Needed for ff_decode_frame_props(). - } - return ret; + dst->size = src->size; // HACK: Needed for ff_decode_frame_props(). + dst->data = (void*)1; // HACK: Needed for IS_EMPTY(). + + return 0; } -static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame) +static int extract_packet_props(AVCodecInternal *avci, const AVPacket *pkt) { - int ret; + AVPacket tmp = { 0 }; + int ret = 0; - /* move the original frame to our backup */ - av_frame_unref(avci->to_free); - av_frame_move_ref(avci->to_free, frame); + if (IS_EMPTY(avci->last_pkt_props)) { + if (av_fifo_size(avci->pkt_props) >= sizeof(*pkt)) { + av_fifo_generic_read(avci->pkt_props, avci->last_pkt_props, + sizeof(*avci->last_pkt_props), NULL); + } else + return copy_packet_props(avci->last_pkt_props, pkt); + } - /* now copy everything except the AVBufferRefs back - * note that we make a COPY of the side data, so calling av_frame_free() on - * the caller's frame will work properly */ - ret = av_frame_copy_props(frame, avci->to_free); + if (av_fifo_space(avci->pkt_props) < sizeof(*pkt)) { + ret = av_fifo_grow(avci->pkt_props, sizeof(*pkt)); + if (ret < 0) + return ret; + } + + ret = copy_packet_props(&tmp, pkt); if (ret < 0) return ret; - memcpy(frame->data, avci->to_free->data, sizeof(frame->data)); - memcpy(frame->linesize, avci->to_free->linesize, sizeof(frame->linesize)); - if (avci->to_free->extended_data != avci->to_free->data) { - int planes = avci->to_free->channels; - int size = planes * sizeof(*frame->extended_data); - - if (!size) { - av_frame_unref(frame); - return AVERROR_BUG; - } - - frame->extended_data = av_malloc(size); - if (!frame->extended_data) { - av_frame_unref(frame); - return AVERROR(ENOMEM); - } - memcpy(frame->extended_data, avci->to_free->extended_data, - size); - } else - frame->extended_data = frame->data; - - frame->format = avci->to_free->format; - frame->width = avci->to_free->width; - frame->height = avci->to_free->height; - frame->channel_layout = avci->to_free->channel_layout; - frame->nb_samples = avci->to_free->nb_samples; - frame->channels = avci->to_free->channels; + av_fifo_generic_write(avci->pkt_props, &tmp, sizeof(tmp), NULL); return 0; } -int ff_decode_bsfs_init(AVCodecContext *avctx) +static int decode_bsfs_init(AVCodecContext *avctx) { AVCodecInternal *avci = avctx->internal; - DecodeFilterContext *s = &avci->filter; - const char *bsfs_str; int ret; - if (s->nb_bsfs) + if (avci->bsf) return 0; - bsfs_str = avctx->codec->bsfs ? avctx->codec->bsfs : "null"; - while (bsfs_str && *bsfs_str) { - AVBSFContext **tmp; - const AVBitStreamFilter *filter; - char *bsf, *bsf_options_str, *bsf_name; - - bsf = av_get_token(&bsfs_str, ","); - if (!bsf) { - ret = AVERROR(ENOMEM); - goto fail; - } - bsf_name = av_strtok(bsf, "=", &bsf_options_str); - if (!bsf_name) { - av_freep(&bsf); - ret = AVERROR(ENOMEM); - goto fail; - } - - filter = av_bsf_get_by_name(bsf_name); - if (!filter) { - av_log(avctx, AV_LOG_ERROR, "A non-existing bitstream filter %s " - "requested by a decoder. This is a bug, please report it.\n", - bsf_name); - av_freep(&bsf); + ret = av_bsf_list_parse_str(avctx->codec->bsfs, &avci->bsf); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error parsing decoder bitstream filters '%s': %s\n", avctx->codec->bsfs, av_err2str(ret)); + if (ret != AVERROR(ENOMEM)) ret = AVERROR_BUG; - goto fail; - } - - tmp = av_realloc_array(s->bsfs, s->nb_bsfs + 1, sizeof(*s->bsfs)); - if (!tmp) { - av_freep(&bsf); - ret = AVERROR(ENOMEM); - goto fail; - } - s->bsfs = tmp; - s->nb_bsfs++; - - ret = av_bsf_alloc(filter, &s->bsfs[s->nb_bsfs - 1]); - if (ret < 0) { - av_freep(&bsf); - goto fail; - } - - if (s->nb_bsfs == 1) { - /* We do not currently have an API for passing the input timebase into decoders, - * but no filters used here should actually need it. - * So we make up some plausible-looking number (the MPEG 90kHz timebase) */ - s->bsfs[s->nb_bsfs - 1]->time_base_in = (AVRational){ 1, 90000 }; - ret = avcodec_parameters_from_context(s->bsfs[s->nb_bsfs - 1]->par_in, - avctx); - } else { - s->bsfs[s->nb_bsfs - 1]->time_base_in = s->bsfs[s->nb_bsfs - 2]->time_base_out; - ret = avcodec_parameters_copy(s->bsfs[s->nb_bsfs - 1]->par_in, - s->bsfs[s->nb_bsfs - 2]->par_out); - } - if (ret < 0) { - av_freep(&bsf); - goto fail; - } - - if (bsf_options_str && filter->priv_class) { - const AVOption *opt = av_opt_next(s->bsfs[s->nb_bsfs - 1]->priv_data, NULL); - const char * shorthand[2] = {NULL}; - - if (opt) - shorthand[0] = opt->name; - - ret = av_opt_set_from_string(s->bsfs[s->nb_bsfs - 1]->priv_data, bsf_options_str, shorthand, "=", ":"); - if (ret < 0) { - if (ret != AVERROR(ENOMEM)) { - av_log(avctx, AV_LOG_ERROR, "Invalid options for bitstream filter %s " - "requested by the decoder. This is a bug, please report it.\n", - bsf_name); - ret = AVERROR_BUG; - } - av_freep(&bsf); - goto fail; - } - } - av_freep(&bsf); + goto fail; + } - ret = av_bsf_init(s->bsfs[s->nb_bsfs - 1]); - if (ret < 0) - goto fail; + /* We do not currently have an API for passing the input timebase into decoders, + * but no filters used here should actually need it. + * So we make up some plausible-looking number (the MPEG 90kHz timebase) */ + avci->bsf->time_base_in = (AVRational){ 1, 90000 }; + ret = avcodec_parameters_from_context(avci->bsf->par_in, avctx); + if (ret < 0) + goto fail; - if (*bsfs_str) - bsfs_str++; - } + ret = av_bsf_init(avci->bsf); + if (ret < 0) + goto fail; return 0; fail: - ff_decode_bsfs_uninit(avctx); + av_bsf_free(&avci->bsf); return ret; } -/* try to get one output packet from the filter chain */ -static int bsfs_poll(AVCodecContext *avctx, AVPacket *pkt) -{ - DecodeFilterContext *s = &avctx->internal->filter; - int idx, ret; - - /* start with the last filter in the chain */ - idx = s->nb_bsfs - 1; - while (idx >= 0) { - /* request a packet from the currently selected filter */ - ret = av_bsf_receive_packet(s->bsfs[idx], pkt); - if (ret == AVERROR(EAGAIN)) { - /* no packets available, try the next filter up the chain */ - ret = 0; - idx--; - continue; - } else if (ret < 0 && ret != AVERROR_EOF) { - return ret; - } - - /* got a packet or EOF -- pass it to the caller or to the next filter - * down the chain */ - if (idx == s->nb_bsfs - 1) { - return ret; - } else { - idx++; - ret = av_bsf_send_packet(s->bsfs[idx], ret < 0 ? NULL : pkt); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, - "Error pre-processing a packet before decoding\n"); - av_packet_unref(pkt); - return ret; - } - } - } - - return AVERROR(EAGAIN); -} - int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt) { AVCodecInternal *avci = avctx->internal; @@ -334,7 +227,7 @@ if (avci->draining) return AVERROR_EOF; - ret = bsfs_poll(avctx, pkt); + ret = av_bsf_receive_packet(avci->bsf, pkt); if (ret == AVERROR_EOF) avci->draining = 1; if (ret < 0) @@ -348,8 +241,10 @@ if (ret < 0) goto finish; +#if FF_API_OLD_ENCDEC if (avctx->codec->receive_frame) avci->compat_decode_consumed += pkt->size; +#endif return 0; finish: @@ -399,12 +294,11 @@ * returning any output, so this function needs to be called in a loop until it * returns EAGAIN. **/ -static int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame) +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; - // copy to ensure we do not change pkt int got_frame, actual_got_frame; int ret; @@ -453,21 +347,14 @@ if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) { if (frame->flags & AV_FRAME_FLAG_DISCARD) got_frame = 0; - if (got_frame) - frame->best_effort_timestamp = guess_correct_pts(avctx, - frame->pts, - frame->pkt_dts); } else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { uint8_t *side; - int side_size; + buffer_size_t side_size; uint32_t discard_padding = 0; uint8_t skip_reason = 0; uint8_t discard_reason = 0; if (ret >= 0 && got_frame) { - frame->best_effort_timestamp = guess_correct_pts(avctx, - frame->pts, - frame->pkt_dts); if (frame->format == AV_SAMPLE_FMT_NONE) frame->format = avctx->sample_fmt; if (!frame->channel_layout) @@ -480,32 +367,34 @@ side= av_packet_get_side_data(avci->last_pkt_props, AV_PKT_DATA_SKIP_SAMPLES, &side_size); if(side && side_size>=10) { - avctx->internal->skip_samples = AV_RL32(side) * avctx->internal->skip_samples_multiplier; + avci->skip_samples = AV_RL32(side) * avci->skip_samples_multiplier; discard_padding = AV_RL32(side + 4); av_log(avctx, AV_LOG_DEBUG, "skip %d / discard %d samples due to side data\n", - avctx->internal->skip_samples, (int)discard_padding); + avci->skip_samples, (int)discard_padding); skip_reason = AV_RL8(side + 8); discard_reason = AV_RL8(side + 9); } if ((frame->flags & AV_FRAME_FLAG_DISCARD) && got_frame && !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { - avctx->internal->skip_samples = FFMAX(0, avctx->internal->skip_samples - frame->nb_samples); + avci->skip_samples = FFMAX(0, avci->skip_samples - frame->nb_samples); got_frame = 0; + *discarded_samples += frame->nb_samples; } - if (avctx->internal->skip_samples > 0 && got_frame && + if (avci->skip_samples > 0 && got_frame && !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { - if(frame->nb_samples <= avctx->internal->skip_samples){ + if(frame->nb_samples <= avci->skip_samples){ got_frame = 0; - avctx->internal->skip_samples -= frame->nb_samples; + *discarded_samples += frame->nb_samples; + avci->skip_samples -= frame->nb_samples; av_log(avctx, AV_LOG_DEBUG, "skip whole frame, skip left: %d\n", - avctx->internal->skip_samples); + avci->skip_samples); } else { - av_samples_copy(frame->extended_data, frame->extended_data, 0, avctx->internal->skip_samples, - frame->nb_samples - avctx->internal->skip_samples, avctx->channels, frame->format); + av_samples_copy(frame->extended_data, frame->extended_data, 0, avci->skip_samples, + frame->nb_samples - avci->skip_samples, avctx->channels, frame->format); if(avctx->pkt_timebase.num && avctx->sample_rate) { - int64_t diff_ts = av_rescale_q(avctx->internal->skip_samples, + int64_t diff_ts = av_rescale_q(avci->skip_samples, (AVRational){1, avctx->sample_rate}, avctx->pkt_timebase); if(frame->pts!=AV_NOPTS_VALUE) @@ -524,15 +413,17 @@ av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for skipped samples.\n"); } av_log(avctx, AV_LOG_DEBUG, "skip %d/%d samples\n", - avctx->internal->skip_samples, frame->nb_samples); - frame->nb_samples -= avctx->internal->skip_samples; - avctx->internal->skip_samples = 0; + avci->skip_samples, frame->nb_samples); + *discarded_samples += avci->skip_samples; + frame->nb_samples -= avci->skip_samples; + avci->skip_samples = 0; } } if (discard_padding > 0 && discard_padding <= frame->nb_samples && got_frame && !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) { if (discard_padding == frame->nb_samples) { + *discarded_samples += frame->nb_samples; got_frame = 0; } else { if(avctx->pkt_timebase.num && avctx->sample_rate) { @@ -552,11 +443,11 @@ if ((avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL) && got_frame) { AVFrameSideData *fside = av_frame_new_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES, 10); if (fside) { - AV_WL32(fside->data, avctx->internal->skip_samples); + AV_WL32(fside->data, avci->skip_samples); AV_WL32(fside->data + 4, discard_padding); AV_WL8(fside->data + 8, skip_reason); AV_WL8(fside->data + 9, discard_reason); - avctx->internal->skip_samples = 0; + avci->skip_samples = 0; } } } @@ -581,7 +472,7 @@ /* do not stop draining when actual_got_frame != 0 or ret < 0 */ /* got_frame == 0 but actual_got_frame != 0 when frame is discarded */ - if (avctx->internal->draining && !actual_got_frame) { + if (avci->draining && !actual_got_frame) { if (ret < 0) { /* prevent infinite loop if a decoder wrongly always return error on draining */ /* reasonable nb_errors_max = maximum b frames + thread count */ @@ -599,10 +490,13 @@ } } +#if FF_API_OLD_ENCDEC avci->compat_decode_consumed += ret; +#endif if (ret >= pkt->size || ret < 0) { av_packet_unref(pkt); + av_packet_unref(avci->last_pkt_props); } else { int consumed = ret; @@ -624,9 +518,12 @@ static int decode_simple_receive_frame(AVCodecContext *avctx, AVFrame *frame) { int ret; + int64_t discarded_samples = 0; while (!frame->buf[0]) { - ret = decode_simple_internal(avctx, frame); + if (discarded_samples > avctx->max_samples) + return AVERROR(EAGAIN); + ret = decode_simple_internal(avctx, frame, &discarded_samples); if (ret < 0) return ret; } @@ -641,15 +538,21 @@ av_assert0(!frame->buf[0]); - if (avctx->codec->receive_frame) + if (avctx->codec->receive_frame) { ret = avctx->codec->receive_frame(avctx, frame); - else + if (ret != AVERROR(EAGAIN)) + av_packet_unref(avci->last_pkt_props); + } else ret = decode_simple_receive_frame(avctx, frame); if (ret == AVERROR_EOF) avci->draining_done = 1; if (!ret) { + frame->best_effort_timestamp = guess_correct_pts(avctx, + frame->pts, + frame->pkt_dts); + /* the only case where decode data is not set should be decoders * that do not call ff_get_buffer() */ av_assert0((frame->private_ref && frame->private_ref->size == sizeof(FrameDecodeData)) || @@ -695,7 +598,7 @@ return ret; } - ret = av_bsf_send_packet(avci->filter.bsfs[0], avci->buffer_pkt); + ret = av_bsf_send_packet(avci->bsf, avci->buffer_pkt); if (ret < 0) { av_packet_unref(avci->buffer_pkt); return ret; @@ -786,7 +689,7 @@ if (avctx->frame_number > 1) { changed = avci->initial_format != frame->format; - switch(avctx->codec_type) { + switch(avctx->codec_type) { case AVMEDIA_TYPE_VIDEO: changed |= avci->initial_width != frame->width || avci->initial_height != frame->height; @@ -813,6 +716,54 @@ return 0; } +#if FF_API_OLD_ENCDEC +FF_DISABLE_DEPRECATION_WARNINGS +static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame) +{ + int ret; + + /* move the original frame to our backup */ + av_frame_unref(avci->to_free); + av_frame_move_ref(avci->to_free, frame); + + /* now copy everything except the AVBufferRefs back + * note that we make a COPY of the side data, so calling av_frame_free() on + * the caller's frame will work properly */ + ret = av_frame_copy_props(frame, avci->to_free); + if (ret < 0) + return ret; + + memcpy(frame->data, avci->to_free->data, sizeof(frame->data)); + memcpy(frame->linesize, avci->to_free->linesize, sizeof(frame->linesize)); + if (avci->to_free->extended_data != avci->to_free->data) { + int planes = avci->to_free->channels; + int size = planes * sizeof(*frame->extended_data); + + if (!size) { + av_frame_unref(frame); + return AVERROR_BUG; + } + + frame->extended_data = av_malloc(size); + if (!frame->extended_data) { + av_frame_unref(frame); + return AVERROR(ENOMEM); + } + memcpy(frame->extended_data, avci->to_free->extended_data, + size); + } else + frame->extended_data = frame->data; + + frame->format = avci->to_free->format; + frame->width = avci->to_free->width; + frame->height = avci->to_free->height; + frame->channel_layout = avci->to_free->channel_layout; + frame->nb_samples = avci->to_free->nb_samples; + frame->channels = avci->to_free->channels; + + return 0; +} + static int compat_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, const AVPacket *pkt) { @@ -827,7 +778,6 @@ } *got_frame = 0; - avci->compat_decode = 1; if (avci->compat_decode_partial_size > 0 && avci->compat_decode_partial_size != pkt->size) { @@ -909,6 +859,8 @@ { return compat_decode(avctx, frame, got_frame_ptr, avpkt); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif static void get_subtitle_defaults(AVSubtitle *sub) { @@ -917,55 +869,58 @@ } #define UTF8_MAX_BYTES 4 /* 5 and 6 bytes sequences should not be used */ -static int recode_subtitle(AVCodecContext *avctx, - AVPacket *outpkt, const AVPacket *inpkt) +static int recode_subtitle(AVCodecContext *avctx, AVPacket **outpkt, + AVPacket *inpkt, AVPacket *buf_pkt) { #if CONFIG_ICONV iconv_t cd = (iconv_t)-1; int ret = 0; char *inb, *outb; size_t inl, outl; - AVPacket tmp; #endif - if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_PRE_DECODER || inpkt->size == 0) + if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_PRE_DECODER || inpkt->size == 0) { + *outpkt = inpkt; return 0; + } #if CONFIG_ICONV - cd = iconv_open("UTF-8", avctx->sub_charenc); - av_assert0(cd != (iconv_t)-1); - inb = inpkt->data; inl = inpkt->size; if (inl >= INT_MAX / UTF8_MAX_BYTES - AV_INPUT_BUFFER_PADDING_SIZE) { av_log(avctx, AV_LOG_ERROR, "Subtitles packet is too big for recoding\n"); - ret = AVERROR(ENOMEM); - goto end; + return AVERROR(ERANGE); } - ret = av_new_packet(&tmp, inl * UTF8_MAX_BYTES); + cd = iconv_open("UTF-8", avctx->sub_charenc); + av_assert0(cd != (iconv_t)-1); + + ret = av_new_packet(buf_pkt, inl * UTF8_MAX_BYTES); if (ret < 0) goto end; - outpkt->buf = tmp.buf; - outpkt->data = tmp.data; - outpkt->size = tmp.size; - outb = outpkt->data; - outl = outpkt->size; + ret = av_packet_copy_props(buf_pkt, inpkt); + if (ret < 0) + goto end; + outb = buf_pkt->data; + outl = buf_pkt->size; if (iconv(cd, &inb, &inl, &outb, &outl) == (size_t)-1 || iconv(cd, NULL, NULL, &outb, &outl) == (size_t)-1 || - outl >= outpkt->size || inl != 0) { + outl >= buf_pkt->size || inl != 0) { ret = FFMIN(AVERROR(errno), -1); av_log(avctx, AV_LOG_ERROR, "Unable to recode subtitle event \"%s\" " "from %s to UTF-8\n", inpkt->data, avctx->sub_charenc); - av_packet_unref(&tmp); goto end; } - outpkt->size -= outl; - memset(outpkt->data + outpkt->size, 0, outl); + buf_pkt->size -= outl; + memset(buf_pkt->data + buf_pkt->size, 0, outl); + *outpkt = buf_pkt; + ret = 0; end: + if (ret < 0) + av_packet_unref(buf_pkt); if (cd != (iconv_t)-1) iconv_close(cd); return ret; @@ -1071,7 +1026,7 @@ int *got_sub_ptr, AVPacket *avpkt) { - int i, ret = 0; + int ret = 0; if (!avpkt->data && avpkt->size) { av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n"); @@ -1088,69 +1043,60 @@ get_subtitle_defaults(sub); if ((avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || avpkt->size) { - AVPacket pkt_recoded = *avpkt; + AVCodecInternal *avci = avctx->internal; + AVPacket *pkt; - ret = recode_subtitle(avctx, &pkt_recoded, avpkt); - if (ret < 0) { - *got_sub_ptr = 0; - } else { - ret = extract_packet_props(avctx->internal, &pkt_recoded); - if (ret < 0) - return ret; - - if (avctx->pkt_timebase.num && avpkt->pts != AV_NOPTS_VALUE) - sub->pts = av_rescale_q(avpkt->pts, - avctx->pkt_timebase, AV_TIME_BASE_Q); - ret = avctx->codec->decode(avctx, sub, got_sub_ptr, &pkt_recoded); - av_assert1((ret >= 0) >= !!*got_sub_ptr && - !!*got_sub_ptr >= !!sub->num_rects); + ret = recode_subtitle(avctx, &pkt, avpkt, avci->buffer_pkt); + if (ret < 0) + return ret; + + if (avctx->pkt_timebase.num && avpkt->pts != AV_NOPTS_VALUE) + sub->pts = av_rescale_q(avpkt->pts, + avctx->pkt_timebase, AV_TIME_BASE_Q); + ret = avctx->codec->decode(avctx, sub, got_sub_ptr, pkt); + av_assert1((ret >= 0) >= !!*got_sub_ptr && + !!*got_sub_ptr >= !!sub->num_rects); #if FF_API_ASS_TIMING - if (avctx->sub_text_format == FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS - && *got_sub_ptr && sub->num_rects) { - const AVRational tb = avctx->pkt_timebase.num ? avctx->pkt_timebase - : avctx->time_base; - int err = convert_sub_to_old_ass_form(sub, avpkt, tb); - if (err < 0) - ret = err; - } + if (avctx->sub_text_format == FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS + && *got_sub_ptr && sub->num_rects) { + const AVRational tb = avctx->pkt_timebase.num ? avctx->pkt_timebase + : avctx->time_base; + int err = convert_sub_to_old_ass_form(sub, avpkt, tb); + if (err < 0) + ret = err; + } #endif - if (sub->num_rects && !sub->end_display_time && avpkt->duration && - avctx->pkt_timebase.num) { - AVRational ms = { 1, 1000 }; - sub->end_display_time = av_rescale_q(avpkt->duration, - avctx->pkt_timebase, ms); - } - - if (avctx->codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB) - sub->format = 0; - else if (avctx->codec_descriptor->props & AV_CODEC_PROP_TEXT_SUB) - sub->format = 1; - - for (i = 0; i < sub->num_rects; i++) { - if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_IGNORE && - sub->rects[i]->ass && !utf8_check(sub->rects[i]->ass)) { - av_log(avctx, AV_LOG_ERROR, - "Invalid UTF-8 in decoded subtitles text; " - "maybe missing -sub_charenc option\n"); - avsubtitle_free(sub); - ret = AVERROR_INVALIDDATA; - break; - } - } - - if (avpkt->data != pkt_recoded.data) { // did we recode? - /* prevent from destroying side data from original packet */ - pkt_recoded.side_data = NULL; - pkt_recoded.side_data_elems = 0; + if (sub->num_rects && !sub->end_display_time && avpkt->duration && + avctx->pkt_timebase.num) { + AVRational ms = { 1, 1000 }; + sub->end_display_time = av_rescale_q(avpkt->duration, + avctx->pkt_timebase, ms); + } - av_packet_unref(&pkt_recoded); + if (avctx->codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB) + sub->format = 0; + else if (avctx->codec_descriptor->props & AV_CODEC_PROP_TEXT_SUB) + sub->format = 1; + + for (unsigned i = 0; i < sub->num_rects; i++) { + if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_IGNORE && + sub->rects[i]->ass && !utf8_check(sub->rects[i]->ass)) { + av_log(avctx, AV_LOG_ERROR, + "Invalid UTF-8 in decoded subtitles text; " + "maybe missing -sub_charenc option\n"); + avsubtitle_free(sub); + ret = AVERROR_INVALIDDATA; + break; } } if (*got_sub_ptr) avctx->frame_number++; + + if (pkt == avci->buffer_pkt) // did we recode? + av_packet_unref(avci->buffer_pkt); } return ret; @@ -1505,23 +1451,70 @@ return ret; } +static void frame_pool_free(void *opaque, uint8_t *data) +{ + FramePool *pool = (FramePool*)data; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++) + av_buffer_pool_uninit(&pool->pools[i]); + + av_freep(&data); +} + +static AVBufferRef *frame_pool_alloc(void) +{ + FramePool *pool = av_mallocz(sizeof(*pool)); + AVBufferRef *buf; + + if (!pool) + return NULL; + + buf = av_buffer_create((uint8_t*)pool, sizeof(*pool), + frame_pool_free, NULL, 0); + if (!buf) { + av_freep(&pool); + return NULL; + } + + return buf; +} + static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) { - FramePool *pool = avctx->internal->pool; - int i, ret; + FramePool *pool = avctx->internal->pool ? + (FramePool*)avctx->internal->pool->data : NULL; + AVBufferRef *pool_buf; + int i, ret, ch, planes; + + if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { + int planar = av_sample_fmt_is_planar(frame->format); + ch = frame->channels; + planes = planar ? ch : 1; + } + + if (pool && pool->format == frame->format) { + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && + pool->width == frame->width && pool->height == frame->height) + return 0; + if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && pool->planes == planes && + pool->channels == ch && frame->nb_samples == pool->samples) + return 0; + } + + pool_buf = frame_pool_alloc(); + if (!pool_buf) + return AVERROR(ENOMEM); + pool = (FramePool*)pool_buf->data; switch (avctx->codec_type) { case AVMEDIA_TYPE_VIDEO: { - uint8_t *data[4]; int linesize[4]; - int size[4] = { 0 }; int w = frame->width; int h = frame->height; - int tmpsize, unaligned; - - if (pool->format == frame->format && - pool->width == frame->width && pool->height == frame->height) - return 0; + int unaligned; + ptrdiff_t linesize1[4]; + size_t size[4]; avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align); @@ -1530,7 +1523,7 @@ // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2 ret = av_image_fill_linesizes(linesize, avctx->pix_fmt, w); if (ret < 0) - return ret; + goto fail; // increase alignment of w for next try (rhs gives the lowest bit set in w) w += w & ~(w - 1); @@ -1539,19 +1532,19 @@ unaligned |= linesize[i] % pool->stride_align[i]; } while (unaligned); - tmpsize = av_image_fill_pointers(data, avctx->pix_fmt, h, - NULL, linesize); - if (tmpsize < 0) - return tmpsize; - - for (i = 0; i < 3 && data[i + 1]; i++) - size[i] = data[i + 1] - data[i]; - size[i] = tmpsize - (data[i] - data[0]); + for (i = 0; i < 4; i++) + linesize1[i] = linesize[i]; + ret = av_image_fill_plane_sizes(size, avctx->pix_fmt, h, linesize1); + if (ret < 0) + goto fail; for (i = 0; i < 4; i++) { - av_buffer_pool_uninit(&pool->pools[i]); pool->linesize[i] = linesize[i]; if (size[i]) { + if (size[i] > INT_MAX - (16 + STRIDE_ALIGN - 1)) { + ret = AVERROR(EINVAL); + goto fail; + } pool->pools[i] = av_buffer_pool_init(size[i] + 16 + STRIDE_ALIGN - 1, CONFIG_MEMORY_POISONING ? NULL : @@ -1569,15 +1562,6 @@ break; } case AVMEDIA_TYPE_AUDIO: { - int ch = frame->channels; //av_get_channel_layout_nb_channels(frame->channel_layout); - int planar = av_sample_fmt_is_planar(frame->format); - int planes = planar ? ch : 1; - - if (pool->format == frame->format && pool->planes == planes && - pool->channels == ch && frame->nb_samples == pool->samples) - return 0; - - av_buffer_pool_uninit(&pool->pools[0]); ret = av_samples_get_buffer_size(&pool->linesize[0], ch, frame->nb_samples, frame->format, 0); if (ret < 0) @@ -1597,19 +1581,19 @@ } default: av_assert0(0); } + + av_buffer_unref(&avctx->internal->pool); + avctx->internal->pool = pool_buf; + return 0; fail: - for (i = 0; i < 4; i++) - av_buffer_pool_uninit(&pool->pools[i]); - pool->format = -1; - pool->planes = pool->channels = pool->samples = 0; - pool->width = pool->height = 0; + av_buffer_unref(&pool_buf); return ret; } static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) { - FramePool *pool = avctx->internal->pool; + FramePool *pool = (FramePool*)avctx->internal->pool->data; int planes = pool->planes; int i; @@ -1654,7 +1638,7 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic) { - FramePool *pool = s->internal->pool; + FramePool *pool = (FramePool*)s->internal->pool->data; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format); int i; @@ -1725,7 +1709,7 @@ static int add_metadata_from_side_data(const AVPacket *avpkt, AVFrame *frame) { - int size; + buffer_size_t size; const uint8_t *side_metadata; AVDictionary **frame_md = &frame->metadata; @@ -1737,8 +1721,7 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) { - const AVPacket *pkt = avctx->internal->last_pkt_props; - int i; + AVPacket *pkt = avctx->internal->last_pkt_props; static const struct { enum AVPacketSideDataType packet; enum AVFrameSideDataType frame; @@ -1751,39 +1734,43 @@ { AV_PKT_DATA_MASTERING_DISPLAY_METADATA, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA }, { AV_PKT_DATA_CONTENT_LIGHT_LEVEL, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL }, { AV_PKT_DATA_A53_CC, AV_FRAME_DATA_A53_CC }, + { AV_PKT_DATA_ICC_PROFILE, AV_FRAME_DATA_ICC_PROFILE }, + { AV_PKT_DATA_S12M_TIMECODE, AV_FRAME_DATA_S12M_TIMECODE }, }; - if (pkt) { - frame->pts = pkt->pts; + if (IS_EMPTY(pkt) && av_fifo_size(avctx->internal->pkt_props) >= sizeof(*pkt)) + av_fifo_generic_read(avctx->internal->pkt_props, + pkt, sizeof(*pkt), NULL); + + frame->pts = pkt->pts; #if FF_API_PKT_PTS FF_DISABLE_DEPRECATION_WARNINGS - frame->pkt_pts = pkt->pts; + frame->pkt_pts = pkt->pts; FF_ENABLE_DEPRECATION_WARNINGS #endif - frame->pkt_pos = pkt->pos; - frame->pkt_duration = pkt->duration; - frame->pkt_size = pkt->size; - - for (i = 0; i < FF_ARRAY_ELEMS(sd); i++) { - int size; - uint8_t *packet_sd = av_packet_get_side_data(pkt, sd[i].packet, &size); - if (packet_sd) { - AVFrameSideData *frame_sd = av_frame_new_side_data(frame, - sd[i].frame, - size); - if (!frame_sd) - return AVERROR(ENOMEM); + frame->pkt_pos = pkt->pos; + frame->pkt_duration = pkt->duration; + frame->pkt_size = pkt->size; + + for (int i = 0; i < FF_ARRAY_ELEMS(sd); i++) { + buffer_size_t size; + uint8_t *packet_sd = av_packet_get_side_data(pkt, sd[i].packet, &size); + if (packet_sd) { + AVFrameSideData *frame_sd = av_frame_new_side_data(frame, + sd[i].frame, + size); + if (!frame_sd) + return AVERROR(ENOMEM); - memcpy(frame_sd->data, packet_sd, size); - } + memcpy(frame_sd->data, packet_sd, size); } - add_metadata_from_side_data(pkt, frame); + } + add_metadata_from_side_data(pkt, frame); - if (pkt->flags & AV_PKT_FLAG_DISCARD) { - frame->flags |= AV_FRAME_FLAG_DISCARD; - } else { - frame->flags = (frame->flags & ~AV_FRAME_FLAG_DISCARD); - } + if (pkt->flags & AV_PKT_FLAG_DISCARD) { + frame->flags |= AV_FRAME_FLAG_DISCARD; + } else { + frame->flags = (frame->flags & ~AV_FRAME_FLAG_DISCARD); } frame->reordered_opaque = avctx->reordered_opaque; @@ -1903,16 +1890,18 @@ return 0; } -static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) +int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) { const AVHWAccel *hwaccel = avctx->hwaccel; int override_dimensions = 1; int ret; if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { - if ((ret = av_image_check_size2(FFALIGN(avctx->width, STRIDE_ALIGN), avctx->height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx)) < 0 || avctx->pix_fmt<0) { + if ((unsigned)avctx->width > INT_MAX - STRIDE_ALIGN || + (ret = av_image_check_size2(FFALIGN(avctx->width, STRIDE_ALIGN), avctx->height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx)) < 0 || avctx->pix_fmt<0) { av_log(avctx, AV_LOG_ERROR, "video_get_buffer: image parameters invalid\n"); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } if (frame->width <= 0 || frame->height <= 0) { @@ -1923,12 +1912,19 @@ if (frame->data[0] || frame->data[1] || frame->data[2] || frame->data[3]) { av_log(avctx, AV_LOG_ERROR, "pic->data[*]!=NULL in get_buffer_internal\n"); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; + } + } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { + if (frame->nb_samples * (int64_t)avctx->channels > avctx->max_samples) { + av_log(avctx, AV_LOG_ERROR, "samples per frame %d, exceeds max_samples %"PRId64"\n", frame->nb_samples, avctx->max_samples); + ret = AVERROR(EINVAL); + goto fail; } } ret = ff_decode_frame_props(avctx, frame); if (ret < 0) - return ret; + goto fail; if (hwaccel) { if (hwaccel->alloc_frame) { @@ -1940,13 +1936,13 @@ ret = avctx->get_buffer2(avctx, frame, flags); if (ret < 0) - goto end; + goto fail; validate_avframe_allocation(avctx, frame); ret = ff_attach_decode_data(frame); if (ret < 0) - goto end; + goto fail; end: if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions && @@ -1955,23 +1951,16 @@ frame->height = avctx->height; } - if (ret < 0) - av_frame_unref(frame); - - return ret; -} - -int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) -{ - int ret = get_buffer_internal(avctx, frame, flags); +fail: if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); - frame->width = frame->height = 0; + av_frame_unref(frame); } + return ret; } -static int reget_buffer_internal(AVCodecContext *avctx, AVFrame *frame) +static int reget_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) { AVFrame *tmp; int ret; @@ -1987,7 +1976,7 @@ if (!frame->data[0]) return ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF); - if (av_frame_is_writable(frame)) + if ((flags & FF_REGET_BUFFER_FLAG_READONLY) || av_frame_is_writable(frame)) return ff_decode_frame_props(avctx, frame); tmp = av_frame_alloc(); @@ -2008,55 +1997,57 @@ return 0; } -int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame) +int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) { - int ret = reget_buffer_internal(avctx, frame); + int ret = reget_buffer_internal(avctx, frame, flags); if (ret < 0) av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); return ret; } -static void bsfs_flush(AVCodecContext *avctx) +int ff_decode_preinit(AVCodecContext *avctx) { - DecodeFilterContext *s = &avctx->internal->filter; - - for (int i = 0; i < s->nb_bsfs; i++) - av_bsf_flush(s->bsfs[i]); -} + int ret = 0; -void avcodec_flush_buffers(AVCodecContext *avctx) -{ - avctx->internal->draining = 0; - avctx->internal->draining_done = 0; - avctx->internal->nb_draining_errors = 0; - av_frame_unref(avctx->internal->buffer_frame); - av_frame_unref(avctx->internal->compat_decode_frame); - av_packet_unref(avctx->internal->buffer_pkt); - avctx->internal->buffer_pkt_valid = 0; + /* if the decoder init function was already called previously, + * free the already allocated subtitle_header before overwriting it */ + av_freep(&avctx->subtitle_header); - av_packet_unref(avctx->internal->ds.in_pkt); +#if FF_API_THREAD_SAFE_CALLBACKS +FF_DISABLE_DEPRECATION_WARNINGS + if ((avctx->thread_type & FF_THREAD_FRAME) && + avctx->get_buffer2 != avcodec_default_get_buffer2 && + !avctx->thread_safe_callbacks) { + av_log(avctx, AV_LOG_WARNING, "Requested frame threading with a " + "custom get_buffer2() implementation which is not marked as " + "thread safe. This is not supported anymore, make your " + "callback thread-safe.\n"); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif - if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) - ff_thread_flush(avctx); - else if (avctx->codec->flush) - avctx->codec->flush(avctx); + if (avctx->codec->max_lowres < avctx->lowres || avctx->lowres < 0) { + av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n", + avctx->codec->max_lowres); + avctx->lowres = avctx->codec->max_lowres; + } + avctx->pts_correction_num_faulty_pts = + avctx->pts_correction_num_faulty_dts = 0; avctx->pts_correction_last_pts = avctx->pts_correction_last_dts = INT64_MIN; - bsfs_flush(avctx); - - if (!avctx->refcounted_frames) - av_frame_unref(avctx->internal->to_free); -} + if ( !CONFIG_GRAY && avctx->flags & AV_CODEC_FLAG_GRAY + && avctx->codec_descriptor->type == AVMEDIA_TYPE_VIDEO) + av_log(avctx, AV_LOG_WARNING, + "gray decoding requested but not enabled at configuration time\n"); + if (avctx->flags2 & AV_CODEC_FLAG2_EXPORT_MVS) { + avctx->export_side_data |= AV_CODEC_EXPORT_DATA_MVS; + } -void ff_decode_bsfs_uninit(AVCodecContext *avctx) -{ - DecodeFilterContext *s = &avctx->internal->filter; - int i; + ret = decode_bsfs_init(avctx); + if (ret < 0) + return ret; - for (i = 0; i < s->nb_bsfs; i++) - av_bsf_free(&s->bsfs[i]); - av_freep(&s->bsfs); - s->nb_bsfs = 0; + return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/decode.h ffmpeg-4.4/libavcodec/decode.h --- ffmpeg-4.2.2/libavcodec/decode.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/decode.h 2021-04-08 21:28:39.000000000 +0000 @@ -64,9 +64,10 @@ */ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt); -int ff_decode_bsfs_init(AVCodecContext *avctx); - -void ff_decode_bsfs_uninit(AVCodecContext *avctx); +/** + * Set various frame properties from the codec context / packet data. + */ +int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame); /** * Make sure avctx.hw_frames_ctx is set. If it's not set, the function will @@ -78,4 +79,10 @@ int ff_attach_decode_data(AVFrame *frame); +/** + * Perform decoder initialization and validation. + * Called when opening the decoder, before the AVCodec.init() call. + */ +int ff_decode_preinit(AVCodecContext *avctx); + #endif /* AVCODEC_DECODE_H */ diff -Nru ffmpeg-4.2.2/libavcodec/dfa.c ffmpeg-4.4/libavcodec/dfa.c --- ffmpeg-4.2.2/libavcodec/dfa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dfa.c 2020-07-11 10:39:30.000000000 +0000 @@ -332,7 +332,7 @@ decode_tdlt, decode_dsw1, decode_blck, decode_dds1, }; -static const char * const chunk_name[8] = { +static const char chunk_name[8][5] = { "COPY", "TSW1", "BDLT", "WDLT", "TDLT", "DSW1", "BLCK", "DDS1" }; diff -Nru ffmpeg-4.2.2/libavcodec/dirac_arith.c ffmpeg-4.4/libavcodec/dirac_arith.c --- ffmpeg-4.2.2/libavcodec/dirac_arith.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dirac_arith.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,7 +28,7 @@ #include "dirac_arith.h" -const uint16_t ff_dirac_prob[256] = { +static const uint16_t dirac_prob[256] = { 0, 2, 5, 8, 11, 15, 20, 24, 29, 35, 41, 47, 53, 60, 67, 74, 82, 89, 97, 106, 114, 123, 132, 141, @@ -88,8 +88,8 @@ int i; for (i = 0; i < 256; i++) { - ff_dirac_prob_branchless[i][0] = ff_dirac_prob[255-i]; - ff_dirac_prob_branchless[i][1] = -ff_dirac_prob[i]; + ff_dirac_prob_branchless[i][0] = dirac_prob[255-i]; + ff_dirac_prob_branchless[i][1] = -dirac_prob[i]; } } diff -Nru ffmpeg-4.2.2/libavcodec/dirac_arith.h ffmpeg-4.4/libavcodec/dirac_arith.h --- ffmpeg-4.2.2/libavcodec/dirac_arith.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dirac_arith.h 2021-04-08 21:28:39.000000000 +0000 @@ -86,7 +86,6 @@ } DiracArith; extern const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT]; -extern const uint16_t ff_dirac_prob[256]; extern int16_t ff_dirac_prob_branchless[256][2]; static inline void renorm(DiracArith *c) diff -Nru ffmpeg-4.2.2/libavcodec/diracdec.c ffmpeg-4.4/libavcodec/diracdec.c --- ffmpeg-4.2.2/libavcodec/diracdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/diracdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,7 @@ * @author Marco Gerards , David Conrad, Jordi Ortiz */ +#include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" #include "libavutil/thread.h" #include "avcodec.h" @@ -136,7 +137,6 @@ MpegvideoEncDSPContext mpvencdsp; VideoDSPContext vdsp; DiracDSPContext diracdsp; - DiracGolombLUT *reader_ctx; DiracVersionInfo version; GetBitContext gb; AVDiracSeqHeader seq; @@ -395,7 +395,6 @@ s->threads_num_buf = -1; s->thread_buf_size = -1; - ff_dirac_golomb_reader_init(&s->reader_ctx); ff_diracdsp_init(&s->diracdsp); ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx); ff_videodsp_init(&s->vdsp, 8); @@ -428,8 +427,6 @@ DiracContext *s = avctx->priv_data; int i; - ff_dirac_golomb_reader_end(&s->reader_ctx); - dirac_decode_flush(avctx); for (i = 0; i < MAX_FRAMES; i++) av_frame_free(&s->all_frames[i].avframe); @@ -881,11 +878,11 @@ coef_num = subband_coeffs(s, slice->slice_x, slice->slice_y, i, coeffs_num); if (s->pshift) - coef_par = ff_dirac_golomb_read_32bit(s->reader_ctx, addr, - length, tmp_buf, coef_num); + coef_par = ff_dirac_golomb_read_32bit(addr, length, + tmp_buf, coef_num); else - coef_par = ff_dirac_golomb_read_16bit(s->reader_ctx, addr, - length, tmp_buf, coef_num); + coef_par = ff_dirac_golomb_read_16bit(addr, length, + tmp_buf, coef_num); if (coef_num > coef_par) { const int start_b = coef_par * (1 << (s->pshift + 1)); diff -Nru ffmpeg-4.2.2/libavcodec/diracdsp.c ffmpeg-4.4/libavcodec/diracdsp.c --- ffmpeg-4.2.2/libavcodec/diracdsp.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/diracdsp.c 2021-04-08 21:28:39.000000000 +0000 @@ -195,12 +195,12 @@ { \ int i, y; \ for (y = 0; y < tot_v; y++) { \ - PX c, sign, *src_r = (PX *)src, *dst_r = (PX *)dst; \ + PX c, *src_r = (PX *)src, *dst_r = (PX *)dst; \ for (i = 0; i < tot_h; i++) { \ c = *src_r++; \ - sign = FFSIGN(c)*(!!c); \ - c = (FFABS(c)*(unsigned)qf + qs) >> 2; \ - *dst_r++ = c*sign; \ + if (c < 0) c = -((-(unsigned)c*qf + qs) >> 2); \ + else if(c > 0) c = (( (unsigned)c*qf + qs) >> 2); \ + *dst_r++ = c; \ } \ src += tot_h << (sizeof(PX) >> 1); \ dst += stride; \ diff -Nru ffmpeg-4.2.2/libavcodec/dirac_parser.c ffmpeg-4.4/libavcodec/dirac_parser.c --- ffmpeg-4.2.2/libavcodec/dirac_parser.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dirac_parser.c 2021-02-20 20:27:47.000000000 +0000 @@ -215,7 +215,7 @@ int64_t pts = AV_RB32(cur_pu + 13); if (s->last_pts == 0 && s->last_dts == 0) s->dts = pts - 1; - else + else if (s->last_dts != AV_NOPTS_VALUE) s->dts = s->last_dts + 1; s->pts = pts; if (!avctx->has_b_frames && (cur_pu[4] & 0x03)) diff -Nru ffmpeg-4.2.2/libavcodec/dirac_vlc.c ffmpeg-4.4/libavcodec/dirac_vlc.c --- ffmpeg-4.2.2/libavcodec/dirac_vlc.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dirac_vlc.c 2021-04-08 21:28:39.000000000 +0000 @@ -1,7 +1,4 @@ /* - * Copyright (C) 2016 Open Broadcast Systems Ltd. - * Author 2016 Rostislav Pehlivanov - * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -19,234 +16,1118 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "dirac_vlc.h" - -#define LUT_SIZE (1 << LUT_BITS) -#define RSIZE_BITS (CHAR_BIT*sizeof(residual)) - -#define CONVERT_TO_RESIDUE(a, b) \ - (((residual)(a)) << (RSIZE_BITS - (b))) - -#define INIT_RESIDUE(N) \ - residual N = 0; \ - av_unused int32_t N ## _bits = 0 - -#define SET_RESIDUE(N, I, B) \ - N = CONVERT_TO_RESIDUE(I, B); \ - N ## _bits = B - -#define APPEND_RESIDUE(N, M) \ - N |= M >> (N ## _bits); \ - N ## _bits = (N ## _bits + (M ## _bits)) & 0x3F - -int ff_dirac_golomb_read_32bit(DiracGolombLUT *lut_ctx, const uint8_t *buf, - int bytes, uint8_t *_dst, int coeffs) -{ - int i, b, c_idx = 0; - int32_t *dst = (int32_t *)_dst; - DiracGolombLUT *future[4], *l = &lut_ctx[2*LUT_SIZE + buf[0]]; - INIT_RESIDUE(res); - - for (b = 1; b <= bytes; b++) { - future[0] = &lut_ctx[buf[b]]; - future[1] = future[0] + 1*LUT_SIZE; - future[2] = future[0] + 2*LUT_SIZE; - future[3] = future[0] + 3*LUT_SIZE; - - if ((c_idx + 1) > coeffs) - return c_idx; - - /* res_bits is a hint for better branch prediction */ - if (res_bits && l->sign) { - int32_t coeff = 1; - APPEND_RESIDUE(res, l->preamble); - for (i = 0; i < (res_bits >> 1) - 1; i++) { - coeff <<= 1; - coeff |= (res >> (RSIZE_BITS - 2*i - 2)) & 1; - } - dst[c_idx++] = l->sign * (coeff - 1); - res_bits = res = 0; - } - - memcpy(&dst[c_idx], l->ready, LUT_BITS*sizeof(int32_t)); - c_idx += l->ready_num; - - APPEND_RESIDUE(res, l->leftover); - - l = future[l->need_s ? 3 : !res_bits ? 2 : res_bits & 1]; - } - - return c_idx; -} - -int ff_dirac_golomb_read_16bit(DiracGolombLUT *lut_ctx, const uint8_t *buf, - int bytes, uint8_t *_dst, int coeffs) -{ - int i, b, c_idx = 0; - int16_t *dst = (int16_t *)_dst; - DiracGolombLUT *future[4], *l = &lut_ctx[2*LUT_SIZE + buf[0]]; - INIT_RESIDUE(res); - - for (b = 1; b <= bytes; b++) { - future[0] = &lut_ctx[buf[b]]; - future[1] = future[0] + 1*LUT_SIZE; - future[2] = future[0] + 2*LUT_SIZE; - future[3] = future[0] + 3*LUT_SIZE; - - if ((c_idx + 1) > coeffs) - return c_idx; - - if (res_bits && l->sign) { - int32_t coeff = 1; - APPEND_RESIDUE(res, l->preamble); - for (i = 0; i < (res_bits >> 1) - 1; i++) { - coeff <<= 1; - coeff |= (res >> (RSIZE_BITS - 2*i - 2)) & 1; - } - dst[c_idx++] = l->sign * (coeff - 1); - res_bits = res = 0; - } - - for (i = 0; i < LUT_BITS; i++) - dst[c_idx + i] = l->ready[i]; - c_idx += l->ready_num; +#include "libavutil/mem_internal.h" - APPEND_RESIDUE(res, l->leftover); - - l = future[l->need_s ? 3 : !res_bits ? 2 : res_bits & 1]; - } +#include "dirac_vlc.h" - return c_idx; -} +enum { + /* Next byte contains an exactly aligned start to a new symbol (even bit) */ + STATE_START = 0, + /* Next byte should end the current value on an odd bit */ + STATE_FOLLOW = 256, + /* Byte is completely data and doesn't end nor start a value */ + STATE_DATA = 512, + /* Byte has the current value's sign bit and starts a new value */ + STATE_SIGN = 768, +}; + +/* Exactly 128 bits */ +typedef struct LUTState { + int16_t val0; /* Bits to which to add after applying preshift */ + int16_t val1; + int16_t val2; + int16_t val3; + int16_t val4; + uint8_t val0_bits; /* The size of val0 in bits */ + int8_t sign; /* Sign of the current value (0 == zero the value) */ + int8_t num; /* Number of values in this byte */ + uint8_t val; /* Init value in case current value was terminated */ + uint16_t state; /* Expected state for the next byte */ +} LUTState; + +static const DECLARE_ALIGNED(32, LUTState, dirac_golomb_lut)[1024] = { + { +16, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +17, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +8, 0, 0, 0, 0, 4, +1, 1, 0, STATE_START }, + { +8, 0, 0, 0, 0, 4, -1, 1, 0, STATE_START }, + { +18, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +19, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +9, 0, 0, 0, 0, 4, +1, 1, 0, STATE_START }, + { +9, 0, 0, 0, 0, 4, -1, 1, 0, STATE_START }, + { +4, 0, 0, 0, 0, 3, +1, 1, 2, STATE_FOLLOW }, + { +4, 0, 0, 0, 0, 3, +1, 1, 3, STATE_FOLLOW }, + { +4, 0, 0, 0, 0, 3, +1, 2, 1, STATE_DATA }, + { +4, 0, 0, 0, 0, 3, +1, 3, 0, STATE_START }, + { +4, 0, 0, 0, 0, 3, -1, 1, 2, STATE_FOLLOW }, + { +4, 0, 0, 0, 0, 3, -1, 1, 3, STATE_FOLLOW }, + { +4, 0, 0, 0, 0, 3, -1, 2, 1, STATE_DATA }, + { +4, 0, 0, 0, 0, 3, -1, 3, 0, STATE_START }, + { +20, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +21, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +10, 0, 0, 0, 0, 4, +1, 1, 0, STATE_START }, + { +10, 0, 0, 0, 0, 4, -1, 1, 0, STATE_START }, + { +22, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +23, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +11, 0, 0, 0, 0, 4, +1, 1, 0, STATE_START }, + { +11, 0, 0, 0, 0, 4, -1, 1, 0, STATE_START }, + { +5, 0, 0, 0, 0, 3, +1, 1, 2, STATE_FOLLOW }, + { +5, 0, 0, 0, 0, 3, +1, 1, 3, STATE_FOLLOW }, + { +5, 0, 0, 0, 0, 3, +1, 2, 1, STATE_DATA }, + { +5, 0, 0, 0, 0, 3, +1, 3, 0, STATE_START }, + { +5, 0, 0, 0, 0, 3, -1, 1, 2, STATE_FOLLOW }, + { +5, 0, 0, 0, 0, 3, -1, 1, 3, STATE_FOLLOW }, + { +5, 0, 0, 0, 0, 3, -1, 2, 1, STATE_DATA }, + { +5, 0, 0, 0, 0, 3, -1, 3, 0, STATE_START }, + { +2, 0, 0, 0, 0, 2, +1, 1, 4, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, +1, 1, 5, STATE_FOLLOW }, + { +2, +1, 0, 0, 0, 2, +1, 2, 0, STATE_START }, + { +2, -1, 0, 0, 0, 2, +1, 2, 0, STATE_START }, + { +2, 0, 0, 0, 0, 2, +1, 1, 6, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, +1, 1, 7, STATE_FOLLOW }, + { +2, +2, 0, 0, 0, 2, +1, 2, 0, STATE_START }, + { +2, -2, 0, 0, 0, 2, +1, 2, 0, STATE_START }, + { +2, 0, 0, 0, 0, 2, +1, 2, 2, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, +1, 2, 2, STATE_SIGN }, + { +2, 0, 0, 0, 0, 2, +1, 2, 3, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, +1, 2, 3, STATE_SIGN }, + { +2, 0, 0, 0, 0, 2, +1, 3, 2, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, +1, 3, 3, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, +1, 4, 1, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, +1, 5, 0, STATE_START }, + { +2, 0, 0, 0, 0, 2, -1, 1, 4, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, -1, 1, 5, STATE_FOLLOW }, + { +2, +1, 0, 0, 0, 2, -1, 2, 0, STATE_START }, + { +2, -1, 0, 0, 0, 2, -1, 2, 0, STATE_START }, + { +2, 0, 0, 0, 0, 2, -1, 1, 6, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, -1, 1, 7, STATE_FOLLOW }, + { +2, +2, 0, 0, 0, 2, -1, 2, 0, STATE_START }, + { +2, -2, 0, 0, 0, 2, -1, 2, 0, STATE_START }, + { +2, 0, 0, 0, 0, 2, -1, 2, 2, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, -1, 2, 2, STATE_SIGN }, + { +2, 0, 0, 0, 0, 2, -1, 2, 3, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, -1, 2, 3, STATE_SIGN }, + { +2, 0, 0, 0, 0, 2, -1, 3, 2, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, -1, 3, 3, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, -1, 4, 1, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, -1, 5, 0, STATE_START }, + { +24, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +25, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +12, 0, 0, 0, 0, 4, +1, 1, 0, STATE_START }, + { +12, 0, 0, 0, 0, 4, -1, 1, 0, STATE_START }, + { +26, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +27, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +13, 0, 0, 0, 0, 4, +1, 1, 0, STATE_START }, + { +13, 0, 0, 0, 0, 4, -1, 1, 0, STATE_START }, + { +6, 0, 0, 0, 0, 3, +1, 1, 2, STATE_FOLLOW }, + { +6, 0, 0, 0, 0, 3, +1, 1, 3, STATE_FOLLOW }, + { +6, 0, 0, 0, 0, 3, +1, 2, 1, STATE_DATA }, + { +6, 0, 0, 0, 0, 3, +1, 3, 0, STATE_START }, + { +6, 0, 0, 0, 0, 3, -1, 1, 2, STATE_FOLLOW }, + { +6, 0, 0, 0, 0, 3, -1, 1, 3, STATE_FOLLOW }, + { +6, 0, 0, 0, 0, 3, -1, 2, 1, STATE_DATA }, + { +6, 0, 0, 0, 0, 3, -1, 3, 0, STATE_START }, + { +28, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +29, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +14, 0, 0, 0, 0, 4, +1, 1, 0, STATE_START }, + { +14, 0, 0, 0, 0, 4, -1, 1, 0, STATE_START }, + { +30, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +31, 0, 0, 0, 0, 5, +1, 0, 0, STATE_FOLLOW }, + { +15, 0, 0, 0, 0, 4, +1, 1, 0, STATE_START }, + { +15, 0, 0, 0, 0, 4, -1, 1, 0, STATE_START }, + { +7, 0, 0, 0, 0, 3, +1, 1, 2, STATE_FOLLOW }, + { +7, 0, 0, 0, 0, 3, +1, 1, 3, STATE_FOLLOW }, + { +7, 0, 0, 0, 0, 3, +1, 2, 1, STATE_DATA }, + { +7, 0, 0, 0, 0, 3, +1, 3, 0, STATE_START }, + { +7, 0, 0, 0, 0, 3, -1, 1, 2, STATE_FOLLOW }, + { +7, 0, 0, 0, 0, 3, -1, 1, 3, STATE_FOLLOW }, + { +7, 0, 0, 0, 0, 3, -1, 2, 1, STATE_DATA }, + { +7, 0, 0, 0, 0, 3, -1, 3, 0, STATE_START }, + { +3, 0, 0, 0, 0, 2, +1, 1, 4, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, +1, 1, 5, STATE_FOLLOW }, + { +3, +1, 0, 0, 0, 2, +1, 2, 0, STATE_START }, + { +3, -1, 0, 0, 0, 2, +1, 2, 0, STATE_START }, + { +3, 0, 0, 0, 0, 2, +1, 1, 6, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, +1, 1, 7, STATE_FOLLOW }, + { +3, +2, 0, 0, 0, 2, +1, 2, 0, STATE_START }, + { +3, -2, 0, 0, 0, 2, +1, 2, 0, STATE_START }, + { +3, 0, 0, 0, 0, 2, +1, 2, 2, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, +1, 2, 2, STATE_SIGN }, + { +3, 0, 0, 0, 0, 2, +1, 2, 3, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, +1, 2, 3, STATE_SIGN }, + { +3, 0, 0, 0, 0, 2, +1, 3, 2, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, +1, 3, 3, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, +1, 4, 1, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, +1, 5, 0, STATE_START }, + { +3, 0, 0, 0, 0, 2, -1, 1, 4, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, -1, 1, 5, STATE_FOLLOW }, + { +3, +1, 0, 0, 0, 2, -1, 2, 0, STATE_START }, + { +3, -1, 0, 0, 0, 2, -1, 2, 0, STATE_START }, + { +3, 0, 0, 0, 0, 2, -1, 1, 6, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, -1, 1, 7, STATE_FOLLOW }, + { +3, +2, 0, 0, 0, 2, -1, 2, 0, STATE_START }, + { +3, -2, 0, 0, 0, 2, -1, 2, 0, STATE_START }, + { +3, 0, 0, 0, 0, 2, -1, 2, 2, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, -1, 2, 2, STATE_SIGN }, + { +3, 0, 0, 0, 0, 2, -1, 2, 3, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, -1, 2, 3, STATE_SIGN }, + { +3, 0, 0, 0, 0, 2, -1, 3, 2, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, -1, 3, 3, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, -1, 4, 1, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, -1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 1, 8, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 1, 8, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, 0, 1, 9, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 1, 9, STATE_SIGN }, + { 0, +3, 0, 0, 0, 0, 0, 2, 1, STATE_DATA }, + { 0, +3, 0, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, -3, 0, 0, 0, 0, 0, 2, 1, STATE_DATA }, + { 0, -3, 0, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 1, 10, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 1, 10, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, 0, 1, 11, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 1, 11, STATE_SIGN }, + { 0, +4, 0, 0, 0, 0, 0, 2, 1, STATE_DATA }, + { 0, +4, 0, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, -4, 0, 0, 0, 0, 0, 2, 1, STATE_DATA }, + { 0, -4, 0, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, +1, 0, 0, 0, 0, 0, 2, 2, STATE_DATA }, + { 0, +1, 0, 0, 0, 0, 0, 2, 2, STATE_SIGN }, + { 0, +1, 0, 0, 0, 0, 0, 2, 3, STATE_DATA }, + { 0, +1, 0, 0, 0, 0, 0, 2, 3, STATE_SIGN }, + { 0, +1, 0, 0, 0, 0, 0, 3, 2, STATE_FOLLOW }, + { 0, +1, 0, 0, 0, 0, 0, 3, 3, STATE_FOLLOW }, + { 0, +1, 0, 0, 0, 0, 0, 4, 1, STATE_DATA }, + { 0, +1, 0, 0, 0, 0, 0, 5, 0, STATE_START }, + { 0, -1, 0, 0, 0, 0, 0, 2, 2, STATE_DATA }, + { 0, -1, 0, 0, 0, 0, 0, 2, 2, STATE_SIGN }, + { 0, -1, 0, 0, 0, 0, 0, 2, 3, STATE_DATA }, + { 0, -1, 0, 0, 0, 0, 0, 2, 3, STATE_SIGN }, + { 0, -1, 0, 0, 0, 0, 0, 3, 2, STATE_FOLLOW }, + { 0, -1, 0, 0, 0, 0, 0, 3, 3, STATE_FOLLOW }, + { 0, -1, 0, 0, 0, 0, 0, 4, 1, STATE_DATA }, + { 0, -1, 0, 0, 0, 0, 0, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 1, 12, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 1, 12, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, 0, 1, 13, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 1, 13, STATE_SIGN }, + { 0, +5, 0, 0, 0, 0, 0, 2, 1, STATE_DATA }, + { 0, +5, 0, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, -5, 0, 0, 0, 0, 0, 2, 1, STATE_DATA }, + { 0, -5, 0, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 1, 14, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 1, 14, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, 0, 1, 15, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 1, 15, STATE_SIGN }, + { 0, +6, 0, 0, 0, 0, 0, 2, 1, STATE_DATA }, + { 0, +6, 0, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, -6, 0, 0, 0, 0, 0, 2, 1, STATE_DATA }, + { 0, -6, 0, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, +2, 0, 0, 0, 0, 0, 2, 2, STATE_DATA }, + { 0, +2, 0, 0, 0, 0, 0, 2, 2, STATE_SIGN }, + { 0, +2, 0, 0, 0, 0, 0, 2, 3, STATE_DATA }, + { 0, +2, 0, 0, 0, 0, 0, 2, 3, STATE_SIGN }, + { 0, +2, 0, 0, 0, 0, 0, 3, 2, STATE_FOLLOW }, + { 0, +2, 0, 0, 0, 0, 0, 3, 3, STATE_FOLLOW }, + { 0, +2, 0, 0, 0, 0, 0, 4, 1, STATE_DATA }, + { 0, +2, 0, 0, 0, 0, 0, 5, 0, STATE_START }, + { 0, -2, 0, 0, 0, 0, 0, 2, 2, STATE_DATA }, + { 0, -2, 0, 0, 0, 0, 0, 2, 2, STATE_SIGN }, + { 0, -2, 0, 0, 0, 0, 0, 2, 3, STATE_DATA }, + { 0, -2, 0, 0, 0, 0, 0, 2, 3, STATE_SIGN }, + { 0, -2, 0, 0, 0, 0, 0, 3, 2, STATE_FOLLOW }, + { 0, -2, 0, 0, 0, 0, 0, 3, 3, STATE_FOLLOW }, + { 0, -2, 0, 0, 0, 0, 0, 4, 1, STATE_DATA }, + { 0, -2, 0, 0, 0, 0, 0, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 2, 8, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, 0, 2, 9, STATE_FOLLOW }, + { 0, 0, +3, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, 0, -3, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 2, 10, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, 0, 2, 11, STATE_FOLLOW }, + { 0, 0, +4, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, 0, -4, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, 0, +1, 0, 0, 0, 0, 3, 2, STATE_FOLLOW }, + { 0, 0, +1, 0, 0, 0, 0, 3, 3, STATE_FOLLOW }, + { 0, 0, +1, 0, 0, 0, 0, 4, 1, STATE_DATA }, + { 0, 0, +1, 0, 0, 0, 0, 5, 0, STATE_START }, + { 0, 0, -1, 0, 0, 0, 0, 3, 2, STATE_FOLLOW }, + { 0, 0, -1, 0, 0, 0, 0, 3, 3, STATE_FOLLOW }, + { 0, 0, -1, 0, 0, 0, 0, 4, 1, STATE_DATA }, + { 0, 0, -1, 0, 0, 0, 0, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 2, 12, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, 0, 2, 13, STATE_FOLLOW }, + { 0, 0, +5, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, 0, -5, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 2, 14, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, 0, 2, 15, STATE_FOLLOW }, + { 0, 0, +6, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, 0, -6, 0, 0, 0, 0, 3, 0, STATE_START }, + { 0, 0, +2, 0, 0, 0, 0, 3, 2, STATE_FOLLOW }, + { 0, 0, +2, 0, 0, 0, 0, 3, 3, STATE_FOLLOW }, + { 0, 0, +2, 0, 0, 0, 0, 4, 1, STATE_DATA }, + { 0, 0, +2, 0, 0, 0, 0, 5, 0, STATE_START }, + { 0, 0, -2, 0, 0, 0, 0, 3, 2, STATE_FOLLOW }, + { 0, 0, -2, 0, 0, 0, 0, 3, 3, STATE_FOLLOW }, + { 0, 0, -2, 0, 0, 0, 0, 4, 1, STATE_DATA }, + { 0, 0, -2, 0, 0, 0, 0, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 3, 4, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 3, 4, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, 0, 3, 5, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 3, 5, STATE_SIGN }, + { 0, 0, 0, +1, 0, 0, 0, 4, 1, STATE_DATA }, + { 0, 0, 0, +1, 0, 0, 0, 5, 0, STATE_START }, + { 0, 0, 0, -1, 0, 0, 0, 4, 1, STATE_DATA }, + { 0, 0, 0, -1, 0, 0, 0, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 3, 6, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 3, 6, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, 0, 3, 7, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 3, 7, STATE_SIGN }, + { 0, 0, 0, +2, 0, 0, 0, 4, 1, STATE_DATA }, + { 0, 0, 0, +2, 0, 0, 0, 5, 0, STATE_START }, + { 0, 0, 0, -2, 0, 0, 0, 4, 1, STATE_DATA }, + { 0, 0, 0, -2, 0, 0, 0, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 4, 4, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, 0, 4, 5, STATE_FOLLOW }, + { 0, 0, 0, 0, +1, 0, 0, 5, 0, STATE_START }, + { 0, 0, 0, 0, -1, 0, 0, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 4, 6, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, 0, 4, 7, STATE_FOLLOW }, + { 0, 0, 0, 0, +2, 0, 0, 5, 0, STATE_START }, + { 0, 0, 0, 0, -2, 0, 0, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, 0, 5, 2, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 5, 2, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, 0, 5, 3, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 5, 3, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, 0, 6, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, 0, 6, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, 0, 7, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, 0, 8, 0, STATE_START }, + { 0, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 3, +1, 1, 0, STATE_START }, + { 0, 0, 0, 0, 0, 3, -1, 1, 0, STATE_START }, + { +2, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 3, +1, 1, 0, STATE_START }, + { +1, 0, 0, 0, 0, 3, -1, 1, 0, STATE_START }, + { 0, 0, 0, 0, 0, 2, +1, 1, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 2, +1, 1, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 2, +1, 2, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 2, +1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 2, -1, 1, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 2, -1, 1, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 2, -1, 2, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 2, -1, 3, 0, STATE_START }, + { +4, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +5, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 3, +1, 1, 0, STATE_START }, + { +2, 0, 0, 0, 0, 3, -1, 1, 0, STATE_START }, + { +6, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +7, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 3, +1, 1, 0, STATE_START }, + { +3, 0, 0, 0, 0, 3, -1, 1, 0, STATE_START }, + { +1, 0, 0, 0, 0, 2, +1, 1, 2, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 2, +1, 1, 3, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 2, +1, 2, 1, STATE_DATA }, + { +1, 0, 0, 0, 0, 2, +1, 3, 0, STATE_START }, + { +1, 0, 0, 0, 0, 2, -1, 1, 2, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 2, -1, 1, 3, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 2, -1, 2, 1, STATE_DATA }, + { +1, 0, 0, 0, 0, 2, -1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, +1, 1, 4, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, +1, 1, 5, STATE_FOLLOW }, + { 0, +1, 0, 0, 0, 1, +1, 2, 0, STATE_START }, + { 0, -1, 0, 0, 0, 1, +1, 2, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, +1, 1, 6, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, +1, 1, 7, STATE_FOLLOW }, + { 0, +2, 0, 0, 0, 1, +1, 2, 0, STATE_START }, + { 0, -2, 0, 0, 0, 1, +1, 2, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, +1, 2, 2, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, +1, 2, 2, STATE_SIGN }, + { 0, 0, 0, 0, 0, 1, +1, 2, 3, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, +1, 2, 3, STATE_SIGN }, + { 0, 0, 0, 0, 0, 1, +1, 3, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, +1, 3, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, +1, 4, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, +1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, -1, 1, 4, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, -1, 1, 5, STATE_FOLLOW }, + { 0, +1, 0, 0, 0, 1, -1, 2, 0, STATE_START }, + { 0, -1, 0, 0, 0, 1, -1, 2, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, -1, 1, 6, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, -1, 1, 7, STATE_FOLLOW }, + { 0, +2, 0, 0, 0, 1, -1, 2, 0, STATE_START }, + { 0, -2, 0, 0, 0, 1, -1, 2, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, -1, 2, 2, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, -1, 2, 2, STATE_SIGN }, + { 0, 0, 0, 0, 0, 1, -1, 2, 3, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, -1, 2, 3, STATE_SIGN }, + { 0, 0, 0, 0, 0, 1, -1, 3, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, -1, 3, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, -1, 4, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, -1, 5, 0, STATE_START }, + { +8, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +9, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +4, 0, 0, 0, 0, 3, +1, 1, 0, STATE_START }, + { +4, 0, 0, 0, 0, 3, -1, 1, 0, STATE_START }, + { +10, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +11, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +5, 0, 0, 0, 0, 3, +1, 1, 0, STATE_START }, + { +5, 0, 0, 0, 0, 3, -1, 1, 0, STATE_START }, + { +2, 0, 0, 0, 0, 2, +1, 1, 2, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, +1, 1, 3, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, +1, 2, 1, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, +1, 3, 0, STATE_START }, + { +2, 0, 0, 0, 0, 2, -1, 1, 2, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, -1, 1, 3, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, -1, 2, 1, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, -1, 3, 0, STATE_START }, + { +12, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +13, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +6, 0, 0, 0, 0, 3, +1, 1, 0, STATE_START }, + { +6, 0, 0, 0, 0, 3, -1, 1, 0, STATE_START }, + { +14, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +15, 0, 0, 0, 0, 4, +1, 0, 0, STATE_FOLLOW }, + { +7, 0, 0, 0, 0, 3, +1, 1, 0, STATE_START }, + { +7, 0, 0, 0, 0, 3, -1, 1, 0, STATE_START }, + { +3, 0, 0, 0, 0, 2, +1, 1, 2, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, +1, 1, 3, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, +1, 2, 1, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, +1, 3, 0, STATE_START }, + { +3, 0, 0, 0, 0, 2, -1, 1, 2, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, -1, 1, 3, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, -1, 2, 1, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, -1, 3, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, +1, 1, 4, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, +1, 1, 5, STATE_FOLLOW }, + { +1, +1, 0, 0, 0, 1, +1, 2, 0, STATE_START }, + { +1, -1, 0, 0, 0, 1, +1, 2, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, +1, 1, 6, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, +1, 1, 7, STATE_FOLLOW }, + { +1, +2, 0, 0, 0, 1, +1, 2, 0, STATE_START }, + { +1, -2, 0, 0, 0, 1, +1, 2, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, +1, 2, 2, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, +1, 2, 2, STATE_SIGN }, + { +1, 0, 0, 0, 0, 1, +1, 2, 3, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, +1, 2, 3, STATE_SIGN }, + { +1, 0, 0, 0, 0, 1, +1, 3, 2, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, +1, 3, 3, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, +1, 4, 1, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, +1, 5, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, -1, 1, 4, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, -1, 1, 5, STATE_FOLLOW }, + { +1, +1, 0, 0, 0, 1, -1, 2, 0, STATE_START }, + { +1, -1, 0, 0, 0, 1, -1, 2, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, -1, 1, 6, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, -1, 1, 7, STATE_FOLLOW }, + { +1, +2, 0, 0, 0, 1, -1, 2, 0, STATE_START }, + { +1, -2, 0, 0, 0, 1, -1, 2, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, -1, 2, 2, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, -1, 2, 2, STATE_SIGN }, + { +1, 0, 0, 0, 0, 1, -1, 2, 3, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, -1, 2, 3, STATE_SIGN }, + { +1, 0, 0, 0, 0, 1, -1, 3, 2, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, -1, 3, 3, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, -1, 4, 1, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, -1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 1, 8, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 1, 9, STATE_FOLLOW }, + { 0, +3, 0, 0, 0, 0, +1, 2, 0, STATE_START }, + { 0, -3, 0, 0, 0, 0, +1, 2, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 1, 10, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 1, 11, STATE_FOLLOW }, + { 0, +4, 0, 0, 0, 0, +1, 2, 0, STATE_START }, + { 0, -4, 0, 0, 0, 0, +1, 2, 0, STATE_START }, + { 0, +1, 0, 0, 0, 0, +1, 2, 2, STATE_FOLLOW }, + { 0, +1, 0, 0, 0, 0, +1, 2, 3, STATE_FOLLOW }, + { 0, +1, 0, 0, 0, 0, +1, 3, 1, STATE_DATA }, + { 0, +1, 0, 0, 0, 0, +1, 4, 0, STATE_START }, + { 0, -1, 0, 0, 0, 0, +1, 2, 2, STATE_FOLLOW }, + { 0, -1, 0, 0, 0, 0, +1, 2, 3, STATE_FOLLOW }, + { 0, -1, 0, 0, 0, 0, +1, 3, 1, STATE_DATA }, + { 0, -1, 0, 0, 0, 0, +1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 1, 12, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 1, 13, STATE_FOLLOW }, + { 0, +5, 0, 0, 0, 0, +1, 2, 0, STATE_START }, + { 0, -5, 0, 0, 0, 0, +1, 2, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 1, 14, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 1, 15, STATE_FOLLOW }, + { 0, +6, 0, 0, 0, 0, +1, 2, 0, STATE_START }, + { 0, -6, 0, 0, 0, 0, +1, 2, 0, STATE_START }, + { 0, +2, 0, 0, 0, 0, +1, 2, 2, STATE_FOLLOW }, + { 0, +2, 0, 0, 0, 0, +1, 2, 3, STATE_FOLLOW }, + { 0, +2, 0, 0, 0, 0, +1, 3, 1, STATE_DATA }, + { 0, +2, 0, 0, 0, 0, +1, 4, 0, STATE_START }, + { 0, -2, 0, 0, 0, 0, +1, 2, 2, STATE_FOLLOW }, + { 0, -2, 0, 0, 0, 0, +1, 2, 3, STATE_FOLLOW }, + { 0, -2, 0, 0, 0, 0, +1, 3, 1, STATE_DATA }, + { 0, -2, 0, 0, 0, 0, +1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 2, 4, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 2, 4, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, +1, 2, 5, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 2, 5, STATE_SIGN }, + { 0, 0, +1, 0, 0, 0, +1, 3, 1, STATE_DATA }, + { 0, 0, +1, 0, 0, 0, +1, 4, 0, STATE_START }, + { 0, 0, -1, 0, 0, 0, +1, 3, 1, STATE_DATA }, + { 0, 0, -1, 0, 0, 0, +1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 2, 6, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 2, 6, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, +1, 2, 7, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 2, 7, STATE_SIGN }, + { 0, 0, +2, 0, 0, 0, +1, 3, 1, STATE_DATA }, + { 0, 0, +2, 0, 0, 0, +1, 4, 0, STATE_START }, + { 0, 0, -2, 0, 0, 0, +1, 3, 1, STATE_DATA }, + { 0, 0, -2, 0, 0, 0, +1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 3, 4, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 3, 5, STATE_FOLLOW }, + { 0, 0, 0, +1, 0, 0, +1, 4, 0, STATE_START }, + { 0, 0, 0, -1, 0, 0, +1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 3, 6, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 3, 7, STATE_FOLLOW }, + { 0, 0, 0, +2, 0, 0, +1, 4, 0, STATE_START }, + { 0, 0, 0, -2, 0, 0, +1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 4, 2, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 4, 2, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, +1, 4, 3, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 4, 3, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, +1, 5, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 5, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 6, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 7, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 1, 8, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 1, 9, STATE_FOLLOW }, + { 0, +3, 0, 0, 0, 0, -1, 2, 0, STATE_START }, + { 0, -3, 0, 0, 0, 0, -1, 2, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 1, 10, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 1, 11, STATE_FOLLOW }, + { 0, +4, 0, 0, 0, 0, -1, 2, 0, STATE_START }, + { 0, -4, 0, 0, 0, 0, -1, 2, 0, STATE_START }, + { 0, +1, 0, 0, 0, 0, -1, 2, 2, STATE_FOLLOW }, + { 0, +1, 0, 0, 0, 0, -1, 2, 3, STATE_FOLLOW }, + { 0, +1, 0, 0, 0, 0, -1, 3, 1, STATE_DATA }, + { 0, +1, 0, 0, 0, 0, -1, 4, 0, STATE_START }, + { 0, -1, 0, 0, 0, 0, -1, 2, 2, STATE_FOLLOW }, + { 0, -1, 0, 0, 0, 0, -1, 2, 3, STATE_FOLLOW }, + { 0, -1, 0, 0, 0, 0, -1, 3, 1, STATE_DATA }, + { 0, -1, 0, 0, 0, 0, -1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 1, 12, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 1, 13, STATE_FOLLOW }, + { 0, +5, 0, 0, 0, 0, -1, 2, 0, STATE_START }, + { 0, -5, 0, 0, 0, 0, -1, 2, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 1, 14, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 1, 15, STATE_FOLLOW }, + { 0, +6, 0, 0, 0, 0, -1, 2, 0, STATE_START }, + { 0, -6, 0, 0, 0, 0, -1, 2, 0, STATE_START }, + { 0, +2, 0, 0, 0, 0, -1, 2, 2, STATE_FOLLOW }, + { 0, +2, 0, 0, 0, 0, -1, 2, 3, STATE_FOLLOW }, + { 0, +2, 0, 0, 0, 0, -1, 3, 1, STATE_DATA }, + { 0, +2, 0, 0, 0, 0, -1, 4, 0, STATE_START }, + { 0, -2, 0, 0, 0, 0, -1, 2, 2, STATE_FOLLOW }, + { 0, -2, 0, 0, 0, 0, -1, 2, 3, STATE_FOLLOW }, + { 0, -2, 0, 0, 0, 0, -1, 3, 1, STATE_DATA }, + { 0, -2, 0, 0, 0, 0, -1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 2, 4, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 2, 4, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, -1, 2, 5, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 2, 5, STATE_SIGN }, + { 0, 0, +1, 0, 0, 0, -1, 3, 1, STATE_DATA }, + { 0, 0, +1, 0, 0, 0, -1, 4, 0, STATE_START }, + { 0, 0, -1, 0, 0, 0, -1, 3, 1, STATE_DATA }, + { 0, 0, -1, 0, 0, 0, -1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 2, 6, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 2, 6, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, -1, 2, 7, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 2, 7, STATE_SIGN }, + { 0, 0, +2, 0, 0, 0, -1, 3, 1, STATE_DATA }, + { 0, 0, +2, 0, 0, 0, -1, 4, 0, STATE_START }, + { 0, 0, -2, 0, 0, 0, -1, 3, 1, STATE_DATA }, + { 0, 0, -2, 0, 0, 0, -1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 3, 4, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 3, 5, STATE_FOLLOW }, + { 0, 0, 0, +1, 0, 0, -1, 4, 0, STATE_START }, + { 0, 0, 0, -1, 0, 0, -1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 3, 6, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 3, 7, STATE_FOLLOW }, + { 0, 0, 0, +2, 0, 0, -1, 4, 0, STATE_START }, + { 0, 0, 0, -2, 0, 0, -1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 4, 2, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 4, 2, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, -1, 4, 3, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 4, 3, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, -1, 5, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 5, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 6, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 7, 0, STATE_START }, + { 0, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { 0, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +1, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +1, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { 0, 0, 0, 0, 0, 3, +1, 1, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 3, +1, 2, 0, STATE_START }, + { 0, 0, 0, 0, 0, 3, -1, 1, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 3, -1, 2, 0, STATE_START }, + { +2, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +2, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +3, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +3, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +1, 0, 0, 0, 0, 3, +1, 1, 1, STATE_DATA }, + { +1, 0, 0, 0, 0, 3, +1, 2, 0, STATE_START }, + { +1, 0, 0, 0, 0, 3, -1, 1, 1, STATE_DATA }, + { +1, 0, 0, 0, 0, 3, -1, 2, 0, STATE_START }, + { 0, 0, 0, 0, 0, 2, +1, 1, 2, STATE_DATA }, + { 0, 0, 0, 0, 0, 2, +1, 1, 2, STATE_SIGN }, + { 0, 0, 0, 0, 0, 2, +1, 1, 3, STATE_DATA }, + { 0, 0, 0, 0, 0, 2, +1, 1, 3, STATE_SIGN }, + { 0, 0, 0, 0, 0, 2, +1, 2, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 2, +1, 2, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 2, +1, 3, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 2, +1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 2, -1, 1, 2, STATE_DATA }, + { 0, 0, 0, 0, 0, 2, -1, 1, 2, STATE_SIGN }, + { 0, 0, 0, 0, 0, 2, -1, 1, 3, STATE_DATA }, + { 0, 0, 0, 0, 0, 2, -1, 1, 3, STATE_SIGN }, + { 0, 0, 0, 0, 0, 2, -1, 2, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 2, -1, 2, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 2, -1, 3, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 2, -1, 4, 0, STATE_START }, + { +4, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +4, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +5, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +5, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +2, 0, 0, 0, 0, 3, +1, 1, 1, STATE_DATA }, + { +2, 0, 0, 0, 0, 3, +1, 2, 0, STATE_START }, + { +2, 0, 0, 0, 0, 3, -1, 1, 1, STATE_DATA }, + { +2, 0, 0, 0, 0, 3, -1, 2, 0, STATE_START }, + { +6, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +6, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +7, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +7, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +3, 0, 0, 0, 0, 3, +1, 1, 1, STATE_DATA }, + { +3, 0, 0, 0, 0, 3, +1, 2, 0, STATE_START }, + { +3, 0, 0, 0, 0, 3, -1, 1, 1, STATE_DATA }, + { +3, 0, 0, 0, 0, 3, -1, 2, 0, STATE_START }, + { +1, 0, 0, 0, 0, 2, +1, 1, 2, STATE_DATA }, + { +1, 0, 0, 0, 0, 2, +1, 1, 2, STATE_SIGN }, + { +1, 0, 0, 0, 0, 2, +1, 1, 3, STATE_DATA }, + { +1, 0, 0, 0, 0, 2, +1, 1, 3, STATE_SIGN }, + { +1, 0, 0, 0, 0, 2, +1, 2, 2, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 2, +1, 2, 3, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 2, +1, 3, 1, STATE_DATA }, + { +1, 0, 0, 0, 0, 2, +1, 4, 0, STATE_START }, + { +1, 0, 0, 0, 0, 2, -1, 1, 2, STATE_DATA }, + { +1, 0, 0, 0, 0, 2, -1, 1, 2, STATE_SIGN }, + { +1, 0, 0, 0, 0, 2, -1, 1, 3, STATE_DATA }, + { +1, 0, 0, 0, 0, 2, -1, 1, 3, STATE_SIGN }, + { +1, 0, 0, 0, 0, 2, -1, 2, 2, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 2, -1, 2, 3, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 2, -1, 3, 1, STATE_DATA }, + { +1, 0, 0, 0, 0, 2, -1, 4, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, +1, 1, 4, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, +1, 1, 4, STATE_SIGN }, + { 0, 0, 0, 0, 0, 1, +1, 1, 5, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, +1, 1, 5, STATE_SIGN }, + { 0, +1, 0, 0, 0, 1, +1, 2, 1, STATE_DATA }, + { 0, +1, 0, 0, 0, 1, +1, 3, 0, STATE_START }, + { 0, -1, 0, 0, 0, 1, +1, 2, 1, STATE_DATA }, + { 0, -1, 0, 0, 0, 1, +1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, +1, 1, 6, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, +1, 1, 6, STATE_SIGN }, + { 0, 0, 0, 0, 0, 1, +1, 1, 7, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, +1, 1, 7, STATE_SIGN }, + { 0, +2, 0, 0, 0, 1, +1, 2, 1, STATE_DATA }, + { 0, +2, 0, 0, 0, 1, +1, 3, 0, STATE_START }, + { 0, -2, 0, 0, 0, 1, +1, 2, 1, STATE_DATA }, + { 0, -2, 0, 0, 0, 1, +1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, +1, 2, 4, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, +1, 2, 5, STATE_FOLLOW }, + { 0, 0, +1, 0, 0, 1, +1, 3, 0, STATE_START }, + { 0, 0, -1, 0, 0, 1, +1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, +1, 2, 6, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, +1, 2, 7, STATE_FOLLOW }, + { 0, 0, +2, 0, 0, 1, +1, 3, 0, STATE_START }, + { 0, 0, -2, 0, 0, 1, +1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, +1, 3, 2, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, +1, 3, 2, STATE_SIGN }, + { 0, 0, 0, 0, 0, 1, +1, 3, 3, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, +1, 3, 3, STATE_SIGN }, + { 0, 0, 0, 0, 0, 1, +1, 4, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, +1, 4, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, +1, 5, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, +1, 6, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, -1, 1, 4, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, -1, 1, 4, STATE_SIGN }, + { 0, 0, 0, 0, 0, 1, -1, 1, 5, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, -1, 1, 5, STATE_SIGN }, + { 0, +1, 0, 0, 0, 1, -1, 2, 1, STATE_DATA }, + { 0, +1, 0, 0, 0, 1, -1, 3, 0, STATE_START }, + { 0, -1, 0, 0, 0, 1, -1, 2, 1, STATE_DATA }, + { 0, -1, 0, 0, 0, 1, -1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, -1, 1, 6, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, -1, 1, 6, STATE_SIGN }, + { 0, 0, 0, 0, 0, 1, -1, 1, 7, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, -1, 1, 7, STATE_SIGN }, + { 0, +2, 0, 0, 0, 1, -1, 2, 1, STATE_DATA }, + { 0, +2, 0, 0, 0, 1, -1, 3, 0, STATE_START }, + { 0, -2, 0, 0, 0, 1, -1, 2, 1, STATE_DATA }, + { 0, -2, 0, 0, 0, 1, -1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, -1, 2, 4, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, -1, 2, 5, STATE_FOLLOW }, + { 0, 0, +1, 0, 0, 1, -1, 3, 0, STATE_START }, + { 0, 0, -1, 0, 0, 1, -1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, -1, 2, 6, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, -1, 2, 7, STATE_FOLLOW }, + { 0, 0, +2, 0, 0, 1, -1, 3, 0, STATE_START }, + { 0, 0, -2, 0, 0, 1, -1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 1, -1, 3, 2, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, -1, 3, 2, STATE_SIGN }, + { 0, 0, 0, 0, 0, 1, -1, 3, 3, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, -1, 3, 3, STATE_SIGN }, + { 0, 0, 0, 0, 0, 1, -1, 4, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, -1, 4, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 1, -1, 5, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 1, -1, 6, 0, STATE_START }, + { +8, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +8, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +9, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +9, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +4, 0, 0, 0, 0, 3, +1, 1, 1, STATE_DATA }, + { +4, 0, 0, 0, 0, 3, +1, 2, 0, STATE_START }, + { +4, 0, 0, 0, 0, 3, -1, 1, 1, STATE_DATA }, + { +4, 0, 0, 0, 0, 3, -1, 2, 0, STATE_START }, + { +10, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +10, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +11, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +11, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +5, 0, 0, 0, 0, 3, +1, 1, 1, STATE_DATA }, + { +5, 0, 0, 0, 0, 3, +1, 2, 0, STATE_START }, + { +5, 0, 0, 0, 0, 3, -1, 1, 1, STATE_DATA }, + { +5, 0, 0, 0, 0, 3, -1, 2, 0, STATE_START }, + { +2, 0, 0, 0, 0, 2, +1, 1, 2, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, +1, 1, 2, STATE_SIGN }, + { +2, 0, 0, 0, 0, 2, +1, 1, 3, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, +1, 1, 3, STATE_SIGN }, + { +2, 0, 0, 0, 0, 2, +1, 2, 2, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, +1, 2, 3, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, +1, 3, 1, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, +1, 4, 0, STATE_START }, + { +2, 0, 0, 0, 0, 2, -1, 1, 2, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, -1, 1, 2, STATE_SIGN }, + { +2, 0, 0, 0, 0, 2, -1, 1, 3, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, -1, 1, 3, STATE_SIGN }, + { +2, 0, 0, 0, 0, 2, -1, 2, 2, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, -1, 2, 3, STATE_FOLLOW }, + { +2, 0, 0, 0, 0, 2, -1, 3, 1, STATE_DATA }, + { +2, 0, 0, 0, 0, 2, -1, 4, 0, STATE_START }, + { +12, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +12, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +13, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +13, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +6, 0, 0, 0, 0, 3, +1, 1, 1, STATE_DATA }, + { +6, 0, 0, 0, 0, 3, +1, 2, 0, STATE_START }, + { +6, 0, 0, 0, 0, 3, -1, 1, 1, STATE_DATA }, + { +6, 0, 0, 0, 0, 3, -1, 2, 0, STATE_START }, + { +14, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +14, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +15, 0, 0, 0, 0, 4, +1, 0, 0, STATE_DATA }, + { +15, 0, 0, 0, 0, 4, +1, 0, 0, STATE_SIGN }, + { +7, 0, 0, 0, 0, 3, +1, 1, 1, STATE_DATA }, + { +7, 0, 0, 0, 0, 3, +1, 2, 0, STATE_START }, + { +7, 0, 0, 0, 0, 3, -1, 1, 1, STATE_DATA }, + { +7, 0, 0, 0, 0, 3, -1, 2, 0, STATE_START }, + { +3, 0, 0, 0, 0, 2, +1, 1, 2, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, +1, 1, 2, STATE_SIGN }, + { +3, 0, 0, 0, 0, 2, +1, 1, 3, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, +1, 1, 3, STATE_SIGN }, + { +3, 0, 0, 0, 0, 2, +1, 2, 2, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, +1, 2, 3, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, +1, 3, 1, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, +1, 4, 0, STATE_START }, + { +3, 0, 0, 0, 0, 2, -1, 1, 2, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, -1, 1, 2, STATE_SIGN }, + { +3, 0, 0, 0, 0, 2, -1, 1, 3, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, -1, 1, 3, STATE_SIGN }, + { +3, 0, 0, 0, 0, 2, -1, 2, 2, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, -1, 2, 3, STATE_FOLLOW }, + { +3, 0, 0, 0, 0, 2, -1, 3, 1, STATE_DATA }, + { +3, 0, 0, 0, 0, 2, -1, 4, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, +1, 1, 4, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, +1, 1, 4, STATE_SIGN }, + { +1, 0, 0, 0, 0, 1, +1, 1, 5, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, +1, 1, 5, STATE_SIGN }, + { +1, +1, 0, 0, 0, 1, +1, 2, 1, STATE_DATA }, + { +1, +1, 0, 0, 0, 1, +1, 3, 0, STATE_START }, + { +1, -1, 0, 0, 0, 1, +1, 2, 1, STATE_DATA }, + { +1, -1, 0, 0, 0, 1, +1, 3, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, +1, 1, 6, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, +1, 1, 6, STATE_SIGN }, + { +1, 0, 0, 0, 0, 1, +1, 1, 7, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, +1, 1, 7, STATE_SIGN }, + { +1, +2, 0, 0, 0, 1, +1, 2, 1, STATE_DATA }, + { +1, +2, 0, 0, 0, 1, +1, 3, 0, STATE_START }, + { +1, -2, 0, 0, 0, 1, +1, 2, 1, STATE_DATA }, + { +1, -2, 0, 0, 0, 1, +1, 3, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, +1, 2, 4, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, +1, 2, 5, STATE_FOLLOW }, + { +1, 0, +1, 0, 0, 1, +1, 3, 0, STATE_START }, + { +1, 0, -1, 0, 0, 1, +1, 3, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, +1, 2, 6, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, +1, 2, 7, STATE_FOLLOW }, + { +1, 0, +2, 0, 0, 1, +1, 3, 0, STATE_START }, + { +1, 0, -2, 0, 0, 1, +1, 3, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, +1, 3, 2, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, +1, 3, 2, STATE_SIGN }, + { +1, 0, 0, 0, 0, 1, +1, 3, 3, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, +1, 3, 3, STATE_SIGN }, + { +1, 0, 0, 0, 0, 1, +1, 4, 2, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, +1, 4, 3, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, +1, 5, 1, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, +1, 6, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, -1, 1, 4, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, -1, 1, 4, STATE_SIGN }, + { +1, 0, 0, 0, 0, 1, -1, 1, 5, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, -1, 1, 5, STATE_SIGN }, + { +1, +1, 0, 0, 0, 1, -1, 2, 1, STATE_DATA }, + { +1, +1, 0, 0, 0, 1, -1, 3, 0, STATE_START }, + { +1, -1, 0, 0, 0, 1, -1, 2, 1, STATE_DATA }, + { +1, -1, 0, 0, 0, 1, -1, 3, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, -1, 1, 6, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, -1, 1, 6, STATE_SIGN }, + { +1, 0, 0, 0, 0, 1, -1, 1, 7, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, -1, 1, 7, STATE_SIGN }, + { +1, +2, 0, 0, 0, 1, -1, 2, 1, STATE_DATA }, + { +1, +2, 0, 0, 0, 1, -1, 3, 0, STATE_START }, + { +1, -2, 0, 0, 0, 1, -1, 2, 1, STATE_DATA }, + { +1, -2, 0, 0, 0, 1, -1, 3, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, -1, 2, 4, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, -1, 2, 5, STATE_FOLLOW }, + { +1, 0, +1, 0, 0, 1, -1, 3, 0, STATE_START }, + { +1, 0, -1, 0, 0, 1, -1, 3, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, -1, 2, 6, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, -1, 2, 7, STATE_FOLLOW }, + { +1, 0, +2, 0, 0, 1, -1, 3, 0, STATE_START }, + { +1, 0, -2, 0, 0, 1, -1, 3, 0, STATE_START }, + { +1, 0, 0, 0, 0, 1, -1, 3, 2, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, -1, 3, 2, STATE_SIGN }, + { +1, 0, 0, 0, 0, 1, -1, 3, 3, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, -1, 3, 3, STATE_SIGN }, + { +1, 0, 0, 0, 0, 1, -1, 4, 2, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, -1, 4, 3, STATE_FOLLOW }, + { +1, 0, 0, 0, 0, 1, -1, 5, 1, STATE_DATA }, + { +1, 0, 0, 0, 0, 1, -1, 6, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 1, 8, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 1, 8, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, +1, 1, 9, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 1, 9, STATE_SIGN }, + { 0, +3, 0, 0, 0, 0, +1, 2, 1, STATE_DATA }, + { 0, +3, 0, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, -3, 0, 0, 0, 0, +1, 2, 1, STATE_DATA }, + { 0, -3, 0, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 1, 10, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 1, 10, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, +1, 1, 11, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 1, 11, STATE_SIGN }, + { 0, +4, 0, 0, 0, 0, +1, 2, 1, STATE_DATA }, + { 0, +4, 0, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, -4, 0, 0, 0, 0, +1, 2, 1, STATE_DATA }, + { 0, -4, 0, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, +1, 0, 0, 0, 0, +1, 2, 2, STATE_DATA }, + { 0, +1, 0, 0, 0, 0, +1, 2, 2, STATE_SIGN }, + { 0, +1, 0, 0, 0, 0, +1, 2, 3, STATE_DATA }, + { 0, +1, 0, 0, 0, 0, +1, 2, 3, STATE_SIGN }, + { 0, +1, 0, 0, 0, 0, +1, 3, 2, STATE_FOLLOW }, + { 0, +1, 0, 0, 0, 0, +1, 3, 3, STATE_FOLLOW }, + { 0, +1, 0, 0, 0, 0, +1, 4, 1, STATE_DATA }, + { 0, +1, 0, 0, 0, 0, +1, 5, 0, STATE_START }, + { 0, -1, 0, 0, 0, 0, +1, 2, 2, STATE_DATA }, + { 0, -1, 0, 0, 0, 0, +1, 2, 2, STATE_SIGN }, + { 0, -1, 0, 0, 0, 0, +1, 2, 3, STATE_DATA }, + { 0, -1, 0, 0, 0, 0, +1, 2, 3, STATE_SIGN }, + { 0, -1, 0, 0, 0, 0, +1, 3, 2, STATE_FOLLOW }, + { 0, -1, 0, 0, 0, 0, +1, 3, 3, STATE_FOLLOW }, + { 0, -1, 0, 0, 0, 0, +1, 4, 1, STATE_DATA }, + { 0, -1, 0, 0, 0, 0, +1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 1, 12, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 1, 12, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, +1, 1, 13, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 1, 13, STATE_SIGN }, + { 0, +5, 0, 0, 0, 0, +1, 2, 1, STATE_DATA }, + { 0, +5, 0, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, -5, 0, 0, 0, 0, +1, 2, 1, STATE_DATA }, + { 0, -5, 0, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 1, 14, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 1, 14, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, +1, 1, 15, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 1, 15, STATE_SIGN }, + { 0, +6, 0, 0, 0, 0, +1, 2, 1, STATE_DATA }, + { 0, +6, 0, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, -6, 0, 0, 0, 0, +1, 2, 1, STATE_DATA }, + { 0, -6, 0, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, +2, 0, 0, 0, 0, +1, 2, 2, STATE_DATA }, + { 0, +2, 0, 0, 0, 0, +1, 2, 2, STATE_SIGN }, + { 0, +2, 0, 0, 0, 0, +1, 2, 3, STATE_DATA }, + { 0, +2, 0, 0, 0, 0, +1, 2, 3, STATE_SIGN }, + { 0, +2, 0, 0, 0, 0, +1, 3, 2, STATE_FOLLOW }, + { 0, +2, 0, 0, 0, 0, +1, 3, 3, STATE_FOLLOW }, + { 0, +2, 0, 0, 0, 0, +1, 4, 1, STATE_DATA }, + { 0, +2, 0, 0, 0, 0, +1, 5, 0, STATE_START }, + { 0, -2, 0, 0, 0, 0, +1, 2, 2, STATE_DATA }, + { 0, -2, 0, 0, 0, 0, +1, 2, 2, STATE_SIGN }, + { 0, -2, 0, 0, 0, 0, +1, 2, 3, STATE_DATA }, + { 0, -2, 0, 0, 0, 0, +1, 2, 3, STATE_SIGN }, + { 0, -2, 0, 0, 0, 0, +1, 3, 2, STATE_FOLLOW }, + { 0, -2, 0, 0, 0, 0, +1, 3, 3, STATE_FOLLOW }, + { 0, -2, 0, 0, 0, 0, +1, 4, 1, STATE_DATA }, + { 0, -2, 0, 0, 0, 0, +1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 2, 8, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 2, 9, STATE_FOLLOW }, + { 0, 0, +3, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, 0, -3, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 2, 10, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 2, 11, STATE_FOLLOW }, + { 0, 0, +4, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, 0, -4, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, 0, +1, 0, 0, 0, +1, 3, 2, STATE_FOLLOW }, + { 0, 0, +1, 0, 0, 0, +1, 3, 3, STATE_FOLLOW }, + { 0, 0, +1, 0, 0, 0, +1, 4, 1, STATE_DATA }, + { 0, 0, +1, 0, 0, 0, +1, 5, 0, STATE_START }, + { 0, 0, -1, 0, 0, 0, +1, 3, 2, STATE_FOLLOW }, + { 0, 0, -1, 0, 0, 0, +1, 3, 3, STATE_FOLLOW }, + { 0, 0, -1, 0, 0, 0, +1, 4, 1, STATE_DATA }, + { 0, 0, -1, 0, 0, 0, +1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 2, 12, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 2, 13, STATE_FOLLOW }, + { 0, 0, +5, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, 0, -5, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 2, 14, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 2, 15, STATE_FOLLOW }, + { 0, 0, +6, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, 0, -6, 0, 0, 0, +1, 3, 0, STATE_START }, + { 0, 0, +2, 0, 0, 0, +1, 3, 2, STATE_FOLLOW }, + { 0, 0, +2, 0, 0, 0, +1, 3, 3, STATE_FOLLOW }, + { 0, 0, +2, 0, 0, 0, +1, 4, 1, STATE_DATA }, + { 0, 0, +2, 0, 0, 0, +1, 5, 0, STATE_START }, + { 0, 0, -2, 0, 0, 0, +1, 3, 2, STATE_FOLLOW }, + { 0, 0, -2, 0, 0, 0, +1, 3, 3, STATE_FOLLOW }, + { 0, 0, -2, 0, 0, 0, +1, 4, 1, STATE_DATA }, + { 0, 0, -2, 0, 0, 0, +1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 3, 4, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 3, 4, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, +1, 3, 5, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 3, 5, STATE_SIGN }, + { 0, 0, 0, +1, 0, 0, +1, 4, 1, STATE_DATA }, + { 0, 0, 0, +1, 0, 0, +1, 5, 0, STATE_START }, + { 0, 0, 0, -1, 0, 0, +1, 4, 1, STATE_DATA }, + { 0, 0, 0, -1, 0, 0, +1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 3, 6, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 3, 6, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, +1, 3, 7, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 3, 7, STATE_SIGN }, + { 0, 0, 0, +2, 0, 0, +1, 4, 1, STATE_DATA }, + { 0, 0, 0, +2, 0, 0, +1, 5, 0, STATE_START }, + { 0, 0, 0, -2, 0, 0, +1, 4, 1, STATE_DATA }, + { 0, 0, 0, -2, 0, 0, +1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 4, 4, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 4, 5, STATE_FOLLOW }, + { 0, 0, 0, 0, +1, 0, +1, 5, 0, STATE_START }, + { 0, 0, 0, 0, -1, 0, +1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 4, 6, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 4, 7, STATE_FOLLOW }, + { 0, 0, 0, 0, +2, 0, +1, 5, 0, STATE_START }, + { 0, 0, 0, 0, -2, 0, +1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, +1, 5, 2, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 5, 2, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, +1, 5, 3, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 5, 3, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, +1, 6, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 6, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, +1, 7, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, +1, 8, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 1, 8, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 1, 8, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, -1, 1, 9, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 1, 9, STATE_SIGN }, + { 0, +3, 0, 0, 0, 0, -1, 2, 1, STATE_DATA }, + { 0, +3, 0, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, -3, 0, 0, 0, 0, -1, 2, 1, STATE_DATA }, + { 0, -3, 0, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 1, 10, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 1, 10, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, -1, 1, 11, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 1, 11, STATE_SIGN }, + { 0, +4, 0, 0, 0, 0, -1, 2, 1, STATE_DATA }, + { 0, +4, 0, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, -4, 0, 0, 0, 0, -1, 2, 1, STATE_DATA }, + { 0, -4, 0, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, +1, 0, 0, 0, 0, -1, 2, 2, STATE_DATA }, + { 0, +1, 0, 0, 0, 0, -1, 2, 2, STATE_SIGN }, + { 0, +1, 0, 0, 0, 0, -1, 2, 3, STATE_DATA }, + { 0, +1, 0, 0, 0, 0, -1, 2, 3, STATE_SIGN }, + { 0, +1, 0, 0, 0, 0, -1, 3, 2, STATE_FOLLOW }, + { 0, +1, 0, 0, 0, 0, -1, 3, 3, STATE_FOLLOW }, + { 0, +1, 0, 0, 0, 0, -1, 4, 1, STATE_DATA }, + { 0, +1, 0, 0, 0, 0, -1, 5, 0, STATE_START }, + { 0, -1, 0, 0, 0, 0, -1, 2, 2, STATE_DATA }, + { 0, -1, 0, 0, 0, 0, -1, 2, 2, STATE_SIGN }, + { 0, -1, 0, 0, 0, 0, -1, 2, 3, STATE_DATA }, + { 0, -1, 0, 0, 0, 0, -1, 2, 3, STATE_SIGN }, + { 0, -1, 0, 0, 0, 0, -1, 3, 2, STATE_FOLLOW }, + { 0, -1, 0, 0, 0, 0, -1, 3, 3, STATE_FOLLOW }, + { 0, -1, 0, 0, 0, 0, -1, 4, 1, STATE_DATA }, + { 0, -1, 0, 0, 0, 0, -1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 1, 12, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 1, 12, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, -1, 1, 13, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 1, 13, STATE_SIGN }, + { 0, +5, 0, 0, 0, 0, -1, 2, 1, STATE_DATA }, + { 0, +5, 0, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, -5, 0, 0, 0, 0, -1, 2, 1, STATE_DATA }, + { 0, -5, 0, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 1, 14, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 1, 14, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, -1, 1, 15, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 1, 15, STATE_SIGN }, + { 0, +6, 0, 0, 0, 0, -1, 2, 1, STATE_DATA }, + { 0, +6, 0, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, -6, 0, 0, 0, 0, -1, 2, 1, STATE_DATA }, + { 0, -6, 0, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, +2, 0, 0, 0, 0, -1, 2, 2, STATE_DATA }, + { 0, +2, 0, 0, 0, 0, -1, 2, 2, STATE_SIGN }, + { 0, +2, 0, 0, 0, 0, -1, 2, 3, STATE_DATA }, + { 0, +2, 0, 0, 0, 0, -1, 2, 3, STATE_SIGN }, + { 0, +2, 0, 0, 0, 0, -1, 3, 2, STATE_FOLLOW }, + { 0, +2, 0, 0, 0, 0, -1, 3, 3, STATE_FOLLOW }, + { 0, +2, 0, 0, 0, 0, -1, 4, 1, STATE_DATA }, + { 0, +2, 0, 0, 0, 0, -1, 5, 0, STATE_START }, + { 0, -2, 0, 0, 0, 0, -1, 2, 2, STATE_DATA }, + { 0, -2, 0, 0, 0, 0, -1, 2, 2, STATE_SIGN }, + { 0, -2, 0, 0, 0, 0, -1, 2, 3, STATE_DATA }, + { 0, -2, 0, 0, 0, 0, -1, 2, 3, STATE_SIGN }, + { 0, -2, 0, 0, 0, 0, -1, 3, 2, STATE_FOLLOW }, + { 0, -2, 0, 0, 0, 0, -1, 3, 3, STATE_FOLLOW }, + { 0, -2, 0, 0, 0, 0, -1, 4, 1, STATE_DATA }, + { 0, -2, 0, 0, 0, 0, -1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 2, 8, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 2, 9, STATE_FOLLOW }, + { 0, 0, +3, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, 0, -3, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 2, 10, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 2, 11, STATE_FOLLOW }, + { 0, 0, +4, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, 0, -4, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, 0, +1, 0, 0, 0, -1, 3, 2, STATE_FOLLOW }, + { 0, 0, +1, 0, 0, 0, -1, 3, 3, STATE_FOLLOW }, + { 0, 0, +1, 0, 0, 0, -1, 4, 1, STATE_DATA }, + { 0, 0, +1, 0, 0, 0, -1, 5, 0, STATE_START }, + { 0, 0, -1, 0, 0, 0, -1, 3, 2, STATE_FOLLOW }, + { 0, 0, -1, 0, 0, 0, -1, 3, 3, STATE_FOLLOW }, + { 0, 0, -1, 0, 0, 0, -1, 4, 1, STATE_DATA }, + { 0, 0, -1, 0, 0, 0, -1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 2, 12, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 2, 13, STATE_FOLLOW }, + { 0, 0, +5, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, 0, -5, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 2, 14, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 2, 15, STATE_FOLLOW }, + { 0, 0, +6, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, 0, -6, 0, 0, 0, -1, 3, 0, STATE_START }, + { 0, 0, +2, 0, 0, 0, -1, 3, 2, STATE_FOLLOW }, + { 0, 0, +2, 0, 0, 0, -1, 3, 3, STATE_FOLLOW }, + { 0, 0, +2, 0, 0, 0, -1, 4, 1, STATE_DATA }, + { 0, 0, +2, 0, 0, 0, -1, 5, 0, STATE_START }, + { 0, 0, -2, 0, 0, 0, -1, 3, 2, STATE_FOLLOW }, + { 0, 0, -2, 0, 0, 0, -1, 3, 3, STATE_FOLLOW }, + { 0, 0, -2, 0, 0, 0, -1, 4, 1, STATE_DATA }, + { 0, 0, -2, 0, 0, 0, -1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 3, 4, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 3, 4, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, -1, 3, 5, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 3, 5, STATE_SIGN }, + { 0, 0, 0, +1, 0, 0, -1, 4, 1, STATE_DATA }, + { 0, 0, 0, +1, 0, 0, -1, 5, 0, STATE_START }, + { 0, 0, 0, -1, 0, 0, -1, 4, 1, STATE_DATA }, + { 0, 0, 0, -1, 0, 0, -1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 3, 6, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 3, 6, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, -1, 3, 7, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 3, 7, STATE_SIGN }, + { 0, 0, 0, +2, 0, 0, -1, 4, 1, STATE_DATA }, + { 0, 0, 0, +2, 0, 0, -1, 5, 0, STATE_START }, + { 0, 0, 0, -2, 0, 0, -1, 4, 1, STATE_DATA }, + { 0, 0, 0, -2, 0, 0, -1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 4, 4, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 4, 5, STATE_FOLLOW }, + { 0, 0, 0, 0, +1, 0, -1, 5, 0, STATE_START }, + { 0, 0, 0, 0, -1, 0, -1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 4, 6, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 4, 7, STATE_FOLLOW }, + { 0, 0, 0, 0, +2, 0, -1, 5, 0, STATE_START }, + { 0, 0, 0, 0, -2, 0, -1, 5, 0, STATE_START }, + { 0, 0, 0, 0, 0, 0, -1, 5, 2, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 5, 2, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, -1, 5, 3, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 5, 3, STATE_SIGN }, + { 0, 0, 0, 0, 0, 0, -1, 6, 2, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 6, 3, STATE_FOLLOW }, + { 0, 0, 0, 0, 0, 0, -1, 7, 1, STATE_DATA }, + { 0, 0, 0, 0, 0, 0, -1, 8, 0, STATE_START }, +}; + +#define PROCESS_VALS \ + do { \ + val <<= lut.val0_bits; \ + val |= lut.val0; \ + dst[0] = (val - 1) * lut.sign; \ + dst[1] = lut.val1; \ + dst[2] = lut.val2; \ + dst[3] = lut.val3; \ + dst[4] = lut.val4; \ + dst[5] = 0; \ + dst[6] = 0; \ + dst[7] = 0; \ + if (lut.num) \ + val = lut.val; \ + dst += lut.num; \ + if (dst >= last) \ + return coeffs; \ + lut = dirac_golomb_lut[lut.state + *buf++]; \ + } while (0) -/* Searches for golomb codes in a residue */ -static inline void search_for_golomb(DiracGolombLUT *l, residual r, int bits) +int ff_dirac_golomb_read_16bit(const uint8_t *buf, int bytes, + uint8_t *_dst, int coeffs) { - int r_count = RSIZE_BITS - 1; - int bits_start, bits_tot = bits, need_sign = 0; - -#define READ_BIT(N) (((N) >> (N ## _count--)) & 1) - - while (1) { - int32_t coef = 1; - bits_start = (RSIZE_BITS - 1) - r_count; - - while (1) { - if (!bits--) - goto leftover; - if (READ_BIT(r)) - break; - - coef <<= 1; - - if (!bits--) - goto leftover; - coef |= READ_BIT(r); - } - - l->ready[l->ready_num] = coef - 1; - if (l->ready[l->ready_num]) { - if (!bits--) { - need_sign = 1; - goto leftover; - } - l->ready[l->ready_num] *= READ_BIT(r) ? -1 : +1; - } - l->ready_num++; - - if (!bits) - return; - } - - leftover: - l->leftover = r << bits_start; - l->leftover_bits = bits_tot - bits_start; - l->need_s = need_sign; -} + LUTState lut = dirac_golomb_lut[*buf++]; + int16_t *dst = (int16_t *)_dst, *last = dst + coeffs; + uint16_t val = 0; -/* Parity LUTs - even and odd bit end positions */ -static void generate_parity_lut(DiracGolombLUT *lut, int even) -{ - int idx; - for (idx = 0; idx < LUT_SIZE; idx++) { - DiracGolombLUT *l = &lut[idx]; - int symbol_end_loc = -1; - uint32_t code; - int i; - - INIT_RESIDUE(res); - SET_RESIDUE(res, idx, LUT_BITS); - - for (i = 0; i < LUT_BITS; i++) { - const int cond = even ? (i & 1) : !(i & 1); - if (((res >> (RSIZE_BITS - i - 1)) & 1) && cond) { - symbol_end_loc = i + 2; - break; - } - } - - if (symbol_end_loc < 0 || symbol_end_loc > LUT_BITS) { - l->preamble = 0; - l->preamble_bits = 0; - l->leftover_bits = LUT_BITS; - l->leftover = CONVERT_TO_RESIDUE(idx, l->leftover_bits); - if (even) - l->need_s = idx & 1; - continue; - } - - /* Gets bits 0 through to (symbol_end_loc - 1) inclusive */ - code = idx >> ((LUT_BITS - 1) - (symbol_end_loc - 1)); - code &= ((1 << LUT_BITS) - 1) >> (LUT_BITS - symbol_end_loc); - l->preamble_bits = symbol_end_loc; - l->preamble = CONVERT_TO_RESIDUE(code, l->preamble_bits); - l->sign = ((l->preamble >> (RSIZE_BITS - l->preamble_bits)) & 1) ? -1 : +1; + for (int i = 1; i < bytes; i++) + PROCESS_VALS; - search_for_golomb(l, res << symbol_end_loc, LUT_BITS - symbol_end_loc); - } -} + /* Reader needs to be flushed */ + PROCESS_VALS; -/* Reset (off == 0) and needs-one-more-bit (off == 1) LUTs */ -static void generate_offset_lut(DiracGolombLUT *lut, int off) -{ - int idx; - for (idx = 0; idx < LUT_SIZE; idx++) { - DiracGolombLUT *l = &lut[idx]; - - INIT_RESIDUE(res); - SET_RESIDUE(res, idx, LUT_BITS); - - l->preamble_bits = off; - if (off) { - l->preamble = CONVERT_TO_RESIDUE(res >> (RSIZE_BITS - off), off); - l->sign = ((l->preamble >> (RSIZE_BITS - l->preamble_bits)) & 1) ? -1 : +1; - } else { - l->preamble = 0; - l->sign = 1; - } + /* Still short of coeffs - try to guess and at least output what we have */ + if (lut.state != STATE_START) + *dst++ = -((lut.state != STATE_SIGN ? (val << 1) | 1 : val) - 1); - search_for_golomb(l, res << off, LUT_BITS - off); - } + return coeffs - (int)(last - dst); } -av_cold int ff_dirac_golomb_reader_init(DiracGolombLUT **lut_ctx) +int ff_dirac_golomb_read_32bit(const uint8_t *buf, int bytes, + uint8_t *_dst, int coeffs) { - DiracGolombLUT *lut; + LUTState lut = dirac_golomb_lut[*buf++]; + int32_t *dst = (int32_t *)_dst, *last = dst + coeffs; + uint32_t val = 0; - if (!(lut = av_calloc(4*LUT_SIZE, sizeof(DiracGolombLUT)))) - return AVERROR(ENOMEM); + for (int i = 1; i < bytes; i++) + PROCESS_VALS; - generate_parity_lut(&lut[0*LUT_SIZE], 0); - generate_parity_lut(&lut[1*LUT_SIZE], 1); - generate_offset_lut(&lut[2*LUT_SIZE], 0); - generate_offset_lut(&lut[3*LUT_SIZE], 1); + /* Reader needs to be flushed */ + PROCESS_VALS; - *lut_ctx = lut; + /* Still short of coeffs - try to guess and at least output what we have */ + if (lut.state != STATE_START) + *dst++ = -((lut.state != STATE_SIGN ? (val << 1) | 1 : val) - 1); - return 0; -} - -av_cold void ff_dirac_golomb_reader_end(DiracGolombLUT **lut_ctx) -{ - av_freep(lut_ctx); + return coeffs - (int)(last - dst); } diff -Nru ffmpeg-4.2.2/libavcodec/dirac_vlc.h ffmpeg-4.4/libavcodec/dirac_vlc.h --- ffmpeg-4.2.2/libavcodec/dirac_vlc.h 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dirac_vlc.h 2020-07-11 10:39:30.000000000 +0000 @@ -1,7 +1,4 @@ /* - * Copyright (C) 2016 Open Broadcast Systems Ltd. - * Author 2016 Rostislav Pehlivanov - * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -24,28 +21,9 @@ #include "libavutil/avutil.h" -/* Can be 32 bits wide for some performance gain on some machines, but it will - * incorrectly decode very long coefficients (usually only 1 or 2 per frame) */ -typedef uint64_t residual; - -#define LUT_BITS 8 - -/* Exactly 64 bytes */ -typedef struct DiracGolombLUT { - residual preamble, leftover; - int32_t ready[LUT_BITS]; - int32_t preamble_bits, leftover_bits, ready_num; - int8_t need_s, sign; -} DiracGolombLUT; - -av_cold int ff_dirac_golomb_reader_init(DiracGolombLUT **lut_ctx); - -int ff_dirac_golomb_read_32bit(DiracGolombLUT *lut_ctx, const uint8_t *buf, - int bytes, uint8_t *dst, int coeffs); - -int ff_dirac_golomb_read_16bit(DiracGolombLUT *lut_ctx, const uint8_t *buf, - int bytes, uint8_t *_dst, int coeffs); - -av_cold void ff_dirac_golomb_reader_end(DiracGolombLUT **lut_ctx); +int ff_dirac_golomb_read_16bit(const uint8_t *buf, int bytes, + uint8_t *_dst, int coeffs); +int ff_dirac_golomb_read_32bit(const uint8_t *buf, int bytes, + uint8_t *_dst, int coeffs); #endif /* AVCODEC_DIRAC_VLC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/dnxhddata.c ffmpeg-4.4/libavcodec/dnxhddata.c --- ffmpeg-4.2.2/libavcodec/dnxhddata.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dnxhddata.c 2021-04-08 21:28:39.000000000 +0000 @@ -932,7 +932,7 @@ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, }; -const CIDEntry ff_dnxhd_cid_table[] = { +static const CIDEntry dnxhd_cid_table[] = { { 1235, 1920, 1080, 917504, 917504, 0, 6, 10, 4, dnxhd_1235_luma_weight, dnxhd_1235_chroma_weight, @@ -1075,31 +1075,31 @@ { 0 }, { 5888, 255} }, }; -int ff_dnxhd_get_cid_table(int cid) +const CIDEntry *ff_dnxhd_get_cid_table(int cid) { - int i; - for (i = 0; i < FF_ARRAY_ELEMS(ff_dnxhd_cid_table); i++) - if (ff_dnxhd_cid_table[i].cid == cid) - return i; - return -1; + for (int i = 0; i < FF_ARRAY_ELEMS(dnxhd_cid_table); i++) + if (dnxhd_cid_table[i].cid == cid) + return &dnxhd_cid_table[i]; + return NULL; } int avpriv_dnxhd_get_frame_size(int cid) { - int i = ff_dnxhd_get_cid_table(cid); - if (i<0) - return i; - return ff_dnxhd_cid_table[i].frame_size; + const CIDEntry *entry = ff_dnxhd_get_cid_table(cid); + if (!entry) + return -1; + return entry->frame_size; } int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h) { - int result, i = ff_dnxhd_get_cid_table(cid); + const CIDEntry *entry = ff_dnxhd_get_cid_table(cid); + int result; - if (i < 0) - return i; + if (!entry) + return -1; - result = ((h + 15) / 16) * ((w + 15) / 16) * (int64_t)ff_dnxhd_cid_table[i].packet_scale.num / ff_dnxhd_cid_table[i].packet_scale.den; + result = ((h + 15) / 16) * ((w + 15) / 16) * (int64_t)entry->packet_scale.num / entry->packet_scale.den; result = (result + 2048) / 4096 * 4096; return FFMAX(result, 8192); @@ -1107,10 +1107,10 @@ int avpriv_dnxhd_get_interlaced(int cid) { - int i = ff_dnxhd_get_cid_table(cid); - if (i < 0) - return i; - return ff_dnxhd_cid_table[i].flags & DNXHD_INTERLACED ? 1 : 0; + 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) @@ -1140,8 +1140,8 @@ if (!mbs) return 0; - for (i = 0; i < FF_ARRAY_ELEMS(ff_dnxhd_cid_table); i++) { - const CIDEntry *cid = &ff_dnxhd_cid_table[i]; + for (i = 0; i < FF_ARRAY_ELEMS(dnxhd_cid_table); i++) { + const CIDEntry *cid = &dnxhd_cid_table[i]; int interlaced = cid->flags & DNXHD_INTERLACED ? 1 : 0; if (cid->width == avctx->width && cid->height == avctx->height && interlaced == !!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) && @@ -1163,8 +1163,8 @@ void ff_dnxhd_print_profiles(AVCodecContext *avctx, int loglevel) { int i, j; - for (i = 0; i < FF_ARRAY_ELEMS(ff_dnxhd_cid_table); i++) { - const CIDEntry *cid = &ff_dnxhd_cid_table[i]; + for (i = 0; i < FF_ARRAY_ELEMS(dnxhd_cid_table); i++) { + const CIDEntry *cid = &dnxhd_cid_table[i]; for (j = 0; j < FF_ARRAY_ELEMS(cid->bit_rates); j++) { if (!cid->bit_rates[j]) break; diff -Nru ffmpeg-4.2.2/libavcodec/dnxhddata.h ffmpeg-4.4/libavcodec/dnxhddata.h --- ffmpeg-4.2.2/libavcodec/dnxhddata.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dnxhddata.h 2021-04-08 21:28:39.000000000 +0000 @@ -58,9 +58,7 @@ AVRational packet_scale; } CIDEntry; -extern const CIDEntry ff_dnxhd_cid_table[]; - -int ff_dnxhd_get_cid_table(int cid); +const CIDEntry *ff_dnxhd_get_cid_table(int cid); int ff_dnxhd_find_cid(AVCodecContext *avctx, int bit_depth); void ff_dnxhd_print_profiles(AVCodecContext *avctx, int loglevel); diff -Nru ffmpeg-4.2.2/libavcodec/dnxhddec.c ffmpeg-4.4/libavcodec/dnxhddec.c --- ffmpeg-4.2.2/libavcodec/dnxhddec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dnxhddec.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,7 +25,8 @@ */ #include "libavutil/imgutils.h" -#include "libavutil/timer.h" +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "blockdsp.h" #define UNCHECKED_BITSTREAM_READER 1 @@ -112,18 +113,19 @@ static int dnxhd_init_vlc(DNXHDContext *ctx, uint32_t cid, int bitdepth) { if (cid != ctx->cid) { - int index; + const CIDEntry *cid_table = ff_dnxhd_get_cid_table(cid); - if ((index = ff_dnxhd_get_cid_table(cid)) < 0) { + if (!cid_table) { av_log(ctx->avctx, AV_LOG_ERROR, "unsupported cid %"PRIu32"\n", cid); return AVERROR(ENOSYS); } - if (ff_dnxhd_cid_table[index].bit_depth != bitdepth && - ff_dnxhd_cid_table[index].bit_depth != DNXHD_VARIABLE) { - av_log(ctx->avctx, AV_LOG_ERROR, "bit depth mismatches %d %d\n", ff_dnxhd_cid_table[index].bit_depth, bitdepth); + if (cid_table->bit_depth != bitdepth && + cid_table->bit_depth != DNXHD_VARIABLE) { + av_log(ctx->avctx, AV_LOG_ERROR, "bit depth mismatches %d %d\n", + cid_table->bit_depth, bitdepth); return AVERROR_INVALIDDATA; } - ctx->cid_table = &ff_dnxhd_cid_table[index]; + ctx->cid_table = cid_table; av_log(ctx->avctx, AV_LOG_VERBOSE, "Profile cid %"PRIu32".\n", cid); ff_free_vlc(&ctx->ac_vlc); @@ -145,21 +147,6 @@ return 0; } -static av_cold int dnxhd_decode_init_thread_copy(AVCodecContext *avctx) -{ - DNXHDContext *ctx = avctx->priv_data; - - ctx->avctx = avctx; - // make sure VLC tables will be loaded when cid is parsed - ctx->cid = -1; - - ctx->rows = av_mallocz_array(avctx->thread_count, sizeof(RowContext)); - if (!ctx->rows) - return AVERROR(ENOMEM); - - return 0; -} - static int dnxhd_get_profile(int cid) { switch(cid) { @@ -235,7 +222,14 @@ av_log(ctx->avctx, AV_LOG_WARNING, "Adaptive MB interlace flag in an unsupported profile.\n"); - ctx->act = buf[0x2C] & 7; + switch ((buf[0x2C] >> 1) & 3) { + case 0: frame->colorspace = AVCOL_SPC_BT709; break; + case 1: frame->colorspace = AVCOL_SPC_BT2020_NCL; break; + case 2: frame->colorspace = AVCOL_SPC_BT2020_CL; break; + case 3: frame->colorspace = AVCOL_SPC_UNSPECIFIED; break; + } + + ctx->act = buf[0x2C] & 1; if (ctx->act && ctx->cid_table->cid != 1256 && ctx->cid_table->cid != 1270) av_log(ctx->avctx, AV_LOG_WARNING, "Adaptive color transform in an unsupported profile.\n"); @@ -600,13 +594,11 @@ return ret; } for (x = 0; x < ctx->mb_width; x++) { - //START_TIMER; int ret = dnxhd_decode_macroblock(ctx, row, data, x, rownb); if (ret < 0) { row->errors++; return ret; } - //STOP_TIMER("decode macroblock"); } return 0; @@ -736,6 +728,5 @@ .decode = dnxhd_decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(dnxhd_decode_init_thread_copy), .profiles = NULL_IF_CONFIG_SMALL(ff_dnxhd_profiles), }; diff -Nru ffmpeg-4.2.2/libavcodec/dnxhdenc.c ffmpeg-4.4/libavcodec/dnxhdenc.c --- ffmpeg-4.2.2/libavcodec/dnxhdenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dnxhdenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,8 +25,8 @@ #include "libavutil/attributes.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" -#include "libavutil/timer.h" #include "avcodec.h" #include "blockdsp.h" @@ -34,6 +34,7 @@ #include "internal.h" #include "mpegvideo.h" #include "pixblockdsp.h" +#include "packet_internal.h" #include "profiles.h" #include "dnxhdenc.h" @@ -207,20 +208,16 @@ int i, j, level, run; int max_level = 1 << (ctx->bit_depth + 2); - FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->orig_vlc_codes, - max_level, 4 * sizeof(*ctx->orig_vlc_codes), fail); - FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->orig_vlc_bits, - max_level, 4 * sizeof(*ctx->orig_vlc_bits), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->run_codes, - 63 * 2, fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->run_bits, - 63, fail); - + if (!FF_ALLOCZ_TYPED_ARRAY(ctx->orig_vlc_codes, max_level * 4) || + !FF_ALLOCZ_TYPED_ARRAY(ctx->orig_vlc_bits, max_level * 4) || + !(ctx->run_codes = av_mallocz(63 * 2)) || + !(ctx->run_bits = av_mallocz(63))) + return AVERROR(ENOMEM); ctx->vlc_codes = ctx->orig_vlc_codes + max_level * 2; ctx->vlc_bits = ctx->orig_vlc_bits + max_level * 2; for (level = -max_level; level < max_level; level++) { for (run = 0; run < 2; run++) { - int index = (level << 1) | run; + int index = level * (1 << 1) | run; int sign, offset = 0, alevel = level; MASK_ABS(sign, alevel); @@ -259,8 +256,6 @@ ctx->run_bits[run] = ctx->cid_table->run_bits[i]; } return 0; -fail: - return AVERROR(ENOMEM); } static av_cold int dnxhd_init_qmat(DNXHDEncContext *ctx, int lbias, int cbias) @@ -271,16 +266,11 @@ const uint8_t *luma_weight_table = ctx->cid_table->luma_weight; const uint8_t *chroma_weight_table = ctx->cid_table->chroma_weight; - FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->qmatrix_l, - (ctx->m.avctx->qmax + 1), 64 * sizeof(int), fail); - FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->qmatrix_c, - (ctx->m.avctx->qmax + 1), 64 * sizeof(int), fail); - FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->qmatrix_l16, - (ctx->m.avctx->qmax + 1), 64 * 2 * sizeof(uint16_t), - fail); - FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->qmatrix_c16, - (ctx->m.avctx->qmax + 1), 64 * 2 * sizeof(uint16_t), - fail); + if (!FF_ALLOCZ_TYPED_ARRAY(ctx->qmatrix_l, ctx->m.avctx->qmax + 1) || + !FF_ALLOCZ_TYPED_ARRAY(ctx->qmatrix_c, ctx->m.avctx->qmax + 1) || + !FF_ALLOCZ_TYPED_ARRAY(ctx->qmatrix_l16, ctx->m.avctx->qmax + 1) || + !FF_ALLOCZ_TYPED_ARRAY(ctx->qmatrix_c16, ctx->m.avctx->qmax + 1)) + return AVERROR(ENOMEM); if (ctx->bit_depth == 8) { for (i = 1; i < 64; i++) { @@ -339,33 +329,29 @@ ctx->m.q_intra_matrix = ctx->qmatrix_l; return 0; -fail: - return AVERROR(ENOMEM); } static av_cold int dnxhd_init_rc(DNXHDEncContext *ctx) { - FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->mb_rc, (ctx->m.avctx->qmax + 1), - ctx->m.mb_num * sizeof(RCEntry), fail); + if (!FF_ALLOCZ_TYPED_ARRAY(ctx->mb_rc, (ctx->m.avctx->qmax + 1) * ctx->m.mb_num)) + return AVERROR(ENOMEM); + if (ctx->m.avctx->mb_decision != FF_MB_DECISION_RD) { - FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->mb_cmp, - ctx->m.mb_num, sizeof(RCCMPEntry), fail); - FF_ALLOCZ_ARRAY_OR_GOTO(ctx->m.avctx, ctx->mb_cmp_tmp, - ctx->m.mb_num, sizeof(RCCMPEntry), fail); + if (!FF_ALLOCZ_TYPED_ARRAY(ctx->mb_cmp, ctx->m.mb_num) || + !FF_ALLOCZ_TYPED_ARRAY(ctx->mb_cmp_tmp, ctx->m.mb_num)) + return AVERROR(ENOMEM); } ctx->frame_bits = (ctx->coding_unit_size - ctx->data_offset - 4 - ctx->min_padding) * 8; ctx->qscale = 1; ctx->lambda = 2 << LAMBDA_FRAC_BITS; // qscale 2 return 0; -fail: - return AVERROR(ENOMEM); } static av_cold int dnxhd_encode_init(AVCodecContext *avctx) { DNXHDEncContext *ctx = avctx->priv_data; - int i, index, ret; + int i, ret; switch (avctx->pix_fmt) { case AV_PIX_FMT_YUV422P: @@ -425,10 +411,8 @@ return AVERROR(EINVAL); } - index = ff_dnxhd_get_cid_table(ctx->cid); - av_assert0(index >= 0); - - ctx->cid_table = &ff_dnxhd_cid_table[index]; + ctx->cid_table = ff_dnxhd_get_cid_table(ctx->cid); + av_assert0(ctx->cid_table); ctx->m.avctx = avctx; ctx->m.mb_intra = 1; @@ -510,15 +494,11 @@ if ((ret = dnxhd_init_rc(ctx)) < 0) return ret; - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->slice_size, - ctx->m.mb_height * sizeof(uint32_t), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->slice_offs, - ctx->m.mb_height * sizeof(uint32_t), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_bits, - ctx->m.mb_num * sizeof(uint16_t), fail); - FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_qscale, - ctx->m.mb_num * sizeof(uint8_t), fail); - + if (!FF_ALLOCZ_TYPED_ARRAY(ctx->slice_size, ctx->m.mb_height) || + !FF_ALLOCZ_TYPED_ARRAY(ctx->slice_offs, ctx->m.mb_height) || + !FF_ALLOCZ_TYPED_ARRAY(ctx->mb_bits, ctx->m.mb_num) || + !FF_ALLOCZ_TYPED_ARRAY(ctx->mb_qscale, ctx->m.mb_num)) + return AVERROR(ENOMEM); #if FF_API_CODED_FRAME FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->key_frame = 1; @@ -542,13 +522,13 @@ if (avctx->active_thread_type == FF_THREAD_SLICE) { for (i = 1; i < avctx->thread_count; i++) { ctx->thread[i] = av_malloc(sizeof(DNXHDEncContext)); + if (!ctx->thread[i]) + return AVERROR(ENOMEM); memcpy(ctx->thread[i], ctx, sizeof(DNXHDEncContext)); } } return 0; -fail: // for FF_ALLOCZ_OR_GOTO - return AVERROR(ENOMEM); } static int dnxhd_write_header(AVCodecContext *avctx, uint8_t *buf) @@ -616,7 +596,7 @@ slevel = block[j]; if (slevel) { int run_level = i - last_non_zero - 1; - int rlevel = (slevel << 1) | !!run_level; + int rlevel = slevel * (1 << 1) | !!run_level; put_bits(&ctx->m.pb, ctx->vlc_bits[rlevel], ctx->vlc_codes[rlevel]); if (run_level) put_bits(&ctx->m.pb, ctx->run_bits[run_level], @@ -696,7 +676,7 @@ level = block[j]; if (level) { int run_level = i - last_non_zero - 1; - bits += ctx->vlc_bits[(level << 1) | + bits += ctx->vlc_bits[level * (1 << 1) | !!run_level] + ctx->run_bits[run_level]; last_non_zero = i; } @@ -931,9 +911,8 @@ int last_index = ctx->m.dct_quantize(&ctx->m, block, ctx->is_444 ? (((i >> 1) % 3) < 1 ? 0 : 4): 4 & (2*i), qscale, &overflow); - // START_TIMER; + dnxhd_encode_block(ctx, block, last_index, n); - // STOP_TIMER("encode_block"); } } if (put_bits_count(&ctx->m.pb) & 31) @@ -1396,7 +1375,7 @@ .init = dnxhd_encode_init, .encode2 = dnxhd_encode_picture, .close = dnxhd_encode_end, - .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV422P, diff -Nru ffmpeg-4.2.2/libavcodec/dnxhdenc.h ffmpeg-4.4/libavcodec/dnxhdenc.h --- ffmpeg-4.2.2/libavcodec/dnxhdenc.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dnxhdenc.h 2021-04-08 21:28:39.000000000 +0000 @@ -28,6 +28,8 @@ #include "config.h" +#include "libavutil/mem_internal.h" + #include "mpegvideo.h" #include "dnxhddata.h" diff -Nru ffmpeg-4.2.2/libavcodec/dolby_e.c ffmpeg-4.4/libavcodec/dolby_e.c --- ffmpeg-4.2.2/libavcodec/dolby_e.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dolby_e.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,13 +21,586 @@ #include "libavutil/float_dsp.h" #include "libavutil/thread.h" #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "internal.h" #include "get_bits.h" -#include "put_bits.h" #include "dolby_e.h" +#include "kbdwin.h" #include "fft.h" +#define MAX_SEGMENTS 2 + +#define MAX_GROUPS 8 +#define MAX_EXPONENTS 304 +#define MAX_MANTISSAS 1024 + +#define MAX_MSTR_EXP 2 +#define MAX_BIAS_EXP 50 + +typedef struct DBEGroup { + uint8_t nb_exponent; + uint8_t nb_bias_exp[MAX_MSTR_EXP]; + uint16_t exp_ofs; + uint16_t mnt_ofs; + const uint8_t *nb_mantissa; + uint8_t imdct_idx; + uint8_t imdct_phs; + uint16_t win_len; + uint16_t dst_ofs; + uint16_t win_ofs; + uint16_t src_ofs; +} DBEGroup; + +typedef struct DBEChannel { + int gr_code; + int bw_code; + + int nb_groups; + int nb_mstr_exp; + DBEGroup groups[MAX_GROUPS]; + + int exp_strategy[MAX_GROUPS]; + int exponents[MAX_EXPONENTS]; + int bap[MAX_EXPONENTS]; + int idx[MAX_EXPONENTS]; + + DECLARE_ALIGNED(32, float, mantissas)[MAX_MANTISSAS]; +} DBEChannel; + +typedef struct DBEDecodeContext { + AVCodecContext *avctx; + DBEContext dectx; + + DBEChannel channels[MAX_SEGMENTS][MAX_CHANNELS]; + + DECLARE_ALIGNED(32, float, history)[MAX_CHANNELS][256]; + + FFTContext imdct[3]; + AVFloatDSPContext *fdsp; +} DBEDecodeContext; + +static const int8_t lfe_channel_tab[MAX_PROG_CONF + 1] = { + 5, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 5 +}; + +static const uint8_t ch_reorder_4[4] = { 0, 2, 1, 3 }; +static const uint8_t ch_reorder_6[6] = { 0, 2, 4, 1, 3, 5 }; +static const uint8_t ch_reorder_8[8] = { 0, 2, 6, 4, 1, 3, 7, 5 }; +static const uint8_t ch_reorder_n[8] = { 0, 2, 4, 6, 1, 3, 5, 7 }; + + +static const uint8_t nb_groups_tab[4] = { 1, 8, 7, 1 }; + +static const uint8_t nb_mstr_exp_tab[4] = { 2, 2, 2, 1 }; + +static const uint8_t nb_mantissa_38[38] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, + 7, 8, 9, 10, 11, 12, +}; + +static const uint8_t nb_mantissa_44[44] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 7, 7, + 8, 9, 10, 11, 12, 13, 15, 16, 18, 20, 22, 25, +}; + +static const uint8_t nb_mantissa_50[50] = { + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, + 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 9, 10, 12, 13, 14, 16, + 18, 19, 22, 24, 27, 29, 32, 36, 40, 44, 49, 54, 60, 66, 74, 82, + 90, 100, +}; + +static const uint8_t imdct_bits_tab[3] = { 8, 9, 11 }; + +static const DBEGroup grp_tab_0[1] = { + { 50, { 27, 23 }, 0, 0, nb_mantissa_50, 2, 0, 1152, 0, 1408, 0 }, +}; + +static const DBEGroup grp_tab_1[8] = { + { 38, { 12, 26 }, 0, 0, nb_mantissa_38, 0, 0, 192, 0, 256, 0 }, + { 38, { 12, 26 }, 38, 128, nb_mantissa_38, 0, 1, 256, 64, 448, 0 }, + { 38, { 12, 26 }, 76, 256, nb_mantissa_38, 0, 1, 256, 192, 704, 0 }, + { 38, { 12, 26 }, 114, 384, nb_mantissa_38, 0, 1, 256, 320, 0, 0 }, + { 38, { 12, 26 }, 152, 512, nb_mantissa_38, 0, 1, 256, 448, 0, 0 }, + { 38, { 12, 26 }, 190, 640, nb_mantissa_38, 0, 1, 256, 576, 0, 0 }, + { 38, { 12, 26 }, 228, 768, nb_mantissa_38, 0, 1, 256, 704, 0, 0 }, + { 38, { 12, 26 }, 266, 896, nb_mantissa_38, 0, 1, 256, 832, 0, 0 }, +}; + +static const DBEGroup grp_tab_2[7] = { + { 38, { 12, 26 }, 0, 0, nb_mantissa_38, 0, 0, 192, 0, 256, 0 }, + { 38, { 12, 26 }, 38, 128, nb_mantissa_38, 0, 1, 256, 64, 448, 0 }, + { 38, { 12, 26 }, 76, 256, nb_mantissa_38, 0, 1, 256, 192, 704, 0 }, + { 38, { 12, 26 }, 114, 384, nb_mantissa_38, 0, 1, 256, 320, 0, 0 }, + { 38, { 12, 26 }, 152, 512, nb_mantissa_38, 0, 1, 256, 448, 0, 0 }, + { 38, { 12, 26 }, 190, 640, nb_mantissa_38, 0, 1, 256, 576, 0, 0 }, + { 44, { 19, 25 }, 228, 768, nb_mantissa_44, 1, 1, 448, 704, 960, 64 }, +}; + +static const DBEGroup grp_tab_3[1] = { + { 21, { 21 }, 0, 0, nb_mantissa_50, 2, 0, 1152, 0, 1408, 0 }, +}; + +static const DBEGroup grp_tab_4[1] = { + { 50, { 27, 23 }, 0, 0, nb_mantissa_50, 2, 2, 1152, 0, 1408, 896 }, +}; + +static const DBEGroup grp_tab_5[8] = { + { 38, { 12, 26 }, 0, 0, nb_mantissa_38, 0, 1, 256, 64, 0, 0 }, + { 38, { 12, 26 }, 38, 128, nb_mantissa_38, 0, 1, 256, 192, 0, 0 }, + { 38, { 12, 26 }, 76, 256, nb_mantissa_38, 0, 1, 256, 320, 0, 0 }, + { 38, { 12, 26 }, 114, 384, nb_mantissa_38, 0, 1, 256, 448, 0, 0 }, + { 38, { 12, 26 }, 152, 512, nb_mantissa_38, 0, 1, 256, 576, 0, 0 }, + { 38, { 12, 26 }, 190, 640, nb_mantissa_38, 0, 1, 256, 704, 3008, 0 }, + { 38, { 12, 26 }, 228, 768, nb_mantissa_38, 0, 1, 256, 832, 2752, 0 }, + { 38, { 12, 26 }, 266, 896, nb_mantissa_38, 0, 2, 192, 960, 2560, 64 }, +}; + +static const DBEGroup grp_tab_6[7] = { + { 44, { 19, 25 }, 0, 0, nb_mantissa_44, 1, 1, 448, 0, 3264, 0 }, + { 38, { 12, 26 }, 44, 256, nb_mantissa_38, 0, 1, 256, 320, 0, 0 }, + { 38, { 12, 26 }, 82, 384, nb_mantissa_38, 0, 1, 256, 448, 0, 0 }, + { 38, { 12, 26 }, 120, 512, nb_mantissa_38, 0, 1, 256, 576, 0, 0 }, + { 38, { 12, 26 }, 158, 640, nb_mantissa_38, 0, 1, 256, 704, 3008, 0 }, + { 38, { 12, 26 }, 196, 768, nb_mantissa_38, 0, 1, 256, 832, 2752, 0 }, + { 38, { 12, 26 }, 234, 896, nb_mantissa_38, 0, 2, 192, 960, 2560, 64 }, +}; + +static const DBEGroup grp_tab_7[1] = { + { 21, { 21 }, 0, 0, nb_mantissa_50, 2, 2, 1152, 0, 1408, 896 }, +}; + +static const DBEGroup *const frm_ofs_tab[2][4] = { + { grp_tab_0, grp_tab_1, grp_tab_2, grp_tab_3 }, + { grp_tab_4, grp_tab_5, grp_tab_6, grp_tab_7 } +}; + +static const uint8_t mantissa_size1[16][4] = { + { 0, 0, 0, 0 }, { 2, 1, 1, 1 }, { 3, 2, 1, 1 }, { 4, 3, 2, 1 }, + { 5, 4, 3, 2 }, { 6, 5, 4, 3 }, { 7, 6, 5, 4 }, { 8, 7, 6, 5 }, + { 9, 8, 7, 6 }, { 10, 9, 8, 7 }, { 11, 10, 9, 8 }, { 12, 11, 10, 9 }, + { 13, 12, 11, 10 }, { 14, 13, 12, 11 }, { 15, 14, 13, 12 }, { 16, 15, 14, 13 }, +}; + +static const uint8_t mantissa_size2[16][4] = { + { 0, 0, 0, 0 }, { 2, 1, 2, 2 }, { 3, 2, 3, 3 }, { 4, 3, 4, 4 }, + { 5, 4, 5, 5 }, { 6, 5, 6, 6 }, { 7, 6, 7, 7 }, { 8, 7, 8, 8 }, + { 9, 8, 9, 9 }, { 10, 9, 10, 10 }, { 11, 10, 11, 11 }, { 12, 11, 12, 12 }, + { 13, 12, 13, 13 }, { 14, 13, 14, 14 }, { 15, 14, 15, 15 }, { 16, 15, 16, 16 }, +}; + +static const float start_window[192] = { + 0.00161569379826, 0.00185748233347, 0.00198562758548, 0.00207834078104, + 0.00215717748523, 0.00223067096393, 0.00230299213147, 0.00237651215396, + 0.00245275561606, 0.00253281402069, 0.00261754673613, 0.00270768786168, + 0.00280390761895, 0.00290684998656, 0.00301715751161, 0.00313548872798, + 0.00326253122934, 0.00339901215995, 0.00354570716636, 0.00370344845023, + 0.00387313232586, 0.00405572653911, 0.00425227750970, 0.00446391759265, + 0.00469187240551, 0.00493746822816, 0.00520213944619, 0.00548743597507, + 0.00579503056737, 0.00612672586953, 0.00648446105606, 0.00687031782873, + 0.00728652552677, 0.00773546505205, 0.00821967127415, 0.00874183354619, + 0.00930479393832, 0.00991154278653, 0.01056521116692, 0.01126905994567, + 0.01202646513050, 0.01284089936559, 0.01371590957417, 0.01465509096066, + 0.01566205783408, 0.01674041199523, 0.01789370972358, 0.01912542867865, + 0.02043893626265, 0.02183746113793, 0.02332406961796, 0.02490164852364, + 0.02657289580178, 0.02834031974193, 0.03020624702903, 0.03217283918354, + 0.03424211623810, 0.03641598586180, 0.03869627565015, 0.04108476601498, + 0.04358322107390, 0.04619341515939, 0.04891715301882, 0.05175628239149, + + 0.05471237327267, 0.05778734733755, 0.06098291402413, 0.06430101352084, + 0.06774345212186, 0.07131188644726, 0.07500780649199, 0.07883251748595, + 0.08278712056651, 0.08687249228061, 0.09108926295730, 0.09543779401074, + 0.09991815425851, 0.10453009536427, 0.10927302653894, 0.11414598865987, + 0.11914762799220, 0.12427616972097, 0.12952939152560, 0.13490459744934, + 0.14039859233595, 0.14600765712201, 0.15172752528722, 0.15755336077528, + 0.16347973770491, 0.16950062219342, 0.17560935661442, 0.18179864660619, + 0.18806055113821, 0.19438647593012, 0.20076717050010, 0.20719272909882, + 0.21365259576030, 0.22013557367283, 0.22662983904194, 0.23312295958328, + 0.23960191774666, 0.24605313873388, 0.25246252333253, 0.25881548554631, + 0.26509699495987, 0.27129162373316, 0.27738359807707, 0.28335685401987, + 0.28919509723179, 0.29488186663467, 0.30040060148455, 0.30573471157819, + 0.31086765019993, 0.31578298939317, 0.32046449711227, 0.32489621578468, + 0.32906254179156, 0.33294830535654, 0.33653885031840, 0.33982011325336, + 0.34277870140679, 0.34540196889300, 0.34767809062480, 0.34959613344194, + 0.35114612391958, 0.35231911235422, 0.35310723244504, 0.35350375621308, + + 0.35350314372945, 0.35310108725579, 0.35229454943591, 0.35108179521634, + 0.34946241721522, 0.34743735430290, 0.34500890320420, 0.34218072298001, + 0.33895783229541, 0.33534659943168, 0.33135472505060, 0.32699121776996, + 0.32226636266000, 0.31719168282019, 0.31177989424432, 0.30604485422875, + 0.30000150362379, 0.29366580327088, 0.28705466500775, 0.28018587766131, + 0.27307802848095, 0.26575042049535, 0.25822298630189, 0.25051619882000, + 0.24265097955783, 0.23464860495522, 0.22653061137548, 0.21831869932335, + 0.21003463746705, 0.20170016703857, 0.19333690717811, 0.18496626177620, + 0.17660932835062, 0.16828680947474, 0.16001892724986, 0.15182534128597, + 0.14372507062477, 0.13573642000364, 0.12787691082233, 0.12016321713317, + 0.11261110693234, 0.10523538898282, 0.09804986534955, 0.09106728977263, + 0.08429933194438, 0.07775654768810, 0.07144835495683, 0.06538301547324, + 0.05956762170687, 0.05400808871425, 0.04870915012107, 0.04367435714993, + 0.03890607899172, 0.03440550179663, 0.03017262174627, 0.02620622428513, + 0.02250383492507, 0.01906161305732, 0.01587412848221, 0.01293388032354, + 0.01023019677288, 0.00774641320626, 0.00545109736891, 0.00325868651263, +}; + +static const float short_window2[192] = { + 0.00018861094606, 0.00033433010202, 0.00050309624485, 0.00070306161748, + 0.00093995174533, 0.00121913067128, 0.00154606505568, 0.00192647806126, + 0.00236641248692, 0.00287225985240, 0.00345077377440, 0.00410907465023, + 0.00485464855241, 0.00569534163219, 0.00663935063508, 0.00769520981249, + 0.00887177436246, 0.01017820046395, 0.01162392194150, 0.01321862359335, + 0.01497221122468, 0.01689477844427, 0.01899657030441, 0.02128794388846, + 0.02377932597692, 0.02648116795039, 0.02940389811590, 0.03255787167130, + 0.03595331854986, 0.03960028941437, 0.04350860009563, 0.04768777479454, + 0.05214698838949, 0.05689500821121, 0.06194013566525, 0.06729014809766, + 0.07295224131210, 0.07893297315602, 0.08523820859989, 0.09187306673620, + 0.09884187012422, 0.10614809690222, 0.11379433608064, 0.12178224641797, + 0.13011251926531, 0.13878484574660, 0.14779788861830, 0.15714925912610, + 0.16683549914631, 0.17685206886673, 0.18719334022589, 0.19785259629099, + 0.20882203671372, 0.22009278936030, 0.23165492816694, 0.24349749722585, + 0.25560854105961, 0.26797514099368, 0.28058345748882, 0.29341877824732, + 0.30646557185942, 0.31970754671026, 0.33312771482295, 0.34670846027024, + + 0.36043161174692, 0.37427851885723, 0.38823013163645, 0.40226708279486, + 0.41636977214436, 0.43051845264462, 0.44469331748632, 0.45887458761470, + 0.47304259908636, 0.48717788964798, 0.50126128392546, 0.51527397661778, + 0.52919761310050, 0.54301436685998, 0.55670701320069, 0.57025899869448, + 0.58365450587230, 0.59687851269542, 0.60991684638414, 0.62275623122793, + 0.63538433005035, 0.64778977905593, 0.65996221584264, 0.67189230042379, + 0.68357172916486, 0.69499324160511, 0.70615062019861, 0.71703868307548, + 0.72765326998919, 0.73799122168099, 0.74805035295521, 0.75782941981995, + 0.76732808110520, 0.77654685502339, 0.78548707118622, 0.79415081863423, + 0.80254089047207, 0.81066072573188, 0.81851434910893, 0.82610630922734, + 0.83344161609862, 0.84052567843230, 0.84736424144524, 0.85396332579459, + 0.86032916822973, 0.86646816451999, 0.87238681516918, 0.87809167437532, + 0.88358930263537, 0.88888622333073, 0.89398888356256, 0.89890361943564, + 0.90363662591861, 0.90819393133744, 0.91258137648979, 0.91680459830070, + 0.92086901787718, 0.92477983276087, 0.92854201312583, 0.93216030163834, + 0.93563921662343, 0.93898305819384, 0.94219591693690, 0.94528168477979, + + 0.94823843319821, 0.95106834367330, 0.95377776558539, 0.95636718335775, + 0.95883679961479, 0.96118650212341, 0.96341583179195, 0.96552395212906, + 0.96750962060547, 0.96937116231768, 0.97110644638309, 0.97271286544154, + 0.97418731862798, 0.97552619834964, 0.97672538116257, 0.97778022299974, + 0.97868555895586, 0.97943570778357, 0.98002448120255, 0.98044519806866, + 0.98069070339493, 0.98075339216123, 0.98062523779637, 0.98029782516478, + 0.97976238784222, 0.97900984942031, 0.97803086854002, 0.97681588731895, + 0.97535518280755, 0.97363892108474, 0.97165721358452, 0.96940017523145, + 0.96685798395452, 0.96402094114589, 0.96087953263194, 0.95742448973047, + 0.95364684997699, 0.94953801711660, 0.94508981997396, 0.94029456983253, + 0.93514511597504, 0.92963489905951, 0.92375800202883, 0.91750919827624, + 0.91088399681406, 0.90387868421832, 0.89649036314692, 0.88871698725397, + 0.88055739234735, 0.87201132366062, 0.86307945913336, 0.85376342861693, + 0.84406582894455, 0.83399023482637, 0.82354120554757, 0.81272428745995, + 0.80154601230457, 0.79001389138101, 0.77813640562199, 0.76592299164227, + 0.75338402384395, 0.74053079267526, 0.72737547915460, 0.71393112578527, +}; + +static const float short_window3[64] = { + 0.00326887936450, 0.00550242900936, 0.00786846643791, 0.01045683453520, + 0.01330402120132, 0.01643221072863, 0.01985798040609, 0.02359509464766, + 0.02765559221954, 0.03205025893128, 0.03678884369614, 0.04188015679495, + 0.04733210987781, 0.05315172583924, 0.05934513287609, 0.06591755045290, + 0.07287327156378, 0.08021564389822, 0.08794705152307, 0.09606889811179, + 0.10458159240070, 0.11348453632940, 0.12277611617809, 0.13245369691511, + 0.14251361989876, 0.15295120402567, 0.16376075037904, 0.17493555039885, + 0.18646789757072, 0.19834910260891, 0.21056951208995, 0.22311853047787, + 0.23598464546683, 0.24915545655419, 0.26261770674500, 0.27635731727778, + 0.29035942525136, 0.30460842402318, 0.31908800624032, 0.33378120935681, + 0.34867046348260, 0.36373764140285, 0.37896411059909, 0.39433078709788, + 0.40981819096657, 0.42540650327031, 0.44107562429959, 0.45680523287270, + 0.47257484651351, 0.48836388230077, 0.50415171818214, 0.51991775454258, + 0.53564147581496, 0.55130251191887, 0.56688069931047, 0.58235614142007, + 0.59770926827271, 0.61292089506118, 0.62797227945823, 0.64284517745255, + 0.65752189749349, 0.67198535273209, 0.68621911114984, 0.70020744337099, +}; + +static const uint8_t dc_code_tab[5] = { 0, 0, 0, 1, 1 }; + +static const uint8_t ht_code_tab[5] = { 0, 0, 1, 2, 2 }; + +static const uint8_t band_ofs_tab[3][4] = { + { 12, 8, 4, 0 }, { 14, 10, 6, 0 }, { 12, 8, 4, 0 } +}; + +static const uint8_t band_low_tab[3] = { 9, 17, 24 }; + +static const uint16_t fast_gain_tab[8] = { + 128, 256, 384, 512, 640, 768, 896, 1024 +}; + +static const uint16_t slow_decay_tab[2][2] = { { 27, -1 }, { 32, 21 } }; + +static const uint16_t misc_decay_tab[3][2][2] = { + { { 354, -1 }, { 425, 425 } }, + { { 266, -1 }, { 320, -1 } }, + { { 213, -1 }, { 256, -1 } } +}; + +static const uint16_t fast_decay_tab[3][2][2][50] = { + {{{ + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, + }, { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + }}, {{ + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, + }, { + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + }}}, {{{ + 266, 266, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, + }, { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + }}, {{ + 319, 319, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, + }, { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + }}}, {{{ + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + }, { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }}, {{ + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + }, { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }}} +}; + +static const uint16_t fast_gain_adj_tab[3][2][62] = { + {{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 4, 7, 11, 16, 29, 44, 59, + 76, 94, 116, 142, 179, 221, 252, 285, 312, 334, + }, { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 5, 8, 10, 15, 28, 42, 57, 75, 93, + 115, 140, 177, 219, 247, 280, 308, 330, 427, 533, + }}, {{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 5, 8, 12, 21, 35, 51, 69, 89, + 111, 138, 176, 220, 251, 284, 312, 334, + }, { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 5, 8, 11, 18, 33, 49, 65, 84, 106, 132, + 168, 214, 245, 279, 308, 329, 427, 533, + }}, {{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 4, 7, 10, 17, + 31, 47, 65, 84, 107, 134, 171, 215, 250, 283, + 312, 334, + }, { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 6, 9, 13, 27, 43, + 60, 79, 100, 126, 160, 207, 242, 276, 307, 329, + 427, 533, + }} +}; + +static const uint16_t slow_gain_tab[3][2][50] = { + {{ + 3072, 3072, 3072, 3072, 3072, 3072, 1063, 1063, 1063, 1063, + 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, + }, { + 3072, 3072, 3072, 3072, 3072, 3072, 850, 850, 850, 850, + 850, 850, 850, 850, 850, 850, 850, 850, 850, 850, + 850, 850, 850, 850, 850, 850, 850, 850, 850, 850, + 850, 850, 850, 850, 850, 850, 850, 850, + }}, {{ + 3072, 1212, 1212, 1212, 999, 999, 999, 999, 999, 999, + 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, + 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, + 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, + 999, 999, 999, 999, + }, { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + }}, {{ + 3072, 3072, 3072, 3072, 3072, 3072, 3072, 3072, 3072, 3072, + 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, + 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, + 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, + 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, + }, { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }} +}; + +static const uint16_t hearing_thresh_tab[3][3][50] = { + {{ + 1403, 1141, 1000, 959, 948, 957, 946, 925, 899, 871, + 843, 815, 789, 766, 745, 727, 705, 687, 681, 686, + 701, 725, 768, 854, 940, 1018, 1075, 1103, 1111, 1106, + 1098, 1105, 1142, 1237, 1419, 1721, 2169, 2805, + }, { + 1401, 1130, 995, 957, 947, 955, 941, 918, 890, 861, + 831, 803, 777, 754, 734, 717, 698, 684, 682, 692, + 712, 743, 798, 894, 976, 1045, 1091, 1109, 1110, 1102, + 1098, 1116, 1174, 1300, 1526, 1884, 2401, 3072, + }, { + 1393, 1086, 974, 949, 957, 941, 913, 878, 843, 808, + 777, 750, 727, 708, 695, 686, 681, 689, 714, 752, + 811, 888, 971, 1044, 1087, 1108, 1110, 1102, 1098, 1115, + 1172, 1290, 1489, 1812, 2293, 2964, 3072, 3072, + }}, {{ + 1412, 1343, 1141, 1047, 1000, 974, 959, 951, 948, 947, + 957, 953, 946, 936, 925, 906, 878, 850, 822, 795, + 771, 745, 719, 700, 687, 681, 685, 701, 733, 784, + 885, 977, 1047, 1092, 1110, 1108, 1099, 1102, 1138, 1233, + 1413, 1711, 2157, 2797, + }, { + 1412, 1336, 1130, 1040, 995, 970, 957, 950, 947, 947, + 955, 950, 941, 930, 918, 897, 868, 838, 810, 783, + 759, 734, 710, 693, 684, 681, 690, 712, 752, 823, + 924, 1009, 1069, 1102, 1111, 1104, 1098, 1111, 1168, 1295, + 1518, 1873, 2388, 3072, + }, { + 1411, 1293, 1086, 1009, 974, 957, 949, 947, 957, 951, + 941, 928, 913, 896, 878, 852, 817, 785, 756, 732, + 713, 695, 683, 682, 689, 710, 746, 811, 906, 992, + 1061, 1099, 1111, 1106, 1098, 1107, 1155, 1266, 1471, 1799, + 2277, 2945, 3072, 3072, + }}, {{ + 1431, 1412, 1403, 1379, 1343, 1293, 1229, 1180, 1125, 1075, + 1040, 1014, 996, 979, 965, 957, 951, 948, 947, 957, + 951, 940, 924, 903, 877, 846, 815, 785, 753, 725, + 702, 686, 681, 689, 714, 760, 847, 947, 1028, 1083, + 1108, 1109, 1101, 1100, 1132, 1222, 1402, 1705, 2160, 2803, + }, { + 1431, 1412, 1401, 1375, 1336, 1278, 1215, 1168, 1115, 1066, + 1032, 1008, 991, 975, 962, 954, 950, 947, 947, 955, + 948, 935, 916, 894, 866, 835, 803, 772, 742, 715, + 695, 683, 683, 697, 729, 784, 887, 982, 1054, 1096, + 1111, 1106, 1098, 1107, 1159, 1281, 1505, 1865, 2391, 3072, + }, { + 1427, 1411, 1393, 1353, 1293, 1215, 1160, 1118, 1072, 1031, + 1003, 984, 971, 960, 952, 948, 947, 957, 952, 941, + 924, 902, 876, 847, 815, 781, 750, 723, 700, 685, + 681, 691, 719, 766, 858, 958, 1039, 1089, 1109, 1108, + 1099, 1102, 1141, 1245, 1442, 1766, 2250, 2930, 3072, 3072, + }} +}; + +static const int16_t lwc_gain_tab[11][7] = { + { -21, -197, -271, -466, 32767, 32767, 32767 }, + { -197, -29, -244, -271, -540, 32767, 32767 }, + { -271, -244, -29, -249, -271, -593, 32767 }, + { -466, -271, -249, -29, -251, -271, -632 }, + { -540, -271, -251, -29, -251, -271, -664 }, + { -593, -271, -251, -29, -252, -271, -690 }, + { -632, -271, -252, -29, -252, -271, -711 }, + { -664, -271, -252, -29, -252, -271, -730 }, + { -690, -271, -252, -29, -252, -271, -745 }, + { -711, -271, -252, -29, -253, -271, -759 }, + { -730, -271, -253, -29, -253, -271, -771 }, +}; + +static const int16_t lwc_adj_tab[7] = { + -192, -320, -448, -512, -448, -320, -192, +}; + +static const uint8_t log_add_tab[212] = { + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 52, 51, 50, + 49, 48, 47, 47, 46, 45, 44, 44, 43, 42, 41, 41, 40, 39, 38, 38, + 37, 36, 36, 35, 35, 34, 33, 33, 32, 32, 31, 30, 30, 29, 29, 28, + 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 21, + 20, 20, 19, 19, 19, 18, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, + 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 11, + 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, +}; + +static const uint8_t bap_tab[64] = { + 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, + 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, + 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, +}; + +static float mantissa_tab1[17][4]; +static float mantissa_tab2[17][4]; +static float mantissa_tab3[17][4]; +static float exponent_tab[50]; +static float gain_tab[1024]; + +DECLARE_ALIGNED(32, static float, window)[3712]; + static int skip_input(DBEContext *s, int nb_words) { if (nb_words > s->input_size) { @@ -43,7 +616,7 @@ static int parse_key(DBEContext *s) { if (s->key_present) { - uint8_t *key = s->input; + const uint8_t *key = s->input; int ret = skip_input(s, 1); if (ret < 0) return ret; @@ -52,105 +625,11 @@ return 0; } -static int convert_input(DBEContext *s, int nb_words, int key) -{ - uint8_t *src = s->input; - uint8_t *dst = s->buffer; - PutBitContext pb; - int i; - - av_assert0(nb_words <= 1024u); - - if (nb_words > s->input_size) { - av_log(s->avctx, AV_LOG_ERROR, "Packet too short\n"); - return AVERROR_INVALIDDATA; - } - - switch (s->word_bits) { - case 16: - for (i = 0; i < nb_words; i++, src += 2, dst += 2) - AV_WB16(dst, AV_RB16(src) ^ key); - break; - case 20: - init_put_bits(&pb, s->buffer, sizeof(s->buffer)); - for (i = 0; i < nb_words; i++, src += 3) - put_bits(&pb, 20, AV_RB24(src) >> 4 ^ key); - flush_put_bits(&pb); - break; - case 24: - for (i = 0; i < nb_words; i++, src += 3, dst += 3) - AV_WB24(dst, AV_RB24(src) ^ key); - break; - default: - av_assert0(0); - } - - return init_get_bits(&s->gb, s->buffer, nb_words * s->word_bits); -} - -static int parse_metadata(DBEContext *s) +static int parse_metadata_ext(DBEDecodeContext *s1) { - int i, ret, key, mtd_size; - - if ((key = parse_key(s)) < 0) - return key; - if ((ret = convert_input(s, 1, key)) < 0) - return ret; - - skip_bits(&s->gb, 4); - mtd_size = get_bits(&s->gb, 10); - if (!mtd_size) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid metadata size\n"); - return AVERROR_INVALIDDATA; - } - - if ((ret = convert_input(s, mtd_size, key)) < 0) - return ret; - - skip_bits(&s->gb, 14); - s->prog_conf = get_bits(&s->gb, 6); - if (s->prog_conf > MAX_PROG_CONF) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid program configuration\n"); - return AVERROR_INVALIDDATA; - } - - s->nb_channels = nb_channels_tab[s->prog_conf]; - s->nb_programs = nb_programs_tab[s->prog_conf]; - - s->fr_code = get_bits(&s->gb, 4); - s->fr_code_orig = get_bits(&s->gb, 4); - if (!sample_rate_tab[s->fr_code] || - !sample_rate_tab[s->fr_code_orig]) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid frame rate code\n"); - return AVERROR_INVALIDDATA; - } - - skip_bits_long(&s->gb, 88); - for (i = 0; i < s->nb_channels; i++) - s->ch_size[i] = get_bits(&s->gb, 10); - s->mtd_ext_size = get_bits(&s->gb, 8); - s->meter_size = get_bits(&s->gb, 8); - - skip_bits_long(&s->gb, 10 * s->nb_programs); - for (i = 0; i < s->nb_channels; i++) { - s->rev_id[i] = get_bits(&s->gb, 4); - skip_bits1(&s->gb); - s->begin_gain[i] = get_bits(&s->gb, 10); - s->end_gain[i] = get_bits(&s->gb, 10); - } - - if (get_bits_left(&s->gb) < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Read past end of metadata\n"); - return AVERROR_INVALIDDATA; - } - - return skip_input(s, mtd_size + 1); -} - -static int parse_metadata_ext(DBEContext *s) -{ - if (s->mtd_ext_size) - return skip_input(s, s->key_present + s->mtd_ext_size + 1); + DBEContext *s = &s1->dectx; + if (s->metadata.mtd_ext_size) + return skip_input(s, s->key_present + s->metadata.mtd_ext_size + 1); return 0; } @@ -278,8 +757,9 @@ } } -static int parse_bit_alloc(DBEContext *s, DBEChannel *c) +static int parse_bit_alloc(DBEDecodeContext *s1, DBEChannel *c) { + DBEContext *s = &s1->dectx; DBEGroup *p, *g; int bap_strategy[MAX_GROUPS], fg_spc[MAX_GROUPS]; int fg_ofs[MAX_GROUPS], msk_mod[MAX_GROUPS]; @@ -311,7 +791,7 @@ for (i = 0, p = NULL, g = c->groups; i < c->nb_groups; i++, p = g, g++) { if (c->exp_strategy[i] || bap_strategy[i]) { - bit_allocate(g->nb_exponent, g->imdct_idx, s->fr_code, + bit_allocate(g->nb_exponent, g->imdct_idx, s->metadata.fr_code, c->exponents + g->exp_ofs, c->bap + g->exp_ofs, fg_spc[i], fg_ofs[i], msk_mod[i], snr_ofs); } else { @@ -411,17 +891,18 @@ return 0; } -static int parse_channel(DBEContext *s, int ch, int seg_id) +static int parse_channel(DBEDecodeContext *s1, int ch, int seg_id) { - DBEChannel *c = &s->channels[seg_id][ch]; + DBEContext *s = &s1->dectx; + DBEChannel *c = &s1->channels[seg_id][ch]; int i, ret; - if (s->rev_id[ch] > 1) { - avpriv_report_missing_feature(s->avctx, "Encoder revision %d", s->rev_id[ch]); + if (s->metadata.rev_id[ch] > 1) { + avpriv_report_missing_feature(s->avctx, "Encoder revision %d", s->metadata.rev_id[ch]); return AVERROR_PATCHWELCOME; } - if (ch == lfe_channel_tab[s->prog_conf]) { + if (ch == lfe_channel_tab[s->metadata.prog_conf]) { c->gr_code = 3; c->bw_code = 29; } else { @@ -446,7 +927,7 @@ if ((ret = parse_exponents(s, c)) < 0) return ret; - if ((ret = parse_bit_alloc(s, c)) < 0) + if ((ret = parse_bit_alloc(s1, c)) < 0) return ret; if ((ret = parse_indices(s, c)) < 0) return ret; @@ -461,42 +942,45 @@ return 0; } -static int parse_audio(DBEContext *s, int start, int end, int seg_id) +static int parse_audio(DBEDecodeContext *s1, int start, int end, int seg_id) { + DBEContext *s = &s1->dectx; int ch, ret, key; if ((key = parse_key(s)) < 0) return key; for (ch = start; ch < end; ch++) { - if (!s->ch_size[ch]) { - s->channels[seg_id][ch].nb_groups = 0; + if (!s->metadata.ch_size[ch]) { + s1->channels[seg_id][ch].nb_groups = 0; continue; } - if ((ret = convert_input(s, s->ch_size[ch], key)) < 0) + ret = ff_dolby_e_convert_input(s, s->metadata.ch_size[ch], key); + if (ret < 0) return ret; - if ((ret = parse_channel(s, ch, seg_id)) < 0) { - if (s->avctx->err_recognition & AV_EF_EXPLODE) + if ((ret = parse_channel(s1, ch, seg_id)) < 0) { + if (s1->avctx->err_recognition & AV_EF_EXPLODE) return ret; - s->channels[seg_id][ch].nb_groups = 0; + s1->channels[seg_id][ch].nb_groups = 0; } - if ((ret = skip_input(s, s->ch_size[ch])) < 0) + if ((ret = skip_input(s, s->metadata.ch_size[ch])) < 0) return ret; } return skip_input(s, 1); } -static int parse_meter(DBEContext *s) +static int parse_meter(DBEDecodeContext *s1) { - if (s->meter_size) - return skip_input(s, s->key_present + s->meter_size + 1); + DBEContext *s = &s1->dectx; + if (s->metadata.meter_size) + return skip_input(s, s->key_present + s->metadata.meter_size + 1); return 0; } -static void imdct_calc(DBEContext *s, DBEGroup *g, float *result, float *values) +static void imdct_calc(DBEDecodeContext *s1, DBEGroup *g, float *result, float *values) { - FFTContext *imdct = &s->imdct[g->imdct_idx]; + FFTContext *imdct = &s1->imdct[g->imdct_idx]; int n = 1 << imdct_bits_tab[g->imdct_idx]; int n2 = n >> 1; int i; @@ -520,7 +1004,7 @@ } } -static void transform(DBEContext *s, DBEChannel *c, float *history, float *output) +static void transform(DBEDecodeContext *s1, DBEChannel *c, float *history, float *output) { LOCAL_ALIGNED_32(float, buffer, [2048]); LOCAL_ALIGNED_32(float, result, [1152]); @@ -533,8 +1017,8 @@ float *dst = result + g->dst_ofs; float *win = window + g->win_ofs; - imdct_calc(s, g, buffer, c->mantissas + g->mnt_ofs); - s->fdsp->vector_fmul_add(dst, src, win, dst, g->win_len); + imdct_calc(s1, g, buffer, c->mantissas + g->mnt_ofs); + s1->fdsp->vector_fmul_add(dst, src, win, dst, g->win_len); } for (i = 0; i < 256; i++) @@ -545,7 +1029,7 @@ history[i] = result[896 + i]; } -static void apply_gain(DBEContext *s, int begin, int end, float *output) +static void apply_gain(DBEDecodeContext *s, int begin, int end, float *output) { if (begin == 960 && end == 960) return; @@ -562,16 +1046,17 @@ } } -static int filter_frame(DBEContext *s, AVFrame *frame) +static int filter_frame(DBEDecodeContext *s, AVFrame *frame) { + const DolbyEHeaderInfo *const metadata = &s->dectx.metadata; const uint8_t *reorder; int ch, ret; - if (s->nb_channels == 4) + if (metadata->nb_channels == 4) reorder = ch_reorder_4; - else if (s->nb_channels == 6) + else if (metadata->nb_channels == 6) reorder = ch_reorder_6; - else if (s->nb_programs == 1 && !(s->avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE)) + else if (metadata->nb_programs == 1 && !(s->avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE)) reorder = ch_reorder_8; else reorder = ch_reorder_n; @@ -580,11 +1065,11 @@ if ((ret = ff_get_buffer(s->avctx, frame, 0)) < 0) return ret; - for (ch = 0; ch < s->nb_channels; ch++) { + for (ch = 0; ch < metadata->nb_channels; ch++) { float *output = (float *)frame->extended_data[reorder[ch]]; transform(s, &s->channels[0][ch], s->history[ch], output); transform(s, &s->channels[1][ch], s->history[ch], output + FRAME_SAMPLES / 2); - apply_gain(s, s->begin_gain[ch], s->end_gain[ch], output); + apply_gain(s, metadata->begin_gain[ch], metadata->end_gain[ch], output); } return 0; @@ -593,39 +1078,21 @@ static int dolby_e_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { - DBEContext *s = avctx->priv_data; - int i, j, hdr, ret; - - if (avpkt->size < 3) - return AVERROR_INVALIDDATA; - - hdr = AV_RB24(avpkt->data); - if ((hdr & 0xfffffe) == 0x7888e) { - s->word_bits = 24; - } else if ((hdr & 0xffffe0) == 0x788e0) { - s->word_bits = 20; - } else if ((hdr & 0xfffe00) == 0x78e00) { - s->word_bits = 16; - } else { - av_log(avctx, AV_LOG_ERROR, "Invalid frame header\n"); - return AVERROR_INVALIDDATA; - } - - s->word_bytes = s->word_bits + 7 >> 3; - s->input = avpkt->data + s->word_bytes; - s->input_size = avpkt->size / s->word_bytes - 1; - s->key_present = hdr >> 24 - s->word_bits & 1; + DBEDecodeContext *s1 = avctx->priv_data; + DBEContext *s = &s1->dectx; + int i, j, ret; - if ((ret = parse_metadata(s)) < 0) + if ((ret = ff_dolby_e_parse_header(s, avpkt->data, avpkt->size)) < 0) return ret; - if (s->nb_programs > 1 && !s->multi_prog_warned) { + if (s->metadata.nb_programs > 1 && !s->metadata.multi_prog_warned) { av_log(avctx, AV_LOG_WARNING, "Stream has %d programs (configuration %d), " - "channels will be output in native order.\n", s->nb_programs, s->prog_conf); - s->multi_prog_warned = 1; + "channels will be output in native order.\n", + s->metadata.nb_programs, s->metadata.prog_conf); + s->metadata.multi_prog_warned = 1; } - switch (s->nb_channels) { + switch (s->metadata.nb_channels) { case 4: avctx->channel_layout = AV_CH_LAYOUT_4POINT0; break; @@ -637,25 +1104,25 @@ break; } - avctx->channels = s->nb_channels; - avctx->sample_rate = sample_rate_tab[s->fr_code]; + avctx->channels = s->metadata.nb_channels; + avctx->sample_rate = s->metadata.sample_rate; avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; - i = s->nb_channels / 2; - j = s->nb_channels; - if ((ret = parse_audio(s, 0, i, 0)) < 0) + i = s->metadata.nb_channels / 2; + j = s->metadata.nb_channels; + if ((ret = parse_audio(s1, 0, i, 0)) < 0) return ret; - if ((ret = parse_audio(s, i, j, 0)) < 0) + if ((ret = parse_audio(s1, i, j, 0)) < 0) return ret; - if ((ret = parse_metadata_ext(s)) < 0) + if ((ret = parse_metadata_ext(s1)) < 0) return ret; - if ((ret = parse_audio(s, 0, i, 1)) < 0) + if ((ret = parse_audio(s1, 0, i, 1)) < 0) return ret; - if ((ret = parse_audio(s, i, j, 1)) < 0) + if ((ret = parse_audio(s1, i, j, 1)) < 0) return ret; - if ((ret = parse_meter(s)) < 0) + if ((ret = parse_meter(s1)) < 0) return ret; - if ((ret = filter_frame(s, data)) < 0) + if ((ret = filter_frame(s1, data)) < 0) return ret; *got_frame_ptr = 1; @@ -664,14 +1131,14 @@ static av_cold void dolby_e_flush(AVCodecContext *avctx) { - DBEContext *s = avctx->priv_data; + DBEDecodeContext *s = avctx->priv_data; memset(s->history, 0, sizeof(s->history)); } static av_cold int dolby_e_close(AVCodecContext *avctx) { - DBEContext *s = avctx->priv_data; + DBEDecodeContext *s = avctx->priv_data; int i; for (i = 0; i < 3; i++) @@ -771,7 +1238,7 @@ static av_cold int dolby_e_init(AVCodecContext *avctx) { static AVOnce init_once = AV_ONCE_INIT; - DBEContext *s = avctx->priv_data; + DBEDecodeContext *s = avctx->priv_data; int i; if (ff_thread_once(&init_once, init_tables)) @@ -784,8 +1251,8 @@ if (!(s->fdsp = avpriv_float_dsp_alloc(0))) return AVERROR(ENOMEM); - s->multi_prog_warned = !!(avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE); - s->avctx = avctx; + s->dectx.metadata.multi_prog_warned = !!(avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE); + s->dectx.avctx = s->avctx = avctx; return 0; } @@ -794,7 +1261,7 @@ .long_name = NULL_IF_CONFIG_SMALL("Dolby E"), .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_DOLBY_E, - .priv_data_size = sizeof(DBEContext), + .priv_data_size = sizeof(DBEDecodeContext), .init = dolby_e_init, .decode = dolby_e_decode_frame, .close = dolby_e_close, diff -Nru ffmpeg-4.2.2/libavcodec/dolby_e.h ffmpeg-4.4/libavcodec/dolby_e.h --- ffmpeg-4.2.2/libavcodec/dolby_e.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dolby_e.h 2021-04-08 21:28:39.000000000 +0000 @@ -21,70 +21,23 @@ #ifndef AVCODEC_DOLBY_E_H #define AVCODEC_DOLBY_E_H -#include "libavutil/float_dsp.h" -#include "libavutil/libm.h" -#include "libavutil/mem.h" - -#include "internal.h" +#include #include "get_bits.h" -#include "kbdwin.h" -#include "fft.h" #define FRAME_SAMPLES 1792 #define MAX_PROG_CONF 23 #define MAX_PROGRAMS 8 #define MAX_CHANNELS 8 -#define MAX_SEGMENTS 2 - -#define MAX_GROUPS 8 -#define MAX_EXPONENTS 304 -#define MAX_MANTISSAS 1024 - -#define MAX_MSTR_EXP 2 -#define MAX_BIAS_EXP 50 - -typedef struct DBEGroup { - uint8_t nb_exponent; - uint8_t nb_bias_exp[MAX_MSTR_EXP]; - uint16_t exp_ofs; - uint16_t mnt_ofs; - const uint8_t *nb_mantissa; - uint8_t imdct_idx; - uint8_t imdct_phs; - uint16_t win_len; - uint16_t dst_ofs; - uint16_t win_ofs; - uint16_t src_ofs; -} DBEGroup; - -typedef struct DBEChannel { - int gr_code; - int bw_code; - - int nb_groups; - int nb_mstr_exp; - DBEGroup groups[MAX_GROUPS]; - - int exp_strategy[MAX_GROUPS]; - int exponents[MAX_EXPONENTS]; - int bap[MAX_EXPONENTS]; - int idx[MAX_EXPONENTS]; - - DECLARE_ALIGNED(32, float, mantissas)[MAX_MANTISSAS]; -} DBEChannel; - -typedef struct DBEContext { - AVCodecContext *avctx; - GetBitContext gb; - - uint8_t *input; - int input_size; - - int word_bits; - int word_bytes; - int key_present; +/** + * @struct DolbyEHeaderInfo + * Coded Dolby E header values up to end_gain element, plus derived values. + */ +typedef struct DolbyEHeaderInfo { + /** @name Coded elements + * @{ + */ int prog_conf; int nb_channels; int nb_programs; @@ -99,549 +52,52 @@ int rev_id[MAX_CHANNELS]; int begin_gain[MAX_CHANNELS]; int end_gain[MAX_CHANNELS]; + /** @} */ + /** @name Derived values + * @{ + */ int multi_prog_warned; - DBEChannel channels[MAX_SEGMENTS][MAX_CHANNELS]; + int sample_rate; + /** @} */ +} DolbyEHeaderInfo; + +/** + * @struct DBEContext + * Dolby E reading context used by decoder and parser. + */ +typedef struct DBEContext { + void *avctx; + GetBitContext gb; + + const uint8_t *input; + int input_size; - DECLARE_ALIGNED(32, float, history)[MAX_CHANNELS][256]; + int word_bits; + int word_bytes; + int key_present; - FFTContext imdct[3]; - AVFloatDSPContext *fdsp; + DolbyEHeaderInfo metadata; uint8_t buffer[1024 * 3 + AV_INPUT_BUFFER_PADDING_SIZE]; } DBEContext; -static const uint8_t nb_programs_tab[MAX_PROG_CONF + 1] = { - 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 8, 1, 2, 3, 3, 4, 5, 6, 1, 2, 3, 4, 1, 1 -}; - -static const uint8_t nb_channels_tab[MAX_PROG_CONF + 1] = { - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, 8, 8 -}; - -static const int8_t lfe_channel_tab[MAX_PROG_CONF + 1] = { - 5, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 5 -}; - -static const uint8_t ch_reorder_4[4] = { 0, 2, 1, 3 }; -static const uint8_t ch_reorder_6[6] = { 0, 2, 4, 1, 3, 5 }; -static const uint8_t ch_reorder_8[8] = { 0, 2, 6, 4, 1, 3, 7, 5 }; -static const uint8_t ch_reorder_n[8] = { 0, 2, 4, 6, 1, 3, 5, 7 }; - -static const uint16_t sample_rate_tab[16] = { - 0, 42965, 43008, 44800, 53706, 53760 -}; - -static const uint8_t nb_groups_tab[4] = { 1, 8, 7, 1 }; - -static const uint8_t nb_mstr_exp_tab[4] = { 2, 2, 2, 1 }; - -static const uint8_t nb_mantissa_38[38] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, - 7, 8, 9, 10, 11, 12, -}; - -static const uint8_t nb_mantissa_44[44] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 7, 7, - 8, 9, 10, 11, 12, 13, 15, 16, 18, 20, 22, 25, -}; - -static const uint8_t nb_mantissa_50[50] = { - 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, - 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 9, 10, 12, 13, 14, 16, - 18, 19, 22, 24, 27, 29, 32, 36, 40, 44, 49, 54, 60, 66, 74, 82, - 90, 100, -}; - -static const uint8_t imdct_bits_tab[3] = { 8, 9, 11 }; - -static const DBEGroup grp_tab_0[1] = { - { 50, { 27, 23 }, 0, 0, nb_mantissa_50, 2, 0, 1152, 0, 1408, 0 }, -}; - -static const DBEGroup grp_tab_1[8] = { - { 38, { 12, 26 }, 0, 0, nb_mantissa_38, 0, 0, 192, 0, 256, 0 }, - { 38, { 12, 26 }, 38, 128, nb_mantissa_38, 0, 1, 256, 64, 448, 0 }, - { 38, { 12, 26 }, 76, 256, nb_mantissa_38, 0, 1, 256, 192, 704, 0 }, - { 38, { 12, 26 }, 114, 384, nb_mantissa_38, 0, 1, 256, 320, 0, 0 }, - { 38, { 12, 26 }, 152, 512, nb_mantissa_38, 0, 1, 256, 448, 0, 0 }, - { 38, { 12, 26 }, 190, 640, nb_mantissa_38, 0, 1, 256, 576, 0, 0 }, - { 38, { 12, 26 }, 228, 768, nb_mantissa_38, 0, 1, 256, 704, 0, 0 }, - { 38, { 12, 26 }, 266, 896, nb_mantissa_38, 0, 1, 256, 832, 0, 0 }, -}; - -static const DBEGroup grp_tab_2[7] = { - { 38, { 12, 26 }, 0, 0, nb_mantissa_38, 0, 0, 192, 0, 256, 0 }, - { 38, { 12, 26 }, 38, 128, nb_mantissa_38, 0, 1, 256, 64, 448, 0 }, - { 38, { 12, 26 }, 76, 256, nb_mantissa_38, 0, 1, 256, 192, 704, 0 }, - { 38, { 12, 26 }, 114, 384, nb_mantissa_38, 0, 1, 256, 320, 0, 0 }, - { 38, { 12, 26 }, 152, 512, nb_mantissa_38, 0, 1, 256, 448, 0, 0 }, - { 38, { 12, 26 }, 190, 640, nb_mantissa_38, 0, 1, 256, 576, 0, 0 }, - { 44, { 19, 25 }, 228, 768, nb_mantissa_44, 1, 1, 448, 704, 960, 64 }, -}; - -static const DBEGroup grp_tab_3[1] = { - { 21, { 21 }, 0, 0, nb_mantissa_50, 2, 0, 1152, 0, 1408, 0 }, -}; - -static const DBEGroup grp_tab_4[1] = { - { 50, { 27, 23 }, 0, 0, nb_mantissa_50, 2, 2, 1152, 0, 1408, 896 }, -}; - -static const DBEGroup grp_tab_5[8] = { - { 38, { 12, 26 }, 0, 0, nb_mantissa_38, 0, 1, 256, 64, 0, 0 }, - { 38, { 12, 26 }, 38, 128, nb_mantissa_38, 0, 1, 256, 192, 0, 0 }, - { 38, { 12, 26 }, 76, 256, nb_mantissa_38, 0, 1, 256, 320, 0, 0 }, - { 38, { 12, 26 }, 114, 384, nb_mantissa_38, 0, 1, 256, 448, 0, 0 }, - { 38, { 12, 26 }, 152, 512, nb_mantissa_38, 0, 1, 256, 576, 0, 0 }, - { 38, { 12, 26 }, 190, 640, nb_mantissa_38, 0, 1, 256, 704, 3008, 0 }, - { 38, { 12, 26 }, 228, 768, nb_mantissa_38, 0, 1, 256, 832, 2752, 0 }, - { 38, { 12, 26 }, 266, 896, nb_mantissa_38, 0, 2, 192, 960, 2560, 64 }, -}; - -static const DBEGroup grp_tab_6[7] = { - { 44, { 19, 25 }, 0, 0, nb_mantissa_44, 1, 1, 448, 0, 3264, 0 }, - { 38, { 12, 26 }, 44, 256, nb_mantissa_38, 0, 1, 256, 320, 0, 0 }, - { 38, { 12, 26 }, 82, 384, nb_mantissa_38, 0, 1, 256, 448, 0, 0 }, - { 38, { 12, 26 }, 120, 512, nb_mantissa_38, 0, 1, 256, 576, 0, 0 }, - { 38, { 12, 26 }, 158, 640, nb_mantissa_38, 0, 1, 256, 704, 3008, 0 }, - { 38, { 12, 26 }, 196, 768, nb_mantissa_38, 0, 1, 256, 832, 2752, 0 }, - { 38, { 12, 26 }, 234, 896, nb_mantissa_38, 0, 2, 192, 960, 2560, 64 }, -}; - -static const DBEGroup grp_tab_7[1] = { - { 21, { 21 }, 0, 0, nb_mantissa_50, 2, 2, 1152, 0, 1408, 896 }, -}; - -static const DBEGroup *const frm_ofs_tab[2][4] = { - { grp_tab_0, grp_tab_1, grp_tab_2, grp_tab_3 }, - { grp_tab_4, grp_tab_5, grp_tab_6, grp_tab_7 } -}; - -static const uint8_t mantissa_size1[16][4] = { - { 0, 0, 0, 0 }, { 2, 1, 1, 1 }, { 3, 2, 1, 1 }, { 4, 3, 2, 1 }, - { 5, 4, 3, 2 }, { 6, 5, 4, 3 }, { 7, 6, 5, 4 }, { 8, 7, 6, 5 }, - { 9, 8, 7, 6 }, { 10, 9, 8, 7 }, { 11, 10, 9, 8 }, { 12, 11, 10, 9 }, - { 13, 12, 11, 10 }, { 14, 13, 12, 11 }, { 15, 14, 13, 12 }, { 16, 15, 14, 13 }, -}; - -static const uint8_t mantissa_size2[16][4] = { - { 0, 0, 0, 0 }, { 2, 1, 2, 2 }, { 3, 2, 3, 3 }, { 4, 3, 4, 4 }, - { 5, 4, 5, 5 }, { 6, 5, 6, 6 }, { 7, 6, 7, 7 }, { 8, 7, 8, 8 }, - { 9, 8, 9, 9 }, { 10, 9, 10, 10 }, { 11, 10, 11, 11 }, { 12, 11, 12, 12 }, - { 13, 12, 13, 13 }, { 14, 13, 14, 14 }, { 15, 14, 15, 15 }, { 16, 15, 16, 16 }, -}; - -static const float start_window[192] = { - 0.00161569379826, 0.00185748233347, 0.00198562758548, 0.00207834078104, - 0.00215717748523, 0.00223067096393, 0.00230299213147, 0.00237651215396, - 0.00245275561606, 0.00253281402069, 0.00261754673613, 0.00270768786168, - 0.00280390761895, 0.00290684998656, 0.00301715751161, 0.00313548872798, - 0.00326253122934, 0.00339901215995, 0.00354570716636, 0.00370344845023, - 0.00387313232586, 0.00405572653911, 0.00425227750970, 0.00446391759265, - 0.00469187240551, 0.00493746822816, 0.00520213944619, 0.00548743597507, - 0.00579503056737, 0.00612672586953, 0.00648446105606, 0.00687031782873, - 0.00728652552677, 0.00773546505205, 0.00821967127415, 0.00874183354619, - 0.00930479393832, 0.00991154278653, 0.01056521116692, 0.01126905994567, - 0.01202646513050, 0.01284089936559, 0.01371590957417, 0.01465509096066, - 0.01566205783408, 0.01674041199523, 0.01789370972358, 0.01912542867865, - 0.02043893626265, 0.02183746113793, 0.02332406961796, 0.02490164852364, - 0.02657289580178, 0.02834031974193, 0.03020624702903, 0.03217283918354, - 0.03424211623810, 0.03641598586180, 0.03869627565015, 0.04108476601498, - 0.04358322107390, 0.04619341515939, 0.04891715301882, 0.05175628239149, - - 0.05471237327267, 0.05778734733755, 0.06098291402413, 0.06430101352084, - 0.06774345212186, 0.07131188644726, 0.07500780649199, 0.07883251748595, - 0.08278712056651, 0.08687249228061, 0.09108926295730, 0.09543779401074, - 0.09991815425851, 0.10453009536427, 0.10927302653894, 0.11414598865987, - 0.11914762799220, 0.12427616972097, 0.12952939152560, 0.13490459744934, - 0.14039859233595, 0.14600765712201, 0.15172752528722, 0.15755336077528, - 0.16347973770491, 0.16950062219342, 0.17560935661442, 0.18179864660619, - 0.18806055113821, 0.19438647593012, 0.20076717050010, 0.20719272909882, - 0.21365259576030, 0.22013557367283, 0.22662983904194, 0.23312295958328, - 0.23960191774666, 0.24605313873388, 0.25246252333253, 0.25881548554631, - 0.26509699495987, 0.27129162373316, 0.27738359807707, 0.28335685401987, - 0.28919509723179, 0.29488186663467, 0.30040060148455, 0.30573471157819, - 0.31086765019993, 0.31578298939317, 0.32046449711227, 0.32489621578468, - 0.32906254179156, 0.33294830535654, 0.33653885031840, 0.33982011325336, - 0.34277870140679, 0.34540196889300, 0.34767809062480, 0.34959613344194, - 0.35114612391958, 0.35231911235422, 0.35310723244504, 0.35350375621308, - - 0.35350314372945, 0.35310108725579, 0.35229454943591, 0.35108179521634, - 0.34946241721522, 0.34743735430290, 0.34500890320420, 0.34218072298001, - 0.33895783229541, 0.33534659943168, 0.33135472505060, 0.32699121776996, - 0.32226636266000, 0.31719168282019, 0.31177989424432, 0.30604485422875, - 0.30000150362379, 0.29366580327088, 0.28705466500775, 0.28018587766131, - 0.27307802848095, 0.26575042049535, 0.25822298630189, 0.25051619882000, - 0.24265097955783, 0.23464860495522, 0.22653061137548, 0.21831869932335, - 0.21003463746705, 0.20170016703857, 0.19333690717811, 0.18496626177620, - 0.17660932835062, 0.16828680947474, 0.16001892724986, 0.15182534128597, - 0.14372507062477, 0.13573642000364, 0.12787691082233, 0.12016321713317, - 0.11261110693234, 0.10523538898282, 0.09804986534955, 0.09106728977263, - 0.08429933194438, 0.07775654768810, 0.07144835495683, 0.06538301547324, - 0.05956762170687, 0.05400808871425, 0.04870915012107, 0.04367435714993, - 0.03890607899172, 0.03440550179663, 0.03017262174627, 0.02620622428513, - 0.02250383492507, 0.01906161305732, 0.01587412848221, 0.01293388032354, - 0.01023019677288, 0.00774641320626, 0.00545109736891, 0.00325868651263, -}; - -static const float short_window2[192] = { - 0.00018861094606, 0.00033433010202, 0.00050309624485, 0.00070306161748, - 0.00093995174533, 0.00121913067128, 0.00154606505568, 0.00192647806126, - 0.00236641248692, 0.00287225985240, 0.00345077377440, 0.00410907465023, - 0.00485464855241, 0.00569534163219, 0.00663935063508, 0.00769520981249, - 0.00887177436246, 0.01017820046395, 0.01162392194150, 0.01321862359335, - 0.01497221122468, 0.01689477844427, 0.01899657030441, 0.02128794388846, - 0.02377932597692, 0.02648116795039, 0.02940389811590, 0.03255787167130, - 0.03595331854986, 0.03960028941437, 0.04350860009563, 0.04768777479454, - 0.05214698838949, 0.05689500821121, 0.06194013566525, 0.06729014809766, - 0.07295224131210, 0.07893297315602, 0.08523820859989, 0.09187306673620, - 0.09884187012422, 0.10614809690222, 0.11379433608064, 0.12178224641797, - 0.13011251926531, 0.13878484574660, 0.14779788861830, 0.15714925912610, - 0.16683549914631, 0.17685206886673, 0.18719334022589, 0.19785259629099, - 0.20882203671372, 0.22009278936030, 0.23165492816694, 0.24349749722585, - 0.25560854105961, 0.26797514099368, 0.28058345748882, 0.29341877824732, - 0.30646557185942, 0.31970754671026, 0.33312771482295, 0.34670846027024, - - 0.36043161174692, 0.37427851885723, 0.38823013163645, 0.40226708279486, - 0.41636977214436, 0.43051845264462, 0.44469331748632, 0.45887458761470, - 0.47304259908636, 0.48717788964798, 0.50126128392546, 0.51527397661778, - 0.52919761310050, 0.54301436685998, 0.55670701320069, 0.57025899869448, - 0.58365450587230, 0.59687851269542, 0.60991684638414, 0.62275623122793, - 0.63538433005035, 0.64778977905593, 0.65996221584264, 0.67189230042379, - 0.68357172916486, 0.69499324160511, 0.70615062019861, 0.71703868307548, - 0.72765326998919, 0.73799122168099, 0.74805035295521, 0.75782941981995, - 0.76732808110520, 0.77654685502339, 0.78548707118622, 0.79415081863423, - 0.80254089047207, 0.81066072573188, 0.81851434910893, 0.82610630922734, - 0.83344161609862, 0.84052567843230, 0.84736424144524, 0.85396332579459, - 0.86032916822973, 0.86646816451999, 0.87238681516918, 0.87809167437532, - 0.88358930263537, 0.88888622333073, 0.89398888356256, 0.89890361943564, - 0.90363662591861, 0.90819393133744, 0.91258137648979, 0.91680459830070, - 0.92086901787718, 0.92477983276087, 0.92854201312583, 0.93216030163834, - 0.93563921662343, 0.93898305819384, 0.94219591693690, 0.94528168477979, - - 0.94823843319821, 0.95106834367330, 0.95377776558539, 0.95636718335775, - 0.95883679961479, 0.96118650212341, 0.96341583179195, 0.96552395212906, - 0.96750962060547, 0.96937116231768, 0.97110644638309, 0.97271286544154, - 0.97418731862798, 0.97552619834964, 0.97672538116257, 0.97778022299974, - 0.97868555895586, 0.97943570778357, 0.98002448120255, 0.98044519806866, - 0.98069070339493, 0.98075339216123, 0.98062523779637, 0.98029782516478, - 0.97976238784222, 0.97900984942031, 0.97803086854002, 0.97681588731895, - 0.97535518280755, 0.97363892108474, 0.97165721358452, 0.96940017523145, - 0.96685798395452, 0.96402094114589, 0.96087953263194, 0.95742448973047, - 0.95364684997699, 0.94953801711660, 0.94508981997396, 0.94029456983253, - 0.93514511597504, 0.92963489905951, 0.92375800202883, 0.91750919827624, - 0.91088399681406, 0.90387868421832, 0.89649036314692, 0.88871698725397, - 0.88055739234735, 0.87201132366062, 0.86307945913336, 0.85376342861693, - 0.84406582894455, 0.83399023482637, 0.82354120554757, 0.81272428745995, - 0.80154601230457, 0.79001389138101, 0.77813640562199, 0.76592299164227, - 0.75338402384395, 0.74053079267526, 0.72737547915460, 0.71393112578527, -}; - -static const float short_window3[64] = { - 0.00326887936450, 0.00550242900936, 0.00786846643791, 0.01045683453520, - 0.01330402120132, 0.01643221072863, 0.01985798040609, 0.02359509464766, - 0.02765559221954, 0.03205025893128, 0.03678884369614, 0.04188015679495, - 0.04733210987781, 0.05315172583924, 0.05934513287609, 0.06591755045290, - 0.07287327156378, 0.08021564389822, 0.08794705152307, 0.09606889811179, - 0.10458159240070, 0.11348453632940, 0.12277611617809, 0.13245369691511, - 0.14251361989876, 0.15295120402567, 0.16376075037904, 0.17493555039885, - 0.18646789757072, 0.19834910260891, 0.21056951208995, 0.22311853047787, - 0.23598464546683, 0.24915545655419, 0.26261770674500, 0.27635731727778, - 0.29035942525136, 0.30460842402318, 0.31908800624032, 0.33378120935681, - 0.34867046348260, 0.36373764140285, 0.37896411059909, 0.39433078709788, - 0.40981819096657, 0.42540650327031, 0.44107562429959, 0.45680523287270, - 0.47257484651351, 0.48836388230077, 0.50415171818214, 0.51991775454258, - 0.53564147581496, 0.55130251191887, 0.56688069931047, 0.58235614142007, - 0.59770926827271, 0.61292089506118, 0.62797227945823, 0.64284517745255, - 0.65752189749349, 0.67198535273209, 0.68621911114984, 0.70020744337099, -}; - -static const uint8_t dc_code_tab[5] = { 0, 0, 0, 1, 1 }; - -static const uint8_t ht_code_tab[5] = { 0, 0, 1, 2, 2 }; - -static const uint8_t band_ofs_tab[3][4] = { - { 12, 8, 4, 0 }, { 14, 10, 6, 0 }, { 12, 8, 4, 0 } -}; - -static const uint8_t band_low_tab[3] = { 9, 17, 24 }; - -static const uint16_t fast_gain_tab[8] = { - 128, 256, 384, 512, 640, 768, 896, 1024 -}; - -static const uint16_t slow_decay_tab[2][2] = { { 27, -1 }, { 32, 21 } }; - -static const uint16_t misc_decay_tab[3][2][2] = { - { { 354, -1 }, { 425, 425 } }, - { { 266, -1 }, { 320, -1 } }, - { { 213, -1 }, { 256, -1 } } -}; - -static const uint16_t fast_decay_tab[3][2][2][50] = { - {{{ - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, - 142, 142, 142, 142, 142, 142, 142, 142, - }, { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - }}, {{ - 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, - 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, - 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, - 170, 170, 170, 170, 170, 170, 170, 170, - }, { - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - }}}, {{{ - 266, 266, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 106, 106, 106, - }, { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - }}, {{ - 319, 319, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, - }, { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - }}}, {{{ - 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, - }, { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }}, {{ - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - }, { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }}} -}; - -static const uint16_t fast_gain_adj_tab[3][2][62] = { - {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 4, 7, 11, 16, 29, 44, 59, - 76, 94, 116, 142, 179, 221, 252, 285, 312, 334, - }, { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 5, 8, 10, 15, 28, 42, 57, 75, 93, - 115, 140, 177, 219, 247, 280, 308, 330, 427, 533, - }}, {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 5, 8, 12, 21, 35, 51, 69, 89, - 111, 138, 176, 220, 251, 284, 312, 334, - }, { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, - 5, 8, 11, 18, 33, 49, 65, 84, 106, 132, - 168, 214, 245, 279, 308, 329, 427, 533, - }}, {{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 4, 7, 10, 17, - 31, 47, 65, 84, 107, 134, 171, 215, 250, 283, - 312, 334, - }, { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 6, 9, 13, 27, 43, - 60, 79, 100, 126, 160, 207, 242, 276, 307, 329, - 427, 533, - }} -}; - -static const uint16_t slow_gain_tab[3][2][50] = { - {{ - 3072, 3072, 3072, 3072, 3072, 3072, 1063, 1063, 1063, 1063, - 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, - 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, - 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, - }, { - 3072, 3072, 3072, 3072, 3072, 3072, 850, 850, 850, 850, - 850, 850, 850, 850, 850, 850, 850, 850, 850, 850, - 850, 850, 850, 850, 850, 850, 850, 850, 850, 850, - 850, 850, 850, 850, 850, 850, 850, 850, - }}, {{ - 3072, 1212, 1212, 1212, 999, 999, 999, 999, 999, 999, - 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, - 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, - 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, - 999, 999, 999, 999, - }, { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - }}, {{ - 3072, 3072, 3072, 3072, 3072, 3072, 3072, 3072, 3072, 3072, - 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, - 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, - 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, - 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, - }, { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }} -}; - -static const uint16_t hearing_thresh_tab[3][3][50] = { - {{ - 1403, 1141, 1000, 959, 948, 957, 946, 925, 899, 871, - 843, 815, 789, 766, 745, 727, 705, 687, 681, 686, - 701, 725, 768, 854, 940, 1018, 1075, 1103, 1111, 1106, - 1098, 1105, 1142, 1237, 1419, 1721, 2169, 2805, - }, { - 1401, 1130, 995, 957, 947, 955, 941, 918, 890, 861, - 831, 803, 777, 754, 734, 717, 698, 684, 682, 692, - 712, 743, 798, 894, 976, 1045, 1091, 1109, 1110, 1102, - 1098, 1116, 1174, 1300, 1526, 1884, 2401, 3072, - }, { - 1393, 1086, 974, 949, 957, 941, 913, 878, 843, 808, - 777, 750, 727, 708, 695, 686, 681, 689, 714, 752, - 811, 888, 971, 1044, 1087, 1108, 1110, 1102, 1098, 1115, - 1172, 1290, 1489, 1812, 2293, 2964, 3072, 3072, - }}, {{ - 1412, 1343, 1141, 1047, 1000, 974, 959, 951, 948, 947, - 957, 953, 946, 936, 925, 906, 878, 850, 822, 795, - 771, 745, 719, 700, 687, 681, 685, 701, 733, 784, - 885, 977, 1047, 1092, 1110, 1108, 1099, 1102, 1138, 1233, - 1413, 1711, 2157, 2797, - }, { - 1412, 1336, 1130, 1040, 995, 970, 957, 950, 947, 947, - 955, 950, 941, 930, 918, 897, 868, 838, 810, 783, - 759, 734, 710, 693, 684, 681, 690, 712, 752, 823, - 924, 1009, 1069, 1102, 1111, 1104, 1098, 1111, 1168, 1295, - 1518, 1873, 2388, 3072, - }, { - 1411, 1293, 1086, 1009, 974, 957, 949, 947, 957, 951, - 941, 928, 913, 896, 878, 852, 817, 785, 756, 732, - 713, 695, 683, 682, 689, 710, 746, 811, 906, 992, - 1061, 1099, 1111, 1106, 1098, 1107, 1155, 1266, 1471, 1799, - 2277, 2945, 3072, 3072, - }}, {{ - 1431, 1412, 1403, 1379, 1343, 1293, 1229, 1180, 1125, 1075, - 1040, 1014, 996, 979, 965, 957, 951, 948, 947, 957, - 951, 940, 924, 903, 877, 846, 815, 785, 753, 725, - 702, 686, 681, 689, 714, 760, 847, 947, 1028, 1083, - 1108, 1109, 1101, 1100, 1132, 1222, 1402, 1705, 2160, 2803, - }, { - 1431, 1412, 1401, 1375, 1336, 1278, 1215, 1168, 1115, 1066, - 1032, 1008, 991, 975, 962, 954, 950, 947, 947, 955, - 948, 935, 916, 894, 866, 835, 803, 772, 742, 715, - 695, 683, 683, 697, 729, 784, 887, 982, 1054, 1096, - 1111, 1106, 1098, 1107, 1159, 1281, 1505, 1865, 2391, 3072, - }, { - 1427, 1411, 1393, 1353, 1293, 1215, 1160, 1118, 1072, 1031, - 1003, 984, 971, 960, 952, 948, 947, 957, 952, 941, - 924, 902, 876, 847, 815, 781, 750, 723, 700, 685, - 681, 691, 719, 766, 858, 958, 1039, 1089, 1109, 1108, - 1099, 1102, 1141, 1245, 1442, 1766, 2250, 2930, 3072, 3072, - }} -}; - -static const int16_t lwc_gain_tab[11][7] = { - { -21, -197, -271, -466, 32767, 32767, 32767 }, - { -197, -29, -244, -271, -540, 32767, 32767 }, - { -271, -244, -29, -249, -271, -593, 32767 }, - { -466, -271, -249, -29, -251, -271, -632 }, - { -540, -271, -251, -29, -251, -271, -664 }, - { -593, -271, -251, -29, -252, -271, -690 }, - { -632, -271, -252, -29, -252, -271, -711 }, - { -664, -271, -252, -29, -252, -271, -730 }, - { -690, -271, -252, -29, -252, -271, -745 }, - { -711, -271, -252, -29, -253, -271, -759 }, - { -730, -271, -253, -29, -253, -271, -771 }, -}; - -static const int16_t lwc_adj_tab[7] = { - -192, -320, -448, -512, -448, -320, -192, -}; - -static const uint8_t log_add_tab[212] = { - 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 52, 51, 50, - 49, 48, 47, 47, 46, 45, 44, 44, 43, 42, 41, 41, 40, 39, 38, 38, - 37, 36, 36, 35, 35, 34, 33, 33, 32, 32, 31, 30, 30, 29, 29, 28, - 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 21, - 20, 20, 19, 19, 19, 18, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, - 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 11, - 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 0, -}; - -static const uint8_t bap_tab[64] = { - 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, - 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, - 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, - 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, -}; - -static float mantissa_tab1[17][4]; -static float mantissa_tab2[17][4]; -static float mantissa_tab3[17][4]; -static float exponent_tab[50]; -static float gain_tab[1024]; - -DECLARE_ALIGNED(32, static float, window)[3712]; +/** + * Use the provided key to transform the input into data (put into s->buffer) + * suitable for further processing and initialize s->gb to read said data. + */ +int ff_dolby_e_convert_input(DBEContext *s, int nb_words, int key); + +/** + * Initialize DBEContext and parse Dolby E metadata. + * Set word_bits/word_bytes, input, input_size, key_present + * and parse the header up to the end_gain element. + * @param[out] s DBEContext. + * @param[in] buf raw input buffer. + * @param[in] buf_size must be 3 bytes at least. + * @return Returns 0 on success, AVERROR_INVALIDDATA on error + */ +int ff_dolby_e_parse_header(DBEContext *s, const uint8_t *buf, int buf_size); #endif diff -Nru ffmpeg-4.2.2/libavcodec/dolby_e_parse.c ffmpeg-4.4/libavcodec/dolby_e_parse.c --- ffmpeg-4.2.2/libavcodec/dolby_e_parse.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dolby_e_parse.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2017 foo86 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "get_bits.h" +#include "put_bits.h" +#include "dolby_e.h" + +static const uint8_t nb_programs_tab[MAX_PROG_CONF + 1] = { + 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 8, 1, 2, 3, 3, 4, 5, 6, 1, 2, 3, 4, 1, 1 +}; + +static const uint8_t nb_channels_tab[MAX_PROG_CONF + 1] = { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, 8, 8 +}; + +static const uint16_t sample_rate_tab[16] = { + 0, 42965, 43008, 44800, 53706, 53760 +}; + +static int skip_input(DBEContext *s, int nb_words) +{ + if (nb_words > s->input_size) { + return AVERROR_INVALIDDATA; + } + + s->input += nb_words * s->word_bytes; + s->input_size -= nb_words; + return 0; +} + +static int parse_key(DBEContext *s) +{ + if (s->key_present) { + const uint8_t *key = s->input; + int ret = skip_input(s, 1); + if (ret < 0) + return ret; + return AV_RB24(key) >> 24 - s->word_bits; + } + return 0; +} + +int ff_dolby_e_convert_input(DBEContext *s, int nb_words, int key) +{ + const uint8_t *src = s->input; + uint8_t *dst = s->buffer; + PutBitContext pb; + int i; + + av_assert0(nb_words <= 1024u); + + if (nb_words > s->input_size) { + if (s->avctx) + av_log(s->avctx, AV_LOG_ERROR, "Packet too short\n"); + return AVERROR_INVALIDDATA; + } + + switch (s->word_bits) { + case 16: + for (i = 0; i < nb_words; i++, src += 2, dst += 2) + AV_WB16(dst, AV_RB16(src) ^ key); + break; + case 20: + init_put_bits(&pb, s->buffer, sizeof(s->buffer)); + for (i = 0; i < nb_words; i++, src += 3) + put_bits(&pb, 20, AV_RB24(src) >> 4 ^ key); + flush_put_bits(&pb); + break; + case 24: + for (i = 0; i < nb_words; i++, src += 3, dst += 3) + AV_WB24(dst, AV_RB24(src) ^ key); + break; + default: + av_assert0(0); + } + + return init_get_bits(&s->gb, s->buffer, nb_words * s->word_bits); +} + +int ff_dolby_e_parse_header(DBEContext *s, const uint8_t *buf, int buf_size) +{ + DolbyEHeaderInfo *const header = &s->metadata; + int hdr, ret, key, mtd_size; + + if (buf_size < 3) + return AVERROR_INVALIDDATA; + + hdr = AV_RB24(buf); + if ((hdr & 0xfffffe) == 0x7888e) { + s->word_bits = 24; + } else if ((hdr & 0xffffe0) == 0x788e0) { + s->word_bits = 20; + } else if ((hdr & 0xfffe00) == 0x78e00) { + s->word_bits = 16; + } else { + if (s->avctx) + av_log(s->avctx, AV_LOG_ERROR, "Invalid frame header\n"); + return AVERROR_INVALIDDATA; + } + + s->word_bytes = s->word_bits + 7 >> 3; + s->input = buf + s->word_bytes; + s->input_size = buf_size / s->word_bytes - 1; + s->key_present = hdr >> 24 - s->word_bits & 1; + + if ((key = parse_key(s)) < 0) + return key; + if ((ret = ff_dolby_e_convert_input(s, 1, key)) < 0) + return ret; + + skip_bits(&s->gb, 4); + mtd_size = get_bits(&s->gb, 10); + if (!mtd_size) { + if (s->avctx) + av_log(s->avctx, AV_LOG_ERROR, "Invalid metadata size\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_dolby_e_convert_input(s, mtd_size, key)) < 0) + return ret; + + skip_bits(&s->gb, 14); + header->prog_conf = get_bits(&s->gb, 6); + if (header->prog_conf > MAX_PROG_CONF) { + if (s->avctx) + av_log(s->avctx, AV_LOG_ERROR, "Invalid program configuration\n"); + return AVERROR_INVALIDDATA; + } + + header->nb_channels = nb_channels_tab[header->prog_conf]; + header->nb_programs = nb_programs_tab[header->prog_conf]; + + header->fr_code = get_bits(&s->gb, 4); + header->fr_code_orig = get_bits(&s->gb, 4); + if (!(header->sample_rate = sample_rate_tab[header->fr_code]) || + !sample_rate_tab[header->fr_code_orig]) { + if (s->avctx) + av_log(s->avctx, AV_LOG_ERROR, "Invalid frame rate code\n"); + return AVERROR_INVALIDDATA; + } + + skip_bits_long(&s->gb, 88); + for (int i = 0; i < header->nb_channels; i++) + header->ch_size[i] = get_bits(&s->gb, 10); + header->mtd_ext_size = get_bits(&s->gb, 8); + header->meter_size = get_bits(&s->gb, 8); + + skip_bits_long(&s->gb, 10 * header->nb_programs); + for (int i = 0; i < header->nb_channels; i++) { + header->rev_id[i] = get_bits(&s->gb, 4); + skip_bits1(&s->gb); + header->begin_gain[i] = get_bits(&s->gb, 10); + header->end_gain[i] = get_bits(&s->gb, 10); + } + + if (get_bits_left(&s->gb) < 0) { + if (s->avctx) + av_log(s->avctx, AV_LOG_ERROR, "Read past end of metadata\n"); + return AVERROR_INVALIDDATA; + } + + return skip_input(s, mtd_size + 1); +} diff -Nru ffmpeg-4.2.2/libavcodec/dolby_e_parser.c ffmpeg-4.4/libavcodec/dolby_e_parser.c --- ffmpeg-4.2.2/libavcodec/dolby_e_parser.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dolby_e_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 foo86 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "dolby_e.h" +#include "get_bits.h" +#include "put_bits.h" + +typedef struct DBEParseContext { + DBEContext dectx; +} DBEParseContext; + +static int dolby_e_parse(AVCodecParserContext *s2, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + DBEParseContext *s1 = s2->priv_data; + DBEContext *s = &s1->dectx; + int ret; + + if ((ret = ff_dolby_e_parse_header(s, buf, buf_size)) < 0) + goto end; + + s2->duration = FRAME_SAMPLES; + switch (s->metadata.nb_channels) { + case 4: + avctx->channel_layout = AV_CH_LAYOUT_4POINT0; + break; + case 6: + avctx->channel_layout = AV_CH_LAYOUT_5POINT1; + break; + case 8: + avctx->channel_layout = AV_CH_LAYOUT_7POINT1; + break; + } + + avctx->channels = s->metadata.nb_channels; + avctx->sample_rate = s->metadata.sample_rate; + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + +end: + /* always return the full packet. this parser isn't doing any splitting or + combining, only packet analysis */ + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; +} + +AVCodecParser ff_dolby_e_parser = { + .codec_ids = { AV_CODEC_ID_DOLBY_E }, + .priv_data_size = sizeof(DBEParseContext), + .parser_parse = dolby_e_parse, +}; diff -Nru ffmpeg-4.2.2/libavcodec/dpcm.c ffmpeg-4.4/libavcodec/dpcm.c --- ffmpeg-4.2.2/libavcodec/dpcm.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dpcm.c 2020-07-11 10:39:30.000000000 +0000 @@ -49,6 +49,21 @@ const int8_t *sol_table; ///< delta table for SOL_DPCM } DPCMContext; +static const int32_t derf_steps[96] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 16, + 17, 19, 21, 23, 25, 28, 31, 34, + 37, 41, 45, 50, 55, 60, 66, 73, + 80, 88, 97, 107, 118, 130, 143, 157, + 173, 190, 209, 230, 253, 279, 307, 337, + 371, 408, 449, 494, 544, 598, 658, 724, + 796, 876, 963, 1060, 1166, 1282, 1411, 1552, + 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, + 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, + 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, + 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767, +}; + static const int16_t interplay_delta_table[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, @@ -225,6 +240,7 @@ else out = buf_size; break; + case AV_CODEC_ID_DERF_DPCM: case AV_CODEC_ID_GREMLIN_DPCM: case AV_CODEC_ID_SDX2_DPCM: out = buf_size; @@ -305,9 +321,8 @@ shift[ch] -= (2 * n); diff = sign_extend((diff &~ 3) << 8, 16); - /* saturate the shifter to a lower limit of 0 */ - if (shift[ch] < 0) - shift[ch] = 0; + /* saturate the shifter to 0..31 */ + shift[ch] = av_clip_uintp2(shift[ch], 5); diff >>= shift[ch]; predictor[ch] += diff; @@ -367,11 +382,26 @@ while (output_samples < samples_end) { uint8_t n = bytestream2_get_byteu(&gb); - *output_samples++ = s->sample[idx] += s->array[n]; + *output_samples++ = s->sample[idx] += (unsigned)s->array[n]; idx ^= 1; } } break; + + case AV_CODEC_ID_DERF_DPCM: { + int idx = 0; + + while (output_samples < samples_end) { + uint8_t n = bytestream2_get_byteu(&gb); + int index = FFMIN(n & 0x7f, 95); + + s->sample[idx] += (n & 0x80 ? -1: 1) * derf_steps[index]; + s->sample[idx] = av_clip_int16(s->sample[idx]); + *output_samples++ = s->sample[idx]; + idx ^= stereo; + } + } + break; } *got_frame_ptr = 1; @@ -391,6 +421,7 @@ .capabilities = AV_CODEC_CAP_DR1, \ } +DPCM_DECODER(AV_CODEC_ID_DERF_DPCM, derf_dpcm, "DPCM Xilam DERF"); DPCM_DECODER(AV_CODEC_ID_GREMLIN_DPCM, gremlin_dpcm, "DPCM Gremlin"); DPCM_DECODER(AV_CODEC_ID_INTERPLAY_DPCM, interplay_dpcm, "DPCM Interplay"); DPCM_DECODER(AV_CODEC_ID_ROQ_DPCM, roq_dpcm, "DPCM id RoQ"); diff -Nru ffmpeg-4.2.2/libavcodec/dpx.c ffmpeg-4.4/libavcodec/dpx.c --- ffmpeg-4.2.2/libavcodec/dpx.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dpx.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,10 +23,43 @@ #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" #include "libavutil/imgutils.h" +#include "libavutil/timecode.h" #include "bytestream.h" #include "avcodec.h" #include "internal.h" +enum DPX_TRC { + DPX_TRC_USER_DEFINED = 0, + DPX_TRC_PRINTING_DENSITY = 1, + DPX_TRC_LINEAR = 2, + DPX_TRC_LOGARITHMIC = 3, + DPX_TRC_UNSPECIFIED_VIDEO = 4, + DPX_TRC_SMPTE_274 = 5, + DPX_TRC_ITU_R_709_4 = 6, + DPX_TRC_ITU_R_601_625 = 7, + DPX_TRC_ITU_R_601_525 = 8, + DPX_TRC_SMPTE_170 = 9, + DPX_TRC_ITU_R_624_4_PAL = 10, + DPX_TRC_Z_LINEAR = 11, + DPX_TRC_Z_HOMOGENEOUS = 12, +}; + +enum DPX_COL_SPEC { + DPX_COL_SPEC_USER_DEFINED = 0, + DPX_COL_SPEC_PRINTING_DENSITY = 1, + /* 2 = N/A */ + /* 3 = N/A */ + DPX_COL_SPEC_UNSPECIFIED_VIDEO = 4, + DPX_COL_SPEC_SMPTE_274 = 5, + DPX_COL_SPEC_ITU_R_709_4 = 6, + DPX_COL_SPEC_ITU_R_601_625 = 7, + DPX_COL_SPEC_ITU_R_601_525 = 8, + DPX_COL_SPEC_SMPTE_170 = 9, + DPX_COL_SPEC_ITU_R_624_4_PAL = 10, + /* 11 = N/A */ + /* 12 = N/A */ +}; + static unsigned int read16(const uint8_t **ptr, int is_big) { unsigned int temp; @@ -126,14 +159,15 @@ AVFrame *const p = data; uint8_t *ptr[AV_NUM_DATA_POINTERS]; uint32_t header_version, version = 0; - char creator[101]; - char input_device[33]; + char creator[101] = { 0 }; + char input_device[33] = { 0 }; unsigned int offset; int magic_num, endian; - int x, y, stride, i, ret; + int x, y, stride, i, j, ret; int w, h, bits_per_color, descriptor, elements, packing; - int encoding, need_align = 0; + int yuv, color_trc, color_spec; + int encoding, need_align = 0, unpadded_10bit = 0; unsigned int rgbBuffer = 0; int n_datum = 0; @@ -192,6 +226,8 @@ // Need to end in 0x320 to read the descriptor buf += 20; descriptor = buf[0]; + color_trc = buf[1]; + color_spec = buf[2]; // Need to end in 0x323 to read the bits per color buf += 3; @@ -216,31 +252,109 @@ else avctx->sample_aspect_ratio = (AVRational){ 0, 1 }; + /* preferred frame rate from Motion-picture film header */ if (offset >= 1724 + 4) { buf = avpkt->data + 1724; i = read32(&buf, endian); - if(i) { + if(i && i != 0xFFFFFFFF) { + AVRational q = av_d2q(av_int2float(i), 4096); + if (q.num > 0 && q.den > 0) + avctx->framerate = q; + } + } + + /* alternative frame rate from television header */ + if (offset >= 1940 + 4 && + !(avctx->framerate.num && avctx->framerate.den)) { + buf = avpkt->data + 1940; + i = read32(&buf, endian); + if(i && i != 0xFFFFFFFF) { AVRational q = av_d2q(av_int2float(i), 4096); if (q.num > 0 && q.den > 0) avctx->framerate = q; } } + /* SMPTE TC from television header */ + if (offset >= 1920 + 4) { + uint32_t tc; + uint32_t *tc_sd; + char tcbuf[AV_TIMECODE_STR_SIZE]; + + buf = avpkt->data + 1920; + // read32 to native endian, av_bswap32 to opposite of native for + // compatibility with av_timecode_make_smpte_tc_string2 etc + tc = av_bswap32(read32(&buf, endian)); + + if (i != 0xFFFFFFFF) { + AVFrameSideData *tcside = + av_frame_new_side_data(p, AV_FRAME_DATA_S12M_TIMECODE, + sizeof(uint32_t) * 4); + if (!tcside) + return AVERROR(ENOMEM); + + tc_sd = (uint32_t*)tcside->data; + tc_sd[0] = 1; + tc_sd[1] = tc; + + av_timecode_make_smpte_tc_string2(tcbuf, avctx->framerate, + tc_sd[1], 0, 0); + av_dict_set(&p->metadata, "timecode", tcbuf, 0); + } + } + + /* color range from television header */ + if (offset >= 1964 + 4) { + buf = avpkt->data + 1952; + i = read32(&buf, endian); + + buf = avpkt->data + 1964; + j = read32(&buf, endian); + + if (i != 0xFFFFFFFF && j != 0xFFFFFFFF) { + float minCV, maxCV; + minCV = av_int2float(i); + maxCV = av_int2float(j); + if (bits_per_color >= 1 && + minCV == 0.0f && maxCV == ((1<color_range = AVCOL_RANGE_JPEG; + } else if (bits_per_color >= 8 && + minCV == (1 <<(bits_per_color - 4)) && + maxCV == (235<<(bits_per_color - 8))) { + avctx->color_range = AVCOL_RANGE_MPEG; + } + } + } + switch (descriptor) { + case 1: // R + case 2: // G + case 3: // B + case 4: // A case 6: // Y elements = 1; + yuv = 1; + break; + case 50: // RGB + elements = 3; + yuv = 0; break; case 52: // ABGR case 51: // RGBA - case 103: // UYVA4444 elements = 4; + yuv = 0; + break; + case 100: // UYVY422 + elements = 2; + yuv = 1; break; - case 50: // RGB case 102: // UYV444 elements = 3; + yuv = 1; break; - case 100: // UYVY422 - elements = 2; + case 103: // UYVA4444 + elements = 4; + yuv = 1; break; default: avpriv_report_missing_feature(avctx, "Descriptor %d", descriptor); @@ -275,8 +389,10 @@ case 16: stride = 2 * avctx->width * elements; break; - case 1: case 32: + stride = 4 * avctx->width * elements; + break; + case 1: case 64: avpriv_report_missing_feature(avctx, "Depth %d", bits_per_color); return AVERROR_PATCHWELCOME; @@ -284,6 +400,82 @@ return AVERROR_INVALIDDATA; } + switch (color_trc) { + case DPX_TRC_LINEAR: + avctx->color_trc = AVCOL_TRC_LINEAR; + break; + case DPX_TRC_SMPTE_274: + case DPX_TRC_ITU_R_709_4: + avctx->color_trc = AVCOL_TRC_BT709; + break; + case DPX_TRC_ITU_R_601_625: + case DPX_TRC_ITU_R_601_525: + case DPX_TRC_SMPTE_170: + avctx->color_trc = AVCOL_TRC_SMPTE170M; + break; + case DPX_TRC_ITU_R_624_4_PAL: + avctx->color_trc = AVCOL_TRC_GAMMA28; + break; + case DPX_TRC_USER_DEFINED: + case DPX_TRC_UNSPECIFIED_VIDEO: + /* Nothing to do */ + break; + default: + av_log(avctx, AV_LOG_VERBOSE, "Cannot map DPX transfer characteristic " + "%d to color_trc.\n", color_trc); + break; + } + + switch (color_spec) { + case DPX_COL_SPEC_SMPTE_274: + case DPX_COL_SPEC_ITU_R_709_4: + avctx->color_primaries = AVCOL_PRI_BT709; + break; + case DPX_COL_SPEC_ITU_R_601_625: + case DPX_COL_SPEC_ITU_R_624_4_PAL: + avctx->color_primaries = AVCOL_PRI_BT470BG; + break; + case DPX_COL_SPEC_ITU_R_601_525: + case DPX_COL_SPEC_SMPTE_170: + avctx->color_primaries = AVCOL_PRI_SMPTE170M; + break; + case DPX_COL_SPEC_USER_DEFINED: + case DPX_COL_SPEC_UNSPECIFIED_VIDEO: + /* Nothing to do */ + break; + default: + av_log(avctx, AV_LOG_VERBOSE, "Cannot map DPX color specification " + "%d to color_primaries.\n", color_spec); + break; + } + + if (yuv) { + switch (color_spec) { + case DPX_COL_SPEC_SMPTE_274: + case DPX_COL_SPEC_ITU_R_709_4: + avctx->colorspace = AVCOL_SPC_BT709; + break; + case DPX_COL_SPEC_ITU_R_601_625: + case DPX_COL_SPEC_ITU_R_624_4_PAL: + avctx->colorspace = AVCOL_SPC_BT470BG; + break; + case DPX_COL_SPEC_ITU_R_601_525: + case DPX_COL_SPEC_SMPTE_170: + avctx->colorspace = AVCOL_SPC_SMPTE170M; + break; + case DPX_COL_SPEC_USER_DEFINED: + case DPX_COL_SPEC_UNSPECIFIED_VIDEO: + /* Nothing to do */ + break; + default: + av_log(avctx, AV_LOG_INFO, "Cannot map DPX color specification " + "%d to colorspace.\n", color_spec); + break; + } + } else { + avctx->colorspace = AVCOL_SPC_RGB; + } + // Table 3c: Runs will always break at scan line boundaries. Packing // will always break to the next 32-bit word at scan-line boundaries. // Unfortunately, the encoder produced invalid files, so attempt @@ -305,6 +497,14 @@ } switch (1000 * descriptor + 10 * bits_per_color + endian) { + case 1081: + case 1080: + case 2081: + case 2080: + case 3081: + case 3080: + case 4081: + case 4080: case 6081: case 6080: avctx->pix_fmt = AV_PIX_FMT_GRAY8; @@ -313,6 +513,20 @@ case 6120: avctx->pix_fmt = AV_PIX_FMT_GRAY12; break; + case 1320: + case 2320: + case 3320: + case 4320: + case 6320: + avctx->pix_fmt = AV_PIX_FMT_GRAYF32LE; + break; + case 1321: + case 2321: + case 3321: + case 4321: + case 6321: + avctx->pix_fmt = AV_PIX_FMT_GRAYF32BE; + break; case 50081: case 50080: avctx->pix_fmt = AV_PIX_FMT_RGB24; @@ -363,6 +577,18 @@ case 51160: avctx->pix_fmt = AV_PIX_FMT_RGBA64LE; break; + case 50320: + avctx->pix_fmt = AV_PIX_FMT_GBRPF32LE; + break; + case 50321: + avctx->pix_fmt = AV_PIX_FMT_GBRPF32BE; + break; + case 51320: + avctx->pix_fmt = AV_PIX_FMT_GBRAPF32LE; + break; + case 51321: + avctx->pix_fmt = AV_PIX_FMT_GBRAPF32BE; + break; case 100081: avctx->pix_fmt = AV_PIX_FMT_UYVY422; break; @@ -373,7 +599,8 @@ avctx->pix_fmt = AV_PIX_FMT_YUVA444P; break; default: - av_log(avctx, AV_LOG_ERROR, "Unsupported format\n"); + av_log(avctx, AV_LOG_ERROR, "Unsupported format %d\n", + 1000 * descriptor + 10 * bits_per_color + endian); return AVERROR_PATCHWELCOME; } @@ -390,6 +617,12 @@ input_device[32] = '\0'; av_dict_set(&p->metadata, "Input Device", input_device, 0); + // Some devices do not pad 10bit samples to whole 32bit words per row + if (!memcmp(input_device, "Scanity", 7) || + !memcmp(creator, "Lasergraphics Inc.", 18)) { + unpadded_10bit = 1; + } + // Move pointer to offset from start of file buf = avpkt->data + offset; @@ -422,7 +655,7 @@ read10in32(&buf, &rgbBuffer, &n_datum, endian, shift); } - if (memcmp(input_device, "Scanity", 7)) + if (!unpadded_10bit) n_datum = 0; for (i = 0; i < elements; i++) ptr[i] += p->linesize[i]; @@ -465,6 +698,36 @@ buf += need_align; } break; + case 32: + if (elements == 1) { + av_image_copy_plane(ptr[0], p->linesize[0], + buf, stride, + elements * avctx->width * 4, avctx->height); + } else { + for (y = 0; y < avctx->height; y++) { + ptr[0] = p->data[0] + y * p->linesize[0]; + ptr[1] = p->data[1] + y * p->linesize[1]; + ptr[2] = p->data[2] + y * p->linesize[2]; + ptr[3] = p->data[3] + y * p->linesize[3]; + for (x = 0; x < avctx->width; x++) { + AV_WN32(ptr[2], AV_RN32(buf)); + AV_WN32(ptr[0], AV_RN32(buf + 4)); + AV_WN32(ptr[1], AV_RN32(buf + 8)); + if (avctx->pix_fmt == AV_PIX_FMT_GBRAPF32BE || + avctx->pix_fmt == AV_PIX_FMT_GBRAPF32LE) { + AV_WN32(ptr[3], AV_RN32(buf + 12)); + buf += 4; + ptr[3] += 4; + } + + buf += 12; + ptr[2] += 4; + ptr[0] += 4; + ptr[1] += 4; + } + } + } + break; case 16: elements *= 2; case 8: diff -Nru ffmpeg-4.2.2/libavcodec/dsd.c ffmpeg-4.4/libavcodec/dsd.c --- ffmpeg-4.2.2/libavcodec/dsd.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dsd.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/thread.h" #include "libavcodec/internal.h" #include "libavcodec/mathops.h" #include "avcodec.h" @@ -45,34 +46,34 @@ av_cold void ff_init_dsd_data(void) { - static int done = 0; - if (done) - return; - dsd_ctables_tableinit(); - done = 1; + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, dsd_ctables_tableinit); } void ff_dsd2pcm_translate(DSDContext* s, size_t samples, int lsbf, - const unsigned char *src, ptrdiff_t src_stride, + const uint8_t *src, ptrdiff_t src_stride, float *dst, ptrdiff_t dst_stride) { + uint8_t buf[FIFOSIZE]; unsigned pos, i; - unsigned char* p; + uint8_t* p; double sum; pos = s->pos; + memcpy(buf, s->buf, sizeof(buf)); + while (samples-- > 0) { - s->buf[pos] = lsbf ? ff_reverse[*src] : *src; + buf[pos] = lsbf ? ff_reverse[*src] : *src; src += src_stride; - p = s->buf + ((pos - CTABLES) & FIFOMASK); + p = buf + ((pos - CTABLES) & FIFOMASK); *p = ff_reverse[*p]; sum = 0.0; for (i = 0; i < CTABLES; i++) { - unsigned char a = s->buf[(pos - i) & FIFOMASK]; - unsigned char b = s->buf[(pos - (CTABLES*2 - 1) + i) & FIFOMASK]; + uint8_t a = buf[(pos - i) & FIFOMASK]; + uint8_t b = buf[(pos - (CTABLES*2 - 1) + i) & FIFOMASK]; sum += ctables[i][a] + ctables[i][b]; } @@ -83,4 +84,5 @@ } s->pos = pos; + memcpy(s->buf, buf, sizeof(buf)); } diff -Nru ffmpeg-4.2.2/libavcodec/dsddec.c ffmpeg-4.4/libavcodec/dsddec.c --- ffmpeg-4.2.2/libavcodec/dsddec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dsddec.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,11 +27,11 @@ */ #include "libavcodec/internal.h" -#include "libavcodec/mathops.h" #include "avcodec.h" #include "dsd.h" #define DSD_SILENCE 0x69 +#define DSD_SILENCE_REVERSED 0x96 /* 0x69 = 01101001 * This pattern "on repeat" makes a low energy 352.8 kHz tone * and a high energy 1.0584 MHz tone which should be filtered @@ -44,13 +44,16 @@ int i; uint8_t silence; + if (!avctx->channels) + return AVERROR_INVALIDDATA; + ff_init_dsd_data(); s = av_malloc_array(sizeof(DSDContext), avctx->channels); if (!s) return AVERROR(ENOMEM); - silence = avctx->codec_id == AV_CODEC_ID_DSD_LSBF || avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR ? ff_reverse[DSD_SILENCE] : DSD_SILENCE; + silence = avctx->codec_id == AV_CODEC_ID_DSD_LSBF || avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR ? DSD_SILENCE_REVERSED : DSD_SILENCE; for (i = 0; i < avctx->channels; i++) { s[i].pos = 0; memset(s[i].buf, silence, sizeof(s[i].buf)); @@ -61,17 +64,20 @@ return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, - int *got_frame_ptr, AVPacket *avpkt) +typedef struct ThreadData { + AVFrame *frame; + const AVPacket *avpkt; +} ThreadData; + +static int dsd_channel(AVCodecContext *avctx, void *tdata, int j, int threadnr) { - DSDContext * s = avctx->priv_data; - AVFrame *frame = data; - int ret, i; int lsbf = avctx->codec_id == AV_CODEC_ID_DSD_LSBF || avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR; - int src_next; - int src_stride; - - frame->nb_samples = avpkt->size / avctx->channels; + DSDContext *s = avctx->priv_data; + ThreadData *td = tdata; + AVFrame *frame = td->frame; + const AVPacket *avpkt = td->avpkt; + int src_next, src_stride; + float *dst = ((float **)frame->extended_data)[j]; if (avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR || avctx->codec_id == AV_CODEC_ID_DSD_MSBF_PLANAR) { src_next = frame->nb_samples; @@ -81,15 +87,28 @@ src_stride = avctx->channels; } + ff_dsd2pcm_translate(&s[j], frame->nb_samples, lsbf, + avpkt->data + j * src_next, src_stride, + dst, 1); + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + ThreadData td; + AVFrame *frame = data; + int ret; + + frame->nb_samples = avpkt->size / avctx->channels; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - for (i = 0; i < avctx->channels; i++) { - float * dst = ((float **)frame->extended_data)[i]; - ff_dsd2pcm_translate(&s[i], frame->nb_samples, lsbf, - avpkt->data + i * src_next, src_stride, - dst, 1); - } + td.frame = frame; + td.avpkt = avpkt; + avctx->execute2(avctx, dsd_channel, &td, NULL, avctx->channels); *got_frame_ptr = 1; return frame->nb_samples * avctx->channels; @@ -103,8 +122,10 @@ .id = AV_CODEC_ID_##id_, \ .init = decode_init, \ .decode = decode_frame, \ + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, \ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, \ AV_SAMPLE_FMT_NONE }, \ + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \ }; DSD_DECODER(DSD_LSBF, dsd_lsbf, "DSD (Direct Stream Digital), least significant bit first") diff -Nru ffmpeg-4.2.2/libavcodec/dsd.h ffmpeg-4.4/libavcodec/dsd.h --- ffmpeg-4.2.2/libavcodec/dsd.h 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dsd.h 2020-07-11 10:39:30.000000000 +0000 @@ -40,13 +40,13 @@ * Per-channel buffer */ typedef struct DSDContext { - unsigned char buf[FIFOSIZE]; + uint8_t buf[FIFOSIZE]; unsigned pos; } DSDContext; void ff_init_dsd_data(void); void ff_dsd2pcm_translate(DSDContext* s, size_t samples, int lsbf, - const unsigned char *src, ptrdiff_t src_stride, + const uint8_t *src, ptrdiff_t src_stride, float *dst, ptrdiff_t dst_stride); #endif /* AVCODEC_DSD_H */ diff -Nru ffmpeg-4.2.2/libavcodec/dsicinaudio.c ffmpeg-4.4/libavcodec/dsicinaudio.c --- ffmpeg-4.2.2/libavcodec/dsicinaudio.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dsicinaudio.c 2021-04-08 21:28:39.000000000 +0000 @@ -129,5 +129,5 @@ .priv_data_size = sizeof(CinAudioContext), .init = cinaudio_decode_init, .decode = cinaudio_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; diff -Nru ffmpeg-4.2.2/libavcodec/dsicinvideo.c ffmpeg-4.4/libavcodec/dsicinvideo.c --- ffmpeg-4.2.2/libavcodec/dsicinvideo.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dsicinvideo.c 2021-04-08 21:28:39.000000000 +0000 @@ -58,7 +58,6 @@ cin->bitmap_table[i] = av_mallocz(cin->bitmap_size); if (!cin->bitmap_table[i]) { av_log(cin->avctx, AV_LOG_ERROR, "Can't allocate bitmap buffers.\n"); - destroy_buffers(cin); return AVERROR(ENOMEM); } } @@ -290,7 +289,7 @@ break; } - if ((res = ff_reget_buffer(avctx, cin->frame)) < 0) + if ((res = ff_reget_buffer(avctx, cin->frame, 0)) < 0) return res; memcpy(cin->frame->data[1], cin->palette, sizeof(cin->palette)); diff -Nru ffmpeg-4.2.2/libavcodec/dss_sp.c ffmpeg-4.4/libavcodec/dss_sp.c --- ffmpeg-4.2.2/libavcodec/dss_sp.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dss_sp.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "avcodec.h" @@ -781,5 +782,5 @@ .priv_data_size = sizeof(DssSpContext), .init = dss_sp_decode_init, .decode = dss_sp_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; diff -Nru ffmpeg-4.2.2/libavcodec/dstdec.c ffmpeg-4.4/libavcodec/dstdec.c --- ffmpeg-4.2.2/libavcodec/dstdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dstdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ #include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #include "internal.h" #include "get_bits.h" #include "avcodec.h" @@ -85,6 +86,16 @@ return AVERROR_PATCHWELCOME; } + // the sample rate is only allowed to be 64,128,256 * 44100 by ISO/IEC 14496-3:2005(E) + // We are a bit more tolerant here, but this check is needed to bound the size and duration + if (avctx->sample_rate > 512 * 44100) + return AVERROR_INVALIDDATA; + + + if (DST_SAMPLES_PER_FRAME(avctx->sample_rate) & 7) { + return AVERROR_PATCHWELCOME; + } + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; for (i = 0; i < avctx->channels; i++) @@ -155,7 +166,7 @@ for (j = method + 1; j < t->length[i]; j++) { int c, x = 0; for (k = 0; k < method + 1; k++) - x += code_pred_coeff[method][k] * t->coeff[i][j - k - 1]; + x += code_pred_coeff[method][k] * (unsigned)t->coeff[i][j - k - 1]; c = get_sr_golomb_dst(gb, lsb_size); if (x >= 0) c -= (x + 4) / 8; @@ -258,7 +269,7 @@ skip_bits1(gb); if (get_bits(gb, 6)) return AVERROR_INVALIDDATA; - memcpy(frame->data[0], avpkt->data + 1, FFMIN(avpkt->size - 1, frame->nb_samples * avctx->channels)); + memcpy(frame->data[0], avpkt->data + 1, FFMIN(avpkt->size - 1, frame->nb_samples * channels)); goto dsd; } @@ -283,7 +294,7 @@ same_map = get_bits1(gb); - if ((ret = read_map(gb, &s->fsets, map_ch_to_felem, avctx->channels)) < 0) + if ((ret = read_map(gb, &s->fsets, map_ch_to_felem, channels)) < 0) return ret; if (same_map) { @@ -291,13 +302,13 @@ memcpy(map_ch_to_pelem, map_ch_to_felem, sizeof(map_ch_to_felem)); } else { avpriv_request_sample(avctx, "Not Same Mapping"); - if ((ret = read_map(gb, &s->probs, map_ch_to_pelem, avctx->channels)) < 0) + if ((ret = read_map(gb, &s->probs, map_ch_to_pelem, channels)) < 0) return ret; } /* Half Probability (10.10) */ - for (ch = 0; ch < avctx->channels; ch++) + for (ch = 0; ch < channels; ch++) half_prob[ch] = get_bits1(gb); /* Filter Coef Sets (10.12) */ @@ -321,7 +332,7 @@ build_filter(s->filter, &s->fsets); memset(s->status, 0xAA, sizeof(s->status)); - memset(dsd, 0, frame->nb_samples * 4 * avctx->channels); + memset(dsd, 0, frame->nb_samples * 4 * channels); ac_get(ac, gb, prob_dst_x_bit(s->fsets.coeff[0][0]), &dst_x_bit); @@ -357,10 +368,10 @@ } dsd: - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < channels; i++) { ff_dsd2pcm_translate(&s->dsdctx[i], frame->nb_samples, 0, frame->data[0] + i * 4, - avctx->channels * 4, pcm + i, avctx->channels); + channels * 4, pcm + i, channels); } *got_frame_ptr = 1; @@ -379,4 +390,5 @@ .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/dump_extradata_bsf.c ffmpeg-4.4/libavcodec/dump_extradata_bsf.c --- ffmpeg-4.2.2/libavcodec/dump_extradata_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dump_extradata_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -20,11 +20,10 @@ #include -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "libavutil/log.h" -#include "libavutil/mem.h" #include "libavutil/opt.h" enum DumpFreq { @@ -51,8 +50,8 @@ if (ctx->par_in->extradata && (s->freq == DUMP_FREQ_ALL || (s->freq == DUMP_FREQ_KEYFRAME && in->flags & AV_PKT_FLAG_KEY)) && - in->size >= ctx->par_in->extradata_size && - memcmp(in->data, ctx->par_in->extradata, ctx->par_in->extradata_size)) { + (in->size < ctx->par_in->extradata_size || + memcmp(in->data, ctx->par_in->extradata, ctx->par_in->extradata_size))) { if (in->size >= INT_MAX - ctx->par_in->extradata_size) { ret = AVERROR(ERANGE); goto fail; diff -Nru ffmpeg-4.2.2/libavcodec/dvbsub.c ffmpeg-4.4/libavcodec/dvbsub.c --- ffmpeg-4.2.2/libavcodec/dvbsub.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dvbsub.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,476 +0,0 @@ -/* - * DVB subtitle encoding - * Copyright (c) 2005 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 "avcodec.h" -#include "bytestream.h" -#include "libavutil/colorspace.h" - -typedef struct DVBSubtitleContext { - int object_version; -} DVBSubtitleContext; - -#define PUTBITS2(val)\ -{\ - bitbuf |= (val) << bitcnt;\ - bitcnt -= 2;\ - if (bitcnt < 0) {\ - bitcnt = 6;\ - *q++ = bitbuf;\ - bitbuf = 0;\ - }\ -} - -static void dvb_encode_rle2(uint8_t **pq, - const uint8_t *bitmap, int linesize, - int w, int h) -{ - uint8_t *q; - unsigned int bitbuf; - int bitcnt; - int x, y, len, x1, v, color; - - q = *pq; - - for(y = 0; y < h; y++) { - *q++ = 0x10; - bitbuf = 0; - bitcnt = 6; - - x = 0; - while (x < w) { - x1 = x; - color = bitmap[x1++]; - while (x1 < w && bitmap[x1] == color) - x1++; - len = x1 - x; - if (color == 0 && len == 2) { - PUTBITS2(0); - PUTBITS2(0); - PUTBITS2(1); - } else if (len >= 3 && len <= 10) { - v = len - 3; - PUTBITS2(0); - PUTBITS2((v >> 2) | 2); - PUTBITS2(v & 3); - PUTBITS2(color); - } else if (len >= 12 && len <= 27) { - v = len - 12; - PUTBITS2(0); - PUTBITS2(0); - PUTBITS2(2); - PUTBITS2(v >> 2); - PUTBITS2(v & 3); - PUTBITS2(color); - } else if (len >= 29) { - /* length = 29 ... 284 */ - if (len > 284) - len = 284; - v = len - 29; - PUTBITS2(0); - PUTBITS2(0); - PUTBITS2(3); - PUTBITS2((v >> 6)); - PUTBITS2((v >> 4) & 3); - PUTBITS2((v >> 2) & 3); - PUTBITS2(v & 3); - PUTBITS2(color); - } else { - PUTBITS2(color); - if (color == 0) { - PUTBITS2(1); - } - len = 1; - } - x += len; - } - /* end of line */ - PUTBITS2(0); - PUTBITS2(0); - PUTBITS2(0); - if (bitcnt != 6) { - *q++ = bitbuf; - } - *q++ = 0xf0; - bitmap += linesize; - } - *pq = q; -} - -#define PUTBITS4(val)\ -{\ - bitbuf |= (val) << bitcnt;\ - bitcnt -= 4;\ - if (bitcnt < 0) {\ - bitcnt = 4;\ - *q++ = bitbuf;\ - bitbuf = 0;\ - }\ -} - -/* some DVB decoders only implement 4 bits/pixel */ -static void dvb_encode_rle4(uint8_t **pq, - const uint8_t *bitmap, int linesize, - int w, int h) -{ - uint8_t *q; - unsigned int bitbuf; - int bitcnt; - int x, y, len, x1, v, color; - - q = *pq; - - for(y = 0; y < h; y++) { - *q++ = 0x11; - bitbuf = 0; - bitcnt = 4; - - x = 0; - while (x < w) { - x1 = x; - color = bitmap[x1++]; - while (x1 < w && bitmap[x1] == color) - x1++; - len = x1 - x; - if (color == 0 && len == 2) { - PUTBITS4(0); - PUTBITS4(0xd); - } else if (color == 0 && (len >= 3 && len <= 9)) { - PUTBITS4(0); - PUTBITS4(len - 2); - } else if (len >= 4 && len <= 7) { - PUTBITS4(0); - PUTBITS4(8 + len - 4); - PUTBITS4(color); - } else if (len >= 9 && len <= 24) { - PUTBITS4(0); - PUTBITS4(0xe); - PUTBITS4(len - 9); - PUTBITS4(color); - } else if (len >= 25) { - if (len > 280) - len = 280; - v = len - 25; - PUTBITS4(0); - PUTBITS4(0xf); - PUTBITS4(v >> 4); - PUTBITS4(v & 0xf); - PUTBITS4(color); - } else { - PUTBITS4(color); - if (color == 0) { - PUTBITS4(0xc); - } - len = 1; - } - x += len; - } - /* end of line */ - PUTBITS4(0); - PUTBITS4(0); - if (bitcnt != 4) { - *q++ = bitbuf; - } - *q++ = 0xf0; - bitmap += linesize; - } - *pq = q; -} - -static void dvb_encode_rle8(uint8_t **pq, - const uint8_t *bitmap, int linesize, - int w, int h) -{ - uint8_t *q; - int x, y, len, x1, color; - - q = *pq; - - for (y = 0; y < h; y++) { - *q++ = 0x12; - - x = 0; - while (x < w) { - x1 = x; - color = bitmap[x1++]; - while (x1 < w && bitmap[x1] == color) - x1++; - len = x1 - x; - if (len == 1 && color) { - // 00000001 to 11111111 1 pixel in colour x - *q++ = color; - } else { - if (color == 0x00) { - // 00000000 0LLLLLLL L pixels (1-127) in colour 0 (L > 0) - len = FFMIN(len, 127); - *q++ = 0x00; - *q++ = len; - } else if (len > 2) { - // 00000000 1LLLLLLL CCCCCCCC L pixels (3-127) in colour C (L > 2) - len = FFMIN(len, 127); - *q++ = 0x00; - *q++ = 0x80+len; - *q++ = color; - } - else if (len == 2) { - *q++ = color; - *q++ = color; - } else { - *q++ = color; - len = 1; - } - } - x += len; - } - /* end of line */ - // 00000000 end of 8-bit/pixel_code_string - *q++ = 0x00; - *q++ = 0xf0; - bitmap += linesize; - } - *pq = q; -} - -static int encode_dvb_subtitles(AVCodecContext *avctx, - uint8_t *outbuf, const AVSubtitle *h) -{ - DVBSubtitleContext *s = avctx->priv_data; - uint8_t *q, *pseg_len; - int page_id, region_id, clut_id, object_id, i, bpp_index, page_state; - - - q = outbuf; - - page_id = 1; - - if (h->num_rects && !h->rects) - return -1; - - if (avctx->width > 0 && avctx->height > 0) { - /* display definition segment */ - *q++ = 0x0f; /* sync_byte */ - *q++ = 0x14; /* segment_type */ - bytestream_put_be16(&q, page_id); - pseg_len = q; - q += 2; /* segment length */ - *q++ = 0x00; /* dds version number & display window flag */ - bytestream_put_be16(&q, avctx->width - 1); /* display width */ - bytestream_put_be16(&q, avctx->height - 1); /* display height */ - bytestream_put_be16(&pseg_len, q - pseg_len - 2); - } - - /* page composition segment */ - - *q++ = 0x0f; /* sync_byte */ - *q++ = 0x10; /* segment_type */ - bytestream_put_be16(&q, page_id); - pseg_len = q; - q += 2; /* segment length */ - *q++ = 30; /* page_timeout (seconds) */ - page_state = 2; /* mode change */ - /* page_version = 0 + page_state */ - *q++ = (s->object_version << 4) | (page_state << 2) | 3; - - for (region_id = 0; region_id < h->num_rects; region_id++) { - *q++ = region_id; - *q++ = 0xff; /* reserved */ - bytestream_put_be16(&q, h->rects[region_id]->x); /* left pos */ - bytestream_put_be16(&q, h->rects[region_id]->y); /* top pos */ - } - - bytestream_put_be16(&pseg_len, q - pseg_len - 2); - - if (h->num_rects) { - for (clut_id = 0; clut_id < h->num_rects; clut_id++) { - - /* CLUT segment */ - - if (h->rects[clut_id]->nb_colors <= 4) { - /* 2 bpp, some decoders do not support it correctly */ - bpp_index = 0; - } else if (h->rects[clut_id]->nb_colors <= 16) { - /* 4 bpp, standard encoding */ - bpp_index = 1; - } else if (h->rects[clut_id]->nb_colors <= 256) { - /* 8 bpp, standard encoding */ - bpp_index = 2; - } else { - return -1; - } - - - /* CLUT segment */ - *q++ = 0x0f; /* sync byte */ - *q++ = 0x12; /* CLUT definition segment */ - bytestream_put_be16(&q, page_id); - pseg_len = q; - q += 2; /* segment length */ - *q++ = clut_id; - *q++ = (0 << 4) | 0xf; /* version = 0 */ - - for(i = 0; i < h->rects[clut_id]->nb_colors; i++) { - *q++ = i; /* clut_entry_id */ - *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */ - { - int a, r, g, b; - uint32_t x= ((uint32_t*)h->rects[clut_id]->data[1])[i]; - a = (x >> 24) & 0xff; - r = (x >> 16) & 0xff; - g = (x >> 8) & 0xff; - b = (x >> 0) & 0xff; - - *q++ = RGB_TO_Y_CCIR(r, g, b); - *q++ = RGB_TO_V_CCIR(r, g, b, 0); - *q++ = RGB_TO_U_CCIR(r, g, b, 0); - *q++ = 255 - a; - } - } - - bytestream_put_be16(&pseg_len, q - pseg_len - 2); - } - } - - for (region_id = 0; region_id < h->num_rects; region_id++) { - - /* region composition segment */ - - if (h->rects[region_id]->nb_colors <= 4) { - /* 2 bpp, some decoders do not support it correctly */ - bpp_index = 0; - } else if (h->rects[region_id]->nb_colors <= 16) { - /* 4 bpp, standard encoding */ - bpp_index = 1; - } else if (h->rects[region_id]->nb_colors <= 256) { - /* 8 bpp, standard encoding */ - bpp_index = 2; - } else { - return -1; - } - - *q++ = 0x0f; /* sync_byte */ - *q++ = 0x11; /* segment_type */ - bytestream_put_be16(&q, page_id); - pseg_len = q; - q += 2; /* segment length */ - *q++ = region_id; - *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */ - bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */ - bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */ - *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03; - *q++ = region_id; /* clut_id == region_id */ - *q++ = 0; /* 8 bit fill colors */ - *q++ = 0x03; /* 4 bit and 2 bit fill colors */ - - bytestream_put_be16(&q, region_id); /* object_id == region_id */ - *q++ = (0 << 6) | (0 << 4); - *q++ = 0; - *q++ = 0xf0; - *q++ = 0; - - bytestream_put_be16(&pseg_len, q - pseg_len - 2); - } - - if (h->num_rects) { - - for (object_id = 0; object_id < h->num_rects; object_id++) { - void (*dvb_encode_rle)(uint8_t **pq, - const uint8_t *bitmap, int linesize, - int w, int h); - - /* bpp_index maths */ - if (h->rects[object_id]->nb_colors <= 4) { - /* 2 bpp, some decoders do not support it correctly */ - dvb_encode_rle = dvb_encode_rle2; - } else if (h->rects[object_id]->nb_colors <= 16) { - /* 4 bpp, standard encoding */ - dvb_encode_rle = dvb_encode_rle4; - } else if (h->rects[object_id]->nb_colors <= 256) { - /* 8 bpp, standard encoding */ - dvb_encode_rle = dvb_encode_rle8; - } else { - return -1; - } - - /* Object Data segment */ - *q++ = 0x0f; /* sync byte */ - *q++ = 0x13; - bytestream_put_be16(&q, page_id); - pseg_len = q; - q += 2; /* segment length */ - - bytestream_put_be16(&q, object_id); - *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0, - onject_coding_method, - non_modifying_color_flag */ - { - uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr; - - ptop_field_len = q; - q += 2; - pbottom_field_len = q; - q += 2; - - top_ptr = q; - dvb_encode_rle(&q, h->rects[object_id]->data[0], h->rects[object_id]->w * 2, - h->rects[object_id]->w, h->rects[object_id]->h >> 1); - bottom_ptr = q; - dvb_encode_rle(&q, h->rects[object_id]->data[0] + h->rects[object_id]->w, - h->rects[object_id]->w * 2, h->rects[object_id]->w, - h->rects[object_id]->h >> 1); - - bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr); - bytestream_put_be16(&pbottom_field_len, q - bottom_ptr); - } - - bytestream_put_be16(&pseg_len, q - pseg_len - 2); - } - } - - /* end of display set segment */ - - *q++ = 0x0f; /* sync_byte */ - *q++ = 0x80; /* segment_type */ - bytestream_put_be16(&q, page_id); - pseg_len = q; - q += 2; /* segment length */ - - bytestream_put_be16(&pseg_len, q - pseg_len - 2); - - s->object_version = (s->object_version + 1) & 0xf; - return q - outbuf; -} - -static int dvbsub_encode(AVCodecContext *avctx, - unsigned char *buf, int buf_size, - const AVSubtitle *sub) -{ - int ret; - - ret = encode_dvb_subtitles(avctx, buf, sub); - return ret; -} - -AVCodec ff_dvbsub_encoder = { - .name = "dvbsub", - .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_DVB_SUBTITLE, - .priv_data_size = sizeof(DVBSubtitleContext), - .encode_sub = dvbsub_encode, -}; diff -Nru ffmpeg-4.2.2/libavcodec/dvbsubdec.c ffmpeg-4.4/libavcodec/dvbsubdec.c --- ffmpeg-4.2.2/libavcodec/dvbsubdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dvbsubdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -710,8 +710,8 @@ } count = FFMAX(i - 1, 1); - for (i--; i>=0; i--) { - int v = i*255/count; + for (i--; i >= 0; i--) { + int v = i * 255 / count; AV_WN32(clut + 4*list_inv[i], RGBA(v/2,v,v/2,v)); } } @@ -737,7 +737,7 @@ } /* Not touching AVSubtitles again*/ - if(sub->num_rects) { + if (sub->num_rects) { avpriv_request_sample(ctx, "Different Version of Segment asked Twice"); return AVERROR_PATCHWELCOME; } @@ -747,7 +747,7 @@ sub->num_rects++; } - if(ctx->compute_edt == 0) { + if (ctx->compute_edt == 0) { sub->end_display_time = ctx->time_out * 1000; *got_output = 1; } else if (ctx->prev_start != AV_NOPTS_VALUE) { @@ -813,7 +813,7 @@ ret = AVERROR(ENOMEM); goto fail; } - memcpy(rect->data[1], clut_table, (1 << region->depth) * sizeof(uint32_t)); + memcpy(rect->data[1], clut_table, (1 << region->depth) * sizeof(*clut_table)); rect->data[0] = av_malloc(region->buf_size); if (!rect->data[0]) { @@ -851,7 +851,7 @@ return 0; fail: if (sub->rects) { - for(i=0; inum_rects; i++) { + for (i=0; i < sub->num_rects; i++) { rect = sub->rects[i]; if (rect) { av_freep(&rect->data[0]); @@ -1032,11 +1032,15 @@ dvbsub_parse_pixel_data_block(avctx, display, block, bfl, 1, non_modifying_color); } - -/* } else if (coding_method == 1) {*/ - + } else if (coding_method == 1) { + avpriv_report_missing_feature(avctx, "coded as a string of characters"); + return AVERROR_PATCHWELCOME; + } else if (coding_method == 2) { + avpriv_report_missing_feature(avctx, "progressive coding of pixels"); + return AVERROR_PATCHWELCOME; } else { av_log(avctx, AV_LOG_ERROR, "Unknown object coding %d\n", coding_method); + return AVERROR_INVALIDDATA; } return 0; @@ -1073,11 +1077,11 @@ clut = get_clut(ctx, clut_id); if (!clut) { - clut = av_malloc(sizeof(DVBSubCLUT)); + clut = av_malloc(sizeof(*clut)); if (!clut) return AVERROR(ENOMEM); - memcpy(clut, &default_clut, sizeof(DVBSubCLUT)); + memcpy(clut, &default_clut, sizeof(*clut)); clut->id = clut_id; clut->version = -1; @@ -1088,53 +1092,53 @@ if (clut->version != version) { - clut->version = version; + clut->version = version; - while (buf + 4 < buf_end) { - entry_id = *buf++; + while (buf + 4 < buf_end) { + entry_id = *buf++; - depth = (*buf) & 0xe0; + depth = (*buf) & 0xe0; - if (depth == 0) { - av_log(avctx, AV_LOG_ERROR, "Invalid clut depth 0x%x!\n", *buf); - } + if (depth == 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid clut depth 0x%x!\n", *buf); + } - full_range = (*buf++) & 1; + full_range = (*buf++) & 1; - if (full_range) { - y = *buf++; - cr = *buf++; - cb = *buf++; - alpha = *buf++; - } else { - y = buf[0] & 0xfc; - cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4; - cb = (buf[1] << 2) & 0xf0; - alpha = (buf[1] << 6) & 0xc0; + if (full_range) { + y = *buf++; + cr = *buf++; + cb = *buf++; + alpha = *buf++; + } else { + y = buf[0] & 0xfc; + cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4; + cb = (buf[1] << 2) & 0xf0; + alpha = (buf[1] << 6) & 0xc0; - buf += 2; - } + buf += 2; + } - if (y == 0) - alpha = 0xff; + if (y == 0) + alpha = 0xff; - YUV_TO_RGB1_CCIR(cb, cr); - YUV_TO_RGB2_CCIR(r, g, b, y); + YUV_TO_RGB1_CCIR(cb, cr); + YUV_TO_RGB2_CCIR(r, g, b, y); - ff_dlog(avctx, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha); - if (!!(depth & 0x80) + !!(depth & 0x40) + !!(depth & 0x20) > 1) { - ff_dlog(avctx, "More than one bit level marked: %x\n", depth); - if (avctx->strict_std_compliance > FF_COMPLIANCE_NORMAL) - return AVERROR_INVALIDDATA; - } + ff_dlog(avctx, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha); + if (!!(depth & 0x80) + !!(depth & 0x40) + !!(depth & 0x20) > 1) { + ff_dlog(avctx, "More than one bit level marked: %x\n", depth); + if (avctx->strict_std_compliance > FF_COMPLIANCE_NORMAL) + return AVERROR_INVALIDDATA; + } - if (depth & 0x80 && entry_id < 4) - clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha); - else if (depth & 0x40 && entry_id < 16) - clut->clut16[entry_id] = RGBA(r,g,b,255 - alpha); - else if (depth & 0x20) - clut->clut256[entry_id] = RGBA(r,g,b,255 - alpha); - } + if (depth & 0x80 && entry_id < 4) + clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha); + else if (depth & 0x40 && entry_id < 16) + clut->clut16[entry_id] = RGBA(r,g,b,255 - alpha); + else if (depth & 0x20) + clut->clut256[entry_id] = RGBA(r,g,b,255 - alpha); + } } return 0; @@ -1163,7 +1167,7 @@ region = get_region(ctx, region_id); if (!region) { - region = av_mallocz(sizeof(DVBSubRegion)); + region = av_mallocz(sizeof(*region)); if (!region) return AVERROR(ENOMEM); @@ -1210,7 +1214,7 @@ } region->depth = 1 << (((*buf++) >> 2) & 7); - if(region->depth<2 || region->depth>8){ + if (region->depth < 2 || region->depth > 8) { av_log(avctx, AV_LOG_ERROR, "region depth %d is invalid\n", region->depth); region->depth= 4; } @@ -1244,7 +1248,7 @@ object = get_object(ctx, object_id); if (!object) { - object = av_mallocz(sizeof(DVBSubObject)); + object = av_mallocz(sizeof(*object)); if (!object) return AVERROR(ENOMEM); @@ -1255,7 +1259,7 @@ object->type = (*buf) >> 6; - display = av_mallocz(sizeof(DVBSubObjectDisplay)); + display = av_mallocz(sizeof(*display)); if (!display) return AVERROR(ENOMEM); @@ -1318,7 +1322,7 @@ ff_dlog(avctx, "Page time out %ds, state %d\n", ctx->time_out, page_state); - if(ctx->compute_edt == 1) + if (ctx->compute_edt == 1) save_subtitle_set(avctx, sub, got_output); if (page_state == 1 || page_state == 2) { @@ -1352,7 +1356,7 @@ } if (!display) { - display = av_mallocz(sizeof(DVBSubRegionDisplay)); + display = av_mallocz(sizeof(*display)); if (!display) return AVERROR(ENOMEM); } @@ -1601,7 +1605,7 @@ { DVBSubContext *ctx = avctx->priv_data; - if(ctx->compute_edt == 0) + if (ctx->compute_edt == 0) save_subtitle_set(avctx, sub, got_output); #ifdef DEBUG save_display_set(ctx); @@ -1610,7 +1614,7 @@ } static int dvbsub_decode(AVCodecContext *avctx, - void *data, int *data_size, + void *data, int *got_sub_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; @@ -1668,7 +1672,7 @@ int ret = 0; switch (segment_type) { case DVBSUB_PAGE_SEGMENT: - ret = dvbsub_parse_page_segment(avctx, p, segment_length, sub, data_size); + ret = dvbsub_parse_page_segment(avctx, p, segment_length, sub, got_sub_ptr); got_segment |= 1; break; case DVBSUB_REGION_SEGMENT: @@ -1690,7 +1694,7 @@ got_dds = 1; break; case DVBSUB_DISPLAY_SEGMENT: - ret = dvbsub_display_end_segment(avctx, p, segment_length, sub, data_size); + ret = dvbsub_display_end_segment(avctx, p, segment_length, sub, got_sub_ptr); if (got_segment == 15 && !got_dds && !avctx->width && !avctx->height) { // Default from ETSI EN 300 743 V1.3.1 (7.2.1) avctx->width = 720; @@ -1713,16 +1717,16 @@ // segments then we need no further data. if (got_segment == 15) { av_log(avctx, AV_LOG_DEBUG, "Missing display_end_segment, emulating\n"); - dvbsub_display_end_segment(avctx, p, 0, sub, data_size); + dvbsub_display_end_segment(avctx, p, 0, sub, got_sub_ptr); } end: - if(ret < 0) { - *data_size = 0; + if (ret < 0) { + *got_sub_ptr = 0; avsubtitle_free(sub); return ret; } else { - if(ctx->compute_edt == 1 ) + if (ctx->compute_edt == 1) FFSWAP(int64_t, ctx->prev_start, sub->pts); } @@ -1730,10 +1734,11 @@ } #define DS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_SUBTITLE_PARAM +#define OFFSET(x) offsetof(DVBSubContext, x) static const AVOption options[] = { - {"compute_edt", "compute end of time using pts or timeout", offsetof(DVBSubContext, compute_edt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DS}, - {"compute_clut", "compute clut when not available(-1) or always(1) or never(0)", offsetof(DVBSubContext, compute_clut), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, DS}, - {"dvb_substream", "", offsetof(DVBSubContext, substream), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 63, DS}, + {"compute_edt", "compute end of time using pts or timeout", OFFSET(compute_edt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DS}, + {"compute_clut", "compute clut when not available(-1) or always(1) or never(0)", OFFSET(compute_clut), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, DS}, + {"dvb_substream", "", OFFSET(substream), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 63, DS}, {NULL} }; static const AVClass dvbsubdec_class = { diff -Nru ffmpeg-4.2.2/libavcodec/dvbsubenc.c ffmpeg-4.4/libavcodec/dvbsubenc.c --- ffmpeg-4.2.2/libavcodec/dvbsubenc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dvbsubenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,515 @@ +/* + * DVB subtitle encoding + * Copyright (c) 2005 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 "avcodec.h" +#include "bytestream.h" +#include "libavutil/colorspace.h" + +typedef struct DVBSubtitleContext { + int object_version; +} DVBSubtitleContext; + +#define PUTBITS2(val)\ +{\ + bitbuf |= (val) << bitcnt;\ + bitcnt -= 2;\ + if (bitcnt < 0) {\ + bitcnt = 6;\ + *q++ = bitbuf;\ + bitbuf = 0;\ + }\ +} + +static int dvb_encode_rle2(uint8_t **pq, int buf_size, + const uint8_t *bitmap, int linesize, + int w, int h) +{ + uint8_t *q, *line_begin; + unsigned int bitbuf; + int bitcnt; + int x, y, len, x1, v, color; + + q = *pq; + + for(y = 0; y < h; y++) { + // Worst case line is 3 bits per value + 4 bytes overhead + if (buf_size * 8 < w * 3 + 32) + return AVERROR_BUFFER_TOO_SMALL; + line_begin = q; + *q++ = 0x10; + bitbuf = 0; + bitcnt = 6; + + x = 0; + while (x < w) { + x1 = x; + color = bitmap[x1++]; + while (x1 < w && bitmap[x1] == color) + x1++; + len = x1 - x; + if (color == 0 && len == 2) { + PUTBITS2(0); + PUTBITS2(0); + PUTBITS2(1); + } else if (len >= 3 && len <= 10) { + v = len - 3; + PUTBITS2(0); + PUTBITS2((v >> 2) | 2); + PUTBITS2(v & 3); + PUTBITS2(color); + } else if (len >= 12 && len <= 27) { + v = len - 12; + PUTBITS2(0); + PUTBITS2(0); + PUTBITS2(2); + PUTBITS2(v >> 2); + PUTBITS2(v & 3); + PUTBITS2(color); + } else if (len >= 29) { + /* length = 29 ... 284 */ + if (len > 284) + len = 284; + v = len - 29; + PUTBITS2(0); + PUTBITS2(0); + PUTBITS2(3); + PUTBITS2((v >> 6)); + PUTBITS2((v >> 4) & 3); + PUTBITS2((v >> 2) & 3); + PUTBITS2(v & 3); + PUTBITS2(color); + } else { + PUTBITS2(color); + if (color == 0) { + PUTBITS2(1); + } + len = 1; + } + x += len; + } + /* end of line */ + PUTBITS2(0); + PUTBITS2(0); + PUTBITS2(0); + if (bitcnt != 6) { + *q++ = bitbuf; + } + *q++ = 0xf0; + bitmap += linesize; + buf_size -= q - line_begin; + } + len = q - *pq; + *pq = q; + return len; +} + +#define PUTBITS4(val)\ +{\ + bitbuf |= (val) << bitcnt;\ + bitcnt -= 4;\ + if (bitcnt < 0) {\ + bitcnt = 4;\ + *q++ = bitbuf;\ + bitbuf = 0;\ + }\ +} + +/* some DVB decoders only implement 4 bits/pixel */ +static int dvb_encode_rle4(uint8_t **pq, int buf_size, + const uint8_t *bitmap, int linesize, + int w, int h) +{ + uint8_t *q, *line_begin; + unsigned int bitbuf; + int bitcnt; + int x, y, len, x1, v, color; + + q = *pq; + + for(y = 0; y < h; y++) { + // Worst case line is 6 bits per value, + 4 bytes overhead + if (buf_size * 8 < w * 6 + 32) + return AVERROR_BUFFER_TOO_SMALL; + line_begin = q; + *q++ = 0x11; + bitbuf = 0; + bitcnt = 4; + + x = 0; + while (x < w) { + x1 = x; + color = bitmap[x1++]; + while (x1 < w && bitmap[x1] == color) + x1++; + len = x1 - x; + if (color == 0 && len == 2) { + PUTBITS4(0); + PUTBITS4(0xd); + } else if (color == 0 && (len >= 3 && len <= 9)) { + PUTBITS4(0); + PUTBITS4(len - 2); + } else if (len >= 4 && len <= 7) { + PUTBITS4(0); + PUTBITS4(8 + len - 4); + PUTBITS4(color); + } else if (len >= 9 && len <= 24) { + PUTBITS4(0); + PUTBITS4(0xe); + PUTBITS4(len - 9); + PUTBITS4(color); + } else if (len >= 25) { + if (len > 280) + len = 280; + v = len - 25; + PUTBITS4(0); + PUTBITS4(0xf); + PUTBITS4(v >> 4); + PUTBITS4(v & 0xf); + PUTBITS4(color); + } else { + PUTBITS4(color); + if (color == 0) { + PUTBITS4(0xc); + } + len = 1; + } + x += len; + } + /* end of line */ + PUTBITS4(0); + PUTBITS4(0); + if (bitcnt != 4) { + *q++ = bitbuf; + } + *q++ = 0xf0; + bitmap += linesize; + buf_size -= q - line_begin; + } + len = q - *pq; + *pq = q; + return len; +} + +static int dvb_encode_rle8(uint8_t **pq, int buf_size, + const uint8_t *bitmap, int linesize, + int w, int h) +{ + uint8_t *q, *line_begin; + int x, y, len, x1, color; + + q = *pq; + + for (y = 0; y < h; y++) { + // Worst case line is 12 bits per value, + 3 bytes overhead + if (buf_size * 8 < w * 12 + 24) + return AVERROR_BUFFER_TOO_SMALL; + line_begin = q; + *q++ = 0x12; + + x = 0; + while (x < w) { + x1 = x; + color = bitmap[x1++]; + while (x1 < w && bitmap[x1] == color) + x1++; + len = x1 - x; + if (len == 1 && color) { + // 00000001 to 11111111 1 pixel in colour x + *q++ = color; + } else { + if (color == 0x00) { + // 00000000 0LLLLLLL L pixels (1-127) in colour 0 (L > 0) + len = FFMIN(len, 127); + *q++ = 0x00; + *q++ = len; + } else if (len > 2) { + // 00000000 1LLLLLLL CCCCCCCC L pixels (3-127) in colour C (L > 2) + len = FFMIN(len, 127); + *q++ = 0x00; + *q++ = 0x80+len; + *q++ = color; + } + else if (len == 2) { + *q++ = color; + *q++ = color; + } else { + *q++ = color; + len = 1; + } + } + x += len; + } + /* end of line */ + // 00000000 end of 8-bit/pixel_code_string + *q++ = 0x00; + *q++ = 0xf0; + bitmap += linesize; + buf_size -= q - line_begin; + } + len = q - *pq; + *pq = q; + return len; +} + +static int dvbsub_encode(AVCodecContext *avctx, uint8_t *outbuf, int buf_size, + const AVSubtitle *h) +{ + DVBSubtitleContext *s = avctx->priv_data; + uint8_t *q, *pseg_len; + int page_id, region_id, clut_id, object_id, i, bpp_index, page_state; + + + q = outbuf; + + page_id = 1; + + if (h->num_rects && !h->rects) + return AVERROR(EINVAL); + + if (avctx->width > 0 && avctx->height > 0) { + if (buf_size < 11) + return AVERROR_BUFFER_TOO_SMALL; + /* display definition segment */ + *q++ = 0x0f; /* sync_byte */ + *q++ = 0x14; /* segment_type */ + bytestream_put_be16(&q, page_id); + pseg_len = q; + q += 2; /* segment length */ + *q++ = 0x00; /* dds version number & display window flag */ + bytestream_put_be16(&q, avctx->width - 1); /* display width */ + bytestream_put_be16(&q, avctx->height - 1); /* display height */ + bytestream_put_be16(&pseg_len, q - pseg_len - 2); + buf_size -= 11; + } + + /* page composition segment */ + + if (buf_size < 8 + h->num_rects * 6) + return AVERROR_BUFFER_TOO_SMALL; + *q++ = 0x0f; /* sync_byte */ + *q++ = 0x10; /* segment_type */ + bytestream_put_be16(&q, page_id); + pseg_len = q; + q += 2; /* segment length */ + *q++ = 30; /* page_timeout (seconds) */ + page_state = 2; /* mode change */ + /* page_version = 0 + page_state */ + *q++ = (s->object_version << 4) | (page_state << 2) | 3; + + for (region_id = 0; region_id < h->num_rects; region_id++) { + *q++ = region_id; + *q++ = 0xff; /* reserved */ + bytestream_put_be16(&q, h->rects[region_id]->x); /* left pos */ + bytestream_put_be16(&q, h->rects[region_id]->y); /* top pos */ + } + + bytestream_put_be16(&pseg_len, q - pseg_len - 2); + buf_size -= 8 + h->num_rects * 6; + + if (h->num_rects) { + for (clut_id = 0; clut_id < h->num_rects; clut_id++) { + if (buf_size < 6 + h->rects[clut_id]->nb_colors * 6) + return AVERROR_BUFFER_TOO_SMALL; + + /* CLUT segment */ + + if (h->rects[clut_id]->nb_colors <= 4) { + /* 2 bpp, some decoders do not support it correctly */ + bpp_index = 0; + } else if (h->rects[clut_id]->nb_colors <= 16) { + /* 4 bpp, standard encoding */ + bpp_index = 1; + } else if (h->rects[clut_id]->nb_colors <= 256) { + /* 8 bpp, standard encoding */ + bpp_index = 2; + } else { + return AVERROR(EINVAL); + } + + + /* CLUT segment */ + *q++ = 0x0f; /* sync byte */ + *q++ = 0x12; /* CLUT definition segment */ + bytestream_put_be16(&q, page_id); + pseg_len = q; + q += 2; /* segment length */ + *q++ = clut_id; + *q++ = (0 << 4) | 0xf; /* version = 0 */ + + for(i = 0; i < h->rects[clut_id]->nb_colors; i++) { + *q++ = i; /* clut_entry_id */ + *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */ + { + int a, r, g, b; + uint32_t x= ((uint32_t*)h->rects[clut_id]->data[1])[i]; + a = (x >> 24) & 0xff; + r = (x >> 16) & 0xff; + g = (x >> 8) & 0xff; + b = (x >> 0) & 0xff; + + *q++ = RGB_TO_Y_CCIR(r, g, b); + *q++ = RGB_TO_V_CCIR(r, g, b, 0); + *q++ = RGB_TO_U_CCIR(r, g, b, 0); + *q++ = 255 - a; + } + } + + bytestream_put_be16(&pseg_len, q - pseg_len - 2); + buf_size -= 6 + h->rects[clut_id]->nb_colors * 6; + } + + if (buf_size < h->num_rects * 22) + return AVERROR_BUFFER_TOO_SMALL; + for (region_id = 0; region_id < h->num_rects; region_id++) { + + /* region composition segment */ + + if (h->rects[region_id]->nb_colors <= 4) { + /* 2 bpp, some decoders do not support it correctly */ + bpp_index = 0; + } else if (h->rects[region_id]->nb_colors <= 16) { + /* 4 bpp, standard encoding */ + bpp_index = 1; + } else if (h->rects[region_id]->nb_colors <= 256) { + /* 8 bpp, standard encoding */ + bpp_index = 2; + } else { + return AVERROR(EINVAL); + } + + *q++ = 0x0f; /* sync_byte */ + *q++ = 0x11; /* segment_type */ + bytestream_put_be16(&q, page_id); + pseg_len = q; + q += 2; /* segment length */ + *q++ = region_id; + *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */ + bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */ + bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */ + *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03; + *q++ = region_id; /* clut_id == region_id */ + *q++ = 0; /* 8 bit fill colors */ + *q++ = 0x03; /* 4 bit and 2 bit fill colors */ + + bytestream_put_be16(&q, region_id); /* object_id == region_id */ + *q++ = (0 << 6) | (0 << 4); + *q++ = 0; + *q++ = 0xf0; + *q++ = 0; + + bytestream_put_be16(&pseg_len, q - pseg_len - 2); + } + buf_size -= h->num_rects * 22; + + for (object_id = 0; object_id < h->num_rects; object_id++) { + int (*dvb_encode_rle)(uint8_t **pq, int buf_size, + const uint8_t *bitmap, int linesize, + int w, int h); + + if (buf_size < 13) + return AVERROR_BUFFER_TOO_SMALL; + + /* bpp_index maths */ + if (h->rects[object_id]->nb_colors <= 4) { + /* 2 bpp, some decoders do not support it correctly */ + dvb_encode_rle = dvb_encode_rle2; + } else if (h->rects[object_id]->nb_colors <= 16) { + /* 4 bpp, standard encoding */ + dvb_encode_rle = dvb_encode_rle4; + } else if (h->rects[object_id]->nb_colors <= 256) { + /* 8 bpp, standard encoding */ + dvb_encode_rle = dvb_encode_rle8; + } else { + return AVERROR(EINVAL); + } + + /* Object Data segment */ + *q++ = 0x0f; /* sync byte */ + *q++ = 0x13; + bytestream_put_be16(&q, page_id); + pseg_len = q; + q += 2; /* segment length */ + + bytestream_put_be16(&q, object_id); + *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0, + object_coding_method, + non_modifying_color_flag */ + { + uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr; + int ret; + + ptop_field_len = q; + q += 2; + pbottom_field_len = q; + q += 2; + buf_size -= 13; + + top_ptr = q; + ret = dvb_encode_rle(&q, buf_size, + h->rects[object_id]->data[0], + h->rects[object_id]->w * 2, + h->rects[object_id]->w, + h->rects[object_id]->h >> 1); + if (ret < 0) + return ret; + buf_size -= ret; + bottom_ptr = q; + ret = dvb_encode_rle(&q, buf_size, + h->rects[object_id]->data[0] + h->rects[object_id]->w, + h->rects[object_id]->w * 2, + h->rects[object_id]->w, + h->rects[object_id]->h >> 1); + if (ret < 0) + return ret; + buf_size -= ret; + + bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr); + bytestream_put_be16(&pbottom_field_len, q - bottom_ptr); + } + + bytestream_put_be16(&pseg_len, q - pseg_len - 2); + } + } + + /* end of display set segment */ + + if (buf_size < 6) + return AVERROR_BUFFER_TOO_SMALL; + *q++ = 0x0f; /* sync_byte */ + *q++ = 0x80; /* segment_type */ + bytestream_put_be16(&q, page_id); + pseg_len = q; + q += 2; /* segment length */ + + bytestream_put_be16(&pseg_len, q - pseg_len - 2); + buf_size -= 6; + + s->object_version = (s->object_version + 1) & 0xf; + return q - outbuf; +} + +AVCodec ff_dvbsub_encoder = { + .name = "dvbsub", + .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_DVB_SUBTITLE, + .priv_data_size = sizeof(DVBSubtitleContext), + .encode_sub = dvbsub_encode, +}; diff -Nru ffmpeg-4.2.2/libavcodec/dvbsub_parser.c ffmpeg-4.4/libavcodec/dvbsub_parser.c --- ffmpeg-4.2.2/libavcodec/dvbsub_parser.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dvbsub_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -35,20 +35,12 @@ /* parser definition */ typedef struct DVBSubParseContext { - uint8_t *packet_buf; int packet_start; int packet_index; int in_packet; + uint8_t packet_buf[PARSE_BUF_SIZE]; } DVBSubParseContext; -static av_cold int dvbsub_parse_init(AVCodecParserContext *s) -{ - DVBSubParseContext *pc = s->priv_data; - pc->packet_buf = av_malloc(PARSE_BUF_SIZE); - - return 0; -} - static int dvbsub_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, @@ -173,16 +165,8 @@ return buf_size; } -static av_cold void dvbsub_parse_close(AVCodecParserContext *s) -{ - DVBSubParseContext *pc = s->priv_data; - av_freep(&pc->packet_buf); -} - AVCodecParser ff_dvbsub_parser = { .codec_ids = { AV_CODEC_ID_DVB_SUBTITLE }, .priv_data_size = sizeof(DVBSubParseContext), - .parser_init = dvbsub_parse_init, .parser_parse = dvbsub_parse, - .parser_close = dvbsub_parse_close, }; diff -Nru ffmpeg-4.2.2/libavcodec/dvdec.c ffmpeg-4.4/libavcodec/dvdec.c --- ffmpeg-4.2.2/libavcodec/dvdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dvdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -38,6 +38,7 @@ #include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" #include "avcodec.h" @@ -45,7 +46,6 @@ #include "dv_profile_internal.h" #include "dvdata.h" #include "get_bits.h" -#include "idctdsp.h" #include "internal.h" #include "put_bits.h" #include "simple_idct.h" @@ -177,24 +177,22 @@ static av_cold int dvvideo_decode_init(AVCodecContext *avctx) { DVVideoContext *s = avctx->priv_data; - IDCTDSPContext idsp; int i; - memset(&idsp,0, sizeof(idsp)); - ff_idctdsp_init(&idsp, avctx); + ff_idctdsp_init(&s->idsp, avctx); for (i = 0; i < 64; i++) - s->dv_zigzag[0][i] = idsp.idct_permutation[ff_zigzag_direct[i]]; + s->dv_zigzag[0][i] = s->idsp.idct_permutation[ff_zigzag_direct[i]]; if (avctx->lowres){ for (i = 0; i < 64; i++){ int j = ff_dv_zigzag248_direct[i]; - s->dv_zigzag[1][i] = idsp.idct_permutation[(j & 7) + (j & 8) * 4 + (j & 48) / 2]; + s->dv_zigzag[1][i] = s->idsp.idct_permutation[(j & 7) + (j & 8) * 4 + (j & 48) / 2]; } }else memcpy(s->dv_zigzag[1], ff_dv_zigzag248_direct, sizeof(s->dv_zigzag[1])); - s->idct_put[0] = idsp.idct_put; + s->idct_put[0] = s->idsp.idct_put; s->idct_put[1] = ff_simple_idct248_put; return ff_dvvideo_init(avctx); @@ -272,6 +270,48 @@ put_bits(pb, bits_left, get_bits(gb, bits_left)); } +static av_always_inline void put_block_8x4(int16_t *block, uint8_t *av_restrict p, int stride) +{ + int i, j; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 8; j++) + p[j] = av_clip_uint8(block[j]); + block += 8; + p += stride; + } +} + +static void dv100_idct_put_last_row_field_chroma(DVVideoContext *s, uint8_t *data, + int stride, int16_t *blocks) +{ + s->idsp.idct(blocks + 0*64); + s->idsp.idct(blocks + 1*64); + + put_block_8x4(blocks+0*64, data, stride<<1); + put_block_8x4(blocks+0*64 + 4*8, data + 8, stride<<1); + put_block_8x4(blocks+1*64, data + stride, stride<<1); + put_block_8x4(blocks+1*64 + 4*8, data + 8 + stride, stride<<1); +} + +static void dv100_idct_put_last_row_field_luma(DVVideoContext *s, uint8_t *data, + int stride, int16_t *blocks) +{ + s->idsp.idct(blocks + 0*64); + s->idsp.idct(blocks + 1*64); + s->idsp.idct(blocks + 2*64); + s->idsp.idct(blocks + 3*64); + + put_block_8x4(blocks+0*64, data, stride<<1); + put_block_8x4(blocks+0*64 + 4*8, data + 16, stride<<1); + put_block_8x4(blocks+1*64, data + 8, stride<<1); + put_block_8x4(blocks+1*64 + 4*8, data + 24, stride<<1); + put_block_8x4(blocks+2*64, data + stride, stride<<1); + put_block_8x4(blocks+2*64 + 4*8, data + 16 + stride, stride<<1); + put_block_8x4(blocks+3*64, data + 8 + stride, stride<<1); + put_block_8x4(blocks+3*64 + 4*8, data + 24 + stride, stride<<1); +} + /* mb_x and mb_y are in units of 8 pixels */ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) { @@ -443,14 +483,18 @@ } y_ptr = s->frame->data[0] + ((mb_y * s->frame->linesize[0] + mb_x) << log2_blocksize); - linesize = s->frame->linesize[0] << is_field_mode[mb_index]; - mb[0].idct_put(y_ptr, linesize, block + 0 * 64); - if (s->sys->video_stype == 4) { /* SD 422 */ - mb[2].idct_put(y_ptr + (1 << log2_blocksize), linesize, block + 2 * 64); + if (mb_y == 134 && is_field_mode[mb_index]) { + dv100_idct_put_last_row_field_luma(s, y_ptr, s->frame->linesize[0], block); } else { - mb[1].idct_put(y_ptr + (1 << log2_blocksize), linesize, block + 1 * 64); - mb[2].idct_put(y_ptr + y_stride, linesize, block + 2 * 64); - mb[3].idct_put(y_ptr + (1 << log2_blocksize) + y_stride, linesize, block + 3 * 64); + linesize = s->frame->linesize[0] << is_field_mode[mb_index]; + mb[0].idct_put(y_ptr, linesize, block + 0 * 64); + if (s->sys->video_stype == 4) { /* SD 422 */ + mb[2].idct_put(y_ptr + (1 << log2_blocksize), linesize, block + 2 * 64); + } else { + mb[1].idct_put(y_ptr + (1 << log2_blocksize), linesize, block + 1 * 64); + mb[2].idct_put(y_ptr + y_stride, linesize, block + 2 * 64); + mb[3].idct_put(y_ptr + (1 << log2_blocksize) + y_stride, linesize, block + 3 * 64); + } } mb += 4; block += 4 * 64; @@ -478,13 +522,19 @@ mb++; } else { y_stride = (mb_y == 134) ? (1 << log2_blocksize) : - s->frame->linesize[j] << ((!is_field_mode[mb_index]) * log2_blocksize); - linesize = s->frame->linesize[j] << is_field_mode[mb_index]; - (mb++)->idct_put(c_ptr, linesize, block); - block += 64; - if (s->sys->bpm == 8) { - (mb++)->idct_put(c_ptr + y_stride, linesize, block); + s->frame->linesize[j] << ((!is_field_mode[mb_index]) * log2_blocksize); + if (mb_y == 134 && is_field_mode[mb_index]) { + dv100_idct_put_last_row_field_chroma(s, c_ptr, s->frame->linesize[j], block); + mb += 2; + block += 2*64; + } else { + linesize = s->frame->linesize[j] << is_field_mode[mb_index]; + (mb++)->idct_put(c_ptr, linesize, block); block += 64; + if (s->sys->bpm == 8) { + (mb++)->idct_put(c_ptr + y_stride, linesize, block); + block += 64; + } } } } @@ -542,12 +592,19 @@ if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; - frame.f->interlaced_frame = 1; - frame.f->top_field_first = 0; /* Determine the codec's field order from the packet */ if ( *vsc_pack == dv_video_control ) { - frame.f->top_field_first = !(vsc_pack[3] & 0x40); + if (avctx->height == 720) { + frame.f->interlaced_frame = 0; + frame.f->top_field_first = 0; + } else if (avctx->height == 1080) { + frame.f->interlaced_frame = 1; + frame.f->top_field_first = (vsc_pack[3] & 0x40) == 0x40; + } else { + frame.f->interlaced_frame = (vsc_pack[3] & 0x10) == 0x10; + frame.f->top_field_first = !(vsc_pack[3] & 0x40); + } } s->buf = buf; diff -Nru ffmpeg-4.2.2/libavcodec/dvdsub.c ffmpeg-4.4/libavcodec/dvdsub.c --- ffmpeg-4.2.2/libavcodec/dvdsub.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dvdsub.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,33 @@ +/* + * DVD subtitle decoding/encoding + * Copyright (c) 2005 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 "internal.h" +#include "libavutil/avstring.h" +#include + +void ff_dvdsub_parse_palette(uint32_t *palette, const char *p) +{ + for (int i = 0; i < 16; i++) { + palette[i] = strtoul(p, (char **)&p, 16); + while (*p == ',' || av_isspace(*p)) + p++; + } +} diff -Nru ffmpeg-4.2.2/libavcodec/dvdsubdec.c ffmpeg-4.4/libavcodec/dvdsubdec.c --- ffmpeg-4.2.2/libavcodec/dvdsubdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dvdsubdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -27,7 +27,6 @@ #include "libavutil/colorspace.h" #include "libavutil/opt.h" #include "libavutil/imgutils.h" -#include "libavutil/avstring.h" #include "libavutil/bswap.h" typedef struct DVDSubContext @@ -626,18 +625,6 @@ return buf_size; } -static void parse_palette(DVDSubContext *ctx, char *p) -{ - int i; - - ctx->has_palette = 1; - for(i=0;i<16;i++) { - ctx->palette[i] = strtoul(p, &p, 16); - while(*p == ',' || av_isspace(*p)) - p++; - } -} - static int parse_ifo_palette(DVDSubContext *ctx, char *p) { FILE *ifo; @@ -719,7 +706,8 @@ break; if (strncmp("palette:", data, 8) == 0) { - parse_palette(ctx, data + 8); + ctx->has_palette = 1; + ff_dvdsub_parse_palette(ctx->palette, data + 8); } else if (strncmp("size:", data, 5) == 0) { int w, h; if (sscanf(data + 5, "%dx%d", &w, &h) == 2) { @@ -748,8 +736,10 @@ if (ctx->ifo_str) parse_ifo_palette(ctx, ctx->ifo_str); - if (ctx->palette_str) - parse_palette(ctx, ctx->palette_str); + if (ctx->palette_str) { + ctx->has_palette = 1; + ff_dvdsub_parse_palette(ctx->palette, ctx->palette_str); + } if (ctx->has_palette) { int i; av_log(avctx, AV_LOG_DEBUG, "palette:"); diff -Nru ffmpeg-4.2.2/libavcodec/dvdsubenc.c ffmpeg-4.4/libavcodec/dvdsubenc.c --- ffmpeg-4.2.2/libavcodec/dvdsubenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dvdsubenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,7 @@ typedef struct { AVClass *class; uint32_t global_palette[16]; + char *palette_str; int even_rows_fix; } DVDSubtitleContext; @@ -423,6 +424,29 @@ return ret; } +static int bprint_to_extradata(AVCodecContext *avctx, struct AVBPrint *buf) +{ + int ret; + char *str; + + ret = av_bprint_finalize(buf, &str); + if (ret < 0) + return ret; + if (!av_bprint_is_complete(buf)) { + av_free(str); + return AVERROR(ENOMEM); + } + + avctx->extradata = str; + /* Note: the string is NUL terminated (so extradata can be read as a + * string), but the ending character is not accounted in the size (in + * binary formats you are likely not supposed to mux that character). When + * extradata is copied, it is also padded with AV_INPUT_BUFFER_PADDING_SIZE + * zeros. */ + avctx->extradata_size = buf->len; + return 0; +} + static int dvdsub_init(AVCodecContext *avctx) { DVDSubtitleContext *dvdc = avctx->priv_data; @@ -436,7 +460,11 @@ int i, ret; av_assert0(sizeof(dvdc->global_palette) == sizeof(default_palette)); - memcpy(dvdc->global_palette, default_palette, sizeof(dvdc->global_palette)); + if (dvdc->palette_str) { + ff_dvdsub_parse_palette(dvdc->global_palette, dvdc->palette_str); + } else { + memcpy(dvdc->global_palette, default_palette, sizeof(dvdc->global_palette)); + } av_bprint_init(&extradata, 0, AV_BPRINT_SIZE_AUTOMATIC); if (avctx->width && avctx->height) @@ -446,7 +474,7 @@ av_bprintf(&extradata, " %06"PRIx32"%c", dvdc->global_palette[i] & 0xFFFFFF, i < 15 ? ',' : '\n'); - ret = avpriv_bprint_to_extradata(avctx, &extradata); + ret = bprint_to_extradata(avctx, &extradata); if (ret < 0) return ret; @@ -467,6 +495,7 @@ #define OFFSET(x) offsetof(DVDSubtitleContext, x) #define SE AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { + {"palette", "set the global palette", OFFSET(palette_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SE }, {"even_rows_fix", "Make number of rows even (workaround for some players)", OFFSET(even_rows_fix), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, SE}, { NULL }, }; diff -Nru ffmpeg-4.2.2/libavcodec/dvdsub_parser.c ffmpeg-4.4/libavcodec/dvdsub_parser.c --- ffmpeg-4.2.2/libavcodec/dvdsub_parser.c 2018-10-27 22:28:19.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dvdsub_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,11 +32,6 @@ int packet_index; } DVDSubParseContext; -static av_cold int dvdsub_parse_init(AVCodecParserContext *s) -{ - return 0; -} - static int dvdsub_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, @@ -92,7 +87,6 @@ AVCodecParser ff_dvdsub_parser = { .codec_ids = { AV_CODEC_ID_DVD_SUBTITLE }, .priv_data_size = sizeof(DVDSubParseContext), - .parser_init = dvdsub_parse_init, .parser_parse = dvdsub_parse, .parser_close = dvdsub_parse_close, }; diff -Nru ffmpeg-4.2.2/libavcodec/dvenc.c ffmpeg-4.4/libavcodec/dvenc.c --- ffmpeg-4.2.2/libavcodec/dvenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dvenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/attributes.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -60,10 +61,7 @@ ff_dv_print_profiles(avctx, AV_LOG_ERROR); return AVERROR(EINVAL); } - if (avctx->height > 576) { - av_log(avctx, AV_LOG_ERROR, "DVCPRO HD encoding is not supported.\n"); - return AVERROR_PATCHWELCOME; - } + ret = ff_dv_init_dynamic_tables(s, s->sys); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error initializing work tables.\n"); @@ -90,6 +88,7 @@ } /* bit budget for AC only in 5 MBs */ +static const int vs_total_ac_bits_hd = (68 * 6 + 52*2) * 5; static const int vs_total_ac_bits = (100 * 4 + 68 * 2) * 5; static const int mb_area_start[5] = { 1, 6, 21, 43, 64 }; @@ -158,6 +157,11 @@ uint8_t sign[64]; uint8_t partial_bit_count; uint32_t partial_bit_buffer; /* we can't use uint16_t here */ + /* used by DV100 only: a copy of the weighted and classified but + not-yet-quantized AC coefficients. This is necessary for + re-quantizing at different steps. */ + int16_t save[64]; + int min_qlevel; /* DV100 only: minimum qlevel (for AC coefficients >255) */ } EncBlockInfo; static av_always_inline PutBitContext *dv_encode_ac(EncBlockInfo *bi, @@ -212,8 +216,8 @@ if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { int ps = s->ildct_cmp(NULL, data, NULL, linesize, 8) - 400; if (ps > 0) { - int is = s->ildct_cmp(NULL, data, NULL, linesize << 1, 4) + - s->ildct_cmp(NULL, data + linesize, NULL, linesize << 1, 4); + int is = s->ildct_cmp(NULL, data, NULL, linesize * 2, 4) + + s->ildct_cmp(NULL, data + linesize, NULL, linesize * 2, 4); return ps > is; } } @@ -243,13 +247,122 @@ 170627, 170627, 153560, 153560, 165371, 165371, 144651, 144651, }; -static av_always_inline int dv_init_enc_block(EncBlockInfo *bi, uint8_t *data, - ptrdiff_t linesize, - DVVideoContext *s, int bias) +/* setting this to 1 results in a faster codec but + * somewhat lower image quality */ +#define DV100_SACRIFICE_QUALITY_FOR_SPEED 1 +#define DV100_ENABLE_FINER 1 + +/* pack combination of QNO and CNO into a single 8-bit value */ +#define DV100_MAKE_QLEVEL(qno,cno) ((qno<<2) | (cno)) +#define DV100_QLEVEL_QNO(qlevel) (qlevel>>2) +#define DV100_QLEVEL_CNO(qlevel) (qlevel&0x3) + +#define DV100_NUM_QLEVELS 31 + +/* The quantization step is determined by a combination of QNO and + CNO. We refer to these combinations as "qlevels" (this term is our + own, it's not mentioned in the spec). We use CNO, a multiplier on + the quantization step, to "fill in the gaps" between quantization + steps associated with successive values of QNO. e.g. there is no + QNO for a quantization step of 10, but we can use QNO=5 CNO=1 to + get the same result. The table below encodes combinations of QNO + and CNO in order of increasing quantization coarseness. */ +static const uint8_t dv100_qlevels[DV100_NUM_QLEVELS] = { + DV100_MAKE_QLEVEL( 1,0), // 1*1= 1 + DV100_MAKE_QLEVEL( 1,0), // 1*1= 1 + DV100_MAKE_QLEVEL( 2,0), // 2*1= 2 + DV100_MAKE_QLEVEL( 3,0), // 3*1= 3 + DV100_MAKE_QLEVEL( 4,0), // 4*1= 4 + DV100_MAKE_QLEVEL( 5,0), // 5*1= 5 + DV100_MAKE_QLEVEL( 6,0), // 6*1= 6 + DV100_MAKE_QLEVEL( 7,0), // 7*1= 7 + DV100_MAKE_QLEVEL( 8,0), // 8*1= 8 + DV100_MAKE_QLEVEL( 5,1), // 5*2=10 + DV100_MAKE_QLEVEL( 6,1), // 6*2=12 + DV100_MAKE_QLEVEL( 7,1), // 7*2=14 + DV100_MAKE_QLEVEL( 9,0), // 16*1=16 + DV100_MAKE_QLEVEL(10,0), // 18*1=18 + DV100_MAKE_QLEVEL(11,0), // 20*1=20 + DV100_MAKE_QLEVEL(12,0), // 22*1=22 + DV100_MAKE_QLEVEL(13,0), // 24*1=24 + DV100_MAKE_QLEVEL(14,0), // 28*1=28 + DV100_MAKE_QLEVEL( 9,1), // 16*2=32 + DV100_MAKE_QLEVEL(10,1), // 18*2=36 + DV100_MAKE_QLEVEL(11,1), // 20*2=40 + DV100_MAKE_QLEVEL(12,1), // 22*2=44 + DV100_MAKE_QLEVEL(13,1), // 24*2=48 + DV100_MAKE_QLEVEL(15,0), // 52*1=52 + DV100_MAKE_QLEVEL(14,1), // 28*2=56 + DV100_MAKE_QLEVEL( 9,2), // 16*4=64 + DV100_MAKE_QLEVEL(10,2), // 18*4=72 + DV100_MAKE_QLEVEL(11,2), // 20*4=80 + DV100_MAKE_QLEVEL(12,2), // 22*4=88 + DV100_MAKE_QLEVEL(13,2), // 24*4=96 + // ... + DV100_MAKE_QLEVEL(15,3), // 52*8=416 +}; + +static const int dv100_min_bias = 0; +static const int dv100_chroma_bias = 0; +static const int dv100_starting_qno = 1; + +#if DV100_SACRIFICE_QUALITY_FOR_SPEED +static const int dv100_qlevel_inc = 4; +#else +static const int dv100_qlevel_inc = 1; +#endif + +// 1/qstep, shifted up by 16 bits +static const int dv100_qstep_bits = 16; +static const int dv100_qstep_inv[16] = { + 65536, 65536, 32768, 21845, 16384, 13107, 10923, 9362, 8192, 4096, 3641, 3277, 2979, 2731, 2341, 1260, +}; + +/* DV100 weights are pre-zigzagged, inverted and multiplied by 2^16 + (in DV100 the AC components are divided by the spec weights) */ +static const int dv_weight_1080[2][64] = { + { 8192, 65536, 65536, 61681, 61681, 61681, 58254, 58254, + 58254, 58254, 58254, 58254, 55188, 58254, 58254, 55188, + 55188, 55188, 55188, 55188, 55188, 24966, 27594, 26214, + 26214, 26214, 27594, 24966, 23831, 24385, 25575, 25575, + 25575, 25575, 24385, 23831, 23302, 23302, 24966, 24966, + 24966, 23302, 23302, 21845, 22795, 24385, 24385, 22795, + 21845, 21400, 21845, 23831, 21845, 21400, 10382, 10700, + 10700, 10382, 10082, 9620, 10082, 9039, 9039, 8525, }, + { 8192, 65536, 65536, 61681, 61681, 61681, 41943, 41943, + 41943, 41943, 40330, 41943, 40330, 41943, 40330, 40330, + 40330, 38836, 38836, 40330, 40330, 24966, 27594, 26214, + 26214, 26214, 27594, 24966, 23831, 24385, 25575, 25575, + 25575, 25575, 24385, 23831, 11523, 11523, 12483, 12483, + 12483, 11523, 11523, 10923, 11275, 12193, 12193, 11275, + 10923, 5323, 5490, 5924, 5490, 5323, 5165, 5323, + 5323, 5165, 5017, 4788, 5017, 4520, 4520, 4263, } +}; + +static const int dv_weight_720[2][64] = { + { 8192, 65536, 65536, 61681, 61681, 61681, 58254, 58254, + 58254, 58254, 58254, 58254, 55188, 58254, 58254, 55188, + 55188, 55188, 55188, 55188, 55188, 24966, 27594, 26214, + 26214, 26214, 27594, 24966, 23831, 24385, 25575, 25575, + 25575, 25575, 24385, 23831, 15420, 15420, 16644, 16644, + 16644, 15420, 15420, 10923, 11398, 12193, 12193, 11398, + 10923, 10700, 10923, 11916, 10923, 10700, 5191, 5350, + 5350, 5191, 5041, 4810, 5041, 4520, 4520, 4263, }, + { 8192, 43691, 43691, 40330, 40330, 40330, 29127, 29127, + 29127, 29127, 29127, 29127, 27594, 29127, 29127, 27594, + 27594, 27594, 27594, 27594, 27594, 12483, 13797, 13107, + 13107, 13107, 13797, 12483, 11916, 12193, 12788, 12788, + 12788, 12788, 12193, 11916, 5761, 5761, 6242, 6242, + 6242, 5761, 5761, 5461, 5638, 5461, 6096, 5638, + 5461, 2661, 2745, 2962, 2745, 2661, 2583, 2661, + 2661, 2583, 2509, 2394, 2509, 2260, 2260, 2131, } +}; + +static av_always_inline int dv_set_class_number_sd(DVVideoContext *s, + int16_t *blk, EncBlockInfo *bi, + const uint8_t *zigzag_scan, + const int *weight, int bias) { - const int *weight; - const uint8_t *zigzag_scan; - LOCAL_ALIGNED_16(int16_t, blk, [64]); int i, area; /* We offer two different methods for class number assignment: the * method suggested in SMPTE 314M Table 22, and an improved @@ -271,31 +384,8 @@ const unsigned deadzone = s->quant_deadzone; const unsigned threshold = 2 * deadzone; - av_assert2((((int) blk) & 15) == 0); - - bi->area_q[0] = - bi->area_q[1] = - bi->area_q[2] = - bi->area_q[3] = 0; - bi->partial_bit_count = 0; - bi->partial_bit_buffer = 0; - bi->cur_ac = 0; - if (data) { - bi->dct_mode = dv_guess_dct_mode(s, data, linesize); - s->get_pixels(blk, data, linesize); - s->fdct[bi->dct_mode](blk); - } else { - /* We rely on the fact that encoding all zeros leads to an immediate - * EOB, which is precisely what the spec calls for in the "dummy" - * blocks. */ - memset(blk, 0, 64 * sizeof(*blk)); - bi->dct_mode = 0; - } bi->mb[0] = blk[0]; - zigzag_scan = bi->dct_mode ? ff_dv_zigzag248_direct : ff_zigzag_direct; - weight = bi->dct_mode ? dv_weight_248 : dv_weight_88; - for (area = 0; area < 4; area++) { bi->prev[area] = prev; bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :) @@ -350,6 +440,309 @@ bi->bit_size[2] + bi->bit_size[3]; } +/* this function just copies the DCT coefficients and performs + the initial (non-)quantization. */ +static inline void dv_set_class_number_hd(DVVideoContext *s, + int16_t *blk, EncBlockInfo *bi, + const uint8_t *zigzag_scan, + const int *weight, int bias) +{ + int i, max = 0; + + /* the first quantization (none at all) */ + bi->area_q[0] = 1; + + /* weigh AC components and store to save[] */ + /* (i=0 is the DC component; we only include it to make the + number of loop iterations even, for future possible SIMD optimization) */ + for (i = 0; i < 64; i += 2) { + int level0, level1; + + /* get the AC component (in zig-zag order) */ + level0 = blk[zigzag_scan[i+0]]; + level1 = blk[zigzag_scan[i+1]]; + + /* extract sign and make it the lowest bit */ + bi->sign[i+0] = (level0>>31)&1; + bi->sign[i+1] = (level1>>31)&1; + + /* take absolute value of the level */ + level0 = FFABS(level0); + level1 = FFABS(level1); + + /* weigh it */ + level0 = (level0*weight[i+0] + 4096 + (1<<17)) >> 18; + level1 = (level1*weight[i+1] + 4096 + (1<<17)) >> 18; + + /* save unquantized value */ + bi->save[i+0] = level0; + bi->save[i+1] = level1; + + /* find max component */ + if (bi->save[i+0] > max) + max = bi->save[i+0]; + if (bi->save[i+1] > max) + max = bi->save[i+1]; + } + + /* copy DC component */ + bi->mb[0] = blk[0]; + + /* the EOB code is 4 bits */ + bi->bit_size[0] = 4; + bi->bit_size[1] = bi->bit_size[2] = bi->bit_size[3] = 0; + + /* ensure that no AC coefficients are cut off */ + bi->min_qlevel = ((max+256) >> 8); + + bi->area_q[0] = 25; /* set to an "impossible" value */ + bi->cno = 0; +} + +static av_always_inline int dv_init_enc_block(EncBlockInfo* bi, uint8_t *data, int linesize, + DVVideoContext *s, int chroma) +{ + LOCAL_ALIGNED_16(int16_t, blk, [64]); + + bi->area_q[0] = bi->area_q[1] = bi->area_q[2] = bi->area_q[3] = 0; + bi->partial_bit_count = 0; + bi->partial_bit_buffer = 0; + bi->cur_ac = 0; + + if (data) { + if (DV_PROFILE_IS_HD(s->sys)) { + s->get_pixels(blk, data, linesize * (1 << bi->dct_mode)); + s->fdct[0](blk); + } else { + bi->dct_mode = dv_guess_dct_mode(s, data, linesize); + s->get_pixels(blk, data, linesize); + s->fdct[bi->dct_mode](blk); + } + } else { + /* We rely on the fact that encoding all zeros leads to an immediate EOB, + which is precisely what the spec calls for in the "dummy" blocks. */ + memset(blk, 0, 64*sizeof(*blk)); + bi->dct_mode = 0; + } + + if (DV_PROFILE_IS_HD(s->sys)) { + const int *weights; + if (s->sys->height == 1080) { + weights = dv_weight_1080[chroma]; + } else { /* 720p */ + weights = dv_weight_720[chroma]; + } + dv_set_class_number_hd(s, blk, bi, + ff_zigzag_direct, + weights, + dv100_min_bias+chroma*dv100_chroma_bias); + } else { + dv_set_class_number_sd(s, blk, bi, + bi->dct_mode ? ff_dv_zigzag248_direct : ff_zigzag_direct, + bi->dct_mode ? dv_weight_248 : dv_weight_88, + chroma); + } + + return bi->bit_size[0] + bi->bit_size[1] + bi->bit_size[2] + bi->bit_size[3]; +} + +/* DV100 quantize + Perform quantization by divinding the AC component by the qstep. + As an optimization we use a fixed-point integer multiply instead + of a divide. */ +static av_always_inline int dv100_quantize(int level, int qsinv) +{ + /* this code is equivalent to */ + /* return (level + qs/2) / qs; */ + + return (level * qsinv + 1024 + (1<<(dv100_qstep_bits-1))) >> dv100_qstep_bits; + + /* the extra +1024 is needed to make the rounding come out right. */ + + /* I (DJM) have verified that the results are exactly the same as + division for level 0-2048 at all QNOs. */ +} + +static int dv100_actual_quantize(EncBlockInfo *b, int qlevel) +{ + int prev, k, qsinv; + + int qno = DV100_QLEVEL_QNO(dv100_qlevels[qlevel]); + int cno = DV100_QLEVEL_CNO(dv100_qlevels[qlevel]); + + if (b->area_q[0] == qno && b->cno == cno) + return b->bit_size[0]; + + qsinv = dv100_qstep_inv[qno]; + + /* record the new qstep */ + b->area_q[0] = qno; + b->cno = cno; + + /* reset encoded size (EOB = 4 bits) */ + b->bit_size[0] = 4; + + /* visit nonzero components and quantize */ + prev = 0; + for (k = 1; k < 64; k++) { + /* quantize */ + int ac = dv100_quantize(b->save[k], qsinv) >> cno; + if (ac) { + if (ac > 255) + ac = 255; + b->mb[k] = ac; + b->bit_size[0] += dv_rl2vlc_size(k - prev - 1, ac); + b->next[prev] = k; + prev = k; + } + } + b->next[prev] = k; + + return b->bit_size[0]; +} + +static inline void dv_guess_qnos_hd(EncBlockInfo *blks, int *qnos) +{ + EncBlockInfo *b; + int min_qlevel[5]; + int qlevels[5]; + int size[5]; + int i, j; + /* cache block sizes at hypothetical qlevels */ + uint16_t size_cache[5*8][DV100_NUM_QLEVELS] = {{0}}; + + /* get minimum qlevels */ + for (i = 0; i < 5; i++) { + min_qlevel[i] = 1; + for (j = 0; j < 8; j++) { + if (blks[8*i+j].min_qlevel > min_qlevel[i]) + min_qlevel[i] = blks[8*i+j].min_qlevel; + } + } + + /* initialize sizes */ + for (i = 0; i < 5; i++) { + qlevels[i] = dv100_starting_qno; + if (qlevels[i] < min_qlevel[i]) + qlevels[i] = min_qlevel[i]; + + qnos[i] = DV100_QLEVEL_QNO(dv100_qlevels[qlevels[i]]); + size[i] = 0; + for (j = 0; j < 8; j++) { + size_cache[8*i+j][qlevels[i]] = dv100_actual_quantize(&blks[8*i+j], qlevels[i]); + size[i] += size_cache[8*i+j][qlevels[i]]; + } + } + + /* must we go coarser? */ + if (size[0]+size[1]+size[2]+size[3]+size[4] > vs_total_ac_bits_hd) { + int largest = size[0] % 5; /* 'random' number */ + int qlevels_done = 0; + + do { + /* find the macroblock with the lowest qlevel */ + for (i = 0; i < 5; i++) { + if (qlevels[i] < qlevels[largest]) + largest = i; + } + + i = largest; + /* ensure that we don't enter infinite loop */ + largest = (largest+1) % 5; + + /* quantize a little bit more */ + qlevels[i] += dv100_qlevel_inc; + if (qlevels[i] > DV100_NUM_QLEVELS-1) { + qlevels[i] = DV100_NUM_QLEVELS-1; + qlevels_done++; + } + + qnos[i] = DV100_QLEVEL_QNO(dv100_qlevels[qlevels[i]]); + size[i] = 0; + + /* for each block */ + b = &blks[8*i]; + for (j = 0; j < 8; j++, b++) { + /* accumulate block size into macroblock */ + if(size_cache[8*i+j][qlevels[i]] == 0) { + /* it is safe to use actual_quantize() here because we only go from finer to coarser, + and it saves the final actual_quantize() down below */ + size_cache[8*i+j][qlevels[i]] = dv100_actual_quantize(b, qlevels[i]); + } + size[i] += size_cache[8*i+j][qlevels[i]]; + } /* for each block */ + + } while (vs_total_ac_bits_hd < size[0] + size[1] + size[2] + size[3] + size[4] && qlevels_done < 5); + + // can we go finer? + } else if (DV100_ENABLE_FINER && + size[0]+size[1]+size[2]+size[3]+size[4] < vs_total_ac_bits_hd) { + int save_qlevel; + int largest = size[0] % 5; /* 'random' number */ + + while (qlevels[0] > min_qlevel[0] || + qlevels[1] > min_qlevel[1] || + qlevels[2] > min_qlevel[2] || + qlevels[3] > min_qlevel[3] || + qlevels[4] > min_qlevel[4]) { + + /* find the macroblock with the highest qlevel */ + for (i = 0; i < 5; i++) { + if (qlevels[i] > min_qlevel[i] && qlevels[i] > qlevels[largest]) + largest = i; + } + + i = largest; + + /* ensure that we don't enter infinite loop */ + largest = (largest+1) % 5; + + if (qlevels[i] <= min_qlevel[i]) { + /* can't unquantize any more */ + continue; + } + /* quantize a little bit less */ + save_qlevel = qlevels[i]; + qlevels[i] -= dv100_qlevel_inc; + if (qlevels[i] < min_qlevel[i]) + qlevels[i] = min_qlevel[i]; + + qnos[i] = DV100_QLEVEL_QNO(dv100_qlevels[qlevels[i]]); + + size[i] = 0; + + /* for each block */ + b = &blks[8*i]; + for (j = 0; j < 8; j++, b++) { + /* accumulate block size into macroblock */ + if(size_cache[8*i+j][qlevels[i]] == 0) { + size_cache[8*i+j][qlevels[i]] = dv100_actual_quantize(b, qlevels[i]); + } + size[i] += size_cache[8*i+j][qlevels[i]]; + } /* for each block */ + + /* did we bust the limit? */ + if (vs_total_ac_bits_hd < size[0] + size[1] + size[2] + size[3] + size[4]) { + /* go back down and exit */ + qlevels[i] = save_qlevel; + qnos[i] = DV100_QLEVEL_QNO(dv100_qlevels[qlevels[i]]); + break; + } + } + } + + /* now do the actual quantization */ + for (i = 0; i < 5; i++) { + /* for each block */ + b = &blks[8*i]; + size[i] = 0; + for (j = 0; j < 8; j++, b++) { + /* accumulate block size into macroblock */ + size[i] += dv100_actual_quantize(b, qlevels[i]); + } /* for each block */ + } +} + static inline void dv_guess_qnos(EncBlockInfo *blks, int *qnos) { int size[5]; @@ -422,6 +815,26 @@ } } +/* update all cno values into the blocks, over-writing the old values without + touching anything else. (only used for DV100) */ +static inline void dv_revise_cnos(uint8_t *dif, EncBlockInfo *blk, const AVDVProfile *profile) +{ + uint8_t *data; + int mb_index, i; + + for (mb_index = 0; mb_index < 5; mb_index++) { + data = dif + mb_index*80 + 4; + for (i = 0; i < profile->bpm; i++) { + /* zero out the class number */ + data[1] &= 0xCF; + /* add the new one */ + data[1] |= blk[profile->bpm*mb_index+i].cno << 4; + + data += profile->block_sizes[i] >> 3; + } + } +} + static int dv_encode_video_segment(AVCodecContext *avctx, void *arg) { DVVideoContext *s = avctx->priv_data; @@ -430,31 +843,43 @@ int mb_x, mb_y, c_offset; ptrdiff_t linesize, y_stride; uint8_t *y_ptr; - uint8_t *dif; + uint8_t *dif, *p; LOCAL_ALIGNED_8(uint8_t, scratch, [128]); EncBlockInfo enc_blks[5 * DV_MAX_BPM]; PutBitContext pbs[5 * DV_MAX_BPM]; PutBitContext *pb; EncBlockInfo *enc_blk; int vs_bit_size = 0; - int qnos[5] = { 15, 15, 15, 15, 15 }; /* No quantization */ + int qnos[5]; int *qnosp = &qnos[0]; - dif = &s->buf[work_chunk->buf_offset * 80]; + p = dif = &s->buf[work_chunk->buf_offset * 80]; enc_blk = &enc_blks[0]; for (mb_index = 0; mb_index < 5; mb_index++) { dv_calculate_mb_xy(s, work_chunk, mb_index, &mb_x, &mb_y); + qnos[mb_index] = DV_PROFILE_IS_HD(s->sys) ? 1 : 15; + + y_ptr = s->frame->data[0] + (mb_y * s->frame->linesize[0] + mb_x) * 8; + linesize = s->frame->linesize[0]; + + if (s->sys->height == 1080 && mb_y < 134) + enc_blk->dct_mode = dv_guess_dct_mode(s, y_ptr, linesize); + else + enc_blk->dct_mode = 0; + for (i = 1; i < 8; i++) + enc_blk[i].dct_mode = enc_blk->dct_mode; + /* initializing luminance blocks */ if ((s->sys->pix_fmt == AV_PIX_FMT_YUV420P) || (s->sys->pix_fmt == AV_PIX_FMT_YUV411P && mb_x >= (704 / 8)) || (s->sys->height >= 720 && mb_y != 134)) { - y_stride = s->frame->linesize[0] << 3; + y_stride = s->frame->linesize[0] * (1 << (3*!enc_blk->dct_mode)); } else { y_stride = 16; } y_ptr = s->frame->data[0] + - ((mb_y * s->frame->linesize[0] + mb_x) << 3); + (mb_y * s->frame->linesize[0] + mb_x) * 8; linesize = s->frame->linesize[0]; if (s->sys->video_stype == 4) { /* SD 422 */ @@ -473,17 +898,17 @@ enc_blk += 4; /* initializing chrominance blocks */ - c_offset = (((mb_y >> (s->sys->pix_fmt == AV_PIX_FMT_YUV420P)) * s->frame->linesize[1] + - (mb_x >> ((s->sys->pix_fmt == AV_PIX_FMT_YUV411P) ? 2 : 1))) << 3); + c_offset = ((mb_y >> (s->sys->pix_fmt == AV_PIX_FMT_YUV420P)) * s->frame->linesize[1] + + (mb_x >> ((s->sys->pix_fmt == AV_PIX_FMT_YUV411P) ? 2 : 1))) * 8; for (j = 2; j; j--) { uint8_t *c_ptr = s->frame->data[j] + c_offset; linesize = s->frame->linesize[j]; - y_stride = (mb_y == 134) ? 8 : (s->frame->linesize[j] << 3); + y_stride = (mb_y == 134) ? 8 : (s->frame->linesize[j] * (1 << (3*!enc_blk->dct_mode))); if (s->sys->pix_fmt == AV_PIX_FMT_YUV411P && mb_x >= (704 / 8)) { uint8_t *d; uint8_t *b = scratch; for (i = 0; i < 8; i++) { - d = c_ptr + (linesize << 3); + d = c_ptr + linesize * 8; b[0] = c_ptr[0]; b[1] = c_ptr[1]; b[2] = c_ptr[2]; @@ -506,27 +931,31 @@ } } - if (vs_total_ac_bits < vs_bit_size) + if (DV_PROFILE_IS_HD(s->sys)) { + /* unconditional */ + dv_guess_qnos_hd(&enc_blks[0], qnosp); + } else if (vs_total_ac_bits < vs_bit_size) { dv_guess_qnos(&enc_blks[0], qnosp); + } /* DIF encoding process */ for (j = 0; j < 5 * s->sys->bpm;) { int start_mb = j; - dif[3] = *qnosp++; - dif += 4; + p[3] = *qnosp++; + p += 4; /* First pass over individual cells only */ for (i = 0; i < s->sys->bpm; i++, j++) { int sz = s->sys->block_sizes[i] >> 3; - init_put_bits(&pbs[j], dif, sz); + init_put_bits(&pbs[j], p, sz); put_sbits(&pbs[j], 9, ((enc_blks[j].mb[0] >> 3) - 1024 + 2) >> 2); - put_bits(&pbs[j], 1, enc_blks[j].dct_mode); + put_bits(&pbs[j], 1, DV_PROFILE_IS_HD(s->sys) && i ? 1 : enc_blks[j].dct_mode); put_bits(&pbs[j], 2, enc_blks[j].cno); dv_encode_ac(&enc_blks[j], &pbs[j], &pbs[j + 1]); - dif += sz; + p += sz; } /* Second pass over each MB space */ @@ -559,6 +988,9 @@ memset(pbs[j].buf + pos, 0xff, size - pos); } + if (DV_PROFILE_IS_HD(s->sys)) + dv_revise_cnos(dif, enc_blks, s->sys); + return 0; } @@ -583,12 +1015,19 @@ * 2. It is not at all clear what STYPE is used for 4:2:0 PAL * compression scheme (if any). */ + uint8_t aspect = 0; int apt = (c->sys->pix_fmt == AV_PIX_FMT_YUV420P ? 0 : 1); - int fs = c->frame->top_field_first ? 0x00 : 0x40; + int fs; - uint8_t aspect = 0; - if ((int) (av_q2d(c->avctx->sample_aspect_ratio) * - c->avctx->width / c->avctx->height * 10) >= 17) /* 16:9 */ + if (c->avctx->height >= 720) + fs = c->avctx->height == 720 || c->frame->top_field_first ? 0x40 : 0x00; + else + fs = c->frame->top_field_first ? 0x00 : 0x40; + + if (DV_PROFILE_IS_HD(c->sys) || + (int)(av_q2d(c->avctx->sample_aspect_ratio) * + c->avctx->width / c->avctx->height * 10) >= 17) + /* HD formats are always 16:9 */ aspect = 0x02; buf[0] = (uint8_t) pack_id; @@ -643,10 +1082,14 @@ uint8_t seq_num, uint8_t dif_num, uint8_t *buf) { + int fsc = chan_num & 1; + int fsp = 1 - (chan_num >> 1); + buf[0] = (uint8_t) t; /* Section type */ buf[1] = (seq_num << 4) | /* DIF seq number 0-9 for 525/60; 0-11 for 625/50 */ - (chan_num << 3) | /* FSC: for 50Mb/s 0 - first channel; 1 - second */ - 7; /* reserved -- always 1 */ + (fsc << 3) | /* FSC: for 50 and 100Mb/s 0 - first channel; 1 - second */ + (fsp << 2) | /* FSP: for 100Mb/s 1 - channels 0-1; 0 - channels 2-3 */ + 3; /* reserved -- always 1 */ buf[2] = dif_num; /* DIF block number Video: 0-134, Audio: 0-8 */ return 3; } @@ -674,20 +1117,22 @@ static void dv_format_frame(DVVideoContext *c, uint8_t *buf) { int chan, i, j, k; + /* We work with 720p frames split in half. The odd half-frame is chan 2,3 */ + int chan_offset = 2*(c->sys->height == 720 && c->avctx->frame_number & 1); for (chan = 0; chan < c->sys->n_difchan; chan++) { for (i = 0; i < c->sys->difseg_size; i++) { memset(buf, 0xff, 80 * 6); /* first 6 DIF blocks are for control data */ /* DV header: 1DIF */ - buf += dv_write_dif_id(dv_sect_header, chan, i, 0, buf); + buf += dv_write_dif_id(dv_sect_header, chan+chan_offset, i, 0, buf); buf += dv_write_pack((c->sys->dsf ? dv_header625 : dv_header525), c, buf); buf += 72; /* unused bytes */ /* DV subcode: 2DIFs */ for (j = 0; j < 2; j++) { - buf += dv_write_dif_id(dv_sect_subcode, chan, i, j, buf); + buf += dv_write_dif_id(dv_sect_subcode, chan+chan_offset, i, j, buf); for (k = 0; k < 6; k++) buf += dv_write_ssyb_id(k, (i < c->sys->difseg_size / 2), buf) + 5; buf += 29; /* unused bytes */ @@ -695,7 +1140,7 @@ /* DV VAUX: 3DIFS */ for (j = 0; j < 3; j++) { - buf += dv_write_dif_id(dv_sect_vaux, chan, i, j, buf); + buf += dv_write_dif_id(dv_sect_vaux, chan+chan_offset, i, j, buf); buf += dv_write_pack(dv_video_source, c, buf); buf += dv_write_pack(dv_video_control, c, buf); buf += 7 * 5; @@ -708,10 +1153,10 @@ for (j = 0; j < 135; j++) { if (j % 15 == 0) { memset(buf, 0xff, 80); - buf += dv_write_dif_id(dv_sect_audio, chan, i, j / 15, buf); + buf += dv_write_dif_id(dv_sect_audio, chan+chan_offset, i, j/15, buf); buf += 77; /* audio control & shuffled PCM audio */ } - buf += dv_write_dif_id(dv_sect_video, chan, i, j, buf); + buf += dv_write_dif_id(dv_sect_video, chan+chan_offset, i, j, buf); buf += 77; /* 1 video macroblock: 1 bytes control * 4 * 14 bytes Y 8x8 data * 10 bytes Cr 8x8 data @@ -738,15 +1183,15 @@ c->coded_frame->pict_type = AV_PICTURE_TYPE_I; FF_ENABLE_DEPRECATION_WARNINGS #endif - s->buf = pkt->data; + + dv_format_frame(s, pkt->data); + c->execute(c, dv_encode_video_segment, s->work_chunks, NULL, dv_work_pool_size(s->sys), sizeof(DVwork_chunk)); emms_c(); - dv_format_frame(s, pkt->data); - pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; @@ -775,7 +1220,7 @@ .priv_data_size = sizeof(DVVideoContext), .init = dvvideo_encode_init, .encode2 = dvvideo_encode_frame, - .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE diff -Nru ffmpeg-4.2.2/libavcodec/dv.h ffmpeg-4.4/libavcodec/dv.h --- ffmpeg-4.2.2/libavcodec/dv.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dv.h 2020-07-11 10:39:30.000000000 +0000 @@ -31,6 +31,7 @@ #include "dv_profile.h" #include "me_cmp.h" #include "vlc.h" +#include "idctdsp.h" typedef struct DVwork_chunk { uint16_t buf_offset; @@ -52,6 +53,7 @@ me_cmp_func ildct_cmp; DVwork_chunk work_chunks[4 * 12 * 27]; uint32_t idct_factor[2 * 4 * 16 * 64]; + IDCTDSPContext idsp; int quant_deadzone; } DVVideoContext; @@ -81,6 +83,7 @@ #define DV_PROFILE_IS_HD(p) ((p)->video_stype & 0x10) #define DV_PROFILE_IS_1080i50(p) (((p)->video_stype == 0x14) && ((p)->dsf == 1)) +#define DV_PROFILE_IS_1080i60(p) (((p)->video_stype == 0x14) && ((p)->dsf == 0)) #define DV_PROFILE_IS_720p50(p) (((p)->video_stype == 0x18) && ((p)->dsf == 1)) /** diff -Nru ffmpeg-4.2.2/libavcodec/dv_profile.c ffmpeg-4.4/libavcodec/dv_profile.c --- ffmpeg-4.2.2/libavcodec/dv_profile.c 2018-07-17 09:27:39.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dv_profile.c 2021-04-08 21:28:39.000000000 +0000 @@ -261,24 +261,22 @@ const uint8_t *frame, unsigned buf_size) { #if CONFIG_DVPROFILE - int i, dsf, stype; + int i, dsf, stype, pal; if(buf_size < DV_PROFILE_BYTES) return NULL; dsf = (frame[3] & 0x80) >> 7; stype = frame[80 * 5 + 48 + 3] & 0x1f; + pal = !!(frame[80 * 5 + 48 + 3] & 0x20); /* 576i50 25Mbps 4:1:1 is a special case */ if ((dsf == 1 && stype == 0 && frame[4] & 0x07 /* the APT field */) || (stype == 31 && codec && codec->codec_tag==AV_RL32("SL25") && codec->coded_width==720 && codec->coded_height==576)) return &dv_profiles[2]; - if( stype == 0 - && codec - && (codec->codec_tag==AV_RL32("dvsd") || codec->codec_tag==AV_RL32("CDVC")) - && codec->coded_width ==720 - && codec->coded_height==576) + /* hack for trac issues #8333 and #2177, PAL DV files with dsf flag 0 - detect via pal flag and buf_size */ + if (dsf == 0 && pal == 1 && stype == dv_profiles[1].video_stype && buf_size == dv_profiles[1].frame_size) return &dv_profiles[1]; for (i = 0; i < FF_ARRAY_ELEMS(dv_profiles); i++) diff -Nru ffmpeg-4.2.2/libavcodec/dxa.c ffmpeg-4.4/libavcodec/dxa.c --- ffmpeg-4.2.2/libavcodec/dxa.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dxa.c 2021-04-08 21:28:39.000000000 +0000 @@ -343,7 +343,6 @@ c->dsize = avctx->width * avctx->height * 2; c->decomp_buf = av_malloc(c->dsize + DECOMP_BUF_PADDING); if (!c->decomp_buf) { - av_frame_free(&c->prev); av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); return AVERROR(ENOMEM); } @@ -371,4 +370,5 @@ .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/dxtory.c ffmpeg-4.4/libavcodec/dxtory.c --- ffmpeg-4.2.2/libavcodec/dxtory.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dxtory.c 2021-04-08 21:28:39.000000000 +0000 @@ -31,24 +31,84 @@ #include "get_bits.h" #include "internal.h" #include "unary.h" +#include "thread.h" + +static int64_t get_raw_size(enum AVPixelFormat fmt, int width, int height) +{ + switch (fmt) { + case AV_PIX_FMT_RGB555LE: + case AV_PIX_FMT_RGB565LE: + return width * height * 2LL; + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_BGR24: + case AV_PIX_FMT_YUV444P: + return width * height * 3LL; + case AV_PIX_FMT_YUV420P: + return (int64_t)(width * height) + 2 * AV_CEIL_RSHIFT(width, 1) * AV_CEIL_RSHIFT(height, 1); + case AV_PIX_FMT_YUV410P: + return (int64_t)(width * height) + 2 * AV_CEIL_RSHIFT(width, 2) * AV_CEIL_RSHIFT(height, 2); + } + + return 0; +} + +static void do_vflip(AVCodecContext *avctx, AVFrame *pic, int vflip) +{ + if (!vflip) + return; + + switch (pic->format) { + case AV_PIX_FMT_YUV444P: + pic->data[1] += (avctx->height - 1) * pic->linesize[1]; + pic->linesize[1] = -pic->linesize[1]; + pic->data[2] += (avctx->height - 1) * pic->linesize[2]; + pic->linesize[2] = -pic->linesize[2]; + case AV_PIX_FMT_RGB555LE: + case AV_PIX_FMT_RGB565LE: + case AV_PIX_FMT_BGR24: + case AV_PIX_FMT_RGB24: + pic->data[0] += (avctx->height - 1) * pic->linesize[0]; + pic->linesize[0] = -pic->linesize[0]; + break; + case AV_PIX_FMT_YUV410P: + pic->data[0] += (avctx->height - 1) * pic->linesize[0]; + pic->linesize[0] = -pic->linesize[0]; + pic->data[1] += (AV_CEIL_RSHIFT(avctx->height, 2) - 1) * pic->linesize[1]; + pic->linesize[1] = -pic->linesize[1]; + pic->data[2] += (AV_CEIL_RSHIFT(avctx->height, 2) - 1) * pic->linesize[2]; + pic->linesize[2] = -pic->linesize[2]; + break; + case AV_PIX_FMT_YUV420P: + pic->data[0] += (avctx->height - 1) * pic->linesize[0]; + pic->linesize[0] = -pic->linesize[0]; + pic->data[1] += (AV_CEIL_RSHIFT(avctx->height, 1) - 1) * pic->linesize[1]; + pic->linesize[1] = -pic->linesize[1]; + pic->data[2] += (AV_CEIL_RSHIFT(avctx->height, 1) - 1) * pic->linesize[2]; + pic->linesize[2] = -pic->linesize[2]; + break; + } +} static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size, - int id, int bpp) + int id, int bpp, uint32_t vflipped) { + ThreadFrame frame = { .f = pic }; int h; uint8_t *dst; int ret; - if (src_size < avctx->width * avctx->height * (int64_t)bpp) { + if (src_size < get_raw_size(id, avctx->width, avctx->height)) { av_log(avctx, AV_LOG_ERROR, "packet too small\n"); return AVERROR_INVALIDDATA; } avctx->pix_fmt = id; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + dst = pic->data[0]; for (h = 0; h < avctx->height; h++) { memcpy(dst, src, avctx->width * bpp); @@ -56,33 +116,47 @@ dst += pic->linesize[0]; } + do_vflip(avctx, pic, vflipped); + return 0; } static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { + ThreadFrame frame = { .f = pic }; int h, w; uint8_t *Y1, *Y2, *Y3, *Y4, *U, *V; + int height, width, hmargin, vmargin; + int huvborder; int ret; - if (src_size < FFALIGN(avctx->width, 4) * FFALIGN(avctx->height, 4) * 9LL / 8) { + if (src_size < get_raw_size(AV_PIX_FMT_YUV410P, avctx->width, avctx->height)) { av_log(avctx, AV_LOG_ERROR, "packet too small\n"); return AVERROR_INVALIDDATA; } avctx->pix_fmt = AV_PIX_FMT_YUV410P; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + + height = avctx->height & ~3; + width = avctx->width & ~3; + hmargin = avctx->width - width; + vmargin = avctx->height - height; + huvborder = AV_CEIL_RSHIFT(avctx->width, 2) - 1; + Y1 = pic->data[0]; Y2 = pic->data[0] + pic->linesize[0]; Y3 = pic->data[0] + pic->linesize[0] * 2; Y4 = pic->data[0] + pic->linesize[0] * 3; U = pic->data[1]; V = pic->data[2]; - for (h = 0; h < avctx->height; h += 4) { - for (w = 0; w < avctx->width; w += 4) { + for (h = 0; h < height; h += 4) { + for (w = 0; w < width; w += 4) { AV_COPY32U(Y1 + w, src); AV_COPY32U(Y2 + w, src + 4); AV_COPY32U(Y3 + w, src + 8); @@ -91,70 +165,151 @@ V[w >> 2] = src[17] + 0x80; src += 18; } - Y1 += pic->linesize[0] << 2; - Y2 += pic->linesize[0] << 2; - Y3 += pic->linesize[0] << 2; - Y4 += pic->linesize[0] << 2; + if (hmargin) { + for (w = 0; w < hmargin; w++) { + Y1[width + w] = src[w]; + Y2[width + w] = src[w + hmargin * 1]; + Y3[width + w] = src[w + hmargin * 2]; + Y4[width + w] = src[w + hmargin * 3]; + } + src += 4 * hmargin; + U[huvborder] = src[0] + 0x80; + V[huvborder] = src[1] + 0x80; + src += 2; + } + Y1 += pic->linesize[0] * 4; + Y2 += pic->linesize[0] * 4; + Y3 += pic->linesize[0] * 4; + Y4 += pic->linesize[0] * 4; U += pic->linesize[1]; V += pic->linesize[2]; } + if (vmargin) { + for (w = 0; w < width; w += 4) { + AV_COPY32U(Y1 + w, src); + if (vmargin > 1) + AV_COPY32U(Y2 + w, src + 4); + if (vmargin > 2) + AV_COPY32U(Y3 + w, src + 8); + src += 4 * vmargin; + U[w >> 2] = src[0] + 0x80; + V[w >> 2] = src[1] + 0x80; + src += 2; + } + if (hmargin) { + for (w = 0; w < hmargin; w++) { + AV_COPY32U(Y1 + w, src); + if (vmargin > 1) + AV_COPY32U(Y2 + w, src + 4); + if (vmargin > 2) + AV_COPY32U(Y3 + w, src + 8); + src += 4 * vmargin; + } + U[huvborder] = src[0] + 0x80; + V[huvborder] = src[1] + 0x80; + src += 2; + } + } + + do_vflip(avctx, pic, vflipped); + return 0; } static int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { + ThreadFrame frame = { .f = pic }; int h, w; uint8_t *Y1, *Y2, *U, *V; + int height, width, hmargin, vmargin; + int huvborder; int ret; - if (src_size < FFALIGN(avctx->width, 2) * FFALIGN(avctx->height, 2) * 3LL / 2) { + if (src_size < get_raw_size(AV_PIX_FMT_YUV420P, avctx->width, avctx->height)) { av_log(avctx, AV_LOG_ERROR, "packet too small\n"); return AVERROR_INVALIDDATA; } avctx->pix_fmt = AV_PIX_FMT_YUV420P; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + + height = avctx->height & ~1; + width = avctx->width & ~1; + hmargin = avctx->width - width; + vmargin = avctx->height - height; + huvborder = AV_CEIL_RSHIFT(avctx->width, 1) - 1; + Y1 = pic->data[0]; Y2 = pic->data[0] + pic->linesize[0]; U = pic->data[1]; V = pic->data[2]; - for (h = 0; h < avctx->height; h += 2) { - for (w = 0; w < avctx->width; w += 2) { + for (h = 0; h < height; h += 2) { + for (w = 0; w < width; w += 2) { AV_COPY16(Y1 + w, src); AV_COPY16(Y2 + w, src + 2); U[w >> 1] = src[4] + 0x80; V[w >> 1] = src[5] + 0x80; src += 6; } - Y1 += pic->linesize[0] << 1; - Y2 += pic->linesize[0] << 1; + if (hmargin) { + Y1[width + 1] = src[0]; + Y2[width + 1] = src[1]; + U[huvborder] = src[2] + 0x80; + V[huvborder] = src[3] + 0x80; + src += 4; + } + Y1 += pic->linesize[0] * 2; + Y2 += pic->linesize[0] * 2; U += pic->linesize[1]; V += pic->linesize[2]; } + if (vmargin) { + for (w = 0; w < width; w += 2) { + AV_COPY16U(Y1 + w, src); + U[w >> 1] = src[0] + 0x80; + V[w >> 1] = src[1] + 0x80; + src += 4; + } + if (hmargin) { + Y1[w] = src[0]; + U[huvborder] = src[1] + 0x80; + V[huvborder] = src[2] + 0x80; + src += 3; + } + } + + do_vflip(avctx, pic, vflipped); + return 0; } static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { + ThreadFrame frame = { .f = pic }; int h, w; uint8_t *Y, *U, *V; int ret; - if (src_size < avctx->width * avctx->height * 3LL) { + if (src_size < get_raw_size(AV_PIX_FMT_YUV444P, avctx->width, avctx->height)) { av_log(avctx, AV_LOG_ERROR, "packet too small\n"); return AVERROR_INVALIDDATA; } avctx->pix_fmt = AV_PIX_FMT_YUV444P; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + Y = pic->data[0]; U = pic->data[1]; V = pic->data[2]; @@ -169,6 +324,8 @@ V += pic->linesize[2]; } + do_vflip(avctx, pic, vflipped); + return 0; } @@ -270,8 +427,10 @@ const uint8_t *src, int src_size, decode_slice_func decode_slice, setup_lru_func setup_lru, - enum AVPixelFormat fmt) + enum AVPixelFormat fmt, + uint32_t vflipped) { + ThreadFrame frame = { .f = pic }; GetByteContext gb, gb_check; GetBitContext gb2; int nslices, slice, line = 0; @@ -298,9 +457,11 @@ return AVERROR_INVALIDDATA; avctx->pix_fmt = fmt; - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; + do_vflip(avctx, pic, vflipped); + for (slice = 0; slice < nslices; slice++) { slice_size = bytestream2_get_le32(&gb); @@ -322,6 +483,8 @@ avpriv_request_sample(avctx, "Not enough slice data available"); } + do_vflip(avctx, pic, vflipped); + return 0; } @@ -336,7 +499,7 @@ int stride = frame->linesize[0]; uint8_t *dst = frame->data[0] + stride * line; - for (y = 0; y < left && get_bits_left(gb) > 6 * width; y++) { + for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) { for (x = 0; x < width; x++) { b = decode_sym_565(gb, lru[0], 5); g = decode_sym_565(gb, lru[1], is_565 ? 6 : 5); @@ -379,19 +542,20 @@ } static int dxtory_decode_v2_565(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size, int is_565) + const uint8_t *src, int src_size, int is_565, + uint32_t vflipped) { enum AVPixelFormat fmt = AV_PIX_FMT_RGB24; if (is_565) return dxtory_decode_v2(avctx, pic, src, src_size, dx2_decode_slice_565, setup_lru_565, - fmt); + fmt, vflipped); else return dxtory_decode_v2(avctx, pic, src, src_size, dx2_decode_slice_555, setup_lru_555, - fmt); + fmt, vflipped); } static int dx2_decode_slice_rgb(GetBitContext *gb, AVFrame *frame, @@ -402,7 +566,7 @@ int stride = frame->linesize[0]; uint8_t *dst = frame->data[0] + stride * line; - for (y = 0; y < left && get_bits_left(gb) > 6 * width; y++) { + for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) { for (x = 0; x < width; x++) { dst[x * 3 + 0] = decode_sym(gb, lru[0]); dst[x * 3 + 1] = decode_sym(gb, lru[1]); @@ -424,12 +588,13 @@ } static int dxtory_decode_v2_rgb(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { return dxtory_decode_v2(avctx, pic, src, src_size, dx2_decode_slice_rgb, default_setup_lru, - AV_PIX_FMT_BGR24); + AV_PIX_FMT_BGR24, vflipped); } static int dx2_decode_slice_410(GetBitContext *gb, AVFrame *frame, @@ -447,31 +612,68 @@ uint8_t *U = frame->data[1] + (ustride >> 2) * line; uint8_t *V = frame->data[2] + (vstride >> 2) * line; - for (y = 0; y < left - 3 && get_bits_left(gb) > 9 * width; y += 4) { - for (x = 0; x < width; x += 4) { + int h, w, hmargin, vmargin; + int huvborder; + + h = frame->height & ~3; + w = frame->width & ~3; + hmargin = frame->width - w; + vmargin = frame->height - h; + huvborder = AV_CEIL_RSHIFT(frame->width, 2) - 1; + + for (y = 0; y < left - 3 && get_bits_left(gb) >= 18 * w / 4 + hmargin * 4 + (!!hmargin * 2); y += 4) { + for (x = 0; x < w; x += 4) { for (j = 0; j < 4; j++) for (i = 0; i < 4; i++) Y[x + i + j * ystride] = decode_sym(gb, lru[0]); U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80; V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80; } + if (hmargin) { + for (j = 0; j < 4; j++) + for (i = 0; i < hmargin; i++) + Y[x + i + j * ystride] = decode_sym(gb, lru[0]); + U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80; + V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80; + } - Y += ystride << 2; + Y += ystride * 4; U += ustride; V += vstride; } + if (vmargin && y + vmargin == left) { + for (x = 0; x < width; x += 4) { + for (j = 0; j < vmargin; j++) + for (i = 0; i < 4; i++) + Y[x + i + j * ystride] = decode_sym(gb, lru[0]); + U[x >> 2] = decode_sym(gb, lru[1]) ^ 0x80; + V[x >> 2] = decode_sym(gb, lru[2]) ^ 0x80; + } + if (hmargin) { + for (j = 0; j < vmargin; j++) { + for (i = 0; i < hmargin; i++) + Y[x + i + j * ystride] = decode_sym(gb, lru[0]); + } + U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80; + V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80; + } + + y += vmargin; + } + return y; } static int dxtory_decode_v2_410(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { return dxtory_decode_v2(avctx, pic, src, src_size, dx2_decode_slice_410, default_setup_lru, - AV_PIX_FMT_YUV410P); + AV_PIX_FMT_YUV410P, vflipped); } static int dx2_decode_slice_420(GetBitContext *gb, AVFrame *frame, @@ -490,9 +692,17 @@ uint8_t *U = frame->data[1] + (ustride >> 1) * line; uint8_t *V = frame->data[2] + (vstride >> 1) * line; + int h, w, hmargin, vmargin; + int huvborder; - for (y = 0; y < left - 1 && get_bits_left(gb) > 6 * width; y += 2) { - for (x = 0; x < width; x += 2) { + h = frame->height & ~1; + w = frame->width & ~1; + hmargin = frame->width - w; + vmargin = frame->height - h; + huvborder = AV_CEIL_RSHIFT(frame->width, 1) - 1; + + for (y = 0; y < left - 1 && get_bits_left(gb) >= 3 * w + hmargin * 4; y += 2) { + for (x = 0; x < w; x += 2) { Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]); Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]); Y[x + 0 + 1 * ystride] = decode_sym(gb, lru[0]); @@ -500,22 +710,42 @@ U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80; V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80; } + if (hmargin) { + Y[x + 0 * ystride] = decode_sym(gb, lru[0]); + Y[x + 1 * ystride] = decode_sym(gb, lru[0]); + U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80; + V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80; + } - Y += ystride << 1; + Y += ystride * 2; U += ustride; V += vstride; } + if (vmargin) { + for (x = 0; x < width; x += 2) { + Y[x + 0] = decode_sym(gb, lru[0]); + U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80; + V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80; + } + if (hmargin) { + Y[x] = decode_sym(gb, lru[0]); + U[huvborder] = decode_sym(gb, lru[1]) ^ 0x80; + V[huvborder] = decode_sym(gb, lru[2]) ^ 0x80; + } + } + return y; } static int dxtory_decode_v2_420(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { return dxtory_decode_v2(avctx, pic, src, src_size, dx2_decode_slice_420, default_setup_lru, - AV_PIX_FMT_YUV420P); + AV_PIX_FMT_YUV420P, vflipped); } static int dx2_decode_slice_444(GetBitContext *gb, AVFrame *frame, @@ -534,7 +764,7 @@ uint8_t *U = frame->data[1] + ustride * line; uint8_t *V = frame->data[2] + vstride * line; - for (y = 0; y < left && get_bits_left(gb) > 6 * width; y++) { + for (y = 0; y < left && get_bits_left(gb) >= 3 * width; y++) { for (x = 0; x < width; x++) { Y[x] = decode_sym(gb, lru[0]); U[x] = decode_sym(gb, lru[1]) ^ 0x80; @@ -550,12 +780,13 @@ } static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic, - const uint8_t *src, int src_size) + const uint8_t *src, int src_size, + uint32_t vflipped) { return dxtory_decode_v2(avctx, pic, src, src_size, dx2_decode_slice_444, default_setup_lru, - AV_PIX_FMT_YUV444P); + AV_PIX_FMT_YUV444P, vflipped); } static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, @@ -563,57 +794,75 @@ { AVFrame *pic = data; const uint8_t *src = avpkt->data; - int ret; + uint32_t type; + int vflipped, ret; if (avpkt->size < 16) { av_log(avctx, AV_LOG_ERROR, "packet too small\n"); return AVERROR_INVALIDDATA; } - switch (AV_RB32(src)) { + type = AV_RB32(src); + vflipped = !!(type & 0x20); + + switch (type) { + case 0x01000021: case 0x01000001: ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16, - AV_PIX_FMT_BGR24, 3); + AV_PIX_FMT_BGR24, 3, vflipped); break; + case 0x01000029: case 0x01000009: - ret = dxtory_decode_v2_rgb(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v2_rgb(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x02000021: case 0x02000001: - ret = dxtory_decode_v1_420(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v1_420(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x02000029: case 0x02000009: - ret = dxtory_decode_v2_420(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v2_420(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x03000021: case 0x03000001: - ret = dxtory_decode_v1_410(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v1_410(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x03000029: case 0x03000009: - ret = dxtory_decode_v2_410(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v2_410(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x04000021: case 0x04000001: - ret = dxtory_decode_v1_444(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v1_444(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x04000029: case 0x04000009: - ret = dxtory_decode_v2_444(avctx, pic, src + 16, avpkt->size - 16); + ret = dxtory_decode_v2_444(avctx, pic, src + 16, avpkt->size - 16, vflipped); break; + case 0x17000021: case 0x17000001: ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16, - AV_PIX_FMT_RGB565LE, 2); + AV_PIX_FMT_RGB565LE, 2, vflipped); break; + case 0x17000029: case 0x17000009: - ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 1); + ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 1, vflipped); break; + case 0x18000021: + case 0x19000021: case 0x18000001: case 0x19000001: ret = dxtory_decode_v1_rgb(avctx, pic, src + 16, avpkt->size - 16, - AV_PIX_FMT_RGB555LE, 2); + AV_PIX_FMT_RGB555LE, 2, vflipped); break; + case 0x18000029: + case 0x19000029: case 0x18000009: case 0x19000009: - ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0); + ret = dxtory_decode_v2_565(avctx, pic, src + 16, avpkt->size - 16, 0, vflipped); break; default: - avpriv_request_sample(avctx, "Frame header %"PRIX32, AV_RB32(src)); + avpriv_request_sample(avctx, "Frame header %"PRIX32, type); return AVERROR_PATCHWELCOME; } @@ -633,5 +882,5 @@ .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_DXTORY, .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, }; diff -Nru ffmpeg-4.2.2/libavcodec/dxva2_av1.c ffmpeg-4.4/libavcodec/dxva2_av1.c --- ffmpeg-4.2.2/libavcodec/dxva2_av1.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dxva2_av1.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,506 @@ +/* + * DXVA2 AV1 HW acceleration. + * + * copyright (c) 2020 Hendrik Leppkes + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/pixdesc.h" + +#include "dxva2_internal.h" +#include "av1dec.h" + +#define MAX_TILES 256 + +struct AV1DXVAContext { + FFDXVASharedContext shared; + + unsigned int bitstream_allocated; + uint8_t *bitstream_cache; +}; + +struct av1_dxva2_picture_context { + DXVA_PicParams_AV1 pp; + unsigned tile_count; + DXVA_Tile_AV1 tiles[MAX_TILES]; + uint8_t *bitstream; + unsigned bitstream_size; +}; + +static int get_bit_depth_from_seq(const AV1RawSequenceHeader *seq) +{ + if (seq->seq_profile == 2 && seq->color_config.high_bitdepth) + return seq->color_config.twelve_bit ? 12 : 10; + else if (seq->seq_profile <= 2 && seq->color_config.high_bitdepth) + return 10; + else + return 8; +} + +static int fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, const AV1DecContext *h, + DXVA_PicParams_AV1 *pp) +{ + int i,j, uses_lr; + const AV1RawSequenceHeader *seq = h->raw_seq; + const AV1RawFrameHeader *frame_header = h->raw_frame_header; + const AV1RawFilmGrainParams *film_grain = &h->cur_frame.film_grain; + + unsigned char remap_lr_type[4] = { AV1_RESTORE_NONE, AV1_RESTORE_SWITCHABLE, AV1_RESTORE_WIENER, AV1_RESTORE_SGRPROJ }; + int apply_grain = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && film_grain->apply_grain; + + memset(pp, 0, sizeof(*pp)); + + pp->width = avctx->width; + pp->height = avctx->height; + + pp->max_width = seq->max_frame_width_minus_1 + 1; + pp->max_height = seq->max_frame_height_minus_1 + 1; + + pp->CurrPicTextureIndex = ff_dxva2_get_surface_index(avctx, ctx, h->cur_frame.tf.f); + pp->superres_denom = frame_header->use_superres ? frame_header->coded_denom : AV1_SUPERRES_NUM; + pp->bitdepth = get_bit_depth_from_seq(seq); + pp->seq_profile = seq->seq_profile; + + /* Tiling info */ + pp->tiles.cols = frame_header->tile_cols; + pp->tiles.rows = frame_header->tile_rows; + pp->tiles.context_update_id = frame_header->context_update_tile_id; + + for (i = 0; i < pp->tiles.cols; i++) + pp->tiles.widths[i] = frame_header->width_in_sbs_minus_1[i] + 1; + + for (i = 0; i < pp->tiles.rows; i++) + pp->tiles.heights[i] = frame_header->height_in_sbs_minus_1[i] + 1; + + /* Coding tools */ + pp->coding.use_128x128_superblock = seq->use_128x128_superblock; + pp->coding.intra_edge_filter = seq->enable_intra_edge_filter; + pp->coding.interintra_compound = seq->enable_interintra_compound; + pp->coding.masked_compound = seq->enable_masked_compound; + pp->coding.warped_motion = frame_header->allow_warped_motion; + pp->coding.dual_filter = seq->enable_dual_filter; + pp->coding.jnt_comp = seq->enable_jnt_comp; + pp->coding.screen_content_tools = frame_header->allow_screen_content_tools; + pp->coding.integer_mv = frame_header->force_integer_mv || !(frame_header->frame_type & 1); + pp->coding.cdef = seq->enable_cdef; + pp->coding.restoration = seq->enable_restoration; + pp->coding.film_grain = seq->film_grain_params_present && !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN); + pp->coding.intrabc = frame_header->allow_intrabc; + pp->coding.high_precision_mv = frame_header->allow_high_precision_mv; + pp->coding.switchable_motion_mode = frame_header->is_motion_mode_switchable; + pp->coding.filter_intra = seq->enable_filter_intra; + pp->coding.disable_frame_end_update_cdf = frame_header->disable_frame_end_update_cdf; + pp->coding.disable_cdf_update = frame_header->disable_cdf_update; + pp->coding.reference_mode = frame_header->reference_select; + pp->coding.skip_mode = frame_header->skip_mode_present; + pp->coding.reduced_tx_set = frame_header->reduced_tx_set; + pp->coding.superres = frame_header->use_superres; + pp->coding.tx_mode = frame_header->tx_mode; + pp->coding.use_ref_frame_mvs = frame_header->use_ref_frame_mvs; + pp->coding.enable_ref_frame_mvs = seq->enable_ref_frame_mvs; + pp->coding.reference_frame_update = 1; // 0 for show_existing_frame with key frames, but those are not passed to the hwaccel + + /* Format & Picture Info flags */ + pp->format.frame_type = frame_header->frame_type; + pp->format.show_frame = frame_header->show_frame; + pp->format.showable_frame = frame_header->showable_frame; + pp->format.subsampling_x = seq->color_config.subsampling_x; + pp->format.subsampling_y = seq->color_config.subsampling_y; + pp->format.mono_chrome = seq->color_config.mono_chrome; + + /* References */ + pp->primary_ref_frame = frame_header->primary_ref_frame; + pp->order_hint = frame_header->order_hint; + pp->order_hint_bits = seq->enable_order_hint ? seq->order_hint_bits_minus_1 + 1 : 0; + + memset(pp->RefFrameMapTextureIndex, 0xFF, sizeof(pp->RefFrameMapTextureIndex)); + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + int8_t ref_idx = frame_header->ref_frame_idx[i]; + AVFrame *ref_frame = h->ref[ref_idx].tf.f; + + pp->frame_refs[i].width = ref_frame->width; + pp->frame_refs[i].height = ref_frame->height; + pp->frame_refs[i].Index = ref_frame->buf[0] ? ref_idx : 0xFF; + + /* Global Motion */ + pp->frame_refs[i].wminvalid = (h->cur_frame.gm_type[AV1_REF_FRAME_LAST + i] == AV1_WARP_MODEL_IDENTITY); + pp->frame_refs[i].wmtype = h->cur_frame.gm_type[AV1_REF_FRAME_LAST + i]; + for (j = 0; j < 6; ++j) { + pp->frame_refs[i].wmmat[j] = h->cur_frame.gm_params[AV1_REF_FRAME_LAST + i][j]; + } + } + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + AVFrame *ref_frame = h->ref[i].tf.f; + if (ref_frame->buf[0]) + pp->RefFrameMapTextureIndex[i] = ff_dxva2_get_surface_index(avctx, ctx, ref_frame); + } + + /* Loop filter parameters */ + pp->loop_filter.filter_level[0] = frame_header->loop_filter_level[0]; + pp->loop_filter.filter_level[1] = frame_header->loop_filter_level[1]; + pp->loop_filter.filter_level_u = frame_header->loop_filter_level[2]; + pp->loop_filter.filter_level_v = frame_header->loop_filter_level[3]; + pp->loop_filter.sharpness_level = frame_header->loop_filter_sharpness; + pp->loop_filter.mode_ref_delta_enabled = frame_header->loop_filter_delta_enabled; + pp->loop_filter.mode_ref_delta_update = frame_header->loop_filter_delta_update; + pp->loop_filter.delta_lf_multi = frame_header->delta_lf_multi; + pp->loop_filter.delta_lf_present = frame_header->delta_lf_present; + pp->loop_filter.delta_lf_res = frame_header->delta_lf_res; + + for (i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) { + pp->loop_filter.ref_deltas[i] = frame_header->loop_filter_ref_deltas[i]; + } + + pp->loop_filter.mode_deltas[0] = frame_header->loop_filter_mode_deltas[0]; + pp->loop_filter.mode_deltas[1] = frame_header->loop_filter_mode_deltas[1]; + pp->loop_filter.frame_restoration_type[0] = remap_lr_type[frame_header->lr_type[0]]; + pp->loop_filter.frame_restoration_type[1] = remap_lr_type[frame_header->lr_type[1]]; + pp->loop_filter.frame_restoration_type[2] = remap_lr_type[frame_header->lr_type[2]]; + uses_lr = frame_header->lr_type[0] || frame_header->lr_type[1] || frame_header->lr_type[2]; + pp->loop_filter.log2_restoration_unit_size[0] = uses_lr ? (6 + frame_header->lr_unit_shift) : 8; + pp->loop_filter.log2_restoration_unit_size[1] = uses_lr ? (6 + frame_header->lr_unit_shift - frame_header->lr_uv_shift) : 8; + pp->loop_filter.log2_restoration_unit_size[2] = uses_lr ? (6 + frame_header->lr_unit_shift - frame_header->lr_uv_shift) : 8; + + /* Quantization */ + pp->quantization.delta_q_present = frame_header->delta_q_present; + pp->quantization.delta_q_res = frame_header->delta_q_res; + pp->quantization.base_qindex = frame_header->base_q_idx; + pp->quantization.y_dc_delta_q = frame_header->delta_q_y_dc; + pp->quantization.u_dc_delta_q = frame_header->delta_q_u_dc; + pp->quantization.v_dc_delta_q = frame_header->delta_q_v_dc; + pp->quantization.u_ac_delta_q = frame_header->delta_q_u_ac; + pp->quantization.v_ac_delta_q = frame_header->delta_q_v_ac; + pp->quantization.qm_y = frame_header->using_qmatrix ? frame_header->qm_y : 0xFF; + pp->quantization.qm_u = frame_header->using_qmatrix ? frame_header->qm_u : 0xFF; + pp->quantization.qm_v = frame_header->using_qmatrix ? frame_header->qm_v : 0xFF; + + /* Cdef parameters */ + pp->cdef.damping = frame_header->cdef_damping_minus_3; + pp->cdef.bits = frame_header->cdef_bits; + for (i = 0; i < 8; i++) { + pp->cdef.y_strengths[i].primary = frame_header->cdef_y_pri_strength[i]; + pp->cdef.y_strengths[i].secondary = frame_header->cdef_y_sec_strength[i]; + pp->cdef.uv_strengths[i].primary = frame_header->cdef_uv_pri_strength[i]; + pp->cdef.uv_strengths[i].secondary = frame_header->cdef_uv_sec_strength[i]; + } + + /* Misc flags */ + pp->interp_filter = frame_header->interpolation_filter; + + /* Segmentation */ + pp->segmentation.enabled = frame_header->segmentation_enabled; + pp->segmentation.update_map = frame_header->segmentation_update_map; + pp->segmentation.update_data = frame_header->segmentation_update_data; + pp->segmentation.temporal_update = frame_header->segmentation_temporal_update; + for (i = 0; i < AV1_MAX_SEGMENTS; i++) { + for (j = 0; j < AV1_SEG_LVL_MAX; j++) { + pp->segmentation.feature_mask[i].mask |= frame_header->feature_enabled[i][j] << j; + pp->segmentation.feature_data[i][j] = frame_header->feature_value[i][j]; + } + } + + /* Film grain */ + if (apply_grain) { + pp->film_grain.apply_grain = 1; + pp->film_grain.scaling_shift_minus8 = film_grain->grain_scaling_minus_8; + pp->film_grain.chroma_scaling_from_luma = film_grain->chroma_scaling_from_luma; + pp->film_grain.ar_coeff_lag = film_grain->ar_coeff_lag; + pp->film_grain.ar_coeff_shift_minus6 = film_grain->ar_coeff_shift_minus_6; + pp->film_grain.grain_scale_shift = film_grain->grain_scale_shift; + pp->film_grain.overlap_flag = film_grain->overlap_flag; + pp->film_grain.clip_to_restricted_range = film_grain->clip_to_restricted_range; + pp->film_grain.matrix_coeff_is_identity = (seq->color_config.matrix_coefficients == AVCOL_SPC_RGB); + + pp->film_grain.grain_seed = film_grain->grain_seed; + pp->film_grain.num_y_points = film_grain->num_y_points; + for (i = 0; i < film_grain->num_y_points; i++) { + pp->film_grain.scaling_points_y[i][0] = film_grain->point_y_value[i]; + pp->film_grain.scaling_points_y[i][1] = film_grain->point_y_scaling[i]; + } + pp->film_grain.num_cb_points = film_grain->num_cb_points; + for (i = 0; i < film_grain->num_cb_points; i++) { + pp->film_grain.scaling_points_cb[i][0] = film_grain->point_cb_value[i]; + pp->film_grain.scaling_points_cb[i][1] = film_grain->point_cb_scaling[i]; + } + pp->film_grain.num_cr_points = film_grain->num_cr_points; + for (i = 0; i < film_grain->num_cr_points; i++) { + pp->film_grain.scaling_points_cr[i][0] = film_grain->point_cr_value[i]; + pp->film_grain.scaling_points_cr[i][1] = film_grain->point_cr_scaling[i]; + } + for (i = 0; i < 24; i++) { + pp->film_grain.ar_coeffs_y[i] = film_grain->ar_coeffs_y_plus_128[i]; + } + for (i = 0; i < 25; i++) { + pp->film_grain.ar_coeffs_cb[i] = film_grain->ar_coeffs_cb_plus_128[i]; + pp->film_grain.ar_coeffs_cr[i] = film_grain->ar_coeffs_cr_plus_128[i]; + } + pp->film_grain.cb_mult = film_grain->cb_mult; + pp->film_grain.cb_luma_mult = film_grain->cb_luma_mult; + pp->film_grain.cr_mult = film_grain->cr_mult; + pp->film_grain.cr_luma_mult = film_grain->cr_luma_mult; + pp->film_grain.cb_offset = film_grain->cb_offset; + pp->film_grain.cr_offset = film_grain->cr_offset; + pp->film_grain.cr_offset = film_grain->cr_offset; + } + + // XXX: Setting the StatusReportFeedbackNumber breaks decoding on some drivers (tested on NVIDIA 457.09) + // Status Reporting is not used by FFmpeg, hence not providing a number does not cause any issues + //pp->StatusReportFeedbackNumber = 1 + DXVA_CONTEXT_REPORT_ID(avctx, ctx)++; + return 0; +} + +static int dxva2_av1_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + const AV1DecContext *h = avctx->priv_data; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); + struct av1_dxva2_picture_context *ctx_pic = h->cur_frame.hwaccel_picture_private; + + if (!DXVA_CONTEXT_VALID(avctx, ctx)) + return -1; + av_assert0(ctx_pic); + + /* Fill up DXVA_PicParams_AV1 */ + if (fill_picture_parameters(avctx, ctx, h, &ctx_pic->pp) < 0) + return -1; + + ctx_pic->bitstream_size = 0; + ctx_pic->bitstream = NULL; + return 0; +} + +static int dxva2_av1_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + const AV1DecContext *h = avctx->priv_data; + const AV1RawFrameHeader *frame_header = h->raw_frame_header; + struct av1_dxva2_picture_context *ctx_pic = h->cur_frame.hwaccel_picture_private; + struct AV1DXVAContext *ctx = avctx->internal->hwaccel_priv_data; + void *tmp; + + ctx_pic->tile_count = frame_header->tile_cols * frame_header->tile_rows; + + /* too many tiles, exceeding all defined levels in the AV1 spec */ + if (ctx_pic->tile_count > MAX_TILES) + return AVERROR(ENOSYS); + + /* Shortcut if all tiles are in the same buffer */ + if (ctx_pic->tile_count == h->tg_end - h->tg_start + 1) { + ctx_pic->bitstream = (uint8_t *)buffer; + ctx_pic->bitstream_size = size; + + for (uint32_t tile_num = 0; tile_num < ctx_pic->tile_count; tile_num++) { + ctx_pic->tiles[tile_num].DataOffset = h->tile_group_info[tile_num].tile_offset; + ctx_pic->tiles[tile_num].DataSize = h->tile_group_info[tile_num].tile_size; + ctx_pic->tiles[tile_num].row = h->tile_group_info[tile_num].tile_row; + ctx_pic->tiles[tile_num].column = h->tile_group_info[tile_num].tile_column; + ctx_pic->tiles[tile_num].anchor_frame = 0xFF; + } + + return 0; + } + + /* allocate an internal buffer */ + tmp = av_fast_realloc(ctx->bitstream_cache, &ctx->bitstream_allocated, + ctx_pic->bitstream_size + size); + if (!tmp) { + return AVERROR(ENOMEM); + } + ctx_pic->bitstream = ctx->bitstream_cache = tmp; + + memcpy(ctx_pic->bitstream + ctx_pic->bitstream_size, buffer, size); + + for (uint32_t tile_num = h->tg_start; tile_num <= h->tg_end; tile_num++) { + ctx_pic->tiles[tile_num].DataOffset = ctx_pic->bitstream_size + h->tile_group_info[tile_num].tile_offset; + ctx_pic->tiles[tile_num].DataSize = h->tile_group_info[tile_num].tile_size; + ctx_pic->tiles[tile_num].row = h->tile_group_info[tile_num].tile_row; + ctx_pic->tiles[tile_num].column = h->tile_group_info[tile_num].tile_column; + ctx_pic->tiles[tile_num].anchor_frame = 0xFF; + } + + ctx_pic->bitstream_size += size; + + return 0; +} + +static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, + DECODER_BUFFER_DESC *bs, + DECODER_BUFFER_DESC *sc) +{ + const AV1DecContext *h = avctx->priv_data; + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); + struct av1_dxva2_picture_context *ctx_pic = h->cur_frame.hwaccel_picture_private; + void *dxva_data_ptr; + uint8_t *dxva_data; + unsigned dxva_size; + unsigned padding; + unsigned type; + +#if CONFIG_D3D11VA + if (ff_dxva2_is_d3d11(avctx)) { + type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; + if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, + D3D11VA_CONTEXT(ctx)->decoder, + type, + &dxva_size, &dxva_data_ptr))) + return -1; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + type = DXVA2_BitStreamDateBufferType; + if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, + type, + &dxva_data_ptr, &dxva_size))) + return -1; + } +#endif + + dxva_data = dxva_data_ptr; + + if (ctx_pic->bitstream_size > dxva_size) { + av_log(avctx, AV_LOG_ERROR, "Bitstream size exceeds hardware buffer"); + return -1; + } + + memcpy(dxva_data, ctx_pic->bitstream, ctx_pic->bitstream_size); + + padding = FFMIN(128 - ((ctx_pic->bitstream_size) & 127), dxva_size - ctx_pic->bitstream_size); + if (padding > 0) { + memset(dxva_data + ctx_pic->bitstream_size, 0, padding); + ctx_pic->bitstream_size += padding; + } + +#if CONFIG_D3D11VA + if (ff_dxva2_is_d3d11(avctx)) + if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type))) + return -1; +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) + if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type))) + return -1; +#endif + +#if CONFIG_D3D11VA + if (ff_dxva2_is_d3d11(avctx)) { + D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs; + memset(dsc11, 0, sizeof(*dsc11)); + dsc11->BufferType = type; + dsc11->DataSize = ctx_pic->bitstream_size; + dsc11->NumMBsInBuffer = 0; + + type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL; + } +#endif +#if CONFIG_DXVA2 + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + DXVA2_DecodeBufferDesc *dsc2 = bs; + memset(dsc2, 0, sizeof(*dsc2)); + dsc2->CompressedBufferType = type; + dsc2->DataSize = ctx_pic->bitstream_size; + dsc2->NumMBsInBuffer = 0; + + type = DXVA2_SliceControlBufferType; + } +#endif + + return ff_dxva2_commit_buffer(avctx, ctx, sc, type, + ctx_pic->tiles, sizeof(*ctx_pic->tiles) * ctx_pic->tile_count, 0); +} + +static int dxva2_av1_end_frame(AVCodecContext *avctx) +{ + const AV1DecContext *h = avctx->priv_data; + struct av1_dxva2_picture_context *ctx_pic = h->cur_frame.hwaccel_picture_private; + int ret; + + if (ctx_pic->bitstream_size <= 0) + return -1; + + ret = ff_dxva2_common_end_frame(avctx, h->cur_frame.tf.f, + &ctx_pic->pp, sizeof(ctx_pic->pp), + NULL, 0, + commit_bitstream_and_slice_buffer); + + return ret; +} + +static int dxva2_av1_uninit(AVCodecContext *avctx) +{ + struct AV1DXVAContext *ctx = avctx->internal->hwaccel_priv_data; + + av_freep(&ctx->bitstream_cache); + ctx->bitstream_allocated = 0; + + return ff_dxva2_decode_uninit(avctx); +} + +#if CONFIG_AV1_DXVA2_HWACCEL +const AVHWAccel ff_av1_dxva2_hwaccel = { + .name = "av1_dxva2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .pix_fmt = AV_PIX_FMT_DXVA2_VLD, + .init = ff_dxva2_decode_init, + .uninit = dxva2_av1_uninit, + .start_frame = dxva2_av1_start_frame, + .decode_slice = dxva2_av1_decode_slice, + .end_frame = dxva2_av1_end_frame, + .frame_params = ff_dxva2_common_frame_params, + .frame_priv_data_size = sizeof(struct av1_dxva2_picture_context), + .priv_data_size = sizeof(struct AV1DXVAContext), +}; +#endif + +#if CONFIG_AV1_D3D11VA_HWACCEL +const AVHWAccel ff_av1_d3d11va_hwaccel = { + .name = "av1_d3d11va", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .pix_fmt = AV_PIX_FMT_D3D11VA_VLD, + .init = ff_dxva2_decode_init, + .uninit = dxva2_av1_uninit, + .start_frame = dxva2_av1_start_frame, + .decode_slice = dxva2_av1_decode_slice, + .end_frame = dxva2_av1_end_frame, + .frame_params = ff_dxva2_common_frame_params, + .frame_priv_data_size = sizeof(struct av1_dxva2_picture_context), + .priv_data_size = sizeof(struct AV1DXVAContext), +}; +#endif + +#if CONFIG_AV1_D3D11VA2_HWACCEL +const AVHWAccel ff_av1_d3d11va2_hwaccel = { + .name = "av1_d3d11va2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .pix_fmt = AV_PIX_FMT_D3D11, + .init = ff_dxva2_decode_init, + .uninit = dxva2_av1_uninit, + .start_frame = dxva2_av1_start_frame, + .decode_slice = dxva2_av1_decode_slice, + .end_frame = dxva2_av1_end_frame, + .frame_params = ff_dxva2_common_frame_params, + .frame_priv_data_size = sizeof(struct av1_dxva2_picture_context), + .priv_data_size = sizeof(struct AV1DXVAContext), +}; +#endif diff -Nru ffmpeg-4.2.2/libavcodec/dxva2.c ffmpeg-4.4/libavcodec/dxva2.c --- ffmpeg-4.2.2/libavcodec/dxva2.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dxva2.c 2021-04-08 21:28:39.000000000 +0000 @@ -45,6 +45,7 @@ DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main10,0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13); DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_Profile0,0x463707f8,0xa1d0,0x4585,0x87,0x6d,0x83,0xaa,0x6d,0x60,0xb8,0x9e); DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_10bit_Profile2,0xa4c749ef,0x6ecf,0x48aa,0x84,0x48,0x50,0xa7,0xa1,0x16,0x5f,0xf7); +DEFINE_GUID(ff_DXVA2_ModeAV1_VLD_Profile0,0xb8be4ccb,0xcf53,0x46ba,0x8d,0x59,0xd6,0xb8,0xa6,0xda,0x5d,0x2a); DEFINE_GUID(ff_DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); DEFINE_GUID(ff_GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00); DEFINE_GUID(ff_IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02); @@ -72,6 +73,8 @@ FF_PROFILE_UNKNOWN}; static const int prof_vp9_profile2[] = {FF_PROFILE_VP9_2, FF_PROFILE_UNKNOWN}; +static const int prof_av1_profile0[] = {FF_PROFILE_AV1_MAIN, + FF_PROFILE_UNKNOWN}; static const dxva_mode dxva_modes[] = { /* MPEG-2 */ @@ -98,6 +101,9 @@ { &ff_DXVA2_ModeVP9_VLD_Profile0, AV_CODEC_ID_VP9, prof_vp9_profile0 }, { &ff_DXVA2_ModeVP9_VLD_10bit_Profile2, AV_CODEC_ID_VP9, prof_vp9_profile2 }, + /* AV1 */ + { &ff_DXVA2_ModeAV1_VLD_Profile0, AV_CODEC_ID_AV1, prof_av1_profile0 }, + { NULL, 0 }, }; @@ -604,7 +610,7 @@ surface_alignment = 32; /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure all coding features have enough room to work with */ - else if (avctx->codec_id == AV_CODEC_ID_HEVC) + else if (avctx->codec_id == AV_CODEC_ID_HEVC || avctx->codec_id == AV_CODEC_ID_AV1) surface_alignment = 128; else surface_alignment = 16; @@ -615,7 +621,7 @@ /* add surfaces based on number of possible refs */ if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC) num_surfaces += 16; - else if (avctx->codec_id == AV_CODEC_ID_VP9) + else if (avctx->codec_id == AV_CODEC_ID_VP9 || avctx->codec_id == AV_CODEC_ID_AV1) num_surfaces += 8; else num_surfaces += 2; diff -Nru ffmpeg-4.2.2/libavcodec/dxv.c ffmpeg-4.4/libavcodec/dxv.c --- ffmpeg-4.2.2/libavcodec/dxv.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dxv.c 2020-07-11 10:39:30.000000000 +0000 @@ -867,8 +867,8 @@ { DXVContext *ctx = avctx->priv_data; GetByteContext *gbc = &ctx->gbc; - uint32_t value, op; - int idx, prev, state = 0; + uint32_t value, op, prev; + int idx, state = 0; int pos = 4; int run = 0; int probe, check; diff -Nru ffmpeg-4.2.2/libavcodec/dynamic_hdr10_plus.c ffmpeg-4.4/libavcodec/dynamic_hdr10_plus.c --- ffmpeg-4.2.2/libavcodec/dynamic_hdr10_plus.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dynamic_hdr10_plus.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,198 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "dynamic_hdr10_plus.h" +#include "get_bits.h" + +static const int64_t luminance_den = 1; +static const int32_t peak_luminance_den = 15; +static const int64_t rgb_den = 100000; +static const int32_t fraction_pixel_den = 1000; +static const int32_t knee_point_den = 4095; +static const int32_t bezier_anchor_den = 1023; +static const int32_t saturation_weight_den = 8; + +int ff_parse_itu_t_t35_to_dynamic_hdr10_plus(AVDynamicHDRPlus *s, const uint8_t *data, + int size) +{ + GetBitContext gbc, *gb = &gbc; + int ret; + + if (!s) + return AVERROR(ENOMEM); + + ret = init_get_bits8(gb, data, size); + if (ret < 0) + return ret; + + s->application_version = get_bits(gb, 8); + + if (get_bits_left(gb) < 2) + return AVERROR_INVALIDDATA; + s->num_windows = get_bits(gb, 2); + + if (s->num_windows < 1 || s->num_windows > 3) { + return AVERROR_INVALIDDATA; + } + + if (get_bits_left(gb) < ((19 * 8 + 1) * (s->num_windows - 1))) + return AVERROR_INVALIDDATA; + + for (int w = 1; w < s->num_windows; w++) { + // The corners are set to absolute coordinates here. They should be + // converted to the relative coordinates (in [0, 1]) in the decoder. + AVHDRPlusColorTransformParams *params = &s->params[w]; + params->window_upper_left_corner_x = + (AVRational){get_bits(gb, 16), 1}; + params->window_upper_left_corner_y = + (AVRational){get_bits(gb, 16), 1}; + params->window_lower_right_corner_x = + (AVRational){get_bits(gb, 16), 1}; + params->window_lower_right_corner_y = + (AVRational){get_bits(gb, 16), 1}; + + params->center_of_ellipse_x = get_bits(gb, 16); + params->center_of_ellipse_y = get_bits(gb, 16); + params->rotation_angle = get_bits(gb, 8); + params->semimajor_axis_internal_ellipse = get_bits(gb, 16); + params->semimajor_axis_external_ellipse = get_bits(gb, 16); + params->semiminor_axis_external_ellipse = get_bits(gb, 16); + params->overlap_process_option = get_bits1(gb); + } + + if (get_bits_left(gb) < 28) + return AVERROR(EINVAL); + + s->targeted_system_display_maximum_luminance = + (AVRational){get_bits_long(gb, 27), luminance_den}; + s->targeted_system_display_actual_peak_luminance_flag = get_bits1(gb); + + if (s->targeted_system_display_actual_peak_luminance_flag) { + int rows, cols; + if (get_bits_left(gb) < 10) + return AVERROR(EINVAL); + rows = get_bits(gb, 5); + cols = get_bits(gb, 5); + if (((rows < 2) || (rows > 25)) || ((cols < 2) || (cols > 25))) { + return AVERROR_INVALIDDATA; + } + s->num_rows_targeted_system_display_actual_peak_luminance = rows; + s->num_cols_targeted_system_display_actual_peak_luminance = cols; + + if (get_bits_left(gb) < (rows * cols * 4)) + return AVERROR(EINVAL); + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + s->targeted_system_display_actual_peak_luminance[i][j] = + (AVRational){get_bits(gb, 4), peak_luminance_den}; + } + } + } + for (int w = 0; w < s->num_windows; w++) { + AVHDRPlusColorTransformParams *params = &s->params[w]; + if (get_bits_left(gb) < (3 * 17 + 17 + 4)) + return AVERROR(EINVAL); + + for (int i = 0; i < 3; i++) { + params->maxscl[i] = + (AVRational){get_bits(gb, 17), rgb_den}; + } + params->average_maxrgb = + (AVRational){get_bits(gb, 17), rgb_den}; + params->num_distribution_maxrgb_percentiles = get_bits(gb, 4); + + if (get_bits_left(gb) < + (params->num_distribution_maxrgb_percentiles * 24)) + return AVERROR(EINVAL); + + for (int i = 0; i < params->num_distribution_maxrgb_percentiles; i++) { + params->distribution_maxrgb[i].percentage = get_bits(gb, 7); + params->distribution_maxrgb[i].percentile = + (AVRational){get_bits(gb, 17), rgb_den}; + } + + if (get_bits_left(gb) < 10) + return AVERROR(EINVAL); + + params->fraction_bright_pixels = (AVRational){get_bits(gb, 10), fraction_pixel_den}; + } + if (get_bits_left(gb) < 1) + return AVERROR(EINVAL); + s->mastering_display_actual_peak_luminance_flag = get_bits1(gb); + if (s->mastering_display_actual_peak_luminance_flag) { + int rows, cols; + if (get_bits_left(gb) < 10) + return AVERROR(EINVAL); + rows = get_bits(gb, 5); + cols = get_bits(gb, 5); + if (((rows < 2) || (rows > 25)) || ((cols < 2) || (cols > 25))) { + return AVERROR_INVALIDDATA; + } + s->num_rows_mastering_display_actual_peak_luminance = rows; + s->num_cols_mastering_display_actual_peak_luminance = cols; + + if (get_bits_left(gb) < (rows * cols * 4)) + return AVERROR(EINVAL); + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + s->mastering_display_actual_peak_luminance[i][j] = + (AVRational){get_bits(gb, 4), peak_luminance_den}; + } + } + } + + for (int w = 0; w < s->num_windows; w++) { + AVHDRPlusColorTransformParams *params = &s->params[w]; + if (get_bits_left(gb) < 1) + return AVERROR(EINVAL); + + params->tone_mapping_flag = get_bits1(gb); + if (params->tone_mapping_flag) { + if (get_bits_left(gb) < 28) + return AVERROR(EINVAL); + + params->knee_point_x = + (AVRational){get_bits(gb, 12), knee_point_den}; + params->knee_point_y = + (AVRational){get_bits(gb, 12), knee_point_den}; + params->num_bezier_curve_anchors = get_bits(gb, 4); + + if (get_bits_left(gb) < (params->num_bezier_curve_anchors * 10)) + return AVERROR(EINVAL); + + for (int i = 0; i < params->num_bezier_curve_anchors; i++) { + params->bezier_curve_anchors[i] = + (AVRational){get_bits(gb, 10), bezier_anchor_den}; + } + } + + if (get_bits_left(gb) < 1) + return AVERROR(EINVAL); + params->color_saturation_mapping_flag = get_bits1(gb); + if (params->color_saturation_mapping_flag) { + if (get_bits_left(gb) < 6) + return AVERROR(EINVAL); + params->color_saturation_weight = + (AVRational){get_bits(gb, 6), saturation_weight_den}; + } + } + + return 0; +} diff -Nru ffmpeg-4.2.2/libavcodec/dynamic_hdr10_plus.h ffmpeg-4.4/libavcodec/dynamic_hdr10_plus.h --- ffmpeg-4.2.2/libavcodec/dynamic_hdr10_plus.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/dynamic_hdr10_plus.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,35 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DYNAMIC_HDR10_PLUS_H +#define AVCODEC_DYNAMIC_HDR10_PLUS_H + +#include "libavutil/hdr_dynamic_metadata.h" + +/** + * Parse the user data registered ITU-T T.35 to AVbuffer (AVDynamicHDRPlus). + * @param s A pointer containing the decoded AVDynamicHDRPlus structure. + * @param data The byte array containing the raw ITU-T T.35 data. + * @param size Size of the data array in bytes. + * + * @return 0 if succeed. Otherwise, returns the appropriate AVERROR. + */ +int ff_parse_itu_t_t35_to_dynamic_hdr10_plus(AVDynamicHDRPlus *s, const uint8_t *data, + int size); + +#endif /* AVCODEC_DYNAMIC_HDR10_PLUS_H */ diff -Nru ffmpeg-4.2.2/libavcodec/eac3_core_bsf.c ffmpeg-4.4/libavcodec/eac3_core_bsf.c --- ffmpeg-4.2.2/libavcodec/eac3_core_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/eac3_core_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "get_bits.h" #include "ac3_parser_internal.h" diff -Nru ffmpeg-4.2.2/libavcodec/eac3enc.c ffmpeg-4.4/libavcodec/eac3enc.c --- ffmpeg-4.2.2/libavcodec/eac3enc.c 2016-03-29 02:25:13.000000000 +0000 +++ ffmpeg-4.4/libavcodec/eac3enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,7 +24,7 @@ * E-AC-3 encoder */ -#define CONFIG_AC3ENC_FLOAT 1 +#define AC3ENC_FLOAT 1 #include "libavutil/attributes.h" #include "ac3enc.h" @@ -32,13 +32,10 @@ #include "eac3_data.h" -#define AC3ENC_TYPE AC3ENC_TYPE_EAC3 -#include "ac3enc_opts_template.c" - static const AVClass eac3enc_class = { .class_name = "E-AC-3 Encoder", .item_name = av_default_item_name, - .option = ac3_options, + .option = &ff_ac3_enc_options[2], /* First two options are AC-3 only. */ .version = LIBAVUTIL_VERSION_INT, }; @@ -263,6 +260,8 @@ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .priv_class = &eac3enc_class, + .supported_samplerates = ff_ac3_sample_rate_tab, .channel_layouts = ff_ac3_channel_layouts, - .defaults = ac3_defaults, + .defaults = ff_ac3_enc_defaults, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/eacmv.c ffmpeg-4.4/libavcodec/eacmv.c --- ffmpeg-4.2.2/libavcodec/eacmv.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/eacmv.c 2021-04-08 21:28:39.000000000 +0000 @@ -50,11 +50,8 @@ s->last_frame = av_frame_alloc(); s->last2_frame = av_frame_alloc(); - if (!s->last_frame || !s->last2_frame) { - av_frame_free(&s->last_frame); - av_frame_free(&s->last2_frame); + if (!s->last_frame || !s->last2_frame) return AVERROR(ENOMEM); - } return 0; } @@ -243,4 +240,5 @@ .close = cmv_decode_end, .decode = cmv_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/eamad.c ffmpeg-4.4/libavcodec/eamad.c --- ffmpeg-4.2.2/libavcodec/eamad.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/eamad.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,6 +28,8 @@ * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_MAD */ +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "blockdsp.h" #include "bytestream.h" @@ -349,4 +351,5 @@ .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/eatgq.c ffmpeg-4.4/libavcodec/eatgq.c --- ffmpeg-4.2.2/libavcodec/eatgq.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/eatgq.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,9 @@ */ #define BITSTREAM_READER_LE + +#include "libavutil/mem_internal.h" + #include "aandcttab.h" #include "avcodec.h" #include "bytestream.h" diff -Nru ffmpeg-4.2.2/libavcodec/eatqi.c ffmpeg-4.4/libavcodec/eatqi.c --- ffmpeg-4.2.2/libavcodec/eatqi.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/eatqi.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,8 @@ * @see http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TQI */ +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "blockdsp.h" #include "bswapdsp.h" @@ -189,4 +191,5 @@ .close = tqi_decode_end, .decode = tqi_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/encode.c ffmpeg-4.4/libavcodec/encode.c --- ffmpeg-4.2.2/libavcodec/encode.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/encode.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,71 +26,101 @@ #include "libavutil/samplefmt.h" #include "avcodec.h" +#include "encode.h" #include "frame_thread_encoder.h" #include "internal.h" int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64_t min_size) { - if (avpkt->size < 0) { - av_log(avctx, AV_LOG_ERROR, "Invalid negative user packet size %d\n", avpkt->size); - return AVERROR(EINVAL); - } if (size < 0 || size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { av_log(avctx, AV_LOG_ERROR, "Invalid minimum required packet size %"PRId64" (max allowed is %d)\n", size, INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE); return AVERROR(EINVAL); } + av_assert0(!avpkt->data); + if (avctx && 2*min_size < size) { // FIXME The factor needs to be finetuned - av_assert0(!avpkt->data || avpkt->data != avctx->internal->byte_buffer); - if (!avpkt->data || avpkt->size < size) { - av_fast_padded_malloc(&avctx->internal->byte_buffer, &avctx->internal->byte_buffer_size, size); - avpkt->data = avctx->internal->byte_buffer; - avpkt->size = avctx->internal->byte_buffer_size; - } + av_fast_padded_malloc(&avctx->internal->byte_buffer, &avctx->internal->byte_buffer_size, size); + avpkt->data = avctx->internal->byte_buffer; + avpkt->size = size; } - if (avpkt->data) { - AVBufferRef *buf = avpkt->buf; - - if (avpkt->size < size) { - av_log(avctx, AV_LOG_ERROR, "User packet is too small (%d < %"PRId64")\n", avpkt->size, size); - return AVERROR(EINVAL); - } - - av_init_packet(avpkt); - avpkt->buf = buf; - avpkt->size = size; - return 0; - } else { + if (!avpkt->data) { int ret = av_new_packet(avpkt, size); if (ret < 0) av_log(avctx, AV_LOG_ERROR, "Failed to allocate packet of size %"PRId64"\n", size); return ret; } + + return 0; } -int ff_alloc_packet(AVPacket *avpkt, int size) +int avcodec_default_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int flags) { - return ff_alloc_packet2(NULL, avpkt, size, 0); + int ret; + + if (avpkt->size < 0 || avpkt->size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) + return AVERROR(EINVAL); + + if (avpkt->data || avpkt->buf) { + av_log(avctx, AV_LOG_ERROR, "avpkt->{data,buf} != NULL in avcodec_default_get_encode_buffer()\n"); + return AVERROR(EINVAL); + } + + ret = av_buffer_realloc(&avpkt->buf, avpkt->size + AV_INPUT_BUFFER_PADDING_SIZE); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to allocate packet of size %d\n", avpkt->size); + return ret; + } + avpkt->data = avpkt->buf->data; + memset(avpkt->data + avpkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + return 0; +} + +int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags) +{ + int ret; + + if (size < 0 || size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) + return AVERROR(EINVAL); + + av_assert0(!avpkt->data && !avpkt->buf); + + avpkt->size = size; + ret = avctx->get_encode_buffer(avctx, avpkt, flags); + if (ret < 0) + goto fail; + + if (!avpkt->data || !avpkt->buf) { + av_log(avctx, AV_LOG_ERROR, "No buffer returned by get_encode_buffer()\n"); + ret = AVERROR(EINVAL); + goto fail; + } + + ret = 0; +fail: + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "get_encode_buffer() failed\n"); + av_packet_unref(avpkt); + } + + return ret; } /** * Pad last frame with silence. */ -static int pad_last_frame(AVCodecContext *s, AVFrame **dst, const AVFrame *src) +static int pad_last_frame(AVCodecContext *s, AVFrame *frame, const AVFrame *src) { - AVFrame *frame = NULL; int ret; - if (!(frame = av_frame_alloc())) - return AVERROR(ENOMEM); - frame->format = src->format; frame->channel_layout = src->channel_layout; frame->channels = src->channels; frame->nb_samples = s->frame_size; - ret = av_frame_get_buffer(frame, 32); + ret = av_frame_get_buffer(frame, 0); if (ret < 0) goto fail; @@ -106,342 +136,547 @@ s->channels, s->sample_fmt)) < 0) goto fail; - *dst = frame; - return 0; fail: - av_frame_free(&frame); + av_frame_unref(frame); return ret; } -int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, - AVPacket *avpkt, - const AVFrame *frame, - int *got_packet_ptr) +int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVSubtitle *sub) { - AVFrame *extended_frame = NULL; - AVFrame *padded_frame = NULL; int ret; - AVPacket user_pkt = *avpkt; - int needs_realloc = !user_pkt.data; + if (sub->start_display_time) { + av_log(avctx, AV_LOG_ERROR, "start_display_time must be 0.\n"); + return -1; + } - *got_packet_ptr = 0; + ret = avctx->codec->encode_sub(avctx, buf, buf_size, sub); + avctx->frame_number++; + return ret; +} - if (!avctx->codec->encode2) { - av_log(avctx, AV_LOG_ERROR, "This encoder requires using the avcodec_send_frame() API.\n"); - return AVERROR(ENOSYS); - } +int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame) +{ + AVCodecInternal *avci = avctx->internal; - if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY) && !frame) { - av_packet_unref(avpkt); - return 0; - } + if (avci->draining) + return AVERROR_EOF; - /* ensure that extended_data is properly set */ - if (frame && !frame->extended_data) { - if (av_sample_fmt_is_planar(avctx->sample_fmt) && - avctx->channels > AV_NUM_DATA_POINTERS) { - av_log(avctx, AV_LOG_ERROR, "Encoding to a planar sample format, " - "with more than %d channels, but extended_data is not set.\n", - AV_NUM_DATA_POINTERS); - return AVERROR(EINVAL); - } - av_log(avctx, AV_LOG_WARNING, "extended_data is not set.\n"); + if (!avci->buffer_frame->buf[0]) + return AVERROR(EAGAIN); + + av_frame_move_ref(frame, avci->buffer_frame); + + return 0; +} + +static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt) +{ + AVCodecInternal *avci = avctx->internal; + EncodeSimpleContext *es = &avci->es; + AVFrame *frame = es->in_frame; + int got_packet; + int ret; - extended_frame = av_frame_alloc(); - if (!extended_frame) - return AVERROR(ENOMEM); + if (avci->draining_done) + return AVERROR_EOF; - memcpy(extended_frame, frame, sizeof(AVFrame)); - extended_frame->extended_data = extended_frame->data; - frame = extended_frame; + if (!frame->buf[0] && !avci->draining) { + av_frame_unref(frame); + ret = ff_encode_get_frame(avctx, frame); + if (ret < 0 && ret != AVERROR_EOF) + return ret; } - /* extract audio service type metadata */ - if (frame) { - AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_AUDIO_SERVICE_TYPE); - if (sd && sd->size >= sizeof(enum AVAudioServiceType)) - avctx->audio_service_type = *(enum AVAudioServiceType*)sd->data; + if (!frame->buf[0]) { + if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY || + (avci->frame_thread_encoder && avctx->active_thread_type & FF_THREAD_FRAME))) + return AVERROR_EOF; + + // Flushing is signaled with a NULL frame + frame = NULL; } - /* check for valid frame size */ - if (frame) { - if (avctx->codec->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME) { - if (frame->nb_samples > avctx->frame_size) { - av_log(avctx, AV_LOG_ERROR, "more samples than frame size (avcodec_encode_audio2)\n"); - ret = AVERROR(EINVAL); - goto end; - } - } else if (!(avctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) { - if (frame->nb_samples < avctx->frame_size && - !avctx->internal->last_audio_frame) { - ret = pad_last_frame(avctx, &padded_frame, frame); - if (ret < 0) - goto end; + got_packet = 0; - frame = padded_frame; - avctx->internal->last_audio_frame = 1; - } + av_assert0(avctx->codec->encode2); - if (frame->nb_samples != avctx->frame_size) { - av_log(avctx, AV_LOG_ERROR, "nb_samples (%d) != frame_size (%d) (avcodec_encode_audio2)\n", frame->nb_samples, avctx->frame_size); - ret = AVERROR(EINVAL); - goto end; - } - } + if (CONFIG_FRAME_THREAD_ENCODER && + avci->frame_thread_encoder && (avctx->active_thread_type & FF_THREAD_FRAME)) + /* This might modify frame, but it doesn't matter, because + * the frame properties used below are not used for video + * (due to the delay inherent in frame threaded encoding, it makes + * no sense to use the properties of the current frame anyway). */ + ret = ff_thread_video_encode_frame(avctx, avpkt, frame, &got_packet); + else { + ret = avctx->codec->encode2(avctx, avpkt, frame, &got_packet); + if (avctx->codec->type == AVMEDIA_TYPE_VIDEO && !ret && got_packet && + !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) + avpkt->pts = avpkt->dts = frame->pts; } - av_assert0(avctx->codec->encode2); + av_assert0(ret <= 0); + + emms_c(); + + if (!ret && got_packet) { + if (avpkt->data) { + ret = av_packet_make_refcounted(avpkt); + if (ret < 0) + goto end; + } - ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr); - if (!ret) { - if (*got_packet_ptr) { - if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) { + if (frame && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) { + if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { if (avpkt->pts == AV_NOPTS_VALUE) avpkt->pts = frame->pts; if (!avpkt->duration) avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples); } - avpkt->dts = avpkt->pts; - } else { - avpkt->size = 0; } - } - if (avpkt->data && avpkt->data == avctx->internal->byte_buffer) { - needs_realloc = 0; - if (user_pkt.data) { - if (user_pkt.size >= avpkt->size) { - memcpy(user_pkt.data, avpkt->data, avpkt->size); - } else { - av_log(avctx, AV_LOG_ERROR, "Provided packet is too small, needs to be %d\n", avpkt->size); - avpkt->size = user_pkt.size; - ret = -1; - } - avpkt->buf = user_pkt.buf; - avpkt->data = user_pkt.data; - } else if (!avpkt->buf) { - ret = av_packet_make_refcounted(avpkt); - if (ret < 0) - goto end; + if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { + /* NOTE: if we add any audio encoders which output non-keyframe packets, + * this needs to be moved to the encoders, but for now we can do it + * here to simplify things */ + avpkt->flags |= AV_PKT_FLAG_KEY; + avpkt->dts = avpkt->pts; } } - if (!ret) { - if (needs_realloc && avpkt->data) { - ret = av_buffer_realloc(&avpkt->buf, avpkt->size + AV_INPUT_BUFFER_PADDING_SIZE); - if (ret >= 0) - avpkt->data = avpkt->buf->data; - } - if (frame) - avctx->frame_number++; - } + if (avci->draining && !got_packet) + avci->draining_done = 1; - if (ret < 0 || !*got_packet_ptr) { +end: + if (ret < 0 || !got_packet) av_packet_unref(avpkt); - goto end; - } - /* NOTE: if we add any audio encoders which output non-keyframe packets, - * this needs to be moved to the encoders, but for now we can do it - * here to simplify things */ - avpkt->flags |= AV_PKT_FLAG_KEY; + if (frame) { + if (!ret) + avctx->frame_number++; + av_frame_unref(frame); + } -end: - av_frame_free(&padded_frame); - av_free(extended_frame); + if (got_packet) + // Encoders must always return ref-counted buffers. + // Side-data only packets have no data and can be not ref-counted. + av_assert0(!avpkt->data || avpkt->buf); return ret; } -int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, - AVPacket *avpkt, - const AVFrame *frame, - int *got_packet_ptr) +static int encode_simple_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) { int ret; - AVPacket user_pkt = *avpkt; - int needs_realloc = !user_pkt.data; - - *got_packet_ptr = 0; - if (!avctx->codec->encode2) { - av_log(avctx, AV_LOG_ERROR, "This encoder requires using the avcodec_send_frame() API.\n"); - return AVERROR(ENOSYS); + while (!avpkt->data && !avpkt->side_data) { + ret = encode_simple_internal(avctx, avpkt); + if (ret < 0) + return ret; } - if(CONFIG_FRAME_THREAD_ENCODER && - avctx->internal->frame_thread_encoder && (avctx->active_thread_type&FF_THREAD_FRAME)) - return ff_thread_video_encode_frame(avctx, avpkt, frame, got_packet_ptr); + return 0; +} - if ((avctx->flags&AV_CODEC_FLAG_PASS1) && avctx->stats_out) - avctx->stats_out[0] = '\0'; +static int encode_receive_packet_internal(AVCodecContext *avctx, AVPacket *avpkt) +{ + AVCodecInternal *avci = avctx->internal; + int ret; - if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY) && !frame) { - av_packet_unref(avpkt); - return 0; + if (avci->draining_done) + return AVERROR_EOF; + + av_assert0(!avpkt->data && !avpkt->side_data); + + if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) { + if ((avctx->flags & AV_CODEC_FLAG_PASS1) && avctx->stats_out) + avctx->stats_out[0] = '\0'; + if (av_image_check_size2(avctx->width, avctx->height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx)) + return AVERROR(EINVAL); } - if (av_image_check_size2(avctx->width, avctx->height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx)) - return AVERROR(EINVAL); + if (avctx->codec->receive_packet) { + ret = avctx->codec->receive_packet(avctx, avpkt); + if (ret < 0) + av_packet_unref(avpkt); + else + // Encoders must always return ref-counted buffers. + // Side-data only packets have no data and can be not ref-counted. + av_assert0(!avpkt->data || avpkt->buf); + } else + ret = encode_simple_receive_packet(avctx, avpkt); - if (frame && frame->format == AV_PIX_FMT_NONE) - av_log(avctx, AV_LOG_WARNING, "AVFrame.format is not set\n"); - if (frame && (frame->width == 0 || frame->height == 0)) - av_log(avctx, AV_LOG_WARNING, "AVFrame.width or height is not set\n"); + if (ret == AVERROR_EOF) + avci->draining_done = 1; - av_assert0(avctx->codec->encode2); + return ret; +} - ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr); - av_assert0(ret <= 0); +static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src) +{ + AVCodecInternal *avci = avctx->internal; + AVFrame *dst = avci->buffer_frame; + int ret; - emms_c(); + if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { + /* extract audio service type metadata */ + AVFrameSideData *sd = av_frame_get_side_data(src, AV_FRAME_DATA_AUDIO_SERVICE_TYPE); + if (sd && sd->size >= sizeof(enum AVAudioServiceType)) + avctx->audio_service_type = *(enum AVAudioServiceType*)sd->data; - if (avpkt->data && avpkt->data == avctx->internal->byte_buffer) { - needs_realloc = 0; - if (user_pkt.data) { - if (user_pkt.size >= avpkt->size) { - memcpy(user_pkt.data, avpkt->data, avpkt->size); - } else { - av_log(avctx, AV_LOG_ERROR, "Provided packet is too small, needs to be %d\n", avpkt->size); - avpkt->size = user_pkt.size; - ret = -1; + /* check for valid frame size */ + if (avctx->codec->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME) { + if (src->nb_samples > avctx->frame_size) { + av_log(avctx, AV_LOG_ERROR, "more samples than frame size\n"); + return AVERROR(EINVAL); + } + } else if (!(avctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) { + /* if we already got an undersized frame, that must have been the last */ + if (avctx->internal->last_audio_frame) { + av_log(avctx, AV_LOG_ERROR, "frame_size (%d) was not respected for a non-last frame\n", avctx->frame_size); + return AVERROR(EINVAL); + } + + if (src->nb_samples < avctx->frame_size) { + ret = pad_last_frame(avctx, dst, src); + if (ret < 0) + return ret; + + avctx->internal->last_audio_frame = 1; + } else if (src->nb_samples > avctx->frame_size) { + av_log(avctx, AV_LOG_ERROR, "nb_samples (%d) != frame_size (%d)\n", src->nb_samples, avctx->frame_size); + return AVERROR(EINVAL); } - avpkt->buf = user_pkt.buf; - avpkt->data = user_pkt.data; - } else if (!avpkt->buf) { - ret = av_packet_make_refcounted(avpkt); - if (ret < 0) - return ret; } } - if (!ret) { - if (!*got_packet_ptr) - avpkt->size = 0; - else if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) - avpkt->pts = avpkt->dts = frame->pts; + if (!dst->data[0]) { + ret = av_frame_ref(dst, src); + if (ret < 0) + return ret; + } - if (needs_realloc && avpkt->data) { - ret = av_buffer_realloc(&avpkt->buf, avpkt->size + AV_INPUT_BUFFER_PADDING_SIZE); - if (ret >= 0) - avpkt->data = avpkt->buf->data; - } + return 0; +} - if (frame) - avctx->frame_number++; +int attribute_align_arg avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame) +{ + AVCodecInternal *avci = avctx->internal; + int ret; + + if (!avcodec_is_open(avctx) || !av_codec_is_encoder(avctx->codec)) + return AVERROR(EINVAL); + + if (avci->draining) + return AVERROR_EOF; + + if (avci->buffer_frame->data[0]) + return AVERROR(EAGAIN); + + if (!frame) { + avci->draining = 1; + } else { + ret = encode_send_frame_internal(avctx, frame); + if (ret < 0) + return ret; } - if (ret < 0 || !*got_packet_ptr) - av_packet_unref(avpkt); + if (!avci->buffer_pkt->data && !avci->buffer_pkt->side_data) { + ret = encode_receive_packet_internal(avctx, avci->buffer_pkt); + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + return ret; + } - return ret; + return 0; } -int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, - const AVSubtitle *sub) +int attribute_align_arg avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) { + AVCodecInternal *avci = avctx->internal; int ret; - if (sub->start_display_time) { - av_log(avctx, AV_LOG_ERROR, "start_display_time must be 0.\n"); - return -1; + + av_packet_unref(avpkt); + + if (!avcodec_is_open(avctx) || !av_codec_is_encoder(avctx->codec)) + return AVERROR(EINVAL); + + if (avci->buffer_pkt->data || avci->buffer_pkt->side_data) { + av_packet_move_ref(avpkt, avci->buffer_pkt); + } else { + ret = encode_receive_packet_internal(avctx, avpkt); + if (ret < 0) + return ret; } - ret = avctx->codec->encode_sub(avctx, buf, buf_size, sub); - avctx->frame_number++; - return ret; + return 0; } -static int do_encode(AVCodecContext *avctx, const AVFrame *frame, int *got_packet) +#if FF_API_OLD_ENCDEC +static int compat_encode(AVCodecContext *avctx, AVPacket *avpkt, + int *got_packet, const AVFrame *frame) { + AVCodecInternal *avci = avctx->internal; + AVPacket user_pkt; int ret; + *got_packet = 0; - av_packet_unref(avctx->internal->buffer_pkt); - avctx->internal->buffer_pkt_valid = 0; + if (frame && avctx->codec->type == AVMEDIA_TYPE_VIDEO) { + if (frame->format == AV_PIX_FMT_NONE) + av_log(avctx, AV_LOG_WARNING, "AVFrame.format is not set\n"); + if (frame->width == 0 || frame->height == 0) + av_log(avctx, AV_LOG_WARNING, "AVFrame.width or height is not set\n"); + } - if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { - ret = avcodec_encode_video2(avctx, avctx->internal->buffer_pkt, - frame, got_packet); - } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { - ret = avcodec_encode_audio2(avctx, avctx->internal->buffer_pkt, - frame, got_packet); - } else { - ret = AVERROR(EINVAL); + if (avctx->codec->capabilities & AV_CODEC_CAP_DR1) { + av_log(avctx, AV_LOG_WARNING, "The deprecated avcodec_encode_* API does not support " + "AV_CODEC_CAP_DR1 encoders\n"); + return AVERROR(ENOSYS); } - if (ret >= 0 && *got_packet) { - // Encoders must always return ref-counted buffers. - // Side-data only packets have no data and can be not ref-counted. - av_assert0(!avctx->internal->buffer_pkt->data || avctx->internal->buffer_pkt->buf); - avctx->internal->buffer_pkt_valid = 1; + ret = avcodec_send_frame(avctx, frame); + if (ret == AVERROR_EOF) ret = 0; - } else { - av_packet_unref(avctx->internal->buffer_pkt); + else if (ret == AVERROR(EAGAIN)) { + /* we fully drain all the output in each encode call, so this should not + * ever happen */ + return AVERROR_BUG; + } else if (ret < 0) + return ret; + + av_packet_move_ref(&user_pkt, avpkt); + while (ret >= 0) { + ret = avcodec_receive_packet(avctx, avpkt); + if (ret < 0) { + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + ret = 0; + goto finish; + } + + if (avpkt != avci->compat_encode_packet) { + if (avpkt->data && user_pkt.data) { + if (user_pkt.size >= avpkt->size) { + memcpy(user_pkt.data, avpkt->data, avpkt->size); + av_buffer_unref(&avpkt->buf); + avpkt->buf = user_pkt.buf; + avpkt->data = user_pkt.data; +FF_DISABLE_DEPRECATION_WARNINGS + av_init_packet(&user_pkt); +FF_ENABLE_DEPRECATION_WARNINGS + } else { + av_log(avctx, AV_LOG_ERROR, "Provided packet is too small, needs to be %d\n", avpkt->size); + av_packet_unref(avpkt); + ret = AVERROR(EINVAL); + goto finish; + } + } + + *got_packet = 1; + avpkt = avci->compat_encode_packet; + } else { + if (!avci->compat_decode_warned) { + av_log(avctx, AV_LOG_WARNING, "The deprecated avcodec_encode_* " + "API cannot return all the packets for this encoder. " + "Some packets will be dropped. Update your code to the " + "new encoding API to fix this.\n"); + avci->compat_decode_warned = 1; + av_packet_unref(avpkt); + } + } + + if (avci->draining) + break; } +finish: + if (ret < 0) + av_packet_unref(&user_pkt); + return ret; } -int attribute_align_arg avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame) +int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, + AVPacket *avpkt, + const AVFrame *frame, + int *got_packet_ptr) { - if (!avcodec_is_open(avctx) || !av_codec_is_encoder(avctx->codec)) - return AVERROR(EINVAL); - - if (avctx->internal->draining) - return AVERROR_EOF; + int ret = compat_encode(avctx, avpkt, got_packet_ptr, frame); - if (!frame) { - avctx->internal->draining = 1; - - if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) - return 0; - } + if (ret < 0) + av_packet_unref(avpkt); - if (avctx->codec->send_frame) - return avctx->codec->send_frame(avctx, frame); + return ret; +} - // Emulation via old API. Do it here instead of avcodec_receive_packet, because: - // 1. if the AVFrame is not refcounted, the copying will be much more - // expensive than copying the packet data - // 2. assume few users use non-refcounted AVPackets, so usually no copy is - // needed +int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, + AVPacket *avpkt, + const AVFrame *frame, + int *got_packet_ptr) +{ + int ret = compat_encode(avctx, avpkt, got_packet_ptr, frame); - if (avctx->internal->buffer_pkt_valid) - return AVERROR(EAGAIN); + if (ret < 0) + av_packet_unref(avpkt); - return do_encode(avctx, frame, &(int){0}); + return ret; } +#endif -int attribute_align_arg avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) +int ff_encode_preinit(AVCodecContext *avctx) { - av_packet_unref(avpkt); + int i; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame = av_frame_alloc(); + if (!avctx->coded_frame) { + return AVERROR(ENOMEM); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif - if (!avcodec_is_open(avctx) || !av_codec_is_encoder(avctx->codec)) + if (avctx->time_base.num <= 0 || avctx->time_base.den <= 0) { + av_log(avctx, AV_LOG_ERROR, "The encoder timebase is not set.\n"); return AVERROR(EINVAL); + } - if (avctx->codec->receive_packet) { - if (avctx->internal->draining && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) - return AVERROR_EOF; - return avctx->codec->receive_packet(avctx, avpkt); + if (avctx->codec->sample_fmts) { + for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) { + if (avctx->sample_fmt == avctx->codec->sample_fmts[i]) + break; + if (avctx->channels == 1 && + av_get_planar_sample_fmt(avctx->sample_fmt) == + av_get_planar_sample_fmt(avctx->codec->sample_fmts[i])) { + avctx->sample_fmt = avctx->codec->sample_fmts[i]; + break; + } + } + if (avctx->codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) { + char buf[128]; + snprintf(buf, sizeof(buf), "%d", avctx->sample_fmt); + av_log(avctx, AV_LOG_ERROR, "Specified sample format %s is invalid or not supported\n", + (char *)av_x_if_null(av_get_sample_fmt_name(avctx->sample_fmt), buf)); + return AVERROR(EINVAL); + } + } + if (avctx->codec->pix_fmts) { + for (i = 0; avctx->codec->pix_fmts[i] != AV_PIX_FMT_NONE; i++) + if (avctx->pix_fmt == avctx->codec->pix_fmts[i]) + break; + if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_NONE + && !(avctx->codec_id == AV_CODEC_ID_MJPEG + && avctx->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL)) { + char buf[128]; + snprintf(buf, sizeof(buf), "%d", avctx->pix_fmt); + av_log(avctx, AV_LOG_ERROR, "Specified pixel format %s is invalid or not supported\n", + (char *)av_x_if_null(av_get_pix_fmt_name(avctx->pix_fmt), buf)); + return AVERROR(EINVAL); + } + if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ420P || + avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ411P || + avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ422P || + avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ440P || + avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ444P) + avctx->color_range = AVCOL_RANGE_JPEG; + } + if (avctx->codec->supported_samplerates) { + for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++) + if (avctx->sample_rate == avctx->codec->supported_samplerates[i]) + break; + if (avctx->codec->supported_samplerates[i] == 0) { + av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n", + avctx->sample_rate); + return AVERROR(EINVAL); + } + } + if (avctx->sample_rate < 0) { + av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n", + avctx->sample_rate); + return AVERROR(EINVAL); + } + if (avctx->codec->channel_layouts) { + if (!avctx->channel_layout) { + av_log(avctx, AV_LOG_WARNING, "Channel layout not specified\n"); + } else { + for (i = 0; avctx->codec->channel_layouts[i] != 0; i++) + if (avctx->channel_layout == avctx->codec->channel_layouts[i]) + break; + if (avctx->codec->channel_layouts[i] == 0) { + char buf[512]; + av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); + av_log(avctx, AV_LOG_ERROR, "Specified channel layout '%s' is not supported\n", buf); + return AVERROR(EINVAL); + } + } + } + if (avctx->channel_layout && avctx->channels) { + int channels = av_get_channel_layout_nb_channels(avctx->channel_layout); + if (channels != avctx->channels) { + char buf[512]; + av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); + av_log(avctx, AV_LOG_ERROR, + "Channel layout '%s' with %d channels does not match number of specified channels %d\n", + buf, channels, avctx->channels); + return AVERROR(EINVAL); + } + } else if (avctx->channel_layout) { + avctx->channels = av_get_channel_layout_nb_channels(avctx->channel_layout); + } + if (avctx->channels < 0) { + av_log(avctx, AV_LOG_ERROR, "Specified number of channels %d is not supported\n", + avctx->channels); + return AVERROR(EINVAL); + } + if(avctx->codec_type == AVMEDIA_TYPE_VIDEO) { + const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(avctx->pix_fmt); + if ( avctx->bits_per_raw_sample < 0 + || (avctx->bits_per_raw_sample > 8 && pixdesc->comp[0].depth <= 8)) { + av_log(avctx, AV_LOG_WARNING, "Specified bit depth %d not possible with the specified pixel formats depth %d\n", + avctx->bits_per_raw_sample, pixdesc->comp[0].depth); + avctx->bits_per_raw_sample = pixdesc->comp[0].depth; + } + if (avctx->width <= 0 || avctx->height <= 0) { + av_log(avctx, AV_LOG_ERROR, "dimensions not set\n"); + return AVERROR(EINVAL); + } + } + if ( (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO) + && avctx->bit_rate>0 && avctx->bit_rate<1000) { + av_log(avctx, AV_LOG_WARNING, "Bitrate %"PRId64" is extremely low, maybe you mean %"PRId64"k\n", avctx->bit_rate, avctx->bit_rate); } - // Emulation via old API. + if (!avctx->rc_initial_buffer_occupancy) + avctx->rc_initial_buffer_occupancy = avctx->rc_buffer_size * 3LL / 4; + + if (avctx->ticks_per_frame && avctx->time_base.num && + avctx->ticks_per_frame > INT_MAX / avctx->time_base.num) { + av_log(avctx, AV_LOG_ERROR, + "ticks_per_frame %d too large for the timebase %d/%d.", + avctx->ticks_per_frame, + avctx->time_base.num, + avctx->time_base.den); + return AVERROR(EINVAL); + } - if (!avctx->internal->buffer_pkt_valid) { - int got_packet; - int ret; - if (!avctx->internal->draining) - return AVERROR(EAGAIN); - ret = do_encode(avctx, NULL, &got_packet); - if (ret < 0) - return ret; - if (ret >= 0 && !got_packet) - return AVERROR_EOF; + if (avctx->hw_frames_ctx) { + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; + if (frames_ctx->format != avctx->pix_fmt) { + av_log(avctx, AV_LOG_ERROR, + "Mismatching AVCodecContext.pix_fmt and AVHWFramesContext.format\n"); + return AVERROR(EINVAL); + } + if (avctx->sw_pix_fmt != AV_PIX_FMT_NONE && + avctx->sw_pix_fmt != frames_ctx->sw_format) { + av_log(avctx, AV_LOG_ERROR, + "Mismatching AVCodecContext.sw_pix_fmt (%s) " + "and AVHWFramesContext.sw_format (%s)\n", + av_get_pix_fmt_name(avctx->sw_pix_fmt), + av_get_pix_fmt_name(frames_ctx->sw_format)); + return AVERROR(EINVAL); + } + avctx->sw_pix_fmt = frames_ctx->sw_format; } - av_packet_move_ref(avpkt, avctx->internal->buffer_pkt); - avctx->internal->buffer_pkt_valid = 0; return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/encode.h ffmpeg-4.4/libavcodec/encode.h --- ffmpeg-4.2.2/libavcodec/encode.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/encode.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,53 @@ +/* + * generic encoding-related code + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_ENCODE_H +#define AVCODEC_ENCODE_H + +#include "libavutil/frame.h" + +#include "avcodec.h" +#include "packet.h" + +/** + * Called by encoders to get the next frame for encoding. + * + * @param frame An empty frame to be filled with data. + * @return 0 if a new reference has been successfully written to frame + * AVERROR(EAGAIN) if no data is currently available + * AVERROR_EOF if end of stream has been reached, so no more data + * will be available + */ +int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame); + +/** + * Get a buffer for a packet. This is a wrapper around + * AVCodecContext.get_encode_buffer() and should be used instead calling get_encode_buffer() + * directly. + */ +int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags); + +/* + * Perform encoder initialization and validation. + * Called when opening the encoder, before the AVCodec.init() call. + */ +int ff_encode_preinit(AVCodecContext *avctx); + +#endif /* AVCODEC_ENCODE_H */ diff -Nru ffmpeg-4.2.2/libavcodec/escape124.c ffmpeg-4.4/libavcodec/escape124.c --- ffmpeg-4.2.2/libavcodec/escape124.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/escape124.c 2020-07-11 10:39:30.000000000 +0000 @@ -252,7 +252,7 @@ if (i == 2) { // This codebook can be cut off at places other than // powers of 2, leaving some of the entries undefined. - cb_size = get_bits_long(&gb, 20); + cb_size = get_bits(&gb, 20); if (!cb_size) { av_log(avctx, AV_LOG_ERROR, "Invalid codebook size 0.\n"); return AVERROR_INVALIDDATA; diff -Nru ffmpeg-4.2.2/libavcodec/escape130.c ffmpeg-4.4/libavcodec/escape130.c --- ffmpeg-4.2.2/libavcodec/escape130.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/escape130.c 2021-04-08 21:28:39.000000000 +0000 @@ -128,9 +128,6 @@ s->buf1 = av_malloc(avctx->width * avctx->height * 3 / 2); s->buf2 = av_malloc(avctx->width * avctx->height * 3 / 2); if (!s->old_y_avg || !s->buf1 || !s->buf2) { - av_freep(&s->old_y_avg); - av_freep(&s->buf1); - av_freep(&s->buf2); av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n"); return AVERROR(ENOMEM); } @@ -358,4 +355,5 @@ .close = escape130_decode_close, .decode = escape130_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/evrcdec.c ffmpeg-4.4/libavcodec/evrcdec.c --- ffmpeg-4.2.2/libavcodec/evrcdec.c 2018-07-17 09:27:39.000000000 +0000 +++ ffmpeg-4.4/libavcodec/evrcdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -935,7 +935,7 @@ .id = AV_CODEC_ID_EVRC, .init = evrc_decode_init, .decode = evrc_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .priv_data_size = sizeof(EVRCContext), .priv_class = &evrcdec_class, }; diff -Nru ffmpeg-4.2.2/libavcodec/exif.c ffmpeg-4.4/libavcodec/exif.c --- ffmpeg-4.2.2/libavcodec/exif.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/exif.c 2021-04-08 21:28:39.000000000 +0000 @@ -95,22 +95,15 @@ ret = ff_exif_decode_ifd(logctx, gbytes, le, depth + 1, metadata); } else { const char *name = exif_get_tag_name(id); - char *use_name = (char*) name; + char buf[7]; - if (!use_name) { - use_name = av_malloc(7); - if (!use_name) { - return AVERROR(ENOMEM); - } - snprintf(use_name, 7, "0x%04X", id); + if (!name) { + name = buf; + snprintf(buf, sizeof(buf), "0x%04X", id); } - ret = exif_add_metadata(logctx, count, type, use_name, NULL, + ret = exif_add_metadata(logctx, count, type, name, NULL, gbytes, le, metadata); - - if (!name) { - av_freep(&use_name); - } } bytestream2_seek(gbytes, cur_pos, SEEK_SET); diff -Nru ffmpeg-4.2.2/libavcodec/exr.c ffmpeg-4.4/libavcodec/exr.c --- ffmpeg-4.2.2/libavcodec/exr.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/exr.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,9 +29,6 @@ * * For more information on the OpenEXR format, visit: * http://openexr.com/ - * - * exr_flt2uint() and exr_halflt2uint() is credited to Reimar Döffinger. - * exr_half2float() is credited to Aaftab Munshi, Dan Ginsburg, Dave Shreiner. */ #include @@ -41,6 +38,7 @@ #include "libavutil/common.h" #include "libavutil/imgutils.h" #include "libavutil/intfloat.h" +#include "libavutil/avstring.h" #include "libavutil/opt.h" #include "libavutil/color_utils.h" @@ -54,6 +52,7 @@ #include "exrdsp.h" #include "get_bits.h" #include "internal.h" +#include "half2float.h" #include "mathops.h" #include "thread.h" @@ -66,8 +65,8 @@ EXR_PXR24, EXR_B44, EXR_B44A, - EXR_DWA, - EXR_DWB, + EXR_DWAA, + EXR_DWAB, EXR_UNKN, }; @@ -91,6 +90,12 @@ EXR_TILE_ROUND_UNKNOWN, }; +typedef struct HuffEntry { + uint8_t len; + uint16_t sym; + uint32_t code; +} HuffEntry; + typedef struct EXRChannel { int xsub, ysub; enum ExrPixelType pixel_type; @@ -113,9 +118,28 @@ uint8_t *bitmap; uint16_t *lut; + uint8_t *ac_data; + unsigned ac_size; + + uint8_t *dc_data; + unsigned dc_size; + + uint8_t *rle_data; + unsigned rle_size; + + uint8_t *rle_raw_data; + unsigned rle_raw_size; + + float block[3][64]; + int ysize, xsize; int channel_line_size; + + int run_sym; + HuffEntry *he; + uint64_t *freq; + VLC vlc; } EXRThreadData; typedef struct EXRContext { @@ -134,14 +158,17 @@ const AVPixFmtDescriptor *desc; int w, h; - uint32_t xmax, xmin; - uint32_t ymax, ymin; + uint32_t sar; + int32_t xmax, xmin; + int32_t ymax, ymin; uint32_t xdelta, ydelta; int scan_lines_per_block; EXRTileAttribute tile_attr; /* header data attribute of tile */ int is_tile; /* 0 if scanline, 1 if tile */ + int is_multipart; + int current_part; int is_luma;/* 1 if there is an Y plane */ @@ -152,118 +179,21 @@ EXRChannel *channels; int nb_channels; int current_channel_offset; + uint32_t chunk_count; EXRThreadData *thread_data; const char *layer; + int selected_part; enum AVColorTransferCharacteristic apply_trc_type; float gamma; - uint16_t gamma_table[65536]; -} EXRContext; - -/* -15 stored using a single precision bias of 127 */ -#define HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP 0x38000000 + union av_intfloat32 gamma_table[65536]; -/* max exponent value in single precision that will be converted - * to Inf or Nan when stored as a half-float */ -#define HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP 0x47800000 - -/* 255 is the max exponent biased value */ -#define FLOAT_MAX_BIASED_EXP (0xFF << 23) - -#define HALF_FLOAT_MAX_BIASED_EXP (0x1F << 10) - -/** - * Convert a half float as a uint16_t into a full float. - * - * @param hf half float as uint16_t - * - * @return float value - */ -static union av_intfloat32 exr_half2float(uint16_t hf) -{ - unsigned int sign = (unsigned int) (hf >> 15); - unsigned int mantissa = (unsigned int) (hf & ((1 << 10) - 1)); - unsigned int exp = (unsigned int) (hf & HALF_FLOAT_MAX_BIASED_EXP); - union av_intfloat32 f; - - if (exp == HALF_FLOAT_MAX_BIASED_EXP) { - // we have a half-float NaN or Inf - // half-float NaNs will be converted to a single precision NaN - // half-float Infs will be converted to a single precision Inf - exp = FLOAT_MAX_BIASED_EXP; - if (mantissa) - mantissa = (1 << 23) - 1; // set all bits to indicate a NaN - } else if (exp == 0x0) { - // convert half-float zero/denorm to single precision value - if (mantissa) { - mantissa <<= 1; - exp = HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP; - // check for leading 1 in denorm mantissa - while ((mantissa & (1 << 10))) { - // for every leading 0, decrement single precision exponent by 1 - // and shift half-float mantissa value to the left - mantissa <<= 1; - exp -= (1 << 23); - } - // clamp the mantissa to 10 bits - mantissa &= ((1 << 10) - 1); - // shift left to generate single-precision mantissa of 23 bits - mantissa <<= 13; - } - } else { - // shift left to generate single-precision mantissa of 23 bits - mantissa <<= 13; - // generate single precision biased exponent value - exp = (exp << 13) + HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP; - } - - f.i = (sign << 31) | exp | mantissa; - - return f; -} - - -/** - * Convert from 32-bit float as uint32_t to uint16_t. - * - * @param v 32-bit float - * - * @return normalized 16-bit unsigned int - */ -static inline uint16_t exr_flt2uint(int32_t v) -{ - int32_t exp = v >> 23; - // "HACK": negative values result in exp< 0, so clipping them to 0 - // is also handled by this condition, avoids explicit check for sign bit. - if (exp <= 127 + 7 - 24) // we would shift out all bits anyway - return 0; - if (exp >= 127) - return 0xffff; - v &= 0x007fffff; - return (v + (1 << 23)) >> (127 + 7 - exp); -} - -/** - * Convert from 16-bit float as uint16_t to uint16_t. - * - * @param v 16-bit float - * - * @return normalized 16-bit unsigned int - */ -static inline uint16_t exr_halflt2uint(uint16_t v) -{ - unsigned exp = 14 - (v >> 10); - if (exp >= 14) { - if (exp == 14) - return (v >> 9) & 1; - else - return (v & 0x8000) ? 0 : 0xffff; - } - v <<= 6; - return (v + (1 << 16)) >> (exp + 1); -} + uint32_t mantissatable[2048]; + uint32_t exponenttable[64]; + uint16_t offsettable[64]; +} EXRContext; static int zip_uncompress(EXRContext *s, const uint8_t *src, int compressed_size, int uncompressed_size, EXRThreadData *td) @@ -282,10 +212,10 @@ return 0; } -static int rle_uncompress(EXRContext *ctx, const uint8_t *src, int compressed_size, - int uncompressed_size, EXRThreadData *td) +static int rle(uint8_t *dst, const uint8_t *src, + int compressed_size, int uncompressed_size) { - uint8_t *d = td->tmp; + uint8_t *d = dst; const int8_t *s = src; int ssize = compressed_size; int dsize = uncompressed_size; @@ -321,6 +251,14 @@ if (dend != d) return AVERROR_INVALIDDATA; + return 0; +} + +static int rle_uncompress(EXRContext *ctx, const uint8_t *src, int compressed_size, + int uncompressed_size, EXRThreadData *td) +{ + rle(td->tmp, src, compressed_size, uncompressed_size); + av_assert1(uncompressed_size % 2 == 0); ctx->dsp.predictor(td->tmp, uncompressed_size); @@ -356,25 +294,15 @@ } #define HUF_ENCBITS 16 // literal (value) bit length -#define HUF_DECBITS 14 // decoding bit size (>= 8) - #define HUF_ENCSIZE ((1 << HUF_ENCBITS) + 1) // encoding table size -#define HUF_DECSIZE (1 << HUF_DECBITS) // decoding table size -#define HUF_DECMASK (HUF_DECSIZE - 1) -typedef struct HufDec { - int len; - int lit; - int *p; -} HufDec; - -static void huf_canonical_code_table(uint64_t *hcode) +static void huf_canonical_code_table(uint64_t *freq) { uint64_t c, n[59] = { 0 }; int i; - for (i = 0; i < HUF_ENCSIZE; ++i) - n[hcode[i]] += 1; + for (i = 0; i < HUF_ENCSIZE; i++) + n[freq[i]] += 1; c = 0; for (i = 58; i > 0; --i) { @@ -384,10 +312,10 @@ } for (i = 0; i < HUF_ENCSIZE; ++i) { - int l = hcode[i]; + int l = freq[i]; if (l > 0) - hcode[i] = l | (n[l]++ << 6); + freq[i] = l | (n[l]++ << 6); } } @@ -397,7 +325,7 @@ #define LONGEST_LONG_RUN (255 + SHORTEST_LONG_RUN) static int huf_unpack_enc_table(GetByteContext *gb, - int32_t im, int32_t iM, uint64_t *hcode) + int32_t im, int32_t iM, uint64_t *freq) { GetBitContext gbit; int ret = init_get_bits8(&gbit, gb->buffer, bytestream2_get_bytes_left(gb)); @@ -405,7 +333,7 @@ return ret; for (; im <= iM; im++) { - uint64_t l = hcode[im] = get_bits(&gbit, 6); + uint64_t l = freq[im] = get_bits(&gbit, 6); if (l == LONG_ZEROCODE_RUN) { int zerun = get_bits(&gbit, 8) + SHORTEST_LONG_RUN; @@ -414,7 +342,7 @@ return AVERROR_INVALIDDATA; while (zerun--) - hcode[im++] = 0; + freq[im++] = 0; im--; } else if (l >= SHORT_ZEROCODE_RUN) { @@ -424,202 +352,133 @@ return AVERROR_INVALIDDATA; while (zerun--) - hcode[im++] = 0; + freq[im++] = 0; im--; } } bytestream2_skip(gb, (get_bits_count(&gbit) + 7) / 8); - huf_canonical_code_table(hcode); + huf_canonical_code_table(freq); return 0; } -static int huf_build_dec_table(const uint64_t *hcode, int im, - int iM, HufDec *hdecod) +static int huf_build_dec_table(EXRContext *s, + EXRThreadData *td, int im, int iM) { - for (; im <= iM; im++) { - uint64_t c = hcode[im] >> 6; - int i, l = hcode[im] & 63; + int j = 0; - if (c >> l) - return AVERROR_INVALIDDATA; + td->run_sym = -1; + for (int i = im; i < iM; i++) { + td->he[j].sym = i; + td->he[j].len = td->freq[i] & 63; + td->he[j].code = td->freq[i] >> 6; + if (td->he[j].len > 32) { + avpriv_request_sample(s->avctx, "Too big code length"); + return AVERROR_PATCHWELCOME; + } + if (td->he[j].len > 0) + j++; + else + td->run_sym = i; + } - if (l > HUF_DECBITS) { - HufDec *pl = hdecod + (c >> (l - HUF_DECBITS)); - if (pl->len) - return AVERROR_INVALIDDATA; + if (im > 0) + td->run_sym = 0; + else if (iM < 65535) + td->run_sym = 65535; - pl->lit++; + if (td->run_sym == -1) { + avpriv_request_sample(s->avctx, "No place for run symbol"); + return AVERROR_PATCHWELCOME; + } - pl->p = av_realloc(pl->p, pl->lit * sizeof(int)); - if (!pl->p) - return AVERROR(ENOMEM); - - pl->p[pl->lit - 1] = im; - } else if (l) { - HufDec *pl = hdecod + (c << (HUF_DECBITS - l)); - - for (i = 1 << (HUF_DECBITS - l); i > 0; i--, pl++) { - if (pl->len || pl->p) - return AVERROR_INVALIDDATA; - pl->len = l; - pl->lit = im; - } - } + td->he[j].sym = td->run_sym; + td->he[j].len = td->freq[iM] & 63; + if (td->he[j].len > 32) { + avpriv_request_sample(s->avctx, "Too big code length"); + return AVERROR_PATCHWELCOME; } + td->he[j].code = td->freq[iM] >> 6; + j++; - return 0; + ff_free_vlc(&td->vlc); + return ff_init_vlc_sparse(&td->vlc, 12, j, + &td->he[0].len, sizeof(td->he[0]), sizeof(td->he[0].len), + &td->he[0].code, sizeof(td->he[0]), sizeof(td->he[0].code), + &td->he[0].sym, sizeof(td->he[0]), sizeof(td->he[0].sym), 0); } -#define get_char(c, lc, gb) \ -{ \ - c = (c << 8) | bytestream2_get_byte(gb); \ - lc += 8; \ -} - -#define get_code(po, rlc, c, lc, gb, out, oe, outb) \ -{ \ - if (po == rlc) { \ - if (lc < 8) \ - get_char(c, lc, gb); \ - lc -= 8; \ - \ - cs = c >> lc; \ - \ - if (out + cs > oe || out == outb) \ - return AVERROR_INVALIDDATA; \ - \ - s = out[-1]; \ - \ - while (cs-- > 0) \ - *out++ = s; \ - } else if (out < oe) { \ - *out++ = po; \ - } else { \ - return AVERROR_INVALIDDATA; \ - } \ -} - -static int huf_decode(const uint64_t *hcode, const HufDec *hdecod, - GetByteContext *gb, int nbits, - int rlc, int no, uint16_t *out) -{ - uint64_t c = 0; - uint16_t *outb = out; - uint16_t *oe = out + no; - const uint8_t *ie = gb->buffer + (nbits + 7) / 8; // input byte size - uint8_t cs; - uint16_t s; - int i, lc = 0; - - while (gb->buffer < ie) { - get_char(c, lc, gb); - - while (lc >= HUF_DECBITS) { - const HufDec pl = hdecod[(c >> (lc - HUF_DECBITS)) & HUF_DECMASK]; - - if (pl.len) { - lc -= pl.len; - get_code(pl.lit, rlc, c, lc, gb, out, oe, outb); - } else { - int j; +static int huf_decode(VLC *vlc, GetByteContext *gb, int nbits, int run_sym, + int no, uint16_t *out) +{ + GetBitContext gbit; + int oe = 0; - if (!pl.p) - return AVERROR_INVALIDDATA; + init_get_bits(&gbit, gb->buffer, nbits); + while (get_bits_left(&gbit) > 0 && oe < no) { + uint16_t x = get_vlc2(&gbit, vlc->table, 12, 2); - for (j = 0; j < pl.lit; j++) { - int l = hcode[pl.p[j]] & 63; + if (x == run_sym) { + int run = get_bits(&gbit, 8); + uint16_t fill; - while (lc < l && bytestream2_get_bytes_left(gb) > 0) - get_char(c, lc, gb); - - if (lc >= l) { - if ((hcode[pl.p[j]] >> 6) == - ((c >> (lc - l)) & ((1LL << l) - 1))) { - lc -= l; - get_code(pl.p[j], rlc, c, lc, gb, out, oe, outb); - break; - } - } - } - - if (j == pl.lit) - return AVERROR_INVALIDDATA; - } - } - } - - i = (8 - nbits) & 7; - c >>= i; - lc -= i; + if (oe == 0 || oe + run > no) + return AVERROR_INVALIDDATA; - while (lc > 0) { - const HufDec pl = hdecod[(c << (HUF_DECBITS - lc)) & HUF_DECMASK]; + fill = out[oe - 1]; - if (pl.len && lc >= pl.len) { - lc -= pl.len; - get_code(pl.lit, rlc, c, lc, gb, out, oe, outb); + while (run-- > 0) + out[oe++] = fill; } else { - return AVERROR_INVALIDDATA; + out[oe++] = x; } } - if (out - outb != no) - return AVERROR_INVALIDDATA; return 0; } -static int huf_uncompress(GetByteContext *gb, +static int huf_uncompress(EXRContext *s, + EXRThreadData *td, + GetByteContext *gb, uint16_t *dst, int dst_size) { - int32_t src_size, im, iM; + int32_t im, iM; uint32_t nBits; - uint64_t *freq; - HufDec *hdec; - int ret, i; + int ret; - src_size = bytestream2_get_le32(gb); im = bytestream2_get_le32(gb); iM = bytestream2_get_le32(gb); bytestream2_skip(gb, 4); nBits = bytestream2_get_le32(gb); if (im < 0 || im >= HUF_ENCSIZE || - iM < 0 || iM >= HUF_ENCSIZE || - src_size < 0) + iM < 0 || iM >= HUF_ENCSIZE) return AVERROR_INVALIDDATA; bytestream2_skip(gb, 4); - freq = av_mallocz_array(HUF_ENCSIZE, sizeof(*freq)); - hdec = av_mallocz_array(HUF_DECSIZE, sizeof(*hdec)); - if (!freq || !hdec) { + if (!td->freq) + td->freq = av_malloc_array(HUF_ENCSIZE, sizeof(*td->freq)); + if (!td->he) + td->he = av_calloc(HUF_ENCSIZE, sizeof(*td->he)); + if (!td->freq || !td->he) { ret = AVERROR(ENOMEM); - goto fail; + return ret; } - if ((ret = huf_unpack_enc_table(gb, im, iM, freq)) < 0) - goto fail; + memset(td->freq, 0, sizeof(*td->freq) * HUF_ENCSIZE); + if ((ret = huf_unpack_enc_table(gb, im, iM, td->freq)) < 0) + return ret; if (nBits > 8 * bytestream2_get_bytes_left(gb)) { ret = AVERROR_INVALIDDATA; - goto fail; + return ret; } - if ((ret = huf_build_dec_table(freq, im, iM, hdec)) < 0) - goto fail; - ret = huf_decode(freq, hdec, gb, nBits, iM, dst_size, dst); - -fail: - for (i = 0; i < HUF_DECSIZE; i++) - if (hdec) - av_freep(&hdec[i].p); - - av_free(freq); - av_free(hdec); - - return ret; + if ((ret = huf_build_dec_table(s, td, im, iM)) < 0) + return ret; + return huf_decode(&td->vlc, gb, nBits, td->run_sym, dst_size, dst); } static inline void wdec14(uint16_t l, uint16_t h, uint16_t *a, uint16_t *b) @@ -767,7 +626,8 @@ maxval = reverse_lut(td->bitmap, td->lut); - ret = huf_uncompress(&gb, tmp, dsize / sizeof(uint16_t)); + bytestream2_skip(&gb, 4); + ret = huf_uncompress(s, td, &gb, tmp, dsize / sizeof(uint16_t)); if (ret) return ret; @@ -881,7 +741,7 @@ in = ptr[3] + s->xdelta; for (j = 0; j < s->xdelta; ++j) { - uint32_t diff = (*(ptr[0]++) << 24) | + uint32_t diff = ((uint32_t)*(ptr[0]++) << 24) | (*(ptr[1]++) << 16) | (*(ptr[2]++) << 8 ) | (*(ptr[3]++)); @@ -1025,6 +885,292 @@ return 0; } +static int ac_uncompress(EXRContext *s, GetByteContext *gb, float *block) +{ + int ret = 0, n = 1; + + while (n < 64) { + uint16_t val = bytestream2_get_ne16(gb); + + if (val == 0xff00) { + n = 64; + } else if ((val >> 8) == 0xff) { + n += val & 0xff; + } else { + ret = n; + block[ff_zigzag_direct[n]] = av_int2float(half2float(val, + s->mantissatable, + s->exponenttable, + s->offsettable)); + n++; + } + } + + return ret; +} + +static void idct_1d(float *blk, int step) +{ + const float a = .5f * cosf( M_PI / 4.f); + const float b = .5f * cosf( M_PI / 16.f); + const float c = .5f * cosf( M_PI / 8.f); + const float d = .5f * cosf(3.f*M_PI / 16.f); + const float e = .5f * cosf(5.f*M_PI / 16.f); + const float f = .5f * cosf(3.f*M_PI / 8.f); + const float g = .5f * cosf(7.f*M_PI / 16.f); + + float alpha[4], beta[4], theta[4], gamma[4]; + + alpha[0] = c * blk[2 * step]; + alpha[1] = f * blk[2 * step]; + alpha[2] = c * blk[6 * step]; + alpha[3] = f * blk[6 * step]; + + beta[0] = b * blk[1 * step] + d * blk[3 * step] + e * blk[5 * step] + g * blk[7 * step]; + beta[1] = d * blk[1 * step] - g * blk[3 * step] - b * blk[5 * step] - e * blk[7 * step]; + beta[2] = e * blk[1 * step] - b * blk[3 * step] + g * blk[5 * step] + d * blk[7 * step]; + beta[3] = g * blk[1 * step] - e * blk[3 * step] + d * blk[5 * step] - b * blk[7 * step]; + + theta[0] = a * (blk[0 * step] + blk[4 * step]); + theta[3] = a * (blk[0 * step] - blk[4 * step]); + + theta[1] = alpha[0] + alpha[3]; + theta[2] = alpha[1] - alpha[2]; + + gamma[0] = theta[0] + theta[1]; + gamma[1] = theta[3] + theta[2]; + gamma[2] = theta[3] - theta[2]; + gamma[3] = theta[0] - theta[1]; + + blk[0 * step] = gamma[0] + beta[0]; + blk[1 * step] = gamma[1] + beta[1]; + blk[2 * step] = gamma[2] + beta[2]; + blk[3 * step] = gamma[3] + beta[3]; + + blk[4 * step] = gamma[3] - beta[3]; + blk[5 * step] = gamma[2] - beta[2]; + blk[6 * step] = gamma[1] - beta[1]; + blk[7 * step] = gamma[0] - beta[0]; +} + +static void dct_inverse(float *block) +{ + for (int i = 0; i < 8; i++) + idct_1d(block + i, 8); + + for (int i = 0; i < 8; i++) { + idct_1d(block, 1); + block += 8; + } +} + +static void convert(float y, float u, float v, + float *b, float *g, float *r) +{ + *r = y + 1.5747f * v; + *g = y - 0.1873f * u - 0.4682f * v; + *b = y + 1.8556f * u; +} + +static float to_linear(float x, float scale) +{ + float ax = fabsf(x); + + if (ax <= 1.f) { + return FFSIGN(x) * powf(ax, 2.2f * scale); + } else { + const float log_base = expf(2.2f * scale); + + return FFSIGN(x) * powf(log_base, ax - 1.f); + } +} + +static int dwa_uncompress(EXRContext *s, const uint8_t *src, int compressed_size, + int uncompressed_size, EXRThreadData *td) +{ + int64_t version, lo_usize, lo_size; + int64_t ac_size, dc_size, rle_usize, rle_csize, rle_raw_size; + int64_t ac_count, dc_count, ac_compression; + const int dc_w = td->xsize >> 3; + const int dc_h = td->ysize >> 3; + GetByteContext gb, agb; + int skip, ret; + + if (compressed_size <= 88) + return AVERROR_INVALIDDATA; + + version = AV_RL64(src + 0); + if (version != 2) + return AVERROR_INVALIDDATA; + + lo_usize = AV_RL64(src + 8); + lo_size = AV_RL64(src + 16); + ac_size = AV_RL64(src + 24); + dc_size = AV_RL64(src + 32); + rle_csize = AV_RL64(src + 40); + rle_usize = AV_RL64(src + 48); + rle_raw_size = AV_RL64(src + 56); + ac_count = AV_RL64(src + 64); + dc_count = AV_RL64(src + 72); + ac_compression = AV_RL64(src + 80); + + if (compressed_size < 88LL + lo_size + ac_size + dc_size + rle_csize) + return AVERROR_INVALIDDATA; + + bytestream2_init(&gb, src + 88, compressed_size - 88); + skip = bytestream2_get_le16(&gb); + if (skip < 2) + return AVERROR_INVALIDDATA; + + bytestream2_skip(&gb, skip - 2); + + if (lo_size > 0) { + if (lo_usize > uncompressed_size) + return AVERROR_INVALIDDATA; + bytestream2_skip(&gb, lo_size); + } + + if (ac_size > 0) { + unsigned long dest_len = ac_count * 2LL; + GetByteContext agb = gb; + + if (ac_count > 3LL * td->xsize * s->scan_lines_per_block) + return AVERROR_INVALIDDATA; + + av_fast_padded_malloc(&td->ac_data, &td->ac_size, dest_len); + if (!td->ac_data) + return AVERROR(ENOMEM); + + switch (ac_compression) { + case 0: + ret = huf_uncompress(s, td, &agb, (int16_t *)td->ac_data, ac_count); + if (ret < 0) + return ret; + break; + case 1: + if (uncompress(td->ac_data, &dest_len, agb.buffer, ac_size) != Z_OK || + dest_len != ac_count * 2LL) + return AVERROR_INVALIDDATA; + break; + default: + return AVERROR_INVALIDDATA; + } + + bytestream2_skip(&gb, ac_size); + } + + if (dc_size > 0) { + unsigned long dest_len = dc_count * 2LL; + GetByteContext agb = gb; + + if (dc_count > (6LL * td->xsize * td->ysize + 63) / 64) + return AVERROR_INVALIDDATA; + + av_fast_padded_malloc(&td->dc_data, &td->dc_size, FFALIGN(dest_len, 64) * 2); + if (!td->dc_data) + return AVERROR(ENOMEM); + + if (uncompress(td->dc_data + FFALIGN(dest_len, 64), &dest_len, agb.buffer, dc_size) != Z_OK || + (dest_len != dc_count * 2LL)) + return AVERROR_INVALIDDATA; + + s->dsp.predictor(td->dc_data + FFALIGN(dest_len, 64), dest_len); + s->dsp.reorder_pixels(td->dc_data, td->dc_data + FFALIGN(dest_len, 64), dest_len); + + bytestream2_skip(&gb, dc_size); + } + + if (rle_raw_size > 0 && rle_csize > 0 && rle_usize > 0) { + unsigned long dest_len = rle_usize; + + av_fast_padded_malloc(&td->rle_data, &td->rle_size, rle_usize); + if (!td->rle_data) + return AVERROR(ENOMEM); + + av_fast_padded_malloc(&td->rle_raw_data, &td->rle_raw_size, rle_raw_size); + if (!td->rle_raw_data) + return AVERROR(ENOMEM); + + if (uncompress(td->rle_data, &dest_len, gb.buffer, rle_csize) != Z_OK || + (dest_len != rle_usize)) + return AVERROR_INVALIDDATA; + + ret = rle(td->rle_raw_data, td->rle_data, rle_usize, rle_raw_size); + if (ret < 0) + return ret; + bytestream2_skip(&gb, rle_csize); + } + + bytestream2_init(&agb, td->ac_data, ac_count * 2); + + for (int y = 0; y < td->ysize; y += 8) { + for (int x = 0; x < td->xsize; x += 8) { + memset(td->block, 0, sizeof(td->block)); + + for (int j = 0; j < 3; j++) { + float *block = td->block[j]; + const int idx = (x >> 3) + (y >> 3) * dc_w + dc_w * dc_h * j; + uint16_t *dc = (uint16_t *)td->dc_data; + union av_intfloat32 dc_val; + + dc_val.i = half2float(dc[idx], s->mantissatable, + s->exponenttable, s->offsettable); + + block[0] = dc_val.f; + ac_uncompress(s, &agb, block); + dct_inverse(block); + } + + { + const float scale = s->pixel_type == EXR_FLOAT ? 2.f : 1.f; + const int o = s->nb_channels == 4; + float *bo = ((float *)td->uncompressed_data) + + y * td->xsize * s->nb_channels + td->xsize * (o + 0) + x; + float *go = ((float *)td->uncompressed_data) + + y * td->xsize * s->nb_channels + td->xsize * (o + 1) + x; + float *ro = ((float *)td->uncompressed_data) + + y * td->xsize * s->nb_channels + td->xsize * (o + 2) + x; + float *yb = td->block[0]; + float *ub = td->block[1]; + float *vb = td->block[2]; + + for (int yy = 0; yy < 8; yy++) { + for (int xx = 0; xx < 8; xx++) { + const int idx = xx + yy * 8; + + convert(yb[idx], ub[idx], vb[idx], &bo[xx], &go[xx], &ro[xx]); + + bo[xx] = to_linear(bo[xx], scale); + go[xx] = to_linear(go[xx], scale); + ro[xx] = to_linear(ro[xx], scale); + } + + bo += td->xsize * s->nb_channels; + go += td->xsize * s->nb_channels; + ro += td->xsize * s->nb_channels; + } + } + } + } + + if (s->nb_channels < 4) + return 0; + + for (int y = 0; y < td->ysize && td->rle_raw_data; y++) { + uint32_t *ao = ((uint32_t *)td->uncompressed_data) + y * td->xsize * s->nb_channels; + uint8_t *ai0 = td->rle_raw_data + y * td->xsize; + uint8_t *ai1 = td->rle_raw_data + y * td->xsize + rle_raw_size / 2; + + for (int x = 0; x < td->xsize; x++) { + uint16_t ha = ai0[x] | (ai1[x] << 8); + + ao[x] = half2float(ha, s->mantissatable, s->exponenttable, s->offsettable); + } + } + + return 0; +} + static int decode_block(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr) { @@ -1034,14 +1180,15 @@ const uint8_t *channel_buffer[4] = { 0 }; const uint8_t *buf = s->buf; uint64_t line_offset, uncompressed_size; - uint16_t *ptr_x; uint8_t *ptr; uint32_t data_size; - uint64_t line, col = 0; + int line, col = 0; uint64_t tile_x, tile_y, tile_level_x, tile_level_y; const uint8_t *src; - int axmax = (avctx->width - (s->xmax + 1)) * 2 * s->desc->nb_components; /* nb pixel to add at the right of the datawindow */ - int bxmin = s->xmin * 2 * s->desc->nb_components; /* nb pixel to add at the left of the datawindow */ + int step = s->desc->flags & AV_PIX_FMT_FLAG_FLOAT ? 4 : 2 * s->desc->nb_components; + int bxmin = 0, axmax = 0, window_xoffset = 0; + int window_xmin, window_xmax, window_ymin, window_ymax; + int data_xoffset, data_yoffset, data_window_offset, xsize, ysize; int i, x, buf_size = s->buf_size; int c, rgb_channel_count; float one_gamma = 1.0f / s->gamma; @@ -1055,6 +1202,8 @@ return AVERROR_INVALIDDATA; src = buf + line_offset + 20; + if (s->is_multipart) + src += 4; tile_x = AV_RL32(src - 20); tile_y = AV_RL32(src - 16); @@ -1070,27 +1219,23 @@ return AVERROR_PATCHWELCOME; } - if (s->xmin || s->ymin) { - avpriv_report_missing_feature(s->avctx, "Tiles with xmin/ymin"); - return AVERROR_PATCHWELCOME; - } + if (tile_x && s->tile_attr.xSize + (int64_t)FFMAX(s->xmin, 0) >= INT_MAX / tile_x ) + return AVERROR_INVALIDDATA; + if (tile_y && s->tile_attr.ySize + (int64_t)FFMAX(s->ymin, 0) >= INT_MAX / tile_y ) + return AVERROR_INVALIDDATA; - line = s->tile_attr.ySize * tile_y; + line = s->ymin + s->tile_attr.ySize * tile_y; col = s->tile_attr.xSize * tile_x; if (line < s->ymin || line > s->ymax || - col < s->xmin || col > s->xmax) + s->xmin + col < s->xmin || s->xmin + col > s->xmax) return AVERROR_INVALIDDATA; td->ysize = FFMIN(s->tile_attr.ySize, s->ydelta - tile_y * s->tile_attr.ySize); td->xsize = FFMIN(s->tile_attr.xSize, s->xdelta - tile_x * s->tile_attr.xSize); - if (col) { /* not the first tile of the line */ - bxmin = 0; /* doesn't add pixel at the left of the datawindow */ - } - - if ((col + td->xsize) != s->xdelta)/* not the last tile of the line */ - axmax = 0; /* doesn't add pixel at the right of the datawindow */ + if (td->xsize * (uint64_t)s->current_channel_offset > INT_MAX) + return AVERROR_INVALIDDATA; td->channel_line_size = td->xsize * s->current_channel_offset;/* uncompress size of one line */ uncompressed_size = td->channel_line_size * (uint64_t)td->ysize;/* uncompress size of the block */ @@ -1099,6 +1244,8 @@ return AVERROR_INVALIDDATA; src = buf + line_offset + 8; + if (s->is_multipart) + src += 4; line = AV_RL32(src - 8); if (line < s->ymin || line > s->ymax) @@ -1111,6 +1258,9 @@ td->ysize = FFMIN(s->scan_lines_per_block, s->ymax - line + 1); /* s->ydelta - line ?? */ td->xsize = s->xdelta; + if (td->xsize * (uint64_t)s->current_channel_offset > INT_MAX) + return AVERROR_INVALIDDATA; + td->channel_line_size = td->xsize * s->current_channel_offset;/* uncompress size of one line */ uncompressed_size = td->channel_line_size * (uint64_t)td->ysize;/* uncompress size of the block */ @@ -1122,6 +1272,33 @@ } } + window_xmin = FFMIN(avctx->width, FFMAX(0, s->xmin + col)); + window_xmax = FFMIN(avctx->width, FFMAX(0, s->xmin + col + td->xsize)); + window_ymin = FFMIN(avctx->height, FFMAX(0, line )); + window_ymax = FFMIN(avctx->height, FFMAX(0, line + td->ysize)); + xsize = window_xmax - window_xmin; + ysize = window_ymax - window_ymin; + + /* tile or scanline not visible skip decoding */ + if (xsize <= 0 || ysize <= 0) + return 0; + + /* is the first tile or is a scanline */ + if(col == 0) { + window_xmin = 0; + /* pixels to add at the left of the display window */ + window_xoffset = FFMAX(0, s->xmin); + /* bytes to add at the left of the display window */ + bxmin = window_xoffset * step; + } + + /* is the last tile or is a scanline */ + if(col + td->xsize == s->xdelta) { + window_xmax = avctx->width; + /* bytes to add at the right of the display window */ + axmax = FFMAX(0, (avctx->width - (s->xmax + 1))) * step; + } + if (data_size < uncompressed_size || s->is_tile) { /* td->tmp is use for tile reorganization */ av_fast_padded_malloc(&td->tmp, &td->tmp_size, uncompressed_size); if (!td->tmp) @@ -1154,6 +1331,10 @@ case EXR_B44A: ret = b44_uncompress(s, src, data_size, uncompressed_size, td); break; + case EXR_DWAA: + case EXR_DWAB: + ret = dwa_uncompress(s, src, data_size, uncompressed_size, td); + break; } if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "decode_block() failed.\n"); @@ -1162,82 +1343,117 @@ src = td->uncompressed_data; } + /* offsets to crop data outside display window */ + data_xoffset = FFABS(FFMIN(0, s->xmin + col)) * (s->pixel_type == EXR_HALF ? 2 : 4); + data_yoffset = FFABS(FFMIN(0, line)); + data_window_offset = (data_yoffset * td->channel_line_size) + data_xoffset; + if (!s->is_luma) { - channel_buffer[0] = src + td->xsize * s->channel_offsets[0]; - channel_buffer[1] = src + td->xsize * s->channel_offsets[1]; - channel_buffer[2] = src + td->xsize * s->channel_offsets[2]; + channel_buffer[0] = src + (td->xsize * s->channel_offsets[0]) + data_window_offset; + channel_buffer[1] = src + (td->xsize * s->channel_offsets[1]) + data_window_offset; + channel_buffer[2] = src + (td->xsize * s->channel_offsets[2]) + data_window_offset; rgb_channel_count = 3; } else { /* put y data in the first channel_buffer */ - channel_buffer[0] = src + td->xsize * s->channel_offsets[1]; + channel_buffer[0] = src + (td->xsize * s->channel_offsets[1]) + data_window_offset; rgb_channel_count = 1; } - if (s->channel_offsets[3] >= 0) - channel_buffer[3] = src + td->xsize * s->channel_offsets[3]; + if (s->channel_offsets[3] >= 0) + channel_buffer[3] = src + (td->xsize * s->channel_offsets[3]) + data_window_offset; - ptr = p->data[0] + line * p->linesize[0] + (col * s->desc->nb_components * 2); - - for (i = 0; - i < td->ysize; i++, ptr += p->linesize[0]) { - - const uint8_t * a; - const uint8_t *rgb[3]; + if (s->desc->flags & AV_PIX_FMT_FLAG_FLOAT) { + /* todo: change this when a floating point pixel format with luma with alpha is implemented */ + int channel_count = s->channel_offsets[3] >= 0 ? 4 : rgb_channel_count; + if (s->is_luma) { + channel_buffer[1] = channel_buffer[0]; + channel_buffer[2] = channel_buffer[0]; + } + + for (c = 0; c < channel_count; c++) { + int plane = s->desc->comp[c].plane; + ptr = p->data[plane] + window_ymin * p->linesize[plane] + (window_xmin * 4); + + for (i = 0; i < ysize; i++, ptr += p->linesize[plane]) { + const uint8_t *src; + union av_intfloat32 *ptr_x; + + src = channel_buffer[c]; + ptr_x = (union av_intfloat32 *)ptr; + + // Zero out the start if xmin is not 0 + memset(ptr_x, 0, bxmin); + ptr_x += window_xoffset; + + if (s->pixel_type == EXR_FLOAT || + s->compression == EXR_DWAA || + s->compression == EXR_DWAB) { + // 32-bit + union av_intfloat32 t; + if (trc_func && c < 3) { + for (x = 0; x < xsize; x++) { + t.i = bytestream_get_le32(&src); + t.f = trc_func(t.f); + *ptr_x++ = t; + } + } else if (one_gamma != 1.f) { + for (x = 0; x < xsize; x++) { + t.i = bytestream_get_le32(&src); + if (t.f > 0.0f && c < 3) /* avoid negative values */ + t.f = powf(t.f, one_gamma); + *ptr_x++ = t; + } + } else { + for (x = 0; x < xsize; x++) { + t.i = bytestream_get_le32(&src); + *ptr_x++ = t; + } + } + } else if (s->pixel_type == EXR_HALF) { + // 16-bit + if (c < 3 || !trc_func) { + for (x = 0; x < xsize; x++) { + *ptr_x++ = s->gamma_table[bytestream_get_le16(&src)]; + } + } else { + for (x = 0; x < xsize; x++) { + ptr_x[0].i = half2float(bytestream_get_le16(&src), + s->mantissatable, + s->exponenttable, + s->offsettable); + ptr_x++; + } + } + } - for (c = 0; c < rgb_channel_count; c++){ - rgb[c] = channel_buffer[c]; + // Zero out the end if xmax+1 is not w + memset(ptr_x, 0, axmax); + channel_buffer[c] += td->channel_line_size; + } } + } else { - if (channel_buffer[3]) - a = channel_buffer[3]; + av_assert1(s->pixel_type == EXR_UINT); + ptr = p->data[0] + window_ymin * p->linesize[0] + (window_xmin * s->desc->nb_components * 2); - ptr_x = (uint16_t *) ptr; + for (i = 0; i < ysize; i++, ptr += p->linesize[0]) { - // Zero out the start if xmin is not 0 - memset(ptr_x, 0, bxmin); - ptr_x += s->xmin * s->desc->nb_components; + const uint8_t * a; + const uint8_t *rgb[3]; + uint16_t *ptr_x; - if (s->pixel_type == EXR_FLOAT) { - // 32-bit - if (trc_func) { - for (x = 0; x < td->xsize; x++) { - union av_intfloat32 t; + for (c = 0; c < rgb_channel_count; c++) { + rgb[c] = channel_buffer[c]; + } - for (c = 0; c < rgb_channel_count; c++) { - t.i = bytestream_get_le32(&rgb[c]); - t.f = trc_func(t.f); - *ptr_x++ = exr_flt2uint(t.i); - } - if (channel_buffer[3]) - *ptr_x++ = exr_flt2uint(bytestream_get_le32(&a)); - } - } else { - for (x = 0; x < td->xsize; x++) { - union av_intfloat32 t; - int c; + if (channel_buffer[3]) + a = channel_buffer[3]; - for (c = 0; c < rgb_channel_count; c++) { - t.i = bytestream_get_le32(&rgb[c]); - if (t.f > 0.0f) /* avoid negative values */ - t.f = powf(t.f, one_gamma); - *ptr_x++ = exr_flt2uint(t.i); - } + ptr_x = (uint16_t *) ptr; - if (channel_buffer[3]) - *ptr_x++ = exr_flt2uint(bytestream_get_le32(&a)); - } - } - } else if (s->pixel_type == EXR_HALF) { - // 16-bit - for (x = 0; x < td->xsize; x++) { - int c; - for (c = 0; c < rgb_channel_count; c++) { - *ptr_x++ = s->gamma_table[bytestream_get_le16(&rgb[c])]; - } + // Zero out the start if xmin is not 0 + memset(ptr_x, 0, bxmin); + ptr_x += window_xoffset * s->desc->nb_components; - if (channel_buffer[3]) - *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&a)); - } - } else if (s->pixel_type == EXR_UINT) { - for (x = 0; x < td->xsize; x++) { + for (x = 0; x < xsize; x++) { for (c = 0; c < rgb_channel_count; c++) { *ptr_x++ = bytestream_get_le32(&rgb[c]) >> 16; } @@ -1245,21 +1461,38 @@ if (channel_buffer[3]) *ptr_x++ = bytestream_get_le32(&a) >> 16; } - } - // Zero out the end if xmax+1 is not w - memset(ptr_x, 0, axmax); + // Zero out the end if xmax+1 is not w + memset(ptr_x, 0, axmax); - channel_buffer[0] += td->channel_line_size; - channel_buffer[1] += td->channel_line_size; - channel_buffer[2] += td->channel_line_size; - if (channel_buffer[3]) - channel_buffer[3] += td->channel_line_size; + channel_buffer[0] += td->channel_line_size; + channel_buffer[1] += td->channel_line_size; + channel_buffer[2] += td->channel_line_size; + if (channel_buffer[3]) + channel_buffer[3] += td->channel_line_size; + } } return 0; } +static void skip_header_chunk(EXRContext *s) +{ + GetByteContext *gb = &s->gb; + + while (bytestream2_get_bytes_left(gb) > 0) { + if (!bytestream2_peek_byte(gb)) + break; + + // Process unknown variables + for (int i = 0; i < 2; i++) // value_name and value_type + while (bytestream2_get_byte(gb) != 0); + + // Skip variable length + bytestream2_skip(gb, bytestream2_get_le32(gb)); + } +} + /** * Check if the variable name corresponds to its data type. * @@ -1277,21 +1510,22 @@ const char *value_type, unsigned int minimum_length) { + GetByteContext *gb = &s->gb; int var_size = -1; - if (bytestream2_get_bytes_left(&s->gb) >= minimum_length && - !strcmp(s->gb.buffer, value_name)) { + if (bytestream2_get_bytes_left(gb) >= minimum_length && + !strcmp(gb->buffer, value_name)) { // found value_name, jump to value_type (null terminated strings) - s->gb.buffer += strlen(value_name) + 1; - if (!strcmp(s->gb.buffer, value_type)) { - s->gb.buffer += strlen(value_type) + 1; - var_size = bytestream2_get_le32(&s->gb); + gb->buffer += strlen(value_name) + 1; + if (!strcmp(gb->buffer, value_type)) { + gb->buffer += strlen(value_type) + 1; + var_size = bytestream2_get_le32(gb); // don't go read past boundaries - if (var_size > bytestream2_get_bytes_left(&s->gb)) + if (var_size > bytestream2_get_bytes_left(gb)) var_size = 0; } else { // value_type not found, reset the buffer - s->gb.buffer -= strlen(value_name) + 1; + gb->buffer -= strlen(value_name) + 1; av_log(s->avctx, AV_LOG_WARNING, "Unknown data type %s for header variable %s.\n", value_type, value_name); @@ -1304,7 +1538,8 @@ static int decode_header(EXRContext *s, AVFrame *frame) { AVDictionary *metadata = NULL; - int magic_number, version, i, flags, sar = 0; + GetByteContext *gb = &s->gb; + int magic_number, version, flags; int layer_match = 0; int ret; int dup_channels = 0; @@ -1328,14 +1563,16 @@ s->tile_attr.xSize = -1; s->tile_attr.ySize = -1; s->is_tile = 0; + s->is_multipart = 0; s->is_luma = 0; + s->current_part = 0; - if (bytestream2_get_bytes_left(&s->gb) < 10) { + if (bytestream2_get_bytes_left(gb) < 10) { av_log(s->avctx, AV_LOG_ERROR, "Header too short to parse.\n"); return AVERROR_INVALIDDATA; } - magic_number = bytestream2_get_le32(&s->gb); + magic_number = bytestream2_get_le32(gb); if (magic_number != 20000630) { /* As per documentation of OpenEXR, it is supposed to be * int 20000630 little-endian */ @@ -1343,28 +1580,60 @@ return AVERROR_INVALIDDATA; } - version = bytestream2_get_byte(&s->gb); + version = bytestream2_get_byte(gb); if (version != 2) { avpriv_report_missing_feature(s->avctx, "Version %d", version); return AVERROR_PATCHWELCOME; } - flags = bytestream2_get_le24(&s->gb); + flags = bytestream2_get_le24(gb); if (flags & 0x02) s->is_tile = 1; + if (flags & 0x10) + s->is_multipart = 1; if (flags & 0x08) { avpriv_report_missing_feature(s->avctx, "deep data"); return AVERROR_PATCHWELCOME; } - if (flags & 0x10) { - avpriv_report_missing_feature(s->avctx, "multipart"); - return AVERROR_PATCHWELCOME; - } // Parse the header - while (bytestream2_get_bytes_left(&s->gb) > 0 && *s->gb.buffer) { + while (bytestream2_get_bytes_left(gb) > 0) { int var_size; + + while (s->is_multipart && s->current_part < s->selected_part && + bytestream2_get_bytes_left(gb) > 0) { + if (bytestream2_peek_byte(gb)) { + skip_header_chunk(s); + } else { + bytestream2_skip(gb, 1); + if (!bytestream2_peek_byte(gb)) + break; + } + bytestream2_skip(gb, 1); + s->current_part++; + } + + if (!bytestream2_peek_byte(gb)) { + if (!s->is_multipart) + break; + bytestream2_skip(gb, 1); + if (s->current_part == s->selected_part) { + while (bytestream2_get_bytes_left(gb) > 0) { + if (bytestream2_peek_byte(gb)) { + skip_header_chunk(s); + } else { + bytestream2_skip(gb, 1); + if (!bytestream2_peek_byte(gb)) + break; + } + } + } + if (!bytestream2_peek_byte(gb)) + break; + s->current_part++; + } + if ((var_size = check_header_variable(s, "channels", "chlist", 38)) >= 0) { GetByteContext ch_gb; @@ -1373,7 +1642,7 @@ goto fail; } - bytestream2_init(&ch_gb, s->gb.buffer, var_size); + bytestream2_init(&ch_gb, gb->buffer, var_size); while (bytestream2_get_bytes_left(&ch_gb) >= 19) { EXRChannel *channel; @@ -1399,24 +1668,24 @@ } if (layer_match) { /* only search channel if the layer match is valid */ - if (!strcmp(ch_gb.buffer, "R") || - !strcmp(ch_gb.buffer, "X") || - !strcmp(ch_gb.buffer, "U")) { + if (!av_strcasecmp(ch_gb.buffer, "R") || + !av_strcasecmp(ch_gb.buffer, "X") || + !av_strcasecmp(ch_gb.buffer, "U")) { channel_index = 0; s->is_luma = 0; - } else if (!strcmp(ch_gb.buffer, "G") || - !strcmp(ch_gb.buffer, "V")) { + } else if (!av_strcasecmp(ch_gb.buffer, "G") || + !av_strcasecmp(ch_gb.buffer, "V")) { channel_index = 1; s->is_luma = 0; - } else if (!strcmp(ch_gb.buffer, "Y")) { + } else if (!av_strcasecmp(ch_gb.buffer, "Y")) { channel_index = 1; s->is_luma = 1; - } else if (!strcmp(ch_gb.buffer, "B") || - !strcmp(ch_gb.buffer, "Z") || - !strcmp(ch_gb.buffer, "W")){ - channel_index = 2; + } else if (!av_strcasecmp(ch_gb.buffer, "B") || + !av_strcasecmp(ch_gb.buffer, "Z") || + !av_strcasecmp(ch_gb.buffer, "W")) { + channel_index = 2; s->is_luma = 0; - } else if (!strcmp(ch_gb.buffer, "A")) { + } else if (!av_strcasecmp(ch_gb.buffer, "A")) { channel_index = 3; } else { av_log(s->avctx, AV_LOG_WARNING, @@ -1494,7 +1763,7 @@ /* Check if all channels are set with an offset or if the channels * are causing an overflow */ - if (!s->is_luma){/* if we expected to have at least 3 channels */ + if (!s->is_luma) {/* if we expected to have at least 3 channels */ if (FFMIN3(s->channel_offsets[0], s->channel_offsets[1], s->channel_offsets[2]) < 0) { @@ -1510,33 +1779,51 @@ } // skip one last byte and update main gb - s->gb.buffer = ch_gb.buffer + 1; + gb->buffer = ch_gb.buffer + 1; continue; } else if ((var_size = check_header_variable(s, "dataWindow", "box2i", 31)) >= 0) { + int xmin, ymin, xmax, ymax; if (!var_size) { ret = AVERROR_INVALIDDATA; goto fail; } - s->xmin = bytestream2_get_le32(&s->gb); - s->ymin = bytestream2_get_le32(&s->gb); - s->xmax = bytestream2_get_le32(&s->gb); - s->ymax = bytestream2_get_le32(&s->gb); + xmin = bytestream2_get_le32(gb); + ymin = bytestream2_get_le32(gb); + xmax = bytestream2_get_le32(gb); + ymax = bytestream2_get_le32(gb); + + if (xmin > xmax || ymin > ymax || + (unsigned)xmax - xmin >= INT_MAX || + (unsigned)ymax - ymin >= INT_MAX) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + s->xmin = xmin; + s->xmax = xmax; + s->ymin = ymin; + s->ymax = ymax; s->xdelta = (s->xmax - s->xmin) + 1; s->ydelta = (s->ymax - s->ymin) + 1; continue; } else if ((var_size = check_header_variable(s, "displayWindow", "box2i", 34)) >= 0) { + int32_t sx, sy, dx, dy; + if (!var_size) { ret = AVERROR_INVALIDDATA; goto fail; } - bytestream2_skip(&s->gb, 8); - s->w = bytestream2_get_le32(&s->gb) + 1; - s->h = bytestream2_get_le32(&s->gb) + 1; + sx = bytestream2_get_le32(gb); + sy = bytestream2_get_le32(gb); + dx = bytestream2_get_le32(gb); + dy = bytestream2_get_le32(gb); + + s->w = dx - sx + 1; + s->h = dy - sy + 1; continue; } else if ((var_size = check_header_variable(s, "lineOrder", @@ -1547,7 +1834,7 @@ goto fail; } - line_order = bytestream2_get_byte(&s->gb); + line_order = bytestream2_get_byte(gb); av_log(s->avctx, AV_LOG_DEBUG, "line order: %d.\n", line_order); if (line_order > 2) { av_log(s->avctx, AV_LOG_ERROR, "Unknown line order.\n"); @@ -1563,7 +1850,7 @@ goto fail; } - sar = bytestream2_get_le32(&s->gb); + s->sar = bytestream2_get_le32(gb); continue; } else if ((var_size = check_header_variable(s, "compression", @@ -1574,10 +1861,12 @@ } if (s->compression == EXR_UNKN) - s->compression = bytestream2_get_byte(&s->gb); - else + s->compression = bytestream2_get_byte(gb); + else { + bytestream2_skip(gb, 1); av_log(s->avctx, AV_LOG_WARNING, "Found more than one compression attribute.\n"); + } continue; } else if ((var_size = check_header_variable(s, "tiles", @@ -1588,14 +1877,14 @@ av_log(s->avctx, AV_LOG_WARNING, "Found tile attribute and scanline flags. Exr will be interpreted as scanline.\n"); - s->tile_attr.xSize = bytestream2_get_le32(&s->gb); - s->tile_attr.ySize = bytestream2_get_le32(&s->gb); + s->tile_attr.xSize = bytestream2_get_le32(gb); + s->tile_attr.ySize = bytestream2_get_le32(gb); - tileLevel = bytestream2_get_byte(&s->gb); + tileLevel = bytestream2_get_byte(gb); s->tile_attr.level_mode = tileLevel & 0x0f; s->tile_attr.level_round = (tileLevel >> 4) & 0x0f; - if (s->tile_attr.level_mode >= EXR_TILE_LEVEL_UNKNOWN){ + if (s->tile_attr.level_mode >= EXR_TILE_LEVEL_UNKNOWN) { avpriv_report_missing_feature(s->avctx, "Tile level mode %d", s->tile_attr.level_mode); ret = AVERROR_PATCHWELCOME; @@ -1614,29 +1903,85 @@ "string", 1)) >= 0) { uint8_t key[256] = { 0 }; - bytestream2_get_buffer(&s->gb, key, FFMIN(sizeof(key) - 1, var_size)); + bytestream2_get_buffer(gb, key, FFMIN(sizeof(key) - 1, var_size)); av_dict_set(&metadata, "writer", key, 0); continue; + } else if ((var_size = check_header_variable(s, "framesPerSecond", + "rational", 33)) >= 0) { + if (!var_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + s->avctx->framerate.num = bytestream2_get_le32(gb); + s->avctx->framerate.den = bytestream2_get_le32(gb); + + continue; + } else if ((var_size = check_header_variable(s, "chunkCount", + "int", 23)) >= 0) { + + s->chunk_count = bytestream2_get_le32(gb); + + continue; + } else if ((var_size = check_header_variable(s, "type", + "string", 16)) >= 0) { + uint8_t key[256] = { 0 }; + + bytestream2_get_buffer(gb, key, FFMIN(sizeof(key) - 1, var_size)); + if (strncmp("scanlineimage", key, var_size) && + strncmp("tiledimage", key, var_size)) + return AVERROR_PATCHWELCOME; + + continue; + } else if ((var_size = check_header_variable(s, "preview", + "preview", 16)) >= 0) { + uint32_t pw = bytestream2_get_le32(gb); + uint32_t ph = bytestream2_get_le32(gb); + int64_t psize = 4LL * pw * ph; + + if (psize >= bytestream2_get_bytes_left(gb)) + return AVERROR_INVALIDDATA; + + bytestream2_skip(gb, psize); + + continue; } // Check if there are enough bytes for a header - if (bytestream2_get_bytes_left(&s->gb) <= 9) { + if (bytestream2_get_bytes_left(gb) <= 9) { av_log(s->avctx, AV_LOG_ERROR, "Incomplete header\n"); ret = AVERROR_INVALIDDATA; goto fail; } // Process unknown variables - for (i = 0; i < 2; i++) // value_name and value_type - while (bytestream2_get_byte(&s->gb) != 0); - - // Skip variable length - bytestream2_skip(&s->gb, bytestream2_get_le32(&s->gb)); + { + uint8_t name[256] = { 0 }; + uint8_t type[256] = { 0 }; + uint8_t value[256] = { 0 }; + int i = 0, size; + + while (bytestream2_get_bytes_left(gb) > 0 && + bytestream2_peek_byte(gb) && i < 255) { + name[i++] = bytestream2_get_byte(gb); + } + + bytestream2_skip(gb, 1); + i = 0; + while (bytestream2_get_bytes_left(gb) > 0 && + bytestream2_peek_byte(gb) && i < 255) { + type[i++] = bytestream2_get_byte(gb); + } + bytestream2_skip(gb, 1); + size = bytestream2_get_le32(gb); + + bytestream2_get_buffer(gb, value, FFMIN(sizeof(value) - 1, size)); + if (!strcmp(type, "string")) + av_dict_set(&metadata, name, value, 0); + } } - ff_set_sar(s->avctx, av_d2q(av_int2float(sar), 255)); - if (s->compression == EXR_UNKN) { av_log(s->avctx, AV_LOG_ERROR, "Missing compression attribute.\n"); ret = AVERROR_INVALIDDATA; @@ -1651,7 +1996,7 @@ } } - if (bytestream2_get_bytes_left(&s->gb) <= 0) { + if (bytestream2_get_bytes_left(gb) <= 0) { av_log(s->avctx, AV_LOG_ERROR, "Incomplete frame.\n"); ret = AVERROR_INVALIDDATA; goto fail; @@ -1660,7 +2005,7 @@ frame->metadata = metadata; // aaand we are done - bytestream2_skip(&s->gb, 1); + bytestream2_skip(gb, 1); return 0; fail: av_dict_free(&metadata); @@ -1671,25 +2016,49 @@ int *got_frame, AVPacket *avpkt) { EXRContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; ThreadFrame frame = { .f = data }; AVFrame *picture = data; uint8_t *ptr; - int y, ret; + int i, y, ret, ymax; + int planes; int out_line_size; int nb_blocks; /* nb scanline or nb tile */ uint64_t start_offset_table; uint64_t start_next_scanline; PutByteContext offset_table_writer; - bytestream2_init(&s->gb, avpkt->data, avpkt->size); + bytestream2_init(gb, avpkt->data, avpkt->size); if ((ret = decode_header(s, picture)) < 0) return ret; + if ((s->compression == EXR_DWAA || s->compression == EXR_DWAB) && + s->pixel_type == EXR_HALF) { + s->current_channel_offset *= 2; + for (int i = 0; i < 4; i++) + s->channel_offsets[i] *= 2; + } + switch (s->pixel_type) { case EXR_FLOAT: case EXR_HALF: + if (s->channel_offsets[3] >= 0) { + if (!s->is_luma) { + avctx->pix_fmt = AV_PIX_FMT_GBRAPF32; + } else { + /* todo: change this when a floating point pixel format with luma with alpha is implemented */ + avctx->pix_fmt = AV_PIX_FMT_GBRAPF32; + } + } else { + if (!s->is_luma) { + avctx->pix_fmt = AV_PIX_FMT_GBRPF32; + } else { + avctx->pix_fmt = AV_PIX_FMT_GRAYF32; + } + } + break; case EXR_UINT: if (s->channel_offsets[3] >= 0) { if (!s->is_luma) { @@ -1726,20 +2095,21 @@ case EXR_PIZ: case EXR_B44: case EXR_B44A: + case EXR_DWAA: s->scan_lines_per_block = 32; break; + case EXR_DWAB: + s->scan_lines_per_block = 256; + break; default: avpriv_report_missing_feature(avctx, "Compression %d", s->compression); return AVERROR_PATCHWELCOME; } - /* Verify the xmin, xmax, ymin, ymax and xdelta before setting - * the actual image size. */ - if (s->xmin > s->xmax || - s->ymin > s->ymax || - s->xdelta != s->xmax - s->xmin + 1 || - s->xmax >= s->w || - s->ymax >= s->h) { + /* Verify the xmin, xmax, ymin and ymax before setting the actual image size. + * It's possible for the data window can larger or outside the display window */ + if (s->xmin > s->xmax || s->ymin > s->ymax || + s->ydelta == 0xFFFFFFFF || s->xdelta == 0xFFFFFFFF) { av_log(avctx, AV_LOG_ERROR, "Wrong or missing size information.\n"); return AVERROR_INVALIDDATA; } @@ -1747,10 +2117,19 @@ if ((ret = ff_set_dimensions(avctx, s->w, s->h)) < 0) return ret; + ff_set_sar(s->avctx, av_d2q(av_int2float(s->sar), 255)); + s->desc = av_pix_fmt_desc_get(avctx->pix_fmt); if (!s->desc) return AVERROR_INVALIDDATA; - out_line_size = avctx->width * 2 * s->desc->nb_components; + + if (s->desc->flags & AV_PIX_FMT_FLAG_FLOAT) { + planes = s->desc->nb_components; + out_line_size = avctx->width * 4; + } else { + planes = 1; + out_line_size = avctx->width * 2 * s->desc->nb_components; + } if (s->is_tile) { nb_blocks = ((s->xdelta + s->tile_attr.xSize - 1) / s->tile_attr.xSize) * @@ -1763,14 +2142,14 @@ if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; - if (bytestream2_get_bytes_left(&s->gb) < nb_blocks * 8) + if (bytestream2_get_bytes_left(gb)/8 < nb_blocks) return AVERROR_INVALIDDATA; // check offset table and recreate it if need - if (!s->is_tile && bytestream2_peek_le64(&s->gb) == 0) { + if (!s->is_tile && bytestream2_peek_le64(gb) == 0) { av_log(s->avctx, AV_LOG_DEBUG, "recreating invalid scanline offset table\n"); - start_offset_table = bytestream2_tell(&s->gb); + start_offset_table = bytestream2_tell(gb); start_next_scanline = start_offset_table + nb_blocks * 8; bytestream2_init_writer(&offset_table_writer, &avpkt->data[start_offset_table], nb_blocks * 8); @@ -1779,33 +2158,39 @@ bytestream2_put_le64(&offset_table_writer, start_next_scanline); /* get len of next scanline */ - bytestream2_seek(&s->gb, start_next_scanline + 4, SEEK_SET);/* skip line number */ - start_next_scanline += (bytestream2_get_le32(&s->gb) + 8); + bytestream2_seek(gb, start_next_scanline + 4, SEEK_SET);/* skip line number */ + start_next_scanline += (bytestream2_get_le32(gb) + 8); } - bytestream2_seek(&s->gb, start_offset_table, SEEK_SET); + bytestream2_seek(gb, start_offset_table, SEEK_SET); } // save pointer we are going to use in decode_block s->buf = avpkt->data; s->buf_size = avpkt->size; - ptr = picture->data[0]; // Zero out the start if ymin is not 0 - for (y = 0; y < s->ymin; y++) { - memset(ptr, 0, out_line_size); - ptr += picture->linesize[0]; + for (i = 0; i < planes; i++) { + ptr = picture->data[i]; + for (y = 0; y < FFMIN(s->ymin, s->h); y++) { + memset(ptr, 0, out_line_size); + ptr += picture->linesize[i]; + } } s->picture = picture; avctx->execute2(avctx, decode_block, s->thread_data, NULL, nb_blocks); + ymax = FFMAX(0, s->ymax + 1); // Zero out the end if ymax+1 is not h - ptr = picture->data[0] + ((s->ymax+1) * picture->linesize[0]); - for (y = s->ymax + 1; y < avctx->height; y++) { - memset(ptr, 0, out_line_size); - ptr += picture->linesize[0]; - } + if (ymax < avctx->height) + for (i = 0; i < planes; i++) { + ptr = picture->data[i] + (ymax * picture->linesize[i]); + for (y = ymax; y < avctx->height; y++) { + memset(ptr, 0, out_line_size); + ptr += picture->linesize[i]; + } + } picture->pict_type = AV_PICTURE_TYPE_I; *got_frame = 1; @@ -1821,6 +2206,8 @@ float one_gamma = 1.0f / s->gamma; avpriv_trc_function trc_func = NULL; + half2float_table(s->mantissatable, s->exponenttable, s->offsettable); + s->avctx = avctx; ff_exrdsp_init(&s->dsp); @@ -1832,23 +2219,24 @@ trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type); if (trc_func) { for (i = 0; i < 65536; ++i) { - t = exr_half2float(i); + t.i = half2float(i, s->mantissatable, s->exponenttable, s->offsettable); t.f = trc_func(t.f); - s->gamma_table[i] = exr_flt2uint(t.i); + s->gamma_table[i] = t; } } else { if (one_gamma > 0.9999f && one_gamma < 1.0001f) { - for (i = 0; i < 65536; ++i) - s->gamma_table[i] = exr_halflt2uint(i); + for (i = 0; i < 65536; ++i) { + s->gamma_table[i].i = half2float(i, s->mantissatable, s->exponenttable, s->offsettable); + } } else { for (i = 0; i < 65536; ++i) { - t = exr_half2float(i); + t.i = half2float(i, s->mantissatable, s->exponenttable, s->offsettable); /* If negative value we reuse half value */ if (t.f <= 0.0f) { - s->gamma_table[i] = exr_halflt2uint(i); + s->gamma_table[i] = t; } else { t.f = powf(t.f, one_gamma); - s->gamma_table[i] = exr_flt2uint(t.i); + s->gamma_table[i] = t; } } } @@ -1862,19 +2250,6 @@ return 0; } -#if HAVE_THREADS -static int decode_init_thread_copy(AVCodecContext *avctx) -{ EXRContext *s = avctx->priv_data; - - // allocate thread data, used for non EXR_RAW compression types - s->thread_data = av_mallocz_array(avctx->thread_count, sizeof(EXRThreadData)); - if (!s->thread_data) - return AVERROR_INVALIDDATA; - - return 0; -} -#endif - static av_cold int decode_end(AVCodecContext *avctx) { EXRContext *s = avctx->priv_data; @@ -1885,6 +2260,13 @@ av_freep(&td->tmp); av_freep(&td->bitmap); av_freep(&td->lut); + av_freep(&td->he); + av_freep(&td->freq); + av_freep(&td->ac_data); + av_freep(&td->dc_data); + av_freep(&td->rle_data); + av_freep(&td->rle_raw_data); + ff_free_vlc(&td->vlc); } av_freep(&s->thread_data); @@ -1898,6 +2280,8 @@ static const AVOption options[] = { { "layer", "Set the decoding layer", OFFSET(layer), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD }, + { "part", "Set the decoding part", OFFSET(selected_part), + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VD }, { "gamma", "Set the float gamma value when decoding", OFFSET(gamma), AV_OPT_TYPE_FLOAT, { .dbl = 1.0f }, 0.001, FLT_MAX, VD }, @@ -1954,7 +2338,6 @@ .id = AV_CODEC_ID_EXR, .priv_data_size = sizeof(EXRContext), .init = decode_init, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | diff -Nru ffmpeg-4.2.2/libavcodec/exrenc.c ffmpeg-4.4/libavcodec/exrenc.c --- ffmpeg-4.2.2/libavcodec/exrenc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/exrenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,552 @@ +/* + * 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 + */ + +/** + * @file + * OpenEXR encoder + */ + +#include +#include + +#include "libavutil/avassert.h" +#include "libavutil/opt.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "float2half.h" + +enum ExrCompr { + EXR_RAW, + EXR_RLE, + EXR_ZIP1, + EXR_ZIP16, + EXR_NBCOMPR, +}; + +enum ExrPixelType { + EXR_UINT, + EXR_HALF, + EXR_FLOAT, + EXR_UNKNOWN, +}; + +static const char abgr_chlist[4] = { 'A', 'B', 'G', 'R' }; +static const char bgr_chlist[4] = { 'B', 'G', 'R', 'A' }; +static const uint8_t gbra_order[4] = { 3, 1, 0, 2 }; +static const uint8_t gbr_order[4] = { 1, 0, 2, 0 }; + +typedef struct EXRScanlineData { + uint8_t *compressed_data; + unsigned int compressed_size; + + uint8_t *uncompressed_data; + unsigned int uncompressed_size; + + uint8_t *tmp; + unsigned int tmp_size; + + int64_t actual_size; +} EXRScanlineData; + +typedef struct EXRContext { + const AVClass *class; + + int compression; + int pixel_type; + int planes; + int nb_scanlines; + int scanline_height; + float gamma; + const char *ch_names; + const uint8_t *ch_order; + PutByteContext pb; + + EXRScanlineData *scanline; + + uint16_t basetable[512]; + uint8_t shifttable[512]; +} EXRContext; + +static int encode_init(AVCodecContext *avctx) +{ + EXRContext *s = avctx->priv_data; + + float2half_tables(s->basetable, s->shifttable); + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_GBRPF32: + s->planes = 3; + s->ch_names = bgr_chlist; + s->ch_order = gbr_order; + break; + case AV_PIX_FMT_GBRAPF32: + s->planes = 4; + s->ch_names = abgr_chlist; + s->ch_order = gbra_order; + break; + default: + av_assert0(0); + } + + switch (s->compression) { + case EXR_RAW: + case EXR_RLE: + case EXR_ZIP1: + s->scanline_height = 1; + s->nb_scanlines = avctx->height; + break; + case EXR_ZIP16: + s->scanline_height = 16; + s->nb_scanlines = (avctx->height + s->scanline_height - 1) / s->scanline_height; + break; + default: + av_assert0(0); + } + + s->scanline = av_calloc(s->nb_scanlines, sizeof(*s->scanline)); + if (!s->scanline) + return AVERROR(ENOMEM); + + return 0; +} + +static int encode_close(AVCodecContext *avctx) +{ + EXRContext *s = avctx->priv_data; + + for (int y = 0; y < s->nb_scanlines && s->scanline; y++) { + EXRScanlineData *scanline = &s->scanline[y]; + + av_freep(&scanline->tmp); + av_freep(&scanline->compressed_data); + av_freep(&scanline->uncompressed_data); + } + + av_freep(&s->scanline); + + return 0; +} + +static void reorder_pixels(uint8_t *dst, const uint8_t *src, ptrdiff_t size) +{ + const ptrdiff_t half_size = (size + 1) / 2; + uint8_t *t1 = dst; + uint8_t *t2 = dst + half_size; + + for (ptrdiff_t i = 0; i < half_size; i++) { + t1[i] = *(src++); + t2[i] = *(src++); + } +} + +static void predictor(uint8_t *src, ptrdiff_t size) +{ + int p = src[0]; + + for (ptrdiff_t i = 1; i < size; i++) { + int d = src[i] - p + 384; + + p = src[i]; + src[i] = d; + } +} + +static int64_t rle_compress(uint8_t *out, int64_t out_size, + const uint8_t *in, int64_t in_size) +{ + int64_t i = 0, o = 0, run = 1, copy = 0; + + while (i < in_size) { + while (i + run < in_size && in[i] == in[i + run] && run < 128) + run++; + + if (run >= 3) { + if (o + 2 >= out_size) + return -1; + out[o++] = run - 1; + out[o++] = in[i]; + i += run; + } else { + if (i + run < in_size) + copy += run; + while (i + copy < in_size && copy < 127 && in[i + copy] != in[i + copy - 1]) + copy++; + + if (o + 1 + copy >= out_size) + return -1; + out[o++] = -copy; + + for (int x = 0; x < copy; x++) + out[o + x] = in[i + x]; + + o += copy; + i += copy; + copy = 0; + } + + run = 1; + } + + return o; +} + +static int encode_scanline_rle(EXRContext *s, const AVFrame *frame) +{ + const int64_t element_size = s->pixel_type == EXR_HALF ? 2LL : 4LL; + + for (int y = 0; y < frame->height; y++) { + EXRScanlineData *scanline = &s->scanline[y]; + int64_t tmp_size = element_size * s->planes * frame->width; + int64_t max_compressed_size = tmp_size * 3 / 2; + + av_fast_padded_malloc(&scanline->uncompressed_data, &scanline->uncompressed_size, tmp_size); + if (!scanline->uncompressed_data) + return AVERROR(ENOMEM); + + av_fast_padded_malloc(&scanline->tmp, &scanline->tmp_size, tmp_size); + if (!scanline->tmp) + return AVERROR(ENOMEM); + + av_fast_padded_malloc(&scanline->compressed_data, &scanline->compressed_size, max_compressed_size); + if (!scanline->compressed_data) + return AVERROR(ENOMEM); + + switch (s->pixel_type) { + case EXR_FLOAT: + for (int p = 0; p < s->planes; p++) { + int ch = s->ch_order[p]; + + memcpy(scanline->uncompressed_data + frame->width * 4 * p, + frame->data[ch] + y * frame->linesize[ch], frame->width * 4); + } + break; + case EXR_HALF: + for (int p = 0; p < s->planes; p++) { + int ch = s->ch_order[p]; + uint16_t *dst = (uint16_t *)(scanline->uncompressed_data + frame->width * 2 * p); + uint32_t *src = (uint32_t *)(frame->data[ch] + y * frame->linesize[ch]); + + for (int x = 0; x < frame->width; x++) + dst[x] = float2half(src[x], s->basetable, s->shifttable); + } + break; + } + + reorder_pixels(scanline->tmp, scanline->uncompressed_data, tmp_size); + predictor(scanline->tmp, tmp_size); + scanline->actual_size = rle_compress(scanline->compressed_data, + max_compressed_size, + scanline->tmp, tmp_size); + + if (scanline->actual_size <= 0 || scanline->actual_size >= tmp_size) { + FFSWAP(uint8_t *, scanline->uncompressed_data, scanline->compressed_data); + FFSWAP(int, scanline->uncompressed_size, scanline->compressed_size); + scanline->actual_size = tmp_size; + } + } + + return 0; +} + +static int encode_scanline_zip(EXRContext *s, const AVFrame *frame) +{ + const int64_t element_size = s->pixel_type == EXR_HALF ? 2LL : 4LL; + + for (int y = 0; y < s->nb_scanlines; y++) { + EXRScanlineData *scanline = &s->scanline[y]; + const int scanline_height = FFMIN(s->scanline_height, frame->height - y * s->scanline_height); + int64_t tmp_size = element_size * s->planes * frame->width * scanline_height; + int64_t max_compressed_size = tmp_size * 3 / 2; + unsigned long actual_size, source_size; + + av_fast_padded_malloc(&scanline->uncompressed_data, &scanline->uncompressed_size, tmp_size); + if (!scanline->uncompressed_data) + return AVERROR(ENOMEM); + + av_fast_padded_malloc(&scanline->tmp, &scanline->tmp_size, tmp_size); + if (!scanline->tmp) + return AVERROR(ENOMEM); + + av_fast_padded_malloc(&scanline->compressed_data, &scanline->compressed_size, max_compressed_size); + if (!scanline->compressed_data) + return AVERROR(ENOMEM); + + switch (s->pixel_type) { + case EXR_FLOAT: + for (int l = 0; l < scanline_height; l++) { + const int scanline_size = frame->width * 4 * s->planes; + + for (int p = 0; p < s->planes; p++) { + int ch = s->ch_order[p]; + + memcpy(scanline->uncompressed_data + scanline_size * l + p * frame->width * 4, + frame->data[ch] + (y * s->scanline_height + l) * frame->linesize[ch], + frame->width * 4); + } + } + break; + case EXR_HALF: + for (int l = 0; l < scanline_height; l++) { + const int scanline_size = frame->width * 2 * s->planes; + + for (int p = 0; p < s->planes; p++) { + int ch = s->ch_order[p]; + uint16_t *dst = (uint16_t *)(scanline->uncompressed_data + scanline_size * l + p * frame->width * 2); + uint32_t *src = (uint32_t *)(frame->data[ch] + (y * s->scanline_height + l) * frame->linesize[ch]); + + for (int x = 0; x < frame->width; x++) + dst[x] = float2half(src[x], s->basetable, s->shifttable); + } + } + break; + } + + reorder_pixels(scanline->tmp, scanline->uncompressed_data, tmp_size); + predictor(scanline->tmp, tmp_size); + source_size = tmp_size; + actual_size = max_compressed_size; + compress(scanline->compressed_data, &actual_size, + scanline->tmp, source_size); + + scanline->actual_size = actual_size; + if (scanline->actual_size >= tmp_size) { + FFSWAP(uint8_t *, scanline->uncompressed_data, scanline->compressed_data); + FFSWAP(int, scanline->uncompressed_size, scanline->compressed_size); + scanline->actual_size = tmp_size; + } + } + + return 0; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + EXRContext *s = avctx->priv_data; + PutByteContext *pb = &s->pb; + int64_t offset; + int ret; + int64_t out_size = 2048LL + avctx->height * 16LL + + av_image_get_buffer_size(avctx->pix_fmt, + avctx->width, + avctx->height, 64) * 3LL / 2; + + if ((ret = ff_alloc_packet2(avctx, pkt, out_size, out_size)) < 0) + return ret; + + bytestream2_init_writer(pb, pkt->data, pkt->size); + + bytestream2_put_le32(pb, 20000630); + bytestream2_put_byte(pb, 2); + bytestream2_put_le24(pb, 0); + bytestream2_put_buffer(pb, "channels\0chlist\0", 16); + bytestream2_put_le32(pb, s->planes * 18 + 1); + + for (int p = 0; p < s->planes; p++) { + bytestream2_put_byte(pb, s->ch_names[p]); + bytestream2_put_byte(pb, 0); + bytestream2_put_le32(pb, s->pixel_type); + bytestream2_put_le32(pb, 0); + bytestream2_put_le32(pb, 1); + bytestream2_put_le32(pb, 1); + } + bytestream2_put_byte(pb, 0); + + bytestream2_put_buffer(pb, "compression\0compression\0", 24); + bytestream2_put_le32(pb, 1); + bytestream2_put_byte(pb, s->compression); + + bytestream2_put_buffer(pb, "dataWindow\0box2i\0", 17); + bytestream2_put_le32(pb, 16); + bytestream2_put_le32(pb, 0); + bytestream2_put_le32(pb, 0); + bytestream2_put_le32(pb, avctx->width - 1); + bytestream2_put_le32(pb, avctx->height - 1); + + bytestream2_put_buffer(pb, "displayWindow\0box2i\0", 20); + bytestream2_put_le32(pb, 16); + bytestream2_put_le32(pb, 0); + bytestream2_put_le32(pb, 0); + bytestream2_put_le32(pb, avctx->width - 1); + bytestream2_put_le32(pb, avctx->height - 1); + + bytestream2_put_buffer(pb, "lineOrder\0lineOrder\0", 20); + bytestream2_put_le32(pb, 1); + bytestream2_put_byte(pb, 0); + + bytestream2_put_buffer(pb, "screenWindowCenter\0v2f\0", 23); + bytestream2_put_le32(pb, 8); + bytestream2_put_le64(pb, 0); + + bytestream2_put_buffer(pb, "screenWindowWidth\0float\0", 24); + bytestream2_put_le32(pb, 4); + bytestream2_put_le32(pb, av_float2int(1.f)); + + if (avctx->sample_aspect_ratio.num && avctx->sample_aspect_ratio.den) { + bytestream2_put_buffer(pb, "pixelAspectRatio\0float\0", 23); + bytestream2_put_le32(pb, 4); + bytestream2_put_le32(pb, av_float2int(av_q2d(avctx->sample_aspect_ratio))); + } + + if (avctx->framerate.num && avctx->framerate.den) { + bytestream2_put_buffer(pb, "framesPerSecond\0rational\0", 25); + bytestream2_put_le32(pb, 8); + bytestream2_put_le32(pb, avctx->framerate.num); + bytestream2_put_le32(pb, avctx->framerate.den); + } + + bytestream2_put_buffer(pb, "gamma\0float\0", 12); + bytestream2_put_le32(pb, 4); + bytestream2_put_le32(pb, av_float2int(s->gamma)); + + bytestream2_put_buffer(pb, "writer\0string\0", 14); + bytestream2_put_le32(pb, 4); + bytestream2_put_buffer(pb, "lavc", 4); + bytestream2_put_byte(pb, 0); + + switch (s->compression) { + case EXR_RAW: + /* nothing to do */ + break; + case EXR_RLE: + encode_scanline_rle(s, frame); + break; + case EXR_ZIP16: + case EXR_ZIP1: + encode_scanline_zip(s, frame); + break; + default: + av_assert0(0); + } + + switch (s->compression) { + case EXR_RAW: + offset = bytestream2_tell_p(pb) + avctx->height * 8LL; + + if (s->pixel_type == EXR_FLOAT) { + + for (int y = 0; y < avctx->height; y++) { + bytestream2_put_le64(pb, offset); + offset += avctx->width * s->planes * 4 + 8; + } + + for (int y = 0; y < avctx->height; y++) { + bytestream2_put_le32(pb, y); + bytestream2_put_le32(pb, s->planes * avctx->width * 4); + for (int p = 0; p < s->planes; p++) { + int ch = s->ch_order[p]; + bytestream2_put_buffer(pb, frame->data[ch] + y * frame->linesize[ch], + avctx->width * 4); + } + } + } else { + for (int y = 0; y < avctx->height; y++) { + bytestream2_put_le64(pb, offset); + offset += avctx->width * s->planes * 2 + 8; + } + + for (int y = 0; y < avctx->height; y++) { + bytestream2_put_le32(pb, y); + bytestream2_put_le32(pb, s->planes * avctx->width * 2); + for (int p = 0; p < s->planes; p++) { + int ch = s->ch_order[p]; + uint32_t *src = (uint32_t *)(frame->data[ch] + y * frame->linesize[ch]); + + for (int x = 0; x < frame->width; x++) + bytestream2_put_le16(pb, float2half(src[x], s->basetable, s->shifttable)); + } + } + } + break; + case EXR_ZIP16: + case EXR_ZIP1: + case EXR_RLE: + offset = bytestream2_tell_p(pb) + s->nb_scanlines * 8LL; + + for (int y = 0; y < s->nb_scanlines; y++) { + EXRScanlineData *scanline = &s->scanline[y]; + + bytestream2_put_le64(pb, offset); + offset += scanline->actual_size + 8; + } + + for (int y = 0; y < s->nb_scanlines; y++) { + EXRScanlineData *scanline = &s->scanline[y]; + + bytestream2_put_le32(pb, y * s->scanline_height); + bytestream2_put_le32(pb, scanline->actual_size); + bytestream2_put_buffer(pb, scanline->compressed_data, + scanline->actual_size); + } + break; + default: + av_assert0(0); + } + + av_shrink_packet(pkt, bytestream2_tell_p(pb)); + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +#define OFFSET(x) offsetof(EXRContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "compression", "set compression type", OFFSET(compression), AV_OPT_TYPE_INT, {.i64=0}, 0, EXR_NBCOMPR-1, VE, "compr" }, + { "none", "none", 0, AV_OPT_TYPE_CONST, {.i64=EXR_RAW}, 0, 0, VE, "compr" }, + { "rle" , "RLE", 0, AV_OPT_TYPE_CONST, {.i64=EXR_RLE}, 0, 0, VE, "compr" }, + { "zip1", "ZIP1", 0, AV_OPT_TYPE_CONST, {.i64=EXR_ZIP1}, 0, 0, VE, "compr" }, + { "zip16", "ZIP16", 0, AV_OPT_TYPE_CONST, {.i64=EXR_ZIP16}, 0, 0, VE, "compr" }, + { "format", "set pixel type", OFFSET(pixel_type), AV_OPT_TYPE_INT, {.i64=EXR_FLOAT}, EXR_HALF, EXR_UNKNOWN-1, VE, "pixel" }, + { "half" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=EXR_HALF}, 0, 0, VE, "pixel" }, + { "float", NULL, 0, AV_OPT_TYPE_CONST, {.i64=EXR_FLOAT}, 0, 0, VE, "pixel" }, + { "gamma", "set gamma", OFFSET(gamma), AV_OPT_TYPE_FLOAT, {.dbl=1.f}, 0.001, FLT_MAX, VE }, + { NULL}, +}; + +static const AVClass exr_class = { + .class_name = "exr", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_exr_encoder = { + .name = "exr", + .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), + .priv_data_size = sizeof(EXRContext), + .priv_class = &exr_class, + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_EXR, + .init = encode_init, + .encode2 = encode_frame, + .close = encode_close, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_GBRPF32, + AV_PIX_FMT_GBRAPF32, + AV_PIX_FMT_NONE }, +}; diff -Nru ffmpeg-4.2.2/libavcodec/extract_extradata_bsf.c ffmpeg-4.4/libavcodec/extract_extradata_bsf.c --- ffmpeg-4.2.2/libavcodec/extract_extradata_bsf.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/extract_extradata_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,10 +23,11 @@ #include "libavutil/log.h" #include "libavutil/opt.h" -#include "avcodec.h" #include "av1.h" #include "av1_parse.h" #include "bsf.h" +#include "bsf_internal.h" +#include "bytestream.h" #include "h2645_parse.h" #include "h264.h" #include "hevc.h" @@ -38,10 +39,10 @@ int (*extract)(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size); - /* AV1 specifc fields */ + /* AV1 specific fields */ AV1Packet av1_pkt; - /* H264/HEVC specifc fields */ + /* H264/HEVC specific fields */ H2645Packet h2645_pkt; /* AVOptions */ @@ -86,7 +87,8 @@ if (extradata_size && has_seq) { AVBufferRef *filtered_buf = NULL; - uint8_t *extradata, *filtered_data; + PutByteContext pb_filtered_data, pb_extradata; + uint8_t *extradata; if (s->remove) { filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE); @@ -94,8 +96,6 @@ return AVERROR(ENOMEM); } memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); - - filtered_data = filtered_buf->data; } extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); @@ -103,20 +103,21 @@ av_buffer_unref(&filtered_buf); return AVERROR(ENOMEM); } - memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); *data = extradata; *size = extradata_size; + bytestream2_init_writer(&pb_extradata, extradata, extradata_size); + if (s->remove) + bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size); + for (i = 0; i < s->av1_pkt.nb_obus; i++) { AV1OBU *obu = &s->av1_pkt.obus[i]; if (val_in_array(extradata_obu_types, nb_extradata_obu_types, obu->type)) { - memcpy(extradata, obu->raw_data, obu->raw_size); - extradata += obu->raw_size; + bytestream2_put_bufferu(&pb_extradata, obu->raw_data, obu->raw_size); } else if (s->remove) { - memcpy(filtered_data, obu->raw_data, obu->raw_size); - filtered_data += obu->raw_size; + bytestream2_put_bufferu(&pb_filtered_data, obu->raw_data, obu->raw_size); } } @@ -180,7 +181,8 @@ ((ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) || (ctx->par_in->codec_id == AV_CODEC_ID_H264 && has_sps))) { AVBufferRef *filtered_buf = NULL; - uint8_t *extradata, *filtered_data; + PutByteContext pb_filtered_data, pb_extradata; + uint8_t *extradata; if (s->remove) { filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE); @@ -188,8 +190,6 @@ return AVERROR(ENOMEM); } memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); - - filtered_data = filtered_buf->data; } extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); @@ -197,22 +197,23 @@ av_buffer_unref(&filtered_buf); return AVERROR(ENOMEM); } - memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); *data = extradata; *size = extradata_size; + bytestream2_init_writer(&pb_extradata, extradata, extradata_size); + if (s->remove) + bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size); + for (i = 0; i < s->h2645_pkt.nb_nals; i++) { H2645NAL *nal = &s->h2645_pkt.nals[i]; if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { - AV_WB24(extradata, 1); // startcode - memcpy(extradata + 3, nal->raw_data, nal->raw_size); - extradata += 3 + nal->raw_size; + bytestream2_put_be24u(&pb_extradata, 1); //startcode + bytestream2_put_bufferu(&pb_extradata, nal->raw_data, nal->raw_size); } else if (s->remove) { - AV_WB24(filtered_data, 1); // startcode - memcpy(filtered_data + 3, nal->raw_data, nal->raw_size); - filtered_data += 3 + nal->raw_size; + bytestream2_put_be24u(&pb_filtered_data, 1); // startcode + bytestream2_put_bufferu(&pb_filtered_data, nal->raw_data, nal->raw_size); } } @@ -251,7 +252,6 @@ return AVERROR(ENOMEM); memcpy(*data, pkt->data, extradata_size); - memset(*data + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); *size = extradata_size; if (s->remove) { @@ -275,19 +275,16 @@ if (state == 0x1B3) found = 1; else if (found && state != 0x1B5 && state < 0x200 && state >= 0x100) { - if (i > 3) { - *size = i - 3; - *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!*data) - return AVERROR(ENOMEM); + *size = i - 3; + *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!*data) + return AVERROR(ENOMEM); - memcpy(*data, pkt->data, *size); - memset(*data + *size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + memcpy(*data, pkt->data, *size); - if (s->remove) { - pkt->data += *size; - pkt->size -= *size; - } + if (s->remove) { + pkt->data += *size; + pkt->size -= *size; } break; } @@ -312,7 +309,6 @@ return AVERROR(ENOMEM); memcpy(*data, pkt->data, *size); - memset(*data + *size, 0, AV_INPUT_BUFFER_PADDING_SIZE); if (s->remove) { pkt->data += *size; @@ -374,6 +370,7 @@ goto fail; if (extradata) { + memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); ret = av_packet_add_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, extradata, extradata_size); if (ret < 0) { diff -Nru ffmpeg-4.2.2/libavcodec/fastaudio.c ffmpeg-4.4/libavcodec/fastaudio.c --- ffmpeg-4.2.2/libavcodec/fastaudio.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/fastaudio.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,202 @@ +/* + * MOFLEX Fast Audio decoder + * Copyright (c) 2015-2016 Florian Nouwt + * Copyright (c) 2017 Adib Surani + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "mathops.h" + +typedef struct ChannelItems { + float f[8]; + float last; +} ChannelItems; + +typedef struct FastAudioContext { + float table[8][64]; + + ChannelItems *ch; +} FastAudioContext; + +static av_cold int fastaudio_init(AVCodecContext *avctx) +{ + FastAudioContext *s = avctx->priv_data; + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + for (int i = 0; i < 8; i++) + s->table[0][i] = (i - 159.5f) / 160.f; + for (int i = 0; i < 11; i++) + s->table[0][i + 8] = (i - 37.5f) / 40.f; + for (int i = 0; i < 27; i++) + s->table[0][i + 8 + 11] = (i - 13.f) / 20.f; + for (int i = 0; i < 11; i++) + s->table[0][i + 8 + 11 + 27] = (i + 27.5f) / 40.f; + for (int i = 0; i < 7; i++) + s->table[0][i + 8 + 11 + 27 + 11] = (i + 152.5f) / 160.f; + + memcpy(s->table[1], s->table[0], sizeof(s->table[0])); + + for (int i = 0; i < 7; i++) + s->table[2][i] = (i - 33.5f) / 40.f; + for (int i = 0; i < 25; i++) + s->table[2][i + 7] = (i - 13.f) / 20.f; + + for (int i = 0; i < 32; i++) + s->table[3][i] = -s->table[2][31 - i]; + + for (int i = 0; i < 16; i++) + s->table[4][i] = i * 0.22f / 3.f - 0.6f; + + for (int i = 0; i < 16; i++) + s->table[5][i] = i * 0.20f / 3.f - 0.3f; + + for (int i = 0; i < 8; i++) + s->table[6][i] = i * 0.36f / 3.f - 0.4f; + + for (int i = 0; i < 8; i++) + s->table[7][i] = i * 0.34f / 3.f - 0.2f; + + s->ch = av_calloc(avctx->channels, sizeof(*s->ch)); + if (!s->ch) + return AVERROR(ENOMEM); + + return 0; +} + +static int read_bits(int bits, int *ppos, unsigned *src) +{ + int r, pos; + + pos = *ppos; + pos += bits; + r = src[(pos - 1) / 32] >> ((-pos) & 31); + *ppos = pos; + + return r & ((1 << bits) - 1); +} + +static const uint8_t bits[8] = { 6, 6, 5, 5, 4, 0, 3, 3, }; + +static void set_sample(int i, int j, int v, float *result, int *pads, float value) +{ + result[i * 64 + pads[i] + j * 3] = value * (2 * v - 7); +} + +static int fastaudio_decode(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *pkt) +{ + FastAudioContext *s = avctx->priv_data; + GetByteContext gb; + AVFrame *frame = data; + int subframes; + int ret; + + subframes = pkt->size / (40 * avctx->channels); + frame->nb_samples = subframes * 256; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + bytestream2_init(&gb, pkt->data, pkt->size); + + for (int subframe = 0; subframe < subframes; subframe++) { + for (int channel = 0; channel < avctx->channels; channel++) { + ChannelItems *ch = &s->ch[channel]; + float result[256] = { 0 }; + unsigned src[10]; + int inds[4], pads[4]; + float m[8]; + int pos = 0; + + for (int i = 0; i < 10; i++) + src[i] = bytestream2_get_le32(&gb); + + for (int i = 0; i < 8; i++) + m[7 - i] = s->table[i][read_bits(bits[i], &pos, src)]; + + for (int i = 0; i < 4; i++) + inds[3 - i] = read_bits(6, &pos, src); + + for (int i = 0; i < 4; i++) + pads[3 - i] = read_bits(2, &pos, src); + + for (int i = 0, index5 = 0; i < 4; i++) { + float value = av_int2float((inds[i] + 1) << 20) * powf(2.f, 116.f); + + for (int j = 0, tmp = 0; j < 21; j++) { + set_sample(i, j, j == 20 ? tmp / 2 : read_bits(3, &pos, src), result, pads, value); + if (j % 10 == 9) + tmp = 4 * tmp + read_bits(2, &pos, src); + if (j == 20) + index5 = FFMIN(2 * index5 + tmp % 2, 63); + } + + m[2] = s->table[5][index5]; + } + + for (int i = 0; i < 256; i++) { + float x = result[i]; + + for (int j = 0; j < 8; j++) { + x -= m[j] * ch->f[j]; + ch->f[j] += m[j] * x; + } + + memmove(&ch->f[0], &ch->f[1], sizeof(float) * 7); + ch->f[7] = x; + ch->last = x + ch->last * 0.86f; + result[i] = ch->last * 2.f; + } + + memcpy(frame->extended_data[channel] + 1024 * subframe, result, 256 * sizeof(float)); + } + } + + *got_frame = 1; + + return pkt->size; +} + +static av_cold int fastaudio_close(AVCodecContext *avctx) +{ + FastAudioContext *s = avctx->priv_data; + + av_freep(&s->ch); + + return 0; +} + +AVCodec ff_fastaudio_decoder = { + .name = "fastaudio", + .long_name = NULL_IF_CONFIG_SMALL("MobiClip FastAudio"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_FASTAUDIO, + .priv_data_size = sizeof(FastAudioContext), + .init = fastaudio_init, + .decode = fastaudio_decode, + .close = fastaudio_close, + .capabilities = AV_CODEC_CAP_DR1, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; diff -Nru ffmpeg-4.2.2/libavcodec/faxcompr.c ffmpeg-4.4/libavcodec/faxcompr.c --- ffmpeg-4.2.2/libavcodec/faxcompr.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/faxcompr.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,7 @@ * CCITT Fax Group 3 and 4 decompression * @author Konstantin Shishkov */ +#include "libavutil/thread.h" #include "avcodec.h" #include "get_bits.h" #include "put_bits.h" @@ -96,15 +97,12 @@ static VLC ccitt_vlc[2], ccitt_group3_2d_vlc; -av_cold void ff_ccitt_unpack_init(void) +static av_cold void ccitt_unpack_init(void) { static VLC_TYPE code_table1[528][2]; static VLC_TYPE code_table2[648][2]; int i; - static int initialized = 0; - if (initialized) - return; ccitt_vlc[0].table = code_table1; ccitt_vlc[0].table_allocated = 528; ccitt_vlc[1].table = code_table2; @@ -119,7 +117,12 @@ INIT_VLC_STATIC(&ccitt_group3_2d_vlc, 9, 11, ccitt_group3_2d_lens, 1, 1, ccitt_group3_2d_bits, 1, 1, 512); - initialized = 1; +} + +av_cold void ff_ccitt_unpack_init(void) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, ccitt_unpack_init); } static int decode_uncompressed(AVCodecContext *avctx, GetBitContext *gb, diff -Nru ffmpeg-4.2.2/libavcodec/fft_fixed.c ffmpeg-4.4/libavcodec/fft_fixed.c --- ffmpeg-4.2.2/libavcodec/fft_fixed.c 2016-03-29 02:25:13.000000000 +0000 +++ ffmpeg-4.4/libavcodec/fft_fixed.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +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 - */ - -#define FFT_FLOAT 0 -#define FFT_FIXED_32 0 -#include "fft_template.c" diff -Nru ffmpeg-4.2.2/libavcodec/fft.h ffmpeg-4.4/libavcodec/fft.h --- ffmpeg-4.2.2/libavcodec/fft.h 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/fft.h 2021-04-08 21:28:39.000000000 +0000 @@ -32,7 +32,8 @@ #include #include "config.h" -#include "libavutil/mem.h" + +#include "libavutil/mem_internal.h" #if FFT_FLOAT @@ -51,12 +52,6 @@ typedef int32_t FFTSample; -#else /* FFT_FIXED_32 */ - -#define FFT_NAME(x) x ## _fixed - -typedef int16_t FFTSample; - #endif /* FFT_FIXED_32 */ typedef struct FFTComplex { @@ -107,7 +102,6 @@ void (*imdct_calc)(struct FFTContext *s, FFTSample *output, const FFTSample *input); void (*imdct_half)(struct FFTContext *s, FFTSample *output, const FFTSample *input); void (*mdct_calc)(struct FFTContext *s, FFTSample *output, const FFTSample *input); - void (*mdct_calcw)(struct FFTContext *s, FFTDouble *output, const FFTSample *input); enum fft_permutation_type fft_permutation; enum mdct_permutation_type mdct_permutation; uint32_t *revtab32; @@ -115,8 +109,16 @@ #if CONFIG_HARDCODED_TABLES #define COSTABLE_CONST const +#define ff_init_ff_cos_tabs(index) #else #define COSTABLE_CONST +#define ff_init_ff_cos_tabs FFT_NAME(ff_init_ff_cos_tabs) + +/** + * Initialize the cosine table in ff_cos_tabs[index] + * @param index index in ff_cos_tabs array of the table to initialize + */ +void ff_init_ff_cos_tabs(int index); #endif #define COSTABLE(size) \ @@ -138,14 +140,6 @@ extern COSTABLE(131072); extern COSTABLE_CONST FFTSample* const FFT_NAME(ff_cos_tabs)[18]; -#define ff_init_ff_cos_tabs FFT_NAME(ff_init_ff_cos_tabs) - -/** - * Initialize the cosine table in ff_cos_tabs[index] - * @param index index in ff_cos_tabs array of the table to initialize - */ -void ff_init_ff_cos_tabs(int index); - #define ff_fft_init FFT_NAME(ff_fft_init) #define ff_fft_end FFT_NAME(ff_fft_end) @@ -162,8 +156,6 @@ void ff_fft_init_mips(FFTContext *s); void ff_fft_init_ppc(FFTContext *s); -void ff_fft_fixed_init_arm(FFTContext *s); - void ff_fft_end(FFTContext *s); #define ff_mdct_init FFT_NAME(ff_mdct_init) diff -Nru ffmpeg-4.2.2/libavcodec/fft_init_table.c ffmpeg-4.4/libavcodec/fft_init_table.c --- ffmpeg-4.2.2/libavcodec/fft_init_table.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/fft_init_table.c 2021-04-08 21:28:27.000000000 +0000 @@ -51,6 +51,8 @@ * @file * definitions and initialization of LUT table for FFT */ +#include "libavutil/thread.h" + #include "libavcodec/fft_table.h" const int32_t ff_w_tab_sr[MAX_FFT_SIZE/(4*16)] = { @@ -314,15 +316,29 @@ uint16_t ff_fft_offsets_lut[21845]; -void ff_fft_lut_init(uint16_t *table, int off, int size, int *index) +static void fft_lut_init(uint16_t *table, int off, int size, int *index) { if (size < 16) { table[*index] = off >> 2; (*index)++; } else { - ff_fft_lut_init(table, off, size>>1, index); - ff_fft_lut_init(table, off+(size>>1), size>>2, index); - ff_fft_lut_init(table, off+3*(size>>2), size>>2, index); + fft_lut_init(table, off, size >> 1, index); + fft_lut_init(table, off + (size >> 1), size >> 2, index); + fft_lut_init(table, off + 3 * (size >> 2), size >> 2, index); } } + +static void fft_lut_init_start(void) +{ + int n = 0; + + fft_lut_init(ff_fft_offsets_lut, 0, 1 << 17, &n); +} + +void ff_fft_lut_init(void) +{ + static AVOnce init_once = AV_ONCE_INIT; + + ff_thread_once(&init_once, fft_lut_init_start); +} diff -Nru ffmpeg-4.2.2/libavcodec/fft-internal.h ffmpeg-4.4/libavcodec/fft-internal.h --- ffmpeg-4.2.2/libavcodec/fft-internal.h 2016-03-29 02:25:13.000000000 +0000 +++ ffmpeg-4.4/libavcodec/fft-internal.h 2021-04-08 21:28:39.000000000 +0000 @@ -34,7 +34,7 @@ (dim) = (are) * (bim) + (aim) * (bre); \ } while (0) -#else +#else /* FFT_FLOAT */ #define SCALE_FLOAT(a, bits) lrint((a) * (double)(1 << (bits))) @@ -52,33 +52,6 @@ #define FIX15(a) av_clip(SCALE_FLOAT(a, 31), -2147483647, 2147483647) -#else /* FFT_FIXED_32 */ - -#include "fft.h" -#include "mathops.h" - -void ff_mdct_calcw_c(FFTContext *s, FFTDouble *output, const FFTSample *input); - -#define FIX15(a) av_clip(SCALE_FLOAT(a, 15), -32767, 32767) - -#define sqrthalf ((int16_t)((1<<15)*M_SQRT1_2)) - -#define BF(x, y, a, b) do { \ - x = (a - b) >> 1; \ - y = (a + b) >> 1; \ - } while (0) - -#define CMULS(dre, dim, are, aim, bre, bim, sh) do { \ - (dre) = (MUL16(are, bre) - MUL16(aim, bim)) >> sh; \ - (dim) = (MUL16(are, bim) + MUL16(aim, bre)) >> sh; \ - } while (0) - -#define CMUL(dre, dim, are, aim, bre, bim) \ - CMULS(dre, dim, are, aim, bre, bim, 15) - -#define CMULL(dre, dim, are, aim, bre, bim) \ - CMULS(dre, dim, are, aim, bre, bim, 0) - #endif /* FFT_FIXED_32 */ #endif /* FFT_FLOAT */ diff -Nru ffmpeg-4.2.2/libavcodec/fft_table.h ffmpeg-4.4/libavcodec/fft_table.h --- ffmpeg-4.2.2/libavcodec/fft_table.h 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/fft_table.h 2021-04-08 21:28:27.000000000 +0000 @@ -61,6 +61,6 @@ extern const int32_t ff_w_tab_sr[]; extern uint16_t ff_fft_offsets_lut[]; -void ff_fft_lut_init(uint16_t *table, int off, int size, int *index); +void ff_fft_lut_init(void); #endif /* AVCODEC_FFT_TABLE_H */ diff -Nru ffmpeg-4.2.2/libavcodec/fft_template.c ffmpeg-4.4/libavcodec/fft_template.c --- ffmpeg-4.2.2/libavcodec/fft_template.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/fft_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -35,13 +35,6 @@ #if FFT_FIXED_32 #include "fft_table.h" - -static void av_cold fft_lut_init(void) -{ - int n = 0; - ff_fft_lut_init(ff_fft_offsets_lut, 0, 1 << 17, &n); -} - #else /* FFT_FIXED_32 */ /* cos(2*pi*x/n) for 0<=x<=n/4, followed by its reverse */ @@ -120,6 +113,10 @@ { init_ff_cos_tabs_131072, AV_ONCE_INIT }, }; +av_cold void ff_init_ff_cos_tabs(int index) +{ + ff_thread_once(&cos_tabs_init_once[index].control, cos_tabs_init_once[index].func); +} #endif COSTABLE_CONST FFTSample * const FFT_NAME(ff_cos_tabs)[] = { NULL, NULL, NULL, NULL, @@ -155,12 +152,6 @@ else return split_radix_permutation(i, m, inverse)*4 - 1; } -av_cold void ff_init_ff_cos_tabs(int index) -{ -#if (!CONFIG_HARDCODED_TABLES) && (!FFT_FIXED_32) - ff_thread_once(&cos_tabs_init_once[index].control, cos_tabs_init_once[index].func); -#endif -} static const int avx_tab[] = { 0, 4, 1, 5, 8, 12, 9, 13, 2, 6, 3, 7, 10, 14, 11, 15 @@ -236,21 +227,14 @@ #endif #if FFT_FIXED_32 - { - static AVOnce control = AV_ONCE_INIT; - ff_thread_once(&control, fft_lut_init); - } + ff_fft_lut_init(); #else /* FFT_FIXED_32 */ #if FFT_FLOAT if (ARCH_AARCH64) ff_fft_init_aarch64(s); if (ARCH_ARM) ff_fft_init_arm(s); if (ARCH_PPC) ff_fft_init_ppc(s); if (ARCH_X86) ff_fft_init_x86(s); - if (CONFIG_MDCT) s->mdct_calcw = s->mdct_calc; if (HAVE_MIPSFPU) ff_fft_init_mips(s); -#else - if (CONFIG_MDCT) s->mdct_calcw = ff_mdct_calcw_c; - if (ARCH_ARM) ff_fft_fixed_init_arm(s); #endif for(j=4; j<=nbits; j++) { ff_init_ff_cos_tabs(j); @@ -258,7 +242,7 @@ #endif /* FFT_FIXED_32 */ - if (s->fft_permutation == FF_FFT_PERM_AVX) { + if (ARCH_X86 && FFT_FLOAT && s->fft_permutation == FF_FFT_PERM_AVX) { fft_perm_avx(s); } else { #define PROCESS_FFT_PERM_SWAP_LSBS(num) do {\ diff -Nru ffmpeg-4.2.2/libavcodec/ffv1.c ffmpeg-4.4/libavcodec/ffv1.c --- ffmpeg-4.2.2/libavcodec/ffv1.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ffv1.c 2021-04-08 21:28:39.000000000 +0000 @@ -31,7 +31,6 @@ #include "libavutil/opt.h" #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" -#include "libavutil/timer.h" #include "avcodec.h" #include "internal.h" @@ -116,12 +115,11 @@ av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f) { - int i; + int i, max_slice_count = f->num_h_slices * f->num_v_slices; - f->max_slice_count = f->num_h_slices * f->num_v_slices; - av_assert0(f->max_slice_count > 0); + av_assert0(max_slice_count > 0); - for (i = 0; i < f->max_slice_count; i++) { + for (i = 0; i < max_slice_count;) { int sx = i % f->num_h_slices; int sy = i / f->num_h_slices; int sxs = f->avctx->width * sx / f->num_h_slices; @@ -133,7 +131,7 @@ if (!fs) goto memfail; - f->slice_context[i] = fs; + f->slice_context[i++] = fs; memcpy(fs, f, sizeof(*fs)); memset(fs->rc_stat2, 0, sizeof(fs->rc_stat2)); @@ -146,21 +144,14 @@ sizeof(*fs->sample_buffer)); fs->sample_buffer32 = av_malloc_array((fs->width + 6), 3 * MAX_PLANES * sizeof(*fs->sample_buffer32)); - if (!fs->sample_buffer || !fs->sample_buffer32) { - av_freep(&fs->sample_buffer); - av_freep(&fs->sample_buffer32); - av_freep(&f->slice_context[i]); + if (!fs->sample_buffer || !fs->sample_buffer32) goto memfail; - } } + f->max_slice_count = max_slice_count; return 0; memfail: - while(--i >= 0) { - av_freep(&f->slice_context[i]->sample_buffer); - av_freep(&f->slice_context[i]->sample_buffer32); - av_freep(&f->slice_context[i]); - } + f->max_slice_count = i; return AVERROR(ENOMEM); } diff -Nru ffmpeg-4.2.2/libavcodec/ffv1dec.c ffmpeg-4.4/libavcodec/ffv1dec.c --- ffmpeg-4.2.2/libavcodec/ffv1dec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ffv1dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,7 +30,6 @@ #include "libavutil/opt.h" #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" -#include "libavutil/timer.h" #include "avcodec.h" #include "internal.h" #include "get_bits.h" @@ -138,7 +137,6 @@ sample[1][-1] = sample[0][0]; sample[0][w] = sample[0][w - 1]; -// { START_TIMER if (s->avctx->bits_per_raw_sample <= 8) { int ret = decode_line(s, w, sample, plane_index, 8); if (ret < 0) @@ -159,7 +157,6 @@ } } } -// STOP_TIMER("decode-line") } } return 0; } @@ -789,7 +786,7 @@ if (f->version == 2) { int idx = get_symbol(c, state, 0); - if (idx > (unsigned)f->quant_table_count) { + if (idx >= (unsigned)f->quant_table_count) { av_log(f->avctx, AV_LOG_ERROR, "quant_table_index out of range\n"); return AVERROR_INVALIDDATA; @@ -829,8 +826,6 @@ if ((ret = ff_ffv1_init_slice_contexts(f)) < 0) return ret; - avctx->internal->allocate_progress = 1; - return 0; } @@ -893,8 +888,10 @@ int trailer = 3 + 5*!!f->ec; int v; - if (i || f->version > 2) v = AV_RB24(buf_p-trailer) + trailer; - else v = buf_p - c->bytestream_start; + if (i || f->version > 2) { + if (trailer > buf_p - buf) v = INT_MAX; + else v = AV_RB24(buf_p-trailer) + trailer; + } else v = buf_p - c->bytestream_start; if (buf_p - c->bytestream_start < v) { av_log(avctx, AV_LOG_ERROR, "Slice pointer chain broken\n"); ff_thread_report_progress(&f->picture, INT_MAX, 0); @@ -982,34 +979,6 @@ return buf_size; } -#if HAVE_THREADS -static int init_thread_copy(AVCodecContext *avctx) -{ - FFV1Context *f = avctx->priv_data; - int i, ret; - - f->picture.f = NULL; - f->last_picture.f = NULL; - f->sample_buffer = NULL; - f->max_slice_count = 0; - f->slice_count = 0; - - for (i = 0; i < f->quant_table_count; i++) { - av_assert0(f->version > 1); - f->initial_states[i] = av_memdup(f->initial_states[i], - f->context_count[i] * sizeof(*f->initial_states[i])); - } - - f->picture.f = av_frame_alloc(); - f->last_picture.f = av_frame_alloc(); - - if ((ret = ff_ffv1_init_slice_contexts(f)) < 0) - return ret; - - return 0; -} -#endif - static void copy_fields(FFV1Context *fsdst, FFV1Context *fssrc, FFV1Context *fsrc) { fsdst->version = fsrc->version; @@ -1093,9 +1062,8 @@ .init = decode_init, .close = ff_ffv1_close, .decode = decode_frame, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), .capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/ | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_ALLOCATE_PROGRESS, }; diff -Nru ffmpeg-4.2.2/libavcodec/ffv1enc.c ffmpeg-4.4/libavcodec/ffv1enc.c --- ffmpeg-4.2.2/libavcodec/ffv1enc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ffv1enc.c 2021-04-08 21:28:27.000000000 +0000 @@ -31,7 +31,6 @@ #include "libavutil/opt.h" #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" -#include "libavutil/timer.h" #include "avcodec.h" #include "internal.h" @@ -287,7 +286,6 @@ sample[0][-1]= sample[1][0 ]; sample[1][ w]= sample[1][w-1]; -// { START_TIMER if (s->bits_per_raw_sample <= 8) { for (x = 0; x < w; x++) sample[0][x] = src[x * pixel_stride + stride * y]; @@ -306,7 +304,6 @@ if((ret = encode_line(s, w, sample, plane_index, s->bits_per_raw_sample)) < 0) return ret; } -// STOP_TIMER("encode line") } } return 0; } @@ -334,6 +331,18 @@ write_quant_table(c, quant_table[i]); } +static int contains_non_128(uint8_t (*initial_state)[CONTEXT_SIZE], + int nb_contexts) +{ + if (!initial_state) + return 0; + for (int i = 0; i < nb_contexts; i++) + for (int j = 0; j < CONTEXT_SIZE; j++) + if (initial_state[i][j] != 128) + return 1; + return 0; +} + static void write_header(FFV1Context *f) { uint8_t state[CONTEXT_SIZE]; @@ -428,10 +437,7 @@ write_quant_tables(c, f->quant_tables[i]); for (i = 0; i < f->quant_table_count; i++) { - for (j = 0; j < f->context_count[i] * CONTEXT_SIZE; j++) - if (f->initial_states[i] && f->initial_states[i][0][j] != 128) - break; - if (j < f->context_count[i] * CONTEXT_SIZE) { + if (contains_non_128(f->initial_states[i], f->context_count[i])) { put_rac(c, state, 1); for (j = 0; j < f->context_count[i]; j++) for (k = 0; k < CONTEXT_SIZE; k++) { @@ -1348,4 +1354,5 @@ .defaults = ffv1_defaults, #endif .priv_class = &ffv1_class, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/ffv1.h ffmpeg-4.4/libavcodec/ffv1.h --- ffmpeg-4.2.2/libavcodec/ffv1.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ffv1.h 2020-07-11 10:39:30.000000000 +0000 @@ -33,7 +33,6 @@ #include "libavutil/opt.h" #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" -#include "libavutil/timer.h" #include "avcodec.h" #include "get_bits.h" #include "internal.h" diff -Nru ffmpeg-4.2.2/libavcodec/ffv1_template.c ffmpeg-4.4/libavcodec/ffv1_template.c --- ffmpeg-4.2.2/libavcodec/ffv1_template.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ffv1_template.c 2020-07-11 10:39:30.000000000 +0000 @@ -37,7 +37,7 @@ const int RT = last[1]; const int L = src[-1]; - if (p->quant_table[3][127]) { + if (p->quant_table[3][127] || p->quant_table[4][127]) { const int TT = last2[0]; const int LL = src[-2]; return p->quant_table[0][(L - LT) & 0xFF] + diff -Nru ffmpeg-4.2.2/libavcodec/ffwavesynth.c ffmpeg-4.4/libavcodec/ffwavesynth.c --- ffmpeg-4.2.2/libavcodec/ffwavesynth.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ffwavesynth.c 2021-04-08 21:28:39.000000000 +0000 @@ -188,7 +188,7 @@ static uint64_t phi_at(struct ws_interval *in, int64_t ts) { - uint64_t dt = ts - in->ts_start; + uint64_t dt = ts - (uint64_t)in->ts_start; uint64_t dt2 = dt & 1 ? /* dt * (dt - 1) / 2 without overflow */ dt * ((dt - 1) >> 1) : (dt >> 1) * (dt - 1); return in->phi0 + dt * in->dphi0 + dt2 * in->ddphi; @@ -217,7 +217,7 @@ *last = -1; lcg_seek(&ws->dither_state, (uint32_t)ts - (uint32_t)ws->cur_ts); if (ws->pink_need) { - uint64_t pink_ts_cur = (ws->cur_ts + PINK_UNIT - 1) & ~(PINK_UNIT - 1); + uint64_t pink_ts_cur = (ws->cur_ts + (uint64_t)PINK_UNIT - 1) & ~(PINK_UNIT - 1); uint64_t pink_ts_next = ts & ~(PINK_UNIT - 1); int pos = ts & (PINK_UNIT - 1); lcg_seek(&ws->pink_state, (uint32_t)(pink_ts_next - pink_ts_cur) * 2); @@ -281,7 +281,7 @@ dphi1 = frac64(f1, (int64_t)avc->sample_rate << 16); dphi2 = frac64(f2, (int64_t)avc->sample_rate << 16); in->dphi0 = dphi1; - in->ddphi = (dphi2 - dphi1) / dt; + in->ddphi = (int64_t)(dphi2 - (uint64_t)dphi1) / dt; if (phi & 0x80000000) { phi &= ~0x80000000; if (phi >= i) @@ -323,13 +323,11 @@ r = wavesynth_parse_extradata(avc); if (r < 0) { av_log(avc, AV_LOG_ERROR, "Invalid intervals definitions.\n"); - goto fail; + return r; } ws->sin = av_malloc(sizeof(*ws->sin) << SIN_BITS); - if (!ws->sin) { - r = AVERROR(ENOMEM); - goto fail; - } + if (!ws->sin) + return AVERROR(ENOMEM); for (i = 0; i < 1 << SIN_BITS; i++) ws->sin[i] = floor(32767 * sin(2 * M_PI * i / (1 << SIN_BITS))); ws->dither_state = MKTAG('D','I','T','H'); @@ -340,11 +338,6 @@ wavesynth_seek(ws, 0); avc->sample_fmt = AV_SAMPLE_FMT_S16; return 0; - -fail: - av_freep(&ws->inter); - av_freep(&ws->sin); - return r; } static void wavesynth_synth_sample(struct wavesynth_context *ws, int64_t ts, @@ -373,7 +366,7 @@ in->amp += in->damp; switch (in->type) { case WS_SINE: - val = amp * ws->sin[in->phi >> (64 - SIN_BITS)]; + val = amp * (unsigned)ws->sin[in->phi >> (64 - SIN_BITS)]; in->phi += in->dphi; in->dphi += in->ddphi; break; @@ -444,7 +437,7 @@ if (r < 0) return r; pcm = (int16_t *)frame->data[0]; - for (s = 0; s < duration; s++, ts++) { + for (s = 0; s < duration; s++, ts+=(uint64_t)1) { memset(channels, 0, avc->channels * sizeof(*channels)); if (ts >= ws->next_ts) wavesynth_enter_intervals(ws, ts); @@ -452,7 +445,7 @@ for (c = 0; c < avc->channels; c++) *(pcm++) = channels[c] >> 16; } - ws->cur_ts += duration; + ws->cur_ts += (uint64_t)duration; *rgot_frame = 1; return packet->size; } @@ -476,4 +469,5 @@ .close = wavesynth_close, .decode = wavesynth_decode, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/fic.c ffmpeg-4.4/libavcodec/fic.c --- ffmpeg-4.2.2/libavcodec/fic.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/fic.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ */ #include "libavutil/common.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "avcodec.h" #include "internal.h" @@ -278,7 +279,7 @@ int skip_cursor = ctx->skip_cursor; uint8_t *sdata; - if ((ret = ff_reget_buffer(avctx, ctx->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, ctx->frame, 0)) < 0) return ret; /* Header + at least one slice (4) */ @@ -421,7 +422,7 @@ } /* Make sure we use a user-supplied buffer. */ - if ((ret = ff_reget_buffer(avctx, ctx->final_frame)) < 0) { + if ((ret = ff_reget_buffer(avctx, ctx->final_frame, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "Could not make frame writable.\n"); return ret; } diff -Nru ffmpeg-4.2.2/libavcodec/filter_units_bsf.c ffmpeg-4.4/libavcodec/filter_units_bsf.c --- ffmpeg-4.2.2/libavcodec/filter_units_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/filter_units_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "libavutil/opt.h" #include "bsf.h" +#include "bsf_internal.h" #include "cbs.h" @@ -124,7 +125,7 @@ } if (ctx->mode == REMOVE ? j < ctx->nb_types : j >= ctx->nb_types) - ff_cbs_delete_unit(ctx->cbc, frag, i); + ff_cbs_delete_unit(frag, i); } if (frag->nb_units == 0) { @@ -142,7 +143,7 @@ fail: if (err < 0) av_packet_unref(pkt); - ff_cbs_fragment_reset(ctx->cbc, frag); + ff_cbs_fragment_reset(frag); return err; } @@ -198,7 +199,7 @@ av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); } - ff_cbs_fragment_reset(ctx->cbc, frag); + ff_cbs_fragment_reset(frag); } return err; @@ -210,7 +211,7 @@ av_freep(&ctx->type_list); - ff_cbs_fragment_free(ctx->cbc, &ctx->fragment); + ff_cbs_fragment_free(&ctx->fragment); ff_cbs_close(&ctx->cbc); } diff -Nru ffmpeg-4.2.2/libavcodec/fits.c ffmpeg-4.4/libavcodec/fits.c --- ffmpeg-4.2.2/libavcodec/fits.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/fits.c 2021-02-20 20:27:47.000000000 +0000 @@ -187,6 +187,8 @@ header->blank = t; header->blank_found = 1; } else if (!strcmp(keyword, "BSCALE") && sscanf(value, "%lf", &d) == 1) { + if (d <= 0) + return AVERROR_INVALIDDATA; header->bscale = d; } else if (!strcmp(keyword, "BZERO") && sscanf(value, "%lf", &d) == 1) { header->bzero = d; @@ -203,8 +205,12 @@ } else if (!strcmp(keyword, "GROUPS") && sscanf(value, "%c", &c) == 1) { header->groups = (c == 'T'); } else if (!strcmp(keyword, "GCOUNT") && sscanf(value, "%"SCNd64"", &t) == 1) { + if (t < 0 || t > INT_MAX) + return AVERROR_INVALIDDATA; header->gcount = t; } else if (!strcmp(keyword, "PCOUNT") && sscanf(value, "%"SCNd64"", &t) == 1) { + if (t < 0 || t > INT_MAX) + return AVERROR_INVALIDDATA; header->pcount = t; } dict_set_if_not_null(metadata, keyword, value); diff -Nru ffmpeg-4.2.2/libavcodec/fitsdec.c ffmpeg-4.4/libavcodec/fitsdec.c --- ffmpeg-4.2.2/libavcodec/fitsdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/fitsdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -63,7 +63,7 @@ int i, j; header->data_min = DBL_MAX; - header->data_max = DBL_MIN; + header->data_max = -DBL_MAX; switch (header->bitpix) { #define CASE_N(a, t, rd) \ case a: \ diff -Nru ffmpeg-4.2.2/libavcodec/flac.c ffmpeg-4.4/libavcodec/flac.c --- ffmpeg-4.2.2/libavcodec/flac.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/flac.c 2020-07-11 10:39:30.000000000 +0000 @@ -217,9 +217,9 @@ } skip_bits(&gb, 24); /* skip min frame size */ - s->max_framesize = get_bits_long(&gb, 24); + s->max_framesize = get_bits(&gb, 24); - s->samplerate = get_bits_long(&gb, 20); + s->samplerate = get_bits(&gb, 20); s->channels = get_bits(&gb, 3) + 1; s->bps = get_bits(&gb, 5) + 1; diff -Nru ffmpeg-4.2.2/libavcodec/flacdec.c ffmpeg-4.4/libavcodec/flacdec.c --- ffmpeg-4.2.2/libavcodec/flacdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/flacdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -262,7 +262,7 @@ } else { int real_limit = tmp ? (INT_MAX >> tmp) + 2 : INT_MAX; for (; i < samples; i++) { - int v = get_sr_golomb_flac(&gb, tmp, real_limit, 0); + int v = get_sr_golomb_flac(&gb, tmp, real_limit, 1); if (v == 0x80000000){ av_log(s->avctx, AV_LOG_ERROR, "invalid residual\n"); return AVERROR_INVALIDDATA; @@ -639,19 +639,6 @@ return bytes_read; } -#if HAVE_THREADS -static int init_thread_copy(AVCodecContext *avctx) -{ - FLACContext *s = avctx->priv_data; - s->decoded_buffer = NULL; - s->decoded_buffer_size = 0; - s->avctx = avctx; - if (s->flac_stream_info.max_blocksize) - return allocate_buffers(s); - return 0; -} -#endif - static av_cold int flac_decode_close(AVCodecContext *avctx) { FLACContext *s = avctx->priv_data; @@ -667,10 +654,10 @@ }; static const AVClass flac_decoder_class = { - "FLAC decoder", - av_default_item_name, - options, - LIBAVUTIL_VERSION_INT, + .class_name = "FLAC decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, }; AVCodec ff_flac_decoder = { @@ -682,8 +669,9 @@ .init = flac_decode_init, .close = flac_decode_close, .decode = flac_decode_frame, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(init_thread_copy), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_FRAME_THREADS, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32, diff -Nru ffmpeg-4.2.2/libavcodec/flacdsp_template.c ffmpeg-4.4/libavcodec/flacdsp_template.c --- ffmpeg-4.2.2/libavcodec/flacdsp_template.c 2017-12-31 02:32:05.000000000 +0000 +++ ffmpeg-4.4/libavcodec/flacdsp_template.c 2020-07-04 22:36:04.000000000 +0000 @@ -66,8 +66,8 @@ int i; for (i = 0; i < len; i++) { - int a = in[0][i]; - int b = in[1][i]; + unsigned a = in[0][i]; + unsigned b = in[1][i]; S(samples, 0, i) = a << shift; S(samples, 1, i) = (a - b) << shift; } @@ -80,8 +80,8 @@ int i; for (i = 0; i < len; i++) { - int a = in[0][i]; - int b = in[1][i]; + unsigned a = in[0][i]; + unsigned b = in[1][i]; S(samples, 0, i) = (a + b) << shift; S(samples, 1, i) = b << shift; } @@ -94,7 +94,7 @@ int i; for (i = 0; i < len; i++) { - int a = in[0][i]; + unsigned a = in[0][i]; int b = in[1][i]; a -= b >> 1; S(samples, 0, i) = (a + b) << shift; diff -Nru ffmpeg-4.2.2/libavcodec/flacenc.c ffmpeg-4.4/libavcodec/flacenc.c --- ffmpeg-4.2.2/libavcodec/flacenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/flacenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -1508,9 +1508,10 @@ .init = flac_encode_init, .encode2 = flac_encode_frame, .close = flac_encode_close, - .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_LOSSLESS, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, .priv_class = &flac_encoder_class, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/flac_parser.c ffmpeg-4.4/libavcodec/flac_parser.c --- ffmpeg-4.2.2/libavcodec/flac_parser.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/flac_parser.c 2020-07-11 10:39:30.000000000 +0000 @@ -58,8 +58,9 @@ typedef struct FLACHeaderMarker { int offset; /**< byte offset from start of FLACParseContext->buffer */ - int *link_penalty; /**< pointer to array of local scores between this header - and the one at a distance equal array position */ + int link_penalty[FLAC_MAX_SEQUENTIAL_HEADERS]; /**< array of local scores + between this header and the one at a distance equal + array position */ int max_score; /**< maximum score found after checking each child that has a valid CRC */ FLACFrameInfo fi; /**< decoded frame header info */ @@ -112,8 +113,8 @@ * This function is based on av_fifo_generic_read, which is why there is a comment * about a memory barrier for SMP. */ -static uint8_t* flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len, - uint8_t** wrap_buf, int* allocated_size) +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; uint8_t *start = f->rptr + offset; @@ -152,7 +153,7 @@ * 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(FLACParseContext *fpc, int offset, int *len) { AVFifoBuffer *f = fpc->fifo_buf; uint8_t *start = f->rptr + offset; @@ -188,16 +189,8 @@ "couldn't allocate FLACHeaderMarker\n"); return AVERROR(ENOMEM); } - (*end_handle)->fi = fi; - (*end_handle)->offset = offset; - (*end_handle)->link_penalty = av_malloc(sizeof(int) * - FLAC_MAX_SEQUENTIAL_HEADERS); - if (!(*end_handle)->link_penalty) { - av_freep(end_handle); - av_log(fpc->avctx, AV_LOG_ERROR, - "couldn't allocate link_penalty\n"); - return AVERROR(ENOMEM); - } + (*end_handle)->fi = fi; + (*end_handle)->offset = offset; for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS; i++) (*end_handle)->link_penalty[i] = FLAC_HEADER_NOT_PENALIZED_YET; @@ -208,24 +201,27 @@ return size; } -static int find_headers_search(FLACParseContext *fpc, uint8_t *buf, int buf_size, - int search_start) - +static int find_headers_search(FLACParseContext *fpc, uint8_t *buf, + int buf_size, int search_start) { int size = 0, mod_offset = (buf_size - 1) % 4, i, j; uint32_t x; for (i = 0; i < mod_offset; i++) { - if ((AV_RB16(buf + i) & 0xFFFE) == 0xFFF8) - size = find_headers_search_validate(fpc, search_start + i); + if ((AV_RB16(buf + i) & 0xFFFE) == 0xFFF8) { + int ret = find_headers_search_validate(fpc, search_start + i); + size = FFMAX(size, ret); + } } for (; i < buf_size - 1; i += 4) { - x = AV_RB32(buf + i); + x = AV_RN32(buf + i); if (((x & ~(x + 0x01010101)) & 0x80808080)) { for (j = 0; j < 4; j++) { - if ((AV_RB16(buf + i + j) & 0xFFFE) == 0xFFF8) - size = find_headers_search_validate(fpc, search_start + i + j); + if ((AV_RB16(buf + i + j) & 0xFFFE) == 0xFFF8) { + int ret = find_headers_search_validate(fpc, search_start + i + j); + size = FFMAX(size, ret); + } } } } @@ -251,9 +247,9 @@ uint8_t wrap[2]; wrap[0] = buf[read_len - 1]; - read_len = search_end - search_start + 1; - /* 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); wrap[1] = buf[0]; @@ -321,7 +317,7 @@ (child_fi->frame_or_sample_num != header_fi->frame_or_sample_num + 1)) { FLACHeaderMarker *curr; - int expected_frame_num, expected_sample_num; + int64_t expected_frame_num, expected_sample_num; /* If there are frames in the middle we expect this deduction, as they are probably valid and this one follows it */ @@ -471,7 +467,7 @@ } } -static int get_best_header(FLACParseContext* fpc, const uint8_t **poutbuf, +static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf, int *poutbuf_size) { FLACHeaderMarker *header = fpc->best_header; @@ -497,7 +493,7 @@ &fpc->wrap_buf_allocated_size); - if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS){ + if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS) { if (header->fi.is_var_size) fpc->pc->pts = header->fi.frame_or_sample_num; else if (header->best_child) @@ -531,7 +527,7 @@ s->duration = fi.blocksize; if (!avctx->sample_rate) avctx->sample_rate = fi.samplerate; - if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS){ + if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS) { fpc->pc->pts = fi.frame_or_sample_num; if (!fi.is_var_size) fpc->pc->pts *= fi.blocksize; @@ -559,7 +555,6 @@ curr->max_score, curr->offset, curr->next->offset); } temp = curr->next; - av_freep(&curr->link_penalty); av_free(curr); fpc->nb_headers_buffered--; } @@ -570,7 +565,6 @@ for (curr = best_child->next; curr; curr = curr->next) curr->offset -= best_child->offset; - fpc->nb_headers_buffered--; best_child->offset = 0; fpc->headers = best_child; if (fpc->nb_headers_buffered >= FLAC_MIN_HEADERS) { @@ -584,30 +578,26 @@ for (curr = fpc->headers; curr != fpc->best_header; curr = temp) { temp = curr->next; - av_freep(&curr->link_penalty); av_free(curr); fpc->nb_headers_buffered--; } fpc->headers = fpc->best_header->next; - av_freep(&fpc->best_header->link_penalty); av_freep(&fpc->best_header); fpc->nb_headers_buffered--; } /* Find and score new headers. */ - /* buf_size is to zero when padding, so check for this since we do */ + /* buf_size is zero when flushing, so check for this since we do */ /* not want to try to read more input once we have found the end. */ - /* Note that as (non-modified) parameters, buf can be non-NULL, */ - /* while buf_size is 0. */ - while ((buf && buf_size && read_end < buf + buf_size && + /* Also note that buf can't be NULL. */ + while ((buf_size && read_end < buf + buf_size && fpc->nb_headers_buffered < FLAC_MIN_HEADERS) - || ((!buf || !buf_size) && !fpc->end_padded)) { + || (!buf_size && !fpc->end_padded)) { int start_offset; /* Pad the end once if EOF, to check the final region for headers. */ - if (!buf || !buf_size) { - fpc->end_padded = 1; - buf_size = MAX_FRAME_HEADER_SIZE; + if (!buf_size) { + fpc->end_padded = 1; read_end = read_start + MAX_FRAME_HEADER_SIZE; } else { /* The maximum read size is the upper-bound of what the parser @@ -635,7 +625,7 @@ goto handle_error; } - if (buf && buf_size) { + if (buf_size) { av_fifo_generic_write(fpc->fifo_buf, (void*) read_start, read_end - read_start, NULL); } else { @@ -658,7 +648,7 @@ fpc->nb_headers_buffered = nb_headers; /* Wait till FLAC_MIN_HEADERS to output a valid frame. */ if (!fpc->end_padded && fpc->nb_headers_buffered < FLAC_MIN_HEADERS) { - if (buf && read_end < buf + buf_size) { + if (read_end < buf + buf_size) { read_start = read_end; continue; } else { @@ -680,7 +670,6 @@ fpc->fifo_buf->wptr += fpc->fifo_buf->end - fpc->fifo_buf->buffer; } - buf_size = 0; read_start = read_end = NULL; } } @@ -693,7 +682,7 @@ if (fpc->best_header && fpc->best_header->max_score <= 0) { // Only accept a bad header if there is no other option to continue - if (!buf_size || !buf || read_end != buf || fpc->nb_headers_buffered < FLAC_MIN_HEADERS) + if (!buf_size || read_end != buf || fpc->nb_headers_buffered < FLAC_MIN_HEADERS) fpc->best_header = NULL; } @@ -705,13 +694,13 @@ fpc->best_header->offset); /* Set duration to 0. It is unknown or invalid in a junk frame. */ - s->duration = 0; - *poutbuf_size = fpc->best_header->offset; - *poutbuf = flac_fifo_read_wrap(fpc, 0, *poutbuf_size, - &fpc->wrap_buf, - &fpc->wrap_buf_allocated_size); + s->duration = 0; + *poutbuf_size = fpc->best_header->offset; + *poutbuf = flac_fifo_read_wrap(fpc, 0, *poutbuf_size, + &fpc->wrap_buf, + &fpc->wrap_buf_allocated_size); return buf_size ? (read_end - buf) : (fpc->best_header->offset - - av_fifo_size(fpc->fifo_buf)); + av_fifo_size(fpc->fifo_buf)); } if (!buf_size) return get_best_header(fpc, poutbuf, poutbuf_size); @@ -745,10 +734,10 @@ while (curr) { temp = curr->next; - av_freep(&curr->link_penalty); av_free(curr); curr = temp; } + fpc->headers = NULL; av_fifo_freep(&fpc->fifo_buf); av_freep(&fpc->wrap_buf); } diff -Nru ffmpeg-4.2.2/libavcodec/flashsv2enc.c ffmpeg-4.4/libavcodec/flashsv2enc.c --- ffmpeg-4.2.2/libavcodec/flashsv2enc.c 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/flashsv2enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -142,6 +142,7 @@ { int row, col; Block *b; + memset(blocks, 0, s->cols * s->rows * sizeof(*blocks)); for (col = 0; col < s->cols; col++) { for (row = 0; row < s->rows; row++) { b = blocks + (col + row * s->cols); @@ -158,7 +159,7 @@ b->enc = encbuf; b->data = databuf; encbuf += b->width * b->height * 3; - databuf += !databuf ? 0 : b->width * b->height * 6; + databuf = databuf ? databuf + b->width * b->height * 6 : NULL; } } } @@ -174,9 +175,37 @@ #endif } +static int update_block_dimensions(FlashSV2Context *s, int block_width, int block_height) +{ + s->block_width = block_width; + s->block_height = block_height; + s->rows = (s->image_height + s->block_height - 1) / s->block_height; + s->cols = (s->image_width + s->block_width - 1) / s->block_width; + if (s->rows * s->cols > s->blocks_size / sizeof(Block)) { + s->frame_blocks = av_realloc_array(s->frame_blocks, s->rows, s->cols * sizeof(Block)); + s->key_blocks = av_realloc_array(s->key_blocks, s->cols, s->rows * sizeof(Block)); + if (!s->frame_blocks || !s->key_blocks) { + av_log(s->avctx, AV_LOG_ERROR, "Memory allocation failed.\n"); + return AVERROR(ENOMEM); + } + s->blocks_size = s->rows * s->cols * sizeof(Block); + } + init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer); + init_blocks(s, s->key_blocks, s->keybuffer, 0); + + av_fast_malloc(&s->blockbuffer, &s->blockbuffer_size, block_width * block_height * 6); + if (!s->blockbuffer) { + av_log(s->avctx, AV_LOG_ERROR, "Could not allocate block buffer.\n"); + return AVERROR(ENOMEM); + } + return 0; +} + + static av_cold int flashsv2_encode_init(AVCodecContext * avctx) { FlashSV2Context *s = avctx->priv_data; + int ret; s->avctx = avctx; @@ -186,23 +215,23 @@ if (s->comp < 0 || s->comp > 9) { av_log(avctx, AV_LOG_ERROR, "Compression level should be 0-9, not %d\n", s->comp); - return -1; + return AVERROR(EINVAL); } if ((avctx->width > 4095) || (avctx->height > 4095)) { av_log(avctx, AV_LOG_ERROR, "Input dimensions too large, input must be max 4095x4095 !\n"); - return -1; + return AVERROR(EINVAL); } if ((avctx->width < 16) || (avctx->height < 16)) { av_log(avctx, AV_LOG_ERROR, "Input dimensions too small, input must be at least 16x16 !\n"); - return -1; + return AVERROR(EINVAL); } - if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) - return -1; + if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0) + return ret; s->last_key_frame = 0; @@ -210,33 +239,19 @@ s->image_width = avctx->width; s->image_height = avctx->height; - s->block_width = (s->image_width / 12) & ~15; - s->block_height = (s->image_height / 12) & ~15; - - if(!s->block_width) - s->block_width = 1; - if(!s->block_height) - s->block_height = 1; - - s->rows = (s->image_height + s->block_height - 1) / s->block_height; - s->cols = (s->image_width + s->block_width - 1) / s->block_width; - s->frame_size = s->image_width * s->image_height * 3; - s->blocks_size = s->rows * s->cols * sizeof(Block); s->encbuffer = av_mallocz(s->frame_size); s->keybuffer = av_mallocz(s->frame_size); s->databuffer = av_mallocz(s->frame_size * 6); s->current_frame = av_mallocz(s->frame_size); s->key_frame = av_mallocz(s->frame_size); - s->frame_blocks = av_mallocz(s->blocks_size); - s->key_blocks = av_mallocz(s->blocks_size); - - s->blockbuffer = NULL; - s->blockbuffer_size = 0; + if (!s->encbuffer || !s->keybuffer || !s->databuffer + || !s->current_frame || !s->key_frame) { + av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n"); + return AVERROR(ENOMEM); + } - init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer); - init_blocks(s, s->key_blocks, s->keybuffer, 0); reset_stats(s); #ifndef FLASHSV2_DUMB s->total_bits = 1; @@ -245,15 +260,7 @@ s->use_custom_palette = 0; s->palette_type = -1; // so that the palette will be generated in reconfigure_at_keyframe - if (!s->encbuffer || !s->keybuffer || !s->databuffer - || !s->current_frame || !s->key_frame || !s->key_blocks - || !s->frame_blocks) { - av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n"); - cleanup(s); - return -1; - } - - return 0; + return update_block_dimensions(s, 64, 64); } static int new_key_frame(FlashSV2Context * s) @@ -801,29 +808,10 @@ int block_width = optimum_block_width (s); int block_height = optimum_block_height(s); - s->rows = (s->image_height + block_height - 1) / block_height; - s->cols = (s->image_width + block_width - 1) / block_width; - if (block_width != s->block_width || block_height != s->block_height) { - s->block_width = block_width; - s->block_height = block_height; - if (s->rows * s->cols > s->blocks_size / sizeof(Block)) { - s->frame_blocks = av_realloc_array(s->frame_blocks, s->rows, s->cols * sizeof(Block)); - s->key_blocks = av_realloc_array(s->key_blocks, s->cols, s->rows * sizeof(Block)); - if (!s->frame_blocks || !s->key_blocks) { - av_log(s->avctx, AV_LOG_ERROR, "Memory allocation failed.\n"); - return -1; - } - s->blocks_size = s->rows * s->cols * sizeof(Block); - } - init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer); - init_blocks(s, s->key_blocks, s->keybuffer, 0); - - av_fast_malloc(&s->blockbuffer, &s->blockbuffer_size, block_width * block_height * 6); - if (!s->blockbuffer) { - av_log(s->avctx, AV_LOG_ERROR, "Could not allocate block buffer.\n"); - return AVERROR(ENOMEM); - } + res = update_block_dimensions(s, block_width, block_height); + if (res < 0) + return res; } s->use15_7 = optimum_use15_7(s); @@ -919,4 +907,5 @@ .encode2 = flashsv2_encode_frame, .close = flashsv2_encode_end, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/flashsv.c ffmpeg-4.4/libavcodec/flashsv.c --- ffmpeg-4.2.2/libavcodec/flashsv.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/flashsv.c 2021-04-08 21:28:39.000000000 +0000 @@ -179,7 +179,7 @@ return 0; } -static int flashsv_decode_block(AVCodecContext *avctx, AVPacket *avpkt, +static int flashsv_decode_block(AVCodecContext *avctx, const AVPacket *avpkt, GetBitContext *gb, int block_size, int width, int height, int x_pos, int y_pos, int blk_idx) @@ -368,7 +368,7 @@ s->image_width, s->image_height, s->block_width, s->block_height, h_blocks, v_blocks, h_part, v_part); - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; /* loop over all block columns */ diff -Nru ffmpeg-4.2.2/libavcodec/flashsvenc.c ffmpeg-4.4/libavcodec/flashsvenc.c --- ffmpeg-4.2.2/libavcodec/flashsvenc.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/flashsvenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -59,11 +59,10 @@ uint8_t *previous_frame; int image_width, image_height; int block_width, block_height; - uint8_t *tmpblock; uint8_t *encbuffer; int block_size; - z_stream zstream; int last_key_frame; + uint8_t tmpblock[3 * 256 * 256]; } FlashSVContext; static int copy_region_enc(uint8_t *sptr, uint8_t *dptr, int dx, int dy, @@ -92,11 +91,8 @@ { FlashSVContext *s = avctx->priv_data; - deflateEnd(&s->zstream); - av_freep(&s->encbuffer); av_freep(&s->previous_frame); - av_freep(&s->tmpblock); return 0; } @@ -113,18 +109,14 @@ return AVERROR_INVALIDDATA; } - // Needed if zlib unused or init aborted before deflateInit - memset(&s->zstream, 0, sizeof(z_stream)); - s->last_key_frame = 0; s->image_width = avctx->width; s->image_height = avctx->height; - s->tmpblock = av_mallocz(3 * 256 * 256); s->encbuffer = av_mallocz(s->image_width * s->image_height * 3); - if (!s->tmpblock || !s->encbuffer) { + if (!s->encbuffer) { av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n"); return AVERROR(ENOMEM); } @@ -182,7 +174,6 @@ ret = compress2(ptr + 2, &zsize, s->tmpblock, 3 * cur_blk_width * cur_blk_height, 9); - //ret = deflateReset(&s->zstream); if (ret != Z_OK) av_log(s->avctx, AV_LOG_ERROR, "error while compressing block %dx%d\n", i, j); diff -Nru ffmpeg-4.2.2/libavcodec/flicvideo.c ffmpeg-4.4/libavcodec/flicvideo.c --- ffmpeg-4.2.2/libavcodec/flicvideo.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/flicvideo.c 2020-07-11 10:39:30.000000000 +0000 @@ -185,7 +185,7 @@ bytestream2_init(&g2, buf, buf_size); - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; pixels = s->frame->data[0]; @@ -519,7 +519,7 @@ bytestream2_init(&g2, buf, buf_size); - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; pixels = s->frame->data[0]; @@ -817,7 +817,7 @@ bytestream2_init(&g2, buf, buf_size); - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; pixels = s->frame->data[0]; diff -Nru ffmpeg-4.2.2/libavcodec/float2half.h ffmpeg-4.4/libavcodec/float2half.h --- ffmpeg-4.2.2/libavcodec/float2half.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/float2half.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,67 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_FLOAT2HALF_H +#define AVCODEC_FLOAT2HALF_H + +#include + +static void float2half_tables(uint16_t *basetable, uint8_t *shifttable) +{ + for (int i = 0; i < 256; i++) { + int e = i - 127; + + if (e < -24) { // Very small numbers map to zero + basetable[i|0x000] = 0x0000; + basetable[i|0x100] = 0x8000; + shifttable[i|0x000] = 24; + shifttable[i|0x100] = 24; + } else if (e < -14) { // Small numbers map to denorms + basetable[i|0x000] = (0x0400>>(-e-14)); + basetable[i|0x100] = (0x0400>>(-e-14)) | 0x8000; + shifttable[i|0x000] = -e-1; + shifttable[i|0x100] = -e-1; + } else if (e <= 15) { // Normal numbers just lose precision + basetable[i|0x000] = ((e + 15) << 10); + basetable[i|0x100] = ((e + 15) << 10) | 0x8000; + shifttable[i|0x000] = 13; + shifttable[i|0x100] = 13; + } else if (e < 128) { // Large numbers map to Infinity + basetable[i|0x000] = 0x7C00; + basetable[i|0x100] = 0xFC00; + shifttable[i|0x000] = 24; + shifttable[i|0x100] = 24; + } else { // Infinity and NaN's stay Infinity and NaN's + basetable[i|0x000] = 0x7C00; + basetable[i|0x100] = 0xFC00; + shifttable[i|0x000] = 13; + shifttable[i|0x100] = 13; + } + } +} + +static uint16_t float2half(uint32_t f, uint16_t *basetable, uint8_t *shifttable) +{ + uint16_t h; + + h = basetable[(f >> 23) & 0x1ff] + ((f & 0x007fffff) >> shifttable[(f >> 23) & 0x1ff]); + + return h; +} + +#endif /* AVCODEC_FLOAT2HALF_H */ diff -Nru ffmpeg-4.2.2/libavcodec/flvdec.c ffmpeg-4.4/libavcodec/flvdec.c --- ffmpeg-4.2.2/libavcodec/flvdec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/flvdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -30,7 +30,7 @@ int format, width, height; /* picture header */ - if (get_bits_long(&s->gb, 17) != 1) { + if (get_bits(&s->gb, 17) != 1) { av_log(s->avctx, AV_LOG_ERROR, "Bad picture start code\n"); return AVERROR_INVALIDDATA; } diff -Nru ffmpeg-4.2.2/libavcodec/flvenc.c ffmpeg-4.4/libavcodec/flvenc.c --- ffmpeg-4.2.2/libavcodec/flvenc.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/flvenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,7 +28,7 @@ { int format; - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); put_bits(&s->pb, 17, 1); /* 0: H.263 escape codes 1: 11-bit escape codes */ @@ -107,6 +107,7 @@ .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE}, .priv_class = &flv_class, diff -Nru ffmpeg-4.2.2/libavcodec/fmvc.c ffmpeg-4.4/libavcodec/fmvc.c --- ffmpeg-4.2.2/libavcodec/fmvc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/fmvc.c 2021-04-08 21:28:39.000000000 +0000 @@ -440,6 +440,8 @@ memcpy(dst, src, avctx->width * s->bpp); dst -= frame->linesize[0]; src += s->stride * 4; + if (bytestream2_tell_p(pb) < y*s->stride * 4) + break; } } else { unsigned block, nb_blocks; diff -Nru ffmpeg-4.2.2/libavcodec/frame_thread_encoder.c ffmpeg-4.4/libavcodec/frame_thread_encoder.c --- ffmpeg-4.2.2/libavcodec/frame_thread_encoder.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/frame_thread_encoder.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,7 +22,6 @@ #include "frame_thread_encoder.h" -#include "libavutil/fifo.h" #include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" @@ -32,27 +31,32 @@ #include "thread.h" #define MAX_THREADS 64 -#define BUFFER_SIZE (2*MAX_THREADS) +/* There can be as many as MAX_THREADS + 1 outstanding tasks. + * An additional + 1 is needed so that one can distinguish + * the case of zero and MAX_THREADS + 1 outstanding tasks modulo + * the number of buffers. */ +#define BUFFER_SIZE (MAX_THREADS + 2) typedef struct{ - void *indata; - void *outdata; - int64_t return_code; - unsigned index; + AVFrame *indata; + AVPacket *outdata; + int return_code; + int finished; } Task; typedef struct{ AVCodecContext *parent_avctx; pthread_mutex_t buffer_mutex; - AVFifoBuffer *task_fifo; - pthread_mutex_t task_fifo_mutex; + pthread_mutex_t task_fifo_mutex; /* Used to guard (next_)task_index */ pthread_cond_t task_fifo_cond; - Task finished_tasks[BUFFER_SIZE]; - pthread_mutex_t finished_task_mutex; + unsigned max_tasks; + Task tasks[BUFFER_SIZE]; + pthread_mutex_t finished_task_mutex; /* Guards tasks[i].finished */ pthread_cond_t finished_task_cond; + unsigned next_task_index; unsigned task_index; unsigned finished_task_index; @@ -63,50 +67,53 @@ static void * attribute_align_arg worker(void *v){ AVCodecContext *avctx = v; ThreadContext *c = avctx->internal->frame_thread_encoder; - AVPacket *pkt = NULL; while (!atomic_load(&c->exit)) { - int got_packet, ret; + int got_packet = 0, ret; + AVPacket *pkt; AVFrame *frame; - Task task; - - if(!pkt) pkt = av_packet_alloc(); - if(!pkt) continue; - av_init_packet(pkt); + Task *task; + unsigned task_index; pthread_mutex_lock(&c->task_fifo_mutex); - while (av_fifo_size(c->task_fifo) <= 0 || atomic_load(&c->exit)) { + while (c->next_task_index == c->task_index || atomic_load(&c->exit)) { if (atomic_load(&c->exit)) { pthread_mutex_unlock(&c->task_fifo_mutex); goto end; } pthread_cond_wait(&c->task_fifo_cond, &c->task_fifo_mutex); } - av_fifo_generic_read(c->task_fifo, &task, sizeof(task), NULL); + task_index = c->next_task_index; + c->next_task_index = (c->next_task_index + 1) % c->max_tasks; pthread_mutex_unlock(&c->task_fifo_mutex); - frame = task.indata; + /* The main thread ensures that any two outstanding tasks have + * different indices, ergo each worker thread owns its element + * of c->tasks with the exception of finished, which is shared + * with the main thread and guarded by finished_task_mutex. */ + task = &c->tasks[task_index]; + frame = task->indata; + pkt = task->outdata; - ret = avcodec_encode_video2(avctx, pkt, frame, &got_packet); - pthread_mutex_lock(&c->buffer_mutex); - av_frame_unref(frame); - pthread_mutex_unlock(&c->buffer_mutex); - av_frame_free(&frame); + ret = avctx->codec->encode2(avctx, pkt, frame, &got_packet); if(got_packet) { int ret2 = av_packet_make_refcounted(pkt); if (ret >= 0 && ret2 < 0) ret = ret2; + pkt->pts = pkt->dts = frame->pts; } else { pkt->data = NULL; pkt->size = 0; } + pthread_mutex_lock(&c->buffer_mutex); + av_frame_unref(frame); + pthread_mutex_unlock(&c->buffer_mutex); pthread_mutex_lock(&c->finished_task_mutex); - c->finished_tasks[task.index].outdata = pkt; pkt = NULL; - c->finished_tasks[task.index].return_code = ret; + task->return_code = ret; + task->finished = 1; pthread_cond_signal(&c->finished_task_cond); pthread_mutex_unlock(&c->finished_task_mutex); } end: - av_free(pkt); pthread_mutex_lock(&c->buffer_mutex); avcodec_close(avctx); pthread_mutex_unlock(&c->buffer_mutex); @@ -120,7 +127,7 @@ if( !(avctx->thread_type & FF_THREAD_FRAME) - || !(avctx->codec->capabilities & AV_CODEC_CAP_INTRA_ONLY)) + || !(avctx->codec->capabilities & AV_CODEC_CAP_FRAME_THREADS)) return 0; if( !avctx->thread_count @@ -180,10 +187,6 @@ c->parent_avctx = avctx; - c->task_fifo = av_fifo_alloc_array(BUFFER_SIZE, sizeof(Task)); - if(!c->task_fifo) - goto fail; - pthread_mutex_init(&c->task_fifo_mutex, NULL); pthread_mutex_init(&c->finished_task_mutex, NULL); pthread_mutex_init(&c->buffer_mutex, NULL); @@ -191,6 +194,13 @@ pthread_cond_init(&c->finished_task_cond, NULL); atomic_init(&c->exit, 0); + c->max_tasks = avctx->thread_count + 2; + for (unsigned i = 0; i < c->max_tasks; i++) { + if (!(c->tasks[i].indata = av_frame_alloc()) || + !(c->tasks[i].outdata = av_packet_alloc())) + goto fail; + } + for(i=0; ithread_count ; i++){ AVDictionary *tmp = NULL; int ret; @@ -209,8 +219,9 @@ int ret = av_opt_copy(thread_avctx->priv_data, avctx->priv_data); if (ret < 0) goto fail; - } else + } else if (avctx->codec->priv_data_size) { memcpy(thread_avctx->priv_data, avctx->priv_data, avctx->codec->priv_data_size); + } thread_avctx->thread_count = 1; thread_avctx->active_thread_type &= ~FF_THREAD_FRAME; @@ -251,21 +262,9 @@ pthread_join(c->worker[i], NULL); } - while (av_fifo_size(c->task_fifo) > 0) { - Task task; - AVFrame *frame; - av_fifo_generic_read(c->task_fifo, &task, sizeof(task), NULL); - frame = task.indata; - av_frame_free(&frame); - task.indata = NULL; - } - - for (i=0; ifinished_tasks[i].outdata != NULL) { - AVPacket *pkt = c->finished_tasks[i].outdata; - av_packet_free(&pkt); - c->finished_tasks[i].outdata = NULL; - } + for (unsigned i = 0; i < c->max_tasks; i++) { + av_frame_free(&c->tasks[i].indata); + av_packet_free(&c->tasks[i].outdata); } pthread_mutex_destroy(&c->task_fifo_mutex); @@ -273,55 +272,47 @@ pthread_mutex_destroy(&c->buffer_mutex); pthread_cond_destroy(&c->task_fifo_cond); pthread_cond_destroy(&c->finished_task_cond); - av_fifo_freep(&c->task_fifo); av_freep(&avctx->internal->frame_thread_encoder); } -int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet_ptr){ +int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + AVFrame *frame, int *got_packet_ptr) +{ ThreadContext *c = avctx->internal->frame_thread_encoder; - Task task; - int ret; + Task *outtask; av_assert1(!*got_packet_ptr); if(frame){ - AVFrame *new = av_frame_alloc(); - if(!new) - return AVERROR(ENOMEM); - ret = av_frame_ref(new, frame); - if(ret < 0) { - av_frame_free(&new); - return ret; - } + av_frame_move_ref(c->tasks[c->task_index].indata, frame); - task.index = c->task_index; - task.indata = (void*)new; pthread_mutex_lock(&c->task_fifo_mutex); - av_fifo_generic_write(c->task_fifo, &task, sizeof(task), NULL); + c->task_index = (c->task_index + 1) % c->max_tasks; pthread_cond_signal(&c->task_fifo_cond); pthread_mutex_unlock(&c->task_fifo_mutex); - - c->task_index = (c->task_index+1) % BUFFER_SIZE; } + outtask = &c->tasks[c->finished_task_index]; pthread_mutex_lock(&c->finished_task_mutex); + /* The access to task_index in the following code is ok, + * because it is only ever changed by the main thread. */ if (c->task_index == c->finished_task_index || - (frame && !c->finished_tasks[c->finished_task_index].outdata && - (c->task_index - c->finished_task_index) % BUFFER_SIZE <= avctx->thread_count)) { + (frame && !outtask->finished && + (c->task_index - c->finished_task_index + c->max_tasks) % c->max_tasks <= avctx->thread_count)) { pthread_mutex_unlock(&c->finished_task_mutex); return 0; } - - while (!c->finished_tasks[c->finished_task_index].outdata) { + while (!outtask->finished) { pthread_cond_wait(&c->finished_task_cond, &c->finished_task_mutex); } - task = c->finished_tasks[c->finished_task_index]; - *pkt = *(AVPacket*)(task.outdata); + pthread_mutex_unlock(&c->finished_task_mutex); + /* We now own outtask completely: No worker thread touches it any more, + * because there is no outstanding task with this index. */ + outtask->finished = 0; + av_packet_move_ref(pkt, outtask->outdata); if(pkt->data) *got_packet_ptr = 1; - av_freep(&c->finished_tasks[c->finished_task_index].outdata); - c->finished_task_index = (c->finished_task_index+1) % BUFFER_SIZE; - pthread_mutex_unlock(&c->finished_task_mutex); + c->finished_task_index = (c->finished_task_index + 1) % c->max_tasks; - return task.return_code; + return outtask->return_code; } diff -Nru ffmpeg-4.2.2/libavcodec/frame_thread_encoder.h ffmpeg-4.4/libavcodec/frame_thread_encoder.h --- ffmpeg-4.2.2/libavcodec/frame_thread_encoder.h 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/frame_thread_encoder.h 2021-04-08 21:28:39.000000000 +0000 @@ -25,6 +25,7 @@ int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options); void ff_frame_thread_encoder_free(AVCodecContext *avctx); -int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet_ptr); +int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + AVFrame *frame, int *got_packet_ptr); #endif /* AVCODEC_FRAME_THREAD_ENCODER_H */ diff -Nru ffmpeg-4.2.2/libavcodec/fraps.c ffmpeg-4.4/libavcodec/fraps.c --- ffmpeg-4.2.2/libavcodec/fraps.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/fraps.c 2021-04-08 21:28:39.000000000 +0000 @@ -31,6 +31,10 @@ * Version 2 files support by Konstantin Shishkov */ +#include "config.h" + +#define CACHED_BITSTREAM_READER HAVE_FAST_64BIT +#define UNCHECKED_BITSTREAM_READER 1 #include "avcodec.h" #include "get_bits.h" #include "huffman.h" diff -Nru ffmpeg-4.2.2/libavcodec/g2meet.c ffmpeg-4.4/libavcodec/g2meet.c --- ffmpeg-4.2.2/libavcodec/g2meet.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/g2meet.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "blockdsp.h" @@ -40,6 +41,7 @@ #include "internal.h" #include "jpegtables.h" #include "mjpeg.h" +#include "mjpegdec.h" #define EPIC_PIX_STACK_SIZE 1024 #define EPIC_PIX_STACK_MAX (EPIC_PIX_STACK_SIZE - 1) @@ -158,45 +160,24 @@ int cursor_hot_x, cursor_hot_y; } G2MContext; -static av_cold int build_vlc(VLC *vlc, const uint8_t *bits_table, - const uint8_t *val_table, int nb_codes, - int is_ac) -{ - uint8_t huff_size[256] = { 0 }; - uint16_t huff_code[256]; - uint16_t huff_sym[256]; - int i; - - ff_mjpeg_build_huffman_codes(huff_size, huff_code, bits_table, val_table); - - for (i = 0; i < 256; i++) - huff_sym[i] = i + 16 * is_ac; - - if (is_ac) - huff_sym[0] = 16 * 256; - - return ff_init_vlc_sparse(vlc, 9, nb_codes, huff_size, 1, 1, - huff_code, 2, 2, huff_sym, 2, 2, 0); -} - static av_cold int jpg_init(AVCodecContext *avctx, JPGContext *c) { int ret; - ret = build_vlc(&c->dc_vlc[0], avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc, 12, 0); + ret = ff_mjpeg_build_vlc(&c->dc_vlc[0], avpriv_mjpeg_bits_dc_luminance, + avpriv_mjpeg_val_dc, 0, avctx); if (ret) return ret; - ret = build_vlc(&c->dc_vlc[1], avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc, 12, 0); + ret = ff_mjpeg_build_vlc(&c->dc_vlc[1], avpriv_mjpeg_bits_dc_chrominance, + avpriv_mjpeg_val_dc, 0, avctx); if (ret) return ret; - ret = build_vlc(&c->ac_vlc[0], avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance, 251, 1); + ret = ff_mjpeg_build_vlc(&c->ac_vlc[0], avpriv_mjpeg_bits_ac_luminance, + avpriv_mjpeg_val_ac_luminance, 1, avctx); if (ret) return ret; - ret = build_vlc(&c->ac_vlc[1], avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance, 251, 1); + ret = ff_mjpeg_build_vlc(&c->ac_vlc[1], avpriv_mjpeg_bits_ac_chrominance, + avpriv_mjpeg_val_ac_chrominance, 1, avctx); if (ret) return ret; @@ -248,7 +229,7 @@ return AVERROR_INVALIDDATA; c->bdsp.clear_block(block); - dc = get_vlc2(gb, c->dc_vlc[is_chroma].table, 9, 3); + dc = get_vlc2(gb, c->dc_vlc[is_chroma].table, 9, 2); if (dc < 0) return AVERROR_INVALIDDATA; if (dc) @@ -259,7 +240,7 @@ pos = 0; while (pos < 63) { - val = get_vlc2(gb, c->ac_vlc[is_chroma].table, 9, 3); + val = get_vlc2(gb, c->ac_vlc[is_chroma].table, 9, 2); if (val < 0) return AVERROR_INVALIDDATA; pos += val >> 4; @@ -560,7 +541,7 @@ } if (R<0 || G<0 || B<0 || R > 255 || G > 255 || B > 255) { - avpriv_request_sample(NULL, "RGB %d %d %d is out of range\n", R, G, B); + avpriv_request_sample(NULL, "RGB %d %d %d (out of range)", R, G, B); return 0; } @@ -917,6 +898,11 @@ awidth = FFALIGN(tile_width, 16); aheight = FFALIGN(tile_height, 16); + if (tile_width > (1 << FF_ARRAY_ELEMS(c->ec.prev_row_rung))) { + avpriv_request_sample(avctx, "large tile width"); + return AVERROR_INVALIDDATA; + } + if (els_dsize) { int ret, i, j, k; uint8_t tr_r, tr_g, tr_b, *buf; @@ -1043,7 +1029,7 @@ else if (npal <= 16) nb = 4; else nb = 8; - for (j = 0; j < height; j++, dst += stride, jpeg_tile += tile_stride) { + for (j = 0; j < height; j++, dst += stride, jpeg_tile = FF_PTR_ADD(jpeg_tile, tile_stride)) { if (get_bits(&gb, 8)) continue; for (i = 0; i < width; i++) { diff -Nru ffmpeg-4.2.2/libavcodec/g722dec.c ffmpeg-4.4/libavcodec/g722dec.c --- ffmpeg-4.2.2/libavcodec/g722dec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/g722dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -147,6 +147,6 @@ .priv_data_size = sizeof(G722Context), .init = g722_decode_init, .decode = g722_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .priv_class = &g722_decoder_class, }; diff -Nru ffmpeg-4.2.2/libavcodec/g722enc.c ffmpeg-4.4/libavcodec/g722enc.c --- ffmpeg-4.2.2/libavcodec/g722enc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/g722enc.c 2021-04-08 21:28:27.000000000 +0000 @@ -59,27 +59,11 @@ static av_cold int g722_encode_init(AVCodecContext * avctx) { G722Context *c = avctx->priv_data; - int ret; c->band[0].scale_factor = 8; c->band[1].scale_factor = 2; c->prev_samples_pos = 22; - if (avctx->trellis) { - int frontier = 1 << avctx->trellis; - int max_paths = frontier * FREEZE_INTERVAL; - int i; - for (i = 0; i < 2; i++) { - c->paths[i] = av_mallocz_array(max_paths, sizeof(**c->paths)); - c->node_buf[i] = av_mallocz_array(frontier, 2 * sizeof(**c->node_buf)); - c->nodep_buf[i] = av_mallocz_array(frontier, 2 * sizeof(**c->nodep_buf)); - if (!c->paths[i] || !c->node_buf[i] || !c->nodep_buf[i]) { - ret = AVERROR(ENOMEM); - goto error; - } - } - } - if (avctx->frame_size) { /* validate frame size */ if (avctx->frame_size & 1 || avctx->frame_size > MAX_FRAME_SIZE) { @@ -113,14 +97,23 @@ avctx->trellis); avctx->trellis = new_trellis; } + if (avctx->trellis) { + int frontier = 1 << avctx->trellis; + int max_paths = frontier * FREEZE_INTERVAL; + + for (int i = 0; i < 2; i++) { + c->paths[i] = av_calloc(max_paths, sizeof(**c->paths)); + c->node_buf[i] = av_calloc(frontier, 2 * sizeof(**c->node_buf)); + c->nodep_buf[i] = av_calloc(frontier, 2 * sizeof(**c->nodep_buf)); + if (!c->paths[i] || !c->node_buf[i] || !c->nodep_buf[i]) + return AVERROR(ENOMEM); + } + } } ff_g722dsp_init(&c->dsp); return 0; -error: - g722_encode_close(avctx); - return ret; } static const int16_t low_quant[33] = { @@ -387,4 +380,5 @@ .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, 0 }, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/g723_1.c ffmpeg-4.4/libavcodec/g723_1.c --- ffmpeg-4.2.2/libavcodec/g723_1.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/g723_1.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,1077 @@ #include "celp_math.h" #include "g723_1.h" +const int16_t ff_g723_1_cos_tab[COS_TBL_SIZE + 1] = { + 16384, 16383, 16379, 16373, 16364, 16353, 16340, 16324, + 16305, 16284, 16261, 16235, 16207, 16176, 16143, 16107, + 16069, 16029, 15986, 15941, 15893, 15843, 15791, 15736, + 15679, 15619, 15557, 15493, 15426, 15357, 15286, 15213, + 15137, 15059, 14978, 14896, 14811, 14724, 14635, 14543, + 14449, 14354, 14256, 14155, 14053, 13949, 13842, 13733, + 13623, 13510, 13395, 13279, 13160, 13039, 12916, 12792, + 12665, 12537, 12406, 12274, 12140, 12004, 11866, 11727, + 11585, 11442, 11297, 11151, 11003, 10853, 10702, 10549, + 10394, 10238, 10080, 9921, 9760, 9598, 9434, 9269, + 9102, 8935, 8765, 8595, 8423, 8250, 8076, 7900, + 7723, 7545, 7366, 7186, 7005, 6823, 6639, 6455, + 6270, 6084, 5897, 5708, 5520, 5330, 5139, 4948, + 4756, 4563, 4370, 4176, 3981, 3786, 3590, 3393, + 3196, 2999, 2801, 2603, 2404, 2205, 2006, 1806, + 1606, 1406, 1205, 1005, 804, 603, 402, 201, + 0, -201, -402, -603, -804, -1005, -1205, -1406, + -1606, -1806, -2006, -2205, -2404, -2603, -2801, -2999, + -3196, -3393, -3590, -3786, -3981, -4176, -4370, -4563, + -4756, -4948, -5139, -5330, -5520, -5708, -5897, -6084, + -6270, -6455, -6639, -6823, -7005, -7186, -7366, -7545, + -7723, -7900, -8076, -8250, -8423, -8595, -8765, -8935, + -9102, -9269, -9434, -9598, -9760, -9921, -10080, -10238, + -10394, -10549, -10702, -10853, -11003, -11151, -11297, -11442, + -11585, -11727, -11866, -12004, -12140, -12274, -12406, -12537, + -12665, -12792, -12916, -13039, -13160, -13279, -13395, -13510, + -13623, -13733, -13842, -13949, -14053, -14155, -14256, -14354, + -14449, -14543, -14635, -14724, -14811, -14896, -14978, -15059, + -15137, -15213, -15286, -15357, -15426, -15493, -15557, -15619, + -15679, -15736, -15791, -15843, -15893, -15941, -15986, -16029, + -16069, -16107, -16143, -16176, -16207, -16235, -16261, -16284, + -16305, -16324, -16340, -16353, -16364, -16373, -16379, -16383, + -16384, -16383, -16379, -16373, -16364, -16353, -16340, -16324, + -16305, -16284, -16261, -16235, -16207, -16176, -16143, -16107, + -16069, -16029, -15986, -15941, -15893, -15843, -15791, -15736, + -15679, -15619, -15557, -15493, -15426, -15357, -15286, -15213, + -15137, -15059, -14978, -14896, -14811, -14724, -14635, -14543, + -14449, -14354, -14256, -14155, -14053, -13949, -13842, -13733, + -13623, -13510, -13395, -13279, -13160, -13039, -12916, -12792, + -12665, -12537, -12406, -12274, -12140, -12004, -11866, -11727, + -11585, -11442, -11297, -11151, -11003, -10853, -10702, -10549, + -10394, -10238, -10080, -9921, -9760, -9598, -9434, -9269, + -9102, -8935, -8765, -8595, -8423, -8250, -8076, -7900, + -7723, -7545, -7366, -7186, -7005, -6823, -6639, -6455, + -6270, -6084, -5897, -5708, -5520, -5330, -5139, -4948, + -4756, -4563, -4370, -4176, -3981, -3786, -3590, -3393, + -3196, -2999, -2801, -2603, -2404, -2205, -2006, -1806, + -1606, -1406, -1205, -1005, -804, -603, -402, -201, + 0, 201, 402, 603, 804, 1005, 1205, 1406, + 1606, 1806, 2006, 2205, 2404, 2603, 2801, 2999, + 3196, 3393, 3590, 3786, 3981, 4176, 4370, 4563, + 4756, 4948, 5139, 5330, 5520, 5708, 5897, 6084, + 6270, 6455, 6639, 6823, 7005, 7186, 7366, 7545, + 7723, 7900, 8076, 8250, 8423, 8595, 8765, 8935, + 9102, 9269, 9434, 9598, 9760, 9921, 10080, 10238, + 10394, 10549, 10702, 10853, 11003, 11151, 11297, 11442, + 11585, 11727, 11866, 12004, 12140, 12274, 12406, 12537, + 12665, 12792, 12916, 13039, 13160, 13279, 13395, 13510, + 13623, 13733, 13842, 13949, 14053, 14155, 14256, 14354, + 14449, 14543, 14635, 14724, 14811, 14896, 14978, 15059, + 15137, 15213, 15286, 15357, 15426, 15493, 15557, 15619, + 15679, 15736, 15791, 15843, 15893, 15941, 15986, 16029, + 16069, 16107, 16143, 16176, 16207, 16235, 16261, 16284, + 16305, 16324, 16340, 16353, 16364, 16373, 16379, 16383, + 16384 +}; + +const int16_t ff_g723_1_lsp_band0[LSP_CB_SIZE][3] = { + { 0, 0, 0}, { -270, -1372, -1032}, { -541, -1650, -1382}, + { -723, -2011, -2213}, { -941, -1122, -1942}, { -780, -1145, -2454}, + { -884, -1309, -1373}, {-1051, -1523, -1766}, {-1083, -1622, -2300}, + { -777, -1377, -2147}, { -935, -1467, -2763}, { -802, -1327, -3471}, + { -935, -1959, -3999}, { -240, -89, 222}, { -661, -257, -160}, + { -994, -466, -419}, { -188, -164, -278}, { -342, -512, -415}, + { -607, -511, -797}, { 16, 19, -716}, { 374, 425, -972}, + { -346, 245, -282}, { -265, 506, -754}, { -620, -147, 1955}, + { -742, -860, 2597}, { -150, -352, 2704}, { 305, 880, 1954}, + { 123, 731, 2766}, { -348, 765, 3327}, { 618, 221, 3258}, + { -178, -47, 4219}, { 393, 1304, 3842}, { 698, 1702, 4801}, + { 63, -584, 1229}, { -215, -732, 1704}, { 172, -335, 1909}, + { -2, 216, 1797}, { 353, 127, 2205}, {-1208, 188, 11}, + { -513, -75, -683}, { -973, 222, -646}, { -616, -843, -388}, + { -950, -1113, -359}, {-1431, -623, -705}, {-1398, -1063, -178}, + { -45, -461, 35}, { -9, -657, -216}, { 127, -1078, 95}, + { -950, -1156, 584}, {-1480, -1494, 449}, { -120, -705, 516}, + { -368, -961, 727}, { -378, -526, 973}, { -793, -614, 676}, + { -801, -755, 1287}, {-1476, -340, 1636}, { -505, -1254, 1543}, + {-1243, -1622, 1532}, { -776, -1477, -655}, {-1151, -1296, -823}, + {-1153, -1672, -1124}, {-1291, -2003, -1702}, { -622, -1283, 57}, + { -471, -1611, 509}, {-1060, -1570, -139}, { -873, -2156, -536}, + {-1716, -2021, -364}, {-2150, -3218, -1291}, {-1248, -1945, -2904}, + {-1215, -2633, -2855}, { 167, -244, 84}, { 349, -412, -217}, + { -40, -352, 632}, { 227, -529, 405}, { 68, -383, -443}, + { 167, -558, -706}, { -275, -854, -14}, { -351, -1089, -449}, + { 341, -72, -289}, { 603, -106, -474}, { 322, -219, -649}, + { 179, -317, -998}, { 450, -291, -996}, { 555, 195, -525}, + { 784, 272, -831}, { -148, -384, -849}, { 82, -536, -1357}, + { 238, -172, -1354}, { 422, -268, -1841}, { 297, -737, -2079}, + { -111, -801, -598}, { 1, -668, -984}, { -131, -818, -1299}, + { -329, -521, -1310}, { -151, -778, -1834}, { -93, -352, -1746}, + { -568, -640, -1821}, { -509, -941, -2183}, { 464, -815, -1250}, + { 79, -1133, -1597}, { -184, -1353, -2123}, { -196, -410, -2427}, + { -192, -833, -2810}, { -259, -1382, -3045}, { -217, 4, -1166}, + { -800, -325, -1219}, { -363, -830, -898}, { -661, -1134, -960}, + { -386, -980, -1501}, { -627, -1159, -1722}, { -903, -829, -855}, + { -685, -829, -1313}, {-1065, -959, -1405}, { 441, 25, -847}, + { 655, -27, -1181}, { 1159, -110, -705}, { 856, 253, -1671}, + { 415, 404, -1}, { 322, 903, -398}, { 670, 499, -292}, + { 803, 591, -610}, { 1144, 591, -814}, { 717, 183, 393}, + { 857, 381, 106}, { 609, 62, -27}, { 792, 198, -325}, + { 735, 805, 88}, { 1142, 812, 78}, { 1028, 366, -292}, + { 1309, 743, -237}, { 1615, 589, -79}, { 1010, 639, -243}, + { 999, 964, -311}, { 1500, 1137, -615}, { 988, 357, 646}, + { 1227, 667, 683}, { 1164, 1565, 894}, { 1392, 2015, 477}, + { 1138, 533, 250}, { 1437, 896, 391}, { 1765, 1118, 99}, + { 1112, 1090, 802}, { 1596, 846, 1134}, { 937, 1161, 279}, + { 1719, 1254, 683}, { 1338, 1086, 35}, { 1419, 1324, 428}, + { 1428, 1524, 40}, { 2108, 1594, 89}, { 1015, 544, 1222}, + { 1121, 925, 1263}, { 1030, 1318, 1485}, { 1295, 789, 1817}, + { 1323, 1272, 1909}, { 1724, 1237, 1803}, { 1797, 1689, 858}, + { 2149, 1367, 1301}, { 2302, 1867, 761}, { 2863, 2351, 1053}, + { 52, 163, -76}, { 230, 309, -492}, { -71, 619, 39}, + { -218, 856, 499}, { -654, 736, -207}, { -535, 1259, 155}, + { -480, 1476, 643}, { 262, 1081, 102}, { 309, 1592, -182}, + { 627, 1629, 534}, { 337, 643, 456}, { 758, 670, 713}, + { 202, 1126, 658}, { 612, 1131, 666}, { 686, 1223, 1136}, + { -131, 377, 525}, { 42, 708, 907}, { 87, 1488, 1035}, + { 432, 2117, 904}, { 137, 981, 1332}, { -447, 1014, 1136}, + { -839, 1793, 1246}, { -559, 297, 198}, { -850, 685, 446}, + {-1273, 632, 826}, { -401, -544, 173}, { -753, -793, 144}, + { -436, -9, 772}, { -115, -243, 1310}, { -670, -269, 374}, + {-1027, -13, 639}, { -887, -81, 1137}, {-1277, -455, 158}, + {-1411, -720, 736}, { 172, 88, 403}, { 386, 255, 756}, + { -500, 522, 910}, { -958, 659, 1388}, { -395, 301, 1344}, + { -356, 768, 1813}, { -613, 841, 2419}, { 445, -122, 252}, + { 629, -87, 723}, { 283, -253, 870}, { 456, -116, 1381}, + { 757, 180, 1059}, { 532, 408, 1509}, { 947, 288, 1806}, + { 1325, 994, 2524}, { 892, 1219, 3023}, { 1397, 1596, 3406}, + { 1143, 1552, 2546}, { 1850, 1433, 2710}, { -10, 134, 1002}, + { 154, 499, 1323}, { 508, 792, 1117}, { 509, 1340, 1616}, + { 762, 862, 1608}, { 787, 740, 2320}, { 794, 1727, 1283}, + { 465, 2108, 1660}, { -120, 1451, 1613}, { -386, 2016, 2169}, + { 891, 1225, 2050}, { 456, 1480, 2185}, { 1493, 1283, 1209}, + { 1397, 1636, 1518}, { 1776, 1738, 1552}, { 1572, 1698, 2141}, + { 1389, 2126, 1271}, { 1959, 2413, 1119}, { 1365, 2892, 1505}, + { 2206, 1971, 1623}, { 2076, 1950, 2280}, { 1717, 2291, 1867}, + { 2366, 2515, 1953}, { 2865, 2838, 2522}, { 2535, 3465, 2011}, + { 3381, 4127, 2638}, { 836, 2667, 2289}, { 1761, 2773, 2337}, + { 1415, 3325, 2911}, { 2354, 3138, 3126}, { 2659, 4192, 4010}, + { 1048, 1786, 1818}, { 1242, 2111, 2240}, { 1512, 2079, 2780}, + { 1573, 2491, 3138}, { 2230, 2377, 2782}, { 416, 1773, 2704}, + { 725, 2336, 3297}, { 1252, 2373, 3978}, { 2094, 2268, 3568}, + { 2011, 2712, 4528}, { 1341, 3507, 3876}, { 1216, 3919, 4922}, + { 1693, 4793, 6012} +}; + +const int16_t ff_g723_1_lsp_band1[LSP_CB_SIZE][3] = { + { 0, 0, 0}, {-2114, -1302, 76}, {-2652, -1278, -1368}, + {-2847, -828, -349}, {-3812, -2190, -349}, {-3946, -364, -449}, + {-2725, -4492, -3607}, {-3495, -4764, -1744}, { -51, -756, 84}, + { -153, -1191, 504}, { 108, -1418, 1167}, { -835, -896, 390}, + { -569, -1702, 87}, {-1151, -1818, 933}, {-1826, -2547, 411}, + {-1842, -1818, 1451}, {-2438, -1611, 781}, {-2747, -2477, 1311}, + { -940, 1252, 477}, {-1629, 1688, 602}, {-1202, 617, 280}, + {-1737, 393, 580}, {-1528, 1077, 1199}, {-2165, -161, 1408}, + {-2504, -1087, 2371}, {-3458, -175, 1395}, {-1397, -98, -843}, + {-2252, -177, -1149}, {-1489, -726, -1283}, {-1558, -265, -1744}, + {-1867, -821, -1897}, {-2062, -1516, -2340}, {-2595, -1142, -2861}, + { 170, 46, -819}, { -193, -204, -1151}, { 326, -196, -1532}, + { 780, 329, -816}, { 201, 369, -1243}, { 650, -209, -1060}, + { 1144, -15, -1216}, { 1203, -259, -1867}, { -890, -564, -1430}, + { -638, -852, -1921}, { 177, -739, -1358}, { -261, -526, -1666}, + { 206, -407, -2255}, { 338, -526, -822}, { 421, -1095, -1009}, + { 765, -607, -1408}, { 825, -1295, -2004}, { 357, -905, -1815}, + { -58, -1248, -1588}, { -596, -1436, -2046}, { -73, -1159, -2116}, + { -115, -1382, -2581}, { -160, -1723, -1952}, { -6, -2196, -2954}, + { -649, -1705, -2603}, { -617, -1453, -3282}, { -949, -2019, -3102}, + { -812, 1544, 1937}, {-1854, 574, 2000}, {-1463, 1140, 2649}, + {-2683, 1748, 1452}, {-2486, 2241, 2523}, { 783, 1910, 1435}, + { 581, 2682, 1376}, { 236, 2197, 1885}, { -453, 2943, 2057}, + { -682, 2178, 2565}, {-1342, 3201, 3328}, { -288, -184, 262}, + { 121, -149, -183}, { 758, -412, 206}, { 1038, -204, 853}, + { 1577, -457, 700}, { 937, -640, -567}, { 1508, -528, -1024}, + { -225, -527, -427}, { -564, -1095, -332}, { -742, -353, -186}, + {-1288, -459, 84}, {-1853, -484, -274}, {-1554, -731, 825}, + {-2425, -234, 382}, {-1722, 293, -271}, {-2515, 425, -564}, + {-2599, 818, 464}, { -358, 118, -375}, { -613, 198, -874}, + { -690, 683, -324}, {-1352, 1155, -168}, {-1093, 129, -324}, + {-1184, 611, -858}, { 433, 386, -372}, { -120, 486, -634}, + { 234, 851, -631}, { 602, 128, 46}, { 1099, 410, 159}, + { 715, -145, -424}, { 1198, -85, -593}, { 1390, 367, -358}, + { 1683, 362, -964}, { 1711, 622, 45}, { 2033, 833, -383}, + { 2890, 549, -506}, { 7, 401, 52}, { 72, 811, 415}, + { 566, 668, 41}, { 467, 1218, 130}, { 68, 957, -187}, + { -25, 1649, -103}, { -661, 260, 214}, { -925, -94, 612}, + { -321, -422, 965}, { -788, -672, 1783}, { 400, -673, 779}, + { 741, -595, 1635}, { -161, 307, 657}, { -382, 836, 871}, + { -814, 400, 1223}, { 364, 606, 1247}, { 57, 75, 1571}, + { 151, 471, 2287}, { -81, 1021, 1502}, { 227, 1470, 1097}, + { 658, 1275, 1653}, { 664, 1478, 2377}, { 263, -127, 444}, + { 264, 89, 969}, { 794, 171, 576}, { 821, 186, 1226}, + { 404, 462, 517}, { 339, 918, 794}, { 1280, 1423, 196}, + { 1453, 2019, 365}, { 1615, 1481, 672}, { 2394, 1708, 508}, + { 806, 1238, 573}, { 713, 1158, 1078}, { 1285, 1436, 1232}, + { 1790, 1188, 1141}, { 765, 643, 864}, { 1032, 797, 1279}, + { 900, 563, 1827}, { 1514, 673, 2312}, { 1544, 1129, 3240}, + { 1469, 1050, 1594}, { 1945, 1318, 1988}, { 2397, 2026, 2060}, + { 3538, 2057, 2620}, { 1249, -118, 74}, { 1727, 194, 421}, + { 2078, -50, -463}, { 970, 688, -432}, { 1149, 952, -110}, + { 1254, 1275, -651}, { 1386, 929, 401}, { 1960, 1167, 232}, + { 407, -752, -243}, { 859, -1118, 172}, { -227, -860, -992}, + { -796, -1175, -1380}, { 8, -1282, -388}, { 353, -1781, -1037}, + { -732, -397, -807}, { -853, -28, -1342}, {-1229, -1207, -1959}, + {-1015, -1125, -2543}, {-1452, -1791, -2725}, {-1891, -2416, -3269}, + { -918, -1629, -783}, { -580, -2155, -698}, {-1097, -2364, -96}, + {-1387, -1513, 7}, {-1588, -2076, -664}, {-1473, -2740, -784}, + {-2378, -3149, -56}, {-2856, -2092, -169}, {-3391, -3708, 316}, + {-1176, -890, -614}, {-1944, -1061, -800}, { -299, -1517, -1000}, + { -640, -1850, -1526}, {-1454, -1536, -1233}, {-1890, -1955, -1756}, + {-1086, -1921, -2122}, { -750, -2325, -2260}, {-1325, -2413, -2673}, + {-1114, -2542, -3459}, {-1341, -2901, -3963}, {-1160, -2226, -1393}, + {-1001, -2772, -1573}, {-1594, -2641, -1978}, {-1534, -3046, -2624}, + {-2224, -2196, -675}, {-2807, -3054, -1102}, {-2008, -2840, -1186}, + {-1980, -3332, -1695}, {-1715, -3562, -505}, {-2527, -4000, -1887}, + {-2333, -2734, -2296}, {-3440, -2401, -3211}, {-2008, -3528, -3337}, + {-2247, -3291, -4510}, { -475, 949, 155}, { -149, 1365, 545}, + { -757, 1644, 1083}, { -217, 2053, 1353}, {-1433, 2301, 1462}, + { 495, 1661, 529}, { 10, 2037, 740}, { 2082, 1898, 978}, + { 2831, 2294, 911}, { 842, 793, 420}, { 1223, 1023, 863}, + { 1237, 451, 780}, { 1744, 708, 822}, { 1533, 284, 1384}, + { 2135, 609, 1538}, { 2305, 626, 540}, { 2368, 1187, 955}, + { 2586, 1255, -7}, { 3116, 1131, 726}, { 3431, 1730, 428}, + { 2734, 1648, 1307}, { 2988, 1231, 2010}, { 3523, 2024, 1488}, + { 1034, 1657, 871}, { 1206, 2163, 1036}, { 1807, 2372, 1233}, + { 1808, 1769, 1493}, { 1573, 2332, 1779}, { 1216, 1609, 1866}, + { 1480, 1898, 2513}, { 465, 2708, 2776}, { 771, 3638, 3338}, + { 1869, 2599, 2623}, { 2825, 2745, 2468}, { 2638, 2439, 1585}, + { 2094, 2970, 1308}, { 2022, 3057, 1999}, { 3428, 2912, 1816}, + { 4536, 2974, 2129}, { 1046, 2563, 2086}, { 1363, 3562, 2318}, + { 2511, 1891, 2984}, { 1866, 2306, 3986}, { 3272, 2924, 3682}, + { 3146, 3564, 2272}, { 3592, 3968, 2822}, { 2431, 3369, 3069}, + { 1931, 4709, 3090}, { 2629, 4220, 3986}, { 4639, 4056, 3664}, + { 4035, 5334, 4912} +}; + +const int16_t ff_g723_1_lsp_band2[LSP_CB_SIZE][4] = { + { 0, 0, 0, 0}, { 601, 512, -542, 334}, + { 428, 1087, -484, -132}, { 652, 622, -391, -572}, + { 378, 799, 141, -860}, { 1040, 409, 112, -554}, + { 1123, 670, -75, -847}, { 1421, 494, -315, -1095}, + { 787, 1001, 114, -460}, { 988, 1672, 216, -681}, + { 1007, 1241, -132, -1247}, { 1073, 399, 186, -5}, + { 1262, 193, -694, -129}, { 325, 196, 51, -641}, + { 861, -59, 350, -458}, { 1261, 567, 586, -346}, + { 1532, 885, 210, -517}, { 2027, 937, 113, -792}, + { 1383, 1064, 334, 38}, { 1964, 1468, 459, 133}, + { 2062, 1186, -98, -121}, { 2577, 1445, 506, -373}, + { 2310, 1682, -2, -960}, { 2876, 1939, 765, 138}, + { 3581, 2360, 649, -414}, { 219, 176, -398, -309}, + { 434, -78, -435, -880}, { -344, 301, 265, -552}, + { -915, 470, 657, -380}, { 419, -432, -163, -453}, + { 351, -953, 8, -562}, { 789, -43, 20, -958}, + { 302, -594, -352, -1159}, { 1040, 108, -668, -924}, + { 1333, 210, -1217, -1663}, { 483, 589, -350, -1140}, + { 1003, 824, -802, -1184}, { 745, 58, -589, -1443}, + { 346, 247, -915, -1683}, { 270, 796, -720, -2043}, + { 1208, 722, -222, -193}, { 1486, 1180, -412, -672}, + { 1722, 179, -69, -521}, { 2047, 860, -666, -1410}, + { -146, 222, -281, -805}, { -189, 90, -114, -1307}, + { -152, 1086, -241, -764}, { -439, 733, -601, -1302}, + { -833, -167, -351, -601}, { -856, -422, -411, -1059}, + { -747, -355, -582, -1644}, { -837, 210, -916, -1144}, + {-1800, 32, -878, -1687}, { -48, -23, -1146, 52}, + { -350, -409, -1656, -364}, { 265, -728, -858, -577}, + { 458, -247, -1141, -997}, { 691, -407, -1988, -1161}, + { -66, -104, -705, -1249}, { -431, -93, -1191, -1844}, + { 203, -732, -1000, -1693}, { 10, -832, -1846, -1819}, + { 493, -128, -1436, -1768}, { 488, -311, -1730, -2540}, + { -653, -532, -1150, -1172}, {-1086, -289, -1706, -1533}, + { -699, -1205, -1216, -1766}, {-1032, -1481, -2074, -1523}, + { -721, -1220, -2277, -2600}, { 12, -539, -1484, -1131}, + { -40, -911, -2106, -441}, { -471, -484, -2267, -1549}, + { -141, -988, -3006, -1721}, {-1545, -2102, -583, 342}, + {-1383, -2772, -386, -13}, {-2118, -2589, -1205, 72}, + {-2147, -3231, -965, 390}, {-2949, -3300, -621, 637}, + {-3907, -4138, -865, 803}, {-1287, -845, -375, -548}, + {-1416, -1169, -487, -1277}, {-1400, -1690, -1027, -418}, + {-2018, -1909, -1188, -1260}, {-1418, -2222, -2029, -128}, + {-2067, -2998, -2693, -310}, { -950, -1028, -1538, 185}, + {-1616, -915, -2205, -549}, { 19, -821, -1145, 352}, + { 184, -1175, -1356, -627}, { -547, -1088, -1661, -911}, + { -216, -1502, -2197, -948}, { -795, -1306, -2374, -451}, + { -924, -1889, -2796, -680}, { -600, -1614, -3609, -885}, + {-2392, -2528, 319, 303}, {-2908, -2095, -310, 573}, + {-3460, -2141, 49, -113}, {-2231, -448, 675, -146}, + {-2805, -532, 1231, 479}, {-2684, -486, -200, 611}, + {-3525, -971, -198, 704}, {-3707, 173, 349, 254}, + {-4734, -1447, -34, 880}, { 777, -512, 114, -10}, + { 1250, -66, 442, -5}, { 604, 613, 452, -352}, + { 1224, 777, 675, -1014}, {-1372, -79, -1208, -238}, + {-2389, -17, -1157, -818}, {-1504, -673, -1133, -1060}, + {-1984, -799, -2005, -1973}, {-2037, -798, -1068, -105}, + {-3190, -899, -1817, -194}, { -156, -886, 394, -318}, + { -258, -1283, 551, 202}, { -536, -1729, 910, 331}, + { -847, -1109, 795, -163}, {-1171, -1128, 715, 519}, + {-1080, -1319, 1685, 668}, {-1000, -1921, 96, 211}, + {-1487, -2148, 831, 174}, {-1139, -374, 414, -4}, + {-1517, -1383, 396, -352}, {-1012, 439, -59, -967}, + {-1812, 706, -440, -1030}, {-1971, -329, -34, -827}, + {-2472, -1588, -151, -606}, {-2161, 374, -281, 76}, + {-3012, 231, -15, -690}, { 1104, 566, 721, 209}, + { 1685, 564, 383, 98}, { 1898, 750, 792, -97}, + { 556, -64, 561, -93}, { 876, 162, 913, -22}, + { 961, 675, 1296, 140}, { 756, -396, 851, 544}, + { 360, -303, 1341, 396}, { 878, -22, 1464, 863}, + { -309, -273, 642, -129}, { -686, -82, 842, 454}, + { -5, -47, 1069, 998}, { -94, 967, 1277, 298}, + { -489, 385, 1473, 746}, { -369, -717, 1333, 242}, + { 281, -993, 1726, 924}, { 464, 601, 1575, 1376}, + { -250, 206, 2339, 1175}, { -438, 377, -597, -285}, + {-1020, 787, -790, -287}, { -458, -410, 215, 295}, + { -589, -860, -121, 797}, {-1175, 122, -437, 466}, + {-1480, -121, 367, 924}, { 234, 323, 770, -555}, + { 145, 30, 996, 26}, { 66, 849, 93, -145}, + { -117, 1261, 474, -399}, {-1495, 1051, 218, -506}, + {-1390, 694, 994, 88}, { 616, 7, 78, 304}, + { 1060, 52, -62, 835}, { 833, 454, 649, 1359}, + { -770, 464, 47, 93}, { -574, 1199, -39, 379}, + { 114, -98, 488, 485}, { 727, 244, 606, 696}, + { -76, 455, 671, 546}, { -565, -13, 145, 819}, + { -376, 569, 448, 1128}, { 218, 122, 265, 1167}, + { 230, 738, 932, 1003}, { 138, 477, 36, 450}, + { 404, 787, -73, 1000}, { 497, 1259, 387, 1231}, + { 17, 207, 195, -79}, { 562, 358, 53, -158}, + { 493, 387, 478, 189}, { 678, 831, 640, 558}, + { -197, 523, 613, 57}, { 429, 894, 769, 111}, + { 67, 1174, 568, 511}, { 1242, 824, 251, 840}, + { 1419, 1074, 864, 481}, { 924, 1474, 669, 724}, + { 1539, 1879, 654, 1590}, { 445, 337, 1111, 541}, + { 472, 1421, 1264, 1094}, { 794, 735, 1103, 668}, + { 1055, 863, 1192, 1020}, { 778, 1105, 806, 1798}, + { 1052, 1527, 1587, 2151}, { 881, 1552, 1265, 391}, + { 726, 872, 1812, 601}, { 1469, 280, 1008, 616}, + { 1403, 577, 1803, 1244}, { 1650, 1314, 1148, 1072}, + { 1297, 1669, 1911, 1026}, { 2093, 1044, 2115, 1189}, + { 1644, 1961, 2587, 1512}, { 25, -315, -9, -106}, + { 290, -339, 428, -444}, { -68, -783, 735, 772}, + { 245, -555, 468, 47}, { 334, -895, 814, 146}, + { 235, 368, -964, -959}, { -203, 315, -1566, -1217}, + { 801, 17, -276, -354}, { 894, -495, -789, -635}, + { 716, 291, -1189, -357}, { 560, -260, -733, -2}, + { 679, -508, -1429, 211}, { -51, -62, -428, 557}, + { 322, -638, -211, 614}, { -878, -1057, -84, -71}, + { -388, -1415, -167, -318}, { -754, -1574, 214, -539}, + {-1419, -2004, -92, -787}, { -47, -856, -347, -255}, + { 23, -1211, -173, 320}, { -658, -487, -893, 353}, + { -783, -1587, -584, 507}, {-1420, -859, -378, 441}, + {-2095, -1491, -137, 439}, { -321, -1450, -1288, -12}, + { -359, -2113, -553, -8}, { -831, -1918, -1561, 32}, + {-1014, -2487, -1359, -939}, { -475, -311, -169, -236}, + { -907, -426, 276, -611}, { -96, -400, 50, -710}, + { -426, -1022, -10, -985}, { -197, -258, -744, -575}, + { -611, -930, -771, -394}, { -267, -776, -612, -939}, + { -256, -1346, -802, -1122}, { -796, -1570, -825, -754}, + { 712, 876, 141, 227}, { 981, 1509, 85, 124}, + { 1462, 1228, 979, -39}, { 1734, 999, 1481, 440}, + { 2293, 1116, 769, 440}, { 2504, 1480, 1241, 356}, + { 2474, 1909, 1558, 810}, { 917, 1134, 607, -134}, + { 509, 1809, 781, -123}, { 1712, 1506, 559, -423}, + { 2037, 2317, 726, -155}, { 3031, 2676, 1203, 331}, + { 3664, 3274, 1768, 531}, { 1610, 1839, 867, 183}, + { 1774, 1972, 1538, 97}, { 1822, 2158, 1282, 659}, + { 2222, 2758, 1818, 900}, { 3251, 2124, 1723, 996}, + { 3633, 2336, 2408, 1453}, { 2923, 3517, 2567, 1318}, +}; + +const int32_t ff_g723_1_combinatorial_table[PULSE_MAX][SUBFRAME_LEN/GRID_SIZE] = { + {118755, 98280, 80730, 65780, 53130, + 42504, 33649, 26334, 20349, 15504, + 11628, 8568, 6188, 4368, 3003, + 2002, 1287, 792, 462, 252, + 126, 56, 21, 6, 1, + 0, 0, 0, 0, 0}, + + { 23751, 20475, 17550, 14950, 12650, + 10626, 8855, 7315, 5985, 4845, + 3876, 3060, 2380, 1820, 1365, + 1001, 715, 495, 330, 210, + 126, 70, 35, 15, 5, + 1, 0, 0, 0, 0}, + + { 3654, 3276, 2925, 2600, 2300, + 2024, 1771, 1540, 1330, 1140, + 969, 816, 680, 560, 455, + 364, 286, 220, 165, 120, + 84, 56, 35, 20, 10, + 4, 1, 0, 0, 0}, + + { 406, 378, 351, 325, 300, + 276, 253, 231, 210, 190, + 171, 153, 136, 120, 105, + 91, 78, 66, 55, 45, + 36, 28, 21, 15, 10, + 6, 3, 1, 0, 0}, + + { 29, 28, 27, 26, 25, + 24, 23, 22, 21, 20, + 19, 18, 17, 16, 15, + 14, 13, 12, 11, 10, + 9, 8, 7, 6, 5, + 4, 3, 2, 1, 0}, + + { 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1}, +}; + +const int16_t ff_g723_1_fixed_cb_gain[GAIN_LEVELS] = { + 1, 2, 3, 4, 6, 9, 13, 18, + 26, 38, 55, 80, 115, 166, 240, 348, + 502, 726, 1050, 1517, 2193, 3170, 4582, 6623, +}; + +const int16_t ff_g723_1_adaptive_cb_gain85[85 * 20] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 800, 1496, 167, -256, + -338, -39, -136, -1, -4, -6, -73, -8, + -15, 12, 23, 2, 16, 30, 3, -5, + -462, -686, 493, 2575, 311, -13, -28, -14, + -404, -5, -19, 13, 20, 72, 107, -77, + 8, 13, -9, -48, 1483, 144, 784, 928, + 1243, -134, -1, -37, -52, -94, -13, -71, + -6, -84, -8, -44, -112, -10, -59, -70, + -77, 275, 3522, 1056, -1254, 0, -4, -757, + -68, -95, 1, 16, -59, 4, -17, -227, + -5, 21, 269, 80, -125, -40, -264, 381, + 5027, 0, 0, -4, -8, -1542, 0, -2, + 0, 2, 0, 6, 38, 12, 81, -117, + 138, 332, 2215, 2574, 1339, -1, -6, -299, + -404, -109, -2, -18, -44, -21, -52, -348, + -11, -27, -181, -210, 3685, 2883, -887, 866, + -1639, -828, -507, -48, -45, -164, -648, 199, + 156, -194, -152, 46, 368, 288, -88, 86, + 1396, 2146, 2235, 345, 942, -118, -281, -305, + -7, -54, -182, -190, -292, -29, -45, -47, + -80, -123, -128, -19, 13, 4475, 3549, -804, + -655, 0, -1222, -768, -39, -26, -3, -2, + -969, 0, 219, 174, 0, 179, 141, -32, + -724, 254, 242, 6049, 2462, -32, -3, -3, + -2233, -370, 11, 10, -3, 267, -94, -89, + 108, -38, -36, -909, 626, -1713, 6121, 4561, + -1061, -23, -179, -2287, -1270, -68, 65, -233, + 640, -174, 477, -1704, 40, -111, 396, 295, + -350, 1391, 7985, 511, -405, -7, -118, -3892, + -15, -10, 29, 170, -678, 10, -43, -249, + -8, 34, 197, 12, 3144, -529, 608, 2530, + 3878, -603, -17, -22, -390, -918, 101, -116, + 19, -485, 81, -93, -744, 125, -144, -599, + 2589, -689, 3045, 5603, -404, -409, -29, -566, + -1916, -10, 108, -481, 128, -885, 235, -1041, + 63, -17, 75, 138, 3107, 513, 1374, -3594, + -4922, -589, -16, -115, -788, -1478, -97, -260, + -43, 681, 112, 301, 933, 154, 413, -1079, + 2468, 6010, 1107, -390, 1961, -372, -2204, -74, + -9, -234, -905, -166, -406, 58, 143, 26, + -295, -719, -132, 46, 4773, 2766, 2368, 4862, + -4044, -1390, -467, -342, -1443, -998, -806, -690, + -399, -1416, -821, -702, 1178, 682, 584, 1200, + 1665, -1879, 1443, 1701, 8562, -169, -215, -127, + -176, -4475, 190, -146, 165, -172, 195, -149, + -870, 982, -754, -889, 2716, 9011, -1007, 755, + -1785, -450, -4956, -61, -34, -194, -1493, 167, + 554, -125, -415, 46, 296, 982, -109, 82, + -2727, 7548, 1285, 938, 3420, -453, -3478, -100, + -53, -714, 1256, 213, -592, 156, -432, -73, + 569, -1576, -268, -196, 3677, 882, 4050, 1202, + 2323, -825, -47, -1001, -88, -329, -198, -909, + -218, -269, -64, -297, -521, -125, -574, -170, + 2046, -753, 122, 10102, 603, -255, -34, 0, + -6229, -22, 94, -15, 5, -1261, 464, -75, + -75, 27, -4, -372, 449, -1815, 10690, 3870, + -527, -12, -201, -6976, -914, -16, 49, -293, + 1184, -106, 428, -2525, 14, -58, 344, 124, + -941, 2352, 5049, 3650, 2637, -54, -337, -1556, + -813, -424, 135, 290, -725, 209, -524, -1125, + 151, -378, -812, -587, -1879, 796, 3117, 9569, + -404, -215, -38, -593, -5589, -9, 91, 357, + -151, 1097, -464, -1821, -46, 19, 76, 236, + -1715, 2043, -2096, 9946, 4001, -179, -254, -268, + -6038, -977, 213, -219, 261, 1041, -1240, 1272, + 418, -498, 511, -2429, -5772, -618, -3921, 284, + -3155, -2033, -23, -938, -4, -607, -218, -1381, + -148, 100, 10, 68, -1111, -119, -755, 54, + 382, 4748, 8003, -2064, 2198, -8, -1376, -3909, + -260, -294, -110, -186, -2319, 48, 598, 1008, + -51, -637, -1073, 277, -867, 3015, 11926, -1675, + 947, -45, -555, -8681, -171, -54, 159, 631, + -2195, -88, 308, 1219, 50, -174, -690, 96, + -4933, -432, 6757, 3771, 1352, -1485, -11, -2786, + -867, -111, -130, 2034, 178, 1135, 99, -1555, + 407, 35, -557, -311, 152, 9726, 4231, -1928, + 1490, -1, -5774, -1092, -226, -135, -90, -39, + -2511, 17, 1144, 498, -13, -884, -384, 175, + 2512, 193, 9033, 5361, -3148, -385, -2, -4980, + -1754, -605, -29, -1385, -106, -822, -63, -2956, + 482, 37, 1735, 1030, 8464, 2844, 12, 549, + 2132, -4373, -493, 0, -18, -277, -1469, -6, + -2, -284, -95, 0, -1101, -370, -1, -71, + 2141, -2602, 7166, 9046, -1350, -279, -413, -3134, + -4994, -111, 340, -936, 1138, -1182, 1436, -3957, + 176, -214, 590, 745, -244, 278, 13307, 1227, + -161, -3, -4, -10808, -91, -1, 4, 198, + -226, 18, -20, -997, -2, 2, 131, 12, + -1947, 8217, 6269, 917, -2559, -231, -4121, -2399, + -51, -399, 976, 745, -3144, 108, -460, -350, + -304, 1283, 979, 143, -1810, 2061, -2781, 6056, + 10058, -200, -259, -472, -2238, -6174, 227, -307, + 349, 669, -761, 1028, 1111, -1265, 1707, -3717, + 7827, 9161, -3409, 2473, -1510, -3739, -5122, -709, + -373, -139, -4376, 1628, 1906, -1181, -1382, 514, + 721, 844, -314, 228, -1430, 8313, 9541, -2955, + 1626, -124, -4218, -5556, -533, -161, 725, 832, + -4841, -257, 1499, 1721, 142, -825, -947, 293, + 2819, -4247, 5391, 8673, 2756, -485, -1101, -1774, + -4591, -463, 730, -927, 1397, -1492, 2248, -2854, + -474, 714, -907, -1459, 141, 14552, 690, 257, + -112, -1, -12926, -29, -4, 0, -125, -5, + -613, -2, -228, -10, 0, 99, 4, 1, + 11938, -1859, 1806, -962, -884, -8699, -211, -199, + -56, -47, 1355, -1316, 205, 701, -109, 106, + 644, -100, 97, -51, 3728, 1982, 2264, 4584, + 3131, -848, -239, -312, -1282, -598, -451, -515, + -273, -1043, -554, -633, -712, -378, -432, -876, + -1181, 766, 720, 14303, -216, -85, -35, -31, + -12486, -2, 55, 51, -33, 1031, -668, -628, + -15, 10, 9, 189, -4385, 4826, 10112, 1569, + 3388, -1173, -1421, -6242, -150, -700, 1291, 2706, + -2979, 420, -462, -969, 906, -998, -2091, -324, + -448, 1932, 15591, -1842, 657, -12, -227, -14837, + -207, -26, 52, 427, -1838, -50, 217, 1753, + 18, -77, -626, 74, -4141, 1844, 3962, 5517, + 6220, -1046, -207, -958, -1858, -2361, 466, 1001, + -446, 1394, -621, -1334, 1572, -700, -1504, -2094, + 729, -2299, 14755, 3657, -952, -32, -322, -13288, + -816, -55, 102, -656, 2071, -162, 513, -3294, + 42, -133, 857, 212, -1385, 5801, 13339, -3137, + 1344, -117, -2054, -10861, -600, -110, 490, 1127, + -4723, -265, 1111, 2554, 113, -476, -1094, 257, + 4710, 9661, 1073, -2467, 3274, -1354, -5697, -70, + -371, -654, -2777, -308, -633, 709, 1455, 161, + -941, -1930, -214, 493, 1843, -3624, 12422, 6898, + -1559, -207, -802, -9419, -2904, -148, 407, -1397, + 2748, -775, 1526, -5230, 175, -344, 1182, 656, + 1433, 2394, 2507, 1380, 8780, -125, -349, -383, + -116, -4705, -209, -219, -366, -120, -201, -211, + -768, -1283, -1343, -740, -1712, 12915, 5883, -2197, + 991, -179, -10181, -2112, -294, -60, 1350, 615, + -4638, -229, 1732, 789, 103, -781, -356, 133, + 15072, 2158, -1245, 910, -496, -13865, -284, -94, + -50, -15, -1986, 1145, 164, -837, -119, 69, + 456, 65, -37, 27, 4655, 7319, 4916, 586, + -3381, -1322, -3270, -1475, -20, -697, -2079, -1396, + -2196, -166, -261, -175, 960, 1510, 1014, 120, + 1191, -2140, 5120, 13498, -1418, -86, -279, -1600, + -11121, -122, 155, -372, 669, -981, 1763, -4218, + 103, -185, 443, 1168, -1530, -817, 8191, 9632, + -1452, -143, -40, -4095, -5663, -128, -76, 765, + 408, 900, 480, -4815, -135, -72, 726, 854, + -3236, 607, 1696, -2106, 11485, -639, -22, -175, + -270, -8051, 119, 335, -62, -416, 78, 218, + 2268, -425, -1189, 1476, 3203, -1903, -837, 9679, + 7057, -626, -221, -42, -5718, -3039, 372, 163, + -97, -1892, 1124, 494, -1380, 819, 360, -4169, + 213, -655, 17015, 620, -384, -2, -26, -17671, + -23, -9, 8, -221, 681, -8, 24, -644, + 5, -15, 399, 14, 5088, 35, -3339, 3726, + 8488, -1580, 0, -680, -847, -4397, -10, 1037, + 7, -1157, -8, 759, -2636, -18, 1730, -1930, + -988, 1454, -2688, 15039, 2682, -59, -129, -441, + -13805, -439, 87, -162, 238, 907, -1335, 2467, + 161, -238, 440, -2462, -4865, -2842, -53, 5495, + 6523, -1445, -493, 0, -1843, -2597, -844, -16, + -9, 1632, 953, 18, 1937, 1131, 21, -2188, + 3076, 15069, -2914, 1810, -971, -577, -13860, -518, + -200, -57, -2829, 547, 2680, -339, -1665, 322, + 182, 893, -172, 107, 1311, 5355, 11054, 2299, + -3654, -105, -1750, -7458, -322, -814, -428, -885, + -3613, -184, -751, -1551, 292, 1194, 2465, 512, + 4035, 5619, 4618, 1815, 1912, -994, -1927, -1301, + -201, -223, -1384, -1137, -1583, -447, -622, -511, + -471, -656, -539, -211, -2131, 2754, -4501, 12879, + 7432, -277, -463, -1236, -10124, -3371, 358, -585, + 756, 1675, -2165, 3538, 967, -1249, 2042, -5842, + 5618, -515, 3219, -4149, 4857, -1926, -16, -632, + -1050, -1440, 176, -1104, 101, 1422, -130, 815, + -1666, 152, -954, 1230, 1838, -1709, 1139, 16867, + 716, -206, -178, -79, -17366, -31, 191, -127, + 118, -1892, 1759, -1173, -80, 74, -49, -737, + 1978, -3845, 10050, 11854, -2492, -238, -902, -6164, + -8576, -379, 464, -1213, 2358, -1431, 2782, -7271, + 301, -585, 1529, 1803, -2600, 11246, 11289, -3647, + 1463, -412, -7720, -7778, -812, -130, 1784, 1791, + -7749, -578, 2504, 2513, 232, -1004, -1008, 325, + 3442, 907, 2725, 8970, 3638, -723, -50, -453, + -4911, -808, -190, -572, -150, -1884, -496, -1492, + -764, -201, -605, -1992, -126, 17498, 3481, -2003, + 1090, 0, -18689, -739, -244, -72, 135, 26, + -3717, -15, 2139, 425, 8, -1165, -231, 133, + -1814, 1048, -2164, 4070, 16272, -200, -67, -285, + -1011, -16160, 116, -239, 138, 450, -260, 537, + 1801, -1041, 2149, -4042, 9354, 12580, -1883, 962, + -617, -5341, -9660, -216, -56, -23, -7183, 1075, + 1446, -549, -738, 110, 352, 474, -71, 36, + 1708, 4199, 7387, 6335, 1003, -178, -1076, -3330, + -2449, -61, -437, -770, -1893, -660, -1623, -2856, + -104, -257, -452, -388, -2624, 5623, 17310, -2353, + 592, -420, -1930, -18288, -338, -21, 900, 2772, + -5941, -376, 807, 2486, 94, -203, -625, 85, + 1211, -850, 1193, -1926, 15992, -89, -44, -86, + -226, -15609, 62, -88, 61, 142, -100, 140, + -1182, 830, -1165, 1880, 3983, -2054, 11506, -19, + 3622, -968, -257, -8080, 0, -801, 499, -2797, + 1442, 4, -2, 13, -880, 454, -2544, 4, + -786, -1354, 16092, 7246, -1665, -37, -111, -15805, + -3205, -169, -65, 772, 1330, 348, 599, -7117, + -80, -137, 1636, 736, -4316, -511, 6674, 11665, + 4633, -1137, -15, -2719, -8305, -1310, -134, 1758, + 208, 3073, 364, -4752, 1220, 144, -1887, -3299, + 7912, 4557, 1937, 1885, 7037, -3821, -1267, -229, + -216, -3022, -2200, -935, -538, -910, -524, -222, + -3398, -1957, -832, -809, 3434, 2967, 5867, 8196, + 8766, -720, -537, -2101, -4100, -4690, -622, -1230, + -1062, -1718, -1484, -2935, -1837, -1588, -3139, -4385, + 5881, 9176, 8119, 3934, 3355, -2111, -5139, -4023, + -944, -687, -3294, -2914, -4547, -1412, -2203, -1949, + -1204, -1879, -1662, -805 +}; + +const int16_t ff_g723_1_adaptive_cb_gain170[170 * 20] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 776, 212, 715, 670, + 809, -36, -2, -31, -27, -39, -10, -33, + -9, -31, -8, -29, -38, -10, -35, -33, + 1296, 1316, -168, -320, -815, -102, -105, -1, + -6, -40, -104, 13, 13, 25, 25, -3, + 64, 65, -8, -15, -589, 680, 2478, 308, + -596, -21, -28, -375, -5, -21, 24, 89, + -102, 11, -12, -46, -21, 24, 90, 11, + -735, -487, -5, 2948, 468, -33, -14, 0, + -530, -13, -21, 0, 0, 132, 87, 0, + 21, 13, 0, -84, 1042, 1730, 1068, 333, + 626, -66, -182, -69, -6, -23, -110, -67, + -112, -21, -35, -21, -39, -66, -40, -12, + 486, -769, 4074, 2825, -1107, -14, -36, -1013, + -487, -74, 22, -120, 191, -83, 132, -702, + 32, -52, 275, 191, 1521, -767, -124, 4320, + 1026, -141, -35, 0, -1139, -64, 71, 11, + -5, -401, 202, 32, -95, 48, 7, -270, + 2425, 1267, 3439, -91, -1166, -359, -98, -722, + 0, -83, -187, -509, -266, 13, 7, 19, + 172, 90, 244, -6, -1251, 975, 173, 4039, + 2005, -95, -58, -1, -996, -245, 74, 13, + -10, 308, -240, -42, 153, -119, -21, -494, + 1820, 632, 1322, 2062, 1031, -202, -24, -106, + -259, -64, -70, -146, -51, -229, -79, -166, + -114, -39, -83, -129, -447, 4904, 244, -315, + -2038, -12, -1467, -3, -6, -253, 134, 6, + -73, -8, 94, 4, -55, 610, 30, -39, + -208, -1102, 463, -448, 5653, -2, -74, -13, + -12, -1950, -14, 5, 31, -5, -30, 12, + 71, 380, -159, 154, 4739, 2600, -1864, 856, + -1554, -1371, -412, -212, -44, -147, -752, 539, + 295, -247, -135, 97, 449, 246, -176, 81, + 1894, 3533, 35, -26, 2145, -219, -762, 0, + 0, -280, -408, -4, -7, 3, 5, 0, + -248, -462, -4, 3, -2699, 1841, 4072, 2443, + 1582, -444, -207, -1012, -364, -152, 303, 670, + -457, 402, -274, -607, 260, -177, -393, -236, + -844, 3358, 6106, -1059, -537, -43, -688, -2275, + -68, -17, 173, 314, -1251, -54, 217, 395, + -27, 110, 200, -34, 1251, 1016, 3020, 2210, + 1445, -95, -63, -556, -298, -127, -77, -230, + -187, -168, -137, -407, -110, -89, -266, -194, + 2099, 2277, 4038, 3533, -2870, -269, -316, -995, + -762, -503, -291, -517, -561, -452, -491, -871, + 367, 399, 707, 619, 400, -1114, 8516, 2422, + -1117, -9, -75, -4426, -358, -76, 27, -208, + 579, -59, 164, -1259, 27, -75, 580, 165, + -4398, -2011, 3912, -2407, 2258, -1180, -247, -934, + -353, -311, -540, 1050, 480, -646, -295, 575, + 606, 277, -539, 331, 1767, -1447, 4240, 6160, + -757, -190, -127, -1097, -2316, -35, 156, -457, + 374, -664, 544, -1594, 81, -66, 195, 284, + 1594, -1463, 1035, 6938, 1920, -155, -130, -65, + -2938, -225, 142, -100, 92, -675, 619, -438, + -186, 171, -121, -813, -562, 4716, 4085, -591, + 2421, -19, -1357, -1018, -21, -357, 162, 140, + -1175, -20, 170, 147, 83, -696, -603, 87, + 1552, 8778, -935, 354, -1424, -147, -4703, -53, + -7, -123, -831, 88, 501, -33, -189, 20, + 134, 763, -81, 30, 4831, -4431, 41, -1479, + -2976, -1424, -1198, 0, -133, -540, 1306, -12, + 11, 436, -400, 3, 877, -804, 7, -268, + 2090, 1192, 1006, 1645, 4853, -266, -86, -61, + -165, -1437, -152, -128, -73, -210, -119, -101, + -619, -353, -298, -487, 2386, 5712, 1426, -94, + 1350, -347, -1991, -124, 0, -111, -832, -207, + -497, 13, 32, 8, -196, -470, -117, 7, + -1349, 1091, 1659, 8891, 313, -111, -72, -168, + -4825, -5, 89, 136, -110, 732, -592, -900, + 25, -20, -31, -170, 9980, 916, -381, -808, + 88, -6080, -51, -8, -39, 0, -558, 232, + 21, 492, 45, -18, -53, -4, 2, 4, + 2338, -1031, -248, 3928, 6484, -333, -64, -3, + -942, -2566, 147, 35, -15, -560, 247, 59, + -925, 408, 98, -1555, 6166, -1240, -337, 3672, + -1277, -2320, -93, -6, -823, -99, 466, 126, + -25, -1382, 278, 75, 480, -96, -26, 286, + 4377, -132, -2588, 1701, 4865, -1169, -1, -409, + -176, -1444, 35, 691, -20, -454, 13, 268, + -1299, 39, 768, -505, 2594, 3295, 3944, 1481, + 682, -410, -662, -949, -133, -28, -521, -624, + -793, -234, -297, -356, -108, -137, -164, -61, + 4151, 624, 815, 4485, 2229, -1052, -23, -40, + -1228, -303, -158, -206, -31, -1136, -170, -223, + -565, -84, -111, -610, -3575, -361, 4924, 2791, + 4698, -780, -7, -1480, -475, -1347, -78, 1074, + 108, 609, 61, -839, 1025, 103, -1412, -800, + -2518, 3791, 8623, 315, 2465, -387, -877, -4538, + -6, -370, 582, 1325, -1995, 48, -73, -166, + 378, -570, -1297, -47, -691, 2989, 9957, -421, + -1142, -29, -545, -6051, -10, -79, 126, 420, + -1817, -17, 76, 256, -48, 208, 694, -29, + -1918, 104, -3190, -3410, -4440, -224, 0, -621, + -709, -1203, 12, -373, 20, -399, 21, -664, + -519, 28, -864, -924, -3359, -1668, 1854, 6939, + 1430, -688, -169, -209, -2939, -124, -341, 380, + 188, 1422, 706, -785, 293, 145, -161, -606, + 42, 9706, 3164, -952, 907, 0, -5750, -611, + -55, -50, -25, -8, -1874, 2, 564, 183, + -2, -537, -175, 52, 1607, 785, 2862, 4327, + 3307, -157, -37, -500, -1143, -667, -77, -280, + -137, -424, -207, -756, -324, -158, -577, -873, + 6801, 3416, 2227, 1682, -3217, -2823, -712, -302, + -172, -631, -1418, -924, -464, -698, -350, -228, + 1335, 670, 437, 330, 3459, 3898, 364, 7841, + -2640, -730, -927, -8, -3753, -425, -823, -76, + -86, -1655, -1865, -174, 557, 628, 58, 1263, + -5902, -3458, -2465, -1886, 4334, -2126, -730, -371, + -217, -1146, -1245, -888, -520, -679, -398, -283, + 1561, 915, 652, 499, -3710, 1133, 7849, 3443, + -215, -840, -78, -3760, -723, -2, 256, 1777, + -543, 779, -238, -1649, -48, 14, 103, 45, + 4132, 2828, 2, -4212, -4116, -1042, -488, 0, + -1083, -1034, -713, 0, 0, 1062, 727, 0, + 1038, 710, 0, -1058, 5875, 8496, -1796, 1376, + -1786, -2107, -4406, -197, -115, -194, -3047, 644, + 931, -493, -713, 150, 640, 926, -195, 150, + 3143, 3483, 3546, -793, 4489, -603, -740, -767, + -38, -1230, -668, -680, -754, 152, 168, 171, + -861, -954, -971, 217, 2845, 7965, 3695, -5432, + 3978, -494, -3873, -833, -1801, -966, -1383, -641, + -1796, 943, 2641, 1225, -691, -1934, -897, 1319, + 1538, 150, 7139, 2049, 3097, -144, -1, -3110, + -256, -585, -14, -670, -65, -192, -18, -892, + -290, -28, -1349, -387, 618, 7520, 4729, -238, + -3373, -23, -3452, -1365, -3, -694, -283, -178, + -2170, 8, 109, 68, 127, 1548, 973, -49, + 2965, -3013, 7912, 7076, -1997, -536, -554, -3821, + -3056, -243, 545, -1431, 1455, -1280, 1301, -3417, + 361, -367, 964, 862, 2443, -929, -1113, 9677, + 4138, -364, -52, -75, -5716, -1045, 138, 166, + -63, -1443, 549, 657, -617, 234, 281, -2444, + 1966, 3309, 10085, -3399, 2105, -236, -668, -6207, + -705, -270, -397, -1210, -2037, 408, 686, 2092, + -252, -425, -1295, 436, -112, -1368, 8868, 4822, + 2048, 0, -114, -4800, -1419, -256, -9, 61, + 740, 33, 402, -2610, 14, 171, -1108, -602, + -2597, 438, -1839, 6229, 7266, -411, -11, -206, + -2368, -3223, 69, -291, 49, 987, -166, 699, + 1152, -194, 816, -2763, 3454, 553, 9127, 4946, + -5596, -728, -18, -5084, -1493, -1911, -116, -1924, + -308, -1042, -166, -2755, 1179, 188, 3117, 1689, + -532, -663, 12262, 2495, -1004, -17, -26, -9177, + -380, -61, -21, 398, 496, 81, 101, -1867, + -32, -40, 751, 152, -2100, 1317, -1509, 11425, + 2997, -269, -105, -139, -7967, -548, 168, -193, + 121, 1464, -918, 1052, 384, -240, 276, -2090, + 1193, -2697, 11259, 5373, -763, -86, -444, -7737, + -1762, -35, 196, -819, 1853, -391, 884, -3692, + 55, -125, 525, 250, 2405, -471, 11079, 203, + 782, -353, -13, -7491, -2, -37, 69, -1626, + 318, -29, 5, -137, -114, 22, -529, -9, + -1871, 5685, 11290, -2662, 1353, -213, -1972, -7780, + -432, -111, 649, 1289, -3917, -304, 923, 1834, + 154, -469, -932, 220, -3768, 5927, -3093, 5041, + 5212, -866, -2144, -584, -1551, -1658, 1363, -711, + 1119, 1159, -1824, 951, 1198, -1885, 984, -1603, + -2546, 9502, 5969, -2440, 1928, -395, -5511, -2175, + -363, -226, 1477, 927, -3462, -379, 1415, 889, + 299, -1118, -702, 287, -4963, 3568, 4592, 5508, + 3451, -1503, -777, -1287, -1851, -727, 1080, 1391, + -1000, 1668, -1199, -1543, 1045, -751, -967, -1160, + 1745, -2586, 3983, 10899, -1551, -186, -408, -968, + -7250, -146, 275, -424, 628, -1161, 1720, -2649, + 165, -244, 377, 1032, 867, -456, -727, 3369, + 11822, -45, -12, -32, -692, -8531, 24, 38, + -20, -178, 93, 149, -625, 329, 525, -2431, + 7535, 2422, 1926, 1405, 1599, -3466, -358, -226, + -120, -156, -1114, -886, -284, -646, -207, -165, + -735, -236, -188, -137, 1041, -735, -142, 13209, + 1515, -66, -33, -1, -10649, -140, 46, 9, + -6, -839, 593, 114, -96, 68, 13, -1222, + 7950, 6745, -1444, -1008, 2721, -3857, -2777, -127, + -62, -452, -3273, 700, 594, 489, 415, -88, + -1320, -1120, 239, 167, -4754, -1379, 4522, -578, + -5733, -1379, -116, -1248, -20, -2006, -400, 1312, + 380, -167, -48, 159, -1663, -482, 1582, -202, + 3220, 5978, 5923, 2430, -2689, -633, -2181, -2141, + -360, -441, -1175, -1164, -2161, -477, -886, -878, + 528, 981, 972, 398, 377, 1312, 13978, -1470, + 677, -8, -105, -11925, -132, -28, -30, -321, + -1119, 33, 117, 1254, -15, -54, -577, 60, + -3435, 6770, 314, -885, 5686, -720, -2797, -6, + -47, -1973, 1419, 65, -129, -185, 366, 16, + 1192, -2349, -109, 307, 3171, 8774, -2260, 2679, + 3069, -613, -4699, -312, -438, -575, -1698, 437, + 1210, -518, -1435, 369, -594, -1643, 423, -501, + 5557, 1509, 5407, -125, -7386, -1884, -139, -1784, + 0, -3330, -511, -1834, -498, 42, 11, 41, + 2505, 680, 2438, -56, -2838, 2595, 13228, 271, + 1793, -491, -411, -10680, -4, -196, 449, 2291, + -2095, 47, -42, -219, 310, -284, -1447, -29, + 664, -278, 14966, 951, -711, -26, -4, -13672, + -55, -30, 11, -606, 253, -38, 16, -869, + 28, -12, 650, 41, 808, 1770, 8658, 5863, + -1486, -39, -191, -4576, -2098, -134, -87, -427, + -935, -289, -633, -3098, 73, 160, 785, 531, + 3063, 1539, 2000, -542, 9576, -572, -144, -244, + -17, -5597, -287, -374, -188, 101, 51, 66, + -1790, -900, -1169, 317, 514, 14083, -323, 896, + -891, -16, -12106, -6, -49, -48, -442, 10, + 277, -28, -770, 17, 27, 766, -17, 48, + 892, 158, 5237, 11057, -1603, -48, -1, -1674, + -7462, -156, -8, -285, -50, -602, -106, -3534, + 87, 15, 512, 1082, -1612, 2564, -4296, 12526, + 5710, -158, -401, -1126, -9576, -1990, 252, -422, + 672, 1232, -1960, 3284, 561, -893, 1497, -4365, + 4889, -6878, 612, 6109, 4753, -1459, -2887, -22, + -2277, -1379, 2052, -182, 257, -1823, 2564, -228, + -1418, 1995, -177, -1772, 3053, -506, 2403, 9625, + 1322, -569, -15, -352, -5655, -106, 94, -448, + 74, -1794, 297, -1412, -246, 40, -194, -777, + -754, 12904, 4480, -2113, 1471, -34, -10163, -1225, + -272, -132, 594, 206, -3529, -97, 1664, 577, + 67, -1159, -402, 189, 4255, 1476, 5055, 2393, + 2912, -1105, -132, -1559, -349, -517, -383, -1313, + -455, -621, -215, -738, -756, -262, -898, -425, + -1371, 535, 1417, 14604, -997, -114, -17, -122, + -13017, -60, 44, 118, -46, 1222, -477, -1263, + -83, 32, 86, 888, 5368, -1744, 4083, -1236, + 3753, -1758, -185, -1017, -93, -860, 571, -1338, + 434, 405, -131, 308, -1229, 399, -935, 283, + 1588, -3097, 14415, 3699, -1171, -154, -585, -12683, + -835, -83, 300, -1397, 2725, -358, 699, -3255, + 113, -221, 1030, 264, 212, 7989, 9471, -3344, + 2009, -2, -3895, -5475, -682, -246, -103, -123, + -4618, 43, 1630, 1933, -26, -979, -1161, 410, + 856, 2294, -627, 6930, 6929, -44, -321, -24, + -2931, -2930, -119, 32, 87, -362, -970, 265, + -362, -970, 265, -2931, 2357, -4187, 7162, 7683, + 3371, -339, -1070, -3131, -3603, -693, 602, -1030, + 1830, -1105, 1963, -3359, -485, 861, -1474, -1581, + 350, 4585, 14053, -3819, 1218, -7, -1283, -12054, + -890, -90, -97, -300, -3933, 81, 1068, 3275, + -26, -341, -1045, 284, -3248, 3531, 475, 2137, + 11711, -644, -761, -13, -278, -8372, 700, 94, + -102, 423, -460, -62, 2322, -2524, -340, -1528, + -3017, 3852, 1725, 8440, 5257, -555, -905, -181, + -4348, -1686, 709, 317, -405, 1554, -1984, -889, + 968, -1236, -553, -2708, -909, 3196, 15512, -2528, + 1066, -50, -623, -14686, -390, -69, 177, 861, + -3026, -140, 493, 2393, 59, -208, -1009, 164, + 959, -3370, 9617, 9545, -1761, -56, -693, -5645, + -5561, -189, 197, -563, 1978, -558, 1963, -5603, + 103, -362, 1034, 1026, 7575, 11796, -4845, 3252, + -1703, -3502, -8493, -1433, -645, -177, -5454, 2240, + 3488, -1503, -2341, 961, 787, 1226, -503, 338, + 6409, 1722, 1764, -4191, 6015, -2507, -181, -189, + -1072, -2208, -673, -690, -185, 1639, 440, 451, + -2353, -632, -647, 1538, -2420, 12161, 5038, 1286, + -2098, -357, -9027, -1549, -100, -268, 1796, 744, + -3740, 190, -954, -395, -310, 1557, 645, 164, + -2232, -1341, 7246, 9470, -1977, -304, -109, -3204, + -5474, -238, -182, 987, 593, 1290, 775, -4188, + -269, -161, 874, 1143, 1030, 7034, 4231, 1551, + 3077, -64, -3019, -1093, -146, -577, -442, -266, + -1816, -97, -666, -400, -193, -1321, -794, -291, + 5121, 11835, -477, -1749, 2298, -1601, -8549, -13, + -186, -322, -3699, 149, 344, 546, 1264, -50, + -718, -1660, 66, 245, -3328, 3827, 5921, 9976, + -1045, -676, -894, -2140, -6075, -66, 777, 1203, + -1383, 2027, -2330, -3605, -212, 244, 377, 636, + 3813, 5718, -4666, -3412, 5674, -887, -1995, -1329, + -710, -1965, -1331, 1086, 1628, 794, 1191, -972, + -1320, -1980, 1616, 1181, 1348, -3672, 13154, 6938, + -1690, -110, -823, -10561, -2938, -174, 302, -1082, + 2948, -570, 1555, -5570, 139, -379, 1357, 716, + 2151, -3586, 6949, 12131, -1224, -282, -785, -2947, + -8982, -91, 470, -912, 1521, -1592, 2655, -5145, + 160, -268, 519, 906, -2889, 9647, 10276, -2728, + 995, -509, -5680, -6445, -454, -60, 1701, 1812, + -6051, -481, 1606, 1711, 175, -586, -624, 165, + 6177, 2184, 555, 1985, 6589, -2329, -291, -18, + -240, -2650, -823, -209, -74, -748, -264, -67, + -2484, -878, -223, -798, -492, 391, 17166, -681, + 240, -14, -9, -17987, -28, -3, 11, 515, + -410, -20, 16, 713, 7, -5, -252, 10, + 12628, 5448, -2630, 3011, -2695, -9733, -1811, -422, + -553, -443, -4199, 2027, 874, -2321, -1001, 483, + 2077, 896, -432, 495, -3628, -534, 3447, 7002, + 6751, -803, -17, -725, -2992, -2782, -118, 763, + 112, 1550, 228, -1473, 1495, 220, -1420, -2885, + -5239, 5901, 8107, 3650, 4846, -1675, -2125, -4012, + -813, -1433, 1887, 2592, -2920, 1167, -1315, -1806, + 1550, -1745, -2398, -1080, 6157, 6678, 4099, -1074, + 2348, -2314, -2722, -1025, -70, -336, -2509, -1540, + -1670, 403, 437, 268, -882, -957, -587, 153, + 1079, 16099, 242, -881, 1690, -71, -15820, -3, + -47, -174, -1060, -16, -238, 58, 865, 13, + -111, -1661, -25, 90, -278, 227, -1039, 1636, + 16945, -4, -3, -65, -163, -17526, 3, -17, + 14, 27, -22, 103, 287, -234, 1074, -1693, + 15778, -1454, 574, -603, -107, -15195, -129, -20, + -22, 0, 1400, -553, 51, 581, -53, 21, + 103, -9, 3, -3, 2406, -836, 13224, 7993, + -4266, -353, -42, -10673, -3899, -1111, 122, -1942, + 674, -1174, 407, -6451, 626, -217, 3443, 2081, + 3184, 14368, -3336, 2255, -1801, -619, -12600, -679, + -310, -198, -2793, 648, 2926, -438, -1977, 459, + 350, 1580, -366, 247, -1698, 17076, 2504, -539, + -646, -176, -17798, -382, -17, -25, 1770, 259, + -2610, -55, 561, 82, -67, 673, 98, -21, + 2375, -797, -2696, 14483, 5383, -344, -38, -443, + -12803, -1769, 115, 391, -131, -2100, 705, 2384, + -780, 262, 886, -4759, -2691, 2554, -4520, 9573, + 10655, -442, -398, -1247, -5594, -6930, 419, -742, + 704, 1572, -1492, 2641, 1750, -1661, 2939, -6226, + -4332, -4399, -1657, 4880, 7375, -1145, -1181, -167, + -1453, -3319, -1163, -438, -444, 1290, 1310, 493, + 1950, 1980, 745, -2196, -3498, 7405, 9955, 2693, + -2971, -746, -3347, -6049, -442, -538, 1581, 2125, + -4499, 575, -1217, -1636, -634, 1342, 1805, 488, + 6717, -3792, 7739, 2798, 3489, -2754, -877, -3655, + -477, -743, 1554, -3173, 1791, -1147, 647, -1321, + -1430, 807, -1648, -595, 5263, 9770, 3463, 1069, + -3971, -1690, -5826, -732, -69, -962, -3138, -1112, + -2065, -343, -637, -226, 1275, 2368, 839, 259, + 1243, -2634, 16772, 1871, 332, -94, -423, -17169, + -213, -6, 199, -1273, 2696, -142, 300, -1915, + -25, 53, -339, -37, 2691, 2836, 3105, 5711, + 4817, -442, -491, -588, -1991, -1416, -465, -510, + -537, -938, -988, -1082, -791, -834, -913, -1679, + 4366, 2944, 7210, 3627, 1161, -1163, -529, -3172, + -803, -82, -784, -1921, -1295, -966, -651, -1596, + -309, -208, -511, -257, 13888, 3951, -671, -2305, + 3354, -11773, -953, -27, -324, -686, -3349, 569, + 161, 1954, 556, -94, -2843, -809, 137, 472, + 7053, 5847, 2929, 8378, -4794, -3036, -2086, -523, + -4284, -1403, -2517, -1261, -1045, -3607, -2990, -1498, + 2064, 1711, 857, 2451, -2191, 12838, 9182, -3915, + 1617, -293, -10059, -5146, -935, -159, 1717, 1228, + -7195, -523, 3068, 2194, 216, -1267, -906, 386, + -4881, 13114, 5767, -435, 4155, -1454, -10498, -2030, + -11, -1054, 3907, 1718, -4616, -129, 348, 153, + 1238, -3326, -1462, 110, 7843, -1250, 210, 7106, + -5203, -3754, -95, -2, -3082, -1652, 598, -100, + 16, -3402, 542, -91, 2491, -397, 66, 2257, + -2463, 8168, 14551, -3908, 1828, -370, -4072, -12923, + -932, -204, 1228, 2188, -7254, -587, 1948, 3471, + 274, -911, -1623, 436, -1579, 347, -272, -2735, + 16031, -152, -7, -4, -456, -15686, 33, -26, + 5, -263, 58, -45, 1545, -340, 266, 2676, + -6327, 1328, 5093, -5079, 7617, -2443, -107, -1583, + -1574, -3541, 513, 1967, -413, -1961, 411, 1578, + 2941, -617, -2367, 2361, 3286, -4509, 11306, 11025, + -2623, -659, -1241, -7802, -7419, -420, 904, -2267, + 3112, -2211, 3034, -7608, 526, -722, 1810, 1765, + 5567, 17853, -3754, 1166, -519, -1892, -19455, -860, + -83, -16, -6067, 1275, 4090, -396, -1271, 267, + 176, 566, -119, 37, -2136, -424, 15292, 5108, + -1648, -278, -10, -14273, -1593, -165, -55, 1993, + 396, 666, 132, -4768, -214, -42, 1538, 514, + 2267, -3297, 2549, 16563, -791, -313, -663, -396, + -16745, -38, 456, -352, 513, -2291, 3333, -2576, + 109, -159, 123, 799, 3655, 1899, -3364, 6279, + 12510, -815, -220, -690, -2406, -9552, -423, 750, + 390, -1400, -728, 1289, -2791, -1450, 2568, -4794, + 8052, 2285, -6193, 5138, 6003, -3957, -318, -2341, + -1611, -2199, -1123, 3044, 864, -2525, -716, 1942, + -2950, -837, 2269, -1882, -386, -2291, 7679, 15387, + -2723, -9, -320, -3599, -14452, -452, -54, 181, + 1074, 362, 2152, -7212, -64, -380, 1276, 2557, + 2777, -1173, 3984, 13079, 2508, -470, -84, -969, + -10440, -384, 198, -675, 285, -2217, 936, -3180, + -425, 179, -610, -2002, -1879, 1771, -2684, 16705, + 1833, -215, -191, -439, -17032, -205, 203, -308, + 290, 1916, -1805, 2736, 210, -198, 300, -1869, + 1052, 4495, 15519, 1467, -4032, -67, -1233, -14700, + -131, -992, -288, -997, -4257, -94, -402, -1389, + 259, 1106, 3819, 361, 3010, 2544, 6969, 7559, + 1996, -553, -395, -2964, -3487, -243, -467, -1280, + -1082, -1388, -1174, -3215, -366, -310, -849, -921, + -5209, -1867, 8713, 10351, 1549, -1656, -212, -4634, + -6540, -146, -593, 2770, 993, 3291, 1180, -5505, + 492, 176, -824, -979, -4314, 8513, 913, 7547, + -2723, -1135, -4423, -50, -3476, -452, 2241, 240, + -474, 1987, -3921, -420, -717, 1415, 151, 1254, + 12929, -1219, 2448, 1757, 6303, -10204, -90, -365, + -188, -2425, 962, -1932, 182, -1386, 130, -262, + -4974, 469, -941, -676, 6465, 4132, 3167, 3160, + 5697, -2551, -1042, -612, -609, -1981, -1630, -1249, + -798, -1247, -797, -611, -2248, -1437, -1101, -1099, + -3636, 4859, 18914, -1335, 810, -807, -1441, -21836, + -108, -40, 1078, 4198, -5609, -296, 396, 1541, + 179, -240, -936, 66, 8844, 7864, 654, -4063, + -5680, -4774, -3774, -26, -1007, -1969, -4245, -353, + -314, 2193, 1950, 162, 3066, 2726, 226, -1408, + 1859, 2634, 9228, 996, 9464, -211, -423, -5197, + -60, -5467, -299, -1047, -1483, -113, -160, -561, + -1074, -1521, -5330, -575, 2949, 12260, 10290, -497, + -3943, -530, -9174, -6463, -15, -949, -2206, -1852, + -7700, 89, 372, 312, 709, 2950, 2476, -119, + -2903, 1552, 14867, 9970, -496, -514, -147, -13491, + -6068, -15, 275, 2634, -1408, 1766, -944, -9047, + -87, 47, 450, 302, 3243, 8234, 7586, 3373, + 2151, -642, -4138, -3512, -694, -282, -1630, -1501, + -3812, -667, -1695, -1561, -425, -1081, -996, -442, + -9631, 60, 3501, 5359, 10150, -5662, 0, -748, + -1752, -6288, 35, 2058, -12, 3150, -19, -1145, + 5967, -37, -2169, -3320, -6874, -2553, -5446, -2195, + -7841, -2884, -397, -1810, -294, -3753, -1071, -2285, + -848, -921, -342, -729, -3290, -1221, -2606, -1050, + -3413, -1141, 4630, 13612, 7897, -711, -79, -1308, + -11310, -3806, -237, 964, 322, 2836, 948, -3847, + 1645, 550, -2231, -6561, 4410, -5678, 8006, -3992, + 3811, -1187, -1968, -3912, -973, -886, 1528, -2155, + 2775, 1074, -1383, 1951, -1025, 1321, -1862, 928, + 5659, 11535, 2203, -452, 7169, -1954, -8121, -296, + -12, -3137, -3984, -761, -1551, 156, 318, 60, + -2476, -5048, -964, 197, 2914, -2914, 3485, -3965, + 13675, -518, -518, -741, -959, -11414, 518, -620, + 620, 705, -705, 843, -2433, 2432, -2909, 3310, + 7843, 1907, 1022, 8882, 7972, -3755, -222, -63, + -4815, -3879, -913, -489, -119, -4252, -1034, -554, + -3816, -928, -497, -4322, 13807, 9531, 1436, 1612, + 1779, -11636, -5544, -125, -158, -193, -8032, -1210, + -835, -1358, -938, -141, -1499, -1035, -156, -175, + 13620, -5337, 5450, -2263, 1723, -11322, -1738, -1813, + -312, -181, 4436, -4531, 1775, 1881, -737, 752, + -1432, 561, -573, 238, 5297, 8374, 8872, 7694, + 6538, -1712, -4280, -4804, -3613, -2609, -2707, -2868, + -4534, -2487, -3932, -4166, -2113, -3341, -3540, -3070 +}; + int ff_g723_1_scale_vector(int16_t *dst, const int16_t *vector, int length) { int bits, max = 0; @@ -98,9 +1169,9 @@ /* Select quantization table */ if (cur_rate == RATE_6300 && pitch_lag < SUBFRAME_LEN - 2) { - cb_ptr = adaptive_cb_gain85; + cb_ptr = ff_g723_1_adaptive_cb_gain85; } else - cb_ptr = adaptive_cb_gain170; + cb_ptr = ff_g723_1_adaptive_cb_gain170; /* Calculate adaptive vector */ cb_ptr += subfrm->ad_cb_gain * 20; @@ -125,8 +1196,8 @@ for (j = 0; j < LPC_ORDER; j++) { int index = (lpc[j] >> 7) & 0x1FF; int offset = lpc[j] & 0x7f; - int temp1 = cos_tab[index] * (1 << 16); - int temp2 = (cos_tab[index + 1] - cos_tab[index]) * + int temp1 = ff_g723_1_cos_tab[index] * (1 << 16); + int temp2 = (ff_g723_1_cos_tab[index + 1] - ff_g723_1_cos_tab[index]) * (((offset << 8) + 0x80) << 1); lpc[j] = -(av_sat_dadd32(1 << 15, temp1 + temp2) >> 16); @@ -215,16 +1286,16 @@ } /* Get the VQ table entry corresponding to the transmitted index */ - cur_lsp[0] = lsp_band0[lsp_index[0]][0]; - cur_lsp[1] = lsp_band0[lsp_index[0]][1]; - cur_lsp[2] = lsp_band0[lsp_index[0]][2]; - cur_lsp[3] = lsp_band1[lsp_index[1]][0]; - cur_lsp[4] = lsp_band1[lsp_index[1]][1]; - cur_lsp[5] = lsp_band1[lsp_index[1]][2]; - cur_lsp[6] = lsp_band2[lsp_index[2]][0]; - cur_lsp[7] = lsp_band2[lsp_index[2]][1]; - cur_lsp[8] = lsp_band2[lsp_index[2]][2]; - cur_lsp[9] = lsp_band2[lsp_index[2]][3]; + cur_lsp[0] = ff_g723_1_lsp_band0[lsp_index[0]][0]; + cur_lsp[1] = ff_g723_1_lsp_band0[lsp_index[0]][1]; + cur_lsp[2] = ff_g723_1_lsp_band0[lsp_index[0]][2]; + cur_lsp[3] = ff_g723_1_lsp_band1[lsp_index[1]][0]; + cur_lsp[4] = ff_g723_1_lsp_band1[lsp_index[1]][1]; + cur_lsp[5] = ff_g723_1_lsp_band1[lsp_index[1]][2]; + cur_lsp[6] = ff_g723_1_lsp_band2[lsp_index[2]][0]; + cur_lsp[7] = ff_g723_1_lsp_band2[lsp_index[2]][1]; + cur_lsp[8] = ff_g723_1_lsp_band2[lsp_index[2]][2]; + cur_lsp[9] = ff_g723_1_lsp_band2[lsp_index[2]][3]; /* Add predicted vector & DC component to the previously quantized vector */ for (i = 0; i < LPC_ORDER; i++) { diff -Nru ffmpeg-4.2.2/libavcodec/g723_1dec.c ffmpeg-4.4/libavcodec/g723_1dec.c --- ffmpeg-4.2.2/libavcodec/g723_1dec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/g723_1dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -40,6 +40,78 @@ #define CNG_RANDOM_SEED 12345 +/** + * Postfilter gain weighting factors scaled by 2^15 + */ +static const int16_t ppf_gain_weight[2] = {0x1800, 0x2000}; + +static const int16_t pitch_contrib[340] = { + 60, 0, 0, 2489, 60, 0, 0, 5217, + 1, 6171, 0, 3953, 0, 10364, 1, 9357, + -1, 8843, 1, 9396, 0, 5794, -1, 10816, + 2, 11606, -2, 12072, 0, 8616, 1, 12170, + 0, 14440, 0, 7787, -1, 13721, 0, 18205, + 0, 14471, 0, 15807, 1, 15275, 0, 13480, + -1, 18375, -1, 0, 1, 11194, -1, 13010, + 1, 18836, -2, 20354, 1, 16233, -1, 0, + 60, 0, 0, 12130, 0, 13385, 1, 17834, + 1, 20875, 0, 21996, 1, 0, 1, 18277, + -1, 21321, 1, 13738, -1, 19094, -1, 20387, + -1, 0, 0, 21008, 60, 0, -2, 22807, + 0, 15900, 1, 0, 0, 17989, -1, 22259, + 1, 24395, 1, 23138, 0, 23948, 1, 22997, + 2, 22604, -1, 25942, 0, 26246, 1, 25321, + 0, 26423, 0, 24061, 0, 27247, 60, 0, + -1, 25572, 1, 23918, 1, 25930, 2, 26408, + -1, 19049, 1, 27357, -1, 24538, 60, 0, + -1, 25093, 0, 28549, 1, 0, 0, 22793, + -1, 25659, 0, 29377, 0, 30276, 0, 26198, + 1, 22521, -1, 28919, 0, 27384, 1, 30162, + -1, 0, 0, 24237, -1, 30062, 0, 21763, + 1, 30917, 60, 0, 0, 31284, 0, 29433, + 1, 26821, 1, 28655, 0, 31327, 2, 30799, + 1, 31389, 0, 32322, 1, 31760, -2, 31830, + 0, 26936, -1, 31180, 1, 30875, 0, 27873, + -1, 30429, 1, 31050, 0, 0, 0, 31912, + 1, 31611, 0, 31565, 0, 25557, 0, 31357, + 60, 0, 1, 29536, 1, 28985, -1, 26984, + -1, 31587, 2, 30836, -2, 31133, 0, 30243, + -1, 30742, -1, 32090, 60, 0, 2, 30902, + 60, 0, 0, 30027, 0, 29042, 60, 0, + 0, 31756, 0, 24553, 0, 25636, -2, 30501, + 60, 0, -1, 29617, 0, 30649, 60, 0, + 0, 29274, 2, 30415, 0, 27480, 0, 31213, + -1, 28147, 0, 30600, 1, 31652, 2, 29068, + 60, 0, 1, 28571, 1, 28730, 1, 31422, + 0, 28257, 0, 24797, 60, 0, 0, 0, + 60, 0, 0, 22105, 0, 27852, 60, 0, + 60, 0, -1, 24214, 0, 24642, 0, 23305, + 60, 0, 60, 0, 1, 22883, 0, 21601, + 60, 0, 2, 25650, 60, 0, -2, 31253, + -2, 25144, 0, 17998 +}; + +/** + * Size of the MP-MLQ fixed excitation codebooks + */ +static const int32_t max_pos[4] = {593775, 142506, 593775, 142506}; + +/** + * 0.65^i (Zero part) and 0.75^i (Pole part) scaled by 2^15 + */ +static const int16_t postfilter_tbl[2][LPC_ORDER] = { + /* Zero */ + {21299, 13844, 8999, 5849, 3802, 2471, 1606, 1044, 679, 441}, + /* Pole */ + {24576, 18432, 13824, 10368, 7776, 5832, 4374, 3281, 2460, 1845} +}; + +static const int cng_adaptive_cb_lag[4] = { 1, 0, 1, 3 }; + +static const int cng_filt[4] = { 273, 998, 499, 333 }; + +static const int cng_bseg[3] = { 2048, 18432, 231233 }; + static av_cold int g723_1_decode_init(AVCodecContext *avctx) { G723_1_Context *s = avctx->priv_data; @@ -221,16 +293,16 @@ j = PULSE_MAX - pulses[index]; temp = subfrm->pulse_pos; for (i = 0; i < SUBFRAME_LEN / GRID_SIZE; i++) { - temp -= combinatorial_table[j][i]; + temp -= ff_g723_1_combinatorial_table[j][i]; if (temp >= 0) continue; - temp += combinatorial_table[j++][i]; + temp += ff_g723_1_combinatorial_table[j++][i]; if (subfrm->pulse_sign & (1 << (PULSE_MAX - j))) { vector[subfrm->grid_index + GRID_SIZE * i] = - -fixed_cb_gain[subfrm->amp_index]; + -ff_g723_1_fixed_cb_gain[subfrm->amp_index]; } else { vector[subfrm->grid_index + GRID_SIZE * i] = - fixed_cb_gain[subfrm->amp_index]; + ff_g723_1_fixed_cb_gain[subfrm->amp_index]; } if (j == PULSE_MAX) break; @@ -238,7 +310,7 @@ if (subfrm->dirac_train == 1) ff_g723_1_gen_dirac_train(vector, pitch_lag); } else { /* 5300 bps */ - int cb_gain = fixed_cb_gain[subfrm->amp_index]; + int cb_gain = ff_g723_1_fixed_cb_gain[subfrm->amp_index]; int cb_shift = subfrm->grid_index; int cb_sign = subfrm->pulse_sign; int cb_pos = subfrm->pulse_pos; @@ -915,7 +987,7 @@ int16_t *vector_ptr = p->excitation + PITCH_MAX; /* Update interpolation gain memory */ - p->interp_gain = fixed_cb_gain[(p->subframe[2].amp_index + + p->interp_gain = ff_g723_1_fixed_cb_gain[(p->subframe[2].amp_index + p->subframe[3].amp_index) >> 1]; for (i = 0; i < SUBFRAMES; i++) { gen_fcb_excitation(vector_ptr, &p->subframe[i], p->cur_rate, @@ -1012,7 +1084,7 @@ formant_postfilter(p, lpc, p->audio, out); } else { // if output is not postfiltered it should be scaled by 2 for (i = 0; i < FRAME_LEN; i++) - out[i] = av_clip_int16(p->audio[LPC_ORDER + i] << 1); + out[i] = av_clip_int16(2 * p->audio[LPC_ORDER + i]); } } diff -Nru ffmpeg-4.2.2/libavcodec/g723_1enc.c ffmpeg-4.4/libavcodec/g723_1enc.c --- ffmpeg-4.2.2/libavcodec/g723_1enc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/g723_1enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -40,6 +40,54 @@ #define BITSTREAM_WRITER_LE #include "put_bits.h" +/** + * Hamming window coefficients scaled by 2^15 + */ +static const int16_t hamming_window[LPC_FRAME] = { + 2621, 2631, 2659, 2705, 2770, 2853, 2955, 3074, 3212, 3367, + 3541, 3731, 3939, 4164, 4405, 4663, 4937, 5226, 5531, 5851, + 6186, 6534, 6897, 7273, 7661, 8062, 8475, 8899, 9334, 9780, + 10235, 10699, 11172, 11653, 12141, 12636, 13138, 13645, 14157, 14673, + 15193, 15716, 16242, 16769, 17298, 17827, 18356, 18884, 19411, 19935, + 20457, 20975, 21489, 21999, 22503, 23002, 23494, 23978, 24455, 24924, + 25384, 25834, 26274, 26704, 27122, 27529, 27924, 28306, 28675, 29031, + 29373, 29700, 30012, 30310, 30592, 30857, 31107, 31340, 31557, 31756, + 31938, 32102, 32249, 32377, 32488, 32580, 32654, 32710, 32747, 32766, + 32766, 32747, 32710, 32654, 32580, 32488, 32377, 32249, 32102, 31938, + 31756, 31557, 31340, 31107, 30857, 30592, 30310, 30012, 29700, 29373, + 29031, 28675, 28306, 27924, 27529, 27122, 26704, 26274, 25834, 25384, + 24924, 24455, 23978, 23494, 23002, 22503, 21999, 21489, 20975, 20457, + 19935, 19411, 18884, 18356, 17827, 17298, 16769, 16242, 15716, 15193, + 14673, 14157, 13645, 13138, 12636, 12141, 11653, 11172, 10699, 10235, + 9780, 9334, 8899, 8475, 8062, 7661, 7273, 6897, 6534, 6186, + 5851, 5531, 5226, 4937, 4663, 4405, 4164, 3939, 3731, 3541, + 3367, 3212, 3074, 2955, 2853, 2770, 2705, 2659, 2631, 2621 +}; + +/** + * Binomial window coefficients scaled by 2^15 + */ +static const int16_t binomial_window[LPC_ORDER] = { + 32749, 32695, 32604, 32477, 32315, 32118, 31887, 31622, 31324, 30995 +}; + +/** + * 0.994^i scaled by 2^15 + */ +static const int16_t bandwidth_expand[LPC_ORDER] = { + 32571, 32376, 32182, 31989, 31797, 31606, 31416, 31228, 31040, 30854 +}; + +/** + * 0.5^i scaled by 2^15 + */ +static const int16_t percept_flt_tbl[2][LPC_ORDER] = { + /* Zero part */ + {29491, 26542, 23888, 21499, 19349, 17414, 15673, 14106, 12695, 11425}, + /* Pole part */ + {16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32} +}; + static av_cold int g723_1_encode_init(AVCodecContext *avctx) { G723_1_Context *s = avctx->priv_data; @@ -242,14 +290,14 @@ p = 0; temp = 0; for (i = 0; i <= LPC_ORDER / 2; i++) - temp += f[2 * i] * cos_tab[0]; + temp += f[2 * i] * G723_1_COS_TAB_FIRST_ELEMENT; prev_val = av_clipl_int32(temp << 1); count = 0; for (i = 1; i < COS_TBL_SIZE / 2; i++) { /* Evaluate */ temp = 0; for (j = 0; j <= LPC_ORDER / 2; j++) - temp += f[LPC_ORDER - 2 * j + p] * cos_tab[i * j % COS_TBL_SIZE]; + temp += f[LPC_ORDER - 2 * j + p] * ff_g723_1_cos_tab[i * j % COS_TBL_SIZE]; cur_val = av_clipl_int32(temp << 1); /* Check for sign change, indicating a zero crossing */ @@ -273,7 +321,7 @@ temp = 0; for (j = 0; j <= LPC_ORDER / 2; j++) temp += f[LPC_ORDER - 2 * j + p] * - cos_tab[i * j % COS_TBL_SIZE]; + ff_g723_1_cos_tab[i * j % COS_TBL_SIZE]; cur_val = av_clipl_int32(temp << 1); } prev_val = cur_val; @@ -298,11 +346,11 @@ \ for (i = 0; i < LSP_CB_SIZE; i++) { \ for (j = 0; j < size; j++){ \ - temp[j] = (weight[j + (offset)] * lsp_band##num[i][j] + \ + temp[j] = (weight[j + (offset)] * ff_g723_1_lsp_band##num[i][j] + \ (1 << 14)) >> 15; \ } \ error = ff_g723_1_dot_product(lsp + (offset), temp, size) << 1; \ - error -= ff_g723_1_dot_product(lsp_band##num[i], temp, size); \ + error -= ff_g723_1_dot_product(ff_g723_1_lsp_band##num[i], temp, size); \ if (error > max) { \ max = error; \ lsp_index[num] = i; \ @@ -642,7 +690,7 @@ { int16_t flt_buf[PITCH_ORDER][SUBFRAME_LEN]; - const int16_t *cb_tbl = adaptive_cb_gain85; + const int16_t *cb_tbl = ff_g723_1_adaptive_cb_gain85; int ccr_buf[PITCH_ORDER * SUBFRAMES << 2]; @@ -720,7 +768,7 @@ /* Select quantization table */ if (!odd_frame && pitch_lag + i - 1 >= SUBFRAME_LEN - 2 || odd_frame && pitch_lag >= SUBFRAME_LEN - 2) { - cb_tbl = adaptive_cb_gain170; + cb_tbl = ff_g723_1_adaptive_cb_gain170; tbl_size = 170; } @@ -838,7 +886,7 @@ min = 1 << 30; max_amp_index = GAIN_LEVELS - 2; for (j = max_amp_index; j >= 2; j--) { - temp = av_clipl_int32((int64_t) fixed_cb_gain[j] * + temp = av_clipl_int32((int64_t) ff_g723_1_fixed_cb_gain[j] * impulse_corr[0] << 1); temp = FFABS(temp - amp); if (temp < min) { @@ -855,7 +903,7 @@ ccr2[k] = ccr1[k]; } param.amp_index = max_amp_index + j - 2; - amp = fixed_cb_gain[param.amp_index]; + amp = ff_g723_1_fixed_cb_gain[param.amp_index]; param.pulse_sign[0] = (ccr2[param.pulse_pos[0]] < 0) ? -amp : amp; temp_corr[param.pulse_pos[0]] = 1; @@ -942,7 +990,7 @@ for (i = 0; i < SUBFRAME_LEN >> 1; i++) { int val = buf[optim->grid_index + (i << 1)]; if (!val) { - subfrm->pulse_pos += combinatorial_table[j][i]; + subfrm->pulse_pos += ff_g723_1_combinatorial_table[j][i]; } else { subfrm->pulse_sign <<= 1; if (val < 0) @@ -1030,7 +1078,7 @@ put_bits(&pb, 1, p->subframe[3].grid_index); if (p->cur_rate == RATE_6300) { - skip_put_bits(&pb, 1); /* reserved bit */ + put_bits(&pb, 1, 0); /* reserved bit */ /* Write 13 bit combined position index */ temp = (p->subframe[0].pulse_pos >> 16) * 810 + diff -Nru ffmpeg-4.2.2/libavcodec/g723_1.h ffmpeg-4.4/libavcodec/g723_1.h --- ffmpeg-4.2.2/libavcodec/g723_1.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/g723_1.h 2021-04-08 21:28:39.000000000 +0000 @@ -222,11 +222,6 @@ static const uint8_t frame_size[4] = { 24, 20, 4, 1 }; /** - * Postfilter gain weighting factors scaled by 2^15 - */ -static const int16_t ppf_gain_weight[2] = {0x1800, 0x2000}; - -/** * LSP DC component */ static const int16_t dc_lsp[LPC_ORDER] = { @@ -243,1202 +238,30 @@ }; /* Cosine table scaled by 2^14 */ -static const int16_t cos_tab[COS_TBL_SIZE + 1] = { - 16384, 16383, 16379, 16373, 16364, 16353, 16340, 16324, - 16305, 16284, 16261, 16235, 16207, 16176, 16143, 16107, - 16069, 16029, 15986, 15941, 15893, 15843, 15791, 15736, - 15679, 15619, 15557, 15493, 15426, 15357, 15286, 15213, - 15137, 15059, 14978, 14896, 14811, 14724, 14635, 14543, - 14449, 14354, 14256, 14155, 14053, 13949, 13842, 13733, - 13623, 13510, 13395, 13279, 13160, 13039, 12916, 12792, - 12665, 12537, 12406, 12274, 12140, 12004, 11866, 11727, - 11585, 11442, 11297, 11151, 11003, 10853, 10702, 10549, - 10394, 10238, 10080, 9921, 9760, 9598, 9434, 9269, - 9102, 8935, 8765, 8595, 8423, 8250, 8076, 7900, - 7723, 7545, 7366, 7186, 7005, 6823, 6639, 6455, - 6270, 6084, 5897, 5708, 5520, 5330, 5139, 4948, - 4756, 4563, 4370, 4176, 3981, 3786, 3590, 3393, - 3196, 2999, 2801, 2603, 2404, 2205, 2006, 1806, - 1606, 1406, 1205, 1005, 804, 603, 402, 201, - 0, -201, -402, -603, -804, -1005, -1205, -1406, - -1606, -1806, -2006, -2205, -2404, -2603, -2801, -2999, - -3196, -3393, -3590, -3786, -3981, -4176, -4370, -4563, - -4756, -4948, -5139, -5330, -5520, -5708, -5897, -6084, - -6270, -6455, -6639, -6823, -7005, -7186, -7366, -7545, - -7723, -7900, -8076, -8250, -8423, -8595, -8765, -8935, - -9102, -9269, -9434, -9598, -9760, -9921, -10080, -10238, - -10394, -10549, -10702, -10853, -11003, -11151, -11297, -11442, - -11585, -11727, -11866, -12004, -12140, -12274, -12406, -12537, - -12665, -12792, -12916, -13039, -13160, -13279, -13395, -13510, - -13623, -13733, -13842, -13949, -14053, -14155, -14256, -14354, - -14449, -14543, -14635, -14724, -14811, -14896, -14978, -15059, - -15137, -15213, -15286, -15357, -15426, -15493, -15557, -15619, - -15679, -15736, -15791, -15843, -15893, -15941, -15986, -16029, - -16069, -16107, -16143, -16176, -16207, -16235, -16261, -16284, - -16305, -16324, -16340, -16353, -16364, -16373, -16379, -16383, - -16384, -16383, -16379, -16373, -16364, -16353, -16340, -16324, - -16305, -16284, -16261, -16235, -16207, -16176, -16143, -16107, - -16069, -16029, -15986, -15941, -15893, -15843, -15791, -15736, - -15679, -15619, -15557, -15493, -15426, -15357, -15286, -15213, - -15137, -15059, -14978, -14896, -14811, -14724, -14635, -14543, - -14449, -14354, -14256, -14155, -14053, -13949, -13842, -13733, - -13623, -13510, -13395, -13279, -13160, -13039, -12916, -12792, - -12665, -12537, -12406, -12274, -12140, -12004, -11866, -11727, - -11585, -11442, -11297, -11151, -11003, -10853, -10702, -10549, - -10394, -10238, -10080, -9921, -9760, -9598, -9434, -9269, - -9102, -8935, -8765, -8595, -8423, -8250, -8076, -7900, - -7723, -7545, -7366, -7186, -7005, -6823, -6639, -6455, - -6270, -6084, -5897, -5708, -5520, -5330, -5139, -4948, - -4756, -4563, -4370, -4176, -3981, -3786, -3590, -3393, - -3196, -2999, -2801, -2603, -2404, -2205, -2006, -1806, - -1606, -1406, -1205, -1005, -804, -603, -402, -201, - 0, 201, 402, 603, 804, 1005, 1205, 1406, - 1606, 1806, 2006, 2205, 2404, 2603, 2801, 2999, - 3196, 3393, 3590, 3786, 3981, 4176, 4370, 4563, - 4756, 4948, 5139, 5330, 5520, 5708, 5897, 6084, - 6270, 6455, 6639, 6823, 7005, 7186, 7366, 7545, - 7723, 7900, 8076, 8250, 8423, 8595, 8765, 8935, - 9102, 9269, 9434, 9598, 9760, 9921, 10080, 10238, - 10394, 10549, 10702, 10853, 11003, 11151, 11297, 11442, - 11585, 11727, 11866, 12004, 12140, 12274, 12406, 12537, - 12665, 12792, 12916, 13039, 13160, 13279, 13395, 13510, - 13623, 13733, 13842, 13949, 14053, 14155, 14256, 14354, - 14449, 14543, 14635, 14724, 14811, 14896, 14978, 15059, - 15137, 15213, 15286, 15357, 15426, 15493, 15557, 15619, - 15679, 15736, 15791, 15843, 15893, 15941, 15986, 16029, - 16069, 16107, 16143, 16176, 16207, 16235, 16261, 16284, - 16305, 16324, 16340, 16353, 16364, 16373, 16379, 16383, - 16384 -}; +extern const int16_t ff_g723_1_cos_tab[COS_TBL_SIZE + 1]; +#define G723_1_COS_TAB_FIRST_ELEMENT 16384 /** * LSP VQ tables */ -static const int16_t lsp_band0[LSP_CB_SIZE][3] = { - { 0, 0, 0}, { -270, -1372, -1032}, { -541, -1650, -1382}, - { -723, -2011, -2213}, { -941, -1122, -1942}, { -780, -1145, -2454}, - { -884, -1309, -1373}, {-1051, -1523, -1766}, {-1083, -1622, -2300}, - { -777, -1377, -2147}, { -935, -1467, -2763}, { -802, -1327, -3471}, - { -935, -1959, -3999}, { -240, -89, 222}, { -661, -257, -160}, - { -994, -466, -419}, { -188, -164, -278}, { -342, -512, -415}, - { -607, -511, -797}, { 16, 19, -716}, { 374, 425, -972}, - { -346, 245, -282}, { -265, 506, -754}, { -620, -147, 1955}, - { -742, -860, 2597}, { -150, -352, 2704}, { 305, 880, 1954}, - { 123, 731, 2766}, { -348, 765, 3327}, { 618, 221, 3258}, - { -178, -47, 4219}, { 393, 1304, 3842}, { 698, 1702, 4801}, - { 63, -584, 1229}, { -215, -732, 1704}, { 172, -335, 1909}, - { -2, 216, 1797}, { 353, 127, 2205}, {-1208, 188, 11}, - { -513, -75, -683}, { -973, 222, -646}, { -616, -843, -388}, - { -950, -1113, -359}, {-1431, -623, -705}, {-1398, -1063, -178}, - { -45, -461, 35}, { -9, -657, -216}, { 127, -1078, 95}, - { -950, -1156, 584}, {-1480, -1494, 449}, { -120, -705, 516}, - { -368, -961, 727}, { -378, -526, 973}, { -793, -614, 676}, - { -801, -755, 1287}, {-1476, -340, 1636}, { -505, -1254, 1543}, - {-1243, -1622, 1532}, { -776, -1477, -655}, {-1151, -1296, -823}, - {-1153, -1672, -1124}, {-1291, -2003, -1702}, { -622, -1283, 57}, - { -471, -1611, 509}, {-1060, -1570, -139}, { -873, -2156, -536}, - {-1716, -2021, -364}, {-2150, -3218, -1291}, {-1248, -1945, -2904}, - {-1215, -2633, -2855}, { 167, -244, 84}, { 349, -412, -217}, - { -40, -352, 632}, { 227, -529, 405}, { 68, -383, -443}, - { 167, -558, -706}, { -275, -854, -14}, { -351, -1089, -449}, - { 341, -72, -289}, { 603, -106, -474}, { 322, -219, -649}, - { 179, -317, -998}, { 450, -291, -996}, { 555, 195, -525}, - { 784, 272, -831}, { -148, -384, -849}, { 82, -536, -1357}, - { 238, -172, -1354}, { 422, -268, -1841}, { 297, -737, -2079}, - { -111, -801, -598}, { 1, -668, -984}, { -131, -818, -1299}, - { -329, -521, -1310}, { -151, -778, -1834}, { -93, -352, -1746}, - { -568, -640, -1821}, { -509, -941, -2183}, { 464, -815, -1250}, - { 79, -1133, -1597}, { -184, -1353, -2123}, { -196, -410, -2427}, - { -192, -833, -2810}, { -259, -1382, -3045}, { -217, 4, -1166}, - { -800, -325, -1219}, { -363, -830, -898}, { -661, -1134, -960}, - { -386, -980, -1501}, { -627, -1159, -1722}, { -903, -829, -855}, - { -685, -829, -1313}, {-1065, -959, -1405}, { 441, 25, -847}, - { 655, -27, -1181}, { 1159, -110, -705}, { 856, 253, -1671}, - { 415, 404, -1}, { 322, 903, -398}, { 670, 499, -292}, - { 803, 591, -610}, { 1144, 591, -814}, { 717, 183, 393}, - { 857, 381, 106}, { 609, 62, -27}, { 792, 198, -325}, - { 735, 805, 88}, { 1142, 812, 78}, { 1028, 366, -292}, - { 1309, 743, -237}, { 1615, 589, -79}, { 1010, 639, -243}, - { 999, 964, -311}, { 1500, 1137, -615}, { 988, 357, 646}, - { 1227, 667, 683}, { 1164, 1565, 894}, { 1392, 2015, 477}, - { 1138, 533, 250}, { 1437, 896, 391}, { 1765, 1118, 99}, - { 1112, 1090, 802}, { 1596, 846, 1134}, { 937, 1161, 279}, - { 1719, 1254, 683}, { 1338, 1086, 35}, { 1419, 1324, 428}, - { 1428, 1524, 40}, { 2108, 1594, 89}, { 1015, 544, 1222}, - { 1121, 925, 1263}, { 1030, 1318, 1485}, { 1295, 789, 1817}, - { 1323, 1272, 1909}, { 1724, 1237, 1803}, { 1797, 1689, 858}, - { 2149, 1367, 1301}, { 2302, 1867, 761}, { 2863, 2351, 1053}, - { 52, 163, -76}, { 230, 309, -492}, { -71, 619, 39}, - { -218, 856, 499}, { -654, 736, -207}, { -535, 1259, 155}, - { -480, 1476, 643}, { 262, 1081, 102}, { 309, 1592, -182}, - { 627, 1629, 534}, { 337, 643, 456}, { 758, 670, 713}, - { 202, 1126, 658}, { 612, 1131, 666}, { 686, 1223, 1136}, - { -131, 377, 525}, { 42, 708, 907}, { 87, 1488, 1035}, - { 432, 2117, 904}, { 137, 981, 1332}, { -447, 1014, 1136}, - { -839, 1793, 1246}, { -559, 297, 198}, { -850, 685, 446}, - {-1273, 632, 826}, { -401, -544, 173}, { -753, -793, 144}, - { -436, -9, 772}, { -115, -243, 1310}, { -670, -269, 374}, - {-1027, -13, 639}, { -887, -81, 1137}, {-1277, -455, 158}, - {-1411, -720, 736}, { 172, 88, 403}, { 386, 255, 756}, - { -500, 522, 910}, { -958, 659, 1388}, { -395, 301, 1344}, - { -356, 768, 1813}, { -613, 841, 2419}, { 445, -122, 252}, - { 629, -87, 723}, { 283, -253, 870}, { 456, -116, 1381}, - { 757, 180, 1059}, { 532, 408, 1509}, { 947, 288, 1806}, - { 1325, 994, 2524}, { 892, 1219, 3023}, { 1397, 1596, 3406}, - { 1143, 1552, 2546}, { 1850, 1433, 2710}, { -10, 134, 1002}, - { 154, 499, 1323}, { 508, 792, 1117}, { 509, 1340, 1616}, - { 762, 862, 1608}, { 787, 740, 2320}, { 794, 1727, 1283}, - { 465, 2108, 1660}, { -120, 1451, 1613}, { -386, 2016, 2169}, - { 891, 1225, 2050}, { 456, 1480, 2185}, { 1493, 1283, 1209}, - { 1397, 1636, 1518}, { 1776, 1738, 1552}, { 1572, 1698, 2141}, - { 1389, 2126, 1271}, { 1959, 2413, 1119}, { 1365, 2892, 1505}, - { 2206, 1971, 1623}, { 2076, 1950, 2280}, { 1717, 2291, 1867}, - { 2366, 2515, 1953}, { 2865, 2838, 2522}, { 2535, 3465, 2011}, - { 3381, 4127, 2638}, { 836, 2667, 2289}, { 1761, 2773, 2337}, - { 1415, 3325, 2911}, { 2354, 3138, 3126}, { 2659, 4192, 4010}, - { 1048, 1786, 1818}, { 1242, 2111, 2240}, { 1512, 2079, 2780}, - { 1573, 2491, 3138}, { 2230, 2377, 2782}, { 416, 1773, 2704}, - { 725, 2336, 3297}, { 1252, 2373, 3978}, { 2094, 2268, 3568}, - { 2011, 2712, 4528}, { 1341, 3507, 3876}, { 1216, 3919, 4922}, - { 1693, 4793, 6012} -}; - -static const int16_t lsp_band1[LSP_CB_SIZE][3] = { - { 0, 0, 0}, {-2114, -1302, 76}, {-2652, -1278, -1368}, - {-2847, -828, -349}, {-3812, -2190, -349}, {-3946, -364, -449}, - {-2725, -4492, -3607}, {-3495, -4764, -1744}, { -51, -756, 84}, - { -153, -1191, 504}, { 108, -1418, 1167}, { -835, -896, 390}, - { -569, -1702, 87}, {-1151, -1818, 933}, {-1826, -2547, 411}, - {-1842, -1818, 1451}, {-2438, -1611, 781}, {-2747, -2477, 1311}, - { -940, 1252, 477}, {-1629, 1688, 602}, {-1202, 617, 280}, - {-1737, 393, 580}, {-1528, 1077, 1199}, {-2165, -161, 1408}, - {-2504, -1087, 2371}, {-3458, -175, 1395}, {-1397, -98, -843}, - {-2252, -177, -1149}, {-1489, -726, -1283}, {-1558, -265, -1744}, - {-1867, -821, -1897}, {-2062, -1516, -2340}, {-2595, -1142, -2861}, - { 170, 46, -819}, { -193, -204, -1151}, { 326, -196, -1532}, - { 780, 329, -816}, { 201, 369, -1243}, { 650, -209, -1060}, - { 1144, -15, -1216}, { 1203, -259, -1867}, { -890, -564, -1430}, - { -638, -852, -1921}, { 177, -739, -1358}, { -261, -526, -1666}, - { 206, -407, -2255}, { 338, -526, -822}, { 421, -1095, -1009}, - { 765, -607, -1408}, { 825, -1295, -2004}, { 357, -905, -1815}, - { -58, -1248, -1588}, { -596, -1436, -2046}, { -73, -1159, -2116}, - { -115, -1382, -2581}, { -160, -1723, -1952}, { -6, -2196, -2954}, - { -649, -1705, -2603}, { -617, -1453, -3282}, { -949, -2019, -3102}, - { -812, 1544, 1937}, {-1854, 574, 2000}, {-1463, 1140, 2649}, - {-2683, 1748, 1452}, {-2486, 2241, 2523}, { 783, 1910, 1435}, - { 581, 2682, 1376}, { 236, 2197, 1885}, { -453, 2943, 2057}, - { -682, 2178, 2565}, {-1342, 3201, 3328}, { -288, -184, 262}, - { 121, -149, -183}, { 758, -412, 206}, { 1038, -204, 853}, - { 1577, -457, 700}, { 937, -640, -567}, { 1508, -528, -1024}, - { -225, -527, -427}, { -564, -1095, -332}, { -742, -353, -186}, - {-1288, -459, 84}, {-1853, -484, -274}, {-1554, -731, 825}, - {-2425, -234, 382}, {-1722, 293, -271}, {-2515, 425, -564}, - {-2599, 818, 464}, { -358, 118, -375}, { -613, 198, -874}, - { -690, 683, -324}, {-1352, 1155, -168}, {-1093, 129, -324}, - {-1184, 611, -858}, { 433, 386, -372}, { -120, 486, -634}, - { 234, 851, -631}, { 602, 128, 46}, { 1099, 410, 159}, - { 715, -145, -424}, { 1198, -85, -593}, { 1390, 367, -358}, - { 1683, 362, -964}, { 1711, 622, 45}, { 2033, 833, -383}, - { 2890, 549, -506}, { 7, 401, 52}, { 72, 811, 415}, - { 566, 668, 41}, { 467, 1218, 130}, { 68, 957, -187}, - { -25, 1649, -103}, { -661, 260, 214}, { -925, -94, 612}, - { -321, -422, 965}, { -788, -672, 1783}, { 400, -673, 779}, - { 741, -595, 1635}, { -161, 307, 657}, { -382, 836, 871}, - { -814, 400, 1223}, { 364, 606, 1247}, { 57, 75, 1571}, - { 151, 471, 2287}, { -81, 1021, 1502}, { 227, 1470, 1097}, - { 658, 1275, 1653}, { 664, 1478, 2377}, { 263, -127, 444}, - { 264, 89, 969}, { 794, 171, 576}, { 821, 186, 1226}, - { 404, 462, 517}, { 339, 918, 794}, { 1280, 1423, 196}, - { 1453, 2019, 365}, { 1615, 1481, 672}, { 2394, 1708, 508}, - { 806, 1238, 573}, { 713, 1158, 1078}, { 1285, 1436, 1232}, - { 1790, 1188, 1141}, { 765, 643, 864}, { 1032, 797, 1279}, - { 900, 563, 1827}, { 1514, 673, 2312}, { 1544, 1129, 3240}, - { 1469, 1050, 1594}, { 1945, 1318, 1988}, { 2397, 2026, 2060}, - { 3538, 2057, 2620}, { 1249, -118, 74}, { 1727, 194, 421}, - { 2078, -50, -463}, { 970, 688, -432}, { 1149, 952, -110}, - { 1254, 1275, -651}, { 1386, 929, 401}, { 1960, 1167, 232}, - { 407, -752, -243}, { 859, -1118, 172}, { -227, -860, -992}, - { -796, -1175, -1380}, { 8, -1282, -388}, { 353, -1781, -1037}, - { -732, -397, -807}, { -853, -28, -1342}, {-1229, -1207, -1959}, - {-1015, -1125, -2543}, {-1452, -1791, -2725}, {-1891, -2416, -3269}, - { -918, -1629, -783}, { -580, -2155, -698}, {-1097, -2364, -96}, - {-1387, -1513, 7}, {-1588, -2076, -664}, {-1473, -2740, -784}, - {-2378, -3149, -56}, {-2856, -2092, -169}, {-3391, -3708, 316}, - {-1176, -890, -614}, {-1944, -1061, -800}, { -299, -1517, -1000}, - { -640, -1850, -1526}, {-1454, -1536, -1233}, {-1890, -1955, -1756}, - {-1086, -1921, -2122}, { -750, -2325, -2260}, {-1325, -2413, -2673}, - {-1114, -2542, -3459}, {-1341, -2901, -3963}, {-1160, -2226, -1393}, - {-1001, -2772, -1573}, {-1594, -2641, -1978}, {-1534, -3046, -2624}, - {-2224, -2196, -675}, {-2807, -3054, -1102}, {-2008, -2840, -1186}, - {-1980, -3332, -1695}, {-1715, -3562, -505}, {-2527, -4000, -1887}, - {-2333, -2734, -2296}, {-3440, -2401, -3211}, {-2008, -3528, -3337}, - {-2247, -3291, -4510}, { -475, 949, 155}, { -149, 1365, 545}, - { -757, 1644, 1083}, { -217, 2053, 1353}, {-1433, 2301, 1462}, - { 495, 1661, 529}, { 10, 2037, 740}, { 2082, 1898, 978}, - { 2831, 2294, 911}, { 842, 793, 420}, { 1223, 1023, 863}, - { 1237, 451, 780}, { 1744, 708, 822}, { 1533, 284, 1384}, - { 2135, 609, 1538}, { 2305, 626, 540}, { 2368, 1187, 955}, - { 2586, 1255, -7}, { 3116, 1131, 726}, { 3431, 1730, 428}, - { 2734, 1648, 1307}, { 2988, 1231, 2010}, { 3523, 2024, 1488}, - { 1034, 1657, 871}, { 1206, 2163, 1036}, { 1807, 2372, 1233}, - { 1808, 1769, 1493}, { 1573, 2332, 1779}, { 1216, 1609, 1866}, - { 1480, 1898, 2513}, { 465, 2708, 2776}, { 771, 3638, 3338}, - { 1869, 2599, 2623}, { 2825, 2745, 2468}, { 2638, 2439, 1585}, - { 2094, 2970, 1308}, { 2022, 3057, 1999}, { 3428, 2912, 1816}, - { 4536, 2974, 2129}, { 1046, 2563, 2086}, { 1363, 3562, 2318}, - { 2511, 1891, 2984}, { 1866, 2306, 3986}, { 3272, 2924, 3682}, - { 3146, 3564, 2272}, { 3592, 3968, 2822}, { 2431, 3369, 3069}, - { 1931, 4709, 3090}, { 2629, 4220, 3986}, { 4639, 4056, 3664}, - { 4035, 5334, 4912} -}; - -static const int16_t lsp_band2[LSP_CB_SIZE][4] = { - { 0, 0, 0, 0}, { 601, 512, -542, 334}, - { 428, 1087, -484, -132}, { 652, 622, -391, -572}, - { 378, 799, 141, -860}, { 1040, 409, 112, -554}, - { 1123, 670, -75, -847}, { 1421, 494, -315, -1095}, - { 787, 1001, 114, -460}, { 988, 1672, 216, -681}, - { 1007, 1241, -132, -1247}, { 1073, 399, 186, -5}, - { 1262, 193, -694, -129}, { 325, 196, 51, -641}, - { 861, -59, 350, -458}, { 1261, 567, 586, -346}, - { 1532, 885, 210, -517}, { 2027, 937, 113, -792}, - { 1383, 1064, 334, 38}, { 1964, 1468, 459, 133}, - { 2062, 1186, -98, -121}, { 2577, 1445, 506, -373}, - { 2310, 1682, -2, -960}, { 2876, 1939, 765, 138}, - { 3581, 2360, 649, -414}, { 219, 176, -398, -309}, - { 434, -78, -435, -880}, { -344, 301, 265, -552}, - { -915, 470, 657, -380}, { 419, -432, -163, -453}, - { 351, -953, 8, -562}, { 789, -43, 20, -958}, - { 302, -594, -352, -1159}, { 1040, 108, -668, -924}, - { 1333, 210, -1217, -1663}, { 483, 589, -350, -1140}, - { 1003, 824, -802, -1184}, { 745, 58, -589, -1443}, - { 346, 247, -915, -1683}, { 270, 796, -720, -2043}, - { 1208, 722, -222, -193}, { 1486, 1180, -412, -672}, - { 1722, 179, -69, -521}, { 2047, 860, -666, -1410}, - { -146, 222, -281, -805}, { -189, 90, -114, -1307}, - { -152, 1086, -241, -764}, { -439, 733, -601, -1302}, - { -833, -167, -351, -601}, { -856, -422, -411, -1059}, - { -747, -355, -582, -1644}, { -837, 210, -916, -1144}, - {-1800, 32, -878, -1687}, { -48, -23, -1146, 52}, - { -350, -409, -1656, -364}, { 265, -728, -858, -577}, - { 458, -247, -1141, -997}, { 691, -407, -1988, -1161}, - { -66, -104, -705, -1249}, { -431, -93, -1191, -1844}, - { 203, -732, -1000, -1693}, { 10, -832, -1846, -1819}, - { 493, -128, -1436, -1768}, { 488, -311, -1730, -2540}, - { -653, -532, -1150, -1172}, {-1086, -289, -1706, -1533}, - { -699, -1205, -1216, -1766}, {-1032, -1481, -2074, -1523}, - { -721, -1220, -2277, -2600}, { 12, -539, -1484, -1131}, - { -40, -911, -2106, -441}, { -471, -484, -2267, -1549}, - { -141, -988, -3006, -1721}, {-1545, -2102, -583, 342}, - {-1383, -2772, -386, -13}, {-2118, -2589, -1205, 72}, - {-2147, -3231, -965, 390}, {-2949, -3300, -621, 637}, - {-3907, -4138, -865, 803}, {-1287, -845, -375, -548}, - {-1416, -1169, -487, -1277}, {-1400, -1690, -1027, -418}, - {-2018, -1909, -1188, -1260}, {-1418, -2222, -2029, -128}, - {-2067, -2998, -2693, -310}, { -950, -1028, -1538, 185}, - {-1616, -915, -2205, -549}, { 19, -821, -1145, 352}, - { 184, -1175, -1356, -627}, { -547, -1088, -1661, -911}, - { -216, -1502, -2197, -948}, { -795, -1306, -2374, -451}, - { -924, -1889, -2796, -680}, { -600, -1614, -3609, -885}, - {-2392, -2528, 319, 303}, {-2908, -2095, -310, 573}, - {-3460, -2141, 49, -113}, {-2231, -448, 675, -146}, - {-2805, -532, 1231, 479}, {-2684, -486, -200, 611}, - {-3525, -971, -198, 704}, {-3707, 173, 349, 254}, - {-4734, -1447, -34, 880}, { 777, -512, 114, -10}, - { 1250, -66, 442, -5}, { 604, 613, 452, -352}, - { 1224, 777, 675, -1014}, {-1372, -79, -1208, -238}, - {-2389, -17, -1157, -818}, {-1504, -673, -1133, -1060}, - {-1984, -799, -2005, -1973}, {-2037, -798, -1068, -105}, - {-3190, -899, -1817, -194}, { -156, -886, 394, -318}, - { -258, -1283, 551, 202}, { -536, -1729, 910, 331}, - { -847, -1109, 795, -163}, {-1171, -1128, 715, 519}, - {-1080, -1319, 1685, 668}, {-1000, -1921, 96, 211}, - {-1487, -2148, 831, 174}, {-1139, -374, 414, -4}, - {-1517, -1383, 396, -352}, {-1012, 439, -59, -967}, - {-1812, 706, -440, -1030}, {-1971, -329, -34, -827}, - {-2472, -1588, -151, -606}, {-2161, 374, -281, 76}, - {-3012, 231, -15, -690}, { 1104, 566, 721, 209}, - { 1685, 564, 383, 98}, { 1898, 750, 792, -97}, - { 556, -64, 561, -93}, { 876, 162, 913, -22}, - { 961, 675, 1296, 140}, { 756, -396, 851, 544}, - { 360, -303, 1341, 396}, { 878, -22, 1464, 863}, - { -309, -273, 642, -129}, { -686, -82, 842, 454}, - { -5, -47, 1069, 998}, { -94, 967, 1277, 298}, - { -489, 385, 1473, 746}, { -369, -717, 1333, 242}, - { 281, -993, 1726, 924}, { 464, 601, 1575, 1376}, - { -250, 206, 2339, 1175}, { -438, 377, -597, -285}, - {-1020, 787, -790, -287}, { -458, -410, 215, 295}, - { -589, -860, -121, 797}, {-1175, 122, -437, 466}, - {-1480, -121, 367, 924}, { 234, 323, 770, -555}, - { 145, 30, 996, 26}, { 66, 849, 93, -145}, - { -117, 1261, 474, -399}, {-1495, 1051, 218, -506}, - {-1390, 694, 994, 88}, { 616, 7, 78, 304}, - { 1060, 52, -62, 835}, { 833, 454, 649, 1359}, - { -770, 464, 47, 93}, { -574, 1199, -39, 379}, - { 114, -98, 488, 485}, { 727, 244, 606, 696}, - { -76, 455, 671, 546}, { -565, -13, 145, 819}, - { -376, 569, 448, 1128}, { 218, 122, 265, 1167}, - { 230, 738, 932, 1003}, { 138, 477, 36, 450}, - { 404, 787, -73, 1000}, { 497, 1259, 387, 1231}, - { 17, 207, 195, -79}, { 562, 358, 53, -158}, - { 493, 387, 478, 189}, { 678, 831, 640, 558}, - { -197, 523, 613, 57}, { 429, 894, 769, 111}, - { 67, 1174, 568, 511}, { 1242, 824, 251, 840}, - { 1419, 1074, 864, 481}, { 924, 1474, 669, 724}, - { 1539, 1879, 654, 1590}, { 445, 337, 1111, 541}, - { 472, 1421, 1264, 1094}, { 794, 735, 1103, 668}, - { 1055, 863, 1192, 1020}, { 778, 1105, 806, 1798}, - { 1052, 1527, 1587, 2151}, { 881, 1552, 1265, 391}, - { 726, 872, 1812, 601}, { 1469, 280, 1008, 616}, - { 1403, 577, 1803, 1244}, { 1650, 1314, 1148, 1072}, - { 1297, 1669, 1911, 1026}, { 2093, 1044, 2115, 1189}, - { 1644, 1961, 2587, 1512}, { 25, -315, -9, -106}, - { 290, -339, 428, -444}, { -68, -783, 735, 772}, - { 245, -555, 468, 47}, { 334, -895, 814, 146}, - { 235, 368, -964, -959}, { -203, 315, -1566, -1217}, - { 801, 17, -276, -354}, { 894, -495, -789, -635}, - { 716, 291, -1189, -357}, { 560, -260, -733, -2}, - { 679, -508, -1429, 211}, { -51, -62, -428, 557}, - { 322, -638, -211, 614}, { -878, -1057, -84, -71}, - { -388, -1415, -167, -318}, { -754, -1574, 214, -539}, - {-1419, -2004, -92, -787}, { -47, -856, -347, -255}, - { 23, -1211, -173, 320}, { -658, -487, -893, 353}, - { -783, -1587, -584, 507}, {-1420, -859, -378, 441}, - {-2095, -1491, -137, 439}, { -321, -1450, -1288, -12}, - { -359, -2113, -553, -8}, { -831, -1918, -1561, 32}, - {-1014, -2487, -1359, -939}, { -475, -311, -169, -236}, - { -907, -426, 276, -611}, { -96, -400, 50, -710}, - { -426, -1022, -10, -985}, { -197, -258, -744, -575}, - { -611, -930, -771, -394}, { -267, -776, -612, -939}, - { -256, -1346, -802, -1122}, { -796, -1570, -825, -754}, - { 712, 876, 141, 227}, { 981, 1509, 85, 124}, - { 1462, 1228, 979, -39}, { 1734, 999, 1481, 440}, - { 2293, 1116, 769, 440}, { 2504, 1480, 1241, 356}, - { 2474, 1909, 1558, 810}, { 917, 1134, 607, -134}, - { 509, 1809, 781, -123}, { 1712, 1506, 559, -423}, - { 2037, 2317, 726, -155}, { 3031, 2676, 1203, 331}, - { 3664, 3274, 1768, 531}, { 1610, 1839, 867, 183}, - { 1774, 1972, 1538, 97}, { 1822, 2158, 1282, 659}, - { 2222, 2758, 1818, 900}, { 3251, 2124, 1723, 996}, - { 3633, 2336, 2408, 1453}, { 2923, 3517, 2567, 1318}, -}; +extern const int16_t ff_g723_1_lsp_band0[LSP_CB_SIZE][3]; +extern const int16_t ff_g723_1_lsp_band1[LSP_CB_SIZE][3]; +extern const int16_t ff_g723_1_lsp_band2[LSP_CB_SIZE][4]; /** * Used for the coding/decoding of the pulses positions * for the MP-MLQ codebook */ -static const int32_t combinatorial_table[PULSE_MAX][SUBFRAME_LEN/GRID_SIZE] = { - {118755, 98280, 80730, 65780, 53130, - 42504, 33649, 26334, 20349, 15504, - 11628, 8568, 6188, 4368, 3003, - 2002, 1287, 792, 462, 252, - 126, 56, 21, 6, 1, - 0, 0, 0, 0, 0}, - - { 23751, 20475, 17550, 14950, 12650, - 10626, 8855, 7315, 5985, 4845, - 3876, 3060, 2380, 1820, 1365, - 1001, 715, 495, 330, 210, - 126, 70, 35, 15, 5, - 1, 0, 0, 0, 0}, - - { 3654, 3276, 2925, 2600, 2300, - 2024, 1771, 1540, 1330, 1140, - 969, 816, 680, 560, 455, - 364, 286, 220, 165, 120, - 84, 56, 35, 20, 10, - 4, 1, 0, 0, 0}, - - { 406, 378, 351, 325, 300, - 276, 253, 231, 210, 190, - 171, 153, 136, 120, 105, - 91, 78, 66, 55, 45, - 36, 28, 21, 15, 10, - 6, 3, 1, 0, 0}, - - { 29, 28, 27, 26, 25, - 24, 23, 22, 21, 20, - 19, 18, 17, 16, 15, - 14, 13, 12, 11, 10, - 9, 8, 7, 6, 5, - 4, 3, 2, 1, 0}, - - { 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1}, -}; - -static const int16_t pitch_contrib[340] = { - 60, 0, 0, 2489, 60, 0, 0, 5217, - 1, 6171, 0, 3953, 0, 10364, 1, 9357, - -1, 8843, 1, 9396, 0, 5794, -1, 10816, - 2, 11606, -2, 12072, 0, 8616, 1, 12170, - 0, 14440, 0, 7787, -1, 13721, 0, 18205, - 0, 14471, 0, 15807, 1, 15275, 0, 13480, - -1, 18375, -1, 0, 1, 11194, -1, 13010, - 1, 18836, -2, 20354, 1, 16233, -1, 0, - 60, 0, 0, 12130, 0, 13385, 1, 17834, - 1, 20875, 0, 21996, 1, 0, 1, 18277, - -1, 21321, 1, 13738, -1, 19094, -1, 20387, - -1, 0, 0, 21008, 60, 0, -2, 22807, - 0, 15900, 1, 0, 0, 17989, -1, 22259, - 1, 24395, 1, 23138, 0, 23948, 1, 22997, - 2, 22604, -1, 25942, 0, 26246, 1, 25321, - 0, 26423, 0, 24061, 0, 27247, 60, 0, - -1, 25572, 1, 23918, 1, 25930, 2, 26408, - -1, 19049, 1, 27357, -1, 24538, 60, 0, - -1, 25093, 0, 28549, 1, 0, 0, 22793, - -1, 25659, 0, 29377, 0, 30276, 0, 26198, - 1, 22521, -1, 28919, 0, 27384, 1, 30162, - -1, 0, 0, 24237, -1, 30062, 0, 21763, - 1, 30917, 60, 0, 0, 31284, 0, 29433, - 1, 26821, 1, 28655, 0, 31327, 2, 30799, - 1, 31389, 0, 32322, 1, 31760, -2, 31830, - 0, 26936, -1, 31180, 1, 30875, 0, 27873, - -1, 30429, 1, 31050, 0, 0, 0, 31912, - 1, 31611, 0, 31565, 0, 25557, 0, 31357, - 60, 0, 1, 29536, 1, 28985, -1, 26984, - -1, 31587, 2, 30836, -2, 31133, 0, 30243, - -1, 30742, -1, 32090, 60, 0, 2, 30902, - 60, 0, 0, 30027, 0, 29042, 60, 0, - 0, 31756, 0, 24553, 0, 25636, -2, 30501, - 60, 0, -1, 29617, 0, 30649, 60, 0, - 0, 29274, 2, 30415, 0, 27480, 0, 31213, - -1, 28147, 0, 30600, 1, 31652, 2, 29068, - 60, 0, 1, 28571, 1, 28730, 1, 31422, - 0, 28257, 0, 24797, 60, 0, 0, 0, - 60, 0, 0, 22105, 0, 27852, 60, 0, - 60, 0, -1, 24214, 0, 24642, 0, 23305, - 60, 0, 60, 0, 1, 22883, 0, 21601, - 60, 0, 2, 25650, 60, 0, -2, 31253, - -2, 25144, 0, 17998 -}; +extern const int32_t ff_g723_1_combinatorial_table[PULSE_MAX][SUBFRAME_LEN/GRID_SIZE]; /** * Number of non-zero pulses in the MP-MLQ excitation */ static const int8_t pulses[4] = {6, 5, 6, 5}; -/** - * Size of the MP-MLQ fixed excitation codebooks - */ -static const int32_t max_pos[4] = {593775, 142506, 593775, 142506}; - -static const int16_t fixed_cb_gain[GAIN_LEVELS] = { - 1, 2, 3, 4, 6, 9, 13, 18, - 26, 38, 55, 80, 115, 166, 240, 348, - 502, 726, 1050, 1517, 2193, 3170, 4582, 6623, -}; - -static const int16_t adaptive_cb_gain85[85 * 20] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 800, 1496, 167, -256, - -338, -39, -136, -1, -4, -6, -73, -8, - -15, 12, 23, 2, 16, 30, 3, -5, - -462, -686, 493, 2575, 311, -13, -28, -14, - -404, -5, -19, 13, 20, 72, 107, -77, - 8, 13, -9, -48, 1483, 144, 784, 928, - 1243, -134, -1, -37, -52, -94, -13, -71, - -6, -84, -8, -44, -112, -10, -59, -70, - -77, 275, 3522, 1056, -1254, 0, -4, -757, - -68, -95, 1, 16, -59, 4, -17, -227, - -5, 21, 269, 80, -125, -40, -264, 381, - 5027, 0, 0, -4, -8, -1542, 0, -2, - 0, 2, 0, 6, 38, 12, 81, -117, - 138, 332, 2215, 2574, 1339, -1, -6, -299, - -404, -109, -2, -18, -44, -21, -52, -348, - -11, -27, -181, -210, 3685, 2883, -887, 866, - -1639, -828, -507, -48, -45, -164, -648, 199, - 156, -194, -152, 46, 368, 288, -88, 86, - 1396, 2146, 2235, 345, 942, -118, -281, -305, - -7, -54, -182, -190, -292, -29, -45, -47, - -80, -123, -128, -19, 13, 4475, 3549, -804, - -655, 0, -1222, -768, -39, -26, -3, -2, - -969, 0, 219, 174, 0, 179, 141, -32, - -724, 254, 242, 6049, 2462, -32, -3, -3, - -2233, -370, 11, 10, -3, 267, -94, -89, - 108, -38, -36, -909, 626, -1713, 6121, 4561, - -1061, -23, -179, -2287, -1270, -68, 65, -233, - 640, -174, 477, -1704, 40, -111, 396, 295, - -350, 1391, 7985, 511, -405, -7, -118, -3892, - -15, -10, 29, 170, -678, 10, -43, -249, - -8, 34, 197, 12, 3144, -529, 608, 2530, - 3878, -603, -17, -22, -390, -918, 101, -116, - 19, -485, 81, -93, -744, 125, -144, -599, - 2589, -689, 3045, 5603, -404, -409, -29, -566, - -1916, -10, 108, -481, 128, -885, 235, -1041, - 63, -17, 75, 138, 3107, 513, 1374, -3594, - -4922, -589, -16, -115, -788, -1478, -97, -260, - -43, 681, 112, 301, 933, 154, 413, -1079, - 2468, 6010, 1107, -390, 1961, -372, -2204, -74, - -9, -234, -905, -166, -406, 58, 143, 26, - -295, -719, -132, 46, 4773, 2766, 2368, 4862, - -4044, -1390, -467, -342, -1443, -998, -806, -690, - -399, -1416, -821, -702, 1178, 682, 584, 1200, - 1665, -1879, 1443, 1701, 8562, -169, -215, -127, - -176, -4475, 190, -146, 165, -172, 195, -149, - -870, 982, -754, -889, 2716, 9011, -1007, 755, - -1785, -450, -4956, -61, -34, -194, -1493, 167, - 554, -125, -415, 46, 296, 982, -109, 82, - -2727, 7548, 1285, 938, 3420, -453, -3478, -100, - -53, -714, 1256, 213, -592, 156, -432, -73, - 569, -1576, -268, -196, 3677, 882, 4050, 1202, - 2323, -825, -47, -1001, -88, -329, -198, -909, - -218, -269, -64, -297, -521, -125, -574, -170, - 2046, -753, 122, 10102, 603, -255, -34, 0, - -6229, -22, 94, -15, 5, -1261, 464, -75, - -75, 27, -4, -372, 449, -1815, 10690, 3870, - -527, -12, -201, -6976, -914, -16, 49, -293, - 1184, -106, 428, -2525, 14, -58, 344, 124, - -941, 2352, 5049, 3650, 2637, -54, -337, -1556, - -813, -424, 135, 290, -725, 209, -524, -1125, - 151, -378, -812, -587, -1879, 796, 3117, 9569, - -404, -215, -38, -593, -5589, -9, 91, 357, - -151, 1097, -464, -1821, -46, 19, 76, 236, - -1715, 2043, -2096, 9946, 4001, -179, -254, -268, - -6038, -977, 213, -219, 261, 1041, -1240, 1272, - 418, -498, 511, -2429, -5772, -618, -3921, 284, - -3155, -2033, -23, -938, -4, -607, -218, -1381, - -148, 100, 10, 68, -1111, -119, -755, 54, - 382, 4748, 8003, -2064, 2198, -8, -1376, -3909, - -260, -294, -110, -186, -2319, 48, 598, 1008, - -51, -637, -1073, 277, -867, 3015, 11926, -1675, - 947, -45, -555, -8681, -171, -54, 159, 631, - -2195, -88, 308, 1219, 50, -174, -690, 96, - -4933, -432, 6757, 3771, 1352, -1485, -11, -2786, - -867, -111, -130, 2034, 178, 1135, 99, -1555, - 407, 35, -557, -311, 152, 9726, 4231, -1928, - 1490, -1, -5774, -1092, -226, -135, -90, -39, - -2511, 17, 1144, 498, -13, -884, -384, 175, - 2512, 193, 9033, 5361, -3148, -385, -2, -4980, - -1754, -605, -29, -1385, -106, -822, -63, -2956, - 482, 37, 1735, 1030, 8464, 2844, 12, 549, - 2132, -4373, -493, 0, -18, -277, -1469, -6, - -2, -284, -95, 0, -1101, -370, -1, -71, - 2141, -2602, 7166, 9046, -1350, -279, -413, -3134, - -4994, -111, 340, -936, 1138, -1182, 1436, -3957, - 176, -214, 590, 745, -244, 278, 13307, 1227, - -161, -3, -4, -10808, -91, -1, 4, 198, - -226, 18, -20, -997, -2, 2, 131, 12, - -1947, 8217, 6269, 917, -2559, -231, -4121, -2399, - -51, -399, 976, 745, -3144, 108, -460, -350, - -304, 1283, 979, 143, -1810, 2061, -2781, 6056, - 10058, -200, -259, -472, -2238, -6174, 227, -307, - 349, 669, -761, 1028, 1111, -1265, 1707, -3717, - 7827, 9161, -3409, 2473, -1510, -3739, -5122, -709, - -373, -139, -4376, 1628, 1906, -1181, -1382, 514, - 721, 844, -314, 228, -1430, 8313, 9541, -2955, - 1626, -124, -4218, -5556, -533, -161, 725, 832, - -4841, -257, 1499, 1721, 142, -825, -947, 293, - 2819, -4247, 5391, 8673, 2756, -485, -1101, -1774, - -4591, -463, 730, -927, 1397, -1492, 2248, -2854, - -474, 714, -907, -1459, 141, 14552, 690, 257, - -112, -1, -12926, -29, -4, 0, -125, -5, - -613, -2, -228, -10, 0, 99, 4, 1, - 11938, -1859, 1806, -962, -884, -8699, -211, -199, - -56, -47, 1355, -1316, 205, 701, -109, 106, - 644, -100, 97, -51, 3728, 1982, 2264, 4584, - 3131, -848, -239, -312, -1282, -598, -451, -515, - -273, -1043, -554, -633, -712, -378, -432, -876, - -1181, 766, 720, 14303, -216, -85, -35, -31, - -12486, -2, 55, 51, -33, 1031, -668, -628, - -15, 10, 9, 189, -4385, 4826, 10112, 1569, - 3388, -1173, -1421, -6242, -150, -700, 1291, 2706, - -2979, 420, -462, -969, 906, -998, -2091, -324, - -448, 1932, 15591, -1842, 657, -12, -227, -14837, - -207, -26, 52, 427, -1838, -50, 217, 1753, - 18, -77, -626, 74, -4141, 1844, 3962, 5517, - 6220, -1046, -207, -958, -1858, -2361, 466, 1001, - -446, 1394, -621, -1334, 1572, -700, -1504, -2094, - 729, -2299, 14755, 3657, -952, -32, -322, -13288, - -816, -55, 102, -656, 2071, -162, 513, -3294, - 42, -133, 857, 212, -1385, 5801, 13339, -3137, - 1344, -117, -2054, -10861, -600, -110, 490, 1127, - -4723, -265, 1111, 2554, 113, -476, -1094, 257, - 4710, 9661, 1073, -2467, 3274, -1354, -5697, -70, - -371, -654, -2777, -308, -633, 709, 1455, 161, - -941, -1930, -214, 493, 1843, -3624, 12422, 6898, - -1559, -207, -802, -9419, -2904, -148, 407, -1397, - 2748, -775, 1526, -5230, 175, -344, 1182, 656, - 1433, 2394, 2507, 1380, 8780, -125, -349, -383, - -116, -4705, -209, -219, -366, -120, -201, -211, - -768, -1283, -1343, -740, -1712, 12915, 5883, -2197, - 991, -179, -10181, -2112, -294, -60, 1350, 615, - -4638, -229, 1732, 789, 103, -781, -356, 133, - 15072, 2158, -1245, 910, -496, -13865, -284, -94, - -50, -15, -1986, 1145, 164, -837, -119, 69, - 456, 65, -37, 27, 4655, 7319, 4916, 586, - -3381, -1322, -3270, -1475, -20, -697, -2079, -1396, - -2196, -166, -261, -175, 960, 1510, 1014, 120, - 1191, -2140, 5120, 13498, -1418, -86, -279, -1600, - -11121, -122, 155, -372, 669, -981, 1763, -4218, - 103, -185, 443, 1168, -1530, -817, 8191, 9632, - -1452, -143, -40, -4095, -5663, -128, -76, 765, - 408, 900, 480, -4815, -135, -72, 726, 854, - -3236, 607, 1696, -2106, 11485, -639, -22, -175, - -270, -8051, 119, 335, -62, -416, 78, 218, - 2268, -425, -1189, 1476, 3203, -1903, -837, 9679, - 7057, -626, -221, -42, -5718, -3039, 372, 163, - -97, -1892, 1124, 494, -1380, 819, 360, -4169, - 213, -655, 17015, 620, -384, -2, -26, -17671, - -23, -9, 8, -221, 681, -8, 24, -644, - 5, -15, 399, 14, 5088, 35, -3339, 3726, - 8488, -1580, 0, -680, -847, -4397, -10, 1037, - 7, -1157, -8, 759, -2636, -18, 1730, -1930, - -988, 1454, -2688, 15039, 2682, -59, -129, -441, - -13805, -439, 87, -162, 238, 907, -1335, 2467, - 161, -238, 440, -2462, -4865, -2842, -53, 5495, - 6523, -1445, -493, 0, -1843, -2597, -844, -16, - -9, 1632, 953, 18, 1937, 1131, 21, -2188, - 3076, 15069, -2914, 1810, -971, -577, -13860, -518, - -200, -57, -2829, 547, 2680, -339, -1665, 322, - 182, 893, -172, 107, 1311, 5355, 11054, 2299, - -3654, -105, -1750, -7458, -322, -814, -428, -885, - -3613, -184, -751, -1551, 292, 1194, 2465, 512, - 4035, 5619, 4618, 1815, 1912, -994, -1927, -1301, - -201, -223, -1384, -1137, -1583, -447, -622, -511, - -471, -656, -539, -211, -2131, 2754, -4501, 12879, - 7432, -277, -463, -1236, -10124, -3371, 358, -585, - 756, 1675, -2165, 3538, 967, -1249, 2042, -5842, - 5618, -515, 3219, -4149, 4857, -1926, -16, -632, - -1050, -1440, 176, -1104, 101, 1422, -130, 815, - -1666, 152, -954, 1230, 1838, -1709, 1139, 16867, - 716, -206, -178, -79, -17366, -31, 191, -127, - 118, -1892, 1759, -1173, -80, 74, -49, -737, - 1978, -3845, 10050, 11854, -2492, -238, -902, -6164, - -8576, -379, 464, -1213, 2358, -1431, 2782, -7271, - 301, -585, 1529, 1803, -2600, 11246, 11289, -3647, - 1463, -412, -7720, -7778, -812, -130, 1784, 1791, - -7749, -578, 2504, 2513, 232, -1004, -1008, 325, - 3442, 907, 2725, 8970, 3638, -723, -50, -453, - -4911, -808, -190, -572, -150, -1884, -496, -1492, - -764, -201, -605, -1992, -126, 17498, 3481, -2003, - 1090, 0, -18689, -739, -244, -72, 135, 26, - -3717, -15, 2139, 425, 8, -1165, -231, 133, - -1814, 1048, -2164, 4070, 16272, -200, -67, -285, - -1011, -16160, 116, -239, 138, 450, -260, 537, - 1801, -1041, 2149, -4042, 9354, 12580, -1883, 962, - -617, -5341, -9660, -216, -56, -23, -7183, 1075, - 1446, -549, -738, 110, 352, 474, -71, 36, - 1708, 4199, 7387, 6335, 1003, -178, -1076, -3330, - -2449, -61, -437, -770, -1893, -660, -1623, -2856, - -104, -257, -452, -388, -2624, 5623, 17310, -2353, - 592, -420, -1930, -18288, -338, -21, 900, 2772, - -5941, -376, 807, 2486, 94, -203, -625, 85, - 1211, -850, 1193, -1926, 15992, -89, -44, -86, - -226, -15609, 62, -88, 61, 142, -100, 140, - -1182, 830, -1165, 1880, 3983, -2054, 11506, -19, - 3622, -968, -257, -8080, 0, -801, 499, -2797, - 1442, 4, -2, 13, -880, 454, -2544, 4, - -786, -1354, 16092, 7246, -1665, -37, -111, -15805, - -3205, -169, -65, 772, 1330, 348, 599, -7117, - -80, -137, 1636, 736, -4316, -511, 6674, 11665, - 4633, -1137, -15, -2719, -8305, -1310, -134, 1758, - 208, 3073, 364, -4752, 1220, 144, -1887, -3299, - 7912, 4557, 1937, 1885, 7037, -3821, -1267, -229, - -216, -3022, -2200, -935, -538, -910, -524, -222, - -3398, -1957, -832, -809, 3434, 2967, 5867, 8196, - 8766, -720, -537, -2101, -4100, -4690, -622, -1230, - -1062, -1718, -1484, -2935, -1837, -1588, -3139, -4385, - 5881, 9176, 8119, 3934, 3355, -2111, -5139, -4023, - -944, -687, -3294, -2914, -4547, -1412, -2203, -1949, - -1204, -1879, -1662, -805 -}; - -static const int16_t adaptive_cb_gain170[170 * 20] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 776, 212, 715, 670, - 809, -36, -2, -31, -27, -39, -10, -33, - -9, -31, -8, -29, -38, -10, -35, -33, - 1296, 1316, -168, -320, -815, -102, -105, -1, - -6, -40, -104, 13, 13, 25, 25, -3, - 64, 65, -8, -15, -589, 680, 2478, 308, - -596, -21, -28, -375, -5, -21, 24, 89, - -102, 11, -12, -46, -21, 24, 90, 11, - -735, -487, -5, 2948, 468, -33, -14, 0, - -530, -13, -21, 0, 0, 132, 87, 0, - 21, 13, 0, -84, 1042, 1730, 1068, 333, - 626, -66, -182, -69, -6, -23, -110, -67, - -112, -21, -35, -21, -39, -66, -40, -12, - 486, -769, 4074, 2825, -1107, -14, -36, -1013, - -487, -74, 22, -120, 191, -83, 132, -702, - 32, -52, 275, 191, 1521, -767, -124, 4320, - 1026, -141, -35, 0, -1139, -64, 71, 11, - -5, -401, 202, 32, -95, 48, 7, -270, - 2425, 1267, 3439, -91, -1166, -359, -98, -722, - 0, -83, -187, -509, -266, 13, 7, 19, - 172, 90, 244, -6, -1251, 975, 173, 4039, - 2005, -95, -58, -1, -996, -245, 74, 13, - -10, 308, -240, -42, 153, -119, -21, -494, - 1820, 632, 1322, 2062, 1031, -202, -24, -106, - -259, -64, -70, -146, -51, -229, -79, -166, - -114, -39, -83, -129, -447, 4904, 244, -315, - -2038, -12, -1467, -3, -6, -253, 134, 6, - -73, -8, 94, 4, -55, 610, 30, -39, - -208, -1102, 463, -448, 5653, -2, -74, -13, - -12, -1950, -14, 5, 31, -5, -30, 12, - 71, 380, -159, 154, 4739, 2600, -1864, 856, - -1554, -1371, -412, -212, -44, -147, -752, 539, - 295, -247, -135, 97, 449, 246, -176, 81, - 1894, 3533, 35, -26, 2145, -219, -762, 0, - 0, -280, -408, -4, -7, 3, 5, 0, - -248, -462, -4, 3, -2699, 1841, 4072, 2443, - 1582, -444, -207, -1012, -364, -152, 303, 670, - -457, 402, -274, -607, 260, -177, -393, -236, - -844, 3358, 6106, -1059, -537, -43, -688, -2275, - -68, -17, 173, 314, -1251, -54, 217, 395, - -27, 110, 200, -34, 1251, 1016, 3020, 2210, - 1445, -95, -63, -556, -298, -127, -77, -230, - -187, -168, -137, -407, -110, -89, -266, -194, - 2099, 2277, 4038, 3533, -2870, -269, -316, -995, - -762, -503, -291, -517, -561, -452, -491, -871, - 367, 399, 707, 619, 400, -1114, 8516, 2422, - -1117, -9, -75, -4426, -358, -76, 27, -208, - 579, -59, 164, -1259, 27, -75, 580, 165, - -4398, -2011, 3912, -2407, 2258, -1180, -247, -934, - -353, -311, -540, 1050, 480, -646, -295, 575, - 606, 277, -539, 331, 1767, -1447, 4240, 6160, - -757, -190, -127, -1097, -2316, -35, 156, -457, - 374, -664, 544, -1594, 81, -66, 195, 284, - 1594, -1463, 1035, 6938, 1920, -155, -130, -65, - -2938, -225, 142, -100, 92, -675, 619, -438, - -186, 171, -121, -813, -562, 4716, 4085, -591, - 2421, -19, -1357, -1018, -21, -357, 162, 140, - -1175, -20, 170, 147, 83, -696, -603, 87, - 1552, 8778, -935, 354, -1424, -147, -4703, -53, - -7, -123, -831, 88, 501, -33, -189, 20, - 134, 763, -81, 30, 4831, -4431, 41, -1479, - -2976, -1424, -1198, 0, -133, -540, 1306, -12, - 11, 436, -400, 3, 877, -804, 7, -268, - 2090, 1192, 1006, 1645, 4853, -266, -86, -61, - -165, -1437, -152, -128, -73, -210, -119, -101, - -619, -353, -298, -487, 2386, 5712, 1426, -94, - 1350, -347, -1991, -124, 0, -111, -832, -207, - -497, 13, 32, 8, -196, -470, -117, 7, - -1349, 1091, 1659, 8891, 313, -111, -72, -168, - -4825, -5, 89, 136, -110, 732, -592, -900, - 25, -20, -31, -170, 9980, 916, -381, -808, - 88, -6080, -51, -8, -39, 0, -558, 232, - 21, 492, 45, -18, -53, -4, 2, 4, - 2338, -1031, -248, 3928, 6484, -333, -64, -3, - -942, -2566, 147, 35, -15, -560, 247, 59, - -925, 408, 98, -1555, 6166, -1240, -337, 3672, - -1277, -2320, -93, -6, -823, -99, 466, 126, - -25, -1382, 278, 75, 480, -96, -26, 286, - 4377, -132, -2588, 1701, 4865, -1169, -1, -409, - -176, -1444, 35, 691, -20, -454, 13, 268, - -1299, 39, 768, -505, 2594, 3295, 3944, 1481, - 682, -410, -662, -949, -133, -28, -521, -624, - -793, -234, -297, -356, -108, -137, -164, -61, - 4151, 624, 815, 4485, 2229, -1052, -23, -40, - -1228, -303, -158, -206, -31, -1136, -170, -223, - -565, -84, -111, -610, -3575, -361, 4924, 2791, - 4698, -780, -7, -1480, -475, -1347, -78, 1074, - 108, 609, 61, -839, 1025, 103, -1412, -800, - -2518, 3791, 8623, 315, 2465, -387, -877, -4538, - -6, -370, 582, 1325, -1995, 48, -73, -166, - 378, -570, -1297, -47, -691, 2989, 9957, -421, - -1142, -29, -545, -6051, -10, -79, 126, 420, - -1817, -17, 76, 256, -48, 208, 694, -29, - -1918, 104, -3190, -3410, -4440, -224, 0, -621, - -709, -1203, 12, -373, 20, -399, 21, -664, - -519, 28, -864, -924, -3359, -1668, 1854, 6939, - 1430, -688, -169, -209, -2939, -124, -341, 380, - 188, 1422, 706, -785, 293, 145, -161, -606, - 42, 9706, 3164, -952, 907, 0, -5750, -611, - -55, -50, -25, -8, -1874, 2, 564, 183, - -2, -537, -175, 52, 1607, 785, 2862, 4327, - 3307, -157, -37, -500, -1143, -667, -77, -280, - -137, -424, -207, -756, -324, -158, -577, -873, - 6801, 3416, 2227, 1682, -3217, -2823, -712, -302, - -172, -631, -1418, -924, -464, -698, -350, -228, - 1335, 670, 437, 330, 3459, 3898, 364, 7841, - -2640, -730, -927, -8, -3753, -425, -823, -76, - -86, -1655, -1865, -174, 557, 628, 58, 1263, - -5902, -3458, -2465, -1886, 4334, -2126, -730, -371, - -217, -1146, -1245, -888, -520, -679, -398, -283, - 1561, 915, 652, 499, -3710, 1133, 7849, 3443, - -215, -840, -78, -3760, -723, -2, 256, 1777, - -543, 779, -238, -1649, -48, 14, 103, 45, - 4132, 2828, 2, -4212, -4116, -1042, -488, 0, - -1083, -1034, -713, 0, 0, 1062, 727, 0, - 1038, 710, 0, -1058, 5875, 8496, -1796, 1376, - -1786, -2107, -4406, -197, -115, -194, -3047, 644, - 931, -493, -713, 150, 640, 926, -195, 150, - 3143, 3483, 3546, -793, 4489, -603, -740, -767, - -38, -1230, -668, -680, -754, 152, 168, 171, - -861, -954, -971, 217, 2845, 7965, 3695, -5432, - 3978, -494, -3873, -833, -1801, -966, -1383, -641, - -1796, 943, 2641, 1225, -691, -1934, -897, 1319, - 1538, 150, 7139, 2049, 3097, -144, -1, -3110, - -256, -585, -14, -670, -65, -192, -18, -892, - -290, -28, -1349, -387, 618, 7520, 4729, -238, - -3373, -23, -3452, -1365, -3, -694, -283, -178, - -2170, 8, 109, 68, 127, 1548, 973, -49, - 2965, -3013, 7912, 7076, -1997, -536, -554, -3821, - -3056, -243, 545, -1431, 1455, -1280, 1301, -3417, - 361, -367, 964, 862, 2443, -929, -1113, 9677, - 4138, -364, -52, -75, -5716, -1045, 138, 166, - -63, -1443, 549, 657, -617, 234, 281, -2444, - 1966, 3309, 10085, -3399, 2105, -236, -668, -6207, - -705, -270, -397, -1210, -2037, 408, 686, 2092, - -252, -425, -1295, 436, -112, -1368, 8868, 4822, - 2048, 0, -114, -4800, -1419, -256, -9, 61, - 740, 33, 402, -2610, 14, 171, -1108, -602, - -2597, 438, -1839, 6229, 7266, -411, -11, -206, - -2368, -3223, 69, -291, 49, 987, -166, 699, - 1152, -194, 816, -2763, 3454, 553, 9127, 4946, - -5596, -728, -18, -5084, -1493, -1911, -116, -1924, - -308, -1042, -166, -2755, 1179, 188, 3117, 1689, - -532, -663, 12262, 2495, -1004, -17, -26, -9177, - -380, -61, -21, 398, 496, 81, 101, -1867, - -32, -40, 751, 152, -2100, 1317, -1509, 11425, - 2997, -269, -105, -139, -7967, -548, 168, -193, - 121, 1464, -918, 1052, 384, -240, 276, -2090, - 1193, -2697, 11259, 5373, -763, -86, -444, -7737, - -1762, -35, 196, -819, 1853, -391, 884, -3692, - 55, -125, 525, 250, 2405, -471, 11079, 203, - 782, -353, -13, -7491, -2, -37, 69, -1626, - 318, -29, 5, -137, -114, 22, -529, -9, - -1871, 5685, 11290, -2662, 1353, -213, -1972, -7780, - -432, -111, 649, 1289, -3917, -304, 923, 1834, - 154, -469, -932, 220, -3768, 5927, -3093, 5041, - 5212, -866, -2144, -584, -1551, -1658, 1363, -711, - 1119, 1159, -1824, 951, 1198, -1885, 984, -1603, - -2546, 9502, 5969, -2440, 1928, -395, -5511, -2175, - -363, -226, 1477, 927, -3462, -379, 1415, 889, - 299, -1118, -702, 287, -4963, 3568, 4592, 5508, - 3451, -1503, -777, -1287, -1851, -727, 1080, 1391, - -1000, 1668, -1199, -1543, 1045, -751, -967, -1160, - 1745, -2586, 3983, 10899, -1551, -186, -408, -968, - -7250, -146, 275, -424, 628, -1161, 1720, -2649, - 165, -244, 377, 1032, 867, -456, -727, 3369, - 11822, -45, -12, -32, -692, -8531, 24, 38, - -20, -178, 93, 149, -625, 329, 525, -2431, - 7535, 2422, 1926, 1405, 1599, -3466, -358, -226, - -120, -156, -1114, -886, -284, -646, -207, -165, - -735, -236, -188, -137, 1041, -735, -142, 13209, - 1515, -66, -33, -1, -10649, -140, 46, 9, - -6, -839, 593, 114, -96, 68, 13, -1222, - 7950, 6745, -1444, -1008, 2721, -3857, -2777, -127, - -62, -452, -3273, 700, 594, 489, 415, -88, - -1320, -1120, 239, 167, -4754, -1379, 4522, -578, - -5733, -1379, -116, -1248, -20, -2006, -400, 1312, - 380, -167, -48, 159, -1663, -482, 1582, -202, - 3220, 5978, 5923, 2430, -2689, -633, -2181, -2141, - -360, -441, -1175, -1164, -2161, -477, -886, -878, - 528, 981, 972, 398, 377, 1312, 13978, -1470, - 677, -8, -105, -11925, -132, -28, -30, -321, - -1119, 33, 117, 1254, -15, -54, -577, 60, - -3435, 6770, 314, -885, 5686, -720, -2797, -6, - -47, -1973, 1419, 65, -129, -185, 366, 16, - 1192, -2349, -109, 307, 3171, 8774, -2260, 2679, - 3069, -613, -4699, -312, -438, -575, -1698, 437, - 1210, -518, -1435, 369, -594, -1643, 423, -501, - 5557, 1509, 5407, -125, -7386, -1884, -139, -1784, - 0, -3330, -511, -1834, -498, 42, 11, 41, - 2505, 680, 2438, -56, -2838, 2595, 13228, 271, - 1793, -491, -411, -10680, -4, -196, 449, 2291, - -2095, 47, -42, -219, 310, -284, -1447, -29, - 664, -278, 14966, 951, -711, -26, -4, -13672, - -55, -30, 11, -606, 253, -38, 16, -869, - 28, -12, 650, 41, 808, 1770, 8658, 5863, - -1486, -39, -191, -4576, -2098, -134, -87, -427, - -935, -289, -633, -3098, 73, 160, 785, 531, - 3063, 1539, 2000, -542, 9576, -572, -144, -244, - -17, -5597, -287, -374, -188, 101, 51, 66, - -1790, -900, -1169, 317, 514, 14083, -323, 896, - -891, -16, -12106, -6, -49, -48, -442, 10, - 277, -28, -770, 17, 27, 766, -17, 48, - 892, 158, 5237, 11057, -1603, -48, -1, -1674, - -7462, -156, -8, -285, -50, -602, -106, -3534, - 87, 15, 512, 1082, -1612, 2564, -4296, 12526, - 5710, -158, -401, -1126, -9576, -1990, 252, -422, - 672, 1232, -1960, 3284, 561, -893, 1497, -4365, - 4889, -6878, 612, 6109, 4753, -1459, -2887, -22, - -2277, -1379, 2052, -182, 257, -1823, 2564, -228, - -1418, 1995, -177, -1772, 3053, -506, 2403, 9625, - 1322, -569, -15, -352, -5655, -106, 94, -448, - 74, -1794, 297, -1412, -246, 40, -194, -777, - -754, 12904, 4480, -2113, 1471, -34, -10163, -1225, - -272, -132, 594, 206, -3529, -97, 1664, 577, - 67, -1159, -402, 189, 4255, 1476, 5055, 2393, - 2912, -1105, -132, -1559, -349, -517, -383, -1313, - -455, -621, -215, -738, -756, -262, -898, -425, - -1371, 535, 1417, 14604, -997, -114, -17, -122, - -13017, -60, 44, 118, -46, 1222, -477, -1263, - -83, 32, 86, 888, 5368, -1744, 4083, -1236, - 3753, -1758, -185, -1017, -93, -860, 571, -1338, - 434, 405, -131, 308, -1229, 399, -935, 283, - 1588, -3097, 14415, 3699, -1171, -154, -585, -12683, - -835, -83, 300, -1397, 2725, -358, 699, -3255, - 113, -221, 1030, 264, 212, 7989, 9471, -3344, - 2009, -2, -3895, -5475, -682, -246, -103, -123, - -4618, 43, 1630, 1933, -26, -979, -1161, 410, - 856, 2294, -627, 6930, 6929, -44, -321, -24, - -2931, -2930, -119, 32, 87, -362, -970, 265, - -362, -970, 265, -2931, 2357, -4187, 7162, 7683, - 3371, -339, -1070, -3131, -3603, -693, 602, -1030, - 1830, -1105, 1963, -3359, -485, 861, -1474, -1581, - 350, 4585, 14053, -3819, 1218, -7, -1283, -12054, - -890, -90, -97, -300, -3933, 81, 1068, 3275, - -26, -341, -1045, 284, -3248, 3531, 475, 2137, - 11711, -644, -761, -13, -278, -8372, 700, 94, - -102, 423, -460, -62, 2322, -2524, -340, -1528, - -3017, 3852, 1725, 8440, 5257, -555, -905, -181, - -4348, -1686, 709, 317, -405, 1554, -1984, -889, - 968, -1236, -553, -2708, -909, 3196, 15512, -2528, - 1066, -50, -623, -14686, -390, -69, 177, 861, - -3026, -140, 493, 2393, 59, -208, -1009, 164, - 959, -3370, 9617, 9545, -1761, -56, -693, -5645, - -5561, -189, 197, -563, 1978, -558, 1963, -5603, - 103, -362, 1034, 1026, 7575, 11796, -4845, 3252, - -1703, -3502, -8493, -1433, -645, -177, -5454, 2240, - 3488, -1503, -2341, 961, 787, 1226, -503, 338, - 6409, 1722, 1764, -4191, 6015, -2507, -181, -189, - -1072, -2208, -673, -690, -185, 1639, 440, 451, - -2353, -632, -647, 1538, -2420, 12161, 5038, 1286, - -2098, -357, -9027, -1549, -100, -268, 1796, 744, - -3740, 190, -954, -395, -310, 1557, 645, 164, - -2232, -1341, 7246, 9470, -1977, -304, -109, -3204, - -5474, -238, -182, 987, 593, 1290, 775, -4188, - -269, -161, 874, 1143, 1030, 7034, 4231, 1551, - 3077, -64, -3019, -1093, -146, -577, -442, -266, - -1816, -97, -666, -400, -193, -1321, -794, -291, - 5121, 11835, -477, -1749, 2298, -1601, -8549, -13, - -186, -322, -3699, 149, 344, 546, 1264, -50, - -718, -1660, 66, 245, -3328, 3827, 5921, 9976, - -1045, -676, -894, -2140, -6075, -66, 777, 1203, - -1383, 2027, -2330, -3605, -212, 244, 377, 636, - 3813, 5718, -4666, -3412, 5674, -887, -1995, -1329, - -710, -1965, -1331, 1086, 1628, 794, 1191, -972, - -1320, -1980, 1616, 1181, 1348, -3672, 13154, 6938, - -1690, -110, -823, -10561, -2938, -174, 302, -1082, - 2948, -570, 1555, -5570, 139, -379, 1357, 716, - 2151, -3586, 6949, 12131, -1224, -282, -785, -2947, - -8982, -91, 470, -912, 1521, -1592, 2655, -5145, - 160, -268, 519, 906, -2889, 9647, 10276, -2728, - 995, -509, -5680, -6445, -454, -60, 1701, 1812, - -6051, -481, 1606, 1711, 175, -586, -624, 165, - 6177, 2184, 555, 1985, 6589, -2329, -291, -18, - -240, -2650, -823, -209, -74, -748, -264, -67, - -2484, -878, -223, -798, -492, 391, 17166, -681, - 240, -14, -9, -17987, -28, -3, 11, 515, - -410, -20, 16, 713, 7, -5, -252, 10, - 12628, 5448, -2630, 3011, -2695, -9733, -1811, -422, - -553, -443, -4199, 2027, 874, -2321, -1001, 483, - 2077, 896, -432, 495, -3628, -534, 3447, 7002, - 6751, -803, -17, -725, -2992, -2782, -118, 763, - 112, 1550, 228, -1473, 1495, 220, -1420, -2885, - -5239, 5901, 8107, 3650, 4846, -1675, -2125, -4012, - -813, -1433, 1887, 2592, -2920, 1167, -1315, -1806, - 1550, -1745, -2398, -1080, 6157, 6678, 4099, -1074, - 2348, -2314, -2722, -1025, -70, -336, -2509, -1540, - -1670, 403, 437, 268, -882, -957, -587, 153, - 1079, 16099, 242, -881, 1690, -71, -15820, -3, - -47, -174, -1060, -16, -238, 58, 865, 13, - -111, -1661, -25, 90, -278, 227, -1039, 1636, - 16945, -4, -3, -65, -163, -17526, 3, -17, - 14, 27, -22, 103, 287, -234, 1074, -1693, - 15778, -1454, 574, -603, -107, -15195, -129, -20, - -22, 0, 1400, -553, 51, 581, -53, 21, - 103, -9, 3, -3, 2406, -836, 13224, 7993, - -4266, -353, -42, -10673, -3899, -1111, 122, -1942, - 674, -1174, 407, -6451, 626, -217, 3443, 2081, - 3184, 14368, -3336, 2255, -1801, -619, -12600, -679, - -310, -198, -2793, 648, 2926, -438, -1977, 459, - 350, 1580, -366, 247, -1698, 17076, 2504, -539, - -646, -176, -17798, -382, -17, -25, 1770, 259, - -2610, -55, 561, 82, -67, 673, 98, -21, - 2375, -797, -2696, 14483, 5383, -344, -38, -443, - -12803, -1769, 115, 391, -131, -2100, 705, 2384, - -780, 262, 886, -4759, -2691, 2554, -4520, 9573, - 10655, -442, -398, -1247, -5594, -6930, 419, -742, - 704, 1572, -1492, 2641, 1750, -1661, 2939, -6226, - -4332, -4399, -1657, 4880, 7375, -1145, -1181, -167, - -1453, -3319, -1163, -438, -444, 1290, 1310, 493, - 1950, 1980, 745, -2196, -3498, 7405, 9955, 2693, - -2971, -746, -3347, -6049, -442, -538, 1581, 2125, - -4499, 575, -1217, -1636, -634, 1342, 1805, 488, - 6717, -3792, 7739, 2798, 3489, -2754, -877, -3655, - -477, -743, 1554, -3173, 1791, -1147, 647, -1321, - -1430, 807, -1648, -595, 5263, 9770, 3463, 1069, - -3971, -1690, -5826, -732, -69, -962, -3138, -1112, - -2065, -343, -637, -226, 1275, 2368, 839, 259, - 1243, -2634, 16772, 1871, 332, -94, -423, -17169, - -213, -6, 199, -1273, 2696, -142, 300, -1915, - -25, 53, -339, -37, 2691, 2836, 3105, 5711, - 4817, -442, -491, -588, -1991, -1416, -465, -510, - -537, -938, -988, -1082, -791, -834, -913, -1679, - 4366, 2944, 7210, 3627, 1161, -1163, -529, -3172, - -803, -82, -784, -1921, -1295, -966, -651, -1596, - -309, -208, -511, -257, 13888, 3951, -671, -2305, - 3354, -11773, -953, -27, -324, -686, -3349, 569, - 161, 1954, 556, -94, -2843, -809, 137, 472, - 7053, 5847, 2929, 8378, -4794, -3036, -2086, -523, - -4284, -1403, -2517, -1261, -1045, -3607, -2990, -1498, - 2064, 1711, 857, 2451, -2191, 12838, 9182, -3915, - 1617, -293, -10059, -5146, -935, -159, 1717, 1228, - -7195, -523, 3068, 2194, 216, -1267, -906, 386, - -4881, 13114, 5767, -435, 4155, -1454, -10498, -2030, - -11, -1054, 3907, 1718, -4616, -129, 348, 153, - 1238, -3326, -1462, 110, 7843, -1250, 210, 7106, - -5203, -3754, -95, -2, -3082, -1652, 598, -100, - 16, -3402, 542, -91, 2491, -397, 66, 2257, - -2463, 8168, 14551, -3908, 1828, -370, -4072, -12923, - -932, -204, 1228, 2188, -7254, -587, 1948, 3471, - 274, -911, -1623, 436, -1579, 347, -272, -2735, - 16031, -152, -7, -4, -456, -15686, 33, -26, - 5, -263, 58, -45, 1545, -340, 266, 2676, - -6327, 1328, 5093, -5079, 7617, -2443, -107, -1583, - -1574, -3541, 513, 1967, -413, -1961, 411, 1578, - 2941, -617, -2367, 2361, 3286, -4509, 11306, 11025, - -2623, -659, -1241, -7802, -7419, -420, 904, -2267, - 3112, -2211, 3034, -7608, 526, -722, 1810, 1765, - 5567, 17853, -3754, 1166, -519, -1892, -19455, -860, - -83, -16, -6067, 1275, 4090, -396, -1271, 267, - 176, 566, -119, 37, -2136, -424, 15292, 5108, - -1648, -278, -10, -14273, -1593, -165, -55, 1993, - 396, 666, 132, -4768, -214, -42, 1538, 514, - 2267, -3297, 2549, 16563, -791, -313, -663, -396, - -16745, -38, 456, -352, 513, -2291, 3333, -2576, - 109, -159, 123, 799, 3655, 1899, -3364, 6279, - 12510, -815, -220, -690, -2406, -9552, -423, 750, - 390, -1400, -728, 1289, -2791, -1450, 2568, -4794, - 8052, 2285, -6193, 5138, 6003, -3957, -318, -2341, - -1611, -2199, -1123, 3044, 864, -2525, -716, 1942, - -2950, -837, 2269, -1882, -386, -2291, 7679, 15387, - -2723, -9, -320, -3599, -14452, -452, -54, 181, - 1074, 362, 2152, -7212, -64, -380, 1276, 2557, - 2777, -1173, 3984, 13079, 2508, -470, -84, -969, - -10440, -384, 198, -675, 285, -2217, 936, -3180, - -425, 179, -610, -2002, -1879, 1771, -2684, 16705, - 1833, -215, -191, -439, -17032, -205, 203, -308, - 290, 1916, -1805, 2736, 210, -198, 300, -1869, - 1052, 4495, 15519, 1467, -4032, -67, -1233, -14700, - -131, -992, -288, -997, -4257, -94, -402, -1389, - 259, 1106, 3819, 361, 3010, 2544, 6969, 7559, - 1996, -553, -395, -2964, -3487, -243, -467, -1280, - -1082, -1388, -1174, -3215, -366, -310, -849, -921, - -5209, -1867, 8713, 10351, 1549, -1656, -212, -4634, - -6540, -146, -593, 2770, 993, 3291, 1180, -5505, - 492, 176, -824, -979, -4314, 8513, 913, 7547, - -2723, -1135, -4423, -50, -3476, -452, 2241, 240, - -474, 1987, -3921, -420, -717, 1415, 151, 1254, - 12929, -1219, 2448, 1757, 6303, -10204, -90, -365, - -188, -2425, 962, -1932, 182, -1386, 130, -262, - -4974, 469, -941, -676, 6465, 4132, 3167, 3160, - 5697, -2551, -1042, -612, -609, -1981, -1630, -1249, - -798, -1247, -797, -611, -2248, -1437, -1101, -1099, - -3636, 4859, 18914, -1335, 810, -807, -1441, -21836, - -108, -40, 1078, 4198, -5609, -296, 396, 1541, - 179, -240, -936, 66, 8844, 7864, 654, -4063, - -5680, -4774, -3774, -26, -1007, -1969, -4245, -353, - -314, 2193, 1950, 162, 3066, 2726, 226, -1408, - 1859, 2634, 9228, 996, 9464, -211, -423, -5197, - -60, -5467, -299, -1047, -1483, -113, -160, -561, - -1074, -1521, -5330, -575, 2949, 12260, 10290, -497, - -3943, -530, -9174, -6463, -15, -949, -2206, -1852, - -7700, 89, 372, 312, 709, 2950, 2476, -119, - -2903, 1552, 14867, 9970, -496, -514, -147, -13491, - -6068, -15, 275, 2634, -1408, 1766, -944, -9047, - -87, 47, 450, 302, 3243, 8234, 7586, 3373, - 2151, -642, -4138, -3512, -694, -282, -1630, -1501, - -3812, -667, -1695, -1561, -425, -1081, -996, -442, - -9631, 60, 3501, 5359, 10150, -5662, 0, -748, - -1752, -6288, 35, 2058, -12, 3150, -19, -1145, - 5967, -37, -2169, -3320, -6874, -2553, -5446, -2195, - -7841, -2884, -397, -1810, -294, -3753, -1071, -2285, - -848, -921, -342, -729, -3290, -1221, -2606, -1050, - -3413, -1141, 4630, 13612, 7897, -711, -79, -1308, - -11310, -3806, -237, 964, 322, 2836, 948, -3847, - 1645, 550, -2231, -6561, 4410, -5678, 8006, -3992, - 3811, -1187, -1968, -3912, -973, -886, 1528, -2155, - 2775, 1074, -1383, 1951, -1025, 1321, -1862, 928, - 5659, 11535, 2203, -452, 7169, -1954, -8121, -296, - -12, -3137, -3984, -761, -1551, 156, 318, 60, - -2476, -5048, -964, 197, 2914, -2914, 3485, -3965, - 13675, -518, -518, -741, -959, -11414, 518, -620, - 620, 705, -705, 843, -2433, 2432, -2909, 3310, - 7843, 1907, 1022, 8882, 7972, -3755, -222, -63, - -4815, -3879, -913, -489, -119, -4252, -1034, -554, - -3816, -928, -497, -4322, 13807, 9531, 1436, 1612, - 1779, -11636, -5544, -125, -158, -193, -8032, -1210, - -835, -1358, -938, -141, -1499, -1035, -156, -175, - 13620, -5337, 5450, -2263, 1723, -11322, -1738, -1813, - -312, -181, 4436, -4531, 1775, 1881, -737, 752, - -1432, 561, -573, 238, 5297, 8374, 8872, 7694, - 6538, -1712, -4280, -4804, -3613, -2609, -2707, -2868, - -4534, -2487, -3932, -4166, -2113, -3341, -3540, -3070 -}; - -/** - * 0.65^i (Zero part) and 0.75^i (Pole part) scaled by 2^15 - */ -static const int16_t postfilter_tbl[2][LPC_ORDER] = { - /* Zero */ - {21299, 13844, 8999, 5849, 3802, 2471, 1606, 1044, 679, 441}, - /* Pole */ - {24576, 18432, 13824, 10368, 7776, 5832, 4374, 3281, 2460, 1845} -}; - -/** - * Hamming window coefficients scaled by 2^15 - */ -static const int16_t hamming_window[LPC_FRAME] = { - 2621, 2631, 2659, 2705, 2770, 2853, 2955, 3074, 3212, 3367, - 3541, 3731, 3939, 4164, 4405, 4663, 4937, 5226, 5531, 5851, - 6186, 6534, 6897, 7273, 7661, 8062, 8475, 8899, 9334, 9780, - 10235, 10699, 11172, 11653, 12141, 12636, 13138, 13645, 14157, 14673, - 15193, 15716, 16242, 16769, 17298, 17827, 18356, 18884, 19411, 19935, - 20457, 20975, 21489, 21999, 22503, 23002, 23494, 23978, 24455, 24924, - 25384, 25834, 26274, 26704, 27122, 27529, 27924, 28306, 28675, 29031, - 29373, 29700, 30012, 30310, 30592, 30857, 31107, 31340, 31557, 31756, - 31938, 32102, 32249, 32377, 32488, 32580, 32654, 32710, 32747, 32766, - 32766, 32747, 32710, 32654, 32580, 32488, 32377, 32249, 32102, 31938, - 31756, 31557, 31340, 31107, 30857, 30592, 30310, 30012, 29700, 29373, - 29031, 28675, 28306, 27924, 27529, 27122, 26704, 26274, 25834, 25384, - 24924, 24455, 23978, 23494, 23002, 22503, 21999, 21489, 20975, 20457, - 19935, 19411, 18884, 18356, 17827, 17298, 16769, 16242, 15716, 15193, - 14673, 14157, 13645, 13138, 12636, 12141, 11653, 11172, 10699, 10235, - 9780, 9334, 8899, 8475, 8062, 7661, 7273, 6897, 6534, 6186, - 5851, 5531, 5226, 4937, 4663, 4405, 4164, 3939, 3731, 3541, - 3367, 3212, 3074, 2955, 2853, 2770, 2705, 2659, 2631, 2621 -}; - -/** - * Binomial window coefficients scaled by 2^15 - */ -static const int16_t binomial_window[LPC_ORDER] = { - 32749, 32695, 32604, 32477, 32315, 32118, 31887, 31622, 31324, 30995 -}; - -/** - * 0.994^i scaled by 2^15 - */ -static const int16_t bandwidth_expand[LPC_ORDER] = { - 32571, 32376, 32182, 31989, 31797, 31606, 31416, 31228, 31040, 30854 -}; - -/** - * 0.5^i scaled by 2^15 - */ -static const int16_t percept_flt_tbl[2][LPC_ORDER] = { - /* Zero part */ - {29491, 26542, 23888, 21499, 19349, 17414, 15673, 14106, 12695, 11425}, - /* Pole part */ - {16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32} -}; - -static const int cng_adaptive_cb_lag[4] = { 1, 0, 1, 3 }; - -static const int cng_filt[4] = { 273, 998, 499, 333 }; +extern const int16_t ff_g723_1_fixed_cb_gain[GAIN_LEVELS]; -static const int cng_bseg[3] = { 2048, 18432, 231233 }; +extern const int16_t ff_g723_1_adaptive_cb_gain85 [ 85 * 20]; +extern const int16_t ff_g723_1_adaptive_cb_gain170[170 * 20]; #endif /* AVCODEC_G723_1_H */ diff -Nru ffmpeg-4.2.2/libavcodec/g726.c ffmpeg-4.4/libavcodec/g726.c --- ffmpeg-4.2.2/libavcodec/g726.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/g726.c 2021-04-08 21:28:39.000000000 +0000 @@ -513,7 +513,7 @@ .init = g726_decode_init, .decode = g726_decode_frame, .flush = g726_decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; #endif @@ -526,7 +526,7 @@ .init = g726_decode_init, .decode = g726_decode_frame, .flush = g726_decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM little-endian"), }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/g729dec.c ffmpeg-4.4/libavcodec/g729dec.c --- ffmpeg-4.2.2/libavcodec/g729dec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/g729dec.c 2020-07-11 10:39:30.000000000 +0000 @@ -430,14 +430,14 @@ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - if (buf_size && buf_size % (G729_8K_BLOCK_SIZE * avctx->channels) == 0) { + if (buf_size && buf_size % ((G729_8K_BLOCK_SIZE + (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN)) * avctx->channels) == 0) { packet_type = FORMAT_G729_8K; format = &format_g729_8k; //Reset voice decision ctx->onset = 0; ctx->voice_decision = DECISION_VOICE; av_log(avctx, AV_LOG_DEBUG, "Packet type: %s\n", "G.729 @ 8kbit/s"); - } else if (buf_size == G729D_6K4_BLOCK_SIZE * avctx->channels) { + } else if (buf_size == G729D_6K4_BLOCK_SIZE * avctx->channels && avctx->codec_id != AV_CODEC_ID_ACELP_KELVIN) { packet_type = FORMAT_G729D_6K4; format = &format_g729d_6k4; av_log(avctx, AV_LOG_DEBUG, "Packet type: %s\n", "G.729D @ 6.4kbit/s"); @@ -451,12 +451,17 @@ int bad_pitch = 0; ///< parity check failed int is_periodic = 0; ///< whether one of the subframes is declared as periodic or not out_frame = (int16_t*)frame->data[c]; + if (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN) { + if (*buf != ((avctx->channels - 1 - c) * 0x80 | 2)) + avpriv_request_sample(avctx, "First byte value %x for channel %d", *buf, c); + buf++; + } for (i = 0; i < format->block_size; i++) frame_erasure |= buf[i]; frame_erasure = !frame_erasure; - init_get_bits(&gb, buf, 8*format->block_size); + init_get_bits8(&gb, buf, format->block_size); ma_predictor = get_bits(&gb, 1); quantizer_1st = get_bits(&gb, VQ_1ST_BITS); @@ -734,7 +739,7 @@ } *got_frame_ptr = 1; - return format->block_size * avctx->channels; + return (format->block_size + (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN)) * avctx->channels; } static av_cold int decode_close(AVCodecContext *avctx) @@ -753,6 +758,18 @@ .priv_data_size = sizeof(G729Context), .init = decoder_init, .decode = decode_frame, + .close = decode_close, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, +}; + +AVCodec ff_acelp_kelvin_decoder = { + .name = "acelp.kelvin", + .long_name = NULL_IF_CONFIG_SMALL("Sipro ACELP.KELVIN"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ACELP_KELVIN, + .priv_data_size = sizeof(G729Context), + .init = decoder_init, + .decode = decode_frame, .close = decode_close, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, }; diff -Nru ffmpeg-4.2.2/libavcodec/g729_parser.c ffmpeg-4.4/libavcodec/g729_parser.c --- ffmpeg-4.2.2/libavcodec/g729_parser.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/g729_parser.c 2020-07-11 10:39:30.000000000 +0000 @@ -45,9 +45,10 @@ int next; if (!s->block_size) { - av_assert1(avctx->codec_id == AV_CODEC_ID_G729); /* FIXME: replace this heuristic block_size with more precise estimate */ s->block_size = (avctx->bit_rate < 8000) ? G729D_6K4_BLOCK_SIZE : G729_8K_BLOCK_SIZE; + if (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN) + s->block_size++; s->block_size *= avctx->channels; s->duration = avctx->frame_size; } @@ -82,7 +83,7 @@ } AVCodecParser ff_g729_parser = { - .codec_ids = { AV_CODEC_ID_G729 }, + .codec_ids = { AV_CODEC_ID_G729, AV_CODEC_ID_ACELP_KELVIN }, .priv_data_size = sizeof(G729ParseContext), .parser_parse = g729_parse, .parser_close = ff_parse_close, diff -Nru ffmpeg-4.2.2/libavcodec/g729postfilter.c ffmpeg-4.4/libavcodec/g729postfilter.c --- ffmpeg-4.2.2/libavcodec/g729postfilter.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/g729postfilter.c 2020-07-09 09:17:46.000000000 +0000 @@ -486,14 +486,14 @@ if (refl_coeff > 0) { gt = (refl_coeff * G729_TILT_FACTOR_PLUS + 0x4000) >> 15; - fact = 0x4000; // 0.5 in (0.15) - sh_fact = 15; + fact = 0x2000; // 0.5 in (0.15) + sh_fact = 14; } else { gt = (refl_coeff * G729_TILT_FACTOR_MINUS + 0x4000) >> 15; - fact = 0x800; // 0.5 in (3.12) - sh_fact = 12; + fact = 0x400; // 0.5 in (3.12) + sh_fact = 11; } - ga = (fact << 15) / av_clip_int16(32768 - FFABS(gt)); + ga = (fact << 16) / av_clip_int16(32768 - FFABS(gt)); gt >>= 1; /* Apply tilt compensation filter to signal. */ @@ -503,12 +503,12 @@ tmp2 = (gt * res_pst[i-1]) * 2 + 0x4000; tmp2 = res_pst[i] + (tmp2 >> 15); - tmp2 = (tmp2 * ga * 2 + fact) >> sh_fact; + tmp2 = (tmp2 * ga + fact) >> sh_fact; out[i] = tmp2; } tmp2 = (gt * ht_prev_data) * 2 + 0x4000; tmp2 = res_pst[0] + (tmp2 >> 15); - tmp2 = (tmp2 * ga * 2 + fact) >> sh_fact; + tmp2 = (tmp2 * ga + fact) >> sh_fact; out[0] = tmp2; return tmp; @@ -600,6 +600,7 @@ gain = ((gain_before - gain_after) << 14) / gain_after + 0x4000; gain = bidir_sal(gain, exp_after - exp_before); } + gain = av_clip_int16(gain); gain = (gain * G729_AGC_FAC1 + 0x4000) >> 15; // gain * (1-0.9875) } else gain = 0; diff -Nru ffmpeg-4.2.2/libavcodec/gdv.c ffmpeg-4.4/libavcodec/gdv.c --- ffmpeg-4.2.2/libavcodec/gdv.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/gdv.c 2021-04-08 21:28:39.000000000 +0000 @@ -461,7 +461,8 @@ GetByteContext *gb = &gdv->gb; PutByteContext *pb = &gdv->pb; AVFrame *frame = data; - int ret, i, pal_size; + int ret, i; + buffer_size_t pal_size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size); int compression; unsigned flags; @@ -551,7 +552,7 @@ *got_frame = 1; - return ret < 0 ? ret : avpkt->size; + return avpkt->size; } static av_cold int gdv_decode_close(AVCodecContext *avctx) diff -Nru ffmpeg-4.2.2/libavcodec/get_bits.h ffmpeg-4.4/libavcodec/get_bits.h --- ffmpeg-4.2.2/libavcodec/get_bits.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/get_bits.h 2020-07-11 10:39:30.000000000 +0000 @@ -234,9 +234,9 @@ #endif if (is_le) - s->cache = (uint64_t)AV_RL32(s->buffer + (s->index >> 3)) << s->bits_left | s->cache; + s->cache = (uint64_t)AV_RL32(s->buffer + (s->index >> 3)) << s->bits_left | s->cache; else - s->cache = s->cache | (uint64_t)AV_RB32(s->buffer + (s->index >> 3)) << (32 - s->bits_left); + s->cache = s->cache | (uint64_t)AV_RB32(s->buffer + (s->index >> 3)) << (32 - s->bits_left); s->index += 32; s->bits_left += 32; } @@ -249,9 +249,9 @@ #endif if (is_le) - s->cache = AV_RL64(s->buffer + (s->index >> 3)); + s->cache = AV_RL64(s->buffer + (s->index >> 3)); else - s->cache = AV_RB64(s->buffer + (s->index >> 3)); + s->cache = AV_RB64(s->buffer + (s->index >> 3)); s->index += 64; s->bits_left = 64; } diff -Nru ffmpeg-4.2.2/libavcodec/gif.c ffmpeg-4.4/libavcodec/gif.c --- ffmpeg-4.2.2/libavcodec/gif.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/gif.c 2021-04-08 21:28:39.000000000 +0000 @@ -47,10 +47,12 @@ const AVClass *class; LZWState *lzw; uint8_t *buf; + uint8_t *shrunk_buf; int buf_size; AVFrame *last_frame; int flags; int image; + int use_global_palette; uint32_t palette[AVPALETTE_COUNT]; ///< local reference palette for !pal8 int palette_loaded; int transparent_index; @@ -62,6 +64,38 @@ GF_TRANSDIFF = 1<<1, }; +static void shrink_palette(const uint32_t *src, uint8_t *map, + uint32_t *dst, size_t *palette_count) +{ + size_t colors_seen = 0; + + for (size_t i = 0; i < AVPALETTE_COUNT; i++) { + int seen = 0; + for (size_t c = 0; c < colors_seen; c++) { + if (src[i] == dst[c]) { + seen = 1; + break; + } + } + if (!seen) { + dst[colors_seen] = src[i]; + map[i] = colors_seen; + colors_seen++; + } + } + + *palette_count = colors_seen; +} + +static void remap_frame_to_palette(const uint8_t *src, int src_linesize, + uint8_t *dst, int dst_linesize, + int w, int h, uint8_t *map) +{ + for (int i = 0; i < h; i++) + for (int j = 0; j < w; j++) + dst[i * dst_linesize + j] = map[src[i * src_linesize + j]]; +} + static int is_image_translucent(AVCodecContext *avctx, const uint8_t *buf, const int linesize) { @@ -266,8 +300,19 @@ int x_start = 0, y_start = 0, trans = s->transparent_index; int bcid = -1, honor_transparency = (s->flags & GF_TRANSDIFF) && s->last_frame && !palette; const uint8_t *ptr; + uint32_t shrunk_palette[AVPALETTE_COUNT]; + uint8_t map[AVPALETTE_COUNT] = { 0 }; + size_t shrunk_palette_count = 0; + + /* + * We memset to 0xff instead of 0x00 so that the transparency detection + * doesn't pick anything after the palette entries as the transparency + * index, and because GIF89a requires us to always write a power-of-2 + * number of palette entries. + */ + memset(shrunk_palette, 0xff, AVPALETTE_SIZE); - if (!s->image && avctx->frame_number && is_image_translucent(avctx, buf, linesize)) { + if (!s->image && is_image_translucent(avctx, buf, linesize)) { gif_crop_translucent(avctx, buf, linesize, &width, &height, &x_start, &y_start); honor_transparency = 0; disposal = GCE_DISPOSAL_BACKGROUND; @@ -293,12 +338,14 @@ bcid = get_palette_transparency_index(global_palette); - bytestream_put_byte(bytestream, 0xf7); /* flags: global clut, 256 entries */ + bytestream_put_byte(bytestream, ((uint8_t) s->use_global_palette << 7) | 0x70 | (s->use_global_palette ? 7 : 0)); /* flags: global clut, 256 entries */ bytestream_put_byte(bytestream, bcid < 0 ? DEFAULT_TRANSPARENCY_INDEX : bcid); /* background color index */ bytestream_put_byte(bytestream, aspect); - for (int i = 0; i < 256; i++) { - const uint32_t v = global_palette[i] & 0xffffff; - bytestream_put_be24(bytestream, v); + if (s->use_global_palette) { + for (int i = 0; i < 256; i++) { + const uint32_t v = global_palette[i] & 0xffffff; + bytestream_put_be24(bytestream, v); + } } } @@ -312,6 +359,11 @@ if (trans < 0) honor_transparency = 0; + if (palette || !s->use_global_palette) { + const uint32_t *pal = palette ? palette : s->palette; + shrink_palette(pal, map, shrunk_palette, &shrunk_palette_count); + } + bcid = honor_transparency || disposal == GCE_DISPOSAL_BACKGROUND ? trans : get_palette_transparency_index(palette); /* graphic control extension */ @@ -320,7 +372,7 @@ bytestream_put_byte(bytestream, 0x04); /* block size */ bytestream_put_byte(bytestream, disposal<<2 | (bcid >= 0)); bytestream_put_le16(bytestream, 5); // default delay - bytestream_put_byte(bytestream, bcid < 0 ? DEFAULT_TRANSPARENCY_INDEX : bcid); + bytestream_put_byte(bytestream, bcid < 0 ? DEFAULT_TRANSPARENCY_INDEX : (shrunk_palette_count ? map[bcid] : bcid)); bytestream_put_byte(bytestream, 0x00); /* image block */ @@ -330,23 +382,37 @@ bytestream_put_le16(bytestream, width); bytestream_put_le16(bytestream, height); - if (!palette) { - bytestream_put_byte(bytestream, 0x00); /* flags */ - } else { + if (palette || !s->use_global_palette) { + unsigned pow2_count = av_log2(shrunk_palette_count - 1); unsigned i; - bytestream_put_byte(bytestream, 1<<7 | 0x7); /* flags */ - for (i = 0; i < AVPALETTE_COUNT; i++) { - const uint32_t v = palette[i]; + + bytestream_put_byte(bytestream, 1<<7 | pow2_count); /* flags */ + for (i = 0; i < 1 << (pow2_count + 1); i++) { + const uint32_t v = shrunk_palette[i]; bytestream_put_be24(bytestream, v); } + } else { + bytestream_put_byte(bytestream, 0x00); /* flags */ } bytestream_put_byte(bytestream, 0x08); ff_lzw_encode_init(s->lzw, s->buf, s->buf_size, - 12, FF_LZW_GIF, put_bits); + 12, FF_LZW_GIF, 1); - ptr = buf + y_start*linesize + x_start; + if (shrunk_palette_count) { + if (!s->shrunk_buf) { + s->shrunk_buf = av_malloc(avctx->height * linesize); + if (!s->shrunk_buf) { + av_log(avctx, AV_LOG_ERROR, "Could not allocated remapped frame buffer.\n"); + return AVERROR(ENOMEM); + } + } + remap_frame_to_palette(buf, linesize, s->shrunk_buf, linesize, avctx->width, avctx->height, map); + ptr = s->shrunk_buf + y_start*linesize + x_start; + } else { + ptr = buf + y_start*linesize + x_start; + } if (honor_transparency) { const int ref_linesize = s->last_frame->linesize[0]; const uint8_t *ref = s->last_frame->data[0] + y_start*ref_linesize + x_start; @@ -366,7 +432,7 @@ ptr += linesize; } } - len += ff_lzw_encode_flush(s->lzw, flush_put_bits); + len += ff_lzw_encode_flush(s->lzw); ptr = s->buf; while (len > 0) { @@ -460,6 +526,7 @@ av_freep(&s->lzw); av_freep(&s->buf); + av_freep(&s->shrunk_buf); s->buf_size = 0; av_frame_free(&s->last_frame); av_freep(&s->tmpl); @@ -473,6 +540,7 @@ { "offsetting", "enable picture offsetting", 0, AV_OPT_TYPE_CONST, {.i64=GF_OFFSETTING}, INT_MIN, INT_MAX, FLAGS, "flags" }, { "transdiff", "enable transparency detection between frames", 0, AV_OPT_TYPE_CONST, {.i64=GF_TRANSDIFF}, INT_MIN, INT_MAX, FLAGS, "flags" }, { "gifimage", "enable encoding only images per frame", OFFSET(image), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "global_palette", "write a palette to the global gif header where feasible", OFFSET(use_global_palette), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, { NULL } }; @@ -497,4 +565,5 @@ AV_PIX_FMT_GRAY8, AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE }, .priv_class = &gif_class, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/gifdec.c ffmpeg-4.4/libavcodec/gifdec.c --- ffmpeg-4.2.2/libavcodec/gifdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/gifdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -513,7 +513,7 @@ return AVERROR_INVALIDDATA; } - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; s->frame->pict_type = AV_PICTURE_TYPE_P; diff -Nru ffmpeg-4.2.2/libavcodec/golomb.h ffmpeg-4.4/libavcodec/golomb.h --- ffmpeg-4.2.2/libavcodec/golomb.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/golomb.h 2021-04-08 21:28:39.000000000 +0000 @@ -66,9 +66,12 @@ return ff_ue_golomb_vlc_code[buf]; } else { int log = 2 * av_log2(buf) - 31; + + skip_bits_long(gb, 32 - log); + if (log < 7) + return AVERROR_INVALIDDATA; buf >>= log; buf--; - skip_bits_long(gb, 32 - log); return buf; } @@ -87,10 +90,8 @@ int log = 2 * av_log2(buf) - 31; LAST_SKIP_BITS(re, gb, 32 - log); CLOSE_READER(re, gb); - if (log < 7) { - av_log(NULL, AV_LOG_ERROR, "Invalid UE golomb code\n"); + if (log < 7) return AVERROR_INVALIDDATA; - } buf >>= log; buf--; @@ -115,7 +116,8 @@ /** * read unsigned exp golomb code, constraint to a max of 31. - * the return value is undefined if the stored value exceeds 31. + * If the value encountered is not in 0..31, the return value + * is outside the range 0..30. */ static inline int get_ue_golomb_31(GetBitContext *gb) { @@ -313,7 +315,7 @@ } else { int log; skip_bits(gb, 8); - buf |= 1 | show_bits_long(gb, 24); + buf |= 1 | show_bits(gb, 24); if ((buf & 0xAAAAAAAA) == 0) return INVALID_VLC; diff -Nru ffmpeg-4.2.2/libavcodec/gsmdec.c ffmpeg-4.4/libavcodec/gsmdec.c --- ffmpeg-4.2.2/libavcodec/gsmdec.c 2017-12-31 22:35:46.000000000 +0000 +++ ffmpeg-4.4/libavcodec/gsmdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -120,7 +120,7 @@ .init = gsm_init, .decode = gsm_decode_frame, .flush = gsm_flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; #endif #if CONFIG_GSM_MS_DECODER @@ -133,6 +133,6 @@ .init = gsm_init, .decode = gsm_decode_frame, .flush = gsm_flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/h261.c ffmpeg-4.4/libavcodec/h261.c --- ffmpeg-4.2.2/libavcodec/h261.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h261.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,8 +30,6 @@ #define IS_FIL(a) ((a) & MB_TYPE_H261_FIL) -uint8_t ff_h261_rl_table_store[2][2 * MAX_RUN + MAX_LEVEL + 3]; - static void h261_loop_filter(uint8_t *src, int stride) { int x, y, xy, yz; @@ -79,14 +77,3 @@ h261_loop_filter(dest_cb, uvlinesize); h261_loop_filter(dest_cr, uvlinesize); } - -av_cold void ff_h261_common_init(void) -{ - static int done = 0; - - if (done) - return; - - ff_rl_init(&ff_h261_rl_tcoeff, ff_h261_rl_table_store); - done = 1; -} diff -Nru ffmpeg-4.2.2/libavcodec/h261dec.c ffmpeg-4.4/libavcodec/h261dec.c --- ffmpeg-4.2.2/libavcodec/h261dec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h261dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,7 @@ */ #include "libavutil/avassert.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "mpeg_er.h" #include "mpegutils.h" @@ -34,7 +35,7 @@ #include "h261.h" #include "internal.h" -#define H261_MBA_VLC_BITS 9 +#define H261_MBA_VLC_BITS 8 #define H261_MTYPE_VLC_BITS 6 #define H261_MV_VLC_BITS 7 #define H261_CBP_VLC_BITS 9 @@ -47,46 +48,40 @@ static VLC h261_mv_vlc; static VLC h261_cbp_vlc; -static av_cold void h261_decode_init_vlc(H261Context *h) +static av_cold void h261_decode_init_static(void) { - static int done = 0; - - if (!done) { - done = 1; - INIT_VLC_STATIC(&h261_mba_vlc, H261_MBA_VLC_BITS, 35, - ff_h261_mba_bits, 1, 1, - ff_h261_mba_code, 1, 1, 662); - INIT_VLC_STATIC(&h261_mtype_vlc, H261_MTYPE_VLC_BITS, 10, - ff_h261_mtype_bits, 1, 1, - ff_h261_mtype_code, 1, 1, 80); - INIT_VLC_STATIC(&h261_mv_vlc, H261_MV_VLC_BITS, 17, - &ff_h261_mv_tab[0][1], 2, 1, - &ff_h261_mv_tab[0][0], 2, 1, 144); - INIT_VLC_STATIC(&h261_cbp_vlc, H261_CBP_VLC_BITS, 63, - &ff_h261_cbp_tab[0][1], 2, 1, - &ff_h261_cbp_tab[0][0], 2, 1, 512); - INIT_VLC_RL(ff_h261_rl_tcoeff, 552); - } + INIT_VLC_STATIC(&h261_mba_vlc, H261_MBA_VLC_BITS, 35, + ff_h261_mba_bits, 1, 1, + ff_h261_mba_code, 1, 1, 540); + INIT_VLC_STATIC(&h261_mtype_vlc, H261_MTYPE_VLC_BITS, 10, + ff_h261_mtype_bits, 1, 1, + ff_h261_mtype_code, 1, 1, 80); + INIT_VLC_STATIC(&h261_mv_vlc, H261_MV_VLC_BITS, 17, + &ff_h261_mv_tab[0][1], 2, 1, + &ff_h261_mv_tab[0][0], 2, 1, 144); + INIT_VLC_STATIC(&h261_cbp_vlc, H261_CBP_VLC_BITS, 63, + &ff_h261_cbp_tab[0][1], 2, 1, + &ff_h261_cbp_tab[0][0], 2, 1, 512); + INIT_FIRST_VLC_RL(ff_h261_rl_tcoeff, 552); } static av_cold int h261_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; H261Context *h = avctx->priv_data; MpegEncContext *const s = &h->s; // set defaults - ff_mpv_decode_defaults(s); ff_mpv_decode_init(s, avctx); s->out_format = FMT_H261; s->low_delay = 1; avctx->pix_fmt = AV_PIX_FMT_YUV420P; - ff_h261_common_init(); - h261_decode_init_vlc(h); - h->gob_start_code_skipped = 0; + ff_thread_once(&init_static_once, h261_decode_init_static); + return 0; } @@ -431,7 +426,7 @@ // Read cbp if (HAS_CBP(h->mtype)) - cbp = get_vlc2(&s->gb, h261_cbp_vlc.table, H261_CBP_VLC_BITS, 2) + 1; + cbp = get_vlc2(&s->gb, h261_cbp_vlc.table, H261_CBP_VLC_BITS, 1) + 1; if (s->mb_intra) { s->current_picture.mb_type[xy] = MB_TYPE_INTRA; @@ -613,10 +608,7 @@ } if (s->width != avctx->coded_width || s->height != avctx->coded_height) { - ParseContext pc = s->parse_context; // FIXME move this demuxing hack to libavformat - s->parse_context.buffer = 0; ff_mpv_common_end(s); - s->parse_context = pc; } if (!s->context_initialized) { @@ -686,5 +678,6 @@ .close = h261_decode_end, .decode = h261_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .max_lowres = 3, }; diff -Nru ffmpeg-4.2.2/libavcodec/h261enc.c ffmpeg-4.4/libavcodec/h261enc.c --- ffmpeg-4.2.2/libavcodec/h261enc.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h261enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ #include "libavutil/attributes.h" #include "libavutil/avassert.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "mpegutils.h" #include "mpegvideo.h" @@ -55,7 +56,7 @@ H261Context *h = (H261Context *)s; int format, temp_ref; - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); /* Update the pointer to last GOB */ s->ptr_lastgob = put_bits_ptr(&s->pb); @@ -322,8 +323,7 @@ } } -static av_cold void init_uni_h261_rl_tab(RLTable *rl, uint32_t *bits_tab, - uint8_t *len_tab) +static av_cold void init_uni_h261_rl_tab(const RLTable *rl, uint8_t *len_tab) { int slevel, run, last; @@ -362,9 +362,17 @@ } } +static av_cold void h261_encode_init_static(void) +{ + static uint8_t h261_rl_table_store[2][2 * MAX_RUN + MAX_LEVEL + 3]; + + ff_rl_init(&ff_h261_rl_tcoeff, h261_rl_table_store); + init_uni_h261_rl_tab(&ff_h261_rl_tcoeff, uni_h261_rl_len); +} + av_cold void ff_h261_encode_init(MpegEncContext *s) { - ff_h261_common_init(); + static AVOnce init_static_once = AV_ONCE_INIT; s->min_qcoeff = -127; s->max_qcoeff = 127; @@ -372,10 +380,9 @@ s->c_dc_scale_table = ff_mpeg1_dc_scale_table; s->ac_esc_length = 6+6+8; - init_uni_h261_rl_tab(&ff_h261_rl_tcoeff, NULL, uni_h261_rl_len); - s->intra_ac_vlc_length = s->inter_ac_vlc_length = uni_h261_rl_len; s->intra_ac_vlc_last_length = s->inter_ac_vlc_last_length = uni_h261_rl_len + 128*64; + ff_thread_once(&init_static_once, h261_encode_init_static); } static const AVClass h261_class = { @@ -394,6 +401,7 @@ .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &h261_class, diff -Nru ffmpeg-4.2.2/libavcodec/h261.h ffmpeg-4.4/libavcodec/h261.h --- ffmpeg-4.2.2/libavcodec/h261.h 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h261.h 2021-04-08 21:28:39.000000000 +0000 @@ -48,8 +48,6 @@ #define MB_TYPE_H261_FIL 0x800000 -extern uint8_t ff_h261_rl_table_store[2][2 * MAX_RUN + MAX_LEVEL + 3]; - extern const uint8_t ff_h261_mba_code[35]; extern const uint8_t ff_h261_mba_bits[35]; extern const uint8_t ff_h261_mtype_code[10]; @@ -60,7 +58,6 @@ extern RLTable ff_h261_rl_tcoeff; void ff_h261_loop_filter(MpegEncContext *s); -void ff_h261_common_init(void); int ff_h261_get_picture_format(int width, int height); void ff_h261_reorder_mb_index(MpegEncContext *s); diff -Nru ffmpeg-4.2.2/libavcodec/h263data.c ffmpeg-4.4/libavcodec/h263data.c --- ffmpeg-4.2.2/libavcodec/h263data.c 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h263data.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,11 +25,11 @@ #include +#include "libavutil/thread.h" + #include "h263data.h" #include "mpegvideo.h" -uint8_t ff_h263_static_rl_table_store[2][2][2 * MAX_RUN + MAX_LEVEL + 3]; - /* intra MCBPC, mb_type = (intra), then (intraq) */ const uint8_t ff_h263_intra_MCBPC_code[9] = { 1, 1, 2, 3, 1, 1, 2, 3, 1 }; const uint8_t ff_h263_intra_MCBPC_bits[9] = { 1, 3, 3, 3, 4, 6, 6, 6, 9 }; @@ -290,3 +290,15 @@ { 0, 1 }, { 0, 1 }, }; + +static av_cold void h263_init_rl_inter(void) +{ + static uint8_t h263_rl_inter_table[2][2 * MAX_RUN + MAX_LEVEL + 3]; + ff_rl_init(&ff_h263_rl_inter, h263_rl_inter_table); +} + +av_cold void ff_h263_init_rl_inter(void) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, h263_init_rl_inter); +} diff -Nru ffmpeg-4.2.2/libavcodec/h263data.h ffmpeg-4.4/libavcodec/h263data.h --- ffmpeg-4.2.2/libavcodec/h263data.h 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h263data.h 2021-04-08 21:28:39.000000000 +0000 @@ -61,7 +61,7 @@ extern RLTable ff_h263_rl_inter; extern RLTable ff_rl_intra_aic; -extern uint8_t ff_h263_static_rl_table_store[2][2][2 * MAX_RUN + MAX_LEVEL + 3]; +void ff_h263_init_rl_inter(void); extern const uint16_t ff_h263_format[8][2]; diff -Nru ffmpeg-4.2.2/libavcodec/h263dec.c ffmpeg-4.4/libavcodec/h263dec.c --- ffmpeg-4.2.2/libavcodec/h263dec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h263dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,12 +28,14 @@ #define UNCHECKED_BITSTREAM_READER 1 #include "libavutil/cpu.h" +#include "libavutil/video_enc_params.h" + #include "avcodec.h" #include "error_resilience.h" #include "flv.h" #include "h263.h" #include "h263_parser.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "internal.h" #include "mpeg_er.h" #include "mpeg4video.h" @@ -73,7 +75,6 @@ s->out_format = FMT_H263; // set defaults - ff_mpv_decode_defaults(s); ff_mpv_decode_init(s, avctx); s->quant_precision = 5; @@ -743,7 +744,7 @@ AV_PIX_FMT_NONE }; -const AVCodecHWConfigInternal *ff_h263_hw_config_list[] = { +const AVCodecHWConfigInternal *const ff_h263_hw_config_list[] = { #if CONFIG_H263_VAAPI_HWACCEL HWACCEL_VAAPI(h263), #endif diff -Nru ffmpeg-4.2.2/libavcodec/h263.h ffmpeg-4.4/libavcodec/h263.h --- ffmpeg-4.2.2/libavcodec/h263.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h263.h 2021-04-08 21:28:39.000000000 +0000 @@ -34,6 +34,7 @@ // reading vlc values. Changing these may improve speed and data cache needs // be aware though that decreasing them may need the number of stages that is // passed to get_vlc* to be increased. +#define H263_MV_VLC_BITS 9 #define INTRA_MCBPC_VLC_BITS 6 #define INTER_MCBPC_VLC_BITS 7 #define CBPY_VLC_BITS 6 @@ -44,6 +45,7 @@ extern VLC ff_h263_intra_MCBPC_vlc; extern VLC ff_h263_inter_MCBPC_vlc; extern VLC ff_h263_cbpy_vlc; +extern VLC ff_h263_mv_vlc; extern const enum AVPixelFormat ff_h263_hwaccel_pixfmt_list_420[]; diff -Nru ffmpeg-4.2.2/libavcodec/h2645_parse.c ffmpeg-4.4/libavcodec/h2645_parse.c --- ffmpeg-4.2.2/libavcodec/h2645_parse.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h2645_parse.c 2021-04-08 21:28:39.000000000 +0000 @@ -146,7 +146,7 @@ return si; } -static const char *hevc_nal_type_name[64] = { +static const char *const hevc_nal_type_name[64] = { "TRAIL_N", // HEVC_NAL_TRAIL_N "TRAIL_R", // HEVC_NAL_TRAIL_R "TSA_N", // HEVC_NAL_TSA_N @@ -169,8 +169,8 @@ "IDR_W_RADL", // HEVC_NAL_IDR_W_RADL "IDR_N_LP", // HEVC_NAL_IDR_N_LP "CRA_NUT", // HEVC_NAL_CRA_NUT - "IRAP_IRAP_VCL22", // HEVC_NAL_IRAP_VCL22 - "IRAP_IRAP_VCL23", // HEVC_NAL_IRAP_VCL23 + "RSV_IRAP_VCL22", // HEVC_NAL_RSV_IRAP_VCL22 + "RSV_IRAP_VCL23", // HEVC_NAL_RSV_IRAP_VCL23 "RSV_VCL24", // HEVC_NAL_RSV_VCL24 "RSV_VCL25", // HEVC_NAL_RSV_VCL25 "RSV_VCL26", // HEVC_NAL_RSV_VCL26 @@ -219,7 +219,7 @@ return hevc_nal_type_name[nal_type]; } -static const char *h264_nal_type_name[32] = { +static const char *const h264_nal_type_name[32] = { "Unspecified 0", //H264_NAL_UNSPECIFIED "Coded slice of a non-IDR picture", // H264_NAL_SLICE "Coded slice data partition A", // H264_NAL_DPA @@ -287,28 +287,27 @@ /** * @return AVERROR_INVALIDDATA if the packet is not a valid NAL unit, - * 0 if the unit should be skipped, 1 otherwise + * 0 otherwise */ static int hevc_parse_nal_header(H2645NAL *nal, void *logctx) { GetBitContext *gb = &nal->gb; - int nuh_layer_id; if (get_bits1(gb) != 0) return AVERROR_INVALIDDATA; nal->type = get_bits(gb, 6); - nuh_layer_id = get_bits(gb, 6); + nal->nuh_layer_id = get_bits(gb, 6); nal->temporal_id = get_bits(gb, 3) - 1; if (nal->temporal_id < 0) return AVERROR_INVALIDDATA; av_log(logctx, AV_LOG_DEBUG, "nal_unit_type: %d(%s), nuh_layer_id: %d, temporal_id: %d\n", - nal->type, hevc_nal_unit_name(nal->type), nuh_layer_id, nal->temporal_id); + nal->type, hevc_nal_unit_name(nal->type), nal->nuh_layer_id, nal->temporal_id); - return nuh_layer_id == 0; + return 0; } static int h264_parse_nal_header(H2645NAL *nal, void *logctx) @@ -325,7 +324,7 @@ "nal_unit_type: %d(%s), nal_ref_idc: %d\n", nal->type, h264_nal_unit_name(nal->type), nal->ref_idc); - return 1; + return 0; } static int find_next_start_code(const uint8_t *buf, const uint8_t *next_avc) @@ -455,17 +454,20 @@ if (pkt->nals_allocated < pkt->nb_nals + 1) { int new_size = pkt->nals_allocated + 1; - void *tmp = av_realloc_array(pkt->nals, new_size, sizeof(*pkt->nals)); + void *tmp; + + if (new_size >= INT_MAX / sizeof(*pkt->nals)) + return AVERROR(ENOMEM); + tmp = av_fast_realloc(pkt->nals, &pkt->nal_buffer_size, new_size * sizeof(*pkt->nals)); if (!tmp) return AVERROR(ENOMEM); pkt->nals = tmp; - memset(pkt->nals + pkt->nals_allocated, 0, - (new_size - pkt->nals_allocated) * sizeof(*pkt->nals)); + memset(pkt->nals + pkt->nals_allocated, 0, sizeof(*pkt->nals)); nal = &pkt->nals[pkt->nb_nals]; - nal->skipped_bytes_pos_size = 1024; // initial buffer size + nal->skipped_bytes_pos_size = FFMIN(1024, extract_length/3+1); // initial buffer size nal->skipped_bytes_pos = av_malloc_array(nal->skipped_bytes_pos_size, sizeof(*nal->skipped_bytes_pos)); if (!nal->skipped_bytes_pos) return AVERROR(ENOMEM); @@ -483,8 +485,6 @@ "NALFF: Consumed only %d bytes instead of %d\n", consumed, extract_length); - pkt->nb_nals++; - bytestream2_skip(&bc, consumed); /* see commit 3566042a0 */ @@ -494,21 +494,27 @@ nal->size_bits = get_bit_length(nal, skip_trailing_zeros); + if (nal->size <= 0 || nal->size_bits <= 0) + continue; + ret = init_get_bits(&nal->gb, nal->data, nal->size_bits); if (ret < 0) return ret; + /* Reset type in case it contains a stale value from a previously parsed NAL */ + nal->type = 0; + if (codec_id == AV_CODEC_ID_HEVC) ret = hevc_parse_nal_header(nal, logctx); else ret = h264_parse_nal_header(nal, logctx); - if (ret <= 0 || nal->size <= 0 || nal->size_bits <= 0) { - if (ret < 0) { - av_log(logctx, AV_LOG_WARNING, "Invalid NAL unit %d, skipping.\n", - nal->type); - } - pkt->nb_nals--; + if (ret < 0) { + av_log(logctx, AV_LOG_WARNING, "Invalid NAL unit %d, skipping.\n", + nal->type); + continue; } + + pkt->nb_nals++; } return 0; @@ -521,7 +527,7 @@ av_freep(&pkt->nals[i].skipped_bytes_pos); } av_freep(&pkt->nals); - pkt->nals_allocated = 0; + pkt->nals_allocated = pkt->nal_buffer_size = 0; if (pkt->rbsp.rbsp_buffer_ref) { av_buffer_unref(&pkt->rbsp.rbsp_buffer_ref); pkt->rbsp.rbsp_buffer = NULL; diff -Nru ffmpeg-4.2.2/libavcodec/h2645_parse.h ffmpeg-4.4/libavcodec/h2645_parse.h --- ffmpeg-4.2.2/libavcodec/h2645_parse.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h2645_parse.h 2020-07-11 10:39:30.000000000 +0000 @@ -56,6 +56,11 @@ */ int temporal_id; + /* + * HEVC only, identifier of layer to which nal unit belongs + */ + int nuh_layer_id; + int skipped_bytes; int skipped_bytes_pos_size; int *skipped_bytes_pos; @@ -78,6 +83,7 @@ H2645RBSP rbsp; int nb_nals; int nals_allocated; + unsigned nal_buffer_size; } H2645Packet; /** diff -Nru ffmpeg-4.2.2/libavcodec/h264_cabac.c ffmpeg-4.4/libavcodec/h264_cabac.c --- ffmpeg-4.2.2/libavcodec/h264_cabac.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_cabac.c 2020-07-11 10:39:30.000000000 +0000 @@ -31,7 +31,6 @@ #include "libavutil/attributes.h" #include "libavutil/avassert.h" -#include "libavutil/timer.h" #include "config.h" #include "cabac.h" #include "cabac_functions.h" @@ -1895,9 +1894,7 @@ qmul = h->ps.pps->dequant4_coeff[cqm][qscale]; for( i4x4 = 0; i4x4 < 4; i4x4++ ) { const int index = 16*p + 4*i8x8 + i4x4; -//START_TIMER decode_cabac_residual_nondc(h, sl, sl->mb + (16*index << pixel_shift), ctx_cat[2][p], index, scan, qmul, 16); -//STOP_TIMER("decode_residual") } } } else { diff -Nru ffmpeg-4.2.2/libavcodec/h264_cavlc.c ffmpeg-4.4/libavcodec/h264_cavlc.c --- ffmpeg-4.2.2/libavcodec/h264_cavlc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_cavlc.c 2021-04-08 21:28:39.000000000 +0000 @@ -324,93 +324,88 @@ } } -av_cold void ff_h264_decode_init_vlc(void){ - static int done = 0; - - if (!done) { - int i; - int offset; - done = 1; - - chroma_dc_coeff_token_vlc.table = chroma_dc_coeff_token_vlc_table; - chroma_dc_coeff_token_vlc.table_allocated = chroma_dc_coeff_token_vlc_table_size; - init_vlc(&chroma_dc_coeff_token_vlc, CHROMA_DC_COEFF_TOKEN_VLC_BITS, 4*5, - &chroma_dc_coeff_token_len [0], 1, 1, - &chroma_dc_coeff_token_bits[0], 1, 1, +av_cold void ff_h264_decode_init_vlc(void) +{ + int offset; + + chroma_dc_coeff_token_vlc.table = chroma_dc_coeff_token_vlc_table; + chroma_dc_coeff_token_vlc.table_allocated = chroma_dc_coeff_token_vlc_table_size; + init_vlc(&chroma_dc_coeff_token_vlc, CHROMA_DC_COEFF_TOKEN_VLC_BITS, 4*5, + &chroma_dc_coeff_token_len [0], 1, 1, + &chroma_dc_coeff_token_bits[0], 1, 1, + INIT_VLC_USE_NEW_STATIC); + + chroma422_dc_coeff_token_vlc.table = chroma422_dc_coeff_token_vlc_table; + chroma422_dc_coeff_token_vlc.table_allocated = chroma422_dc_coeff_token_vlc_table_size; + init_vlc(&chroma422_dc_coeff_token_vlc, CHROMA422_DC_COEFF_TOKEN_VLC_BITS, 4*9, + &chroma422_dc_coeff_token_len [0], 1, 1, + &chroma422_dc_coeff_token_bits[0], 1, 1, + INIT_VLC_USE_NEW_STATIC); + + offset = 0; + for (int i = 0; i < 4; i++) { + coeff_token_vlc[i].table = coeff_token_vlc_tables + offset; + coeff_token_vlc[i].table_allocated = coeff_token_vlc_tables_size[i]; + init_vlc(&coeff_token_vlc[i], COEFF_TOKEN_VLC_BITS, 4*17, + &coeff_token_len [i][0], 1, 1, + &coeff_token_bits[i][0], 1, 1, + INIT_VLC_USE_NEW_STATIC); + offset += coeff_token_vlc_tables_size[i]; + } + /* + * This is a one time safety check to make sure that + * the packed static coeff_token_vlc table sizes + * were initialized correctly. + */ + av_assert0(offset == FF_ARRAY_ELEMS(coeff_token_vlc_tables)); + + for (int i = 0; i < 3; i++) { + chroma_dc_total_zeros_vlc[i + 1].table = chroma_dc_total_zeros_vlc_tables[i]; + chroma_dc_total_zeros_vlc[i + 1].table_allocated = chroma_dc_total_zeros_vlc_tables_size; + init_vlc(&chroma_dc_total_zeros_vlc[i + 1], + CHROMA_DC_TOTAL_ZEROS_VLC_BITS, 4, + &chroma_dc_total_zeros_len [i][0], 1, 1, + &chroma_dc_total_zeros_bits[i][0], 1, 1, INIT_VLC_USE_NEW_STATIC); + } - chroma422_dc_coeff_token_vlc.table = chroma422_dc_coeff_token_vlc_table; - chroma422_dc_coeff_token_vlc.table_allocated = chroma422_dc_coeff_token_vlc_table_size; - init_vlc(&chroma422_dc_coeff_token_vlc, CHROMA422_DC_COEFF_TOKEN_VLC_BITS, 4*9, - &chroma422_dc_coeff_token_len [0], 1, 1, - &chroma422_dc_coeff_token_bits[0], 1, 1, + for (int i = 0; i < 7; i++) { + chroma422_dc_total_zeros_vlc[i + 1].table = chroma422_dc_total_zeros_vlc_tables[i]; + chroma422_dc_total_zeros_vlc[i + 1].table_allocated = chroma422_dc_total_zeros_vlc_tables_size; + init_vlc(&chroma422_dc_total_zeros_vlc[i + 1], + CHROMA422_DC_TOTAL_ZEROS_VLC_BITS, 8, + &chroma422_dc_total_zeros_len [i][0], 1, 1, + &chroma422_dc_total_zeros_bits[i][0], 1, 1, INIT_VLC_USE_NEW_STATIC); + } - offset = 0; - for(i=0; i<4; i++){ - coeff_token_vlc[i].table = coeff_token_vlc_tables+offset; - coeff_token_vlc[i].table_allocated = coeff_token_vlc_tables_size[i]; - init_vlc(&coeff_token_vlc[i], COEFF_TOKEN_VLC_BITS, 4*17, - &coeff_token_len [i][0], 1, 1, - &coeff_token_bits[i][0], 1, 1, - INIT_VLC_USE_NEW_STATIC); - offset += coeff_token_vlc_tables_size[i]; - } - /* - * This is a one time safety check to make sure that - * the packed static coeff_token_vlc table sizes - * were initialized correctly. - */ - av_assert0(offset == FF_ARRAY_ELEMS(coeff_token_vlc_tables)); - - for(i=0; i<3; i++){ - chroma_dc_total_zeros_vlc[i+1].table = chroma_dc_total_zeros_vlc_tables[i]; - chroma_dc_total_zeros_vlc[i+1].table_allocated = chroma_dc_total_zeros_vlc_tables_size; - init_vlc(&chroma_dc_total_zeros_vlc[i+1], - CHROMA_DC_TOTAL_ZEROS_VLC_BITS, 4, - &chroma_dc_total_zeros_len [i][0], 1, 1, - &chroma_dc_total_zeros_bits[i][0], 1, 1, - INIT_VLC_USE_NEW_STATIC); - } - - for(i=0; i<7; i++){ - chroma422_dc_total_zeros_vlc[i+1].table = chroma422_dc_total_zeros_vlc_tables[i]; - chroma422_dc_total_zeros_vlc[i+1].table_allocated = chroma422_dc_total_zeros_vlc_tables_size; - init_vlc(&chroma422_dc_total_zeros_vlc[i+1], - CHROMA422_DC_TOTAL_ZEROS_VLC_BITS, 8, - &chroma422_dc_total_zeros_len [i][0], 1, 1, - &chroma422_dc_total_zeros_bits[i][0], 1, 1, - INIT_VLC_USE_NEW_STATIC); - } - - for(i=0; i<15; i++){ - total_zeros_vlc[i+1].table = total_zeros_vlc_tables[i]; - total_zeros_vlc[i+1].table_allocated = total_zeros_vlc_tables_size; - init_vlc(&total_zeros_vlc[i+1], - TOTAL_ZEROS_VLC_BITS, 16, - &total_zeros_len [i][0], 1, 1, - &total_zeros_bits[i][0], 1, 1, - INIT_VLC_USE_NEW_STATIC); - } - - for(i=0; i<6; i++){ - run_vlc[i+1].table = run_vlc_tables[i]; - run_vlc[i+1].table_allocated = run_vlc_tables_size; - init_vlc(&run_vlc[i+1], - RUN_VLC_BITS, 7, - &run_len [i][0], 1, 1, - &run_bits[i][0], 1, 1, - INIT_VLC_USE_NEW_STATIC); - } - run7_vlc.table = run7_vlc_table, - run7_vlc.table_allocated = run7_vlc_table_size; - init_vlc(&run7_vlc, RUN7_VLC_BITS, 16, - &run_len [6][0], 1, 1, - &run_bits[6][0], 1, 1, + for (int i = 0; i < 15; i++) { + total_zeros_vlc[i + 1].table = total_zeros_vlc_tables[i]; + total_zeros_vlc[i + 1].table_allocated = total_zeros_vlc_tables_size; + init_vlc(&total_zeros_vlc[i + 1], + TOTAL_ZEROS_VLC_BITS, 16, + &total_zeros_len [i][0], 1, 1, + &total_zeros_bits[i][0], 1, 1, INIT_VLC_USE_NEW_STATIC); + } - init_cavlc_level_tab(); + for (int i = 0; i < 6; i++) { + run_vlc[i + 1].table = run_vlc_tables[i]; + run_vlc[i + 1].table_allocated = run_vlc_tables_size; + init_vlc(&run_vlc[i + 1], + RUN_VLC_BITS, 7, + &run_len [i][0], 1, 1, + &run_bits[i][0], 1, 1, + INIT_VLC_USE_NEW_STATIC); } + run7_vlc.table = run7_vlc_table; + run7_vlc.table_allocated = run7_vlc_table_size; + init_vlc(&run7_vlc, RUN7_VLC_BITS, 16, + &run_len [6][0], 1, 1, + &run_bits[6][0], 1, 1, + INIT_VLC_USE_NEW_STATIC); + + init_cavlc_level_tab(); } static inline int get_level_prefix(GetBitContext *gb){ diff -Nru ffmpeg-4.2.2/libavcodec/h264dec.c ffmpeg-4.4/libavcodec/h264dec.c --- ffmpeg-4.2.2/libavcodec/h264dec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,7 +32,8 @@ #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/stereo3d.h" -#include "libavutil/timer.h" +#include "libavutil/video_enc_params.h" + #include "internal.h" #include "bytestream.h" #include "cabac.h" @@ -47,7 +48,7 @@ #include "h264_mvpred.h" #include "h264_ps.h" #include "golomb.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "mathops.h" #include "me_cmp.h" #include "mpegutils.h" @@ -181,40 +182,27 @@ { const int big_mb_num = h->mb_stride * (h->mb_height + 1); const int row_mb_num = 2*h->mb_stride*FFMAX(h->nb_slice_ctx, 1); + const int st_size = big_mb_num + h->mb_stride; int x, y; - FF_ALLOCZ_ARRAY_OR_GOTO(h->avctx, h->intra4x4_pred_mode, - row_mb_num, 8 * sizeof(uint8_t), fail) + if (!FF_ALLOCZ_TYPED_ARRAY(h->intra4x4_pred_mode, row_mb_num * 8) || + !FF_ALLOCZ_TYPED_ARRAY(h->non_zero_count, big_mb_num) || + !FF_ALLOCZ_TYPED_ARRAY(h->slice_table_base, st_size) || + !FF_ALLOCZ_TYPED_ARRAY(h->cbp_table, big_mb_num) || + !FF_ALLOCZ_TYPED_ARRAY(h->chroma_pred_mode_table, big_mb_num) || + !FF_ALLOCZ_TYPED_ARRAY(h->mvd_table[0], row_mb_num * 8) || + !FF_ALLOCZ_TYPED_ARRAY(h->mvd_table[1], row_mb_num * 8) || + !FF_ALLOCZ_TYPED_ARRAY(h->direct_table, big_mb_num * 4) || + !FF_ALLOCZ_TYPED_ARRAY(h->list_counts, big_mb_num) || + !FF_ALLOCZ_TYPED_ARRAY(h->mb2b_xy, big_mb_num) || + !FF_ALLOCZ_TYPED_ARRAY(h->mb2br_xy, big_mb_num)) + return AVERROR(ENOMEM); h->slice_ctx[0].intra4x4_pred_mode = h->intra4x4_pred_mode; - - FF_ALLOCZ_OR_GOTO(h->avctx, h->non_zero_count, - big_mb_num * 48 * sizeof(uint8_t), fail) - FF_ALLOCZ_OR_GOTO(h->avctx, h->slice_table_base, - (big_mb_num + h->mb_stride) * sizeof(*h->slice_table_base), fail) - FF_ALLOCZ_OR_GOTO(h->avctx, h->cbp_table, - big_mb_num * sizeof(uint16_t), fail) - FF_ALLOCZ_OR_GOTO(h->avctx, h->chroma_pred_mode_table, - big_mb_num * sizeof(uint8_t), fail) - FF_ALLOCZ_ARRAY_OR_GOTO(h->avctx, h->mvd_table[0], - row_mb_num, 16 * sizeof(uint8_t), fail); - FF_ALLOCZ_ARRAY_OR_GOTO(h->avctx, h->mvd_table[1], - row_mb_num, 16 * sizeof(uint8_t), fail); h->slice_ctx[0].mvd_table[0] = h->mvd_table[0]; h->slice_ctx[0].mvd_table[1] = h->mvd_table[1]; - - FF_ALLOCZ_OR_GOTO(h->avctx, h->direct_table, - 4 * big_mb_num * sizeof(uint8_t), fail); - FF_ALLOCZ_OR_GOTO(h->avctx, h->list_counts, - big_mb_num * sizeof(uint8_t), fail) - memset(h->slice_table_base, -1, - (big_mb_num + h->mb_stride) * sizeof(*h->slice_table_base)); + st_size * sizeof(*h->slice_table_base)); h->slice_table = h->slice_table_base + h->mb_stride * 2 + 1; - - FF_ALLOCZ_OR_GOTO(h->avctx, h->mb2b_xy, - big_mb_num * sizeof(uint32_t), fail); - FF_ALLOCZ_OR_GOTO(h->avctx, h->mb2br_xy, - big_mb_num * sizeof(uint32_t), fail); for (y = 0; y < h->mb_height; y++) for (x = 0; x < h->mb_width; x++) { const int mb_xy = x + y * h->mb_stride; @@ -225,10 +213,6 @@ } return 0; - -fail: - ff_h264_free_tables(h); - return AVERROR(ENOMEM); } /** @@ -253,8 +237,8 @@ if (sl != h->slice_ctx) { memset(er, 0, sizeof(*er)); - } else - if (CONFIG_ERROR_RESILIENCE) { + } else if (CONFIG_ERROR_RESILIENCE) { + const int er_size = h->mb_height * h->mb_stride * (4*sizeof(int) + 1); /* init ER */ er->avctx = h->avctx; @@ -269,8 +253,11 @@ er->b8_stride = h->mb_width * 2 + 1; // error resilience code looks cleaner with this - FF_ALLOCZ_OR_GOTO(h->avctx, er->mb_index2xy, - (h->mb_num + 1) * sizeof(int), fail); + if (!FF_ALLOCZ_TYPED_ARRAY(er->mb_index2xy, h->mb_num + 1) || + !FF_ALLOCZ_TYPED_ARRAY(er->error_status_table, mb_array_size) || + !FF_ALLOCZ_TYPED_ARRAY(er->er_temp_buffer, er_size) || + !FF_ALLOCZ_TYPED_ARRAY(sl->dc_val_base, yc_size)) + return AVERROR(ENOMEM); // ff_h264_free_tables will clean up for us for (y = 0; y < h->mb_height; y++) for (x = 0; x < h->mb_width; x++) @@ -278,15 +265,6 @@ er->mb_index2xy[h->mb_height * h->mb_width] = (h->mb_height - 1) * h->mb_stride + h->mb_width; - - FF_ALLOCZ_OR_GOTO(h->avctx, er->error_status_table, - mb_array_size * sizeof(uint8_t), fail); - - FF_ALLOC_OR_GOTO(h->avctx, er->er_temp_buffer, - h->mb_height * h->mb_stride * (4*sizeof(int) + 1), fail); - - FF_ALLOCZ_OR_GOTO(h->avctx, sl->dc_val_base, - yc_size * sizeof(int16_t), fail); er->dc_val[0] = sl->dc_val_base + h->mb_width * 2 + 2; er->dc_val[1] = sl->dc_val_base + y_size + h->mb_stride + 1; er->dc_val[2] = er->dc_val[1] + c_size; @@ -295,9 +273,6 @@ } return 0; - -fail: - return AVERROR(ENOMEM); // ff_h264_free_tables will clean up for us } static int h264_init_context(AVCodecContext *avctx, H264Context *h) @@ -310,7 +285,6 @@ h->width_from_caller = avctx->width; h->height_from_caller = avctx->height; - h->picture_structure = PICT_FRAME; h->workaround_bugs = avctx->workaround_bugs; h->flags = avctx->flags; h->poc.prev_poc_msb = 1 << 16; @@ -326,8 +300,6 @@ ff_h264_sei_uninit(&h->sei); - avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; - h->nb_slice_ctx = (avctx->active_thread_type & FF_THREAD_SLICE) ? avctx->thread_count : 1; h->slice_ctx = av_mallocz_array(h->nb_slice_ctx, sizeof(*h->slice_ctx)); if (!h->slice_ctx) { @@ -412,13 +384,20 @@ } avctx->ticks_per_frame = 2; - if (avctx->extradata_size > 0 && avctx->extradata) { - ret = ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size, - &h->ps, &h->is_avc, &h->nal_length_size, - avctx->err_recognition, avctx); - if (ret < 0) { - h264_decode_end(avctx); - return ret; + if (!avctx->internal->is_copy) { + if (avctx->extradata_size > 0 && avctx->extradata) { + ret = ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size, + &h->ps, &h->is_avc, &h->nal_length_size, + avctx->err_recognition, avctx); + if (ret < 0) { + int explode = avctx->err_recognition & AV_EF_EXPLODE; + av_log(avctx, explode ? AV_LOG_ERROR: AV_LOG_WARNING, + "Error decoding the extradata\n"); + if (explode) { + return ret; + } + ret = 0; + } } } @@ -427,8 +406,6 @@ h->avctx->has_b_frames = h->ps.sps->num_reorder_frames; } - avctx->internal->allocate_progress = 1; - ff_h264_flush_change(h); if (h->enable_er < 0 && (avctx->active_thread_type & FF_THREAD_SLICE)) @@ -443,27 +420,6 @@ return 0; } -#if HAVE_THREADS -static int decode_init_thread_copy(AVCodecContext *avctx) -{ - H264Context *h = avctx->priv_data; - int ret; - - if (!avctx->internal->is_copy) - return 0; - - memset(h, 0, sizeof(*h)); - - ret = h264_init_context(avctx, h); - if (ret < 0) - return ret; - - h->context_initialized = 0; - - return 0; -} -#endif - /** * instantaneous decoder refresh. */ @@ -474,7 +430,7 @@ h->poc.prev_frame_num = h->poc.prev_frame_num_offset = 0; h->poc.prev_poc_msb = 1<<16; - h->poc.prev_poc_lsb = 0; + h->poc.prev_poc_lsb = -1; for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) h->last_pocs[i] = INT_MIN; } @@ -505,8 +461,7 @@ h->mmco_reset = 1; } -/* forget old pics after a seek */ -static void flush_dpb(AVCodecContext *avctx) +static void h264_decode_flush(AVCodecContext *avctx) { H264Context *h = avctx->priv_data; int i; @@ -623,7 +578,7 @@ } ret = ff_h2645_packet_split(&h->pkt, buf, buf_size, avctx, h->is_avc, h->nal_length_size, - avctx->codec_id, avctx->flags2 & AV_CODEC_FLAG2_FAST, 0); + avctx->codec_id, 0, 0); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error splitting the input into NAL units.\n"); @@ -782,9 +737,7 @@ * past end by one (callers fault) and resync_mb_y != 0 * causes problems for the first MB line, too. */ - if (!FIELD_PICTURE(h) && h->current_slice && - h->ps.sps == (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data && - h->enable_er) { + if (!FIELD_PICTURE(h) && h->current_slice && h->enable_er) { H264SliceContext *sl = h->slice_ctx; int use_last_pic = h->last_pic_for_ec.f->buf[0] && !sl->ref_count[0]; @@ -834,6 +787,40 @@ return pos; } +static int h264_export_enc_params(AVFrame *f, H264Picture *p) +{ + AVVideoEncParams *par; + unsigned int nb_mb = p->mb_height * p->mb_width; + unsigned int x, y; + + par = av_video_enc_params_create_side_data(f, AV_VIDEO_ENC_PARAMS_H264, nb_mb); + if (!par) + return AVERROR(ENOMEM); + + par->qp = p->pps->init_qp; + + par->delta_qp[1][0] = p->pps->chroma_qp_index_offset[0]; + par->delta_qp[1][1] = p->pps->chroma_qp_index_offset[0]; + par->delta_qp[2][0] = p->pps->chroma_qp_index_offset[1]; + par->delta_qp[2][1] = p->pps->chroma_qp_index_offset[1]; + + for (y = 0; y < p->mb_height; y++) + for (x = 0; x < p->mb_width; x++) { + const unsigned int block_idx = y * p->mb_width + x; + const unsigned int mb_xy = y * p->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] - par->qp; + } + + return 0; +} + static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp) { AVFrame *src = srcp->f; @@ -848,10 +835,19 @@ if (srcp->sei_recovery_frame_cnt == 0) dst->key_frame = 1; + if (h->avctx->export_side_data & AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS) { + ret = h264_export_enc_params(dst, srcp); + if (ret < 0) + goto fail; + } + return 0; +fail: + av_frame_unref(dst); + return ret; } -static int is_extra(const uint8_t *buf, int buf_size) +static int is_avcc_extradata(const uint8_t *buf, int buf_size) { int cnt= buf[5]&0x1f; const uint8_t *p= buf+6; @@ -978,16 +974,15 @@ if (buf_size == 0) return send_next_delayed_frame(h, pict, got_frame, 0); - if (h->is_avc && av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, NULL)) { - int side_size; + if (av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, NULL)) { + buffer_size_t side_size; uint8_t *side = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); - if (is_extra(side, side_size)) - ff_h264_decode_extradata(side, side_size, - &h->ps, &h->is_avc, &h->nal_length_size, - avctx->err_recognition, avctx); + ff_h264_decode_extradata(side, side_size, + &h->ps, &h->is_avc, &h->nal_length_size, + avctx->err_recognition, avctx); } if (h->is_avc && buf_size >= 9 && buf[0]==1 && buf[2]==0 && (buf[4]&0xFC)==0xFC) { - if (is_extra(buf, buf_size)) + if (is_avcc_extradata(buf, buf_size)) return ff_h264_decode_extradata(buf, buf_size, &h->ps, &h->is_avc, &h->nal_length_size, avctx->err_recognition, avctx); @@ -1059,7 +1054,7 @@ .capabilities = /*AV_CODEC_CAP_DRAW_HORIZ_BAND |*/ AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, - .hw_configs = (const AVCodecHWConfigInternal*[]) { + .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_H264_DXVA2_HWACCEL HWACCEL_DXVA2(h264), #endif @@ -1083,9 +1078,9 @@ #endif NULL }, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING, - .flush = flush_dpb, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING | + FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_INIT_CLEANUP, + .flush = h264_decode_flush, .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_h264_update_thread_context), .profiles = NULL_IF_CONFIG_SMALL(ff_h264_profiles), .priv_class = &h264_class, diff -Nru ffmpeg-4.2.2/libavcodec/h264dec.h ffmpeg-4.4/libavcodec/h264dec.h --- ffmpeg-4.2.2/libavcodec/h264dec.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264dec.h 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/buffer.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #include "libavutil/thread.h" #include "cabac.h" @@ -161,6 +162,12 @@ int recovered; ///< picture at IDR or recovery point + recovery count int invalid_gap; int sei_recovery_frame_cnt; + + AVBufferRef *pps_buf; + const PPS *pps; + + int mb_width, mb_height; + int mb_stride; } H264Picture; typedef struct H264Ref { @@ -832,8 +839,6 @@ void ff_h264_draw_horiz_band(const H264Context *h, H264SliceContext *sl, int y, int height); -int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl, - const H2645NAL *nal); /** * Submit a slice for decoding. * diff -Nru ffmpeg-4.2.2/libavcodec/h264_direct.c ffmpeg-4.4/libavcodec/h264_direct.c --- ffmpeg-4.2.2/libavcodec/h264_direct.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_direct.c 2021-04-08 21:28:39.000000000 +0000 @@ -43,7 +43,7 @@ int td = av_clip_int8(pocdiff); if (pocdiff != (int)pocdiff) - avpriv_request_sample(sl->h264->avctx, "pocdiff overflow\n"); + avpriv_request_sample(sl->h264->avctx, "pocdiff overflow"); if (td == 0 || sl->ref_list[0][i].parent->long_ref) { return 256; diff -Nru ffmpeg-4.2.2/libavcodec/h264idct_template.c ffmpeg-4.4/libavcodec/h264idct_template.c --- ffmpeg-4.2.2/libavcodec/h264idct_template.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264idct_template.c 2021-02-20 20:27:47.000000000 +0000 @@ -278,13 +278,13 @@ const int stride= 16*2; const int xStride= 16; int i; - int temp[8]; + unsigned temp[8]; static const uint8_t x_offset[2]={0, 16}; dctcoef *block = (dctcoef*)_block; for(i=0; i<4; i++){ - temp[2*i+0] = block[stride*i + xStride*0] + block[stride*i + xStride*1]; - temp[2*i+1] = block[stride*i + xStride*0] - block[stride*i + xStride*1]; + temp[2*i+0] = block[stride*i + xStride*0] + (unsigned)block[stride*i + xStride*1]; + temp[2*i+1] = block[stride*i + xStride*0] - (unsigned)block[stride*i + xStride*1]; } for(i=0; i<2; i++){ diff -Nru ffmpeg-4.2.2/libavcodec/h264_levels.c ffmpeg-4.4/libavcodec/h264_levels.c --- ffmpeg-4.2.2/libavcodec/h264_levels.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_levels.c 2021-04-08 21:28:39.000000000 +0000 @@ -75,18 +75,6 @@ return 1200; } -const H264LevelDescriptor *ff_h264_get_level(int level_idc, - int constraint_set3_flag) -{ - int i; - for (i = 0; i < FF_ARRAY_ELEMS(h264_levels); i++) { - if (h264_levels[i].level_idc == level_idc && - h264_levels[i].constraint_set3_flag == constraint_set3_flag) - return &h264_levels[i]; - } - return NULL; -} - const H264LevelDescriptor *ff_h264_guess_level(int profile_idc, int64_t bitrate, int framerate, diff -Nru ffmpeg-4.2.2/libavcodec/h264_levels.h ffmpeg-4.4/libavcodec/h264_levels.h --- ffmpeg-4.2.2/libavcodec/h264_levels.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_levels.h 2021-04-08 21:28:39.000000000 +0000 @@ -36,9 +36,6 @@ uint8_t max_mvs_per_2mb; } H264LevelDescriptor; -const H264LevelDescriptor *ff_h264_get_level(int level_idc, - int constraint_set3_flag); - /** * Guess the level of a stream from some parameters. * diff -Nru ffmpeg-4.2.2/libavcodec/h264_loopfilter.c ffmpeg-4.4/libavcodec/h264_loopfilter.c --- ffmpeg-4.2.2/libavcodec/h264_loopfilter.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_loopfilter.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #include "internal.h" #include "avcodec.h" #include "h264dec.h" diff -Nru ffmpeg-4.2.2/libavcodec/h264_metadata_bsf.c ffmpeg-4.4/libavcodec/h264_metadata_bsf.c --- ffmpeg-4.2.2/libavcodec/h264_metadata_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_metadata_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,19 +23,13 @@ #include "bsf.h" #include "cbs.h" +#include "cbs_bsf.h" #include "cbs_h264.h" #include "h264.h" #include "h264_levels.h" #include "h264_sei.h" enum { - PASS, - INSERT, - REMOVE, - EXTRACT, -}; - -enum { FLIP_HORIZONTAL = 1, FLIP_VERTICAL = 2, }; @@ -46,17 +40,17 @@ }; typedef struct H264MetadataContext { - const AVClass *class; - - CodedBitstreamContext *cbc; - CodedBitstreamFragment access_unit; + CBSBSFContext common; int done_first_au; int aud; + H264RawAUD aud_nal; AVRational sample_aspect_ratio; + int overscan_appropriate_flag; + int video_format; int video_full_range_flag; int colour_primaries; @@ -74,17 +68,72 @@ int crop_bottom; const char *sei_user_data; + SEIRawUserDataUnregistered sei_user_data_payload; int delete_filler; int display_orientation; double rotate; int flip; + H264RawSEIDisplayOrientation display_orientation_payload; int level; } H264MetadataContext; +static int h264_metadata_insert_aud(AVBSFContext *bsf, + CodedBitstreamFragment *au) +{ + H264MetadataContext *ctx = bsf->priv_data; + int primary_pic_type_mask = 0xff; + int err, i, j; + + static const int primary_pic_type_table[] = { + 0x084, // 2, 7 + 0x0a5, // 0, 2, 5, 7 + 0x0e7, // 0, 1, 2, 5, 6, 7 + 0x210, // 4, 9 + 0x318, // 3, 4, 8, 9 + 0x294, // 2, 4, 7, 9 + 0x3bd, // 0, 2, 3, 4, 5, 7, 8, 9 + 0x3ff, // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + }; + + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_SLICE || + au->units[i].type == H264_NAL_IDR_SLICE) { + H264RawSlice *slice = au->units[i].content; + for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++) { + if (!(primary_pic_type_table[j] & + (1 << slice->header.slice_type))) + primary_pic_type_mask &= ~(1 << j); + } + } + } + for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++) + if (primary_pic_type_mask & (1 << j)) + break; + if (j >= FF_ARRAY_ELEMS(primary_pic_type_table)) { + av_log(bsf, AV_LOG_ERROR, "No usable primary_pic_type: " + "invalid slice types?\n"); + return AVERROR_INVALIDDATA; + } + + ctx->aud_nal = (H264RawAUD) { + .nal_unit_header.nal_unit_type = H264_NAL_AUD, + .primary_pic_type = j, + }; + + err = ff_cbs_insert_unit_content(au, 0, H264_NAL_AUD, + &ctx->aud_nal, NULL); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); + return err; + } + + return 0; +} + static int h264_metadata_update_sps(AVBSFContext *bsf, H264RawSPS *sps) { @@ -122,47 +171,39 @@ need_vui = 1; } -#define SET_OR_INFER(field, value, present_flag, infer) do { \ - if (value >= 0) { \ - field = value; \ +#define SET_VUI_FIELD(field) do { \ + if (ctx->field >= 0) { \ + sps->vui.field = ctx->field; \ need_vui = 1; \ - } else if (!present_flag) \ - field = infer; \ + } \ } while (0) + if (ctx->overscan_appropriate_flag >= 0) { + SET_VUI_FIELD(overscan_appropriate_flag); + sps->vui.overscan_info_present_flag = 1; + } + if (ctx->video_format >= 0 || ctx->video_full_range_flag >= 0 || ctx->colour_primaries >= 0 || ctx->transfer_characteristics >= 0 || ctx->matrix_coefficients >= 0) { - SET_OR_INFER(sps->vui.video_format, ctx->video_format, - sps->vui.video_signal_type_present_flag, 5); + SET_VUI_FIELD(video_format); - SET_OR_INFER(sps->vui.video_full_range_flag, - ctx->video_full_range_flag, - sps->vui.video_signal_type_present_flag, 0); + SET_VUI_FIELD(video_full_range_flag); if (ctx->colour_primaries >= 0 || ctx->transfer_characteristics >= 0 || ctx->matrix_coefficients >= 0) { - SET_OR_INFER(sps->vui.colour_primaries, - ctx->colour_primaries, - sps->vui.colour_description_present_flag, 2); - - SET_OR_INFER(sps->vui.transfer_characteristics, - ctx->transfer_characteristics, - sps->vui.colour_description_present_flag, 2); - - SET_OR_INFER(sps->vui.matrix_coefficients, - ctx->matrix_coefficients, - sps->vui.colour_description_present_flag, 2); + SET_VUI_FIELD(colour_primaries); + SET_VUI_FIELD(transfer_characteristics); + SET_VUI_FIELD(matrix_coefficients); sps->vui.colour_description_present_flag = 1; } sps->vui.video_signal_type_present_flag = 1; - need_vui = 1; } if (ctx->chroma_sample_loc_type >= 0) { @@ -186,9 +227,7 @@ sps->vui.timing_info_present_flag = 1; need_vui = 1; } - SET_OR_INFER(sps->vui.fixed_frame_rate_flag, - ctx->fixed_frame_rate_flag, - sps->vui.timing_info_present_flag, 0); + SET_VUI_FIELD(fixed_frame_rate_flag); if (sps->separate_colour_plane_flag || sps->chroma_format_idc == 0) { crop_unit_x = 1; @@ -283,247 +322,94 @@ return 0; } -static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *pkt) +static int h264_metadata_handle_display_orientation(AVBSFContext *bsf, + AVPacket *pkt, + CodedBitstreamFragment *au, + int seek_point) { H264MetadataContext *ctx = bsf->priv_data; - CodedBitstreamFragment *au = &ctx->access_unit; - int err, i, j, has_sps; - H264RawAUD aud; - - err = ff_bsf_get_packet_ref(bsf, pkt); - if (err < 0) - return err; - - err = ff_cbs_read_packet(ctx->cbc, au, pkt); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); - goto fail; - } - - if (au->nb_units == 0) { - av_log(bsf, AV_LOG_ERROR, "No NAL units in packet.\n"); - err = AVERROR_INVALIDDATA; - goto fail; - } - - // If an AUD is present, it must be the first NAL unit. - if (au->units[0].type == H264_NAL_AUD) { - if (ctx->aud == REMOVE) - ff_cbs_delete_unit(ctx->cbc, au, 0); - } else { - if (ctx->aud == INSERT) { - static const int primary_pic_type_table[] = { - 0x084, // 2, 7 - 0x0a5, // 0, 2, 5, 7 - 0x0e7, // 0, 1, 2, 5, 6, 7 - 0x210, // 4, 9 - 0x318, // 3, 4, 8, 9 - 0x294, // 2, 4, 7, 9 - 0x3bd, // 0, 2, 3, 4, 5, 7, 8, 9 - 0x3ff, // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 - }; - int primary_pic_type_mask = 0xff; - - for (i = 0; i < au->nb_units; i++) { - if (au->units[i].type == H264_NAL_SLICE || - au->units[i].type == H264_NAL_IDR_SLICE) { - H264RawSlice *slice = au->units[i].content; - for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++) { - if (!(primary_pic_type_table[j] & - (1 << slice->header.slice_type))) - primary_pic_type_mask &= ~(1 << j); - } - } - } - for (j = 0; j < FF_ARRAY_ELEMS(primary_pic_type_table); j++) - if (primary_pic_type_mask & (1 << j)) - break; - if (j >= FF_ARRAY_ELEMS(primary_pic_type_table)) { - av_log(bsf, AV_LOG_ERROR, "No usable primary_pic_type: " - "invalid slice types?\n"); - err = AVERROR_INVALIDDATA; - goto fail; - } - - aud = (H264RawAUD) { - .nal_unit_header.nal_unit_type = H264_NAL_AUD, - .primary_pic_type = j, - }; - - err = ff_cbs_insert_unit_content(ctx->cbc, au, - 0, H264_NAL_AUD, &aud, NULL); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); - goto fail; - } - } - } + SEIRawMessage *message; + int err; - has_sps = 0; - for (i = 0; i < au->nb_units; i++) { - if (au->units[i].type == H264_NAL_SPS) { - err = h264_metadata_update_sps(bsf, au->units[i].content); - if (err < 0) - goto fail; - has_sps = 1; + message = NULL; + while (ff_cbs_sei_find_message(ctx->common.output, au, + SEI_TYPE_DISPLAY_ORIENTATION, + &message) == 0) { + H264RawSEIDisplayOrientation *disp = message->payload; + 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_matrix_flip(matrix, disp->hor_flip, disp->ver_flip); + + // If there are multiple display orientation messages in an + // access unit, then the last one added to the packet (i.e. + // the first one in the access unit) will prevail. + err = av_packet_add_side_data(pkt, AV_PKT_DATA_DISPLAYMATRIX, + (uint8_t*)matrix, + 9 * sizeof(int32_t)); + if (err < 0) { + av_log(bsf, AV_LOG_ERROR, "Failed to attach extracted " + "displaymatrix side data to packet.\n"); + av_free(matrix); + return AVERROR(ENOMEM); } } - // Only insert the SEI in access units containing SPSs, and also - // unconditionally in the first access unit we ever see. - if (ctx->sei_user_data && (has_sps || !ctx->done_first_au)) { - H264RawSEIPayload payload = { - .payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED, - }; - H264RawSEIUserDataUnregistered *udu = - &payload.payload.user_data_unregistered; - - for (i = j = 0; j < 32 && ctx->sei_user_data[i]; i++) { - int c, v; - c = ctx->sei_user_data[i]; - if (c == '-') { - continue; - } else if (av_isxdigit(c)) { - c = av_tolower(c); - v = (c <= '9' ? c - '0' : c - 'a' + 10); - } else { - goto invalid_user_data; - } - if (i & 1) - udu->uuid_iso_iec_11578[j / 2] |= v; - else - udu->uuid_iso_iec_11578[j / 2] = v << 4; - ++j; - } - if (j == 32 && ctx->sei_user_data[i] == '+') { - size_t len = strlen(ctx->sei_user_data + i + 1); - - udu->data_ref = av_buffer_alloc(len + 1); - if (!udu->data_ref) { - err = AVERROR(ENOMEM); - goto fail; - } - - udu->data = udu->data_ref->data; - udu->data_length = len + 1; - memcpy(udu->data, ctx->sei_user_data + i + 1, len + 1); - - err = ff_cbs_h264_add_sei_message(ctx->cbc, au, &payload); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI " - "message to access unit.\n"); - goto fail; - } - - } else { - invalid_user_data: - av_log(bsf, AV_LOG_ERROR, "Invalid user data: " - "must be \"UUID+string\".\n"); - err = AVERROR(EINVAL); - goto fail; - } + if (ctx->display_orientation == BSF_ELEMENT_REMOVE || + ctx->display_orientation == BSF_ELEMENT_INSERT) { + ff_cbs_sei_delete_message_type(ctx->common.output, au, + SEI_TYPE_DISPLAY_ORIENTATION); } - if (ctx->delete_filler) { - for (i = au->nb_units - 1; i >= 0; i--) { - if (au->units[i].type == H264_NAL_FILLER_DATA) { - ff_cbs_delete_unit(ctx->cbc, au, i); - continue; - } - - if (au->units[i].type == H264_NAL_SEI) { - // Filler SEI messages. - H264RawSEI *sei = au->units[i].content; - - for (j = sei->payload_count - 1; j >= 0; j--) { - if (sei->payload[j].payload_type == - H264_SEI_TYPE_FILLER_PAYLOAD) - ff_cbs_h264_delete_sei_message(ctx->cbc, au, - &au->units[i], j); - } - } - } - } - - if (ctx->display_orientation != PASS) { - for (i = au->nb_units - 1; i >= 0; i--) { - H264RawSEI *sei; - if (au->units[i].type != H264_NAL_SEI) - continue; - sei = au->units[i].content; - - for (j = sei->payload_count - 1; j >= 0; j--) { - H264RawSEIDisplayOrientation *disp; - int32_t *matrix; - - if (sei->payload[j].payload_type != - H264_SEI_TYPE_DISPLAY_ORIENTATION) - continue; - disp = &sei->payload[j].payload.display_orientation; - - if (ctx->display_orientation == REMOVE || - ctx->display_orientation == INSERT) { - ff_cbs_h264_delete_sei_message(ctx->cbc, au, - &au->units[i], j); - continue; - } - - matrix = av_malloc(9 * sizeof(int32_t)); - if (!matrix) { - err = AVERROR(ENOMEM); - goto fail; - } - - av_display_rotation_set(matrix, - disp->anticlockwise_rotation * - 180.0 / 65536.0); - av_display_matrix_flip(matrix, disp->hor_flip, disp->ver_flip); - - // If there are multiple display orientation messages in an - // access unit, then the last one added to the packet (i.e. - // the first one in the access unit) will prevail. - err = av_packet_add_side_data(pkt, AV_PKT_DATA_DISPLAYMATRIX, - (uint8_t*)matrix, - 9 * sizeof(int32_t)); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to attach extracted " - "displaymatrix side data to packet.\n"); - av_freep(matrix); - goto fail; - } - } - } - } - if (ctx->display_orientation == INSERT) { - H264RawSEIPayload payload = { - .payload_type = H264_SEI_TYPE_DISPLAY_ORIENTATION, - }; + if (ctx->display_orientation == BSF_ELEMENT_INSERT) { H264RawSEIDisplayOrientation *disp = - &payload.payload.display_orientation; + &ctx->display_orientation_payload; uint8_t *data; - int size; + buffer_size_t size; int write = 0; data = av_packet_get_side_data(pkt, AV_PKT_DATA_DISPLAYMATRIX, &size); if (data && size >= 9 * sizeof(int32_t)) { int32_t matrix[9]; - int hflip, vflip; - double angle; + double dmatrix[9]; + int hflip, vflip, i; + double scale_x, scale_y, angle; memcpy(matrix, data, sizeof(matrix)); - hflip = vflip = 0; - if (matrix[0] < 0 && matrix[4] > 0) - hflip = 1; - else if (matrix[0] > 0 && matrix[4] < 0) - vflip = 1; - av_display_matrix_flip(matrix, hflip, vflip); - - angle = av_display_rotation_get(matrix); - - if (!(angle >= -180.0 && angle <= 180.0 /* also excludes NaN */) || - matrix[2] != 0 || matrix[5] != 0 || - matrix[6] != 0 || matrix[7] != 0) { + for (i = 0; i < 9; i++) + dmatrix[i] = matrix[i] / 65536.0; + + // Extract scale factors. + scale_x = hypot(dmatrix[0], dmatrix[3]); + scale_y = hypot(dmatrix[1], dmatrix[4]); + + // Select flips to make the main diagonal positive. + hflip = dmatrix[0] < 0.0; + vflip = dmatrix[4] < 0.0; + if (hflip) + scale_x = -scale_x; + if (vflip) + scale_y = -scale_y; + + // Rescale. + for (i = 0; i < 9; i += 3) { + dmatrix[i] /= scale_x; + dmatrix[i + 1] /= scale_y; + } + + // Extract rotation. + angle = atan2(dmatrix[3], dmatrix[0]); + + if (!(angle >= -M_PI && angle <= M_PI) || + matrix[2] != 0.0 || matrix[5] != 0.0 || + matrix[6] != 0.0 || matrix[7] != 0.0) { av_log(bsf, AV_LOG_WARNING, "Input display matrix is not " "representable in H.264 parameters.\n"); } else { @@ -531,13 +417,13 @@ disp->ver_flip = vflip; disp->anticlockwise_rotation = (uint16_t)rint((angle >= 0.0 ? angle - : angle + 360.0) * - 65536.0 / 360.0); + : angle + 2 * M_PI) * + 32768.0 / M_PI); write = 1; } } - if (has_sps || !ctx->done_first_au) { + if (seek_point) { if (!isnan(ctx->rotate)) { disp->anticlockwise_rotation = (uint16_t)rint((ctx->rotate >= 0.0 ? ctx->rotate @@ -555,96 +441,157 @@ if (write) { disp->display_orientation_repetition_period = 1; - err = ff_cbs_h264_add_sei_message(ctx->cbc, au, &payload); + err = ff_cbs_sei_add_message(ctx->common.output, au, 1, + SEI_TYPE_DISPLAY_ORIENTATION, + disp, NULL); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to add display orientation " "SEI message to access unit.\n"); - goto fail; + return err; } } } - err = ff_cbs_write_packet(ctx->cbc, pkt, au); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); - goto fail; - } - - ctx->done_first_au = 1; - - err = 0; -fail: - ff_cbs_fragment_reset(ctx->cbc, au); - - if (err < 0) - av_packet_unref(pkt); - - return err; + return 0; } -static int h264_metadata_init(AVBSFContext *bsf) +static int h264_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt, + CodedBitstreamFragment *au) { H264MetadataContext *ctx = bsf->priv_data; - CodedBitstreamFragment *au = &ctx->access_unit; - int err, i; + int err, i, has_sps, seek_point; - err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_H264, bsf); - if (err < 0) - return err; + // If an AUD is present, it must be the first NAL unit. + if (au->nb_units && au->units[0].type == H264_NAL_AUD) { + if (ctx->aud == BSF_ELEMENT_REMOVE) + ff_cbs_delete_unit(au, 0); + } else { + if (pkt && ctx->aud == BSF_ELEMENT_INSERT) { + err = h264_metadata_insert_aud(bsf, au); + if (err < 0) + return err; + } + } + + has_sps = 0; + for (i = 0; i < au->nb_units; i++) { + if (au->units[i].type == H264_NAL_SPS) { + err = h264_metadata_update_sps(bsf, au->units[i].content); + if (err < 0) + return err; + has_sps = 1; + } + } - if (bsf->par_in->extradata) { - err = ff_cbs_read_extradata(ctx->cbc, au, bsf->par_in); + if (pkt) { + // The current packet should be treated as a seek point for metadata + // insertion if any of: + // - It is the first packet in the stream. + // - It contains an SPS, indicating that a sequence might start here. + // - It is marked as containing a key frame. + seek_point = !ctx->done_first_au || has_sps || + (pkt->flags & AV_PKT_FLAG_KEY); + } else { + seek_point = 0; + } + + if (ctx->sei_user_data && seek_point) { + err = ff_cbs_sei_add_message(ctx->common.output, au, 1, + SEI_TYPE_USER_DATA_UNREGISTERED, + &ctx->sei_user_data_payload, NULL); if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); - goto fail; + av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI " + "message to access unit.\n"); + return err; } + } - for (i = 0; i < au->nb_units; i++) { - if (au->units[i].type == H264_NAL_SPS) { - err = h264_metadata_update_sps(bsf, au->units[i].content); - if (err < 0) - goto fail; + if (ctx->delete_filler) { + for (i = au->nb_units - 1; i >= 0; i--) { + if (au->units[i].type == H264_NAL_FILLER_DATA) { + ff_cbs_delete_unit(au, i); + continue; } } - err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, au); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); - goto fail; - } + ff_cbs_sei_delete_message_type(ctx->common.output, au, + SEI_TYPE_FILLER_PAYLOAD); + } + + if (pkt && ctx->display_orientation != BSF_ELEMENT_PASS) { + err = h264_metadata_handle_display_orientation(bsf, pkt, au, + seek_point); + if (err < 0) + return err; } - err = 0; -fail: - ff_cbs_fragment_reset(ctx->cbc, au); - return err; + if (pkt) + ctx->done_first_au = 1; + + return 0; } -static void h264_metadata_close(AVBSFContext *bsf) +static const CBSBSFType h264_metadata_type = { + .codec_id = AV_CODEC_ID_H264, + .fragment_name = "access unit", + .unit_name = "NAL unit", + .update_fragment = &h264_metadata_update_fragment, +}; + +static int h264_metadata_init(AVBSFContext *bsf) { H264MetadataContext *ctx = bsf->priv_data; - ff_cbs_fragment_free(ctx->cbc, &ctx->access_unit); - ff_cbs_close(&ctx->cbc); + if (ctx->sei_user_data) { + SEIRawUserDataUnregistered *udu = &ctx->sei_user_data_payload; + int i, j; + + // Parse UUID. It must be a hex string of length 32, possibly + // containing '-'s between hex digits (which we ignore). + for (i = j = 0; j < 32 && i < 64 && ctx->sei_user_data[i]; i++) { + int c, v; + c = ctx->sei_user_data[i]; + if (c == '-') { + continue; + } else if (av_isxdigit(c)) { + c = av_tolower(c); + v = (c <= '9' ? c - '0' : c - 'a' + 10); + } else { + break; + } + if (j & 1) + udu->uuid_iso_iec_11578[j / 2] |= v; + else + udu->uuid_iso_iec_11578[j / 2] = v << 4; + ++j; + } + if (j == 32 && ctx->sei_user_data[i] == '+') { + udu->data = (uint8_t*)ctx->sei_user_data + i + 1; + udu->data_length = strlen(udu->data) + 1; + } else { + av_log(bsf, AV_LOG_ERROR, "Invalid user data: " + "must be \"UUID+string\".\n"); + return AVERROR(EINVAL); + } + } + + return ff_cbs_bsf_generic_init(bsf, &h264_metadata_type); } #define OFFSET(x) offsetof(H264MetadataContext, x) #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) static const AVOption h264_metadata_options[] = { - { "aud", "Access Unit Delimiter NAL units", - OFFSET(aud), AV_OPT_TYPE_INT, - { .i64 = PASS }, PASS, REMOVE, FLAGS, "aud" }, - { "pass", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = PASS }, .flags = FLAGS, .unit = "aud" }, - { "insert", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = INSERT }, .flags = FLAGS, .unit = "aud" }, - { "remove", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = REMOVE }, .flags = FLAGS, .unit = "aud" }, + BSF_ELEMENT_OPTIONS_PIR("aud", "Access Unit Delimiter NAL units", + aud, FLAGS), { "sample_aspect_ratio", "Set sample aspect ratio (table E-1)", OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, { .dbl = 0.0 }, 0, 65535, FLAGS }, + { "overscan_appropriate_flag", "Set VUI overscan appropriate flag", + OFFSET(overscan_appropriate_flag), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, 1, FLAGS }, + { "video_format", "Set video format (table E-2)", OFFSET(video_format), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 7, FLAGS}, @@ -691,17 +638,9 @@ { "delete_filler", "Delete all filler (both NAL and SEI)", OFFSET(delete_filler), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS}, - { "display_orientation", "Display orientation SEI", - OFFSET(display_orientation), AV_OPT_TYPE_INT, - { .i64 = PASS }, PASS, EXTRACT, FLAGS, "disp_or" }, - { "pass", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = PASS }, .flags = FLAGS, .unit = "disp_or" }, - { "insert", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = INSERT }, .flags = FLAGS, .unit = "disp_or" }, - { "remove", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = REMOVE }, .flags = FLAGS, .unit = "disp_or" }, - { "extract", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = EXTRACT }, .flags = FLAGS, .unit = "disp_or" }, + BSF_ELEMENT_OPTIONS_PIRE("display_orientation", + "Display orientation SEI", + display_orientation, FLAGS), { "rotate", "Set rotation in display orientation SEI (anticlockwise angle in degrees)", OFFSET(rotate), AV_OPT_TYPE_DOUBLE, @@ -765,7 +704,7 @@ .priv_data_size = sizeof(H264MetadataContext), .priv_class = &h264_metadata_class, .init = &h264_metadata_init, - .close = &h264_metadata_close, - .filter = &h264_metadata_filter, + .close = &ff_cbs_bsf_generic_close, + .filter = &ff_cbs_bsf_generic_filter, .codec_ids = h264_metadata_codec_ids, }; diff -Nru ffmpeg-4.2.2/libavcodec/h264_mp4toannexb_bsf.c ffmpeg-4.4/libavcodec/h264_mp4toannexb_bsf.c --- ffmpeg-4.2.2/libavcodec/h264_mp4toannexb_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_mp4toannexb_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -21,16 +21,21 @@ #include +#include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" #include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" +#include "bytestream.h" #include "h264.h" typedef struct H264BSFContext { - int32_t sps_offset; - int32_t pps_offset; + uint8_t *sps; + uint8_t *pps; + int sps_size; + int pps_size; uint8_t length_size; uint8_t new_idr; uint8_t idr_sps_seen; @@ -38,98 +43,91 @@ int extradata_parsed; } H264BSFContext; -static int alloc_and_copy(AVPacket *out, - const uint8_t *sps_pps, uint32_t sps_pps_size, - const uint8_t *in, uint32_t in_size, int ps) +static void count_or_copy(uint8_t **out, uint64_t *out_size, + const uint8_t *in, int in_size, int ps, int copy) { - uint32_t offset = out->size; - uint8_t start_code_size = offset == 0 || ps ? 4 : 3; - int err; - - err = av_grow_packet(out, sps_pps_size + in_size + start_code_size); - if (err < 0) - return err; - - if (sps_pps) - memcpy(out->data + offset, sps_pps, sps_pps_size); - memcpy(out->data + sps_pps_size + start_code_size + offset, in, in_size); - if (start_code_size == 4) { - AV_WB32(out->data + offset + sps_pps_size, 1); - } else { - (out->data + offset + sps_pps_size)[0] = - (out->data + offset + sps_pps_size)[1] = 0; - (out->data + offset + sps_pps_size)[2] = 1; - } + uint8_t start_code_size = ps < 0 ? 0 : *out_size == 0 || ps ? 4 : 3; - return 0; + if (copy) { + memcpy(*out + start_code_size, in, in_size); + if (start_code_size == 4) { + AV_WB32(*out, 1); + } else if (start_code_size) { + (*out)[0] = + (*out)[1] = 0; + (*out)[2] = 1; + } + *out += start_code_size + in_size; + } + *out_size += start_code_size + in_size; } static int h264_extradata_to_annexb(AVBSFContext *ctx, const int padding) { H264BSFContext *s = ctx->priv_data; + GetByteContext ogb, *gb = &ogb; uint16_t unit_size; - uint64_t total_size = 0; - uint8_t *out = NULL, unit_nb, sps_done = 0, - sps_seen = 0, pps_seen = 0; - const uint8_t *extradata = ctx->par_in->extradata + 4; + uint32_t total_size = 0; + uint8_t *out = NULL, unit_nb, sps_done = 0; static const uint8_t nalu_header[4] = { 0, 0, 0, 1 }; - int length_size = (*extradata++ & 0x3) + 1; // retrieve length coded size + int length_size, pps_offset = 0; - s->sps_offset = s->pps_offset = -1; + bytestream2_init(gb, ctx->par_in->extradata, ctx->par_in->extradata_size); + + bytestream2_skipu(gb, 4); + + /* retrieve length coded size */ + length_size = (bytestream2_get_byteu(gb) & 0x3) + 1; /* retrieve sps and pps unit(s) */ - unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */ + unit_nb = bytestream2_get_byteu(gb) & 0x1f; /* number of sps unit(s) */ if (!unit_nb) { goto pps; - } else { - s->sps_offset = 0; - sps_seen = 1; } while (unit_nb--) { int err; - unit_size = AV_RB16(extradata); + /* possible overread ok due to padding */ + unit_size = bytestream2_get_be16u(gb); total_size += unit_size + 4; - if (total_size > INT_MAX - padding) { - av_log(ctx, AV_LOG_ERROR, - "Too big extradata size, corrupted stream or invalid MP4/AVCC bitstream\n"); - av_free(out); - return AVERROR(EINVAL); - } - if (extradata + 2 + unit_size > ctx->par_in->extradata + ctx->par_in->extradata_size) { - av_log(ctx, AV_LOG_ERROR, "Packet header is not contained in global extradata, " + av_assert1(total_size <= INT_MAX - padding); + if (bytestream2_get_bytes_left(gb) < unit_size + !sps_done) { + av_log(ctx, AV_LOG_ERROR, "Global extradata truncated, " "corrupted stream or invalid MP4/AVCC bitstream\n"); av_free(out); - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; } if ((err = av_reallocp(&out, total_size + padding)) < 0) return err; memcpy(out + total_size - unit_size - 4, nalu_header, 4); - memcpy(out + total_size - unit_size, extradata + 2, unit_size); - extradata += 2 + unit_size; + bytestream2_get_bufferu(gb, out + total_size - unit_size, unit_size); pps: if (!unit_nb && !sps_done++) { - unit_nb = *extradata++; /* number of pps unit(s) */ - if (unit_nb) { - s->pps_offset = total_size; - pps_seen = 1; - } + unit_nb = bytestream2_get_byteu(gb); /* number of pps unit(s) */ + pps_offset = total_size; } } if (out) memset(out + total_size, 0, padding); - if (!sps_seen) + if (pps_offset) { + s->sps = out; + s->sps_size = pps_offset; + } else { av_log(ctx, AV_LOG_WARNING, "Warning: SPS NALU missing or invalid. " "The resulting stream may not play.\n"); - - if (!pps_seen) + } + if (pps_offset < total_size) { + s->pps = out + pps_offset; + s->pps_size = total_size - pps_offset; + } else { av_log(ctx, AV_LOG_WARNING, "Warning: PPS NALU missing or invalid. " "The resulting stream may not play.\n"); + } av_freep(&ctx->par_out->extradata); ctx->par_out->extradata = out; @@ -150,7 +148,7 @@ (extra_size >= 4 && AV_RB32(ctx->par_in->extradata) == 1)) { av_log(ctx, AV_LOG_VERBOSE, "The input looks like it is Annex B already\n"); - } else if (extra_size >= 6) { + } else if (extra_size >= 7) { ret = h264_extradata_to_annexb(ctx, AV_INPUT_BUFFER_PADDING_SIZE); if (ret < 0) return ret; @@ -168,18 +166,16 @@ return 0; } -static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out) +static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *opkt) { H264BSFContext *s = ctx->priv_data; - AVPacket *in; - uint8_t unit_type; - int32_t nal_size; - uint32_t cumul_size = 0; + uint8_t unit_type, new_idr, sps_seen, pps_seen; const uint8_t *buf; const uint8_t *buf_end; - int buf_size; - int ret = 0, i; + uint8_t *out; + uint64_t out_size; + int ret; ret = ff_bsf_get_packet(ctx, &in); if (ret < 0) @@ -187,94 +183,117 @@ /* nothing to filter */ if (!s->extradata_parsed) { - av_packet_move_ref(out, in); + av_packet_move_ref(opkt, in); av_packet_free(&in); return 0; } - buf = in->data; - buf_size = in->size; buf_end = in->data + in->size; - do { - ret= AVERROR(EINVAL); - if (buf + s->length_size > buf_end) - goto fail; - - for (nal_size = 0, i = 0; ilength_size; i++) - nal_size = (nal_size << 8) | buf[i]; - - buf += s->length_size; - unit_type = *buf & 0x1f; - - if (nal_size > buf_end - buf || nal_size < 0) - goto fail; - - if (unit_type == H264_NAL_SPS) - s->idr_sps_seen = s->new_idr = 1; - else if (unit_type == H264_NAL_PPS) { - s->idr_pps_seen = s->new_idr = 1; - /* if SPS has not been seen yet, prepend the AVCC one to PPS */ - if (!s->idr_sps_seen) { - if (s->sps_offset == -1) - av_log(ctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n"); - else { - if ((ret = alloc_and_copy(out, - ctx->par_out->extradata + s->sps_offset, - s->pps_offset != -1 ? s->pps_offset : ctx->par_out->extradata_size - s->sps_offset, - buf, nal_size, 1)) < 0) - goto fail; - s->idr_sps_seen = 1; - goto next_nal; +#define LOG_ONCE(...) \ + if (j) \ + av_log(__VA_ARGS__) + for (int j = 0; j < 2; j++) { + buf = in->data; + new_idr = s->new_idr; + sps_seen = s->idr_sps_seen; + pps_seen = s->idr_pps_seen; + out_size = 0; + + do { + uint32_t nal_size = 0; + + /* possible overread ok due to padding */ + for (int i = 0; i < s->length_size; i++) + nal_size = (nal_size << 8) | buf[i]; + + buf += s->length_size; + + /* This check requires the cast as the right side might + * otherwise be promoted to an unsigned value. */ + if ((int64_t)nal_size > buf_end - buf) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + if (!nal_size) + continue; + + unit_type = *buf & 0x1f; + + if (unit_type == H264_NAL_SPS) { + sps_seen = new_idr = 1; + } else if (unit_type == H264_NAL_PPS) { + pps_seen = new_idr = 1; + /* if SPS has not been seen yet, prepend the AVCC one to PPS */ + if (!sps_seen) { + if (!s->sps_size) { + LOG_ONCE(ctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n"); + } else { + count_or_copy(&out, &out_size, s->sps, s->sps_size, -1, j); + sps_seen = 1; + } } } - } - /* if this is a new IDR picture following an IDR picture, reset the idr flag. - * Just check first_mb_in_slice to be 0 as this is the simplest solution. - * This could be checking idr_pic_id instead, but would complexify the parsing. */ - if (!s->new_idr && unit_type == H264_NAL_IDR_SLICE && (buf[1] & 0x80)) - s->new_idr = 1; - - /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */ - if (s->new_idr && unit_type == H264_NAL_IDR_SLICE && !s->idr_sps_seen && !s->idr_pps_seen) { - if ((ret=alloc_and_copy(out, - ctx->par_out->extradata, ctx->par_out->extradata_size, - buf, nal_size, 1)) < 0) - goto fail; - s->new_idr = 0; - /* if only SPS has been seen, also insert PPS */ - } else if (s->new_idr && unit_type == H264_NAL_IDR_SLICE && s->idr_sps_seen && !s->idr_pps_seen) { - if (s->pps_offset == -1) { - av_log(ctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n"); - if ((ret = alloc_and_copy(out, NULL, 0, buf, nal_size, 0)) < 0) - goto fail; - } else if ((ret = alloc_and_copy(out, - ctx->par_out->extradata + s->pps_offset, ctx->par_out->extradata_size - s->pps_offset, - buf, nal_size, 1)) < 0) - goto fail; - } else { - if ((ret=alloc_and_copy(out, NULL, 0, buf, nal_size, unit_type == H264_NAL_SPS || unit_type == H264_NAL_PPS)) < 0) + /* If this is a new IDR picture following an IDR picture, reset the idr flag. + * Just check first_mb_in_slice to be 0 as this is the simplest solution. + * This could be checking idr_pic_id instead, but would complexify the parsing. */ + if (!new_idr && unit_type == H264_NAL_IDR_SLICE && (buf[1] & 0x80)) + new_idr = 1; + + /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */ + if (new_idr && unit_type == H264_NAL_IDR_SLICE && !sps_seen && !pps_seen) { + if (ctx->par_out->extradata) + count_or_copy(&out, &out_size, ctx->par_out->extradata, + ctx->par_out->extradata_size, -1, j); + new_idr = 0; + /* if only SPS has been seen, also insert PPS */ + } else if (new_idr && unit_type == H264_NAL_IDR_SLICE && sps_seen && !pps_seen) { + if (!s->pps_size) { + LOG_ONCE(ctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n"); + } else { + count_or_copy(&out, &out_size, s->pps, s->pps_size, -1, j); + } + } + + count_or_copy(&out, &out_size, buf, nal_size, + unit_type == H264_NAL_SPS || unit_type == H264_NAL_PPS, j); + if (!new_idr && unit_type == H264_NAL_SLICE) { + new_idr = 1; + sps_seen = 0; + pps_seen = 0; + } + + buf += nal_size; + } while (buf < buf_end); + + if (!j) { + if (out_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { + ret = AVERROR_INVALIDDATA; goto fail; - if (!s->new_idr && unit_type == H264_NAL_SLICE) { - s->new_idr = 1; - s->idr_sps_seen = 0; - s->idr_pps_seen = 0; } + ret = av_new_packet(opkt, out_size); + if (ret < 0) + goto fail; + out = opkt->data; } + } +#undef LOG_ONCE + + av_assert1(out_size == opkt->size); -next_nal: - buf += nal_size; - cumul_size += nal_size + s->length_size; - } while (cumul_size < buf_size); + s->new_idr = new_idr; + s->idr_sps_seen = sps_seen; + s->idr_pps_seen = pps_seen; - ret = av_packet_copy_props(out, in); + ret = av_packet_copy_props(opkt, in); if (ret < 0) goto fail; fail: if (ret < 0) - av_packet_unref(out); + av_packet_unref(opkt); av_packet_free(&in); return ret; diff -Nru ffmpeg-4.2.2/libavcodec/h264_mvpred.h ffmpeg-4.4/libavcodec/h264_mvpred.h --- ffmpeg-4.2.2/libavcodec/h264_mvpred.h 2018-11-01 18:34:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_mvpred.h 2021-04-08 21:28:39.000000000 +0000 @@ -33,6 +33,7 @@ #include "h264dec.h" #include "mpegutils.h" #include "libavutil/avassert.h" +#include "libavutil/mem_internal.h" static av_always_inline int fetch_diagonal_mv(const H264Context *h, H264SliceContext *sl, diff -Nru ffmpeg-4.2.2/libavcodec/h264_parse.c ffmpeg-4.4/libavcodec/h264_parse.c --- ffmpeg-4.2.2/libavcodec/h264_parse.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_parse.c 2021-04-08 21:28:39.000000000 +0000 @@ -35,7 +35,7 @@ pwt->use_weight = 0; pwt->use_weight_chroma = 0; - pwt->luma_log2_weight_denom = get_ue_golomb(gb); + pwt->luma_log2_weight_denom = get_ue_golomb_31(gb); if (pwt->luma_log2_weight_denom > 7U) { av_log(logctx, AV_LOG_ERROR, "luma_log2_weight_denom %d is out of range\n", pwt->luma_log2_weight_denom); pwt->luma_log2_weight_denom = 0; @@ -43,7 +43,7 @@ luma_def = 1 << pwt->luma_log2_weight_denom; if (sps->chroma_format_idc) { - pwt->chroma_log2_weight_denom = get_ue_golomb(gb); + pwt->chroma_log2_weight_denom = get_ue_golomb_31(gb); if (pwt->chroma_log2_weight_denom > 7U) { av_log(logctx, AV_LOG_ERROR, "chroma_log2_weight_denom %d is out of range\n", pwt->chroma_log2_weight_denom); pwt->chroma_log2_weight_denom = 0; @@ -287,6 +287,8 @@ if (sps->poc_type == 0) { const int max_poc_lsb = 1 << sps->log2_max_poc_lsb; + if (pc->prev_poc_lsb < 0) + pc->prev_poc_lsb = pc->poc_lsb; if (pc->poc_lsb < pc->prev_poc_lsb && pc->prev_poc_lsb - pc->poc_lsb >= max_poc_lsb / 2) @@ -374,11 +376,22 @@ for (i = 0; i < pkt.nb_nals; i++) { H2645NAL *nal = &pkt.nals[i]; switch (nal->type) { - case H264_NAL_SPS: - ret = ff_h264_decode_seq_parameter_set(&nal->gb, logctx, ps, 0); + case H264_NAL_SPS: { + GetBitContext tmp_gb = nal->gb; + ret = ff_h264_decode_seq_parameter_set(&tmp_gb, logctx, ps, 0); + if (ret >= 0) + break; + av_log(logctx, AV_LOG_DEBUG, + "SPS decoding failure, trying again with the complete NAL\n"); + init_get_bits8(&tmp_gb, nal->raw_data + 1, nal->raw_size - 1); + ret = ff_h264_decode_seq_parameter_set(&tmp_gb, logctx, ps, 0); + if (ret >= 0) + break; + ret = ff_h264_decode_seq_parameter_set(&nal->gb, logctx, ps, 1); if (ret < 0) goto fail; break; + } case H264_NAL_PPS: ret = ff_h264_decode_picture_parameter_set(&nal->gb, logctx, ps, nal->size_bits); diff -Nru ffmpeg-4.2.2/libavcodec/h264_parser.c ffmpeg-4.4/libavcodec/h264_parser.c --- ffmpeg-4.2.2/libavcodec/h264_parser.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_parser.c 2020-07-11 10:39:30.000000000 +0000 @@ -361,26 +361,14 @@ } av_buffer_unref(&p->ps.pps_ref); - av_buffer_unref(&p->ps.sps_ref); p->ps.pps = NULL; p->ps.sps = NULL; p->ps.pps_ref = av_buffer_ref(p->ps.pps_list[pps_id]); if (!p->ps.pps_ref) goto fail; p->ps.pps = (const PPS*)p->ps.pps_ref->data; - - if (!p->ps.sps_list[p->ps.pps->sps_id]) { - av_log(avctx, AV_LOG_ERROR, - "non-existing SPS %u referenced\n", p->ps.pps->sps_id); - goto fail; - } - - p->ps.sps_ref = av_buffer_ref(p->ps.sps_list[p->ps.pps->sps_id]); - if (!p->ps.sps_ref) - goto fail; - p->ps.sps = (const SPS*)p->ps.sps_ref->data; - - sps = p->ps.sps; + p->ps.sps = p->ps.pps->sps; + sps = p->ps.sps; // heuristic to detect non marked keyframes if (p->ps.sps->ref_frame_count <= 1 && p->ps.pps->ref_count[0] <= 1 && s->pict_type == AV_PICTURE_TYPE_I) @@ -481,6 +469,15 @@ } } + if (p->sei.picture_timing.present) { + ret = ff_h264_sei_process_picture_timing(&p->sei.picture_timing, + sps, avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error processing the picture timing SEI\n"); + p->sei.picture_timing.present = 0; + } + } + if (sps->pic_struct_present_flag && p->sei.picture_timing.present) { switch (p->sei.picture_timing.pic_struct) { case H264_SEI_PIC_STRUCT_TOP_FIELD: diff -Nru ffmpeg-4.2.2/libavcodec/h264_picture.c ffmpeg-4.4/libavcodec/h264_picture.c --- ffmpeg-4.2.2/libavcodec/h264_picture.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_picture.c 2020-07-11 10:39:30.000000000 +0000 @@ -27,7 +27,6 @@ #include "libavutil/avassert.h" #include "libavutil/imgutils.h" -#include "libavutil/timer.h" #include "internal.h" #include "cabac.h" #include "cabac_functions.h" @@ -55,6 +54,7 @@ av_buffer_unref(&pic->qscale_table_buf); av_buffer_unref(&pic->mb_type_buf); + av_buffer_unref(&pic->pps_buf); for (i = 0; i < 2; i++) { av_buffer_unref(&pic->motion_val_buf[i]); av_buffer_unref(&pic->ref_index_buf[i]); @@ -78,12 +78,14 @@ dst->qscale_table_buf = av_buffer_ref(src->qscale_table_buf); dst->mb_type_buf = av_buffer_ref(src->mb_type_buf); - if (!dst->qscale_table_buf || !dst->mb_type_buf) { + dst->pps_buf = av_buffer_ref(src->pps_buf); + if (!dst->qscale_table_buf || !dst->mb_type_buf || !dst->pps_buf) { ret = AVERROR(ENOMEM); goto fail; } dst->qscale_table = src->qscale_table; dst->mb_type = src->mb_type; + dst->pps = src->pps; for (i = 0; i < 2; i++) { dst->motion_val_buf[i] = av_buffer_ref(src->motion_val_buf[i]); @@ -121,6 +123,9 @@ dst->recovered = src->recovered; dst->invalid_gap = src->invalid_gap; dst->sei_recovery_frame_cnt = src->sei_recovery_frame_cnt; + dst->mb_width = src->mb_width; + dst->mb_height = src->mb_height; + dst->mb_stride = src->mb_stride; return 0; fail: diff -Nru ffmpeg-4.2.2/libavcodec/h264_ps.c ffmpeg-4.4/libavcodec/h264_ps.c --- ffmpeg-4.2.2/libavcodec/h264_ps.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_ps.c 2021-04-08 21:28:39.000000000 +0000 @@ -104,14 +104,14 @@ av_buffer_unref(&s->sps_list[id]); } -static inline int decode_hrd_parameters(GetBitContext *gb, AVCodecContext *avctx, +static inline int decode_hrd_parameters(GetBitContext *gb, void *logctx, SPS *sps) { int cpb_count, i; cpb_count = get_ue_golomb_31(gb) + 1; if (cpb_count > 32U) { - av_log(avctx, AV_LOG_ERROR, "cpb_count %d invalid\n", cpb_count); + av_log(logctx, AV_LOG_ERROR, "cpb_count %d invalid\n", cpb_count); return AVERROR_INVALIDDATA; } @@ -130,7 +130,7 @@ return 0; } -static inline int decode_vui_parameters(GetBitContext *gb, AVCodecContext *avctx, +static inline int decode_vui_parameters(GetBitContext *gb, void *logctx, SPS *sps) { int aspect_ratio_info_present_flag; @@ -146,7 +146,7 @@ } else if (aspect_ratio_idc < FF_ARRAY_ELEMS(ff_h264_pixel_aspect)) { sps->sar = ff_h264_pixel_aspect[aspect_ratio_idc]; } else { - av_log(avctx, AV_LOG_ERROR, "illegal aspect ratio\n"); + av_log(logctx, AV_LOG_ERROR, "illegal aspect ratio\n"); return AVERROR_INVALIDDATA; } } else { @@ -181,12 +181,13 @@ /* chroma_location_info_present_flag */ if (get_bits1(gb)) { /* chroma_sample_location_type_top_field */ - avctx->chroma_sample_location = get_ue_golomb(gb) + 1; - get_ue_golomb(gb); /* chroma_sample_location_type_bottom_field */ - } + sps->chroma_location = get_ue_golomb_31(gb) + 1; + get_ue_golomb_31(gb); /* chroma_sample_location_type_bottom_field */ + } else + sps->chroma_location = AVCHROMA_LOC_LEFT; if (show_bits1(gb) && get_bits_left(gb) < 10) { - av_log(avctx, AV_LOG_WARNING, "Truncated VUI\n"); + av_log(logctx, AV_LOG_WARNING, "Truncated VUI (%d)\n", get_bits_left(gb)); return 0; } @@ -195,7 +196,7 @@ unsigned num_units_in_tick = get_bits_long(gb, 32); unsigned time_scale = get_bits_long(gb, 32); if (!num_units_in_tick || !time_scale) { - av_log(avctx, AV_LOG_ERROR, + av_log(logctx, AV_LOG_ERROR, "time_scale/num_units_in_tick invalid or unsupported (%u/%u)\n", time_scale, num_units_in_tick); sps->timing_info_present_flag = 0; @@ -208,11 +209,11 @@ sps->nal_hrd_parameters_present_flag = get_bits1(gb); if (sps->nal_hrd_parameters_present_flag) - if (decode_hrd_parameters(gb, avctx, sps) < 0) + if (decode_hrd_parameters(gb, logctx, sps) < 0) return AVERROR_INVALIDDATA; sps->vcl_hrd_parameters_present_flag = get_bits1(gb); if (sps->vcl_hrd_parameters_present_flag) - if (decode_hrd_parameters(gb, avctx, sps) < 0) + if (decode_hrd_parameters(gb, logctx, sps) < 0) return AVERROR_INVALIDDATA; if (sps->nal_hrd_parameters_present_flag || sps->vcl_hrd_parameters_present_flag) @@ -223,12 +224,12 @@ sps->bitstream_restriction_flag = get_bits1(gb); if (sps->bitstream_restriction_flag) { get_bits1(gb); /* motion_vectors_over_pic_boundaries_flag */ - get_ue_golomb(gb); /* max_bytes_per_pic_denom */ - get_ue_golomb(gb); /* max_bits_per_mb_denom */ - get_ue_golomb(gb); /* log2_max_mv_length_horizontal */ - get_ue_golomb(gb); /* log2_max_mv_length_vertical */ - sps->num_reorder_frames = get_ue_golomb(gb); - get_ue_golomb(gb); /*max_dec_frame_buffering*/ + get_ue_golomb_31(gb); /* max_bytes_per_pic_denom */ + get_ue_golomb_31(gb); /* max_bits_per_mb_denom */ + get_ue_golomb_31(gb); /* log2_max_mv_length_horizontal */ + get_ue_golomb_31(gb); /* log2_max_mv_length_vertical */ + sps->num_reorder_frames = get_ue_golomb_31(gb); + get_ue_golomb_31(gb); /*max_dec_frame_buffering*/ if (get_bits_left(gb) < 0) { sps->num_reorder_frames = 0; @@ -237,7 +238,7 @@ if (sps->num_reorder_frames > 16U /* max_dec_frame_buffering || max_dec_frame_buffering > 16 */) { - av_log(avctx, AV_LOG_ERROR, + av_log(logctx, AV_LOG_ERROR, "Clipping illegal num_reorder_frames %d\n", sps->num_reorder_frames); sps->num_reorder_frames = 16; @@ -323,7 +324,6 @@ for (i = 0; i < MAX_PPS_COUNT; i++) av_buffer_unref(&ps->pps_list[i]); - av_buffer_unref(&ps->sps_ref); av_buffer_unref(&ps->pps_ref); ps->pps = NULL; @@ -403,8 +403,8 @@ goto fail; } } - sps->bit_depth_luma = get_ue_golomb(gb) + 8; - sps->bit_depth_chroma = get_ue_golomb(gb) + 8; + sps->bit_depth_luma = get_ue_golomb_31(gb) + 8; + sps->bit_depth_chroma = get_ue_golomb_31(gb) + 8; if (sps->bit_depth_chroma != sps->bit_depth_luma) { avpriv_request_sample(avctx, "Different chroma and luma bit depth"); @@ -428,7 +428,7 @@ sps->bit_depth_chroma = 8; } - log2_max_frame_num_minus4 = get_ue_golomb(gb); + log2_max_frame_num_minus4 = get_ue_golomb_31(gb); if (log2_max_frame_num_minus4 < MIN_LOG2_MAX_FRAME_NUM - 4 || log2_max_frame_num_minus4 > MAX_LOG2_MAX_FRAME_NUM - 4) { av_log(avctx, AV_LOG_ERROR, @@ -441,7 +441,7 @@ sps->poc_type = get_ue_golomb_31(gb); if (sps->poc_type == 0) { // FIXME #define - unsigned t = get_ue_golomb(gb); + unsigned t = get_ue_golomb_31(gb); if (t>12) { av_log(avctx, AV_LOG_ERROR, "log2_max_poc_lsb (%d) is out of range\n", t); goto fail; @@ -579,7 +579,8 @@ } if (get_bits_left(gb) < 0) { - av_log(avctx, ignore_truncation ? AV_LOG_WARNING : AV_LOG_ERROR, + av_log_once(avctx, ignore_truncation ? AV_LOG_WARNING : AV_LOG_ERROR, AV_LOG_DEBUG, + &ps->overread_warning_printed[sps->vui_parameters_present_flag], "Overread %s by %d bits\n", sps->vui_parameters_present_flag ? "VUI" : "SPS", -get_bits_left(gb)); if (!ignore_truncation) goto fail; @@ -736,6 +737,15 @@ return 1; } +static void pps_free(void *opaque, uint8_t *data) +{ + PPS *pps = (PPS*)data; + + av_buffer_unref(&pps->sps_ref); + + av_freep(&data); +} + int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avctx, H264ParamSets *ps, int bit_length) { @@ -752,10 +762,15 @@ return AVERROR_INVALIDDATA; } - pps_buf = av_buffer_allocz(sizeof(*pps)); - if (!pps_buf) + pps = av_mallocz(sizeof(*pps)); + if (!pps) return AVERROR(ENOMEM); - pps = (PPS*)pps_buf->data; + pps_buf = av_buffer_create((uint8_t*)pps, sizeof(*pps), + pps_free, NULL, 0); + if (!pps_buf) { + av_freep(&pps); + return AVERROR(ENOMEM); + } pps->data_size = gb->buffer_end - gb->buffer; if (pps->data_size > sizeof(pps->data)) { @@ -773,7 +788,14 @@ ret = AVERROR_INVALIDDATA; goto fail; } - sps = (const SPS*)ps->sps_list[pps->sps_id]->data; + pps->sps_ref = av_buffer_ref(ps->sps_list[pps->sps_id]); + if (!pps->sps_ref) { + ret = AVERROR(ENOMEM); + goto fail; + } + pps->sps = (const SPS*)pps->sps_ref->data; + sps = pps->sps; + if (sps->bit_depth_luma > 14) { av_log(avctx, AV_LOG_ERROR, "Invalid luma bit depth=%d\n", @@ -793,7 +815,9 @@ pps->slice_group_count = get_ue_golomb(gb) + 1; if (pps->slice_group_count > 1) { pps->mb_slice_group_map_type = get_ue_golomb(gb); - av_log(avctx, AV_LOG_ERROR, "FMO not supported\n"); + avpriv_report_missing_feature(avctx, "FMO"); + ret = AVERROR_PATCHWELCOME; + goto fail; } pps->ref_count[0] = get_ue_golomb(gb) + 1; pps->ref_count[1] = get_ue_golomb(gb) + 1; diff -Nru ffmpeg-4.2.2/libavcodec/h264_ps.h ffmpeg-4.4/libavcodec/h264_ps.h --- ffmpeg-4.2.2/libavcodec/h264_ps.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_ps.h 2020-07-11 10:39:30.000000000 +0000 @@ -77,6 +77,8 @@ enum AVColorPrimaries color_primaries; enum AVColorTransferCharacteristic color_trc; enum AVColorSpace colorspace; + enum AVChromaLocation chroma_location; + int timing_info_present_flag; uint32_t num_units_in_tick; uint32_t time_scale; @@ -133,6 +135,9 @@ uint32_t dequant8_buffer[6][QP_MAX_NUM + 1][64]; uint32_t(*dequant4_coeff[6])[16]; uint32_t(*dequant8_coeff[6])[64]; + + AVBufferRef *sps_ref; + const SPS *sps; } PPS; typedef struct H264ParamSets { @@ -140,10 +145,11 @@ AVBufferRef *pps_list[MAX_PPS_COUNT]; AVBufferRef *pps_ref; - AVBufferRef *sps_ref; /* currently active parameters sets */ const PPS *pps; const SPS *sps; + + int overread_warning_printed[2]; } H264ParamSets; /** diff -Nru ffmpeg-4.2.2/libavcodec/h264_redundant_pps_bsf.c ffmpeg-4.4/libavcodec/h264_redundant_pps_bsf.c --- ffmpeg-4.2.2/libavcodec/h264_redundant_pps_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_redundant_pps_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,16 +22,15 @@ #include "libavutil/mem.h" #include "bsf.h" +#include "bsf_internal.h" #include "cbs.h" +#include "cbs_bsf.h" #include "cbs_h264.h" #include "h264.h" typedef struct H264RedundantPPSContext { - CodedBitstreamContext *input; - CodedBitstreamContext *output; - - CodedBitstreamFragment access_unit; + CBSBSFContext common; int global_pic_init_qp; int current_pic_init_qp; @@ -40,8 +39,19 @@ static int h264_redundant_pps_fixup_pps(H264RedundantPPSContext *ctx, - H264RawPPS *pps) + CodedBitstreamUnit *unit) { + H264RawPPS *pps; + int err; + + // The changes we are about to perform affect the parsing process, + // so we must make sure that the PPS is writable, otherwise the + // parsing of future slices will be incorrect and even raise errors. + err = ff_cbs_make_unit_writable(ctx->common.input, unit); + if (err < 0) + 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; @@ -66,21 +76,14 @@ return 0; } -static int h264_redundant_pps_filter(AVBSFContext *bsf, AVPacket *pkt) +static int h264_redundant_pps_update_fragment(AVBSFContext *bsf, + AVPacket *pkt, + CodedBitstreamFragment *au) { H264RedundantPPSContext *ctx = bsf->priv_data; - CodedBitstreamFragment *au = &ctx->access_unit; int au_has_sps; int err, i; - err = ff_bsf_get_packet_ref(bsf, pkt); - if (err < 0) - return err; - - err = ff_cbs_read_packet(ctx->input, au, pkt); - if (err < 0) - goto fail; - au_has_sps = 0; for (i = 0; i < au->nb_units; i++) { CodedBitstreamUnit *nal = &au->units[i]; @@ -88,13 +91,13 @@ if (nal->type == H264_NAL_SPS) au_has_sps = 1; if (nal->type == H264_NAL_PPS) { - err = h264_redundant_pps_fixup_pps(ctx, nal->content); + err = h264_redundant_pps_fixup_pps(ctx, nal); if (err < 0) - goto fail; + return err; if (!au_has_sps) { av_log(bsf, AV_LOG_VERBOSE, "Deleting redundant PPS " "at %"PRId64".\n", pkt->pts); - ff_cbs_delete_unit(ctx->input, au, i); + ff_cbs_delete_unit(au, i); i--; continue; } @@ -106,62 +109,7 @@ } } - err = ff_cbs_write_packet(ctx->output, pkt, au); - if (err < 0) - goto fail; - - err = 0; -fail: - ff_cbs_fragment_reset(ctx->output, au); - if (err < 0) - av_packet_unref(pkt); - - return err; -} - -static int h264_redundant_pps_init(AVBSFContext *bsf) -{ - H264RedundantPPSContext *ctx = bsf->priv_data; - CodedBitstreamFragment *au = &ctx->access_unit; - int err, i; - - err = ff_cbs_init(&ctx->input, AV_CODEC_ID_H264, bsf); - if (err < 0) - return err; - - err = ff_cbs_init(&ctx->output, AV_CODEC_ID_H264, bsf); - if (err < 0) - return err; - - ctx->global_pic_init_qp = 26; - - if (bsf->par_in->extradata) { - err = ff_cbs_read_extradata(ctx->input, au, bsf->par_in); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); - goto fail; - } - - for (i = 0; i < au->nb_units; i++) { - if (au->units[i].type == H264_NAL_PPS) { - err = h264_redundant_pps_fixup_pps(ctx, au->units[i].content); - if (err < 0) - goto fail; - } - } - - ctx->extradata_pic_init_qp = ctx->current_pic_init_qp; - err = ff_cbs_write_extradata(ctx->output, bsf->par_out, au); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); - goto fail; - } - } - - err = 0; -fail: - ff_cbs_fragment_reset(ctx->output, au); - return err; + return 0; } static void h264_redundant_pps_flush(AVBSFContext *bsf) @@ -170,13 +118,20 @@ ctx->current_pic_init_qp = ctx->extradata_pic_init_qp; } -static void h264_redundant_pps_close(AVBSFContext *bsf) +static const CBSBSFType h264_redundant_pps_type = { + .codec_id = AV_CODEC_ID_H264, + .fragment_name = "access unit", + .unit_name = "NAL unit", + .update_fragment = &h264_redundant_pps_update_fragment, +}; + +static int h264_redundant_pps_init(AVBSFContext *bsf) { H264RedundantPPSContext *ctx = bsf->priv_data; - ff_cbs_fragment_free(ctx->input, &ctx->access_unit); - ff_cbs_close(&ctx->input); - ff_cbs_close(&ctx->output); + ctx->global_pic_init_qp = 26; + + return ff_cbs_bsf_generic_init(bsf, &h264_redundant_pps_type); } static const enum AVCodecID h264_redundant_pps_codec_ids[] = { @@ -188,7 +143,7 @@ .priv_data_size = sizeof(H264RedundantPPSContext), .init = &h264_redundant_pps_init, .flush = &h264_redundant_pps_flush, - .close = &h264_redundant_pps_close, - .filter = &h264_redundant_pps_filter, + .close = &ff_cbs_bsf_generic_close, + .filter = &ff_cbs_bsf_generic_filter, .codec_ids = h264_redundant_pps_codec_ids, }; diff -Nru ffmpeg-4.2.2/libavcodec/h264_refs.c ffmpeg-4.4/libavcodec/h264_refs.c --- ffmpeg-4.2.2/libavcodec/h264_refs.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_refs.c 2020-07-11 10:39:30.000000000 +0000 @@ -732,7 +732,7 @@ for (j = 0; j < MAX_DELAYED_PIC_COUNT; j++) h->last_pocs[j] = INT_MIN; break; - default: assert(0); + default: av_assert0(0); } } @@ -868,6 +868,7 @@ av_log(logctx, AV_LOG_ERROR, "illegal long ref in memory management control " "operation %d\n", opcode); + sl->nb_mmco = i; return -1; } mmco[i].long_arg = long_arg; @@ -877,6 +878,7 @@ av_log(logctx, AV_LOG_ERROR, "illegal memory management control operation %d\n", opcode); + sl->nb_mmco = i; return -1; } if (opcode == MMCO_END) diff -Nru ffmpeg-4.2.2/libavcodec/h264_sei.c ffmpeg-4.4/libavcodec/h264_sei.c --- ffmpeg-4.2.2/libavcodec/h264_sei.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_sei.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,6 +25,7 @@ * @author Michael Niedermayer */ +#include "atsc_a53.h" #include "avcodec.h" #include "get_bits.h" #include "golomb.h" @@ -52,32 +53,28 @@ h->afd.present = 0; av_buffer_unref(&h->a53_caption.buf_ref); + for (int i = 0; i < h->unregistered.nb_buf_ref; i++) + av_buffer_unref(&h->unregistered.buf_ref[i]); + h->unregistered.nb_buf_ref = 0; + av_freep(&h->unregistered.buf_ref); } -static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb, - const H264ParamSets *ps, void *logctx) +int ff_h264_sei_process_picture_timing(H264SEIPictureTiming *h, const SPS *sps, + void *logctx) { - int i; - const SPS *sps = ps->sps; + GetBitContext gb; - for (i = 0; ilog2_max_frame_num) && ps->sps_list[i]) - sps = (const SPS *)ps->sps_list[i]->data; - - if (!sps) { - av_log(logctx, AV_LOG_ERROR, "SPS unavailable in decode_picture_timing\n"); - return AVERROR_PS_NOT_FOUND; - } + init_get_bits(&gb, h->payload, h->payload_size_bits); if (sps->nal_hrd_parameters_present_flag || sps->vcl_hrd_parameters_present_flag) { - h->cpb_removal_delay = get_bits_long(gb, sps->cpb_removal_delay_length); - h->dpb_output_delay = get_bits_long(gb, sps->dpb_output_delay_length); + h->cpb_removal_delay = get_bits_long(&gb, sps->cpb_removal_delay_length); + h->dpb_output_delay = get_bits_long(&gb, sps->dpb_output_delay_length); } if (sps->pic_struct_present_flag) { unsigned int i, num_clock_ts; - h->pic_struct = get_bits(gb, 4); + h->pic_struct = get_bits(&gb, 4); h->ct_type = 0; if (h->pic_struct > H264_SEI_PIC_STRUCT_FRAME_TRIPLING) @@ -86,38 +83,38 @@ num_clock_ts = sei_num_clock_ts_table[h->pic_struct]; h->timecode_cnt = 0; for (i = 0; i < num_clock_ts; i++) { - if (get_bits(gb, 1)) { /* clock_timestamp_flag */ + if (get_bits(&gb, 1)) { /* clock_timestamp_flag */ H264SEITimeCode *tc = &h->timecode[h->timecode_cnt++]; unsigned int full_timestamp_flag; unsigned int counting_type, cnt_dropped_flag; - h->ct_type |= 1 << get_bits(gb, 2); - skip_bits(gb, 1); /* nuit_field_based_flag */ - counting_type = get_bits(gb, 5); /* counting_type */ - full_timestamp_flag = get_bits(gb, 1); - skip_bits(gb, 1); /* discontinuity_flag */ - cnt_dropped_flag = get_bits(gb, 1); /* cnt_dropped_flag */ + h->ct_type |= 1 << get_bits(&gb, 2); + skip_bits(&gb, 1); /* nuit_field_based_flag */ + counting_type = get_bits(&gb, 5); /* counting_type */ + full_timestamp_flag = get_bits(&gb, 1); + skip_bits(&gb, 1); /* discontinuity_flag */ + cnt_dropped_flag = get_bits(&gb, 1); /* cnt_dropped_flag */ if (cnt_dropped_flag && counting_type > 1 && counting_type < 7) tc->dropframe = 1; - tc->frame = get_bits(gb, 8); /* n_frames */ + tc->frame = get_bits(&gb, 8); /* n_frames */ if (full_timestamp_flag) { tc->full = 1; - tc->seconds = get_bits(gb, 6); /* seconds_value 0..59 */ - tc->minutes = get_bits(gb, 6); /* minutes_value 0..59 */ - tc->hours = get_bits(gb, 5); /* hours_value 0..23 */ + tc->seconds = get_bits(&gb, 6); /* seconds_value 0..59 */ + tc->minutes = get_bits(&gb, 6); /* minutes_value 0..59 */ + tc->hours = get_bits(&gb, 5); /* hours_value 0..23 */ } else { tc->seconds = tc->minutes = tc->hours = tc->full = 0; - if (get_bits(gb, 1)) { /* seconds_flag */ - tc->seconds = get_bits(gb, 6); - if (get_bits(gb, 1)) { /* minutes_flag */ - tc->minutes = get_bits(gb, 6); - if (get_bits(gb, 1)) /* hours_flag */ - tc->hours = get_bits(gb, 5); + if (get_bits(&gb, 1)) { /* seconds_flag */ + tc->seconds = get_bits(&gb, 6); + if (get_bits(&gb, 1)) { /* minutes_flag */ + tc->minutes = get_bits(&gb, 6); + if (get_bits(&gb, 1)) /* hours_flag */ + tc->hours = get_bits(&gb, 5); } } } if (sps->time_offset_length > 0) - skip_bits(gb, + skip_bits(&gb, sps->time_offset_length); /* time_offset */ } } @@ -126,6 +123,28 @@ h->ct_type, h->pic_struct); } + return 0; +} + +static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb, + void *logctx) +{ + int index = get_bits_count(gb); + int size_bits = get_bits_left(gb); + int size = (size_bits + 7) / 8; + + if (index & 7) { + av_log(logctx, AV_LOG_ERROR, "Unaligned SEI payload\n"); + return AVERROR_INVALIDDATA; + } + if (size > sizeof(h->payload)) { + av_log(logctx, AV_LOG_ERROR, "Picture timing SEI payload too large\n"); + return AVERROR_INVALIDDATA; + } + memcpy(h->payload, gb->buffer + index / 8, size); + + h->payload_size_bits = size_bits; + h->present = 1; return 0; } @@ -155,87 +174,68 @@ GetBitContext *gb, void *logctx, int size) { - int flag; - int user_data_type_code; - int cc_count; - if (size < 3) return AVERROR(EINVAL); - user_data_type_code = get_bits(gb, 8); - if (user_data_type_code == 0x3) { - skip_bits(gb, 1); // reserved - - flag = get_bits(gb, 1); // process_cc_data_flag - if (flag) { - skip_bits(gb, 1); // zero bit - cc_count = get_bits(gb, 5); - skip_bits(gb, 8); // reserved - size -= 2; - - if (cc_count && size >= cc_count * 3) { - int old_size = h->buf_ref ? h->buf_ref->size : 0; - const uint64_t new_size = (old_size + cc_count - * UINT64_C(3)); - int i, ret; - - if (new_size > INT_MAX) - return AVERROR(EINVAL); - - /* Allow merging of the cc data from two fields. */ - ret = av_buffer_realloc(&h->buf_ref, new_size); - if (ret < 0) - return ret; - - /* Use of av_buffer_realloc assumes buffer is writeable */ - for (i = 0; i < cc_count; i++) { - h->buf_ref->data[old_size++] = get_bits(gb, 8); - h->buf_ref->data[old_size++] = get_bits(gb, 8); - h->buf_ref->data[old_size++] = get_bits(gb, 8); - } - - skip_bits(gb, 8); // marker_bits - } - } - } else { - int i; - for (i = 0; i < size - 1; i++) - skip_bits(gb, 8); - } - - return 0; + return ff_parse_a53_cc(&h->buf_ref, gb->buffer + get_bits_count(gb) / 8, size); } static int decode_registered_user_data(H264SEIContext *h, GetBitContext *gb, void *logctx, int size) { - uint32_t country_code; - uint32_t user_identifier; + int country_code, provider_code; - if (size < 7) + if (size < 3) return AVERROR_INVALIDDATA; - size -= 7; + size -= 3; country_code = get_bits(gb, 8); // itu_t_t35_country_code if (country_code == 0xFF) { + if (size < 1) + return AVERROR_INVALIDDATA; + skip_bits(gb, 8); // itu_t_t35_country_code_extension_byte size--; } + if (country_code != 0xB5) { // usa_country_code + av_log(logctx, AV_LOG_VERBOSE, + "Unsupported User Data Registered ITU-T T35 SEI message (country_code = %d)\n", + country_code); + return 0; + } + /* itu_t_t35_payload_byte follows */ - skip_bits(gb, 8); // terminal provider code - skip_bits(gb, 8); // terminal provider oriented code - user_identifier = get_bits_long(gb, 32); + provider_code = get_bits(gb, 16); + + switch (provider_code) { + case 0x31: { // atsc_provider_code + uint32_t user_identifier; + + if (size < 4) + return AVERROR_INVALIDDATA; + size -= 4; - switch (user_identifier) { + user_identifier = get_bits_long(gb, 32); + switch (user_identifier) { case MKBETAG('D', 'T', 'G', '1'): // afd_data return decode_registered_user_data_afd(&h->afd, gb, size); case MKBETAG('G', 'A', '9', '4'): // closed captions return decode_registered_user_data_closed_caption(&h->a53_caption, gb, logctx, size); default: - skip_bits(gb, size * 8); + av_log(logctx, AV_LOG_VERBOSE, + "Unsupported User Data Registered ITU-T T35 SEI message (atsc user_identifier = 0x%04x)\n", + user_identifier); break; + } + break; + } + default: + av_log(logctx, AV_LOG_VERBOSE, + "Unsupported User Data Registered ITU-T T35 SEI message (provider_code = %d)\n", + provider_code); + break; } return 0; @@ -246,25 +246,34 @@ { uint8_t *user_data; int e, build, i; + AVBufferRef *buf_ref, **tmp; - if (size < 16 || size >= INT_MAX - 16) + if (size < 16 || size >= INT_MAX - 1) return AVERROR_INVALIDDATA; - user_data = av_malloc(16 + size + 1); - if (!user_data) + tmp = av_realloc_array(h->buf_ref, h->nb_buf_ref + 1, sizeof(*h->buf_ref)); + if (!tmp) + return AVERROR(ENOMEM); + h->buf_ref = tmp; + + buf_ref = av_buffer_alloc(size + 1); + if (!buf_ref) return AVERROR(ENOMEM); + user_data = buf_ref->data; - for (i = 0; i < size + 16; i++) + for (i = 0; i < size; i++) user_data[i] = get_bits(gb, 8); user_data[i] = 0; + buf_ref->size = size; + h->buf_ref[h->nb_buf_ref++] = buf_ref; + e = sscanf(user_data + 16, "x264 - core %d", &build); if (e == 1 && build > 0) h->x264_build = build; if (e == 1 && build == 1 && !strncmp(user_data+16, "x264 - core 0000", 16)) h->x264_build = 67; - av_free(user_data); return 0; } @@ -407,9 +416,9 @@ int master_ret = 0; while (get_bits_left(gb) > 16 && show_bits(gb, 16)) { + GetBitContext gb_payload; int type = 0; unsigned size = 0; - unsigned next; int ret = 0; do { @@ -429,35 +438,38 @@ type, 8*size, get_bits_left(gb)); return AVERROR_INVALIDDATA; } - next = get_bits_count(gb) + 8 * size; + + ret = init_get_bits8(&gb_payload, gb->buffer + get_bits_count(gb) / 8, size); + if (ret < 0) + return ret; switch (type) { - case H264_SEI_TYPE_PIC_TIMING: // Picture timing SEI - ret = decode_picture_timing(&h->picture_timing, gb, ps, logctx); + case SEI_TYPE_PIC_TIMING: // Picture timing SEI + ret = decode_picture_timing(&h->picture_timing, &gb_payload, logctx); break; - case H264_SEI_TYPE_USER_DATA_REGISTERED: - ret = decode_registered_user_data(h, gb, logctx, size); + case SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35: + ret = decode_registered_user_data(h, &gb_payload, logctx, size); break; - case H264_SEI_TYPE_USER_DATA_UNREGISTERED: - ret = decode_unregistered_user_data(&h->unregistered, gb, logctx, size); + case SEI_TYPE_USER_DATA_UNREGISTERED: + ret = decode_unregistered_user_data(&h->unregistered, &gb_payload, logctx, size); break; - case H264_SEI_TYPE_RECOVERY_POINT: - ret = decode_recovery_point(&h->recovery_point, gb, logctx); + case SEI_TYPE_RECOVERY_POINT: + ret = decode_recovery_point(&h->recovery_point, &gb_payload, logctx); break; - case H264_SEI_TYPE_BUFFERING_PERIOD: - ret = decode_buffering_period(&h->buffering_period, gb, ps, logctx); + case SEI_TYPE_BUFFERING_PERIOD: + ret = decode_buffering_period(&h->buffering_period, &gb_payload, ps, logctx); break; - case H264_SEI_TYPE_FRAME_PACKING: - ret = decode_frame_packing_arrangement(&h->frame_packing, gb); + case SEI_TYPE_FRAME_PACKING_ARRANGEMENT: + ret = decode_frame_packing_arrangement(&h->frame_packing, &gb_payload); break; - case H264_SEI_TYPE_DISPLAY_ORIENTATION: - ret = decode_display_orientation(&h->display_orientation, gb); + case SEI_TYPE_DISPLAY_ORIENTATION: + ret = decode_display_orientation(&h->display_orientation, &gb_payload); break; - case H264_SEI_TYPE_GREEN_METADATA: - ret = decode_green_metadata(&h->green_metadata, gb); + case SEI_TYPE_GREEN_METADATA: + ret = decode_green_metadata(&h->green_metadata, &gb_payload); break; - case H264_SEI_TYPE_ALTERNATIVE_TRANSFER: - ret = decode_alternative_transfer(&h->alternative_transfer, gb); + case SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS: + ret = decode_alternative_transfer(&h->alternative_transfer, &gb_payload); break; default: av_log(logctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type); @@ -467,10 +479,12 @@ if (ret < 0) master_ret = ret; - skip_bits_long(gb, next - get_bits_count(gb)); + if (get_bits_left(&gb_payload) < 0) { + av_log(logctx, AV_LOG_WARNING, "SEI type %d overread by %d bits\n", + type, -get_bits_left(&gb_payload)); + } - // FIXME check bits here - align_get_bits(gb); + skip_bits_long(gb, 8 * size); } return master_ret; diff -Nru ffmpeg-4.2.2/libavcodec/h264_sei.h ffmpeg-4.4/libavcodec/h264_sei.h --- ffmpeg-4.2.2/libavcodec/h264_sei.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_sei.h 2021-04-08 21:28:39.000000000 +0000 @@ -20,24 +20,9 @@ #define AVCODEC_H264_SEI_H #include "get_bits.h" +#include "h264_ps.h" +#include "sei.h" -/** - * SEI message types - */ -typedef enum { - H264_SEI_TYPE_BUFFERING_PERIOD = 0, ///< buffering period (H.264, D.1.1) - H264_SEI_TYPE_PIC_TIMING = 1, ///< picture timing - H264_SEI_TYPE_PAN_SCAN_RECT = 2, ///< pan-scan rectangle - H264_SEI_TYPE_FILLER_PAYLOAD = 3, ///< filler data - H264_SEI_TYPE_USER_DATA_REGISTERED = 4, ///< registered user data as specified by Rec. ITU-T T.35 - H264_SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data - H264_SEI_TYPE_RECOVERY_POINT = 6, ///< recovery point (frame # to decoder sync) - H264_SEI_TYPE_FRAME_PACKING = 45, ///< frame packing arrangement - H264_SEI_TYPE_DISPLAY_ORIENTATION = 47, ///< display orientation - H264_SEI_TYPE_GREEN_METADATA = 56, ///< GreenMPEG information - H264_SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME = 137, ///< mastering display properties - H264_SEI_TYPE_ALTERNATIVE_TRANSFER = 147, ///< alternative transfer -} H264_SEI_Type; /** * pic_struct in picture timing SEI message @@ -79,6 +64,10 @@ } H264SEITimeCode; typedef struct H264SEIPictureTiming { + // maximum size of pic_timing according to the spec should be 274 bits + uint8_t payload[40]; + int payload_size_bits; + int present; H264_SEI_PicStructType pic_struct; @@ -121,6 +110,8 @@ typedef struct H264SEIUnregistered { int x264_build; + AVBufferRef **buf_ref; + int nb_buf_ref; } H264SEIUnregistered; typedef struct H264SEIRecoveryPoint { @@ -202,4 +193,10 @@ */ const char *ff_h264_sei_stereo_mode(const H264SEIFramePacking *h); +/** + * Parse the contents of a picture timing message given an active SPS. + */ +int ff_h264_sei_process_picture_timing(H264SEIPictureTiming *h, const SPS *sps, + void *logctx); + #endif /* AVCODEC_H264_SEI_H */ diff -Nru ffmpeg-4.2.2/libavcodec/h264_slice.c ffmpeg-4.4/libavcodec/h264_slice.c --- ffmpeg-4.2.2/libavcodec/h264_slice.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h264_slice.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,7 +29,6 @@ #include "libavutil/display.h" #include "libavutil/imgutils.h" #include "libavutil/stereo3d.h" -#include "libavutil/timer.h" #include "internal.h" #include "cabac.h" #include "cabac_functions.h" @@ -244,6 +243,15 @@ pic->ref_index[i] = pic->ref_index_buf[i]->data; } + pic->pps_buf = av_buffer_ref(h->ps.pps_ref); + if (!pic->pps_buf) + goto fail; + pic->pps = (const PPS*)pic->pps_buf->data; + + pic->mb_width = h->mb_width; + pic->mb_height = h->mb_height; + pic->mb_stride = h->mb_stride; + return 0; fail: ff_h264_unref_picture(h, pic); @@ -296,9 +304,8 @@ if (dst == src) return 0; - // We can't fail if SPS isn't set at it breaks current skip_frame code - //if (!h1->ps.sps) - // return AVERROR_INVALIDDATA; + if (inited && !h1->ps.sps) + return AVERROR_INVALIDDATA; if (inited && (h->width != h1->width || @@ -317,37 +324,24 @@ // SPS/PPS for (i = 0; i < FF_ARRAY_ELEMS(h->ps.sps_list); i++) { - av_buffer_unref(&h->ps.sps_list[i]); - if (h1->ps.sps_list[i]) { - h->ps.sps_list[i] = av_buffer_ref(h1->ps.sps_list[i]); - if (!h->ps.sps_list[i]) - return AVERROR(ENOMEM); - } + ret = av_buffer_replace(&h->ps.sps_list[i], h1->ps.sps_list[i]); + if (ret < 0) + return ret; } for (i = 0; i < FF_ARRAY_ELEMS(h->ps.pps_list); i++) { - av_buffer_unref(&h->ps.pps_list[i]); - if (h1->ps.pps_list[i]) { - h->ps.pps_list[i] = av_buffer_ref(h1->ps.pps_list[i]); - if (!h->ps.pps_list[i]) - return AVERROR(ENOMEM); - } + ret = av_buffer_replace(&h->ps.pps_list[i], h1->ps.pps_list[i]); + if (ret < 0) + return ret; } - av_buffer_unref(&h->ps.pps_ref); - av_buffer_unref(&h->ps.sps_ref); + ret = av_buffer_replace(&h->ps.pps_ref, h1->ps.pps_ref); + if (ret < 0) + return ret; h->ps.pps = NULL; h->ps.sps = NULL; if (h1->ps.pps_ref) { - h->ps.pps_ref = av_buffer_ref(h1->ps.pps_ref); - if (!h->ps.pps_ref) - return AVERROR(ENOMEM); h->ps.pps = (const PPS*)h->ps.pps_ref->data; - } - if (h1->ps.sps_ref) { - h->ps.sps_ref = av_buffer_ref(h1->ps.sps_ref); - if (!h->ps.sps_ref) - return AVERROR(ENOMEM); - h->ps.sps = (const SPS*)h->ps.sps_ref->data; + h->ps.sps = h->ps.pps->sps; } if (need_reinit || !inited) { @@ -430,12 +424,29 @@ h->frame_recovered = h1->frame_recovered; - av_buffer_unref(&h->sei.a53_caption.buf_ref); - if (h1->sei.a53_caption.buf_ref) { - h->sei.a53_caption.buf_ref = av_buffer_ref(h1->sei.a53_caption.buf_ref); - if (!h->sei.a53_caption.buf_ref) - return AVERROR(ENOMEM); + ret = av_buffer_replace(&h->sei.a53_caption.buf_ref, h1->sei.a53_caption.buf_ref); + if (ret < 0) + return ret; + + for (i = 0; i < h->sei.unregistered.nb_buf_ref; i++) + av_buffer_unref(&h->sei.unregistered.buf_ref[i]); + h->sei.unregistered.nb_buf_ref = 0; + + if (h1->sei.unregistered.nb_buf_ref) { + ret = av_reallocp_array(&h->sei.unregistered.buf_ref, + h1->sei.unregistered.nb_buf_ref, + sizeof(*h->sei.unregistered.buf_ref)); + if (ret < 0) + return ret; + + for (i = 0; i < h1->sei.unregistered.nb_buf_ref; i++) { + h->sei.unregistered.buf_ref[i] = av_buffer_ref(h1->sei.unregistered.buf_ref[i]); + if (!h->sei.unregistered.buf_ref[i]) + return AVERROR(ENOMEM); + h->sei.unregistered.nb_buf_ref++; + } } + h->sei.unregistered.x264_build = h1->sei.unregistered.x264_build; if (!h->cur_pic_ptr) return 0; @@ -458,12 +469,6 @@ H264Picture *pic; int i, ret; const int pixel_shift = h->pixel_shift; - int c[4] = { - 1<<(h->ps.sps->bit_depth_luma-1), - 1<<(h->ps.sps->bit_depth_chroma-1), - 1<<(h->ps.sps->bit_depth_chroma-1), - -1 - }; if (!ff_thread_can_start_frame(h->avctx)) { av_log(h->avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n"); @@ -504,8 +509,6 @@ if ((ret = alloc_picture(h, pic)) < 0) return ret; - if(!h->frame_recovered && !h->avctx->hwaccel) - ff_color_frame(pic->f, c); h->cur_pic_ptr = pic; ff_h264_unref_picture(h, &h->cur_pic); @@ -873,7 +876,7 @@ } /* export coded and cropped frame dimensions to AVCodecContext */ -static int init_dimensions(H264Context *h) +static void init_dimensions(H264Context *h) { const SPS *sps = (const SPS*)h->ps.sps; int cr = sps->crop_right; @@ -911,8 +914,6 @@ h->crop_left = cl; h->crop_top = ct; h->crop_bottom = cb; - - return 0; } static int h264_slice_header_init(H264Context *h) @@ -920,6 +921,11 @@ const SPS *sps = h->ps.sps; int i, ret; + if (!sps) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + ff_set_sar(h->avctx, sps->sar); av_pix_fmt_get_chroma_sub_sample(h->avctx->pix_fmt, &h->chroma_x_shift, &h->chroma_y_shift); @@ -1024,13 +1030,8 @@ h->ps.pps = (const PPS*)h->ps.pps_ref->data; } - if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { - av_buffer_unref(&h->ps.sps_ref); - h->ps.sps = NULL; - h->ps.sps_ref = av_buffer_ref(h->ps.sps_list[h->ps.pps->sps_id]); - if (!h->ps.sps_ref) - return AVERROR(ENOMEM); - h->ps.sps = (const SPS*)h->ps.sps_ref->data; + if (h->ps.sps != h->ps.pps->sps) { + h->ps.sps = (const SPS*)h->ps.pps->sps; if (h->mb_width != h->ps.sps->mb_width || h->mb_height != h->ps.sps->mb_height || @@ -1077,9 +1078,7 @@ h->width = 16 * h->mb_width; h->height = 16 * h->mb_height; - ret = init_dimensions(h); - if (ret < 0) - return ret; + init_dimensions(h); if (sps->video_signal_type_present_flag) { h->avctx->color_range = sps->full_range > 0 ? AVCOL_RANGE_JPEG @@ -1099,6 +1098,7 @@ h->avctx->color_trc = h->sei.alternative_transfer.preferred_transfer_characteristics; } } + h->avctx->chroma_sample_location = sps->chroma_location; if (!h->context_initialized || must_reinit || needs_reinit) { int flush_changes = h->context_initialized; @@ -1139,13 +1139,24 @@ { const SPS *sps = h->ps.sps; H264Picture *cur = h->cur_pic_ptr; + AVFrame *out = cur->f; - cur->f->interlaced_frame = 0; - cur->f->repeat_pict = 0; + out->interlaced_frame = 0; + out->repeat_pict = 0; /* Signal interlacing information externally. */ /* Prioritize picture timing SEI information over used * decoding process if it exists. */ + if (h->sei.picture_timing.present) { + int ret = ff_h264_sei_process_picture_timing(&h->sei.picture_timing, sps, + h->avctx); + if (ret < 0) { + av_log(h->avctx, AV_LOG_ERROR, "Error processing a picture timing SEI\n"); + if (h->avctx->err_recognition & AV_EF_EXPLODE) + return ret; + h->sei.picture_timing.present = 0; + } + } if (sps->pic_struct_present_flag && h->sei.picture_timing.present) { H264SEIPictureTiming *pt = &h->sei.picture_timing; @@ -1154,59 +1165,59 @@ break; case H264_SEI_PIC_STRUCT_TOP_FIELD: case H264_SEI_PIC_STRUCT_BOTTOM_FIELD: - cur->f->interlaced_frame = 1; + out->interlaced_frame = 1; break; case H264_SEI_PIC_STRUCT_TOP_BOTTOM: case H264_SEI_PIC_STRUCT_BOTTOM_TOP: if (FIELD_OR_MBAFF_PICTURE(h)) - cur->f->interlaced_frame = 1; + out->interlaced_frame = 1; else // try to flag soft telecine progressive - cur->f->interlaced_frame = h->prev_interlaced_frame; + out->interlaced_frame = h->prev_interlaced_frame; break; case H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: case H264_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: /* Signal the possibility of telecined film externally * (pic_struct 5,6). From these hints, let the applications * decide if they apply deinterlacing. */ - cur->f->repeat_pict = 1; + out->repeat_pict = 1; break; case H264_SEI_PIC_STRUCT_FRAME_DOUBLING: - cur->f->repeat_pict = 2; + out->repeat_pict = 2; break; case H264_SEI_PIC_STRUCT_FRAME_TRIPLING: - cur->f->repeat_pict = 4; + out->repeat_pict = 4; break; } if ((pt->ct_type & 3) && pt->pic_struct <= H264_SEI_PIC_STRUCT_BOTTOM_TOP) - cur->f->interlaced_frame = (pt->ct_type & (1 << 1)) != 0; + out->interlaced_frame = (pt->ct_type & (1 << 1)) != 0; } else { /* Derive interlacing flag from used decoding process. */ - cur->f->interlaced_frame = FIELD_OR_MBAFF_PICTURE(h); + out->interlaced_frame = FIELD_OR_MBAFF_PICTURE(h); } - h->prev_interlaced_frame = cur->f->interlaced_frame; + h->prev_interlaced_frame = out->interlaced_frame; if (cur->field_poc[0] != cur->field_poc[1]) { /* Derive top_field_first from field pocs. */ - cur->f->top_field_first = cur->field_poc[0] < cur->field_poc[1]; + out->top_field_first = cur->field_poc[0] < cur->field_poc[1]; } else { if (sps->pic_struct_present_flag && h->sei.picture_timing.present) { /* Use picture timing SEI information. Even if it is a * information of a past frame, better than nothing. */ if (h->sei.picture_timing.pic_struct == H264_SEI_PIC_STRUCT_TOP_BOTTOM || h->sei.picture_timing.pic_struct == H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP) - cur->f->top_field_first = 1; + out->top_field_first = 1; else - cur->f->top_field_first = 0; - } else if (cur->f->interlaced_frame) { + out->top_field_first = 0; + } else if (out->interlaced_frame) { /* Default to top field first when pic_struct_present_flag * is not set but interlaced frame detected */ - cur->f->top_field_first = 1; + out->top_field_first = 1; } else { /* Most likely progressive */ - cur->f->top_field_first = 0; + out->top_field_first = 0; } } @@ -1215,7 +1226,7 @@ h->sei.frame_packing.content_interpretation_type > 0 && h->sei.frame_packing.content_interpretation_type < 3) { H264SEIFramePacking *fp = &h->sei.frame_packing; - AVStereo3D *stereo = av_stereo3d_create_side_data(cur->f); + AVStereo3D *stereo = av_stereo3d_create_side_data(out); if (stereo) { switch (fp->arrangement_type) { case H264_SEI_FPA_TYPE_CHECKERBOARD: @@ -1262,7 +1273,7 @@ h->sei.display_orientation.vflip)) { H264SEIDisplayOrientation *o = &h->sei.display_orientation; double angle = o->anticlockwise_rotation * 360 / (double) (1 << 16); - AVFrameSideData *rotation = av_frame_new_side_data(cur->f, + AVFrameSideData *rotation = av_frame_new_side_data(out, AV_FRAME_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9); if (rotation) { @@ -1273,7 +1284,7 @@ } if (h->sei.afd.present) { - AVFrameSideData *sd = av_frame_new_side_data(cur->f, AV_FRAME_DATA_AFD, + AVFrameSideData *sd = av_frame_new_side_data(out, AV_FRAME_DATA_AFD, sizeof(uint8_t)); if (sd) { @@ -1285,7 +1296,7 @@ if (h->sei.a53_caption.buf_ref) { H264SEIA53Caption *a53 = &h->sei.a53_caption; - AVFrameSideData *sd = av_frame_new_side_data_from_buf(cur->f, AV_FRAME_DATA_A53_CC, a53->buf_ref); + AVFrameSideData *sd = av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_A53_CC, a53->buf_ref); if (!sd) av_buffer_unref(&a53->buf_ref); a53->buf_ref = NULL; @@ -1293,11 +1304,25 @@ h->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; } + for (int i = 0; i < h->sei.unregistered.nb_buf_ref; i++) { + H264SEIUnregistered *unreg = &h->sei.unregistered; + + if (unreg->buf_ref[i]) { + AVFrameSideData *sd = av_frame_new_side_data_from_buf(out, + AV_FRAME_DATA_SEI_UNREGISTERED, + unreg->buf_ref[i]); + if (!sd) + av_buffer_unref(&unreg->buf_ref[i]); + unreg->buf_ref[i] = NULL; + } + } + h->sei.unregistered.nb_buf_ref = 0; + if (h->sei.picture_timing.timecode_cnt > 0) { - uint32_t tc = 0; uint32_t *tc_sd; + char tcbuf[AV_TIMECODE_STR_SIZE]; - AVFrameSideData *tcside = av_frame_new_side_data(cur->f, + AVFrameSideData *tcside = av_frame_new_side_data(out, AV_FRAME_DATA_S12M_TIMECODE, sizeof(uint32_t)*4); if (!tcside) @@ -1307,33 +1332,15 @@ tc_sd[0] = h->sei.picture_timing.timecode_cnt; for (int i = 0; i < tc_sd[0]; i++) { - uint32_t frames; - - /* For SMPTE 12-M timecodes, frame count is a special case if > 30 FPS. - See SMPTE ST 12-1:2014 Sec 12.1 for more info. */ - if (av_cmp_q(h->avctx->framerate, (AVRational) {30, 1}) == 1) { - frames = h->sei.picture_timing.timecode[i].frame / 2; - if (h->sei.picture_timing.timecode[i].frame % 2 == 1) { - if (av_cmp_q(h->avctx->framerate, (AVRational) {50, 1}) == 0) - tc |= (1 << 7); - else - tc |= (1 << 23); - } - } else { - frames = h->sei.picture_timing.timecode[i].frame; - } - - tc |= h->sei.picture_timing.timecode[i].dropframe << 30; - tc |= (frames / 10) << 28; - tc |= (frames % 10) << 24; - tc |= (h->sei.picture_timing.timecode[i].seconds / 10) << 20; - tc |= (h->sei.picture_timing.timecode[i].seconds % 10) << 16; - tc |= (h->sei.picture_timing.timecode[i].minutes / 10) << 12; - tc |= (h->sei.picture_timing.timecode[i].minutes % 10) << 8; - tc |= (h->sei.picture_timing.timecode[i].hours / 10) << 4; - tc |= (h->sei.picture_timing.timecode[i].hours % 10); - - tc_sd[i + 1] = tc; + int drop = h->sei.picture_timing.timecode[i].dropframe; + int hh = h->sei.picture_timing.timecode[i].hours; + int mm = h->sei.picture_timing.timecode[i].minutes; + int ss = h->sei.picture_timing.timecode[i].seconds; + int ff = h->sei.picture_timing.timecode[i].frame; + + tc_sd[i + 1] = av_timecode_get_smpte(h->avctx->framerate, drop, hh, mm, ss, ff); + av_timecode_make_smpte_tc_string2(tcbuf, h->avctx->framerate, tc_sd[i + 1], 0, 0); + av_dict_set(&out->metadata, "timecode", tcbuf, 0); } h->sei.picture_timing.timecode_cnt = 0; } @@ -1582,6 +1589,13 @@ * vectors. Given we are concealing a lost frame, this probably * is not noticeable by comparison, but it should be fixed. */ if (h->short_ref_count) { + int c[4] = { + 1<<(h->ps.sps->bit_depth_luma-1), + 1<<(h->ps.sps->bit_depth_chroma-1), + 1<<(h->ps.sps->bit_depth_chroma-1), + -1 + }; + if (prev && h->short_ref[0]->f->width == prev->f->width && h->short_ref[0]->f->height == prev->f->height && @@ -1589,15 +1603,17 @@ ff_thread_await_progress(&prev->tf, INT_MAX, 0); if (prev->field_picture) ff_thread_await_progress(&prev->tf, INT_MAX, 1); - av_image_copy(h->short_ref[0]->f->data, - h->short_ref[0]->f->linesize, - (const uint8_t **)prev->f->data, - prev->f->linesize, - prev->f->format, - prev->f->width, - prev->f->height); - h->short_ref[0]->poc = prev->poc + 2; - } + ff_thread_release_buffer(h->avctx, &h->short_ref[0]->tf); + h->short_ref[0]->tf.f = h->short_ref[0]->f; + ret = ff_thread_ref_frame(&h->short_ref[0]->tf, &prev->tf); + if (ret < 0) + return ret; + h->short_ref[0]->poc = prev->poc + 2U; + ff_thread_report_progress(&h->short_ref[0]->tf, INT_MAX, 0); + if (h->short_ref[0]->field_picture) + ff_thread_report_progress(&h->short_ref[0]->tf, INT_MAX, 1); + } else if (!h->frame_recovered && !h->avctx->hwaccel) + ff_color_frame(h->short_ref[0]->f, c); h->short_ref[0]->frame_num = h->poc.prev_frame_num; } } @@ -1773,13 +1789,7 @@ return AVERROR_INVALIDDATA; } pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data; - - if (!h->ps.sps_list[pps->sps_id]) { - av_log(h->avctx, AV_LOG_ERROR, - "non-existing SPS %u referenced\n", pps->sps_id); - return AVERROR_INVALIDDATA; - } - sps = (const SPS*)h->ps.sps_list[pps->sps_id]->data; + sps = pps->sps; sl->frame_num = get_bits(&sl->gb, sps->log2_max_frame_num); if (!first_slice) { @@ -2165,7 +2175,7 @@ av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n"); return AVERROR_INVALIDDATA; } - if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) { + if (h->ps.sps != pps->sps) { av_log(h->avctx, AV_LOG_ERROR, "SPS changed in the middle of the frame\n"); return AVERROR_INVALIDDATA; @@ -2621,7 +2631,6 @@ ff_h264_init_cabac_states(h, sl); for (;;) { - // START_TIMER int ret, eos; if (sl->mb_x + sl->mb_y * h->mb_width >= sl->next_slice_idx) { av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps with next at %d\n", @@ -2632,7 +2641,6 @@ } ret = ff_h264_decode_mb_cabac(h, sl); - // STOP_TIMER("decode_mb_cabac") if (ret >= 0) ff_h264_hl_decode_mb(h, sl); diff -Nru ffmpeg-4.2.2/libavcodec/h265_metadata_bsf.c ffmpeg-4.4/libavcodec/h265_metadata_bsf.c --- ffmpeg-4.2.2/libavcodec/h265_metadata_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h265_metadata_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,26 +21,18 @@ #include "bsf.h" #include "cbs.h" +#include "cbs_bsf.h" #include "cbs_h265.h" #include "hevc.h" #include "h265_profile_level.h" enum { - PASS, - INSERT, - REMOVE, -}; - -enum { LEVEL_UNSET = -2, LEVEL_AUTO = -1, }; typedef struct H265MetadataContext { - const AVClass *class; - - CodedBitstreamContext *cbc; - CodedBitstreamFragment access_unit; + CBSBSFContext common; H265RawAUD aud_nal; @@ -131,7 +123,7 @@ } desc = ff_h265_guess_level(ptl, bit_rate, width, height, - 0, tile_cols, tile_rows, + 0, tile_rows, tile_cols, max_dec_pic_buffering); if (desc) { av_log(bsf, AV_LOG_DEBUG, "Stream appears to conform to " @@ -336,34 +328,18 @@ return 0; } -static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *pkt) +static int h265_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt, + CodedBitstreamFragment *au) { H265MetadataContext *ctx = bsf->priv_data; - CodedBitstreamFragment *au = &ctx->access_unit; int err, i; - err = ff_bsf_get_packet_ref(bsf, pkt); - if (err < 0) - return err; - - err = ff_cbs_read_packet(ctx->cbc, au, pkt); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); - goto fail; - } - - if (au->nb_units == 0) { - av_log(bsf, AV_LOG_ERROR, "No NAL units in packet.\n"); - err = AVERROR_INVALIDDATA; - goto fail; - } - // If an AUD is present, it must be the first NAL unit. - if (au->units[0].type == HEVC_NAL_AUD) { - if (ctx->aud == REMOVE) - ff_cbs_delete_unit(ctx->cbc, au, 0); + if (au->nb_units && au->units[0].type == HEVC_NAL_AUD) { + if (ctx->aud == BSF_ELEMENT_REMOVE) + ff_cbs_delete_unit(au, 0); } else { - if (ctx->aud == INSERT) { + if (pkt && ctx->aud == BSF_ELEMENT_INSERT) { H265RawAUD *aud = &ctx->aud_nal; int pic_type = 0, temporal_id = 8, layer_id = 0; @@ -393,11 +369,10 @@ }; aud->pic_type = pic_type; - err = ff_cbs_insert_unit_content(ctx->cbc, au, - 0, HEVC_NAL_AUD, aud, NULL); + err = ff_cbs_insert_unit_content(au, 0, HEVC_NAL_AUD, aud, NULL); if (err < 0) { av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n"); - goto fail; + return err; } } } @@ -409,97 +384,35 @@ if (au->units[i].type == HEVC_NAL_VPS) { err = h265_metadata_update_vps(bsf, au->units[i].content); if (err < 0) - goto fail; + return err; } if (au->units[i].type == HEVC_NAL_SPS) { err = h265_metadata_update_sps(bsf, au->units[i].content); if (err < 0) - goto fail; + return err; } } - err = ff_cbs_write_packet(ctx->cbc, pkt, au); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); - goto fail; - } - - err = 0; -fail: - ff_cbs_fragment_reset(ctx->cbc, au); - - if (err < 0) - av_packet_unref(pkt); - - return err; + return 0; } -static int h265_metadata_init(AVBSFContext *bsf) -{ - H265MetadataContext *ctx = bsf->priv_data; - CodedBitstreamFragment *au = &ctx->access_unit; - int err, i; - - err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_HEVC, bsf); - if (err < 0) - return err; - - if (bsf->par_in->extradata) { - err = ff_cbs_read_extradata(ctx->cbc, au, bsf->par_in); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); - goto fail; - } - - if (ctx->level == LEVEL_AUTO) - h265_metadata_guess_level(bsf, au); - - for (i = 0; i < au->nb_units; i++) { - if (au->units[i].type == HEVC_NAL_VPS) { - err = h265_metadata_update_vps(bsf, au->units[i].content); - if (err < 0) - goto fail; - } - if (au->units[i].type == HEVC_NAL_SPS) { - err = h265_metadata_update_sps(bsf, au->units[i].content); - if (err < 0) - goto fail; - } - } - - err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, au); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); - goto fail; - } - } - - err = 0; -fail: - ff_cbs_fragment_reset(ctx->cbc, au); - return err; -} +static const CBSBSFType h265_metadata_type = { + .codec_id = AV_CODEC_ID_HEVC, + .fragment_name = "access unit", + .unit_name = "NAL unit", + .update_fragment = &h265_metadata_update_fragment, +}; -static void h265_metadata_close(AVBSFContext *bsf) +static int h265_metadata_init(AVBSFContext *bsf) { - H265MetadataContext *ctx = bsf->priv_data; - - ff_cbs_fragment_free(ctx->cbc, &ctx->access_unit); - ff_cbs_close(&ctx->cbc); + return ff_cbs_bsf_generic_init(bsf, &h265_metadata_type); } #define OFFSET(x) offsetof(H265MetadataContext, x) #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) static const AVOption h265_metadata_options[] = { - { "aud", "Access Unit Delimiter NAL units", - OFFSET(aud), AV_OPT_TYPE_INT, - { .i64 = PASS }, PASS, REMOVE, FLAGS, "aud" }, - { "pass", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = PASS }, .flags = FLAGS, .unit = "aud" }, - { "insert", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = INSERT }, .flags = FLAGS, .unit = "aud" }, - { "remove", NULL, 0, AV_OPT_TYPE_CONST, - { .i64 = REMOVE }, .flags = FLAGS, .unit = "aud" }, + BSF_ELEMENT_OPTIONS_PIR("aud", "Access Unit Delimiter NAL units", + aud, FLAGS), { "sample_aspect_ratio", "Set sample aspect ratio (table E-1)", OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, @@ -590,7 +503,7 @@ .priv_data_size = sizeof(H265MetadataContext), .priv_class = &h265_metadata_class, .init = &h265_metadata_init, - .close = &h265_metadata_close, - .filter = &h265_metadata_filter, + .close = &ff_cbs_bsf_generic_close, + .filter = &ff_cbs_bsf_generic_filter, .codec_ids = h265_metadata_codec_ids, }; diff -Nru ffmpeg-4.2.2/libavcodec/h265_profile_level.c ffmpeg-4.4/libavcodec/h265_profile_level.c --- ffmpeg-4.2.2/libavcodec/h265_profile_level.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h265_profile_level.c 2021-04-08 21:28:39.000000000 +0000 @@ -120,18 +120,6 @@ }; -const H265LevelDescriptor *ff_h265_get_level(int level_idc) -{ - int i; - - for (i = 0; i < FF_ARRAY_ELEMS(h265_levels); i++) { - if (h265_levels[i].level_idc == level_idc) - return &h265_levels[i]; - } - - return NULL; -} - const H265ProfileDescriptor *ff_h265_get_profile(const H265RawProfileTierLevel *ptl) { int i; @@ -188,7 +176,7 @@ profile = NULL; if (!profile) { // Default to using multiplication factors for Main profile. - profile = &h265_profiles[3]; + profile = &h265_profiles[4]; } pic_size = width * height; diff -Nru ffmpeg-4.2.2/libavcodec/h265_profile_level.h ffmpeg-4.4/libavcodec/h265_profile_level.h --- ffmpeg-4.2.2/libavcodec/h265_profile_level.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/h265_profile_level.h 2021-04-08 21:28:39.000000000 +0000 @@ -70,8 +70,6 @@ } H265ProfileDescriptor; -const H265LevelDescriptor *ff_h265_get_level(int level_idc); - const H265ProfileDescriptor *ff_h265_get_profile(const H265RawProfileTierLevel *ptl); diff -Nru ffmpeg-4.2.2/libavcodec/half2float.h ffmpeg-4.4/libavcodec/half2float.h --- ffmpeg-4.2.2/libavcodec/half2float.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/half2float.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,74 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HALF2FLOAT_H +#define AVCODEC_HALF2FLOAT_H + +#include + +static uint32_t convertmantissa(uint32_t i) +{ + int32_t m = i << 13; // Zero pad mantissa bits + int32_t e = 0; // Zero exponent + + while (!(m & 0x00800000)) { // While not normalized + e -= 0x00800000; // Decrement exponent (1<<23) + m <<= 1; // Shift mantissa + } + + m &= ~0x00800000; // Clear leading 1 bit + e += 0x38800000; // Adjust bias ((127-14)<<23) + + return m | e; // Return combined number +} + +static void half2float_table(uint32_t *mantissatable, uint32_t *exponenttable, + uint16_t *offsettable) +{ + mantissatable[0] = 0; + for (int i = 1; i < 1024; i++) + mantissatable[i] = convertmantissa(i); + for (int i = 1024; i < 2048; i++) + mantissatable[i] = 0x38000000UL + ((i - 1024) << 13UL); + + exponenttable[0] = 0; + for (int i = 1; i < 31; i++) + exponenttable[i] = i << 23; + for (int i = 33; i < 63; i++) + exponenttable[i] = 0x80000000UL + ((i - 32) << 23UL); + exponenttable[31]= 0x47800000UL; + exponenttable[32]= 0x80000000UL; + exponenttable[63]= 0xC7800000UL; + + offsettable[0] = 0; + for (int i = 1; i < 64; i++) + offsettable[i] = 1024; + offsettable[32] = 0; +} + +static uint32_t half2float(uint16_t h, uint32_t *mantissatable, uint32_t *exponenttable, + uint16_t *offsettable) +{ + uint32_t f; + + f = mantissatable[offsettable[h >> 10] + (h & 0x3ff)] + exponenttable[h >> 10]; + + return f; +} + +#endif /* AVCODEC_HALF2FLOAT_H */ diff -Nru ffmpeg-4.2.2/libavcodec/hapdec.c ffmpeg-4.4/libavcodec/hapdec.c --- ffmpeg-4.2.2/libavcodec/hapdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hapdec.c 2021-02-20 20:27:47.000000000 +0000 @@ -105,6 +105,8 @@ size_t running_size = 0; for (i = 0; i < ctx->chunk_count; i++) { ctx->chunks[i].compressed_offset = running_size; + if (ctx->chunks[i].compressed_size > UINT32_MAX - running_size) + return AVERROR_INVALIDDATA; running_size += ctx->chunks[i].compressed_size; } } @@ -186,7 +188,7 @@ HapChunk *chunk = &ctx->chunks[i]; /* Check the compressed buffer is valid */ - if (chunk->compressed_offset + chunk->compressed_size > bytestream2_get_bytes_left(gbc)) + if (chunk->compressed_offset + (uint64_t)chunk->compressed_size > bytestream2_get_bytes_left(gbc)) return AVERROR_INVALIDDATA; /* Chunks are unpacked sequentially, ctx->tex_size is the uncompressed @@ -305,7 +307,6 @@ HapContext *ctx = avctx->priv_data; ThreadFrame tframe; int ret, i, t; - int tex_size; int section_size; enum HapSectionType section_type; int start_texture_section = 0; @@ -342,6 +343,13 @@ if (ret < 0) return ret; + if (ctx->tex_size != (avctx->coded_width / TEXTURE_BLOCK_W) + *(avctx->coded_height / TEXTURE_BLOCK_H) + *tex_rat[t]) { + av_log(avctx, AV_LOG_ERROR, "uncompressed size mismatches\n"); + return AVERROR_INVALIDDATA; + } + start_texture_section += ctx->texture_section_size + 4; if (avctx->codec->update_thread_context) @@ -349,9 +357,16 @@ /* Unpack the DXT texture */ if (hap_can_use_tex_in_place(ctx)) { + int tex_size; /* Only DXTC texture compression in a contiguous block */ ctx->tex_data = ctx->gbc.buffer; tex_size = FFMIN(ctx->texture_section_size, bytestream2_get_bytes_left(&ctx->gbc)); + if (tex_size < (avctx->coded_width / TEXTURE_BLOCK_W) + *(avctx->coded_height / TEXTURE_BLOCK_H) + *tex_rat[t]) { + av_log(avctx, AV_LOG_ERROR, "Insufficient data\n"); + return AVERROR_INVALIDDATA; + } } else { /* Perform the second-stage decompression */ ret = av_reallocp(&ctx->tex_buf, ctx->tex_size); @@ -367,14 +382,6 @@ } ctx->tex_data = ctx->tex_buf; - tex_size = ctx->tex_size; - } - - if (tex_size < (avctx->coded_width / TEXTURE_BLOCK_W) - *(avctx->coded_height / TEXTURE_BLOCK_H) - *tex_rat[t]) { - av_log(avctx, AV_LOG_ERROR, "Insufficient data\n"); - return AVERROR_INVALIDDATA; } /* Use the decompress function on the texture, one block per thread */ @@ -484,4 +491,12 @@ AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .codec_tags = (const uint32_t []){ + MKTAG('H','a','p','1'), + MKTAG('H','a','p','5'), + MKTAG('H','a','p','Y'), + MKTAG('H','a','p','A'), + MKTAG('H','a','p','M'), + FF_CODEC_TAGS_END, + }, }; diff -Nru ffmpeg-4.2.2/libavcodec/hap.h ffmpeg-4.4/libavcodec/hap.h --- ffmpeg-4.2.2/libavcodec/hap.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hap.h 2021-02-20 20:27:47.000000000 +0000 @@ -52,7 +52,7 @@ typedef struct HapChunk { enum HapCompressor compressor; - int compressed_offset; + uint32_t compressed_offset; size_t compressed_size; int uncompressed_offset; size_t uncompressed_size; diff -Nru ffmpeg-4.2.2/libavcodec/hapqa_extract_bsf.c ffmpeg-4.4/libavcodec/hapqa_extract_bsf.c --- ffmpeg-4.2.2/libavcodec/hapqa_extract_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hapqa_extract_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -25,8 +25,8 @@ * extract one of the two textures of the HAQA */ -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "bytestream.h" #include "hap.h" diff -Nru ffmpeg-4.2.2/libavcodec/hca_data.h ffmpeg-4.4/libavcodec/hca_data.h --- ffmpeg-4.2.2/libavcodec/hca_data.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hca_data.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,176 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_HCA_DATA_H +#define AVCODEC_HCA_DATA_H + +#include + +static const uint8_t max_bits_table[] = { + 0, 2, 3, 3, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, +}; + +static const uint8_t quant_spectrum_bits[] = +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,3,3,0,0,0,0,0,0,0,0, + 2,2,3,3,3,3,3,3,0,0,0,0,0,0,0,0, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4, + 3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4, + 3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4, + 3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +}; + +static const int8_t quant_spectrum_value[] = +{ + +0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, + +0,+0,+1,-1,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0,+0, + +0,+0,+1,+1,-1,-1,+2,-2,+0,+0,+0,+0,+0,+0,+0,+0, + +0,+0,+1,-1,+2,-2,+3,-3,+0,+0,+0,+0,+0,+0,+0,+0, + +0,+0,+1,+1,-1,-1,+2,+2,-2,-2,+3,+3,-3,-3,+4,-4, + +0,+0,+1,+1,-1,-1,+2,+2,-2,-2,+3,-3,+4,-4,+5,-5, + +0,+0,+1,+1,-1,-1,+2,-2,+3,-3,+4,-4,+5,-5,+6,-6, + +0,+0,+1,-1,+2,-2,+3,-3,+4,-4,+5,-5,+6,-6,+7,-7, +}; + +static const uint8_t scale_table[] = +{ + 15, 14, 14, 14, 14, 14, 14, 13, 13, + 13, 13, 13, 13, 12, 12, 12, 12, + 12, 12, 11, 11, 11, 11, 11, 11, + 10, 10, 10, 10, 10, 10, 10, 9, + 9, 9, 9, 9, 9, 8, 8, 8, + 8, 8, 8, 7, 6, 6, 5, 4, + 4, 4, 3, 3, 3, 2, 2, 2, + 2, 1, +}; + +static const float window[128] = +{ + 0.000690534, 0.00197623, 0.00367386, 0.00572424, 0.0080967, 0.0107732, 0.0137425, 0.0169979, + 0.0205353, 0.0243529, 0.0284505, 0.0328291, 0.0374906, 0.0424379, 0.0476744, 0.0532043, + 0.0590321, 0.0651629, 0.071602, 0.0783552, 0.0854285, 0.092828, 0.10056, 0.108631, + 0.117048, 0.125817, 0.134944, 0.144437, 0.1543, 0.164539, 0.175161, 0.186169, + 0.197569, 0.209363, 0.221555, 0.234145, 0.247136, 0.260526, 0.274313, 0.288493, + 0.303062, 0.318012, 0.333333, 0.349015, 0.365044, 0.381403, 0.398073, 0.415034, + 0.43226, 0.449725, 0.4674, 0.485251, 0.503245, 0.521344, 0.539509, 0.557698, + 0.575869, 0.593978, 0.611981, 0.629831, 0.647486, 0.6649, 0.682031, 0.698838, + 0.71528, 0.731323, 0.746932, 0.762077, 0.776732, 0.790873, 0.804481, 0.817542, + 0.830044, 0.84198, 0.853347, 0.864144, 0.874375, 0.884046, 0.893167, 0.901749, + 0.909806, 0.917354, 0.924409, 0.93099, 0.937117, 0.942809, 0.948087, 0.952971, + 0.957482, 0.961641, 0.965467, 0.968981, 0.972202, 0.975148, 0.977838, 0.980289, + 0.982518, 0.98454, 0.986371, 0.988024, 0.989514, 0.990853, 0.992053, 0.993126, + 0.994082, 0.994931, 0.995682, 0.996344, 0.996926, 0.997433, 0.997875, 0.998256, + 0.998584, 0.998863, 0.999099, 0.999297, 0.999461, 0.999595, 0.999703, 0.999789, + 0.999856, 0.999906, 0.999942, 0.999967, 0.999984, 0.999993, 0.999998, 1.0, +}; + +static const float intensity_ratio_table[] = +{ + 2.0, 1.85714, 1.71429, 1.57143, 1.42857, 1.28571, 1.14286, 1.0, + 0.857143, 0.714286, 0.571429, 0.428571, 0.285714, 0.142857, 0.0, 0.0, +}; + +static const float scale_conversion_table[] = +{ + 0, 0, 1.87066e-08, 2.49253e-08, 3.32113e-08, 4.42518e-08, 5.89626e-08, 7.85637e-08, 1.04681e-07, + 1.3948e-07, 1.85848e-07, 2.4763e-07, 3.2995e-07, 4.39636e-07, 5.85785e-07, 7.80519e-07, 1.03999e-06, + 1.38572e-06, 1.84637e-06, 2.46017e-06, 3.27801e-06, 4.36772e-06, 5.8197e-06, 7.75435e-06, 1.03321e-05, + 1.37669e-05, 1.83435e-05, 2.44414e-05, 3.25665e-05, 4.33927e-05, 5.78179e-05, 7.70384e-05, 0.000102648, + 0.000136772, 0.00018224, 0.000242822, 0.000323544, 0.000431101, 0.000574413, 0.000765366, 0.0010198, + 0.00135881, 0.00181053, 0.0024124, 0.00321437, 0.00428293, 0.00570671, 0.00760381, 0.0101316, + 0.0134996, 0.0179873, 0.0239669, 0.0319343, 0.0425503, 0.0566954, 0.0755428, 0.100656, + 0.134117, 0.178702, 0.238108, 0.317263, 0.422731, 0.563261, 0.750507, + 1.0, 1.33243, 1.77538, 2.36557, 3.15196, 4.19978, 5.59592, 7.45618, + 9.93486, 13.2375, 17.6381, 23.5016, 31.3143, 41.7242, 55.5947, 74.0762, + 98.7015, 131.513, 175.232, 233.485, 311.103, 414.524, 552.326, 735.937, + 980.586, 1306.56, 1740.91, 2319.64, 3090.77, 4118.24, 5487.28, 7311.43, + 9741.98, 12980.5, 17295.7, 23045.3, 30706.4, 40914.2, 54515.4, 72638, + 96785.3, 128960, 171830, 228952, 305064, 406477, 541603, 721649, + 961548, 1.2812e+06, 1.70711e+06, 2.27461e+06, 3.03076e+06, 4.03829e+06, 5.38075e+06, 7.16948e+06, + 9.55285e+06, 1.27285e+07, 1.69599e+07, 2.25979e+07, 3.01102e+07, 4.01198e+07, 5.3457e+07, 0, +}; + +static const int scale_conv_bias = 64; + +static const float dequantizer_scaling_table[] = +{ + 1.58838e-07, 2.11641e-07, 2.81998e-07, 3.75743e-07, 5.00652e-07, 6.67085e-07, 8.88846e-07, 1.18433e-06, + 1.57804e-06, 2.10263e-06, 2.80161e-06, 3.73296e-06, 4.97391e-06, 6.6274e-06, 8.83057e-06, 1.17661e-05, + 1.56776e-05, 2.08893e-05, 2.78336e-05, 3.70864e-05, 4.94151e-05, 6.58423e-05, 8.77305e-05, 0.000116895, + 0.000155755, 0.000207533, 0.000276523, 0.000368448, 0.000490933, 0.000654135, 0.00087159, 0.00116134, + 0.0015474, 0.00206181, 0.00274722, 0.00366048, 0.00487735, 0.00649874, 0.00865913, 0.0115377, + 0.0153732, 0.0204838, 0.0272932, 0.0363664, 0.0484558, 0.0645641, 0.0860272, 0.114626, + 0.152731, 0.203503, 0.271155, 0.361295, 0.481401, 0.641435, 0.854669, 1.13879, + 1.51736, 2.02178, 2.69388, 3.58942, 4.78266, 6.37257, 8.49102, 11.3137, +}; + +static const float quant_step_size[] = +{ + 0.0, 0.666667, 0.4, 0.285714, 0.222222, 0.181818, 0.153846, 0.133333, 0.0645161, + 0.031746, 0.015748, 0.00784314, 0.00391389, 0.00195503, 0.00097704, 0.000488401, +}; + +static const uint8_t ath_base_curve[656] = +{ + 0x78,0x5F,0x56,0x51,0x4E,0x4C,0x4B,0x49,0x48,0x48,0x47,0x46,0x46,0x45,0x45,0x45, + 0x44,0x44,0x44,0x44,0x43,0x43,0x43,0x43,0x43,0x43,0x42,0x42,0x42,0x42,0x42,0x42, + 0x42,0x42,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, + 0x3F,0x3F,0x3F,0x3E,0x3E,0x3E,0x3E,0x3E,0x3E,0x3D,0x3D,0x3D,0x3D,0x3D,0x3D,0x3D, + 0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B, + 0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B, + 0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3B,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C, + 0x3D,0x3D,0x3D,0x3D,0x3D,0x3D,0x3D,0x3D,0x3E,0x3E,0x3E,0x3E,0x3E,0x3E,0x3E,0x3F, + 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, + 0x3F,0x3F,0x3F,0x3F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x41,0x41,0x41,0x41,0x41,0x41,0x41, + 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, + 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42, + 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x43,0x43,0x43, + 0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x44,0x44, + 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x45,0x45,0x45,0x45, + 0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46, + 0x46,0x46,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x47,0x48,0x48,0x48,0x48, + 0x48,0x48,0x48,0x48,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x4A,0x4A,0x4A,0x4A, + 0x4A,0x4A,0x4A,0x4A,0x4B,0x4B,0x4B,0x4B,0x4B,0x4B,0x4B,0x4C,0x4C,0x4C,0x4C,0x4C, + 0x4C,0x4D,0x4D,0x4D,0x4D,0x4D,0x4D,0x4E,0x4E,0x4E,0x4E,0x4E,0x4E,0x4F,0x4F,0x4F, + 0x4F,0x4F,0x4F,0x50,0x50,0x50,0x50,0x50,0x51,0x51,0x51,0x51,0x51,0x52,0x52,0x52, + 0x52,0x52,0x53,0x53,0x53,0x53,0x54,0x54,0x54,0x54,0x54,0x55,0x55,0x55,0x55,0x56, + 0x56,0x56,0x56,0x57,0x57,0x57,0x57,0x57,0x58,0x58,0x58,0x59,0x59,0x59,0x59,0x5A, + 0x5A,0x5A,0x5A,0x5B,0x5B,0x5B,0x5B,0x5C,0x5C,0x5C,0x5D,0x5D,0x5D,0x5D,0x5E,0x5E, + 0x5E,0x5F,0x5F,0x5F,0x60,0x60,0x60,0x61,0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63, + 0x63,0x64,0x64,0x64,0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68,0x69, + 0x69,0x6A,0x6A,0x6A,0x6B,0x6B,0x6B,0x6C,0x6C,0x6D,0x6D,0x6D,0x6E,0x6E,0x6F,0x6F, + 0x70,0x70,0x70,0x71,0x71,0x72,0x72,0x73,0x73,0x73,0x74,0x74,0x75,0x75,0x76,0x76, + 0x77,0x77,0x78,0x78,0x78,0x79,0x79,0x7A,0x7A,0x7B,0x7B,0x7C,0x7C,0x7D,0x7D,0x7E, + 0x7E,0x7F,0x7F,0x80,0x80,0x81,0x81,0x82,0x83,0x83,0x84,0x84,0x85,0x85,0x86,0x86, + 0x87,0x88,0x88,0x89,0x89,0x8A,0x8A,0x8B,0x8C,0x8C,0x8D,0x8D,0x8E,0x8F,0x8F,0x90, + 0x90,0x91,0x92,0x92,0x93,0x94,0x94,0x95,0x95,0x96,0x97,0x97,0x98,0x99,0x99,0x9A, + 0x9B,0x9B,0x9C,0x9D,0x9D,0x9E,0x9F,0xA0,0xA0,0xA1,0xA2,0xA2,0xA3,0xA4,0xA5,0xA5, + 0xA6,0xA7,0xA7,0xA8,0xA9,0xAA,0xAA,0xAB,0xAC,0xAD,0xAE,0xAE,0xAF,0xB0,0xB1,0xB1, + 0xB2,0xB3,0xB4,0xB5,0xB6,0xB6,0xB7,0xB8,0xB9,0xBA,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, + 0xC0,0xC1,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xC9,0xCA,0xCB,0xCC,0xCD, + 0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD, + 0xDE,0xDF,0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xED,0xEE, + 0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFF,0xFF, +}; + +#endif /* AVCODEC_HCA_DATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/hcadec.c ffmpeg-4.4/libavcodec/hcadec.c --- ffmpeg-4.2.2/libavcodec/hcadec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hcadec.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,460 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/crc.h" +#include "libavutil/float_dsp.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" +#include "libavutil/tx.h" + +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "hca_data.h" + +typedef struct ChannelContext { + float base[128]; + DECLARE_ALIGNED(32, float, imdct_in)[128]; + DECLARE_ALIGNED(32, float, imdct_out)[128]; + DECLARE_ALIGNED(32, float, imdct_prev)[128]; + int8_t scale_factors[128]; + uint8_t scale[128]; + int8_t intensity[8]; + int8_t *hfr_scale; + unsigned count; + int chan_type; +} ChannelContext; + +typedef struct HCAContext { + GetBitContext gb; + + const AVCRC *crc_table; + + ChannelContext ch[16]; + + uint8_t ath[128]; + + int ath_type; + unsigned hfr_group_count; + uint8_t track_count; + uint8_t channel_config; + uint8_t total_band_count; + uint8_t base_band_count; + uint8_t stereo_band_count; + uint8_t bands_per_hfr_group; + + av_tx_fn tx_fn; + AVTXContext *tx_ctx; + AVFloatDSPContext *fdsp; +} HCAContext; + +static void ath_init1(uint8_t *ath, int sample_rate) +{ + unsigned int index; + unsigned int acc = 0; + + for (int i = 0; i < 128; i++) { + acc += sample_rate; + index = acc >> 13; + + if (index >= 654) { + memset(ath+i, 0xFF, (128 - i)); + break; + } + + ath[i] = ath_base_curve[index]; + } +} + +static int ath_init(uint8_t *ath, int type, int sample_rate) +{ + switch (type) { + case 0: + /* nothing to do */ + break; + case 1: + ath_init1(ath, sample_rate); + break; + default: + return AVERROR_INVALIDDATA; + } + + return 0; +} + +static inline unsigned ceil2(unsigned a, unsigned b) +{ + return (b > 0) ? (a / b + ((a % b) ? 1 : 0)) : 0; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + HCAContext *c = avctx->priv_data; + GetBitContext *gb = &c->gb; + int8_t r[16] = { 0 }; + float scale = 1.f / 8.f; + unsigned b, chunk; + int version, ret; + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + c->crc_table = av_crc_get_table(AV_CRC_16_ANSI); + + if (avctx->channels <= 0 || avctx->channels > 16) + return AVERROR(EINVAL); + + ret = init_get_bits8(gb, avctx->extradata, avctx->extradata_size); + if (ret < 0) + return ret; + skip_bits_long(gb, 32); + version = get_bits(gb, 16); + skip_bits_long(gb, 16); + + c->ath_type = version >= 0x200 ? 0 : 1; + + if (get_bits_long(gb, 32) != MKBETAG('f', 'm', 't', 0)) + return AVERROR_INVALIDDATA; + skip_bits_long(gb, 32); + skip_bits_long(gb, 32); + skip_bits_long(gb, 32); + + chunk = get_bits_long(gb, 32); + if (chunk == MKBETAG('c', 'o', 'm', 'p')) { + skip_bits_long(gb, 16); + skip_bits_long(gb, 8); + skip_bits_long(gb, 8); + c->track_count = get_bits(gb, 8); + c->channel_config = get_bits(gb, 8); + c->total_band_count = get_bits(gb, 8); + c->base_band_count = get_bits(gb, 8); + c->stereo_band_count = get_bits(gb, 8); + c->bands_per_hfr_group = get_bits(gb, 8); + } else if (chunk == MKBETAG('d', 'e', 'c', 0)) { + skip_bits_long(gb, 16); + skip_bits_long(gb, 8); + skip_bits_long(gb, 8); + c->total_band_count = get_bits(gb, 8) + 1; + c->base_band_count = get_bits(gb, 8) + 1; + c->track_count = get_bits(gb, 4); + c->channel_config = get_bits(gb, 4); + if (!get_bits(gb, 8)) + c->base_band_count = c->total_band_count; + c->stereo_band_count = c->total_band_count - c->base_band_count; + c->bands_per_hfr_group = 0; + } else + return AVERROR_INVALIDDATA; + + if (c->total_band_count > FF_ARRAY_ELEMS(c->ch->imdct_in)) + return AVERROR_INVALIDDATA; + + + while (get_bits_left(gb) >= 32) { + chunk = get_bits_long(gb, 32); + if (chunk == MKBETAG('v', 'b', 'r', 0)) { + skip_bits_long(gb, 16); + skip_bits_long(gb, 16); + } else if (chunk == MKBETAG('a', 't', 'h', 0)) { + c->ath_type = get_bits(gb, 16); + } else if (chunk == MKBETAG('r', 'v', 'a', 0)) { + skip_bits_long(gb, 32); + } else if (chunk == MKBETAG('c', 'o', 'm', 'm')) { + skip_bits_long(gb, get_bits(gb, 8) * 8); + } else if (chunk == MKBETAG('c', 'i', 'p', 'h')) { + skip_bits_long(gb, 16); + } else if (chunk == MKBETAG('l', 'o', 'o', 'p')) { + skip_bits_long(gb, 32); + skip_bits_long(gb, 32); + skip_bits_long(gb, 16); + skip_bits_long(gb, 16); + } else if (chunk == MKBETAG('p', 'a', 'd', 0)) { + break; + } else { + break; + } + } + + ret = ath_init(c->ath, c->ath_type, avctx->sample_rate); + if (ret < 0) + return ret; + + if (!c->track_count) + c->track_count = 1; + + b = avctx->channels / c->track_count; + if (c->stereo_band_count && b > 1) { + int8_t *x = r; + + for (int i = 0; i < c->track_count; i++, x+=b) { + switch (b) { + case 2: + case 3: + x[0] = 1; + x[1] = 2; + break; + case 4: + x[0]=1; x[1] = 2; + if (c->channel_config == 0) { + x[2]=1; + x[3]=2; + } + break; + case 5: + x[0]=1; x[1] = 2; + if (c->channel_config <= 2) { + x[3]=1; + x[4]=2; + } + break; + case 6: + case 7: + x[0] = 1; x[1] = 2; x[4] = 1; x[5] = 2; + break; + case 8: + x[0] = 1; x[1] = 2; x[4] = 1; x[5] = 2; x[6] = 1; x[7] = 2; + break; + } + } + } + + if (c->total_band_count < c->base_band_count) + return AVERROR_INVALIDDATA; + + c->hfr_group_count = ceil2(c->total_band_count - (c->base_band_count + c->stereo_band_count), + c->bands_per_hfr_group); + + if (c->base_band_count + c->stereo_band_count + (unsigned long)c->hfr_group_count > 128ULL) + return AVERROR_INVALIDDATA; + + for (int i = 0; i < avctx->channels; i++) { + c->ch[i].chan_type = r[i]; + c->ch[i].count = c->base_band_count + ((r[i] != 2) ? c->stereo_band_count : 0); + c->ch[i].hfr_scale = &c->ch[i].scale_factors[c->base_band_count + c->stereo_band_count]; + if (c->ch[i].count > 128) + return AVERROR_INVALIDDATA; + } + + c->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); + if (!c->fdsp) + return AVERROR(ENOMEM); + + return av_tx_init(&c->tx_ctx, &c->tx_fn, AV_TX_FLOAT_MDCT, 1, 128, &scale, 0); +} + +static void run_imdct(HCAContext *c, ChannelContext *ch, int index, float *out) +{ + c->tx_fn(c->tx_ctx, ch->imdct_out, ch->imdct_in, sizeof(float)); + + c->fdsp->vector_fmul_window(out, ch->imdct_prev + (128 >> 1), + ch->imdct_out, window, 128 >> 1); + + memcpy(ch->imdct_prev, ch->imdct_out, 128 * sizeof(float)); +} + +static void apply_intensity_stereo(HCAContext *s, ChannelContext *ch1, ChannelContext *ch2, + int index, unsigned band_count, unsigned base_band_count, + unsigned stereo_band_count) +{ + float ratio_l = intensity_ratio_table[ch2->intensity[index]]; + float ratio_r = ratio_l - 2.0f; + float *c1 = &ch1->imdct_in[base_band_count]; + float *c2 = &ch2->imdct_in[base_band_count]; + + if (ch1->chan_type != 1 || !stereo_band_count) + return; + + for (int i = 0; i < band_count; i++) { + *(c2++) = *c1 * ratio_r; + *(c1++) *= ratio_l; + } +} + +static void reconstruct_hfr(HCAContext *s, ChannelContext *ch, + unsigned hfr_group_count, + unsigned bands_per_hfr_group, + unsigned start_band, unsigned total_band_count) +{ + if (ch->chan_type == 2 || !bands_per_hfr_group) + return; + + for (int i = 0, k = start_band, l = start_band - 1; i < hfr_group_count; i++){ + for (int j = 0; j < bands_per_hfr_group && k < total_band_count && l >= 0; j++, k++, l--){ + ch->imdct_in[k] = scale_conversion_table[ scale_conv_bias + + av_clip_intp2(ch->hfr_scale[i] - ch->scale_factors[l], 6) ] * ch->imdct_in[l]; + } + } + + ch->imdct_in[127] = 0; +} + +static void dequantize_coefficients(HCAContext *c, ChannelContext *ch) +{ + GetBitContext *gb = &c->gb; + + for (int i = 0; i < ch->count; i++) { + unsigned scale = ch->scale[i]; + int nb_bits = max_bits_table[scale]; + int value = get_bitsz(gb, nb_bits); + float factor; + + if (scale > 7) { + value = (1 - ((value & 1) << 1)) * (value >> 1); + if (!value) + skip_bits_long(gb, -1); + factor = value; + } else { + value += scale << 4; + skip_bits_long(gb, quant_spectrum_bits[value] - nb_bits); + factor = quant_spectrum_value[value]; + } + ch->imdct_in[i] = factor * ch->base[i]; + } + + memset(ch->imdct_in + ch->count, 0, sizeof(ch->imdct_in) - ch->count * sizeof(ch->imdct_in[0])); +} + +static void unpack(HCAContext *c, ChannelContext *ch, + unsigned hfr_group_count, + int packed_noise_level, + const uint8_t *ath) +{ + GetBitContext *gb = &c->gb; + int delta_bits = get_bits(gb, 3); + + if (delta_bits > 5) { + for (int i = 0; i < ch->count; i++) + ch->scale_factors[i] = get_bits(gb, 6); + } else if (delta_bits) { + int factor = get_bits(gb, 6); + int max_value = (1 << delta_bits) - 1; + int half_max = max_value >> 1; + + ch->scale_factors[0] = factor; + for (int i = 1; i < ch->count; i++){ + int delta = get_bits(gb, delta_bits); + + if (delta == max_value) { + factor = get_bits(gb, 6); + } else { + factor += delta - half_max; + } + factor = av_clip_uintp2(factor, 6); + + ch->scale_factors[i] = factor; + } + } else { + memset(ch->scale_factors, 0, 128); + } + + if (ch->chan_type == 2){ + ch->intensity[0] = get_bits(gb, 4); + if (ch->intensity[0] < 15) { + for (int i = 1; i < 8; i++) + ch->intensity[i] = get_bits(gb, 4); + } + } else { + for (int i = 0; i < hfr_group_count; i++) + ch->hfr_scale[i] = get_bits(gb, 6); + } + + for (int i = 0; i < ch->count; i++) { + int scale = ch->scale_factors[i]; + + if (scale) { + scale = c->ath[i] + ((packed_noise_level + i) >> 8) - ((scale * 5) >> 1) + 2; + scale = scale_table[av_clip(scale, 0, 58)]; + } + ch->scale[i] = scale; + } + + memset(ch->scale + ch->count, 0, sizeof(ch->scale) - ch->count); + + for (int i = 0; i < ch->count; i++) + ch->base[i] = dequantizer_scaling_table[ch->scale_factors[i]] * quant_step_size[ch->scale[i]]; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + HCAContext *c = avctx->priv_data; + int ch, ret, packed_noise_level; + GetBitContext *gb = &c->gb; + float **samples; + + if (avctx->err_recognition & AV_EF_CRCCHECK) { + if (av_crc(c->crc_table, 0, avpkt->data, avpkt->size)) + return AVERROR_INVALIDDATA; + } + + if ((ret = init_get_bits8(gb, avpkt->data, avpkt->size)) < 0) + return ret; + + if (get_bits(gb, 16) != 0xFFFF) + return AVERROR_INVALIDDATA; + + frame->nb_samples = 1024; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (float **)frame->extended_data; + + packed_noise_level = (get_bits(gb, 9) << 8) - get_bits(gb, 7); + + for (ch = 0; ch < avctx->channels; ch++) + unpack(c, &c->ch[ch], c->hfr_group_count, packed_noise_level, c->ath); + + for (int i = 0; i < 8; i++) { + for (ch = 0; ch < avctx->channels; ch++) + dequantize_coefficients(c, &c->ch[ch]); + for (ch = 0; ch < avctx->channels; ch++) + reconstruct_hfr(c, &c->ch[ch], c->hfr_group_count, c->bands_per_hfr_group, + c->stereo_band_count + c->base_band_count, c->total_band_count); + for (ch = 0; ch < avctx->channels - 1; ch++) + apply_intensity_stereo(c, &c->ch[ch], &c->ch[ch+1], i, + c->total_band_count - c->base_band_count, + c->base_band_count, c->stereo_band_count); + for (ch = 0; ch < avctx->channels; ch++) + run_imdct(c, &c->ch[ch], i, samples[ch] + i * 128); + } + + *got_frame_ptr = 1; + + return avpkt->size; +} + +static av_cold int decode_close(AVCodecContext *avctx) +{ + HCAContext *c = avctx->priv_data; + + av_freep(&c->fdsp); + av_tx_uninit(&c->tx_ctx); + + return 0; +} + +AVCodec ff_hca_decoder = { + .name = "hca", + .long_name = NULL_IF_CONFIG_SMALL("CRI HCA"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_HCA, + .priv_data_size = sizeof(HCAContext), + .init = decode_init, + .decode = decode_frame, + .close = decode_close, + .capabilities = AV_CODEC_CAP_DR1, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; diff -Nru ffmpeg-4.2.2/libavcodec/hcom.c ffmpeg-4.4/libavcodec/hcom.c --- ffmpeg-4.2.2/libavcodec/hcom.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hcom.c 2021-04-08 21:28:39.000000000 +0000 @@ -67,15 +67,11 @@ if (s->dict[i].l >= 0 && (s->dict[i].l >= s->dict_entries || s->dict[i].r >= s->dict_entries || - s->dict[i].r < 0 )) { - av_freep(&s->dict); + s->dict[i].r < 0 )) return AVERROR_INVALIDDATA; - } } - if (s->dict[0].l < 0) { - av_freep(&s->dict); + if (s->dict[0].l < 0) return AVERROR_INVALIDDATA; - } avctx->sample_fmt = AV_SAMPLE_FMT_U8; s->dict_entry = 0; @@ -148,4 +144,5 @@ .close = hcom_close, .decode = hcom_decode, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/hevc_cabac.c ffmpeg-4.4/libavcodec/hevc_cabac.c --- ffmpeg-4.2.2/libavcodec/hevc_cabac.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevc_cabac.c 2021-04-08 21:28:39.000000000 +0000 @@ -66,7 +66,7 @@ 1, // no_residual_data_flag 3, // split_transform_flag 2, // cbf_luma - 4, // cbf_cb, cbf_cr + 5, // cbf_cb, cbf_cr 2, // transform_skip_flag[][] 2, // explicit_rdpcm_flag[][] 2, // explicit_rdpcm_dir_flag[][] @@ -122,23 +122,23 @@ 37, // split_transform_flag 40, // cbf_luma 42, // cbf_cb, cbf_cr - 46, // transform_skip_flag[][] - 48, // explicit_rdpcm_flag[][] - 50, // explicit_rdpcm_dir_flag[][] - 52, // last_significant_coeff_x_prefix - 70, // last_significant_coeff_y_prefix - 88, // last_significant_coeff_x_suffix - 88, // last_significant_coeff_y_suffix - 88, // significant_coeff_group_flag - 92, // significant_coeff_flag - 136, // coeff_abs_level_greater1_flag - 160, // coeff_abs_level_greater2_flag - 166, // coeff_abs_level_remaining - 166, // coeff_sign_flag - 166, // log2_res_scale_abs - 174, // res_scale_sign_flag - 176, // cu_chroma_qp_offset_flag - 177, // cu_chroma_qp_offset_idx + 47, // transform_skip_flag[][] + 49, // explicit_rdpcm_flag[][] + 51, // explicit_rdpcm_dir_flag[][] + 53, // last_significant_coeff_x_prefix + 71, // last_significant_coeff_y_prefix + 89, // last_significant_coeff_x_suffix + 89, // last_significant_coeff_y_suffix + 89, // significant_coeff_group_flag + 93, // significant_coeff_flag + 137, // coeff_abs_level_greater1_flag + 161, // coeff_abs_level_greater2_flag + 167, // coeff_abs_level_remaining + 167, // coeff_sign_flag + 167, // log2_res_scale_abs + 175, // res_scale_sign_flag + 177, // cu_chroma_qp_offset_flag + 178, // cu_chroma_qp_offset_idx }; #define CNU 154 @@ -189,7 +189,7 @@ // cbf_luma 111, 141, // cbf_cb, cbf_cr - 94, 138, 182, 154, + 94, 138, 182, 154, 154, // transform_skip_flag 139, 139, // explicit_rdpcm_flag @@ -266,7 +266,7 @@ // cbf_luma 153, 111, // cbf_cb, cbf_cr - 149, 107, 167, 154, + 149, 107, 167, 154, 154, // transform_skip_flag 139, 139, // explicit_rdpcm_flag @@ -343,7 +343,7 @@ // cbf_luma 153, 111, // cbf_cb, cbf_cr - 149, 92, 167, 154, + 149, 92, 167, 154, 154, // transform_skip_flag 139, 139, // explicit_rdpcm_flag @@ -454,12 +454,19 @@ (s->ps.sps->ctb_width == 2 && ctb_addr_ts % s->ps.sps->ctb_width == 0))) { memcpy(s->cabac_state, s->HEVClc->cabac_state, HEVC_CONTEXTS); + if (s->ps.sps->persistent_rice_adaptation_enabled_flag) { + memcpy(s->stat_coeff, s->HEVClc->stat_coeff, HEVC_STAT_COEFFS); + } } } -static void load_states(HEVCContext *s) +static void load_states(HEVCContext *s, int thread) { memcpy(s->HEVClc->cabac_state, s->cabac_state, HEVC_CONTEXTS); + if (s->ps.sps->persistent_rice_adaptation_enabled_flag) { + const HEVCContext *prev = s->sList[(thread + s->threads_number - 1) % s->threads_number]; + memcpy(s->HEVClc->stat_coeff, prev->stat_coeff, HEVC_STAT_COEFFS); + } } static int cabac_reinit(HEVCLocalContext *lc) @@ -501,7 +508,7 @@ s->HEVClc->stat_coeff[i] = 0; } -int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts) +int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts, int thread) { if (ctb_addr_ts == s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]) { int ret = cabac_init_decoder(s); @@ -518,7 +525,7 @@ if (s->ps.sps->ctb_width == 1) cabac_init_state(s); else if (s->sh.dependent_slice_segment_flag == 1) - load_states(s); + load_states(s, thread); } } } else { @@ -549,7 +556,7 @@ if (s->ps.sps->ctb_width == 1) cabac_init_state(s); else - load_states(s); + load_states(s, thread); } } } @@ -998,7 +1005,7 @@ } else { int prefix_minus3 = prefix - 3; - if (prefix == CABAC_MAX_BIN || prefix_minus3 + rc_rice_param >= 31) { + if (prefix == CABAC_MAX_BIN || prefix_minus3 + rc_rice_param > 16 + 6) { av_log(s->avctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", prefix); return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/hevcdec.c ffmpeg-4.4/libavcodec/hevcdec.c --- ffmpeg-4.2.2/libavcodec/hevcdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevcdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,6 +32,7 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/stereo3d.h" +#include "libavutil/timecode.h" #include "bswapdsp.h" #include "bytestream.h" @@ -41,7 +42,7 @@ #include "hevc_data.h" #include "hevc_parse.h" #include "hevcdec.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "profiles.h" const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 }; @@ -280,7 +281,6 @@ rps->nb_refs = nb_sh + nb_sps; for (i = 0; i < rps->nb_refs; i++) { - uint8_t delta_poc_msb_present; if (i < nb_sps) { uint8_t lt_idx_sps = 0; @@ -295,8 +295,8 @@ rps->used[i] = get_bits1(gb); } - delta_poc_msb_present = get_bits1(gb); - if (delta_poc_msb_present) { + rps->poc_msb_present[i] = get_bits1(gb); + if (rps->poc_msb_present[i]) { int64_t delta = get_ue_golomb_long(gb); int64_t poc; @@ -349,6 +349,15 @@ avctx->colorspace = AVCOL_SPC_UNSPECIFIED; } + avctx->chroma_sample_location = AVCHROMA_LOC_UNSPECIFIED; + if (sps->chroma_format_idc == 1) { + if (sps->vui.chroma_loc_info_present_flag) { + if (sps->vui.chroma_sample_loc_type_top_field <= 5) + avctx->chroma_sample_location = sps->vui.chroma_sample_loc_type_top_field + 1; + } else + avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; + } + if (vps->vps_timing_info_present_flag) { num = vps->vps_num_units_in_tick; den = vps->vps_time_scale; @@ -360,12 +369,22 @@ if (num != 0 && den != 0) av_reduce(&avctx->framerate.den, &avctx->framerate.num, num, den, 1 << 30); +} + +static int export_stream_params_from_sei(HEVCContext *s) +{ + AVCodecContext *avctx = s->avctx; + + if (s->sei.a53_caption.buf_ref) + s->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; if (s->sei.alternative_transfer.present && av_color_transfer_name(s->sei.alternative_transfer.preferred_transfer_characteristics) && s->sei.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { avctx->color_trc = s->sei.alternative_transfer.preferred_transfer_characteristics; } + + return 0; } static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) @@ -415,6 +434,9 @@ #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif +#if CONFIG_HEVC_VDPAU_HWACCEL + *fmt++ = AV_PIX_FMT_VDPAU; +#endif #if CONFIG_HEVC_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; #endif @@ -427,9 +449,18 @@ *fmt++ = AV_PIX_FMT_CUDA; #endif break; + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV422P10LE: +#if CONFIG_HEVC_VAAPI_HWACCEL + *fmt++ = AV_PIX_FMT_VAAPI; +#endif + break; case AV_PIX_FMT_YUV420P12: case AV_PIX_FMT_YUV444P10: case AV_PIX_FMT_YUV444P12: +#if CONFIG_HEVC_VDPAU_HWACCEL + *fmt++ = AV_PIX_FMT_VDPAU; +#endif #if CONFIG_HEVC_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; #endif @@ -484,6 +515,9 @@ s->sao_pixel_buffer_v[c_idx] = av_malloc((h * 2 * sps->ctb_width) << sps->pixel_shift); + if (!s->sao_pixel_buffer_h[c_idx] || + !s->sao_pixel_buffer_v[c_idx]) + goto fail; } } @@ -494,6 +528,10 @@ fail: pic_arrays_free(s); + for (i = 0; i < 3; i++) { + av_freep(&s->sao_pixel_buffer_h[i]); + av_freep(&s->sao_pixel_buffer_v[i]); + } s->ps.sps = NULL; return ret; } @@ -561,6 +599,10 @@ s->max_ra = INT_MAX; } + ret = export_stream_params_from_sei(s); + if (ret < 0) + return ret; + sh->dependent_slice_segment_flag = 0; if (!sh->first_slice_in_pic_flag) { int slice_address_length; @@ -780,6 +822,11 @@ if (s->ps.pps->pic_slice_level_chroma_qp_offsets_present_flag) { sh->slice_cb_qp_offset = get_se_golomb(gb); sh->slice_cr_qp_offset = get_se_golomb(gb); + if (sh->slice_cb_qp_offset < -12 || sh->slice_cb_qp_offset > 12 || + sh->slice_cr_qp_offset < -12 || sh->slice_cr_qp_offset > 12) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid slice cx qp offset.\n"); + return AVERROR_INVALIDDATA; + } } else { sh->slice_cb_qp_offset = 0; sh->slice_cr_qp_offset = 0; @@ -2433,7 +2480,7 @@ y_ctb = (ctb_addr_rs / ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size; hls_decode_neighbour(s, x_ctb, y_ctb, ctb_addr_ts); - ret = ff_hevc_cabac_init(s, ctb_addr_ts); + ret = ff_hevc_cabac_init(s, ctb_addr_ts, 0); if (ret < 0) { s->tab_slice_address[ctb_addr_rs] = -1; return ret; @@ -2511,7 +2558,7 @@ return 0; } - ret = ff_hevc_cabac_init(s, ctb_addr_ts); + ret = ff_hevc_cabac_init(s, ctb_addr_ts, thread); if (ret < 0) goto error; hls_sao_param(s, x_ctb >> s->ps.sps->log2_ctb_size, y_ctb >> s->ps.sps->log2_ctb_size); @@ -2584,13 +2631,19 @@ ff_alloc_entries(s->avctx, s->sh.num_entry_point_offsets + 1); - if (!s->sList[1]) { - for (i = 1; i < s->threads_number; i++) { - s->sList[i] = av_malloc(sizeof(HEVCContext)); - memcpy(s->sList[i], s, sizeof(HEVCContext)); - s->HEVClcList[i] = av_mallocz(sizeof(HEVCLocalContext)); - s->sList[i]->HEVClc = s->HEVClcList[i]; + for (i = 1; i < s->threads_number; i++) { + if (s->sList[i] && s->HEVClcList[i]) + continue; + av_freep(&s->sList[i]); + av_freep(&s->HEVClcList[i]); + s->sList[i] = av_malloc(sizeof(HEVCContext)); + s->HEVClcList[i] = av_mallocz(sizeof(HEVCLocalContext)); + if (!s->sList[i] || !s->HEVClcList[i]) { + res = AVERROR(ENOMEM); + goto error; } + memcpy(s->sList[i], s, sizeof(HEVCContext)); + s->sList[i]->HEVClc = s->HEVClcList[i]; } offset = (lc->gb.index >> 3); @@ -2778,15 +2831,64 @@ metadata->MaxCLL, metadata->MaxFALL); } - if (s->sei.a53_caption.a53_caption) { - AVFrameSideData* sd = av_frame_new_side_data(out, - AV_FRAME_DATA_A53_CC, - s->sei.a53_caption.a53_caption_size); - if (sd) - memcpy(sd->data, s->sei.a53_caption.a53_caption, s->sei.a53_caption.a53_caption_size); - av_freep(&s->sei.a53_caption.a53_caption); - s->sei.a53_caption.a53_caption_size = 0; - s->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; + if (s->sei.a53_caption.buf_ref) { + HEVCSEIA53Caption *a53 = &s->sei.a53_caption; + + AVFrameSideData *sd = av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_A53_CC, a53->buf_ref); + if (!sd) + av_buffer_unref(&a53->buf_ref); + a53->buf_ref = NULL; + } + + for (int i = 0; i < s->sei.unregistered.nb_buf_ref; i++) { + HEVCSEIUnregistered *unreg = &s->sei.unregistered; + + if (unreg->buf_ref[i]) { + AVFrameSideData *sd = av_frame_new_side_data_from_buf(out, + AV_FRAME_DATA_SEI_UNREGISTERED, + unreg->buf_ref[i]); + if (!sd) + av_buffer_unref(&unreg->buf_ref[i]); + unreg->buf_ref[i] = NULL; + } + } + s->sei.unregistered.nb_buf_ref = 0; + + if (s->sei.timecode.present) { + uint32_t *tc_sd; + char tcbuf[AV_TIMECODE_STR_SIZE]; + AVFrameSideData *tcside = av_frame_new_side_data(out, AV_FRAME_DATA_S12M_TIMECODE, + sizeof(uint32_t) * 4); + if (!tcside) + return AVERROR(ENOMEM); + + tc_sd = (uint32_t*)tcside->data; + tc_sd[0] = s->sei.timecode.num_clock_ts; + + for (int i = 0; i < tc_sd[0]; i++) { + int drop = s->sei.timecode.cnt_dropped_flag[i]; + int hh = s->sei.timecode.hours_value[i]; + int mm = s->sei.timecode.minutes_value[i]; + int ss = s->sei.timecode.seconds_value[i]; + int ff = s->sei.timecode.n_frames[i]; + + tc_sd[i + 1] = av_timecode_get_smpte(s->avctx->framerate, drop, hh, mm, ss, ff); + av_timecode_make_smpte_tc_string2(tcbuf, s->avctx->framerate, tc_sd[i + 1], 0, 0); + av_dict_set(&out->metadata, "timecode", tcbuf, 0); + } + + s->sei.timecode.num_clock_ts = 0; + } + + if (s->sei.dynamic_hdr_plus.info) { + AVBufferRef *info_ref = av_buffer_ref(s->sei.dynamic_hdr_plus.info); + if (!info_ref) + return AVERROR(ENOMEM); + + if (!av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_DYNAMIC_HDR_PLUS, info_ref)) { + av_buffer_unref(&info_ref); + return AVERROR(ENOMEM); + } } return 0; @@ -3077,7 +3179,7 @@ if (s->avctx->skip_frame >= AVDISCARD_ALL || (s->avctx->skip_frame >= AVDISCARD_NONREF - && ff_hevc_nal_is_nonref(nal->type))) + && ff_hevc_nal_is_nonref(nal->type)) || nal->nuh_layer_id > 0) continue; ret = decode_nal_unit(s, nal); @@ -3189,6 +3291,11 @@ } } + /* export stream parameters from SEI */ + ret = export_stream_params_from_sei(s); + if (ret < 0) + return ret; + return 0; } @@ -3196,7 +3303,7 @@ AVPacket *avpkt) { int ret; - int new_extradata_size; + buffer_size_t new_extradata_size; uint8_t *new_extradata; HEVCContext *s = avctx->priv_data; @@ -3323,16 +3430,15 @@ av_freep(&s->sh.offset); av_freep(&s->sh.size); - for (i = 1; i < s->threads_number; i++) { - HEVCLocalContext *lc = s->HEVClcList[i]; - if (lc) { + if (s->HEVClcList && s->sList) { + for (i = 1; i < s->threads_number; i++) { av_freep(&s->HEVClcList[i]); av_freep(&s->sList[i]); } } - if (s->HEVClc == s->HEVClcList[0]) - s->HEVClc = NULL; - av_freep(&s->HEVClcList[0]); + av_freep(&s->HEVClc); + av_freep(&s->HEVClcList); + av_freep(&s->sList); ff_h2645_packet_uninit(&s->pkt); @@ -3349,7 +3455,9 @@ s->avctx = avctx; s->HEVClc = av_mallocz(sizeof(HEVCLocalContext)); - if (!s->HEVClc) + s->HEVClcList = av_mallocz(sizeof(HEVCLocalContext*) * s->threads_number); + s->sList = av_mallocz(sizeof(HEVCContext*) * s->threads_number); + if (!s->HEVClc || !s->HEVClcList || !s->sList) goto fail; s->HEVClcList[0] = s->HEVClc; s->sList[0] = s; @@ -3415,30 +3523,21 @@ if (s->ps.sps != s0->ps.sps) s->ps.sps = NULL; for (i = 0; i < FF_ARRAY_ELEMS(s->ps.vps_list); i++) { - av_buffer_unref(&s->ps.vps_list[i]); - if (s0->ps.vps_list[i]) { - s->ps.vps_list[i] = av_buffer_ref(s0->ps.vps_list[i]); - if (!s->ps.vps_list[i]) - return AVERROR(ENOMEM); - } + ret = av_buffer_replace(&s->ps.vps_list[i], s0->ps.vps_list[i]); + if (ret < 0) + return ret; } for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) { - av_buffer_unref(&s->ps.sps_list[i]); - if (s0->ps.sps_list[i]) { - s->ps.sps_list[i] = av_buffer_ref(s0->ps.sps_list[i]); - if (!s->ps.sps_list[i]) - return AVERROR(ENOMEM); - } + ret = av_buffer_replace(&s->ps.sps_list[i], s0->ps.sps_list[i]); + if (ret < 0) + return ret; } for (i = 0; i < FF_ARRAY_ELEMS(s->ps.pps_list); i++) { - av_buffer_unref(&s->ps.pps_list[i]); - if (s0->ps.pps_list[i]) { - s->ps.pps_list[i] = av_buffer_ref(s0->ps.pps_list[i]); - if (!s->ps.pps_list[i]) - return AVERROR(ENOMEM); - } + ret = av_buffer_replace(&s->ps.pps_list[i], s0->ps.pps_list[i]); + if (ret < 0) + return ret; } if (s->ps.sps != s0->ps.sps) @@ -3463,12 +3562,43 @@ s->max_ra = INT_MAX; } + ret = av_buffer_replace(&s->sei.a53_caption.buf_ref, s0->sei.a53_caption.buf_ref); + if (ret < 0) + return ret; + + for (i = 0; i < s->sei.unregistered.nb_buf_ref; i++) + av_buffer_unref(&s->sei.unregistered.buf_ref[i]); + s->sei.unregistered.nb_buf_ref = 0; + + if (s0->sei.unregistered.nb_buf_ref) { + ret = av_reallocp_array(&s->sei.unregistered.buf_ref, + s0->sei.unregistered.nb_buf_ref, + sizeof(*s->sei.unregistered.buf_ref)); + if (ret < 0) + return ret; + + for (i = 0; i < s0->sei.unregistered.nb_buf_ref; i++) { + s->sei.unregistered.buf_ref[i] = av_buffer_ref(s0->sei.unregistered.buf_ref[i]); + if (!s->sei.unregistered.buf_ref[i]) + return AVERROR(ENOMEM); + s->sei.unregistered.nb_buf_ref++; + } + } + + ret = av_buffer_replace(&s->sei.dynamic_hdr_plus.info, s0->sei.dynamic_hdr_plus.info); + if (ret < 0) + return ret; + s->sei.frame_packing = s0->sei.frame_packing; s->sei.display_orientation = s0->sei.display_orientation; s->sei.mastering_display = s0->sei.mastering_display; s->sei.content_light = s0->sei.content_light; s->sei.alternative_transfer = s0->sei.alternative_transfer; + ret = export_stream_params_from_sei(s); + if (ret < 0) + return ret; + return 0; } #endif @@ -3478,7 +3608,15 @@ HEVCContext *s = avctx->priv_data; int ret; - avctx->internal->allocate_progress = 1; + if(avctx->active_thread_type & FF_THREAD_SLICE) + s->threads_number = avctx->thread_count; + else + s->threads_number = 1; + + if((avctx->active_thread_type & FF_THREAD_FRAME) && avctx->thread_count > 1) + s->threads_type = FF_THREAD_FRAME; + else + s->threads_type = FF_THREAD_SLICE; ret = hevc_init_context(avctx); if (ret < 0) @@ -3490,43 +3628,18 @@ atomic_init(&s->wpp_err, 0); - if(avctx->active_thread_type & FF_THREAD_SLICE) - s->threads_number = avctx->thread_count; - else - s->threads_number = 1; - - if (avctx->extradata_size > 0 && avctx->extradata) { - ret = hevc_decode_extradata(s, avctx->extradata, avctx->extradata_size, 1); - if (ret < 0) { - hevc_decode_free(avctx); - return ret; + if (!avctx->internal->is_copy) { + if (avctx->extradata_size > 0 && avctx->extradata) { + ret = hevc_decode_extradata(s, avctx->extradata, avctx->extradata_size, 1); + if (ret < 0) { + return ret; + } } } - if((avctx->active_thread_type & FF_THREAD_FRAME) && avctx->thread_count > 1) - s->threads_type = FF_THREAD_FRAME; - else - s->threads_type = FF_THREAD_SLICE; - return 0; } -#if HAVE_THREADS -static av_cold int hevc_init_thread_copy(AVCodecContext *avctx) -{ - HEVCContext *s = avctx->priv_data; - int ret; - - memset(s, 0, sizeof(*s)); - - ret = hevc_init_context(avctx); - if (ret < 0) - return ret; - - return 0; -} -#endif - static void hevc_decode_flush(AVCodecContext *avctx) { HEVCContext *s = avctx->priv_data; @@ -3566,12 +3679,12 @@ .decode = hevc_decode_frame, .flush = hevc_decode_flush, .update_thread_context = ONLY_IF_THREADS_ENABLED(hevc_update_thread_context), - .init_thread_copy = ONLY_IF_THREADS_ENABLED(hevc_init_thread_copy), .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING | + FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_INIT_CLEANUP, .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), - .hw_configs = (const AVCodecHWConfigInternal*[]) { + .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_HEVC_DXVA2_HWACCEL HWACCEL_DXVA2(hevc), #endif diff -Nru ffmpeg-4.2.2/libavcodec/hevcdec.h ffmpeg-4.4/libavcodec/hevcdec.h --- ffmpeg-4.2.2/libavcodec/hevcdec.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevcdec.h 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ #include "libavutil/buffer.h" #include "libavutil/md5.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "bswapdsp.h" @@ -42,7 +43,6 @@ #include "thread.h" #include "videodsp.h" -#define MAX_NB_THREADS 16 #define SHIFT_CTB_WPP 2 //TODO: check if this is really the maximum @@ -53,6 +53,7 @@ #define DEFAULT_INTRA_TC_OFFSET 2 #define HEVC_CONTEXTS 199 +#define HEVC_STAT_COEFFS 4 #define MRG_MAX_NUM_CANDS 5 @@ -228,6 +229,13 @@ SCAN_VERT, }; +typedef struct LongTermRPS { + int poc[32]; + uint8_t poc_msb_present[32]; + uint8_t used[32]; + uint8_t nb_refs; +} LongTermRPS; + typedef struct RefPicList { struct HEVCFrame *ref[HEVC_MAX_REFS]; int list[HEVC_MAX_REFS]; @@ -239,6 +247,83 @@ RefPicList refPicList[2]; } RefPicListTab; +typedef struct SliceHeader { + unsigned int pps_id; + + ///< address (in raster order) of the first block in the current slice segment + unsigned int slice_segment_addr; + ///< address (in raster order) of the first block in the current slice + unsigned int slice_addr; + + enum HEVCSliceType slice_type; + + int pic_order_cnt_lsb; + + uint8_t first_slice_in_pic_flag; + uint8_t dependent_slice_segment_flag; + uint8_t pic_output_flag; + uint8_t colour_plane_id; + + ///< RPS coded in the slice header itself is stored here + int short_term_ref_pic_set_sps_flag; + int short_term_ref_pic_set_size; + ShortTermRPS slice_rps; + const ShortTermRPS *short_term_rps; + int long_term_ref_pic_set_size; + LongTermRPS long_term_rps; + unsigned int list_entry_lx[2][32]; + + uint8_t rpl_modification_flag[2]; + uint8_t no_output_of_prior_pics_flag; + uint8_t slice_temporal_mvp_enabled_flag; + + unsigned int nb_refs[2]; + + uint8_t slice_sample_adaptive_offset_flag[3]; + uint8_t mvd_l1_zero_flag; + + uint8_t cabac_init_flag; + uint8_t disable_deblocking_filter_flag; ///< slice_header_disable_deblocking_filter_flag + uint8_t slice_loop_filter_across_slices_enabled_flag; + uint8_t collocated_list; + + unsigned int collocated_ref_idx; + + int slice_qp_delta; + int slice_cb_qp_offset; + int slice_cr_qp_offset; + + uint8_t cu_chroma_qp_offset_enabled_flag; + + int beta_offset; ///< beta_offset_div2 * 2 + int tc_offset; ///< tc_offset_div2 * 2 + + unsigned int max_num_merge_cand; ///< 5 - 5_minus_max_num_merge_cand + + unsigned *entry_point_offset; + int * offset; + int * size; + int num_entry_point_offsets; + + int8_t slice_qp; + + uint8_t luma_log2_weight_denom; + int16_t chroma_log2_weight_denom; + + int16_t luma_weight_l0[16]; + int16_t chroma_weight_l0[16][2]; + int16_t chroma_weight_l1[16][2]; + int16_t luma_weight_l1[16]; + + int16_t luma_offset_l0[16]; + int16_t chroma_offset_l0[16][2]; + + int16_t luma_offset_l1[16]; + int16_t chroma_offset_l1[16][2]; + + int slice_ctb_addr_rs; +} SliceHeader; + typedef struct CodingUnit { int x; int y; @@ -340,7 +425,7 @@ typedef struct HEVCLocalContext { uint8_t cabac_state[HEVC_CONTEXTS]; - uint8_t stat_coeff[4]; + uint8_t stat_coeff[HEVC_STAT_COEFFS]; uint8_t first_qp_group; @@ -384,9 +469,9 @@ const AVClass *c; // needed by private avoptions AVCodecContext *avctx; - struct HEVCContext *sList[MAX_NB_THREADS]; + struct HEVCContext **sList; - HEVCLocalContext *HEVClcList[MAX_NB_THREADS]; + HEVCLocalContext **HEVClcList; HEVCLocalContext *HEVClc; uint8_t threads_type; @@ -396,6 +481,7 @@ int height; uint8_t *cabac_state; + uint8_t stat_coeff[HEVC_STAT_COEFFS]; /** 1 if the independent slice segment header was successfully parsed */ uint8_t slice_initialized; @@ -510,7 +596,7 @@ int ff_hevc_slice_rpl(HEVCContext *s); void ff_hevc_save_states(HEVCContext *s, int ctb_addr_ts); -int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts); +int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts, int thread); int ff_hevc_sao_merge_flag_decode(HEVCContext *s); int ff_hevc_sao_type_idx_decode(HEVCContext *s); int ff_hevc_sao_band_position_decode(HEVCContext *s); @@ -561,7 +647,6 @@ case HEVC_NAL_VCL_N12: case HEVC_NAL_VCL_N14: return 1; - break; default: break; } return 0; diff -Nru ffmpeg-4.2.2/libavcodec/hevcdsp.c ffmpeg-4.4/libavcodec/hevcdsp.c --- ffmpeg-4.2.2/libavcodec/hevcdsp.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevcdsp.c 2021-04-08 21:28:39.000000000 +0000 @@ -257,6 +257,8 @@ break; } + if (ARCH_AARCH64) + ff_hevc_dsp_init_aarch64(hevcdsp, bit_depth); if (ARCH_ARM) ff_hevc_dsp_init_arm(hevcdsp, bit_depth); if (ARCH_PPC) diff -Nru ffmpeg-4.2.2/libavcodec/hevcdsp.h ffmpeg-4.4/libavcodec/hevcdsp.h --- ffmpeg-4.2.2/libavcodec/hevcdsp.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevcdsp.h 2021-04-08 21:28:39.000000000 +0000 @@ -25,6 +25,8 @@ #ifndef AVCODEC_HEVCDSP_H #define AVCODEC_HEVCDSP_H +#include "libavutil/mem_internal.h" + #include "get_bits.h" #define MAX_PB_SIZE 64 @@ -127,6 +129,7 @@ extern const int8_t ff_hevc_epel_filters[7][4]; extern const int8_t ff_hevc_qpel_filters[3][16]; +void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth); void ff_hevc_dsp_init_arm(HEVCDSPContext *c, const int bit_depth); void ff_hevc_dsp_init_ppc(HEVCDSPContext *c, const int bit_depth); void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth); diff -Nru ffmpeg-4.2.2/libavcodec/hevc.h ffmpeg-4.4/libavcodec/hevc.h --- ffmpeg-4.2.2/libavcodec/hevc.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevc.h 2020-07-11 10:39:30.000000000 +0000 @@ -26,70 +26,70 @@ * T-REC-H.265-201802 */ enum HEVCNALUnitType { - HEVC_NAL_TRAIL_N = 0, - HEVC_NAL_TRAIL_R = 1, - HEVC_NAL_TSA_N = 2, - HEVC_NAL_TSA_R = 3, - HEVC_NAL_STSA_N = 4, - HEVC_NAL_STSA_R = 5, - HEVC_NAL_RADL_N = 6, - HEVC_NAL_RADL_R = 7, - HEVC_NAL_RASL_N = 8, - HEVC_NAL_RASL_R = 9, - HEVC_NAL_VCL_N10 = 10, - HEVC_NAL_VCL_R11 = 11, - HEVC_NAL_VCL_N12 = 12, - HEVC_NAL_VCL_R13 = 13, - HEVC_NAL_VCL_N14 = 14, - HEVC_NAL_VCL_R15 = 15, - HEVC_NAL_BLA_W_LP = 16, - HEVC_NAL_BLA_W_RADL = 17, - HEVC_NAL_BLA_N_LP = 18, - HEVC_NAL_IDR_W_RADL = 19, - HEVC_NAL_IDR_N_LP = 20, - HEVC_NAL_CRA_NUT = 21, - HEVC_NAL_IRAP_VCL22 = 22, - HEVC_NAL_IRAP_VCL23 = 23, - HEVC_NAL_RSV_VCL24 = 24, - HEVC_NAL_RSV_VCL25 = 25, - HEVC_NAL_RSV_VCL26 = 26, - HEVC_NAL_RSV_VCL27 = 27, - HEVC_NAL_RSV_VCL28 = 28, - HEVC_NAL_RSV_VCL29 = 29, - HEVC_NAL_RSV_VCL30 = 30, - HEVC_NAL_RSV_VCL31 = 31, - HEVC_NAL_VPS = 32, - HEVC_NAL_SPS = 33, - HEVC_NAL_PPS = 34, - HEVC_NAL_AUD = 35, - HEVC_NAL_EOS_NUT = 36, - HEVC_NAL_EOB_NUT = 37, - HEVC_NAL_FD_NUT = 38, - HEVC_NAL_SEI_PREFIX = 39, - HEVC_NAL_SEI_SUFFIX = 40, - HEVC_NAL_RSV_NVCL41 = 41, - HEVC_NAL_RSV_NVCL42 = 42, - HEVC_NAL_RSV_NVCL43 = 43, - HEVC_NAL_RSV_NVCL44 = 44, - HEVC_NAL_RSV_NVCL45 = 45, - HEVC_NAL_RSV_NVCL46 = 46, - HEVC_NAL_RSV_NVCL47 = 47, - HEVC_NAL_UNSPEC48 = 48, - HEVC_NAL_UNSPEC49 = 49, - HEVC_NAL_UNSPEC50 = 50, - HEVC_NAL_UNSPEC51 = 51, - HEVC_NAL_UNSPEC52 = 52, - HEVC_NAL_UNSPEC53 = 53, - HEVC_NAL_UNSPEC54 = 54, - HEVC_NAL_UNSPEC55 = 55, - HEVC_NAL_UNSPEC56 = 56, - HEVC_NAL_UNSPEC57 = 57, - HEVC_NAL_UNSPEC58 = 58, - HEVC_NAL_UNSPEC59 = 59, - HEVC_NAL_UNSPEC60 = 60, - HEVC_NAL_UNSPEC61 = 61, - HEVC_NAL_UNSPEC62 = 62, - HEVC_NAL_UNSPEC63 = 63, + HEVC_NAL_TRAIL_N = 0, + HEVC_NAL_TRAIL_R = 1, + HEVC_NAL_TSA_N = 2, + HEVC_NAL_TSA_R = 3, + HEVC_NAL_STSA_N = 4, + HEVC_NAL_STSA_R = 5, + HEVC_NAL_RADL_N = 6, + HEVC_NAL_RADL_R = 7, + HEVC_NAL_RASL_N = 8, + HEVC_NAL_RASL_R = 9, + HEVC_NAL_VCL_N10 = 10, + HEVC_NAL_VCL_R11 = 11, + HEVC_NAL_VCL_N12 = 12, + HEVC_NAL_VCL_R13 = 13, + HEVC_NAL_VCL_N14 = 14, + HEVC_NAL_VCL_R15 = 15, + HEVC_NAL_BLA_W_LP = 16, + HEVC_NAL_BLA_W_RADL = 17, + HEVC_NAL_BLA_N_LP = 18, + HEVC_NAL_IDR_W_RADL = 19, + HEVC_NAL_IDR_N_LP = 20, + HEVC_NAL_CRA_NUT = 21, + HEVC_NAL_RSV_IRAP_VCL22 = 22, + HEVC_NAL_RSV_IRAP_VCL23 = 23, + HEVC_NAL_RSV_VCL24 = 24, + HEVC_NAL_RSV_VCL25 = 25, + HEVC_NAL_RSV_VCL26 = 26, + HEVC_NAL_RSV_VCL27 = 27, + HEVC_NAL_RSV_VCL28 = 28, + HEVC_NAL_RSV_VCL29 = 29, + HEVC_NAL_RSV_VCL30 = 30, + HEVC_NAL_RSV_VCL31 = 31, + HEVC_NAL_VPS = 32, + HEVC_NAL_SPS = 33, + HEVC_NAL_PPS = 34, + HEVC_NAL_AUD = 35, + HEVC_NAL_EOS_NUT = 36, + HEVC_NAL_EOB_NUT = 37, + HEVC_NAL_FD_NUT = 38, + HEVC_NAL_SEI_PREFIX = 39, + HEVC_NAL_SEI_SUFFIX = 40, + HEVC_NAL_RSV_NVCL41 = 41, + HEVC_NAL_RSV_NVCL42 = 42, + HEVC_NAL_RSV_NVCL43 = 43, + HEVC_NAL_RSV_NVCL44 = 44, + HEVC_NAL_RSV_NVCL45 = 45, + HEVC_NAL_RSV_NVCL46 = 46, + HEVC_NAL_RSV_NVCL47 = 47, + HEVC_NAL_UNSPEC48 = 48, + HEVC_NAL_UNSPEC49 = 49, + HEVC_NAL_UNSPEC50 = 50, + HEVC_NAL_UNSPEC51 = 51, + HEVC_NAL_UNSPEC52 = 52, + HEVC_NAL_UNSPEC53 = 53, + HEVC_NAL_UNSPEC54 = 54, + HEVC_NAL_UNSPEC55 = 55, + HEVC_NAL_UNSPEC56 = 56, + HEVC_NAL_UNSPEC57 = 57, + HEVC_NAL_UNSPEC58 = 58, + HEVC_NAL_UNSPEC59 = 59, + HEVC_NAL_UNSPEC60 = 60, + HEVC_NAL_UNSPEC61 = 61, + HEVC_NAL_UNSPEC62 = 62, + HEVC_NAL_UNSPEC63 = 63, }; enum HEVCSliceType { diff -Nru ffmpeg-4.2.2/libavcodec/hevc_mp4toannexb_bsf.c ffmpeg-4.4/libavcodec/hevc_mp4toannexb_bsf.c --- ffmpeg-4.2.2/libavcodec/hevc_mp4toannexb_bsf.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevc_mp4toannexb_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "bytestream.h" #include "hevc.h" @@ -141,9 +142,18 @@ int nalu_type; int is_irap, add_extradata, extra_size, prev_size; + if (bytestream2_get_bytes_left(&gb) < s->length_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } for (i = 0; i < s->length_size; i++) nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb); + if (nalu_size < 2 || nalu_size > bytestream2_get_bytes_left(&gb)) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f; /* prepend extradata to IRAP frames */ @@ -152,8 +162,7 @@ extra_size = add_extradata * ctx->par_out->extradata_size; got_irap |= is_irap; - if (SIZE_MAX - nalu_size < 4 || - SIZE_MAX - 4 - nalu_size < extra_size) { + if (FFMIN(INT_MAX, SIZE_MAX) < 4ULL + nalu_size + extra_size) { ret = AVERROR_INVALIDDATA; goto fail; } @@ -164,7 +173,7 @@ if (ret < 0) goto fail; - if (add_extradata) + if (extra_size) memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size); AV_WB32(out->data + prev_size + extra_size, 1); bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, nalu_size); diff -Nru ffmpeg-4.2.2/libavcodec/hevc_mvs.c ffmpeg-4.4/libavcodec/hevc_mvs.c --- ffmpeg-4.2.2/libavcodec/hevc_mvs.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevc_mvs.c 2021-04-08 21:28:39.000000000 +0000 @@ -48,9 +48,9 @@ lc->na.cand_up = (lc->ctb_up_flag || y0b); lc->na.cand_left = (lc->ctb_left_flag || x0b); - lc->na.cand_up_left = (!x0b && !y0b) ? lc->ctb_up_left_flag : lc->na.cand_left && lc->na.cand_up; + lc->na.cand_up_left = (x0b || y0b) ? lc->na.cand_left && lc->na.cand_up : lc->ctb_up_left_flag; lc->na.cand_up_right_sap = - ((x0b + nPbW) == (1 << s->ps.sps->log2_ctb_size)) ? + (x0b + nPbW == 1 << s->ps.sps->log2_ctb_size) ? lc->ctb_up_right_flag && !y0b : lc->na.cand_up; lc->na.cand_up_right = lc->na.cand_up_right_sap diff -Nru ffmpeg-4.2.2/libavcodec/hevc_parse.c ffmpeg-4.4/libavcodec/hevc_parse.c --- ffmpeg-4.2.2/libavcodec/hevc_parse.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevc_parse.c 2020-07-11 10:39:30.000000000 +0000 @@ -37,6 +37,8 @@ for (i = 0; i < pkt.nb_nals; i++) { H2645NAL *nal = &pkt.nals[i]; + if (nal->nuh_layer_id > 0) + continue; /* ignore everything except parameter sets and VCL NALUs */ switch (nal->type) { diff -Nru ffmpeg-4.2.2/libavcodec/hevc_parser.c ffmpeg-4.4/libavcodec/hevc_parser.c --- ffmpeg-4.2.2/libavcodec/hevc_parser.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevc_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -42,7 +42,6 @@ H2645Packet pkt; HEVCParamSets ps; HEVCSEI sei; - SliceHeader sh; int is_avc; int nal_length_size; @@ -58,26 +57,28 @@ HEVCParserContext *ctx = s->priv_data; HEVCParamSets *ps = &ctx->ps; HEVCSEI *sei = &ctx->sei; - SliceHeader *sh = &ctx->sh; GetBitContext *gb = &nal->gb; const HEVCWindow *ow; int i, num = 0, den = 0; - sh->first_slice_in_pic_flag = get_bits1(gb); + unsigned int pps_id, first_slice_in_pic_flag, dependent_slice_segment_flag; + enum HEVCSliceType slice_type; + + first_slice_in_pic_flag = get_bits1(gb); s->picture_structure = sei->picture_timing.picture_struct; s->field_order = sei->picture_timing.picture_struct; if (IS_IRAP_NAL(nal)) { s->key_frame = 1; - sh->no_output_of_prior_pics_flag = get_bits1(gb); + skip_bits1(gb); // no_output_of_prior_pics_flag } - sh->pps_id = get_ue_golomb(gb); - if (sh->pps_id >= HEVC_MAX_PPS_COUNT || !ps->pps_list[sh->pps_id]) { - av_log(avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", sh->pps_id); + pps_id = get_ue_golomb(gb); + if (pps_id >= HEVC_MAX_PPS_COUNT || !ps->pps_list[pps_id]) { + av_log(avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", pps_id); return AVERROR_INVALIDDATA; } - ps->pps = (HEVCPPS*)ps->pps_list[sh->pps_id]->data; + ps->pps = (HEVCPPS*)ps->pps_list[pps_id]->data; if (ps->pps->sps_id >= HEVC_MAX_SPS_COUNT || !ps->sps_list[ps->pps->sps_id]) { av_log(avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", ps->pps->sps_id); @@ -109,51 +110,53 @@ av_reduce(&avctx->framerate.den, &avctx->framerate.num, num, den, 1 << 30); - if (!sh->first_slice_in_pic_flag) { + if (!first_slice_in_pic_flag) { + unsigned int slice_segment_addr; int slice_address_length; if (ps->pps->dependent_slice_segments_enabled_flag) - sh->dependent_slice_segment_flag = get_bits1(gb); + dependent_slice_segment_flag = get_bits1(gb); else - sh->dependent_slice_segment_flag = 0; + dependent_slice_segment_flag = 0; slice_address_length = av_ceil_log2_c(ps->sps->ctb_width * ps->sps->ctb_height); - sh->slice_segment_addr = get_bitsz(gb, slice_address_length); - if (sh->slice_segment_addr >= ps->sps->ctb_width * ps->sps->ctb_height) { + slice_segment_addr = get_bitsz(gb, slice_address_length); + if (slice_segment_addr >= ps->sps->ctb_width * ps->sps->ctb_height) { av_log(avctx, AV_LOG_ERROR, "Invalid slice segment address: %u.\n", - sh->slice_segment_addr); + slice_segment_addr); return AVERROR_INVALIDDATA; } } else - sh->dependent_slice_segment_flag = 0; + dependent_slice_segment_flag = 0; - if (sh->dependent_slice_segment_flag) + if (dependent_slice_segment_flag) return 0; /* break; */ for (i = 0; i < ps->pps->num_extra_slice_header_bits; i++) skip_bits(gb, 1); // slice_reserved_undetermined_flag[] - sh->slice_type = get_ue_golomb(gb); - if (!(sh->slice_type == HEVC_SLICE_I || sh->slice_type == HEVC_SLICE_P || - sh->slice_type == HEVC_SLICE_B)) { + slice_type = get_ue_golomb_31(gb); + if (!(slice_type == HEVC_SLICE_I || slice_type == HEVC_SLICE_P || + slice_type == HEVC_SLICE_B)) { av_log(avctx, AV_LOG_ERROR, "Unknown slice type: %d.\n", - sh->slice_type); + slice_type); return AVERROR_INVALIDDATA; } - s->pict_type = sh->slice_type == HEVC_SLICE_B ? AV_PICTURE_TYPE_B : - sh->slice_type == HEVC_SLICE_P ? AV_PICTURE_TYPE_P : - AV_PICTURE_TYPE_I; + s->pict_type = slice_type == HEVC_SLICE_B ? AV_PICTURE_TYPE_B : + slice_type == HEVC_SLICE_P ? AV_PICTURE_TYPE_P : + AV_PICTURE_TYPE_I; if (ps->pps->output_flag_present_flag) - sh->pic_output_flag = get_bits1(gb); + skip_bits1(gb); // pic_output_flag if (ps->sps->separate_colour_plane_flag) - sh->colour_plane_id = get_bits(gb, 2); + skip_bits(gb, 2); // colour_plane_id if (!IS_IDR_NAL(nal)) { - sh->pic_order_cnt_lsb = get_bits(gb, ps->sps->log2_max_poc_lsb); - s->output_picture_number = ctx->poc = ff_hevc_compute_poc(ps->sps, ctx->pocTid0, sh->pic_order_cnt_lsb, nal->type); + int pic_order_cnt_lsb = get_bits(gb, ps->sps->log2_max_poc_lsb); + s->output_picture_number = ctx->poc = + ff_hevc_compute_poc(ps->sps, ctx->pocTid0, pic_order_cnt_lsb, nal->type); } else s->output_picture_number = ctx->poc = 0; @@ -202,6 +205,9 @@ H2645NAL *nal = &ctx->pkt.nals[i]; GetBitContext *gb = &nal->gb; + if (nal->nuh_layer_id > 0) + continue; + switch (nal->type) { case HEVC_NAL_VPS: ff_hevc_decode_nal_vps(gb, avctx, ps); @@ -232,6 +238,11 @@ case HEVC_NAL_RADL_R: case HEVC_NAL_RASL_N: case HEVC_NAL_RASL_R: + if (ctx->sei.picture_timing.picture_struct == HEVC_SEI_PIC_STRUCT_FRAME_DOUBLING) { + s->repeat_pict = 1; + } else if (ctx->sei.picture_timing.picture_struct == HEVC_SEI_PIC_STRUCT_FRAME_TRIPLING) { + s->repeat_pict = 2; + } ret = hevc_parse_slice_header(s, nal, avctx); if (ret) return ret; diff -Nru ffmpeg-4.2.2/libavcodec/hevcpred_template.c ffmpeg-4.4/libavcodec/hevcpred_template.c --- ffmpeg-4.2.2/libavcodec/hevcpred_template.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevcpred_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -83,6 +83,7 @@ int y = y0 >> vshift; int x_tb = (x0 >> s->ps.sps->log2_min_tb_size) & s->ps.sps->tb_mask; int y_tb = (y0 >> s->ps.sps->log2_min_tb_size) & s->ps.sps->tb_mask; + int spin = c_idx && !size_in_tbs_v && ((2 * y0) & (1 << s->ps.sps->log2_min_tb_size)); int cur_tb_addr = MIN_TB_ADDR_ZS(x_tb, y_tb); @@ -103,11 +104,11 @@ pixel *top = top_array + 1; pixel *filtered_left = filtered_left_array + 1; pixel *filtered_top = filtered_top_array + 1; - int cand_bottom_left = lc->na.cand_bottom_left && cur_tb_addr > MIN_TB_ADDR_ZS( x_tb - 1, (y_tb + size_in_tbs_v) & s->ps.sps->tb_mask); + int cand_bottom_left = lc->na.cand_bottom_left && cur_tb_addr > MIN_TB_ADDR_ZS( x_tb - 1, (y_tb + size_in_tbs_v + spin) & s->ps.sps->tb_mask); int cand_left = lc->na.cand_left; int cand_up_left = lc->na.cand_up_left; int cand_up = lc->na.cand_up; - int cand_up_right = lc->na.cand_up_right && cur_tb_addr > MIN_TB_ADDR_ZS((x_tb + size_in_tbs_h) & s->ps.sps->tb_mask, y_tb - 1); + int cand_up_right = lc->na.cand_up_right && !spin && cur_tb_addr > MIN_TB_ADDR_ZS((x_tb + size_in_tbs_h) & s->ps.sps->tb_mask, y_tb - 1); int bottom_left_size = (FFMIN(y0 + 2 * size_in_luma_v, s->ps.sps->height) - (y0 + size_in_luma_v)) >> vshift; @@ -213,7 +214,7 @@ while (j < size_max_x && !IS_INTRA(j, -1)) j++; if (j > 0) - if (x0 > 0) { + if (cand_up_left) { EXTEND_LEFT_CIP(top, j, j + 1); } else { EXTEND_LEFT_CIP(top, j, j); diff -Nru ffmpeg-4.2.2/libavcodec/hevc_ps.c ffmpeg-4.4/libavcodec/hevc_ps.c --- ffmpeg-4.2.2/libavcodec/hevc_ps.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevc_ps.c 2021-04-08 21:28:39.000000000 +0000 @@ -267,7 +267,7 @@ { int i; - if (get_bits_left(gb) < 2+1+5 + 32 + 4 + 16 + 16 + 12) + if (get_bits_left(gb) < 2+1+5 + 32 + 4 + 43 + 1) return -1; ptl->profile_space = get_bits(gb, 2); @@ -295,9 +295,43 @@ ptl->non_packed_constraint_flag = get_bits1(gb); ptl->frame_only_constraint_flag = get_bits1(gb); - skip_bits(gb, 16); // XXX_reserved_zero_44bits[0..15] - skip_bits(gb, 16); // XXX_reserved_zero_44bits[16..31] - skip_bits(gb, 12); // XXX_reserved_zero_44bits[32..43] +#define check_profile_idc(idc) \ + ptl->profile_idc == idc || ptl->profile_compatibility_flag[idc] + + if (check_profile_idc(4) || check_profile_idc(5) || check_profile_idc(6) || + check_profile_idc(7) || check_profile_idc(8) || check_profile_idc(9) || + check_profile_idc(10)) { + + ptl->max_12bit_constraint_flag = get_bits1(gb); + ptl->max_10bit_constraint_flag = get_bits1(gb); + ptl->max_8bit_constraint_flag = get_bits1(gb); + ptl->max_422chroma_constraint_flag = get_bits1(gb); + ptl->max_420chroma_constraint_flag = get_bits1(gb); + ptl->max_monochrome_constraint_flag = get_bits1(gb); + ptl->intra_constraint_flag = get_bits1(gb); + ptl->one_picture_only_constraint_flag = get_bits1(gb); + ptl->lower_bit_rate_constraint_flag = get_bits1(gb); + + if (check_profile_idc(5) || check_profile_idc(9) || check_profile_idc(10)) { + ptl->max_14bit_constraint_flag = get_bits1(gb); + skip_bits_long(gb, 33); // XXX_reserved_zero_33bits[0..32] + } else { + skip_bits_long(gb, 34); // XXX_reserved_zero_34bits[0..33] + } + } else if (check_profile_idc(2)) { + skip_bits(gb, 7); + ptl->one_picture_only_constraint_flag = get_bits1(gb); + skip_bits_long(gb, 35); // XXX_reserved_zero_35bits[0..34] + } else { + skip_bits_long(gb, 43); // XXX_reserved_zero_43bits[0..42] + } + + if (check_profile_idc(1) || check_profile_idc(2) || check_profile_idc(3) || + check_profile_idc(4) || check_profile_idc(5) || check_profile_idc(9)) + ptl->inbld_flag = get_bits1(gb); + else + skip_bits1(gb); +#undef check_profile_idc return 0; } @@ -448,10 +482,6 @@ memcpy(vps->data, gb->buffer, vps->data_size); vps_id = get_bits(gb, 4); - if (vps_id >= HEVC_MAX_VPS_COUNT) { - av_log(avctx, AV_LOG_ERROR, "VPS id out of range: %d\n", vps_id); - goto err; - } if (get_bits(gb, 2) != 3) { // vps_reserved_three_2bits av_log(avctx, AV_LOG_ERROR, "vps_reserved_three_2bits is not three\n"); @@ -753,7 +783,7 @@ static int scaling_list_data(GetBitContext *gb, AVCodecContext *avctx, ScalingList *sl, HEVCSPS *sps) { uint8_t scaling_list_pred_mode_flag; - int32_t scaling_list_dc_coef[2][6]; + uint8_t scaling_list_dc_coef[2][6]; int size_id, matrix_id, pos; int i; @@ -786,7 +816,11 @@ next_coef = 8; coef_num = FFMIN(64, 1 << (4 + (size_id << 1))); if (size_id > 1) { - scaling_list_dc_coef[size_id - 2][matrix_id] = get_se_golomb(gb) + 8; + int scaling_list_coeff_minus8 = get_se_golomb(gb); + if (scaling_list_coeff_minus8 < -7 || + scaling_list_coeff_minus8 > 247) + return AVERROR_INVALIDDATA; + scaling_list_dc_coef[size_id - 2][matrix_id] = scaling_list_coeff_minus8 + 8; next_coef = scaling_list_dc_coef[size_id - 2][matrix_id]; sl->sl_dc[size_id - 2][matrix_id] = next_coef; } @@ -883,10 +917,6 @@ // Coded parameters sps->vps_id = get_bits(gb, 4); - if (sps->vps_id >= HEVC_MAX_VPS_COUNT) { - av_log(avctx, AV_LOG_ERROR, "VPS id out of range: %d\n", sps->vps_id); - return AVERROR_INVALIDDATA; - } if (vps_list && !vps_list[sps->vps_id]) { av_log(avctx, AV_LOG_ERROR, "VPS %d does not exist\n", diff -Nru ffmpeg-4.2.2/libavcodec/hevc_ps_enc.c ffmpeg-4.4/libavcodec/hevc_ps_enc.c --- ffmpeg-4.2.2/libavcodec/hevc_ps_enc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevc_ps_enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -113,10 +113,9 @@ put_bits(&pb, 1, 0); // extension flag put_bits(&pb, 1, 1); // stop bit - avpriv_align_put_bits(&pb); + flush_put_bits(&pb); data_size = put_bits_count(&pb) / 8; - flush_put_bits(&pb); return data_size; } diff -Nru ffmpeg-4.2.2/libavcodec/hevc_ps.h ffmpeg-4.4/libavcodec/hevc_ps.h --- ffmpeg-4.2.2/libavcodec/hevc_ps.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevc_ps.h 2020-07-11 10:39:30.000000000 +0000 @@ -39,89 +39,6 @@ uint8_t used[32]; } ShortTermRPS; -typedef struct LongTermRPS { - int poc[32]; - uint8_t used[32]; - uint8_t nb_refs; -} LongTermRPS; - -typedef struct SliceHeader { - unsigned int pps_id; - - ///< address (in raster order) of the first block in the current slice segment - unsigned int slice_segment_addr; - ///< address (in raster order) of the first block in the current slice - unsigned int slice_addr; - - enum HEVCSliceType slice_type; - - int pic_order_cnt_lsb; - - uint8_t first_slice_in_pic_flag; - uint8_t dependent_slice_segment_flag; - uint8_t pic_output_flag; - uint8_t colour_plane_id; - - ///< RPS coded in the slice header itself is stored here - int short_term_ref_pic_set_sps_flag; - int short_term_ref_pic_set_size; - ShortTermRPS slice_rps; - const ShortTermRPS *short_term_rps; - int long_term_ref_pic_set_size; - LongTermRPS long_term_rps; - unsigned int list_entry_lx[2][32]; - - uint8_t rpl_modification_flag[2]; - uint8_t no_output_of_prior_pics_flag; - uint8_t slice_temporal_mvp_enabled_flag; - - unsigned int nb_refs[2]; - - uint8_t slice_sample_adaptive_offset_flag[3]; - uint8_t mvd_l1_zero_flag; - - uint8_t cabac_init_flag; - uint8_t disable_deblocking_filter_flag; ///< slice_header_disable_deblocking_filter_flag - uint8_t slice_loop_filter_across_slices_enabled_flag; - uint8_t collocated_list; - - unsigned int collocated_ref_idx; - - int slice_qp_delta; - int slice_cb_qp_offset; - int slice_cr_qp_offset; - - uint8_t cu_chroma_qp_offset_enabled_flag; - - int beta_offset; ///< beta_offset_div2 * 2 - int tc_offset; ///< tc_offset_div2 * 2 - - unsigned int max_num_merge_cand; ///< 5 - 5_minus_max_num_merge_cand - - unsigned *entry_point_offset; - int * offset; - int * size; - int num_entry_point_offsets; - - int8_t slice_qp; - - uint8_t luma_log2_weight_denom; - int16_t chroma_log2_weight_denom; - - int16_t luma_weight_l0[16]; - int16_t chroma_weight_l0[16][2]; - int16_t chroma_weight_l1[16][2]; - int16_t luma_weight_l1[16]; - - int16_t luma_offset_l0[16]; - int16_t chroma_offset_l0[16][2]; - - int16_t luma_offset_l1[16]; - int16_t chroma_offset_l1[16][2]; - - int slice_ctb_addr_rs; -} SliceHeader; - typedef struct HEVCWindow { unsigned int left_offset; unsigned int right_offset; @@ -177,11 +94,22 @@ uint8_t tier_flag; uint8_t profile_idc; uint8_t profile_compatibility_flag[32]; - uint8_t level_idc; uint8_t progressive_source_flag; uint8_t interlaced_source_flag; uint8_t non_packed_constraint_flag; uint8_t frame_only_constraint_flag; + uint8_t max_12bit_constraint_flag; + uint8_t max_10bit_constraint_flag; + uint8_t max_8bit_constraint_flag; + uint8_t max_422chroma_constraint_flag; + uint8_t max_420chroma_constraint_flag; + uint8_t max_monochrome_constraint_flag; + uint8_t intra_constraint_flag; + uint8_t one_picture_only_constraint_flag; + uint8_t lower_bit_rate_constraint_flag; + uint8_t max_14bit_constraint_flag; + uint8_t inbld_flag; + uint8_t level_idc; } PTLCommon; typedef struct PTL { diff -Nru ffmpeg-4.2.2/libavcodec/hevc_refs.c ffmpeg-4.4/libavcodec/hevc_refs.c --- ffmpeg-4.2.2/libavcodec/hevc_refs.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevc_refs.c 2020-07-11 10:39:30.000000000 +0000 @@ -358,23 +358,15 @@ return 0; } -static HEVCFrame *find_ref_idx(HEVCContext *s, int poc) +static HEVCFrame *find_ref_idx(HEVCContext *s, int poc, uint8_t use_msb) { + int mask = use_msb ? ~0 : (1 << s->ps.sps->log2_max_poc_lsb) - 1; int i; - int LtMask = (1 << s->ps.sps->log2_max_poc_lsb) - 1; - - for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { - HEVCFrame *ref = &s->DPB[i]; - if (ref->frame->buf[0] && (ref->sequence == s->seq_decode)) { - if ((ref->poc & LtMask) == poc) - return ref; - } - } for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { HEVCFrame *ref = &s->DPB[i]; if (ref->frame->buf[0] && ref->sequence == s->seq_decode) { - if (ref->poc == poc || (ref->poc & LtMask) == poc) + if ((ref->poc & mask) == poc) return ref; } } @@ -427,9 +419,9 @@ /* add a reference with the given poc to the list and mark it as used in DPB */ static int add_candidate_ref(HEVCContext *s, RefPicList *list, - int poc, int ref_flag) + int poc, int ref_flag, uint8_t use_msb) { - HEVCFrame *ref = find_ref_idx(s, poc); + HEVCFrame *ref = find_ref_idx(s, poc, use_msb); if (ref == s->ref || list->nb_refs >= HEVC_MAX_REFS) return AVERROR_INVALIDDATA; @@ -485,7 +477,7 @@ else list = ST_CURR_AFT; - ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_SHORT_REF); + ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_SHORT_REF, 1); if (ret < 0) goto fail; } @@ -495,7 +487,7 @@ int poc = long_rps->poc[i]; int list = long_rps->used[i] ? LT_CURR : LT_FOLL; - ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_LONG_REF); + ret = add_candidate_ref(s, &rps[list], poc, HEVC_FRAME_FLAG_LONG_REF, long_rps->poc_msb_present[i]); if (ret < 0) goto fail; } diff -Nru ffmpeg-4.2.2/libavcodec/hevc_sei.c ffmpeg-4.4/libavcodec/hevc_sei.c --- ffmpeg-4.2.2/libavcodec/hevc_sei.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevc_sei.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "atsc_a53.h" +#include "dynamic_hdr10_plus.h" #include "golomb.h" #include "hevc_ps.h" #include "hevc_sei.h" @@ -76,8 +78,8 @@ static int decode_nal_sei_content_light_info(HEVCSEIContentLight *s, GetBitContext *gb) { // Max and average light levels - s->max_content_light_level = get_bits_long(gb, 16); - s->max_pic_average_light_level = get_bits_long(gb, 16); + s->max_content_light_level = get_bits(gb, 16); + s->max_pic_average_light_level = get_bits(gb, 16); // As this SEI message comes before the first frame that references it, // initialize the flag to 2 and decrement on IRAP access unit so it // persists for the coded video sequence (e.g., between two IRAPs) @@ -144,6 +146,12 @@ } else if (pic_struct == 1 || pic_struct == 9 || pic_struct == 11) { av_log(logctx, AV_LOG_DEBUG, "TOP Field\n"); h->picture_struct = AV_PICTURE_STRUCTURE_TOP_FIELD; + } else if (pic_struct == 7) { + av_log(logctx, AV_LOG_DEBUG, "Frame/Field Doubling\n"); + h->picture_struct = HEVC_SEI_PIC_STRUCT_FRAME_DOUBLING; + } else if (pic_struct == 8) { + av_log(logctx, AV_LOG_DEBUG, "Frame/Field Tripling\n"); + h->picture_struct = HEVC_SEI_PIC_STRUCT_FRAME_TRIPLING; } get_bits(gb, 2); // source_scan_type get_bits(gb, 1); // duplicate_flag @@ -158,82 +166,150 @@ static int decode_registered_user_data_closed_caption(HEVCSEIA53Caption *s, GetBitContext *gb, int size) { - int flag; - int user_data_type_code; - int cc_count; + int ret; if (size < 3) - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; - user_data_type_code = get_bits(gb, 8); - if (user_data_type_code == 0x3) { - skip_bits(gb, 1); // reserved - - flag = get_bits(gb, 1); // process_cc_data_flag - if (flag) { - skip_bits(gb, 1); - cc_count = get_bits(gb, 5); - skip_bits(gb, 8); // reserved - size -= 2; - - if (cc_count && size >= cc_count * 3) { - const uint64_t new_size = (s->a53_caption_size + cc_count - * UINT64_C(3)); - int i, ret; - - if (new_size > INT_MAX) - return AVERROR(EINVAL); - - /* Allow merging of the cc data from two fields. */ - ret = av_reallocp(&s->a53_caption, new_size); - if (ret < 0) - return ret; - - for (i = 0; i < cc_count; i++) { - s->a53_caption[s->a53_caption_size++] = get_bits(gb, 8); - s->a53_caption[s->a53_caption_size++] = get_bits(gb, 8); - s->a53_caption[s->a53_caption_size++] = get_bits(gb, 8); - } - skip_bits(gb, 8); // marker_bits - } - } - } else { - int i; - for (i = 0; i < size - 1; i++) - skip_bits(gb, 8); + ret = ff_parse_a53_cc(&s->buf_ref, gb->buffer + get_bits_count(gb) / 8, size); + + if (ret < 0) + return ret; + + skip_bits_long(gb, size * 8); + + return 0; +} + +static int decode_nal_sei_user_data_unregistered(HEVCSEIUnregistered *s, GetBitContext *gb, + int size) +{ + AVBufferRef *buf_ref, **tmp; + + if (size < 16 || size >= INT_MAX - 1) + return AVERROR_INVALIDDATA; + + tmp = av_realloc_array(s->buf_ref, s->nb_buf_ref + 1, sizeof(*s->buf_ref)); + if (!tmp) + return AVERROR(ENOMEM); + s->buf_ref = tmp; + + buf_ref = av_buffer_alloc(size + 1); + if (!buf_ref) + return AVERROR(ENOMEM); + + for (int i = 0; i < size; i++) + buf_ref->data[i] = get_bits(gb, 8); + buf_ref->data[size] = 0; + buf_ref->size = size; + s->buf_ref[s->nb_buf_ref++] = buf_ref; + + return 0; +} + +static int decode_registered_user_data_dynamic_hdr_plus(HEVCSEIDynamicHDRPlus *s, + GetBitContext *gb, int size) +{ + size_t meta_size; + int err; + AVDynamicHDRPlus *metadata = av_dynamic_hdr_plus_alloc(&meta_size); + if (!metadata) + return AVERROR(ENOMEM); + + err = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(metadata, + gb->buffer + get_bits_count(gb) / 8, size); + if (err < 0) { + av_free(metadata); + return err; + } + + av_buffer_unref(&s->info); + s->info = av_buffer_create((uint8_t *)metadata, meta_size, NULL, NULL, 0); + if (!s->info) { + av_free(metadata); + return AVERROR(ENOMEM); } + skip_bits_long(gb, size * 8); + return 0; } static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCSEI *s, GetBitContext *gb, - int size) + void *logctx, int size) { - uint32_t country_code; - uint32_t user_identifier; + int country_code, provider_code; - if (size < 7) - return AVERROR(EINVAL); - size -= 7; + if (size < 3) + return AVERROR_INVALIDDATA; + size -= 3; country_code = get_bits(gb, 8); if (country_code == 0xFF) { + if (size < 1) + return AVERROR_INVALIDDATA; + skip_bits(gb, 8); size--; } - skip_bits(gb, 8); - skip_bits(gb, 8); + if (country_code != 0xB5) { // usa_country_code + av_log(logctx, AV_LOG_VERBOSE, + "Unsupported User Data Registered ITU-T T35 SEI message (country_code = %d)\n", + country_code); + goto end; + } + + provider_code = get_bits(gb, 16); + + switch (provider_code) { + case 0x3C: { // smpte_provider_code + // A/341 Amendment - 2094-40 + const uint16_t smpte2094_40_provider_oriented_code = 0x0001; + const uint8_t smpte2094_40_application_identifier = 0x04; + uint16_t provider_oriented_code; + uint8_t application_identifier; - user_identifier = get_bits_long(gb, 32); + if (size < 3) + return AVERROR_INVALIDDATA; + size -= 3; - switch (user_identifier) { + provider_oriented_code = get_bits(gb, 16); + application_identifier = get_bits(gb, 8); + if (provider_oriented_code == smpte2094_40_provider_oriented_code && + application_identifier == smpte2094_40_application_identifier) { + return decode_registered_user_data_dynamic_hdr_plus(&s->dynamic_hdr_plus, gb, size); + } + break; + } + case 0x31: { // atsc_provider_code + uint32_t user_identifier; + + if (size < 4) + return AVERROR_INVALIDDATA; + size -= 4; + + user_identifier = get_bits_long(gb, 32); + switch (user_identifier) { case MKBETAG('G', 'A', '9', '4'): return decode_registered_user_data_closed_caption(&s->a53_caption, gb, size); default: - skip_bits_long(gb, size * 8); + av_log(logctx, AV_LOG_VERBOSE, + "Unsupported User Data Registered ITU-T T35 SEI message (atsc user_identifier = 0x%04x)\n", + user_identifier); break; + } + break; + } + default: + av_log(logctx, AV_LOG_VERBOSE, + "Unsupported User Data Registered ITU-T T35 SEI message (provider_code = %d)\n", + provider_code); + break; } + +end: + skip_bits_long(gb, size * 8); return 0; } @@ -273,28 +349,79 @@ return 0; } +static int decode_nal_sei_timecode(HEVCSEITimeCode *s, GetBitContext *gb) +{ + s->num_clock_ts = get_bits(gb, 2); + + for (int i = 0; i < s->num_clock_ts; i++) { + s->clock_timestamp_flag[i] = get_bits(gb, 1); + + if (s->clock_timestamp_flag[i]) { + s->units_field_based_flag[i] = get_bits(gb, 1); + s->counting_type[i] = get_bits(gb, 5); + s->full_timestamp_flag[i] = get_bits(gb, 1); + s->discontinuity_flag[i] = get_bits(gb, 1); + s->cnt_dropped_flag[i] = get_bits(gb, 1); + + s->n_frames[i] = get_bits(gb, 9); + + if (s->full_timestamp_flag[i]) { + s->seconds_value[i] = av_clip(get_bits(gb, 6), 0, 59); + s->minutes_value[i] = av_clip(get_bits(gb, 6), 0, 59); + s->hours_value[i] = av_clip(get_bits(gb, 5), 0, 23); + } else { + s->seconds_flag[i] = get_bits(gb, 1); + if (s->seconds_flag[i]) { + s->seconds_value[i] = av_clip(get_bits(gb, 6), 0, 59); + s->minutes_flag[i] = get_bits(gb, 1); + if (s->minutes_flag[i]) { + s->minutes_value[i] = av_clip(get_bits(gb, 6), 0, 59); + s->hours_flag[i] = get_bits(gb, 1); + if (s->hours_flag[i]) { + s->hours_value[i] = av_clip(get_bits(gb, 5), 0, 23); + } + } + } + } + + s->time_offset_length[i] = get_bits(gb, 5); + if (s->time_offset_length[i] > 0) { + s->time_offset_value[i] = get_bits(gb, s->time_offset_length[i]); + } + } + } + + s->present = 1; + return 0; +} + + static int decode_nal_sei_prefix(GetBitContext *gb, void *logctx, HEVCSEI *s, const HEVCParamSets *ps, int type, int size) { switch (type) { case 256: // Mismatched value from HM 8.1 return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gb); - case HEVC_SEI_TYPE_FRAME_PACKING: + case SEI_TYPE_FRAME_PACKING_ARRANGEMENT: return decode_nal_sei_frame_packing_arrangement(&s->frame_packing, gb); - case HEVC_SEI_TYPE_DISPLAY_ORIENTATION: + case SEI_TYPE_DISPLAY_ORIENTATION: return decode_nal_sei_display_orientation(&s->display_orientation, gb); - case HEVC_SEI_TYPE_PICTURE_TIMING: + case SEI_TYPE_PIC_TIMING: return decode_nal_sei_pic_timing(s, gb, ps, logctx, size); - case HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO: + case SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME: return decode_nal_sei_mastering_display_info(&s->mastering_display, gb); - case HEVC_SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO: + case SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO: return decode_nal_sei_content_light_info(&s->content_light, gb); - case HEVC_SEI_TYPE_ACTIVE_PARAMETER_SETS: + case SEI_TYPE_ACTIVE_PARAMETER_SETS: return decode_nal_sei_active_parameter_sets(s, gb, logctx); - case HEVC_SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35: - return decode_nal_sei_user_data_registered_itu_t_t35(s, gb, size); - case HEVC_SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS: + case SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35: + return decode_nal_sei_user_data_registered_itu_t_t35(s, gb, logctx, size); + case SEI_TYPE_USER_DATA_UNREGISTERED: + return decode_nal_sei_user_data_unregistered(&s->unregistered, gb, size); + case SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS: return decode_nal_sei_alternative_transfer(&s->alternative_transfer, gb); + case SEI_TYPE_TIME_CODE: + return decode_nal_sei_timecode(&s->timecode, gb); default: av_log(logctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type); skip_bits_long(gb, 8 * size); @@ -306,7 +433,7 @@ int type, int size) { switch (type) { - case HEVC_SEI_TYPE_DECODED_PICTURE_HASH: + case SEI_TYPE_DECODED_PICTURE_HASH: return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gb); default: av_log(logctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", type); @@ -336,6 +463,8 @@ byte = get_bits(gb, 8); payload_size += byte; } + if (get_bits_left(gb) < 8LL*payload_size) + return AVERROR_INVALIDDATA; if (nal_unit_type == HEVC_NAL_SEI_PREFIX) { return decode_nal_sei_prefix(gb, logctx, s, ps, payload_type, payload_size); } else { /* nal_unit_type == NAL_SEI_SUFFIX */ @@ -363,6 +492,11 @@ void ff_hevc_reset_sei(HEVCSEI *s) { - s->a53_caption.a53_caption_size = 0; - av_freep(&s->a53_caption.a53_caption); + av_buffer_unref(&s->a53_caption.buf_ref); + + for (int i = 0; i < s->unregistered.nb_buf_ref; i++) + av_buffer_unref(&s->unregistered.buf_ref[i]); + s->unregistered.nb_buf_ref = 0; + av_freep(&s->unregistered.buf_ref); + av_buffer_unref(&s->dynamic_hdr_plus.info); } diff -Nru ffmpeg-4.2.2/libavcodec/hevc_sei.h ffmpeg-4.4/libavcodec/hevc_sei.h --- ffmpeg-4.2.2/libavcodec/hevc_sei.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hevc_sei.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,40 +24,13 @@ #include #include "get_bits.h" +#include "sei.h" + -/** - * SEI message types - */ typedef enum { - HEVC_SEI_TYPE_BUFFERING_PERIOD = 0, - HEVC_SEI_TYPE_PICTURE_TIMING = 1, - HEVC_SEI_TYPE_PAN_SCAN_RECT = 2, - HEVC_SEI_TYPE_FILLER_PAYLOAD = 3, - HEVC_SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35 = 4, - HEVC_SEI_TYPE_USER_DATA_UNREGISTERED = 5, - HEVC_SEI_TYPE_RECOVERY_POINT = 6, - HEVC_SEI_TYPE_SCENE_INFO = 9, - HEVC_SEI_TYPE_FULL_FRAME_SNAPSHOT = 15, - HEVC_SEI_TYPE_PROGRESSIVE_REFINEMENT_SEGMENT_START = 16, - HEVC_SEI_TYPE_PROGRESSIVE_REFINEMENT_SEGMENT_END = 17, - HEVC_SEI_TYPE_FILM_GRAIN_CHARACTERISTICS = 19, - HEVC_SEI_TYPE_POST_FILTER_HINT = 22, - HEVC_SEI_TYPE_TONE_MAPPING_INFO = 23, - HEVC_SEI_TYPE_FRAME_PACKING = 45, - HEVC_SEI_TYPE_DISPLAY_ORIENTATION = 47, - HEVC_SEI_TYPE_SOP_DESCRIPTION = 128, - HEVC_SEI_TYPE_ACTIVE_PARAMETER_SETS = 129, - HEVC_SEI_TYPE_DECODING_UNIT_INFO = 130, - HEVC_SEI_TYPE_TEMPORAL_LEVEL0_INDEX = 131, - HEVC_SEI_TYPE_DECODED_PICTURE_HASH = 132, - HEVC_SEI_TYPE_SCALABLE_NESTING = 133, - HEVC_SEI_TYPE_REGION_REFRESH_INFO = 134, - HEVC_SEI_TYPE_TIME_CODE = 136, - HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO = 137, - HEVC_SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO = 144, - HEVC_SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS = 147, - HEVC_SEI_TYPE_ALPHA_CHANNEL_INFO = 165, -} HEVC_SEI_Type; + HEVC_SEI_PIC_STRUCT_FRAME_DOUBLING = 7, + HEVC_SEI_PIC_STRUCT_FRAME_TRIPLING = 8 +} HEVC_SEI_PicStructType; typedef struct HEVCSEIPictureHash { uint8_t md5[3][16]; @@ -83,10 +56,14 @@ } HEVCSEIPictureTiming; typedef struct HEVCSEIA53Caption { - int a53_caption_size; - uint8_t *a53_caption; + AVBufferRef *buf_ref; } HEVCSEIA53Caption; +typedef struct HEVCSEIUnregistered { + AVBufferRef **buf_ref; + int nb_buf_ref; +} HEVCSEIUnregistered; + typedef struct HEVCSEIMasteringDisplay { int present; uint16_t display_primaries[3][2]; @@ -95,6 +72,10 @@ uint32_t min_luminance; } HEVCSEIMasteringDisplay; +typedef struct HEVCSEIDynamicHDRPlus { + AVBufferRef *info; +} HEVCSEIDynamicHDRPlus; + typedef struct HEVCSEIContentLight { int present; uint16_t max_content_light_level; @@ -106,16 +87,39 @@ int preferred_transfer_characteristics; } HEVCSEIAlternativeTransfer; +typedef struct HEVCSEITimeCode { + int present; + uint8_t num_clock_ts; + uint8_t clock_timestamp_flag[3]; + uint8_t units_field_based_flag[3]; + uint8_t counting_type[3]; + uint8_t full_timestamp_flag[3]; + uint8_t discontinuity_flag[3]; + uint8_t cnt_dropped_flag[3]; + uint16_t n_frames[3]; + uint8_t seconds_value[3]; + uint8_t minutes_value[3]; + uint8_t hours_value[3]; + uint8_t seconds_flag[3]; + uint8_t minutes_flag[3]; + uint8_t hours_flag[3]; + uint8_t time_offset_length[3]; + int32_t time_offset_value[3]; +} HEVCSEITimeCode; + typedef struct HEVCSEI { HEVCSEIPictureHash picture_hash; HEVCSEIFramePacking frame_packing; HEVCSEIDisplayOrientation display_orientation; HEVCSEIPictureTiming picture_timing; HEVCSEIA53Caption a53_caption; + HEVCSEIUnregistered unregistered; HEVCSEIMasteringDisplay mastering_display; + HEVCSEIDynamicHDRPlus dynamic_hdr_plus; HEVCSEIContentLight content_light; int active_seq_parameter_set_id; HEVCSEIAlternativeTransfer alternative_transfer; + HEVCSEITimeCode timecode; } HEVCSEI; struct HEVCParamSets; diff -Nru ffmpeg-4.2.2/libavcodec/hnm4video.c ffmpeg-4.4/libavcodec/hnm4video.c --- ffmpeg-4.2.2/libavcodec/hnm4video.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hnm4video.c 2021-04-08 21:28:39.000000000 +0000 @@ -387,15 +387,6 @@ } } -static void hnm_flip_buffers(Hnm4VideoContext *hnm) -{ - uint8_t *temp; - - temp = hnm->current; - hnm->current = hnm->previous; - hnm->previous = temp; -} - static int hnm_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { @@ -450,7 +441,7 @@ frame->key_frame = 0; memcpy(frame->data[1], hnm->palette, 256 * 4); *got_frame = 1; - hnm_flip_buffers(hnm); + FFSWAP(uint8_t *, hnm->current, hnm->previous); } else { av_log(avctx, AV_LOG_ERROR, "invalid chunk id: %d\n", chunk_id); return AVERROR_INVALIDDATA; @@ -473,6 +464,8 @@ ret = av_image_check_size(avctx->width, avctx->height, 0, avctx); if (ret < 0) return ret; + if (avctx->height & 1) + return AVERROR(EINVAL); hnm->version = avctx->extradata[0]; avctx->pix_fmt = AV_PIX_FMT_PAL8; @@ -482,13 +475,8 @@ hnm->buffer2 = av_mallocz(avctx->width * avctx->height); hnm->processed = av_mallocz(avctx->width * avctx->height); - if ( !hnm->buffer1 || !hnm->buffer2 || !hnm->processed - || avctx->width * avctx->height == 0 - || avctx->height % 2) { + if (!hnm->buffer1 || !hnm->buffer2 || !hnm->processed) { av_log(avctx, AV_LOG_ERROR, "av_mallocz() failed\n"); - av_freep(&hnm->buffer1); - av_freep(&hnm->buffer2); - av_freep(&hnm->processed); return AVERROR(ENOMEM); } @@ -519,4 +507,5 @@ .close = hnm_decode_end, .decode = hnm_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/hq_hqa.c ffmpeg-4.4/libavcodec/hq_hqa.c --- ffmpeg-4.2.2/libavcodec/hq_hqa.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hq_hqa.c 2020-07-09 09:17:49.000000000 +0000 @@ -321,7 +321,7 @@ int info_size; bytestream2_skip(&ctx->gbc, 4); info_size = bytestream2_get_le32(&ctx->gbc); - if (bytestream2_get_bytes_left(&ctx->gbc) < info_size) { + if (info_size < 0 || bytestream2_get_bytes_left(&ctx->gbc) < info_size) { av_log(avctx, AV_LOG_ERROR, "Invalid INFO size (%d).\n", info_size); return AVERROR_INVALIDDATA; } diff -Nru ffmpeg-4.2.2/libavcodec/hq_hqadata.c ffmpeg-4.4/libavcodec/hq_hqadata.c --- ffmpeg-4.2.2/libavcodec/hq_hqadata.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hq_hqadata.c 2021-04-08 21:28:39.000000000 +0000 @@ -1142,7 +1142,7 @@ { { qmat3A, qmat48, qmat4C, qmat4C }, { qmat3B, qmat49, qmat4D, qmat4D } }, }; -const uint8_t ff_hq_ac_bits[NUM_HQ_AC_ENTRIES] = { +static const uint8_t hq_ac_bits[NUM_HQ_AC_ENTRIES] = { 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, @@ -1192,7 +1192,7 @@ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, }; -const uint16_t ff_hq_ac_codes[NUM_HQ_AC_ENTRIES] = { +static const uint16_t hq_ac_codes[NUM_HQ_AC_ENTRIES] = { 0x0000, 0x0001, 0x0004, 0x0005, 0x0006, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, @@ -8373,5 +8373,5 @@ return ret; return init_vlc(&c->hq_ac_vlc, 9, NUM_HQ_AC_ENTRIES, - ff_hq_ac_bits, 1, 1, ff_hq_ac_codes, 2, 2, 0); + hq_ac_bits, 1, 1, hq_ac_codes, 2, 2, 0); } diff -Nru ffmpeg-4.2.2/libavcodec/hq_hqa.h ffmpeg-4.4/libavcodec/hq_hqa.h --- ffmpeg-4.2.2/libavcodec/hq_hqa.h 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hq_hqa.h 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,8 @@ #include +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "bytestream.h" #include "hq_hqadsp.h" diff -Nru ffmpeg-4.2.2/libavcodec/hqx.c ffmpeg-4.4/libavcodec/hqx.c --- ffmpeg-4.2.2/libavcodec/hqx.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hqx.c 2021-04-08 21:28:39.000000000 +0000 @@ -122,8 +122,6 @@ memset(block, 0, 64 * sizeof(*block)); dc = get_vlc2(gb, vlc->table, HQX_DC_VLC_BITS, 2); - if (dc < 0) - return AVERROR_INVALIDDATA; *last_dc += dc; block[0] = sign_extend(*last_dc << (12 - dcb), 12); @@ -197,7 +195,7 @@ int i, ret; int cbp; - cbp = get_vlc2(gb, ctx->cbp_vlc.table, ctx->cbp_vlc.bits, 1); + cbp = get_vlc2(gb, ctx->cbp_vlc.table, HQX_CBP_VLC_BITS, 1); for (i = 0; i < 12; i++) memset(slice->block[i], 0, sizeof(**slice->block) * 64); @@ -283,7 +281,7 @@ int i, ret; int cbp; - cbp = get_vlc2(gb, ctx->cbp_vlc.table, ctx->cbp_vlc.bits, 1); + cbp = get_vlc2(gb, ctx->cbp_vlc.table, HQX_CBP_VLC_BITS, 1); for (i = 0; i < 16; i++) memset(slice->block[i], 0, sizeof(**slice->block) * 64); @@ -471,6 +469,14 @@ avctx->height = ctx->height; avctx->bits_per_raw_sample = 10; + //The minimum size is 2bit per macroblock + // hqx_decode_422 & hqx_decode_444 have a unconditionally stored 4bits hqx_quants index + // hqx_decode_422a & hqx_decode_444a use cbp_vlc which has a minimum length of 2 bits for its VLCs + // The code rejects slices overlapping in their input data + if (avctx->coded_width / 16 * (avctx->coded_height / 16) * + (100 - avctx->discard_damaged_percentage) / 100 > 4LL * avpkt->size) + return AVERROR_INVALIDDATA; + switch (ctx->format) { case HQX_422: avctx->pix_fmt = AV_PIX_FMT_YUV422P16; @@ -512,9 +518,6 @@ int i; HQXContext *ctx = avctx->priv_data; - if (avctx->internal->is_copy) - return 0; - ff_free_vlc(&ctx->cbp_vlc); for (i = 0; i < 3; i++) { ff_free_vlc(&ctx->dc_vlc[i]); diff -Nru ffmpeg-4.2.2/libavcodec/hqx.h ffmpeg-4.4/libavcodec/hqx.h --- ffmpeg-4.2.2/libavcodec/hqx.h 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hqx.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,7 +24,8 @@ #include #include "libavutil/frame.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" + #include "get_bits.h" #include "hqxdsp.h" @@ -77,6 +78,7 @@ VLC dc_vlc[3]; } HQXContext; +#define HQX_CBP_VLC_BITS 5 #define HQX_DC_VLC_BITS 9 extern const HQXAC ff_hqx_ac[NUM_HQX_AC]; diff -Nru ffmpeg-4.2.2/libavcodec/hqxvlc.c ffmpeg-4.4/libavcodec/hqxvlc.c --- ffmpeg-4.2.2/libavcodec/hqxvlc.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hqxvlc.c 2021-04-08 21:28:39.000000000 +0000 @@ -2150,7 +2150,7 @@ av_cold int ff_hqx_init_vlcs(HQXContext *ctx) { - int ret = init_vlc(&ctx->cbp_vlc, 5, FF_ARRAY_ELEMS(cbp_vlc_lens), + int ret = init_vlc(&ctx->cbp_vlc, HQX_CBP_VLC_BITS, FF_ARRAY_ELEMS(cbp_vlc_lens), cbp_vlc_lens, 1, 1, cbp_vlc_bits, 1, 1, 0); if (ret < 0) return ret; diff -Nru ffmpeg-4.2.2/libavcodec/huffyuvdec.c ffmpeg-4.4/libavcodec/huffyuvdec.c --- ffmpeg-4.2.2/libavcodec/huffyuvdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/huffyuvdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -570,35 +570,6 @@ return ret; } -#if HAVE_THREADS -static av_cold int decode_init_thread_copy(AVCodecContext *avctx) -{ - HYuvContext *s = avctx->priv_data; - int i, ret; - - s->avctx = avctx; - - if ((ret = ff_huffyuv_alloc_temp(s)) < 0) { - ff_huffyuv_common_end(s); - return ret; - } - - for (i = 0; i < 8; i++) - s->vlc[i].table = NULL; - - if (s->version >= 2) { - if ((ret = read_huffman_tables(s, avctx->extradata + 4, - avctx->extradata_size)) < 0) - return ret; - } else { - if ((ret = read_old_huffman_tables(s)) < 0) - return ret; - } - - return 0; -} -#endif - /** Subset of GET_VLC for use in hand-roller VLC code */ #define VLC_INTERN(dst, table, gb, name, bits, max_depth) \ code = table[index][0]; \ @@ -957,12 +928,16 @@ left= left_prediction(s, p->data[plane], s->temp[0], w, 0); y = 1; + if (y >= h) + break; /* second line is left predicted for interlaced case */ if (s->interlaced) { decode_plane_bitstream(s, w, plane); left = left_prediction(s, p->data[plane] + p->linesize[plane], s->temp[0], w, left); y++; + if (y >= h) + break; } lefttop = p->data[plane][0]; @@ -1074,6 +1049,8 @@ } cy = y = 1; + if (y >= height) + break; /* second line is left predicted for interlaced case */ if (s->interlaced) { @@ -1086,6 +1063,8 @@ } y++; cy++; + if (y >= height) + break; } /* next 4 pixels are left predicted too */ @@ -1302,7 +1281,6 @@ .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), }; #if CONFIG_FFVHUFF_DECODER @@ -1317,7 +1295,6 @@ .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), }; #endif /* CONFIG_FFVHUFF_DECODER */ @@ -1333,6 +1310,5 @@ .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), }; #endif /* CONFIG_HYMT_DECODER */ diff -Nru ffmpeg-4.2.2/libavcodec/huffyuvenc.c ffmpeg-4.4/libavcodec/huffyuvenc.c --- ffmpeg-4.2.2/libavcodec/huffyuvenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/huffyuvenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -1091,7 +1091,7 @@ .init = encode_init, .encode2 = encode_frame, .close = encode_end, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .priv_class = &normal_class, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P, AV_PIX_FMT_RGB24, @@ -1111,7 +1111,7 @@ .init = encode_init, .encode2 = encode_frame, .close = encode_end, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .priv_class = &ff_class, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV411P, diff -Nru ffmpeg-4.2.2/libavcodec/hwaccel.h ffmpeg-4.4/libavcodec/hwaccel.h --- ffmpeg-4.2.2/libavcodec/hwaccel.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hwaccel.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVCODEC_HWACCEL_H -#define AVCODEC_HWACCEL_H - -#include "avcodec.h" -#include "hwaccels.h" - - -#define HWACCEL_CAP_ASYNC_SAFE (1 << 0) - - -typedef struct AVCodecHWConfigInternal { - /** - * This is the structure which will be returned to the user by - * avcodec_get_hw_config(). - */ - AVCodecHWConfig public; - /** - * If this configuration uses a hwaccel, a pointer to it. - * If not, NULL. - */ - const AVHWAccel *hwaccel; -} AVCodecHWConfigInternal; - - -// These macros are used to simplify AVCodecHWConfigInternal definitions. - -#define HW_CONFIG_HWACCEL(device, frames, ad_hoc, format, device_type_, name) \ - &(const AVCodecHWConfigInternal) { \ - .public = { \ - .pix_fmt = AV_PIX_FMT_ ## format, \ - .methods = (device ? AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX : 0) | \ - (frames ? AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX : 0) | \ - (ad_hoc ? AV_CODEC_HW_CONFIG_METHOD_AD_HOC : 0), \ - .device_type = AV_HWDEVICE_TYPE_ ## device_type_, \ - }, \ - .hwaccel = &name, \ - } - -#define HW_CONFIG_INTERNAL(format) \ - &(const AVCodecHWConfigInternal) { \ - .public = { \ - .pix_fmt = AV_PIX_FMT_ ## format, \ - .methods = AV_CODEC_HW_CONFIG_METHOD_INTERNAL, \ - .device_type = AV_HWDEVICE_TYPE_NONE, \ - }, \ - .hwaccel = NULL, \ - } - -#define HWACCEL_DXVA2(codec) \ - HW_CONFIG_HWACCEL(1, 1, 1, DXVA2_VLD, DXVA2, ff_ ## codec ## _dxva2_hwaccel) -#define HWACCEL_D3D11VA2(codec) \ - HW_CONFIG_HWACCEL(1, 1, 0, D3D11, D3D11VA, ff_ ## codec ## _d3d11va2_hwaccel) -#define HWACCEL_NVDEC(codec) \ - HW_CONFIG_HWACCEL(1, 1, 0, CUDA, CUDA, ff_ ## codec ## _nvdec_hwaccel) -#define HWACCEL_VAAPI(codec) \ - HW_CONFIG_HWACCEL(1, 1, 1, VAAPI, VAAPI, ff_ ## codec ## _vaapi_hwaccel) -#define HWACCEL_VDPAU(codec) \ - HW_CONFIG_HWACCEL(1, 1, 1, VDPAU, VDPAU, ff_ ## codec ## _vdpau_hwaccel) -#define HWACCEL_VIDEOTOOLBOX(codec) \ - HW_CONFIG_HWACCEL(1, 1, 1, VIDEOTOOLBOX, VIDEOTOOLBOX, ff_ ## codec ## _videotoolbox_hwaccel) -#define HWACCEL_D3D11VA(codec) \ - HW_CONFIG_HWACCEL(0, 0, 1, D3D11VA_VLD, NONE, ff_ ## codec ## _d3d11va_hwaccel) -#define HWACCEL_XVMC(codec) \ - HW_CONFIG_HWACCEL(0, 0, 1, XVMC, NONE, ff_ ## codec ## _xvmc_hwaccel) - -#endif /* AVCODEC_HWACCEL_H */ diff -Nru ffmpeg-4.2.2/libavcodec/hwaccels.h ffmpeg-4.4/libavcodec/hwaccels.h --- ffmpeg-4.2.2/libavcodec/hwaccels.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hwaccels.h 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,11 @@ #include "avcodec.h" +extern const AVHWAccel ff_av1_d3d11va_hwaccel; +extern const AVHWAccel ff_av1_d3d11va2_hwaccel; +extern const AVHWAccel ff_av1_dxva2_hwaccel; +extern const AVHWAccel ff_av1_nvdec_hwaccel; +extern const AVHWAccel ff_av1_vaapi_hwaccel; extern const AVHWAccel ff_h263_vaapi_hwaccel; extern const AVHWAccel ff_h263_videotoolbox_hwaccel; extern const AVHWAccel ff_h264_d3d11va_hwaccel; @@ -68,6 +73,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_wmv3_d3d11va_hwaccel; extern const AVHWAccel ff_wmv3_d3d11va2_hwaccel; extern const AVHWAccel ff_wmv3_dxva2_hwaccel; diff -Nru ffmpeg-4.2.2/libavcodec/hwconfig.h ffmpeg-4.4/libavcodec/hwconfig.h --- ffmpeg-4.2.2/libavcodec/hwconfig.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/hwconfig.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,102 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_HWCONFIG_H +#define AVCODEC_HWCONFIG_H + +#include "avcodec.h" +#include "hwaccels.h" + + +#define HWACCEL_CAP_ASYNC_SAFE (1 << 0) + + +typedef struct AVCodecHWConfigInternal { + /** + * This is the structure which will be returned to the user by + * avcodec_get_hw_config(). + */ + AVCodecHWConfig public; + /** + * If this configuration uses a hwaccel, a pointer to it. + * If not, NULL. + */ + const AVHWAccel *hwaccel; +} AVCodecHWConfigInternal; + + +// These macros are used to simplify AVCodecHWConfigInternal definitions. + +#define HW_CONFIG_HWACCEL(device, frames, ad_hoc, format, device_type_, name) \ + &(const AVCodecHWConfigInternal) { \ + .public = { \ + .pix_fmt = AV_PIX_FMT_ ## format, \ + .methods = (device ? AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX : 0) | \ + (frames ? AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX : 0) | \ + (ad_hoc ? AV_CODEC_HW_CONFIG_METHOD_AD_HOC : 0), \ + .device_type = AV_HWDEVICE_TYPE_ ## device_type_, \ + }, \ + .hwaccel = &name, \ + } + +#define HW_CONFIG_INTERNAL(format) \ + &(const AVCodecHWConfigInternal) { \ + .public = { \ + .pix_fmt = AV_PIX_FMT_ ## format, \ + .methods = AV_CODEC_HW_CONFIG_METHOD_INTERNAL, \ + .device_type = AV_HWDEVICE_TYPE_NONE, \ + }, \ + .hwaccel = NULL, \ + } + +#define HWACCEL_DXVA2(codec) \ + HW_CONFIG_HWACCEL(1, 1, 1, DXVA2_VLD, DXVA2, ff_ ## codec ## _dxva2_hwaccel) +#define HWACCEL_D3D11VA2(codec) \ + HW_CONFIG_HWACCEL(1, 1, 0, D3D11, D3D11VA, ff_ ## codec ## _d3d11va2_hwaccel) +#define HWACCEL_NVDEC(codec) \ + HW_CONFIG_HWACCEL(1, 1, 0, CUDA, CUDA, ff_ ## codec ## _nvdec_hwaccel) +#define HWACCEL_VAAPI(codec) \ + HW_CONFIG_HWACCEL(1, 1, 1, VAAPI, VAAPI, ff_ ## codec ## _vaapi_hwaccel) +#define HWACCEL_VDPAU(codec) \ + HW_CONFIG_HWACCEL(1, 1, 1, VDPAU, VDPAU, ff_ ## codec ## _vdpau_hwaccel) +#define HWACCEL_VIDEOTOOLBOX(codec) \ + HW_CONFIG_HWACCEL(1, 1, 1, VIDEOTOOLBOX, VIDEOTOOLBOX, ff_ ## codec ## _videotoolbox_hwaccel) +#define HWACCEL_D3D11VA(codec) \ + HW_CONFIG_HWACCEL(0, 0, 1, D3D11VA_VLD, NONE, ff_ ## codec ## _d3d11va_hwaccel) +#define HWACCEL_XVMC(codec) \ + HW_CONFIG_HWACCEL(0, 0, 1, XVMC, NONE, ff_ ## codec ## _xvmc_hwaccel) + +#define HW_CONFIG_ENCODER(device, frames, ad_hoc, format, device_type_) \ + &(const AVCodecHWConfigInternal) { \ + .public = { \ + .pix_fmt = AV_PIX_FMT_ ## format, \ + .methods = (device ? AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX : 0) | \ + (frames ? AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX : 0) | \ + (ad_hoc ? AV_CODEC_HW_CONFIG_METHOD_AD_HOC : 0), \ + .device_type = AV_HWDEVICE_TYPE_ ## device_type_, \ + }, \ + .hwaccel = NULL, \ + } + +#define HW_CONFIG_ENCODER_DEVICE(format, device_type_) \ + HW_CONFIG_ENCODER(1, 0, 0, format, device_type_) + +#define HW_CONFIG_ENCODER_FRAMES(format, device_type_) \ + HW_CONFIG_ENCODER(0, 1, 0, format, device_type_) + +#endif /* AVCODEC_HWCONFIG_H */ diff -Nru ffmpeg-4.2.2/libavcodec/idcinvideo.c ffmpeg-4.4/libavcodec/idcinvideo.c --- ffmpeg-4.2.2/libavcodec/idcinvideo.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/idcinvideo.c 2021-04-08 21:28:39.000000000 +0000 @@ -214,7 +214,7 @@ const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; IdcinContext *s = avctx->priv_data; - int pal_size; + buffer_size_t pal_size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size); AVFrame *frame = data; int ret; @@ -258,4 +258,5 @@ .decode = idcin_decode_frame, .capabilities = AV_CODEC_CAP_DR1, .defaults = idcin_defaults, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/iff.c ffmpeg-4.4/libavcodec/iff.c --- ffmpeg-4.2.2/libavcodec/iff.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/iff.c 2020-07-11 10:39:30.000000000 +0000 @@ -332,13 +332,17 @@ int i, count = FFMIN(palette_size / 3, 1 << s->ham); int ham_count; const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata); + int extra_space = 1; + + if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ') && s->ham == 4) + extra_space = 4; s->ham_buf = av_malloc((s->planesize * 8) + AV_INPUT_BUFFER_PADDING_SIZE); if (!s->ham_buf) return AVERROR(ENOMEM); ham_count = 8 * (1 << s->ham); - s->ham_palbuf = av_malloc((ham_count << !!(s->masking == MASK_HAS_MASK)) * sizeof (uint32_t) + AV_INPUT_BUFFER_PADDING_SIZE); + s->ham_palbuf = av_malloc(extra_space * (ham_count << !!(s->masking == MASK_HAS_MASK)) * sizeof (uint32_t) + AV_INPUT_BUFFER_PADDING_SIZE); if (!s->ham_palbuf) { av_freep(&s->ham_buf); return AVERROR(ENOMEM); @@ -436,6 +440,8 @@ if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) { s->video_size = FFALIGN(avctx->width, 2) * avctx->height * s->bpp; + if (!s->video_size) + return AVERROR_INVALIDDATA; s->video[0] = av_calloc(FFALIGN(avctx->width, 2) * avctx->height, s->bpp); s->video[1] = av_calloc(FFALIGN(avctx->width, 2) * avctx->height, s->bpp); s->pal = av_calloc(256, sizeof(*s->pal)); @@ -711,13 +717,15 @@ { const uint8_t *src_end = src + src_size; int x = 0, y = 0, i; - while (src + 5 <= src_end) { + while (src_end - src >= 5) { int opcode; opcode = *(int8_t *)src++; if (opcode >= 0) { int size = opcode + 1; for (i = 0; i < size; i++) { - int length = FFMIN(size - i, width); + int length = FFMIN(size - i, width - x); + if (src_end - src < length * 4) + return; memcpy(dst + y*linesize + x * 4, src, length * 4); src += length * 4; x += length; @@ -1354,6 +1362,9 @@ bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc)); entries = bytestream2_get_be32(&gb); + if (entries * 8LL > bytestream2_get_bytes_left(&gb)) + return; + while (entries && bytestream2_get_bytes_left(&gb) >= 8) { int32_t opcode = bytestream2_get_be32(&gb); unsigned offset = bytestream2_get_be32(&gb); @@ -1369,11 +1380,10 @@ opcode--; } } else { - opcode = -opcode; while (opcode && bytestream2_get_bytes_left(&gb) > 0) { bytestream2_put_be32(&pb, bytestream2_get_be32(&gb)); bytestream2_skip_p(&pb, pitch - 4); - opcode--; + opcode++; } } entries--; diff -Nru ffmpeg-4.2.2/libavcodec/iirfilter.c ffmpeg-4.4/libavcodec/iirfilter.c --- ffmpeg-4.2.2/libavcodec/iirfilter.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/iirfilter.c 2021-04-08 21:28:39.000000000 +0000 @@ -171,12 +171,10 @@ if (order <= 0 || order > MAXORDER || cutoff_ratio >= 1.0) return NULL; - FF_ALLOCZ_OR_GOTO(avc, c, sizeof(FFIIRFilterCoeffs), - init_fail); - FF_ALLOC_OR_GOTO(avc, c->cx, sizeof(c->cx[0]) * ((order >> 1) + 1), - init_fail); - FF_ALLOC_OR_GOTO(avc, c->cy, sizeof(c->cy[0]) * order, - init_fail); + if (!(c = av_mallocz(sizeof(*c))) || + !(c->cx = av_malloc (sizeof(c->cx[0]) * ((order >> 1) + 1))) || + !(c->cy = av_malloc (sizeof(c->cy[0]) * order))) + goto free; c->order = order; switch (filt_type) { @@ -190,13 +188,12 @@ break; default: av_log(avc, AV_LOG_ERROR, "filter type is not currently implemented\n"); - goto init_fail; + goto free; } if (!ret) return c; - -init_fail: +free: ff_iir_filter_free_coeffsp(&c); return NULL; } diff -Nru ffmpeg-4.2.2/libavcodec/ilbcdata.h ffmpeg-4.4/libavcodec/ilbcdata.h --- ffmpeg-4.2.2/libavcodec/ilbcdata.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ilbcdata.h 2021-04-08 21:28:39.000000000 +0000 @@ -60,10 +60,6 @@ 32767, 29573, 26690, 24087, 21739, 19619, 17707, 15980, 14422, 13016, 11747 }; -static const int16_t LpcChirpWeightDenum[] = { - 32767, 13835, 5841, 2466, 1041, 440, 186, 78, 33, 14, 6 -}; - static const int16_t cos_tbl[64] = { 32767, 32729, 32610, 32413, 32138, 31786, 31357, 30853, 30274, 29622, 28899, 28106, 27246, 26320, 25330, 24279, diff -Nru ffmpeg-4.2.2/libavcodec/ilbcdec.c ffmpeg-4.4/libavcodec/ilbcdec.c --- ffmpeg-4.2.2/libavcodec/ilbcdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ilbcdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -1484,6 +1484,6 @@ .id = AV_CODEC_ID_ILBC, .init = ilbc_decode_init, .decode = ilbc_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .priv_data_size = sizeof(ILBCContext), }; diff -Nru ffmpeg-4.2.2/libavcodec/imc.c ffmpeg-4.4/libavcodec/imc.c --- ffmpeg-4.2.2/libavcodec/imc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/imc.c 2021-04-08 21:28:39.000000000 +0000 @@ -38,6 +38,9 @@ #include "libavutil/ffmath.h" #include "libavutil/float_dsp.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" +#include "libavutil/thread.h" + #include "avcodec.h" #include "bswapdsp.h" #include "get_bits.h" @@ -95,7 +98,7 @@ GetBitContext gb; BswapDSPContext bdsp; - AVFloatDSPContext *fdsp; + void (*butterflies_float)(float *av_restrict v1, float *av_restrict v2, int len); FFTContext fft; DECLARE_ALIGNED(32, FFTComplex, samples)[COEFFS / 2]; float *out_samples; @@ -110,13 +113,9 @@ static VLC huffman_vlc[4][4]; +#define IMC_VLC_BITS 9 #define VLC_TABLES_SIZE 9512 -static const int vlc_offsets[17] = { - 0, 640, 1156, 1732, 2308, 2852, 3396, 3924, - 4452, 5220, 5860, 6628, 7268, 7908, 8424, 8936, VLC_TABLES_SIZE -}; - static VLC_TYPE vlc_tables[VLC_TABLES_SIZE][2]; static inline double freq2bark(double freq) @@ -175,10 +174,28 @@ } } +static av_cold void imc_init_static(void) +{ + /* initialize the VLC tables */ + for (int i = 0, offset = 0; i < 4 ; i++) { + for (int j = 0; j < 4; j++) { + huffman_vlc[i][j].table = &vlc_tables[offset]; + huffman_vlc[i][j].table_allocated = VLC_TABLES_SIZE - offset; + ff_init_vlc_from_lengths(&huffman_vlc[i][j], IMC_VLC_BITS, imc_huffman_sizes[i], + imc_huffman_lens[i][j], 1, + imc_huffman_syms[i][j], 1, 1, + 0, INIT_VLC_STATIC_OVERLONG, NULL); + offset += huffman_vlc[i][j].table_size; + } + } +} + static av_cold int imc_decode_init(AVCodecContext *avctx) { int i, j, ret; IMCContext *q = avctx->priv_data; + static AVOnce init_static_once = AV_ONCE_INIT; + AVFloatDSPContext *fdsp; double r1, r2; if (avctx->codec_id == AV_CODEC_ID_IAC && avctx->sample_rate > 96000) { @@ -232,17 +249,6 @@ for (i = 0; i < 30; i++) q->sqrt_tab[i] = sqrt(i); - /* initialize the VLC tables */ - for (i = 0; i < 4 ; i++) { - for (j = 0; j < 4; j++) { - huffman_vlc[i][j].table = &vlc_tables[vlc_offsets[i * 4 + j]]; - huffman_vlc[i][j].table_allocated = vlc_offsets[i * 4 + j + 1] - vlc_offsets[i * 4 + j]; - init_vlc(&huffman_vlc[i][j], 9, imc_huffman_sizes[i], - imc_huffman_lens[i][j], 1, 1, - imc_huffman_bits[i][j], 2, 2, INIT_VLC_USE_NEW_STATIC); - } - } - if (avctx->codec_id == AV_CODEC_ID_IAC) { iac_generate_tabs(q, avctx->sample_rate); } else { @@ -252,22 +258,23 @@ memcpy(q->weights2, imc_weights2, sizeof(imc_weights2)); } + fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); + if (!fdsp) + return AVERROR(ENOMEM); + q->butterflies_float = fdsp->butterflies_float; + av_free(fdsp); if ((ret = ff_fft_init(&q->fft, 7, 1))) { av_log(avctx, AV_LOG_INFO, "FFT init failed\n"); return ret; } ff_bswapdsp_init(&q->bdsp); - q->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); - if (!q->fdsp) { - ff_fft_end(&q->fft); - - return AVERROR(ENOMEM); - } avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; + ff_thread_once(&init_static_once, imc_init_static); + return 0; } @@ -348,7 +355,7 @@ levlCoeffs[0] = get_bits(&q->gb, 7); for (i = start; i < BANDS; i++) { levlCoeffs[i] = get_vlc2(&q->gb, hufftab[cb_sel[i]]->table, - hufftab[cb_sel[i]]->bits, 2); + IMC_VLC_BITS, 2); if (levlCoeffs[i] == 17) levlCoeffs[i] += get_bits(&q->gb, 4); } @@ -1050,8 +1057,8 @@ } if (avctx->channels == 2) { - q->fdsp->butterflies_float((float *)frame->extended_data[0], - (float *)frame->extended_data[1], COEFFS); + q->butterflies_float((float *)frame->extended_data[0], + (float *)frame->extended_data[1], COEFFS); } *got_frame_ptr = 1; @@ -1064,7 +1071,6 @@ IMCContext *q = avctx->priv_data; ff_fft_end(&q->fft); - av_freep(&q->fdsp); return 0; } @@ -1088,9 +1094,10 @@ .close = imc_decode_close, .decode = imc_decode_frame, .flush = flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_IAC_DECODER @@ -1107,5 +1114,6 @@ .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/imcdata.h ffmpeg-4.4/libavcodec/imcdata.h --- ffmpeg-4.2.2/libavcodec/imcdata.h 2016-03-29 02:25:16.000000000 +0000 +++ ffmpeg-4.4/libavcodec/imcdata.h 2021-04-08 21:28:39.000000000 +0000 @@ -114,55 +114,55 @@ static const uint8_t imc_huffman_lens[4][4][18] = { { - { 16, 15, 13, 11, 8, 5, 3, 1, 2, 4, 6, 9, 10, 12, 14, 16, 7, 0 }, - { 10, 8, 7, 6, 4, 4, 3, 2, 2, 3, 4, 6, 7, 9, 11, 11, 7, 0 }, - { 15, 15, 14, 11, 8, 6, 4, 2, 1, 4, 5, 7, 9, 10, 12, 13, 4, 0 }, - { 13, 11, 10, 8, 6, 4, 2, 2, 2, 3, 5, 7, 9, 12, 15, 15, 14, 0 }, + { 1, 2, 5, 6, 11, 12, 15, 16, 16, 14, 13, 10, 9, 8, 7, 4, 3 }, + { 2, 3, 3, 4, 4, 4, 6, 6, 7, 7, 7, 8, 9, 10, 11, 11, 2 }, + { 1, 4, 4, 7, 9, 10, 12, 15, 15, 14, 13, 11, 8, 6, 5, 4, 2 }, + { 2, 2, 4, 8, 9, 14, 15, 15, 13, 12, 11, 10, 7, 6, 5, 3, 2 }, }, { - { 14, 12, 10, 8, 7, 4, 2, 2, 2, 3, 5, 7, 9, 11, 13, 14, 7, 0 }, - { 14, 13, 11, 8, 6, 4, 3, 2, 2, 3, 5, 7, 9, 10, 12, 14, 3, 0 }, - { 13, 12, 10, 7, 5, 4, 3, 2, 2, 3, 4, 6, 8, 9, 11, 13, 4, 0 }, - { 13, 12, 10, 7, 5, 4, 3, 2, 2, 3, 4, 6, 8, 9, 11, 13, 4, 0 }, + { 2, 2, 3, 4, 7, 7, 10, 11, 12, 14, 14, 13, 9, 8, 7, 5, 2 }, + { 2, 3, 14, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2 }, + { 2, 3, 3, 4, 4, 5, 7, 9, 11, 12, 13, 13, 10, 8, 6, 4, 2 }, + { 2, 3, 3, 4, 4, 5, 7, 9, 11, 12, 13, 13, 10, 8, 6, 4, 2 }, }, { - { 16, 14, 12, 10, 8, 5, 3, 1, 2, 4, 7, 9, 11, 13, 15, 17, 6, 17 }, - { 15, 13, 11, 8, 6, 4, 2, 2, 2, 3, 5, 7, 10, 12, 14, 16, 9, 16 }, - { 14, 12, 11, 9, 8, 6, 3, 1, 2, 5, 7, 10, 13, 15, 16, 17, 4, 17 }, - { 16, 14, 12, 9, 7, 5, 2, 2, 2, 3, 4, 6, 8, 11, 13, 15, 10, 16 }, + { 3, 5, 8, 9, 12, 15, 17, 17, 16, 14, 13, 11, 10, 7, 6, 4, 2, 1 }, + { 4, 7, 8, 10, 11, 12, 15, 16, 16, 14, 13, 9, 6, 5, 3, 2, 2, 2 }, + { 4, 5, 6, 7, 12, 13, 17, 17, 16, 15, 14, 11, 10, 9, 8, 3, 2, 1 }, + { 2, 5, 7, 8, 14, 15, 16, 16, 13, 12, 11, 10, 9, 6, 4, 3, 2, 2 }, }, { - { 13, 11, 10, 8, 7, 5, 2, 2, 2, 4, 6, 9, 12, 14, 15, 16, 3, 16 }, - { 11, 11, 10, 9, 8, 7, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 5 }, - { 9, 9, 7, 6, 5, 4, 3, 3, 2, 3, 4, 5, 4, 5, 5, 6, 8, 6 }, - { 13, 12, 10, 8, 5, 3, 3, 2, 2, 3, 4, 7, 9, 11, 14, 15, 6, 15 }, + { 2, 4, 7, 9, 10, 12, 13, 15, 16, 16, 14, 11, 8, 6, 5, 3, 2, 2 }, + { 3, 5, 5, 7, 10, 11, 11, 9, 8, 6, 5, 4, 4, 3, 3, 3, 3, 3 }, + { 5, 8, 9, 9, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2 }, + { 2, 3, 5, 7, 8, 11, 12, 13, 15, 15, 14, 10, 9, 6, 4, 3, 3, 2 }, } }; -static const uint16_t imc_huffman_bits[4][4][18] = { +static const uint8_t imc_huffman_syms[4][4][18] = { { - { 0xCC32, 0x6618, 0x1987, 0x0660, 0x00CD, 0x0018, 0x0007, 0x0000, 0x0002, 0x000D, 0x0032, 0x0199, 0x0331, 0x0CC2, 0x330D, 0xCC33, 0x0067, 0x0000 }, - { 0x02FE, 0x00BE, 0x005E, 0x002D, 0x000A, 0x0009, 0x0003, 0x0003, 0x0000, 0x0002, 0x0008, 0x002C, 0x005D, 0x017E, 0x05FE, 0x05FF, 0x005C, 0x0000 }, - { 0x5169, 0x5168, 0x28B5, 0x0517, 0x00A3, 0x0029, 0x0008, 0x0003, 0x0000, 0x0009, 0x0015, 0x0050, 0x0144, 0x028A, 0x0A2C, 0x145B, 0x000B, 0x0000 }, - { 0x1231, 0x048D, 0x0247, 0x0090, 0x0025, 0x0008, 0x0001, 0x0003, 0x0000, 0x0005, 0x0013, 0x0049, 0x0122, 0x0919, 0x48C3, 0x48C2, 0x2460, 0x0000 }, + { 7, 8, 5, 10, 3, 13, 1, 0, 15, 14, 2, 12, 11, 4, 16, 9, 6 }, + { 8, 9, 6, 10, 5, 4, 11, 3, 16, 12, 2, 1, 13, 0, 14, 15, 7 }, + { 8, 6, 9, 11, 12, 13, 14, 1, 0, 2, 15, 3, 4, 5, 10, 16, 7 }, + { 8, 6, 5, 3, 12, 16, 15, 14, 0, 13, 1, 2, 11, 4, 10, 9, 7 }, }, { - { 0x2D1D, 0x0B46, 0x02D0, 0x00B5, 0x0059, 0x000A, 0x0003, 0x0001, 0x0000, 0x0004, 0x0017, 0x005B, 0x0169, 0x05A2, 0x168F, 0x2D1C, 0x0058, 0x0000 }, - { 0x1800, 0x0C01, 0x0301, 0x0061, 0x0019, 0x0007, 0x0004, 0x0003, 0x0000, 0x0005, 0x000D, 0x0031, 0x00C1, 0x0181, 0x0601, 0x1801, 0x0002, 0x0000 }, - { 0x1556, 0x0AAA, 0x02AB, 0x0054, 0x0014, 0x000B, 0x0002, 0x0003, 0x0000, 0x0003, 0x0008, 0x002B, 0x00AB, 0x0154, 0x0554, 0x1557, 0x0009, 0x0000 }, - { 0x1556, 0x0AAA, 0x02AB, 0x0054, 0x0014, 0x000B, 0x0002, 0x0003, 0x0000, 0x0003, 0x0008, 0x002B, 0x00AB, 0x0154, 0x0554, 0x1557, 0x0009, 0x0000 }, + { 8, 7, 9, 5, 16, 4, 2, 13, 1, 15, 0, 14, 12, 3, 11, 10, 6 }, + { 8, 16, 0, 15, 1, 14, 2, 13, 12, 3, 11, 4, 10, 5, 6, 9, 7 }, + { 8, 6, 9, 10, 16, 4, 3, 13, 14, 1, 0, 15, 2, 12, 11, 5, 7 }, + { 8, 6, 9, 10, 16, 4, 3, 13, 14, 1, 0, 15, 2, 12, 11, 5, 7 }, }, { - { 0x2993, 0x0A65, 0x0298, 0x00A7, 0x0028, 0x0004, 0x0000, 0x0001, 0x0001, 0x0003, 0x0015, 0x0052, 0x014D, 0x0533, 0x14C8, 0x5324, 0x000B, 0x5325 }, - { 0x09B8, 0x026F, 0x009A, 0x0012, 0x0005, 0x0000, 0x0001, 0x0002, 0x0003, 0x0001, 0x0003, 0x0008, 0x004C, 0x0136, 0x04DD, 0x1373, 0x0027, 0x1372 }, - { 0x0787, 0x01E0, 0x00F1, 0x003D, 0x001F, 0x0006, 0x0001, 0x0001, 0x0001, 0x0002, 0x000E, 0x0079, 0x03C2, 0x0F0D, 0x1E19, 0x3C30, 0x0000, 0x3C31 }, - { 0x4B06, 0x12C0, 0x04B1, 0x0097, 0x0024, 0x0008, 0x0002, 0x0003, 0x0000, 0x0003, 0x0005, 0x0013, 0x004A, 0x0259, 0x0961, 0x2582, 0x012D, 0x4B07 }, + { 6, 5, 4, 11, 2, 14, 15, 17, 0, 1, 13, 12, 3, 10, 16, 9, 8, 7 }, + { 5, 11, 3, 12, 2, 13, 0, 17, 15, 14, 1, 16, 4, 10, 9, 6, 7, 8 }, + { 16, 9, 5, 10, 1, 12, 15, 17, 14, 13, 0, 2, 11, 3, 4, 6, 8, 7 }, + { 8, 5, 4, 12, 1, 15, 0, 17, 14, 2, 13, 16, 3, 11, 10, 9, 6, 7 }, }, { - { 0x0A5A, 0x0297, 0x014A, 0x0053, 0x0028, 0x000B, 0x0003, 0x0000, 0x0002, 0x0004, 0x0015, 0x00A4, 0x052C, 0x14B7, 0x296C, 0x52DB, 0x0003, 0x52DA }, - { 0x0193, 0x0192, 0x00C8, 0x0065, 0x0033, 0x0018, 0x0007, 0x0004, 0x0000, 0x0004, 0x0005, 0x0007, 0x0006, 0x0003, 0x0005, 0x0005, 0x000D, 0x0004 }, - { 0x0012, 0x0013, 0x0005, 0x0003, 0x0000, 0x0003, 0x0005, 0x0004, 0x0003, 0x0003, 0x0005, 0x0005, 0x0004, 0x0004, 0x0003, 0x0005, 0x0008, 0x0004 }, - { 0x0D66, 0x06B2, 0x01AD, 0x006A, 0x000C, 0x0005, 0x0004, 0x0000, 0x0003, 0x0002, 0x0007, 0x0034, 0x00D7, 0x0358, 0x1ACF, 0x359C, 0x001B, 0x359D }, + { 7, 9, 4, 11, 2, 12, 0, 14, 17, 15, 13, 1, 3, 10, 5, 16, 8, 6 }, + { 8, 17, 15, 5, 2, 1, 0, 3, 4, 16, 6, 7, 14, 13, 9, 10, 12, 11 }, + { 4, 16, 0, 1, 2, 3, 17, 15, 14, 13, 11, 5, 12, 10, 9, 7, 6, 8 }, + { 7, 9, 4, 11, 3, 13, 1, 0, 15, 17, 14, 2, 12, 16, 10, 6, 5, 8 }, } }; diff -Nru ffmpeg-4.2.2/libavcodec/imgconvert.c ffmpeg-4.4/libavcodec/imgconvert.c --- ffmpeg-4.2.2/libavcodec/imgconvert.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/imgconvert.c 2021-04-08 21:28:39.000000000 +0000 @@ -44,6 +44,7 @@ } #endif +#if FF_API_AVCODEC_PIX_FMT int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt, int has_alpha) @@ -60,9 +61,10 @@ enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr) { - return avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr); + return av_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr); } +#endif enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *pix_fmt_list, enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr){ @@ -73,7 +75,7 @@ for (i=0; pix_fmt_list[i] != AV_PIX_FMT_NONE; i++) { loss = loss_ptr ? *loss_ptr : 0; - best = avcodec_find_best_pix_fmt_of_2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, &loss); + best = av_find_best_pix_fmt_of_2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, &loss); } if (loss_ptr) diff -Nru ffmpeg-4.2.2/libavcodec/imm4.c ffmpeg-4.4/libavcodec/imm4.c --- ffmpeg-4.2.2/libavcodec/imm4.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/imm4.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,7 @@ #include #include +#include "libavutil/mem_internal.h" #include "libavutil/thread.h" #include "avcodec.h" @@ -33,6 +34,11 @@ #include "idctdsp.h" #include "internal.h" +#define CBPLO_VLC_BITS 6 +#define CBPHI_VLC_BITS 6 +#define BLKTYPE_VLC_BITS 9 +#define BLOCK_VLC_BITS 12 + typedef struct IMM4Context { BswapDSPContext bdsp; GetBitContext gb; @@ -58,16 +64,9 @@ 30, 20, 15 }; -static const uint8_t cbplo_symbols[] = { - 3, 4, 19, 20, 35, 36, 51, 52 -}; - -static const uint8_t cbplo_bits[] = { - 1, 4, 3, 6, 3, 6, 3, 6 -}; - -static const uint8_t cbplo_codes[] = { - 1, 1, 1, 1, 2, 2, 3, 3 +static const uint8_t cbplo[][2] = { + { 0,-6 }, { 0x01, 6 }, { 0x02, 6 }, { 0x03, 6 }, { 0x00, 4 }, + { 0x01, 3 }, { 0x02, 3 }, { 0x03, 3 }, { 0x00, 1 }, }; static const uint8_t cbphi_bits[] = { @@ -78,47 +77,36 @@ 3, 5, 4, 9, 3, 7, 2, 11, 2, 3, 5, 10, 4, 8, 6, 3 }; -static const uint8_t blktype_symbols[] = { - 0, 1, 2, 3, 4, 16, 17, 18, 19, 20, 32, 33, 34, 35, 48, 50, 51, 52 -}; - -static const uint8_t blktype_bits[] = { - 1, 3, 3, 5, 6, 4, 7, 7, 8, 9, 4, 7, 7, 8, 6, 8, 7, 9 -}; - -static const uint8_t blktype_codes[] = { - 1, 3, 2, 3, 4, 3, 7, 5, 4, 4, 2, 6, 4, 3, 5, 5, 3, 2 +static const uint8_t blktype[][2] = { + { 0,-8 }, { 0x34, 9 }, { 0,-9 }, { 0x14, 9 }, { 0,-9 }, + { 0x23, 8 }, { 0x13, 8 }, { 0x32, 8 }, { 0x33, 7 }, { 0x22, 7 }, + { 0x12, 7 }, { 0x21, 7 }, { 0x11, 7 }, { 0x04, 6 }, { 0x30, 6 }, + { 0x03, 5 }, { 0x20, 4 }, { 0x10, 4 }, { 0x02, 3 }, { 0x01, 3 }, + { 0x00, 1 }, }; static const uint16_t block_symbols[] = { - 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0x81, 0x82, 0x83, - 0x84, 0x85, 0x86, 0x101, 0x102, 0x103, 0x104, 0x181, 0x182, 0x183, 0x201, 0x202, - 0x203, 0x281, 0x282, 0x283, 0x301, 0x302, 0x303, 0x381, 0x382, 0x401, 0x402, - 0x481, 0x482, 0x501, 0x502, 0x581, 0x601, 0x681, 0x701, 0x781, 0x801, 0x881, - 0x901, 0x981, 0xA01, 0xA81, 0xB01, 0xB81, 0xC01, 0xC81, 0xD01, 0x4001, 0x4002, - 0x4003, 0x4081, 0x4082, 0x4101, 0x4181, 0x4201, 0x4281, 0x4301, 0x4381, 0x4401, - 0x4481, 0x4501, 0x4581, 0x4601, 0x4681, 0x4701, 0x4781, 0x4801, 0x4881, 0x4901, - 0x4981, 0x4A01, 0x4A81, 0x4B01, 0x4B81, 0x4C01, 0x4C81, 0x4D01, 0x4D81, 0x4E01, - 0x4E81, 0x4F01, 0x4F81, 0x5001, 0x5081, 0x5101, 0x5181, 0x5201, 0x5281, 0x5301, - 0x5381, 0x5401 + 0, 0x4082, 0x4003, 0x000B, 0x000A, 0x4E01, 0x4D81, 0x4D01, 0x4C81, + 0x0482, 0x0402, 0x0382, 0x0302, 0x0282, 0x0183, 0x0103, 0x0084, 0x000C, + 0x0085, 0x0B81, 0x0C01, 0x4E81, 0x4F01, 0x4F81, 0x5001, 0x0086, 0x0104, + 0x0203, 0x0283, 0x0303, 0x0502, 0x0C81, 0x0D01, 0x5081, 0x5101, 0x5181, + 0x5201, 0x5281, 0x5301, 0x5381, 0x5401, 0x0000, 0x0009, 0x0008, 0x4C01, + 0x4B81, 0x4B01, 0x4A81, 0x4A01, 0x4981, 0x4901, 0x4881, 0x4002, 0x0B01, + 0x0A81, 0x0A01, 0x0981, 0x0901, 0x0881, 0x0801, 0x0781, 0x0202, 0x0182, + 0x0007, 0x0006, 0x4801, 0x4781, 0x4701, 0x4681, 0x4601, 0x4581, 0x4501, + 0x4481, 0x0701, 0x0681, 0x0102, 0x0083, 0x0005, 0x4401, 0x4381, 0x4301, + 0x4281, 0x0601, 0x0581, 0x0501, 0x0004, 0x4201, 0x4181, 0x4101, 0x4081, + 0x0481, 0x0401, 0x0381, 0x0301, 0x0082, 0x0003, 0x0281, 0x0201, 0x0181, + 0x4001, 0x0001, 0x0081, 0x0101, 0x0002, }; static const uint8_t block_bits[] = { - 7, 2, 4, 6, 7, 8, 9, 9, 10, 10, 11, 11, 11, 3, 6, 8, 10, 11, 12, 4, 8, - 10, 12, 5, 9, 10, 5, 9, 12, 5, 10, 12, 6, 10, 12, 6, 10, 6, 10, 6, - 10, 7, 12, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 12, 12, 4, 9, - 11, 6, 11, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, - 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, - 12, 12 -}; - -static const uint8_t block_codes[] = { - 3, 2, 15, 21, 23, 31, 37, 36, 33, 32, 7, 6, 32, 6, 20, 30, 15, 33, 80, - 14, 29, 14, 81, 13, 35, 13, 12, 34, 82, 11, 12, 83, 19, 11, 84, 18, - 10, 17, 9, 16, 8, 22, 85, 21, 20, 28, 27, 33, 32, 31, 30, 29, 28, - 27, 26, 34, 35, 86, 87, 7, 25, 5, 15, 4, 14, 13, 12, 19, 18, 17, 16, - 26, 25, 24, 23, 22, 21, 20, 19, 24, 23, 22, 21, 20, 19, 18, 17, 7, - 6, 5, 4, 36, 37, 38, 39, 88, 89, 90, 91, 92, 93, 94, 95 + -9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, + 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 7, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 5, 5, 5, 4, 2, 3, 4, 4, }; static VLC cbplo_tab; @@ -130,7 +118,7 @@ { int value; - value = get_vlc2(gb, cbphi_tab.table, cbphi_tab.bits, 1); + value = get_vlc2(gb, cbphi_tab.table, CBPHI_VLC_BITS, 1); if (value < 0) return AVERROR_INVALIDDATA; @@ -147,7 +135,7 @@ for (i = !flag; i < 64; i++) { int value; - value = get_vlc2(gb, block_tab.table, block_tab.bits, 1); + value = get_vlc2(gb, block_tab.table, BLOCK_VLC_BITS, 1); if (value < 0) return AVERROR_INVALIDDATA; if (value == 0) { @@ -234,7 +222,7 @@ for (x = 0; x < avctx->width; x += 16) { unsigned flag, cbphi, cbplo; - cbplo = get_vlc2(gb, cbplo_tab.table, cbplo_tab.bits, 1) >> 4; + cbplo = get_vlc2(gb, cbplo_tab.table, CBPLO_VLC_BITS, 1); flag = get_bits1(gb); cbphi = get_cbphi(gb, 1); @@ -300,7 +288,7 @@ continue; } - value = get_vlc2(gb, blktype_tab.table, blktype_tab.bits, 1); + value = get_vlc2(gb, blktype_tab.table, BLKTYPE_VLC_BITS, 1); if (value < 0) return AVERROR_INVALIDDATA; @@ -488,17 +476,20 @@ static av_cold void imm4_init_static_data(void) { - INIT_VLC_SPARSE_STATIC(&cbplo_tab, 9, FF_ARRAY_ELEMS(cbplo_bits), - cbplo_bits, 1, 1, cbplo_codes, 1, 1, cbplo_symbols, 1, 1, 512); + INIT_VLC_STATIC_FROM_LENGTHS(&cbplo_tab, CBPLO_VLC_BITS, FF_ARRAY_ELEMS(cbplo), + &cbplo[0][1], 2, &cbplo[0][0], 2, 1, + 0, 0, 1 << CBPLO_VLC_BITS); - INIT_VLC_SPARSE_STATIC(&cbphi_tab, 6, FF_ARRAY_ELEMS(cbphi_bits), + INIT_VLC_SPARSE_STATIC(&cbphi_tab, CBPHI_VLC_BITS, FF_ARRAY_ELEMS(cbphi_bits), cbphi_bits, 1, 1, cbphi_codes, 1, 1, NULL, 0, 0, 64); - INIT_VLC_SPARSE_STATIC(&blktype_tab, 9, FF_ARRAY_ELEMS(blktype_bits), - blktype_bits, 1, 1, blktype_codes, 1, 1, blktype_symbols, 1, 1, 512); - - INIT_VLC_SPARSE_STATIC(&block_tab, 12, FF_ARRAY_ELEMS(block_bits), - block_bits, 1, 1, block_codes, 1, 1, block_symbols, 2, 2, 4096); + INIT_VLC_STATIC_FROM_LENGTHS(&blktype_tab, BLKTYPE_VLC_BITS, FF_ARRAY_ELEMS(blktype), + &blktype[0][1], 2, &blktype[0][0], 2, 1, + 0, 0, 1 << BLKTYPE_VLC_BITS); + + INIT_VLC_STATIC_FROM_LENGTHS(&block_tab, BLOCK_VLC_BITS, FF_ARRAY_ELEMS(block_bits), + block_bits, 1, block_symbols, 2, 2, + 0, 0, 1 << BLOCK_VLC_BITS); } static av_cold int decode_init(AVCodecContext *avctx) diff -Nru ffmpeg-4.2.2/libavcodec/imm5.c ffmpeg-4.4/libavcodec/imm5.c --- ffmpeg-4.2.2/libavcodec/imm5.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/imm5.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2019 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" + +#include "avcodec.h" +#include "internal.h" + +typedef struct IMM5Context { + AVCodecContext *h264_avctx; // wrapper context for H264 + AVCodecContext *hevc_avctx; // wrapper context for HEVC +} IMM5Context; + +static const struct IMM5_unit { + uint8_t bits[14]; + uint8_t len; +} IMM5_units[14] = { + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x0B, 0x0F, 0x88 }, 12 }, + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x05, 0x83, 0xE2 }, 12 }, + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x05, 0x81, 0xE8, 0x80 }, 13 }, + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x0B, 0x04, 0xA2 }, 12 }, + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x05, 0x81, 0x28, 0x80 }, 13 }, + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x05, 0x80, 0x92, 0x20 }, 13 }, + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x0B, 0x0F, 0xC8 }, 13 }, + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x05, 0x83, 0xF2 }, 13 }, + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x05, 0x81, 0xEC, 0x80 }, 14 }, + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x0B, 0x04, 0xB2 }, 13 }, + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x05, 0x81, 0x2C, 0x80 }, 14 }, + { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x05, 0x80, 0x93, 0x20 }, 14 }, + { { 0x00, 0x00, 0x00, 0x01, 0x68, 0xDE, 0x3C, 0x80 }, 8 }, + { { 0x00, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x32, 0x28 }, 8 }, +}; + +static av_cold int imm5_init(AVCodecContext *avctx) +{ + IMM5Context *ctx = avctx->priv_data; + const AVCodec *codec; + int ret; + + codec = avcodec_find_decoder(AV_CODEC_ID_H264); + if (!codec) + return AVERROR_BUG; + ctx->h264_avctx = avcodec_alloc_context3(codec); + if (!ctx->h264_avctx) + return AVERROR(ENOMEM); + ctx->h264_avctx->thread_count = 1; + ctx->h264_avctx->flags = avctx->flags; + ctx->h264_avctx->flags2 = avctx->flags2; + ret = avcodec_open2(ctx->h264_avctx, codec, NULL); + if (ret < 0) + return ret; + + codec = avcodec_find_decoder(AV_CODEC_ID_HEVC); + if (!codec) + return AVERROR_BUG; + ctx->hevc_avctx = avcodec_alloc_context3(codec); + if (!ctx->hevc_avctx) + return AVERROR(ENOMEM); + ctx->hevc_avctx->thread_count = 1; + ctx->hevc_avctx->flags = avctx->flags; + ctx->hevc_avctx->flags2 = avctx->flags2; + ret = avcodec_open2(ctx->hevc_avctx, codec, NULL); + if (ret < 0) + return ret; + + return 0; +} + +static int imm5_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + IMM5Context *ctx = avctx->priv_data; + AVFrame *frame = data; + AVCodecContext *codec_avctx = ctx->h264_avctx; + int ret; + + if (avpkt->size > 24 && avpkt->data[8] <= 1 && AV_RL32(avpkt->data + 4) + 24ULL <= avpkt->size) { + int codec_type = avpkt->data[1]; + int index = avpkt->data[10]; + int new_size = AV_RL32(avpkt->data + 4); + int offset, off; + + if (codec_type == 0xA) { + codec_avctx = ctx->hevc_avctx; + } else if (index == 17) { + index = 4; + } else if (index == 18) { + index = 5; + } + + if (index >= 1 && index <= 12) { + ret = av_packet_make_writable(avpkt); + if (ret < 0) + return ret; + + index -= 1; + off = offset = IMM5_units[index].len; + if (codec_type == 2) { + offset += IMM5_units[12].len; + } else { + offset += IMM5_units[13].len; + } + + avpkt->data += 24 - offset; + avpkt->size = new_size + offset; + + memcpy(avpkt->data, IMM5_units[index].bits, IMM5_units[index].len); + if (codec_type == 2) { + memcpy(avpkt->data + off, IMM5_units[12].bits, IMM5_units[12].len); + } else { + memcpy(avpkt->data + off, IMM5_units[13].bits, IMM5_units[13].len); + } + } else { + avpkt->data += 24; + avpkt->size -= 24; + } + } + + ret = avcodec_send_packet(codec_avctx, avpkt); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); + return ret; + } + + ret = avcodec_receive_frame(codec_avctx, frame); + if (ret < 0) + return ret; + + avctx->pix_fmt = codec_avctx->pix_fmt; + avctx->coded_width = codec_avctx->coded_width; + avctx->coded_height = codec_avctx->coded_height; + avctx->width = codec_avctx->width; + avctx->height = codec_avctx->height; + avctx->bit_rate = codec_avctx->bit_rate; + avctx->colorspace = codec_avctx->colorspace; + avctx->color_range = codec_avctx->color_range; + avctx->color_trc = codec_avctx->color_trc; + avctx->color_primaries = codec_avctx->color_primaries; + avctx->chroma_sample_location = codec_avctx->chroma_sample_location; + + *got_frame = 1; + + return avpkt->size; +} + +static void imm5_flush(AVCodecContext *avctx) +{ + IMM5Context *ctx = avctx->priv_data; + + avcodec_flush_buffers(ctx->h264_avctx); + avcodec_flush_buffers(ctx->hevc_avctx); +} + +static av_cold int imm5_close(AVCodecContext *avctx) +{ + IMM5Context *ctx = avctx->priv_data; + + avcodec_free_context(&ctx->h264_avctx); + avcodec_free_context(&ctx->hevc_avctx); + + return 0; +} + +AVCodec ff_imm5_decoder = { + .name = "imm5", + .long_name = NULL_IF_CONFIG_SMALL("Infinity IMM5"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_IMM5, + .init = imm5_init, + .decode = imm5_decode_frame, + .close = imm5_close, + .flush = imm5_flush, + .priv_data_size = sizeof(IMM5Context), + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff -Nru ffmpeg-4.2.2/libavcodec/imx.c ffmpeg-4.4/libavcodec/imx.c --- ffmpeg-4.2.2/libavcodec/imx.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/imx.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,197 @@ +/* + * 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 "libavutil/common.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct SimbiosisIMXContext { + AVFrame *frame; + uint32_t pal[256]; + uint8_t history[32768]; + int pos; +} SimbiosisIMXContext; + +static av_cold int imx_decode_init(AVCodecContext *avctx) +{ + SimbiosisIMXContext *imx = avctx->priv_data; + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + avctx->width = 320; + avctx->height = 160; + + imx->frame = av_frame_alloc(); + if (!imx->frame) + return AVERROR(ENOMEM); + + return 0; +} + +static int imx_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + SimbiosisIMXContext *imx = avctx->priv_data; + int ret, x, y; + buffer_size_t pal_size; + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size); + AVFrame *frame = imx->frame; + GetByteContext gb; + + if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0) + return ret; + + if (pal && pal_size == AVPALETTE_SIZE) { + memcpy(imx->pal, pal, pal_size); + frame->palette_has_changed = 1; + frame->key_frame = 1; + } else { + frame->key_frame = 0; + frame->palette_has_changed = 0; + } + + bytestream2_init(&gb, avpkt->data, avpkt->size); + + memcpy(frame->data[1], imx->pal, AVPALETTE_SIZE); + + x = 0, y = 0; + while (bytestream2_get_bytes_left(&gb) > 0 && + x < 320 && y < 160) { + int b = bytestream2_get_byte(&gb); + int len = b & 0x3f; + int op = b >> 6; + int fill; + + switch (op) { + case 3: + len = len * 64 + bytestream2_get_byte(&gb); + case 0: + while (len > 0) { + x++; + len--; + if (x >= 320) { + x = 0; + y++; + } + if (y >= 160) + break; + } + + frame->key_frame = 0; + break; + case 1: + if (len == 0) { + int offset = bytestream2_get_le16(&gb); + + if (offset < 0 || offset >= 32768) + return AVERROR_INVALIDDATA; + + len = bytestream2_get_byte(&gb); + while (len > 0 && offset < 32768) { + frame->data[0][x + y * frame->linesize[0]] = imx->history[offset++]; + x++; + len--; + if (x >= 320) { + x = 0; + y++; + } + if (y >= 160) + break; + } + + frame->key_frame = 0; + } else { + while (len > 0) { + fill = bytestream2_get_byte(&gb); + frame->data[0][x + y * frame->linesize[0]] = fill; + if (imx->pos < 32768) + imx->history[imx->pos++] = fill; + x++; + len--; + if (x >= 320) { + x = 0; + y++; + } + if (y >= 160) + break; + } + } + break; + case 2: + fill = bytestream2_get_byte(&gb); + + while (len > 0) { + frame->data[0][x + y * frame->linesize[0]] = fill; + x++; + len--; + if (x >= 320) { + x = 0; + y++; + } + if (y >= 160) + break; + } + break; + } + } + + frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + + if ((ret = av_frame_ref(data, frame)) < 0) + return ret; + + *got_frame = 1; + + return avpkt->size; +} + +static void imx_decode_flush(AVCodecContext *avctx) +{ + SimbiosisIMXContext *imx = avctx->priv_data; + + av_frame_unref(imx->frame); + imx->pos = 0; + memset(imx->pal, 0, sizeof(imx->pal)); + memset(imx->history, 0, sizeof(imx->history)); +} + +static int imx_decode_close(AVCodecContext *avctx) +{ + SimbiosisIMXContext *imx = avctx->priv_data; + + av_frame_free(&imx->frame); + + return 0; +} + +AVCodec ff_simbiosis_imx_decoder = { + .name = "simbiosis_imx", + .long_name = NULL_IF_CONFIG_SMALL("Simbiosis Interactive IMX Video"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SIMBIOSIS_IMX, + .priv_data_size = sizeof(SimbiosisIMXContext), + .init = imx_decode_init, + .decode = imx_decode_frame, + .close = imx_decode_close, + .flush = imx_decode_flush, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff -Nru ffmpeg-4.2.2/libavcodec/imx_dump_header_bsf.c ffmpeg-4.4/libavcodec/imx_dump_header_bsf.c --- ffmpeg-4.2.2/libavcodec/imx_dump_header_bsf.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/imx_dump_header_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -25,8 +25,8 @@ * modifies bitstream to fit in mov and be decoded by final cut pro decoder */ -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "bytestream.h" diff -Nru ffmpeg-4.2.2/libavcodec/indeo2.c ffmpeg-4.4/libavcodec/indeo2.c --- ffmpeg-4.2.2/libavcodec/indeo2.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/indeo2.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,6 +25,7 @@ */ #include "libavutil/attributes.h" +#include "libavutil/thread.h" #define BITSTREAM_READER_LE #include "avcodec.h" @@ -46,7 +47,7 @@ /* Indeo 2 codes are in range 0x01..0x7F and 0x81..0x90 */ static inline int ir2_get_code(GetBitContext *gb) { - return get_vlc2(gb, ir2_vlc.table, CODE_VLC_BITS, 1) + 1; + return get_vlc2(gb, ir2_vlc.table, CODE_VLC_BITS, 1); } static int ir2_decode_plane(Ir2Context *ctx, int width, int height, uint8_t *dst, @@ -161,7 +162,7 @@ int start, ret; int ltab, ctab; - if ((ret = ff_reget_buffer(avctx, p)) < 0) + if ((ret = ff_reget_buffer(avctx, p, 0)) < 0) return ret; start = 48; /* hardcoded for now */ @@ -174,10 +175,6 @@ s->decode_delta = buf[18]; /* decide whether frame uses deltas or not */ -#ifndef BITSTREAM_READER_LE - for (i = 0; i < buf_size; i++) - buf[i] = ff_reverse[buf[i]]; -#endif if ((ret = init_get_bits8(&s->gb, buf + start, buf_size - start)) < 0) return ret; @@ -229,10 +226,17 @@ return buf_size; } +static av_cold void ir2_init_static(void) +{ + INIT_VLC_STATIC_FROM_LENGTHS(&ir2_vlc, CODE_VLC_BITS, IR2_CODES, + &ir2_tab[0][1], 2, &ir2_tab[0][0], 2, 1, + 0, INIT_VLC_OUTPUT_LE, 1 << CODE_VLC_BITS); +} + static av_cold int ir2_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; Ir2Context * const ic = avctx->priv_data; - static VLC_TYPE vlc_tables[1 << CODE_VLC_BITS][2]; ic->avctx = avctx; @@ -242,17 +246,7 @@ if (!ic->picture) return AVERROR(ENOMEM); - ir2_vlc.table = vlc_tables; - ir2_vlc.table_allocated = 1 << CODE_VLC_BITS; -#ifdef BITSTREAM_READER_LE - init_vlc(&ir2_vlc, CODE_VLC_BITS, IR2_CODES, - &ir2_codes[0][1], 4, 2, - &ir2_codes[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); -#else - init_vlc(&ir2_vlc, CODE_VLC_BITS, IR2_CODES, - &ir2_codes[0][1], 4, 2, - &ir2_codes[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC); -#endif + ff_thread_once(&init_static_once, ir2_init_static); return 0; } @@ -276,4 +270,5 @@ .close = ir2_decode_end, .decode = ir2_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/indeo2data.h ffmpeg-4.4/libavcodec/indeo2data.h --- ffmpeg-4.2.2/libavcodec/indeo2data.h 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/indeo2data.h 2021-04-08 21:28:39.000000000 +0000 @@ -25,43 +25,36 @@ #include #define IR2_CODES 143 -static const uint16_t ir2_codes[IR2_CODES][2] = { - { 0x0000, 3 }, { 0x0004, 3 }, { 0x0006, 3 }, { 0x0001, 5 }, - { 0x0009, 5 }, { 0x0019, 5 }, { 0x000D, 5 }, { 0x001D, 5 }, - { 0x0023, 6 }, { 0x0013, 6 }, { 0x0033, 6 }, { 0x000B, 6 }, - { 0x002B, 6 }, { 0x001B, 6 }, { 0x0007, 8 }, { 0x0087, 8 }, - { 0x0027, 8 }, { 0x00A7, 8 }, { 0x0067, 8 }, { 0x00E7, 8 }, - { 0x0097, 8 }, { 0x0057, 8 }, { 0x0037, 8 }, { 0x00B7, 8 }, - { 0x00F7, 8 }, { 0x000F, 9 }, { 0x008F, 9 }, { 0x018F, 9 }, - { 0x014F, 9 }, { 0x00CF, 9 }, { 0x002F, 9 }, { 0x012F, 9 }, - { 0x01AF, 9 }, { 0x006F, 9 }, { 0x00EF, 9 }, { 0x01EF, 9 }, - { 0x001F, 10 }, { 0x021F, 10 }, { 0x011F, 10 }, { 0x031F, 10 }, - { 0x009F, 10 }, { 0x029F, 10 }, { 0x019F, 10 }, { 0x039F, 10 }, - { 0x005F, 10 }, { 0x025F, 10 }, { 0x015F, 10 }, { 0x035F, 10 }, - { 0x00DF, 10 }, { 0x02DF, 10 }, { 0x01DF, 10 }, { 0x03DF, 10 }, - { 0x003F, 13 }, { 0x103F, 13 }, { 0x083F, 13 }, { 0x183F, 13 }, - { 0x043F, 13 }, { 0x143F, 13 }, { 0x0C3F, 13 }, { 0x1C3F, 13 }, - { 0x023F, 13 }, { 0x123F, 13 }, { 0x0A3F, 13 }, { 0x1A3F, 13 }, - { 0x063F, 13 }, { 0x163F, 13 }, { 0x0E3F, 13 }, { 0x1E3F, 13 }, - { 0x013F, 13 }, { 0x113F, 13 }, { 0x093F, 13 }, { 0x193F, 13 }, - { 0x053F, 13 }, { 0x153F, 13 }, { 0x0D3F, 13 }, { 0x1D3F, 13 }, - { 0x033F, 13 }, { 0x133F, 13 }, { 0x0B3F, 13 }, { 0x1B3F, 13 }, - { 0x073F, 13 }, { 0x173F, 13 }, { 0x0F3F, 13 }, { 0x1F3F, 13 }, - { 0x00BF, 13 }, { 0x10BF, 13 }, { 0x08BF, 13 }, { 0x18BF, 13 }, - { 0x04BF, 13 }, { 0x14BF, 13 }, { 0x0CBF, 13 }, { 0x1CBF, 13 }, - { 0x02BF, 13 }, { 0x12BF, 13 }, { 0x0ABF, 13 }, { 0x1ABF, 13 }, - { 0x06BF, 13 }, { 0x16BF, 13 }, { 0x0EBF, 13 }, { 0x1EBF, 13 }, - { 0x01BF, 13 }, { 0x11BF, 13 }, { 0x09BF, 13 }, { 0x19BF, 13 }, - { 0x05BF, 13 }, { 0x15BF, 13 }, { 0x0DBF, 13 }, { 0x1DBF, 13 }, - { 0x03BF, 13 }, { 0x13BF, 13 }, { 0x0BBF, 13 }, { 0x1BBF, 13 }, - { 0x07BF, 13 }, { 0x17BF, 13 }, { 0x0FBF, 13 }, { 0x1FBF, 13 }, - { 0x007F, 14 }, { 0x207F, 14 }, { 0x107F, 14 }, { 0x307F, 14 }, - { 0x087F, 14 }, { 0x287F, 14 }, { 0x187F, 14 }, { 0x387F, 14 }, - { 0x047F, 14 }, { 0x247F, 14 }, { 0x147F, 14 }, { 0x0002, 3 }, - { 0x0011, 5 }, { 0x0005, 5 }, { 0x0015, 5 }, { 0x0003, 6 }, - { 0x003B, 6 }, { 0x0047, 8 }, { 0x00C7, 8 }, { 0x0017, 8 }, - { 0x00D7, 8 }, { 0x0077, 8 }, { 0x010F, 9 }, { 0x004F, 9 }, - { 0x01CF, 9 }, { 0x00AF, 9 }, { 0x016F, 9 }, +static const uint8_t ir2_tab[IR2_CODES][2] = { + { 0x01, 3 }, { 0x02, 3 }, { 0x80, 3 }, { 0x03, 3 }, { 0x04, 5 }, + { 0x81, 5 }, { 0x05, 5 }, { 0x06, 5 }, { 0x82, 5 }, { 0x83, 5 }, + { 0x07, 5 }, { 0x08, 5 }, { 0x84, 6 }, { 0x09, 6 }, { 0x0A, 6 }, + { 0x0B, 6 }, { 0x0C, 6 }, { 0x0D, 6 }, { 0x0E, 6 }, { 0x85, 6 }, + { 0x0F, 8 }, { 0x10, 8 }, { 0x86, 8 }, { 0x87, 8 }, { 0x11, 8 }, + { 0x12, 8 }, { 0x13, 8 }, { 0x14, 8 }, { 0x88, 8 }, { 0x15, 8 }, + { 0x16, 8 }, { 0x89, 8 }, { 0x17, 8 }, { 0x18, 8 }, { 0x8A, 8 }, + { 0x19, 8 }, { 0x1A, 9 }, { 0x8B, 9 }, { 0x1B, 9 }, { 0x1C, 9 }, + { 0x8C, 9 }, { 0x1D, 9 }, { 0x1E, 9 }, { 0x8D, 9 }, { 0x1F, 9 }, + { 0x20, 9 }, { 0x8E, 9 }, { 0x21, 9 }, { 0x22, 9 }, { 0x8F, 9 }, + { 0x23, 9 }, { 0x24, 9 }, { 0x25, 10 }, { 0x26, 10 }, { 0x27, 10 }, + { 0x28, 10 }, { 0x29, 10 }, { 0x2A, 10 }, { 0x2B, 10 }, { 0x2C, 10 }, + { 0x2D, 10 }, { 0x2E, 10 }, { 0x2F, 10 }, { 0x30, 10 }, { 0x31, 10 }, + { 0x32, 10 }, { 0x33, 10 }, { 0x34, 10 }, { 0x35, 13 }, { 0x36, 13 }, + { 0x37, 13 }, { 0x38, 13 }, { 0x39, 13 }, { 0x3A, 13 }, { 0x3B, 13 }, + { 0x3C, 13 }, { 0x3D, 13 }, { 0x3E, 13 }, { 0x3F, 13 }, { 0x40, 13 }, + { 0x41, 13 }, { 0x42, 13 }, { 0x43, 13 }, { 0x44, 13 }, { 0x45, 13 }, + { 0x46, 13 }, { 0x47, 13 }, { 0x48, 13 }, { 0x49, 13 }, { 0x4A, 13 }, + { 0x4B, 13 }, { 0x4C, 13 }, { 0x4D, 13 }, { 0x4E, 13 }, { 0x4F, 13 }, + { 0x50, 13 }, { 0x51, 13 }, { 0x52, 13 }, { 0x53, 13 }, { 0x54, 13 }, + { 0x55, 13 }, { 0x56, 13 }, { 0x57, 13 }, { 0x58, 13 }, { 0x59, 13 }, + { 0x5A, 13 }, { 0x5B, 13 }, { 0x5C, 13 }, { 0x5D, 13 }, { 0x5E, 13 }, + { 0x5F, 13 }, { 0x60, 13 }, { 0x61, 13 }, { 0x62, 13 }, { 0x63, 13 }, + { 0x64, 13 }, { 0x65, 13 }, { 0x66, 13 }, { 0x67, 13 }, { 0x68, 13 }, + { 0x69, 13 }, { 0x6A, 13 }, { 0x6B, 13 }, { 0x6C, 13 }, { 0x6D, 13 }, + { 0x6E, 13 }, { 0x6F, 13 }, { 0x70, 13 }, { 0x71, 13 }, { 0x72, 13 }, + { 0x73, 13 }, { 0x74, 13 }, { 0x75, 14 }, { 0x76, 14 }, { 0x77, 14 }, + { 0x78, 14 }, { 0x79, 14 }, { 0x7A, 14 }, { 0x7B, 14 }, { 0x7C, 14 }, + { 0x7D, 14 }, { 0x7E, 14 }, { 0x7F, 14 }, }; static const uint8_t ir2_delta_table[4][256] = { diff -Nru ffmpeg-4.2.2/libavcodec/indeo3.c ffmpeg-4.4/libavcodec/indeo3.c --- ffmpeg-4.2.2/libavcodec/indeo3.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/indeo3.c 2021-04-08 21:28:39.000000000 +0000 @@ -171,7 +171,7 @@ if (luma_width < 16 || luma_width > 640 || luma_height < 16 || luma_height > 480 || - luma_width & 3 || luma_height & 3) { + luma_width & 1 || luma_height & 1) { av_log(avctx, AV_LOG_ERROR, "Invalid picture dimensions: %d x %d!\n", luma_width, luma_height); return AVERROR_INVALIDDATA; @@ -203,10 +203,8 @@ ctx->planes[p].buffers[0] = av_malloc(!p ? luma_size : chroma_size); ctx->planes[p].buffers[1] = av_malloc(!p ? luma_size : chroma_size); - if (!ctx->planes[p].buffers[0] || !ctx->planes[p].buffers[1]) { - free_frame_buffers(ctx); + if (!ctx->planes[p].buffers[0] || !ctx->planes[p].buffers[1]) return AVERROR(ENOMEM); - } /* fill the INTRA prediction lines with the middle pixel value = 64 */ memset(ctx->planes[p].buffers[0], 0x40, ctx->planes[p].pitch); @@ -1143,4 +1141,5 @@ .close = decode_close, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/indeo4.c ffmpeg-4.4/libavcodec/indeo4.c --- ffmpeg-4.2.2/libavcodec/indeo4.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/indeo4.c 2021-04-08 21:28:39.000000000 +0000 @@ -713,4 +713,5 @@ .close = ff_ivi_decode_close, .decode = ff_ivi_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/indeo5.c ffmpeg-4.4/libavcodec/indeo5.c --- ffmpeg-4.2.2/libavcodec/indeo5.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/indeo5.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" +#include "internal.h" #include "ivi.h" #include "ivi_dsp.h" #include "indeo5data.h" @@ -264,7 +265,7 @@ } if (get_bits1(&ctx->gb)) - skip_bits_long(&ctx->gb, 24); /* skip transparency fill color */ + skip_bits(&ctx->gb, 24); /* skip transparency fill color */ } align_get_bits(&ctx->gb); @@ -348,7 +349,7 @@ if (ctx->frame_type != FRAMETYPE_NULL) { ctx->frame_flags = get_bits(&ctx->gb, 8); - ctx->pic_hdr_size = (ctx->frame_flags & 1) ? get_bits_long(&ctx->gb, 24) : 0; + ctx->pic_hdr_size = (ctx->frame_flags & 1) ? get_bits(&ctx->gb, 24) : 0; ctx->checksum = (ctx->frame_flags & 0x10) ? get_bits(&ctx->gb, 16) : 0; @@ -392,7 +393,7 @@ return 0; } - band->data_size = (ctx->frame_flags & 0x80) ? get_bits_long(&ctx->gb, 24) : 0; + band->data_size = (ctx->frame_flags & 0x80) ? get_bits(&ctx->gb, 24) : 0; band->inherit_mv = band_flags & 2; band->inherit_qdelta = band_flags & 8; @@ -692,4 +693,5 @@ .close = ff_ivi_decode_close, .decode = ff_ivi_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/intelh263dec.c ffmpeg-4.4/libavcodec/intelh263dec.c --- ffmpeg-4.2.2/libavcodec/intelh263dec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/intelh263dec.c 2020-07-11 10:39:30.000000000 +0000 @@ -33,7 +33,7 @@ } /* picture header */ - if (get_bits_long(&s->gb, 22) != 0x20) { + if (get_bits(&s->gb, 22) != 0x20) { av_log(s->avctx, AV_LOG_ERROR, "Bad picture start code\n"); return -1; } diff -Nru ffmpeg-4.2.2/libavcodec/internal.h ffmpeg-4.4/libavcodec/internal.h --- ffmpeg-4.2.2/libavcodec/internal.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/internal.h 2021-04-08 21:28:39.000000000 +0000 @@ -28,6 +28,7 @@ #include "libavutil/buffer.h" #include "libavutil/channel_layout.h" +#include "libavutil/fifo.h" #include "libavutil/mathematics.h" #include "libavutil/pixfmt.h" #include "avcodec.h" @@ -68,6 +69,21 @@ * Codec initializes slice-based threading with a main function */ #define FF_CODEC_CAP_SLICE_THREAD_HAS_MF (1 << 5) +/* + * The codec supports frame threading and has inter-frame dependencies, so it + * uses ff_thread_report/await_progress(). + */ +#define FF_CODEC_CAP_ALLOCATE_PROGRESS (1 << 6) +/** + * Codec handles avctx->thread_count == 0 (auto) internally. + */ +#define FF_CODEC_CAP_AUTO_THREADS (1 << 7) + +/** + * AVCodec.codec_tags termination value + */ +#define FF_CODEC_TAGS_END -1 + #ifdef TRACE # define ff_tlog(ctx, ...) av_log(ctx, AV_LOG_TRACE, __VA_ARGS__) @@ -83,7 +99,7 @@ #define FF_QSCALE_TYPE_H264 2 #define FF_QSCALE_TYPE_VP56 3 -#define FF_SANE_NB_CHANNELS 256U +#define FF_SANE_NB_CHANNELS 512U #define FF_SIGNBIT(x) ((x) >> CHAR_BIT * sizeof(x) - 1) @@ -97,34 +113,13 @@ # define STRIDE_ALIGN 8 #endif -typedef struct FramePool { - /** - * Pools for each data plane. For audio all the planes have the same size, - * so only pools[0] is used. - */ - AVBufferPool *pools[4]; - - /* - * Pool parameters - */ - int format; - int width, height; - int stride_align[AV_NUM_DATA_POINTERS]; - int linesize[4]; - int planes; - int channels; - int samples; -} FramePool; - typedef struct DecodeSimpleContext { AVPacket *in_pkt; - AVFrame *out_frame; } DecodeSimpleContext; -typedef struct DecodeFilterContext { - AVBSFContext **bsfs; - int nb_bsfs; -} DecodeFilterContext; +typedef struct EncodeSimpleContext { + AVFrame *in_frame; +} EncodeSimpleContext; typedef struct AVCodecInternal { /** @@ -136,40 +131,28 @@ int is_copy; /** - * Whether to allocate progress for frame threading. - * - * The codec must set it to 1 if it uses ff_thread_await/report_progress(), - * then progress will be allocated in ff_thread_get_buffer(). The frames - * then MUST be freed with ff_thread_release_buffer(). - * - * If the codec does not need to call the progress functions (there are no - * dependencies between the frames), it should leave this at 0. Then it can - * decode straight to the user-provided frames (which the user will then - * free with av_frame_unref()), there is no need to call - * ff_thread_release_buffer(). - */ - int allocate_progress; - - /** * An audio frame with less than required samples has been submitted and * padded with silence. Reject all subsequent frames. */ int last_audio_frame; +#if FF_API_OLD_ENCDEC AVFrame *to_free; +#endif - FramePool *pool; + AVBufferRef *pool; void *thread_ctx; DecodeSimpleContext ds; - DecodeFilterContext filter; + AVBSFContext *bsf; /** * Properties (timestamps+side data) extracted from the last packet passed * for decoding. */ AVPacket *last_pkt_props; + AVFifoBuffer *pkt_props; /** * temporary buffer used for encoders to store their bitstream @@ -179,6 +162,8 @@ void *frame_thread_encoder; + EncodeSimpleContext es; + /** * Number of audio samples to skip at the start of the next decoded frame */ @@ -198,11 +183,10 @@ * buffers for using new encode/decode API through legacy API */ AVPacket *buffer_pkt; - int buffer_pkt_valid; // encoding: packet without data can be valid AVFrame *buffer_frame; int draining_done; - /* set to 1 when the caller is using the old decoding API */ - int compat_decode; + +#if FF_API_OLD_ENCDEC int compat_decode_warned; /* this variable is set by the decoder internals to signal to the old * API compat wrappers the amount of data consumed from the last packet */ @@ -211,6 +195,8 @@ * of the packet (that should be submitted in the next decode call */ size_t compat_decode_partial_size; AVFrame *compat_decode_frame; + AVPacket *compat_encode_packet; +#endif int showed_multi_packet_warning; @@ -280,8 +266,6 @@ */ int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64_t min_size); -attribute_deprecated int ff_alloc_packet(AVPacket *avpkt, int size); - /** * Rescale from sample rate to AVCodecContext.time_base. */ @@ -320,28 +304,17 @@ */ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags); +#define FF_REGET_BUFFER_FLAG_READONLY 1 ///< the returned buffer does not need to be writable /** - * Identical in function to av_frame_make_writable(), except it uses - * ff_get_buffer() to allocate the buffer when needed. + * Identical in function to ff_get_buffer(), except it reuses the existing buffer + * if available. */ -int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame); +int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags); int ff_thread_can_start_frame(AVCodecContext *avctx); int avpriv_h264_has_num_reorder_frames(AVCodecContext *avctx); -/** - * Call avcodec_open2 recursively by decrementing counter, unlocking mutex, - * calling the function and then restoring again. Assumes the mutex is - * already locked - */ -int ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); - -/** - * Finalize buf into extradata and set its size appropriately. - */ -int avpriv_bprint_to_extradata(AVCodecContext *avctx, struct AVBPrint *buf); - const uint8_t *avpriv_find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state); @@ -380,30 +353,24 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt); /** - * Set various frame properties from the codec context / packet data. - */ -int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame); - -/** * Add a CPB properties side data to an encoding context. */ AVCPBProperties *ff_add_cpb_side_data(AVCodecContext *avctx); -int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type); - /** - * Check AVFrame for A53 side data and allocate and fill SEI message with A53 info + * Check AVFrame for S12M timecode side data and allocate and fill TC SEI message with timecode info * - * @param frame Raw frame to get A53 side data from + * @param frame Raw frame to get S12M timecode side data from + * @param rate The frame rate * @param prefix_len Number of bytes to allocate before SEI message * @param data Pointer to a variable to store allocated memory - * Upon return the variable will hold NULL on error or if frame has no A53 info. + * Upon return the variable will hold NULL on error or if frame has no S12M timecode info. * Otherwise it will point to prefix_len uninitialized bytes followed by * *sei_size SEI message * @param sei_size Pointer to a variable to store generated SEI message length * @return Zero on success, negative error code on failure */ -int ff_alloc_a53_sei(const AVFrame *frame, size_t prefix_len, +int ff_alloc_timecode_sei(const AVFrame *frame, AVRational rate, size_t prefix_len, void **data, size_t *sei_size); /** @@ -424,6 +391,8 @@ int ff_int_from_list_or_default(void *ctx, const char * val_name, int val, const int * array_valid_values, int default_value); +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 diff -Nru ffmpeg-4.2.2/libavcodec/interplayacm.c ffmpeg-4.4/libavcodec/interplayacm.c --- ffmpeg-4.2.2/libavcodec/interplayacm.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/interplayacm.c 2020-07-11 10:39:30.000000000 +0000 @@ -435,7 +435,8 @@ static void juggle(int *wrap_p, int *block_p, unsigned sub_len, unsigned sub_count) { unsigned i, j; - int *p, r0, r1, r2, r3; + int *p; + unsigned int r0, r1, r2, r3; for (i = 0; i < sub_len; i++) { p = block_p; diff -Nru ffmpeg-4.2.2/libavcodec/interplayvideo.c ffmpeg-4.4/libavcodec/interplayvideo.c --- ffmpeg-4.2.2/libavcodec/interplayvideo.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/interplayvideo.c 2021-04-08 21:28:39.000000000 +0000 @@ -77,9 +77,14 @@ static int copy_from(IpvideoContext *s, AVFrame *src, AVFrame *dst, int delta_x, int delta_y) { + int width = dst->width; int current_offset = s->pixel_ptr - dst->data[0]; - int motion_offset = current_offset + delta_y * dst->linesize[0] - + delta_x * (1 + s->is_16bpp); + int x = (current_offset % dst->linesize[0]) / (1 + s->is_16bpp); + int y = current_offset / dst->linesize[0]; + int dx = delta_x + x - ((delta_x + x >= width) - (delta_x + x < 0)) * width; + int dy = delta_y + y + (delta_x + x >= width) - (delta_x + x < 0); + int motion_offset = dy * src->linesize[0] + dx * (1 + s->is_16bpp); + if (motion_offset < 0) { av_log(s->avctx, AV_LOG_ERROR, "motion offset < 0 (%d)\n", motion_offset); return AVERROR_INVALIDDATA; @@ -931,12 +936,12 @@ int off_x, off_y; if (opcode < 0) { - off_x = ((uint16_t)opcode - 0xC000) % frame->linesize[0]; - off_y = ((uint16_t)opcode - 0xC000) / frame->linesize[0]; + off_x = ((uint16_t)opcode - 0xC000) % frame->width; + off_y = ((uint16_t)opcode - 0xC000) / frame->width; copy_from(s, s->last_frame, frame, off_x, off_y); } else if (opcode > 0) { - off_x = ((uint16_t)opcode - 0x4000) % frame->linesize[0]; - off_y = ((uint16_t)opcode - 0x4000) / frame->linesize[0]; + off_x = ((uint16_t)opcode - 0x4000) % frame->width; + off_y = ((uint16_t)opcode - 0x4000) / frame->width; copy_from(s, frame, frame, off_x, off_y); } } @@ -1001,12 +1006,12 @@ int off_x, off_y; if (opcode < 0) { - off_x = ((uint16_t)opcode - 0xC000) % s->cur_decode_frame->linesize[0]; - off_y = ((uint16_t)opcode - 0xC000) / s->cur_decode_frame->linesize[0]; + off_x = ((uint16_t)opcode - 0xC000) % s->cur_decode_frame->width; + off_y = ((uint16_t)opcode - 0xC000) / s->cur_decode_frame->width; copy_from(s, s->prev_decode_frame, s->cur_decode_frame, off_x, off_y); } else if (opcode > 0) { - off_x = ((uint16_t)opcode - 0x4000) % s->cur_decode_frame->linesize[0]; - off_y = ((uint16_t)opcode - 0x4000) / s->cur_decode_frame->linesize[0]; + off_x = ((uint16_t)opcode - 0x4000) % s->cur_decode_frame->width; + off_y = ((uint16_t)opcode - 0x4000) / s->cur_decode_frame->width; copy_from(s, s->cur_decode_frame, s->cur_decode_frame, off_x, off_y); } } @@ -1155,7 +1160,6 @@ static av_cold int ipvideo_decode_init(AVCodecContext *avctx) { IpvideoContext *s = avctx->priv_data; - int ret; s->avctx = avctx; @@ -1170,8 +1174,7 @@ s->prev_decode_frame = av_frame_alloc(); if (!s->last_frame || !s->second_last_frame || !s->cur_decode_frame || !s->prev_decode_frame) { - ret = AVERROR(ENOMEM); - goto error; + return AVERROR(ENOMEM); } s->cur_decode_frame->width = avctx->width; @@ -1181,21 +1184,7 @@ s->cur_decode_frame->format = avctx->pix_fmt; s->prev_decode_frame->format = avctx->pix_fmt; - ret = ff_get_buffer(avctx, s->cur_decode_frame, 0); - if (ret < 0) - goto error; - - ret = ff_get_buffer(avctx, s->prev_decode_frame, 0); - if (ret < 0) - goto error; - return 0; -error: - av_frame_free(&s->last_frame); - av_frame_free(&s->second_last_frame); - av_frame_free(&s->cur_decode_frame); - av_frame_free(&s->prev_decode_frame); - return ret; } static int ipvideo_decode_frame(AVCodecContext *avctx, @@ -1239,83 +1228,83 @@ s->decoding_map_size = AV_RL16(buf + 4); s->skip_map_size = AV_RL16(buf + 6); - switch(frame_format) { - case 0x06: - if (s->decoding_map_size) { - av_log(avctx, AV_LOG_ERROR, "Decoding map for format 0x06\n"); - return AVERROR_INVALIDDATA; - } + switch (frame_format) { + case 0x06: + if (s->decoding_map_size) { + av_log(avctx, AV_LOG_ERROR, "Decoding map for format 0x06\n"); + return AVERROR_INVALIDDATA; + } - if (s->skip_map_size) { - av_log(avctx, AV_LOG_ERROR, "Skip map for format 0x06\n"); - return AVERROR_INVALIDDATA; - } + if (s->skip_map_size) { + av_log(avctx, AV_LOG_ERROR, "Skip map for format 0x06\n"); + return AVERROR_INVALIDDATA; + } - if (s->is_16bpp) { - av_log(avctx, AV_LOG_ERROR, "Video format 0x06 does not support 16bpp movies\n"); - return AVERROR_INVALIDDATA; - } + if (s->is_16bpp) { + av_log(avctx, AV_LOG_ERROR, "Video format 0x06 does not support 16bpp movies\n"); + return AVERROR_INVALIDDATA; + } - /* Decoding map for 0x06 frame format is at the top of pixeldata */ - s->decoding_map_size = ((s->avctx->width / 8) * (s->avctx->height / 8)) * 2; - s->decoding_map = buf + 8 + 14; /* 14 bits of op data */ - video_data_size -= s->decoding_map_size + 14; - if (video_data_size <= 0 || s->decoding_map_size == 0) - return AVERROR_INVALIDDATA; + /* Decoding map for 0x06 frame format is at the top of pixeldata */ + s->decoding_map_size = ((s->avctx->width / 8) * (s->avctx->height / 8)) * 2; + s->decoding_map = buf + 8 + 14; /* 14 bits of op data */ + video_data_size -= s->decoding_map_size + 14; + if (video_data_size <= 0 || s->decoding_map_size == 0) + return AVERROR_INVALIDDATA; - if (buf_size < 8 + s->decoding_map_size + 14 + video_data_size) - return AVERROR_INVALIDDATA; + if (buf_size < 8 + s->decoding_map_size + 14 + video_data_size) + return AVERROR_INVALIDDATA; - bytestream2_init(&s->stream_ptr, buf + 8 + s->decoding_map_size + 14, video_data_size); + bytestream2_init(&s->stream_ptr, buf + 8 + s->decoding_map_size + 14, video_data_size); - break; + break; - case 0x10: - if (! s->decoding_map_size) { - av_log(avctx, AV_LOG_ERROR, "Empty decoding map for format 0x10\n"); - return AVERROR_INVALIDDATA; - } + case 0x10: + if (! s->decoding_map_size) { + av_log(avctx, AV_LOG_ERROR, "Empty decoding map for format 0x10\n"); + return AVERROR_INVALIDDATA; + } - if (! s->skip_map_size) { - av_log(avctx, AV_LOG_ERROR, "Empty skip map for format 0x10\n"); - return AVERROR_INVALIDDATA; - } + if (! s->skip_map_size) { + av_log(avctx, AV_LOG_ERROR, "Empty skip map for format 0x10\n"); + return AVERROR_INVALIDDATA; + } - if (s->is_16bpp) { - av_log(avctx, AV_LOG_ERROR, "Video format 0x10 does not support 16bpp movies\n"); - return AVERROR_INVALIDDATA; - } + if (s->is_16bpp) { + av_log(avctx, AV_LOG_ERROR, "Video format 0x10 does not support 16bpp movies\n"); + return AVERROR_INVALIDDATA; + } - if (buf_size < 8 + video_data_size + s->decoding_map_size + s->skip_map_size) - return AVERROR_INVALIDDATA; + if (buf_size < 8 + video_data_size + s->decoding_map_size + s->skip_map_size) + return AVERROR_INVALIDDATA; - bytestream2_init(&s->stream_ptr, buf + 8, video_data_size); - s->decoding_map = buf + 8 + video_data_size; - s->skip_map = buf + 8 + video_data_size + s->decoding_map_size; + bytestream2_init(&s->stream_ptr, buf + 8, video_data_size); + s->decoding_map = buf + 8 + video_data_size; + s->skip_map = buf + 8 + video_data_size + s->decoding_map_size; - break; + break; - case 0x11: - if (! s->decoding_map_size) { - av_log(avctx, AV_LOG_ERROR, "Empty decoding map for format 0x11\n"); - return AVERROR_INVALIDDATA; - } + case 0x11: + if (! s->decoding_map_size) { + av_log(avctx, AV_LOG_ERROR, "Empty decoding map for format 0x11\n"); + return AVERROR_INVALIDDATA; + } - if (s->skip_map_size) { - av_log(avctx, AV_LOG_ERROR, "Skip map for format 0x11\n"); - return AVERROR_INVALIDDATA; - } + if (s->skip_map_size) { + av_log(avctx, AV_LOG_ERROR, "Skip map for format 0x11\n"); + return AVERROR_INVALIDDATA; + } - if (buf_size < 8 + video_data_size + s->decoding_map_size) - return AVERROR_INVALIDDATA; + if (buf_size < 8 + video_data_size + s->decoding_map_size) + return AVERROR_INVALIDDATA; - bytestream2_init(&s->stream_ptr, buf + 8, video_data_size); - s->decoding_map = buf + 8 + video_data_size; + bytestream2_init(&s->stream_ptr, buf + 8, video_data_size); + s->decoding_map = buf + 8 + video_data_size; - break; + break; - default: - av_log(avctx, AV_LOG_ERROR, "Frame type 0x%02X unsupported\n", frame_format); + default: + av_log(avctx, AV_LOG_ERROR, "Frame type 0x%02X unsupported\n", frame_format); } /* ensure we can't overread the packet */ @@ -1328,7 +1317,7 @@ return ret; if (!s->is_16bpp) { - int size; + buffer_size_t size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size); if (pal && size == AVPALETTE_SIZE) { frame->palette_has_changed = 1; @@ -1338,16 +1327,16 @@ } } - switch(frame_format) { - case 0x06: - ipvideo_decode_format_06_opcodes(s, frame); - break; - case 0x10: - ipvideo_decode_format_10_opcodes(s, frame); - break; - case 0x11: - ipvideo_decode_format_11_opcodes(s, frame); - break; + switch (frame_format) { + case 0x06: + ipvideo_decode_format_06_opcodes(s, frame); + break; + case 0x10: + ipvideo_decode_format_10_opcodes(s, frame); + break; + case 0x11: + ipvideo_decode_format_11_opcodes(s, frame); + break; } *got_frame = send_buffer; @@ -1384,4 +1373,5 @@ .close = ipvideo_decode_end, .decode = ipvideo_decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/intrax8.c ffmpeg-4.4/libavcodec/intrax8.c --- ffmpeg-4.2.2/libavcodec/intrax8.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/intrax8.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ */ #include "libavutil/avassert.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "get_bits.h" #include "idctdsp.h" @@ -31,6 +32,8 @@ #include "intrax8dsp.h" #include "mpegutils.h" +#define VLC_BUFFER_SIZE 28150 + #define MAX_TABLE_DEPTH(table_bits, max_bits) \ ((max_bits + table_bits - 1) / table_bits) @@ -46,82 +49,45 @@ static VLC j_dc_vlc[2][8]; // [quant], [select] static VLC j_orient_vlc[2][4]; // [quant], [select] -static av_cold int x8_vlc_init(void) +static av_cold void x8_init_vlc(VLC *vlc, int nb_bits, int nb_codes, + int *offset, const uint8_t table[][2]) { - int i; - int offset = 0; - int sizeidx = 0; - static const uint16_t sizes[8 * 4 + 8 * 2 + 2 + 4] = { - 576, 548, 582, 618, 546, 616, 560, 642, - 584, 582, 704, 664, 512, 544, 656, 640, - 512, 648, 582, 566, 532, 614, 596, 648, - 586, 552, 584, 590, 544, 578, 584, 624, - - 528, 528, 526, 528, 536, 528, 526, 544, - 544, 512, 512, 528, 528, 544, 512, 544, + static VLC_TYPE vlc_buf[VLC_BUFFER_SIZE][2]; - 128, 128, 128, 128, 128, 128, - }; + vlc->table = &vlc_buf[*offset]; + vlc->table_allocated = VLC_BUFFER_SIZE - *offset; + ff_init_vlc_from_lengths(vlc, nb_bits, nb_codes, &table[0][1], 2, + &table[0][0], 2, 1, 0, INIT_VLC_STATIC_OVERLONG, NULL); + *offset += vlc->table_size; +} - static VLC_TYPE table[28150][2]; +static av_cold void x8_vlc_init(void) +{ + int i; + int offset = 0; // set ac tables -#define init_ac_vlc(dst, src) \ - do { \ - dst.table = &table[offset]; \ - dst.table_allocated = sizes[sizeidx]; \ - offset += sizes[sizeidx++]; \ - init_vlc(&dst, AC_VLC_BITS, 77, &src[1], 4, 2, &src[0], 4, 2, \ - INIT_VLC_USE_NEW_STATIC); \ - } while(0) - - for (i = 0; i < 8; i++) { - init_ac_vlc(j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0]); - init_ac_vlc(j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0]); - init_ac_vlc(j_ac_vlc[1][0][i], x8_ac0_lowquant_table[i][0]); - init_ac_vlc(j_ac_vlc[1][1][i], x8_ac1_lowquant_table[i][0]); - } -#undef init_ac_vlc + for (int i = 0; i < 2; i++) + for (int j = 0; j < 2; j++) + for (int k = 0; k < 8; k++) + x8_init_vlc(&j_ac_vlc[i][j][k], AC_VLC_BITS, 77, + &offset, x8_ac_quant_table[i][j][k]); // set dc tables -#define init_dc_vlc(dst, src) \ - do { \ - dst.table = &table[offset]; \ - dst.table_allocated = sizes[sizeidx]; \ - offset += sizes[sizeidx++]; \ - init_vlc(&dst, DC_VLC_BITS, 34, &src[1], 4, 2, &src[0], 4, 2, \ - INIT_VLC_USE_NEW_STATIC); \ - } while(0) - - for (i = 0; i < 8; i++) { - init_dc_vlc(j_dc_vlc[0][i], x8_dc_highquant_table[i][0]); - init_dc_vlc(j_dc_vlc[1][i], x8_dc_lowquant_table[i][0]); - } -#undef init_dc_vlc + for (int i = 0; i < 2; i++) + for (int j = 0; j < 8; j++) + x8_init_vlc(&j_dc_vlc[i][j], DC_VLC_BITS, 34, &offset, + x8_dc_quant_table[i][j]); // set orient tables -#define init_or_vlc(dst, src) \ - do { \ - dst.table = &table[offset]; \ - dst.table_allocated = sizes[sizeidx]; \ - offset += sizes[sizeidx++]; \ - init_vlc(&dst, OR_VLC_BITS, 12, &src[1], 4, 2, &src[0], 4, 2, \ - INIT_VLC_USE_NEW_STATIC); \ - } while(0) - for (i = 0; i < 2; i++) - init_or_vlc(j_orient_vlc[0][i], x8_orient_highquant_table[i][0]); + x8_init_vlc(&j_orient_vlc[0][i], OR_VLC_BITS, 12, + &offset, x8_orient_highquant_table[i]); for (i = 0; i < 4; i++) - init_or_vlc(j_orient_vlc[1][i], x8_orient_lowquant_table[i][0]); -#undef init_or_vlc + x8_init_vlc(&j_orient_vlc[1][i], OR_VLC_BITS, 12, + &offset, x8_orient_lowquant_table[i]); - if (offset != sizeof(table) / sizeof(VLC_TYPE) / 2) { - av_log(NULL, AV_LOG_ERROR, "table size %"SIZE_SPECIFIER" does not match needed %i\n", - sizeof(table) / sizeof(VLC_TYPE) / 2, offset); - return AVERROR_INVALIDDATA; - } - - return 0; + av_assert2(offset == VLC_BUFFER_SIZE); } static void x8_reset_vlc_tables(IntraX8Context *w) @@ -731,9 +697,7 @@ int block_last_index[12], int mb_width, int mb_height) { - int ret = x8_vlc_init(); - if (ret < 0) - return ret; + static AVOnce init_static_once = AV_ONCE_INIT; w->avctx = avctx; w->idsp = *idsp; @@ -762,6 +726,8 @@ ff_intrax8dsp_init(&w->dsp); ff_blockdsp_init(&w->bdsp, avctx); + ff_thread_once(&init_static_once, x8_vlc_init); + return 0; } @@ -801,6 +767,8 @@ for (w->mb_y = 0; w->mb_y < w->mb_height * 2; w->mb_y++) { x8_init_block_index(w, w->frame); mb_xy = (w->mb_y >> 1) * (w->mb_width + 1); + if (get_bits_left(gb) < 1) + goto error; for (w->mb_x = 0; w->mb_x < w->mb_width * 2; w->mb_x++) { x8_get_prediction(w); if (x8_setup_spatial_predictor(w, 0)) diff -Nru ffmpeg-4.2.2/libavcodec/intrax8huf.h ffmpeg-4.4/libavcodec/intrax8huf.h --- ffmpeg-4.2.2/libavcodec/intrax8huf.h 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/intrax8huf.h 2021-04-08 21:28:39.000000000 +0000 @@ -21,939 +21,777 @@ #include -static const uint16_t x8_orient_lowquant_table[4][12][2] = { - { // 0 - { 0x0000, 1 }, { 0x0004, 3 }, { 0x0005, 3 }, { 0x000C, 4 }, - { 0x000D, 4 }, { 0x0038, 6 }, { 0x001D, 5 }, { 0x0039, 6 }, - { 0x003C, 6 }, { 0x003D, 6 }, { 0x003E, 6 }, { 0x003F, 6 }, - }, - { // 1 - { 0x0000, 5 }, { 0x0001, 5 }, { 0x0002, 5 }, { 0x0001, 2 }, - { 0x0002, 2 }, { 0x0002, 4 }, { 0x0003, 5 }, { 0x0006, 3 }, - { 0x0003, 4 }, { 0x000E, 4 }, { 0x001E, 5 }, { 0x001F, 5 }, - }, - { // 2 - { 0x0000, 2 }, { 0x0001, 2 }, { 0x0004, 3 }, { 0x0005, 3 }, - { 0x0006, 3 }, { 0x0038, 6 }, { 0x0039, 6 }, { 0x001D, 5 }, - { 0x003C, 6 }, { 0x003D, 6 }, { 0x003E, 6 }, { 0x003F, 6 }, - }, - { // 3 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0001, 2 }, - { 0x0002, 2 }, { 0x0018, 5 }, { 0x0019, 5 }, { 0x000D, 4 }, - { 0x001C, 5 }, { 0x001D, 5 }, { 0x001E, 5 }, { 0x001F, 5 }, +static const uint8_t x8_orient_lowquant_table[4][12][2] = { + { /* Orient lowquant table 0 */ + { 0, 1 }, { 1, 3 }, { 2, 3 }, { 3, 4 }, { 4, 4 }, { 5, 6 }, + { 7, 6 }, { 6, 5 }, { 8, 6 }, { 9, 6 }, { 10, 6 }, { 11, 6 }, + }, + { /* Orient lowquant table 1 */ + { 0, 5 }, { 1, 5 }, { 2, 5 }, { 6, 5 }, { 5, 4 }, { 8, 4 }, + { 3, 2 }, { 4, 2 }, { 7, 3 }, { 9, 4 }, { 10, 5 }, { 11, 5 }, + }, + { /* Orient lowquant table 2 */ + { 0, 2 }, { 1, 2 }, { 2, 3 }, { 3, 3 }, { 4, 3 }, { 5, 6 }, + { 6, 6 }, { 7, 5 }, { 8, 6 }, { 9, 6 }, { 10, 6 }, { 11, 6 }, + }, + { /* Orient lowquant table 3 */ + { 0, 3 }, { 1, 4 }, { 2, 4 }, { 3, 2 }, { 4, 2 }, { 5, 5 }, + { 6, 5 }, { 7, 4 }, { 8, 5 }, { 9, 5 }, { 10, 5 }, { 11, 5 }, }, }; -static const uint16_t x8_orient_highquant_table[2][12][2] = { - { // 0 - { 0x0000, 2 }, { 0x0001, 2 }, { 0x0004, 3 }, { 0x0005, 3 }, - { 0x0006, 3 }, { 0x0038, 6 }, { 0x001D, 5 }, { 0x0039, 6 }, - { 0x003C, 6 }, { 0x003D, 6 }, { 0x003E, 6 }, { 0x003F, 6 }, - }, - { // 1 - { 0x0000, 1 }, { 0x0002, 2 }, { 0x0006, 3 }, { 0x001C, 5 }, - { 0x001D, 5 }, { 0x0078, 7 }, { 0x003D, 6 }, { 0x0079, 7 }, - { 0x007C, 7 }, { 0x007D, 7 }, { 0x007E, 7 }, { 0x007F, 7 }, +static const uint8_t x8_orient_highquant_table[2][12][2] = { + { /* Orient highquant table 0 */ + { 0, 2 }, { 1, 2 }, { 2, 3 }, { 3, 3 }, { 4, 3 }, { 5, 6 }, + { 7, 6 }, { 6, 5 }, { 8, 6 }, { 9, 6 }, { 10, 6 }, { 11, 6 }, + }, + { /* Orient highquant table 1 */ + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 5 }, { 4, 5 }, { 5, 7 }, + { 7, 7 }, { 6, 6 }, { 8, 7 }, { 9, 7 }, { 10, 7 }, { 11, 7 }, }, }; #define MAX_OR_VLC_BITS 7 -static const uint16_t x8_dc_lowquant_table[8][34][2] = { - { // 0 - { 0x0000, 5 }, { 0x0001, 4 }, { 0x0001, 5 }, { 0x0004, 5 }, - { 0x0005, 5 }, { 0x0006, 5 }, { 0x000E, 6 }, { 0x000F, 6 }, - { 0x0040, 8 }, { 0x0041, 8 }, { 0x0840, 13 }, { 0x0841, 13 }, - { 0x0842, 13 }, { 0x0843, 13 }, { 0x0844, 13 }, { 0x0845, 13 }, - { 0x0846, 13 }, { 0x0002, 2 }, { 0x0003, 2 }, { 0x0003, 3 }, - { 0x0005, 4 }, { 0x0009, 5 }, { 0x0011, 6 }, { 0x0043, 8 }, - { 0x0085, 9 }, { 0x0847, 13 }, { 0x0848, 13 }, { 0x0849, 13 }, - { 0x084A, 13 }, { 0x084B, 13 }, { 0x084C, 13 }, { 0x084D, 13 }, - { 0x084E, 13 }, { 0x084F, 13 }, - }, - { // 1 - { 0x0000, 4 }, { 0x0001, 3 }, { 0x0002, 3 }, { 0x0001, 4 }, - { 0x0006, 4 }, { 0x0004, 3 }, { 0x0007, 4 }, { 0x0005, 3 }, - { 0x000C, 4 }, { 0x000D, 4 }, { 0x001C, 5 }, { 0x003A, 6 }, - { 0x01D8, 9 }, { 0x01D9, 9 }, { 0x1DA0, 13 }, { 0x1DA1, 13 }, - { 0x1DA2, 13 }, { 0x003C, 6 }, { 0x003D, 6 }, { 0x003E, 6 }, - { 0x0077, 7 }, { 0x01DB, 9 }, { 0x007E, 7 }, { 0x00FE, 8 }, - { 0x01FE, 9 }, { 0x1DA3, 13 }, { 0x1DA4, 13 }, { 0x1DA5, 13 }, - { 0x0ED3, 12 }, { 0x0ED4, 12 }, { 0x01FF, 9 }, { 0x0ED5, 12 }, - { 0x0ED6, 12 }, { 0x0ED7, 12 }, - }, - { // 2 - { 0x0000, 4 }, { 0x0001, 3 }, { 0x0002, 3 }, { 0x0001, 4 }, - { 0x0006, 4 }, { 0x0007, 4 }, { 0x0008, 4 }, { 0x0009, 4 }, - { 0x0028, 6 }, { 0x0029, 6 }, { 0x0054, 7 }, { 0x0055, 7 }, - { 0x0AC0, 12 }, { 0x0AC1, 12 }, { 0x0AC2, 12 }, { 0x0AC3, 12 }, - { 0x0AC4, 12 }, { 0x000B, 4 }, { 0x0006, 3 }, { 0x000E, 4 }, - { 0x001E, 5 }, { 0x003E, 6 }, { 0x003F, 6 }, { 0x0057, 7 }, - { 0x00AD, 8 }, { 0x0AC5, 12 }, { 0x0AC6, 12 }, { 0x0AC7, 12 }, - { 0x0AC8, 12 }, { 0x0AC9, 12 }, { 0x0ACA, 12 }, { 0x0ACB, 12 }, - { 0x0566, 11 }, { 0x0567, 11 }, - }, - { // 3 - { 0x0000, 4 }, { 0x0001, 2 }, { 0x0001, 3 }, { 0x0004, 3 }, - { 0x0005, 3 }, { 0x0006, 3 }, { 0x0001, 4 }, { 0x000E, 4 }, - { 0x003C, 6 }, { 0x003D, 6 }, { 0x007C, 7 }, { 0x00FA, 8 }, - { 0x3EC0, 14 }, { 0x3EC1, 14 }, { 0x3EC2, 14 }, { 0x3EC3, 14 }, - { 0x1F62, 13 }, { 0x01F7, 9 }, { 0x007E, 7 }, { 0x00FE, 8 }, - { 0x00FF, 8 }, { 0x1F63, 13 }, { 0x1F64, 13 }, { 0x1F65, 13 }, - { 0x1F66, 13 }, { 0x1F67, 13 }, { 0x1F68, 13 }, { 0x1F69, 13 }, - { 0x1F6A, 13 }, { 0x1F6B, 13 }, { 0x1F6C, 13 }, { 0x1F6D, 13 }, - { 0x1F6E, 13 }, { 0x1F6F, 13 }, - }, - { // 4 - { 0x0000, 7 }, { 0x0001, 7 }, { 0x0002, 7 }, { 0x0003, 7 }, - { 0x0004, 7 }, { 0x0005, 7 }, { 0x0006, 7 }, { 0x0007, 7 }, - { 0x0008, 7 }, { 0x0009, 7 }, { 0x000A, 7 }, { 0x000B, 7 }, - { 0x000C, 7 }, { 0x000D, 7 }, { 0x000E, 7 }, { 0x000F, 7 }, - { 0x0010, 7 }, { 0x0001, 1 }, { 0x0001, 2 }, { 0x0011, 7 }, - { 0x0012, 7 }, { 0x0013, 7 }, { 0x0014, 7 }, { 0x0015, 7 }, - { 0x0016, 7 }, { 0x0017, 7 }, { 0x0018, 7 }, { 0x0019, 7 }, - { 0x001A, 7 }, { 0x001B, 7 }, { 0x001C, 7 }, { 0x001D, 7 }, - { 0x001E, 7 }, { 0x001F, 7 }, - }, - { // 5 - { 0x0000, 5 }, { 0x0001, 4 }, { 0x0001, 5 }, { 0x0008, 6 }, - { 0x0009, 6 }, { 0x000A, 6 }, { 0x0016, 7 }, { 0x000C, 6 }, - { 0x0017, 7 }, { 0x000D, 6 }, { 0x0038, 8 }, { 0x001D, 7 }, - { 0x0039, 8 }, { 0x0780, 13 }, { 0x0781, 13 }, { 0x0782, 13 }, - { 0x0783, 13 }, { 0x0002, 3 }, { 0x0001, 1 }, { 0x0003, 3 }, - { 0x001F, 7 }, { 0x003D, 8 }, { 0x0079, 9 }, { 0x0784, 13 }, - { 0x0785, 13 }, { 0x0786, 13 }, { 0x0787, 13 }, { 0x0788, 13 }, - { 0x0789, 13 }, { 0x078A, 13 }, { 0x078B, 13 }, { 0x078C, 13 }, - { 0x078D, 13 }, { 0x03C7, 12 }, - }, - { // 6 - { 0x0000, 4 }, { 0x0001, 2 }, { 0x0001, 3 }, { 0x0004, 3 }, - { 0x0001, 4 }, { 0x000A, 4 }, { 0x0016, 5 }, { 0x002E, 6 }, - { 0x005E, 7 }, { 0x005F, 7 }, { 0x00C0, 8 }, { 0x3040, 14 }, - { 0x3041, 14 }, { 0x0305, 10 }, { 0x0183, 9 }, { 0x3042, 14 }, - { 0x3043, 14 }, { 0x000D, 4 }, { 0x0007, 3 }, { 0x0019, 5 }, - { 0x0031, 6 }, { 0x00C2, 8 }, { 0x00C3, 8 }, { 0x3044, 14 }, - { 0x3045, 14 }, { 0x3046, 14 }, { 0x3047, 14 }, { 0x3048, 14 }, - { 0x3049, 14 }, { 0x304A, 14 }, { 0x304B, 14 }, { 0x304C, 14 }, - { 0x304D, 14 }, { 0x1827, 13 }, - }, - { // 7 - { 0x0000, 6 }, { 0x0001, 6 }, { 0x0002, 6 }, { 0x0006, 7 }, - { 0x0007, 7 }, { 0x0004, 6 }, { 0x0005, 6 }, { 0x0006, 6 }, - { 0x000E, 7 }, { 0x001E, 8 }, { 0x001F, 8 }, { 0x0040, 9 }, - { 0x0082, 10 }, { 0x0830, 14 }, { 0x0831, 14 }, { 0x0832, 14 }, - { 0x0833, 14 }, { 0x0001, 1 }, { 0x0001, 2 }, { 0x0003, 4 }, - { 0x0005, 5 }, { 0x0009, 6 }, { 0x0011, 7 }, { 0x0021, 8 }, - { 0x0834, 14 }, { 0x0835, 14 }, { 0x0836, 14 }, { 0x0837, 14 }, - { 0x0838, 14 }, { 0x0839, 14 }, { 0x083A, 14 }, { 0x083B, 14 }, - { 0x041E, 13 }, { 0x041F, 13 }, - }, -}; - -static const uint16_t x8_dc_highquant_table[8][34][2] = { - { // 0 - { 0x0000, 5 }, { 0x0001, 4 }, { 0x0002, 4 }, { 0x0001, 5 }, - { 0x0006, 5 }, { 0x0004, 4 }, { 0x0007, 5 }, { 0x000A, 5 }, - { 0x002C, 7 }, { 0x002D, 7 }, { 0x05C0, 12 }, { 0x05C1, 12 }, - { 0x05C2, 12 }, { 0x05C3, 12 }, { 0x05C4, 12 }, { 0x05C5, 12 }, - { 0x05C6, 12 }, { 0x0003, 3 }, { 0x0002, 2 }, { 0x0006, 3 }, - { 0x000E, 4 }, { 0x001E, 5 }, { 0x001F, 5 }, { 0x002F, 7 }, - { 0x005D, 8 }, { 0x05C7, 12 }, { 0x05C8, 12 }, { 0x05C9, 12 }, - { 0x05CA, 12 }, { 0x05CB, 12 }, { 0x05CC, 12 }, { 0x05CD, 12 }, - { 0x05CE, 12 }, { 0x05CF, 12 }, - }, - { // 1 - { 0x0000, 3 }, { 0x0001, 3 }, { 0x0002, 3 }, { 0x0006, 4 }, - { 0x0007, 4 }, { 0x0004, 3 }, { 0x000A, 4 }, { 0x000B, 4 }, - { 0x0030, 6 }, { 0x0062, 7 }, { 0x0063, 7 }, { 0x0640, 11 }, - { 0x0641, 11 }, { 0x0642, 11 }, { 0x0643, 11 }, { 0x0644, 11 }, - { 0x0645, 11 }, { 0x0033, 6 }, { 0x000D, 4 }, { 0x001C, 5 }, - { 0x001D, 5 }, { 0x003C, 6 }, { 0x001F, 5 }, { 0x0065, 7 }, - { 0x007A, 7 }, { 0x0646, 11 }, { 0x007B, 7 }, { 0x0647, 11 }, - { 0x0648, 11 }, { 0x0649, 11 }, { 0x064A, 11 }, { 0x064B, 11 }, - { 0x0326, 10 }, { 0x0327, 10 }, - }, - { // 2 - { 0x0000, 7 }, { 0x0001, 7 }, { 0x0001, 6 }, { 0x0004, 7 }, - { 0x0003, 6 }, { 0x0005, 7 }, { 0x0010, 8 }, { 0x0011, 8 }, - { 0x0240, 13 }, { 0x0241, 13 }, { 0x0242, 13 }, { 0x0243, 13 }, - { 0x0244, 13 }, { 0x0245, 13 }, { 0x0246, 13 }, { 0x0247, 13 }, - { 0x0124, 12 }, { 0x0001, 1 }, { 0x0001, 2 }, { 0x0001, 3 }, - { 0x0003, 5 }, { 0x0005, 6 }, { 0x0013, 8 }, { 0x0125, 12 }, - { 0x0126, 12 }, { 0x0127, 12 }, { 0x0128, 12 }, { 0x0129, 12 }, - { 0x012A, 12 }, { 0x012B, 12 }, { 0x012C, 12 }, { 0x012D, 12 }, - { 0x012E, 12 }, { 0x012F, 12 }, - }, - { // 3 - { 0x0000, 4 }, { 0x0001, 3 }, { 0x0002, 3 }, { 0x0001, 4 }, - { 0x0006, 4 }, { 0x0004, 3 }, { 0x0005, 3 }, { 0x0006, 3 }, - { 0x000E, 5 }, { 0x000F, 5 }, { 0x0070, 7 }, { 0x0710, 11 }, - { 0x0711, 11 }, { 0x0712, 11 }, { 0x0713, 11 }, { 0x0714, 11 }, - { 0x0715, 11 }, { 0x001D, 5 }, { 0x0072, 7 }, { 0x003C, 6 }, - { 0x003D, 6 }, { 0x0073, 7 }, { 0x007C, 7 }, { 0x007D, 7 }, - { 0x007E, 7 }, { 0x0716, 11 }, { 0x0717, 11 }, { 0x0718, 11 }, - { 0x007F, 7 }, { 0x0719, 11 }, { 0x071A, 11 }, { 0x071B, 11 }, - { 0x038E, 10 }, { 0x038F, 10 }, - }, - { // 4 - { 0x0000, 8 }, { 0x0001, 7 }, { 0x0002, 7 }, { 0x0003, 7 }, - { 0x0002, 9 }, { 0x0008, 8 }, { 0x0003, 9 }, { 0x0240, 14 }, - { 0x0241, 14 }, { 0x0242, 14 }, { 0x0243, 14 }, { 0x0244, 14 }, - { 0x0245, 14 }, { 0x0246, 14 }, { 0x0247, 14 }, { 0x0124, 13 }, - { 0x0125, 13 }, { 0x0001, 2 }, { 0x0001, 1 }, { 0x0001, 3 }, - { 0x0001, 4 }, { 0x0003, 6 }, { 0x0005, 7 }, { 0x0013, 9 }, - { 0x0126, 13 }, { 0x0127, 13 }, { 0x0128, 13 }, { 0x0129, 13 }, - { 0x012A, 13 }, { 0x012B, 13 }, { 0x012C, 13 }, { 0x012D, 13 }, - { 0x012E, 13 }, { 0x012F, 13 }, - }, - { // 5 - { 0x0000, 7 }, { 0x0001, 7 }, { 0x0001, 6 }, { 0x0002, 6 }, - { 0x0003, 6 }, { 0x0004, 6 }, { 0x0005, 6 }, { 0x0006, 6 }, - { 0x0007, 6 }, { 0x0008, 6 }, { 0x0009, 6 }, { 0x000A, 6 }, - { 0x000B, 6 }, { 0x000C, 6 }, { 0x000D, 6 }, { 0x000E, 6 }, - { 0x000F, 6 }, { 0x0010, 6 }, { 0x0011, 6 }, { 0x0012, 6 }, - { 0x0013, 6 }, { 0x0014, 6 }, { 0x0015, 6 }, { 0x0016, 6 }, - { 0x0017, 6 }, { 0x0018, 6 }, { 0x0019, 6 }, { 0x0001, 1 }, - { 0x001A, 6 }, { 0x001B, 6 }, { 0x001C, 6 }, { 0x001D, 6 }, - { 0x001E, 6 }, { 0x001F, 6 }, - }, - { // 6 - { 0x0000, 5 }, { 0x0001, 4 }, { 0x0001, 5 }, { 0x0004, 5 }, - { 0x000A, 6 }, { 0x0006, 5 }, { 0x000B, 6 }, { 0x000E, 6 }, - { 0x003C, 8 }, { 0x003D, 8 }, { 0x07C0, 13 }, { 0x07C1, 13 }, - { 0x07C2, 13 }, { 0x07C3, 13 }, { 0x07C4, 13 }, { 0x07C5, 13 }, - { 0x07C6, 13 }, { 0x0001, 2 }, { 0x0002, 2 }, { 0x0006, 3 }, - { 0x000E, 4 }, { 0x001E, 5 }, { 0x001F, 5 }, { 0x003F, 8 }, - { 0x007D, 9 }, { 0x07C7, 13 }, { 0x07C8, 13 }, { 0x07C9, 13 }, - { 0x07CA, 13 }, { 0x07CB, 13 }, { 0x07CC, 13 }, { 0x07CD, 13 }, - { 0x07CE, 13 }, { 0x07CF, 13 }, - }, - { // 7 - { 0x0000, 7 }, { 0x0001, 7 }, { 0x0002, 7 }, { 0x0003, 7 }, - { 0x0004, 7 }, { 0x0005, 7 }, { 0x0006, 7 }, { 0x0007, 7 }, - { 0x0008, 7 }, { 0x0009, 7 }, { 0x000A, 7 }, { 0x000B, 7 }, - { 0x000C, 7 }, { 0x000D, 7 }, { 0x000E, 7 }, { 0x000F, 7 }, - { 0x0010, 7 }, { 0x0001, 1 }, { 0x0001, 2 }, { 0x0011, 7 }, - { 0x0012, 7 }, { 0x0013, 7 }, { 0x0014, 7 }, { 0x0015, 7 }, - { 0x0016, 7 }, { 0x0017, 7 }, { 0x0018, 7 }, { 0x0019, 7 }, - { 0x001A, 7 }, { 0x001B, 7 }, { 0x001C, 7 }, { 0x001D, 7 }, - { 0x001E, 7 }, { 0x001F, 7 }, +static const uint8_t x8_dc_quant_table[2][8][34][2] = { + { + { /* DC highquant table 0 */ + { 0, 5 }, { 3, 5 }, { 1, 4 }, { 2, 4 }, { 4, 5 }, + { 6, 5 }, { 5, 4 }, { 7, 5 }, { 8, 7 }, { 9, 7 }, + { 10, 12 }, { 11, 12 }, { 12, 12 }, { 13, 12 }, { 14, 12 }, + { 15, 12 }, { 16, 12 }, { 25, 12 }, { 26, 12 }, { 27, 12 }, + { 28, 12 }, { 29, 12 }, { 30, 12 }, { 31, 12 }, { 32, 12 }, + { 33, 12 }, { 24, 8 }, { 23, 7 }, { 17, 3 }, { 18, 2 }, + { 19, 3 }, { 20, 4 }, { 21, 5 }, { 22, 5 }, + }, + { /* DC highquant table 1 */ + { 0, 3 }, { 1, 3 }, { 2, 3 }, { 3, 4 }, { 4, 4 }, + { 5, 3 }, { 6, 4 }, { 7, 4 }, { 8, 6 }, { 9, 7 }, + { 10, 7 }, { 11, 11 }, { 12, 11 }, { 13, 11 }, { 14, 11 }, + { 15, 11 }, { 16, 11 }, { 25, 11 }, { 27, 11 }, { 28, 11 }, + { 29, 11 }, { 30, 11 }, { 31, 11 }, { 32, 10 }, { 33, 10 }, + { 23, 7 }, { 17, 6 }, { 18, 4 }, { 19, 5 }, { 20, 5 }, + { 21, 6 }, { 24, 7 }, { 26, 7 }, { 22, 5 }, + }, + { /* DC highquant table 2 */ + { 0, 7 }, { 1, 7 }, { 2, 6 }, { 3, 7 }, { 5, 7 }, + { 4, 6 }, { 6, 8 }, { 7, 8 }, { 8, 13 }, { 9, 13 }, + { 10, 13 }, { 11, 13 }, { 12, 13 }, { 13, 13 }, { 14, 13 }, + { 15, 13 }, { 16, 12 }, { 23, 12 }, { 24, 12 }, { 25, 12 }, + { 26, 12 }, { 27, 12 }, { 28, 12 }, { 29, 12 }, { 30, 12 }, + { 31, 12 }, { 32, 12 }, { 33, 12 }, { 22, 8 }, { 21, 6 }, + { 20, 5 }, { 19, 3 }, { 18, 2 }, { 17, 1 }, + }, + { /* DC highquant table 3 */ + { 0, 4 }, { 3, 4 }, { 1, 3 }, { 2, 3 }, { 4, 4 }, + { 8, 5 }, { 9, 5 }, { 5, 3 }, { 6, 3 }, { 7, 3 }, + { 10, 7 }, { 11, 11 }, { 12, 11 }, { 13, 11 }, { 14, 11 }, + { 15, 11 }, { 16, 11 }, { 25, 11 }, { 26, 11 }, { 27, 11 }, + { 29, 11 }, { 30, 11 }, { 31, 11 }, { 32, 10 }, { 33, 10 }, + { 18, 7 }, { 21, 7 }, { 17, 5 }, { 19, 6 }, { 20, 6 }, + { 22, 7 }, { 23, 7 }, { 24, 7 }, { 28, 7 }, + }, + { /* DC highquant table 4 */ + { 0, 8 }, { 4, 9 }, { 6, 9 }, { 1, 7 }, { 2, 7 }, + { 3, 7 }, { 5, 8 }, { 7, 14 }, { 8, 14 }, { 9, 14 }, + { 10, 14 }, { 11, 14 }, { 12, 14 }, { 13, 14 }, { 14, 14 }, + { 15, 13 }, { 16, 13 }, { 24, 13 }, { 25, 13 }, { 26, 13 }, + { 27, 13 }, { 28, 13 }, { 29, 13 }, { 30, 13 }, { 31, 13 }, + { 32, 13 }, { 33, 13 }, { 23, 9 }, { 22, 7 }, { 21, 6 }, + { 20, 4 }, { 19, 3 }, { 17, 2 }, { 18, 1 }, + }, + { /* DC highquant table 5 */ + { 0, 7 }, { 1, 7 }, { 2, 6 }, { 3, 6 }, { 4, 6 }, + { 5, 6 }, { 6, 6 }, { 7, 6 }, { 8, 6 }, { 9, 6 }, + { 10, 6 }, { 11, 6 }, { 12, 6 }, { 13, 6 }, { 14, 6 }, + { 15, 6 }, { 16, 6 }, { 17, 6 }, { 18, 6 }, { 19, 6 }, + { 20, 6 }, { 21, 6 }, { 22, 6 }, { 23, 6 }, { 24, 6 }, + { 25, 6 }, { 26, 6 }, { 28, 6 }, { 29, 6 }, { 30, 6 }, + { 31, 6 }, { 32, 6 }, { 33, 6 }, { 27, 1 }, + }, + { /* DC highquant table 6 */ + { 0, 5 }, { 2, 5 }, { 1, 4 }, { 3, 5 }, { 4, 6 }, + { 6, 6 }, { 5, 5 }, { 7, 6 }, { 8, 8 }, { 9, 8 }, + { 10, 13 }, { 11, 13 }, { 12, 13 }, { 13, 13 }, { 14, 13 }, + { 15, 13 }, { 16, 13 }, { 25, 13 }, { 26, 13 }, { 27, 13 }, + { 28, 13 }, { 29, 13 }, { 30, 13 }, { 31, 13 }, { 32, 13 }, + { 33, 13 }, { 24, 9 }, { 23, 8 }, { 17, 2 }, { 18, 2 }, + { 19, 3 }, { 20, 4 }, { 21, 5 }, { 22, 5 }, + }, + { /* DC highquant table 7 */ + { 0, 7 }, { 1, 7 }, { 2, 7 }, { 3, 7 }, { 4, 7 }, + { 5, 7 }, { 6, 7 }, { 7, 7 }, { 8, 7 }, { 9, 7 }, + { 10, 7 }, { 11, 7 }, { 12, 7 }, { 13, 7 }, { 14, 7 }, + { 15, 7 }, { 16, 7 }, { 19, 7 }, { 20, 7 }, { 21, 7 }, + { 22, 7 }, { 23, 7 }, { 24, 7 }, { 25, 7 }, { 26, 7 }, + { 27, 7 }, { 28, 7 }, { 29, 7 }, { 30, 7 }, { 31, 7 }, + { 32, 7 }, { 33, 7 }, { 18, 2 }, { 17, 1 }, + }, + }, + { + { /* DC lowquant table 0 */ + { 0, 5 }, { 2, 5 }, { 1, 4 }, { 3, 5 }, { 4, 5 }, + { 5, 5 }, { 6, 6 }, { 7, 6 }, { 8, 8 }, { 9, 8 }, + { 10, 13 }, { 11, 13 }, { 12, 13 }, { 13, 13 }, { 14, 13 }, + { 15, 13 }, { 16, 13 }, { 25, 13 }, { 26, 13 }, { 27, 13 }, + { 28, 13 }, { 29, 13 }, { 30, 13 }, { 31, 13 }, { 32, 13 }, + { 33, 13 }, { 24, 9 }, { 23, 8 }, { 22, 6 }, { 21, 5 }, + { 20, 4 }, { 19, 3 }, { 17, 2 }, { 18, 2 }, + }, + { /* DC lowquant table 1 */ + { 0, 4 }, { 3, 4 }, { 1, 3 }, { 2, 3 }, { 4, 4 }, + { 6, 4 }, { 5, 3 }, { 7, 3 }, { 8, 4 }, { 9, 4 }, + { 10, 5 }, { 11, 6 }, { 12, 9 }, { 13, 9 }, { 14, 13 }, + { 15, 13 }, { 16, 13 }, { 25, 13 }, { 26, 13 }, { 27, 13 }, + { 28, 12 }, { 29, 12 }, { 31, 12 }, { 32, 12 }, { 33, 12 }, + { 21, 9 }, { 20, 7 }, { 17, 6 }, { 18, 6 }, { 19, 6 }, + { 22, 7 }, { 23, 8 }, { 24, 9 }, { 30, 9 }, + }, + { /* DC lowquant table 2 */ + { 0, 4 }, { 3, 4 }, { 1, 3 }, { 2, 3 }, { 4, 4 }, + { 5, 4 }, { 6, 4 }, { 7, 4 }, { 8, 6 }, { 9, 6 }, + { 10, 7 }, { 11, 7 }, { 12, 12 }, { 13, 12 }, { 14, 12 }, + { 15, 12 }, { 16, 12 }, { 25, 12 }, { 26, 12 }, { 27, 12 }, + { 28, 12 }, { 29, 12 }, { 30, 12 }, { 31, 12 }, { 32, 11 }, + { 33, 11 }, { 24, 8 }, { 23, 7 }, { 17, 4 }, { 18, 3 }, + { 19, 4 }, { 20, 5 }, { 21, 6 }, { 22, 6 }, + }, + { /* DC lowquant table 3 */ + { 0, 4 }, { 6, 4 }, { 2, 3 }, { 1, 2 }, { 3, 3 }, + { 4, 3 }, { 5, 3 }, { 7, 4 }, { 8, 6 }, { 9, 6 }, + { 10, 7 }, { 11, 8 }, { 12, 14 }, { 13, 14 }, { 14, 14 }, + { 15, 14 }, { 16, 13 }, { 21, 13 }, { 22, 13 }, { 23, 13 }, + { 24, 13 }, { 25, 13 }, { 26, 13 }, { 27, 13 }, { 28, 13 }, + { 29, 13 }, { 30, 13 }, { 31, 13 }, { 32, 13 }, { 33, 13 }, + { 17, 9 }, { 18, 7 }, { 19, 8 }, { 20, 8 }, + }, + { /* DC lowquant table 4 */ + { 0, 7 }, { 1, 7 }, { 2, 7 }, { 3, 7 }, { 4, 7 }, + { 5, 7 }, { 6, 7 }, { 7, 7 }, { 8, 7 }, { 9, 7 }, + { 10, 7 }, { 11, 7 }, { 12, 7 }, { 13, 7 }, { 14, 7 }, + { 15, 7 }, { 16, 7 }, { 19, 7 }, { 20, 7 }, { 21, 7 }, + { 22, 7 }, { 23, 7 }, { 24, 7 }, { 25, 7 }, { 26, 7 }, + { 27, 7 }, { 28, 7 }, { 29, 7 }, { 30, 7 }, { 31, 7 }, + { 32, 7 }, { 33, 7 }, { 18, 2 }, { 17, 1 }, + }, + { /* DC lowquant table 5 */ + { 0, 5 }, { 2, 5 }, { 1, 4 }, { 3, 6 }, { 4, 6 }, + { 5, 6 }, { 6, 7 }, { 8, 7 }, { 7, 6 }, { 9, 6 }, + { 10, 8 }, { 12, 8 }, { 11, 7 }, { 13, 13 }, { 14, 13 }, + { 15, 13 }, { 16, 13 }, { 23, 13 }, { 24, 13 }, { 25, 13 }, + { 26, 13 }, { 27, 13 }, { 28, 13 }, { 29, 13 }, { 30, 13 }, + { 31, 13 }, { 32, 13 }, { 33, 12 }, { 22, 9 }, { 21, 8 }, + { 20, 7 }, { 17, 3 }, { 19, 3 }, { 18, 1 }, + }, + { /* DC lowquant table 6 */ + { 0, 4 }, { 4, 4 }, { 2, 3 }, { 1, 2 }, { 3, 3 }, + { 5, 4 }, { 6, 5 }, { 7, 6 }, { 8, 7 }, { 9, 7 }, + { 10, 8 }, { 11, 14 }, { 12, 14 }, { 15, 14 }, { 16, 14 }, + { 23, 14 }, { 24, 14 }, { 25, 14 }, { 26, 14 }, { 27, 14 }, + { 28, 14 }, { 29, 14 }, { 30, 14 }, { 31, 14 }, { 32, 14 }, + { 33, 13 }, { 13, 10 }, { 14, 9 }, { 21, 8 }, { 22, 8 }, + { 20, 6 }, { 19, 5 }, { 17, 4 }, { 18, 3 }, + }, + { /* DC lowquant table 7 */ + { 0, 6 }, { 1, 6 }, { 2, 6 }, { 3, 7 }, { 4, 7 }, + { 5, 6 }, { 6, 6 }, { 7, 6 }, { 8, 7 }, { 9, 8 }, + { 10, 8 }, { 11, 9 }, { 12, 10 }, { 13, 14 }, { 14, 14 }, + { 15, 14 }, { 16, 14 }, { 24, 14 }, { 25, 14 }, { 26, 14 }, + { 27, 14 }, { 28, 14 }, { 29, 14 }, { 30, 14 }, { 31, 14 }, + { 32, 13 }, { 33, 13 }, { 23, 8 }, { 22, 7 }, { 21, 6 }, + { 20, 5 }, { 19, 4 }, { 18, 2 }, { 17, 1 }, + }, }, }; #define MAX_DC_VLC_BITS 14 -static const uint16_t x8_ac0_lowquant_table[8][77][2] = { - { // 0 - { 0x0000, 2 }, { 0x0002, 3 }, { 0x0006, 4 }, { 0x000E, 5 }, - { 0x001E, 6 }, { 0x003E, 7 }, { 0x003F, 7 }, { 0x0040, 7 }, - { 0x0104, 9 }, { 0x0083, 8 }, { 0x0084, 8 }, { 0x0085, 8 }, - { 0x020A, 10 }, { 0x020B, 10 }, { 0x0218, 10 }, { 0x0219, 10 }, - { 0x0009, 4 }, { 0x0044, 7 }, { 0x010D, 9 }, { 0x021C, 10 }, - { 0x0023, 6 }, { 0x0045, 7 }, { 0x0050, 7 }, { 0x000B, 4 }, - { 0x000C, 4 }, { 0x0015, 5 }, { 0x001A, 5 }, { 0x001B, 5 }, - { 0x0029, 6 }, { 0x0038, 6 }, { 0x0039, 6 }, { 0x003A, 6 }, - { 0x0051, 7 }, { 0x0076, 7 }, { 0x0077, 7 }, { 0x0078, 7 }, - { 0x0079, 7 }, { 0x007A, 7 }, { 0x007B, 7 }, { 0x00F8, 8 }, - { 0x010F, 9 }, { 0x021D, 10 }, { 0x3E40, 14 }, { 0x3E41, 14 }, - { 0x3E42, 14 }, { 0x3E43, 14 }, { 0x03E5, 10 }, { 0x3E44, 14 }, - { 0x01F3, 9 }, { 0x3E45, 14 }, { 0x3E46, 14 }, { 0x3E47, 14 }, - { 0x00FA, 8 }, { 0x3E48, 14 }, { 0x3E49, 14 }, { 0x3E4A, 14 }, - { 0x3E4B, 14 }, { 0x03EC, 10 }, { 0x3E4C, 14 }, { 0x007E, 7 }, - { 0x00FE, 8 }, { 0x00FF, 8 }, { 0x01F7, 9 }, { 0x3E4D, 14 }, - { 0x3E4E, 14 }, { 0x3E4F, 14 }, { 0x3ED0, 14 }, { 0x3ED1, 14 }, - { 0x3ED2, 14 }, { 0x3ED3, 14 }, { 0x3ED4, 14 }, { 0x3ED5, 14 }, - { 0x1F6B, 13 }, { 0x1F6C, 13 }, { 0x1F6D, 13 }, { 0x1F6E, 13 }, - { 0x1F6F, 13 }, - }, - { // 1 - { 0x0000, 3 }, { 0x0004, 5 }, { 0x0014, 7 }, { 0x000B, 6 }, - { 0x000C, 6 }, { 0x002A, 8 }, { 0x002B, 8 }, { 0x0034, 8 }, - { 0x0D40, 14 }, { 0x0D41, 14 }, { 0x001B, 7 }, { 0x0D42, 14 }, - { 0x0D43, 14 }, { 0x0D44, 14 }, { 0x0D45, 14 }, { 0x0D46, 14 }, - { 0x000E, 6 }, { 0x003C, 8 }, { 0x0D47, 14 }, { 0x003D, 8 }, - { 0x0D48, 14 }, { 0x0D49, 14 }, { 0x0D4A, 14 }, { 0x0001, 2 }, - { 0x0004, 3 }, { 0x0014, 5 }, { 0x000B, 4 }, { 0x000C, 4 }, - { 0x000D, 4 }, { 0x002A, 6 }, { 0x001F, 7 }, { 0x0056, 7 }, - { 0x0057, 7 }, { 0x0070, 7 }, { 0x00E2, 8 }, { 0x0072, 7 }, - { 0x003A, 6 }, { 0x003B, 6 }, { 0x003C, 6 }, { 0x003D, 6 }, - { 0x00E3, 8 }, { 0x0D4B, 14 }, { 0x00E6, 8 }, { 0x00E7, 8 }, - { 0x00F8, 8 }, { 0x0D4C, 14 }, { 0x0D4D, 14 }, { 0x0D4E, 14 }, - { 0x00F9, 8 }, { 0x0D4F, 14 }, { 0x0D50, 14 }, { 0x0D51, 14 }, - { 0x06A9, 13 }, { 0x06AA, 13 }, { 0x06AB, 13 }, { 0x06AC, 13 }, - { 0x06AD, 13 }, { 0x06AE, 13 }, { 0x06AF, 13 }, { 0x003F, 6 }, - { 0x06B0, 13 }, { 0x06B1, 13 }, { 0x06B2, 13 }, { 0x06B3, 13 }, - { 0x06B4, 13 }, { 0x007D, 7 }, { 0x06B5, 13 }, { 0x06B6, 13 }, - { 0x06B7, 13 }, { 0x06B8, 13 }, { 0x06B9, 13 }, { 0x06BA, 13 }, - { 0x06BB, 13 }, { 0x06BC, 13 }, { 0x06BD, 13 }, { 0x06BE, 13 }, - { 0x06BF, 13 }, - }, - { // 2 - { 0x0000, 2 }, { 0x0002, 3 }, { 0x0003, 3 }, { 0x0008, 4 }, - { 0x0012, 5 }, { 0x0013, 5 }, { 0x0028, 6 }, { 0x0029, 6 }, - { 0x0054, 7 }, { 0x0055, 7 }, { 0x0056, 7 }, { 0x00AE, 8 }, - { 0x00AF, 8 }, { 0x00B0, 8 }, { 0x0162, 9 }, { 0x02C6, 10 }, - { 0x000C, 4 }, { 0x002D, 6 }, { 0x00B2, 8 }, { 0x0166, 9 }, - { 0x002E, 6 }, { 0x0167, 9 }, { 0x00BC, 8 }, { 0x001A, 5 }, - { 0x0036, 6 }, { 0x0037, 6 }, { 0x0038, 6 }, { 0x005F, 7 }, - { 0x0072, 7 }, { 0x0073, 7 }, { 0x0074, 7 }, { 0x0075, 7 }, - { 0x0076, 7 }, { 0x0077, 7 }, { 0x0078, 7 }, { 0x0079, 7 }, - { 0x007A, 7 }, { 0x007B, 7 }, { 0x00BD, 8 }, { 0xB1C0, 16 }, - { 0xB1C1, 16 }, { 0x58E1, 15 }, { 0x0B1D, 12 }, { 0x58E2, 15 }, - { 0x58E3, 15 }, { 0x58E4, 15 }, { 0x00F8, 8 }, { 0x03E4, 10 }, - { 0x01F3, 9 }, { 0x0B1E, 12 }, { 0x58E5, 15 }, { 0x58E6, 15 }, - { 0x00FA, 8 }, { 0x58E7, 15 }, { 0x58F8, 15 }, { 0x58F9, 15 }, - { 0x58FA, 15 }, { 0x01F6, 9 }, { 0x58FB, 15 }, { 0x007E, 7 }, - { 0x00FE, 8 }, { 0x00FF, 8 }, { 0x07CA, 11 }, { 0x0F96, 12 }, - { 0x58FC, 15 }, { 0x58FD, 15 }, { 0x58FE, 15 }, { 0x58FF, 15 }, - { 0x7CB8, 15 }, { 0x7CB9, 15 }, { 0x7CBA, 15 }, { 0x7CBB, 15 }, - { 0x7CBC, 15 }, { 0x01F7, 9 }, { 0x7CBD, 15 }, { 0x7CBE, 15 }, - { 0x7CBF, 15 }, - }, - { // 3 - { 0x0000, 2 }, { 0x0002, 3 }, { 0x0006, 4 }, { 0x000E, 5 }, - { 0x000F, 5 }, { 0x0020, 6 }, { 0x0021, 6 }, { 0x0044, 7 }, - { 0x0045, 7 }, { 0x008C, 8 }, { 0x008D, 8 }, { 0x011C, 9 }, - { 0x011D, 9 }, { 0x011E, 9 }, { 0x023E, 10 }, { 0x023F, 10 }, - { 0x0005, 3 }, { 0x0012, 5 }, { 0x004C, 7 }, { 0x004D, 7 }, - { 0x000C, 4 }, { 0x004E, 7 }, { 0x001A, 5 }, { 0x0036, 6 }, - { 0x004F, 7 }, { 0x006E, 7 }, { 0x006F, 7 }, { 0x00E0, 8 }, - { 0x00E1, 8 }, { 0x00E2, 8 }, { 0x00E3, 8 }, { 0x00E4, 8 }, - { 0x00E5, 8 }, { 0x01CC, 9 }, { 0x00E7, 8 }, { 0x00E8, 8 }, - { 0x00E9, 8 }, { 0x01CD, 9 }, { 0x0750, 11 }, { 0x03A9, 10 }, - { 0x0751, 11 }, { 0x7540, 15 }, { 0x03AB, 10 }, { 0x7541, 15 }, - { 0x7542, 15 }, { 0x7543, 15 }, { 0x01D6, 9 }, { 0x0755, 11 }, - { 0x0076, 7 }, { 0x0EA9, 12 }, { 0x7544, 15 }, { 0x7545, 15 }, - { 0x001E, 5 }, { 0x0077, 7 }, { 0x00F8, 8 }, { 0x03AE, 10 }, - { 0x075E, 11 }, { 0x007D, 7 }, { 0x03E4, 10 }, { 0x00FC, 8 }, - { 0x00FD, 8 }, { 0x03E5, 10 }, { 0x03E6, 10 }, { 0x0EBE, 12 }, - { 0x7546, 15 }, { 0x07CE, 11 }, { 0x7547, 15 }, { 0x75F8, 15 }, - { 0x75F9, 15 }, { 0x75FA, 15 }, { 0x75FB, 15 }, { 0x75FC, 15 }, - { 0x75FD, 15 }, { 0x007F, 7 }, { 0x3AFF, 14 }, { 0x0F9E, 12 }, - { 0x0F9F, 12 }, - }, - { // 4 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, - { 0x0012, 6 }, { 0x0013, 6 }, { 0x0014, 6 }, { 0x002A, 7 }, - { 0x0016, 6 }, { 0x002B, 7 }, { 0x005C, 8 }, { 0x005D, 8 }, - { 0x005E, 8 }, { 0x00BE, 9 }, { 0x00BF, 9 }, { 0x0060, 8 }, - { 0x0007, 4 }, { 0x000D, 5 }, { 0x0019, 6 }, { 0x0020, 6 }, - { 0x0009, 4 }, { 0x0021, 6 }, { 0x0011, 5 }, { 0x0014, 5 }, - { 0x002A, 6 }, { 0x002B, 6 }, { 0x002C, 6 }, { 0x002D, 6 }, - { 0x002E, 6 }, { 0x002F, 6 }, { 0x0030, 6 }, { 0x0031, 7 }, - { 0x0062, 7 }, { 0x0063, 7 }, { 0x0064, 7 }, { 0x0065, 7 }, - { 0x0066, 7 }, { 0x0061, 8 }, { 0x0670, 11 }, { 0x0068, 7 }, - { 0x0069, 7 }, { 0x00CF, 8 }, { 0x019D, 9 }, { 0x01A8, 9 }, - { 0x01A9, 9 }, { 0x0339, 10 }, { 0x01AA, 9 }, { 0x0356, 10 }, - { 0x0036, 6 }, { 0x00D6, 8 }, { 0x6710, 15 }, { 0x6711, 15 }, - { 0x000E, 4 }, { 0x006E, 7 }, { 0x01AE, 9 }, { 0x6712, 15 }, - { 0x6713, 15 }, { 0x003C, 6 }, { 0x0357, 10 }, { 0x006F, 7 }, - { 0x00F4, 8 }, { 0x00F5, 8 }, { 0x035E, 10 }, { 0x01EC, 9 }, - { 0x6714, 15 }, { 0x01ED, 9 }, { 0x035F, 10 }, { 0x03DC, 10 }, - { 0x03DD, 10 }, { 0x6715, 15 }, { 0x338B, 14 }, { 0x338C, 14 }, - { 0x338D, 14 }, { 0x001F, 5 }, { 0x01EF, 9 }, { 0x338E, 14 }, - { 0x338F, 14 }, - }, - { // 5 - { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x000B, 5 }, - { 0x0018, 6 }, { 0x0019, 6 }, { 0x0034, 7 }, { 0x006A, 8 }, - { 0x006B, 8 }, { 0x006C, 8 }, { 0x00DA, 9 }, { 0x036C, 11 }, - { 0x006E, 8 }, { 0x01B7, 10 }, { 0x036D, 11 }, { 0x3780, 15 }, - { 0x0004, 3 }, { 0x000E, 5 }, { 0x001E, 6 }, { 0x003E, 7 }, - { 0x000A, 4 }, { 0x002C, 6 }, { 0x0017, 5 }, { 0x002D, 6 }, - { 0x003F, 7 }, { 0x00C0, 8 }, { 0x0061, 7 }, { 0x00C1, 8 }, - { 0x0062, 7 }, { 0x00C6, 8 }, { 0x0064, 7 }, { 0x00C7, 8 }, - { 0x00CA, 8 }, { 0x00DF, 9 }, { 0x0196, 9 }, { 0x0197, 9 }, - { 0x0198, 9 }, { 0x0199, 9 }, { 0x0379, 11 }, { 0x019A, 9 }, - { 0x01BD, 10 }, { 0x066C, 11 }, { 0x3781, 15 }, { 0x0337, 10 }, - { 0x066D, 11 }, { 0x0670, 11 }, { 0x0339, 10 }, { 0x0671, 11 }, - { 0x0034, 6 }, { 0x00CF, 8 }, { 0x3782, 15 }, { 0x3783, 15 }, - { 0x000E, 4 }, { 0x001B, 5 }, { 0x006A, 7 }, { 0x006B, 7 }, - { 0x019D, 9 }, { 0x003C, 6 }, { 0x00F4, 8 }, { 0x00F5, 8 }, - { 0x03D8, 10 }, { 0x07B2, 11 }, { 0x3784, 15 }, { 0x03DA, 10 }, - { 0x3785, 15 }, { 0x03DB, 10 }, { 0x03DC, 10 }, { 0x3786, 15 }, - { 0x3787, 15 }, { 0x1BC4, 14 }, { 0x1BC5, 14 }, { 0x1BC6, 14 }, - { 0x1BC7, 14 }, { 0x001F, 5 }, { 0x03DD, 10 }, { 0x07B3, 11 }, - { 0x01EF, 9 }, - }, - { // 6 - { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x0016, 6 }, - { 0x0017, 6 }, { 0x0060, 8 }, { 0x00C2, 9 }, { 0x0186, 10 }, - { 0x0187, 10 }, { 0x00C4, 9 }, { 0x3140, 15 }, { 0x3141, 15 }, - { 0x018B, 10 }, { 0x3142, 15 }, { 0x018C, 10 }, { 0x3143, 15 }, - { 0x0007, 4 }, { 0x000D, 5 }, { 0x0064, 8 }, { 0x0065, 8 }, - { 0x0010, 5 }, { 0x00C7, 9 }, { 0x0066, 8 }, { 0x0005, 3 }, - { 0x0006, 3 }, { 0x0009, 4 }, { 0x0011, 5 }, { 0x0038, 6 }, - { 0x0039, 6 }, { 0x0074, 7 }, { 0x0075, 7 }, { 0x0076, 7 }, - { 0x0067, 8 }, { 0x00EE, 8 }, { 0x01DE, 9 }, { 0x00F0, 8 }, - { 0x018D, 10 }, { 0x3144, 15 }, { 0x01DF, 9 }, { 0x003D, 6 }, - { 0x003E, 6 }, { 0x01E2, 9 }, { 0x03C6, 10 }, { 0x00F2, 8 }, - { 0x00F3, 8 }, { 0x03C7, 10 }, { 0x3145, 15 }, { 0x3146, 15 }, - { 0x01F8, 9 }, { 0x3147, 15 }, { 0x3148, 15 }, { 0x3149, 15 }, - { 0x00FD, 8 }, { 0x314A, 15 }, { 0x314B, 15 }, { 0x314C, 15 }, - { 0x314D, 15 }, { 0x01F9, 9 }, { 0x314E, 15 }, { 0x01FC, 9 }, - { 0x314F, 15 }, { 0x3150, 15 }, { 0x3151, 15 }, { 0x3152, 15 }, - { 0x3153, 15 }, { 0x03FA, 10 }, { 0x03FB, 10 }, { 0x3154, 15 }, - { 0x3155, 15 }, { 0x3156, 15 }, { 0x3157, 15 }, { 0x3158, 15 }, - { 0x3159, 15 }, { 0x00FF, 8 }, { 0x18AD, 14 }, { 0x18AE, 14 }, - { 0x18AF, 14 }, - }, - { // 7 - { 0x0000, 4 }, { 0x0080, 11 }, { 0x0081, 11 }, { 0x0082, 11 }, - { 0x0083, 11 }, { 0x0084, 11 }, { 0x0085, 11 }, { 0x0086, 11 }, - { 0x0087, 11 }, { 0x0088, 11 }, { 0x0089, 11 }, { 0x008A, 11 }, - { 0x008B, 11 }, { 0x008C, 11 }, { 0x008D, 11 }, { 0x008E, 11 }, - { 0x008F, 11 }, { 0x0048, 10 }, { 0x0049, 10 }, { 0x004A, 10 }, - { 0x004B, 10 }, { 0x004C, 10 }, { 0x004D, 10 }, { 0x0001, 1 }, - { 0x0001, 2 }, { 0x004E, 10 }, { 0x0002, 4 }, { 0x0003, 4 }, - { 0x004F, 10 }, { 0x0050, 10 }, { 0x0051, 10 }, { 0x0052, 10 }, - { 0x0053, 10 }, { 0x0054, 10 }, { 0x0055, 10 }, { 0x0056, 10 }, - { 0x0057, 10 }, { 0x0058, 10 }, { 0x0059, 10 }, { 0x005A, 10 }, - { 0x005B, 10 }, { 0x005C, 10 }, { 0x005D, 10 }, { 0x005E, 10 }, - { 0x005F, 10 }, { 0x0060, 10 }, { 0x0061, 10 }, { 0x0062, 10 }, - { 0x0063, 10 }, { 0x0064, 10 }, { 0x0065, 10 }, { 0x0066, 10 }, - { 0x0067, 10 }, { 0x0068, 10 }, { 0x0069, 10 }, { 0x006A, 10 }, - { 0x006B, 10 }, { 0x006C, 10 }, { 0x006D, 10 }, { 0x006E, 10 }, - { 0x006F, 10 }, { 0x0070, 10 }, { 0x0071, 10 }, { 0x0072, 10 }, - { 0x0073, 10 }, { 0x0074, 10 }, { 0x0075, 10 }, { 0x0076, 10 }, - { 0x0077, 10 }, { 0x0078, 10 }, { 0x0079, 10 }, { 0x007A, 10 }, - { 0x007B, 10 }, { 0x007C, 10 }, { 0x007D, 10 }, { 0x007E, 10 }, - { 0x007F, 10 }, - }, -}; - -static const uint16_t x8_ac0_highquant_table[8][77][2] = { - { // 0 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x000C, 6 }, { 0x000D, 6 }, - { 0x001C, 7 }, { 0x000F, 6 }, { 0x1D00, 15 }, { 0x003B, 8 }, - { 0x1D01, 15 }, { 0x0075, 9 }, { 0x1D02, 15 }, { 0x0080, 9 }, - { 0x1D03, 15 }, { 0x1D04, 15 }, { 0x1D05, 15 }, { 0x0E83, 14 }, - { 0x0009, 5 }, { 0x0011, 6 }, { 0x0081, 9 }, { 0x0082, 9 }, - { 0x0021, 7 }, { 0x0028, 7 }, { 0x0083, 9 }, { 0x0002, 2 }, - { 0x0003, 3 }, { 0x000C, 4 }, { 0x000D, 4 }, { 0x000B, 5 }, - { 0x0015, 6 }, { 0x0052, 8 }, { 0x0070, 7 }, { 0x0039, 6 }, - { 0x0071, 7 }, { 0x0053, 8 }, { 0x0E84, 14 }, { 0x0074, 7 }, - { 0x0075, 7 }, { 0x0076, 7 }, { 0x01DC, 9 }, { 0x001E, 5 }, - { 0x003E, 6 }, { 0x01DD, 9 }, { 0x00EF, 8 }, { 0x01F8, 9 }, - { 0x01F9, 9 }, { 0x0E85, 14 }, { 0x0E86, 14 }, { 0x0E87, 14 }, - { 0x00FD, 8 }, { 0x0E88, 14 }, { 0x0E89, 14 }, { 0x0E8A, 14 }, - { 0x0E8B, 14 }, { 0x0E8C, 14 }, { 0x0E8D, 14 }, { 0x0E8E, 14 }, - { 0x0E8F, 14 }, { 0x0E90, 14 }, { 0x0E91, 14 }, { 0x01FC, 9 }, - { 0x0E92, 14 }, { 0x0E93, 14 }, { 0x0E94, 14 }, { 0x0E95, 14 }, - { 0x0E96, 14 }, { 0x0E97, 14 }, { 0x01FD, 9 }, { 0x0E98, 14 }, - { 0x01FE, 9 }, { 0x0E99, 14 }, { 0x0E9A, 14 }, { 0x0E9B, 14 }, - { 0x0E9C, 14 }, { 0x01FF, 9 }, { 0x0E9D, 14 }, { 0x0E9E, 14 }, - { 0x0E9F, 14 }, - }, - { // 1 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, - { 0x0012, 6 }, { 0x0013, 6 }, { 0x0014, 6 }, { 0x0015, 6 }, - { 0x002C, 7 }, { 0x005A, 8 }, { 0x005B, 8 }, { 0x005C, 8 }, - { 0x005D, 8 }, { 0x1780, 14 }, { 0x0179, 10 }, { 0x017A, 10 }, - { 0x0006, 4 }, { 0x000E, 5 }, { 0x001E, 6 }, { 0x003E, 7 }, - { 0x0010, 5 }, { 0x0022, 6 }, { 0x0012, 5 }, { 0x000A, 4 }, - { 0x0013, 5 }, { 0x0016, 5 }, { 0x0023, 6 }, { 0x002E, 6 }, - { 0x002F, 6 }, { 0x0030, 6 }, { 0x0031, 6 }, { 0x003F, 7 }, - { 0x005F, 8 }, { 0x00C8, 8 }, { 0x0065, 7 }, { 0x0066, 7 }, - { 0x0067, 7 }, { 0x0068, 7 }, { 0x00C9, 8 }, { 0x0069, 7 }, - { 0x006A, 7 }, { 0x00D6, 8 }, { 0x00D7, 8 }, { 0x00D8, 8 }, - { 0x1781, 14 }, { 0x017B, 10 }, { 0x01B2, 9 }, { 0x1782, 14 }, - { 0x001C, 5 }, { 0x01B3, 9 }, { 0x1783, 14 }, { 0x1784, 14 }, - { 0x001D, 5 }, { 0x00DA, 8 }, { 0x1785, 14 }, { 0x1786, 14 }, - { 0x1787, 14 }, { 0x0037, 6 }, { 0x00DB, 8 }, { 0x0078, 7 }, - { 0x00F2, 8 }, { 0x01E6, 9 }, { 0x00F4, 8 }, { 0x1788, 14 }, - { 0x1789, 14 }, { 0x00F5, 8 }, { 0x01E7, 9 }, { 0x178A, 14 }, - { 0x178B, 14 }, { 0x178C, 14 }, { 0x178D, 14 }, { 0x01EC, 9 }, - { 0x178E, 14 }, { 0x001F, 5 }, { 0x00F7, 8 }, { 0x01ED, 9 }, - { 0x178F, 14 }, - }, - { // 2 - { 0x0000, 4 }, { 0x0002, 5 }, { 0x0180, 12 }, { 0x0181, 12 }, - { 0x0182, 12 }, { 0x0183, 12 }, { 0x0184, 12 }, { 0x0185, 12 }, - { 0x0186, 12 }, { 0x0187, 12 }, { 0x0188, 12 }, { 0x0189, 12 }, - { 0x00C5, 11 }, { 0x00C6, 11 }, { 0x00C7, 11 }, { 0x00C8, 11 }, - { 0x00C9, 11 }, { 0x00CA, 11 }, { 0x00CB, 11 }, { 0x00CC, 11 }, - { 0x00CD, 11 }, { 0x00CE, 11 }, { 0x00CF, 11 }, { 0x0001, 1 }, - { 0x0001, 2 }, { 0x0004, 5 }, { 0x0005, 5 }, { 0x0006, 5 }, - { 0x00D0, 11 }, { 0x00D1, 11 }, { 0x00D2, 11 }, { 0x00D3, 11 }, - { 0x00D4, 11 }, { 0x00D5, 11 }, { 0x00D6, 11 }, { 0x00D7, 11 }, - { 0x00D8, 11 }, { 0x00D9, 11 }, { 0x00DA, 11 }, { 0x0007, 5 }, - { 0x00DB, 11 }, { 0x00DC, 11 }, { 0x00DD, 11 }, { 0x00DE, 11 }, - { 0x00DF, 11 }, { 0x00E0, 11 }, { 0x00E1, 11 }, { 0x00E2, 11 }, - { 0x00E3, 11 }, { 0x00E4, 11 }, { 0x00E5, 11 }, { 0x00E6, 11 }, - { 0x00E7, 11 }, { 0x00E8, 11 }, { 0x00E9, 11 }, { 0x00EA, 11 }, - { 0x00EB, 11 }, { 0x00EC, 11 }, { 0x00ED, 11 }, { 0x00EE, 11 }, - { 0x00EF, 11 }, { 0x00F0, 11 }, { 0x00F1, 11 }, { 0x00F2, 11 }, - { 0x00F3, 11 }, { 0x00F4, 11 }, { 0x00F5, 11 }, { 0x00F6, 11 }, - { 0x00F7, 11 }, { 0x00F8, 11 }, { 0x00F9, 11 }, { 0x00FA, 11 }, - { 0x00FB, 11 }, { 0x00FC, 11 }, { 0x00FD, 11 }, { 0x00FE, 11 }, - { 0x00FF, 11 }, - }, - { // 3 - { 0x0000, 8 }, { 0x0001, 8 }, { 0x0002, 8 }, { 0x0003, 8 }, - { 0x0004, 8 }, { 0x0005, 8 }, { 0x0006, 8 }, { 0x0007, 8 }, - { 0x0008, 8 }, { 0x0009, 8 }, { 0x000A, 8 }, { 0x000B, 8 }, - { 0x000C, 8 }, { 0x000D, 8 }, { 0x000E, 8 }, { 0x000F, 8 }, - { 0x0010, 8 }, { 0x0011, 8 }, { 0x0012, 8 }, { 0x0013, 8 }, - { 0x0014, 8 }, { 0x0015, 8 }, { 0x0016, 8 }, { 0x0001, 1 }, - { 0x0017, 8 }, { 0x000C, 7 }, { 0x000D, 7 }, { 0x000E, 7 }, - { 0x000F, 7 }, { 0x0010, 7 }, { 0x0011, 7 }, { 0x0012, 7 }, - { 0x0013, 7 }, { 0x0014, 7 }, { 0x0015, 7 }, { 0x0016, 7 }, - { 0x0017, 7 }, { 0x0018, 7 }, { 0x0019, 7 }, { 0x001A, 7 }, - { 0x001B, 7 }, { 0x001C, 7 }, { 0x001D, 7 }, { 0x001E, 7 }, - { 0x001F, 7 }, { 0x0020, 7 }, { 0x0021, 7 }, { 0x0022, 7 }, - { 0x0023, 7 }, { 0x0024, 7 }, { 0x0025, 7 }, { 0x0026, 7 }, - { 0x0027, 7 }, { 0x0028, 7 }, { 0x0029, 7 }, { 0x002A, 7 }, - { 0x002B, 7 }, { 0x002C, 7 }, { 0x002D, 7 }, { 0x002E, 7 }, - { 0x002F, 7 }, { 0x0030, 7 }, { 0x0031, 7 }, { 0x0032, 7 }, - { 0x0033, 7 }, { 0x0034, 7 }, { 0x0035, 7 }, { 0x0036, 7 }, - { 0x0037, 7 }, { 0x0038, 7 }, { 0x0039, 7 }, { 0x003A, 7 }, - { 0x003B, 7 }, { 0x003C, 7 }, { 0x003D, 7 }, { 0x003E, 7 }, - { 0x003F, 7 }, - }, - { // 4 - { 0x0000, 9 }, { 0x0001, 9 }, { 0x0002, 9 }, { 0x0003, 9 }, - { 0x0004, 9 }, { 0x0005, 9 }, { 0x0006, 9 }, { 0x0007, 9 }, - { 0x0008, 9 }, { 0x0009, 9 }, { 0x000A, 9 }, { 0x000B, 9 }, - { 0x000C, 9 }, { 0x000D, 9 }, { 0x000E, 9 }, { 0x000F, 9 }, - { 0x0010, 9 }, { 0x0011, 9 }, { 0x0012, 9 }, { 0x0013, 9 }, - { 0x0014, 9 }, { 0x0015, 9 }, { 0x000B, 8 }, { 0x0001, 2 }, - { 0x0001, 1 }, { 0x000C, 8 }, { 0x000D, 8 }, { 0x000E, 8 }, - { 0x000F, 8 }, { 0x0010, 8 }, { 0x0011, 8 }, { 0x0012, 8 }, - { 0x0013, 8 }, { 0x0014, 8 }, { 0x0015, 8 }, { 0x0016, 8 }, - { 0x0017, 8 }, { 0x0018, 8 }, { 0x0019, 8 }, { 0x001A, 8 }, - { 0x001B, 8 }, { 0x001C, 8 }, { 0x001D, 8 }, { 0x001E, 8 }, - { 0x001F, 8 }, { 0x0020, 8 }, { 0x0021, 8 }, { 0x0022, 8 }, - { 0x0023, 8 }, { 0x0024, 8 }, { 0x0025, 8 }, { 0x0026, 8 }, - { 0x0027, 8 }, { 0x0028, 8 }, { 0x0029, 8 }, { 0x002A, 8 }, - { 0x002B, 8 }, { 0x002C, 8 }, { 0x002D, 8 }, { 0x002E, 8 }, - { 0x002F, 8 }, { 0x0030, 8 }, { 0x0031, 8 }, { 0x0032, 8 }, - { 0x0033, 8 }, { 0x0034, 8 }, { 0x0035, 8 }, { 0x0036, 8 }, - { 0x0037, 8 }, { 0x0038, 8 }, { 0x0039, 8 }, { 0x003A, 8 }, - { 0x003B, 8 }, { 0x003C, 8 }, { 0x003D, 8 }, { 0x003E, 8 }, - { 0x003F, 8 }, - }, - { // 5 - { 0x0000, 10 }, { 0x0001, 10 }, { 0x0002, 10 }, { 0x0003, 10 }, - { 0x0004, 10 }, { 0x0005, 10 }, { 0x0006, 10 }, { 0x0007, 10 }, - { 0x0008, 10 }, { 0x0009, 10 }, { 0x000A, 10 }, { 0x000B, 10 }, - { 0x000C, 10 }, { 0x000D, 10 }, { 0x000E, 10 }, { 0x000F, 10 }, - { 0x0010, 10 }, { 0x0011, 10 }, { 0x0012, 10 }, { 0x0013, 10 }, - { 0x000A, 9 }, { 0x000B, 9 }, { 0x000C, 9 }, { 0x0001, 1 }, - { 0x0001, 3 }, { 0x000D, 9 }, { 0x000E, 9 }, { 0x0001, 2 }, - { 0x000F, 9 }, { 0x0010, 9 }, { 0x0011, 9 }, { 0x0012, 9 }, - { 0x0013, 9 }, { 0x0014, 9 }, { 0x0015, 9 }, { 0x0016, 9 }, - { 0x0017, 9 }, { 0x0018, 9 }, { 0x0019, 9 }, { 0x001A, 9 }, - { 0x001B, 9 }, { 0x001C, 9 }, { 0x001D, 9 }, { 0x001E, 9 }, - { 0x001F, 9 }, { 0x0020, 9 }, { 0x0021, 9 }, { 0x0022, 9 }, - { 0x0023, 9 }, { 0x0024, 9 }, { 0x0025, 9 }, { 0x0026, 9 }, - { 0x0027, 9 }, { 0x0028, 9 }, { 0x0029, 9 }, { 0x002A, 9 }, - { 0x002B, 9 }, { 0x002C, 9 }, { 0x002D, 9 }, { 0x002E, 9 }, - { 0x002F, 9 }, { 0x0030, 9 }, { 0x0031, 9 }, { 0x0032, 9 }, - { 0x0033, 9 }, { 0x0034, 9 }, { 0x0035, 9 }, { 0x0036, 9 }, - { 0x0037, 9 }, { 0x0038, 9 }, { 0x0039, 9 }, { 0x003A, 9 }, - { 0x003B, 9 }, { 0x003C, 9 }, { 0x003D, 9 }, { 0x003E, 9 }, - { 0x003F, 9 }, - }, - { // 6 - { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x000B, 5 }, - { 0x0018, 6 }, { 0x0019, 6 }, { 0x0034, 7 }, { 0x006A, 8 }, - { 0x006B, 8 }, { 0x006C, 8 }, { 0x00DA, 9 }, { 0x00DB, 9 }, - { 0x01B8, 10 }, { 0x00DD, 9 }, { 0x01B9, 10 }, { 0x3780, 15 }, - { 0x0004, 3 }, { 0x000E, 5 }, { 0x001E, 6 }, { 0x001F, 6 }, - { 0x000A, 4 }, { 0x0058, 7 }, { 0x0017, 5 }, { 0x0018, 5 }, - { 0x0059, 7 }, { 0x005A, 7 }, { 0x005B, 7 }, { 0x00C8, 8 }, - { 0x0065, 7 }, { 0x0066, 7 }, { 0x00C9, 8 }, { 0x00CE, 8 }, - { 0x00CF, 8 }, { 0x00D0, 8 }, { 0x00D1, 8 }, { 0x00D2, 8 }, - { 0x00D3, 8 }, { 0x00DF, 9 }, { 0x00D4, 8 }, { 0x00D5, 8 }, - { 0x00D6, 8 }, { 0x01AE, 9 }, { 0x3781, 15 }, { 0x01BD, 10 }, - { 0x035E, 10 }, { 0x035F, 10 }, { 0x3782, 15 }, { 0x0360, 10 }, - { 0x0037, 6 }, { 0x01B1, 9 }, { 0x3783, 15 }, { 0x3784, 15 }, - { 0x000E, 4 }, { 0x003C, 6 }, { 0x0361, 10 }, { 0x3785, 15 }, - { 0x1BC3, 14 }, { 0x003D, 6 }, { 0x00D9, 8 }, { 0x1BC4, 14 }, - { 0x0368, 10 }, { 0x1BC5, 14 }, { 0x1BC6, 14 }, { 0x1BC7, 14 }, - { 0x1BC8, 14 }, { 0x00DB, 8 }, { 0x0369, 10 }, { 0x036A, 10 }, - { 0x1BC9, 14 }, { 0x1BCA, 14 }, { 0x1BCB, 14 }, { 0x1BCC, 14 }, - { 0x1BCD, 14 }, { 0x001F, 5 }, { 0x036B, 10 }, { 0x1BCE, 14 }, - { 0x1BCF, 14 }, - }, - { // 7 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0006, 5 }, { 0x0007, 5 }, - { 0x0010, 6 }, { 0x0044, 8 }, { 0x0023, 7 }, { 0x0012, 6 }, - { 0x0026, 7 }, { 0x08A0, 13 }, { 0x004E, 8 }, { 0x004F, 8 }, - { 0x08A1, 13 }, { 0x08A2, 13 }, { 0x08A3, 13 }, { 0x0050, 8 }, - { 0x0006, 4 }, { 0x000B, 5 }, { 0x0029, 7 }, { 0x0015, 6 }, - { 0x001C, 6 }, { 0x003A, 7 }, { 0x001E, 6 }, { 0x0004, 3 }, - { 0x0014, 5 }, { 0x0015, 5 }, { 0x000B, 4 }, { 0x001F, 6 }, - { 0x0030, 6 }, { 0x0031, 6 }, { 0x0019, 5 }, { 0x0051, 8 }, - { 0x0034, 6 }, { 0x0035, 6 }, { 0x0036, 6 }, { 0x0037, 6 }, - { 0x0076, 8 }, { 0x0077, 8 }, { 0x0070, 7 }, { 0x001D, 5 }, - { 0x0071, 7 }, { 0x0072, 7 }, { 0x08A4, 13 }, { 0x0073, 7 }, - { 0x00F0, 8 }, { 0x08A5, 13 }, { 0x08A6, 13 }, { 0x08A7, 13 }, - { 0x0079, 7 }, { 0x007A, 7 }, { 0x08A8, 13 }, { 0x08A9, 13 }, - { 0x00F1, 8 }, { 0x08AA, 13 }, { 0x08AB, 13 }, { 0x08AC, 13 }, - { 0x08AD, 13 }, { 0x00F6, 8 }, { 0x08AE, 13 }, { 0x007C, 7 }, - { 0x00F7, 8 }, { 0x08AF, 13 }, { 0x08B0, 13 }, { 0x08B1, 13 }, - { 0x08B2, 13 }, { 0x00FA, 8 }, { 0x08B3, 13 }, { 0x08B4, 13 }, - { 0x08B5, 13 }, { 0x08B6, 13 }, { 0x08B7, 13 }, { 0x00FB, 8 }, - { 0x045C, 12 }, { 0x003F, 6 }, { 0x045D, 12 }, { 0x045E, 12 }, - { 0x045F, 12 }, - }, -}; - -static const uint16_t x8_ac1_lowquant_table[8][77][2] = { - { // 0 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, - { 0x0012, 6 }, { 0x0026, 7 }, { 0x0014, 6 }, { 0x004E, 8 }, - { 0x004F, 8 }, { 0x00A8, 9 }, { 0x0152, 10 }, { 0x00AA, 9 }, - { 0x00AB, 9 }, { 0x00AC, 9 }, { 0x2A60, 15 }, { 0x02A7, 11 }, - { 0x0006, 4 }, { 0x000B, 5 }, { 0x001C, 6 }, { 0x003A, 7 }, - { 0x000F, 5 }, { 0x003B, 7 }, { 0x0010, 5 }, { 0x0005, 3 }, - { 0x0009, 4 }, { 0x0011, 5 }, { 0x0018, 5 }, { 0x0019, 5 }, - { 0x001A, 5 }, { 0x0036, 6 }, { 0x0037, 6 }, { 0x0070, 7 }, - { 0x0057, 8 }, { 0x00E2, 8 }, { 0x00E3, 8 }, { 0x00E4, 8 }, - { 0x00E5, 8 }, { 0x00AD, 9 }, { 0x0398, 10 }, { 0x003A, 6 }, - { 0x0076, 7 }, { 0x00E7, 8 }, { 0x00EE, 8 }, { 0x00EF, 8 }, - { 0x0732, 11 }, { 0x039A, 10 }, { 0x0733, 11 }, { 0x2A61, 15 }, - { 0x0078, 7 }, { 0x1531, 14 }, { 0x1532, 14 }, { 0x1533, 14 }, - { 0x003D, 6 }, { 0x039B, 10 }, { 0x1534, 14 }, { 0x1535, 14 }, - { 0x1536, 14 }, { 0x0079, 7 }, { 0x1537, 14 }, { 0x00F8, 8 }, - { 0x01F2, 9 }, { 0x07CC, 11 }, { 0x03E7, 10 }, { 0x07CD, 11 }, - { 0x3E80, 14 }, { 0x00FB, 8 }, { 0x03E9, 10 }, { 0x3E81, 14 }, - { 0x3E82, 14 }, { 0x3E83, 14 }, { 0x3E84, 14 }, { 0x3E85, 14 }, - { 0x3E86, 14 }, { 0x003F, 6 }, { 0x01F5, 9 }, { 0x07D1, 11 }, - { 0x3E87, 14 }, - }, - { // 1 - { 0x0000, 2 }, { 0x0002, 3 }, { 0x0006, 4 }, { 0x000E, 5 }, - { 0x001E, 6 }, { 0x001F, 6 }, { 0x0040, 7 }, { 0x0082, 8 }, - { 0x0083, 8 }, { 0x0084, 8 }, { 0x010A, 9 }, { 0x010B, 9 }, - { 0x0430, 11 }, { 0x0431, 11 }, { 0x0432, 11 }, { 0x0433, 11 }, - { 0x0005, 3 }, { 0x0011, 5 }, { 0x0024, 6 }, { 0x004A, 7 }, - { 0x000C, 4 }, { 0x0026, 6 }, { 0x000D, 4 }, { 0x0087, 8 }, - { 0x010D, 9 }, { 0x0258, 10 }, { 0x012D, 9 }, { 0x0259, 10 }, - { 0x025C, 10 }, { 0x0974, 12 }, { 0x025E, 10 }, { 0x025F, 10 }, - { 0x0270, 10 }, { 0x0271, 10 }, { 0x04BB, 11 }, { 0x0975, 12 }, - { 0x0272, 10 }, { 0x09CC, 12 }, { 0x09CD, 12 }, { 0x4E70, 15 }, - { 0x4E71, 15 }, { 0x4E72, 15 }, { 0x4E73, 15 }, { 0x273A, 14 }, - { 0x273B, 14 }, { 0x273C, 14 }, { 0x04E8, 11 }, { 0x04E9, 11 }, - { 0x009E, 8 }, { 0x0275, 10 }, { 0x09D8, 12 }, { 0x273D, 14 }, - { 0x000E, 4 }, { 0x003C, 6 }, { 0x007A, 7 }, { 0x009F, 8 }, - { 0x0277, 10 }, { 0x003E, 6 }, { 0x00F6, 8 }, { 0x04ED, 11 }, - { 0x03DC, 10 }, { 0x273E, 14 }, { 0x07BA, 11 }, { 0x09D9, 12 }, - { 0x273F, 14 }, { 0x3DD8, 14 }, { 0x3DD9, 14 }, { 0x3DDA, 14 }, - { 0x3DDB, 14 }, { 0x3DDC, 14 }, { 0x3DDD, 14 }, { 0x3DDE, 14 }, - { 0x3DDF, 14 }, { 0x003F, 6 }, { 0x07BC, 11 }, { 0x07BD, 11 }, - { 0x03DF, 10 }, - }, - { // 2 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0006, 5 }, { 0x000E, 6 }, - { 0x001E, 7 }, { 0x003E, 8 }, { 0x003F, 8 }, { 0x0040, 8 }, - { 0x0104, 10 }, { 0x0083, 9 }, { 0x0105, 10 }, { 0x0108, 10 }, - { 0x4240, 16 }, { 0x010A, 10 }, { 0x010B, 10 }, { 0x4241, 16 }, - { 0x0003, 3 }, { 0x0009, 5 }, { 0x0011, 6 }, { 0x0043, 8 }, - { 0x0004, 3 }, { 0x000A, 5 }, { 0x000A, 4 }, { 0x002C, 7 }, - { 0x00B4, 9 }, { 0x00B5, 9 }, { 0x00B6, 9 }, { 0x00B7, 9 }, - { 0x00B8, 9 }, { 0x0172, 10 }, { 0x0173, 10 }, { 0x0174, 10 }, - { 0x0175, 10 }, { 0x0176, 10 }, { 0x0177, 10 }, { 0x00BC, 9 }, - { 0x017A, 10 }, { 0x0213, 11 }, { 0x4242, 16 }, { 0x017B, 10 }, - { 0x02F8, 11 }, { 0x017D, 10 }, { 0x02F9, 11 }, { 0x017E, 10 }, - { 0x4243, 16 }, { 0x02FE, 11 }, { 0x2122, 15 }, { 0x2123, 15 }, - { 0x0058, 7 }, { 0x0164, 9 }, { 0x2124, 15 }, { 0x2125, 15 }, - { 0x0006, 3 }, { 0x000E, 4 }, { 0x002D, 6 }, { 0x002E, 6 }, - { 0x00B3, 8 }, { 0x001E, 5 }, { 0x005E, 7 }, { 0x2126, 15 }, - { 0x2127, 15 }, { 0x2128, 15 }, { 0x2129, 15 }, { 0x02FF, 11 }, - { 0x212A, 15 }, { 0x0594, 11 }, { 0x0595, 11 }, { 0x0596, 11 }, - { 0x212B, 15 }, { 0x212C, 15 }, { 0x212D, 15 }, { 0x212E, 15 }, - { 0x212F, 15 }, { 0x001F, 5 }, { 0x0597, 11 }, { 0x00BE, 8 }, - { 0x00BF, 8 }, - }, - { // 3 - { 0x0000, 2 }, { 0x0002, 3 }, { 0x0006, 4 }, { 0x0007, 4 }, - { 0x0010, 5 }, { 0x0011, 5 }, { 0x0024, 6 }, { 0x0025, 6 }, - { 0x0026, 6 }, { 0x0027, 6 }, { 0x0050, 7 }, { 0x0051, 7 }, - { 0x00A4, 8 }, { 0x00A5, 8 }, { 0x00A6, 8 }, { 0x014E, 9 }, - { 0x000B, 4 }, { 0x002A, 6 }, { 0x0056, 7 }, { 0x014F, 9 }, - { 0x0030, 6 }, { 0x00AE, 8 }, { 0x0062, 7 }, { 0x0032, 6 }, - { 0x0033, 6 }, { 0x0034, 6 }, { 0x0035, 6 }, { 0x0036, 6 }, - { 0x0063, 7 }, { 0x006E, 7 }, { 0x006F, 7 }, { 0x0070, 7 }, - { 0x0071, 7 }, { 0x0072, 7 }, { 0x0073, 7 }, { 0x0074, 7 }, - { 0x00AF, 8 }, { 0x00EA, 8 }, { 0x01D6, 9 }, { 0x075C, 11 }, - { 0x03AF, 10 }, { 0x75D0, 15 }, { 0x75D1, 15 }, { 0x75D2, 15 }, - { 0x75D3, 15 }, { 0x75D4, 15 }, { 0x0076, 7 }, { 0x00EE, 8 }, - { 0x00EF, 8 }, { 0x0EBB, 12 }, { 0x01E0, 9 }, { 0x75D5, 15 }, - { 0x0079, 7 }, { 0x01E1, 9 }, { 0x75D6, 15 }, { 0x75D7, 15 }, - { 0x7880, 15 }, { 0x00F4, 8 }, { 0x0789, 11 }, { 0x003E, 6 }, - { 0x007B, 7 }, { 0x00F5, 8 }, { 0x00FC, 8 }, { 0x007F, 7 }, - { 0x01E3, 9 }, { 0x078A, 11 }, { 0x078B, 11 }, { 0x7881, 15 }, - { 0x7882, 15 }, { 0x7883, 15 }, { 0x3C42, 14 }, { 0x3C43, 14 }, - { 0x3C44, 14 }, { 0x00FD, 8 }, { 0x3C45, 14 }, { 0x3C46, 14 }, - { 0x3C47, 14 }, - }, - { // 4 - { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x0016, 6 }, - { 0x0017, 6 }, { 0x0030, 7 }, { 0x0031, 7 }, { 0x0064, 8 }, - { 0x0065, 8 }, { 0x0066, 8 }, { 0x00CE, 9 }, { 0x00CF, 9 }, - { 0x01A0, 10 }, { 0x01A1, 10 }, { 0x1A20, 14 }, { 0x0689, 12 }, - { 0x0004, 3 }, { 0x000E, 5 }, { 0x001B, 6 }, { 0x0035, 7 }, - { 0x000A, 4 }, { 0x001E, 6 }, { 0x0016, 5 }, { 0x0017, 5 }, - { 0x001F, 6 }, { 0x0030, 6 }, { 0x0031, 6 }, { 0x0064, 7 }, - { 0x0065, 7 }, { 0x0069, 8 }, { 0x0066, 7 }, { 0x00CE, 8 }, - { 0x00CF, 8 }, { 0x00D0, 8 }, { 0x00D1, 8 }, { 0x00D2, 8 }, - { 0x01A6, 9 }, { 0x01A3, 10 }, { 0x034E, 10 }, { 0x006A, 7 }, - { 0x00D6, 8 }, { 0x01AE, 9 }, { 0x01AF, 9 }, { 0x034F, 10 }, - { 0x0345, 11 }, { 0x01B0, 9 }, { 0x01B1, 9 }, { 0x0364, 10 }, - { 0x006D, 7 }, { 0x00DC, 8 }, { 0x0D94, 12 }, { 0x0D95, 12 }, - { 0x000E, 4 }, { 0x003C, 6 }, { 0x00DD, 8 }, { 0x00DE, 8 }, - { 0x01B3, 9 }, { 0x003D, 6 }, { 0x00DF, 8 }, { 0x01F0, 9 }, - { 0x03E2, 10 }, { 0x03E3, 10 }, { 0x06CB, 11 }, { 0x03E4, 10 }, - { 0x07CA, 11 }, { 0x01F3, 9 }, { 0x01F4, 9 }, { 0x07CB, 11 }, - { 0x07D4, 11 }, { 0x1A21, 14 }, { 0x1A22, 14 }, { 0x07D5, 11 }, - { 0x1A23, 14 }, { 0x003F, 6 }, { 0x01F6, 9 }, { 0x01F7, 9 }, - { 0x03EB, 10 }, - }, - { // 5 - { 0x0000, 2 }, { 0x0002, 3 }, { 0x0006, 4 }, { 0x000E, 5 }, - { 0x000F, 5 }, { 0x0020, 6 }, { 0x0021, 6 }, { 0x0044, 7 }, - { 0x0045, 7 }, { 0x0046, 7 }, { 0x008E, 8 }, { 0x008F, 8 }, - { 0x0090, 8 }, { 0x0122, 9 }, { 0x0246, 10 }, { 0x0124, 9 }, - { 0x0005, 3 }, { 0x0013, 5 }, { 0x004A, 7 }, { 0x0093, 8 }, - { 0x0018, 5 }, { 0x004B, 7 }, { 0x0032, 6 }, { 0x001A, 5 }, - { 0x0033, 6 }, { 0x006C, 7 }, { 0x006D, 7 }, { 0x006E, 7 }, - { 0x00DE, 8 }, { 0x00DF, 8 }, { 0x0070, 7 }, { 0x00E2, 8 }, - { 0x00E3, 8 }, { 0x00E4, 8 }, { 0x00E5, 8 }, { 0x00E6, 8 }, - { 0x00E7, 8 }, { 0x0125, 9 }, { 0x01D0, 9 }, { 0x048E, 11 }, - { 0x091E, 12 }, { 0x091F, 12 }, { 0x7440, 15 }, { 0x1D11, 13 }, - { 0x7441, 15 }, { 0x7442, 15 }, { 0x00E9, 8 }, { 0x01D4, 9 }, - { 0x00EB, 8 }, { 0x03A3, 10 }, { 0x01D5, 9 }, { 0x1D12, 13 }, - { 0x001E, 5 }, { 0x0076, 7 }, { 0x01DC, 9 }, { 0x01DD, 9 }, - { 0x7443, 15 }, { 0x007C, 7 }, { 0x0745, 11 }, { 0x00EF, 8 }, - { 0x00FA, 8 }, { 0x00FB, 8 }, { 0x01F8, 9 }, { 0x00FD, 8 }, - { 0x07E4, 11 }, { 0x0FCA, 12 }, { 0x1D13, 13 }, { 0x7E58, 15 }, - { 0x7E59, 15 }, { 0x7E5A, 15 }, { 0x7E5B, 15 }, { 0x7E5C, 15 }, - { 0x7E5D, 15 }, { 0x007F, 7 }, { 0x3F2F, 14 }, { 0x07E6, 11 }, - { 0x07E7, 11 }, - }, - { // 6 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, - { 0x0009, 5 }, { 0x0014, 6 }, { 0x0015, 6 }, { 0x002C, 7 }, - { 0x005A, 8 }, { 0x005B, 8 }, { 0x005C, 8 }, { 0x00BA, 9 }, - { 0x00BB, 9 }, { 0x00BC, 9 }, { 0x02F4, 11 }, { 0x05EA, 12 }, - { 0x0003, 3 }, { 0x0010, 5 }, { 0x0022, 6 }, { 0x0046, 7 }, - { 0x0009, 4 }, { 0x0028, 6 }, { 0x0015, 5 }, { 0x000B, 4 }, - { 0x0018, 5 }, { 0x0029, 6 }, { 0x0032, 6 }, { 0x0047, 7 }, - { 0x0066, 7 }, { 0x0067, 7 }, { 0x0068, 7 }, { 0x0069, 7 }, - { 0x006A, 7 }, { 0x005F, 8 }, { 0x00D6, 8 }, { 0x00D7, 8 }, - { 0x01B0, 9 }, { 0x00D9, 8 }, { 0x017B, 10 }, { 0x006D, 7 }, - { 0x00DC, 8 }, { 0x01B1, 9 }, { 0x06E8, 11 }, { 0x01BB, 9 }, - { 0x0375, 10 }, { 0x05EB, 12 }, { 0x01BC, 9 }, { 0x6E90, 15 }, - { 0x0038, 6 }, { 0x0072, 7 }, { 0x6E91, 15 }, { 0x6E92, 15 }, - { 0x001D, 5 }, { 0x0073, 7 }, { 0x01BD, 9 }, { 0x06F8, 11 }, - { 0x6E93, 15 }, { 0x003C, 6 }, { 0x01BF, 9 }, { 0x00F4, 8 }, - { 0x01EA, 9 }, { 0x037D, 10 }, { 0x03D6, 10 }, { 0x06F9, 11 }, - { 0x6E94, 15 }, { 0x00F6, 8 }, { 0x01EE, 9 }, { 0x6E95, 15 }, - { 0x6E96, 15 }, { 0x6E97, 15 }, { 0x374C, 14 }, { 0x374D, 14 }, - { 0x374E, 14 }, { 0x001F, 5 }, { 0x03D7, 10 }, { 0x01EF, 9 }, - { 0x374F, 14 }, - }, - { // 7 - { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x0016, 6 }, - { 0x002E, 7 }, { 0x002F, 7 }, { 0x0060, 8 }, { 0x0061, 8 }, - { 0x00C4, 9 }, { 0x00C5, 9 }, { 0x00C6, 9 }, { 0x018E, 10 }, - { 0x31E0, 15 }, { 0x31E1, 15 }, { 0x31E2, 15 }, { 0x31E3, 15 }, - { 0x0004, 3 }, { 0x000D, 5 }, { 0x0019, 6 }, { 0x0038, 7 }, - { 0x000A, 4 }, { 0x001D, 6 }, { 0x000B, 4 }, { 0x0072, 8 }, - { 0x0073, 8 }, { 0x00F0, 9 }, { 0x01E2, 10 }, { 0x00F2, 9 }, - { 0x01E3, 10 }, { 0x00F3, 9 }, { 0x01E8, 10 }, { 0x01E9, 10 }, - { 0x31E4, 15 }, { 0x01EA, 10 }, { 0x031F, 11 }, { 0x03D6, 11 }, - { 0x31E5, 15 }, { 0x01EC, 10 }, { 0x31E6, 15 }, { 0x00F7, 9 }, - { 0x03D7, 11 }, { 0x31E7, 15 }, { 0x31E8, 15 }, { 0x03DA, 11 }, - { 0x03DB, 11 }, { 0x31E9, 15 }, { 0x03E0, 11 }, { 0x31EA, 15 }, - { 0x003F, 7 }, { 0x01F1, 10 }, { 0x31EB, 15 }, { 0x31EC, 15 }, - { 0x0006, 3 }, { 0x001C, 5 }, { 0x0074, 7 }, { 0x0075, 7 }, - { 0x00F9, 9 }, { 0x001E, 5 }, { 0x0076, 7 }, { 0x00FA, 9 }, - { 0x03E1, 11 }, { 0x31ED, 15 }, { 0x18F7, 14 }, { 0x1F60, 14 }, - { 0x1F61, 14 }, { 0x01DC, 9 }, { 0x01DD, 9 }, { 0x1F62, 14 }, - { 0x1F63, 14 }, { 0x1F64, 14 }, { 0x1F65, 14 }, { 0x1F66, 14 }, - { 0x1F67, 14 }, { 0x001F, 5 }, { 0x03ED, 11 }, { 0x00EF, 8 }, - { 0x01F7, 10 }, - }, -}; - -static const uint16_t x8_ac1_highquant_table[8][77][2] = { - { // 0 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0006, 5 }, { 0x0007, 5 }, - { 0x0008, 5 }, { 0x0009, 5 }, { 0x0014, 6 }, { 0x002A, 7 }, - { 0x0016, 6 }, { 0x002B, 7 }, { 0x005C, 8 }, { 0x002F, 7 }, - { 0x0030, 7 }, { 0x005D, 8 }, { 0x0062, 8 }, { 0x00C6, 9 }, - { 0x0007, 4 }, { 0x0019, 6 }, { 0x001A, 6 }, { 0x0036, 7 }, - { 0x0010, 5 }, { 0x006E, 8 }, { 0x0022, 6 }, { 0x0009, 4 }, - { 0x000A, 4 }, { 0x0016, 5 }, { 0x0023, 6 }, { 0x002E, 6 }, - { 0x002F, 6 }, { 0x0030, 6 }, { 0x0062, 7 }, { 0x0063, 7 }, - { 0x0064, 7 }, { 0x0065, 7 }, { 0x0066, 7 }, { 0x0067, 7 }, - { 0x0068, 7 }, { 0x0069, 7 }, { 0x006A, 7 }, { 0x006B, 7 }, - { 0x006C, 7 }, { 0x00C7, 9 }, { 0x00DE, 9 }, { 0x00DF, 9 }, - { 0x06D0, 11 }, { 0x01B5, 9 }, { 0x0037, 6 }, { 0x00DB, 8 }, - { 0x001C, 5 }, { 0x0074, 7 }, { 0x01D4, 9 }, { 0x01D5, 9 }, - { 0x0076, 7 }, { 0x0369, 10 }, { 0x3688, 14 }, { 0x3689, 14 }, - { 0x368A, 14 }, { 0x0077, 7 }, { 0x03AC, 10 }, { 0x0078, 7 }, - { 0x00F2, 8 }, { 0x01D7, 9 }, { 0x00F3, 8 }, { 0x007A, 7 }, - { 0x368B, 14 }, { 0x007B, 7 }, { 0x007C, 7 }, { 0x03AD, 10 }, - { 0x03E8, 10 }, { 0x368C, 14 }, { 0x368D, 14 }, { 0x03E9, 10 }, - { 0x368E, 14 }, { 0x003F, 6 }, { 0x01F5, 9 }, { 0x00FB, 8 }, - { 0x368F, 14 }, - }, - { // 1 - { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x000B, 5 }, - { 0x0018, 6 }, { 0x0032, 7 }, { 0x0033, 7 }, { 0x0034, 7 }, - { 0x006A, 8 }, { 0x00D6, 9 }, { 0x00D7, 9 }, { 0x00D8, 9 }, - { 0x00D9, 9 }, { 0x3680, 15 }, { 0x01B5, 10 }, { 0x0369, 11 }, - { 0x0004, 3 }, { 0x000E, 5 }, { 0x001E, 6 }, { 0x0037, 7 }, - { 0x000A, 4 }, { 0x0016, 5 }, { 0x000C, 4 }, { 0x001F, 6 }, - { 0x005C, 7 }, { 0x005D, 7 }, { 0x00BC, 8 }, { 0x00BD, 8 }, - { 0x005F, 7 }, { 0x00D0, 8 }, { 0x00DB, 9 }, { 0x00D1, 8 }, - { 0x01A4, 9 }, { 0x01A5, 9 }, { 0x01A6, 9 }, { 0x01A7, 9 }, - { 0x0350, 10 }, { 0x06A2, 11 }, { 0x06A3, 11 }, { 0x01A9, 9 }, - { 0x01AA, 9 }, { 0x06AC, 11 }, { 0x3681, 15 }, { 0x0357, 10 }, - { 0x3682, 15 }, { 0x3683, 15 }, { 0x3684, 15 }, { 0x3685, 15 }, - { 0x0036, 6 }, { 0x00D6, 8 }, { 0x3686, 15 }, { 0x3687, 15 }, - { 0x000E, 4 }, { 0x006E, 7 }, { 0x00D7, 8 }, { 0x06AD, 11 }, - { 0x3688, 15 }, { 0x001E, 5 }, { 0x00DE, 8 }, { 0x06F8, 11 }, - { 0x037D, 10 }, { 0x3689, 15 }, { 0x368A, 15 }, { 0x368B, 15 }, - { 0x368C, 15 }, { 0x01BF, 9 }, { 0x368D, 15 }, { 0x1B47, 14 }, - { 0x37C8, 14 }, { 0x37C9, 14 }, { 0x37CA, 14 }, { 0x37CB, 14 }, - { 0x37CC, 14 }, { 0x001F, 5 }, { 0x37CD, 14 }, { 0x37CE, 14 }, - { 0x37CF, 14 }, - }, - { // 2 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, - { 0x0012, 6 }, { 0x0026, 7 }, { 0x0014, 6 }, { 0x0027, 7 }, - { 0x00A8, 9 }, { 0x00A9, 9 }, { 0x0055, 8 }, { 0x2B00, 15 }, - { 0x00AD, 9 }, { 0x2B01, 15 }, { 0x2B02, 15 }, { 0x2B03, 15 }, - { 0x0003, 3 }, { 0x000B, 5 }, { 0x0040, 7 }, { 0x0041, 7 }, - { 0x0009, 4 }, { 0x0021, 6 }, { 0x0011, 5 }, { 0x000A, 4 }, - { 0x000B, 4 }, { 0x0018, 5 }, { 0x0032, 6 }, { 0x0033, 6 }, - { 0x0034, 6 }, { 0x0035, 6 }, { 0x006C, 7 }, { 0x0057, 8 }, - { 0x006D, 7 }, { 0x00DC, 8 }, { 0x0159, 10 }, { 0x00DD, 8 }, - { 0x01BC, 9 }, { 0x037A, 10 }, { 0x037B, 10 }, { 0x0038, 6 }, - { 0x0072, 7 }, { 0x01BE, 9 }, { 0x01BF, 9 }, { 0x00E6, 8 }, - { 0x039C, 10 }, { 0x01CF, 9 }, { 0x2B04, 15 }, { 0x2B05, 15 }, - { 0x0074, 7 }, { 0x01D4, 9 }, { 0x2B06, 15 }, { 0x2B07, 15 }, - { 0x001E, 5 }, { 0x00EB, 8 }, { 0x1584, 14 }, { 0x1585, 14 }, - { 0x1586, 14 }, { 0x003B, 6 }, { 0x01D5, 9 }, { 0x01F0, 9 }, - { 0x039D, 10 }, { 0x03E2, 10 }, { 0x1587, 14 }, { 0x1588, 14 }, - { 0x1589, 14 }, { 0x00F9, 8 }, { 0x158A, 14 }, { 0x158B, 14 }, - { 0x03E3, 10 }, { 0x158C, 14 }, { 0x158D, 14 }, { 0x01F4, 9 }, - { 0x158E, 14 }, { 0x003F, 6 }, { 0x00FB, 8 }, { 0x01F5, 9 }, - { 0x158F, 14 }, - }, - { // 3 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0006, 5 }, { 0x0007, 5 }, - { 0x0010, 6 }, { 0x0011, 6 }, { 0x0024, 7 }, { 0x0025, 7 }, - { 0x0013, 6 }, { 0x0014, 6 }, { 0x002A, 7 }, { 0x002B, 7 }, - { 0x00B0, 9 }, { 0x00B1, 9 }, { 0x002D, 7 }, { 0x0059, 8 }, - { 0x000C, 5 }, { 0x0017, 6 }, { 0x00D0, 9 }, { 0x0035, 7 }, - { 0x001B, 6 }, { 0x0038, 7 }, { 0x0039, 7 }, { 0x0004, 3 }, - { 0x0005, 3 }, { 0x000F, 5 }, { 0x0018, 5 }, { 0x001D, 6 }, - { 0x0032, 6 }, { 0x0033, 6 }, { 0x0068, 7 }, { 0x0069, 7 }, - { 0x0069, 8 }, { 0x00D4, 8 }, { 0x00D5, 8 }, { 0x00D6, 8 }, - { 0x006C, 7 }, { 0x0037, 6 }, { 0x006D, 7 }, { 0x0070, 7 }, - { 0x0039, 6 }, { 0x00D7, 8 }, { 0x00D1, 9 }, { 0x3880, 14 }, - { 0x3881, 14 }, { 0x3882, 14 }, { 0x0074, 7 }, { 0x01C5, 9 }, - { 0x0075, 7 }, { 0x00E3, 8 }, { 0x3883, 14 }, { 0x3884, 14 }, - { 0x00EC, 8 }, { 0x3885, 14 }, { 0x1C43, 13 }, { 0x1C44, 13 }, - { 0x1C45, 13 }, { 0x00ED, 8 }, { 0x1C46, 13 }, { 0x003C, 6 }, - { 0x0077, 7 }, { 0x01E8, 9 }, { 0x003E, 6 }, { 0x007B, 7 }, - { 0x1C47, 13 }, { 0x007E, 7 }, { 0x007F, 7 }, { 0x1C48, 13 }, - { 0x1C49, 13 }, { 0x1C4A, 13 }, { 0x1C4B, 13 }, { 0x1C4C, 13 }, - { 0x1C4D, 13 }, { 0x00F5, 8 }, { 0x1C4E, 13 }, { 0x01E9, 9 }, - { 0x1C4F, 13 }, - }, - { // 4 - { 0x0000, 2 }, { 0x0004, 4 }, { 0x000A, 5 }, { 0x000B, 5 }, - { 0x0018, 6 }, { 0x0019, 6 }, { 0x0034, 7 }, { 0x0035, 7 }, - { 0x0036, 7 }, { 0x006E, 8 }, { 0x00DE, 9 }, { 0x00DF, 9 }, - { 0x01C0, 10 }, { 0x01C1, 10 }, { 0x01C2, 10 }, { 0x3860, 15 }, - { 0x0004, 3 }, { 0x000F, 5 }, { 0x001D, 6 }, { 0x0039, 7 }, - { 0x000A, 4 }, { 0x002C, 6 }, { 0x002D, 6 }, { 0x000C, 4 }, - { 0x0017, 5 }, { 0x0034, 6 }, { 0x0035, 6 }, { 0x0036, 6 }, - { 0x006E, 7 }, { 0x006F, 7 }, { 0x0070, 7 }, { 0x0071, 7 }, - { 0x0071, 8 }, { 0x00E4, 8 }, { 0x00E5, 8 }, { 0x00E6, 8 }, - { 0x00E7, 8 }, { 0x00E8, 8 }, { 0x03A4, 10 }, { 0x0075, 7 }, - { 0x00EC, 8 }, { 0x01D3, 9 }, { 0x01DA, 9 }, { 0x03A5, 10 }, - { 0x03B6, 10 }, { 0x070D, 12 }, { 0x03B7, 10 }, { 0x070E, 12 }, - { 0x003C, 6 }, { 0x00EE, 8 }, { 0x3861, 15 }, { 0x3862, 15 }, - { 0x003D, 6 }, { 0x01DE, 9 }, { 0x3863, 15 }, { 0x3864, 15 }, - { 0x3865, 15 }, { 0x007C, 7 }, { 0x070F, 12 }, { 0x03BE, 10 }, - { 0x03BF, 10 }, { 0x3866, 15 }, { 0x0FA0, 12 }, { 0x07D1, 11 }, - { 0x3867, 15 }, { 0x00FB, 8 }, { 0x01F5, 9 }, { 0x7D08, 15 }, - { 0x0FA4, 12 }, { 0x7D09, 15 }, { 0x7D0A, 15 }, { 0x7D0B, 15 }, - { 0x3E86, 14 }, { 0x003F, 6 }, { 0x0FA5, 12 }, { 0x07D3, 11 }, - { 0x3E87, 14 }, - }, - { // 5 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, - { 0x0009, 5 }, { 0x0014, 6 }, { 0x002A, 7 }, { 0x0056, 8 }, - { 0x02B8, 11 }, { 0x00AF, 9 }, { 0x02B9, 11 }, { 0x015D, 10 }, - { 0x02C0, 11 }, { 0x2C10, 15 }, { 0x2C11, 15 }, { 0x2C12, 15 }, - { 0x0006, 4 }, { 0x000E, 5 }, { 0x0017, 6 }, { 0x002D, 7 }, - { 0x000F, 5 }, { 0x0040, 7 }, { 0x0021, 6 }, { 0x0005, 3 }, - { 0x0009, 4 }, { 0x0011, 5 }, { 0x0018, 5 }, { 0x0019, 5 }, - { 0x001A, 5 }, { 0x0036, 6 }, { 0x0037, 6 }, { 0x0041, 7 }, - { 0x0059, 8 }, { 0x00E0, 8 }, { 0x00E1, 8 }, { 0x0071, 7 }, - { 0x00E4, 8 }, { 0x00B1, 9 }, { 0x02C2, 11 }, { 0x001D, 5 }, - { 0x0073, 7 }, { 0x00E5, 8 }, { 0x00F0, 8 }, { 0x0079, 7 }, - { 0x03C4, 10 }, { 0x01E3, 9 }, { 0x01E8, 9 }, { 0x2C13, 15 }, - { 0x007B, 7 }, { 0x2C14, 15 }, { 0x2C15, 15 }, { 0x2C16, 15 }, - { 0x007C, 7 }, { 0x02C3, 11 }, { 0x2C17, 15 }, { 0x160C, 14 }, - { 0x160D, 14 }, { 0x007D, 7 }, { 0x160E, 14 }, { 0x01E9, 9 }, - { 0x03C5, 10 }, { 0x03D4, 10 }, { 0x01EB, 9 }, { 0x160F, 14 }, - { 0x3D50, 14 }, { 0x00FC, 8 }, { 0x07AB, 11 }, { 0x3D51, 14 }, - { 0x3D52, 14 }, { 0x3D53, 14 }, { 0x3D54, 14 }, { 0x01FA, 9 }, - { 0x3D55, 14 }, { 0x007F, 7 }, { 0x01FB, 9 }, { 0x3D56, 14 }, - { 0x3D57, 14 }, - }, - { // 6 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0008, 5 }, - { 0x0009, 5 }, { 0x000A, 5 }, { 0x000B, 5 }, { 0x0018, 6 }, - { 0x0032, 7 }, { 0x000D, 5 }, { 0x0033, 7 }, { 0x0E00, 13 }, - { 0x0039, 7 }, { 0x0E01, 13 }, { 0x003A, 7 }, { 0x0E02, 13 }, - { 0x0008, 4 }, { 0x001E, 6 }, { 0x003B, 7 }, { 0x003E, 7 }, - { 0x0012, 5 }, { 0x003F, 7 }, { 0x0013, 5 }, { 0x0028, 6 }, - { 0x0029, 6 }, { 0x0054, 7 }, { 0x002B, 6 }, { 0x0055, 7 }, - { 0x0058, 7 }, { 0x0E03, 13 }, { 0x0059, 7 }, { 0x005A, 7 }, - { 0x0E04, 13 }, { 0x0E05, 13 }, { 0x0703, 12 }, { 0x005B, 7 }, - { 0x005C, 7 }, { 0x0704, 12 }, { 0x0705, 12 }, { 0x005D, 7 }, - { 0x0706, 12 }, { 0x0707, 12 }, { 0x0708, 12 }, { 0x0709, 12 }, - { 0x070A, 12 }, { 0x070B, 12 }, { 0x0018, 5 }, { 0x002F, 6 }, - { 0x000D, 4 }, { 0x0019, 5 }, { 0x070C, 12 }, { 0x0070, 7 }, - { 0x001D, 5 }, { 0x070D, 12 }, { 0x070E, 12 }, { 0x070F, 12 }, - { 0x0710, 12 }, { 0x0039, 6 }, { 0x0711, 12 }, { 0x003C, 6 }, - { 0x0712, 12 }, { 0x0713, 12 }, { 0x0714, 12 }, { 0x0715, 12 }, - { 0x0716, 12 }, { 0x003D, 6 }, { 0x0717, 12 }, { 0x0718, 12 }, - { 0x0719, 12 }, { 0x071A, 12 }, { 0x071B, 12 }, { 0x071C, 12 }, - { 0x071D, 12 }, { 0x001F, 5 }, { 0x071E, 12 }, { 0x0071, 7 }, - { 0x071F, 12 }, - }, - { // 7 - { 0x0000, 3 }, { 0x0002, 4 }, { 0x0006, 5 }, { 0x000E, 6 }, - { 0x000F, 6 }, { 0x0040, 8 }, { 0x0041, 8 }, { 0x0042, 8 }, - { 0x0218, 11 }, { 0x2190, 15 }, { 0x2191, 15 }, { 0x2192, 15 }, - { 0x2193, 15 }, { 0x2194, 15 }, { 0x2195, 15 }, { 0x2196, 15 }, - { 0x0005, 4 }, { 0x0011, 6 }, { 0x0024, 7 }, { 0x0087, 9 }, - { 0x000C, 5 }, { 0x004A, 8 }, { 0x004B, 8 }, { 0x0002, 2 }, - { 0x0006, 3 }, { 0x000D, 5 }, { 0x000E, 5 }, { 0x000F, 5 }, - { 0x0013, 6 }, { 0x0038, 6 }, { 0x00E4, 8 }, { 0x00E5, 8 }, - { 0x01CC, 9 }, { 0x00E7, 8 }, { 0x0074, 7 }, { 0x00EA, 8 }, - { 0x01CD, 9 }, { 0x021A, 11 }, { 0x2197, 15 }, { 0x001E, 5 }, - { 0x0076, 7 }, { 0x00EB, 8 }, { 0x01DC, 9 }, { 0x00EF, 8 }, - { 0x01DD, 9 }, { 0x01F0, 9 }, { 0x2198, 15 }, { 0x2199, 15 }, - { 0x00F9, 8 }, { 0x03E2, 10 }, { 0x219A, 15 }, { 0x219B, 15 }, - { 0x00FA, 8 }, { 0x219C, 15 }, { 0x219D, 15 }, { 0x219E, 15 }, - { 0x219F, 15 }, { 0x01F6, 9 }, { 0x21B0, 15 }, { 0x00FC, 8 }, - { 0x01F7, 9 }, { 0x21B1, 15 }, { 0x21B2, 15 }, { 0x21B3, 15 }, - { 0x21B4, 15 }, { 0x01FA, 9 }, { 0x21B5, 15 }, { 0x21B6, 15 }, - { 0x21B7, 15 }, { 0x21B8, 15 }, { 0x21B9, 15 }, { 0x03E3, 10 }, - { 0x10DD, 14 }, { 0x007F, 7 }, { 0x01FB, 9 }, { 0x10DE, 14 }, - { 0x10DF, 14 }, +static const uint8_t x8_ac_quant_table[2][2][8][77][2] = { + { + { + { /* AC highquant table group 0, table 0 */ + { 0, 3 }, { 1, 4 }, { 2, 6 }, { 3, 6 }, { 4, 7 }, + { 6, 15 }, { 8, 15 }, { 10, 15 }, { 12, 15 }, { 13, 15 }, + { 14, 15 }, { 15, 14 }, { 34, 14 }, { 45, 14 }, { 46, 14 }, + { 47, 14 }, { 49, 14 }, { 50, 14 }, { 51, 14 }, { 52, 14 }, + { 53, 14 }, { 54, 14 }, { 55, 14 }, { 56, 14 }, { 57, 14 }, + { 58, 14 }, { 60, 14 }, { 61, 14 }, { 62, 14 }, { 63, 14 }, + { 64, 14 }, { 65, 14 }, { 67, 14 }, { 69, 14 }, { 70, 14 }, + { 71, 14 }, { 72, 14 }, { 74, 14 }, { 75, 14 }, { 76, 14 }, + { 9, 9 }, { 7, 8 }, { 5, 6 }, { 11, 9 }, { 18, 9 }, + { 19, 9 }, { 22, 9 }, { 20, 7 }, { 17, 6 }, { 16, 5 }, + { 21, 7 }, { 29, 8 }, { 33, 8 }, { 28, 6 }, { 27, 5 }, + { 24, 3 }, { 23, 2 }, { 25, 4 }, { 26, 4 }, { 30, 7 }, + { 32, 7 }, { 31, 6 }, { 35, 7 }, { 36, 7 }, { 37, 7 }, + { 38, 9 }, { 41, 9 }, { 42, 8 }, { 39, 5 }, { 40, 6 }, + { 43, 9 }, { 44, 9 }, { 48, 8 }, { 59, 9 }, { 66, 9 }, + { 68, 9 }, { 73, 9 }, + }, + { /* AC highquant table group 0, table 1 */ + { 0, 3 }, { 1, 4 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, + { 5, 6 }, { 6, 6 }, { 7, 6 }, { 8, 7 }, { 9, 8 }, + { 10, 8 }, { 11, 8 }, { 12, 8 }, { 13, 14 }, { 44, 14 }, + { 47, 14 }, { 50, 14 }, { 51, 14 }, { 54, 14 }, { 55, 14 }, + { 56, 14 }, { 63, 14 }, { 64, 14 }, { 67, 14 }, { 68, 14 }, + { 69, 14 }, { 70, 14 }, { 72, 14 }, { 76, 14 }, { 14, 10 }, + { 15, 10 }, { 45, 10 }, { 32, 8 }, { 16, 4 }, { 17, 5 }, + { 18, 6 }, { 19, 7 }, { 31, 7 }, { 20, 5 }, { 21, 6 }, + { 26, 6 }, { 22, 5 }, { 24, 5 }, { 23, 4 }, { 25, 5 }, + { 27, 6 }, { 28, 6 }, { 29, 6 }, { 30, 6 }, { 33, 8 }, + { 38, 8 }, { 34, 7 }, { 35, 7 }, { 36, 7 }, { 37, 7 }, + { 39, 7 }, { 40, 7 }, { 41, 8 }, { 42, 8 }, { 43, 8 }, + { 46, 9 }, { 49, 9 }, { 53, 8 }, { 58, 8 }, { 57, 6 }, + { 48, 5 }, { 52, 5 }, { 59, 7 }, { 60, 8 }, { 61, 9 }, + { 66, 9 }, { 62, 8 }, { 65, 8 }, { 71, 9 }, { 75, 9 }, + { 74, 8 }, { 73, 5 }, + }, + { /* AC highquant table group 0, table 2 */ + { 0, 4 }, { 1, 5 }, { 2, 12 }, { 3, 12 }, { 4, 12 }, + { 5, 12 }, { 6, 12 }, { 7, 12 }, { 8, 12 }, { 9, 12 }, + { 10, 12 }, { 11, 12 }, { 12, 11 }, { 13, 11 }, { 14, 11 }, + { 15, 11 }, { 16, 11 }, { 17, 11 }, { 18, 11 }, { 19, 11 }, + { 20, 11 }, { 21, 11 }, { 22, 11 }, { 28, 11 }, { 29, 11 }, + { 30, 11 }, { 31, 11 }, { 32, 11 }, { 33, 11 }, { 34, 11 }, + { 35, 11 }, { 36, 11 }, { 37, 11 }, { 38, 11 }, { 40, 11 }, + { 41, 11 }, { 42, 11 }, { 43, 11 }, { 44, 11 }, { 45, 11 }, + { 46, 11 }, { 47, 11 }, { 48, 11 }, { 49, 11 }, { 50, 11 }, + { 51, 11 }, { 52, 11 }, { 53, 11 }, { 54, 11 }, { 55, 11 }, + { 56, 11 }, { 57, 11 }, { 58, 11 }, { 59, 11 }, { 60, 11 }, + { 61, 11 }, { 62, 11 }, { 63, 11 }, { 64, 11 }, { 65, 11 }, + { 66, 11 }, { 67, 11 }, { 68, 11 }, { 69, 11 }, { 70, 11 }, + { 71, 11 }, { 72, 11 }, { 73, 11 }, { 74, 11 }, { 75, 11 }, + { 76, 11 }, { 25, 5 }, { 26, 5 }, { 27, 5 }, { 39, 5 }, + { 24, 2 }, { 23, 1 }, + }, + { /* AC highquant table group 0, table 3 */ + { 0, 8 }, { 1, 8 }, { 2, 8 }, { 3, 8 }, { 4, 8 }, + { 5, 8 }, { 6, 8 }, { 7, 8 }, { 8, 8 }, { 9, 8 }, + { 10, 8 }, { 11, 8 }, { 12, 8 }, { 13, 8 }, { 14, 8 }, + { 15, 8 }, { 16, 8 }, { 17, 8 }, { 18, 8 }, { 19, 8 }, + { 20, 8 }, { 21, 8 }, { 22, 8 }, { 24, 8 }, { 25, 7 }, + { 26, 7 }, { 27, 7 }, { 28, 7 }, { 29, 7 }, { 30, 7 }, + { 31, 7 }, { 32, 7 }, { 33, 7 }, { 34, 7 }, { 35, 7 }, + { 36, 7 }, { 37, 7 }, { 38, 7 }, { 39, 7 }, { 40, 7 }, + { 41, 7 }, { 42, 7 }, { 43, 7 }, { 44, 7 }, { 45, 7 }, + { 46, 7 }, { 47, 7 }, { 48, 7 }, { 49, 7 }, { 50, 7 }, + { 51, 7 }, { 52, 7 }, { 53, 7 }, { 54, 7 }, { 55, 7 }, + { 56, 7 }, { 57, 7 }, { 58, 7 }, { 59, 7 }, { 60, 7 }, + { 61, 7 }, { 62, 7 }, { 63, 7 }, { 64, 7 }, { 65, 7 }, + { 66, 7 }, { 67, 7 }, { 68, 7 }, { 69, 7 }, { 70, 7 }, + { 71, 7 }, { 72, 7 }, { 73, 7 }, { 74, 7 }, { 75, 7 }, + { 76, 7 }, { 23, 1 }, + }, + { /* AC highquant table group 0, table 4 */ + { 0, 9 }, { 1, 9 }, { 2, 9 }, { 3, 9 }, { 4, 9 }, + { 5, 9 }, { 6, 9 }, { 7, 9 }, { 8, 9 }, { 9, 9 }, + { 10, 9 }, { 11, 9 }, { 12, 9 }, { 13, 9 }, { 14, 9 }, + { 15, 9 }, { 16, 9 }, { 17, 9 }, { 18, 9 }, { 19, 9 }, + { 20, 9 }, { 21, 9 }, { 22, 8 }, { 25, 8 }, { 26, 8 }, + { 27, 8 }, { 28, 8 }, { 29, 8 }, { 30, 8 }, { 31, 8 }, + { 32, 8 }, { 33, 8 }, { 34, 8 }, { 35, 8 }, { 36, 8 }, + { 37, 8 }, { 38, 8 }, { 39, 8 }, { 40, 8 }, { 41, 8 }, + { 42, 8 }, { 43, 8 }, { 44, 8 }, { 45, 8 }, { 46, 8 }, + { 47, 8 }, { 48, 8 }, { 49, 8 }, { 50, 8 }, { 51, 8 }, + { 52, 8 }, { 53, 8 }, { 54, 8 }, { 55, 8 }, { 56, 8 }, + { 57, 8 }, { 58, 8 }, { 59, 8 }, { 60, 8 }, { 61, 8 }, + { 62, 8 }, { 63, 8 }, { 64, 8 }, { 65, 8 }, { 66, 8 }, + { 67, 8 }, { 68, 8 }, { 69, 8 }, { 70, 8 }, { 71, 8 }, + { 72, 8 }, { 73, 8 }, { 74, 8 }, { 75, 8 }, { 76, 8 }, + { 23, 2 }, { 24, 1 }, + }, + { /* AC highquant table group 0, table 5 */ + { 0, 10 }, { 1, 10 }, { 2, 10 }, { 3, 10 }, { 4, 10 }, + { 5, 10 }, { 6, 10 }, { 7, 10 }, { 8, 10 }, { 9, 10 }, + { 10, 10 }, { 11, 10 }, { 12, 10 }, { 13, 10 }, { 14, 10 }, + { 15, 10 }, { 16, 10 }, { 17, 10 }, { 18, 10 }, { 19, 10 }, + { 20, 9 }, { 21, 9 }, { 22, 9 }, { 25, 9 }, { 26, 9 }, + { 28, 9 }, { 29, 9 }, { 30, 9 }, { 31, 9 }, { 32, 9 }, + { 33, 9 }, { 34, 9 }, { 35, 9 }, { 36, 9 }, { 37, 9 }, + { 38, 9 }, { 39, 9 }, { 40, 9 }, { 41, 9 }, { 42, 9 }, + { 43, 9 }, { 44, 9 }, { 45, 9 }, { 46, 9 }, { 47, 9 }, + { 48, 9 }, { 49, 9 }, { 50, 9 }, { 51, 9 }, { 52, 9 }, + { 53, 9 }, { 54, 9 }, { 55, 9 }, { 56, 9 }, { 57, 9 }, + { 58, 9 }, { 59, 9 }, { 60, 9 }, { 61, 9 }, { 62, 9 }, + { 63, 9 }, { 64, 9 }, { 65, 9 }, { 66, 9 }, { 67, 9 }, + { 68, 9 }, { 69, 9 }, { 70, 9 }, { 71, 9 }, { 72, 9 }, + { 73, 9 }, { 74, 9 }, { 75, 9 }, { 76, 9 }, { 24, 3 }, + { 27, 2 }, { 23, 1 }, + }, + { /* AC highquant table group 0, table 6 */ + { 0, 2 }, { 1, 4 }, { 2, 5 }, { 3, 5 }, { 4, 6 }, + { 5, 6 }, { 6, 7 }, { 7, 8 }, { 8, 8 }, { 9, 8 }, + { 10, 9 }, { 11, 9 }, { 12, 10 }, { 14, 10 }, { 13, 9 }, + { 15, 15 }, { 42, 15 }, { 46, 15 }, { 50, 15 }, { 51, 15 }, + { 55, 15 }, { 56, 14 }, { 59, 14 }, { 61, 14 }, { 62, 14 }, + { 63, 14 }, { 64, 14 }, { 68, 14 }, { 69, 14 }, { 70, 14 }, + { 71, 14 }, { 72, 14 }, { 75, 14 }, { 76, 14 }, { 43, 10 }, + { 37, 9 }, { 17, 5 }, { 18, 6 }, { 19, 6 }, { 16, 3 }, + { 20, 4 }, { 21, 7 }, { 24, 7 }, { 25, 7 }, { 26, 7 }, + { 22, 5 }, { 23, 5 }, { 27, 8 }, { 30, 8 }, { 28, 7 }, + { 29, 7 }, { 31, 8 }, { 32, 8 }, { 33, 8 }, { 34, 8 }, + { 35, 8 }, { 36, 8 }, { 38, 8 }, { 39, 8 }, { 40, 8 }, + { 41, 9 }, { 44, 10 }, { 45, 10 }, { 47, 10 }, { 54, 10 }, + { 49, 9 }, { 58, 8 }, { 60, 10 }, { 66, 10 }, { 67, 10 }, + { 74, 10 }, { 65, 8 }, { 48, 6 }, { 52, 4 }, { 53, 6 }, + { 57, 6 }, { 73, 5 }, + }, + { /* AC highquant table group 0, table 7 */ + { 0, 3 }, { 1, 4 }, { 2, 5 }, { 3, 5 }, { 4, 6 }, + { 5, 8 }, { 9, 13 }, { 12, 13 }, { 13, 13 }, { 14, 13 }, + { 42, 13 }, { 45, 13 }, { 46, 13 }, { 47, 13 }, { 50, 13 }, + { 51, 13 }, { 53, 13 }, { 54, 13 }, { 55, 13 }, { 56, 13 }, + { 58, 13 }, { 61, 13 }, { 62, 13 }, { 63, 13 }, { 64, 13 }, + { 66, 13 }, { 67, 13 }, { 68, 13 }, { 69, 13 }, { 70, 13 }, + { 72, 12 }, { 74, 12 }, { 75, 12 }, { 76, 12 }, { 6, 7 }, + { 7, 6 }, { 8, 7 }, { 10, 8 }, { 11, 8 }, { 15, 8 }, + { 31, 8 }, { 18, 7 }, { 19, 6 }, { 17, 5 }, { 16, 4 }, + { 20, 6 }, { 21, 7 }, { 36, 8 }, { 37, 8 }, { 22, 6 }, + { 27, 6 }, { 23, 3 }, { 24, 5 }, { 25, 5 }, { 26, 4 }, + { 28, 6 }, { 29, 6 }, { 30, 5 }, { 32, 6 }, { 33, 6 }, + { 34, 6 }, { 35, 6 }, { 38, 7 }, { 40, 7 }, { 41, 7 }, + { 43, 7 }, { 39, 5 }, { 44, 8 }, { 52, 8 }, { 48, 7 }, + { 49, 7 }, { 57, 8 }, { 60, 8 }, { 59, 7 }, { 65, 8 }, + { 71, 8 }, { 73, 6 }, + }, + }, + { + { /* AC highquant table group 1, table 0 */ + { 0, 3 }, { 1, 4 }, { 2, 5 }, { 3, 5 }, { 4, 5 }, + { 5, 5 }, { 6, 6 }, { 7, 7 }, { 9, 7 }, { 8, 6 }, + { 10, 8 }, { 13, 8 }, { 11, 7 }, { 12, 7 }, { 14, 8 }, + { 15, 9 }, { 41, 9 }, { 17, 6 }, { 18, 6 }, { 19, 7 }, + { 21, 8 }, { 42, 9 }, { 43, 9 }, { 16, 4 }, { 20, 5 }, + { 22, 6 }, { 26, 6 }, { 23, 4 }, { 24, 4 }, { 25, 5 }, + { 27, 6 }, { 28, 6 }, { 29, 6 }, { 30, 7 }, { 31, 7 }, + { 32, 7 }, { 33, 7 }, { 34, 7 }, { 35, 7 }, { 36, 7 }, + { 37, 7 }, { 38, 7 }, { 39, 7 }, { 40, 7 }, { 44, 11 }, + { 54, 14 }, { 55, 14 }, { 56, 14 }, { 64, 14 }, { 69, 14 }, + { 70, 14 }, { 72, 14 }, { 76, 14 }, { 53, 10 }, { 45, 9 }, + { 47, 8 }, { 46, 6 }, { 48, 5 }, { 49, 7 }, { 50, 9 }, + { 51, 9 }, { 58, 10 }, { 67, 10 }, { 61, 9 }, { 52, 7 }, + { 57, 7 }, { 59, 7 }, { 60, 8 }, { 62, 8 }, { 63, 7 }, + { 65, 7 }, { 66, 7 }, { 68, 10 }, { 71, 10 }, { 74, 9 }, + { 75, 8 }, { 73, 6 }, + }, + { /* AC highquant table group 1, table 1 */ + { 0, 2 }, { 1, 4 }, { 2, 5 }, { 3, 5 }, { 4, 6 }, + { 5, 7 }, { 6, 7 }, { 7, 7 }, { 8, 8 }, { 9, 9 }, + { 10, 9 }, { 11, 9 }, { 12, 9 }, { 13, 15 }, { 42, 15 }, + { 44, 15 }, { 45, 15 }, { 46, 15 }, { 47, 15 }, { 50, 15 }, + { 51, 15 }, { 56, 15 }, { 61, 15 }, { 62, 15 }, { 63, 15 }, + { 64, 15 }, { 66, 15 }, { 67, 14 }, { 15, 11 }, { 14, 10 }, + { 30, 9 }, { 19, 7 }, { 17, 5 }, { 18, 6 }, { 23, 6 }, + { 16, 3 }, { 20, 4 }, { 21, 5 }, { 24, 7 }, { 25, 7 }, + { 26, 8 }, { 27, 8 }, { 28, 7 }, { 22, 4 }, { 29, 8 }, + { 31, 8 }, { 32, 9 }, { 33, 9 }, { 34, 9 }, { 35, 9 }, + { 36, 10 }, { 37, 11 }, { 38, 11 }, { 39, 9 }, { 40, 9 }, + { 41, 11 }, { 55, 11 }, { 43, 10 }, { 49, 8 }, { 54, 8 }, + { 48, 6 }, { 53, 7 }, { 58, 8 }, { 59, 11 }, { 68, 14 }, + { 69, 14 }, { 70, 14 }, { 71, 14 }, { 72, 14 }, { 74, 14 }, + { 75, 14 }, { 76, 14 }, { 60, 10 }, { 65, 9 }, { 52, 4 }, + { 57, 5 }, { 73, 5 }, + }, + { /* AC highquant table group 1, table 2 */ + { 0, 3 }, { 1, 4 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, + { 5, 7 }, { 7, 7 }, { 6, 6 }, { 8, 9 }, { 9, 9 }, + { 10, 8 }, { 11, 15 }, { 13, 15 }, { 14, 15 }, { 15, 15 }, + { 46, 15 }, { 47, 15 }, { 50, 15 }, { 51, 15 }, { 54, 14 }, + { 55, 14 }, { 56, 14 }, { 62, 14 }, { 63, 14 }, { 64, 14 }, + { 66, 14 }, { 67, 14 }, { 69, 14 }, { 70, 14 }, { 72, 14 }, + { 76, 14 }, { 34, 10 }, { 12, 9 }, { 31, 8 }, { 17, 5 }, + { 16, 3 }, { 18, 7 }, { 19, 7 }, { 21, 6 }, { 22, 5 }, + { 20, 4 }, { 23, 4 }, { 24, 4 }, { 25, 5 }, { 26, 6 }, + { 27, 6 }, { 28, 6 }, { 29, 6 }, { 30, 7 }, { 32, 7 }, + { 33, 8 }, { 35, 8 }, { 36, 9 }, { 37, 10 }, { 38, 10 }, + { 41, 9 }, { 42, 9 }, { 39, 6 }, { 40, 7 }, { 43, 8 }, + { 44, 10 }, { 60, 10 }, { 45, 9 }, { 48, 7 }, { 49, 9 }, + { 58, 9 }, { 53, 8 }, { 57, 6 }, { 52, 5 }, { 59, 9 }, + { 61, 10 }, { 68, 10 }, { 65, 8 }, { 71, 9 }, { 75, 9 }, + { 74, 8 }, { 73, 6 }, + }, + { /* AC highquant table group 1, table 3 */ + { 0, 3 }, { 1, 4 }, { 2, 5 }, { 3, 5 }, { 4, 6 }, + { 5, 6 }, { 6, 7 }, { 7, 7 }, { 8, 6 }, { 9, 6 }, + { 10, 7 }, { 11, 7 }, { 12, 9 }, { 13, 9 }, { 15, 8 }, + { 14, 7 }, { 17, 6 }, { 16, 5 }, { 18, 9 }, { 42, 9 }, + { 32, 8 }, { 19, 7 }, { 20, 6 }, { 21, 7 }, { 22, 7 }, + { 27, 6 }, { 25, 5 }, { 23, 3 }, { 24, 3 }, { 26, 5 }, + { 28, 6 }, { 29, 6 }, { 30, 7 }, { 31, 7 }, { 33, 8 }, + { 34, 8 }, { 35, 8 }, { 41, 8 }, { 36, 7 }, { 38, 7 }, + { 37, 6 }, { 39, 7 }, { 43, 14 }, { 44, 14 }, { 45, 14 }, + { 50, 14 }, { 51, 14 }, { 53, 14 }, { 54, 13 }, { 55, 13 }, + { 56, 13 }, { 58, 13 }, { 64, 13 }, { 67, 13 }, { 68, 13 }, + { 69, 13 }, { 70, 13 }, { 71, 13 }, { 72, 13 }, { 74, 13 }, + { 76, 13 }, { 47, 9 }, { 49, 8 }, { 40, 6 }, { 46, 7 }, + { 48, 7 }, { 52, 8 }, { 57, 8 }, { 60, 7 }, { 59, 6 }, + { 61, 9 }, { 75, 9 }, { 73, 8 }, { 63, 7 }, { 62, 6 }, + { 65, 7 }, { 66, 7 }, + }, + { /* AC highquant table group 1, table 4 */ + { 0, 2 }, { 1, 4 }, { 2, 5 }, { 3, 5 }, { 4, 6 }, + { 5, 6 }, { 6, 7 }, { 7, 7 }, { 8, 7 }, { 9, 8 }, + { 10, 9 }, { 11, 9 }, { 12, 10 }, { 13, 10 }, { 14, 10 }, + { 15, 15 }, { 50, 15 }, { 51, 15 }, { 54, 15 }, { 55, 15 }, + { 56, 15 }, { 61, 15 }, { 64, 15 }, { 45, 12 }, { 47, 12 }, + { 58, 12 }, { 32, 8 }, { 19, 7 }, { 18, 6 }, { 17, 5 }, + { 16, 3 }, { 20, 4 }, { 21, 6 }, { 22, 6 }, { 24, 5 }, + { 23, 4 }, { 25, 6 }, { 26, 6 }, { 27, 6 }, { 28, 7 }, + { 29, 7 }, { 30, 7 }, { 31, 7 }, { 33, 8 }, { 34, 8 }, + { 35, 8 }, { 36, 8 }, { 37, 8 }, { 38, 10 }, { 43, 10 }, + { 41, 9 }, { 39, 7 }, { 40, 8 }, { 42, 9 }, { 44, 10 }, + { 46, 10 }, { 49, 8 }, { 53, 9 }, { 59, 10 }, { 60, 10 }, + { 48, 6 }, { 52, 6 }, { 57, 7 }, { 62, 12 }, { 67, 15 }, + { 69, 15 }, { 70, 15 }, { 71, 15 }, { 72, 14 }, { 76, 14 }, + { 63, 11 }, { 68, 12 }, { 74, 12 }, { 75, 11 }, { 66, 9 }, + { 65, 8 }, { 73, 6 }, + }, + { /* AC highquant table group 1, table 5 */ + { 0, 3 }, { 1, 4 }, { 2, 4 }, { 3, 5 }, { 4, 5 }, + { 5, 6 }, { 6, 7 }, { 7, 8 }, { 8, 11 }, { 10, 11 }, + { 11, 10 }, { 9, 9 }, { 12, 11 }, { 13, 15 }, { 14, 15 }, + { 15, 15 }, { 47, 15 }, { 49, 15 }, { 50, 15 }, { 51, 15 }, + { 54, 15 }, { 55, 14 }, { 56, 14 }, { 58, 14 }, { 63, 14 }, + { 38, 11 }, { 53, 11 }, { 37, 9 }, { 32, 8 }, { 19, 7 }, + { 18, 6 }, { 16, 4 }, { 17, 5 }, { 20, 5 }, { 21, 7 }, + { 31, 7 }, { 22, 6 }, { 25, 5 }, { 24, 4 }, { 23, 3 }, + { 26, 5 }, { 27, 5 }, { 28, 5 }, { 29, 6 }, { 30, 6 }, + { 33, 8 }, { 34, 8 }, { 35, 7 }, { 36, 8 }, { 41, 8 }, + { 40, 7 }, { 39, 5 }, { 42, 8 }, { 44, 10 }, { 60, 10 }, + { 45, 9 }, { 43, 7 }, { 46, 9 }, { 59, 9 }, { 61, 10 }, + { 64, 14 }, { 67, 14 }, { 68, 14 }, { 69, 14 }, { 70, 14 }, + { 72, 14 }, { 75, 14 }, { 76, 14 }, { 66, 11 }, { 62, 9 }, + { 48, 7 }, { 52, 7 }, { 57, 7 }, { 65, 8 }, { 71, 9 }, + { 74, 9 }, { 73, 7 }, + }, + { /* AC highquant table group 1, table 6 */ + { 0, 3 }, { 1, 4 }, { 2, 4 }, { 3, 5 }, { 4, 5 }, + { 5, 5 }, { 6, 5 }, { 7, 6 }, { 8, 7 }, { 10, 7 }, + { 9, 5 }, { 11, 13 }, { 13, 13 }, { 15, 13 }, { 29, 13 }, + { 32, 13 }, { 33, 13 }, { 34, 12 }, { 37, 12 }, { 38, 12 }, + { 40, 12 }, { 41, 12 }, { 42, 12 }, { 43, 12 }, { 44, 12 }, + { 45, 12 }, { 50, 12 }, { 53, 12 }, { 54, 12 }, { 55, 12 }, + { 56, 12 }, { 58, 12 }, { 60, 12 }, { 61, 12 }, { 62, 12 }, + { 63, 12 }, { 64, 12 }, { 66, 12 }, { 67, 12 }, { 68, 12 }, + { 69, 12 }, { 70, 12 }, { 71, 12 }, { 72, 12 }, { 74, 12 }, + { 76, 12 }, { 12, 7 }, { 14, 7 }, { 18, 7 }, { 17, 6 }, + { 19, 7 }, { 21, 7 }, { 16, 4 }, { 20, 5 }, { 22, 5 }, + { 23, 6 }, { 24, 6 }, { 25, 7 }, { 27, 7 }, { 26, 6 }, + { 28, 7 }, { 30, 7 }, { 31, 7 }, { 35, 7 }, { 36, 7 }, + { 39, 7 }, { 47, 6 }, { 46, 5 }, { 49, 5 }, { 48, 4 }, + { 51, 7 }, { 75, 7 }, { 57, 6 }, { 52, 5 }, { 59, 6 }, + { 65, 6 }, { 73, 5 }, + }, + { /* AC highquant table group 1, table 7 */ + { 0, 3 }, { 1, 4 }, { 2, 5 }, { 3, 6 }, { 4, 6 }, + { 5, 8 }, { 6, 8 }, { 7, 8 }, { 8, 11 }, { 9, 15 }, + { 10, 15 }, { 11, 15 }, { 12, 15 }, { 13, 15 }, { 14, 15 }, + { 15, 15 }, { 38, 15 }, { 46, 15 }, { 47, 15 }, { 50, 15 }, + { 51, 15 }, { 53, 15 }, { 54, 15 }, { 55, 15 }, { 56, 15 }, + { 37, 11 }, { 58, 15 }, { 61, 15 }, { 62, 15 }, { 63, 15 }, + { 64, 15 }, { 66, 15 }, { 67, 15 }, { 68, 15 }, { 69, 15 }, + { 70, 15 }, { 72, 14 }, { 75, 14 }, { 76, 14 }, { 19, 9 }, + { 17, 6 }, { 18, 7 }, { 21, 8 }, { 22, 8 }, { 28, 6 }, + { 16, 4 }, { 20, 5 }, { 25, 5 }, { 26, 5 }, { 27, 5 }, + { 23, 2 }, { 24, 3 }, { 29, 6 }, { 30, 8 }, { 31, 8 }, + { 32, 9 }, { 36, 9 }, { 33, 8 }, { 34, 7 }, { 35, 8 }, + { 41, 8 }, { 40, 7 }, { 42, 9 }, { 44, 9 }, { 43, 8 }, + { 39, 5 }, { 45, 9 }, { 49, 10 }, { 71, 10 }, { 48, 8 }, + { 52, 8 }, { 57, 9 }, { 60, 9 }, { 59, 8 }, { 65, 9 }, + { 74, 9 }, { 73, 7 }, + }, + }, + }, + { + { + { /* AC lowquant table group 0, table 0 */ + { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, + { 5, 7 }, { 6, 7 }, { 7, 7 }, { 8, 9 }, { 12, 10 }, + { 13, 10 }, { 9, 8 }, { 10, 8 }, { 11, 8 }, { 14, 10 }, + { 15, 10 }, { 18, 9 }, { 19, 10 }, { 41, 10 }, { 40, 9 }, + { 17, 7 }, { 21, 7 }, { 20, 6 }, { 16, 4 }, { 22, 7 }, + { 32, 7 }, { 28, 6 }, { 25, 5 }, { 23, 4 }, { 24, 4 }, + { 26, 5 }, { 27, 5 }, { 29, 6 }, { 30, 6 }, { 31, 6 }, + { 33, 7 }, { 34, 7 }, { 35, 7 }, { 36, 7 }, { 37, 7 }, + { 38, 7 }, { 39, 8 }, { 42, 14 }, { 43, 14 }, { 44, 14 }, + { 45, 14 }, { 47, 14 }, { 49, 14 }, { 50, 14 }, { 51, 14 }, + { 53, 14 }, { 54, 14 }, { 55, 14 }, { 56, 14 }, { 58, 14 }, + { 63, 14 }, { 64, 14 }, { 65, 14 }, { 46, 10 }, { 48, 9 }, + { 52, 8 }, { 57, 10 }, { 66, 14 }, { 67, 14 }, { 68, 14 }, + { 69, 14 }, { 70, 14 }, { 71, 14 }, { 72, 13 }, { 73, 13 }, + { 74, 13 }, { 75, 13 }, { 76, 13 }, { 62, 9 }, { 59, 7 }, + { 60, 8 }, { 61, 8 }, + }, + { /* AC lowquant table group 0, table 1 */ + { 0, 3 }, { 1, 5 }, { 2, 7 }, { 5, 8 }, { 6, 8 }, + { 3, 6 }, { 4, 6 }, { 7, 8 }, { 8, 14 }, { 9, 14 }, + { 11, 14 }, { 12, 14 }, { 13, 14 }, { 14, 14 }, { 15, 14 }, + { 18, 14 }, { 20, 14 }, { 21, 14 }, { 22, 14 }, { 41, 14 }, + { 45, 14 }, { 46, 14 }, { 47, 14 }, { 49, 14 }, { 50, 14 }, + { 51, 14 }, { 52, 13 }, { 53, 13 }, { 54, 13 }, { 55, 13 }, + { 56, 13 }, { 57, 13 }, { 58, 13 }, { 60, 13 }, { 61, 13 }, + { 62, 13 }, { 63, 13 }, { 64, 13 }, { 66, 13 }, { 67, 13 }, + { 68, 13 }, { 69, 13 }, { 70, 13 }, { 71, 13 }, { 72, 13 }, + { 73, 13 }, { 74, 13 }, { 75, 13 }, { 76, 13 }, { 10, 7 }, + { 16, 6 }, { 17, 8 }, { 19, 8 }, { 30, 7 }, { 23, 2 }, + { 24, 3 }, { 25, 5 }, { 29, 6 }, { 31, 7 }, { 32, 7 }, + { 26, 4 }, { 27, 4 }, { 28, 4 }, { 33, 7 }, { 34, 8 }, + { 40, 8 }, { 35, 7 }, { 42, 8 }, { 43, 8 }, { 36, 6 }, + { 37, 6 }, { 38, 6 }, { 39, 6 }, { 44, 8 }, { 48, 8 }, + { 65, 7 }, { 59, 6 }, + }, + { /* AC lowquant table group 0, table 2 */ + { 0, 2 }, { 1, 3 }, { 2, 3 }, { 3, 4 }, { 4, 5 }, + { 5, 5 }, { 6, 6 }, { 7, 6 }, { 8, 7 }, { 9, 7 }, + { 10, 7 }, { 11, 8 }, { 12, 8 }, { 13, 8 }, { 14, 9 }, + { 15, 10 }, { 39, 16 }, { 40, 16 }, { 41, 15 }, { 43, 15 }, + { 44, 15 }, { 45, 15 }, { 50, 15 }, { 51, 15 }, { 53, 15 }, + { 42, 12 }, { 49, 12 }, { 54, 15 }, { 55, 15 }, { 56, 15 }, + { 58, 15 }, { 64, 15 }, { 65, 15 }, { 66, 15 }, { 67, 15 }, + { 18, 8 }, { 19, 9 }, { 21, 9 }, { 17, 6 }, { 20, 6 }, + { 22, 8 }, { 38, 8 }, { 27, 7 }, { 16, 4 }, { 23, 5 }, + { 24, 6 }, { 25, 6 }, { 26, 6 }, { 28, 7 }, { 29, 7 }, + { 30, 7 }, { 31, 7 }, { 32, 7 }, { 33, 7 }, { 34, 7 }, + { 35, 7 }, { 36, 7 }, { 37, 7 }, { 46, 8 }, { 47, 10 }, + { 62, 11 }, { 63, 12 }, { 68, 15 }, { 69, 15 }, { 70, 15 }, + { 71, 15 }, { 72, 15 }, { 74, 15 }, { 75, 15 }, { 76, 15 }, + { 48, 9 }, { 52, 8 }, { 57, 9 }, { 73, 9 }, { 59, 7 }, + { 60, 8 }, { 61, 8 }, + }, + { /* AC lowquant table group 0, table 3 */ + { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 5 }, + { 5, 6 }, { 6, 6 }, { 7, 7 }, { 8, 7 }, { 9, 8 }, + { 10, 8 }, { 11, 9 }, { 12, 9 }, { 13, 9 }, { 14, 10 }, + { 15, 10 }, { 17, 5 }, { 18, 7 }, { 19, 7 }, { 21, 7 }, + { 24, 7 }, { 16, 3 }, { 20, 4 }, { 22, 5 }, { 23, 6 }, + { 25, 7 }, { 26, 7 }, { 27, 8 }, { 28, 8 }, { 29, 8 }, + { 30, 8 }, { 31, 8 }, { 32, 8 }, { 33, 9 }, { 37, 9 }, + { 34, 8 }, { 35, 8 }, { 36, 8 }, { 38, 11 }, { 40, 11 }, + { 39, 10 }, { 41, 15 }, { 43, 15 }, { 44, 15 }, { 45, 15 }, + { 50, 15 }, { 51, 15 }, { 64, 15 }, { 66, 15 }, { 49, 12 }, + { 47, 11 }, { 42, 10 }, { 46, 9 }, { 55, 10 }, { 56, 11 }, + { 63, 12 }, { 67, 15 }, { 68, 15 }, { 69, 15 }, { 70, 15 }, + { 71, 15 }, { 72, 15 }, { 74, 14 }, { 48, 7 }, { 53, 7 }, + { 52, 5 }, { 54, 8 }, { 58, 10 }, { 61, 10 }, { 62, 10 }, + { 65, 11 }, { 75, 12 }, { 76, 12 }, { 57, 7 }, { 59, 8 }, + { 60, 8 }, { 73, 7 }, + }, + { /* AC lowquant table group 0, table 4 */ + { 0, 3 }, { 1, 4 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, + { 5, 6 }, { 6, 6 }, { 7, 7 }, { 9, 7 }, { 8, 6 }, + { 10, 8 }, { 11, 8 }, { 12, 8 }, { 13, 9 }, { 14, 9 }, + { 15, 8 }, { 37, 8 }, { 31, 7 }, { 18, 6 }, { 17, 5 }, + { 16, 4 }, { 19, 6 }, { 21, 6 }, { 22, 5 }, { 20, 4 }, + { 23, 5 }, { 24, 6 }, { 25, 6 }, { 26, 6 }, { 27, 6 }, + { 28, 6 }, { 29, 6 }, { 30, 6 }, { 32, 7 }, { 33, 7 }, + { 34, 7 }, { 35, 7 }, { 36, 7 }, { 38, 11 }, { 50, 15 }, + { 51, 15 }, { 55, 15 }, { 56, 15 }, { 64, 15 }, { 69, 15 }, + { 70, 14 }, { 71, 14 }, { 72, 14 }, { 75, 14 }, { 76, 14 }, + { 45, 10 }, { 42, 9 }, { 41, 8 }, { 39, 7 }, { 40, 7 }, + { 43, 9 }, { 44, 9 }, { 46, 9 }, { 47, 10 }, { 58, 10 }, + { 49, 8 }, { 54, 9 }, { 62, 10 }, { 66, 10 }, { 48, 6 }, + { 53, 7 }, { 59, 7 }, { 52, 4 }, { 57, 6 }, { 60, 8 }, + { 61, 8 }, { 63, 9 }, { 65, 9 }, { 67, 10 }, { 68, 10 }, + { 74, 9 }, { 73, 5 }, + }, + { /* AC lowquant table group 0, table 5 */ + { 0, 2 }, { 1, 4 }, { 2, 5 }, { 3, 5 }, { 4, 6 }, + { 5, 6 }, { 6, 7 }, { 7, 8 }, { 8, 8 }, { 9, 8 }, + { 10, 9 }, { 11, 11 }, { 14, 11 }, { 13, 10 }, { 12, 8 }, + { 15, 15 }, { 42, 15 }, { 50, 15 }, { 51, 15 }, { 62, 15 }, + { 64, 15 }, { 67, 15 }, { 68, 15 }, { 69, 14 }, { 70, 14 }, + { 71, 14 }, { 72, 14 }, { 38, 11 }, { 40, 10 }, { 33, 9 }, + { 17, 5 }, { 18, 6 }, { 19, 7 }, { 24, 7 }, { 16, 3 }, + { 20, 4 }, { 21, 6 }, { 23, 6 }, { 22, 5 }, { 25, 8 }, + { 27, 8 }, { 26, 7 }, { 28, 7 }, { 29, 8 }, { 31, 8 }, + { 30, 7 }, { 32, 8 }, { 34, 9 }, { 35, 9 }, { 36, 9 }, + { 37, 9 }, { 39, 9 }, { 41, 11 }, { 44, 11 }, { 43, 10 }, + { 45, 11 }, { 47, 11 }, { 46, 10 }, { 56, 9 }, { 49, 8 }, + { 48, 6 }, { 54, 7 }, { 55, 7 }, { 53, 5 }, { 52, 4 }, + { 57, 6 }, { 58, 8 }, { 59, 8 }, { 60, 10 }, { 61, 11 }, + { 75, 11 }, { 63, 10 }, { 65, 10 }, { 66, 10 }, { 74, 10 }, + { 76, 9 }, { 73, 5 }, + }, + { /* AC lowquant table group 0, table 6 */ + { 0, 2 }, { 1, 4 }, { 2, 5 }, { 3, 6 }, { 4, 6 }, + { 5, 8 }, { 6, 9 }, { 7, 10 }, { 8, 10 }, { 9, 9 }, + { 10, 15 }, { 11, 15 }, { 13, 15 }, { 15, 15 }, { 37, 15 }, + { 46, 15 }, { 47, 15 }, { 49, 15 }, { 50, 15 }, { 51, 15 }, + { 53, 15 }, { 54, 15 }, { 55, 15 }, { 56, 15 }, { 58, 15 }, + { 60, 15 }, { 61, 15 }, { 62, 15 }, { 63, 15 }, { 64, 15 }, + { 67, 15 }, { 68, 15 }, { 69, 15 }, { 70, 15 }, { 71, 15 }, + { 72, 15 }, { 74, 14 }, { 75, 14 }, { 76, 14 }, { 12, 10 }, + { 14, 10 }, { 36, 10 }, { 21, 9 }, { 18, 8 }, { 19, 8 }, + { 22, 8 }, { 32, 8 }, { 17, 5 }, { 16, 4 }, { 20, 5 }, + { 26, 5 }, { 25, 4 }, { 23, 3 }, { 24, 3 }, { 27, 6 }, + { 28, 6 }, { 29, 7 }, { 30, 7 }, { 31, 7 }, { 33, 8 }, + { 34, 9 }, { 38, 9 }, { 35, 8 }, { 41, 9 }, { 42, 10 }, + { 45, 10 }, { 43, 8 }, { 44, 8 }, { 39, 6 }, { 40, 6 }, + { 48, 9 }, { 57, 9 }, { 52, 8 }, { 59, 9 }, { 65, 10 }, + { 66, 10 }, { 73, 8 }, + }, + { /* AC lowquant table group 0, table 7 */ + { 0, 4 }, { 1, 11 }, { 2, 11 }, { 3, 11 }, { 4, 11 }, + { 5, 11 }, { 6, 11 }, { 7, 11 }, { 8, 11 }, { 9, 11 }, + { 10, 11 }, { 11, 11 }, { 12, 11 }, { 13, 11 }, { 14, 11 }, + { 15, 11 }, { 16, 11 }, { 17, 10 }, { 18, 10 }, { 19, 10 }, + { 20, 10 }, { 21, 10 }, { 22, 10 }, { 25, 10 }, { 28, 10 }, + { 29, 10 }, { 30, 10 }, { 31, 10 }, { 32, 10 }, { 33, 10 }, + { 34, 10 }, { 35, 10 }, { 36, 10 }, { 37, 10 }, { 38, 10 }, + { 39, 10 }, { 40, 10 }, { 41, 10 }, { 42, 10 }, { 43, 10 }, + { 44, 10 }, { 45, 10 }, { 46, 10 }, { 47, 10 }, { 48, 10 }, + { 49, 10 }, { 50, 10 }, { 51, 10 }, { 52, 10 }, { 53, 10 }, + { 54, 10 }, { 55, 10 }, { 56, 10 }, { 57, 10 }, { 58, 10 }, + { 59, 10 }, { 60, 10 }, { 61, 10 }, { 62, 10 }, { 63, 10 }, + { 64, 10 }, { 65, 10 }, { 66, 10 }, { 67, 10 }, { 68, 10 }, + { 69, 10 }, { 70, 10 }, { 71, 10 }, { 72, 10 }, { 73, 10 }, + { 74, 10 }, { 75, 10 }, { 76, 10 }, { 26, 4 }, { 27, 4 }, + { 24, 2 }, { 23, 1 }, + }, + }, + { + { /* AC lowquant table group 1, table 0 */ + { 0, 3 }, { 1, 4 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, + { 5, 7 }, { 7, 8 }, { 8, 8 }, { 6, 6 }, { 9, 9 }, + { 10, 10 }, { 14, 15 }, { 47, 15 }, { 49, 14 }, { 50, 14 }, + { 51, 14 }, { 54, 14 }, { 55, 14 }, { 56, 14 }, { 58, 14 }, + { 15, 11 }, { 11, 9 }, { 12, 9 }, { 13, 9 }, { 37, 9 }, + { 32, 8 }, { 17, 5 }, { 16, 4 }, { 18, 6 }, { 19, 7 }, + { 21, 7 }, { 20, 5 }, { 22, 5 }, { 25, 5 }, { 24, 4 }, + { 23, 3 }, { 26, 5 }, { 27, 5 }, { 28, 5 }, { 29, 6 }, + { 30, 6 }, { 31, 7 }, { 33, 8 }, { 34, 8 }, { 35, 8 }, + { 36, 8 }, { 38, 10 }, { 44, 11 }, { 46, 11 }, { 45, 10 }, + { 53, 10 }, { 41, 8 }, { 39, 6 }, { 40, 7 }, { 42, 8 }, + { 43, 8 }, { 48, 7 }, { 57, 7 }, { 52, 6 }, { 59, 8 }, + { 60, 9 }, { 61, 11 }, { 63, 11 }, { 62, 10 }, { 64, 14 }, + { 67, 14 }, { 68, 14 }, { 69, 14 }, { 70, 14 }, { 71, 14 }, + { 72, 14 }, { 76, 14 }, { 75, 11 }, { 66, 10 }, { 74, 9 }, + { 65, 8 }, { 73, 6 }, + }, + { /* AC lowquant table group 1, table 1 */ + { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 6 }, + { 5, 6 }, { 6, 7 }, { 7, 8 }, { 8, 8 }, { 9, 8 }, + { 10, 9 }, { 11, 9 }, { 12, 11 }, { 13, 11 }, { 14, 11 }, + { 15, 11 }, { 24, 9 }, { 23, 8 }, { 17, 5 }, { 18, 6 }, + { 19, 7 }, { 25, 10 }, { 27, 10 }, { 26, 9 }, { 28, 10 }, + { 29, 12 }, { 35, 12 }, { 34, 11 }, { 30, 10 }, { 31, 10 }, + { 21, 6 }, { 32, 10 }, { 33, 10 }, { 36, 10 }, { 37, 12 }, + { 38, 12 }, { 39, 15 }, { 40, 15 }, { 41, 15 }, { 42, 15 }, + { 43, 14 }, { 44, 14 }, { 45, 14 }, { 51, 14 }, { 61, 14 }, + { 64, 14 }, { 46, 11 }, { 47, 11 }, { 49, 10 }, { 50, 12 }, + { 63, 12 }, { 59, 11 }, { 56, 10 }, { 48, 8 }, { 55, 8 }, + { 16, 3 }, { 20, 4 }, { 22, 4 }, { 52, 4 }, { 53, 6 }, + { 54, 7 }, { 58, 8 }, { 60, 10 }, { 62, 11 }, { 65, 14 }, + { 66, 14 }, { 67, 14 }, { 68, 14 }, { 69, 14 }, { 70, 14 }, + { 71, 14 }, { 72, 14 }, { 74, 11 }, { 75, 11 }, { 76, 10 }, + { 57, 6 }, { 73, 6 }, + }, + { /* AC lowquant table group 1, table 2 */ + { 0, 3 }, { 1, 4 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, + { 5, 8 }, { 6, 8 }, { 7, 8 }, { 8, 10 }, { 10, 10 }, + { 9, 9 }, { 11, 10 }, { 12, 16 }, { 15, 16 }, { 38, 16 }, + { 44, 16 }, { 46, 15 }, { 47, 15 }, { 50, 15 }, { 51, 15 }, + { 59, 15 }, { 60, 15 }, { 61, 15 }, { 62, 15 }, { 64, 15 }, + { 68, 15 }, { 69, 15 }, { 70, 15 }, { 71, 15 }, { 72, 15 }, + { 37, 11 }, { 13, 10 }, { 14, 10 }, { 19, 8 }, { 18, 6 }, + { 17, 5 }, { 21, 5 }, { 23, 7 }, { 24, 9 }, { 25, 9 }, + { 26, 9 }, { 27, 9 }, { 28, 9 }, { 29, 10 }, { 30, 10 }, + { 31, 10 }, { 32, 10 }, { 33, 10 }, { 34, 10 }, { 35, 9 }, + { 36, 10 }, { 39, 10 }, { 40, 11 }, { 42, 11 }, { 41, 10 }, + { 43, 10 }, { 45, 11 }, { 63, 11 }, { 16, 3 }, { 20, 3 }, + { 22, 4 }, { 48, 7 }, { 49, 9 }, { 65, 11 }, { 66, 11 }, + { 67, 11 }, { 74, 11 }, { 56, 8 }, { 54, 6 }, { 55, 6 }, + { 58, 7 }, { 75, 8 }, { 76, 8 }, { 52, 3 }, { 53, 4 }, + { 57, 5 }, { 73, 5 }, + }, + { /* AC lowquant table group 1, table 3 */ + { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 4 }, { 4, 5 }, + { 5, 5 }, { 6, 6 }, { 7, 6 }, { 8, 6 }, { 9, 6 }, + { 10, 7 }, { 11, 7 }, { 12, 8 }, { 13, 8 }, { 14, 8 }, + { 15, 9 }, { 19, 9 }, { 17, 6 }, { 18, 7 }, { 21, 8 }, + { 36, 8 }, { 16, 4 }, { 20, 6 }, { 22, 7 }, { 28, 7 }, + { 23, 6 }, { 24, 6 }, { 25, 6 }, { 26, 6 }, { 27, 6 }, + { 29, 7 }, { 30, 7 }, { 31, 7 }, { 32, 7 }, { 33, 7 }, + { 34, 7 }, { 35, 7 }, { 37, 8 }, { 38, 9 }, { 39, 11 }, + { 41, 15 }, { 42, 15 }, { 43, 15 }, { 44, 15 }, { 45, 15 }, + { 51, 15 }, { 54, 15 }, { 55, 15 }, { 49, 12 }, { 40, 10 }, + { 46, 7 }, { 47, 8 }, { 48, 8 }, { 50, 9 }, { 53, 9 }, + { 56, 15 }, { 67, 15 }, { 68, 15 }, { 69, 15 }, { 70, 14 }, + { 71, 14 }, { 72, 14 }, { 74, 14 }, { 75, 14 }, { 76, 14 }, + { 58, 11 }, { 65, 11 }, { 66, 11 }, { 64, 9 }, { 52, 7 }, + { 57, 8 }, { 61, 8 }, { 60, 7 }, { 59, 6 }, { 62, 8 }, + { 73, 8 }, { 63, 7 }, + }, + { /* AC lowquant table group 1, table 4 */ + { 0, 2 }, { 1, 4 }, { 2, 5 }, { 3, 6 }, { 4, 6 }, + { 5, 7 }, { 6, 7 }, { 7, 8 }, { 8, 8 }, { 9, 8 }, + { 10, 9 }, { 11, 9 }, { 12, 10 }, { 13, 10 }, { 14, 14 }, + { 69, 14 }, { 70, 14 }, { 72, 14 }, { 15, 12 }, { 44, 11 }, + { 37, 10 }, { 29, 8 }, { 19, 7 }, { 18, 6 }, { 17, 5 }, + { 21, 6 }, { 24, 6 }, { 16, 3 }, { 20, 4 }, { 22, 5 }, + { 23, 5 }, { 25, 6 }, { 26, 6 }, { 27, 7 }, { 28, 7 }, + { 30, 7 }, { 31, 8 }, { 32, 8 }, { 33, 8 }, { 34, 8 }, + { 35, 8 }, { 36, 9 }, { 38, 10 }, { 43, 10 }, { 39, 7 }, + { 40, 8 }, { 41, 9 }, { 42, 9 }, { 45, 9 }, { 46, 9 }, + { 47, 10 }, { 50, 12 }, { 51, 12 }, { 62, 11 }, { 56, 9 }, + { 48, 7 }, { 49, 8 }, { 54, 8 }, { 55, 8 }, { 58, 8 }, + { 52, 4 }, { 53, 6 }, { 57, 6 }, { 59, 9 }, { 60, 10 }, + { 61, 10 }, { 63, 10 }, { 64, 11 }, { 67, 11 }, { 65, 9 }, + { 66, 9 }, { 68, 11 }, { 71, 11 }, { 76, 10 }, { 74, 9 }, + { 75, 9 }, { 73, 6 }, + }, + { /* AC lowquant table group 1, table 5 */ + { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 5 }, { 4, 5 }, + { 5, 6 }, { 6, 6 }, { 7, 7 }, { 8, 7 }, { 9, 7 }, + { 10, 8 }, { 11, 8 }, { 12, 8 }, { 13, 9 }, { 14, 10 }, + { 39, 11 }, { 40, 12 }, { 41, 12 }, { 15, 9 }, { 37, 9 }, + { 19, 8 }, { 18, 7 }, { 21, 7 }, { 17, 5 }, { 16, 3 }, + { 20, 5 }, { 22, 6 }, { 24, 6 }, { 23, 5 }, { 25, 7 }, + { 26, 7 }, { 27, 7 }, { 28, 8 }, { 29, 8 }, { 30, 7 }, + { 31, 8 }, { 32, 8 }, { 33, 8 }, { 34, 8 }, { 35, 8 }, + { 36, 8 }, { 38, 9 }, { 42, 15 }, { 44, 15 }, { 45, 15 }, + { 56, 15 }, { 43, 13 }, { 51, 13 }, { 66, 13 }, { 58, 11 }, + { 49, 10 }, { 46, 8 }, { 47, 9 }, { 50, 9 }, { 48, 8 }, + { 53, 7 }, { 54, 9 }, { 55, 9 }, { 59, 8 }, { 52, 5 }, + { 57, 7 }, { 60, 8 }, { 61, 8 }, { 62, 9 }, { 64, 11 }, + { 65, 12 }, { 67, 15 }, { 68, 15 }, { 69, 15 }, { 70, 15 }, + { 71, 15 }, { 72, 15 }, { 74, 14 }, { 75, 11 }, { 76, 11 }, + { 63, 8 }, { 73, 7 }, + }, + { /* AC lowquant table group 1, table 6 */ + { 0, 3 }, { 1, 4 }, { 2, 4 }, { 3, 5 }, { 4, 5 }, + { 5, 6 }, { 6, 6 }, { 7, 7 }, { 8, 8 }, { 9, 8 }, + { 10, 8 }, { 11, 9 }, { 12, 9 }, { 13, 9 }, { 14, 11 }, + { 15, 12 }, { 45, 12 }, { 38, 10 }, { 33, 8 }, { 16, 3 }, + { 17, 5 }, { 18, 6 }, { 19, 7 }, { 27, 7 }, { 20, 4 }, + { 21, 6 }, { 25, 6 }, { 22, 5 }, { 23, 4 }, { 24, 5 }, + { 26, 6 }, { 28, 7 }, { 29, 7 }, { 30, 7 }, { 31, 7 }, + { 32, 7 }, { 34, 8 }, { 35, 8 }, { 36, 9 }, { 41, 9 }, + { 37, 8 }, { 39, 7 }, { 40, 8 }, { 42, 11 }, { 47, 15 }, + { 50, 15 }, { 51, 15 }, { 56, 15 }, { 64, 15 }, { 67, 15 }, + { 68, 15 }, { 69, 15 }, { 70, 14 }, { 71, 14 }, { 72, 14 }, + { 76, 14 }, { 44, 10 }, { 43, 9 }, { 46, 9 }, { 54, 9 }, + { 55, 11 }, { 63, 11 }, { 61, 10 }, { 58, 9 }, { 48, 6 }, + { 49, 7 }, { 53, 7 }, { 52, 5 }, { 57, 6 }, { 59, 8 }, + { 60, 9 }, { 62, 10 }, { 74, 10 }, { 65, 8 }, { 66, 9 }, + { 75, 9 }, { 73, 5 }, + }, + { /* AC lowquant table group 1, table 7 */ + { 0, 2 }, { 1, 4 }, { 2, 5 }, { 3, 6 }, { 4, 7 }, + { 5, 7 }, { 6, 8 }, { 7, 8 }, { 8, 9 }, { 9, 9 }, + { 10, 9 }, { 11, 10 }, { 12, 15 }, { 13, 15 }, { 14, 15 }, + { 15, 15 }, { 32, 15 }, { 36, 15 }, { 38, 15 }, { 41, 15 }, + { 42, 15 }, { 45, 15 }, { 47, 15 }, { 50, 15 }, { 51, 15 }, + { 61, 15 }, { 62, 14 }, { 34, 11 }, { 18, 6 }, { 17, 5 }, + { 19, 7 }, { 23, 8 }, { 24, 8 }, { 21, 6 }, { 25, 9 }, + { 26, 10 }, { 28, 10 }, { 27, 9 }, { 29, 9 }, { 30, 10 }, + { 31, 10 }, { 33, 10 }, { 35, 11 }, { 40, 11 }, { 37, 10 }, + { 43, 11 }, { 44, 11 }, { 39, 9 }, { 46, 11 }, { 60, 11 }, + { 49, 10 }, { 56, 9 }, { 59, 9 }, { 63, 14 }, { 64, 14 }, + { 67, 14 }, { 68, 14 }, { 69, 14 }, { 70, 14 }, { 71, 14 }, + { 72, 14 }, { 74, 11 }, { 76, 10 }, { 48, 7 }, { 16, 3 }, + { 20, 4 }, { 22, 4 }, { 52, 3 }, { 53, 5 }, { 54, 7 }, + { 55, 7 }, { 58, 7 }, { 65, 9 }, { 66, 9 }, { 75, 8 }, + { 57, 5 }, { 73, 5 }, + }, + }, }, }; #define MAX_AC_VLC_BITS 16 diff -Nru ffmpeg-4.2.2/libavcodec/ipu_parser.c ffmpeg-4.4/libavcodec/ipu_parser.c --- ffmpeg-4.2.2/libavcodec/ipu_parser.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ipu_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * IPU parser + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * IPU parser + */ + +#include "parser.h" + +typedef struct IPUParseContext { + ParseContext pc; +} IPUParseContext; + +static int ipu_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + IPUParseContext *ipc = s->priv_data; + uint32_t state = ipc->pc.state; + int next = END_NOT_FOUND, i = 0; + + s->pict_type = AV_PICTURE_TYPE_NONE; + s->duration = 1; + + *poutbuf_size = 0; + *poutbuf = NULL; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + for (; i < buf_size; i++) { + state = (state << 8) | buf[i]; + if (state == 0x1b0) { + next = i + 1; + break; + } + } + + ipc->pc.state = state; + if (ff_combine_frame(&ipc->pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_ipu_parser = { + .codec_ids = { AV_CODEC_ID_IPU }, + .priv_data_size = sizeof(IPUParseContext), + .parser_parse = ipu_parse, + .parser_close = ff_parse_close, +}; diff -Nru ffmpeg-4.2.2/libavcodec/ituh263dec.c ffmpeg-4.4/libavcodec/ituh263dec.c --- ffmpeg-4.2.2/libavcodec/ituh263dec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ituh263dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,6 +34,7 @@ #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/mathematics.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "mpegvideo.h" #include "h263.h" @@ -51,7 +52,6 @@ // reading vlc values. Changing these may improve speed and data cache needs // be aware though that decreasing them may need the number of stages that is // passed to get_vlc* to be increased. -#define MV_VLC_BITS 9 #define H263_MBTYPE_B_VLC_BITS 6 #define CBPC_B_VLC_BITS 3 @@ -98,7 +98,7 @@ VLC ff_h263_intra_MCBPC_vlc; VLC ff_h263_inter_MCBPC_vlc; VLC ff_h263_cbpy_vlc; -static VLC mv_vlc; +VLC ff_h263_mv_vlc; static VLC h263_mbtype_b_vlc; static VLC cbpc_b_vlc; @@ -119,13 +119,12 @@ INIT_VLC_STATIC(&ff_h263_cbpy_vlc, CBPY_VLC_BITS, 16, &ff_h263_cbpy_tab[0][1], 2, 1, &ff_h263_cbpy_tab[0][0], 2, 1, 64); - INIT_VLC_STATIC(&mv_vlc, MV_VLC_BITS, 33, + INIT_VLC_STATIC(&ff_h263_mv_vlc, H263_MV_VLC_BITS, 33, &ff_mvtab[0][1], 2, 1, &ff_mvtab[0][0], 2, 1, 538); - ff_rl_init(&ff_h263_rl_inter, ff_h263_static_rl_table_store[0]); - ff_rl_init(&ff_rl_intra_aic, ff_h263_static_rl_table_store[1]); + ff_h263_init_rl_inter(); INIT_VLC_RL(ff_h263_rl_inter, 554); - INIT_VLC_RL(ff_rl_intra_aic, 554); + INIT_FIRST_VLC_RL(ff_rl_intra_aic, 554); INIT_VLC_STATIC(&h263_mbtype_b_vlc, H263_MBTYPE_B_VLC_BITS, 15, &ff_h263_mbtype_b_tab[0][1], 2, 1, &ff_h263_mbtype_b_tab[0][0], 2, 1, 80); @@ -270,7 +269,7 @@ int ff_h263_decode_motion(MpegEncContext * s, int pred, int f_code) { int code, val, sign, shift; - code = get_vlc2(&s->gb, mv_vlc.table, MV_VLC_BITS, 2); + code = get_vlc2(&s->gb, ff_h263_mv_vlc.table, H263_MV_VLC_BITS, 2); if (code == 0) return pred; @@ -467,7 +466,7 @@ level = s->last_dc[component]; if (s->rv10_first_dc_coded[component]) { diff = ff_rv_decode_dc(s, n); - if (diff == 0xffff) + if (diff < 0) return -1; level += diff; level = level & 0xff; /* handle wrap round */ @@ -1286,7 +1285,7 @@ for(i=0; i<13; i++){ for(j=0; j<3; j++){ int v= get_bits(&s->gb, 8); - v |= get_sbits(&s->gb, 8)<<8; + v |= get_sbits(&s->gb, 8) * (1 << 8); av_log(s->avctx, AV_LOG_DEBUG, " %5d", v); } av_log(s->avctx, AV_LOG_DEBUG, "\n"); diff -Nru ffmpeg-4.2.2/libavcodec/ituh263enc.c ffmpeg-4.4/libavcodec/ituh263enc.c --- ffmpeg-4.2.2/libavcodec/ituh263enc.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ituh263enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -124,7 +124,7 @@ coded_frame_rate= 1800000; coded_frame_rate_base= (1000+best_clock_code)*best_divisor; - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); /* Update the pointer to last GOB */ s->ptr_lastgob = put_bits_ptr(&s->pb); @@ -713,8 +713,7 @@ } } -static av_cold void init_uni_h263_rl_tab(RLTable *rl, uint32_t *bits_tab, - uint8_t *len_tab) +static av_cold void init_uni_h263_rl_tab(const RLTable *rl, uint8_t *len_tab) { int slevel, run, last; @@ -738,10 +737,9 @@ len= rl->table_vlc[code][1]; bits=bits*2+sign; len++; - if(code!=rl->n && len < len_tab[index]){ - if(bits_tab) bits_tab[index]= bits; + if (code != rl->n && len < len_tab[index]) len_tab [index]= len; - } + /* ESC */ bits= rl->table_vlc[rl->n][0]; len = rl->table_vlc[rl->n][1]; @@ -749,10 +747,8 @@ bits=bits*64+run; len+=6; bits=bits*256+(level&0xff); len+=8; - if(len < len_tab[index]){ - if(bits_tab) bits_tab[index]= bits; + if (len < len_tab[index]) len_tab [index]= len; - } } } } @@ -763,13 +759,14 @@ static int done = 0; if (!done) { + static uint8_t rl_intra_table[2][2 * MAX_RUN + MAX_LEVEL + 3]; done = 1; - ff_rl_init(&ff_h263_rl_inter, ff_h263_static_rl_table_store[0]); - ff_rl_init(&ff_rl_intra_aic, ff_h263_static_rl_table_store[1]); + ff_rl_init(&ff_rl_intra_aic, rl_intra_table); + ff_h263_init_rl_inter(); - init_uni_h263_rl_tab(&ff_rl_intra_aic, NULL, uni_h263_intra_aic_rl_len); - init_uni_h263_rl_tab(&ff_h263_rl_inter , NULL, uni_h263_inter_rl_len); + init_uni_h263_rl_tab(&ff_rl_intra_aic, uni_h263_intra_aic_rl_len); + init_uni_h263_rl_tab(&ff_h263_rl_inter, uni_h263_inter_rl_len); init_mv_penalty_and_fcode(s); } diff -Nru ffmpeg-4.2.2/libavcodec/ivi.c ffmpeg-4.4/libavcodec/ivi.c --- ffmpeg-4.2.2/libavcodec/ivi.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ivi.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,13 +30,12 @@ #include "libavutil/attributes.h" #include "libavutil/imgutils.h" -#include "libavutil/timer.h" +#include "libavutil/thread.h" #define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" #include "internal.h" -#include "mathops.h" #include "ivi.h" #include "ivi_dsp.h" @@ -116,23 +115,6 @@ return 0; } -/** - * Reverse "nbits" bits of the value "val" and return the result - * in the least significant bits. - */ -static uint16_t inv_bits(uint16_t val, int nbits) -{ - uint16_t res; - - if (nbits <= 8) { - res = ff_reverse[val] >> (8 - nbits); - } else - res = ((ff_reverse[val & 0xFF] << 8) + - (ff_reverse[val >> 8])) >> (16 - nbits); - - return res; -} - /* * Generate a huffman codebook from the given descriptor * and convert it into the FFmpeg VLC table. @@ -163,7 +145,7 @@ if (bits[pos] > IVI_VLC_BITS) return AVERROR_INVALIDDATA; /* invalid descriptor */ - codewords[pos] = inv_bits((prefix | j), bits[pos]); + codewords[pos] = prefix | j; if (!bits[pos]) bits[pos] = 1; @@ -173,17 +155,14 @@ /* number of codewords = pos */ return init_vlc(vlc, IVI_VLC_BITS, pos, bits, 1, 1, codewords, 2, 2, - (flag ? INIT_VLC_USE_NEW_STATIC : 0) | INIT_VLC_LE); + (flag ? INIT_VLC_USE_NEW_STATIC : 0) | INIT_VLC_OUTPUT_LE); } -av_cold void ff_ivi_init_static_vlc(void) +static av_cold void ivi_init_static_vlc(void) { int i; static VLC_TYPE table_data[8192 * 16][2]; - static int initialized_vlcs = 0; - if (initialized_vlcs) - return; for (i = 0; i < 8; i++) { ivi_mb_vlc_tabs[i].table = table_data + i * 2 * 8192; ivi_mb_vlc_tabs[i].table_allocated = 8192; @@ -194,7 +173,12 @@ ivi_create_huff_from_desc(&ivi_blk_huff_desc[i], &ivi_blk_vlc_tabs[i], 1); } - initialized_vlcs = 1; +} + +av_cold void ff_ivi_init_static_vlc(void) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, ivi_init_static_vlc); } /* @@ -354,23 +338,11 @@ band->height = b_height; band->pitch = width_aligned; band->aheight = height_aligned; - band->bufs[0] = av_mallocz(buf_size); - band->bufs[1] = av_mallocz(buf_size); + av_assert0(!band->bufs[0] && !band->bufs[1] && + !band->bufs[2] && !band->bufs[3]); band->bufsize = buf_size/2; - if (!band->bufs[0] || !band->bufs[1]) - return AVERROR(ENOMEM); + av_assert0(buf_size % 2 == 0); - /* allocate the 3rd band buffer for scalability mode */ - if (cfg->luma_bands > 1) { - band->bufs[2] = av_mallocz(buf_size); - if (!band->bufs[2]) - return AVERROR(ENOMEM); - } - if (is_indeo4) { - band->bufs[3] = av_mallocz(buf_size); - if (!band->bufs[3]) - return AVERROR(ENOMEM); - } /* reset custom vlc */ planes[p].bands[0].blk_vlc.cust_desc.num_rows = 0; } @@ -455,8 +427,10 @@ av_freep(&band->tiles); band->tiles = av_mallocz_array(band->num_tiles, sizeof(IVITile)); - if (!band->tiles) + if (!band->tiles) { + band->num_tiles = 0; return AVERROR(ENOMEM); + } /* use the first luma band as reference for motion vectors * and quant */ @@ -488,7 +462,7 @@ if (get_bits1(gb)) { len = get_bits(gb, 8); if (len == 255) - len = get_bits_long(gb, 24); + len = get_bits(gb, 24); } /* align the bitstream reader on the byte boundary */ @@ -945,6 +919,15 @@ } } +static void *prepare_buf(IVI45DecContext *ctx, IVIBandDesc *band, int i) +{ + if (ctx->pic_conf.luma_bands <= 1 && i == 2) + return NULL; + if (!band->bufs[i]) + band->bufs[i] = av_mallocz(2 * band->bufsize); + return band->bufs[i]; +} + /** * Decode an Indeo 4 or 5 band. * @@ -959,18 +942,22 @@ int result, i, t, idx1, idx2, pos; IVITile *tile; - band->buf = band->bufs[ctx->dst_buf]; + band->buf = prepare_buf(ctx, band, ctx->dst_buf); if (!band->buf) { av_log(avctx, AV_LOG_ERROR, "Band buffer points to no data!\n"); return AVERROR_INVALIDDATA; } if (ctx->is_indeo4 && ctx->frame_type == IVI4_FRAMETYPE_BIDIR) { - band->ref_buf = band->bufs[ctx->b_ref_buf]; - band->b_ref_buf = band->bufs[ctx->ref_buf]; + band->ref_buf = prepare_buf(ctx, band, ctx->b_ref_buf); + band->b_ref_buf = prepare_buf(ctx, band, ctx->ref_buf); + if (!band->b_ref_buf) + return AVERROR(ENOMEM); } else { - band->ref_buf = band->bufs[ctx->ref_buf]; + band->ref_buf = prepare_buf(ctx, band, ctx->ref_buf); band->b_ref_buf = 0; } + if (!band->ref_buf) + return AVERROR(ENOMEM); band->data_ptr = ctx->frame_data + (get_bits_count(&ctx->gb) >> 3); result = ctx->decode_band_hdr(ctx, band, avctx); @@ -1123,8 +1110,6 @@ ctx->switch_buffers(ctx); - //{ START_TIMER; - if (ctx->is_nonnull_frame(ctx)) { ctx->buf_invalid[ctx->dst_buf] = 1; for (p = 0; p < 3; p++) { @@ -1150,8 +1135,6 @@ if (ctx->buf_invalid[ctx->dst_buf]) return -1; - //STOP_TIMER("decode_planes"); } - if (!ctx->is_nonnull_frame(ctx)) return buf_size; @@ -1192,10 +1175,12 @@ left = get_bits_count(&ctx->gb) & 0x18; skip_bits_long(&ctx->gb, 64 - left); if (get_bits_left(&ctx->gb) > 18 && - show_bits_long(&ctx->gb, 21) == 0xBFFF8) { // syncheader + inter type + show_bits(&ctx->gb, 21) == 0xBFFF8) { // syncheader + inter type AVPacket pkt; pkt.data = avpkt->data + (get_bits_count(&ctx->gb) >> 3); pkt.size = get_bits_left(&ctx->gb) >> 3; + ctx->got_p_frame = 0; + av_frame_unref(ctx->p_frame); ff_ivi_decode_frame(avctx, ctx->p_frame, &ctx->got_p_frame, &pkt); } } diff -Nru ffmpeg-4.2.2/libavcodec/j2kenc.c ffmpeg-4.4/libavcodec/j2kenc.c --- ffmpeg-4.2.2/libavcodec/j2kenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/j2kenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,6 +32,7 @@ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe * Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2007, Callum Lerwick + * Copyright (c) 2020, Gautam Ramakrishnan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -72,6 +73,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/opt.h" #include "libavutil/intreadwrite.h" +#include "libavutil/avstring.h" #define NMSEDEC_BITS 7 #define NMSEDEC_FRACBITS (NMSEDEC_BITS-1) @@ -100,6 +102,7 @@ typedef struct { Jpeg2000Component *comp; + double *layer_rates; } Jpeg2000Tile; typedef struct { @@ -126,9 +129,16 @@ Jpeg2000QuantStyle qntsty; Jpeg2000Tile *tile; + int layer_rates[100]; + uint8_t compression_rate_enc; ///< Is compression done using compression ratio? int format; int pred; + int sop; + int eph; + int prog; + int nlayers; + char *lr_str; } Jpeg2000EncoderContext; @@ -239,27 +249,36 @@ static void tag_tree_code(Jpeg2000EncoderContext *s, Jpeg2000TgtNode *node, int threshold) { Jpeg2000TgtNode *stack[30]; - int sp = 1, curval = 0; - stack[0] = node; + int sp = -1, curval = 0; - node = node->parent; - while(node){ - if (node->vis){ - curval = node->val; - break; - } - node->vis++; - stack[sp++] = node; + while(node->parent){ + stack[++sp] = node; node = node->parent; } - while(--sp >= 0){ - if (stack[sp]->val >= threshold){ + + while (1) { + if (curval > node->temp_val) + node->temp_val = curval; + else { + curval = node->temp_val; + } + + if (node->val >= threshold) { put_bits(s, 0, threshold - curval); - break; + curval = threshold; + } else { + put_bits(s, 0, node->val - curval); + curval = node->val; + if (!node->vis) { + put_bits(s, 1, 1); + node->vis = 1; + } } - put_bits(s, 0, stack[sp]->val - curval); - put_bits(s, 1, 1); - curval = stack[sp]->val; + + node->temp_val = curval; + if (sp < 0) + break; + node = stack[sp--]; } } @@ -298,7 +317,7 @@ bytestream_put_be16(&s->buf, s->ncomponents); // CSiz for (i = 0; i < s->ncomponents; i++){ // Ssiz_i XRsiz_i, YRsiz_i - bytestream_put_byte(&s->buf, 7); + bytestream_put_byte(&s->buf, s->cbps[i] - 1); bytestream_put_byte(&s->buf, i?1<chroma_shift[0]:1); bytestream_put_byte(&s->buf, i?1<chroma_shift[1]:1); } @@ -308,16 +327,21 @@ static int put_cod(Jpeg2000EncoderContext *s) { Jpeg2000CodingStyle *codsty = &s->codsty; + uint8_t scod = 0; if (s->buf_end - s->buf < 14) return -1; bytestream_put_be16(&s->buf, JPEG2000_COD); bytestream_put_be16(&s->buf, 12); // Lcod - bytestream_put_byte(&s->buf, 0); // Scod + if (s->sop) + scod |= JPEG2000_CSTY_SOP; + if (s->eph) + scod |= JPEG2000_CSTY_EPH; + bytestream_put_byte(&s->buf, scod); // Scod // SGcod - bytestream_put_byte(&s->buf, 0); // progression level - bytestream_put_be16(&s->buf, 1); // num of layers + bytestream_put_byte(&s->buf, s->prog); // progression level + bytestream_put_be16(&s->buf, s->nlayers); // num of layers if(s->avctx->pix_fmt == AV_PIX_FMT_YUV444P){ bytestream_put_byte(&s->buf, 0); // unspecified }else{ @@ -396,6 +420,31 @@ return psotptr; } +static void compute_rates(Jpeg2000EncoderContext* s) +{ + int i, j; + int layno, compno; + for (i = 0; i < s->numYtiles; i++) { + for (j = 0; j < s->numXtiles; j++) { + Jpeg2000Tile *tile = &s->tile[s->numXtiles * i + j]; + for (compno = 0; compno < s->ncomponents; compno++) { + int tilew = tile->comp[compno].coord[0][1] - tile->comp[compno].coord[0][0]; + int tileh = tile->comp[compno].coord[1][1] - tile->comp[compno].coord[1][0]; + int scale = (compno?1 << s->chroma_shift[0]:1) * (compno?1 << s->chroma_shift[1]:1); + for (layno = 0; layno < s->nlayers; layno++) { + if (s->layer_rates[layno] > 0) { + tile->layer_rates[layno] += (double)(tilew * tileh) * s->ncomponents * s->cbps[compno] / + (double)(s->layer_rates[layno] * 8 * scale); + } else { + tile->layer_rates[layno] = 0.0; + } + } + } + } + } + +} + /** * compute the sizes of tiles, resolution levels, bands, etc. * allocate memory for them @@ -410,7 +459,7 @@ s->numXtiles = ff_jpeg2000_ceildiv(s->width, s->tile_width); s->numYtiles = ff_jpeg2000_ceildiv(s->height, s->tile_height); - s->tile = av_malloc_array(s->numXtiles, s->numYtiles * sizeof(Jpeg2000Tile)); + s->tile = av_calloc(s->numXtiles, s->numYtiles * sizeof(Jpeg2000Tile)); if (!s->tile) return AVERROR(ENOMEM); for (tileno = 0, tiley = 0; tiley < s->numYtiles; tiley++) @@ -420,6 +469,11 @@ tile->comp = av_mallocz_array(s->ncomponents, sizeof(Jpeg2000Component)); if (!tile->comp) return AVERROR(ENOMEM); + + tile->layer_rates = av_mallocz_array(s->nlayers, sizeof(*tile->layer_rates)); + if (!tile->layer_rates) + return AVERROR(ENOMEM); + for (compno = 0; compno < s->ncomponents; compno++){ Jpeg2000Component *comp = tile->comp + compno; int ret, i, j; @@ -444,46 +498,53 @@ return ret; } } + compute_rates(s); return 0; } -static void copy_frame(Jpeg2000EncoderContext *s) -{ - int tileno, compno, i, y, x; - uint8_t *line; - for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){ - Jpeg2000Tile *tile = s->tile + tileno; - if (s->planar){ - for (compno = 0; compno < s->ncomponents; compno++){ - Jpeg2000Component *comp = tile->comp + compno; - int *dst = comp->i_data; - line = s->picture->data[compno] - + comp->coord[1][0] * s->picture->linesize[compno] - + comp->coord[0][0]; - for (y = comp->coord[1][0]; y < comp->coord[1][1]; y++){ - uint8_t *ptr = line; - for (x = comp->coord[0][0]; x < comp->coord[0][1]; x++) - *dst++ = *ptr++ - (1 << 7); - line += s->picture->linesize[compno]; - } - } - } else{ - line = s->picture->data[0] + tile->comp[0].coord[1][0] * s->picture->linesize[0] - + tile->comp[0].coord[0][0] * s->ncomponents; - - i = 0; - for (y = tile->comp[0].coord[1][0]; y < tile->comp[0].coord[1][1]; y++){ - uint8_t *ptr = line; - for (x = tile->comp[0].coord[0][0]; x < tile->comp[0].coord[0][1]; x++, i++){ - for (compno = 0; compno < s->ncomponents; compno++){ - tile->comp[compno].i_data[i] = *ptr++ - (1 << 7); - } - } - line += s->picture->linesize[0]; - } - } +#define COPY_FRAME(D, PIXEL) \ + static void copy_frame_ ##D(Jpeg2000EncoderContext *s) \ + { \ + int tileno, compno, i, y, x; \ + PIXEL *line; \ + for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){ \ + Jpeg2000Tile *tile = s->tile + tileno; \ + if (s->planar){ \ + for (compno = 0; compno < s->ncomponents; compno++){ \ + Jpeg2000Component *comp = tile->comp + compno; \ + int *dst = comp->i_data; \ + int cbps = s->cbps[compno]; \ + line = (PIXEL*)s->picture->data[compno] \ + + comp->coord[1][0] * (s->picture->linesize[compno] / sizeof(PIXEL)) \ + + comp->coord[0][0]; \ + for (y = comp->coord[1][0]; y < comp->coord[1][1]; y++){ \ + PIXEL *ptr = line; \ + for (x = comp->coord[0][0]; x < comp->coord[0][1]; x++) \ + *dst++ = *ptr++ - (1 << (cbps - 1)); \ + line += s->picture->linesize[compno] / sizeof(PIXEL); \ + } \ + } \ + } else{ \ + line = (PIXEL*)s->picture->data[0] + tile->comp[0].coord[1][0] * (s->picture->linesize[0] / sizeof(PIXEL)) \ + + tile->comp[0].coord[0][0] * s->ncomponents; \ + \ + i = 0; \ + for (y = tile->comp[0].coord[1][0]; y < tile->comp[0].coord[1][1]; y++){ \ + PIXEL *ptr = line; \ + for (x = tile->comp[0].coord[0][0]; x < tile->comp[0].coord[0][1]; x++, i++){ \ + for (compno = 0; compno < s->ncomponents; compno++){ \ + int cbps = s->cbps[compno]; \ + tile->comp[compno].i_data[i] = *ptr++ - (1 << (cbps - 1)); \ + } \ + } \ + line += s->picture->linesize[0] / sizeof(PIXEL); \ + } \ + } \ + } \ } -} + +COPY_FRAME(8, uint8_t) +COPY_FRAME(16, uint16_t) static void init_quantization(Jpeg2000EncoderContext *s) { @@ -521,13 +582,13 @@ mask = ~((1<> (NMSEDEC_BITS-2)&2) + 1; - lut_nmsedec_ref[i] = FFMAX((-2*i + (1<passes[passno].rate = ff_mqc_flush_to(&t1->mqc, cblk->passes[passno].flushed, &cblk->passes[passno].flushed_len); + cblk->passes[passno].rate -= cblk->passes[passno].flushed_len; + wmsedec += (int64_t)nmsedec << (2*bpno); cblk->passes[passno].disto = wmsedec; @@ -691,8 +754,10 @@ cblk->npasses = passno; cblk->ninclpasses = passno; - if (passno) + if (passno) { cblk->passes[passno-1].rate = ff_mqc_flush_to(&t1->mqc, cblk->passes[passno-1].flushed, &cblk->passes[passno-1].flushed_len); + cblk->passes[passno-1].rate -= cblk->passes[passno-1].flushed_len; + } } /* tier-2 routines: */ @@ -712,33 +777,82 @@ } -static int encode_packet(Jpeg2000EncoderContext *s, Jpeg2000ResLevel *rlevel, int precno, - uint8_t *expn, int numgbits) +static int encode_packet(Jpeg2000EncoderContext *s, Jpeg2000ResLevel *rlevel, int layno, + int precno, uint8_t *expn, int numgbits, int packetno, + int nlayers) { int bandno, empty = 1; - + int i; // init bitstream *s->buf = 0; s->bit_index = 0; + if (s->sop) { + bytestream_put_be16(&s->buf, JPEG2000_SOP); + bytestream_put_be16(&s->buf, 4); + bytestream_put_be16(&s->buf, packetno); + } // header + if (!layno) { + for (bandno = 0; bandno < rlevel->nbands; bandno++) { + Jpeg2000Band *band = rlevel->band + bandno; + if (band->coord[0][0] < band->coord[0][1] + && band->coord[1][0] < band->coord[1][1]) { + Jpeg2000Prec *prec = band->prec + precno; + int nb_cblks = prec->nb_codeblocks_height * prec->nb_codeblocks_width; + int pos; + ff_tag_tree_zero(prec->zerobits, prec->nb_codeblocks_width, prec->nb_codeblocks_height, 99); + ff_tag_tree_zero(prec->cblkincl, prec->nb_codeblocks_width, prec->nb_codeblocks_height, 99); + for (pos = 0; pos < nb_cblks; pos++) { + Jpeg2000Cblk *cblk = &prec->cblk[pos]; + prec->zerobits[pos].val = expn[bandno] + numgbits - 1 - cblk->nonzerobits; + cblk->incl = 0; + cblk->lblock = 3; + tag_tree_update(prec->zerobits + pos); + for (i = 0; i < nlayers; i++) { + if (cblk->layers[i].npasses > 0) { + prec->cblkincl[pos].val = i; + break; + } + } + if (i == nlayers) + prec->cblkincl[pos].val = i; + tag_tree_update(prec->cblkincl + pos); + } + } + } + } + // is the packet empty? for (bandno = 0; bandno < rlevel->nbands; bandno++){ - if (rlevel->band[bandno].coord[0][0] < rlevel->band[bandno].coord[0][1] - && rlevel->band[bandno].coord[1][0] < rlevel->band[bandno].coord[1][1]){ - empty = 0; - break; + Jpeg2000Band *band = rlevel->band + bandno; + if (band->coord[0][0] < band->coord[0][1] + && band->coord[1][0] < band->coord[1][1]) { + Jpeg2000Prec *prec = band->prec + precno; + int nb_cblks = prec->nb_codeblocks_height * prec->nb_codeblocks_width; + int pos; + for (pos = 0; pos < nb_cblks; pos++) { + Jpeg2000Cblk *cblk = &prec->cblk[pos]; + if (cblk->layers[layno].npasses) { + empty = 0; + break; + } + } + if (!empty) + break; } } put_bits(s, !empty, 1); if (empty){ j2k_flush(s); + if (s->eph) + bytestream_put_be16(&s->buf, JPEG2000_EPH); return 0; } - for (bandno = 0; bandno < rlevel->nbands; bandno++){ + for (bandno = 0; bandno < rlevel->nbands; bandno++) { Jpeg2000Band *band = rlevel->band + bandno; Jpeg2000Prec *prec = band->prec + precno; int yi, xi, pos; @@ -748,61 +862,70 @@ || band->coord[1][0] == band->coord[1][1]) continue; - for (pos=0, yi = 0; yi < prec->nb_codeblocks_height; yi++){ + for (pos=0, yi = 0; yi < prec->nb_codeblocks_height; yi++) { for (xi = 0; xi < cblknw; xi++, pos++){ - prec->cblkincl[pos].val = prec->cblk[yi * cblknw + xi].ninclpasses == 0; - tag_tree_update(prec->cblkincl + pos); - prec->zerobits[pos].val = expn[bandno] + numgbits - 1 - prec->cblk[yi * cblknw + xi].nonzerobits; - tag_tree_update(prec->zerobits + pos); - } - } - - for (pos=0, yi = 0; yi < prec->nb_codeblocks_height; yi++){ - for (xi = 0; xi < cblknw; xi++, pos++){ - int pad = 0, llen, length; + int llen = 0, length; Jpeg2000Cblk *cblk = prec->cblk + yi * cblknw + xi; if (s->buf_end - s->buf < 20) // approximately return -1; // inclusion information - tag_tree_code(s, prec->cblkincl + pos, 1); - if (!cblk->ninclpasses) + if (!cblk->incl) + tag_tree_code(s, prec->cblkincl + pos, layno + 1); + else { + put_bits(s, cblk->layers[layno].npasses > 0, 1); + } + + if (!cblk->layers[layno].npasses) continue; + // zerobits information - tag_tree_code(s, prec->zerobits + pos, 100); + if (!cblk->incl) { + tag_tree_code(s, prec->zerobits + pos, 100); + cblk->incl = 1; + } + // number of passes - putnumpasses(s, cblk->ninclpasses); + putnumpasses(s, cblk->layers[layno].npasses); - length = cblk->passes[cblk->ninclpasses-1].rate; - llen = av_log2(length) - av_log2(cblk->ninclpasses) - 2; - if (llen < 0){ - pad = -llen; - llen = 0; + length = cblk->layers[layno].data_len; + if (layno == nlayers - 1 && cblk->layers[layno].cum_passes){ + length += cblk->passes[cblk->layers[layno].cum_passes-1].flushed_len; + } + if (cblk->lblock + av_log2(cblk->layers[layno].npasses) < av_log2(length) + 1) { + llen = av_log2(length) + 1 - cblk->lblock - av_log2(cblk->layers[layno].npasses); } + // length of code block + cblk->lblock += llen; put_bits(s, 1, llen); put_bits(s, 0, 1); - put_num(s, length, av_log2(length)+1+pad); + put_num(s, length, cblk->lblock + av_log2(cblk->layers[layno].npasses)); } } } j2k_flush(s); - for (bandno = 0; bandno < rlevel->nbands; bandno++){ + if (s->eph) { + bytestream_put_be16(&s->buf, JPEG2000_EPH); + } + + for (bandno = 0; bandno < rlevel->nbands; bandno++) { Jpeg2000Band *band = rlevel->band + bandno; Jpeg2000Prec *prec = band->prec + precno; int yi, cblknw = prec->nb_codeblocks_width; - for (yi =0; yi < prec->nb_codeblocks_height; yi++){ + for (yi =0; yi < prec->nb_codeblocks_height; yi++) { int xi; for (xi = 0; xi < cblknw; xi++){ Jpeg2000Cblk *cblk = prec->cblk + yi * cblknw + xi; - if (cblk->ninclpasses){ - if (s->buf_end - s->buf < cblk->passes[cblk->ninclpasses-1].rate) + if (cblk->layers[layno].npasses) { + if (s->buf_end - s->buf < cblk->layers[layno].data_len + 2) return -1; - bytestream_put_buffer(&s->buf, cblk->data + 1, cblk->passes[cblk->ninclpasses-1].rate - - cblk->passes[cblk->ninclpasses-1].flushed_len); - bytestream_put_buffer(&s->buf, cblk->passes[cblk->ninclpasses-1].flushed, - cblk->passes[cblk->ninclpasses-1].flushed_len); + bytestream_put_buffer(&s->buf, cblk->layers[layno].data_start + 1, cblk->layers[layno].data_len); + if (layno == nlayers - 1 && cblk->layers[layno].cum_passes) { + bytestream_put_buffer(&s->buf, cblk->passes[cblk->layers[layno].cum_passes-1].flushed, + cblk->passes[cblk->layers[layno].cum_passes-1].flushed_len); + } } } } @@ -810,29 +933,420 @@ return 0; } -static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno) +static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno, int nlayers) { - int compno, reslevelno, ret; + int compno, reslevelno, layno, ret; Jpeg2000CodingStyle *codsty = &s->codsty; Jpeg2000QuantStyle *qntsty = &s->qntsty; + int packetno = 0; + int step_x, step_y; + int x, y; + int tile_coord[2][2]; + int col = tileno % s->numXtiles; + int row = tileno / s->numXtiles; + + tile_coord[0][0] = col * s->tile_width; + tile_coord[0][1] = FFMIN(tile_coord[0][0] + s->tile_width, s->width); + tile_coord[1][0] = row * s->tile_height; + tile_coord[1][1] = FFMIN(tile_coord[1][0] + s->tile_height, s->height); av_log(s->avctx, AV_LOG_DEBUG, "tier2\n"); // lay-rlevel-comp-pos progression + switch (s->prog) { + case JPEG2000_PGOD_LRCP: + for (layno = 0; layno < nlayers; layno++) { + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ + for (compno = 0; compno < s->ncomponents; compno++){ + int precno; + Jpeg2000ResLevel *reslevel = s->tile[tileno].comp[compno].reslevel + reslevelno; + for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){ + if ((ret = encode_packet(s, reslevel, layno, precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), + qntsty->nguardbits, packetno++, nlayers)) < 0) + return ret; + } + } + } + } + break; + case JPEG2000_PGOD_RLCP: for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ - for (compno = 0; compno < s->ncomponents; compno++){ - int precno; - Jpeg2000ResLevel *reslevel = s->tile[tileno].comp[compno].reslevel + reslevelno; - for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){ - if ((ret = encode_packet(s, reslevel, precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), - qntsty->nguardbits)) < 0) - return ret; + for (layno = 0; layno < nlayers; layno++) { + for (compno = 0; compno < s->ncomponents; compno++){ + int precno; + Jpeg2000ResLevel *reslevel = s->tile[tileno].comp[compno].reslevel + reslevelno; + for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){ + if ((ret = encode_packet(s, reslevel, layno, precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), + qntsty->nguardbits, packetno++, nlayers)) < 0) + return ret; + } + } + } + } + break; + case JPEG2000_PGOD_RPCL: + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) { + int precno; + step_x = 30; + step_y = 30; + for (compno = 0; compno < s->ncomponents; compno++) { + Jpeg2000Component *comp = tile->comp + compno; + if (reslevelno < codsty->nreslevels) { + uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r + Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno; + step_x = FFMIN(step_x, rlevel->log2_prec_width + reducedresno); + step_y = FFMIN(step_y, rlevel->log2_prec_height + reducedresno); + } + } + + step_x = 1<ncomponents; compno++) { + Jpeg2000Component *comp = tile->comp + compno; + uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r + Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno; + int log_subsampling[2] = { compno?s->chroma_shift[0]:0, compno?s->chroma_shift[1]:0}; + unsigned prcx, prcy; + int trx0, try0; + + trx0 = ff_jpeg2000_ceildivpow2(tile_coord[0][0], log_subsampling[0] + reducedresno); + try0 = ff_jpeg2000_ceildivpow2(tile_coord[1][0], log_subsampling[1] + reducedresno); + + if (!(y % ((uint64_t)1 << (reslevel->log2_prec_height + reducedresno + log_subsampling[1])) == 0 || + (y == tile_coord[1][0] && (try0 << reducedresno) % (1U << (reducedresno + reslevel->log2_prec_height))))) + continue; + + if (!(x % ((uint64_t)1 << (reslevel->log2_prec_width + reducedresno + log_subsampling[0])) == 0 || + (x == tile_coord[0][0] && (trx0 << reducedresno) % (1U << (reducedresno + reslevel->log2_prec_width))))) + continue; + + // check if a precinct exists + prcx = ff_jpeg2000_ceildivpow2(x, log_subsampling[0] + reducedresno) >> reslevel->log2_prec_width; + prcy = ff_jpeg2000_ceildivpow2(y, log_subsampling[1] + reducedresno) >> reslevel->log2_prec_height; + prcx -= ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], reducedresno) >> reslevel->log2_prec_width; + prcy -= ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], reducedresno) >> reslevel->log2_prec_height; + precno = prcx + reslevel->num_precincts_x * prcy; + + if (prcx >= reslevel->num_precincts_x || prcy >= reslevel->num_precincts_y) { + av_log(s->avctx, AV_LOG_WARNING, "prc %d %d outside limits %d %d\n", + prcx, prcy, reslevel->num_precincts_x, reslevel->num_precincts_y); + continue; + } + for (layno = 0; layno < nlayers; layno++) { + if ((ret = encode_packet(s, reslevel, layno, precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), + qntsty->nguardbits, packetno++, nlayers)) < 0) + return ret; + } + } + } + } + } + break; + case JPEG2000_PGOD_PCRL: + step_x = 32; + step_y = 32; + for (compno = 0; compno < s->ncomponents; compno++) { + Jpeg2000Component *comp = tile->comp + compno; + + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) { + uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r + Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno; + step_x = FFMIN(step_x, rlevel->log2_prec_width + reducedresno); + step_y = FFMIN(step_y, rlevel->log2_prec_height + reducedresno); + } + } + if (step_x >= 31 || step_y >= 31){ + avpriv_request_sample(s->avctx, "PCRL with large step"); + return AVERROR_PATCHWELCOME; + } + step_x = 1<ncomponents; compno++) { + Jpeg2000Component *comp = tile->comp + compno; + int log_subsampling[2] = { compno?s->chroma_shift[0]:0, compno?s->chroma_shift[1]:0}; + + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) { + unsigned prcx, prcy; + int precno; + uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r + Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno; + int trx0, try0; + + trx0 = ff_jpeg2000_ceildivpow2(tile_coord[0][0], log_subsampling[0] + reducedresno); + try0 = ff_jpeg2000_ceildivpow2(tile_coord[1][0], log_subsampling[1] + reducedresno); + + if (!(y % ((uint64_t)1 << (reslevel->log2_prec_height + reducedresno + log_subsampling[1])) == 0 || + (y == tile_coord[1][0] && (try0 << reducedresno) % (1U << (reducedresno + reslevel->log2_prec_height))))) + continue; + + if (!(x % ((uint64_t)1 << (reslevel->log2_prec_width + reducedresno + log_subsampling[0])) == 0 || + (x == tile_coord[0][0] && (trx0 << reducedresno) % (1U << (reducedresno + reslevel->log2_prec_width))))) + continue; + + // check if a precinct exists + prcx = ff_jpeg2000_ceildivpow2(x, log_subsampling[0] + reducedresno) >> reslevel->log2_prec_width; + prcy = ff_jpeg2000_ceildivpow2(y, log_subsampling[1] + reducedresno) >> reslevel->log2_prec_height; + prcx -= ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], reducedresno) >> reslevel->log2_prec_width; + prcy -= ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], reducedresno) >> reslevel->log2_prec_height; + + precno = prcx + reslevel->num_precincts_x * prcy; + + if (prcx >= reslevel->num_precincts_x || prcy >= reslevel->num_precincts_y) { + av_log(s->avctx, AV_LOG_WARNING, "prc %d %d outside limits %d %d\n", + prcx, prcy, reslevel->num_precincts_x, reslevel->num_precincts_y); + continue; + } + for (layno = 0; layno < nlayers; layno++) { + if ((ret = encode_packet(s, reslevel, layno, precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), + qntsty->nguardbits, packetno++, nlayers)) < 0) + return ret; + } + } + } + } + } + break; + case JPEG2000_PGOD_CPRL: + for (compno = 0; compno < s->ncomponents; compno++) { + Jpeg2000Component *comp = tile->comp + compno; + int log_subsampling[2] = { compno?s->chroma_shift[0]:0, compno?s->chroma_shift[1]:0}; + step_x = 32; + step_y = 32; + + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) { + uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r + Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno; + step_x = FFMIN(step_x, rlevel->log2_prec_width + reducedresno); + step_y = FFMIN(step_y, rlevel->log2_prec_height + reducedresno); + } + if (step_x >= 31 || step_y >= 31){ + avpriv_request_sample(s->avctx, "CPRL with large step"); + return AVERROR_PATCHWELCOME; + } + step_x = 1<nreslevels; reslevelno++) { + unsigned prcx, prcy; + int precno; + int trx0, try0; + uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r + Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno; + + trx0 = ff_jpeg2000_ceildivpow2(tile_coord[0][0], log_subsampling[0] + reducedresno); + try0 = ff_jpeg2000_ceildivpow2(tile_coord[1][0], log_subsampling[1] + reducedresno); + + if (!(y % ((uint64_t)1 << (reslevel->log2_prec_height + reducedresno + log_subsampling[1])) == 0 || + (y == tile_coord[1][0] && (try0 << reducedresno) % (1U << (reducedresno + reslevel->log2_prec_height))))) + continue; + + if (!(x % ((uint64_t)1 << (reslevel->log2_prec_width + reducedresno + log_subsampling[0])) == 0 || + (x == tile_coord[0][0] && (trx0 << reducedresno) % (1U << (reducedresno + reslevel->log2_prec_width))))) + continue; + + // check if a precinct exists + prcx = ff_jpeg2000_ceildivpow2(x, log_subsampling[0] + reducedresno) >> reslevel->log2_prec_width; + prcy = ff_jpeg2000_ceildivpow2(y, log_subsampling[1] + reducedresno) >> reslevel->log2_prec_height; + prcx -= ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], reducedresno) >> reslevel->log2_prec_width; + prcy -= ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], reducedresno) >> reslevel->log2_prec_height; + + precno = prcx + reslevel->num_precincts_x * prcy; + + if (prcx >= reslevel->num_precincts_x || prcy >= reslevel->num_precincts_y) { + av_log(s->avctx, AV_LOG_WARNING, "prc %d %d outside limits %d %d\n", + prcx, prcy, reslevel->num_precincts_x, reslevel->num_precincts_y); + continue; + } + for (layno = 0; layno < nlayers; layno++) { + if ((ret = encode_packet(s, reslevel, layno, precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), + qntsty->nguardbits, packetno++, nlayers)) < 0) + return ret; + } + } + } } } + } + av_log(s->avctx, AV_LOG_DEBUG, "after tier2\n"); return 0; } +static void makelayer(Jpeg2000EncoderContext *s, int layno, double thresh, Jpeg2000Tile* tile, int final) +{ + int compno, resno, bandno, precno, cblkno; + int passno; + + for (compno = 0; compno < s->ncomponents; compno++) { + Jpeg2000Component *comp = &tile->comp[compno]; + + for (resno = 0; resno < s->codsty.nreslevels; resno++) { + Jpeg2000ResLevel *reslevel = comp->reslevel + resno; + + for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){ + for (bandno = 0; bandno < reslevel->nbands ; bandno++){ + Jpeg2000Band *band = reslevel->band + bandno; + Jpeg2000Prec *prec = band->prec + precno; + + for (cblkno = 0; cblkno < prec->nb_codeblocks_height * prec->nb_codeblocks_width; cblkno++){ + Jpeg2000Cblk *cblk = prec->cblk + cblkno; + Jpeg2000Layer *layer = &cblk->layers[layno]; + int n; + + if (layno == 0) { + cblk->ninclpasses = 0; + } + + n = cblk->ninclpasses; + + if (thresh < 0) { + n = cblk->npasses; + } else { + for (passno = cblk->ninclpasses; passno < cblk->npasses; passno++) { + int32_t dr; + double dd; + Jpeg2000Pass *pass = &cblk->passes[passno]; + + if (n == 0) { + dr = pass->rate; + dd = pass->disto; + } else { + dr = pass->rate - cblk->passes[n - 1].rate; + dd = pass->disto - cblk->passes[n-1].disto; + } + + if (!dr) { + if (dd != 0.0) { + n = passno + 1; + } + continue; + } + + if (thresh - (dd / dr) < DBL_EPSILON) + n = passno + 1; + } + } + layer->npasses = n - cblk->ninclpasses; + layer->cum_passes = n; + + if (layer->npasses == 0) { + layer->disto = 0; + layer->data_len = 0; + continue; + } + + if (cblk->ninclpasses == 0) { + layer->data_len = cblk->passes[n - 1].rate; + layer->data_start = cblk->data; + layer->disto = cblk->passes[n - 1].disto; + } else { + layer->data_len = cblk->passes[n - 1].rate - cblk->passes[cblk->ninclpasses - 1].rate; + layer->data_start = cblk->data + cblk->passes[cblk->ninclpasses - 1].rate; + layer->disto = cblk->passes[n - 1].disto - + cblk->passes[cblk->ninclpasses - 1].disto; + } + if (final) { + cblk->ninclpasses = n; + } + } + } + } + } + } +} + +static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile) +{ + int precno, compno, reslevelno, bandno, cblkno, lev, passno, layno; + int i; + double min = DBL_MAX; + double max = 0; + double thresh; + int tile_disto = 0; + + Jpeg2000CodingStyle *codsty = &s->codsty; + + for (compno = 0; compno < s->ncomponents; compno++){ + Jpeg2000Component *comp = tile->comp + compno; + + for (reslevelno = 0, lev = codsty->nreslevels-1; reslevelno < codsty->nreslevels; reslevelno++, lev--){ + Jpeg2000ResLevel *reslevel = comp->reslevel + reslevelno; + + for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){ + for (bandno = 0; bandno < reslevel->nbands ; bandno++){ + Jpeg2000Band *band = reslevel->band + bandno; + Jpeg2000Prec *prec = band->prec + precno; + + for (cblkno = 0; cblkno < prec->nb_codeblocks_height * prec->nb_codeblocks_width; cblkno++){ + Jpeg2000Cblk *cblk = prec->cblk + cblkno; + for (passno = 0; passno < cblk->npasses; passno++) { + Jpeg2000Pass *pass = &cblk->passes[passno]; + int dr; + double dd, drslope; + + tile_disto += pass->disto; + if (passno == 0) { + dr = (int32_t)pass->rate; + dd = pass->disto; + } else { + dr = (int32_t)(pass->rate - cblk->passes[passno - 1].rate); + dd = pass->disto - cblk->passes[passno - 1].disto; + } + + if (dr <= 0) + continue; + + drslope = dd / dr; + if (drslope < min) + min = drslope; + + if (drslope > max) + max = drslope; + } + } + } + } + } + } + + for (layno = 0; layno < s->nlayers; layno++) { + double lo = min; + double hi = max; + double stable_thresh = 0.0; + double good_thresh = 0.0; + if (!s->layer_rates[layno]) { + good_thresh = -1.0; + } else { + for (i = 0; i < 128; i++) { + uint8_t *stream_pos = s->buf; + int ret; + thresh = (lo + hi) / 2; + makelayer(s, layno, thresh, tile, 0); + ret = encode_packets(s, tile, (int)(tile - s->tile), layno + 1); + memset(stream_pos, 0, s->buf - stream_pos); + if ((s->buf - stream_pos > ceil(tile->layer_rates[layno])) || ret < 0) { + lo = thresh; + s->buf = stream_pos; + continue; + } + hi = thresh; + stable_thresh = thresh; + s->buf = stream_pos; + } + } + if (good_thresh >= 0.0) + good_thresh = stable_thresh == 0.0 ? thresh : stable_thresh; + makelayer(s, layno, good_thresh, tile, 1); + } +} + static int getcut(Jpeg2000Cblk *cblk, int64_t lambda, int dwt_norm) { int passno, res = 0; @@ -841,9 +1355,9 @@ int64_t dd; dr = cblk->passes[passno].rate - - (res ? cblk->passes[res-1].rate:0); + - (res ? cblk->passes[res-1].rate : 0); dd = cblk->passes[passno].disto - - (res ? cblk->passes[res-1].disto:0); + - (res ? cblk->passes[res-1].disto : 0); if (((dd * dwt_norm) >> WMSEDEC_SHIFT) * dwt_norm >= dr * lambda) res = passno+1; @@ -873,6 +1387,11 @@ cblk->ninclpasses = getcut(cblk, s->lambda, (int64_t)dwt_norms[codsty->transform == FF_DWT53][bandpos][lev] * (int64_t)band->i_stepsize >> 15); + cblk->layers[0].data_start = cblk->data; + cblk->layers[0].cum_passes = cblk->ninclpasses; + cblk->layers[0].npasses = cblk->ninclpasses; + if (cblk->ninclpasses) + cblk->layers[0].data_len = cblk->passes[cblk->ninclpasses - 1].rate; } } } @@ -927,7 +1446,7 @@ for (y = yy0; y < yy1; y++){ int *ptr = t1.data + (y-yy0)*t1.stride; for (x = xx0; x < xx1; x++){ - *ptr++ = comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * y + x] << NMSEDEC_FRACBITS; + *ptr++ = comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * y + x] * (1 << NMSEDEC_FRACBITS); } } } else{ @@ -960,8 +1479,12 @@ } av_log(s->avctx, AV_LOG_DEBUG, "rate control\n"); - truncpasses(s, tile); - if ((ret = encode_packets(s, tile, tileno)) < 0) + if (s->compression_rate_enc) + makelayers(s, tile); + else + truncpasses(s, tile); + + if ((ret = encode_packets(s, tile, tileno, s->nlayers)) < 0) return ret; av_log(s->avctx, AV_LOG_DEBUG, "after rate control\n"); return 0; @@ -972,12 +1495,17 @@ int tileno, compno; Jpeg2000CodingStyle *codsty = &s->codsty; + if (!s->tile) + return; for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){ - for (compno = 0; compno < s->ncomponents; compno++){ - Jpeg2000Component *comp = s->tile[tileno].comp + compno; - ff_jpeg2000_cleanup(comp, codsty); + if (s->tile[tileno].comp) { + for (compno = 0; compno < s->ncomponents; compno++){ + Jpeg2000Component *comp = s->tile[tileno].comp + compno; + ff_jpeg2000_cleanup(comp, codsty); + } + av_freep(&s->tile[tileno].comp); } - av_freep(&s->tile[tileno].comp); + av_freep(&s->tile[tileno].layer_rates); } av_freep(&s->tile); } @@ -1015,7 +1543,11 @@ s->lambda = s->picture->quality * LAMBDA_SCALE; - copy_frame(s); + if (avctx->pix_fmt == AV_PIX_FMT_BGR48 || avctx->pix_fmt == AV_PIX_FMT_GRAY16) + copy_frame_16(s); + else + copy_frame_8(s); + reinit(s); if (s->format == CODEC_JP2) { @@ -1132,6 +1664,53 @@ return 0; } +static int parse_layer_rates(Jpeg2000EncoderContext *s) +{ + int i; + char *token; + char *saveptr = NULL; + int rate; + int nlayers = 0; + if (!s->lr_str) { + s->nlayers = 1; + s->layer_rates[0] = 0; + s->compression_rate_enc = 0; + return 0; + } + + token = av_strtok(s->lr_str, ",", &saveptr); + if (rate = strtol(token, NULL, 10)) { + s->layer_rates[0] = rate <= 1 ? 0:rate; + nlayers++; + } else { + return AVERROR_INVALIDDATA; + } + + while (1) { + token = av_strtok(NULL, ",", &saveptr); + if (!token) + break; + if (rate = strtol(token, NULL, 10)) { + if (nlayers >= 100) { + return AVERROR_INVALIDDATA; + } + s->layer_rates[nlayers] = rate <= 1 ? 0:rate; + nlayers++; + } else { + return AVERROR_INVALIDDATA; + } + } + + for (i = 1; i < nlayers; i++) { + if (s->layer_rates[i] >= s->layer_rates[i-1]) { + return AVERROR_INVALIDDATA; + } + } + s->nlayers = nlayers; + s->compression_rate_enc = 1; + return 0; +} + static av_cold int j2kenc_init(AVCodecContext *avctx) { int i, ret; @@ -1141,6 +1720,12 @@ s->avctx = avctx; av_log(s->avctx, AV_LOG_DEBUG, "init\n"); + if (parse_layer_rates(s)) { + av_log(s, AV_LOG_WARNING, "Layer rates invalid. Encoding with 1 layer based on quality metric.\n"); + s->nlayers = 1; + s->layer_rates[0] = 0; + s->compression_rate_enc = 0; + } #if FF_API_PRIVATE_OPT FF_DISABLE_DEPRECATION_WARNINGS @@ -1161,6 +1746,7 @@ memset(codsty->log2_prec_heights, 15, sizeof(codsty->log2_prec_heights)); codsty->nreslevels2decode= codsty->nreslevels = 7; + codsty->nlayers = s->nlayers; codsty->log2_cblk_width = 4; codsty->log2_cblk_height = 4; codsty->transform = s->pred ? FF_DWT53 : FF_DWT97_INT; @@ -1180,12 +1766,16 @@ s->width = avctx->width; s->height = avctx->height; - for (i = 0; i < 3; i++) - s->cbps[i] = 8; + for (i = 0; i < 3; i++) { + if (avctx->pix_fmt == AV_PIX_FMT_GRAY16 || avctx->pix_fmt == AV_PIX_FMT_RGB48) + s->cbps[i] = 16; + else + s->cbps[i] = 8; + } - if (avctx->pix_fmt == AV_PIX_FMT_RGB24){ + if (avctx->pix_fmt == AV_PIX_FMT_RGB24 || avctx->pix_fmt == AV_PIX_FMT_RGB48){ s->ncomponents = 3; - } else if (avctx->pix_fmt == AV_PIX_FMT_GRAY8 || avctx->pix_fmt == AV_PIX_FMT_PAL8){ + } else if (avctx->pix_fmt == AV_PIX_FMT_GRAY8 || avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY16){ s->ncomponents = 1; } else{ // planar YUV s->planar = 1; @@ -1230,7 +1820,15 @@ { "pred", "DWT Type", OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, "pred" }, { "dwt97int", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "pred" }, { "dwt53", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "pred" }, - + { "sop", "SOP marker", OFFSET(sop), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, }, + { "eph", "EPH marker", OFFSET(eph), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, }, + { "prog", "Progression Order", OFFSET(prog), AV_OPT_TYPE_INT, { .i64 = 0 }, JPEG2000_PGOD_LRCP, JPEG2000_PGOD_CPRL, VE, "prog" }, + { "lrcp", NULL, OFFSET(prog), AV_OPT_TYPE_CONST, { .i64 = JPEG2000_PGOD_LRCP }, 0, 0, VE, "prog" }, + { "rlcp", NULL, OFFSET(prog), AV_OPT_TYPE_CONST, { .i64 = JPEG2000_PGOD_RLCP }, 0, 0, VE, "prog" }, + { "rpcl", NULL, OFFSET(prog), AV_OPT_TYPE_CONST, { .i64 = JPEG2000_PGOD_RPCL }, 0, 0, VE, "prog" }, + { "pcrl", NULL, OFFSET(prog), AV_OPT_TYPE_CONST, { .i64 = JPEG2000_PGOD_PCRL }, 0, 0, VE, "prog" }, + { "cprl", NULL, OFFSET(prog), AV_OPT_TYPE_CONST, { .i64 = JPEG2000_PGOD_CPRL }, 0, 0, VE, "prog" }, + { "layer_rates", "Layer Rates", OFFSET(lr_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE }, { NULL } }; @@ -1255,7 +1853,9 @@ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_PAL8, + AV_PIX_FMT_RGB48, AV_PIX_FMT_GRAY16, AV_PIX_FMT_NONE }, .priv_class = &j2k_class, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/jpeg2000.c ffmpeg-4.4/libavcodec/jpeg2000.c --- ffmpeg-4.2.2/libavcodec/jpeg2000.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/jpeg2000.c 2021-04-08 21:28:39.000000000 +0000 @@ -39,7 +39,7 @@ /* tag tree routines */ /* allocate the memory for tag tree */ -static int32_t tag_tree_size(int w, int h) +int32_t ff_tag_tree_size(int w, int h) { int64_t res = 0; while (w > 1 || h > 1) { @@ -57,7 +57,7 @@ Jpeg2000TgtNode *res, *t, *t2; int32_t tt_size; - tt_size = tag_tree_size(w, h); + tt_size = ff_tag_tree_size(w, h); t = res = av_mallocz_array(tt_size, sizeof(*t)); if (!res) @@ -82,12 +82,13 @@ return res; } -static void tag_tree_zero(Jpeg2000TgtNode *t, int w, int h) +void ff_tag_tree_zero(Jpeg2000TgtNode *t, int w, int h, int val) { - int i, siz = tag_tree_size(w, h); + int i, siz = ff_tag_tree_size(w, h); for (i = 0; i < siz; i++) { - t[i].val = 0; + t[i].val = val; + t[i].temp_val = 0; t[i].vis = 0; } } @@ -260,9 +261,11 @@ band->f_stepsize *= 0.5; } -static int init_prec(Jpeg2000Band *band, +static int init_prec(AVCodecContext *avctx, + Jpeg2000Band *band, Jpeg2000ResLevel *reslevel, Jpeg2000Component *comp, + Jpeg2000CodingStyle *codsty, int precno, int bandno, int reslevelno, int log2_band_prec_width, int log2_band_prec_height) @@ -276,11 +279,11 @@ /* TODO: Verify with previous count of codeblocks per band */ /* Compute P_x0 */ - prec->coord[0][0] = ((band->coord[0][0] >> log2_band_prec_width) + precno % reslevel->num_precincts_x) * + prec->coord[0][0] = ((reslevel->coord[0][0] >> reslevel->log2_prec_width) + precno % reslevel->num_precincts_x) * (1 << log2_band_prec_width); /* Compute P_y0 */ - prec->coord[1][0] = ((band->coord[1][0] >> log2_band_prec_height) + precno / reslevel->num_precincts_x) * + prec->coord[1][0] = ((reslevel->coord[1][0] >> reslevel->log2_prec_height) + precno / reslevel->num_precincts_x) * (1 << log2_band_prec_height); /* Compute P_x1 */ @@ -365,6 +368,11 @@ cblk->lblock = 3; cblk->length = 0; cblk->npasses = 0; + if (av_codec_is_encoder(avctx->codec)) { + cblk->layers = av_mallocz_array(codsty->nlayers, sizeof(*cblk->layers)); + if (!cblk->layers) + return AVERROR(ENOMEM); + } } return 0; @@ -438,7 +446,7 @@ return AVERROR(ENOMEM); for (precno = 0; precno < nb_precincts; precno++) { - ret = init_prec(band, reslevel, comp, + ret = init_prec(avctx, band, reslevel, comp, codsty, precno, bandno, reslevelno, log2_band_prec_width, log2_band_prec_height); if (ret < 0) @@ -509,9 +517,6 @@ // update precincts size: 2^n value reslevel->log2_prec_width = codsty->log2_prec_widths[reslevelno]; reslevel->log2_prec_height = codsty->log2_prec_heights[reslevelno]; - if (!reslevel->log2_prec_width || !reslevel->log2_prec_height) { - return AVERROR_INVALIDDATA; - } /* Number of bands for each resolution level */ if (reslevelno == 0) @@ -570,8 +575,8 @@ Jpeg2000Band *band = rlevel->band + bandno; for(precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++) { Jpeg2000Prec *prec = band->prec + precno; - tag_tree_zero(prec->zerobits, prec->nb_codeblocks_width, prec->nb_codeblocks_height); - tag_tree_zero(prec->cblkincl, prec->nb_codeblocks_width, prec->nb_codeblocks_height); + ff_tag_tree_zero(prec->zerobits, prec->nb_codeblocks_width, prec->nb_codeblocks_height, 0); + ff_tag_tree_zero(prec->cblkincl, prec->nb_codeblocks_width, prec->nb_codeblocks_height, 0); for (cblkno = 0; cblkno < prec->nb_codeblocks_width * prec->nb_codeblocks_height; cblkno++) { Jpeg2000Cblk *cblk = prec->cblk + cblkno; cblk->length = 0; @@ -616,6 +621,7 @@ av_freep(&cblk->passes); av_freep(&cblk->lengthinc); av_freep(&cblk->data_start); + av_freep(&cblk->layers); } av_freep(&prec->cblk); } diff -Nru ffmpeg-4.2.2/libavcodec/jpeg2000dec.c ffmpeg-4.4/libavcodec/jpeg2000dec.c --- ffmpeg-4.2.2/libavcodec/jpeg2000dec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/jpeg2000dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -71,6 +71,7 @@ typedef struct Jpeg2000TilePart { uint8_t tile_index; // Tile index who refers the tile-part const uint8_t *tp_end; + GetByteContext header_tpg; // bit stream of header if PPM header is used GetByteContext tpg; // bit stream in tile-part } Jpeg2000TilePart; @@ -83,6 +84,10 @@ Jpeg2000QuantStyle qntsty[4]; Jpeg2000POC poc; Jpeg2000TilePart tile_part[32]; + uint8_t has_ppt; // whether this tile has a ppt marker + uint8_t *packed_headers; // contains packed headers. Used only along with PPT marker + int packed_headers_size; // size in bytes of the packed headers + GetByteContext packed_headers_stream; // byte context corresponding to packed headers uint16_t tp_idx; // Tile-part index int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} } Jpeg2000Tile; @@ -98,6 +103,13 @@ uint8_t cbps[4]; // bits per sample in particular components uint8_t sgnd[4]; // if a component is signed uint8_t properties[4]; + + uint8_t has_ppm; + uint8_t *packed_headers; // contains packed headers. Used only along with PPM marker + int packed_headers_size; + GetByteContext packed_headers_stream; + uint8_t in_tile_headers; + int cdx[4], cdy[4]; int precision; int ncomponents; @@ -113,6 +125,7 @@ Jpeg2000CodingStyle codsty[4]; Jpeg2000QuantStyle qntsty[4]; Jpeg2000POC poc; + uint8_t roi_shift[4]; int bit_index; @@ -264,6 +277,8 @@ const enum AVPixelFormat *possible_fmts = NULL; int possible_fmts_nb = 0; int ret; + int o_dimx, o_dimy; //original image dimensions. + int dimx, dimy; if (bytestream2_get_bytes_left(&s->g) < 36) { av_log(s->avctx, AV_LOG_ERROR, "Insufficient space for SIZ\n"); @@ -281,10 +296,6 @@ s->tile_offset_y = bytestream2_get_be32u(&s->g); // YT0Siz ncomponents = bytestream2_get_be16u(&s->g); // CSiz - if (s->image_offset_x || s->image_offset_y) { - avpriv_request_sample(s->avctx, "Support for image offsets"); - return AVERROR_PATCHWELCOME; - } if (av_image_check_size2(s->width, s->height, s->avctx->max_pixels, AV_PIX_FMT_NONE, 0, s->avctx)) { avpriv_request_sample(s->avctx, "Large Dimensions"); return AVERROR_PATCHWELCOME; @@ -366,11 +377,18 @@ } /* compute image size with reduction factor */ - ret = ff_set_dimensions(s->avctx, - ff_jpeg2000_ceildivpow2(s->width - s->image_offset_x, - s->reduction_factor), - ff_jpeg2000_ceildivpow2(s->height - s->image_offset_y, - s->reduction_factor)); + o_dimx = ff_jpeg2000_ceildivpow2(s->width - s->image_offset_x, + s->reduction_factor); + o_dimy = ff_jpeg2000_ceildivpow2(s->height - s->image_offset_y, + s->reduction_factor); + dimx = ff_jpeg2000_ceildiv(o_dimx, s->cdx[0]); + dimy = ff_jpeg2000_ceildiv(o_dimy, s->cdy[0]); + for (i = 1; i < s->ncomponents; i++) { + dimx = FFMAX(dimx, ff_jpeg2000_ceildiv(o_dimx, s->cdx[i])); + dimy = FFMAX(dimy, ff_jpeg2000_ceildiv(o_dimy, s->cdy[i])); + } + + ret = ff_set_dimensions(s->avctx, dimx, dimy); if (ret < 0) return ret; @@ -398,12 +416,16 @@ break; } } - for (i = 0; i < possible_fmts_nb; ++i) { - if (pix_fmt_match(possible_fmts[i], ncomponents, s->precision, log2_chroma_wh, s->pal8)) { - s->avctx->pix_fmt = possible_fmts[i]; - break; + if ( s->avctx->pix_fmt != AV_PIX_FMT_NONE + && !pix_fmt_match(s->avctx->pix_fmt, ncomponents, s->precision, log2_chroma_wh, s->pal8)) + s->avctx->pix_fmt = AV_PIX_FMT_NONE; + if (s->avctx->pix_fmt == AV_PIX_FMT_NONE) + for (i = 0; i < possible_fmts_nb; ++i) { + if (pix_fmt_match(possible_fmts[i], ncomponents, s->precision, log2_chroma_wh, s->pal8)) { + s->avctx->pix_fmt = possible_fmts[i]; + break; + } } - } if (i == possible_fmts_nb) { if (ncomponents == 4 && @@ -418,6 +440,18 @@ s->cdef[3] = 3; i = 0; } + } else if (ncomponents == 3 && s->precision == 8 && + s->cdx[0] == s->cdx[1] && s->cdx[0] == s->cdx[2] && + s->cdy[0] == s->cdy[1] && s->cdy[0] == s->cdy[2]) { + s->avctx->pix_fmt = AV_PIX_FMT_RGB24; + i = 0; + } else if (ncomponents == 2 && s->precision == 8 && + s->cdx[0] == s->cdx[1] && s->cdy[0] == s->cdy[1]) { + s->avctx->pix_fmt = AV_PIX_FMT_YA8; + i = 0; + } else if (ncomponents == 1 && s->precision == 8) { + s->avctx->pix_fmt = AV_PIX_FMT_GRAY8; + i = 0; } } @@ -549,7 +583,7 @@ if ((ret = get_cox(s, &tmp)) < 0) return ret; - + tmp.init = 1; for (compno = 0; compno < s->ncomponents; compno++) if (!(properties[compno] & HAD_COC)) memcpy(c + compno, &tmp, sizeof(tmp)); @@ -562,6 +596,7 @@ uint8_t *properties) { int compno, ret; + uint8_t has_eph, has_sop; if (bytestream2_get_bytes_left(&s->g) < 2) { av_log(s->avctx, AV_LOG_ERROR, "Insufficient space for COC\n"); @@ -578,15 +613,52 @@ } c += compno; + has_eph = c->csty & JPEG2000_CSTY_EPH; + has_sop = c->csty & JPEG2000_CSTY_SOP; c->csty = bytestream2_get_byteu(&s->g); + c->csty |= has_eph; //do not override eph present bits from COD + c->csty |= has_sop; //do not override sop present bits from COD if ((ret = get_cox(s, c)) < 0) return ret; properties[compno] |= HAD_COC; + c->init = 1; return 0; } +static int get_rgn(Jpeg2000DecoderContext *s, int n) +{ + uint16_t compno; + compno = (s->ncomponents < 257)? bytestream2_get_byte(&s->g): + bytestream2_get_be16u(&s->g); + if (bytestream2_get_byte(&s->g)) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid RGN header.\n"); + return AVERROR_INVALIDDATA; // SRgn field value is 0 + } + // SPrgn field + // Currently compno cannot be greater than 4. + // However, future implementation should support compno up to 65536 + if (compno < s->ncomponents) { + int v; + if (s->curtileno == -1) { + v = bytestream2_get_byte(&s->g); + if (v > 30) + return AVERROR_PATCHWELCOME; + s->roi_shift[compno] = v; + } else { + if (s->tile[s->curtileno].tp_idx != 0) + return AVERROR_INVALIDDATA; // marker occurs only in first tile part of tile + v = bytestream2_get_byte(&s->g); + if (v > 30) + return AVERROR_PATCHWELCOME; + s->tile[s->curtileno].comp[compno].roi_shift = v; + } + return 0; + } + return AVERROR_INVALIDDATA; +} + /* Get common part for QCD and QCC segments. */ static int get_qcx(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q) { @@ -787,6 +859,15 @@ return 0; } +static int read_crg(Jpeg2000DecoderContext *s, int n) +{ + if (s->ncomponents*4 != n - 2) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid CRG marker.\n"); + return AVERROR_INVALIDDATA; + } + bytestream2_skip(&s->g, n - 2); + return 0; +} /* Tile-part lengths: see ISO 15444-1:2002, section A.7.1 * Used to know the number of tile parts and lengths. * There may be multiple TLMs in the header. @@ -795,7 +876,7 @@ * markers. Parsing the TLM header is needed to increment the input header * buffer. * This marker is mandatory for DCI. */ -static uint8_t get_tlm(Jpeg2000DecoderContext *s, int n) +static int get_tlm(Jpeg2000DecoderContext *s, int n) { uint8_t Stlm, ST, SP, tile_tlm, i; bytestream2_get_byte(&s->g); /* Ztlm: skipped */ @@ -803,7 +884,11 @@ // too complex ? ST = ((Stlm >> 4) & 0x01) + ((Stlm >> 4) & 0x02); ST = (Stlm >> 4) & 0x03; - // TODO: Manage case of ST = 0b11 --> raise error + if (ST == 0x03) { + av_log(s->avctx, AV_LOG_ERROR, "TLM marker contains invalid ST value.\n"); + return AVERROR_INVALIDDATA; + } + SP = (Stlm >> 6) & 0x01; tile_tlm = (n - 4) / ((SP + 1) * 2 + ST); for (i = 0; i < tile_tlm; i++) { @@ -851,6 +936,66 @@ return 0; } +static int get_ppm(Jpeg2000DecoderContext *s, int n) +{ + void *new; + + if (n < 3) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid length for PPM data.\n"); + return AVERROR_INVALIDDATA; + } + bytestream2_get_byte(&s->g); //Zppm is skipped and not used + new = av_realloc(s->packed_headers, + s->packed_headers_size + n - 3); + if (new) { + s->packed_headers = new; + } else + return AVERROR(ENOMEM); + s->has_ppm = 1; + memset(&s->packed_headers_stream, 0, sizeof(s->packed_headers_stream)); + bytestream_get_buffer(&s->g.buffer, s->packed_headers + s->packed_headers_size, + n - 3); + s->packed_headers_size += n - 3; + + return 0; +} + +static int get_ppt(Jpeg2000DecoderContext *s, int n) +{ + Jpeg2000Tile *tile; + void *new; + + if (n < 3) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid length for PPT data.\n"); + return AVERROR_INVALIDDATA; + } + if (s->curtileno < 0) + return AVERROR_INVALIDDATA; + + tile = &s->tile[s->curtileno]; + if (tile->tp_idx != 0) { + av_log(s->avctx, AV_LOG_ERROR, + "PPT marker can occur only on first tile part of a tile.\n"); + return AVERROR_INVALIDDATA; + } + + tile->has_ppt = 1; // this tile has a ppt marker + bytestream2_get_byte(&s->g); // Zppt is skipped and not used + new = av_realloc(tile->packed_headers, + tile->packed_headers_size + n - 3); + if (new) { + tile->packed_headers = new; + } else + return AVERROR(ENOMEM); + memset(&tile->packed_headers_stream, 0, sizeof(tile->packed_headers_stream)); + memcpy(tile->packed_headers + tile->packed_headers_size, + s->g.buffer, n - 3); + tile->packed_headers_size += n - 3; + bytestream2_skip(&s->g, n - 3); + + return 0; +} + static int init_tile(Jpeg2000DecoderContext *s, int tileno) { int compno; @@ -876,18 +1021,21 @@ comp->coord_o[0][1] = tile->coord[0][1]; comp->coord_o[1][0] = tile->coord[1][0]; comp->coord_o[1][1] = tile->coord[1][1]; - if (compno) { - comp->coord_o[0][0] /= s->cdx[compno]; - comp->coord_o[0][1] /= s->cdx[compno]; - comp->coord_o[1][0] /= s->cdy[compno]; - comp->coord_o[1][1] /= s->cdy[compno]; - } + + comp->coord_o[0][0] = ff_jpeg2000_ceildiv(comp->coord_o[0][0], s->cdx[compno]); + comp->coord_o[0][1] = ff_jpeg2000_ceildiv(comp->coord_o[0][1], s->cdx[compno]); + comp->coord_o[1][0] = ff_jpeg2000_ceildiv(comp->coord_o[1][0], s->cdy[compno]); + comp->coord_o[1][1] = ff_jpeg2000_ceildiv(comp->coord_o[1][1], s->cdy[compno]); comp->coord[0][0] = ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], s->reduction_factor); comp->coord[0][1] = ff_jpeg2000_ceildivpow2(comp->coord_o[0][1], s->reduction_factor); comp->coord[1][0] = ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], s->reduction_factor); comp->coord[1][1] = ff_jpeg2000_ceildivpow2(comp->coord_o[1][1], s->reduction_factor); + if (!comp->roi_shift) + comp->roi_shift = s->roi_shift[compno]; + if (!codsty->init) + return AVERROR_INVALIDDATA; if (ret = ff_jpeg2000_init_component(comp, codsty, qntsty, s->cbps[compno], s->cdx[compno], s->cdy[compno], s->avctx)) @@ -923,6 +1071,34 @@ return res; } +static inline void select_header(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, + int *tp_index) +{ + s->g = tile->tile_part[*tp_index].header_tpg; + if (bytestream2_get_bytes_left(&s->g) == 0 && s->bit_index == 8) { + if (*tp_index < FF_ARRAY_ELEMS(tile->tile_part) - 1) { + s->g = tile->tile_part[++(*tp_index)].tpg; + } + } +} + +static inline void select_stream(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, + int *tp_index, Jpeg2000CodingStyle *codsty) +{ + s->g = tile->tile_part[*tp_index].tpg; + if (bytestream2_get_bytes_left(&s->g) == 0 && s->bit_index == 8) { + if (*tp_index < FF_ARRAY_ELEMS(tile->tile_part) - 1) { + s->g = tile->tile_part[++(*tp_index)].tpg; + } + } + if (codsty->csty & JPEG2000_CSTY_SOP) { + if (bytestream2_peek_be32(&s->g) == JPEG2000_SOP_FIXED_BYTES) + bytestream2_skip(&s->g, JPEG2000_SOP_BYTE_LENGTH); + else + av_log(s->avctx, AV_LOG_ERROR, "SOP marker not found. instead %X\n", bytestream2_peek_be32(&s->g)); + } +} + static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, int *tp_index, Jpeg2000CodingStyle *codsty, Jpeg2000ResLevel *rlevel, int precno, @@ -934,19 +1110,17 @@ if (layno < rlevel->band[0].prec[precno].decoded_layers) return 0; rlevel->band[0].prec[precno].decoded_layers = layno + 1; - - if (bytestream2_get_bytes_left(&s->g) == 0 && s->bit_index == 8) { - if (*tp_index < FF_ARRAY_ELEMS(tile->tile_part) - 1) { - s->g = tile->tile_part[++(*tp_index)].tpg; - } - } - - if (bytestream2_peek_be32(&s->g) == JPEG2000_SOP_FIXED_BYTES) - bytestream2_skip(&s->g, JPEG2000_SOP_BYTE_LENGTH); + // Select stream to read from + if (s->has_ppm) + select_header(s, tile, tp_index); + else if (tile->has_ppt) + s->g = tile->packed_headers_stream; + else + select_stream(s, tile, tp_index, codsty); if (!(ret = get_bits(s, 1))) { jpeg2000_flush(s); - return 0; + goto skip_data; } else if (ret < 0) return ret; @@ -1052,6 +1226,14 @@ av_log(s->avctx, AV_LOG_ERROR, "EPH marker not found. instead %X\n", bytestream2_peek_be32(&s->g)); } + // Save state of stream + if (s->has_ppm) { + tile->tile_part[*tp_index].header_tpg = s->g; + select_stream(s, tile, tp_index, codsty); + } else if (tile->has_ppt) { + tile->packed_headers_stream = s->g; + select_stream(s, tile, tp_index, codsty); + } for (bandno = 0; bandno < rlevel->nbands; bandno++) { Jpeg2000Band *band = rlevel->band + bandno; Jpeg2000Prec *prec = band->prec + precno; @@ -1093,6 +1275,25 @@ av_freep(&cblk->lengthinc); } } + // Save state of stream + tile->tile_part[*tp_index].tpg = s->g; + return 0; + +skip_data: + if (codsty->csty & JPEG2000_CSTY_EPH) { + if (bytestream2_peek_be16(&s->g) == JPEG2000_EPH) + bytestream2_skip(&s->g, 2); + else + av_log(s->avctx, AV_LOG_ERROR, "EPH marker not found. instead %X\n", bytestream2_peek_be32(&s->g)); + } + if (s->has_ppm) { + tile->tile_part[*tp_index].header_tpg = s->g; + select_stream(s, tile, tp_index, codsty); + } else if (tile->has_ppt) { + tile->packed_headers_stream = s->g; + select_stream(s, tile, tp_index, codsty); + } + tile->tile_part[*tp_index].tpg = s->g; return 0; } @@ -1256,22 +1457,28 @@ uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno; unsigned prcx, prcy; + int trx0, try0; - int xc = x / s->cdx[compno]; - int yc = y / s->cdy[compno]; + if (!s->cdx[compno] || !s->cdy[compno]) + return AVERROR_INVALIDDATA; if (reslevelno >= codsty->nreslevels) continue; - if (yc % (1LL << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check + trx0 = ff_jpeg2000_ceildiv(tile->coord[0][0], (int64_t)s->cdx[compno] << reducedresno); + try0 = ff_jpeg2000_ceildiv(tile->coord[1][0], (int64_t)s->cdy[compno] << reducedresno); + + if (!(y % ((uint64_t)s->cdy[compno] << (rlevel->log2_prec_height + reducedresno)) == 0 || + (y == tile->coord[1][0] && ((int64_t)try0 << reducedresno) % (1ULL << (reducedresno + rlevel->log2_prec_height))))) continue; - if (xc % (1LL << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check + if (!(x % ((uint64_t)s->cdx[compno] << (rlevel->log2_prec_width + reducedresno)) == 0 || + (x == tile->coord[0][0] && ((int64_t)trx0 << reducedresno) % (1ULL << (reducedresno + rlevel->log2_prec_width))))) continue; // check if a precinct exists - prcx = ff_jpeg2000_ceildivpow2(xc, reducedresno) >> rlevel->log2_prec_width; - prcy = ff_jpeg2000_ceildivpow2(yc, reducedresno) >> rlevel->log2_prec_height; + prcx = ff_jpeg2000_ceildiv(x, (int64_t)s->cdx[compno] << reducedresno) >> rlevel->log2_prec_width; + prcy = ff_jpeg2000_ceildiv(y, (int64_t)s->cdy[compno] << reducedresno) >> rlevel->log2_prec_height; prcx -= ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], reducedresno) >> rlevel->log2_prec_width; prcy -= ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], reducedresno) >> rlevel->log2_prec_height; @@ -1284,14 +1491,14 @@ continue; } - for (layno = 0; layno < LYEpoc; layno++) { - if ((ret = jpeg2000_decode_packet(s, tile, tp_index, - codsty, rlevel, - precno, layno, - qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0), - qntsty->nguardbits)) < 0) - return ret; - } + for (layno = 0; layno < LYEpoc; layno++) { + if ((ret = jpeg2000_decode_packet(s, tile, tp_index, + codsty, rlevel, + precno, layno, + qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0), + qntsty->nguardbits)) < 0) + return ret; + } } } } @@ -1326,23 +1533,30 @@ Jpeg2000Component *comp = tile->comp + compno; Jpeg2000CodingStyle *codsty = tile->codsty + compno; Jpeg2000QuantStyle *qntsty = tile->qntsty + compno; - int xc = x / s->cdx[compno]; - int yc = y / s->cdy[compno]; + + if (!s->cdx[compno] || !s->cdy[compno]) + return AVERROR_INVALIDDATA; for (reslevelno = RSpoc; reslevelno < FFMIN(codsty->nreslevels, REpoc); reslevelno++) { unsigned prcx, prcy; uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno; + int trx0, try0; - if (yc % (1LL << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check - continue; + trx0 = ff_jpeg2000_ceildiv(tile->coord[0][0], (int64_t)s->cdx[compno] << reducedresno); + try0 = ff_jpeg2000_ceildiv(tile->coord[1][0], (int64_t)s->cdy[compno] << reducedresno); - if (xc % (1LL << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check - continue; + if (!(y % ((uint64_t)s->cdy[compno] << (rlevel->log2_prec_height + reducedresno)) == 0 || + (y == tile->coord[1][0] && ((int64_t)try0 << reducedresno) % (1ULL << (reducedresno + rlevel->log2_prec_height))))) + continue; + + if (!(x % ((uint64_t)s->cdx[compno] << (rlevel->log2_prec_width + reducedresno)) == 0 || + (x == tile->coord[0][0] && ((int64_t)trx0 << reducedresno) % (1ULL << (reducedresno + rlevel->log2_prec_width))))) + continue; // check if a precinct exists - prcx = ff_jpeg2000_ceildivpow2(xc, reducedresno) >> rlevel->log2_prec_width; - prcy = ff_jpeg2000_ceildivpow2(yc, reducedresno) >> rlevel->log2_prec_height; + prcx = ff_jpeg2000_ceildiv(x, (int64_t)s->cdx[compno] << reducedresno) >> rlevel->log2_prec_width; + prcy = ff_jpeg2000_ceildiv(y, (int64_t)s->cdy[compno] << reducedresno) >> rlevel->log2_prec_height; prcx -= ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], reducedresno) >> rlevel->log2_prec_width; prcy -= ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], reducedresno) >> rlevel->log2_prec_height; @@ -1533,9 +1747,9 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, - int width, int height, int bandpos) + int width, int height, int bandpos, uint8_t roi_shift) { - int passno = cblk->npasses, pass_t = 2, bpno = cblk->nonzerobits - 1; + int passno = cblk->npasses, pass_t = 2, bpno = cblk->nonzerobits - 1 + roi_shift; int pass_cnt = 0; int vert_causal_ctx_csty_symbol = codsty->cblk_style & JPEG2000_CBLK_VSC; int term_cnt = 0; @@ -1557,8 +1771,8 @@ ff_mqc_initdec(&t1->mqc, cblk->data, 0, 1); while (passno--) { - if (bpno < 0) { - av_log(s->avctx, AV_LOG_ERROR, "bpno became negative\n"); + if (bpno < 0 || bpno > 29) { + av_log(s->avctx, AV_LOG_ERROR, "bpno became invalid\n"); return AVERROR_INVALIDDATA; } switch(pass_t) { @@ -1601,14 +1815,31 @@ pass_cnt ++; } - if (cblk->data + cblk->length - 2*(term_cnt < cblk->nb_terminations) != t1->mqc.bp) { + if (cblk->data + cblk->length - 2 > t1->mqc.bp) { av_log(s->avctx, AV_LOG_WARNING, "End mismatch %"PTRDIFF_SPECIFIER"\n", - cblk->data + cblk->length - 2*(term_cnt < cblk->nb_terminations) - t1->mqc.bp); + cblk->data + cblk->length - 2 - t1->mqc.bp); + } + + if (cblk->data + cblk->length < t1->mqc.bp) { + av_log(s->avctx, AV_LOG_WARNING, "Synthetic End of Stream Marker Read.\n"); } return 1; } +static inline int roi_shift_param(Jpeg2000Component *comp, + int quan_parameter) +{ + uint8_t roi_shift; + int val; + roi_shift = comp->roi_shift; + val = (quan_parameter < 0)?-quan_parameter:quan_parameter; + + if (val > (1 << roi_shift)) + return (quan_parameter < 0)?-(val >> roi_shift):(val >> roi_shift); + return quan_parameter; +} + /* TODO: Verify dequantization for lossless case * comp->data can be float or int * band->stepsize can be float or int @@ -1693,6 +1924,19 @@ s->dsp.mct_decode[tile->codsty[0].transform](src[0], src[1], src[2], csize); } +static inline void roi_scale_cblk(Jpeg2000Cblk *cblk, + Jpeg2000Component *comp, + Jpeg2000T1Context *t1) +{ + int i, j; + int w = cblk->coord[0][1] - cblk->coord[0][0]; + for (j = 0; j < (cblk->coord[1][1] - cblk->coord[1][0]); ++j) { + int *src = t1->data + j*t1->stride; + for (i = 0; i < w; ++i) + src[i] = roi_shift_param(comp, src[i]); + } +} + static inline void tile_codeblocks(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) { Jpeg2000T1Context t1; @@ -1736,7 +1980,7 @@ int ret = decode_cblk(s, codsty, &t1, cblk, cblk->coord[0][1] - cblk->coord[0][0], cblk->coord[1][1] - cblk->coord[1][0], - bandpos); + bandpos, comp->roi_shift); if (ret) coded = 1; else @@ -1744,6 +1988,8 @@ x = cblk->coord[0][0] - band->coord[0][0]; y = cblk->coord[1][0] - band->coord[1][0]; + if (comp->roi_shift) + roi_scale_cblk(cblk, comp, &t1); if (codsty->transform == FF_DWT97) dequantization_float(x, y, cblk, comp, &t1, band); else if (codsty->transform == FF_DWT97_INT) @@ -1780,18 +2026,23 @@ float *datap = comp->f_data; \ int32_t *i_datap = comp->i_data; \ int cbps = s->cbps[compno]; \ - int w = tile->comp[compno].coord[0][1] - s->image_offset_x; \ + int w = tile->comp[compno].coord[0][1] - \ + ff_jpeg2000_ceildiv(s->image_offset_x, s->cdx[compno]); \ + int h = tile->comp[compno].coord[1][1] - \ + ff_jpeg2000_ceildiv(s->image_offset_y, s->cdy[compno]); \ int plane = 0; \ \ if (planar) \ plane = s->cdef[compno] ? s->cdef[compno]-1 : (s->ncomponents-1); \ \ - y = tile->comp[compno].coord[1][0] - s->image_offset_y / s->cdy[compno]; \ + y = tile->comp[compno].coord[1][0] - \ + ff_jpeg2000_ceildiv(s->image_offset_y, s->cdy[compno]); \ line = (PIXEL *)picture->data[plane] + y * (picture->linesize[plane] / sizeof(PIXEL));\ - for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y++) { \ + for (; y < h; y++) { \ PIXEL *dst; \ \ - x = tile->comp[compno].coord[0][0] - s->image_offset_x / s->cdx[compno]; \ + x = tile->comp[compno].coord[0][0] - \ + ff_jpeg2000_ceildiv(s->image_offset_x, s->cdx[compno]); \ dst = line + x * pixelsize + compno*!planar; \ \ if (codsty->transform == FF_DWT97) { \ @@ -1875,8 +2126,13 @@ ff_jpeg2000_cleanup(comp, codsty); } av_freep(&s->tile[tileno].comp); + av_freep(&s->tile[tileno].packed_headers); + s->tile[tileno].packed_headers_size = 0; } } + av_freep(&s->packed_headers); + s->packed_headers_size = 0; + memset(&s->packed_headers_stream, 0, sizeof(s->packed_headers_stream)); av_freep(&s->tile); memset(s->codsty, 0, sizeof(s->codsty)); memset(s->qntsty, 0, sizeof(s->qntsty)); @@ -1905,7 +2161,8 @@ marker = bytestream2_get_be16u(&s->g); oldpos = bytestream2_tell(&s->g); - + if (marker >= 0xFF30 && marker <= 0xFF3F) + continue; if (marker == JPEG2000_SOD) { Jpeg2000Tile *tile; Jpeg2000TilePart *tp; @@ -1925,6 +2182,18 @@ av_log(s->avctx, AV_LOG_ERROR, "Invalid tpend\n"); return AVERROR_INVALIDDATA; } + + if (s->has_ppm) { + uint32_t tp_header_size = bytestream2_get_be32(&s->packed_headers_stream); + if (bytestream2_get_bytes_left(&s->packed_headers_stream) < tp_header_size) + return AVERROR_INVALIDDATA; + bytestream2_init(&tp->header_tpg, s->packed_headers_stream.buffer, tp_header_size); + bytestream2_skip(&s->packed_headers_stream, tp_header_size); + } + if (tile->has_ppt && tile->tp_idx == 0) { + bytestream2_init(&tile->packed_headers_stream, tile->packed_headers, tile->packed_headers_size); + } + bytestream2_init(&tp->tpg, s->g.buffer, tp->tp_end - s->g.buffer); bytestream2_skip(&s->g, tp->tp_end - s->g.buffer); @@ -1935,8 +2204,12 @@ len = bytestream2_get_be16(&s->g); if (len < 2 || bytestream2_get_bytes_left(&s->g) < len - 2) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid len %d left=%d\n", len, bytestream2_get_bytes_left(&s->g)); - return AVERROR_INVALIDDATA; + if (s->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid len %d left=%d\n", len, bytestream2_get_bytes_left(&s->g)); + return AVERROR_INVALIDDATA; + } + av_log(s->avctx, AV_LOG_WARNING, "Missing EOC Marker.\n"); + break; } switch (marker) { @@ -1955,6 +2228,9 @@ case JPEG2000_COD: ret = get_cod(s, codsty, properties); break; + case JPEG2000_RGN: + ret = get_rgn(s, len); + break; case JPEG2000_QCC: ret = get_qcc(s, len, qntsty, properties); break; @@ -1965,6 +2241,12 @@ ret = get_poc(s, len, poc); break; case JPEG2000_SOT: + if (!s->in_tile_headers) { + s->in_tile_headers = 1; + if (s->has_ppm) { + bytestream2_init(&s->packed_headers_stream, s->packed_headers, s->packed_headers_size); + } + } if (!(ret = get_sot(s, len))) { av_assert1(s->curtileno >= 0); codsty = s->tile[s->curtileno].codsty; @@ -1979,6 +2261,9 @@ // the comment is ignored bytestream2_skip(&s->g, len - 2); break; + case JPEG2000_CRG: + ret = read_crg(s, len); + break; case JPEG2000_TLM: // Tile-part lengths ret = get_tlm(s, len); @@ -1987,6 +2272,24 @@ // Packet length, tile-part header ret = get_plt(s, len); break; + case JPEG2000_PPM: + // Packed headers, main header + if (s->in_tile_headers) { + av_log(s->avctx, AV_LOG_ERROR, "PPM Marker can only be in Main header\n"); + return AVERROR_INVALIDDATA; + } + ret = get_ppm(s, len); + break; + case JPEG2000_PPT: + // Packed headers, tile-part header + if (s->has_ppm) { + av_log(s->avctx, AV_LOG_ERROR, + "Cannot have both PPT and PPM marker.\n"); + return AVERROR_INVALIDDATA; + } + + ret = get_ppt(s, len); + break; default: av_log(s->avctx, AV_LOG_ERROR, "unsupported marker 0x%.4"PRIX16" at pos 0x%X\n", @@ -2016,7 +2319,6 @@ if ((ret = init_tile(s, tileno)) < 0) return ret; - s->g = tile->tile_part[0].tpg; if ((ret = jpeg2000_decode_packets(s, tile)) < 0) return ret; } @@ -2040,8 +2342,12 @@ return 0; } atom_size = bytestream2_get_be32u(&s->g); + if (atom_size < 16 || (int64_t)bytestream2_tell(&s->g) + atom_size - 16 > INT_MAX) + return AVERROR_INVALIDDATA; atom_end = bytestream2_tell(&s->g) + atom_size - 16; } else { + if (atom_size < 8 || (int64_t)bytestream2_tell(&s->g) + atom_size - 8 > INT_MAX) + return AVERROR_INVALIDDATA; atom_end = bytestream2_tell(&s->g) + atom_size - 8; } diff -Nru ffmpeg-4.2.2/libavcodec/jpeg2000dwt.c ffmpeg-4.4/libavcodec/jpeg2000dwt.c --- ffmpeg-4.2.2/libavcodec/jpeg2000dwt.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/jpeg2000dwt.c 2020-07-09 09:17:46.000000000 +0000 @@ -255,7 +255,7 @@ line += 5; for (i = 0; i < w * h; i++) - t[i] <<= I_PRESHIFT; + t[i] *= 1 << I_PRESHIFT; for (lev = s->ndeclevels-1; lev >= 0; lev--){ int lh = s->linelen[lev][0], diff -Nru ffmpeg-4.2.2/libavcodec/jpeg2000.h ffmpeg-4.4/libavcodec/jpeg2000.h --- ffmpeg-4.2.2/libavcodec/jpeg2000.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/jpeg2000.h 2021-04-08 21:28:39.000000000 +0000 @@ -40,15 +40,15 @@ JPEG2000_SIZ = 0xff51, // image and tile size JPEG2000_COD, // coding style default JPEG2000_COC, // coding style component - JPEG2000_TLM = 0xff55, // packed packet headers, tile-part header - JPEG2000_PLM = 0xff57, // tile-part lengths - JPEG2000_PLT, // packet length, main header + JPEG2000_TLM = 0xff55, // tile-part length, main header + JPEG2000_PLM = 0xff57, // packet length, main header + JPEG2000_PLT, // packet length, tile-part header JPEG2000_QCD = 0xff5c, // quantization default JPEG2000_QCC, // quantization component JPEG2000_RGN, // region of interest JPEG2000_POC, // progression order change - JPEG2000_PPM, // packet length, tile-part header - JPEG2000_PPT, // packed packet headers, main header + JPEG2000_PPM, // packed packet headers, main header + JPEG2000_PPT, // packed packet headers, tile-part header JPEG2000_CRG = 0xff63, // component registration JPEG2000_COM, // comment JPEG2000_SOT = 0xff90, // start of tile-part @@ -127,6 +127,7 @@ typedef struct Jpeg2000TgtNode { uint8_t val; + uint8_t temp_val; uint8_t vis; struct Jpeg2000TgtNode *parent; } Jpeg2000TgtNode; @@ -144,6 +145,7 @@ uint8_t prog_order; // progression order uint8_t log2_prec_widths[JPEG2000_MAX_RESLEVELS]; // precincts size according resolution levels uint8_t log2_prec_heights[JPEG2000_MAX_RESLEVELS]; // TODO: initialize prec_size array with 0? + uint8_t init; } Jpeg2000CodingStyle; typedef struct Jpeg2000QuantStyle { @@ -160,10 +162,19 @@ int flushed_len; } Jpeg2000Pass; +typedef struct Jpeg2000Layer { + uint8_t *data_start; + int data_len; + int npasses; + double disto; + int cum_passes; +} Jpeg2000Layer; + typedef struct Jpeg2000Cblk { uint8_t npasses; uint8_t ninclpasses; // number coding of passes included in codestream uint8_t nonzerobits; + uint8_t incl; uint16_t length; uint16_t *lengthinc; uint8_t nb_lengthinc; @@ -174,6 +185,7 @@ int nb_terminationsinc; int *data_start; Jpeg2000Pass *passes; + Jpeg2000Layer *layers; int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} } Jpeg2000Cblk; // code block @@ -210,6 +222,7 @@ int *i_data; int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} -- can be reduced with lowres option int coord_o[2][2]; // border coordinates {{x0, x1}, {y0, y1}} -- original values from jpeg2000 headers + uint8_t roi_shift; // ROI scaling value for the component } Jpeg2000Component; /* misc tools */ @@ -218,9 +231,9 @@ return -((-(int64_t)a) >> b); } -static inline int ff_jpeg2000_ceildiv(int a, int b) +static inline int ff_jpeg2000_ceildiv(int a, int64_t b) { - return (a + (int64_t)b - 1) / b; + return (a + b - 1) / b; } /* TIER-1 routines */ @@ -288,4 +301,7 @@ return 0; } +int32_t ff_tag_tree_size(int w, int h); +void ff_tag_tree_zero(Jpeg2000TgtNode *t, int w, int h, int val); + #endif /* AVCODEC_JPEG2000_H */ diff -Nru ffmpeg-4.2.2/libavcodec/jpeg2000_parser.c ffmpeg-4.4/libavcodec/jpeg2000_parser.c --- ffmpeg-4.2.2/libavcodec/jpeg2000_parser.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/jpeg2000_parser.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,190 @@ +/* + * JPEG2000 parser + * Copyright (c) 2020 Gautam Ramakrishnan + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * JPEG2000 parser. + */ + +#include "parser.h" + +/* Whether frame is jp2 file or codestream +*/ +enum frame_type { + jp2_file = 1, + j2k_cstream +}; + +typedef struct JPEG2000ParserContext { + ParseContext pc; + uint64_t bytes_read; + uint64_t fheader_state; + uint32_t skip_bytes; // skip bytes inside codestream data + enum frame_type ft; // 1 if file, 2 if codestream + uint8_t fheader_read; // are we reading + uint8_t reading_file_header; + uint8_t skipped_codestream; + uint8_t codestream_frame_end; + uint8_t read_tp; + uint8_t in_codestream; +} JPEG2000ParserContext; + +static inline void reset_context(JPEG2000ParserContext *m) +{ + ParseContext *pc = &m->pc; + + pc->frame_start_found= 0; + pc->state = 0; + m->bytes_read = 0; + m->ft = 0; + m->skipped_codestream = 0; + m->fheader_read = 0; + m->codestream_frame_end = 0; + m->skip_bytes = 0; + m->read_tp = 0; + m->in_codestream = 0; +} + +/* Returns 1 if marker has any data which can be skipped +*/ +static uint8_t info_marker(uint16_t marker) +{ + if (marker == 0xFF92 || marker == 0xFF4F || + marker == 0xFF90 || marker == 0xFF93 || + marker == 0xFFD9) + return 0; + else + if (marker > 0xFF00) return 1; + return 0; +} + +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or -1 + */ +static int find_frame_end(JPEG2000ParserContext *m, const uint8_t *buf, int buf_size) +{ + ParseContext *pc= &m->pc; + int i; + uint32_t state; + uint64_t state64; + state= pc->state; + state64 = pc->state64; + if (buf_size == 0) { + return 0; + } + + for (i = 0; i < buf_size; i++) { + state = state << 8 | buf[i]; + state64 = state64 << 8 | buf[i]; + m->bytes_read++; + if (m->skip_bytes) { + m->skip_bytes--; + continue; + } + if (m->codestream_frame_end) { + reset_context(m); + return i; + } + if (m->read_tp) { // Find out how many bytes inside Tile part codestream to skip. + if (m->read_tp == 1) { + m->skip_bytes = (state64 & 0xFFFFFFFF) - 10 > 0? + (state64 & 0xFFFFFFFF) - 10 : 0; + } + m->read_tp--; + } + if (m->fheader_read) { + if (m->fheader_read == 1) { + if (state64 == 0x6A5020200D0A870A) { // JP2 signature box value. + if (pc->frame_start_found) { + pc->frame_start_found = 0; + reset_context(m); + return i - 11; + } else { + pc->frame_start_found = 1; + m->ft = jp2_file; + } + } + } + m->fheader_read--; + } + if (state == 0x0000000C && m->bytes_read >= 3) { // Indicates start of JP2 file. Check signature next. + m->fheader_read = 8; + } else if ((state & 0xFFFF) == 0xFF4F) { + m->in_codestream = 1; + if (!pc->frame_start_found) { + pc->frame_start_found = 1; + m->ft = j2k_cstream; + } else if (pc->frame_start_found && m->ft == jp2_file && m->skipped_codestream) { + reset_context(m); + return i - 1; + } + } else if ((state & 0xFFFF) == 0xFFD9) { + if (pc->frame_start_found && m->ft == jp2_file) { + m->skipped_codestream = 1; + } else if (pc->frame_start_found && m->ft == j2k_cstream) { + m->codestream_frame_end = 1; + } + m->in_codestream = 0; + } else if (m->in_codestream && (state & 0xFFFF) == 0xFF90) { // Are we in tile part header? + m->read_tp = 8; + } else if (pc->frame_start_found && info_marker((state & 0xFFFF0000)>>16) && m->in_codestream) { + m->skip_bytes = (state & 0xFFFF) - 2; + } + } + + pc->state = state; + pc->state64 = state64; + return END_NOT_FOUND; +} + +static int jpeg2000_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + JPEG2000ParserContext *m = s->priv_data; + ParseContext *pc = &m->pc; + int next; + + if(s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next= buf_size; + } else { + next= find_frame_end(m, buf, buf_size); + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_jpeg2000_parser = { + .codec_ids = { AV_CODEC_ID_JPEG2000 }, + .priv_data_size = sizeof(JPEG2000ParserContext), + .parser_parse = jpeg2000_parse, + .parser_close = ff_parse_close, +}; diff -Nru ffmpeg-4.2.2/libavcodec/jpeglsdec.c ffmpeg-4.4/libavcodec/jpeglsdec.c --- ffmpeg-4.2.2/libavcodec/jpeglsdec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/jpeglsdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -149,7 +149,7 @@ { int k, ret; - for (k = 0; (state->N[Q] << k) < state->A[Q]; k++) + for (k = 0; ((unsigned)state->N[Q] << k) < state->A[Q]; k++) ; #ifdef JLS_BROKEN @@ -222,7 +222,7 @@ /** * Decode one line of image */ -static inline void ls_decode_line(JLSState *state, MJpegDecodeContext *s, +static inline int ls_decode_line(JLSState *state, MJpegDecodeContext *s, void *last, void *dst, int last2, int w, int stride, int comp, int bits) { @@ -234,7 +234,7 @@ int err, pred; if (get_bits_left(&s->gb) <= 0) - return; + return AVERROR_INVALIDDATA; /* compute gradients */ Ra = x ? R(dst, x - stride) : R(last, x); @@ -263,11 +263,11 @@ } /* if EOL reached, we stop decoding */ if (r != 1 << ff_log2_run[state->run_index[comp]]) - return; + return 0; if (state->run_index[comp] < 31) state->run_index[comp]++; if (x + stride > w) - return; + return 0; } /* decode aborted run */ r = ff_log2_run[state->run_index[comp]]; @@ -284,7 +284,7 @@ if (x >= w) { av_log(NULL, AV_LOG_ERROR, "run overflow\n"); av_assert0(x <= w); - return; + return AVERROR_INVALIDDATA; } /* decode run termination value */ @@ -341,6 +341,8 @@ W(dst, x, pred); x += stride; } + + return 0; } int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, @@ -350,6 +352,7 @@ uint8_t *zero, *last, *cur; JLSState *state; int off = 0, stride = 1, width, shift, ret = 0; + int decoded_height = 0; zero = av_mallocz(s->picture_ptr->linesize[0]); if (!zero) @@ -407,13 +410,16 @@ width = s->width * stride; cur += off; for (i = 0; i < s->height; i++) { + int ret; if (s->bits <= 8) { - ls_decode_line(state, s, last, cur, t, width, stride, off, 8); + ret = ls_decode_line(state, s, last, cur, t, width, stride, off, 8); t = last[0]; } else { - ls_decode_line(state, s, last, cur, t, width, stride, off, 16); + ret = ls_decode_line(state, s, last, cur, t, width, stride, off, 16); t = *((uint16_t *)last); } + if (ret < 0) + break; last = cur; cur += s->picture_ptr->linesize[0]; @@ -422,6 +428,7 @@ skip_bits(&s->gb, 16); /* skip RSTn */ } } + decoded_height = i; } else if (ilv == 1) { /* line interleaving */ int j; int Rc[3] = { 0, 0, 0 }; @@ -429,9 +436,12 @@ memset(cur, 0, s->picture_ptr->linesize[0]); width = s->width * stride; for (i = 0; i < s->height; i++) { + int ret; for (j = 0; j < stride; j++) { - ls_decode_line(state, s, last + j, cur + j, + ret = ls_decode_line(state, s, last + j, cur + j, Rc[j], width, stride, j, 8); + if (ret < 0) + break; Rc[j] = last[j]; if (s->restart_interval && !--s->restart_count) { @@ -439,9 +449,12 @@ skip_bits(&s->gb, 16); /* skip RSTn */ } } + if (ret < 0) + break; last = cur; cur += s->picture_ptr->linesize[0]; } + decoded_height = i; } else if (ilv == 2) { /* sample interleaving */ avpriv_report_missing_feature(s->avctx, "Sample interleaved images"); ret = AVERROR_PATCHWELCOME; @@ -507,7 +520,7 @@ if (s->bits <= 8) { uint8_t *src = s->picture_ptr->data[0]; - for (i = 0; i < s->height; i++) { + for (i = 0; i < decoded_height; i++) { for (x = off; x < w; x += stride) src[x] <<= shift; src += s->picture_ptr->linesize[0]; @@ -515,7 +528,7 @@ } else { uint16_t *src = (uint16_t *)s->picture_ptr->data[0]; - for (i = 0; i < s->height; i++) { + for (i = 0; i < decoded_height; i++) { for (x = 0; x < w; x++) src[x] <<= shift; src += s->picture_ptr->linesize[0] / 2; @@ -538,7 +551,8 @@ .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, - .decode = ff_mjpeg_decode_frame, + .receive_frame = ff_mjpeg_receive_frame, .capabilities = AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_SETS_PKT_DTS, }; diff -Nru ffmpeg-4.2.2/libavcodec/jpeglsenc.c ffmpeg-4.4/libavcodec/jpeglsenc.c --- ffmpeg-4.2.2/libavcodec/jpeglsenc.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/jpeglsenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,7 @@ */ #include "avcodec.h" +#include "bytestream.h" #include "get_bits.h" #include "put_bits.h" #include "golomb.h" @@ -41,6 +42,18 @@ int pred; } JPEGLSContext; +static inline void put_marker_byteu(PutByteContext *pb, enum JpegMarker code) +{ + bytestream2_put_byteu(pb, 0xff); + bytestream2_put_byteu(pb, code); +} + +static inline void put_marker_byte(PutByteContext *pb, enum JpegMarker code) +{ + bytestream2_put_byte(pb, 0xff); + bytestream2_put_byte(pb, code); +} + /** * Encode error from regular symbol */ @@ -128,21 +141,19 @@ * Encode one line of image */ static inline void ls_encode_line(JLSState *state, PutBitContext *pb, - void *last, void *cur, int last2, int w, + void *tmp, const void *in, int last2, int w, int stride, int comp, int bits) { int x = 0; - int Ra, Rb, Rc, Rd; + int Ra = R(tmp, 0), Rb, Rc = last2, Rd; int D0, D1, D2; while (x < w) { int err, pred, sign; /* compute gradients */ - Ra = x ? R(cur, x - stride) : R(last, x); - Rb = R(last, x); - Rc = x ? R(last, x - stride) : last2; - Rd = (x >= w - stride) ? R(last, x) : R(last, x + stride); + Rb = R(tmp, x); + Rd = (x >= w - stride) ? R(tmp, x) : R(tmp, x + stride); D0 = Rd - Rb; D1 = Rb - Rc; D2 = Rc - Ra; @@ -155,18 +166,18 @@ run = 0; RUNval = Ra; - while (x < w && (FFABS(R(cur, x) - RUNval) <= state->near)) { + while (x < w && (FFABS(R(in, x) - RUNval) <= state->near)) { run++; - W(cur, x, Ra); + W(tmp, x, Ra); x += stride; } ls_encode_run(state, pb, run, comp, x < w); if (x >= w) return; - Rb = R(last, x); + Rb = R(tmp, x); RItype = FFABS(Ra - Rb) <= state->near; pred = RItype ? Ra : Rb; - err = R(cur, x) - pred; + err = R(in, x) - pred; if (!RItype && Ra > Rb) err = -err; @@ -181,8 +192,10 @@ Ra = av_clip(pred + err * state->twonear, 0, state->maxval); else Ra = av_clip(pred - err * state->twonear, 0, state->maxval); - W(cur, x, Ra); - } + } else + Ra = R(in, x); + W(tmp, x, Ra); + if (err < 0) err += state->range; if (err >= state->range + 1 >> 1) @@ -205,11 +218,11 @@ context = -context; sign = 1; pred = av_clip(pred - state->C[context], 0, state->maxval); - err = pred - R(cur, x); + err = pred - R(in, x); } else { sign = 0; pred = av_clip(pred + state->C[context], 0, state->maxval); - err = R(cur, x) - pred; + err = R(in, x) - pred; } if (state->near) { @@ -221,16 +234,18 @@ Ra = av_clip(pred + err * state->twonear, 0, state->maxval); else Ra = av_clip(pred - err * state->twonear, 0, state->maxval); - W(cur, x, Ra); - } + } else + Ra = R(in, x); + W(tmp, x, Ra); ls_encode_regular(state, pb, context, err); } + Rc = Rb; x += stride; } } -static void ls_store_lse(JLSState *state, PutBitContext *pb) +static void ls_store_lse(JLSState *state, PutByteContext *pb) { /* Test if we have default params and don't need to store LSE */ JLSState state2 = { 0 }; @@ -243,14 +258,14 @@ state->reset == state2.reset) return; /* store LSE type 1 */ - put_marker(pb, LSE); - put_bits(pb, 16, 13); - put_bits(pb, 8, 1); - put_bits(pb, 16, state->maxval); - put_bits(pb, 16, state->T1); - put_bits(pb, 16, state->T2); - put_bits(pb, 16, state->T3); - put_bits(pb, 16, state->reset); + put_marker_byteu(pb, LSE); + bytestream2_put_be16u(pb, 13); + bytestream2_put_byteu(pb, 1); + bytestream2_put_be16u(pb, state->maxval); + bytestream2_put_be16u(pb, state->T1); + bytestream2_put_be16u(pb, state->T2); + bytestream2_put_be16u(pb, state->T3); + bytestream2_put_be16u(pb, state->reset); } static int encode_picture_ls(AVCodecContext *avctx, AVPacket *pkt, @@ -258,13 +273,12 @@ { JPEGLSContext *ctx = avctx->priv_data; const AVFrame *const p = pict; - PutBitContext pb, pb2; + PutByteContext pb; + PutBitContext pb2; GetBitContext gb; - uint8_t *buf2 = NULL; - uint8_t *zero = NULL; - uint8_t *cur = NULL; + const uint8_t *in; uint8_t *last = NULL; - JLSState *state = NULL; + JLSState state = { 0 }; int i, size, ret; int comps; @@ -285,72 +299,65 @@ AV_INPUT_BUFFER_MIN_SIZE, 0)) < 0) return ret; - buf2 = av_malloc(pkt->size); - if (!buf2) - goto memfail; + last = av_malloc((unsigned)pkt->size + FFABS(p->linesize[0])); + if (!last) + return AVERROR(ENOMEM); + memset(last, 0, FFABS(p->linesize[0])); - init_put_bits(&pb, pkt->data, pkt->size); - init_put_bits(&pb2, buf2, pkt->size); + bytestream2_init_writer(&pb, pkt->data, pkt->size); + init_put_bits(&pb2, last + FFABS(p->linesize[0]), pkt->size); /* write our own JPEG header, can't use mjpeg_picture_header */ - put_marker(&pb, SOI); - put_marker(&pb, SOF48); - put_bits(&pb, 16, 8 + comps * 3); // header size depends on components - put_bits(&pb, 8, (avctx->pix_fmt == AV_PIX_FMT_GRAY16) ? 16 : 8); // bpp - put_bits(&pb, 16, avctx->height); - put_bits(&pb, 16, avctx->width); - put_bits(&pb, 8, comps); // components + put_marker_byteu(&pb, SOI); + put_marker_byteu(&pb, SOF48); + bytestream2_put_be16u(&pb, 8 + comps * 3); // header size depends on components + bytestream2_put_byteu(&pb, (avctx->pix_fmt == AV_PIX_FMT_GRAY16) ? 16 : 8); // bpp + bytestream2_put_be16u(&pb, avctx->height); + bytestream2_put_be16u(&pb, avctx->width); + bytestream2_put_byteu(&pb, comps); // components for (i = 1; i <= comps; i++) { - put_bits(&pb, 8, i); // component ID - put_bits(&pb, 8, 0x11); // subsampling: none - put_bits(&pb, 8, 0); // Tiq, used by JPEG-LS ext + bytestream2_put_byteu(&pb, i); // component ID + bytestream2_put_byteu(&pb, 0x11); // subsampling: none + bytestream2_put_byteu(&pb, 0); // Tiq, used by JPEG-LS ext } - put_marker(&pb, SOS); - put_bits(&pb, 16, 6 + comps * 2); - put_bits(&pb, 8, comps); + put_marker_byteu(&pb, SOS); + bytestream2_put_be16u(&pb, 6 + comps * 2); + bytestream2_put_byteu(&pb, comps); for (i = 1; i <= comps; i++) { - put_bits(&pb, 8, i); // component ID - put_bits(&pb, 8, 0); // mapping index: none + bytestream2_put_byteu(&pb, i); // component ID + bytestream2_put_byteu(&pb, 0); // mapping index: none } - put_bits(&pb, 8, ctx->pred); - put_bits(&pb, 8, (comps > 1) ? 1 : 0); // interleaving: 0 - plane, 1 - line - put_bits(&pb, 8, 0); // point transform: none - - state = av_mallocz(sizeof(JLSState)); - if (!state) - goto memfail; + bytestream2_put_byteu(&pb, ctx->pred); + bytestream2_put_byteu(&pb, (comps > 1) ? 1 : 0); // interleaving: 0 - plane, 1 - line + bytestream2_put_byteu(&pb, 0); // point transform: none /* initialize JPEG-LS state from JPEG parameters */ - state->near = ctx->pred; - state->bpp = (avctx->pix_fmt == AV_PIX_FMT_GRAY16) ? 16 : 8; - ff_jpegls_reset_coding_parameters(state, 0); - ff_jpegls_init_state(state); - - ls_store_lse(state, &pb); - - zero = last = av_mallocz(FFABS(p->linesize[0])); - if (!zero) - goto memfail; + state.near = ctx->pred; + state.bpp = (avctx->pix_fmt == AV_PIX_FMT_GRAY16) ? 16 : 8; + ff_jpegls_reset_coding_parameters(&state, 0); + ff_jpegls_init_state(&state); - cur = p->data[0]; + ls_store_lse(&state, &pb); + + in = p->data[0]; if (avctx->pix_fmt == AV_PIX_FMT_GRAY8) { int t = 0; for (i = 0; i < avctx->height; i++) { - ls_encode_line(state, &pb2, last, cur, t, avctx->width, 1, 0, 8); - t = last[0]; - last = cur; - cur += p->linesize[0]; + int last0 = last[0]; + ls_encode_line(&state, &pb2, last, in, t, avctx->width, 1, 0, 8); + t = last0; + in += p->linesize[0]; } } else if (avctx->pix_fmt == AV_PIX_FMT_GRAY16) { int t = 0; for (i = 0; i < avctx->height; i++) { - ls_encode_line(state, &pb2, last, cur, t, avctx->width, 1, 0, 16); - t = *((uint16_t *)last); - last = cur; - cur += p->linesize[0]; + int last0 = *((uint16_t *)last); + ls_encode_line(&state, &pb2, last, in, t, avctx->width, 1, 0, 16); + t = last0; + in += p->linesize[0]; } } else if (avctx->pix_fmt == AV_PIX_FMT_RGB24) { int j, width; @@ -359,12 +366,12 @@ width = avctx->width * 3; for (i = 0; i < avctx->height; i++) { for (j = 0; j < 3; j++) { - ls_encode_line(state, &pb2, last + j, cur + j, Rc[j], + int last0 = last[j]; + ls_encode_line(&state, &pb2, last + j, in + j, Rc[j], width, 3, j, 8); - Rc[j] = last[j]; + Rc[j] = last0; } - last = cur; - cur += p->linesize[0]; + in += p->linesize[0]; } } else if (avctx->pix_fmt == AV_PIX_FMT_BGR24) { int j, width; @@ -373,18 +380,15 @@ width = avctx->width * 3; for (i = 0; i < avctx->height; i++) { for (j = 2; j >= 0; j--) { - ls_encode_line(state, &pb2, last + j, cur + j, Rc[j], + int last0 = last[j]; + ls_encode_line(&state, &pb2, last + j, in + j, Rc[j], width, 3, j, 8); - Rc[j] = last[j]; + Rc[j] = last0; } - last = cur; - cur += p->linesize[0]; + in += p->linesize[0]; } } - av_freep(&zero); - av_freep(&state); - /* the specification says that after doing 0xff escaping unused bits in * the last byte must be set to 0, so just append 7 "optional" zero bits * to avoid special-casing. */ @@ -392,37 +396,28 @@ size = put_bits_count(&pb2); flush_put_bits(&pb2); /* do escape coding */ - init_get_bits(&gb, buf2, size); + init_get_bits(&gb, pb2.buf, size); size -= 7; while (get_bits_count(&gb) < size) { int v; v = get_bits(&gb, 8); - put_bits(&pb, 8, v); + bytestream2_put_byte(&pb, v); if (v == 0xFF) { v = get_bits(&gb, 7); - put_bits(&pb, 8, v); + bytestream2_put_byte(&pb, v); } } - avpriv_align_put_bits(&pb); - av_freep(&buf2); + av_freep(&last); /* End of image */ - put_marker(&pb, EOI); - flush_put_bits(&pb); + put_marker_byte(&pb, EOI); emms_c(); - pkt->size = put_bits_count(&pb) >> 3; + pkt->size = bytestream2_tell_p(&pb); pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; return 0; - -memfail: - av_packet_unref(pkt); - av_freep(&buf2); - av_freep(&state); - av_freep(&zero); - return AVERROR(ENOMEM); } static av_cold int encode_init_ls(AVCodecContext *ctx) @@ -471,7 +466,7 @@ .priv_data_size = sizeof(JPEGLSContext), .priv_class = &jpegls_class, .init = encode_init_ls, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .encode2 = encode_picture_ls, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB24, diff -Nru ffmpeg-4.2.2/libavcodec/jpegls.h ffmpeg-4.4/libavcodec/jpegls.h --- ffmpeg-4.2.2/libavcodec/jpegls.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/jpegls.h 2021-04-08 21:28:39.000000000 +0000 @@ -34,10 +34,6 @@ #undef near /* This file uses struct member 'near' which in windows.h is defined as empty. */ -typedef struct JpeglsContext { - AVCodecContext *avctx; -} JpeglsContext; - typedef struct JLSState { int T1, T2, T3; int A[367], B[367], C[365], N[367]; @@ -99,7 +95,7 @@ static inline int ff_jpegls_update_state_regular(JLSState *state, int Q, int err) { - if(FFABS(err) > 0xFFFF) + if(FFABS(err) > 0xFFFF || FFABS(err) > INT_MAX - state->A[Q]) return -0x10000; state->A[Q] += FFABS(err); err *= state->twonear; diff -Nru ffmpeg-4.2.2/libavcodec/jpegtables.c ffmpeg-4.4/libavcodec/jpegtables.c --- ffmpeg-4.2.2/libavcodec/jpegtables.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/jpegtables.c 2021-04-08 21:28:39.000000000 +0000 @@ -122,24 +122,3 @@ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; - -/* isn't this function nicer than the one in the libjpeg ? */ -void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, - const uint8_t *bits_table, - const uint8_t *val_table) -{ - int i, j, k,nb, code, sym; - - code = 0; - k = 0; - for(i=1;i<=16;i++) { - nb = bits_table[i]; - for(j=0;jframe)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; if (avctx->height/8 * (avctx->width/8) > 4 * video_size) { diff -Nru ffmpeg-4.2.2/libavcodec/kmvc.c ffmpeg-4.4/libavcodec/kmvc.c --- ffmpeg-4.2.2/libavcodec/kmvc.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/kmvc.c 2021-04-08 21:28:39.000000000 +0000 @@ -268,7 +268,7 @@ int i, ret; int header; int blocksize; - int pal_size; + buffer_size_t pal_size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size); bytestream2_init(&ctx->g, avpkt->data, avpkt->size); diff -Nru ffmpeg-4.2.2/libavcodec/lagarith.c ffmpeg-4.4/libavcodec/lagarith.c --- ffmpeg-4.2.2/libavcodec/lagarith.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/lagarith.c 2020-07-11 10:39:30.000000000 +0000 @@ -226,6 +226,9 @@ } } + if (scale_factor > 23) + return AVERROR_INVALIDDATA; + rac->scale = scale_factor; /* Fill probability array with cumulative probability for each symbol. */ @@ -709,16 +712,6 @@ return 0; } -#if HAVE_THREADS -static av_cold int lag_decode_init_thread_copy(AVCodecContext *avctx) -{ - LagarithContext *l = avctx->priv_data; - l->avctx = avctx; - - return 0; -} -#endif - AVCodec ff_lagarith_decoder = { .name = "lagarith", .long_name = NULL_IF_CONFIG_SMALL("Lagarith lossless"), @@ -726,7 +719,6 @@ .id = AV_CODEC_ID_LAGARITH, .priv_data_size = sizeof(LagarithContext), .init = lag_decode_init, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(lag_decode_init_thread_copy), .decode = lag_decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, }; diff -Nru ffmpeg-4.2.2/libavcodec/lcldec.c ffmpeg-4.4/libavcodec/lcldec.c --- ffmpeg-4.2.2/libavcodec/lcldec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/lcldec.c 2021-04-08 21:28:39.000000000 +0000 @@ -136,7 +136,7 @@ av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); return AVERROR_UNKNOWN; } - c->zstream.next_in = (uint8_t *)src; + c->zstream.next_in = src; c->zstream.avail_in = src_len; c->zstream.next_out = c->decomp_buf + offset; c->zstream.avail_out = c->decomp_size - offset; @@ -173,7 +173,7 @@ int uqvq, ret; unsigned int mthread_inlen, mthread_outlen; unsigned int len = buf_size; - int linesize; + int linesize, offset; if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) return ret; @@ -190,11 +190,10 @@ ; } else if (c->flags & FLAG_MULTITHREAD) { mthread_inlen = AV_RL32(buf); - if (len < 8) { + if (len < 8 || len - 8 < mthread_inlen) { av_log(avctx, AV_LOG_ERROR, "len %d is too small\n", len); return AVERROR_INVALIDDATA; } - mthread_inlen = FFMIN(mthread_inlen, len - 8); mthread_outlen = AV_RL32(buf + 4); mthread_outlen = FFMIN(mthread_outlen, c->decomp_size); mszh_dlen = mszh_decomp(buf + 8, mthread_inlen, c->decomp_buf, c->decomp_size); @@ -374,8 +373,10 @@ /* Convert colorspace */ y_out = frame->data[0] + (height - 1) * frame->linesize[0]; - u_out = frame->data[1] + (height - 1) * frame->linesize[1]; - v_out = frame->data[2] + (height - 1) * frame->linesize[2]; + offset = (height - 1) * frame->linesize[1]; + u_out = FF_PTR_ADD(frame->data[1], offset); + offset = (height - 1) * frame->linesize[2]; + v_out = FF_PTR_ADD(frame->data[2], offset); switch (c->imgtype) { case IMGTYPE_YUV111: for (row = 0; row < height; row++) { @@ -623,13 +624,6 @@ return 0; } -#if HAVE_THREADS -static int init_thread_copy(AVCodecContext *avctx) -{ - return decode_init(avctx); -} -#endif - static av_cold int decode_end(AVCodecContext *avctx) { LclDecContext * const c = avctx->priv_data; @@ -651,7 +645,6 @@ .id = AV_CODEC_ID_MSZH, .priv_data_size = sizeof(LclDecContext), .init = decode_init, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(init_thread_copy), .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, @@ -667,7 +660,6 @@ .id = AV_CODEC_ID_ZLIB, .priv_data_size = sizeof(LclDecContext), .init = decode_init, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(init_thread_copy), .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, diff -Nru ffmpeg-4.2.2/libavcodec/lclenc.c ffmpeg-4.4/libavcodec/lclenc.c --- ffmpeg-4.2.2/libavcodec/lclenc.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/lclenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -176,7 +176,7 @@ .init = encode_init, .encode2 = encode_frame, .close = encode_end, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, diff -Nru ffmpeg-4.2.2/libavcodec/libaomdec.c ffmpeg-4.4/libavcodec/libaomdec.c --- ffmpeg-4.2.2/libavcodec/libaomdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libaomdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -197,6 +197,14 @@ } if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) return ret; + + av_reduce(&picture->sample_aspect_ratio.num, + &picture->sample_aspect_ratio.den, + picture->height * img->r_w, + picture->width * img->r_h, + INT_MAX); + ff_set_sar(avctx, picture->sample_aspect_ratio); + if ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) && img->bit_depth == 8) image_copy_16_to_8(picture, img); else @@ -228,7 +236,8 @@ .init = av1_init, .close = aom_free, .decode = aom_decode, - .capabilities = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), .wrapper_name = "libaom", }; diff -Nru ffmpeg-4.2.2/libavcodec/libaomenc.c ffmpeg-4.4/libavcodec/libaomenc.c --- ffmpeg-4.2.2/libavcodec/libaomenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libaomenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -37,6 +37,7 @@ #include "av1.h" #include "avcodec.h" #include "internal.h" +#include "packet_internal.h" #include "profiles.h" /* @@ -92,6 +93,38 @@ int enable_cdef; int enable_global_motion; int enable_intrabc; + int enable_restoration; + int usage; + int tune; + int enable_rect_partitions; + int enable_1to4_partitions; + int enable_ab_partitions; + int enable_angle_delta; + int enable_cfl_intra; + int enable_paeth_intra; + int enable_smooth_intra; + int enable_intra_edge_filter; + int enable_palette; + int enable_filter_intra; + int enable_flip_idtx; + int enable_tx64; + int reduced_tx_type_set; + int use_intra_dct_only; + int use_inter_dct_only; + int use_intra_default_tx_only; + int enable_ref_frame_mvs; + int enable_interinter_wedge; + int enable_interintra_wedge; + int enable_interintra_comp; + int enable_masked_comp; + int enable_obmc; + int enable_onesided_comp; + int enable_reduced_reference_set; + int enable_smooth_interintra; + int enable_diff_wtd_comp; + int enable_dist_wtd_comp; + int enable_dual_filter; + AVDictionary *aom_params; } AOMContext; static const char *const ctlidstr[] = { @@ -110,6 +143,7 @@ [AV1E_SET_SUPERBLOCK_SIZE] = "AV1E_SET_SUPERBLOCK_SIZE", [AV1E_SET_TILE_COLUMNS] = "AV1E_SET_TILE_COLUMNS", [AV1E_SET_TILE_ROWS] = "AV1E_SET_TILE_ROWS", + [AV1E_SET_ENABLE_RESTORATION] = "AV1E_SET_ENABLE_RESTORATION", #ifdef AOM_CTRL_AV1E_SET_ROW_MT [AV1E_SET_ROW_MT] = "AV1E_SET_ROW_MT", #endif @@ -129,6 +163,37 @@ [AV1E_SET_ENABLE_INTRABC] = "AV1E_SET_ENABLE_INTRABC", #endif [AV1E_SET_ENABLE_CDEF] = "AV1E_SET_ENABLE_CDEF", + [AOME_SET_TUNING] = "AOME_SET_TUNING", +#if AOM_ENCODER_ABI_VERSION >= 22 + [AV1E_SET_ENABLE_1TO4_PARTITIONS] = "AV1E_SET_ENABLE_1TO4_PARTITIONS", + [AV1E_SET_ENABLE_AB_PARTITIONS] = "AV1E_SET_ENABLE_AB_PARTITIONS", + [AV1E_SET_ENABLE_RECT_PARTITIONS] = "AV1E_SET_ENABLE_RECT_PARTITIONS", + [AV1E_SET_ENABLE_ANGLE_DELTA] = "AV1E_SET_ENABLE_ANGLE_DELTA", + [AV1E_SET_ENABLE_CFL_INTRA] = "AV1E_SET_ENABLE_CFL_INTRA", + [AV1E_SET_ENABLE_FILTER_INTRA] = "AV1E_SET_ENABLE_FILTER_INTRA", + [AV1E_SET_ENABLE_INTRA_EDGE_FILTER] = "AV1E_SET_ENABLE_INTRA_EDGE_FILTER", + [AV1E_SET_ENABLE_PAETH_INTRA] = "AV1E_SET_ENABLE_PAETH_INTRA", + [AV1E_SET_ENABLE_SMOOTH_INTRA] = "AV1E_SET_ENABLE_SMOOTH_INTRA", + [AV1E_SET_ENABLE_PALETTE] = "AV1E_SET_ENABLE_PALETTE", + [AV1E_SET_ENABLE_FLIP_IDTX] = "AV1E_SET_ENABLE_FLIP_IDTX", + [AV1E_SET_ENABLE_TX64] = "AV1E_SET_ENABLE_TX64", + [AV1E_SET_INTRA_DCT_ONLY] = "AV1E_SET_INTRA_DCT_ONLY", + [AV1E_SET_INTER_DCT_ONLY] = "AV1E_SET_INTER_DCT_ONLY", + [AV1E_SET_INTRA_DEFAULT_TX_ONLY] = "AV1E_SET_INTRA_DEFAULT_TX_ONLY", + [AV1E_SET_REDUCED_TX_TYPE_SET] = "AV1E_SET_REDUCED_TX_TYPE_SET", + [AV1E_SET_ENABLE_DIFF_WTD_COMP] = "AV1E_SET_ENABLE_DIFF_WTD_COMP", + [AV1E_SET_ENABLE_DIST_WTD_COMP] = "AV1E_SET_ENABLE_DIST_WTD_COMP", + [AV1E_SET_ENABLE_DUAL_FILTER] = "AV1E_SET_ENABLE_DUAL_FILTER", + [AV1E_SET_ENABLE_INTERINTER_WEDGE] = "AV1E_SET_ENABLE_INTERINTER_WEDGE", + [AV1E_SET_ENABLE_INTERINTRA_WEDGE] = "AV1E_SET_ENABLE_INTERINTRA_WEDGE", + [AV1E_SET_ENABLE_MASKED_COMP] = "AV1E_SET_ENABLE_MASKED_COMP", + [AV1E_SET_ENABLE_INTERINTRA_COMP] = "AV1E_SET_ENABLE_INTERINTRA_COMP", + [AV1E_SET_ENABLE_OBMC] = "AV1E_SET_ENABLE_OBMC", + [AV1E_SET_ENABLE_ONESIDED_COMP] = "AV1E_SET_ENABLE_ONESIDED_COMP", + [AV1E_SET_REDUCED_REFERENCE_SET] = "AV1E_SET_REDUCED_REFERENCE_SET", + [AV1E_SET_ENABLE_SMOOTH_INTERINTRA] = "AV1E_SET_ENABLE_SMOOTH_INTERINTRA", + [AV1E_SET_ENABLE_REF_FRAME_MVS] = "AV1E_SET_ENABLE_REF_FRAME_MVS", +#endif }; static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc) @@ -271,8 +336,12 @@ aom_img_fmt_t *img_fmt) { AOMContext av_unused *ctx = avctx->priv_data; - enccfg->g_bit_depth = enccfg->g_input_bit_depth = 8; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + enccfg->g_bit_depth = enccfg->g_input_bit_depth = desc->comp[0].depth; switch (avctx->pix_fmt) { + case AV_PIX_FMT_GRAY8: + enccfg->monochrome = 1; + /* Fall-through */ case AV_PIX_FMT_YUV420P: enccfg->g_profile = FF_PROFILE_AV1_MAIN; *img_fmt = AOM_IMG_FMT_I420; @@ -282,14 +351,17 @@ *img_fmt = AOM_IMG_FMT_I422; return 0; case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_GBRP: enccfg->g_profile = FF_PROFILE_AV1_HIGH; *img_fmt = AOM_IMG_FMT_I444; return 0; + case AV_PIX_FMT_GRAY10: + case AV_PIX_FMT_GRAY12: + enccfg->monochrome = 1; + /* Fall-through */ case AV_PIX_FMT_YUV420P10: case AV_PIX_FMT_YUV420P12: if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH) { - enccfg->g_bit_depth = enccfg->g_input_bit_depth = - avctx->pix_fmt == AV_PIX_FMT_YUV420P10 ? 10 : 12; enccfg->g_profile = enccfg->g_bit_depth == 10 ? FF_PROFILE_AV1_MAIN : FF_PROFILE_AV1_PROFESSIONAL; *img_fmt = AOM_IMG_FMT_I42016; @@ -300,8 +372,6 @@ case AV_PIX_FMT_YUV422P10: case AV_PIX_FMT_YUV422P12: if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH) { - enccfg->g_bit_depth = enccfg->g_input_bit_depth = - avctx->pix_fmt == AV_PIX_FMT_YUV422P10 ? 10 : 12; enccfg->g_profile = FF_PROFILE_AV1_PROFESSIONAL; *img_fmt = AOM_IMG_FMT_I42216; *flags |= AOM_CODEC_USE_HIGHBITDEPTH; @@ -310,9 +380,9 @@ break; case AV_PIX_FMT_YUV444P10: case AV_PIX_FMT_YUV444P12: + case AV_PIX_FMT_GBRP10: + case AV_PIX_FMT_GBRP12: if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH) { - enccfg->g_bit_depth = enccfg->g_input_bit_depth = - avctx->pix_fmt == AV_PIX_FMT_YUV444P10 ? 10 : 12; enccfg->g_profile = enccfg->g_bit_depth == 10 ? FF_PROFILE_AV1_HIGH : FF_PROFILE_AV1_PROFESSIONAL; *img_fmt = AOM_IMG_FMT_I44416; @@ -510,6 +580,7 @@ const struct aom_codec_iface *iface) { AOMContext *ctx = avctx->priv_data; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); struct aom_codec_enc_cfg enccfg = { 0 }; #ifdef AOM_FRAME_IS_INTRAONLY aom_codec_flags_t flags = @@ -549,6 +620,8 @@ enccfg.g_threads = FFMIN(avctx->thread_count ? avctx->thread_count : av_cpu_count(), 64); + enccfg.g_usage = ctx->usage; + if (ctx->lag_in_frames >= 0) enccfg.g_lag_in_frames = ctx->lag_in_frames; @@ -572,14 +645,11 @@ enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000, AV_ROUND_NEAR_INF); } else if (enccfg.rc_end_usage != AOM_Q) { - if (enccfg.rc_end_usage == AOM_CQ) { - enccfg.rc_target_bitrate = 1000000; - } else { - avctx->bit_rate = enccfg.rc_target_bitrate * 1000; - av_log(avctx, AV_LOG_WARNING, - "Neither bitrate nor constrained quality specified, using default bitrate of %dkbit/sec\n", - enccfg.rc_target_bitrate); - } + enccfg.rc_end_usage = AOM_Q; + ctx->crf = 32; + av_log(avctx, AV_LOG_WARNING, + "Neither bitrate nor constrained quality specified, using default CRF of %d\n", + ctx->crf); } if (avctx->qmin >= 0) @@ -691,13 +761,82 @@ codecctl_int(avctx, AOME_SET_ARNR_STRENGTH, ctx->arnr_strength); if (ctx->enable_cdef >= 0) codecctl_int(avctx, AV1E_SET_ENABLE_CDEF, ctx->enable_cdef); + if (ctx->enable_restoration >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_RESTORATION, ctx->enable_restoration); +#if AOM_ENCODER_ABI_VERSION >= 22 + if (ctx->enable_rect_partitions >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_RECT_PARTITIONS, ctx->enable_rect_partitions); + if (ctx->enable_1to4_partitions >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_1TO4_PARTITIONS, ctx->enable_1to4_partitions); + if (ctx->enable_ab_partitions >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_AB_PARTITIONS, ctx->enable_ab_partitions); + if (ctx->enable_angle_delta >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_ANGLE_DELTA, ctx->enable_angle_delta); + if (ctx->enable_cfl_intra >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_CFL_INTRA, ctx->enable_cfl_intra); + if (ctx->enable_filter_intra >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_FILTER_INTRA, ctx->enable_filter_intra); + if (ctx->enable_intra_edge_filter >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_INTRA_EDGE_FILTER, ctx->enable_intra_edge_filter); + if (ctx->enable_paeth_intra >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_PAETH_INTRA, ctx->enable_paeth_intra); + if (ctx->enable_smooth_intra >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_SMOOTH_INTRA, ctx->enable_smooth_intra); + if (ctx->enable_palette >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_PALETTE, ctx->enable_palette); + if (ctx->enable_tx64 >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_TX64, ctx->enable_tx64); + if (ctx->enable_flip_idtx >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_FLIP_IDTX, ctx->enable_flip_idtx); + if (ctx->use_intra_dct_only >= 0) + codecctl_int(avctx, AV1E_SET_INTRA_DCT_ONLY, ctx->use_intra_dct_only); + if (ctx->use_inter_dct_only >= 0) + codecctl_int(avctx, AV1E_SET_INTER_DCT_ONLY, ctx->use_inter_dct_only); + if (ctx->use_intra_default_tx_only >= 0) + codecctl_int(avctx, AV1E_SET_INTRA_DEFAULT_TX_ONLY, ctx->use_intra_default_tx_only); + if (ctx->reduced_tx_type_set >= 0) + codecctl_int(avctx, AV1E_SET_REDUCED_TX_TYPE_SET, ctx->reduced_tx_type_set); + if (ctx->enable_ref_frame_mvs >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_REF_FRAME_MVS, ctx->enable_ref_frame_mvs); + if (ctx->enable_reduced_reference_set >= 0) + codecctl_int(avctx, AV1E_SET_REDUCED_REFERENCE_SET, ctx->enable_reduced_reference_set); + if (ctx->enable_diff_wtd_comp >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_DIFF_WTD_COMP, ctx->enable_diff_wtd_comp); + if (ctx->enable_dist_wtd_comp >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_DIST_WTD_COMP, ctx->enable_dist_wtd_comp); + if (ctx->enable_dual_filter >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_DUAL_FILTER, ctx->enable_dual_filter); + if (ctx->enable_interinter_wedge >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_INTERINTER_WEDGE, ctx->enable_interinter_wedge); + if (ctx->enable_masked_comp >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_MASKED_COMP, ctx->enable_masked_comp); + if (ctx->enable_interintra_comp >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_INTERINTRA_COMP, ctx->enable_interintra_comp); + if (ctx->enable_interintra_wedge >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_INTERINTRA_WEDGE, ctx->enable_interintra_wedge); + if (ctx->enable_obmc >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_OBMC, ctx->enable_obmc); + if (ctx->enable_onesided_comp >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_ONESIDED_COMP, ctx->enable_onesided_comp); + if (ctx->enable_smooth_interintra >= 0) + codecctl_int(avctx, AV1E_SET_ENABLE_SMOOTH_INTERINTRA, ctx->enable_smooth_interintra); +#endif + codecctl_int(avctx, AOME_SET_STATIC_THRESHOLD, ctx->static_thresh); if (ctx->crf >= 0) codecctl_int(avctx, AOME_SET_CQ_LEVEL, ctx->crf); + if (ctx->tune >= 0) + codecctl_int(avctx, AOME_SET_TUNING, ctx->tune); - codecctl_int(avctx, AV1E_SET_COLOR_PRIMARIES, avctx->color_primaries); - codecctl_int(avctx, AV1E_SET_MATRIX_COEFFICIENTS, avctx->colorspace); - codecctl_int(avctx, AV1E_SET_TRANSFER_CHARACTERISTICS, avctx->color_trc); + if (desc->flags & AV_PIX_FMT_FLAG_RGB) { + codecctl_int(avctx, AV1E_SET_COLOR_PRIMARIES, AVCOL_PRI_BT709); + codecctl_int(avctx, AV1E_SET_MATRIX_COEFFICIENTS, AVCOL_SPC_RGB); + codecctl_int(avctx, AV1E_SET_TRANSFER_CHARACTERISTICS, AVCOL_TRC_IEC61966_2_1); + } else { + codecctl_int(avctx, AV1E_SET_COLOR_PRIMARIES, avctx->color_primaries); + codecctl_int(avctx, AV1E_SET_MATRIX_COEFFICIENTS, avctx->colorspace); + codecctl_int(avctx, AV1E_SET_TRANSFER_CHARACTERISTICS, avctx->color_trc); + } if (ctx->aq_mode >= 0) codecctl_int(avctx, AV1E_SET_AQ_MODE, ctx->aq_mode); if (ctx->frame_parallel >= 0) @@ -736,6 +875,20 @@ codecctl_int(avctx, AV1E_SET_ENABLE_INTRABC, ctx->enable_intrabc); #endif +#if AOM_ENCODER_ABI_VERSION >= 23 + { + AVDictionaryEntry *en = NULL; + + while ((en = av_dict_get(ctx->aom_params, "", en, AV_DICT_IGNORE_SUFFIX))) { + int ret = aom_codec_set_option(&ctx->encoder, en->key, en->value); + if (ret != AOM_CODEC_OK) { + log_encoder_error(avctx, en->key); + return AVERROR_EXTERNAL; + } + } + } +#endif + // provide dummy value to initialize wrapper, values will be updated each _encode() aom_img_wrap(&ctx->rawimg, img_fmt, avctx->width, avctx->height, 1, (unsigned char*)1); @@ -1023,6 +1176,16 @@ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_GBRP, + AV_PIX_FMT_NONE +}; + +static const enum AVPixelFormat av1_pix_fmts_with_gray[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV444P, + AV_PIX_FMT_GBRP, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }; @@ -1030,22 +1193,50 @@ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_GBRP, + AV_PIX_FMT_YUV420P10, + AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV422P12, + AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, + AV_PIX_FMT_NONE +}; + +static const enum AVPixelFormat av1_pix_fmts_highbd_with_gray[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV444P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, + AV_PIX_FMT_GRAY8, + AV_PIX_FMT_GRAY10, + AV_PIX_FMT_GRAY12, AV_PIX_FMT_NONE }; static av_cold void av1_init_static(AVCodec *codec) { + int supports_monochrome = aom_codec_version() >= 20001; aom_codec_caps_t codec_caps = aom_codec_get_caps(aom_codec_av1_cx()); if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH) - codec->pix_fmts = av1_pix_fmts_highbd; + codec->pix_fmts = supports_monochrome ? av1_pix_fmts_highbd_with_gray : + av1_pix_fmts_highbd; else - codec->pix_fmts = av1_pix_fmts; + codec->pix_fmts = supports_monochrome ? av1_pix_fmts_with_gray : + av1_pix_fmts; + + if (aom_codec_version_major() < 2) + codec->capabilities |= AV_CODEC_CAP_EXPERIMENTAL; } static av_cold int av1_init(AVCodecContext *avctx) @@ -1087,11 +1278,50 @@ { "enable-cdef", "Enable CDEF filtering", OFFSET(enable_cdef), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, { "enable-global-motion", "Enable global motion", OFFSET(enable_global_motion), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, { "enable-intrabc", "Enable intra block copy prediction mode", OFFSET(enable_intrabc), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-restoration", "Enable Loop Restoration filtering", OFFSET(enable_restoration), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "usage", "Quality and compression efficiency vs speed trade-off", OFFSET(usage), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "usage"}, + { "good", "Good quality", 0, AV_OPT_TYPE_CONST, {.i64 = 0 /* AOM_USAGE_GOOD_QUALITY */}, 0, 0, VE, "usage"}, + { "realtime", "Realtime encoding", 0, AV_OPT_TYPE_CONST, {.i64 = 1 /* AOM_USAGE_REALTIME */}, 0, 0, VE, "usage"}, + { "tune", "The metric that the encoder tunes for. Automatically chosen by the encoder by default", OFFSET(tune), AV_OPT_TYPE_INT, {.i64 = -1}, -1, AOM_TUNE_SSIM, VE, "tune"}, + { "psnr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AOM_TUNE_PSNR}, 0, 0, VE, "tune"}, + { "ssim", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AOM_TUNE_SSIM}, 0, 0, VE, "tune"}, + FF_AV1_PROFILE_OPTS + { "enable-rect-partitions", "Enable rectangular partitions", OFFSET(enable_rect_partitions), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-1to4-partitions", "Enable 1:4/4:1 partitions", OFFSET(enable_1to4_partitions), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-ab-partitions", "Enable ab shape partitions", OFFSET(enable_ab_partitions), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-angle-delta", "Enable angle delta intra prediction", OFFSET(enable_angle_delta), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-cfl-intra", "Enable chroma predicted from luma intra prediction", OFFSET(enable_cfl_intra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-filter-intra", "Enable filter intra predictor", OFFSET(enable_filter_intra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-intra-edge-filter", "Enable intra edge filter", OFFSET(enable_intra_edge_filter), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-smooth-intra", "Enable smooth intra prediction mode", OFFSET(enable_smooth_intra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-paeth-intra", "Enable paeth predictor in intra prediction", OFFSET(enable_paeth_intra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-palette", "Enable palette prediction mode", OFFSET(enable_palette), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-flip-idtx", "Enable extended transform type", OFFSET(enable_flip_idtx), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-tx64", "Enable 64-pt transform", OFFSET(enable_tx64), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "reduced-tx-type-set", "Use reduced set of transform types", OFFSET(reduced_tx_type_set), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "use-intra-dct-only", "Use DCT only for INTRA modes", OFFSET(use_intra_dct_only), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "use-inter-dct-only", "Use DCT only for INTER modes", OFFSET(use_inter_dct_only), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "use-intra-default-tx-only", "Use default-transform only for INTRA modes", OFFSET(use_intra_default_tx_only), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-ref-frame-mvs", "Enable temporal mv prediction", OFFSET(enable_ref_frame_mvs), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-reduced-reference-set", "Use reduced set of single and compound references", OFFSET(enable_reduced_reference_set), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-obmc", "Enable obmc", OFFSET(enable_obmc), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-dual-filter", "Enable dual filter", OFFSET(enable_dual_filter), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-diff-wtd-comp", "Enable difference-weighted compound", OFFSET(enable_diff_wtd_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-dist-wtd-comp", "Enable distance-weighted compound", OFFSET(enable_dist_wtd_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-onesided-comp", "Enable one sided compound", OFFSET(enable_onesided_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-interinter-wedge", "Enable interinter wedge compound", OFFSET(enable_interinter_wedge), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-interintra-wedge", "Enable interintra wedge compound", OFFSET(enable_interintra_wedge), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-masked-comp", "Enable masked compound", OFFSET(enable_masked_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-interintra-comp", "Enable interintra compound", OFFSET(enable_interintra_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "enable-smooth-interintra", "Enable smooth interintra mode", OFFSET(enable_smooth_interintra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, +#if AOM_ENCODER_ABI_VERSION >= 23 + { "aom-params", "Set libaom options using a :-separated list of key=value pairs", OFFSET(aom_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, +#endif { NULL }, }; static const AVCodecDefault defaults[] = { - { "b", "256*1000" }, + { "b", "0" }, { "qmin", "-1" }, { "qmax", "-1" }, { "g", "-1" }, @@ -1115,7 +1345,8 @@ .init = av1_init, .encode2 = aom_encode, .close = aom_free, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_EXPERIMENTAL, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), .priv_class = &class_aom, .defaults = defaults, diff -Nru ffmpeg-4.2.2/libavcodec/libcodec2.c ffmpeg-4.4/libavcodec/libcodec2.c --- ffmpeg-4.2.2/libavcodec/libcodec2.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libcodec2.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,7 +34,7 @@ static const AVOption options[] = { //not AV_OPT_FLAG_DECODING_PARAM since mode should come from the demuxer //1300 (aka FreeDV 1600) is the most common mode on-the-air, default to it here as well - AVPRIV_CODEC2_AVOPTIONS("codec2 mode", LibCodec2Context, 0, 4 /*CODEC2_MODE_1300*/, AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_ENCODING_PARAM), + CODEC2_AVOPTIONS("codec2 mode", LibCodec2Context, 0, 4 /*CODEC2_MODE_1300*/, AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_ENCODING_PARAM), { NULL }, }; @@ -55,7 +55,7 @@ { LibCodec2Context *c2 = avctx->priv_data; //Grab mode name from options, unless it's some weird number. - const char *modename = mode >= 0 && mode <= AVPRIV_CODEC2_MODE_MAX ? options[mode+1].name : "?"; + const char *modename = mode >= 0 && mode <= CODEC2_MODE_MAX ? options[mode+1].name : "?"; c2->codec = codec2_create(mode); if (!c2->codec) { @@ -93,13 +93,13 @@ avctx->sample_fmt = AV_SAMPLE_FMT_S16; avctx->channel_layout = AV_CH_LAYOUT_MONO; - if (avctx->extradata_size != AVPRIV_CODEC2_EXTRADATA_SIZE) { + if (avctx->extradata_size != CODEC2_EXTRADATA_SIZE) { av_log(avctx, AV_LOG_ERROR, "must have exactly %i bytes of extradata (got %i)\n", - AVPRIV_CODEC2_EXTRADATA_SIZE, avctx->extradata_size); + CODEC2_EXTRADATA_SIZE, avctx->extradata_size); return AVERROR_INVALIDDATA; } - return libcodec2_init_common(avctx, avpriv_codec2_mode_from_extradata(avctx->extradata)); + return libcodec2_init_common(avctx, codec2_mode_from_extradata(avctx->extradata)); } static av_cold int libcodec2_init_encoder(AVCodecContext *avctx) @@ -114,13 +114,13 @@ return AVERROR(EINVAL); } - avctx->extradata = av_mallocz(AVPRIV_CODEC2_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); + avctx->extradata = av_mallocz(CODEC2_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { return AVERROR(ENOMEM); } - avctx->extradata_size = AVPRIV_CODEC2_EXTRADATA_SIZE; - avpriv_codec2_make_extradata(avctx->extradata, c2->mode); + avctx->extradata_size = CODEC2_EXTRADATA_SIZE; + codec2_make_extradata(avctx->extradata, c2->mode); return libcodec2_init_common(avctx, c2->mode); } @@ -189,7 +189,7 @@ .init = libcodec2_init_decoder, .close = libcodec2_close, .decode = libcodec2_decode, - .capabilities = 0, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF, .supported_samplerates = (const int[]){ 8000, 0 }, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 }, diff -Nru ffmpeg-4.2.2/libavcodec/libdav1d.c ffmpeg-4.4/libavcodec/libdav1d.c --- ffmpeg-4.2.2/libavcodec/libdav1d.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libdav1d.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,11 +22,14 @@ #include #include "libavutil/avassert.h" +#include "libavutil/film_grain_params.h" #include "libavutil/mastering_display_metadata.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" +#include "atsc_a53.h" #include "avcodec.h" +#include "bytestream.h" #include "decode.h" #include "internal.h" @@ -40,6 +43,8 @@ int tile_threads; int frame_threads; int apply_grain; + int operating_point; + int all_layers; } Libdav1dContext; static const enum AVPixelFormat pix_fmt[][3] = { @@ -64,12 +69,11 @@ { Libdav1dContext *dav1d = cookie; enum AVPixelFormat format = pix_fmt[p->p.layout][p->seq_hdr->hbd]; - int ret, linesize[4], h = FFALIGN(p->p.h, 128); + int ret, linesize[4], h = FFALIGN(p->p.h, 128), w = FFALIGN(p->p.w, 128); uint8_t *aligned_ptr, *data[4]; AVBufferRef *buf; - ret = av_image_fill_arrays(data, linesize, NULL, format, FFALIGN(p->p.w, 128), - h, DAV1D_PICTURE_ALIGNMENT); + ret = av_image_get_buffer_size(format, w, h, DAV1D_PICTURE_ALIGNMENT); if (ret < 0) return ret; @@ -92,7 +96,8 @@ // Use the extra DAV1D_PICTURE_ALIGNMENT padding bytes in the buffer to align it // if required. aligned_ptr = (uint8_t *)FFALIGN((uintptr_t)buf->data, DAV1D_PICTURE_ALIGNMENT); - ret = av_image_fill_pointers(data, format, h, aligned_ptr, linesize); + ret = av_image_fill_arrays(data, linesize, aligned_ptr, format, w, h, + DAV1D_PICTURE_ALIGNMENT); if (ret < 0) { av_buffer_unref(&buf); return ret; @@ -130,7 +135,15 @@ s.allocator.cookie = dav1d; s.allocator.alloc_picture_callback = libdav1d_picture_allocator; s.allocator.release_picture_callback = libdav1d_picture_release; - s.apply_grain = dav1d->apply_grain; + 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; + + s.all_layers = dav1d->all_layers; + if (dav1d->operating_point >= 0) + s.operating_point = dav1d->operating_point; s.n_tile_threads = dav1d->tile_threads ? dav1d->tile_threads @@ -162,6 +175,11 @@ av_buffer_unref(&buf); } +static void libdav1d_user_data_free(const uint8_t *data, void *opaque) { + av_assert0(data == opaque); + av_free(opaque); +} + static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) { Libdav1dContext *dav1d = c->priv_data; @@ -189,6 +207,23 @@ pkt.buf = NULL; av_packet_unref(&pkt); + + if (c->reordered_opaque != AV_NOPTS_VALUE) { + uint8_t *reordered_opaque = av_malloc(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) { + av_free(reordered_opaque); + dav1d_data_unref(data); + return res; + } + } } } @@ -237,6 +272,13 @@ goto fail; } + av_reduce(&frame->sample_aspect_ratio.num, + &frame->sample_aspect_ratio.den, + frame->height * (int64_t)p->frame_hdr->render_width, + frame->width * (int64_t)p->frame_hdr->render_height, + INT_MAX); + ff_set_sar(c, frame->sample_aspect_ratio); + switch (p->seq_hdr->chr) { case DAV1D_CHR_VERTICAL: frame->chroma_location = c->chroma_sample_location = AVCHROMA_LOC_LEFT; @@ -258,8 +300,20 @@ else frame->format = c->pix_fmt = pix_fmt[p->p.layout][p->seq_hdr->hbd]; + if (p->m.user_data.data) + memcpy(&frame->reordered_opaque, p->m.user_data.data, sizeof(frame->reordered_opaque)); + else + frame->reordered_opaque = AV_NOPTS_VALUE; + + if (p->seq_hdr->num_units_in_tick && p->seq_hdr->time_scale) { + av_reduce(&c->framerate.den, &c->framerate.num, + p->seq_hdr->num_units_in_tick, p->seq_hdr->time_scale, INT_MAX); + if (p->seq_hdr->equal_picture_interval) + c->ticks_per_frame = p->seq_hdr->num_ticks_per_picture; + } + // match timestamps and packet size - frame->pts = frame->best_effort_timestamp = p->m.timestamp; + frame->pts = p->m.timestamp; #if FF_API_PKT_PTS FF_DISABLE_DEPRECATION_WARNINGS frame->pkt_pts = p->m.timestamp; @@ -316,6 +370,72 @@ light->MaxCLL = p->content_light->max_content_light_level; light->MaxFALL = p->content_light->max_frame_average_light_level; } + if (p->itut_t35) { + GetByteContext gb; + unsigned int user_identifier; + + bytestream2_init(&gb, p->itut_t35->payload, p->itut_t35->payload_size); + bytestream2_skip(&gb, 1); // terminal provider code + bytestream2_skip(&gb, 1); // terminal provider oriented code + user_identifier = bytestream2_get_be32(&gb); + switch (user_identifier) { + case MKBETAG('G', 'A', '9', '4'): { // closed captions + AVBufferRef *buf = NULL; + + res = ff_parse_a53_cc(&buf, gb.buffer, bytestream2_get_bytes_left(&gb)); + if (res < 0) + goto fail; + if (!res) + break; + + if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_A53_CC, buf)) + av_buffer_unref(&buf); + + c->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; + break; + } + default: // ignore unsupported identifiers + break; + } + } + if (p->frame_hdr->film_grain.present && (!dav1d->apply_grain || + (c->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN))) { + AVFilmGrainParams *fgp = av_film_grain_params_create_side_data(frame); + if (!fgp) { + res = AVERROR(ENOMEM); + goto fail; + } + + fgp->type = AV_FILM_GRAIN_PARAMS_AV1; + fgp->seed = p->frame_hdr->film_grain.data.seed; + fgp->codec.aom.num_y_points = p->frame_hdr->film_grain.data.num_y_points; + fgp->codec.aom.chroma_scaling_from_luma = p->frame_hdr->film_grain.data.chroma_scaling_from_luma; + fgp->codec.aom.scaling_shift = p->frame_hdr->film_grain.data.scaling_shift; + fgp->codec.aom.ar_coeff_lag = p->frame_hdr->film_grain.data.ar_coeff_lag; + fgp->codec.aom.ar_coeff_shift = p->frame_hdr->film_grain.data.ar_coeff_shift; + fgp->codec.aom.grain_scale_shift = p->frame_hdr->film_grain.data.grain_scale_shift; + fgp->codec.aom.overlap_flag = p->frame_hdr->film_grain.data.overlap_flag; + fgp->codec.aom.limit_output_range = p->frame_hdr->film_grain.data.clip_to_restricted_range; + + memcpy(&fgp->codec.aom.y_points, &p->frame_hdr->film_grain.data.y_points, + sizeof(fgp->codec.aom.y_points)); + memcpy(&fgp->codec.aom.num_uv_points, &p->frame_hdr->film_grain.data.num_uv_points, + sizeof(fgp->codec.aom.num_uv_points)); + memcpy(&fgp->codec.aom.uv_points, &p->frame_hdr->film_grain.data.uv_points, + sizeof(fgp->codec.aom.uv_points)); + memcpy(&fgp->codec.aom.ar_coeffs_y, &p->frame_hdr->film_grain.data.ar_coeffs_y, + sizeof(fgp->codec.aom.ar_coeffs_y)); + memcpy(&fgp->codec.aom.ar_coeffs_uv[0], &p->frame_hdr->film_grain.data.ar_coeffs_uv[0], + sizeof(fgp->codec.aom.ar_coeffs_uv[0])); + memcpy(&fgp->codec.aom.ar_coeffs_uv[1], &p->frame_hdr->film_grain.data.ar_coeffs_uv[1], + sizeof(fgp->codec.aom.ar_coeffs_uv[1])); + memcpy(&fgp->codec.aom.uv_mult, &p->frame_hdr->film_grain.data.uv_mult, + sizeof(fgp->codec.aom.uv_mult)); + memcpy(&fgp->codec.aom.uv_mult_luma, &p->frame_hdr->film_grain.data.uv_luma_mult, + sizeof(fgp->codec.aom.uv_mult_luma)); + memcpy(&fgp->codec.aom.uv_offset, &p->frame_hdr->film_grain.data.uv_offset, + sizeof(fgp->codec.aom.uv_offset)); + } res = 0; fail: @@ -341,7 +461,9 @@ static const AVOption libdav1d_options[] = { { "tilethreads", "Tile threads", OFFSET(tile_threads), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, DAV1D_MAX_TILE_THREADS, VD }, { "framethreads", "Frame threads", OFFSET(frame_threads), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, DAV1D_MAX_FRAME_THREADS, VD }, - { "filmgrain", "Apply Film Grain", OFFSET(apply_grain), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VD }, + { "filmgrain", "Apply Film Grain", OFFSET(apply_grain), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VD | AV_OPT_FLAG_DEPRECATED }, + { "oppoint", "Select an operating point of the scalable bitstream", OFFSET(operating_point), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 31, VD }, + { "alllayers", "Output all spatial layers", OFFSET(all_layers), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VD }, { NULL } }; @@ -362,8 +484,9 @@ .close = libdav1d_close, .flush = libdav1d_flush, .receive_frame = libdav1d_receive_frame, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SETS_PKT_DTS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SETS_PKT_DTS | + FF_CODEC_CAP_AUTO_THREADS, .priv_class = &libdav1d_class, .wrapper_name = "libdav1d", }; diff -Nru ffmpeg-4.2.2/libavcodec/libdavs2.c ffmpeg-4.4/libavcodec/libdavs2.c --- ffmpeg-4.2.2/libavcodec/libdavs2.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libdavs2.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ */ #include "avcodec.h" +#include "internal.h" #include "davs2.h" typedef struct DAVS2Context { @@ -221,7 +222,8 @@ .close = davs2_end, .decode = davs2_decode_frame, .flush = davs2_flush, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .wrapper_name = "libdavs2", diff -Nru ffmpeg-4.2.2/libavcodec/libfdk-aacdec.c ffmpeg-4.4/libavcodec/libfdk-aacdec.c --- ffmpeg-4.2.2/libavcodec/libfdk-aacdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libfdk-aacdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -57,6 +57,7 @@ int drc_effect; int drc_cut; int level_limit; + int output_delay; } FDKAACDecContext; @@ -75,12 +76,13 @@ OFFSET(drc_boost), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 127, AD, NULL }, { "drc_cut", "Dynamic Range Control: attenuation factor, where [0] is none and [127] is max compression", OFFSET(drc_cut), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 127, AD, NULL }, - { "drc_level", "Dynamic Range Control: reference level, quantized to 0.25dB steps where [0] is 0dB and [127] is -31.75dB", - OFFSET(drc_level), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 127, AD, NULL }, + { "drc_level", "Dynamic Range Control: reference level, quantized to 0.25dB steps where [0] is 0dB and [127] is -31.75dB, -1 for auto, and -2 for disabled", + OFFSET(drc_level), AV_OPT_TYPE_INT, { .i64 = -1}, -2, 127, AD, NULL }, { "drc_heavy", "Dynamic Range Control: heavy compression, where [1] is on (RF mode) and [0] is off", OFFSET(drc_heavy), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 1, AD, NULL }, #if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 - { "level_limit", "Signal level limiting", OFFSET(level_limit), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, 1, AD }, + { "level_limit", "Signal level limiting", + OFFSET(level_limit), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, AD }, #endif #if FDKDEC_VER_AT_LEAST(3, 0) // 3.0.0 { "drc_effect","Dynamic Range Control: effect type, where e.g. [0] is none and [6] is general", @@ -115,6 +117,9 @@ } avctx->sample_rate = info->sampleRate; avctx->frame_size = info->frameSize; +#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 + s->output_delay = info->outputDelay; +#endif for (i = 0; i < info->numChannels; i++) { AUDIO_CHANNEL_TYPE ctype = info->pChannelType[i]; @@ -294,6 +299,12 @@ } if (s->drc_level != -1) { + // This option defaults to -1, i.e. not calling + // aacDecoder_SetParam(AAC_DRC_REFERENCE_LEVEL) at all, which defaults + // to the level from DRC metadata, if available. The user can set + // -drc_level -2, which calls aacDecoder_SetParam( + // AAC_DRC_REFERENCE_LEVEL) with a negative value, which then + // explicitly disables the feature. if (aacDecoder_SetParam(s->handle, AAC_DRC_REFERENCE_LEVEL, s->drc_level) != AAC_DEC_OK) { av_log(avctx, AV_LOG_ERROR, "Unable to set DRC reference level in the decoder\n"); return AVERROR_UNKNOWN; @@ -308,6 +319,7 @@ } #if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 + // Setting this parameter to -1 enables the auto behaviour in the library. if (aacDecoder_SetParam(s->handle, AAC_PCM_LIMITER_ENABLE, s->level_limit) != AAC_DEC_OK) { av_log(avctx, AV_LOG_ERROR, "Unable to set in signal level limiting in the decoder\n"); return AVERROR_UNKNOWN; @@ -367,6 +379,11 @@ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) goto end; + if (frame->pts != AV_NOPTS_VALUE) + frame->pts -= av_rescale_q(s->output_delay, + (AVRational){1, avctx->sample_rate}, + avctx->time_base); + memcpy(frame->extended_data[0], s->decoder_buffer, avctx->channels * avctx->frame_size * av_get_bytes_per_sample(avctx->sample_fmt)); diff -Nru ffmpeg-4.2.2/libavcodec/libfdk-aacenc.c ffmpeg-4.4/libavcodec/libfdk-aacenc.c --- ffmpeg-4.2.2/libavcodec/libfdk-aacenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libfdk-aacenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -25,6 +25,7 @@ #include "avcodec.h" #include "audio_frame_queue.h" #include "internal.h" +#include "profiles.h" #ifdef AACENCODER_LIB_VL0 #define FDKENC_VER_AT_LEAST(vl0, vl1) \ @@ -62,6 +63,7 @@ { "latm", "Output LATM/LOAS encapsulated data", offsetof(AACContext, latm), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, { "header_period", "StreamMuxConfig and PCE repetition period (in frames)", offsetof(AACContext, header_period), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xffff, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, { "vbr", "VBR mode (1-5)", offsetof(AACContext, vbr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 5, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + FF_AAC_PROFILE_OPTS { NULL } }; diff -Nru ffmpeg-4.2.2/libavcodec/libgsmdec.c ffmpeg-4.4/libavcodec/libgsmdec.c --- ffmpeg-4.2.2/libavcodec/libgsmdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libgsmdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -134,7 +134,7 @@ .close = libgsm_decode_close, .decode = libgsm_decode_frame, .flush = libgsm_flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .wrapper_name = "libgsm", }; #endif @@ -149,7 +149,7 @@ .close = libgsm_decode_close, .decode = libgsm_decode_frame, .flush = libgsm_flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .wrapper_name = "libgsm", }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/libilbc.c ffmpeg-4.4/libavcodec/libilbc.c --- ffmpeg-4.2.2/libavcodec/libilbc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libilbc.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,10 @@ #include "avcodec.h" #include "internal.h" +#ifndef LIBILBC_VERSION_MAJOR +#define LIBILBC_VERSION_MAJOR 2 +#endif + static int get_mode(AVCodecContext *avctx) { if (avctx->block_align == 38) @@ -41,7 +45,11 @@ typedef struct ILBCDecContext { const AVClass *class; +#if LIBILBC_VERSION_MAJOR < 3 iLBC_Dec_Inst_t decoder; +#else + IlbcDecoder decoder; +#endif int enhance; } ILBCDecContext; @@ -87,7 +95,12 @@ int ret; if (s->decoder.no_of_bytes > buf_size) { +#if LIBILBC_VERSION_MAJOR < 3 av_log(avctx, AV_LOG_ERROR, "iLBC frame too short (%u, should be %u)\n", +#else + av_log(avctx, AV_LOG_ERROR, "iLBC frame too short (%u, should be " + "%"SIZE_SPECIFIER")\n", +#endif buf_size, s->decoder.no_of_bytes); return AVERROR_INVALIDDATA; } @@ -111,13 +124,17 @@ .priv_data_size = sizeof(ILBCDecContext), .init = ilbc_decode_init, .decode = ilbc_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .priv_class = &ilbc_dec_class, }; typedef struct ILBCEncContext { const AVClass *class; +#if LIBILBC_VERSION_MAJOR < 3 iLBC_Enc_Inst_t encoder; +#else + IlbcEncoder encoder; +#endif int mode; } ILBCEncContext; diff -Nru ffmpeg-4.2.2/libavcodec/libkvazaar.c ffmpeg-4.4/libavcodec/libkvazaar.c --- ffmpeg-4.2.2/libavcodec/libkvazaar.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libkvazaar.c 2021-04-08 21:28:39.000000000 +0000 @@ -37,6 +37,7 @@ #include "avcodec.h" #include "internal.h" +#include "packet_internal.h" typedef struct LibkvazaarContext { const AVClass *class; @@ -80,13 +81,8 @@ cfg->height = avctx->height; if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { - if (avctx->ticks_per_frame > INT_MAX / avctx->framerate.den) { - av_log(avctx, AV_LOG_ERROR, - "Could not set framerate for kvazaar: integer overflow\n"); - return AVERROR(EINVAL); - } cfg->framerate_num = avctx->framerate.num; - cfg->framerate_denom = avctx->time_base.den * avctx->ticks_per_frame; + cfg->framerate_denom = avctx->framerate.den; } else { if (avctx->ticks_per_frame > INT_MAX / avctx->time_base.num) { av_log(avctx, AV_LOG_ERROR, @@ -99,6 +95,9 @@ cfg->target_bitrate = avctx->bit_rate; cfg->vui.sar_width = avctx->sample_aspect_ratio.num; cfg->vui.sar_height = avctx->sample_aspect_ratio.den; + if (avctx->bit_rate) { + cfg->rc_algorithm = KVZ_LAMBDA; + } if (ctx->kvz_params) { AVDictionary *dict = NULL; @@ -110,8 +109,8 @@ entry->key, entry->value); } } - av_dict_free(&dict); } + av_dict_free(&dict); } ctx->encoder = enc = api->encoder_open(cfg); @@ -175,6 +174,7 @@ kvz_data_chunk *data_out = NULL; uint32_t len_out = 0; int retval = 0; + int pict_type; *got_packet_ptr = 0; @@ -262,6 +262,34 @@ avpkt->flags |= AV_PKT_FLAG_KEY; } + switch (frame_info.slice_type) { + case KVZ_SLICE_I: + pict_type = AV_PICTURE_TYPE_I; + break; + case KVZ_SLICE_P: + pict_type = AV_PICTURE_TYPE_P; + break; + case KVZ_SLICE_B: + pict_type = AV_PICTURE_TYPE_B; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown picture type encountered.\n"); + return AVERROR_EXTERNAL; + } +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->pict_type = pict_type; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + ff_side_data_set_encoder_stats(avpkt, frame_info.qp * FF_QP2LAMBDA, NULL, 0, pict_type); + +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->quality = frame_info.qp * FF_QP2LAMBDA; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + *got_packet_ptr = 1; } @@ -302,7 +330,7 @@ .long_name = NULL_IF_CONFIG_SMALL("libkvazaar H.265 / HEVC"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, .pix_fmts = pix_fmts, .priv_class = &class, @@ -313,7 +341,8 @@ .encode2 = libkvazaar_encode, .close = libkvazaar_close, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_AUTO_THREADS, .wrapper_name = "libkvazaar", }; diff -Nru ffmpeg-4.2.2/libavcodec/libmp3lame.c ffmpeg-4.4/libavcodec/libmp3lame.c --- ffmpeg-4.2.2/libavcodec/libmp3lame.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libmp3lame.c 2020-07-09 09:17:46.000000000 +0000 @@ -279,7 +279,6 @@ if ((discard_padding < avctx->frame_size) != (avpkt->duration > 0)) { av_log(avctx, AV_LOG_ERROR, "discard padding overflow\n"); av_packet_unref(avpkt); - av_free(avpkt); return AVERROR(EINVAL); } if ((!s->delay_sent && avctx->initial_padding > 0) || discard_padding > 0) { @@ -288,7 +287,6 @@ 10); if(!side_data) { av_packet_unref(avpkt); - av_free(avpkt); return AVERROR(ENOMEM); } if (!s->delay_sent) { diff -Nru ffmpeg-4.2.2/libavcodec/libopencore-amr.c ffmpeg-4.4/libavcodec/libopencore-amr.c --- ffmpeg-4.2.2/libavcodec/libopencore-amr.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libopencore-amr.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,7 @@ #include "audio_frame_queue.h" #include "internal.h" +#if CONFIG_LIBOPENCORE_AMRNB_DECODER || CONFIG_LIBOPENCORE_AMRWB_DECODER static int amr_decode_fix_avctx(AVCodecContext *avctx) { const int is_amr_wb = 1 + (avctx->codec_id == AV_CODEC_ID_AMR_WB); @@ -46,6 +47,7 @@ avctx->sample_fmt = AV_SAMPLE_FMT_S16; return 0; } +#endif #if CONFIG_LIBOPENCORE_AMRNB @@ -137,7 +139,7 @@ .init = amr_nb_decode_init, .close = amr_nb_decode_close, .decode = amr_nb_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; #endif /* CONFIG_LIBOPENCORE_AMRNB_DECODER */ @@ -377,7 +379,7 @@ .init = amr_wb_decode_init, .close = amr_wb_decode_close, .decode = amr_wb_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .wrapper_name = "libopencore_amrwb", }; diff -Nru ffmpeg-4.2.2/libavcodec/libopenh264enc.c ffmpeg-4.4/libavcodec/libopenh264enc.c --- ffmpeg-4.2.2/libavcodec/libopenh264enc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libopenh264enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -37,25 +37,35 @@ #define SM_SIZELIMITED_SLICE SM_DYN_SLICE #endif +#define TARGET_BITRATE_DEFAULT 2*1000*1000 + typedef struct SVCContext { const AVClass *av_class; ISVCEncoder *encoder; int slice_mode; int loopfilter; - char *profile; + int profile; int max_nal_size; int skip_frames; int skipped; - int cabac; +#if FF_API_OPENH264_CABAC + int cabac; // deprecated +#endif + int coder; + + // rate control mode + int rc_mode; } SVCContext; #define OFFSET(x) offsetof(SVCContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +#define DEPRECATED AV_OPT_FLAG_DEPRECATED static const AVOption options[] = { +#if FF_API_OPENH264_SLICE_MODE #if OPENH264_VER_AT_LEAST(1, 6) - { "slice_mode", "set slice mode", OFFSET(slice_mode), AV_OPT_TYPE_INT, { .i64 = SM_FIXEDSLCNUM_SLICE }, SM_SINGLE_SLICE, SM_RESERVED, VE, "slice_mode" }, + { "slice_mode", "set slice mode, use slices/max_nal_size", OFFSET(slice_mode), AV_OPT_TYPE_INT, { .i64 = SM_FIXEDSLCNUM_SLICE }, SM_SINGLE_SLICE, SM_RESERVED, VE|DEPRECATED, "slice_mode" }, #else - { "slice_mode", "set slice mode", OFFSET(slice_mode), AV_OPT_TYPE_INT, { .i64 = SM_AUTO_SLICE }, SM_SINGLE_SLICE, SM_RESERVED, VE, "slice_mode" }, + { "slice_mode", "set slice mode, use slices/max_nal_size", OFFSET(slice_mode), AV_OPT_TYPE_INT, { .i64 = SM_AUTO_SLICE }, SM_SINGLE_SLICE, SM_RESERVED, VE|DEPRECATED, "slice_mode" }, #endif { "fixed", "a fixed number of slices", 0, AV_OPT_TYPE_CONST, { .i64 = SM_FIXEDSLCNUM_SLICE }, 0, 0, VE, "slice_mode" }, #if OPENH264_VER_AT_LEAST(1, 6) @@ -66,11 +76,35 @@ { "auto", "automatic number of slices according to number of threads", 0, AV_OPT_TYPE_CONST, { .i64 = SM_AUTO_SLICE }, 0, 0, VE, "slice_mode" }, { "dyn", "Dynamic slicing", 0, AV_OPT_TYPE_CONST, { .i64 = SM_DYN_SLICE }, 0, 0, VE, "slice_mode" }, #endif +#endif { "loopfilter", "enable loop filter", OFFSET(loopfilter), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, - { "profile", "set profile restrictions", OFFSET(profile), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE }, + { "profile", "set profile restrictions", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = FF_PROFILE_UNKNOWN }, FF_PROFILE_UNKNOWN, 0xffff, VE, "profile" }, +#define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, { .i64 = value }, 0, 0, VE, "profile" + { PROFILE("constrained_baseline", FF_PROFILE_H264_CONSTRAINED_BASELINE) }, + { PROFILE("main", FF_PROFILE_H264_MAIN) }, + { PROFILE("high", FF_PROFILE_H264_HIGH) }, +#undef PROFILE { "max_nal_size", "set maximum NAL size in bytes", OFFSET(max_nal_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, { "allow_skip_frames", "allow skipping frames to hit the target bitrate", OFFSET(skip_frames), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "cabac", "Enable cabac", OFFSET(cabac), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, +#if FF_API_OPENH264_CABAC + { "cabac", "Enable cabac(deprecated, use coder)", OFFSET(cabac), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE|DEPRECATED }, +#endif + { "coder", "Coder type", OFFSET(coder), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE, "coder" }, + { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, VE, "coder" }, + { "cavlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "coder" }, + { "cabac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "coder" }, + { "vlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "coder" }, + { "ac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "coder" }, + + { "rc_mode", "Select rate control mode", OFFSET(rc_mode), AV_OPT_TYPE_INT, { .i64 = RC_QUALITY_MODE }, RC_OFF_MODE, RC_TIMESTAMP_MODE, VE, "rc_mode" }, + { "off", "bit rate control off", 0, AV_OPT_TYPE_CONST, { .i64 = RC_OFF_MODE }, 0, 0, VE, "rc_mode" }, + { "quality", "quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RC_QUALITY_MODE }, 0, 0, VE, "rc_mode" }, + { "bitrate", "bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = RC_BITRATE_MODE }, 0, 0, VE, "rc_mode" }, + { "buffer", "using buffer status to adjust the video quality (no bitrate control)", 0, AV_OPT_TYPE_CONST, { .i64 = RC_BUFFERBASED_MODE }, 0, 0, VE, "rc_mode" }, +#if OPENH264_VER_AT_LEAST(1, 4) + { "timestamp", "bit rate control based on timestamp", 0, AV_OPT_TYPE_CONST, { .i64 = RC_TIMESTAMP_MODE }, 0, 0, VE, "rc_mode" }, +#endif + { NULL } }; @@ -122,19 +156,25 @@ (*s->encoder)->GetDefaultParams(s->encoder, ¶m); -#if FF_API_CODER_TYPE -FF_DISABLE_DEPRECATION_WARNINGS - if (!s->cabac) - s->cabac = avctx->coder_type == FF_CODER_TYPE_AC; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - - param.fMaxFrameRate = 1/av_q2d(avctx->time_base); + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + param.fMaxFrameRate = av_q2d(avctx->framerate); + } else { + if (avctx->ticks_per_frame > INT_MAX / avctx->time_base.num) { + av_log(avctx, AV_LOG_ERROR, + "Could not set framerate for libopenh264enc: integer overflow\n"); + return AVERROR(EINVAL); + } + param.fMaxFrameRate = 1.0 / av_q2d(avctx->time_base) / FFMAX(avctx->ticks_per_frame, 1); + } param.iPicWidth = avctx->width; param.iPicHeight = avctx->height; - param.iTargetBitrate = avctx->bit_rate; + param.iTargetBitrate = avctx->bit_rate > 0 ? avctx->bit_rate : TARGET_BITRATE_DEFAULT; param.iMaxBitrate = FFMAX(avctx->rc_max_rate, avctx->bit_rate); - param.iRCMode = RC_QUALITY_MODE; + param.iRCMode = s->rc_mode; + if (avctx->qmax >= 0) + param.iMaxQp = av_clip(avctx->qmax, 1, 51); + if (avctx->qmin >= 0) + param.iMinQp = av_clip(avctx->qmin, 1, param.iMaxQp); param.iTemporalLayerNum = 1; param.iSpatialLayerNum = 1; param.bEnableDenoise = 0; @@ -143,7 +183,8 @@ param.bEnableFrameSkip = s->skip_frames; param.bEnableLongTermReference = 0; param.iLtrMarkPeriod = 30; - param.uiIntraPeriod = avctx->gop_size; + if (avctx->gop_size >= 0) + param.uiIntraPeriod = avctx->gop_size; #if OPENH264_VER_AT_LEAST(1, 4) param.eSpsPpsIdStrategy = CONSTANT_ID; #else @@ -153,10 +194,66 @@ param.iLoopFilterDisableIdc = !s->loopfilter; param.iEntropyCodingModeFlag = 0; param.iMultipleThreadIdc = avctx->thread_count; - if (s->profile && !strcmp(s->profile, "main")) + + /* Allow specifying the libopenh264 profile through AVCodecContext. */ + if (FF_PROFILE_UNKNOWN == s->profile && + FF_PROFILE_UNKNOWN != avctx->profile) + switch (avctx->profile) { + case FF_PROFILE_H264_HIGH: + case FF_PROFILE_H264_MAIN: + case FF_PROFILE_H264_CONSTRAINED_BASELINE: + s->profile = avctx->profile; + break; + default: + av_log(avctx, AV_LOG_WARNING, + "Unsupported avctx->profile: %d.\n", avctx->profile); + break; + } + +#if FF_API_CODER_TYPE && FF_API_OPENH264_CABAC +FF_DISABLE_DEPRECATION_WARNINGS + if (s->coder < 0 && avctx->coder_type == FF_CODER_TYPE_AC) + s->coder = 1; + + if (s->coder < 0) + s->coder = s->cabac; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (s->profile == FF_PROFILE_UNKNOWN && s->coder >= 0) + s->profile = s->coder == 0 ? FF_PROFILE_H264_CONSTRAINED_BASELINE : +#if OPENH264_VER_AT_LEAST(1, 8) + FF_PROFILE_H264_HIGH; +#else + FF_PROFILE_H264_MAIN; +#endif + + switch (s->profile) { +#if OPENH264_VER_AT_LEAST(1, 8) + case FF_PROFILE_H264_HIGH: param.iEntropyCodingModeFlag = 1; - else if (!s->profile && s->cabac) + av_log(avctx, AV_LOG_VERBOSE, "Using CABAC, " + "select EProfileIdc PRO_HIGH in libopenh264.\n"); + 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"); + break; +#endif + case FF_PROFILE_H264_CONSTRAINED_BASELINE: + case FF_PROFILE_UNKNOWN: + param.iEntropyCodingModeFlag = 0; + av_log(avctx, AV_LOG_VERBOSE, "Using CAVLC, " + "select EProfileIdc PRO_BASELINE in libopenh264.\n"); + break; + default: + param.iEntropyCodingModeFlag = 0; + av_log(avctx, AV_LOG_WARNING, "Unsupported profile, " + "select EProfileIdc PRO_BASELINE in libopenh264.\n"); + break; + } param.sSpatialLayers[0].iVideoWidth = param.iPicWidth; param.sSpatialLayers[0].iVideoHeight = param.iPicHeight; @@ -199,8 +296,7 @@ param.sSpatialLayers[0].eAspectRatio = asp_idc[i]; } param.sSpatialLayers[0].bAspectRatioPresent = true; - } - else { + } else { param.sSpatialLayers[0].bAspectRatioPresent = false; } #endif @@ -225,9 +321,11 @@ param.sSpatialLayers[0].sSliceCfg.uiSliceMode = s->slice_mode; param.sSpatialLayers[0].sSliceCfg.sSliceArgument.uiSliceNum = avctx->slices; #endif + if (avctx->slices == 0 && s->slice_mode == SM_FIXEDSLCNUM_SLICE) + av_log(avctx, AV_LOG_WARNING, "Slice count will be set automatically\n"); if (s->slice_mode == SM_SIZELIMITED_SLICE) { - if (s->max_nal_size){ + if (s->max_nal_size) { param.uiMaxNalSize = s->max_nal_size; #if OPENH264_VER_AT_LEAST(1, 6) param.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint = s->max_nal_size; @@ -332,6 +430,14 @@ return 0; } +static const AVCodecDefault svc_enc_defaults[] = { + { "b", "0" }, + { "g", "-1" }, + { "qmin", "-1" }, + { "qmax", "-1" }, + { NULL }, +}; + AVCodec ff_libopenh264_encoder = { .name = "libopenh264", .long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), @@ -341,10 +447,12 @@ .init = svc_encode_init, .encode2 = svc_encode_frame, .close = svc_encode_close, - .capabilities = AV_CODEC_CAP_AUTO_THREADS, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .capabilities = AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_AUTO_THREADS, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .defaults = svc_enc_defaults, .priv_class = &class, .wrapper_name = "libopenh264", }; diff -Nru ffmpeg-4.2.2/libavcodec/libopenjpegenc.c ffmpeg-4.4/libavcodec/libopenjpegenc.c --- ffmpeg-4.2.2/libavcodec/libopenjpegenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libopenjpegenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -763,7 +763,7 @@ .priv_data_size = sizeof(LibOpenJPEGContext), .init = libopenjpeg_encode_init, .encode2 = libopenjpeg_encode_frame, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48, AV_PIX_FMT_RGBA64, AV_PIX_FMT_GBR24P, diff -Nru ffmpeg-4.2.2/libavcodec/libopusdec.c ffmpeg-4.4/libavcodec/libopusdec.c --- ffmpeg-4.2.2/libavcodec/libopusdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libopusdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -235,7 +235,7 @@ .close = libopus_decode_close, .decode = libopus_decode, .flush = libopus_flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, diff -Nru ffmpeg-4.2.2/libavcodec/libopusenc.c ffmpeg-4.4/libavcodec/libopusenc.c --- ffmpeg-4.2.2/libavcodec/libopusenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libopusenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,6 +34,7 @@ int vbr; int application; int packet_loss; + int fec; int complexity; float frame_duration; int packet_size; @@ -93,7 +94,7 @@ bytestream_put_buffer(&p, "OpusHead", 8); bytestream_put_byte(&p, 1); /* Version */ bytestream_put_byte(&p, channels); - bytestream_put_le16(&p, avctx->initial_padding); /* Lookahead samples at 48kHz */ + bytestream_put_le16(&p, avctx->initial_padding * 48000 / avctx->sample_rate); /* Lookahead samples at 48kHz */ bytestream_put_le32(&p, avctx->sample_rate); /* Original sample rate */ bytestream_put_le16(&p, 0); /* Gain of 0dB is recommended. */ @@ -149,6 +150,13 @@ "Unable to set expected packet loss percentage: %s\n", opus_strerror(ret)); + ret = opus_multistream_encoder_ctl(enc, + OPUS_SET_INBAND_FEC(opts->fec)); + if (ret != OPUS_OK) + av_log(avctx, AV_LOG_WARNING, + "Unable to set inband FEC: %s\n", + opus_strerror(ret)); + if (avctx->cutoff) { ret = opus_multistream_encoder_ctl(enc, OPUS_SET_MAX_BANDWIDTH(opts->max_bandwidth)); @@ -503,7 +511,6 @@ // Check if subtraction resulted in an overflow if ((discard_padding < opus->opts.packet_size) != (avpkt->duration > 0)) { av_packet_unref(avpkt); - av_free(avpkt); return AVERROR(EINVAL); } if (discard_padding > 0) { @@ -512,7 +519,6 @@ 10); if(!side_data) { av_packet_unref(avpkt); - av_free(avpkt); return AVERROR(ENOMEM); } AV_WL32(side_data + 4, discard_padding); @@ -546,6 +552,7 @@ { "lowdelay", "Restrict to only the lowest delay modes", 0, AV_OPT_TYPE_CONST, { .i64 = OPUS_APPLICATION_RESTRICTED_LOWDELAY }, 0, 0, FLAGS, "application" }, { "frame_duration", "Duration of a frame in milliseconds", OFFSET(frame_duration), AV_OPT_TYPE_FLOAT, { .dbl = 20.0 }, 2.5, 120.0, FLAGS }, { "packet_loss", "Expected packet loss percentage", OFFSET(packet_loss), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, FLAGS }, + { "fec", "Enable inband FEC. Expected packet loss must be non-zero", OFFSET(fec), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, { "vbr", "Variable bit rate mode", OFFSET(vbr), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 2, FLAGS, "vbr" }, { "off", "Use constant bit rate", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "vbr" }, { "on", "Use variable bit rate", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "vbr" }, diff -Nru ffmpeg-4.2.2/libavcodec/librav1e.c ffmpeg-4.4/libavcodec/librav1e.c --- ffmpeg-4.2.2/libavcodec/librav1e.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/librav1e.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,631 @@ +/* + * librav1e encoder + * + * Copyright (c) 2019 Derek Buitenhuis + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/internal.h" +#include "libavutil/avassert.h" +#include "libavutil/base64.h" +#include "libavutil/common.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avcodec.h" +#include "encode.h" +#include "internal.h" + +typedef struct librav1eContext { + const AVClass *class; + + RaContext *ctx; + AVFrame *frame; + RaFrame *rframe; + AVBSFContext *bsf; + + uint8_t *pass_data; + size_t pass_pos; + int pass_size; + + AVDictionary *rav1e_opts; + int quantizer; + int speed; + int tiles; + int tile_rows; + int tile_cols; +} librav1eContext; + +static inline RaPixelRange range_map(enum AVPixelFormat pix_fmt, enum AVColorRange range) +{ + switch (pix_fmt) { + case AV_PIX_FMT_YUVJ420P: + case AV_PIX_FMT_YUVJ422P: + case AV_PIX_FMT_YUVJ444P: + return RA_PIXEL_RANGE_FULL; + } + + switch (range) { + case AVCOL_RANGE_JPEG: + return RA_PIXEL_RANGE_FULL; + case AVCOL_RANGE_MPEG: + default: + return RA_PIXEL_RANGE_LIMITED; + } +} + +static inline RaChromaSampling pix_fmt_map(enum AVPixelFormat pix_fmt) +{ + switch (pix_fmt) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUVJ420P: + case AV_PIX_FMT_YUV420P10: + case AV_PIX_FMT_YUV420P12: + return RA_CHROMA_SAMPLING_CS420; + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUVJ422P: + case AV_PIX_FMT_YUV422P10: + case AV_PIX_FMT_YUV422P12: + return RA_CHROMA_SAMPLING_CS422; + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUVJ444P: + case AV_PIX_FMT_YUV444P10: + case AV_PIX_FMT_YUV444P12: + return RA_CHROMA_SAMPLING_CS444; + default: + av_assert0(0); + } +} + +static inline RaChromaSamplePosition chroma_loc_map(enum AVChromaLocation chroma_loc) +{ + switch (chroma_loc) { + case AVCHROMA_LOC_LEFT: + return RA_CHROMA_SAMPLE_POSITION_VERTICAL; + case AVCHROMA_LOC_TOPLEFT: + return RA_CHROMA_SAMPLE_POSITION_COLOCATED; + default: + return RA_CHROMA_SAMPLE_POSITION_UNKNOWN; + } +} + +static int get_stats(AVCodecContext *avctx, int eos) +{ + librav1eContext *ctx = avctx->priv_data; + RaData* buf = rav1e_twopass_out(ctx->ctx); + if (!buf) + return 0; + + if (!eos) { + uint8_t *tmp = av_fast_realloc(ctx->pass_data, &ctx->pass_size, + ctx->pass_pos + buf->len); + if (!tmp) { + rav1e_data_unref(buf); + return AVERROR(ENOMEM); + } + + ctx->pass_data = tmp; + memcpy(ctx->pass_data + ctx->pass_pos, buf->data, buf->len); + ctx->pass_pos += buf->len; + } else { + size_t b64_size = AV_BASE64_SIZE(ctx->pass_pos); + + memcpy(ctx->pass_data, buf->data, buf->len); + + avctx->stats_out = av_malloc(b64_size); + if (!avctx->stats_out) { + rav1e_data_unref(buf); + return AVERROR(ENOMEM); + } + + av_base64_encode(avctx->stats_out, b64_size, ctx->pass_data, ctx->pass_pos); + + av_freep(&ctx->pass_data); + } + + rav1e_data_unref(buf); + + return 0; +} + +static int set_stats(AVCodecContext *avctx) +{ + librav1eContext *ctx = avctx->priv_data; + int ret = 1; + + while (ret > 0 && ctx->pass_size - ctx->pass_pos > 0) { + ret = rav1e_twopass_in(ctx->ctx, ctx->pass_data + ctx->pass_pos, ctx->pass_size); + if (ret < 0) + return AVERROR_EXTERNAL; + ctx->pass_pos += ret; + } + + return 0; +} + +static av_cold int librav1e_encode_close(AVCodecContext *avctx) +{ + librav1eContext *ctx = avctx->priv_data; + + if (ctx->ctx) { + rav1e_context_unref(ctx->ctx); + ctx->ctx = NULL; + } + if (ctx->rframe) { + rav1e_frame_unref(ctx->rframe); + ctx->rframe = NULL; + } + + av_frame_free(&ctx->frame); + av_bsf_free(&ctx->bsf); + av_freep(&ctx->pass_data); + + return 0; +} + +static av_cold int librav1e_encode_init(AVCodecContext *avctx) +{ + librav1eContext *ctx = avctx->priv_data; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + RaConfig *cfg = NULL; + int rret; + int ret = 0; + + ctx->frame = av_frame_alloc(); + if (!ctx->frame) + return AVERROR(ENOMEM); + + cfg = rav1e_config_default(); + if (!cfg) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate rav1e config.\n"); + return AVERROR_EXTERNAL; + } + + /* + * Rav1e currently uses the time base given to it only for ratecontrol... where + * the inverse is taken and used as a framerate. So, do what we do in other wrappers + * and use the framerate if we can. + */ + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + rav1e_config_set_time_base(cfg, (RaRational) { + avctx->framerate.den, avctx->framerate.num + }); + } else { + rav1e_config_set_time_base(cfg, (RaRational) { + avctx->time_base.num * avctx->ticks_per_frame, + avctx->time_base.den + }); + } + + if ((avctx->flags & AV_CODEC_FLAG_PASS1 || avctx->flags & AV_CODEC_FLAG_PASS2) && !avctx->bit_rate) { + av_log(avctx, AV_LOG_ERROR, "A bitrate must be set to use two pass mode.\n"); + ret = AVERROR_INVALIDDATA; + goto end; + } + + if (avctx->flags & AV_CODEC_FLAG_PASS2) { + if (!avctx->stats_in) { + av_log(avctx, AV_LOG_ERROR, "No stats file provided for second pass.\n"); + ret = AVERROR(EINVAL); + goto end; + } + + ctx->pass_size = (strlen(avctx->stats_in) * 3) / 4; + ctx->pass_data = av_malloc(ctx->pass_size); + if (!ctx->pass_data) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate stats buffer.\n"); + ret = AVERROR(ENOMEM); + goto end; + } + + ctx->pass_size = av_base64_decode(ctx->pass_data, avctx->stats_in, ctx->pass_size); + if (ctx->pass_size < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid pass file.\n"); + ret = AVERROR(EINVAL); + goto end; + } + } + + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { + const AVBitStreamFilter *filter = av_bsf_get_by_name("extract_extradata"); + int bret; + + if (!filter) { + av_log(avctx, AV_LOG_ERROR, "extract_extradata bitstream filter " + "not found. This is a bug, please report it.\n"); + ret = AVERROR_BUG; + goto end; + } + + bret = av_bsf_alloc(filter, &ctx->bsf); + if (bret < 0) { + ret = bret; + goto end; + } + + bret = avcodec_parameters_from_context(ctx->bsf->par_in, avctx); + if (bret < 0) { + ret = bret; + goto end; + } + + bret = av_bsf_init(ctx->bsf); + if (bret < 0) { + ret = bret; + goto end; + } + } + + { + AVDictionaryEntry *en = NULL; + while ((en = av_dict_get(ctx->rav1e_opts, "", en, AV_DICT_IGNORE_SUFFIX))) { + int parse_ret = rav1e_config_parse(cfg, en->key, en->value); + if (parse_ret < 0) + av_log(avctx, AV_LOG_WARNING, "Invalid value for %s: %s.\n", en->key, en->value); + } + } + + rret = rav1e_config_parse_int(cfg, "width", avctx->width); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid width passed to rav1e.\n"); + ret = AVERROR_INVALIDDATA; + goto end; + } + + rret = rav1e_config_parse_int(cfg, "height", avctx->height); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid height passed to rav1e.\n"); + ret = AVERROR_INVALIDDATA; + goto end; + } + + rret = rav1e_config_parse_int(cfg, "threads", avctx->thread_count); + if (rret < 0) + av_log(avctx, AV_LOG_WARNING, "Invalid number of threads, defaulting to auto.\n"); + + if (ctx->speed >= 0) { + rret = rav1e_config_parse_int(cfg, "speed", ctx->speed); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set speed preset.\n"); + ret = AVERROR_EXTERNAL; + goto end; + } + } + + /* rav1e handles precedence between 'tiles' and cols/rows for us. */ + if (ctx->tiles > 0) { + rret = rav1e_config_parse_int(cfg, "tiles", ctx->tiles); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set number of tiles to encode with.\n"); + ret = AVERROR_EXTERNAL; + goto end; + } + } + if (ctx->tile_rows > 0) { + rret = rav1e_config_parse_int(cfg, "tile_rows", ctx->tile_rows); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set number of tile rows to encode with.\n"); + ret = AVERROR_EXTERNAL; + goto end; + } + } + if (ctx->tile_cols > 0) { + rret = rav1e_config_parse_int(cfg, "tile_cols", ctx->tile_cols); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set number of tile cols to encode with.\n"); + ret = AVERROR_EXTERNAL; + goto end; + } + } + + if (avctx->gop_size > 0) { + rret = rav1e_config_parse_int(cfg, "key_frame_interval", avctx->gop_size); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set max keyint.\n"); + ret = AVERROR_EXTERNAL; + goto end; + } + } + + if (avctx->keyint_min > 0) { + rret = rav1e_config_parse_int(cfg, "min_key_frame_interval", avctx->keyint_min); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set min keyint.\n"); + ret = AVERROR_EXTERNAL; + goto end; + } + } + + if (avctx->bit_rate && ctx->quantizer < 0) { + int max_quantizer = avctx->qmax >= 0 ? avctx->qmax : 255; + + rret = rav1e_config_parse_int(cfg, "quantizer", max_quantizer); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set max quantizer.\n"); + ret = AVERROR_EXTERNAL; + goto end; + } + + if (avctx->qmin >= 0) { + rret = rav1e_config_parse_int(cfg, "min_quantizer", avctx->qmin); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set min quantizer.\n"); + ret = AVERROR_EXTERNAL; + goto end; + } + } + + rret = rav1e_config_parse_int(cfg, "bitrate", avctx->bit_rate); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set bitrate.\n"); + ret = AVERROR_INVALIDDATA; + goto end; + } + } else if (ctx->quantizer >= 0) { + if (avctx->bit_rate) + av_log(avctx, AV_LOG_WARNING, "Both bitrate and quantizer specified. Using quantizer mode."); + + rret = rav1e_config_parse_int(cfg, "quantizer", ctx->quantizer); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set quantizer.\n"); + ret = AVERROR_EXTERNAL; + goto end; + } + } + + rret = rav1e_config_set_pixel_format(cfg, desc->comp[0].depth, + pix_fmt_map(avctx->pix_fmt), + chroma_loc_map(avctx->chroma_sample_location), + range_map(avctx->pix_fmt, avctx->color_range)); + if (rret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to set pixel format properties.\n"); + ret = AVERROR_INVALIDDATA; + goto end; + } + + /* rav1e's colorspace enums match standard values. */ + rret = rav1e_config_set_color_description(cfg, (RaMatrixCoefficients) avctx->colorspace, + (RaColorPrimaries) avctx->color_primaries, + (RaTransferCharacteristics) avctx->color_trc); + if (rret < 0) { + av_log(avctx, AV_LOG_WARNING, "Failed to set color properties.\n"); + if (avctx->err_recognition & AV_EF_EXPLODE) { + ret = AVERROR_INVALIDDATA; + goto end; + } + } + + ctx->ctx = rav1e_context_new(cfg); + if (!ctx->ctx) { + av_log(avctx, AV_LOG_ERROR, "Failed to create rav1e encode context.\n"); + ret = AVERROR_EXTERNAL; + goto end; + } + + ret = 0; + +end: + + rav1e_config_unref(cfg); + + return ret; +} + +static int librav1e_receive_packet(AVCodecContext *avctx, AVPacket *pkt) +{ + librav1eContext *ctx = avctx->priv_data; + RaFrame *rframe = ctx->rframe; + RaPacket *rpkt = NULL; + int ret; + + if (!rframe) { + AVFrame *frame = ctx->frame; + + ret = ff_encode_get_frame(avctx, frame); + if (ret < 0 && ret != AVERROR_EOF) + return ret; + + if (frame->buf[0]) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); + + int64_t *pts = av_malloc(sizeof(int64_t)); + if (!pts) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate PTS buffer.\n"); + return AVERROR(ENOMEM); + } + *pts = frame->pts; + + rframe = rav1e_frame_new(ctx->ctx); + if (!rframe) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate new rav1e frame.\n"); + av_frame_unref(frame); + av_freep(&pts); + return AVERROR(ENOMEM); + } + + for (int i = 0; i < desc->nb_components; i++) { + int shift = i ? desc->log2_chroma_h : 0; + int bytes = desc->comp[0].depth == 8 ? 1 : 2; + rav1e_frame_fill_plane(rframe, i, frame->data[i], + (frame->height >> shift) * frame->linesize[i], + frame->linesize[i], bytes); + } + av_frame_unref(frame); + rav1e_frame_set_opaque(rframe, pts, av_free); + } + } + + ret = rav1e_send_frame(ctx->ctx, rframe); + if (rframe) + if (ret == RA_ENCODER_STATUS_ENOUGH_DATA) { + ctx->rframe = rframe; /* Queue is full. Store the RaFrame to retry next call */ + } else { + rav1e_frame_unref(rframe); /* No need to unref if flushing. */ + ctx->rframe = NULL; + } + + switch (ret) { + case RA_ENCODER_STATUS_SUCCESS: + case RA_ENCODER_STATUS_ENOUGH_DATA: + break; + case RA_ENCODER_STATUS_FAILURE: + av_log(avctx, AV_LOG_ERROR, "Could not send frame: %s\n", rav1e_status_to_str(ret)); + return AVERROR_EXTERNAL; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown return code %d from rav1e_send_frame: %s\n", ret, rav1e_status_to_str(ret)); + return AVERROR_UNKNOWN; + } + +retry: + + if (avctx->flags & AV_CODEC_FLAG_PASS1) { + int sret = get_stats(avctx, 0); + if (sret < 0) + return sret; + } else if (avctx->flags & AV_CODEC_FLAG_PASS2) { + int sret = set_stats(avctx); + if (sret < 0) + return sret; + } + + ret = rav1e_receive_packet(ctx->ctx, &rpkt); + switch (ret) { + case RA_ENCODER_STATUS_SUCCESS: + break; + case RA_ENCODER_STATUS_LIMIT_REACHED: + if (avctx->flags & AV_CODEC_FLAG_PASS1) { + int sret = get_stats(avctx, 1); + if (sret < 0) + return sret; + } + return AVERROR_EOF; + case RA_ENCODER_STATUS_ENCODED: + goto retry; + case RA_ENCODER_STATUS_NEED_MORE_DATA: + if (avctx->internal->draining) { + av_log(avctx, AV_LOG_ERROR, "Unexpected error when receiving packet after EOF.\n"); + return AVERROR_EXTERNAL; + } + return AVERROR(EAGAIN); + case RA_ENCODER_STATUS_FAILURE: + av_log(avctx, AV_LOG_ERROR, "Could not encode frame: %s\n", rav1e_status_to_str(ret)); + return AVERROR_EXTERNAL; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown return code %d from rav1e_receive_packet: %s\n", ret, rav1e_status_to_str(ret)); + return AVERROR_UNKNOWN; + } + + ret = ff_get_encode_buffer(avctx, pkt, rpkt->len, 0); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate packet.\n"); + rav1e_packet_unref(rpkt); + return ret; + } + + memcpy(pkt->data, rpkt->data, rpkt->len); + + if (rpkt->frame_type == RA_FRAME_TYPE_KEY) + pkt->flags |= AV_PKT_FLAG_KEY; + + pkt->pts = pkt->dts = *((int64_t *) rpkt->opaque); + av_free(rpkt->opaque); + rav1e_packet_unref(rpkt); + + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { + int ret = av_bsf_send_packet(ctx->bsf, pkt); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "extradata extraction send failed.\n"); + av_packet_unref(pkt); + return ret; + } + + ret = av_bsf_receive_packet(ctx->bsf, pkt); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "extradata extraction receive failed.\n"); + av_packet_unref(pkt); + return ret; + } + } + + return 0; +} + +#define OFFSET(x) offsetof(librav1eContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM + +static const AVOption options[] = { + { "qp", "use constant quantizer mode", OFFSET(quantizer), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, VE }, + { "speed", "what speed preset to use", OFFSET(speed), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 10, VE }, + { "tiles", "number of tiles encode with", OFFSET(tiles), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT64_MAX, VE }, + { "tile-rows", "number of tiles rows to encode with", OFFSET(tile_rows), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT64_MAX, VE }, + { "tile-columns", "number of tiles columns to encode with", OFFSET(tile_cols), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT64_MAX, VE }, + { "rav1e-params", "set the rav1e configuration using a :-separated list of key=value parameters", OFFSET(rav1e_opts), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, + { NULL } +}; + +static const AVCodecDefault librav1e_defaults[] = { + { "b", "0" }, + { "g", "0" }, + { "keyint_min", "0" }, + { "qmax", "-1" }, + { "qmin", "-1" }, + { NULL } +}; + +const enum AVPixelFormat librav1e_pix_fmts[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUV420P10, + AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_YUV422P12, + AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_NONE +}; + +static const AVClass class = { + .class_name = "librav1e", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_librav1e_encoder = { + .name = "librav1e", + .long_name = NULL_IF_CONFIG_SMALL("librav1e AV1"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .init = librav1e_encode_init, + .receive_packet = librav1e_receive_packet, + .close = librav1e_encode_close, + .priv_data_size = sizeof(librav1eContext), + .priv_class = &class, + .defaults = librav1e_defaults, + .pix_fmts = librav1e_pix_fmts, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, + .wrapper_name = "librav1e", +}; diff -Nru ffmpeg-4.2.2/libavcodec/librsvgdec.c ffmpeg-4.4/libavcodec/librsvgdec.c --- ffmpeg-4.2.2/libavcodec/librsvgdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/librsvgdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -125,6 +125,6 @@ .id = AV_CODEC_ID_SVG, .decode = librsvg_decode_frame, .priv_data_size = sizeof(LibRSVGContext), - .capabilities = AV_CODEC_CAP_LOSSLESS | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .wrapper_name = "librsvg", }; diff -Nru ffmpeg-4.2.2/libavcodec/libspeexdec.c ffmpeg-4.4/libavcodec/libspeexdec.c --- ffmpeg-4.2.2/libavcodec/libspeexdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libspeexdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -199,6 +199,6 @@ .close = libspeex_decode_close, .decode = libspeex_decode_frame, .flush = libspeex_decode_flush, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .wrapper_name = "libspeex", }; diff -Nru ffmpeg-4.2.2/libavcodec/libsvtav1.c ffmpeg-4.4/libavcodec/libsvtav1.c --- ffmpeg-4.2.2/libavcodec/libsvtav1.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libsvtav1.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,572 @@ +/* + * Scalable Video Technology for AV1 encoder library plugin + * + * Copyright (c) 2018 Intel Corporation + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "libavutil/common.h" +#include "libavutil/frame.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/avassert.h" + +#include "internal.h" +#include "encode.h" +#include "packet_internal.h" +#include "avcodec.h" +#include "profiles.h" + +typedef enum eos_status { + EOS_NOT_REACHED = 0, + EOS_SENT, + EOS_RECEIVED +}EOS_STATUS; + +typedef struct SvtContext { + const AVClass *class; + + EbSvtAv1EncConfiguration enc_params; + EbComponentType *svt_handle; + + EbBufferHeaderType *in_buf; + int raw_size; + int max_tu_size; + + AVFrame *frame; + + AVBufferPool *pool; + + EOS_STATUS eos_flag; + + // User options. + int hierarchical_level; + int la_depth; + int enc_mode; + int rc_mode; + int scd; + int qp; + + int tier; + + int tile_columns; + int tile_rows; +} SvtContext; + +static const struct { + EbErrorType eb_err; + int av_err; + const char *desc; +} svt_errors[] = { + { EB_ErrorNone, 0, "success" }, + { EB_ErrorInsufficientResources, AVERROR(ENOMEM), "insufficient resources" }, + { EB_ErrorUndefined, AVERROR(EINVAL), "undefined error" }, + { EB_ErrorInvalidComponent, AVERROR(EINVAL), "invalid component" }, + { EB_ErrorBadParameter, AVERROR(EINVAL), "bad parameter" }, + { EB_ErrorDestroyThreadFailed, AVERROR_EXTERNAL, "failed to destroy thread" }, + { EB_ErrorSemaphoreUnresponsive, AVERROR_EXTERNAL, "semaphore unresponsive" }, + { EB_ErrorDestroySemaphoreFailed, AVERROR_EXTERNAL, "failed to destroy semaphore"}, + { EB_ErrorCreateMutexFailed, AVERROR_EXTERNAL, "failed to create mutex" }, + { EB_ErrorMutexUnresponsive, AVERROR_EXTERNAL, "mutex unresponsive" }, + { EB_ErrorDestroyMutexFailed, AVERROR_EXTERNAL, "failed to destroy mutex" }, + { EB_NoErrorEmptyQueue, AVERROR(EAGAIN), "empty queue" }, +}; + +static int svt_map_error(EbErrorType eb_err, const char **desc) +{ + int i; + + av_assert0(desc); + for (i = 0; i < FF_ARRAY_ELEMS(svt_errors); i++) { + if (svt_errors[i].eb_err == eb_err) { + *desc = svt_errors[i].desc; + return svt_errors[i].av_err; + } + } + *desc = "unknown error"; + return AVERROR_UNKNOWN; +} + +static int svt_print_error(void *log_ctx, EbErrorType err, + const char *error_string) +{ + const char *desc; + int ret = svt_map_error(err, &desc); + + av_log(log_ctx, AV_LOG_ERROR, "%s: %s (0x%x)\n", error_string, desc, err); + + return ret; +} + +static int alloc_buffer(EbSvtAv1EncConfiguration *config, SvtContext *svt_enc) +{ + const int pack_mode_10bit = + (config->encoder_bit_depth > 8) && (config->compressed_ten_bit_format == 0) ? 1 : 0; + const size_t luma_size_8bit = + config->source_width * config->source_height * (1 << pack_mode_10bit); + const size_t luma_size_10bit = + (config->encoder_bit_depth > 8 && pack_mode_10bit == 0) ? luma_size_8bit : 0; + + EbSvtIOFormat *in_data; + + svt_enc->raw_size = (luma_size_8bit + luma_size_10bit) * 3 / 2; + + // allocate buffer for in and out + svt_enc->in_buf = av_mallocz(sizeof(*svt_enc->in_buf)); + if (!svt_enc->in_buf) + return AVERROR(ENOMEM); + + svt_enc->in_buf->p_buffer = av_mallocz(sizeof(*in_data)); + if (!svt_enc->in_buf->p_buffer) + return AVERROR(ENOMEM); + + svt_enc->in_buf->size = sizeof(*svt_enc->in_buf); + + return 0; + +} + +static int config_enc_params(EbSvtAv1EncConfiguration *param, + AVCodecContext *avctx) +{ + SvtContext *svt_enc = avctx->priv_data; + const AVPixFmtDescriptor *desc; + + param->source_width = avctx->width; + param->source_height = avctx->height; + + desc = av_pix_fmt_desc_get(avctx->pix_fmt); + param->encoder_bit_depth = desc->comp[0].depth; + + if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 1) + param->encoder_color_format = EB_YUV420; + else if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 0) + param->encoder_color_format = EB_YUV422; + else if (!desc->log2_chroma_w && !desc->log2_chroma_h) + param->encoder_color_format = EB_YUV444; + else { + av_log(avctx, AV_LOG_ERROR , "Unsupported pixel format\n"); + return AVERROR(EINVAL); + } + + if (avctx->profile != FF_PROFILE_UNKNOWN) + param->profile = avctx->profile; + + if (avctx->level != FF_LEVEL_UNKNOWN) + param->level = avctx->level; + + if ((param->encoder_color_format == EB_YUV422 || param->encoder_bit_depth > 10) + && param->profile != FF_PROFILE_AV1_PROFESSIONAL ) { + av_log(avctx, AV_LOG_WARNING, "Forcing Professional profile\n"); + param->profile = FF_PROFILE_AV1_PROFESSIONAL; + } else if (param->encoder_color_format == EB_YUV444 && param->profile != FF_PROFILE_AV1_HIGH) { + av_log(avctx, AV_LOG_WARNING, "Forcing High profile\n"); + param->profile = FF_PROFILE_AV1_HIGH; + } + + // Update param from options + param->hierarchical_levels = svt_enc->hierarchical_level; + param->enc_mode = svt_enc->enc_mode; + param->tier = svt_enc->tier; + param->rate_control_mode = svt_enc->rc_mode; + param->scene_change_detection = svt_enc->scd; + param->qp = svt_enc->qp; + + param->target_bit_rate = avctx->bit_rate; + + if (avctx->gop_size > 0) + param->intra_period_length = avctx->gop_size - 1; + + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + param->frame_rate_numerator = avctx->framerate.num; + param->frame_rate_denominator = avctx->framerate.den; + } else { + param->frame_rate_numerator = avctx->time_base.den; + param->frame_rate_denominator = avctx->time_base.num * avctx->ticks_per_frame; + } + + if (param->rate_control_mode) { + param->max_qp_allowed = avctx->qmax; + param->min_qp_allowed = avctx->qmin; + } + + param->intra_refresh_type = 2; /* Real keyframes only */ + + if (svt_enc->la_depth >= 0) + param->look_ahead_distance = svt_enc->la_depth; + + param->tile_columns = svt_enc->tile_columns; + param->tile_rows = svt_enc->tile_rows; + + return 0; +} + +static int read_in_data(EbSvtAv1EncConfiguration *param, const AVFrame *frame, + EbBufferHeaderType *header_ptr) +{ + EbSvtIOFormat *in_data = (EbSvtIOFormat *)header_ptr->p_buffer; + ptrdiff_t linesizes[4]; + size_t sizes[4]; + int bytes_shift = param->encoder_bit_depth > 8 ? 1 : 0; + int ret, frame_size; + + for (int i = 0; i < 4; i++) + linesizes[i] = frame->linesize[i]; + + ret = av_image_fill_plane_sizes(sizes, frame->format, frame->height, + linesizes); + if (ret < 0) + return ret; + + frame_size = 0; + for (int i = 0; i < 4; i++) { + if (sizes[i] > INT_MAX - frame_size) + return AVERROR(EINVAL); + frame_size += sizes[i]; + } + + in_data->luma = frame->data[0]; + in_data->cb = frame->data[1]; + in_data->cr = frame->data[2]; + + in_data->y_stride = AV_CEIL_RSHIFT(frame->linesize[0], bytes_shift); + in_data->cb_stride = AV_CEIL_RSHIFT(frame->linesize[1], bytes_shift); + in_data->cr_stride = AV_CEIL_RSHIFT(frame->linesize[2], bytes_shift); + + header_ptr->n_filled_len = frame_size; + + return 0; +} + +static av_cold int eb_enc_init(AVCodecContext *avctx) +{ + SvtContext *svt_enc = avctx->priv_data; + EbErrorType svt_ret; + int ret; + + svt_enc->eos_flag = EOS_NOT_REACHED; + + svt_ret = svt_av1_enc_init_handle(&svt_enc->svt_handle, svt_enc, &svt_enc->enc_params); + if (svt_ret != EB_ErrorNone) { + return svt_print_error(avctx, svt_ret, "Error initializing encoder handle"); + } + + ret = config_enc_params(&svt_enc->enc_params, avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error configuring encoder parameters\n"); + return ret; + } + + svt_ret = svt_av1_enc_set_parameter(svt_enc->svt_handle, &svt_enc->enc_params); + if (svt_ret != EB_ErrorNone) { + return svt_print_error(avctx, svt_ret, "Error setting encoder parameters"); + } + + svt_ret = svt_av1_enc_init(svt_enc->svt_handle); + if (svt_ret != EB_ErrorNone) { + return svt_print_error(avctx, svt_ret, "Error initializing encoder"); + } + + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { + EbBufferHeaderType *headerPtr = NULL; + + svt_ret = svt_av1_enc_stream_header(svt_enc->svt_handle, &headerPtr); + if (svt_ret != EB_ErrorNone) { + return svt_print_error(avctx, svt_ret, "Error building stream header"); + } + + avctx->extradata_size = headerPtr->n_filled_len; + avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + av_log(avctx, AV_LOG_ERROR, + "Cannot allocate AV1 header of size %d.\n", avctx->extradata_size); + return AVERROR(ENOMEM); + } + + memcpy(avctx->extradata, headerPtr->p_buffer, avctx->extradata_size); + + svt_ret = svt_av1_enc_stream_header_release(headerPtr); + if (svt_ret != EB_ErrorNone) { + return svt_print_error(avctx, svt_ret, "Error freeing stream header"); + } + } + + svt_enc->frame = av_frame_alloc(); + if (!svt_enc->frame) + return AVERROR(ENOMEM); + + return alloc_buffer(&svt_enc->enc_params, svt_enc); +} + +static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame) +{ + SvtContext *svt_enc = avctx->priv_data; + EbBufferHeaderType *headerPtr = svt_enc->in_buf; + int ret; + + if (!frame) { + EbBufferHeaderType headerPtrLast; + + if (svt_enc->eos_flag == EOS_SENT) + return 0; + + headerPtrLast.n_alloc_len = 0; + headerPtrLast.n_filled_len = 0; + headerPtrLast.n_tick_count = 0; + headerPtrLast.p_app_private = NULL; + headerPtrLast.p_buffer = NULL; + headerPtrLast.flags = EB_BUFFERFLAG_EOS; + + svt_av1_enc_send_picture(svt_enc->svt_handle, &headerPtrLast); + svt_enc->eos_flag = EOS_SENT; + return 0; + } + + ret = read_in_data(&svt_enc->enc_params, frame, headerPtr); + if (ret < 0) + return ret; + + headerPtr->flags = 0; + headerPtr->p_app_private = NULL; + headerPtr->pts = frame->pts; + + svt_av1_enc_send_picture(svt_enc->svt_handle, headerPtr); + + return 0; +} + +static AVBufferRef *get_output_ref(AVCodecContext *avctx, SvtContext *svt_enc, int filled_len) +{ + if (filled_len > svt_enc->max_tu_size) { + const int max_frames = 8; + int max_tu_size; + + if (filled_len > svt_enc->raw_size * max_frames) { + av_log(avctx, AV_LOG_ERROR, "TU size > %d raw frame size.\n", max_frames); + return NULL; + } + + max_tu_size = 1 << av_ceil_log2(filled_len); + av_buffer_pool_uninit(&svt_enc->pool); + svt_enc->pool = av_buffer_pool_init(max_tu_size + AV_INPUT_BUFFER_PADDING_SIZE, NULL); + if (!svt_enc->pool) + return NULL; + + svt_enc->max_tu_size = max_tu_size; + } + av_assert0(svt_enc->pool); + + return av_buffer_pool_get(svt_enc->pool); +} + +static int eb_receive_packet(AVCodecContext *avctx, AVPacket *pkt) +{ + SvtContext *svt_enc = avctx->priv_data; + EbBufferHeaderType *headerPtr; + AVFrame *frame = svt_enc->frame; + EbErrorType svt_ret; + AVBufferRef *ref; + int ret = 0, pict_type; + + if (svt_enc->eos_flag == EOS_RECEIVED) + return AVERROR_EOF; + + ret = ff_encode_get_frame(avctx, frame); + if (ret < 0 && ret != AVERROR_EOF) + return ret; + if (ret == AVERROR_EOF) + frame = NULL; + + ret = eb_send_frame(avctx, frame); + if (ret < 0) + return ret; + av_frame_unref(svt_enc->frame); + + svt_ret = svt_av1_enc_get_packet(svt_enc->svt_handle, &headerPtr, svt_enc->eos_flag); + if (svt_ret == EB_NoErrorEmptyQueue) + return AVERROR(EAGAIN); + + ref = get_output_ref(avctx, svt_enc, headerPtr->n_filled_len); + if (!ref) { + av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n"); + svt_av1_enc_release_out_buffer(&headerPtr); + return AVERROR(ENOMEM); + } + pkt->buf = ref; + pkt->data = ref->data; + + memcpy(pkt->data, headerPtr->p_buffer, headerPtr->n_filled_len); + memset(pkt->data + headerPtr->n_filled_len, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + pkt->size = headerPtr->n_filled_len; + pkt->pts = headerPtr->pts; + pkt->dts = headerPtr->dts; + + switch (headerPtr->pic_type) { + case EB_AV1_KEY_PICTURE: + pkt->flags |= AV_PKT_FLAG_KEY; + // fall-through + case EB_AV1_INTRA_ONLY_PICTURE: + pict_type = AV_PICTURE_TYPE_I; + break; + case EB_AV1_INVALID_PICTURE: + pict_type = AV_PICTURE_TYPE_NONE; + break; + default: + pict_type = AV_PICTURE_TYPE_P; + break; + } + + if (headerPtr->pic_type == EB_AV1_NON_REF_PICTURE) + pkt->flags |= AV_PKT_FLAG_DISPOSABLE; + + if (headerPtr->flags & EB_BUFFERFLAG_EOS) + svt_enc->eos_flag = EOS_RECEIVED; + + ff_side_data_set_encoder_stats(pkt, headerPtr->qp * FF_QP2LAMBDA, NULL, 0, pict_type); + + svt_av1_enc_release_out_buffer(&headerPtr); + + return 0; +} + +static av_cold int eb_enc_close(AVCodecContext *avctx) +{ + SvtContext *svt_enc = avctx->priv_data; + + if (svt_enc->svt_handle) { + svt_av1_enc_deinit(svt_enc->svt_handle); + svt_av1_enc_deinit_handle(svt_enc->svt_handle); + } + if (svt_enc->in_buf) { + av_free(svt_enc->in_buf->p_buffer); + av_freep(&svt_enc->in_buf); + } + + av_buffer_pool_uninit(&svt_enc->pool); + av_frame_free(&svt_enc->frame); + + return 0; +} + +#define OFFSET(x) offsetof(SvtContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "hielevel", "Hierarchical prediction levels setting", OFFSET(hierarchical_level), + AV_OPT_TYPE_INT, { .i64 = 4 }, 3, 4, VE , "hielevel"}, + { "3level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, INT_MIN, INT_MAX, VE, "hielevel" }, + { "4level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 4 }, INT_MIN, INT_MAX, VE, "hielevel" }, + + { "la_depth", "Look ahead distance [0, 120]", OFFSET(la_depth), + AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 120, VE }, + + { "preset", "Encoding preset [0, 8]", + OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = MAX_ENC_PRESET }, 0, MAX_ENC_PRESET, VE }, + + { "tier", "Set operating point tier", OFFSET(tier), + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, "tier" }, + { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "tier" }, + { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "tier" }, + + FF_AV1_PROFILE_OPTS + +#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ + { .i64 = value }, 0, 0, VE, "avctx.level" + { LEVEL("2.0", 20) }, + { LEVEL("2.1", 21) }, + { LEVEL("2.2", 22) }, + { LEVEL("2.3", 23) }, + { LEVEL("3.0", 30) }, + { LEVEL("3.1", 31) }, + { LEVEL("3.2", 32) }, + { LEVEL("3.3", 33) }, + { LEVEL("4.0", 40) }, + { LEVEL("4.1", 41) }, + { LEVEL("4.2", 42) }, + { LEVEL("4.3", 43) }, + { LEVEL("5.0", 50) }, + { LEVEL("5.1", 51) }, + { LEVEL("5.2", 52) }, + { LEVEL("5.3", 53) }, + { LEVEL("6.0", 60) }, + { LEVEL("6.1", 61) }, + { LEVEL("6.2", 62) }, + { LEVEL("6.3", 63) }, + { LEVEL("7.0", 70) }, + { LEVEL("7.1", 71) }, + { LEVEL("7.2", 72) }, + { LEVEL("7.3", 73) }, +#undef LEVEL + + { "rc", "Bit rate control mode", OFFSET(rc_mode), + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 3, VE , "rc"}, + { "cqp", "Constant quantizer", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "rc" }, + { "vbr", "Variable Bit Rate, use a target bitrate for the entire stream", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "rc" }, + { "cvbr", "Constrained Variable Bit Rate, use a target bitrate for each GOP", 0, AV_OPT_TYPE_CONST,{ .i64 = 2 }, INT_MIN, INT_MAX, VE, "rc" }, + + { "qp", "Quantizer to use with cqp rate control mode", OFFSET(qp), + AV_OPT_TYPE_INT, { .i64 = 50 }, 0, 63, VE }, + + { "sc_detection", "Scene change detection", OFFSET(scd), + AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + + { "tile_columns", "Log2 of number of tile columns to use", OFFSET(tile_columns), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 4, VE}, + { "tile_rows", "Log2 of number of tile rows to use", OFFSET(tile_rows), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 6, VE}, + + {NULL}, +}; + +static const AVClass class = { + .class_name = "libsvtav1", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault eb_enc_defaults[] = { + { "b", "7M" }, + { "g", "-1" }, + { "qmin", "0" }, + { "qmax", "63" }, + { NULL }, +}; + +AVCodec ff_libsvtav1_encoder = { + .name = "libsvtav1", + .long_name = NULL_IF_CONFIG_SMALL("SVT-AV1(Scalable Video Technology for AV1) encoder"), + .priv_data_size = sizeof(SvtContext), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .init = eb_enc_init, + .receive_packet = eb_receive_packet, + .close = eb_enc_close, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV420P10, + AV_PIX_FMT_NONE }, + .priv_class = &class, + .defaults = eb_enc_defaults, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "libsvtav1", +}; diff -Nru ffmpeg-4.2.2/libavcodec/libtwolame.c ffmpeg-4.4/libavcodec/libtwolame.c --- ffmpeg-4.2.2/libavcodec/libtwolame.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libtwolame.c 2020-07-11 10:39:30.000000000 +0000 @@ -78,8 +78,12 @@ twolame_set_in_samplerate(s->glopts, avctx->sample_rate); twolame_set_out_samplerate(s->glopts, avctx->sample_rate); - if (!avctx->bit_rate) - avctx->bit_rate = avctx->sample_rate < 28000 ? 160000 : 384000; + if (!avctx->bit_rate) { + if ((s->mode == TWOLAME_AUTO_MODE && avctx->channels == 1) || s->mode == TWOLAME_MONO) + avctx->bit_rate = avctx->sample_rate < 28000 ? 80000 : 192000; + else + avctx->bit_rate = avctx->sample_rate < 28000 ? 160000 : 384000; + } if (avctx->flags & AV_CODEC_FLAG_QSCALE || !avctx->bit_rate) { twolame_set_VBR(s->glopts, TRUE); diff -Nru ffmpeg-4.2.2/libavcodec/libuavs3d.c ffmpeg-4.4/libavcodec/libuavs3d.c --- ffmpeg-4.2.2/libavcodec/libuavs3d.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libuavs3d.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,263 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang + * Bingjie Han + * Huiwen Ren + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/avutil.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "avs3.h" +#include "internal.h" +#include "uavs3d.h" + +typedef struct uavs3d_context { + AVCodecContext *avctx; + void *dec_handle; + int frame_threads; + int got_seqhdr; + uavs3d_io_frm_t dec_frame; +} uavs3d_context; + +#define UAVS3D_CHECK_START_CODE(data_ptr, PIC_START_CODE) \ + (AV_RL32(data_ptr) != (PIC_START_CODE << 24) + AVS3_NAL_START_CODE) +static int uavs3d_find_next_start_code(const unsigned char *bs_data, int bs_len, int *left) +{ + const unsigned char *data_ptr = bs_data + 4; + int count = bs_len - 4; + + while (count >= 4 && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTER_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_INTRA_PIC_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_FIRST_SLICE_START_CODE) && + UAVS3D_CHECK_START_CODE(data_ptr, AVS3_SEQ_END_CODE)) { + data_ptr++; + count--; + } + + if (count >= 4) { + *left = count; + return 1; + } + + return 0; +} + +static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { + uavs3d_io_frm_t frm_out; + AVFrame *frm = (AVFrame *)dec_frame->priv; + int i; + + if (!frm || !frm->data[0]) { + dec_frame->got_pic = 0; + av_log(NULL, AV_LOG_ERROR, "Invalid AVFrame in uavs3d output.\n"); + return; + } + + frm->pts = dec_frame->pts; + frm->pkt_dts = dec_frame->dts; + frm->pkt_pos = dec_frame->pkt_pos; + frm->pkt_size = dec_frame->pkt_size; + frm->coded_picture_number = dec_frame->dtr; + frm->display_picture_number = dec_frame->ptr; + + if (dec_frame->type < 0 || dec_frame->type >= 4) { + av_log(NULL, AV_LOG_WARNING, "Error frame type in uavs3d: %d.\n", dec_frame->type); + } + + frm->pict_type = ff_avs3_image_type[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); + + for (i = 0; i < 3; i++) { + frm_out.width [i] = dec_frame->width[i]; + frm_out.height[i] = dec_frame->height[i]; + frm_out.stride[i] = frm->linesize[i]; + frm_out.buffer[i] = frm->data[i]; + } + + uavs3d_img_cpy_cvt(&frm_out, dec_frame, dec_frame->bit_depth); +} + +static av_cold int libuavs3d_init(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + uavs3d_cfg_t cdsc; + + cdsc.frm_threads = avctx->thread_count > 0 ? avctx->thread_count : av_cpu_count(); + cdsc.check_md5 = 0; + h->dec_handle = uavs3d_create(&cdsc, uavs3d_output_callback, NULL); + h->got_seqhdr = 0; + + if (!h->dec_handle) { + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int libuavs3d_end(AVCodecContext *avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_flush(h->dec_handle, NULL); + uavs3d_delete(h->dec_handle); + h->dec_handle = NULL; + } + h->got_seqhdr = 0; + + return 0; +} + +static void libuavs3d_flush(AVCodecContext * avctx) +{ + uavs3d_context *h = avctx->priv_data; + + if (h->dec_handle) { + uavs3d_reset(h->dec_handle); + } +} + +#define UAVS3D_CHECK_INVALID_RANGE(v, l, r) ((v)<(l)||(v)>(r)) +static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + uavs3d_context *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + AVFrame *frm = data; + int left_bytes; + int ret, finish = 0; + + *got_frame = 0; + frm->pts = -1; + frm->pict_type = AV_PICTURE_TYPE_NONE; + + if (!buf_size) { + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + do { + ret = uavs3d_flush(h->dec_handle, &h->dec_frame); + } while (ret > 0 && !h->dec_frame.got_pic); + } else { + uavs3d_io_frm_t *frm_dec = &h->dec_frame; + + buf_ptr = buf; + buf_end = buf + buf_size; + frm_dec->pkt_pos = avpkt->pos; + frm_dec->pkt_size = avpkt->size; + + while (!finish) { + int bs_len; + + if (h->got_seqhdr) { + if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { + return ret; + } + h->dec_frame.priv = data; // AVFrame + } + + if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { + bs_len = buf_end - buf_ptr - left_bytes; + } else { + bs_len = buf_end - buf_ptr; + finish = 1; + } + frm_dec->bs = (unsigned char *)buf_ptr; + frm_dec->bs_len = bs_len; + frm_dec->pts = avpkt->pts; + frm_dec->dts = avpkt->dts; + uavs3d_decode(h->dec_handle, frm_dec); + buf_ptr += bs_len; + + if (frm_dec->nal_type == NAL_SEQ_HEADER) { + struct uavs3d_com_seqh_t *seqh = frm_dec->seqhdr; + if (UAVS3D_CHECK_INVALID_RANGE(seqh->frame_rate_code, 0, 15)) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame rate code: %d.\n", seqh->frame_rate_code); + seqh->frame_rate_code = 3; // default 25 fps + } else { + avctx->framerate.num = ff_avs3_frame_rate_tab[seqh->frame_rate_code].num; + avctx->framerate.den = ff_avs3_frame_rate_tab[seqh->frame_rate_code].den; + } + avctx->has_b_frames = !seqh->low_delay; + avctx->pix_fmt = seqh->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; + ff_set_dimensions(avctx, seqh->horizontal_size, seqh->vertical_size); + h->got_seqhdr = 1; + + if (seqh->colour_description) { + if (UAVS3D_CHECK_INVALID_RANGE(seqh->colour_primaries, 0, 9) || + UAVS3D_CHECK_INVALID_RANGE(seqh->transfer_characteristics, 0, 14) || + UAVS3D_CHECK_INVALID_RANGE(seqh->matrix_coefficients, 0, 11)) { + av_log(avctx, AV_LOG_ERROR, + "Invalid colour description: primaries: %d" + "transfer characteristics: %d" + "matrix coefficients: %d.\n", + seqh->colour_primaries, + seqh->transfer_characteristics, + seqh->matrix_coefficients); + } else { + avctx->color_primaries = ff_avs3_color_primaries_tab[seqh->colour_primaries]; + avctx->color_trc = ff_avs3_color_transfer_tab [seqh->transfer_characteristics]; + avctx->colorspace = ff_avs3_color_matrix_tab [seqh->matrix_coefficients]; + } + } + } + if (frm_dec->got_pic) { + break; + } + } + } + + *got_frame = h->dec_frame.got_pic; + + if (!(*got_frame)) { + av_frame_unref(frm); + } + + return buf_ptr - buf; +} + +AVCodec ff_libuavs3d_decoder = { + .name = "libuavs3d", + .long_name = NULL_IF_CONFIG_SMALL("libuavs3d AVS3-P2/IEEE1857.10"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS3, + .priv_data_size = sizeof(uavs3d_context), + .init = libuavs3d_init, + .close = libuavs3d_end, + .decode = libuavs3d_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, + .flush = libuavs3d_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV420P10LE, + AV_PIX_FMT_NONE }, + .wrapper_name = "libuavs3d", +}; diff -Nru ffmpeg-4.2.2/libavcodec/libvorbisdec.c ffmpeg-4.4/libavcodec/libvorbisdec.c --- ffmpeg-4.2.2/libavcodec/libvorbisdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libvorbisdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -217,5 +217,5 @@ .init = oggvorbis_decode_init, .decode = oggvorbis_decode_frame, .close = oggvorbis_decode_close, - .capabilities = AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF, }; diff -Nru ffmpeg-4.2.2/libavcodec/libvorbisenc.c ffmpeg-4.4/libavcodec/libvorbisenc.c --- ffmpeg-4.2.2/libavcodec/libvorbisenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libvorbisenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -70,6 +70,17 @@ .version = LIBAVUTIL_VERSION_INT, }; +static const uint8_t vorbis_encoding_channel_layout_offsets[8][8] = { + { 0 }, + { 0, 1 }, + { 0, 2, 1 }, + { 0, 1, 2, 3 }, + { 0, 2, 1, 3, 4 }, + { 0, 2, 1, 4, 5, 3 }, + { 0, 2, 1, 5, 6, 4, 3 }, + { 0, 2, 1, 6, 7, 4, 5, 3 }, +}; + static int vorbis_error_to_averror(int ov_err) { switch (ov_err) { @@ -287,7 +298,7 @@ buffer = vorbis_analysis_buffer(&s->vd, samples); for (c = 0; c < channels; c++) { int co = (channels > 8) ? c : - ff_vorbis_encoding_channel_layout_offsets[channels - 1][c]; + vorbis_encoding_channel_layout_offsets[channels - 1][c]; memcpy(buffer[c], frame->extended_data[co], samples * sizeof(*buffer[c])); } diff -Nru ffmpeg-4.2.2/libavcodec/libvpxdec.c ffmpeg-4.4/libavcodec/libvpxdec.c --- ffmpeg-4.2.2/libavcodec/libvpxdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libvpxdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,12 +25,14 @@ #define VPX_CODEC_DISABLE_COMPAT 1 #include +#include #include #include "libavutil/common.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "decode.h" #include "internal.h" #include "libvpx.h" #include "profiles.h" @@ -38,14 +40,50 @@ typedef struct VPxDecoderContext { struct vpx_codec_ctx decoder; struct vpx_codec_ctx decoder_alpha; + AVBufferPool *pool; + size_t pool_size; int has_alpha_channel; } VPxContext; + +static int get_frame_buffer(void *priv, size_t min_size, vpx_codec_frame_buffer_t *fb) +{ + VPxContext *ctx = priv; + AVBufferRef *buf; + + if (min_size > ctx->pool_size) { + av_buffer_pool_uninit(&ctx->pool); + /* According to the libvpx docs the buffer must be zeroed out. */ + ctx->pool = av_buffer_pool_init(min_size, av_buffer_allocz); + if (!ctx->pool) { + ctx->pool_size = 0; + return AVERROR(ENOMEM); + } + ctx->pool_size = min_size; + } + + buf = av_buffer_pool_get(ctx->pool); + if (!buf) + return AVERROR(ENOMEM); + + fb->priv = buf; + fb->size = ctx->pool_size; + fb->data = buf->data; + + return 0; +} + +static int release_frame_buffer(void *priv, vpx_codec_frame_buffer_t *fb) +{ + AVBufferRef *buf = fb->priv; + av_buffer_unref(&buf); + return 0; +} + static av_cold int vpx_init(AVCodecContext *avctx, - const struct vpx_codec_iface *iface, - int is_alpha_decoder) + struct vpx_codec_ctx* decoder, + const struct vpx_codec_iface *iface) { - VPxContext *ctx = avctx->priv_data; struct vpx_codec_dec_cfg deccfg = { .threads = FFMIN(avctx->thread_count ? avctx->thread_count : av_cpu_count(), 16) }; @@ -53,15 +91,16 @@ av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config()); - if (vpx_codec_dec_init( - is_alpha_decoder ? &ctx->decoder_alpha : &ctx->decoder, - iface, &deccfg, 0) != VPX_CODEC_OK) { - const char *error = vpx_codec_error(&ctx->decoder); + if (vpx_codec_dec_init(decoder, iface, &deccfg, 0) != VPX_CODEC_OK) { + const char *error = vpx_codec_error(decoder); av_log(avctx, AV_LOG_ERROR, "Failed to initialize decoder: %s\n", error); return AVERROR(EINVAL); } + if (avctx->codec_id == AV_CODEC_ID_VP9) + vpx_codec_set_frame_buffer_functions(decoder, get_frame_buffer, release_frame_buffer, avctx->priv_data); + return 0; } @@ -182,7 +221,7 @@ struct vpx_image *img, *img_alpha; int ret; uint8_t *side_data = NULL; - int side_data_size = 0; + buffer_size_t side_data_size; ret = decode_frame(avctx, &ctx->decoder, avpkt->data, avpkt->size); if (ret) @@ -191,7 +230,7 @@ side_data = av_packet_get_side_data(avpkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, &side_data_size); - if (side_data_size > 1) { + if (side_data_size >= 8) { const uint64_t additional_id = AV_RB64(side_data); side_data += 8; side_data_size -= 8; @@ -199,15 +238,16 @@ if (!ctx->has_alpha_channel) { ctx->has_alpha_channel = 1; ret = vpx_init(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_algo : &vpx_codec_vp9_dx_algo #elif CONFIG_LIBVPX_VP8_DECODER - &vpx_codec_vp8_dx_algo, + &vpx_codec_vp8_dx_algo #else - &vpx_codec_vp9_dx_algo, + &vpx_codec_vp9_dx_algo #endif - 1); + ); if (ret) return ret; } @@ -243,8 +283,17 @@ if (ret < 0) return ret; } - if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) - return ret; + + if (ctx->has_alpha_channel && + (img->d_w != img_alpha->d_w || + img->d_h != img_alpha->d_h || + img->bit_depth != img_alpha->bit_depth)) { + av_log(avctx, AV_LOG_ERROR, + "Video dimensions %dx%d@%dbpc differ from alpha dimensions %dx%d@%dbpc\n", + img->d_w, img->d_h, img->bit_depth, + img_alpha->d_w, img_alpha->d_h, img_alpha->bit_depth); + return AVERROR_INVALIDDATA; + } planes[0] = img->planes[VPX_PLANE_Y]; planes[1] = img->planes[VPX_PLANE_U]; @@ -256,8 +305,31 @@ linesizes[2] = img->stride[VPX_PLANE_V]; linesizes[3] = ctx->has_alpha_channel ? img_alpha->stride[VPX_PLANE_Y] : 0; - av_image_copy(picture->data, picture->linesize, (const uint8_t**)planes, - linesizes, avctx->pix_fmt, img->d_w, img->d_h); + + if (img->fb_priv && (!ctx->has_alpha_channel || img_alpha->fb_priv)) { + ret = ff_decode_frame_props(avctx, picture); + if (ret < 0) + return ret; + picture->buf[0] = av_buffer_ref(img->fb_priv); + if (!picture->buf[0]) + return AVERROR(ENOMEM); + if (ctx->has_alpha_channel) { + picture->buf[1] = av_buffer_ref(img_alpha->fb_priv); + if (!picture->buf[1]) { + av_frame_unref(picture); + return AVERROR(ENOMEM); + } + } + for (int i = 0; i < 4; i++) { + picture->data[i] = planes[i]; + picture->linesize[i] = linesizes[i]; + } + } else { + if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) + return ret; + av_image_copy(picture->data, picture->linesize, (const uint8_t**)planes, + linesizes, avctx->pix_fmt, img->d_w, img->d_h); + } *got_frame = 1; } return avpkt->size; @@ -269,13 +341,15 @@ vpx_codec_destroy(&ctx->decoder); if (ctx->has_alpha_channel) vpx_codec_destroy(&ctx->decoder_alpha); + av_buffer_pool_uninit(&ctx->pool); return 0; } #if CONFIG_LIBVPX_VP8_DECODER static av_cold int vp8_init(AVCodecContext *avctx) { - return vpx_init(avctx, &vpx_codec_vp8_dx_algo, 0); + VPxContext *ctx = avctx->priv_data; + return vpx_init(avctx, &ctx->decoder, &vpx_codec_vp8_dx_algo); } AVCodec ff_libvpx_vp8_decoder = { @@ -287,7 +361,8 @@ .init = vp8_init, .close = vpx_free, .decode = vpx_decode, - .capabilities = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .wrapper_name = "libvpx", }; #endif /* CONFIG_LIBVPX_VP8_DECODER */ @@ -295,7 +370,8 @@ #if CONFIG_LIBVPX_VP9_DECODER static av_cold int vp9_init(AVCodecContext *avctx) { - return vpx_init(avctx, &vpx_codec_vp9_dx_algo, 0); + VPxContext *ctx = avctx->priv_data; + return vpx_init(avctx, &ctx->decoder, &vpx_codec_vp9_dx_algo); } AVCodec ff_libvpx_vp9_decoder = { @@ -307,7 +383,8 @@ .init = vp9_init, .close = vpx_free, .decode = vpx_decode, - .capabilities = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .init_static_data = ff_vp9_init_static, .profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), .wrapper_name = "libvpx", diff -Nru ffmpeg-4.2.2/libavcodec/libvpxenc.c ffmpeg-4.4/libavcodec/libvpxenc.c --- ffmpeg-4.2.2/libavcodec/libvpxenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libvpxenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,6 +32,7 @@ #include "internal.h" #include "libavutil/avassert.h" #include "libvpx.h" +#include "packet_internal.h" #include "profiles.h" #include "libavutil/avstring.h" #include "libavutil/base64.h" @@ -40,6 +41,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" +#include "libavutil/pixdesc.h" /** * Portion of struct vpx_codec_cx_pkt from vpx_encoder.h. @@ -100,7 +102,9 @@ int rc_undershoot_pct; int rc_overshoot_pct; - char *vp8_ts_parameters; + AVDictionary *vpx_ts_parameters; + int *ts_layer_flags; + int current_temporal_idx; // VP9-only int lossless; @@ -116,6 +120,14 @@ int tune_content; int corpus_complexity; int tpl_model; + /** + * If the driver does not support ROI then warn the first time we + * encounter a frame with ROI side data. + */ + int roi_warned; +#if CONFIG_LIBVPX_VP9_ENCODER && defined(VPX_CTRL_VP9E_SET_MAX_INTER_BITRATE_PCT) + vpx_svc_ref_frame_config_t ref_frame_config; +#endif } VPxContext; /** String mappings for enum vp8e_enc_control_id */ @@ -132,6 +144,7 @@ [VP8E_SET_CQ_LEVEL] = "VP8E_SET_CQ_LEVEL", [VP8E_SET_MAX_INTRA_BITRATE_PCT] = "VP8E_SET_MAX_INTRA_BITRATE_PCT", [VP8E_SET_SHARPNESS] = "VP8E_SET_SHARPNESS", + [VP8E_SET_TEMPORAL_LAYER_ID] = "VP8E_SET_TEMPORAL_LAYER_ID", #if CONFIG_LIBVPX_VP9_ENCODER [VP9E_SET_LOSSLESS] = "VP9E_SET_LOSSLESS", [VP9E_SET_TILE_COLUMNS] = "VP9E_SET_TILE_COLUMNS", @@ -139,6 +152,12 @@ [VP9E_SET_FRAME_PARALLEL_DECODING] = "VP9E_SET_FRAME_PARALLEL_DECODING", [VP9E_SET_AQ_MODE] = "VP9E_SET_AQ_MODE", [VP9E_SET_COLOR_SPACE] = "VP9E_SET_COLOR_SPACE", + [VP9E_SET_SVC_LAYER_ID] = "VP9E_SET_SVC_LAYER_ID", +#if VPX_ENCODER_ABI_VERSION >= 12 + [VP9E_SET_SVC_PARAMETERS] = "VP9E_SET_SVC_PARAMETERS", + [VP9E_SET_SVC_REF_FRAME_CONFIG] = "VP9E_SET_SVC_REF_FRAME_CONFIG", +#endif + [VP9E_SET_SVC] = "VP9E_SET_SVC", #if VPX_ENCODER_ABI_VERSION >= 11 [VP9E_SET_COLOR_RANGE] = "VP9E_SET_COLOR_RANGE", #endif @@ -216,10 +235,22 @@ width, "rc_overshoot_pct:", cfg->rc_overshoot_pct); av_log(avctx, level, "temporal layering settings\n" " %*s%u\n", width, "ts_number_layers:", cfg->ts_number_layers); - av_log(avctx, level, - "\n %*s", width, "ts_target_bitrate:"); - for (i = 0; i < VPX_TS_MAX_LAYERS; i++) - av_log(avctx, level, "%u ", cfg->ts_target_bitrate[i]); + if (avctx->codec_id == AV_CODEC_ID_VP8) { + av_log(avctx, level, + "\n %*s", width, "ts_target_bitrate:"); + for (i = 0; i < VPX_TS_MAX_LAYERS; i++) + av_log(avctx, level, + "%u ", cfg->ts_target_bitrate[i]); + } +#if (VPX_ENCODER_ABI_VERSION >= 12) && CONFIG_LIBVPX_VP9_ENCODER + if (avctx->codec_id == AV_CODEC_ID_VP9) { + av_log(avctx, level, + "\n %*s", width, "layer_target_bitrate:"); + for (i = 0; i < VPX_TS_MAX_LAYERS; i++) + av_log(avctx, level, + "%u ", cfg->layer_target_bitrate[i]); + } +#endif av_log(avctx, level, "\n"); av_log(avctx, level, "\n %*s", width, "ts_rate_decimator:"); @@ -341,9 +372,14 @@ } #endif + av_freep(&ctx->ts_layer_flags); + vpx_codec_destroy(&ctx->encoder); - if (ctx->is_alpha) + if (ctx->is_alpha) { vpx_codec_destroy(&ctx->encoder_alpha); + av_freep(&ctx->rawimg_alpha.planes[VPX_PLANE_U]); + av_freep(&ctx->rawimg_alpha.planes[VPX_PLANE_V]); + } av_freep(&ctx->twopass_stats.buf); av_freep(&avctx->stats_out); free_frame_list(ctx->coded_frame_list); @@ -362,34 +398,255 @@ } } -static int vp8_ts_param_parse(struct vpx_codec_enc_cfg *enccfg, char *key, char *value) +#if CONFIG_LIBVPX_VP9_ENCODER && defined(VPX_CTRL_VP9E_SET_MAX_INTER_BITRATE_PCT) +static void vp8_ts_parse_int64_array(int64_t *dest, char *value, size_t value_len, int max_entries) +{ + int dest_idx = 0; + char *saveptr = NULL; + char *token = av_strtok(value, ",", &saveptr); + + while (token && dest_idx < max_entries) { + dest[dest_idx++] = strtoull(token, NULL, 10); + token = av_strtok(NULL, ",", &saveptr); + } +} +#endif + +static void set_temporal_layer_pattern(int layering_mode, vpx_codec_enc_cfg_t *cfg, + int *layer_flags, int *flag_periodicity) +{ + switch (layering_mode) { + case 2: { + /** + * 2-layers, 2-frame period. + */ + static const int ids[2] = { 0, 1 }; + cfg->ts_periodicity = 2; + *flag_periodicity = 2; + cfg->ts_number_layers = 2; + cfg->ts_rate_decimator[0] = 2; + cfg->ts_rate_decimator[1] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + + layer_flags[0] = + VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + layer_flags[1] = + VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_LAST | + VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF; + break; + } + case 3: { + /** + * 3-layers structure with one reference frame. + * This works same as temporal_layering_mode 3. + * + * 3-layers, 4-frame period. + */ + static const int ids[4] = { 0, 2, 1, 2 }; + cfg->ts_periodicity = 4; + *flag_periodicity = 4; + cfg->ts_number_layers = 3; + cfg->ts_rate_decimator[0] = 4; + cfg->ts_rate_decimator[1] = 2; + cfg->ts_rate_decimator[2] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + + /** + * 0=L, 1=GF, 2=ARF, + * Intra-layer prediction disabled. + */ + layer_flags[0] = + VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + layer_flags[1] = + VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + layer_flags[2] = + VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; + layer_flags[3] = + VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + break; + } + case 4: { + /** + * 3-layers structure. + * added dependency between the two TL2 frames (on top of case 3). + * 3-layers, 4-frame period. + */ + static const int ids[4] = { 0, 2, 1, 2 }; + cfg->ts_periodicity = 4; + *flag_periodicity = 4; + cfg->ts_number_layers = 3; + cfg->ts_rate_decimator[0] = 4; + cfg->ts_rate_decimator[1] = 2; + cfg->ts_rate_decimator[2] = 1; + memcpy(cfg->ts_layer_id, ids, sizeof(ids)); + + /** + * 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled. + */ + layer_flags[0] = + VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; + layer_flags[1] = + VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; + layer_flags[2] = + VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | + VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST; + layer_flags[3] = + VP8_EFLAG_NO_REF_LAST | + VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | + VP8_EFLAG_NO_UPD_ARF; + break; + } + default: + /** + * do not change the layer_flags or the flag_periodicity in this case; + * it might be that the code is using external flags to be used. + */ + break; + + } +} + +static int vpx_ts_param_parse(VPxContext *ctx, struct vpx_codec_enc_cfg *enccfg, + char *key, char *value, enum AVCodecID codec_id) { size_t value_len = strlen(value); + int ts_layering_mode = 0; if (!value_len) return -1; if (!strcmp(key, "ts_number_layers")) enccfg->ts_number_layers = strtoul(value, &value, 10); - else if (!strcmp(key, "ts_target_bitrate")) - vp8_ts_parse_int_array(enccfg->ts_target_bitrate, value, value_len, VPX_TS_MAX_LAYERS); - else if (!strcmp(key, "ts_rate_decimator")) - vp8_ts_parse_int_array(enccfg->ts_rate_decimator, value, value_len, VPX_TS_MAX_LAYERS); - else if (!strcmp(key, "ts_periodicity")) + else if (!strcmp(key, "ts_target_bitrate")) { + if (codec_id == AV_CODEC_ID_VP8) + vp8_ts_parse_int_array(enccfg->ts_target_bitrate, value, value_len, VPX_TS_MAX_LAYERS); +#if (VPX_ENCODER_ABI_VERSION >= 12) && CONFIG_LIBVPX_VP9_ENCODER + if (codec_id == AV_CODEC_ID_VP9) + vp8_ts_parse_int_array(enccfg->layer_target_bitrate, value, value_len, VPX_TS_MAX_LAYERS); +#endif + } else if (!strcmp(key, "ts_rate_decimator")) { + vp8_ts_parse_int_array(enccfg->ts_rate_decimator, value, value_len, VPX_TS_MAX_LAYERS); + } else if (!strcmp(key, "ts_periodicity")) { enccfg->ts_periodicity = strtoul(value, &value, 10); - else if (!strcmp(key, "ts_layer_id")) + } else if (!strcmp(key, "ts_layer_id")) { vp8_ts_parse_int_array(enccfg->ts_layer_id, value, value_len, VPX_TS_MAX_PERIODICITY); + } else if (!strcmp(key, "ts_layering_mode")) { + /* option for pre-defined temporal structures in function set_temporal_layer_pattern. */ + ts_layering_mode = strtoul(value, &value, 4); + } + +#if (VPX_ENCODER_ABI_VERSION >= 12) && CONFIG_LIBVPX_VP9_ENCODER + enccfg->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; // only bypass mode is supported for now. + enccfg->ss_number_layers = 1; // TODO: add spatial scalability support. +#endif + if (ts_layering_mode) { + // make sure the ts_layering_mode comes at the end of the ts_parameter string to ensure that + // correct configuration is done. + ctx->ts_layer_flags = av_malloc_array(VPX_TS_MAX_PERIODICITY, sizeof(*ctx->ts_layer_flags)); + set_temporal_layer_pattern(ts_layering_mode, enccfg, ctx->ts_layer_flags, &enccfg->ts_periodicity); + } + + return 0; +} + +#if CONFIG_LIBVPX_VP9_ENCODER && defined(VPX_CTRL_VP9E_SET_MAX_INTER_BITRATE_PCT) +static int vpx_ref_frame_config_set_value(vpx_svc_ref_frame_config_t *ref_frame_config, + int ss_number_layers, char *key, char *value) +{ + size_t value_len = strlen(value); + + if (!value_len) + return AVERROR(EINVAL); + + if (!strcmp(key, "rfc_update_buffer_slot")) { + vp8_ts_parse_int_array(ref_frame_config->update_buffer_slot, value, value_len, ss_number_layers); + } else if (!strcmp(key, "rfc_update_last")) { + vp8_ts_parse_int_array(ref_frame_config->update_last, value, value_len, ss_number_layers); + } else if (!strcmp(key, "rfc_update_golden")) { + vp8_ts_parse_int_array(ref_frame_config->update_golden, value, value_len, ss_number_layers); + } else if (!strcmp(key, "rfc_update_alt_ref")) { + vp8_ts_parse_int_array(ref_frame_config->update_alt_ref, value, value_len, ss_number_layers); + } else if (!strcmp(key, "rfc_lst_fb_idx")) { + vp8_ts_parse_int_array(ref_frame_config->lst_fb_idx, value, value_len, ss_number_layers); + } else if (!strcmp(key, "rfc_gld_fb_idx")) { + vp8_ts_parse_int_array(ref_frame_config->gld_fb_idx, value, value_len, ss_number_layers); + } else if (!strcmp(key, "rfc_alt_fb_idx")) { + vp8_ts_parse_int_array(ref_frame_config->alt_fb_idx, value, value_len, ss_number_layers); + } else if (!strcmp(key, "rfc_reference_last")) { + vp8_ts_parse_int_array(ref_frame_config->reference_last, value, value_len, ss_number_layers); + } else if (!strcmp(key, "rfc_reference_golden")) { + vp8_ts_parse_int_array(ref_frame_config->reference_golden, value, value_len, ss_number_layers); + } else if (!strcmp(key, "rfc_reference_alt_ref")) { + vp8_ts_parse_int_array(ref_frame_config->reference_alt_ref, value, value_len, ss_number_layers); + } else if (!strcmp(key, "rfc_reference_duration")) { + vp8_ts_parse_int64_array(ref_frame_config->duration, value, value_len, ss_number_layers); + } return 0; } +static int vpx_parse_ref_frame_config_element(vpx_svc_ref_frame_config_t *ref_frame_config, + int ss_number_layers, const char **buf) +{ + const char key_val_sep[] = "="; + const char pairs_sep[] = ":"; + char *key = av_get_token(buf, key_val_sep); + char *val = NULL; + int ret; + + if (key && *key && strspn(*buf, key_val_sep)) { + (*buf)++; + val = av_get_token(buf, pairs_sep); + } + + if (key && *key && val && *val) + ret = vpx_ref_frame_config_set_value(ref_frame_config, ss_number_layers, key, val); + else + ret = AVERROR(EINVAL); + + av_freep(&key); + av_freep(&val); + + return ret; +} + +static int vpx_parse_ref_frame_config(vpx_svc_ref_frame_config_t *ref_frame_config, + int ss_number_layers, const char *str) +{ + int ret = 0; + + while (*str) { + ret = + vpx_parse_ref_frame_config_element(ref_frame_config, ss_number_layers, &str); + if (ret < 0) + return ret; + + if (*str) + str++; + } + + return ret; +} +#endif + #if CONFIG_LIBVPX_VP9_ENCODER static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps, struct vpx_codec_enc_cfg *enccfg, vpx_codec_flags_t *flags, vpx_img_fmt_t *img_fmt) { VPxContext av_unused *ctx = avctx->priv_data; - enccfg->g_bit_depth = enccfg->g_input_bit_depth = 8; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + enccfg->g_bit_depth = enccfg->g_input_bit_depth = desc->comp[0].depth; switch (avctx->pix_fmt) { case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUVA420P: @@ -413,8 +670,6 @@ case AV_PIX_FMT_YUV420P10: case AV_PIX_FMT_YUV420P12: if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) { - enccfg->g_bit_depth = enccfg->g_input_bit_depth = - avctx->pix_fmt == AV_PIX_FMT_YUV420P10 ? 10 : 12; enccfg->g_profile = 2; *img_fmt = VPX_IMG_FMT_I42016; *flags |= VPX_CODEC_USE_HIGHBITDEPTH; @@ -424,8 +679,6 @@ case AV_PIX_FMT_YUV422P10: case AV_PIX_FMT_YUV422P12: if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) { - enccfg->g_bit_depth = enccfg->g_input_bit_depth = - avctx->pix_fmt == AV_PIX_FMT_YUV422P10 ? 10 : 12; enccfg->g_profile = 3; *img_fmt = VPX_IMG_FMT_I42216; *flags |= VPX_CODEC_USE_HIGHBITDEPTH; @@ -435,8 +688,6 @@ case AV_PIX_FMT_YUV440P10: case AV_PIX_FMT_YUV440P12: if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) { - enccfg->g_bit_depth = enccfg->g_input_bit_depth = - avctx->pix_fmt == AV_PIX_FMT_YUV440P10 ? 10 : 12; enccfg->g_profile = 3; *img_fmt = VPX_IMG_FMT_I44016; *flags |= VPX_CODEC_USE_HIGHBITDEPTH; @@ -449,9 +700,6 @@ case AV_PIX_FMT_YUV444P10: case AV_PIX_FMT_YUV444P12: if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) { - enccfg->g_bit_depth = enccfg->g_input_bit_depth = - avctx->pix_fmt == AV_PIX_FMT_YUV444P10 || - avctx->pix_fmt == AV_PIX_FMT_GBRP10 ? 10 : 12; enccfg->g_profile = 3; *img_fmt = VPX_IMG_FMT_I44416; *flags |= VPX_CODEC_USE_HIGHBITDEPTH; @@ -510,6 +758,66 @@ #endif #endif +/** + * Set the target bitrate to VPX library default. Also set CRF to 32 if needed. + */ +static void set_vp8_defaults(AVCodecContext *avctx, + struct vpx_codec_enc_cfg *enccfg) +{ + VPxContext *ctx = avctx->priv_data; + av_assert0(!avctx->bit_rate); + avctx->bit_rate = enccfg->rc_target_bitrate * 1000; + if (enccfg->rc_end_usage == VPX_CQ) { + av_log(avctx, AV_LOG_WARNING, + "Bitrate not specified for constrained quality mode, using default of %dkbit/sec\n", + enccfg->rc_target_bitrate); + } else { + enccfg->rc_end_usage = VPX_CQ; + ctx->crf = 32; + av_log(avctx, AV_LOG_WARNING, + "Neither bitrate nor constrained quality specified, using default CRF of %d and bitrate of %dkbit/sec\n", + ctx->crf, enccfg->rc_target_bitrate); + } +} + + +#if CONFIG_LIBVPX_VP9_ENCODER +/** + * Keep the target bitrate at 0 to engage constant quality mode. If CRF is not + * set, use 32. + */ +static void set_vp9_defaults(AVCodecContext *avctx, + struct vpx_codec_enc_cfg *enccfg) +{ + VPxContext *ctx = avctx->priv_data; + av_assert0(!avctx->bit_rate); + if (enccfg->rc_end_usage != VPX_Q && ctx->lossless < 0) { + enccfg->rc_end_usage = VPX_Q; + ctx->crf = 32; + av_log(avctx, AV_LOG_WARNING, + "Neither bitrate nor constrained quality specified, using default CRF of %d\n", + ctx->crf); + } +} +#endif + +/** + * Called when the bitrate is not set. It sets appropriate default values for + * bitrate and CRF. + */ +static void set_vpx_defaults(AVCodecContext *avctx, + struct vpx_codec_enc_cfg *enccfg) +{ + av_assert0(!avctx->bit_rate); +#if CONFIG_LIBVPX_VP9_ENCODER + if (avctx->codec_id == AV_CODEC_ID_VP9) { + set_vp9_defaults(avctx, enccfg); + return; + } +#endif + set_vp8_defaults(avctx, enccfg); +} + static av_cold int vpx_init(AVCodecContext *avctx, const struct vpx_codec_iface *iface) { @@ -522,7 +830,9 @@ vpx_img_fmt_t img_fmt = VPX_IMG_FMT_I420; #if CONFIG_LIBVPX_VP9_ENCODER vpx_codec_caps_t codec_caps = vpx_codec_get_caps(iface); + vpx_svc_extra_cfg_t svc_params; #endif + AVDictionaryEntry* en = NULL; av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config()); @@ -581,17 +891,11 @@ enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000, AV_ROUND_NEAR_INF); #if CONFIG_LIBVPX_VP9_ENCODER - } else if (enccfg.rc_end_usage == VPX_Q) { + enccfg.ss_target_bitrate[0] = enccfg.rc_target_bitrate; #endif } else { - if (enccfg.rc_end_usage == VPX_CQ) { - enccfg.rc_target_bitrate = 1000000; - } else { - avctx->bit_rate = enccfg.rc_target_bitrate * 1000; - av_log(avctx, AV_LOG_WARNING, - "Neither bitrate nor constrained quality specified, using default bitrate of %dkbit/sec\n", - enccfg.rc_target_bitrate); - } + // Set bitrate to default value. Also sets CRF to default if needed. + set_vpx_defaults(avctx, &enccfg); } if (avctx->codec_id == AV_CODEC_ID_VP9 && ctx->lossless == 1) { @@ -698,20 +1002,11 @@ enccfg.g_error_resilient = ctx->error_resilient || ctx->flags & VP8F_ERROR_RESILIENT; - if (CONFIG_LIBVPX_VP8_ENCODER && avctx->codec_id == AV_CODEC_ID_VP8 && ctx->vp8_ts_parameters) { - AVDictionary *dict = NULL; - AVDictionaryEntry* en = NULL; - - if (!av_dict_parse_string(&dict, ctx->vp8_ts_parameters, "=", ":", 0)) { - while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) { - if (vp8_ts_param_parse(&enccfg, en->key, en->value) < 0) - av_log(avctx, AV_LOG_WARNING, - "Error parsing option '%s = %s'.\n", - en->key, en->value); - } - - av_dict_free(&dict); - } + while ((en = av_dict_get(ctx->vpx_ts_parameters, "", en, AV_DICT_IGNORE_SUFFIX))) { + if (vpx_ts_param_parse(ctx, &enccfg, en->key, en->value, avctx->codec_id) < 0) + av_log(avctx, AV_LOG_WARNING, + "Error parsing option '%s = %s'.\n", + en->key, en->value); } dump_enc_cfg(avctx, &enccfg); @@ -721,7 +1016,21 @@ log_encoder_error(avctx, "Failed to initialize encoder"); return AVERROR(EINVAL); } - +#if CONFIG_LIBVPX_VP9_ENCODER + if (avctx->codec_id == AV_CODEC_ID_VP9 && enccfg.ts_number_layers > 1) { + memset(&svc_params, 0, sizeof(svc_params)); + for (int i = 0; i < enccfg.ts_number_layers; ++i) { + svc_params.max_quantizers[i] = enccfg.rc_max_quantizer; + svc_params.min_quantizers[i] = enccfg.rc_min_quantizer; + } + svc_params.scaling_factor_num[0] = enccfg.g_h; + svc_params.scaling_factor_den[0] = enccfg.g_h; +#if VPX_ENCODER_ABI_VERSION >= 12 + codecctl_int(avctx, VP9E_SET_SVC, 1); + codecctl_intp(avctx, VP9E_SET_SVC_PARAMETERS, (int *)&svc_params); +#endif + } +#endif if (ctx->is_alpha) { enccfg_alpha = enccfg; res = vpx_codec_enc_init(&ctx->encoder_alpha, iface, &enccfg_alpha, flags); @@ -816,10 +1125,6 @@ ctx->rawimg.bit_depth = enccfg.g_bit_depth; #endif - if (ctx->is_alpha) - vpx_img_wrap(&ctx->rawimg_alpha, VPX_IMG_FMT_I420, avctx->width, avctx->height, 1, - (unsigned char*)1); - cpb_props = ff_add_cpb_side_data(avctx); if (!cpb_props) return AVERROR(ENOMEM); @@ -916,7 +1221,7 @@ if (cx_frame->have_sse) { int i; /* Beware of the Y/U/V/all order! */ -#if FF_API_CODED_FRAME +#if FF_API_CODED_FRAME && FF_API_ERROR_FRAME FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->error[0] = cx_frame->sse[1]; avctx->coded_frame->error[1] = cx_frame->sse[2]; @@ -935,7 +1240,6 @@ cx_frame->sz_alpha + 8); if(!side_data) { av_packet_unref(pkt); - av_free(pkt); return AVERROR(ENOMEM); } AV_WB64(side_data, 1); @@ -992,8 +1296,7 @@ if (size < 0) return size; } else { - struct FrameListData *cx_frame = - av_malloc(sizeof(struct FrameListData)); + struct FrameListData *cx_frame = av_malloc(sizeof(*cx_frame)); if (!cx_frame) { av_log(avctx, AV_LOG_ERROR, @@ -1057,6 +1360,213 @@ return size; } +static int set_roi_map(AVCodecContext *avctx, const AVFrameSideData *sd, int frame_width, int frame_height, + vpx_roi_map_t *roi_map, int block_size, int segment_cnt) +{ + /** + * range of vpx_roi_map_t.delta_q[i] is [-63, 63] + */ +#define MAX_DELTA_Q 63 + + const AVRegionOfInterest *roi = NULL; + int nb_rois; + uint32_t self_size; + int segment_id; + + /* record the mapping from delta_q to "segment id + 1" in segment_mapping[]. + * the range of delta_q is [-MAX_DELTA_Q, MAX_DELTA_Q], + * and its corresponding array index is [0, 2 * MAX_DELTA_Q], + * and so the length of the mapping array is 2 * MAX_DELTA_Q + 1. + * "segment id + 1", so we can say there's no mapping if the value of array element is zero. + */ + int segment_mapping[2 * MAX_DELTA_Q + 1] = { 0 }; + + memset(roi_map, 0, sizeof(*roi_map)); + + /* segment id 0 in roi_map is reserved for the areas not covered by AVRegionOfInterest. + * segment id 0 in roi_map is also for the areas with AVRegionOfInterest.qoffset near 0. + * (delta_q of segment id 0 is 0). + */ + segment_mapping[MAX_DELTA_Q] = 1; + segment_id = 1; + + roi = (const AVRegionOfInterest*)sd->data; + self_size = roi->self_size; + if (!self_size || sd->size % self_size) { + av_log(avctx, AV_LOG_ERROR, "Invalid AVRegionOfInterest.self_size.\n"); + return AVERROR(EINVAL); + } + nb_rois = sd->size / self_size; + + /* This list must be iterated from zero because regions are + * defined in order of decreasing importance. So discard less + * important areas if they exceed the segment count. + */ + for (int i = 0; i < nb_rois; i++) { + int delta_q; + int mapping_index; + + roi = (const AVRegionOfInterest*)(sd->data + self_size * i); + if (!roi->qoffset.den) { + av_log(avctx, AV_LOG_ERROR, "AVRegionOfInterest.qoffset.den must not be zero.\n"); + return AVERROR(EINVAL); + } + + delta_q = (int)(roi->qoffset.num * 1.0f / roi->qoffset.den * MAX_DELTA_Q); + delta_q = av_clip(delta_q, -MAX_DELTA_Q, MAX_DELTA_Q); + + mapping_index = delta_q + MAX_DELTA_Q; + if (!segment_mapping[mapping_index]) { + if (segment_id == segment_cnt) { + av_log(avctx, AV_LOG_WARNING, + "ROI only supports %d segments (and segment 0 is reserved for non-ROIs), skipping the left ones.\n", + segment_cnt); + break; + } + + segment_mapping[mapping_index] = segment_id + 1; + roi_map->delta_q[segment_id] = delta_q; + segment_id++; + } + } + + roi_map->rows = (frame_height + block_size - 1) / block_size; + roi_map->cols = (frame_width + block_size - 1) / block_size; + roi_map->roi_map = av_mallocz_array(roi_map->rows * roi_map->cols, sizeof(*roi_map->roi_map)); + if (!roi_map->roi_map) { + av_log(avctx, AV_LOG_ERROR, "roi_map alloc failed.\n"); + return AVERROR(ENOMEM); + } + + /* This list must be iterated in reverse, so for the case that + * two regions are overlapping, the more important area takes effect. + */ + for (int i = nb_rois - 1; i >= 0; i--) { + int delta_q; + int mapping_value; + int starty, endy, startx, endx; + + roi = (const AVRegionOfInterest*)(sd->data + self_size * i); + + starty = av_clip(roi->top / block_size, 0, roi_map->rows); + endy = av_clip((roi->bottom + block_size - 1) / block_size, 0, roi_map->rows); + startx = av_clip(roi->left / block_size, 0, roi_map->cols); + endx = av_clip((roi->right + block_size - 1) / block_size, 0, roi_map->cols); + + delta_q = (int)(roi->qoffset.num * 1.0f / roi->qoffset.den * MAX_DELTA_Q); + delta_q = av_clip(delta_q, -MAX_DELTA_Q, MAX_DELTA_Q); + + mapping_value = segment_mapping[delta_q + MAX_DELTA_Q]; + if (mapping_value) { + for (int y = starty; y < endy; y++) + for (int x = startx; x < endx; x++) + roi_map->roi_map[x + y * roi_map->cols] = mapping_value - 1; + } + } + + return 0; +} + +static int vp9_encode_set_roi(AVCodecContext *avctx, int frame_width, int frame_height, const AVFrameSideData *sd) +{ + VPxContext *ctx = avctx->priv_data; + +#ifdef VPX_CTRL_VP9E_SET_ROI_MAP + int version = vpx_codec_version(); + int major = VPX_VERSION_MAJOR(version); + int minor = VPX_VERSION_MINOR(version); + int patch = VPX_VERSION_PATCH(version); + + if (major > 1 || (major == 1 && minor > 8) || (major == 1 && minor == 8 && patch >= 1)) { + vpx_roi_map_t roi_map; + const int segment_cnt = 8; + const int block_size = 8; + int ret; + + if (ctx->aq_mode > 0 || ctx->cpu_used < 5 || ctx->deadline != VPX_DL_REALTIME) { + if (!ctx->roi_warned) { + ctx->roi_warned = 1; + av_log(avctx, AV_LOG_WARNING, "ROI is only enabled when aq_mode is 0, cpu_used >= 5 " + "and deadline is REALTIME, so skipping ROI.\n"); + return AVERROR(EINVAL); + } + } + + ret = set_roi_map(avctx, sd, frame_width, frame_height, &roi_map, block_size, segment_cnt); + if (ret) { + log_encoder_error(avctx, "Failed to set_roi_map.\n"); + return ret; + } + + memset(roi_map.ref_frame, -1, sizeof(roi_map.ref_frame)); + + if (vpx_codec_control(&ctx->encoder, VP9E_SET_ROI_MAP, &roi_map)) { + log_encoder_error(avctx, "Failed to set VP9E_SET_ROI_MAP codec control.\n"); + ret = AVERROR_INVALIDDATA; + } + av_freep(&roi_map.roi_map); + return ret; + } +#endif + + if (!ctx->roi_warned) { + ctx->roi_warned = 1; + av_log(avctx, AV_LOG_WARNING, "ROI is not supported, please upgrade libvpx to version >= 1.8.1. " + "You may need to rebuild ffmpeg.\n"); + } + return 0; +} + +static int vp8_encode_set_roi(AVCodecContext *avctx, int frame_width, int frame_height, const AVFrameSideData *sd) +{ + vpx_roi_map_t roi_map; + const int segment_cnt = 4; + const int block_size = 16; + VPxContext *ctx = avctx->priv_data; + + int ret = set_roi_map(avctx, sd, frame_width, frame_height, &roi_map, block_size, segment_cnt); + if (ret) { + log_encoder_error(avctx, "Failed to set_roi_map.\n"); + return ret; + } + + if (vpx_codec_control(&ctx->encoder, VP8E_SET_ROI_MAP, &roi_map)) { + log_encoder_error(avctx, "Failed to set VP8E_SET_ROI_MAP codec control.\n"); + ret = AVERROR_INVALIDDATA; + } + + av_freep(&roi_map.roi_map); + return ret; +} + +static int realloc_alpha_uv(AVCodecContext *avctx, int width, int height) +{ + VPxContext *ctx = avctx->priv_data; + struct vpx_image *rawimg_alpha = &ctx->rawimg_alpha; + unsigned char **planes = rawimg_alpha->planes; + int *stride = rawimg_alpha->stride; + + if (!planes[VPX_PLANE_U] || + !planes[VPX_PLANE_V] || + width != (int)rawimg_alpha->d_w || + height != (int)rawimg_alpha->d_h) { + av_freep(&planes[VPX_PLANE_U]); + av_freep(&planes[VPX_PLANE_V]); + + vpx_img_wrap(rawimg_alpha, VPX_IMG_FMT_I420, width, height, 1, + (unsigned char*)1); + planes[VPX_PLANE_U] = av_malloc_array(stride[VPX_PLANE_U], height); + planes[VPX_PLANE_V] = av_malloc_array(stride[VPX_PLANE_V], height); + if (!planes[VPX_PLANE_U] || !planes[VPX_PLANE_V]) + return AVERROR(ENOMEM); + + memset(planes[VPX_PLANE_U], 0x80, stride[VPX_PLANE_U] * height); + memset(planes[VPX_PLANE_V], 0x80, stride[VPX_PLANE_V] * height); + } + + return 0; +} + static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { @@ -1066,8 +1576,12 @@ int64_t timestamp = 0; int res, coded_size; vpx_enc_frame_flags_t flags = 0; + const struct vpx_codec_enc_cfg *enccfg = ctx->encoder.config.enc; + vpx_svc_layer_id_t layer_id; + int layer_id_valid = 0; if (frame) { + const AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST); rawimg = &ctx->rawimg; rawimg->planes[VPX_PLANE_Y] = frame->data[0]; rawimg->planes[VPX_PLANE_U] = frame->data[1]; @@ -1076,23 +1590,12 @@ rawimg->stride[VPX_PLANE_U] = frame->linesize[1]; rawimg->stride[VPX_PLANE_V] = frame->linesize[2]; if (ctx->is_alpha) { - uint8_t *u_plane, *v_plane; rawimg_alpha = &ctx->rawimg_alpha; + res = realloc_alpha_uv(avctx, frame->width, frame->height); + if (res < 0) + return res; rawimg_alpha->planes[VPX_PLANE_Y] = frame->data[3]; - u_plane = av_malloc(frame->linesize[1] * frame->height); - v_plane = av_malloc(frame->linesize[2] * frame->height); - if (!u_plane || !v_plane) { - av_free(u_plane); - av_free(v_plane); - return AVERROR(ENOMEM); - } - memset(u_plane, 0x80, frame->linesize[1] * frame->height); - rawimg_alpha->planes[VPX_PLANE_U] = u_plane; - memset(v_plane, 0x80, frame->linesize[2] * frame->height); - rawimg_alpha->planes[VPX_PLANE_V] = v_plane; - rawimg_alpha->stride[VPX_PLANE_Y] = frame->linesize[0]; - rawimg_alpha->stride[VPX_PLANE_U] = frame->linesize[1]; - rawimg_alpha->stride[VPX_PLANE_V] = frame->linesize[2]; + rawimg_alpha->stride[VPX_PLANE_Y] = frame->linesize[3]; } timestamp = frame->pts; #if VPX_IMAGE_ABI_VERSION >= 4 @@ -1107,14 +1610,89 @@ #endif if (frame->pict_type == AV_PICTURE_TYPE_I) flags |= VPX_EFLAG_FORCE_KF; - if (CONFIG_LIBVPX_VP8_ENCODER && avctx->codec_id == AV_CODEC_ID_VP8 && frame->metadata) { + if (frame->metadata) { AVDictionaryEntry* en = av_dict_get(frame->metadata, "vp8-flags", NULL, 0); if (en) { flags |= strtoul(en->value, NULL, 10); } + + memset(&layer_id, 0, sizeof(layer_id)); + + en = av_dict_get(frame->metadata, "temporal_id", NULL, 0); + if (en) { + layer_id.temporal_layer_id = strtoul(en->value, NULL, 10); +#ifdef VPX_CTRL_VP9E_SET_MAX_INTER_BITRATE_PCT + layer_id.temporal_layer_id_per_spatial[0] = layer_id.temporal_layer_id; +#endif + layer_id_valid = 1; + } +#if CONFIG_LIBVPX_VP9_ENCODER && defined(VPX_CTRL_VP9E_SET_MAX_INTER_BITRATE_PCT) + en = av_dict_get(frame->metadata, "ref-frame-config", NULL, 0); + + if (en) { + if (avctx->codec_id == AV_CODEC_ID_VP9) { + int ret = vpx_parse_ref_frame_config(&ctx->ref_frame_config, + enccfg->ss_number_layers, en->value); + if (ret < 0) { + av_log(avctx, AV_LOG_WARNING, + "Error parsing ref_frame_config option %s.\n", en->value); + return ret; + } + + codecctl_intp(avctx, VP9E_SET_SVC_REF_FRAME_CONFIG, (int *)&ctx->ref_frame_config); + } else { + av_log(avctx, AV_LOG_WARNING, + "Ignoring ref-frame-config for a non-VP9 codec\n"); + } + } +#endif + } + + if (sd) { + if (avctx->codec_id == AV_CODEC_ID_VP8) { + vp8_encode_set_roi(avctx, frame->width, frame->height, sd); + } else { + vp9_encode_set_roi(avctx, frame->width, frame->height, sd); + } } } + // this is for encoding with preset temporal layering patterns defined in + // set_temporal_layer_pattern function. + if (enccfg->ts_number_layers > 1 && ctx->ts_layer_flags) { + if (flags & VPX_EFLAG_FORCE_KF) { + // keyframe, reset temporal layering. + ctx->current_temporal_idx = 0; + flags = VPX_EFLAG_FORCE_KF; + } else { + flags = 0; + } + + /* get the flags from the temporal layer configuration. */ + flags |= ctx->ts_layer_flags[ctx->current_temporal_idx]; + + memset(&layer_id, 0, sizeof(layer_id)); +#if VPX_ENCODER_ABI_VERSION >= 12 + layer_id.spatial_layer_id = 0; +#endif + layer_id.temporal_layer_id = enccfg->ts_layer_id[ctx->current_temporal_idx]; +#ifdef VPX_CTRL_VP9E_SET_MAX_INTER_BITRATE_PCT + layer_id.temporal_layer_id_per_spatial[0] = layer_id.temporal_layer_id; +#endif + layer_id_valid = 1; + } + + if (layer_id_valid) { + if (avctx->codec_id == AV_CODEC_ID_VP8) { + codecctl_int(avctx, VP8E_SET_TEMPORAL_LAYER_ID, layer_id.temporal_layer_id); + } +#if CONFIG_LIBVPX_VP9_ENCODER && VPX_ENCODER_ABI_VERSION >= 12 + else if (avctx->codec_id == AV_CODEC_ID_VP9) { + codecctl_intp(avctx, VP9E_SET_SVC_LAYER_ID, (int *)&layer_id); + } +#endif + } + res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp, avctx->ticks_per_frame, flags, ctx->deadline); if (res != VPX_CODEC_OK) { @@ -1144,11 +1722,8 @@ } av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf, ctx->twopass_stats.sz); - } - - if (rawimg_alpha) { - av_freep(&rawimg_alpha->planes[VPX_PLANE_U]); - av_freep(&rawimg_alpha->planes[VPX_PLANE_V]); + } else if (enccfg->ts_number_layers > 1 && ctx->ts_layer_flags) { + ctx->current_temporal_idx = (ctx->current_temporal_idx + 1) % enccfg->ts_periodicity; } *got_packet = !!coded_size; @@ -1179,7 +1754,7 @@ { "default", "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_DEFAULT}, 0, 0, VE, "er"}, \ { "partitions", "The frame partitions are independently decodable " \ "by the bool decoder, meaning that partitions can be decoded even " \ - "though earlier partitions have been lost. Note that intra predicition" \ + "though earlier partitions have been lost. Note that intra prediction" \ " is still done over the partition boundary.", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"}, \ { "crf", "Select the quality for constant quality mode", offsetof(VPxContext, crf), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 63, VE }, \ { "static-thresh", "A change threshold on blocks below which they will be skipped by the encoder", OFFSET(static_thresh), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, \ @@ -1187,6 +1762,7 @@ { "noise-sensitivity", "Noise sensitivity", OFFSET(noise_sensitivity), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 4, VE}, \ { "undershoot-pct", "Datarate undershoot (min) target (%)", OFFSET(rc_undershoot_pct), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 100, VE }, \ { "overshoot-pct", "Datarate overshoot (max) target (%)", OFFSET(rc_overshoot_pct), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1000, VE }, \ + { "ts-parameters", "Temporal scaling configuration using a :-separated list of key=value parameters", OFFSET(vpx_ts_parameters), AV_OPT_TYPE_DICT, {.str=NULL}, 0, 0, VE}, \ #define LEGACY_OPTIONS \ {"speed", "", offsetof(VPxContext, cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, -16, 16, VE}, \ @@ -1206,8 +1782,6 @@ { "auto-alt-ref", "Enable use of alternate reference " "frames (2-pass only)", OFFSET(auto_alt_ref), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, VE}, { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, -16, 16, VE}, - { "ts-parameters", "Temporal scaling configuration using a " - ":-separated list of key=value parameters", OFFSET(vp8_ts_parameters), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, LEGACY_OPTIONS { NULL } }; @@ -1266,6 +1840,7 @@ #undef LEGACY_OPTIONS static const AVCodecDefault defaults[] = { + { "b", "0" }, { "qmin", "-1" }, { "qmax", "-1" }, { "g", "-1" }, @@ -1295,7 +1870,8 @@ .init = vp8_init, .encode2 = vpx_encode, .close = vpx_free, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE }, .priv_class = &class_vp8, .defaults = defaults, @@ -1325,7 +1901,8 @@ .init = vp9_init, .encode2 = vpx_encode, .close = vpx_free, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), .priv_class = &class_vp9, .defaults = defaults, diff -Nru ffmpeg-4.2.2/libavcodec/libwavpackenc.c ffmpeg-4.4/libavcodec/libwavpackenc.c --- ffmpeg-4.2.2/libavcodec/libwavpackenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libwavpackenc.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,195 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include "libavutil/attributes.h" -#include "libavutil/opt.h" -#include "libavutil/samplefmt.h" - -#include "audio_frame_queue.h" -#include "avcodec.h" -#include "internal.h" - -#define WV_DEFAULT_BLOCK_SIZE 32768 - -typedef struct LibWavpackContext { - const AVClass *class; - WavpackContext *wv; - AudioFrameQueue afq; - - AVPacket *pkt; - int user_size; - - int got_output; -} LibWavpackContext; - -static int wavpack_encode_frame(AVCodecContext *avctx, AVPacket *pkt, - const AVFrame *frame, int *got_output) -{ - LibWavpackContext *s = avctx->priv_data; - int ret; - - s->got_output = 0; - s->pkt = pkt; - s->user_size = pkt->size; - - if (frame) { - ret = ff_af_queue_add(&s->afq, frame); - if (ret < 0) - return ret; - - ret = WavpackPackSamples(s->wv, (int32_t*)frame->data[0], frame->nb_samples); - if (!ret) { - av_log(avctx, AV_LOG_ERROR, "Error encoding a frame: %s\n", - WavpackGetErrorMessage(s->wv)); - return AVERROR_UNKNOWN; - } - } - - if (!s->got_output && - (!frame || frame->nb_samples < avctx->frame_size)) { - ret = WavpackFlushSamples(s->wv); - if (!ret) { - av_log(avctx, AV_LOG_ERROR, "Error flushing the encoder: %s\n", - WavpackGetErrorMessage(s->wv)); - return AVERROR_UNKNOWN; - } - } - - if (s->got_output) { - ff_af_queue_remove(&s->afq, avctx->frame_size, &pkt->pts, &pkt->duration); - *got_output = 1; - } - - return 0; -} - -static int encode_callback(void *id, void *data, int32_t count) -{ - AVCodecContext *avctx = id; - LibWavpackContext *s = avctx->priv_data; - int ret, offset = s->pkt->size; - - if (s->user_size) { - if (s->user_size - count < s->pkt->size) { - av_log(avctx, AV_LOG_ERROR, "Provided packet too small.\n"); - return 0; - } - s->pkt->size += count; - } else { - ret = av_grow_packet(s->pkt, count); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Error allocating output packet.\n"); - return 0; - } - } - - memcpy(s->pkt->data + offset, data, count); - - s->got_output = 1; - - return 1; -} - -static av_cold int wavpack_encode_init(AVCodecContext *avctx) -{ - LibWavpackContext *s = avctx->priv_data; - WavpackConfig config = { 0 }; - int ret; - - s->wv = WavpackOpenFileOutput(encode_callback, avctx, NULL); - if (!s->wv) { - av_log(avctx, AV_LOG_ERROR, "Error allocating the encoder.\n"); - return AVERROR(ENOMEM); - } - - if (!avctx->frame_size) - avctx->frame_size = WV_DEFAULT_BLOCK_SIZE; - - config.bytes_per_sample = 4; - config.bits_per_sample = 32; - config.block_samples = avctx->frame_size; - config.channel_mask = avctx->channel_layout; - config.num_channels = avctx->channels; - config.sample_rate = avctx->sample_rate; - - if (avctx->compression_level != FF_COMPRESSION_DEFAULT) { - if (avctx->compression_level >= 3) { - config.flags |= CONFIG_VERY_HIGH_FLAG; - - if (avctx->compression_level >= 8) - config.xmode = 6; - else if (avctx->compression_level >= 7) - config.xmode = 5; - else if (avctx->compression_level >= 6) - config.xmode = 4; - else if (avctx->compression_level >= 5) - config.xmode = 3; - else if (avctx->compression_level >= 4) - config.xmode = 2; - } else if (avctx->compression_level >= 2) - config.flags |= CONFIG_HIGH_FLAG; - else if (avctx->compression_level < 1) - config.flags |= CONFIG_FAST_FLAG; - } - - ret = WavpackSetConfiguration(s->wv, &config, -1); - if (!ret) - goto fail; - - ret = WavpackPackInit(s->wv); - if (!ret) - goto fail; - - ff_af_queue_init(avctx, &s->afq); - - return 0; - -fail: - av_log(avctx, AV_LOG_ERROR, "Error configuring the encoder: %s.\n", - WavpackGetErrorMessage(s->wv)); - WavpackCloseFile(s->wv); - return AVERROR_UNKNOWN; -} - -static av_cold int wavpack_encode_close(AVCodecContext *avctx) -{ - LibWavpackContext *s = avctx->priv_data; - - WavpackCloseFile(s->wv); - - ff_af_queue_close(&s->afq); - - return 0; -} - -AVCodec ff_libwavpack_encoder = { - .name = "libwavpack", - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_WAVPACK, - .priv_data_size = sizeof(LibWavpackContext), - .init = wavpack_encode_init, - .encode2 = wavpack_encode_frame, - .close = wavpack_encode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32, - AV_SAMPLE_FMT_NONE }, - .wrapper_name = "libwavpack", -}; diff -Nru ffmpeg-4.2.2/libavcodec/libwebpenc_common.c ffmpeg-4.4/libavcodec/libwebpenc_common.c --- ffmpeg-4.2.2/libavcodec/libwebpenc_common.c 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libwebpenc_common.c 2020-07-11 10:39:30.000000000 +0000 @@ -142,7 +142,7 @@ alt_frame->format = frame->format; if (s->cr_threshold) alt_frame->format = AV_PIX_FMT_YUVA420P; - ret = av_frame_get_buffer(alt_frame, 32); + ret = av_frame_get_buffer(alt_frame, 0); if (ret < 0) goto end; alt_frame->format = frame->format; diff -Nru ffmpeg-4.2.2/libavcodec/libx264.c ffmpeg-4.4/libavcodec/libx264.c --- ffmpeg-4.2.2/libavcodec/libx264.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libx264.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,9 +25,12 @@ #include "libavutil/mem.h" #include "libavutil/pixdesc.h" #include "libavutil/stereo3d.h" +#include "libavutil/time.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "internal.h" +#include "packet_internal.h" +#include "atsc_a53.h" #if defined(_MSC_VER) #define X264_API_IMPORTS 1 @@ -44,6 +47,11 @@ // blocks of pixels (with respect to the luma plane) #define MB_SIZE 16 +typedef struct X264Opaque { + int64_t reordered_opaque; + int64_t wallclock; +} X264Opaque; + typedef struct X264Context { AVClass *class; x264_param_t params; @@ -95,10 +103,16 @@ int scenechange_threshold; int noise_reduction; - char *x264_params; + AVDictionary *x264_params; int nb_reordered_opaque, next_reordered_opaque; - int64_t *reordered_opaque; + X264Opaque *reordered_opaque; + + /** + * If the encoder does not support ROI then warn the first time we + * encounter a frame with ROI side data. + */ + int roi_warned; } X264Context; static void X264_log(void *p, int level, const char *fmt, va_list args) @@ -183,51 +197,51 @@ AVFrameSideData *side_data; - if (x4->avcintra_class < 0) { - if (x4->params.b_interlaced && x4->params.b_tff != frame->top_field_first) { + if (x4->avcintra_class < 0) { + if (x4->params.b_interlaced && x4->params.b_tff != frame->top_field_first) { - x4->params.b_tff = frame->top_field_first; - x264_encoder_reconfig(x4->enc, &x4->params); - } - if (x4->params.vui.i_sar_height*ctx->sample_aspect_ratio.num != ctx->sample_aspect_ratio.den * x4->params.vui.i_sar_width) { - x4->params.vui.i_sar_height = ctx->sample_aspect_ratio.den; - x4->params.vui.i_sar_width = ctx->sample_aspect_ratio.num; - x264_encoder_reconfig(x4->enc, &x4->params); - } + x4->params.b_tff = frame->top_field_first; + x264_encoder_reconfig(x4->enc, &x4->params); + } + if (x4->params.vui.i_sar_height*ctx->sample_aspect_ratio.num != ctx->sample_aspect_ratio.den * x4->params.vui.i_sar_width) { + x4->params.vui.i_sar_height = ctx->sample_aspect_ratio.den; + x4->params.vui.i_sar_width = ctx->sample_aspect_ratio.num; + x264_encoder_reconfig(x4->enc, &x4->params); + } - if (x4->params.rc.i_vbv_buffer_size != ctx->rc_buffer_size / 1000 || - x4->params.rc.i_vbv_max_bitrate != ctx->rc_max_rate / 1000) { - x4->params.rc.i_vbv_buffer_size = ctx->rc_buffer_size / 1000; - x4->params.rc.i_vbv_max_bitrate = ctx->rc_max_rate / 1000; - x264_encoder_reconfig(x4->enc, &x4->params); - } + if (x4->params.rc.i_vbv_buffer_size != ctx->rc_buffer_size / 1000 || + x4->params.rc.i_vbv_max_bitrate != ctx->rc_max_rate / 1000) { + x4->params.rc.i_vbv_buffer_size = ctx->rc_buffer_size / 1000; + x4->params.rc.i_vbv_max_bitrate = ctx->rc_max_rate / 1000; + x264_encoder_reconfig(x4->enc, &x4->params); + } - if (x4->params.rc.i_rc_method == X264_RC_ABR && - x4->params.rc.i_bitrate != ctx->bit_rate / 1000) { - x4->params.rc.i_bitrate = ctx->bit_rate / 1000; - x264_encoder_reconfig(x4->enc, &x4->params); - } + if (x4->params.rc.i_rc_method == X264_RC_ABR && + x4->params.rc.i_bitrate != ctx->bit_rate / 1000) { + x4->params.rc.i_bitrate = ctx->bit_rate / 1000; + x264_encoder_reconfig(x4->enc, &x4->params); + } - if (x4->crf >= 0 && - x4->params.rc.i_rc_method == X264_RC_CRF && - x4->params.rc.f_rf_constant != x4->crf) { - x4->params.rc.f_rf_constant = x4->crf; - x264_encoder_reconfig(x4->enc, &x4->params); - } + if (x4->crf >= 0 && + x4->params.rc.i_rc_method == X264_RC_CRF && + x4->params.rc.f_rf_constant != x4->crf) { + x4->params.rc.f_rf_constant = x4->crf; + x264_encoder_reconfig(x4->enc, &x4->params); + } - if (x4->params.rc.i_rc_method == X264_RC_CQP && - x4->cqp >= 0 && - x4->params.rc.i_qp_constant != x4->cqp) { - x4->params.rc.i_qp_constant = x4->cqp; - x264_encoder_reconfig(x4->enc, &x4->params); - } + if (x4->params.rc.i_rc_method == X264_RC_CQP && + x4->cqp >= 0 && + x4->params.rc.i_qp_constant != x4->cqp) { + x4->params.rc.i_qp_constant = x4->cqp; + x264_encoder_reconfig(x4->enc, &x4->params); + } - if (x4->crf_max >= 0 && - x4->params.rc.f_rf_constant_max != x4->crf_max) { - x4->params.rc.f_rf_constant_max = x4->crf_max; - x264_encoder_reconfig(x4->enc, &x4->params); + if (x4->crf_max >= 0 && + x4->params.rc.f_rf_constant_max != x4->crf_max) { + x4->params.rc.f_rf_constant_max = x4->crf_max; + x264_encoder_reconfig(x4->enc, &x4->params); + } } - } side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_STEREO3D); if (side_data) { @@ -286,7 +300,8 @@ x264_picture_t pic_out = {0}; int pict_type; int bit_depth; - int64_t *out_opaque; + int64_t wallclock = 0; + X264Opaque *out_opaque; AVFrameSideData *sd; x264_picture_init( &x4->pic ); @@ -308,7 +323,10 @@ x4->pic.i_pts = frame->pts; - x4->reordered_opaque[x4->next_reordered_opaque] = frame->reordered_opaque; + x4->reordered_opaque[x4->next_reordered_opaque].reordered_opaque = frame->reordered_opaque; + x4->reordered_opaque[x4->next_reordered_opaque].wallclock = wallclock; + if (ctx->export_side_data & AV_CODEC_EXPORT_DATA_PRFT) + x4->reordered_opaque[x4->next_reordered_opaque].wallclock = av_gettime(); x4->pic.opaque = &x4->reordered_opaque[x4->next_reordered_opaque]; x4->next_reordered_opaque++; x4->next_reordered_opaque %= x4->nb_reordered_opaque; @@ -356,7 +374,10 @@ sd = av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST); if (sd) { if (x4->params.rc.i_aq_mode == X264_AQ_NONE) { - av_log(ctx, AV_LOG_WARNING, "Adaptive quantization must be enabled to use ROI encoding, skipping ROI.\n"); + if (!x4->roi_warned) { + x4->roi_warned = 1; + av_log(ctx, AV_LOG_WARNING, "Adaptive quantization must be enabled to use ROI encoding, skipping ROI.\n"); + } } else { if (frame->interlaced_frame == 0) { int mbx = (frame->width + MB_SIZE - 1) / MB_SIZE; @@ -410,7 +431,10 @@ x4->pic.prop.quant_offsets = qoffsets; x4->pic.prop.quant_offsets_free = av_free; } else { - av_log(ctx, AV_LOG_WARNING, "interlaced_frame not supported for ROI encoding yet, skipping ROI.\n"); + if (!x4->roi_warned) { + x4->roi_warned = 1; + av_log(ctx, AV_LOG_WARNING, "interlaced_frame not supported for ROI encoding yet, skipping ROI.\n"); + } } } } @@ -425,13 +449,17 @@ return ret; } while (!ret && !frame && x264_encoder_delayed_frames(x4->enc)); + if (!ret) + return 0; + pkt->pts = pic_out.i_pts; pkt->dts = pic_out.i_dts; out_opaque = pic_out.opaque; if (out_opaque >= x4->reordered_opaque && out_opaque < &x4->reordered_opaque[x4->nb_reordered_opaque]) { - ctx->reordered_opaque = *out_opaque; + ctx->reordered_opaque = out_opaque->reordered_opaque; + wallclock = out_opaque->wallclock; } else { // Unexpected opaque pointer on picture output ctx->reordered_opaque = 0; @@ -450,7 +478,8 @@ pict_type = AV_PICTURE_TYPE_B; break; default: - pict_type = AV_PICTURE_TYPE_NONE; + av_log(ctx, AV_LOG_ERROR, "Unknown picture type encountered.\n"); + return AVERROR_EXTERNAL; } #if FF_API_CODED_FRAME FF_DISABLE_DEPRECATION_WARNINGS @@ -461,6 +490,8 @@ pkt->flags |= AV_PKT_FLAG_KEY*pic_out.b_keyframe; if (ret) { ff_side_data_set_encoder_stats(pkt, (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA, NULL, 0, pict_type); + if (wallclock) + ff_side_data_set_prft(pkt, wallclock); #if FF_API_CODED_FRAME FF_DISABLE_DEPRECATION_WARNINGS @@ -481,6 +512,10 @@ av_freep(&x4->sei); av_freep(&x4->reordered_opaque); +#if X264_BUILD >= 161 + x264_param_cleanup(&x4->params); +#endif + if (x4->enc) { x264_encoder_close(x4->enc); x4->enc = NULL; @@ -489,19 +524,31 @@ return 0; } -#define OPT_STR(opt, param) \ - do { \ - int ret; \ - if ((ret = x264_param_parse(&x4->params, opt, param)) < 0) { \ - if(ret == X264_PARAM_BAD_NAME) \ - av_log(avctx, AV_LOG_ERROR, \ - "bad option '%s': '%s'\n", opt, param); \ - else \ - av_log(avctx, AV_LOG_ERROR, \ - "bad value for '%s': '%s'\n", opt, param); \ - return -1; \ - } \ - } while (0) +static int parse_opts(AVCodecContext *avctx, const char *opt, const char *param) +{ + X264Context *x4 = avctx->priv_data; + int ret; + + if ((ret = x264_param_parse(&x4->params, opt, param)) < 0) { + if (ret == X264_PARAM_BAD_NAME) { + av_log(avctx, AV_LOG_ERROR, + "bad option '%s': '%s'\n", opt, param); + ret = AVERROR(EINVAL); +#if X264_BUILD >= 161 + } else if (ret == X264_PARAM_ALLOC_FAILED) { + av_log(avctx, AV_LOG_ERROR, + "out of memory parsing option '%s': '%s'\n", opt, param); + ret = AVERROR(ENOMEM); +#endif + } else { + av_log(avctx, AV_LOG_ERROR, + "bad value for '%s': '%s'\n", opt, param); + ret = AVERROR(EINVAL); + } + } + + return ret; +} static int convert_pix_fmt(enum AVPixelFormat pix_fmt) { @@ -551,6 +598,7 @@ X264Context *x4 = avctx->priv_data; AVCPBProperties *cpb_props; int sw,sh; + int ret; if (avctx->global_quality > 0) av_log(avctx, AV_LOG_WARNING, "-qscale is ignored, -crf is recommended.\n"); @@ -594,6 +642,10 @@ PARSE_X264_OPT("weightp", wpredp); if (avctx->bit_rate) { + if (avctx->bit_rate / 1000 > INT_MAX || avctx->rc_max_rate / 1000 > INT_MAX) { + av_log(avctx, AV_LOG_ERROR, "bit_rate and rc_max_rate > %d000 not supported by libx264\n", INT_MAX); + return AVERROR(EINVAL); + } x4->params.rc.i_bitrate = avctx->bit_rate / 1000; x4->params.rc.i_rc_method = X264_RC_ABR; } @@ -630,11 +682,11 @@ #if FF_API_PRIVATE_OPT FF_DISABLE_DEPRECATION_WARNINGS - if (avctx->chromaoffset >= 0) + if (avctx->chromaoffset) x4->chroma_offset = avctx->chromaoffset; FF_ENABLE_DEPRECATION_WARNINGS #endif - if (x4->chroma_offset >= 0) + if (x4->chroma_offset) x4->params.analyse.i_chroma_qp_offset = x4->chroma_offset; if (avctx->gop_size >= 0) @@ -663,25 +715,13 @@ x4->params.rc.f_qcompress = avctx->qcompress; /* 0.0 => cbr, 1.0 => constant qp */ if (avctx->refs >= 0) x4->params.i_frame_reference = avctx->refs; - else if (x4->level) { + else if (x4->params.i_level_idc > 0) { int i; int mbn = AV_CEIL_RSHIFT(avctx->width, 4) * AV_CEIL_RSHIFT(avctx->height, 4); - int level_id = -1; - char *tail; int scale = X264_BUILD < 129 ? 384 : 1; - if (!strcmp(x4->level, "1b")) { - level_id = 9; - } else if (strlen(x4->level) <= 3){ - level_id = av_strtod(x4->level, &tail) * 10 + 0.5; - if (*tail) - level_id = -1; - } - if (level_id <= 0) - av_log(avctx, AV_LOG_WARNING, "Failed to parse level\n"); - for (i = 0; iparams.i_level_idc) x4->params.i_frame_reference = av_clip(x264_levels[i].dpb / mbn / scale, 1, x4->params.i_frame_reference); } @@ -868,27 +908,32 @@ while(p){ char param[4096]={0}, val[4096]={0}; if(sscanf(p, "%4095[^:=]=%4095[^:]", param, val) == 1){ - OPT_STR(param, "1"); - }else - OPT_STR(param, val); + ret = parse_opts(avctx, param, "1"); + if (ret < 0) + return ret; + } else { + ret = parse_opts(avctx, param, val); + if (ret < 0) + return ret; + } p= strchr(p, ':'); p+=!!p; } } - if (x4->x264_params) { - AVDictionary *dict = NULL; - AVDictionaryEntry *en = NULL; - - if (!av_dict_parse_string(&dict, x4->x264_params, "=", ":", 0)) { - while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) { - if (x264_param_parse(&x4->params, en->key, en->value) < 0) - av_log(avctx, AV_LOG_WARNING, - "Error parsing option '%s = %s'.\n", - en->key, en->value); - } - av_dict_free(&dict); + { + AVDictionaryEntry *en = NULL; + while (en = av_dict_get(x4->x264_params, "", en, AV_DICT_IGNORE_SUFFIX)) { + if ((ret = x264_param_parse(&x4->params, en->key, en->value)) < 0) { + av_log(avctx, AV_LOG_WARNING, + "Error parsing option '%s = %s'.\n", + en->key, en->value); +#if X264_BUILD >= 161 + if (ret == X264_PARAM_ALLOC_FAILED) + return AVERROR(ENOMEM); +#endif + } } } @@ -898,7 +943,7 @@ if (avctx->max_b_frames < 0) avctx->max_b_frames = 0; - avctx->bit_rate = x4->params.rc.i_bitrate*1000; + avctx->bit_rate = x4->params.rc.i_bitrate*1000LL; x4->enc = x264_encoder_open(&x4->params); if (!x4->enc) @@ -935,8 +980,8 @@ if (!cpb_props) return AVERROR(ENOMEM); cpb_props->buffer_size = x4->params.rc.i_vbv_buffer_size * 1000; - cpb_props->max_bitrate = x4->params.rc.i_vbv_max_bitrate * 1000; - cpb_props->avg_bitrate = x4->params.rc.i_bitrate * 1000; + cpb_props->max_bitrate = x4->params.rc.i_vbv_max_bitrate * 1000LL; + cpb_props->avg_bitrate = x4->params.rc.i_bitrate * 1000LL; // Overestimate the reordered opaque buffer size, in case a runtime // reconfigure would increase the delay (which it shouldn't). @@ -1006,19 +1051,17 @@ }; #endif +#if X264_BUILD < 153 static av_cold void X264_init_static(AVCodec *codec) { -#if X264_BUILD < 153 if (x264_bit_depth == 8) codec->pix_fmts = pix_fmts_8bit; else if (x264_bit_depth == 9) codec->pix_fmts = pix_fmts_9bit; else if (x264_bit_depth == 10) codec->pix_fmts = pix_fmts_10bit; -#else - codec->pix_fmts = pix_fmts_all; -#endif } +#endif #define OFFSET(x) offsetof(X264Context, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM @@ -1096,11 +1139,11 @@ { "vlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "coder" }, { "ac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "coder" }, { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 2, VE }, - { "chromaoffset", "QP difference between chroma and luma", OFFSET(chroma_offset), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE }, + { "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 }, - { "x264-params", "Override the x264 configuration using a :-separated list of key=value parameters", OFFSET(x264_params), AV_OPT_TYPE_STRING, { 0 }, 0, 0, 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 }, }; @@ -1159,12 +1202,21 @@ .init = X264_init, .encode2 = X264_frame, .close = X264_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS | + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .priv_class = &x264_class, .defaults = x264_defaults, +#if X264_BUILD < 153 .init_static_data = X264_init_static, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +#else + .pix_fmts = pix_fmts_all, +#endif + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS +#if X264_BUILD >= 158 + | FF_CODEC_CAP_INIT_THREADSAFE +#endif + , .wrapper_name = "libx264", }; #endif @@ -1186,11 +1238,16 @@ .init = X264_init, .encode2 = X264_frame, .close = X264_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS | + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_class = &rgbclass, .defaults = x264_defaults, .pix_fmts = pix_fmts_8bit_rgb, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS +#if X264_BUILD >= 158 + | FF_CODEC_CAP_INIT_THREADSAFE +#endif + , .wrapper_name = "libx264", }; #endif @@ -1212,12 +1269,12 @@ .init = X264_init, .encode2 = X264_frame, .close = X264_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS | + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, .priv_class = &X262_class, .defaults = x264_defaults, .pix_fmts = pix_fmts_8bit, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, .wrapper_name = "libx264", }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/libx265.c ffmpeg-4.4/libavcodec/libx265.c --- ffmpeg-4.2.2/libavcodec/libx265.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libx265.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,6 +33,7 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" #include "internal.h" +#include "packet_internal.h" typedef struct libx265Context { const AVClass *class; @@ -42,11 +43,18 @@ const x265_api *api; float crf; + int cqp; int forced_idr; char *preset; char *tune; char *profile; - char *x265_opts; + AVDictionary *x265_opts; + + /** + * If the encoder does not support ROI then warn the first time we + * encounter a frame with ROI side data. + */ + int roi_warned; } libx265Context; static int is_keyframe(NalUnitType naltype) @@ -76,10 +84,41 @@ return 0; } +static av_cold int libx265_param_parse_float(AVCodecContext *avctx, + const char *key, float value) +{ + libx265Context *ctx = avctx->priv_data; + char buf[256]; + + snprintf(buf, sizeof(buf), "%2.2f", value); + if (ctx->api->param_parse(ctx->params, key, buf) == X265_PARAM_BAD_VALUE) { + av_log(avctx, AV_LOG_ERROR, "Invalid value %2.2f for param \"%s\".\n", value, key); + return AVERROR(EINVAL); + } + + return 0; +} + +static av_cold int libx265_param_parse_int(AVCodecContext *avctx, + const char *key, int value) +{ + libx265Context *ctx = avctx->priv_data; + char buf[256]; + + snprintf(buf, sizeof(buf), "%d", value); + if (ctx->api->param_parse(ctx->params, key, buf) == X265_PARAM_BAD_VALUE) { + av_log(avctx, AV_LOG_ERROR, "Invalid value %d for param \"%s\".\n", value, key); + return AVERROR(EINVAL); + } + + return 0; +} + static av_cold int libx265_encode_init(AVCodecContext *avctx) { libx265Context *ctx = avctx->priv_data; AVCPBProperties *cpb_props = NULL; + int ret; ctx->api = x265_api_get(av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth); if (!ctx->api) @@ -153,6 +192,10 @@ // x265 validates the parameters internally ctx->params->vui.colorPrimaries = avctx->color_primaries; ctx->params->vui.transferCharacteristics = avctx->color_trc; +#if X265_BUILD >= 159 + if (avctx->color_trc == AVCOL_TRC_ARIB_STD_B67) + ctx->params->preferredTransferCharacteristics = ctx->params->vui.transferCharacteristics; +#endif ctx->params->vui.matrixCoeffs = avctx->colorspace; } @@ -216,6 +259,48 @@ } else if (avctx->bit_rate > 0) { ctx->params->rc.bitrate = avctx->bit_rate / 1000; ctx->params->rc.rateControlMode = X265_RC_ABR; + } else if (ctx->cqp >= 0) { + ret = libx265_param_parse_int(avctx, "qp", ctx->cqp); + if (ret < 0) + return ret; + } + +#if X265_BUILD >= 89 + if (avctx->qmin >= 0) { + ret = libx265_param_parse_int(avctx, "qpmin", avctx->qmin); + if (ret < 0) + return ret; + } + if (avctx->qmax >= 0) { + ret = libx265_param_parse_int(avctx, "qpmax", avctx->qmax); + if (ret < 0) + return ret; + } +#endif + if (avctx->max_qdiff >= 0) { + ret = libx265_param_parse_int(avctx, "qpstep", avctx->max_qdiff); + if (ret < 0) + return ret; + } + if (avctx->qblur >= 0) { + ret = libx265_param_parse_float(avctx, "qblur", avctx->qblur); + if (ret < 0) + return ret; + } + if (avctx->qcompress >= 0) { + ret = libx265_param_parse_float(avctx, "qcomp", avctx->qcompress); + if (ret < 0) + return ret; + } + if (avctx->i_quant_factor >= 0) { + ret = libx265_param_parse_float(avctx, "ipratio", avctx->i_quant_factor); + if (ret < 0) + return ret; + } + if (avctx->b_quant_factor >= 0) { + ret = libx265_param_parse_float(avctx, "pbratio", avctx->b_quant_factor); + if (ret < 0) + return ret; } ctx->params->rc.vbvBufferSize = avctx->rc_buffer_size / 1000; @@ -225,34 +310,50 @@ if (!cpb_props) return AVERROR(ENOMEM); cpb_props->buffer_size = ctx->params->rc.vbvBufferSize * 1000; - cpb_props->max_bitrate = ctx->params->rc.vbvMaxBitrate * 1000; - cpb_props->avg_bitrate = ctx->params->rc.bitrate * 1000; + cpb_props->max_bitrate = ctx->params->rc.vbvMaxBitrate * 1000LL; + cpb_props->avg_bitrate = ctx->params->rc.bitrate * 1000LL; if (!(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) ctx->params->bRepeatHeaders = 1; - if (ctx->x265_opts) { - AVDictionary *dict = NULL; + if (avctx->gop_size >= 0) { + ret = libx265_param_parse_int(avctx, "keyint", avctx->gop_size); + if (ret < 0) + return ret; + } + if (avctx->keyint_min > 0) { + ret = libx265_param_parse_int(avctx, "min-keyint", avctx->keyint_min); + if (ret < 0) + return ret; + } + if (avctx->max_b_frames >= 0) { + ret = libx265_param_parse_int(avctx, "bframes", avctx->max_b_frames); + if (ret < 0) + return ret; + } + if (avctx->refs >= 0) { + ret = libx265_param_parse_int(avctx, "ref", avctx->refs); + if (ret < 0) + return ret; + } + + { AVDictionaryEntry *en = NULL; + while ((en = av_dict_get(ctx->x265_opts, "", en, AV_DICT_IGNORE_SUFFIX))) { + int parse_ret = ctx->api->param_parse(ctx->params, en->key, en->value); - if (!av_dict_parse_string(&dict, ctx->x265_opts, "=", ":", 0)) { - while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) { - int parse_ret = ctx->api->param_parse(ctx->params, en->key, en->value); - - switch (parse_ret) { - case X265_PARAM_BAD_NAME: - av_log(avctx, AV_LOG_WARNING, - "Unknown option: %s.\n", en->key); - break; - case X265_PARAM_BAD_VALUE: - av_log(avctx, AV_LOG_WARNING, - "Invalid value for %s: %s.\n", en->key, en->value); - break; - default: - break; - } + switch (parse_ret) { + case X265_PARAM_BAD_NAME: + av_log(avctx, AV_LOG_WARNING, + "Unknown option: %s.\n", en->key); + break; + case X265_PARAM_BAD_VALUE: + av_log(avctx, AV_LOG_WARNING, + "Invalid value for %s: %s.\n", en->key, en->value); + break; + default: + break; } - av_dict_free(&dict); } } @@ -300,6 +401,7 @@ } memcpy(avctx->extradata, nal[0].payload, avctx->extradata_size); + memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); } return 0; @@ -310,7 +412,10 @@ AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST); if (sd) { if (ctx->params->rc.aqMode == X265_AQ_NONE) { - av_log(ctx, AV_LOG_WARNING, "Adaptive quantization must be enabled to use ROI encoding, skipping ROI.\n"); + if (!ctx->roi_warned) { + ctx->roi_warned = 1; + av_log(ctx, AV_LOG_WARNING, "Adaptive quantization must be enabled to use ROI encoding, skipping ROI.\n"); + } } else { /* 8x8 block when qg-size is 8, 16*16 block otherwise. */ int mb_size = (ctx->params->rc.qgSize == 8) ? 8 : 16; @@ -374,6 +479,7 @@ x265_picture x265pic_out = { 0 }; x265_nal *nal; uint8_t *dst; + int pict_type; int payload = 0; int nnal; int ret; @@ -399,6 +505,16 @@ ret = libx265_encode_set_roi(ctx, pic, &x265pic); if (ret < 0) return ret; + + if (pic->reordered_opaque) { + x265pic.userData = av_malloc(sizeof(pic->reordered_opaque)); + if (!x265pic.userData) { + av_freep(&x265pic.quantOffsets); + return AVERROR(ENOMEM); + } + + memcpy(x265pic.userData, &pic->reordered_opaque, sizeof(pic->reordered_opaque)); + } } ret = ctx->api->encoder_encode(ctx->encoder, &nal, &nnal, @@ -433,20 +549,26 @@ pkt->pts = x265pic_out.pts; pkt->dts = x265pic_out.dts; -#if FF_API_CODED_FRAME -FF_DISABLE_DEPRECATION_WARNINGS switch (x265pic_out.sliceType) { case X265_TYPE_IDR: case X265_TYPE_I: - avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + pict_type = AV_PICTURE_TYPE_I; break; case X265_TYPE_P: - avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P; + pict_type = AV_PICTURE_TYPE_P; break; case X265_TYPE_B: - avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B; + case X265_TYPE_BREF: + pict_type = AV_PICTURE_TYPE_B; break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown picture type encountered.\n"); + return AVERROR_EXTERNAL; } + +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + avctx->coded_frame->pict_type = pict_type; FF_ENABLE_DEPRECATION_WARNINGS #endif @@ -457,6 +579,14 @@ #endif pkt->flags |= AV_PKT_FLAG_DISPOSABLE; + ff_side_data_set_encoder_stats(pkt, x265pic_out.frameData.qp * FF_QP2LAMBDA, NULL, 0, pict_type); + + if (x265pic_out.userData) { + memcpy(&avctx->reordered_opaque, x265pic_out.userData, sizeof(avctx->reordered_opaque)); + av_freep(&x265pic_out.userData); + } else + avctx->reordered_opaque = 0; + *got_packet = 1; return 0; } @@ -526,11 +656,12 @@ #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "crf", "set the x265 crf", OFFSET(crf), AV_OPT_TYPE_FLOAT, { .dbl = -1 }, -1, FLT_MAX, VE }, + { "qp", "set the x265 qp", OFFSET(cqp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, { "forced-idr", "if forcing keyframes, force them as IDR frames", OFFSET(forced_idr),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "preset", "set the x265 preset", OFFSET(preset), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { "tune", "set the x265 tune parameter", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { "profile", "set the x265 profile", OFFSET(profile), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, - { "x265-params", "set the x265 configuration using a :-separated list of key=value parameters", OFFSET(x265_opts), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, + { "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 } }; @@ -543,6 +674,17 @@ static const AVCodecDefault x265_defaults[] = { { "b", "0" }, + { "bf", "-1" }, + { "g", "-1" }, + { "keyint_min", "-1" }, + { "refs", "-1" }, + { "qmin", "-1" }, + { "qmax", "-1" }, + { "qdiff", "-1" }, + { "qblur", "-1" }, + { "qcomp", "-1" }, + { "i_qfactor", "-1" }, + { "b_qfactor", "-1" }, { NULL }, }; @@ -558,6 +700,8 @@ .priv_data_size = sizeof(libx265Context), .priv_class = &class, .defaults = x265_defaults, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .wrapper_name = "libx265", }; diff -Nru ffmpeg-4.2.2/libavcodec/libxavs2.c ffmpeg-4.4/libavcodec/libxavs2.c --- ffmpeg-4.2.2/libavcodec/libxavs2.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libxavs2.c 2021-04-08 21:28:39.000000000 +0000 @@ -31,7 +31,7 @@ int err; \ av_strlcatf(opt_str, sizeof(opt_str), format, __VA_ARGS__); \ err = cae->api->opt_set2(cae->param, name, opt_str); \ - if (err) {\ + if (err < 0) {\ av_log(avctx, AV_LOG_WARNING, "Invalid value for %s: %s\n", name, opt_str);\ }\ } while(0); @@ -48,7 +48,7 @@ int log_level; void *encoder; - char *xavs2_opts; + AVDictionary *xavs2_opts; xavs2_outpacket_t packet; xavs2_param_t *param; @@ -59,7 +59,7 @@ static av_cold int xavs2_init(AVCodecContext *avctx) { - XAVS2EContext *cae= avctx->priv_data; + XAVS2EContext *cae = avctx->priv_data; int bit_depth, code; bit_depth = avctx->pix_fmt == AV_PIX_FMT_YUV420P ? 8 : 10; @@ -67,13 +67,13 @@ /* get API handler */ cae->api = xavs2_api_get(bit_depth); if (!cae->api) { - av_log(avctx, AV_LOG_ERROR, "api get failed\n"); + av_log(avctx, AV_LOG_ERROR, "Failed to get xavs2 api context\n"); return AVERROR_EXTERNAL; } cae->param = cae->api->opt_alloc(); if (!cae->param) { - av_log(avctx, AV_LOG_ERROR, "param alloc failed\n"); + av_log(avctx, AV_LOG_ERROR, "Failed to alloc xavs2 parameters\n"); return AVERROR(ENOMEM); } @@ -92,16 +92,10 @@ xavs2_opt_set2("OpenGOP", "%d", !(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP)); - if (cae->xavs2_opts) { - AVDictionary *dict = NULL; + { AVDictionaryEntry *en = NULL; - - if (!av_dict_parse_string(&dict, cae->xavs2_opts, "=", ":", 0)) { - while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) { - xavs2_opt_set2(en->key, "%s", en->value); - } - av_dict_free(&dict); - } + while ((en = av_dict_get(cae->xavs2_opts, "", en, AV_DICT_IGNORE_SUFFIX))) + xavs2_opt_set2(en->key, "%s", en->value); } /* Rate control */ @@ -115,15 +109,13 @@ xavs2_opt_set2("InitialQP", "%d", cae->qp); } - ff_mpeg12_find_best_frame_rate(avctx->framerate, &code, NULL, NULL, 0); - xavs2_opt_set2("FrameRate", "%d", code); cae->encoder = cae->api->encoder_create(cae->param); if (!cae->encoder) { - av_log(avctx,AV_LOG_ERROR, "Can not create encoder. Null pointer returned\n"); + av_log(avctx, AV_LOG_ERROR, "Failed to create xavs2 encoder instance.\n"); return AVERROR(EINVAL); } @@ -132,29 +124,42 @@ static void xavs2_copy_frame_with_shift(xavs2_picture_t *pic, const AVFrame *frame, const int shift_in) { - int j, k; - for (k = 0; k < 3; k++) { - int i_stride = pic->img.i_stride[k]; - for (j = 0; j < pic->img.i_lines[k]; j++) { - uint16_t *p_plane = (uint16_t *)&pic->img.img_planes[k][j * i_stride]; - int i; - uint8_t *p_buffer = frame->data[k] + frame->linesize[k] * j; - memset(p_plane, 0, i_stride); - for (i = 0; i < pic->img.i_width[k]; i++) { - p_plane[i] = p_buffer[i] << shift_in; + uint16_t *p_plane; + uint8_t *p_buffer; + int plane; + int hIdx; + int wIdx; + + for (plane = 0; plane < 3; plane++) { + p_plane = (uint16_t *)pic->img.img_planes[plane]; + p_buffer = frame->data[plane]; + for (hIdx = 0; hIdx < pic->img.i_lines[plane]; hIdx++) { + memset(p_plane, 0, pic->img.i_stride[plane]); + for (wIdx = 0; wIdx < pic->img.i_width[plane]; wIdx++) { + p_plane[wIdx] = p_buffer[wIdx] << shift_in; } + p_plane += pic->img.i_stride[plane]; + p_buffer += frame->linesize[plane]; } } } static void xavs2_copy_frame(xavs2_picture_t *pic, const AVFrame *frame) { - int j, k; - for (k = 0; k < 3; k++) { - for (j = 0; j < pic->img.i_lines[k]; j++) { - memcpy( pic->img.img_planes[k] + pic->img.i_stride[k] * j, - frame->data[k]+frame->linesize[k] * j, - pic->img.i_width[k] * pic->img.in_sample_size); + uint8_t *p_plane; + uint8_t *p_buffer; + int plane; + int hIdx; + int stride; + + for (plane = 0; plane < 3; plane++) { + p_plane = pic->img.img_planes[plane]; + p_buffer = frame->data[plane]; + stride = pic->img.i_width[plane] * pic->img.in_sample_size; + for (hIdx = 0; hIdx < pic->img.i_lines[plane]; hIdx++) { + memcpy(p_plane, p_buffer, stride); + p_plane += pic->img.i_stride[plane]; + p_buffer += frame->linesize[plane]; } } } @@ -169,7 +174,7 @@ /* create the XAVS2 video encoder */ /* read frame data and send to the XAVS2 video encoder */ if (cae->api->encoder_get_buffer(cae->encoder, &pic) < 0) { - av_log(avctx,AV_LOG_ERROR, "failed to get frame buffer\n"); + av_log(avctx, AV_LOG_ERROR, "Failed to get xavs2 frame buffer\n"); return AVERROR_EXTERNAL; } if (frame) { @@ -200,7 +205,7 @@ ret = cae->api->encoder_encode(cae->encoder, &pic, &cae->packet); if (ret) { - av_log(avctx, AV_LOG_ERROR, "encode failed\n"); + av_log(avctx, AV_LOG_ERROR, "Encoding error occured.\n"); return AVERROR_EXTERNAL; } @@ -208,10 +213,9 @@ cae->api->encoder_encode(cae->encoder, NULL, &cae->packet); } - if ((cae->packet.len) && (cae->packet.state != XAVS2_STATE_FLUSH_END)){ - - if (av_new_packet(pkt, cae->packet.len) < 0){ - av_log(avctx, AV_LOG_ERROR, "packet alloc failed\n"); + if ((cae->packet.len) && (cae->packet.state != XAVS2_STATE_FLUSH_END)) { + if (av_new_packet(pkt, cae->packet.len) < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to alloc xavs2 packet.\n"); cae->api->encoder_packet_unref(cae->encoder, &cae->packet); return AVERROR(ENOMEM); } @@ -219,6 +223,12 @@ pkt->pts = cae->packet.pts; pkt->dts = cae->packet.dts; + if (cae->packet.type == XAVS2_TYPE_IDR || + cae->packet.type == XAVS2_TYPE_I || + cae->packet.type == XAVS2_TYPE_KEYFRAME) { + pkt->flags |= AV_PKT_FLAG_KEY; + } + memcpy(pkt->data, cae->packet.stream, cae->packet.len); pkt->size = cae->packet.len; @@ -257,7 +267,7 @@ { "min_qp" , "min qp for rate control" , OFFSET(min_qp) , AV_OPT_TYPE_INT, {.i64 = 20 }, 0, 63, VE }, { "speed_level" , "Speed level, higher is better but slower", OFFSET(preset_level) , AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 9, VE }, { "log_level" , "log level: -1: none, 0: error, 1: warning, 2: info, 3: debug", OFFSET(log_level) , AV_OPT_TYPE_INT, {.i64 = 0 }, -1, 3, VE }, - { "xavs2-params" , "set the xavs2 configuration using a :-separated list of key=value parameters", OFFSET(xavs2_opts), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, + { "xavs2-params" , "set the xavs2 configuration using a :-separated list of key=value parameters", OFFSET(xavs2_opts), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, { NULL }, }; @@ -284,7 +294,8 @@ .init = xavs2_init, .encode2 = xavs2_encode_frame, .close = xavs2_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &libxavs2, diff -Nru ffmpeg-4.2.2/libavcodec/libxavs.c ffmpeg-4.4/libavcodec/libxavs.c --- ffmpeg-4.2.2/libavcodec/libxavs.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libxavs.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,6 +28,7 @@ #include #include "avcodec.h" #include "internal.h" +#include "packet_internal.h" #include "libavutil/internal.h" #include "libavutil/mem.h" #include "libavutil/opt.h" @@ -474,7 +475,8 @@ .init = XAVS_init, .encode2 = XAVS_frame, .close = XAVS_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &xavs_class, .defaults = xavs_defaults, diff -Nru ffmpeg-4.2.2/libavcodec/libxvid.c ffmpeg-4.4/libavcodec/libxvid.c --- ffmpeg-4.2.2/libavcodec/libxvid.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libxvid.c 2021-04-08 21:28:39.000000000 +0000 @@ -40,8 +40,8 @@ #include "avcodec.h" #include "internal.h" -#include "libxvid.h" #include "mpegutils.h" +#include "packet_internal.h" #if HAVE_UNISTD_H #include @@ -684,17 +684,22 @@ /* Encode a dummy frame to get the extradata immediately */ if (x->quicktime_format) { AVFrame *picture; - AVPacket packet = {0}; - int size, got_packet, ret; + AVPacket *packet; + int size, got_packet; - av_init_packet(&packet); + packet = av_packet_alloc(); + if (!packet) + return AVERROR(ENOMEM); picture = av_frame_alloc(); - if (!picture) + if (!picture) { + av_packet_free(&packet); return AVERROR(ENOMEM); + } xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL); if( xerr ) { + av_packet_free(&packet); av_frame_free(&picture); av_log(avctx, AV_LOG_ERROR, "Xvid: Could not create encoder reference\n"); return AVERROR_EXTERNAL; @@ -703,6 +708,7 @@ size = ((avctx->width + 1) & ~1) * ((avctx->height + 1) & ~1); picture->data[0] = av_malloc(size + size / 2); if (!picture->data[0]) { + av_packet_free(&packet); av_frame_free(&picture); return AVERROR(ENOMEM); } @@ -710,9 +716,8 @@ picture->data[2] = picture->data[1] + size / 4; memset(picture->data[0], 0, size); memset(picture->data[1], 128, size / 2); - ret = xvid_encode_frame(avctx, &packet, picture, &got_packet); - if (!ret && got_packet) - av_packet_unref(&packet); + xvid_encode_frame(avctx, packet, picture, &got_packet); + av_packet_free(&packet); av_free(picture->data[0]); av_frame_free(&picture); xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL); diff -Nru ffmpeg-4.2.2/libavcodec/libxvid.h ffmpeg-4.4/libavcodec/libxvid.h --- ffmpeg-4.2.2/libavcodec/libxvid.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libxvid.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -/* - * copyright (C) 2006 Corey Hickey - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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_LIBXVID_H -#define AVCODEC_LIBXVID_H - -/** - * @file - * common functions for use with the Xvid wrappers - */ - -struct MpegEncContext; - -/* rate control */ -int ff_xvid_rate_control_init(struct MpegEncContext *s); -void ff_xvid_rate_control_uninit(struct MpegEncContext *s); -float ff_xvid_rate_estimate_qscale(struct MpegEncContext *s, int dry_run); - -#endif /* AVCODEC_LIBXVID_H */ diff -Nru ffmpeg-4.2.2/libavcodec/libzvbi-teletextdec.c ffmpeg-4.4/libavcodec/libzvbi-teletextdec.c --- ffmpeg-4.2.2/libavcodec/libzvbi-teletextdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/libzvbi-teletextdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -55,6 +55,7 @@ { AVClass *class; char *pgno; + int default_region; int x_offset; int y_offset; int format_id; /* 0 = bitmap, 1 = text/ass, 2 = ass */ @@ -635,7 +636,7 @@ return lines; } -static int teletext_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *pkt) +static int teletext_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, AVPacket *pkt) { TeletextContext *ctx = avctx->priv_data; AVSubtitle *sub = data; @@ -645,6 +646,10 @@ if (!ctx->vbi) { if (!(ctx->vbi = vbi_decoder_new())) return AVERROR(ENOMEM); + if (ctx->default_region != -1) { + av_log(avctx, AV_LOG_INFO, "Setting default zvbi region to %i\n", ctx->default_region); + vbi_teletext_set_default_region(ctx->vbi, ctx->default_region); + } if (!vbi_event_handler_register(ctx->vbi, VBI_EVENT_TTX_PAGE, handler, ctx)) { vbi_decoder_delete(ctx->vbi); ctx->vbi = NULL; @@ -719,9 +724,9 @@ ctx->nb_pages--; if (ret >= 0) - *data_size = 1; + *got_sub_ptr = 1; } else - *data_size = 0; + *got_sub_ptr = 0; return ret; } @@ -792,6 +797,7 @@ #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { {"txt_page", "page numbers to decode, subtitle for subtitles, * for all", OFFSET(pgno), AV_OPT_TYPE_STRING, {.str = "*"}, 0, 0, SD}, + {"txt_default_region", "default G0 character set used for decoding", OFFSET(default_region), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 87, SD}, {"txt_chop_top", "discards the top teletext line", OFFSET(chop_top), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, SD}, {"txt_format", "format of the subtitles (bitmap or text or ass)", OFFSET(format_id), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 2, SD, "txt_format"}, {"bitmap", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, SD, "txt_format"}, diff -Nru ffmpeg-4.2.2/libavcodec/ljpegenc.c ffmpeg-4.4/libavcodec/ljpegenc.c --- ffmpeg-4.2.2/libavcodec/ljpegenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ljpegenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,12 +32,14 @@ #include "libavutil/frame.h" #include "libavutil/mem.h" +#include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avcodec.h" #include "idctdsp.h" #include "internal.h" #include "jpegtables.h" +#include "mathops.h" #include "mjpegenc_common.h" #include "mjpeg.h" @@ -309,7 +311,7 @@ s->scratch = av_malloc_array(avctx->width + 1, sizeof(*s->scratch)); if (!s->scratch) - goto fail; + return AVERROR(ENOMEM); ff_idctdsp_init(&s->idsp, avctx); ff_init_scantable(s->idsp.idct_permutation, &s->scantable, @@ -327,9 +329,6 @@ avpriv_mjpeg_val_dc); return 0; -fail: - ljpeg_encode_close(avctx); - return AVERROR(ENOMEM); } #define OFFSET(x) offsetof(LJpegEncContext, x) @@ -360,7 +359,7 @@ .init = ljpeg_encode_init, .encode2 = ljpeg_encode_frame, .close = ljpeg_encode_close, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24 , AV_PIX_FMT_BGRA , AV_PIX_FMT_BGR0, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, diff -Nru ffmpeg-4.2.2/libavcodec/loco.c ffmpeg-4.4/libavcodec/loco.c --- ffmpeg-4.2.2/libavcodec/loco.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/loco.c 2021-04-08 21:28:39.000000000 +0000 @@ -82,7 +82,7 @@ static inline int loco_get_rice(RICEContext *r) { - int v; + unsigned v; if (r->run > 0) { /* we have zero run */ r->run--; loco_update_rice_param(r, 0); @@ -131,7 +131,7 @@ int stride, const uint8_t *buf, int buf_size) { RICEContext rc; - int val; + unsigned val; int ret; int i, j; @@ -346,4 +346,5 @@ .init = decode_init, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/lossless_audiodsp.c ffmpeg-4.4/libavcodec/lossless_audiodsp.c --- ffmpeg-4.2.2/libavcodec/lossless_audiodsp.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/lossless_audiodsp.c 2020-07-09 09:17:49.000000000 +0000 @@ -27,7 +27,7 @@ const int16_t *v3, int order, int mul) { - int res = 0; + unsigned res = 0; do { res += *v1 * *v2++; diff -Nru ffmpeg-4.2.2/libavcodec/lpc.c ffmpeg-4.4/libavcodec/lpc.c --- ffmpeg-4.2.2/libavcodec/lpc.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/lpc.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,7 @@ #include "libavutil/common.h" #include "libavutil/lls.h" +#include "libavutil/mem_internal.h" #define LPC_USE_DOUBLE #include "lpc.h" diff -Nru ffmpeg-4.2.2/libavcodec/lscrdec.c ffmpeg-4.4/libavcodec/lscrdec.c --- ffmpeg-4.2.2/libavcodec/lscrdec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/lscrdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2019 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/frame.h" +#include "libavutil/error.h" +#include "libavutil/log.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "codec.h" +#include "internal.h" +#include "packet.h" +#include "png.h" +#include "pngdsp.h" + +typedef struct LSCRContext { + PNGDSPContext dsp; + AVCodecContext *avctx; + + AVFrame *last_picture; + uint8_t *buffer; + int buffer_size; + uint8_t *crow_buf; + int crow_size; + uint8_t *last_row; + unsigned int last_row_size; + + GetByteContext gb; + uint8_t *image_buf; + int image_linesize; + int row_size; + int cur_h; + int y; + + z_stream zstream; +} LSCRContext; + +static void handle_row(LSCRContext *s) +{ + uint8_t *ptr, *last_row; + + ptr = s->image_buf + s->image_linesize * s->y; + if (s->y == 0) + last_row = s->last_row; + else + last_row = ptr - s->image_linesize; + + ff_png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1, + last_row, s->row_size, 3); + + s->y++; +} + +static int decode_idat(LSCRContext *s, int length) +{ + int ret; + s->zstream.avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb)); + s->zstream.next_in = s->gb.buffer; + + if (length <= 0) + return AVERROR_INVALIDDATA; + + bytestream2_skip(&s->gb, length); + + /* decode one line if possible */ + while (s->zstream.avail_in > 0) { + ret = inflate(&s->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) { + av_log(s->avctx, AV_LOG_ERROR, "inflate returned error %d\n", ret); + return AVERROR_EXTERNAL; + } + if (s->zstream.avail_out == 0) { + if (s->y < s->cur_h) { + handle_row(s); + } + s->zstream.avail_out = s->crow_size; + s->zstream.next_out = s->crow_buf; + } + if (ret == Z_STREAM_END && s->zstream.avail_in > 0) { + av_log(s->avctx, AV_LOG_WARNING, + "%d undecompressed bytes left in buffer\n", s->zstream.avail_in); + return 0; + } + } + return 0; +} + +static int decode_frame_lscr(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + LSCRContext *const s = avctx->priv_data; + GetByteContext *gb = &s->gb; + AVFrame *frame = s->last_picture; + int ret, nb_blocks, offset = 0; + + if (avpkt->size < 2) + return AVERROR_INVALIDDATA; + if (avpkt->size == 2) + return 0; + + bytestream2_init(gb, avpkt->data, avpkt->size); + + nb_blocks = bytestream2_get_le16(gb); + if (bytestream2_get_bytes_left(gb) < 2 + nb_blocks * (12 + 8)) + return AVERROR_INVALIDDATA; + + ret = ff_reget_buffer(avctx, frame, + nb_blocks ? 0 : FF_REGET_BUFFER_FLAG_READONLY); + if (ret < 0) + return ret; + + for (int b = 0; b < nb_blocks; b++) { + int x, y, x2, y2, w, h, left; + uint32_t csize, size; + + s->zstream.zalloc = ff_png_zalloc; + s->zstream.zfree = ff_png_zfree; + s->zstream.opaque = NULL; + + if ((ret = inflateInit(&s->zstream)) != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret); + ret = AVERROR_EXTERNAL; + goto end; + } + + bytestream2_seek(gb, 2 + b * 12, SEEK_SET); + + x = bytestream2_get_le16(gb); + y = bytestream2_get_le16(gb); + x2 = bytestream2_get_le16(gb); + y2 = bytestream2_get_le16(gb); + w = x2-x; + s->cur_h = h = y2-y; + + if (w <= 0 || x < 0 || x >= avctx->width || w + x > avctx->width || + h <= 0 || y < 0 || y >= avctx->height || h + y > avctx->height) { + ret = AVERROR_INVALIDDATA; + goto end; + } + + size = bytestream2_get_le32(gb); + + frame->key_frame = (nb_blocks == 1) && + (w == avctx->width) && + (h == avctx->height) && + (x == 0) && (y == 0); + + bytestream2_seek(gb, 2 + nb_blocks * 12 + offset, SEEK_SET); + csize = bytestream2_get_be32(gb); + if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T')) { + ret = AVERROR_INVALIDDATA; + goto end; + } + + offset += size; + left = size; + + s->y = 0; + s->row_size = w * 3; + + av_fast_padded_malloc(&s->buffer, &s->buffer_size, s->row_size + 16); + if (!s->buffer) { + ret = AVERROR(ENOMEM); + goto end; + } + + av_fast_padded_malloc(&s->last_row, &s->last_row_size, s->row_size); + if (!s->last_row) { + ret = AVERROR(ENOMEM); + goto end; + } + + s->crow_size = w * 3 + 1; + s->crow_buf = s->buffer + 15; + s->zstream.avail_out = s->crow_size; + s->zstream.next_out = s->crow_buf; + s->image_buf = frame->data[0] + (avctx->height - y - 1) * frame->linesize[0] + x * 3; + s->image_linesize =-frame->linesize[0]; + + while (left > 16) { + ret = decode_idat(s, csize); + if (ret < 0) + goto end; + left -= csize + 16; + if (left > 16) { + bytestream2_skip(gb, 4); + csize = bytestream2_get_be32(gb); + if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T')) { + ret = AVERROR_INVALIDDATA; + goto end; + } + } + } + + inflateEnd(&s->zstream); + } + + frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + + if ((ret = av_frame_ref(data, frame)) < 0) + return ret; + + *got_frame = 1; +end: + inflateEnd(&s->zstream); + + if (ret < 0) + return ret; + return avpkt->size; +} + +static int lscr_decode_close(AVCodecContext *avctx) +{ + LSCRContext *s = avctx->priv_data; + + av_frame_free(&s->last_picture); + av_freep(&s->buffer); + av_freep(&s->last_row); + + return 0; +} + +static int lscr_decode_init(AVCodecContext *avctx) +{ + LSCRContext *s = avctx->priv_data; + + avctx->color_range = AVCOL_RANGE_JPEG; + avctx->pix_fmt = AV_PIX_FMT_BGR24; + + s->avctx = avctx; + s->last_picture = av_frame_alloc(); + if (!s->last_picture) + return AVERROR(ENOMEM); + + ff_pngdsp_init(&s->dsp); + + return 0; +} + +static void lscr_decode_flush(AVCodecContext *avctx) +{ + LSCRContext *s = avctx->priv_data; + av_frame_unref(s->last_picture); +} + +AVCodec ff_lscr_decoder = { + .name = "lscr", + .long_name = NULL_IF_CONFIG_SMALL("LEAD Screen Capture"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_LSCR, + .priv_data_size = sizeof(LSCRContext), + .init = lscr_decode_init, + .close = lscr_decode_close, + .decode = decode_frame_lscr, + .flush = lscr_decode_flush, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff -Nru ffmpeg-4.2.2/libavcodec/lzf.c ffmpeg-4.4/libavcodec/lzf.c --- ffmpeg-4.2.2/libavcodec/lzf.c 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/lzf.c 2020-07-09 09:17:49.000000000 +0000 @@ -49,7 +49,7 @@ if (s < LZF_LITERAL_MAX) { s++; if (s > *size - len) { - *size += *size /2; + *size += s + *size /2; ret = av_reallocp(buf, *size); if (ret < 0) return ret; @@ -72,7 +72,7 @@ return AVERROR_INVALIDDATA; if (l > *size - len) { - *size += *size / 2; + *size += l + *size / 2; ret = av_reallocp(buf, *size); if (ret < 0) return ret; diff -Nru ffmpeg-4.2.2/libavcodec/lzwenc.c ffmpeg-4.4/libavcodec/lzwenc.c --- ffmpeg-4.2.2/libavcodec/lzwenc.c 2016-03-29 02:25:17.000000000 +0000 +++ ffmpeg-4.4/libavcodec/lzwenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -60,7 +60,7 @@ int output_bytes; ///< Number of written bytes int last_code; ///< Value of last output code or LZW_PREFIX_EMPTY enum FF_LZW_MODES mode; ///< TIFF or GIF - void (*put_bits)(PutBitContext *, int, unsigned); ///< GIF is LE while TIFF is BE + int little_endian; ///< GIF is LE while TIFF is BE }LZWEncodeState; @@ -113,7 +113,10 @@ static inline void writeCode(LZWEncodeState * s, int c) { av_assert2(0 <= c && c < 1 << s->bits); - s->put_bits(&s->pb, s->bits, c); + if (s->little_endian) + put_bits_le(&s->pb, s->bits, c); + else + put_bits(&s->pb, s->bits, c); } @@ -200,8 +203,7 @@ * @param maxbits Maximum length of code */ void ff_lzw_encode_init(LZWEncodeState *s, uint8_t *outbuf, int outsize, - int maxbits, enum FF_LZW_MODES mode, - void (*lzw_put_bits)(PutBitContext *, int, unsigned)) + int maxbits, enum FF_LZW_MODES mode, int little_endian) { s->clear_code = 256; s->end_code = 257; @@ -214,7 +216,7 @@ s->last_code = LZW_PREFIX_EMPTY; s->bits = 9; s->mode = mode; - s->put_bits = lzw_put_bits; + s->little_endian = little_endian; } /** @@ -257,16 +259,22 @@ * @param s LZW state * @return Number of bytes written or -1 on error */ -int ff_lzw_encode_flush(LZWEncodeState *s, - void (*lzw_flush_put_bits)(PutBitContext *)) +int ff_lzw_encode_flush(LZWEncodeState *s) { if (s->last_code != -1) writeCode(s, s->last_code); writeCode(s, s->end_code); - if (s->mode == FF_LZW_GIF) - s->put_bits(&s->pb, 1, 0); + if (s->little_endian) { + if (s->mode == FF_LZW_GIF) + put_bits_le(&s->pb, 1, 0); + + flush_put_bits_le(&s->pb); + } else { + if (s->mode == FF_LZW_GIF) + put_bits(&s->pb, 1, 0); - lzw_flush_put_bits(&s->pb); + flush_put_bits(&s->pb); + } s->last_code = -1; return writtenBytes(s); diff -Nru ffmpeg-4.2.2/libavcodec/lzw.h ffmpeg-4.4/libavcodec/lzw.h --- ffmpeg-4.2.2/libavcodec/lzw.h 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/lzw.h 2021-04-08 21:28:39.000000000 +0000 @@ -54,10 +54,8 @@ extern const int ff_lzw_encode_state_size; void ff_lzw_encode_init(struct LZWEncodeState *s, uint8_t *outbuf, int outsize, - int maxbits, enum FF_LZW_MODES mode, - void (*lzw_put_bits)(struct PutBitContext *, int, unsigned int)); + int maxbits, enum FF_LZW_MODES mode, int little_endian); int ff_lzw_encode(struct LZWEncodeState * s, const uint8_t * inbuf, int insize); -int ff_lzw_encode_flush(struct LZWEncodeState *s, - void (*lzw_flush_put_bits)(struct PutBitContext *)); +int ff_lzw_encode_flush(struct LZWEncodeState *s); #endif /* AVCODEC_LZW_H */ diff -Nru ffmpeg-4.2.2/libavcodec/magicyuv.c ffmpeg-4.4/libavcodec/magicyuv.c --- ffmpeg-4.2.2/libavcodec/magicyuv.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/magicyuv.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,8 +22,9 @@ #include #include +#define CACHED_BITSTREAM_READER !ARCH_X86_32 + #include "libavutil/pixdesc.h" -#include "libavutil/qsort.h" #include "avcodec.h" #include "bytestream.h" @@ -45,9 +46,8 @@ } Prediction; typedef struct HuffEntry { - uint16_t sym; uint8_t len; - uint32_t code; + uint16_t sym; } HuffEntry; typedef struct MagicYUVContext { @@ -61,131 +61,33 @@ int color_matrix; // video color matrix int flags; int interlaced; // video is interlaced - uint8_t *buf; // pointer to AVPacket->data + const uint8_t *buf; // pointer to AVPacket->data int hshift[4]; int vshift[4]; Slice *slices[4]; // slice bitstream positions for each plane unsigned int slices_size[4]; // slice sizes for each plane - uint8_t len[4][4096]; // table of code lengths for each plane VLC vlc[4]; // VLC for each plane - int (*huff_build)(VLC *vlc, uint8_t *len); int (*magy_decode_slice)(AVCodecContext *avctx, void *tdata, int j, int threadnr); LLVidDSPContext llviddsp; } MagicYUVContext; -static int huff_cmp_len(const void *a, const void *b) -{ - const HuffEntry *aa = a, *bb = b; - return (aa->len - bb->len) * 256 + aa->sym - bb->sym; -} - -static int huff_cmp_len10(const void *a, const void *b) -{ - const HuffEntry *aa = a, *bb = b; - return (aa->len - bb->len) * 1024 + aa->sym - bb->sym; -} - -static int huff_cmp_len12(const void *a, const void *b) -{ - const HuffEntry *aa = a, *bb = b; - return (aa->len - bb->len) * 4096 + aa->sym - bb->sym; -} - -static int huff_build10(VLC *vlc, uint8_t *len) -{ - HuffEntry he[1024]; - uint32_t codes[1024]; - uint8_t bits[1024]; - uint16_t syms[1024]; - uint32_t code; - int i; - - for (i = 0; i < 1024; i++) { - he[i].sym = 1023 - i; - he[i].len = len[i]; - if (len[i] == 0 || len[i] > 32) - return AVERROR_INVALIDDATA; - } - AV_QSORT(he, 1024, HuffEntry, huff_cmp_len10); - - code = 1; - for (i = 1023; i >= 0; i--) { - codes[i] = code >> (32 - he[i].len); - bits[i] = he[i].len; - syms[i] = he[i].sym; - code += 0x80000000u >> (he[i].len - 1); - } - - ff_free_vlc(vlc); - return ff_init_vlc_sparse(vlc, FFMIN(he[1023].len, 12), 1024, - bits, sizeof(*bits), sizeof(*bits), - codes, sizeof(*codes), sizeof(*codes), - syms, sizeof(*syms), sizeof(*syms), 0); -} - -static int huff_build12(VLC *vlc, uint8_t *len) +static int huff_build(const uint8_t len[], uint16_t codes_pos[33], + VLC *vlc, int nb_elems, void *logctx) { HuffEntry he[4096]; - uint32_t codes[4096]; - uint8_t bits[4096]; - uint16_t syms[4096]; - uint32_t code; - int i; - for (i = 0; i < 4096; i++) { - he[i].sym = 4095 - i; - he[i].len = len[i]; - if (len[i] == 0 || len[i] > 32) - return AVERROR_INVALIDDATA; - } - AV_QSORT(he, 4096, HuffEntry, huff_cmp_len12); + for (int i = 31; i > 0; i--) + codes_pos[i] += codes_pos[i + 1]; - code = 1; - for (i = 4095; i >= 0; i--) { - codes[i] = code >> (32 - he[i].len); - bits[i] = he[i].len; - syms[i] = he[i].sym; - code += 0x80000000u >> (he[i].len - 1); - } + for (unsigned i = nb_elems; i-- > 0;) + he[--codes_pos[len[i]]] = (HuffEntry){ len[i], i }; ff_free_vlc(vlc); - return ff_init_vlc_sparse(vlc, FFMIN(he[4095].len, 14), 4096, - bits, sizeof(*bits), sizeof(*bits), - codes, sizeof(*codes), sizeof(*codes), - syms, sizeof(*syms), sizeof(*syms), 0); -} - -static int huff_build(VLC *vlc, uint8_t *len) -{ - HuffEntry he[256]; - uint32_t codes[256]; - uint8_t bits[256]; - uint8_t syms[256]; - uint32_t code; - int i; - - for (i = 0; i < 256; i++) { - he[i].sym = 255 - i; - he[i].len = len[i]; - if (len[i] == 0 || len[i] > 32) - return AVERROR_INVALIDDATA; - } - AV_QSORT(he, 256, HuffEntry, huff_cmp_len); - - code = 1; - for (i = 255; i >= 0; i--) { - codes[i] = code >> (32 - he[i].len); - bits[i] = he[i].len; - syms[i] = he[i].sym; - code += 0x80000000u >> (he[i].len - 1); - } - - ff_free_vlc(vlc); - return ff_init_vlc_sparse(vlc, FFMIN(he[255].len, 12), 256, - bits, sizeof(*bits), sizeof(*bits), - codes, sizeof(*codes), sizeof(*codes), - syms, sizeof(*syms), sizeof(*syms), 0); + return ff_init_vlc_from_lengths(vlc, FFMIN(he[0].len, 12), nb_elems, + &he[0].len, sizeof(he[0]), + &he[0].sym, sizeof(he[0]), sizeof(he[0].sym), + 0, 0, logctx); } static void magicyuv_median_pred16(uint16_t *dst, const uint16_t *src1, @@ -259,7 +161,7 @@ if (pix < 0) return AVERROR_INVALIDDATA; - dst[x] = max - pix; + dst[x] = pix; } dst += stride; } @@ -358,27 +260,26 @@ int sheight = AV_CEIL_RSHIFT(s->slice_height, s->vshift[i]); ptrdiff_t fake_stride = p->linesize[i] * (1 + interlaced); ptrdiff_t stride = p->linesize[i]; + const uint8_t *slice = s->buf + s->slices[i][j].start; int flags, pred; - int ret = init_get_bits8(&gb, s->buf + s->slices[i][j].start, - s->slices[i][j].size); - if (ret < 0) - return ret; - - flags = get_bits(&gb, 8); - pred = get_bits(&gb, 8); + flags = bytestream_get_byte(&slice); + pred = bytestream_get_byte(&slice); dst = p->data[i] + j * sheight * stride; if (flags & 1) { - if (get_bits_left(&gb) < 8* width * height) + if (s->slices[i][j].size - 2 < width * height) return AVERROR_INVALIDDATA; for (k = 0; k < height; k++) { - for (x = 0; x < width; x++) - dst[x] = get_bits(&gb, 8); - + bytestream_get_buffer(&slice, dst, width); dst += stride; } } else { + int ret = init_get_bits8(&gb, slice, s->slices[i][j].size - 2); + + if (ret < 0) + return ret; + for (k = 0; k < height; k++) { for (x = 0; x < width; x++) { int pix; @@ -389,7 +290,7 @@ if (pix < 0) return AVERROR_INVALIDDATA; - dst[x] = 255 - pix; + dst[x] = pix; } dst += stride; } @@ -473,25 +374,40 @@ return 0; } -static int build_huffman(AVCodecContext *avctx, GetBitContext *gbit, int max) +static int build_huffman(AVCodecContext *avctx, const uint8_t *table, + int table_size, int max) { MagicYUVContext *s = avctx->priv_data; + GetByteContext gb; + uint8_t len[4096]; + uint16_t length_count[33] = { 0 }; int i = 0, j = 0, k; - memset(s->len, 0, sizeof(s->len)); - while (get_bits_left(gbit) >= 8) { - int b = get_bits(gbit, 1); - int x = get_bits(gbit, 7); - int l = get_bitsz(gbit, b * 8) + 1; - - for (k = 0; k < l; k++) - if (j + k < max) - s->len[i][j + k] = x; + bytestream2_init(&gb, table, table_size); + + while (bytestream2_get_bytes_left(&gb) > 0) { + int b = bytestream2_peek_byteu(&gb) & 0x80; + int x = bytestream2_get_byteu(&gb) & ~0x80; + int l = 1; + + if (b) { + if (bytestream2_get_bytes_left(&gb) <= 0) + break; + l += bytestream2_get_byteu(&gb); + } + k = j + l; + if (k > max || x == 0 || x > 32) { + av_log(avctx, AV_LOG_ERROR, "Invalid Huffman codes\n"); + return AVERROR_INVALIDDATA; + } + + length_count[x] += l; + for (; j < k; j++) + len[j] = x; - j += l; if (j == max) { j = 0; - if (s->huff_build(&s->vlc[i], s->len[i])) { + if (huff_build(len, length_count, &s->vlc[i], max, avctx)) { av_log(avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); return AVERROR_INVALIDDATA; } @@ -499,9 +415,7 @@ if (i == s->planes) { break; } - } else if (j > max) { - av_log(avctx, AV_LOG_ERROR, "Invalid Huffman codes\n"); - return AVERROR_INVALIDDATA; + memset(length_count, 0, sizeof(length_count)); } } @@ -519,24 +433,26 @@ MagicYUVContext *s = avctx->priv_data; ThreadFrame frame = { .f = data }; AVFrame *p = data; - GetByteContext gbyte; - GetBitContext gbit; + GetByteContext gb; uint32_t first_offset, offset, next_offset, header_size, slice_width; int width, height, format, version, table_size; int ret, i, j; - bytestream2_init(&gbyte, avpkt->data, avpkt->size); - if (bytestream2_get_le32(&gbyte) != MKTAG('M', 'A', 'G', 'Y')) + if (avpkt->size < 36) + return AVERROR_INVALIDDATA; + + bytestream2_init(&gb, avpkt->data, avpkt->size); + if (bytestream2_get_le32u(&gb) != MKTAG('M', 'A', 'G', 'Y')) return AVERROR_INVALIDDATA; - header_size = bytestream2_get_le32(&gbyte); + header_size = bytestream2_get_le32u(&gb); if (header_size < 32 || header_size >= avpkt->size) { av_log(avctx, AV_LOG_ERROR, "header or packet too small %"PRIu32"\n", header_size); return AVERROR_INVALIDDATA; } - version = bytestream2_get_byte(&gbyte); + version = bytestream2_get_byteu(&gb); if (version != 7) { avpriv_request_sample(avctx, "Version %d", version); return AVERROR_PATCHWELCOME; @@ -547,12 +463,9 @@ s->hshift[2] = s->vshift[2] = 0; s->decorrelate = 0; - s->max = 256; s->bps = 8; - s->huff_build = huff_build; - s->magy_decode_slice = magy_decode_slice; - format = bytestream2_get_byte(&gbyte); + format = bytestream2_get_byteu(&gb); switch (format) { case 0x65: avctx->pix_fmt = AV_PIX_FMT_GBRP; @@ -587,102 +500,104 @@ avctx->pix_fmt = AV_PIX_FMT_YUV422P10; s->hshift[1] = s->hshift[2] = 1; - s->max = 1024; - s->huff_build = huff_build10; - s->magy_decode_slice = magy_decode_slice10; s->bps = 10; break; case 0x76: avctx->pix_fmt = AV_PIX_FMT_YUV444P10; - s->max = 1024; - s->huff_build = huff_build10; - s->magy_decode_slice = magy_decode_slice10; s->bps = 10; break; case 0x6d: avctx->pix_fmt = AV_PIX_FMT_GBRP10; s->decorrelate = 1; - s->max = 1024; - s->huff_build = huff_build10; - s->magy_decode_slice = magy_decode_slice10; s->bps = 10; break; case 0x6e: avctx->pix_fmt = AV_PIX_FMT_GBRAP10; s->decorrelate = 1; - s->max = 1024; - s->huff_build = huff_build10; - s->magy_decode_slice = magy_decode_slice10; s->bps = 10; break; case 0x6f: avctx->pix_fmt = AV_PIX_FMT_GBRP12; s->decorrelate = 1; - s->max = 4096; - s->huff_build = huff_build12; - s->magy_decode_slice = magy_decode_slice10; s->bps = 12; break; case 0x70: avctx->pix_fmt = AV_PIX_FMT_GBRAP12; s->decorrelate = 1; - s->max = 4096; - s->huff_build = huff_build12; - s->magy_decode_slice = magy_decode_slice10; s->bps = 12; break; case 0x73: avctx->pix_fmt = AV_PIX_FMT_GRAY10; - s->max = 1024; - s->huff_build = huff_build10; - s->magy_decode_slice = magy_decode_slice10; + s->bps = 10; + break; + case 0x7b: + avctx->pix_fmt = AV_PIX_FMT_YUV420P10; + s->hshift[1] = + s->vshift[1] = + s->hshift[2] = + s->vshift[2] = 1; s->bps = 10; break; default: avpriv_request_sample(avctx, "Format 0x%X", format); return AVERROR_PATCHWELCOME; } + s->max = 1 << s->bps; + s->magy_decode_slice = s->bps == 8 ? magy_decode_slice : magy_decode_slice10; s->planes = av_pix_fmt_count_planes(avctx->pix_fmt); - bytestream2_skip(&gbyte, 1); - s->color_matrix = bytestream2_get_byte(&gbyte); - s->flags = bytestream2_get_byte(&gbyte); + bytestream2_skipu(&gb, 1); + s->color_matrix = bytestream2_get_byteu(&gb); + s->flags = bytestream2_get_byteu(&gb); s->interlaced = !!(s->flags & 2); - bytestream2_skip(&gbyte, 3); + bytestream2_skipu(&gb, 3); - width = bytestream2_get_le32(&gbyte); - height = bytestream2_get_le32(&gbyte); + width = bytestream2_get_le32u(&gb); + height = bytestream2_get_le32u(&gb); ret = ff_set_dimensions(avctx, width, height); if (ret < 0) return ret; - slice_width = bytestream2_get_le32(&gbyte); + slice_width = bytestream2_get_le32u(&gb); if (slice_width != avctx->coded_width) { avpriv_request_sample(avctx, "Slice width %"PRIu32, slice_width); return AVERROR_PATCHWELCOME; } - s->slice_height = bytestream2_get_le32(&gbyte); + s->slice_height = bytestream2_get_le32u(&gb); if (s->slice_height <= 0 || s->slice_height > INT_MAX - avctx->coded_height) { av_log(avctx, AV_LOG_ERROR, "invalid slice height: %d\n", s->slice_height); return AVERROR_INVALIDDATA; } - bytestream2_skip(&gbyte, 4); + bytestream2_skipu(&gb, 4); s->nb_slices = (avctx->coded_height + s->slice_height - 1) / s->slice_height; - if (s->nb_slices > INT_MAX / sizeof(Slice)) { + if (s->nb_slices > INT_MAX / FFMAX(sizeof(Slice), 4 * 5)) { av_log(avctx, AV_LOG_ERROR, "invalid number of slices: %d\n", s->nb_slices); return AVERROR_INVALIDDATA; } + if (s->interlaced) { + if ((s->slice_height >> s->vshift[1]) < 2) { + av_log(avctx, AV_LOG_ERROR, "impossible slice height\n"); + return AVERROR_INVALIDDATA; + } + if ((avctx->coded_height % s->slice_height) && ((avctx->coded_height % s->slice_height) >> s->vshift[1]) < 2) { + av_log(avctx, AV_LOG_ERROR, "impossible height\n"); + return AVERROR_INVALIDDATA; + } + } + + if (bytestream2_get_bytes_left(&gb) <= s->nb_slices * s->planes * 5) + return AVERROR_INVALIDDATA; for (i = 0; i < s->planes; i++) { av_fast_malloc(&s->slices[i], &s->slices_size[i], s->nb_slices * sizeof(Slice)); if (!s->slices[i]) return AVERROR(ENOMEM); - offset = bytestream2_get_le32(&gbyte); + offset = bytestream2_get_le32u(&gb); if (offset >= avpkt->size - header_size) return AVERROR_INVALIDDATA; @@ -692,32 +607,34 @@ for (j = 0; j < s->nb_slices - 1; j++) { s->slices[i][j].start = offset + header_size; - next_offset = bytestream2_get_le32(&gbyte); + next_offset = bytestream2_get_le32u(&gb); if (next_offset <= offset || next_offset >= avpkt->size - header_size) return AVERROR_INVALIDDATA; s->slices[i][j].size = next_offset - offset; + if (s->slices[i][j].size < 2) + return AVERROR_INVALIDDATA; offset = next_offset; } s->slices[i][j].start = offset + header_size; s->slices[i][j].size = avpkt->size - s->slices[i][j].start; + + if (s->slices[i][j].size < 2) + return AVERROR_INVALIDDATA; } - if (bytestream2_get_byte(&gbyte) != s->planes) + if (bytestream2_get_byteu(&gb) != s->planes) return AVERROR_INVALIDDATA; - bytestream2_skip(&gbyte, s->nb_slices * s->planes); + bytestream2_skipu(&gb, s->nb_slices * s->planes); - table_size = header_size + first_offset - bytestream2_tell(&gbyte); + table_size = header_size + first_offset - bytestream2_tell(&gb); if (table_size < 2) return AVERROR_INVALIDDATA; - ret = init_get_bits8(&gbit, avpkt->data + bytestream2_tell(&gbyte), table_size); - if (ret < 0) - return ret; - - ret = build_huffman(avctx, &gbit, s->max); + ret = build_huffman(avctx, avpkt->data + bytestream2_tell(&gb), + table_size, s->max); if (ret < 0) return ret; @@ -756,21 +673,6 @@ return avpkt->size; } -#if HAVE_THREADS -static int magy_init_thread_copy(AVCodecContext *avctx) -{ - MagicYUVContext *s = avctx->priv_data; - int i; - - for (i = 0; i < FF_ARRAY_ELEMS(s->slices); i++) { - s->slices[i] = NULL; - s->slices_size[i] = 0; - } - - return 0; -} -#endif - static av_cold int magy_decode_init(AVCodecContext *avctx) { MagicYUVContext *s = avctx->priv_data; @@ -799,7 +701,6 @@ .id = AV_CODEC_ID_MAGICYUV, .priv_data_size = sizeof(MagicYUVContext), .init = magy_decode_init, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(magy_init_thread_copy), .close = magy_decode_end, .decode = magy_decode_frame, .capabilities = AV_CODEC_CAP_DR1 | diff -Nru ffmpeg-4.2.2/libavcodec/magicyuvenc.c ffmpeg-4.4/libavcodec/magicyuvenc.c --- ffmpeg-4.2.2/libavcodec/magicyuvenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/magicyuvenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -40,7 +40,6 @@ } Prediction; typedef struct HuffEntry { - uint8_t sym; uint8_t len; uint32_t code; } HuffEntry; @@ -245,32 +244,18 @@ return 0; } -static int magy_huff_cmp_len(const void *a, const void *b) +static void calculate_codes(HuffEntry *he, uint16_t codes_count[33]) { - const HuffEntry *aa = a, *bb = b; - return (aa->len - bb->len) * 256 + aa->sym - bb->sym; -} - -static int huff_cmp_sym(const void *a, const void *b) -{ - const HuffEntry *aa = a, *bb = b; - return bb->sym - aa->sym; -} - -static void calculate_codes(HuffEntry *he) -{ - uint32_t code; - int i; - - AV_QSORT(he, 256, HuffEntry, magy_huff_cmp_len); - - code = 1; - for (i = 255; i >= 0; i--) { - he[i].code = code >> (32 - he[i].len); - code += 0x80000000u >> (he[i].len - 1); + for (unsigned i = 32, nb_codes = 0; i > 0; i--) { + uint16_t curr = codes_count[i]; // # of leafs of length i + codes_count[i] = nb_codes / 2; // # of non-leaf nodes on level i + nb_codes = codes_count[i] + curr; // # of nodes on level i } - AV_QSORT(he, 256, HuffEntry, huff_cmp_sym); + for (unsigned i = 0; i < 256; i++) { + he[i].code = codes_count[he[i].len]; + codes_count[he[i].len]++; + } } static void count_usage(uint8_t *src, int width, @@ -295,12 +280,13 @@ static int compare_by_prob(const void *a, const void *b) { - PTable a_val = *(PTable *)a; - PTable b_val = *(PTable *)b; - return a_val.prob - b_val.prob; + const PTable *a2 = a; + const PTable *b2 = b; + return a2->prob - b2->prob; } static void magy_huffman_compute_bits(PTable *prob_table, HuffEntry *distincts, + uint16_t codes_counts[33], int size, int max_length) { PackageMergerList list_a, list_b, *to = &list_a, *from = &list_b, *temp; @@ -356,8 +342,8 @@ } for (i = 0; i < size; i++) { - distincts[i].sym = i; distincts[i].len = nbits[i]; + codes_counts[nbits[i]]++; } } @@ -366,18 +352,19 @@ PutBitContext *pb, HuffEntry *he) { PTable counts[256] = { {0} }; + uint16_t codes_counts[33] = { 0 }; int i; count_usage(dst, width, height, counts); for (i = 0; i < 256; i++) { counts[i].prob++; - counts[i].value = 255 - i; + counts[i].value = i; } - magy_huffman_compute_bits(counts, he, 256, 12); + magy_huffman_compute_bits(counts, he, codes_counts, 256, 12); - calculate_codes(he); + calculate_codes(he, codes_counts); for (i = 0; i < 256; i++) { put_bits(pb, 1, 0); @@ -581,10 +568,11 @@ .init = magy_encode_init, .close = magy_encode_close, .encode2 = magy_encode_frame, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/Makefile ffmpeg-4.4/libavcodec/Makefile --- ffmpeg-4.2.2/libavcodec/Makefile 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/Makefile 2021-04-08 21:28:39.000000000 +0000 @@ -6,12 +6,18 @@ avcodec.h \ avdct.h \ avfft.h \ + bsf.h \ + codec.h \ + codec_desc.h \ + codec_id.h \ + codec_par.h \ d3d11va.h \ dirac.h \ dv_profile.h \ dxva2.h \ jni.h \ mediacodec.h \ + packet.h \ qsv.h \ vaapi.h \ vdpau.h \ @@ -23,6 +29,7 @@ OBJS = ac3_parser.o \ adts_parser.o \ allcodecs.o \ + avcodec.o \ avdct.o \ avpacket.o \ avpicture.o \ @@ -31,6 +38,7 @@ bitstream_filters.o \ bsf.o \ codec_desc.o \ + codec_par.o \ d3d11va.o \ decode.o \ dirac.o \ @@ -42,7 +50,6 @@ mediacodec.o \ mpeg12framerate.o \ options.o \ - mjpegenc_huffman.o \ parser.o \ parsers.o \ profiles.o \ @@ -58,14 +65,15 @@ OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio.o OBJS-$(CONFIG_AMF) += amfenc.o OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o +OBJS-$(CONFIG_ATSC_A53) += atsc_a53.o OBJS-$(CONFIG_AUDIODSP) += audiodsp.o OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o OBJS-$(CONFIG_CABAC) += cabac.o -OBJS-$(CONFIG_CBS) += cbs.o +OBJS-$(CONFIG_CBS) += cbs.o cbs_bsf.o OBJS-$(CONFIG_CBS_AV1) += cbs_av1.o -OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o h2645_parse.o -OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o h2645_parse.o +OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o cbs_sei.o h2645_parse.o +OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o cbs_sei.o h2645_parse.o OBJS-$(CONFIG_CBS_JPEG) += cbs_jpeg.o OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o @@ -76,10 +84,9 @@ OBJS-$(CONFIG_FAANDCT) += faandct.o OBJS-$(CONFIG_FAANIDCT) += faanidct.o OBJS-$(CONFIG_FDCTDSP) += fdctdsp.o jfdctfst.o jfdctint.o -FFT-OBJS-$(CONFIG_HARDCODED_TABLES) += cos_tables.o cos_fixed_tables.o -OBJS-$(CONFIG_FFT) += avfft.o fft_fixed.o fft_float.o \ - fft_fixed_32.o fft_init_table.o \ - $(FFT-OBJS-yes) +FFT-OBJS-$(CONFIG_HARDCODED_TABLES) += cos_tables.o +OBJS-$(CONFIG_FFT) += avfft.o fft_float.o fft_fixed_32.o \ + fft_init_table.o $(FFT-OBJS-yes) OBJS-$(CONFIG_FLACDSP) += flacdsp.o OBJS-$(CONFIG_FMTCONVERT) += fmtconvert.o OBJS-$(CONFIG_GOLOMB) += golomb.o @@ -89,7 +96,8 @@ OBJS-$(CONFIG_H264PARSE) += h264_parse.o h2645_parse.o h264_ps.o OBJS-$(CONFIG_H264PRED) += h264pred.o OBJS-$(CONFIG_H264QPEL) += h264qpel.o -OBJS-$(CONFIG_HEVCPARSE) += hevc_parse.o h2645_parse.o hevc_ps.o hevc_sei.o hevc_data.o +OBJS-$(CONFIG_HEVCPARSE) += hevc_parse.o h2645_parse.o hevc_ps.o hevc_sei.o hevc_data.o \ + dynamic_hdr10_plus.o OBJS-$(CONFIG_HPELDSP) += hpeldsp.o OBJS-$(CONFIG_HUFFMAN) += huffman.o OBJS-$(CONFIG_HUFFYUVDSP) += huffyuvdsp.o @@ -107,11 +115,11 @@ OBJS-$(CONFIG_LPC) += lpc.o OBJS-$(CONFIG_LSP) += lsp.o OBJS-$(CONFIG_LZF) += lzf.o -OBJS-$(CONFIG_MDCT) += mdct_fixed.o mdct_float.o mdct_fixed_32.o +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 +OBJS-$(CONFIG_MPEGAUDIO) += mpegaudio.o mpegaudiodec_common.o OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_data.o \ mpegaudiodsp_fixed.o \ @@ -134,7 +142,7 @@ OBJS-$(CONFIG_RDFT) += rdft.o OBJS-$(CONFIG_RV34DSP) += rv34dsp.o OBJS-$(CONFIG_SHARED) += log2_tab.o reverse.o -OBJS-$(CONFIG_SINEWIN) += sinewin.o sinewin_fixed.o +OBJS-$(CONFIG_SINEWIN) += sinewin.o OBJS-$(CONFIG_SNAPPY) += snappy.o OBJS-$(CONFIG_STARTCODE) += startcode.o OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o @@ -154,10 +162,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_float.o \ +OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps_common.o aacps_float.o \ mpeg4audio.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_fixed.o \ +OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o aacsbr_fixed.o aacps_common.o aacps_fixed.o \ mpeg4audio.o kbdwin.o \ sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \ @@ -166,13 +174,16 @@ aacenc_tns.o \ aacenc_ltp.o \ aacenc_pred.o \ - psymodel.o mpeg4audio.o kbdwin.o cbrt_data.o + psymodel.o mpeg4audio.o kbdwin.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_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 +OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o kbdwin.o +OBJS-$(CONFIG_AC3_MF_ENCODER) += mfenc.o mf_utils.o +OBJS-$(CONFIG_ACELP_KELVIN_DECODER) += g729dec.o lsp.o celp_math.o celp_filters.o acelp_filters.o acelp_pitch_delay.o acelp_vectors.o g729postfilter.o OBJS-$(CONFIG_AGM_DECODER) += agm.o OBJS-$(CONFIG_AIC_DECODER) += aic.o OBJS-$(CONFIG_ALAC_DECODER) += alac.o alac_data.o alacdsp.o @@ -193,13 +204,14 @@ OBJS-$(CONFIG_ANM_DECODER) += anm.o OBJS-$(CONFIG_ANSI_DECODER) += ansi.o cga_data.o OBJS-$(CONFIG_APE_DECODER) += apedec.o -OBJS-$(CONFIG_APTX_DECODER) += aptx.o -OBJS-$(CONFIG_APTX_ENCODER) += aptx.o -OBJS-$(CONFIG_APTX_HD_DECODER) += aptx.o -OBJS-$(CONFIG_APTX_HD_ENCODER) += aptx.o +OBJS-$(CONFIG_APTX_DECODER) += aptxdec.o aptx.o +OBJS-$(CONFIG_APTX_ENCODER) += aptxenc.o aptx.o +OBJS-$(CONFIG_APTX_HD_DECODER) += aptxdec.o aptx.o +OBJS-$(CONFIG_APTX_HD_ENCODER) += aptxenc.o aptx.o OBJS-$(CONFIG_APNG_DECODER) += png.o pngdec.o pngdsp.o OBJS-$(CONFIG_APNG_ENCODER) += png.o pngenc.o OBJS-$(CONFIG_ARBC_DECODER) += arbc.o +OBJS-$(CONFIG_ARGO_DECODER) += argo.o OBJS-$(CONFIG_SSA_DECODER) += assdec.o ass.o OBJS-$(CONFIG_SSA_ENCODER) += assenc.o ass.o OBJS-$(CONFIG_ASS_DECODER) += assdec.o ass.o @@ -218,7 +230,9 @@ OBJS-$(CONFIG_ATRAC9_DECODER) += atrac9dec.o OBJS-$(CONFIG_AURA_DECODER) += cyuv.o OBJS-$(CONFIG_AURA2_DECODER) += aura.o -OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o mjpegdec.o +OBJS-$(CONFIG_AV1_DECODER) += av1dec.o +OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o +OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o OBJS-$(CONFIG_AVS_DECODER) += avs.o @@ -241,10 +255,12 @@ OBJS-$(CONFIG_C93_DECODER) += c93.o OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ cavsdata.o -OBJS-$(CONFIG_CCAPTION_DECODER) += ccaption_dec.o +OBJS-$(CONFIG_CCAPTION_DECODER) += ccaption_dec.o ass.o OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o +OBJS-$(CONFIG_CDTOONS_DECODER) += cdtoons.o OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o -OBJS-$(CONFIG_CFHD_DECODER) += cfhd.o cfhddata.o +OBJS-$(CONFIG_CFHD_DECODER) += cfhd.o cfhddata.o cfhddsp.o +OBJS-$(CONFIG_CFHD_ENCODER) += cfhdenc.o cfhddata.o cfhdencdsp.o OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o OBJS-$(CONFIG_CINEPAK_ENCODER) += cinepakenc.o elbg.o OBJS-$(CONFIG_CLEARVIDEO_DECODER) += clearvideo.o @@ -255,20 +271,22 @@ OBJS-$(CONFIG_COMFORTNOISE_ENCODER) += cngenc.o OBJS-$(CONFIG_COOK_DECODER) += cook.o OBJS-$(CONFIG_CPIA_DECODER) += cpia.o +OBJS-$(CONFIG_CRI_DECODER) += cri.o 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 -OBJS-$(CONFIG_DCA_ENCODER) += dcaenc.o dca.o dcadata.o dcahuff.o \ +OBJS-$(CONFIG_DCA_ENCODER) += dcaenc.o dcadata.o dcahuff.o \ dcaadpcm.o OBJS-$(CONFIG_DDS_DECODER) += dds.o +OBJS-$(CONFIG_DERF_DPCM_DECODER) += dpcm.o OBJS-$(CONFIG_DIRAC_DECODER) += diracdec.o dirac.o diracdsp.o diractab.o \ dirac_arith.o dirac_dwt.o dirac_vlc.o OBJS-$(CONFIG_DFA_DECODER) += dfa.o OBJS-$(CONFIG_DNXHD_DECODER) += dnxhddec.o dnxhddata.o OBJS-$(CONFIG_DNXHD_ENCODER) += dnxhdenc.o dnxhddata.o -OBJS-$(CONFIG_DOLBY_E_DECODER) += dolby_e.o kbdwin.o +OBJS-$(CONFIG_DOLBY_E_DECODER) += dolby_e.o dolby_e_parse.o kbdwin.o OBJS-$(CONFIG_DPX_DECODER) += dpx.o OBJS-$(CONFIG_DPX_ENCODER) += dpxenc.o OBJS-$(CONFIG_DSD_LSBF_DECODER) += dsddec.o dsd.o @@ -280,9 +298,9 @@ OBJS-$(CONFIG_DSS_SP_DECODER) += dss_sp.o OBJS-$(CONFIG_DST_DECODER) += dstdec.o dsd.o OBJS-$(CONFIG_DVBSUB_DECODER) += dvbsubdec.o -OBJS-$(CONFIG_DVBSUB_ENCODER) += dvbsub.o -OBJS-$(CONFIG_DVDSUB_DECODER) += dvdsubdec.o -OBJS-$(CONFIG_DVDSUB_ENCODER) += dvdsubenc.o +OBJS-$(CONFIG_DVBSUB_ENCODER) += dvbsubenc.o +OBJS-$(CONFIG_DVDSUB_DECODER) += dvdsubdec.o dvdsub.o +OBJS-$(CONFIG_DVDSUB_ENCODER) += dvdsubenc.o dvdsub.o OBJS-$(CONFIG_DVAUDIO_DECODER) += dvaudiodec.o OBJS-$(CONFIG_DVVIDEO_DECODER) += dvdec.o dv.o dvdata.o OBJS-$(CONFIG_DVVIDEO_ENCODER) += dvenc.o dv.o dvdata.o @@ -304,6 +322,8 @@ OBJS-$(CONFIG_ESCAPE130_DECODER) += escape130.o OBJS-$(CONFIG_EVRC_DECODER) += evrcdec.o acelp_vectors.o lsp.o OBJS-$(CONFIG_EXR_DECODER) += exr.o exrdsp.o +OBJS-$(CONFIG_EXR_ENCODER) += exrenc.o +OBJS-$(CONFIG_FASTAUDIO_DECODER) += fastaudio.o OBJS-$(CONFIG_FFV1_DECODER) += ffv1dec.o ffv1.o OBJS-$(CONFIG_FFV1_ENCODER) += ffv1enc.o ffv1.o OBJS-$(CONFIG_FFWAVESYNTH_DECODER) += ffwavesynth.o @@ -311,17 +331,19 @@ OBJS-$(CONFIG_FITS_DECODER) += fitsdec.o fits.o OBJS-$(CONFIG_FITS_ENCODER) += fitsenc.o OBJS-$(CONFIG_FLAC_DECODER) += flacdec.o flacdata.o flac.o -OBJS-$(CONFIG_FLAC_ENCODER) += flacenc.o flacdata.o flac.o vorbis_data.o +OBJS-$(CONFIG_FLAC_ENCODER) += flacenc.o flacdata.o flac.o OBJS-$(CONFIG_FLASHSV_DECODER) += flashsv.o OBJS-$(CONFIG_FLASHSV_ENCODER) += flashsvenc.o OBJS-$(CONFIG_FLASHSV2_ENCODER) += flashsv2enc.o OBJS-$(CONFIG_FLASHSV2_DECODER) += flashsv.o OBJS-$(CONFIG_FLIC_DECODER) += flicvideo.o +OBJS-$(CONFIG_FLV_DECODER) += flvdec.o +OBJS-$(CONFIG_FLV_ENCODER) += flvenc.o OBJS-$(CONFIG_FMVC_DECODER) += fmvc.o OBJS-$(CONFIG_FOURXM_DECODER) += 4xm.o OBJS-$(CONFIG_FRAPS_DECODER) += fraps.o OBJS-$(CONFIG_FRWU_DECODER) += frwu.o -OBJS-$(CONFIG_G2M_DECODER) += g2meet.o elsdec.o +OBJS-$(CONFIG_G2M_DECODER) += g2meet.o elsdec.o mjpegdec_common.o OBJS-$(CONFIG_G723_1_DECODER) += g723_1dec.o g723_1.o \ acelp_vectors.o celp_filters.o celp_math.o OBJS-$(CONFIG_G723_1_ENCODER) += g723_1enc.o g723_1.o \ @@ -336,10 +358,11 @@ OBJS-$(CONFIG_H261_DECODER) += h261dec.o h261data.o h261.o OBJS-$(CONFIG_H261_ENCODER) += h261enc.o h261data.o h261.o OBJS-$(CONFIG_H263_DECODER) += h263dec.o h263.o ituh263dec.o \ - mpeg4video.o mpeg4videodec.o flvdec.o\ - intelh263dec.o h263data.o -OBJS-$(CONFIG_H263_ENCODER) += mpeg4videoenc.o mpeg4video.o \ - h263.o ituh263enc.o flvenc.o h263data.o + mpeg4video.o mpeg4videodec.o \ + h263data.o +OBJS-$(CONFIG_H263I_DECODER) += intelh263dec.o +OBJS-$(CONFIG_H263_ENCODER) += mpeg4video.o \ + h263.o ituh263enc.o h263data.o OBJS-$(CONFIG_H263_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_H263_V4L2M2M_ENCODER) += v4l2_m2m_enc.o OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \ @@ -350,12 +373,13 @@ OBJS-$(CONFIG_H264_AMF_ENCODER) += amfenc_h264.o OBJS-$(CONFIG_H264_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_H264_MEDIACODEC_DECODER) += mediacodecdec.o +OBJS-$(CONFIG_H264_MF_ENCODER) += mfenc.o mf_utils.o OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o OBJS-$(CONFIG_NVENC_ENCODER) += nvenc_h264.o OBJS-$(CONFIG_NVENC_H264_ENCODER) += nvenc_h264.o OBJS-$(CONFIG_H264_OMX_ENCODER) += omx.o -OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec_h2645.o +OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o OBJS-$(CONFIG_H264_RKMPP_DECODER) += rkmppdec.o OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o h264_levels.o @@ -364,6 +388,7 @@ OBJS-$(CONFIG_H264_V4L2M2M_ENCODER) += v4l2_m2m_enc.o OBJS-$(CONFIG_HAP_DECODER) += hapdec.o hap.o OBJS-$(CONFIG_HAP_ENCODER) += hapenc.o hap.o +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 \ @@ -371,9 +396,10 @@ 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_NVENC_HEVC_ENCODER) += nvenc_hevc.o -OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec_h2645.o +OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \ hevc_data.o OBJS-$(CONFIG_HEVC_RKMPP_DECODER) += rkmppdec.o @@ -393,6 +419,7 @@ OBJS-$(CONFIG_ILBC_DECODER) += ilbcdec.o OBJS-$(CONFIG_IMC_DECODER) += imc.o OBJS-$(CONFIG_IMM4_DECODER) += imm4.o +OBJS-$(CONFIG_IMM5_DECODER) += imm5.o OBJS-$(CONFIG_INDEO2_DECODER) += indeo2.o OBJS-$(CONFIG_INDEO3_DECODER) += indeo3.o OBJS-$(CONFIG_INDEO4_DECODER) += indeo4.o ivi.o @@ -400,6 +427,7 @@ OBJS-$(CONFIG_INTERPLAY_ACM_DECODER) += interplayacm.o OBJS-$(CONFIG_INTERPLAY_DPCM_DECODER) += dpcm.o OBJS-$(CONFIG_INTERPLAY_VIDEO_DECODER) += interplayvideo.o +OBJS-$(CONFIG_IPU_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_JACOSUB_DECODER) += jacosubdec.o ass.o OBJS-$(CONFIG_JPEG2000_ENCODER) += j2kenc.o mqcenc.o mqc.o jpeg2000.o \ jpeg2000dwt.o @@ -413,7 +441,7 @@ OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc_common.o OBJS-$(CONFIG_LOCO_DECODER) += loco.o -OBJS-$(CONFIG_LSCR_DECODER) += png.o pngdec.o pngdsp.o +OBJS-$(CONFIG_LSCR_DECODER) += lscrdec.o png.o pngdec.o pngdsp.o OBJS-$(CONFIG_M101_DECODER) += m101.o OBJS-$(CONFIG_MACE3_DECODER) += mace.o OBJS-$(CONFIG_MACE6_DECODER) += mace.o @@ -424,7 +452,8 @@ twinvq.o OBJS-$(CONFIG_MICRODVD_DECODER) += microdvddec.o ass.o OBJS-$(CONFIG_MIMIC_DECODER) += mimic.o -OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o +OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o mjpegdec_common.o +OBJS-$(CONFIG_MJPEG_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpegenc_common.o \ mjpegenc_huffman.o OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o @@ -434,6 +463,7 @@ OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o OBJS-$(CONFIG_MLP_ENCODER) += mlpenc.o mlp.o OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o +OBJS-$(CONFIG_MOBICLIP_DECODER) += mobiclip.o OBJS-$(CONFIG_MOTIONPIXELS_DECODER) += motionpixels.o OBJS-$(CONFIG_MOVTEXT_DECODER) += movtextdec.o ass.o OBJS-$(CONFIG_MOVTEXT_ENCODER) += movtextenc.o ass_split.o @@ -446,6 +476,7 @@ mpegaudiodata.o mpegaudiodsp_data.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 @@ -459,7 +490,7 @@ OBJS-$(CONFIG_MPEG1_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MPEG1_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_MPEG2_MMAL_DECODER) += mmaldec.o -OBJS-$(CONFIG_MPEG2_QSV_DECODER) += qsvdec_other.o +OBJS-$(CONFIG_MPEG2_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_MPEG2_QSV_ENCODER) += qsvenc_mpeg2.o OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpeg12.o @@ -468,6 +499,7 @@ OBJS-$(CONFIG_MPEG2_VAAPI_ENCODER) += vaapi_encode_mpeg2.o OBJS-$(CONFIG_MPEG2_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_MPEG4_DECODER) += xvididct.o +OBJS-$(CONFIG_MPEG4_ENCODER) += mpeg4videoenc.o OBJS-$(CONFIG_MPEG4_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MPEG4_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_MPEG4_OMX_ENCODER) += omx.o @@ -481,6 +513,7 @@ OBJS-$(CONFIG_MSMPEG4V2_ENCODER) += msmpeg4enc.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_MSMPEG4V3_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_MSMPEG4V3_ENCODER) += msmpeg4enc.o msmpeg4.o msmpeg4data.o +OBJS-$(CONFIG_MSP2_DECODER) += msp2dec.o OBJS-$(CONFIG_MSRLE_DECODER) += msrle.o msrledec.o OBJS-$(CONFIG_MSS1_DECODER) += mss1.o mss12.o OBJS-$(CONFIG_MSS2_DECODER) += mss2.o mss12.o mss2dsp.o wmv2data.o @@ -488,19 +521,23 @@ OBJS-$(CONFIG_MSVIDEO1_ENCODER) += msvideo1enc.o elbg.o OBJS-$(CONFIG_MSZH_DECODER) += lcldec.o OBJS-$(CONFIG_MTS2_DECODER) += mss4.o +OBJS-$(CONFIG_MV30_DECODER) += mv30.o OBJS-$(CONFIG_MVC1_DECODER) += mvcdec.o OBJS-$(CONFIG_MVC2_DECODER) += mvcdec.o +OBJS-$(CONFIG_MVDV_DECODER) += midivid.o +OBJS-$(CONFIG_MVHA_DECODER) += mvha.o OBJS-$(CONFIG_MWSC_DECODER) += mwsc.o OBJS-$(CONFIG_MXPEG_DECODER) += mxpegdec.o OBJS-$(CONFIG_NELLYMOSER_DECODER) += nellymoserdec.o nellymoser.o OBJS-$(CONFIG_NELLYMOSER_ENCODER) += nellymoserenc.o nellymoser.o +OBJS-$(CONFIG_NOTCHLC_DECODER) += notchlc.o OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o OBJS-$(CONFIG_ON2AVC_DECODER) += on2avc.o on2avcdata.o OBJS-$(CONFIG_OPUS_DECODER) += opusdec.o opus.o opus_celt.o opus_rc.o \ opus_pvq.o opus_silk.o opustab.o vorbis_data.o \ opusdsp.o OBJS-$(CONFIG_OPUS_ENCODER) += opusenc.o opus.o opus_rc.o opustab.o opus_pvq.o \ - opusenc_psy.o + opusenc_psy.o vorbis_data.o OBJS-$(CONFIG_PAF_AUDIO_DECODER) += pafaudio.o OBJS-$(CONFIG_PAF_VIDEO_DECODER) += pafvideo.o OBJS-$(CONFIG_PAM_DECODER) += pnmdec.o pnm.o @@ -509,11 +546,15 @@ OBJS-$(CONFIG_PBM_ENCODER) += pnmenc.o OBJS-$(CONFIG_PCX_DECODER) += pcx.o OBJS-$(CONFIG_PCX_ENCODER) += pcxenc.o +OBJS-$(CONFIG_PFM_DECODER) += pnmdec.o pnm.o +OBJS-$(CONFIG_PFM_ENCODER) += pnmenc.o OBJS-$(CONFIG_PGM_DECODER) += pnmdec.o pnm.o OBJS-$(CONFIG_PGM_ENCODER) += pnmenc.o OBJS-$(CONFIG_PGMYUV_DECODER) += pnmdec.o pnm.o OBJS-$(CONFIG_PGMYUV_ENCODER) += pnmenc.o OBJS-$(CONFIG_PGSSUB_DECODER) += pgssubdec.o +OBJS-$(CONFIG_PGX_DECODER) += pgxdec.o +OBJS-$(CONFIG_PHOTOCD_DECODER) += photocd.o OBJS-$(CONFIG_PICTOR_DECODER) += pictordec.o cga_data.o OBJS-$(CONFIG_PIXLET_DECODER) += pixlet.o OBJS-$(CONFIG_PJS_DECODER) += textdec.o ass.o @@ -555,6 +596,7 @@ OBJS-$(CONFIG_ROQ_DPCM_DECODER) += dpcm.o OBJS-$(CONFIG_ROQ_DPCM_ENCODER) += roqaudioenc.o OBJS-$(CONFIG_RPZA_DECODER) += rpza.o +OBJS-$(CONFIG_RPZA_ENCODER) += rpzaenc.o OBJS-$(CONFIG_RSCC_DECODER) += rscc.o OBJS-$(CONFIG_RV10_DECODER) += rv10.o OBJS-$(CONFIG_RV10_ENCODER) += rv10enc.o @@ -569,6 +611,7 @@ OBJS-$(CONFIG_SCPR_DECODER) += scpr.o OBJS-$(CONFIG_SCREENPRESSO_DECODER) += screenpresso.o OBJS-$(CONFIG_SDX2_DPCM_DECODER) += dpcm.o +OBJS-$(CONFIG_SGA_DECODER) += sga.o OBJS-$(CONFIG_SGI_DECODER) += sgidec.o OBJS-$(CONFIG_SGI_ENCODER) += sgienc.o rle.o OBJS-$(CONFIG_SGIRLE_DECODER) += sgirledec.o @@ -578,18 +621,20 @@ celp_math.o acelp_vectors.o \ acelp_filters.o celp_filters.o \ sipr16k.o +OBJS-$(CONFIG_SIREN_DECODER) += siren.o +OBJS-$(CONFIG_SIMBIOSIS_IMX_DECODER) += imx.o OBJS-$(CONFIG_SMACKAUD_DECODER) += smacker.o OBJS-$(CONFIG_SMACKER_DECODER) += smacker.o OBJS-$(CONFIG_SMC_DECODER) += smc.o -OBJS-$(CONFIG_SMVJPEG_DECODER) += smvjpegdec.o OBJS-$(CONFIG_SNOW_DECODER) += snowdec.o snow.o snow_dwt.o OBJS-$(CONFIG_SNOW_ENCODER) += snowenc.o snow.o snow_dwt.o \ - h263.o ituh263enc.o + h263.o h263data.o ituh263enc.o OBJS-$(CONFIG_SOL_DPCM_DECODER) += dpcm.o OBJS-$(CONFIG_SONIC_DECODER) += sonic.o OBJS-$(CONFIG_SONIC_ENCODER) += sonic.o OBJS-$(CONFIG_SONIC_LS_ENCODER) += sonic.o OBJS-$(CONFIG_SPEEDHQ_DECODER) += speedhq.o mpeg12.o mpeg12data.o simple_idct.o +OBJS-$(CONFIG_SPEEDHQ_ENCODER) += speedhq.o mpeg12data.o mpeg12enc.o speedhqenc.o OBJS-$(CONFIG_SP5X_DECODER) += sp5xdec.o OBJS-$(CONFIG_SRGC_DECODER) += mscc.o OBJS-$(CONFIG_SRT_DECODER) += srtdec.o ass.o htmlsubtitles.o @@ -604,10 +649,10 @@ OBJS-$(CONFIG_LIBRSVG_DECODER) += librsvgdec.o OBJS-$(CONFIG_SBC_DECODER) += sbcdec.o sbcdec_data.o sbc.o OBJS-$(CONFIG_SBC_ENCODER) += sbcenc.o sbc.o sbcdsp.o sbcdsp_data.o -OBJS-$(CONFIG_SVQ1_DECODER) += svq1dec.o svq1.o svq13.o h263data.o +OBJS-$(CONFIG_SVQ1_DECODER) += svq1dec.o svq1.o h263data.o OBJS-$(CONFIG_SVQ1_ENCODER) += svq1enc.o svq1.o h263data.o \ h263.o ituh263enc.o -OBJS-$(CONFIG_SVQ3_DECODER) += svq3.o svq13.o mpegutils.o h264data.o +OBJS-$(CONFIG_SVQ3_DECODER) += svq3.o mpegutils.o h264data.o OBJS-$(CONFIG_TEXT_DECODER) += textdec.o ass.o OBJS-$(CONFIG_TEXT_ENCODER) += srtenc.o ass_split.o OBJS-$(CONFIG_TAK_DECODER) += takdec.o tak.o takdsp.o @@ -616,8 +661,8 @@ OBJS-$(CONFIG_TARGA_Y216_DECODER) += targa_y216dec.o OBJS-$(CONFIG_TDSC_DECODER) += tdsc.o OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o -OBJS-$(CONFIG_TIFF_DECODER) += tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o -OBJS-$(CONFIG_TIFF_ENCODER) += tiffenc.o rle.o lzwenc.o tiff_data.o +OBJS-$(CONFIG_TIFF_DECODER) += tiff.o lzw.o faxcompr.o tiff_common.o +OBJS-$(CONFIG_TIFF_ENCODER) += tiffenc.o rle.o lzwenc.o OBJS-$(CONFIG_TMV_DECODER) += tmv.o cga_data.o OBJS-$(CONFIG_TRUEHD_DECODER) += mlpdec.o mlpdsp.o OBJS-$(CONFIG_TRUEHD_ENCODER) += mlpenc.o mlp.o @@ -629,11 +674,12 @@ OBJS-$(CONFIG_TSCC2_DECODER) += tscc2.o OBJS-$(CONFIG_TTA_DECODER) += tta.o ttadata.o ttadsp.o OBJS-$(CONFIG_TTA_ENCODER) += ttaenc.o ttaencdsp.o ttadata.o -OBJS-$(CONFIG_TWINVQ_DECODER) += twinvqdec.o twinvq.o +OBJS-$(CONFIG_TTML_ENCODER) += ttmlenc.o ass_split.o +OBJS-$(CONFIG_TWINVQ_DECODER) += twinvqdec.o twinvq.o metasound_data.o OBJS-$(CONFIG_TXD_DECODER) += txd.o OBJS-$(CONFIG_ULTI_DECODER) += ulti.o -OBJS-$(CONFIG_UTVIDEO_DECODER) += utvideodec.o utvideo.o utvideodsp.o -OBJS-$(CONFIG_UTVIDEO_ENCODER) += utvideoenc.o utvideo.o +OBJS-$(CONFIG_UTVIDEO_DECODER) += utvideodec.o utvideodsp.o +OBJS-$(CONFIG_UTVIDEO_ENCODER) += utvideoenc.o OBJS-$(CONFIG_V210_DECODER) += v210dec.o OBJS-$(CONFIG_V210_ENCODER) += v210enc.o OBJS-$(CONFIG_V210X_DECODER) += v210x.o @@ -651,7 +697,7 @@ wmv2dsp.o wmv2data.o OBJS-$(CONFIG_VC1_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_VC1_MMAL_DECODER) += mmaldec.o -OBJS-$(CONFIG_VC1_QSV_DECODER) += qsvdec_other.o +OBJS-$(CONFIG_VC1_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_VC1_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_VC2_ENCODER) += vc2enc.o vc2enc_dwt.o diractab.o OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o @@ -670,7 +716,7 @@ OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp56rac.o OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_VP8_MEDIACODEC_DECODER) += mediacodecdec.o -OBJS-$(CONFIG_VP8_QSV_DECODER) += qsvdec_other.o +OBJS-$(CONFIG_VP8_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_VP8_RKMPP_DECODER) += rkmppdec.o OBJS-$(CONFIG_VP8_VAAPI_ENCODER) += vaapi_encode_vp8.o OBJS-$(CONFIG_VP8_V4L2M2M_DECODER) += v4l2_m2m_dec.o @@ -682,11 +728,12 @@ OBJS-$(CONFIG_VP9_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_VP9_RKMPP_DECODER) += rkmppdec.o OBJS-$(CONFIG_VP9_VAAPI_ENCODER) += vaapi_encode_vp9.o +OBJS-$(CONFIG_VP9_QSV_ENCODER) += qsvenc_vp9.o OBJS-$(CONFIG_VPLAYER_DECODER) += textdec.o ass.o OBJS-$(CONFIG_VP9_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o -OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o -OBJS-$(CONFIG_WAVPACK_ENCODER) += wavpackenc.o +OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o wavpackdata.o dsd.o +OBJS-$(CONFIG_WAVPACK_ENCODER) += wavpackdata.o wavpackenc.o OBJS-$(CONFIG_WCMV_DECODER) += wcmv.o OBJS-$(CONFIG_WEBP_DECODER) += webp.o OBJS-$(CONFIG_WEBVTT_DECODER) += webvttdec.o ass.o @@ -701,7 +748,7 @@ celp_filters.o \ acelp_vectors.o acelp_filters.o OBJS-$(CONFIG_WMV1_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o -OBJS-$(CONFIG_WMV1_ENCODER) += msmpeg4enc.o +OBJS-$(CONFIG_WMV1_ENCODER) += msmpeg4enc.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_WMV2_DECODER) += wmv2dec.o wmv2.o wmv2data.o \ msmpeg4dec.o msmpeg4.o msmpeg4data.o OBJS-$(CONFIG_WMV2_ENCODER) += wmv2enc.o wmv2.o wmv2data.o \ @@ -787,6 +834,7 @@ OBJS-$(CONFIG_PCM_S64BE_ENCODER) += pcm.o OBJS-$(CONFIG_PCM_S64LE_DECODER) += pcm.o OBJS-$(CONFIG_PCM_S64LE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_SGA_DECODER) += pcm.o OBJS-$(CONFIG_PCM_U8_DECODER) += pcm.o OBJS-$(CONFIG_PCM_U8_ENCODER) += pcm.o OBJS-$(CONFIG_PCM_U16BE_DECODER) += pcm.o @@ -803,7 +851,6 @@ OBJS-$(CONFIG_PCM_U32LE_ENCODER) += pcm.o OBJS-$(CONFIG_PCM_VIDC_DECODER) += pcm.o OBJS-$(CONFIG_PCM_VIDC_ENCODER) += pcm.o -OBJS-$(CONFIG_PCM_ZORK_DECODER) += pcm.o OBJS-$(CONFIG_ADPCM_4XM_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_ADX_DECODER) += adxdec.o adx.o @@ -811,6 +858,8 @@ OBJS-$(CONFIG_ADPCM_AFC_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_AGM_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_AICA_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_ARGO_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_ARGO_ENCODER) += adpcm.o adpcmenc.o OBJS-$(CONFIG_ADPCM_CT_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_DTK_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_EA_DECODER) += adpcm.o adpcm_data.o @@ -826,17 +875,26 @@ OBJS-$(CONFIG_ADPCM_G726LE_DECODER) += g726.o OBJS-$(CONFIG_ADPCM_G726LE_ENCODER) += g726.o OBJS-$(CONFIG_ADPCM_IMA_AMV_DECODER) += adpcm.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 +OBJS-$(CONFIG_ADPCM_IMA_APM_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_APM_ENCODER) += adpcmenc.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_CUNNING_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_DAT4_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_DK3_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_EA_EACS_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_EA_SEAD_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_MOFLEX_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_MTF_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_OKI_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_QT_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_QT_ENCODER) += adpcmenc.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_RAD_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_SSI_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_SSI_ENCODER) += adpcmenc.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_SMJPEG_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_WAV_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_WAV_ENCODER) += adpcmenc.o adpcm_data.o @@ -856,6 +914,7 @@ OBJS-$(CONFIG_ADPCM_XA_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_ZORK_DECODER) += adpcm.o adpcm_data.o # hardware accelerators OBJS-$(CONFIG_D3D11VA) += dxva2.o @@ -865,21 +924,25 @@ OBJS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.o OBJS-$(CONFIG_VDPAU) += vdpau.o +OBJS-$(CONFIG_AV1_D3D11VA_HWACCEL) += dxva2_av1.o +OBJS-$(CONFIG_AV1_DXVA2_HWACCEL) += dxva2_av1.o +OBJS-$(CONFIG_AV1_NVDEC_HWACCEL) += nvdec_av1.o +OBJS-$(CONFIG_AV1_VAAPI_HWACCEL) += vaapi_av1.o OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o OBJS-$(CONFIG_H263_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o OBJS-$(CONFIG_H264_NVDEC_HWACCEL) += nvdec_h264.o -OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o +OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec.o OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o -OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o -OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o -OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o +OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec.o +OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o h265_profile_level.o +OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o h265_profile_level.o OBJS-$(CONFIG_MJPEG_NVDEC_HWACCEL) += nvdec_mjpeg.o OBJS-$(CONFIG_MJPEG_VAAPI_HWACCEL) += vaapi_mjpeg.o OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL) += nvdec_mpeg12.o @@ -889,7 +952,7 @@ OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o -OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec_other.o +OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec.o OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o OBJS-$(CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o @@ -901,7 +964,7 @@ OBJS-$(CONFIG_VC1_D3D11VA_HWACCEL) += dxva2_vc1.o OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o OBJS-$(CONFIG_VC1_NVDEC_HWACCEL) += nvdec_vc1.o -OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec_other.o +OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec.o OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o OBJS-$(CONFIG_VP8_NVDEC_HWACCEL) += nvdec_vp8.o @@ -910,26 +973,25 @@ OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o -OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec_other.o +OBJS-$(CONFIG_VP9_VDPAU_HWACCEL) += vdpau_vp9.o +OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec.o # libavformat dependencies OBJS-$(CONFIG_ISO_MEDIA) += mpeg4audio.o mpegaudiodata.o OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_CAF_DEMUXER) += ac3tab.o OBJS-$(CONFIG_CODEC2_DEMUXER) += codec2utils.o OBJS-$(CONFIG_CODEC2_MUXER) += codec2utils.o OBJS-$(CONFIG_CODEC2RAW_DEMUXER) += codec2utils.o OBJS-$(CONFIG_DNXHD_DEMUXER) += dnxhddata.o OBJS-$(CONFIG_FITS_DEMUXER) += fits.o -OBJS-$(CONFIG_FLV_DEMUXER) += mpeg4audio.o 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_NUT_DEMUXER) += mpegaudiodata.o mpeg4audio.o OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o OBJS-$(CONFIG_SPDIF_MUXER) += dca.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o @@ -988,11 +1050,14 @@ vorbis_data.o OBJS-$(CONFIG_LIBOPUS_ENCODER) += libopusenc.o libopus.o \ vorbis_data.o +OBJS-$(CONFIG_LIBRAV1E_ENCODER) += librav1e.o OBJS-$(CONFIG_LIBSHINE_ENCODER) += libshine.o OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o +OBJS-$(CONFIG_LIBSVTAV1_ENCODER) += libsvtav1.o OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUAVS3D_DECODER) += libuavs3d.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ @@ -1001,7 +1066,6 @@ OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o libvpx.o OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o -OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.o libwebpenc.o OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER) += libwebpenc_common.o libwebpenc_animencoder.o OBJS-$(CONFIG_LIBX262_ENCODER) += libx264.o @@ -1020,19 +1084,21 @@ OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o av1_parse.o OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o 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_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 OBJS-$(CONFIG_DPX_PARSER) += dpx_parser.o OBJS-$(CONFIG_DVAUDIO_PARSER) += dvaudio_parser.o OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsub_parser.o OBJS-$(CONFIG_DVD_NAV_PARSER) += dvd_nav_parser.o OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o -OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o \ - vorbis_data.o +OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o OBJS-$(CONFIG_G723_1_PARSER) += g723_1_parser.o OBJS-$(CONFIG_G729_PARSER) += g729_parser.o OBJS-$(CONFIG_GIF_PARSER) += gif_parser.o @@ -1041,12 +1107,13 @@ OBJS-$(CONFIG_H263_PARSER) += h263_parser.o OBJS-$(CONFIG_H264_PARSER) += h264_parser.o h264_sei.o h264data.o OBJS-$(CONFIG_HEVC_PARSER) += hevc_parser.o hevc_data.o +OBJS-$(CONFIG_IPU_PARSER) += ipu_parser.o +OBJS-$(CONFIG_JPEG2000_PARSER) += jpeg2000_parser.o OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o OBJS-$(CONFIG_MLP_PARSER) += mlp_parse.o mlp_parser.o mlp.o OBJS-$(CONFIG_MPEG4VIDEO_PARSER) += mpeg4video_parser.o h263.o \ mpeg4videodec.o mpeg4video.o \ ituh263dec.o h263dec.o h263data.o -OBJS-$(CONFIG_PNG_PARSER) += png_parser.o OBJS-$(CONFIG_MPEGAUDIO_PARSER) += mpegaudio_parser.o OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o \ mpeg12.o mpeg12data.o @@ -1064,11 +1131,14 @@ OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o OBJS-$(CONFIG_VP8_PARSER) += vp8_parser.o OBJS-$(CONFIG_VP9_PARSER) += vp9_parser.o +OBJS-$(CONFIG_WEBP_PARSER) += webp_parser.o +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_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 OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o @@ -1093,8 +1163,11 @@ OBJS-$(CONFIG_MPEG2_METADATA_BSF) += mpeg2_metadata_bsf.o OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o +OBJS-$(CONFIG_OPUS_METADATA_BSF) += opus_metadata_bsf.o +OBJS-$(CONFIG_PCM_RECHUNK_BSF) += pcm_rechunk_bsf.o OBJS-$(CONFIG_PRORES_METADATA_BSF) += prores_metadata_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o +OBJS-$(CONFIG_SETTS_BSF) += setts_bsf.o OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o OBJS-$(CONFIG_TRACE_HEADERS_BSF) += trace_headers_bsf.o OBJS-$(CONFIG_TRUEHD_CORE_BSF) += truehd_core_bsf.o mlp_parse.o mlp.o @@ -1130,13 +1203,13 @@ SKIPHEADERS-$(CONFIG_LIBVPX) += libvpx.h SKIPHEADERS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.h SKIPHEADERS-$(CONFIG_MEDIACODEC) += mediacodecdec_common.h mediacodec_surface.h mediacodec_wrapper.h mediacodec_sw_buffer.h +SKIPHEADERS-$(CONFIG_MEDIAFOUNDATION) += mf_utils.h SKIPHEADERS-$(CONFIG_NVDEC) += nvdec.h SKIPHEADERS-$(CONFIG_NVENC) += nvenc.h SKIPHEADERS-$(CONFIG_QSV) += qsv.h qsv_internal.h -SKIPHEADERS-$(CONFIG_QSVDEC) += qsvdec.h SKIPHEADERS-$(CONFIG_QSVENC) += qsvenc.h SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h -SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_decode.h vaapi_encode.h +SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_decode.h vaapi_hevc.h vaapi_encode.h SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h vdpau_internal.h SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vt_internal.h SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m.h @@ -1148,16 +1221,15 @@ imgconvert \ jpeg2000dwt \ mathops \ - options \ - mjpegenc_huffman \ utils \ TESTPROGS-$(CONFIG_CABAC) += cabac TESTPROGS-$(CONFIG_DCT) += avfft -TESTPROGS-$(CONFIG_FFT) += fft fft-fixed fft-fixed32 +TESTPROGS-$(CONFIG_FFT) += fft fft-fixed32 TESTPROGS-$(CONFIG_GOLOMB) += golomb TESTPROGS-$(CONFIG_IDCTDSP) += dct TESTPROGS-$(CONFIG_IIRFILTER) += iirfilter +TESTPROGS-$(CONFIG_MJPEG_ENCODER) += mjpegenc_huffman TESTPROGS-$(HAVE_MMX) += motion TESTPROGS-$(CONFIG_MPEGVIDEO) += mpeg12framerate TESTPROGS-$(CONFIG_H264_METADATA_BSF) += h264_levels @@ -1177,6 +1249,7 @@ dv_tablegen \ motionpixels_tablegen \ mpegaudio_tablegen \ + mpegaudiodec_common_tablegen \ pcm_tablegen \ qdm2_tablegen \ sinewin_tablegen \ @@ -1201,7 +1274,8 @@ GEN_HEADERS = cbrt_tables.h cbrt_fixed_tables.h aacps_tables.h aacps_fixed_tables.h \ dv_tables.h \ - sinewin_tables.h sinewin_fixed_tables.h mpegaudio_tables.h motionpixels_tables.h \ + sinewin_tables.h sinewin_fixed_tables.h mpegaudio_tables.h \ + mpegaudiodec_common_tables.h motionpixels_tables.h \ pcm_tables.h qdm2_tables.h GEN_HEADERS := $(addprefix $(SUBDIR), $(GEN_HEADERS)) @@ -1211,15 +1285,15 @@ ifdef CONFIG_HARDCODED_TABLES $(SUBDIR)cbrt_data.o: $(SUBDIR)cbrt_tables.h $(SUBDIR)cbrt_data_fixed.o: $(SUBDIR)cbrt_fixed_tables.h +$(SUBDIR)aacdec_fixed.o: $(SUBDIR)sinewin_fixed_tables.h $(SUBDIR)aacps_float.o: $(SUBDIR)aacps_tables.h $(SUBDIR)aacps_fixed.o: $(SUBDIR)aacps_fixed_tables.h -$(SUBDIR)aactab_fixed.o: $(SUBDIR)aac_fixed_tables.h $(SUBDIR)dvenc.o: $(SUBDIR)dv_tables.h $(SUBDIR)motionpixels.o: $(SUBDIR)motionpixels_tables.h +$(SUBDIR)mpegaudiodec_common.o: $(SUBDIR)mpegaudiodec_common_tables.h $(SUBDIR)mpegaudiodec_fixed.o: $(SUBDIR)mpegaudio_tables.h $(SUBDIR)mpegaudiodec_float.o: $(SUBDIR)mpegaudio_tables.h $(SUBDIR)pcm.o: $(SUBDIR)pcm_tables.h $(SUBDIR)qdm2.o: $(SUBDIR)qdm2_tables.h $(SUBDIR)sinewin.o: $(SUBDIR)sinewin_tables.h -$(SUBDIR)sinewin_fixed.o: $(SUBDIR)sinewin_fixed_tables.h endif diff -Nru ffmpeg-4.2.2/libavcodec/mdct15.h ffmpeg-4.4/libavcodec/mdct15.h --- ffmpeg-4.2.2/libavcodec/mdct15.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mdct15.h 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,8 @@ #include +#include "libavutil/mem_internal.h" + #include "fft.h" typedef struct MDCT15Context { diff -Nru ffmpeg-4.2.2/libavcodec/mdct_fixed.c ffmpeg-4.4/libavcodec/mdct_fixed.c --- ffmpeg-4.2.2/libavcodec/mdct_fixed.c 2018-02-19 00:50:32.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mdct_fixed.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +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 - */ - -#define FFT_FLOAT 0 -#define FFT_FIXED_32 0 -#include "mdct_template.c" - -/* same as ff_mdct_calcw_c with double-width unscaled output */ -void ff_mdct_calcw_c(FFTContext *s, FFTDouble *out, const FFTSample *input) -{ - int i, j, n, n8, n4, n2, n3; - FFTDouble re, im; - const uint16_t *revtab = s->revtab; - const FFTSample *tcos = s->tcos; - const FFTSample *tsin = s->tsin; - FFTComplex *x = s->tmp_buf; - FFTDComplex *o = (FFTDComplex *)out; - - n = 1 << s->mdct_bits; - n2 = n >> 1; - n4 = n >> 2; - n8 = n >> 3; - n3 = 3 * n4; - - /* pre rotation */ - for(i=0;ifft_calc(s, x); - - /* post rotation */ - for(i=0;igb, component); - if (diff >= 0xffff) - return AVERROR_INVALIDDATA; a->last_dc[component] += diff; block[0] = a->last_dc[component] * (1 << 3); } @@ -240,17 +240,6 @@ return 0; } -#if HAVE_THREADS -static av_cold int decode_init_thread_copy(AVCodecContext *avctx) -{ - MDECContext * const a = avctx->priv_data; - - a->avctx = avctx; - - return 0; -} -#endif - static av_cold int decode_end(AVCodecContext *avctx) { MDECContext * const a = avctx->priv_data; @@ -271,5 +260,5 @@ .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy) + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/me_cmp.c ffmpeg-4.4/libavcodec/me_cmp.c --- ffmpeg-4.2.2/libavcodec/me_cmp.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/me_cmp.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "libavutil/attributes.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "copy_block.h" #include "simple_idct.h" @@ -1011,31 +1012,8 @@ WRAPPER8_16_SQ(rd8x8_c, rd16_c) WRAPPER8_16_SQ(bit8x8_c, bit16_c) -int ff_check_alignment(void) -{ - static int did_fail = 0; - LOCAL_ALIGNED_16(int, aligned, [4]); - - if ((intptr_t)aligned & 15) { - if (!did_fail) { -#if HAVE_MMX || HAVE_ALTIVEC - av_log(NULL, AV_LOG_ERROR, - "Compiler did not align stack variables. Libavcodec has been miscompiled\n" - "and may be very slow or crash. This is not a bug in libavcodec,\n" - "but in the compiler. You may try recompiling using gcc >= 4.2.\n" - "Do not report crashes to FFmpeg developers.\n"); -#endif - did_fail=1; - } - return -1; - } - return 0; -} - av_cold void ff_me_cmp_init(MECmpContext *c, AVCodecContext *avctx) { - ff_check_alignment(); - c->sum_abs_dctelem = sum_abs_dctelem_c; /* TODO [0] 16 [1] 8 */ diff -Nru ffmpeg-4.2.2/libavcodec/me_cmp.h ffmpeg-4.4/libavcodec/me_cmp.h --- ffmpeg-4.2.2/libavcodec/me_cmp.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/me_cmp.h 2021-04-08 21:28:39.000000000 +0000 @@ -79,8 +79,6 @@ me_cmp_func median_sad[6]; } MECmpContext; -int ff_check_alignment(void); - void ff_me_cmp_init(MECmpContext *c, AVCodecContext *avctx); void ff_me_cmp_init_alpha(MECmpContext *c, AVCodecContext *avctx); void ff_me_cmp_init_arm(MECmpContext *c, AVCodecContext *avctx); diff -Nru ffmpeg-4.2.2/libavcodec/mediacodecdec.c ffmpeg-4.4/libavcodec/mediacodecdec.c --- ffmpeg-4.2.2/libavcodec/mediacodecdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mediacodecdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,7 +34,7 @@ #include "decode.h" #include "h264_parse.h" #include "hevc_parse.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "internal.h" #include "mediacodec_wrapper.h" #include "mediacodecdec_common.h" @@ -167,8 +167,11 @@ ff_AMediaFormat_setBuffer(format, "csd-1", (void*)data, data_size); av_freep(&data); } else { - av_log(avctx, AV_LOG_ERROR, "Could not extract PPS/SPS from extradata"); - ret = AVERROR_INVALIDDATA; + const int warn = is_avc && (avctx->codec_tag == MKTAG('a','v','c','1') || + avctx->codec_tag == MKTAG('a','v','c','2')); + av_log(avctx, warn ? AV_LOG_WARNING : AV_LOG_DEBUG, + "Could not extract PPS/SPS from extradata\n"); + ret = 0; } done: @@ -254,8 +257,10 @@ av_freep(&data); } else { - av_log(avctx, AV_LOG_ERROR, "Could not extract VPS/PPS/SPS from extradata"); - ret = AVERROR_INVALIDDATA; + const int warn = is_nalff && avctx->codec_tag == MKTAG('h','v','c','1'); + av_log(avctx, warn ? AV_LOG_WARNING : AV_LOG_DEBUG, + "Could not extract VPS/PPS/SPS from extradata\n"); + ret = 0; } done: @@ -440,8 +445,13 @@ if (ret >= 0) { s->buffered_pkt.size -= ret; s->buffered_pkt.data += ret; - if (s->buffered_pkt.size <= 0) + if (s->buffered_pkt.size <= 0) { av_packet_unref(&s->buffered_pkt); + } else { + av_log(avctx, AV_LOG_WARNING, + "could not send entire packet in single input buffer (%d < %d)\n", + ret, s->buffered_pkt.size+ret); + } } else if (ret < 0 && ret != AVERROR(EAGAIN)) { return ret; } @@ -481,7 +491,7 @@ ff_mediacodec_dec_flush(avctx, s->ctx); } -static const AVCodecHWConfigInternal *mediacodec_hw_configs[] = { +static const AVCodecHWConfigInternal *const mediacodec_hw_configs[] = { &(const AVCodecHWConfigInternal) { .public = { .pix_fmt = AV_PIX_FMT_MEDIACODEC, diff -Nru ffmpeg-4.2.2/libavcodec/mediacodecdec_common.c ffmpeg-4.4/libavcodec/mediacodecdec_common.c --- ffmpeg-4.2.2/libavcodec/mediacodecdec_common.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mediacodecdec_common.c 2020-07-11 10:39:30.000000000 +0000 @@ -86,6 +86,85 @@ #define OUTPUT_DEQUEUE_BLOCK_TIMEOUT_US 1000000 enum { + COLOR_RANGE_FULL = 0x1, + COLOR_RANGE_LIMITED = 0x2, +}; + +static enum AVColorRange mcdec_get_color_range(int color_range) +{ + switch (color_range) { + case COLOR_RANGE_FULL: + return AVCOL_RANGE_JPEG; + case COLOR_RANGE_LIMITED: + return AVCOL_RANGE_MPEG; + default: + return AVCOL_RANGE_UNSPECIFIED; + } +} + +enum { + COLOR_STANDARD_BT709 = 0x1, + COLOR_STANDARD_BT601_PAL = 0x2, + COLOR_STANDARD_BT601_NTSC = 0x4, + COLOR_STANDARD_BT2020 = 0x6, +}; + +static enum AVColorSpace mcdec_get_color_space(int color_standard) +{ + switch (color_standard) { + case COLOR_STANDARD_BT709: + return AVCOL_SPC_BT709; + case COLOR_STANDARD_BT601_PAL: + return AVCOL_SPC_BT470BG; + case COLOR_STANDARD_BT601_NTSC: + return AVCOL_SPC_SMPTE170M; + case COLOR_STANDARD_BT2020: + return AVCOL_SPC_BT2020_NCL; + default: + return AVCOL_SPC_UNSPECIFIED; + } +} + +static enum AVColorPrimaries mcdec_get_color_pri(int color_standard) +{ + switch (color_standard) { + case COLOR_STANDARD_BT709: + return AVCOL_PRI_BT709; + case COLOR_STANDARD_BT601_PAL: + return AVCOL_PRI_BT470BG; + case COLOR_STANDARD_BT601_NTSC: + return AVCOL_PRI_SMPTE170M; + case COLOR_STANDARD_BT2020: + return AVCOL_PRI_BT2020; + default: + return AVCOL_PRI_UNSPECIFIED; + } +} + +enum { + COLOR_TRANSFER_LINEAR = 0x1, + COLOR_TRANSFER_SDR_VIDEO = 0x3, + COLOR_TRANSFER_ST2084 = 0x6, + COLOR_TRANSFER_HLG = 0x7, +}; + +static enum AVColorTransferCharacteristic mcdec_get_color_trc(int color_transfer) +{ + switch (color_transfer) { + case COLOR_TRANSFER_LINEAR: + return AVCOL_TRC_LINEAR; + case COLOR_TRANSFER_SDR_VIDEO: + return AVCOL_TRC_SMPTE170M; + case COLOR_TRANSFER_ST2084: + return AVCOL_TRC_SMPTEST2084; + case COLOR_TRANSFER_HLG: + return AVCOL_TRC_ARIB_STD_B67; + default: + return AVCOL_TRC_UNSPECIFIED; + } +} + +enum { COLOR_FormatYUV420Planar = 0x13, COLOR_FormatYUV420SemiPlanar = 0x15, COLOR_FormatYCbYCr = 0x19, @@ -220,6 +299,10 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif frame->pkt_dts = AV_NOPTS_VALUE; + frame->color_range = avctx->color_range; + frame->color_primaries = avctx->color_primaries; + frame->color_trc = avctx->color_trc; + frame->colorspace = avctx->colorspace; buffer = av_mallocz(sizeof(AVMediaCodecBuffer)); if (!buffer) { @@ -368,6 +451,9 @@ int ret = 0; int width = 0; int height = 0; + int color_range = 0; + int color_standard = 0; + int color_transfer = 0; char *format = NULL; if (!s->format) { @@ -426,6 +512,20 @@ ff_set_sar(avctx, sar); } + AMEDIAFORMAT_GET_INT32(color_range, "color-range", 0); + if (color_range) + avctx->color_range = mcdec_get_color_range(color_range); + + AMEDIAFORMAT_GET_INT32(color_standard, "color-standard", 0); + if (color_standard) { + avctx->colorspace = mcdec_get_color_space(color_standard); + avctx->color_primaries = mcdec_get_color_pri(color_standard); + } + + AMEDIAFORMAT_GET_INT32(color_transfer, "color-transfer", 0); + if (color_transfer) + avctx->color_trc = mcdec_get_color_trc(color_transfer); + av_log(avctx, AV_LOG_INFO, "Output crop parameters top=%d bottom=%d left=%d right=%d, " "resulting dimensions width=%d height=%d\n", @@ -525,8 +625,8 @@ if (status < 0) { char *desc = ff_AMediaFormat_toString(format); av_log(avctx, AV_LOG_ERROR, - "Failed to configure codec (status = %d) with format %s\n", - status, desc); + "Failed to configure codec %s (status = %d) with format %s\n", + s->codec_name, status, desc); av_freep(&desc); ret = AVERROR_EXTERNAL; @@ -537,8 +637,8 @@ if (status < 0) { char *desc = ff_AMediaFormat_toString(format); av_log(avctx, AV_LOG_ERROR, - "Failed to start codec (status = %d) with format %s\n", - status, desc); + "Failed to start codec %s (status = %d) with format %s\n", + s->codec_name, status, desc); av_freep(&desc); ret = AVERROR_EXTERNAL; goto fail; @@ -569,7 +669,6 @@ int offset = 0; int need_draining = 0; uint8_t *data; - ssize_t index = s->current_input_buffer; size_t size; FFAMediaCodec *codec = s->codec; int status; @@ -591,6 +690,7 @@ } while (offset < pkt->size || (need_draining && !s->draining)) { + ssize_t index = s->current_input_buffer; if (index < 0) { index = ff_AMediaCodec_dequeueInputBuffer(codec, input_dequeue_timeout_us); if (ff_AMediaCodec_infoTryAgainLater(codec, index)) { @@ -612,7 +712,11 @@ } pts = pkt->pts; - if (pts != AV_NOPTS_VALUE && avctx->pkt_timebase.num && avctx->pkt_timebase.den) { + if (pts == AV_NOPTS_VALUE) { + av_log(avctx, AV_LOG_WARNING, "Input packet is missing PTS\n"); + pts = 0; + } + if (pts && avctx->pkt_timebase.num && avctx->pkt_timebase.den) { pts = av_rescale_q(pts, avctx->pkt_timebase, AV_TIME_BASE_Q); } @@ -628,7 +732,7 @@ } av_log(avctx, AV_LOG_TRACE, - "Queued input buffer %zd size=%zd ts=%"PRIi64"\n", index, size, pts); + "Queued empty EOS input buffer %zd with flags=%d\n", index, flags); s->draining = 1; return 0; diff -Nru ffmpeg-4.2.2/libavcodec/mediacodec_surface.c ffmpeg-4.4/libavcodec/mediacodec_surface.c --- ffmpeg-4.2.2/libavcodec/mediacodec_surface.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mediacodec_surface.c 2020-07-11 10:39:30.000000000 +0000 @@ -25,23 +25,19 @@ #include "ffjni.h" #include "mediacodec_surface.h" -void *ff_mediacodec_surface_ref(void *surface, void *log_ctx) +FFANativeWindow *ff_mediacodec_surface_ref(void *surface, void *log_ctx) { JNIEnv *env = NULL; - void *reference = NULL; - env = ff_jni_get_env(log_ctx); if (!env) { return NULL; } - reference = (*env)->NewGlobalRef(env, surface); - - return reference; + return (*env)->NewGlobalRef(env, surface); } -int ff_mediacodec_surface_unref(void *surface, void *log_ctx) +int ff_mediacodec_surface_unref(FFANativeWindow *window, void *log_ctx) { JNIEnv *env = NULL; @@ -50,7 +46,7 @@ return AVERROR_EXTERNAL; } - (*env)->DeleteGlobalRef(env, surface); + (*env)->DeleteGlobalRef(env, window); return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/mediacodec_surface.h ffmpeg-4.4/libavcodec/mediacodec_surface.h --- ffmpeg-4.2.2/libavcodec/mediacodec_surface.h 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mediacodec_surface.h 2020-07-11 10:39:30.000000000 +0000 @@ -25,7 +25,10 @@ #include "libavcodec/avcodec.h" -void *ff_mediacodec_surface_ref(void *surface, void *log_ctx); -int ff_mediacodec_surface_unref(void *surface, void *log_ctx); +struct FFANativeWindow; +typedef struct FFANativeWindow FFANativeWindow; + +FFANativeWindow *ff_mediacodec_surface_ref(void *surface, void *log_ctx); +int ff_mediacodec_surface_unref(FFANativeWindow *window, void *log_ctx); #endif /* AVCODEC_MEDIACODEC_SURFACE_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mediacodec_wrapper.c ffmpeg-4.4/libavcodec/mediacodec_wrapper.c --- ffmpeg-4.2.2/libavcodec/mediacodec_wrapper.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mediacodec_wrapper.c 2021-04-08 21:28:39.000000000 +0000 @@ -45,6 +45,7 @@ jmethodID get_codec_capabilities_id; jmethodID get_supported_types_id; jmethodID is_encoder_id; + jmethodID is_software_only_id; jclass codec_capabilities_class; jfieldID color_formats_id; @@ -81,6 +82,7 @@ { "android/media/MediaCodecInfo", "getCapabilitiesForType", "(Ljava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_capabilities_id), 1 }, { "android/media/MediaCodecInfo", "getSupportedTypes", "()[Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_supported_types_id), 1 }, { "android/media/MediaCodecInfo", "isEncoder", "()Z", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, is_encoder_id), 1 }, + { "android/media/MediaCodecInfo", "isSoftwareOnly", "()Z", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, is_software_only_id), 0 }, { "android/media/MediaCodecInfo$CodecCapabilities", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, codec_capabilities_class), 1 }, { "android/media/MediaCodecInfo$CodecCapabilities", "colorFormats", "[I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, color_formats_id), 1 }, @@ -441,6 +443,41 @@ goto done_with_info; } + if (jfields.is_software_only_id) { + int is_software_only = (*env)->CallBooleanMethod(env, info, jfields.is_software_only_id); + if (ff_jni_exception_check(env, 1, log_ctx) < 0) { + goto done; + } + + if (is_software_only) { + goto done_with_info; + } + } + + codec_name = (*env)->CallObjectMethod(env, info, jfields.get_name_id); + if (ff_jni_exception_check(env, 1, log_ctx) < 0) { + goto done; + } + + name = ff_jni_jstring_to_utf_chars(env, codec_name, log_ctx); + if (!name) { + goto done; + } + + if (codec_name) { + (*env)->DeleteLocalRef(env, codec_name); + codec_name = NULL; + } + + /* Skip software decoders */ + if ( + strstr(name, "OMX.google") || + strstr(name, "OMX.ffmpeg") || + (strstr(name, "OMX.SEC") && strstr(name, ".sw.")) || + !strcmp(name, "OMX.qcom.video.decoder.hevcswvdec")) { + goto done_with_info; + } + type_count = (*env)->GetArrayLength(env, types); for (j = 0; j < type_count; j++) { int k; @@ -456,74 +493,51 @@ goto done; } - if (!av_strcasecmp(supported_type, mime)) { - codec_name = (*env)->CallObjectMethod(env, info, jfields.get_name_id); - if (ff_jni_exception_check(env, 1, log_ctx) < 0) { - goto done; - } + if (av_strcasecmp(supported_type, mime)) { + goto done_with_type; + } - name = ff_jni_jstring_to_utf_chars(env, codec_name, log_ctx); - if (!name) { - goto done; - } + capabilities = (*env)->CallObjectMethod(env, info, jfields.get_codec_capabilities_id, type); + if (ff_jni_exception_check(env, 1, log_ctx) < 0) { + goto done; + } - if (codec_name) { - (*env)->DeleteLocalRef(env, codec_name); - codec_name = NULL; - } + profile_levels = (*env)->GetObjectField(env, capabilities, jfields.profile_levels_id); + if (ff_jni_exception_check(env, 1, log_ctx) < 0) { + goto done; + } - /* Skip software decoders */ - if ( - strstr(name, "OMX.google") || - strstr(name, "OMX.ffmpeg") || - (strstr(name, "OMX.SEC") && strstr(name, ".sw.")) || - !strcmp(name, "OMX.qcom.video.decoder.hevcswvdec")) { - av_freep(&name); - goto done_with_type; + profile_count = (*env)->GetArrayLength(env, profile_levels); + if (!profile_count) { + found_codec = 1; + } + for (k = 0; k < profile_count; k++) { + int supported_profile = 0; + + if (profile < 0) { + found_codec = 1; + break; } - capabilities = (*env)->CallObjectMethod(env, info, jfields.get_codec_capabilities_id, type); + profile_level = (*env)->GetObjectArrayElement(env, profile_levels, k); if (ff_jni_exception_check(env, 1, log_ctx) < 0) { goto done; } - profile_levels = (*env)->GetObjectField(env, capabilities, jfields.profile_levels_id); + supported_profile = (*env)->GetIntField(env, profile_level, jfields.profile_id); if (ff_jni_exception_check(env, 1, log_ctx) < 0) { goto done; } - profile_count = (*env)->GetArrayLength(env, profile_levels); - if (!profile_count) { - found_codec = 1; + found_codec = profile == supported_profile; + + if (profile_level) { + (*env)->DeleteLocalRef(env, profile_level); + profile_level = NULL; } - for (k = 0; k < profile_count; k++) { - int supported_profile = 0; - if (profile < 0) { - found_codec = 1; - break; - } - - profile_level = (*env)->GetObjectArrayElement(env, profile_levels, k); - if (ff_jni_exception_check(env, 1, log_ctx) < 0) { - goto done; - } - - supported_profile = (*env)->GetIntField(env, profile_level, jfields.profile_id); - if (ff_jni_exception_check(env, 1, log_ctx) < 0) { - goto done; - } - - found_codec = profile == supported_profile; - - if (profile_level) { - (*env)->DeleteLocalRef(env, profile_level); - profile_level = NULL; - } - - if (found_codec) { - break; - } + if (found_codec) { + break; } } @@ -548,8 +562,6 @@ if (found_codec) { break; } - - av_freep(&name); } done_with_info: @@ -566,6 +578,8 @@ if (found_codec) { break; } + + av_freep(&name); } done: @@ -1303,6 +1317,12 @@ ret = AVERROR_EXTERNAL; } + (*env)->DeleteGlobalRef(env, codec->input_buffers); + codec->input_buffers = NULL; + + (*env)->DeleteGlobalRef(env, codec->output_buffers); + codec->output_buffers = NULL; + (*env)->DeleteGlobalRef(env, codec->object); codec->object = NULL; diff -Nru ffmpeg-4.2.2/libavcodec/metasound.c ffmpeg-4.4/libavcodec/metasound.c --- ffmpeg-4.2.2/libavcodec/metasound.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/metasound.c 2021-04-08 21:28:39.000000000 +0000 @@ -341,22 +341,16 @@ tctx->mtab = &ff_metasound_mode2224s; break; case (1 << 16) + (44 << 8) + 32: - tctx->mtab = &ff_metasound_mode4432; - break; case (2 << 16) + (44 << 8) + 32: - tctx->mtab = &ff_metasound_mode4432s; + tctx->mtab = &ff_metasound_mode4432; break; case (1 << 16) + (44 << 8) + 40: - tctx->mtab = &ff_metasound_mode4440; - break; case (2 << 16) + (44 << 8) + 40: - tctx->mtab = &ff_metasound_mode4440s; + tctx->mtab = &ff_metasound_mode4440; break; case (1 << 16) + (44 << 8) + 48: - tctx->mtab = &ff_metasound_mode4448; - break; case (2 << 16) + (44 << 8) + 48: - tctx->mtab = &ff_metasound_mode4448s; + tctx->mtab = &ff_metasound_mode4448; break; default: av_log(avctx, AV_LOG_ERROR, @@ -385,7 +379,7 @@ .init = metasound_decode_init, .close = ff_twinvq_decode_close, .decode = ff_twinvq_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff -Nru ffmpeg-4.2.2/libavcodec/metasound_data.c ffmpeg-4.4/libavcodec/metasound_data.c --- ffmpeg-4.2.2/libavcodec/metasound_data.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/metasound_data.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,8 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" #include "metasound_data.h" +#if CONFIG_METASOUND_DECODER static const int16_t cb0806sl0[] = { -417, -225, -84, 16, -106, -34, -246, -164, 112, 48, -47, 36, -65, -68, -172, -1655, @@ -12101,8 +12103,9 @@ -623, -588, 38, -58, 975, 1529, -986, -891, -1121, -619, 1967, -463, -7, 632, 768, 953, }; +#endif /* CONFIG_METASOUND_DECODER */ -static const float lsp8[] = { +const float ff_metasound_lsp8[] = { 0.2702, 0.5096, 0.6437, 0.7672, 0.9639, 1.0696, 1.2625, 1.5789, 1.9285, 2.2383, 2.5129, 2.8470, 0.1740, 0.3677, 0.6082, 0.8387, 1.1084, 1.3721, 1.6362, 1.8733, 2.0640, 2.3442, 2.6087, 2.8548, @@ -12168,240 +12171,7 @@ 0.2217, 0.2632, 0.2706, 0.2624, 0.2162, 0.2453, 0.2460, 0.2531, }; -static const float lsp8s[] = { - 0.2702, 0.5096, 0.6437, 0.7672, 0.9639, 1.0696, 1.2625, 1.5789, - 1.9285, 2.2383, 2.5129, 2.8470, 0.1740, 0.3677, 0.6082, 0.8387, - 1.1084, 1.3721, 1.6362, 1.8733, 2.0640, 2.3442, 2.6087, 2.8548, - 0.1536, 0.3279, 0.5143, 0.6859, 0.9763, 1.2744, 1.5605, 1.8566, - 2.1007, 2.3450, 2.6075, 2.8850, 0.2075, 0.4533, 0.7709, 1.0377, - 1.2953, 1.5132, 1.7826, 2.0351, 2.2590, 2.4996, 2.6795, 2.8748, - 0.1393, 0.2453, 0.3754, 0.5453, 0.8148, 1.1289, 1.4389, 1.7592, - 2.0353, 2.3215, 2.5934, 2.8588, 0.1250, 0.3627, 0.7613, 1.1380, - 1.4163, 1.5565, 1.6920, 1.8130, 1.8678, 2.0427, 2.4318, 2.8544, - 0.2256, 0.4223, 0.6452, 0.8599, 1.0673, 1.3118, 1.5486, 1.8366, - 2.0759, 2.3026, 2.5284, 2.8030, 0.2304, 0.4404, 0.6891, 0.8964, - 1.1510, 1.4202, 1.6483, 1.8580, 2.1181, 2.3686, 2.6078, 2.9128, - 0.2230, 0.3816, 0.5520, 0.6062, 0.7909, 1.0988, 1.4330, 1.7846, - 2.0713, 2.3457, 2.6048, 2.8708, 0.2447, 0.5800, 0.8249, 0.9905, - 1.1721, 1.3990, 1.6694, 1.9064, 2.1307, 2.4255, 2.6815, 2.9117, - 0.1974, 0.3812, 0.5802, 0.7759, 0.9280, 1.1547, 1.4170, 1.6369, - 1.8890, 2.2587, 2.5626, 2.8239, 0.1209, 0.2510, 0.4841, 0.8048, - 1.1197, 1.3563, 1.6073, 1.8926, 2.1350, 2.3669, 2.6291, 2.8985, - 0.2352, 0.4347, 0.6582, 0.8178, 0.9548, 1.1654, 1.4942, 1.8812, - 2.1703, 2.3779, 2.6412, 2.8871, 0.2091, 0.4084, 0.6730, 0.9151, - 1.1259, 1.3262, 1.5937, 1.8129, 2.0237, 2.3317, 2.5778, 2.8620, - 0.1167, 0.2406, 0.4520, 0.7298, 0.9848, 1.2448, 1.5137, 1.7874, - 2.0280, 2.3020, 2.5914, 2.8794, 0.3003, 0.4966, 0.6520, 0.8505, - 1.1600, 1.3981, 1.5805, 1.8346, 2.0757, 2.3102, 2.5760, 2.8499, - 0.2451, 0.4163, 0.5960, 0.7805, 0.9507, 1.2438, 1.5587, 1.8581, - 2.0735, 2.3198, 2.5704, 2.8220, 0.3112, 0.5517, 0.7032, 0.8528, - 1.1489, 1.4257, 1.6848, 1.9388, 2.1577, 2.4265, 2.6678, 2.9051, - 0.2249, 0.3897, 0.5559, 0.7473, 1.0158, 1.3581, 1.6914, 1.9930, - 2.1843, 2.3534, 2.5512, 2.8065, 0.2600, 0.4574, 0.7349, 0.9691, - 1.1696, 1.3848, 1.6335, 1.9021, 2.1174, 2.3481, 2.5902, 2.8390, - 0.2246, 0.3372, 0.4560, 0.5249, 0.7056, 1.0273, 1.3810, 1.7132, - 1.9819, 2.2574, 2.5410, 2.8491, 0.1419, 0.4834, 0.8835, 1.1453, - 1.2839, 1.4224, 1.5593, 1.7877, 2.1285, 2.4070, 2.6043, 2.8511, - 0.1886, 0.3677, 0.5617, 0.8099, 1.1277, 1.3841, 1.5804, 1.8136, - 2.0307, 2.2805, 2.5399, 2.8322, 0.2351, 0.4151, 0.6675, 0.8713, - 1.0464, 1.3292, 1.6586, 1.9281, 2.1355, 2.3495, 2.6222, 2.8782, - 0.2700, 0.4489, 0.6206, 0.7121, 0.7737, 0.9848, 1.3658, 1.7433, - 2.0139, 2.2243, 2.4806, 2.8175, 0.2479, 0.4425, 0.6490, 0.8745, - 1.1161, 1.3849, 1.6773, 1.9566, 2.1491, 2.3624, 2.5685, 2.8114, - 0.2035, 0.3701, 0.5567, 0.7953, 1.0082, 1.2758, 1.5373, 1.7822, - 2.0175, 2.2601, 2.4759, 2.7771, 0.1856, 0.3461, 0.5998, 0.9041, - 1.2383, 1.4612, 1.6667, 1.9305, 2.1617, 2.4107, 2.6477, 2.8656, - 0.2107, 0.3715, 0.5289, 0.6651, 0.8420, 1.1168, 1.4401, 1.7230, - 1.9901, 2.2687, 2.5452, 2.8655, 0.1218, 0.2999, 0.6348, 0.9482, - 1.2745, 1.5876, 1.9129, 2.2348, 2.4020, 2.4922, 2.6351, 2.8357, - 0.1617, 0.3483, 0.5869, 0.8163, 1.0366, 1.2344, 1.4609, 1.7029, - 1.9476, 2.2337, 2.5258, 2.8442, 0.2505, 0.4894, 0.7510, 0.9152, - 1.0845, 1.3657, 1.6528, 1.8346, 2.0160, 2.2811, 2.5338, 2.8136, - 0.0947, 0.1158, 0.0578, -0.0337, -0.0066, 0.0104, -0.0447, -0.0505, - -0.0778, -0.0293, 0.0251, -0.0143, 0.0349, -0.0227, -0.0909, 0.0523, - 0.0325, -0.0410, -0.1045, -0.0899, -0.0009, 0.0075, -0.0575, -0.0855, - -0.0129, 0.0575, 0.0597, 0.0391, 0.0371, -0.0184, -0.0083, 0.0287, - 0.0143, 0.0167, 0.0120, -0.0168, 0.0452, 0.0223, -0.0352, 0.0119, - -0.0496, -0.0965, -0.0661, -0.0072, 0.1099, 0.0843, -0.0087, -0.0478, - -0.0128, -0.0120, -0.0004, 0.0731, 0.1047, 0.0630, 0.0196, -0.0103, - -0.0399, -0.0986, -0.0912, -0.0390, -0.0247, -0.0694, -0.0749, -0.0066, - 0.0223, 0.0634, 0.0343, -0.0134, 0.0727, 0.0241, 0.0066, 0.0437, - 0.0610, 0.0364, 0.0248, -0.0358, -0.0686, -0.0104, 0.0426, 0.0088, - -0.0137, -0.0165, 0.0671, 0.0815, -0.0863, -0.0644, -0.0088, 0.0023, - 0.0482, 0.1174, 0.1270, 0.0594, 0.0165, 0.0949, 0.1098, 0.0137, - 0.4951, 0.4999, 0.4958, 0.4907, 0.4984, 0.4965, 0.4958, 0.4996, - 0.4987, 0.4958, 0.4986, 0.4977, 0.2841, 0.2186, 0.1474, 0.1687, - 0.2217, 0.2632, 0.2706, 0.2624, 0.2162, 0.2453, 0.2460, 0.2531, -}; - -static const float lsp11[] = { - 0.1103, 0.3862, 0.6863, 0.8447, 0.9231, 1.0261, 1.1248, 1.4057, - 1.6621, 1.8010, 1.8692, 2.0704, 2.3490, 2.6060, 2.7539, 2.8977, - 0.1273, 0.2407, 0.3812, 0.6004, 0.7767, 0.9383, 1.1344, 1.3351, - 1.5233, 1.7262, 1.9466, 2.1739, 2.3495, 2.5162, 2.7164, 2.9202, - 0.2010, 0.3330, 0.4488, 0.6465, 0.8046, 0.9889, 1.1479, 1.2964, - 1.4770, 1.6606, 1.8789, 2.1155, 2.3287, 2.5199, 2.7101, 2.9119, - 0.1168, 0.2197, 0.3279, 0.4691, 0.6268, 0.8251, 1.0533, 1.2714, - 1.4712, 1.6762, 1.8831, 2.1114, 2.3230, 2.5297, 2.7365, 2.9270, - 0.1405, 0.3109, 0.4986, 0.6891, 0.8634, 1.0583, 1.2594, 1.4349, - 1.6232, 1.8116, 1.9905, 2.1935, 2.3799, 2.5656, 2.7661, 2.9486, - 0.1703, 0.3057, 0.4403, 0.5225, 0.5969, 0.8110, 1.0729, 1.3215, - 1.5407, 1.7381, 1.9477, 2.1680, 2.3586, 2.5612, 2.7630, 2.9410, - 0.1128, 0.2628, 0.4523, 0.6495, 0.8176, 0.9816, 1.1746, 1.3710, - 1.5568, 1.7518, 1.9497, 2.1452, 2.3346, 2.5389, 2.7362, 2.9264, - 0.1809, 0.3287, 0.5205, 0.7264, 0.9298, 1.1217, 1.2970, 1.4894, - 1.6874, 1.8493, 2.0576, 2.2382, 2.4097, 2.6041, 2.7796, 2.9389, - 0.2502, 0.4709, 0.6892, 0.8346, 0.9209, 1.0455, 1.2399, 1.4616, - 1.6463, 1.8380, 2.0475, 2.2397, 2.4665, 2.6550, 2.7701, 2.8895, - 0.1040, 0.2340, 0.3964, 0.5740, 0.7764, 0.9941, 1.2000, 1.4014, - 1.6024, 1.7974, 1.9939, 2.1959, 2.3783, 2.5663, 2.7613, 2.9484, - 0.1912, 0.3393, 0.4743, 0.6313, 0.8014, 0.9879, 1.1855, 1.3922, - 1.5678, 1.7289, 1.9271, 2.1165, 2.3089, 2.5414, 2.7448, 2.9269, - 0.0965, 0.2025, 0.3398, 0.4990, 0.6934, 0.9386, 1.1730, 1.3766, - 1.5783, 1.7783, 1.9790, 2.1831, 2.3670, 2.5578, 2.7641, 2.9516, - 0.2126, 0.3652, 0.5545, 0.7170, 0.8674, 1.0640, 1.2558, 1.4061, - 1.5904, 1.8095, 1.9760, 2.1505, 2.3549, 2.5575, 2.7023, 2.8877, - 0.1827, 0.3426, 0.4894, 0.6488, 0.7960, 0.9535, 1.1217, 1.2798, - 1.4566, 1.6453, 1.8044, 2.0042, 2.2379, 2.4611, 2.6697, 2.8966, - 0.2034, 0.3822, 0.5231, 0.6960, 0.9200, 1.0394, 1.1616, 1.3772, - 1.5493, 1.7330, 1.9646, 2.1233, 2.3334, 2.5361, 2.7087, 2.9470, - 0.1050, 0.2060, 0.3705, 0.5998, 0.8337, 1.0577, 1.2559, 1.4327, - 1.6334, 1.8165, 1.9853, 2.2058, 2.4063, 2.5818, 2.7625, 2.9458, - 0.1419, 0.4053, 0.6660, 0.8911, 1.0405, 1.1547, 1.2506, 1.3926, - 1.5669, 1.7527, 1.9694, 2.2054, 2.3889, 2.5743, 2.7586, 2.9174, - 0.1514, 0.2825, 0.4309, 0.5772, 0.7470, 0.9703, 1.1462, 1.3316, - 1.5321, 1.7259, 1.9282, 2.1266, 2.3106, 2.5064, 2.7067, 2.9094, - 0.1693, 0.3156, 0.4878, 0.6635, 0.8206, 0.9569, 1.1154, 1.3064, - 1.5109, 1.7184, 1.9179, 2.1036, 2.2763, 2.4820, 2.6949, 2.9105, - 0.1432, 0.2718, 0.4241, 0.5564, 0.6939, 0.9011, 1.1582, 1.3948, - 1.6181, 1.8024, 1.9814, 2.1740, 2.3459, 2.5456, 2.7491, 2.9307, - 0.2294, 0.3857, 0.5590, 0.7434, 0.9189, 1.0941, 1.2740, 1.4456, - 1.6178, 1.7994, 1.9689, 2.1644, 2.3525, 2.5385, 2.7468, 2.9405, - 0.1667, 0.3109, 0.4612, 0.6032, 0.7375, 0.8866, 1.0840, 1.3053, - 1.4982, 1.7044, 1.9146, 2.1117, 2.2942, 2.4983, 2.7084, 2.9132, - 0.1810, 0.3205, 0.4696, 0.6231, 0.7641, 0.9959, 1.2427, 1.4361, - 1.5889, 1.7544, 1.9083, 2.0733, 2.2457, 2.4461, 2.6793, 2.9098, - 0.1164, 0.3753, 0.6068, 0.7503, 1.0100, 1.2131, 1.3793, 1.5302, - 1.6300, 1.7950, 1.9057, 2.1031, 2.3830, 2.5745, 2.6949, 2.8779, - 0.1571, 0.4378, 0.6735, 0.8312, 0.8944, 0.9818, 1.1622, 1.4094, - 1.6423, 1.8066, 1.9258, 2.1838, 2.4363, 2.6279, 2.7358, 2.8790, - 0.1398, 0.2686, 0.4248, 0.6156, 0.7870, 1.0035, 1.2012, 1.3689, - 1.5363, 1.7398, 1.9604, 2.1619, 2.3345, 2.5097, 2.7271, 2.9368, - 0.1913, 0.3338, 0.4987, 0.6446, 0.7852, 1.0163, 1.1886, 1.3610, - 1.5379, 1.7230, 1.8880, 2.0862, 2.2960, 2.4928, 2.7122, 2.9151, - 0.0908, 0.1752, 0.2899, 0.5365, 0.7761, 1.0100, 1.2124, 1.4060, - 1.6019, 1.8010, 1.9774, 2.1905, 2.3733, 2.5623, 2.7660, 2.9565, - 0.1773, 0.3179, 0.4925, 0.6864, 0.8452, 0.9897, 1.1860, 1.3722, - 1.5515, 1.7658, 1.9802, 2.1819, 2.3620, 2.5442, 2.7250, 2.9220, - 0.1286, 0.2341, 0.3689, 0.5364, 0.7176, 0.9350, 1.1083, 1.2943, - 1.4974, 1.7059, 1.9047, 2.1145, 2.3242, 2.5361, 2.7453, 2.9329, - 0.2273, 0.3834, 0.5565, 0.7192, 0.8431, 0.9962, 1.1763, 1.3571, - 1.5774, 1.7419, 1.9202, 2.1131, 2.2919, 2.4898, 2.6895, 2.9180, - 0.1775, 0.3058, 0.4274, 0.6023, 0.8151, 1.0734, 1.3211, 1.5178, - 1.6706, 1.8154, 1.9686, 2.1537, 2.3461, 2.5276, 2.7181, 2.9121, - 0.1653, 0.4304, 0.6361, 0.7824, 0.9183, 1.0452, 1.2071, 1.4077, - 1.6206, 1.8299, 2.0089, 2.1948, 2.3900, 2.5982, 2.7844, 2.9487, - 0.1492, 0.2609, 0.3820, 0.5485, 0.7243, 0.9319, 1.1538, 1.3579, - 1.5266, 1.7002, 1.8873, 2.1016, 2.3175, 2.5221, 2.7241, 2.9243, - 0.2074, 0.3781, 0.5209, 0.6869, 0.8577, 0.9875, 1.1849, 1.3568, - 1.4907, 1.7335, 1.8902, 2.1224, 2.3099, 2.4918, 2.7023, 2.8765, - 0.1359, 0.2254, 0.3286, 0.4432, 0.6586, 0.8964, 1.1125, 1.3523, - 1.5626, 1.7579, 1.9846, 2.1905, 2.3548, 2.5542, 2.7663, 2.9346, - 0.1430, 0.2966, 0.4685, 0.6493, 0.8315, 1.0304, 1.2220, 1.4082, - 1.5995, 1.7888, 1.9774, 2.1737, 2.3607, 2.5577, 2.7558, 2.9405, - 0.1477, 0.2694, 0.4056, 0.5626, 0.7051, 0.8647, 1.0491, 1.2488, - 1.4814, 1.7072, 1.9150, 2.1147, 2.3038, 2.5144, 2.7184, 2.9202, - 0.1690, 0.3033, 0.4580, 0.6686, 0.8536, 1.0293, 1.2124, 1.3998, - 1.5718, 1.7607, 1.9580, 2.1245, 2.2971, 2.4762, 2.6896, 2.9177, - 0.1092, 0.2779, 0.4853, 0.6880, 0.9011, 1.0953, 1.2752, 1.4618, - 1.6623, 1.8484, 2.0264, 2.2152, 2.4017, 2.5835, 2.7671, 2.9436, - 0.1497, 0.3637, 0.6014, 0.8032, 0.9963, 1.1835, 1.3741, 1.5698, - 1.7382, 1.9094, 2.0710, 2.2392, 2.4082, 2.5926, 2.7762, 2.9536, - 0.1434, 0.2492, 0.3966, 0.5934, 0.8033, 1.0657, 1.2796, 1.4276, - 1.5745, 1.7833, 1.9288, 2.1247, 2.3543, 2.5412, 2.7049, 2.8872, - 0.1612, 0.2926, 0.4574, 0.6387, 0.8265, 1.0180, 1.1808, 1.3526, - 1.5564, 1.7536, 1.9187, 2.1192, 2.3149, 2.5006, 2.7101, 2.9217, - 0.0828, 0.1863, 0.3235, 0.5050, 0.7250, 0.9867, 1.2093, 1.3941, - 1.5980, 1.7932, 1.9809, 2.1894, 2.3918, 2.5773, 2.7540, 2.9329, - 0.2001, 0.3655, 0.5290, 0.6761, 0.8027, 0.9972, 1.2090, 1.4255, - 1.6085, 1.7825, 1.9804, 2.1681, 2.3457, 2.5325, 2.7319, 2.9196, - 0.1505, 0.2767, 0.4254, 0.6054, 0.7821, 0.9567, 1.1294, 1.3080, - 1.4984, 1.6954, 1.8666, 2.0736, 2.2875, 2.4969, 2.7072, 2.9163, - 0.1589, 0.4151, 0.5749, 0.6651, 0.8061, 1.0470, 1.2616, 1.3690, - 1.4985, 1.7808, 1.9825, 2.1068, 2.2751, 2.5448, 2.7133, 2.8689, - 0.0916, 0.1846, 0.3788, 0.6329, 0.8774, 1.0687, 1.2653, 1.4561, - 1.6573, 1.8449, 2.0402, 2.2254, 2.3968, 2.5861, 2.7792, 2.9508, - 0.2282, 0.4159, 0.5834, 0.6899, 0.8108, 1.0321, 1.2795, 1.5262, - 1.6936, 1.8469, 2.0922, 2.2607, 2.3795, 2.5301, 2.7386, 2.9530, - 0.1651, 0.3004, 0.4555, 0.6179, 0.7891, 0.9584, 1.1372, 1.3707, - 1.5951, 1.7880, 1.9434, 2.1465, 2.3311, 2.5081, 2.6977, 2.8970, - 0.1279, 0.3828, 0.6330, 0.8323, 0.9652, 1.1175, 1.2319, 1.3511, - 1.5115, 1.6392, 1.7835, 1.9558, 2.2008, 2.4635, 2.6910, 2.9058, - 0.1193, 0.2185, 0.3521, 0.5311, 0.7378, 0.9239, 1.1105, 1.3217, - 1.5362, 1.7504, 1.9536, 2.1627, 2.3560, 2.5506, 2.7548, 2.9453, - 0.1806, 0.3432, 0.4981, 0.6948, 0.8928, 1.0527, 1.2467, 1.4140, - 1.6326, 1.7950, 1.9935, 2.1969, 2.3512, 2.5682, 2.7445, 2.9277, - 0.1846, 0.3112, 0.4568, 0.5891, 0.7317, 0.8493, 1.0204, 1.2022, - 1.3688, 1.6020, 1.8428, 2.0710, 2.2725, 2.4879, 2.7057, 2.9160, - 0.0880, 0.2514, 0.5332, 0.7272, 0.8906, 1.1354, 1.3199, 1.4941, - 1.6010, 1.7151, 1.8712, 2.0643, 2.2755, 2.5375, 2.7054, 2.8891, - 0.1382, 0.2833, 0.4658, 0.6897, 0.9071, 1.0716, 1.2469, 1.4143, - 1.5910, 1.7947, 1.9805, 2.1581, 2.3338, 2.5215, 2.7292, 2.9211, - 0.1061, 0.3494, 0.6327, 0.8570, 0.9748, 1.0560, 1.1529, 1.3250, - 1.6032, 1.8340, 1.9711, 2.1157, 2.3011, 2.5464, 2.8078, 2.9803, - 0.1603, 0.2839, 0.4307, 0.5980, 0.7980, 1.0399, 1.1971, 1.3524, - 1.5715, 1.7838, 1.9468, 2.1498, 2.3627, 2.5514, 2.7327, 2.9148, - 0.1691, 0.3117, 0.4796, 0.6895, 0.8732, 1.0164, 1.1916, 1.3707, - 1.5384, 1.7202, 1.8857, 2.0672, 2.2487, 2.4593, 2.6789, 2.8940, - 0.0965, 0.1702, 0.3191, 0.5721, 0.8100, 1.0241, 1.2272, 1.4196, - 1.6093, 1.8057, 1.9884, 2.2037, 2.3925, 2.5805, 2.7578, 2.9366, - 0.1950, 0.3519, 0.5272, 0.6973, 0.8732, 1.0656, 1.2112, 1.3959, - 1.6116, 1.7821, 1.9445, 2.1592, 2.3348, 2.5142, 2.7440, 2.9297, - 0.1388, 0.2557, 0.4120, 0.5727, 0.7354, 0.9196, 1.0985, 1.2805, - 1.4643, 1.6535, 1.8340, 2.0546, 2.2758, 2.4778, 2.6921, 2.9122, - 0.1823, 0.3336, 0.4957, 0.6771, 0.8563, 1.0137, 1.2299, 1.3849, - 1.5718, 1.7667, 1.9193, 2.1326, 2.3135, 2.5268, 2.7133, 2.8998, - 0.0790, 0.1901, 0.4083, 0.6456, 0.8463, 1.0285, 1.2297, 1.4181, - 1.6159, 1.8056, 1.9971, 2.1912, 2.3816, 2.5746, 2.7692, 2.9497, - 0.0049, 0.0116, 0.0045, 0.0039, -0.0010, -0.0122, -0.0205, -0.0034, - -0.0140, -0.0041, 0.0191, -0.0322, 0.0002, -0.0124, -0.0269, 0.0059, - 0.0586, 0.0339, -0.0389, -0.0319, -0.0079, -0.0205, -0.0363, -0.0211, - 0.0241, 0.0595, 0.0469, 0.0283, 0.0176, -0.0183, -0.0173, -0.0004, - 0.0024, 0.0145, 0.0534, 0.0197, -0.0065, -0.0067, 0.0133, 0.0358, - -0.0104, -0.0386, -0.0109, -0.0078, 0.0275, 0.0565, 0.0251, -0.0027, - -0.0053, 0.0171, 0.0088, 0.0495, 0.0141, 0.0039, -0.0445, -0.0426, - -0.0184, -0.0280, -0.0223, 0.0039, -0.0171, -0.0606, -0.0786, -0.0430, - 0.0544, 0.0595, 0.0320, -0.0012, 0.0108, 0.0185, 0.0066, 0.0408, - 0.0552, -0.0073, -0.0247, -0.0480, -0.0288, 0.0186, 0.0212, -0.0013, - 0.0403, 0.0598, 0.0690, 0.0516, -0.0298, -0.0177, 0.0278, 0.0168, - -0.0106, 0.0251, 0.0386, 0.0331, -0.0052, 0.0133, 0.0291, -0.0158, - -0.0329, -0.0367, 0.0287, 0.0462, -0.0176, 0.0049, 0.0242, -0.0034, - 0.0135, 0.0086, -0.0149, 0.0241, 0.0504, 0.0246, -0.0273, -0.0369, - -0.0108, -0.0449, -0.0625, -0.0414, -0.0292, -0.0571, -0.0440, -0.0088, - 0.0098, 0.0009, -0.0004, 0.0007, -0.0314, -0.0208, -0.0138, -0.0277, - -0.0044, 0.0522, 0.0315, -0.0270, -0.0277, -0.0256, -0.0103, -0.0201, - -0.0287, -0.0279, -0.0182, 0.0472, 0.0613, 0.0450, 0.0413, 0.0333, - 0.0444, 0.0223, 0.0061, 0.0316, 0.0321, 0.0501, 0.0460, 0.0250, - 0.0227, 0.0235, 0.0099, 0.0185, -0.0347, -0.0684, -0.0189, 0.0242, - -0.0190, -0.0273, -0.0012, -0.0253, 0.0293, -0.0231, -0.0219, -0.0010, - 0.0153, 0.0128, -0.0166, -0.0435, -0.0417, -0.0121, -0.0351, -0.0390, - 0.0077, -0.0278, -0.0355, 0.0092, -0.0063, 0.0005, 0.0216, 0.0461, - 0.0538, 0.0451, 0.0298, -0.0130, 0.0058, 0.0206, 0.0471, 0.0499, - 0.0280, 0.0086, -0.0007, -0.0317, 0.0259, 0.0176, 0.0043, 0.0212, - 0.0138, 0.0106, 0.0220, -0.0025, 0.0050, 0.0122, -0.0051, -0.0086, - -0.0472, -0.0005, 0.0193, 0.0032, 0.0246, 0.0222, 0.0090, -0.0320, - -0.0713, -0.0526, -0.0151, -0.0440, -0.0648, -0.0466, -0.0092, 0.0115, - -0.0129, 0.0053, -0.0344, -0.0385, 0.0392, 0.0599, 0.0414, 0.0165, - -0.0098, -0.0320, -0.0261, -0.0055, -0.0139, -0.0110, 0.0084, 0.0172, - -0.0492, -0.0537, -0.0320, -0.0036, 0.0265, 0.0385, 0.0064, -0.0280, - -0.0230, 0.0134, 0.0241, 0.0106, 0.0387, 0.0105, 0.0068, 0.0260, - 0.4940, 0.4911, 0.4849, 0.4820, 0.4837, 0.4839, 0.4824, 0.4799, - 0.4812, 0.4782, 0.4788, 0.4711, 0.4706, 0.4671, 0.4601, 0.4578, - 0.2954, 0.2121, 0.1859, 0.1958, 0.1474, 0.1086, 0.1351, 0.1362, - 0.1486, 0.1342, 0.1215, 0.1423, 0.1634, 0.1588, 0.1539, 0.1857, -}; - -static const float lsp11s[] = { +const float ff_metasound_lsp11[] = { 0.1103, 0.3862, 0.6863, 0.8447, 0.9231, 1.0261, 1.1248, 1.4057, 1.6621, 1.8010, 1.8692, 2.0704, 2.3490, 2.6060, 2.7539, 2.8977, 0.1273, 0.2407, 0.3812, 0.6004, 0.7767, 0.9383, 1.1344, 1.3351, @@ -12568,7 +12338,7 @@ 0.1486, 0.1342, 0.1215, 0.1423, 0.1634, 0.1588, 0.1539, 0.1857, }; -static const float lsp16[] = { +const float ff_metasound_lsp16[] = { 0.1813, 0.3911, 0.6301, 0.8012, 1.0057, 1.2041, 1.4271, 1.6943, 1.9402, 2.1733, 2.3521, 2.4989, 2.5839, 2.6846, 2.7634, 2.8950, 0.1311, 0.3183, 0.4659, 0.5601, 0.6658, 0.7828, 1.0065, 1.2717, @@ -12747,7 +12517,7 @@ -0.0429, -0.0615, -0.0893, -0.0618, -0.0384, -0.0134, -0.0232, -0.0238, }; -static const float lsp22[] = { +const float ff_metasound_lsp22[] = { 0.0664, 0.1875, 0.4300, 0.6730, 0.8793, 1.0640, 1.2563, 1.4433, 1.6394, 1.8176, 2.0029, 2.1921, 2.3796, 2.5671, 2.7595, 2.9536, 0.2128, 0.4052, 0.5311, 0.6404, 0.7875, 0.8775, 1.0974, 1.3261, @@ -12914,174 +12684,7 @@ 0.4239, 0.4331, 0.4522, 0.4423, 0.4475, 0.4387, 0.4525, 0.4446, }; -static const float lsp22s[] = { - 0.0664, 0.1875, 0.4300, 0.6730, 0.8793, 1.0640, 1.2563, 1.4433, - 1.6394, 1.8176, 2.0029, 2.1921, 2.3796, 2.5671, 2.7595, 2.9536, - 0.2128, 0.4052, 0.5311, 0.6404, 0.7875, 0.8775, 1.0974, 1.3261, - 1.5563, 1.6790, 1.8339, 2.1195, 2.3226, 2.4609, 2.6440, 2.8947, - 0.2024, 0.3362, 0.4834, 0.6784, 0.9088, 1.0850, 1.2188, 1.4054, - 1.6102, 1.7767, 1.9679, 2.1436, 2.3445, 2.5467, 2.7429, 2.9320, - 0.1181, 0.2279, 0.4413, 0.6114, 0.7710, 0.9427, 1.1142, 1.2707, - 1.4892, 1.7416, 1.9526, 2.1466, 2.3629, 2.5445, 2.7293, 2.9205, - 0.1155, 0.2720, 0.4886, 0.6812, 0.8594, 1.0422, 1.2315, 1.4116, - 1.6137, 1.8020, 1.9758, 2.1743, 2.3602, 2.5568, 2.7472, 2.9374, - 0.1110, 0.3312, 0.4735, 0.5612, 0.7129, 0.8146, 1.0233, 1.3155, - 1.5765, 1.7746, 1.9574, 2.1416, 2.3220, 2.5384, 2.7334, 2.9318, - 0.1656, 0.3350, 0.4215, 0.5609, 0.6759, 0.8503, 1.1405, 1.4094, - 1.6057, 1.6860, 1.7639, 2.0031, 2.2680, 2.5076, 2.7263, 2.9368, - 0.1466, 0.3638, 0.4587, 0.5674, 0.7381, 0.8669, 0.9619, 1.1658, - 1.4667, 1.7440, 1.9335, 2.1018, 2.3022, 2.5281, 2.7359, 2.9261, - 0.1061, 0.2566, 0.4739, 0.6751, 0.8711, 1.0704, 1.2720, 1.4655, - 1.6605, 1.8494, 2.0290, 2.2197, 2.4008, 2.5912, 2.7772, 2.9513, - 0.1116, 0.2364, 0.3971, 0.6316, 0.8583, 1.0335, 1.1686, 1.3302, - 1.5612, 1.7877, 1.9829, 2.2052, 2.3596, 2.5460, 2.7341, 2.9290, - 0.2661, 0.4186, 0.5126, 0.6477, 0.8818, 1.1045, 1.2852, 1.4128, - 1.5851, 1.7593, 1.9399, 2.1757, 2.3684, 2.5136, 2.6927, 2.9064, - 0.1495, 0.2749, 0.4391, 0.6304, 0.8239, 1.0181, 1.1995, 1.3759, - 1.5669, 1.7722, 1.9671, 2.1635, 2.3586, 2.5528, 2.7445, 2.9311, - 0.0912, 0.1759, 0.3066, 0.5660, 0.8005, 0.9568, 1.1832, 1.4504, - 1.6259, 1.7948, 2.0113, 2.2002, 2.3654, 2.5583, 2.7929, 2.9735, - 0.1353, 0.2747, 0.4078, 0.5977, 0.7658, 0.9124, 1.1081, 1.3630, - 1.5875, 1.7847, 1.9323, 2.1181, 2.3321, 2.5046, 2.7183, 2.9225, - 0.1938, 0.4063, 0.4982, 0.6002, 0.7702, 0.9071, 1.1631, 1.3885, - 1.6043, 1.8118, 1.9306, 2.0893, 2.2724, 2.4609, 2.6283, 2.8802, - 0.1857, 0.3351, 0.4381, 0.6101, 0.7561, 0.8555, 1.0384, 1.3171, - 1.5667, 1.6904, 1.7552, 1.9689, 2.2597, 2.5260, 2.7272, 2.9337, - 0.1037, 0.2159, 0.4188, 0.6174, 0.8035, 1.0285, 1.2256, 1.4230, - 1.6400, 1.8322, 2.0144, 2.1988, 2.3810, 2.5682, 2.7613, 2.9438, - 0.1625, 0.2776, 0.4225, 0.6001, 0.7879, 0.9087, 1.0801, 1.2759, - 1.4899, 1.7448, 1.9911, 2.1770, 2.3723, 2.5777, 2.7971, 2.9444, - 0.2111, 0.3640, 0.5839, 0.7290, 0.8051, 1.0023, 1.2315, 1.4143, - 1.5878, 1.7755, 1.9804, 2.1498, 2.3312, 2.5350, 2.7613, 2.9472, - 0.1423, 0.2646, 0.4136, 0.6350, 0.8070, 0.9514, 1.1168, 1.3213, - 1.5776, 1.7721, 1.9404, 2.1545, 2.3385, 2.5137, 2.7396, 2.9553, - 0.1132, 0.2386, 0.4103, 0.5931, 0.7808, 0.9881, 1.1840, 1.3860, - 1.6021, 1.7990, 1.9922, 2.1885, 2.3852, 2.5717, 2.7640, 2.9510, - 0.1267, 0.2602, 0.3913, 0.5944, 0.7598, 0.9198, 1.0781, 1.2715, - 1.5299, 1.7573, 1.9308, 2.1346, 2.3267, 2.5419, 2.7466, 2.9320, - 0.2023, 0.3417, 0.4392, 0.6141, 0.7439, 0.8593, 1.1096, 1.3543, - 1.5185, 1.6553, 1.7862, 2.0341, 2.2718, 2.4834, 2.7103, 2.9466, - 0.1113, 0.2470, 0.3677, 0.5686, 0.7700, 0.9356, 1.0806, 1.2452, - 1.4830, 1.7344, 1.9268, 2.1404, 2.3371, 2.5169, 2.7329, 2.9012, - 0.1664, 0.3554, 0.5573, 0.7471, 0.9245, 1.0998, 1.2787, 1.4655, - 1.6654, 1.8346, 2.0179, 2.2159, 2.4096, 2.5946, 2.7790, 2.9530, - 0.1313, 0.2625, 0.4731, 0.6444, 0.8110, 0.9878, 1.1493, 1.3212, - 1.5719, 1.8138, 1.9861, 2.1943, 2.3714, 2.5578, 2.7346, 2.9296, - 0.1186, 0.3035, 0.5049, 0.6860, 0.8670, 0.9975, 1.1364, 1.3471, - 1.5695, 1.7412, 1.9346, 2.1506, 2.3413, 2.5531, 2.7794, 2.9627, - 0.1108, 0.2697, 0.4787, 0.6344, 0.7909, 0.9586, 1.1440, 1.3511, - 1.5686, 1.7601, 1.9246, 2.1241, 2.3293, 2.5390, 2.7315, 2.9333, - 0.0985, 0.2302, 0.3544, 0.5759, 0.7620, 0.9651, 1.1497, 1.3080, - 1.5500, 1.7845, 1.9518, 2.1734, 2.3565, 2.5665, 2.7605, 2.9102, - 0.1208, 0.2727, 0.4381, 0.5736, 0.7382, 0.8390, 1.0102, 1.2648, - 1.5100, 1.7440, 1.9619, 2.1430, 2.3307, 2.5159, 2.7264, 2.9211, - 0.1582, 0.2777, 0.4475, 0.6551, 0.8591, 1.0084, 1.1414, 1.3291, - 1.5902, 1.7826, 1.9543, 2.1659, 2.3233, 2.5044, 2.6935, 2.9199, - 0.1360, 0.2873, 0.4585, 0.6295, 0.7592, 0.9089, 1.0492, 1.2733, - 1.5391, 1.7768, 1.9372, 2.1329, 2.3168, 2.5015, 2.6857, 2.8837, - 0.0886, 0.1829, 0.3696, 0.6126, 0.8334, 1.0135, 1.2303, 1.4674, - 1.6743, 1.8564, 2.0530, 2.2370, 2.3960, 2.5787, 2.7756, 2.9377, - 0.2005, 0.3537, 0.4700, 0.6249, 0.7385, 0.9097, 1.1759, 1.3811, - 1.5314, 1.6705, 1.8546, 2.1229, 2.3292, 2.5251, 2.7951, 2.9646, - 0.1999, 0.3112, 0.4722, 0.7146, 0.8908, 1.0028, 1.1831, 1.3903, - 1.6125, 1.7514, 1.9083, 2.1248, 2.3271, 2.5339, 2.6945, 2.8918, - 0.1243, 0.2606, 0.4382, 0.5850, 0.7705, 0.9727, 1.1214, 1.3059, - 1.5218, 1.7406, 1.9137, 2.1353, 2.3354, 2.5299, 2.7287, 2.9068, - 0.1039, 0.2426, 0.4265, 0.6284, 0.8152, 0.9941, 1.2004, 1.4038, - 1.5912, 1.7763, 1.9650, 2.1598, 2.3474, 2.5488, 2.7419, 2.9322, - 0.1364, 0.2420, 0.3886, 0.5864, 0.7663, 0.8844, 1.0860, 1.3242, - 1.5518, 1.7893, 2.0004, 2.1562, 2.3619, 2.5516, 2.7687, 2.9181, - 0.1483, 0.2851, 0.4479, 0.6312, 0.7924, 0.9821, 1.1705, 1.3386, - 1.5375, 1.7226, 1.9053, 2.0991, 2.2898, 2.4953, 2.7000, 2.9146, - 0.2332, 0.4561, 0.5407, 0.6212, 0.7524, 0.8215, 0.9522, 1.1685, - 1.5216, 1.7132, 1.8291, 2.0647, 2.2811, 2.4857, 2.7071, 2.9281, - 0.1348, 0.3126, 0.5179, 0.7192, 0.9227, 1.1363, 1.3223, 1.4756, - 1.6509, 1.8191, 1.9991, 2.1976, 2.3877, 2.5768, 2.7590, 2.9386, - 0.1093, 0.2211, 0.4763, 0.6703, 0.8282, 0.9536, 1.1202, 1.3796, - 1.6043, 1.8031, 1.9832, 2.1604, 2.3578, 2.5856, 2.7650, 2.9291, - 0.1865, 0.3027, 0.4580, 0.6719, 0.8400, 1.0082, 1.1901, 1.3782, - 1.5448, 1.6885, 1.9477, 2.1381, 2.2797, 2.5113, 2.7465, 2.9414, - 0.1575, 0.3124, 0.4649, 0.6262, 0.8095, 0.9858, 1.1676, 1.3602, - 1.5646, 1.7582, 1.9550, 2.1671, 2.3628, 2.5734, 2.7670, 2.9519, - 0.1174, 0.2777, 0.4663, 0.6333, 0.8169, 1.0096, 1.1885, 1.3847, - 1.5803, 1.7571, 1.9380, 2.1398, 2.3414, 2.5407, 2.7360, 2.9375, - 0.1073, 0.2264, 0.4083, 0.5973, 0.7474, 0.9514, 1.1349, 1.3337, - 1.5433, 1.7348, 1.9380, 2.1436, 2.3441, 2.5438, 2.7457, 2.9383, - 0.1472, 0.2880, 0.4793, 0.6268, 0.8015, 1.0063, 1.1715, 1.3644, - 1.5525, 1.7410, 1.9258, 2.1227, 2.3214, 2.5149, 2.7148, 2.9196, - 0.1414, 0.2565, 0.4349, 0.6111, 0.7695, 0.9496, 1.1212, 1.3265, - 1.5218, 1.7209, 1.9015, 2.0887, 2.3158, 2.5077, 2.7233, 2.9421, - 0.1252, 0.2667, 0.4454, 0.6431, 0.8371, 1.0124, 1.2110, 1.4160, - 1.6240, 1.8242, 2.0047, 2.1974, 2.3902, 2.5778, 2.7637, 2.9481, - 0.1321, 0.2565, 0.3846, 0.5847, 0.7578, 0.9259, 1.0637, 1.2239, - 1.4690, 1.7346, 1.9750, 2.1882, 2.3712, 2.5509, 2.7280, 2.8885, - 0.1437, 0.2930, 0.4428, 0.6156, 0.8045, 0.9638, 1.1450, 1.3138, - 1.5144, 1.7355, 1.9469, 2.1534, 2.3414, 2.5452, 2.7353, 2.9334, - 0.1692, 0.2770, 0.3831, 0.6100, 0.7825, 0.9302, 1.0690, 1.2481, - 1.4615, 1.6799, 1.9165, 2.1739, 2.3435, 2.5349, 2.7520, 2.9163, - 0.1235, 0.2489, 0.4354, 0.6343, 0.8236, 1.0066, 1.1908, 1.3474, - 1.5656, 1.8275, 2.0620, 2.2548, 2.4135, 2.5913, 2.7639, 2.9334, - 0.1090, 0.1961, 0.3854, 0.5701, 0.7024, 0.8843, 1.1393, 1.3785, - 1.5940, 1.7797, 1.9442, 2.1740, 2.3853, 2.5773, 2.7727, 2.9406, - 0.1560, 0.3477, 0.5011, 0.6287, 0.7612, 0.9896, 1.1510, 1.3420, - 1.5435, 1.6816, 1.8731, 2.0651, 2.2613, 2.4999, 2.7027, 2.8971, - 0.1459, 0.2416, 0.3833, 0.5450, 0.7916, 0.9223, 1.0662, 1.1953, - 1.4029, 1.6616, 1.9320, 2.1459, 2.3386, 2.5081, 2.6799, 2.9195, - 0.1546, 0.3854, 0.6184, 0.8460, 1.0599, 1.2428, 1.3906, 1.5550, - 1.7388, 1.8945, 2.0757, 2.2386, 2.4014, 2.5705, 2.7574, 2.9400, - 0.1080, 0.2307, 0.4112, 0.6067, 0.7725, 0.9467, 1.1285, 1.3205, - 1.5348, 1.7609, 1.9937, 2.1878, 2.3583, 2.5515, 2.7199, 2.9049, - 0.1482, 0.3178, 0.4983, 0.6342, 0.7783, 0.9880, 1.2019, 1.3404, - 1.5223, 1.7296, 1.9211, 2.0943, 2.2928, 2.5008, 2.7136, 2.9224, - 0.1145, 0.2910, 0.4891, 0.6492, 0.8126, 0.9530, 1.1180, 1.3155, - 1.5054, 1.6893, 1.8899, 2.1188, 2.3389, 2.5512, 2.7313, 2.9224, - 0.0939, 0.1689, 0.3250, 0.5792, 0.7698, 0.9245, 1.1574, 1.3865, - 1.5959, 1.7977, 1.9821, 2.1528, 2.3326, 2.5540, 2.7553, 2.9179, - 0.1243, 0.2474, 0.3923, 0.6199, 0.7908, 0.9379, 1.1497, 1.3734, - 1.5582, 1.7420, 1.9539, 2.1385, 2.3240, 2.5277, 2.7311, 2.9178, - 0.1961, 0.3748, 0.5176, 0.6387, 0.8169, 1.0477, 1.2124, 1.3869, - 1.5604, 1.7225, 1.8770, 2.0837, 2.2960, 2.5103, 2.6945, 2.8862, - 0.1295, 0.2403, 0.4149, 0.6189, 0.7913, 0.9130, 1.0832, 1.2787, - 1.4860, 1.7112, 1.9502, 2.1348, 2.2776, 2.4982, 2.7431, 2.9522, - 0.0160, 0.0362, 0.0097, 0.0057, -0.0014, -0.0073, -0.0046, -0.0064, - -0.0121, 0.0019, 0.0149, -0.0440, -0.0479, -0.0382, -0.0480, -0.0182, - 0.0170, 0.0114, -0.0298, -0.0175, -0.0033, -0.0354, -0.0510, -0.0025, - 0.0307, 0.0351, 0.0338, 0.0420, 0.0138, -0.0175, -0.0102, 0.0053, - 0.0084, -0.0003, 0.0412, -0.0027, 0.0145, -0.0039, 0.0083, 0.0400, - 0.0001, -0.0262, 0.0055, -0.0082, 0.0348, 0.0433, 0.0137, -0.0024, - -0.0055, 0.0262, 0.0521, 0.0349, 0.0185, 0.0076, -0.0319, -0.0561, - -0.0460, -0.0253, -0.0097, 0.0163, 0.0184, -0.0037, -0.0480, -0.0371, - 0.0628, 0.0665, 0.0296, -0.0057, 0.0253, 0.0227, 0.0350, 0.0692, - 0.0545, 0.0218, 0.0094, -0.0449, -0.0372, 0.0005, 0.0258, 0.0118, - 0.0285, 0.0760, 0.0822, 0.0527, -0.0299, -0.0049, 0.0170, 0.0195, - 0.0136, 0.0286, 0.0289, 0.0139, 0.0054, 0.0152, 0.0244, 0.0028, - -0.0056, -0.0260, 0.0307, 0.0572, -0.0087, 0.0088, 0.0062, 0.0000, - 0.0125, 0.0000, -0.0292, 0.0820, 0.0872, 0.0646, 0.0346, 0.0076, - -0.0022, -0.0253, -0.0567, -0.0188, -0.0336, -0.0673, -0.0549, -0.0166, - -0.0259, -0.0140, 0.0040, -0.0029, -0.0430, -0.0531, -0.0253, -0.0019, - -0.0071, 0.0393, 0.0072, -0.0327, -0.0236, -0.0235, -0.0177, -0.0186, - -0.0280, -0.0201, -0.0077, 0.0383, 0.0418, 0.0321, 0.0294, 0.0169, - 0.0468, 0.0301, 0.0133, 0.0363, 0.0516, 0.0937, 0.1240, 0.1404, - 0.1325, 0.1178, 0.0999, 0.0251, -0.0037, -0.0495, -0.0703, -0.0219, - -0.0261, -0.0304, -0.0204, -0.0372, 0.0355, 0.0131, -0.0093, -0.0099, - -0.0069, -0.0034, -0.0065, -0.0208, -0.0231, -0.0117, -0.0211, -0.0243, - 0.0046, -0.0107, -0.0070, 0.0123, 0.0230, 0.0152, 0.0164, 0.0412, - 0.0619, 0.0858, 0.0862, -0.0056, 0.0125, 0.0182, 0.0347, 0.0388, - 0.0456, 0.0407, -0.0249, -0.0460, 0.0206, 0.0299, 0.0253, 0.0207, - 0.0177, 0.0238, 0.0253, 0.0030, 0.0042, 0.0020, -0.0081, -0.0136, - -0.0290, -0.0042, 0.0122, 0.0051, 0.0107, 0.0228, 0.0211, -0.0068, - -0.0436, -0.0299, -0.0078, -0.0779, -0.1157, -0.0679, 0.0172, 0.0150, - -0.0051, 0.0081, -0.0512, -0.0616, 0.0576, 0.0799, 0.0803, 0.0336, - 0.0001, -0.0298, -0.0747, -0.0115, -0.0101, -0.0170, -0.0050, 0.0174, - -0.0290, -0.0601, -0.0150, 0.0121, 0.0165, 0.0230, 0.0028, -0.0317, - -0.0165, 0.0356, 0.0451, 0.0120, 0.0321, 0.0084, -0.0058, 0.0122, - 0.1935, 0.1802, 0.2195, 0.2410, 0.2201, 0.1915, 0.1840, 0.1935, - 0.2213, 0.2079, 0.1858, 0.1974, 0.2239, 0.2173, 0.1840, 0.2120, - 0.4912, 0.4777, 0.4607, 0.4395, 0.4426, 0.4388, 0.4416, 0.4345, - 0.4239, 0.4331, 0.4522, 0.4423, 0.4475, 0.4387, 0.4525, 0.4446, -}; - -static const float lsp44s[] = { +const float ff_metasound_lsp44[] = { 0.0927, 0.2291, 0.4059, 0.5779, 0.7288, 0.8821, 1.0377, 1.1915, 1.3433, 1.4931, 1.6475, 1.7989, 1.9381, 2.0858, 2.2321, 2.3765, 2.5187, 2.6530, 2.7895, 2.9354, 0.0944, 0.1974, 0.3046, 0.4714, @@ -13289,6 +12892,7 @@ 0.1897, 0.1772, 0.1651, 0.1247, 0.1041, 0.1231, 0.1809, 0.2234, }; +#if CONFIG_METASOUND_DECODER static const int16_t shape8[] = { 2765, 1262, 6624, 867, 688, 1884, 3245, 1248, -2160, 593, 182, -1004, -1067, 687, 1021, -920, @@ -14971,17 +14575,6 @@ 29, 36, 45, 60, 80, 113, 173, 302, }; -static const uint16_t bark_tab_s22_128[] = { - 1, 2, 1, 2, 3, 4, 6, 10, - 23, 76, -}; - -static const uint16_t bark_tab_m22_512[] = { - 3, 2, 3, 3, 3, 4, 3, 5, - 4, 6, 7, 8, 10, 14, 18, 25, - 36, 55, 95, 208, -}; - static const uint16_t bark_tab_l22s_1024[] = { 6, 7, 6, 6, 7, 7, 7, 7, 7, 8, 9, 8, 10, 10, 11, 12, @@ -15006,11 +14599,13 @@ 64, 79, 98, 123, 161, 220, 320, 512, }; +#define bark_tab_m22_512 bark_tab_m44_512 /* Both tables are identical */ static const uint16_t bark_tab_m44_512[] = { 3, 2, 3, 3, 3, 4, 3, 5, 4, 6, 7, 8, 10, 14, 18, 25, 36, 55, 95, 208, }; +#define bark_tab_s22_128 bark_tab_s44_128 /* Both tables are identical */ static const uint16_t bark_tab_s44_128[] = { 1, 2, 1, 2, 3, 4, 6, 10, 23, 76 }; @@ -15021,7 +14616,7 @@ { 2, bark_tab_m8_256, 20, fcb8m, 2, 5, cb0806sm0, cb0806sm1, 22 }, { 1, bark_tab_l8_512, 30, fcb8l, 3, 6, cb0806sl0, cb0806sl1, 24 } }, - 512, 12, lsp8, 1, 5, 3, 3, shape8, 8, 28, 20, 6, 200 + 512, 12, ff_metasound_lsp8, 1, 5, 3, 3, shape8, 8, 28, 20, 6, 200 }; const TwinVQModeTab ff_metasound_mode0806s = { @@ -15030,7 +14625,7 @@ { 2, bark_tab_m8s_256, 20, fcb8sm, 2, 5, cb0806sm0, cb0806sm1, 22 }, { 1, bark_tab_l8s_512, 30, fcb8sl, 3, 6, cb0806sl0, cb0806sl1, 24 } }, - 512, 12, lsp8s, 1, 5, 3, 3, shape8s, 8, 28, 20, 6, 200 + 512, 12, ff_metasound_lsp8, 1, 5, 3, 3, shape8s, 8, 28, 20, 6, 200 }; const TwinVQModeTab ff_metasound_mode0808 = { @@ -15039,7 +14634,7 @@ { 2, bark_tab_m8_256, 20, fcb8m, 2, 5, cb0808m0, cb0808m1, 16 }, { 1, bark_tab_l8_512, 30, fcb8l, 3, 6, cb0808l0, cb0808l1, 17 } }, - 512, 12, lsp8, 1, 5, 3, 3, shape8, 8, 28, 20, 6, 200 + 512, 12, ff_metasound_lsp8, 1, 5, 3, 3, shape8, 8, 28, 20, 6, 200 }; const TwinVQModeTab ff_metasound_mode0808s = { @@ -15048,7 +14643,7 @@ { 2, bark_tab_m8s_256, 20, fcb8sm, 2, 5, cb0808sm0, cb0808sm1, 16 }, { 1, bark_tab_l8s_512, 30, fcb8sl, 3, 6, cb0808sl0, cb0808sl1, 17 } }, - 512, 12, lsp8s, 1, 5, 3, 3, shape8s, 8, 28, 20, 6, 200 + 512, 12, ff_metasound_lsp8, 1, 5, 3, 3, shape8s, 8, 28, 20, 6, 200 }; const TwinVQModeTab ff_metasound_mode1110 = { @@ -15057,7 +14652,7 @@ { 2, bark_tab_m11_256, 16, fcb11m, 2, 5, cb1110m0, cb1110m1, 18 }, { 1, bark_tab_l11_512, 24, fcb11l, 3, 6, cb1110l0, cb1110l1, 19 } }, - 512, 16, lsp11, 1, 6, 4, 3, shape11, 9, 28, 20, 7, 200 + 512, 16, ff_metasound_lsp11, 1, 6, 4, 3, shape11, 9, 28, 20, 7, 200 }; const TwinVQModeTab ff_metasound_mode1110s = { @@ -15066,7 +14661,7 @@ { 2, bark_tab_m11s_256, 20, fcb11sm, 2, 5, cb1110sm0, cb1110sm1, 18 }, { 1, bark_tab_l11s_512, 30, fcb11sl, 3, 6, cb1110sl0, cb1110sl1, 20 } }, - 512, 16, lsp11s, 1, 6, 4, 3, shape11s, 9, 36, 30, 7, 200 + 512, 16, ff_metasound_lsp11, 1, 6, 4, 3, shape11s, 9, 36, 30, 7, 200 }; const TwinVQModeTab ff_metasound_mode1616 = { @@ -15075,7 +14670,7 @@ { 2, bark_tab_m16_512, 24, fcb16m, 2, 5, cb1616m0, cb1616m1, 15 }, { 1, bark_tab_l16_1024, 30, fcb16l, 3, 6, cb1616l0, cb1616l1, 16 } }, - 1024, 16, lsp16, 1, 6, 4, 3, shape16, 9, 28, 30, 7, 200 + 1024, 16, ff_metasound_lsp16, 1, 6, 4, 3, shape16, 9, 28, 30, 7, 200 }; const TwinVQModeTab ff_metasound_mode1616s = { @@ -15084,7 +14679,7 @@ { 2, bark_tab_m16s_512, 20, fcb16sm, 2, 5, cb1616sm0, cb1616sm1, 15 }, { 1, bark_tab_l16s_1024, 30, fcb16sl, 3, 6, cb1616sl0, cb1616sl1, 16 } }, - 1024, 16, lsp16, 1, 6, 4, 3, shape16s, 9, 56, 60, 7, 200 + 1024, 16, ff_metasound_lsp16, 1, 6, 4, 3, shape16s, 9, 56, 60, 7, 200 }; const TwinVQModeTab ff_metasound_mode2224 = { @@ -15093,7 +14688,7 @@ { 2, bark_tab_m22_512, 20, fcb22m, 2, 6, cb2224m0, cb2224m1, 14 }, { 1, bark_tab_l22_1024, 32, fcb22l, 4, 6, cb2224l0, cb2224l1, 15 } }, - 1024, 16, lsp22, 1, 6, 4, 3, shape22, 9, 56, 36, 7, 200 + 1024, 16, ff_metasound_lsp22, 1, 6, 4, 3, shape22, 9, 56, 36, 7, 200 }; const TwinVQModeTab ff_metasound_mode2224s = { @@ -15102,7 +14697,7 @@ { 2, bark_tab_m22s_512, 20, fcb22sm, 2, 6, cb2224sm0, cb2224sm1, 14 }, { 1, bark_tab_l22s_1024, 32, fcb22sl, 4, 6, cb2224sl0, cb2224sl1, 15 } }, - 1024, 16, lsp22s, 1, 6, 4, 3, shape22s, 9, 56, 36, 7, 200 + 1024, 16, ff_metasound_lsp22, 1, 6, 4, 3, shape22s, 9, 56, 36, 7, 200 }; const TwinVQModeTab ff_metasound_mode4432 = { @@ -15111,16 +14706,7 @@ { 4, bark_tab_m44_512, 20, fcb44sm, 2, 6, cb4432m0, cb4432m1, 21 }, { 1, bark_tab_l44_2048, 40, fcb44sl, 4, 6, cb4432l0, cb4432l1, 22 } }, - 2048, 20, lsp44s, 1, 6, 4, 4, shape44s, 9, 84, 54, 7, 200, -}; - -const TwinVQModeTab ff_metasound_mode4432s = { - { - { 16, bark_tab_s44_128, 10, fcb44ss, 1, 6, cb4432s0, cb4432s1, 23 }, - { 4, bark_tab_m44_512, 20, fcb44sm, 2, 6, cb4432m0, cb4432m1, 21 }, - { 1, bark_tab_l44_2048, 40, fcb44sl, 4, 6, cb4432l0, cb4432l1, 22 } - }, - 2048, 20, lsp44s, 1, 6, 4, 4, shape44s, 9, 84, 54, 7, 200, + 2048, 20, ff_metasound_lsp44, 1, 6, 4, 4, shape44s, 9, 84, 54, 7, 200, }; const TwinVQModeTab ff_metasound_mode4440 = { @@ -15129,16 +14715,7 @@ { 4, bark_tab_m44_512, 20, fcb44sm, 2, 6, cb4440sm0, cb4440sm1, 17 }, { 1, bark_tab_l44_2048, 40, fcb44sl, 4, 6, cb4440sl0, cb4440sl1, 17 } }, - 2048, 20, lsp44s, 1, 6, 4, 4, shape44s, 9, 84, 54, 7, 200 -}; - -const TwinVQModeTab ff_metasound_mode4440s = { - { - { 16, bark_tab_s44_128, 10, fcb44ss, 1, 6, cb4440ss0, cb4440ss1, 18 }, - { 4, bark_tab_m44_512, 20, fcb44sm, 2, 6, cb4440sm0, cb4440sm1, 17 }, - { 1, bark_tab_l44_2048, 40, fcb44sl, 4, 6, cb4440sl0, cb4440sl1, 17 } - }, - 2048, 20, lsp44s, 1, 6, 4, 4, shape44s, 9, 84, 54, 7, 200 + 2048, 20, ff_metasound_lsp44, 1, 6, 4, 4, shape44s, 9, 84, 54, 7, 200 }; const TwinVQModeTab ff_metasound_mode4448 = { @@ -15147,14 +14724,6 @@ { 4, bark_tab_m44_512, 20, fcb44sm, 2, 6, cb4448sm0, cb4448sm1, 14 }, { 1, bark_tab_l44_2048, 40, fcb44sl, 4, 6, cb4448sl0, cb4448sl1, 14 } }, - 2048, 20, lsp44s, 1, 6, 4, 4, shape44s, 9, 84, 54, 7, 200 -}; - -const TwinVQModeTab ff_metasound_mode4448s = { - { - { 16, bark_tab_s44_128, 10, fcb44ss, 1, 6, cb4448ss0, cb4448ss1, 15 }, - { 4, bark_tab_m44_512, 20, fcb44sm, 2, 6, cb4448sm0, cb4448sm1, 14 }, - { 1, bark_tab_l44_2048, 40, fcb44sl, 4, 6, cb4448sl0, cb4448sl1, 14 } - }, - 2048, 20, lsp44s, 1, 6, 4, 4, shape44s, 9, 84, 54, 7, 200 + 2048, 20, ff_metasound_lsp44, 1, 6, 4, 4, shape44s, 9, 84, 54, 7, 200 }; +#endif /* CONFIG_METASOUND_DECODER */ diff -Nru ffmpeg-4.2.2/libavcodec/metasound_data.h ffmpeg-4.4/libavcodec/metasound_data.h --- ffmpeg-4.2.2/libavcodec/metasound_data.h 2016-03-29 02:25:17.000000000 +0000 +++ ffmpeg-4.4/libavcodec/metasound_data.h 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,12 @@ #include "twinvq.h" +extern const float ff_metasound_lsp8[]; +extern const float ff_metasound_lsp11[]; +extern const float ff_metasound_lsp16[]; +extern const float ff_metasound_lsp22[]; +extern const float ff_metasound_lsp44[]; + extern const TwinVQModeTab ff_metasound_mode0806; extern const TwinVQModeTab ff_metasound_mode0806s; extern const TwinVQModeTab ff_metasound_mode0808; @@ -40,10 +46,7 @@ extern const TwinVQModeTab ff_metasound_mode2232; extern const TwinVQModeTab ff_metasound_mode2232s; extern const TwinVQModeTab ff_metasound_mode4432; -extern const TwinVQModeTab ff_metasound_mode4432s; extern const TwinVQModeTab ff_metasound_mode4440; -extern const TwinVQModeTab ff_metasound_mode4440s; extern const TwinVQModeTab ff_metasound_mode4448; -extern const TwinVQModeTab ff_metasound_mode4448s; #endif /* AVCODEC_METASOUND_DATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mfenc.c ffmpeg-4.4/libavcodec/mfenc.c --- ffmpeg-4.2.2/libavcodec/mfenc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mfenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,1213 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define COBJMACROS +#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0602 +#endif + +#include "encode.h" +#include "mf_utils.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/time.h" +#include "internal.h" + +typedef struct MFContext { + AVClass *av_class; + AVFrame *frame; + int is_video, is_audio; + GUID main_subtype; + IMFTransform *mft; + IMFMediaEventGenerator *async_events; + DWORD in_stream_id, out_stream_id; + MFT_INPUT_STREAM_INFO in_info; + MFT_OUTPUT_STREAM_INFO out_info; + int out_stream_provides_samples; + int draining, draining_done; + int sample_sent; + int async_need_input, async_have_output, async_marker; + int64_t reorder_delay; + ICodecAPI *codec_api; + // set by AVOption + int opt_enc_rc; + int opt_enc_quality; + int opt_enc_scenario; + int opt_enc_hw; +} MFContext; + +static int mf_choose_output_type(AVCodecContext *avctx); +static int mf_setup_context(AVCodecContext *avctx); + +#define MF_TIMEBASE (AVRational){1, 10000000} +// Sentinel value only used by us. +#define MF_INVALID_TIME AV_NOPTS_VALUE + +static int mf_wait_events(AVCodecContext *avctx) +{ + MFContext *c = avctx->priv_data; + + if (!c->async_events) + return 0; + + while (!(c->async_need_input || c->async_have_output || c->draining_done || c->async_marker)) { + IMFMediaEvent *ev = NULL; + MediaEventType ev_id = 0; + HRESULT hr = IMFMediaEventGenerator_GetEvent(c->async_events, 0, &ev); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "IMFMediaEventGenerator_GetEvent() failed: %s\n", + ff_hr_str(hr)); + return AVERROR_EXTERNAL; + } + IMFMediaEvent_GetType(ev, &ev_id); + switch (ev_id) { + case ff_METransformNeedInput: + if (!c->draining) + c->async_need_input = 1; + break; + case ff_METransformHaveOutput: + c->async_have_output = 1; + break; + case ff_METransformDrainComplete: + c->draining_done = 1; + break; + case ff_METransformMarker: + c->async_marker = 1; + break; + default: ; + } + IMFMediaEvent_Release(ev); + } + + return 0; +} + +static AVRational mf_get_tb(AVCodecContext *avctx) +{ + if (avctx->pkt_timebase.num > 0 && avctx->pkt_timebase.den > 0) + return avctx->pkt_timebase; + if (avctx->time_base.num > 0 && avctx->time_base.den > 0) + return avctx->time_base; + return MF_TIMEBASE; +} + +static LONGLONG mf_to_mf_time(AVCodecContext *avctx, int64_t av_pts) +{ + if (av_pts == AV_NOPTS_VALUE) + return MF_INVALID_TIME; + return av_rescale_q(av_pts, mf_get_tb(avctx), MF_TIMEBASE); +} + +static void mf_sample_set_pts(AVCodecContext *avctx, IMFSample *sample, int64_t av_pts) +{ + LONGLONG stime = mf_to_mf_time(avctx, av_pts); + if (stime != MF_INVALID_TIME) + IMFSample_SetSampleTime(sample, stime); +} + +static int64_t mf_from_mf_time(AVCodecContext *avctx, LONGLONG stime) +{ + return av_rescale_q(stime, MF_TIMEBASE, mf_get_tb(avctx)); +} + +static int64_t mf_sample_get_pts(AVCodecContext *avctx, IMFSample *sample) +{ + LONGLONG pts; + HRESULT hr = IMFSample_GetSampleTime(sample, &pts); + if (FAILED(hr)) + return AV_NOPTS_VALUE; + return mf_from_mf_time(avctx, pts); +} + +static int mf_enca_output_type_get(AVCodecContext *avctx, IMFMediaType *type) +{ + MFContext *c = avctx->priv_data; + HRESULT hr; + UINT32 sz; + + if (avctx->codec_id != AV_CODEC_ID_MP3 && avctx->codec_id != AV_CODEC_ID_AC3) { + hr = IMFAttributes_GetBlobSize(type, &MF_MT_USER_DATA, &sz); + if (!FAILED(hr) && sz > 0) { + avctx->extradata = av_mallocz(sz + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) + return AVERROR(ENOMEM); + avctx->extradata_size = sz; + hr = IMFAttributes_GetBlob(type, &MF_MT_USER_DATA, avctx->extradata, sz, NULL); + if (FAILED(hr)) + return AVERROR_EXTERNAL; + + if (avctx->codec_id == AV_CODEC_ID_AAC && avctx->extradata_size >= 12) { + // Get rid of HEAACWAVEINFO (after wfx field, 12 bytes). + avctx->extradata_size = avctx->extradata_size - 12; + memmove(avctx->extradata, avctx->extradata + 12, avctx->extradata_size); + } + } + } + + // I don't know where it's documented that we need this. It happens with the + // MS mp3 encoder MFT. The idea for the workaround is taken from NAudio. + // (Certainly any lossy codec will have frames much smaller than 1 second.) + if (!c->out_info.cbSize && !c->out_stream_provides_samples) { + hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &sz); + if (!FAILED(hr)) { + av_log(avctx, AV_LOG_VERBOSE, "MFT_OUTPUT_STREAM_INFO.cbSize set to 0, " + "assuming %d bytes instead.\n", (int)sz); + c->out_info.cbSize = sz; + } + } + + return 0; +} + +static int mf_encv_output_type_get(AVCodecContext *avctx, IMFMediaType *type) +{ + HRESULT hr; + UINT32 sz; + + hr = IMFAttributes_GetBlobSize(type, &MF_MT_MPEG_SEQUENCE_HEADER, &sz); + if (!FAILED(hr) && sz > 0) { + uint8_t *extradata = av_mallocz(sz + AV_INPUT_BUFFER_PADDING_SIZE); + if (!extradata) + return AVERROR(ENOMEM); + hr = IMFAttributes_GetBlob(type, &MF_MT_MPEG_SEQUENCE_HEADER, extradata, sz, NULL); + if (FAILED(hr)) { + av_free(extradata); + return AVERROR_EXTERNAL; + } + av_freep(&avctx->extradata); + avctx->extradata = extradata; + avctx->extradata_size = sz; + } + + return 0; +} + +static int mf_output_type_get(AVCodecContext *avctx) +{ + MFContext *c = avctx->priv_data; + HRESULT hr; + IMFMediaType *type; + int ret; + + hr = IMFTransform_GetOutputCurrentType(c->mft, c->out_stream_id, &type); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "could not get output type\n"); + return AVERROR_EXTERNAL; + } + + av_log(avctx, AV_LOG_VERBOSE, "final output type:\n"); + ff_media_type_dump(avctx, type); + + ret = 0; + if (c->is_video) { + ret = mf_encv_output_type_get(avctx, type); + } else if (c->is_audio) { + ret = mf_enca_output_type_get(avctx, type); + } + + if (ret < 0) + av_log(avctx, AV_LOG_ERROR, "output type not supported\n"); + + IMFMediaType_Release(type); + return ret; +} + +static int mf_sample_to_avpacket(AVCodecContext *avctx, IMFSample *sample, AVPacket *avpkt) +{ + MFContext *c = avctx->priv_data; + HRESULT hr; + int ret; + DWORD len; + IMFMediaBuffer *buffer; + BYTE *data; + UINT64 t; + UINT32 t32; + + hr = IMFSample_GetTotalLength(sample, &len); + if (FAILED(hr)) + return AVERROR_EXTERNAL; + + if ((ret = ff_get_encode_buffer(avctx, avpkt, len, 0)) < 0) + return ret; + + IMFSample_ConvertToContiguousBuffer(sample, &buffer); + if (FAILED(hr)) + return AVERROR_EXTERNAL; + + hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL); + if (FAILED(hr)) { + IMFMediaBuffer_Release(buffer); + return AVERROR_EXTERNAL; + } + + memcpy(avpkt->data, data, len); + + IMFMediaBuffer_Unlock(buffer); + IMFMediaBuffer_Release(buffer); + + avpkt->pts = avpkt->dts = mf_sample_get_pts(avctx, sample); + + hr = IMFAttributes_GetUINT32(sample, &MFSampleExtension_CleanPoint, &t32); + if (c->is_audio || (!FAILED(hr) && t32 != 0)) + avpkt->flags |= AV_PKT_FLAG_KEY; + + hr = IMFAttributes_GetUINT64(sample, &MFSampleExtension_DecodeTimestamp, &t); + if (!FAILED(hr)) { + avpkt->dts = mf_from_mf_time(avctx, t); + // At least on Qualcomm's HEVC encoder on SD 835, the output dts + // starts from the input pts of the first frame, while the output pts + // is shifted forward. Therefore, shift the output values back so that + // the output pts matches the input. + if (c->reorder_delay == AV_NOPTS_VALUE) + c->reorder_delay = avpkt->pts - avpkt->dts; + avpkt->dts -= c->reorder_delay; + avpkt->pts -= c->reorder_delay; + } + + return 0; +} + +static IMFSample *mf_a_avframe_to_sample(AVCodecContext *avctx, const AVFrame *frame) +{ + MFContext *c = avctx->priv_data; + size_t len; + size_t bps; + IMFSample *sample; + + bps = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->channels; + len = frame->nb_samples * bps; + + sample = ff_create_memory_sample(frame->data[0], len, c->in_info.cbAlignment); + if (sample) + IMFSample_SetSampleDuration(sample, mf_to_mf_time(avctx, frame->nb_samples)); + return sample; +} + +static IMFSample *mf_v_avframe_to_sample(AVCodecContext *avctx, const AVFrame *frame) +{ + MFContext *c = avctx->priv_data; + IMFSample *sample; + IMFMediaBuffer *buffer; + BYTE *data; + HRESULT hr; + int ret; + int size; + + size = av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1); + if (size < 0) + return NULL; + + sample = ff_create_memory_sample(NULL, size, c->in_info.cbAlignment); + if (!sample) + return NULL; + + hr = IMFSample_GetBufferByIndex(sample, 0, &buffer); + if (FAILED(hr)) { + IMFSample_Release(sample); + return NULL; + } + + hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL); + if (FAILED(hr)) { + IMFMediaBuffer_Release(buffer); + IMFSample_Release(sample); + return NULL; + } + + ret = av_image_copy_to_buffer((uint8_t *)data, size, (void *)frame->data, frame->linesize, + avctx->pix_fmt, avctx->width, avctx->height, 1); + IMFMediaBuffer_SetCurrentLength(buffer, size); + IMFMediaBuffer_Unlock(buffer); + IMFMediaBuffer_Release(buffer); + if (ret < 0) { + IMFSample_Release(sample); + return NULL; + } + + IMFSample_SetSampleDuration(sample, mf_to_mf_time(avctx, frame->pkt_duration)); + + return sample; +} + +static IMFSample *mf_avframe_to_sample(AVCodecContext *avctx, const AVFrame *frame) +{ + MFContext *c = avctx->priv_data; + IMFSample *sample; + + if (c->is_audio) { + sample = mf_a_avframe_to_sample(avctx, frame); + } else { + sample = mf_v_avframe_to_sample(avctx, frame); + } + + if (sample) + mf_sample_set_pts(avctx, sample, frame->pts); + + return sample; +} + +static int mf_send_sample(AVCodecContext *avctx, IMFSample *sample) +{ + MFContext *c = avctx->priv_data; + HRESULT hr; + int ret; + + if (sample) { + if (c->async_events) { + if ((ret = mf_wait_events(avctx)) < 0) + return ret; + if (!c->async_need_input) + return AVERROR(EAGAIN); + } + if (!c->sample_sent) + IMFSample_SetUINT32(sample, &MFSampleExtension_Discontinuity, TRUE); + c->sample_sent = 1; + hr = IMFTransform_ProcessInput(c->mft, c->in_stream_id, sample, 0); + if (hr == MF_E_NOTACCEPTING) { + return AVERROR(EAGAIN); + } else if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "failed processing input: %s\n", ff_hr_str(hr)); + return AVERROR_EXTERNAL; + } + c->async_need_input = 0; + } else if (!c->draining) { + hr = IMFTransform_ProcessMessage(c->mft, MFT_MESSAGE_COMMAND_DRAIN, 0); + if (FAILED(hr)) + av_log(avctx, AV_LOG_ERROR, "failed draining: %s\n", ff_hr_str(hr)); + // Some MFTs (AC3) will send a frame after each drain command (???), so + // this is required to make draining actually terminate. + c->draining = 1; + c->async_need_input = 0; + } else { + return AVERROR_EOF; + } + return 0; +} + +static int mf_receive_sample(AVCodecContext *avctx, IMFSample **out_sample) +{ + MFContext *c = avctx->priv_data; + HRESULT hr; + DWORD st; + MFT_OUTPUT_DATA_BUFFER out_buffers; + IMFSample *sample; + int ret = 0; + + while (1) { + *out_sample = NULL; + sample = NULL; + + if (c->async_events) { + if ((ret = mf_wait_events(avctx)) < 0) + return ret; + if (!c->async_have_output || c->draining_done) { + ret = 0; + break; + } + } + + if (!c->out_stream_provides_samples) { + sample = ff_create_memory_sample(NULL, c->out_info.cbSize, c->out_info.cbAlignment); + if (!sample) + return AVERROR(ENOMEM); + } + + out_buffers = (MFT_OUTPUT_DATA_BUFFER) { + .dwStreamID = c->out_stream_id, + .pSample = sample, + }; + + st = 0; + hr = IMFTransform_ProcessOutput(c->mft, 0, 1, &out_buffers, &st); + + if (out_buffers.pEvents) + IMFCollection_Release(out_buffers.pEvents); + + if (!FAILED(hr)) { + *out_sample = out_buffers.pSample; + ret = 0; + break; + } + + if (out_buffers.pSample) + IMFSample_Release(out_buffers.pSample); + + if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { + if (c->draining) + c->draining_done = 1; + ret = 0; + } else if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { + av_log(avctx, AV_LOG_WARNING, "stream format change\n"); + ret = mf_choose_output_type(avctx); + if (ret == 0) // we don't expect renegotiating the input type + ret = AVERROR_EXTERNAL; + if (ret > 0) { + ret = mf_setup_context(avctx); + if (ret >= 0) { + c->async_have_output = 0; + continue; + } + } + } else { + av_log(avctx, AV_LOG_ERROR, "failed processing output: %s\n", ff_hr_str(hr)); + ret = AVERROR_EXTERNAL; + } + + break; + } + + c->async_have_output = 0; + + if (ret >= 0 && !*out_sample) + ret = c->draining_done ? AVERROR_EOF : AVERROR(EAGAIN); + + return ret; +} + +static int mf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) +{ + MFContext *c = avctx->priv_data; + IMFSample *sample = NULL; + int ret; + + if (!c->frame->buf[0]) { + ret = ff_encode_get_frame(avctx, c->frame); + if (ret < 0 && ret != AVERROR_EOF) + return ret; + } + + if (c->frame->buf[0]) { + sample = mf_avframe_to_sample(avctx, c->frame); + if (!sample) { + av_frame_unref(c->frame); + return AVERROR(ENOMEM); + } + if (c->is_video && c->codec_api) { + if (c->frame->pict_type == AV_PICTURE_TYPE_I || !c->sample_sent) + ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncVideoForceKeyFrame, FF_VAL_VT_UI4(1)); + } + } + + ret = mf_send_sample(avctx, sample); + if (sample) + IMFSample_Release(sample); + if (ret != AVERROR(EAGAIN)) + av_frame_unref(c->frame); + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + return ret; + + ret = mf_receive_sample(avctx, &sample); + if (ret < 0) + return ret; + + ret = mf_sample_to_avpacket(avctx, sample, avpkt); + IMFSample_Release(sample); + + return ret; +} + +// Most encoders seem to enumerate supported audio formats on the output types, +// at least as far as channel configuration and sample rate is concerned. Pick +// the one which seems to match best. +static int64_t mf_enca_output_score(AVCodecContext *avctx, IMFMediaType *type) +{ + MFContext *c = avctx->priv_data; + HRESULT hr; + UINT32 t; + GUID tg; + int64_t score = 0; + + hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t); + if (!FAILED(hr) && t == avctx->sample_rate) + score |= 1LL << 32; + + hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &t); + if (!FAILED(hr) && t == avctx->channels) + score |= 2LL << 32; + + hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &tg); + if (!FAILED(hr)) { + if (IsEqualGUID(&c->main_subtype, &tg)) + score |= 4LL << 32; + } + + // Select the bitrate (lowest priority). + hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &t); + if (!FAILED(hr)) { + int diff = (int)t - avctx->bit_rate / 8; + if (diff >= 0) { + score |= (1LL << 31) - diff; // prefer lower bitrate + } else { + score |= (1LL << 30) + diff; // prefer higher bitrate + } + } + + hr = IMFAttributes_GetUINT32(type, &MF_MT_AAC_PAYLOAD_TYPE, &t); + if (!FAILED(hr) && t != 0) + return -1; + + return score; +} + +static int mf_enca_output_adjust(AVCodecContext *avctx, IMFMediaType *type) +{ + // (some decoders allow adjusting this freely, but it can also cause failure + // to set the output type - so it's commented for being too fragile) + //IMFAttributes_SetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, avctx->bit_rate / 8); + //IMFAttributes_SetUINT32(type, &MF_MT_AVG_BITRATE, avctx->bit_rate); + + return 0; +} + +static int64_t mf_enca_input_score(AVCodecContext *avctx, IMFMediaType *type) +{ + HRESULT hr; + UINT32 t; + int64_t score = 0; + + enum AVSampleFormat sformat = ff_media_type_to_sample_fmt((IMFAttributes *)type); + if (sformat == AV_SAMPLE_FMT_NONE) + return -1; // can not use + + if (sformat == avctx->sample_fmt) + score |= 1; + + hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t); + if (!FAILED(hr) && t == avctx->sample_rate) + score |= 2; + + hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &t); + if (!FAILED(hr) && t == avctx->channels) + score |= 4; + + return score; +} + +static int mf_enca_input_adjust(AVCodecContext *avctx, IMFMediaType *type) +{ + HRESULT hr; + UINT32 t; + + enum AVSampleFormat sformat = ff_media_type_to_sample_fmt((IMFAttributes *)type); + if (sformat != avctx->sample_fmt) { + av_log(avctx, AV_LOG_ERROR, "unsupported input sample format set\n"); + return AVERROR(EINVAL); + } + + hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &t); + if (FAILED(hr) || t != avctx->sample_rate) { + av_log(avctx, AV_LOG_ERROR, "unsupported input sample rate set\n"); + return AVERROR(EINVAL); + } + + hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &t); + if (FAILED(hr) || t != avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "unsupported input channel number set\n"); + return AVERROR(EINVAL); + } + + return 0; +} + +static int64_t mf_encv_output_score(AVCodecContext *avctx, IMFMediaType *type) +{ + MFContext *c = avctx->priv_data; + GUID tg; + HRESULT hr; + int score = -1; + + hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &tg); + if (!FAILED(hr)) { + if (IsEqualGUID(&c->main_subtype, &tg)) + score = 1; + } + + return score; +} + +static int mf_encv_output_adjust(AVCodecContext *avctx, IMFMediaType *type) +{ + MFContext *c = avctx->priv_data; + AVRational framerate; + + ff_MFSetAttributeSize((IMFAttributes *)type, &MF_MT_FRAME_SIZE, avctx->width, avctx->height); + IMFAttributes_SetUINT32(type, &MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); + + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + framerate = avctx->framerate; + } else { + framerate = av_inv_q(avctx->time_base); + framerate.den *= avctx->ticks_per_frame; + } + + ff_MFSetAttributeRatio((IMFAttributes *)type, &MF_MT_FRAME_RATE, framerate.num, framerate.den); + + // (MS HEVC supports eAVEncH265VProfile_Main_420_8 only.) + if (avctx->codec_id == AV_CODEC_ID_H264) { + UINT32 profile = ff_eAVEncH264VProfile_Base; + switch (avctx->profile) { + case FF_PROFILE_H264_MAIN: + profile = ff_eAVEncH264VProfile_Main; + break; + case FF_PROFILE_H264_HIGH: + profile = ff_eAVEncH264VProfile_High; + break; + } + IMFAttributes_SetUINT32(type, &MF_MT_MPEG2_PROFILE, profile); + } + + IMFAttributes_SetUINT32(type, &MF_MT_AVG_BITRATE, avctx->bit_rate); + + // Note that some of the ICodecAPI options must be set before SetOutputType. + if (c->codec_api) { + if (avctx->bit_rate) + ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncCommonMeanBitRate, FF_VAL_VT_UI4(avctx->bit_rate)); + + if (c->opt_enc_rc >= 0) + ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncCommonRateControlMode, FF_VAL_VT_UI4(c->opt_enc_rc)); + + if (c->opt_enc_quality >= 0) + ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncCommonQuality, FF_VAL_VT_UI4(c->opt_enc_quality)); + + // Always set the number of b-frames. Qualcomm's HEVC encoder on SD835 + // defaults this to 1, and that setting is buggy with many of the + // rate control modes. (0 or 2 b-frames works fine with most rate + // control modes, but 2 seems buggy with the u_vbr mode.) Setting + // "scenario" to "camera_record" sets it in CFR mode (where the default + // is VFR), which makes the encoder avoid dropping frames. + ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncMPVDefaultBPictureCount, FF_VAL_VT_UI4(avctx->max_b_frames)); + avctx->has_b_frames = avctx->max_b_frames > 0; + + ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVEncH264CABACEnable, FF_VAL_VT_BOOL(1)); + + if (c->opt_enc_scenario >= 0) + ICodecAPI_SetValue(c->codec_api, &ff_CODECAPI_AVScenarioInfo, FF_VAL_VT_UI4(c->opt_enc_scenario)); + } + + return 0; +} + +static int64_t mf_encv_input_score(AVCodecContext *avctx, IMFMediaType *type) +{ + enum AVPixelFormat pix_fmt = ff_media_type_to_pix_fmt((IMFAttributes *)type); + if (pix_fmt != avctx->pix_fmt) + return -1; // can not use + + return 0; +} + +static int mf_encv_input_adjust(AVCodecContext *avctx, IMFMediaType *type) +{ + enum AVPixelFormat pix_fmt = ff_media_type_to_pix_fmt((IMFAttributes *)type); + if (pix_fmt != avctx->pix_fmt) { + av_log(avctx, AV_LOG_ERROR, "unsupported input pixel format set\n"); + return AVERROR(EINVAL); + } + + //ff_MFSetAttributeSize((IMFAttributes *)type, &MF_MT_FRAME_SIZE, avctx->width, avctx->height); + + return 0; +} + +static int mf_choose_output_type(AVCodecContext *avctx) +{ + MFContext *c = avctx->priv_data; + HRESULT hr; + int ret; + IMFMediaType *out_type = NULL; + int64_t out_type_score = -1; + int out_type_index = -1; + int n; + + av_log(avctx, AV_LOG_VERBOSE, "output types:\n"); + for (n = 0; ; n++) { + IMFMediaType *type; + int64_t score = -1; + + hr = IMFTransform_GetOutputAvailableType(c->mft, c->out_stream_id, n, &type); + if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL) + break; + if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) { + av_log(avctx, AV_LOG_VERBOSE, "(need to set input type)\n"); + ret = 0; + goto done; + } + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "error getting output type: %s\n", ff_hr_str(hr)); + ret = AVERROR_EXTERNAL; + goto done; + } + + av_log(avctx, AV_LOG_VERBOSE, "output type %d:\n", n); + ff_media_type_dump(avctx, type); + + if (c->is_video) { + score = mf_encv_output_score(avctx, type); + } else if (c->is_audio) { + score = mf_enca_output_score(avctx, type); + } + + if (score > out_type_score) { + if (out_type) + IMFMediaType_Release(out_type); + out_type = type; + out_type_score = score; + out_type_index = n; + IMFMediaType_AddRef(out_type); + } + + IMFMediaType_Release(type); + } + + if (out_type) { + av_log(avctx, AV_LOG_VERBOSE, "picking output type %d.\n", out_type_index); + } else { + hr = MFCreateMediaType(&out_type); + if (FAILED(hr)) { + ret = AVERROR(ENOMEM); + goto done; + } + } + + ret = 0; + if (c->is_video) { + ret = mf_encv_output_adjust(avctx, out_type); + } else if (c->is_audio) { + ret = mf_enca_output_adjust(avctx, out_type); + } + + if (ret >= 0) { + av_log(avctx, AV_LOG_VERBOSE, "setting output type:\n"); + ff_media_type_dump(avctx, out_type); + + hr = IMFTransform_SetOutputType(c->mft, c->out_stream_id, out_type, 0); + if (!FAILED(hr)) { + ret = 1; + } else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) { + av_log(avctx, AV_LOG_VERBOSE, "rejected - need to set input type\n"); + ret = 0; + } else { + av_log(avctx, AV_LOG_ERROR, "could not set output type (%s)\n", ff_hr_str(hr)); + ret = AVERROR_EXTERNAL; + } + } + +done: + if (out_type) + IMFMediaType_Release(out_type); + return ret; +} + +static int mf_choose_input_type(AVCodecContext *avctx) +{ + MFContext *c = avctx->priv_data; + HRESULT hr; + int ret; + IMFMediaType *in_type = NULL; + int64_t in_type_score = -1; + int in_type_index = -1; + int n; + + av_log(avctx, AV_LOG_VERBOSE, "input types:\n"); + for (n = 0; ; n++) { + IMFMediaType *type = NULL; + int64_t score = -1; + + hr = IMFTransform_GetInputAvailableType(c->mft, c->in_stream_id, n, &type); + if (hr == MF_E_NO_MORE_TYPES || hr == E_NOTIMPL) + break; + if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) { + av_log(avctx, AV_LOG_VERBOSE, "(need to set output type 1)\n"); + ret = 0; + goto done; + } + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "error getting input type: %s\n", ff_hr_str(hr)); + ret = AVERROR_EXTERNAL; + goto done; + } + + av_log(avctx, AV_LOG_VERBOSE, "input type %d:\n", n); + ff_media_type_dump(avctx, type); + + if (c->is_video) { + score = mf_encv_input_score(avctx, type); + } else if (c->is_audio) { + score = mf_enca_input_score(avctx, type); + } + + if (score > in_type_score) { + if (in_type) + IMFMediaType_Release(in_type); + in_type = type; + in_type_score = score; + in_type_index = n; + IMFMediaType_AddRef(in_type); + } + + IMFMediaType_Release(type); + } + + if (in_type) { + av_log(avctx, AV_LOG_VERBOSE, "picking input type %d.\n", in_type_index); + } else { + // Some buggy MFTs (WMA encoder) fail to return MF_E_TRANSFORM_TYPE_NOT_SET. + av_log(avctx, AV_LOG_VERBOSE, "(need to set output type 2)\n"); + ret = 0; + goto done; + } + + ret = 0; + if (c->is_video) { + ret = mf_encv_input_adjust(avctx, in_type); + } else if (c->is_audio) { + ret = mf_enca_input_adjust(avctx, in_type); + } + + if (ret >= 0) { + av_log(avctx, AV_LOG_VERBOSE, "setting input type:\n"); + ff_media_type_dump(avctx, in_type); + + hr = IMFTransform_SetInputType(c->mft, c->in_stream_id, in_type, 0); + if (!FAILED(hr)) { + ret = 1; + } else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) { + av_log(avctx, AV_LOG_VERBOSE, "rejected - need to set output type\n"); + ret = 0; + } else { + av_log(avctx, AV_LOG_ERROR, "could not set input type (%s)\n", ff_hr_str(hr)); + ret = AVERROR_EXTERNAL; + } + } + +done: + if (in_type) + IMFMediaType_Release(in_type); + return ret; +} + +static int mf_negotiate_types(AVCodecContext *avctx) +{ + // This follows steps 1-5 on: + // https://msdn.microsoft.com/en-us/library/windows/desktop/aa965264(v=vs.85).aspx + // If every MFT implementer does this correctly, this loop should at worst + // be repeated once. + int need_input = 1, need_output = 1; + int n; + for (n = 0; n < 2 && (need_input || need_output); n++) { + int ret; + ret = mf_choose_input_type(avctx); + if (ret < 0) + return ret; + need_input = ret < 1; + ret = mf_choose_output_type(avctx); + if (ret < 0) + return ret; + need_output = ret < 1; + } + if (need_input || need_output) { + av_log(avctx, AV_LOG_ERROR, "format negotiation failed (%d/%d)\n", + need_input, need_output); + return AVERROR_EXTERNAL; + } + return 0; +} + +static int mf_setup_context(AVCodecContext *avctx) +{ + MFContext *c = avctx->priv_data; + HRESULT hr; + int ret; + + hr = IMFTransform_GetInputStreamInfo(c->mft, c->in_stream_id, &c->in_info); + if (FAILED(hr)) + return AVERROR_EXTERNAL; + av_log(avctx, AV_LOG_VERBOSE, "in_info: size=%d, align=%d\n", + (int)c->in_info.cbSize, (int)c->in_info.cbAlignment); + + hr = IMFTransform_GetOutputStreamInfo(c->mft, c->out_stream_id, &c->out_info); + if (FAILED(hr)) + return AVERROR_EXTERNAL; + c->out_stream_provides_samples = + (c->out_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) || + (c->out_info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES); + av_log(avctx, AV_LOG_VERBOSE, "out_info: size=%d, align=%d%s\n", + (int)c->out_info.cbSize, (int)c->out_info.cbAlignment, + c->out_stream_provides_samples ? " (provides samples)" : ""); + + if ((ret = mf_output_type_get(avctx)) < 0) + return ret; + + return 0; +} + +static int mf_unlock_async(AVCodecContext *avctx) +{ + MFContext *c = avctx->priv_data; + HRESULT hr; + IMFAttributes *attrs; + UINT32 v; + int res = AVERROR_EXTERNAL; + + // For hw encoding we unfortunately need to use async mode, otherwise + // play it safe and avoid it. + if (!(c->is_video && c->opt_enc_hw)) + return 0; + + hr = IMFTransform_GetAttributes(c->mft, &attrs); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "error retrieving MFT attributes: %s\n", ff_hr_str(hr)); + goto err; + } + + hr = IMFAttributes_GetUINT32(attrs, &MF_TRANSFORM_ASYNC, &v); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "error querying async: %s\n", ff_hr_str(hr)); + goto err; + } + + if (!v) { + av_log(avctx, AV_LOG_ERROR, "hardware MFT is not async\n"); + goto err; + } + + hr = IMFAttributes_SetUINT32(attrs, &MF_TRANSFORM_ASYNC_UNLOCK, TRUE); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "could not set async unlock: %s\n", ff_hr_str(hr)); + goto err; + } + + hr = IMFTransform_QueryInterface(c->mft, &IID_IMFMediaEventGenerator, (void **)&c->async_events); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "could not get async interface\n"); + goto err; + } + + res = 0; + +err: + IMFAttributes_Release(attrs); + return res; +} + +static int mf_create(void *log, IMFTransform **mft, const AVCodec *codec, int use_hw) +{ + int is_audio = codec->type == AVMEDIA_TYPE_AUDIO; + const CLSID *subtype = ff_codec_to_mf_subtype(codec->id); + MFT_REGISTER_TYPE_INFO reg = {0}; + GUID category; + int ret; + + *mft = NULL; + + if (!subtype) + return AVERROR(ENOSYS); + + reg.guidSubtype = *subtype; + + if (is_audio) { + reg.guidMajorType = MFMediaType_Audio; + category = MFT_CATEGORY_AUDIO_ENCODER; + } else { + reg.guidMajorType = MFMediaType_Video; + category = MFT_CATEGORY_VIDEO_ENCODER; + } + + if ((ret = ff_instantiate_mf(log, category, NULL, ®, use_hw, mft)) < 0) + return ret; + + return 0; +} + +static int mf_init(AVCodecContext *avctx) +{ + MFContext *c = avctx->priv_data; + HRESULT hr; + int ret; + const CLSID *subtype = ff_codec_to_mf_subtype(avctx->codec_id); + int use_hw = 0; + + c->frame = av_frame_alloc(); + if (!c->frame) + return AVERROR(ENOMEM); + + c->is_audio = avctx->codec_type == AVMEDIA_TYPE_AUDIO; + c->is_video = !c->is_audio; + c->reorder_delay = AV_NOPTS_VALUE; + + if (c->is_video && c->opt_enc_hw) + use_hw = 1; + + if (!subtype) + return AVERROR(ENOSYS); + + c->main_subtype = *subtype; + + if ((ret = mf_create(avctx, &c->mft, avctx->codec, use_hw)) < 0) + return ret; + + if ((ret = mf_unlock_async(avctx)) < 0) + return ret; + + hr = IMFTransform_QueryInterface(c->mft, &IID_ICodecAPI, (void **)&c->codec_api); + if (!FAILED(hr)) + av_log(avctx, AV_LOG_VERBOSE, "MFT supports ICodecAPI.\n"); + + + hr = IMFTransform_GetStreamIDs(c->mft, 1, &c->in_stream_id, 1, &c->out_stream_id); + if (hr == E_NOTIMPL) { + c->in_stream_id = c->out_stream_id = 0; + } else if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "could not get stream IDs (%s)\n", ff_hr_str(hr)); + return AVERROR_EXTERNAL; + } + + if ((ret = mf_negotiate_types(avctx)) < 0) + return ret; + + if ((ret = mf_setup_context(avctx)) < 0) + return ret; + + hr = IMFTransform_ProcessMessage(c->mft, MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "could not start streaming (%s)\n", ff_hr_str(hr)); + return AVERROR_EXTERNAL; + } + + hr = IMFTransform_ProcessMessage(c->mft, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); + if (FAILED(hr)) { + av_log(avctx, AV_LOG_ERROR, "could not start stream (%s)\n", ff_hr_str(hr)); + return AVERROR_EXTERNAL; + } + + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER && c->async_events && + c->is_video && !avctx->extradata) { + int sleep = 10000, total = 0; + av_log(avctx, AV_LOG_VERBOSE, "Awaiting extradata\n"); + while (total < 70*1000) { + // The Qualcomm H264 encoder on SD835 doesn't provide extradata + // immediately, but it becomes available soon after init (without + // any waitable event). In practice, it's available after less + // than 10 ms, but wait for up to 70 ms before giving up. + // Some encoders (Qualcomm's HEVC encoder on SD835, some versions + // of the QSV H264 encoder at least) don't provide extradata this + // way at all, not even after encoding a frame - it's only + // available prepended to frames. + av_usleep(sleep); + total += sleep; + mf_output_type_get(avctx); + if (avctx->extradata) + break; + sleep *= 2; + } + av_log(avctx, AV_LOG_VERBOSE, "%s extradata in %d ms\n", + avctx->extradata ? "Got" : "Didn't get", total / 1000); + } + + return 0; +} + +static int mf_close(AVCodecContext *avctx) +{ + MFContext *c = avctx->priv_data; + + if (c->codec_api) + ICodecAPI_Release(c->codec_api); + + if (c->async_events) + IMFMediaEventGenerator_Release(c->async_events); + + ff_free_mf(&c->mft); + + av_frame_free(&c->frame); + + av_freep(&avctx->extradata); + avctx->extradata_size = 0; + + return 0; +} + +#define OFFSET(x) offsetof(MFContext, x) + +#define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, EXTRA) \ + static const AVClass ff_ ## NAME ## _mf_encoder_class = { \ + .class_name = #NAME "_mf", \ + .item_name = av_default_item_name, \ + .option = OPTS, \ + .version = LIBAVUTIL_VERSION_INT, \ + }; \ + AVCodec ff_ ## NAME ## _mf_encoder = { \ + .priv_class = &ff_ ## NAME ## _mf_encoder_class, \ + .name = #NAME "_mf", \ + .long_name = NULL_IF_CONFIG_SMALL(#ID " via MediaFoundation"), \ + .type = AVMEDIA_TYPE_ ## MEDIATYPE, \ + .id = AV_CODEC_ID_ ## ID, \ + .priv_data_size = sizeof(MFContext), \ + .init = mf_init, \ + .close = mf_close, \ + .receive_packet = mf_receive_packet, \ + EXTRA \ + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID | \ + AV_CODEC_CAP_DR1, \ + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | \ + FF_CODEC_CAP_INIT_CLEANUP, \ + }; + +#define AFMTS \ + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, \ + AV_SAMPLE_FMT_NONE }, + +MF_ENCODER(AUDIO, aac, AAC, NULL, AFMTS); +MF_ENCODER(AUDIO, ac3, AC3, NULL, AFMTS); +MF_ENCODER(AUDIO, mp3, MP3, NULL, AFMTS); + +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption venc_opts[] = { + {"rate_control", "Select rate control mode", OFFSET(opt_enc_rc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, "rate_control"}, + { "default", "Default mode", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, VE, "rate_control"}, + { "cbr", "CBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_CBR}, 0, 0, VE, "rate_control"}, + { "pc_vbr", "Peak constrained VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_PeakConstrainedVBR}, 0, 0, VE, "rate_control"}, + { "u_vbr", "Unconstrained VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_UnconstrainedVBR}, 0, 0, VE, "rate_control"}, + { "quality", "Quality mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_Quality}, 0, 0, VE, "rate_control" }, + // The following rate_control modes require Windows 8. + { "ld_vbr", "Low delay VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_LowDelayVBR}, 0, 0, VE, "rate_control"}, + { "g_vbr", "Global VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_GlobalVBR}, 0, 0, VE, "rate_control" }, + { "gld_vbr", "Global low delay VBR mode", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVEncCommonRateControlMode_GlobalLowDelayVBR}, 0, 0, VE, "rate_control"}, + + {"scenario", "Select usage scenario", OFFSET(opt_enc_scenario), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, "scenario"}, + { "default", "Default scenario", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, VE, "scenario"}, + { "display_remoting", "Display remoting", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_DisplayRemoting}, 0, 0, VE, "scenario"}, + { "video_conference", "Video conference", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_VideoConference}, 0, 0, VE, "scenario"}, + { "archive", "Archive", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_Archive}, 0, 0, VE, "scenario"}, + { "live_streaming", "Live streaming", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_LiveStreaming}, 0, 0, VE, "scenario"}, + { "camera_record", "Camera record", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_CameraRecord}, 0, 0, VE, "scenario"}, + { "display_remoting_with_feature_map", "Display remoting with feature map", 0, AV_OPT_TYPE_CONST, {.i64 = ff_eAVScenarioInfo_DisplayRemotingWithFeatureMap}, 0, 0, VE, "scenario"}, + + {"quality", "Quality", OFFSET(opt_enc_quality), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 100, VE}, + {"hw_encoding", "Force hardware encoding", OFFSET(opt_enc_hw), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VE}, + {NULL} +}; + +#define VFMTS \ + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, \ + AV_PIX_FMT_YUV420P, \ + AV_PIX_FMT_NONE }, + +MF_ENCODER(VIDEO, h264, H264, venc_opts, VFMTS); +MF_ENCODER(VIDEO, hevc, HEVC, venc_opts, VFMTS); diff -Nru ffmpeg-4.2.2/libavcodec/mf_utils.c ffmpeg-4.4/libavcodec/mf_utils.c --- ffmpeg-4.2.2/libavcodec/mf_utils.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mf_utils.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,680 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define COBJMACROS +#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0602 +#endif + +#include "mf_utils.h" +#include "libavutil/pixdesc.h" + +HRESULT ff_MFGetAttributeSize(IMFAttributes *pattr, REFGUID guid, + UINT32 *pw, UINT32 *ph) +{ + UINT64 t; + HRESULT hr = IMFAttributes_GetUINT64(pattr, guid, &t); + if (!FAILED(hr)) { + *pw = t >> 32; + *ph = (UINT32)t; + } + return hr; +} + +HRESULT ff_MFSetAttributeSize(IMFAttributes *pattr, REFGUID guid, + UINT32 uw, UINT32 uh) +{ + UINT64 t = (((UINT64)uw) << 32) | uh; + return IMFAttributes_SetUINT64(pattr, guid, t); +} + +#define ff_MFSetAttributeRatio ff_MFSetAttributeSize +#define ff_MFGetAttributeRatio ff_MFGetAttributeSize + +// MFTEnumEx was missing from mingw-w64's mfplat import library until +// mingw-w64 v6.0.0, thus wrap it and load it using GetProcAddress. +// It's also missing in Windows Vista's mfplat.dll. +HRESULT ff_MFTEnumEx(GUID guidCategory, UINT32 Flags, + const MFT_REGISTER_TYPE_INFO *pInputType, + const MFT_REGISTER_TYPE_INFO *pOutputType, + IMFActivate ***pppMFTActivate, UINT32 *pnumMFTActivate) +{ + HRESULT (WINAPI *MFTEnumEx_ptr)(GUID guidCategory, UINT32 Flags, + const MFT_REGISTER_TYPE_INFO *pInputType, + const MFT_REGISTER_TYPE_INFO *pOutputType, + IMFActivate ***pppMFTActivate, + UINT32 *pnumMFTActivate) = NULL; +#if !HAVE_UWP + HANDLE lib = GetModuleHandleW(L"mfplat.dll"); + if (lib) + MFTEnumEx_ptr = (void *)GetProcAddress(lib, "MFTEnumEx"); +#else + // In UWP (which lacks GetModuleHandle), just link directly against + // the functions - this requires building with new/complete enough + // import libraries. + MFTEnumEx_ptr = MFTEnumEx; +#endif + if (!MFTEnumEx_ptr) + return E_FAIL; + return MFTEnumEx_ptr(guidCategory, + Flags, + pInputType, + pOutputType, + pppMFTActivate, + pnumMFTActivate); +} + +char *ff_hr_str_buf(char *buf, size_t size, HRESULT hr) +{ +#define HR(x) case x: return (char *) # x; + switch (hr) { + HR(S_OK) + HR(E_UNEXPECTED) + HR(MF_E_INVALIDMEDIATYPE) + HR(MF_E_INVALIDSTREAMNUMBER) + HR(MF_E_INVALIDTYPE) + HR(MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING) + HR(MF_E_TRANSFORM_TYPE_NOT_SET) + HR(MF_E_UNSUPPORTED_D3D_TYPE) + HR(MF_E_TRANSFORM_NEED_MORE_INPUT) + HR(MF_E_TRANSFORM_STREAM_CHANGE) + HR(MF_E_NOTACCEPTING) + HR(MF_E_NO_SAMPLE_TIMESTAMP) + HR(MF_E_NO_SAMPLE_DURATION) +#undef HR + } + snprintf(buf, size, "%x", (unsigned)hr); + return buf; +} + +// If fill_data!=NULL, initialize the buffer and set the length. (This is a +// subtle but important difference: some decoders want CurrentLength==0 on +// provided output buffers.) +IMFSample *ff_create_memory_sample(void *fill_data, size_t size, size_t align) +{ + HRESULT hr; + IMFSample *sample; + IMFMediaBuffer *buffer; + + hr = MFCreateSample(&sample); + if (FAILED(hr)) + return NULL; + + align = FFMAX(align, 16); // 16 is "recommended", even if not required + + hr = MFCreateAlignedMemoryBuffer(size, align - 1, &buffer); + if (FAILED(hr)) + return NULL; + + if (fill_data) { + BYTE *tmp; + + hr = IMFMediaBuffer_Lock(buffer, &tmp, NULL, NULL); + if (FAILED(hr)) { + IMFMediaBuffer_Release(buffer); + IMFSample_Release(sample); + return NULL; + } + memcpy(tmp, fill_data, size); + + IMFMediaBuffer_SetCurrentLength(buffer, size); + IMFMediaBuffer_Unlock(buffer); + } + + IMFSample_AddBuffer(sample, buffer); + IMFMediaBuffer_Release(buffer); + + return sample; +} + +enum AVSampleFormat ff_media_type_to_sample_fmt(IMFAttributes *type) +{ + HRESULT hr; + UINT32 bits; + GUID subtype; + + hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits); + if (FAILED(hr)) + return AV_SAMPLE_FMT_NONE; + + hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &subtype); + if (FAILED(hr)) + return AV_SAMPLE_FMT_NONE; + + if (IsEqualGUID(&subtype, &MFAudioFormat_PCM)) { + switch (bits) { + case 8: return AV_SAMPLE_FMT_U8; + case 16: return AV_SAMPLE_FMT_S16; + case 32: return AV_SAMPLE_FMT_S32; + } + } else if (IsEqualGUID(&subtype, &MFAudioFormat_Float)) { + switch (bits) { + case 32: return AV_SAMPLE_FMT_FLT; + case 64: return AV_SAMPLE_FMT_DBL; + } + } + + return AV_SAMPLE_FMT_NONE; +} + +struct mf_pix_fmt_entry { + const GUID *guid; + enum AVPixelFormat pix_fmt; +}; + +static const struct mf_pix_fmt_entry mf_pix_fmts[] = { + {&MFVideoFormat_IYUV, AV_PIX_FMT_YUV420P}, + {&MFVideoFormat_I420, AV_PIX_FMT_YUV420P}, + {&MFVideoFormat_NV12, AV_PIX_FMT_NV12}, + {&MFVideoFormat_P010, AV_PIX_FMT_P010}, + {&MFVideoFormat_P016, AV_PIX_FMT_P010}, // not equal, but compatible + {&MFVideoFormat_YUY2, AV_PIX_FMT_YUYV422}, +}; + +enum AVPixelFormat ff_media_type_to_pix_fmt(IMFAttributes *type) +{ + HRESULT hr; + GUID subtype; + int i; + + hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &subtype); + if (FAILED(hr)) + return AV_PIX_FMT_NONE; + + for (i = 0; i < FF_ARRAY_ELEMS(mf_pix_fmts); i++) { + if (IsEqualGUID(&subtype, mf_pix_fmts[i].guid)) + return mf_pix_fmts[i].pix_fmt; + } + + return AV_PIX_FMT_NONE; +} + +const GUID *ff_pix_fmt_to_guid(enum AVPixelFormat pix_fmt) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(mf_pix_fmts); i++) { + if (mf_pix_fmts[i].pix_fmt == pix_fmt) + return mf_pix_fmts[i].guid; + } + + return NULL; +} + +// If this GUID is of the form XXXXXXXX-0000-0010-8000-00AA00389B71, then +// extract the XXXXXXXX prefix as FourCC (oh the pain). +int ff_fourcc_from_guid(const GUID *guid, uint32_t *out_fourcc) +{ + if (guid->Data2 == 0 && guid->Data3 == 0x0010 && + guid->Data4[0] == 0x80 && + guid->Data4[1] == 0x00 && + guid->Data4[2] == 0x00 && + guid->Data4[3] == 0xAA && + guid->Data4[4] == 0x00 && + guid->Data4[5] == 0x38 && + guid->Data4[6] == 0x9B && + guid->Data4[7] == 0x71) { + *out_fourcc = guid->Data1; + return 0; + } + + *out_fourcc = 0; + return AVERROR_UNKNOWN; +} + +struct GUID_Entry { + const GUID *guid; + const char *name; +}; + +#define GUID_ENTRY(var) {&(var), # var} + +static struct GUID_Entry guid_names[] = { + GUID_ENTRY(MFT_FRIENDLY_NAME_Attribute), + GUID_ENTRY(MFT_TRANSFORM_CLSID_Attribute), + GUID_ENTRY(MFT_ENUM_HARDWARE_URL_Attribute), + GUID_ENTRY(MFT_CONNECTED_STREAM_ATTRIBUTE), + GUID_ENTRY(MFT_CONNECTED_TO_HW_STREAM), + GUID_ENTRY(MF_SA_D3D_AWARE), + GUID_ENTRY(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT), + GUID_ENTRY(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE), + GUID_ENTRY(ff_MF_SA_D3D11_BINDFLAGS), + GUID_ENTRY(ff_MF_SA_D3D11_USAGE), + GUID_ENTRY(ff_MF_SA_D3D11_AWARE), + GUID_ENTRY(ff_MF_SA_D3D11_SHARED), + GUID_ENTRY(ff_MF_SA_D3D11_SHARED_WITHOUT_MUTEX), + GUID_ENTRY(MF_MT_SUBTYPE), + GUID_ENTRY(MF_MT_MAJOR_TYPE), + GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_SECOND), + GUID_ENTRY(MF_MT_AUDIO_NUM_CHANNELS), + GUID_ENTRY(MF_MT_AUDIO_CHANNEL_MASK), + GUID_ENTRY(MF_MT_FRAME_SIZE), + GUID_ENTRY(MF_MT_INTERLACE_MODE), + GUID_ENTRY(MF_MT_USER_DATA), + GUID_ENTRY(MF_MT_PIXEL_ASPECT_RATIO), + GUID_ENTRY(MFMediaType_Audio), + GUID_ENTRY(MFMediaType_Video), + GUID_ENTRY(MFAudioFormat_PCM), + GUID_ENTRY(MFAudioFormat_Float), + GUID_ENTRY(MFVideoFormat_H264), + GUID_ENTRY(MFVideoFormat_H264_ES), + GUID_ENTRY(ff_MFVideoFormat_HEVC), + GUID_ENTRY(ff_MFVideoFormat_HEVC_ES), + GUID_ENTRY(MFVideoFormat_MPEG2), + GUID_ENTRY(MFVideoFormat_MP43), + GUID_ENTRY(MFVideoFormat_MP4V), + GUID_ENTRY(MFVideoFormat_WMV1), + GUID_ENTRY(MFVideoFormat_WMV2), + GUID_ENTRY(MFVideoFormat_WMV3), + GUID_ENTRY(MFVideoFormat_WVC1), + GUID_ENTRY(MFAudioFormat_Dolby_AC3), + GUID_ENTRY(MFAudioFormat_Dolby_DDPlus), + GUID_ENTRY(MFAudioFormat_AAC), + GUID_ENTRY(MFAudioFormat_MP3), + GUID_ENTRY(MFAudioFormat_MSP1), + GUID_ENTRY(MFAudioFormat_WMAudioV8), + GUID_ENTRY(MFAudioFormat_WMAudioV9), + GUID_ENTRY(MFAudioFormat_WMAudio_Lossless), + GUID_ENTRY(MF_MT_ALL_SAMPLES_INDEPENDENT), + GUID_ENTRY(MF_MT_COMPRESSED), + GUID_ENTRY(MF_MT_FIXED_SIZE_SAMPLES), + GUID_ENTRY(MF_MT_SAMPLE_SIZE), + GUID_ENTRY(MF_MT_WRAPPED_TYPE), + GUID_ENTRY(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION), + GUID_ENTRY(MF_MT_AAC_PAYLOAD_TYPE), + GUID_ENTRY(MF_MT_AUDIO_AVG_BYTES_PER_SECOND), + GUID_ENTRY(MF_MT_AUDIO_BITS_PER_SAMPLE), + GUID_ENTRY(MF_MT_AUDIO_BLOCK_ALIGNMENT), + GUID_ENTRY(MF_MT_AUDIO_CHANNEL_MASK), + GUID_ENTRY(MF_MT_AUDIO_FLOAT_SAMPLES_PER_SECOND), + GUID_ENTRY(MF_MT_AUDIO_FOLDDOWN_MATRIX), + GUID_ENTRY(MF_MT_AUDIO_NUM_CHANNELS), + GUID_ENTRY(MF_MT_AUDIO_PREFER_WAVEFORMATEX), + GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_BLOCK), + GUID_ENTRY(MF_MT_AUDIO_SAMPLES_PER_SECOND), + GUID_ENTRY(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE), + GUID_ENTRY(MF_MT_AUDIO_WMADRC_AVGREF), + GUID_ENTRY(MF_MT_AUDIO_WMADRC_AVGTARGET), + GUID_ENTRY(MF_MT_AUDIO_WMADRC_PEAKREF), + GUID_ENTRY(MF_MT_AUDIO_WMADRC_PEAKTARGET), + GUID_ENTRY(MF_MT_AVG_BIT_ERROR_RATE), + GUID_ENTRY(MF_MT_AVG_BITRATE), + GUID_ENTRY(MF_MT_DEFAULT_STRIDE), + GUID_ENTRY(MF_MT_DRM_FLAGS), + GUID_ENTRY(MF_MT_FRAME_RATE), + GUID_ENTRY(MF_MT_FRAME_RATE_RANGE_MAX), + GUID_ENTRY(MF_MT_FRAME_RATE_RANGE_MIN), + GUID_ENTRY(MF_MT_FRAME_SIZE), + GUID_ENTRY(MF_MT_GEOMETRIC_APERTURE), + GUID_ENTRY(MF_MT_INTERLACE_MODE), + GUID_ENTRY(MF_MT_MAX_KEYFRAME_SPACING), + GUID_ENTRY(MF_MT_MINIMUM_DISPLAY_APERTURE), + GUID_ENTRY(MF_MT_MPEG_SEQUENCE_HEADER), + GUID_ENTRY(MF_MT_MPEG_START_TIME_CODE), + GUID_ENTRY(MF_MT_MPEG2_FLAGS), + GUID_ENTRY(MF_MT_MPEG2_LEVEL), + GUID_ENTRY(MF_MT_MPEG2_PROFILE), + GUID_ENTRY(MF_MT_PAD_CONTROL_FLAGS), + GUID_ENTRY(MF_MT_PALETTE), + GUID_ENTRY(MF_MT_PAN_SCAN_APERTURE), + GUID_ENTRY(MF_MT_PAN_SCAN_ENABLED), + GUID_ENTRY(MF_MT_PIXEL_ASPECT_RATIO), + GUID_ENTRY(MF_MT_SOURCE_CONTENT_HINT), + GUID_ENTRY(MF_MT_TRANSFER_FUNCTION), + GUID_ENTRY(MF_MT_VIDEO_CHROMA_SITING), + GUID_ENTRY(MF_MT_VIDEO_LIGHTING), + GUID_ENTRY(MF_MT_VIDEO_NOMINAL_RANGE), + GUID_ENTRY(MF_MT_VIDEO_PRIMARIES), + GUID_ENTRY(MF_MT_VIDEO_ROTATION), + GUID_ENTRY(MF_MT_YUV_MATRIX), + GUID_ENTRY(ff_CODECAPI_AVDecVideoThumbnailGenerationMode), + GUID_ENTRY(ff_CODECAPI_AVDecVideoDropPicWithMissingRef), + GUID_ENTRY(ff_CODECAPI_AVDecVideoSoftwareDeinterlaceMode), + GUID_ENTRY(ff_CODECAPI_AVDecVideoFastDecodeMode), + GUID_ENTRY(ff_CODECAPI_AVLowLatencyMode), + GUID_ENTRY(ff_CODECAPI_AVDecVideoH264ErrorConcealment), + GUID_ENTRY(ff_CODECAPI_AVDecVideoMPEG2ErrorConcealment), + GUID_ENTRY(ff_CODECAPI_AVDecVideoCodecType), + GUID_ENTRY(ff_CODECAPI_AVDecVideoDXVAMode), + GUID_ENTRY(ff_CODECAPI_AVDecVideoDXVABusEncryption), + GUID_ENTRY(ff_CODECAPI_AVDecVideoSWPowerLevel), + GUID_ENTRY(ff_CODECAPI_AVDecVideoMaxCodedWidth), + GUID_ENTRY(ff_CODECAPI_AVDecVideoMaxCodedHeight), + GUID_ENTRY(ff_CODECAPI_AVDecNumWorkerThreads), + GUID_ENTRY(ff_CODECAPI_AVDecSoftwareDynamicFormatChange), + GUID_ENTRY(ff_CODECAPI_AVDecDisableVideoPostProcessing), +}; + +char *ff_guid_str_buf(char *buf, size_t buf_size, const GUID *guid) +{ + uint32_t fourcc; + int n; + for (n = 0; n < FF_ARRAY_ELEMS(guid_names); n++) { + if (IsEqualGUID(guid, guid_names[n].guid)) { + snprintf(buf, buf_size, "%s", guid_names[n].name); + return buf; + } + } + + if (ff_fourcc_from_guid(guid, &fourcc) >= 0) { + snprintf(buf, buf_size, "", av_fourcc2str(fourcc)); + return buf; + } + + snprintf(buf, buf_size, + "{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}", + (unsigned) guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], + guid->Data4[2], guid->Data4[3], + guid->Data4[4], guid->Data4[5], + guid->Data4[6], guid->Data4[7]); + return buf; +} + +void ff_attributes_dump(void *log, IMFAttributes *attrs) +{ + HRESULT hr; + UINT32 count; + int n; + + hr = IMFAttributes_GetCount(attrs, &count); + if (FAILED(hr)) + return; + + for (n = 0; n < count; n++) { + GUID key; + MF_ATTRIBUTE_TYPE type; + char extra[80] = {0}; + const char *name = NULL; + + hr = IMFAttributes_GetItemByIndex(attrs, n, &key, NULL); + if (FAILED(hr)) + goto err; + + name = ff_guid_str(&key); + + if (IsEqualGUID(&key, &MF_MT_AUDIO_CHANNEL_MASK)) { + UINT32 v; + hr = IMFAttributes_GetUINT32(attrs, &key, &v); + if (FAILED(hr)) + goto err; + snprintf(extra, sizeof(extra), " (0x%x)", (unsigned)v); + } else if (IsEqualGUID(&key, &MF_MT_FRAME_SIZE)) { + UINT32 w, h; + + hr = ff_MFGetAttributeSize(attrs, &MF_MT_FRAME_SIZE, &w, &h); + if (FAILED(hr)) + goto err; + snprintf(extra, sizeof(extra), " (%dx%d)", (int)w, (int)h); + } else if (IsEqualGUID(&key, &MF_MT_PIXEL_ASPECT_RATIO) || + IsEqualGUID(&key, &MF_MT_FRAME_RATE)) { + UINT32 num, den; + + hr = ff_MFGetAttributeRatio(attrs, &key, &num, &den); + if (FAILED(hr)) + goto err; + snprintf(extra, sizeof(extra), " (%d:%d)", (int)num, (int)den); + } + + hr = IMFAttributes_GetItemType(attrs, &key, &type); + if (FAILED(hr)) + goto err; + + switch (type) { + case MF_ATTRIBUTE_UINT32: { + UINT32 v; + hr = IMFAttributes_GetUINT32(attrs, &key, &v); + if (FAILED(hr)) + goto err; + av_log(log, AV_LOG_VERBOSE, " %s=%d%s\n", name, (int)v, extra); + break; + case MF_ATTRIBUTE_UINT64: { + UINT64 v; + hr = IMFAttributes_GetUINT64(attrs, &key, &v); + if (FAILED(hr)) + goto err; + av_log(log, AV_LOG_VERBOSE, " %s=%lld%s\n", name, (long long)v, extra); + break; + } + case MF_ATTRIBUTE_DOUBLE: { + DOUBLE v; + hr = IMFAttributes_GetDouble(attrs, &key, &v); + if (FAILED(hr)) + goto err; + av_log(log, AV_LOG_VERBOSE, " %s=%f%s\n", name, (double)v, extra); + break; + } + case MF_ATTRIBUTE_STRING: { + wchar_t s[512]; // being lazy here + hr = IMFAttributes_GetString(attrs, &key, s, sizeof(s), NULL); + if (FAILED(hr)) + goto err; + av_log(log, AV_LOG_VERBOSE, " %s='%ls'%s\n", name, s, extra); + break; + } + case MF_ATTRIBUTE_GUID: { + GUID v; + hr = IMFAttributes_GetGUID(attrs, &key, &v); + if (FAILED(hr)) + goto err; + av_log(log, AV_LOG_VERBOSE, " %s=%s%s\n", name, ff_guid_str(&v), extra); + break; + } + case MF_ATTRIBUTE_BLOB: { + UINT32 sz; + UINT8 buffer[100]; + hr = IMFAttributes_GetBlobSize(attrs, &key, &sz); + if (FAILED(hr)) + goto err; + if (sz <= sizeof(buffer)) { + // hex-dump it + char str[512] = {0}; + size_t pos = 0; + hr = IMFAttributes_GetBlob(attrs, &key, buffer, sizeof(buffer), &sz); + if (FAILED(hr)) + goto err; + for (pos = 0; pos < sz; pos++) { + const char *hex = "0123456789ABCDEF"; + if (pos * 3 + 3 > sizeof(str)) + break; + str[pos * 3 + 0] = hex[buffer[pos] >> 4]; + str[pos * 3 + 1] = hex[buffer[pos] & 15]; + str[pos * 3 + 2] = ' '; + } + str[pos * 3 + 0] = 0; + av_log(log, AV_LOG_VERBOSE, " %s=%s\n", name, (int)sz, str, extra); + } else { + av_log(log, AV_LOG_VERBOSE, " %s=%s\n", name, (int)sz, extra); + } + break; + } + case MF_ATTRIBUTE_IUNKNOWN: { + av_log(log, AV_LOG_VERBOSE, " %s=%s\n", name, extra); + break; + } + default: + av_log(log, AV_LOG_VERBOSE, " %s=%s\n", name, extra); + break; + } + } + + if (IsEqualGUID(&key, &MF_MT_SUBTYPE)) { + const char *fmt; + fmt = av_get_sample_fmt_name(ff_media_type_to_sample_fmt(attrs)); + if (fmt) + av_log(log, AV_LOG_VERBOSE, " FF-sample-format=%s\n", fmt); + + fmt = av_get_pix_fmt_name(ff_media_type_to_pix_fmt(attrs)); + if (fmt) + av_log(log, AV_LOG_VERBOSE, " FF-pixel-format=%s\n", fmt); + } + + continue; + err: + av_log(log, AV_LOG_VERBOSE, " %s=\n", name ? name : "?"); + } +} + +void ff_media_type_dump(void *log, IMFMediaType *type) +{ + ff_attributes_dump(log, (IMFAttributes *)type); +} + +const CLSID *ff_codec_to_mf_subtype(enum AVCodecID codec) +{ + switch (codec) { + case AV_CODEC_ID_H264: return &MFVideoFormat_H264; + case AV_CODEC_ID_HEVC: return &ff_MFVideoFormat_HEVC; + case AV_CODEC_ID_AC3: return &MFAudioFormat_Dolby_AC3; + case AV_CODEC_ID_AAC: return &MFAudioFormat_AAC; + case AV_CODEC_ID_MP3: return &MFAudioFormat_MP3; + default: return NULL; + } +} + +static int init_com_mf(void *log) +{ + HRESULT hr; + + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if (hr == RPC_E_CHANGED_MODE) { + av_log(log, AV_LOG_ERROR, "COM must not be in STA mode\n"); + return AVERROR(EINVAL); + } else if (FAILED(hr)) { + av_log(log, AV_LOG_ERROR, "could not initialize COM\n"); + return AVERROR(ENOSYS); + } + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + if (FAILED(hr)) { + av_log(log, AV_LOG_ERROR, "could not initialize MediaFoundation\n"); + CoUninitialize(); + return AVERROR(ENOSYS); + } + + return 0; +} + +static void uninit_com_mf(void) +{ + MFShutdown(); + CoUninitialize(); +} + +// Find and create a IMFTransform with the given input/output types. When done, +// you should use ff_free_mf() to destroy it, which will also uninit COM. +int ff_instantiate_mf(void *log, + GUID category, + MFT_REGISTER_TYPE_INFO *in_type, + MFT_REGISTER_TYPE_INFO *out_type, + int use_hw, + IMFTransform **res) +{ + HRESULT hr; + int n; + int ret; + IMFActivate **activate; + UINT32 num_activate; + IMFActivate *winner = 0; + UINT32 flags; + + ret = init_com_mf(log); + if (ret < 0) + return ret; + + flags = MFT_ENUM_FLAG_SORTANDFILTER; + + if (use_hw) { + flags |= MFT_ENUM_FLAG_HARDWARE; + } else { + flags |= MFT_ENUM_FLAG_SYNCMFT; + } + + hr = ff_MFTEnumEx(category, flags, in_type, out_type, &activate, + &num_activate); + if (FAILED(hr)) + goto error_uninit_mf; + + if (log) { + if (!num_activate) + av_log(log, AV_LOG_ERROR, "could not find any MFT for the given media type\n"); + + for (n = 0; n < num_activate; n++) { + av_log(log, AV_LOG_VERBOSE, "MF %d attributes:\n", n); + ff_attributes_dump(log, (IMFAttributes *)activate[n]); + } + } + + *res = NULL; + for (n = 0; n < num_activate; n++) { + if (log) + av_log(log, AV_LOG_VERBOSE, "activate MFT %d\n", n); + hr = IMFActivate_ActivateObject(activate[n], &IID_IMFTransform, + (void **)res); + if (*res) { + winner = activate[n]; + IMFActivate_AddRef(winner); + break; + } + } + + for (n = 0; n < num_activate; n++) + IMFActivate_Release(activate[n]); + CoTaskMemFree(activate); + + if (!*res) { + if (log) + av_log(log, AV_LOG_ERROR, "could not create MFT\n"); + goto error_uninit_mf; + } + + if (log) { + wchar_t s[512]; // being lazy here + IMFAttributes *attrs; + hr = IMFTransform_GetAttributes(*res, &attrs); + if (!FAILED(hr) && attrs) { + + av_log(log, AV_LOG_VERBOSE, "MFT attributes\n"); + ff_attributes_dump(log, attrs); + IMFAttributes_Release(attrs); + } + + hr = IMFActivate_GetString(winner, &MFT_FRIENDLY_NAME_Attribute, s, + sizeof(s), NULL); + if (!FAILED(hr)) + av_log(log, AV_LOG_INFO, "MFT name: '%ls'\n", s); + + } + + IMFActivate_Release(winner); + + return 0; + +error_uninit_mf: + uninit_com_mf(); + return AVERROR(ENOSYS); +} + +void ff_free_mf(IMFTransform **mft) +{ + if (*mft) + IMFTransform_Release(*mft); + *mft = NULL; + uninit_com_mf(); +} diff -Nru ffmpeg-4.2.2/libavcodec/mf_utils.h ffmpeg-4.4/libavcodec/mf_utils.h --- ffmpeg-4.2.2/libavcodec/mf_utils.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mf_utils.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,169 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_MF_UTILS_H +#define AVCODEC_MF_UTILS_H + +#include +#include +#ifdef _MSC_VER +// The official way of including codecapi (via dshow.h) makes the ICodecAPI +// interface unavailable in UWP mode, but including icodecapi.h + codecapi.h +// seems to be equivalent. (These headers conflict with the official way +// of including it though, through strmif.h via dshow.h. And on mingw, the +// mf*.h headers below indirectly include strmif.h.) +#include +#else +#include +// Older versions of mingw-w64 need codecapi.h explicitly included, while newer +// ones include it implicitly from dshow.h (via uuids.h). +#include +#endif +#include +#include +#include +#include + +#include "avcodec.h" + +// These functions do exist in mfapi.h, but are only available within +// __cplusplus ifdefs. +HRESULT ff_MFGetAttributeSize(IMFAttributes *pattr, REFGUID guid, + UINT32 *pw, UINT32 *ph); +HRESULT ff_MFSetAttributeSize(IMFAttributes *pattr, REFGUID guid, + UINT32 uw, UINT32 uh); +#define ff_MFSetAttributeRatio ff_MFSetAttributeSize +#define ff_MFGetAttributeRatio ff_MFGetAttributeSize + +// MFTEnumEx was missing from mingw-w64's mfplat import library until +// mingw-w64 v6.0.0, thus wrap it and load it using GetProcAddress. +// It's also missing in Windows Vista's mfplat.dll. +HRESULT ff_MFTEnumEx(GUID guidCategory, UINT32 Flags, + const MFT_REGISTER_TYPE_INFO *pInputType, + const MFT_REGISTER_TYPE_INFO *pOutputType, + IMFActivate ***pppMFTActivate, UINT32 *pnumMFTActivate); + + +// These do exist in mingw-w64's codecapi.h, but they aren't properly defined +// by the header until after mingw-w64 v7.0.0. +DEFINE_GUID(ff_CODECAPI_AVDecVideoThumbnailGenerationMode, 0x2efd8eee,0x1150,0x4328,0x9c,0xf5,0x66,0xdc,0xe9,0x33,0xfc,0xf4); +DEFINE_GUID(ff_CODECAPI_AVDecVideoDropPicWithMissingRef, 0xf8226383,0x14c2,0x4567,0x97,0x34,0x50,0x04,0xe9,0x6f,0xf8,0x87); +DEFINE_GUID(ff_CODECAPI_AVDecVideoSoftwareDeinterlaceMode, 0x0c08d1ce,0x9ced,0x4540,0xba,0xe3,0xce,0xb3,0x80,0x14,0x11,0x09); +DEFINE_GUID(ff_CODECAPI_AVDecVideoFastDecodeMode, 0x6b529f7d,0xd3b1,0x49c6,0xa9,0x99,0x9e,0xc6,0x91,0x1b,0xed,0xbf); +DEFINE_GUID(ff_CODECAPI_AVLowLatencyMode, 0x9c27891a,0xed7a,0x40e1,0x88,0xe8,0xb2,0x27,0x27,0xa0,0x24,0xee); +DEFINE_GUID(ff_CODECAPI_AVDecVideoH264ErrorConcealment, 0xececace8,0x3436,0x462c,0x92,0x94,0xcd,0x7b,0xac,0xd7,0x58,0xa9); +DEFINE_GUID(ff_CODECAPI_AVDecVideoMPEG2ErrorConcealment, 0x9d2bfe18,0x728d,0x48d2,0xb3,0x58,0xbc,0x7e,0x43,0x6c,0x66,0x74); +DEFINE_GUID(ff_CODECAPI_AVDecVideoCodecType, 0x434528e5,0x21f0,0x46b6,0xb6,0x2c,0x9b,0x1b,0x6b,0x65,0x8c,0xd1); +DEFINE_GUID(ff_CODECAPI_AVDecVideoDXVAMode, 0xf758f09e,0x7337,0x4ae7,0x83,0x87,0x73,0xdc,0x2d,0x54,0xe6,0x7d); +DEFINE_GUID(ff_CODECAPI_AVDecVideoDXVABusEncryption, 0x42153c8b,0xfd0b,0x4765,0xa4,0x62,0xdd,0xd9,0xe8,0xbc,0xc3,0x88); +DEFINE_GUID(ff_CODECAPI_AVDecVideoSWPowerLevel, 0xfb5d2347,0x4dd8,0x4509,0xae,0xd0,0xdb,0x5f,0xa9,0xaa,0x93,0xf4); +DEFINE_GUID(ff_CODECAPI_AVDecVideoMaxCodedWidth, 0x5ae557b8,0x77af,0x41f5,0x9f,0xa6,0x4d,0xb2,0xfe,0x1d,0x4b,0xca); +DEFINE_GUID(ff_CODECAPI_AVDecVideoMaxCodedHeight, 0x7262a16a,0xd2dc,0x4e75,0x9b,0xa8,0x65,0xc0,0xc6,0xd3,0x2b,0x13); +DEFINE_GUID(ff_CODECAPI_AVDecNumWorkerThreads, 0x9561c3e8,0xea9e,0x4435,0x9b,0x1e,0xa9,0x3e,0x69,0x18,0x94,0xd8); +DEFINE_GUID(ff_CODECAPI_AVDecSoftwareDynamicFormatChange, 0x862e2f0a,0x507b,0x47ff,0xaf,0x47,0x01,0xe2,0x62,0x42,0x98,0xb7); +DEFINE_GUID(ff_CODECAPI_AVDecDisableVideoPostProcessing, 0xf8749193,0x667a,0x4f2c,0xa9,0xe8,0x5d,0x4a,0xf9,0x24,0xf0,0x8f); + +// These are missing from mingw-w64's headers until after mingw-w64 v7.0.0. +DEFINE_GUID(ff_CODECAPI_AVEncCommonRateControlMode, 0x1c0608e9, 0x370c, 0x4710, 0x8a, 0x58, 0xcb, 0x61, 0x81, 0xc4, 0x24, 0x23); +DEFINE_GUID(ff_CODECAPI_AVEncCommonQuality, 0xfcbf57a3, 0x7ea5, 0x4b0c, 0x96, 0x44, 0x69, 0xb4, 0x0c, 0x39, 0xc3, 0x91); +DEFINE_GUID(ff_CODECAPI_AVEncCommonMeanBitRate, 0xf7222374, 0x2144, 0x4815, 0xb5, 0x50, 0xa3, 0x7f, 0x8e, 0x12, 0xee, 0x52); +DEFINE_GUID(ff_CODECAPI_AVEncH264CABACEnable, 0xee6cad62, 0xd305, 0x4248, 0xa5, 0xe, 0xe1, 0xb2, 0x55, 0xf7, 0xca, 0xf8); +DEFINE_GUID(ff_CODECAPI_AVEncVideoForceKeyFrame, 0x398c1b98, 0x8353, 0x475a, 0x9e, 0xf2, 0x8f, 0x26, 0x5d, 0x26, 0x3, 0x45); +DEFINE_GUID(ff_CODECAPI_AVEncMPVDefaultBPictureCount, 0x8d390aac, 0xdc5c, 0x4200, 0xb5, 0x7f, 0x81, 0x4d, 0x04, 0xba, 0xba, 0xb2); +DEFINE_GUID(ff_CODECAPI_AVScenarioInfo, 0xb28a6e64,0x3ff9,0x446a,0x8a,0x4b,0x0d,0x7a,0x53,0x41,0x32,0x36); + +DEFINE_GUID(ff_MF_SA_D3D11_BINDFLAGS, 0xeacf97ad, 0x065c, 0x4408, 0xbe, 0xe3, 0xfd, 0xcb, 0xfd, 0x12, 0x8b, 0xe2); +DEFINE_GUID(ff_MF_SA_D3D11_USAGE, 0xe85fe442, 0x2ca3, 0x486e, 0xa9, 0xc7, 0x10, 0x9d, 0xda, 0x60, 0x98, 0x80); +DEFINE_GUID(ff_MF_SA_D3D11_AWARE, 0x206b4fc8, 0xfcf9, 0x4c51, 0xaf, 0xe3, 0x97, 0x64, 0x36, 0x9e, 0x33, 0xa0); +DEFINE_GUID(ff_MF_SA_D3D11_SHARED, 0x7b8f32c3, 0x6d96, 0x4b89, 0x92, 0x3, 0xdd, 0x38, 0xb6, 0x14, 0x14, 0xf3); +DEFINE_GUID(ff_MF_SA_D3D11_SHARED_WITHOUT_MUTEX, 0x39dbd44d, 0x2e44, 0x4931, 0xa4, 0xc8, 0x35, 0x2d, 0x3d, 0xc4, 0x21, 0x15); +DEFINE_GUID(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT, 0x851745d5, 0xc3d6, 0x476d, 0x95, 0x27, 0x49, 0x8e, 0xf2, 0xd1, 0xd, 0x18); +DEFINE_GUID(ff_MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE, 0xf5523a5, 0x1cb2, 0x47c5, 0xa5, 0x50, 0x2e, 0xeb, 0x84, 0xb4, 0xd1, 0x4a); + +DEFINE_MEDIATYPE_GUID(ff_MFVideoFormat_HEVC, 0x43564548); // FCC('HEVC') +DEFINE_MEDIATYPE_GUID(ff_MFVideoFormat_HEVC_ES, 0x53564548); // FCC('HEVS') + + +// This enum is missing from mingw-w64's codecapi.h by v7.0.0. +enum ff_eAVEncCommonRateControlMode { + ff_eAVEncCommonRateControlMode_CBR = 0, + ff_eAVEncCommonRateControlMode_PeakConstrainedVBR = 1, + ff_eAVEncCommonRateControlMode_UnconstrainedVBR = 2, + ff_eAVEncCommonRateControlMode_Quality = 3, + ff_eAVEncCommonRateControlMode_LowDelayVBR = 4, + ff_eAVEncCommonRateControlMode_GlobalVBR = 5, + ff_eAVEncCommonRateControlMode_GlobalLowDelayVBR = 6 +}; + +enum ff_eAVScenarioInfo { + ff_eAVScenarioInfo_Unknown = 0, + ff_eAVScenarioInfo_DisplayRemoting = 1, + ff_eAVScenarioInfo_VideoConference = 2, + ff_eAVScenarioInfo_Archive = 3, + ff_eAVScenarioInfo_LiveStreaming = 4, + ff_eAVScenarioInfo_CameraRecord = 5, + ff_eAVScenarioInfo_DisplayRemotingWithFeatureMap = 6 +}; + +// These do exist in mingw-w64's mfobjects.idl, but are missing from +// mfobjects.h that is generated from the former, due to incorrect use of +// ifdefs in the IDL file. +enum { + ff_METransformUnknown = 600, + ff_METransformNeedInput, + ff_METransformHaveOutput, + ff_METransformDrainComplete, + ff_METransformMarker, +}; + +// These do exist in all supported headers, but are manually defined here +// to avoid having to include codecapi.h, as there's problems including that +// header when targeting UWP (where including it with MSVC seems to work, +// but fails when built with clang in MSVC mode). +enum ff_eAVEncH264VProfile { + ff_eAVEncH264VProfile_Base = 66, + ff_eAVEncH264VProfile_Main = 77, + ff_eAVEncH264VProfile_High = 100, +}; + +char *ff_hr_str_buf(char *buf, size_t size, HRESULT hr); +#define ff_hr_str(hr) ff_hr_str_buf((char[80]){0}, 80, hr) + +// Possibly compiler-dependent; the MS/MinGW definition for this is just crazy. +#define FF_VARIANT_VALUE(type, contents) &(VARIANT){ .vt = (type), contents } + +#define FF_VAL_VT_UI4(v) FF_VARIANT_VALUE(VT_UI4, .ulVal = (v)) +#define FF_VAL_VT_BOOL(v) FF_VARIANT_VALUE(VT_BOOL, .boolVal = (v)) + +IMFSample *ff_create_memory_sample(void *fill_data, size_t size, size_t align); +enum AVSampleFormat ff_media_type_to_sample_fmt(IMFAttributes *type); +enum AVPixelFormat ff_media_type_to_pix_fmt(IMFAttributes *type); +const GUID *ff_pix_fmt_to_guid(enum AVPixelFormat pix_fmt); +int ff_fourcc_from_guid(const GUID *guid, uint32_t *out_fourcc); +char *ff_guid_str_buf(char *buf, size_t buf_size, const GUID *guid); +#define ff_guid_str(guid) ff_guid_str_buf((char[80]){0}, 80, guid) +void ff_attributes_dump(void *log, IMFAttributes *attrs); +void ff_media_type_dump(void *log, IMFMediaType *type); +const CLSID *ff_codec_to_mf_subtype(enum AVCodecID codec); +int ff_instantiate_mf(void *log, GUID category, + MFT_REGISTER_TYPE_INFO *in_type, + MFT_REGISTER_TYPE_INFO *out_type, + int use_hw, IMFTransform **res); +void ff_free_mf(IMFTransform **mft); + +#endif diff -Nru ffmpeg-4.2.2/libavcodec/midivid.c ffmpeg-4.4/libavcodec/midivid.c --- ffmpeg-4.2.2/libavcodec/midivid.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/midivid.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,292 @@ +/* + * MidiVid decoder + * Copyright (c) 2019 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 + +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" + +#define BITSTREAM_READER_LE +#include "avcodec.h" +#include "get_bits.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct MidiVidContext { + GetByteContext gb; + + uint8_t *uncompressed; + unsigned int uncompressed_size; + uint8_t *skip; + + AVFrame *frame; +} MidiVidContext; + +static int decode_mvdv(MidiVidContext *s, AVCodecContext *avctx, AVFrame *frame) +{ + GetByteContext *gb = &s->gb; + GetBitContext mask; + GetByteContext idx9; + uint16_t nb_vectors, intra_flag; + const uint8_t *vec; + const uint8_t *mask_start; + uint8_t *skip; + uint32_t mask_size; + int idx9bits = 0; + int idx9val = 0; + uint32_t nb_blocks; + + nb_vectors = bytestream2_get_le16(gb); + intra_flag = !!bytestream2_get_le16(gb); + if (intra_flag) { + nb_blocks = (avctx->width / 2) * (avctx->height / 2); + } else { + int ret, skip_linesize, padding; + + nb_blocks = bytestream2_get_le32(gb); + skip_linesize = avctx->width >> 1; + mask_start = gb->buffer_start + bytestream2_tell(gb); + mask_size = (FFALIGN(avctx->width, 32) >> 2) * (avctx->height >> 2) >> 3; + padding = (FFALIGN(avctx->width, 32) - avctx->width) >> 2; + + if (bytestream2_get_bytes_left(gb) < mask_size) + return AVERROR_INVALIDDATA; + + ret = init_get_bits8(&mask, mask_start, mask_size); + if (ret < 0) + return ret; + bytestream2_skip(gb, mask_size); + skip = s->skip; + + for (int y = 0; y < avctx->height >> 2; y++) { + for (int x = 0; x < avctx->width >> 2; x++) { + int flag = !get_bits1(&mask); + + skip[(y*2) *skip_linesize + x*2 ] = flag; + skip[(y*2) *skip_linesize + x*2+1] = flag; + skip[(y*2+1)*skip_linesize + x*2 ] = flag; + skip[(y*2+1)*skip_linesize + x*2+1] = flag; + } + skip_bits_long(&mask, padding); + } + } + + vec = gb->buffer_start + bytestream2_tell(gb); + if (bytestream2_get_bytes_left(gb) < nb_vectors * 12) + return AVERROR_INVALIDDATA; + bytestream2_skip(gb, nb_vectors * 12); + if (nb_vectors > 256) { + if (bytestream2_get_bytes_left(gb) < (nb_blocks + 7 * !intra_flag) / 8) + return AVERROR_INVALIDDATA; + bytestream2_init(&idx9, gb->buffer_start + bytestream2_tell(gb), (nb_blocks + 7 * !intra_flag) / 8); + bytestream2_skip(gb, (nb_blocks + 7 * !intra_flag) / 8); + } + + skip = s->skip; + + for (int y = avctx->height - 2; y >= 0; y -= 2) { + uint8_t *dsty = frame->data[0] + y * frame->linesize[0]; + uint8_t *dstu = frame->data[1] + y * frame->linesize[1]; + uint8_t *dstv = frame->data[2] + y * frame->linesize[2]; + + for (int x = 0; x < avctx->width; x += 2) { + int idx; + + if (!intra_flag && *skip++) + continue; + if (bytestream2_get_bytes_left(gb) <= 0) + return AVERROR_INVALIDDATA; + if (nb_vectors <= 256) { + idx = bytestream2_get_byte(gb); + } else { + if (idx9bits == 0) { + idx9val = bytestream2_get_byte(&idx9); + idx9bits = 8; + } + idx9bits--; + idx = bytestream2_get_byte(gb) | (((idx9val >> (7 - idx9bits)) & 1) << 8); + } + if (idx >= nb_vectors) + return AVERROR_INVALIDDATA; + + dsty[x +frame->linesize[0]] = vec[idx * 12 + 0]; + dsty[x+1+frame->linesize[0]] = vec[idx * 12 + 3]; + dsty[x] = vec[idx * 12 + 6]; + dsty[x+1] = vec[idx * 12 + 9]; + + dstu[x +frame->linesize[1]] = vec[idx * 12 + 1]; + dstu[x+1+frame->linesize[1]] = vec[idx * 12 + 4]; + dstu[x] = vec[idx * 12 + 7]; + dstu[x+1] = vec[idx * 12 +10]; + + dstv[x +frame->linesize[2]] = vec[idx * 12 + 2]; + dstv[x+1+frame->linesize[2]] = vec[idx * 12 + 5]; + dstv[x] = vec[idx * 12 + 8]; + dstv[x+1] = vec[idx * 12 +11]; + } + } + + return intra_flag; +} + +static ptrdiff_t lzss_uncompress(MidiVidContext *s, GetByteContext *gb, uint8_t *dst, unsigned int size) +{ + uint8_t *dst_start = dst; + uint8_t *dst_end = dst + size; + + for (;bytestream2_get_bytes_left(gb) >= 3;) { + int op = bytestream2_get_le16(gb); + + for (int i = 0; i < 16; i++) { + if (op & 1) { + int s0 = bytestream2_get_byte(gb); + int s1 = bytestream2_get_byte(gb); + int offset = ((s0 & 0xF0) << 4) | s1; + int length = (s0 & 0xF) + 3; + + if (dst + length > dst_end || + dst - offset < dst_start) + return AVERROR_INVALIDDATA; + if (offset > 0) { + for (int j = 0; j < length; j++) { + dst[j] = dst[j - offset]; + } + } + dst += length; + } else { + if (dst >= dst_end) + return AVERROR_INVALIDDATA; + *dst++ = bytestream2_get_byte(gb); + } + op >>= 1; + } + } + + return dst - dst_start; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + MidiVidContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + AVFrame *frame = s->frame; + int ret, key, uncompressed; + + if (avpkt->size <= 13) + return AVERROR_INVALIDDATA; + + bytestream2_init(gb, avpkt->data, avpkt->size); + bytestream2_skip(gb, 8); + uncompressed = bytestream2_get_le32(gb); + + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) + return ret; + + if (uncompressed) { + ret = decode_mvdv(s, avctx, frame); + } else { + av_fast_padded_malloc(&s->uncompressed, &s->uncompressed_size, 16LL * (avpkt->size - 12)); + if (!s->uncompressed) + return AVERROR(ENOMEM); + + ret = lzss_uncompress(s, gb, s->uncompressed, s->uncompressed_size); + if (ret < 0) + return ret; + bytestream2_init(gb, s->uncompressed, ret); + ret = decode_mvdv(s, avctx, frame); + } + + if (ret < 0) + return ret; + key = ret; + + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; + + frame->pict_type = key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + frame->key_frame = key; + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + MidiVidContext *s = avctx->priv_data; + int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx); + + if (avctx->width & 3 || avctx->height & 3) + ret = AVERROR_INVALIDDATA; + + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid image size %dx%d.\n", + avctx->width, avctx->height); + return ret; + } + + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + s->skip = av_calloc(avctx->width >> 1, avctx->height >> 1); + if (!s->skip) + return AVERROR(ENOMEM); + + return 0; +} + +static void decode_flush(AVCodecContext *avctx) +{ + MidiVidContext *s = avctx->priv_data; + + av_frame_unref(s->frame); +} + +static av_cold int decode_close(AVCodecContext *avctx) +{ + MidiVidContext *s = avctx->priv_data; + + av_frame_free(&s->frame); + av_freep(&s->uncompressed); + av_freep(&s->skip); + + return 0; +} + +AVCodec ff_mvdv_decoder = { + .name = "mvdv", + .long_name = NULL_IF_CONFIG_SMALL("MidiVid VQ"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MVDV, + .priv_data_size = sizeof(MidiVidContext), + .init = decode_init, + .decode = decode_frame, + .flush = decode_flush, + .close = decode_close, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +}; diff -Nru ffmpeg-4.2.2/libavcodec/mimic.c ffmpeg-4.4/libavcodec/mimic.c --- ffmpeg-4.2.2/libavcodec/mimic.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mimic.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,9 @@ #include #include +#include "libavutil/mem_internal.h" +#include "libavutil/thread.h" + #include "avcodec.h" #include "blockdsp.h" #include "internal.h" @@ -34,6 +37,7 @@ #include "thread.h" #define MIMIC_HEADER_SIZE 20 +#define MIMIC_VLC_BITS 11 typedef struct MimicContext { AVCodecContext *avctx; @@ -57,50 +61,33 @@ BswapDSPContext bbdsp; HpelDSPContext hdsp; IDCTDSPContext idsp; - VLC vlc; /* Kept in the context so multithreading can have a constant to read from */ int next_cur_index; int next_prev_index; } MimicContext; -static const uint32_t huffcodes[] = { - 0x0000000a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000b, - 0x0000001b, 0x00000038, 0x00000078, 0x00000079, 0x0000007a, 0x000000f9, - 0x000000fa, 0x000003fb, 0x000007f8, 0x000007f9, 0x000007fa, 0x000007fb, - 0x00000ff8, 0x00000ff9, 0x00000001, 0x00000039, 0x0000007b, 0x000000fb, - 0x000001f8, 0x000001f9, 0x00000ffa, 0x00000ffb, 0x00001ff8, 0x00001ff9, - 0x00001ffa, 0x00001ffb, 0x00003ff8, 0x00003ff9, 0x00003ffa, 0x00000000, - 0x00000004, 0x0000003a, 0x000001fa, 0x00003ffb, 0x00007ff8, 0x00007ff9, - 0x00007ffa, 0x00007ffb, 0x0000fff8, 0x0000fff9, 0x0000fffa, 0x0000fffb, - 0x0001fff8, 0x0001fff9, 0x0001fffa, 0x00000000, 0x0000000c, 0x000000f8, - 0x000001fb, 0x0001fffb, 0x0003fff8, 0x0003fff9, 0x0003fffa, 0x0003fffb, - 0x0007fff8, 0x0007fff9, 0x0007fffa, 0x0007fffb, 0x000ffff8, 0x000ffff9, - 0x000ffffa, 0x00000000, 0x0000001a, 0x000003f8, 0x000ffffb, 0x001ffff8, - 0x001ffff9, 0x001ffffa, 0x001ffffb, 0x003ffff8, 0x003ffff9, 0x003ffffa, - 0x003ffffb, 0x007ffff8, 0x007ffff9, 0x007ffffa, 0x007ffffb, 0x00000000, - 0x0000003b, 0x000003f9, 0x00fffff8, 0x00fffff9, 0x00fffffa, 0x00fffffb, - 0x01fffff8, 0x01fffff9, 0x01fffffa, 0x01fffffb, 0x03fffff8, 0x03fffff9, - 0x03fffffa, 0x03fffffb, 0x07fffff8, 0x00000000, 0x000003fa, 0x07fffff9, - 0x07fffffa, 0x07fffffb, 0x0ffffff8, 0x0ffffff9, 0x0ffffffa, 0x0ffffffb, - 0x1ffffff8, 0x1ffffff9, 0x1ffffffa, 0x1ffffffb, 0x3ffffff8, 0x3ffffff9, - 0x3ffffffa, +static VLC block_vlc; + +static const uint8_t huffsyms[] = { + 0x10, 0x20, 0x30, 0x00, 0x11, 0x40, 0x50, 0x12, 0x13, 0x21, 0x31, 0x60, + 0x14, 0x15, 0x16, 0x22, 0x41, 0x17, 0x18, 0x23, 0x24, 0x25, 0x32, 0x42, + 0x51, 0x61, 0x70, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x52, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x62, 0x63, 0x64, 0x65, + 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x71, 0x72, 0x73, + 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, }; static const uint8_t huffbits[] = { - 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 4, 5, 6, 7, 7, 7, 8, - 8, 10, 11, 11, 11, 11, 12, 12, 2, 6, 7, 8, - 9, 9, 12, 12, 13, 13, 13, 13, 14, 14, 14, 0, - 3, 6, 9, 14, 15, 15, 15, 15, 16, 16, 16, 16, - 17, 17, 17, 0, 4, 8, 9, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 0, 5, 10, 20, 21, - 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 0, - 6, 10, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, - 26, 26, 27, 0, 10, 27, 27, 27, 28, 28, 28, 28, - 29, 29, 29, 29, 30, 30, 30, + 2, 2, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, + 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, + 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, + 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, + 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, + 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, }; static const uint8_t col_zag[64] = { @@ -128,27 +115,24 @@ av_frame_free(&ctx->frames[i].f); } - if (!avctx->internal->is_copy) - ff_free_vlc(&ctx->vlc); - return 0; } +static av_cold void mimic_init_static(void) +{ + INIT_VLC_STATIC_FROM_LENGTHS(&block_vlc, MIMIC_VLC_BITS, FF_ARRAY_ELEMS(huffbits), + huffbits, 1, huffsyms, 1, 1, 0, 0, 4368); +} + static av_cold int mimic_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; MimicContext *ctx = avctx->priv_data; - int ret, i; - - avctx->internal->allocate_progress = 1; + int i; ctx->prev_index = 0; ctx->cur_index = 15; - if ((ret = init_vlc(&ctx->vlc, 11, FF_ARRAY_ELEMS(huffbits), - huffbits, 1, 1, huffcodes, 4, 4, 0)) < 0) { - av_log(avctx, AV_LOG_ERROR, "error initializing vlc table\n"); - return ret; - } ff_blockdsp_init(&ctx->bdsp, avctx); ff_bswapdsp_init(&ctx->bbdsp); ff_hpeldsp_init(&ctx->hdsp, avctx->flags); @@ -157,12 +141,12 @@ for (i = 0; i < FF_ARRAY_ELEMS(ctx->frames); i++) { ctx->frames[i].f = av_frame_alloc(); - if (!ctx->frames[i].f) { - mimic_decode_end(avctx); + if (!ctx->frames[i].f) return AVERROR(ENOMEM); - } } + ff_thread_once(&init_static_once, mimic_init_static); + return 0; } @@ -242,7 +226,7 @@ int value; int coeff; - vlc = get_vlc2(&ctx->gb, ctx->vlc.table, ctx->vlc.bits, 3); + vlc = get_vlc2(&ctx->gb, block_vlc.table, MIMIC_VLC_BITS, 3); if (!vlc) /* end-of-block code */ return 0; if (vlc == -1) @@ -451,24 +435,6 @@ return buf_size; } -#if HAVE_THREADS -static av_cold int mimic_init_thread_copy(AVCodecContext *avctx) -{ - MimicContext *ctx = avctx->priv_data; - int i; - - for (i = 0; i < FF_ARRAY_ELEMS(ctx->frames); i++) { - ctx->frames[i].f = av_frame_alloc(); - if (!ctx->frames[i].f) { - mimic_decode_end(avctx); - return AVERROR(ENOMEM); - } - } - - return 0; -} -#endif - AVCodec ff_mimic_decoder = { .name = "mimic", .long_name = NULL_IF_CONFIG_SMALL("Mimic"), @@ -480,5 +446,6 @@ .decode = mimic_decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .update_thread_context = ONLY_IF_THREADS_ENABLED(mimic_decode_update_thread_context), - .init_thread_copy = ONLY_IF_THREADS_ENABLED(mimic_init_thread_copy), + .caps_internal = FF_CODEC_CAP_ALLOCATE_PROGRESS | + FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/mips/aacdec_mips.c ffmpeg-4.4/libavcodec/mips/aacdec_mips.c --- ffmpeg-4.2.2/libavcodec/mips/aacdec_mips.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/aacdec_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -59,6 +59,7 @@ #include "libavutil/mips/asmdefs.h" #if HAVE_INLINE_ASM +#if HAVE_MIPSFPU static av_always_inline void float_copy(float *dst, const float *src, int count) { // Copy 'count' floats from src to dst @@ -237,9 +238,9 @@ if (ltp->lag < 1024) num_samples = ltp->lag + 1024; - j = (2048 - num_samples) >> 2; - k = (2048 - num_samples) & 3; - p_predTime = &predTime[num_samples]; + j = (2048 - num_samples) >> 2; + k = (2048 - num_samples) & 3; + p_predTime = &predTime[num_samples]; for (i = 0; i < num_samples; i++) predTime[i] = sce->ltp_state[i + 2048 - ltp->lag] * ltp->coef; @@ -282,7 +283,6 @@ } } -#if HAVE_MIPSFPU static av_always_inline void fmul_and_reverse(float *dst, const float *src0, const float *src1, int count) { /* Multiply 'count' floats in src0 by src1 and store the results in dst in reverse */ @@ -340,7 +340,7 @@ float *saved_ltp = sce->coeffs; const float *lwindow = ics->use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024; const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128; - float temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) { float *p_saved_ltp = saved_ltp + 576; @@ -433,9 +433,9 @@ void ff_aacdec_init_mips(AACContext *c) { #if HAVE_INLINE_ASM +#if HAVE_MIPSFPU c->imdct_and_windowing = imdct_and_windowing_mips; c->apply_ltp = apply_ltp_mips; -#if HAVE_MIPSFPU c->update_ltp = update_ltp_mips; #endif /* HAVE_MIPSFPU */ #endif /* HAVE_INLINE_ASM */ diff -Nru ffmpeg-4.2.2/libavcodec/mips/aacpsdsp_mips.c ffmpeg-4.4/libavcodec/mips/aacpsdsp_mips.c --- ffmpeg-4.2.2/libavcodec/mips/aacpsdsp_mips.c 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/aacpsdsp_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -57,6 +57,7 @@ #include "libavutil/mips/asmdefs.h" #if HAVE_INLINE_ASM +#if HAVE_MIPSFPU static void ps_hybrid_analysis_ileave_mips(float (*out)[32][2], float L[2][38][64], int i, int len) { @@ -187,7 +188,6 @@ } } -#if HAVE_MIPSFPU #if !HAVE_MIPS32R6 && !HAVE_MIPS64R6 static void ps_add_squares_mips(float *dst, const float (*src)[2], int n) { @@ -293,16 +293,17 @@ float phi_fract0 = phi_fract[0]; float phi_fract1 = phi_fract[1]; float temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; + float f1, f2, f3; float *p_delay_end = (p_delay + (len << 1)); /* merged 2 loops */ + f1 = 0.65143905753106; + f2 = 0.56471812200776; + f3 = 0.48954165955695; __asm__ volatile( ".set push \n\t" ".set noreorder \n\t" - "li.s %[ag0], 0.65143905753106 \n\t" - "li.s %[ag1], 0.56471812200776 \n\t" - "li.s %[ag2], 0.48954165955695 \n\t" "mul.s %[ag0], %[ag0], %[g_decay_slope] \n\t" "mul.s %[ag1], %[ag1], %[g_decay_slope] \n\t" "mul.s %[ag2], %[ag2], %[g_decay_slope] \n\t" @@ -378,10 +379,10 @@ [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), [temp8]"=&f"(temp8), [temp9]"=&f"(temp9), [p_delay]"+r"(p_delay), [p_ap_delay]"+r"(p_ap_delay), - [p_Q_fract]"+r"(p_Q_fract), [p_t_gain]"+r"(p_t_gain), [p_out]"+r"(p_out), - [ag0]"=&f"(ag0), [ag1]"=&f"(ag1), [ag2]"=&f"(ag2) + [p_Q_fract]"+r"(p_Q_fract), [p_t_gain]"+r"(p_t_gain), [p_out]"+r"(p_out) : [phi_fract0]"f"(phi_fract0), [phi_fract1]"f"(phi_fract1), - [p_delay_end]"r"(p_delay_end), [g_decay_slope]"f"(g_decay_slope) + [p_delay_end]"r"(p_delay_end), [g_decay_slope]"f"(g_decay_slope), + [ag0]"f"(f1), [ag1]"f"(f2), [ag2]"f"(f3) : "memory" ); } @@ -450,9 +451,9 @@ void ff_psdsp_init_mips(PSDSPContext *s) { #if HAVE_INLINE_ASM +#if HAVE_MIPSFPU s->hybrid_analysis_ileave = ps_hybrid_analysis_ileave_mips; s->hybrid_synthesis_deint = ps_hybrid_synthesis_deint_mips; -#if HAVE_MIPSFPU #if !HAVE_MIPS32R6 && !HAVE_MIPS64R6 s->add_squares = ps_add_squares_mips; s->mul_pair_single = ps_mul_pair_single_mips; diff -Nru ffmpeg-4.2.2/libavcodec/mips/aacpsy_mips.h ffmpeg-4.4/libavcodec/mips/aacpsy_mips.h --- ffmpeg-4.2.2/libavcodec/mips/aacpsy_mips.h 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/aacpsy_mips.h 2021-04-08 21:28:39.000000000 +0000 @@ -135,11 +135,11 @@ float coeff3 = psy_fir_coeffs[7]; float coeff4 = psy_fir_coeffs[9]; + float f1 = 32768.0; __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" - "li.s $f12, 32768 \n\t" "1: \n\t" "lwc1 $f0, 40(%[fb]) \n\t" "lwc1 $f1, 4(%[fb]) \n\t" @@ -203,14 +203,14 @@ "madd.s %[sum2], %[sum2], $f9, %[coeff4] \n\t" "madd.s %[sum4], %[sum4], $f6, %[coeff4] \n\t" "madd.s %[sum3], %[sum3], $f3, %[coeff4] \n\t" - "mul.s %[sum1], %[sum1], $f12 \n\t" - "mul.s %[sum2], %[sum2], $f12 \n\t" + "mul.s %[sum1], %[sum1], %[f1] \n\t" + "mul.s %[sum2], %[sum2], %[f1] \n\t" "madd.s %[sum4], %[sum4], $f11, %[coeff4] \n\t" "madd.s %[sum3], %[sum3], $f8, %[coeff4] \n\t" "swc1 %[sum1], 0(%[hp]) \n\t" "swc1 %[sum2], 4(%[hp]) \n\t" - "mul.s %[sum4], %[sum4], $f12 \n\t" - "mul.s %[sum3], %[sum3], $f12 \n\t" + "mul.s %[sum4], %[sum4], %[f1] \n\t" + "mul.s %[sum3], %[sum3], %[f1] \n\t" "swc1 %[sum4], 12(%[hp]) \n\t" "swc1 %[sum3], 8(%[hp]) \n\t" "bne %[fb], %[fb_end], 1b \n\t" @@ -223,9 +223,9 @@ [fb]"+r"(fb), [hp]"+r"(hp) : [coeff0]"f"(coeff0), [coeff1]"f"(coeff1), [coeff2]"f"(coeff2), [coeff3]"f"(coeff3), - [coeff4]"f"(coeff4), [fb_end]"r"(fb_end) + [coeff4]"f"(coeff4), [fb_end]"r"(fb_end), [f1]"f"(f1) : "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", - "$f7", "$f8", "$f9", "$f10", "$f11", "$f12", + "$f7", "$f8", "$f9", "$f10", "$f11", "memory" ); } diff -Nru ffmpeg-4.2.2/libavcodec/mips/aacsbr_mips.c ffmpeg-4.4/libavcodec/mips/aacsbr_mips.c --- ffmpeg-4.2.2/libavcodec/mips/aacsbr_mips.c 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/aacsbr_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -53,11 +53,13 @@ #include "libavcodec/aac.h" #include "libavcodec/aacsbr.h" +#include "libavutil/mem_internal.h" #include "libavutil/mips/asmdefs.h" #define ENVELOPE_ADJUSTMENT_OFFSET 2 #if HAVE_INLINE_ASM +#if HAVE_MIPSFPU static int sbr_lf_gen_mips(AACContext *ac, SpectralBandReplication *sbr, float X_low[32][40][2], const float W[2][32][32][2], int buf_idx) @@ -310,7 +312,6 @@ return 0; } -#if HAVE_MIPSFPU #if !HAVE_MIPS32R6 && !HAVE_MIPS64R6 static void sbr_hf_assemble_mips(float Y1[38][64][2], const float X_high[64][40][2], @@ -333,7 +334,7 @@ int indexnoise = ch_data->f_indexnoise; int indexsine = ch_data->f_indexsine; float *g_temp1, *q_temp1, *pok, *pok1; - float temp1, temp2, temp3, temp4; + uint32_t temp1, temp2, temp3, temp4; int size = m_max; if (sbr->reset) { @@ -611,9 +612,9 @@ void ff_aacsbr_func_ptr_init_mips(AACSBRContext *c) { #if HAVE_INLINE_ASM +#if HAVE_MIPSFPU c->sbr_lf_gen = sbr_lf_gen_mips; c->sbr_x_gen = sbr_x_gen_mips; -#if HAVE_MIPSFPU #if !HAVE_MIPS32R6 && !HAVE_MIPS64R6 c->sbr_hf_inverse_filter = sbr_hf_inverse_filter_mips; c->sbr_hf_assemble = sbr_hf_assemble_mips; diff -Nru ffmpeg-4.2.2/libavcodec/mips/blockdsp_init_mips.c ffmpeg-4.4/libavcodec/mips/blockdsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/blockdsp_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/blockdsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,36 +19,26 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "blockdsp_mips.h" -#if HAVE_MSA -static av_cold void blockdsp_init_msa(BlockDSPContext *c) -{ - c->clear_block = ff_clear_block_msa; - c->clear_blocks = ff_clear_blocks_msa; - - c->fill_block_tab[0] = ff_fill_block16_msa; - c->fill_block_tab[1] = ff_fill_block8_msa; -} -#endif // #if HAVE_MSA - -#if HAVE_MMI -static av_cold void blockdsp_init_mmi(BlockDSPContext *c) -{ - c->clear_block = ff_clear_block_mmi; - c->clear_blocks = ff_clear_blocks_mmi; - - c->fill_block_tab[0] = ff_fill_block16_mmi; - c->fill_block_tab[1] = ff_fill_block8_mmi; -} -#endif /* HAVE_MMI */ - void ff_blockdsp_init_mips(BlockDSPContext *c) { -#if HAVE_MMI - blockdsp_init_mmi(c); -#endif /* HAVE_MMI */ -#if HAVE_MSA - blockdsp_init_msa(c); -#endif // #if HAVE_MSA + int cpu_flags = av_get_cpu_flags(); + + if (have_mmi(cpu_flags)) { + c->clear_block = ff_clear_block_mmi; + c->clear_blocks = ff_clear_blocks_mmi; + + c->fill_block_tab[0] = ff_fill_block16_mmi; + c->fill_block_tab[1] = ff_fill_block8_mmi; + } + + if (have_msa(cpu_flags)) { + c->clear_block = ff_clear_block_msa; + c->clear_blocks = ff_clear_blocks_msa; + + c->fill_block_tab[0] = ff_fill_block16_msa; + c->fill_block_tab[1] = ff_fill_block8_msa; + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/cabac.h ffmpeg-4.4/libavcodec/mips/cabac.h --- ffmpeg-4.2.2/libavcodec/mips/cabac.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/cabac.h 2021-04-08 21:28:39.000000000 +0000 @@ -25,11 +25,11 @@ #define AVCODEC_MIPS_CABAC_H #include "libavcodec/cabac.h" -#include "libavutil/mips/mmiutils.h" +#include "libavutil/mips/asmdefs.h" #include "config.h" #define get_cabac_inline get_cabac_inline_mips -static av_always_inline int get_cabac_inline(CABACContext *c, +static av_always_inline int get_cabac_inline_mips(CABACContext *c, uint8_t * const state){ mips_reg tmp0, tmp1, tmp2, bit; @@ -109,7 +109,7 @@ [lps_off]"i"(H264_LPS_RANGE_OFFSET), [mlps_off]"i"(H264_MLPS_STATE_OFFSET + 128), [norm_off]"i"(H264_NORM_SHIFT_OFFSET), - [cabac_mask]"i"(CABAC_MASK) + [cabac_mask]"r"(CABAC_MASK) : "memory" ); diff -Nru ffmpeg-4.2.2/libavcodec/mips/compute_antialias_fixed.h ffmpeg-4.4/libavcodec/mips/compute_antialias_fixed.h --- ffmpeg-4.2.2/libavcodec/mips/compute_antialias_fixed.h 2016-03-29 02:25:17.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/compute_antialias_fixed.h 2021-04-08 21:28:39.000000000 +0000 @@ -59,7 +59,8 @@ static void compute_antialias_mips_fixed(MPADecodeContext *s, GranuleDef *g) { - int32_t *ptr, *csa; + const int32_t *csa; + int32_t *ptr; int n, i; int MAX_lo = 0xffffffff; diff -Nru ffmpeg-4.2.2/libavcodec/mips/compute_antialias_float.h ffmpeg-4.4/libavcodec/mips/compute_antialias_float.h --- ffmpeg-4.2.2/libavcodec/mips/compute_antialias_float.h 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/compute_antialias_float.h 2021-04-08 21:28:39.000000000 +0000 @@ -63,7 +63,7 @@ GranuleDef *g) { float *ptr, *ptr_end; - float *csa = &csa_table[0][0]; + const float *csa = &csa_table[0][0]; /* temporary variables */ float in1, in2, in3, in4, in5, in6, in7, in8; float out1, out2, out3, out4; diff -Nru ffmpeg-4.2.2/libavcodec/mips/constants.c ffmpeg-4.4/libavcodec/mips/constants.c --- ffmpeg-4.2.2/libavcodec/mips/constants.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/constants.c 2021-04-08 21:28:39.000000000 +0000 @@ -20,7 +20,7 @@ */ #include "config.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "constants.h" DECLARE_ALIGNED(8, const uint64_t, ff_pw_1) = {0x0001000100010001ULL}; diff -Nru ffmpeg-4.2.2/libavcodec/mips/fft_mips.c ffmpeg-4.4/libavcodec/mips/fft_mips.c --- ffmpeg-4.2.2/libavcodec/mips/fft_mips.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/fft_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -71,6 +71,7 @@ float temp, temp1, temp3, temp4; FFTComplex * tmpz_n2, * tmpz_n34, * tmpz_n4; FFTComplex * tmpz_n2_i, * tmpz_n34_i, * tmpz_n4_i, * tmpz_i; + float f1 = 0.7071067812; num_transforms = (21845 >> (17 - s->nbits)) | 1; @@ -148,7 +149,6 @@ "swc1 %[pom2], 4(%[tmpz]) \n\t" // tmpz[0].im = tmpz[0].im + tmp6; "lwc1 %[pom1], 16(%[tmpz]) \n\t" "lwc1 %[pom3], 20(%[tmpz]) \n\t" - "li.s %[pom], 0.7071067812 \n\t" // float pom = 0.7071067812f; "add.s %[temp1],%[tmp1], %[tmp2] \n\t" "sub.s %[temp], %[pom1], %[tmp8] \n\t" "add.s %[pom2], %[pom3], %[tmp7] \n\t" @@ -159,10 +159,10 @@ "add.s %[pom1], %[pom1], %[tmp8] \n\t" "sub.s %[pom3], %[pom3], %[tmp7] \n\t" "add.s %[tmp3], %[tmp3], %[tmp4] \n\t" - "mul.s %[tmp5], %[pom], %[temp1] \n\t" // tmp5 = pom * (tmp1 + tmp2); - "mul.s %[tmp7], %[pom], %[temp3] \n\t" // tmp7 = pom * (tmp3 - tmp4); - "mul.s %[tmp6], %[pom], %[temp4] \n\t" // tmp6 = pom * (tmp2 - tmp1); - "mul.s %[tmp8], %[pom], %[tmp3] \n\t" // tmp8 = pom * (tmp3 + tmp4); + "mul.s %[tmp5], %[f1], %[temp1] \n\t" // tmp5 = pom * (tmp1 + tmp2); + "mul.s %[tmp7], %[f1], %[temp3] \n\t" // tmp7 = pom * (tmp3 - tmp4); + "mul.s %[tmp6], %[f1], %[temp4] \n\t" // tmp6 = pom * (tmp2 - tmp1); + "mul.s %[tmp8], %[f1], %[tmp3] \n\t" // tmp8 = pom * (tmp3 + tmp4); "swc1 %[pom1], 16(%[tmpz]) \n\t" // tmpz[2].re = tmpz[2].re + tmp8; "swc1 %[pom3], 20(%[tmpz]) \n\t" // tmpz[2].im = tmpz[2].im - tmp7; "add.s %[tmp1], %[tmp5], %[tmp7] \n\t" // tmp1 = tmp5 + tmp7; @@ -193,7 +193,7 @@ [tmp3]"=&f"(tmp3), [tmp2]"=&f"(tmp2), [tmp4]"=&f"(tmp4), [tmp5]"=&f"(tmp5), [tmp7]"=&f"(tmp7), [tmp6]"=&f"(tmp6), [tmp8]"=&f"(tmp8), [pom3]"=&f"(pom3),[temp]"=&f"(temp), [temp1]"=&f"(temp1), [temp3]"=&f"(temp3), [temp4]"=&f"(temp4) - : [tmpz]"r"(tmpz) + : [tmpz]"r"(tmpz), [f1]"f"(f1) : "memory" ); } @@ -500,9 +500,7 @@ av_cold void ff_fft_init_mips(FFTContext *s) { - int n=0; - - ff_fft_lut_init(ff_fft_offsets_lut, 0, 1 << 17, &n); + ff_fft_lut_init(); ff_init_ff_cos_tabs(17); #if HAVE_INLINE_ASM diff -Nru ffmpeg-4.2.2/libavcodec/mips/h263dsp_init_mips.c ffmpeg-4.4/libavcodec/mips/h263dsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/h263dsp_init_mips.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/h263dsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,19 +18,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "h263dsp_mips.h" -#if HAVE_MSA -static av_cold void h263dsp_init_msa(H263DSPContext *c) -{ - c->h263_h_loop_filter = ff_h263_h_loop_filter_msa; - c->h263_v_loop_filter = ff_h263_v_loop_filter_msa; -} -#endif // #if HAVE_MSA - av_cold void ff_h263dsp_init_mips(H263DSPContext *c) { -#if HAVE_MSA - h263dsp_init_msa(c); -#endif // #if HAVE_MSA + int cpu_flags = av_get_cpu_flags(); + + if (have_msa(cpu_flags)){ + c->h263_h_loop_filter = ff_h263_h_loop_filter_msa; + c->h263_v_loop_filter = ff_h263_v_loop_filter_msa; + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/h264chroma_init_mips.c ffmpeg-4.4/libavcodec/mips/h264chroma_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/h264chroma_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/h264chroma_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,45 +19,34 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "h264chroma_mips.h" -#if HAVE_MSA -static av_cold void h264chroma_init_msa(H264ChromaContext *c, int bit_depth) -{ - const int high_bit_depth = bit_depth > 8; - if (!high_bit_depth) { - c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_msa; - c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_msa; - c->put_h264_chroma_pixels_tab[2] = ff_put_h264_chroma_mc2_msa; - - c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_msa; - c->avg_h264_chroma_pixels_tab[1] = ff_avg_h264_chroma_mc4_msa; - c->avg_h264_chroma_pixels_tab[2] = ff_avg_h264_chroma_mc2_msa; - } -} -#endif // #if HAVE_MSA - -#if HAVE_MMI -static av_cold void h264chroma_init_mmi(H264ChromaContext *c, int bit_depth) +av_cold void ff_h264chroma_init_mips(H264ChromaContext *c, int bit_depth) { + int cpu_flags = av_get_cpu_flags(); int high_bit_depth = bit_depth > 8; - if (!high_bit_depth) { - c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_mmi; - c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_mmi; - c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_mmi; - c->avg_h264_chroma_pixels_tab[1] = ff_avg_h264_chroma_mc4_mmi; + /* MMI apears to be faster than MSA here */ + if (have_msa(cpu_flags)) { + if (!high_bit_depth) { + c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_msa; + c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_msa; + c->put_h264_chroma_pixels_tab[2] = ff_put_h264_chroma_mc2_msa; + + c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_msa; + c->avg_h264_chroma_pixels_tab[1] = ff_avg_h264_chroma_mc4_msa; + c->avg_h264_chroma_pixels_tab[2] = ff_avg_h264_chroma_mc2_msa; + } } -} -#endif /* HAVE_MMI */ -av_cold void ff_h264chroma_init_mips(H264ChromaContext *c, int bit_depth) -{ -#if HAVE_MMI - h264chroma_init_mmi(c, bit_depth); -#endif /* HAVE_MMI */ -#if HAVE_MSA - h264chroma_init_msa(c, bit_depth); -#endif // #if HAVE_MSA + if (have_mmi(cpu_flags)) { + if (!high_bit_depth) { + c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_mmi; + c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_mmi; + c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_mmi; + c->avg_h264_chroma_pixels_tab[1] = ff_avg_h264_chroma_mc4_mmi; + } + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/h264dsp_init_mips.c ffmpeg-4.4/libavcodec/mips/h264dsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/h264dsp_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/h264dsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,129 +19,116 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "h264dsp_mips.h" -#if HAVE_MSA -static av_cold void h264dsp_init_msa(H264DSPContext *c, - const int bit_depth, - const int chroma_format_idc) +av_cold void ff_h264dsp_init_mips(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc) { - if (8 == bit_depth) { - c->h264_v_loop_filter_luma = ff_h264_v_lpf_luma_inter_msa; - c->h264_h_loop_filter_luma = ff_h264_h_lpf_luma_inter_msa; - c->h264_h_loop_filter_luma_mbaff = - ff_h264_h_loop_filter_luma_mbaff_msa; - c->h264_v_loop_filter_luma_intra = ff_h264_v_lpf_luma_intra_msa; - c->h264_h_loop_filter_luma_intra = ff_h264_h_lpf_luma_intra_msa; - c->h264_h_loop_filter_luma_mbaff_intra = - ff_h264_h_loop_filter_luma_mbaff_intra_msa; - c->h264_v_loop_filter_chroma = ff_h264_v_lpf_chroma_inter_msa; - - if (chroma_format_idc <= 1) - c->h264_h_loop_filter_chroma = ff_h264_h_lpf_chroma_inter_msa; - else - c->h264_h_loop_filter_chroma = - ff_h264_h_loop_filter_chroma422_msa; - - if (chroma_format_idc > 1) - c->h264_h_loop_filter_chroma_mbaff = - ff_h264_h_loop_filter_chroma422_mbaff_msa; - - c->h264_v_loop_filter_chroma_intra = - ff_h264_v_lpf_chroma_intra_msa; - - if (chroma_format_idc <= 1) - c->h264_h_loop_filter_chroma_intra = - ff_h264_h_lpf_chroma_intra_msa; - - /* Weighted MC */ - c->weight_h264_pixels_tab[0] = ff_weight_h264_pixels16_8_msa; - c->weight_h264_pixels_tab[1] = ff_weight_h264_pixels8_8_msa; - c->weight_h264_pixels_tab[2] = ff_weight_h264_pixels4_8_msa; - - c->biweight_h264_pixels_tab[0] = ff_biweight_h264_pixels16_8_msa; - c->biweight_h264_pixels_tab[1] = ff_biweight_h264_pixels8_8_msa; - c->biweight_h264_pixels_tab[2] = ff_biweight_h264_pixels4_8_msa; - - c->h264_idct_add = ff_h264_idct_add_msa; - c->h264_idct8_add = ff_h264_idct8_addblk_msa; - c->h264_idct_dc_add = ff_h264_idct4x4_addblk_dc_msa; - c->h264_idct8_dc_add = ff_h264_idct8_dc_addblk_msa; - c->h264_idct_add16 = ff_h264_idct_add16_msa; - c->h264_idct8_add4 = ff_h264_idct8_add4_msa; - - if (chroma_format_idc <= 1) - c->h264_idct_add8 = ff_h264_idct_add8_msa; - else - c->h264_idct_add8 = ff_h264_idct_add8_422_msa; - - c->h264_idct_add16intra = ff_h264_idct_add16_intra_msa; - c->h264_luma_dc_dequant_idct = ff_h264_deq_idct_luma_dc_msa; - } // if (8 == bit_depth) -} -#endif // #if HAVE_MSA + int cpu_flags = av_get_cpu_flags(); -#if HAVE_MMI -static av_cold void h264dsp_init_mmi(H264DSPContext * c, const int bit_depth, - const int chroma_format_idc) -{ - if (bit_depth == 8) { - c->h264_add_pixels4_clear = ff_h264_add_pixels4_8_mmi; - c->h264_idct_add = ff_h264_idct_add_8_mmi; - c->h264_idct8_add = ff_h264_idct8_add_8_mmi; - c->h264_idct_dc_add = ff_h264_idct_dc_add_8_mmi; - c->h264_idct8_dc_add = ff_h264_idct8_dc_add_8_mmi; - c->h264_idct_add16 = ff_h264_idct_add16_8_mmi; - c->h264_idct_add16intra = ff_h264_idct_add16intra_8_mmi; - c->h264_idct8_add4 = ff_h264_idct8_add4_8_mmi; - - if (chroma_format_idc <= 1) - c->h264_idct_add8 = ff_h264_idct_add8_8_mmi; - else - c->h264_idct_add8 = ff_h264_idct_add8_422_8_mmi; - - c->h264_luma_dc_dequant_idct = ff_h264_luma_dc_dequant_idct_8_mmi; - - if (chroma_format_idc <= 1) - c->h264_chroma_dc_dequant_idct = - ff_h264_chroma_dc_dequant_idct_8_mmi; - else - c->h264_chroma_dc_dequant_idct = - ff_h264_chroma422_dc_dequant_idct_8_mmi; - - c->weight_h264_pixels_tab[0] = ff_h264_weight_pixels16_8_mmi; - c->weight_h264_pixels_tab[1] = ff_h264_weight_pixels8_8_mmi; - c->weight_h264_pixels_tab[2] = ff_h264_weight_pixels4_8_mmi; - - c->biweight_h264_pixels_tab[0] = ff_h264_biweight_pixels16_8_mmi; - c->biweight_h264_pixels_tab[1] = ff_h264_biweight_pixels8_8_mmi; - c->biweight_h264_pixels_tab[2] = ff_h264_biweight_pixels4_8_mmi; - - c->h264_v_loop_filter_chroma = ff_deblock_v_chroma_8_mmi; - c->h264_v_loop_filter_chroma_intra = ff_deblock_v_chroma_intra_8_mmi; - - if (chroma_format_idc <= 1) { - c->h264_h_loop_filter_chroma = - ff_deblock_h_chroma_8_mmi; - c->h264_h_loop_filter_chroma_intra = - ff_deblock_h_chroma_intra_8_mmi; + if (have_mmi(cpu_flags)) { + if (bit_depth == 8) { + c->h264_add_pixels4_clear = ff_h264_add_pixels4_8_mmi; + c->h264_idct_add = ff_h264_idct_add_8_mmi; + c->h264_idct8_add = ff_h264_idct8_add_8_mmi; + c->h264_idct_dc_add = ff_h264_idct_dc_add_8_mmi; + c->h264_idct8_dc_add = ff_h264_idct8_dc_add_8_mmi; + c->h264_idct_add16 = ff_h264_idct_add16_8_mmi; + c->h264_idct_add16intra = ff_h264_idct_add16intra_8_mmi; + c->h264_idct8_add4 = ff_h264_idct8_add4_8_mmi; + + if (chroma_format_idc <= 1) + c->h264_idct_add8 = ff_h264_idct_add8_8_mmi; + else + c->h264_idct_add8 = ff_h264_idct_add8_422_8_mmi; + + c->h264_luma_dc_dequant_idct = ff_h264_luma_dc_dequant_idct_8_mmi; + + if (chroma_format_idc <= 1) + c->h264_chroma_dc_dequant_idct = + ff_h264_chroma_dc_dequant_idct_8_mmi; + else + c->h264_chroma_dc_dequant_idct = + ff_h264_chroma422_dc_dequant_idct_8_mmi; + + c->weight_h264_pixels_tab[0] = ff_h264_weight_pixels16_8_mmi; + c->weight_h264_pixels_tab[1] = ff_h264_weight_pixels8_8_mmi; + c->weight_h264_pixels_tab[2] = ff_h264_weight_pixels4_8_mmi; + + c->biweight_h264_pixels_tab[0] = ff_h264_biweight_pixels16_8_mmi; + c->biweight_h264_pixels_tab[1] = ff_h264_biweight_pixels8_8_mmi; + c->biweight_h264_pixels_tab[2] = ff_h264_biweight_pixels4_8_mmi; + + c->h264_v_loop_filter_chroma = ff_deblock_v_chroma_8_mmi; + c->h264_v_loop_filter_chroma_intra = ff_deblock_v_chroma_intra_8_mmi; + + if (chroma_format_idc <= 1) { + c->h264_h_loop_filter_chroma = + ff_deblock_h_chroma_8_mmi; + c->h264_h_loop_filter_chroma_intra = + ff_deblock_h_chroma_intra_8_mmi; + } + + c->h264_v_loop_filter_luma = ff_deblock_v_luma_8_mmi; + c->h264_v_loop_filter_luma_intra = ff_deblock_v_luma_intra_8_mmi; + c->h264_h_loop_filter_luma = ff_deblock_h_luma_8_mmi; + c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_8_mmi; } - - c->h264_v_loop_filter_luma = ff_deblock_v_luma_8_mmi; - c->h264_v_loop_filter_luma_intra = ff_deblock_v_luma_intra_8_mmi; - c->h264_h_loop_filter_luma = ff_deblock_h_luma_8_mmi; - c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_8_mmi; } -} -#endif /* HAVE_MMI */ -av_cold void ff_h264dsp_init_mips(H264DSPContext *c, const int bit_depth, - const int chroma_format_idc) -{ -#if HAVE_MMI - h264dsp_init_mmi(c, bit_depth, chroma_format_idc); -#endif /* HAVE_MMI */ -#if HAVE_MSA - h264dsp_init_msa(c, bit_depth, chroma_format_idc); -#endif // #if HAVE_MSA + if (have_msa(cpu_flags)) { + if (bit_depth == 8) { + c->h264_v_loop_filter_luma = ff_h264_v_lpf_luma_inter_msa; + c->h264_h_loop_filter_luma = ff_h264_h_lpf_luma_inter_msa; + c->h264_h_loop_filter_luma_mbaff = + ff_h264_h_loop_filter_luma_mbaff_msa; + c->h264_v_loop_filter_luma_intra = ff_h264_v_lpf_luma_intra_msa; + c->h264_h_loop_filter_luma_intra = ff_h264_h_lpf_luma_intra_msa; + c->h264_h_loop_filter_luma_mbaff_intra = + ff_h264_h_loop_filter_luma_mbaff_intra_msa; + c->h264_v_loop_filter_chroma = ff_h264_v_lpf_chroma_inter_msa; + + if (chroma_format_idc <= 1) + c->h264_h_loop_filter_chroma = ff_h264_h_lpf_chroma_inter_msa; + else + c->h264_h_loop_filter_chroma = + ff_h264_h_loop_filter_chroma422_msa; + + if (chroma_format_idc > 1) + c->h264_h_loop_filter_chroma_mbaff = + ff_h264_h_loop_filter_chroma422_mbaff_msa; + + c->h264_v_loop_filter_chroma_intra = + ff_h264_v_lpf_chroma_intra_msa; + + if (chroma_format_idc <= 1) + c->h264_h_loop_filter_chroma_intra = + ff_h264_h_lpf_chroma_intra_msa; + + /* Weighted MC */ + c->weight_h264_pixels_tab[0] = ff_weight_h264_pixels16_8_msa; + c->weight_h264_pixels_tab[1] = ff_weight_h264_pixels8_8_msa; + c->weight_h264_pixels_tab[2] = ff_weight_h264_pixels4_8_msa; + + c->biweight_h264_pixels_tab[0] = ff_biweight_h264_pixels16_8_msa; + c->biweight_h264_pixels_tab[1] = ff_biweight_h264_pixels8_8_msa; + c->biweight_h264_pixels_tab[2] = ff_biweight_h264_pixels4_8_msa; + + c->h264_idct_add = ff_h264_idct_add_msa; + c->h264_idct8_add = ff_h264_idct8_addblk_msa; + c->h264_idct_dc_add = ff_h264_idct4x4_addblk_dc_msa; + c->h264_idct8_dc_add = ff_h264_idct8_dc_addblk_msa; + c->h264_idct_add16 = ff_h264_idct_add16_msa; + c->h264_idct8_add4 = ff_h264_idct8_add4_msa; + + if (chroma_format_idc <= 1) + c->h264_idct_add8 = ff_h264_idct_add8_msa; + else + c->h264_idct_add8 = ff_h264_idct_add8_422_msa; + + c->h264_idct_add16intra = ff_h264_idct_add16_intra_msa; + c->h264_luma_dc_dequant_idct = ff_h264_deq_idct_luma_dc_msa; + } + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/h264dsp_mips.h ffmpeg-4.4/libavcodec/mips/h264dsp_mips.h --- ffmpeg-4.2.2/libavcodec/mips/h264dsp_mips.h 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/h264dsp_mips.h 2021-04-08 21:28:39.000000000 +0000 @@ -25,21 +25,21 @@ #include "libavcodec/h264dec.h" #include "constants.h" -void ff_h264_h_lpf_luma_inter_msa(uint8_t *src, int stride, +void ff_h264_h_lpf_luma_inter_msa(uint8_t *src, ptrdiff_t stride, int alpha, int beta, int8_t *tc0); -void ff_h264_v_lpf_luma_inter_msa(uint8_t *src, int stride, +void ff_h264_v_lpf_luma_inter_msa(uint8_t *src, ptrdiff_t stride, int alpha, int beta, int8_t *tc0); -void ff_h264_h_lpf_chroma_inter_msa(uint8_t *src, int stride, +void ff_h264_h_lpf_chroma_inter_msa(uint8_t *src, ptrdiff_t stride, int alpha, int beta, int8_t *tc0); -void ff_h264_v_lpf_chroma_inter_msa(uint8_t *src, int stride, +void ff_h264_v_lpf_chroma_inter_msa(uint8_t *src, ptrdiff_t stride, int alpha, int beta, int8_t *tc0); -void ff_h264_h_loop_filter_chroma422_msa(uint8_t *src, int32_t stride, +void ff_h264_h_loop_filter_chroma422_msa(uint8_t *src, ptrdiff_t stride, int32_t alpha, int32_t beta, int8_t *tc0); -void ff_h264_h_loop_filter_chroma422_mbaff_msa(uint8_t *src, int32_t stride, +void ff_h264_h_loop_filter_chroma422_mbaff_msa(uint8_t *src, ptrdiff_t stride, int32_t alpha, int32_t beta, int8_t *tc0); -void ff_h264_h_loop_filter_luma_mbaff_msa(uint8_t *src, int32_t stride, +void ff_h264_h_loop_filter_luma_mbaff_msa(uint8_t *src, ptrdiff_t stride, int32_t alpha, int32_t beta, int8_t *tc0); @@ -67,15 +67,15 @@ int16_t *blk, int dst_stride, const uint8_t nnzc[15 * 8]); -void ff_h264_h_lpf_luma_intra_msa(uint8_t *src, int stride, +void ff_h264_h_lpf_luma_intra_msa(uint8_t *src, ptrdiff_t stride, int alpha, int beta); -void ff_h264_v_lpf_luma_intra_msa(uint8_t *src, int stride, +void ff_h264_v_lpf_luma_intra_msa(uint8_t *src, ptrdiff_t stride, int alpha, int beta); -void ff_h264_h_lpf_chroma_intra_msa(uint8_t *src, int stride, +void ff_h264_h_lpf_chroma_intra_msa(uint8_t *src, ptrdiff_t stride, int alpha, int beta); -void ff_h264_v_lpf_chroma_intra_msa(uint8_t *src, int stride, +void ff_h264_v_lpf_chroma_intra_msa(uint8_t *src, ptrdiff_t stride, int alpha, int beta); -void ff_h264_h_loop_filter_luma_mbaff_intra_msa(uint8_t *src, int stride, +void ff_h264_h_loop_filter_luma_mbaff_intra_msa(uint8_t *src, ptrdiff_t stride, int alpha, int beta); void ff_biweight_h264_pixels16_8_msa(uint8_t *dst, uint8_t *src, @@ -357,23 +357,23 @@ void ff_deblock_v_chroma_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int8_t *tc0); -void ff_deblock_v_chroma_intra_8_mmi(uint8_t *pix, int stride, int alpha, +void ff_deblock_v_chroma_intra_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta); -void ff_deblock_h_chroma_8_mmi(uint8_t *pix, int stride, int alpha, int beta, +void ff_deblock_h_chroma_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int8_t *tc0); -void ff_deblock_h_chroma_intra_8_mmi(uint8_t *pix, int stride, int alpha, +void ff_deblock_h_chroma_intra_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta); -void ff_deblock_v_luma_8_mmi(uint8_t *pix, int stride, int alpha, int beta, +void ff_deblock_v_luma_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int8_t *tc0); -void ff_deblock_v_luma_intra_8_mmi(uint8_t *pix, int stride, int alpha, +void ff_deblock_v_luma_intra_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta); -void ff_deblock_h_luma_8_mmi(uint8_t *pix, int stride, int alpha, int beta, +void ff_deblock_h_luma_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int8_t *tc0); -void ff_deblock_h_luma_intra_8_mmi(uint8_t *pix, int stride, int alpha, +void ff_deblock_h_luma_intra_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta); -void ff_deblock_v8_luma_8_mmi(uint8_t *pix, int stride, int alpha, int beta, +void ff_deblock_v8_luma_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int8_t *tc0); -void ff_deblock_v8_luma_intra_8_mmi(uint8_t *pix, int stride, int alpha, +void ff_deblock_v8_luma_intra_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta); void ff_put_h264_qpel16_mc00_mmi(uint8_t *dst, const uint8_t *src, diff -Nru ffmpeg-4.2.2/libavcodec/mips/h264dsp_mmi.c ffmpeg-4.4/libavcodec/mips/h264dsp_mmi.c --- ffmpeg-4.2.2/libavcodec/mips/h264dsp_mmi.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/h264dsp_mmi.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,7 @@ #include "libavcodec/bit_depth_template.c" #include "h264dsp_mips.h" #include "libavutil/mips/mmiutils.h" +#include "libavutil/mem_internal.h" void ff_h264_add_pixels4_8_mmi(uint8_t *dst, int16_t *src, int stride) { @@ -38,6 +39,9 @@ MMI_LDC1(%[ftmp2], %[src], 0x08) MMI_LDC1(%[ftmp3], %[src], 0x10) MMI_LDC1(%[ftmp4], %[src], 0x18) + /* memset(src, 0, 32); */ + "gssqc1 %[ftmp0], %[ftmp0], 0x00(%[src]) \n\t" + "gssqc1 %[ftmp0], %[ftmp0], 0x10(%[src]) \n\t" MMI_ULWC1(%[ftmp5], %[dst0], 0x00) MMI_ULWC1(%[ftmp6], %[dst1], 0x00) MMI_ULWC1(%[ftmp7], %[dst2], 0x00) @@ -58,11 +62,6 @@ MMI_SWC1(%[ftmp2], %[dst1], 0x00) MMI_SWC1(%[ftmp3], %[dst2], 0x00) MMI_SWC1(%[ftmp4], %[dst3], 0x00) - - /* memset(src, 0, 32); */ - "xor %[ftmp0], %[ftmp0], %[ftmp0] \n\t" - "gssqc1 %[ftmp0], %[ftmp0], 0x00(%[src]) \n\t" - "gssqc1 %[ftmp0], %[ftmp0], 0x10(%[src]) \n\t" : [ftmp0]"=&f"(ftmp[0]), [ftmp1]"=&f"(ftmp[1]), [ftmp2]"=&f"(ftmp[2]), [ftmp3]"=&f"(ftmp[3]), [ftmp4]"=&f"(ftmp[4]), [ftmp5]"=&f"(ftmp[5]), @@ -85,15 +84,19 @@ DECLARE_VAR_ADDRT; __asm__ volatile ( - "dli %[tmp0], 0x01 \n\t" MMI_LDC1(%[ftmp0], %[block], 0x00) - "mtc1 %[tmp0], %[ftmp8] \n\t" MMI_LDC1(%[ftmp1], %[block], 0x08) - "dli %[tmp0], 0x06 \n\t" MMI_LDC1(%[ftmp2], %[block], 0x10) + MMI_LDC1(%[ftmp3], %[block], 0x18) + /* memset(block, 0, 32) */ + "xor %[ftmp4], %[ftmp4], %[ftmp4] \n\t" + "gssqc1 %[ftmp4], %[ftmp4], 0x00(%[block]) \n\t" + "gssqc1 %[ftmp4], %[ftmp4], 0x10(%[block]) \n\t" + "dli %[tmp0], 0x01 \n\t" + "mtc1 %[tmp0], %[ftmp8] \n\t" + "dli %[tmp0], 0x06 \n\t" "mtc1 %[tmp0], %[ftmp9] \n\t" "psrah %[ftmp4], %[ftmp1], %[ftmp8] \n\t" - MMI_LDC1(%[ftmp3], %[block], 0x18) "psrah %[ftmp5], %[ftmp3], %[ftmp8] \n\t" "psubh %[ftmp4], %[ftmp4], %[ftmp3] \n\t" "paddh %[ftmp5], %[ftmp5], %[ftmp1] \n\t" @@ -121,15 +124,11 @@ "paddh %[ftmp10], %[ftmp3], %[ftmp1] \n\t" "psubh %[ftmp1], %[ftmp1], %[ftmp3] \n\t" "paddh %[ftmp11], %[ftmp4], %[ftmp5] \n\t" - "xor %[ftmp7], %[ftmp7], %[ftmp7] \n\t" "psubh %[ftmp5], %[ftmp5], %[ftmp4] \n\t" - MMI_SDC1(%[ftmp7], %[block], 0x00) - MMI_SDC1(%[ftmp7], %[block], 0x08) - MMI_SDC1(%[ftmp7], %[block], 0x10) - MMI_SDC1(%[ftmp7], %[block], 0x18) MMI_ULWC1(%[ftmp2], %[dst], 0x00) - "psrah %[ftmp3], %[ftmp10], %[ftmp9] \n\t" MMI_LWXC1(%[ftmp0], %[dst], %[stride], 0x00) + "xor %[ftmp7], %[ftmp7], %[ftmp7] \n\t" + "psrah %[ftmp3], %[ftmp10], %[ftmp9] \n\t" "psrah %[ftmp4], %[ftmp11], %[ftmp9] \n\t" "punpcklbh %[ftmp2], %[ftmp2], %[ftmp7] \n\t" "punpcklbh %[ftmp0], %[ftmp0], %[ftmp7] \n\t" @@ -153,11 +152,6 @@ MMI_SWC1(%[ftmp2], %[dst], 0x00) "packushb %[ftmp0], %[ftmp0], %[ftmp7] \n\t" MMI_SWXC1(%[ftmp0], %[dst], %[stride], 0x00) - - /* memset(block, 0, 32) */ - "xor %[ftmp0], %[ftmp0], %[ftmp0] \n\t" - "gssqc1 %[ftmp0], %[ftmp0], 0x00(%[block]) \n\t" - "gssqc1 %[ftmp0], %[ftmp0], 0x10(%[block]) \n\t" : [ftmp0]"=&f"(ftmp[0]), [ftmp1]"=&f"(ftmp[1]), [ftmp2]"=&f"(ftmp[2]), [ftmp3]"=&f"(ftmp[3]), [ftmp4]"=&f"(ftmp[4]), [ftmp5]"=&f"(ftmp[5]), @@ -184,7 +178,7 @@ __asm__ volatile ( "lhu %[tmp0], 0x00(%[block]) \n\t" - PTR_ADDI "$29, $29, -0x20 \n\t" + PTR_ADDI "$sp, $sp, -0x20 \n\t" PTR_ADDIU "%[tmp0], %[tmp0], 0x20 \n\t" MMI_LDC1(%[ftmp1], %[block], 0x10) "sh %[tmp0], 0x00(%[block]) \n\t" @@ -261,8 +255,8 @@ "punpckhwd %[ftmp3], %[ftmp6], %[ftmp0] \n\t" "punpcklwd %[ftmp6], %[ftmp6], %[ftmp0] \n\t" MMI_LDC1(%[ftmp0], %[block], 0x00) - MMI_SDC1(%[ftmp7], $29, 0x00) - MMI_SDC1(%[ftmp1], $29, 0x10) + MMI_SDC1(%[ftmp7], $sp, 0x00) + MMI_SDC1(%[ftmp1], $sp, 0x10) "dmfc1 %[tmp1], %[ftmp6] \n\t" "dmfc1 %[tmp3], %[ftmp3] \n\t" "punpckhhw %[ftmp3], %[ftmp5], %[ftmp2] \n\t" @@ -273,8 +267,8 @@ "punpcklwd %[ftmp5], %[ftmp5], %[ftmp4] \n\t" "punpckhwd %[ftmp4], %[ftmp3], %[ftmp2] \n\t" "punpcklwd %[ftmp3], %[ftmp3], %[ftmp2] \n\t" - MMI_SDC1(%[ftmp5], $29, 0x08) - MMI_SDC1(%[ftmp0], $29, 0x18) + MMI_SDC1(%[ftmp5], $sp, 0x08) + MMI_SDC1(%[ftmp0], $sp, 0x18) "dmfc1 %[tmp2], %[ftmp3] \n\t" "dmfc1 %[tmp4], %[ftmp4] \n\t" MMI_LDC1(%[ftmp1], %[block], 0x18) @@ -366,7 +360,7 @@ PTR_ADDIU "%[addr0], %[dst], 0x04 \n\t" "mov.d %[ftmp7], %[ftmp10] \n\t" "dmtc1 %[tmp3], %[ftmp6] \n\t" - MMI_LDC1(%[ftmp1], $29, 0x10) + MMI_LDC1(%[ftmp1], $sp, 0x10) "dmtc1 %[tmp1], %[ftmp3] \n\t" "mov.d %[ftmp4], %[ftmp1] \n\t" "psrah %[ftmp1], %[ftmp1], %[ftmp8] \n\t" @@ -399,7 +393,7 @@ "psrah %[ftmp0], %[ftmp3], %[ftmp8] \n\t" "paddh %[ftmp2], %[ftmp2], %[ftmp3] \n\t" "psubh %[ftmp0], %[ftmp0], %[ftmp7] \n\t" - MMI_LDC1(%[ftmp3], $29, 0x00) + MMI_LDC1(%[ftmp3], $sp, 0x00) "dmtc1 %[tmp5], %[ftmp7] \n\t" "paddh %[ftmp7], %[ftmp7], %[ftmp3] \n\t" "paddh %[ftmp3], %[ftmp3], %[ftmp3] \n\t" @@ -421,9 +415,9 @@ "paddh %[ftmp1], %[ftmp1], %[ftmp7] \n\t" "psubh %[ftmp3], %[ftmp3], %[ftmp6] \n\t" "paddh %[ftmp7], %[ftmp7], %[ftmp7] \n\t" - MMI_SDC1(%[ftmp3], $29, 0x00) + MMI_SDC1(%[ftmp3], $sp, 0x00) "psubh %[ftmp7], %[ftmp7], %[ftmp1] \n\t" - MMI_SDC1(%[ftmp0], $29, 0x10) + MMI_SDC1(%[ftmp0], $sp, 0x10) "dmfc1 %[tmp1], %[ftmp2] \n\t" "xor %[ftmp2], %[ftmp2], %[ftmp2] \n\t" MMI_SDC1(%[ftmp2], %[block], 0x00) @@ -470,8 +464,8 @@ "packushb %[ftmp0], %[ftmp0], %[ftmp2] \n\t" MMI_SWC1(%[ftmp3], %[dst], 0x00) MMI_SWXC1(%[ftmp0], %[dst], %[stride], 0x00) - MMI_LDC1(%[ftmp5], $29, 0x00) - MMI_LDC1(%[ftmp4], $29, 0x10) + MMI_LDC1(%[ftmp5], $sp, 0x00) + MMI_LDC1(%[ftmp4], $sp, 0x10) "dmtc1 %[tmp1], %[ftmp6] \n\t" PTR_ADDU "%[dst], %[dst], %[stride] \n\t" PTR_ADDU "%[dst], %[dst], %[stride] \n\t" @@ -503,7 +497,7 @@ MMI_SWXC1(%[ftmp0], %[dst], %[stride], 0x00) "dmtc1 %[tmp4], %[ftmp1] \n\t" "dmtc1 %[tmp2], %[ftmp6] \n\t" - MMI_LDC1(%[ftmp4], $29, 0x18) + MMI_LDC1(%[ftmp4], $sp, 0x18) "mov.d %[ftmp5], %[ftmp4] \n\t" "psrah %[ftmp4], %[ftmp4], %[ftmp8] \n\t" "psrah %[ftmp7], %[ftmp11], %[ftmp8] \n\t" @@ -535,7 +529,7 @@ "psrah %[ftmp7], %[ftmp6], %[ftmp8] \n\t" "paddh %[ftmp0], %[ftmp0], %[ftmp6] \n\t" "psubh %[ftmp7], %[ftmp7], %[ftmp3] \n\t" - MMI_LDC1(%[ftmp6], $29, 0x08) + MMI_LDC1(%[ftmp6], $sp, 0x08) "dmtc1 %[tmp6], %[ftmp3] \n\t" "paddh %[ftmp3], %[ftmp3], %[ftmp6] \n\t" "paddh %[ftmp6], %[ftmp6], %[ftmp6] \n\t" @@ -557,9 +551,9 @@ "paddh %[ftmp4], %[ftmp4], %[ftmp3] \n\t" "psubh %[ftmp6], %[ftmp6], %[ftmp1] \n\t" "paddh %[ftmp3], %[ftmp3], %[ftmp3] \n\t" - MMI_SDC1(%[ftmp6], $29, 0x08) + MMI_SDC1(%[ftmp6], $sp, 0x08) "psubh %[ftmp3], %[ftmp3], %[ftmp4] \n\t" - MMI_SDC1(%[ftmp7], $29, 0x18) + MMI_SDC1(%[ftmp7], $sp, 0x18) "dmfc1 %[tmp2], %[ftmp0] \n\t" "xor %[ftmp0], %[ftmp0], %[ftmp0] \n\t" MMI_ULWC1(%[ftmp6], %[addr0], 0x00) @@ -588,8 +582,8 @@ "packushb %[ftmp7], %[ftmp7], %[ftmp0] \n\t" MMI_SWC1(%[ftmp6], %[addr0], 0x00) MMI_SWXC1(%[ftmp7], %[addr0], %[stride], 0x00) - MMI_LDC1(%[ftmp2], $29, 0x08) - MMI_LDC1(%[ftmp5], $29, 0x18) + MMI_LDC1(%[ftmp2], $sp, 0x08) + MMI_LDC1(%[ftmp5], $sp, 0x18) PTR_ADDU "%[addr0], %[addr0], %[stride] \n\t" "dmtc1 %[tmp2], %[ftmp1] \n\t" PTR_ADDU "%[addr0], %[addr0], %[stride] \n\t" @@ -619,18 +613,7 @@ "packushb %[ftmp7], %[ftmp7], %[ftmp0] \n\t" MMI_SWC1(%[ftmp6], %[addr0], 0x00) MMI_SWXC1(%[ftmp7], %[addr0], %[stride], 0x00) - PTR_ADDIU "$29, $29, 0x20 \n\t" - - /* memset(block, 0, 128) */ - "xor %[ftmp0], %[ftmp0], %[ftmp0] \n\t" - "gssqc1 %[ftmp0], %[ftmp0], 0x00(%[block]) \n\t" - "gssqc1 %[ftmp0], %[ftmp0], 0x10(%[block]) \n\t" - "gssqc1 %[ftmp0], %[ftmp0], 0x20(%[block]) \n\t" - "gssqc1 %[ftmp0], %[ftmp0], 0x30(%[block]) \n\t" - "gssqc1 %[ftmp0], %[ftmp0], 0x40(%[block]) \n\t" - "gssqc1 %[ftmp0], %[ftmp0], 0x50(%[block]) \n\t" - "gssqc1 %[ftmp0], %[ftmp0], 0x60(%[block]) \n\t" - "gssqc1 %[ftmp0], %[ftmp0], 0x70(%[block]) \n\t" + PTR_ADDIU "$sp, $sp, 0x20 \n\t" : [ftmp0]"=&f"(ftmp[0]), [ftmp1]"=&f"(ftmp[1]), [ftmp2]"=&f"(ftmp[2]), [ftmp3]"=&f"(ftmp[3]), [ftmp4]"=&f"(ftmp[4]), [ftmp5]"=&f"(ftmp[5]), @@ -648,7 +631,7 @@ [addr0]"=&r"(addr[0]) : [dst]"r"(dst), [block]"r"(block), [stride]"r"((mips_reg)stride) - : "$29","memory" + : "memory" ); } @@ -1451,7 +1434,7 @@ } } -void ff_deblock_v8_luma_8_mmi(uint8_t *pix, int stride, int alpha, int beta, +void ff_deblock_v8_luma_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int8_t *tc0) { double ftmp[12]; @@ -1579,7 +1562,7 @@ ); } -static void deblock_v8_luma_intra_8_mmi(uint8_t *pix, int stride, int alpha, +static void deblock_v8_luma_intra_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta) { DECLARE_ALIGNED(8, const uint64_t, stack[0x0a]); @@ -1889,7 +1872,7 @@ ); } -void ff_deblock_v_chroma_intra_8_mmi(uint8_t *pix, int stride, int alpha, +void ff_deblock_v_chroma_intra_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta) { double ftmp[9]; @@ -1967,7 +1950,7 @@ ); } -void ff_deblock_h_chroma_8_mmi(uint8_t *pix, int stride, int alpha, int beta, +void ff_deblock_h_chroma_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int8_t *tc0) { double ftmp[11]; @@ -2107,7 +2090,7 @@ ); } -void ff_deblock_h_chroma_intra_8_mmi(uint8_t *pix, int stride, int alpha, +void ff_deblock_h_chroma_intra_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta) { double ftmp[11]; @@ -2240,7 +2223,7 @@ ); } -void ff_deblock_v_luma_8_mmi(uint8_t *pix, int stride, int alpha, int beta, +void ff_deblock_v_luma_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int8_t *tc0) { if ((tc0[0] & tc0[1]) >= 0) @@ -2249,14 +2232,14 @@ ff_deblock_v8_luma_8_mmi(pix + 8, stride, alpha, beta, tc0 + 2); } -void ff_deblock_v_luma_intra_8_mmi(uint8_t *pix, int stride, int alpha, +void ff_deblock_v_luma_intra_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta) { deblock_v8_luma_intra_8_mmi(pix + 0, stride, alpha, beta); deblock_v8_luma_intra_8_mmi(pix + 8, stride, alpha, beta); } -void ff_deblock_h_luma_8_mmi(uint8_t *pix, int stride, int alpha, int beta, +void ff_deblock_h_luma_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta, int8_t *tc0) { DECLARE_ALIGNED(8, const uint64_t, stack[0x0d]); @@ -2475,7 +2458,7 @@ ); } -void ff_deblock_h_luma_intra_8_mmi(uint8_t *pix, int stride, int alpha, +void ff_deblock_h_luma_intra_8_mmi(uint8_t *pix, ptrdiff_t stride, int alpha, int beta) { DECLARE_ALIGNED(8, const uint64_t, ptmp[0x11]); diff -Nru ffmpeg-4.2.2/libavcodec/mips/h264dsp_msa.c ffmpeg-4.4/libavcodec/mips/h264dsp_msa.c --- ffmpeg-4.2.2/libavcodec/mips/h264dsp_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/h264dsp_msa.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,7 +21,7 @@ #include "libavutil/mips/generic_macros_msa.h" #include "h264dsp_mips.h" -static void avc_wgt_4x2_msa(uint8_t *data, int32_t stride, +static void avc_wgt_4x2_msa(uint8_t *data, ptrdiff_t stride, int32_t log2_denom, int32_t src_weight, int32_t offset_in) { @@ -48,8 +48,9 @@ ST_W2(src0, 0, 1, data, stride); } -static void avc_wgt_4x4_msa(uint8_t *data, int32_t stride, int32_t log2_denom, - int32_t src_weight, int32_t offset_in) +static void avc_wgt_4x4_msa(uint8_t *data, ptrdiff_t stride, + int32_t log2_denom, int32_t src_weight, + int32_t offset_in) { uint32_t tp0, tp1, tp2, tp3, offset_val; v16u8 src0 = { 0 }; @@ -74,8 +75,9 @@ ST_W4(src0, 0, 1, 2, 3, data, stride); } -static void avc_wgt_4x8_msa(uint8_t *data, int32_t stride, int32_t log2_denom, - int32_t src_weight, int32_t offset_in) +static void avc_wgt_4x8_msa(uint8_t *data, ptrdiff_t stride, + int32_t log2_denom, int32_t src_weight, + int32_t offset_in) { uint32_t tp0, tp1, tp2, tp3, offset_val; v16u8 src0 = { 0 }, src1 = { 0 }; @@ -105,8 +107,9 @@ ST_W8(src0, src1, 0, 1, 2, 3, 0, 1, 2, 3, data, stride); } -static void avc_wgt_8x4_msa(uint8_t *data, int32_t stride, int32_t log2_denom, - int32_t src_weight, int32_t offset_in) +static void avc_wgt_8x4_msa(uint8_t *data, ptrdiff_t stride, + int32_t log2_denom, int32_t src_weight, + int32_t offset_in) { uint32_t offset_val; uint64_t tp0, tp1, tp2, tp3; @@ -136,7 +139,7 @@ ST_D4(src0, src1, 0, 1, 0, 1, data, stride); } -static void avc_wgt_8x8_msa(uint8_t *data, int32_t stride, int32_t log2_denom, +static void avc_wgt_8x8_msa(uint8_t *data, ptrdiff_t stride, int32_t log2_denom, int32_t src_weight, int32_t offset_in) { uint32_t offset_val; @@ -178,8 +181,9 @@ ST_D8(src0, src1, src2, src3, 0, 1, 0, 1, 0, 1, 0, 1, data, stride); } -static void avc_wgt_8x16_msa(uint8_t *data, int32_t stride, int32_t log2_denom, - int32_t src_weight, int32_t offset_in) +static void avc_wgt_8x16_msa(uint8_t *data, ptrdiff_t stride, + int32_t log2_denom, int32_t src_weight, + int32_t offset_in) { uint32_t offset_val, cnt; uint64_t tp0, tp1, tp2, tp3; @@ -223,7 +227,7 @@ } } -static void avc_biwgt_4x2_msa(uint8_t *src, uint8_t *dst, int32_t stride, +static void avc_biwgt_4x2_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride, int32_t log2_denom, int32_t src_weight, int32_t dst_weight, int32_t offset_in) { @@ -256,7 +260,7 @@ ST_W2(dst0, 0, 1, dst, stride); } -static void avc_biwgt_4x4_msa(uint8_t *src, uint8_t *dst, int32_t stride, +static void avc_biwgt_4x4_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride, int32_t log2_denom, int32_t src_weight, int32_t dst_weight, int32_t offset_in) { @@ -290,7 +294,7 @@ ST_W4(dst0, 0, 1, 2, 3, dst, stride); } -static void avc_biwgt_4x8_msa(uint8_t *src, uint8_t *dst, int32_t stride, +static void avc_biwgt_4x8_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride, int32_t log2_denom, int32_t src_weight, int32_t dst_weight, int32_t offset_in) { @@ -330,7 +334,7 @@ ST_W8(dst0, dst1, 0, 1, 2, 3, 0, 1, 2, 3, dst, stride); } -static void avc_biwgt_8x4_msa(uint8_t *src, uint8_t *dst, int32_t stride, +static void avc_biwgt_8x4_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride, int32_t log2_denom, int32_t src_weight, int32_t dst_weight, int32_t offset_in) { @@ -368,7 +372,7 @@ ST_D4(dst0, dst1, 0, 1, 0, 1, dst, stride); } -static void avc_biwgt_8x8_msa(uint8_t *src, uint8_t *dst, int32_t stride, +static void avc_biwgt_8x8_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride, int32_t log2_denom, int32_t src_weight, int32_t dst_weight, int32_t offset_in) { @@ -413,14 +417,13 @@ tmp7 = __msa_dpadd_s_h(offset, wgt, vec7); SRA_4V(tmp0, tmp1, tmp2, tmp3, denom); SRA_4V(tmp4, tmp5, tmp6, tmp7, denom); - CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); - CLIP_SH4_0_255(tmp4, tmp5, tmp6, tmp7); + CLIP_SH8_0_255(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, dst0, dst1); PCKEV_B2_UB(tmp5, tmp4, tmp7, tmp6, dst2, dst3); ST_D8(dst0, dst1, dst2, dst3, 0, 1, 0, 1, 0, 1, 0, 1, dst, stride); } -static void avc_biwgt_8x16_msa(uint8_t *src, uint8_t *dst, int32_t stride, +static void avc_biwgt_8x16_msa(uint8_t *src, uint8_t *dst, ptrdiff_t stride, int32_t log2_denom, int32_t src_weight, int32_t dst_weight, int32_t offset_in) { @@ -475,8 +478,7 @@ SRA_4V(temp0, temp1, temp2, temp3, denom); SRA_4V(temp4, temp5, temp6, temp7, denom); - CLIP_SH4_0_255(temp0, temp1, temp2, temp3); - CLIP_SH4_0_255(temp4, temp5, temp6, temp7); + CLIP_SH8_0_255(temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7); PCKEV_B4_UB(temp1, temp0, temp3, temp2, temp5, temp4, temp7, temp6, dst0, dst1, dst2, dst3); ST_D8(dst0, dst1, dst2, dst3, 0, 1, 0, 1, 0, 1, 0, 1, dst, stride); @@ -531,7 +533,7 @@ temp = p1_or_q1_org_in << 1; \ clip3 = clip3 - temp; \ clip3 = __msa_ave_s_h(p2_or_q2_org_in, clip3); \ - clip3 = CLIP_SH(clip3, negate_tc_in, tc_in); \ + CLIP_SH(clip3, negate_tc_in, tc_in); \ p1_or_q1_out = p1_or_q1_org_in + clip3; \ } @@ -549,7 +551,7 @@ delta = q0_sub_p0 + p1_sub_q1; \ delta >>= 3; \ \ - delta = CLIP_SH(delta, negate_threshold_in, threshold_in); \ + CLIP_SH(delta, negate_threshold_in, threshold_in); \ \ p0_or_q0_out = p0_or_q0_org_in + delta; \ q0_or_p0_out = q0_or_p0_org_in - delta; \ @@ -598,7 +600,7 @@ delta = q0_sub_p0 + p1_sub_q1; \ delta = __msa_srari_h(delta, 3); \ \ - delta = CLIP_SH(delta, -tc, tc); \ + CLIP_SH(delta, -tc, tc); \ \ ILVR_B2_SH(zeros, src1, zeros, src2, res0_r, res1_r); \ \ @@ -620,7 +622,7 @@ \ out0 = (v16u8) __msa_ilvr_b((v16i8) in1, (v16i8) in0); \ out1 = (v16u8) __msa_sldi_b(zero_m, (v16i8) out0, 2); \ - SLDI_B2_0_UB(out1, out2, out2, out3, 2); \ + SLDI_B2_UB(zero_m, out1, zero_m, out2, 2, out2, out3); \ } #define AVC_LPF_H_2BYTE_CHROMA_422(src, stride, tc_val, alpha, beta, res) \ @@ -662,7 +664,7 @@ q0_sub_p0 <<= 2; \ delta = q0_sub_p0 + p1_sub_q1; \ delta = __msa_srari_h(delta, 3); \ - delta = CLIP_SH(delta, -tc, tc); \ + CLIP_SH(delta, -tc, tc); \ \ ILVR_B2_SH(zeros, src1, zeros, src2, res0_r, res1_r); \ \ @@ -681,7 +683,7 @@ static void avc_loopfilter_luma_intra_edge_hor_msa(uint8_t *data, uint8_t alpha_in, uint8_t beta_in, - uint32_t img_width) + ptrdiff_t img_width) { v16u8 p0_asub_q0, p1_asub_p0, q1_asub_q0; v16u8 is_less_than, is_less_than_beta, is_less_than_alpha; @@ -814,7 +816,7 @@ static void avc_loopfilter_luma_intra_edge_ver_msa(uint8_t *data, uint8_t alpha_in, uint8_t beta_in, - uint32_t img_width) + ptrdiff_t img_width) { uint8_t *src = data - 4; v16u8 alpha, beta, p0_asub_q0; @@ -971,7 +973,8 @@ } } -static void avc_h_loop_filter_luma_mbaff_intra_msa(uint8_t *src, int32_t stride, +static void avc_h_loop_filter_luma_mbaff_intra_msa(uint8_t *src, + ptrdiff_t stride, int32_t alpha_in, int32_t beta_in) { @@ -1025,7 +1028,8 @@ ILVR_W2_SB(tmp2, tmp0, tmp3, tmp1, src6, src3); ILVL_W2_SB(tmp2, tmp0, tmp3, tmp1, src1, src5); - SLDI_B4_0_SB(src6, src1, src3, src5, src0, src2, src4, src7, 8); + SLDI_B4_SB(zeros, src6, zeros, src1, zeros, src3, zeros, src5, + 8, src0, src2, src4, src7); p0_asub_q0 = __msa_asub_u_b((v16u8) src2, (v16u8) src3); p1_asub_p0 = __msa_asub_u_b((v16u8) src1, (v16u8) src2); @@ -1116,10 +1120,10 @@ ILVRL_H2_SH(zeros, dst2_x, tmp2, tmp3); ILVR_W2_UB(tmp2, tmp0, tmp3, tmp1, dst0, dst4); - SLDI_B2_0_UB(dst0, dst4, dst1, dst5, 8); + SLDI_B2_UB(zeros, dst0, zeros, dst4, 8, dst1, dst5); dst2_x = (v16u8) __msa_ilvl_w((v4i32) tmp2, (v4i32) tmp0); dst2_y = (v16u8) __msa_ilvl_w((v4i32) tmp3, (v4i32) tmp1); - SLDI_B2_0_UB(dst2_x, dst2_y, dst3_x, dst3_y, 8); + SLDI_B2_UB(zeros, dst2_x, zeros, dst2_y, 8, dst3_x, dst3_y); out0 = __msa_copy_u_w((v4i32) dst0, 0); out1 = __msa_copy_u_h((v8i16) dst0, 2); @@ -1172,7 +1176,7 @@ static void avc_loopfilter_cb_or_cr_intra_edge_hor_msa(uint8_t *data_cb_or_cr, uint8_t alpha_in, uint8_t beta_in, - uint32_t img_width) + ptrdiff_t img_width) { v16u8 alpha, beta; v16u8 is_less_than; @@ -1221,7 +1225,7 @@ static void avc_loopfilter_cb_or_cr_intra_edge_ver_msa(uint8_t *data_cb_or_cr, uint8_t alpha_in, uint8_t beta_in, - uint32_t img_width) + ptrdiff_t img_width) { v8i16 tmp1; v16u8 alpha, beta, is_less_than; @@ -1287,7 +1291,7 @@ uint8_t tc2, uint8_t tc3, uint8_t alpha_in, uint8_t beta_in, - uint32_t img_width) + ptrdiff_t img_width) { v16u8 tmp_vec, bs = { 0 }; @@ -1567,7 +1571,7 @@ uint8_t tc2, uint8_t tc3, uint8_t alpha_in, uint8_t beta_in, - uint32_t image_width) + ptrdiff_t image_width) { v16u8 tmp_vec; v16u8 bs = { 0 }; @@ -1716,7 +1720,7 @@ } } -static void avc_h_loop_filter_luma_mbaff_msa(uint8_t *in, int32_t stride, +static void avc_h_loop_filter_luma_mbaff_msa(uint8_t *in, ptrdiff_t stride, int32_t alpha_in, int32_t beta_in, int8_t *tc0) { @@ -1741,7 +1745,7 @@ v8i16 tc, tc_orig_r, tc_plus1; v16u8 is_tc_orig1, is_tc_orig2, tc_orig = { 0 }; v8i16 p0_ilvr_q0, p0_add_q0, q0_sub_p0, p1_sub_q1; - v8u16 src2_r, src3_r; + v8i16 src2_r, src3_r; v8i16 p2_r, p1_r, q2_r, q1_r; v16u8 p2, q2, p0, q0; v4i32 dst0, dst1; @@ -1839,8 +1843,8 @@ tc_orig_r = (v8i16) __msa_ilvr_b(zeros, (v16i8) tc_orig); tc = tc_orig_r; - p2_r = CLIP_SH(p2_r, -tc_orig_r, tc_orig_r); - q2_r = CLIP_SH(q2_r, -tc_orig_r, tc_orig_r); + CLIP_SH(p2_r, -tc_orig_r, tc_orig_r); + CLIP_SH(q2_r, -tc_orig_r, tc_orig_r); p2_r += p1_r; q2_r += q1_r; @@ -1872,14 +1876,13 @@ (v16i8) is_less_than_beta2); tc = (v8i16) __msa_bmnz_v((v16u8) tc, (v16u8) tc_plus1, is_less_than_beta2); - q0_sub_p0 = CLIP_SH(q0_sub_p0, -tc, tc); + CLIP_SH(q0_sub_p0, -tc, tc); - ILVR_B2_UH(zeros, src2, zeros, src3, src2_r, src3_r); + ILVR_B2_SH(zeros, src2, zeros, src3, src2_r, src3_r); src2_r += q0_sub_p0; src3_r -= q0_sub_p0; - src2_r = (v8u16) CLIP_SH_0_255(src2_r); - src3_r = (v8u16) CLIP_SH_0_255(src3_r); + CLIP_SH2_0_255(src2_r, src3_r); PCKEV_B2_UB(src2_r, src2_r, src3_r, src3_r, p0, q0); @@ -1943,7 +1946,7 @@ uint8_t tc2, uint8_t tc3, uint8_t alpha_in, uint8_t beta_in, - uint32_t img_width) + ptrdiff_t img_width) { v16u8 alpha, beta; v8i16 tmp_vec; @@ -2029,7 +2032,7 @@ uint8_t tc2, uint8_t tc3, uint8_t alpha_in, uint8_t beta_in, - uint32_t img_width) + ptrdiff_t img_width) { uint8_t *src; v16u8 alpha, beta; @@ -2117,7 +2120,7 @@ } } -static void avc_h_loop_filter_chroma422_msa(uint8_t *src, int32_t stride, +static void avc_h_loop_filter_chroma422_msa(uint8_t *src, ptrdiff_t stride, int32_t alpha_in, int32_t beta_in, int8_t *tc0) { @@ -2141,7 +2144,8 @@ } } -static void avc_h_loop_filter_chroma422_mbaff_msa(uint8_t *src, int32_t stride, +static void avc_h_loop_filter_chroma422_mbaff_msa(uint8_t *src, + ptrdiff_t stride, int32_t alpha_in, int32_t beta_in, int8_t *tc0) @@ -2173,7 +2177,7 @@ } } -void ff_h264_h_lpf_luma_inter_msa(uint8_t *data, int img_width, +void ff_h264_h_lpf_luma_inter_msa(uint8_t *data, ptrdiff_t img_width, int alpha, int beta, int8_t *tc) { uint8_t bs0 = 1; @@ -2195,7 +2199,7 @@ alpha, beta, img_width); } -void ff_h264_v_lpf_luma_inter_msa(uint8_t *data, int img_width, +void ff_h264_v_lpf_luma_inter_msa(uint8_t *data, ptrdiff_t img_width, int alpha, int beta, int8_t *tc) { @@ -2218,7 +2222,7 @@ alpha, beta, img_width); } -void ff_h264_h_lpf_chroma_inter_msa(uint8_t *data, int img_width, +void ff_h264_h_lpf_chroma_inter_msa(uint8_t *data, ptrdiff_t img_width, int alpha, int beta, int8_t *tc) { uint8_t bs0 = 1; @@ -2240,7 +2244,7 @@ alpha, beta, img_width); } -void ff_h264_v_lpf_chroma_inter_msa(uint8_t *data, int img_width, +void ff_h264_v_lpf_chroma_inter_msa(uint8_t *data, ptrdiff_t img_width, int alpha, int beta, int8_t *tc) { uint8_t bs0 = 1; @@ -2262,40 +2266,40 @@ alpha, beta, img_width); } -void ff_h264_h_lpf_luma_intra_msa(uint8_t *data, int img_width, +void ff_h264_h_lpf_luma_intra_msa(uint8_t *data, ptrdiff_t img_width, int alpha, int beta) { avc_loopfilter_luma_intra_edge_ver_msa(data, (uint8_t) alpha, (uint8_t) beta, - (unsigned int) img_width); + img_width); } -void ff_h264_v_lpf_luma_intra_msa(uint8_t *data, int img_width, +void ff_h264_v_lpf_luma_intra_msa(uint8_t *data, ptrdiff_t img_width, int alpha, int beta) { avc_loopfilter_luma_intra_edge_hor_msa(data, (uint8_t) alpha, (uint8_t) beta, - (unsigned int) img_width); + img_width); } -void ff_h264_h_lpf_chroma_intra_msa(uint8_t *data, int img_width, +void ff_h264_h_lpf_chroma_intra_msa(uint8_t *data, ptrdiff_t img_width, int alpha, int beta) { avc_loopfilter_cb_or_cr_intra_edge_ver_msa(data, (uint8_t) alpha, (uint8_t) beta, - (unsigned int) img_width); + img_width); } -void ff_h264_v_lpf_chroma_intra_msa(uint8_t *data, int img_width, +void ff_h264_v_lpf_chroma_intra_msa(uint8_t *data, ptrdiff_t img_width, int alpha, int beta) { avc_loopfilter_cb_or_cr_intra_edge_hor_msa(data, (uint8_t) alpha, (uint8_t) beta, - (unsigned int) img_width); + img_width); } void ff_h264_h_loop_filter_chroma422_msa(uint8_t *src, - int32_t ystride, + ptrdiff_t ystride, int32_t alpha, int32_t beta, int8_t *tc0) { @@ -2303,7 +2307,7 @@ } void ff_h264_h_loop_filter_chroma422_mbaff_msa(uint8_t *src, - int32_t ystride, + ptrdiff_t ystride, int32_t alpha, int32_t beta, int8_t *tc0) @@ -2312,7 +2316,7 @@ } void ff_h264_h_loop_filter_luma_mbaff_msa(uint8_t *src, - int32_t ystride, + ptrdiff_t ystride, int32_t alpha, int32_t beta, int8_t *tc0) @@ -2321,7 +2325,7 @@ } void ff_h264_h_loop_filter_luma_mbaff_intra_msa(uint8_t *src, - int32_t ystride, + ptrdiff_t ystride, int32_t alpha, int32_t beta) { @@ -2509,10 +2513,8 @@ SRA_4V(tmp4, tmp5, tmp6, tmp7, denom); SRA_4V(tmp8, tmp9, tmp10, tmp11, denom); SRA_4V(tmp12, tmp13, tmp14, tmp15, denom); - CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); - CLIP_SH4_0_255(tmp4, tmp5, tmp6, tmp7); - CLIP_SH4_0_255(tmp8, tmp9, tmp10, tmp11); - CLIP_SH4_0_255(tmp12, tmp13, tmp14, tmp15); + CLIP_SH8_0_255(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7); + CLIP_SH8_0_255(tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15); PCKEV_B4_UB(tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, tmp7, tmp6, dst0, dst1, dst2, dst3); PCKEV_B4_UB(tmp9, tmp8, tmp11, tmp10, tmp13, tmp12, tmp15, tmp14, dst4, @@ -2553,10 +2555,8 @@ SRA_4V(tmp4, tmp5, tmp6, tmp7, denom); SRA_4V(tmp8, tmp9, tmp10, tmp11, denom); SRA_4V(tmp12, tmp13, tmp14, tmp15, denom); - CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); - CLIP_SH4_0_255(tmp4, tmp5, tmp6, tmp7); - CLIP_SH4_0_255(tmp8, tmp9, tmp10, tmp11); - CLIP_SH4_0_255(tmp12, tmp13, tmp14, tmp15); + CLIP_SH8_0_255(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7); + CLIP_SH8_0_255(tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15); PCKEV_B4_UB(tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, tmp7, tmp6, dst0, dst1, dst2, dst3); PCKEV_B4_UB(tmp9, tmp8, tmp11, tmp10, tmp13, tmp12, tmp15, tmp14, dst4, diff -Nru ffmpeg-4.2.2/libavcodec/mips/h264idct_msa.c ffmpeg-4.4/libavcodec/mips/h264idct_msa.c --- ffmpeg-4.2.2/libavcodec/mips/h264idct_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/h264idct_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -233,8 +233,7 @@ res0, res1, res2, res3); ADD4(res4, tmp4, res5, tmp5, res6, tmp6, res7, tmp7, res4, res5, res6, res7); - CLIP_SH4_0_255(res0, res1, res2, res3); - CLIP_SH4_0_255(res4, res5, res6, res7); + CLIP_SH8_0_255(res0, res1, res2, res3, res4, res5, res6, res7); PCKEV_B4_SB(res1, res0, res3, res2, res5, res4, res7, res6, dst0, dst1, dst2, dst3); ST_D8(dst0, dst1, dst2, dst3, 0, 1, 0, 1, 0, 1, 0, 1, dst, dst_stride) @@ -263,8 +262,8 @@ dst0_r, dst1_r, dst2_r, dst3_r); ADD4(dst4_r, dc, dst5_r, dc, dst6_r, dc, dst7_r, dc, dst4_r, dst5_r, dst6_r, dst7_r); - CLIP_SH4_0_255(dst0_r, dst1_r, dst2_r, dst3_r); - CLIP_SH4_0_255(dst4_r, dst5_r, dst6_r, dst7_r); + CLIP_SH8_0_255(dst0_r, dst1_r, dst2_r, dst3_r, + dst4_r, dst5_r, dst6_r, dst7_r); PCKEV_B4_SB(dst1_r, dst0_r, dst3_r, dst2_r, dst5_r, dst4_r, dst7_r, dst6_r, dst0, dst1, dst2, dst3); ST_D8(dst0, dst1, dst2, dst3, 0, 1, 0, 1, 0, 1, 0, 1, dst, dst_stride) diff -Nru ffmpeg-4.2.2/libavcodec/mips/h264pred_init_mips.c ffmpeg-4.4/libavcodec/mips/h264pred_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/h264pred_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/h264pred_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,137 +19,121 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "config.h" #include "h264dsp_mips.h" #include "h264pred_mips.h" -#if HAVE_MSA -static av_cold void h264_pred_init_msa(H264PredContext *h, int codec_id, - const int bit_depth, - const int chroma_format_idc) +av_cold void ff_h264_pred_init_mips(H264PredContext *h, int codec_id, + int bit_depth, + const int chroma_format_idc) { - if (8 == bit_depth) { - if (chroma_format_idc == 1) { - h->pred8x8[VERT_PRED8x8] = ff_h264_intra_pred_vert_8x8_msa; - h->pred8x8[HOR_PRED8x8] = ff_h264_intra_pred_horiz_8x8_msa; - } + int cpu_flags = av_get_cpu_flags(); - if (codec_id != AV_CODEC_ID_VP7 && codec_id != AV_CODEC_ID_VP8) { + if (have_mmi(cpu_flags)) { + if (bit_depth == 8) { if (chroma_format_idc == 1) { - h->pred8x8[PLANE_PRED8x8] = ff_h264_intra_predict_plane_8x8_msa; + h->pred8x8 [VERT_PRED8x8 ] = ff_pred8x8_vertical_8_mmi; + h->pred8x8 [HOR_PRED8x8 ] = ff_pred8x8_horizontal_8_mmi; + } else { + h->pred8x8 [VERT_PRED8x8 ] = ff_pred8x16_vertical_8_mmi; + h->pred8x8 [HOR_PRED8x8 ] = ff_pred8x16_horizontal_8_mmi; } - } - if (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] = ff_h264_intra_predict_dc_4blk_8x8_msa; - h->pred8x8[LEFT_DC_PRED8x8] = - ff_h264_intra_predict_hor_dc_8x8_msa; - h->pred8x8[TOP_DC_PRED8x8] = - ff_h264_intra_predict_vert_dc_8x8_msa; - h->pred8x8[ALZHEIMER_DC_L0T_PRED8x8] = - ff_h264_intra_predict_mad_cow_dc_l0t_8x8_msa; - h->pred8x8[ALZHEIMER_DC_0LT_PRED8x8] = - ff_h264_intra_predict_mad_cow_dc_0lt_8x8_msa; - h->pred8x8[ALZHEIMER_DC_L00_PRED8x8] = - ff_h264_intra_predict_mad_cow_dc_l00_8x8_msa; - h->pred8x8[ALZHEIMER_DC_0L0_PRED8x8] = - ff_h264_intra_predict_mad_cow_dc_0l0_8x8_msa; - } - } else { - if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) { - h->pred8x8[7] = ff_vp8_pred8x8_127_dc_8_msa; - h->pred8x8[8] = ff_vp8_pred8x8_129_dc_8_msa; - } - } - if (chroma_format_idc == 1) { - h->pred8x8[DC_128_PRED8x8] = ff_h264_intra_pred_dc_128_8x8_msa; - } + h->pred16x16[DC_PRED8x8 ] = ff_pred16x16_dc_8_mmi; + h->pred16x16[VERT_PRED8x8 ] = ff_pred16x16_vertical_8_mmi; + h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_horizontal_8_mmi; + h->pred8x8l [TOP_DC_PRED ] = ff_pred8x8l_top_dc_8_mmi; + h->pred8x8l [DC_PRED ] = ff_pred8x8l_dc_8_mmi; + + #if ARCH_MIPS64 + switch (codec_id) { + case AV_CODEC_ID_SVQ3: + h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_svq3_8_mmi; + break; + case AV_CODEC_ID_RV40: + h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_rv40_8_mmi; + break; + case AV_CODEC_ID_VP7: + case AV_CODEC_ID_VP8: + break; + default: + h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_h264_8_mmi; + break; + } + #endif - h->pred16x16[DC_PRED8x8] = ff_h264_intra_pred_dc_16x16_msa; - h->pred16x16[VERT_PRED8x8] = ff_h264_intra_pred_vert_16x16_msa; - h->pred16x16[HOR_PRED8x8] = ff_h264_intra_pred_horiz_16x16_msa; - - switch (codec_id) { - case AV_CODEC_ID_SVQ3: - ; - break; - case AV_CODEC_ID_RV40: - ; - break; - case AV_CODEC_ID_VP7: - case AV_CODEC_ID_VP8: - h->pred16x16[7] = ff_vp8_pred16x16_127_dc_8_msa; - h->pred16x16[8] = ff_vp8_pred16x16_129_dc_8_msa; - break; - default: - h->pred16x16[PLANE_PRED8x8] = - ff_h264_intra_predict_plane_16x16_msa; - break; + if (codec_id == AV_CODEC_ID_SVQ3 || codec_id == AV_CODEC_ID_H264) { + if (chroma_format_idc == 1) { + h->pred8x8[TOP_DC_PRED8x8 ] = ff_pred8x8_top_dc_8_mmi; + h->pred8x8[DC_PRED8x8 ] = ff_pred8x8_dc_8_mmi; + } + } } - - h->pred16x16[LEFT_DC_PRED8x8] = ff_h264_intra_pred_dc_left_16x16_msa; - h->pred16x16[TOP_DC_PRED8x8] = ff_h264_intra_pred_dc_top_16x16_msa; - h->pred16x16[DC_128_PRED8x8] = ff_h264_intra_pred_dc_128_16x16_msa; } -} -#endif // #if HAVE_MSA -#if HAVE_MMI -static av_cold void h264_pred_init_mmi(H264PredContext *h, int codec_id, - const int bit_depth, const int chroma_format_idc) -{ - if (bit_depth == 8) { - if (chroma_format_idc == 1) { - h->pred8x8 [VERT_PRED8x8 ] = ff_pred8x8_vertical_8_mmi; - h->pred8x8 [HOR_PRED8x8 ] = ff_pred8x8_horizontal_8_mmi; - } else { - h->pred8x8 [VERT_PRED8x8 ] = ff_pred8x16_vertical_8_mmi; - h->pred8x8 [HOR_PRED8x8 ] = ff_pred8x16_horizontal_8_mmi; - } + if (have_msa(cpu_flags)) { + if (8 == bit_depth) { + if (chroma_format_idc == 1) { + h->pred8x8[VERT_PRED8x8] = ff_h264_intra_pred_vert_8x8_msa; + h->pred8x8[HOR_PRED8x8] = ff_h264_intra_pred_horiz_8x8_msa; + } - h->pred16x16[DC_PRED8x8 ] = ff_pred16x16_dc_8_mmi; - h->pred16x16[VERT_PRED8x8 ] = ff_pred16x16_vertical_8_mmi; - h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_horizontal_8_mmi; - h->pred8x8l [TOP_DC_PRED ] = ff_pred8x8l_top_dc_8_mmi; - h->pred8x8l [DC_PRED ] = ff_pred8x8l_dc_8_mmi; - -#if ARCH_MIPS64 - switch (codec_id) { - case AV_CODEC_ID_SVQ3: - h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_svq3_8_mmi; - break; - case AV_CODEC_ID_RV40: - h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_rv40_8_mmi; - break; - case AV_CODEC_ID_VP7: - case AV_CODEC_ID_VP8: - break; - default: - h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_h264_8_mmi; - break; - } -#endif + if (codec_id != AV_CODEC_ID_VP7 && codec_id != AV_CODEC_ID_VP8) { + if (chroma_format_idc == 1) { + h->pred8x8[PLANE_PRED8x8] = ff_h264_intra_predict_plane_8x8_msa; + } + } + if (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] = ff_h264_intra_predict_dc_4blk_8x8_msa; + h->pred8x8[LEFT_DC_PRED8x8] = + ff_h264_intra_predict_hor_dc_8x8_msa; + h->pred8x8[TOP_DC_PRED8x8] = + ff_h264_intra_predict_vert_dc_8x8_msa; + h->pred8x8[ALZHEIMER_DC_L0T_PRED8x8] = + ff_h264_intra_predict_mad_cow_dc_l0t_8x8_msa; + h->pred8x8[ALZHEIMER_DC_0LT_PRED8x8] = + ff_h264_intra_predict_mad_cow_dc_0lt_8x8_msa; + h->pred8x8[ALZHEIMER_DC_L00_PRED8x8] = + ff_h264_intra_predict_mad_cow_dc_l00_8x8_msa; + h->pred8x8[ALZHEIMER_DC_0L0_PRED8x8] = + ff_h264_intra_predict_mad_cow_dc_0l0_8x8_msa; + } + } else { + if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) { + h->pred8x8[7] = ff_vp8_pred8x8_127_dc_8_msa; + h->pred8x8[8] = ff_vp8_pred8x8_129_dc_8_msa; + } + } - if (codec_id == AV_CODEC_ID_SVQ3 || codec_id == AV_CODEC_ID_H264) { if (chroma_format_idc == 1) { - h->pred8x8[TOP_DC_PRED8x8 ] = ff_pred8x8_top_dc_8_mmi; - h->pred8x8[DC_PRED8x8 ] = ff_pred8x8_dc_8_mmi; + h->pred8x8[DC_128_PRED8x8] = ff_h264_intra_pred_dc_128_8x8_msa; + } + + h->pred16x16[DC_PRED8x8] = ff_h264_intra_pred_dc_16x16_msa; + h->pred16x16[VERT_PRED8x8] = ff_h264_intra_pred_vert_16x16_msa; + h->pred16x16[HOR_PRED8x8] = ff_h264_intra_pred_horiz_16x16_msa; + + switch (codec_id) { + case AV_CODEC_ID_SVQ3: + case AV_CODEC_ID_RV40: + break; + case AV_CODEC_ID_VP7: + case AV_CODEC_ID_VP8: + h->pred16x16[7] = ff_vp8_pred16x16_127_dc_8_msa; + h->pred16x16[8] = ff_vp8_pred16x16_129_dc_8_msa; + break; + default: + h->pred16x16[PLANE_PRED8x8] = + ff_h264_intra_predict_plane_16x16_msa; + break; } + + h->pred16x16[LEFT_DC_PRED8x8] = ff_h264_intra_pred_dc_left_16x16_msa; + h->pred16x16[TOP_DC_PRED8x8] = ff_h264_intra_pred_dc_top_16x16_msa; + h->pred16x16[DC_128_PRED8x8] = ff_h264_intra_pred_dc_128_16x16_msa; } } } -#endif /* HAVE_MMI */ - -av_cold void ff_h264_pred_init_mips(H264PredContext *h, int codec_id, - int bit_depth, - const int chroma_format_idc) -{ -#if HAVE_MMI - h264_pred_init_mmi(h, codec_id, bit_depth, chroma_format_idc); -#endif /* HAVE_MMI */ -#if HAVE_MSA - h264_pred_init_msa(h, codec_id, bit_depth, chroma_format_idc); -#endif // #if HAVE_MSA -} diff -Nru ffmpeg-4.2.2/libavcodec/mips/h264pred_mmi.c ffmpeg-4.4/libavcodec/mips/h264pred_mmi.c --- ffmpeg-4.2.2/libavcodec/mips/h264pred_mmi.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/h264pred_mmi.c 2021-04-08 21:28:39.000000000 +0000 @@ -178,7 +178,9 @@ "1: \n\t" "bnez %[has_topright], 2f \n\t" - "pinsrh_3 %[ftmp2], %[ftmp2], %[ftmp4] \n\t" + "dli %[tmp0], 0xa4 \n\t" + "mtc1 %[tmp0], %[ftmp1] \n\t" + "pshufh %[ftmp2], %[ftmp2], %[ftmp1] \n\t" "2: \n\t" "dli %[tmp0], 0x02 \n\t" @@ -370,7 +372,9 @@ "1: \n\t" "bnez %[has_topright], 2f \n\t" - "pinsrh_3 %[ftmp11], %[ftmp11], %[ftmp9] \n\t" + "dli %[tmp0], 0xa4 \n\t" + "mtc1 %[tmp0], %[ftmp1] \n\t" + "pshufh %[ftmp11], %[ftmp11], %[ftmp1] \n\t" "2: \n\t" "dli %[tmp0], 0x02 \n\t" diff -Nru ffmpeg-4.2.2/libavcodec/mips/h264qpel_init_mips.c ffmpeg-4.4/libavcodec/mips/h264qpel_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/h264qpel_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/h264qpel_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,231 +19,221 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "h264dsp_mips.h" -#if HAVE_MSA -static av_cold void h264qpel_init_msa(H264QpelContext *c, int bit_depth) +av_cold void ff_h264qpel_init_mips(H264QpelContext *c, int bit_depth) { - if (8 == bit_depth) { - c->put_h264_qpel_pixels_tab[0][0] = ff_put_h264_qpel16_mc00_msa; - c->put_h264_qpel_pixels_tab[0][1] = ff_put_h264_qpel16_mc10_msa; - c->put_h264_qpel_pixels_tab[0][2] = ff_put_h264_qpel16_mc20_msa; - c->put_h264_qpel_pixels_tab[0][3] = ff_put_h264_qpel16_mc30_msa; - c->put_h264_qpel_pixels_tab[0][4] = ff_put_h264_qpel16_mc01_msa; - c->put_h264_qpel_pixels_tab[0][5] = ff_put_h264_qpel16_mc11_msa; - c->put_h264_qpel_pixels_tab[0][6] = ff_put_h264_qpel16_mc21_msa; - c->put_h264_qpel_pixels_tab[0][7] = ff_put_h264_qpel16_mc31_msa; - c->put_h264_qpel_pixels_tab[0][8] = ff_put_h264_qpel16_mc02_msa; - c->put_h264_qpel_pixels_tab[0][9] = ff_put_h264_qpel16_mc12_msa; - c->put_h264_qpel_pixels_tab[0][10] = ff_put_h264_qpel16_mc22_msa; - c->put_h264_qpel_pixels_tab[0][11] = ff_put_h264_qpel16_mc32_msa; - c->put_h264_qpel_pixels_tab[0][12] = ff_put_h264_qpel16_mc03_msa; - c->put_h264_qpel_pixels_tab[0][13] = ff_put_h264_qpel16_mc13_msa; - c->put_h264_qpel_pixels_tab[0][14] = ff_put_h264_qpel16_mc23_msa; - c->put_h264_qpel_pixels_tab[0][15] = ff_put_h264_qpel16_mc33_msa; - - c->put_h264_qpel_pixels_tab[1][0] = ff_put_h264_qpel8_mc00_msa; - c->put_h264_qpel_pixels_tab[1][1] = ff_put_h264_qpel8_mc10_msa; - c->put_h264_qpel_pixels_tab[1][2] = ff_put_h264_qpel8_mc20_msa; - c->put_h264_qpel_pixels_tab[1][3] = ff_put_h264_qpel8_mc30_msa; - c->put_h264_qpel_pixels_tab[1][4] = ff_put_h264_qpel8_mc01_msa; - c->put_h264_qpel_pixels_tab[1][5] = ff_put_h264_qpel8_mc11_msa; - c->put_h264_qpel_pixels_tab[1][6] = ff_put_h264_qpel8_mc21_msa; - c->put_h264_qpel_pixels_tab[1][7] = ff_put_h264_qpel8_mc31_msa; - c->put_h264_qpel_pixels_tab[1][8] = ff_put_h264_qpel8_mc02_msa; - c->put_h264_qpel_pixels_tab[1][9] = ff_put_h264_qpel8_mc12_msa; - c->put_h264_qpel_pixels_tab[1][10] = ff_put_h264_qpel8_mc22_msa; - c->put_h264_qpel_pixels_tab[1][11] = ff_put_h264_qpel8_mc32_msa; - c->put_h264_qpel_pixels_tab[1][12] = ff_put_h264_qpel8_mc03_msa; - c->put_h264_qpel_pixels_tab[1][13] = ff_put_h264_qpel8_mc13_msa; - c->put_h264_qpel_pixels_tab[1][14] = ff_put_h264_qpel8_mc23_msa; - c->put_h264_qpel_pixels_tab[1][15] = ff_put_h264_qpel8_mc33_msa; - - c->put_h264_qpel_pixels_tab[2][1] = ff_put_h264_qpel4_mc10_msa; - c->put_h264_qpel_pixels_tab[2][2] = ff_put_h264_qpel4_mc20_msa; - c->put_h264_qpel_pixels_tab[2][3] = ff_put_h264_qpel4_mc30_msa; - c->put_h264_qpel_pixels_tab[2][4] = ff_put_h264_qpel4_mc01_msa; - c->put_h264_qpel_pixels_tab[2][5] = ff_put_h264_qpel4_mc11_msa; - c->put_h264_qpel_pixels_tab[2][6] = ff_put_h264_qpel4_mc21_msa; - c->put_h264_qpel_pixels_tab[2][7] = ff_put_h264_qpel4_mc31_msa; - c->put_h264_qpel_pixels_tab[2][8] = ff_put_h264_qpel4_mc02_msa; - c->put_h264_qpel_pixels_tab[2][9] = ff_put_h264_qpel4_mc12_msa; - c->put_h264_qpel_pixels_tab[2][10] = ff_put_h264_qpel4_mc22_msa; - c->put_h264_qpel_pixels_tab[2][11] = ff_put_h264_qpel4_mc32_msa; - c->put_h264_qpel_pixels_tab[2][12] = ff_put_h264_qpel4_mc03_msa; - c->put_h264_qpel_pixels_tab[2][13] = ff_put_h264_qpel4_mc13_msa; - c->put_h264_qpel_pixels_tab[2][14] = ff_put_h264_qpel4_mc23_msa; - c->put_h264_qpel_pixels_tab[2][15] = ff_put_h264_qpel4_mc33_msa; - - c->avg_h264_qpel_pixels_tab[0][0] = ff_avg_h264_qpel16_mc00_msa; - c->avg_h264_qpel_pixels_tab[0][1] = ff_avg_h264_qpel16_mc10_msa; - c->avg_h264_qpel_pixels_tab[0][2] = ff_avg_h264_qpel16_mc20_msa; - c->avg_h264_qpel_pixels_tab[0][3] = ff_avg_h264_qpel16_mc30_msa; - c->avg_h264_qpel_pixels_tab[0][4] = ff_avg_h264_qpel16_mc01_msa; - c->avg_h264_qpel_pixels_tab[0][5] = ff_avg_h264_qpel16_mc11_msa; - c->avg_h264_qpel_pixels_tab[0][6] = ff_avg_h264_qpel16_mc21_msa; - c->avg_h264_qpel_pixels_tab[0][7] = ff_avg_h264_qpel16_mc31_msa; - c->avg_h264_qpel_pixels_tab[0][8] = ff_avg_h264_qpel16_mc02_msa; - c->avg_h264_qpel_pixels_tab[0][9] = ff_avg_h264_qpel16_mc12_msa; - c->avg_h264_qpel_pixels_tab[0][10] = ff_avg_h264_qpel16_mc22_msa; - c->avg_h264_qpel_pixels_tab[0][11] = ff_avg_h264_qpel16_mc32_msa; - c->avg_h264_qpel_pixels_tab[0][12] = ff_avg_h264_qpel16_mc03_msa; - c->avg_h264_qpel_pixels_tab[0][13] = ff_avg_h264_qpel16_mc13_msa; - c->avg_h264_qpel_pixels_tab[0][14] = ff_avg_h264_qpel16_mc23_msa; - c->avg_h264_qpel_pixels_tab[0][15] = ff_avg_h264_qpel16_mc33_msa; - - c->avg_h264_qpel_pixels_tab[1][0] = ff_avg_h264_qpel8_mc00_msa; - c->avg_h264_qpel_pixels_tab[1][1] = ff_avg_h264_qpel8_mc10_msa; - c->avg_h264_qpel_pixels_tab[1][2] = ff_avg_h264_qpel8_mc20_msa; - c->avg_h264_qpel_pixels_tab[1][3] = ff_avg_h264_qpel8_mc30_msa; - c->avg_h264_qpel_pixels_tab[1][4] = ff_avg_h264_qpel8_mc01_msa; - c->avg_h264_qpel_pixels_tab[1][5] = ff_avg_h264_qpel8_mc11_msa; - c->avg_h264_qpel_pixels_tab[1][6] = ff_avg_h264_qpel8_mc21_msa; - c->avg_h264_qpel_pixels_tab[1][7] = ff_avg_h264_qpel8_mc31_msa; - c->avg_h264_qpel_pixels_tab[1][8] = ff_avg_h264_qpel8_mc02_msa; - c->avg_h264_qpel_pixels_tab[1][9] = ff_avg_h264_qpel8_mc12_msa; - c->avg_h264_qpel_pixels_tab[1][10] = ff_avg_h264_qpel8_mc22_msa; - c->avg_h264_qpel_pixels_tab[1][11] = ff_avg_h264_qpel8_mc32_msa; - c->avg_h264_qpel_pixels_tab[1][12] = ff_avg_h264_qpel8_mc03_msa; - c->avg_h264_qpel_pixels_tab[1][13] = ff_avg_h264_qpel8_mc13_msa; - c->avg_h264_qpel_pixels_tab[1][14] = ff_avg_h264_qpel8_mc23_msa; - c->avg_h264_qpel_pixels_tab[1][15] = ff_avg_h264_qpel8_mc33_msa; - - c->avg_h264_qpel_pixels_tab[2][0] = ff_avg_h264_qpel4_mc00_msa; - c->avg_h264_qpel_pixels_tab[2][1] = ff_avg_h264_qpel4_mc10_msa; - c->avg_h264_qpel_pixels_tab[2][2] = ff_avg_h264_qpel4_mc20_msa; - c->avg_h264_qpel_pixels_tab[2][3] = ff_avg_h264_qpel4_mc30_msa; - c->avg_h264_qpel_pixels_tab[2][4] = ff_avg_h264_qpel4_mc01_msa; - c->avg_h264_qpel_pixels_tab[2][5] = ff_avg_h264_qpel4_mc11_msa; - c->avg_h264_qpel_pixels_tab[2][6] = ff_avg_h264_qpel4_mc21_msa; - c->avg_h264_qpel_pixels_tab[2][7] = ff_avg_h264_qpel4_mc31_msa; - c->avg_h264_qpel_pixels_tab[2][8] = ff_avg_h264_qpel4_mc02_msa; - c->avg_h264_qpel_pixels_tab[2][9] = ff_avg_h264_qpel4_mc12_msa; - c->avg_h264_qpel_pixels_tab[2][10] = ff_avg_h264_qpel4_mc22_msa; - c->avg_h264_qpel_pixels_tab[2][11] = ff_avg_h264_qpel4_mc32_msa; - c->avg_h264_qpel_pixels_tab[2][12] = ff_avg_h264_qpel4_mc03_msa; - c->avg_h264_qpel_pixels_tab[2][13] = ff_avg_h264_qpel4_mc13_msa; - c->avg_h264_qpel_pixels_tab[2][14] = ff_avg_h264_qpel4_mc23_msa; - c->avg_h264_qpel_pixels_tab[2][15] = ff_avg_h264_qpel4_mc33_msa; - } -} -#endif // #if HAVE_MSA + int cpu_flags = av_get_cpu_flags(); -#if HAVE_MMI -static av_cold void h264qpel_init_mmi(H264QpelContext *c, int bit_depth) -{ - if (8 == bit_depth) { - c->put_h264_qpel_pixels_tab[0][0] = ff_put_h264_qpel16_mc00_mmi; - c->put_h264_qpel_pixels_tab[0][1] = ff_put_h264_qpel16_mc10_mmi; - c->put_h264_qpel_pixels_tab[0][2] = ff_put_h264_qpel16_mc20_mmi; - c->put_h264_qpel_pixels_tab[0][3] = ff_put_h264_qpel16_mc30_mmi; - c->put_h264_qpel_pixels_tab[0][4] = ff_put_h264_qpel16_mc01_mmi; - c->put_h264_qpel_pixels_tab[0][5] = ff_put_h264_qpel16_mc11_mmi; - c->put_h264_qpel_pixels_tab[0][6] = ff_put_h264_qpel16_mc21_mmi; - c->put_h264_qpel_pixels_tab[0][7] = ff_put_h264_qpel16_mc31_mmi; - c->put_h264_qpel_pixels_tab[0][8] = ff_put_h264_qpel16_mc02_mmi; - c->put_h264_qpel_pixels_tab[0][9] = ff_put_h264_qpel16_mc12_mmi; - c->put_h264_qpel_pixels_tab[0][10] = ff_put_h264_qpel16_mc22_mmi; - c->put_h264_qpel_pixels_tab[0][11] = ff_put_h264_qpel16_mc32_mmi; - c->put_h264_qpel_pixels_tab[0][12] = ff_put_h264_qpel16_mc03_mmi; - c->put_h264_qpel_pixels_tab[0][13] = ff_put_h264_qpel16_mc13_mmi; - c->put_h264_qpel_pixels_tab[0][14] = ff_put_h264_qpel16_mc23_mmi; - c->put_h264_qpel_pixels_tab[0][15] = ff_put_h264_qpel16_mc33_mmi; - - c->put_h264_qpel_pixels_tab[1][0] = ff_put_h264_qpel8_mc00_mmi; - c->put_h264_qpel_pixels_tab[1][1] = ff_put_h264_qpel8_mc10_mmi; - c->put_h264_qpel_pixels_tab[1][2] = ff_put_h264_qpel8_mc20_mmi; - c->put_h264_qpel_pixels_tab[1][3] = ff_put_h264_qpel8_mc30_mmi; - c->put_h264_qpel_pixels_tab[1][4] = ff_put_h264_qpel8_mc01_mmi; - c->put_h264_qpel_pixels_tab[1][5] = ff_put_h264_qpel8_mc11_mmi; - c->put_h264_qpel_pixels_tab[1][6] = ff_put_h264_qpel8_mc21_mmi; - c->put_h264_qpel_pixels_tab[1][7] = ff_put_h264_qpel8_mc31_mmi; - c->put_h264_qpel_pixels_tab[1][8] = ff_put_h264_qpel8_mc02_mmi; - c->put_h264_qpel_pixels_tab[1][9] = ff_put_h264_qpel8_mc12_mmi; - c->put_h264_qpel_pixels_tab[1][10] = ff_put_h264_qpel8_mc22_mmi; - c->put_h264_qpel_pixels_tab[1][11] = ff_put_h264_qpel8_mc32_mmi; - c->put_h264_qpel_pixels_tab[1][12] = ff_put_h264_qpel8_mc03_mmi; - c->put_h264_qpel_pixels_tab[1][13] = ff_put_h264_qpel8_mc13_mmi; - c->put_h264_qpel_pixels_tab[1][14] = ff_put_h264_qpel8_mc23_mmi; - c->put_h264_qpel_pixels_tab[1][15] = ff_put_h264_qpel8_mc33_mmi; - - c->put_h264_qpel_pixels_tab[2][0] = ff_put_h264_qpel4_mc00_mmi; - c->put_h264_qpel_pixels_tab[2][1] = ff_put_h264_qpel4_mc10_mmi; - c->put_h264_qpel_pixels_tab[2][2] = ff_put_h264_qpel4_mc20_mmi; - c->put_h264_qpel_pixels_tab[2][3] = ff_put_h264_qpel4_mc30_mmi; - c->put_h264_qpel_pixels_tab[2][4] = ff_put_h264_qpel4_mc01_mmi; - c->put_h264_qpel_pixels_tab[2][5] = ff_put_h264_qpel4_mc11_mmi; - c->put_h264_qpel_pixels_tab[2][6] = ff_put_h264_qpel4_mc21_mmi; - c->put_h264_qpel_pixels_tab[2][7] = ff_put_h264_qpel4_mc31_mmi; - c->put_h264_qpel_pixels_tab[2][8] = ff_put_h264_qpel4_mc02_mmi; - c->put_h264_qpel_pixels_tab[2][9] = ff_put_h264_qpel4_mc12_mmi; - c->put_h264_qpel_pixels_tab[2][10] = ff_put_h264_qpel4_mc22_mmi; - c->put_h264_qpel_pixels_tab[2][11] = ff_put_h264_qpel4_mc32_mmi; - c->put_h264_qpel_pixels_tab[2][12] = ff_put_h264_qpel4_mc03_mmi; - c->put_h264_qpel_pixels_tab[2][13] = ff_put_h264_qpel4_mc13_mmi; - c->put_h264_qpel_pixels_tab[2][14] = ff_put_h264_qpel4_mc23_mmi; - c->put_h264_qpel_pixels_tab[2][15] = ff_put_h264_qpel4_mc33_mmi; - - c->avg_h264_qpel_pixels_tab[0][0] = ff_avg_h264_qpel16_mc00_mmi; - c->avg_h264_qpel_pixels_tab[0][1] = ff_avg_h264_qpel16_mc10_mmi; - c->avg_h264_qpel_pixels_tab[0][2] = ff_avg_h264_qpel16_mc20_mmi; - c->avg_h264_qpel_pixels_tab[0][3] = ff_avg_h264_qpel16_mc30_mmi; - c->avg_h264_qpel_pixels_tab[0][4] = ff_avg_h264_qpel16_mc01_mmi; - c->avg_h264_qpel_pixels_tab[0][5] = ff_avg_h264_qpel16_mc11_mmi; - c->avg_h264_qpel_pixels_tab[0][6] = ff_avg_h264_qpel16_mc21_mmi; - c->avg_h264_qpel_pixels_tab[0][7] = ff_avg_h264_qpel16_mc31_mmi; - c->avg_h264_qpel_pixels_tab[0][8] = ff_avg_h264_qpel16_mc02_mmi; - c->avg_h264_qpel_pixels_tab[0][9] = ff_avg_h264_qpel16_mc12_mmi; - c->avg_h264_qpel_pixels_tab[0][10] = ff_avg_h264_qpel16_mc22_mmi; - c->avg_h264_qpel_pixels_tab[0][11] = ff_avg_h264_qpel16_mc32_mmi; - c->avg_h264_qpel_pixels_tab[0][12] = ff_avg_h264_qpel16_mc03_mmi; - c->avg_h264_qpel_pixels_tab[0][13] = ff_avg_h264_qpel16_mc13_mmi; - c->avg_h264_qpel_pixels_tab[0][14] = ff_avg_h264_qpel16_mc23_mmi; - c->avg_h264_qpel_pixels_tab[0][15] = ff_avg_h264_qpel16_mc33_mmi; - - c->avg_h264_qpel_pixels_tab[1][0] = ff_avg_h264_qpel8_mc00_mmi; - c->avg_h264_qpel_pixels_tab[1][1] = ff_avg_h264_qpel8_mc10_mmi; - c->avg_h264_qpel_pixels_tab[1][2] = ff_avg_h264_qpel8_mc20_mmi; - c->avg_h264_qpel_pixels_tab[1][3] = ff_avg_h264_qpel8_mc30_mmi; - c->avg_h264_qpel_pixels_tab[1][4] = ff_avg_h264_qpel8_mc01_mmi; - c->avg_h264_qpel_pixels_tab[1][5] = ff_avg_h264_qpel8_mc11_mmi; - c->avg_h264_qpel_pixels_tab[1][6] = ff_avg_h264_qpel8_mc21_mmi; - c->avg_h264_qpel_pixels_tab[1][7] = ff_avg_h264_qpel8_mc31_mmi; - c->avg_h264_qpel_pixels_tab[1][8] = ff_avg_h264_qpel8_mc02_mmi; - c->avg_h264_qpel_pixels_tab[1][9] = ff_avg_h264_qpel8_mc12_mmi; - c->avg_h264_qpel_pixels_tab[1][10] = ff_avg_h264_qpel8_mc22_mmi; - c->avg_h264_qpel_pixels_tab[1][11] = ff_avg_h264_qpel8_mc32_mmi; - c->avg_h264_qpel_pixels_tab[1][12] = ff_avg_h264_qpel8_mc03_mmi; - c->avg_h264_qpel_pixels_tab[1][13] = ff_avg_h264_qpel8_mc13_mmi; - c->avg_h264_qpel_pixels_tab[1][14] = ff_avg_h264_qpel8_mc23_mmi; - c->avg_h264_qpel_pixels_tab[1][15] = ff_avg_h264_qpel8_mc33_mmi; - - c->avg_h264_qpel_pixels_tab[2][0] = ff_avg_h264_qpel4_mc00_mmi; - c->avg_h264_qpel_pixels_tab[2][1] = ff_avg_h264_qpel4_mc10_mmi; - c->avg_h264_qpel_pixels_tab[2][2] = ff_avg_h264_qpel4_mc20_mmi; - c->avg_h264_qpel_pixels_tab[2][3] = ff_avg_h264_qpel4_mc30_mmi; - c->avg_h264_qpel_pixels_tab[2][4] = ff_avg_h264_qpel4_mc01_mmi; - c->avg_h264_qpel_pixels_tab[2][5] = ff_avg_h264_qpel4_mc11_mmi; - c->avg_h264_qpel_pixels_tab[2][6] = ff_avg_h264_qpel4_mc21_mmi; - c->avg_h264_qpel_pixels_tab[2][7] = ff_avg_h264_qpel4_mc31_mmi; - c->avg_h264_qpel_pixels_tab[2][8] = ff_avg_h264_qpel4_mc02_mmi; - c->avg_h264_qpel_pixels_tab[2][9] = ff_avg_h264_qpel4_mc12_mmi; - c->avg_h264_qpel_pixels_tab[2][10] = ff_avg_h264_qpel4_mc22_mmi; - c->avg_h264_qpel_pixels_tab[2][11] = ff_avg_h264_qpel4_mc32_mmi; - c->avg_h264_qpel_pixels_tab[2][12] = ff_avg_h264_qpel4_mc03_mmi; - c->avg_h264_qpel_pixels_tab[2][13] = ff_avg_h264_qpel4_mc13_mmi; - c->avg_h264_qpel_pixels_tab[2][14] = ff_avg_h264_qpel4_mc23_mmi; - c->avg_h264_qpel_pixels_tab[2][15] = ff_avg_h264_qpel4_mc33_mmi; + if (have_mmi(cpu_flags)) { + if (bit_depth == 8) { + c->put_h264_qpel_pixels_tab[0][0] = ff_put_h264_qpel16_mc00_mmi; + c->put_h264_qpel_pixels_tab[0][1] = ff_put_h264_qpel16_mc10_mmi; + c->put_h264_qpel_pixels_tab[0][2] = ff_put_h264_qpel16_mc20_mmi; + c->put_h264_qpel_pixels_tab[0][3] = ff_put_h264_qpel16_mc30_mmi; + c->put_h264_qpel_pixels_tab[0][4] = ff_put_h264_qpel16_mc01_mmi; + c->put_h264_qpel_pixels_tab[0][5] = ff_put_h264_qpel16_mc11_mmi; + c->put_h264_qpel_pixels_tab[0][6] = ff_put_h264_qpel16_mc21_mmi; + c->put_h264_qpel_pixels_tab[0][7] = ff_put_h264_qpel16_mc31_mmi; + c->put_h264_qpel_pixels_tab[0][8] = ff_put_h264_qpel16_mc02_mmi; + c->put_h264_qpel_pixels_tab[0][9] = ff_put_h264_qpel16_mc12_mmi; + c->put_h264_qpel_pixels_tab[0][10] = ff_put_h264_qpel16_mc22_mmi; + c->put_h264_qpel_pixels_tab[0][11] = ff_put_h264_qpel16_mc32_mmi; + c->put_h264_qpel_pixels_tab[0][12] = ff_put_h264_qpel16_mc03_mmi; + c->put_h264_qpel_pixels_tab[0][13] = ff_put_h264_qpel16_mc13_mmi; + c->put_h264_qpel_pixels_tab[0][14] = ff_put_h264_qpel16_mc23_mmi; + c->put_h264_qpel_pixels_tab[0][15] = ff_put_h264_qpel16_mc33_mmi; + + c->put_h264_qpel_pixels_tab[1][0] = ff_put_h264_qpel8_mc00_mmi; + c->put_h264_qpel_pixels_tab[1][1] = ff_put_h264_qpel8_mc10_mmi; + c->put_h264_qpel_pixels_tab[1][2] = ff_put_h264_qpel8_mc20_mmi; + c->put_h264_qpel_pixels_tab[1][3] = ff_put_h264_qpel8_mc30_mmi; + c->put_h264_qpel_pixels_tab[1][4] = ff_put_h264_qpel8_mc01_mmi; + c->put_h264_qpel_pixels_tab[1][5] = ff_put_h264_qpel8_mc11_mmi; + c->put_h264_qpel_pixels_tab[1][6] = ff_put_h264_qpel8_mc21_mmi; + c->put_h264_qpel_pixels_tab[1][7] = ff_put_h264_qpel8_mc31_mmi; + c->put_h264_qpel_pixels_tab[1][8] = ff_put_h264_qpel8_mc02_mmi; + c->put_h264_qpel_pixels_tab[1][9] = ff_put_h264_qpel8_mc12_mmi; + c->put_h264_qpel_pixels_tab[1][10] = ff_put_h264_qpel8_mc22_mmi; + c->put_h264_qpel_pixels_tab[1][11] = ff_put_h264_qpel8_mc32_mmi; + c->put_h264_qpel_pixels_tab[1][12] = ff_put_h264_qpel8_mc03_mmi; + c->put_h264_qpel_pixels_tab[1][13] = ff_put_h264_qpel8_mc13_mmi; + c->put_h264_qpel_pixels_tab[1][14] = ff_put_h264_qpel8_mc23_mmi; + c->put_h264_qpel_pixels_tab[1][15] = ff_put_h264_qpel8_mc33_mmi; + + c->put_h264_qpel_pixels_tab[2][0] = ff_put_h264_qpel4_mc00_mmi; + c->put_h264_qpel_pixels_tab[2][1] = ff_put_h264_qpel4_mc10_mmi; + c->put_h264_qpel_pixels_tab[2][2] = ff_put_h264_qpel4_mc20_mmi; + c->put_h264_qpel_pixels_tab[2][3] = ff_put_h264_qpel4_mc30_mmi; + c->put_h264_qpel_pixels_tab[2][4] = ff_put_h264_qpel4_mc01_mmi; + c->put_h264_qpel_pixels_tab[2][5] = ff_put_h264_qpel4_mc11_mmi; + c->put_h264_qpel_pixels_tab[2][6] = ff_put_h264_qpel4_mc21_mmi; + c->put_h264_qpel_pixels_tab[2][7] = ff_put_h264_qpel4_mc31_mmi; + c->put_h264_qpel_pixels_tab[2][8] = ff_put_h264_qpel4_mc02_mmi; + c->put_h264_qpel_pixels_tab[2][9] = ff_put_h264_qpel4_mc12_mmi; + c->put_h264_qpel_pixels_tab[2][10] = ff_put_h264_qpel4_mc22_mmi; + c->put_h264_qpel_pixels_tab[2][11] = ff_put_h264_qpel4_mc32_mmi; + c->put_h264_qpel_pixels_tab[2][12] = ff_put_h264_qpel4_mc03_mmi; + c->put_h264_qpel_pixels_tab[2][13] = ff_put_h264_qpel4_mc13_mmi; + c->put_h264_qpel_pixels_tab[2][14] = ff_put_h264_qpel4_mc23_mmi; + c->put_h264_qpel_pixels_tab[2][15] = ff_put_h264_qpel4_mc33_mmi; + + c->avg_h264_qpel_pixels_tab[0][0] = ff_avg_h264_qpel16_mc00_mmi; + c->avg_h264_qpel_pixels_tab[0][1] = ff_avg_h264_qpel16_mc10_mmi; + c->avg_h264_qpel_pixels_tab[0][2] = ff_avg_h264_qpel16_mc20_mmi; + c->avg_h264_qpel_pixels_tab[0][3] = ff_avg_h264_qpel16_mc30_mmi; + c->avg_h264_qpel_pixels_tab[0][4] = ff_avg_h264_qpel16_mc01_mmi; + c->avg_h264_qpel_pixels_tab[0][5] = ff_avg_h264_qpel16_mc11_mmi; + c->avg_h264_qpel_pixels_tab[0][6] = ff_avg_h264_qpel16_mc21_mmi; + c->avg_h264_qpel_pixels_tab[0][7] = ff_avg_h264_qpel16_mc31_mmi; + c->avg_h264_qpel_pixels_tab[0][8] = ff_avg_h264_qpel16_mc02_mmi; + c->avg_h264_qpel_pixels_tab[0][9] = ff_avg_h264_qpel16_mc12_mmi; + c->avg_h264_qpel_pixels_tab[0][10] = ff_avg_h264_qpel16_mc22_mmi; + c->avg_h264_qpel_pixels_tab[0][11] = ff_avg_h264_qpel16_mc32_mmi; + c->avg_h264_qpel_pixels_tab[0][12] = ff_avg_h264_qpel16_mc03_mmi; + c->avg_h264_qpel_pixels_tab[0][13] = ff_avg_h264_qpel16_mc13_mmi; + c->avg_h264_qpel_pixels_tab[0][14] = ff_avg_h264_qpel16_mc23_mmi; + c->avg_h264_qpel_pixels_tab[0][15] = ff_avg_h264_qpel16_mc33_mmi; + + c->avg_h264_qpel_pixels_tab[1][0] = ff_avg_h264_qpel8_mc00_mmi; + c->avg_h264_qpel_pixels_tab[1][1] = ff_avg_h264_qpel8_mc10_mmi; + c->avg_h264_qpel_pixels_tab[1][2] = ff_avg_h264_qpel8_mc20_mmi; + c->avg_h264_qpel_pixels_tab[1][3] = ff_avg_h264_qpel8_mc30_mmi; + c->avg_h264_qpel_pixels_tab[1][4] = ff_avg_h264_qpel8_mc01_mmi; + c->avg_h264_qpel_pixels_tab[1][5] = ff_avg_h264_qpel8_mc11_mmi; + c->avg_h264_qpel_pixels_tab[1][6] = ff_avg_h264_qpel8_mc21_mmi; + c->avg_h264_qpel_pixels_tab[1][7] = ff_avg_h264_qpel8_mc31_mmi; + c->avg_h264_qpel_pixels_tab[1][8] = ff_avg_h264_qpel8_mc02_mmi; + c->avg_h264_qpel_pixels_tab[1][9] = ff_avg_h264_qpel8_mc12_mmi; + c->avg_h264_qpel_pixels_tab[1][10] = ff_avg_h264_qpel8_mc22_mmi; + c->avg_h264_qpel_pixels_tab[1][11] = ff_avg_h264_qpel8_mc32_mmi; + c->avg_h264_qpel_pixels_tab[1][12] = ff_avg_h264_qpel8_mc03_mmi; + c->avg_h264_qpel_pixels_tab[1][13] = ff_avg_h264_qpel8_mc13_mmi; + c->avg_h264_qpel_pixels_tab[1][14] = ff_avg_h264_qpel8_mc23_mmi; + c->avg_h264_qpel_pixels_tab[1][15] = ff_avg_h264_qpel8_mc33_mmi; + + c->avg_h264_qpel_pixels_tab[2][0] = ff_avg_h264_qpel4_mc00_mmi; + c->avg_h264_qpel_pixels_tab[2][1] = ff_avg_h264_qpel4_mc10_mmi; + c->avg_h264_qpel_pixels_tab[2][2] = ff_avg_h264_qpel4_mc20_mmi; + c->avg_h264_qpel_pixels_tab[2][3] = ff_avg_h264_qpel4_mc30_mmi; + c->avg_h264_qpel_pixels_tab[2][4] = ff_avg_h264_qpel4_mc01_mmi; + c->avg_h264_qpel_pixels_tab[2][5] = ff_avg_h264_qpel4_mc11_mmi; + c->avg_h264_qpel_pixels_tab[2][6] = ff_avg_h264_qpel4_mc21_mmi; + c->avg_h264_qpel_pixels_tab[2][7] = ff_avg_h264_qpel4_mc31_mmi; + c->avg_h264_qpel_pixels_tab[2][8] = ff_avg_h264_qpel4_mc02_mmi; + c->avg_h264_qpel_pixels_tab[2][9] = ff_avg_h264_qpel4_mc12_mmi; + c->avg_h264_qpel_pixels_tab[2][10] = ff_avg_h264_qpel4_mc22_mmi; + c->avg_h264_qpel_pixels_tab[2][11] = ff_avg_h264_qpel4_mc32_mmi; + c->avg_h264_qpel_pixels_tab[2][12] = ff_avg_h264_qpel4_mc03_mmi; + c->avg_h264_qpel_pixels_tab[2][13] = ff_avg_h264_qpel4_mc13_mmi; + c->avg_h264_qpel_pixels_tab[2][14] = ff_avg_h264_qpel4_mc23_mmi; + c->avg_h264_qpel_pixels_tab[2][15] = ff_avg_h264_qpel4_mc33_mmi; + } } -} -#endif /* HAVE_MMI */ -av_cold void ff_h264qpel_init_mips(H264QpelContext *c, int bit_depth) -{ -#if HAVE_MMI - h264qpel_init_mmi(c, bit_depth); -#endif /* HAVE_MMI */ -#if HAVE_MSA - h264qpel_init_msa(c, bit_depth); -#endif // #if HAVE_MSA + if (have_msa(cpu_flags)) { + if (bit_depth == 8) { + c->put_h264_qpel_pixels_tab[0][0] = ff_put_h264_qpel16_mc00_msa; + c->put_h264_qpel_pixels_tab[0][1] = ff_put_h264_qpel16_mc10_msa; + c->put_h264_qpel_pixels_tab[0][2] = ff_put_h264_qpel16_mc20_msa; + c->put_h264_qpel_pixels_tab[0][3] = ff_put_h264_qpel16_mc30_msa; + c->put_h264_qpel_pixels_tab[0][4] = ff_put_h264_qpel16_mc01_msa; + c->put_h264_qpel_pixels_tab[0][5] = ff_put_h264_qpel16_mc11_msa; + c->put_h264_qpel_pixels_tab[0][6] = ff_put_h264_qpel16_mc21_msa; + c->put_h264_qpel_pixels_tab[0][7] = ff_put_h264_qpel16_mc31_msa; + c->put_h264_qpel_pixels_tab[0][8] = ff_put_h264_qpel16_mc02_msa; + c->put_h264_qpel_pixels_tab[0][9] = ff_put_h264_qpel16_mc12_msa; + c->put_h264_qpel_pixels_tab[0][10] = ff_put_h264_qpel16_mc22_msa; + c->put_h264_qpel_pixels_tab[0][11] = ff_put_h264_qpel16_mc32_msa; + c->put_h264_qpel_pixels_tab[0][12] = ff_put_h264_qpel16_mc03_msa; + c->put_h264_qpel_pixels_tab[0][13] = ff_put_h264_qpel16_mc13_msa; + c->put_h264_qpel_pixels_tab[0][14] = ff_put_h264_qpel16_mc23_msa; + c->put_h264_qpel_pixels_tab[0][15] = ff_put_h264_qpel16_mc33_msa; + + c->put_h264_qpel_pixels_tab[1][0] = ff_put_h264_qpel8_mc00_msa; + c->put_h264_qpel_pixels_tab[1][1] = ff_put_h264_qpel8_mc10_msa; + c->put_h264_qpel_pixels_tab[1][2] = ff_put_h264_qpel8_mc20_msa; + c->put_h264_qpel_pixels_tab[1][3] = ff_put_h264_qpel8_mc30_msa; + c->put_h264_qpel_pixels_tab[1][4] = ff_put_h264_qpel8_mc01_msa; + c->put_h264_qpel_pixels_tab[1][5] = ff_put_h264_qpel8_mc11_msa; + c->put_h264_qpel_pixels_tab[1][6] = ff_put_h264_qpel8_mc21_msa; + c->put_h264_qpel_pixels_tab[1][7] = ff_put_h264_qpel8_mc31_msa; + c->put_h264_qpel_pixels_tab[1][8] = ff_put_h264_qpel8_mc02_msa; + c->put_h264_qpel_pixels_tab[1][9] = ff_put_h264_qpel8_mc12_msa; + c->put_h264_qpel_pixels_tab[1][10] = ff_put_h264_qpel8_mc22_msa; + c->put_h264_qpel_pixels_tab[1][11] = ff_put_h264_qpel8_mc32_msa; + c->put_h264_qpel_pixels_tab[1][12] = ff_put_h264_qpel8_mc03_msa; + c->put_h264_qpel_pixels_tab[1][13] = ff_put_h264_qpel8_mc13_msa; + c->put_h264_qpel_pixels_tab[1][14] = ff_put_h264_qpel8_mc23_msa; + c->put_h264_qpel_pixels_tab[1][15] = ff_put_h264_qpel8_mc33_msa; + + c->put_h264_qpel_pixels_tab[2][1] = ff_put_h264_qpel4_mc10_msa; + c->put_h264_qpel_pixels_tab[2][2] = ff_put_h264_qpel4_mc20_msa; + c->put_h264_qpel_pixels_tab[2][3] = ff_put_h264_qpel4_mc30_msa; + c->put_h264_qpel_pixels_tab[2][4] = ff_put_h264_qpel4_mc01_msa; + c->put_h264_qpel_pixels_tab[2][5] = ff_put_h264_qpel4_mc11_msa; + c->put_h264_qpel_pixels_tab[2][6] = ff_put_h264_qpel4_mc21_msa; + c->put_h264_qpel_pixels_tab[2][7] = ff_put_h264_qpel4_mc31_msa; + c->put_h264_qpel_pixels_tab[2][8] = ff_put_h264_qpel4_mc02_msa; + c->put_h264_qpel_pixels_tab[2][9] = ff_put_h264_qpel4_mc12_msa; + c->put_h264_qpel_pixels_tab[2][10] = ff_put_h264_qpel4_mc22_msa; + c->put_h264_qpel_pixels_tab[2][11] = ff_put_h264_qpel4_mc32_msa; + c->put_h264_qpel_pixels_tab[2][12] = ff_put_h264_qpel4_mc03_msa; + c->put_h264_qpel_pixels_tab[2][13] = ff_put_h264_qpel4_mc13_msa; + c->put_h264_qpel_pixels_tab[2][14] = ff_put_h264_qpel4_mc23_msa; + c->put_h264_qpel_pixels_tab[2][15] = ff_put_h264_qpel4_mc33_msa; + + c->avg_h264_qpel_pixels_tab[0][0] = ff_avg_h264_qpel16_mc00_msa; + c->avg_h264_qpel_pixels_tab[0][1] = ff_avg_h264_qpel16_mc10_msa; + c->avg_h264_qpel_pixels_tab[0][2] = ff_avg_h264_qpel16_mc20_msa; + c->avg_h264_qpel_pixels_tab[0][3] = ff_avg_h264_qpel16_mc30_msa; + c->avg_h264_qpel_pixels_tab[0][4] = ff_avg_h264_qpel16_mc01_msa; + c->avg_h264_qpel_pixels_tab[0][5] = ff_avg_h264_qpel16_mc11_msa; + c->avg_h264_qpel_pixels_tab[0][6] = ff_avg_h264_qpel16_mc21_msa; + c->avg_h264_qpel_pixels_tab[0][7] = ff_avg_h264_qpel16_mc31_msa; + c->avg_h264_qpel_pixels_tab[0][8] = ff_avg_h264_qpel16_mc02_msa; + c->avg_h264_qpel_pixels_tab[0][9] = ff_avg_h264_qpel16_mc12_msa; + c->avg_h264_qpel_pixels_tab[0][10] = ff_avg_h264_qpel16_mc22_msa; + c->avg_h264_qpel_pixels_tab[0][11] = ff_avg_h264_qpel16_mc32_msa; + c->avg_h264_qpel_pixels_tab[0][12] = ff_avg_h264_qpel16_mc03_msa; + c->avg_h264_qpel_pixels_tab[0][13] = ff_avg_h264_qpel16_mc13_msa; + c->avg_h264_qpel_pixels_tab[0][14] = ff_avg_h264_qpel16_mc23_msa; + c->avg_h264_qpel_pixels_tab[0][15] = ff_avg_h264_qpel16_mc33_msa; + + c->avg_h264_qpel_pixels_tab[1][0] = ff_avg_h264_qpel8_mc00_msa; + c->avg_h264_qpel_pixels_tab[1][1] = ff_avg_h264_qpel8_mc10_msa; + c->avg_h264_qpel_pixels_tab[1][2] = ff_avg_h264_qpel8_mc20_msa; + c->avg_h264_qpel_pixels_tab[1][3] = ff_avg_h264_qpel8_mc30_msa; + c->avg_h264_qpel_pixels_tab[1][4] = ff_avg_h264_qpel8_mc01_msa; + c->avg_h264_qpel_pixels_tab[1][5] = ff_avg_h264_qpel8_mc11_msa; + c->avg_h264_qpel_pixels_tab[1][6] = ff_avg_h264_qpel8_mc21_msa; + c->avg_h264_qpel_pixels_tab[1][7] = ff_avg_h264_qpel8_mc31_msa; + c->avg_h264_qpel_pixels_tab[1][8] = ff_avg_h264_qpel8_mc02_msa; + c->avg_h264_qpel_pixels_tab[1][9] = ff_avg_h264_qpel8_mc12_msa; + c->avg_h264_qpel_pixels_tab[1][10] = ff_avg_h264_qpel8_mc22_msa; + c->avg_h264_qpel_pixels_tab[1][11] = ff_avg_h264_qpel8_mc32_msa; + c->avg_h264_qpel_pixels_tab[1][12] = ff_avg_h264_qpel8_mc03_msa; + c->avg_h264_qpel_pixels_tab[1][13] = ff_avg_h264_qpel8_mc13_msa; + c->avg_h264_qpel_pixels_tab[1][14] = ff_avg_h264_qpel8_mc23_msa; + c->avg_h264_qpel_pixels_tab[1][15] = ff_avg_h264_qpel8_mc33_msa; + + c->avg_h264_qpel_pixels_tab[2][0] = ff_avg_h264_qpel4_mc00_msa; + c->avg_h264_qpel_pixels_tab[2][1] = ff_avg_h264_qpel4_mc10_msa; + c->avg_h264_qpel_pixels_tab[2][2] = ff_avg_h264_qpel4_mc20_msa; + c->avg_h264_qpel_pixels_tab[2][3] = ff_avg_h264_qpel4_mc30_msa; + c->avg_h264_qpel_pixels_tab[2][4] = ff_avg_h264_qpel4_mc01_msa; + c->avg_h264_qpel_pixels_tab[2][5] = ff_avg_h264_qpel4_mc11_msa; + c->avg_h264_qpel_pixels_tab[2][6] = ff_avg_h264_qpel4_mc21_msa; + c->avg_h264_qpel_pixels_tab[2][7] = ff_avg_h264_qpel4_mc31_msa; + c->avg_h264_qpel_pixels_tab[2][8] = ff_avg_h264_qpel4_mc02_msa; + c->avg_h264_qpel_pixels_tab[2][9] = ff_avg_h264_qpel4_mc12_msa; + c->avg_h264_qpel_pixels_tab[2][10] = ff_avg_h264_qpel4_mc22_msa; + c->avg_h264_qpel_pixels_tab[2][11] = ff_avg_h264_qpel4_mc32_msa; + c->avg_h264_qpel_pixels_tab[2][12] = ff_avg_h264_qpel4_mc03_msa; + c->avg_h264_qpel_pixels_tab[2][13] = ff_avg_h264_qpel4_mc13_msa; + c->avg_h264_qpel_pixels_tab[2][14] = ff_avg_h264_qpel4_mc23_msa; + c->avg_h264_qpel_pixels_tab[2][15] = ff_avg_h264_qpel4_mc33_msa; + } + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/h264qpel_msa.c ffmpeg-4.4/libavcodec/mips/h264qpel_msa.c --- ffmpeg-4.2.2/libavcodec/mips/h264qpel_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/h264qpel_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -790,8 +790,8 @@ minus5b, res4, res5, res6, res7); DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, plus20b, res4, res5, res6, res7); - SLDI_B2_SB(src1, src3, src0, src2, src0, src2, 2); - SLDI_B2_SB(src5, src7, src4, src6, src4, src6, 2); + SLDI_B4_SB(src1, src0, src3, src2, src5, src4, src7, src6, 2, + src0, src2, src4, src6); SRARI_H4_SH(res0, res1, res2, res3, 5); SRARI_H4_SH(res4, res5, res6, res7, 5); SAT_SH4_SH(res0, res1, res2, res3, 7); @@ -858,8 +858,8 @@ minus5b, res4, res5, res6, res7); DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, plus20b, res4, res5, res6, res7); - SLDI_B2_SB(src1, src3, src0, src2, src0, src2, 3); - SLDI_B2_SB(src5, src7, src4, src6, src4, src6, 3); + SLDI_B4_SB(src1, src0, src3, src2, src5, src4, src7, src6, 3, + src0, src2, src4, src6); SRARI_H4_SH(res0, res1, res2, res3, 5); SRARI_H4_SH(res4, res5, res6, res7, 5); SAT_SH4_SH(res0, res1, res2, res3, 7); @@ -911,10 +911,10 @@ VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec10, vec11); DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, plus20b, res4, res5, res6, res7); - SLDI_B2_SB(src0, src1, src0, src1, src0, src1, 2); - SLDI_B2_SB(src2, src3, src2, src3, src2, src3, 2); - SLDI_B2_SB(src4, src5, src4, src5, src4, src5, 2); - SLDI_B2_SB(src6, src7, src6, src7, src6, src7, 2); + SLDI_B4_SB(src0, src0, src1, src1, src2, src2, src3, src3, 2, + src0, src1, src2, src3); + SLDI_B4_SB(src4, src4, src5, src5, src6, src6, src7, src7, 2, + src4, src5, src6, src7); PCKEV_D2_SB(src1, src0, src3, src2, src0, src1); PCKEV_D2_SB(src5, src4, src7, src6, src4, src5); SRARI_H4_SH(res0, res1, res2, res3, 5); @@ -966,10 +966,10 @@ VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec10, vec11); DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, plus20b, res4, res5, res6, res7); - SLDI_B2_SB(src0, src1, src0, src1, src0, src1, 3); - SLDI_B2_SB(src2, src3, src2, src3, src2, src3, 3); - SLDI_B2_SB(src4, src5, src4, src5, src4, src5, 3); - SLDI_B2_SB(src6, src7, src6, src7, src6, src7, 3); + SLDI_B4_SB(src0, src0, src1, src1, src2, src2, src3, src3, 3, + src0, src1, src2, src3); + SLDI_B4_SB(src4, src4, src5, src5, src6, src6, src7, src7, 3, + src4, src5, src6, src7); PCKEV_D2_SB(src1, src0, src3, src2, src0, src1); PCKEV_D2_SB(src5, src4, src7, src6, src4, src5); SRARI_H4_SH(res0, res1, res2, res3, 5); @@ -1007,8 +1007,8 @@ SRARI_H2_SH(res0, res1, 5); SAT_SH2_SH(res0, res1, 7); res = __msa_pckev_b((v16i8) res1, (v16i8) res0); - SLDI_B2_SB(src0, src1, src0, src1, src0, src1, 2); - SLDI_B2_SB(src2, src3, src2, src3, src2, src3, 2); + SLDI_B4_SB(src0, src0, src1, src1, src2, src2, src3, src3, 2, + src0, src1, src2, src3); src0 = (v16i8) __msa_insve_w((v4i32) src0, 1, (v4i32) src1); src1 = (v16i8) __msa_insve_w((v4i32) src2, 1, (v4i32) src3); src0 = (v16i8) __msa_insve_d((v2i64) src0, 1, (v2i64) src1); @@ -1038,8 +1038,8 @@ SRARI_H2_SH(res0, res1, 5); SAT_SH2_SH(res0, res1, 7); res = __msa_pckev_b((v16i8) res1, (v16i8) res0); - SLDI_B2_SB(src0, src1, src0, src1, src0, src1, 3); - SLDI_B2_SB(src2, src3, src2, src3, src2, src3, 3); + SLDI_B4_SB(src0, src0, src1, src1, src2, src2, src3, src3, 3, + src0, src1, src2, src3); src0 = (v16i8) __msa_insve_w((v4i32) src0, 1, (v4i32) src1); src1 = (v16i8) __msa_insve_w((v4i32) src2, 1, (v4i32) src3); src0 = (v16i8) __msa_insve_d((v2i64) src0, 1, (v2i64) src1); @@ -3194,8 +3194,8 @@ minus5b, res4, res5, res6, res7); DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, plus20b, res4, res5, res6, res7); - SLDI_B2_SB(src1, src3, src0, src2, src0, src2, 2); - SLDI_B2_SB(src5, src7, src4, src6, src4, src6, 2); + SLDI_B4_SB(src1, src0, src3, src2, src5, src4, src7, src6, 2, + src0, src2, src4, src6); SRARI_H4_SH(res0, res1, res2, res3, 5); SRARI_H4_SH(res4, res5, res6, res7, 5); SAT_SH4_SH(res0, res1, res2, res3, 7); @@ -3266,8 +3266,8 @@ minus5b, res4, res5, res6, res7); DPADD_SB4_SH(vec2, vec5, vec8, vec11, plus20b, plus20b, plus20b, plus20b, res4, res5, res6, res7); - SLDI_B2_SB(src1, src3, src0, src2, src0, src2, 3); - SLDI_B2_SB(src5, src7, src4, src6, src4, src6, 3); + SLDI_B4_SB(src1, src0, src3, src2, src5, src4, src7, src6, 3, + src0, src2, src4, src6); SRARI_H4_SH(res0, res1, res2, res3, 5); SRARI_H4_SH(res4, res5, res6, res7, 5); SAT_SH4_SH(res0, res1, res2, res3, 7); @@ -3323,10 +3323,10 @@ VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec10, vec11); DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, plus20b, res4, res5, res6, res7); - SLDI_B2_SB(src0, src1, src0, src1, src0, src1, 2); - SLDI_B2_SB(src2, src3, src2, src3, src2, src3, 2); - SLDI_B2_SB(src4, src5, src4, src5, src4, src5, 2); - SLDI_B2_SB(src6, src7, src6, src7, src6, src7, 2); + SLDI_B4_SB(src0, src0, src1, src1, src2, src2, src3, src3, 2, + src0, src1, src2, src3); + SLDI_B4_SB(src4, src4, src5, src5, src6, src6, src7, src7, 2, + src4, src5, src6, src7); PCKEV_D2_SB(src1, src0, src3, src2, src0, src1); PCKEV_D2_SB(src5, src4, src7, src6, src4, src5); SRARI_H4_SH(res0, res1, res2, res3, 5); @@ -3388,10 +3388,10 @@ VSHF_B2_SB(src6, src6, src7, src7, mask2, mask2, vec10, vec11); DPADD_SB4_SH(vec8, vec9, vec10, vec11, plus20b, plus20b, plus20b, plus20b, res4, res5, res6, res7); - SLDI_B2_SB(src0, src1, src0, src1, src0, src1, 3); - SLDI_B2_SB(src2, src3, src2, src3, src2, src3, 3); - SLDI_B2_SB(src4, src5, src4, src5, src4, src5, 3); - SLDI_B2_SB(src6, src7, src6, src7, src6, src7, 3); + SLDI_B4_SB(src0, src0, src1, src1, src2, src2, src3, src3, 3, + src0, src1, src2, src3); + SLDI_B4_SB(src4, src4, src5, src5, src6, src6, src7, src7, 3, + src4, src5, src6, src7); PCKEV_D2_SB(src1, src0, src3, src2, src0, src1); PCKEV_D2_SB(src5, src4, src7, src6, src4, src5); SRARI_H4_SH(res0, res1, res2, res3, 5); @@ -3439,8 +3439,8 @@ SRARI_H2_SH(out0, out1, 5); SAT_SH2_SH(out0, out1, 7); res = __msa_pckev_b((v16i8) out1, (v16i8) out0); - SLDI_B2_SB(src0, src1, src0, src1, src0, src1, 2); - SLDI_B2_SB(src2, src3, src2, src3, src2, src3, 2); + SLDI_B4_SB(src0, src0, src1, src1, src2, src2, src3, src3, 2, + src0, src1, src2, src3); src0 = (v16i8) __msa_insve_w((v4i32) src0, 1, (v4i32) src1); src1 = (v16i8) __msa_insve_w((v4i32) src2, 1, (v4i32) src3); src0 = (v16i8) __msa_insve_d((v2i64) src0, 1, (v2i64) src1); @@ -3475,8 +3475,8 @@ SRARI_H2_SH(out0, out1, 5); SAT_SH2_SH(out0, out1, 7); res = __msa_pckev_b((v16i8) out1, (v16i8) out0); - SLDI_B2_SB(src0, src1, src0, src1, src0, src1, 3); - SLDI_B2_SB(src2, src3, src2, src3, src2, src3, 3); + SLDI_B4_SB(src0, src0, src1, src1, src2, src2, src3, src3, 3, + src0, src1, src2, src3); src0 = (v16i8) __msa_insve_w((v4i32) src0, 1, (v4i32) src1); src1 = (v16i8) __msa_insve_w((v4i32) src2, 1, (v4i32) src3); src0 = (v16i8) __msa_insve_d((v2i64) src0, 1, (v2i64) src1); diff -Nru ffmpeg-4.2.2/libavcodec/mips/hevcdsp_init_mips.c ffmpeg-4.4/libavcodec/mips/hevcdsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/hevcdsp_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/hevcdsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,512 +18,500 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "libavcodec/mips/hevcdsp_mips.h" -#if HAVE_MMI -static av_cold void hevc_dsp_init_mmi(HEVCDSPContext *c, - const int bit_depth) +void ff_hevc_dsp_init_mips(HEVCDSPContext *c, const int bit_depth) { - if (8 == bit_depth) { - c->put_hevc_qpel[1][0][1] = ff_hevc_put_hevc_qpel_h4_8_mmi; - c->put_hevc_qpel[3][0][1] = ff_hevc_put_hevc_qpel_h8_8_mmi; - c->put_hevc_qpel[4][0][1] = ff_hevc_put_hevc_qpel_h12_8_mmi; - c->put_hevc_qpel[5][0][1] = ff_hevc_put_hevc_qpel_h16_8_mmi; - c->put_hevc_qpel[6][0][1] = ff_hevc_put_hevc_qpel_h24_8_mmi; - c->put_hevc_qpel[7][0][1] = ff_hevc_put_hevc_qpel_h32_8_mmi; - c->put_hevc_qpel[8][0][1] = ff_hevc_put_hevc_qpel_h48_8_mmi; - c->put_hevc_qpel[9][0][1] = ff_hevc_put_hevc_qpel_h64_8_mmi; - - c->put_hevc_qpel[1][1][1] = ff_hevc_put_hevc_qpel_hv4_8_mmi; - c->put_hevc_qpel[3][1][1] = ff_hevc_put_hevc_qpel_hv8_8_mmi; - c->put_hevc_qpel[4][1][1] = ff_hevc_put_hevc_qpel_hv12_8_mmi; - c->put_hevc_qpel[5][1][1] = ff_hevc_put_hevc_qpel_hv16_8_mmi; - c->put_hevc_qpel[6][1][1] = ff_hevc_put_hevc_qpel_hv24_8_mmi; - c->put_hevc_qpel[7][1][1] = ff_hevc_put_hevc_qpel_hv32_8_mmi; - c->put_hevc_qpel[8][1][1] = ff_hevc_put_hevc_qpel_hv48_8_mmi; - c->put_hevc_qpel[9][1][1] = ff_hevc_put_hevc_qpel_hv64_8_mmi; - - c->put_hevc_qpel_bi[1][0][1] = ff_hevc_put_hevc_qpel_bi_h4_8_mmi; - c->put_hevc_qpel_bi[3][0][1] = ff_hevc_put_hevc_qpel_bi_h8_8_mmi; - c->put_hevc_qpel_bi[4][0][1] = ff_hevc_put_hevc_qpel_bi_h12_8_mmi; - c->put_hevc_qpel_bi[5][0][1] = ff_hevc_put_hevc_qpel_bi_h16_8_mmi; - c->put_hevc_qpel_bi[6][0][1] = ff_hevc_put_hevc_qpel_bi_h24_8_mmi; - c->put_hevc_qpel_bi[7][0][1] = ff_hevc_put_hevc_qpel_bi_h32_8_mmi; - c->put_hevc_qpel_bi[8][0][1] = ff_hevc_put_hevc_qpel_bi_h48_8_mmi; - c->put_hevc_qpel_bi[9][0][1] = ff_hevc_put_hevc_qpel_bi_h64_8_mmi; - - c->put_hevc_qpel_bi[1][1][1] = ff_hevc_put_hevc_qpel_bi_hv4_8_mmi; - c->put_hevc_qpel_bi[3][1][1] = ff_hevc_put_hevc_qpel_bi_hv8_8_mmi; - c->put_hevc_qpel_bi[4][1][1] = ff_hevc_put_hevc_qpel_bi_hv12_8_mmi; - c->put_hevc_qpel_bi[5][1][1] = ff_hevc_put_hevc_qpel_bi_hv16_8_mmi; - c->put_hevc_qpel_bi[6][1][1] = ff_hevc_put_hevc_qpel_bi_hv24_8_mmi; - c->put_hevc_qpel_bi[7][1][1] = ff_hevc_put_hevc_qpel_bi_hv32_8_mmi; - c->put_hevc_qpel_bi[8][1][1] = ff_hevc_put_hevc_qpel_bi_hv48_8_mmi; - c->put_hevc_qpel_bi[9][1][1] = ff_hevc_put_hevc_qpel_bi_hv64_8_mmi; - - c->put_hevc_qpel_bi[3][0][0] = ff_hevc_put_hevc_pel_bi_pixels8_8_mmi; - c->put_hevc_qpel_bi[5][0][0] = ff_hevc_put_hevc_pel_bi_pixels16_8_mmi; - c->put_hevc_qpel_bi[6][0][0] = ff_hevc_put_hevc_pel_bi_pixels24_8_mmi; - c->put_hevc_qpel_bi[7][0][0] = ff_hevc_put_hevc_pel_bi_pixels32_8_mmi; - c->put_hevc_qpel_bi[8][0][0] = ff_hevc_put_hevc_pel_bi_pixels48_8_mmi; - c->put_hevc_qpel_bi[9][0][0] = ff_hevc_put_hevc_pel_bi_pixels64_8_mmi; - - c->put_hevc_epel_bi[3][0][0] = ff_hevc_put_hevc_pel_bi_pixels8_8_mmi; - c->put_hevc_epel_bi[5][0][0] = ff_hevc_put_hevc_pel_bi_pixels16_8_mmi; - c->put_hevc_epel_bi[6][0][0] = ff_hevc_put_hevc_pel_bi_pixels24_8_mmi; - c->put_hevc_epel_bi[7][0][0] = ff_hevc_put_hevc_pel_bi_pixels32_8_mmi; - - c->put_hevc_epel_bi[1][1][1] = ff_hevc_put_hevc_epel_bi_hv4_8_mmi; - c->put_hevc_epel_bi[3][1][1] = ff_hevc_put_hevc_epel_bi_hv8_8_mmi; - c->put_hevc_epel_bi[4][1][1] = ff_hevc_put_hevc_epel_bi_hv12_8_mmi; - c->put_hevc_epel_bi[5][1][1] = ff_hevc_put_hevc_epel_bi_hv16_8_mmi; - c->put_hevc_epel_bi[6][1][1] = ff_hevc_put_hevc_epel_bi_hv24_8_mmi; - c->put_hevc_epel_bi[7][1][1] = ff_hevc_put_hevc_epel_bi_hv32_8_mmi; - - c->put_hevc_qpel_uni[1][1][1] = ff_hevc_put_hevc_qpel_uni_hv4_8_mmi; - c->put_hevc_qpel_uni[3][1][1] = ff_hevc_put_hevc_qpel_uni_hv8_8_mmi; - c->put_hevc_qpel_uni[4][1][1] = ff_hevc_put_hevc_qpel_uni_hv12_8_mmi; - c->put_hevc_qpel_uni[5][1][1] = ff_hevc_put_hevc_qpel_uni_hv16_8_mmi; - c->put_hevc_qpel_uni[6][1][1] = ff_hevc_put_hevc_qpel_uni_hv24_8_mmi; - c->put_hevc_qpel_uni[7][1][1] = ff_hevc_put_hevc_qpel_uni_hv32_8_mmi; - c->put_hevc_qpel_uni[8][1][1] = ff_hevc_put_hevc_qpel_uni_hv48_8_mmi; - c->put_hevc_qpel_uni[9][1][1] = ff_hevc_put_hevc_qpel_uni_hv64_8_mmi; - } -} -#endif // #if HAVE_MMI + int cpu_flags = av_get_cpu_flags(); -#if HAVE_MSA -static av_cold void hevc_dsp_init_msa(HEVCDSPContext *c, - const int bit_depth) -{ - if (8 == bit_depth) { - c->put_hevc_qpel[1][0][0] = ff_hevc_put_hevc_pel_pixels4_8_msa; - c->put_hevc_qpel[2][0][0] = ff_hevc_put_hevc_pel_pixels6_8_msa; - c->put_hevc_qpel[3][0][0] = ff_hevc_put_hevc_pel_pixels8_8_msa; - c->put_hevc_qpel[4][0][0] = ff_hevc_put_hevc_pel_pixels12_8_msa; - c->put_hevc_qpel[5][0][0] = ff_hevc_put_hevc_pel_pixels16_8_msa; - c->put_hevc_qpel[6][0][0] = ff_hevc_put_hevc_pel_pixels24_8_msa; - c->put_hevc_qpel[7][0][0] = ff_hevc_put_hevc_pel_pixels32_8_msa; - c->put_hevc_qpel[8][0][0] = ff_hevc_put_hevc_pel_pixels48_8_msa; - c->put_hevc_qpel[9][0][0] = ff_hevc_put_hevc_pel_pixels64_8_msa; - - c->put_hevc_qpel[1][0][1] = ff_hevc_put_hevc_qpel_h4_8_msa; - c->put_hevc_qpel[3][0][1] = ff_hevc_put_hevc_qpel_h8_8_msa; - c->put_hevc_qpel[4][0][1] = ff_hevc_put_hevc_qpel_h12_8_msa; - c->put_hevc_qpel[5][0][1] = ff_hevc_put_hevc_qpel_h16_8_msa; - c->put_hevc_qpel[6][0][1] = ff_hevc_put_hevc_qpel_h24_8_msa; - c->put_hevc_qpel[7][0][1] = ff_hevc_put_hevc_qpel_h32_8_msa; - c->put_hevc_qpel[8][0][1] = ff_hevc_put_hevc_qpel_h48_8_msa; - c->put_hevc_qpel[9][0][1] = ff_hevc_put_hevc_qpel_h64_8_msa; - - c->put_hevc_qpel[1][1][0] = ff_hevc_put_hevc_qpel_v4_8_msa; - c->put_hevc_qpel[3][1][0] = ff_hevc_put_hevc_qpel_v8_8_msa; - c->put_hevc_qpel[4][1][0] = ff_hevc_put_hevc_qpel_v12_8_msa; - c->put_hevc_qpel[5][1][0] = ff_hevc_put_hevc_qpel_v16_8_msa; - c->put_hevc_qpel[6][1][0] = ff_hevc_put_hevc_qpel_v24_8_msa; - c->put_hevc_qpel[7][1][0] = ff_hevc_put_hevc_qpel_v32_8_msa; - c->put_hevc_qpel[8][1][0] = ff_hevc_put_hevc_qpel_v48_8_msa; - c->put_hevc_qpel[9][1][0] = ff_hevc_put_hevc_qpel_v64_8_msa; - - c->put_hevc_qpel[1][1][1] = ff_hevc_put_hevc_qpel_hv4_8_msa; - c->put_hevc_qpel[3][1][1] = ff_hevc_put_hevc_qpel_hv8_8_msa; - c->put_hevc_qpel[4][1][1] = ff_hevc_put_hevc_qpel_hv12_8_msa; - c->put_hevc_qpel[5][1][1] = ff_hevc_put_hevc_qpel_hv16_8_msa; - c->put_hevc_qpel[6][1][1] = ff_hevc_put_hevc_qpel_hv24_8_msa; - c->put_hevc_qpel[7][1][1] = ff_hevc_put_hevc_qpel_hv32_8_msa; - c->put_hevc_qpel[8][1][1] = ff_hevc_put_hevc_qpel_hv48_8_msa; - c->put_hevc_qpel[9][1][1] = ff_hevc_put_hevc_qpel_hv64_8_msa; - - c->put_hevc_epel[1][0][0] = ff_hevc_put_hevc_pel_pixels4_8_msa; - c->put_hevc_epel[2][0][0] = ff_hevc_put_hevc_pel_pixels6_8_msa; - c->put_hevc_epel[3][0][0] = ff_hevc_put_hevc_pel_pixels8_8_msa; - c->put_hevc_epel[4][0][0] = ff_hevc_put_hevc_pel_pixels12_8_msa; - c->put_hevc_epel[5][0][0] = ff_hevc_put_hevc_pel_pixels16_8_msa; - c->put_hevc_epel[6][0][0] = ff_hevc_put_hevc_pel_pixels24_8_msa; - c->put_hevc_epel[7][0][0] = ff_hevc_put_hevc_pel_pixels32_8_msa; - - c->put_hevc_epel[1][0][1] = ff_hevc_put_hevc_epel_h4_8_msa; - c->put_hevc_epel[2][0][1] = ff_hevc_put_hevc_epel_h6_8_msa; - c->put_hevc_epel[3][0][1] = ff_hevc_put_hevc_epel_h8_8_msa; - c->put_hevc_epel[4][0][1] = ff_hevc_put_hevc_epel_h12_8_msa; - c->put_hevc_epel[5][0][1] = ff_hevc_put_hevc_epel_h16_8_msa; - c->put_hevc_epel[6][0][1] = ff_hevc_put_hevc_epel_h24_8_msa; - c->put_hevc_epel[7][0][1] = ff_hevc_put_hevc_epel_h32_8_msa; - - c->put_hevc_epel[1][1][0] = ff_hevc_put_hevc_epel_v4_8_msa; - c->put_hevc_epel[2][1][0] = ff_hevc_put_hevc_epel_v6_8_msa; - c->put_hevc_epel[3][1][0] = ff_hevc_put_hevc_epel_v8_8_msa; - c->put_hevc_epel[4][1][0] = ff_hevc_put_hevc_epel_v12_8_msa; - c->put_hevc_epel[5][1][0] = ff_hevc_put_hevc_epel_v16_8_msa; - c->put_hevc_epel[6][1][0] = ff_hevc_put_hevc_epel_v24_8_msa; - c->put_hevc_epel[7][1][0] = ff_hevc_put_hevc_epel_v32_8_msa; - - c->put_hevc_epel[1][1][1] = ff_hevc_put_hevc_epel_hv4_8_msa; - c->put_hevc_epel[2][1][1] = ff_hevc_put_hevc_epel_hv6_8_msa; - c->put_hevc_epel[3][1][1] = ff_hevc_put_hevc_epel_hv8_8_msa; - c->put_hevc_epel[4][1][1] = ff_hevc_put_hevc_epel_hv12_8_msa; - c->put_hevc_epel[5][1][1] = ff_hevc_put_hevc_epel_hv16_8_msa; - c->put_hevc_epel[6][1][1] = ff_hevc_put_hevc_epel_hv24_8_msa; - c->put_hevc_epel[7][1][1] = ff_hevc_put_hevc_epel_hv32_8_msa; - - c->put_hevc_qpel_uni[3][0][0] = ff_hevc_put_hevc_uni_pel_pixels8_8_msa; - c->put_hevc_qpel_uni[4][0][0] = ff_hevc_put_hevc_uni_pel_pixels12_8_msa; - c->put_hevc_qpel_uni[5][0][0] = ff_hevc_put_hevc_uni_pel_pixels16_8_msa; - c->put_hevc_qpel_uni[6][0][0] = ff_hevc_put_hevc_uni_pel_pixels24_8_msa; - c->put_hevc_qpel_uni[7][0][0] = ff_hevc_put_hevc_uni_pel_pixels32_8_msa; - c->put_hevc_qpel_uni[8][0][0] = ff_hevc_put_hevc_uni_pel_pixels48_8_msa; - c->put_hevc_qpel_uni[9][0][0] = ff_hevc_put_hevc_uni_pel_pixels64_8_msa; - - c->put_hevc_qpel_uni[1][0][1] = ff_hevc_put_hevc_uni_qpel_h4_8_msa; - c->put_hevc_qpel_uni[3][0][1] = ff_hevc_put_hevc_uni_qpel_h8_8_msa; - c->put_hevc_qpel_uni[4][0][1] = ff_hevc_put_hevc_uni_qpel_h12_8_msa; - c->put_hevc_qpel_uni[5][0][1] = ff_hevc_put_hevc_uni_qpel_h16_8_msa; - c->put_hevc_qpel_uni[6][0][1] = ff_hevc_put_hevc_uni_qpel_h24_8_msa; - c->put_hevc_qpel_uni[7][0][1] = ff_hevc_put_hevc_uni_qpel_h32_8_msa; - c->put_hevc_qpel_uni[8][0][1] = ff_hevc_put_hevc_uni_qpel_h48_8_msa; - c->put_hevc_qpel_uni[9][0][1] = ff_hevc_put_hevc_uni_qpel_h64_8_msa; - - c->put_hevc_qpel_uni[1][1][0] = ff_hevc_put_hevc_uni_qpel_v4_8_msa; - c->put_hevc_qpel_uni[3][1][0] = ff_hevc_put_hevc_uni_qpel_v8_8_msa; - c->put_hevc_qpel_uni[4][1][0] = ff_hevc_put_hevc_uni_qpel_v12_8_msa; - c->put_hevc_qpel_uni[5][1][0] = ff_hevc_put_hevc_uni_qpel_v16_8_msa; - c->put_hevc_qpel_uni[6][1][0] = ff_hevc_put_hevc_uni_qpel_v24_8_msa; - c->put_hevc_qpel_uni[7][1][0] = ff_hevc_put_hevc_uni_qpel_v32_8_msa; - c->put_hevc_qpel_uni[8][1][0] = ff_hevc_put_hevc_uni_qpel_v48_8_msa; - c->put_hevc_qpel_uni[9][1][0] = ff_hevc_put_hevc_uni_qpel_v64_8_msa; - - c->put_hevc_qpel_uni[1][1][1] = ff_hevc_put_hevc_uni_qpel_hv4_8_msa; - c->put_hevc_qpel_uni[3][1][1] = ff_hevc_put_hevc_uni_qpel_hv8_8_msa; - c->put_hevc_qpel_uni[4][1][1] = ff_hevc_put_hevc_uni_qpel_hv12_8_msa; - c->put_hevc_qpel_uni[5][1][1] = ff_hevc_put_hevc_uni_qpel_hv16_8_msa; - c->put_hevc_qpel_uni[6][1][1] = ff_hevc_put_hevc_uni_qpel_hv24_8_msa; - c->put_hevc_qpel_uni[7][1][1] = ff_hevc_put_hevc_uni_qpel_hv32_8_msa; - c->put_hevc_qpel_uni[8][1][1] = ff_hevc_put_hevc_uni_qpel_hv48_8_msa; - c->put_hevc_qpel_uni[9][1][1] = ff_hevc_put_hevc_uni_qpel_hv64_8_msa; - - c->put_hevc_epel_uni[3][0][0] = ff_hevc_put_hevc_uni_pel_pixels8_8_msa; - c->put_hevc_epel_uni[4][0][0] = ff_hevc_put_hevc_uni_pel_pixels12_8_msa; - c->put_hevc_epel_uni[5][0][0] = ff_hevc_put_hevc_uni_pel_pixels16_8_msa; - c->put_hevc_epel_uni[6][0][0] = ff_hevc_put_hevc_uni_pel_pixels24_8_msa; - c->put_hevc_epel_uni[7][0][0] = ff_hevc_put_hevc_uni_pel_pixels32_8_msa; - - c->put_hevc_epel_uni[1][0][1] = ff_hevc_put_hevc_uni_epel_h4_8_msa; - c->put_hevc_epel_uni[2][0][1] = ff_hevc_put_hevc_uni_epel_h6_8_msa; - c->put_hevc_epel_uni[3][0][1] = ff_hevc_put_hevc_uni_epel_h8_8_msa; - c->put_hevc_epel_uni[4][0][1] = ff_hevc_put_hevc_uni_epel_h12_8_msa; - c->put_hevc_epel_uni[5][0][1] = ff_hevc_put_hevc_uni_epel_h16_8_msa; - c->put_hevc_epel_uni[6][0][1] = ff_hevc_put_hevc_uni_epel_h24_8_msa; - c->put_hevc_epel_uni[7][0][1] = ff_hevc_put_hevc_uni_epel_h32_8_msa; - - c->put_hevc_epel_uni[1][1][0] = ff_hevc_put_hevc_uni_epel_v4_8_msa; - c->put_hevc_epel_uni[2][1][0] = ff_hevc_put_hevc_uni_epel_v6_8_msa; - c->put_hevc_epel_uni[3][1][0] = ff_hevc_put_hevc_uni_epel_v8_8_msa; - c->put_hevc_epel_uni[4][1][0] = ff_hevc_put_hevc_uni_epel_v12_8_msa; - c->put_hevc_epel_uni[5][1][0] = ff_hevc_put_hevc_uni_epel_v16_8_msa; - c->put_hevc_epel_uni[6][1][0] = ff_hevc_put_hevc_uni_epel_v24_8_msa; - c->put_hevc_epel_uni[7][1][0] = ff_hevc_put_hevc_uni_epel_v32_8_msa; - - c->put_hevc_epel_uni[1][1][1] = ff_hevc_put_hevc_uni_epel_hv4_8_msa; - c->put_hevc_epel_uni[2][1][1] = ff_hevc_put_hevc_uni_epel_hv6_8_msa; - c->put_hevc_epel_uni[3][1][1] = ff_hevc_put_hevc_uni_epel_hv8_8_msa; - c->put_hevc_epel_uni[4][1][1] = ff_hevc_put_hevc_uni_epel_hv12_8_msa; - c->put_hevc_epel_uni[5][1][1] = ff_hevc_put_hevc_uni_epel_hv16_8_msa; - c->put_hevc_epel_uni[6][1][1] = ff_hevc_put_hevc_uni_epel_hv24_8_msa; - c->put_hevc_epel_uni[7][1][1] = ff_hevc_put_hevc_uni_epel_hv32_8_msa; - - c->put_hevc_qpel_uni_w[1][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels4_8_msa; - c->put_hevc_qpel_uni_w[3][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels8_8_msa; - c->put_hevc_qpel_uni_w[4][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels12_8_msa; - c->put_hevc_qpel_uni_w[5][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels16_8_msa; - c->put_hevc_qpel_uni_w[6][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels24_8_msa; - c->put_hevc_qpel_uni_w[7][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels32_8_msa; - c->put_hevc_qpel_uni_w[8][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels48_8_msa; - c->put_hevc_qpel_uni_w[9][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels64_8_msa; - - c->put_hevc_qpel_uni_w[1][0][1] = ff_hevc_put_hevc_uni_w_qpel_h4_8_msa; - c->put_hevc_qpel_uni_w[3][0][1] = ff_hevc_put_hevc_uni_w_qpel_h8_8_msa; - c->put_hevc_qpel_uni_w[4][0][1] = ff_hevc_put_hevc_uni_w_qpel_h12_8_msa; - c->put_hevc_qpel_uni_w[5][0][1] = ff_hevc_put_hevc_uni_w_qpel_h16_8_msa; - c->put_hevc_qpel_uni_w[6][0][1] = ff_hevc_put_hevc_uni_w_qpel_h24_8_msa; - c->put_hevc_qpel_uni_w[7][0][1] = ff_hevc_put_hevc_uni_w_qpel_h32_8_msa; - c->put_hevc_qpel_uni_w[8][0][1] = ff_hevc_put_hevc_uni_w_qpel_h48_8_msa; - c->put_hevc_qpel_uni_w[9][0][1] = ff_hevc_put_hevc_uni_w_qpel_h64_8_msa; - - c->put_hevc_qpel_uni_w[1][1][0] = ff_hevc_put_hevc_uni_w_qpel_v4_8_msa; - c->put_hevc_qpel_uni_w[3][1][0] = ff_hevc_put_hevc_uni_w_qpel_v8_8_msa; - c->put_hevc_qpel_uni_w[4][1][0] = ff_hevc_put_hevc_uni_w_qpel_v12_8_msa; - c->put_hevc_qpel_uni_w[5][1][0] = ff_hevc_put_hevc_uni_w_qpel_v16_8_msa; - c->put_hevc_qpel_uni_w[6][1][0] = ff_hevc_put_hevc_uni_w_qpel_v24_8_msa; - c->put_hevc_qpel_uni_w[7][1][0] = ff_hevc_put_hevc_uni_w_qpel_v32_8_msa; - c->put_hevc_qpel_uni_w[8][1][0] = ff_hevc_put_hevc_uni_w_qpel_v48_8_msa; - c->put_hevc_qpel_uni_w[9][1][0] = ff_hevc_put_hevc_uni_w_qpel_v64_8_msa; - - c->put_hevc_qpel_uni_w[1][1][1] = ff_hevc_put_hevc_uni_w_qpel_hv4_8_msa; - c->put_hevc_qpel_uni_w[3][1][1] = ff_hevc_put_hevc_uni_w_qpel_hv8_8_msa; - c->put_hevc_qpel_uni_w[4][1][1] = - ff_hevc_put_hevc_uni_w_qpel_hv12_8_msa; - c->put_hevc_qpel_uni_w[5][1][1] = - ff_hevc_put_hevc_uni_w_qpel_hv16_8_msa; - c->put_hevc_qpel_uni_w[6][1][1] = - ff_hevc_put_hevc_uni_w_qpel_hv24_8_msa; - c->put_hevc_qpel_uni_w[7][1][1] = - ff_hevc_put_hevc_uni_w_qpel_hv32_8_msa; - c->put_hevc_qpel_uni_w[8][1][1] = - ff_hevc_put_hevc_uni_w_qpel_hv48_8_msa; - c->put_hevc_qpel_uni_w[9][1][1] = - ff_hevc_put_hevc_uni_w_qpel_hv64_8_msa; - - c->put_hevc_epel_uni_w[1][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels4_8_msa; - c->put_hevc_epel_uni_w[2][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels6_8_msa; - c->put_hevc_epel_uni_w[3][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels8_8_msa; - c->put_hevc_epel_uni_w[4][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels12_8_msa; - c->put_hevc_epel_uni_w[5][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels16_8_msa; - c->put_hevc_epel_uni_w[6][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels24_8_msa; - c->put_hevc_epel_uni_w[7][0][0] = - ff_hevc_put_hevc_uni_w_pel_pixels32_8_msa; - - c->put_hevc_epel_uni_w[1][0][1] = ff_hevc_put_hevc_uni_w_epel_h4_8_msa; - c->put_hevc_epel_uni_w[2][0][1] = ff_hevc_put_hevc_uni_w_epel_h6_8_msa; - c->put_hevc_epel_uni_w[3][0][1] = ff_hevc_put_hevc_uni_w_epel_h8_8_msa; - c->put_hevc_epel_uni_w[4][0][1] = ff_hevc_put_hevc_uni_w_epel_h12_8_msa; - c->put_hevc_epel_uni_w[5][0][1] = ff_hevc_put_hevc_uni_w_epel_h16_8_msa; - c->put_hevc_epel_uni_w[6][0][1] = ff_hevc_put_hevc_uni_w_epel_h24_8_msa; - c->put_hevc_epel_uni_w[7][0][1] = ff_hevc_put_hevc_uni_w_epel_h32_8_msa; - - c->put_hevc_epel_uni_w[1][1][0] = ff_hevc_put_hevc_uni_w_epel_v4_8_msa; - c->put_hevc_epel_uni_w[2][1][0] = ff_hevc_put_hevc_uni_w_epel_v6_8_msa; - c->put_hevc_epel_uni_w[3][1][0] = ff_hevc_put_hevc_uni_w_epel_v8_8_msa; - c->put_hevc_epel_uni_w[4][1][0] = ff_hevc_put_hevc_uni_w_epel_v12_8_msa; - c->put_hevc_epel_uni_w[5][1][0] = ff_hevc_put_hevc_uni_w_epel_v16_8_msa; - c->put_hevc_epel_uni_w[6][1][0] = ff_hevc_put_hevc_uni_w_epel_v24_8_msa; - c->put_hevc_epel_uni_w[7][1][0] = ff_hevc_put_hevc_uni_w_epel_v32_8_msa; - - c->put_hevc_epel_uni_w[1][1][1] = ff_hevc_put_hevc_uni_w_epel_hv4_8_msa; - c->put_hevc_epel_uni_w[2][1][1] = ff_hevc_put_hevc_uni_w_epel_hv6_8_msa; - c->put_hevc_epel_uni_w[3][1][1] = ff_hevc_put_hevc_uni_w_epel_hv8_8_msa; - c->put_hevc_epel_uni_w[4][1][1] = - ff_hevc_put_hevc_uni_w_epel_hv12_8_msa; - c->put_hevc_epel_uni_w[5][1][1] = - ff_hevc_put_hevc_uni_w_epel_hv16_8_msa; - c->put_hevc_epel_uni_w[6][1][1] = - ff_hevc_put_hevc_uni_w_epel_hv24_8_msa; - c->put_hevc_epel_uni_w[7][1][1] = - ff_hevc_put_hevc_uni_w_epel_hv32_8_msa; - - c->put_hevc_qpel_bi[1][0][0] = ff_hevc_put_hevc_bi_pel_pixels4_8_msa; - c->put_hevc_qpel_bi[3][0][0] = ff_hevc_put_hevc_bi_pel_pixels8_8_msa; - c->put_hevc_qpel_bi[4][0][0] = ff_hevc_put_hevc_bi_pel_pixels12_8_msa; - c->put_hevc_qpel_bi[5][0][0] = ff_hevc_put_hevc_bi_pel_pixels16_8_msa; - c->put_hevc_qpel_bi[6][0][0] = ff_hevc_put_hevc_bi_pel_pixels24_8_msa; - c->put_hevc_qpel_bi[7][0][0] = ff_hevc_put_hevc_bi_pel_pixels32_8_msa; - c->put_hevc_qpel_bi[8][0][0] = ff_hevc_put_hevc_bi_pel_pixels48_8_msa; - c->put_hevc_qpel_bi[9][0][0] = ff_hevc_put_hevc_bi_pel_pixels64_8_msa; - - c->put_hevc_qpel_bi[1][0][1] = ff_hevc_put_hevc_bi_qpel_h4_8_msa; - c->put_hevc_qpel_bi[3][0][1] = ff_hevc_put_hevc_bi_qpel_h8_8_msa; - c->put_hevc_qpel_bi[4][0][1] = ff_hevc_put_hevc_bi_qpel_h12_8_msa; - c->put_hevc_qpel_bi[5][0][1] = ff_hevc_put_hevc_bi_qpel_h16_8_msa; - c->put_hevc_qpel_bi[6][0][1] = ff_hevc_put_hevc_bi_qpel_h24_8_msa; - c->put_hevc_qpel_bi[7][0][1] = ff_hevc_put_hevc_bi_qpel_h32_8_msa; - c->put_hevc_qpel_bi[8][0][1] = ff_hevc_put_hevc_bi_qpel_h48_8_msa; - c->put_hevc_qpel_bi[9][0][1] = ff_hevc_put_hevc_bi_qpel_h64_8_msa; - - c->put_hevc_qpel_bi[1][1][0] = ff_hevc_put_hevc_bi_qpel_v4_8_msa; - c->put_hevc_qpel_bi[3][1][0] = ff_hevc_put_hevc_bi_qpel_v8_8_msa; - c->put_hevc_qpel_bi[4][1][0] = ff_hevc_put_hevc_bi_qpel_v12_8_msa; - c->put_hevc_qpel_bi[5][1][0] = ff_hevc_put_hevc_bi_qpel_v16_8_msa; - c->put_hevc_qpel_bi[6][1][0] = ff_hevc_put_hevc_bi_qpel_v24_8_msa; - c->put_hevc_qpel_bi[7][1][0] = ff_hevc_put_hevc_bi_qpel_v32_8_msa; - c->put_hevc_qpel_bi[8][1][0] = ff_hevc_put_hevc_bi_qpel_v48_8_msa; - c->put_hevc_qpel_bi[9][1][0] = ff_hevc_put_hevc_bi_qpel_v64_8_msa; - - c->put_hevc_qpel_bi[1][1][1] = ff_hevc_put_hevc_bi_qpel_hv4_8_msa; - c->put_hevc_qpel_bi[3][1][1] = ff_hevc_put_hevc_bi_qpel_hv8_8_msa; - c->put_hevc_qpel_bi[4][1][1] = ff_hevc_put_hevc_bi_qpel_hv12_8_msa; - c->put_hevc_qpel_bi[5][1][1] = ff_hevc_put_hevc_bi_qpel_hv16_8_msa; - c->put_hevc_qpel_bi[6][1][1] = ff_hevc_put_hevc_bi_qpel_hv24_8_msa; - c->put_hevc_qpel_bi[7][1][1] = ff_hevc_put_hevc_bi_qpel_hv32_8_msa; - c->put_hevc_qpel_bi[8][1][1] = ff_hevc_put_hevc_bi_qpel_hv48_8_msa; - c->put_hevc_qpel_bi[9][1][1] = ff_hevc_put_hevc_bi_qpel_hv64_8_msa; - - c->put_hevc_epel_bi[1][0][0] = ff_hevc_put_hevc_bi_pel_pixels4_8_msa; - c->put_hevc_epel_bi[2][0][0] = ff_hevc_put_hevc_bi_pel_pixels6_8_msa; - c->put_hevc_epel_bi[3][0][0] = ff_hevc_put_hevc_bi_pel_pixels8_8_msa; - c->put_hevc_epel_bi[4][0][0] = ff_hevc_put_hevc_bi_pel_pixels12_8_msa; - c->put_hevc_epel_bi[5][0][0] = ff_hevc_put_hevc_bi_pel_pixels16_8_msa; - c->put_hevc_epel_bi[6][0][0] = ff_hevc_put_hevc_bi_pel_pixels24_8_msa; - c->put_hevc_epel_bi[7][0][0] = ff_hevc_put_hevc_bi_pel_pixels32_8_msa; - - c->put_hevc_epel_bi[1][0][1] = ff_hevc_put_hevc_bi_epel_h4_8_msa; - c->put_hevc_epel_bi[2][0][1] = ff_hevc_put_hevc_bi_epel_h6_8_msa; - c->put_hevc_epel_bi[3][0][1] = ff_hevc_put_hevc_bi_epel_h8_8_msa; - c->put_hevc_epel_bi[4][0][1] = ff_hevc_put_hevc_bi_epel_h12_8_msa; - c->put_hevc_epel_bi[5][0][1] = ff_hevc_put_hevc_bi_epel_h16_8_msa; - c->put_hevc_epel_bi[6][0][1] = ff_hevc_put_hevc_bi_epel_h24_8_msa; - c->put_hevc_epel_bi[7][0][1] = ff_hevc_put_hevc_bi_epel_h32_8_msa; - - c->put_hevc_epel_bi[1][1][0] = ff_hevc_put_hevc_bi_epel_v4_8_msa; - c->put_hevc_epel_bi[2][1][0] = ff_hevc_put_hevc_bi_epel_v6_8_msa; - c->put_hevc_epel_bi[3][1][0] = ff_hevc_put_hevc_bi_epel_v8_8_msa; - c->put_hevc_epel_bi[4][1][0] = ff_hevc_put_hevc_bi_epel_v12_8_msa; - c->put_hevc_epel_bi[5][1][0] = ff_hevc_put_hevc_bi_epel_v16_8_msa; - c->put_hevc_epel_bi[6][1][0] = ff_hevc_put_hevc_bi_epel_v24_8_msa; - c->put_hevc_epel_bi[7][1][0] = ff_hevc_put_hevc_bi_epel_v32_8_msa; - - c->put_hevc_epel_bi[1][1][1] = ff_hevc_put_hevc_bi_epel_hv4_8_msa; - c->put_hevc_epel_bi[2][1][1] = ff_hevc_put_hevc_bi_epel_hv6_8_msa; - c->put_hevc_epel_bi[3][1][1] = ff_hevc_put_hevc_bi_epel_hv8_8_msa; - c->put_hevc_epel_bi[4][1][1] = ff_hevc_put_hevc_bi_epel_hv12_8_msa; - c->put_hevc_epel_bi[5][1][1] = ff_hevc_put_hevc_bi_epel_hv16_8_msa; - c->put_hevc_epel_bi[6][1][1] = ff_hevc_put_hevc_bi_epel_hv24_8_msa; - c->put_hevc_epel_bi[7][1][1] = ff_hevc_put_hevc_bi_epel_hv32_8_msa; - - c->put_hevc_qpel_bi_w[1][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels4_8_msa; - c->put_hevc_qpel_bi_w[3][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels8_8_msa; - c->put_hevc_qpel_bi_w[4][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels12_8_msa; - c->put_hevc_qpel_bi_w[5][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels16_8_msa; - c->put_hevc_qpel_bi_w[6][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels24_8_msa; - c->put_hevc_qpel_bi_w[7][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels32_8_msa; - c->put_hevc_qpel_bi_w[8][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels48_8_msa; - c->put_hevc_qpel_bi_w[9][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels64_8_msa; - - c->put_hevc_qpel_bi_w[1][0][1] = ff_hevc_put_hevc_bi_w_qpel_h4_8_msa; - c->put_hevc_qpel_bi_w[3][0][1] = ff_hevc_put_hevc_bi_w_qpel_h8_8_msa; - c->put_hevc_qpel_bi_w[4][0][1] = ff_hevc_put_hevc_bi_w_qpel_h12_8_msa; - c->put_hevc_qpel_bi_w[5][0][1] = ff_hevc_put_hevc_bi_w_qpel_h16_8_msa; - c->put_hevc_qpel_bi_w[6][0][1] = ff_hevc_put_hevc_bi_w_qpel_h24_8_msa; - c->put_hevc_qpel_bi_w[7][0][1] = ff_hevc_put_hevc_bi_w_qpel_h32_8_msa; - c->put_hevc_qpel_bi_w[8][0][1] = ff_hevc_put_hevc_bi_w_qpel_h48_8_msa; - c->put_hevc_qpel_bi_w[9][0][1] = ff_hevc_put_hevc_bi_w_qpel_h64_8_msa; - - c->put_hevc_qpel_bi_w[1][1][0] = ff_hevc_put_hevc_bi_w_qpel_v4_8_msa; - c->put_hevc_qpel_bi_w[3][1][0] = ff_hevc_put_hevc_bi_w_qpel_v8_8_msa; - c->put_hevc_qpel_bi_w[4][1][0] = ff_hevc_put_hevc_bi_w_qpel_v12_8_msa; - c->put_hevc_qpel_bi_w[5][1][0] = ff_hevc_put_hevc_bi_w_qpel_v16_8_msa; - c->put_hevc_qpel_bi_w[6][1][0] = ff_hevc_put_hevc_bi_w_qpel_v24_8_msa; - c->put_hevc_qpel_bi_w[7][1][0] = ff_hevc_put_hevc_bi_w_qpel_v32_8_msa; - c->put_hevc_qpel_bi_w[8][1][0] = ff_hevc_put_hevc_bi_w_qpel_v48_8_msa; - c->put_hevc_qpel_bi_w[9][1][0] = ff_hevc_put_hevc_bi_w_qpel_v64_8_msa; - - c->put_hevc_qpel_bi_w[1][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv4_8_msa; - c->put_hevc_qpel_bi_w[3][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv8_8_msa; - c->put_hevc_qpel_bi_w[4][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv12_8_msa; - c->put_hevc_qpel_bi_w[5][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv16_8_msa; - c->put_hevc_qpel_bi_w[6][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv24_8_msa; - c->put_hevc_qpel_bi_w[7][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv32_8_msa; - c->put_hevc_qpel_bi_w[8][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv48_8_msa; - c->put_hevc_qpel_bi_w[9][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv64_8_msa; - - c->put_hevc_epel_bi_w[1][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels4_8_msa; - c->put_hevc_epel_bi_w[2][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels6_8_msa; - c->put_hevc_epel_bi_w[3][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels8_8_msa; - c->put_hevc_epel_bi_w[4][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels12_8_msa; - c->put_hevc_epel_bi_w[5][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels16_8_msa; - c->put_hevc_epel_bi_w[6][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels24_8_msa; - c->put_hevc_epel_bi_w[7][0][0] = - ff_hevc_put_hevc_bi_w_pel_pixels32_8_msa; - - c->put_hevc_epel_bi_w[1][0][1] = ff_hevc_put_hevc_bi_w_epel_h4_8_msa; - c->put_hevc_epel_bi_w[2][0][1] = ff_hevc_put_hevc_bi_w_epel_h6_8_msa; - c->put_hevc_epel_bi_w[3][0][1] = ff_hevc_put_hevc_bi_w_epel_h8_8_msa; - c->put_hevc_epel_bi_w[4][0][1] = ff_hevc_put_hevc_bi_w_epel_h12_8_msa; - c->put_hevc_epel_bi_w[5][0][1] = ff_hevc_put_hevc_bi_w_epel_h16_8_msa; - c->put_hevc_epel_bi_w[6][0][1] = ff_hevc_put_hevc_bi_w_epel_h24_8_msa; - c->put_hevc_epel_bi_w[7][0][1] = ff_hevc_put_hevc_bi_w_epel_h32_8_msa; - - c->put_hevc_epel_bi_w[1][1][0] = ff_hevc_put_hevc_bi_w_epel_v4_8_msa; - c->put_hevc_epel_bi_w[2][1][0] = ff_hevc_put_hevc_bi_w_epel_v6_8_msa; - c->put_hevc_epel_bi_w[3][1][0] = ff_hevc_put_hevc_bi_w_epel_v8_8_msa; - c->put_hevc_epel_bi_w[4][1][0] = ff_hevc_put_hevc_bi_w_epel_v12_8_msa; - c->put_hevc_epel_bi_w[5][1][0] = ff_hevc_put_hevc_bi_w_epel_v16_8_msa; - c->put_hevc_epel_bi_w[6][1][0] = ff_hevc_put_hevc_bi_w_epel_v24_8_msa; - c->put_hevc_epel_bi_w[7][1][0] = ff_hevc_put_hevc_bi_w_epel_v32_8_msa; - - c->put_hevc_epel_bi_w[1][1][1] = ff_hevc_put_hevc_bi_w_epel_hv4_8_msa; - c->put_hevc_epel_bi_w[2][1][1] = ff_hevc_put_hevc_bi_w_epel_hv6_8_msa; - c->put_hevc_epel_bi_w[3][1][1] = ff_hevc_put_hevc_bi_w_epel_hv8_8_msa; - c->put_hevc_epel_bi_w[4][1][1] = ff_hevc_put_hevc_bi_w_epel_hv12_8_msa; - c->put_hevc_epel_bi_w[5][1][1] = ff_hevc_put_hevc_bi_w_epel_hv16_8_msa; - c->put_hevc_epel_bi_w[6][1][1] = ff_hevc_put_hevc_bi_w_epel_hv24_8_msa; - c->put_hevc_epel_bi_w[7][1][1] = ff_hevc_put_hevc_bi_w_epel_hv32_8_msa; - - c->sao_band_filter[0] = - c->sao_band_filter[1] = - c->sao_band_filter[2] = - c->sao_band_filter[3] = - c->sao_band_filter[4] = ff_hevc_sao_band_filter_0_8_msa; - - c->sao_edge_filter[0] = - c->sao_edge_filter[1] = - c->sao_edge_filter[2] = - c->sao_edge_filter[3] = - c->sao_edge_filter[4] = ff_hevc_sao_edge_filter_8_msa; - - c->hevc_h_loop_filter_luma = ff_hevc_loop_filter_luma_h_8_msa; - c->hevc_v_loop_filter_luma = ff_hevc_loop_filter_luma_v_8_msa; - - c->hevc_h_loop_filter_chroma = ff_hevc_loop_filter_chroma_h_8_msa; - c->hevc_v_loop_filter_chroma = ff_hevc_loop_filter_chroma_v_8_msa; - - c->hevc_h_loop_filter_luma_c = ff_hevc_loop_filter_luma_h_8_msa; - c->hevc_v_loop_filter_luma_c = ff_hevc_loop_filter_luma_v_8_msa; - - c->hevc_h_loop_filter_chroma_c = - ff_hevc_loop_filter_chroma_h_8_msa; - c->hevc_v_loop_filter_chroma_c = - ff_hevc_loop_filter_chroma_v_8_msa; - - c->idct[0] = ff_hevc_idct_4x4_msa; - c->idct[1] = ff_hevc_idct_8x8_msa; - c->idct[2] = ff_hevc_idct_16x16_msa; - c->idct[3] = ff_hevc_idct_32x32_msa; - c->idct_dc[0] = ff_hevc_idct_dc_4x4_msa; - c->idct_dc[1] = ff_hevc_idct_dc_8x8_msa; - c->idct_dc[2] = ff_hevc_idct_dc_16x16_msa; - c->idct_dc[3] = ff_hevc_idct_dc_32x32_msa; - c->add_residual[0] = ff_hevc_addblk_4x4_msa; - c->add_residual[1] = ff_hevc_addblk_8x8_msa; - c->add_residual[2] = ff_hevc_addblk_16x16_msa; - c->add_residual[3] = ff_hevc_addblk_32x32_msa; - c->transform_4x4_luma = ff_hevc_idct_luma_4x4_msa; + if (have_mmi(cpu_flags)) { + if (bit_depth == 8) { + c->put_hevc_qpel[1][0][1] = ff_hevc_put_hevc_qpel_h4_8_mmi; + c->put_hevc_qpel[3][0][1] = ff_hevc_put_hevc_qpel_h8_8_mmi; + c->put_hevc_qpel[4][0][1] = ff_hevc_put_hevc_qpel_h12_8_mmi; + c->put_hevc_qpel[5][0][1] = ff_hevc_put_hevc_qpel_h16_8_mmi; + c->put_hevc_qpel[6][0][1] = ff_hevc_put_hevc_qpel_h24_8_mmi; + c->put_hevc_qpel[7][0][1] = ff_hevc_put_hevc_qpel_h32_8_mmi; + c->put_hevc_qpel[8][0][1] = ff_hevc_put_hevc_qpel_h48_8_mmi; + c->put_hevc_qpel[9][0][1] = ff_hevc_put_hevc_qpel_h64_8_mmi; + + c->put_hevc_qpel[1][1][1] = ff_hevc_put_hevc_qpel_hv4_8_mmi; + c->put_hevc_qpel[3][1][1] = ff_hevc_put_hevc_qpel_hv8_8_mmi; + c->put_hevc_qpel[4][1][1] = ff_hevc_put_hevc_qpel_hv12_8_mmi; + c->put_hevc_qpel[5][1][1] = ff_hevc_put_hevc_qpel_hv16_8_mmi; + c->put_hevc_qpel[6][1][1] = ff_hevc_put_hevc_qpel_hv24_8_mmi; + c->put_hevc_qpel[7][1][1] = ff_hevc_put_hevc_qpel_hv32_8_mmi; + c->put_hevc_qpel[8][1][1] = ff_hevc_put_hevc_qpel_hv48_8_mmi; + c->put_hevc_qpel[9][1][1] = ff_hevc_put_hevc_qpel_hv64_8_mmi; + + c->put_hevc_qpel_bi[1][0][1] = ff_hevc_put_hevc_qpel_bi_h4_8_mmi; + c->put_hevc_qpel_bi[3][0][1] = ff_hevc_put_hevc_qpel_bi_h8_8_mmi; + c->put_hevc_qpel_bi[4][0][1] = ff_hevc_put_hevc_qpel_bi_h12_8_mmi; + c->put_hevc_qpel_bi[5][0][1] = ff_hevc_put_hevc_qpel_bi_h16_8_mmi; + c->put_hevc_qpel_bi[6][0][1] = ff_hevc_put_hevc_qpel_bi_h24_8_mmi; + c->put_hevc_qpel_bi[7][0][1] = ff_hevc_put_hevc_qpel_bi_h32_8_mmi; + c->put_hevc_qpel_bi[8][0][1] = ff_hevc_put_hevc_qpel_bi_h48_8_mmi; + c->put_hevc_qpel_bi[9][0][1] = ff_hevc_put_hevc_qpel_bi_h64_8_mmi; + + c->put_hevc_qpel_bi[1][1][1] = ff_hevc_put_hevc_qpel_bi_hv4_8_mmi; + c->put_hevc_qpel_bi[3][1][1] = ff_hevc_put_hevc_qpel_bi_hv8_8_mmi; + c->put_hevc_qpel_bi[4][1][1] = ff_hevc_put_hevc_qpel_bi_hv12_8_mmi; + c->put_hevc_qpel_bi[5][1][1] = ff_hevc_put_hevc_qpel_bi_hv16_8_mmi; + c->put_hevc_qpel_bi[6][1][1] = ff_hevc_put_hevc_qpel_bi_hv24_8_mmi; + c->put_hevc_qpel_bi[7][1][1] = ff_hevc_put_hevc_qpel_bi_hv32_8_mmi; + c->put_hevc_qpel_bi[8][1][1] = ff_hevc_put_hevc_qpel_bi_hv48_8_mmi; + c->put_hevc_qpel_bi[9][1][1] = ff_hevc_put_hevc_qpel_bi_hv64_8_mmi; + + c->put_hevc_qpel_bi[3][0][0] = ff_hevc_put_hevc_pel_bi_pixels8_8_mmi; + c->put_hevc_qpel_bi[5][0][0] = ff_hevc_put_hevc_pel_bi_pixels16_8_mmi; + c->put_hevc_qpel_bi[6][0][0] = ff_hevc_put_hevc_pel_bi_pixels24_8_mmi; + c->put_hevc_qpel_bi[7][0][0] = ff_hevc_put_hevc_pel_bi_pixels32_8_mmi; + c->put_hevc_qpel_bi[8][0][0] = ff_hevc_put_hevc_pel_bi_pixels48_8_mmi; + c->put_hevc_qpel_bi[9][0][0] = ff_hevc_put_hevc_pel_bi_pixels64_8_mmi; + + c->put_hevc_epel_bi[3][0][0] = ff_hevc_put_hevc_pel_bi_pixels8_8_mmi; + c->put_hevc_epel_bi[5][0][0] = ff_hevc_put_hevc_pel_bi_pixels16_8_mmi; + c->put_hevc_epel_bi[6][0][0] = ff_hevc_put_hevc_pel_bi_pixels24_8_mmi; + c->put_hevc_epel_bi[7][0][0] = ff_hevc_put_hevc_pel_bi_pixels32_8_mmi; + + c->put_hevc_epel_bi[1][1][1] = ff_hevc_put_hevc_epel_bi_hv4_8_mmi; + c->put_hevc_epel_bi[3][1][1] = ff_hevc_put_hevc_epel_bi_hv8_8_mmi; + c->put_hevc_epel_bi[4][1][1] = ff_hevc_put_hevc_epel_bi_hv12_8_mmi; + c->put_hevc_epel_bi[5][1][1] = ff_hevc_put_hevc_epel_bi_hv16_8_mmi; + c->put_hevc_epel_bi[6][1][1] = ff_hevc_put_hevc_epel_bi_hv24_8_mmi; + c->put_hevc_epel_bi[7][1][1] = ff_hevc_put_hevc_epel_bi_hv32_8_mmi; + + c->put_hevc_qpel_uni[1][1][1] = ff_hevc_put_hevc_qpel_uni_hv4_8_mmi; + c->put_hevc_qpel_uni[3][1][1] = ff_hevc_put_hevc_qpel_uni_hv8_8_mmi; + c->put_hevc_qpel_uni[4][1][1] = ff_hevc_put_hevc_qpel_uni_hv12_8_mmi; + c->put_hevc_qpel_uni[5][1][1] = ff_hevc_put_hevc_qpel_uni_hv16_8_mmi; + c->put_hevc_qpel_uni[6][1][1] = ff_hevc_put_hevc_qpel_uni_hv24_8_mmi; + c->put_hevc_qpel_uni[7][1][1] = ff_hevc_put_hevc_qpel_uni_hv32_8_mmi; + c->put_hevc_qpel_uni[8][1][1] = ff_hevc_put_hevc_qpel_uni_hv48_8_mmi; + c->put_hevc_qpel_uni[9][1][1] = ff_hevc_put_hevc_qpel_uni_hv64_8_mmi; + } } -} -#endif // #if HAVE_MSA -void ff_hevc_dsp_init_mips(HEVCDSPContext *c, const int bit_depth) -{ -#if HAVE_MMI - hevc_dsp_init_mmi(c, bit_depth); -#endif // #if HAVE_MMI -#if HAVE_MSA - hevc_dsp_init_msa(c, bit_depth); -#endif // #if HAVE_MSA + if (have_msa(cpu_flags)) { + if (bit_depth == 8) { + c->put_hevc_qpel[1][0][0] = ff_hevc_put_hevc_pel_pixels4_8_msa; + c->put_hevc_qpel[2][0][0] = ff_hevc_put_hevc_pel_pixels6_8_msa; + c->put_hevc_qpel[3][0][0] = ff_hevc_put_hevc_pel_pixels8_8_msa; + c->put_hevc_qpel[4][0][0] = ff_hevc_put_hevc_pel_pixels12_8_msa; + c->put_hevc_qpel[5][0][0] = ff_hevc_put_hevc_pel_pixels16_8_msa; + c->put_hevc_qpel[6][0][0] = ff_hevc_put_hevc_pel_pixels24_8_msa; + c->put_hevc_qpel[7][0][0] = ff_hevc_put_hevc_pel_pixels32_8_msa; + c->put_hevc_qpel[8][0][0] = ff_hevc_put_hevc_pel_pixels48_8_msa; + c->put_hevc_qpel[9][0][0] = ff_hevc_put_hevc_pel_pixels64_8_msa; + + c->put_hevc_qpel[1][0][1] = ff_hevc_put_hevc_qpel_h4_8_msa; + c->put_hevc_qpel[3][0][1] = ff_hevc_put_hevc_qpel_h8_8_msa; + c->put_hevc_qpel[4][0][1] = ff_hevc_put_hevc_qpel_h12_8_msa; + c->put_hevc_qpel[5][0][1] = ff_hevc_put_hevc_qpel_h16_8_msa; + c->put_hevc_qpel[6][0][1] = ff_hevc_put_hevc_qpel_h24_8_msa; + c->put_hevc_qpel[7][0][1] = ff_hevc_put_hevc_qpel_h32_8_msa; + c->put_hevc_qpel[8][0][1] = ff_hevc_put_hevc_qpel_h48_8_msa; + c->put_hevc_qpel[9][0][1] = ff_hevc_put_hevc_qpel_h64_8_msa; + + c->put_hevc_qpel[1][1][0] = ff_hevc_put_hevc_qpel_v4_8_msa; + c->put_hevc_qpel[3][1][0] = ff_hevc_put_hevc_qpel_v8_8_msa; + c->put_hevc_qpel[4][1][0] = ff_hevc_put_hevc_qpel_v12_8_msa; + c->put_hevc_qpel[5][1][0] = ff_hevc_put_hevc_qpel_v16_8_msa; + c->put_hevc_qpel[6][1][0] = ff_hevc_put_hevc_qpel_v24_8_msa; + c->put_hevc_qpel[7][1][0] = ff_hevc_put_hevc_qpel_v32_8_msa; + c->put_hevc_qpel[8][1][0] = ff_hevc_put_hevc_qpel_v48_8_msa; + c->put_hevc_qpel[9][1][0] = ff_hevc_put_hevc_qpel_v64_8_msa; + + c->put_hevc_qpel[1][1][1] = ff_hevc_put_hevc_qpel_hv4_8_msa; + c->put_hevc_qpel[3][1][1] = ff_hevc_put_hevc_qpel_hv8_8_msa; + c->put_hevc_qpel[4][1][1] = ff_hevc_put_hevc_qpel_hv12_8_msa; + c->put_hevc_qpel[5][1][1] = ff_hevc_put_hevc_qpel_hv16_8_msa; + c->put_hevc_qpel[6][1][1] = ff_hevc_put_hevc_qpel_hv24_8_msa; + c->put_hevc_qpel[7][1][1] = ff_hevc_put_hevc_qpel_hv32_8_msa; + c->put_hevc_qpel[8][1][1] = ff_hevc_put_hevc_qpel_hv48_8_msa; + c->put_hevc_qpel[9][1][1] = ff_hevc_put_hevc_qpel_hv64_8_msa; + + c->put_hevc_epel[1][0][0] = ff_hevc_put_hevc_pel_pixels4_8_msa; + c->put_hevc_epel[2][0][0] = ff_hevc_put_hevc_pel_pixels6_8_msa; + c->put_hevc_epel[3][0][0] = ff_hevc_put_hevc_pel_pixels8_8_msa; + c->put_hevc_epel[4][0][0] = ff_hevc_put_hevc_pel_pixels12_8_msa; + c->put_hevc_epel[5][0][0] = ff_hevc_put_hevc_pel_pixels16_8_msa; + c->put_hevc_epel[6][0][0] = ff_hevc_put_hevc_pel_pixels24_8_msa; + c->put_hevc_epel[7][0][0] = ff_hevc_put_hevc_pel_pixels32_8_msa; + + c->put_hevc_epel[1][0][1] = ff_hevc_put_hevc_epel_h4_8_msa; + c->put_hevc_epel[2][0][1] = ff_hevc_put_hevc_epel_h6_8_msa; + c->put_hevc_epel[3][0][1] = ff_hevc_put_hevc_epel_h8_8_msa; + c->put_hevc_epel[4][0][1] = ff_hevc_put_hevc_epel_h12_8_msa; + c->put_hevc_epel[5][0][1] = ff_hevc_put_hevc_epel_h16_8_msa; + c->put_hevc_epel[6][0][1] = ff_hevc_put_hevc_epel_h24_8_msa; + c->put_hevc_epel[7][0][1] = ff_hevc_put_hevc_epel_h32_8_msa; + + c->put_hevc_epel[1][1][0] = ff_hevc_put_hevc_epel_v4_8_msa; + c->put_hevc_epel[2][1][0] = ff_hevc_put_hevc_epel_v6_8_msa; + c->put_hevc_epel[3][1][0] = ff_hevc_put_hevc_epel_v8_8_msa; + c->put_hevc_epel[4][1][0] = ff_hevc_put_hevc_epel_v12_8_msa; + c->put_hevc_epel[5][1][0] = ff_hevc_put_hevc_epel_v16_8_msa; + c->put_hevc_epel[6][1][0] = ff_hevc_put_hevc_epel_v24_8_msa; + c->put_hevc_epel[7][1][0] = ff_hevc_put_hevc_epel_v32_8_msa; + + c->put_hevc_epel[1][1][1] = ff_hevc_put_hevc_epel_hv4_8_msa; + c->put_hevc_epel[2][1][1] = ff_hevc_put_hevc_epel_hv6_8_msa; + c->put_hevc_epel[3][1][1] = ff_hevc_put_hevc_epel_hv8_8_msa; + c->put_hevc_epel[4][1][1] = ff_hevc_put_hevc_epel_hv12_8_msa; + c->put_hevc_epel[5][1][1] = ff_hevc_put_hevc_epel_hv16_8_msa; + c->put_hevc_epel[6][1][1] = ff_hevc_put_hevc_epel_hv24_8_msa; + c->put_hevc_epel[7][1][1] = ff_hevc_put_hevc_epel_hv32_8_msa; + + c->put_hevc_qpel_uni[3][0][0] = ff_hevc_put_hevc_uni_pel_pixels8_8_msa; + c->put_hevc_qpel_uni[4][0][0] = ff_hevc_put_hevc_uni_pel_pixels12_8_msa; + c->put_hevc_qpel_uni[5][0][0] = ff_hevc_put_hevc_uni_pel_pixels16_8_msa; + c->put_hevc_qpel_uni[6][0][0] = ff_hevc_put_hevc_uni_pel_pixels24_8_msa; + c->put_hevc_qpel_uni[7][0][0] = ff_hevc_put_hevc_uni_pel_pixels32_8_msa; + c->put_hevc_qpel_uni[8][0][0] = ff_hevc_put_hevc_uni_pel_pixels48_8_msa; + c->put_hevc_qpel_uni[9][0][0] = ff_hevc_put_hevc_uni_pel_pixels64_8_msa; + + c->put_hevc_qpel_uni[1][0][1] = ff_hevc_put_hevc_uni_qpel_h4_8_msa; + c->put_hevc_qpel_uni[3][0][1] = ff_hevc_put_hevc_uni_qpel_h8_8_msa; + c->put_hevc_qpel_uni[4][0][1] = ff_hevc_put_hevc_uni_qpel_h12_8_msa; + c->put_hevc_qpel_uni[5][0][1] = ff_hevc_put_hevc_uni_qpel_h16_8_msa; + c->put_hevc_qpel_uni[6][0][1] = ff_hevc_put_hevc_uni_qpel_h24_8_msa; + c->put_hevc_qpel_uni[7][0][1] = ff_hevc_put_hevc_uni_qpel_h32_8_msa; + c->put_hevc_qpel_uni[8][0][1] = ff_hevc_put_hevc_uni_qpel_h48_8_msa; + c->put_hevc_qpel_uni[9][0][1] = ff_hevc_put_hevc_uni_qpel_h64_8_msa; + + c->put_hevc_qpel_uni[1][1][0] = ff_hevc_put_hevc_uni_qpel_v4_8_msa; + c->put_hevc_qpel_uni[3][1][0] = ff_hevc_put_hevc_uni_qpel_v8_8_msa; + c->put_hevc_qpel_uni[4][1][0] = ff_hevc_put_hevc_uni_qpel_v12_8_msa; + c->put_hevc_qpel_uni[5][1][0] = ff_hevc_put_hevc_uni_qpel_v16_8_msa; + c->put_hevc_qpel_uni[6][1][0] = ff_hevc_put_hevc_uni_qpel_v24_8_msa; + c->put_hevc_qpel_uni[7][1][0] = ff_hevc_put_hevc_uni_qpel_v32_8_msa; + c->put_hevc_qpel_uni[8][1][0] = ff_hevc_put_hevc_uni_qpel_v48_8_msa; + c->put_hevc_qpel_uni[9][1][0] = ff_hevc_put_hevc_uni_qpel_v64_8_msa; + + c->put_hevc_qpel_uni[1][1][1] = ff_hevc_put_hevc_uni_qpel_hv4_8_msa; + c->put_hevc_qpel_uni[3][1][1] = ff_hevc_put_hevc_uni_qpel_hv8_8_msa; + c->put_hevc_qpel_uni[4][1][1] = ff_hevc_put_hevc_uni_qpel_hv12_8_msa; + c->put_hevc_qpel_uni[5][1][1] = ff_hevc_put_hevc_uni_qpel_hv16_8_msa; + c->put_hevc_qpel_uni[6][1][1] = ff_hevc_put_hevc_uni_qpel_hv24_8_msa; + c->put_hevc_qpel_uni[7][1][1] = ff_hevc_put_hevc_uni_qpel_hv32_8_msa; + c->put_hevc_qpel_uni[8][1][1] = ff_hevc_put_hevc_uni_qpel_hv48_8_msa; + c->put_hevc_qpel_uni[9][1][1] = ff_hevc_put_hevc_uni_qpel_hv64_8_msa; + + c->put_hevc_epel_uni[3][0][0] = ff_hevc_put_hevc_uni_pel_pixels8_8_msa; + c->put_hevc_epel_uni[4][0][0] = ff_hevc_put_hevc_uni_pel_pixels12_8_msa; + c->put_hevc_epel_uni[5][0][0] = ff_hevc_put_hevc_uni_pel_pixels16_8_msa; + c->put_hevc_epel_uni[6][0][0] = ff_hevc_put_hevc_uni_pel_pixels24_8_msa; + c->put_hevc_epel_uni[7][0][0] = ff_hevc_put_hevc_uni_pel_pixels32_8_msa; + + c->put_hevc_epel_uni[1][0][1] = ff_hevc_put_hevc_uni_epel_h4_8_msa; + c->put_hevc_epel_uni[2][0][1] = ff_hevc_put_hevc_uni_epel_h6_8_msa; + c->put_hevc_epel_uni[3][0][1] = ff_hevc_put_hevc_uni_epel_h8_8_msa; + c->put_hevc_epel_uni[4][0][1] = ff_hevc_put_hevc_uni_epel_h12_8_msa; + c->put_hevc_epel_uni[5][0][1] = ff_hevc_put_hevc_uni_epel_h16_8_msa; + c->put_hevc_epel_uni[6][0][1] = ff_hevc_put_hevc_uni_epel_h24_8_msa; + c->put_hevc_epel_uni[7][0][1] = ff_hevc_put_hevc_uni_epel_h32_8_msa; + + c->put_hevc_epel_uni[1][1][0] = ff_hevc_put_hevc_uni_epel_v4_8_msa; + c->put_hevc_epel_uni[2][1][0] = ff_hevc_put_hevc_uni_epel_v6_8_msa; + c->put_hevc_epel_uni[3][1][0] = ff_hevc_put_hevc_uni_epel_v8_8_msa; + c->put_hevc_epel_uni[4][1][0] = ff_hevc_put_hevc_uni_epel_v12_8_msa; + c->put_hevc_epel_uni[5][1][0] = ff_hevc_put_hevc_uni_epel_v16_8_msa; + c->put_hevc_epel_uni[6][1][0] = ff_hevc_put_hevc_uni_epel_v24_8_msa; + c->put_hevc_epel_uni[7][1][0] = ff_hevc_put_hevc_uni_epel_v32_8_msa; + + c->put_hevc_epel_uni[1][1][1] = ff_hevc_put_hevc_uni_epel_hv4_8_msa; + c->put_hevc_epel_uni[2][1][1] = ff_hevc_put_hevc_uni_epel_hv6_8_msa; + c->put_hevc_epel_uni[3][1][1] = ff_hevc_put_hevc_uni_epel_hv8_8_msa; + c->put_hevc_epel_uni[4][1][1] = ff_hevc_put_hevc_uni_epel_hv12_8_msa; + c->put_hevc_epel_uni[5][1][1] = ff_hevc_put_hevc_uni_epel_hv16_8_msa; + c->put_hevc_epel_uni[6][1][1] = ff_hevc_put_hevc_uni_epel_hv24_8_msa; + c->put_hevc_epel_uni[7][1][1] = ff_hevc_put_hevc_uni_epel_hv32_8_msa; + + c->put_hevc_qpel_uni_w[1][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels4_8_msa; + c->put_hevc_qpel_uni_w[3][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels8_8_msa; + c->put_hevc_qpel_uni_w[4][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels12_8_msa; + c->put_hevc_qpel_uni_w[5][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels16_8_msa; + c->put_hevc_qpel_uni_w[6][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels24_8_msa; + c->put_hevc_qpel_uni_w[7][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels32_8_msa; + c->put_hevc_qpel_uni_w[8][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels48_8_msa; + c->put_hevc_qpel_uni_w[9][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels64_8_msa; + + c->put_hevc_qpel_uni_w[1][0][1] = ff_hevc_put_hevc_uni_w_qpel_h4_8_msa; + c->put_hevc_qpel_uni_w[3][0][1] = ff_hevc_put_hevc_uni_w_qpel_h8_8_msa; + c->put_hevc_qpel_uni_w[4][0][1] = ff_hevc_put_hevc_uni_w_qpel_h12_8_msa; + c->put_hevc_qpel_uni_w[5][0][1] = ff_hevc_put_hevc_uni_w_qpel_h16_8_msa; + c->put_hevc_qpel_uni_w[6][0][1] = ff_hevc_put_hevc_uni_w_qpel_h24_8_msa; + c->put_hevc_qpel_uni_w[7][0][1] = ff_hevc_put_hevc_uni_w_qpel_h32_8_msa; + c->put_hevc_qpel_uni_w[8][0][1] = ff_hevc_put_hevc_uni_w_qpel_h48_8_msa; + c->put_hevc_qpel_uni_w[9][0][1] = ff_hevc_put_hevc_uni_w_qpel_h64_8_msa; + + c->put_hevc_qpel_uni_w[1][1][0] = ff_hevc_put_hevc_uni_w_qpel_v4_8_msa; + c->put_hevc_qpel_uni_w[3][1][0] = ff_hevc_put_hevc_uni_w_qpel_v8_8_msa; + c->put_hevc_qpel_uni_w[4][1][0] = ff_hevc_put_hevc_uni_w_qpel_v12_8_msa; + c->put_hevc_qpel_uni_w[5][1][0] = ff_hevc_put_hevc_uni_w_qpel_v16_8_msa; + c->put_hevc_qpel_uni_w[6][1][0] = ff_hevc_put_hevc_uni_w_qpel_v24_8_msa; + c->put_hevc_qpel_uni_w[7][1][0] = ff_hevc_put_hevc_uni_w_qpel_v32_8_msa; + c->put_hevc_qpel_uni_w[8][1][0] = ff_hevc_put_hevc_uni_w_qpel_v48_8_msa; + c->put_hevc_qpel_uni_w[9][1][0] = ff_hevc_put_hevc_uni_w_qpel_v64_8_msa; + + c->put_hevc_qpel_uni_w[1][1][1] = ff_hevc_put_hevc_uni_w_qpel_hv4_8_msa; + c->put_hevc_qpel_uni_w[3][1][1] = ff_hevc_put_hevc_uni_w_qpel_hv8_8_msa; + c->put_hevc_qpel_uni_w[4][1][1] = + ff_hevc_put_hevc_uni_w_qpel_hv12_8_msa; + c->put_hevc_qpel_uni_w[5][1][1] = + ff_hevc_put_hevc_uni_w_qpel_hv16_8_msa; + c->put_hevc_qpel_uni_w[6][1][1] = + ff_hevc_put_hevc_uni_w_qpel_hv24_8_msa; + c->put_hevc_qpel_uni_w[7][1][1] = + ff_hevc_put_hevc_uni_w_qpel_hv32_8_msa; + c->put_hevc_qpel_uni_w[8][1][1] = + ff_hevc_put_hevc_uni_w_qpel_hv48_8_msa; + c->put_hevc_qpel_uni_w[9][1][1] = + ff_hevc_put_hevc_uni_w_qpel_hv64_8_msa; + + c->put_hevc_epel_uni_w[1][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels4_8_msa; + c->put_hevc_epel_uni_w[2][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels6_8_msa; + c->put_hevc_epel_uni_w[3][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels8_8_msa; + c->put_hevc_epel_uni_w[4][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels12_8_msa; + c->put_hevc_epel_uni_w[5][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels16_8_msa; + c->put_hevc_epel_uni_w[6][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels24_8_msa; + c->put_hevc_epel_uni_w[7][0][0] = + ff_hevc_put_hevc_uni_w_pel_pixels32_8_msa; + + c->put_hevc_epel_uni_w[1][0][1] = ff_hevc_put_hevc_uni_w_epel_h4_8_msa; + c->put_hevc_epel_uni_w[2][0][1] = ff_hevc_put_hevc_uni_w_epel_h6_8_msa; + c->put_hevc_epel_uni_w[3][0][1] = ff_hevc_put_hevc_uni_w_epel_h8_8_msa; + c->put_hevc_epel_uni_w[4][0][1] = ff_hevc_put_hevc_uni_w_epel_h12_8_msa; + c->put_hevc_epel_uni_w[5][0][1] = ff_hevc_put_hevc_uni_w_epel_h16_8_msa; + c->put_hevc_epel_uni_w[6][0][1] = ff_hevc_put_hevc_uni_w_epel_h24_8_msa; + c->put_hevc_epel_uni_w[7][0][1] = ff_hevc_put_hevc_uni_w_epel_h32_8_msa; + + c->put_hevc_epel_uni_w[1][1][0] = ff_hevc_put_hevc_uni_w_epel_v4_8_msa; + c->put_hevc_epel_uni_w[2][1][0] = ff_hevc_put_hevc_uni_w_epel_v6_8_msa; + c->put_hevc_epel_uni_w[3][1][0] = ff_hevc_put_hevc_uni_w_epel_v8_8_msa; + c->put_hevc_epel_uni_w[4][1][0] = ff_hevc_put_hevc_uni_w_epel_v12_8_msa; + c->put_hevc_epel_uni_w[5][1][0] = ff_hevc_put_hevc_uni_w_epel_v16_8_msa; + c->put_hevc_epel_uni_w[6][1][0] = ff_hevc_put_hevc_uni_w_epel_v24_8_msa; + c->put_hevc_epel_uni_w[7][1][0] = ff_hevc_put_hevc_uni_w_epel_v32_8_msa; + + c->put_hevc_epel_uni_w[1][1][1] = ff_hevc_put_hevc_uni_w_epel_hv4_8_msa; + c->put_hevc_epel_uni_w[2][1][1] = ff_hevc_put_hevc_uni_w_epel_hv6_8_msa; + c->put_hevc_epel_uni_w[3][1][1] = ff_hevc_put_hevc_uni_w_epel_hv8_8_msa; + c->put_hevc_epel_uni_w[4][1][1] = + ff_hevc_put_hevc_uni_w_epel_hv12_8_msa; + c->put_hevc_epel_uni_w[5][1][1] = + ff_hevc_put_hevc_uni_w_epel_hv16_8_msa; + c->put_hevc_epel_uni_w[6][1][1] = + ff_hevc_put_hevc_uni_w_epel_hv24_8_msa; + c->put_hevc_epel_uni_w[7][1][1] = + ff_hevc_put_hevc_uni_w_epel_hv32_8_msa; + + c->put_hevc_qpel_bi[1][0][0] = ff_hevc_put_hevc_bi_pel_pixels4_8_msa; + c->put_hevc_qpel_bi[3][0][0] = ff_hevc_put_hevc_bi_pel_pixels8_8_msa; + c->put_hevc_qpel_bi[4][0][0] = ff_hevc_put_hevc_bi_pel_pixels12_8_msa; + c->put_hevc_qpel_bi[5][0][0] = ff_hevc_put_hevc_bi_pel_pixels16_8_msa; + c->put_hevc_qpel_bi[6][0][0] = ff_hevc_put_hevc_bi_pel_pixels24_8_msa; + c->put_hevc_qpel_bi[7][0][0] = ff_hevc_put_hevc_bi_pel_pixels32_8_msa; + c->put_hevc_qpel_bi[8][0][0] = ff_hevc_put_hevc_bi_pel_pixels48_8_msa; + c->put_hevc_qpel_bi[9][0][0] = ff_hevc_put_hevc_bi_pel_pixels64_8_msa; + + c->put_hevc_qpel_bi[1][0][1] = ff_hevc_put_hevc_bi_qpel_h4_8_msa; + c->put_hevc_qpel_bi[3][0][1] = ff_hevc_put_hevc_bi_qpel_h8_8_msa; + c->put_hevc_qpel_bi[4][0][1] = ff_hevc_put_hevc_bi_qpel_h12_8_msa; + c->put_hevc_qpel_bi[5][0][1] = ff_hevc_put_hevc_bi_qpel_h16_8_msa; + c->put_hevc_qpel_bi[6][0][1] = ff_hevc_put_hevc_bi_qpel_h24_8_msa; + c->put_hevc_qpel_bi[7][0][1] = ff_hevc_put_hevc_bi_qpel_h32_8_msa; + c->put_hevc_qpel_bi[8][0][1] = ff_hevc_put_hevc_bi_qpel_h48_8_msa; + c->put_hevc_qpel_bi[9][0][1] = ff_hevc_put_hevc_bi_qpel_h64_8_msa; + + c->put_hevc_qpel_bi[1][1][0] = ff_hevc_put_hevc_bi_qpel_v4_8_msa; + c->put_hevc_qpel_bi[3][1][0] = ff_hevc_put_hevc_bi_qpel_v8_8_msa; + c->put_hevc_qpel_bi[4][1][0] = ff_hevc_put_hevc_bi_qpel_v12_8_msa; + c->put_hevc_qpel_bi[5][1][0] = ff_hevc_put_hevc_bi_qpel_v16_8_msa; + c->put_hevc_qpel_bi[6][1][0] = ff_hevc_put_hevc_bi_qpel_v24_8_msa; + c->put_hevc_qpel_bi[7][1][0] = ff_hevc_put_hevc_bi_qpel_v32_8_msa; + c->put_hevc_qpel_bi[8][1][0] = ff_hevc_put_hevc_bi_qpel_v48_8_msa; + c->put_hevc_qpel_bi[9][1][0] = ff_hevc_put_hevc_bi_qpel_v64_8_msa; + + c->put_hevc_qpel_bi[1][1][1] = ff_hevc_put_hevc_bi_qpel_hv4_8_msa; + c->put_hevc_qpel_bi[3][1][1] = ff_hevc_put_hevc_bi_qpel_hv8_8_msa; + c->put_hevc_qpel_bi[4][1][1] = ff_hevc_put_hevc_bi_qpel_hv12_8_msa; + c->put_hevc_qpel_bi[5][1][1] = ff_hevc_put_hevc_bi_qpel_hv16_8_msa; + c->put_hevc_qpel_bi[6][1][1] = ff_hevc_put_hevc_bi_qpel_hv24_8_msa; + c->put_hevc_qpel_bi[7][1][1] = ff_hevc_put_hevc_bi_qpel_hv32_8_msa; + c->put_hevc_qpel_bi[8][1][1] = ff_hevc_put_hevc_bi_qpel_hv48_8_msa; + c->put_hevc_qpel_bi[9][1][1] = ff_hevc_put_hevc_bi_qpel_hv64_8_msa; + + c->put_hevc_epel_bi[1][0][0] = ff_hevc_put_hevc_bi_pel_pixels4_8_msa; + c->put_hevc_epel_bi[2][0][0] = ff_hevc_put_hevc_bi_pel_pixels6_8_msa; + c->put_hevc_epel_bi[3][0][0] = ff_hevc_put_hevc_bi_pel_pixels8_8_msa; + c->put_hevc_epel_bi[4][0][0] = ff_hevc_put_hevc_bi_pel_pixels12_8_msa; + c->put_hevc_epel_bi[5][0][0] = ff_hevc_put_hevc_bi_pel_pixels16_8_msa; + c->put_hevc_epel_bi[6][0][0] = ff_hevc_put_hevc_bi_pel_pixels24_8_msa; + c->put_hevc_epel_bi[7][0][0] = ff_hevc_put_hevc_bi_pel_pixels32_8_msa; + + c->put_hevc_epel_bi[1][0][1] = ff_hevc_put_hevc_bi_epel_h4_8_msa; + c->put_hevc_epel_bi[2][0][1] = ff_hevc_put_hevc_bi_epel_h6_8_msa; + c->put_hevc_epel_bi[3][0][1] = ff_hevc_put_hevc_bi_epel_h8_8_msa; + c->put_hevc_epel_bi[4][0][1] = ff_hevc_put_hevc_bi_epel_h12_8_msa; + c->put_hevc_epel_bi[5][0][1] = ff_hevc_put_hevc_bi_epel_h16_8_msa; + c->put_hevc_epel_bi[6][0][1] = ff_hevc_put_hevc_bi_epel_h24_8_msa; + c->put_hevc_epel_bi[7][0][1] = ff_hevc_put_hevc_bi_epel_h32_8_msa; + + c->put_hevc_epel_bi[1][1][0] = ff_hevc_put_hevc_bi_epel_v4_8_msa; + c->put_hevc_epel_bi[2][1][0] = ff_hevc_put_hevc_bi_epel_v6_8_msa; + c->put_hevc_epel_bi[3][1][0] = ff_hevc_put_hevc_bi_epel_v8_8_msa; + c->put_hevc_epel_bi[4][1][0] = ff_hevc_put_hevc_bi_epel_v12_8_msa; + c->put_hevc_epel_bi[5][1][0] = ff_hevc_put_hevc_bi_epel_v16_8_msa; + c->put_hevc_epel_bi[6][1][0] = ff_hevc_put_hevc_bi_epel_v24_8_msa; + c->put_hevc_epel_bi[7][1][0] = ff_hevc_put_hevc_bi_epel_v32_8_msa; + + c->put_hevc_epel_bi[1][1][1] = ff_hevc_put_hevc_bi_epel_hv4_8_msa; + c->put_hevc_epel_bi[2][1][1] = ff_hevc_put_hevc_bi_epel_hv6_8_msa; + c->put_hevc_epel_bi[3][1][1] = ff_hevc_put_hevc_bi_epel_hv8_8_msa; + c->put_hevc_epel_bi[4][1][1] = ff_hevc_put_hevc_bi_epel_hv12_8_msa; + c->put_hevc_epel_bi[5][1][1] = ff_hevc_put_hevc_bi_epel_hv16_8_msa; + c->put_hevc_epel_bi[6][1][1] = ff_hevc_put_hevc_bi_epel_hv24_8_msa; + c->put_hevc_epel_bi[7][1][1] = ff_hevc_put_hevc_bi_epel_hv32_8_msa; + + c->put_hevc_qpel_bi_w[1][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels4_8_msa; + c->put_hevc_qpel_bi_w[3][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels8_8_msa; + c->put_hevc_qpel_bi_w[4][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels12_8_msa; + c->put_hevc_qpel_bi_w[5][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels16_8_msa; + c->put_hevc_qpel_bi_w[6][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels24_8_msa; + c->put_hevc_qpel_bi_w[7][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels32_8_msa; + c->put_hevc_qpel_bi_w[8][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels48_8_msa; + c->put_hevc_qpel_bi_w[9][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels64_8_msa; + + c->put_hevc_qpel_bi_w[1][0][1] = ff_hevc_put_hevc_bi_w_qpel_h4_8_msa; + c->put_hevc_qpel_bi_w[3][0][1] = ff_hevc_put_hevc_bi_w_qpel_h8_8_msa; + c->put_hevc_qpel_bi_w[4][0][1] = ff_hevc_put_hevc_bi_w_qpel_h12_8_msa; + c->put_hevc_qpel_bi_w[5][0][1] = ff_hevc_put_hevc_bi_w_qpel_h16_8_msa; + c->put_hevc_qpel_bi_w[6][0][1] = ff_hevc_put_hevc_bi_w_qpel_h24_8_msa; + c->put_hevc_qpel_bi_w[7][0][1] = ff_hevc_put_hevc_bi_w_qpel_h32_8_msa; + c->put_hevc_qpel_bi_w[8][0][1] = ff_hevc_put_hevc_bi_w_qpel_h48_8_msa; + c->put_hevc_qpel_bi_w[9][0][1] = ff_hevc_put_hevc_bi_w_qpel_h64_8_msa; + + c->put_hevc_qpel_bi_w[1][1][0] = ff_hevc_put_hevc_bi_w_qpel_v4_8_msa; + c->put_hevc_qpel_bi_w[3][1][0] = ff_hevc_put_hevc_bi_w_qpel_v8_8_msa; + c->put_hevc_qpel_bi_w[4][1][0] = ff_hevc_put_hevc_bi_w_qpel_v12_8_msa; + c->put_hevc_qpel_bi_w[5][1][0] = ff_hevc_put_hevc_bi_w_qpel_v16_8_msa; + c->put_hevc_qpel_bi_w[6][1][0] = ff_hevc_put_hevc_bi_w_qpel_v24_8_msa; + c->put_hevc_qpel_bi_w[7][1][0] = ff_hevc_put_hevc_bi_w_qpel_v32_8_msa; + c->put_hevc_qpel_bi_w[8][1][0] = ff_hevc_put_hevc_bi_w_qpel_v48_8_msa; + c->put_hevc_qpel_bi_w[9][1][0] = ff_hevc_put_hevc_bi_w_qpel_v64_8_msa; + + c->put_hevc_qpel_bi_w[1][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv4_8_msa; + c->put_hevc_qpel_bi_w[3][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv8_8_msa; + c->put_hevc_qpel_bi_w[4][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv12_8_msa; + c->put_hevc_qpel_bi_w[5][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv16_8_msa; + c->put_hevc_qpel_bi_w[6][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv24_8_msa; + c->put_hevc_qpel_bi_w[7][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv32_8_msa; + c->put_hevc_qpel_bi_w[8][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv48_8_msa; + c->put_hevc_qpel_bi_w[9][1][1] = ff_hevc_put_hevc_bi_w_qpel_hv64_8_msa; + + c->put_hevc_epel_bi_w[1][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels4_8_msa; + c->put_hevc_epel_bi_w[2][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels6_8_msa; + c->put_hevc_epel_bi_w[3][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels8_8_msa; + c->put_hevc_epel_bi_w[4][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels12_8_msa; + c->put_hevc_epel_bi_w[5][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels16_8_msa; + c->put_hevc_epel_bi_w[6][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels24_8_msa; + c->put_hevc_epel_bi_w[7][0][0] = + ff_hevc_put_hevc_bi_w_pel_pixels32_8_msa; + + c->put_hevc_epel_bi_w[1][0][1] = ff_hevc_put_hevc_bi_w_epel_h4_8_msa; + c->put_hevc_epel_bi_w[2][0][1] = ff_hevc_put_hevc_bi_w_epel_h6_8_msa; + c->put_hevc_epel_bi_w[3][0][1] = ff_hevc_put_hevc_bi_w_epel_h8_8_msa; + c->put_hevc_epel_bi_w[4][0][1] = ff_hevc_put_hevc_bi_w_epel_h12_8_msa; + c->put_hevc_epel_bi_w[5][0][1] = ff_hevc_put_hevc_bi_w_epel_h16_8_msa; + c->put_hevc_epel_bi_w[6][0][1] = ff_hevc_put_hevc_bi_w_epel_h24_8_msa; + c->put_hevc_epel_bi_w[7][0][1] = ff_hevc_put_hevc_bi_w_epel_h32_8_msa; + + c->put_hevc_epel_bi_w[1][1][0] = ff_hevc_put_hevc_bi_w_epel_v4_8_msa; + c->put_hevc_epel_bi_w[2][1][0] = ff_hevc_put_hevc_bi_w_epel_v6_8_msa; + c->put_hevc_epel_bi_w[3][1][0] = ff_hevc_put_hevc_bi_w_epel_v8_8_msa; + c->put_hevc_epel_bi_w[4][1][0] = ff_hevc_put_hevc_bi_w_epel_v12_8_msa; + c->put_hevc_epel_bi_w[5][1][0] = ff_hevc_put_hevc_bi_w_epel_v16_8_msa; + c->put_hevc_epel_bi_w[6][1][0] = ff_hevc_put_hevc_bi_w_epel_v24_8_msa; + c->put_hevc_epel_bi_w[7][1][0] = ff_hevc_put_hevc_bi_w_epel_v32_8_msa; + + c->put_hevc_epel_bi_w[1][1][1] = ff_hevc_put_hevc_bi_w_epel_hv4_8_msa; + c->put_hevc_epel_bi_w[2][1][1] = ff_hevc_put_hevc_bi_w_epel_hv6_8_msa; + c->put_hevc_epel_bi_w[3][1][1] = ff_hevc_put_hevc_bi_w_epel_hv8_8_msa; + c->put_hevc_epel_bi_w[4][1][1] = ff_hevc_put_hevc_bi_w_epel_hv12_8_msa; + c->put_hevc_epel_bi_w[5][1][1] = ff_hevc_put_hevc_bi_w_epel_hv16_8_msa; + c->put_hevc_epel_bi_w[6][1][1] = ff_hevc_put_hevc_bi_w_epel_hv24_8_msa; + c->put_hevc_epel_bi_w[7][1][1] = ff_hevc_put_hevc_bi_w_epel_hv32_8_msa; + + c->sao_band_filter[0] = + c->sao_band_filter[1] = + c->sao_band_filter[2] = + c->sao_band_filter[3] = + c->sao_band_filter[4] = ff_hevc_sao_band_filter_0_8_msa; + + c->sao_edge_filter[0] = + c->sao_edge_filter[1] = + c->sao_edge_filter[2] = + c->sao_edge_filter[3] = + c->sao_edge_filter[4] = ff_hevc_sao_edge_filter_8_msa; + + c->hevc_h_loop_filter_luma = ff_hevc_loop_filter_luma_h_8_msa; + c->hevc_v_loop_filter_luma = ff_hevc_loop_filter_luma_v_8_msa; + + c->hevc_h_loop_filter_chroma = ff_hevc_loop_filter_chroma_h_8_msa; + c->hevc_v_loop_filter_chroma = ff_hevc_loop_filter_chroma_v_8_msa; + + c->hevc_h_loop_filter_luma_c = ff_hevc_loop_filter_luma_h_8_msa; + c->hevc_v_loop_filter_luma_c = ff_hevc_loop_filter_luma_v_8_msa; + + c->hevc_h_loop_filter_chroma_c = + ff_hevc_loop_filter_chroma_h_8_msa; + c->hevc_v_loop_filter_chroma_c = + ff_hevc_loop_filter_chroma_v_8_msa; + + c->idct[0] = ff_hevc_idct_4x4_msa; + c->idct[1] = ff_hevc_idct_8x8_msa; + c->idct[2] = ff_hevc_idct_16x16_msa; + c->idct[3] = ff_hevc_idct_32x32_msa; + c->idct_dc[0] = ff_hevc_idct_dc_4x4_msa; + c->idct_dc[1] = ff_hevc_idct_dc_8x8_msa; + c->idct_dc[2] = ff_hevc_idct_dc_16x16_msa; + c->idct_dc[3] = ff_hevc_idct_dc_32x32_msa; + c->add_residual[0] = ff_hevc_addblk_4x4_msa; + c->add_residual[1] = ff_hevc_addblk_8x8_msa; + c->add_residual[2] = ff_hevc_addblk_16x16_msa; + c->add_residual[3] = ff_hevc_addblk_32x32_msa; + c->transform_4x4_luma = ff_hevc_idct_luma_4x4_msa; + } + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/hevc_idct_msa.c ffmpeg-4.4/libavcodec/mips/hevc_idct_msa.c --- ffmpeg-4.2.2/libavcodec/mips/hevc_idct_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/hevc_idct_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -803,8 +803,9 @@ LD_SH4((coeffs + 8), 16, in1, in3, in5, in7); coeffs += 64; - CLIP_SH4_0_255(dst_r0, dst_l0, dst_r1, dst_l1); - CLIP_SH4_0_255(dst_r2, dst_l2, dst_r3, dst_l3); + CLIP_SH8_0_255(dst_r0, dst_l0, dst_r1, dst_l1, + dst_r2, dst_l2, dst_r3, dst_l3); + PCKEV_B4_UB(dst_l0, dst_r0, dst_l1, dst_r1, dst_l2, dst_r2, dst_l3, dst_r3, dst0, dst1, dst2, dst3); ST_UB4(dst0, dst1, dst2, dst3, dst, stride); @@ -825,8 +826,8 @@ dst_r3 += in6; dst_l3 += in7; - CLIP_SH4_0_255(dst_r0, dst_l0, dst_r1, dst_l1); - CLIP_SH4_0_255(dst_r2, dst_l2, dst_r3, dst_l3); + CLIP_SH8_0_255(dst_r0, dst_l0, dst_r1, dst_l1, + dst_r2, dst_l2, dst_r3, dst_l3); PCKEV_B4_UB(dst_l0, dst_r0, dst_l1, dst_r1, dst_l2, dst_r2, dst_l3, dst_r3, dst0, dst1, dst2, dst3); ST_UB4(dst0, dst1, dst2, dst3, dst, stride); @@ -873,8 +874,8 @@ LD_SH4((coeffs + 8), 16, in1, in3, in5, in7); coeffs += 64; - CLIP_SH4_0_255(dst_r0, dst_l0, dst_r1, dst_l1); - CLIP_SH4_0_255(dst_r2, dst_l2, dst_r3, dst_l3); + CLIP_SH8_0_255(dst_r0, dst_l0, dst_r1, dst_l1, + dst_r2, dst_l2, dst_r3, dst_l3); PCKEV_B4_UB(dst_l0, dst_r0, dst_l1, dst_r1, dst_l2, dst_r2, dst_l3, dst_r3, dst0, dst1, dst2, dst3); ST_UB2(dst0, dst1, dst, 16); @@ -905,8 +906,8 @@ LD_SH4(coeffs, 16, in0, in2, in4, in6); LD_SH4((coeffs + 8), 16, in1, in3, in5, in7); - CLIP_SH4_0_255(dst_r0, dst_l0, dst_r1, dst_l1); - CLIP_SH4_0_255(dst_r2, dst_l2, dst_r3, dst_l3); + CLIP_SH8_0_255(dst_r0, dst_l0, dst_r1, dst_l1, + dst_r2, dst_l2, dst_r3, dst_l3); PCKEV_B4_UB(dst_l0, dst_r0, dst_l1, dst_r1, dst_l2, dst_r2, dst_l3, dst_r3, dst0, dst1, dst2, dst3); ST_UB2(dst0, dst1, dst, 16); @@ -928,8 +929,8 @@ dst_r3 += in6; dst_l3 += in7; - CLIP_SH4_0_255(dst_r0, dst_l0, dst_r1, dst_l1); - CLIP_SH4_0_255(dst_r2, dst_l2, dst_r3, dst_l3); + CLIP_SH8_0_255(dst_r0, dst_l0, dst_r1, dst_l1, + dst_r2, dst_l2, dst_r3, dst_l3); PCKEV_B4_UB(dst_l0, dst_r0, dst_l1, dst_r1, dst_l2, dst_r2, dst_l3, dst_r3, dst0, dst1, dst2, dst3); ST_UB2(dst0, dst1, dst, 16); diff -Nru ffmpeg-4.2.2/libavcodec/mips/hevc_lpf_sao_msa.c ffmpeg-4.4/libavcodec/mips/hevc_lpf_sao_msa.c --- ffmpeg-4.2.2/libavcodec/mips/hevc_lpf_sao_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/hevc_lpf_sao_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -140,19 +140,19 @@ temp1 = ((p3_src + p2_src) << 1) + p2_src + temp0; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - p2_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst0 = (v16u8) (temp2 + (v8i16) p2_src); temp1 = temp0 + p2_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 2); temp2 = (v8i16) (temp1 - p1_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst1 = (v16u8) (temp2 + (v8i16) p1_src); temp1 = (temp0 << 1) + p2_src + q1_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - p0_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst2 = (v16u8) (temp2 + (v8i16) p0_src); dst0 = __msa_bmz_v(dst0, (v16u8) p2_src, (v16u8) p_is_pcm_vec); @@ -165,19 +165,19 @@ temp1 = ((q3_src + q2_src) << 1) + q2_src + temp0; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - q2_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst5 = (v16u8) (temp2 + (v8i16) q2_src); temp1 = temp0 + q2_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 2); temp2 = (v8i16) (temp1 - q1_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst4 = (v16u8) (temp2 + (v8i16) q1_src); temp1 = (temp0 << 1) + p1_src + q2_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - q0_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst3 = (v16u8) (temp2 + (v8i16) q0_src); dst3 = __msa_bmz_v(dst3, (v16u8) q0_src, (v16u8) q_is_pcm_vec); @@ -218,15 +218,15 @@ abs_delta0 = __msa_add_a_h(delta0, (v8i16) zero); abs_delta0 = (v8u16) abs_delta0 < temp1; - delta0 = CLIP_SH(delta0, tc_neg, tc_pos); + CLIP_SH(delta0, tc_neg, tc_pos); - temp0 = (v8u16) (delta0 + p0_src); - temp0 = (v8u16) CLIP_SH_0_255(temp0); - temp0 = (v8u16) __msa_bmz_v((v16u8) temp0, (v16u8) p0_src, + temp2 = (v8i16) (delta0 + p0_src); + CLIP_SH_0_255(temp2); + temp0 = (v8u16) __msa_bmz_v((v16u8) temp2, (v16u8) p0_src, (v16u8) p_is_pcm_vec); temp2 = (v8i16) (q0_src - delta0); - temp2 = CLIP_SH_0_255(temp2); + CLIP_SH_0_255(temp2); temp2 = (v8i16) __msa_bmz_v((v16u8) temp2, (v16u8) q0_src, (v16u8) q_is_pcm_vec); @@ -252,9 +252,9 @@ delta1 -= (v8i16) p1_src; delta1 += delta0; delta1 >>= 1; - delta1 = CLIP_SH(delta1, tc_neg, tc_pos); + CLIP_SH(delta1, tc_neg, tc_pos); delta1 = (v8i16) p1_src + (v8i16) delta1; - delta1 = CLIP_SH_0_255(delta1); + CLIP_SH_0_255(delta1); delta1 = (v8i16) __msa_bmnz_v((v16u8) delta1, (v16u8) p1_src, (v16u8) p_is_pcm_vec); @@ -262,9 +262,9 @@ delta2 = delta2 - (v8i16) q1_src; delta2 = delta2 - delta0; delta2 = delta2 >> 1; - delta2 = CLIP_SH(delta2, tc_neg, tc_pos); + CLIP_SH(delta2, tc_neg, tc_pos); delta2 = (v8i16) q1_src + (v8i16) delta2; - delta2 = CLIP_SH_0_255(delta2); + CLIP_SH_0_255(delta2); delta2 = (v8i16) __msa_bmnz_v((v16u8) delta2, (v16u8) q1_src, (v16u8) q_is_pcm_vec); @@ -298,19 +298,19 @@ temp1 = ((p3_src + p2_src) << 1) + p2_src + temp0; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - p2_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst0 = (v16u8) (temp2 + (v8i16) p2_src); temp1 = temp0 + p2_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 2); temp2 = (v8i16) (temp1 - p1_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst1 = (v16u8) (temp2 + (v8i16) p1_src); temp1 = (temp0 << 1) + p2_src + q1_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - p0_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst2 = (v16u8) (temp2 + (v8i16) p0_src); dst0 = __msa_bmz_v(dst0, (v16u8) p2_src, (v16u8) p_is_pcm_vec); @@ -323,19 +323,19 @@ temp1 = ((q3_src + q2_src) << 1) + q2_src + temp0; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - q2_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst5 = (v16u8) (temp2 + (v8i16) q2_src); temp1 = temp0 + q2_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 2); temp2 = (v8i16) (temp1 - q1_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst4 = (v16u8) (temp2 + (v8i16) q1_src); temp1 = (temp0 << 1) + p1_src + q2_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - q0_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst3 = (v16u8) (temp2 + (v8i16) q0_src); dst3 = __msa_bmz_v(dst3, (v16u8) q0_src, (v16u8) q_is_pcm_vec); @@ -362,15 +362,15 @@ abs_delta0 = __msa_add_a_h(delta0, (v8i16) zero); abs_delta0 = (v8u16) abs_delta0 < temp1; - delta0 = CLIP_SH(delta0, tc_neg, tc_pos); + CLIP_SH(delta0, tc_neg, tc_pos); - temp0 = (v8u16) (delta0 + p0_src); - temp0 = (v8u16) CLIP_SH_0_255(temp0); - temp0 = (v8u16) __msa_bmz_v((v16u8) temp0, (v16u8) p0_src, + temp2 = (v8i16) (delta0 + p0_src); + CLIP_SH_0_255(temp2); + temp0 = (v8u16) __msa_bmz_v((v16u8) temp2, (v16u8) p0_src, (v16u8) p_is_pcm_vec); temp2 = (v8i16) (q0_src - delta0); - temp2 = CLIP_SH_0_255(temp2); + CLIP_SH_0_255(temp2); temp2 = (v8i16) __msa_bmz_v((v16u8) temp2, (v16u8) q0_src, (v16u8) q_is_pcm_vec); @@ -394,9 +394,9 @@ delta1 -= (v8i16) p1_src; delta1 += delta0; delta1 >>= 1; - delta1 = CLIP_SH(delta1, tc_neg, tc_pos); + CLIP_SH(delta1, tc_neg, tc_pos); delta1 = (v8i16) p1_src + (v8i16) delta1; - delta1 = CLIP_SH_0_255(delta1); + CLIP_SH_0_255(delta1); delta1 = (v8i16) __msa_bmnz_v((v16u8) delta1, (v16u8) p1_src, (v16u8) p_is_pcm_vec); @@ -404,9 +404,9 @@ delta2 = delta2 - (v8i16) q1_src; delta2 = delta2 - delta0; delta2 = delta2 >> 1; - delta2 = CLIP_SH(delta2, tc_neg, tc_pos); + CLIP_SH(delta2, tc_neg, tc_pos); delta2 = (v8i16) q1_src + (v8i16) delta2; - delta2 = CLIP_SH_0_255(delta2); + CLIP_SH_0_255(delta2); delta2 = (v8i16) __msa_bmnz_v((v16u8) delta2, (v16u8) q1_src, (v16u8) q_is_pcm_vec); @@ -561,19 +561,19 @@ temp1 = ((p3_src + p2_src) << 1) + p2_src + temp0; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - p2_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst0 = (v16u8) (temp2 + (v8i16) p2_src); temp1 = temp0 + p2_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 2); temp2 = (v8i16) (temp1 - p1_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst1 = (v16u8) (temp2 + (v8i16) p1_src); temp1 = (temp0 << 1) + p2_src + q1_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - p0_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst2 = (v16u8) (temp2 + (v8i16) p0_src); dst0 = __msa_bmz_v(dst0, (v16u8) p2_src, (v16u8) p_is_pcm_vec); @@ -585,19 +585,19 @@ temp1 = ((q3_src + q2_src) << 1) + q2_src + temp0; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - q2_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst5 = (v16u8) (temp2 + (v8i16) q2_src); temp1 = temp0 + q2_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 2); temp2 = (v8i16) (temp1 - q1_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst4 = (v16u8) (temp2 + (v8i16) q1_src); temp1 = (temp0 << 1) + p1_src + q2_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - q0_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst3 = (v16u8) (temp2 + (v8i16) q0_src); dst3 = __msa_bmz_v(dst3, (v16u8) q0_src, (v16u8) q_is_pcm_vec); @@ -620,14 +620,14 @@ abs_delta0 = __msa_add_a_h(delta0, (v8i16) zero); abs_delta0 = (v8u16) abs_delta0 < temp1; - delta0 = CLIP_SH(delta0, tc_neg, tc_pos); - temp0 = (v8u16) (delta0 + p0_src); - temp0 = (v8u16) CLIP_SH_0_255(temp0); - temp0 = (v8u16) __msa_bmz_v((v16u8) temp0, (v16u8) p0_src, + CLIP_SH(delta0, tc_neg, tc_pos); + temp2 = (v8i16) (delta0 + p0_src); + CLIP_SH_0_255(temp2); + temp0 = (v8u16) __msa_bmz_v((v16u8) temp2, (v16u8) p0_src, (v16u8) p_is_pcm_vec); temp2 = (v8i16) (q0_src - delta0); - temp2 = CLIP_SH_0_255(temp2); + CLIP_SH_0_255(temp2); temp2 = (v8i16) __msa_bmz_v((v16u8) temp2, (v16u8) q0_src, (v16u8) q_is_pcm_vec); @@ -649,9 +649,9 @@ delta1 -= (v8i16) p1_src; delta1 += delta0; delta1 >>= 1; - delta1 = CLIP_SH(delta1, tc_neg, tc_pos); + CLIP_SH(delta1, tc_neg, tc_pos); delta1 = (v8i16) p1_src + (v8i16) delta1; - delta1 = CLIP_SH_0_255(delta1); + CLIP_SH_0_255(delta1); delta1 = (v8i16) __msa_bmnz_v((v16u8) delta1, (v16u8) p1_src, (v16u8) p_is_pcm_vec); @@ -659,9 +659,9 @@ delta2 = delta2 - (v8i16) q1_src; delta2 = delta2 - delta0; delta2 = delta2 >> 1; - delta2 = CLIP_SH(delta2, tc_neg, tc_pos); + CLIP_SH(delta2, tc_neg, tc_pos); delta2 = (v8i16) q1_src + (v8i16) delta2; - delta2 = CLIP_SH_0_255(delta2); + CLIP_SH_0_255(delta2); delta2 = (v8i16) __msa_bmnz_v((v16u8) delta2, (v16u8) q1_src, (v16u8) q_is_pcm_vec); @@ -726,19 +726,19 @@ temp1 = ((p3_src + p2_src) << 1) + p2_src + temp0; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - p2_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst0 = (v16u8) (temp2 + (v8i16) p2_src); temp1 = temp0 + p2_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 2); temp2 = (v8i16) (temp1 - p1_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst1 = (v16u8) (temp2 + (v8i16) p1_src); temp1 = (temp0 << 1) + p2_src + q1_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - p0_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst2 = (v16u8) (temp2 + (v8i16) p0_src); dst0 = __msa_bmz_v(dst0, (v16u8) p2_src, (v16u8) p_is_pcm_vec); @@ -750,19 +750,19 @@ temp1 = ((q3_src + q2_src) << 1) + q2_src + temp0; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - q2_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst5 = (v16u8) (temp2 + (v8i16) q2_src); temp1 = temp0 + q2_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 2); temp2 = (v8i16) (temp1 - q1_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst4 = (v16u8) (temp2 + (v8i16) q1_src); temp1 = (temp0 << 1) + p1_src + q2_src; temp1 = (v8u16) __msa_srari_h((v8i16) temp1, 3); temp2 = (v8i16) (temp1 - q0_src); - temp2 = CLIP_SH(temp2, tc_neg, tc_pos); + CLIP_SH(temp2, tc_neg, tc_pos); dst3 = (v16u8) (temp2 + (v8i16) q0_src); dst3 = __msa_bmz_v(dst3, (v16u8) q0_src, (v16u8) q_is_pcm_vec); @@ -785,15 +785,15 @@ abs_delta0 = __msa_add_a_h(delta0, (v8i16) zero); abs_delta0 = (v8u16) abs_delta0 < temp1; - delta0 = CLIP_SH(delta0, tc_neg, tc_pos); + CLIP_SH(delta0, tc_neg, tc_pos); - temp0 = (v8u16) (delta0 + p0_src); - temp0 = (v8u16) CLIP_SH_0_255(temp0); - temp0 = (v8u16) __msa_bmz_v((v16u8) temp0, (v16u8) p0_src, + temp2 = (v8i16) (delta0 + p0_src); + CLIP_SH_0_255(temp2); + temp0 = (v8u16) __msa_bmz_v((v16u8) temp2, (v16u8) p0_src, (v16u8) p_is_pcm_vec); temp2 = (v8i16) (q0_src - delta0); - temp2 = CLIP_SH_0_255(temp2); + CLIP_SH_0_255(temp2); temp2 = (v8i16) __msa_bmz_v((v16u8) temp2, (v16u8) q0_src, (v16u8) q_is_pcm_vec); @@ -815,9 +815,9 @@ delta1 -= (v8i16) p1_src; delta1 += delta0; delta1 >>= 1; - delta1 = CLIP_SH(delta1, tc_neg, tc_pos); + CLIP_SH(delta1, tc_neg, tc_pos); delta1 = (v8i16) p1_src + (v8i16) delta1; - delta1 = CLIP_SH_0_255(delta1); + CLIP_SH_0_255(delta1); delta1 = (v8i16) __msa_bmnz_v((v16u8) delta1, (v16u8) p1_src, (v16u8) p_is_pcm_vec); @@ -825,9 +825,9 @@ delta2 = delta2 - (v8i16) q1_src; delta2 = delta2 - delta0; delta2 = delta2 >> 1; - delta2 = CLIP_SH(delta2, tc_neg, tc_pos); + CLIP_SH(delta2, tc_neg, tc_pos); delta2 = (v8i16) q1_src + (v8i16) delta2; - delta2 = CLIP_SH_0_255(delta2); + CLIP_SH_0_255(delta2); delta2 = (v8i16) __msa_bmnz_v((v16u8) delta2, (v16u8) q1_src, (v16u8) q_is_pcm_vec); delta1 = (v8i16) __msa_bmz_v((v16u8) delta1, (v16u8) p1_src, @@ -955,15 +955,15 @@ temp0 <<= 2; temp0 += temp1; delta = __msa_srari_h((v8i16) temp0, 3); - delta = CLIP_SH(delta, tc_neg, tc_pos); + CLIP_SH(delta, tc_neg, tc_pos); temp0 = (v8i16) ((v8i16) p0 + delta); - temp0 = CLIP_SH_0_255(temp0); + CLIP_SH_0_255(temp0); temp0 = (v8i16) __msa_bmz_v((v16u8) temp0, (v16u8) p0, (v16u8) p_is_pcm_vec); temp1 = (v8i16) ((v8i16) q0 - delta); - temp1 = CLIP_SH_0_255(temp1); + CLIP_SH_0_255(temp1); temp1 = (v8i16) __msa_bmz_v((v16u8) temp1, (v16u8) q0, (v16u8) q_is_pcm_vec); @@ -1014,15 +1014,15 @@ temp0 <<= 2; temp0 += temp1; delta = __msa_srari_h((v8i16) temp0, 3); - delta = CLIP_SH(delta, tc_neg, tc_pos); + CLIP_SH(delta, tc_neg, tc_pos); temp0 = (v8i16) ((v8i16) p0 + delta); - temp0 = CLIP_SH_0_255(temp0); + CLIP_SH_0_255(temp0); temp0 = (v8i16) __msa_bmz_v((v16u8) temp0, (v16u8) p0, (v16u8) p_is_pcm_vec); temp1 = (v8i16) ((v8i16) q0 - delta); - temp1 = CLIP_SH_0_255(temp1); + CLIP_SH_0_255(temp1); temp1 = (v8i16) __msa_bmz_v((v16u8) temp1, (v16u8) q0, (v16u8) q_is_pcm_vec); @@ -1357,6 +1357,7 @@ v16u8 cmp_minus10, diff_minus10, diff_minus11; v16u8 src0, src1, dst0, src_minus10, src_minus11, src_plus10, src_plus11; v16i8 offset, sao_offset = LD_SB(sao_offset_val); + v16i8 zeros = { 0 }; sao_offset = __msa_pckev_b(sao_offset, sao_offset); src -= 1; @@ -1367,8 +1368,8 @@ for (height -= 2; height; height -= 2) { src += (src_stride << 1); - SLDI_B2_0_UB(src_minus10, src_minus11, src0, src1, 1); - SLDI_B2_0_UB(src_minus10, src_minus11, src_plus10, src_plus11, 2); + SLDI_B2_UB(zeros, src_minus10, zeros, src_minus11, 1, src0, src1); + SLDI_B2_UB(zeros, src_minus10, zeros, src_minus11, 2, src_plus10, src_plus11); PCKEV_D2_UB(src_minus11, src_minus10, src_plus11, src_plus10, src_minus10, src_plus10); @@ -1404,8 +1405,8 @@ dst += dst_stride; } - SLDI_B2_0_UB(src_minus10, src_minus11, src0, src1, 1); - SLDI_B2_0_UB(src_minus10, src_minus11, src_plus10, src_plus11, 2); + SLDI_B2_UB(zeros, src_minus10, zeros, src_minus11, 1, src0, src1); + SLDI_B2_UB(zeros, src_minus10, zeros, src_minus11, 2, src_plus10, src_plus11); PCKEV_D2_UB(src_minus11, src_minus10, src_plus11, src_plus10, src_minus10, src_plus10); @@ -1473,14 +1474,12 @@ dst_ptr = dst + v_cnt; LD_UB4(src_minus1, src_stride, src10, src11, src12, src13); - SLDI_B2_SB(src10, src11, src_minus10, src_minus11, src_zero0, - src_zero1, 1); - SLDI_B2_SB(src12, src13, src_minus12, src_minus13, src_zero2, - src_zero3, 1); - SLDI_B2_SB(src10, src11, src_minus10, src_minus11, src_plus10, - src_plus11, 2); - SLDI_B2_SB(src12, src13, src_minus12, src_minus13, src_plus12, - src_plus13, 2); + SLDI_B4_SB(src10, src_minus10, src11, src_minus11, + src12, src_minus12, src13, src_minus13, 1, + src_zero0, src_zero1, src_zero2, src_zero3); + SLDI_B4_SB(src10, src_minus10, src11, src_minus11, + src12, src_minus12, src13, src_minus13, 2, + src_plus10, src_plus11, src_plus12, src_plus13); cmp_minus10 = ((v16u8) src_zero0 == src_minus10); cmp_plus10 = ((v16u8) src_zero0 == (v16u8) src_plus10); @@ -1880,6 +1879,7 @@ v16u8 src_minus11, src10, src11; v16i8 src_plus0, src_zero0, src_plus1, src_zero1, dst0; v8i16 offset_mask0, offset_mask1; + v16i8 zeros = { 0 }; sao_offset = __msa_pckev_b(sao_offset, sao_offset); @@ -1892,8 +1892,8 @@ for (height -= 2; height; height -= 2) { src_orig += (src_stride << 1); - SLDI_B2_0_SB(src_minus11, src10, src_zero0, src_zero1, 1); - SLDI_B2_0_SB(src10, src11, src_plus0, src_plus1, 2); + SLDI_B2_SB(zeros, src_minus11, zeros, src10, 1, src_zero0, src_zero1); + SLDI_B2_SB(zeros, src10, zeros, src11, 2, src_plus0, src_plus1); ILVR_B2_UB(src_plus0, src_minus10, src_plus1, src_minus11, src_minus10, src_minus11); @@ -1938,8 +1938,8 @@ dst += dst_stride; } - SLDI_B2_0_SB(src_minus11, src10, src_zero0, src_zero1, 1); - SLDI_B2_0_SB(src10, src11, src_plus0, src_plus1, 2); + SLDI_B2_SB(zeros, src_minus11, zeros, src10, 1, src_zero0, src_zero1); + SLDI_B2_SB(zeros, src10, zeros, src11, 2, src_plus0, src_plus1); ILVR_B2_UB(src_plus0, src_minus10, src_plus1, src_minus11, src_minus10, src_minus11); @@ -1992,6 +1992,7 @@ v16u8 src_minus10, src10, src_minus11, src11; v16i8 src_zero0, src_plus10, src_zero1, src_plus11, dst0; v8i16 offset_mask0, offset_mask1; + v16i8 zeros = { 0 }; sao_offset = __msa_pckev_b(sao_offset, sao_offset); src_orig = src - 1; @@ -2003,8 +2004,8 @@ for (height -= 2; height; height -= 2) { src_orig += (src_stride << 1); - SLDI_B2_0_SB(src_minus11, src10, src_zero0, src_zero1, 1); - SLDI_B2_0_SB(src10, src11, src_plus10, src_plus11, 2); + SLDI_B2_SB(zeros, src_minus11, zeros, src10, 1, src_zero0, src_zero1); + SLDI_B2_SB(zeros, src10, zeros, src11, 2, src_plus10, src_plus11); ILVR_B2_UB(src_plus10, src_minus10, src_plus11, src_minus11, src_minus10, src_minus11); @@ -2048,8 +2049,8 @@ dst += dst_stride; } - SLDI_B2_0_SB(src_minus11, src10, src_zero0, src_zero1, 1); - SLDI_B2_0_SB(src10, src11, src_plus10, src_plus11, 2); + SLDI_B2_SB(zeros, src_minus11, zeros, src10, 1, src_zero0, src_zero1); + SLDI_B2_SB(zeros, src10, zeros, src11, 2, src_plus10, src_plus11); ILVR_B2_UB(src_plus10, src_minus10, src_plus11, src_minus11, src_minus10, src_minus11); ILVR_B2_SB(src_zero0, src_zero0, src_zero1, src_zero1, src_zero0, @@ -2130,12 +2131,11 @@ src_plus13 = LD_UB(src + 1 + v_cnt + (src_stride << 2)); src_orig += 16; - SLDI_B2_SB(src10, src11, src_minus11, src_minus12, src_zero0, - src_zero1, 1); - SLDI_B2_SB(src12, src13, src_minus13, src_minus14, src_zero2, - src_zero3, 1); - SLDI_B2_SB(src11, src12, src_minus12, src_minus13, src_plus10, - src_plus11, 2); + SLDI_B4_SB(src10, src_minus11, src11, src_minus12, + src12, src_minus13, src13, src_minus14, 1, + src_zero0, src_zero1, src_zero2, src_zero3); + SLDI_B2_SB(src11, src_minus12, src12, src_minus13, 2, src_plus10, + src_plus11); src_plus12 = __msa_sldi_b((v16i8) src13, (v16i8) src_minus14, 2); @@ -2228,6 +2228,7 @@ v16u8 cmp_minus10, diff_minus10, cmp_minus11, diff_minus11; v16u8 src_minus10, src10, src_minus11, src11; v8i16 offset_mask0, offset_mask1; + v16i8 zeros = { 0 }; sao_offset = __msa_pckev_b(sao_offset, sao_offset); src_orig = src - 1; @@ -2239,8 +2240,8 @@ for (height -= 2; height; height -= 2) { src_orig += (src_stride << 1); - SLDI_B2_0_SB(src_minus11, src10, src_zero0, src_zero1, 1); - SLDI_B2_0_UB(src_minus10, src_minus11, src_minus10, src_minus11, 2); + SLDI_B2_SB(zeros, src_minus11, zeros, src10, 1, src_zero0, src_zero1); + SLDI_B2_UB(zeros, src_minus10, zeros, src_minus11, 2, src_minus10, src_minus11); ILVR_B2_UB(src10, src_minus10, src11, src_minus11, src_minus10, src_minus11); @@ -2286,8 +2287,8 @@ dst += dst_stride; } - SLDI_B2_0_SB(src_minus11, src10, src_zero0, src_zero1, 1); - SLDI_B2_0_UB(src_minus10, src_minus11, src_minus10, src_minus11, 2); + SLDI_B2_SB(zeros, src_minus11, zeros, src10, 1, src_zero0, src_zero1); + SLDI_B2_UB(zeros, src_minus10, zeros, src_minus11, 2, src_minus10, src_minus11); ILVR_B2_UB(src10, src_minus10, src11, src_minus11, src_minus10, src_minus11); @@ -2342,6 +2343,7 @@ v16u8 src_minus10, src10, src_minus11, src11; v16i8 src_zero0, src_zero1, dst0; v8i16 offset_mask0, offset_mask1; + v16i8 zeros = { 0 }; sao_offset = __msa_pckev_b(sao_offset, sao_offset); src_orig = src - 1; @@ -2353,8 +2355,8 @@ for (height -= 2; height; height -= 2) { src_orig += (src_stride << 1); - SLDI_B2_0_SB(src_minus11, src10, src_zero0, src_zero1, 1); - SLDI_B2_0_UB(src_minus10, src_minus11, src_minus10, src_minus11, 2); + SLDI_B2_SB(zeros, src_minus11, zeros, src10, 1, src_zero0, src_zero1); + SLDI_B2_UB(zeros, src_minus10, zeros, src_minus11, 2, src_minus10, src_minus11); ILVR_B2_UB(src10, src_minus10, src11, src_minus11, src_minus10, src_minus11); ILVR_B2_SB(src_zero0, src_zero0, src_zero1, src_zero1, src_zero0, @@ -2398,8 +2400,8 @@ dst += dst_stride; } - SLDI_B2_0_SB(src_minus11, src10, src_zero0, src_zero1, 1); - SLDI_B2_0_UB(src_minus10, src_minus11, src_minus10, src_minus11, 2); + SLDI_B2_SB(zeros, src_minus11, zeros, src10, 1, src_zero0, src_zero1); + SLDI_B2_UB(zeros, src_minus10, zeros, src_minus11, 2, src_minus10, src_minus11); ILVR_B2_UB(src10, src_minus10, src11, src_minus11, src_minus10, src_minus11); ILVR_B2_SB(src_zero0, src_zero0, src_zero1, src_zero1, src_zero0, diff -Nru ffmpeg-4.2.2/libavcodec/mips/hevc_mc_bi_msa.c ffmpeg-4.4/libavcodec/mips/hevc_mc_bi_msa.c --- ffmpeg-4.2.2/libavcodec/mips/hevc_mc_bi_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/hevc_mc_bi_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -48,7 +48,7 @@ { \ ADDS_SH2_SH(vec0, in0, vec1, in1, out0, out1); \ SRARI_H2_SH(out0, out1, rnd_val); \ - CLIP_SH2_0_255_MAX_SATU(out0, out1); \ + CLIP_SH2_0_255(out0, out1); \ } #define HEVC_BI_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, vec0, vec1, vec2, \ @@ -83,7 +83,7 @@ dst0 <<= 6; dst0 += in0; dst0 = __msa_srari_h(dst0, 7); - dst0 = CLIP_SH_0_255_MAX_SATU(dst0); + CLIP_SH_0_255(dst0); dst0 = (v8i16) __msa_pckev_b((v16i8) dst0, (v16i8) dst0); ST_W2(dst0, 0, 1, dst, dst_stride); @@ -739,7 +739,7 @@ HEVC_BI_RND_CLIP2(in0, in1, dst0, dst1, 7, dst0, dst1); dst2 = __msa_adds_s_h(in2, dst2); dst2 = __msa_srari_h(dst2, 7); - dst2 = CLIP_SH_0_255(dst2); + CLIP_SH_0_255(dst2); PCKEV_B2_SH(dst1, dst0, dst2, dst2, dst0, dst1); tmp2 = __msa_copy_s_d((v2i64) dst0, 0); @@ -888,7 +888,7 @@ HEVC_BI_RND_CLIP2(in0, in1, dst0, dst1, 7, dst0, dst1); dst2 = __msa_adds_s_h(dst2, in2); dst2 = __msa_srari_h(dst2, 7); - dst2 = CLIP_SH_0_255(dst2); + CLIP_SH_0_255(dst2); PCKEV_B2_SB(dst1, dst0, dst2, dst2, tmp0, tmp1); dst_val0 = __msa_copy_u_d((v2i64) tmp1, 0); @@ -1726,7 +1726,7 @@ ADDS_SH2_SH(out0, in0, out1, in1, out0, out1); ADDS_SH2_SH(out0, const_vec, out1, const_vec, out0, out1); SRARI_H2_SH(out0, out1, 7); - CLIP_SH2_0_255_MAX_SATU(out0, out1); + CLIP_SH2_0_255(out0, out1); out = (v16u8) __msa_pckev_b((v16i8) out1, (v16i8) out0); ST_W4(out, 0, 1, 2, 3, dst, dst_stride); dst += (4 * dst_stride); @@ -1854,7 +1854,7 @@ tmp = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); ADDS_SH2_SH(tmp, in0, tmp, const_vec, tmp, tmp); tmp = __msa_srari_h(tmp, 7); - tmp = CLIP_SH_0_255_MAX_SATU(tmp); + CLIP_SH_0_255(tmp); out = (v16u8) __msa_pckev_b((v16i8) tmp, (v16i8) tmp); ST_D1(out, 0, dst_tmp); dst_tmp += dst_stride; @@ -2000,7 +2000,7 @@ tmp = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); ADDS_SH2_SH(tmp, in0, tmp, const_vec, tmp, tmp); tmp = __msa_srari_h(tmp, 7); - tmp = CLIP_SH_0_255_MAX_SATU(tmp); + CLIP_SH_0_255(tmp); out = (v16u8) __msa_pckev_b((v16i8) tmp, (v16i8) tmp); ST_D1(out, 0, dst_tmp); dst_tmp += dst_stride; @@ -2088,7 +2088,7 @@ ADDS_SH2_SH(out0, in0, out1, in1, out0, out1); ADDS_SH2_SH(out0, const_vec, out1, const_vec, out0, out1); SRARI_H2_SH(out0, out1, 7); - CLIP_SH2_0_255_MAX_SATU(out0, out1); + CLIP_SH2_0_255(out0, out1); out = (v16u8) __msa_pckev_b((v16i8) out1, (v16i8) out0); ST_W4(out, 0, 1, 2, 3, dst, dst_stride); dst += (4 * dst_stride); @@ -2215,7 +2215,7 @@ tmp0 = __msa_adds_s_h(tmp0, in0); tmp0 = __msa_srari_h(tmp0, 7); - tmp0 = CLIP_SH_0_255(tmp0); + CLIP_SH_0_255(tmp0); dst0 = __msa_pckev_b((v16i8) tmp0, (v16i8) tmp0); ST_W2(dst0, 0, 1, dst, dst_stride); @@ -2943,7 +2943,7 @@ DPADD_SB2_SH(src2110, src4332, filt0, filt1, dst10, dst10); dst10 = __msa_adds_s_h(dst10, in0); dst10 = __msa_srari_h(dst10, 7); - dst10 = CLIP_SH_0_255(dst10); + CLIP_SH_0_255(dst10); dst10 = (v8i16) __msa_pckev_b((v16i8) dst10, (v16i8) dst10); ST_W2(dst10, 0, 1, dst, dst_stride); @@ -3843,7 +3843,7 @@ tmp = __msa_pckev_h((v8i16) dst1, (v8i16) dst0); tmp = __msa_adds_s_h(tmp, in0); tmp = __msa_srari_h(tmp, 7); - tmp = CLIP_SH_0_255_MAX_SATU(tmp); + CLIP_SH_0_255(tmp); out = (v16u8) __msa_pckev_b((v16i8) tmp, (v16i8) tmp); ST_W2(out, 0, 1, dst, dst_stride); } @@ -3919,7 +3919,7 @@ PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); ADDS_SH2_SH(tmp0, in0, tmp1, in1, tmp0, tmp1); SRARI_H2_SH(tmp0, tmp1, 7); - CLIP_SH2_0_255_MAX_SATU(tmp0, tmp1); + CLIP_SH2_0_255(tmp0, tmp1); out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); ST_W4(out, 0, 1, 2, 3, dst, dst_stride); } @@ -4032,7 +4032,7 @@ ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, tmp0, tmp1, tmp2, tmp3); SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_W8(out0, out1, 0, 1, 2, 3, 0, 1, 2, 3, dst, dst_stride); dst += (8 * dst_stride); @@ -4200,7 +4200,7 @@ ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, tmp0, tmp1, tmp2, tmp3); SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_W8(out0, out1, 0, 1, 2, 3, 0, 1, 2, 3, dst, dst_stride); @@ -4212,7 +4212,7 @@ ADDS_SH2_SH(in4, const_vec, in5, const_vec, in4, in5); ADDS_SH2_SH(in4, tmp4, in5, tmp5, tmp4, tmp5); SRARI_H2_SH(tmp4, tmp5, 7); - CLIP_SH2_0_255_MAX_SATU(tmp4, tmp5); + CLIP_SH2_0_255(tmp4, tmp5); out2 = (v16u8) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); ST_H8(out2, 0, 1, 2, 3, 4, 5, 6, 7, dst + 4, dst_stride); } @@ -4286,7 +4286,7 @@ PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, tmp0, tmp1); ADDS_SH2_SH(in0, tmp0, in1, tmp1, tmp0, tmp1); SRARI_H2_SH(tmp0, tmp1, 7); - CLIP_SH2_0_255_MAX_SATU(tmp0, tmp1); + CLIP_SH2_0_255(tmp0, tmp1); out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); ST_D2(out, 0, 1, dst, dst_stride); } @@ -4380,7 +4380,7 @@ ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, tmp0, tmp1, tmp2, tmp3); SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_D4(out0, out1, 0, 1, 0, 1, dst, dst_stride); dst += 8; @@ -4495,8 +4495,8 @@ ADDS_SH2_SH(in4, tmp4, in5, tmp5, tmp4, tmp5); SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); SRARI_H2_SH(tmp4, tmp5, 7); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); - CLIP_SH2_0_255_MAX_SATU(tmp4, tmp5); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); + CLIP_SH2_0_255(tmp4, tmp5); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); out2 = (v16u8) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); ST_D4(out0, out1, 0, 1, 0, 1, dst, dst_stride); @@ -4610,7 +4610,7 @@ ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, tmp0, tmp1, tmp2, tmp3); SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_D4(out0, out1, 0, 1, 0, 1, dst_tmp, dst_stride); dst_tmp += (4 * dst_stride); @@ -4760,7 +4760,7 @@ ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, tmp0, tmp1, tmp2, tmp3); SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_D4(out0, out1, 0, 1, 0, 1, dst_tmp, dst_stride); dst_tmp += (4 * dst_stride); @@ -4846,7 +4846,7 @@ ADDS_SH4_SH(in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, tmp0, tmp1, tmp2, tmp3); SRARI_H4_SH(tmp0, tmp1, tmp2, tmp3, 7); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_W8(out0, out1, 0, 1, 2, 3, 0, 1, 2, 3, dst, dst_stride); dst += (8 * dst_stride); diff -Nru ffmpeg-4.2.2/libavcodec/mips/hevc_mc_biw_msa.c ffmpeg-4.4/libavcodec/mips/hevc_mc_biw_msa.c --- ffmpeg-4.2.2/libavcodec/mips/hevc_mc_biw_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/hevc_mc_biw_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -66,7 +66,7 @@ out1_l = __msa_dpadd_s_w(offset, (v8i16) out1_l, (v8i16) wgt); \ SRAR_W4_SW(out0_r, out1_r, out0_l, out1_l, rnd); \ PCKEV_H2_SH(out0_l, out0_r, out1_l, out1_r, out0, out1); \ - CLIP_SH2_0_255_MAX_SATU(out0, out1); \ + CLIP_SH2_0_255(out0, out1); \ } #define HEVC_BIW_RND_CLIP4_MAX_SATU(in0, in1, in2, in3, vec0, vec1, vec2, \ @@ -124,7 +124,7 @@ dst0_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst0_l, weight_vec); SRAR_W2_SW(dst0_r, dst0_l, rnd_vec); dst0 = (v8i16) __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); - dst0 = CLIP_SH_0_255_MAX_SATU(dst0); + CLIP_SH_0_255(dst0); out0 = (v16u8) __msa_pckev_b((v16i8) dst0, (v16i8) dst0); ST_W2(out0, 0, 1, dst, dst_stride); } else if (4 == height) { @@ -1069,8 +1069,8 @@ dst2_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst2_l, (v8i16) weight_vec); SRAR_W2_SW(dst2_r, dst2_l, rnd_vec); - dst2_r = (v4i32) __msa_pckev_h((v8i16) dst2_l, (v8i16) dst2_r); - out2 = CLIP_SH_0_255(dst2_r); + out2 = __msa_pckev_h((v8i16) dst2_l, (v8i16) dst2_r); + CLIP_SH_0_255(out2); LD_SB2(src0_ptr, 16, src0, src1); src0_ptr += src_stride; @@ -1100,8 +1100,8 @@ dst2_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst2_r, (v8i16) weight_vec); dst2_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst2_l, (v8i16) weight_vec); SRAR_W2_SW(dst2_r, dst2_l, rnd_vec); - dst2_r = (v4i32) __msa_pckev_h((v8i16) dst2_l, (v8i16) dst2_r); - out2 = CLIP_SH_0_255(dst2_r); + out2 = __msa_pckev_h((v8i16) dst2_l, (v8i16) dst2_r); + CLIP_SH_0_255(out2); PCKEV_B2_SH(out1, out0, out2, out2, out0, out2); dst_val0 = __msa_copy_u_d((v2i64) out2, 0); ST_SH(out0, dst); @@ -1674,8 +1674,8 @@ dst2_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst2_l, (v8i16) weight_vec); SRAR_W2_SW(dst2_r, dst2_l, rnd_vec); - dst2_r = (v4i32) __msa_pckev_h((v8i16) dst2_l, (v8i16) dst2_r); - out2 = CLIP_SH_0_255(dst2_r); + out2 = __msa_pckev_h((v8i16) dst2_l, (v8i16) dst2_r); + CLIP_SH_0_255(out2); PCKEV_B2_SH(out1, out0, out2, out2, out0, out2); ST_D2(out0, 0, 1, dst, dst_stride); ST_W2(out2, 0, 1, dst + 8, dst_stride); @@ -2048,7 +2048,7 @@ dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); - CLIP_SW4_0_255_MAX_SATU(dst0, dst1, dst2, dst3); + CLIP_SW4_0_255(dst0, dst1, dst2, dst3); PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); ST_W4(out, 0, 1, 2, 3, dst, dst_stride); @@ -2226,7 +2226,7 @@ dst1_r = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); dst1_l = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); SRAR_W4_SW(dst0_l, dst0_r, dst1_l, dst1_r, rnd_vec); - CLIP_SW4_0_255_MAX_SATU(dst0_l, dst0_r, dst1_l, dst1_r); + CLIP_SW4_0_255(dst0_l, dst0_r, dst1_l, dst1_r); PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, tmp0, tmp1); out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); ST_D2(out, 0, 1, dst_tmp, dst_stride); @@ -2412,7 +2412,7 @@ dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); SRAR_W4_SW(dst1, dst0, dst3, dst2, rnd_vec); - CLIP_SW4_0_255_MAX_SATU(dst1, dst0, dst3, dst2); + CLIP_SW4_0_255(dst1, dst0, dst3, dst2); PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); ST_D2(out, 0, 1, dst_tmp, dst_stride); @@ -2503,7 +2503,7 @@ dst2 = __msa_dpadd_s_w(offset_vec, tmp2, weight_vec); dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); - CLIP_SW4_0_255_MAX_SATU(dst0, dst1, dst2, dst3); + CLIP_SW4_0_255(dst0, dst1, dst2, dst3); PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); ST_W4(out, 0, 1, 2, 3, dst, dst_stride); @@ -2683,8 +2683,8 @@ dst0_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst0_r, (v8i16) weight_vec); dst0_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst0_l, (v8i16) weight_vec); SRAR_W2_SW(dst0_r, dst0_l, rnd_vec); - dst0_r = (v4i32) __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); - out0 = CLIP_SH_0_255(dst0_r); + out0 = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); + CLIP_SH_0_255(out0); out0 = (v8i16) __msa_pckev_b((v16i8) out0, (v16i8) out0); ST_W2(out0, 0, 1, dst, dst_stride); } @@ -3554,8 +3554,8 @@ dst10_r = __msa_dpadd_s_w(offset_vec, (v8i16) dst10_r, (v8i16) weight_vec); dst10_l = __msa_dpadd_s_w(offset_vec, (v8i16) dst10_l, (v8i16) weight_vec); SRAR_W2_SW(dst10_r, dst10_l, rnd_vec); - dst10_r = (v4i32) __msa_pckev_h((v8i16) dst10_l, (v8i16) dst10_r); - out = CLIP_SH_0_255(dst10_r); + out = __msa_pckev_h((v8i16) dst10_l, (v8i16) dst10_r); + CLIP_SH_0_255(out); out = (v8i16) __msa_pckev_b((v16i8) out, (v16i8) out); ST_W2(out, 0, 1, dst, dst_stride); } @@ -4575,7 +4575,7 @@ dst1 = __msa_dpadd_s_w(offset_vec, tmp1, weight_vec); SRAR_W2_SW(dst0, dst1, rnd_vec); tmp = __msa_pckev_h((v8i16) dst1, (v8i16) dst0); - tmp = CLIP_SH_0_255_MAX_SATU(tmp); + CLIP_SH_0_255(tmp); out = (v16u8) __msa_pckev_b((v16i8) tmp, (v16i8) tmp); ST_W2(out, 0, 1, dst, dst_stride); } @@ -4672,7 +4672,7 @@ dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); - CLIP_SH2_0_255_MAX_SATU(tmp0, tmp1); + CLIP_SH2_0_255(tmp0, tmp1); out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); ST_W4(out, 0, 1, 2, 3, dst, dst_stride); } @@ -4810,7 +4810,7 @@ SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, tmp0, tmp1, tmp2, tmp3); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_W8(out0, out1, 0, 1, 2, 3, 0, 1, 2, 3, dst, dst_stride); dst += (8 * dst_stride); @@ -5008,7 +5008,7 @@ SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, tmp0, tmp1, tmp2, tmp3); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_W8(out0, out1, 0, 1, 2, 3, 0, 1, 2, 3, dst, dst_stride); @@ -5030,7 +5030,7 @@ SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp4, tmp5); - CLIP_SH2_0_255_MAX_SATU(tmp4, tmp5); + CLIP_SH2_0_255(tmp4, tmp5); out2 = (v16u8) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); ST_H8(out2, 0, 1, 2, 3, 4, 5, 6, 7, dst + 4, dst_stride); } @@ -5126,7 +5126,7 @@ dst1_l = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); SRAR_W4_SW(dst0_r, dst0_l, dst1_r, dst1_l, rnd_vec); PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, tmp0, tmp1); - CLIP_SH2_0_255_MAX_SATU(tmp0, tmp1); + CLIP_SH2_0_255(tmp0, tmp1); out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); ST_D2(out, 0, 1, dst, dst_stride); } @@ -5248,7 +5248,7 @@ SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, tmp0, tmp1, tmp2, tmp3); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_D4(out0, out1, 0, 1, 0, 1, dst, dst_stride); dst += 8; @@ -5387,7 +5387,7 @@ SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, tmp0, tmp1, tmp2, tmp3); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); PCKEV_H2_SW(dst4_l, dst4_r, dst5_l, dst5_r, dst0, dst1); @@ -5399,7 +5399,7 @@ dst3 = __msa_dpadd_s_w(offset_vec, tmp3, weight_vec); SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp4, tmp5); - CLIP_SH2_0_255_MAX_SATU(tmp4, tmp5); + CLIP_SH2_0_255(tmp4, tmp5); out2 = (v16u8) __msa_pckev_b((v16i8) tmp5, (v16i8) tmp4); ST_D4(out0, out1, 0, 1, 0, 1, dst, dst_stride); ST_D2(out2, 0, 1, dst + 4 * dst_stride, dst_stride); @@ -5537,7 +5537,7 @@ SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, tmp0, tmp1, tmp2, tmp3); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_D4(out0, out1, 0, 1, 0, 1, dst_tmp, dst_stride); dst_tmp += (4 * dst_stride); @@ -5724,7 +5724,7 @@ SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, tmp0, tmp1, tmp2, tmp3); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_D4(out0, out1, 0, 1, 0, 1, dst_tmp, dst_stride); dst_tmp += (4 * dst_stride); @@ -5820,7 +5820,7 @@ SRAR_W4_SW(dst4, dst5, dst6, dst7, rnd_vec); PCKEV_H4_SH(dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, tmp0, tmp1, tmp2, tmp3); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_W8(out0, out1, 0, 1, 2, 3, 0, 1, 2, 3, dst, dst_stride); dst += (8 * dst_stride); diff -Nru ffmpeg-4.2.2/libavcodec/mips/hevc_mc_uniw_msa.c ffmpeg-4.4/libavcodec/mips/hevc_mc_uniw_msa.c --- ffmpeg-4.2.2/libavcodec/mips/hevc_mc_uniw_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/hevc_mc_uniw_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -41,7 +41,7 @@ SRAR_W4_SW(in0_r_m, in1_r_m, in0_l_m, in1_l_m, rnd_w); \ PCKEV_H2_SH(in0_l_m, in0_r_m, in1_l_m, in1_r_m, out0_h, out1_h); \ ADDS_SH2_SH(out0_h, offset_h, out1_h, offset_h, out0_h, out1_h); \ - CLIP_SH2_0_255_MAX_SATU(out0_h, out1_h); \ + CLIP_SH2_0_255(out0_h, out1_h); \ } #define HEVC_UNIW_RND_CLIP4_MAX_SATU_H(in0_h, in1_h, in2_h, in3_h, wgt_w, \ @@ -88,7 +88,7 @@ SRAR_W2_SW(dst0_r, dst0_l, rnd_vec); dst0 = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); dst0 += offset_vec; - dst0 = CLIP_SH_0_255_MAX_SATU(dst0); + CLIP_SH_0_255(dst0); out0 = (v16u8) __msa_pckev_b((v16i8) dst0, (v16i8) dst0); ST_W2(out0, 0, 1, dst, dst_stride); } else if (4 == height) { @@ -1863,7 +1863,7 @@ SRAR_W4_SW(dst0_r, dst1_r, dst2_r, dst3_r, rnd_vec); ADD2(dst0_r, offset_vec, dst1_r, offset_vec, dst0_r, dst1_r); ADD2(dst2_r, offset_vec, dst3_r, offset_vec, dst2_r, dst3_r); - CLIP_SW4_0_255_MAX_SATU(dst0_r, dst1_r, dst2_r, dst3_r); + CLIP_SW4_0_255(dst0_r, dst1_r, dst2_r, dst3_r); PCKEV_H2_SW(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst1_r); out = (v16u8) __msa_pckev_b((v16i8) dst1_r, (v16i8) dst0_r); ST_W4(out, 0, 1, 2, 3, dst, dst_stride); @@ -2014,7 +2014,7 @@ SRAR_W4_SW(dst0_r, dst1_r, dst0_l, dst1_l, rnd_vec); ADD2(dst0_r, offset_vec, dst0_l, offset_vec, dst0_r, dst0_l); ADD2(dst1_r, offset_vec, dst1_l, offset_vec, dst1_r, dst1_l); - CLIP_SW4_0_255_MAX_SATU(dst0_r, dst1_r, dst0_l, dst1_l); + CLIP_SW4_0_255(dst0_r, dst1_r, dst0_l, dst1_l); PCKEV_H2_SW(dst0_l, dst0_r, dst1_l, dst1_r, dst0_r, dst1_r); dst0_r = (v4i32) __msa_pckev_b((v16i8) dst1_r, (v16i8) dst0_r); @@ -2165,7 +2165,7 @@ MUL2(dst0_r, weight_vec, dst0_l, weight_vec, dst0_r, dst0_l); SRAR_W2_SW(dst0_r, dst0_l, rnd_vec); ADD2(dst0_r, offset_vec, dst0_l, offset_vec, dst0_r, dst0_l); - CLIP_SW2_0_255_MAX_SATU(dst0_r, dst0_l); + CLIP_SW2_0_255(dst0_r, dst0_l); dst0_r = (v4i32) __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); out = (v16u8) __msa_pckev_b((v16i8) dst0_r, (v16i8) dst0_r); ST_D1(out, 0, dst_tmp); @@ -2246,7 +2246,7 @@ SRAR_W4_SW(dst0_r, dst1_r, dst2_r, dst3_r, rnd_vec); ADD2(dst0_r, offset_vec, dst1_r, offset_vec, dst0_r, dst1_r); ADD2(dst2_r, offset_vec, dst3_r, offset_vec, dst2_r, dst3_r); - CLIP_SW4_0_255_MAX_SATU(dst0_r, dst1_r, dst2_r, dst3_r); + CLIP_SW4_0_255(dst0_r, dst1_r, dst2_r, dst3_r); PCKEV_H2_SW(dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst1_r); out = (v16u8) __msa_pckev_b((v16i8) dst1_r, (v16i8) dst0_r); ST_W4(out, 0, 1, 2, 3, dst, dst_stride); @@ -2394,7 +2394,7 @@ SRAR_W2_SW(dst0_r, dst0_l, rnd_vec); dst0 = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); dst0 = __msa_adds_s_h(dst0, offset_vec); - dst0 = CLIP_SH_0_255_MAX_SATU(dst0); + CLIP_SH_0_255(dst0); out = (v16u8) __msa_pckev_b((v16i8) dst0, (v16i8) dst0); ST_W2(out, 0, 1, dst, dst_stride); dst += (4 * dst_stride); @@ -3295,7 +3295,7 @@ SRAR_W2_SW(dst0_r, dst0_l, rnd_vec); dst0 = __msa_pckev_h((v8i16) dst0_l, (v8i16) dst0_r); dst0 = __msa_adds_s_h(dst0, offset_vec); - dst0 = CLIP_SH_0_255_MAX_SATU(dst0); + CLIP_SH_0_255(dst0); out = (v16u8) __msa_pckev_b((v16i8) dst0, (v16i8) dst0); ST_W2(out, 0, 1, dst, dst_stride); } @@ -4247,7 +4247,7 @@ SRAR_W2_SW(dst0, dst1, rnd_vec); tmp = __msa_pckev_h((v8i16) dst1, (v8i16) dst0); tmp += offset_vec; - tmp = CLIP_SH_0_255_MAX_SATU(tmp); + CLIP_SH_0_255(tmp); out = (v16u8) __msa_pckev_b((v16i8) tmp, (v16i8) tmp); ST_W2(out, 0, 1, dst, dst_stride); } @@ -4316,7 +4316,7 @@ SRAR_W4_SW(dst0, dst1, dst2, dst3, rnd_vec); PCKEV_H2_SH(dst1, dst0, dst3, dst2, tmp0, tmp1); ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); - CLIP_SH2_0_255_MAX_SATU(tmp0, tmp1); + CLIP_SH2_0_255(tmp0, tmp1); out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); ST_W4(out, 0, 1, 2, 3, dst, dst_stride); } @@ -4417,7 +4417,7 @@ tmp2, tmp3); ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_W8(out0, out1, 0, 1, 2, 3, 0, 1, 2, 3, dst, dst_stride); dst += (8 * dst_stride); @@ -4574,8 +4574,8 @@ ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); ADD2(tmp4, offset_vec, tmp5, offset_vec, tmp4, tmp5); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); - CLIP_SH2_0_255_MAX_SATU(tmp4, tmp5); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); + CLIP_SH2_0_255(tmp4, tmp5); PCKEV_B3_UB(tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, out0, out1, out2); ST_W8(out0, out1, 0, 1, 2, 3, 0, 1, 2, 3, dst, dst_stride); ST_H8(out2, 0, 1, 2, 3, 4, 5, 6, 7, dst + 4, dst_stride); @@ -4652,7 +4652,7 @@ SRAR_W4_SW(dst0_r, dst0_l, dst1_r, dst1_l, rnd_vec); PCKEV_H2_SH(dst0_l, dst0_r, dst1_l, dst1_r, tmp0, tmp1); ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); - CLIP_SH2_0_255_MAX_SATU(tmp0, tmp1); + CLIP_SH2_0_255(tmp0, tmp1); out = (v16u8) __msa_pckev_b((v16i8) tmp1, (v16i8) tmp0); ST_D2(out, 0, 1, dst, dst_stride); } @@ -4745,7 +4745,7 @@ dst3_r, tmp0, tmp1, tmp2, tmp3); ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_D4(out0, out1, 0, 1, 0, 1, dst, dst_stride); dst += 8; @@ -4861,8 +4861,8 @@ ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); ADD2(tmp4, offset_vec, tmp5, offset_vec, tmp4, tmp5); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); - CLIP_SH2_0_255_MAX_SATU(tmp4, tmp5); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); + CLIP_SH2_0_255(tmp4, tmp5); PCKEV_B3_UB(tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, out0, out1, out2); ST_D4(out0, out1, 0, 1, 0, 1, dst, dst_stride); ST_D2(out2, 0, 1, dst + 4 * dst_stride, dst_stride); @@ -4973,7 +4973,7 @@ dst3_r, tmp0, tmp1, tmp2, tmp3); ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_D4(out0, out1, 0, 1, 0, 1, dst_tmp, dst_stride); dst_tmp += (4 * dst_stride); @@ -5120,7 +5120,7 @@ dst3_r, tmp0, tmp1, tmp2, tmp3); ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_D4(out0, out1, 0, 1, 0, 1, dst_tmp, dst_stride); dst_tmp += (4 * dst_stride); @@ -5187,7 +5187,7 @@ tmp2, tmp3); ADD2(tmp0, offset_vec, tmp1, offset_vec, tmp0, tmp1); ADD2(tmp2, offset_vec, tmp3, offset_vec, tmp2, tmp3); - CLIP_SH4_0_255_MAX_SATU(tmp0, tmp1, tmp2, tmp3); + CLIP_SH4_0_255(tmp0, tmp1, tmp2, tmp3); PCKEV_B2_UB(tmp1, tmp0, tmp3, tmp2, out0, out1); ST_W8(out0, out1, 0, 1, 2, 3, 0, 1, 2, 3, dst, dst_stride); dst += (8 * dst_stride); diff -Nru ffmpeg-4.2.2/libavcodec/mips/hevcpred_init_mips.c ffmpeg-4.4/libavcodec/mips/hevcpred_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/hevcpred_init_mips.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/hevcpred_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,32 +18,28 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "config.h" #include "libavutil/attributes.h" #include "libavcodec/mips/hevcpred_mips.h" -#if HAVE_MSA -static av_cold void hevc_pred_init_msa(HEVCPredContext *c, const int bit_depth) -{ - if (8 == bit_depth) { - c->intra_pred[2] = ff_intra_pred_8_16x16_msa; - c->intra_pred[3] = ff_intra_pred_8_32x32_msa; - c->pred_planar[0] = ff_hevc_intra_pred_planar_0_msa; - c->pred_planar[1] = ff_hevc_intra_pred_planar_1_msa; - c->pred_planar[2] = ff_hevc_intra_pred_planar_2_msa; - c->pred_planar[3] = ff_hevc_intra_pred_planar_3_msa; - c->pred_dc = ff_hevc_intra_pred_dc_msa; - c->pred_angular[0] = ff_pred_intra_pred_angular_0_msa; - c->pred_angular[1] = ff_pred_intra_pred_angular_1_msa; - c->pred_angular[2] = ff_pred_intra_pred_angular_2_msa; - c->pred_angular[3] = ff_pred_intra_pred_angular_3_msa; - } -} -#endif // #if HAVE_MSA - void ff_hevc_pred_init_mips(HEVCPredContext *c, const int bit_depth) { -#if HAVE_MSA - hevc_pred_init_msa(c, bit_depth); -#endif // #if HAVE_MSA + int cpu_flags = av_get_cpu_flags(); + + if (have_msa(cpu_flags)) { + if (bit_depth == 8) { + c->intra_pred[2] = ff_intra_pred_8_16x16_msa; + c->intra_pred[3] = ff_intra_pred_8_32x32_msa; + c->pred_planar[0] = ff_hevc_intra_pred_planar_0_msa; + c->pred_planar[1] = ff_hevc_intra_pred_planar_1_msa; + c->pred_planar[2] = ff_hevc_intra_pred_planar_2_msa; + c->pred_planar[3] = ff_hevc_intra_pred_planar_3_msa; + c->pred_dc = ff_hevc_intra_pred_dc_msa; + c->pred_angular[0] = ff_pred_intra_pred_angular_0_msa; + c->pred_angular[1] = ff_pred_intra_pred_angular_1_msa; + c->pred_angular[2] = ff_pred_intra_pred_angular_2_msa; + c->pred_angular[3] = ff_pred_intra_pred_angular_3_msa; + } + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/hevcpred_msa.c ffmpeg-4.4/libavcodec/mips/hevcpred_msa.c --- ffmpeg-4.2.2/libavcodec/mips/hevcpred_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/hevcpred_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -83,7 +83,7 @@ vec2 -= vec0; vec2 >>= 1; vec2 += vec1; - vec2 = CLIP_SH_0_255(vec2); + CLIP_SH_0_255(vec2); for (col = 0; col < 4; col++) { dst[stride * col] = (uint8_t) vec2[col]; @@ -122,7 +122,7 @@ vec2 -= vec0; vec2 >>= 1; vec2 += vec1; - vec2 = CLIP_SH_0_255(vec2); + CLIP_SH_0_255(vec2); val0 = vec2[0]; val1 = vec2[1]; @@ -214,7 +214,7 @@ src0_r -= src_top_val; src0_r >>= 1; src0_r += src_left_val; - src0_r = CLIP_SH_0_255(src0_r); + CLIP_SH_0_255(src0_r); src0 = __msa_pckev_b((v16i8) src0_r, (v16i8) src0_r); val0 = __msa_copy_s_w((v4i32) src0, 0); SW(val0, dst); @@ -254,7 +254,7 @@ src0_r -= src_top_val; src0_r >>= 1; src0_r += src_left_val; - src0_r = CLIP_SH_0_255(src0_r); + CLIP_SH_0_255(src0_r); src0 = __msa_pckev_b((v16i8) src0_r, (v16i8) src0_r); val0 = __msa_copy_s_d((v2i64) src0, 0); SD(val0, dst); @@ -998,7 +998,8 @@ ILVR_D2_SH(fact3, fact1, fact7, fact5, fact1, fact3); ILVR_B4_SH(zero, top0, zero, top1, zero, top2, zero, top3, diff0, diff2, diff4, diff6); - SLDI_B4_0_SH(diff0, diff2, diff4, diff6, diff1, diff3, diff5, diff7, 2); + SLDI_B4_SH(zero, diff0, zero, diff2, zero, diff4, zero, diff6, 2, + diff1, diff3, diff5, diff7); ILVR_D2_SH(diff2, diff0, diff6, diff4, diff0, diff2); ILVR_D2_SH(diff3, diff1, diff7, diff5, diff1, diff3); MUL2(diff1, fact0, diff3, fact2, diff1, diff3); @@ -1093,8 +1094,8 @@ UNPCK_UB_SH(top2, diff4, diff5); UNPCK_UB_SH(top3, diff6, diff7); - SLDI_B2_SH(diff1, diff3, diff0, diff2, diff1, diff3, 2); - SLDI_B2_SH(diff5, diff7, diff4, diff6, diff5, diff7, 2); + SLDI_B4_SH(diff1, diff0, diff3, diff2, diff5, diff4, diff7, diff6, 2, + diff1, diff3, diff5, diff7); MUL4(diff1, fact0, diff3, fact2, diff5, fact4, diff7, fact6, diff1, diff3, diff5, diff7); @@ -1186,8 +1187,8 @@ fact6 = __msa_fill_h(fact_val3); fact7 = __msa_fill_h(32 - fact_val3); - SLDI_B2_UB(top1, top3, top0, top2, top1, top3, 1); - SLDI_B2_UB(top5, top7, top4, top6, top5, top7, 1); + SLDI_B4_UB(top1, top0, top3, top2, top5, top4, top7, top6, 1, + top1, top3, top5, top7); UNPCK_UB_SH(top0, diff0, diff1); UNPCK_UB_SH(top1, diff2, diff3); UNPCK_UB_SH(top2, diff4, diff5); @@ -1297,8 +1298,8 @@ top2 = top1; top6 = top5; - SLDI_B2_UB(top1, top3, top0, top2, top1, top3, 1); - SLDI_B2_UB(top5, top7, top4, top6, top5, top7, 1); + SLDI_B4_UB(top1, top0, top3, top2, top5, top4, top7, top6, 1, + top1, top3, top5, top7); UNPCK_UB_SH(top0, diff0, diff1); UNPCK_UB_SH(top1, diff2, diff3); UNPCK_UB_SH(top2, diff4, diff5); @@ -1407,7 +1408,8 @@ ILVR_D2_SH(fact3, fact1, fact7, fact5, fact1, fact3); ILVR_B4_SH(zero, top0, zero, top1, zero, top2, zero, top3, diff0, diff2, diff4, diff6); - SLDI_B4_0_SH(diff0, diff2, diff4, diff6, diff1, diff3, diff5, diff7, 2); + SLDI_B4_SH(zero, diff0, zero, diff2, zero, diff4, zero, diff6, 2, + diff1, diff3, diff5, diff7); ILVR_D2_SH(diff2, diff0, diff6, diff4, diff0, diff2); ILVR_D2_SH(diff3, diff1, diff7, diff5, diff1, diff3); MUL2(diff1, fact0, diff3, fact2, diff1, diff3); @@ -1511,8 +1513,8 @@ UNPCK_UB_SH(top1, diff2, diff3); UNPCK_UB_SH(top2, diff4, diff5); UNPCK_UB_SH(top3, diff6, diff7); - SLDI_B2_SH(diff1, diff3, diff0, diff2, diff1, diff3, 2); - SLDI_B2_SH(diff5, diff7, diff4, diff6, diff5, diff7, 2); + SLDI_B4_SH(diff1, diff0, diff3, diff2, diff5, diff4, diff7, diff6, 2, + diff1, diff3, diff5, diff7); MUL4(diff1, fact0, diff3, fact2, diff5, fact4, diff7, fact6, diff1, diff3, diff5, diff7); @@ -1606,8 +1608,8 @@ fact6 = __msa_fill_h(fact_val3); fact7 = __msa_fill_h(32 - fact_val3); - SLDI_B2_SB(top1, top3, top0, top2, top1, top3, 1); - SLDI_B2_SB(top5, top7, top4, top6, top5, top7, 1); + SLDI_B4_SB(top1, top0, top3, top2, top5, top4, top7, top6, 1, + top1, top3, top5, top7); UNPCK_UB_SH(top0, diff0, diff1); UNPCK_UB_SH(top1, diff2, diff3); @@ -1713,8 +1715,8 @@ top2 = top1; top6 = top5; - SLDI_B2_SB(top1, top3, top0, top2, top1, top3, 1); - SLDI_B2_SB(top5, top7, top4, top6, top5, top7, 1); + SLDI_B4_SB(top1, top0, top3, top2, top5, top4, top7, top6, 1, + top1, top3, top5, top7); UNPCK_UB_SH(top0, diff0, diff1); UNPCK_UB_SH(top1, diff2, diff3); diff -Nru ffmpeg-4.2.2/libavcodec/mips/hpeldsp_init_mips.c ffmpeg-4.4/libavcodec/mips/hpeldsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/hpeldsp_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/hpeldsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,104 +19,94 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "../hpeldsp.h" #include "libavcodec/mips/hpeldsp_mips.h" -#if HAVE_MSA -static void ff_hpeldsp_init_msa(HpelDSPContext *c, int flags) -{ - c->put_pixels_tab[0][0] = ff_put_pixels16_msa; - c->put_pixels_tab[0][1] = ff_put_pixels16_x2_msa; - c->put_pixels_tab[0][2] = ff_put_pixels16_y2_msa; - c->put_pixels_tab[0][3] = ff_put_pixels16_xy2_msa; - - c->put_pixels_tab[1][0] = ff_put_pixels8_msa; - c->put_pixels_tab[1][1] = ff_put_pixels8_x2_msa; - c->put_pixels_tab[1][2] = ff_put_pixels8_y2_msa; - c->put_pixels_tab[1][3] = ff_put_pixels8_xy2_msa; - - c->put_pixels_tab[2][1] = ff_put_pixels4_x2_msa; - c->put_pixels_tab[2][2] = ff_put_pixels4_y2_msa; - c->put_pixels_tab[2][3] = ff_put_pixels4_xy2_msa; - - c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_msa; - c->put_no_rnd_pixels_tab[0][1] = ff_put_no_rnd_pixels16_x2_msa; - c->put_no_rnd_pixels_tab[0][2] = ff_put_no_rnd_pixels16_y2_msa; - c->put_no_rnd_pixels_tab[0][3] = ff_put_no_rnd_pixels16_xy2_msa; - - c->put_no_rnd_pixels_tab[1][0] = ff_put_pixels8_msa; - c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_msa; - c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_msa; - c->put_no_rnd_pixels_tab[1][3] = ff_put_no_rnd_pixels8_xy2_msa; - - c->avg_pixels_tab[0][0] = ff_avg_pixels16_msa; - c->avg_pixels_tab[0][1] = ff_avg_pixels16_x2_msa; - c->avg_pixels_tab[0][2] = ff_avg_pixels16_y2_msa; - c->avg_pixels_tab[0][3] = ff_avg_pixels16_xy2_msa; - - c->avg_pixels_tab[1][0] = ff_avg_pixels8_msa; - c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_msa; - c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_msa; - c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_msa; - - c->avg_pixels_tab[2][0] = ff_avg_pixels4_msa; - c->avg_pixels_tab[2][1] = ff_avg_pixels4_x2_msa; - c->avg_pixels_tab[2][2] = ff_avg_pixels4_y2_msa; - c->avg_pixels_tab[2][3] = ff_avg_pixels4_xy2_msa; -} -#endif // #if HAVE_MSA - -#if HAVE_MMI -static void ff_hpeldsp_init_mmi(HpelDSPContext *c, int flags) -{ - c->put_pixels_tab[0][0] = ff_put_pixels16_8_mmi; - c->put_pixels_tab[0][1] = ff_put_pixels16_x2_8_mmi; - c->put_pixels_tab[0][2] = ff_put_pixels16_y2_8_mmi; - c->put_pixels_tab[0][3] = ff_put_pixels16_xy2_8_mmi; - - c->put_pixels_tab[1][0] = ff_put_pixels8_8_mmi; - c->put_pixels_tab[1][1] = ff_put_pixels8_x2_8_mmi; - c->put_pixels_tab[1][2] = ff_put_pixels8_y2_8_mmi; - c->put_pixels_tab[1][3] = ff_put_pixels8_xy2_8_mmi; - - c->put_pixels_tab[2][0] = ff_put_pixels4_8_mmi; - c->put_pixels_tab[2][1] = ff_put_pixels4_x2_8_mmi; - c->put_pixels_tab[2][2] = ff_put_pixels4_y2_8_mmi; - c->put_pixels_tab[2][3] = ff_put_pixels4_xy2_8_mmi; - - c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_8_mmi; - c->put_no_rnd_pixels_tab[0][1] = ff_put_no_rnd_pixels16_x2_8_mmi; - c->put_no_rnd_pixels_tab[0][2] = ff_put_no_rnd_pixels16_y2_8_mmi; - c->put_no_rnd_pixels_tab[0][3] = ff_put_no_rnd_pixels16_xy2_8_mmi; - - c->put_no_rnd_pixels_tab[1][0] = ff_put_pixels8_8_mmi; - c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_8_mmi; - c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_8_mmi; - c->put_no_rnd_pixels_tab[1][3] = ff_put_no_rnd_pixels8_xy2_8_mmi; - - c->avg_pixels_tab[0][0] = ff_avg_pixels16_8_mmi; - c->avg_pixels_tab[0][1] = ff_avg_pixels16_x2_8_mmi; - c->avg_pixels_tab[0][2] = ff_avg_pixels16_y2_8_mmi; - c->avg_pixels_tab[0][3] = ff_avg_pixels16_xy2_8_mmi; - - c->avg_pixels_tab[1][0] = ff_avg_pixels8_8_mmi; - c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_8_mmi; - c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_8_mmi; - c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_8_mmi; - - c->avg_pixels_tab[2][0] = ff_avg_pixels4_8_mmi; - c->avg_pixels_tab[2][1] = ff_avg_pixels4_x2_8_mmi; - c->avg_pixels_tab[2][2] = ff_avg_pixels4_y2_8_mmi; - c->avg_pixels_tab[2][3] = ff_avg_pixels4_xy2_8_mmi; -} -#endif // #if HAVE_MMI - void ff_hpeldsp_init_mips(HpelDSPContext *c, int flags) { -#if HAVE_MMI - ff_hpeldsp_init_mmi(c, flags); -#endif // #if HAVE_MMI -#if HAVE_MSA - ff_hpeldsp_init_msa(c, flags); -#endif // #if HAVE_MSA + int cpu_flags = av_get_cpu_flags(); + + if (have_mmi(cpu_flags)) { + c->put_pixels_tab[0][0] = ff_put_pixels16_8_mmi; + c->put_pixels_tab[0][1] = ff_put_pixels16_x2_8_mmi; + c->put_pixels_tab[0][2] = ff_put_pixels16_y2_8_mmi; + c->put_pixels_tab[0][3] = ff_put_pixels16_xy2_8_mmi; + + c->put_pixels_tab[1][0] = ff_put_pixels8_8_mmi; + c->put_pixels_tab[1][1] = ff_put_pixels8_x2_8_mmi; + c->put_pixels_tab[1][2] = ff_put_pixels8_y2_8_mmi; + c->put_pixels_tab[1][3] = ff_put_pixels8_xy2_8_mmi; + + c->put_pixels_tab[2][0] = ff_put_pixels4_8_mmi; + c->put_pixels_tab[2][1] = ff_put_pixels4_x2_8_mmi; + c->put_pixels_tab[2][2] = ff_put_pixels4_y2_8_mmi; + c->put_pixels_tab[2][3] = ff_put_pixels4_xy2_8_mmi; + + c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_8_mmi; + c->put_no_rnd_pixels_tab[0][1] = ff_put_no_rnd_pixels16_x2_8_mmi; + c->put_no_rnd_pixels_tab[0][2] = ff_put_no_rnd_pixels16_y2_8_mmi; + c->put_no_rnd_pixels_tab[0][3] = ff_put_no_rnd_pixels16_xy2_8_mmi; + + c->put_no_rnd_pixels_tab[1][0] = ff_put_pixels8_8_mmi; + c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_8_mmi; + c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_8_mmi; + c->put_no_rnd_pixels_tab[1][3] = ff_put_no_rnd_pixels8_xy2_8_mmi; + + c->avg_pixels_tab[0][0] = ff_avg_pixels16_8_mmi; + c->avg_pixels_tab[0][1] = ff_avg_pixels16_x2_8_mmi; + c->avg_pixels_tab[0][2] = ff_avg_pixels16_y2_8_mmi; + c->avg_pixels_tab[0][3] = ff_avg_pixels16_xy2_8_mmi; + + c->avg_pixels_tab[1][0] = ff_avg_pixels8_8_mmi; + c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_8_mmi; + c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_8_mmi; + c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_8_mmi; + + c->avg_pixels_tab[2][0] = ff_avg_pixels4_8_mmi; + c->avg_pixels_tab[2][1] = ff_avg_pixels4_x2_8_mmi; + c->avg_pixels_tab[2][2] = ff_avg_pixels4_y2_8_mmi; + c->avg_pixels_tab[2][3] = ff_avg_pixels4_xy2_8_mmi; + } + + if (have_msa(cpu_flags)) { + c->put_pixels_tab[0][0] = ff_put_pixels16_msa; + c->put_pixels_tab[0][1] = ff_put_pixels16_x2_msa; + c->put_pixels_tab[0][2] = ff_put_pixels16_y2_msa; + c->put_pixels_tab[0][3] = ff_put_pixels16_xy2_msa; + + c->put_pixels_tab[1][0] = ff_put_pixels8_msa; + c->put_pixels_tab[1][1] = ff_put_pixels8_x2_msa; + c->put_pixels_tab[1][2] = ff_put_pixels8_y2_msa; + c->put_pixels_tab[1][3] = ff_put_pixels8_xy2_msa; + + c->put_pixels_tab[2][1] = ff_put_pixels4_x2_msa; + c->put_pixels_tab[2][2] = ff_put_pixels4_y2_msa; + c->put_pixels_tab[2][3] = ff_put_pixels4_xy2_msa; + + c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_msa; + c->put_no_rnd_pixels_tab[0][1] = ff_put_no_rnd_pixels16_x2_msa; + c->put_no_rnd_pixels_tab[0][2] = ff_put_no_rnd_pixels16_y2_msa; + c->put_no_rnd_pixels_tab[0][3] = ff_put_no_rnd_pixels16_xy2_msa; + + c->put_no_rnd_pixels_tab[1][0] = ff_put_pixels8_msa; + c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_msa; + c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_msa; + c->put_no_rnd_pixels_tab[1][3] = ff_put_no_rnd_pixels8_xy2_msa; + + c->avg_pixels_tab[0][0] = ff_avg_pixels16_msa; + c->avg_pixels_tab[0][1] = ff_avg_pixels16_x2_msa; + c->avg_pixels_tab[0][2] = ff_avg_pixels16_y2_msa; + c->avg_pixels_tab[0][3] = ff_avg_pixels16_xy2_msa; + + c->avg_pixels_tab[1][0] = ff_avg_pixels8_msa; + c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_msa; + c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_msa; + c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_msa; + + c->avg_pixels_tab[2][0] = ff_avg_pixels4_msa; + c->avg_pixels_tab[2][1] = ff_avg_pixels4_x2_msa; + c->avg_pixels_tab[2][2] = ff_avg_pixels4_y2_msa; + c->avg_pixels_tab[2][3] = ff_avg_pixels4_xy2_msa; + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/hpeldsp_msa.c ffmpeg-4.4/libavcodec/mips/hpeldsp_msa.c --- ffmpeg-4.2.2/libavcodec/mips/hpeldsp_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/hpeldsp_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -59,12 +59,13 @@ uint8_t loop_cnt; uint32_t out0, out1; v16u8 src0, src1, src0_sld1, src1_sld1, res0, res1; + v16i8 zeros = { 0 }; for (loop_cnt = (height >> 1); loop_cnt--;) { LD_UB2(src, src_stride, src0, src1); src += (2 * src_stride); - SLDI_B2_0_UB(src0, src1, src0_sld1, src1_sld1, 1); + SLDI_B2_UB(zeros, src0, zeros, src1, 1, src0_sld1, src1_sld1); AVER_UB2_UB(src0_sld1, src0, src1_sld1, src1, res0, res1); out0 = __msa_copy_u_w((v4i32) res0, 0); @@ -82,13 +83,14 @@ { uint8_t loop_cnt; v16i8 src0, src1, src2, src3, src0_sld1, src1_sld1, src2_sld1, src3_sld1; + v16i8 zeros = { 0 }; for (loop_cnt = (height >> 2); loop_cnt--;) { LD_SB4(src, src_stride, src0, src1, src2, src3); src += (4 * src_stride); - SLDI_B4_0_SB(src0, src1, src2, src3, - src0_sld1, src1_sld1, src2_sld1, src3_sld1, 1); + SLDI_B4_SB(zeros, src0, zeros, src1, zeros, src2, zeros, src3, 1, + src0_sld1, src1_sld1, src2_sld1, src3_sld1); AVER_ST8x4_UB(src0, src0_sld1, src1, src1_sld1, src2, src2_sld1, src3, src3_sld1, dst, dst_stride); dst += (4 * dst_stride); @@ -125,14 +127,15 @@ v16i8 src0, src1, src2, src3, src4, src5, src6, src7; v16i8 src0_sld1, src1_sld1, src2_sld1, src3_sld1; v16i8 src4_sld1, src5_sld1, src6_sld1, src7_sld1; + v16i8 zeros = { 0 }; LD_SB8(src, src_stride, src0, src1, src2, src3, src4, src5, src6, src7); src += (8 * src_stride); - SLDI_B4_0_SB(src0, src1, src2, src3, - src0_sld1, src1_sld1, src2_sld1, src3_sld1, 1); - SLDI_B4_0_SB(src4, src5, src6, src7, - src4_sld1, src5_sld1, src6_sld1, src7_sld1, 1); + SLDI_B4_SB(zeros, src0, zeros, src1, zeros, src2, zeros, src3, 1, + src0_sld1, src1_sld1, src2_sld1, src3_sld1); + SLDI_B4_SB(zeros, src4, zeros, src5, zeros, src6, zeros, src7, 1, + src4_sld1, src5_sld1, src6_sld1, src7_sld1); AVE_ST8x4_UB(src0, src0_sld1, src1, src1_sld1, src2, src2_sld1, src3, src3_sld1, dst, dst_stride); @@ -145,10 +148,11 @@ uint8_t *dst, int32_t dst_stride) { v16i8 src0, src1, src2, src3, src0_sld1, src1_sld1, src2_sld1, src3_sld1; + v16i8 zeros = { 0 }; LD_SB4(src, src_stride, src0, src1, src2, src3); - SLDI_B4_0_SB(src0, src1, src2, src3, - src0_sld1, src1_sld1, src2_sld1, src3_sld1, 1); + SLDI_B4_SB(zeros, src0, zeros, src1, zeros, src2, zeros, src3, 1, + src0_sld1, src1_sld1, src2_sld1, src3_sld1); AVE_ST8x4_UB(src0, src0_sld1, src1, src1_sld1, src2, src2_sld1, src3, src3_sld1, dst, dst_stride); } @@ -216,12 +220,13 @@ v16u8 src0, src1, src0_sld1, src1_sld1, res0, res1; v16u8 tmp0 = { 0 }; v16u8 tmp1 = { 0 }; + v16i8 zeros = { 0 }; for (loop_cnt = (height >> 1); loop_cnt--;) { LD_UB2(src, src_stride, src0, src1); src += (2 * src_stride); - SLDI_B2_0_UB(src0, src1, src0_sld1, src1_sld1, 1); + SLDI_B2_UB(zeros, src0, zeros, src1, 1, src0_sld1, src1_sld1); dst0 = LW(dst); dst1 = LW(dst + dst_stride); @@ -247,13 +252,14 @@ { uint8_t loop_cnt; v16i8 src0, src1, src2, src3, src0_sld1, src1_sld1, src2_sld1, src3_sld1; + v16i8 zeros = { 0 }; for (loop_cnt = (height >> 2); loop_cnt--;) { LD_SB4(src, src_stride, src0, src1, src2, src3); src += (4 * src_stride); - SLDI_B4_0_SB(src0, src1, src2, src3, - src0_sld1, src1_sld1, src2_sld1, src3_sld1, 1); + SLDI_B4_SB(zeros, src0, zeros, src1, zeros, src2, zeros, src3, 1, + src0_sld1, src1_sld1, src2_sld1, src3_sld1); AVER_DST_ST8x4_UB(src0, src0_sld1, src1, src1_sld1, src2, src2_sld1, src3, src3_sld1, dst, dst_stride); @@ -529,6 +535,7 @@ v16i8 src0, src1, src2, src0_sld1, src1_sld1, src2_sld1; v16u8 src0_r, src1_r, src2_r, res; v8u16 add0, add1, add2, sum0, sum1; + v16i8 zeros = { 0 }; src0 = LD_SB(src); src += src_stride; @@ -537,7 +544,8 @@ LD_SB2(src, src_stride, src1, src2); src += (2 * src_stride); - SLDI_B3_0_SB(src0, src1, src2, src0_sld1, src1_sld1, src2_sld1, 1); + SLDI_B3_SB(zeros, src0, zeros, src1, zeros, src2, 1, src0_sld1, + src1_sld1, src2_sld1); ILVR_B3_UB(src0_sld1, src0, src1_sld1, src1, src2_sld1, src2, src0_r, src1_r, src2_r); HADD_UB3_UH(src0_r, src1_r, src2_r, add0, add1, add2); @@ -565,6 +573,7 @@ v16u8 src0_r, src1_r, src2_r, src3_r, src4_r; v8u16 add0, add1, add2, add3, add4; v8u16 sum0, sum1, sum2, sum3; + v16i8 zeros = { 0 }; src0 = LD_SB(src); src += src_stride; @@ -573,8 +582,9 @@ LD_SB4(src, src_stride, src1, src2, src3, src4); src += (4 * src_stride); - SLDI_B3_0_SB(src0, src1, src2, src0_sld1, src1_sld1, src2_sld1, 1); - SLDI_B2_0_SB(src3, src4, src3_sld1, src4_sld1, 1); + SLDI_B3_SB(zeros, src0, zeros, src1, zeros, src2, 1, src0_sld1, + src1_sld1, src2_sld1); + SLDI_B2_SB(zeros, src3, zeros, src4, 1, src3_sld1, src4_sld1); ILVR_B3_UB(src0_sld1, src0, src1_sld1, src1, src2_sld1, src2, src0_r, src1_r, src2_r); ILVR_B2_UB(src3_sld1, src3, src4_sld1, src4, src3_r, src4_r); @@ -659,15 +669,17 @@ v8u16 add0, add1, add2, add3, add4, add5, add6, add7, add8; v8u16 sum0, sum1, sum2, sum3, sum4, sum5, sum6, sum7; v16i8 out0, out1; + v16i8 zeros = { 0 }; LD_UB8(src, src_stride, src0, src1, src2, src3, src4, src5, src6, src7); src += (8 * src_stride); src8 = LD_UB(src); - SLDI_B4_0_UB(src0, src1, src2, src3, src0_sld1, src1_sld1, src2_sld1, - src3_sld1, 1); - SLDI_B3_0_UB(src4, src5, src6, src4_sld1, src5_sld1, src6_sld1, 1); - SLDI_B2_0_UB(src7, src8, src7_sld1, src8_sld1, 1); + SLDI_B4_UB(zeros, src0, zeros, src1, zeros, src2, zeros, src3, 1, + src0_sld1, src1_sld1, src2_sld1, src3_sld1); + SLDI_B3_UB(zeros, src4, zeros, src5, zeros, src6, 1, src4_sld1, + src5_sld1, src6_sld1); + SLDI_B2_UB(zeros, src7, zeros, src8, 1, src7_sld1, src8_sld1); ILVR_B4_UH(src0_sld1, src0, src1_sld1, src1, src2_sld1, src2, src3_sld1, src3, src0_r, src1_r, src2_r, src3_r); ILVR_B3_UH(src4_sld1, src4, src5_sld1, src5, src6_sld1, src6, src4_r, @@ -703,13 +715,15 @@ v8u16 add0, add1, add2, add3, add4; v8u16 sum0, sum1, sum2, sum3; v16i8 out0, out1; + v16i8 zeros = { 0 }; LD_SB4(src, src_stride, src0, src1, src2, src3); src += (4 * src_stride); src4 = LD_SB(src); - SLDI_B3_0_SB(src0, src1, src2, src0_sld1, src1_sld1, src2_sld1, 1); - SLDI_B2_0_SB(src3, src4, src3_sld1, src4_sld1, 1); + SLDI_B3_SB(zeros, src0, zeros, src1, zeros, src2, 1, src0_sld1, + src1_sld1, src2_sld1); + SLDI_B2_SB(zeros, src3, zeros, src4, 1, src3_sld1, src4_sld1); ILVR_B3_UH(src0_sld1, src0, src1_sld1, src1, src2_sld1, src2, src0_r, src1_r, src2_r); ILVR_B2_UH(src3_sld1, src3, src4_sld1, src4, src3_r, src4_r); @@ -918,6 +932,7 @@ v16u8 src0_r, src1_r, src2_r; v8u16 add0, add1, add2, sum0, sum1; v16u8 dst0, dst1, res0, res1; + v16i8 zeros = { 0 }; src0 = LD_SB(src); src += src_stride; @@ -927,7 +942,8 @@ src += (2 * src_stride); LD_UB2(dst, dst_stride, dst0, dst1); - SLDI_B3_0_SB(src0, src1, src2, src0_sld1, src1_sld1, src2_sld1, 1); + SLDI_B3_SB(zeros, src0, zeros, src1, zeros, src2, 1, src0_sld1, + src1_sld1, src2_sld1); ILVR_B3_UB(src0_sld1, src0, src1_sld1, src1, src2_sld1, src2, src0_r, src1_r, src2_r); HADD_UB3_UH(src0_r, src1_r, src2_r, add0, add1, add2); @@ -959,6 +975,7 @@ v16u8 src0_r, src1_r, src2_r, src3_r, src4_r; v8u16 add0, add1, add2, add3, add4; v8u16 sum0, sum1, sum2, sum3; + v16i8 zeros = { 0 }; src0 = LD_SB(src); src += src_stride; @@ -968,8 +985,9 @@ src += (4 * src_stride); LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - SLDI_B3_0_SB(src0, src1, src2, src0_sld1, src1_sld1, src2_sld1, 1); - SLDI_B2_0_SB(src3, src4, src3_sld1, src4_sld1, 1); + SLDI_B3_SB(zeros, src0, zeros, src1, zeros, src2, 1, src0_sld1, + src1_sld1, src2_sld1); + SLDI_B2_SB(zeros, src3, zeros, src4, 1, src3_sld1, src4_sld1); ILVR_B3_UB(src0_sld1, src0, src1_sld1, src1, src2_sld1, src2, src0_r, src1_r, src2_r); ILVR_B2_UB(src3_sld1, src3, src4_sld1, src4, src3_r, src4_r); diff -Nru ffmpeg-4.2.2/libavcodec/mips/idctdsp_init_mips.c ffmpeg-4.4/libavcodec/mips/idctdsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/idctdsp_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/idctdsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,56 +19,44 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "idctdsp_mips.h" #include "xvididct_mips.h" -#if HAVE_MSA -static av_cold void idctdsp_init_msa(IDCTDSPContext *c, AVCodecContext *avctx, - unsigned high_bit_depth) +av_cold void ff_idctdsp_init_mips(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) { - 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_msa; - c->idct_add = ff_simple_idct_add_msa; - c->idct = ff_simple_idct_msa; - c->perm_type = FF_IDCT_PERM_NONE; - } + int cpu_flags = av_get_cpu_flags(); - c->put_pixels_clamped = ff_put_pixels_clamped_msa; - c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_msa; - c->add_pixels_clamped = ff_add_pixels_clamped_msa; -} -#endif // #if HAVE_MSA - -#if HAVE_MMI -static av_cold void idctdsp_init_mmi(IDCTDSPContext *c, AVCodecContext *avctx, - unsigned high_bit_depth) -{ - 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) || (avctx->idct_algo == FF_IDCT_SIMPLE))) { - c->idct_put = ff_simple_idct_put_8_mmi; - c->idct_add = ff_simple_idct_add_8_mmi; - c->idct = ff_simple_idct_8_mmi; - c->perm_type = FF_IDCT_PERM_NONE; + if (have_mmi(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) || (avctx->idct_algo == FF_IDCT_SIMPLE))) { + c->idct_put = ff_simple_idct_put_8_mmi; + c->idct_add = ff_simple_idct_add_8_mmi; + c->idct = ff_simple_idct_8_mmi; + c->perm_type = FF_IDCT_PERM_NONE; + } + + c->put_pixels_clamped = ff_put_pixels_clamped_mmi; + c->add_pixels_clamped = ff_add_pixels_clamped_mmi; + c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_mmi; } - c->put_pixels_clamped = ff_put_pixels_clamped_mmi; - c->add_pixels_clamped = ff_add_pixels_clamped_mmi; - c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_mmi; -} -#endif /* HAVE_MMI */ - -av_cold void ff_idctdsp_init_mips(IDCTDSPContext *c, AVCodecContext *avctx, - unsigned high_bit_depth) -{ -#if HAVE_MMI - idctdsp_init_mmi(c, avctx, high_bit_depth); -#endif /* HAVE_MMI */ -#if HAVE_MSA - idctdsp_init_msa(c, avctx, high_bit_depth); -#endif // #if HAVE_MSA + if (have_msa(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_msa; + c->idct_add = ff_simple_idct_add_msa; + c->idct = ff_simple_idct_msa; + c->perm_type = FF_IDCT_PERM_NONE; + } + + c->put_pixels_clamped = ff_put_pixels_clamped_msa; + c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_msa; + c->add_pixels_clamped = ff_add_pixels_clamped_msa; + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/idctdsp_msa.c ffmpeg-4.4/libavcodec/mips/idctdsp_msa.c --- ffmpeg-4.2.2/libavcodec/mips/idctdsp_msa.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/idctdsp_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -28,8 +28,7 @@ v8i16 in0, in1, in2, in3, in4, in5, in6, in7; LD_SH8(block, 8, in0, in1, in2, in3, in4, in5, in6, in7); - CLIP_SH4_0_255(in0, in1, in2, in3); - CLIP_SH4_0_255(in4, in5, in6, in7); + CLIP_SH8_0_255(in0, in1, in2, in3, in4, in5, in6, in7); PCKEV_B4_SH(in0, in0, in1, in1, in2, in2, in3, in3, in0, in1, in2, in3); PCKEV_B4_SH(in4, in4, in5, in5, in6, in6, in7, in7, in4, in5, in6, in7); @@ -63,8 +62,7 @@ in6 += 128; in7 += 128; - CLIP_SH4_0_255(in0, in1, in2, in3); - CLIP_SH4_0_255(in4, in5, in6, in7); + CLIP_SH8_0_255(in0, in1, in2, in3, in4, in5, in6, in7); PCKEV_B4_SH(in0, in0, in1, in1, in2, in2, in3, in3, in0, in1, in2, in3); PCKEV_B4_SH(in4, in4, in5, in5, in6, in6, in7, in7, in4, in5, in6, in7); @@ -109,8 +107,7 @@ in6 += (v8i16) pix6; in7 += (v8i16) pix7; - CLIP_SH4_0_255(in0, in1, in2, in3); - CLIP_SH4_0_255(in4, in5, in6, in7); + CLIP_SH8_0_255(in0, in1, in2, in3, in4, in5, in6, in7); PCKEV_B4_SH(in0, in0, in1, in1, in2, in2, in3, in3, in0, in1, in2, in3); PCKEV_B4_SH(in4, in4, in5, in5, in6, in6, in7, in7, in4, in5, in6, in7); diff -Nru ffmpeg-4.2.2/libavcodec/mips/Makefile ffmpeg-4.4/libavcodec/mips/Makefile --- ffmpeg-4.2.2/libavcodec/mips/Makefile 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/Makefile 2021-04-08 21:28:39.000000000 +0000 @@ -71,6 +71,8 @@ MSA-OBJS-$(CONFIG_MPEGVIDEO) += mips/mpegvideo_msa.o MSA-OBJS-$(CONFIG_MPEGVIDEOENC) += mips/mpegvideoencdsp_msa.o MSA-OBJS-$(CONFIG_ME_CMP) += mips/me_cmp_msa.o +MSA-OBJS-$(CONFIG_VC1_DECODER) += mips/vc1dsp_msa.o + MMI-OBJS += mips/constants.o MMI-OBJS-$(CONFIG_H264DSP) += mips/h264dsp_mmi.o MMI-OBJS-$(CONFIG_H264CHROMA) += mips/h264chroma_mmi.o diff -Nru ffmpeg-4.2.2/libavcodec/mips/me_cmp_init_mips.c ffmpeg-4.4/libavcodec/mips/me_cmp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/me_cmp_init_mips.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/me_cmp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,39 +18,35 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "me_cmp_mips.h" -#if HAVE_MSA -static av_cold void me_cmp_msa(MECmpContext *c, AVCodecContext *avctx) +av_cold void ff_me_cmp_init_mips(MECmpContext *c, AVCodecContext *avctx) { + int cpu_flags = av_get_cpu_flags(); + + if (have_msa(cpu_flags)) { #if BIT_DEPTH == 8 - c->pix_abs[0][0] = ff_pix_abs16_msa; - c->pix_abs[0][1] = ff_pix_abs16_x2_msa; - c->pix_abs[0][2] = ff_pix_abs16_y2_msa; - c->pix_abs[0][3] = ff_pix_abs16_xy2_msa; - c->pix_abs[1][0] = ff_pix_abs8_msa; - c->pix_abs[1][1] = ff_pix_abs8_x2_msa; - c->pix_abs[1][2] = ff_pix_abs8_y2_msa; - c->pix_abs[1][3] = ff_pix_abs8_xy2_msa; - - c->hadamard8_diff[0] = ff_hadamard8_diff16_msa; - c->hadamard8_diff[1] = ff_hadamard8_diff8x8_msa; - - c->hadamard8_diff[4] = ff_hadamard8_intra16_msa; - c->hadamard8_diff[5] = ff_hadamard8_intra8x8_msa; - - c->sad[0] = ff_pix_abs16_msa; - c->sad[1] = ff_pix_abs8_msa; - c->sse[0] = ff_sse16_msa; - c->sse[1] = ff_sse8_msa; - c->sse[2] = ff_sse4_msa; + c->pix_abs[0][0] = ff_pix_abs16_msa; + c->pix_abs[0][1] = ff_pix_abs16_x2_msa; + c->pix_abs[0][2] = ff_pix_abs16_y2_msa; + c->pix_abs[0][3] = ff_pix_abs16_xy2_msa; + c->pix_abs[1][0] = ff_pix_abs8_msa; + c->pix_abs[1][1] = ff_pix_abs8_x2_msa; + c->pix_abs[1][2] = ff_pix_abs8_y2_msa; + c->pix_abs[1][3] = ff_pix_abs8_xy2_msa; + + c->hadamard8_diff[0] = ff_hadamard8_diff16_msa; + c->hadamard8_diff[1] = ff_hadamard8_diff8x8_msa; + + c->hadamard8_diff[4] = ff_hadamard8_intra16_msa; + c->hadamard8_diff[5] = ff_hadamard8_intra8x8_msa; + + c->sad[0] = ff_pix_abs16_msa; + c->sad[1] = ff_pix_abs8_msa; + c->sse[0] = ff_sse16_msa; + c->sse[1] = ff_sse8_msa; + c->sse[2] = ff_sse4_msa; #endif -} -#endif // #if HAVE_MSA - -av_cold void ff_me_cmp_init_mips(MECmpContext *c, AVCodecContext *avctx) -{ -#if HAVE_MSA - me_cmp_msa(c, avctx); -#endif // #if HAVE_MSA + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/me_cmp_msa.c ffmpeg-4.4/libavcodec/mips/me_cmp_msa.c --- ffmpeg-4.2.2/libavcodec/mips/me_cmp_msa.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/me_cmp_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -87,8 +87,8 @@ PCKEV_D2_UB(src1, src0, src3, src2, src0, src1); PCKEV_D2_UB(ref1, ref0, ref3, ref2, ref4, ref5); - SLDI_B2_UB(ref0, ref1, ref0, ref1, ref0, ref1, 1); - SLDI_B2_UB(ref2, ref3, ref2, ref3, ref2, ref3, 1); + SLDI_B4_UB(ref0, ref0, ref1, ref1, ref2, ref2, ref3, ref3, 1, + ref0, ref1, ref2, ref3); PCKEV_D2_UB(ref1, ref0, ref3, ref2, ref0, ref1); AVER_UB2_UB(ref4, ref0, ref5, ref1, comp0, comp1); sad += SAD_UB2_UH(src0, src1, comp0, comp1); @@ -100,8 +100,8 @@ PCKEV_D2_UB(src1, src0, src3, src2, src0, src1); PCKEV_D2_UB(ref1, ref0, ref3, ref2, ref4, ref5); - SLDI_B2_UB(ref0, ref1, ref0, ref1, ref0, ref1, 1); - SLDI_B2_UB(ref2, ref3, ref2, ref3, ref2, ref3, 1); + SLDI_B4_UB(ref0, ref0, ref1, ref1, ref2, ref2, ref3, ref3, 1, + ref0, ref1, ref2, ref3); PCKEV_D2_UB(ref1, ref0, ref3, ref2, ref0, ref1); AVER_UB2_UB(ref4, ref0, ref5, ref1, comp0, comp1); sad += SAD_UB2_UH(src0, src1, comp0, comp1); diff -Nru ffmpeg-4.2.2/libavcodec/mips/mpegaudiodsp_mips_float.c ffmpeg-4.4/libavcodec/mips/mpegaudiodsp_mips_float.c --- ffmpeg-4.2.2/libavcodec/mips/mpegaudiodsp_mips_float.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/mpegaudiodsp_mips_float.c 2021-04-08 21:28:39.000000000 +0000 @@ -287,9 +287,16 @@ val8 , val9 , val10, val11, val12, val13, val14, val15, val16, val17, val18, val19, val20, val21, val22, val23, val24, val25, val26, val27, val28, val29, val30, val31; - float fTmp1, fTmp2, fTmp3, fTmp4, fTmp5, fTmp6, fTmp7, fTmp8, - fTmp9, fTmp10, fTmp11; + float fTmp1, fTmp2, fTmp3, fTmp4, fTmp5, fTmp6, fTmp8, fTmp9; + float f1, f2, f3, f4, f5, f6, f7; + f1 = 0.50241928618815570551; + f2 = 0.50060299823519630134; + f3 = 10.19000812354805681150; + f4 = 5.10114861868916385802; + f5 = 0.67480834145500574602; + f6 = 0.74453627100229844977; + f7 = 0.50979557910415916894; /** * instructions are scheduled to minimize pipeline stall. */ @@ -298,149 +305,142 @@ "lwc1 %[fTmp2], 31*4(%[tab]) \n\t" "lwc1 %[fTmp3], 15*4(%[tab]) \n\t" "lwc1 %[fTmp4], 16*4(%[tab]) \n\t" - "li.s %[fTmp7], 0.50241928618815570551 \n\t" "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" - "li.s %[fTmp10], 0.50060299823519630134 \n\t" - "li.s %[fTmp11], 10.19000812354805681150 \n\t" - "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "mul.s %[fTmp8], %[fTmp8], %[f2] \n\t" "add.s %[val0], %[fTmp5], %[fTmp6] \n\t" "sub.s %[val15], %[fTmp5], %[fTmp6] \n\t" "lwc1 %[fTmp1], 7*4(%[tab]) \n\t" "lwc1 %[fTmp2], 24*4(%[tab]) \n\t" - "madd.s %[val16], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "nmsub.s %[val31], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "mul.s %[val15], %[val15], %[fTmp7] \n\t" + "madd.s %[val16], %[fTmp8], %[fTmp9], %[f3] \n\t" + "nmsub.s %[val31], %[fTmp8], %[fTmp9], %[f3] \n\t" + "mul.s %[val15], %[val15], %[f1] \n\t" "lwc1 %[fTmp3], 8*4(%[tab]) \n\t" "lwc1 %[fTmp4], 23*4(%[tab]) \n\t" "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" - "mul.s %[val31], %[val31], %[fTmp7] \n\t" + "mul.s %[val31], %[val31], %[f1] \n\t" "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" - "li.s %[fTmp7], 5.10114861868916385802 \n\t" - "li.s %[fTmp10], 0.67480834145500574602 \n\t" - "li.s %[fTmp11], 0.74453627100229844977 \n\t" "add.s %[val7], %[fTmp5], %[fTmp6] \n\t" "sub.s %[val8], %[fTmp5], %[fTmp6] \n\t" - "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" - "li.s %[fTmp1], 0.50979557910415916894 \n\t" + "mul.s %[fTmp8], %[fTmp8], %[f5] \n\t" "sub.s %[fTmp2], %[val0], %[val7] \n\t" - "mul.s %[val8], %[val8], %[fTmp7] \n\t" - "madd.s %[val23], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "nmsub.s %[val24], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "mul.s %[val8], %[val8], %[f4] \n\t" + "madd.s %[val23], %[fTmp8], %[fTmp9], %[f6] \n\t" + "nmsub.s %[val24], %[fTmp8], %[fTmp9], %[f6] \n\t" "add.s %[val0], %[val0], %[val7] \n\t" - "mul.s %[val7], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val7], %[f7], %[fTmp2] \n\t" "sub.s %[fTmp2], %[val15], %[val8] \n\t" "add.s %[val8], %[val15], %[val8] \n\t" - "mul.s %[val24], %[val24], %[fTmp7] \n\t" + "mul.s %[val24], %[val24], %[f4] \n\t" "sub.s %[fTmp3], %[val16], %[val23] \n\t" "add.s %[val16], %[val16], %[val23] \n\t" - "mul.s %[val15], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val15], %[f7], %[fTmp2] \n\t" "sub.s %[fTmp4], %[val31], %[val24] \n\t" - "mul.s %[val23], %[fTmp1], %[fTmp3] \n\t" + "mul.s %[val23], %[f7], %[fTmp3] \n\t" "add.s %[val24], %[val31], %[val24] \n\t" - "mul.s %[val31], %[fTmp1], %[fTmp4] \n\t" + "mul.s %[val31], %[f7], %[fTmp4] \n\t" : [fTmp1] "=&f" (fTmp1), [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), [fTmp5] "=&f" (fTmp5), [fTmp6] "=&f" (fTmp6), - [fTmp7] "=&f" (fTmp7), [fTmp8] "=&f" (fTmp8), [fTmp9] "=&f" (fTmp9), - [fTmp10] "=&f" (fTmp10), [fTmp11] "=&f" (fTmp11), - [val0] "=f" (val0), [val7] "=f" (val7), - [val8] "=f" (val8), [val15] "=f" (val15), - [val16] "=f" (val16), [val23] "=f" (val23), - [val24] "=f" (val24), [val31] "=f" (val31) - : [tab] "r" (tab) + [fTmp8] "=&f" (fTmp8), [fTmp9] "=&f" (fTmp9), + [val0] "=&f" (val0), [val7] "=&f" (val7), + [val8] "=&f" (val8), [val15] "=&f" (val15), + [val16] "=&f" (val16), [val23] "=&f" (val23), + [val24] "=&f" (val24), [val31] "=&f" (val31) + : [tab] "r" (tab), [f1]"f"(f1), [f2]"f"(f2), [f3]"f"(f3), + [f4]"f"(f4), [f5]"f"(f5), [f6]"f"(f6), [f7]"f"(f7) : "memory" ); + f1 = 0.64682178335999012954; + f2 = 0.53104259108978417447; + f3 = 1.48416461631416627724; + f4 = 0.78815462345125022473; + f5 = 0.55310389603444452782; + f6 = 1.16943993343288495515; + f7 = 2.56291544774150617881; __asm__ volatile ( "lwc1 %[fTmp1], 3*4(%[tab]) \n\t" "lwc1 %[fTmp2], 28*4(%[tab]) \n\t" "lwc1 %[fTmp3], 12*4(%[tab]) \n\t" "lwc1 %[fTmp4], 19*4(%[tab]) \n\t" - "li.s %[fTmp7], 0.64682178335999012954 \n\t" "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" - "li.s %[fTmp10], 0.53104259108978417447 \n\t" - "li.s %[fTmp11], 1.48416461631416627724 \n\t" - "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "mul.s %[fTmp8], %[fTmp8], %[f2] \n\t" "add.s %[val3], %[fTmp5], %[fTmp6] \n\t" "sub.s %[val12], %[fTmp5], %[fTmp6] \n\t" "lwc1 %[fTmp1], 4*4(%[tab]) \n\t" "lwc1 %[fTmp2], 27*4(%[tab]) \n\t" - "madd.s %[val19], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "nmsub.s %[val28], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "mul.s %[val12], %[val12], %[fTmp7] \n\t" + "madd.s %[val19], %[fTmp8], %[fTmp9], %[f3] \n\t" + "nmsub.s %[val28], %[fTmp8], %[fTmp9], %[f3] \n\t" + "mul.s %[val12], %[val12], %[f1] \n\t" "lwc1 %[fTmp3], 11*4(%[tab]) \n\t" "lwc1 %[fTmp4], 20*4(%[tab]) \n\t" "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" - "mul.s %[val28], %[val28], %[fTmp7] \n\t" + "mul.s %[val28], %[val28], %[f1] \n\t" "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" - "li.s %[fTmp7], 0.78815462345125022473 \n\t" "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" - "li.s %[fTmp10], 0.55310389603444452782 \n\t" - "li.s %[fTmp11], 1.16943993343288495515 \n\t" - "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "mul.s %[fTmp8], %[fTmp8], %[f5] \n\t" "add.s %[val4], %[fTmp5], %[fTmp6] \n\t" "sub.s %[val11], %[fTmp5], %[fTmp6] \n\t" - "li.s %[fTmp1], 2.56291544774150617881 \n\t" - "madd.s %[val20], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "nmsub.s %[val27], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "mul.s %[val11], %[val11], %[fTmp7] \n\t" + "madd.s %[val20], %[fTmp8], %[fTmp9], %[f6] \n\t" + "nmsub.s %[val27], %[fTmp8], %[fTmp9], %[f6] \n\t" + "mul.s %[val11], %[val11], %[f4] \n\t" "sub.s %[fTmp2], %[val3], %[val4] \n\t" "add.s %[val3], %[val3], %[val4] \n\t" "sub.s %[fTmp4], %[val19], %[val20] \n\t" - "mul.s %[val27], %[val27], %[fTmp7] \n\t" + "mul.s %[val27], %[val27], %[f4] \n\t" "sub.s %[fTmp3], %[val12], %[val11] \n\t" - "mul.s %[val4], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val4], %[f7], %[fTmp2] \n\t" "add.s %[val11], %[val12], %[val11] \n\t" "add.s %[val19], %[val19], %[val20] \n\t" - "mul.s %[val20], %[fTmp1], %[fTmp4] \n\t" - "mul.s %[val12], %[fTmp1], %[fTmp3] \n\t" + "mul.s %[val20], %[f7], %[fTmp4] \n\t" + "mul.s %[val12], %[f7], %[fTmp3] \n\t" "sub.s %[fTmp2], %[val28], %[val27] \n\t" "add.s %[val27], %[val28], %[val27] \n\t" - "mul.s %[val28], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val28], %[f7], %[fTmp2] \n\t" : [fTmp1] "=&f" (fTmp1), [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), [fTmp5] "=&f" (fTmp5), [fTmp6] "=&f" (fTmp6), - [fTmp7] "=&f" (fTmp7), [fTmp8] "=&f" (fTmp8), [fTmp9] "=&f" (fTmp9), - [fTmp10] "=&f" (fTmp10), [fTmp11] "=&f" (fTmp11), - [val3] "=f" (val3), [val4] "=f" (val4), - [val11] "=f" (val11), [val12] "=f" (val12), - [val19] "=f" (val19), [val20] "=f" (val20), - [val27] "=f" (val27), [val28] "=f" (val28) - : [tab] "r" (tab) + [fTmp8] "=&f" (fTmp8), [fTmp9] "=&f" (fTmp9), + [val3] "=&f" (val3), [val4] "=&f" (val4), + [val11] "=&f" (val11), [val12] "=&f" (val12), + [val19] "=&f" (val19), [val20] "=&f" (val20), + [val27] "=&f" (val27), [val28] "=&f" (val28) + : [tab] "r" (tab), [f1]"f"(f1), [f2]"f"(f2), [f3]"f"(f3), + [f4]"f"(f4), [f5]"f"(f5), [f6]"f"(f6), [f7]"f"(f7) : "memory" ); + f1 = 0.54119610014619698439; __asm__ volatile ( - "li.s %[fTmp1], 0.54119610014619698439 \n\t" "sub.s %[fTmp2], %[val0], %[val3] \n\t" "add.s %[val0], %[val0], %[val3] \n\t" "sub.s %[fTmp3], %[val7], %[val4] \n\t" "add.s %[val4], %[val7], %[val4] \n\t" "sub.s %[fTmp4], %[val8], %[val11] \n\t" - "mul.s %[val3], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val3], %[f1], %[fTmp2] \n\t" "add.s %[val8], %[val8], %[val11] \n\t" - "mul.s %[val7], %[fTmp1], %[fTmp3] \n\t" + "mul.s %[val7], %[f1], %[fTmp3] \n\t" "sub.s %[fTmp2], %[val15], %[val12] \n\t" - "mul.s %[val11], %[fTmp1], %[fTmp4] \n\t" + "mul.s %[val11], %[f1], %[fTmp4] \n\t" "add.s %[val12], %[val15], %[val12] \n\t" - "mul.s %[val15], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val15], %[f1], %[fTmp2] \n\t" - : [val0] "+f" (val0), [val3] "+f" (val3), - [val4] "+f" (val4), [val7] "+f" (val7), - [val8] "+f" (val8), [val11] "+f" (val11), - [val12] "+f" (val12), [val15] "+f" (val15), - [fTmp1] "=f" (fTmp1), [fTmp2] "=&f" (fTmp2), + : [val0] "+&f" (val0), [val3] "+&f" (val3), + [val4] "+&f" (val4), [val7] "+&f" (val7), + [val8] "+&f" (val8), [val11] "+&f" (val11), + [val12] "+&f" (val12), [val15] "+&f" (val15), + [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4) - : + : [f1] "f" (f1) ); __asm__ volatile ( @@ -449,169 +449,169 @@ "sub.s %[fTmp3], %[val23], %[val20] \n\t" "add.s %[val20], %[val23], %[val20] \n\t" "sub.s %[fTmp4], %[val24], %[val27] \n\t" - "mul.s %[val19], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val19], %[f1], %[fTmp2] \n\t" "add.s %[val24], %[val24], %[val27] \n\t" - "mul.s %[val23], %[fTmp1], %[fTmp3] \n\t" + "mul.s %[val23], %[f1], %[fTmp3] \n\t" "sub.s %[fTmp2], %[val31], %[val28] \n\t" - "mul.s %[val27], %[fTmp1], %[fTmp4] \n\t" + "mul.s %[val27], %[f1], %[fTmp4] \n\t" "add.s %[val28], %[val31], %[val28] \n\t" - "mul.s %[val31], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val31], %[f1], %[fTmp2] \n\t" : [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), - [val16] "+f" (val16), [val19] "+f" (val19), [val20] "+f" (val20), - [val23] "+f" (val23), [val24] "+f" (val24), [val27] "+f" (val27), - [val28] "+f" (val28), [val31] "+f" (val31) - : [fTmp1] "f" (fTmp1) + [val16] "+&f" (val16), [val19] "+&f" (val19), [val20] "+&f" (val20), + [val23] "+&f" (val23), [val24] "+&f" (val24), [val27] "+&f" (val27), + [val28] "+&f" (val28), [val31] "+&f" (val31) + : [f1] "f" (f1) ); + f1 = 0.52249861493968888062; + f2 = 0.50547095989754365998; + f3 = 3.40760841846871878570; + f4 = 1.72244709823833392782; + f5 = 0.62250412303566481615; + f6 = 0.83934964541552703873; + f7 = 0.60134488693504528054; __asm__ volatile ( "lwc1 %[fTmp1], 1*4(%[tab]) \n\t" "lwc1 %[fTmp2], 30*4(%[tab]) \n\t" "lwc1 %[fTmp3], 14*4(%[tab]) \n\t" "lwc1 %[fTmp4], 17*4(%[tab]) \n\t" - "li.s %[fTmp7], 0.52249861493968888062 \n\t" "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" - "li.s %[fTmp10], 0.50547095989754365998 \n\t" - "li.s %[fTmp11], 3.40760841846871878570 \n\t" - "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "mul.s %[fTmp8], %[fTmp8], %[f2] \n\t" "add.s %[val1], %[fTmp5], %[fTmp6] \n\t" "sub.s %[val14], %[fTmp5], %[fTmp6] \n\t" "lwc1 %[fTmp1], 6*4(%[tab]) \n\t" "lwc1 %[fTmp2], 25*4(%[tab]) \n\t" - "madd.s %[val17], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "nmsub.s %[val30], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "mul.s %[val14], %[val14], %[fTmp7] \n\t" + "madd.s %[val17], %[fTmp8], %[fTmp9], %[f3] \n\t" + "nmsub.s %[val30], %[fTmp8], %[fTmp9], %[f3] \n\t" + "mul.s %[val14], %[val14], %[f1] \n\t" "lwc1 %[fTmp3], 9*4(%[tab]) \n\t" "lwc1 %[fTmp4], 22*4(%[tab]) \n\t" "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" - "mul.s %[val30], %[val30], %[fTmp7] \n\t" + "mul.s %[val30], %[val30], %[f1] \n\t" "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" - "li.s %[fTmp7], 1.72244709823833392782 \n\t" - "li.s %[fTmp10], 0.62250412303566481615 \n\t" - "li.s %[fTmp11], 0.83934964541552703873 \n\t" "add.s %[val6], %[fTmp5], %[fTmp6] \n\t" "sub.s %[val9], %[fTmp5], %[fTmp6] \n\t" - "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" - "li.s %[fTmp1], 0.60134488693504528054 \n\t" + "mul.s %[fTmp8], %[fTmp8], %[f5] \n\t" "sub.s %[fTmp2], %[val1], %[val6] \n\t" "add.s %[val1], %[val1], %[val6] \n\t" - "mul.s %[val9], %[val9], %[fTmp7] \n\t" - "madd.s %[val22], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "nmsub.s %[val25], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "mul.s %[val6], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val9], %[val9], %[f4] \n\t" + "madd.s %[val22], %[fTmp8], %[fTmp9], %[f6] \n\t" + "nmsub.s %[val25], %[fTmp8], %[fTmp9], %[f6] \n\t" + "mul.s %[val6], %[f7], %[fTmp2] \n\t" "sub.s %[fTmp2], %[val14], %[val9] \n\t" "add.s %[val9], %[val14], %[val9] \n\t" - "mul.s %[val25], %[val25], %[fTmp7] \n\t" + "mul.s %[val25], %[val25], %[f4] \n\t" "sub.s %[fTmp3], %[val17], %[val22] \n\t" "add.s %[val17], %[val17], %[val22] \n\t" - "mul.s %[val14], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val14], %[f7], %[fTmp2] \n\t" "sub.s %[fTmp2], %[val30], %[val25] \n\t" - "mul.s %[val22], %[fTmp1], %[fTmp3] \n\t" + "mul.s %[val22], %[f7], %[fTmp3] \n\t" "add.s %[val25], %[val30], %[val25] \n\t" - "mul.s %[val30], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val30], %[f7], %[fTmp2] \n\t" : [fTmp1] "=&f" (fTmp1), [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), [fTmp5] "=&f" (fTmp5), [fTmp6] "=&f" (fTmp6), - [fTmp7] "=&f" (fTmp7), [fTmp8] "=&f" (fTmp8), [fTmp9] "=&f" (fTmp9), - [fTmp10] "=&f" (fTmp10), [fTmp11] "=&f" (fTmp11), - [val1] "=f" (val1), [val6] "=f" (val6), - [val9] "=f" (val9), [val14] "=f" (val14), - [val17] "=f" (val17), [val22] "=f" (val22), - [val25] "=f" (val25), [val30] "=f" (val30) - : [tab] "r" (tab) + [fTmp8] "=&f" (fTmp8), [fTmp9] "=&f" (fTmp9), + [val1] "=&f" (val1), [val6] "=&f" (val6), + [val9] "=&f" (val9), [val14] "=&f" (val14), + [val17] "=&f" (val17), [val22] "=&f" (val22), + [val25] "=&f" (val25), [val30] "=&f" (val30) + : [tab] "r" (tab), [f1]"f"(f1), [f2]"f"(f2), [f3]"f"(f3), + [f4]"f"(f4), [f5]"f"(f5), [f6]"f"(f6), [f7]"f"(f7) : "memory" ); + f1 = 0.56694403481635770368; + f2 = 0.51544730992262454697; + f3 = 2.05778100995341155085; + f4 = 1.06067768599034747134; + f5 = 0.58293496820613387367; + f6 = 0.97256823786196069369; + f7 = 0.89997622313641570463; __asm__ volatile ( "lwc1 %[fTmp1], 2*4(%[tab]) \n\t" "lwc1 %[fTmp2], 29*4(%[tab]) \n\t" "lwc1 %[fTmp3], 13*4(%[tab]) \n\t" "lwc1 %[fTmp4], 18*4(%[tab]) \n\t" - "li.s %[fTmp7], 0.56694403481635770368 \n\t" "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" - "li.s %[fTmp10], 0.51544730992262454697 \n\t" - "li.s %[fTmp11], 2.05778100995341155085 \n\t" - "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "mul.s %[fTmp8], %[fTmp8], %[f2] \n\t" "add.s %[val2], %[fTmp5], %[fTmp6] \n\t" "sub.s %[val13], %[fTmp5], %[fTmp6] \n\t" "lwc1 %[fTmp1], 5*4(%[tab]) \n\t" "lwc1 %[fTmp2], 26*4(%[tab]) \n\t" - "madd.s %[val18], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "nmsub.s %[val29], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "mul.s %[val13], %[val13], %[fTmp7] \n\t" + "madd.s %[val18], %[fTmp8], %[fTmp9], %[f3] \n\t" + "nmsub.s %[val29], %[fTmp8], %[fTmp9], %[f3] \n\t" + "mul.s %[val13], %[val13], %[f1] \n\t" "lwc1 %[fTmp3], 10*4(%[tab]) \n\t" "lwc1 %[fTmp4], 21*4(%[tab]) \n\t" - "mul.s %[val29], %[val29], %[fTmp7] \n\t" + "mul.s %[val29], %[val29], %[f1] \n\t" "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" - "li.s %[fTmp7], 1.06067768599034747134 \n\t" - "li.s %[fTmp10], 0.58293496820613387367 \n\t" - "li.s %[fTmp11], 0.97256823786196069369 \n\t" "add.s %[val5], %[fTmp5], %[fTmp6] \n\t" "sub.s %[val10], %[fTmp5], %[fTmp6] \n\t" - "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" - "li.s %[fTmp1], 0.89997622313641570463 \n\t" + "mul.s %[fTmp8], %[fTmp8], %[f5] \n\t" "sub.s %[fTmp2], %[val2], %[val5] \n\t" - "mul.s %[val10], %[val10], %[fTmp7] \n\t" - "madd.s %[val21], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" - "nmsub.s %[val26], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "mul.s %[val10], %[val10], %[f4] \n\t" + "madd.s %[val21], %[fTmp8], %[fTmp9], %[f6] \n\t" + "nmsub.s %[val26], %[fTmp8], %[fTmp9], %[f6] \n\t" "add.s %[val2], %[val2], %[val5] \n\t" - "mul.s %[val5], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val5], %[f7], %[fTmp2] \n\t" "sub.s %[fTmp3], %[val13], %[val10] \n\t" "add.s %[val10], %[val13], %[val10] \n\t" - "mul.s %[val26], %[val26], %[fTmp7] \n\t" + "mul.s %[val26], %[val26], %[f4] \n\t" "sub.s %[fTmp4], %[val18], %[val21] \n\t" "add.s %[val18], %[val18], %[val21] \n\t" - "mul.s %[val13], %[fTmp1], %[fTmp3] \n\t" + "mul.s %[val13], %[f7], %[fTmp3] \n\t" "sub.s %[fTmp2], %[val29], %[val26] \n\t" "add.s %[val26], %[val29], %[val26] \n\t" - "mul.s %[val21], %[fTmp1], %[fTmp4] \n\t" - "mul.s %[val29], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val21], %[f7], %[fTmp4] \n\t" + "mul.s %[val29], %[f7], %[fTmp2] \n\t" : [fTmp1] "=&f" (fTmp1), [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), [fTmp5] "=&f" (fTmp5), [fTmp6] "=&f" (fTmp6), - [fTmp7] "=&f" (fTmp7), [fTmp8] "=&f" (fTmp8), [fTmp9] "=&f" (fTmp9), - [fTmp10] "=&f" (fTmp10), [fTmp11] "=&f" (fTmp11), - [val2] "=f" (val2), [val5] "=f" (val5), - [val10] "=f" (val10), [val13] "=f" (val13), - [val18] "=f" (val18), [val21] "=f" (val21), - [val26] "=f" (val26), [val29] "=f" (val29) - : [tab] "r" (tab) + [fTmp8] "=&f" (fTmp8), [fTmp9] "=&f" (fTmp9), + [val2] "=&f" (val2), [val5] "=&f" (val5), + [val10] "=&f" (val10), [val13] "=&f" (val13), + [val18] "=&f" (val18), [val21] "=&f" (val21), + [val26] "=&f" (val26), [val29] "=&f" (val29) + : [tab] "r" (tab), [f1]"f"(f1), [f2]"f"(f2), [f3]"f"(f3), + [f4]"f"(f4), [f5]"f"(f5), [f6]"f"(f6), [f7]"f"(f7) : "memory" ); + f1 = 1.30656296487637652785; __asm__ volatile ( - "li.s %[fTmp1], 1.30656296487637652785 \n\t" "sub.s %[fTmp2], %[val1], %[val2] \n\t" "add.s %[val1], %[val1], %[val2] \n\t" "sub.s %[fTmp3], %[val6], %[val5] \n\t" "add.s %[val5], %[val6], %[val5] \n\t" "sub.s %[fTmp4], %[val9], %[val10] \n\t" - "mul.s %[val2], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val2], %[f1], %[fTmp2] \n\t" "add.s %[val9], %[val9], %[val10] \n\t" - "mul.s %[val6], %[fTmp1], %[fTmp3] \n\t" + "mul.s %[val6], %[f1], %[fTmp3] \n\t" "sub.s %[fTmp2], %[val14], %[val13] \n\t" - "mul.s %[val10], %[fTmp1], %[fTmp4] \n\t" + "mul.s %[val10], %[f1], %[fTmp4] \n\t" "add.s %[val13], %[val14], %[val13] \n\t" - "mul.s %[val14], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val14], %[f1], %[fTmp2] \n\t" - : [fTmp1] "=f" (fTmp1), [fTmp2] "=&f" (fTmp2), + : [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), - [val1] "+f" (val1), [val2] "+f" (val2), - [val5] "+f" (val5), [val6] "+f" (val6), - [val9] "+f" (val9), [val10] "+f" (val10), - [val13] "+f" (val13), [val14] "+f" (val14) - : + [val1] "+&f" (val1), [val2] "+&f" (val2), + [val5] "+&f" (val5), [val6] "+&f" (val6), + [val9] "+&f" (val9), [val10] "+&f" (val10), + [val13] "+&f" (val13), [val14] "+&f" (val14) + : [f1]"f"(f1) ); __asm__ volatile ( @@ -620,39 +620,39 @@ "sub.s %[fTmp3], %[val22], %[val21] \n\t" "add.s %[val21], %[val22], %[val21] \n\t" "sub.s %[fTmp4], %[val25], %[val26] \n\t" - "mul.s %[val18], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val18], %[f1], %[fTmp2] \n\t" "add.s %[val25], %[val25], %[val26] \n\t" - "mul.s %[val22], %[fTmp1], %[fTmp3] \n\t" + "mul.s %[val22], %[f1], %[fTmp3] \n\t" "sub.s %[fTmp2], %[val30], %[val29] \n\t" - "mul.s %[val26], %[fTmp1], %[fTmp4] \n\t" + "mul.s %[val26], %[f1], %[fTmp4] \n\t" "add.s %[val29], %[val30], %[val29] \n\t" - "mul.s %[val30], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val30], %[f1], %[fTmp2] \n\t" : [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), - [val17] "+f" (val17), [val18] "+f" (val18), [val21] "+f" (val21), - [val22] "+f" (val22), [val25] "+f" (val25), [val26] "+f" (val26), - [val29] "+f" (val29), [val30] "+f" (val30) - : [fTmp1] "f" (fTmp1) + [val17] "+&f" (val17), [val18] "+&f" (val18), [val21] "+&f" (val21), + [val22] "+&f" (val22), [val25] "+&f" (val25), [val26] "+&f" (val26), + [val29] "+&f" (val29), [val30] "+&f" (val30) + : [f1] "f" (f1) ); + f1 = 0.70710678118654752439; __asm__ volatile ( - "li.s %[fTmp1], 0.70710678118654752439 \n\t" "sub.s %[fTmp2], %[val0], %[val1] \n\t" "add.s %[val0], %[val0], %[val1] \n\t" "sub.s %[fTmp3], %[val3], %[val2] \n\t" "add.s %[val2], %[val3], %[val2] \n\t" "sub.s %[fTmp4], %[val4], %[val5] \n\t" - "mul.s %[val1], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val1], %[f1], %[fTmp2] \n\t" "swc1 %[val0], 0(%[out]) \n\t" - "mul.s %[val3], %[fTmp3], %[fTmp1] \n\t" + "mul.s %[val3], %[fTmp3], %[f1] \n\t" "add.s %[val4], %[val4], %[val5] \n\t" - "mul.s %[val5], %[fTmp1], %[fTmp4] \n\t" + "mul.s %[val5], %[f1], %[fTmp4] \n\t" "swc1 %[val1], 16*4(%[out]) \n\t" "sub.s %[fTmp2], %[val7], %[val6] \n\t" "add.s %[val2], %[val2], %[val3] \n\t" "swc1 %[val3], 24*4(%[out]) \n\t" "add.s %[val6], %[val7], %[val6] \n\t" - "mul.s %[val7], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val7], %[f1], %[fTmp2] \n\t" "swc1 %[val2], 8*4(%[out]) \n\t" "add.s %[val6], %[val6], %[val7] \n\t" "swc1 %[val7], 28*4(%[out]) \n\t" @@ -663,13 +663,13 @@ "swc1 %[val5], 20*4(%[out]) \n\t" "swc1 %[val6], 12*4(%[out]) \n\t" - : [fTmp1] "=f" (fTmp1), [fTmp2] "=&f" (fTmp2), + : [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), - [val0] "+f" (val0), [val1] "+f" (val1), - [val2] "+f" (val2), [val3] "+f" (val3), - [val4] "+f" (val4), [val5] "+f" (val5), - [val6] "+f" (val6), [val7] "+f" (val7) - : [out] "r" (out) + [val0] "+&f" (val0), [val1] "+&f" (val1), + [val2] "+&f" (val2), [val3] "+&f" (val3), + [val4] "+&f" (val4), [val5] "+&f" (val5), + [val6] "+&f" (val6), [val7] "+&f" (val7) + : [out] "r" (out), [f1]"f"(f1) ); __asm__ volatile ( @@ -678,14 +678,14 @@ "sub.s %[fTmp3], %[val11], %[val10] \n\t" "add.s %[val10], %[val11], %[val10] \n\t" "sub.s %[fTmp4], %[val12], %[val13] \n\t" - "mul.s %[val9], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val9], %[f1], %[fTmp2] \n\t" "add.s %[val12], %[val12], %[val13] \n\t" - "mul.s %[val11], %[fTmp1], %[fTmp3] \n\t" + "mul.s %[val11], %[f1], %[fTmp3] \n\t" "sub.s %[fTmp2], %[val15], %[val14] \n\t" - "mul.s %[val13], %[fTmp1], %[fTmp4] \n\t" + "mul.s %[val13], %[f1], %[fTmp4] \n\t" "add.s %[val14], %[val15], %[val14] \n\t" "add.s %[val10], %[val10], %[val11] \n\t" - "mul.s %[val15], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val15], %[f1], %[fTmp2] \n\t" "add.s %[val14], %[val14], %[val15] \n\t" "add.s %[val12], %[val12], %[val14] \n\t" "add.s %[val14], %[val14], %[val13] \n\t" @@ -707,10 +707,10 @@ "swc1 %[val15], 30*4(%[out]) \n\t" : [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), - [val8] "+f" (val8), [val9] "+f" (val9), [val10] "+f" (val10), - [val11] "+f" (val11), [val12] "+f" (val12), [val13] "+f" (val13), - [val14] "+f" (val14), [val15] "+f" (val15) - : [fTmp1] "f" (fTmp1), [out] "r" (out) + [val8] "+&f" (val8), [val9] "+&f" (val9), [val10] "+&f" (val10), + [val11] "+&f" (val11), [val12] "+&f" (val12), [val13] "+&f" (val13), + [val14] "+&f" (val14), [val15] "+&f" (val15) + : [f1] "f" (f1), [out] "r" (out) ); __asm__ volatile ( @@ -719,24 +719,24 @@ "sub.s %[fTmp3], %[val19], %[val18] \n\t" "add.s %[val18], %[val19], %[val18] \n\t" "sub.s %[fTmp4], %[val20], %[val21] \n\t" - "mul.s %[val17], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val17], %[f1], %[fTmp2] \n\t" "add.s %[val20], %[val20], %[val21] \n\t" - "mul.s %[val19], %[fTmp1], %[fTmp3] \n\t" + "mul.s %[val19], %[f1], %[fTmp3] \n\t" "sub.s %[fTmp2], %[val23], %[val22] \n\t" - "mul.s %[val21], %[fTmp1], %[fTmp4] \n\t" + "mul.s %[val21], %[f1], %[fTmp4] \n\t" "add.s %[val22], %[val23], %[val22] \n\t" "add.s %[val18], %[val18], %[val19] \n\t" - "mul.s %[val23], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val23], %[f1], %[fTmp2] \n\t" "add.s %[val22], %[val22], %[val23] \n\t" "add.s %[val20], %[val20], %[val22] \n\t" "add.s %[val22], %[val22], %[val21] \n\t" "add.s %[val21], %[val21], %[val23] \n\t" : [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), - [val16] "+f" (val16), [val17] "+f" (val17), [val18] "+f" (val18), - [val19] "+f" (val19), [val20] "+f" (val20), [val21] "+f" (val21), - [val22] "+f" (val22), [val23] "+f" (val23) - : [fTmp1] "f" (fTmp1) + [val16] "+&f" (val16), [val17] "+&f" (val17), [val18] "+&f" (val18), + [val19] "+&f" (val19), [val20] "+&f" (val20), [val21] "+&f" (val21), + [val22] "+&f" (val22), [val23] "+&f" (val23) + : [f1] "f" (f1) ); __asm__ volatile ( @@ -745,14 +745,14 @@ "sub.s %[fTmp3], %[val27], %[val26] \n\t" "add.s %[val26], %[val27], %[val26] \n\t" "sub.s %[fTmp4], %[val28], %[val29] \n\t" - "mul.s %[val25], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val25], %[f1], %[fTmp2] \n\t" "add.s %[val28], %[val28], %[val29] \n\t" - "mul.s %[val27], %[fTmp1], %[fTmp3] \n\t" + "mul.s %[val27], %[f1], %[fTmp3] \n\t" "sub.s %[fTmp2], %[val31], %[val30] \n\t" - "mul.s %[val29], %[fTmp1], %[fTmp4] \n\t" + "mul.s %[val29], %[f1], %[fTmp4] \n\t" "add.s %[val30], %[val31], %[val30] \n\t" "add.s %[val26], %[val26], %[val27] \n\t" - "mul.s %[val31], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val31], %[f1], %[fTmp2] \n\t" "add.s %[val30], %[val30], %[val31] \n\t" "add.s %[val28], %[val28], %[val30] \n\t" "add.s %[val30], %[val30], %[val29] \n\t" @@ -766,10 +766,10 @@ "add.s %[val27], %[val27], %[val31] \n\t" : [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), - [val24] "+f" (val24), [val25] "+f" (val25), [val26] "+f" (val26), - [val27] "+f" (val27), [val28] "+f" (val28), [val29] "+f" (val29), - [val30] "+f" (val30), [val31] "+f" (val31) - : [fTmp1] "f" (fTmp1) + [val24] "+&f" (val24), [val25] "+&f" (val25), [val26] "+&f" (val26), + [val27] "+&f" (val27), [val28] "+&f" (val28), [val29] "+&f" (val29), + [val30] "+&f" (val30), [val31] "+&f" (val31) + : [f1] "f" (f1) ); out[ 1] = val16 + val24; @@ -797,7 +797,7 @@ /* temporary variables */ float in1, in2, in3, in4, in5, in6; float out1, out2, out3, out4, out5; - float c1, c2, c3, c4, c5, c6, c7, c8, c9; + float f1, f2, f3, f4, f5, f6, f7, f8, f9; /** * all loops are unrolled totally, and instructions are scheduled to @@ -881,33 +881,36 @@ ); /* loop 3 */ + f1 = 0.5; + f2 = 0.93969262078590838405; + f3 = -0.76604444311897803520; + f4 = -0.17364817766693034885; + f5 = -0.86602540378443864676; + f6 = 0.98480775301220805936; + f7 = -0.34202014332566873304; + f8 = 0.86602540378443864676; + f9 = -0.64278760968653932632; __asm__ volatile ( - "li.s %[c1], 0.5 \t\n" "lwc1 %[in1], 8*4(%[in]) \t\n" "lwc1 %[in2], 16*4(%[in]) \t\n" "lwc1 %[in3], 4*4(%[in]) \t\n" "lwc1 %[in4], 0(%[in]) \t\n" "lwc1 %[in5], 12*4(%[in]) \t\n" - "li.s %[c2], 0.93969262078590838405 \t\n" "add.s %[t2], %[in1], %[in2] \t\n" "add.s %[t0], %[in1], %[in3] \t\n" - "li.s %[c3], -0.76604444311897803520 \t\n" - "madd.s %[t3], %[in4], %[in5], %[c1] \t\n" + "madd.s %[t3], %[in4], %[in5], %[f1] \t\n" "sub.s %[t1], %[in4], %[in5] \t\n" "sub.s %[t2], %[t2], %[in3] \t\n" - "mul.s %[t0], %[t0], %[c2] \t\n" - "li.s %[c4], -0.17364817766693034885 \t\n" - "li.s %[c5], -0.86602540378443864676 \t\n" - "li.s %[c6], 0.98480775301220805936 \t\n" - "nmsub.s %[out1], %[t1], %[t2], %[c1] \t\n" + "mul.s %[t0], %[t0], %[f2] \t\n" + "nmsub.s %[out1], %[t1], %[t2], %[f1] \t\n" "add.s %[out2], %[t1], %[t2] \t\n" "add.s %[t2], %[in2], %[in3] \t\n" "sub.s %[t1], %[in1], %[in2] \t\n" "sub.s %[out3], %[t3], %[t0] \t\n" "swc1 %[out1], 6*4(%[tmp]) \t\n" "swc1 %[out2], 16*4(%[tmp]) \t\n" - "mul.s %[t2], %[t2], %[c3] \t\n" - "mul.s %[t1], %[t1], %[c4] \t\n" + "mul.s %[t2], %[t2], %[f3] \t\n" + "mul.s %[t1], %[t1], %[f4] \t\n" "add.s %[out1], %[t3], %[t0] \t\n" "lwc1 %[in1], 10*4(%[in]) \t\n" "lwc1 %[in2], 14*4(%[in]) \t\n" @@ -923,19 +926,16 @@ "add.s %[t2], %[in1], %[in3] \t\n" "sub.s %[t3], %[in1], %[in2] \t\n" "swc1 %[out2], 14*4(%[tmp]) \t\n" - "li.s %[c7], -0.34202014332566873304 \t\n" "sub.s %[out1], %[out1], %[in3] \t\n" - "mul.s %[t2], %[t2], %[c6] \t\n" - "mul.s %[t3], %[t3], %[c7] \t\n" - "li.s %[c8], 0.86602540378443864676 \t\n" - "mul.s %[t0], %[in4], %[c8] \t\n" - "mul.s %[out1], %[out1], %[c5] \t\n" + "mul.s %[t2], %[t2], %[f6] \t\n" + "mul.s %[t3], %[t3], %[f7] \t\n" + "mul.s %[t0], %[in4], %[f8] \t\n" + "mul.s %[out1], %[out1], %[f5] \t\n" "add.s %[t1], %[in2], %[in3] \t\n" - "li.s %[c9], -0.64278760968653932632 \t\n" "add.s %[out2], %[t2], %[t3] \t\n" "lwc1 %[in1], 9*4(%[in]) \t\n" "swc1 %[out1], 4*4(%[tmp]) \t\n" - "mul.s %[t1], %[t1], %[c9] \t\n" + "mul.s %[t1], %[t1], %[f9] \t\n" "lwc1 %[in2], 17*4(%[in]) \t\n" "add.s %[out2], %[out2], %[t0] \t\n" "lwc1 %[in3], 5*4(%[in]) \t\n" @@ -948,21 +948,21 @@ "sub.s %[out3], %[out3], %[t0] \t\n" "sub.s %[out1], %[out1], %[t0] \t\n" "add.s %[t0], %[in1], %[in3] \t\n" - "madd.s %[t3], %[in4], %[in5], %[c1] \t\n" + "madd.s %[t3], %[in4], %[in5], %[f1] \t\n" "sub.s %[t2], %[t2], %[in3] \t\n" "swc1 %[out3], 12*4(%[tmp]) \t\n" "swc1 %[out1], 8*4(%[tmp]) \t\n" "sub.s %[t1], %[in4], %[in5] \t\n" - "mul.s %[t0], %[t0], %[c2] \t\n" - "nmsub.s %[out1], %[t1], %[t2], %[c1] \t\n" + "mul.s %[t0], %[t0], %[f2] \t\n" + "nmsub.s %[out1], %[t1], %[t2], %[f1] \t\n" "add.s %[out2], %[t1], %[t2] \t\n" "add.s %[t2], %[in2], %[in3] \t\n" "sub.s %[t1], %[in1], %[in2] \t\n" "sub.s %[out3], %[t3], %[t0] \t\n" "swc1 %[out1], 7*4(%[tmp]) \t\n" "swc1 %[out2], 17*4(%[tmp]) \t\n" - "mul.s %[t2], %[t2], %[c3] \t\n" - "mul.s %[t1], %[t1], %[c4] \t\n" + "mul.s %[t2], %[t2], %[f3] \t\n" + "mul.s %[t1], %[t1], %[f4] \t\n" "add.s %[out1], %[t3], %[t0] \t\n" "lwc1 %[in1], 11*4(%[in]) \t\n" "lwc1 %[in2], 15*4(%[in]) \t\n" @@ -978,14 +978,14 @@ "add.s %[t2], %[in1], %[in3] \t\n" "sub.s %[t3], %[in1], %[in2] \t\n" "swc1 %[out2], 15*4(%[tmp]) \t\n" - "mul.s %[t0], %[in4], %[c8] \t\n" + "mul.s %[t0], %[in4], %[f8] \t\n" "sub.s %[out3], %[out3], %[in3] \t\n" - "mul.s %[t2], %[t2], %[c6] \t\n" - "mul.s %[t3], %[t3], %[c7] \t\n" + "mul.s %[t2], %[t2], %[f6] \t\n" + "mul.s %[t3], %[t3], %[f7] \t\n" "add.s %[t1], %[in2], %[in3] \t\n" - "mul.s %[out3], %[out3], %[c5] \t\n" + "mul.s %[out3], %[out3], %[f5] \t\n" "add.s %[out1], %[t2], %[t3] \t\n" - "mul.s %[t1], %[t1], %[c9] \t\n" + "mul.s %[t1], %[t1], %[f9] \t\n" "swc1 %[out3], 5*4(%[tmp]) \t\n" "add.s %[out1], %[out1], %[t0] \t\n" "add.s %[out2], %[t2], %[t1] \t\n" @@ -1000,26 +1000,29 @@ [t2] "=&f" (t2), [t3] "=&f" (t3), [in1] "=&f" (in1), [in2] "=&f" (in2), [in3] "=&f" (in3), [in4] "=&f" (in4), - [in5] "=&f" (in5), - [out1] "=&f" (out1), [out2] "=&f" (out2), - [out3] "=&f" (out3), - [c1] "=&f" (c1), [c2] "=&f" (c2), - [c3] "=&f" (c3), [c4] "=&f" (c4), - [c5] "=&f" (c5), [c6] "=&f" (c6), - [c7] "=&f" (c7), [c8] "=&f" (c8), - [c9] "=&f" (c9) - : [in] "r" (in), [tmp] "r" (tmp) + [in5] "=&f" (in5), [out1] "=&f" (out1), + [out2] "=&f" (out2), [out3] "=&f" (out3) + : [in] "r" (in), [tmp] "r" (tmp), [f1]"f"(f1), [f2]"f"(f2), + [f3]"f"(f3), [f4]"f"(f4), [f5]"f"(f5), [f6]"f"(f6), + [f7]"f"(f7), [f8]"f"(f8), [f9]"f"(f9) : "memory" ); /* loop 4 */ + f1 = 0.50190991877167369479; + f2 = 5.73685662283492756461; + f3 = 0.51763809020504152469; + f4 = 1.93185165257813657349; + f5 = 0.55168895948124587824; + f6 = 1.18310079157624925896; + f7 = 0.61038729438072803416; + f8 = 0.87172339781054900991; + f9 = 0.70710678118654752439; __asm__ volatile ( "lwc1 %[in1], 2*4(%[tmp]) \t\n" "lwc1 %[in2], 0(%[tmp]) \t\n" "lwc1 %[in3], 3*4(%[tmp]) \t\n" "lwc1 %[in4], 1*4(%[tmp]) \t\n" - "li.s %[c1], 0.50190991877167369479 \t\n" - "li.s %[c2], 5.73685662283492756461 \t\n" "add.s %[s0], %[in1], %[in2] \t\n" "sub.s %[s2], %[in1], %[in2] \t\n" "add.s %[s1], %[in3], %[in4] \t\n" @@ -1027,15 +1030,13 @@ "lwc1 %[in1], 9*4(%[win]) \t\n" "lwc1 %[in2], 4*9*4(%[buf]) \t\n" "lwc1 %[in3], 8*4(%[win]) \t\n" - "mul.s %[s1], %[s1], %[c1] \t\n" - "mul.s %[s3], %[s3], %[c2] \t\n" + "mul.s %[s1], %[s1], %[f1] \t\n" + "mul.s %[s3], %[s3], %[f2] \t\n" "lwc1 %[in4], 4*8*4(%[buf]) \t\n" "lwc1 %[in5], 29*4(%[win]) \t\n" "lwc1 %[in6], 28*4(%[win]) \t\n" "add.s %[t0], %[s0], %[s1] \t\n" "sub.s %[t1], %[s0], %[s1] \t\n" - "li.s %[c1], 0.51763809020504152469 \t\n" - "li.s %[c2], 1.93185165257813657349 \t\n" "mul.s %[out3], %[in5], %[t0] \t\n" "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" @@ -1071,14 +1072,13 @@ "lwc1 %[in1], 10*4(%[win]) \t\n" "lwc1 %[in2], 4*10*4(%[buf]) \t\n" "lwc1 %[in3], 7*4(%[win]) \t\n" - "mul.s %[s1], %[s1], %[c1] \t\n" - "mul.s %[s3], %[s3], %[c2] \t\n" + "mul.s %[s1], %[s1], %[f3] \t\n" + "mul.s %[s3], %[s3], %[f4] \t\n" "add.s %[t0], %[s0], %[s1] \t\n" "sub.s %[t1], %[s0], %[s1] \t\n" "lwc1 %[in4], 4*7*4(%[buf]) \t\n" "lwc1 %[in5], 30*4(%[win]) \t\n" "lwc1 %[in6], 27*4(%[win]) \t\n" - "li.s %[c1], 0.55168895948124587824 \t\n" "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" "mul.s %[out3], %[t0], %[in5] \t\n" @@ -1105,7 +1105,6 @@ "swc1 %[out2], 32*4(%[out]) \t\n" "swc1 %[out3], 4*16*4(%[buf]) \t\n" "swc1 %[out4], 4*1*4(%[buf]) \t\n" - "li.s %[c2], 1.18310079157624925896 \t\n" "add.s %[s0], %[in1], %[in2] \t\n" "sub.s %[s2], %[in1], %[in2] \t\n" "lwc1 %[in3], 11*4(%[tmp]) \t\n" @@ -1115,8 +1114,8 @@ "lwc1 %[in1], 11*4(%[win]) \t\n" "lwc1 %[in2], 4*11*4(%[buf]) \t\n" "lwc1 %[in3], 6*4(%[win]) \t\n" - "mul.s %[s1], %[s1], %[c1] \t\n" - "mul.s %[s3], %[s3], %[c2] \t\n" + "mul.s %[s1], %[s1], %[f5] \t\n" + "mul.s %[s3], %[s3], %[f6] \t\n" "lwc1 %[in4], 4*6*4(%[buf]) \t\n" "lwc1 %[in5], 31*4(%[win]) \t\n" "lwc1 %[in6], 26*4(%[win]) \t\n" @@ -1152,15 +1151,13 @@ "add.s %[s0], %[in1], %[in2] \t\n" "sub.s %[s2], %[in1], %[in2] \t\n" "lwc1 %[in4], 13*4(%[tmp]) \t\n" - "li.s %[c1], 0.61038729438072803416 \t\n" - "li.s %[c2], 0.87172339781054900991 \t\n" "add.s %[s1], %[in3], %[in4] \t\n" "sub.s %[s3], %[in3], %[in4] \t\n" "lwc1 %[in1], 12*4(%[win]) \t\n" "lwc1 %[in2], 4*12*4(%[buf]) \t\n" "lwc1 %[in3], 5*4(%[win]) \t\n" - "mul.s %[s1], %[s1], %[c1] \t\n" - "mul.s %[s3], %[s3], %[c2] \t\n" + "mul.s %[s1], %[s1], %[f7] \t\n" + "mul.s %[s3], %[s3], %[f8] \t\n" "lwc1 %[in4], 4*5*4(%[buf]) \t\n" "lwc1 %[in5], 32*4(%[win]) \t\n" "lwc1 %[in6], 25*4(%[win]) \t\n" @@ -1168,7 +1165,6 @@ "sub.s %[t1], %[s0], %[s1] \t\n" "lwc1 %[s0], 16*4(%[tmp]) \t\n" "lwc1 %[s1], 17*4(%[tmp]) \t\n" - "li.s %[c1], 0.70710678118654752439 \t\n" "mul.s %[out3], %[t0], %[in5] \t\n" "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" @@ -1186,7 +1182,7 @@ "lwc1 %[in5], 34*4(%[win]) \t\n" "lwc1 %[in6], 23*4(%[win]) \t\n" "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" - "mul.s %[s1], %[s1], %[c1] \t\n" + "mul.s %[s1], %[s1], %[f9] \t\n" "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" "mul.s %[out3], %[in5], %[t0] \t\n" "mul.s %[out4], %[in6], %[t0] \t\n" @@ -1211,18 +1207,18 @@ "swc1 %[out3], 4*13*4(%[buf]) \t\n" "swc1 %[out4], 4*4*4(%[buf]) \t\n" - : [c1] "=&f" (c1), [c2] "=&f" (c2), - [in1] "=&f" (in1), [in2] "=&f" (in2), + : [in1] "=&f" (in1), [in2] "=&f" (in2), [in3] "=&f" (in3), [in4] "=&f" (in4), [in5] "=&f" (in5), [in6] "=&f" (in6), [out1] "=&f" (out1), [out2] "=&f" (out2), [out3] "=&f" (out3), [out4] "=&f" (out4), [t0] "=&f" (t0), [t1] "=&f" (t1), - [t2] "=&f" (t2), [t3] "=&f" (t3), [s0] "=&f" (s0), [s1] "=&f" (s1), [s2] "=&f" (s2), [s3] "=&f" (s3) : [tmp] "r" (tmp), [win] "r" (win), - [buf] "r" (buf), [out] "r" (out) + [buf] "r" (buf), [out] "r" (out), + [f1]"f"(f1), [f2]"f"(f2), [f3]"f"(f3), [f4]"f"(f4), + [f5]"f"(f5), [f6]"f"(f6), [f7]"f"(f7), [f8]"f"(f8), [f9]"f"(f9) : "memory" ); } diff -Nru ffmpeg-4.2.2/libavcodec/mips/mpegvideoencdsp_init_mips.c ffmpeg-4.4/libavcodec/mips/mpegvideoencdsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/mpegvideoencdsp_init_mips.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/mpegvideoencdsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,23 +18,18 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "libavcodec/bit_depth_template.c" #include "h263dsp_mips.h" -#if HAVE_MSA -static av_cold void mpegvideoencdsp_init_msa(MpegvideoEncDSPContext *c, - AVCodecContext *avctx) -{ -#if BIT_DEPTH == 8 - c->pix_sum = ff_pix_sum_msa; -#endif -} -#endif // #if HAVE_MSA - av_cold void ff_mpegvideoencdsp_init_mips(MpegvideoEncDSPContext *c, AVCodecContext *avctx) { -#if HAVE_MSA - mpegvideoencdsp_init_msa(c, avctx); -#endif // #if HAVE_MSA + int cpu_flags = av_get_cpu_flags(); + + if (have_msa(cpu_flags)) { +#if BIT_DEPTH == 8 + c->pix_sum = ff_pix_sum_msa; +#endif + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/mpegvideo_init_mips.c ffmpeg-4.4/libavcodec/mips/mpegvideo_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/mpegvideo_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/mpegvideo_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,41 +18,31 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "h263dsp_mips.h" #include "mpegvideo_mips.h" -#if HAVE_MSA -static av_cold void dct_unquantize_init_msa(MpegEncContext *s) -{ - s->dct_unquantize_h263_intra = ff_dct_unquantize_h263_intra_msa; - s->dct_unquantize_h263_inter = ff_dct_unquantize_h263_inter_msa; - if (!s->q_scale_type) - s->dct_unquantize_mpeg2_inter = ff_dct_unquantize_mpeg2_inter_msa; -} -#endif // #if HAVE_MSA - -#if HAVE_MMI -static av_cold void dct_unquantize_init_mmi(MpegEncContext *s) +av_cold void ff_mpv_common_init_mips(MpegEncContext *s) { - s->dct_unquantize_h263_intra = ff_dct_unquantize_h263_intra_mmi; - s->dct_unquantize_h263_inter = ff_dct_unquantize_h263_inter_mmi; - s->dct_unquantize_mpeg1_intra = ff_dct_unquantize_mpeg1_intra_mmi; - s->dct_unquantize_mpeg1_inter = ff_dct_unquantize_mpeg1_inter_mmi; + int cpu_flags = av_get_cpu_flags(); - if (!(s->avctx->flags & AV_CODEC_FLAG_BITEXACT)) + if (have_mmi(cpu_flags)) { + s->dct_unquantize_h263_intra = ff_dct_unquantize_h263_intra_mmi; + s->dct_unquantize_h263_inter = ff_dct_unquantize_h263_inter_mmi; + s->dct_unquantize_mpeg1_intra = ff_dct_unquantize_mpeg1_intra_mmi; + s->dct_unquantize_mpeg1_inter = ff_dct_unquantize_mpeg1_inter_mmi; + + if (!(s->avctx->flags & AV_CODEC_FLAG_BITEXACT)) + if (!s->q_scale_type) + s->dct_unquantize_mpeg2_intra = ff_dct_unquantize_mpeg2_intra_mmi; + + s->denoise_dct= ff_denoise_dct_mmi; + } + + if (have_msa(cpu_flags)) { + s->dct_unquantize_h263_intra = ff_dct_unquantize_h263_intra_msa; + s->dct_unquantize_h263_inter = ff_dct_unquantize_h263_inter_msa; if (!s->q_scale_type) - s->dct_unquantize_mpeg2_intra = ff_dct_unquantize_mpeg2_intra_mmi; - - s->denoise_dct= ff_denoise_dct_mmi; -} -#endif /* HAVE_MMI */ - -av_cold void ff_mpv_common_init_mips(MpegEncContext *s) -{ -#if HAVE_MMI - dct_unquantize_init_mmi(s); -#endif /* HAVE_MMI */ -#if HAVE_MSA - dct_unquantize_init_msa(s); -#endif // #if HAVE_MSA + s->dct_unquantize_mpeg2_inter = ff_dct_unquantize_mpeg2_inter_msa; + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/pixblockdsp_init_mips.c ffmpeg-4.4/libavcodec/mips/pixblockdsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/pixblockdsp_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/pixblockdsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,51 +19,38 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "pixblockdsp_mips.h" -#if HAVE_MSA -static av_cold void pixblockdsp_init_msa(PixblockDSPContext *c, - AVCodecContext *avctx, - unsigned high_bit_depth) +void ff_pixblockdsp_init_mips(PixblockDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) { - c->diff_pixels = ff_diff_pixels_msa; + int cpu_flags = av_get_cpu_flags(); + + if (have_mmi(cpu_flags)) { + c->diff_pixels = ff_diff_pixels_mmi; - switch (avctx->bits_per_raw_sample) { - case 9: - case 10: - case 12: - case 14: - c->get_pixels = ff_get_pixels_16_msa; - break; - default: - if (avctx->bits_per_raw_sample <= 8 || avctx->codec_type != - AVMEDIA_TYPE_VIDEO) { - c->get_pixels = ff_get_pixels_8_msa; + if (!high_bit_depth || avctx->codec_type != AVMEDIA_TYPE_VIDEO) { + c->get_pixels = ff_get_pixels_8_mmi; } - break; } -} -#endif // #if HAVE_MSA -#if HAVE_MMI -static av_cold void pixblockdsp_init_mmi(PixblockDSPContext *c, - AVCodecContext *avctx, unsigned high_bit_depth) -{ - c->diff_pixels = ff_diff_pixels_mmi; + if (have_msa(cpu_flags)) { + c->diff_pixels = ff_diff_pixels_msa; - if (!high_bit_depth || avctx->codec_type != AVMEDIA_TYPE_VIDEO) { - c->get_pixels = ff_get_pixels_8_mmi; + switch (avctx->bits_per_raw_sample) { + case 9: + case 10: + case 12: + case 14: + c->get_pixels = ff_get_pixels_16_msa; + break; + default: + if (avctx->bits_per_raw_sample <= 8 || avctx->codec_type != + AVMEDIA_TYPE_VIDEO) { + c->get_pixels = ff_get_pixels_8_msa; + } + break; + } } } -#endif /* HAVE_MMI */ - -void ff_pixblockdsp_init_mips(PixblockDSPContext *c, AVCodecContext *avctx, - unsigned high_bit_depth) -{ -#if HAVE_MMI - pixblockdsp_init_mmi(c, avctx, high_bit_depth); -#endif /* HAVE_MMI */ -#if HAVE_MSA - pixblockdsp_init_msa(c, avctx, high_bit_depth); -#endif // #if HAVE_MSA -} diff -Nru ffmpeg-4.2.2/libavcodec/mips/qpeldsp_init_mips.c ffmpeg-4.4/libavcodec/mips/qpeldsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/qpeldsp_init_mips.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/qpeldsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,150 +18,146 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "qpeldsp_mips.h" -#if HAVE_MSA -static av_cold void qpeldsp_init_msa(QpelDSPContext *c) -{ - c->put_qpel_pixels_tab[0][0] = ff_copy_16x16_msa; - c->put_qpel_pixels_tab[0][1] = ff_horiz_mc_qpel_aver_src0_16width_msa; - c->put_qpel_pixels_tab[0][2] = ff_horiz_mc_qpel_16width_msa; - c->put_qpel_pixels_tab[0][3] = ff_horiz_mc_qpel_aver_src1_16width_msa; - c->put_qpel_pixels_tab[0][4] = ff_vert_mc_qpel_aver_src0_16x16_msa; - c->put_qpel_pixels_tab[0][5] = ff_hv_mc_qpel_aver_hv_src00_16x16_msa; - c->put_qpel_pixels_tab[0][6] = ff_hv_mc_qpel_aver_v_src0_16x16_msa; - c->put_qpel_pixels_tab[0][7] = ff_hv_mc_qpel_aver_hv_src10_16x16_msa; - c->put_qpel_pixels_tab[0][8] = ff_vert_mc_qpel_16x16_msa; - c->put_qpel_pixels_tab[0][9] = ff_hv_mc_qpel_aver_h_src0_16x16_msa; - c->put_qpel_pixels_tab[0][10] = ff_hv_mc_qpel_16x16_msa; - c->put_qpel_pixels_tab[0][11] = ff_hv_mc_qpel_aver_h_src1_16x16_msa; - c->put_qpel_pixels_tab[0][12] = ff_vert_mc_qpel_aver_src1_16x16_msa; - c->put_qpel_pixels_tab[0][13] = ff_hv_mc_qpel_aver_hv_src01_16x16_msa; - c->put_qpel_pixels_tab[0][14] = ff_hv_mc_qpel_aver_v_src1_16x16_msa; - c->put_qpel_pixels_tab[0][15] = ff_hv_mc_qpel_aver_hv_src11_16x16_msa; - - c->put_qpel_pixels_tab[1][0] = ff_copy_8x8_msa; - c->put_qpel_pixels_tab[1][1] = ff_horiz_mc_qpel_aver_src0_8width_msa; - c->put_qpel_pixels_tab[1][2] = ff_horiz_mc_qpel_8width_msa; - c->put_qpel_pixels_tab[1][3] = ff_horiz_mc_qpel_aver_src1_8width_msa; - c->put_qpel_pixels_tab[1][4] = ff_vert_mc_qpel_aver_src0_8x8_msa; - c->put_qpel_pixels_tab[1][5] = ff_hv_mc_qpel_aver_hv_src00_8x8_msa; - c->put_qpel_pixels_tab[1][6] = ff_hv_mc_qpel_aver_v_src0_8x8_msa; - c->put_qpel_pixels_tab[1][7] = ff_hv_mc_qpel_aver_hv_src10_8x8_msa; - c->put_qpel_pixels_tab[1][8] = ff_vert_mc_qpel_8x8_msa; - c->put_qpel_pixels_tab[1][9] = ff_hv_mc_qpel_aver_h_src0_8x8_msa; - c->put_qpel_pixels_tab[1][10] = ff_hv_mc_qpel_8x8_msa; - c->put_qpel_pixels_tab[1][11] = ff_hv_mc_qpel_aver_h_src1_8x8_msa; - c->put_qpel_pixels_tab[1][12] = ff_vert_mc_qpel_aver_src1_8x8_msa; - c->put_qpel_pixels_tab[1][13] = ff_hv_mc_qpel_aver_hv_src01_8x8_msa; - c->put_qpel_pixels_tab[1][14] = ff_hv_mc_qpel_aver_v_src1_8x8_msa; - c->put_qpel_pixels_tab[1][15] = ff_hv_mc_qpel_aver_hv_src11_8x8_msa; - - c->put_no_rnd_qpel_pixels_tab[0][0] = ff_copy_16x16_msa; - c->put_no_rnd_qpel_pixels_tab[0][1] = - ff_horiz_mc_qpel_no_rnd_aver_src0_16width_msa; - c->put_no_rnd_qpel_pixels_tab[0][2] = ff_horiz_mc_qpel_no_rnd_16width_msa; - c->put_no_rnd_qpel_pixels_tab[0][3] = - ff_horiz_mc_qpel_no_rnd_aver_src1_16width_msa; - c->put_no_rnd_qpel_pixels_tab[0][4] = - ff_vert_mc_qpel_no_rnd_aver_src0_16x16_msa; - c->put_no_rnd_qpel_pixels_tab[0][5] = - ff_hv_mc_qpel_no_rnd_aver_hv_src00_16x16_msa; - c->put_no_rnd_qpel_pixels_tab[0][6] = - ff_hv_mc_qpel_no_rnd_aver_v_src0_16x16_msa; - c->put_no_rnd_qpel_pixels_tab[0][7] = - ff_hv_mc_qpel_no_rnd_aver_hv_src10_16x16_msa; - c->put_no_rnd_qpel_pixels_tab[0][8] = ff_vert_mc_qpel_no_rnd_16x16_msa; - c->put_no_rnd_qpel_pixels_tab[0][9] = - ff_hv_mc_qpel_no_rnd_aver_h_src0_16x16_msa; - c->put_no_rnd_qpel_pixels_tab[0][10] = ff_hv_mc_qpel_no_rnd_16x16_msa; - c->put_no_rnd_qpel_pixels_tab[0][11] = - ff_hv_mc_qpel_no_rnd_aver_h_src1_16x16_msa; - c->put_no_rnd_qpel_pixels_tab[0][12] = - ff_vert_mc_qpel_no_rnd_aver_src1_16x16_msa; - c->put_no_rnd_qpel_pixels_tab[0][13] = - ff_hv_mc_qpel_no_rnd_aver_hv_src01_16x16_msa; - c->put_no_rnd_qpel_pixels_tab[0][14] = - ff_hv_mc_qpel_no_rnd_aver_v_src1_16x16_msa; - c->put_no_rnd_qpel_pixels_tab[0][15] = - ff_hv_mc_qpel_no_rnd_aver_hv_src11_16x16_msa; - - c->put_no_rnd_qpel_pixels_tab[1][0] = ff_copy_8x8_msa; - c->put_no_rnd_qpel_pixels_tab[1][1] = - ff_horiz_mc_qpel_no_rnd_aver_src0_8width_msa; - c->put_no_rnd_qpel_pixels_tab[1][2] = ff_horiz_mc_qpel_no_rnd_8width_msa; - c->put_no_rnd_qpel_pixels_tab[1][3] = - ff_horiz_mc_qpel_no_rnd_aver_src1_8width_msa; - c->put_no_rnd_qpel_pixels_tab[1][4] = - ff_vert_mc_qpel_no_rnd_aver_src0_8x8_msa; - c->put_no_rnd_qpel_pixels_tab[1][5] = - ff_hv_mc_qpel_no_rnd_aver_hv_src00_8x8_msa; - c->put_no_rnd_qpel_pixels_tab[1][6] = - ff_hv_mc_qpel_no_rnd_aver_v_src0_8x8_msa; - c->put_no_rnd_qpel_pixels_tab[1][7] = - ff_hv_mc_qpel_no_rnd_aver_hv_src10_8x8_msa; - c->put_no_rnd_qpel_pixels_tab[1][8] = ff_vert_mc_qpel_no_rnd_8x8_msa; - c->put_no_rnd_qpel_pixels_tab[1][9] = - ff_hv_mc_qpel_no_rnd_aver_h_src0_8x8_msa; - c->put_no_rnd_qpel_pixels_tab[1][10] = ff_hv_mc_qpel_no_rnd_8x8_msa; - c->put_no_rnd_qpel_pixels_tab[1][11] = - ff_hv_mc_qpel_no_rnd_aver_h_src1_8x8_msa; - c->put_no_rnd_qpel_pixels_tab[1][12] = - ff_vert_mc_qpel_no_rnd_aver_src1_8x8_msa; - c->put_no_rnd_qpel_pixels_tab[1][13] = - ff_hv_mc_qpel_no_rnd_aver_hv_src01_8x8_msa; - c->put_no_rnd_qpel_pixels_tab[1][14] = - ff_hv_mc_qpel_no_rnd_aver_v_src1_8x8_msa; - c->put_no_rnd_qpel_pixels_tab[1][15] = - ff_hv_mc_qpel_no_rnd_aver_hv_src11_8x8_msa; - - c->avg_qpel_pixels_tab[0][0] = ff_avg_width16_msa; - c->avg_qpel_pixels_tab[0][1] = - ff_horiz_mc_qpel_avg_dst_aver_src0_16width_msa; - c->avg_qpel_pixels_tab[0][2] = ff_horiz_mc_qpel_avg_dst_16width_msa; - c->avg_qpel_pixels_tab[0][3] = - ff_horiz_mc_qpel_avg_dst_aver_src1_16width_msa; - c->avg_qpel_pixels_tab[0][4] = ff_vert_mc_qpel_avg_dst_aver_src0_16x16_msa; - c->avg_qpel_pixels_tab[0][5] = - ff_hv_mc_qpel_avg_dst_aver_hv_src00_16x16_msa; - c->avg_qpel_pixels_tab[0][6] = ff_hv_mc_qpel_avg_dst_aver_v_src0_16x16_msa; - c->avg_qpel_pixels_tab[0][7] = - ff_hv_mc_qpel_avg_dst_aver_hv_src10_16x16_msa; - c->avg_qpel_pixels_tab[0][8] = ff_vert_mc_qpel_avg_dst_16x16_msa; - c->avg_qpel_pixels_tab[0][9] = ff_hv_mc_qpel_avg_dst_aver_h_src0_16x16_msa; - c->avg_qpel_pixels_tab[0][10] = ff_hv_mc_qpel_avg_dst_16x16_msa; - c->avg_qpel_pixels_tab[0][11] = ff_hv_mc_qpel_avg_dst_aver_h_src1_16x16_msa; - c->avg_qpel_pixels_tab[0][12] = ff_vert_mc_qpel_avg_dst_aver_src1_16x16_msa; - c->avg_qpel_pixels_tab[0][13] = - ff_hv_mc_qpel_avg_dst_aver_hv_src01_16x16_msa; - c->avg_qpel_pixels_tab[0][14] = ff_hv_mc_qpel_avg_dst_aver_v_src1_16x16_msa; - c->avg_qpel_pixels_tab[0][15] = - ff_hv_mc_qpel_avg_dst_aver_hv_src11_16x16_msa; - - c->avg_qpel_pixels_tab[1][0] = ff_avg_width8_msa; - c->avg_qpel_pixels_tab[1][1] = - ff_horiz_mc_qpel_avg_dst_aver_src0_8width_msa; - c->avg_qpel_pixels_tab[1][2] = ff_horiz_mc_qpel_avg_dst_8width_msa; - c->avg_qpel_pixels_tab[1][3] = - ff_horiz_mc_qpel_avg_dst_aver_src1_8width_msa; - c->avg_qpel_pixels_tab[1][4] = ff_vert_mc_qpel_avg_dst_aver_src0_8x8_msa; - c->avg_qpel_pixels_tab[1][5] = ff_hv_mc_qpel_avg_dst_aver_hv_src00_8x8_msa; - c->avg_qpel_pixels_tab[1][6] = ff_hv_mc_qpel_avg_dst_aver_v_src0_8x8_msa; - c->avg_qpel_pixels_tab[1][7] = ff_hv_mc_qpel_avg_dst_aver_hv_src10_8x8_msa; - c->avg_qpel_pixels_tab[1][8] = ff_vert_mc_qpel_avg_dst_8x8_msa; - c->avg_qpel_pixels_tab[1][9] = ff_hv_mc_qpel_avg_dst_aver_h_src0_8x8_msa; - c->avg_qpel_pixels_tab[1][10] = ff_hv_mc_qpel_avg_dst_8x8_msa; - c->avg_qpel_pixels_tab[1][11] = ff_hv_mc_qpel_avg_dst_aver_h_src1_8x8_msa; - c->avg_qpel_pixels_tab[1][12] = ff_vert_mc_qpel_avg_dst_aver_src1_8x8_msa; - c->avg_qpel_pixels_tab[1][13] = ff_hv_mc_qpel_avg_dst_aver_hv_src01_8x8_msa; - c->avg_qpel_pixels_tab[1][14] = ff_hv_mc_qpel_avg_dst_aver_v_src1_8x8_msa; - c->avg_qpel_pixels_tab[1][15] = ff_hv_mc_qpel_avg_dst_aver_hv_src11_8x8_msa; -} -#endif // #if HAVE_MSA - void ff_qpeldsp_init_mips(QpelDSPContext *c) { -#if HAVE_MSA - qpeldsp_init_msa(c); -#endif // #if HAVE_MSA + int cpu_flags = av_get_cpu_flags(); + + if (have_msa(cpu_flags)) { + c->put_qpel_pixels_tab[0][0] = ff_copy_16x16_msa; + c->put_qpel_pixels_tab[0][1] = ff_horiz_mc_qpel_aver_src0_16width_msa; + c->put_qpel_pixels_tab[0][2] = ff_horiz_mc_qpel_16width_msa; + c->put_qpel_pixels_tab[0][3] = ff_horiz_mc_qpel_aver_src1_16width_msa; + c->put_qpel_pixels_tab[0][4] = ff_vert_mc_qpel_aver_src0_16x16_msa; + c->put_qpel_pixels_tab[0][5] = ff_hv_mc_qpel_aver_hv_src00_16x16_msa; + c->put_qpel_pixels_tab[0][6] = ff_hv_mc_qpel_aver_v_src0_16x16_msa; + c->put_qpel_pixels_tab[0][7] = ff_hv_mc_qpel_aver_hv_src10_16x16_msa; + c->put_qpel_pixels_tab[0][8] = ff_vert_mc_qpel_16x16_msa; + c->put_qpel_pixels_tab[0][9] = ff_hv_mc_qpel_aver_h_src0_16x16_msa; + c->put_qpel_pixels_tab[0][10] = ff_hv_mc_qpel_16x16_msa; + c->put_qpel_pixels_tab[0][11] = ff_hv_mc_qpel_aver_h_src1_16x16_msa; + c->put_qpel_pixels_tab[0][12] = ff_vert_mc_qpel_aver_src1_16x16_msa; + c->put_qpel_pixels_tab[0][13] = ff_hv_mc_qpel_aver_hv_src01_16x16_msa; + c->put_qpel_pixels_tab[0][14] = ff_hv_mc_qpel_aver_v_src1_16x16_msa; + c->put_qpel_pixels_tab[0][15] = ff_hv_mc_qpel_aver_hv_src11_16x16_msa; + + c->put_qpel_pixels_tab[1][0] = ff_copy_8x8_msa; + c->put_qpel_pixels_tab[1][1] = ff_horiz_mc_qpel_aver_src0_8width_msa; + c->put_qpel_pixels_tab[1][2] = ff_horiz_mc_qpel_8width_msa; + c->put_qpel_pixels_tab[1][3] = ff_horiz_mc_qpel_aver_src1_8width_msa; + c->put_qpel_pixels_tab[1][4] = ff_vert_mc_qpel_aver_src0_8x8_msa; + c->put_qpel_pixels_tab[1][5] = ff_hv_mc_qpel_aver_hv_src00_8x8_msa; + c->put_qpel_pixels_tab[1][6] = ff_hv_mc_qpel_aver_v_src0_8x8_msa; + c->put_qpel_pixels_tab[1][7] = ff_hv_mc_qpel_aver_hv_src10_8x8_msa; + c->put_qpel_pixels_tab[1][8] = ff_vert_mc_qpel_8x8_msa; + c->put_qpel_pixels_tab[1][9] = ff_hv_mc_qpel_aver_h_src0_8x8_msa; + c->put_qpel_pixels_tab[1][10] = ff_hv_mc_qpel_8x8_msa; + c->put_qpel_pixels_tab[1][11] = ff_hv_mc_qpel_aver_h_src1_8x8_msa; + c->put_qpel_pixels_tab[1][12] = ff_vert_mc_qpel_aver_src1_8x8_msa; + c->put_qpel_pixels_tab[1][13] = ff_hv_mc_qpel_aver_hv_src01_8x8_msa; + c->put_qpel_pixels_tab[1][14] = ff_hv_mc_qpel_aver_v_src1_8x8_msa; + c->put_qpel_pixels_tab[1][15] = ff_hv_mc_qpel_aver_hv_src11_8x8_msa; + + c->put_no_rnd_qpel_pixels_tab[0][0] = ff_copy_16x16_msa; + c->put_no_rnd_qpel_pixels_tab[0][1] = + ff_horiz_mc_qpel_no_rnd_aver_src0_16width_msa; + c->put_no_rnd_qpel_pixels_tab[0][2] = ff_horiz_mc_qpel_no_rnd_16width_msa; + c->put_no_rnd_qpel_pixels_tab[0][3] = + ff_horiz_mc_qpel_no_rnd_aver_src1_16width_msa; + c->put_no_rnd_qpel_pixels_tab[0][4] = + ff_vert_mc_qpel_no_rnd_aver_src0_16x16_msa; + c->put_no_rnd_qpel_pixels_tab[0][5] = + ff_hv_mc_qpel_no_rnd_aver_hv_src00_16x16_msa; + c->put_no_rnd_qpel_pixels_tab[0][6] = + ff_hv_mc_qpel_no_rnd_aver_v_src0_16x16_msa; + c->put_no_rnd_qpel_pixels_tab[0][7] = + ff_hv_mc_qpel_no_rnd_aver_hv_src10_16x16_msa; + c->put_no_rnd_qpel_pixels_tab[0][8] = ff_vert_mc_qpel_no_rnd_16x16_msa; + c->put_no_rnd_qpel_pixels_tab[0][9] = + ff_hv_mc_qpel_no_rnd_aver_h_src0_16x16_msa; + c->put_no_rnd_qpel_pixels_tab[0][10] = ff_hv_mc_qpel_no_rnd_16x16_msa; + c->put_no_rnd_qpel_pixels_tab[0][11] = + ff_hv_mc_qpel_no_rnd_aver_h_src1_16x16_msa; + c->put_no_rnd_qpel_pixels_tab[0][12] = + ff_vert_mc_qpel_no_rnd_aver_src1_16x16_msa; + c->put_no_rnd_qpel_pixels_tab[0][13] = + ff_hv_mc_qpel_no_rnd_aver_hv_src01_16x16_msa; + c->put_no_rnd_qpel_pixels_tab[0][14] = + ff_hv_mc_qpel_no_rnd_aver_v_src1_16x16_msa; + c->put_no_rnd_qpel_pixels_tab[0][15] = + ff_hv_mc_qpel_no_rnd_aver_hv_src11_16x16_msa; + + c->put_no_rnd_qpel_pixels_tab[1][0] = ff_copy_8x8_msa; + c->put_no_rnd_qpel_pixels_tab[1][1] = + ff_horiz_mc_qpel_no_rnd_aver_src0_8width_msa; + c->put_no_rnd_qpel_pixels_tab[1][2] = ff_horiz_mc_qpel_no_rnd_8width_msa; + c->put_no_rnd_qpel_pixels_tab[1][3] = + ff_horiz_mc_qpel_no_rnd_aver_src1_8width_msa; + c->put_no_rnd_qpel_pixels_tab[1][4] = + ff_vert_mc_qpel_no_rnd_aver_src0_8x8_msa; + c->put_no_rnd_qpel_pixels_tab[1][5] = + ff_hv_mc_qpel_no_rnd_aver_hv_src00_8x8_msa; + c->put_no_rnd_qpel_pixels_tab[1][6] = + ff_hv_mc_qpel_no_rnd_aver_v_src0_8x8_msa; + c->put_no_rnd_qpel_pixels_tab[1][7] = + ff_hv_mc_qpel_no_rnd_aver_hv_src10_8x8_msa; + c->put_no_rnd_qpel_pixels_tab[1][8] = ff_vert_mc_qpel_no_rnd_8x8_msa; + c->put_no_rnd_qpel_pixels_tab[1][9] = + ff_hv_mc_qpel_no_rnd_aver_h_src0_8x8_msa; + c->put_no_rnd_qpel_pixels_tab[1][10] = ff_hv_mc_qpel_no_rnd_8x8_msa; + c->put_no_rnd_qpel_pixels_tab[1][11] = + ff_hv_mc_qpel_no_rnd_aver_h_src1_8x8_msa; + c->put_no_rnd_qpel_pixels_tab[1][12] = + ff_vert_mc_qpel_no_rnd_aver_src1_8x8_msa; + c->put_no_rnd_qpel_pixels_tab[1][13] = + ff_hv_mc_qpel_no_rnd_aver_hv_src01_8x8_msa; + c->put_no_rnd_qpel_pixels_tab[1][14] = + ff_hv_mc_qpel_no_rnd_aver_v_src1_8x8_msa; + c->put_no_rnd_qpel_pixels_tab[1][15] = + ff_hv_mc_qpel_no_rnd_aver_hv_src11_8x8_msa; + + c->avg_qpel_pixels_tab[0][0] = ff_avg_width16_msa; + c->avg_qpel_pixels_tab[0][1] = + ff_horiz_mc_qpel_avg_dst_aver_src0_16width_msa; + c->avg_qpel_pixels_tab[0][2] = ff_horiz_mc_qpel_avg_dst_16width_msa; + c->avg_qpel_pixels_tab[0][3] = + ff_horiz_mc_qpel_avg_dst_aver_src1_16width_msa; + c->avg_qpel_pixels_tab[0][4] = ff_vert_mc_qpel_avg_dst_aver_src0_16x16_msa; + c->avg_qpel_pixels_tab[0][5] = + ff_hv_mc_qpel_avg_dst_aver_hv_src00_16x16_msa; + c->avg_qpel_pixels_tab[0][6] = ff_hv_mc_qpel_avg_dst_aver_v_src0_16x16_msa; + c->avg_qpel_pixels_tab[0][7] = + ff_hv_mc_qpel_avg_dst_aver_hv_src10_16x16_msa; + c->avg_qpel_pixels_tab[0][8] = ff_vert_mc_qpel_avg_dst_16x16_msa; + c->avg_qpel_pixels_tab[0][9] = ff_hv_mc_qpel_avg_dst_aver_h_src0_16x16_msa; + c->avg_qpel_pixels_tab[0][10] = ff_hv_mc_qpel_avg_dst_16x16_msa; + c->avg_qpel_pixels_tab[0][11] = ff_hv_mc_qpel_avg_dst_aver_h_src1_16x16_msa; + c->avg_qpel_pixels_tab[0][12] = ff_vert_mc_qpel_avg_dst_aver_src1_16x16_msa; + c->avg_qpel_pixels_tab[0][13] = + ff_hv_mc_qpel_avg_dst_aver_hv_src01_16x16_msa; + c->avg_qpel_pixels_tab[0][14] = ff_hv_mc_qpel_avg_dst_aver_v_src1_16x16_msa; + c->avg_qpel_pixels_tab[0][15] = + ff_hv_mc_qpel_avg_dst_aver_hv_src11_16x16_msa; + + c->avg_qpel_pixels_tab[1][0] = ff_avg_width8_msa; + c->avg_qpel_pixels_tab[1][1] = + ff_horiz_mc_qpel_avg_dst_aver_src0_8width_msa; + c->avg_qpel_pixels_tab[1][2] = ff_horiz_mc_qpel_avg_dst_8width_msa; + c->avg_qpel_pixels_tab[1][3] = + ff_horiz_mc_qpel_avg_dst_aver_src1_8width_msa; + c->avg_qpel_pixels_tab[1][4] = ff_vert_mc_qpel_avg_dst_aver_src0_8x8_msa; + c->avg_qpel_pixels_tab[1][5] = ff_hv_mc_qpel_avg_dst_aver_hv_src00_8x8_msa; + c->avg_qpel_pixels_tab[1][6] = ff_hv_mc_qpel_avg_dst_aver_v_src0_8x8_msa; + c->avg_qpel_pixels_tab[1][7] = ff_hv_mc_qpel_avg_dst_aver_hv_src10_8x8_msa; + c->avg_qpel_pixels_tab[1][8] = ff_vert_mc_qpel_avg_dst_8x8_msa; + c->avg_qpel_pixels_tab[1][9] = ff_hv_mc_qpel_avg_dst_aver_h_src0_8x8_msa; + c->avg_qpel_pixels_tab[1][10] = ff_hv_mc_qpel_avg_dst_8x8_msa; + c->avg_qpel_pixels_tab[1][11] = ff_hv_mc_qpel_avg_dst_aver_h_src1_8x8_msa; + c->avg_qpel_pixels_tab[1][12] = ff_vert_mc_qpel_avg_dst_aver_src1_8x8_msa; + c->avg_qpel_pixels_tab[1][13] = ff_hv_mc_qpel_avg_dst_aver_hv_src01_8x8_msa; + c->avg_qpel_pixels_tab[1][14] = ff_hv_mc_qpel_avg_dst_aver_v_src1_8x8_msa; + c->avg_qpel_pixels_tab[1][15] = ff_hv_mc_qpel_avg_dst_aver_hv_src11_8x8_msa; + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/qpeldsp_msa.c ffmpeg-4.4/libavcodec/mips/qpeldsp_msa.c --- ffmpeg-4.2.2/libavcodec/mips/qpeldsp_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/qpeldsp_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -96,7 +96,7 @@ DPADD_UB2_UH(sum2_r, sum1_r, coef2, coef1, sum0_r, sum3_r); \ res0_r = (v8i16) (sum0_r - sum3_r); \ res0_r = __msa_srari_h(res0_r, 5); \ - res0_r = CLIP_SH_0_255(res0_r); \ + CLIP_SH_0_255(res0_r); \ out = (v16u8) __msa_pckev_b((v16i8) res0_r, (v16i8) res0_r); \ \ out; \ @@ -118,7 +118,7 @@ res0_r = (v8i16) (sum0_r - sum3_r); \ res0_r += 15; \ res0_r >>= 5; \ - res0_r = CLIP_SH_0_255(res0_r); \ + CLIP_SH_0_255(res0_r); \ out = (v16u8) __msa_pckev_b((v16i8) res0_r, (v16i8) res0_r); \ \ out; \ @@ -480,8 +480,8 @@ res1 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B4_UB(inp0, inp0, inp1, inp1, inp2, inp2, inp3, inp3, 1, + inp0, inp1, inp2, inp3); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); AVER_UB2_UB(inp0, res0, inp2, res1, res0, res1); @@ -710,8 +710,8 @@ res1 = APPLY_HORIZ_QPEL_NO_ROUND_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B4_UB(inp0, inp0, inp1, inp1, inp2, inp2, inp3, inp3, 1, + inp0, inp1, inp2, inp3); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); res0 = __msa_ave_u_b(inp0, res0); @@ -948,8 +948,8 @@ mask0, mask1, mask2, mask3, const20, const6, const3); LD_UB4(dst, dst_stride, dst0, dst1, dst2, dst3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B4_UB(inp0, inp0, inp1, inp1, inp2, inp2, inp3, inp3, 1, + inp0, inp1, inp2, inp3); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); dst0 = (v16u8) __msa_insve_d((v2i64) dst0, 1, (v2i64) dst1); @@ -3094,7 +3094,7 @@ res0 = APPLY_HORIZ_QPEL_NO_ROUND_FILTER_8BYTE(inp0, inp1, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); horiz0 = __msa_ave_u_b(inp0, res0); @@ -3104,7 +3104,7 @@ res1 = APPLY_HORIZ_QPEL_NO_ROUND_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); horiz2 = __msa_ave_u_b(inp2, res1); @@ -3114,7 +3114,7 @@ res0 = APPLY_HORIZ_QPEL_NO_ROUND_FILTER_8BYTE(inp0, inp1, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); horiz4 = __msa_ave_u_b(inp0, res0); @@ -3134,7 +3134,7 @@ res1 = APPLY_HORIZ_QPEL_NO_ROUND_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); horiz6 = __msa_ave_u_b(inp2, res1); @@ -3389,7 +3389,7 @@ res0 = APPLY_HORIZ_QPEL_NO_ROUND_FILTER_8BYTE(inp0, inp1, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); horiz0 = __msa_ave_u_b(inp0, res0); @@ -3399,7 +3399,7 @@ res1 = APPLY_HORIZ_QPEL_NO_ROUND_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); horiz2 = __msa_ave_u_b(inp2, res1); @@ -3409,7 +3409,7 @@ res0 = APPLY_HORIZ_QPEL_NO_ROUND_FILTER_8BYTE(inp0, inp1, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); horiz4 = __msa_ave_u_b(inp0, res0); @@ -3427,7 +3427,7 @@ res1 = APPLY_HORIZ_QPEL_NO_ROUND_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); horiz6 = __msa_ave_u_b(inp2, res1); @@ -3691,7 +3691,7 @@ res0 = APPLY_HORIZ_QPEL_NO_ROUND_FILTER_8BYTE(inp0, inp1, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); horiz0 = __msa_ave_u_b(inp0, res0); @@ -3701,7 +3701,7 @@ res1 = APPLY_HORIZ_QPEL_NO_ROUND_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); horiz2 = __msa_ave_u_b(inp2, res1); @@ -3712,7 +3712,7 @@ mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); horiz4 = __msa_ave_u_b(inp0, res0); horiz5 = (v16u8) __msa_splati_d((v2i64) horiz4, 1); @@ -3731,7 +3731,7 @@ res1 = APPLY_HORIZ_QPEL_NO_ROUND_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); horiz6 = __msa_ave_u_b(inp2, res1); @@ -4134,12 +4134,12 @@ const20, const6, const3); res1 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); horiz0 = __msa_aver_u_b(inp0, res0); horiz1 = (v16u8) __msa_splati_d((v2i64) horiz0, 1); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); horiz2 = __msa_aver_u_b(inp2, res1); @@ -4150,12 +4150,12 @@ const20, const6, const3); res1 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); horiz4 = __msa_aver_u_b(inp0, res0); horiz5 = (v16u8) __msa_splati_d((v2i64) horiz4, 1); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); horiz6 = __msa_aver_u_b(inp2, res1); @@ -4410,12 +4410,12 @@ const20, const6, const3); res1 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); horiz0 = __msa_aver_u_b(inp0, res0); horiz1 = (v16u8) __msa_splati_d((v2i64) horiz0, 1); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); horiz2 = __msa_aver_u_b(inp2, res1); @@ -4426,12 +4426,12 @@ const20, const6, const3); res1 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); horiz4 = __msa_aver_u_b(inp0, res0); horiz5 = (v16u8) __msa_splati_d((v2i64) horiz4, 1); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); horiz6 = __msa_aver_u_b(inp2, res1); @@ -4690,14 +4690,14 @@ res0 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp0, inp1, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); horiz0 = __msa_aver_u_b(inp0, res0); horiz1 = (v16u8) __msa_splati_d((v2i64) horiz0, 1); res1 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); horiz2 = __msa_aver_u_b(inp2, res1); @@ -4706,7 +4706,7 @@ src += (2 * src_stride); res0 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp0, inp1, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_insve_d((v2i64) inp0, 1, (v2i64) inp1); horiz4 = __msa_aver_u_b(inp0, res0); @@ -4725,7 +4725,7 @@ res1 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_insve_d((v2i64) inp2, 1, (v2i64) inp3); horiz6 = __msa_aver_u_b(inp2, res1); @@ -5020,7 +5020,7 @@ LD_UB2(src, src_stride, inp2, inp3); src += (2 * src_stride); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_ilvr_d((v2i64) inp1, (v2i64) inp0); horiz0 = __msa_aver_u_b(inp0, res0); @@ -5029,7 +5029,7 @@ const20, const6, const3); LD_UB2(src, src_stride, inp0, inp1); src += (2 * src_stride); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_ilvr_d((v2i64) inp3, (v2i64) inp2); horiz2 = __msa_aver_u_b(inp2, res1); @@ -5037,7 +5037,7 @@ res0 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp0, inp1, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_ilvr_d((v2i64) inp1, (v2i64) inp0); horiz4 = __msa_aver_u_b(inp0, res0); @@ -5060,7 +5060,7 @@ res1 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_ilvr_d((v2i64) inp3, (v2i64) inp2); horiz6 = __msa_aver_u_b(inp2, res1); @@ -5347,7 +5347,7 @@ const20, const6, const3); LD_UB2(src, src_stride, inp2, inp3); src += (2 * src_stride); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_ilvr_d((v2i64) inp1, (v2i64) inp0); horiz0 = __msa_aver_u_b(inp0, res0); @@ -5356,7 +5356,7 @@ const20, const6, const3); LD_UB2(src, src_stride, inp0, inp1); src += (2 * src_stride); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_ilvr_d((v2i64) inp3, (v2i64) inp2); horiz2 = __msa_aver_u_b(inp2, res1); @@ -5364,7 +5364,7 @@ res0 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp0, inp1, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_ilvr_d((v2i64) inp1, (v2i64) inp0); horiz4 = __msa_aver_u_b(inp0, res0); @@ -5385,7 +5385,7 @@ res1 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_ilvr_d((v2i64) inp3, (v2i64) inp2); horiz6 = __msa_aver_u_b(inp2, res1); @@ -5684,7 +5684,7 @@ const20, const6, const3); LD_UB2(src, src_stride, inp2, inp3); src += (2 * src_stride); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_ilvr_d((v2i64) inp1, (v2i64) inp0); horiz0 = __msa_aver_u_b(inp0, res0); @@ -5693,14 +5693,14 @@ const20, const6, const3); LD_UB2(src, src_stride, inp0, inp1); src += (2 * src_stride); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_ilvr_d((v2i64) inp3, (v2i64) inp2); horiz2 = __msa_aver_u_b(inp2, res1); horiz3 = (v16u8) __msa_splati_d((v2i64) horiz2, 1); res0 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp0, inp1, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp0, inp1, inp0, inp1, inp0, inp1, 1); + SLDI_B2_UB(inp0, inp0, inp1, inp1, 1, inp0, inp1); inp0 = (v16u8) __msa_ilvr_d((v2i64) inp1, (v2i64) inp0); horiz4 = __msa_aver_u_b(inp0, res0); @@ -5721,7 +5721,7 @@ src += (2 * src_stride); res1 = APPLY_HORIZ_QPEL_FILTER_8BYTE(inp2, inp3, mask0, mask1, mask2, mask3, const20, const6, const3); - SLDI_B2_UB(inp2, inp3, inp2, inp3, inp2, inp3, 1); + SLDI_B2_UB(inp2, inp2, inp3, inp3, 1, inp2, inp3); inp2 = (v16u8) __msa_ilvr_d((v2i64) inp3, (v2i64) inp2); horiz6 = __msa_aver_u_b(inp2, res1); diff -Nru ffmpeg-4.2.2/libavcodec/mips/sbrdsp_mips.c ffmpeg-4.4/libavcodec/mips/sbrdsp_mips.c --- ffmpeg-4.2.2/libavcodec/mips/sbrdsp_mips.c 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/sbrdsp_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -59,6 +59,7 @@ #include "libavutil/mips/asmdefs.h" #if HAVE_INLINE_ASM +#if HAVE_MIPSFPU static void sbr_qmf_pre_shuffle_mips(float *z) { int Temp1, Temp2, Temp3, Temp4, Temp5, Temp6; @@ -165,7 +166,6 @@ ); } -#if HAVE_MIPSFPU #if !HAVE_MIPS32R6 && !HAVE_MIPS64R6 static void sbr_sum64x5_mips(float *z) { @@ -796,9 +796,9 @@ const float *q_filt, int noise, int kx, int m_max) { - int m; + int m, temp0, temp1; float *ff_table; - float y0,y1, temp0, temp1, temp2, temp3, temp4, temp5; + float y0, y1, temp2, temp3, temp4, temp5; for (m = 0; m < m_max; m++) { @@ -808,14 +808,14 @@ __asm__ volatile( "lwc1 %[y0], 0(%[Y1]) \n\t" - "lwc1 %[temp1], 0(%[s_m1]) \n\t" + "lwc1 %[temp3], 0(%[s_m1]) \n\t" "addiu %[noise], %[noise], 1 \n\t" "andi %[noise], %[noise], 0x1ff \n\t" "sll %[temp0], %[noise], 3 \n\t" PTR_ADDU "%[ff_table],%[ff_sbr_noise_table],%[temp0] \n\t" - "sub.s %[y0], %[y0], %[temp1] \n\t" - "mfc1 %[temp3], %[temp1] \n\t" - "bne %[temp3], $0, 1f \n\t" + "sub.s %[y0], %[y0], %[temp3] \n\t" + "mfc1 %[temp1], %[temp3] \n\t" + "bne %[temp1], $0, 1f \n\t" "lwc1 %[y1], 4(%[Y1]) \n\t" "lwc1 %[temp2], 0(%[q_filt1]) \n\t" "lwc1 %[temp4], 0(%[ff_table]) \n\t" @@ -826,9 +826,10 @@ "1: \n\t" "swc1 %[y0], 0(%[Y1]) \n\t" - : [temp0]"=&r"(temp0), [ff_table]"=&r"(ff_table), [y0]"=&f"(y0), - [y1]"=&f"(y1), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), - [temp3]"=&r"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5) + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [y0]"=&f"(y0), + [y1]"=&f"(y1), [ff_table]"=&r"(ff_table), + [temp2]"=&f"(temp2), [temp3]"=&f"(temp3), + [temp4]"=&f"(temp4), [temp5]"=&f"(temp5) : [ff_sbr_noise_table]"r"(ff_sbr_noise_table), [noise]"r"(noise), [Y1]"r"(Y1), [s_m1]"r"(s_m1), [q_filt1]"r"(q_filt1) : "memory" @@ -890,9 +891,9 @@ void ff_sbrdsp_init_mips(SBRDSPContext *s) { #if HAVE_INLINE_ASM +#if HAVE_MIPSFPU s->qmf_pre_shuffle = sbr_qmf_pre_shuffle_mips; s->qmf_post_shuffle = sbr_qmf_post_shuffle_mips; -#if HAVE_MIPSFPU #if !HAVE_MIPS32R6 && !HAVE_MIPS64R6 s->sum64x5 = sbr_sum64x5_mips; s->sum_square = sbr_sum_square_mips; diff -Nru ffmpeg-4.2.2/libavcodec/mips/simple_idct_mmi.c ffmpeg-4.4/libavcodec/mips/simple_idct_mmi.c --- ffmpeg-4.2.2/libavcodec/mips/simple_idct_mmi.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/simple_idct_mmi.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,7 @@ #include "constants.h" #include "libavutil/mips/asmdefs.h" #include "libavutil/mips/mmiutils.h" +#include "libavutil/mem_internal.h" #define W1 22725 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 #define W2 21407 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 @@ -39,7 +40,7 @@ #define COL_SHIFT 20 #define DC_SHIFT 3 -DECLARE_ALIGNED(8, const int16_t, W_arr)[46] = { +DECLARE_ALIGNED(16, const int16_t, W_arr)[46] = { W4, W2, W4, W6, W1, W3, W5, W7, W4, W6, -W4, -W2, diff -Nru ffmpeg-4.2.2/libavcodec/mips/simple_idct_msa.c ffmpeg-4.4/libavcodec/mips/simple_idct_msa.c --- ffmpeg-4.2.2/libavcodec/mips/simple_idct_msa.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/simple_idct_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -336,35 +336,26 @@ SRA_4V(temp2_r, temp2_l, temp3_r, temp3_l, 20); SRA_4V(a3_r, a3_l, a2_r, a2_l, 20); SRA_4V(a1_r, a1_l, a0_r, a0_l, 20); - PCKEV_H4_SW(temp0_l, temp0_r, temp1_l, temp1_r, temp2_l, temp2_r, - temp3_l, temp3_r, temp0_r, temp1_r, temp2_r, temp3_r); - PCKEV_H4_SW(a0_l, a0_r, a1_l, a1_r, a2_l, a2_r, a3_l, a3_r, - a0_r, a1_r, a2_r, a3_r); - temp0_r = (v4i32) CLIP_SH_0_255(temp0_r); - temp1_r = (v4i32) CLIP_SH_0_255(temp1_r); - temp2_r = (v4i32) CLIP_SH_0_255(temp2_r); - temp3_r = (v4i32) CLIP_SH_0_255(temp3_r); - PCKEV_B4_SW(temp0_r, temp0_r, temp1_r, temp1_r, - temp2_r, temp2_r, temp3_r, temp3_r, - temp0_r, temp1_r, temp2_r, temp3_r); - tmp0 = __msa_copy_u_d((v2i64) temp0_r, 1); - tmp1 = __msa_copy_u_d((v2i64) temp1_r, 1); - tmp2 = __msa_copy_u_d((v2i64) temp2_r, 1); - tmp3 = __msa_copy_u_d((v2i64) temp3_r, 1); - SD4(tmp0, tmp1, tmp2, tmp3, dst, dst_stride); - dst += 4 * dst_stride; - a0_r = (v4i32) CLIP_SH_0_255(a0_r); - a1_r = (v4i32) CLIP_SH_0_255(a1_r); - a2_r = (v4i32) CLIP_SH_0_255(a2_r); - a3_r = (v4i32) CLIP_SH_0_255(a3_r); - PCKEV_B4_SW(a0_r, a0_r, a1_r, a1_r, - a2_r, a2_r, a3_r, a3_r, a0_r, a1_r, a2_r, a3_r); - tmp3 = __msa_copy_u_d((v2i64) a0_r, 1); - tmp2 = __msa_copy_u_d((v2i64) a1_r, 1); - tmp1 = __msa_copy_u_d((v2i64) a2_r, 1); - tmp0 = __msa_copy_u_d((v2i64) a3_r, 1); + PCKEV_H4_SH(temp0_l, temp0_r, temp1_l, temp1_r, temp2_l, temp2_r, + temp3_l, temp3_r, in0, in1, in2, in3); + PCKEV_H4_SH(a0_l, a0_r, a1_l, a1_r, a2_l, a2_r, a3_l, a3_r, + in4, in5, in6, in7); + CLIP_SH4_0_255(in0, in1, in2, in3); + PCKEV_B4_SH(in0, in0, in1, in1, in2, in2, in3, in3, + in0, in1, in2, in3); + tmp0 = __msa_copy_u_d((v2i64) in0, 1); + tmp1 = __msa_copy_u_d((v2i64) in1, 1); + tmp2 = __msa_copy_u_d((v2i64) in2, 1); + tmp3 = __msa_copy_u_d((v2i64) in3, 1); SD4(tmp0, tmp1, tmp2, tmp3, dst, dst_stride); - dst += 4 * dst_stride; + CLIP_SH4_0_255(in4, in5, in6, in7); + PCKEV_B4_SH(in4, in4, in5, in5, in6, in6, in7, in7, + in4, in5, in6, in7); + tmp3 = __msa_copy_u_d((v2i64) in4, 1); + tmp2 = __msa_copy_u_d((v2i64) in5, 1); + tmp1 = __msa_copy_u_d((v2i64) in6, 1); + tmp0 = __msa_copy_u_d((v2i64) in7, 1); + SD4(tmp0, tmp1, tmp2, tmp3, dst + 4 * dst_stride, dst_stride); } static void simple_idct_add_msa(uint8_t *dst, int32_t dst_stride, @@ -516,21 +507,17 @@ temp3_l, temp3_r, temp0_r, temp1_r, temp2_r, temp3_r); ILVR_B4_SW(zero, in0, zero, in1, zero, in2, zero, in3, temp0_l, temp1_l, temp2_l, temp3_l); - temp0_r = (v4i32) ((v8i16) (temp0_r) + (v8i16) (temp0_l)); - temp1_r = (v4i32) ((v8i16) (temp1_r) + (v8i16) (temp1_l)); - temp2_r = (v4i32) ((v8i16) (temp2_r) + (v8i16) (temp2_l)); - temp3_r = (v4i32) ((v8i16) (temp3_r) + (v8i16) (temp3_l)); - temp0_r = (v4i32) CLIP_SH_0_255(temp0_r); - temp1_r = (v4i32) CLIP_SH_0_255(temp1_r); - temp2_r = (v4i32) CLIP_SH_0_255(temp2_r); - temp3_r = (v4i32) CLIP_SH_0_255(temp3_r); - PCKEV_B4_SW(temp0_r, temp0_r, temp1_r, temp1_r, - temp2_r, temp2_r, temp3_r, temp3_r, - temp0_r, temp1_r, temp2_r, temp3_r); - tmp0 = __msa_copy_u_d((v2i64) temp0_r, 1); - tmp1 = __msa_copy_u_d((v2i64) temp1_r, 1); - tmp2 = __msa_copy_u_d((v2i64) temp2_r, 1); - tmp3 = __msa_copy_u_d((v2i64) temp3_r, 1); + in0 = (v8i16) (temp0_r) + (v8i16) (temp0_l); + in1 = (v8i16) (temp1_r) + (v8i16) (temp1_l); + in2 = (v8i16) (temp2_r) + (v8i16) (temp2_l); + in3 = (v8i16) (temp3_r) + (v8i16) (temp3_l); + CLIP_SH4_0_255(in0, in1, in2, in3); + PCKEV_B4_SH(in0, in0, in1, in1, in2, in2, in3, in3, + in0, in1, in2, in3); + tmp0 = __msa_copy_u_d((v2i64) in0, 1); + tmp1 = __msa_copy_u_d((v2i64) in1, 1); + tmp2 = __msa_copy_u_d((v2i64) in2, 1); + tmp3 = __msa_copy_u_d((v2i64) in3, 1); SD4(tmp0, tmp1, tmp2, tmp3, dst, dst_stride); SRA_4V(a3_r, a3_l, a2_r, a2_l, 20); @@ -540,20 +527,17 @@ a0_r, a1_r, a2_r, a3_r); ILVR_B4_SW(zero, in4, zero, in5, zero, in6, zero, in7, a3_l, a2_l, a1_l, a0_l); - a3_r = (v4i32) ((v8i16) (a3_r) + (v8i16) (a3_l)); - a2_r = (v4i32) ((v8i16) (a2_r) + (v8i16) (a2_l)); - a1_r = (v4i32) ((v8i16) (a1_r) + (v8i16) (a1_l)); - a0_r = (v4i32) ((v8i16) (a0_r) + (v8i16) (a0_l)); - a3_r = (v4i32) CLIP_SH_0_255(a3_r); - a2_r = (v4i32) CLIP_SH_0_255(a2_r); - a1_r = (v4i32) CLIP_SH_0_255(a1_r); - a0_r = (v4i32) CLIP_SH_0_255(a0_r); - PCKEV_B4_SW(a0_r, a0_r, a1_r, a1_r, - a2_r, a2_r, a3_r, a3_r, a0_r, a1_r, a2_r, a3_r); - tmp0 = __msa_copy_u_d((v2i64) a3_r, 1); - tmp1 = __msa_copy_u_d((v2i64) a2_r, 1); - tmp2 = __msa_copy_u_d((v2i64) a1_r, 1); - tmp3 = __msa_copy_u_d((v2i64) a0_r, 1); + in4 = (v8i16) (a3_r) + (v8i16) (a3_l); + in5 = (v8i16) (a2_r) + (v8i16) (a2_l); + in6 = (v8i16) (a1_r) + (v8i16) (a1_l); + in7 = (v8i16) (a0_r) + (v8i16) (a0_l); + CLIP_SH4_0_255(in4, in5, in6, in7); + PCKEV_B4_SH(in4, in4, in5, in5, in6, in6, in7, in7, + in4, in5, in6, in7); + tmp0 = __msa_copy_u_d((v2i64) in4, 1); + tmp1 = __msa_copy_u_d((v2i64) in5, 1); + tmp2 = __msa_copy_u_d((v2i64) in6, 1); + tmp3 = __msa_copy_u_d((v2i64) in7, 1); SD4(tmp0, tmp1, tmp2, tmp3, dst + 4 * dst_stride, dst_stride); } diff -Nru ffmpeg-4.2.2/libavcodec/mips/vc1dsp_init_mips.c ffmpeg-4.4/libavcodec/mips/vc1dsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/vc1dsp_init_mips.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vc1dsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,91 +18,103 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "libavutil/attributes.h" #include "libavcodec/vc1dsp.h" #include "vc1dsp_mips.h" #include "config.h" -#if HAVE_MMI -static av_cold void vc1dsp_init_mmi(VC1DSPContext *dsp) -{ -#if _MIPS_SIM != _ABIO32 - dsp->vc1_inv_trans_8x8 = ff_vc1_inv_trans_8x8_mmi; - dsp->vc1_inv_trans_4x8 = ff_vc1_inv_trans_4x8_mmi; - dsp->vc1_inv_trans_8x4 = ff_vc1_inv_trans_8x4_mmi; -#endif - dsp->vc1_inv_trans_4x4 = ff_vc1_inv_trans_4x4_mmi; - dsp->vc1_inv_trans_8x8_dc = ff_vc1_inv_trans_8x8_dc_mmi; - dsp->vc1_inv_trans_4x8_dc = ff_vc1_inv_trans_4x8_dc_mmi; - dsp->vc1_inv_trans_8x4_dc = ff_vc1_inv_trans_8x4_dc_mmi; - dsp->vc1_inv_trans_4x4_dc = ff_vc1_inv_trans_4x4_dc_mmi; - - dsp->vc1_h_overlap = ff_vc1_h_overlap_mmi; - dsp->vc1_v_overlap = ff_vc1_v_overlap_mmi; - dsp->vc1_h_s_overlap = ff_vc1_h_s_overlap_mmi; - dsp->vc1_v_s_overlap = ff_vc1_v_s_overlap_mmi; - - dsp->vc1_v_loop_filter4 = ff_vc1_v_loop_filter4_mmi; - dsp->vc1_h_loop_filter4 = ff_vc1_h_loop_filter4_mmi; - dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_mmi; - dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_mmi; - dsp->vc1_v_loop_filter16 = ff_vc1_v_loop_filter16_mmi; - dsp->vc1_h_loop_filter16 = ff_vc1_h_loop_filter16_mmi; - #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 - FN_ASSIGN(put_, 0, 0, _mmi); - FN_ASSIGN(put_, 0, 1, _mmi); - FN_ASSIGN(put_, 0, 2, _mmi); - FN_ASSIGN(put_, 0, 3, _mmi); - - FN_ASSIGN(put_, 1, 0, _mmi); - //FN_ASSIGN(put_, 1, 1, _mmi);//FIXME - //FN_ASSIGN(put_, 1, 2, _mmi);//FIXME - //FN_ASSIGN(put_, 1, 3, _mmi);//FIXME - - FN_ASSIGN(put_, 2, 0, _mmi); - //FN_ASSIGN(put_, 2, 1, _mmi);//FIXME - //FN_ASSIGN(put_, 2, 2, _mmi);//FIXME - //FN_ASSIGN(put_, 2, 3, _mmi);//FIXME - - FN_ASSIGN(put_, 3, 0, _mmi); - //FN_ASSIGN(put_, 3, 1, _mmi);//FIXME - //FN_ASSIGN(put_, 3, 2, _mmi);//FIXME - //FN_ASSIGN(put_, 3, 3, _mmi);//FIXME - - FN_ASSIGN(avg_, 0, 0, _mmi); - FN_ASSIGN(avg_, 0, 1, _mmi); - FN_ASSIGN(avg_, 0, 2, _mmi); - FN_ASSIGN(avg_, 0, 3, _mmi); - - FN_ASSIGN(avg_, 1, 0, _mmi); - //FN_ASSIGN(avg_, 1, 1, _mmi);//FIXME - //FN_ASSIGN(avg_, 1, 2, _mmi);//FIXME - //FN_ASSIGN(avg_, 1, 3, _mmi);//FIXME - - FN_ASSIGN(avg_, 2, 0, _mmi); - //FN_ASSIGN(avg_, 2, 1, _mmi);//FIXME - //FN_ASSIGN(avg_, 2, 2, _mmi);//FIXME - //FN_ASSIGN(avg_, 2, 3, _mmi);//FIXME - - FN_ASSIGN(avg_, 3, 0, _mmi); - //FN_ASSIGN(avg_, 3, 1, _mmi);//FIXME - //FN_ASSIGN(avg_, 3, 2, _mmi);//FIXME - //FN_ASSIGN(avg_, 3, 3, _mmi);//FIXME - - dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_no_rnd_vc1_chroma_mc8_mmi; - dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_no_rnd_vc1_chroma_mc8_mmi; - dsp->put_no_rnd_vc1_chroma_pixels_tab[1] = ff_put_no_rnd_vc1_chroma_mc4_mmi; - dsp->avg_no_rnd_vc1_chroma_pixels_tab[1] = ff_avg_no_rnd_vc1_chroma_mc4_mmi; -} -#endif /* HAVE_MMI */ - av_cold void ff_vc1dsp_init_mips(VC1DSPContext *dsp) { -#if HAVE_MMI - vc1dsp_init_mmi(dsp); -#endif /* HAVE_MMI */ + int cpu_flags = av_get_cpu_flags(); + + if (have_mmi(cpu_flags)) { + #if _MIPS_SIM != _ABIO32 + dsp->vc1_inv_trans_8x8 = ff_vc1_inv_trans_8x8_mmi; + dsp->vc1_inv_trans_4x8 = ff_vc1_inv_trans_4x8_mmi; + dsp->vc1_inv_trans_8x4 = ff_vc1_inv_trans_8x4_mmi; +#endif + dsp->vc1_inv_trans_4x4 = ff_vc1_inv_trans_4x4_mmi; + dsp->vc1_inv_trans_8x8_dc = ff_vc1_inv_trans_8x8_dc_mmi; + dsp->vc1_inv_trans_4x8_dc = ff_vc1_inv_trans_4x8_dc_mmi; + dsp->vc1_inv_trans_8x4_dc = ff_vc1_inv_trans_8x4_dc_mmi; + dsp->vc1_inv_trans_4x4_dc = ff_vc1_inv_trans_4x4_dc_mmi; + + dsp->vc1_h_overlap = ff_vc1_h_overlap_mmi; + dsp->vc1_v_overlap = ff_vc1_v_overlap_mmi; + dsp->vc1_h_s_overlap = ff_vc1_h_s_overlap_mmi; + dsp->vc1_v_s_overlap = ff_vc1_v_s_overlap_mmi; + + dsp->vc1_v_loop_filter4 = ff_vc1_v_loop_filter4_mmi; + dsp->vc1_h_loop_filter4 = ff_vc1_h_loop_filter4_mmi; + dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_mmi; + dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_mmi; + dsp->vc1_v_loop_filter16 = ff_vc1_v_loop_filter16_mmi; + dsp->vc1_h_loop_filter16 = ff_vc1_h_loop_filter16_mmi; + + FN_ASSIGN(put_, 0, 0, _mmi); + FN_ASSIGN(put_, 0, 1, _mmi); + FN_ASSIGN(put_, 0, 2, _mmi); + FN_ASSIGN(put_, 0, 3, _mmi); + + FN_ASSIGN(put_, 1, 0, _mmi); + //FN_ASSIGN(put_, 1, 1, _mmi);//FIXME + //FN_ASSIGN(put_, 1, 2, _mmi);//FIXME + //FN_ASSIGN(put_, 1, 3, _mmi);//FIXME + + FN_ASSIGN(put_, 2, 0, _mmi); + //FN_ASSIGN(put_, 2, 1, _mmi);//FIXME + //FN_ASSIGN(put_, 2, 2, _mmi);//FIXME + //FN_ASSIGN(put_, 2, 3, _mmi);//FIXME + + FN_ASSIGN(put_, 3, 0, _mmi); + //FN_ASSIGN(put_, 3, 1, _mmi);//FIXME + //FN_ASSIGN(put_, 3, 2, _mmi);//FIXME + //FN_ASSIGN(put_, 3, 3, _mmi);//FIXME + + FN_ASSIGN(avg_, 0, 0, _mmi); + FN_ASSIGN(avg_, 0, 1, _mmi); + FN_ASSIGN(avg_, 0, 2, _mmi); + FN_ASSIGN(avg_, 0, 3, _mmi); + + FN_ASSIGN(avg_, 1, 0, _mmi); + //FN_ASSIGN(avg_, 1, 1, _mmi);//FIXME + //FN_ASSIGN(avg_, 1, 2, _mmi);//FIXME + //FN_ASSIGN(avg_, 1, 3, _mmi);//FIXME + + FN_ASSIGN(avg_, 2, 0, _mmi); + //FN_ASSIGN(avg_, 2, 1, _mmi);//FIXME + //FN_ASSIGN(avg_, 2, 2, _mmi);//FIXME + //FN_ASSIGN(avg_, 2, 3, _mmi);//FIXME + + FN_ASSIGN(avg_, 3, 0, _mmi); + //FN_ASSIGN(avg_, 3, 1, _mmi);//FIXME + //FN_ASSIGN(avg_, 3, 2, _mmi);//FIXME + //FN_ASSIGN(avg_, 3, 3, _mmi);//FIXME + + dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_no_rnd_vc1_chroma_mc8_mmi; + dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_no_rnd_vc1_chroma_mc8_mmi; + dsp->put_no_rnd_vc1_chroma_pixels_tab[1] = ff_put_no_rnd_vc1_chroma_mc4_mmi; + dsp->avg_no_rnd_vc1_chroma_pixels_tab[1] = ff_avg_no_rnd_vc1_chroma_mc4_mmi; + } + + if (have_msa(cpu_flags)) { + dsp->vc1_inv_trans_8x8 = ff_vc1_inv_trans_8x8_msa; + dsp->vc1_inv_trans_4x8 = ff_vc1_inv_trans_4x8_msa; + dsp->vc1_inv_trans_8x4 = ff_vc1_inv_trans_8x4_msa; + + FN_ASSIGN(put_, 1, 1, _msa); + FN_ASSIGN(put_, 1, 2, _msa); + FN_ASSIGN(put_, 1, 3, _msa); + FN_ASSIGN(put_, 2, 1, _msa); + FN_ASSIGN(put_, 2, 2, _msa); + FN_ASSIGN(put_, 2, 3, _msa); + FN_ASSIGN(put_, 3, 1, _msa); + FN_ASSIGN(put_, 3, 2, _msa); + FN_ASSIGN(put_, 3, 3, _msa); + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/vc1dsp_mips.h ffmpeg-4.4/libavcodec/mips/vc1dsp_mips.h --- ffmpeg-4.2.2/libavcodec/mips/vc1dsp_mips.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vc1dsp_mips.h 2020-07-11 10:39:30.000000000 +0000 @@ -180,15 +180,38 @@ void ff_put_no_rnd_vc1_chroma_mc8_mmi(uint8_t *dst /* align 8 */, uint8_t *src /* align 1 */, - int stride, int h, int x, int y); + ptrdiff_t stride, int h, int x, int y); void ff_put_no_rnd_vc1_chroma_mc4_mmi(uint8_t *dst /* align 8 */, uint8_t *src /* align 1 */, - int stride, int h, int x, int y); + ptrdiff_t stride, int h, int x, int y); void ff_avg_no_rnd_vc1_chroma_mc8_mmi(uint8_t *dst /* align 8 */, uint8_t *src /* align 1 */, - int stride, int h, int x, int y); + ptrdiff_t stride, int h, int x, int y); void ff_avg_no_rnd_vc1_chroma_mc4_mmi(uint8_t *dst /* align 8 */, uint8_t *src /* align 1 */, - int stride, int h, int x, int y); + ptrdiff_t stride, int h, int x, int y); +void ff_vc1_inv_trans_8x8_msa(int16_t block[64]); +void ff_vc1_inv_trans_8x4_msa(uint8_t *dest, ptrdiff_t linesize, int16_t *block); +void ff_vc1_inv_trans_4x8_msa(uint8_t *dest, ptrdiff_t linesize, int16_t *block); + +#define FF_PUT_VC1_MSPEL_MC_MSA(hmode, vmode) \ +void ff_put_vc1_mspel_mc ## hmode ## vmode ## _msa(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd); \ +void ff_put_vc1_mspel_mc ## hmode ## vmode ## _16_msa(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd); + +FF_PUT_VC1_MSPEL_MC_MSA(1, 1); +FF_PUT_VC1_MSPEL_MC_MSA(1, 2); +FF_PUT_VC1_MSPEL_MC_MSA(1, 3); + +FF_PUT_VC1_MSPEL_MC_MSA(2, 1); +FF_PUT_VC1_MSPEL_MC_MSA(2, 2); +FF_PUT_VC1_MSPEL_MC_MSA(2, 3); + +FF_PUT_VC1_MSPEL_MC_MSA(3, 1); +FF_PUT_VC1_MSPEL_MC_MSA(3, 2); +FF_PUT_VC1_MSPEL_MC_MSA(3, 3); #endif /* AVCODEC_MIPS_VC1DSP_MIPS_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mips/vc1dsp_mmi.c ffmpeg-4.4/libavcodec/mips/vc1dsp_mmi.c --- ffmpeg-4.2.2/libavcodec/mips/vc1dsp_mmi.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vc1dsp_mmi.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,10 +21,13 @@ */ #include "libavutil/avassert.h" +#include "libavutil/mem_internal.h" + #include "libavcodec/vc1dsp.h" #include "constants.h" #include "vc1dsp_mips.h" #include "hpeldsp_mips.h" +#include "libavutil/mem_internal.h" #include "libavutil/mips/mmiutils.h" #define VC1_INV_TRANCS_8_TYPE1(o1, o2, r1, r2, r3, r4, c0) \ @@ -2241,7 +2244,7 @@ void ff_put_no_rnd_vc1_chroma_mc8_mmi(uint8_t *dst /* align 8 */, uint8_t *src /* align 1 */, - int stride, int h, int x, int y) + ptrdiff_t stride, int h, int x, int y) { const int A = (8 - x) * (8 - y); const int B = (x) * (8 - y); @@ -2296,7 +2299,7 @@ void ff_put_no_rnd_vc1_chroma_mc4_mmi(uint8_t *dst /* align 8 */, uint8_t *src /* align 1 */, - int stride, int h, int x, int y) + ptrdiff_t stride, int h, int x, int y) { const int A = (8 - x) * (8 - y); const int B = (x) * (8 - y); @@ -2349,7 +2352,7 @@ void ff_avg_no_rnd_vc1_chroma_mc8_mmi(uint8_t *dst /* align 8 */, uint8_t *src /* align 1 */, - int stride, int h, int x, int y) + ptrdiff_t stride, int h, int x, int y) { const int A = (8 - x) * (8 - y); const int B = (x) * (8 - y); @@ -2407,7 +2410,7 @@ void ff_avg_no_rnd_vc1_chroma_mc4_mmi(uint8_t *dst /* align 8 */, uint8_t *src /* align 1 */, - int stride, int h, int x, int y) + ptrdiff_t stride, int h, int x, int y) { const int A = (8 - x) * (8 - y); const int B = ( x) * (8 - y); diff -Nru ffmpeg-4.2.2/libavcodec/mips/vc1dsp_msa.c ffmpeg-4.4/libavcodec/mips/vc1dsp_msa.c --- ffmpeg-4.2.2/libavcodec/mips/vc1dsp_msa.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vc1dsp_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,461 @@ +/* + * Loongson SIMD optimized vc1dsp + * + * Copyright (c) 2019 Loongson Technology Corporation Limited + * gxw + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_mips.h" +#include "constants.h" +#include "libavutil/mips/generic_macros_msa.h" + +void ff_vc1_inv_trans_8x8_msa(int16_t block[64]) +{ + v8i16 in0, in1, in2, in3, in4, in5, in6, in7; + v4i32 in_r0, in_r1, in_r2, in_r3, in_r4, in_r5, in_r6, in_r7; + v4i32 in_l0, in_l1, in_l2, in_l3, in_l4, in_l5, in_l6, in_l7; + v4i32 t_r1, t_r2, t_r3, t_r4, t_r5, t_r6, t_r7, t_r8; + v4i32 t_l1, t_l2, t_l3, t_l4, t_l5, t_l6, t_l7, t_l8; + v4i32 cnst_12 = {12, 12, 12, 12}; + v4i32 cnst_4 = {4, 4, 4, 4}; + v4i32 cnst_16 = {16, 16, 16, 16}; + v4i32 cnst_6 = {6, 6, 6, 6}; + v4i32 cnst_15 = {15, 15, 15, 15}; + v4i32 cnst_9 = {9, 9, 9, 9}; + v4i32 cnst_1 = {1, 1, 1, 1}; + v4i32 cnst_64 = {64, 64, 64, 64}; + + LD_SH8(block, 8, in0, in1, in2, in3, in4, in5, in6, in7); + UNPCK_SH_SW(in0, in_r0, in_l0); + UNPCK_SH_SW(in1, in_r1, in_l1); + UNPCK_SH_SW(in2, in_r2, in_l2); + UNPCK_SH_SW(in3, in_r3, in_l3); + UNPCK_SH_SW(in4, in_r4, in_l4); + UNPCK_SH_SW(in5, in_r5, in_l5); + UNPCK_SH_SW(in6, in_r6, in_l6); + UNPCK_SH_SW(in7, in_r7, in_l7); + // First loop + t_r1 = cnst_12 * (in_r0 + in_r4) + cnst_4; + t_l1 = cnst_12 * (in_l0 + in_l4) + cnst_4; + t_r2 = cnst_12 * (in_r0 - in_r4) + cnst_4; + t_l2 = cnst_12 * (in_l0 - in_l4) + cnst_4; + t_r3 = cnst_16 * in_r2 + cnst_6 * in_r6; + t_l3 = cnst_16 * in_l2 + cnst_6 * in_l6; + t_r4 = cnst_6 * in_r2 - cnst_16 * in_r6; + t_l4 = cnst_6 * in_l2 - cnst_16 * in_l6; + + ADD4(t_r1, t_r3, t_l1, t_l3, t_r2, t_r4, t_l2, t_l4, t_r5, t_l5, t_r6, t_l6); + SUB4(t_r2, t_r4, t_l2, t_l4, t_r1, t_r3, t_l1, t_l3, t_r7, t_l7, t_r8, t_l8); + t_r1 = cnst_16 * in_r1 + cnst_15 * in_r3 + cnst_9 * in_r5 + cnst_4 * in_r7; + t_l1 = cnst_16 * in_l1 + cnst_15 * in_l3 + cnst_9 * in_l5 + cnst_4 * in_l7; + t_r2 = cnst_15 * in_r1 - cnst_4 * in_r3 - cnst_16 * in_r5 - cnst_9 * in_r7; + t_l2 = cnst_15 * in_l1 - cnst_4 * in_l3 - cnst_16 * in_l5 - cnst_9 * in_l7; + t_r3 = cnst_9 * in_r1 - cnst_16 * in_r3 + cnst_4 * in_r5 + cnst_15 * in_r7; + t_l3 = cnst_9 * in_l1 - cnst_16 * in_l3 + cnst_4 * in_l5 + cnst_15 * in_l7; + t_r4 = cnst_4 * in_r1 - cnst_9 * in_r3 + cnst_15 * in_r5 - cnst_16 * in_r7; + t_l4 = cnst_4 * in_l1 - cnst_9 * in_l3 + cnst_15 * in_l5 - cnst_16 * in_l7; + + in_r0 = (t_r5 + t_r1) >> 3; + in_l0 = (t_l5 + t_l1) >> 3; + in_r1 = (t_r6 + t_r2) >> 3; + in_l1 = (t_l6 + t_l2) >> 3; + in_r2 = (t_r7 + t_r3) >> 3; + in_l2 = (t_l7 + t_l3) >> 3; + in_r3 = (t_r8 + t_r4) >> 3; + in_l3 = (t_l8 + t_l4) >> 3; + + in_r4 = (t_r8 - t_r4) >> 3; + in_l4 = (t_l8 - t_l4) >> 3; + in_r5 = (t_r7 - t_r3) >> 3; + in_l5 = (t_l7 - t_l3) >> 3; + in_r6 = (t_r6 - t_r2) >> 3; + in_l6 = (t_l6 - t_l2) >> 3; + in_r7 = (t_r5 - t_r1) >> 3; + in_l7 = (t_l5 - t_l1) >> 3; + TRANSPOSE4x4_SW_SW(in_r0, in_r1, in_r2, in_r3, in_r0, in_r1, in_r2, in_r3); + TRANSPOSE4x4_SW_SW(in_l0, in_l1, in_l2, in_l3, in_l0, in_l1, in_l2, in_l3); + TRANSPOSE4x4_SW_SW(in_r4, in_r5, in_r6, in_r7, in_r4, in_r5, in_r6, in_r7); + TRANSPOSE4x4_SW_SW(in_l4, in_l5, in_l6, in_l7, in_l4, in_l5, in_l6, in_l7); + // Second loop + t_r1 = cnst_12 * (in_r0 + in_l0) + cnst_64; + t_l1 = cnst_12 * (in_r4 + in_l4) + cnst_64; + t_r2 = cnst_12 * (in_r0 - in_l0) + cnst_64; + t_l2 = cnst_12 * (in_r4 - in_l4) + cnst_64; + t_r3 = cnst_16 * in_r2 + cnst_6 * in_l2; + t_l3 = cnst_16 * in_r6 + cnst_6 * in_l6; + t_r4 = cnst_6 * in_r2 - cnst_16 * in_l2; + t_l4 = cnst_6 * in_r6 - cnst_16 * in_l6; + + ADD4(t_r1, t_r3, t_l1, t_l3, t_r2, t_r4, t_l2, t_l4, t_r5, t_l5, t_r6, t_l6); + SUB4(t_r2, t_r4, t_l2, t_l4, t_r1, t_r3, t_l1, t_l3, t_r7, t_l7, t_r8, t_l8); + t_r1 = cnst_16 * in_r1 + cnst_15 * in_r3 + cnst_9 * in_l1 + cnst_4 * in_l3; + t_l1 = cnst_16 * in_r5 + cnst_15 * in_r7 + cnst_9 * in_l5 + cnst_4 * in_l7; + t_r2 = cnst_15 * in_r1 - cnst_4 * in_r3 - cnst_16 * in_l1 - cnst_9 * in_l3; + t_l2 = cnst_15 * in_r5 - cnst_4 * in_r7 - cnst_16 * in_l5 - cnst_9 * in_l7; + t_r3 = cnst_9 * in_r1 - cnst_16 * in_r3 + cnst_4 * in_l1 + cnst_15 * in_l3; + t_l3 = cnst_9 * in_r5 - cnst_16 * in_r7 + cnst_4 * in_l5 + cnst_15 * in_l7; + t_r4 = cnst_4 * in_r1 - cnst_9 * in_r3 + cnst_15 * in_l1 - cnst_16 * in_l3; + t_l4 = cnst_4 * in_r5 - cnst_9 * in_r7 + cnst_15 * in_l5 - cnst_16 * in_l7; + + in_r0 = (t_r5 + t_r1) >> 7; + in_l0 = (t_l5 + t_l1) >> 7; + in_r1 = (t_r6 + t_r2) >> 7; + in_l1 = (t_l6 + t_l2) >> 7; + in_r2 = (t_r7 + t_r3) >> 7; + in_l2 = (t_l7 + t_l3) >> 7; + in_r3 = (t_r8 + t_r4) >> 7; + in_l3 = (t_l8 + t_l4) >> 7; + + in_r4 = (t_r8 - t_r4 + cnst_1) >> 7; + in_l4 = (t_l8 - t_l4 + cnst_1) >> 7; + in_r5 = (t_r7 - t_r3 + cnst_1) >> 7; + in_l5 = (t_l7 - t_l3 + cnst_1) >> 7; + in_r6 = (t_r6 - t_r2 + cnst_1) >> 7; + in_l6 = (t_l6 - t_l2 + cnst_1) >> 7; + in_r7 = (t_r5 - t_r1 + cnst_1) >> 7; + in_l7 = (t_l5 - t_l1 + cnst_1) >> 7; + PCKEV_H4_SH(in_l0, in_r0, in_l1, in_r1, in_l2, in_r2, in_l3, in_r3, + in0, in1, in2, in3); + PCKEV_H4_SH(in_l4, in_r4, in_l5, in_r5, in_l6, in_r6, in_l7, in_r7, + in4, in5, in6, in7); + ST_SH8(in0, in1, in2, in3, in4, in5, in6, in7, block, 8); +} + +void ff_vc1_inv_trans_4x8_msa(uint8_t *dest, ptrdiff_t linesize, int16_t *block) +{ + v8i16 in0, in1, in2, in3, in4, in5, in6, in7; + v4i32 in_r0, in_r1, in_r2, in_r3, in_r4, in_r5, in_r6, in_r7; + v4i32 t1, t2, t3, t4, t5, t6, t7, t8; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v16i8 zero_m = { 0 }; + v4i32 cnst_17 = {17, 17, 17, 17}; + v4i32 cnst_22 = {22, 22, 22, 22}; + v4i32 cnst_10 = {10, 10, 10, 10}; + v4i32 cnst_12 = {12, 12, 12, 12}; + v4i32 cnst_64 = {64, 64, 64, 64}; + v4i32 cnst_16 = {16, 16, 16, 16}; + v4i32 cnst_15 = {15, 15, 15, 15}; + v4i32 cnst_4 = {4, 4, 4, 4}; + v4i32 cnst_6 = {6, 6, 6, 6}; + v4i32 cnst_9 = {9, 9, 9, 9}; + v4i32 cnst_1 = {1, 1, 1, 1}; + + LD_SH8(block, 8, in0, in1, in2, in3, in4, in5, in6, in7); + UNPCK_R_SH_SW(in0, in_r0); + UNPCK_R_SH_SW(in1, in_r1); + UNPCK_R_SH_SW(in2, in_r2); + UNPCK_R_SH_SW(in3, in_r3); + UNPCK_R_SH_SW(in4, in_r4); + UNPCK_R_SH_SW(in5, in_r5); + UNPCK_R_SH_SW(in6, in_r6); + UNPCK_R_SH_SW(in7, in_r7); + // First loop + TRANSPOSE4x4_SW_SW(in_r0, in_r1, in_r2, in_r3, in_r0, in_r1, in_r2, in_r3); + TRANSPOSE4x4_SW_SW(in_r4, in_r5, in_r6, in_r7, in_r4, in_r5, in_r6, in_r7); + t1 = cnst_17 * (in_r0 + in_r2) + cnst_4; + t5 = cnst_17 * (in_r4 + in_r6) + cnst_4; + t2 = cnst_17 * (in_r0 - in_r2) + cnst_4; + t6 = cnst_17 * (in_r4 - in_r6) + cnst_4; + t3 = cnst_22 * in_r1 + cnst_10 * in_r3; + t7 = cnst_22 * in_r5 + cnst_10 * in_r7; + t4 = cnst_22 * in_r3 - cnst_10 * in_r1; + t8 = cnst_22 * in_r7 - cnst_10 * in_r5; + + in_r0 = (t1 + t3) >> 3; + in_r4 = (t5 + t7) >> 3; + in_r1 = (t2 - t4) >> 3; + in_r5 = (t6 - t8) >> 3; + in_r2 = (t2 + t4) >> 3; + in_r6 = (t6 + t8) >> 3; + in_r3 = (t1 - t3) >> 3; + in_r7 = (t5 - t7) >> 3; + TRANSPOSE4x4_SW_SW(in_r0, in_r1, in_r2, in_r3, in_r0, in_r1, in_r2, in_r3); + TRANSPOSE4x4_SW_SW(in_r4, in_r5, in_r6, in_r7, in_r4, in_r5, in_r6, in_r7); + PCKEV_H4_SH(in_r1, in_r0, in_r3, in_r2, in_r5, in_r4, in_r7, in_r6, + in0, in1, in2, in3); + ST_D8(in0, in1, in2, in3, 0, 1, 0, 1, 0, 1, 0, 1, block, 8); + // Second loop + t1 = cnst_12 * (in_r0 + in_r4) + cnst_64; + t2 = cnst_12 * (in_r0 - in_r4) + cnst_64; + t3 = cnst_16 * in_r2 + cnst_6 * in_r6; + t4 = cnst_6 * in_r2 - cnst_16 * in_r6; + t5 = t1 + t3, t6 = t2 + t4; + t7 = t2 - t4, t8 = t1 - t3; + t1 = cnst_16 * in_r1 + cnst_15 * in_r3 + cnst_9 * in_r5 + cnst_4 * in_r7; + t2 = cnst_15 * in_r1 - cnst_4 * in_r3 - cnst_16 * in_r5 - cnst_9 * in_r7; + t3 = cnst_9 * in_r1 - cnst_16 * in_r3 + cnst_4 * in_r5 + cnst_15 * in_r7; + t4 = cnst_4 * in_r1 - cnst_9 * in_r3 + cnst_15 * in_r5 - cnst_16 * in_r7; + LD_SW8(dest, linesize, dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7); + ILVR_B8_SW(zero_m, dst0, zero_m, dst1, zero_m, dst2, zero_m, dst3, + zero_m, dst4, zero_m, dst5, zero_m, dst6, zero_m, dst7, + dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7); + ILVR_H4_SW(zero_m, dst0, zero_m, dst1, zero_m, dst2, zero_m, dst3, + dst0, dst1, dst2, dst3); + ILVR_H4_SW(zero_m, dst4, zero_m, dst5, zero_m, dst6, zero_m, dst7, + dst4, dst5, dst6, dst7); + in_r0 = (t5 + t1) >> 7; + in_r1 = (t6 + t2) >> 7; + in_r2 = (t7 + t3) >> 7; + in_r3 = (t8 + t4) >> 7; + in_r4 = (t8 - t4 + cnst_1) >> 7; + in_r5 = (t7 - t3 + cnst_1) >> 7; + in_r6 = (t6 - t2 + cnst_1) >> 7; + in_r7 = (t5 - t1 + cnst_1) >> 7; + ADD4(in_r0, dst0, in_r1, dst1, in_r2, dst2, in_r3, dst3, + in_r0, in_r1, in_r2, in_r3); + ADD4(in_r4, dst4, in_r5, dst5, in_r6, dst6, in_r7, dst7, + in_r4, in_r5, in_r6, in_r7); + CLIP_SW8_0_255(in_r0, in_r1, in_r2, in_r3, in_r4, in_r5, in_r6, in_r7); + PCKEV_H4_SH(in_r1, in_r0, in_r3, in_r2, in_r5, in_r4, in_r7, in_r6, + in0, in1, in2, in3); + PCKEV_B2_SH(in1, in0, in3, in2, in0, in1); + ST_W8(in0, in1, 0, 1, 2, 3, 0, 1, 2, 3, dest, linesize); +} + +void ff_vc1_inv_trans_8x4_msa(uint8_t *dest, ptrdiff_t linesize, int16_t *block) +{ + v4i32 in0, in1, in2, in3, in4, in5, in6, in7; + v4i32 t1, t2, t3, t4, t5, t6, t7, t8; + v4i32 dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + v16i8 zero_m = { 0 }; + v4i32 cnst_17 = {17, 17, 17, 17}; + v4i32 cnst_22 = {22, 22, 22, 22}; + v4i32 cnst_10 = {10, 10, 10, 10}; + v4i32 cnst_12 = {12, 12, 12, 12}; + v4i32 cnst_64 = {64, 64, 64, 64}; + v4i32 cnst_16 = {16, 16, 16, 16}; + v4i32 cnst_15 = {15, 15, 15, 15}; + v4i32 cnst_4 = {4, 4, 4, 4}; + v4i32 cnst_6 = {6, 6, 6, 6}; + v4i32 cnst_9 = {9, 9, 9, 9}; + + LD_SW4(block, 8, t1, t2, t3, t4); + UNPCK_SH_SW(t1, in0, in4); + UNPCK_SH_SW(t2, in1, in5); + UNPCK_SH_SW(t3, in2, in6); + UNPCK_SH_SW(t4, in3, in7); + TRANSPOSE4x4_SW_SW(in0, in1, in2, in3, in0, in1, in2, in3); + TRANSPOSE4x4_SW_SW(in4, in5, in6, in7, in4, in5, in6, in7); + // First loop + t1 = cnst_12 * (in0 + in4) + cnst_4; + t2 = cnst_12 * (in0 - in4) + cnst_4; + t3 = cnst_16 * in2 + cnst_6 * in6; + t4 = cnst_6 * in2 - cnst_16 * in6; + t5 = t1 + t3, t6 = t2 + t4; + t7 = t2 - t4, t8 = t1 - t3; + t1 = cnst_16 * in1 + cnst_15 * in3 + cnst_9 * in5 + cnst_4 * in7; + t2 = cnst_15 * in1 - cnst_4 * in3 - cnst_16 * in5 - cnst_9 * in7; + t3 = cnst_9 * in1 - cnst_16 * in3 + cnst_4 * in5 + cnst_15 * in7; + t4 = cnst_4 * in1 - cnst_9 * in3 + cnst_15 * in5 - cnst_16 * in7; + in0 = (t5 + t1) >> 3; + in1 = (t6 + t2) >> 3; + in2 = (t7 + t3) >> 3; + in3 = (t8 + t4) >> 3; + in4 = (t8 - t4) >> 3; + in5 = (t7 - t3) >> 3; + in6 = (t6 - t2) >> 3; + in7 = (t5 - t1) >> 3; + TRANSPOSE4x4_SW_SW(in0, in1, in2, in3, in0, in1, in2, in3); + TRANSPOSE4x4_SW_SW(in4, in5, in6, in7, in4, in5, in6, in7); + PCKEV_H4_SW(in4, in0, in5, in1, in6, in2, in7, in3, t1, t2, t3, t4); + ST_SW4(t1, t2, t3, t4, block, 8); + // Second loop + LD_SW4(dest, linesize, dst0, dst1, dst2, dst3); + ILVR_B4_SW(zero_m, dst0, zero_m, dst1, zero_m, dst2, zero_m, dst3, + dst0, dst1, dst2, dst3); + ILVL_H4_SW(zero_m, dst0, zero_m, dst1, zero_m, dst2, zero_m, dst3, + dst4, dst5, dst6, dst7); + ILVR_H4_SW(zero_m, dst0, zero_m, dst1, zero_m, dst2, zero_m, dst3, + dst0, dst1, dst2, dst3); + // Right part + t1 = cnst_17 * (in0 + in2) + cnst_64; + t2 = cnst_17 * (in0 - in2) + cnst_64; + t3 = cnst_22 * in1 + cnst_10 * in3; + t4 = cnst_22 * in3 - cnst_10 * in1; + in0 = (t1 + t3) >> 7; + in1 = (t2 - t4) >> 7; + in2 = (t2 + t4) >> 7; + in3 = (t1 - t3) >> 7; + ADD4(in0, dst0, in1, dst1, in2, dst2, in3, dst3, in0, in1, in2, in3); + CLIP_SW4_0_255(in0, in1, in2, in3); + // Left part + t5 = cnst_17 * (in4 + in6) + cnst_64; + t6 = cnst_17 * (in4 - in6) + cnst_64; + t7 = cnst_22 * in5 + cnst_10 * in7; + t8 = cnst_22 * in7 - cnst_10 * in5; + in4 = (t5 + t7) >> 7; + in5 = (t6 - t8) >> 7; + in6 = (t6 + t8) >> 7; + in7 = (t5 - t7) >> 7; + ADD4(in4, dst4, in5, dst5, in6, dst6, in7, dst7, in4, in5, in6, in7); + CLIP_SW4_0_255(in4, in5, in6, in7); + PCKEV_H4_SW(in4, in0, in5, in1, in6, in2, in7, in3, in0, in1, in2, in3); + PCKEV_B2_SW(in1, in0, in3, in2, in0, in1); + ST_D4(in0, in1, 0, 1, 0, 1, dest, linesize); +} + +static void put_vc1_mspel_mc_h_v_msa(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int hmode, int vmode, + int rnd) +{ + v8i16 in_r0, in_r1, in_r2, in_r3, in_l0, in_l1, in_l2, in_l3; + v8i16 t0, t1, t2, t3, t4, t5, t6, t7; + v8i16 t8, t9, t10, t11, t12, t13, t14, t15; + v8i16 cnst_para0, cnst_para1, cnst_para2, cnst_para3, cnst_r; + static const int para_value[][4] = {{4, 53, 18, 3}, + {1, 9, 9, 1}, + {3, 18, 53, 4}}; + 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; + cnst_r = __msa_fill_h(r); + src -= 1, src -= stride; + cnst_para0 = __msa_fill_h(para_value[vmode - 1][0]); + cnst_para1 = __msa_fill_h(para_value[vmode - 1][1]); + cnst_para2 = __msa_fill_h(para_value[vmode - 1][2]); + cnst_para3 = __msa_fill_h(para_value[vmode - 1][3]); + LD_SH4(src, stride, in_l0, in_l1, in_l2, in_l3); + UNPCK_UB_SH(in_l0, in_r0, in_l0); + UNPCK_UB_SH(in_l1, in_r1, in_l1); + UNPCK_UB_SH(in_l2, in_r2, in_l2); + UNPCK_UB_SH(in_l3, in_r3, in_l3); + // row 0 + t0 = cnst_para1 * in_r1 + cnst_para2 * in_r2 + - cnst_para0 * in_r0 - cnst_para3 * in_r3; + t8 = cnst_para1 * in_l1 + cnst_para2 * in_l2 + - cnst_para0 * in_l0 - cnst_para3 * in_l3; + in_l0 = LD_SH(src + 4 * stride); + UNPCK_UB_SH(in_l0, in_r0, in_l0); + // row 1 + t1 = cnst_para1 * in_r2 + cnst_para2 * in_r3 + - cnst_para0 * in_r1 - cnst_para3 * in_r0; + t9 = cnst_para1 * in_l2 + cnst_para2 * in_l3 + - cnst_para0 * in_l1 - cnst_para3 * in_l0; + in_l1 = LD_SH(src + 5 * stride); + UNPCK_UB_SH(in_l1, in_r1, in_l1); + // row 2 + t2 = cnst_para1 * in_r3 + cnst_para2 * in_r0 + - cnst_para0 * in_r2 - cnst_para3 * in_r1; + t10 = cnst_para1 * in_l3 + cnst_para2 * in_l0 + - cnst_para0 * in_l2 - cnst_para3 * in_l1; + in_l2 = LD_SH(src + 6 * stride); + UNPCK_UB_SH(in_l2, in_r2, in_l2); + // row 3 + t3 = cnst_para1 * in_r0 + cnst_para2 * in_r1 + - cnst_para0 * in_r3 - cnst_para3 * in_r2; + t11 = cnst_para1 * in_l0 + cnst_para2 * in_l1 + - cnst_para0 * in_l3 - cnst_para3 * in_l2; + in_l3 = LD_SH(src + 7 * stride); + UNPCK_UB_SH(in_l3, in_r3, in_l3); + // row 4 + t4 = cnst_para1 * in_r1 + cnst_para2 * in_r2 + - cnst_para0 * in_r0 - cnst_para3 * in_r3; + t12 = cnst_para1 * in_l1 + cnst_para2 * in_l2 + - cnst_para0 * in_l0 - cnst_para3 * in_l3; + in_l0 = LD_SH(src + 8 * stride); + UNPCK_UB_SH(in_l0, in_r0, in_l0); + // row 5 + t5 = cnst_para1 * in_r2 + cnst_para2 * in_r3 + - cnst_para0 * in_r1 - cnst_para3 * in_r0; + t13 = cnst_para1 * in_l2 + cnst_para2 * in_l3 + - cnst_para0 * in_l1 - cnst_para3 * in_l0; + in_l1 = LD_SH(src + 9 * stride); + UNPCK_UB_SH(in_l1, in_r1, in_l1); + // row 6 + t6 = cnst_para1 * in_r3 + cnst_para2 * in_r0 + - cnst_para0 * in_r2 - cnst_para3 * in_r1; + t14 = cnst_para1 * in_l3 + cnst_para2 * in_l0 + - cnst_para0 * in_l2 - cnst_para3 * in_l1; + in_l2 = LD_SH(src + 10 * stride); + UNPCK_UB_SH(in_l2, in_r2, in_l2); + // row 7 + t7 = cnst_para1 * in_r0 + cnst_para2 * in_r1 + - cnst_para0 * in_r3 - cnst_para3 * in_r2; + t15 = cnst_para1 * in_l0 + cnst_para2 * in_l1 + - cnst_para0 * in_l3 - cnst_para3 * in_l2; + + ADD4(t0, cnst_r, t1, cnst_r, t2, cnst_r, t3, cnst_r, t0, t1, t2, t3); + ADD4(t4, cnst_r, t5, cnst_r, t6, cnst_r, t7, cnst_r, t4, t5, t6, t7); + ADD4(t8, cnst_r, t9, cnst_r, t10, cnst_r, t11, cnst_r, + t8, t9, t10, t11); + ADD4(t12, cnst_r, t13, cnst_r, t14, cnst_r, t15, cnst_r, + t12, t13, t14, t15); + t0 >>= shift, t1 >>= shift, t2 >>= shift, t3 >>= shift; + t4 >>= shift, t5 >>= shift, t6 >>= shift, t7 >>= shift; + t8 >>= shift, t9 >>= shift, t10 >>= shift, t11 >>= shift; + t12 >>= shift, t13 >>= shift, t14 >>= shift, t15 >>= shift; + TRANSPOSE8x8_SH_SH(t0, t1, t2, t3, t4, t5, t6, t7, + t0, t1, t2, t3, t4, t5, t6, t7); + TRANSPOSE8x8_SH_SH(t8, t9, t10, t11, t12, t13, t14, t15, + t8, t9, t10, t11, t12, t13, t14, t15); + cnst_para0 = __msa_fill_h(para_value[hmode - 1][0]); + cnst_para1 = __msa_fill_h(para_value[hmode - 1][1]); + cnst_para2 = __msa_fill_h(para_value[hmode - 1][2]); + cnst_para3 = __msa_fill_h(para_value[hmode - 1][3]); + r = 64 - rnd; + cnst_r = __msa_fill_h(r); + // col 0 ~ 7 + t0 = cnst_para1 * t1 + cnst_para2 * t2 - cnst_para0 * t0 - cnst_para3 * t3; + t1 = cnst_para1 * t2 + cnst_para2 * t3 - cnst_para0 * t1 - cnst_para3 * t4; + t2 = cnst_para1 * t3 + cnst_para2 * t4 - cnst_para0 * t2 - cnst_para3 * t5; + t3 = cnst_para1 * t4 + cnst_para2 * t5 - cnst_para0 * t3 - cnst_para3 * t6; + t4 = cnst_para1 * t5 + cnst_para2 * t6 - cnst_para0 * t4 - cnst_para3 * t7; + t5 = cnst_para1 * t6 + cnst_para2 * t7 - cnst_para0 * t5 - cnst_para3 * t8; + t6 = cnst_para1 * t7 + cnst_para2 * t8 - cnst_para0 * t6 - cnst_para3 * t9; + t7 = cnst_para1 * t8 + cnst_para2 * t9 - cnst_para0 * t7 - cnst_para3 * t10; + ADD4(t0, cnst_r, t1, cnst_r, t2, cnst_r, t3, cnst_r, t0, t1, t2, t3); + ADD4(t4, cnst_r, t5, cnst_r, t6, cnst_r, t7, cnst_r, t4, t5, t6, t7); + t0 >>= 7, t1 >>= 7, t2 >>= 7, t3 >>= 7; + t4 >>= 7, t5 >>= 7, t6 >>= 7, t7 >>= 7; + TRANSPOSE8x8_SH_SH(t0, t1, t2, t3, t4, t5, t6, t7, + t0, t1, t2, t3, t4, t5, t6, t7); + CLIP_SH8_0_255(t0, t1, t2, t3, t4, t5, t6, t7); + PCKEV_B4_SH(t1, t0, t3, t2, t5, t4, t7, t6, t0, t1, t2, t3); + ST_D8(t0, t1, t2, t3, 0, 1, 0, 1, 0, 1, 0, 1, dst, stride); +} + +#define PUT_VC1_MSPEL_MC_MSA(hmode, vmode) \ +void ff_put_vc1_mspel_mc ## hmode ## vmode ## _msa(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + put_vc1_mspel_mc_h_v_msa(dst, src, stride, hmode, vmode, rnd); \ +} \ +void ff_put_vc1_mspel_mc ## hmode ## vmode ## _16_msa(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + put_vc1_mspel_mc_h_v_msa(dst, src, stride, hmode, vmode, rnd); \ + put_vc1_mspel_mc_h_v_msa(dst + 8, src + 8, stride, hmode, vmode, rnd); \ + dst += 8 * stride, src += 8 * stride; \ + put_vc1_mspel_mc_h_v_msa(dst, src, stride, hmode, vmode, rnd); \ + put_vc1_mspel_mc_h_v_msa(dst + 8, src + 8, stride, hmode, vmode, rnd); \ +} + +PUT_VC1_MSPEL_MC_MSA(1, 1); +PUT_VC1_MSPEL_MC_MSA(1, 2); +PUT_VC1_MSPEL_MC_MSA(1, 3); + +PUT_VC1_MSPEL_MC_MSA(2, 1); +PUT_VC1_MSPEL_MC_MSA(2, 2); +PUT_VC1_MSPEL_MC_MSA(2, 3); + +PUT_VC1_MSPEL_MC_MSA(3, 1); +PUT_VC1_MSPEL_MC_MSA(3, 2); +PUT_VC1_MSPEL_MC_MSA(3, 3); diff -Nru ffmpeg-4.2.2/libavcodec/mips/videodsp_init.c ffmpeg-4.4/libavcodec/mips/videodsp_init.c --- ffmpeg-4.2.2/libavcodec/mips/videodsp_init.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/videodsp_init.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,12 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "config.h" #include "libavutil/attributes.h" #include "libavutil/mips/asmdefs.h" #include "libavcodec/videodsp.h" -#if HAVE_MSA static void prefetch_mips(uint8_t *mem, ptrdiff_t stride, int h) { register const uint8_t *p = mem; @@ -41,11 +41,11 @@ : [stride] "r" (stride) ); } -#endif // #if HAVE_MSA av_cold void ff_videodsp_init_mips(VideoDSPContext *ctx, int bpc) { -#if HAVE_MSA - ctx->prefetch = prefetch_mips; -#endif // #if HAVE_MSA + int cpu_flags = av_get_cpu_flags(); + + if (have_msa(cpu_flags)) + ctx->prefetch = prefetch_mips; } diff -Nru ffmpeg-4.2.2/libavcodec/mips/vp3dsp_idct_msa.c ffmpeg-4.4/libavcodec/mips/vp3dsp_idct_msa.c --- ffmpeg-4.2.2/libavcodec/mips/vp3dsp_idct_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vp3dsp_idct_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -187,14 +187,7 @@ G += c5; H += c6; } - A = CLIP_SW_0_255(A); - B = CLIP_SW_0_255(B); - C = CLIP_SW_0_255(C); - D = CLIP_SW_0_255(D); - E = CLIP_SW_0_255(E); - F = CLIP_SW_0_255(F); - G = CLIP_SW_0_255(G); - H = CLIP_SW_0_255(H); + CLIP_SW8_0_255(A, B, C, D, E, F, G, H); sign_l = __msa_or_v((v16u8)r1_r, (v16u8)r2_r); sign_l = __msa_or_v(sign_l, (v16u8)r3_r); sign_l = __msa_or_v(sign_l, (v16u8)r0_l); @@ -205,7 +198,7 @@ Add = ((r0_r * cnst46341w) + (8 << 16)) >> 20; if (type == 1) { Bdd = Add + cnst128w; - Bdd = CLIP_SW_0_255(Bdd); + CLIP_SW_0_255(Bdd); Ad = Bdd; Bd = Bdd; Cd = Bdd; @@ -223,14 +216,7 @@ Fd = Add + c5; Gd = Add + c6; Hd = Add + c7; - Ad = CLIP_SW_0_255(Ad); - Bd = CLIP_SW_0_255(Bd); - Cd = CLIP_SW_0_255(Cd); - Dd = CLIP_SW_0_255(Dd); - Ed = CLIP_SW_0_255(Ed); - Fd = CLIP_SW_0_255(Fd); - Gd = CLIP_SW_0_255(Gd); - Hd = CLIP_SW_0_255(Hd); + CLIP_SW8_0_255(Ad, Bd, Cd, Dd, Ed, Fd, Gd, Hd); } Ad = (v4i32)__msa_and_v((v16u8)Ad, (v16u8)sign_t); Bd = (v4i32)__msa_and_v((v16u8)Bd, (v16u8)sign_t); @@ -309,14 +295,7 @@ G += c5; H += c6; } - A = CLIP_SW_0_255(A); - B = CLIP_SW_0_255(B); - C = CLIP_SW_0_255(C); - D = CLIP_SW_0_255(D); - E = CLIP_SW_0_255(E); - F = CLIP_SW_0_255(F); - G = CLIP_SW_0_255(G); - H = CLIP_SW_0_255(H); + CLIP_SW8_0_255(A, B, C, D, E, F, G, H); sign_l = __msa_or_v((v16u8)r5_r, (v16u8)r6_r); sign_l = __msa_or_v(sign_l, (v16u8)r7_r); sign_l = __msa_or_v(sign_l, (v16u8)r4_l); @@ -327,7 +306,7 @@ Add = ((r4_r * cnst46341w) + (8 << 16)) >> 20; if (type == 1) { Bdd = Add + cnst128w; - Bdd = CLIP_SW_0_255(Bdd); + CLIP_SW_0_255(Bdd); Ad = Bdd; Bd = Bdd; Cd = Bdd; @@ -345,14 +324,7 @@ Fd = Add + c5; Gd = Add + c6; Hd = Add + c7; - Ad = CLIP_SW_0_255(Ad); - Bd = CLIP_SW_0_255(Bd); - Cd = CLIP_SW_0_255(Cd); - Dd = CLIP_SW_0_255(Dd); - Ed = CLIP_SW_0_255(Ed); - Fd = CLIP_SW_0_255(Fd); - Gd = CLIP_SW_0_255(Gd); - Hd = CLIP_SW_0_255(Hd); + CLIP_SW8_0_255(Ad, Bd, Cd, Dd, Ed, Fd, Gd, Hd); } Ad = (v4i32)__msa_and_v((v16u8)Ad, (v16u8)sign_t); Bd = (v4i32)__msa_and_v((v16u8)Bd, (v16u8)sign_t); @@ -436,14 +408,7 @@ e5 += dc; e6 += dc; e7 += dc; - e0 = CLIP_SW_0_255(e0); - e1 = CLIP_SW_0_255(e1); - e2 = CLIP_SW_0_255(e2); - e3 = CLIP_SW_0_255(e3); - e4 = CLIP_SW_0_255(e4); - e5 = CLIP_SW_0_255(e5); - e6 = CLIP_SW_0_255(e6); - e7 = CLIP_SW_0_255(e7); + CLIP_SW8_0_255(e0, e1, e2, e3, e4, e5, e6, e7); /* Left part */ ILVL_H4_SW(zero, c0, zero, c1, zero, c2, zero, c3, @@ -458,14 +423,7 @@ r5 += dc; r6 += dc; r7 += dc; - r0 = CLIP_SW_0_255(r0); - r1 = CLIP_SW_0_255(r1); - r2 = CLIP_SW_0_255(r2); - r3 = CLIP_SW_0_255(r3); - r4 = CLIP_SW_0_255(r4); - r5 = CLIP_SW_0_255(r5); - r6 = CLIP_SW_0_255(r6); - r7 = CLIP_SW_0_255(r7); + CLIP_SW8_0_255(r0, r1, r2, r3, r4, r5, r6, r7); VSHF_B2_SB(e0, r0, e1, r1, mask, mask, d0, d1); VSHF_B2_SB(e2, r2, e3, r3, mask, mask, d2, d3); VSHF_B2_SB(e4, r4, e5, r5, mask, mask, d4, d5); @@ -516,10 +474,7 @@ f1 += e1; g0 -= e0; g1 -= e1; - f0 = CLIP_SW_0_255(f0); - f1 = CLIP_SW_0_255(f1); - g0 = CLIP_SW_0_255(g0); - g1 = CLIP_SW_0_255(g1); + CLIP_SW4_0_255(f0, f1, g0, g1); VSHF_B2_SB(f0, f1, g0, g1, mask, mask, d1, d2); /* Final move to first_pixel */ @@ -563,10 +518,7 @@ f1 += e1; g0 -= e0; g1 -= e1; - f0 = CLIP_SW_0_255(f0); - f1 = CLIP_SW_0_255(f1); - g0 = CLIP_SW_0_255(g0); - g1 = CLIP_SW_0_255(g1); + CLIP_SW4_0_255(f0, f1, g0, g1); VSHF_B2_SB(f0, g0, f1, g1, mask, mask, d1, d2); /* Final move to first_pixel */ ST_H4(d1, 0, 1, 2, 3, first_pixel - 1, stride); diff -Nru ffmpeg-4.2.2/libavcodec/mips/vp3dsp_init_mips.c ffmpeg-4.4/libavcodec/mips/vp3dsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/vp3dsp_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vp3dsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,42 +19,32 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "config.h" #include "libavutil/attributes.h" #include "libavcodec/avcodec.h" #include "libavcodec/vp3dsp.h" #include "vp3dsp_mips.h" -#if HAVE_MSA -static av_cold void vp3dsp_init_msa(VP3DSPContext *c, int flags) -{ - c->put_no_rnd_pixels_l2 = ff_put_no_rnd_pixels_l2_msa; - - c->idct_add = ff_vp3_idct_add_msa; - c->idct_put = ff_vp3_idct_put_msa; - c->idct_dc_add = ff_vp3_idct_dc_add_msa; - c->v_loop_filter = ff_vp3_v_loop_filter_msa; - c->h_loop_filter = ff_vp3_h_loop_filter_msa; -} -#endif /* HAVE_MSA */ - -#if HAVE_MMI -static av_cold void vp3dsp_init_mmi(VP3DSPContext *c, int flags) +av_cold void ff_vp3dsp_init_mips(VP3DSPContext *c, int flags) { - c->put_no_rnd_pixels_l2 = ff_put_no_rnd_pixels_l2_mmi; + int cpu_flags = av_get_cpu_flags(); - c->idct_add = ff_vp3_idct_add_mmi; - c->idct_put = ff_vp3_idct_put_mmi; - c->idct_dc_add = ff_vp3_idct_dc_add_mmi; -} -#endif /* HAVE_MMI */ + if (have_mmi(cpu_flags)) { + c->put_no_rnd_pixels_l2 = ff_put_no_rnd_pixels_l2_mmi; -av_cold void ff_vp3dsp_init_mips(VP3DSPContext *c, int flags) -{ -#if HAVE_MMI - vp3dsp_init_mmi(c, flags); -#endif /* HAVE_MMI */ -#if HAVE_MSA - vp3dsp_init_msa(c, flags); -#endif /* HAVE_MSA */ + c->idct_add = ff_vp3_idct_add_mmi; + c->idct_put = ff_vp3_idct_put_mmi; + c->idct_dc_add = ff_vp3_idct_dc_add_mmi; + } + + if (have_msa(cpu_flags)) { + c->put_no_rnd_pixels_l2 = ff_put_no_rnd_pixels_l2_msa; + + c->idct_add = ff_vp3_idct_add_msa; + c->idct_put = ff_vp3_idct_put_msa; + c->idct_dc_add = ff_vp3_idct_dc_add_msa; + c->v_loop_filter = ff_vp3_v_loop_filter_msa; + c->h_loop_filter = ff_vp3_h_loop_filter_msa; + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/vp8dsp_init_mips.c ffmpeg-4.4/libavcodec/mips/vp8dsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/vp8dsp_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vp8dsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,7 @@ * VP8 compatible video decoder */ +#include "libavutil/mips/cpu.h" #include "config.h" #include "libavutil/attributes.h" #include "libavcodec/vp8dsp.h" @@ -71,132 +72,123 @@ dsp->put_vp8_bilinear_pixels_tab[IDX][0][0] = \ ff_put_vp8_pixels##SIZE##_msa; -#if HAVE_MSA -static av_cold void vp8dsp_init_msa(VP8DSPContext *dsp) -{ - dsp->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_msa; - dsp->vp8_idct_add = ff_vp8_idct_add_msa; - dsp->vp8_idct_dc_add = ff_vp8_idct_dc_add_msa; - dsp->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_msa; - dsp->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_msa; - - VP8_MC_MIPS_FUNC(0, 16); - VP8_MC_MIPS_FUNC(1, 8); - VP8_MC_MIPS_FUNC(2, 4); - - VP8_BILINEAR_MC_MIPS_FUNC(0, 16); - VP8_BILINEAR_MC_MIPS_FUNC(1, 8); - VP8_BILINEAR_MC_MIPS_FUNC(2, 4); - - VP8_MC_MIPS_COPY(0, 16); - VP8_MC_MIPS_COPY(1, 8); - - dsp->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16_msa; - dsp->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16_msa; - dsp->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_msa; - dsp->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_msa; - - dsp->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16_inner_msa; - dsp->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16_inner_msa; - dsp->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_msa; - dsp->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_msa; - - dsp->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_msa; - dsp->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_msa; -} -#endif // #if HAVE_MSA -#if HAVE_MMI -static av_cold void vp8dsp_init_mmi(VP8DSPContext *dsp) -{ - dsp->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_mmi; - dsp->vp8_luma_dc_wht_dc = ff_vp8_luma_dc_wht_dc_mmi; - dsp->vp8_idct_add = ff_vp8_idct_add_mmi; - dsp->vp8_idct_dc_add = ff_vp8_idct_dc_add_mmi; - dsp->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_mmi; - dsp->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_mmi; - - dsp->put_vp8_epel_pixels_tab[0][0][1] = ff_put_vp8_epel16_h4_mmi; - dsp->put_vp8_epel_pixels_tab[0][0][2] = ff_put_vp8_epel16_h6_mmi; - dsp->put_vp8_epel_pixels_tab[0][1][0] = ff_put_vp8_epel16_v4_mmi; - dsp->put_vp8_epel_pixels_tab[0][1][1] = ff_put_vp8_epel16_h4v4_mmi; - dsp->put_vp8_epel_pixels_tab[0][1][2] = ff_put_vp8_epel16_h6v4_mmi; - dsp->put_vp8_epel_pixels_tab[0][2][0] = ff_put_vp8_epel16_v6_mmi; - dsp->put_vp8_epel_pixels_tab[0][2][1] = ff_put_vp8_epel16_h4v6_mmi; - dsp->put_vp8_epel_pixels_tab[0][2][2] = ff_put_vp8_epel16_h6v6_mmi; - - dsp->put_vp8_epel_pixels_tab[1][0][1] = ff_put_vp8_epel8_h4_mmi; - dsp->put_vp8_epel_pixels_tab[1][0][2] = ff_put_vp8_epel8_h6_mmi; - dsp->put_vp8_epel_pixels_tab[1][1][0] = ff_put_vp8_epel8_v4_mmi; - dsp->put_vp8_epel_pixels_tab[1][1][1] = ff_put_vp8_epel8_h4v4_mmi; - dsp->put_vp8_epel_pixels_tab[1][1][2] = ff_put_vp8_epel8_h6v4_mmi; - dsp->put_vp8_epel_pixels_tab[1][2][0] = ff_put_vp8_epel8_v6_mmi; - dsp->put_vp8_epel_pixels_tab[1][2][1] = ff_put_vp8_epel8_h4v6_mmi; - dsp->put_vp8_epel_pixels_tab[1][2][2] = ff_put_vp8_epel8_h6v6_mmi; - - dsp->put_vp8_epel_pixels_tab[2][0][1] = ff_put_vp8_epel4_h4_mmi; - dsp->put_vp8_epel_pixels_tab[2][0][2] = ff_put_vp8_epel4_h6_mmi; - dsp->put_vp8_epel_pixels_tab[2][1][0] = ff_put_vp8_epel4_v4_mmi; - dsp->put_vp8_epel_pixels_tab[2][1][1] = ff_put_vp8_epel4_h4v4_mmi; - dsp->put_vp8_epel_pixels_tab[2][1][2] = ff_put_vp8_epel4_h6v4_mmi; - dsp->put_vp8_epel_pixels_tab[2][2][0] = ff_put_vp8_epel4_v6_mmi; - dsp->put_vp8_epel_pixels_tab[2][2][1] = ff_put_vp8_epel4_h4v6_mmi; - dsp->put_vp8_epel_pixels_tab[2][2][2] = ff_put_vp8_epel4_h6v6_mmi; - - dsp->put_vp8_bilinear_pixels_tab[0][0][1] = ff_put_vp8_bilinear16_h_mmi; - dsp->put_vp8_bilinear_pixels_tab[0][0][2] = ff_put_vp8_bilinear16_h_mmi; - dsp->put_vp8_bilinear_pixels_tab[0][1][0] = ff_put_vp8_bilinear16_v_mmi; - dsp->put_vp8_bilinear_pixels_tab[0][1][1] = ff_put_vp8_bilinear16_hv_mmi; - dsp->put_vp8_bilinear_pixels_tab[0][1][2] = ff_put_vp8_bilinear16_hv_mmi; - dsp->put_vp8_bilinear_pixels_tab[0][2][0] = ff_put_vp8_bilinear16_v_mmi; - dsp->put_vp8_bilinear_pixels_tab[0][2][1] = ff_put_vp8_bilinear16_hv_mmi; - dsp->put_vp8_bilinear_pixels_tab[0][2][2] = ff_put_vp8_bilinear16_hv_mmi; - - dsp->put_vp8_bilinear_pixels_tab[1][0][1] = ff_put_vp8_bilinear8_h_mmi; - dsp->put_vp8_bilinear_pixels_tab[1][0][2] = ff_put_vp8_bilinear8_h_mmi; - dsp->put_vp8_bilinear_pixels_tab[1][1][0] = ff_put_vp8_bilinear8_v_mmi; - dsp->put_vp8_bilinear_pixels_tab[1][1][1] = ff_put_vp8_bilinear8_hv_mmi; - dsp->put_vp8_bilinear_pixels_tab[1][1][2] = ff_put_vp8_bilinear8_hv_mmi; - dsp->put_vp8_bilinear_pixels_tab[1][2][0] = ff_put_vp8_bilinear8_v_mmi; - dsp->put_vp8_bilinear_pixels_tab[1][2][1] = ff_put_vp8_bilinear8_hv_mmi; - dsp->put_vp8_bilinear_pixels_tab[1][2][2] = ff_put_vp8_bilinear8_hv_mmi; - - dsp->put_vp8_bilinear_pixels_tab[2][0][1] = ff_put_vp8_bilinear4_h_mmi; - dsp->put_vp8_bilinear_pixels_tab[2][0][2] = ff_put_vp8_bilinear4_h_mmi; - dsp->put_vp8_bilinear_pixels_tab[2][1][0] = ff_put_vp8_bilinear4_v_mmi; - dsp->put_vp8_bilinear_pixels_tab[2][1][1] = ff_put_vp8_bilinear4_hv_mmi; - dsp->put_vp8_bilinear_pixels_tab[2][1][2] = ff_put_vp8_bilinear4_hv_mmi; - dsp->put_vp8_bilinear_pixels_tab[2][2][0] = ff_put_vp8_bilinear4_v_mmi; - dsp->put_vp8_bilinear_pixels_tab[2][2][1] = ff_put_vp8_bilinear4_hv_mmi; - dsp->put_vp8_bilinear_pixels_tab[2][2][2] = ff_put_vp8_bilinear4_hv_mmi; - - dsp->put_vp8_epel_pixels_tab[0][0][0] = ff_put_vp8_pixels16_mmi; - dsp->put_vp8_bilinear_pixels_tab[0][0][0] = ff_put_vp8_pixels16_mmi; - - dsp->put_vp8_epel_pixels_tab[1][0][0] = ff_put_vp8_pixels8_mmi; - dsp->put_vp8_bilinear_pixels_tab[1][0][0] = ff_put_vp8_pixels8_mmi; - - dsp->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16_mmi; - dsp->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16_mmi; - dsp->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mmi; - dsp->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mmi; - - dsp->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16_inner_mmi; - dsp->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16_inner_mmi; - dsp->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_mmi; - dsp->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_mmi; - - dsp->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_mmi; - dsp->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_mmi; -} -#endif /* HAVE_MMI */ av_cold void ff_vp8dsp_init_mips(VP8DSPContext *dsp) { -#if HAVE_MMI - vp8dsp_init_mmi(dsp); -#endif /* HAVE_MMI */ -#if HAVE_MSA - vp8dsp_init_msa(dsp); -#endif // #if HAVE_MSA + int cpu_flags = av_get_cpu_flags(); + + if (have_mmi(cpu_flags)) { + dsp->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_mmi; + dsp->vp8_luma_dc_wht_dc = ff_vp8_luma_dc_wht_dc_mmi; + dsp->vp8_idct_add = ff_vp8_idct_add_mmi; + dsp->vp8_idct_dc_add = ff_vp8_idct_dc_add_mmi; + dsp->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_mmi; + dsp->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_mmi; + + dsp->put_vp8_epel_pixels_tab[0][0][1] = ff_put_vp8_epel16_h4_mmi; + dsp->put_vp8_epel_pixels_tab[0][0][2] = ff_put_vp8_epel16_h6_mmi; + dsp->put_vp8_epel_pixels_tab[0][1][0] = ff_put_vp8_epel16_v4_mmi; + dsp->put_vp8_epel_pixels_tab[0][1][1] = ff_put_vp8_epel16_h4v4_mmi; + dsp->put_vp8_epel_pixels_tab[0][1][2] = ff_put_vp8_epel16_h6v4_mmi; + dsp->put_vp8_epel_pixels_tab[0][2][0] = ff_put_vp8_epel16_v6_mmi; + dsp->put_vp8_epel_pixels_tab[0][2][1] = ff_put_vp8_epel16_h4v6_mmi; + dsp->put_vp8_epel_pixels_tab[0][2][2] = ff_put_vp8_epel16_h6v6_mmi; + + dsp->put_vp8_epel_pixels_tab[1][0][1] = ff_put_vp8_epel8_h4_mmi; + dsp->put_vp8_epel_pixels_tab[1][0][2] = ff_put_vp8_epel8_h6_mmi; + dsp->put_vp8_epel_pixels_tab[1][1][0] = ff_put_vp8_epel8_v4_mmi; + dsp->put_vp8_epel_pixels_tab[1][1][1] = ff_put_vp8_epel8_h4v4_mmi; + dsp->put_vp8_epel_pixels_tab[1][1][2] = ff_put_vp8_epel8_h6v4_mmi; + dsp->put_vp8_epel_pixels_tab[1][2][0] = ff_put_vp8_epel8_v6_mmi; + dsp->put_vp8_epel_pixels_tab[1][2][1] = ff_put_vp8_epel8_h4v6_mmi; + dsp->put_vp8_epel_pixels_tab[1][2][2] = ff_put_vp8_epel8_h6v6_mmi; + + dsp->put_vp8_epel_pixels_tab[2][0][1] = ff_put_vp8_epel4_h4_mmi; + dsp->put_vp8_epel_pixels_tab[2][0][2] = ff_put_vp8_epel4_h6_mmi; + dsp->put_vp8_epel_pixels_tab[2][1][0] = ff_put_vp8_epel4_v4_mmi; + dsp->put_vp8_epel_pixels_tab[2][1][1] = ff_put_vp8_epel4_h4v4_mmi; + dsp->put_vp8_epel_pixels_tab[2][1][2] = ff_put_vp8_epel4_h6v4_mmi; + dsp->put_vp8_epel_pixels_tab[2][2][0] = ff_put_vp8_epel4_v6_mmi; + dsp->put_vp8_epel_pixels_tab[2][2][1] = ff_put_vp8_epel4_h4v6_mmi; + dsp->put_vp8_epel_pixels_tab[2][2][2] = ff_put_vp8_epel4_h6v6_mmi; + + dsp->put_vp8_bilinear_pixels_tab[0][0][1] = ff_put_vp8_bilinear16_h_mmi; + dsp->put_vp8_bilinear_pixels_tab[0][0][2] = ff_put_vp8_bilinear16_h_mmi; + dsp->put_vp8_bilinear_pixels_tab[0][1][0] = ff_put_vp8_bilinear16_v_mmi; + dsp->put_vp8_bilinear_pixels_tab[0][1][1] = ff_put_vp8_bilinear16_hv_mmi; + dsp->put_vp8_bilinear_pixels_tab[0][1][2] = ff_put_vp8_bilinear16_hv_mmi; + dsp->put_vp8_bilinear_pixels_tab[0][2][0] = ff_put_vp8_bilinear16_v_mmi; + dsp->put_vp8_bilinear_pixels_tab[0][2][1] = ff_put_vp8_bilinear16_hv_mmi; + dsp->put_vp8_bilinear_pixels_tab[0][2][2] = ff_put_vp8_bilinear16_hv_mmi; + + dsp->put_vp8_bilinear_pixels_tab[1][0][1] = ff_put_vp8_bilinear8_h_mmi; + dsp->put_vp8_bilinear_pixels_tab[1][0][2] = ff_put_vp8_bilinear8_h_mmi; + dsp->put_vp8_bilinear_pixels_tab[1][1][0] = ff_put_vp8_bilinear8_v_mmi; + dsp->put_vp8_bilinear_pixels_tab[1][1][1] = ff_put_vp8_bilinear8_hv_mmi; + dsp->put_vp8_bilinear_pixels_tab[1][1][2] = ff_put_vp8_bilinear8_hv_mmi; + dsp->put_vp8_bilinear_pixels_tab[1][2][0] = ff_put_vp8_bilinear8_v_mmi; + dsp->put_vp8_bilinear_pixels_tab[1][2][1] = ff_put_vp8_bilinear8_hv_mmi; + dsp->put_vp8_bilinear_pixels_tab[1][2][2] = ff_put_vp8_bilinear8_hv_mmi; + + dsp->put_vp8_bilinear_pixels_tab[2][0][1] = ff_put_vp8_bilinear4_h_mmi; + dsp->put_vp8_bilinear_pixels_tab[2][0][2] = ff_put_vp8_bilinear4_h_mmi; + dsp->put_vp8_bilinear_pixels_tab[2][1][0] = ff_put_vp8_bilinear4_v_mmi; + dsp->put_vp8_bilinear_pixels_tab[2][1][1] = ff_put_vp8_bilinear4_hv_mmi; + dsp->put_vp8_bilinear_pixels_tab[2][1][2] = ff_put_vp8_bilinear4_hv_mmi; + dsp->put_vp8_bilinear_pixels_tab[2][2][0] = ff_put_vp8_bilinear4_v_mmi; + dsp->put_vp8_bilinear_pixels_tab[2][2][1] = ff_put_vp8_bilinear4_hv_mmi; + dsp->put_vp8_bilinear_pixels_tab[2][2][2] = ff_put_vp8_bilinear4_hv_mmi; + + dsp->put_vp8_epel_pixels_tab[0][0][0] = ff_put_vp8_pixels16_mmi; + dsp->put_vp8_bilinear_pixels_tab[0][0][0] = ff_put_vp8_pixels16_mmi; + + dsp->put_vp8_epel_pixels_tab[1][0][0] = ff_put_vp8_pixels8_mmi; + dsp->put_vp8_bilinear_pixels_tab[1][0][0] = ff_put_vp8_pixels8_mmi; + + dsp->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16_mmi; + dsp->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16_mmi; + dsp->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mmi; + dsp->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mmi; + + dsp->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16_inner_mmi; + dsp->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16_inner_mmi; + dsp->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_mmi; + dsp->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_mmi; + + dsp->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_mmi; + dsp->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_mmi; + } + + if (have_msa(cpu_flags)) { + dsp->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_msa; + dsp->vp8_idct_add = ff_vp8_idct_add_msa; + dsp->vp8_idct_dc_add = ff_vp8_idct_dc_add_msa; + dsp->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_msa; + dsp->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_msa; + + VP8_MC_MIPS_FUNC(0, 16); + VP8_MC_MIPS_FUNC(1, 8); + VP8_MC_MIPS_FUNC(2, 4); + + VP8_BILINEAR_MC_MIPS_FUNC(0, 16); + VP8_BILINEAR_MC_MIPS_FUNC(1, 8); + VP8_BILINEAR_MC_MIPS_FUNC(2, 4); + + VP8_MC_MIPS_COPY(0, 16); + VP8_MC_MIPS_COPY(1, 8); + + dsp->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16_msa; + dsp->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16_msa; + dsp->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_msa; + dsp->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_msa; + + dsp->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16_inner_msa; + dsp->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16_inner_msa; + dsp->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_msa; + dsp->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_msa; + + dsp->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_msa; + dsp->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_msa; + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/vp8dsp_mmi.c ffmpeg-4.4/libavcodec/mips/vp8dsp_mmi.c --- ffmpeg-4.2.2/libavcodec/mips/vp8dsp_mmi.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vp8dsp_mmi.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,7 @@ #include "vp8dsp_mips.h" #include "constants.h" #include "libavutil/mips/mmiutils.h" +#include "libavutil/mem_internal.h" #define DECLARE_DOUBLE_1 double db_1 #define DECLARE_DOUBLE_2 double db_2 diff -Nru ffmpeg-4.2.2/libavcodec/mips/vp8_idct_msa.c ffmpeg-4.4/libavcodec/mips/vp8_idct_msa.c --- ffmpeg-4.2.2/libavcodec/mips/vp8_idct_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vp8_idct_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -71,10 +71,7 @@ ILVR_H4_SW(zero, res0, zero, res1, zero, res2, zero, res3, res0, res1, res2, res3); ADD4(res0, vt0, res1, vt1, res2, vt2, res3, vt3, res0, res1, res2, res3); - res0 = CLIP_SW_0_255(res0); - res1 = CLIP_SW_0_255(res1); - res2 = CLIP_SW_0_255(res2); - res3 = CLIP_SW_0_255(res3); + CLIP_SW4_0_255(res0, res1, res2, res3); VSHF_B2_SB(res0, res1, res2, res3, mask, mask, dest0, dest1); ST_W2(dest0, 0, 1, dst, stride); ST_W2(dest1, 0, 1, dst + 2 * stride, stride); diff -Nru ffmpeg-4.2.2/libavcodec/mips/vp8_mc_msa.c ffmpeg-4.4/libavcodec/mips/vp8_mc_msa.c --- ffmpeg-4.2.2/libavcodec/mips/vp8_mc_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vp8_mc_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -1995,8 +1995,8 @@ hz_out4 = HORIZ_2TAP_FILT_UH(src4, src5, mask, filt_hz, 7); hz_out6 = HORIZ_2TAP_FILT_UH(src6, src7, mask, filt_hz, 7); hz_out8 = HORIZ_2TAP_FILT_UH(src8, src8, mask, filt_hz, 7); - SLDI_B3_UH(hz_out2, hz_out4, hz_out6, hz_out0, hz_out2, hz_out4, hz_out1, - hz_out3, hz_out5, 8); + SLDI_B3_UH(hz_out2, hz_out0, hz_out4, hz_out2, hz_out6, hz_out4, 8, hz_out1, + hz_out3, hz_out5); hz_out7 = (v8u16) __msa_pckod_d((v2i64) hz_out8, (v2i64) hz_out6); ILVEV_B2_UB(hz_out0, hz_out1, hz_out2, hz_out3, vec0, vec1); diff -Nru ffmpeg-4.2.2/libavcodec/mips/vp9dsp_init_mips.c ffmpeg-4.4/libavcodec/mips/vp9dsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/vp9dsp_init_mips.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vp9dsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "config.h" #include "libavutil/common.h" #include "libavcodec/vp9dsp.h" @@ -209,10 +210,17 @@ av_cold void ff_vp9dsp_init_mips(VP9DSPContext *dsp, int bpp) { +#if HAVE_MSA || HAVE_MMI + int cpu_flags = av_get_cpu_flags(); +#endif + #if HAVE_MMI - vp9dsp_init_mmi(dsp, bpp); -#endif // #if HAVE_MMI + if (have_mmi(cpu_flags)) + vp9dsp_init_mmi(dsp, bpp); +#endif + #if HAVE_MSA - vp9dsp_init_msa(dsp, bpp); -#endif // #if HAVE_MSA + if (have_msa(cpu_flags)) + vp9dsp_init_msa(dsp, bpp); +#endif } diff -Nru ffmpeg-4.2.2/libavcodec/mips/vp9_idct_msa.c ffmpeg-4.4/libavcodec/mips/vp9_idct_msa.c --- ffmpeg-4.2.2/libavcodec/mips/vp9_idct_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vp9_idct_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -249,6 +249,7 @@ v8i16 c0_m, c1_m, c2_m, c3_m; \ v8i16 step0_m, step1_m; \ v4i32 tmp0_m, tmp1_m, tmp2_m, tmp3_m; \ + v16i8 zeros = { 0 }; \ \ c0_m = VP9_SET_COSPI_PAIR(cospi_16_64, cospi_16_64); \ c1_m = VP9_SET_COSPI_PAIR(cospi_16_64, -cospi_16_64); \ @@ -262,7 +263,7 @@ SRARI_W4_SW(tmp0_m, tmp1_m, tmp2_m, tmp3_m, VP9_DCT_CONST_BITS); \ \ PCKEV_H2_SW(tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp0_m, tmp2_m); \ - SLDI_B2_0_SW(tmp0_m, tmp2_m, tmp1_m, tmp3_m, 8); \ + SLDI_B2_SW(zeros, tmp0_m, zeros, tmp2_m, 8, tmp1_m, tmp3_m); \ BUTTERFLY_4((v8i16) tmp0_m, (v8i16) tmp1_m, \ (v8i16) tmp2_m, (v8i16) tmp3_m, \ out0, out1, out2, out3); \ @@ -763,13 +764,13 @@ res0 = (v8i16) __msa_ilvr_b((v16i8) zero, (v16i8) dst0); res0 += out0; - res0 = CLIP_SH_0_255(res0); + CLIP_SH_0_255(res0); res0 = (v8i16) __msa_pckev_b((v16i8) res0, (v16i8) res0); ST_D1(res0, 0, dst); res7 = (v8i16) __msa_ilvr_b((v16i8) zero, (v16i8) dst7); res7 += out7; - res7 = CLIP_SH_0_255(res7); + CLIP_SH_0_255(res7); res7 = (v8i16) __msa_pckev_b((v16i8) res7, (v16i8) res7); ST_D1(res7, 0, dst + 7 * dst_stride); @@ -1192,8 +1193,7 @@ res3); ADD4(res4, vec, res5, vec, res6, vec, res7, vec, res4, res5, res6, res7); - CLIP_SH4_0_255(res0, res1, res2, res3); - CLIP_SH4_0_255(res4, res5, res6, res7); + CLIP_SH8_0_255(res0, res1, res2, res3, res4, res5, res6, res7); PCKEV_B4_UB(res4, res0, res5, res1, res6, res2, res7, res3, tmp0, tmp1, tmp2, tmp3); ST_UB4(tmp0, tmp1, tmp2, tmp3, dst, dst_stride); @@ -1981,8 +1981,7 @@ res3); ADD4(res4, vec, res5, vec, res6, vec, res7, vec, res4, res5, res6, res7); - CLIP_SH4_0_255(res0, res1, res2, res3); - CLIP_SH4_0_255(res4, res5, res6, res7); + CLIP_SH8_0_255(res0, res1, res2, res3, res4, res5, res6, res7); PCKEV_B4_UB(res4, res0, res5, res1, res6, res2, res7, res3, tmp0, tmp1, tmp2, tmp3); diff -Nru ffmpeg-4.2.2/libavcodec/mips/vp9_lpf_msa.c ffmpeg-4.4/libavcodec/mips/vp9_lpf_msa.c --- ffmpeg-4.2.2/libavcodec/mips/vp9_lpf_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vp9_lpf_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -1673,6 +1673,7 @@ v16u8 p7_org, p6_org, p5_org, p4_org, p3_org, p2_org, p1_org, p0_org; v16i8 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; v16u8 p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + v16i8 zeros = { 0 }; LD_UB8(input, in_pitch, p7_org, p6_org, p5_org, p4_org, p3_org, p2_org, p1_org, p0_org); @@ -1686,7 +1687,7 @@ ILVL_B2_SB(tmp1, tmp0, tmp3, tmp2, tmp5, tmp7); ILVR_W2_UB(tmp6, tmp4, tmp7, tmp5, q0, q4); ILVL_W2_UB(tmp6, tmp4, tmp7, tmp5, q2, q6); - SLDI_B4_0_UB(q0, q2, q4, q6, q1, q3, q5, q7, 8); + SLDI_B4_UB(zeros, q0, zeros, q2, zeros, q4, zeros, q6, 8, q1, q3, q5, q7); ST_UB8(p7, p6, p5, p4, p3, p2, p1, p0, output, out_pitch); output += (8 * out_pitch); diff -Nru ffmpeg-4.2.2/libavcodec/mips/vp9_mc_msa.c ffmpeg-4.4/libavcodec/mips/vp9_mc_msa.c --- ffmpeg-4.2.2/libavcodec/mips/vp9_mc_msa.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/vp9_mc_msa.c 2020-07-11 10:39:30.000000000 +0000 @@ -795,7 +795,7 @@ filt_hz1, filt_hz2, filt_hz3); hz_out5 = HORIZ_8TAP_FILT(src5, src6, mask0, mask1, mask2, mask3, filt_hz0, filt_hz1, filt_hz2, filt_hz3); - SLDI_B2_SH(hz_out2, hz_out4, hz_out0, hz_out2, hz_out1, hz_out3, 8); + SLDI_B2_SH(hz_out2, hz_out0, hz_out4, hz_out2, 8, hz_out1, hz_out3); filt = LD_SH(filter_vert); SPLATI_H4_SH(filt, 0, 1, 2, 3, filt_vt0, filt_vt1, filt_vt2, filt_vt3); @@ -1585,7 +1585,7 @@ filt_hz1, filt_hz2, filt_hz3); hz_out5 = HORIZ_8TAP_FILT(src5, src6, mask0, mask1, mask2, mask3, filt_hz0, filt_hz1, filt_hz2, filt_hz3); - SLDI_B2_SH(hz_out2, hz_out4, hz_out0, hz_out2, hz_out1, hz_out3, 8); + SLDI_B2_SH(hz_out2, hz_out0, hz_out4, hz_out2, 8, hz_out1, hz_out3); filt = LD_SH(filter_vert); SPLATI_H4_SH(filt, 0, 1, 2, 3, filt_vt0, filt_vt1, filt_vt2, filt_vt3); @@ -2093,7 +2093,7 @@ src4 = LD_SB(src + 32); src6 = LD_SB(src + 48); src7 = LD_SB(src + 56); - SLDI_B3_SB(src2, src4, src6, src0, src2, src4, src1, src3, src5, 8); + SLDI_B3_SB(src2, src0, src4, src2, src6, src4, 8, src1, src3, src5); src += src_stride; VSHF_B2_UB(src0, src0, src1, src1, mask, mask, vec0, vec1); @@ -2544,8 +2544,8 @@ hz_out4 = HORIZ_2TAP_FILT_UH(src4, src5, mask, filt_hz, 7); hz_out6 = HORIZ_2TAP_FILT_UH(src6, src7, mask, filt_hz, 7); hz_out8 = HORIZ_2TAP_FILT_UH(src8, src8, mask, filt_hz, 7); - SLDI_B3_UH(hz_out2, hz_out4, hz_out6, hz_out0, hz_out2, hz_out4, hz_out1, - hz_out3, hz_out5, 8); + SLDI_B3_UH(hz_out2, hz_out0, hz_out4, hz_out2, hz_out6, hz_out4, 8, hz_out1, + hz_out3, hz_out5); hz_out7 = (v8u16) __msa_pckod_d((v2i64) hz_out8, (v2i64) hz_out6); ILVEV_B2_UB(hz_out0, hz_out1, hz_out2, hz_out3, vec0, vec1); @@ -3146,7 +3146,7 @@ for (loop_cnt = height; loop_cnt--;) { LD_SB4(src, 16, src0, src2, src4, src6); src7 = LD_SB(src + 56); - SLDI_B3_SB(src2, src4, src6, src0, src2, src4, src1, src3, src5, 8); + SLDI_B3_SB(src2, src0, src4, src2, src6, src4, 8, src1, src3, src5); src += src_stride; VSHF_B2_UB(src0, src0, src1, src1, mask, mask, vec0, vec1); @@ -3655,8 +3655,8 @@ hz_out4 = HORIZ_2TAP_FILT_UH(src4, src5, mask, filt_hz, 7); hz_out6 = HORIZ_2TAP_FILT_UH(src6, src7, mask, filt_hz, 7); hz_out8 = HORIZ_2TAP_FILT_UH(src8, src8, mask, filt_hz, 7); - SLDI_B3_UH(hz_out2, hz_out4, hz_out6, hz_out0, hz_out2, hz_out4, hz_out1, - hz_out3, hz_out5, 8); + SLDI_B3_UH(hz_out2, hz_out0, hz_out4, hz_out2, hz_out6, hz_out4, 8, hz_out1, + hz_out3, hz_out5); hz_out7 = (v8u16) __msa_pckod_d((v2i64) hz_out8, (v2i64) hz_out6); LW4(dst, dst_stride, tp0, tp1, tp2, tp3); diff -Nru ffmpeg-4.2.2/libavcodec/mips/wmv2dsp_init_mips.c ffmpeg-4.4/libavcodec/mips/wmv2dsp_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/wmv2dsp_init_mips.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/wmv2dsp_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,21 +18,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "config.h" #include "libavutil/attributes.h" #include "wmv2dsp_mips.h" -#if HAVE_MMI -static av_cold void wmv2dsp_init_mmi(WMV2DSPContext *c) -{ - c->idct_add = ff_wmv2_idct_add_mmi; - c->idct_put = ff_wmv2_idct_put_mmi; -} -#endif /* HAVE_MMI */ - av_cold void ff_wmv2dsp_init_mips(WMV2DSPContext *c) { -#if HAVE_MMI - wmv2dsp_init_mmi(c); -#endif /* HAVE_MMI */ + int cpu_flags = av_get_cpu_flags(); + + if (have_mmi(cpu_flags)) { + c->idct_add = ff_wmv2_idct_add_mmi; + c->idct_put = ff_wmv2_idct_put_mmi; + } } diff -Nru ffmpeg-4.2.2/libavcodec/mips/wmv2dsp_mips.h ffmpeg-4.4/libavcodec/mips/wmv2dsp_mips.h --- ffmpeg-4.2.2/libavcodec/mips/wmv2dsp_mips.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/wmv2dsp_mips.h 2021-04-08 21:28:39.000000000 +0000 @@ -23,7 +23,7 @@ #include "libavcodec/wmv2dsp.h" -void ff_wmv2_idct_add_mmi(uint8_t *dest, int line_size, int16_t *block); -void ff_wmv2_idct_put_mmi(uint8_t *dest, int line_size, int16_t *block); +void ff_wmv2_idct_add_mmi(uint8_t *dest, ptrdiff_t line_size, int16_t *block); +void ff_wmv2_idct_put_mmi(uint8_t *dest, ptrdiff_t line_size, int16_t *block); #endif /* AVCODEC_MIPS_WMV2DSP_MIPS_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mips/wmv2dsp_mmi.c ffmpeg-4.4/libavcodec/mips/wmv2dsp_mmi.c --- ffmpeg-4.2.2/libavcodec/mips/wmv2dsp_mmi.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/wmv2dsp_mmi.c 2021-04-08 21:28:39.000000000 +0000 @@ -95,7 +95,7 @@ b[56] = (a0 + a2 - a1 - a5 + 8192) >> 14; } -void ff_wmv2_idct_add_mmi(uint8_t *dest, int line_size, int16_t *block) +void ff_wmv2_idct_add_mmi(uint8_t *dest, ptrdiff_t line_size, int16_t *block) { int i; double ftmp[11]; @@ -212,7 +212,7 @@ ); } -void ff_wmv2_idct_put_mmi(uint8_t *dest, int line_size, int16_t *block) +void ff_wmv2_idct_put_mmi(uint8_t *dest, ptrdiff_t line_size, int16_t *block) { int i; double ftmp[8]; diff -Nru ffmpeg-4.2.2/libavcodec/mips/xvididct_init_mips.c ffmpeg-4.4/libavcodec/mips/xvididct_init_mips.c --- ffmpeg-4.2.2/libavcodec/mips/xvididct_init_mips.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/xvididct_init_mips.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,28 +18,23 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mips/cpu.h" #include "xvididct_mips.h" -#if HAVE_MMI -static av_cold void xvid_idct_init_mmi(IDCTDSPContext *c, AVCodecContext *avctx, +av_cold void ff_xvid_idct_init_mips(IDCTDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth) { - if (!high_bit_depth) { - if (avctx->idct_algo == FF_IDCT_AUTO || - avctx->idct_algo == FF_IDCT_XVID) { - c->idct_put = ff_xvid_idct_put_mmi; - c->idct_add = ff_xvid_idct_add_mmi; - c->idct = ff_xvid_idct_mmi; - c->perm_type = FF_IDCT_PERM_NONE; + int cpu_flags = av_get_cpu_flags(); + + if (have_mmi(cpu_flags)) { + if (!high_bit_depth) { + if (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_XVID) { + c->idct_put = ff_xvid_idct_put_mmi; + c->idct_add = ff_xvid_idct_add_mmi; + c->idct = ff_xvid_idct_mmi; + c->perm_type = FF_IDCT_PERM_NONE; + } } } } -#endif /* HAVE_MMI */ - -av_cold void ff_xvid_idct_init_mips(IDCTDSPContext *c, AVCodecContext *avctx, - unsigned high_bit_depth) -{ -#if HAVE_MMI - xvid_idct_init_mmi(c, avctx, high_bit_depth); -#endif /* HAVE_MMI */ -} diff -Nru ffmpeg-4.2.2/libavcodec/mips/xvididct_mips.h ffmpeg-4.4/libavcodec/mips/xvididct_mips.h --- ffmpeg-4.2.2/libavcodec/mips/xvididct_mips.h 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/xvididct_mips.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,7 +24,7 @@ #include "libavcodec/xvididct.h" void ff_xvid_idct_mmi(int16_t *block); -void ff_xvid_idct_put_mmi(uint8_t *dest, int32_t line_size, int16_t *block); -void ff_xvid_idct_add_mmi(uint8_t *dest, int32_t line_size, int16_t *block); +void ff_xvid_idct_put_mmi(uint8_t *dest, ptrdiff_t line_size, int16_t *block); +void ff_xvid_idct_add_mmi(uint8_t *dest, ptrdiff_t line_size, int16_t *block); #endif /* AVCODEC_MIPS_XVIDIDCT_MIPS_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mips/xvid_idct_mmi.c ffmpeg-4.4/libavcodec/mips/xvid_idct_mmi.c --- ffmpeg-4.2.2/libavcodec/mips/xvid_idct_mmi.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mips/xvid_idct_mmi.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mem_internal.h" + #include "idctdsp_mips.h" #include "xvididct_mips.h" @@ -240,13 +242,13 @@ ); } -void ff_xvid_idct_put_mmi(uint8_t *dest, int32_t line_size, int16_t *block) +void ff_xvid_idct_put_mmi(uint8_t *dest, ptrdiff_t line_size, int16_t *block) { ff_xvid_idct_mmi(block); ff_put_pixels_clamped_mmi(block, dest, line_size); } -void ff_xvid_idct_add_mmi(uint8_t *dest, int32_t line_size, int16_t *block) +void ff_xvid_idct_add_mmi(uint8_t *dest, ptrdiff_t line_size, int16_t *block) { ff_xvid_idct_mmi(block); ff_add_pixels_clamped_mmi(block, dest, line_size); diff -Nru ffmpeg-4.2.2/libavcodec/mjpeg2jpeg_bsf.c ffmpeg-4.4/libavcodec/mjpeg2jpeg_bsf.c --- ffmpeg-4.2.2/libavcodec/mjpeg2jpeg_bsf.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mjpeg2jpeg_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -27,11 +27,10 @@ #include #include "libavutil/error.h" -#include "libavutil/mem.h" #include "libavutil/intreadwrite.h" -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "jpegtables.h" #include "mjpeg.h" diff -Nru ffmpeg-4.2.2/libavcodec/mjpega_dump_header_bsf.c ffmpeg-4.4/libavcodec/mjpega_dump_header_bsf.c --- ffmpeg-4.2.2/libavcodec/mjpega_dump_header_bsf.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mjpega_dump_header_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -25,8 +25,8 @@ * modifies bitstream to be decoded by quicktime */ -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "bytestream.h" #include "mjpeg.h" diff -Nru ffmpeg-4.2.2/libavcodec/mjpegbdec.c ffmpeg-4.4/libavcodec/mjpegbdec.c --- ffmpeg-4.2.2/libavcodec/mjpegbdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mjpegbdec.c 2021-04-08 21:28:27.000000000 +0000 @@ -56,6 +56,7 @@ buf_ptr = buf; buf_end = buf + buf_size; s->got_picture = 0; + s->adobe_transform = -1; read_header: /* reset on every SOI */ @@ -162,5 +163,5 @@ .decode = mjpegb_decode_frame, .capabilities = AV_CODEC_CAP_DR1, .max_lowres = 3, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/mjpegdec.c ffmpeg-4.4/libavcodec/mjpegdec.c --- ffmpeg-4.2.2/libavcodec/mjpegdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mjpegdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -36,7 +36,8 @@ #include "avcodec.h" #include "blockdsp.h" #include "copy_block.h" -#include "hwaccel.h" +#include "decode.h" +#include "hwconfig.h" #include "idctdsp.h" #include "internal.h" #include "jpegtables.h" @@ -50,29 +51,6 @@ #include "bytestream.h" -static int build_vlc(VLC *vlc, const uint8_t *bits_table, - const uint8_t *val_table, int nb_codes, - int use_static, int is_ac) -{ - uint8_t huff_size[256] = { 0 }; - uint16_t huff_code[256]; - uint16_t huff_sym[256]; - int i; - - av_assert0(nb_codes <= 256); - - ff_mjpeg_build_huffman_codes(huff_size, huff_code, bits_table, val_table); - - for (i = 0; i < 256; i++) - huff_sym[i] = i + 16 * is_ac; - - if (is_ac) - huff_sym[0] = 16 * 256; - - return ff_init_vlc_sparse(vlc, 9, nb_codes, huff_size, 1, 1, - huff_code, 2, 2, huff_sym, 2, 2, use_static); -} - static int init_default_huffman_tables(MJpegDecodeContext *s) { static const struct { @@ -80,28 +58,28 @@ int index; const uint8_t *bits; const uint8_t *values; - int codes; int length; } ht[] = { { 0, 0, avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc, 12, 12 }, + avpriv_mjpeg_val_dc, 12 }, { 0, 1, avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc, 12, 12 }, + avpriv_mjpeg_val_dc, 12 }, { 1, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance, 251, 162 }, + avpriv_mjpeg_val_ac_luminance, 162 }, { 1, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance, 251, 162 }, + avpriv_mjpeg_val_ac_chrominance, 162 }, { 2, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance, 251, 162 }, + avpriv_mjpeg_val_ac_luminance, 162 }, { 2, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance, 251, 162 }, + avpriv_mjpeg_val_ac_chrominance, 162 }, }; int i, ret; for (i = 0; i < FF_ARRAY_ELEMS(ht); i++) { - ret = build_vlc(&s->vlcs[ht[i].class][ht[i].index], - ht[i].bits, ht[i].values, ht[i].codes, - 0, ht[i].class == 1); + ff_free_vlc(&s->vlcs[ht[i].class][ht[i].index]); + ret = ff_mjpeg_build_vlc(&s->vlcs[ht[i].class][ht[i].index], + ht[i].bits, ht[i].values, + ht[i].class == 1, s->avctx); if (ret < 0) return ret; @@ -148,6 +126,10 @@ s->picture_ptr = s->picture; } + s->pkt = av_packet_alloc(); + if (!s->pkt) + return AVERROR(ENOMEM); + s->avctx = avctx; ff_blockdsp_init(&s->bdsp, avctx); ff_hpeldsp_init(&s->hdsp, avctx->flags); @@ -157,7 +139,7 @@ s->start_code = -1; s->first_picture = 1; s->got_picture = 0; - s->org_height = avctx->coded_height; + s->orig_height = avctx->coded_height; avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; avctx->colorspace = AVCOL_SPC_BT470BG; s->hwaccel_pix_fmt = s->hwaccel_sw_pix_fmt = AV_PIX_FMT_NONE; @@ -172,7 +154,8 @@ if (ff_mjpeg_decode_dht(s)) { av_log(avctx, AV_LOG_ERROR, "error using external huffman table, switching back to internal\n"); - init_default_huffman_tables(s); + if ((ret = init_default_huffman_tables(s)) < 0) + return ret; } } if (avctx->field_order == AV_FIELD_BB) { /* quicktime icefloe 019 */ @@ -183,7 +166,19 @@ s->interlace_polarity = 1; } - if ( avctx->extradata_size > 8 + if (avctx->codec_id == AV_CODEC_ID_SMVJPEG) { + if (avctx->extradata_size >= 4) + s->smv_frames_per_jpeg = AV_RL32(avctx->extradata); + + if (s->smv_frames_per_jpeg <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of frames per jpeg.\n"); + return AVERROR_INVALIDDATA; + } + + s->smv_frame = av_frame_alloc(); + if (!s->smv_frame) + return AVERROR(ENOMEM); + } else if (avctx->extradata_size > 8 && AV_RL32(avctx->extradata) == 0x2C && AV_RL32(avctx->extradata+4) == 0x18) { parse_avid(s, avctx->extradata, avctx->extradata_size); @@ -240,7 +235,7 @@ /* decode huffman tables and build VLC decoders */ int ff_mjpeg_decode_dht(MJpegDecodeContext *s) { - int len, index, i, class, n, v, code_max; + int len, index, i, class, n, v; uint8_t bits_table[17]; uint8_t val_table[256]; int ret = 0; @@ -270,11 +265,8 @@ if (len < n || n > 256) return AVERROR_INVALIDDATA; - code_max = 0; for (i = 0; i < n; i++) { v = get_bits(&s->gb, 8); - if (v > code_max) - code_max = v; val_table[i] = v; } len -= n; @@ -282,15 +274,15 @@ /* build VLC and flush previous vlc if present */ ff_free_vlc(&s->vlcs[class][index]); av_log(s->avctx, AV_LOG_DEBUG, "class=%d index=%d nb_codes=%d\n", - class, index, code_max + 1); - if ((ret = build_vlc(&s->vlcs[class][index], bits_table, val_table, - code_max + 1, 0, class > 0)) < 0) + class, index, n); + if ((ret = ff_mjpeg_build_vlc(&s->vlcs[class][index], bits_table, + val_table, class > 0, s->avctx)) < 0) return ret; if (class > 0) { ff_free_vlc(&s->vlcs[2][index]); - if ((ret = build_vlc(&s->vlcs[2][index], bits_table, val_table, - code_max + 1, 0, 0)) < 0) + if ((ret = ff_mjpeg_build_vlc(&s->vlcs[2][index], bits_table, + val_table, 0, s->avctx)) < 0) return ret; } @@ -412,6 +404,18 @@ return AVERROR_PATCHWELCOME; } + if (s->bayer) { + if (nb_components == 2) { + /* Bayer images embedded in DNGs can contain 2 interleaved components and the + width stored in their SOF3 markers is the width of each one. We only output + a single component, therefore we need to adjust the output image width. We + handle the deinterleaving (but not the debayering) in this file. */ + width *= 2; + } + /* They can also contain 1 component, which is double the width and half the height + of the final image (rows are interleaved). We don't handle the decoding in this + file, but leave that to the TIFF/DNG decoder. */ + } /* if different size, realloc/alloc picture */ if (width != s->width || height != s->height || bits != s->bits || @@ -430,8 +434,8 @@ /* test interlaced mode */ if (s->first_picture && (s->multiscope != 2 || s->avctx->time_base.den >= 25 * s->avctx->time_base.num) && - s->org_height != 0 && - s->height < ((s->org_height * 3) / 4)) { + s->orig_height != 0 && + s->height < ((s->orig_height * 3) / 4)) { s->interlaced = 1; s->bottom_field = s->interlace_polarity; s->picture_ptr->interlaced_frame = 1; @@ -443,11 +447,22 @@ if (ret < 0) return ret; + if ((s->avctx->codec_tag == MKTAG('A', 'V', 'R', 'n') || + s->avctx->codec_tag == MKTAG('A', 'V', 'D', 'J')) && + s->orig_height < height) + s->avctx->height = AV_CEIL_RSHIFT(s->orig_height, s->avctx->lowres); + s->first_picture = 0; } else { size_change = 0; } + if (s->avctx->codec_id == AV_CODEC_ID_SMVJPEG) { + s->avctx->height = s->avctx->coded_height / s->smv_frames_per_jpeg; + if (s->avctx->height <= 0) + return AVERROR_INVALIDDATA; + } + if (s->got_picture && s->interlaced && (s->bottom_field == !s->interlace_polarity)) { if (s->progressive) { avpriv_request_sample(s->avctx, "progressively coded interlaced picture"); @@ -487,7 +502,17 @@ } } + if (s->bayer) { + if (pix_fmt_id != 0x11110000 && pix_fmt_id != 0x11000000) + goto unk_pixfmt; + } + switch (pix_fmt_id) { + case 0x11110000: /* for bayer-encoded huffman lossless JPEGs embedded in DNGs */ + if (!s->bayer) + goto unk_pixfmt; + s->avctx->pix_fmt = AV_PIX_FMT_GRAY16LE; + break; case 0x11111100: if (s->rgb) s->avctx->pix_fmt = s->bits <= 9 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_BGR48; @@ -538,11 +563,6 @@ case 0x22122100: case 0x21211100: case 0x22211200: - if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P; - else - goto unk_pixfmt; - s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; - break; case 0x22221100: case 0x22112200: case 0x11222200: @@ -1041,17 +1061,24 @@ return reset; } +/* Handles 1 to 4 components */ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int predictor, int point_transform) { int i, mb_x, mb_y; + unsigned width; uint16_t (*buffer)[4]; int left[4], top[4], topleft[4]; const int linesize = s->linesize[0]; const int mask = ((1 << s->bits) - 1) << point_transform; int resync_mb_y = 0; int resync_mb_x = 0; + int vpred[6]; - if (s->nb_components != 3 && s->nb_components != 4) + if (!s->bayer && s->nb_components < 3) + return AVERROR_INVALIDDATA; + if (s->bayer && s->nb_components > 2) + return AVERROR_INVALIDDATA; + if (s->nb_components <= 0 || s->nb_components > 4) return AVERROR_INVALIDDATA; if (s->v_max != 1 || s->h_max != 1 || !s->lossless) return AVERROR_INVALIDDATA; @@ -1059,8 +1086,15 @@ s->restart_count = s->restart_interval; - av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size, - (unsigned)s->mb_width * 4 * sizeof(s->ljpeg_buffer[0][0])); + if (s->restart_interval == 0) + s->restart_interval = INT_MAX; + + if (s->bayer) + width = s->mb_width / nb_components; /* Interleaved, width stored is the total so need to divide */ + else + width = s->mb_width; + + av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size, width * 4 * sizeof(s->ljpeg_buffer[0][0])); if (!s->ljpeg_buffer) return AVERROR(ENOMEM); @@ -1078,7 +1112,12 @@ for (i = 0; i < 4; i++) top[i] = left[i] = topleft[i] = buffer[0][i]; - for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + if ((mb_y * s->width) % s->restart_interval == 0) { + for (i = 0; i < 6; i++) + vpred[i] = 1 << (s->bits-1); + } + + for (mb_x = 0; mb_x < width; mb_x++) { int modified_predictor = predictor; if (get_bits_left(&s->gb) < 1) { @@ -1102,12 +1141,19 @@ topleft[i] = top[i]; top[i] = buffer[mb_x][i]; - PREDICT(pred, topleft[i], top[i], left[i], modified_predictor); - dc = mjpeg_decode_dc(s, s->dc_index[i]); if(dc == 0xFFFFF) return -1; + if (!s->bayer || mb_x) { + pred = left[i]; + } else { /* This path runs only for the first line in bayer images */ + vpred[i] += dc; + pred = vpred[i] - dc; + } + + PREDICT(pred, topleft[i], top[i], pred, modified_predictor); + left[i] = buffer[mb_x][i] = mask & (pred + (unsigned)(dc * (1 << point_transform))); } @@ -1151,6 +1197,17 @@ ptr[3*mb_x + 0] = buffer[mb_x][1] + ptr[3*mb_x + 1]; ptr[3*mb_x + 2] = buffer[mb_x][2] + ptr[3*mb_x + 1]; } + } else if (s->bayer) { + if (nb_components == 1) { + /* Leave decoding to the TIFF/DNG decoder (see comment in ff_mjpeg_decode_sof) */ + for (mb_x = 0; mb_x < width; mb_x++) + ((uint16_t*)ptr)[mb_x] = buffer[mb_x][0]; + } else if (nb_components == 2) { + for (mb_x = 0; mb_x < width; mb_x++) { + ((uint16_t*)ptr)[2*mb_x + 0] = buffer[mb_x][0]; + ((uint16_t*)ptr)[2*mb_x + 1] = buffer[mb_x][1]; + } + } } else { for(i=0; icomp_index[i]; @@ -1695,7 +1752,7 @@ point_transform, ilv)) < 0) return ret; } else { - if (s->rgb) { + if (s->rgb || s->bayer) { if ((ret = ljpeg_decode_rgb_scan(s, nb_components, predictor, point_transform)) < 0) return ret; } else { @@ -1759,8 +1816,15 @@ int len, id, i; len = get_bits(&s->gb, 16); - if (len < 6) - return AVERROR_INVALIDDATA; + if (len < 6) { + if (s->bayer) { + // Pentax K-1 (digital camera) JPEG images embedded in DNG images contain unknown APP0 markers + av_log(s->avctx, AV_LOG_WARNING, "skipping APPx (len=%"PRId32") for bayer-encoded image\n", len); + skip_bits(&s->gb, len); + return 0; + } else + return AVERROR_INVALIDDATA; + } if (8 * len > get_bits_left(&s->gb)) return AVERROR_INVALIDDATA; @@ -1993,7 +2057,7 @@ unsigned nummarkers; id = get_bits_long(&s->gb, 32); - id2 = get_bits_long(&s->gb, 24); + id2 = get_bits(&s->gb, 24); len -= 7; if (id != AV_RB32("PROF") || id2 != AV_RB24("ILE")) { av_log(s->avctx, AV_LOG_WARNING, "Invalid ICC_PROFILE header in APP2\n"); @@ -2023,28 +2087,26 @@ /* Allocate if this is the first APP2 we've seen. */ if (s->iccnum == 0) { - s->iccdata = av_mallocz(nummarkers * sizeof(*(s->iccdata))); - s->iccdatalens = av_mallocz(nummarkers * sizeof(*(s->iccdatalens))); - if (!s->iccdata || !s->iccdatalens) { + if (!FF_ALLOCZ_TYPED_ARRAY(s->iccentries, nummarkers)) { av_log(s->avctx, AV_LOG_ERROR, "Could not allocate ICC data arrays\n"); return AVERROR(ENOMEM); } s->iccnum = nummarkers; } - if (s->iccdata[seqno - 1]) { + if (s->iccentries[seqno - 1].data) { av_log(s->avctx, AV_LOG_WARNING, "Duplicate ICC sequence number\n"); goto out; } - s->iccdatalens[seqno - 1] = len; - s->iccdata[seqno - 1] = av_malloc(len); - if (!s->iccdata[seqno - 1]) { + s->iccentries[seqno - 1].length = len; + s->iccentries[seqno - 1].data = av_malloc(len); + if (!s->iccentries[seqno - 1].data) { av_log(s->avctx, AV_LOG_ERROR, "Could not allocate ICC data buffer\n"); return AVERROR(ENOMEM); } - memcpy(s->iccdata[seqno - 1], align_get_bits(&s->gb), len); + memcpy(s->iccentries[seqno - 1].data, align_get_bits(&s->gb), len); skip_bits(&s->gb, len << 3); len = 0; s->iccread++; @@ -2253,22 +2315,78 @@ { int i; - if (s->iccdata) + if (s->iccentries) { for (i = 0; i < s->iccnum; i++) - av_freep(&s->iccdata[i]); - av_freep(&s->iccdata); - av_freep(&s->iccdatalens); + av_freep(&s->iccentries[i].data); + av_freep(&s->iccentries); + } s->iccread = 0; s->iccnum = 0; } -int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +// SMV JPEG just stacks several output frames into one JPEG picture +// we handle that by setting up the cropping parameters appropriately +static int smv_process_frame(AVCodecContext *avctx, AVFrame *frame) +{ + MJpegDecodeContext *s = avctx->priv_data; + int ret; + + if (s->smv_next_frame > 0) { + av_assert0(s->smv_frame->buf[0]); + av_frame_unref(frame); + ret = av_frame_ref(frame, s->smv_frame); + if (ret < 0) + return ret; + } else { + av_assert0(frame->buf[0]); + av_frame_unref(s->smv_frame); + ret = av_frame_ref(s->smv_frame, frame); + if (ret < 0) + return ret; + } + + av_assert0((s->smv_next_frame + 1) * avctx->height <= avctx->coded_height); + + frame->width = avctx->coded_width; + frame->height = avctx->coded_height; + frame->crop_top = FFMIN(s->smv_next_frame * avctx->height, frame->height); + frame->crop_bottom = frame->height - (s->smv_next_frame + 1) * avctx->height; + + s->smv_next_frame = (s->smv_next_frame + 1) % s->smv_frames_per_jpeg; + + if (s->smv_next_frame == 0) + av_frame_unref(s->smv_frame); + + return 0; +} + +static int mjpeg_get_packet(AVCodecContext *avctx) +{ + MJpegDecodeContext *s = avctx->priv_data; + int ret; + + av_packet_unref(s->pkt); + ret = ff_decode_get_packet(avctx, s->pkt); + if (ret < 0) + return ret; + +#if CONFIG_SP5X_DECODER || CONFIG_AMV_DECODER + if (avctx->codec_id == AV_CODEC_ID_SP5X || + avctx->codec_id == AV_CODEC_ID_AMV) { + ret = ff_sp5x_process_packet(avctx, s->pkt); + if (ret < 0) + return ret; + } +#endif + + s->buf_size = s->pkt->size; + + return 0; +} + +int ff_mjpeg_receive_frame(AVCodecContext *avctx, AVFrame *frame) { - AVFrame *frame = data; - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; MJpegDecodeContext *s = avctx->priv_data; const uint8_t *buf_end, *buf_ptr; const uint8_t *unescaped_buf_ptr; @@ -2279,7 +2397,8 @@ int ret = 0; int is16bit; - s->buf_size = buf_size; + if (avctx->codec_id == AV_CODEC_ID_SMVJPEG && s->smv_next_frame > 0) + return smv_process_frame(avctx, frame); av_dict_free(&s->exif_metadata); av_freep(&s->stereo3d); @@ -2288,8 +2407,12 @@ if (s->iccnum != 0) reset_icc_profile(s); - buf_ptr = buf; - buf_end = buf + buf_size; + ret = mjpeg_get_packet(avctx); + if (ret < 0) + return ret; + + buf_ptr = s->pkt->data; + buf_end = s->pkt->data + s->pkt->size; while (buf_ptr < buf_end) { /* find start next marker */ start_code = ff_mjpeg_find_marker(s, &buf_ptr, buf_end, @@ -2301,7 +2424,7 @@ } else if (unescaped_buf_size > INT_MAX / 8) { av_log(avctx, AV_LOG_ERROR, "MJPEG packet 0x%x too big (%d/%d), corrupt data?\n", - start_code, unescaped_buf_size, buf_size); + start_code, unescaped_buf_size, s->pkt->size); return AVERROR_INVALIDDATA; } av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%"PTRDIFF_SPECIFIER"\n", @@ -2438,6 +2561,7 @@ } if (avctx->skip_frame == AVDISCARD_ALL) { s->got_picture = 0; + ret = AVERROR(EAGAIN); goto the_end_no_picture; } if (s->avctx->hwaccel) { @@ -2449,22 +2573,16 @@ } if ((ret = av_frame_ref(frame, s->picture_ptr)) < 0) return ret; - *got_frame = 1; s->got_picture = 0; - if (!s->lossless) { + frame->pkt_dts = s->pkt->dts; + + if (!s->lossless && avctx->debug & FF_DEBUG_QP) { int qp = FFMAX3(s->qscale[0], s->qscale[1], s->qscale[2]); - int qpw = (s->width + 15) / 16; - AVBufferRef *qp_table_buf = av_buffer_alloc(qpw); - if (qp_table_buf) { - memset(qp_table_buf->data, qp, qpw); - av_frame_set_qp_table(data, qp_table_buf, 0, FF_QSCALE_TYPE_MPEG1); - } - if(avctx->debug & FF_DEBUG_QP) - av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", qp); + av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", qp); } goto the_end; @@ -2701,7 +2819,7 @@ } if (s->stereo3d) { - AVStereo3D *stereo = av_stereo3d_create_side_data(data); + AVStereo3D *stereo = av_stereo3d_create_side_data(frame); if (stereo) { stereo->type = s->stereo3d->type; stereo->flags = s->stereo3d->flags; @@ -2717,9 +2835,9 @@ /* Sum size of all parts. */ for (i = 0; i < s->iccnum; i++) - total_size += s->iccdatalens[i]; + total_size += s->iccentries[i].length; - sd = av_frame_new_side_data(data, AV_FRAME_DATA_ICC_PROFILE, total_size); + sd = av_frame_new_side_data(frame, AV_FRAME_DATA_ICC_PROFILE, total_size); if (!sd) { av_log(s->avctx, AV_LOG_ERROR, "Could not allocate frame side data\n"); return AVERROR(ENOMEM); @@ -2727,21 +2845,39 @@ /* Reassemble the parts, which are now in-order. */ for (i = 0; i < s->iccnum; i++) { - memcpy(sd->data + offset, s->iccdata[i], s->iccdatalens[i]); - offset += s->iccdatalens[i]; + memcpy(sd->data + offset, s->iccentries[i].data, s->iccentries[i].length); + offset += s->iccentries[i].length; } } - av_dict_copy(&((AVFrame *) data)->metadata, s->exif_metadata, 0); + av_dict_copy(&frame->metadata, s->exif_metadata, 0); av_dict_free(&s->exif_metadata); + if (avctx->codec_id == AV_CODEC_ID_SMVJPEG) { + ret = smv_process_frame(avctx, frame); + if (ret < 0) { + av_frame_unref(frame); + return ret; + } + } + if ((avctx->codec_tag == MKTAG('A', 'V', 'R', 'n') || + avctx->codec_tag == MKTAG('A', 'V', 'D', 'J')) && + avctx->coded_height > s->orig_height) { + frame->height = AV_CEIL_RSHIFT(avctx->coded_height, avctx->lowres); + frame->crop_top = frame->height - avctx->height; + } + + ret = 0; + the_end_no_picture: av_log(avctx, AV_LOG_DEBUG, "decode frame unused %"PTRDIFF_SPECIFIER" bytes\n", buf_end - buf_ptr); -// return buf_end - buf_ptr; - return buf_ptr - buf; + + return ret; } +/* mxpeg may call the following function (with a blank MJpegDecodeContext) + * even without having called ff_mjpeg_decode_init(). */ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx) { MJpegDecodeContext *s = avctx->priv_data; @@ -2757,6 +2893,10 @@ } 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); av_freep(&s->stereo3d); av_freep(&s->ljpeg_buffer); @@ -2783,6 +2923,9 @@ { MJpegDecodeContext *s = avctx->priv_data; s->got_picture = 0; + + s->smv_next_frame = 0; + av_frame_unref(s->smv_frame); } #if CONFIG_MJPEG_DECODER @@ -2809,15 +2952,15 @@ .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, - .decode = ff_mjpeg_decode_frame, + .receive_frame = ff_mjpeg_receive_frame, .flush = decode_flush, .capabilities = AV_CODEC_CAP_DR1, .max_lowres = 3, .priv_class = &mjpegdec_class, .profiles = NULL_IF_CONFIG_SMALL(ff_mjpeg_profiles), - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | - FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, - .hw_configs = (const AVCodecHWConfigInternal*[]) { + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_SETS_PKT_DTS, + .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_MJPEG_NVDEC_HWACCEL HWACCEL_NVDEC(mjpeg), #endif @@ -2837,10 +2980,28 @@ .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, - .decode = ff_mjpeg_decode_frame, + .receive_frame = ff_mjpeg_receive_frame, .flush = decode_flush, .capabilities = AV_CODEC_CAP_DR1, .max_lowres = 3, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_SETS_PKT_DTS, +}; +#endif + +#if CONFIG_SMVJPEG_DECODER +AVCodec ff_smvjpeg_decoder = { + .name = "smvjpeg", + .long_name = NULL_IF_CONFIG_SMALL("SMV JPEG"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SMVJPEG, + .priv_data_size = sizeof(MJpegDecodeContext), + .init = ff_mjpeg_decode_init, + .close = ff_mjpeg_decode_end, + .receive_frame = ff_mjpeg_receive_frame, + .flush = decode_flush, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING | + FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/mjpegdec_common.c ffmpeg-4.4/libavcodec/mjpegdec_common.c --- ffmpeg-4.2.2/libavcodec/mjpegdec_common.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mjpegdec_common.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,57 @@ +/* + * MJPEG decoder VLC code + * 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 +#include "libavutil/avassert.h" +#include "mjpegdec.h" +#include "vlc.h" + +static int build_huffman_codes(uint8_t *huff_size, const uint8_t *bits_table) +{ + int nb_codes = 0; + for (int i = 1, j = 0; i <= 16; i++) { + nb_codes += bits_table[i]; + av_assert1(nb_codes <= 256); + for (; j < nb_codes; j++) + huff_size[j] = i; + } + return nb_codes; +} + +int ff_mjpeg_build_vlc(VLC *vlc, const uint8_t *bits_table, + const uint8_t *val_table, int is_ac, void *logctx) +{ + uint8_t huff_size[256]; + uint16_t huff_sym[256]; + int nb_codes = build_huffman_codes(huff_size, bits_table); + + for (int i = 0; i < nb_codes; i++) { + huff_sym[i] = val_table[i] + 16 * is_ac; + + if (is_ac && !val_table[i]) + huff_sym[i] = 16 * 256; + } + + return ff_init_vlc_from_lengths(vlc, 9, nb_codes, huff_size, 1, + huff_sym, 2, 2, 0, 0, logctx); +} diff -Nru ffmpeg-4.2.2/libavcodec/mjpegdec.h ffmpeg-4.4/libavcodec/mjpegdec.h --- ffmpeg-4.2.2/libavcodec/mjpegdec.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mjpegdec.h 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,7 @@ #define AVCODEC_MJPEGDEC_H #include "libavutil/log.h" +#include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" #include "libavutil/stereo3d.h" @@ -43,12 +44,19 @@ #define MAX_COMPONENTS 4 +typedef struct ICCEntry { + uint8_t *data; + int length; +} ICCEntry; + typedef struct MJpegDecodeContext { AVClass *class; AVCodecContext *avctx; GetBitContext gb; int buf_size; + AVPacket *pkt; + int start_code; /* current start code */ int buffer_size; uint8_t *buffer; @@ -57,13 +65,14 @@ VLC vlcs[3][4]; int qscale[4]; ///< quantizer scale calculated from quant_matrixes - int org_height; /* size given at codec init */ + int orig_height; /* size given at codec init */ int first_picture; /* true if decoding first picture */ int interlaced; /* true if interlaced */ int bottom_field; /* true if bottom field */ int lossless; int ls; int progressive; + int bayer; /* true if it's a bayer-encoded JPEG embedded in a DNG */ int rgb; uint8_t upscale_h[4]; uint8_t upscale_v[4]; @@ -134,11 +143,14 @@ const AVPixFmtDescriptor *pix_desc; - uint8_t **iccdata; - int *iccdatalens; + ICCEntry *iccentries; int iccnum; int iccread; + AVFrame *smv_frame; + int smv_frames_per_jpeg; + int smv_next_frame; + // Raw stream data for hwaccel use. const uint8_t *raw_image_buffer; size_t raw_image_buffer_size; @@ -153,11 +165,11 @@ void *hwaccel_picture_private; } MJpegDecodeContext; +int ff_mjpeg_build_vlc(VLC *vlc, const uint8_t *bits_table, + const uint8_t *val_table, int is_ac, void *logctx); int ff_mjpeg_decode_init(AVCodecContext *avctx); int ff_mjpeg_decode_end(AVCodecContext *avctx); -int ff_mjpeg_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt); +int ff_mjpeg_receive_frame(AVCodecContext *avctx, AVFrame *frame); int ff_mjpeg_decode_dqt(MJpegDecodeContext *s); int ff_mjpeg_decode_dht(MJpegDecodeContext *s); int ff_mjpeg_decode_sof(MJpegDecodeContext *s); @@ -168,4 +180,6 @@ const uint8_t **buf_ptr, const uint8_t *buf_end, const uint8_t **unescaped_buf_ptr, int *unescaped_buf_size); +int ff_sp5x_process_packet(AVCodecContext *avctx, AVPacket *avpkt); + #endif /* AVCODEC_MJPEGDEC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mjpegenc.c ffmpeg-4.4/libavcodec/mjpegenc.c --- ffmpeg-4.2.2/libavcodec/mjpegenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mjpegenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -35,11 +35,198 @@ #include "avcodec.h" #include "jpegtables.h" #include "mjpegenc_common.h" +#include "mjpegenc_huffman.h" #include "mpegvideo.h" #include "mjpeg.h" #include "mjpegenc.h" #include "profiles.h" +static av_cold void init_uni_ac_vlc(const uint8_t huff_size_ac[256], + uint8_t *uni_ac_vlc_len) +{ + for (int i = 0; i < 128; i++) { + int level = i - 64; + if (!level) + continue; + for (int run = 0; run < 64; run++) { + int len, code, nbits; + int alevel = FFABS(level); + + len = (run >> 4) * huff_size_ac[0xf0]; + + nbits= av_log2_16bit(alevel) + 1; + code = ((15&run) << 4) | nbits; + + len += huff_size_ac[code] + nbits; + + uni_ac_vlc_len[UNI_AC_ENC_INDEX(run, i)] = len; + // We ignore EOB as its just a constant which does not change generally + } + } +} + +/** + * Encodes and outputs the entire frame in the JPEG format. + * + * @param s The MpegEncContext. + */ +static void mjpeg_encode_picture_frame(MpegEncContext *s) +{ + int nbits, code, table_id; + MJpegContext *m = s->mjpeg_ctx; + uint8_t *huff_size[4] = { m->huff_size_dc_luminance, + m->huff_size_dc_chrominance, + m->huff_size_ac_luminance, + m->huff_size_ac_chrominance }; + uint16_t *huff_code[4] = { m->huff_code_dc_luminance, + m->huff_code_dc_chrominance, + m->huff_code_ac_luminance, + m->huff_code_ac_chrominance }; + size_t total_bits = 0; + size_t bytes_needed; + + s->header_bits = get_bits_diff(s); + // Estimate the total size first + for (int i = 0; i < m->huff_ncode; i++) { + table_id = m->huff_buffer[i].table_id; + code = m->huff_buffer[i].code; + nbits = code & 0xf; + + total_bits += huff_size[table_id][code] + nbits; + } + + bytes_needed = (total_bits + 7) / 8; + ff_mpv_reallocate_putbitbuffer(s, bytes_needed, bytes_needed); + + for (int i = 0; i < m->huff_ncode; i++) { + table_id = m->huff_buffer[i].table_id; + code = m->huff_buffer[i].code; + nbits = code & 0xf; + + put_bits(&s->pb, huff_size[table_id][code], huff_code[table_id][code]); + if (nbits != 0) { + put_sbits(&s->pb, nbits, m->huff_buffer[i].mant); + } + } + + m->huff_ncode = 0; + s->i_tex_bits = get_bits_diff(s); +} + +/** + * Builds all 4 optimal Huffman tables. + * + * Uses the data stored in the JPEG buffer to compute the tables. + * Stores the Huffman tables in the bits_* and val_* arrays in the MJpegContext. + * + * @param m MJpegContext containing the JPEG buffer. + */ +static void mjpeg_build_optimal_huffman(MJpegContext *m) +{ + MJpegEncHuffmanContext dc_luminance_ctx; + MJpegEncHuffmanContext dc_chrominance_ctx; + MJpegEncHuffmanContext ac_luminance_ctx; + MJpegEncHuffmanContext ac_chrominance_ctx; + MJpegEncHuffmanContext *ctx[4] = { &dc_luminance_ctx, + &dc_chrominance_ctx, + &ac_luminance_ctx, + &ac_chrominance_ctx }; + for (int i = 0; i < 4; i++) + ff_mjpeg_encode_huffman_init(ctx[i]); + + for (int i = 0; i < m->huff_ncode; i++) { + int table_id = m->huff_buffer[i].table_id; + int code = m->huff_buffer[i].code; + + ff_mjpeg_encode_huffman_increment(ctx[table_id], code); + } + + ff_mjpeg_encode_huffman_close(&dc_luminance_ctx, + m->bits_dc_luminance, + m->val_dc_luminance, 12); + ff_mjpeg_encode_huffman_close(&dc_chrominance_ctx, + m->bits_dc_chrominance, + m->val_dc_chrominance, 12); + ff_mjpeg_encode_huffman_close(&ac_luminance_ctx, + m->bits_ac_luminance, + m->val_ac_luminance, 256); + ff_mjpeg_encode_huffman_close(&ac_chrominance_ctx, + m->bits_ac_chrominance, + m->val_ac_chrominance, 256); + + ff_mjpeg_build_huffman_codes(m->huff_size_dc_luminance, + m->huff_code_dc_luminance, + m->bits_dc_luminance, + m->val_dc_luminance); + ff_mjpeg_build_huffman_codes(m->huff_size_dc_chrominance, + m->huff_code_dc_chrominance, + m->bits_dc_chrominance, + m->val_dc_chrominance); + ff_mjpeg_build_huffman_codes(m->huff_size_ac_luminance, + m->huff_code_ac_luminance, + m->bits_ac_luminance, + m->val_ac_luminance); + ff_mjpeg_build_huffman_codes(m->huff_size_ac_chrominance, + m->huff_code_ac_chrominance, + m->bits_ac_chrominance, + m->val_ac_chrominance); +} + +/** + * Writes the complete JPEG frame when optimal huffman tables are enabled, + * otherwise writes the stuffing. + * + * Header + values + stuffing. + * + * @param s The MpegEncContext. + * @return int Error code, 0 if successful. + */ +int ff_mjpeg_encode_stuffing(MpegEncContext *s) +{ + PutBitContext *pbc = &s->pb; + int mb_y = s->mb_y - !s->mb_x; + int ret; + MJpegContext *m; + + m = s->mjpeg_ctx; + + if (s->huffman == HUFFMAN_TABLE_OPTIMAL) { + mjpeg_build_optimal_huffman(m); + + // Replace the VLCs with the optimal ones. + // The default ones may be used for trellis during quantization. + 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); + s->intra_ac_vlc_length = + s->intra_ac_vlc_last_length = m->uni_ac_vlc_len; + 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_frame(s); + } + + ret = ff_mpv_reallocate_putbitbuffer(s, put_bits_count(&s->pb) / 8 + 100, + put_bits_count(&s->pb) / 4 + 1000); + if (ret < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Buffer reallocation failed\n"); + goto fail; + } + + ff_mjpeg_escape_FF(pbc, s->esc_pos); + + if ((s->avctx->active_thread_type & FF_THREAD_SLICE) && mb_y < s->mb_height - 1) + put_marker(pbc, RST0 + (mb_y&7)); + s->esc_pos = put_bits_count(pbc) >> 3; + +fail: + for (int i = 0; i < 3; i++) + s->last_dc[i] = 128 << s->intra_dc_precision; + + return ret; +} + static int alloc_huffman(MpegEncContext *s) { MJpegContext *m = s->mjpeg_ctx; @@ -106,8 +293,8 @@ avpriv_mjpeg_bits_ac_chrominance, avpriv_mjpeg_val_ac_chrominance); - ff_init_uni_ac_vlc(m->huff_size_ac_luminance, m->uni_ac_vlc_len); - ff_init_uni_ac_vlc(m->huff_size_ac_chrominance, m->uni_chroma_ac_vlc_len); + 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); s->intra_ac_vlc_length = s->intra_ac_vlc_last_length = m->uni_ac_vlc_len; s->intra_chroma_ac_vlc_length = @@ -125,8 +312,10 @@ av_cold void ff_mjpeg_encode_close(MpegEncContext *s) { - av_freep(&s->mjpeg_ctx->huff_buffer); - av_freep(&s->mjpeg_ctx); + if (s->mjpeg_ctx) { + av_freep(&s->mjpeg_ctx->huff_buffer); + av_freep(&s->mjpeg_ctx); + } } /** @@ -414,7 +603,8 @@ .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, - .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .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[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_NONE }, @@ -440,6 +630,7 @@ .init = ff_mpv_encode_init, .encode2 = amv_encode_picture, .close = ff_mpv_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_NONE }, diff -Nru ffmpeg-4.2.2/libavcodec/mjpegenc_common.c ffmpeg-4.4/libavcodec/mjpegenc_common.c --- ffmpeg-4.2.2/libavcodec/mjpegenc_common.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mjpegenc_common.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,7 +23,6 @@ #include #include -#include "libavutil/common.h" #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" @@ -33,35 +32,8 @@ #include "put_bits.h" #include "mjpegenc.h" #include "mjpegenc_common.h" -#include "mjpegenc_huffman.h" #include "mjpeg.h" -av_cold void ff_init_uni_ac_vlc(const uint8_t huff_size_ac[256], uint8_t *uni_ac_vlc_len) -{ - int i; - - for (i = 0; i < 128; i++) { - int level = i - 64; - int run; - if (!level) - continue; - for (run = 0; run < 64; run++) { - int len, code, nbits; - int alevel = FFABS(level); - - len = (run >> 4) * huff_size_ac[0xf0]; - - nbits= av_log2_16bit(alevel) + 1; - code = ((15&run) << 4) | nbits; - - len += huff_size_ac[code] + nbits; - - uni_ac_vlc_len[UNI_AC_ENC_INDEX(run, i)] = len; - // We ignore EOB as its just a constant which does not change generally - } - } -} - /* table_class: 0 = DC coef, 1 = AC coefs */ static int put_huffman_table(PutBitContext *p, int table_class, int table_id, const uint8_t *bits_table, const uint8_t *value_table) @@ -181,7 +153,7 @@ /* JFIF header */ put_marker(p, APP0); put_bits(p, 16, 16); - avpriv_put_string(p, "JFIF", 1); /* this puts the trailing zero-byte too */ + ff_put_string(p, "JFIF", 1); /* this puts the trailing zero-byte too */ /* The most significant byte is used for major revisions, the least * significant byte for minor revisions. Version 1.02 is the current * released revision. */ @@ -199,7 +171,7 @@ flush_put_bits(p); ptr = put_bits_ptr(p); put_bits(p, 16, 0); /* patched later */ - avpriv_put_string(p, LIBAVCODEC_IDENT, 1); + ff_put_string(p, LIBAVCODEC_IDENT, 1); size = strlen(LIBAVCODEC_IDENT)+3; AV_WB16(ptr, size); } @@ -212,7 +184,7 @@ flush_put_bits(p); ptr = put_bits_ptr(p); put_bits(p, 16, 0); /* patched later */ - avpriv_put_string(p, "CS=ITU601", 1); + ff_put_string(p, "CS=ITU601", 1); size = strlen("CS=ITU601")+3; AV_WB16(ptr, size); } @@ -359,54 +331,6 @@ } } -/** - * Encodes and outputs the entire frame in the JPEG format. - * - * @param s The MpegEncContext. - */ -void ff_mjpeg_encode_picture_frame(MpegEncContext *s) -{ - int i, nbits, code, table_id; - MJpegContext *m = s->mjpeg_ctx; - uint8_t *huff_size[4] = {m->huff_size_dc_luminance, - m->huff_size_dc_chrominance, - m->huff_size_ac_luminance, - m->huff_size_ac_chrominance}; - uint16_t *huff_code[4] = {m->huff_code_dc_luminance, - m->huff_code_dc_chrominance, - m->huff_code_ac_luminance, - m->huff_code_ac_chrominance}; - size_t total_bits = 0; - size_t bytes_needed; - - s->header_bits = get_bits_diff(s); - // Estimate the total size first - for (i = 0; i < m->huff_ncode; i++) { - table_id = m->huff_buffer[i].table_id; - code = m->huff_buffer[i].code; - nbits = code & 0xf; - - total_bits += huff_size[table_id][code] + nbits; - } - - bytes_needed = (total_bits + 7) / 8; - ff_mpv_reallocate_putbitbuffer(s, bytes_needed, bytes_needed); - - for (i = 0; i < m->huff_ncode; i++) { - table_id = m->huff_buffer[i].table_id; - code = m->huff_buffer[i].code; - nbits = code & 0xf; - - put_bits(&s->pb, huff_size[table_id][code], huff_code[table_id][code]); - if (nbits != 0) { - put_sbits(&s->pb, nbits, m->huff_buffer[i].mant); - } - } - - m->huff_ncode = 0; - s->i_tex_bits = get_bits_diff(s); -} - void ff_mjpeg_escape_FF(PutBitContext *pb, int start) { int size; @@ -466,122 +390,25 @@ } } -/** - * Builds all 4 optimal Huffman tables. - * - * Uses the data stored in the JPEG buffer to compute the tables. - * Stores the Huffman tables in the bits_* and val_* arrays in the MJpegContext. - * - * @param m MJpegContext containing the JPEG buffer. - */ -static void ff_mjpeg_build_optimal_huffman(MJpegContext *m) +/* isn't this function nicer than the one in the libjpeg ? */ +void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, + const uint8_t *bits_table, + const uint8_t *val_table) { - int i, table_id, code; + int k, code; - MJpegEncHuffmanContext dc_luminance_ctx; - MJpegEncHuffmanContext dc_chrominance_ctx; - MJpegEncHuffmanContext ac_luminance_ctx; - MJpegEncHuffmanContext ac_chrominance_ctx; - MJpegEncHuffmanContext *ctx[4] = {&dc_luminance_ctx, - &dc_chrominance_ctx, - &ac_luminance_ctx, - &ac_chrominance_ctx}; - for (i = 0; i < 4; i++) { - ff_mjpeg_encode_huffman_init(ctx[i]); - } - for (i = 0; i < m->huff_ncode; i++) { - table_id = m->huff_buffer[i].table_id; - code = m->huff_buffer[i].code; - - ff_mjpeg_encode_huffman_increment(ctx[table_id], code); - } - - ff_mjpeg_encode_huffman_close(&dc_luminance_ctx, - m->bits_dc_luminance, - m->val_dc_luminance, 12); - ff_mjpeg_encode_huffman_close(&dc_chrominance_ctx, - m->bits_dc_chrominance, - m->val_dc_chrominance, 12); - ff_mjpeg_encode_huffman_close(&ac_luminance_ctx, - m->bits_ac_luminance, - m->val_ac_luminance, 256); - ff_mjpeg_encode_huffman_close(&ac_chrominance_ctx, - m->bits_ac_chrominance, - m->val_ac_chrominance, 256); - - ff_mjpeg_build_huffman_codes(m->huff_size_dc_luminance, - m->huff_code_dc_luminance, - m->bits_dc_luminance, - m->val_dc_luminance); - ff_mjpeg_build_huffman_codes(m->huff_size_dc_chrominance, - m->huff_code_dc_chrominance, - m->bits_dc_chrominance, - m->val_dc_chrominance); - ff_mjpeg_build_huffman_codes(m->huff_size_ac_luminance, - m->huff_code_ac_luminance, - m->bits_ac_luminance, - m->val_ac_luminance); - ff_mjpeg_build_huffman_codes(m->huff_size_ac_chrominance, - m->huff_code_ac_chrominance, - m->bits_ac_chrominance, - m->val_ac_chrominance); -} - -/** - * Writes the complete JPEG frame when optimal huffman tables are enabled, - * otherwise writes the stuffing. - * - * Header + values + stuffing. - * - * @param s The MpegEncContext. - * @return int Error code, 0 if successful. - */ -int ff_mjpeg_encode_stuffing(MpegEncContext *s) -{ - int i; - PutBitContext *pbc = &s->pb; - int mb_y = s->mb_y - !s->mb_x; - int ret; - MJpegContext *m; - - m = s->mjpeg_ctx; - - if (s->huffman == HUFFMAN_TABLE_OPTIMAL) { - ff_mjpeg_build_optimal_huffman(m); - - // Replace the VLCs with the optimal ones. - // The default ones may be used for trellis during quantization. - ff_init_uni_ac_vlc(m->huff_size_ac_luminance, m->uni_ac_vlc_len); - ff_init_uni_ac_vlc(m->huff_size_ac_chrominance, m->uni_chroma_ac_vlc_len); - s->intra_ac_vlc_length = - s->intra_ac_vlc_last_length = m->uni_ac_vlc_len; - 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); - ff_mjpeg_encode_picture_frame(s); - } - - ret = ff_mpv_reallocate_putbitbuffer(s, put_bits_count(&s->pb) / 8 + 100, - put_bits_count(&s->pb) / 4 + 1000); - - if (ret < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Buffer reallocation failed\n"); - goto fail; + k = 0; + code = 0; + for (int i = 1; i <= 16; i++) { + int nb = bits_table[i]; + for (int j = 0; j < nb; j++) { + int sym = val_table[k++]; + huff_size[sym] = i; + huff_code[sym] = code; + code++; + } + code <<= 1; } - - ff_mjpeg_escape_FF(pbc, s->esc_pos); - - if((s->avctx->active_thread_type & FF_THREAD_SLICE) && mb_y < s->mb_height) - put_marker(pbc, RST0 + (mb_y&7)); - s->esc_pos = put_bits_count(pbc) >> 3; -fail: - - for(i=0; i<3; i++) - s->last_dc[i] = 128 << s->intra_dc_precision; - - return ret; } void ff_mjpeg_encode_picture_trailer(PutBitContext *pb, int header_bits) diff -Nru ffmpeg-4.2.2/libavcodec/mjpegenc_common.h ffmpeg-4.4/libavcodec/mjpegenc_common.h --- ffmpeg-4.2.2/libavcodec/mjpegenc_common.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mjpegenc_common.h 2021-04-08 21:28:39.000000000 +0000 @@ -25,22 +25,20 @@ #include "avcodec.h" #include "idctdsp.h" -#include "mpegvideo.h" #include "put_bits.h" void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, ScanTable *intra_scantable, int pred, uint16_t luma_intra_matrix[64], uint16_t chroma_intra_matrix[64]); -void ff_mjpeg_encode_picture_frame(MpegEncContext *s); void ff_mjpeg_encode_picture_trailer(PutBitContext *pb, int header_bits); void ff_mjpeg_escape_FF(PutBitContext *pb, int start); -int ff_mjpeg_encode_stuffing(MpegEncContext *s); +void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, + const uint8_t *bits_table, + const uint8_t *val_table); void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[4], int vsample[4]); void ff_mjpeg_encode_dc(PutBitContext *pb, int val, uint8_t *huff_size, uint16_t *huff_code); -av_cold void ff_init_uni_ac_vlc(const uint8_t huff_size_ac[256], uint8_t *uni_ac_vlc_len); - #endif /* AVCODEC_MJPEGENC_COMMON_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mjpegenc.h ffmpeg-4.4/libavcodec/mjpegenc.h --- ffmpeg-4.2.2/libavcodec/mjpegenc.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mjpegenc.h 2021-04-08 21:28:39.000000000 +0000 @@ -107,5 +107,6 @@ int ff_mjpeg_encode_init(MpegEncContext *s); void ff_mjpeg_encode_close(MpegEncContext *s); void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]); +int ff_mjpeg_encode_stuffing(MpegEncContext *s); #endif /* AVCODEC_MJPEGENC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mjpeg_parser.c ffmpeg-4.4/libavcodec/mjpeg_parser.c --- ffmpeg-4.2.2/libavcodec/mjpeg_parser.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mjpeg_parser.c 2020-07-11 10:39:32.000000000 +0000 @@ -50,7 +50,7 @@ for(i=0; i=0xFFC00000 && state<=0xFFFEFFFF){ - if(state>=0xFFD80000 && state<=0xFFD8FFFF){ + if(state>=0xFFD8FFC0 && state<=0xFFD8FFFF){ i++; vop_found=1; break; @@ -76,12 +76,14 @@ for(; i=0xFFC00000 && state<=0xFFFEFFFF){ - if(state>=0xFFD80000 && state<=0xFFD8FFFF){ + if(state>=0xFFD8FFC0 && state<=0xFFD8FFFF){ pc->frame_start_found=0; pc->state=0; return i-3; } else if(state<0xFFD00000 || state>0xFFD9FFFF){ m->size= (state&0xFFFF)-1; + if (m->size >= 0xF000) + m->size = 0; } } if(m->size>0){ diff -Nru ffmpeg-4.2.2/libavcodec/mlp.c ffmpeg-4.4/libavcodec/mlp.c --- ffmpeg-4.2.2/libavcodec/mlp.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mlp.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/crc.h" #include "libavutil/intreadwrite.h" +#include "libavutil/thread.h" #include "mlp.h" const uint8_t ff_mlp_huffman_tables[3][18][2] = { @@ -62,7 +63,6 @@ AV_CH_LAYOUT_4POINT1, AV_CH_LAYOUT_5POINT1_BACK, 0, }; -static int crc_init = 0; #if CONFIG_SMALL #define CRC_TABLE_SIZE 257 #else @@ -72,14 +72,17 @@ static AVCRC crc_1D[CRC_TABLE_SIZE]; static AVCRC crc_2D[CRC_TABLE_SIZE]; +static av_cold void mlp_init_crc(void) +{ + av_crc_init(crc_63, 0, 8, 0x63, sizeof(crc_63)); + av_crc_init(crc_1D, 0, 8, 0x1D, sizeof(crc_1D)); + av_crc_init(crc_2D, 0, 16, 0x002D, sizeof(crc_2D)); +} + av_cold void ff_mlp_init_crc(void) { - if (!crc_init) { - av_crc_init(crc_63, 0, 8, 0x63, sizeof(crc_63)); - av_crc_init(crc_1D, 0, 8, 0x1D, sizeof(crc_1D)); - av_crc_init(crc_2D, 0, 16, 0x002D, sizeof(crc_2D)); - crc_init = 1; - } + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, mlp_init_crc); } uint16_t ff_mlp_checksum16(const uint8_t *buf, unsigned int buf_size) diff -Nru ffmpeg-4.2.2/libavcodec/mlpdec.c ffmpeg-4.4/libavcodec/mlpdec.c --- ffmpeg-4.2.2/libavcodec/mlpdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mlpdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,8 @@ #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/channel_layout.h" +#include "libavutil/mem_internal.h" +#include "libavutil/thread.h" #include "get_bits.h" #include "internal.h" #include "libavutil/crc.h" @@ -205,16 +207,13 @@ static av_cold void init_static(void) { - if (!huff_vlc[0].bits) { - INIT_VLC_STATIC(&huff_vlc[0], VLC_BITS, 18, - &ff_mlp_huffman_tables[0][0][1], 2, 1, - &ff_mlp_huffman_tables[0][0][0], 2, 1, VLC_STATIC_SIZE); - INIT_VLC_STATIC(&huff_vlc[1], VLC_BITS, 16, - &ff_mlp_huffman_tables[1][0][1], 2, 1, - &ff_mlp_huffman_tables[1][0][0], 2, 1, VLC_STATIC_SIZE); - INIT_VLC_STATIC(&huff_vlc[2], VLC_BITS, 15, - &ff_mlp_huffman_tables[2][0][1], 2, 1, - &ff_mlp_huffman_tables[2][0][0], 2, 1, VLC_STATIC_SIZE); + for (int i = 0; i < 3; i++) { + static VLC_TYPE vlc_buf[3 * VLC_STATIC_SIZE][2]; + huff_vlc[i].table = &vlc_buf[i * VLC_STATIC_SIZE]; + huff_vlc[i].table_allocated = VLC_STATIC_SIZE; + init_vlc(&huff_vlc[i], VLC_BITS, 18, + &ff_mlp_huffman_tables[i][0][1], 2, 1, + &ff_mlp_huffman_tables[i][0][0], 2, 1, INIT_VLC_USE_NEW_STATIC); } ff_mlp_init_crc(); @@ -266,7 +265,7 @@ return AVERROR_INVALIDDATA; if (lsb_bits > 0) - result = (result << lsb_bits) + get_bits(gbp, lsb_bits); + result = (result << lsb_bits) + get_bits_long(gbp, lsb_bits); result += cp->sign_huff_offset; result *= 1 << quant_step_size; @@ -279,15 +278,17 @@ static av_cold int mlp_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; MLPDecodeContext *m = avctx->priv_data; int substr; - init_static(); m->avctx = avctx; for (substr = 0; substr < MAX_SUBSTREAMS; substr++) m->substream[substr].lossless_check_data = 0xffffffff; ff_mlpdsp_init(&m->dsp); + ff_thread_once(&init_static_once, init_static); + return 0; } @@ -829,7 +830,7 @@ cp->codebook = get_bits(gbp, 2); cp->huff_lsbs = get_bits(gbp, 5); - if (cp->huff_lsbs > 24) { + if (cp->codebook > 0 && cp->huff_lsbs > 24) { av_log(m->avctx, AV_LOG_ERROR, "Invalid huff_lsbs.\n"); cp->huff_lsbs = 0; return AVERROR_INVALIDDATA; @@ -1338,7 +1339,8 @@ .priv_data_size = sizeof(MLPDecodeContext), .init = mlp_decode_init, .decode = read_access_unit, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_TRUEHD_DECODER @@ -1350,6 +1352,7 @@ .priv_data_size = sizeof(MLPDecodeContext), .init = mlp_decode_init, .decode = read_access_unit, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif /* CONFIG_TRUEHD_DECODER */ diff -Nru ffmpeg-4.2.2/libavcodec/mlpdsp.c ffmpeg-4.4/libavcodec/mlpdsp.c --- ffmpeg-4.2.2/libavcodec/mlpdsp.c 2018-02-19 00:50:32.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mlpdsp.c 2020-07-04 22:36:04.000000000 +0000 @@ -79,7 +79,7 @@ if (matrix_noise_shift) { index &= access_unit_size_pow2 - 1; - accum += noise_buffer[index] << (matrix_noise_shift + 7); + accum += noise_buffer[index] * (1 << (matrix_noise_shift + 7)); index += index2; } diff -Nru ffmpeg-4.2.2/libavcodec/mlpenc.c ffmpeg-4.4/libavcodec/mlpenc.c --- ffmpeg-4.2.2/libavcodec/mlpenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mlpenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -1,6 +1,7 @@ /** * MLP encoder * Copyright (c) 2008 Ramiro Polla + * Copyright (c) 2016-2019 Jai Luthra * * This file is part of FFmpeg. * @@ -86,15 +87,15 @@ } DecodingParams; typedef struct BestOffset { - int16_t offset; + int32_t offset; int bitcount; int lsb_bits; - int16_t min; - int16_t max; + int32_t min; + int32_t max; } BestOffset; -#define HUFF_OFFSET_MIN -16384 -#define HUFF_OFFSET_MAX 16383 +#define HUFF_OFFSET_MIN (-16384) +#define HUFF_OFFSET_MAX ( 16383) /** Number of possible codebooks (counting "no codebooks") */ #define NUM_CODEBOOKS 4 @@ -466,7 +467,7 @@ */ static int inline number_sbits(int number) { - if (number < 0) + if (number < -1) number++; return av_log2(FFABS(number)) + 1 + !!number; @@ -530,7 +531,7 @@ av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate %d. Supported " "sample rates are 44100, 88200, 176400, 48000, " "96000, and 192000.\n", avctx->sample_rate); - return -1; + return AVERROR(EINVAL); } ctx->coded_sample_rate[1] = -1 & 0xf; @@ -563,7 +564,7 @@ default: av_log(avctx, AV_LOG_ERROR, "Sample format not supported. " "Only 16- and 24-bit samples are supported.\n"); - return -1; + return AVERROR(EINVAL); } ctx->coded_sample_fmt[1] = -1 & 0xf; @@ -637,7 +638,7 @@ ctx->channel_arrangement = 12; break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported channel arrangement\n"); - return -1; + return AVERROR(EINVAL); } ctx->flags = FLAGS_DVDA; ctx->channel_occupancy = ff_mlp_ch_info[ctx->channel_arrangement].channel_occupancy; @@ -665,7 +666,7 @@ break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported channel arrangement\n"); - return -1; + return AVERROR(EINVAL); } ctx->flags = 0; ctx->channel_occupancy = 0; @@ -807,7 +808,7 @@ static void write_restart_header(MLPEncodeContext *ctx, PutBitContext *pb) { RestartHeader *rh = ctx->cur_restart_header; - int32_t lossless_check = xor_32_to_8(rh->lossless_check_data); + uint8_t lossless_check = xor_32_to_8(rh->lossless_check_data); unsigned int start_count = put_bits_count(pb); PutBitContext tmpb; uint8_t checksum; @@ -986,6 +987,9 @@ put_bits(pb, 1, 0); } } + if (cp->codebook > 0 && cp->huff_lsbs > 24) { + av_log(ctx->avctx, AV_LOG_ERROR, "Invalid Huff LSBs\n"); + } put_bits(pb, 2, cp->codebook ); put_bits(pb, 5, cp->huff_lsbs); @@ -1016,12 +1020,10 @@ codebook_index [ch] = cp->codebook - 1; sign_huff_offset[ch] = cp->huff_offset; - sign_shift = lsb_bits[ch] - 1; + sign_shift = lsb_bits[ch] + (cp->codebook ? 2 - cp->codebook : -1); - if (cp->codebook > 0) { + if (cp->codebook > 0) sign_huff_offset[ch] -= 7 << lsb_bits[ch]; - sign_shift += 3 - cp->codebook; - } /* Unsign if needed. */ if (sign_shift >= 0) @@ -1031,7 +1033,6 @@ for (i = 0; i < dp->blocksize; i++) { for (ch = rh->min_channel; ch <= rh->max_channel; ch++) { int32_t sample = *sample_buffer++ >> dp->quant_step_size[ch]; - sample -= sign_huff_offset[ch]; if (codebook_index[ch] >= 0) { @@ -1189,7 +1190,7 @@ int total_length; if (buf_size < 4) - return -1; + return AVERROR(EINVAL); /* Frame header will be written at the end. */ buf += 4; @@ -1197,7 +1198,7 @@ if (restart_frame) { if (buf_size < 28) - return -1; + return AVERROR(EINVAL); write_major_sync(ctx, buf, buf_size); buf += 28; buf_size -= 28; @@ -1251,7 +1252,7 @@ uint32_t abs_sample; int32_t sample; - sample = is24 ? *samples_32++ >> 8 : *samples_16++ << 8; + sample = is24 ? *samples_32++ >> 8 : *samples_16++ * 256; /* TODO Find out if number_sbits can be used for negative values. */ abs_sample = FFABS(sample); @@ -1562,7 +1563,7 @@ BestOffset *bo) { DecodingParams *dp = ctx->cur_decoding_params; - int32_t unsign; + int32_t unsign = 0; int lsb_bits; min -= offset; @@ -1572,7 +1573,8 @@ lsb_bits += !!lsb_bits; - unsign = 1 << (lsb_bits - 1); + if (lsb_bits > 0) + unsign = 1 << (lsb_bits - 1); bo->offset = offset; bo->lsb_bits = lsb_bits; @@ -1591,7 +1593,7 @@ { DecodingParams *dp = ctx->cur_decoding_params; int16_t offset; - int32_t unsign; + int32_t unsign = 0; uint32_t diff; int lsb_bits; @@ -1607,7 +1609,8 @@ lsb_bits = number_sbits(diff) - 1; - unsign = 1 << (lsb_bits - 1); + if (lsb_bits > 0) + unsign = 1 << (lsb_bits - 1); /* If all samples are the same (lsb_bits == 0), offset must be * adjusted because of sign_shift. */ @@ -1699,7 +1702,7 @@ offset_min = FFMAX(min, HUFF_OFFSET_MIN); offset_max = FFMIN(max, HUFF_OFFSET_MAX); - for (;;) { + while (offset <= offset_max && offset >= offset_min) { BestOffset temp_bo; codebook_bits_offset(ctx, channel, codebook, @@ -1718,12 +1721,8 @@ if (direction) { offset = temp_bo.max + 1; - if (offset > offset_max) - break; } else { offset = temp_bo.min - 1; - if (offset < offset_min) - break; } } } @@ -1796,24 +1795,24 @@ #define SAMPLE_MAX(bitdepth) ((1 << (bitdepth - 1)) - 1) #define SAMPLE_MIN(bitdepth) (~SAMPLE_MAX(bitdepth)) -#define MSB_MASK(bits) (-1u << bits) +#define MSB_MASK(bits) (-(int)(1u << (bits))) /** Applies the filter to the current samples, and saves the residual back * into the samples buffer. If the filter is too bad and overflows the - * maximum amount of bits allowed (16 or 24), the samples buffer is left as is and + * maximum amount of bits allowed (24), the samples buffer is left as is and * the function returns -1. */ static int apply_filter(MLPEncodeContext *ctx, unsigned int channel) { FilterParams *fp[NUM_FILTERS] = { &ctx->cur_channel_params[channel].filter_params[FIR], &ctx->cur_channel_params[channel].filter_params[IIR], }; - int32_t *filter_state_buffer[NUM_FILTERS]; + int32_t *filter_state_buffer[NUM_FILTERS] = { NULL }; int32_t mask = MSB_MASK(ctx->cur_decoding_params->quant_step_size[channel]); int32_t *sample_buffer = ctx->sample_buffer + channel; unsigned int number_of_samples = ctx->number_of_samples; unsigned int filter_shift = fp[FIR]->shift; int filter; - int i; + int i, ret = 0; for (i = 0; i < NUM_FILTERS; i++) { unsigned int size = ctx->number_of_samples; @@ -1821,7 +1820,8 @@ if (!filter_state_buffer[i]) { av_log(ctx->avctx, AV_LOG_ERROR, "Not enough memory for applying filters.\n"); - return -1; + ret = AVERROR(ENOMEM); + goto free_and_return; } } @@ -1836,7 +1836,7 @@ int32_t sample = *sample_buffer; unsigned int order; int64_t accum = 0; - int32_t residual; + int64_t residual; for (filter = 0; filter < NUM_FILTERS; filter++) { int32_t *fcoeff = ctx->cur_channel_params[channel].coeff[filter]; @@ -1848,11 +1848,13 @@ accum >>= filter_shift; residual = sample - (accum & mask); - if (residual < SAMPLE_MIN(ctx->wordlength) || residual > SAMPLE_MAX(ctx->wordlength)) - return -1; + if (residual < SAMPLE_MIN(24) || residual > SAMPLE_MAX(24)) { + ret = AVERROR_INVALIDDATA; + goto free_and_return; + } filter_state_buffer[FIR][i] = sample; - filter_state_buffer[IIR][i] = residual; + filter_state_buffer[IIR][i] = (int32_t) residual; sample_buffer += ctx->num_channels; } @@ -1864,11 +1866,12 @@ sample_buffer += ctx->num_channels; } +free_and_return: for (i = 0; i < NUM_FILTERS; i++) { av_freep(&filter_state_buffer[i]); } - return 0; + return ret; } static void apply_filters(MLPEncodeContext *ctx) @@ -1897,8 +1900,8 @@ for (i = 0; i < ctx->number_of_samples; i++) { uint16_t seed_shr7 = seed >> 7; - *sample_buffer++ = ((int8_t)(seed >> 15)) << rh->noise_shift; - *sample_buffer++ = ((int8_t) seed_shr7) << rh->noise_shift; + *sample_buffer++ = ((int8_t)(seed >> 15)) * (1 << rh->noise_shift); + *sample_buffer++ = ((int8_t) seed_shr7) * (1 << rh->noise_shift); seed = (seed << 16) ^ seed_shr7 ^ (seed_shr7 << 5); @@ -1944,24 +1947,16 @@ ****************************************************************************/ typedef struct { - char path[MAJOR_HEADER_INTERVAL + 3]; + char path[MAJOR_HEADER_INTERVAL + 2]; + int cur_idx; int bitcount; } PathCounter; -static const char *path_counter_codebook[] = { "0", "1", "2", "3", }; - -#define ZERO_PATH '0' #define CODEBOOK_CHANGE_BITS 21 static void clear_path_counter(PathCounter *path_counter) { - unsigned int i; - - for (i = 0; i < NUM_CODEBOOKS + 1; i++) { - path_counter[i].path[0] = ZERO_PATH; - path_counter[i].path[1] = 0x00; - path_counter[i].bitcount = 0; - } + memset(path_counter, 0, (NUM_CODEBOOKS + 1) * sizeof(*path_counter)); } static int compare_best_offset(BestOffset *prev, BestOffset *cur) @@ -1975,18 +1970,11 @@ static int best_codebook_path_cost(MLPEncodeContext *ctx, unsigned int channel, PathCounter *src, int cur_codebook) { - BestOffset *cur_bo, *prev_bo = restart_best_offset; + int idx = src->cur_idx; + BestOffset *cur_bo = ctx->best_offset[idx][channel], + *prev_bo = idx ? ctx->best_offset[idx - 1][channel] : restart_best_offset; int bitcount = src->bitcount; - char *path = src->path + 1; - int prev_codebook; - int i; - - for (i = 0; path[i]; i++) - prev_bo = ctx->best_offset[i][channel]; - - prev_codebook = path[i - 1] - ZERO_PATH; - - cur_bo = ctx->best_offset[i][channel]; + int prev_codebook = src->path[idx]; bitcount += cur_bo[cur_codebook].bitcount; @@ -2049,7 +2037,8 @@ prev_best_bitcount = temp_bitcount; if (src_path != dst_path) memcpy(dst_path, src_path, sizeof(PathCounter)); - av_strlcat(dst_path->path, path_counter_codebook[codebook], sizeof(dst_path->path)); + if (dst_path->cur_idx < FF_ARRAY_ELEMS(dst_path->path) - 1) + dst_path->path[++dst_path->cur_idx] = codebook; dst_path->bitcount = temp_bitcount; } } @@ -2066,12 +2055,12 @@ for (index = 0; index < ctx->number_of_subblocks; index++) { ChannelParams *cp = ctx->seq_channel_params + index*(ctx->avctx->channels) + channel; - best_codebook = *best_path++ - ZERO_PATH; + best_codebook = *best_path++; cur_bo = &ctx->best_offset[index][channel][best_codebook]; - cp->huff_offset = cur_bo->offset; - cp->huff_lsbs = cur_bo->lsb_bits + dp->quant_step_size[channel]; - cp->codebook = best_codebook; + cp->huff_offset = cur_bo->offset; + cp->huff_lsbs = cur_bo->lsb_bits + dp->quant_step_size[channel]; + cp->codebook = best_codebook; } } } @@ -2199,9 +2188,6 @@ ctx->number_of_samples = ctx->major_frame_size; for (substr = 0; substr < ctx->num_substreams; substr++) { - RestartHeader *rh = ctx->cur_restart_header; - unsigned int channel; - ctx->cur_restart_header = &ctx->restart_header[substr]; ctx->cur_decoding_params = &ctx->major_decoding_params[1][substr]; @@ -2210,8 +2196,7 @@ generate_2_noise_channels(ctx); rematrix_channels (ctx); - for (channel = rh->min_channel; channel <= rh->max_channel; channel++) - apply_filter(ctx, channel); + apply_filters(ctx); } } @@ -2228,9 +2213,6 @@ if ((ret = ff_alloc_packet2(avctx, avpkt, 87500 * avctx->channels, 0)) < 0) return ret; - if (!frame) - return 1; - /* add current frame to queue */ if ((ret = ff_af_queue_add(&ctx->afq, frame)) < 0) return ret; @@ -2269,7 +2251,7 @@ if (ctx->frame_size[ctx->frame_index] > MAX_BLOCKSIZE) { av_log(avctx, AV_LOG_ERROR, "Invalid frame size (%d > %d)\n", ctx->frame_size[ctx->frame_index], MAX_BLOCKSIZE); - return -1; + return AVERROR_INVALIDDATA; } restart_frame = !ctx->frame_index; @@ -2277,7 +2259,7 @@ if (restart_frame) { set_major_params(ctx); if (ctx->min_restart_interval != ctx->max_restart_interval) - process_major_frame(ctx); + process_major_frame(ctx); } if (ctx->min_restart_interval == ctx->max_restart_interval) @@ -2375,6 +2357,7 @@ av_freep(&ctx->decoding_params); av_freep(&ctx->channel_params); av_freep(&ctx->frame_size); + av_freep(&ctx->max_output_bits); ff_af_queue_close(&ctx->afq); return 0; @@ -2390,10 +2373,11 @@ .init = mlp_encode_init, .encode2 = mlp_encode_frame, .close = mlp_encode_close, - .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_EXPERIMENTAL, .sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE}, .supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0}, .channel_layouts = ff_mlp_channel_layouts, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; #endif #if CONFIG_TRUEHD_ENCODER @@ -2406,9 +2390,10 @@ .init = mlp_encode_init, .encode2 = mlp_encode_frame, .close = mlp_encode_close, - .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_EXPERIMENTAL, .sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE}, .supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0}, .channel_layouts = (const uint64_t[]) {AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_5POINT1_BACK, 0}, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/mlp_parse.c ffmpeg-4.4/libavcodec/mlp_parse.c --- ffmpeg-4.2.2/libavcodec/mlp_parse.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mlp_parse.c 2020-07-11 10:39:30.000000000 +0000 @@ -60,56 +60,6 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static const uint8_t thd_chancount[13] = { -// LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2 - 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1 -}; - -static const uint64_t thd_layout[13] = { - AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT, // LR - AV_CH_FRONT_CENTER, // C - AV_CH_LOW_FREQUENCY, // LFE - AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, // LRs - AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT, // LRvh - AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER, // LRc - AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, // LRrs - AV_CH_BACK_CENTER, // Cs - AV_CH_TOP_CENTER, // Ts - AV_CH_SURROUND_DIRECT_LEFT|AV_CH_SURROUND_DIRECT_RIGHT, // LRsd - AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT, // LRw - AV_CH_TOP_FRONT_CENTER, // Cvh - AV_CH_LOW_FREQUENCY_2, // LFE2 -}; - -static int mlp_samplerate(int in) -{ - if (in == 0xF) - return 0; - - return (in & 8 ? 44100 : 48000) << (in & 7) ; -} - -static int truehd_channels(int chanmap) -{ - int channels = 0, i; - - for (i = 0; i < 13; i++) - channels += thd_chancount[i] * ((chanmap >> i) & 1); - - return channels; -} - -static uint64_t truehd_layout(int chanmap) -{ - int i; - uint64_t layout = 0; - - for (i = 0; i < 13; i++) - layout |= thd_layout[i] * ((chanmap >> i) & 1); - - return layout; -} - static int mlp_get_major_sync_size(const uint8_t * buf, int bufsize) { int has_extension, extensions = 0; @@ -152,7 +102,7 @@ return AVERROR_INVALIDDATA; } - if (get_bits_long(gb, 24) != 0xf8726f) /* Sync words */ + if (get_bits(gb, 24) != 0xf8726f) /* Sync words */ return AVERROR_INVALIDDATA; mh->stream_type = get_bits(gb, 8); diff -Nru ffmpeg-4.2.2/libavcodec/mlp_parse.h ffmpeg-4.4/libavcodec/mlp_parse.h --- ffmpeg-4.2.2/libavcodec/mlp_parse.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mlp_parse.h 2020-07-11 10:39:30.000000000 +0000 @@ -56,6 +56,55 @@ int num_substreams; ///< Number of substreams within stream } MLPHeaderInfo; +static const uint8_t thd_chancount[13] = { +// LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2 + 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1 +}; + +static const uint64_t thd_layout[13] = { + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT, // LR + AV_CH_FRONT_CENTER, // C + AV_CH_LOW_FREQUENCY, // LFE + AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, // LRs + AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT, // LRvh + AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER, // LRc + AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, // LRrs + AV_CH_BACK_CENTER, // Cs + AV_CH_TOP_CENTER, // Ts + AV_CH_SURROUND_DIRECT_LEFT|AV_CH_SURROUND_DIRECT_RIGHT, // LRsd + AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT, // LRw + AV_CH_TOP_FRONT_CENTER, // Cvh + AV_CH_LOW_FREQUENCY_2, // LFE2 +}; + +static inline int mlp_samplerate(int in) +{ + if (in == 0xF) + return 0; + + return (in & 8 ? 44100 : 48000) << (in & 7) ; +} + +static inline int truehd_channels(int chanmap) +{ + int channels = 0, i; + + for (i = 0; i < 13; i++) + channels += thd_chancount[i] * ((chanmap >> i) & 1); + + return channels; +} + +static inline uint64_t truehd_layout(int chanmap) +{ + int i; + uint64_t layout = 0; + + for (i = 0; i < 13; i++) + layout |= thd_layout[i] * ((chanmap >> i) & 1); + + return layout; +} int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb); diff -Nru ffmpeg-4.2.2/libavcodec/mlp_parser.c ffmpeg-4.4/libavcodec/mlp_parser.c --- ffmpeg-4.2.2/libavcodec/mlp_parser.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mlp_parser.c 2020-07-11 10:39:30.000000000 +0000 @@ -61,7 +61,10 @@ int ret; int i, p = 0; + s->key_frame = 0; + *poutbuf_size = 0; + *poutbuf = NULL; if (buf_size == 0) return 0; @@ -136,6 +139,8 @@ * access unit header and all the 2- or 4-byte substream headers. */ // Only check when this isn't a sync frame - syncs have a checksum. + s->key_frame = 0; + parity_bits = 0; for (i = -1; i < mp->num_substreams; i++) { parity_bits ^= buf[p++]; @@ -159,12 +164,15 @@ if (ff_mlp_read_major_sync(avctx, &mh, &gb) < 0) goto lost_sync; + s->key_frame = 1; + avctx->bits_per_raw_sample = mh.group1_bits; if (avctx->bits_per_raw_sample > 16) avctx->sample_fmt = AV_SAMPLE_FMT_S32; else avctx->sample_fmt = AV_SAMPLE_FMT_S16; avctx->sample_rate = mh.group1_samplerate; + avctx->frame_size = s->duration = mh.access_unit_size; if(!avctx->channels || !avctx->channel_layout) { diff -Nru ffmpeg-4.2.2/libavcodec/mmaldec.c ffmpeg-4.4/libavcodec/mmaldec.c --- ffmpeg-4.2.2/libavcodec/mmaldec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mmaldec.c 2021-04-08 21:28:39.000000000 +0000 @@ -1,6 +1,6 @@ /* * MMAL Video Decoder - * Copyright (c) 2015 Rodger Combs + * Copyright (c) 2015 rcombs * * This file is part of FFmpeg. * @@ -34,7 +34,8 @@ #include #include "avcodec.h" -#include "hwaccel.h" +#include "decode.h" +#include "hwconfig.h" #include "internal.h" #include "libavutil/avassert.h" #include "libavutil/buffer.h" @@ -808,7 +809,7 @@ return ret; } -static const AVCodecHWConfigInternal *mmal_hw_configs[] = { +static const AVCodecHWConfigInternal *const mmal_hw_configs[] = { HW_CONFIG_INTERNAL(MMAL), NULL }; diff -Nru ffmpeg-4.2.2/libavcodec/mmvideo.c ffmpeg-4.4/libavcodec/mmvideo.c --- ffmpeg-4.2.2/libavcodec/mmvideo.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mmvideo.c 2020-07-11 10:39:30.000000000 +0000 @@ -201,7 +201,7 @@ buf_size -= MM_PREAMBLE_SIZE; bytestream2_init(&s->gb, buf, buf_size); - if ((res = ff_reget_buffer(avctx, s->frame)) < 0) + if ((res = ff_reget_buffer(avctx, s->frame, 0)) < 0) return res; switch(type) { diff -Nru ffmpeg-4.2.2/libavcodec/mobiclip.c ffmpeg-4.4/libavcodec/mobiclip.c --- ffmpeg-4.2.2/libavcodec/mobiclip.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mobiclip.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,1355 @@ +/* + * MobiClip Video decoder + * Copyright (c) 2015-2016 Florian Nouwt + * Copyright (c) 2017 Adib Surani + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/thread.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "bswapdsp.h" +#include "get_bits.h" +#include "golomb.h" +#include "internal.h" + +#define MOBI_RL_VLC_BITS 12 +#define MOBI_MV_VLC_BITS 6 + +static const uint8_t zigzag4x4_tab[] = +{ + 0x00, 0x04, 0x01, 0x02, 0x05, 0x08, 0x0C, 0x09, 0x06, 0x03, 0x07, 0x0A, + 0x0D, 0x0E, 0x0B, 0x0F +}; + +static const uint8_t quant4x4_tab[][16] = +{ + { 10, 13, 13, 10, 16, 10, 13, 13, 13, 13, 16, 10, 16, 13, 13, 16 }, + { 11, 14, 14, 11, 18, 11, 14, 14, 14, 14, 18, 11, 18, 14, 14, 18 }, + { 13, 16, 16, 13, 20, 13, 16, 16, 16, 16, 20, 13, 20, 16, 16, 20 }, + { 14, 18, 18, 14, 23, 14, 18, 18, 18, 18, 23, 14, 23, 18, 18, 23 }, + { 16, 20, 20, 16, 25, 16, 20, 20, 20, 20, 25, 16, 25, 20, 20, 25 }, + { 18, 23, 23, 18, 29, 18, 23, 23, 23, 23, 29, 18, 29, 23, 23, 29 }, +}; + +static const uint8_t quant8x8_tab[][64] = +{ + { 20, 19, 19, 25, 18, 25, 19, 24, 24, 19, 20, 18, 32, 18, 20, 19, 19, 24, 24, 19, 19, 25, 18, 25, 18, 25, 18, 25, 19, 24, 24, 19, + 19, 24, 24, 19, 18, 32, 18, 20, 18, 32, 18, 24, 24, 19, 19, 24, 24, 18, 25, 18, 25, 18, 19, 24, 24, 19, 18, 32, 18, 24, 24, 18,}, + { 22, 21, 21, 28, 19, 28, 21, 26, 26, 21, 22, 19, 35, 19, 22, 21, 21, 26, 26, 21, 21, 28, 19, 28, 19, 28, 19, 28, 21, 26, 26, 21, + 21, 26, 26, 21, 19, 35, 19, 22, 19, 35, 19, 26, 26, 21, 21, 26, 26, 19, 28, 19, 28, 19, 21, 26, 26, 21, 19, 35, 19, 26, 26, 19,}, + { 26, 24, 24, 33, 23, 33, 24, 31, 31, 24, 26, 23, 42, 23, 26, 24, 24, 31, 31, 24, 24, 33, 23, 33, 23, 33, 23, 33, 24, 31, 31, 24, + 24, 31, 31, 24, 23, 42, 23, 26, 23, 42, 23, 31, 31, 24, 24, 31, 31, 23, 33, 23, 33, 23, 24, 31, 31, 24, 23, 42, 23, 31, 31, 23,}, + { 28, 26, 26, 35, 25, 35, 26, 33, 33, 26, 28, 25, 45, 25, 28, 26, 26, 33, 33, 26, 26, 35, 25, 35, 25, 35, 25, 35, 26, 33, 33, 26, + 26, 33, 33, 26, 25, 45, 25, 28, 25, 45, 25, 33, 33, 26, 26, 33, 33, 25, 35, 25, 35, 25, 26, 33, 33, 26, 25, 45, 25, 33, 33, 25,}, + { 32, 30, 30, 40, 28, 40, 30, 38, 38, 30, 32, 28, 51, 28, 32, 30, 30, 38, 38, 30, 30, 40, 28, 40, 28, 40, 28, 40, 30, 38, 38, 30, + 30, 38, 38, 30, 28, 51, 28, 32, 28, 51, 28, 38, 38, 30, 30, 38, 38, 28, 40, 28, 40, 28, 30, 38, 38, 30, 28, 51, 28, 38, 38, 28,}, + { 36, 34, 34, 46, 32, 46, 34, 43, 43, 34, 36, 32, 58, 32, 36, 34, 34, 43, 43, 34, 34, 46, 32, 46, 32, 46, 32, 46, 34, 43, 43, 34, + 34, 43, 43, 34, 32, 58, 32, 36, 32, 58, 32, 43, 43, 34, 34, 43, 43, 32, 46, 32, 46, 32, 34, 43, 43, 34, 32, 58, 32, 43, 43, 32,}, +}; + +static const uint8_t block4x4_coefficients_tab[] = +{ + 15, 0, 2, 1, 4, 8, 12, 3, 11, 13, 14, 7, 10, 5, 9, 6, +}; + +static const uint8_t pframe_block4x4_coefficients_tab[] = +{ + 0, 4, 1, 8, 2, 12, 3, 5, 10, 15, 7, 13, 14, 11, 9, 6, +}; + +static const uint8_t block8x8_coefficients_tab[] = +{ + 0x00, 0x1F, 0x3F, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x0B, 0x0E, 0x1B, 0x0D, + 0x03, 0x07, 0x0C, 0x17, 0x1D, 0x0A, 0x1E, 0x05, 0x10, 0x2F, 0x37, 0x3B, + 0x13, 0x3D, 0x3E, 0x09, 0x1C, 0x06, 0x15, 0x1A, 0x33, 0x11, 0x12, 0x14, + 0x18, 0x20, 0x3C, 0x35, 0x19, 0x16, 0x3A, 0x30, 0x31, 0x32, 0x27, 0x34, + 0x2B, 0x2D, 0x39, 0x38, 0x23, 0x36, 0x2E, 0x21, 0x25, 0x22, 0x24, 0x2C, + 0x2A, 0x28, 0x29, 0x26, +}; + +static const uint8_t pframe_block8x8_coefficients_tab[] = +{ + 0x00, 0x0F, 0x04, 0x01, 0x08, 0x02, 0x0C, 0x03, 0x05, 0x0A, 0x0D, 0x07, 0x0E, 0x0B, 0x1F, 0x09, + 0x06, 0x10, 0x3F, 0x1E, 0x17, 0x1D, 0x1B, 0x1C, 0x13, 0x18, 0x1A, 0x12, 0x11, 0x14, 0x15, 0x20, + 0x2F, 0x16, 0x19, 0x37, 0x3D, 0x3E, 0x3B, 0x3C, 0x33, 0x35, 0x21, 0x24, 0x22, 0x28, 0x23, 0x2C, + 0x30, 0x27, 0x2D, 0x25, 0x3A, 0x2B, 0x2E, 0x2A, 0x31, 0x34, 0x38, 0x32, 0x29, 0x26, 0x39, 0x36 +}; + +static const uint8_t run_residue[2][256] = +{ + { + 12, 6, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 27, 11, 7, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 41, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + }, + { + 27, 10, 5, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 15, 10, 8, 4, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 21, 7, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + }, +}; + +static const uint8_t bits0[] = { + 9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 10, 10, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 5, 5, 5, 4, 2, 3, 4, 4, +}; + +static const uint16_t syms0[] = { + 0x0, 0x822, 0x803, 0xB, 0xA, 0xB81, 0xB61, 0xB41, 0xB21, 0x122, + 0x102, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x24, 0xC, 0x25, 0x2E1, 0x301, + 0xBA1, 0xBC1, 0xBE1, 0xC01, 0x26, 0x44, 0x83, 0xA3, 0xC3, 0x142, + 0x321, 0x341, 0xC21, 0xC41, 0xC61, 0xC81, 0xCA1, 0xCC1, 0xCE1, 0xD01, + 0x0, 0x9, 0x8, 0xB01, 0xAE1, 0xAC1, 0xAA1, 0xA81, 0xA61, 0xA41, 0xA21, + 0x802, 0x2C1, 0x2A1, 0x281, 0x261, 0x241, 0x221, 0x201, 0x1E1, 0x82, + 0x62, 0x7, 0x6, 0xA01, 0x9E1, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x921, + 0x1C1, 0x1A1, 0x42, 0x23, 0x5, 0x901, 0x8E1, 0x8C1, 0x8A1, 0x181, 0x161, + 0x141, 0x4, 0x881, 0x861, 0x841, 0x821, 0x121, 0x101, 0xE1, 0xC1, 0x22, + 0x3, 0xA1, 0x81, 0x61, 0x801, 0x1, 0x21, 0x41, 0x2, +}; + +static const uint16_t syms1[] = { + 0x0, 0x807, 0x806, 0x16, 0x15, 0x842, 0x823, 0x805, 0x1A1, 0xA3, 0x102, 0x83, + 0x64, 0x44, 0x27, 0x14, 0x13, 0x17, 0x18, 0x28, 0x122, 0x862, 0x882, 0x9E1, 0xA01, + 0x19, 0x1A, 0x1B, 0x29, 0xC3, 0x2A, 0x45, 0xE3, 0x1C1, 0x808, 0x8A2, 0x8C2, 0xA21, + 0xA41, 0xA61, 0xA81, 0x0, 0x12, 0x11, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x822, 0x804, + 0x181, 0x161, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x26, 0x25, 0x10, 0x82, 0xF, 0xE, 0xD, 0x901, + 0x8E1, 0x8C1, 0x803, 0x141, 0x121, 0x101, 0x921, 0x62, 0x24, 0xC, 0xB, 0xA, 0x881, 0x861, + 0xC1, 0x8A1, 0xE1, 0x42, 0x23, 0x9, 0x802, 0xA1, 0x841, 0x821, 0x81, 0x61, 0x8, 0x7, 0x22, + 0x6, 0x41, 0x5, 0x4, 0x801, 0x1, 0x2, 0x21, 0x3, +}; + +static const uint8_t mv_len[16] = +{ + 10, 8, 8, 7, 8, 8, 8, 7, 8, 8, 8, 7, 7, 7, 7, 6, +}; + +static const uint8_t mv_bits[2][16][10] = +{ + { + { 2, 3, 3, 5, 5, 4, 4, 5, 5, 2 }, + { 2, 3, 4, 4, 3, 4, 4, 2 }, + { 3, 4, 4, 2, 4, 4, 3, 2 }, + { 1, 3, 4, 5, 5, 3, 3 }, + { 2, 4, 4, 3, 3, 4, 4, 2 }, + { 2, 3, 4, 4, 4, 4, 3, 2 }, + { 2, 3, 4, 4, 4, 4, 3, 2 }, + { 2, 2, 3, 4, 5, 5, 2 }, + { 2, 3, 4, 4, 3, 4, 4, 2 }, + { 2, 4, 4, 3, 4, 4, 3, 2 }, + { 2, 3, 3, 5, 5, 4, 3, 2 }, + { 2, 3, 4, 4, 3, 3, 2 }, + { 1, 4, 4, 3, 3, 4, 4 }, + { 2, 3, 4, 4, 3, 3, 2 }, + { 2, 3, 4, 4, 3, 3, 2 }, + { 3, 3, 2, 2, 3, 3 }, + }, + { + { 3, 4, 5, 5, 3, 5, 6, 6, 4, 1 }, + { 2, 3, 4, 5, 5, 2, 3, 3 }, + { 2, 4, 4, 3, 3, 4, 4, 2 }, + { 1, 4, 4, 3, 4, 4, 3 }, + { 3, 3, 2, 4, 5, 5, 3, 2 }, + { 3, 4, 4, 3, 3, 3, 3, 2 }, + { 1, 3, 3, 4, 4, 4, 5, 5 }, + { 1, 4, 4, 3, 3, 4, 4 }, + { 2, 4, 4, 3, 3, 4, 4, 2 }, + { 1, 3, 3, 4, 4, 4, 5, 5 }, + { 2, 3, 4, 4, 4, 4, 3, 2 }, + { 2, 3, 3, 4, 4, 3, 2 }, + { 1, 4, 4, 3, 3, 4, 4 }, + { 1, 4, 4, 3, 3, 4, 4 }, + { 2, 3, 3, 4, 4, 3, 2 }, + { 2, 3, 3, 3, 3, 2 }, + } +}; + +static const uint8_t mv_syms[2][16][10] = +{ + { + { 1, 8, 9, 4, 3, 2, 7, 5, 6, 0 }, + { 0, 9, 5, 4, 2, 3, 8, 1 }, + { 3, 9, 5, 0, 4, 8, 2, 1 }, + { 1, 3, 4, 8, 5, 2, 0 }, + { 0, 5, 4, 8, 2, 3, 9, 1 }, + { 0, 3, 5, 9, 4, 8, 2, 1 }, + { 0, 3, 9, 5, 8, 4, 2, 1 }, + { 0, 2, 3, 4, 8, 5, 1 }, + { 0, 3, 8, 4, 2, 5, 9, 1 }, + { 2, 8, 9, 3, 5, 4, 0, 1 }, + { 0, 4, 3, 8, 9, 5, 2, 1 }, + { 0, 4, 8, 5, 3, 2, 1 }, + { 1, 9, 4, 2, 0, 5, 3 }, + { 2, 4, 9, 5, 3, 0, 1 }, + { 0, 4, 9, 5, 3, 2, 1 }, + { 5, 4, 1, 0, 3, 2 }, + }, + { + { 8, 2, 3, 6, 1, 7, 5, 4, 9, 0 }, + { 9, 2, 3, 5, 4, 1, 8, 0 }, + { 0, 5, 4, 2, 9, 3, 8, 1 }, + { 1, 5, 4, 2, 8, 3, 0 }, + { 2, 9, 8, 3, 5, 4, 0, 1 }, + { 3, 5, 4, 2, 9, 8, 0, 1 }, + { 1, 2, 0, 9, 8, 3, 5, 4 }, + { 1, 8, 5, 2, 0, 4, 3 }, + { 0, 5, 4, 2, 8, 3, 9, 1 }, + { 1, 2, 0, 9, 8, 3, 5, 4 }, + { 0, 3, 9, 8, 5, 4, 2, 1 }, + { 0, 4, 3, 8, 5, 2, 1 }, + { 1, 5, 4, 2, 0, 9, 3 }, + { 1, 9, 5, 2, 0, 4, 3 }, + { 0, 5, 3, 9, 4, 2, 1 }, + { 0, 4, 5, 3, 2, 1 }, + } +}; + +typedef struct BlockXY { + int w, h; + int ax, ay; + int x, y; + int size; + uint8_t *block; + int linesize; +} BlockXY; + +typedef struct MotionXY { + int x, y; +} MotionXY; + +typedef struct MobiClipContext { + AVFrame *pic[6]; + + int current_pic; + int moflex; + int dct_tab_idx; + int quantizer; + + GetBitContext gb; + + uint8_t *bitstream; + int bitstream_size; + + int qtab[2][64]; + uint8_t pre[32]; + MotionXY *motion; + int motion_size; + + BswapDSPContext bdsp; +} MobiClipContext; + +static VLC rl_vlc[2]; +static VLC mv_vlc[2][16]; + +static av_cold void mobiclip_init_static(void) +{ + INIT_VLC_STATIC_FROM_LENGTHS(&rl_vlc[0], MOBI_RL_VLC_BITS, 104, + bits0, sizeof(*bits0), + syms0, sizeof(*syms0), sizeof(*syms0), + 0, 0, 1 << MOBI_RL_VLC_BITS); + INIT_VLC_STATIC_FROM_LENGTHS(&rl_vlc[1], MOBI_RL_VLC_BITS, 104, + bits0, sizeof(*bits0), + syms1, sizeof(*syms1), sizeof(*syms1), + 0, 0, 1 << MOBI_RL_VLC_BITS); + for (int i = 0; i < 2; i++) { + static VLC_TYPE vlc_buf[2 * 16 << MOBI_MV_VLC_BITS][2]; + for (int j = 0; j < 16; j++) { + mv_vlc[i][j].table = &vlc_buf[(16 * i + j) << MOBI_MV_VLC_BITS]; + mv_vlc[i][j].table_allocated = 1 << MOBI_MV_VLC_BITS; + ff_init_vlc_from_lengths(&mv_vlc[i][j], MOBI_MV_VLC_BITS, mv_len[j], + mv_bits[i][j], sizeof(*mv_bits[i][j]), + mv_syms[i][j], sizeof(*mv_syms[i][j]), sizeof(*mv_syms[i][j]), + 0, INIT_VLC_USE_NEW_STATIC, NULL); + } + } +} + +static av_cold int mobiclip_init(AVCodecContext *avctx) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + MobiClipContext *s = avctx->priv_data; + + if (avctx->width & 15 || avctx->height & 15) { + av_log(avctx, AV_LOG_ERROR, "width/height not multiple of 16\n"); + return AVERROR_INVALIDDATA; + } + + ff_bswapdsp_init(&s->bdsp); + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + s->motion = av_calloc(avctx->width / 16 + 3, sizeof(MotionXY)); + if (!s->motion) + return AVERROR(ENOMEM); + s->motion_size = (avctx->width / 16 + 3) * sizeof(MotionXY); + + for (int i = 0; i < 6; i++) { + s->pic[i] = av_frame_alloc(); + if (!s->pic[i]) + return AVERROR(ENOMEM); + } + + ff_thread_once(&init_static_once, mobiclip_init_static); + + return 0; +} + +static int setup_qtables(AVCodecContext *avctx, int quantizer) +{ + MobiClipContext *s = avctx->priv_data; + int qx, qy; + + if (quantizer < 12 || quantizer > 161) + return AVERROR_INVALIDDATA; + + s->quantizer = quantizer; + + qx = quantizer % 6; + qy = quantizer / 6; + + for (int i = 0; i < 16; i++) + s->qtab[0][i] = quant4x4_tab[qx][i] << qy; + + for (int i = 0; i < 64; i++) + s->qtab[1][i] = quant8x8_tab[qx][i] << (qy - 2); + + for (int i = 0; i < 20; i++) + s->pre[i] = 9; + + return 0; +} + +static void inverse4(unsigned *rs) +{ + unsigned a = rs[0] + rs[2]; + unsigned b = rs[0] - rs[2]; + unsigned c = rs[1] + ((int)rs[3] >> 1); + unsigned d = ((int)rs[1] >> 1) - rs[3]; + + rs[0] = a + c; + rs[1] = b + d; + rs[2] = b - d; + rs[3] = a - c; +} + +static void idct(int *arr, int size) +{ + int e, f, g, h; + unsigned x3, x2, x1, x0; + int tmp[4]; + + if (size == 4) { + inverse4(arr); + return; + } + + tmp[0] = arr[0]; + tmp[1] = arr[2]; + tmp[2] = arr[4]; + tmp[3] = arr[6]; + + inverse4(tmp); + + e = (unsigned)arr[7] + arr[1] - arr[3] - (arr[3] >> 1); + f = (unsigned)arr[7] - arr[1] + arr[5] + (arr[5] >> 1); + g = (unsigned)arr[5] - arr[3] - arr[7] - (arr[7] >> 1); + h = (unsigned)arr[5] + arr[3] + arr[1] + (arr[1] >> 1); + x3 = (unsigned)g + (h >> 2); + x2 = (unsigned)e + (f >> 2); + x1 = (e >> 2) - (unsigned)f; + x0 = (unsigned)h - (g >> 2); + + arr[0] = tmp[0] + x0; + arr[1] = tmp[1] + x1; + arr[2] = tmp[2] + x2; + arr[3] = tmp[3] + x3; + arr[4] = tmp[3] - x3; + arr[5] = tmp[2] - x2; + arr[6] = tmp[1] - x1; + arr[7] = tmp[0] - x0; +} + +static void read_run_encoding(AVCodecContext *avctx, + int *last, int *run, int *level) +{ + MobiClipContext *s = avctx->priv_data; + GetBitContext *gb = &s->gb; + int n = get_vlc2(gb, rl_vlc[s->dct_tab_idx].table, + MOBI_RL_VLC_BITS, 1); + + *last = (n >> 11) == 1; + *run = (n >> 5) & 0x3F; + *level = n & 0x1F; +} + +static int add_coefficients(AVCodecContext *avctx, AVFrame *frame, + int bx, int by, int size, int plane) +{ + MobiClipContext *s = avctx->priv_data; + GetBitContext *gb = &s->gb; + int mat[64] = { 0 }; + const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab; + const int *qtab = s->qtab[size == 8]; + uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx; + + for (int pos = 0; get_bits_left(gb) > 0; pos++) { + int qval, last, run, level; + + read_run_encoding(avctx, &last, &run, &level); + + if (level) { + if (get_bits1(gb)) + level = -level; + } else if (!get_bits1(gb)) { + read_run_encoding(avctx, &last, &run, &level); + level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run]; + if (get_bits1(gb)) + level = -level; + } else if (!get_bits1(gb)) { + read_run_encoding(avctx, &last, &run, &level); + run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level]; + if (get_bits1(gb)) + level = -level; + } else { + last = get_bits1(gb); + run = get_bits(gb, 6); + level = get_sbits(gb, 12); + } + + pos += run; + if (pos >= size * size) + return AVERROR_INVALIDDATA; + qval = qtab[pos]; + mat[ztab[pos]] = qval *(unsigned)level; + + if (last) + break; + } + + mat[0] += 32; + for (int y = 0; y < size; y++) + idct(&mat[y * size], size); + + for (int y = 0; y < size; y++) { + for (int x = y + 1; x < size; x++) { + int a = mat[x * size + y]; + int b = mat[y * size + x]; + + mat[y * size + x] = a; + mat[x * size + y] = b; + } + + idct(&mat[y * size], size); + for (int x = 0; x < size; x++) + dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6)); + dst += frame->linesize[plane]; + } + + return 0; +} + +static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame, + int bx, int by, int size, int plane) +{ + MobiClipContext *s = avctx->priv_data; + GetBitContext *gb = &s->gb; + int ret, idx = get_ue_golomb_31(gb); + + if (idx == 0) { + ret = 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]; + + for (int y = by; y < by + 8; y += 4) { + for (int x = bx; x < bx + 8; x += 4) { + if (flags & 1) { + ret = add_coefficients(avctx, frame, x, y, 4, plane); + if (ret < 0) + return ret; + } + flags >>= 1; + } + } + } else { + ret = AVERROR_INVALIDDATA; + } + + return ret; +} + +static int adjust(int x, int size) +{ + return size == 16 ? (x + 1) >> 1 : x; +} + +static uint8_t pget(BlockXY b) +{ + BlockXY ret = b; + int x, y; + + if (b.x == -1 && b.y >= b.size) { + ret.x = -1, ret.y = b.size - 1; + } else if (b.x >= -1 && b.y >= -1) { + ret.x = b.x, ret.y = b.y; + } else if (b.x == -1 && b.y == -2) { + ret.x = 0, ret.y = -1; + } else if (b.x == -2 && b.y == -1) { + ret.x = -1, ret.y = 0; + } + + y = av_clip(ret.ay + ret.y, 0, ret.h - 1); + x = av_clip(ret.ax + ret.x, 0, ret.w - 1); + + return ret.block[y * ret.linesize + x]; +} + +static uint8_t half(int a, int b) +{ + return ((a + b) + 1) / 2; +} + +static uint8_t half3(int a, int b, int c) +{ + return ((a + b + b + c) * 2 / 4 + 1) / 2; +} + +static uint8_t pick_above(BlockXY bxy) +{ + bxy.y = bxy.y - 1; + + return pget(bxy); +} + +static uint8_t pick_left(BlockXY bxy) +{ + bxy.x = bxy.x - 1; + + return pget(bxy); +} + +static uint8_t half_horz(BlockXY bxy) +{ + BlockXY a = bxy, b = bxy, c = bxy; + + a.x -= 1; + c.x += 1; + + return half3(pget(a), pget(b), pget(c)); +} + +static uint8_t half_vert(BlockXY bxy) +{ + BlockXY a = bxy, b = bxy, c = bxy; + + a.y -= 1; + c.y += 1; + + return half3(pget(a), pget(b), pget(c)); +} + +static uint8_t pick_4(BlockXY bxy) +{ + int val; + + if ((bxy.x % 2) == 0) { + BlockXY ba, bb; + int a, b; + + ba = bxy; + ba.x = -1; + ba.y = bxy.y + bxy.x / 2; + a = pget(ba); + + bb = bxy; + bb.x = -1; + bb.y = bxy.y + bxy.x / 2 + 1; + b = pget(bb); + + val = half(a, b); + } else { + BlockXY ba; + + ba = bxy; + ba.x = -1; + ba.y = bxy.y + bxy.x / 2 + 1; + val = half_vert(ba); + } + + return val; +} + +static uint8_t pick_5(BlockXY bxy) +{ + int val; + + if (bxy.x == 0) { + BlockXY a = bxy; + BlockXY b = bxy; + + a.x = -1; + a.y -= 1; + + b.x = -1; + + val = half(pget(a), pget(b)); + } else if (bxy.y == 0) { + BlockXY a = bxy; + + a.x -= 2; + a.y -= 1; + + val = half_horz(a); + } else if (bxy.x == 1) { + BlockXY a = bxy; + + a.x -= 2; + a.y -= 1; + + val = half_vert(a); + } else { + BlockXY a = bxy; + + a.x -= 2; + a.y -= 1; + + val = pget(a); + } + + return val; +} + +static uint8_t pick_6(BlockXY bxy) +{ + int val; + + if (bxy.y == 0) { + BlockXY a = bxy; + BlockXY b = bxy; + + a.x -= 1; + a.y = -1; + + b.y = -1; + + val = half(pget(a), pget(b)); + } else if (bxy.x == 0) { + BlockXY a = bxy; + + a.x -= 1; + a.y -= 2; + + val = half_vert(a); + } else if (bxy.y == 1) { + BlockXY a = bxy; + + a.x -= 1; + a.y -= 2; + + val = half_horz(a); + } else { + BlockXY a = bxy; + + a.x -= 1; + a.y -= 2; + + val = pget(a); + } + + return val; +} + +static uint8_t pick_7(BlockXY bxy) +{ + int clr, acc1, acc2; + BlockXY a = bxy; + + a.x -= 1; + a.y -= 1; + clr = pget(a); + if (bxy.x && bxy.y) + return clr; + + if (bxy.x == 0) { + a.x = -1; + a.y = bxy.y; + } else { + a.x = bxy.x - 2; + a.y = -1; + } + acc1 = pget(a); + + if (bxy.y == 0) { + a.x = bxy.x; + a.y = -1; + } else { + a.x = -1; + a.y = bxy.y - 2; + } + acc2 = pget(a); + + return half3(acc1, clr, acc2); +} + +static uint8_t pick_8(BlockXY bxy) +{ + BlockXY ba = bxy; + BlockXY bb = bxy; + int val; + + if (bxy.y == 0) { + int a, b; + + ba.y = -1; + a = pget(ba); + + bb.x += 1; + bb.y = -1; + + b = pget(bb); + + val = half(a, b); + } else if (bxy.y == 1) { + ba.x += 1; + ba.y -= 2; + + val = half_horz(ba); + } else if (bxy.x < bxy.size - 1) { + ba.x += 1; + ba.y -= 2; + + val = pget(ba); + } else if (bxy.y % 2 == 0) { + int a, b; + + ba.x = bxy.y / 2 + bxy.size - 1; + ba.y = -1; + a = pget(ba); + + bb.x = bxy.y / 2 + bxy.size; + bb.y = -1; + + b = pget(bb); + + val = half(a, b); + } else { + ba.x = bxy.y / 2 + bxy.size; + ba.y = -1; + + val = half_horz(ba); + } + + return val; +} + +static void block_fill_simple(uint8_t *block, int size, int linesize, int fill) +{ + for (int y = 0; y < size; y++) { + memset(block, fill, size); + block += linesize; + } +} + +static void block_fill(uint8_t *block, int size, int linesize, + int w, int h, int ax, int ay, + uint8_t (*pick)(BlockXY bxy)) +{ + BlockXY bxy; + + bxy.size = size; + bxy.block = block; + bxy.linesize = linesize; + bxy.w = w; + bxy.h = h; + bxy.ay = ay; + bxy.ax = ax; + + for (int y = 0; y < size; y++) { + bxy.y = y; + for (int x = 0; x < size; x++) { + uint8_t val; + + bxy.x = x; + + val = pick(bxy); + + block[ax + x + (ay + y) * linesize] = val; + } + } +} + +static int block_sum(const uint8_t *block, int w, int h, int linesize) +{ + int sum = 0; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + sum += block[x]; + } + block += linesize; + } + + return sum; +} + +static int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay, + int pmode, int add_coeffs, int size, int plane) +{ + MobiClipContext *s = avctx->priv_data; + GetBitContext *gb = &s->gb; + int w = avctx->width >> !!plane, h = avctx->height >> !!plane; + int ret = 0; + + switch (pmode) { + case 0: + block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_above); + break; + case 1: + block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_left); + break; + case 2: + { + int arr1[16]; + int arr2[16]; + uint8_t *top = frame->data[plane] + FFMAX(ay - 1, 0) * frame->linesize[plane] + ax; + uint8_t *left = frame->data[plane] + ay * frame->linesize[plane] + FFMAX(ax - 1, 0); + int bottommost = frame->data[plane][(ay + size - 1) * frame->linesize[plane] + FFMAX(ax - 1, 0)]; + int rightmost = frame->data[plane][FFMAX(ay - 1, 0) * frame->linesize[plane] + ax + size - 1]; + int avg = (bottommost + rightmost + 1) / 2 + 2 * av_clip(get_se_golomb(gb), -(1<<16), 1<<16); + int r6 = adjust(avg - bottommost, size); + int r9 = adjust(avg - rightmost, size); + int shift = adjust(size, size) == 8 ? 3 : 2; + uint8_t *block; + + for (int x = 0; x < size; x++) { + int val = top[x]; + arr1[x] = adjust(((bottommost - val) * (1 << shift)) + r6 * (x + 1), size); + } + + for (int y = 0; y < size; y++) { + int val = left[y * frame->linesize[plane]]; + arr2[y] = adjust(((rightmost - val) * (1 << shift)) + r9 * (y + 1), size); + } + + block = frame->data[plane] + ay * frame->linesize[plane] + ax; + for (int y = 0; y < size; y++) { + for (int x = 0; x < size; x++) { + block[x] = (((top[x] + left[0] + ((arr1[x] * (y + 1) + + arr2[y] * (x + 1)) >> 2 * shift)) + 1) / 2) & 0xFF; + } + block += frame->linesize[plane]; + left += frame->linesize[plane]; + } + } + break; + case 3: + { + uint8_t fill; + + if (ax == 0 && ay == 0) { + fill = 0x80; + } else if (ax >= 1 && ay >= 1) { + int left = block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1, + 1, size, frame->linesize[plane]); + int top = block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax, + size, 1, frame->linesize[plane]); + + fill = ((left + top) * 2 / (2 * size) + 1) / 2; + } else if (ax >= 1) { + fill = (block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1, + 1, size, frame->linesize[plane]) * 2 / size + 1) / 2; + } else if (ay >= 1) { + fill = (block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax, + size, 1, frame->linesize[plane]) * 2 / size + 1) / 2; + } else { + return -1; + } + + block_fill_simple(frame->data[plane] + ay * frame->linesize[plane] + ax, + size, frame->linesize[plane], fill); + } + break; + case 4: + block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_4); + break; + case 5: + block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_5); + break; + case 6: + block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_6); + break; + case 7: + block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_7); + break; + case 8: + block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_8); + break; + } + + if (add_coeffs) + ret = add_coefficients(avctx, frame, ax, ay, size, plane); + + return ret; +} + +static int get_prediction(AVCodecContext *avctx, int x, int y, int size) +{ + MobiClipContext *s = avctx->priv_data; + GetBitContext *gb = &s->gb; + int index = (y & 0xC) | (x / 4 % 4); + + uint8_t val = FFMIN(s->pre[index], index % 4 == 0 ? 9 : s->pre[index + 3]); + if (val == 9) + val = 3; + + if (!get_bits1(gb)) { + int x = get_bits(gb, 3); + val = x + (x >= val ? 1 : 0); + } + + s->pre[index + 4] = val; + if (size == 8) + s->pre[index + 5] = s->pre[index + 8] = s->pre[index + 9] = val; + + return val; +} + +static int process_block(AVCodecContext *avctx, AVFrame *frame, + int x, int y, int pmode, int has_coeffs, int plane) +{ + MobiClipContext *s = avctx->priv_data; + GetBitContext *gb = &s->gb; + int tmp, ret; + + if (!has_coeffs) { + if (pmode < 0) + pmode = get_prediction(avctx, x, y, 8); + return predict_intra(avctx, frame, x, y, pmode, 0, 8, plane); + } + + tmp = get_ue_golomb_31(gb); + if ((unsigned)tmp > FF_ARRAY_ELEMS(block4x4_coefficients_tab)) + return AVERROR_INVALIDDATA; + + if (tmp == 0) { + if (pmode < 0) + pmode = get_prediction(avctx, x, y, 8); + ret = predict_intra(avctx, frame, x, y, pmode, 1, 8, plane); + } else { + int flags = block4x4_coefficients_tab[tmp - 1]; + + for (int by = y; by < y + 8; by += 4) { + for (int bx = x; bx < x + 8; bx += 4) { + int new_pmode = pmode; + + if (new_pmode < 0) + new_pmode = get_prediction(avctx, bx, by, 4); + ret = predict_intra(avctx, frame, bx, by, new_pmode, flags & 1, 4, plane); + if (ret < 0) + return ret; + flags >>= 1; + } + } + } + + return ret; +} + +static int decode_macroblock(AVCodecContext *avctx, AVFrame *frame, + int x, int y, int predict) +{ + MobiClipContext *s = avctx->priv_data; + GetBitContext *gb = &s->gb; + int flags, pmode_uv, idx = get_ue_golomb(gb); + int ret = 0; + + if (idx < 0 || idx >= FF_ARRAY_ELEMS(block8x8_coefficients_tab)) + return AVERROR_INVALIDDATA; + + flags = block8x8_coefficients_tab[idx]; + + if (predict) { + ret = process_block(avctx, frame, x, y, -1, flags & 1, 0); + if (ret < 0) + return ret; + flags >>= 1; + ret = process_block(avctx, frame, x + 8, y, -1, flags & 1, 0); + if (ret < 0) + return ret; + flags >>= 1; + ret = process_block(avctx, frame, x, y + 8, -1, flags & 1, 0); + if (ret < 0) + return ret; + flags >>= 1; + ret = process_block(avctx, frame, x + 8, y + 8, -1, flags & 1, 0); + if (ret < 0) + return ret; + flags >>= 1; + } else { + int pmode = get_bits(gb, 3); + + if (pmode == 2) { + ret = predict_intra(avctx, frame, x, y, pmode, 0, 16, 0); + if (ret < 0) + return ret; + pmode = 9; + } + + ret = process_block(avctx, frame, x, y, pmode, flags & 1, 0); + if (ret < 0) + return ret; + flags >>= 1; + ret = process_block(avctx, frame, x + 8, y, pmode, flags & 1, 0); + if (ret < 0) + return ret; + flags >>= 1; + ret = process_block(avctx, frame, x, y + 8, pmode, flags & 1, 0); + if (ret < 0) + return ret; + flags >>= 1; + ret = process_block(avctx, frame, x + 8, y + 8, pmode, flags & 1, 0); + if (ret < 0) + return ret; + flags >>= 1; + } + + pmode_uv = get_bits(gb, 3); + if (pmode_uv == 2) { + ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 1 + !s->moflex); + if (ret < 0) + return ret; + ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 2 - !s->moflex); + if (ret < 0) + return ret; + pmode_uv = 9; + } + + ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 1 + !s->moflex); + if (ret < 0) + return ret; + flags >>= 1; + ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 2 - !s->moflex); + if (ret < 0) + return ret; + + return 0; +} + +static int get_index(int x) +{ + return x == 16 ? 0 : x == 8 ? 1 : x == 4 ? 2 : x == 2 ? 3 : 0; +} + +static int predict_motion(AVCodecContext *avctx, + int width, int height, int index, + int offsetm, int offsetx, int offsety) +{ + MobiClipContext *s = avctx->priv_data; + MotionXY *motion = s->motion; + GetBitContext *gb = &s->gb; + int fheight = avctx->height; + int fwidth = avctx->width; + + if (index <= 5) { + int sidx = -FFMAX(1, index) + s->current_pic; + MotionXY mv = s->motion[0]; + + if (sidx < 0) + sidx += 6; + + if (index > 0) { + mv.x = mv.x + (unsigned)get_se_golomb(gb); + mv.y = mv.y + (unsigned)get_se_golomb(gb); + } + if (mv.x >= INT_MAX || mv.y >= INT_MAX) + return AVERROR_INVALIDDATA; + + motion[offsetm].x = mv.x; + motion[offsetm].y = mv.y; + + for (int i = 0; i < 3; i++) { + int method, src_linesize, dst_linesize; + uint8_t *src, *dst; + + if (i == 1) { + offsetx = offsetx >> 1; + offsety = offsety >> 1; + mv.x = mv.x >> 1; + mv.y = mv.y >> 1; + width = width >> 1; + height = height >> 1; + fwidth = fwidth >> 1; + fheight = fheight >> 1; + } + + av_assert0(s->pic[sidx]); + av_assert0(s->pic[s->current_pic]); + av_assert0(s->pic[s->current_pic]->data[i]); + if (!s->pic[sidx]->data[i]) + return AVERROR_INVALIDDATA; + + method = (mv.x & 1) | ((mv.y & 1) << 1); + src_linesize = s->pic[sidx]->linesize[i]; + dst_linesize = s->pic[s->current_pic]->linesize[i]; + dst = s->pic[s->current_pic]->data[i] + offsetx + offsety * dst_linesize; + + if (offsetx + (mv.x >> 1) < 0 || + offsety + (mv.y >> 1) < 0 || + offsetx + width + (mv.x + 1 >> 1) > fwidth || + offsety + height + (mv.y + 1 >> 1) > fheight) + return AVERROR_INVALIDDATA; + + switch (method) { + case 0: + src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) + + (offsety + (mv.y >> 1)) * src_linesize; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) + dst[x] = src[x]; + dst += dst_linesize; + src += src_linesize; + } + break; + case 1: + src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) + + (offsety + (mv.y >> 1)) * src_linesize; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + dst[x] = (uint8_t)((src[x] >> 1) + (src[x + 1] >> 1)); + } + + dst += dst_linesize; + src += src_linesize; + } + break; + case 2: + src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) + + (offsety + (mv.y >> 1)) * src_linesize; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + dst[x] = (uint8_t)((src[x] >> 1) + (src[x + src_linesize] >> 1)); + } + + dst += dst_linesize; + src += src_linesize; + } + break; + case 3: + src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) + + (offsety + (mv.y >> 1)) * src_linesize; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + dst[x] = (uint8_t)((((src[x] >> 1) + (src[x + 1] >> 1)) >> 1) + + (((src[x + src_linesize] >> 1) + (src[x + 1 + src_linesize] >> 1)) >> 1)); + } + + dst += dst_linesize; + src += src_linesize; + } + break; + } + } + } else { + int tidx; + int adjx = index == 8 ? 0 : width / 2; + int adjy = index == 8 ? height / 2 : 0; + + width = width - adjx; + height = height - adjy; + tidx = get_index(height) * 4 + get_index(width); + + for (int i = 0; i < 2; i++) { + int ret, idx2; + + idx2 = get_vlc2(gb, mv_vlc[s->moflex][tidx].table, + MOBI_MV_VLC_BITS, 1); + + ret = predict_motion(avctx, width, height, idx2, + offsetm, offsetx + i * adjx, offsety + i * adjy); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int mobiclip_decode(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *pkt) +{ + MobiClipContext *s = avctx->priv_data; + GetBitContext *gb = &s->gb; + AVFrame *frame = s->pic[s->current_pic]; + int ret; + + av_fast_padded_malloc(&s->bitstream, &s->bitstream_size, + pkt->size); + + if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0) + return ret; + + s->bdsp.bswap16_buf((uint16_t *)s->bitstream, + (uint16_t *)pkt->data, + (pkt->size + 1) >> 1); + + ret = init_get_bits8(gb, s->bitstream, FFALIGN(pkt->size, 2)); + if (ret < 0) + return ret; + + if (get_bits1(gb)) { + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + s->moflex = get_bits1(gb); + s->dct_tab_idx = get_bits1(gb); + + ret = setup_qtables(avctx, get_bits(gb, 6)); + if (ret < 0) + return ret; + + for (int y = 0; y < avctx->height; y += 16) { + for (int x = 0; x < avctx->width; x += 16) { + ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb)); + if (ret < 0) + return ret; + } + } + } else { + MotionXY *motion = s->motion; + + memset(motion, 0, s->motion_size); + + frame->pict_type = AV_PICTURE_TYPE_P; + frame->key_frame = 0; + s->dct_tab_idx = 0; + + ret = setup_qtables(avctx, s->quantizer + get_se_golomb(gb)); + if (ret < 0) + return ret; + + for (int y = 0; y < avctx->height; y += 16) { + for (int x = 0; x < avctx->width; x += 16) { + int idx; + + motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x); + motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y); + motion[x / 16 + 2].x = 0; + motion[x / 16 + 2].y = 0; + + idx = get_vlc2(gb, mv_vlc[s->moflex][0].table, + MOBI_MV_VLC_BITS, 1); + + if (idx == 6 || idx == 7) { + ret = decode_macroblock(avctx, frame, x, y, idx == 7); + if (ret < 0) + return ret; + } else { + int flags, idx2; + ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y); + if (ret < 0) + return ret; + idx2 = get_ue_golomb(gb); + if (idx2 >= FF_ARRAY_ELEMS(pframe_block8x8_coefficients_tab)) + return AVERROR_INVALIDDATA; + flags = pframe_block8x8_coefficients_tab[idx2]; + + for (int sy = y; sy < y + 16; sy += 8) { + for (int sx = x; sx < x + 16; sx += 8) { + if (flags & 1) + add_pframe_coefficients(avctx, frame, sx, sy, 8, 0); + flags >>= 1; + } + } + + if (flags & 1) + add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex); + flags >>= 1; + if (flags & 1) + add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex); + } + } + } + } + + if (!s->moflex) + avctx->colorspace = AVCOL_SPC_YCGCO; + + s->current_pic = (s->current_pic + 1) % 6; + ret = av_frame_ref(data, frame); + if (ret < 0) + return ret; + *got_frame = 1; + + return 0; +} + +static void mobiclip_flush(AVCodecContext *avctx) +{ + MobiClipContext *s = avctx->priv_data; + + for (int i = 0; i < 6; i++) + av_frame_unref(s->pic[i]); +} + +static av_cold int mobiclip_close(AVCodecContext *avctx) +{ + MobiClipContext *s = avctx->priv_data; + + av_freep(&s->bitstream); + s->bitstream_size = 0; + av_freep(&s->motion); + s->motion_size = 0; + + for (int i = 0; i < 6; i++) { + av_frame_free(&s->pic[i]); + } + + return 0; +} + +AVCodec ff_mobiclip_decoder = { + .name = "mobiclip", + .long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MOBICLIP, + .priv_data_size = sizeof(MobiClipContext), + .init = mobiclip_init, + .decode = mobiclip_decode, + .flush = mobiclip_flush, + .close = mobiclip_close, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, +}; diff -Nru ffmpeg-4.2.2/libavcodec/motion_est.c ffmpeg-4.4/libavcodec/motion_est.c --- ffmpeg-4.2.2/libavcodec/motion_est.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/motion_est.c 2021-04-08 21:28:39.000000000 +0000 @@ -109,8 +109,8 @@ me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel){ MotionEstContext * const c= &s->me; const int stride= c->stride; - const int hx= subx + (x<<(1+qpel)); - const int hy= suby + (y<<(1+qpel)); + const int hx = subx + x * (1 << (1 + qpel)); + const int hy = suby + y * (1 << (1 + qpel)); uint8_t * const * const ref= c->ref[ref_index]; uint8_t * const * const src= c->src[src_index]; int d; @@ -578,7 +578,7 @@ int dmin_sum=0, mx4_sum=0, my4_sum=0, i; int same=1; const int stride= c->stride; - uint8_t *mv_penalty= c->current_mv_penalty; + const uint8_t *mv_penalty = c->current_mv_penalty; int safety_clipping= s->unrestricted_mv && (s->width&15) && (s->height&15); init_mv4_ref(c); @@ -599,7 +599,7 @@ P_LEFT[0] = s->current_picture.motion_val[0][mot_xy - 1][0]; P_LEFT[1] = s->current_picture.motion_val[0][mot_xy - 1][1]; - if(P_LEFT[0] > (c->xmax<xmax< c->xmax * (1 << shift)) P_LEFT[0] = c->xmax * (1 << shift); /* special case for first line */ if (s->first_slice_line && block<2) { @@ -610,10 +610,10 @@ P_TOP[1] = s->current_picture.motion_val[0][mot_xy - mot_stride ][1]; P_TOPRIGHT[0] = s->current_picture.motion_val[0][mot_xy - mot_stride + off[block]][0]; P_TOPRIGHT[1] = s->current_picture.motion_val[0][mot_xy - mot_stride + off[block]][1]; - if(P_TOP[1] > (c->ymax<ymax<xmin<xmin< (c->xmax<xmax< (c->ymax<ymax< c->ymax * (1 << shift)) P_TOP[1] = c->ymax * (1 << shift); + if (P_TOPRIGHT[0] < c->xmin * (1 << shift)) P_TOPRIGHT[0] = c->xmin * (1 << shift); + if (P_TOPRIGHT[0] > c->xmax * (1 << shift)) P_TOPRIGHT[0] = c->xmax * (1 << shift); + if (P_TOPRIGHT[1] > c->ymax * (1 << shift)) P_TOPRIGHT[1] = c->ymax * (1 << shift); P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]); P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]); @@ -629,8 +629,8 @@ continue; if (i>4 && i<9) continue; - if(P[i][0] > (c->xmax<xmax< (c->ymax<ymax< c->xmax * (1 << shift)) P[i][0] = c->xmax * (1 << shift); + if (P[i][1] > c->ymax * (1 << shift)) P[i][1] = c->ymax * (1 <p_mv_table, (1<<16)>>shift, 1); @@ -743,7 +743,7 @@ const int h=8; int block; int P[10][2]; - uint8_t * const mv_penalty= c->current_mv_penalty; + const uint8_t * const mv_penalty = c->current_mv_penalty; int same=1; const int stride= 2*s->linesize; int dmin_sum= 0; @@ -785,7 +785,7 @@ P_TOPRIGHT[0] = mv_table[xy - mot_stride + 1][0]; P_TOPRIGHT[1] = mv_table[xy - mot_stride + 1][1]; if(P_TOP[1] > (c->ymax<<1)) P_TOP[1] = (c->ymax<<1); - if(P_TOPRIGHT[0] < (c->xmin<<1)) P_TOPRIGHT[0]= (c->xmin<<1); + if (P_TOPRIGHT[0] < c->xmin * (1 << 1)) P_TOPRIGHT[0] = c->xmin * (1 << 1); if(P_TOPRIGHT[0] > (c->xmax<<1)) P_TOPRIGHT[0]= (c->xmax<<1); if(P_TOPRIGHT[1] > (c->ymax<<1)) P_TOPRIGHT[1]= (c->ymax<<1); @@ -839,7 +839,7 @@ dmin_sum += best_dmin; } - c->ymin<<=1; + c->ymin *= 2; c->ymax<<=1; c->stride>>=1; c->uvstride>>=1; @@ -971,7 +971,7 @@ int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20; c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score); - if (vard*2 + 200*256 > varc) + if (vard*2 + 200*256 > varc && !s->intra_penalty) mb_type|= CANDIDATE_MB_TYPE_INTRA; if (varc*2 + 200*256 > vard || s->qscale > 24){ // if (varc*2 + 200*256 + 50*(s->lambda2>>FF_LAMBDA_SHIFT) > vard){ @@ -981,8 +981,8 @@ if(mx || my) mb_type |= CANDIDATE_MB_TYPE_SKIPPED; //FIXME check difference }else{ - mx <<=shift; - my <<=shift; + mx *= 1 << shift; + my *= 1 << shift; } if ((s->avctx->flags & AV_CODEC_FLAG_4MV) && !c->skip && varc>50<<8 && vard>10<<8){ @@ -1040,7 +1040,7 @@ intra_score= s->mecc.mb_cmp[0](s, c->scratchpad, pix, s->linesize, 16); } - intra_score += c->mb_penalty_factor*16; + intra_score += c->mb_penalty_factor*16 + s->intra_penalty; if(intra_score < dmin){ mb_type= CANDIDATE_MB_TYPE_INTRA; @@ -1120,7 +1120,7 @@ const int shift= 1+s->quarter_sample; const int mot_stride = s->mb_stride; const int mot_xy = mb_y*mot_stride + mb_x; - uint8_t * const mv_penalty= c->mv_penalty[f_code] + MAX_DMV; + const uint8_t * const mv_penalty = c->mv_penalty[f_code] + MAX_DMV; int mv_scale; c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp); @@ -1143,7 +1143,7 @@ P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1][0]; P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1][1]; if (P_TOP[1] > (c->ymax << shift)) P_TOP[1] = (c->ymax << shift); - if (P_TOPRIGHT[0] < (c->xmin << shift)) P_TOPRIGHT[0] = (c->xmin << shift); + if (P_TOPRIGHT[0] < c->xmin * (1 << shift)) P_TOPRIGHT[0] = c->xmin * (1 << shift); if (P_TOPRIGHT[1] > (c->ymax << shift)) P_TOPRIGHT[1] = (c->ymax << shift); P_MEDIAN[0] = mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]); @@ -1155,7 +1155,7 @@ if(mv_table == s->b_forw_mv_table){ mv_scale= (s->pb_time<<16) / (s->pp_time<pb_time - s->pp_time)<<16) / (s->pp_time<pb_time - s->pp_time) * (1 << 16)) / (s->pp_time<p_mv_table, mv_scale, 0, 16); @@ -1184,8 +1184,8 @@ //FIXME better f_code prediction (max mv & distance) //FIXME pointers MotionEstContext * const c= &s->me; - uint8_t * const mv_penalty_f= c->mv_penalty[s->f_code] + MAX_DMV; // f_code of the prev frame - uint8_t * const mv_penalty_b= c->mv_penalty[s->b_code] + MAX_DMV; // f_code of the prev frame + const uint8_t * const mv_penalty_f = c->mv_penalty[s->f_code] + MAX_DMV; // f_code of the prev frame + const uint8_t * const mv_penalty_b = c->mv_penalty[s->b_code] + MAX_DMV; // f_code of the prev frame int stride= c->stride; uint8_t *dest_y = c->scratchpad; uint8_t *ptr; @@ -1255,8 +1255,8 @@ const int flags= c->sub_flags; const int qpel= flags&FLAG_QPEL; const int shift= 1+qpel; - const int xmin= c->xmin<ymin<xmin * (1 << shift); + const int ymin= c->ymin * (1 << shift); const int xmax= c->xmax<ymax<pred_x=0; c->pred_y=0; - P_LEFT[0] = av_clip(mv_table[mot_xy - 1][0], xmin<first_slice_line) { //FIXME maybe allow this over thread boundary as it is clipped - P_TOP[0] = av_clip(mv_table[mot_xy - mot_stride ][0], xmin<motion_est != FF_ME_ZERO) { int score[8]; int i, y, range= s->avctx->me_range ? s->avctx->me_range : (INT_MAX/2); - uint8_t * fcode_tab= s->fcode_tab; + const uint8_t * fcode_tab = s->fcode_tab; int best_fcode=-1; int best_score=-10000000; @@ -1648,7 +1648,7 @@ } } -void ff_fix_long_p_mvs(MpegEncContext * s) +void ff_fix_long_p_mvs(MpegEncContext * s, int type) { MotionEstContext * const c= &s->me; const int f_code= s->f_code; @@ -1682,8 +1682,8 @@ if( mx >=range || mx <-range || my >=range || my <-range){ s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V; - s->mb_type[i] |= CANDIDATE_MB_TYPE_INTRA; - s->current_picture.mb_type[i] = CANDIDATE_MB_TYPE_INTRA; + s->mb_type[i] |= type; + s->current_picture.mb_type[i] = type; } } } diff -Nru ffmpeg-4.2.2/libavcodec/motion_est.h ffmpeg-4.4/libavcodec/motion_est.h --- ffmpeg-4.2.2/libavcodec/motion_est.h 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/motion_est.h 2021-04-08 21:28:39.000000000 +0000 @@ -90,8 +90,8 @@ op_pixels_func(*hpel_avg)[4]; qpel_mc_func(*qpel_put)[16]; qpel_mc_func(*qpel_avg)[16]; - uint8_t (*mv_penalty)[MAX_DMV * 2 + 1]; ///< bit amount needed to encode a MV - uint8_t *current_mv_penalty; + const uint8_t (*mv_penalty)[MAX_DMV * 2 + 1]; ///< bit amount needed to encode a MV + const uint8_t *current_mv_penalty; int (*sub_motion_search)(struct MpegEncContext *s, int *mx_ptr, int *my_ptr, int dmin, int src_index, int ref_index, @@ -127,7 +127,7 @@ int ff_get_best_fcode(struct MpegEncContext *s, int16_t (*mv_table)[2], int type); -void ff_fix_long_p_mvs(struct MpegEncContext *s); +void ff_fix_long_p_mvs(struct MpegEncContext *s, int type); void ff_fix_long_mvs(struct MpegEncContext *s, uint8_t *field_select_table, int field_select, int16_t (*mv_table)[2], int f_code, int type, int truncate); diff -Nru ffmpeg-4.2.2/libavcodec/motion_est_template.c ffmpeg-4.4/libavcodec/motion_est_template.c --- ffmpeg-4.2.2/libavcodec/motion_est_template.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/motion_est_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,7 +34,7 @@ const int av_unused ymin= c->ymin;\ const int av_unused xmax= c->xmax;\ const int av_unused ymax= c->ymax;\ - uint8_t *mv_penalty= c->current_mv_penalty;\ + const uint8_t *mv_penalty = c->current_mv_penalty; \ const int pred_x= c->pred_x;\ const int pred_y= c->pred_y;\ @@ -82,7 +82,7 @@ if (mx > xmin && mx < xmax && my > ymin && my < ymax) { int d= dmin; - const int index= (my<penalty_factor; const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)] @@ -95,13 +95,13 @@ #if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1 unsigned key; unsigned map_generation= c->map_generation; - key= ((my-1)<map[(index-(1<map[(index+(1<map[(index+1)&(ME_MAP_SIZE-1)] == key); - key= ((my)<map[(index-1)&(ME_MAP_SIZE-1)] == key); #endif if(t<=b){ @@ -157,8 +157,8 @@ int src_index, int ref_index, int size, int h) { - (*mx_ptr)<<=1; - (*my_ptr)<<=1; + (*mx_ptr) *= 2; + (*my_ptr) *= 2; return dmin; } @@ -246,7 +246,7 @@ int bx=4*mx, by=4*my; int d= dmin; int i, nx, ny; - const int index= (my<priv_data; int w4 = (avctx->width + 3) & ~3; int h4 = (avctx->height + 3) & ~3; @@ -74,26 +78,23 @@ return AVERROR_INVALIDDATA; } - motionpixels_tableinit(); mp->avctx = avctx; ff_bswapdsp_init(&mp->bdsp); mp->changes_map = av_mallocz_array(avctx->width, h4); mp->offset_bits_len = av_log2(avctx->width * avctx->height) + 1; mp->vpt = av_mallocz_array(avctx->height, sizeof(YuvPixel)); mp->hpt = av_mallocz_array(h4 / 4, w4 / 4 * sizeof(YuvPixel)); - if (!mp->changes_map || !mp->vpt || !mp->hpt) { - av_freep(&mp->changes_map); - av_freep(&mp->vpt); - av_freep(&mp->hpt); + if (!mp->changes_map || !mp->vpt || !mp->hpt) return AVERROR(ENOMEM); - } avctx->pix_fmt = AV_PIX_FMT_RGB555; mp->frame = av_frame_alloc(); - if (!mp->frame) { - mp_decode_end(avctx); + if (!mp->frame) return AVERROR(ENOMEM); - } + +#if !CONFIG_HARDCODED_TABLES + ff_thread_once(&init_static_once, motionpixels_tableinit); +#endif return 0; } @@ -127,7 +128,7 @@ } } -static int mp_get_code(MotionPixelsContext *mp, GetBitContext *gb, int size, int code) +static int mp_get_code(MotionPixelsContext *mp, GetBitContext *gb, int size) { while (get_bits1(gb)) { ++size; @@ -135,16 +136,14 @@ av_log(mp->avctx, AV_LOG_ERROR, "invalid code size %d/%d\n", size, mp->max_codes_bits); return AVERROR_INVALIDDATA; } - code <<= 1; - if (mp_get_code(mp, gb, size, code + 1) < 0) + if (mp_get_code(mp, gb, size) < 0) return AVERROR_INVALIDDATA; } - if (mp->current_codes_count >= MAX_HUFF_CODES) { + if (mp->current_codes_count >= mp->codes_count) { av_log(mp->avctx, AV_LOG_ERROR, "too many codes\n"); return AVERROR_INVALIDDATA; } - mp->codes[mp->current_codes_count ].code = code; mp->codes[mp->current_codes_count++].size = size; return 0; } @@ -161,7 +160,7 @@ for (i = 0; i < mp->codes_count; ++i) mp->codes[i].delta = get_bits(gb, 4); mp->current_codes_count = 0; - if ((ret = mp_get_code(mp, gb, 0, 0)) < 0) + if ((ret = mp_get_code(mp, gb, 0)) < 0) return ret; if (mp->current_codes_count < mp->codes_count) { av_log(mp->avctx, AV_LOG_ERROR, "too few codes\n"); @@ -198,12 +197,8 @@ static av_always_inline int mp_get_vlc(MotionPixelsContext *mp, GetBitContext *gb) { - int i; - - i = (mp->codes_count == 1) ? 0 : get_vlc2(gb, mp->vlc.table, mp->max_codes_bits, 1); - if (i < 0) - return i; - return mp->codes[i].delta; + return mp->vlc.table ? get_vlc2(gb, mp->vlc.table, mp->max_codes_bits, 1) + : mp->codes[0].delta; } static void mp_decode_line(MotionPixelsContext *mp, GetBitContext *gb, int y) @@ -292,7 +287,7 @@ GetBitContext gb; int i, count1, count2, sz, ret; - if ((ret = ff_reget_buffer(avctx, mp->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, mp->frame, 0)) < 0) return ret; /* le32 bitstream msb first */ @@ -330,10 +325,16 @@ if (sz == 0) goto end; - if (mp->max_codes_bits <= 0) - goto end; - if (init_vlc(&mp->vlc, mp->max_codes_bits, mp->codes_count, &mp->codes[0].size, sizeof(HuffCode), 1, &mp->codes[0].code, sizeof(HuffCode), 4, 0)) - goto end; + if (mp->codes_count > 1) { + /* The entries of the mp->codes array are sorted from right to left + * in the Huffman tree, hence -(int)sizeof(HuffCode). */ + ret = ff_init_vlc_from_lengths(&mp->vlc, mp->max_codes_bits, mp->codes_count, + &mp->codes[mp->codes_count - 1].size, -(int)sizeof(HuffCode), + &mp->codes[mp->codes_count - 1].delta, -(int)sizeof(HuffCode), 1, + 0, 0, avctx); + if (ret < 0) + goto end; + } mp_decode_frame_helper(mp, &gb); ff_free_vlc(&mp->vlc); @@ -354,4 +355,5 @@ .close = mp_decode_end, .decode = mp_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/motionpixels_tablegen.h ffmpeg-4.4/libavcodec/motionpixels_tablegen.h --- ffmpeg-4.2.2/libavcodec/motionpixels_tablegen.h 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/motionpixels_tablegen.h 2021-04-08 21:28:39.000000000 +0000 @@ -84,8 +84,7 @@ static av_cold void motionpixels_tableinit(void) { - if (!mp_rgb_yuv_table[0].u) - mp_build_rgb_yuv_table(mp_rgb_yuv_table); + mp_build_rgb_yuv_table(mp_rgb_yuv_table); } #endif /* CONFIG_HARDCODED_TABLES */ diff -Nru ffmpeg-4.2.2/libavcodec/movsub_bsf.c ffmpeg-4.4/libavcodec/movsub_bsf.c --- ffmpeg-4.2.2/libavcodec/movsub_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/movsub_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -20,8 +20,8 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" static int text2movsub(AVBSFContext *ctx, AVPacket *out) { diff -Nru ffmpeg-4.2.2/libavcodec/movtextdec.c ffmpeg-4.4/libavcodec/movtextdec.c --- ffmpeg-4.2.2/libavcodec/movtextdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/movtextdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,11 +21,13 @@ #include "avcodec.h" #include "ass.h" +#include "libavutil/opt.h" #include "libavutil/avstring.h" #include "libavutil/common.h" #include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" +#include "bytestream.h" #define STYLE_FLAG_BOLD (1<<0) #define STYLE_FLAG_ITALIC (1<<1) @@ -48,14 +50,19 @@ #define TOP_CENTER 8 #define TOP_RIGHT 9 +#define RGB_TO_BGR(c) (((c) & 0xff) << 16 | ((c) & 0xff00) | (((c) >> 16) & 0xff)) + typedef struct { - char *font; - int fontsize; + uint16_t fontID; + const char *font; + uint8_t fontsize; int color; + uint8_t alpha; int back_color; - int bold; - int italic; - int underline; + uint8_t back_alpha; + uint8_t bold; + uint8_t italic; + uint8_t underline; int alignment; } MovTextDefault; @@ -68,6 +75,11 @@ uint16_t style_start; uint16_t style_end; uint8_t style_flag; + uint8_t bold; + uint8_t italic; + uint8_t underline; + int color; + uint8_t alpha; uint8_t fontsize; uint16_t style_fontID; } StyleBox; @@ -86,75 +98,61 @@ } TextWrapBox; typedef struct { - StyleBox **s; - StyleBox *s_temp; + AVClass *class; + StyleBox *s; HighlightBox h; HilightcolorBox c; - FontRecord **ftab; - FontRecord *ftab_temp; + FontRecord *ftab; TextWrapBox w; MovTextDefault d; uint8_t box_flags; uint16_t style_entries, ftab_entries; uint64_t tracksize; int size_var; - int count_s, count_f; int readorder; + int frame_width; + int frame_height; } MovTextContext; typedef struct { uint32_t type; size_t base_size; - int (*decode)(const uint8_t *tsmb, MovTextContext *m, AVPacket *avpkt); + int (*decode)(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt); } Box; static void mov_text_cleanup(MovTextContext *m) { - int i; if (m->box_flags & STYL_BOX) { - for(i = 0; i < m->count_s; i++) { - av_freep(&m->s[i]); - } av_freep(&m->s); - m->count_s = 0; m->style_entries = 0; } } static void mov_text_cleanup_ftab(MovTextContext *m) { - int i; - if (m->ftab_temp) - av_freep(&m->ftab_temp->font); - av_freep(&m->ftab_temp); - if (m->ftab) { - for(i = 0; i < m->count_f; i++) { - av_freep(&m->ftab[i]->font); - av_freep(&m->ftab[i]); - } - } + for (unsigned i = 0; i < m->ftab_entries; i++) + av_freep(&m->ftab[i].font); av_freep(&m->ftab); + m->ftab_entries = 0; } static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m) { - uint8_t *tx3g_ptr = avctx->extradata; - int i, box_size, font_length; + 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; - int style_fontID; + unsigned ftab_entries; StyleBox s_default; - m->count_f = 0; m->ftab_entries = 0; - box_size = BOX_SIZE_INITIAL; /* Size till ftab_entries */ - if (avctx->extradata_size < box_size) + if (remaining < 0) return -1; // Display Flags tx3g_ptr += 4; // Alignment - h_align = *tx3g_ptr++; - v_align = *tx3g_ptr++; + h_align = bytestream_get_byte(&tx3g_ptr); + v_align = bytestream_get_byte(&tx3g_ptr); if (h_align == 0) { if (v_align == 0) m->d.alignment = TOP_LEFT; @@ -180,147 +178,133 @@ m->d.alignment = BOTTOM_RIGHT; } // Background Color - m->d.back_color = AV_RB24(tx3g_ptr); - tx3g_ptr += 4; + m->d.back_color = bytestream_get_be24(&tx3g_ptr); + m->d.back_alpha = bytestream_get_byte(&tx3g_ptr); // BoxRecord tx3g_ptr += 8; // StyleRecord tx3g_ptr += 4; // fontID - style_fontID = AV_RB16(tx3g_ptr); - tx3g_ptr += 2; + m->d.fontID = bytestream_get_be16(&tx3g_ptr); // face-style-flags - s_default.style_flag = *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; + 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 = *tx3g_ptr++; + m->d.fontsize = bytestream_get_byte(&tx3g_ptr); // Primary color - m->d.color = AV_RB24(tx3g_ptr); - tx3g_ptr += 4; + m->d.color = bytestream_get_be24(&tx3g_ptr); + m->d.alpha = bytestream_get_byte(&tx3g_ptr); // FontRecord // FontRecord Size tx3g_ptr += 4; // ftab tx3g_ptr += 4; - m->ftab_entries = AV_RB16(tx3g_ptr); - tx3g_ptr += 2; + // In case of broken header, init default font + m->d.font = ASS_DEFAULT_FONT; - for (i = 0; i < m->ftab_entries; i++) { + ftab_entries = bytestream_get_be16(&tx3g_ptr); + if (!ftab_entries) + return 0; + remaining -= 3 * ftab_entries; + if (remaining < 0) + return AVERROR_INVALIDDATA; + m->ftab = av_calloc(ftab_entries, sizeof(*m->ftab)); + if (!m->ftab) + return AVERROR(ENOMEM); + m->ftab_entries = ftab_entries; - box_size += 3; - if (avctx->extradata_size < box_size) { - mov_text_cleanup_ftab(m); - m->ftab_entries = 0; - return -1; - } - m->ftab_temp = av_mallocz(sizeof(*m->ftab_temp)); - if (!m->ftab_temp) { - mov_text_cleanup_ftab(m); - return AVERROR(ENOMEM); - } - m->ftab_temp->fontID = AV_RB16(tx3g_ptr); - tx3g_ptr += 2; - font_length = *tx3g_ptr++; + 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) + j = i; + font_length = bytestream_get_byte(&tx3g_ptr); - box_size = box_size + font_length; - if (avctx->extradata_size < box_size) { + remaining -= font_length; + if (remaining < 0) { mov_text_cleanup_ftab(m); - m->ftab_entries = 0; return -1; } - m->ftab_temp->font = av_malloc(font_length + 1); - if (!m->ftab_temp->font) { + m->ftab[i].font = av_malloc(font_length + 1); + if (!m->ftab[i].font) { mov_text_cleanup_ftab(m); return AVERROR(ENOMEM); } - memcpy(m->ftab_temp->font, tx3g_ptr, font_length); - m->ftab_temp->font[font_length] = '\0'; - av_dynarray_add(&m->ftab, &m->count_f, m->ftab_temp); - if (!m->ftab) { - mov_text_cleanup_ftab(m); - return AVERROR(ENOMEM); - } - m->ftab_temp = NULL; - tx3g_ptr = tx3g_ptr + font_length; - } - for (i = 0; i < m->ftab_entries; i++) { - if (style_fontID == m->ftab[i]->fontID) - m->d.font = m->ftab[i]->font; + bytestream_get_buffer(&tx3g_ptr, m->ftab[i].font, font_length); + m->ftab[i].font[font_length] = '\0'; } + if (j >= 0) + m->d.font = m->ftab[j].font; return 0; } -static int decode_twrp(const uint8_t *tsmb, MovTextContext *m, AVPacket *avpkt) +static int decode_twrp(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) { m->box_flags |= TWRP_BOX; - m->w.wrap_flag = *tsmb++; + m->w.wrap_flag = bytestream_get_byte(&tsmb); return 0; } -static int decode_hlit(const uint8_t *tsmb, MovTextContext *m, AVPacket *avpkt) +static int decode_hlit(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) { m->box_flags |= HLIT_BOX; - m->h.hlit_start = AV_RB16(tsmb); - tsmb += 2; - m->h.hlit_end = AV_RB16(tsmb); - tsmb += 2; + m->h.hlit_start = bytestream_get_be16(&tsmb); + m->h.hlit_end = bytestream_get_be16(&tsmb); return 0; } -static int decode_hclr(const uint8_t *tsmb, MovTextContext *m, AVPacket *avpkt) +static int decode_hclr(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) { m->box_flags |= HCLR_BOX; - memcpy(m->c.hlit_color, tsmb, 4); - tsmb += 4; + bytestream_get_buffer(&tsmb, m->c.hlit_color, 4); return 0; } -static int decode_styl(const uint8_t *tsmb, MovTextContext *m, AVPacket *avpkt) +static int decode_styl(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) { int i; - int style_entries = AV_RB16(tsmb); - tsmb += 2; + 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) return -1; + tmp = av_realloc_array(m->s, style_entries, sizeof(*m->s)); + if (!tmp) + return AVERROR(ENOMEM); + m->s = tmp; m->style_entries = style_entries; m->box_flags |= STYL_BOX; for(i = 0; i < m->style_entries; i++) { - m->s_temp = av_malloc(sizeof(*m->s_temp)); - if (!m->s_temp) { - mov_text_cleanup(m); - return AVERROR(ENOMEM); - } - m->s_temp->style_start = AV_RB16(tsmb); - tsmb += 2; - m->s_temp->style_end = AV_RB16(tsmb); - - if ( m->s_temp->style_end < m->s_temp->style_start - || (m->count_s && m->s_temp->style_start < m->s[m->count_s - 1]->style_end)) { - av_freep(&m->s_temp); - mov_text_cleanup(m); - return AVERROR(ENOMEM); - } + StyleBox *style = &m->s[i]; - tsmb += 2; - m->s_temp->style_fontID = AV_RB16(tsmb); - tsmb += 2; - m->s_temp->style_flag = AV_RB8(tsmb); - tsmb++; - m->s_temp->fontsize = AV_RB8(tsmb); - av_dynarray_add(&m->s, &m->count_s, m->s_temp); - if(!m->s) { + 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)) { mov_text_cleanup(m); return AVERROR(ENOMEM); } - tsmb++; - // text-color-rgba - tsmb += 4; + if (style->style_start == style->style_end) { + /* Skip this style as it applies to no character */ + tsmb += 8; + m->style_entries--; + i--; + 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); } return 0; } @@ -353,8 +337,9 @@ { MovTextContext *m = avctx->priv_data; int i = 0; - int j = 0; int text_pos = 0; + int entry = 0; + int color = m->d.color; if (text < text_end && m->box_flags & TWRP_BOX) { if (m->w.wrap_flag == 1) { @@ -367,26 +352,34 @@ while (text < text_end) { int len; - if (m->box_flags & STYL_BOX) { - for (i = 0; i < m->style_entries; i++) { - if (m->s[i]->style_flag && text_pos == m->s[i]->style_end) { - av_bprintf(buf, "{\\r}"); - } + if ((m->box_flags & STYL_BOX) && entry < m->style_entries) { + const StyleBox *style = &m->s[entry]; + if (text_pos == style->style_end) { + av_bprintf(buf, "{\\r}"); + color = m->d.color; + entry++; + style++; } - for (i = 0; i < m->style_entries; i++) { - if (m->s[i]->style_flag && text_pos == m->s[i]->style_start) { - if (m->s[i]->style_flag & STYLE_FLAG_BOLD) - av_bprintf(buf, "{\\b1}"); - if (m->s[i]->style_flag & STYLE_FLAG_ITALIC) - av_bprintf(buf, "{\\i1}"); - if (m->s[i]->style_flag & STYLE_FLAG_UNDERLINE) - av_bprintf(buf, "{\\u1}"); - av_bprintf(buf, "{\\fs%d}", m->s[i]->fontsize); - for (j = 0; j < m->ftab_entries; j++) { - if (m->s[i]->style_fontID == m->ftab[j]->fontID) - av_bprintf(buf, "{\\fn%s}", m->ftab[j]->font); + if (entry < m->style_entries && text_pos == style->style_start) { + if (style->bold ^ m->d.bold) + av_bprintf(buf, "{\\b%d}", style->bold); + if (style->italic ^ m->d.italic) + av_bprintf(buf, "{\\i%d}", style->italic); + if (style->underline ^ m->d.underline) + av_bprintf(buf, "{\\u%d}", style->underline); + if (style->fontsize != m->d.fontsize) + av_bprintf(buf, "{\\fs%d}", style->fontsize); + if (style->style_fontID != m->d.fontID) + for (i = 0; i < m->ftab_entries; i++) { + if (style->style_fontID == m->ftab[i].fontID) + av_bprintf(buf, "{\\fn%s}", m->ftab[i].font); } + if (m->d.color != style->color) { + color = style->color; + av_bprintf(buf, "{\\1c&H%X&}", RGB_TO_BGR(color)); } + if (m->d.alpha != style->alpha) + av_bprintf(buf, "{\\1a&H%02X&}", 255 - style->alpha); } } if (m->box_flags & HLIT_BOX) { @@ -406,9 +399,10 @@ } if (text_pos == m->h.hlit_end) { if (m->box_flags & HCLR_BOX) { - av_bprintf(buf, "{\\2c&H000000&}"); + av_bprintf(buf, "{\\2c&H%X&}", RGB_TO_BGR(m->d.color)); } else { - av_bprintf(buf, "{\\1c&HFFFFFF&}{\\2c&H000000&}"); + av_bprintf(buf, "{\\1c&H%X&}{\\2c&H%X&}", + RGB_TO_BGR(color), RGB_TO_BGR(m->d.color)); } } } @@ -418,19 +412,17 @@ av_log(avctx, AV_LOG_ERROR, "invalid UTF-8 byte in subtitle\n"); len = 1; } - for (i = 0; i < len; i++) { - switch (*text) { - case '\r': - break; - case '\n': - av_bprintf(buf, "\\N"); - break; - default: - av_bprint_chars(buf, *text, 1); - break; - } - text++; + switch (*text) { + case '\r': + break; + case '\n': + av_bprintf(buf, "\\N"); + break; + default: + av_bprint_append_data(buf, text, len); + break; } + text += len; text_pos++; } @@ -448,10 +440,19 @@ MovTextContext *m = avctx->priv_data; ret = mov_text_tx3g(avctx, m); if (ret == 0) { - return ff_ass_subtitle_header(avctx, m->d.font, m->d.fontsize, m->d.color, - m->d.back_color, m->d.bold, m->d.italic, - m->d.underline, ASS_DEFAULT_BORDERSTYLE, - m->d.alignment); + 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, + ASS_DEFAULT_BORDERSTYLE, m->d.alignment); } else return ff_ass_subtitle_header_default(avctx); } @@ -498,7 +499,6 @@ m->tracksize = 2 + text_length; m->style_entries = 0; m->box_flags = 0; - m->count_s = 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) { @@ -567,12 +567,28 @@ m->readorder = 0; } +#define OFFSET(x) offsetof(MovTextContext, x) +#define FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_SUBTITLE_PARAM +static const AVOption options[] = { + { "width", "Frame width, usually video width", OFFSET(frame_width), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, + { "height", "Frame height, usually video height", OFFSET(frame_height), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, + { NULL }, +}; + +static const AVClass mov_text_decoder_class = { + .class_name = "MOV text decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_movtext_decoder = { .name = "mov_text", .long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"), .type = AVMEDIA_TYPE_SUBTITLE, .id = AV_CODEC_ID_MOV_TEXT, .priv_data_size = sizeof(MovTextContext), + .priv_class = &mov_text_decoder_class, .init = mov_text_init, .decode = mov_text_decode_frame, .close = mov_text_decode_close, diff -Nru ffmpeg-4.2.2/libavcodec/movtextenc.c ffmpeg-4.4/libavcodec/movtextenc.c --- ffmpeg-4.2.2/libavcodec/movtextenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/movtextenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,7 @@ #include #include "avcodec.h" +#include "libavutil/opt.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" @@ -28,6 +29,8 @@ #include "libavutil/common.h" #include "ass_split.h" #include "ass.h" +#include "bytestream.h" +#include "internal.h" #define STYLE_FLAG_BOLD (1<<0) #define STYLE_FLAG_ITALIC (1<<1) @@ -39,12 +42,22 @@ #define HLIT_BOX (1<<1) #define HCLR_BOX (1<<2) +#define DEFAULT_STYLE_FONT_ID 0x01 +#define DEFAULT_STYLE_FONTSIZE 0x12 +#define DEFAULT_STYLE_COLOR 0xffffffff +#define DEFAULT_STYLE_FLAG 0x00 + +#define BGR_TO_RGB(c) (((c) & 0xff) << 16 | ((c) & 0xff00) | (((uint32_t)(c) >> 16) & 0xff)) +#define FONTSIZE_SCALE(s,fs) ((fs) * (s)->font_scale_factor + 0.5) #define av_bprint_append_any(buf, data, size) av_bprint_append_data(buf, ((const char*)data), size) typedef struct { uint16_t style_start; uint16_t style_end; uint8_t style_flag; + uint16_t style_fontID; + uint8_t style_fontsize; + uint32_t style_color; } StyleBox; typedef struct { @@ -57,252 +70,519 @@ } HilightcolorBox; typedef struct { + AVClass *class; AVCodecContext *avctx; ASSSplitContext *ass_ctx; + ASSStyle *ass_dialog_style; + StyleBox *style_attributes; + unsigned count; + unsigned style_attributes_bytes_allocated; + StyleBox style_attributes_temp; AVBPrint buffer; - StyleBox **style_attributes; - StyleBox *style_attributes_temp; HighlightBox hlit; HilightcolorBox hclr; - int count; uint8_t box_flags; - uint16_t style_entries; - uint16_t style_fontID; - uint8_t style_fontsize; - uint32_t style_color; + StyleBox d; uint16_t text_pos; uint16_t byte_count; + char **fonts; + int font_count; + double font_scale_factor; + int frame_height; } MovTextContext; typedef struct { - uint32_t type; - void (*encode)(MovTextContext *s, uint32_t tsmb_type); + void (*encode)(MovTextContext *s); } Box; static void mov_text_cleanup(MovTextContext *s) { - int j; - if (s->box_flags & STYL_BOX) { - for (j = 0; j < s->count; j++) { - av_freep(&s->style_attributes[j]); - } - av_freep(&s->style_attributes); - } + s->count = 0; + s->style_attributes_temp = s->d; } -static void encode_styl(MovTextContext *s, uint32_t tsmb_type) +static void encode_styl(MovTextContext *s) { - int j; - uint32_t tsmb_size; - if (s->box_flags & STYL_BOX) { - tsmb_size = s->count * STYLE_RECORD_SIZE + SIZE_ADD; - tsmb_size = AV_RB32(&tsmb_size); - s->style_entries = AV_RB16(&s->count); - s->style_fontID = 0x00 | 0x01<<8; - s->style_fontsize = 0x12; - s->style_color = MKTAG(0xFF, 0xFF, 0xFF, 0xFF); + if ((s->box_flags & STYL_BOX) && s->count) { + uint8_t buf[12], *p = buf; + + bytestream_put_be32(&p, s->count * STYLE_RECORD_SIZE + SIZE_ADD); + bytestream_put_be32(&p, MKBETAG('s','t','y','l')); + bytestream_put_be16(&p, s->count); /*The above three attributes are hard coded for now but will come from ASS style in the future*/ - av_bprint_append_any(&s->buffer, &tsmb_size, 4); - av_bprint_append_any(&s->buffer, &tsmb_type, 4); - av_bprint_append_any(&s->buffer, &s->style_entries, 2); - for (j = 0; j < s->count; j++) { - av_bprint_append_any(&s->buffer, &s->style_attributes[j]->style_start, 2); - av_bprint_append_any(&s->buffer, &s->style_attributes[j]->style_end, 2); - av_bprint_append_any(&s->buffer, &s->style_fontID, 2); - av_bprint_append_any(&s->buffer, &s->style_attributes[j]->style_flag, 1); - av_bprint_append_any(&s->buffer, &s->style_fontsize, 1); - av_bprint_append_any(&s->buffer, &s->style_color, 4); + av_bprint_append_any(&s->buffer, buf, 10); + for (unsigned j = 0; j < s->count; j++) { + const StyleBox *style = &s->style_attributes[j]; + + p = buf; + bytestream_put_be16(&p, style->style_start); + bytestream_put_be16(&p, style->style_end); + bytestream_put_be16(&p, style->style_fontID); + bytestream_put_byte(&p, style->style_flag); + bytestream_put_byte(&p, style->style_fontsize); + bytestream_put_be32(&p, style->style_color); + + av_bprint_append_any(&s->buffer, buf, 12); } - mov_text_cleanup(s); } + mov_text_cleanup(s); } -static void encode_hlit(MovTextContext *s, uint32_t tsmb_type) +static void encode_hlit(MovTextContext *s) { - uint32_t tsmb_size; if (s->box_flags & HLIT_BOX) { - tsmb_size = 12; - tsmb_size = AV_RB32(&tsmb_size); - av_bprint_append_any(&s->buffer, &tsmb_size, 4); - av_bprint_append_any(&s->buffer, &tsmb_type, 4); - av_bprint_append_any(&s->buffer, &s->hlit.start, 2); - av_bprint_append_any(&s->buffer, &s->hlit.end, 2); + uint8_t buf[12], *p = buf; + + bytestream_put_be32(&p, 12); + bytestream_put_be32(&p, MKBETAG('h','l','i','t')); + bytestream_put_be16(&p, s->hlit.start); + bytestream_put_be16(&p, s->hlit.end); + + av_bprint_append_any(&s->buffer, buf, 12); } } -static void encode_hclr(MovTextContext *s, uint32_t tsmb_type) +static void encode_hclr(MovTextContext *s) { - uint32_t tsmb_size; if (s->box_flags & HCLR_BOX) { - tsmb_size = 12; - tsmb_size = AV_RB32(&tsmb_size); - av_bprint_append_any(&s->buffer, &tsmb_size, 4); - av_bprint_append_any(&s->buffer, &tsmb_type, 4); - av_bprint_append_any(&s->buffer, &s->hclr.color, 4); + uint8_t buf[12], *p = buf; + + bytestream_put_be32(&p, 12); + bytestream_put_be32(&p, MKBETAG('h','c','l','r')); + bytestream_put_be32(&p, s->hclr.color); + + av_bprint_append_any(&s->buffer, buf, 12); } } static const Box box_types[] = { - { MKTAG('s','t','y','l'), encode_styl }, - { MKTAG('h','l','i','t'), encode_hlit }, - { MKTAG('h','c','l','r'), encode_hclr }, + { encode_styl }, + { encode_hlit }, + { encode_hclr }, }; const static size_t box_count = FF_ARRAY_ELEMS(box_types); -static av_cold int mov_text_encode_init(AVCodecContext *avctx) +static int mov_text_encode_close(AVCodecContext *avctx) { - /* - * For now, we'll use a fixed default style. When we add styling - * support, this will be generated from the ASS style. - */ - static const uint8_t text_sample_entry[] = { - 0x00, 0x00, 0x00, 0x00, // uint32_t displayFlags - 0x01, // int8_t horizontal-justification - 0xFF, // int8_t vertical-justification - 0x00, 0x00, 0x00, 0x00, // uint8_t background-color-rgba[4] - // BoxRecord { - 0x00, 0x00, // int16_t top - 0x00, 0x00, // int16_t left - 0x00, 0x00, // int16_t bottom - 0x00, 0x00, // int16_t right - // }; - // StyleRecord { - 0x00, 0x00, // uint16_t startChar - 0x00, 0x00, // uint16_t endChar - 0x00, 0x01, // uint16_t font-ID - 0x00, // uint8_t face-style-flags - 0x12, // uint8_t font-size - 0xFF, 0xFF, 0xFF, 0xFF, // uint8_t text-color-rgba[4] - // }; - // FontTableBox { - 0x00, 0x00, 0x00, 0x12, // uint32_t size - 'f', 't', 'a', 'b', // uint8_t name[4] - 0x00, 0x01, // uint16_t entry-count - // FontRecord { - 0x00, 0x01, // uint16_t font-ID - 0x05, // uint8_t font-name-length - 'S', 'e', 'r', 'i', 'f',// uint8_t font[font-name-length] - // }; - // }; - }; + MovTextContext *s = avctx->priv_data; + ff_ass_split_free(s->ass_ctx); + av_freep(&s->style_attributes); + av_freep(&s->fonts); + av_bprint_finalize(&s->buffer, NULL); + return 0; +} + +static int encode_sample_description(AVCodecContext *avctx) +{ + ASS *ass; + ASSStyle *style; + int i, j; + uint32_t back_color = 0; + int font_names_total_len = 0; MovTextContext *s = avctx->priv_data; - s->avctx = avctx; + uint8_t buf[30], *p = buf; + + // 0x00, 0x00, 0x00, 0x00, // uint32_t displayFlags + // 0x01, // int8_t horizontal-justification + // 0xFF, // int8_t vertical-justification + // 0x00, 0x00, 0x00, 0x00, // uint8_t background-color-rgba[4] + // BoxRecord { + // 0x00, 0x00, // int16_t top + // 0x00, 0x00, // int16_t left + // 0x00, 0x00, // int16_t bottom + // 0x00, 0x00, // int16_t right + // }; + // StyleRecord { + // 0x00, 0x00, // uint16_t startChar + // 0x00, 0x00, // uint16_t endChar + // 0x00, 0x01, // uint16_t font-ID + // 0x00, // uint8_t face-style-flags + // 0x12, // uint8_t font-size + // 0xFF, 0xFF, 0xFF, 0xFF, // uint8_t text-color-rgba[4] + // }; + // FontTableBox { + // 0x00, 0x00, 0x00, 0x12, // uint32_t size + // 'f', 't', 'a', 'b', // uint8_t name[4] + // 0x00, 0x01, // uint16_t entry-count + // FontRecord { + // 0x00, 0x01, // uint16_t font-ID + // 0x05, // uint8_t font-name-length + // 'S', 'e', 'r', 'i', 'f',// uint8_t font[font-name-length] + // }; + // }; + + // Populate sample description from ASS header + ass = (ASS*)s->ass_ctx; + // Compute font scaling factor based on (optionally) provided + // output video height and ASS script play_res_y + if (s->frame_height && ass->script_info.play_res_y) + s->font_scale_factor = (double)s->frame_height / ass->script_info.play_res_y; + else + s->font_scale_factor = 1; + + style = ff_ass_style_get(s->ass_ctx, "Default"); + if (!style && ass->styles_count) { + style = &ass->styles[0]; + } + s->d.style_fontID = DEFAULT_STYLE_FONT_ID; + s->d.style_fontsize = DEFAULT_STYLE_FONTSIZE; + s->d.style_color = DEFAULT_STYLE_COLOR; + s->d.style_flag = DEFAULT_STYLE_FLAG; + if (style) { + s->d.style_fontsize = FONTSIZE_SCALE(s, style->font_size); + s->d.style_color = BGR_TO_RGB(style->primary_color & 0xffffff) << 8 | + 255 - ((uint32_t)style->primary_color >> 24); + s->d.style_flag = (!!style->bold * STYLE_FLAG_BOLD) | + (!!style->italic * STYLE_FLAG_ITALIC) | + (!!style->underline * STYLE_FLAG_UNDERLINE); + back_color = (BGR_TO_RGB(style->back_color & 0xffffff) << 8) | + (255 - ((uint32_t)style->back_color >> 24)); + } + + bytestream_put_be32(&p, 0); // displayFlags + bytestream_put_be16(&p, 0x01FF); // horizontal/vertical justification (2x int8_t) + bytestream_put_be32(&p, back_color); + bytestream_put_be64(&p, 0); // BoxRecord - 4xint16_t: top, left, bottom, right + // StyleRecord { + bytestream_put_be16(&p, s->d.style_start); + bytestream_put_be16(&p, s->d.style_end); + bytestream_put_be16(&p, s->d.style_fontID); + bytestream_put_byte(&p, s->d.style_flag); + bytestream_put_byte(&p, s->d.style_fontsize); + bytestream_put_be32(&p, s->d.style_color); + // }; + av_bprint_append_any(&s->buffer, buf, 30); + + // Build font table + // We can't build a complete font table since that would require + // scanning all dialogs first. But we can at least fill in what + // is avaiable in the ASS header + if (style && ass->styles_count) { + // Find unique font names + if (style->font_name) { + av_dynarray_add(&s->fonts, &s->font_count, style->font_name); + font_names_total_len += strlen(style->font_name); + } + for (i = 0; i < ass->styles_count; i++) { + int found = 0; + if (!ass->styles[i].font_name) + continue; + for (j = 0; j < s->font_count; j++) { + if (!strcmp(s->fonts[j], ass->styles[i].font_name)) { + found = 1; + break; + } + } + if (!found) { + av_dynarray_add(&s->fonts, &s->font_count, + ass->styles[i].font_name); + font_names_total_len += strlen(ass->styles[i].font_name); + } + } + } else + av_dynarray_add(&s->fonts, &s->font_count, (char*)"Serif"); + + // FontTableBox { + p = buf; + bytestream_put_be32(&p, SIZE_ADD + 3 * s->font_count + font_names_total_len); // Size + bytestream_put_be32(&p, MKBETAG('f','t','a','b')); + bytestream_put_be16(&p, s->font_count); + + av_bprint_append_any(&s->buffer, buf, 10); + // FontRecord { + for (i = 0; i < s->font_count; i++) { + size_t len = strlen(s->fonts[i]); + + p = buf; + bytestream_put_be16(&p, i + 1); //fontID + bytestream_put_byte(&p, len); + + av_bprint_append_any(&s->buffer, buf, 3); + av_bprint_append_any(&s->buffer, s->fonts[i], len); + } + // }; + // }; + + if (!av_bprint_is_complete(&s->buffer)) { + return AVERROR(ENOMEM); + } - avctx->extradata_size = sizeof text_sample_entry; + avctx->extradata_size = s->buffer.len; avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!avctx->extradata) + if (!avctx->extradata) { return AVERROR(ENOMEM); + } - av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED); + memcpy(avctx->extradata, s->buffer.str, avctx->extradata_size); + av_bprint_clear(&s->buffer); + + return 0; +} + +static av_cold int mov_text_encode_init(AVCodecContext *avctx) +{ + int ret; + MovTextContext *s = avctx->priv_data; + s->avctx = avctx; - memcpy(avctx->extradata, text_sample_entry, avctx->extradata_size); + av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED); s->ass_ctx = ff_ass_split(avctx->subtitle_header); - return s->ass_ctx ? 0 : AVERROR_INVALIDDATA; + if (!s->ass_ctx) + return AVERROR_INVALIDDATA; + ret = encode_sample_description(avctx); + if (ret < 0) + return ret; + + return 0; } -static void mov_text_style_cb(void *priv, const char style, int close) +// Start a new style box if needed +static int mov_text_style_start(MovTextContext *s) { - MovTextContext *s = priv; - if (!close) { - if (!(s->box_flags & STYL_BOX)) { //first style entry + // there's an existing style entry + if (s->style_attributes_temp.style_start == s->text_pos) + // Still at same text pos, use same entry + return 1; + if (s->style_attributes_temp.style_flag != s->d.style_flag || + s->style_attributes_temp.style_color != s->d.style_color || + s->style_attributes_temp.style_fontID != s->d.style_fontID || + s->style_attributes_temp.style_fontsize != s->d.style_fontsize) { + StyleBox *tmp; + + // last style != defaults, end the style entry and start a new one + if (s->count + 1 > FFMIN(SIZE_MAX / sizeof(*s->style_attributes), UINT16_MAX) || + !(tmp = av_fast_realloc(s->style_attributes, + &s->style_attributes_bytes_allocated, + (s->count + 1) * sizeof(*s->style_attributes)))) { + mov_text_cleanup(s); + av_bprint_clear(&s->buffer); + s->box_flags &= ~STYL_BOX; + return 0; + } + s->style_attributes = tmp; + s->style_attributes_temp.style_end = s->text_pos; + s->style_attributes[s->count++] = s->style_attributes_temp; + s->box_flags |= STYL_BOX; + s->style_attributes_temp = s->d; + s->style_attributes_temp.style_start = s->text_pos; + } else { // style entry matches defaults, drop entry + s->style_attributes_temp = s->d; + s->style_attributes_temp.style_start = s->text_pos; + } + return 1; +} - s->style_attributes_temp = av_malloc(sizeof(*s->style_attributes_temp)); +static uint8_t mov_text_style_to_flag(const char style) +{ + uint8_t style_flag = 0; - if (!s->style_attributes_temp) { - av_bprint_clear(&s->buffer); - s->box_flags &= ~STYL_BOX; - return; - } + switch (style){ + case 'b': + style_flag = STYLE_FLAG_BOLD; + break; + case 'i': + style_flag = STYLE_FLAG_ITALIC; + break; + case 'u': + style_flag = STYLE_FLAG_UNDERLINE; + break; + } + return style_flag; +} - s->style_attributes_temp->style_flag = 0; - s->style_attributes_temp->style_start = AV_RB16(&s->text_pos); - } else { - if (s->style_attributes_temp->style_flag) { //break the style record here and start a new one - s->style_attributes_temp->style_end = AV_RB16(&s->text_pos); - av_dynarray_add(&s->style_attributes, &s->count, s->style_attributes_temp); - s->style_attributes_temp = av_malloc(sizeof(*s->style_attributes_temp)); - if (!s->style_attributes_temp) { - mov_text_cleanup(s); - av_bprint_clear(&s->buffer); - s->box_flags &= ~STYL_BOX; - return; - } +static void mov_text_style_set(MovTextContext *s, uint8_t style_flags) +{ + if (!((s->style_attributes_temp.style_flag & style_flags) ^ style_flags)) { + // setting flags that that are already set + return; + } + if (mov_text_style_start(s)) + s->style_attributes_temp.style_flag |= style_flags; +} - s->style_attributes_temp->style_flag = s->style_attributes[s->count - 1]->style_flag; - s->style_attributes_temp->style_start = AV_RB16(&s->text_pos); - } else { - s->style_attributes_temp->style_flag = 0; - s->style_attributes_temp->style_start = AV_RB16(&s->text_pos); - } - } - switch (style){ - case 'b': - s->style_attributes_temp->style_flag |= STYLE_FLAG_BOLD; - break; - case 'i': - s->style_attributes_temp->style_flag |= STYLE_FLAG_ITALIC; - break; - case 'u': - s->style_attributes_temp->style_flag |= STYLE_FLAG_UNDERLINE; - break; - } - } else if (!s->style_attributes_temp) { - av_log(s->avctx, AV_LOG_WARNING, "Ignoring unmatched close tag\n"); +static void mov_text_style_cb(void *priv, const char style, int close) +{ + MovTextContext *s = priv; + uint8_t style_flag = mov_text_style_to_flag(style); + + if (!!(s->style_attributes_temp.style_flag & style_flag) != close) { + // setting flag that is already set return; - } else { - s->style_attributes_temp->style_end = AV_RB16(&s->text_pos); - av_dynarray_add(&s->style_attributes, &s->count, s->style_attributes_temp); + } + if (mov_text_style_start(s)) { + if (!close) + s->style_attributes_temp.style_flag |= style_flag; + else + s->style_attributes_temp.style_flag &= ~style_flag; + } +} - s->style_attributes_temp = av_malloc(sizeof(*s->style_attributes_temp)); +static void mov_text_color_set(MovTextContext *s, uint32_t color) +{ + if ((s->style_attributes_temp.style_color & 0xffffff00) == color) { + // color hasn't changed + return; + } + if (mov_text_style_start(s)) + s->style_attributes_temp.style_color = (color & 0xffffff00) | + (s->style_attributes_temp.style_color & 0xff); +} - if (!s->style_attributes_temp) { - mov_text_cleanup(s); - av_bprint_clear(&s->buffer); - s->box_flags &= ~STYL_BOX; - return; - } +static void mov_text_color_cb(void *priv, unsigned int color, unsigned int color_id) +{ + MovTextContext *s = priv; - s->style_attributes_temp->style_flag = s->style_attributes[s->count - 1]->style_flag; - switch (style){ - case 'b': - s->style_attributes_temp->style_flag &= ~STYLE_FLAG_BOLD; - break; - case 'i': - s->style_attributes_temp->style_flag &= ~STYLE_FLAG_ITALIC; - break; - case 'u': - s->style_attributes_temp->style_flag &= ~STYLE_FLAG_UNDERLINE; - break; - } - if (s->style_attributes_temp->style_flag) { //start of new style record - s->style_attributes_temp->style_start = AV_RB16(&s->text_pos); + color = BGR_TO_RGB(color) << 8; + if (color_id == 1) { //primary color changes + mov_text_color_set(s, color); + } else if (color_id == 2) { //secondary color changes + if (!(s->box_flags & HCLR_BOX)) + // Highlight alpha not set yet, use current primary alpha + s->hclr.color = s->style_attributes_temp.style_color; + if (!(s->box_flags & HLIT_BOX) || s->hlit.start == s->text_pos) { + s->box_flags |= HCLR_BOX; + s->box_flags |= HLIT_BOX; + s->hlit.start = s->text_pos; + s->hclr.color = color | (s->hclr.color & 0xFF); } + else //close tag + s->hlit.end = s->text_pos; + /* If there are more than one secondary color changes in ASS, + take start of first section and end of last section. Movtext + allows only one highlight box per sample. + */ } - s->box_flags |= STYL_BOX; + // Movtext does not support changes to other color_id (outline, background) } -static void mov_text_color_cb(void *priv, unsigned int color, unsigned int color_id) +static void mov_text_alpha_set(MovTextContext *s, uint8_t alpha) +{ + if ((s->style_attributes_temp.style_color & 0xff) == alpha) { + // color hasn't changed + return; + } + if (mov_text_style_start(s)) + s->style_attributes_temp.style_color = + (s->style_attributes_temp.style_color & 0xffffff00) | alpha; +} + +static void mov_text_alpha_cb(void *priv, int alpha, int alpha_id) { MovTextContext *s = priv; - if (color_id == 2) { //secondary color changes - if (s->box_flags & HLIT_BOX) { //close tag - s->hlit.end = AV_RB16(&s->text_pos); - } else { + + alpha = 255 - alpha; + if (alpha_id == 1) // primary alpha changes + mov_text_alpha_set(s, alpha); + else if (alpha_id == 2) { //secondary alpha changes + if (!(s->box_flags & HCLR_BOX)) + // Highlight color not set yet, use current primary color + s->hclr.color = s->style_attributes_temp.style_color; + if (!(s->box_flags & HLIT_BOX) || s->hlit.start == s->text_pos) { s->box_flags |= HCLR_BOX; s->box_flags |= HLIT_BOX; - s->hlit.start = AV_RB16(&s->text_pos); - s->hclr.color = color | (0xFF << 24); //set alpha value to FF + s->hlit.start = s->text_pos; + s->hclr.color = (s->hclr.color & 0xffffff00) | alpha; } + else //close tag + s->hlit.end = s->text_pos; } - /* If there are more than one secondary color changes in ASS, take start of - first section and end of last section. Movtext allows only one - highlight box per sample. - */ + // Movtext does not support changes to other alpha_id (outline, background) +} + +static uint16_t find_font_id(MovTextContext *s, const char *name) +{ + int i; + for (i = 0; i < s->font_count; i++) { + if (!strcmp(name, s->fonts[i])) + return i + 1; + } + return 1; +} + +static void mov_text_font_name_set(MovTextContext *s, const char *name) +{ + int fontID = find_font_id(s, name); + if (s->style_attributes_temp.style_fontID == fontID) { + // color hasn't changed + return; + } + if (mov_text_style_start(s)) + s->style_attributes_temp.style_fontID = fontID; +} + +static void mov_text_font_name_cb(void *priv, const char *name) +{ + mov_text_font_name_set((MovTextContext*)priv, name); +} + +static void mov_text_font_size_set(MovTextContext *s, int size) +{ + size = FONTSIZE_SCALE(s, size); + if (s->style_attributes_temp.style_fontsize == size) { + // color hasn't changed + return; + } + if (mov_text_style_start(s)) + s->style_attributes_temp.style_fontsize = size; +} + +static void mov_text_font_size_cb(void *priv, int size) +{ + mov_text_font_size_set((MovTextContext*)priv, size); +} + +static void mov_text_end_cb(void *priv) +{ + // End of text, close any open style record + mov_text_style_start((MovTextContext*)priv); +} + +static void mov_text_ass_style_set(MovTextContext *s, ASSStyle *style) +{ + uint8_t style_flags, alpha; + uint32_t color; + + if (style) { + style_flags = (!!style->bold * STYLE_FLAG_BOLD) | + (!!style->italic * STYLE_FLAG_ITALIC) | + (!!style->underline * STYLE_FLAG_UNDERLINE); + mov_text_style_set(s, style_flags); + color = BGR_TO_RGB(style->primary_color & 0xffffff) << 8; + mov_text_color_set(s, color); + alpha = 255 - ((uint32_t)style->primary_color >> 24); + mov_text_alpha_set(s, alpha); + mov_text_font_size_set(s, style->font_size); + mov_text_font_name_set(s, style->font_name); + } else { + // End current style record, go back to defaults + mov_text_style_start(s); + } +} + +static void mov_text_dialog(MovTextContext *s, ASSDialog *dialog) +{ + ASSStyle *style = ff_ass_style_get(s->ass_ctx, dialog->style); + + s->ass_dialog_style = style; + mov_text_ass_style_set(s, style); +} + +static void mov_text_cancel_overrides_cb(void *priv, const char *style_name) +{ + MovTextContext *s = priv; + ASSStyle *style; + + if (!style_name || !*style_name) + style = s->ass_dialog_style; + else + style= ff_ass_style_get(s->ass_ctx, style_name); + + mov_text_ass_style_set(s, style); } static uint16_t utf8_strlen(const char *text, int len) @@ -344,10 +624,15 @@ } static const ASSCodesCallbacks mov_text_callbacks = { - .text = mov_text_text_cb, - .new_line = mov_text_new_line_cb, - .style = mov_text_style_cb, - .color = mov_text_color_cb, + .text = mov_text_text_cb, + .new_line = mov_text_new_line_cb, + .style = mov_text_style_cb, + .color = mov_text_color_cb, + .alpha = mov_text_alpha_cb, + .font_name = mov_text_font_name_cb, + .font_size = mov_text_font_size_cb, + .cancel_overrides = mov_text_cancel_overrides_cb, + .end = mov_text_end_cb, }; static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, @@ -362,13 +647,12 @@ s->text_pos = 0; s->count = 0; s->box_flags = 0; - s->style_entries = 0; for (i = 0; i < sub->num_rects; i++) { const char *ass = sub->rects[i]->ass; if (sub->rects[i]->type != SUBTITLE_ASS) { av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n"); - return AVERROR(ENOSYS); + return AVERROR(EINVAL); } #if FF_API_ASS_TIMING @@ -376,6 +660,7 @@ int num; dialog = ff_ass_split_dialog(s->ass_ctx, ass, 0, &num); for (; dialog && num--; dialog++) { + mov_text_dialog(s, dialog); ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text); } } else { @@ -383,6 +668,7 @@ dialog = ff_ass_split_dialog2(s->ass_ctx, ass); if (!dialog) return AVERROR(ENOMEM); + mov_text_dialog(s, dialog); ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text); ff_ass_free_dialog(&dialog); #if FF_API_ASS_TIMING @@ -390,7 +676,7 @@ #endif for (j = 0; j < box_count; j++) { - box_types[j].encode(s, box_types[j].type); + box_types[j].encode(s); } } @@ -409,7 +695,7 @@ if (s->buffer.len > bufsize - 3) { av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); - length = AVERROR(EINVAL); + length = AVERROR_BUFFER_TOO_SMALL; goto exit; } @@ -421,13 +707,19 @@ return length; } -static int mov_text_encode_close(AVCodecContext *avctx) -{ - MovTextContext *s = avctx->priv_data; - ff_ass_split_free(s->ass_ctx); - av_bprint_finalize(&s->buffer, NULL); - return 0; -} +#define OFFSET(x) offsetof(MovTextContext, x) +#define FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_SUBTITLE_PARAM +static const AVOption options[] = { + { "height", "Frame height, usually video height", OFFSET(frame_height), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, + { NULL }, +}; + +static const AVClass mov_text_encoder_class = { + .class_name = "MOV text enoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; AVCodec ff_movtext_encoder = { .name = "mov_text", @@ -435,7 +727,9 @@ .type = AVMEDIA_TYPE_SUBTITLE, .id = AV_CODEC_ID_MOV_TEXT, .priv_data_size = sizeof(MovTextContext), + .priv_class = &mov_text_encoder_class, .init = mov_text_encode_init, .encode_sub = mov_text_encode_frame, .close = mov_text_encode_close, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/mp3_header_decompress_bsf.c ffmpeg-4.4/libavcodec/mp3_header_decompress_bsf.c --- ffmpeg-4.2.2/libavcodec/mp3_header_decompress_bsf.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mp3_header_decompress_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -20,8 +20,8 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "mpegaudiodecheader.h" #include "mpegaudiodata.h" diff -Nru ffmpeg-4.2.2/libavcodec/mpc7.c ffmpeg-4.4/libavcodec/mpc7.c --- ffmpeg-4.2.2/libavcodec/mpc7.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpc7.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,6 +28,9 @@ #include "libavutil/channel_layout.h" #include "libavutil/internal.h" #include "libavutil/lfg.h" +#include "libavutil/mem_internal.h" +#include "libavutil/thread.h" + #include "avcodec.h" #include "get_bits.h" #include "internal.h" @@ -38,25 +41,42 @@ static VLC scfi_vlc, dscf_vlc, hdr_vlc, quant_vlc[MPC7_QUANT_VLC_TABLES][2]; -static const uint16_t quant_offsets[MPC7_QUANT_VLC_TABLES*2 + 1] = +static av_cold void mpc7_init_static(void) { - 0, 512, 1024, 1536, 2052, 2564, 3076, 3588, 4100, 4612, 5124, - 5636, 6164, 6676, 7224 -}; + static VLC_TYPE quant_tables[7224][2]; + const uint8_t *raw_quant_table = mpc7_quant_vlcs; + INIT_VLC_STATIC_FROM_LENGTHS(&scfi_vlc, MPC7_SCFI_BITS, MPC7_SCFI_SIZE, + &mpc7_scfi[1], 2, + &mpc7_scfi[0], 2, 1, 0, 0, 1 << MPC7_SCFI_BITS); + INIT_VLC_STATIC_FROM_LENGTHS(&dscf_vlc, MPC7_DSCF_BITS, MPC7_DSCF_SIZE, + &mpc7_dscf[1], 2, + &mpc7_dscf[0], 2, 1, -7, 0, 1 << MPC7_DSCF_BITS); + INIT_VLC_STATIC_FROM_LENGTHS(&hdr_vlc, MPC7_HDR_BITS, MPC7_HDR_SIZE, + &mpc7_hdr[1], 2, + &mpc7_hdr[0], 2, 1, -5, 0, 1 << MPC7_HDR_BITS); + for (unsigned i = 0, offset = 0; i < MPC7_QUANT_VLC_TABLES; i++){ + for (int j = 0; j < 2; j++) { + quant_vlc[i][j].table = &quant_tables[offset]; + quant_vlc[i][j].table_allocated = FF_ARRAY_ELEMS(quant_tables) - offset; + ff_init_vlc_from_lengths(&quant_vlc[i][j], 9, mpc7_quant_vlc_sizes[i], + &raw_quant_table[1], 2, + &raw_quant_table[0], 2, 1, + mpc7_quant_vlc_off[i], + INIT_VLC_STATIC_OVERLONG, NULL); + raw_quant_table += 2 * mpc7_quant_vlc_sizes[i]; + offset += quant_vlc[i][j].table_size; + } + } + ff_mpa_synth_init_fixed(); +} static av_cold int mpc7_decode_init(AVCodecContext * avctx) { - int i, j, ret; + static AVOnce init_static_once = AV_ONCE_INIT; MPCContext *c = avctx->priv_data; GetBitContext gb; LOCAL_ALIGNED_16(uint8_t, buf, [16]); - static int vlc_initialized = 0; - - static VLC_TYPE scfi_table[1 << MPC7_SCFI_BITS][2]; - static VLC_TYPE dscf_table[1 << MPC7_DSCF_BITS][2]; - static VLC_TYPE hdr_table[1 << MPC7_HDR_BITS][2]; - static VLC_TYPE quant_tables[7224][2]; /* Musepack SV7 is always stereo */ if (avctx->channels != 2) { @@ -73,7 +93,6 @@ ff_bswapdsp_init(&c->bdsp); ff_mpadsp_init(&c->mpadsp); c->bdsp.bswap_buf((uint32_t *) buf, (const uint32_t *) avctx->extradata, 4); - ff_mpc_init(); init_get_bits(&gb, buf, 128); c->IS = get_bits1(&gb); @@ -93,45 +112,7 @@ avctx->sample_fmt = AV_SAMPLE_FMT_S16P; avctx->channel_layout = AV_CH_LAYOUT_STEREO; - if(vlc_initialized) return 0; - av_log(avctx, AV_LOG_DEBUG, "Initing VLC\n"); - scfi_vlc.table = scfi_table; - scfi_vlc.table_allocated = 1 << MPC7_SCFI_BITS; - if ((ret = init_vlc(&scfi_vlc, MPC7_SCFI_BITS, MPC7_SCFI_SIZE, - &mpc7_scfi[1], 2, 1, - &mpc7_scfi[0], 2, 1, INIT_VLC_USE_NEW_STATIC))) { - av_log(avctx, AV_LOG_ERROR, "Cannot init SCFI VLC\n"); - return ret; - } - dscf_vlc.table = dscf_table; - dscf_vlc.table_allocated = 1 << MPC7_DSCF_BITS; - if ((ret = init_vlc(&dscf_vlc, MPC7_DSCF_BITS, MPC7_DSCF_SIZE, - &mpc7_dscf[1], 2, 1, - &mpc7_dscf[0], 2, 1, INIT_VLC_USE_NEW_STATIC))) { - av_log(avctx, AV_LOG_ERROR, "Cannot init DSCF VLC\n"); - return ret; - } - hdr_vlc.table = hdr_table; - hdr_vlc.table_allocated = 1 << MPC7_HDR_BITS; - if ((ret = init_vlc(&hdr_vlc, MPC7_HDR_BITS, MPC7_HDR_SIZE, - &mpc7_hdr[1], 2, 1, - &mpc7_hdr[0], 2, 1, INIT_VLC_USE_NEW_STATIC))) { - av_log(avctx, AV_LOG_ERROR, "Cannot init HDR VLC\n"); - return ret; - } - for(i = 0; i < MPC7_QUANT_VLC_TABLES; i++){ - for(j = 0; j < 2; j++){ - quant_vlc[i][j].table = &quant_tables[quant_offsets[i*2 + j]]; - quant_vlc[i][j].table_allocated = quant_offsets[i*2 + j + 1] - quant_offsets[i*2 + j]; - if ((ret = init_vlc(&quant_vlc[i][j], 9, mpc7_quant_vlc_sizes[i], - &mpc7_quant_vlc[i][j][1], 4, 2, - &mpc7_quant_vlc[i][j][0], 4, 2, INIT_VLC_USE_NEW_STATIC))) { - av_log(avctx, AV_LOG_ERROR, "Cannot init QUANT VLC %i,%i\n",i,j); - return ret; - } - } - } - vlc_initialized = 1; + ff_thread_once(&init_static_once, mpc7_init_static); return 0; } @@ -168,7 +149,7 @@ case 3: case 4: case 5: case 6: case 7: i1 = get_bits1(gb); for(i = 0; i < SAMPLES_PER_BAND; i++) - *dst++ = get_vlc2(gb, quant_vlc[idx-1][i1].table, 9, 2) - mpc7_quant_vlc_off[idx-1]; + *dst++ = get_vlc2(gb, quant_vlc[idx-1][i1].table, 9, 2); break; case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: @@ -183,7 +164,7 @@ static int get_scale_idx(GetBitContext *gb, int ref) { - int t = get_vlc2(gb, dscf_vlc.table, MPC7_DSCF_BITS, 1) - 7; + int t = get_vlc2(gb, dscf_vlc.table, MPC7_DSCF_BITS, 1); if (t == 8) return get_bits(gb, 6); return ref + t; @@ -238,8 +219,7 @@ /* read subband indexes */ for(i = 0; i <= c->maxbands; i++){ for(ch = 0; ch < 2; ch++){ - int t = 4; - if(i) t = get_vlc2(&gb, hdr_vlc.table, MPC7_HDR_BITS, 1) - 5; + int t = i ? get_vlc2(&gb, hdr_vlc.table, MPC7_HDR_BITS, 1) : 4; if(t == 4) bands[i].res[ch] = get_bits(&gb, 4); else bands[i].res[ch] = bands[i-1].res[ch] + t; if (bands[i].res[ch] < -1 || bands[i].res[ch] > 17) { @@ -341,4 +321,5 @@ .capabilities = AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/mpc7data.h ffmpeg-4.4/libavcodec/mpc7data.h --- ffmpeg-4.2.2/libavcodec/mpc7data.h 2016-03-29 02:25:18.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpc7data.h 2021-04-08 21:28:39.000000000 +0000 @@ -33,139 +33,103 @@ #define MPC7_SCFI_SIZE 4 #define MPC7_SCFI_BITS 3 static const uint8_t mpc7_scfi[MPC7_SCFI_SIZE * 2] = { - 0x2, 3, 0x1, 1, 0x3, 3, 0x0, 2 + 0x03, 2, 0x00, 3, 0x02, 3, 0x01, 1, }; #define MPC7_DSCF_SIZE 16 #define MPC7_DSCF_BITS 6 static const uint8_t mpc7_dscf[MPC7_DSCF_SIZE * 2] = { - 0x20, 6, 0x04, 5, 0x11, 5, 0x1E, 5, 0x0D, 4, 0x00, 3, 0x03, 3, 0x09, 4, - 0x05, 3, 0x02, 3, 0x0E, 4, 0x03, 4, 0x1F, 5, 0x05, 5, 0x21, 6, 0x0C, 4 + 0x05, 3, 0x01, 5, 0x0D, 5, 0x0B, 4, 0x09, 3, 0x06, 3, 0x00, 6, 0x0E, 6, + 0x02, 5, 0x07, 4, 0x08, 3, 0x0F, 4, 0x04, 4, 0x0A, 4, 0x03, 5, 0x0C, 5, }; #define MPC7_HDR_SIZE 10 #define MPC7_HDR_BITS 9 static const uint8_t mpc7_hdr[MPC7_HDR_SIZE * 2] = { - 0x5C, 8, 0x2F, 7, 0x0A, 5, 0x04, 4, 0x00, 2, - 0x01, 1, 0x03, 3, 0x16, 6, 0xBB, 9, 0xBA, 9 + 0x04, 2, 0x03, 4, 0x02, 5, 0x07, 6, 0x00, 8, + 0x09, 9, 0x08, 9, 0x01, 7, 0x06, 3, 0x05, 1, }; #define MPC7_QUANT_VLC_TABLES 7 -static const uint8_t mpc7_quant_vlc_sizes[MPC7_QUANT_VLC_TABLES * 2] = { +static const uint8_t mpc7_quant_vlc_sizes[MPC7_QUANT_VLC_TABLES] = { 27, 25, 7, 9, 15, 31, 63 }; -static const uint8_t mpc7_quant_vlc_off[MPC7_QUANT_VLC_TABLES] = { - 0, 0, 3, 4, 7, 15, 31 +static const int8_t mpc7_quant_vlc_off[MPC7_QUANT_VLC_TABLES] = { + 0, 0, -3, -4, -7, -15, -31 }; -static const uint16_t mpc7_quant_vlc[MPC7_QUANT_VLC_TABLES][2][64 * 2] = { -{ - { - 0x0036, 6, 0x0009, 5, 0x0020, 6, 0x0005, 5, 0x000A, 4, 0x0007, 5, - 0x0034, 6, 0x0000, 5, 0x0023, 6, 0x000A, 5, 0x0006, 4, 0x0004, 5, - 0x000B, 4, 0x0007, 3, 0x000C, 4, 0x0003, 5, 0x0007, 4, 0x000B, 5, - 0x0022, 6, 0x0001, 5, 0x0035, 6, 0x0006, 5, 0x0009, 4, 0x0002, 5, - 0x0021, 6, 0x0008, 5, 0x0037, 6 - }, - { - 0x0067, 8, 0x003E, 7, 0x00E1, 9, 0x0037, 7, 0x0003, 4, 0x0034, 7, - 0x0065, 8, 0x003C, 7, 0x00E3, 9, 0x0018, 6, 0x0000, 4, 0x003D, 7, - 0x0004, 4, 0x0001, 1, 0x0005, 4, 0x003F, 7, 0x0001, 4, 0x003B, 7, - 0x00E2, 9, 0x0039, 7, 0x0064, 8, 0x0035, 7, 0x0002, 4, 0x0036, 7, - 0x00E0, 9, 0x003A, 7, 0x0066, 8 - } -}, -{ - { - 0x0059, 7, 0x002F, 6, 0x000F, 5, 0x0000, 5, 0x005B, 7, 0x0004, 5, - 0x0006, 4, 0x000D, 4, 0x0004, 4, 0x0005, 5, 0x0014, 5, 0x000C, 4, - 0x0004, 3, 0x000F, 4, 0x000E, 5, 0x0003, 5, 0x0003, 4, 0x000E, 4, - 0x0005, 4, 0x0001, 5, 0x005A, 7, 0x0002, 5, 0x0015, 5, 0x002E, 6, - 0x0058, 7 - }, - { - 0x0399, 10, 0x0071, 7, 0x0033, 6, 0x00E7, 8, 0x039A, 10, 0x0068, 7, - 0x001E, 5, 0x0000, 3, 0x001D, 5, 0x0069, 7, 0x0032, 6, 0x0001, 3, - 0x0002, 2, 0x0003, 3, 0x0031, 6, 0x006B, 7, 0x001B, 5, 0x0002, 3, - 0x001F, 5, 0x0070, 7, 0x0398, 10, 0x006A, 7, 0x0030, 6, 0x0072, 7, - 0x039B, 10 - } -}, -{ - { - 0x000C, 4, 0x0004, 3, 0x0000, 2, 0x0001, 2, 0x0007, 3, 0x0005, 3, 0x000D, 4 - }, - { - 0x0004, 5, 0x0003, 4, 0x0002, 2, 0x0003, 2, 0x0001, 2, 0x0000, 3, 0x0005, 5 - } -}, -{ - { - 0x0005, 4, 0x0000, 3, 0x0004, 3, 0x0006, 3, 0x0007, 3, 0x0005, 3, 0x0003, 3, 0x0001, 3, 0x0004, 4 - }, - { - 0x0009, 5, 0x000C, 4, 0x0003, 3, 0x0000, 2, 0x0002, 2, 0x0007, 3, 0x000D, 4, 0x0005, 4, 0x0008, 5 - } -}, -{ - { - 0x0039, 6, 0x0017, 5, 0x0008, 4, 0x000A, 4, 0x000D, 4, 0x0000, 3, - 0x0002, 3, 0x0003, 3, 0x0001, 3, 0x000F, 4, 0x000C, 4, 0x0009, 4, - 0x001D, 5, 0x0016, 5, 0x0038, 6, - }, - { - 0x00E5, 8, 0x0038, 6, 0x0007, 5, 0x0002, 4, 0x0000, 3, 0x0003, 3, - 0x0005, 3, 0x0006, 3, 0x0004, 3, 0x0002, 3, 0x000F, 4, 0x001D, 5, - 0x0006, 5, 0x0073, 7, 0x00E4, 8, - }, -}, -{ - { - 0x0041, 7, 0x0006, 6, 0x002C, 6, 0x002D, 6, 0x003B, 6, 0x000D, 5, - 0x0011, 5, 0x0013, 5, 0x0017, 5, 0x0015, 5, 0x001A, 5, 0x001E, 5, - 0x0000, 4, 0x0002, 4, 0x0005, 4, 0x0007, 4, 0x0003, 4, 0x0004, 4, - 0x001F, 5, 0x001C, 5, 0x0019, 5, 0x001B, 5, 0x0018, 5, 0x0014, 5, - 0x0012, 5, 0x000C, 5, 0x0002, 5, 0x003A, 6, 0x0021, 6, 0x0007, 6, - 0x0040, 7 - }, - { - 0x1948, 13, 0x194A, 13, 0x0328, 10, 0x0195, 9, 0x00CB, 8, 0x0066, 7, - 0x0031, 6, 0x0009, 5, 0x000F, 5, 0x001F, 5, 0x0002, 4, 0x0006, 4, - 0x0008, 4, 0x000B, 4, 0x000D, 4, 0x0000, 3, 0x000E, 4, 0x000A, 4, - 0x0009, 4, 0x0005, 4, 0x0003, 4, 0x001E, 5, 0x000E, 5, 0x0008, 5, - 0x0030, 6, 0x0067, 7, 0x00C9, 8, 0x00C8, 8, 0x0653, 11, 0x1949, 13, - 0x194B, 13 - } -}, -{ - { - 0x0067, 8, 0x0099, 8, 0x00B5, 8, 0x00E9, 8, 0x0040, 7, 0x0041, 7, - 0x004D, 7, 0x0051, 7, 0x005B, 7, 0x0071, 7, 0x0070, 7, 0x0018, 6, - 0x001D, 6, 0x0023, 6, 0x0025, 6, 0x0029, 6, 0x002C, 6, 0x002E, 6, - 0x0033, 6, 0x0031, 6, 0x0036, 6, 0x0037, 6, 0x0039, 6, 0x003C, 6, - 0x0000, 5, 0x0002, 5, 0x000A, 5, 0x0005, 5, 0x0009, 5, 0x0006, 5, - 0x000D, 5, 0x0007, 5, 0x000B, 5, 0x000F, 5, 0x0008, 5, 0x0004, 5, - 0x0003, 5, 0x0001, 5, 0x003F, 6, 0x003E, 6, 0x003D, 6, 0x0035, 6, - 0x003B, 6, 0x0034, 6, 0x0030, 6, 0x002F, 6, 0x002B, 6, 0x002A, 6, - 0x0027, 6, 0x0024, 6, 0x0021, 6, 0x001C, 6, 0x0075, 7, 0x0065, 7, - 0x0064, 7, 0x0050, 7, 0x0045, 7, 0x0044, 7, 0x0032, 7, 0x00E8, 8, - 0x00B4, 8, 0x0098, 8, 0x0066, 8 - }, - { - 0x37A4, 14, 0x37AD, 14, 0x37A6, 14, 0x37AE, 14, 0x0DEA, 12, 0x02F0, 10, - 0x02F1, 10, 0x00A0, 9, 0x00A2, 9, 0x01BC, 9, 0x007A, 8, 0x00DF, 8, - 0x003C, 7, 0x0049, 7, 0x006E, 7, 0x000E, 6, 0x0018, 6, 0x0019, 6, - 0x0022, 6, 0x0025, 6, 0x0036, 6, 0x0003, 5, 0x0009, 5, 0x000B, 5, - 0x0010, 5, 0x0013, 5, 0x0015, 5, 0x0018, 5, 0x001A, 5, 0x001D, 5, - 0x001F, 5, 0x0002, 4, 0x0000, 4, 0x001E, 5, 0x001C, 5, 0x0019, 5, - 0x0016, 5, 0x0014, 5, 0x000E, 5, 0x000D, 5, 0x0008, 5, 0x0006, 5, - 0x0002, 5, 0x002E, 6, 0x0023, 6, 0x001F, 6, 0x0015, 6, 0x000F, 6, - 0x005F, 7, 0x0048, 7, 0x0029, 7, 0x00BD, 8, 0x007B, 8, 0x0179, 9, - 0x00A1, 9, 0x037B, 10, 0x0147, 10, 0x0146, 10, 0x0DE8, 12, 0x37AF, 14, - 0x37A7, 14, 0x37AC, 14, 0x37A5, 14 - } -} +static const uint8_t mpc7_quant_vlcs[177 * 2 * 2] = { + /* quant_vlc[0][0] - 27 entries */ + 0x07, 5, 0x13, 5, 0x17, 5, 0x0F, 5, 0x0B, 5, 0x03, 5, 0x15, 5, + 0x05, 5, 0x19, 5, 0x01, 5, 0x09, 5, 0x11, 5, 0x0A, 4, 0x10, 4, + 0x02, 6, 0x18, 6, 0x12, 6, 0x08, 6, 0x16, 4, 0x04, 4, 0x0C, 4, + 0x0E, 4, 0x06, 6, 0x14, 6, 0x00, 6, 0x1A, 6, 0x0D, 3, + /* quant_vlc[0][1] - 27 entries */ + 0x0A, 4, 0x10, 4, 0x16, 4, 0x04, 4, 0x0C, 4, 0x0E, 4, 0x09, 6, + 0x14, 8, 0x06, 8, 0x1A, 8, 0x00, 8, 0x05, 7, 0x15, 7, 0x17, 7, + 0x03, 7, 0x18, 9, 0x02, 9, 0x12, 9, 0x08, 9, 0x13, 7, 0x19, 7, + 0x11, 7, 0x07, 7, 0x0B, 7, 0x01, 7, 0x0F, 7, 0x0D, 1, + /* quant_vlc[1][0] - 25 entries */ + 0x03, 5, 0x13, 5, 0x15, 5, 0x0F, 5, 0x05, 5, 0x09, 5, 0x10, 4, + 0x08, 4, 0x12, 4, 0x06, 4, 0x0E, 5, 0x02, 5, 0x0C, 3, 0x0A, 5, + 0x16, 5, 0x18, 7, 0x00, 7, 0x14, 7, 0x04, 7, 0x17, 6, 0x01, 6, + 0x0B, 4, 0x07, 4, 0x11, 4, 0x0D, 4, + /* quant_vlc[1][1] - 25 entries */ + 0x07, 3, 0x0B, 3, 0x11, 3, 0x0D, 3, 0x0C, 2, 0x16, 6, 0x0E, 6, + 0x0A, 6, 0x02, 6, 0x05, 7, 0x09, 7, 0x15, 7, 0x0F, 7, 0x10, 5, + 0x13, 7, 0x01, 7, 0x17, 7, 0x14, 10, 0x00, 10, 0x04, 10, 0x18, 10, + 0x03, 8, 0x08, 5, 0x06, 5, 0x12, 5, + /* quant_vlc[2][0] - 7 entries */ + 0x02, 2, 0x03, 2, 0x01, 3, 0x05, 3, 0x00, 4, 0x06, 4, 0x04, 3, + /* quant_vlc[2][1] - 7 entries */ + 0x05, 3, 0x00, 5, 0x06, 5, 0x01, 4, 0x04, 2, 0x02, 2, 0x03, 2, + /* quant_vlc[3][0] - 9 entries */ + 0x01, 3, 0x07, 3, 0x08, 4, 0x00, 4, 0x06, 3, 0x02, 3, 0x05, 3, + 0x03, 3, 0x04, 3, + /* quant_vlc[3][1] - 9 entries */ + 0x03, 2, 0x08, 5, 0x00, 5, 0x07, 4, 0x02, 3, 0x04, 2, 0x01, 4, + 0x06, 4, 0x05, 3, + /* quant_vlc[4][0] - 15 entries */ + 0x05, 3, 0x08, 3, 0x06, 3, 0x07, 3, 0x02, 4, 0x0B, 4, 0x03, 4, + 0x0D, 5, 0x01, 5, 0x0A, 4, 0x04, 4, 0x0E, 6, 0x00, 6, 0x0C, 5, + 0x09, 4, + /* quant_vlc[4][1] - 15 entries */ + 0x04, 3, 0x03, 4, 0x0C, 5, 0x02, 5, 0x09, 3, 0x05, 3, 0x08, 3, + 0x06, 3, 0x07, 3, 0x01, 6, 0x0E, 8, 0x00, 8, 0x0D, 7, 0x0B, 5, + 0x0A, 4, + /* quant_vlc[5][0] - 31 entries */ + 0x0C, 4, 0x1A, 5, 0x01, 6, 0x1D, 6, 0x0D, 4, 0x10, 4, 0x11, 4, + 0x0E, 4, 0x19, 5, 0x05, 5, 0x0F, 4, 0x1E, 7, 0x00, 7, 0x1C, 6, + 0x06, 5, 0x18, 5, 0x07, 5, 0x17, 5, 0x09, 5, 0x02, 6, 0x03, 6, + 0x08, 5, 0x16, 5, 0x14, 5, 0x0A, 5, 0x15, 5, 0x13, 5, 0x1B, 6, + 0x04, 6, 0x0B, 5, 0x12, 5, + /* quant_vlc[5][1] - 31 entries */ + 0x0F, 3, 0x0A, 4, 0x14, 4, 0x17, 5, 0x07, 5, 0x13, 4, 0x0B, 4, + 0x16, 5, 0x08, 5, 0x0C, 4, 0x12, 4, 0x11, 4, 0x0D, 4, 0x18, 6, + 0x06, 6, 0x1B, 8, 0x1A, 8, 0x02, 10, 0x00, 13, 0x1D, 13, 0x01, 13, + 0x1E, 13, 0x1C, 11, 0x03, 9, 0x04, 8, 0x05, 7, 0x19, 7, 0x0E, 4, + 0x10, 4, 0x15, 5, 0x09, 5, + /* quant_vlc[6][0] - 63 entries */ + 0x18, 5, 0x25, 5, 0x19, 5, 0x24, 5, 0x23, 5, 0x1B, 5, 0x1D, 5, + 0x1F, 5, 0x22, 5, 0x1C, 5, 0x1A, 5, 0x20, 5, 0x0B, 6, 0x3A, 7, + 0x3E, 8, 0x00, 8, 0x1E, 5, 0x33, 6, 0x0C, 6, 0x21, 5, 0x04, 7, + 0x05, 7, 0x32, 6, 0x39, 7, 0x38, 7, 0x0D, 6, 0x31, 6, 0x0E, 6, + 0x3D, 8, 0x01, 8, 0x06, 7, 0x30, 6, 0x37, 7, 0x07, 7, 0x0F, 6, + 0x2F, 6, 0x2E, 6, 0x10, 6, 0x3C, 8, 0x02, 8, 0x08, 7, 0x11, 6, + 0x2D, 6, 0x2C, 6, 0x13, 6, 0x36, 7, 0x35, 7, 0x12, 6, 0x2B, 6, + 0x29, 6, 0x14, 6, 0x15, 6, 0x0A, 7, 0x09, 7, 0x16, 6, 0x3B, 8, + 0x03, 8, 0x34, 7, 0x2A, 6, 0x17, 6, 0x28, 6, 0x27, 6, 0x26, 6, + /* quant_vlc[6][1] - 63 entries */ + 0x20, 4, 0x2A, 5, 0x15, 5, 0x1F, 4, 0x29, 5, 0x0F, 6, 0x2F, 6, + 0x28, 5, 0x16, 5, 0x07, 9, 0x36, 9, 0x08, 9, 0x39, 10, 0x38, 10, + 0x32, 7, 0x2E, 6, 0x17, 5, 0x10, 6, 0x11, 6, 0x27, 5, 0x26, 5, + 0x0C, 7, 0x0A, 8, 0x34, 8, 0x2D, 6, 0x18, 5, 0x12, 6, 0x2C, 6, + 0x31, 7, 0x0D, 7, 0x13, 6, 0x19, 5, 0x25, 5, 0x1A, 5, 0x24, 5, + 0x2B, 6, 0x05, 10, 0x06, 10, 0x35, 9, 0x33, 8, 0x30, 7, 0x1B, 5, + 0x23, 5, 0x1C, 5, 0x14, 6, 0x0E, 7, 0x09, 9, 0x3A, 12, 0x00, 14, + 0x3E, 14, 0x02, 14, 0x3C, 14, 0x04, 12, 0x3D, 14, 0x01, 14, 0x03, 14, + 0x3B, 14, 0x37, 10, 0x0B, 8, 0x22, 5, 0x1D, 5, 0x21, 5, 0x1E, 5, }; #endif /* AVCODEC_MPC7DATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mpc8.c ffmpeg-4.4/libavcodec/mpc8.c --- ffmpeg-4.2.2/libavcodec/mpc8.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpc8.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/lfg.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "get_bits.h" #include "internal.h" @@ -39,9 +40,6 @@ static VLC band_vlc, scfi_vlc[2], dscf_vlc[2], res_vlc[2]; static VLC q1_vlc, q2_vlc[2], q3_vlc[2], quant_vlc[4][2], q9up_vlc; -static const int q3_offsets[2] = { MPC8_Q3_OFFSET, MPC8_Q4_OFFSET }; -static const int quant_offsets[6] = { MPC8_Q5_OFFSET, MPC8_Q6_OFFSET, MPC8_Q7_OFFSET, MPC8_Q8_OFFSET }; - static inline int mpc8_dec_base(GetBitContext *gb, int k, int n) { int len = mpc8_cnk_len[k-1][n-1] - 1; @@ -89,29 +87,63 @@ return mask; } -static const uint16_t vlc_offsets[13] = { - 0, 640, 1184, 1748, 2298, 2426, 2554, 3066, 3578, 4106, 4618, 5196, 5708 -}; +static av_cold void build_vlc(VLC *vlc, unsigned *buf_offset, + const uint8_t codes_counts[16], + const uint8_t **syms, int offset) +{ + static VLC_TYPE vlc_buf[9296][2]; + uint8_t len[MPC8_MAX_VLC_SIZE]; + unsigned num = 0; + + vlc->table = &vlc_buf[*buf_offset]; + vlc->table_allocated = FF_ARRAY_ELEMS(vlc_buf) - *buf_offset; + + for (int i = 16; i > 0; i--) + for (unsigned tmp = num + codes_counts[i - 1]; num < tmp; num++) + len[num] = i; + + ff_init_vlc_from_lengths(vlc, FFMIN(len[0], 9), num, len, 1, + *syms, 1, 1, offset, INIT_VLC_STATIC_OVERLONG, NULL); + *buf_offset += vlc->table_size; + *syms += num; +} + +static av_cold void mpc8_init_static(void) +{ + const uint8_t *q_syms = mpc8_q_syms, *bands_syms = mpc8_bands_syms; + const uint8_t *res_syms = mpc8_res_syms, *scfi_syms = mpc8_scfi_syms; + const uint8_t *dscf_syms = mpc8_dscf_syms; + unsigned offset = 0; + + build_vlc(&band_vlc, &offset, mpc8_bands_len_counts, &bands_syms, 0); + + build_vlc(&q1_vlc, &offset, mpc8_q1_len_counts, &q_syms, 0); + build_vlc(&q9up_vlc, &offset, mpc8_q9up_len_counts, &q_syms, 0); + + for (int i = 0; i < 2; i++){ + build_vlc(&scfi_vlc[i], &offset, mpc8_scfi_len_counts[i], &scfi_syms, 0); + + build_vlc(&dscf_vlc[i], &offset, mpc8_dscf_len_counts[i], &dscf_syms, 0); + + build_vlc(&res_vlc[i], &offset, mpc8_res_len_counts[i], &res_syms, 0); + + build_vlc(&q2_vlc[i], &offset, mpc8_q2_len_counts[i], &q_syms, 0); + build_vlc(&q3_vlc[i], &offset, mpc8_q34_len_counts[i], + &q_syms, -48 - 16 * i); + for (int j = 0; j < 4; j++) + build_vlc(&quant_vlc[j][i], &offset, mpc8_q5_8_len_counts[i][j], + &q_syms, -((8 << j) - 1)); + } + ff_mpa_synth_init_fixed(); +} static av_cold int mpc8_decode_init(AVCodecContext * avctx) { - int i; + static AVOnce init_static_once = AV_ONCE_INIT; MPCContext *c = avctx->priv_data; GetBitContext gb; - static int vlc_initialized = 0; int channels; - static VLC_TYPE band_table[542][2]; - static VLC_TYPE q1_table[520][2]; - static VLC_TYPE q9up_table[524][2]; - static VLC_TYPE scfi0_table[1 << MPC8_SCFI0_BITS][2]; - static VLC_TYPE scfi1_table[1 << MPC8_SCFI1_BITS][2]; - static VLC_TYPE dscf0_table[560][2]; - static VLC_TYPE dscf1_table[598][2]; - static VLC_TYPE q3_0_table[512][2]; - static VLC_TYPE q3_1_table[516][2]; - static VLC_TYPE codes_table[5708][2]; - if(avctx->extradata_size < 2){ av_log(avctx, AV_LOG_ERROR, "Too small extradata size (%i)!\n", avctx->extradata_size); return -1; @@ -120,8 +152,6 @@ av_lfg_init(&c->rnd, 0xDEADBEEF); ff_mpadsp_init(&c->mpadsp); - ff_mpc_init(); - init_get_bits(&gb, avctx->extradata, 16); skip_bits(&gb, 3);//sample rate @@ -142,96 +172,7 @@ avctx->channel_layout = (channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; avctx->channels = channels; - if(vlc_initialized) return 0; - av_log(avctx, AV_LOG_DEBUG, "Initing VLC\n"); - - band_vlc.table = band_table; - band_vlc.table_allocated = 542; - init_vlc(&band_vlc, MPC8_BANDS_BITS, MPC8_BANDS_SIZE, - mpc8_bands_bits, 1, 1, - mpc8_bands_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); - - q1_vlc.table = q1_table; - q1_vlc.table_allocated = 520; - init_vlc(&q1_vlc, MPC8_Q1_BITS, MPC8_Q1_SIZE, - mpc8_q1_bits, 1, 1, - mpc8_q1_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); - q9up_vlc.table = q9up_table; - q9up_vlc.table_allocated = 524; - init_vlc(&q9up_vlc, MPC8_Q9UP_BITS, MPC8_Q9UP_SIZE, - mpc8_q9up_bits, 1, 1, - mpc8_q9up_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); - - scfi_vlc[0].table = scfi0_table; - scfi_vlc[0].table_allocated = 1 << MPC8_SCFI0_BITS; - init_vlc(&scfi_vlc[0], MPC8_SCFI0_BITS, MPC8_SCFI0_SIZE, - mpc8_scfi0_bits, 1, 1, - mpc8_scfi0_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); - scfi_vlc[1].table = scfi1_table; - scfi_vlc[1].table_allocated = 1 << MPC8_SCFI1_BITS; - init_vlc(&scfi_vlc[1], MPC8_SCFI1_BITS, MPC8_SCFI1_SIZE, - mpc8_scfi1_bits, 1, 1, - mpc8_scfi1_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); - - dscf_vlc[0].table = dscf0_table; - dscf_vlc[0].table_allocated = 560; - init_vlc(&dscf_vlc[0], MPC8_DSCF0_BITS, MPC8_DSCF0_SIZE, - mpc8_dscf0_bits, 1, 1, - mpc8_dscf0_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); - dscf_vlc[1].table = dscf1_table; - dscf_vlc[1].table_allocated = 598; - init_vlc(&dscf_vlc[1], MPC8_DSCF1_BITS, MPC8_DSCF1_SIZE, - mpc8_dscf1_bits, 1, 1, - mpc8_dscf1_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); - - q3_vlc[0].table = q3_0_table; - q3_vlc[0].table_allocated = 512; - ff_init_vlc_sparse(&q3_vlc[0], MPC8_Q3_BITS, MPC8_Q3_SIZE, - mpc8_q3_bits, 1, 1, - mpc8_q3_codes, 1, 1, - mpc8_q3_syms, 1, 1, INIT_VLC_USE_NEW_STATIC); - q3_vlc[1].table = q3_1_table; - q3_vlc[1].table_allocated = 516; - ff_init_vlc_sparse(&q3_vlc[1], MPC8_Q4_BITS, MPC8_Q4_SIZE, - mpc8_q4_bits, 1, 1, - mpc8_q4_codes, 1, 1, - mpc8_q4_syms, 1, 1, INIT_VLC_USE_NEW_STATIC); - - for(i = 0; i < 2; i++){ - res_vlc[i].table = &codes_table[vlc_offsets[0+i]]; - res_vlc[i].table_allocated = vlc_offsets[1+i] - vlc_offsets[0+i]; - init_vlc(&res_vlc[i], MPC8_RES_BITS, MPC8_RES_SIZE, - &mpc8_res_bits[i], 1, 1, - &mpc8_res_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - - q2_vlc[i].table = &codes_table[vlc_offsets[2+i]]; - q2_vlc[i].table_allocated = vlc_offsets[3+i] - vlc_offsets[2+i]; - init_vlc(&q2_vlc[i], MPC8_Q2_BITS, MPC8_Q2_SIZE, - &mpc8_q2_bits[i], 1, 1, - &mpc8_q2_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - - quant_vlc[0][i].table = &codes_table[vlc_offsets[4+i]]; - quant_vlc[0][i].table_allocated = vlc_offsets[5+i] - vlc_offsets[4+i]; - init_vlc(&quant_vlc[0][i], MPC8_Q5_BITS, MPC8_Q5_SIZE, - &mpc8_q5_bits[i], 1, 1, - &mpc8_q5_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - quant_vlc[1][i].table = &codes_table[vlc_offsets[6+i]]; - quant_vlc[1][i].table_allocated = vlc_offsets[7+i] - vlc_offsets[6+i]; - init_vlc(&quant_vlc[1][i], MPC8_Q6_BITS, MPC8_Q6_SIZE, - &mpc8_q6_bits[i], 1, 1, - &mpc8_q6_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - quant_vlc[2][i].table = &codes_table[vlc_offsets[8+i]]; - quant_vlc[2][i].table_allocated = vlc_offsets[9+i] - vlc_offsets[8+i]; - init_vlc(&quant_vlc[2][i], MPC8_Q7_BITS, MPC8_Q7_SIZE, - &mpc8_q7_bits[i], 1, 1, - &mpc8_q7_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - quant_vlc[3][i].table = &codes_table[vlc_offsets[10+i]]; - quant_vlc[3][i].table_allocated = vlc_offsets[11+i] - vlc_offsets[10+i]; - init_vlc(&quant_vlc[3][i], MPC8_Q8_BITS, MPC8_Q8_SIZE, - &mpc8_q8_bits[i], 1, 1, - &mpc8_q8_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - } - vlc_initialized = 1; + ff_thread_once(&init_static_once, mpc8_init_static); return 0; } @@ -382,9 +323,9 @@ case 3: case 4: for(j = 0; j < SAMPLES_PER_BAND; j += 2){ - t = get_vlc2(gb, q3_vlc[res - 3].table, MPC8_Q3_BITS, 2) + q3_offsets[res - 3]; + t = get_vlc2(gb, q3_vlc[res - 3].table, MPC8_Q3_BITS, 2); c->Q[ch][off + j + 1] = t >> 4; - c->Q[ch][off + j + 0] = (t & 8) ? (t & 0xF) - 16 : (t & 0xF); + c->Q[ch][off + j + 0] = sign_extend(t, 4); } break; case 5: @@ -393,8 +334,8 @@ case 8: cnt = 2 * mpc8_thres[res]; for(j = 0; j < SAMPLES_PER_BAND; j++){ - t = get_vlc2(gb, quant_vlc[res - 5][cnt > mpc8_thres[res]].table, quant_vlc[res - 5][cnt > mpc8_thres[res]].bits, 2) + quant_offsets[res - 5]; - c->Q[ch][off + j] = t; + const VLC *vlc = &quant_vlc[res - 5][cnt > mpc8_thres[res]]; + c->Q[ch][off + j] = get_vlc2(gb, vlc->table, vlc->bits, 2); cnt = (cnt >> 1) + FFABS(c->Q[ch][off + j]); } break; @@ -451,7 +392,8 @@ .init = mpc8_decode_init, .decode = mpc8_decode_frame, .flush = mpc8_decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/mpc8huff.h ffmpeg-4.4/libavcodec/mpc8huff.h --- ffmpeg-4.2.2/libavcodec/mpc8huff.h 2016-03-29 02:25:18.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpc8huff.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,555 +24,207 @@ #include +#define MPC8_MAX_VLC_SIZE 256 + #define MPC8_BANDS_SIZE 33 #define MPC8_BANDS_BITS 9 -static const uint8_t mpc8_bands_codes[MPC8_BANDS_SIZE] = { - 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, - 0x05, 0x06, 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x01, 0x09, 0x0A, 0x0B, 0x07, - 0x08, 0x09, 0x06, 0x07, 0x05, 0x05, 0x03, 0x03, - 0x01, -}; -static const int8_t mpc8_bands_bits[MPC8_BANDS_SIZE] = { - 1, 3, 5, 6, 7, 8, 8, 9, - 10, 11, 12, 12, 12, 13, 12, 12, - 12, 12, 12, 13, 12, 12, 12, 11, - 11, 11, 10, 10, 9, 8, 6, 5, - 2, -}; - -#define MPC8_SCFI0_SIZE 4 -#define MPC8_SCFI0_BITS 3 - -static const uint8_t mpc8_scfi0_codes[MPC8_SCFI0_SIZE] = { - 0x00, 0x01, 0x01, 0x01, +static const uint8_t mpc8_bands_syms[MPC8_BANDS_SIZE] = { + 13, 19, 10, 11, 12, 14, 15, 16, 17, 18, 20, 21, 22, 9, 23, 24, 25, 8, 26, + 27, 7, 28, 5, 6, 29, 4, 3, 30, 2, 31, 1, 32, 0 }; -static const int8_t mpc8_scfi0_bits[MPC8_SCFI0_SIZE] = { - 3, 3, 1, 2, +static const uint8_t mpc8_bands_len_counts[16] = { + 1, 1, 1, 0, 2, 2, 1, 3, 2, 3, 4, 11, 2, 0, 0, 0 }; -#define MPC8_SCFI1_SIZE 16 -#define MPC8_SCFI1_BITS 7 - -static const uint8_t mpc8_scfi1_codes[MPC8_SCFI1_SIZE] = { - 0x01, 0x00, 0x02, 0x03, 0x01, 0x03, 0x04, 0x05, - 0x04, 0x06, 0x02, 0x02, 0x05, 0x07, 0x03, 0x03, - +static const uint8_t mpc8_scfi_syms[] = { + /* SCFI[0] VLC symbols - 4 entries */ + 0, 1, 3, 2, + /* SCFI[1] VLC symbols - 16 entries */ + 1, 4, 0, 2, 3, 8, 12, 5, 6, 7, 9, 13, 11, 14, 10, 15 }; -static const int8_t mpc8_scfi1_bits[MPC8_SCFI1_SIZE] = { - 6, 7, 6, 6, 7, 5, 5, 5, - 6, 5, 2, 3, 6, 5, 3, 2, +static const uint8_t mpc8_scfi_len_counts[2][16] = { + { 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 2, 2, 0, 5, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, }; -#define MPC8_DSCF0_SIZE 64 #define MPC8_DSCF0_BITS 9 - -static const uint8_t mpc8_dscf0_codes[MPC8_DSCF0_SIZE] = { - 0x03, 0x04, 0x05, 0x04, 0x05, 0x06, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x07, 0x08, 0x09, 0x0A, 0x07, - 0x08, 0x09, 0x0A, 0x07, 0x08, 0x09, 0x0A, 0x06, - 0x07, 0x05, 0x04, 0x05, 0x06, 0x06, 0x07, 0x0A, - 0x08, 0x05, 0x06, 0x07, 0x09, 0x07, 0x08, 0x09, - 0x0B, 0x0B, 0x0C, 0x0D, 0x0B, 0x0C, 0x0D, 0x0B, - 0x0C, 0x0D, 0x07, 0x08, 0x09, 0x06, 0x07, 0x03, - 0x04, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, -}; -static const int8_t mpc8_dscf0_bits[MPC8_DSCF0_SIZE] = { - 12, 12, 12, 11, 11, 11, 10, 10, - 10, 10, 10, 9, 9, 9, 9, 8, - 8, 8, 8, 7, 7, 7, 7, 6, - 6, 5, 4, 4, 5, 4, 4, 10, - 4, 3, 3, 3, 4, 5, 6, 6, - 7, 8, 8, 8, 9, 9, 9, 10, - 10, 10, 11, 11, 11, 12, 12, 13, - 13, 13, 14, 14, 14, 14, 14, 14, - -}; - -#define MPC8_DSCF1_SIZE 65 #define MPC8_DSCF1_BITS 9 -static const uint8_t mpc8_dscf1_codes[MPC8_DSCF1_SIZE] = { - 0x00, 0x03, 0x04, 0x04, 0x05, 0x06, 0x05, 0x06, - 0x07, 0x08, 0x07, 0x08, 0x09, 0x0A, 0x07, 0x08, - 0x09, 0x0A, 0x07, 0x08, 0x09, 0x06, 0x07, 0x05, - 0x06, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x05, 0x04, 0x05, 0x05, 0x07, 0x08, - 0x09, 0x0A, 0x0B, 0x0B, 0x0C, 0x0D, 0x0B, 0x0C, - 0x0D, 0x09, 0x0A, 0x0B, 0x0C, 0x07, 0x08, 0x09, - 0x05, 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x0D, -}; -static const int8_t mpc8_dscf1_bits[MPC8_DSCF1_SIZE] = { - 15, 14, 14, 13, 13, 13, 12, 12, - 12, 12, 11, 11, 11, 11, 10, 10, - 10, 10, 9, 9, 9, 8, 8, 7, - 7, 6, 5, 4, 4, 3, 3, 3, - 3, 3, 4, 5, 5, 6, 7, 8, - 8, 9, 9, 10, 10, 10, 11, 11, - 11, 12, 12, 12, 12, 13, 13, 13, - 14, 14, 14, 15, 15, 15, 15, 15, - 12, +static const uint8_t mpc8_dscf_syms[] = { + /* DSCF[0] VLC symbols - 64 entries */ + 58, 59, 60, 61, 62, 63, 55, 56, 57, 0, 1, 2, 53, 54, 3, 4, 5, 50, 51, + 52, 6, 7, 8, 9, 10, 31, 47, 48, 49, 11, 12, 13, 14, 44, 45, 46, 15, 16, + 17, 18, 41, 42, 43, 19, 20, 21, 22, 40, 23, 24, 38, 39, 25, 28, 37, 26, 27, + 29, 30, 32, 36, 33, 34, 35, + /* DSCF[1] VLC symbols - 65 entries */ + 0, 59, 60, 61, 62, 63, 1, 2, 56, 57, 58, 3, 4, 5, 53, 54, 55, 6, 7, + 8, 9, 49, 50, 51, 52, 64, 10, 11, 12, 13, 46, 47, 48, 14, 15, 16, 17, 43, + 44, 45, 18, 19, 20, 41, 42, 21, 22, 39, 40, 23, 24, 38, 25, 37, 26, 35, 36, + 27, 28, 34, 29, 30, 31, 32, 33, +}; + +static const uint8_t mpc8_dscf_len_counts[2][16] = { + { 0, 0, 3, 6, 3, 4, 5, 7, 7, 9, 6, 5, 3, 6, 0, 0 }, + { 0, 0, 5, 3, 3, 2, 3, 4, 5, 7, 7, 9, 6, 5, 6, 0 }, }; -#define MPC8_RES_SIZE 17 #define MPC8_RES_BITS 9 -static const uint8_t mpc8_res_codes[2][MPC8_RES_SIZE] = { - { - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, - 0x01, - }, - { - 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01, 0x01, - 0x03, - } -}; -static const int8_t mpc8_res_bits[2][MPC8_RES_SIZE] = { - { - 1, 2, 4, 5, 6, 7, 9, 10, - 11, 12, 13, 14, 15, 16, 16, 8, - 3, - }, - { - 2, 2, 3, 5, 7, 8, 10, 12, - 14, 14, 14, 14, 11, 9, 6, 4, - 2, - } +static const uint8_t mpc8_res_syms[] = { + /* RES[0] VLC symbols - 17 entries */ + 13, 14, 12, 11, 10, 9, 8, 7, 6, 15, 5, 4, 3, 2, 16, 1, 0, + /* RES[1] VLC symbols - 17 entries */ + 8, 9, 10, 11, 7, 12, 6, 13, 5, 4, 14, 3, 15, 2, 0, 1, 16, +}; + +static const uint8_t mpc8_res_len_counts[2][16] = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2 }, + { 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 4, 0, 0 }, }; -#define MPC8_Q1_SIZE 19 #define MPC8_Q1_BITS 9 -static const uint8_t mpc8_q1_codes[MPC8_Q1_SIZE] = { - 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x03, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x01, -}; -static const int8_t mpc8_q1_bits[MPC8_Q1_SIZE] = { - 6, 4, 4, 3, 3, 3, 3, 3, - 4, 4, 4, 5, 7, 8, 9, 10, - 11, 12, 12, +static const uint8_t mpc8_q1_len_counts[16] = { + 0, 0, 5, 5, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0 }; -#define MPC8_Q9UP_SIZE 256 #define MPC8_Q9UP_BITS 9 -static const uint8_t mpc8_q9up_codes[MPC8_Q9UP_SIZE] = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x26, 0x27, 0x13, 0x14, 0x15, - 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, - 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, - 0x28, 0x26, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, - 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, - 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, - 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, - 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, - 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, - 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, - 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, - 0x67, 0x68, 0x69, 0x6A, 0x56, 0x57, 0x58, 0x59, - 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, - 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x3E, - 0x3F, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7A, 0x6B, 0x7B, 0x6C, 0x6D, 0x6E, - 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, - 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, - 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, - 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, - 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, - 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, - 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0x27, 0x28, 0x29, - 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, - 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, - 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4A, 0x4B, 0x06, 0x07, 0x08, 0x09, 0x00, 0x01, -}; -static const int8_t mpc8_q9up_bits[MPC8_Q9UP_SIZE] = { - 10, 10, 10, 10, 10, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 8, 8, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, - 8, 9, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 6, - 6, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 8, 7, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 10, 10, 10, 10, 11, 11, +static const uint8_t mpc8_q9up_len_counts[16] = { + 0, 0, 0, 0, 0, 2, 38, 134, 71, 9, 2, 0, 0, 0, 0, 0 }; -#define MPC8_Q2_SIZE 125 #define MPC8_Q2_BITS 9 -static const uint8_t mpc8_q2_codes[2][MPC8_Q2_SIZE] = { -{ - 0x02, 0x03, 0x0F, 0x04, 0x00, 0x05, 0x0C, 0x12, - 0x0D, 0x06, 0x07, 0x13, 0x15, 0x14, 0x08, 0x09, - 0x0E, 0x15, 0x0F, 0x0A, 0x03, 0x0B, 0x10, 0x0C, - 0x01, 0x0D, 0x10, 0x16, 0x11, 0x0E, 0x12, 0x0F, - 0x10, 0x16, 0x13, 0x17, 0x11, 0x08, 0x12, 0x18, - 0x14, 0x13, 0x14, 0x17, 0x15, 0x0F, 0x16, 0x19, - 0x17, 0x10, 0x11, 0x1A, 0x18, 0x1B, 0x12, 0x1C, - 0x15, 0x09, 0x16, 0x1D, 0x19, 0x0A, 0x07, 0x0B, - 0x1A, 0x1E, 0x17, 0x0C, 0x18, 0x1F, 0x13, 0x20, - 0x1B, 0x21, 0x14, 0x11, 0x18, 0x22, 0x19, 0x12, - 0x1A, 0x19, 0x1A, 0x1B, 0x1B, 0x23, 0x1C, 0x0D, - 0x1D, 0x24, 0x1C, 0x1C, 0x1E, 0x1F, 0x1D, 0x13, - 0x1E, 0x25, 0x1F, 0x14, 0x02, 0x15, 0x15, 0x16, - 0x04, 0x17, 0x20, 0x26, 0x21, 0x18, 0x16, 0x27, - 0x1D, 0x28, 0x19, 0x1A, 0x22, 0x29, 0x23, 0x1B, - 0x03, 0x1C, 0x17, 0x1D, 0x05, -}, -{ - 0x02, 0x03, 0x0F, 0x04, 0x00, 0x05, 0x0C, 0x0D, - 0x0E, 0x06, 0x07, 0x0F, 0x1E, 0x10, 0x10, 0x08, - 0x11, 0x12, 0x13, 0x09, 0x03, 0x0A, 0x11, 0x0B, - 0x01, 0x0C, 0x14, 0x15, 0x16, 0x0D, 0x17, 0x12, - 0x0E, 0x13, 0x18, 0x19, 0x14, 0x0F, 0x10, 0x1A, - 0x1B, 0x15, 0x11, 0x16, 0x1C, 0x0E, 0x1D, 0x1E, - 0x1F, 0x0F, 0x12, 0x20, 0x1F, 0x21, 0x13, 0x22, - 0x12, 0x13, 0x14, 0x23, 0x20, 0x15, 0x0F, 0x16, - 0x21, 0x24, 0x17, 0x18, 0x19, 0x25, 0x14, 0x26, - 0x22, 0x27, 0x15, 0x10, 0x28, 0x29, 0x2A, 0x11, - 0x2B, 0x17, 0x1A, 0x18, 0x2C, 0x2D, 0x1B, 0x1C, - 0x19, 0x2E, 0x2F, 0x1A, 0x1D, 0x1B, 0x30, 0x12, - 0x31, 0x32, 0x33, 0x13, 0x02, 0x14, 0x15, 0x16, - 0x04, 0x17, 0x34, 0x35, 0x36, 0x18, 0x16, 0x37, - 0x23, 0x38, 0x19, 0x1A, 0x39, 0x3A, 0x3B, 0x1B, - 0x03, 0x1C, 0x17, 0x1D, 0x05, -} -}; -static const int8_t mpc8_q2_bits[2][MPC8_Q2_SIZE] = { -{ - 12, 11, 10, 11, 13, 11, 9, 8, - 9, 11, 11, 8, 7, 8, 11, 11, - 9, 8, 9, 11, 12, 11, 10, 11, - 13, 11, 9, 8, 9, 11, 9, 6, - 6, 7, 9, 8, 6, 4, 6, 8, - 9, 6, 6, 7, 9, 11, 9, 8, - 9, 11, 10, 8, 7, 8, 10, 8, - 6, 4, 6, 8, 7, 4, 3, 4, - 7, 8, 6, 4, 6, 8, 10, 8, - 7, 8, 10, 11, 9, 8, 9, 11, - 9, 6, 6, 6, 9, 8, 6, 4, - 6, 8, 9, 7, 6, 6, 9, 11, - 9, 8, 9, 11, 13, 11, 10, 11, - 12, 11, 9, 8, 9, 11, 10, 8, - 7, 8, 11, 11, 9, 8, 9, 11, - 13, 11, 10, 11, 12, -}, -{ - 11, 10, 9, 10, 12, 10, 8, 8, - 8, 10, 10, 8, 7, 8, 9, 10, - 8, 8, 8, 10, 11, 10, 9, 10, - 12, 10, 8, 8, 8, 10, 8, 6, - 5, 6, 8, 8, 6, 5, 5, 8, - 8, 6, 5, 6, 8, 10, 8, 8, - 8, 10, 9, 8, 7, 8, 9, 8, - 5, 5, 5, 8, 7, 5, 4, 5, - 7, 8, 5, 5, 5, 8, 9, 8, - 7, 8, 9, 10, 8, 8, 8, 10, - 8, 6, 5, 6, 8, 8, 5, 5, - 6, 8, 8, 6, 5, 6, 8, 10, - 8, 8, 8, 10, 12, 10, 10, 10, - 11, 10, 8, 8, 8, 10, 9, 8, - 7, 8, 10, 10, 8, 8, 8, 10, - 12, 10, 9, 10, 11, -} +static const uint8_t mpc8_q2_len_counts[2][16] = { + { 0, 0, 1, 6, 0, 17, 9, 24, 24, 9, 27, 4, 4, 0, 0, 0 }, + { 0, 0, 0, 1, 16, 10, 6, 48, 9, 27, 4, 4, 0, 0, 0, 0 }, }; -#define MPC8_Q3_SIZE 49 #define MPC8_Q3_BITS 9 -#define MPC8_Q3_OFFSET -48 - -static const uint8_t mpc8_q3_codes[MPC8_Q3_SIZE] = { - 0x07, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x0F, - 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x13, 0x12, 0x11, - 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, - 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, - 0x09, 0x08, 0x07, 0x06, 0x05, 0x09, 0x08, 0x07, - 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, - 0x00, -}; -static const int8_t mpc8_q3_bits[MPC8_Q3_SIZE] = { - 3, 4, 4, 4, 4, 4, 4, 5, - 5, 5, 5, 5, 5, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 8, 8, 8, - 8, 8, 8, 8, 8, 9, 9, 9, - 9, -}; -static const int8_t mpc8_q3_syms[MPC8_Q3_SIZE] = { - 48, 65, 64, 49, 63, 32, 47, 80, - 79, 50, 62, 33, 16, 82, 81, 95, - 94, 66, 78, 34, 46, 17, 31, 30, - 97, 96, 111, 67, 77, 51, 61, 35, - 45, 18, 1, 0, 15, 98, 110, 83, - 93, 19, 29, 2, 14, 99, 109, 3, - 13, -}; - -#define MPC8_Q4_SIZE 81 #define MPC8_Q4_BITS 9 -#define MPC8_Q4_OFFSET -64 -static const uint8_t mpc8_q4_codes[MPC8_Q4_SIZE] = { - 0x0F, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, - 0x16, 0x15, 0x14, 0x13, 0x12, 0x23, 0x22, 0x21, - 0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, - 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, - 0x10, 0x0F, 0x0E, 0x0D, 0x19, 0x18, 0x17, 0x16, - 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F, 0x0E, - 0x0D, 0x0C, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, - 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, - 0x09, 0x08, 0x07, 0x06, 0x05, 0x09, 0x08, 0x07, - 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, - 0x00, -}; -static const int8_t mpc8_q4_bits[MPC8_Q4_SIZE] = { - 4, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 9, 9, 9, - 9, 9, 9, 9, 9, 10, 10, 10, - 10, -}; -static const int8_t mpc8_q4_syms[MPC8_Q4_SIZE] = { - 64, 96, 81, 80, 95, 66, 65, 79, - 78, 49, 48, 63, 32, 113, 112, 98, - 97, 111, 110, 83, 82, 94, 93, 67, - 77, 51, 50, 62, 61, 34, 33, 47, - 46, 17, 16, 31, 128, 114, 127, 126, - 99, 109, 68, 76, 35, 45, 18, 30, - 0, 15, 130, 129, 143, 142, 115, 125, - 100, 108, 84, 92, 52, 60, 36, 44, - 19, 29, 2, 1, 14, 131, 141, 116, - 124, 20, 28, 3, 13, 132, 140, 4, - 12, -}; - -#define MPC8_Q5_SIZE 15 -#define MPC8_Q5_BITS 7 -#define MPC8_Q5_OFFSET -7 - -static const uint8_t mpc8_q5_codes[2][MPC8_Q5_SIZE] = { -{ - 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, - 0x04, 0x05, 0x03, 0x03, 0x03, 0x02, 0x03, -}, -{ - 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x04, 0x05, 0x03, 0x02, 0x03, -} -}; -static const int8_t mpc8_q5_bits[2][MPC8_Q5_SIZE] = { -{ - 7, 7, 6, 5, 4, 3, 3, 2, - 3, 3, 4, 5, 6, 7, 7, -}, -{ - 6, 6, 5, 4, 4, 3, 3, 3, - 3, 3, 4, 4, 5, 6, 6, -} -}; - -#define MPC8_Q6_SIZE 31 -#define MPC8_Q6_BITS 9 -#define MPC8_Q6_OFFSET -15 - -static const uint8_t mpc8_q6_codes[2][MPC8_Q6_SIZE] = { -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x04, 0x03, - 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x04, 0x03, - 0x05, 0x06, 0x07, 0x07, 0x06, 0x07, 0x08, 0x09, - 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, -}, -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x04, - 0x05, 0x06, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, - 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x07, 0x08, 0x09, - 0x06, 0x07, 0x05, 0x06, 0x07, 0x02, 0x03, -} -}; -static const int8_t mpc8_q6_bits[2][MPC8_Q6_SIZE] = { -{ - 9, 9, 9, 9, 8, 8, 7, 6, - 6, 6, 5, 5, 4, 4, 3, 2, - 3, 4, 4, 5, 6, 6, 6, 6, - 7, 8, 8, 9, 9, 9, 9, -}, -{ - 8, 8, 7, 7, 7, 6, 6, 5, - 5, 5, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 5, 5, 5, - 6, 6, 7, 7, 7, 8, 8, -} -}; - -#define MPC8_Q7_SIZE 63 -#define MPC8_Q7_BITS 9 -#define MPC8_Q7_OFFSET -31 - -static const uint8_t mpc8_q7_codes[2][MPC8_Q7_SIZE] = { -{ - 0x00, 0x01, 0x02, 0x08, 0x09, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x0A, 0x0B, 0x0C, 0x0D, 0x0A, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, - 0x0A, 0x0B, 0x0C, 0x08, 0x09, 0x06, 0x04, 0x03, - 0x05, 0x07, 0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x0F, - 0x10, 0x11, 0x12, 0x0F, 0x13, 0x10, 0x11, 0x12, - 0x13, 0x0E, 0x0F, 0x10, 0x11, 0x08, 0x09, 0x0A, - 0x0B, 0x0C, 0x12, 0x13, 0x0D, 0x0E, 0x0F, -}, -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x09, 0x0A, - 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x0C, 0x0D, - 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, - 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, - 0x1E, 0x1F, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, - 0x17, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, - 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x02, 0x03, -} -}; -static const int8_t mpc8_q7_bits[2][MPC8_Q7_SIZE] = { -{ - 10, 10, 10, 9, 9, 10, 10, 10, - 10, 10, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 7, 7, 7, 7, 7, - 6, 6, 6, 5, 5, 4, 3, 2, - 3, 4, 5, 5, 6, 6, 6, 7, - 7, 7, 7, 8, 7, 8, 8, 8, - 8, 9, 9, 9, 9, 10, 10, 10, - 10, 10, 9, 9, 10, 10, 10, -}, -{ - 9, 9, 8, 8, 8, 8, 8, 8, - 8, 7, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 6, 6, 6, 6, 6, 6, - 6, 7, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 8, 8, 9, 9, -} -}; - -#define MPC8_Q8_SIZE 127 -#define MPC8_Q8_BITS 9 -#define MPC8_Q8_OFFSET -63 - -static const uint8_t mpc8_q8_codes[2][MPC8_Q8_SIZE] = { -{ - 0x03, 0x04, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x1A, - 0x0F, 0x1B, 0x10, 0x00, 0x01, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x11, 0x0C, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1C, 0x1A, - 0x1B, 0x1C, 0x1D, 0x1E, 0x1D, 0x1E, 0x1F, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x19, 0x25, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1E, 0x1F, 0x14, 0x15, 0x16, 0x17, - 0x0E, 0x0F, 0x10, 0x11, 0x0B, 0x07, 0x04, 0x03, - 0x05, 0x0C, 0x0D, 0x12, 0x13, 0x14, 0x15, 0x18, - 0x19, 0x1A, 0x1B, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x25, 0x26, 0x27, 0x26, 0x27, 0x28, 0x29, 0x2A, - 0x2B, 0x2C, 0x2D, 0x2E, 0x1F, 0x20, 0x2F, 0x21, - 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, - 0x0D, 0x0E, 0x2A, 0x0F, 0x10, 0x11, 0x12, 0x02, - 0x13, 0x03, 0x04, 0x05, 0x2B, 0x2C, 0x30, 0x31, - 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, -}, -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, - 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, - 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, - 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, - 0x2F, 0x30, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, - 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, - 0x3C, 0x3D, 0x3E, 0x31, 0x3F, 0x32, 0x33, 0x34, - 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, - 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x16, - 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, - 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, - 0x27, 0x28, 0x29, 0x04, 0x05, 0x06, 0x07, -} -}; -static const int8_t mpc8_q8_bits[2][MPC8_Q8_SIZE] = { -{ - 11, 11, 10, 10, 10, 10, 10, 9, - 10, 9, 10, 12, 12, 11, 11, 11, - 11, 11, 11, 11, 10, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 9, 10, - 10, 10, 10, 10, 9, 9, 9, 9, - 9, 9, 9, 9, 8, 9, 8, 8, - 8, 8, 8, 8, 7, 7, 7, 7, - 6, 6, 6, 6, 5, 4, 3, 2, - 3, 5, 5, 6, 6, 6, 6, 7, - 7, 7, 7, 8, 8, 8, 8, 8, - 8, 8, 8, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 10, 10, 9, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 10, 11, 11, 11, 11, 12, - 11, 12, 12, 12, 10, 10, 9, 9, - 10, 10, 10, 10, 10, 10, 10, -}, -{ - 9, 9, 9, 9, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 7, 6, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 9, 9, 9, 9, -} +static const uint8_t mpc8_q34_len_counts[2][16] = { + { 0, 0, 1, 6, 6, 11, 13, 8, 4, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 1, 12, 23, 14, 19, 8, 4, 0, 0, 0, 0, 0, 0 }, +}; + +static const uint8_t mpc8_q5_8_len_counts[2][4][16] = { + { /* Q5[0], Q6[0], Q7[0], Q8[0] */ + { 0, 1, 4, 2, 2, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 2, 4, 3, 7, 2, 4, 8, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 2, 2, 4, 6, 10, 10, 12, 16, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 2, 1, 3, 8, 8, 15, 24, 42, 17, 6, 0, 0, 0, 0 }, + }, + { /* Q5[1], Q6[1], Q7[1], Q8[1] */ + { 0, 0, 5, 4, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 11, 6, 4, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 20, 15, 10, 14, 4, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 26, 55, 38, 8, 0, 0, 0, 0, 0, 0, 0 }, + } +}; + +static const uint8_t mpc8_q_syms[] = { + /* Q1 VLC symbols - 19 entries */ + 17, 18, 16, 15, 14, 13, 12, 0, 11, 1, 2, 8, 9, 10, 3, + 4, 5, 6, 7, + /* Q9UP VLC symbols - 256 entries */ + 254, 255, 0, 1, 2, 3, 4, 250, 251, 252, 253, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 41, + 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 19, 20, 40, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 147, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, + 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, + 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 148, 127, + 128, + /* Q2[0] VLC symbols - 125 entries */ + 4, 24, 100, 120, 0, 20, 104, 124, 1, 3, 5, 9, 10, 14, 15, + 19, 21, 23, 25, 29, 45, 49, 75, 79, 95, 99, 101, 103, 105, 109, + 114, 115, 119, 121, 123, 2, 22, 50, 54, 70, 74, 102, 110, 122, 6, + 8, 16, 18, 26, 28, 30, 34, 40, 44, 46, 48, 76, 78, 80, 84, + 90, 94, 96, 98, 106, 108, 116, 118, 7, 11, 13, 17, 27, 35, 39, + 47, 51, 53, 55, 59, 65, 69, 71, 73, 77, 85, 89, 97, 107, 111, + 113, 117, 12, 33, 43, 52, 60, 64, 72, 91, 112, 31, 32, 36, 38, + 41, 42, 56, 58, 66, 68, 81, 82, 83, 86, 88, 92, 93, 37, 57, + 61, 63, 67, 87, 62, + /* Q3 VLC symbols - 49 entries */ + 13, 3, 109, 99, 14, 2, 29, 19, 93, 83, 110, 98, 15, 0, 1, + 18, 45, 35, 61, 51, 77, 67, 111, 96, 97, 30, 31, 17, 46, 34, + 78, 66, 94, 95, 81, 82, 16, 33, 62, 50, 79, 80, 47, 32, 63, + 49, 64, 65, 48, + /* Q5[0] VLC symbols - 15 entries */ + 0, 1, 13, 14, 2, 12, 3, 11, 4, 10, 5, 6, 8, 9, 7, + /* Q6[0] VLC symbols - 31 entries */ + 0, 1, 2, 3, 27, 28, 29, 30, 4, 5, 25, 26, 6, 24, 7, + 8, 9, 20, 21, 22, 23, 10, 11, 19, 12, 13, 17, 18, 14, 16, + 15, + /* Q7[0] VLC symbols - 63 entries */ + 0, 1, 2, 5, 6, 7, 8, 9, 53, 54, 55, 56, 57, 60, 61, + 62, 3, 4, 10, 11, 12, 13, 49, 50, 51, 52, 58, 59, 14, 15, + 16, 17, 18, 43, 45, 46, 47, 48, 19, 20, 21, 22, 23, 39, 40, + 41, 42, 44, 24, 25, 26, 36, 37, 38, 27, 28, 34, 35, 29, 33, + 30, 32, 31, + /* Q8[0] VLC symbols - 127 entries */ + 11, 12, 111, 113, 114, 115, 0, 1, 13, 14, 15, 16, 17, 18, 19, + 21, 104, 105, 107, 108, 109, 110, 112, 2, 3, 4, 5, 6, 8, 10, + 20, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 92, + 93, 95, 96, 97, 98, 99, 100, 101, 102, 103, 106, 116, 117, 120, 121, + 122, 123, 124, 125, 126, 7, 9, 30, 36, 37, 38, 39, 40, 41, 42, + 43, 45, 83, 84, 85, 86, 87, 88, 89, 90, 91, 94, 118, 119, 44, + 46, 47, 48, 49, 50, 51, 75, 76, 77, 78, 79, 80, 81, 82, 52, + 53, 54, 55, 71, 72, 73, 74, 56, 57, 58, 59, 67, 68, 69, 70, + 60, 65, 66, 61, 62, 64, 63, + /* Q2[1] VLC symbols - 125 entries */ + 4, 24, 100, 120, 0, 20, 104, 124, 1, 3, 5, 9, 10, 15, 19, + 21, 23, 25, 29, 45, 49, 75, 79, 95, 99, 101, 102, 103, 105, 109, + 114, 115, 119, 121, 123, 2, 14, 22, 50, 54, 70, 74, 110, 122, 6, + 7, 8, 11, 13, 16, 17, 18, 26, 27, 28, 30, 34, 35, 39, 40, + 44, 46, 47, 48, 51, 53, 55, 59, 65, 69, 71, 73, 76, 77, 78, + 80, 84, 85, 89, 90, 94, 96, 97, 98, 106, 107, 108, 111, 113, 116, + 117, 118, 12, 52, 60, 64, 72, 112, 31, 33, 36, 41, 43, 81, 83, + 88, 91, 93, 32, 37, 38, 42, 56, 57, 58, 61, 63, 66, 67, 68, + 82, 86, 87, 92, 62, + /* Q4 VLC symbols - 81 entries */ + 12, 4, 140, 132, 13, 3, 28, 20, 124, 116, 141, 131, 14, 1, 2, + 29, 19, 44, 36, 60, 52, 92, 84, 108, 100, 125, 115, 142, 143, 129, + 130, 15, 0, 30, 18, 45, 35, 76, 68, 109, 99, 126, 127, 114, 128, + 31, 16, 17, 46, 47, 33, 34, 61, 62, 50, 51, 77, 67, 93, 94, + 82, 83, 110, 111, 97, 98, 112, 113, 32, 63, 48, 49, 78, 79, 65, + 66, 95, 80, 81, 96, 64, + /* Q5[1] VLC symbols - 15 entries */ + 0, 1, 13, 14, 2, 12, 3, 4, 10, 11, 5, 6, 7, 8, 9, + /* Q6[1] VLC symbols - 31 entries */ + 0, 1, 29, 30, 2, 3, 4, 26, 27, 28, 5, 6, 24, 25, 7, + 8, 9, 21, 22, 23, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, + /* Q7[1] VLC symbols - 63 entries */ + 0, 1, 61, 62, 2, 3, 4, 5, 6, 7, 8, 54, 55, 56, 57, + 58, 59, 60, 9, 10, 11, 12, 13, 49, 50, 51, 52, 53, 14, 15, + 16, 17, 18, 19, 20, 21, 42, 43, 44, 45, 46, 47, 48, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, + /* Q8[1] VLC symbols - 127 entries */ + 0, 1, 2, 3, 123, 124, 125, 126, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 75, + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 76, }; #endif /* AVCODEC_MPC8HUFF_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mpc.c ffmpeg-4.4/libavcodec/mpc.c --- ffmpeg-4.2.2/libavcodec/mpc.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpc.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,11 +34,6 @@ #include "mpc.h" #include "mpcdata.h" -av_cold void ff_mpc_init(void) -{ - ff_mpa_synth_init_fixed(ff_mpa_synth_window_fixed); -} - /** * Process decoded Musepack data and produce PCM */ @@ -75,17 +70,17 @@ j = 0; mul = (mpc_CC+1)[bands[i].res[ch]] * mpc_SCF[bands[i].scf_idx[ch][0] & 0xFF]; for(; j < 12; j++) - c->sb_samples[ch][j][i] = mul * c->Q[ch][j + off]; + c->sb_samples[ch][j][i] = av_clipf(mul * c->Q[ch][j + off], INT32_MIN, INT32_MAX); mul = (mpc_CC+1)[bands[i].res[ch]] * mpc_SCF[bands[i].scf_idx[ch][1] & 0xFF]; for(; j < 24; j++) - c->sb_samples[ch][j][i] = mul * c->Q[ch][j + off]; + c->sb_samples[ch][j][i] = av_clipf(mul * c->Q[ch][j + off], INT32_MIN, INT32_MAX); mul = (mpc_CC+1)[bands[i].res[ch]] * mpc_SCF[bands[i].scf_idx[ch][2] & 0xFF]; for(; j < 36; j++) - c->sb_samples[ch][j][i] = mul * c->Q[ch][j + off]; + c->sb_samples[ch][j][i] = av_clipf(mul * c->Q[ch][j + off], INT32_MIN, INT32_MAX); } } if(bands[i].msf){ - int t1, t2; + unsigned t1, t2; for(j = 0; j < SAMPLES_PER_BAND; j++){ t1 = c->sb_samples[0][j][i]; t2 = c->sb_samples[1][j][i]; diff -Nru ffmpeg-4.2.2/libavcodec/mpc.h ffmpeg-4.4/libavcodec/mpc.h --- ffmpeg-4.2.2/libavcodec/mpc.h 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpc.h 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,7 @@ #define AVCODEC_MPC_H #include "libavutil/lfg.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "bswapdsp.h" @@ -70,7 +71,6 @@ DECLARE_ALIGNED(16, int32_t, sb_samples)[MPA_MAX_CHANNELS][36][SBLIMIT]; } MPCContext; -void ff_mpc_init(void); void ff_mpc_dequantize_and_synth(MPCContext *c, int maxband, int16_t **out, int channels); #endif /* AVCODEC_MPC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mpeg12.c ffmpeg-4.4/libavcodec/mpeg12.c --- ffmpeg-4.2.2/libavcodec/mpeg12.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg12.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/timecode.h" +#include "libavutil/thread.h" #include "internal.h" #include "avcodec.h" @@ -41,8 +42,6 @@ #include "bytestream.h" #include "thread.h" -uint8_t ff_mpeg12_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3]; - static const uint8_t table_mb_ptype[7][2] = { { 3, 5 }, // 0x01 MB_INTRA { 1, 2 }, // 0x02 MB_PAT @@ -134,41 +133,39 @@ VLC ff_mb_btype_vlc; VLC ff_mb_pat_vlc; -av_cold void ff_mpeg12_init_vlcs(void) +static av_cold void mpeg12_init_vlcs(void) { - static int done = 0; + INIT_VLC_STATIC(&ff_dc_lum_vlc, DC_VLC_BITS, 12, + ff_mpeg12_vlc_dc_lum_bits, 1, 1, + ff_mpeg12_vlc_dc_lum_code, 2, 2, 512); + INIT_VLC_STATIC(&ff_dc_chroma_vlc, DC_VLC_BITS, 12, + ff_mpeg12_vlc_dc_chroma_bits, 1, 1, + ff_mpeg12_vlc_dc_chroma_code, 2, 2, 514); + INIT_VLC_STATIC(&ff_mv_vlc, MV_VLC_BITS, 17, + &ff_mpeg12_mbMotionVectorTable[0][1], 2, 1, + &ff_mpeg12_mbMotionVectorTable[0][0], 2, 1, 266); + INIT_VLC_STATIC(&ff_mbincr_vlc, MBINCR_VLC_BITS, 36, + &ff_mpeg12_mbAddrIncrTable[0][1], 2, 1, + &ff_mpeg12_mbAddrIncrTable[0][0], 2, 1, 538); + INIT_VLC_STATIC(&ff_mb_pat_vlc, MB_PAT_VLC_BITS, 64, + &ff_mpeg12_mbPatTable[0][1], 2, 1, + &ff_mpeg12_mbPatTable[0][0], 2, 1, 512); + + INIT_VLC_STATIC(&ff_mb_ptype_vlc, MB_PTYPE_VLC_BITS, 7, + &table_mb_ptype[0][1], 2, 1, + &table_mb_ptype[0][0], 2, 1, 64); + INIT_VLC_STATIC(&ff_mb_btype_vlc, MB_BTYPE_VLC_BITS, 11, + &table_mb_btype[0][1], 2, 1, + &table_mb_btype[0][0], 2, 1, 64); - if (!done) { - done = 1; - - INIT_VLC_STATIC(&ff_dc_lum_vlc, DC_VLC_BITS, 12, - ff_mpeg12_vlc_dc_lum_bits, 1, 1, - ff_mpeg12_vlc_dc_lum_code, 2, 2, 512); - INIT_VLC_STATIC(&ff_dc_chroma_vlc, DC_VLC_BITS, 12, - ff_mpeg12_vlc_dc_chroma_bits, 1, 1, - ff_mpeg12_vlc_dc_chroma_code, 2, 2, 514); - INIT_VLC_STATIC(&ff_mv_vlc, MV_VLC_BITS, 17, - &ff_mpeg12_mbMotionVectorTable[0][1], 2, 1, - &ff_mpeg12_mbMotionVectorTable[0][0], 2, 1, 518); - INIT_VLC_STATIC(&ff_mbincr_vlc, MBINCR_VLC_BITS, 36, - &ff_mpeg12_mbAddrIncrTable[0][1], 2, 1, - &ff_mpeg12_mbAddrIncrTable[0][0], 2, 1, 538); - INIT_VLC_STATIC(&ff_mb_pat_vlc, MB_PAT_VLC_BITS, 64, - &ff_mpeg12_mbPatTable[0][1], 2, 1, - &ff_mpeg12_mbPatTable[0][0], 2, 1, 512); - - INIT_VLC_STATIC(&ff_mb_ptype_vlc, MB_PTYPE_VLC_BITS, 7, - &table_mb_ptype[0][1], 2, 1, - &table_mb_ptype[0][0], 2, 1, 64); - INIT_VLC_STATIC(&ff_mb_btype_vlc, MB_BTYPE_VLC_BITS, 11, - &table_mb_btype[0][1], 2, 1, - &table_mb_btype[0][0], 2, 1, 64); - ff_rl_init(&ff_rl_mpeg1, ff_mpeg12_static_rl_table_store[0]); - ff_rl_init(&ff_rl_mpeg2, ff_mpeg12_static_rl_table_store[1]); + INIT_2D_VLC_RL(ff_rl_mpeg1, 680, 0); + INIT_2D_VLC_RL(ff_rl_mpeg2, 674, 0); +} - INIT_2D_VLC_RL(ff_rl_mpeg1, 680, 0); - INIT_2D_VLC_RL(ff_rl_mpeg2, 674, 0); - } +av_cold void ff_mpeg12_init_vlcs(void) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, mpeg12_init_vlcs); } /** diff -Nru ffmpeg-4.2.2/libavcodec/mpeg12dec.c ffmpeg-4.4/libavcodec/mpeg12dec.c --- ffmpeg-4.2.2/libavcodec/mpeg12dec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg12dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -31,12 +31,14 @@ #include "libavutil/attributes.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/stereo3d.h" +#include "libavutil/video_enc_params.h" #include "avcodec.h" #include "bytestream.h" #include "error_resilience.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "idctdsp.h" #include "internal.h" #include "mpeg_er.h" @@ -50,6 +52,8 @@ #include "version.h" #include "xvmc_internal.h" +#define A53_MAX_CC_COUNT 2000 + typedef struct Mpeg1Context { MpegEncContext mpeg_enc_ctx; int mpeg_enc_ctx_allocated; /* true if decoding context allocated */ @@ -57,13 +61,13 @@ AVPanScan pan_scan; /* some temporary storage for the panscan */ AVStereo3D stereo3d; int has_stereo3d; - uint8_t *a53_caption; - int a53_caption_size; + AVBufferRef *a53_buf_ref; uint8_t afd; int has_afd; int slice_count; AVRational save_aspect; int save_width, save_height, save_progressive_seq; + 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 tmpgexs; @@ -220,7 +224,6 @@ } /** - * Note: this function can read out of range and crash for corrupt streams. * Changing this would eat up any speed benefits it has. * Do not use "fast" flag if you need the code to be robust. */ @@ -396,7 +399,6 @@ } /** - * Note: this function can read out of range and crash for corrupt streams. * Changing this would eat up any speed benefits it has. * Do not use "fast" flag if you need the code to be robust. */ @@ -492,8 +494,6 @@ component = (n & 1) + 1; } diff = decode_dc(&s->gb, component); - if (diff >= 0xffff) - return AVERROR_INVALIDDATA; dc = s->last_dc[component]; dc += diff; s->last_dc[component] = dc; @@ -528,10 +528,9 @@ } else { /* escape */ run = SHOW_UBITS(re, &s->gb, 6) + 1; - LAST_SKIP_BITS(re, &s->gb, 6); - UPDATE_CACHE(re, &s->gb); + SKIP_BITS(re, &s->gb, 6); level = SHOW_SBITS(re, &s->gb, 12); - SKIP_BITS(re, &s->gb, 12); + LAST_SKIP_BITS(re, &s->gb, 12); i += run; if (i > MAX_INDEX) break; @@ -558,7 +557,6 @@ } /** - * Note: this function can read out of range and crash for corrupt streams. * Changing this would eat up any speed benefits it has. * Do not use "fast" flag if you need the code to be robust. */ @@ -581,12 +579,10 @@ component = (n & 1) + 1; } diff = decode_dc(&s->gb, component); - if (diff >= 0xffff) - return AVERROR_INVALIDDATA; dc = s->last_dc[component]; dc += diff; s->last_dc[component] = dc; - block[0] = dc << (3 - s->intra_dc_precision); + block[0] = dc * (1 << (3 - s->intra_dc_precision)); i = 0; if (s->intra_vlc_format) rl = &ff_rl_mpeg2; @@ -613,10 +609,9 @@ } else { /* escape */ run = SHOW_UBITS(re, &s->gb, 6) + 1; - LAST_SKIP_BITS(re, &s->gb, 6); - UPDATE_CACHE(re, &s->gb); + SKIP_BITS(re, &s->gb, 6); level = SHOW_SBITS(re, &s->gb, 12); - SKIP_BITS(re, &s->gb, 12); + LAST_SKIP_BITS(re, &s->gb, 12); i += run; j = scantable[i]; if (level < 0) { @@ -1057,15 +1052,11 @@ Mpeg1Context *s = avctx->priv_data; MpegEncContext *s2 = &s->mpeg_enc_ctx; - ff_mpv_decode_defaults(s2); - if ( avctx->codec_tag != AV_RL32("VCR2") && avctx->codec_tag != AV_RL32("BW10")) avctx->coded_width = avctx->coded_height = 0; // do not trust dimensions from input ff_mpv_decode_init(s2, avctx); - s->mpeg_enc_ctx.avctx = avctx; - /* we need some permutation to store matrices, * until the decoder sets the real permutation. */ ff_mpv_idct_init(s2); @@ -1398,6 +1389,7 @@ MpegEncContext *s = &s1->mpeg_enc_ctx; int horiz_size_ext, vert_size_ext; int bit_rate_ext; + AVCPBProperties *cpb_props; skip_bits(&s->gb, 1); /* profile and level esc*/ s->avctx->profile = get_bits(&s->gb, 3); @@ -1417,7 +1409,7 @@ bit_rate_ext = get_bits(&s->gb, 12); /* XXX: handle it */ s->bit_rate += (bit_rate_ext << 18) * 400LL; check_marker(s->avctx, &s->gb, "after bit rate extension"); - s->avctx->rc_buffer_size += get_bits(&s->gb, 8) * 1024 * 16 << 10; + s1->rc_buffer_size += get_bits(&s->gb, 8) * 1024 * 16 << 10; s->low_delay = get_bits1(&s->gb); if (s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY) @@ -1429,11 +1421,17 @@ ff_dlog(s->avctx, "sequence extension\n"); s->codec_id = s->avctx->codec_id = AV_CODEC_ID_MPEG2VIDEO; + if (cpb_props = ff_add_cpb_side_data(s->avctx)) { + cpb_props->buffer_size = s1->rc_buffer_size; + if (s->bit_rate != 0x3FFFF*400) + cpb_props->max_bitrate = s->bit_rate; + } + if (s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_DEBUG, "profile: %d, level: %d ps: %d cf:%d vbv buffer: %d, bitrate:%"PRId64"\n", s->avctx->profile, s->avctx->level, s->progressive_sequence, s->chroma_format, - s->avctx->rc_buffer_size, s->bit_rate); + s1->rc_buffer_size, s->bit_rate); } static void mpeg_decode_sequence_display_extension(Mpeg1Context *s1) @@ -1596,6 +1594,11 @@ Mpeg1Context *s1 = (Mpeg1Context *) s; int ret; + if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) { + if (s->mb_width * s->mb_height * 11LL / (33 * 2 * 8) > buf_size) + return AVERROR_INVALIDDATA; + } + /* start frame decoding */ if (s->first_field || s->picture_structure == PICT_FRAME) { AVFrameSideData *pan_scan; @@ -1625,13 +1628,13 @@ return AVERROR(ENOMEM); memcpy(pan_scan->data, &s1->pan_scan, sizeof(s1->pan_scan)); - if (s1->a53_caption) { - AVFrameSideData *sd = av_frame_new_side_data( + if (s1->a53_buf_ref) { + AVFrameSideData *sd = av_frame_new_side_data_from_buf( s->current_picture_ptr->f, AV_FRAME_DATA_A53_CC, - s1->a53_caption_size); - if (sd) - memcpy(sd->data, s1->a53_caption, s1->a53_caption_size); - av_freep(&s1->a53_caption); + s1->a53_buf_ref); + if (!sd) + av_buffer_unref(&s1->a53_buf_ref); + s1->a53_buf_ref = NULL; } if (s1->has_stereo3d) { @@ -1664,8 +1667,7 @@ return AVERROR_INVALIDDATA; } - if (s->avctx->hwaccel && - (s->avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD)) { + if (s->avctx->hwaccel) { if ((ret = s->avctx->hwaccel->end_frame(s->avctx)) < 0) { av_log(avctx, AV_LOG_ERROR, "hardware accelerator failed to decode first field\n"); @@ -2011,13 +2013,15 @@ start_code = -1; buf = avpriv_find_start_code(buf, s->gb.buffer_end, &start_code); + if (start_code < SLICE_MIN_START_CODE || start_code > SLICE_MAX_START_CODE) + return AVERROR_INVALIDDATA; mb_y = start_code - SLICE_MIN_START_CODE; if (s->codec_id != AV_CODEC_ID_MPEG1VIDEO && s->mb_height > 2800/16) mb_y += (*buf&0xE0)<<2; mb_y <<= field_pic; if (s->picture_structure == PICT_BOTTOM_FIELD) mb_y++; - if (mb_y < 0 || mb_y >= s->end_mb_y) + if (mb_y >= s->end_mb_y) return AVERROR_INVALIDDATA; } } @@ -2112,7 +2116,7 @@ return AVERROR_INVALIDDATA; } - s->avctx->rc_buffer_size = get_bits(&s->gb, 10) * 1024 * 16; + s1->rc_buffer_size = get_bits(&s->gb, 10) * 1024 * 16; skip_bits(&s->gb, 1); /* get matrix */ @@ -2161,7 +2165,7 @@ if (s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_DEBUG, "vbv buffer: %d, bitrate:%"PRId64", aspect_ratio_info: %d \n", - s->avctx->rc_buffer_size, s->bit_rate, s->aspect_ratio_info); + s1->rc_buffer_size, s->bit_rate, s->aspect_ratio_info); return 0; } @@ -2231,14 +2235,18 @@ /* extract A53 Part 4 CC data */ int cc_count = p[5] & 0x1f; if (cc_count > 0 && buf_size >= 7 + cc_count * 3) { - av_freep(&s1->a53_caption); - s1->a53_caption_size = cc_count * 3; - s1->a53_caption = av_malloc(s1->a53_caption_size); - if (!s1->a53_caption) { - s1->a53_caption_size = 0; - } else { - memcpy(s1->a53_caption, p + 7, s1->a53_caption_size); - } + int old_size = s1->a53_buf_ref ? s1->a53_buf_ref->size : 0; + const uint64_t new_size = (old_size + cc_count + * UINT64_C(3)); + int ret; + + if (new_size > 3*A53_MAX_CC_COUNT) + return AVERROR(EINVAL); + + ret = av_buffer_realloc(&s1->a53_buf_ref, new_size); + if (ret >= 0) + memcpy(s1->a53_buf_ref->data + old_size, p + 7, cc_count * UINT64_C(3)); + avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; } return 1; @@ -2247,19 +2255,23 @@ /* extract SCTE-20 CC data */ GetBitContext gb; int cc_count = 0; - int i; + int i, ret; init_get_bits(&gb, p + 2, buf_size - 2); cc_count = get_bits(&gb, 5); if (cc_count > 0) { - av_freep(&s1->a53_caption); - s1->a53_caption_size = cc_count * 3; - s1->a53_caption = av_mallocz(s1->a53_caption_size); - if (!s1->a53_caption) { - s1->a53_caption_size = 0; - } else { + int old_size = s1->a53_buf_ref ? s1->a53_buf_ref->size : 0; + const uint64_t new_size = (old_size + cc_count + * UINT64_C(3)); + if (new_size > 3*A53_MAX_CC_COUNT) + return AVERROR(EINVAL); + + ret = av_buffer_realloc(&s1->a53_buf_ref, new_size); + if (ret >= 0) { uint8_t field, cc1, cc2; - uint8_t *cap = s1->a53_caption; + uint8_t *cap = s1->a53_buf_ref->data; + + memset(s1->a53_buf_ref->data + old_size, 0, cc_count * 3); for (i = 0; i < cc_count && get_bits_left(&gb) >= 26; i++) { skip_bits(&gb, 2); // priority field = get_bits(&gb, 2); @@ -2311,21 +2323,23 @@ * on the even field. There also exist DVDs in the wild that encode an odd field count and the * caption_extra_field_added/caption_odd_field_first bits change per packet to allow that. */ int cc_count = 0; - int i; + int i, ret; // There is a caption count field in the data, but it is often // incorrect. So count the number of captions present. for (i = 5; i + 6 <= buf_size && ((p[i] & 0xfe) == 0xfe); i += 6) cc_count++; // Transform the DVD format into A53 Part 4 format if (cc_count > 0) { - av_freep(&s1->a53_caption); - s1->a53_caption_size = cc_count * 6; - s1->a53_caption = av_malloc(s1->a53_caption_size); - if (!s1->a53_caption) { - s1->a53_caption_size = 0; - } else { + int old_size = s1->a53_buf_ref ? s1->a53_buf_ref->size : 0; + const uint64_t new_size = (old_size + cc_count + * UINT64_C(6)); + if (new_size > 3*A53_MAX_CC_COUNT) + return AVERROR(EINVAL); + + ret = av_buffer_realloc(&s1->a53_buf_ref, new_size); + if (ret >= 0) { uint8_t field1 = !!(p[4] & 0x80); - uint8_t *cap = s1->a53_caption; + uint8_t *cap = s1->a53_buf_ref->data; p += 5; for (i = 0; i < cc_count; i++) { cap[0] = (p[0] == 0xff && field1) ? 0xfc : 0xfd; @@ -2483,7 +2497,7 @@ return ret; else if (ret) { // FIXME: merge with the stuff in mpeg_decode_slice - if (s2->last_picture_ptr || s2->low_delay) + if (s2->last_picture_ptr || s2->low_delay || s2->pict_type == AV_PICTURE_TYPE_B) *got_output = 1; } } @@ -2835,6 +2849,7 @@ s2->current_picture_ptr = NULL; if (s2->timecode_frame_start != -1 && *got_output) { + char tcbuf[AV_TIMECODE_STR_SIZE]; AVFrameSideData *tcside = av_frame_new_side_data(picture, AV_FRAME_DATA_GOP_TIMECODE, sizeof(int64_t)); @@ -2842,6 +2857,9 @@ return AVERROR(ENOMEM); memcpy(tcside->data, &s2->timecode_frame_start, sizeof(int64_t)); + av_timecode_make_mpeg_tc_string(tcbuf, s2->timecode_frame_start); + av_dict_set(&picture->metadata, "timecode", tcbuf, 0); + s2->timecode_frame_start = -1; } } @@ -2864,7 +2882,7 @@ if (s->mpeg_enc_ctx_allocated) ff_mpv_common_end(&s->mpeg_enc_ctx); - av_freep(&s->a53_caption); + av_buffer_unref(&s->a53_buf_ref); return 0; } @@ -2880,11 +2898,12 @@ .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = flush, .max_lowres = 3, .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg_decode_update_thread_context), - .hw_configs = (const AVCodecHWConfigInternal*[]) { + .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_MPEG1_NVDEC_HWACCEL HWACCEL_NVDEC(mpeg1), #endif @@ -2913,11 +2932,12 @@ .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = flush, .max_lowres = 3, .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg2_video_profiles), - .hw_configs = (const AVCodecHWConfigInternal*[]) { + .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_MPEG2_DXVA2_HWACCEL HWACCEL_DXVA2(mpeg2), #endif @@ -2957,7 +2977,167 @@ .close = mpeg_decode_end, .decode = mpeg_decode_frame, .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = flush, .max_lowres = 3, }; + +typedef struct IPUContext { + MpegEncContext m; + + int flags; + DECLARE_ALIGNED(32, int16_t, block)[6][64]; +} IPUContext; + +static int ipu_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + IPUContext *s = avctx->priv_data; + MpegEncContext *m = &s->m; + GetBitContext *gb = &m->gb; + AVFrame * const frame = data; + int ret; + + ret = ff_get_buffer(avctx, frame, 0); + if (ret < 0) + return ret; + + ret = init_get_bits8(gb, avpkt->data, avpkt->size); + if (ret < 0) + return ret; + + s->flags = get_bits(gb, 8); + m->intra_dc_precision = s->flags & 3; + m->q_scale_type = !!(s->flags & 0x40); + m->intra_vlc_format = !!(s->flags & 0x20); + m->alternate_scan = !!(s->flags & 0x10); + + if (s->flags & 0x10) { + ff_init_scantable(m->idsp.idct_permutation, &m->inter_scantable, ff_alternate_vertical_scan); + ff_init_scantable(m->idsp.idct_permutation, &m->intra_scantable, ff_alternate_vertical_scan); + } else { + ff_init_scantable(m->idsp.idct_permutation, &m->inter_scantable, ff_zigzag_direct); + ff_init_scantable(m->idsp.idct_permutation, &m->intra_scantable, ff_zigzag_direct); + } + + m->last_dc[0] = m->last_dc[1] = m->last_dc[2] = 1 << (7 + (s->flags & 3)); + m->qscale = 1; + + for (int y = 0; y < avctx->height; y += 16) { + int intraquant; + + for (int x = 0; x < avctx->width; x += 16) { + if (x || y) { + if (!get_bits1(gb)) + return AVERROR_INVALIDDATA; + } + if (get_bits1(gb)) { + intraquant = 0; + } else { + if (!get_bits1(gb)) + return AVERROR_INVALIDDATA; + intraquant = 1; + } + + if (s->flags & 4) + skip_bits1(gb); + + if (intraquant) + m->qscale = mpeg_get_qscale(m); + + memset(s->block, 0, sizeof(s->block)); + + for (int n = 0; n < 6; n++) { + if (s->flags & 0x80) { + ret = ff_mpeg1_decode_block_intra(&m->gb, + m->intra_matrix, + m->intra_scantable.permutated, + m->last_dc, s->block[n], + n, m->qscale); + if (ret >= 0) + m->block_last_index[n] = ret; + } else { + ret = mpeg2_decode_block_intra(m, s->block[n], n); + } + + if (ret < 0) + return ret; + } + + m->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x, + frame->linesize[0], s->block[0]); + m->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x + 8, + frame->linesize[0], s->block[1]); + m->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x, + frame->linesize[0], s->block[2]); + m->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x + 8, + frame->linesize[0], s->block[3]); + m->idsp.idct_put(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1), + frame->linesize[1], s->block[4]); + m->idsp.idct_put(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1), + frame->linesize[2], s->block[5]); + } + } + + align_get_bits(gb); + if (get_bits_left(gb) != 32) + return AVERROR_INVALIDDATA; + + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int ipu_decode_init(AVCodecContext *avctx) +{ + IPUContext *s = avctx->priv_data; + MpegEncContext *m = &s->m; + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + ff_mpv_decode_init(m, avctx); + ff_mpv_idct_init(m); + ff_mpeg12_common_init(m); + ff_mpeg12_init_vlcs(); + + for (int i = 0; i < 64; i++) { + int j = m->idsp.idct_permutation[i]; + int v = ff_mpeg1_default_intra_matrix[i]; + m->intra_matrix[j] = v; + m->chroma_intra_matrix[j] = v; + } + + for (int i = 0; i < 64; i++) { + int j = m->idsp.idct_permutation[i]; + int v = ff_mpeg1_default_non_intra_matrix[i]; + m->inter_matrix[j] = v; + m->chroma_inter_matrix[j] = v; + } + + return 0; +} + +static av_cold int ipu_decode_end(AVCodecContext *avctx) +{ + IPUContext *s = avctx->priv_data; + + ff_mpv_common_end(&s->m); + + return 0; +} + +AVCodec ff_ipu_decoder = { + .name = "ipu", + .long_name = NULL_IF_CONFIG_SMALL("IPU Video"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_IPU, + .priv_data_size = sizeof(IPUContext), + .init = ipu_decode_init, + .decode = ipu_decode_frame, + .close = ipu_decode_end, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, +}; diff -Nru ffmpeg-4.2.2/libavcodec/mpeg12enc.c ffmpeg-4.4/libavcodec/mpeg12enc.c --- ffmpeg-4.2.2/libavcodec/mpeg12enc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg12enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,10 +27,12 @@ #include +#include "config.h" #include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/log.h" #include "libavutil/opt.h" +#include "libavutil/thread.h" #include "libavutil/timecode.h" #include "libavutil/stereo3d.h" @@ -41,7 +43,9 @@ #include "mpeg12data.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "profiles.h" +#if CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER static const uint8_t svcd_scan_offset_placeholder[] = { 0x10, 0x0E, 0x00, 0x80, 0x81, 0x00, 0x80, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -58,12 +62,10 @@ static uint32_t mpeg1_lum_dc_uni[512]; static uint32_t mpeg1_chr_dc_uni[512]; -static uint8_t mpeg1_index_run[2][64]; -static int8_t mpeg1_max_level[2][64]; - #define A53_MAX_CC_COUNT 0x1f +#endif /* CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER */ -static av_cold void init_uni_ac_vlc(RLTable *rl, uint8_t *uni_ac_vlc_len) +av_cold void ff_mpeg1_init_uni_ac_vlc(const RLTable *rl, uint8_t *uni_ac_vlc_len) { int i; @@ -98,6 +100,7 @@ } } +#if CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER static int find_frame_rate_index(MpegEncContext *s) { int i; @@ -139,16 +142,17 @@ static av_cold int encode_init(AVCodecContext *avctx) { + int ret; MpegEncContext *s = avctx->priv_data; - if (ff_mpv_encode_init(avctx) < 0) - return -1; + if ((ret = ff_mpv_encode_init(avctx)) < 0) + return ret; if (find_frame_rate_index(s) < 0) { if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { av_log(avctx, AV_LOG_ERROR, "MPEG-1/2 does not support %d/%d fps\n", avctx->time_base.den, avctx->time_base.num); - return -1; + return AVERROR(EINVAL); } else { av_log(avctx, AV_LOG_INFO, "MPEG-1/2 does not support %d/%d fps, there may be AV sync issues\n", @@ -159,23 +163,23 @@ if (avctx->profile == FF_PROFILE_UNKNOWN) { if (avctx->level != FF_LEVEL_UNKNOWN) { av_log(avctx, AV_LOG_ERROR, "Set profile and level\n"); - return -1; + return AVERROR(EINVAL); } /* Main or 4:2:2 */ - avctx->profile = s->chroma_format == CHROMA_420 ? 4 : 0; + avctx->profile = s->chroma_format == CHROMA_420 ? FF_PROFILE_MPEG2_MAIN : FF_PROFILE_MPEG2_422; } if (avctx->level == FF_LEVEL_UNKNOWN) { - if (avctx->profile == 0) { /* 4:2:2 */ + if (avctx->profile == FF_PROFILE_MPEG2_422) { /* 4:2:2 */ if (avctx->width <= 720 && avctx->height <= 608) avctx->level = 5; /* Main */ else avctx->level = 2; /* High */ } else { - if (avctx->profile != 1 && s->chroma_format != CHROMA_420) { + if (avctx->profile != FF_PROFILE_MPEG2_HIGH && s->chroma_format != CHROMA_420) { av_log(avctx, AV_LOG_ERROR, "Only High(1) and 4:2:2(0) profiles support 4:2:2 color sampling\n"); - return -1; + return AVERROR(EINVAL); } if (avctx->width <= 720 && avctx->height <= 576) avctx->level = 8; /* Main */ @@ -205,7 +209,7 @@ if (s->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 -1; + return AVERROR(EINVAL); } #if FF_API_PRIVATE_OPT @@ -231,7 +235,7 @@ static void put_header(MpegEncContext *s, int header) { - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); put_bits(&s->pb, 16, header >> 16); put_sbits(&s->pb, 16, header); } @@ -321,7 +325,7 @@ put_header(s, EXT_START_CODE); put_bits(&s->pb, 4, 1); // seq ext - put_bits(&s->pb, 1, s->avctx->profile == 0); // escx 1 for 4:2:2 profile + put_bits(&s->pb, 1, s->avctx->profile == FF_PROFILE_MPEG2_422); // escx 1 for 4:2:2 profile put_bits(&s->pb, 3, s->avctx->profile); // profile put_bits(&s->pb, 4, s->avctx->level); // level @@ -715,8 +719,8 @@ MASK_ABS(sign, alevel); sign &= 1; - if (alevel <= mpeg1_max_level[0][run]) { - code = mpeg1_index_run[0][run] + alevel - 1; + if (alevel <= ff_rl_mpeg1.max_level[0][run]) { + code = ff_rl_mpeg1.index_run[0][run] + alevel - 1; /* store the VLC & sign at once */ put_bits(&s->pb, table_vlc[code][1] + 1, (table_vlc[code][0] << 1) + sign); @@ -1032,84 +1036,77 @@ mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 8); } -av_cold void ff_mpeg1_encode_init(MpegEncContext *s) +static av_cold void mpeg12_encode_init_static(void) { - static int done = 0; + static uint8_t mpeg12_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3]; - ff_mpeg12_common_init(s); + ff_rl_init(&ff_rl_mpeg1, mpeg12_static_rl_table_store[0]); + ff_rl_init(&ff_rl_mpeg2, mpeg12_static_rl_table_store[1]); - if (!done) { - int f_code; - int mv; - int i; + ff_mpeg1_init_uni_ac_vlc(&ff_rl_mpeg1, uni_mpeg1_ac_vlc_len); + ff_mpeg1_init_uni_ac_vlc(&ff_rl_mpeg2, uni_mpeg2_ac_vlc_len); - done = 1; - ff_rl_init(&ff_rl_mpeg1, ff_mpeg12_static_rl_table_store[0]); - ff_rl_init(&ff_rl_mpeg2, ff_mpeg12_static_rl_table_store[1]); + /* build unified dc encoding tables */ + for (int i = -255; i < 256; i++) { + int adiff, index; + int bits, code; + int diff = i; - for (i = 0; i < 64; i++) { - mpeg1_max_level[0][i] = ff_rl_mpeg1.max_level[0][i]; - mpeg1_index_run[0][i] = ff_rl_mpeg1.index_run[0][i]; - } + adiff = FFABS(diff); + if (diff < 0) + diff--; + index = av_log2(2 * adiff); - init_uni_ac_vlc(&ff_rl_mpeg1, uni_mpeg1_ac_vlc_len); - if (s->intra_vlc_format) - init_uni_ac_vlc(&ff_rl_mpeg2, uni_mpeg2_ac_vlc_len); + bits = ff_mpeg12_vlc_dc_lum_bits[index] + index; + code = (ff_mpeg12_vlc_dc_lum_code[index] << index) + + av_mod_uintp2(diff, index); + mpeg1_lum_dc_uni[i + 255] = bits + (code << 8); - /* build unified dc encoding tables */ - for (i = -255; i < 256; i++) { - int adiff, index; - int bits, code; - int diff = i; - - adiff = FFABS(diff); - if (diff < 0) - diff--; - index = av_log2(2 * adiff); - - bits = ff_mpeg12_vlc_dc_lum_bits[index] + index; - code = (ff_mpeg12_vlc_dc_lum_code[index] << index) + - av_mod_uintp2(diff, index); - mpeg1_lum_dc_uni[i + 255] = bits + (code << 8); - - bits = ff_mpeg12_vlc_dc_chroma_bits[index] + index; - code = (ff_mpeg12_vlc_dc_chroma_code[index] << index) + - av_mod_uintp2(diff, index); - mpeg1_chr_dc_uni[i + 255] = bits + (code << 8); - } - - for (f_code = 1; f_code <= MAX_FCODE; f_code++) - for (mv = -MAX_DMV; mv <= MAX_DMV; mv++) { - int len; + bits = ff_mpeg12_vlc_dc_chroma_bits[index] + index; + code = (ff_mpeg12_vlc_dc_chroma_code[index] << index) + + av_mod_uintp2(diff, index); + mpeg1_chr_dc_uni[i + 255] = bits + (code << 8); + } - if (mv == 0) { - len = ff_mpeg12_mbMotionVectorTable[0][1]; - } else { - int val, bit_size, code; + for (int f_code = 1; f_code <= MAX_FCODE; f_code++) + for (int mv = -MAX_DMV; mv <= MAX_DMV; mv++) { + int len; - bit_size = f_code - 1; + if (mv == 0) { + len = ff_mpeg12_mbMotionVectorTable[0][1]; + } else { + int val, bit_size, code; - val = mv; - if (val < 0) - val = -val; - val--; - code = (val >> bit_size) + 1; - if (code < 17) - len = ff_mpeg12_mbMotionVectorTable[code][1] + - 1 + bit_size; - else - len = ff_mpeg12_mbMotionVectorTable[16][1] + - 2 + bit_size; - } + bit_size = f_code - 1; - mv_penalty[f_code][mv + MAX_DMV] = len; + val = mv; + if (val < 0) + val = -val; + val--; + code = (val >> bit_size) + 1; + if (code < 17) + len = ff_mpeg12_mbMotionVectorTable[code][1] + + 1 + bit_size; + else + len = ff_mpeg12_mbMotionVectorTable[16][1] + + 2 + bit_size; } + mv_penalty[f_code][mv + MAX_DMV] = len; + } + + + for (int f_code = MAX_FCODE; f_code > 0; f_code--) + for (int mv = -(8 << f_code); mv < (8 << f_code); mv++) + fcode_tab[mv + MAX_MV] = f_code; +} + +av_cold void ff_mpeg1_encode_init(MpegEncContext *s) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + + ff_mpeg12_common_init(s); - for (f_code = MAX_FCODE; f_code > 0; f_code--) - for (mv = -(8 << f_code); mv < (8 << f_code); mv++) - fcode_tab[mv + MAX_MV] = f_code; - } s->me.mv_penalty = mv_penalty; s->fcode_tab = fcode_tab; if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO) { @@ -1128,15 +1125,15 @@ } s->inter_ac_vlc_length = s->inter_ac_vlc_last_length = uni_mpeg1_ac_vlc_len; + + ff_thread_once(&init_static_once, mpeg12_encode_init_static); } #define OFFSET(x) offsetof(MpegEncContext, 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.", \ - OFFSET(tc_opt_str), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, VE },\ - { "intra_vlc", "Use MPEG-2 intra VLC table.", \ - OFFSET(intra_vlc_format), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \ + OFFSET(tc_opt_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE },\ { "drop_frame_timecode", "Timecode is in drop frame format.", \ OFFSET(drop_frame_timecode), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \ { "scan_offset", "Reserve space for SVCD scan offset user data.", \ @@ -1152,6 +1149,8 @@ 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 }, { "seq_disp_ext", "Write sequence_display_extension blocks.", OFFSET(seq_disp_ext), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE, "seq_disp_ext" }, @@ -1165,7 +1164,14 @@ { "secam", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_SECAM }, 0, 0, VE, "video_format" }, { "mac", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_MAC }, 0, 0, VE, "video_format" }, { "unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_UNSPECIFIED}, 0, 0, VE, "video_format" }, +#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, { .i64 = value }, 0, 0, VE, "avctx.level" + { LEVEL("high", 4) }, + { LEVEL("high1440", 6) }, + { LEVEL("main", 8) }, + { LEVEL("low", 10) }, +#undef LEVEL FF_MPV_COMMON_OPTS + FF_MPEG2_PROFILE_OPTS { NULL }, }; @@ -1193,6 +1199,7 @@ .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .priv_class = &mpeg1_class, }; @@ -1210,5 +1217,7 @@ AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .priv_class = &mpeg2_class, }; +#endif /* CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER */ diff -Nru ffmpeg-4.2.2/libavcodec/mpeg12.h ffmpeg-4.4/libavcodec/mpeg12.h --- ffmpeg-4.2.2/libavcodec/mpeg12.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg12.h 2021-04-08 21:28:39.000000000 +0000 @@ -25,8 +25,6 @@ #include "mpeg12vlc.h" #include "mpegvideo.h" -extern uint8_t ff_mpeg12_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3]; - void ff_mpeg12_common_init(MpegEncContext *s); #define INIT_2D_VLC_RL(rl, static_size, flags)\ @@ -37,6 +35,7 @@ } void ff_init_2d_vlc_rl(RLTable *rl, unsigned static_size, int flags); +void ff_mpeg1_init_uni_ac_vlc(const RLTable *rl, uint8_t *uni_ac_vlc_len); static inline int decode_dc(GetBitContext *gb, int component) { @@ -47,10 +46,6 @@ } else { code = get_vlc2(gb, ff_dc_chroma_vlc.table, DC_VLC_BITS, 2); } - if (code < 0){ - av_log(NULL, AV_LOG_ERROR, "invalid dc code at\n"); - return 0xffff; - } if (code == 0) { diff = 0; } else { diff -Nru ffmpeg-4.2.2/libavcodec/mpeg12vlc.h ffmpeg-4.4/libavcodec/mpeg12vlc.h --- ffmpeg-4.2.2/libavcodec/mpeg12vlc.h 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg12vlc.h 2021-04-08 21:28:39.000000000 +0000 @@ -31,7 +31,7 @@ #include "vlc.h" #define DC_VLC_BITS 9 -#define MV_VLC_BITS 9 +#define MV_VLC_BITS 8 #define TEX_VLC_BITS 9 #define MBINCR_VLC_BITS 9 diff -Nru ffmpeg-4.2.2/libavcodec/mpeg2_metadata_bsf.c ffmpeg-4.4/libavcodec/mpeg2_metadata_bsf.c --- ffmpeg-4.2.2/libavcodec/mpeg2_metadata_bsf.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg2_metadata_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,14 +22,12 @@ #include "bsf.h" #include "cbs.h" +#include "cbs_bsf.h" #include "cbs_mpeg2.h" #include "mpeg12.h" typedef struct MPEG2MetadataContext { - const AVClass *class; - - CodedBitstreamContext *cbc; - CodedBitstreamFragment fragment; + CBSBSFContext common; MPEG2RawExtensionData sequence_display_extension; @@ -47,6 +45,7 @@ static int mpeg2_metadata_update_fragment(AVBSFContext *bsf, + AVPacket *pkt, CodedBitstreamFragment *frag) { MPEG2MetadataContext *ctx = bsf->priv_data; @@ -136,7 +135,7 @@ se->vertical_size_extension << 12 | sh->vertical_size_value, }; - err = ff_cbs_insert_unit_content(ctx->cbc, frag, se_pos + 1, + err = ff_cbs_insert_unit_content(frag, se_pos + 1, MPEG2_START_EXTENSION, &ctx->sequence_display_extension, NULL); @@ -169,49 +168,16 @@ return 0; } -static int mpeg2_metadata_filter(AVBSFContext *bsf, AVPacket *pkt) -{ - MPEG2MetadataContext *ctx = bsf->priv_data; - CodedBitstreamFragment *frag = &ctx->fragment; - int err; - - err = ff_bsf_get_packet_ref(bsf, pkt); - if (err < 0) - return err; - - err = ff_cbs_read_packet(ctx->cbc, frag, pkt); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); - goto fail; - } - - err = mpeg2_metadata_update_fragment(bsf, frag); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to update frame fragment.\n"); - goto fail; - } - - err = ff_cbs_write_packet(ctx->cbc, pkt, frag); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); - goto fail; - } - - err = 0; -fail: - ff_cbs_fragment_reset(ctx->cbc, frag); - - if (err < 0) - av_packet_unref(pkt); - - return err; -} +static const CBSBSFType mpeg2_metadata_type = { + .codec_id = AV_CODEC_ID_MPEG2VIDEO, + .fragment_name = "frame", + .unit_name = "start code", + .update_fragment = &mpeg2_metadata_update_fragment, +}; static int mpeg2_metadata_init(AVBSFContext *bsf) { MPEG2MetadataContext *ctx = bsf->priv_data; - CodedBitstreamFragment *frag = &ctx->fragment; - int err; #define VALIDITY_CHECK(name) do { \ if (!ctx->name) { \ @@ -225,42 +191,7 @@ VALIDITY_CHECK(matrix_coefficients); #undef VALIDITY_CHECK - err = ff_cbs_init(&ctx->cbc, AV_CODEC_ID_MPEG2VIDEO, bsf); - if (err < 0) - return err; - - if (bsf->par_in->extradata) { - err = ff_cbs_read_extradata(ctx->cbc, frag, bsf->par_in); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to read extradata.\n"); - goto fail; - } - - err = mpeg2_metadata_update_fragment(bsf, frag); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to update metadata fragment.\n"); - goto fail; - } - - err = ff_cbs_write_extradata(ctx->cbc, bsf->par_out, frag); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to write extradata.\n"); - goto fail; - } - } - - err = 0; -fail: - ff_cbs_fragment_reset(ctx->cbc, frag); - return err; -} - -static void mpeg2_metadata_close(AVBSFContext *bsf) -{ - MPEG2MetadataContext *ctx = bsf->priv_data; - - ff_cbs_fragment_free(ctx->cbc, &ctx->fragment); - ff_cbs_close(&ctx->cbc); + return ff_cbs_bsf_generic_init(bsf, &mpeg2_metadata_type); } #define OFFSET(x) offsetof(MPEG2MetadataContext, x) @@ -306,7 +237,7 @@ .priv_data_size = sizeof(MPEG2MetadataContext), .priv_class = &mpeg2_metadata_class, .init = &mpeg2_metadata_init, - .close = &mpeg2_metadata_close, - .filter = &mpeg2_metadata_filter, + .close = &ff_cbs_bsf_generic_close, + .filter = &ff_cbs_bsf_generic_filter, .codec_ids = mpeg2_metadata_codec_ids, }; diff -Nru ffmpeg-4.2.2/libavcodec/mpeg4audio.c ffmpeg-4.4/libavcodec/mpeg4audio.c --- ffmpeg-4.2.2/libavcodec/mpeg4audio.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg4audio.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,7 +30,7 @@ * @param[in] c MPEG4AudioConfig structure to fill * @return on success 0 is returned, otherwise a value < 0 */ -static int parse_config_ALS(GetBitContext *gb, MPEG4AudioConfig *c) +static int parse_config_ALS(GetBitContext *gb, MPEG4AudioConfig *c, void *logctx) { if (get_bits_left(gb) < 112) return AVERROR_INVALIDDATA; @@ -43,7 +43,7 @@ c->sample_rate = get_bits_long(gb, 32); if (c->sample_rate <= 0) { - av_log(NULL, AV_LOG_ERROR, "Invalid sample rate %d\n", c->sample_rate); + av_log(logctx, AV_LOG_ERROR, "Invalid sample rate %d\n", c->sample_rate); return AVERROR_INVALIDDATA; } @@ -64,8 +64,21 @@ 24000, 22050, 16000, 12000, 11025, 8000, 7350 }; -const uint8_t ff_mpeg4audio_channels[8] = { - 0, 1, 2, 3, 4, 5, 6, 8 +const uint8_t ff_mpeg4audio_channels[14] = { + 0, + 1, // mono (1/0) + 2, // stereo (2/0) + 3, // 3/0 + 4, // 3/1 + 5, // 3/2 + 6, // 3/2.1 + 8, // 5/2.1 + 0, + 0, + 0, + 7, // 3/3.1 + 8, // 3/2/2.1 + 24 // 3/3/3 - 5/2/3 - 3/0/0.2 }; static inline int get_object_type(GetBitContext *gb) @@ -84,7 +97,7 @@ } int ff_mpeg4audio_get_config_gb(MPEG4AudioConfig *c, GetBitContext *gb, - int sync_extension) + int sync_extension, void *logctx) { int specific_config_bitindex, ret; int start_bit_index = get_bits_count(gb); @@ -94,7 +107,7 @@ if (c->chan_config < FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) c->channels = ff_mpeg4audio_channels[c->chan_config]; else { - av_log(NULL, AV_LOG_ERROR, "Invalid chan_config %d\n", c->chan_config); + av_log(logctx, AV_LOG_ERROR, "Invalid chan_config %d\n", c->chan_config); return AVERROR_INVALIDDATA; } c->sbr = -1; @@ -118,12 +131,12 @@ if (c->object_type == AOT_ALS) { skip_bits(gb, 5); - if (show_bits_long(gb, 24) != MKBETAG('\0','A','L','S')) - skip_bits_long(gb, 24); + if (show_bits(gb, 24) != MKBETAG('\0','A','L','S')) + skip_bits(gb, 24); specific_config_bitindex = get_bits_count(gb); - ret = parse_config_ALS(gb, c); + ret = parse_config_ALS(gb, c, logctx); if (ret < 0) return ret; } @@ -156,6 +169,7 @@ return specific_config_bitindex - start_bit_index; } +#if LIBAVCODEC_VERSION_MAJOR < 59 int avpriv_mpeg4audio_get_config(MPEG4AudioConfig *c, const uint8_t *buf, int bit_size, int sync_extension) { @@ -169,5 +183,22 @@ if (ret < 0) return ret; - return ff_mpeg4audio_get_config_gb(c, &gb, sync_extension); + return ff_mpeg4audio_get_config_gb(c, &gb, sync_extension, NULL); +} +#endif + +int avpriv_mpeg4audio_get_config2(MPEG4AudioConfig *c, const uint8_t *buf, + int size, int sync_extension, void *logctx) +{ + GetBitContext gb; + int ret; + + if (size <= 0) + return AVERROR_INVALIDDATA; + + ret = init_get_bits8(&gb, buf, size); + if (ret < 0) + return ret; + + return ff_mpeg4audio_get_config_gb(c, &gb, sync_extension, logctx); } diff -Nru ffmpeg-4.2.2/libavcodec/mpeg4audio.h ffmpeg-4.4/libavcodec/mpeg4audio.h --- ffmpeg-4.2.2/libavcodec/mpeg4audio.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg4audio.h 2021-04-08 21:28:39.000000000 +0000 @@ -46,28 +46,43 @@ } MPEG4AudioConfig; extern av_export_avcodec const int avpriv_mpeg4audio_sample_rates[16]; -extern const uint8_t ff_mpeg4audio_channels[8]; +extern const uint8_t ff_mpeg4audio_channels[14]; /** * Parse MPEG-4 systems extradata from a potentially unaligned GetBitContext to retrieve audio configuration. * @param[in] c MPEG4AudioConfig structure to fill. * @param[in] gb Extradata from container. * @param[in] sync_extension look for a sync extension after config if true. - * @return On error -1 is returned, on success AudioSpecificConfig bit index in extradata. + * @param[in] logctx opaque struct starting with an AVClass element, used for logging. + * @return negative AVERROR code on error, on success AudioSpecificConfig bit index in extradata. */ int ff_mpeg4audio_get_config_gb(MPEG4AudioConfig *c, GetBitContext *gb, - int sync_extension); + int sync_extension, void *logctx); +#if LIBAVCODEC_VERSION_MAJOR < 59 /** * Parse MPEG-4 systems extradata from a raw buffer to retrieve audio configuration. * @param[in] c MPEG4AudioConfig structure to fill. * @param[in] buf Extradata from container. * @param[in] bit_size Extradata size in bits. * @param[in] sync_extension look for a sync extension after config if true. - * @return On error -1 is returned, on success AudioSpecificConfig bit index in extradata. + * @return negative AVERROR code on error, on success AudioSpecificConfig bit index in extradata. */ int avpriv_mpeg4audio_get_config(MPEG4AudioConfig *c, const uint8_t *buf, int bit_size, int sync_extension); +#endif + +/** + * Parse MPEG-4 systems extradata from a raw buffer to retrieve audio configuration. + * @param[in] c MPEG4AudioConfig structure to fill. + * @param[in] buf Extradata from container. + * @param[in] size Extradata size in bytes. + * @param[in] sync_extension look for a sync extension after config if true. + * @param[in] logctx opaque struct starting with an AVClass element, used for logging. + * @return negative AVERROR code on error, AudioSpecificConfig bit index in extradata on success. + */ +int avpriv_mpeg4audio_get_config2(MPEG4AudioConfig *c, const uint8_t *buf, + int size, int sync_extension, void *logctx); enum AudioObjectType { AOT_NULL, @@ -150,7 +165,7 @@ ff_pce_copy_bits(pb, gb, 16); if (bits) ff_pce_copy_bits(pb, gb, bits); - avpriv_align_put_bits(pb); + align_put_bits(pb); align_get_bits(gb); comment_size = ff_pce_copy_bits(pb, gb, 8); for (; comment_size > 0; comment_size--) diff -Nru ffmpeg-4.2.2/libavcodec/mpeg4data.h ffmpeg-4.4/libavcodec/mpeg4data.h --- ffmpeg-4.2.2/libavcodec/mpeg4data.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg4data.h 2021-04-08 21:28:39.000000000 +0000 @@ -323,10 +323,8 @@ intra_rvlc_level, }; -const uint16_t ff_sprite_trajectory_tab[15][2] = { - {0x00, 2}, {0x02, 3}, {0x03, 3}, {0x04, 3}, {0x05, 3}, {0x06, 3}, - {0x0E, 4}, {0x1E, 5}, {0x3E, 6}, {0x7E, 7}, {0xFE, 8}, - {0x1FE, 9},{0x3FE, 10},{0x7FE, 11},{0xFFE, 12}, +const uint8_t ff_sprite_trajectory_lens[15] = { + 2, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, }; const uint8_t ff_mb_type_b_tab[4][2] = { @@ -374,119 +372,91 @@ }; /* Note these are different in studio mode */ -const uint16_t ff_mpeg4_studio_dc_luma[19][2]={ - {0x0e, 6}, {0x06, 5}, {0x00, 4}, {0x02, 4}, - {0x07, 3}, {0x05, 3}, {0x03, 3}, {0x02, 3}, - {0x04, 3}, {0x06, 3}, {0x01, 4}, {0x1e, 7}, - {0x3e, 8}, {0x7e, 9}, {0xfe, 10}, {0x1fe, 11}, - {0x3fe, 12}, {0x7fe, 13}, {0x7ff, 13} -}; - -const uint16_t ff_mpeg4_studio_dc_chroma[19][2]={ - {0x00, 4}, {0x02, 4}, {0x07, 3}, {0x05, 3}, - {0x03, 3}, {0x02, 3}, {0x04, 3}, {0x06, 3}, - {0x01, 4}, {0x06, 5}, {0x0e, 6}, {0x1e, 7}, - {0x3e, 8}, {0x7e, 9}, {0xfe, 10}, {0x1fe, 11}, - {0x3fe, 12}, {0x7fe, 13}, {0x7ff, 13} -}; - -const uint16_t ff_mpeg4_studio_intra[12][22][2]={ - { - {0x05, 4}, {0x04, 4}, {0x05, 7}, {0x09, 9}, - {0x21, 11}, {0x41, 12}, {0x81, 13}, {0x03, 4}, - {0x03, 5}, {0x05, 6}, {0x04, 7}, {0x03, 7}, - {0x05, 8}, {0x03, 2}, {0x05, 3}, {0x04, 3}, - {0x03, 3}, {0x02, 4}, {0x04, 6}, {0x03, 6}, - {0x11, 10}, {0x80, 13} - }, - { - {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, - {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, - {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}, - {0x00, 0}, {0x00, 0}, {0x01, 1}, {0x01, 2}, - {0x01, 3}, {0x01, 4}, {0x01, 5}, {0x03, 7}, - {0x05, 8}, {0x04, 8} - }, - { - {0x05, 3}, {0x03, 5}, {0x02, 5}, {0x03, 7}, - {0x09, 9}, {0x103, 14}, {0x102, 14}, {0x04, 3}, - {0x03, 3}, {0x03, 4}, {0x02, 4}, {0x03, 6}, - {0x11, 10}, {0x03, 2}, {0x02, 3}, {0x02, 6}, - {0x05, 8}, {0x21, 11}, {0x83, 13}, {0x101, 14}, - {0x201, 15}, {0x82, 13} - }, - { - {0x05, 5}, {0x05, 4}, {0x04, 5}, {0x03, 6}, - {0x09, 9}, {0x83, 13}, {0x82, 13}, {0x03, 3}, - {0x04, 4}, {0x03, 4}, {0x03, 5}, {0x05, 8}, - {0x81, 13}, {0x03, 2}, {0x02, 2}, {0x02, 5}, - {0x02, 6}, {0x03, 7}, {0x11, 10}, {0x43, 12}, - {0x80, 13}, {0x42, 12} - }, - { - {0x05, 7}, {0x03, 4}, {0x03, 5}, {0x04, 7}, - {0x09, 9}, {0x83, 13}, {0x101, 14}, {0x03, 3}, - {0x02, 4}, {0x05, 6}, {0x03, 7}, {0x11, 10}, - {0x201, 15}, {0x03, 2}, {0x02, 2}, {0x02, 3}, - {0x04, 6}, {0x03, 6}, {0x05, 8}, {0x21, 11}, - {0x82, 13}, {0x81, 13} - }, - { - {0x13, 10}, {0x03, 5}, {0x05, 7}, {0x12, 10}, - {0x43, 12}, {0x83, 13}, {0x82, 13}, {0x02, 5}, - {0x04, 7}, {0x05, 8}, {0x23, 11}, {0x81, 13}, - {0x101, 14}, {0x03, 2}, {0x02, 2}, {0x01, 2}, - {0x01, 3}, {0x03, 6}, {0x03, 7}, {0x22, 11}, - {0x201, 15}, {0x42, 12} - }, - { - {0x23, 11}, {0x01, 4}, {0x07, 8}, {0x13, 10}, - {0x22, 11}, {0x103, 14}, {0x102, 14}, {0x03, 6}, - {0x06, 8}, {0x12, 10}, {0x43, 12}, {0x101, 14}, - {0x201, 15}, {0x03, 3}, {0x02, 3}, {0x03, 2}, - {0x02, 2}, {0x01, 3}, {0x02, 6}, {0x05, 8}, - {0x42, 12}, {0x41, 12} - }, - { - {0x0b, 9}, {0x03, 5}, {0x07, 8}, {0x07, 7}, - {0x06, 7}, {0x23, 11}, {0x41, 12}, {0x05, 7}, - {0x06, 8}, {0x0a, 9}, {0x13, 10}, {0x22, 11}, - {0x40, 12}, {0x03, 4}, {0x02, 4}, {0x03, 2}, - {0x02, 2}, {0x01, 2}, {0x02, 5}, {0x04, 7}, - {0x12, 10}, {0x21, 11} - }, - { - {0x15, 10}, {0x03, 6}, {0x14, 10}, {0x23, 11}, - {0x07, 8}, {0x43, 12}, {0x81, 13}, {0x06, 8}, - {0x0b, 9}, {0x13, 10}, {0x12, 10}, {0x42, 12}, - {0x80, 13}, {0x01, 4}, {0x03, 3}, {0x02, 3}, - {0x03, 2}, {0x02, 2}, {0x01, 3}, {0x02, 6}, - {0x22, 11}, {0x41, 12} - }, - { - {0x43, 12}, {0x05, 6}, {0x07, 8}, {0x04, 6}, - {0x03, 6}, {0x13, 10}, {0x42, 12}, {0x05, 7}, - {0x04, 7}, {0x06, 8}, {0x12, 10}, {0x41, 12}, - {0x40, 12}, {0x03, 5}, {0x03, 4}, {0x03, 3}, - {0x02, 3}, {0x03, 2}, {0x02, 2}, {0x02, 4}, - {0x05, 8}, {0x11, 10} - }, - { - {0x83, 13}, {0x05, 7}, {0x07, 8}, {0x03, 4}, - {0x21, 11}, {0x82, 13}, {0x81, 13}, {0x04, 7}, - {0x06, 8}, {0x0b, 9}, {0x0a, 9}, {0x11, 10}, - {0x80, 13}, {0x03, 5}, {0x02, 5}, {0x02, 4}, - {0x03, 3}, {0x02, 3}, {0x03, 2}, {0x02, 2}, - {0x03, 6}, {0x09, 9} - }, - { - {0x13, 10}, {0x03, 5}, {0x03, 6}, {0x0d, 9}, - {0x0c, 9}, {0x21, 11}, {0x20, 11}, {0x02, 5}, - {0x02, 6}, {0x07, 8}, {0x0b, 9}, {0x12, 10}, - {0x11, 10}, {0x05, 3}, {0x04, 3}, {0x05, 4}, - {0x04, 4}, {0x03, 4}, {0x02, 4}, {0x03, 3}, - {0x03, 2}, {0x0a, 9} - } +const uint8_t ff_mpeg4_studio_dc_luma[19][2] = { + { 2, 4 }, { 10, 4 }, { 3, 4 }, { 1, 5 }, { 0, 6 }, { 11, 7 }, + { 12, 8 }, { 13, 9 }, { 14, 10 }, { 15, 11 }, { 16, 12 }, { 17, 13 }, + { 18, 13 }, { 7, 3 }, { 6, 3 }, { 8, 3 }, { 5, 3 }, { 9, 3 }, + { 4, 3 }, +}; + +const uint8_t ff_mpeg4_studio_dc_chroma[19][2] = { + { 0, 4 }, { 8, 4 }, { 1, 4 }, { 9, 5 }, { 10, 6 }, { 11, 7 }, + { 12, 8 }, { 13, 9 }, { 14, 10 }, { 15, 11 }, { 16, 12 }, { 17, 13 }, + { 18, 13 }, { 5, 3 }, { 4, 3 }, { 6, 3 }, { 3, 3 }, { 7, 3 }, + { 2, 3 }, +}; + +const uint8_t ff_mpeg4_studio_intra[12][24][2] = { + { + { 0, -6 }, { 21, 13 }, { 6, 13 }, { 5, 12 }, { 4, 11 }, { 20, 10 }, + { 3, 9 }, { 12, 8 }, { 11, 7 }, { 10, 7 }, { 2, 7 }, { 19, 6 }, + { 18, 6 }, { 9, 6 }, { 8, 5 }, { 17, 4 }, { 7, 4 }, { 1, 4 }, + { 0, 4 }, { 16, 3 }, { 15, 3 }, { 14, 3 }, { 13, 2 }, + }, + { + { 0, -6 }, { 21, 8 }, { 20, 8 }, { 19, 7 }, { 18, 5 }, { 17, 4 }, + { 16, 3 }, { 15, 2 }, { 14, 1 }, + }, + { + { 0, -6 }, { 0,-15 }, { 20, 15 }, { 19, 14 }, { 6, 14 }, { 5, 14 }, + { 21, 13 }, { 18, 13 }, { 17, 11 }, { 12, 10 }, { 4, 9 }, { 16, 8 }, + { 3, 7 }, { 15, 6 }, { 11, 6 }, { 2, 5 }, { 1, 5 }, { 10, 4 }, + { 9, 4 }, { 14, 3 }, { 8, 3 }, { 7, 3 }, { 0, 3 }, { 13, 2 }, + }, + { + { 0, -6 }, { 20, 13 }, { 12, 13 }, { 6, 13 }, { 5, 13 }, { 21, 12 }, + { 19, 12 }, { 18, 10 }, { 4, 9 }, { 11, 8 }, { 17, 7 }, { 16, 6 }, + { 3, 6 }, { 15, 5 }, { 10, 5 }, { 2, 5 }, { 0, 5 }, { 9, 4 }, + { 8, 4 }, { 1, 4 }, { 7, 3 }, { 14, 2 }, { 13, 2 }, + }, + { + { 0, -6 }, { 0,-15 }, { 12, 15 }, { 6, 14 }, { 21, 13 }, { 20, 13 }, + { 5, 13 }, { 19, 11 }, { 11, 10 }, { 4, 9 }, { 18, 8 }, { 10, 7 }, + { 3, 7 }, { 0, 7 }, { 17, 6 }, { 16, 6 }, { 9, 6 }, { 2, 5 }, + { 8, 4 }, { 1, 4 }, { 15, 3 }, { 7, 3 }, { 14, 2 }, { 13, 2 }, + }, + { + { 0, -6 }, { 0,-15 }, { 20, 15 }, { 12, 14 }, { 11, 13 }, { 6, 13 }, + { 5, 13 }, { 21, 12 }, { 4, 12 }, { 19, 11 }, { 10, 11 }, { 3, 10 }, + { 0, 10 }, { 9, 8 }, { 18, 7 }, { 8, 7 }, { 2, 7 }, { 17, 6 }, + { 7, 5 }, { 1, 5 }, { 16, 3 }, { 15, 2 }, { 14, 2 }, { 13, 2 }, + }, + { + { 0, -6 }, { 0,-15 }, { 12, 15 }, { 11, 14 }, { 6, 14 }, { 5, 14 }, + { 21, 12 }, { 20, 12 }, { 10, 12 }, { 4, 11 }, { 0, 11 }, { 9, 10 }, + { 3, 10 }, { 19, 8 }, { 8, 8 }, { 2, 8 }, { 18, 6 }, { 7, 6 }, + { 1, 4 }, { 17, 3 }, { 14, 3 }, { 13, 3 }, { 16, 2 }, { 15, 2 }, + }, + { + { 0, -6 }, { 12, 12 }, { 6, 12 }, { 21, 11 }, { 11, 11 }, { 5, 11 }, + { 20, 10 }, { 10, 10 }, { 9, 9 }, { 0, 9 }, { 8, 8 }, { 2, 8 }, + { 19, 7 }, { 7, 7 }, { 4, 7 }, { 3, 7 }, { 18, 5 }, { 1, 5 }, + { 14, 4 }, { 13, 4 }, { 17, 2 }, { 16, 2 }, { 15, 2 }, + }, + { + { 0, -6 }, { 12, 13 }, { 6, 13 }, { 21, 12 }, { 11, 12 }, { 5, 12 }, + { 20, 11 }, { 3, 11 }, { 10, 10 }, { 9, 10 }, { 2, 10 }, { 0, 10 }, + { 8, 9 }, { 7, 8 }, { 4, 8 }, { 19, 6 }, { 1, 6 }, { 13, 4 }, + { 18, 3 }, { 15, 3 }, { 14, 3 }, { 17, 2 }, { 16, 2 }, + }, + { + { 0, -6 }, { 12, 12 }, { 11, 12 }, { 6, 12 }, { 0, 12 }, { 21, 10 }, + { 10, 10 }, { 5, 10 }, { 20, 8 }, { 9, 8 }, { 2, 8 }, { 8, 7 }, + { 7, 7 }, { 4, 6 }, { 3, 6 }, { 1, 6 }, { 13, 5 }, { 19, 4 }, + { 14, 4 }, { 16, 3 }, { 15, 3 }, { 18, 2 }, { 17, 2 }, + }, + { + { 0, -6 }, { 12, 13 }, { 6, 13 }, { 5, 13 }, { 0, 13 }, { 4, 11 }, + { 11, 10 }, { 21, 9 }, { 10, 9 }, { 9, 9 }, { 8, 8 }, { 2, 8 }, + { 7, 7 }, { 1, 7 }, { 20, 6 }, { 14, 5 }, { 13, 5 }, { 15, 4 }, + { 3, 4 }, { 17, 3 }, { 16, 3 }, { 19, 2 }, { 18, 2 }, + }, + { + { 0, -6 }, { 6, 11 }, { 5, 11 }, { 12, 10 }, { 11, 10 }, { 0, 10 }, + { 21, 9 }, { 10, 9 }, { 4, 9 }, { 3, 9 }, { 9, 8 }, { 8, 6 }, + { 2, 6 }, { 7, 5 }, { 1, 5 }, { 18, 4 }, { 17, 4 }, { 16, 4 }, + { 15, 4 }, { 19, 3 }, { 14, 3 }, { 13, 3 }, { 20, 2 }, + }, }; #endif /* AVCODEC_MPEG4DATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mpeg4_unpack_bframes_bsf.c ffmpeg-4.4/libavcodec/mpeg4_unpack_bframes_bsf.c --- ffmpeg-4.2.2/libavcodec/mpeg4_unpack_bframes_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg4_unpack_bframes_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -19,13 +19,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "internal.h" #include "mpeg4video.h" typedef struct UnpackBFramesBSFContext { - AVPacket *b_frame; + AVBufferRef *b_frame_ref; } UnpackBFramesBSFContext; /* determine the position of the packed marker in the userdata, @@ -56,32 +56,32 @@ } } -static int mpeg4_unpack_bframes_filter(AVBSFContext *ctx, AVPacket *out) +static int mpeg4_unpack_bframes_filter(AVBSFContext *ctx, AVPacket *pkt) { UnpackBFramesBSFContext *s = ctx->priv_data; int pos_p = -1, nb_vop = 0, pos_vop2 = -1, ret = 0; - AVPacket *in; - ret = ff_bsf_get_packet(ctx, &in); + ret = ff_bsf_get_packet_ref(ctx, pkt); if (ret < 0) return ret; - scan_buffer(in->data, in->size, &pos_p, &nb_vop, &pos_vop2); + scan_buffer(pkt->data, pkt->size, &pos_p, &nb_vop, &pos_vop2); av_log(ctx, AV_LOG_DEBUG, "Found %d VOP startcode(s) in this packet.\n", nb_vop); if (pos_vop2 >= 0) { - if (s->b_frame->data) { + if (s->b_frame_ref) { av_log(ctx, AV_LOG_WARNING, "Missing one N-VOP packet, discarding one B-frame.\n"); - av_packet_unref(s->b_frame); + av_buffer_unref(&s->b_frame_ref); } - /* store the packed B-frame in the BSFContext */ - ret = av_packet_ref(s->b_frame, in); - if (ret < 0) { + /* store a reference to the packed B-frame's data in the BSFContext */ + s->b_frame_ref = av_buffer_ref(pkt->buf); + if (!s->b_frame_ref) { + ret = AVERROR(ENOMEM); goto fail; } - s->b_frame->size -= pos_vop2; - s->b_frame->data += pos_vop2; + s->b_frame_ref->data = pkt->data + pos_vop2; + s->b_frame_ref->size = pkt->size - pos_vop2; } if (nb_vop > 2) { @@ -89,56 +89,49 @@ "Found %d VOP headers in one packet, only unpacking one.\n", nb_vop); } - if (nb_vop == 1 && s->b_frame->data) { - /* use frame from BSFContext */ - av_packet_move_ref(out, s->b_frame); - - /* use properties from current input packet */ - ret = av_packet_copy_props(out, in); - if (ret < 0) { - goto fail; - } + if (nb_vop == 1 && s->b_frame_ref) { + AVBufferRef *tmp = pkt->buf; + + /* make tmp accurately reflect the packet's data */ + tmp->data = pkt->data; + tmp->size = pkt->size; + + /* replace data in packet with stored data */ + pkt->buf = s->b_frame_ref; + pkt->data = s->b_frame_ref->data; + pkt->size = s->b_frame_ref->size; - if (in->size <= MAX_NVOP_SIZE) { - /* N-VOP */ + /* store reference to data into BSFContext */ + s->b_frame_ref = tmp; + + if (s->b_frame_ref->size <= MAX_NVOP_SIZE) { + /* N-VOP - discard stored data */ av_log(ctx, AV_LOG_DEBUG, "Skipping N-VOP.\n"); - } else { - /* copy packet into BSFContext */ - av_packet_move_ref(s->b_frame, in); + av_buffer_unref(&s->b_frame_ref); } } else if (nb_vop >= 2) { /* use first frame of the packet */ - av_packet_move_ref(out, in); - out->size = pos_vop2; + pkt->size = pos_vop2; } else if (pos_p >= 0) { - ret = av_packet_make_writable(in); + ret = av_packet_make_writable(pkt); if (ret < 0) goto fail; av_log(ctx, AV_LOG_DEBUG, "Updating DivX userdata (remove trailing 'p').\n"); - av_packet_move_ref(out, in); /* remove 'p' (packed) from the end of the (DivX) userdata string */ - out->data[pos_p] = '\0'; + pkt->data[pos_p] = '\0'; } else { - /* copy packet */ - av_packet_move_ref(out, in); + /* use packet as is */ } fail: if (ret < 0) - av_packet_unref(out); - av_packet_free(&in); + av_packet_unref(pkt); return ret; } static int mpeg4_unpack_bframes_init(AVBSFContext *ctx) { - UnpackBFramesBSFContext *s = ctx->priv_data; - - s->b_frame = av_packet_alloc(); - if (!s->b_frame) - return AVERROR(ENOMEM); - if (ctx->par_in->extradata) { int pos_p_ext = -1; scan_buffer(ctx->par_in->extradata, ctx->par_in->extradata_size, &pos_p_ext, NULL, NULL); @@ -152,16 +145,10 @@ return 0; } -static void mpeg4_unpack_bframes_flush(AVBSFContext *bsfc) -{ - UnpackBFramesBSFContext *ctx = bsfc->priv_data; - av_packet_unref(ctx->b_frame); -} - -static void mpeg4_unpack_bframes_close(AVBSFContext *bsfc) +static void mpeg4_unpack_bframes_close_flush(AVBSFContext *bsfc) { UnpackBFramesBSFContext *ctx = bsfc->priv_data; - av_packet_free(&ctx->b_frame); + av_buffer_unref(&ctx->b_frame_ref); } static const enum AVCodecID codec_ids[] = { @@ -173,7 +160,7 @@ .priv_data_size = sizeof(UnpackBFramesBSFContext), .init = mpeg4_unpack_bframes_init, .filter = mpeg4_unpack_bframes_filter, - .flush = mpeg4_unpack_bframes_flush, - .close = mpeg4_unpack_bframes_close, + .flush = mpeg4_unpack_bframes_close_flush, + .close = mpeg4_unpack_bframes_close_flush, .codec_ids = codec_ids, }; diff -Nru ffmpeg-4.2.2/libavcodec/mpeg4videodec.c ffmpeg-4.4/libavcodec/mpeg4videodec.c --- ffmpeg-4.2.2/libavcodec/mpeg4videodec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg4videodec.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,8 +25,9 @@ #include "libavutil/internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/thread.h" #include "error_resilience.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "idctdsp.h" #include "internal.h" #include "mpegutils.h" @@ -48,11 +49,12 @@ #define MB_TYPE_B_VLC_BITS 4 #define STUDIO_INTRA_BITS 9 -static int decode_studio_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb); - static VLC dc_lum, dc_chrom; static VLC sprite_trajectory; static VLC mb_type_b_vlc; +static VLC studio_intra_tab[12]; +static VLC studio_luma_dc; +static VLC studio_chroma_dc; static const int mb_type_b_map[4] = { MB_TYPE_DIRECT2 | MB_TYPE_L0L1, @@ -195,22 +197,18 @@ if (w <= 0 || h <= 0) return AVERROR_INVALIDDATA; - /* the decoder was not properly initialized and we cannot continue */ - if (sprite_trajectory.table == NULL) - return AVERROR_INVALIDDATA; - for (i = 0; i < ctx->num_sprite_warping_points; i++) { int length; int x = 0, y = 0; - length = get_vlc2(gb, sprite_trajectory.table, SPRITE_TRAJ_VLC_BITS, 3); + length = get_vlc2(gb, sprite_trajectory.table, SPRITE_TRAJ_VLC_BITS, 2); if (length > 0) x = get_xbits(gb, length); if (!(ctx->divx_version == 500 && ctx->divx_build == 413)) check_marker(s->avctx, gb, "before sprite_trajectory"); - length = get_vlc2(gb, sprite_trajectory.table, SPRITE_TRAJ_VLC_BITS, 3); + length = get_vlc2(gb, sprite_trajectory.table, SPRITE_TRAJ_VLC_BITS, 2); if (length > 0) y = get_xbits(gb, length); @@ -610,7 +608,7 @@ dy -= 1 << (shift + a + 1); else dx -= 1 << (shift + a + 1); - mb_v = s->sprite_offset[0][n] + dx * s->mb_x * 16 + dy * s->mb_y * 16; + mb_v = s->sprite_offset[0][n] + dx * s->mb_x * 16U + dy * s->mb_y * 16U; sum = 0; for (y = 0; y < 16; y++) { @@ -711,7 +709,7 @@ int i; do { - if (show_bits_long(&s->gb, 19) == DC_MARKER) + if (show_bits(&s->gb, 19) == DC_MARKER) return mb_num - 1; cbpc = get_vlc2(&s->gb, ff_h263_intra_MCBPC_vlc.table, INTRA_MCBPC_VLC_BITS, 2); @@ -1001,7 +999,7 @@ if (s->pict_type == AV_PICTURE_TYPE_I) { while (show_bits(&s->gb, 9) == 1) skip_bits(&s->gb, 9); - if (get_bits_long(&s->gb, 19) != DC_MARKER) { + if (get_bits(&s->gb, 19) != DC_MARKER) { av_log(s->avctx, AV_LOG_ERROR, "marker missing after first I partition at %d %d\n", s->mb_x, s->mb_y); @@ -1782,7 +1780,7 @@ { align_get_bits(gb); - while (get_bits_left(gb) >= 24 && show_bits_long(gb, 24) != 0x1) { + while (get_bits_left(gb) >= 24 && show_bits(gb, 24) != 0x1) { get_bits(gb, 8); } } @@ -1820,7 +1818,7 @@ int cc, dct_dc_size, dct_diff, code, j, idx = 1, group = 0, run = 0, additional_code_len, sign, mismatch; - VLC *cur_vlc = &ctx->studio_intra_tab[0]; + const VLC *cur_vlc = &studio_intra_tab[0]; uint8_t *const scantable = s->intra_scantable.permutated; const uint16_t *quant_matrix; uint32_t flc; @@ -1834,21 +1832,18 @@ if (n < 4) { cc = 0; - dct_dc_size = get_vlc2(&s->gb, ctx->studio_luma_dc.table, STUDIO_INTRA_BITS, 2); + dct_dc_size = get_vlc2(&s->gb, studio_luma_dc.table, STUDIO_INTRA_BITS, 2); quant_matrix = s->intra_matrix; } else { cc = (n & 1) + 1; if (ctx->rgb) - dct_dc_size = get_vlc2(&s->gb, ctx->studio_luma_dc.table, STUDIO_INTRA_BITS, 2); + dct_dc_size = get_vlc2(&s->gb, studio_luma_dc.table, STUDIO_INTRA_BITS, 2); else - dct_dc_size = get_vlc2(&s->gb, ctx->studio_chroma_dc.table, STUDIO_INTRA_BITS, 2); + dct_dc_size = get_vlc2(&s->gb, studio_chroma_dc.table, STUDIO_INTRA_BITS, 2); quant_matrix = s->chroma_intra_matrix; } - if (dct_dc_size < 0) { - av_log(s->avctx, AV_LOG_ERROR, "illegal dct_dc_size vlc\n"); - return AVERROR_INVALIDDATA; - } else if (dct_dc_size == 0) { + if (dct_dc_size == 0) { dct_diff = 0; } else { dct_diff = get_xbits(&s->gb, dct_dc_size); @@ -1881,7 +1876,7 @@ } additional_code_len = ac_state_tab[group][0]; - cur_vlc = &ctx->studio_intra_tab[ac_state_tab[group][1]]; + cur_vlc = &studio_intra_tab[ac_state_tab[group][1]]; if (group == 0) { /* End of Block */ @@ -2147,6 +2142,158 @@ } } +static int read_quant_matrix_ext(MpegEncContext *s, GetBitContext *gb) +{ + int i, j, v; + + if (get_bits1(gb)) { + if (get_bits_left(gb) < 64*8) + return AVERROR_INVALIDDATA; + /* intra_quantiser_matrix */ + for (i = 0; i < 64; i++) { + v = get_bits(gb, 8); + j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; + s->intra_matrix[j] = v; + s->chroma_intra_matrix[j] = v; + } + } + + if (get_bits1(gb)) { + if (get_bits_left(gb) < 64*8) + return AVERROR_INVALIDDATA; + /* non_intra_quantiser_matrix */ + for (i = 0; i < 64; i++) { + get_bits(gb, 8); + } + } + + if (get_bits1(gb)) { + if (get_bits_left(gb) < 64*8) + return AVERROR_INVALIDDATA; + /* chroma_intra_quantiser_matrix */ + for (i = 0; i < 64; i++) { + v = get_bits(gb, 8); + j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; + s->chroma_intra_matrix[j] = v; + } + } + + if (get_bits1(gb)) { + if (get_bits_left(gb) < 64*8) + return AVERROR_INVALIDDATA; + /* chroma_non_intra_quantiser_matrix */ + for (i = 0; i < 64; i++) { + get_bits(gb, 8); + } + } + + next_start_code_studio(gb); + return 0; +} + +static void extension_and_user_data(MpegEncContext *s, GetBitContext *gb, int id) +{ + uint32_t startcode; + uint8_t extension_type; + + startcode = show_bits_long(gb, 32); + if (startcode == USER_DATA_STARTCODE || startcode == EXT_STARTCODE) { + + if ((id == 2 || id == 4) && startcode == EXT_STARTCODE) { + skip_bits_long(gb, 32); + extension_type = get_bits(gb, 4); + if (extension_type == QUANT_MATRIX_EXT_ID) + read_quant_matrix_ext(s, gb); + } + } +} + +static int decode_studio_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) +{ + MpegEncContext *s = &ctx->m; + int width, height; + int bits_per_raw_sample; + int rgb, chroma_format; + + // random_accessible_vol and video_object_type_indication have already + // been read by the caller decode_vol_header() + skip_bits(gb, 4); /* video_object_layer_verid */ + ctx->shape = get_bits(gb, 2); /* video_object_layer_shape */ + skip_bits(gb, 4); /* video_object_layer_shape_extension */ + skip_bits1(gb); /* progressive_sequence */ + if (ctx->shape != RECT_SHAPE) { + avpriv_request_sample(s->avctx, "MPEG-4 Studio profile non rectangular shape"); + return AVERROR_PATCHWELCOME; + } + if (ctx->shape != BIN_ONLY_SHAPE) { + rgb = get_bits1(gb); /* rgb_components */ + chroma_format = get_bits(gb, 2); /* chroma_format */ + if (!chroma_format || chroma_format == CHROMA_420 || (rgb && chroma_format == CHROMA_422)) { + av_log(s->avctx, AV_LOG_ERROR, "illegal chroma format\n"); + return AVERROR_INVALIDDATA; + } + + bits_per_raw_sample = get_bits(gb, 4); /* bit_depth */ + if (bits_per_raw_sample == 10) { + if (rgb) { + s->avctx->pix_fmt = AV_PIX_FMT_GBRP10; + } else { + s->avctx->pix_fmt = chroma_format == CHROMA_422 ? AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV444P10; + } + } else { + avpriv_request_sample(s->avctx, "MPEG-4 Studio profile bit-depth %u", bits_per_raw_sample); + return AVERROR_PATCHWELCOME; + } + if (rgb != ctx->rgb || s->chroma_format != chroma_format) + s->context_reinit = 1; + s->avctx->bits_per_raw_sample = bits_per_raw_sample; + ctx->rgb = rgb; + s->chroma_format = chroma_format; + } + if (ctx->shape == RECT_SHAPE) { + check_marker(s->avctx, gb, "before video_object_layer_width"); + width = get_bits(gb, 14); /* video_object_layer_width */ + check_marker(s->avctx, gb, "before video_object_layer_height"); + height = get_bits(gb, 14); /* video_object_layer_height */ + check_marker(s->avctx, gb, "after video_object_layer_height"); + + /* Do the same check as non-studio profile */ + if (width && height) { + if (s->width && s->height && + (s->width != width || s->height != height)) + s->context_reinit = 1; + s->width = width; + s->height = height; + } + } + s->aspect_ratio_info = get_bits(gb, 4); + if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) { + s->avctx->sample_aspect_ratio.num = get_bits(gb, 8); // par_width + s->avctx->sample_aspect_ratio.den = get_bits(gb, 8); // par_height + } else { + s->avctx->sample_aspect_ratio = ff_h263_pixel_aspect[s->aspect_ratio_info]; + } + skip_bits(gb, 4); /* frame_rate_code */ + skip_bits(gb, 15); /* first_half_bit_rate */ + check_marker(s->avctx, gb, "after first_half_bit_rate"); + skip_bits(gb, 15); /* latter_half_bit_rate */ + check_marker(s->avctx, gb, "after latter_half_bit_rate"); + skip_bits(gb, 15); /* first_half_vbv_buffer_size */ + check_marker(s->avctx, gb, "after first_half_vbv_buffer_size"); + skip_bits(gb, 3); /* latter_half_vbv_buffer_size */ + skip_bits(gb, 11); /* first_half_vbv_buffer_size */ + check_marker(s->avctx, gb, "after first_half_vbv_buffer_size"); + skip_bits(gb, 15); /* latter_half_vbv_occupancy */ + check_marker(s->avctx, gb, "after latter_half_vbv_occupancy"); + s->low_delay = get_bits1(gb); + s->mpeg_quant = get_bits1(gb); /* mpeg2_stream */ + + next_start_code_studio(gb); + extension_and_user_data(s, gb, 2); + + return 0; +} + static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) { MpegEncContext *s = &ctx->m; @@ -2971,72 +3118,6 @@ return 0; } -static int read_quant_matrix_ext(MpegEncContext *s, GetBitContext *gb) -{ - int i, j, v; - - if (get_bits1(gb)) { - if (get_bits_left(gb) < 64*8) - return AVERROR_INVALIDDATA; - /* intra_quantiser_matrix */ - for (i = 0; i < 64; i++) { - v = get_bits(gb, 8); - j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; - s->intra_matrix[j] = v; - s->chroma_intra_matrix[j] = v; - } - } - - if (get_bits1(gb)) { - if (get_bits_left(gb) < 64*8) - return AVERROR_INVALIDDATA; - /* non_intra_quantiser_matrix */ - for (i = 0; i < 64; i++) { - get_bits(gb, 8); - } - } - - if (get_bits1(gb)) { - if (get_bits_left(gb) < 64*8) - return AVERROR_INVALIDDATA; - /* chroma_intra_quantiser_matrix */ - for (i = 0; i < 64; i++) { - v = get_bits(gb, 8); - j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; - s->chroma_intra_matrix[j] = v; - } - } - - if (get_bits1(gb)) { - if (get_bits_left(gb) < 64*8) - return AVERROR_INVALIDDATA; - /* chroma_non_intra_quantiser_matrix */ - for (i = 0; i < 64; i++) { - get_bits(gb, 8); - } - } - - next_start_code_studio(gb); - return 0; -} - -static void extension_and_user_data(MpegEncContext *s, GetBitContext *gb, int id) -{ - uint32_t startcode; - uint8_t extension_type; - - startcode = show_bits_long(gb, 32); - if (startcode == USER_DATA_STARTCODE || startcode == EXT_STARTCODE) { - - if ((id == 2 || id == 4) && startcode == EXT_STARTCODE) { - skip_bits_long(gb, 32); - extension_type = get_bits(gb, 4); - if (extension_type == QUANT_MATRIX_EXT_ID) - read_quant_matrix_ext(s, gb); - } - } -} - static void decode_smpte_tc(Mpeg4DecContext *ctx, GetBitContext *gb) { MpegEncContext *s = &ctx->m; @@ -3116,94 +3197,15 @@ MpegEncContext *s = &ctx->m; int visual_object_type; - skip_bits(gb, 4); /* visual_object_verid */ - visual_object_type = get_bits(gb, 4); - if (visual_object_type != VOT_VIDEO_ID) { - avpriv_request_sample(s->avctx, "VO type %u", visual_object_type); - return AVERROR_PATCHWELCOME; - } - - next_start_code_studio(gb); - extension_and_user_data(s, gb, 1); - - return 0; -} - -static int decode_studio_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) -{ - MpegEncContext *s = &ctx->m; - int width, height; - int bits_per_raw_sample; - - // random_accessible_vol and video_object_type_indication have already - // been read by the caller decode_vol_header() - skip_bits(gb, 4); /* video_object_layer_verid */ - ctx->shape = get_bits(gb, 2); /* video_object_layer_shape */ - skip_bits(gb, 4); /* video_object_layer_shape_extension */ - skip_bits1(gb); /* progressive_sequence */ - if (ctx->shape != BIN_ONLY_SHAPE) { - ctx->rgb = get_bits1(gb); /* rgb_components */ - s->chroma_format = get_bits(gb, 2); /* chroma_format */ - if (!s->chroma_format) { - av_log(s->avctx, AV_LOG_ERROR, "illegal chroma format\n"); - return AVERROR_INVALIDDATA; - } - - bits_per_raw_sample = get_bits(gb, 4); /* bit_depth */ - if (bits_per_raw_sample == 10) { - if (ctx->rgb) { - s->avctx->pix_fmt = AV_PIX_FMT_GBRP10; - } - else { - s->avctx->pix_fmt = s->chroma_format == CHROMA_422 ? AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV444P10; - } - } - else { - avpriv_request_sample(s->avctx, "MPEG-4 Studio profile bit-depth %u", bits_per_raw_sample); - return AVERROR_PATCHWELCOME; - } - s->avctx->bits_per_raw_sample = bits_per_raw_sample; - } - if (ctx->shape == RECT_SHAPE) { - check_marker(s->avctx, gb, "before video_object_layer_width"); - width = get_bits(gb, 14); /* video_object_layer_width */ - check_marker(s->avctx, gb, "before video_object_layer_height"); - height = get_bits(gb, 14); /* video_object_layer_height */ - check_marker(s->avctx, gb, "after video_object_layer_height"); - - /* Do the same check as non-studio profile */ - if (width && height) { - if (s->width && s->height && - (s->width != width || s->height != height)) - s->context_reinit = 1; - s->width = width; - s->height = height; - } - } - s->aspect_ratio_info = get_bits(gb, 4); - if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) { - s->avctx->sample_aspect_ratio.num = get_bits(gb, 8); // par_width - s->avctx->sample_aspect_ratio.den = get_bits(gb, 8); // par_height - } else { - s->avctx->sample_aspect_ratio = ff_h263_pixel_aspect[s->aspect_ratio_info]; - } - skip_bits(gb, 4); /* frame_rate_code */ - skip_bits(gb, 15); /* first_half_bit_rate */ - check_marker(s->avctx, gb, "after first_half_bit_rate"); - skip_bits(gb, 15); /* latter_half_bit_rate */ - check_marker(s->avctx, gb, "after latter_half_bit_rate"); - skip_bits(gb, 15); /* first_half_vbv_buffer_size */ - check_marker(s->avctx, gb, "after first_half_vbv_buffer_size"); - skip_bits(gb, 3); /* latter_half_vbv_buffer_size */ - skip_bits(gb, 11); /* first_half_vbv_buffer_size */ - check_marker(s->avctx, gb, "after first_half_vbv_buffer_size"); - skip_bits(gb, 15); /* latter_half_vbv_occupancy */ - check_marker(s->avctx, gb, "after latter_half_vbv_occupancy"); - s->low_delay = get_bits1(gb); - s->mpeg_quant = get_bits1(gb); /* mpeg2_stream */ + skip_bits(gb, 4); /* visual_object_verid */ + visual_object_type = get_bits(gb, 4); + if (visual_object_type != VOT_VIDEO_ID) { + avpriv_request_sample(s->avctx, "VO type %u", visual_object_type); + return AVERROR_PATCHWELCOME; + } - next_start_code_studio(gb); - extension_and_user_data(s, gb, 2); + next_start_code_studio(gb); + extension_and_user_data(s, gb, 1); return 0; } @@ -3338,7 +3340,7 @@ next_start_code_studio(gb); extension_and_user_data(s, gb, 0); } else if (s->studio_profile) { - avpriv_request_sample(s->avctx, "Mixes studio and non studio profile\n"); + avpriv_request_sample(s->avctx, "Mix of studio and non studio profile"); return AVERROR_PATCHWELCOME; } s->avctx->profile = profile; @@ -3379,18 +3381,18 @@ ff_rl_init(&ff_mpeg4_rl_intra, ff_mpeg4_static_rl_table_store[0]); ff_rl_init(&ff_rvlc_rl_inter, ff_mpeg4_static_rl_table_store[1]); ff_rl_init(&ff_rvlc_rl_intra, ff_mpeg4_static_rl_table_store[2]); - INIT_VLC_RL(ff_mpeg4_rl_intra, 554); + INIT_FIRST_VLC_RL(ff_mpeg4_rl_intra, 554); INIT_VLC_RL(ff_rvlc_rl_inter, 1072); - INIT_VLC_RL(ff_rvlc_rl_intra, 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(&sprite_trajectory, SPRITE_TRAJ_VLC_BITS, 15, - &ff_sprite_trajectory_tab[0][1], 4, 2, - &ff_sprite_trajectory_tab[0][0], 4, 2, 128); + 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); @@ -3460,7 +3462,33 @@ if (ret < 0) return ret; - memcpy(((uint8_t*)s) + sizeof(MpegEncContext), ((uint8_t*)s1) + sizeof(MpegEncContext), sizeof(Mpeg4DecContext) - sizeof(MpegEncContext)); + // copy all the necessary fields explicitly + s->time_increment_bits = s1->time_increment_bits; + s->shape = s1->shape; + s->vol_sprite_usage = s1->vol_sprite_usage; + s->sprite_brightness_change = s1->sprite_brightness_change; + s->num_sprite_warping_points = s1->num_sprite_warping_points; + s->rvlc = s1->rvlc; + s->resync_marker = s1->resync_marker; + s->t_frame = s1->t_frame; + s->new_pred = s1->new_pred; + s->enhancement_type = s1->enhancement_type; + s->scalability = s1->scalability; + s->use_intra_dc_vlc = s1->use_intra_dc_vlc; + s->intra_dc_threshold = s1->intra_dc_threshold; + s->divx_version = s1->divx_version; + s->divx_build = s1->divx_build; + s->xvid_build = s1->xvid_build; + s->lavc_build = s1->lavc_build; + s->showed_packed_warning = s1->showed_packed_warning; + s->vol_control_parameters = s1->vol_control_parameters; + s->cplx_estimation_trash_i = s1->cplx_estimation_trash_i; + s->cplx_estimation_trash_p = s1->cplx_estimation_trash_p; + s->cplx_estimation_trash_b = s1->cplx_estimation_trash_b; + s->rgb = s1->rgb; + + memcpy(s->sprite_shift, s1->sprite_shift, sizeof(s1->sprite_shift)); + memcpy(s->sprite_traj, s1->sprite_traj, sizeof(s1->sprite_traj)); if (CONFIG_MPEG4_DECODER && !init && s1->xvid_build >= 0) ff_xvid_idct_init(&s->m.idsp, dst); @@ -3469,39 +3497,36 @@ } #endif -static av_cold int init_studio_vlcs(Mpeg4DecContext *ctx) +static av_cold void mpeg4_init_static(void) { - int i, ret; - - for (i = 0; i < 12; i++) { - ret = init_vlc(&ctx->studio_intra_tab[i], STUDIO_INTRA_BITS, 22, - &ff_mpeg4_studio_intra[i][0][1], 4, 2, - &ff_mpeg4_studio_intra[i][0][0], 4, 2, - 0); - - if (ret < 0) - return ret; + 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, + 0, 0, 528); + + INIT_VLC_STATIC_FROM_LENGTHS(&studio_chroma_dc, STUDIO_INTRA_BITS, 19, + &ff_mpeg4_studio_dc_chroma[0][1], 2, + &ff_mpeg4_studio_dc_chroma[0][0], 2, 1, + 0, 0, 528); + + for (unsigned i = 0, offset = 0; i < 12; i++) { + static VLC_TYPE vlc_buf[6498][2]; + + studio_intra_tab[i].table = &vlc_buf[offset]; + studio_intra_tab[i].table_allocated = FF_ARRAY_ELEMS(vlc_buf) - offset; + ff_init_vlc_from_lengths(&studio_intra_tab[i], + STUDIO_INTRA_BITS, 24, + &ff_mpeg4_studio_intra[i][0][1], 2, + &ff_mpeg4_studio_intra[i][0][0], 2, 1, + 0, INIT_VLC_STATIC_OVERLONG, NULL); + offset += studio_intra_tab[i].table_size; } - - ret = init_vlc(&ctx->studio_luma_dc, STUDIO_INTRA_BITS, 19, - &ff_mpeg4_studio_dc_luma[0][1], 4, 2, - &ff_mpeg4_studio_dc_luma[0][0], 4, 2, - 0); - if (ret < 0) - return ret; - - ret = init_vlc(&ctx->studio_chroma_dc, STUDIO_INTRA_BITS, 19, - &ff_mpeg4_studio_dc_chroma[0][1], 4, 2, - &ff_mpeg4_studio_dc_chroma[0][0], 4, 2, - 0); - if (ret < 0) - return ret; - - return 0; + ff_mpeg4videodec_static_init(); } static av_cold int decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; Mpeg4DecContext *ctx = avctx->priv_data; MpegEncContext *s = &ctx->m; int ret; @@ -3514,40 +3539,23 @@ if ((ret = ff_h263_decode_init(avctx)) < 0) return ret; - ff_mpeg4videodec_static_init(); - if ((ret = init_studio_vlcs(ctx)) < 0) - return ret; - s->h263_pred = 1; s->low_delay = 0; /* default, might be overridden in the vol header during header parsing */ s->decode_mb = mpeg4_decode_mb; ctx->time_increment_bits = 4; /* default value for broken headers */ avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; - avctx->internal->allocate_progress = 1; - return 0; -} + ff_thread_once(&init_static_once, mpeg4_init_static); -static av_cold int decode_end(AVCodecContext *avctx) -{ - Mpeg4DecContext *ctx = avctx->priv_data; - int i; - - if (!avctx->internal->is_copy) { - for (i = 0; i < 12; i++) - ff_free_vlc(&ctx->studio_intra_tab[i]); - - ff_free_vlc(&ctx->studio_luma_dc); - ff_free_vlc(&ctx->studio_chroma_dc); - } - - return ff_h263_decode_end(avctx); + return 0; } +#define OFFSET(x) offsetof(MpegEncContext, x) +#define FLAGS AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY static const AVOption mpeg4_options[] = { - {"quarter_sample", "1/4 subpel MC", offsetof(MpegEncContext, quarter_sample), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, 0}, - {"divx_packed", "divx style packed b frames", offsetof(MpegEncContext, divx_packed), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, 0}, + {"quarter_sample", "1/4 subpel MC", OFFSET(quarter_sample), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS}, + {"divx_packed", "divx style packed b frames", OFFSET(divx_packed), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS}, {NULL} }; @@ -3565,19 +3573,20 @@ .id = AV_CODEC_ID_MPEG4, .priv_data_size = sizeof(Mpeg4DecContext), .init = decode_init, - .close = decode_end, + .close = ff_h263_decode_end, .decode = ff_h263_decode_frame, .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_FRAME_THREADS, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | + FF_CODEC_CAP_ALLOCATE_PROGRESS, .flush = ff_mpeg_flush, .max_lowres = 3, .pix_fmts = ff_h263_hwaccel_pixfmt_list_420, .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg4_video_profiles), .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg4_update_thread_context), .priv_class = &mpeg4_class, - .hw_configs = (const AVCodecHWConfigInternal*[]) { + .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_MPEG4_NVDEC_HWACCEL HWACCEL_NVDEC(mpeg4), #endif diff -Nru ffmpeg-4.2.2/libavcodec/mpeg4videoenc.c ffmpeg-4.4/libavcodec/mpeg4videoenc.c --- ffmpeg-4.2.2/libavcodec/mpeg4videoenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg4videoenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ #include "mpegvideo.h" #include "h263.h" #include "mpeg4video.h" +#include "profiles.h" /* The uni_DCtab_* tables below contain unified bits+length tables to encode DC * differences in MPEG-4. Unified in the sense that the specification specifies @@ -104,7 +105,7 @@ memcpy(s->block_last_index, zigzag_last_index, sizeof(int) * 6); for (n = 0; n < 6; n++) { - int16_t *ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + int16_t *ac_val = &s->ac_val[0][0][0] + s->block_index[n] * 16; st[n] = s->intra_scantable.permutated; if (dir[n]) { @@ -143,7 +144,7 @@ score -= get_block_rate(s, block[n], s->block_last_index[n], s->intra_scantable.permutated); - ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + ac_val = &s->ac_val[0][0][0] + s->block_index[n] * 16; ac_val1 = ac_val; if (dir[n]) { const int xy = s->mb_x + s->mb_y * s->mb_stride - s->mb_stride; @@ -960,9 +961,6 @@ { int vo_ver_id; - if (!CONFIG_MPEG4_ENCODER) - return; - if (s->max_b_frames || s->quarter_sample) { vo_ver_id = 5; s->vo_type = ADV_SIMPLE_VO_TYPE; @@ -1053,7 +1051,7 @@ if (!(s->avctx->flags & AV_CODEC_FLAG_BITEXACT)) { put_bits(&s->pb, 16, 0); put_bits(&s->pb, 16, 0x1B2); /* user_data */ - avpriv_put_string(&s->pb, LIBAVCODEC_IDENT, 0); + ff_put_string(&s->pb, LIBAVCODEC_IDENT, 0); } } @@ -1306,6 +1304,8 @@ if (s->avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { s->avctx->extradata = av_malloc(1024); + if (!s->avctx->extradata) + return AVERROR(ENOMEM); init_put_bits(&s->pb, s->avctx->extradata, 1024); if (!(s->workaround_bugs & FF_BUG_MS)) @@ -1353,8 +1353,8 @@ flush_put_bits(&s->tex_pb); set_put_bits_buffer_size(&s->pb, s->pb2.buf_end - s->pb.buf); - avpriv_copy_bits(&s->pb, s->pb2.buf, pb2_len); - avpriv_copy_bits(&s->pb, s->tex_pb.buf, tex_pb_len); + ff_copy_bits(&s->pb, s->pb2.buf, pb2_len); + ff_copy_bits(&s->pb, s->tex_pb.buf, tex_pb_len); s->last_bits = put_bits_count(&s->pb); } @@ -1376,6 +1376,7 @@ { "data_partitioning", "Use data partitioning.", OFFSET(data_partitioning), 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_COMMON_OPTS + FF_MPEG4_PROFILE_OPTS { NULL }, }; @@ -1397,5 +1398,6 @@ .close = ff_mpv_encode_end, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .priv_class = &mpeg4enc_class, }; diff -Nru ffmpeg-4.2.2/libavcodec/mpeg4video.h ffmpeg-4.4/libavcodec/mpeg4video.h --- ffmpeg-4.2.2/libavcodec/mpeg4video.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpeg4video.h 2021-04-08 21:28:39.000000000 +0000 @@ -115,10 +115,6 @@ int cplx_estimation_trash_p; int cplx_estimation_trash_b; - VLC studio_intra_tab[12]; - VLC studio_luma_dc; - VLC studio_chroma_dc; - int rgb; } Mpeg4DecContext; @@ -138,7 +134,7 @@ extern RLTable ff_rvlc_rl_inter; extern RLTable ff_rvlc_rl_intra; -extern const uint16_t ff_sprite_trajectory_tab[15][2]; +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 */ @@ -151,9 +147,9 @@ extern const uint8_t ff_mpeg4_dc_threshold[8]; -extern const uint16_t ff_mpeg4_studio_dc_luma[19][2]; -extern const uint16_t ff_mpeg4_studio_dc_chroma[19][2]; -extern const uint16_t ff_mpeg4_studio_intra[12][22][2]; +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], diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudiodata.h ffmpeg-4.4/libavcodec/mpegaudiodata.h --- ffmpeg-4.2.2/libavcodec/mpegaudiodata.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudiodata.h 2021-04-08 21:28:39.000000000 +0000 @@ -29,7 +29,10 @@ #include +#include "config.h" + #include "internal.h" +#include "vlc.h" #define MODE_EXT_MS_STEREO 2 #define MODE_EXT_I_STEREO 1 @@ -41,4 +44,40 @@ extern const int ff_mpa_quant_bits[17]; extern const unsigned char * const ff_mpa_alloc_tables[5]; +#define TABLE_4_3_SIZE ((8191 + 16)*4) +#if CONFIG_HARDCODED_TABLES +extern const int8_t ff_table_4_3_exp [TABLE_4_3_SIZE]; +extern const uint32_t ff_table_4_3_value[TABLE_4_3_SIZE]; +#else +extern int8_t ff_table_4_3_exp [TABLE_4_3_SIZE]; +extern uint32_t ff_table_4_3_value[TABLE_4_3_SIZE]; +#endif + +/* VLCs for decoding layer 3 huffman tables */ +extern VLC ff_huff_vlc[16]; +extern VLC ff_huff_quad_vlc[2]; + +/* layer3 scale factor size */ +extern const uint8_t ff_slen_table[2][16]; +/* number of lsf scale factors for a given size */ +extern const uint8_t ff_lsf_nsf_table[6][3][4]; +extern const uint8_t ff_mpa_huff_data[32][2]; + +/* band size tables */ +extern const uint8_t ff_band_size_long[9][22]; +extern const uint8_t ff_band_size_short[9][13]; +/* computed from ff_band_size_long */ +extern uint16_t ff_band_index_long[9][23]; + +extern int16_t *const ff_division_tabs[4]; + +/* lower 2 bits: modulo 3, higher bits: shift */ +extern uint16_t ff_scale_factor_modshift[64]; + +extern const uint8_t ff_mpa_pretab[2][22]; + +/* Initialize tables shared between the fixed and + * floating point MPEG audio decoders. */ +void ff_mpegaudiodec_common_init_static(void); + #endif /* AVCODEC_MPEGAUDIODATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudiodec_common.c ffmpeg-4.4/libavcodec/mpegaudiodec_common.c --- ffmpeg-4.2.2/libavcodec/mpegaudiodec_common.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudiodec_common.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,482 @@ +/* + * MPEG Audio decoder + * 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 + */ + +/** + * @file + * mpeg audio layer decoder tables. + */ + +#include +#include + +#include "libavutil/avassert.h" +#include "libavutil/thread.h" + +#include "mpegaudiodata.h" + +#include "mpegaudiodec_common_tablegen.h" + +uint16_t ff_scale_factor_modshift[64]; + +static int16_t division_tab3[1 << 6 ]; +static int16_t division_tab5[1 << 8 ]; +static int16_t division_tab9[1 << 11]; + +int16_t *const ff_division_tabs[4] = { + division_tab3, division_tab5, NULL, division_tab9 +}; + + +/*******************************************************/ +/* layer 3 tables */ + +const uint8_t ff_slen_table[2][16] = { + { 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 }, + { 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 }, +}; + +const uint8_t ff_lsf_nsf_table[6][3][4] = { + { { 6, 5, 5, 5 }, { 9, 9, 9, 9 }, { 6, 9, 9, 9 } }, + { { 6, 5, 7, 3 }, { 9, 9, 12, 6 }, { 6, 9, 12, 6 } }, + { { 11, 10, 0, 0 }, { 18, 18, 0, 0 }, { 15, 18, 0, 0 } }, + { { 7, 7, 7, 0 }, { 12, 12, 12, 0 }, { 6, 15, 12, 0 } }, + { { 6, 6, 6, 3 }, { 12, 9, 9, 6 }, { 6, 12, 9, 6 } }, + { { 8, 8, 5, 0 }, { 15, 12, 9, 0 }, { 6, 18, 9, 0 } }, +}; + +/* mpegaudio layer 3 huffman tables */ +VLC ff_huff_vlc[16]; +static VLC_TYPE huff_vlc_tables[128 + 128 + 128 + 130 + 128 + 154 + 166 + 142 + + 204 + 190 + 170 + 542 + 460 + 662 + 414][2]; +VLC ff_huff_quad_vlc[2]; +static VLC_TYPE huff_quad_vlc_tables[64 + 16][2]; + +static const uint8_t mpa_hufflens[] = { + /* Huffman table 1 - 4 entries */ + 3, 3, 2, 1, + /* Huffman table 2 - 9 entries */ + 6, 6, 5, 5, 5, 3, 3, 3, 1, + /* Huffman table 3 - 9 entries */ + 6, 6, 5, 5, 5, 3, 2, 2, 2, + /* Huffman table 5 - 16 entries */ + 8, 8, 7, 6, 7, 7, 7, 7, 6, 6, 6, 6, 3, 3, 3, 1, + /* Huffman table 6 - 16 entries */ + 7, 7, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 3, 2, 3, 3, + /* Huffman table 7 - 36 entries */ + 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 9, 9, 8, 9, 9, 8, 8, 7, 7, + 7, 8, 8, 8, 8, 7, 7, 7, 7, 6, 5, 6, 6, 4, 3, 3, 1, + /* Huffman table 8 - 36 entries */ + 11, 11, 10, 9, 10, 10, 9, 9, 9, 8, 8, 9, 9, 9, 9, 8, 8, 8, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 6, 4, 4, 2, 3, 3, 2, + /* Huffman table 9 - 36 entries */ + 9, 9, 8, 8, 9, 9, 8, 8, 8, 8, 7, 7, 7, 8, 8, 7, 7, 7, 7, + 6, 6, 6, 6, 5, 5, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, + /* Huffman table 10 - 64 entries */ + 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 11, 11, 10, 9, 9, 10, + 10, 9, 9, 10, 10, 9, 10, 10, 8, 8, 9, 9, 10, 10, 9, 9, 10, 10, 8, + 8, 8, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, + 6, 6, 6, 4, 3, 3, 1, + /* Huffman table 11 - 64 entries */ + 10, 10, 10, 10, 10, 10, 10, 11, 11, 10, 10, 9, 9, 9, 10, 10, 10, 10, 8, + 8, 9, 9, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 8, 7, 8, 8, 7, 7, + 8, 8, 8, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, 6, 6, 7, 7, 6, 5, + 4, 5, 5, 3, 3, 3, 2, + /* Huffman table 12 - 64 entries */ + 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 9, 9, 8, 8, 8, 8, 8, 8, + 9, 9, 8, 8, 8, 8, 8, 9, 9, 7, 7, 7, 8, 8, 8, 8, 8, 8, 7, + 7, 7, 7, 8, 8, 7, 7, 7, 6, 6, 6, 6, 7, 7, 6, 5, 5, 5, 4, + 4, 5, 5, 4, 3, 3, 3, + /* Huffman table 13 - 256 entries */ + 19, 19, 18, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 15, 15, 16, + 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 15, 16, 16, 14, 14, 15, + 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 14, 13, 14, + 14, 13, 13, 14, 14, 13, 14, 14, 13, 14, 14, 13, 14, 14, 13, 13, 14, 14, 12, + 12, 12, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 12, 12, 13, 13, 12, 12, 12, 12, 13, 13, 13, 13, 12, + 13, 13, 12, 11, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 12, 12, 11, + 11, 12, 12, 11, 12, 12, 12, 12, 11, 11, 12, 12, 11, 12, 12, 11, 12, 12, 11, + 12, 12, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 11, 11, + 10, 11, 11, 10, 11, 11, 11, 11, 10, 10, 11, 11, 10, 10, 11, 11, 11, 11, 11, + 11, 9, 9, 10, 10, 10, 10, 10, 11, 11, 9, 9, 9, 10, 10, 9, 9, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 8, 9, 9, 9, 9, 9, 9, 10, 10, 9, 9, + 9, 8, 8, 9, 9, 9, 9, 9, 9, 8, 7, 8, 8, 8, 8, 7, 7, 7, 7, + 7, 6, 6, 6, 6, 4, 4, 3, 1, + /* Huffman table 15 - 256 entries */ + 13, 13, 13, 13, 12, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, + 13, 11, 11, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 12, 12, 11, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 11, 11, 11, 11, 11, + 11, 10, 11, 11, 11, 11, 11, 11, 10, 10, 11, 11, 10, 10, 10, 10, 11, 11, 10, + 10, 10, 10, 10, 10, 10, 11, 11, 10, 10, 10, 10, 10, 11, 11, 9, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 10, 10, 10, 10, 9, 10, 10, 9, 10, + 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 10, 10, 9, 9, 9, + 9, 9, 9, 10, 10, 9, 9, 9, 9, 9, 9, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, + 8, 8, 9, 9, 8, 8, 8, 8, 8, 8, 8, 9, 9, 8, 7, 8, 8, 7, 7, + 7, 7, 8, 8, 7, 7, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, + 5, 5, 5, 5, 5, 3, 4, 4, 3, + /* Huffman table 16 - 256 entries */ + 11, 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 11, 11, 10, 10, 10, 10, 10, 8, + 10, 10, 9, 9, 9, 9, 10, 16, 17, 17, 15, 15, 16, 16, 14, 15, 15, 14, 14, + 15, 15, 14, 14, 15, 15, 15, 15, 14, 15, 15, 14, 13, 8, 9, 9, 8, 8, 13, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 14, 14, 14, 14, 13, 14, 14, + 13, 13, 13, 14, 14, 14, 14, 13, 13, 14, 14, 13, 14, 14, 12, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 13, 13, 13, 13, 13, 12, 13, + 13, 12, 12, 13, 13, 11, 12, 12, 12, 12, 12, 12, 12, 13, 13, 11, 12, 12, 12, + 12, 11, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 12, 12, 11, 12, 12, 11, 12, 12, 11, + 10, 10, 11, 11, 11, 11, 11, 11, 10, 10, 11, 11, 10, 10, 11, 11, 11, 11, 11, + 11, 11, 11, 10, 11, 11, 10, 10, 10, 11, 11, 10, 10, 11, 11, 10, 10, 11, 11, + 10, 9, 9, 10, 10, 10, 10, 10, 10, 9, 9, 9, 10, 10, 9, 10, 10, 9, 9, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 9, 9, 8, 8, 7, 7, 8, 8, + 7, 6, 6, 6, 6, 4, 4, 3, 1, + /* Huffman table 24 - 256 entries */ + 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 8, 7, 7, 8, 8, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 9, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 4, 11, 11, 11, 11, 12, 12, 11, 10, 11, 11, 10, 10, 10, 10, 11, 11, 10, + 10, 10, 10, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 10, 11, 11, 10, 9, 10, 10, 10, 10, 11, 11, 10, 9, 9, 10, + 10, 9, 10, 10, 10, 10, 9, 9, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 9, 9, 9, 10, 10, 8, 9, 9, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 8, 8, 8, 8, 8, + 8, 9, 9, 7, 8, 8, 7, 7, 7, 7, 7, 8, 8, 7, 7, 6, 6, 7, 7, + 6, 5, 5, 6, 6, 4, 4, 4, 4, +}; + +static const uint8_t mpa_huffsymbols[] = { + /* Huffman table 1 - 4 entries */ + 0x11, 0x01, 0x10, 0x00, + /* Huffman table 2 - 9 entries */ + 0x22, 0x02, 0x12, 0x21, 0x20, 0x11, 0x01, 0x10, 0x00, + /* Huffman table 3 - 9 entries */ + 0x22, 0x02, 0x12, 0x21, 0x20, 0x10, 0x11, 0x01, 0x00, + /* Huffman table 5 - 16 entries */ + 0x33, 0x23, 0x32, 0x31, 0x13, 0x03, 0x30, 0x22, 0x12, 0x21, 0x02, 0x20, + 0x11, 0x01, 0x10, 0x00, + /* Huffman table 6 - 16 entries */ + 0x33, 0x03, 0x23, 0x32, 0x30, 0x13, 0x31, 0x22, 0x02, 0x12, 0x21, 0x20, + 0x01, 0x11, 0x10, 0x00, + /* Huffman table 7 - 36 entries */ + 0x55, 0x45, 0x54, 0x53, 0x35, 0x44, 0x25, 0x52, 0x15, 0x51, 0x05, 0x34, + 0x50, 0x43, 0x33, 0x24, 0x42, 0x14, 0x41, 0x40, 0x04, 0x23, 0x32, 0x03, + 0x13, 0x31, 0x30, 0x22, 0x12, 0x21, 0x02, 0x20, 0x11, 0x01, 0x10, 0x00, + /* Huffman table 8 - 36 entries */ + 0x55, 0x54, 0x45, 0x53, 0x35, 0x44, 0x25, 0x52, 0x05, 0x15, 0x51, 0x34, + 0x43, 0x50, 0x33, 0x24, 0x42, 0x14, 0x41, 0x04, 0x40, 0x23, 0x32, 0x13, + 0x31, 0x03, 0x30, 0x22, 0x02, 0x20, 0x12, 0x21, 0x11, 0x01, 0x10, 0x00, + /* Huffman table 9 - 36 entries */ + 0x55, 0x45, 0x35, 0x53, 0x54, 0x05, 0x44, 0x25, 0x52, 0x15, 0x51, 0x34, + 0x43, 0x50, 0x04, 0x24, 0x42, 0x33, 0x40, 0x14, 0x41, 0x23, 0x32, 0x13, + 0x31, 0x03, 0x30, 0x22, 0x02, 0x12, 0x21, 0x20, 0x11, 0x01, 0x10, 0x00, + /* Huffman table 10 - 64 entries */ + 0x77, 0x67, 0x76, 0x57, 0x75, 0x66, 0x47, 0x74, 0x56, 0x65, 0x37, 0x73, + 0x46, 0x55, 0x54, 0x63, 0x27, 0x72, 0x64, 0x07, 0x70, 0x62, 0x45, 0x35, + 0x06, 0x53, 0x44, 0x17, 0x71, 0x36, 0x26, 0x25, 0x52, 0x15, 0x51, 0x34, + 0x43, 0x16, 0x61, 0x60, 0x05, 0x50, 0x24, 0x42, 0x33, 0x04, 0x14, 0x41, + 0x40, 0x23, 0x32, 0x03, 0x13, 0x31, 0x30, 0x22, 0x12, 0x21, 0x02, 0x20, + 0x11, 0x01, 0x10, 0x00, + /* Huffman table 11 - 64 entries */ + 0x77, 0x67, 0x76, 0x75, 0x66, 0x47, 0x74, 0x57, 0x55, 0x56, 0x65, 0x37, + 0x73, 0x46, 0x45, 0x54, 0x35, 0x53, 0x27, 0x72, 0x64, 0x07, 0x71, 0x17, + 0x70, 0x36, 0x63, 0x60, 0x44, 0x25, 0x52, 0x05, 0x15, 0x62, 0x26, 0x06, + 0x16, 0x61, 0x51, 0x34, 0x50, 0x43, 0x33, 0x24, 0x42, 0x14, 0x41, 0x04, + 0x40, 0x23, 0x32, 0x13, 0x31, 0x03, 0x30, 0x22, 0x21, 0x12, 0x02, 0x20, + 0x11, 0x01, 0x10, 0x00, + /* Huffman table 12 - 64 entries */ + 0x77, 0x67, 0x76, 0x57, 0x75, 0x66, 0x47, 0x74, 0x65, 0x56, 0x37, 0x73, + 0x55, 0x27, 0x72, 0x46, 0x64, 0x17, 0x71, 0x07, 0x70, 0x36, 0x63, 0x45, + 0x54, 0x44, 0x06, 0x05, 0x26, 0x62, 0x61, 0x16, 0x60, 0x35, 0x53, 0x25, + 0x52, 0x15, 0x51, 0x34, 0x43, 0x50, 0x04, 0x24, 0x42, 0x14, 0x33, 0x41, + 0x23, 0x32, 0x40, 0x03, 0x30, 0x13, 0x31, 0x22, 0x12, 0x21, 0x02, 0x20, + 0x00, 0x11, 0x01, 0x10, + /* Huffman table 13 - 256 entries */ + 0xFE, 0xFC, 0xFD, 0xED, 0xFF, 0xEF, 0xDF, 0xEE, 0xCF, 0xDE, 0xBF, 0xFB, + 0xCE, 0xDC, 0xAF, 0xE9, 0xEC, 0xDD, 0xFA, 0xCD, 0xBE, 0xEB, 0x9F, 0xF9, + 0xEA, 0xBD, 0xDB, 0x8F, 0xF8, 0xCC, 0xAE, 0x9E, 0x8E, 0x7F, 0x7E, 0xF7, + 0xDA, 0xAD, 0xBC, 0xCB, 0xF6, 0x6F, 0xE8, 0x5F, 0x9D, 0xD9, 0xF5, 0xE7, + 0xAC, 0xBB, 0x4F, 0xF4, 0xCA, 0xE6, 0xF3, 0x3F, 0x8D, 0xD8, 0x2F, 0xF2, + 0x6E, 0x9C, 0x0F, 0xC9, 0x5E, 0xAB, 0x7D, 0xD7, 0x4E, 0xC8, 0xD6, 0x3E, + 0xB9, 0x9B, 0xAA, 0x1F, 0xF1, 0xF0, 0xBA, 0xE5, 0xE4, 0x8C, 0x6D, 0xE3, + 0xE2, 0x2E, 0x0E, 0x1E, 0xE1, 0xE0, 0x5D, 0xD5, 0x7C, 0xC7, 0x4D, 0x8B, + 0xB8, 0xD4, 0x9A, 0xA9, 0x6C, 0xC6, 0x3D, 0xD3, 0x7B, 0x2D, 0xD2, 0x1D, + 0xB7, 0x5C, 0xC5, 0x99, 0x7A, 0xC3, 0xA7, 0x97, 0x4B, 0xD1, 0x0D, 0xD0, + 0x8A, 0xA8, 0x4C, 0xC4, 0x6B, 0xB6, 0x3C, 0x2C, 0xC2, 0x5B, 0xB5, 0x89, + 0x1C, 0xC1, 0x98, 0x0C, 0xC0, 0xB4, 0x6A, 0xA6, 0x79, 0x3B, 0xB3, 0x88, + 0x5A, 0x2B, 0xA5, 0x69, 0xA4, 0x78, 0x87, 0x94, 0x77, 0x76, 0xB2, 0x1B, + 0xB1, 0x0B, 0xB0, 0x96, 0x4A, 0x3A, 0xA3, 0x59, 0x95, 0x2A, 0xA2, 0x1A, + 0xA1, 0x0A, 0x68, 0xA0, 0x86, 0x49, 0x93, 0x39, 0x58, 0x85, 0x67, 0x29, + 0x92, 0x57, 0x75, 0x38, 0x83, 0x66, 0x47, 0x74, 0x56, 0x65, 0x73, 0x19, + 0x91, 0x09, 0x90, 0x48, 0x84, 0x72, 0x46, 0x64, 0x28, 0x82, 0x18, 0x37, + 0x27, 0x17, 0x71, 0x55, 0x07, 0x70, 0x36, 0x63, 0x45, 0x54, 0x26, 0x62, + 0x35, 0x81, 0x08, 0x80, 0x16, 0x61, 0x06, 0x60, 0x53, 0x44, 0x25, 0x52, + 0x05, 0x15, 0x51, 0x34, 0x43, 0x50, 0x24, 0x42, 0x33, 0x14, 0x41, 0x04, + 0x40, 0x23, 0x32, 0x13, 0x31, 0x03, 0x30, 0x22, 0x12, 0x21, 0x02, 0x20, + 0x11, 0x01, 0x10, 0x00, + /* Huffman table 15 - 256 entries */ + 0xFF, 0xEF, 0xFE, 0xDF, 0xEE, 0xFD, 0xCF, 0xFC, 0xDE, 0xED, 0xBF, 0xFB, + 0xCE, 0xEC, 0xDD, 0xAF, 0xFA, 0xBE, 0xEB, 0xCD, 0xDC, 0x9F, 0xF9, 0xEA, + 0xBD, 0xDB, 0x8F, 0xF8, 0xCC, 0x9E, 0xE9, 0x7F, 0xF7, 0xAD, 0xDA, 0xBC, + 0x6F, 0xAE, 0x0F, 0xCB, 0xF6, 0x8E, 0xE8, 0x5F, 0x9D, 0xF5, 0x7E, 0xE7, + 0xAC, 0xCA, 0xBB, 0xD9, 0x8D, 0x4F, 0xF4, 0x3F, 0xF3, 0xD8, 0xE6, 0x2F, + 0xF2, 0x6E, 0xF0, 0x1F, 0xF1, 0x9C, 0xC9, 0x5E, 0xAB, 0xBA, 0xE5, 0x7D, + 0xD7, 0x4E, 0xE4, 0x8C, 0xC8, 0x3E, 0x6D, 0xD6, 0xE3, 0x9B, 0xB9, 0x2E, + 0xAA, 0xE2, 0x1E, 0xE1, 0x0E, 0xE0, 0x5D, 0xD5, 0x7C, 0xC7, 0x4D, 0x8B, + 0xD4, 0xB8, 0x9A, 0xA9, 0x6C, 0xC6, 0x3D, 0xD3, 0xD2, 0x2D, 0x0D, 0x1D, + 0x7B, 0xB7, 0xD1, 0x5C, 0xD0, 0xC5, 0x8A, 0xA8, 0x4C, 0xC4, 0x6B, 0xB6, + 0x99, 0x0C, 0x3C, 0xC3, 0x7A, 0xA7, 0xA6, 0xC0, 0x0B, 0xC2, 0x2C, 0x5B, + 0xB5, 0x1C, 0x89, 0x98, 0xC1, 0x4B, 0xB4, 0x6A, 0x3B, 0x79, 0xB3, 0x97, + 0x88, 0x2B, 0x5A, 0xB2, 0xA5, 0x1B, 0xB1, 0xB0, 0x69, 0x96, 0x4A, 0xA4, + 0x78, 0x87, 0x3A, 0xA3, 0x59, 0x95, 0x2A, 0xA2, 0x1A, 0xA1, 0x0A, 0xA0, + 0x68, 0x86, 0x49, 0x94, 0x39, 0x93, 0x77, 0x09, 0x58, 0x85, 0x29, 0x67, + 0x76, 0x92, 0x91, 0x19, 0x90, 0x48, 0x84, 0x57, 0x75, 0x38, 0x83, 0x66, + 0x47, 0x28, 0x82, 0x18, 0x81, 0x74, 0x08, 0x80, 0x56, 0x65, 0x37, 0x73, + 0x46, 0x27, 0x72, 0x64, 0x17, 0x55, 0x71, 0x07, 0x70, 0x36, 0x63, 0x45, + 0x54, 0x26, 0x62, 0x16, 0x06, 0x60, 0x35, 0x61, 0x53, 0x44, 0x25, 0x52, + 0x15, 0x51, 0x05, 0x50, 0x34, 0x43, 0x24, 0x42, 0x33, 0x41, 0x14, 0x04, + 0x23, 0x32, 0x40, 0x03, 0x13, 0x31, 0x30, 0x22, 0x12, 0x21, 0x02, 0x20, + 0x11, 0x01, 0x10, 0x00, + /* Huffman table 16 - 256 entries */ + 0xEF, 0xFE, 0xDF, 0xFD, 0xCF, 0xFC, 0xBF, 0xFB, 0xAF, 0xFA, 0x9F, 0xF9, + 0xF8, 0x8F, 0x7F, 0xF7, 0x6F, 0xF6, 0xFF, 0x5F, 0xF5, 0x4F, 0xF4, 0xF3, + 0xF0, 0x3F, 0xCE, 0xEC, 0xDD, 0xDE, 0xE9, 0xEA, 0xD9, 0xEE, 0xED, 0xEB, + 0xBE, 0xCD, 0xDC, 0xDB, 0xAE, 0xCC, 0xAD, 0xDA, 0x7E, 0xAC, 0xCA, 0xC9, + 0x7D, 0x5E, 0xBD, 0xF2, 0x2F, 0x0F, 0x1F, 0xF1, 0x9E, 0xBC, 0xCB, 0x8E, + 0xE8, 0x9D, 0xE7, 0xBB, 0x8D, 0xD8, 0x6E, 0xE6, 0x9C, 0xAB, 0xBA, 0xE5, + 0xD7, 0x4E, 0xE4, 0x8C, 0xC8, 0x3E, 0x6D, 0xD6, 0x9B, 0xB9, 0xAA, 0xE1, + 0xD4, 0xB8, 0xA9, 0x7B, 0xB7, 0xD0, 0xE3, 0x0E, 0xE0, 0x5D, 0xD5, 0x7C, + 0xC7, 0x4D, 0x8B, 0x9A, 0x6C, 0xC6, 0x3D, 0x5C, 0xC5, 0x0D, 0x8A, 0xA8, + 0x99, 0x4C, 0xB6, 0x7A, 0x3C, 0x5B, 0x89, 0x1C, 0xC0, 0x98, 0x79, 0xE2, + 0x2E, 0x1E, 0xD3, 0x2D, 0xD2, 0xD1, 0x3B, 0x97, 0x88, 0x1D, 0xC4, 0x6B, + 0xC3, 0xA7, 0x2C, 0xC2, 0xB5, 0xC1, 0x0C, 0x4B, 0xB4, 0x6A, 0xA6, 0xB3, + 0x5A, 0xA5, 0x2B, 0xB2, 0x1B, 0xB1, 0x0B, 0xB0, 0x69, 0x96, 0x4A, 0xA4, + 0x78, 0x87, 0xA3, 0x3A, 0x59, 0x2A, 0x95, 0x68, 0xA1, 0x86, 0x77, 0x94, + 0x49, 0x57, 0x67, 0xA2, 0x1A, 0x0A, 0xA0, 0x39, 0x93, 0x58, 0x85, 0x29, + 0x92, 0x76, 0x09, 0x19, 0x91, 0x90, 0x48, 0x84, 0x75, 0x38, 0x83, 0x66, + 0x28, 0x82, 0x47, 0x74, 0x18, 0x81, 0x80, 0x08, 0x56, 0x37, 0x73, 0x65, + 0x46, 0x27, 0x72, 0x64, 0x55, 0x07, 0x17, 0x71, 0x70, 0x36, 0x63, 0x45, + 0x54, 0x26, 0x62, 0x16, 0x61, 0x06, 0x60, 0x53, 0x35, 0x44, 0x25, 0x52, + 0x51, 0x15, 0x05, 0x34, 0x43, 0x50, 0x24, 0x42, 0x33, 0x14, 0x41, 0x04, + 0x40, 0x23, 0x32, 0x13, 0x31, 0x03, 0x30, 0x22, 0x12, 0x21, 0x02, 0x20, + 0x11, 0x01, 0x10, 0x00, + /* Huffman table 24 - 256 entries */ + 0xEF, 0xFE, 0xDF, 0xFD, 0xCF, 0xFC, 0xBF, 0xFB, 0xFA, 0xAF, 0x9F, 0xF9, + 0xF8, 0x8F, 0x7F, 0xF7, 0x6F, 0xF6, 0x5F, 0xF5, 0x4F, 0xF4, 0x3F, 0xF3, + 0x2F, 0xF2, 0xF1, 0x1F, 0xF0, 0x0F, 0xEE, 0xDE, 0xED, 0xCE, 0xEC, 0xDD, + 0xBE, 0xEB, 0xCD, 0xDC, 0xAE, 0xEA, 0xBD, 0xDB, 0xCC, 0x9E, 0xE9, 0xAD, + 0xDA, 0xBC, 0xCB, 0x8E, 0xE8, 0x9D, 0xD9, 0x7E, 0xE7, 0xAC, 0xFF, 0xCA, + 0xBB, 0x8D, 0xD8, 0x0E, 0xE0, 0x0D, 0xE6, 0x6E, 0x9C, 0xC9, 0x5E, 0xBA, + 0xE5, 0xAB, 0x7D, 0xD7, 0xE4, 0x8C, 0xC8, 0x4E, 0x2E, 0x3E, 0x6D, 0xD6, + 0xE3, 0x9B, 0xB9, 0xAA, 0xE2, 0x1E, 0xE1, 0x5D, 0xD5, 0x7C, 0xC7, 0x4D, + 0x8B, 0xB8, 0xD4, 0x9A, 0xA9, 0x6C, 0xC6, 0x3D, 0xD3, 0x2D, 0xD2, 0x1D, + 0x7B, 0xB7, 0xD1, 0x5C, 0xC5, 0x8A, 0xA8, 0x99, 0x4C, 0xC4, 0x6B, 0xB6, + 0xD0, 0x0C, 0x3C, 0xC3, 0x7A, 0xA7, 0x2C, 0xC2, 0x5B, 0xB5, 0x1C, 0x89, + 0x98, 0xC1, 0x4B, 0xC0, 0x0B, 0x3B, 0xB0, 0x0A, 0x1A, 0xB4, 0x6A, 0xA6, + 0x79, 0x97, 0xA0, 0x09, 0x90, 0xB3, 0x88, 0x2B, 0x5A, 0xB2, 0xA5, 0x1B, + 0xB1, 0x69, 0x96, 0xA4, 0x4A, 0x78, 0x87, 0x3A, 0xA3, 0x59, 0x95, 0x2A, + 0xA2, 0xA1, 0x68, 0x86, 0x77, 0x49, 0x94, 0x39, 0x93, 0x58, 0x85, 0x29, + 0x67, 0x76, 0x92, 0x19, 0x91, 0x48, 0x84, 0x57, 0x75, 0x38, 0x83, 0x66, + 0x28, 0x82, 0x18, 0x47, 0x74, 0x81, 0x08, 0x80, 0x56, 0x65, 0x17, 0x07, + 0x70, 0x73, 0x37, 0x27, 0x72, 0x46, 0x64, 0x55, 0x71, 0x36, 0x63, 0x45, + 0x54, 0x26, 0x62, 0x16, 0x61, 0x06, 0x60, 0x35, 0x53, 0x44, 0x25, 0x52, + 0x15, 0x05, 0x50, 0x51, 0x34, 0x43, 0x24, 0x42, 0x33, 0x14, 0x41, 0x04, + 0x40, 0x23, 0x32, 0x13, 0x31, 0x03, 0x30, 0x22, 0x12, 0x21, 0x02, 0x20, + 0x11, 0x01, 0x10, 0x00, +}; + +static const uint8_t mpa_huff_sizes_minus_one[] = +{ + 3, 8, 8, 15, 15, 35, 35, 35, 63, 63, 63, 255, 255, 255, 255 +}; + +const uint8_t ff_mpa_huff_data[32][2] = { +{ 0, 0 }, +{ 1, 0 }, +{ 2, 0 }, +{ 3, 0 }, +{ 0, 0 }, +{ 4, 0 }, +{ 5, 0 }, +{ 6, 0 }, +{ 7, 0 }, +{ 8, 0 }, +{ 9, 0 }, +{ 10, 0 }, +{ 11, 0 }, +{ 12, 0 }, +{ 0, 0 }, +{ 13, 0 }, +{ 14, 1 }, +{ 14, 2 }, +{ 14, 3 }, +{ 14, 4 }, +{ 14, 6 }, +{ 14, 8 }, +{ 14, 10 }, +{ 14, 13 }, +{ 15, 4 }, +{ 15, 5 }, +{ 15, 6 }, +{ 15, 7 }, +{ 15, 8 }, +{ 15, 9 }, +{ 15, 11 }, +{ 15, 13 }, +}; + + +/* huffman tables for quadrules */ +static const uint8_t mpa_quad_codes[2][16] = { + { 1, 5, 4, 5, 6, 5, 4, 4, 7, 3, 6, 0, 7, 2, 3, 1, }, + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, }, +}; + +static const uint8_t mpa_quad_bits[2][16] = { + { 1, 4, 4, 5, 4, 6, 5, 6, 4, 5, 5, 6, 5, 6, 6, 6, }, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, }, +}; + +const uint8_t ff_band_size_long[9][22] = { +{ 4, 4, 4, 4, 4, 4, 6, 6, 8, 8, 10, + 12, 16, 20, 24, 28, 34, 42, 50, 54, 76, 158, }, /* 44100 */ +{ 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, 10, + 12, 16, 18, 22, 28, 34, 40, 46, 54, 54, 192, }, /* 48000 */ +{ 4, 4, 4, 4, 4, 4, 6, 6, 8, 10, 12, + 16, 20, 24, 30, 38, 46, 56, 68, 84, 102, 26, }, /* 32000 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 22050 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 18, 22, 26, 32, 38, 46, 52, 64, 70, 76, 36, }, /* 24000 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 16000 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 11025 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 12000 */ +{ 12, 12, 12, 12, 12, 12, 16, 20, 24, 28, 32, + 40, 48, 56, 64, 76, 90, 2, 2, 2, 2, 2, }, /* 8000 */ +}; + +const uint8_t ff_band_size_short[9][13] = { +{ 4, 4, 4, 4, 6, 8, 10, 12, 14, 18, 22, 30, 56, }, /* 44100 */ +{ 4, 4, 4, 4, 6, 6, 10, 12, 14, 16, 20, 26, 66, }, /* 48000 */ +{ 4, 4, 4, 4, 6, 8, 12, 16, 20, 26, 34, 42, 12, }, /* 32000 */ +{ 4, 4, 4, 6, 6, 8, 10, 14, 18, 26, 32, 42, 18, }, /* 22050 */ +{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 32, 44, 12, }, /* 24000 */ +{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18, }, /* 16000 */ +{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18, }, /* 11025 */ +{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18, }, /* 12000 */ +{ 8, 8, 8, 12, 16, 20, 24, 28, 36, 2, 2, 2, 26, }, /* 8000 */ +}; + +uint16_t ff_band_index_long[9][23]; + +const uint8_t ff_mpa_pretab[2][22] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 }, +}; + +static av_cold void mpegaudiodec_common_init_static(void) +{ + const uint8_t *huff_sym = mpa_huffsymbols, *huff_lens = mpa_hufflens; + int offset; + + /* scale factors table for layer 1/2 */ + for (int i = 0; i < 64; i++) { + int shift, mod; + /* 1.0 (i = 3) is normalized to 2 ^ FRAC_BITS */ + shift = i / 3; + mod = i % 3; + ff_scale_factor_modshift[i] = mod | (shift << 2); + } + + /* huffman decode tables */ + offset = 0; + for (int i = 0; i < 15;) { + uint16_t tmp_symbols[256]; + int nb_codes_minus_one = mpa_huff_sizes_minus_one[i]; + int j; + + for (j = 0; j <= nb_codes_minus_one; j++) { + uint8_t high = huff_sym[j] & 0xF0, low = huff_sym[j] & 0xF; + + tmp_symbols[j] = high << 1 | ((high && low) << 4) | low; + } + + ff_huff_vlc[++i].table = huff_vlc_tables + offset; + ff_huff_vlc[i].table_allocated = FF_ARRAY_ELEMS(huff_vlc_tables) - offset; + ff_init_vlc_from_lengths(&ff_huff_vlc[i], 7, j, + huff_lens, 1, tmp_symbols, 2, 2, + 0, INIT_VLC_STATIC_OVERLONG, NULL); + offset += ff_huff_vlc[i].table_size; + huff_lens += j; + huff_sym += j; + } + av_assert0(offset == FF_ARRAY_ELEMS(huff_vlc_tables)); + + offset = 0; + for (int i = 0; i < 2; i++) { + int bits = i == 0 ? 6 : 4; + ff_huff_quad_vlc[i].table = huff_quad_vlc_tables + offset; + ff_huff_quad_vlc[i].table_allocated = 1 << bits; + offset += 1 << bits; + init_vlc(&ff_huff_quad_vlc[i], bits, 16, + mpa_quad_bits[i], 1, 1, mpa_quad_codes[i], 1, 1, + INIT_VLC_USE_NEW_STATIC); + } + av_assert0(offset == FF_ARRAY_ELEMS(huff_quad_vlc_tables)); + + for (int i = 0; i < 9; i++) { + int k = 0; + for (int j = 0; j < 22; j++) { + ff_band_index_long[i][j] = k; + k += ff_band_size_long[i][j] >> 1; + } + ff_band_index_long[i][22] = k; + } + + for (int i = 0; i < 4; i++) { + if (ff_mpa_quant_bits[i] < 0) { + for (int j = 0; j < (1 << (-ff_mpa_quant_bits[i] + 1)); j++) { + int val1, val2, val3, steps; + int val = j; + steps = ff_mpa_quant_steps[i]; + val1 = val % steps; + val /= steps; + val2 = val % steps; + val3 = val / steps; + ff_division_tabs[i][j] = val1 + (val2 << 4) + (val3 << 8); + } + } + } + mpegaudiodec_common_tableinit(); +} + +av_cold void ff_mpegaudiodec_common_init_static(void) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + + ff_thread_once(&init_static_once, mpegaudiodec_common_init_static); +} diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudiodec_common_tablegen.c ffmpeg-4.4/libavcodec/mpegaudiodec_common_tablegen.c --- ffmpeg-4.2.2/libavcodec/mpegaudiodec_common_tablegen.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudiodec_common_tablegen.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Generate a header file for hardcoded shared mpegaudiodec tables + * + * Copyright (c) 2009 Reimar Döffinger + * Copyright (c) 2020 Andreas Rheinhardt + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#define CONFIG_HARDCODED_TABLES 0 +#include "libavutil/tablegen.h" +#include "mpegaudiodec_common_tablegen.h" +#include "tableprint.h" + +int main(void) +{ + mpegaudiodec_common_tableinit(); + + write_fileheader(); + + WRITE_ARRAY("const", int8_t, ff_table_4_3_exp); + WRITE_ARRAY("const", uint32_t, ff_table_4_3_value); + + return 0; +} diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudiodec_common_tablegen.h ffmpeg-4.4/libavcodec/mpegaudiodec_common_tablegen.h --- ffmpeg-4.2.2/libavcodec/mpegaudiodec_common_tablegen.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudiodec_common_tablegen.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * Header file for hardcoded shared mpegaudiodec tables + * + * Copyright (c) 2009 Reimar Döffinger + * Copyright (c) 2020 Andreas Rheinhardt + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MPEGAUDIODEC_COMMON_TABLEGEN_H +#define AVCODEC_MPEGAUDIODEC_COMMON_TABLEGEN_H + +#include + +#define TABLE_4_3_SIZE ((8191 + 16)*4) + +#if CONFIG_HARDCODED_TABLES +#define mpegaudiodec_common_tableinit() +#include "libavcodec/mpegaudiodec_common_tables.h" +#else +#include +#include "libavutil/attributes.h" + +int8_t ff_table_4_3_exp [TABLE_4_3_SIZE]; +uint32_t ff_table_4_3_value[TABLE_4_3_SIZE]; + +#define FRAC_BITS 23 +#define IMDCT_SCALAR 1.759 + +static av_cold void mpegaudiodec_common_tableinit(void) +{ + static const double exp2_lut[4] = { + 1.00000000000000000000, /* 2 ^ (0 * 0.25) */ + 1.18920711500272106672, /* 2 ^ (1 * 0.25) */ + M_SQRT2 , /* 2 ^ (2 * 0.25) */ + 1.68179283050742908606, /* 2 ^ (3 * 0.25) */ + }; + double pow43_val = 0; + + for (int i = 1; i < TABLE_4_3_SIZE; i++) { + double f, fm; + int e, m; + double value = i / 4; + if ((i & 3) == 0) + pow43_val = value / IMDCT_SCALAR * cbrt(value); + f = pow43_val * exp2_lut[i & 3]; + fm = frexp(f, &e); + m = llrint(fm * (1LL << 31)); + e += FRAC_BITS - 31 + 5 - 100; + + /* normalized to FRAC_BITS */ + ff_table_4_3_value[i] = m; + ff_table_4_3_exp [i] = -e; + } +} + +#endif /* CONFIG_HARDCODED_TABLES */ +#endif /* AVCODEC_MPEGAUDIODEC_COMMON_TABLEGEN_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudiodec_fixed.c ffmpeg-4.4/libavcodec/mpegaudiodec_fixed.c --- ffmpeg-4.2.2/libavcodec/mpegaudiodec_fixed.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudiodec_fixed.c 2021-04-08 21:28:39.000000000 +0000 @@ -36,6 +36,26 @@ #define OUT_FMT AV_SAMPLE_FMT_S16 #define OUT_FMT_P AV_SAMPLE_FMT_S16P +/* Intensity stereo table. See commit b91d46614df189e7905538e7f5c4ed9c7ed0d274 + * (float based mp1/mp2/mp3 decoders.) for how they were created. */ +static const int32_t is_table[2][16] = { + { 0x000000, 0x1B0CB1, 0x2ED9EC, 0x400000, 0x512614, 0x64F34F, 0x800000 }, + { 0x800000, 0x64F34F, 0x512614, 0x400000, 0x2ED9EC, 0x1B0CB1, 0x000000 } +}; + +/* Antialiasing table. See commit ce4a29c066cddfc180979ed86396812f24337985 + * (optimize antialias) for how they were created. */ +static const int32_t csa_table[8][4] = { + { 0x36E129F8, 0xDF128056, 0x15F3AA4E, 0xA831565E }, + { 0x386E75F2, 0xE1CF24A5, 0x1A3D9A97, 0xA960AEB3 }, + { 0x3CC6B73A, 0xEBF19FA6, 0x28B856E0, 0xAF2AE86C }, + { 0x3EEEA054, 0xF45B88BC, 0x334A2910, 0xB56CE868 }, + { 0x3FB6905C, 0xF9F27F18, 0x39A90F74, 0xBA3BEEBC }, + { 0x3FF23F20, 0xFD60D1E4, 0x3D531104, 0xBD6E92C4 }, + { 0x3FFE5932, 0xFF175EE4, 0x3F15B816, 0xBF1905B2 }, + { 0x3FFFE34A, 0xFFC3612F, 0x3FC34479, 0xBFC37DE5 } +}; + #include "mpegaudiodec_template.c" #if CONFIG_MP1_DECODER @@ -47,11 +67,13 @@ .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP2_DECODER @@ -63,11 +85,13 @@ .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP3_DECODER @@ -79,11 +103,13 @@ .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP3ADU_DECODER @@ -95,11 +121,13 @@ .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame_adu, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP3ON4_DECODER @@ -112,9 +140,11 @@ .init = decode_init_mp3on4, .close = decode_close_mp3on4, .decode = decode_frame_mp3on4, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .flush = flush_mp3on4, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudiodec_float.c ffmpeg-4.4/libavcodec/mpegaudiodec_float.c --- ffmpeg-4.2.2/libavcodec/mpegaudiodec_float.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudiodec_float.c 2021-04-08 21:28:39.000000000 +0000 @@ -36,6 +36,39 @@ #define OUT_FMT AV_SAMPLE_FMT_FLT #define OUT_FMT_P AV_SAMPLE_FMT_FLTP +/* Intensity stereo table. See commit b91d46614df189e7905538e7f5c4ed9c7ed0d274 + * (float based mp1/mp2/mp3 decoders.) for how they were created. */ +static const float is_table[2][16] = { + { 0.000000000000000000e+00, 2.113248705863952637e-01, 3.660253882408142090e-01, + 5.000000000000000000e-01, 6.339746117591857910e-01, 7.886751294136047363e-01, + 1.000000000000000000e+00 }, + { 1.000000000000000000e+00, 7.886751294136047363e-01, 6.339746117591857910e-01, + 5.000000000000000000e-01, 3.660253882408142090e-01, 2.113248705863952637e-01, + 0.000000000000000000e+00 } +}; + +/* Antialiasing table. See commit 6f1ec38ce2193d3d4cacd87edb452c6d7ba751ec + * (mpegaudio: clean up compute_antialias() definition) for how they were + * created. */ +static const float csa_table[8][4] = { + { 8.574929237365722656e-01, -5.144957900047302246e-01, + 3.429971337318420410e-01, -1.371988654136657715e+00 }, + { 8.817420005798339844e-01, -4.717319905757904053e-01, + 4.100100100040435791e-01, -1.353474020957946777e+00 }, + { 9.496286511421203613e-01, -3.133774697780609131e-01, + 6.362511515617370605e-01, -1.263006091117858887e+00 }, + { 9.833145737648010254e-01, -1.819131970405578613e-01, + 8.014013767242431641e-01, -1.165227770805358887e+00 }, + { 9.955177903175354004e-01, -9.457419067621231079e-02, + 9.009436368942260742e-01, -1.090092062950134277e+00 }, + { 9.991605877876281738e-01, -4.096558317542076111e-02, + 9.581949710845947266e-01, -1.040126085281372070e+00 }, + { 9.998992085456848145e-01, -1.419856864959001541e-02, + 9.857006072998046875e-01, -1.014097809791564941e+00 }, + { 9.999931454658508301e-01, -3.699974622577428818e-03, + 9.962931871414184570e-01, -1.003693103790283203e+00 } +}; + #include "mpegaudiodec_template.c" #if CONFIG_MP1FLOAT_DECODER @@ -46,13 +79,14 @@ .id = AV_CODEC_ID_MP1, .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, - .close = decode_close, .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP2FLOAT_DECODER @@ -64,12 +98,13 @@ .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, .decode = decode_frame, - .close = decode_close, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP3FLOAT_DECODER @@ -80,13 +115,14 @@ .id = AV_CODEC_ID_MP3, .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, - .close = decode_close, .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP3ADUFLOAT_DECODER @@ -97,13 +133,14 @@ .id = AV_CODEC_ID_MP3ADU, .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, - .close = decode_close, .decode = decode_frame_adu, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .flush = flush, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP3ON4FLOAT_DECODER @@ -116,9 +153,11 @@ .init = decode_init_mp3on4, .close = decode_close_mp3on4, .decode = decode_frame_mp3on4, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .flush = flush_mp3on4, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudiodectab.h ffmpeg-4.4/libavcodec/mpegaudiodectab.h --- ffmpeg-4.2.2/libavcodec/mpegaudiodectab.h 2016-03-29 02:25:20.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudiodectab.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,615 +0,0 @@ -/* - * MPEG Audio decoder - * 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 - */ - -/** - * @file - * mpeg audio layer decoder tables. - */ - -#ifndef AVCODEC_MPEGAUDIODECTAB_H -#define AVCODEC_MPEGAUDIODECTAB_H - -#include -#include - -#include "mpegaudio.h" - -/*******************************************************/ -/* layer 3 tables */ - -/* layer 3 huffman tables */ -typedef struct HuffTable { - int xsize; - const uint8_t *bits; - const uint16_t *codes; -} HuffTable; - -/* layer3 scale factor size */ -static const uint8_t slen_table[2][16] = { - { 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 }, - { 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 }, -}; - -/* number of lsf scale factors for a given size */ -static const uint8_t lsf_nsf_table[6][3][4] = { - { { 6, 5, 5, 5 }, { 9, 9, 9, 9 }, { 6, 9, 9, 9 } }, - { { 6, 5, 7, 3 }, { 9, 9, 12, 6 }, { 6, 9, 12, 6 } }, - { { 11, 10, 0, 0 }, { 18, 18, 0, 0 }, { 15, 18, 0, 0 } }, - { { 7, 7, 7, 0 }, { 12, 12, 12, 0 }, { 6, 15, 12, 0 } }, - { { 6, 6, 6, 3 }, { 12, 9, 9, 6 }, { 6, 12, 9, 6 } }, - { { 8, 8, 5, 0 }, { 15, 12, 9, 0 }, { 6, 18, 9, 0 } }, -}; - -/* mpegaudio layer 3 huffman tables */ - -static const uint16_t mpa_huffcodes_1[4] = { - 0x0001, 0x0001, 0x0001, 0x0000, -}; - -static const uint8_t mpa_huffbits_1[4] = { - 1, 3, 2, 3, -}; - -static const uint16_t mpa_huffcodes_2[9] = { - 0x0001, 0x0002, 0x0001, 0x0003, 0x0001, 0x0001, 0x0003, 0x0002, - 0x0000, -}; - -static const uint8_t mpa_huffbits_2[9] = { - 1, 3, 6, 3, 3, 5, 5, 5, - 6, -}; - -static const uint16_t mpa_huffcodes_3[9] = { - 0x0003, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0003, 0x0002, - 0x0000, -}; - -static const uint8_t mpa_huffbits_3[9] = { - 2, 2, 6, 3, 2, 5, 5, 5, - 6, -}; - -static const uint16_t mpa_huffcodes_5[16] = { - 0x0001, 0x0002, 0x0006, 0x0005, 0x0003, 0x0001, 0x0004, 0x0004, - 0x0007, 0x0005, 0x0007, 0x0001, 0x0006, 0x0001, 0x0001, 0x0000, -}; - -static const uint8_t mpa_huffbits_5[16] = { - 1, 3, 6, 7, 3, 3, 6, 7, - 6, 6, 7, 8, 7, 6, 7, 8, -}; - -static const uint16_t mpa_huffcodes_6[16] = { - 0x0007, 0x0003, 0x0005, 0x0001, 0x0006, 0x0002, 0x0003, 0x0002, - 0x0005, 0x0004, 0x0004, 0x0001, 0x0003, 0x0003, 0x0002, 0x0000, -}; - -static const uint8_t mpa_huffbits_6[16] = { - 3, 3, 5, 7, 3, 2, 4, 5, - 4, 4, 5, 6, 6, 5, 6, 7, -}; - -static const uint16_t mpa_huffcodes_7[36] = { - 0x0001, 0x0002, 0x000a, 0x0013, 0x0010, 0x000a, 0x0003, 0x0003, - 0x0007, 0x000a, 0x0005, 0x0003, 0x000b, 0x0004, 0x000d, 0x0011, - 0x0008, 0x0004, 0x000c, 0x000b, 0x0012, 0x000f, 0x000b, 0x0002, - 0x0007, 0x0006, 0x0009, 0x000e, 0x0003, 0x0001, 0x0006, 0x0004, - 0x0005, 0x0003, 0x0002, 0x0000, -}; - -static const uint8_t mpa_huffbits_7[36] = { - 1, 3, 6, 8, 8, 9, 3, 4, - 6, 7, 7, 8, 6, 5, 7, 8, - 8, 9, 7, 7, 8, 9, 9, 9, - 7, 7, 8, 9, 9, 10, 8, 8, - 9, 10, 10, 10, -}; - -static const uint16_t mpa_huffcodes_8[36] = { - 0x0003, 0x0004, 0x0006, 0x0012, 0x000c, 0x0005, 0x0005, 0x0001, - 0x0002, 0x0010, 0x0009, 0x0003, 0x0007, 0x0003, 0x0005, 0x000e, - 0x0007, 0x0003, 0x0013, 0x0011, 0x000f, 0x000d, 0x000a, 0x0004, - 0x000d, 0x0005, 0x0008, 0x000b, 0x0005, 0x0001, 0x000c, 0x0004, - 0x0004, 0x0001, 0x0001, 0x0000, -}; - -static const uint8_t mpa_huffbits_8[36] = { - 2, 3, 6, 8, 8, 9, 3, 2, - 4, 8, 8, 8, 6, 4, 6, 8, - 8, 9, 8, 8, 8, 9, 9, 10, - 8, 7, 8, 9, 10, 10, 9, 8, - 9, 9, 11, 11, -}; - -static const uint16_t mpa_huffcodes_9[36] = { - 0x0007, 0x0005, 0x0009, 0x000e, 0x000f, 0x0007, 0x0006, 0x0004, - 0x0005, 0x0005, 0x0006, 0x0007, 0x0007, 0x0006, 0x0008, 0x0008, - 0x0008, 0x0005, 0x000f, 0x0006, 0x0009, 0x000a, 0x0005, 0x0001, - 0x000b, 0x0007, 0x0009, 0x0006, 0x0004, 0x0001, 0x000e, 0x0004, - 0x0006, 0x0002, 0x0006, 0x0000, -}; - -static const uint8_t mpa_huffbits_9[36] = { - 3, 3, 5, 6, 8, 9, 3, 3, - 4, 5, 6, 8, 4, 4, 5, 6, - 7, 8, 6, 5, 6, 7, 7, 8, - 7, 6, 7, 7, 8, 9, 8, 7, - 8, 8, 9, 9, -}; - -static const uint16_t mpa_huffcodes_10[64] = { - 0x0001, 0x0002, 0x000a, 0x0017, 0x0023, 0x001e, 0x000c, 0x0011, - 0x0003, 0x0003, 0x0008, 0x000c, 0x0012, 0x0015, 0x000c, 0x0007, - 0x000b, 0x0009, 0x000f, 0x0015, 0x0020, 0x0028, 0x0013, 0x0006, - 0x000e, 0x000d, 0x0016, 0x0022, 0x002e, 0x0017, 0x0012, 0x0007, - 0x0014, 0x0013, 0x0021, 0x002f, 0x001b, 0x0016, 0x0009, 0x0003, - 0x001f, 0x0016, 0x0029, 0x001a, 0x0015, 0x0014, 0x0005, 0x0003, - 0x000e, 0x000d, 0x000a, 0x000b, 0x0010, 0x0006, 0x0005, 0x0001, - 0x0009, 0x0008, 0x0007, 0x0008, 0x0004, 0x0004, 0x0002, 0x0000, -}; - -static const uint8_t mpa_huffbits_10[64] = { - 1, 3, 6, 8, 9, 9, 9, 10, - 3, 4, 6, 7, 8, 9, 8, 8, - 6, 6, 7, 8, 9, 10, 9, 9, - 7, 7, 8, 9, 10, 10, 9, 10, - 8, 8, 9, 10, 10, 10, 10, 10, - 9, 9, 10, 10, 11, 11, 10, 11, - 8, 8, 9, 10, 10, 10, 11, 11, - 9, 8, 9, 10, 10, 11, 11, 11, -}; - -static const uint16_t mpa_huffcodes_11[64] = { - 0x0003, 0x0004, 0x000a, 0x0018, 0x0022, 0x0021, 0x0015, 0x000f, - 0x0005, 0x0003, 0x0004, 0x000a, 0x0020, 0x0011, 0x000b, 0x000a, - 0x000b, 0x0007, 0x000d, 0x0012, 0x001e, 0x001f, 0x0014, 0x0005, - 0x0019, 0x000b, 0x0013, 0x003b, 0x001b, 0x0012, 0x000c, 0x0005, - 0x0023, 0x0021, 0x001f, 0x003a, 0x001e, 0x0010, 0x0007, 0x0005, - 0x001c, 0x001a, 0x0020, 0x0013, 0x0011, 0x000f, 0x0008, 0x000e, - 0x000e, 0x000c, 0x0009, 0x000d, 0x000e, 0x0009, 0x0004, 0x0001, - 0x000b, 0x0004, 0x0006, 0x0006, 0x0006, 0x0003, 0x0002, 0x0000, -}; - -static const uint8_t mpa_huffbits_11[64] = { - 2, 3, 5, 7, 8, 9, 8, 9, - 3, 3, 4, 6, 8, 8, 7, 8, - 5, 5, 6, 7, 8, 9, 8, 8, - 7, 6, 7, 9, 8, 10, 8, 9, - 8, 8, 8, 9, 9, 10, 9, 10, - 8, 8, 9, 10, 10, 11, 10, 11, - 8, 7, 7, 8, 9, 10, 10, 10, - 8, 7, 8, 9, 10, 10, 10, 10, -}; - -static const uint16_t mpa_huffcodes_12[64] = { - 0x0009, 0x0006, 0x0010, 0x0021, 0x0029, 0x0027, 0x0026, 0x001a, - 0x0007, 0x0005, 0x0006, 0x0009, 0x0017, 0x0010, 0x001a, 0x000b, - 0x0011, 0x0007, 0x000b, 0x000e, 0x0015, 0x001e, 0x000a, 0x0007, - 0x0011, 0x000a, 0x000f, 0x000c, 0x0012, 0x001c, 0x000e, 0x0005, - 0x0020, 0x000d, 0x0016, 0x0013, 0x0012, 0x0010, 0x0009, 0x0005, - 0x0028, 0x0011, 0x001f, 0x001d, 0x0011, 0x000d, 0x0004, 0x0002, - 0x001b, 0x000c, 0x000b, 0x000f, 0x000a, 0x0007, 0x0004, 0x0001, - 0x001b, 0x000c, 0x0008, 0x000c, 0x0006, 0x0003, 0x0001, 0x0000, -}; - -static const uint8_t mpa_huffbits_12[64] = { - 4, 3, 5, 7, 8, 9, 9, 9, - 3, 3, 4, 5, 7, 7, 8, 8, - 5, 4, 5, 6, 7, 8, 7, 8, - 6, 5, 6, 6, 7, 8, 8, 8, - 7, 6, 7, 7, 8, 8, 8, 9, - 8, 7, 8, 8, 8, 9, 8, 9, - 8, 7, 7, 8, 8, 9, 9, 10, - 9, 8, 8, 9, 9, 9, 9, 10, -}; - -static const uint16_t mpa_huffcodes_13[256] = { - 0x0001, 0x0005, 0x000e, 0x0015, 0x0022, 0x0033, 0x002e, 0x0047, - 0x002a, 0x0034, 0x0044, 0x0034, 0x0043, 0x002c, 0x002b, 0x0013, - 0x0003, 0x0004, 0x000c, 0x0013, 0x001f, 0x001a, 0x002c, 0x0021, - 0x001f, 0x0018, 0x0020, 0x0018, 0x001f, 0x0023, 0x0016, 0x000e, - 0x000f, 0x000d, 0x0017, 0x0024, 0x003b, 0x0031, 0x004d, 0x0041, - 0x001d, 0x0028, 0x001e, 0x0028, 0x001b, 0x0021, 0x002a, 0x0010, - 0x0016, 0x0014, 0x0025, 0x003d, 0x0038, 0x004f, 0x0049, 0x0040, - 0x002b, 0x004c, 0x0038, 0x0025, 0x001a, 0x001f, 0x0019, 0x000e, - 0x0023, 0x0010, 0x003c, 0x0039, 0x0061, 0x004b, 0x0072, 0x005b, - 0x0036, 0x0049, 0x0037, 0x0029, 0x0030, 0x0035, 0x0017, 0x0018, - 0x003a, 0x001b, 0x0032, 0x0060, 0x004c, 0x0046, 0x005d, 0x0054, - 0x004d, 0x003a, 0x004f, 0x001d, 0x004a, 0x0031, 0x0029, 0x0011, - 0x002f, 0x002d, 0x004e, 0x004a, 0x0073, 0x005e, 0x005a, 0x004f, - 0x0045, 0x0053, 0x0047, 0x0032, 0x003b, 0x0026, 0x0024, 0x000f, - 0x0048, 0x0022, 0x0038, 0x005f, 0x005c, 0x0055, 0x005b, 0x005a, - 0x0056, 0x0049, 0x004d, 0x0041, 0x0033, 0x002c, 0x002b, 0x002a, - 0x002b, 0x0014, 0x001e, 0x002c, 0x0037, 0x004e, 0x0048, 0x0057, - 0x004e, 0x003d, 0x002e, 0x0036, 0x0025, 0x001e, 0x0014, 0x0010, - 0x0035, 0x0019, 0x0029, 0x0025, 0x002c, 0x003b, 0x0036, 0x0051, - 0x0042, 0x004c, 0x0039, 0x0036, 0x0025, 0x0012, 0x0027, 0x000b, - 0x0023, 0x0021, 0x001f, 0x0039, 0x002a, 0x0052, 0x0048, 0x0050, - 0x002f, 0x003a, 0x0037, 0x0015, 0x0016, 0x001a, 0x0026, 0x0016, - 0x0035, 0x0019, 0x0017, 0x0026, 0x0046, 0x003c, 0x0033, 0x0024, - 0x0037, 0x001a, 0x0022, 0x0017, 0x001b, 0x000e, 0x0009, 0x0007, - 0x0022, 0x0020, 0x001c, 0x0027, 0x0031, 0x004b, 0x001e, 0x0034, - 0x0030, 0x0028, 0x0034, 0x001c, 0x0012, 0x0011, 0x0009, 0x0005, - 0x002d, 0x0015, 0x0022, 0x0040, 0x0038, 0x0032, 0x0031, 0x002d, - 0x001f, 0x0013, 0x000c, 0x000f, 0x000a, 0x0007, 0x0006, 0x0003, - 0x0030, 0x0017, 0x0014, 0x0027, 0x0024, 0x0023, 0x0035, 0x0015, - 0x0010, 0x0017, 0x000d, 0x000a, 0x0006, 0x0001, 0x0004, 0x0002, - 0x0010, 0x000f, 0x0011, 0x001b, 0x0019, 0x0014, 0x001d, 0x000b, - 0x0011, 0x000c, 0x0010, 0x0008, 0x0001, 0x0001, 0x0000, 0x0001, -}; - -static const uint8_t mpa_huffbits_13[256] = { - 1, 4, 6, 7, 8, 9, 9, 10, - 9, 10, 11, 11, 12, 12, 13, 13, - 3, 4, 6, 7, 8, 8, 9, 9, - 9, 9, 10, 10, 11, 12, 12, 12, - 6, 6, 7, 8, 9, 9, 10, 10, - 9, 10, 10, 11, 11, 12, 13, 13, - 7, 7, 8, 9, 9, 10, 10, 10, - 10, 11, 11, 11, 11, 12, 13, 13, - 8, 7, 9, 9, 10, 10, 11, 11, - 10, 11, 11, 12, 12, 13, 13, 14, - 9, 8, 9, 10, 10, 10, 11, 11, - 11, 11, 12, 11, 13, 13, 14, 14, - 9, 9, 10, 10, 11, 11, 11, 11, - 11, 12, 12, 12, 13, 13, 14, 14, - 10, 9, 10, 11, 11, 11, 12, 12, - 12, 12, 13, 13, 13, 14, 16, 16, - 9, 8, 9, 10, 10, 11, 11, 12, - 12, 12, 12, 13, 13, 14, 15, 15, - 10, 9, 10, 10, 11, 11, 11, 13, - 12, 13, 13, 14, 14, 14, 16, 15, - 10, 10, 10, 11, 11, 12, 12, 13, - 12, 13, 14, 13, 14, 15, 16, 17, - 11, 10, 10, 11, 12, 12, 12, 12, - 13, 13, 13, 14, 15, 15, 15, 16, - 11, 11, 11, 12, 12, 13, 12, 13, - 14, 14, 15, 15, 15, 16, 16, 16, - 12, 11, 12, 13, 13, 13, 14, 14, - 14, 14, 14, 15, 16, 15, 16, 16, - 13, 12, 12, 13, 13, 13, 15, 14, - 14, 17, 15, 15, 15, 17, 16, 16, - 12, 12, 13, 14, 14, 14, 15, 14, - 15, 15, 16, 16, 19, 18, 19, 16, -}; - -static const uint16_t mpa_huffcodes_15[256] = { - 0x0007, 0x000c, 0x0012, 0x0035, 0x002f, 0x004c, 0x007c, 0x006c, - 0x0059, 0x007b, 0x006c, 0x0077, 0x006b, 0x0051, 0x007a, 0x003f, - 0x000d, 0x0005, 0x0010, 0x001b, 0x002e, 0x0024, 0x003d, 0x0033, - 0x002a, 0x0046, 0x0034, 0x0053, 0x0041, 0x0029, 0x003b, 0x0024, - 0x0013, 0x0011, 0x000f, 0x0018, 0x0029, 0x0022, 0x003b, 0x0030, - 0x0028, 0x0040, 0x0032, 0x004e, 0x003e, 0x0050, 0x0038, 0x0021, - 0x001d, 0x001c, 0x0019, 0x002b, 0x0027, 0x003f, 0x0037, 0x005d, - 0x004c, 0x003b, 0x005d, 0x0048, 0x0036, 0x004b, 0x0032, 0x001d, - 0x0034, 0x0016, 0x002a, 0x0028, 0x0043, 0x0039, 0x005f, 0x004f, - 0x0048, 0x0039, 0x0059, 0x0045, 0x0031, 0x0042, 0x002e, 0x001b, - 0x004d, 0x0025, 0x0023, 0x0042, 0x003a, 0x0034, 0x005b, 0x004a, - 0x003e, 0x0030, 0x004f, 0x003f, 0x005a, 0x003e, 0x0028, 0x0026, - 0x007d, 0x0020, 0x003c, 0x0038, 0x0032, 0x005c, 0x004e, 0x0041, - 0x0037, 0x0057, 0x0047, 0x0033, 0x0049, 0x0033, 0x0046, 0x001e, - 0x006d, 0x0035, 0x0031, 0x005e, 0x0058, 0x004b, 0x0042, 0x007a, - 0x005b, 0x0049, 0x0038, 0x002a, 0x0040, 0x002c, 0x0015, 0x0019, - 0x005a, 0x002b, 0x0029, 0x004d, 0x0049, 0x003f, 0x0038, 0x005c, - 0x004d, 0x0042, 0x002f, 0x0043, 0x0030, 0x0035, 0x0024, 0x0014, - 0x0047, 0x0022, 0x0043, 0x003c, 0x003a, 0x0031, 0x0058, 0x004c, - 0x0043, 0x006a, 0x0047, 0x0036, 0x0026, 0x0027, 0x0017, 0x000f, - 0x006d, 0x0035, 0x0033, 0x002f, 0x005a, 0x0052, 0x003a, 0x0039, - 0x0030, 0x0048, 0x0039, 0x0029, 0x0017, 0x001b, 0x003e, 0x0009, - 0x0056, 0x002a, 0x0028, 0x0025, 0x0046, 0x0040, 0x0034, 0x002b, - 0x0046, 0x0037, 0x002a, 0x0019, 0x001d, 0x0012, 0x000b, 0x000b, - 0x0076, 0x0044, 0x001e, 0x0037, 0x0032, 0x002e, 0x004a, 0x0041, - 0x0031, 0x0027, 0x0018, 0x0010, 0x0016, 0x000d, 0x000e, 0x0007, - 0x005b, 0x002c, 0x0027, 0x0026, 0x0022, 0x003f, 0x0034, 0x002d, - 0x001f, 0x0034, 0x001c, 0x0013, 0x000e, 0x0008, 0x0009, 0x0003, - 0x007b, 0x003c, 0x003a, 0x0035, 0x002f, 0x002b, 0x0020, 0x0016, - 0x0025, 0x0018, 0x0011, 0x000c, 0x000f, 0x000a, 0x0002, 0x0001, - 0x0047, 0x0025, 0x0022, 0x001e, 0x001c, 0x0014, 0x0011, 0x001a, - 0x0015, 0x0010, 0x000a, 0x0006, 0x0008, 0x0006, 0x0002, 0x0000, -}; - -static const uint8_t mpa_huffbits_15[256] = { - 3, 4, 5, 7, 7, 8, 9, 9, - 9, 10, 10, 11, 11, 11, 12, 13, - 4, 3, 5, 6, 7, 7, 8, 8, - 8, 9, 9, 10, 10, 10, 11, 11, - 5, 5, 5, 6, 7, 7, 8, 8, - 8, 9, 9, 10, 10, 11, 11, 11, - 6, 6, 6, 7, 7, 8, 8, 9, - 9, 9, 10, 10, 10, 11, 11, 11, - 7, 6, 7, 7, 8, 8, 9, 9, - 9, 9, 10, 10, 10, 11, 11, 11, - 8, 7, 7, 8, 8, 8, 9, 9, - 9, 9, 10, 10, 11, 11, 11, 12, - 9, 7, 8, 8, 8, 9, 9, 9, - 9, 10, 10, 10, 11, 11, 12, 12, - 9, 8, 8, 9, 9, 9, 9, 10, - 10, 10, 10, 10, 11, 11, 11, 12, - 9, 8, 8, 9, 9, 9, 9, 10, - 10, 10, 10, 11, 11, 12, 12, 12, - 9, 8, 9, 9, 9, 9, 10, 10, - 10, 11, 11, 11, 11, 12, 12, 12, - 10, 9, 9, 9, 10, 10, 10, 10, - 10, 11, 11, 11, 11, 12, 13, 12, - 10, 9, 9, 9, 10, 10, 10, 10, - 11, 11, 11, 11, 12, 12, 12, 13, - 11, 10, 9, 10, 10, 10, 11, 11, - 11, 11, 11, 11, 12, 12, 13, 13, - 11, 10, 10, 10, 10, 11, 11, 11, - 11, 12, 12, 12, 12, 12, 13, 13, - 12, 11, 11, 11, 11, 11, 11, 11, - 12, 12, 12, 12, 13, 13, 12, 13, - 12, 11, 11, 11, 11, 11, 11, 12, - 12, 12, 12, 12, 13, 13, 13, 13, -}; - -static const uint16_t mpa_huffcodes_16[256] = { - 0x0001, 0x0005, 0x000e, 0x002c, 0x004a, 0x003f, 0x006e, 0x005d, - 0x00ac, 0x0095, 0x008a, 0x00f2, 0x00e1, 0x00c3, 0x0178, 0x0011, - 0x0003, 0x0004, 0x000c, 0x0014, 0x0023, 0x003e, 0x0035, 0x002f, - 0x0053, 0x004b, 0x0044, 0x0077, 0x00c9, 0x006b, 0x00cf, 0x0009, - 0x000f, 0x000d, 0x0017, 0x0026, 0x0043, 0x003a, 0x0067, 0x005a, - 0x00a1, 0x0048, 0x007f, 0x0075, 0x006e, 0x00d1, 0x00ce, 0x0010, - 0x002d, 0x0015, 0x0027, 0x0045, 0x0040, 0x0072, 0x0063, 0x0057, - 0x009e, 0x008c, 0x00fc, 0x00d4, 0x00c7, 0x0183, 0x016d, 0x001a, - 0x004b, 0x0024, 0x0044, 0x0041, 0x0073, 0x0065, 0x00b3, 0x00a4, - 0x009b, 0x0108, 0x00f6, 0x00e2, 0x018b, 0x017e, 0x016a, 0x0009, - 0x0042, 0x001e, 0x003b, 0x0038, 0x0066, 0x00b9, 0x00ad, 0x0109, - 0x008e, 0x00fd, 0x00e8, 0x0190, 0x0184, 0x017a, 0x01bd, 0x0010, - 0x006f, 0x0036, 0x0034, 0x0064, 0x00b8, 0x00b2, 0x00a0, 0x0085, - 0x0101, 0x00f4, 0x00e4, 0x00d9, 0x0181, 0x016e, 0x02cb, 0x000a, - 0x0062, 0x0030, 0x005b, 0x0058, 0x00a5, 0x009d, 0x0094, 0x0105, - 0x00f8, 0x0197, 0x018d, 0x0174, 0x017c, 0x0379, 0x0374, 0x0008, - 0x0055, 0x0054, 0x0051, 0x009f, 0x009c, 0x008f, 0x0104, 0x00f9, - 0x01ab, 0x0191, 0x0188, 0x017f, 0x02d7, 0x02c9, 0x02c4, 0x0007, - 0x009a, 0x004c, 0x0049, 0x008d, 0x0083, 0x0100, 0x00f5, 0x01aa, - 0x0196, 0x018a, 0x0180, 0x02df, 0x0167, 0x02c6, 0x0160, 0x000b, - 0x008b, 0x0081, 0x0043, 0x007d, 0x00f7, 0x00e9, 0x00e5, 0x00db, - 0x0189, 0x02e7, 0x02e1, 0x02d0, 0x0375, 0x0372, 0x01b7, 0x0004, - 0x00f3, 0x0078, 0x0076, 0x0073, 0x00e3, 0x00df, 0x018c, 0x02ea, - 0x02e6, 0x02e0, 0x02d1, 0x02c8, 0x02c2, 0x00df, 0x01b4, 0x0006, - 0x00ca, 0x00e0, 0x00de, 0x00da, 0x00d8, 0x0185, 0x0182, 0x017d, - 0x016c, 0x0378, 0x01bb, 0x02c3, 0x01b8, 0x01b5, 0x06c0, 0x0004, - 0x02eb, 0x00d3, 0x00d2, 0x00d0, 0x0172, 0x017b, 0x02de, 0x02d3, - 0x02ca, 0x06c7, 0x0373, 0x036d, 0x036c, 0x0d83, 0x0361, 0x0002, - 0x0179, 0x0171, 0x0066, 0x00bb, 0x02d6, 0x02d2, 0x0166, 0x02c7, - 0x02c5, 0x0362, 0x06c6, 0x0367, 0x0d82, 0x0366, 0x01b2, 0x0000, - 0x000c, 0x000a, 0x0007, 0x000b, 0x000a, 0x0011, 0x000b, 0x0009, - 0x000d, 0x000c, 0x000a, 0x0007, 0x0005, 0x0003, 0x0001, 0x0003, -}; - -static const uint8_t mpa_huffbits_16[256] = { - 1, 4, 6, 8, 9, 9, 10, 10, - 11, 11, 11, 12, 12, 12, 13, 9, - 3, 4, 6, 7, 8, 9, 9, 9, - 10, 10, 10, 11, 12, 11, 12, 8, - 6, 6, 7, 8, 9, 9, 10, 10, - 11, 10, 11, 11, 11, 12, 12, 9, - 8, 7, 8, 9, 9, 10, 10, 10, - 11, 11, 12, 12, 12, 13, 13, 10, - 9, 8, 9, 9, 10, 10, 11, 11, - 11, 12, 12, 12, 13, 13, 13, 9, - 9, 8, 9, 9, 10, 11, 11, 12, - 11, 12, 12, 13, 13, 13, 14, 10, - 10, 9, 9, 10, 11, 11, 11, 11, - 12, 12, 12, 12, 13, 13, 14, 10, - 10, 9, 10, 10, 11, 11, 11, 12, - 12, 13, 13, 13, 13, 15, 15, 10, - 10, 10, 10, 11, 11, 11, 12, 12, - 13, 13, 13, 13, 14, 14, 14, 10, - 11, 10, 10, 11, 11, 12, 12, 13, - 13, 13, 13, 14, 13, 14, 13, 11, - 11, 11, 10, 11, 12, 12, 12, 12, - 13, 14, 14, 14, 15, 15, 14, 10, - 12, 11, 11, 11, 12, 12, 13, 14, - 14, 14, 14, 14, 14, 13, 14, 11, - 12, 12, 12, 12, 12, 13, 13, 13, - 13, 15, 14, 14, 14, 14, 16, 11, - 14, 12, 12, 12, 13, 13, 14, 14, - 14, 16, 15, 15, 15, 17, 15, 11, - 13, 13, 11, 12, 14, 14, 13, 14, - 14, 15, 16, 15, 17, 15, 14, 11, - 9, 8, 8, 9, 9, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 8, -}; - -static const uint16_t mpa_huffcodes_24[256] = { - 0x000f, 0x000d, 0x002e, 0x0050, 0x0092, 0x0106, 0x00f8, 0x01b2, - 0x01aa, 0x029d, 0x028d, 0x0289, 0x026d, 0x0205, 0x0408, 0x0058, - 0x000e, 0x000c, 0x0015, 0x0026, 0x0047, 0x0082, 0x007a, 0x00d8, - 0x00d1, 0x00c6, 0x0147, 0x0159, 0x013f, 0x0129, 0x0117, 0x002a, - 0x002f, 0x0016, 0x0029, 0x004a, 0x0044, 0x0080, 0x0078, 0x00dd, - 0x00cf, 0x00c2, 0x00b6, 0x0154, 0x013b, 0x0127, 0x021d, 0x0012, - 0x0051, 0x0027, 0x004b, 0x0046, 0x0086, 0x007d, 0x0074, 0x00dc, - 0x00cc, 0x00be, 0x00b2, 0x0145, 0x0137, 0x0125, 0x010f, 0x0010, - 0x0093, 0x0048, 0x0045, 0x0087, 0x007f, 0x0076, 0x0070, 0x00d2, - 0x00c8, 0x00bc, 0x0160, 0x0143, 0x0132, 0x011d, 0x021c, 0x000e, - 0x0107, 0x0042, 0x0081, 0x007e, 0x0077, 0x0072, 0x00d6, 0x00ca, - 0x00c0, 0x00b4, 0x0155, 0x013d, 0x012d, 0x0119, 0x0106, 0x000c, - 0x00f9, 0x007b, 0x0079, 0x0075, 0x0071, 0x00d7, 0x00ce, 0x00c3, - 0x00b9, 0x015b, 0x014a, 0x0134, 0x0123, 0x0110, 0x0208, 0x000a, - 0x01b3, 0x0073, 0x006f, 0x006d, 0x00d3, 0x00cb, 0x00c4, 0x00bb, - 0x0161, 0x014c, 0x0139, 0x012a, 0x011b, 0x0213, 0x017d, 0x0011, - 0x01ab, 0x00d4, 0x00d0, 0x00cd, 0x00c9, 0x00c1, 0x00ba, 0x00b1, - 0x00a9, 0x0140, 0x012f, 0x011e, 0x010c, 0x0202, 0x0179, 0x0010, - 0x014f, 0x00c7, 0x00c5, 0x00bf, 0x00bd, 0x00b5, 0x00ae, 0x014d, - 0x0141, 0x0131, 0x0121, 0x0113, 0x0209, 0x017b, 0x0173, 0x000b, - 0x029c, 0x00b8, 0x00b7, 0x00b3, 0x00af, 0x0158, 0x014b, 0x013a, - 0x0130, 0x0122, 0x0115, 0x0212, 0x017f, 0x0175, 0x016e, 0x000a, - 0x028c, 0x015a, 0x00ab, 0x00a8, 0x00a4, 0x013e, 0x0135, 0x012b, - 0x011f, 0x0114, 0x0107, 0x0201, 0x0177, 0x0170, 0x016a, 0x0006, - 0x0288, 0x0142, 0x013c, 0x0138, 0x0133, 0x012e, 0x0124, 0x011c, - 0x010d, 0x0105, 0x0200, 0x0178, 0x0172, 0x016c, 0x0167, 0x0004, - 0x026c, 0x012c, 0x0128, 0x0126, 0x0120, 0x011a, 0x0111, 0x010a, - 0x0203, 0x017c, 0x0176, 0x0171, 0x016d, 0x0169, 0x0165, 0x0002, - 0x0409, 0x0118, 0x0116, 0x0112, 0x010b, 0x0108, 0x0103, 0x017e, - 0x017a, 0x0174, 0x016f, 0x016b, 0x0168, 0x0166, 0x0164, 0x0000, - 0x002b, 0x0014, 0x0013, 0x0011, 0x000f, 0x000d, 0x000b, 0x0009, - 0x0007, 0x0006, 0x0004, 0x0007, 0x0005, 0x0003, 0x0001, 0x0003, -}; - -static const uint8_t mpa_huffbits_24[256] = { - 4, 4, 6, 7, 8, 9, 9, 10, - 10, 11, 11, 11, 11, 11, 12, 9, - 4, 4, 5, 6, 7, 8, 8, 9, - 9, 9, 10, 10, 10, 10, 10, 8, - 6, 5, 6, 7, 7, 8, 8, 9, - 9, 9, 9, 10, 10, 10, 11, 7, - 7, 6, 7, 7, 8, 8, 8, 9, - 9, 9, 9, 10, 10, 10, 10, 7, - 8, 7, 7, 8, 8, 8, 8, 9, - 9, 9, 10, 10, 10, 10, 11, 7, - 9, 7, 8, 8, 8, 8, 9, 9, - 9, 9, 10, 10, 10, 10, 10, 7, - 9, 8, 8, 8, 8, 9, 9, 9, - 9, 10, 10, 10, 10, 10, 11, 7, - 10, 8, 8, 8, 9, 9, 9, 9, - 10, 10, 10, 10, 10, 11, 11, 8, - 10, 9, 9, 9, 9, 9, 9, 9, - 9, 10, 10, 10, 10, 11, 11, 8, - 10, 9, 9, 9, 9, 9, 9, 10, - 10, 10, 10, 10, 11, 11, 11, 8, - 11, 9, 9, 9, 9, 10, 10, 10, - 10, 10, 10, 11, 11, 11, 11, 8, - 11, 10, 9, 9, 9, 10, 10, 10, - 10, 10, 10, 11, 11, 11, 11, 8, - 11, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 11, 11, 11, 11, 11, 8, - 11, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 8, - 12, 10, 10, 10, 10, 10, 10, 11, - 11, 11, 11, 11, 11, 11, 11, 8, - 8, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 8, 8, 8, 8, 4, -}; - -static const HuffTable mpa_huff_tables[16] = { -{ 1, NULL, NULL }, -{ 2, mpa_huffbits_1, mpa_huffcodes_1 }, -{ 3, mpa_huffbits_2, mpa_huffcodes_2 }, -{ 3, mpa_huffbits_3, mpa_huffcodes_3 }, -{ 4, mpa_huffbits_5, mpa_huffcodes_5 }, -{ 4, mpa_huffbits_6, mpa_huffcodes_6 }, -{ 6, mpa_huffbits_7, mpa_huffcodes_7 }, -{ 6, mpa_huffbits_8, mpa_huffcodes_8 }, -{ 6, mpa_huffbits_9, mpa_huffcodes_9 }, -{ 8, mpa_huffbits_10, mpa_huffcodes_10 }, -{ 8, mpa_huffbits_11, mpa_huffcodes_11 }, -{ 8, mpa_huffbits_12, mpa_huffcodes_12 }, -{ 16, mpa_huffbits_13, mpa_huffcodes_13 }, -{ 16, mpa_huffbits_15, mpa_huffcodes_15 }, -{ 16, mpa_huffbits_16, mpa_huffcodes_16 }, -{ 16, mpa_huffbits_24, mpa_huffcodes_24 }, -}; - -static const uint8_t mpa_huff_data[32][2] = { -{ 0, 0 }, -{ 1, 0 }, -{ 2, 0 }, -{ 3, 0 }, -{ 0, 0 }, -{ 4, 0 }, -{ 5, 0 }, -{ 6, 0 }, -{ 7, 0 }, -{ 8, 0 }, -{ 9, 0 }, -{ 10, 0 }, -{ 11, 0 }, -{ 12, 0 }, -{ 0, 0 }, -{ 13, 0 }, -{ 14, 1 }, -{ 14, 2 }, -{ 14, 3 }, -{ 14, 4 }, -{ 14, 6 }, -{ 14, 8 }, -{ 14, 10 }, -{ 14, 13 }, -{ 15, 4 }, -{ 15, 5 }, -{ 15, 6 }, -{ 15, 7 }, -{ 15, 8 }, -{ 15, 9 }, -{ 15, 11 }, -{ 15, 13 }, -}; - - -/* huffman tables for quadrules */ -static const uint8_t mpa_quad_codes[2][16] = { - { 1, 5, 4, 5, 6, 5, 4, 4, 7, 3, 6, 0, 7, 2, 3, 1, }, - { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, }, -}; - -static const uint8_t mpa_quad_bits[2][16] = { - { 1, 4, 4, 5, 4, 6, 5, 6, 4, 5, 5, 6, 5, 6, 6, 6, }, - { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, }, -}; - -/* band size tables */ -static const uint8_t band_size_long[9][22] = { -{ 4, 4, 4, 4, 4, 4, 6, 6, 8, 8, 10, - 12, 16, 20, 24, 28, 34, 42, 50, 54, 76, 158, }, /* 44100 */ -{ 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, 10, - 12, 16, 18, 22, 28, 34, 40, 46, 54, 54, 192, }, /* 48000 */ -{ 4, 4, 4, 4, 4, 4, 6, 6, 8, 10, 12, - 16, 20, 24, 30, 38, 46, 56, 68, 84, 102, 26, }, /* 32000 */ -{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, - 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 22050 */ -{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, - 18, 22, 26, 32, 38, 46, 52, 64, 70, 76, 36, }, /* 24000 */ -{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, - 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 16000 */ -{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, - 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 11025 */ -{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, - 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 12000 */ -{ 12, 12, 12, 12, 12, 12, 16, 20, 24, 28, 32, - 40, 48, 56, 64, 76, 90, 2, 2, 2, 2, 2, }, /* 8000 */ -}; - -static const uint8_t band_size_short[9][13] = { -{ 4, 4, 4, 4, 6, 8, 10, 12, 14, 18, 22, 30, 56, }, /* 44100 */ -{ 4, 4, 4, 4, 6, 6, 10, 12, 14, 16, 20, 26, 66, }, /* 48000 */ -{ 4, 4, 4, 4, 6, 8, 12, 16, 20, 26, 34, 42, 12, }, /* 32000 */ -{ 4, 4, 4, 6, 6, 8, 10, 14, 18, 26, 32, 42, 18, }, /* 22050 */ -{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 32, 44, 12, }, /* 24000 */ -{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18, }, /* 16000 */ -{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18, }, /* 11025 */ -{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18, }, /* 12000 */ -{ 8, 8, 8, 12, 16, 20, 24, 28, 36, 2, 2, 2, 26, }, /* 8000 */ -}; - -static const uint8_t mpa_pretab[2][22] = { - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 }, -}; - -/* table for alias reduction (XXX: store it as integer !) */ -static const float ci_table[8] = { - -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037, -}; - -#endif /* AVCODEC_MPEGAUDIODECTAB_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudiodec_template.c ffmpeg-4.4/libavcodec/mpegaudiodec_template.c --- ffmpeg-4.2.2/libavcodec/mpegaudiodec_template.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudiodec_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,8 +27,12 @@ #include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" +#include "libavutil/crc.h" #include "libavutil/float_dsp.h" #include "libavutil/libm.h" +#include "libavutil/mem_internal.h" +#include "libavutil/thread.h" + #include "avcodec.h" #include "get_bits.h" #include "internal.h" @@ -86,46 +90,19 @@ int err_recognition; AVCodecContext* avctx; MPADSPContext mpadsp; - AVFloatDSPContext *fdsp; + void (*butterflies_float)(float *av_restrict v1, float *av_restrict v2, int len); AVFrame *frame; + uint32_t crc; } MPADecodeContext; #define HEADER_SIZE 4 #include "mpegaudiodata.h" -#include "mpegaudiodectab.h" -/* vlc structure for decoding layer 3 huffman tables */ -static VLC huff_vlc[16]; -static VLC_TYPE huff_vlc_tables[ - 0 + 128 + 128 + 128 + 130 + 128 + 154 + 166 + - 142 + 204 + 190 + 170 + 542 + 460 + 662 + 414 - ][2]; -static const int huff_vlc_tables_sizes[16] = { - 0, 128, 128, 128, 130, 128, 154, 166, - 142, 204, 190, 170, 542, 460, 662, 414 -}; -static VLC huff_quad_vlc[2]; -static VLC_TYPE huff_quad_vlc_tables[128+16][2]; -static const int huff_quad_vlc_tables_sizes[2] = { 128, 16 }; -/* computed from band_size_long */ -static uint16_t band_index_long[9][23]; #include "mpegaudio_tablegen.h" /* intensity stereo coef table */ -static INTFLOAT is_table[2][16]; static INTFLOAT is_table_lsf[2][2][16]; -static INTFLOAT csa_table[8][4]; - -static int16_t division_tab3[1<<6 ]; -static int16_t division_tab5[1<<8 ]; -static int16_t division_tab9[1<<11]; - -static int16_t * const division_tabs[4] = { - division_tab3, division_tab5, NULL, division_tab9 -}; -/* lower 2 bits: modulo 3, higher bits: shift */ -static uint16_t scale_factor_modshift[64]; /* [i][j]: 2^(-j/3) * FRAC_ONE * 2^(i+2) / (2^(i+2) - 1) */ static int32_t scale_factor_mult[15][3]; /* mult table for layer 2 group quantization */ @@ -176,10 +153,10 @@ int ra1, int ra2) { int l; - g->region_size[0] = band_index_long[s->sample_rate_index][ra1 + 1] >> 1; + g->region_size[0] = ff_band_index_long[s->sample_rate_index][ra1 + 1]; /* should not overflow */ l = FFMIN(ra1 + ra2 + 2, 22); - g->region_size[1] = band_index_long[s->sample_rate_index][ l] >> 1; + g->region_size[1] = ff_band_index_long[s->sample_rate_index][ l]; } static void compute_band_indexes(MPADecodeContext *s, GranuleDef *g) @@ -214,7 +191,7 @@ int shift, mod; int64_t val; - shift = scale_factor_modshift[scale_factor]; + shift = ff_scale_factor_modshift[scale_factor]; mod = shift & 3; shift >>= 2; val = MUL64((int)(mant + (-1U << n) + 1), scale_factor_mult[n-1][mod]); @@ -227,7 +204,7 @@ { int shift, mod, val; - shift = scale_factor_modshift[scale_factor]; + shift = ff_scale_factor_modshift[scale_factor]; mod = shift & 3; shift >>= 2; @@ -244,8 +221,8 @@ unsigned int m; int e; - e = table_4_3_exp [4 * value + (exponent & 3)]; - m = table_4_3_value[4 * value + (exponent & 3)]; + e = ff_table_4_3_exp [4 * value + (exponent & 3)]; + m = ff_table_4_3_value[4 * value + (exponent & 3)]; e -= exponent >> 2; #ifdef DEBUG if(e < 1) @@ -253,24 +230,14 @@ #endif if (e > (SUINT)31) return 0; - m = (m + ((1U << e)>>1)) >> e; + m = (m + ((1U << e) >> 1)) >> e; return m; } static av_cold void decode_init_static(void) { - int i, j, k; - int offset; - - /* scale factors table for layer 1/2 */ - for (i = 0; i < 64; i++) { - int shift, mod; - /* 1.0 (i = 3) is normalized to 2 ^ FRAC_BITS */ - shift = i / 3; - mod = i % 3; - scale_factor_modshift[i] = mod | (shift << 2); - } + int i, j; /* scale factor multiply for layer 1 */ for (i = 0; i < 15; i++) { @@ -287,92 +254,10 @@ scale_factor_mult[i][2]); } - RENAME(ff_mpa_synth_init)(RENAME(ff_mpa_synth_window)); - - /* huffman decode tables */ - offset = 0; - for (i = 1; i < 16; i++) { - const HuffTable *h = &mpa_huff_tables[i]; - int xsize, x, y; - uint8_t tmp_bits [512] = { 0 }; - uint16_t tmp_codes[512] = { 0 }; - - xsize = h->xsize; - - j = 0; - for (x = 0; x < xsize; x++) { - for (y = 0; y < xsize; y++) { - tmp_bits [(x << 5) | y | ((x&&y)<<4)]= h->bits [j ]; - tmp_codes[(x << 5) | y | ((x&&y)<<4)]= h->codes[j++]; - } - } - - /* XXX: fail test */ - huff_vlc[i].table = huff_vlc_tables+offset; - huff_vlc[i].table_allocated = huff_vlc_tables_sizes[i]; - init_vlc(&huff_vlc[i], 7, 512, - tmp_bits, 1, 1, tmp_codes, 2, 2, - INIT_VLC_USE_NEW_STATIC); - offset += huff_vlc_tables_sizes[i]; - } - av_assert0(offset == FF_ARRAY_ELEMS(huff_vlc_tables)); - - offset = 0; - for (i = 0; i < 2; i++) { - huff_quad_vlc[i].table = huff_quad_vlc_tables+offset; - huff_quad_vlc[i].table_allocated = huff_quad_vlc_tables_sizes[i]; - init_vlc(&huff_quad_vlc[i], i == 0 ? 7 : 4, 16, - mpa_quad_bits[i], 1, 1, mpa_quad_codes[i], 1, 1, - INIT_VLC_USE_NEW_STATIC); - offset += huff_quad_vlc_tables_sizes[i]; - } - av_assert0(offset == FF_ARRAY_ELEMS(huff_quad_vlc_tables)); - - for (i = 0; i < 9; i++) { - k = 0; - for (j = 0; j < 22; j++) { - band_index_long[i][j] = k; - k += band_size_long[i][j]; - } - band_index_long[i][22] = k; - } - /* compute n ^ (4/3) and store it in mantissa/exp format */ mpegaudio_tableinit(); - for (i = 0; i < 4; i++) { - if (ff_mpa_quant_bits[i] < 0) { - for (j = 0; j < (1 << (-ff_mpa_quant_bits[i]+1)); j++) { - int val1, val2, val3, steps; - int val = j; - steps = ff_mpa_quant_steps[i]; - val1 = val % steps; - val /= steps; - val2 = val % steps; - val3 = val / steps; - division_tabs[i][j] = val1 + (val2 << 4) + (val3 << 8); - } - } - } - - - for (i = 0; i < 7; i++) { - float f; - INTFLOAT v; - if (i != 6) { - f = tan((double)i * M_PI / 12.0); - v = FIXR(f / (1.0 + f)); - } else { - v = FIXR(1.0); - } - is_table[0][ i] = v; - is_table[1][6 - i] = v; - } - /* invalid values */ - for (i = 7; i < 16; i++) - is_table[0][i] = is_table[1][i] = 0.0; - for (i = 0; i < 16; i++) { double f; int e, k; @@ -388,52 +273,26 @@ (float) is_table_lsf[j][1][i]); } } - - for (i = 0; i < 8; i++) { - double ci, cs, ca; - ci = ci_table[i]; - cs = 1.0 / sqrt(1.0 + ci * ci); - ca = cs * ci; -#if !USE_FLOATS - csa_table[i][0] = FIXHR(cs/4); - csa_table[i][1] = FIXHR(ca/4); - csa_table[i][2] = FIXHR(ca/4) + FIXHR(cs/4); - csa_table[i][3] = FIXHR(ca/4) - FIXHR(cs/4); -#else - csa_table[i][0] = cs; - csa_table[i][1] = ca; - csa_table[i][2] = ca + cs; - csa_table[i][3] = ca - cs; -#endif - } -} - -#if USE_FLOATS -static av_cold int decode_close(AVCodecContext * avctx) -{ - MPADecodeContext *s = avctx->priv_data; - av_freep(&s->fdsp); - - return 0; + RENAME(ff_mpa_synth_init)(); + ff_mpegaudiodec_common_init_static(); } -#endif static av_cold int decode_init(AVCodecContext * avctx) { - static int initialized_tables = 0; + static AVOnce init_static_once = AV_ONCE_INIT; MPADecodeContext *s = avctx->priv_data; - if (!initialized_tables) { - decode_init_static(); - initialized_tables = 1; - } - s->avctx = avctx; #if USE_FLOATS - s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); - if (!s->fdsp) - return AVERROR(ENOMEM); + { + AVFloatDSPContext *fdsp; + fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); + if (!fdsp) + return AVERROR(ENOMEM); + s->butterflies_float = fdsp->butterflies_float; + av_free(fdsp); + } #endif ff_mpadsp_init(&s->mpadsp); @@ -448,6 +307,8 @@ if (avctx->codec_id == AV_CODEC_ID_MP3ADU) s->adu_mode = 1; + ff_thread_once(&init_static_once, decode_init_static); + return 0; } @@ -499,12 +360,43 @@ out[11] = in0 + in5; } +static int handle_crc(MPADecodeContext *s, int sec_len) +{ + if (s->error_protection && (s->err_recognition & AV_EF_CRCCHECK)) { + const uint8_t *buf = s->gb.buffer - HEADER_SIZE; + int sec_byte_len = sec_len >> 3; + int sec_rem_bits = sec_len & 7; + const AVCRC *crc_tab = av_crc_get_table(AV_CRC_16_ANSI); + uint8_t tmp_buf[4]; + uint32_t crc_val = av_crc(crc_tab, UINT16_MAX, &buf[2], 2); + crc_val = av_crc(crc_tab, crc_val, &buf[6], sec_byte_len); + + AV_WB32(tmp_buf, + ((buf[6 + sec_byte_len] & (0xFF00 >> sec_rem_bits)) << 24) + + ((s->crc << 16) >> sec_rem_bits)); + + crc_val = av_crc(crc_tab, crc_val, tmp_buf, 3); + + if (crc_val) { + av_log(s->avctx, AV_LOG_ERROR, "CRC mismatch %X!\n", crc_val); + if (s->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + } + } + return 0; +} + /* return the number of decoded frames */ static int mp_decode_layer1(MPADecodeContext *s) { int bound, i, v, n, ch, j, mant; uint8_t allocation[MPA_MAX_CHANNELS][SBLIMIT]; uint8_t scale_factors[MPA_MAX_CHANNELS][SBLIMIT]; + int ret; + + ret = handle_crc(s, (s->nb_channels == 1) ? 8*16 : 8*32); + if (ret < 0) + return ret; if (s->mode == MPA_JSTEREO) bound = (s->mode_ext + 1) * 4; @@ -574,6 +466,7 @@ unsigned char scale_code[MPA_MAX_CHANNELS][SBLIMIT]; unsigned char scale_factors[MPA_MAX_CHANNELS][SBLIMIT][3], *sf; int scale, qindex, bits, steps, k, l, m, b; + int ret; /* select decoding table */ table = ff_mpa_l2_select_table(s->bit_rate / 1000, s->nb_channels, @@ -616,6 +509,10 @@ } } + ret = handle_crc(s, get_bits_count(&s->gb) - 16); + if (ret < 0) + return ret; + /* scale factors */ for (i = 0; i < sblimit; i++) { for (ch = 0; ch < s->nb_channels; ch++) { @@ -664,7 +561,7 @@ int v2; /* 3 values at the same time */ v = get_bits(&s->gb, -bits); - v2 = division_tabs[qindex][v]; + v2 = ff_division_tabs[qindex][v]; steps = ff_mpa_quant_steps[qindex]; s->sb_samples[ch][k * 12 + l + 0][i] = @@ -697,7 +594,7 @@ int mant, scale0, scale1; scale0 = scale_factors[0][i][k]; scale1 = scale_factors[1][i][k]; - qindex = alloc_table[j+b]; + qindex = alloc_table[j + b]; bits = ff_mpa_quant_bits[qindex]; if (bits < 0) { /* 3 values at the same time */ @@ -792,8 +689,8 @@ gain = g->global_gain - 210; shift = g->scalefac_scale + 1; - bstab = band_size_long[s->sample_rate_index]; - pretab = mpa_pretab[g->preflag]; + bstab = ff_band_size_long[s->sample_rate_index]; + pretab = ff_mpa_pretab[g->preflag]; for (i = 0; i < g->long_end; i++) { v0 = gain - ((g->scale_factors[i] + pretab[i]) << shift) + 400; len = bstab[i]; @@ -802,7 +699,7 @@ } if (g->short_start < 13) { - bstab = band_size_short[s->sample_rate_index]; + bstab = ff_band_size_short[s->sample_rate_index]; gains[0] = gain - (g->subblock_gain[0] << 3); gains[1] = gain - (g->subblock_gain[1] << 3); gains[2] = gain - (g->subblock_gain[2] << 3); @@ -867,9 +764,9 @@ continue; /* select vlc table */ k = g->table_select[i]; - l = mpa_huff_data[k][0]; - linbits = mpa_huff_data[k][1]; - vlc = &huff_vlc[l]; + l = ff_mpa_huff_data[k][0]; + linbits = ff_mpa_huff_data[k][1]; + vlc = &ff_huff_vlc[l]; if (!l) { memset(&g->sb_hybrid[s_index], 0, sizeof(*g->sb_hybrid) * 2 * j); @@ -891,8 +788,8 @@ y = get_vlc2(&s->gb, vlc->table, 7, 3); if (!y) { - g->sb_hybrid[s_index ] = - g->sb_hybrid[s_index+1] = 0; + g->sb_hybrid[s_index ] = + g->sb_hybrid[s_index + 1] = 0; s_index += 2; continue; } @@ -920,7 +817,7 @@ v = l3_unscale(y, exponent); if (get_bits1(&s->gb)) v = -v; - g->sb_hybrid[s_index+1] = v; + g->sb_hybrid[s_index + 1] = v; } } else { x = y >> 5; @@ -942,7 +839,7 @@ } /* high frequencies */ - vlc = &huff_quad_vlc[g->count1table_select]; + vlc = &ff_huff_quad_vlc[g->count1table_select]; last_pos = 0; while (s_index <= 572) { int pos, code; @@ -966,10 +863,10 @@ code = get_vlc2(&s->gb, vlc->table, vlc->bits, 1); ff_dlog(s->avctx, "t=%d code=%d\n", g->count1table_select, code); - g->sb_hybrid[s_index+0] = - g->sb_hybrid[s_index+1] = - g->sb_hybrid[s_index+2] = - g->sb_hybrid[s_index+3] = 0; + g->sb_hybrid[s_index + 0] = + g->sb_hybrid[s_index + 1] = + g->sb_hybrid[s_index + 2] = + g->sb_hybrid[s_index + 3] = 0; while (code) { static const int idxtab[16] = { 3,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0 }; int v; @@ -1019,7 +916,7 @@ } for (i = g->short_start; i < 13; i++) { - len = band_size_short[s->sample_rate_index][i]; + len = ff_band_size_short[s->sample_rate_index][i]; ptr1 = ptr; dst = tmp; for (j = len; j > 0; j--) { @@ -1039,7 +936,8 @@ { int i, j, k, l; int sf_max, sf, len, non_zero_found; - INTFLOAT (*is_tab)[16], *tab0, *tab1, v1, v2; + INTFLOAT *tab0, *tab1, v1, v2; + const INTFLOAT (*is_tab)[16]; SUINTFLOAT tmp0, tmp1; int non_zero_found_short[3]; @@ -1064,7 +962,7 @@ /* for last band, use previous scale factor */ if (i != 11) k -= 3; - len = band_size_short[s->sample_rate_index][i]; + len = ff_band_size_short[s->sample_rate_index][i]; for (l = 2; l >= 0; l--) { tab0 -= len; tab1 -= len; @@ -1108,7 +1006,7 @@ non_zero_found_short[2]; for (i = g1->long_end - 1;i >= 0;i--) { - len = band_size_long[s->sample_rate_index][i]; + len = ff_band_size_long[s->sample_rate_index][i]; tab0 -= len; tab1 -= len; /* test if non zero band. if so, stop doing i-stereo */ @@ -1150,7 +1048,7 @@ /* NOTE: the 1/sqrt(2) normalization factor is included in the global gain */ #if USE_FLOATS - s->fdsp->butterflies_float(g0->sb_hybrid, g1->sb_hybrid, 576); + s->butterflies_float(g0->sb_hybrid, g1->sb_hybrid, 576); #else tab0 = g0->sb_hybrid; tab1 = g1->sb_hybrid; @@ -1309,13 +1207,16 @@ int gr, ch, blocksplit_flag, i, j, k, n, bits_pos; GranuleDef *g; int16_t exponents[576]; //FIXME try INTFLOAT + int ret; /* read side info */ if (s->lsf) { + ret = handle_crc(s, ((s->nb_channels == 1) ? 8*9 : 8*17)); main_data_begin = get_bits(&s->gb, 8); skip_bits(&s->gb, s->nb_channels); nb_granules = 1; } else { + ret = handle_crc(s, ((s->nb_channels == 1) ? 8*17 : 8*32)); main_data_begin = get_bits(&s->gb, 9); if (s->nb_channels == 2) skip_bits(&s->gb, 3); @@ -1327,6 +1228,8 @@ s->granules[ch][1].scfsi = get_bits(&s->gb, 4); } } + if (ret < 0) + return ret; for (gr = 0; gr < nb_granules; gr++) { for (ch = 0; ch < s->nb_channels; ch++) { @@ -1390,7 +1293,7 @@ if (!s->adu_mode) { int skip; - const uint8_t *ptr = s->gb.buffer + (get_bits_count(&s->gb)>>3); + const uint8_t *ptr = s->gb.buffer + (get_bits_count(&s->gb) >> 3); s->extrasize = av_clip((get_bits_left(&s->gb) >> 3) - s->extrasize, 0, FFMAX(0, LAST_BUF_SIZE - s->last_buf_size)); av_assert1((get_bits_count(&s->gb) & 7) == 0); @@ -1434,8 +1337,8 @@ int slen, slen1, slen2; /* MPEG-1 scale factors */ - slen1 = slen_table[0][g->scalefac_compress]; - slen2 = slen_table[1][g->scalefac_compress]; + slen1 = ff_slen_table[0][g->scalefac_compress]; + slen2 = ff_slen_table[1][g->scalefac_compress]; ff_dlog(s->avctx, "slen1=%d slen2=%d\n", slen1, slen2); if (g->block_type == 2) { n = g->switch_point ? 17 : 18; @@ -1520,7 +1423,7 @@ j = 0; for (k = 0; k < 4; k++) { - n = lsf_nsf_table[tindex2][tindex][k]; + n = ff_lsf_nsf_table[tindex2][tindex][k]; sl = slen[k]; if (sl) { for (i = 0; i < n; i++) @@ -1564,10 +1467,8 @@ OUT_INT *samples_ptr; init_get_bits(&s->gb, buf + HEADER_SIZE, (buf_size - HEADER_SIZE) * 8); - - /* skip error protection field */ if (s->error_protection) - skip_bits(&s->gb, 16); + s->crc = get_bits(&s->gb, 16); switch(s->layer) { case 1: @@ -1588,7 +1489,7 @@ align_get_bits(&s->gb); i = (get_bits_left(&s->gb) >> 3) - s->extrasize; if (i >= 0 && i <= BACKSTEP_SIZE) { - memmove(s->last_buf, s->gb.buffer + (get_bits_count(&s->gb)>>3), i); + memmove(s->last_buf, s->gb.buffer + (get_bits_count(&s->gb) >> 3), i); s->last_buf_size=i; } else av_log(s->avctx, AV_LOG_ERROR, "invalid old backstep %d\n", i); @@ -1665,7 +1566,7 @@ return AVERROR_INVALIDDATA; header = AV_RB32(buf); - if (header>>8 == AV_RB32("TAG")>>8) { + if (header >> 8 == AV_RB32("TAG") >> 8) { av_log(avctx, AV_LOG_DEBUG, "discarding ID3 tag\n"); return buf_size + skipped; } @@ -1830,9 +1731,6 @@ MP3On4DecodeContext *s = avctx->priv_data; int i; - if (s->mp3decctx[0]) - av_freep(&s->mp3decctx[0]->fdsp); - for (i = 0; i < s->frames; i++) av_freep(&s->mp3decctx[i]); @@ -1844,15 +1742,15 @@ { MP3On4DecodeContext *s = avctx->priv_data; MPEG4AudioConfig cfg; - int i; + int i, ret; if ((avctx->extradata_size < 2) || !avctx->extradata) { av_log(avctx, AV_LOG_ERROR, "Codec extradata missing or too short.\n"); return AVERROR_INVALIDDATA; } - avpriv_mpeg4audio_get_config(&cfg, avctx->extradata, - avctx->extradata_size * 8, 1); + avpriv_mpeg4audio_get_config2(&cfg, avctx->extradata, + avctx->extradata_size, 1, avctx); if (!cfg.chan_config || cfg.chan_config > 7) { av_log(avctx, AV_LOG_ERROR, "Invalid channel config number.\n"); return AVERROR_INVALIDDATA; @@ -1875,12 +1773,14 @@ // Allocate zeroed memory for the first decoder context s->mp3decctx[0] = av_mallocz(sizeof(MPADecodeContext)); if (!s->mp3decctx[0]) - goto alloc_fail; + return AVERROR(ENOMEM); // Put decoder context in place to make init_decode() happy avctx->priv_data = s->mp3decctx[0]; - decode_init(avctx); + ret = decode_init(avctx); // Restore mp3on4 context pointer avctx->priv_data = s; + if (ret < 0) + return ret; s->mp3decctx[0]->adu_mode = 1; // Set adu mode /* Create a separate codec/context for each frame (first is already ok). @@ -1889,17 +1789,14 @@ for (i = 1; i < s->frames; i++) { s->mp3decctx[i] = av_mallocz(sizeof(MPADecodeContext)); if (!s->mp3decctx[i]) - goto alloc_fail; + return AVERROR(ENOMEM); s->mp3decctx[i]->adu_mode = 1; s->mp3decctx[i]->avctx = avctx; s->mp3decctx[i]->mpadsp = s->mp3decctx[0]->mpadsp; - s->mp3decctx[i]->fdsp = s->mp3decctx[0]->fdsp; + s->mp3decctx[i]->butterflies_float = s->mp3decctx[0]->butterflies_float; } return 0; -alloc_fail: - decode_close_mp3on4(avctx); - return AVERROR(ENOMEM); } diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudiodsp.c ffmpeg-4.4/libavcodec/mpegaudiodsp.c --- ffmpeg-4.2.2/libavcodec/mpegaudiodsp.c 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudiodsp.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,20 +21,69 @@ #include "config.h" #include "libavutil/attributes.h" #include "libavutil/thread.h" +#include "mpegaudio.h" #include "mpegaudiodsp.h" #include "dct.h" #include "dct32.h" -static AVOnce mpadsp_float_table_init = AV_ONCE_INIT; -static AVOnce mpadsp_fixed_table_init = AV_ONCE_INIT; +static AVOnce mpadsp_table_init = AV_ONCE_INIT; + +static av_cold void mpadsp_init_tabs(void) +{ + int i, j; + /* compute mdct windows */ + for (i = 0; i < 36; i++) { + for (j = 0; j < 4; j++) { + double d; + + if (j == 2 && i % 3 != 1) + continue; + + d = sin(M_PI * (i + 0.5) / 36.0); + if (j == 1) { + if (i >= 30) d = 0; + else if (i >= 24) d = sin(M_PI * (i - 18 + 0.5) / 12.0); + else if (i >= 18) d = 1; + } else if (j == 3) { + if (i < 6) d = 0; + else if (i < 12) d = sin(M_PI * (i - 6 + 0.5) / 12.0); + else if (i < 18) d = 1; + } + //merge last stage of imdct into the window coefficients + d *= 0.5 * IMDCT_SCALAR / cos(M_PI * (2 * i + 19) / 72); + + if (j == 2) { + ff_mdct_win_float[j][i/3] = d / (1 << 5); + ff_mdct_win_fixed[j][i/3] = d / (1 << 5) * (1LL << 32) + 0.5; + } else { + int idx = i < 18 ? i : i + (MDCT_BUF_SIZE/2 - 18); + ff_mdct_win_float[j][idx] = d / (1 << 5); + ff_mdct_win_fixed[j][idx] = d / (1 << 5) * (1LL << 32) + 0.5; + } + } + } + + /* NOTE: we do frequency inversion after the MDCT by changing + the sign of the right window coefs */ + for (j = 0; j < 4; j++) { + for (i = 0; i < MDCT_BUF_SIZE; i += 2) { + ff_mdct_win_float[j + 4][i ] = ff_mdct_win_float[j][i ]; + ff_mdct_win_float[j + 4][i + 1] = -ff_mdct_win_float[j][i + 1]; + ff_mdct_win_fixed[j + 4][i ] = ff_mdct_win_fixed[j][i ]; + ff_mdct_win_fixed[j + 4][i + 1] = -ff_mdct_win_fixed[j][i + 1]; + } + } + + if (ARCH_X86) + ff_mpadsp_init_x86_tabs(); +} av_cold void ff_mpadsp_init(MPADSPContext *s) { DCTContext dct; ff_dct_init(&dct, 5, DCT_II); - ff_thread_once(&mpadsp_float_table_init, &ff_init_mpadsp_tabs_float); - ff_thread_once(&mpadsp_fixed_table_init, &ff_init_mpadsp_tabs_fixed); + ff_thread_once(&mpadsp_table_init, &mpadsp_init_tabs); s->apply_window_float = ff_mpadsp_apply_window_float; s->apply_window_fixed = ff_mpadsp_apply_window_fixed; diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudiodsp.h ffmpeg-4.4/libavcodec/mpegaudiodsp.h --- ffmpeg-4.2.2/libavcodec/mpegaudiodsp.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudiodsp.h 2021-04-08 21:28:39.000000000 +0000 @@ -63,11 +63,12 @@ void ff_mpadsp_init_arm(MPADSPContext *s); void ff_mpadsp_init_ppc(MPADSPContext *s); void ff_mpadsp_init_x86(MPADSPContext *s); +void ff_mpadsp_init_x86_tabs(void); void ff_mpadsp_init_mipsfpu(MPADSPContext *s); void ff_mpadsp_init_mipsdsp(MPADSPContext *s); -void ff_mpa_synth_init_float(float *window); -void ff_mpa_synth_init_fixed(int32_t *window); +void ff_mpa_synth_init_float(void); +void ff_mpa_synth_init_fixed(void); void ff_mpadsp_apply_window_float(float *synth_buf, float *window, int *dither_state, float *samples, @@ -82,9 +83,6 @@ void ff_imdct36_blocks_fixed(int *out, int *buf, int *in, int count, int switch_point, int block_type); -void ff_init_mpadsp_tabs_float(void); -void ff_init_mpadsp_tabs_fixed(void); - /** For SSE implementation, MDCT_BUF_SIZE/2 should be 128-bit aligned */ #define MDCT_BUF_SIZE FFALIGN(36, 2*4) diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudiodsp_template.c ffmpeg-4.4/libavcodec/mpegaudiodsp_template.c --- ffmpeg-4.2.2/libavcodec/mpegaudiodsp_template.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudiodsp_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,9 @@ #include "libavutil/attributes.h" #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" +#include "libavutil/thread.h" + #include "dct32.h" #include "mathops.h" #include "mpegaudiodsp.h" @@ -192,7 +195,7 @@ *synth_buf_offset = offset; } -av_cold void RENAME(ff_mpa_synth_init)(MPA_INT *window) +static av_cold void mpa_synth_init(MPA_INT *window) { int i, j; @@ -221,48 +224,17 @@ window[512+128+16*i+j] = window[64*i+48-j]; } -av_cold void RENAME(ff_init_mpadsp_tabs)(void) +static av_cold void mpa_synth_window_init(void) { - int i, j; - /* compute mdct windows */ - for (i = 0; i < 36; i++) { - for (j = 0; j < 4; j++) { - double d; - - if (j == 2 && i % 3 != 1) - continue; - - d = sin(M_PI * (i + 0.5) / 36.0); - if (j == 1) { - if (i >= 30) d = 0; - else if (i >= 24) d = sin(M_PI * (i - 18 + 0.5) / 12.0); - else if (i >= 18) d = 1; - } else if (j == 3) { - if (i < 6) d = 0; - else if (i < 12) d = sin(M_PI * (i - 6 + 0.5) / 12.0); - else if (i < 18) d = 1; - } - //merge last stage of imdct into the window coefficients - d *= 0.5 * IMDCT_SCALAR / cos(M_PI * (2 * i + 19) / 72); - - if (j == 2) - RENAME(ff_mdct_win)[j][i/3] = FIXHR((d / (1<<5))); - else { - int idx = i < 18 ? i : i + (MDCT_BUF_SIZE/2 - 18); - RENAME(ff_mdct_win)[j][idx] = FIXHR((d / (1<<5))); - } - } - } + mpa_synth_init(RENAME(ff_mpa_synth_window)); +} - /* NOTE: we do frequency inversion adter the MDCT by changing - the sign of the right window coefs */ - for (j = 0; j < 4; j++) { - for (i = 0; i < MDCT_BUF_SIZE; i += 2) { - RENAME(ff_mdct_win)[j + 4][i ] = RENAME(ff_mdct_win)[j][i ]; - RENAME(ff_mdct_win)[j + 4][i + 1] = -RENAME(ff_mdct_win)[j][i + 1]; - } - } +av_cold void RENAME(ff_mpa_synth_init)(void) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, mpa_synth_window_init); } + /* cos(pi*i/18) */ #define C1 FIXHR(0.98480775301220805936/2) #define C2 FIXHR(0.93969262078590838405/2) diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudioenc_template.c ffmpeg-4.4/libavcodec/mpegaudioenc_template.c --- ffmpeg-4.2.2/libavcodec/mpegaudioenc_template.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudioenc_template.c 2020-07-09 09:17:46.000000000 +0000 @@ -701,7 +701,7 @@ /* normalize to P bits */ if (shift < 0) - q1 = sample << (-shift); + q1 = sample * (1 << -shift); else q1 = sample >> shift; q1 = (q1 * mult) >> P; diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudio_tablegen.c ffmpeg-4.4/libavcodec/mpegaudio_tablegen.c --- ffmpeg-4.2.2/libavcodec/mpegaudio_tablegen.c 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudio_tablegen.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include #define CONFIG_HARDCODED_TABLES 0 +#define BUILD_TABLES #include "libavutil/tablegen.h" #include "mpegaudio_tablegen.h" #include "tableprint.h" @@ -32,8 +33,6 @@ write_fileheader(); - WRITE_ARRAY("static const", int8_t, table_4_3_exp); - WRITE_ARRAY("static const", uint32_t, table_4_3_value); WRITE_ARRAY("static const", uint32_t, exp_table_fixed); WRITE_ARRAY("static const", float, exp_table_float); WRITE_2D_ARRAY("static const", uint32_t, expval_table_fixed); diff -Nru ffmpeg-4.2.2/libavcodec/mpegaudio_tablegen.h ffmpeg-4.4/libavcodec/mpegaudio_tablegen.h --- ffmpeg-4.2.2/libavcodec/mpegaudio_tablegen.h 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegaudio_tablegen.h 2021-04-08 21:28:39.000000000 +0000 @@ -27,19 +27,22 @@ #include #include "libavutil/attributes.h" -#define TABLE_4_3_SIZE (8191 + 16)*4 #if CONFIG_HARDCODED_TABLES #define mpegaudio_tableinit() #include "libavcodec/mpegaudio_tables.h" #else -static int8_t table_4_3_exp[TABLE_4_3_SIZE]; -static uint32_t table_4_3_value[TABLE_4_3_SIZE]; +#if defined(BUILD_TABLES) || !USE_FLOATS +#define FIXED_TABLE static uint32_t exp_table_fixed[512]; static uint32_t expval_table_fixed[512][16]; +#endif + +#if defined(BUILD_TABLES) || USE_FLOATS +#define FLOAT_TABLE static float exp_table_float[512]; static float expval_table_float[512][16]; +#endif -#define FRAC_BITS 23 #define IMDCT_SCALAR 1.759 static av_cold void mpegaudio_tableinit(void) @@ -51,41 +54,36 @@ M_SQRT2 , /* 2 ^ (2 * 0.25) */ 1.68179283050742908606, /* 2 ^ (3 * 0.25) */ }; - static double pow43_lut[16]; + double pow43_lut[16]; double exp2_base = 2.11758236813575084767080625169910490512847900390625e-22; // 2^(-72) double exp2_val; - double pow43_val = 0; + for (i = 0; i < 16; ++i) pow43_lut[i] = i * cbrt(i); - for (i = 1; i < TABLE_4_3_SIZE; i++) { - double f, fm; - int e, m; - double value = i / 4; - if ((i & 3) == 0) - pow43_val = value / IMDCT_SCALAR * cbrt(value); - f = pow43_val * exp2_lut[i & 3]; - fm = frexp(f, &e); - m = llrint(fm * (1LL << 31)); - e += FRAC_BITS - 31 + 5 - 100; - - /* normalized to FRAC_BITS */ - table_4_3_value[i] = m; - table_4_3_exp[i] = -e; - } for (exponent = 0; exponent < 512; exponent++) { if (exponent && (exponent & 3) == 0) exp2_base *= 2; exp2_val = exp2_base * exp2_lut[exponent & 3] / IMDCT_SCALAR; for (value = 0; value < 16; value++) { double f = pow43_lut[value] * exp2_val; +#ifdef FIXED_TABLE expval_table_fixed[exponent][value] = (f < 0xFFFFFFFF ? llrint(f) : 0xFFFFFFFF); +#endif +#ifdef FLOAT_TABLE expval_table_float[exponent][value] = f; +#endif } +#ifdef FIXED_TABLE exp_table_fixed[exponent] = expval_table_fixed[exponent][1]; +#endif +#ifdef FLOAT_TABLE exp_table_float[exponent] = expval_table_float[exponent][1]; +#endif } } +#undef FLOAT_TABLE +#undef FIXED_TABLE #endif /* CONFIG_HARDCODED_TABLES */ #endif /* AVCODEC_MPEGAUDIO_TABLEGEN_H */ diff -Nru ffmpeg-4.2.2/libavcodec/mpegpicture.c ffmpeg-4.4/libavcodec/mpegpicture.c --- ffmpeg-4.2.2/libavcodec/mpegpicture.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegpicture.c 2021-04-08 21:28:39.000000000 +0000 @@ -78,20 +78,18 @@ // at uvlinesize. It supports only YUV420 so 24x24 is enough // linesize * interlaced * MBsize // we also use this buffer for encoding in encode_mb_internal() needig an additional 32 lines - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, sc->edge_emu_buffer, alloc_size, EMU_EDGE_HEIGHT, - fail); + if (!FF_ALLOCZ_TYPED_ARRAY(sc->edge_emu_buffer, alloc_size * EMU_EDGE_HEIGHT) || + !FF_ALLOCZ_TYPED_ARRAY(me->scratchpad, alloc_size * 4 * 16 * 2)) { + av_freep(&sc->edge_emu_buffer); + return AVERROR(ENOMEM); + } - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, me->scratchpad, alloc_size, 4 * 16 * 2, - fail) me->temp = me->scratchpad; sc->rd_scratchpad = me->scratchpad; sc->b_scratchpad = me->scratchpad; sc->obmc_scratchpad = me->scratchpad + 16; return 0; -fail: - av_freep(&sc->edge_emu_buffer); - return AVERROR(ENOMEM); } /** @@ -208,10 +206,7 @@ } if (out_format == FMT_H263 || encoding || -#if FF_API_DEBUG_MV - avctx->debug_mv || -#endif - (avctx->flags2 & AV_CODEC_FLAG2_EXPORT_MVS)) { + (avctx->export_side_data & AV_CODEC_EXPORT_DATA_MVS)) { int mv_size = 2 * (b8_array_size + 4) * sizeof(int16_t); int ref_index_size = 4 * mb_array_size; @@ -225,6 +220,7 @@ pic->alloc_mb_width = mb_width; pic->alloc_mb_height = mb_height; + pic->alloc_mb_stride = mb_stride; return 0; } @@ -320,30 +316,22 @@ int ff_update_picture_tables(Picture *dst, Picture *src) { - int i; + int i, ret; -#define UPDATE_TABLE(table) \ -do { \ - if (src->table && \ - (!dst->table || dst->table->buffer != src->table->buffer)) { \ - av_buffer_unref(&dst->table); \ - dst->table = av_buffer_ref(src->table); \ - if (!dst->table) { \ - ff_free_picture_tables(dst); \ - return AVERROR(ENOMEM); \ - } \ - } \ -} while (0) - - UPDATE_TABLE(mb_var_buf); - UPDATE_TABLE(mc_mb_var_buf); - UPDATE_TABLE(mb_mean_buf); - UPDATE_TABLE(mbskip_table_buf); - UPDATE_TABLE(qscale_table_buf); - UPDATE_TABLE(mb_type_buf); + ret = av_buffer_replace(&dst->mb_var_buf, src->mb_var_buf); + ret |= av_buffer_replace(&dst->mc_mb_var_buf, src->mc_mb_var_buf); + ret |= av_buffer_replace(&dst->mb_mean_buf, src->mb_mean_buf); + ret |= av_buffer_replace(&dst->mbskip_table_buf, src->mbskip_table_buf); + ret |= av_buffer_replace(&dst->qscale_table_buf, src->qscale_table_buf); + ret |= av_buffer_replace(&dst->mb_type_buf, src->mb_type_buf); for (i = 0; i < 2; i++) { - UPDATE_TABLE(motion_val_buf[i]); - UPDATE_TABLE(ref_index_buf[i]); + ret |= av_buffer_replace(&dst->motion_val_buf[i], src->motion_val_buf[i]); + ret |= av_buffer_replace(&dst->ref_index_buf[i], src->ref_index_buf[i]); + } + + if (ret < 0) { + ff_free_picture_tables(dst); + return ret; } dst->mb_var = src->mb_var; @@ -359,6 +347,7 @@ dst->alloc_mb_width = src->alloc_mb_width; dst->alloc_mb_height = src->alloc_mb_height; + dst->alloc_mb_stride = src->alloc_mb_stride; return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/mpegpicture.h ffmpeg-4.4/libavcodec/mpegpicture.h --- ffmpeg-4.2.2/libavcodec/mpegpicture.h 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegpicture.h 2021-04-08 21:28:39.000000000 +0000 @@ -69,6 +69,7 @@ int alloc_mb_width; ///< mb_width used to allocate tables int alloc_mb_height; ///< mb_height used to allocate tables + int alloc_mb_stride; ///< mb_stride used to allocate tables AVBufferRef *mb_mean_buf; uint8_t *mb_mean; ///< Table for MB luminance diff -Nru ffmpeg-4.2.2/libavcodec/mpegutils.c ffmpeg-4.4/libavcodec/mpegutils.c --- ffmpeg-4.2.2/libavcodec/mpegutils.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegutils.c 2021-04-08 21:28:39.000000000 +0000 @@ -105,7 +105,7 @@ int *low_delay, int mb_width, int mb_height, int mb_stride, int quarter_sample) { - if ((avctx->flags2 & AV_CODEC_FLAG2_EXPORT_MVS) && mbtype_table && motion_val[0]) { + if ((avctx->export_side_data & AV_CODEC_EXPORT_DATA_MVS) && mbtype_table && motion_val[0]) { const int shift = 1 + quarter_sample; const int scale = 1 << shift; const int mv_sample_log2 = avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_SVQ3 ? 2 : 1; @@ -262,132 +262,4 @@ av_log(avctx, AV_LOG_DEBUG, "\n"); } } - -#if FF_API_DEBUG_MV - if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || - (avctx->debug_mv)) { - int mb_y; - int i, ret; - int h_chroma_shift, v_chroma_shift, block_height; - const int mv_sample_log2 = avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_SVQ3 ? 2 : 1; - const int mv_stride = (mb_width << mv_sample_log2) + - (avctx->codec->id == AV_CODEC_ID_H264 ? 0 : 1); - - if (low_delay) - *low_delay = 0; // needed to see the vectors without trashing the buffers - - ret = av_pix_fmt_get_chroma_sub_sample (avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift); - if (ret) - return ret; - - av_frame_make_writable(pict); - - pict->opaque = NULL; - block_height = 16 >> v_chroma_shift; - - for (mb_y = 0; mb_y < mb_height; mb_y++) { - int mb_x; - for (mb_x = 0; mb_x < mb_width; mb_x++) { - const int mb_index = mb_x + mb_y * mb_stride; - if ((avctx->debug & FF_DEBUG_VIS_QP)) { - uint64_t c = (qscale_table[mb_index] * 128 / 31) * - 0x0101010101010101ULL; - int y; - for (y = 0; y < block_height; y++) { - *(uint64_t *)(pict->data[1] + 8 * mb_x + - (block_height * mb_y + y) * - pict->linesize[1]) = c; - *(uint64_t *)(pict->data[2] + 8 * mb_x + - (block_height * mb_y + y) * - pict->linesize[2]) = c; - } - } - if ((avctx->debug & FF_DEBUG_VIS_MB_TYPE) && - motion_val[0]) { - int mb_type = mbtype_table[mb_index]; - uint64_t u,v; - int y; -#define COLOR(theta, r) \ - u = (int)(128 + r * cos(theta * M_PI / 180)); \ - v = (int)(128 + r * sin(theta * M_PI / 180)); - - - u = v = 128; - if (IS_PCM(mb_type)) { - COLOR(120, 48) - } else if ((IS_INTRA(mb_type) && IS_ACPRED(mb_type)) || - IS_INTRA16x16(mb_type)) { - COLOR(30, 48) - } else if (IS_INTRA4x4(mb_type)) { - COLOR(90, 48) - } else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type)) { - // COLOR(120, 48) - } else if (IS_DIRECT(mb_type)) { - COLOR(150, 48) - } else if (IS_GMC(mb_type) && IS_SKIP(mb_type)) { - COLOR(170, 48) - } else if (IS_GMC(mb_type)) { - COLOR(190, 48) - } else if (IS_SKIP(mb_type)) { - // COLOR(180, 48) - } else if (!USES_LIST(mb_type, 1)) { - COLOR(240, 48) - } else if (!USES_LIST(mb_type, 0)) { - COLOR(0, 48) - } else { - av_assert2(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); - COLOR(300,48) - } - - u *= 0x0101010101010101ULL; - v *= 0x0101010101010101ULL; - for (y = 0; y < block_height; y++) { - *(uint64_t *)(pict->data[1] + 8 * mb_x + - (block_height * mb_y + y) * pict->linesize[1]) = u; - *(uint64_t *)(pict->data[2] + 8 * mb_x + - (block_height * mb_y + y) * pict->linesize[2]) = v; - } - - // segmentation - if (IS_8X8(mb_type) || IS_16X8(mb_type)) { - *(uint64_t *)(pict->data[0] + 16 * mb_x + 0 + - (16 * mb_y + 8) * pict->linesize[0]) ^= 0x8080808080808080ULL; - *(uint64_t *)(pict->data[0] + 16 * mb_x + 8 + - (16 * mb_y + 8) * pict->linesize[0]) ^= 0x8080808080808080ULL; - } - if (IS_8X8(mb_type) || IS_8X16(mb_type)) { - for (y = 0; y < 16; y++) - pict->data[0][16 * mb_x + 8 + (16 * mb_y + y) * - pict->linesize[0]] ^= 0x80; - } - if (IS_8X8(mb_type) && mv_sample_log2 >= 2) { - int dm = 1 << (mv_sample_log2 - 2); - for (i = 0; i < 4; i++) { - int sx = mb_x * 16 + 8 * (i & 1); - int sy = mb_y * 16 + 8 * (i >> 1); - int xy = (mb_x * 2 + (i & 1) + - (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); - // FIXME bidir - int32_t *mv = (int32_t *) &motion_val[0][xy]; - if (mv[0] != mv[dm] || - mv[dm * mv_stride] != mv[dm * (mv_stride + 1)]) - for (y = 0; y < 8; y++) - pict->data[0][sx + 4 + (sy + y) * pict->linesize[0]] ^= 0x80; - if (mv[0] != mv[dm * mv_stride] || mv[dm] != mv[dm * (mv_stride + 1)]) - *(uint64_t *)(pict->data[0] + sx + (sy + 4) * - pict->linesize[0]) ^= 0x8080808080808080ULL; - } - } - - if (IS_INTERLACED(mb_type) && - avctx->codec->id == AV_CODEC_ID_H264) { - // hmm - } - } - if (mbskip_table) - mbskip_table[mb_index] = 0; - } - } - } -#endif } diff -Nru ffmpeg-4.2.2/libavcodec/mpegutils.h ffmpeg-4.4/libavcodec/mpegutils.h --- ffmpeg-4.2.2/libavcodec/mpegutils.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegutils.h 2021-04-08 21:28:39.000000000 +0000 @@ -125,6 +125,7 @@ FMT_H261, FMT_H263, FMT_MJPEG, + FMT_SPEEDHQ, }; diff -Nru ffmpeg-4.2.2/libavcodec/mpegvideo.c ffmpeg-4.4/libavcodec/mpegvideo.c --- ffmpeg-4.2.2/libavcodec/mpegvideo.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegvideo.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,7 +32,8 @@ #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/motion_vector.h" -#include "libavutil/timer.h" +#include "libavutil/video_enc_params.h" + #include "avcodec.h" #include "blockdsp.h" #include "h264chroma.h" @@ -347,9 +348,9 @@ ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); } -static int alloc_picture(MpegEncContext *s, Picture *pic, int shared) +static int alloc_picture(MpegEncContext *s, Picture *pic) { - return ff_alloc_picture(s->avctx, pic, &s->me, &s->sc, shared, 0, + 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); @@ -365,33 +366,28 @@ if (s->mb_height & 1) yc_size += 2*s->b8_stride + 2*s->mb_stride; - s->sc.edge_emu_buffer = - s->me.scratchpad = - s->me.temp = - s->sc.rd_scratchpad = - s->sc.b_scratchpad = - s->sc.obmc_scratchpad = NULL; - if (s->encoding) { - FF_ALLOCZ_OR_GOTO(s->avctx, s->me.map, - ME_MAP_SIZE * sizeof(uint32_t), fail) - FF_ALLOCZ_OR_GOTO(s->avctx, s->me.score_map, - ME_MAP_SIZE * sizeof(uint32_t), fail) + if (!FF_ALLOCZ_TYPED_ARRAY(s->me.map, ME_MAP_SIZE) || + !FF_ALLOCZ_TYPED_ARRAY(s->me.score_map, ME_MAP_SIZE)) + return AVERROR(ENOMEM); + if (s->noise_reduction) { - FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_error_sum, - 2 * 64 * sizeof(int), fail) + if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_error_sum, 2)) + return AVERROR(ENOMEM); } } - FF_ALLOCZ_OR_GOTO(s->avctx, s->blocks, 64 * 12 * 2 * sizeof(int16_t), fail) + if (!FF_ALLOCZ_TYPED_ARRAY(s->blocks, 2)) + return AVERROR(ENOMEM); s->block = s->blocks[0]; for (i = 0; i < 12; i++) { s->pblocks[i] = &s->block[i]; } - FF_ALLOCZ_OR_GOTO(s->avctx, s->block32, sizeof(*s->block32), fail) + if (!(s->block32 = av_mallocz(sizeof(*s->block32))) || + !(s->dpcm_macroblock = av_mallocz(sizeof(*s->dpcm_macroblock)))) + return AVERROR(ENOMEM); s->dpcm_direction = 0; - FF_ALLOCZ_OR_GOTO(s->avctx, s->dpcm_macroblock, sizeof(*s->dpcm_macroblock), fail) if (s->avctx->codec_tag == AV_RL32("VCR2")) { // exchange uv @@ -400,16 +396,43 @@ if (s->out_format == FMT_H263) { /* ac values */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_val_base, - yc_size * sizeof(int16_t) * 16, fail); + if (!FF_ALLOCZ_TYPED_ARRAY(s->ac_val_base, yc_size)) + return AVERROR(ENOMEM); s->ac_val[0] = s->ac_val_base + s->b8_stride + 1; s->ac_val[1] = s->ac_val_base + y_size + s->mb_stride + 1; s->ac_val[2] = s->ac_val[1] + c_size; } return 0; -fail: - return -1; // free() through ff_mpv_common_end() +} + +/** + * 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 nb_slices = s->slice_context_count, ret; + + /* We initialize the copies before the original so that + * fields allocated in init_duplicate_context are NULL after + * copying. This prevents double-frees upon allocation error. */ + for (int i = 1; i < nb_slices; i++) { + s->thread_context[i] = av_memdup(s, sizeof(MpegEncContext)); + if (!s->thread_context[i]) + return AVERROR(ENOMEM); + if ((ret = init_duplicate_context(s->thread_context[i])) < 0) + return ret; + s->thread_context[i]->start_mb_y = + (s->mb_height * (i ) + nb_slices / 2) / nb_slices; + s->thread_context[i]->end_mb_y = + (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices; + } + s->start_mb_y = 0; + s->end_mb_y = nb_slices > 1 ? (s->mb_height + nb_slices / 2) / nb_slices + : s->mb_height; + return init_duplicate_context(s); } static void free_duplicate_context(MpegEncContext *s) @@ -434,6 +457,15 @@ s->block = NULL; } +static void free_duplicate_contexts(MpegEncContext *s) +{ + for (int i = 1; i < s->slice_context_count; i++) { + free_duplicate_context(s->thread_context[i]); + av_freep(&s->thread_context[i]); + } + free_duplicate_context(s); +} + static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src) { #define COPY(a) bak->a = src->a @@ -469,7 +501,6 @@ MpegEncContext bak; int i, ret; // FIXME copy only needed parts - // START_TIMER backup_duplicate_context(&bak, dst); memcpy(dst, src, sizeof(MpegEncContext)); backup_duplicate_context(dst, &bak); @@ -487,8 +518,6 @@ "scratch buffers.\n"); return ret; } - // STOP_TIMER("update_duplicate_context") - // about 10k cycles / 0.01 sec for 1000frames on 1ghz with 2 threads return 0; } @@ -526,7 +555,6 @@ } if (s->height != s1->height || s->width != s1->width || s->context_reinit) { - s->context_reinit = 0; s->height = s1->height; s->width = s1->width; if ((ret = ff_mpv_common_frame_size_change(s)) < 0) @@ -664,17 +692,14 @@ } /** - * Set the given MpegEncContext to defaults for decoding. + * Initialize the given MpegEncContext for decoding. * the changed fields will not depend upon * the prior state of the MpegEncContext. */ -void ff_mpv_decode_defaults(MpegEncContext *s) +void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx) { ff_mpv_common_defaults(s); -} -void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx) -{ s->avctx = avctx; s->width = avctx->coded_width; s->height = avctx->coded_height; @@ -719,8 +744,8 @@ if (s->mb_height & 1) yc_size += 2*s->b8_stride + 2*s->mb_stride; - FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num + 1) * sizeof(int), - fail); // error resilience code looks cleaner with this + if (!FF_ALLOCZ_TYPED_ARRAY(s->mb_index2xy, s->mb_num + 1)) + return AVERROR(ENOMEM); for (y = 0; y < s->mb_height; y++) for (x = 0; x < s->mb_width; x++) s->mb_index2xy[x + y * s->mb_width] = x + y * s->mb_stride; @@ -729,12 +754,13 @@ if (s->encoding) { /* Allocate MV tables */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->p_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_forw_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_back_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_forw_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_back_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_direct_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) + if (!FF_ALLOCZ_TYPED_ARRAY(s->p_mv_table_base, mv_table_size) || + !FF_ALLOCZ_TYPED_ARRAY(s->b_forw_mv_table_base, mv_table_size) || + !FF_ALLOCZ_TYPED_ARRAY(s->b_back_mv_table_base, mv_table_size) || + !FF_ALLOCZ_TYPED_ARRAY(s->b_bidir_forw_mv_table_base, mv_table_size) || + !FF_ALLOCZ_TYPED_ARRAY(s->b_bidir_back_mv_table_base, mv_table_size) || + !FF_ALLOCZ_TYPED_ARRAY(s->b_direct_mv_table_base, mv_table_size)) + return AVERROR(ENOMEM); s->p_mv_table = s->p_mv_table_base + s->mb_stride + 1; s->b_forw_mv_table = s->b_forw_mv_table_base + s->mb_stride + 1; s->b_back_mv_table = s->b_back_mv_table_base + s->mb_stride + 1; @@ -743,15 +769,11 @@ s->b_direct_mv_table = s->b_direct_mv_table_base + s->mb_stride + 1; /* Allocate MB type table */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_type, mb_array_size * sizeof(uint16_t), fail) // needed for encoding - - FF_ALLOCZ_OR_GOTO(s->avctx, s->lambda_table, mb_array_size * sizeof(int), fail) - - FF_ALLOC_OR_GOTO(s->avctx, s->cplx_tab, - mb_array_size * sizeof(float), fail); - FF_ALLOC_OR_GOTO(s->avctx, s->bits_tab, - mb_array_size * sizeof(float), fail); - + if (!FF_ALLOCZ_TYPED_ARRAY(s->mb_type, mb_array_size) || + !FF_ALLOCZ_TYPED_ARRAY(s->lambda_table, mb_array_size) || + !FF_ALLOC_TYPED_ARRAY (s->cplx_tab, mb_array_size) || + !FF_ALLOC_TYPED_ARRAY (s->bits_tab, mb_array_size)) + return AVERROR(ENOMEM); } if (s->codec_id == AV_CODEC_ID_MPEG4 || @@ -761,34 +783,34 @@ int j, k; for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { - FF_ALLOCZ_OR_GOTO(s->avctx, - s->b_field_mv_table_base[i][j][k], - mv_table_size * 2 * sizeof(int16_t), - fail); + 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; } - FF_ALLOCZ_OR_GOTO(s->avctx, s->b_field_select_table [i][j], mb_array_size * 2 * sizeof(uint8_t), fail) - FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_mv_table_base[i][j], mv_table_size * 2 * sizeof(int16_t), fail) + 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; } - FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_select_table[i], mb_array_size * 2 * sizeof(uint8_t), fail) + 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 */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->coded_block_base, y_size + (s->mb_height&1)*2*s->b8_stride, fail); + /* 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)) + return AVERROR(ENOMEM); s->coded_block = s->coded_block_base + s->b8_stride + 1; - - /* cbp, ac_pred, pred_dir */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->cbp_table , mb_array_size * sizeof(uint8_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->pred_dir_table, mb_array_size * sizeof(uint8_t), fail); } if (s->h263_pred || s->h263_plus || !s->encoding) { /* dc values */ // MN: we need these for error resilience of intra-frames - FF_ALLOCZ_OR_GOTO(s->avctx, s->dc_val_base, yc_size * sizeof(int16_t), fail); + if (!FF_ALLOCZ_TYPED_ARRAY(s->dc_val_base, yc_size)) + return AVERROR(ENOMEM); s->dc_val[0] = s->dc_val_base + s->b8_stride + 1; s->dc_val[1] = s->dc_val_base + y_size + s->mb_stride + 1; s->dc_val[2] = s->dc_val[1] + c_size; @@ -796,17 +818,14 @@ s->dc_val_base[i] = 1024; } - /* which mb is an intra block */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->mbintra_table, mb_array_size, fail); + /* which mb is an intra block, init macroblock skip table */ + if (!FF_ALLOC_TYPED_ARRAY(s->mbintra_table, 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)) + return AVERROR(ENOMEM); memset(s->mbintra_table, 1, mb_array_size); - /* init macroblock skip table */ - FF_ALLOCZ_OR_GOTO(s->avctx, s->mbskip_table, mb_array_size + 2, fail); - // Note the + 1 is for a quicker MPEG-4 slice_end detection - return ff_mpeg_er_init(s); -fail: - return AVERROR(ENOMEM); } static void clear_context(MpegEncContext *s) @@ -911,7 +930,7 @@ if (s->avctx->pix_fmt == AV_PIX_FMT_NONE) { av_log(s->avctx, AV_LOG_ERROR, "decoding to AV_PIX_FMT_NONE is not supported.\n"); - return -1; + return AVERROR(EINVAL); } if (nb_slices > MAX_THREADS || (nb_slices > s->mb_height && s->mb_height)) { @@ -927,7 +946,7 @@ if ((s->width || s->height) && av_image_check_size(s->width, s->height, 0, s->avctx)) - return -1; + return AVERROR(EINVAL); dct_init(s); @@ -938,27 +957,21 @@ if (ret) return ret; - FF_ALLOCZ_OR_GOTO(s->avctx, s->picture, - MAX_PICTURE_COUNT * sizeof(Picture), fail); + if (!FF_ALLOCZ_TYPED_ARRAY(s->picture, MAX_PICTURE_COUNT)) + return AVERROR(ENOMEM); for (i = 0; i < MAX_PICTURE_COUNT; i++) { s->picture[i].f = av_frame_alloc(); if (!s->picture[i].f) - goto fail; + goto fail_nomem; } - s->next_picture.f = av_frame_alloc(); - if (!s->next_picture.f) - goto fail; - s->last_picture.f = av_frame_alloc(); - if (!s->last_picture.f) - goto fail; - s->current_picture.f = av_frame_alloc(); - if (!s->current_picture.f) - goto fail; - s->new_picture.f = av_frame_alloc(); - if (!s->new_picture.f) - goto fail; - if (init_context_frame(s)) + if (!(s->next_picture.f = av_frame_alloc()) || + !(s->last_picture.f = av_frame_alloc()) || + !(s->current_picture.f = av_frame_alloc()) || + !(s->new_picture.f = av_frame_alloc())) + goto fail_nomem; + + if ((ret = init_context_frame(s))) goto fail; s->parse_context.state = -1; @@ -966,39 +979,25 @@ s->context_initialized = 1; memset(s->thread_context, 0, sizeof(s->thread_context)); s->thread_context[0] = s; + s->slice_context_count = nb_slices; // if (s->width && s->height) { - if (nb_slices > 1) { - for (i = 0; i < nb_slices; i++) { - if (i) { - s->thread_context[i] = av_memdup(s, sizeof(MpegEncContext)); - if (!s->thread_context[i]) - goto fail; - } - if (init_duplicate_context(s->thread_context[i]) < 0) - goto fail; - s->thread_context[i]->start_mb_y = - (s->mb_height * (i) + nb_slices / 2) / nb_slices; - s->thread_context[i]->end_mb_y = - (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices; - } - } else { - if (init_duplicate_context(s) < 0) - goto fail; - s->start_mb_y = 0; - s->end_mb_y = s->mb_height; - } - s->slice_context_count = nb_slices; + ret = init_duplicate_contexts(s); + if (ret < 0) + goto fail; // } return 0; + fail_nomem: + ret = AVERROR(ENOMEM); fail: ff_mpv_common_end(s); - return -1; + return ret; } /** - * Frees and resets MpegEncContext fields depending on the resolution. + * 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. */ @@ -1006,6 +1005,8 @@ { int i, j, k; + free_duplicate_contexts(s); + av_freep(&s->mb_type); av_freep(&s->p_mv_table_base); av_freep(&s->b_forw_mv_table_base); @@ -1058,16 +1059,6 @@ if (!s->context_initialized) return AVERROR(EINVAL); - if (s->slice_context_count > 1) { - for (i = 0; i < s->slice_context_count; i++) { - free_duplicate_context(s->thread_context[i]); - } - for (i = 1; i < s->slice_context_count; i++) { - av_freep(&s->thread_context[i]); - } - } else - free_duplicate_context(s); - free_context_frame(s); if (s->picture) @@ -1089,6 +1080,13 @@ (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; @@ -1096,36 +1094,16 @@ s->thread_context[0] = s; if (s->width && s->height) { - int nb_slices = s->slice_context_count; - if (nb_slices > 1) { - for (i = 0; i < nb_slices; i++) { - if (i) { - s->thread_context[i] = av_memdup(s, sizeof(MpegEncContext)); - if (!s->thread_context[i]) { - err = AVERROR(ENOMEM); - goto fail; - } - } - if ((err = init_duplicate_context(s->thread_context[i])) < 0) - goto fail; - s->thread_context[i]->start_mb_y = - (s->mb_height * (i) + nb_slices / 2) / nb_slices; - s->thread_context[i]->end_mb_y = - (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices; - } - } else { - err = init_duplicate_context(s); - if (err < 0) - goto fail; - s->start_mb_y = 0; - s->end_mb_y = s->mb_height; - } - s->slice_context_count = nb_slices; + err = init_duplicate_contexts(s); + if (err < 0) + goto fail; } + s->context_reinit = 0; return 0; fail: - ff_mpv_common_end(s); + free_context_frame(s); + s->context_reinit = 1; return err; } @@ -1135,17 +1113,11 @@ int i; if (!s) - return ; + return; - if (s->slice_context_count > 1) { - for (i = 0; i < s->slice_context_count; i++) { - free_duplicate_context(s->thread_context[i]); - } - for (i = 1; i < s->slice_context_count; i++) { - av_freep(&s->thread_context[i]); - } + free_context_frame(s); + if (s->slice_context_count > 1) s->slice_context_count = 1; - } else free_duplicate_context(s); av_freep(&s->parse_context.buffer); s->parse_context.buffer_size = 0; @@ -1153,6 +1125,9 @@ av_freep(&s->bitstream_buffer); s->allocated_bitstream_buffer_size = 0; + if (!s->avctx) + return; + if (s->picture) { for (i = 0; i < MAX_PICTURE_COUNT; i++) { ff_free_picture_tables(&s->picture[i]); @@ -1174,9 +1149,8 @@ ff_mpeg_unref_picture(s->avctx, &s->new_picture); av_frame_free(&s->new_picture.f); - free_context_frame(s); - s->context_initialized = 0; + s->context_reinit = 0; s->last_picture_ptr = s->next_picture_ptr = s->current_picture_ptr = NULL; @@ -1263,7 +1237,7 @@ pic->f->coded_picture_number = s->coded_picture_number++; - if (alloc_picture(s, pic, 0) < 0) + if (alloc_picture(s, pic) < 0) return -1; s->current_picture_ptr = pic; @@ -1324,7 +1298,7 @@ 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) < 0) { + if (alloc_picture(s, s->last_picture_ptr) < 0) { s->last_picture_ptr = NULL; return -1; } @@ -1365,7 +1339,7 @@ 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) < 0) { + if (alloc_picture(s, s->next_picture_ptr) < 0) { s->next_picture_ptr = NULL; return -1; } @@ -1445,14 +1419,33 @@ int ff_mpv_export_qp_table(MpegEncContext *s, AVFrame *f, Picture *p, int qp_type) { - AVBufferRef *ref = av_buffer_ref(p->qscale_table_buf); - int offset = 2*s->mb_stride + 1; - if(!ref) + 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); - av_assert0(ref->size >= offset + s->mb_stride * ((f->height+15)/16)); - ref->size -= offset; - ref->data += offset; - return av_frame_set_qp_table(f, ref, s->mb_stride, qp_type); + + 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, diff -Nru ffmpeg-4.2.2/libavcodec/mpegvideodata.c ffmpeg-4.4/libavcodec/mpegvideodata.c --- ffmpeg-4.2.2/libavcodec/mpegvideodata.c 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegvideodata.c 2020-07-11 10:39:30.000000000 +0000 @@ -19,7 +19,6 @@ #include const uint8_t ff_default_chroma_qscale_table[32] = { -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; @@ -32,7 +31,6 @@ }; const uint8_t ff_mpeg1_dc_scale_table[128] = { -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, @@ -44,7 +42,6 @@ }; static const uint8_t mpeg2_dc_scale_table1[128] = { -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, @@ -56,7 +53,6 @@ }; static const uint8_t mpeg2_dc_scale_table2[128] = { -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -68,7 +64,6 @@ }; static const uint8_t mpeg2_dc_scale_table3[128] = { -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, diff -Nru ffmpeg-4.2.2/libavcodec/mpegvideo_enc.c ffmpeg-4.4/libavcodec/mpegvideo_enc.c --- ffmpeg-4.2.2/libavcodec/mpegvideo_enc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegvideo_enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -36,9 +36,10 @@ #include "libavutil/internal.h" #include "libavutil/intmath.h" #include "libavutil/mathematics.h" +#include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" -#include "libavutil/timer.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "dct.h" #include "idctdsp.h" @@ -52,6 +53,7 @@ #include "mathops.h" #include "mpegutils.h" #include "mjpegenc.h" +#include "speedhqenc.h" #include "msmpeg4.h" #include "pixblockdsp.h" #include "qpeldsp.h" @@ -64,7 +66,7 @@ #include "bytestream.h" #include "wmv2.h" #include "rv10.h" -#include "libxvid.h" +#include "packet_internal.h" #include #include "sp5x.h" @@ -165,7 +167,7 @@ } } if (shift) { - av_log(NULL, AV_LOG_INFO, + av_log(s->avctx, AV_LOG_INFO, "Warning, QMAT_SHIFT is larger than %d, overflows possible\n", QMAT_SHIFT - shift); } @@ -247,18 +249,24 @@ #undef COPY } +static void mpv_encode_init_static(void) +{ + for (int i = -16; i < 16; i++) + default_fcode_tab[i + MAX_MV] = 1; +} + /** * Set the given MpegEncContext to defaults for encoding. * the changed fields will not depend upon the prior state of the MpegEncContext. */ static void mpv_encode_defaults(MpegEncContext *s) { - int i; + static AVOnce init_static_once = AV_ONCE_INIT; + ff_mpv_common_defaults(s); - for (i = -16; i < 16; i++) { - default_fcode_tab[i + MAX_MV] = 1; - } + ff_thread_once(&init_static_once, mpv_encode_init_static); + s->me.mv_penalty = default_mv_penalty; s->fcode_tab = default_fcode_tab; @@ -299,7 +307,7 @@ avctx->pix_fmt != AV_PIX_FMT_YUV422P) { av_log(avctx, AV_LOG_ERROR, "only YUV420 and YUV422 are supported\n"); - return -1; + return AVERROR(EINVAL); } break; case AV_CODEC_ID_MJPEG: @@ -323,13 +331,22 @@ if (!format_supported) { av_log(avctx, AV_LOG_ERROR, "colorspace not supported in jpeg\n"); - return -1; + return AVERROR(EINVAL); + } + break; + case AV_CODEC_ID_SPEEDHQ: + if (avctx->pix_fmt != AV_PIX_FMT_YUV420P && + avctx->pix_fmt != AV_PIX_FMT_YUV422P && + avctx->pix_fmt != AV_PIX_FMT_YUV444P) { + av_log(avctx, AV_LOG_ERROR, + "only YUV420/YUV422/YUV444 are supported (no alpha support yet)\n"); + return AVERROR(EINVAL); } break; default: if (avctx->pix_fmt != AV_PIX_FMT_YUV420P) { av_log(avctx, AV_LOG_ERROR, "only YUV420 is supported\n"); - return -1; + return AVERROR(EINVAL); } } @@ -418,16 +435,16 @@ /* Fixed QSCALE */ s->fixed_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE); - s->adaptive_quant = (s->avctx->lumi_masking || - s->avctx->dark_masking || - s->avctx->temporal_cplx_masking || - s->avctx->spatial_cplx_masking || - s->avctx->p_masking || + s->adaptive_quant = (avctx->lumi_masking || + avctx->dark_masking || + avctx->temporal_cplx_masking || + avctx->spatial_cplx_masking || + avctx->p_masking || s->border_masking || (s->mpv_flags & FF_MPV_FLAG_QP_RD)) && !s->fixed_qscale; - s->loop_filter = !!(s->avctx->flags & AV_CODEC_FLAG_LOOP_FILTER); + s->loop_filter = !!(avctx->flags & AV_CODEC_FLAG_LOOP_FILTER); if (avctx->rc_max_rate && !avctx->rc_buffer_size) { switch(avctx->codec_id) { @@ -457,7 +474,7 @@ if ((!avctx->rc_max_rate) != (!avctx->rc_buffer_size)) { av_log(avctx, AV_LOG_ERROR, "Either both buffer size and max rate or neither must be specified\n"); - return -1; + return AVERROR(EINVAL); } if (avctx->rc_min_rate && avctx->rc_max_rate != avctx->rc_min_rate) { @@ -467,12 +484,12 @@ if (avctx->rc_min_rate && avctx->rc_min_rate > avctx->bit_rate) { av_log(avctx, AV_LOG_ERROR, "bitrate below min bitrate\n"); - return -1; + return AVERROR(EINVAL); } if (avctx->rc_max_rate && avctx->rc_max_rate < avctx->bit_rate) { av_log(avctx, AV_LOG_ERROR, "bitrate above max bitrate\n"); - return -1; + return AVERROR(EINVAL); } if (avctx->rc_max_rate && @@ -486,7 +503,7 @@ avctx->bit_rate * (int64_t)avctx->time_base.num > avctx->rc_buffer_size * (int64_t)avctx->time_base.den) { av_log(avctx, AV_LOG_ERROR, "VBV buffer too small for bitrate\n"); - return -1; + return AVERROR(EINVAL); } if (!s->fixed_qscale && @@ -497,33 +514,33 @@ avctx->bit_rate_tolerance = 5 * avctx->bit_rate * av_q2d(avctx->time_base); } - if (s->avctx->rc_max_rate && - s->avctx->rc_min_rate == s->avctx->rc_max_rate && + if (avctx->rc_max_rate && + avctx->rc_min_rate == avctx->rc_max_rate && (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) && 90000LL * (avctx->rc_buffer_size - 1) > - s->avctx->rc_max_rate * 0xFFFFLL) { + avctx->rc_max_rate * 0xFFFFLL) { av_log(avctx, AV_LOG_INFO, "Warning vbv_delay will be set to 0xFFFF (=VBR) as the " "specified vbv buffer is too large for the given bitrate!\n"); } - if ((s->avctx->flags & AV_CODEC_FLAG_4MV) && s->codec_id != AV_CODEC_ID_MPEG4 && + if ((avctx->flags & AV_CODEC_FLAG_4MV) && s->codec_id != AV_CODEC_ID_MPEG4 && s->codec_id != AV_CODEC_ID_H263 && s->codec_id != AV_CODEC_ID_H263P && s->codec_id != AV_CODEC_ID_FLV1) { av_log(avctx, AV_LOG_ERROR, "4MV not supported by codec\n"); - return -1; + return AVERROR(EINVAL); } - if (s->obmc && s->avctx->mb_decision != FF_MB_DECISION_SIMPLE) { + if (s->obmc && avctx->mb_decision != FF_MB_DECISION_SIMPLE) { av_log(avctx, AV_LOG_ERROR, "OBMC is only supported with simple mb decision\n"); - return -1; + return AVERROR(EINVAL); } if (s->quarter_sample && s->codec_id != AV_CODEC_ID_MPEG4) { av_log(avctx, AV_LOG_ERROR, "qpel not supported by codec\n"); - return -1; + return AVERROR(EINVAL); } if (s->max_b_frames && @@ -531,12 +548,12 @@ s->codec_id != AV_CODEC_ID_MPEG1VIDEO && s->codec_id != AV_CODEC_ID_MPEG2VIDEO) { av_log(avctx, AV_LOG_ERROR, "B-frames not supported by codec\n"); - return -1; + return AVERROR(EINVAL); } if (s->max_b_frames < 0) { av_log(avctx, AV_LOG_ERROR, "max b frames must be 0 or positive for mpegvideo based encoders\n"); - return -1; + return AVERROR(EINVAL); } if ((s->codec_id == AV_CODEC_ID_MPEG4 || @@ -556,28 +573,28 @@ (avctx->width > 2048 || avctx->height > 1152 )) { av_log(avctx, AV_LOG_ERROR, "H.263 does not support resolutions above 2048x1152\n"); - return -1; + return AVERROR(EINVAL); } if ((s->codec_id == AV_CODEC_ID_H263 || s->codec_id == AV_CODEC_ID_H263P) && ((avctx->width &3) || (avctx->height&3) )) { av_log(avctx, AV_LOG_ERROR, "w/h must be a multiple of 4\n"); - return -1; + return AVERROR(EINVAL); } if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO && (avctx->width > 4095 || avctx->height > 4095 )) { av_log(avctx, AV_LOG_ERROR, "MPEG-1 does not support resolutions above 4095x4095\n"); - return -1; + return AVERROR(EINVAL); } if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && (avctx->width > 16383 || avctx->height > 16383 )) { av_log(avctx, AV_LOG_ERROR, "MPEG-2 does not support resolutions above 16383x16383\n"); - return -1; + return AVERROR(EINVAL); } if (s->codec_id == AV_CODEC_ID_RV10 && @@ -597,20 +614,20 @@ if ((s->codec_id == AV_CODEC_ID_WMV1 || s->codec_id == AV_CODEC_ID_WMV2) && avctx->width & 1) { - av_log(avctx, AV_LOG_ERROR, "width must be multiple of 2\n"); - return -1; + av_log(avctx, AV_LOG_ERROR, "width must be multiple of 2\n"); + return AVERROR(EINVAL); } - if ((s->avctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME)) && + if ((avctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME)) && s->codec_id != AV_CODEC_ID_MPEG4 && s->codec_id != AV_CODEC_ID_MPEG2VIDEO) { av_log(avctx, AV_LOG_ERROR, "interlacing not supported by codec\n"); - return -1; + return AVERROR(EINVAL); } #if FF_API_PRIVATE_OPT FF_DISABLE_DEPRECATION_WARNINGS if (avctx->mpeg_quant) - s->mpeg_quant = avctx->mpeg_quant; + s->mpeg_quant = 1; FF_ENABLE_DEPRECATION_WARNINGS #endif @@ -619,18 +636,18 @@ && s->codec_id != AV_CODEC_ID_MPEG2VIDEO)) { av_log(avctx, AV_LOG_ERROR, "mpeg2 style quantization not supported by codec\n"); - return -1; + return AVERROR(EINVAL); } if ((s->mpv_flags & FF_MPV_FLAG_CBP_RD) && !avctx->trellis) { av_log(avctx, AV_LOG_ERROR, "CBP RD needs trellis quant\n"); - return -1; + return AVERROR(EINVAL); } if ((s->mpv_flags & FF_MPV_FLAG_QP_RD) && - s->avctx->mb_decision != FF_MB_DECISION_RD) { + avctx->mb_decision != FF_MB_DECISION_RD) { av_log(avctx, AV_LOG_ERROR, "QP RD needs mbd=2\n"); - return -1; + return AVERROR(EINVAL); } if ((s->mpv_flags & FF_MPV_FLAG_QP_RD) && @@ -639,7 +656,7 @@ // Used to produce garbage with MJPEG. av_log(avctx, AV_LOG_ERROR, "QP RD is no longer compatible with MJPEG or AMV\n"); - return -1; + return AVERROR(EINVAL); } #if FF_API_PRIVATE_OPT @@ -650,25 +667,25 @@ #endif if (s->scenechange_threshold < 1000000000 && - (s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP)) { + (avctx->flags & AV_CODEC_FLAG_CLOSED_GOP)) { av_log(avctx, AV_LOG_ERROR, "closed gop with scene change detection are not supported yet, " "set threshold to 1000000000\n"); - return -1; + return AVERROR_PATCHWELCOME; } - if (s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY) { + if (avctx->flags & AV_CODEC_FLAG_LOW_DELAY) { if (s->codec_id != AV_CODEC_ID_MPEG2VIDEO && s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) { av_log(avctx, AV_LOG_ERROR, "low delay forcing is only available for mpeg2, " "set strict_std_compliance to 'unofficial' or lower in order to allow it\n"); - return -1; + return AVERROR(EINVAL); } if (s->max_b_frames != 0) { av_log(avctx, AV_LOG_ERROR, "B-frames cannot be used with low delay\n"); - return -1; + return AVERROR(EINVAL); } } @@ -676,7 +693,7 @@ if (avctx->qmax > 28) { av_log(avctx, AV_LOG_ERROR, "non linear quant only supports qmax <= 28 currently\n"); - return -1; + return AVERROR_PATCHWELCOME; } } @@ -686,7 +703,7 @@ return AVERROR(EINVAL); } - if (s->avctx->thread_count > 1 && + 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 && @@ -694,19 +711,19 @@ (s->codec_id != AV_CODEC_ID_H263P)) { av_log(avctx, AV_LOG_ERROR, "multi threaded encoding not supported by codec\n"); - return -1; + return AVERROR_PATCHWELCOME; } - if (s->avctx->thread_count < 1) { + if (avctx->thread_count < 1) { av_log(avctx, AV_LOG_ERROR, "automatic thread number detection not supported by codec, " "patch welcome\n"); - return -1; + return AVERROR_PATCHWELCOME; } if (!avctx->time_base.den || !avctx->time_base.num) { av_log(avctx, AV_LOG_ERROR, "framerate not set\n"); - return -1; + return AVERROR(EINVAL); } #if FF_API_PRIVATE_OPT @@ -732,7 +749,7 @@ //return -1; } - if (s->mpeg_quant || 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_AMV) { + if (s->mpeg_quant || 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_AMV || s->codec_id == AV_CODEC_ID_SPEEDHQ) { // (a + x * 3 / 8) / x s->intra_quant_bias = 3 << (QUANT_BIAS_SHIFT - 3); s->inter_quant_bias = 0; @@ -750,25 +767,25 @@ av_log(avctx, AV_LOG_DEBUG, "intra_quant_bias = %d inter_quant_bias = %d\n",s->intra_quant_bias,s->inter_quant_bias); if (avctx->codec_id == AV_CODEC_ID_MPEG4 && - s->avctx->time_base.den > (1 << 16) - 1) { + avctx->time_base.den > (1 << 16) - 1) { av_log(avctx, AV_LOG_ERROR, "timebase %d/%d not supported by MPEG 4 standard, " "the maximum admitted value for the timebase denominator " - "is %d\n", s->avctx->time_base.num, s->avctx->time_base.den, + "is %d\n", avctx->time_base.num, avctx->time_base.den, (1 << 16) - 1); - return -1; + return AVERROR(EINVAL); } - s->time_increment_bits = av_log2(s->avctx->time_base.den - 1) + 1; + s->time_increment_bits = av_log2(avctx->time_base.den - 1) + 1; switch (avctx->codec->id) { case AV_CODEC_ID_MPEG1VIDEO: s->out_format = FMT_MPEG1; - s->low_delay = !!(s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY); + s->low_delay = !!(avctx->flags & AV_CODEC_FLAG_LOW_DELAY); avctx->delay = s->low_delay ? 0 : (s->max_b_frames + 1); break; case AV_CODEC_ID_MPEG2VIDEO: s->out_format = FMT_MPEG1; - s->low_delay = !!(s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY); + s->low_delay = !!(avctx->flags & AV_CODEC_FLAG_LOW_DELAY); avctx->delay = s->low_delay ? 0 : (s->max_b_frames + 1); s->rtp_mode = 1; break; @@ -776,21 +793,32 @@ case AV_CODEC_ID_AMV: s->out_format = FMT_MJPEG; s->intra_only = 1; /* force intra only for jpeg */ - if (!CONFIG_MJPEG_ENCODER || - ff_mjpeg_encode_init(s) < 0) - return -1; + if (!CONFIG_MJPEG_ENCODER) + return AVERROR_ENCODER_NOT_FOUND; + if ((ret = ff_mjpeg_encode_init(s)) < 0) + return ret; + avctx->delay = 0; + s->low_delay = 1; + break; + case AV_CODEC_ID_SPEEDHQ: + s->out_format = FMT_SPEEDHQ; + s->intra_only = 1; /* force intra only for SHQ */ + if (!CONFIG_SPEEDHQ_ENCODER) + return AVERROR_ENCODER_NOT_FOUND; + if ((ret = ff_speedhq_encode_init(s)) < 0) + return ret; avctx->delay = 0; s->low_delay = 1; break; case AV_CODEC_ID_H261: if (!CONFIG_H261_ENCODER) - return -1; + return AVERROR_ENCODER_NOT_FOUND; if (ff_h261_get_picture_format(s->width, s->height) < 0) { av_log(avctx, AV_LOG_ERROR, "The specified picture size of %dx%d is not valid for the " "H.261 codec.\nValid sizes are 176x144, 352x288\n", s->width, s->height); - return -1; + return AVERROR(EINVAL); } s->out_format = FMT_H261; avctx->delay = 0; @@ -799,7 +827,7 @@ break; case AV_CODEC_ID_H263: if (!CONFIG_H263_ENCODER) - return -1; + return AVERROR_ENCODER_NOT_FOUND; if (ff_match_2uint16(ff_h263_format, FF_ARRAY_ELEMS(ff_h263_format), s->width, s->height) == 8) { av_log(avctx, AV_LOG_ERROR, @@ -807,7 +835,7 @@ "the H.263 codec.\nValid sizes are 128x96, 176x144, " "352x288, 704x576, and 1408x1152. " "Try H.263+.\n", s->width, s->height); - return -1; + return AVERROR(EINVAL); } s->out_format = FMT_H263; avctx->delay = 0; @@ -893,7 +921,7 @@ s->low_delay = 1; break; default: - return -1; + return AVERROR(EINVAL); } #if FF_API_PRIVATE_OPT @@ -914,8 +942,8 @@ /* init */ ff_mpv_idct_init(s); - if (ff_mpv_common_init(s) < 0) - return -1; + if ((ret = ff_mpv_common_init(s)) < 0) + return ret; ff_fdctdsp_init(&s->fdsp, avctx); ff_me_cmp_init(&s->mecc, avctx); @@ -924,27 +952,25 @@ ff_qpeldsp_init(&s->qdsp); if (s->msmpeg4_version) { - FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_stats, - 2 * 2 * (MAX_LEVEL + 1) * - (MAX_RUN + 1) * 2 * sizeof(int), fail); - } - FF_ALLOCZ_OR_GOTO(s->avctx, s->avctx->stats_out, 256, fail); - - FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix, 64 * 32 * sizeof(int), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->q_chroma_intra_matrix, 64 * 32 * sizeof(int), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix, 64 * 32 * sizeof(int), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix16, 64 * 32 * 2 * sizeof(uint16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->q_chroma_intra_matrix16, 64 * 32 * 2 * sizeof(uint16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix16, 64 * 32 * 2 * sizeof(uint16_t), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->input_picture, - MAX_PICTURE_COUNT * sizeof(Picture *), fail); - FF_ALLOCZ_OR_GOTO(s->avctx, s->reordered_input_picture, - MAX_PICTURE_COUNT * sizeof(Picture *), fail); + int ac_stats_size = 2 * 2 * (MAX_LEVEL + 1) * (MAX_RUN + 1) * 2 * sizeof(int); + if (!(s->ac_stats = av_mallocz(ac_stats_size))) + return AVERROR(ENOMEM); + } + if (!(avctx->stats_out = av_mallocz(256)) || + !FF_ALLOCZ_TYPED_ARRAY(s->q_intra_matrix, 32) || + !FF_ALLOCZ_TYPED_ARRAY(s->q_chroma_intra_matrix, 32) || + !FF_ALLOCZ_TYPED_ARRAY(s->q_inter_matrix, 32) || + !FF_ALLOCZ_TYPED_ARRAY(s->q_intra_matrix16, 32) || + !FF_ALLOCZ_TYPED_ARRAY(s->q_chroma_intra_matrix16, 32) || + !FF_ALLOCZ_TYPED_ARRAY(s->q_inter_matrix16, 32) || + !FF_ALLOCZ_TYPED_ARRAY(s->input_picture, MAX_PICTURE_COUNT) || + !FF_ALLOCZ_TYPED_ARRAY(s->reordered_input_picture, MAX_PICTURE_COUNT)) + return AVERROR(ENOMEM); if (s->noise_reduction) { - FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_offset, - 2 * 64 * sizeof(uint16_t), fail); + if (!FF_ALLOCZ_TYPED_ARRAY(s->dct_offset, 2)) + return AVERROR(ENOMEM); } ff_dct_encode_init(s); @@ -974,7 +1000,7 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif - ff_set_cmp(&s->mecc, s->mecc.ildct_cmp, s->avctx->ildct_cmp); + 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) @@ -982,8 +1008,7 @@ if (CONFIG_H263_ENCODER && s->out_format == FMT_H263) ff_h263_encode_init(s); if (CONFIG_MSMPEG4_ENCODER && s->msmpeg4_version) - if ((ret = ff_msmpeg4_encode_init(s)) < 0) - return ret; + ff_msmpeg4_encode_init(s); if ((CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) && s->out_format == FMT_MPEG1) ff_mpeg1_encode_init(s); @@ -998,16 +1023,19 @@ } else if (s->out_format == FMT_H263 || s->out_format == FMT_H261) { s->intra_matrix[j] = s->inter_matrix[j] = ff_mpeg1_default_non_intra_matrix[i]; + } else if (CONFIG_SPEEDHQ_ENCODER && s->codec_id == AV_CODEC_ID_SPEEDHQ) { + s->intra_matrix[j] = + s->inter_matrix[j] = ff_mpeg1_default_intra_matrix[i]; } else { /* MPEG-1/2 */ s->chroma_intra_matrix[j] = s->intra_matrix[j] = ff_mpeg1_default_intra_matrix[i]; s->inter_matrix[j] = ff_mpeg1_default_non_intra_matrix[i]; } - if (s->avctx->intra_matrix) - s->intra_matrix[j] = s->avctx->intra_matrix[i]; - if (s->avctx->inter_matrix) - s->inter_matrix[j] = s->avctx->inter_matrix[i]; + if (avctx->intra_matrix) + s->intra_matrix[j] = avctx->intra_matrix[i]; + if (avctx->inter_matrix) + s->inter_matrix[j] = avctx->inter_matrix[i]; } /* precompute matrix */ @@ -1021,8 +1049,8 @@ 31, 0); } - if (ff_rate_control_init(s) < 0) - return -1; + if ((ret = ff_rate_control_init(s)) < 0) + return ret; #if FF_API_PRIVATE_OPT FF_DISABLE_DEPRECATION_WARNINGS @@ -1044,7 +1072,7 @@ s->tmp_frames[i]->width = s->width >> s->brd_scale; s->tmp_frames[i]->height = s->height >> s->brd_scale; - ret = av_frame_get_buffer(s->tmp_frames[i], 32); + ret = av_frame_get_buffer(s->tmp_frames[i], 0); if (ret < 0) return ret; } @@ -1059,9 +1087,6 @@ cpb_props->buffer_size = avctx->rc_buffer_size; return 0; -fail: - ff_mpv_encode_end(avctx); - return AVERROR_UNKNOWN; } av_cold int ff_mpv_encode_end(AVCodecContext *avctx) @@ -1082,9 +1107,9 @@ av_frame_free(&s->tmp_frames[i]); ff_free_picture_tables(&s->new_picture); - ff_mpeg_unref_picture(s->avctx, &s->new_picture); + ff_mpeg_unref_picture(avctx, &s->new_picture); - av_freep(&s->avctx->stats_out); + av_freep(&avctx->stats_out); av_freep(&s->ac_stats); if(s->q_chroma_intra_matrix != s->q_intra_matrix ) av_freep(&s->q_chroma_intra_matrix); @@ -1339,23 +1364,20 @@ return 0; } -static int encode_frame(AVCodecContext *c, AVFrame *frame) +static int encode_frame(AVCodecContext *c, AVFrame *frame, AVPacket *pkt) { - AVPacket pkt = { 0 }; int ret; int size = 0; - av_init_packet(&pkt); - ret = avcodec_send_frame(c, frame); if (ret < 0) return ret; do { - ret = avcodec_receive_packet(c, &pkt); + ret = avcodec_receive_packet(c, pkt); if (ret >= 0) { - size += pkt.size; - av_packet_unref(&pkt); + size += pkt->size; + av_packet_unref(pkt); } else if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) return ret; } while (ret >= 0); @@ -1366,6 +1388,7 @@ static int estimate_best_b_count(MpegEncContext *s) { const AVCodec *codec = avcodec_find_encoder(s->avctx->codec_id); + AVPacket *pkt; const int scale = s->brd_scale; int width = s->width >> scale; int height = s->height >> scale; @@ -1376,6 +1399,10 @@ av_assert0(scale >= 0 && scale <= 3); + pkt = av_packet_alloc(); + if (!pkt) + return AVERROR(ENOMEM); + //emms_c(); //s->next_picture_ptr->quality; p_lambda = s->last_lambda_for[AV_PICTURE_TYPE_P]; @@ -1427,8 +1454,10 @@ break; c = avcodec_alloc_context3(NULL); - if (!c) - return AVERROR(ENOMEM); + if (!c) { + ret = AVERROR(ENOMEM); + goto fail; + } c->width = width; c->height = height; @@ -1446,10 +1475,11 @@ if (ret < 0) goto fail; + s->tmp_frames[0]->pict_type = AV_PICTURE_TYPE_I; s->tmp_frames[0]->quality = 1 * FF_QP2LAMBDA; - out_size = encode_frame(c, s->tmp_frames[0]); + out_size = encode_frame(c, s->tmp_frames[0], pkt); if (out_size < 0) { ret = out_size; goto fail; @@ -1464,7 +1494,7 @@ AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_B; s->tmp_frames[i + 1]->quality = is_p ? p_lambda : b_lambda; - out_size = encode_frame(c, s->tmp_frames[i + 1]); + out_size = encode_frame(c, s->tmp_frames[i + 1], pkt); if (out_size < 0) { ret = out_size; goto fail; @@ -1474,7 +1504,7 @@ } /* get the delayed frames */ - out_size = encode_frame(c, NULL); + out_size = encode_frame(c, NULL, pkt); if (out_size < 0) { ret = out_size; goto fail; @@ -1490,10 +1520,15 @@ fail: avcodec_free_context(&c); - if (ret < 0) - return ret; + av_packet_unref(pkt); + if (ret < 0) { + best_b_count = ret; + break; + } } + av_packet_free(&pkt); + return best_b_count; } @@ -1660,7 +1695,8 @@ // input is not a shared pix -> reuse buffer for current_pix s->current_picture_ptr = s->reordered_input_picture[0]; for (i = 0; i < 4; i++) { - s->new_picture.f->data[i] += INPLACE_OFFSET; + if (s->new_picture.f->data[i]) + s->new_picture.f->data[i] += INPLACE_OFFSET; } } ff_mpeg_unref_picture(s->avctx, &s->current_picture); @@ -1896,7 +1932,7 @@ if (avctx->rc_buffer_size) { RateControlContext *rcc = &s->rc_context; int max_size = FFMAX(rcc->buffer_index * avctx->rc_max_available_vbv_use, rcc->buffer_index - 500); - int hq = (s->avctx->mb_decision == FF_MB_DECISION_RD || s->avctx->trellis); + int hq = (avctx->mb_decision == FF_MB_DECISION_RD || avctx->trellis); int min_step = hq ? 1 : (1<<(FF_LAMBDA_SHIFT + 7))/139; if (put_bits_count(&s->pb) > max_size && @@ -1928,14 +1964,14 @@ init_put_bits(pb, pb->buf, pb->buf_end - pb->buf); } s->vbv_ignore_qmax = 1; - av_log(s->avctx, AV_LOG_VERBOSE, "reencoding frame due to VBV\n"); + av_log(avctx, AV_LOG_VERBOSE, "reencoding frame due to VBV\n"); goto vbv_retry; } - av_assert0(s->avctx->rc_max_rate); + av_assert0(avctx->rc_max_rate); } - if (s->avctx->flags & AV_CODEC_FLAG_PASS1) + if (avctx->flags & AV_CODEC_FLAG_PASS1) ff_write_pass1_stats(s); for (i = 0; i < 4; i++) { @@ -1944,10 +1980,10 @@ } ff_side_data_set_encoder_stats(pkt, s->current_picture.f->quality, s->current_picture_ptr->encoding_error, - (s->avctx->flags&AV_CODEC_FLAG_PSNR) ? 4 : 0, + (avctx->flags&AV_CODEC_FLAG_PSNR) ? 4 : 0, s->pict_type); - if (s->avctx->flags & AV_CODEC_FLAG_PASS1) + if (avctx->flags & AV_CODEC_FLAG_PASS1) assert(put_bits_count(&s->pb) == s->header_bits + s->mv_bits + s->misc_bits + s->i_tex_bits + s->p_tex_bits); @@ -1959,7 +1995,7 @@ if (stuffing_count) { if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb) >> 3) < stuffing_count + 50) { - av_log(s->avctx, AV_LOG_ERROR, "stuffing too large\n"); + av_log(avctx, AV_LOG_ERROR, "stuffing too large\n"); return -1; } @@ -1979,37 +2015,37 @@ } break; default: - av_log(s->avctx, AV_LOG_ERROR, "vbv buffer overflow\n"); + av_log(avctx, AV_LOG_ERROR, "vbv buffer overflow\n"); } flush_put_bits(&s->pb); s->frame_bits = put_bits_count(&s->pb); } /* update MPEG-1/2 vbv_delay for CBR */ - if (s->avctx->rc_max_rate && - s->avctx->rc_min_rate == s->avctx->rc_max_rate && + if (avctx->rc_max_rate && + avctx->rc_min_rate == avctx->rc_max_rate && s->out_format == FMT_MPEG1 && 90000LL * (avctx->rc_buffer_size - 1) <= - s->avctx->rc_max_rate * 0xFFFFLL) { + avctx->rc_max_rate * 0xFFFFLL) { AVCPBProperties *props; size_t props_size; int vbv_delay, min_delay; - double inbits = s->avctx->rc_max_rate * - av_q2d(s->avctx->time_base); + double inbits = avctx->rc_max_rate * + av_q2d(avctx->time_base); int minbits = s->frame_bits - 8 * (s->vbv_delay_ptr - s->pb.buf - 1); double bits = s->rc_context.buffer_index + minbits - inbits; if (bits < 0) - av_log(s->avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_ERROR, "Internal error, negative bits\n"); av_assert1(s->repeat_first_field == 0); - vbv_delay = bits * 90000 / s->avctx->rc_max_rate; - min_delay = (minbits * 90000LL + s->avctx->rc_max_rate - 1) / - s->avctx->rc_max_rate; + vbv_delay = bits * 90000 / avctx->rc_max_rate; + min_delay = (minbits * 90000LL + avctx->rc_max_rate - 1) / + avctx->rc_max_rate; vbv_delay = FFMAX(vbv_delay, min_delay); @@ -2067,7 +2103,7 @@ /* 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]); + ff_mpeg_unref_picture(avctx, &s->picture[i]); } av_assert1((s->frame_bits & 7) == 0); @@ -2566,6 +2602,10 @@ if (CONFIG_MJPEG_ENCODER) ff_mjpeg_encode_mb(s, s->block); break; + case AV_CODEC_ID_SPEEDHQ: + if (CONFIG_SPEEDHQ_ENCODER) + ff_speedhq_encode_mb(s, s->block); + break; default: av_assert1(0); } @@ -2762,8 +2802,6 @@ static int estimate_motion_thread(AVCodecContext *c, void *arg){ MpegEncContext *s= *(void**)arg; - ff_check_alignment(); - s->me.dia_size= s->avctx->dia_size; s->first_slice_line=1; for(s->mb_y= s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { @@ -2790,8 +2828,6 @@ MpegEncContext *s= *(void**)arg; int mb_x, mb_y; - ff_check_alignment(); - for(mb_y=s->start_mb_y; mb_y < s->end_mb_y; mb_y++) { for(mb_x=0; mb_x < s->mb_width; mb_x++) { int xx = mb_x * 16; @@ -2820,9 +2856,10 @@ ff_mpeg4_stuffing(&s->pb); }else if(CONFIG_MJPEG_ENCODER && s->out_format == FMT_MJPEG){ ff_mjpeg_encode_stuffing(s); + } else if (CONFIG_SPEEDHQ_ENCODER && s->out_format == FMT_SPEEDHQ) { + ff_speedhq_end_slice(s); } - avpriv_align_put_bits(&s->pb); flush_put_bits(&s->pb); if ((s->avctx->flags & AV_CODEC_FLAG_PASS1) && !s->partitioned_frame) @@ -2910,7 +2947,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ MpegEncContext *s= *(void**)arg; - int mb_x, mb_y; + int mb_x, mb_y, mb_y_order; int chr_h= 16>>s->chroma_y_shift; int i, j; MpegEncContext best_s = { 0 }, backup_s; @@ -2919,8 +2956,6 @@ uint8_t bit_buf_tex[2][MAX_MB_BYTES]; PutBitContext pb[2], pb2[2], tex_pb[2]; - ff_check_alignment(); - for(i=0; i<2; i++){ init_put_bits(&pb [i], bit_buf [i], MAX_MB_BYTES); init_put_bits(&pb2 [i], bit_buf2 [i], MAX_MB_BYTES); @@ -2971,7 +3006,16 @@ s->resync_mb_y=0; s->first_slice_line = 1; s->ptr_lastgob = s->pb.buf; - for(mb_y= s->start_mb_y; mb_y < s->end_mb_y; mb_y++) { + for (mb_y_order = s->start_mb_y; mb_y_order < s->end_mb_y; mb_y_order++) { + if (CONFIG_SPEEDHQ_ENCODER && s->codec_id == AV_CODEC_ID_SPEEDHQ) { + int first_in_slice; + mb_y = ff_speedhq_mb_y_order_to_mb(mb_y_order, s->mb_height, &first_in_slice); + if (first_in_slice && mb_y_order != s->start_mb_y) + ff_speedhq_end_slice(s); + s->last_dc[0] = s->last_dc[1] = s->last_dc[2] = 1024 << s->intra_dc_precision; + } else { + mb_y = mb_y_order; + } s->mb_x=0; s->mb_y= mb_y; @@ -3356,18 +3400,18 @@ pb_bits_count= put_bits_count(&s->pb); flush_put_bits(&s->pb); - avpriv_copy_bits(&backup_s.pb, bit_buf[next_block^1], pb_bits_count); + ff_copy_bits(&backup_s.pb, bit_buf[next_block^1], pb_bits_count); s->pb= backup_s.pb; if(s->data_partitioning){ pb2_bits_count= put_bits_count(&s->pb2); flush_put_bits(&s->pb2); - avpriv_copy_bits(&backup_s.pb2, bit_buf2[next_block^1], pb2_bits_count); + ff_copy_bits(&backup_s.pb2, bit_buf2[next_block^1], pb2_bits_count); s->pb2= backup_s.pb2; tex_pb_bits_count= put_bits_count(&s->tex_pb); flush_put_bits(&s->tex_pb); - avpriv_copy_bits(&backup_s.tex_pb, bit_buf_tex[next_block^1], tex_pb_bits_count); + ff_copy_bits(&backup_s.tex_pb, bit_buf_tex[next_block^1], tex_pb_bits_count); s->tex_pb= backup_s.tex_pb; } s->last_bits= put_bits_count(&s->pb); @@ -3594,7 +3638,7 @@ av_assert1(put_bits_count(&src->pb) % 8 ==0); av_assert1(put_bits_count(&dst->pb) % 8 ==0); - avpriv_copy_bits(&dst->pb, src->pb.buf, put_bits_count(&src->pb)); + ff_copy_bits(&dst->pb, src->pb.buf, put_bits_count(&src->pb)); flush_put_bits(&dst->pb); } @@ -3761,14 +3805,14 @@ s->f_code= FFMAX3(s->f_code, a, b); } - ff_fix_long_p_mvs(s); - ff_fix_long_mvs(s, NULL, 0, s->p_mv_table, s->f_code, CANDIDATE_MB_TYPE_INTER, 0); + ff_fix_long_p_mvs(s, s->intra_penalty ? CANDIDATE_MB_TYPE_INTER : CANDIDATE_MB_TYPE_INTRA); + ff_fix_long_mvs(s, NULL, 0, s->p_mv_table, s->f_code, CANDIDATE_MB_TYPE_INTER, !!s->intra_penalty); if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) { int j; for(i=0; i<2; i++){ for(j=0; j<2; j++) ff_fix_long_mvs(s, s->p_field_select_table[i], j, - s->p_field_mv_table[i][j], s->f_code, CANDIDATE_MB_TYPE_INTER_I, 0); + s->p_field_mv_table[i][j], s->f_code, CANDIDATE_MB_TYPE_INTER_I, !!s->intra_penalty); } } } @@ -3846,8 +3890,8 @@ for(i=1;i<64;i++){ int j= s->idsp.idct_permutation[ff_zigzag_direct[i]]; - s->intra_matrix[j] = sp5x_quant_table[5*2+0][i]; - s->chroma_intra_matrix[j] = sp5x_quant_table[5*2+1][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; @@ -3860,6 +3904,11 @@ s->qscale= 8; } + if (s->out_format == FMT_SPEEDHQ) { + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg2_dc_scale_table[3]; + } + //FIXME var duplication s->current_picture_ptr->f->key_frame = s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; //FIXME pic_ptr @@ -3877,6 +3926,10 @@ ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, s->pred, s->intra_matrix, s->chroma_intra_matrix); break; + case FMT_SPEEDHQ: + if (CONFIG_SPEEDHQ_ENCODER) + ff_speedhq_encode_picture_header(s); + break; case FMT_H261: if (CONFIG_H261_ENCODER) ff_h261_encode_picture_header(s, picture_number); @@ -3918,7 +3971,7 @@ s->avctx->execute(s->avctx, encode_thread, &s->thread_context[0], NULL, context_count, sizeof(void*)); for(i=1; ipb.buf_end == s->thread_context[i]->pb.buf) - set_put_bits_buffer_size(&s->pb, FFMIN(s->thread_context[i]->pb.buf_end - s->pb.buf, INT_MAX/8-32)); + set_put_bits_buffer_size(&s->pb, FFMIN(s->thread_context[i]->pb.buf_end - s->pb.buf, INT_MAX/8-BUF_BITS)); merge_context_after_encode(s, s->thread_context[i]); } emms_c(); @@ -4262,7 +4315,6 @@ return last_non_zero; } -//#define REFINE_STATS 1 static int16_t basis[64][64]; static void build_basis(uint8_t *perm){ @@ -4301,15 +4353,6 @@ uint8_t * last_length; int lambda; int rle_index, run, q = 1, sum; //q is only used when s->mb_intra is true -#ifdef REFINE_STATS -static int count=0; -static int after_last=0; -static int to_zero=0; -static int from_zero=0; -static int raise=0; -static int lower=0; -static int messed_sign=0; -#endif if(basis[0][0] == 0) build_basis(s->idsp.idct_permutation); @@ -4353,16 +4396,11 @@ } last_non_zero = s->block_last_index[n]; -#ifdef REFINE_STATS -{START_TIMER -#endif dc += (1<<(RECON_SHIFT-1)); for(i=0; i<64; i++){ rem[i] = dc - (orig[i] << RECON_SHIFT); // FIXME use orig directly instead of copying to rem[] } -#ifdef REFINE_STATS -STOP_TIMER("memset rem[]")} -#endif + sum=0; for(i=0; i<64; i++){ int one= 36; @@ -4380,9 +4418,7 @@ sum += w*w; } lambda= sum*(uint64_t)s->lambda2 >> (FF_LAMBDA_SHIFT - 6 + 6 + 6 + 6); -#ifdef REFINE_STATS -{START_TIMER -#endif + run=0; rle_index=0; for(i=start_i; i<=last_non_zero; i++){ @@ -4401,41 +4437,21 @@ run++; } } -#ifdef REFINE_STATS -if(last_non_zero>0){ -STOP_TIMER("init rem[]") -} -} -{START_TIMER -#endif for(;;){ int best_score = s->mpvencdsp.try_8x8basis(rem, weight, basis[0], 0); int best_coeff=0; int best_change=0; int run2, best_unquant_change=0, analyze_gradient; -#ifdef REFINE_STATS -{START_TIMER -#endif analyze_gradient = last_non_zero > 2 || s->quantizer_noise_shaping >= 3; if(analyze_gradient){ -#ifdef REFINE_STATS -{START_TIMER -#endif for(i=0; i<64; i++){ int w= weight[i]; d1[i] = (rem[i]*w*w + (1<<(RECON_SHIFT+12-1)))>>(RECON_SHIFT+12); } -#ifdef REFINE_STATS -STOP_TIMER("rem*w*w")} -{START_TIMER -#endif s->fdsp.fdct(d1); -#ifdef REFINE_STATS -STOP_TIMER("dct")} -#endif } if(start_i){ @@ -4597,9 +4613,6 @@ run++; } } -#ifdef REFINE_STATS -STOP_TIMER("iterative step")} -#endif if(best_change){ int j= perm_scantable[ best_coeff ]; @@ -4609,36 +4622,13 @@ if(best_coeff > last_non_zero){ last_non_zero= best_coeff; av_assert2(block[j]); -#ifdef REFINE_STATS -after_last++; -#endif }else{ -#ifdef REFINE_STATS -if(block[j]){ - if(block[j] - best_change){ - if(FFABS(block[j]) > FFABS(block[j] - best_change)){ - raise++; - }else{ - lower++; - } - }else{ - from_zero++; - } -}else{ - to_zero++; -} -#endif for(; last_non_zero>=start_i; last_non_zero--){ if(block[perm_scantable[last_non_zero]]) break; } } -#ifdef REFINE_STATS -count++; -if(256*256*256*64 % count == 0){ - av_log(s->avctx, AV_LOG_DEBUG, "after_last:%d to_zero:%d from_zero:%d raise:%d lower:%d sign:%d xyp:%d/%d/%d\n", after_last, to_zero, from_zero, raise, lower, messed_sign, s->mb_x, s->mb_y, s->picture_number); -} -#endif + run=0; rle_index=0; for(i=start_i; i<=last_non_zero; i++){ @@ -4658,12 +4648,6 @@ break; } } -#ifdef REFINE_STATS -if(last_non_zero>0){ -STOP_TIMER("iterative search") -} -} -#endif return last_non_zero; } @@ -4812,6 +4796,7 @@ .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts= (const enum AVPixelFormat[]){AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE}, .priv_class = &h263_class, }; @@ -4841,6 +4826,7 @@ .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, .capabilities = AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &h263p_class, }; @@ -4861,6 +4847,7 @@ .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &msmpeg4v2_class, }; @@ -4881,6 +4868,7 @@ .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &msmpeg4v3_class, }; @@ -4901,6 +4889,7 @@ .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &wmv1_class, }; diff -Nru ffmpeg-4.2.2/libavcodec/mpegvideo.h ffmpeg-4.4/libavcodec/mpegvideo.h --- ffmpeg-4.2.2/libavcodec/mpegvideo.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegvideo.h 2021-04-08 21:28:39.000000000 +0000 @@ -276,7 +276,7 @@ int mv[2][4][2]; int field_select[2][2]; int last_mv[2][2][2]; ///< last MV, used for MV prediction in MPEG-1 & B-frame MPEG-4 - uint8_t *fcode_tab; ///< smallest fcode needed for each MV + const uint8_t *fcode_tab; ///< smallest fcode needed for each MV int16_t direct_scale_mv[2][64]; ///< precomputed to avoid divisions in ff_mpeg4_set_direct_mv MotionEstContext me; @@ -369,7 +369,9 @@ uint8_t *mb_info_ptr; int mb_info_size; int ehc_mode; +#if FF_API_MPV_RC_STRATEGY int rc_strategy; ///< deprecated +#endif /* H.263+ specific */ int umvplus; ///< == H.263+ && unrestricted_mv @@ -444,6 +446,9 @@ int inter_intra_pred; int mspel; + /* SpeedHQ specific */ + int slice_start; + /* decompression specific */ GetBitContext gb; @@ -580,6 +585,8 @@ int scenechange_threshold; int noise_reduction; + + int intra_penalty; } MpegEncContext; /* mpegvideo_enc common options */ @@ -610,6 +617,14 @@ #ifndef FF_MPV_OFFSET #define FF_MPV_OFFSET(x) offsetof(MpegEncContext, x) #endif +#if FF_API_MPV_RC_STRATEGY +#define FF_MPV_RC_STRATEGY_OPTS \ +{"rc_strategy", "ratecontrol method", FF_MPV_OFFSET(rc_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED, "rc_strategy" }, \ + { "ffmpeg", "deprecated, does nothing", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED, "rc_strategy" }, \ + { "xvid", "deprecated, does nothing", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED, "rc_strategy" }, +#else +#define FF_MPV_RC_STRATEGY_OPTS +#endif #define FF_MPV_OPT_FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) #define FF_MPV_COMMON_OPTS \ FF_MPV_OPT_CMP_FUNC, \ @@ -643,9 +658,6 @@ {"lmax", "maximum Lagrange factor (VBR)", FF_MPV_OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 31*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"ibias", "intra quant bias", FF_MPV_OFFSET(intra_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"pbias", "inter quant bias", FF_MPV_OFFSET(inter_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"rc_strategy", "ratecontrol method", FF_MPV_OFFSET(rc_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED, "rc_strategy" }, \ - { "ffmpeg", "deprecated, does nothing", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED, "rc_strategy" }, \ - { "xvid", "deprecated, does nothing", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED, "rc_strategy" }, \ {"motion_est", "motion estimation algorithm", FF_MPV_OFFSET(motion_est), AV_OPT_TYPE_INT, {.i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, FF_MPV_OPT_FLAGS, "motion_est" }, \ { "zero", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ZERO }, 0, 0, FF_MPV_OPT_FLAGS, "motion_est" }, \ { "epzs", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_EPZS }, 0, 0, FF_MPV_OPT_FLAGS, "motion_est" }, \ @@ -664,7 +676,9 @@ {"ps", "RTP payload size in bytes", FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"mepc", "Motion estimation bitrate penalty compensation (1.0 = 256)", FF_MPV_OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ {"mepre", "pre motion estimation", FF_MPV_OFFSET(me_pre), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"intra_penalty", "Penalty for intra blocks in block decision", FF_MPV_OFFSET(intra_penalty), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX/2, FF_MPV_OPT_FLAGS }, \ {"a53cc", "Use A53 Closed Captions (if available)", FF_MPV_OFFSET(a53_cc), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FF_MPV_OPT_FLAGS }, \ +FF_MPV_RC_STRATEGY_OPTS extern const AVOption ff_mpv_generic_options[]; @@ -688,7 +702,6 @@ int ff_mpv_common_frame_size_change(MpegEncContext *s); void ff_mpv_common_end(MpegEncContext *s); -void ff_mpv_decode_defaults(MpegEncContext *s); void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx); void ff_mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64]); void ff_mpv_report_decode_progress(MpegEncContext *s); diff -Nru ffmpeg-4.2.2/libavcodec/mpegvideo_motion.c ffmpeg-4.4/libavcodec/mpegvideo_motion.c --- ffmpeg-4.2.2/libavcodec/mpegvideo_motion.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegvideo_motion.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,19 +21,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include - #include "libavutil/avassert.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "h261.h" #include "mpegutils.h" #include "mpegvideo.h" -#include "mjpegenc.h" -#include "msmpeg4.h" #include "qpeldsp.h" #include "wmv2.h" -#include static void gmc1_motion(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, @@ -211,16 +208,16 @@ dxy |= (motion_y & 1) << 1; src += src_y * s->linesize + src_x; - if ((unsigned)src_x >= FFMAX(s->h_edge_pos - (motion_x & 1) - 7, 0) || - (unsigned)src_y >= FFMAX(s->v_edge_pos - (motion_y & 1) - 7, 0)) { - s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, src, - s->linesize, s->linesize, - 9, 9, - src_x, src_y, - s->h_edge_pos, s->v_edge_pos); - src = s->sc.edge_emu_buffer; - emu = 1; - } + if ((unsigned)src_x >= FFMAX(s->h_edge_pos - (motion_x & 1) - 7, 0) || + (unsigned)src_y >= FFMAX(s->v_edge_pos - (motion_y & 1) - 7, 0)) { + s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, src, + s->linesize, s->linesize, + 9, 9, + src_x, src_y, + s->h_edge_pos, s->v_edge_pos); + src = s->sc.edge_emu_buffer; + emu = 1; + } pix_op[dxy](dest, src, s->linesize, 8); return emu; } @@ -304,9 +301,9 @@ if ((unsigned)src_x >= FFMAX(s->h_edge_pos - (motion_x & 1) - 15 , 0) || (unsigned)src_y >= FFMAX( v_edge_pos - (motion_y & 1) - h + 1, 0)) { - if (is_mpeg12 || - s->codec_id == AV_CODEC_ID_MPEG2VIDEO || - s->codec_id == AV_CODEC_ID_MPEG1VIDEO) { + if (is_mpeg12 || (CONFIG_SMALL && + (s->codec_id == AV_CODEC_ID_MPEG2VIDEO || + s->codec_id == AV_CODEC_ID_MPEG1VIDEO))) { av_log(s->avctx, AV_LOG_DEBUG, "MPEG motion vector out of boundary (%d %d)\n", src_x, src_y); @@ -851,7 +848,7 @@ switch (s->mv_type) { case MV_TYPE_16X16: - if (s->mcsel) { + if (!is_mpeg12 && s->mcsel) { if (s->real_sprite_warping_points == 1) { gmc1_motion(s, dest_y, dest_cb, dest_cr, ref_picture); @@ -913,60 +910,63 @@ } break; case MV_TYPE_16X8: - for (i = 0; i < 2; i++) { - uint8_t **ref2picture; + if (CONFIG_SMALL || is_mpeg12) { + for (i = 0; i < 2; i++) { + uint8_t **ref2picture; - if ((s->picture_structure == s->field_select[dir][i] + 1 - || s->pict_type == AV_PICTURE_TYPE_B || s->first_field) && ref_picture[0]) { - ref2picture = ref_picture; - } else { - ref2picture = s->current_picture_ptr->f->data; - } + if ((s->picture_structure == s->field_select[dir][i] + 1 || + s->pict_type == AV_PICTURE_TYPE_B || s->first_field) && + ref_picture[0]) { + ref2picture = ref_picture; + } else { + ref2picture = s->current_picture_ptr->f->data; + } - mpeg_motion(s, dest_y, dest_cb, dest_cr, - s->field_select[dir][i], - ref2picture, pix_op, - s->mv[dir][i][0], s->mv[dir][i][1], - 8, 1, (mb_y & ~1) + i); - - dest_y += 16 * s->linesize; - dest_cb += (16 >> s->chroma_y_shift) * s->uvlinesize; - dest_cr += (16 >> s->chroma_y_shift) * s->uvlinesize; + mpeg_motion(s, dest_y, dest_cb, dest_cr, + s->field_select[dir][i], + ref2picture, pix_op, + s->mv[dir][i][0], s->mv[dir][i][1], + 8, 1, (mb_y & ~1) + i); + + dest_y += 16 * s->linesize; + dest_cb += (16 >> s->chroma_y_shift) * s->uvlinesize; + dest_cr += (16 >> s->chroma_y_shift) * s->uvlinesize; + } + break; } - break; case MV_TYPE_DMV: - if (s->picture_structure == PICT_FRAME) { - for (i = 0; i < 2; i++) { - int j; - for (j = 0; j < 2; j++) - mpeg_motion_field(s, dest_y, dest_cb, dest_cr, - j, j ^ i, ref_picture, pix_op, - s->mv[dir][2 * i + j][0], - s->mv[dir][2 * i + j][1], 8, mb_y); - pix_op = s->hdsp.avg_pixels_tab; - } - } else { - if (!ref_picture[0]) { - ref_picture = s->current_picture_ptr->f->data; - } - for (i = 0; i < 2; i++) { - mpeg_motion(s, dest_y, dest_cb, dest_cr, - s->picture_structure != i + 1, - ref_picture, pix_op, - s->mv[dir][2 * i][0], s->mv[dir][2 * i][1], - 16, 0, mb_y >> 1); - - // after put we make avg of the same block - pix_op = s->hdsp.avg_pixels_tab; - - /* opposite parity is always in the same frame if this is - * second field */ - if (!s->first_field) { + if (CONFIG_SMALL || is_mpeg12) { + if (s->picture_structure == PICT_FRAME) { + for (i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) + mpeg_motion_field(s, dest_y, dest_cb, dest_cr, + j, j ^ i, ref_picture, pix_op, + s->mv[dir][2 * i + j][0], + s->mv[dir][2 * i + j][1], 8, mb_y); + pix_op = s->hdsp.avg_pixels_tab; + } + } else { + if (!ref_picture[0]) { ref_picture = s->current_picture_ptr->f->data; } + for (i = 0; i < 2; i++) { + mpeg_motion(s, dest_y, dest_cb, dest_cr, + s->picture_structure != i + 1, + ref_picture, pix_op, + s->mv[dir][2 * i][0], s->mv[dir][2 * i][1], + 16, 0, mb_y >> 1); + + // after put we make avg of the same block + pix_op = s->hdsp.avg_pixels_tab; + + /* opposite parity is always in the same frame if this is + * second field */ + if (!s->first_field) + ref_picture = s->current_picture_ptr->f->data; + } } + break; } - break; default: av_assert2(0); } } diff -Nru ffmpeg-4.2.2/libavcodec/mpegvideo_parser.c ffmpeg-4.4/libavcodec/mpegvideo_parser.c --- ffmpeg-4.2.2/libavcodec/mpegvideo_parser.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mpegvideo_parser.c 2020-07-11 10:39:30.000000000 +0000 @@ -154,7 +154,7 @@ break; } } - the_end: ; + the_end: if (set_dim_ret < 0) av_log(avctx, AV_LOG_ERROR, "Failed to set dimensions\n"); diff -Nru ffmpeg-4.2.2/libavcodec/mqcenc.c ffmpeg-4.4/libavcodec/mqcenc.c --- ffmpeg-4.2.2/libavcodec/mqcenc.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mqcenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -102,11 +102,6 @@ } } -int ff_mqc_length(MqcState *mqc) -{ - return mqc->bp - mqc->bpstart; -} - int ff_mqc_flush(MqcState *mqc) { setbits(mqc); diff -Nru ffmpeg-4.2.2/libavcodec/mqc.h ffmpeg-4.4/libavcodec/mqc.h --- ffmpeg-4.2.2/libavcodec/mqc.h 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mqc.h 2021-04-08 21:28:39.000000000 +0000 @@ -54,9 +54,6 @@ /** code bit d with context cx */ void ff_mqc_encode(MqcState *mqc, uint8_t *cxstate, int d); -/** number of encoded bytes */ -int ff_mqc_length(MqcState *mqc); - /** flush the encoder [returns number of bytes encoded] */ int ff_mqc_flush(MqcState *mqc); int ff_mqc_flush_to(MqcState *mqc, uint8_t *dst, int *dst_len); diff -Nru ffmpeg-4.2.2/libavcodec/mscc.c ffmpeg-4.4/libavcodec/mscc.c --- ffmpeg-4.2.2/libavcodec/mscc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mscc.c 2021-04-08 21:28:39.000000000 +0000 @@ -152,7 +152,7 @@ } if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { - int size; + buffer_size_t size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size); if (pal && size == AVPALETTE_SIZE) { diff -Nru ffmpeg-4.2.2/libavcodec/msmpeg4data.c ffmpeg-4.4/libavcodec/msmpeg4data.c --- ffmpeg-4.2.2/libavcodec/msmpeg4data.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/msmpeg4data.c 2021-04-08 21:28:39.000000000 +0000 @@ -1771,13 +1771,11 @@ }; MVTable ff_mv_tables[2] = { - { 1099, - table0_mv_code, + { table0_mv_code, table0_mv_bits, table0_mvx, table0_mvy, }, - { 1099, - table1_mv_code, + { table1_mv_code, table1_mv_bits, table1_mvx, table1_mvy, } diff -Nru ffmpeg-4.2.2/libavcodec/msmpeg4data.h ffmpeg-4.4/libavcodec/msmpeg4data.h --- ffmpeg-4.2.2/libavcodec/msmpeg4data.h 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/msmpeg4data.h 2021-04-08 21:28:39.000000000 +0000 @@ -37,7 +37,6 @@ /* motion vector table */ typedef struct MVTable { - int n; const uint16_t *table_mv_code; const uint8_t *table_mv_bits; const uint8_t *table_mvx; @@ -69,6 +68,7 @@ extern const uint8_t ff_wmv1_c_dc_scale_table[32]; extern const uint8_t ff_old_ff_y_dc_scale_table[32]; +#define MSMPEG4_MV_TABLES_NB_ELEMS 1099 extern MVTable ff_mv_tables[2]; extern const uint8_t ff_v2_mb_type[8][2]; diff -Nru ffmpeg-4.2.2/libavcodec/msmpeg4dec.c ffmpeg-4.4/libavcodec/msmpeg4dec.c --- ffmpeg-4.2.2/libavcodec/msmpeg4dec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/msmpeg4dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -38,7 +38,6 @@ #define V2_INTRA_CBPC_VLC_BITS 3 #define V2_MB_TYPE_VLC_BITS 7 #define MV_VLC_BITS 9 -#define V2_MV_VLC_BITS 9 #define TEX_VLC_BITS 9 #define DEFAULT_INTER_INDEX 3 @@ -66,7 +65,6 @@ static VLC v2_dc_chroma_vlc; static VLC v2_intra_cbpc_vlc; static VLC v2_mb_type_vlc; -static VLC v2_mv_vlc; VLC ff_inter_intra_vlc; /* This is identical to H.263 except that its range is multiplied by 2. */ @@ -74,7 +72,7 @@ { int code, val, sign, shift; - code = get_vlc2(&s->gb, v2_mv_vlc.table, V2_MV_VLC_BITS, 2); + code = get_vlc2(&s->gb, ff_h263_mv_vlc.table, H263_MV_VLC_BITS, 2); ff_dlog(s, "MV code %d at %d %d pred: %d\n", code, s->mb_x,s->mb_y, pred); if (code < 0) return 0xffff; @@ -230,8 +228,6 @@ } code = get_vlc2(&s->gb, ff_mb_non_intra_vlc[DEFAULT_INTER_INDEX].table, MB_NON_INTRA_VLC_BITS, 3); - if (code < 0) - return -1; //s->mb_intra = (code & 0x40) ? 0 : 1; s->mb_intra = (~code & 0x40) >> 6; @@ -239,8 +235,6 @@ } else { s->mb_intra = 1; code = get_vlc2(&s->gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); - if (code < 0) - return -1; /* predict coded block pattern */ cbp = 0; for(i=0;i<6;i++) { @@ -261,8 +255,7 @@ s->rl_chroma_table_index = s->rl_table_index; } ff_h263_pred_motion(s, 0, 0, &mx, &my); - if (ff_msmpeg4_decode_motion(s, &mx, &my) < 0) - return -1; + ff_msmpeg4_decode_motion(s, &mx, &my); s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_16X16; s->mv[0][0][0] = mx; @@ -317,19 +310,22 @@ for(i=0;ivlc, MV_VLC_BITS, mv->n + 1, + INIT_VLC_STATIC(&mv->vlc, MV_VLC_BITS, MSMPEG4_MV_TABLES_NB_ELEMS + 1, mv->table_mv_bits, 1, 1, mv->table_mv_code, 2, 2, 3714); mv = &ff_mv_tables[1]; - INIT_VLC_STATIC(&mv->vlc, MV_VLC_BITS, mv->n + 1, + INIT_VLC_STATIC(&mv->vlc, MV_VLC_BITS, MSMPEG4_MV_TABLES_NB_ELEMS + 1, mv->table_mv_bits, 1, 1, mv->table_mv_code, 2, 2, 2694); @@ -359,9 +355,6 @@ INIT_VLC_STATIC(&v2_mb_type_vlc, V2_MB_TYPE_VLC_BITS, 8, &ff_v2_mb_type[0][1], 2, 1, &ff_v2_mb_type[0][0], 2, 1, 128); - INIT_VLC_STATIC(&v2_mv_vlc, V2_MV_VLC_BITS, 33, - &ff_mvtab[0][1], 2, 1, - &ff_mvtab[0][0], 2, 1, 538); INIT_VLC_STATIC(&ff_mb_non_intra_vlc[0], MB_NON_INTRA_VLC_BITS, 128, &ff_wmv2_inter_table[0][0][1], 8, 4, @@ -614,11 +607,6 @@ } else { level = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); } - if (level < 0){ - av_log(s->avctx, AV_LOG_ERROR, "illegal dc vlc\n"); - *dir_ptr = 0; - return -1; - } if (level == DC_MAX) { level = get_bits(&s->gb, 8); @@ -840,8 +828,7 @@ return 0; } -int ff_msmpeg4_decode_motion(MpegEncContext * s, - int *mx_ptr, int *my_ptr) +void ff_msmpeg4_decode_motion(MpegEncContext *s, int *mx_ptr, int *my_ptr) { MVTable *mv; int code, mx, my; @@ -849,11 +836,7 @@ mv = &ff_mv_tables[s->mv_table_index]; code = get_vlc2(&s->gb, mv->vlc.table, MV_VLC_BITS, 2); - if (code < 0){ - av_log(s->avctx, AV_LOG_ERROR, "illegal MV code at %d %d\n", s->mb_x, s->mb_y); - return -1; - } - if (code == mv->n) { + if (code == MSMPEG4_MV_TABLES_NB_ELEMS) { mx = get_bits(&s->gb, 6); my = get_bits(&s->gb, 6); } else { @@ -875,7 +858,6 @@ my -= 64; *mx_ptr = mx; *my_ptr = my; - return 0; } AVCodec ff_msmpeg4v1_decoder = { diff -Nru ffmpeg-4.2.2/libavcodec/msmpeg4enc.c ffmpeg-4.4/libavcodec/msmpeg4enc.c --- ffmpeg-4.2.2/libavcodec/msmpeg4enc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/msmpeg4enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,7 +32,6 @@ #include "libavutil/attributes.h" #include "libavutil/avutil.h" -#include "libavutil/mem.h" #include "mpegvideo.h" #include "h263.h" #include "internal.h" @@ -46,25 +45,21 @@ static uint8_t rl_length[NB_RL_TABLES][MAX_LEVEL+1][MAX_RUN+1][2]; /* build the table which associate a (x,y) motion vector to a vlc */ -static av_cold int init_mv_table(MVTable *tab) +static av_cold void init_mv_table(MVTable *tab, uint16_t table_mv_index[4096]) { int i, x, y; - tab->table_mv_index = av_malloc(sizeof(uint16_t) * 4096); - if (!tab->table_mv_index) - return AVERROR(ENOMEM); + tab->table_mv_index = table_mv_index; /* mark all entries as not used */ for(i=0;i<4096;i++) - tab->table_mv_index[i] = tab->n; + tab->table_mv_index[i] = MSMPEG4_MV_TABLES_NB_ELEMS; - for(i=0;in;i++) { + for (i = 0; i < MSMPEG4_MV_TABLES_NB_ELEMS; i++) { x = tab->table_mvx[i]; y = tab->table_mvy[i]; tab->table_mv_index[(x << 6) | y] = i; } - - return 0; } void ff_msmpeg4_code012(PutBitContext *pb, int n) @@ -118,10 +113,10 @@ return size; } -av_cold int ff_msmpeg4_encode_init(MpegEncContext *s) +av_cold void ff_msmpeg4_encode_init(MpegEncContext *s) { static int init_done=0; - int i, ret; + int i; ff_msmpeg4_common_init(s); if(s->msmpeg4_version>=4){ @@ -130,12 +125,12 @@ } if (!init_done) { + static uint16_t mv_index_tables[2][4096]; /* init various encoding tables */ init_done = 1; - if ((ret = init_mv_table(&ff_mv_tables[0])) < 0) - return ret; - if ((ret = init_mv_table(&ff_mv_tables[1])) < 0) - return ret; + init_mv_table(&ff_mv_tables[0], mv_index_tables[0]); + init_mv_table(&ff_mv_tables[1], mv_index_tables[1]); + for(i=0;ipb); + align_put_bits(&s->pb); put_bits(&s->pb, 2, s->pict_type - 1); put_bits(&s->pb, 5, s->qscale); @@ -320,7 +313,7 @@ put_bits(&s->pb, mv->table_mv_bits[code], mv->table_mv_code[code]); - if (code == mv->n) { + if (code == MSMPEG4_MV_TABLES_NB_ELEMS) { /* escape : code literally */ put_bits(&s->pb, 6, mx); put_bits(&s->pb, 6, my); diff -Nru ffmpeg-4.2.2/libavcodec/msmpeg4.h ffmpeg-4.4/libavcodec/msmpeg4.h --- ffmpeg-4.2.2/libavcodec/msmpeg4.h 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/msmpeg4.h 2021-04-08 21:28:39.000000000 +0000 @@ -50,7 +50,7 @@ int ff_msmpeg4_coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr); -int ff_msmpeg4_encode_init(MpegEncContext *s); +void ff_msmpeg4_encode_init(MpegEncContext *s); void ff_msmpeg4_encode_picture_header(MpegEncContext *s, int picture_number); void ff_msmpeg4_encode_ext_header(MpegEncContext *s); void ff_msmpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], @@ -59,7 +59,7 @@ int ff_msmpeg4_decode_init(AVCodecContext *avctx); int ff_msmpeg4_decode_picture_header(MpegEncContext *s); int ff_msmpeg4_decode_ext_header(MpegEncContext *s, int buf_size); -int ff_msmpeg4_decode_motion(MpegEncContext * s, int *mx_ptr, int *my_ptr); +void ff_msmpeg4_decode_motion(MpegEncContext * s, int *mx_ptr, int *my_ptr); int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, int n, int coded, const uint8_t *scan_table); int ff_msmpeg4_pred_dc(MpegEncContext *s, int n, diff -Nru ffmpeg-4.2.2/libavcodec/msp2dec.c ffmpeg-4.4/libavcodec/msp2dec.c --- ffmpeg-4.2.2/libavcodec/msp2dec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/msp2dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,103 @@ +/* + * Microsoft Paint (MSP) version 2 decoder + * Copyright (c) 2020 Peter Ross (pross@xvid.org) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * Microsoft Paint (MSP) version 2 decoder + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +static int msp2_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVFrame *p = data; + int ret; + unsigned int x, y, width = (avctx->width + 7) / 8; + GetByteContext idx, gb; + + if (buf_size <= 2 * avctx->height) + return AVERROR_INVALIDDATA; + + avctx->pix_fmt = AV_PIX_FMT_MONOBLACK; + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + bytestream2_init(&idx, buf, 2 * avctx->height); + buf += 2 * avctx->height; + buf_size -= 2 * avctx->height; + + for (y = 0; y < avctx->height; y++) { + unsigned int pkt_size = bytestream2_get_le16(&idx); + if (!pkt_size) { + memset(p->data[0] + y * p->linesize[0], 0xFF, width); + continue; + } + + if (pkt_size > buf_size) { + av_log(avctx, AV_LOG_WARNING, "image probably corrupt\n"); + pkt_size = buf_size; + } + + bytestream2_init(&gb, buf, pkt_size); + x = 0; + while (bytestream2_get_bytes_left(&gb) && x < width) { + int size = bytestream2_get_byte(&gb); + if (size) { + size = FFMIN(size, bytestream2_get_bytes_left(&gb)); + memcpy(p->data[0] + y * p->linesize[0] + x, gb.buffer, FFMIN(size, width - x)); + bytestream2_skip(&gb, size); + } else { + int value; + size = bytestream2_get_byte(&gb); + if (!size) + avpriv_request_sample(avctx, "escape value"); + value = bytestream2_get_byte(&gb); + memset(p->data[0] + y * p->linesize[0] + x, value, FFMIN(size, width - x)); + } + x += size; + } + + buf += pkt_size; + buf_size -= pkt_size; + } + + *got_frame = 1; + return buf_size; +} + +AVCodec ff_msp2_decoder = { + .name = "msp2", + .long_name = NULL_IF_CONFIG_SMALL("Microsoft Paint (MSP) version 2"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSP2, + .decode = msp2_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, +}; diff -Nru ffmpeg-4.2.2/libavcodec/msrle.c ffmpeg-4.4/libavcodec/msrle.c --- ffmpeg-4.2.2/libavcodec/msrle.c 2019-01-15 11:50:52.000000000 +0000 +++ ffmpeg-4.4/libavcodec/msrle.c 2021-04-08 21:28:39.000000000 +0000 @@ -42,8 +42,6 @@ AVFrame *frame; GetByteContext gb; - const unsigned char *buf; - int size; uint32_t pal[256]; } MsrleContext; @@ -92,17 +90,14 @@ int istride = FFALIGN(avctx->width*avctx->bits_per_coded_sample, 32) / 8; int ret; - s->buf = buf; - s->size = buf_size; - if (buf_size < 2) //Minimally a end of picture code should be there return AVERROR_INVALIDDATA; - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; if (avctx->bits_per_coded_sample > 1 && avctx->bits_per_coded_sample <= 8) { - int size; + buffer_size_t size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size); if (pal && size == AVPALETTE_SIZE) { @@ -153,6 +148,13 @@ return buf_size; } +static void msrle_decode_flush(AVCodecContext *avctx) +{ + MsrleContext *s = avctx->priv_data; + + av_frame_unref(s->frame); +} + static av_cold int msrle_decode_end(AVCodecContext *avctx) { MsrleContext *s = avctx->priv_data; @@ -172,5 +174,6 @@ .init = msrle_decode_init, .close = msrle_decode_end, .decode = msrle_decode_frame, + .flush = msrle_decode_flush, .capabilities = AV_CODEC_CAP_DR1, }; diff -Nru ffmpeg-4.2.2/libavcodec/mss12.c ffmpeg-4.4/libavcodec/mss12.c --- ffmpeg-4.2.2/libavcodec/mss12.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mss12.c 2021-04-08 21:28:39.000000000 +0000 @@ -291,14 +291,15 @@ return decode_pixel(acoder, pctx, ref_pix, nlen, 1); } -static int decode_region(ArithCoder *acoder, uint8_t *dst, uint8_t *rgb_pic, +static int decode_region(ArithCoder *acoder, uint8_t *dst, uint8_t *rgb_dst, int x, int y, int width, int height, ptrdiff_t stride, ptrdiff_t rgb_stride, PixContext *pctx, const uint32_t *pal) { int i, j, p; - uint8_t *rgb_dst = rgb_pic + x * 3 + y * rgb_stride; + rgb_stride = rgb_dst ? rgb_stride : 0; + rgb_dst = rgb_dst ? rgb_dst + x * 3 + y * rgb_stride : NULL; dst += x + y * stride; for (j = 0; j < height; j++) { @@ -312,11 +313,11 @@ return p; dst[i] = p; - if (rgb_pic) + if (rgb_dst) AV_WB24(rgb_dst + i * 3, pal[p]); } dst += stride; - rgb_dst += rgb_stride; + rgb_dst = FF_PTR_ADD(rgb_dst, rgb_stride); } return 0; @@ -476,17 +477,19 @@ ptrdiff_t stride = c->pal_stride; ptrdiff_t rgb_stride = c->rgb_stride; uint8_t *dst = c->pal_pic + x + y * stride; - uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * rgb_stride; + uint8_t *rgb_dst = c->rgb_pic ? c->rgb_pic + x * 3 + y * rgb_stride : NULL; pix = decode_pixel(acoder, &sc->intra_pix_ctx, NULL, 0, 0); if (pix < 0) return pix; rgb_pix = c->pal[pix]; - for (i = 0; i < height; i++, dst += stride, rgb_dst += rgb_stride) { + for (i = 0; i < height; i++, dst += stride) { memset(dst, pix, width); - if (c->rgb_pic) + if (rgb_dst) { for (j = 0; j < width * 3; j += 3) AV_WB24(rgb_dst + j, rgb_pix); + rgb_dst += rgb_stride; + } } } else { return decode_region(acoder, c->pal_pic, c->rgb_pic, diff -Nru ffmpeg-4.2.2/libavcodec/mss1.c ffmpeg-4.4/libavcodec/mss1.c --- ffmpeg-4.2.2/libavcodec/mss1.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mss1.c 2020-07-11 10:39:30.000000000 +0000 @@ -154,7 +154,7 @@ arith_init(&acoder, &gb); - if ((ret = ff_reget_buffer(avctx, ctx->pic)) < 0) + if ((ret = ff_reget_buffer(avctx, ctx->pic, 0)) < 0) return ret; c->pal_pic = ctx->pic->data[0] + ctx->pic->linesize[0] * (avctx->height - 1); diff -Nru ffmpeg-4.2.2/libavcodec/mss2.c ffmpeg-4.4/libavcodec/mss2.c --- ffmpeg-4.2.2/libavcodec/mss2.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mss2.c 2020-07-11 10:39:30.000000000 +0000 @@ -412,8 +412,6 @@ ff_mpeg_er_frame_start(s); - v->bits = buf_size * 8; - v->end_mb_x = (w + 15) >> 4; s->end_mb_y = (h + 15) >> 4; if (v->respic & 1) @@ -618,7 +616,7 @@ return AVERROR_INVALIDDATA; } } else { - if ((ret = ff_reget_buffer(avctx, ctx->last_pic)) < 0) + if ((ret = ff_reget_buffer(avctx, ctx->last_pic, 0)) < 0) return ret; if ((ret = av_frame_ref(frame, ctx->last_pic)) < 0) return ret; diff -Nru ffmpeg-4.2.2/libavcodec/mss3.c ffmpeg-4.4/libavcodec/mss3.c --- ffmpeg-4.2.2/libavcodec/mss3.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mss3.c 2021-04-08 21:28:39.000000000 +0000 @@ -737,7 +737,7 @@ return buf_size; c->got_error = 0; - if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) + if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) return ret; c->pic->key_frame = keyframe; c->pic->pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; @@ -844,20 +844,13 @@ b_width * b_height); if (!c->dct_coder[i].prev_dc) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate buffer\n"); - av_frame_free(&c->pic); - while (i >= 0) { - av_freep(&c->dct_coder[i].prev_dc); - i--; - } return AVERROR(ENOMEM); } } c->pic = av_frame_alloc(); - if (!c->pic) { - mss3_decode_end(avctx); + if (!c->pic) return AVERROR(ENOMEM); - } avctx->pix_fmt = AV_PIX_FMT_YUV420P; @@ -876,4 +869,5 @@ .close = mss3_decode_end, .decode = mss3_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/mss4.c ffmpeg-4.4/libavcodec/mss4.c --- ffmpeg-4.2.2/libavcodec/mss4.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mss4.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,10 +25,13 @@ * aka Microsoft Expression Encoder Screen) decoder */ +#include "libavutil/thread.h" + #include "avcodec.h" #include "bytestream.h" #include "get_bits.h" #include "internal.h" +#include "jpegtables.h" #include "mss34dsp.h" #include "unary.h" @@ -57,56 +60,6 @@ { 0, 3, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0 } }; -static const uint8_t mss4_ac_vlc_lens[2][16] = { - { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125 }, - { 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119 } -}; - -static const uint8_t mss4_ac_vlc_syms[2][162] = { - { 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 }, - { 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 } -}; - static const uint8_t vec_len_syms[2][4] = { { 4, 2, 3, 1 }, { 4, 1, 2, 3 } @@ -127,8 +80,6 @@ typedef struct MSS4Context { AVFrame *pic; - VLC dc_vlc[2], ac_vlc[2]; - VLC vec_entry_vlc[2]; int block[64]; uint8_t imgbuf[3][16 * 16]; @@ -142,56 +93,43 @@ int prev_vec[3][4]; } MSS4Context; -static av_cold int mss4_init_vlc(VLC *vlc, const uint8_t *lens, - const uint8_t *syms, int num_syms) +static VLC dc_vlc[2], ac_vlc[2]; +static VLC vec_entry_vlc[2]; + +static av_cold void mss4_init_vlc(VLC *vlc, unsigned *offset, + const uint8_t *lens, const uint8_t *syms) { + static VLC_TYPE vlc_buf[2146][2]; uint8_t bits[MAX_ENTRIES]; - uint16_t codes[MAX_ENTRIES]; int i, j; - int prefix = 0, max_bits = 0, idx = 0; + int idx = 0; for (i = 0; i < 16; i++) { for (j = 0; j < lens[i]; j++) { bits[idx] = i + 1; - codes[idx] = prefix++; - max_bits = i + 1; idx++; } - prefix <<= 1; } - return ff_init_vlc_sparse(vlc, FFMIN(max_bits, 9), num_syms, bits, 1, 1, - codes, 2, 2, syms, 1, 1, 0); -} - -static av_cold int mss4_init_vlcs(MSS4Context *ctx) -{ - int ret, i; - - for (i = 0; i < 2; i++) { - ret = mss4_init_vlc(&ctx->dc_vlc[i], mss4_dc_vlc_lens[i], NULL, 12); - if (ret) - return ret; - ret = mss4_init_vlc(&ctx->ac_vlc[i], mss4_ac_vlc_lens[i], - mss4_ac_vlc_syms[i], 162); - if (ret) - return ret; - ret = mss4_init_vlc(&ctx->vec_entry_vlc[i], mss4_vec_entry_vlc_lens[i], - mss4_vec_entry_vlc_syms[i], 9); - if (ret) - return ret; - } - return 0; -} - -static av_cold void mss4_free_vlcs(MSS4Context *ctx) -{ - int i; - - for (i = 0; i < 2; i++) { - ff_free_vlc(&ctx->dc_vlc[i]); - ff_free_vlc(&ctx->ac_vlc[i]); - ff_free_vlc(&ctx->vec_entry_vlc[i]); + vlc->table = &vlc_buf[*offset]; + vlc->table_allocated = FF_ARRAY_ELEMS(vlc_buf) - *offset; + ff_init_vlc_from_lengths(vlc, FFMIN(bits[idx - 1], 9), idx, + bits, 1, syms, 1, 1, + 0, INIT_VLC_STATIC_OVERLONG, NULL); + *offset += vlc->table_size; +} + +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); + mss4_init_vlc(&vec_entry_vlc[i], &offset, mss4_vec_entry_vlc_lens[i], + mss4_vec_entry_vlc_syms[i]); } } @@ -289,7 +227,7 @@ int xpos = mb_x * 2 + i; c->dc_cache[j][TOP_LEFT] = c->dc_cache[j][TOP]; c->dc_cache[j][TOP] = c->prev_dc[0][mb_x * 2 + i]; - ret = mss4_decode_dct(gb, c->dc_vlc, c->ac_vlc, c->block, + ret = mss4_decode_dct(gb, &dc_vlc[0], &ac_vlc[0], c->block, c->dc_cache[j], xpos, mb_y * 2 + j, c->quant_mat[0]); if (ret) @@ -305,7 +243,7 @@ for (i = 1; i < 3; i++) { c->dc_cache[i + 1][TOP_LEFT] = c->dc_cache[i + 1][TOP]; c->dc_cache[i + 1][TOP] = c->prev_dc[i][mb_x]; - ret = mss4_decode_dct(gb, c->dc_vlc + 1, c->ac_vlc + 1, + ret = mss4_decode_dct(gb, &dc_vlc[1], &ac_vlc[1], c->block, c->dc_cache[i + 1], mb_x, mb_y, c->quant_mat[1]); if (ret) @@ -397,7 +335,7 @@ for (i = 0; i < 3; i++) { vec_len[i] = vec_len_syms[!!i][get_unary(gb, 0, 3)]; for (j = 0; j < vec_len[i]; j++) { - vec[i][j] = get_coeff(gb, &ctx->vec_entry_vlc[!!i]); + vec[i][j] = get_coeff(gb, &vec_entry_vlc[!!i]); vec[i][j] += ctx->prev_vec[i][j]; ctx->prev_vec[i][j] = vec[i][j]; } @@ -558,7 +496,7 @@ if (frame_type != SKIP_FRAME && 8*buf_size < 8*HEADER_SIZE + mb_width*mb_height) return AVERROR_INVALIDDATA; - if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) + if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) return ret; c->pic->key_frame = (frame_type == INTRA_FRAME); c->pic->pict_type = (frame_type == INTRA_FRAME) ? AV_PICTURE_TYPE_I @@ -636,39 +574,33 @@ av_frame_free(&c->pic); for (i = 0; i < 3; i++) av_freep(&c->prev_dc[i]); - mss4_free_vlcs(c); return 0; } static av_cold int mss4_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; MSS4Context * const c = avctx->priv_data; int i; - if (mss4_init_vlcs(c)) { - av_log(avctx, AV_LOG_ERROR, "Cannot initialise VLCs\n"); - mss4_free_vlcs(c); - return AVERROR(ENOMEM); - } for (i = 0; i < 3; i++) { c->dc_stride[i] = FFALIGN(avctx->width, 16) >> (2 + !!i); c->prev_dc[i] = av_malloc_array(c->dc_stride[i], sizeof(**c->prev_dc)); if (!c->prev_dc[i]) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate buffer\n"); - mss4_free_vlcs(c); return AVERROR(ENOMEM); } } c->pic = av_frame_alloc(); - if (!c->pic) { - mss4_decode_end(avctx); + if (!c->pic) return AVERROR(ENOMEM); - } avctx->pix_fmt = AV_PIX_FMT_YUV444P; + ff_thread_once(&init_static_once, mss4_init_vlcs); + return 0; } @@ -682,4 +614,5 @@ .close = mss4_decode_end, .decode = mss4_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/msvideo1.c ffmpeg-4.4/libavcodec/msvideo1.c --- ffmpeg-4.2.2/libavcodec/msvideo1.c 2019-03-29 00:49:21.000000000 +0000 +++ ffmpeg-4.4/libavcodec/msvideo1.c 2021-04-08 21:28:39.000000000 +0000 @@ -310,11 +310,11 @@ return AVERROR_INVALIDDATA; } - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; if (s->mode_8bit) { - int size; + buffer_size_t size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size); if (pal && size == AVPALETTE_SIZE) { diff -Nru ffmpeg-4.2.2/libavcodec/mv30.c ffmpeg-4.4/libavcodec/mv30.c --- ffmpeg-4.2.2/libavcodec/mv30.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mv30.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,718 @@ +/* + * MidiVid MV30 decoder + * + * Copyright (c) 2020 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 + +#include "libavutil/thread.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "copy_block.h" +#include "mathops.h" +#include "blockdsp.h" +#include "get_bits.h" +#include "internal.h" +#include "aandcttab.h" + +#define CBP_VLC_BITS 9 + +typedef struct MV30Context { + GetBitContext gb; + + int intra_quant; + int inter_quant; + int is_inter; + int mode_size; + int nb_mvectors; + + int block[6][64]; + int16_t *mvectors; + unsigned int mvectors_size; + int16_t *coeffs; + unsigned int coeffs_size; + + int16_t intraq_tab[2][64]; + int16_t interq_tab[2][64]; + + BlockDSPContext bdsp; + AVFrame *prev_frame; +} MV30Context; + +static VLC cbp_tab; + +static const uint8_t luma_tab[] = { + 12, 12, 15, 19, 25, 34, 40, 48, + 12, 12, 18, 22, 27, 44, 47, 46, + 17, 18, 21, 26, 35, 46, 52, 47, + 18, 20, 24, 28, 40, 61, 59, 51, + 20, 24, 32, 43, 50, 72, 72, 63, + 25, 31, 42, 48, 58, 72, 81, 75, + 38, 46, 54, 61, 71, 84, 88, 85, + 50, 61, 65, 68, 79, 78, 86, 91, +}; + +static const uint8_t chroma_tab[] = { + 12, 16, 24, 47, 99, 99, 99, 99, + 16, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, +}; + +static const uint8_t zigzag[] = { + 0, 1, 8, 9, 16, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, +}; + +static void get_qtable(int16_t *table, int quant, const uint8_t *quant_tab) +{ + int factor = quant < 50 ? 5000 / FFMAX(quant, 1) : 200 - FFMIN(quant, 100) * 2; + + for (int i = 0; i < 64; i++) { + table[i] = av_clip((quant_tab[i] * factor + 0x32) / 100, 1, 0x7fff); + table[i] = ((int)ff_aanscales[i] * (int)table[i] + 0x800) >> 12; + } +} + +static inline void idct_1d(unsigned *blk, int step) +{ + const unsigned t0 = blk[0 * step] + blk[4 * step]; + const unsigned t1 = blk[0 * step] - blk[4 * step]; + const unsigned t2 = blk[2 * step] + blk[6 * step]; + const unsigned t3 = ((int)((blk[2 * step] - blk[6 * step]) * 362U) >> 8) - t2; + const unsigned t4 = t0 + t2; + const unsigned t5 = t0 - t2; + const unsigned t6 = t1 + t3; + const unsigned t7 = t1 - t3; + const unsigned t8 = blk[5 * step] + blk[3 * step]; + const unsigned t9 = blk[5 * step] - blk[3 * step]; + const unsigned tA = blk[1 * step] + blk[7 * step]; + const unsigned tB = blk[1 * step] - blk[7 * step]; + const unsigned tC = t8 + tA; + const unsigned tD = (int)((tB + t9) * 473U) >> 8; + const unsigned tE = (((int)(t9 * -669U) >> 8) - tC) + tD; + const unsigned tF = ((int)((tA - t8) * 362U) >> 8) - tE; + const unsigned t10 = (((int)(tB * 277U) >> 8) - tD) + tF; + + blk[0 * step] = t4 + tC; + blk[1 * step] = t6 + tE; + blk[2 * step] = t7 + tF; + blk[3 * step] = t5 - t10; + blk[4 * step] = t5 + t10; + blk[5 * step] = t7 - tF; + blk[6 * step] = t6 - tE; + blk[7 * step] = t4 - tC; +} + +static void idct_put(uint8_t *dst, int stride, int *block) +{ + for (int i = 0; i < 8; i++) { + if ((block[0x08 + i] | + block[0x10 + i] | + block[0x18 + i] | + block[0x20 + i] | + block[0x28 + i] | + block[0x30 + i] | + block[0x38 + i]) == 0) { + block[0x08 + i] = block[i]; + block[0x10 + i] = block[i]; + block[0x18 + i] = block[i]; + block[0x20 + i] = block[i]; + block[0x28 + i] = block[i]; + block[0x30 + i] = block[i]; + block[0x38 + i] = block[i]; + } else { + idct_1d(block + i, 8); + } + } + + for (int i = 0; i < 8; i++) { + idct_1d(block, 1); + for (int j = 0; j < 8; j++) + dst[j] = av_clip_uint8((block[j] >> 5) + 128); + block += 8; + dst += stride; + } +} + +static void idct_add(uint8_t *dst, int stride, + const uint8_t *src, int in_linesize, int *block) +{ + for (int i = 0; i < 8; i++) { + if ((block[0x08 + i] | + block[0x10 + i] | + block[0x18 + i] | + block[0x20 + i] | + block[0x28 + i] | + block[0x30 + i] | + block[0x38 + i]) == 0) { + block[0x08 + i] = block[i]; + block[0x10 + i] = block[i]; + block[0x18 + i] = block[i]; + block[0x20 + i] = block[i]; + block[0x28 + i] = block[i]; + block[0x30 + i] = block[i]; + block[0x38 + i] = block[i]; + } else { + idct_1d(block + i, 8); + } + } + + for (int i = 0; i < 8; i++) { + idct_1d(block, 1); + for (int j = 0; j < 8; j++) + dst[j] = av_clip_uint8((block[j] >> 5) + src[j]); + block += 8; + dst += stride; + src += in_linesize; + } +} + +static inline void idct2_1d(int *blk, int step) +{ + const unsigned int t0 = blk[0 * step]; + const unsigned int t1 = blk[1 * step]; + const unsigned int t2 = (int)(t1 * 473U) >> 8; + const unsigned int t3 = t2 - t1; + const unsigned int t4 = ((int)(t1 * 362U) >> 8) - t3; + const unsigned int t5 = (((int)(t1 * 277U) >> 8) - t2) + t4; + + blk[0 * step] = t1 + t0; + blk[1 * step] = t0 + t3; + blk[2 * step] = t4 + t0; + blk[3 * step] = t0 - t5; + blk[4 * step] = t5 + t0; + blk[5 * step] = t0 - t4; + blk[6 * step] = t0 - t3; + blk[7 * step] = t0 - t1; +} + +static void idct2_put(uint8_t *dst, int stride, int *block) +{ + for (int i = 0; i < 2; i++) { + if ((block[0x08 + i]) == 0) { + block[0x08 + i] = block[i]; + block[0x10 + i] = block[i]; + block[0x18 + i] = block[i]; + block[0x20 + i] = block[i]; + block[0x28 + i] = block[i]; + block[0x30 + i] = block[i]; + block[0x38 + i] = block[i]; + } else { + idct2_1d(block + i, 8); + } + } + + for (int i = 0; i < 8; i++) { + if (block[1] == 0) { + for (int j = 0; j < 8; j++) + dst[j] = av_clip_uint8((block[0] >> 5) + 128); + } else { + idct2_1d(block, 1); + for (int j = 0; j < 8; j++) + dst[j] = av_clip_uint8((block[j] >> 5) + 128); + } + block += 8; + dst += stride; + } +} + +static void idct2_add(uint8_t *dst, int stride, + const uint8_t *src, int in_linesize, + int *block) +{ + for (int i = 0; i < 2; i++) { + if ((block[0x08 + i]) == 0) { + block[0x08 + i] = block[i]; + block[0x10 + i] = block[i]; + block[0x18 + i] = block[i]; + block[0x20 + i] = block[i]; + block[0x28 + i] = block[i]; + block[0x30 + i] = block[i]; + block[0x38 + i] = block[i]; + } else { + idct2_1d(block + i, 8); + } + } + + for (int i = 0; i < 8; i++) { + if (block[1] == 0) { + for (int j = 0; j < 8; j++) + dst[j] = av_clip_uint8((block[0] >> 5) + src[j]); + } else { + idct2_1d(block, 1); + for (int j = 0; j < 8; j++) + dst[j] = av_clip_uint8((block[j] >> 5) + src[j]); + } + block += 8; + dst += stride; + src += in_linesize; + } +} + +static void update_inter_block(uint8_t *dst, int stride, + const uint8_t *src, int in_linesize, + int block) +{ + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) + dst[j] = av_clip_uint8(block + src[j]); + dst += stride; + src += in_linesize; + } +} + +static int decode_intra_block(AVCodecContext *avctx, int mode, + GetByteContext *gbyte, int16_t *qtab, + int *block, int *pfill, + uint8_t *dst, int linesize) +{ + MV30Context *s = avctx->priv_data; + int fill; + + switch (mode) { + case 0: + s->bdsp.fill_block_tab[1](dst, 128, linesize, 8); + break; + case 1: + fill = sign_extend(bytestream2_get_ne16(gbyte), 16); + pfill[0] += fill; + block[0] = ((int)((unsigned)pfill[0] * qtab[0]) >> 5) + 128; + s->bdsp.fill_block_tab[1](dst, block[0], linesize, 8); + break; + case 2: + memset(block, 0, sizeof(*block) * 64); + fill = sign_extend(bytestream2_get_ne16(gbyte), 16); + pfill[0] += fill; + block[0] = (unsigned)pfill[0] * qtab[0]; + block[1] = sign_extend(bytestream2_get_ne16(gbyte), 16) * qtab[1]; + block[8] = sign_extend(bytestream2_get_ne16(gbyte), 16) * qtab[8]; + block[9] = sign_extend(bytestream2_get_ne16(gbyte), 16) * qtab[9]; + idct2_put(dst, linesize, block); + break; + case 3: + fill = sign_extend(bytestream2_get_ne16(gbyte), 16); + pfill[0] += fill; + block[0] = (unsigned)pfill[0] * qtab[0]; + for (int i = 1; i < 64; i++) + block[zigzag[i]] = sign_extend(bytestream2_get_ne16(gbyte), 16) * qtab[zigzag[i]]; + idct_put(dst, linesize, block); + break; + } + + return 0; +} + +static int decode_inter_block(AVCodecContext *avctx, int mode, + GetByteContext *gbyte, int16_t *qtab, + int *block, int *pfill, + uint8_t *dst, int linesize, + const uint8_t *src, int in_linesize) +{ + int fill; + + switch (mode) { + case 0: + copy_block8(dst, src, linesize, in_linesize, 8); + break; + case 1: + fill = sign_extend(bytestream2_get_ne16(gbyte), 16); + pfill[0] += fill; + block[0] = (int)((unsigned)pfill[0] * qtab[0]) >> 5; + update_inter_block(dst, linesize, src, in_linesize, block[0]); + break; + case 2: + memset(block, 0, sizeof(*block) * 64); + fill = sign_extend(bytestream2_get_ne16(gbyte), 16); + pfill[0] += fill; + block[0] = (unsigned)pfill[0] * qtab[0]; + block[1] = sign_extend(bytestream2_get_ne16(gbyte), 16) * qtab[1]; + block[8] = sign_extend(bytestream2_get_ne16(gbyte), 16) * qtab[8]; + block[9] = sign_extend(bytestream2_get_ne16(gbyte), 16) * qtab[9]; + idct2_add(dst, linesize, src, in_linesize, block); + break; + case 3: + fill = sign_extend(bytestream2_get_ne16(gbyte), 16); + pfill[0] += fill; + block[0] = (unsigned)pfill[0] * qtab[0]; + for (int i = 1; i < 64; i++) + block[zigzag[i]] = sign_extend(bytestream2_get_ne16(gbyte), 16) * qtab[zigzag[i]]; + idct_add(dst, linesize, src, in_linesize, block); + break; + } + + return 0; +} + +static int decode_coeffs(GetBitContext *gb, int16_t *coeffs, int nb_codes) +{ + memset(coeffs, 0, nb_codes * sizeof(*coeffs)); + + for (int i = 0; i < nb_codes;) { + int value = get_vlc2(gb, cbp_tab.table, CBP_VLC_BITS, 1); + + if (value > 0) { + int x = get_bits(gb, value); + + if (x < (1 << value) / 2) { + x = (1 << (value - 1)) + (x & ((1 << value) - 1 >> 1)); + } else { + x = -(1 << (value - 1)) - (x & ((1 << value) - 1 >> 1)); + } + coeffs[i++] = x; + } else { + int flag = get_bits1(gb); + + i += get_bits(gb, 3 + flag * 3) + 1 + flag * 8; + } + } + + return 0; +} + +static int decode_intra(AVCodecContext *avctx, GetBitContext *gb, AVFrame *frame) +{ + MV30Context *s = avctx->priv_data; + GetBitContext mgb; + uint8_t *dst[6]; + int linesize[6]; + int ret; + + mgb = *gb; + if (get_bits_left(gb) < s->mode_size * 8) + return AVERROR_INVALIDDATA; + + skip_bits_long(gb, s->mode_size * 8); + + linesize[0] = frame->linesize[0]; + linesize[1] = frame->linesize[0]; + linesize[2] = frame->linesize[0]; + linesize[3] = frame->linesize[0]; + linesize[4] = frame->linesize[1]; + linesize[5] = frame->linesize[2]; + + for (int y = 0; y < avctx->height; y += 16) { + GetByteContext gbyte; + int pfill[3][1] = { {0} }; + int nb_codes = get_bits(gb, 16); + + av_fast_padded_malloc(&s->coeffs, &s->coeffs_size, nb_codes * sizeof(*s->coeffs)); + if (!s->coeffs) + return AVERROR(ENOMEM); + ret = decode_coeffs(gb, s->coeffs, nb_codes); + if (ret < 0) + return ret; + + bytestream2_init(&gbyte, (uint8_t *)s->coeffs, nb_codes * sizeof(*s->coeffs)); + + for (int x = 0; x < avctx->width; x += 16) { + dst[0] = frame->data[0] + linesize[0] * y + x; + dst[1] = frame->data[0] + linesize[0] * y + x + 8; + dst[2] = frame->data[0] + linesize[0] * (y + 8) + x; + dst[3] = frame->data[0] + linesize[0] * (y + 8) + x + 8; + dst[4] = frame->data[1] + linesize[4] * (y >> 1) + (x >> 1); + dst[5] = frame->data[2] + linesize[5] * (y >> 1) + (x >> 1); + + for (int b = 0; b < 6; b++) { + int mode = get_bits_le(&mgb, 2); + + ret = decode_intra_block(avctx, mode, &gbyte, s->intraq_tab[b >= 4], + s->block[b], + pfill[(b >= 4) + (b >= 5)], + dst[b], linesize[b]); + if (ret < 0) + return ret; + } + } + } + + return 0; +} + +static int decode_inter(AVCodecContext *avctx, GetBitContext *gb, + AVFrame *frame, AVFrame *prev) +{ + MV30Context *s = avctx->priv_data; + GetBitContext mask; + GetBitContext mgb; + GetByteContext mv; + const int mask_size = ((avctx->height >> 4) * (avctx->width >> 4) * 2 + 7) / 8; + uint8_t *dst[6], *src[6]; + int in_linesize[6]; + int linesize[6]; + int ret, cnt = 0; + int flags = 0; + + in_linesize[0] = prev->linesize[0]; + in_linesize[1] = prev->linesize[0]; + in_linesize[2] = prev->linesize[0]; + in_linesize[3] = prev->linesize[0]; + in_linesize[4] = prev->linesize[1]; + in_linesize[5] = prev->linesize[2]; + + linesize[0] = frame->linesize[0]; + linesize[1] = frame->linesize[0]; + linesize[2] = frame->linesize[0]; + linesize[3] = frame->linesize[0]; + linesize[4] = frame->linesize[1]; + linesize[5] = frame->linesize[2]; + + av_fast_padded_malloc(&s->mvectors, &s->mvectors_size, 2 * s->nb_mvectors * sizeof(*s->mvectors)); + if (!s->mvectors) { + ret = AVERROR(ENOMEM); + goto fail; + } + + mask = *gb; + skip_bits_long(gb, mask_size * 8); + mgb = *gb; + skip_bits_long(gb, s->mode_size * 8); + + ret = decode_coeffs(gb, s->mvectors, 2 * s->nb_mvectors); + if (ret < 0) + goto fail; + + bytestream2_init(&mv, (uint8_t *)s->mvectors, 2 * s->nb_mvectors * sizeof(*s->mvectors)); + + for (int y = 0; y < avctx->height; y += 16) { + GetByteContext gbyte; + int pfill[3][1] = { {0} }; + int nb_codes = get_bits(gb, 16); + + skip_bits(gb, 8); + if (get_bits_left(gb) < 0) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + av_fast_padded_malloc(&s->coeffs, &s->coeffs_size, nb_codes * sizeof(*s->coeffs)); + if (!s->coeffs) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = decode_coeffs(gb, s->coeffs, nb_codes); + if (ret < 0) + goto fail; + + bytestream2_init(&gbyte, (uint8_t *)s->coeffs, nb_codes * sizeof(*s->coeffs)); + + for (int x = 0; x < avctx->width; x += 16) { + if (cnt >= 4) + cnt = 0; + if (cnt == 0) { + if (get_bits_left(&mask) < 8) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + flags = get_bits(&mask, 8); + } + + dst[0] = frame->data[0] + linesize[0] * y + x; + dst[1] = frame->data[0] + linesize[0] * y + x + 8; + dst[2] = frame->data[0] + linesize[0] * (y + 8) + x; + dst[3] = frame->data[0] + linesize[0] * (y + 8) + x + 8; + dst[4] = frame->data[1] + linesize[4] * (y >> 1) + (x >> 1); + dst[5] = frame->data[2] + linesize[5] * (y >> 1) + (x >> 1); + + if ((flags >> (cnt)) & 1) { + int mv_x = sign_extend(bytestream2_get_ne16(&mv), 16); + int mv_y = sign_extend(bytestream2_get_ne16(&mv), 16); + + int px = x + mv_x; + int py = y + mv_y; + + if (px < 0 || px > FFALIGN(avctx->width , 16) - 16 || + py < 0 || py > FFALIGN(avctx->height, 16) - 16) + return AVERROR_INVALIDDATA; + + src[0] = prev->data[0] + in_linesize[0] * py + px; + src[1] = prev->data[0] + in_linesize[0] * py + px + 8; + src[2] = prev->data[0] + in_linesize[0] * (py + 8) + px; + src[3] = prev->data[0] + in_linesize[0] * (py + 8) + px + 8; + src[4] = prev->data[1] + in_linesize[4] * (py >> 1) + (px >> 1); + src[5] = prev->data[2] + in_linesize[5] * (py >> 1) + (px >> 1); + + if ((flags >> (cnt + 4)) & 1) { + for (int b = 0; b < 6; b++) + copy_block8(dst[b], src[b], linesize[b], in_linesize[b], 8); + } else { + for (int b = 0; b < 6; b++) { + int mode = get_bits_le(&mgb, 2); + + ret = decode_inter_block(avctx, mode, &gbyte, s->interq_tab[b >= 4], + s->block[b], + pfill[(b >= 4) + (b >= 5)], + dst[b], linesize[b], + src[b], in_linesize[b]); + if (ret < 0) + goto fail; + } + } + } else { + for (int b = 0; b < 6; b++) { + int mode = get_bits_le(&mgb, 2); + + ret = decode_intra_block(avctx, mode, &gbyte, s->intraq_tab[b >= 4], + s->block[b], + pfill[(b >= 4) + (b >= 5)], + dst[b], linesize[b]); + if (ret < 0) + goto fail; + } + } + + cnt++; + } + } + +fail: + return ret; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + MV30Context *s = avctx->priv_data; + GetBitContext *gb = &s->gb; + AVFrame *frame = data; + int ret; + + if ((ret = init_get_bits8(gb, avpkt->data, avpkt->size)) < 0) + return ret; + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + s->intra_quant = get_bits(gb, 8); + s->inter_quant = s->intra_quant + get_sbits(gb, 8); + s->is_inter = get_bits_le(gb, 16); + s->mode_size = get_bits_le(gb, 16); + if (s->is_inter) + s->nb_mvectors = get_bits_le(gb, 16); + + get_qtable(s->intraq_tab[0], s->intra_quant, luma_tab); + get_qtable(s->intraq_tab[1], s->intra_quant, chroma_tab); + + frame->key_frame = s->is_inter == 0; + + if (frame->key_frame) { + ret = decode_intra(avctx, gb, frame); + if (ret < 0) + return ret; + } else { + get_qtable(s->interq_tab[0], s->inter_quant, luma_tab); + get_qtable(s->interq_tab[1], s->inter_quant, chroma_tab); + + if (!s->prev_frame->data[0]) { + av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n"); + return AVERROR_INVALIDDATA; + } + + ret = decode_inter(avctx, gb, frame, s->prev_frame); + if (ret < 0) + return ret; + } + + av_frame_unref(s->prev_frame); + if ((ret = av_frame_ref(s->prev_frame, frame)) < 0) + return ret; + + *got_frame = 1; + + return avpkt->size; +} + +static const uint8_t cbp_bits[] = { + 2, 2, 3, 3, 3, 4, 5, 6, 7, 8, 9, 9, +}; + +static av_cold void init_static_data(void) +{ + INIT_VLC_STATIC_FROM_LENGTHS(&cbp_tab, CBP_VLC_BITS, FF_ARRAY_ELEMS(cbp_bits), + cbp_bits, 1, NULL, 0, 0, 0, 0, 1 << CBP_VLC_BITS); +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + MV30Context *s = avctx->priv_data; + static AVOnce init_static_once = AV_ONCE_INIT; + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + avctx->color_range = AVCOL_RANGE_JPEG; + + ff_blockdsp_init(&s->bdsp, avctx); + + s->prev_frame = av_frame_alloc(); + if (!s->prev_frame) + return AVERROR(ENOMEM); + + ff_thread_once(&init_static_once, init_static_data); + + return 0; +} + +static void decode_flush(AVCodecContext *avctx) +{ + MV30Context *s = avctx->priv_data; + + av_frame_unref(s->prev_frame); +} + +static av_cold int decode_close(AVCodecContext *avctx) +{ + MV30Context *s = avctx->priv_data; + + av_frame_free(&s->prev_frame); + av_freep(&s->coeffs); + s->coeffs_size = 0; + av_freep(&s->mvectors); + s->mvectors_size = 0; + + return 0; +} + +AVCodec ff_mv30_decoder = { + .name = "mv30", + .long_name = NULL_IF_CONFIG_SMALL("MidiVid 3.0"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MV30, + .priv_data_size = sizeof(MV30Context), + .init = decode_init, + .close = decode_close, + .decode = decode_frame, + .flush = decode_flush, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff -Nru ffmpeg-4.2.2/libavcodec/mvha.c ffmpeg-4.4/libavcodec/mvha.c --- ffmpeg-4.2.2/libavcodec/mvha.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mvha.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,322 @@ +/* + * MidiVid Archive codec + * + * Copyright (c) 2019 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 + +#define CACHED_BITSTREAM_READER !ARCH_X86_32 +#include "libavutil/intreadwrite.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "get_bits.h" +#include "internal.h" +#include "lossless_videodsp.h" + +#include + +typedef struct MVHAContext { + GetBitContext gb; + int nb_symbols; + + uint8_t symb[256]; + uint32_t prob[256]; + VLC vlc; + + z_stream zstream; + LLVidDSPContext llviddsp; +} MVHAContext; + +typedef struct Node { + int16_t sym; + int16_t n0; + int16_t l, r; + uint32_t count; +} Node; + +static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat, + Node *nodes, int node, + uint32_t pfx, int pl, int *pos) +{ + int s; + + s = nodes[node].sym; + if (s != -1) { + bits[*pos] = (~pfx) & ((1ULL << FFMAX(pl, 1)) - 1); + lens[*pos] = FFMAX(pl, 1); + xlat[*pos] = s + (pl == 0); + (*pos)++; + } else { + pfx <<= 1; + pl++; + get_tree_codes(bits, lens, xlat, nodes, nodes[node].l, pfx, pl, + pos); + pfx |= 1; + get_tree_codes(bits, lens, xlat, nodes, nodes[node].r, pfx, pl, + pos); + } +} + +static int build_vlc(AVCodecContext *avctx, VLC *vlc) +{ + MVHAContext *s = avctx->priv_data; + Node nodes[512]; + uint32_t bits[256]; + int16_t lens[256]; + uint8_t xlat[256]; + int cur_node, i, j, pos = 0; + + ff_free_vlc(vlc); + + for (i = 0; i < s->nb_symbols; i++) { + nodes[i].count = s->prob[i]; + nodes[i].sym = s->symb[i]; + nodes[i].n0 = -2; + nodes[i].l = i; + nodes[i].r = i; + } + + cur_node = s->nb_symbols; + j = 0; + do { + for (i = 0; ; i++) { + int new_node = j; + int first_node = cur_node; + int second_node = cur_node; + unsigned nd, st; + + nodes[cur_node].count = -1; + + do { + int val = nodes[new_node].count; + if (val && (val < nodes[first_node].count)) { + if (val >= nodes[second_node].count) { + first_node = new_node; + } else { + first_node = second_node; + second_node = new_node; + } + } + new_node += 1; + } while (new_node != cur_node); + + if (first_node == cur_node) + break; + + nd = nodes[second_node].count; + st = nodes[first_node].count; + nodes[second_node].count = 0; + nodes[first_node].count = 0; + if (nd >= UINT32_MAX - st) { + av_log(avctx, AV_LOG_ERROR, "count overflow\n"); + return AVERROR_INVALIDDATA; + } + nodes[cur_node].count = nd + st; + nodes[cur_node].sym = -1; + nodes[cur_node].n0 = cur_node; + nodes[cur_node].l = first_node; + nodes[cur_node].r = second_node; + cur_node++; + } + j++; + } while (cur_node - s->nb_symbols == j); + + get_tree_codes(bits, lens, xlat, nodes, cur_node - 1, 0, 0, &pos); + + return ff_init_vlc_sparse(vlc, 12, pos, lens, 2, 2, bits, 4, 4, xlat, 1, 1, 0); +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + MVHAContext *s = avctx->priv_data; + AVFrame *frame = data; + uint32_t type, size; + int ret; + + if (avpkt->size <= 8) + return AVERROR_INVALIDDATA; + + type = AV_RB32(avpkt->data); + size = AV_RL32(avpkt->data + 4); + + if (size < 1 || size >= avpkt->size) + return AVERROR_INVALIDDATA; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + if (type == MKTAG('L','Z','Y','V')) { + ret = inflateReset(&s->zstream); + if (ret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret); + return AVERROR_EXTERNAL; + } + + s->zstream.next_in = avpkt->data + 8; + s->zstream.avail_in = avpkt->size - 8; + + for (int p = 0; p < 3; p++) { + for (int y = 0; y < avctx->height; y++) { + s->zstream.next_out = frame->data[p] + (avctx->height - y - 1) * frame->linesize[p]; + s->zstream.avail_out = avctx->width >> (p > 0); + + ret = inflate(&s->zstream, Z_SYNC_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) { + av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", ret); + return AVERROR_EXTERNAL; + } + } + } + } else if (type == MKTAG('H','U','F','Y')) { + GetBitContext *gb = &s->gb; + int first_symbol, symbol; + + ret = init_get_bits8(gb, avpkt->data + 8, avpkt->size - 8); + if (ret < 0) + return ret; + + skip_bits(gb, 24); + + first_symbol = get_bits(gb, 8); + s->nb_symbols = get_bits(gb, 8) + 1; + + symbol = first_symbol; + for (int i = 0; i < s->nb_symbols; symbol++) { + int prob; + + if (get_bits_left(gb) < 4) + return AVERROR_INVALIDDATA; + + if (get_bits1(gb)) { + prob = get_bits(gb, 12); + } else { + prob = get_bits(gb, 3); + } + + if (prob) { + s->symb[i] = symbol; + s->prob[i] = prob; + i++; + } + } + + ret = build_vlc(avctx, &s->vlc); + if (ret < 0) + return ret; + + for (int p = 0; p < 3; p++) { + int width = avctx->width >> (p > 0); + ptrdiff_t stride = frame->linesize[p]; + uint8_t *dst; + + dst = frame->data[p] + (avctx->height - 1) * frame->linesize[p]; + for (int y = 0; y < avctx->height; y++) { + if (get_bits_left(gb) < width) + return AVERROR_INVALIDDATA; + for (int x = 0; x < width; x++) { + int v = get_vlc2(gb, s->vlc.table, s->vlc.bits, 3); + + if (v < 0) + return AVERROR_INVALIDDATA; + + dst[x] = v; + } + dst -= stride; + } + } + } else { + return AVERROR_INVALIDDATA; + } + + for (int p = 0; p < 3; p++) { + int left, lefttop; + int width = avctx->width >> (p > 0); + ptrdiff_t stride = frame->linesize[p]; + uint8_t *dst; + + dst = frame->data[p] + (avctx->height - 1) * frame->linesize[p]; + s->llviddsp.add_left_pred(dst, dst, width, 0); + if (avctx->height > 1) { + dst -= stride; + lefttop = left = dst[0]; + for (int y = 1; y < avctx->height; y++) { + s->llviddsp.add_median_pred(dst, dst + stride, dst, width, &left, &lefttop); + lefttop = left = dst[0]; + dst -= stride; + } + } + } + + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + MVHAContext *s = avctx->priv_data; + int zret; + + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + + s->zstream.zalloc = Z_NULL; + s->zstream.zfree = Z_NULL; + s->zstream.opaque = Z_NULL; + zret = inflateInit(&s->zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); + return AVERROR_EXTERNAL; + } + + ff_llviddsp_init(&s->llviddsp); + + return 0; +} + +static av_cold int decode_close(AVCodecContext *avctx) +{ + MVHAContext *s = avctx->priv_data; + + inflateEnd(&s->zstream); + ff_free_vlc(&s->vlc); + + return 0; +} + +AVCodec ff_mvha_decoder = { + .name = "mvha", + .long_name = NULL_IF_CONFIG_SMALL("MidiVid Archive Codec"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MVHA, + .priv_data_size = sizeof(MVHAContext), + .init = decode_init, + .close = decode_close, + .decode = decode_frame, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff -Nru ffmpeg-4.2.2/libavcodec/mxpegdec.c ffmpeg-4.4/libavcodec/mxpegdec.c --- ffmpeg-4.2.2/libavcodec/mxpegdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/mxpegdec.c 2021-04-08 21:28:27.000000000 +0000 @@ -67,10 +67,8 @@ s->picture[0] = av_frame_alloc(); s->picture[1] = av_frame_alloc(); - if (!s->picture[0] || !s->picture[1]) { - mxpeg_decode_end(avctx); + if (!s->picture[0] || !s->picture[1]) return AVERROR(ENOMEM); - } s->jpg.picture_ptr = s->picture[0]; return ff_mjpeg_decode_init(avctx); @@ -247,16 +245,17 @@ "Multiple SOF in a frame\n"); return AVERROR_INVALIDDATA; } - s->got_sof_data = 0; ret = ff_mjpeg_decode_sof(jpg); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "SOF data decode error\n"); + s->got_sof_data = 0; return ret; } if (jpg->interlaced) { av_log(avctx, AV_LOG_ERROR, "Interlaced mode not supported in MxPEG\n"); + s->got_sof_data = 0; return AVERROR(EINVAL); } s->got_sof_data ++; @@ -351,5 +350,5 @@ .decode = mxpeg_decode_frame, .capabilities = AV_CODEC_CAP_DR1, .max_lowres = 3, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/nellymoserdec.c ffmpeg-4.4/libavcodec/nellymoserdec.c --- ffmpeg-4.2.2/libavcodec/nellymoserdec.c 2018-11-01 18:34:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/nellymoserdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,6 +34,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/float_dsp.h" #include "libavutil/lfg.h" +#include "libavutil/mem_internal.h" #include "libavutil/random_seed.h" #define BITSTREAM_READER_LE @@ -128,13 +129,12 @@ s->scale_bias = 1.0/(32768*8); avctx->sample_fmt = AV_SAMPLE_FMT_FLT; - /* Generate overlap window */ - if (!ff_sine_128[127]) - ff_init_ff_sine_windows(7); - avctx->channels = 1; avctx->channel_layout = AV_CH_LAYOUT_MONO; + /* Generate overlap window */ + ff_init_ff_sine_windows(7); + return 0; } @@ -143,7 +143,6 @@ { AVFrame *frame = data; const uint8_t *buf = avpkt->data; - const uint8_t *side=av_packet_get_side_data(avpkt, 'F', NULL); int buf_size = avpkt->size; NellyMoserDecodeContext *s = avctx->priv_data; int blocks, i, ret; @@ -160,15 +159,6 @@ av_log(avctx, AV_LOG_WARNING, "Leftover bytes: %d.\n", buf_size % NELLY_BLOCK_LEN); } - /* Normal numbers of blocks for sample rates: - * 8000 Hz - 1 - * 11025 Hz - 2 - * 16000 Hz - 3 - * 22050 Hz - 4 - * 44100 Hz - 8 - */ - if(side && blocks>1 && avctx->sample_rate%11025==0 && (1<<((side[0]>>2)&3)) == blocks) - avctx->sample_rate= 11025*(blocks/2); /* get output buffer */ frame->nb_samples = NELLY_SAMPLES * blocks; @@ -205,7 +195,8 @@ .init = decode_init, .close = decode_end, .decode = decode_tag, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE | AV_CODEC_CAP_CHANNEL_CONF, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/nellymoserenc.c ffmpeg-4.4/libavcodec/nellymoserenc.c --- ffmpeg-4.2.2/libavcodec/nellymoserenc.c 2018-07-17 09:27:40.000000000 +0000 +++ ffmpeg-4.4/libavcodec/nellymoserenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -38,6 +38,7 @@ #include "libavutil/common.h" #include "libavutil/float_dsp.h" #include "libavutil/mathematics.h" +#include "libavutil/thread.h" #include "audio_frame_queue.h" #include "avcodec.h" @@ -147,10 +148,29 @@ return 0; } +static av_cold void nellymoser_init_static(void) +{ + /* faster way of doing + for (int i = 0; i < POW_TABLE_SIZE; i++) + pow_table[i] = 2^(-i / 2048.0 - 3.0 + POW_TABLE_OFFSET); */ + pow_table[0] = 1; + pow_table[1024] = M_SQRT1_2; + for (int i = 1; i < 513; i++) { + double tmp = exp2(-i / 2048.0); + pow_table[i] = tmp; + pow_table[1024-i] = M_SQRT1_2 / tmp; + pow_table[1024+i] = tmp * M_SQRT1_2; + pow_table[2048-i] = 0.5 / tmp; + } + /* Generate overlap window */ + ff_init_ff_sine_windows(7); +} + static av_cold int encode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; NellyMoserEncodeContext *s = avctx->priv_data; - int i, ret; + int ret; if (avctx->channels != 1) { av_log(avctx, AV_LOG_ERROR, "Nellymoser supports only 1 channel\n"); @@ -170,41 +190,21 @@ ff_af_queue_init(avctx, &s->afq); s->avctx = avctx; if ((ret = ff_mdct_init(&s->mdct_ctx, 8, 0, 32768.0)) < 0) - goto error; + return ret; s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); - if (!s->fdsp) { - ret = AVERROR(ENOMEM); - goto error; - } - - /* Generate overlap window */ - ff_init_ff_sine_windows(7); - /* faster way of doing - for (i = 0; i < POW_TABLE_SIZE; i++) - pow_table[i] = 2^(-i / 2048.0 - 3.0 + POW_TABLE_OFFSET); */ - pow_table[0] = 1; - pow_table[1024] = M_SQRT1_2; - for (i = 1; i < 513; i++) { - double tmp = exp2(-i / 2048.0); - pow_table[i] = tmp; - pow_table[1024-i] = M_SQRT1_2 / tmp; - pow_table[1024+i] = tmp * M_SQRT1_2; - pow_table[2048-i] = 0.5 / tmp; - } + if (!s->fdsp) + return AVERROR(ENOMEM); if (s->avctx->trellis) { s->opt = av_malloc(NELLY_BANDS * OPT_SIZE * sizeof(float )); s->path = av_malloc(NELLY_BANDS * OPT_SIZE * sizeof(uint8_t)); - if (!s->opt || !s->path) { - ret = AVERROR(ENOMEM); - goto error; - } + if (!s->opt || !s->path) + return AVERROR(ENOMEM); } + ff_thread_once(&init_static_once, nellymoser_init_static); + return 0; -error: - encode_end(avctx); - return ret; } #define find_best(val, table, LUT, LUT_add, LUT_size) \ @@ -431,4 +431,5 @@ .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/noise_bsf.c ffmpeg-4.4/libavcodec/noise_bsf.c --- ffmpeg-4.2.2/libavcodec/noise_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/noise_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -19,13 +19,11 @@ */ #include -#include -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "libavutil/log.h" -#include "libavutil/mem.h" #include "libavutil/opt.h" typedef struct NoiseContext { @@ -39,7 +37,7 @@ { NoiseContext *s = ctx->priv_data; int amount = s->amount > 0 ? s->amount : (s->state % 10001 + 1); - int i, ret = 0; + int i, ret; if (amount <= 0) return AVERROR(EINVAL); @@ -55,19 +53,18 @@ } ret = av_packet_make_writable(pkt); - if (ret < 0) - goto fail; + if (ret < 0) { + av_packet_unref(pkt); + return ret; + } for (i = 0; i < pkt->size; i++) { s->state += pkt->data[i] + 1; if (s->state % amount == 0) pkt->data[i] = s->state; } -fail: - if (ret < 0) - av_packet_unref(pkt); - return ret; + return 0; } #define OFFSET(x) offsetof(NoiseContext, x) diff -Nru ffmpeg-4.2.2/libavcodec/notchlc.c ffmpeg-4.4/libavcodec/notchlc.c --- ffmpeg-4.2.2/libavcodec/notchlc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/notchlc.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,550 @@ +/* + * NotchLC decoder + * Copyright (c) 2020 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 + +#define BITSTREAM_READER_LE +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "bytestream.h" +#include "get_bits.h" +#include "internal.h" +#include "lzf.h" +#include "thread.h" + +typedef struct NotchLCContext { + unsigned compressed_size; + unsigned format; + + uint8_t *uncompressed_buffer; + unsigned uncompressed_size; + + uint8_t *lzf_buffer; + int64_t lzf_size; + + unsigned texture_size_x; + unsigned texture_size_y; + unsigned y_data_row_offsets; + unsigned uv_offset_data_offset; + unsigned y_control_data_offset; + unsigned a_control_word_offset; + unsigned y_data_offset; + unsigned uv_data_offset; + unsigned y_data_size; + unsigned a_data_offset; + unsigned uv_count_offset; + unsigned a_count_size; + unsigned data_end; + + GetByteContext gb; + PutByteContext pb; +} NotchLCContext; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUVA444P12; + avctx->color_range = AVCOL_RANGE_JPEG; + avctx->colorspace = AVCOL_SPC_RGB; + avctx->color_primaries = AVCOL_PRI_BT709; + avctx->color_trc = AVCOL_TRC_IEC61966_2_1; + + return 0; +} + +#define HISTORY_SIZE (64 * 1024) + +static int lz4_decompress(AVCodecContext *avctx, + GetByteContext *gb, + PutByteContext *pb) +{ + unsigned reference_pos, match_length, delta, pos = 0; + uint8_t history[64 * 1024]; + + while (bytestream2_get_bytes_left(gb) > 0) { + uint8_t token = bytestream2_get_byte(gb); + unsigned num_literals = token >> 4; + + if (num_literals == 15) { + unsigned char current; + do { + current = bytestream2_get_byte(gb); + num_literals += current; + } while (current == 255); + } + + if (pos + num_literals < HISTORY_SIZE) { + bytestream2_get_buffer(gb, history + pos, num_literals); + pos += num_literals; + } else { + while (num_literals-- > 0) { + history[pos++] = bytestream2_get_byte(gb); + if (pos == HISTORY_SIZE) { + bytestream2_put_buffer(pb, history, HISTORY_SIZE); + pos = 0; + } + } + } + + if (bytestream2_get_bytes_left(gb) <= 0) + break; + + delta = bytestream2_get_le16(gb); + if (delta == 0) + return 0; + match_length = 4 + (token & 0x0F); + if (match_length == 4 + 0x0F) { + uint8_t current; + + do { + current = bytestream2_get_byte(gb); + match_length += current; + } while (current == 255); + } + reference_pos = (pos >= delta) ? (pos - delta) : (HISTORY_SIZE + pos - delta); + if (pos + match_length < HISTORY_SIZE && reference_pos + match_length < HISTORY_SIZE) { + if (pos >= reference_pos + match_length || reference_pos >= pos + match_length) { + memcpy(history + pos, history + reference_pos, match_length); + pos += match_length; + } else { + while (match_length-- > 0) + history[pos++] = history[reference_pos++]; + } + } else { + while (match_length-- > 0) { + history[pos++] = history[reference_pos++]; + if (pos == HISTORY_SIZE) { + bytestream2_put_buffer(pb, history, HISTORY_SIZE); + pos = 0; + } + reference_pos %= HISTORY_SIZE; + } + } + } + + bytestream2_put_buffer(pb, history, pos); + + return bytestream2_tell_p(pb); +} + +static int decode_blocks(AVCodecContext *avctx, AVFrame *p, ThreadFrame *frame, + unsigned uncompressed_size) +{ + NotchLCContext *s = avctx->priv_data; + GetByteContext rgb, dgb, *gb = &s->gb; + GetBitContext bit; + int ylinesize, ulinesize, vlinesize, alinesize; + uint16_t *dsty, *dstu, *dstv, *dsta; + int ret; + + s->texture_size_x = bytestream2_get_le32(gb); + s->texture_size_y = bytestream2_get_le32(gb); + + ret = ff_set_dimensions(avctx, s->texture_size_x, s->texture_size_y); + if (ret < 0) + return ret; + + s->uv_offset_data_offset = bytestream2_get_le32(gb); + if (s->uv_offset_data_offset >= UINT_MAX / 4) + return AVERROR_INVALIDDATA; + s->uv_offset_data_offset *= 4; + if (s->uv_offset_data_offset >= uncompressed_size) + return AVERROR_INVALIDDATA; + + s->y_control_data_offset = bytestream2_get_le32(gb); + if (s->y_control_data_offset >= UINT_MAX / 4) + return AVERROR_INVALIDDATA; + s->y_control_data_offset *= 4; + if (s->y_control_data_offset >= uncompressed_size) + return AVERROR_INVALIDDATA; + + s->a_control_word_offset = bytestream2_get_le32(gb); + if (s->a_control_word_offset >= UINT_MAX / 4) + return AVERROR_INVALIDDATA; + s->a_control_word_offset *= 4; + if (s->a_control_word_offset >= uncompressed_size) + return AVERROR_INVALIDDATA; + + s->uv_data_offset = bytestream2_get_le32(gb); + if (s->uv_data_offset >= UINT_MAX / 4) + return AVERROR_INVALIDDATA; + s->uv_data_offset *= 4; + if (s->uv_data_offset >= uncompressed_size) + return AVERROR_INVALIDDATA; + + s->y_data_size = bytestream2_get_le32(gb); + if (s->y_data_size >= UINT_MAX / 4) + return AVERROR_INVALIDDATA; + + s->a_data_offset = bytestream2_get_le32(gb); + if (s->a_data_offset >= UINT_MAX / 4) + return AVERROR_INVALIDDATA; + s->a_data_offset *= 4; + if (s->a_data_offset >= uncompressed_size) + return AVERROR_INVALIDDATA; + + s->a_count_size = bytestream2_get_le32(gb); + if (s->a_count_size >= UINT_MAX / 4) + return AVERROR_INVALIDDATA; + s->a_count_size *= 4; + if (s->a_count_size >= uncompressed_size) + return AVERROR_INVALIDDATA; + + s->data_end = bytestream2_get_le32(gb); + if (s->data_end > uncompressed_size) + return AVERROR_INVALIDDATA; + + s->y_data_row_offsets = bytestream2_tell(gb); + if (s->data_end <= s->y_data_size) + return AVERROR_INVALIDDATA; + s->y_data_offset = s->data_end - s->y_data_size; + if (s->y_data_offset <= s->a_data_offset) + return AVERROR_INVALIDDATA; + s->uv_count_offset = s->y_data_offset - s->a_data_offset; + + if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0) + return ret; + + rgb = *gb; + dgb = *gb; + bytestream2_seek(&rgb, s->y_data_row_offsets, SEEK_SET); + bytestream2_seek(gb, s->y_control_data_offset, SEEK_SET); + + if (bytestream2_get_bytes_left(gb) < (avctx->height + 3) / 4 * ((avctx->width + 3) / 4) * 4) + return AVERROR_INVALIDDATA; + + dsty = (uint16_t *)p->data[0]; + dsta = (uint16_t *)p->data[3]; + ylinesize = p->linesize[0] / 2; + alinesize = p->linesize[3] / 2; + + for (int y = 0; y < avctx->height; y += 4) { + const unsigned row_offset = bytestream2_get_le32(&rgb); + + bytestream2_seek(&dgb, s->y_data_offset + row_offset, SEEK_SET); + + init_get_bits8(&bit, dgb.buffer, bytestream2_get_bytes_left(&dgb)); + for (int x = 0; x < avctx->width; x += 4) { + unsigned item = bytestream2_get_le32(gb); + unsigned y_min = item & 4095; + unsigned y_max = (item >> 12) & 4095; + unsigned y_diff = y_max - y_min; + unsigned control[4]; + + control[0] = (item >> 24) & 3; + control[1] = (item >> 26) & 3; + control[2] = (item >> 28) & 3; + control[3] = (item >> 30) & 3; + + for (int i = 0; i < 4; i++) { + const int nb_bits = control[i] + 1; + const int div = (1 << nb_bits) - 1; + const int add = div - 1; + + dsty[x + i * ylinesize + 0] = av_clip_uintp2(y_min + ((y_diff * get_bits(&bit, nb_bits) + add) / div), 12); + dsty[x + i * ylinesize + 1] = av_clip_uintp2(y_min + ((y_diff * get_bits(&bit, nb_bits) + add) / div), 12); + dsty[x + i * ylinesize + 2] = av_clip_uintp2(y_min + ((y_diff * get_bits(&bit, nb_bits) + add) / div), 12); + dsty[x + i * ylinesize + 3] = av_clip_uintp2(y_min + ((y_diff * get_bits(&bit, nb_bits) + add) / div), 12); + } + } + + dsty += 4 * ylinesize; + } + + rgb = *gb; + dgb = *gb; + bytestream2_seek(gb, s->a_control_word_offset, SEEK_SET); + if (s->uv_count_offset == s->a_control_word_offset) { + for (int y = 0; y < avctx->height; y++) { + for (int x = 0; x < avctx->width; x++) + dsta[x] = 4095; + dsta += alinesize; + } + } else { + if (bytestream2_get_bytes_left(gb) < (avctx->height + 15) / 16 * ((avctx->width + 15) / 16) * 8) + return AVERROR_INVALIDDATA; + + for (int y = 0; y < avctx->height; y += 16) { + for (int x = 0; x < avctx->width; x += 16) { + unsigned m = bytestream2_get_le32(gb); + unsigned offset = bytestream2_get_le32(gb); + unsigned alpha0, alpha1; + uint64_t control; + + if (offset >= UINT_MAX / 4) + return AVERROR_INVALIDDATA; + offset = offset * 4 + s->uv_data_offset + s->a_data_offset; + if (offset >= s->data_end) + return AVERROR_INVALIDDATA; + + bytestream2_seek(&dgb, offset, SEEK_SET); + control = bytestream2_get_le64(&dgb); + alpha0 = control & 0xFF; + alpha1 = (control >> 8) & 0xFF; + control = control >> 16; + + for (int by = 0; by < 4; by++) { + for (int bx = 0; bx < 4; bx++) { + switch (m & 3) { + case 0: + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + dsta[x + (i + by * 4) * alinesize + bx * 4 + j] = 0; + } + } + break; + case 1: + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + dsta[x + (i + by * 4) * alinesize + bx * 4 + j] = 4095; + } + } + break; + case 2: + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + dsta[x + (i + by * 4) * alinesize + bx * 4 + j] = (alpha0 + (alpha1 - alpha0) * (control & 7)) << 4; + } + } + break; + default: + return AVERROR_INVALIDDATA; + } + + control >>= 3; + m >>= 2; + } + } + } + + dsta += 16 * alinesize; + } + } + + bytestream2_seek(&rgb, s->uv_offset_data_offset, SEEK_SET); + + dstu = (uint16_t *)p->data[1]; + dstv = (uint16_t *)p->data[2]; + ulinesize = p->linesize[1] / 2; + vlinesize = p->linesize[2] / 2; + + for (int y = 0; y < avctx->height; y += 16) { + for (int x = 0; x < avctx->width; x += 16) { + unsigned offset = bytestream2_get_le32(&rgb) * 4; + int u[16][16] = { 0 }, v[16][16] = { 0 }; + int u0, v0, u1, v1, udif, vdif; + unsigned escape, is8x8, loc; + + bytestream2_seek(&dgb, s->uv_data_offset + offset, SEEK_SET); + + is8x8 = bytestream2_get_le16(&dgb); + escape = bytestream2_get_le16(&dgb); + + if (escape == 0 && is8x8 == 0) { + u0 = bytestream2_get_byte(&dgb); + v0 = bytestream2_get_byte(&dgb); + u1 = bytestream2_get_byte(&dgb); + v1 = bytestream2_get_byte(&dgb); + loc = bytestream2_get_le32(&dgb); + u0 = (u0 << 4) | (u0 & 0xF); + v0 = (v0 << 4) | (v0 & 0xF); + u1 = (u1 << 4) | (u1 & 0xF); + v1 = (v1 << 4) | (v1 & 0xF); + udif = u1 - u0; + vdif = v1 - v0; + + for (int i = 0; i < 16; i += 4) { + for (int j = 0; j < 16; j += 4) { + for (int ii = 0; ii < 4; ii++) { + for (int jj = 0; jj < 4; jj++) { + u[i + ii][j + jj] = u0 + ((udif * (int)(loc & 3) + 2) / 3); + v[i + ii][j + jj] = v0 + ((vdif * (int)(loc & 3) + 2) / 3); + } + } + + loc >>= 2; + } + } + } else { + for (int i = 0; i < 16; i += 8) { + for (int j = 0; j < 16; j += 8) { + if (is8x8 & 1) { + u0 = bytestream2_get_byte(&dgb); + v0 = bytestream2_get_byte(&dgb); + u1 = bytestream2_get_byte(&dgb); + v1 = bytestream2_get_byte(&dgb); + loc = bytestream2_get_le32(&dgb); + u0 = (u0 << 4) | (u0 & 0xF); + v0 = (v0 << 4) | (v0 & 0xF); + u1 = (u1 << 4) | (u1 & 0xF); + v1 = (v1 << 4) | (v1 & 0xF); + udif = u1 - u0; + vdif = v1 - v0; + + for (int ii = 0; ii < 8; ii += 2) { + for (int jj = 0; jj < 8; jj += 2) { + for (int iii = 0; iii < 2; iii++) { + for (int jjj = 0; jjj < 2; jjj++) { + u[i + ii + iii][j + jj + jjj] = u0 + ((udif * (int)(loc & 3) + 2) / 3); + v[i + ii + iii][j + jj + jjj] = v0 + ((vdif * (int)(loc & 3) + 2) / 3); + } + } + + loc >>= 2; + } + } + } else if (escape) { + for (int ii = 0; ii < 8; ii += 4) { + for (int jj = 0; jj < 8; jj += 4) { + u0 = bytestream2_get_byte(&dgb); + v0 = bytestream2_get_byte(&dgb); + u1 = bytestream2_get_byte(&dgb); + v1 = bytestream2_get_byte(&dgb); + loc = bytestream2_get_le32(&dgb); + u0 = (u0 << 4) | (u0 & 0xF); + v0 = (v0 << 4) | (v0 & 0xF); + u1 = (u1 << 4) | (u1 & 0xF); + v1 = (v1 << 4) | (v1 & 0xF); + udif = u1 - u0; + vdif = v1 - v0; + + for (int iii = 0; iii < 4; iii++) { + for (int jjj = 0; jjj < 4; jjj++) { + u[i + ii + iii][j + jj + jjj] = u0 + ((udif * (int)(loc & 3) + 2) / 3); + v[i + ii + iii][j + jj + jjj] = v0 + ((vdif * (int)(loc & 3) + 2) / 3); + + loc >>= 2; + } + } + } + } + } + + is8x8 >>= 1; + } + } + } + + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + dstu[x + i * ulinesize + j] = u[i][j]; + dstv[x + i * vlinesize + j] = v[i][j]; + } + } + } + + dstu += 16 * ulinesize; + dstv += 16 * vlinesize; + } + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + NotchLCContext *s = avctx->priv_data; + ThreadFrame frame = { .f = data }; + GetByteContext *gb = &s->gb; + PutByteContext *pb = &s->pb; + unsigned uncompressed_size; + AVFrame *p = data; + int ret; + + if (avpkt->size <= 40) + return AVERROR_INVALIDDATA; + + bytestream2_init(gb, avpkt->data, avpkt->size); + + if (bytestream2_get_le32(gb) != MKBETAG('N','L','C','1')) + return AVERROR_INVALIDDATA; + + uncompressed_size = bytestream2_get_le32(gb); + s->compressed_size = bytestream2_get_le32(gb); + s->format = bytestream2_get_le32(gb); + + if (s->format > 2) + return AVERROR_PATCHWELCOME; + + if (s->format == 0) { + ret = ff_lzf_uncompress(gb, &s->lzf_buffer, &s->lzf_size); + if (ret < 0) + return ret; + + if (uncompressed_size > s->lzf_size) + return AVERROR_INVALIDDATA; + + bytestream2_init(gb, s->lzf_buffer, uncompressed_size); + } else if (s->format == 1) { + if (bytestream2_get_bytes_left(gb) < uncompressed_size / 255) + return AVERROR_INVALIDDATA; + + av_fast_padded_malloc(&s->uncompressed_buffer, &s->uncompressed_size, + uncompressed_size); + if (!s->uncompressed_buffer) + return AVERROR(ENOMEM); + + bytestream2_init_writer(pb, s->uncompressed_buffer, s->uncompressed_size); + + ret = lz4_decompress(avctx, gb, pb); + if (ret != uncompressed_size) + return AVERROR_INVALIDDATA; + + bytestream2_init(gb, s->uncompressed_buffer, uncompressed_size); + } + + ret = decode_blocks(avctx, p, &frame, uncompressed_size); + if (ret < 0) + return ret; + + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + NotchLCContext *s = avctx->priv_data; + + av_freep(&s->uncompressed_buffer); + s->uncompressed_size = 0; + av_freep(&s->lzf_buffer); + s->lzf_size = 0; + + return 0; +} + +AVCodec ff_notchlc_decoder = { + .name = "notchlc", + .long_name = NULL_IF_CONFIG_SMALL("NotchLC"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_NOTCHLC, + .priv_data_size = sizeof(NotchLCContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, +}; diff -Nru ffmpeg-4.2.2/libavcodec/null_bsf.c ffmpeg-4.4/libavcodec/null_bsf.c --- ffmpeg-4.2.2/libavcodec/null_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/null_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -21,15 +21,10 @@ * Null bitstream filter -- pass the input through unchanged. */ -#include "avcodec.h" #include "bsf.h" - -static int null_filter(AVBSFContext *ctx, AVPacket *pkt) -{ - return ff_bsf_get_packet_ref(ctx, pkt); -} +#include "bsf_internal.h" const AVBitStreamFilter ff_null_bsf = { .name = "null", - .filter = null_filter, + .filter = ff_bsf_get_packet_ref, }; diff -Nru ffmpeg-4.2.2/libavcodec/nuv.c ffmpeg-4.4/libavcodec/nuv.c --- ffmpeg-4.2.2/libavcodec/nuv.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/nuv.c 2020-07-11 10:39:30.000000000 +0000 @@ -126,7 +126,7 @@ get_quant_quality(c, quality); if (width != c->width || height != c->height) { // also reserve space for a possible additional header - int buf_size = height * width * 3 / 2 + int64_t buf_size = height * (int64_t)width * 3 / 2 + FFMAX(AV_LZO_OUTPUT_PADDING, AV_INPUT_BUFFER_PADDING_SIZE) + RTJPEG_HEADER_SIZE; if (buf_size > INT_MAX/8) @@ -162,6 +162,7 @@ int keyframe, ret; int size_change = 0; int minsize = 0; + int flags = 0; int result, init_frame = !avctx->frame_number; enum { NUV_UNCOMPRESSED = '0', @@ -204,6 +205,7 @@ } break; case NUV_COPY_LAST: + flags |= FF_REGET_BUFFER_FLAG_READONLY; keyframe = 0; break; default: @@ -276,7 +278,7 @@ init_frame = 1; } - if ((result = ff_reget_buffer(avctx, c->pic)) < 0) + if ((result = ff_reget_buffer(avctx, c->pic, flags)) < 0) return result; if (init_frame) { memset(c->pic->data[0], 0, avctx->height * c->pic->linesize[0]); diff -Nru ffmpeg-4.2.2/libavcodec/nvdec_av1.c ffmpeg-4.4/libavcodec/nvdec_av1.c --- ffmpeg-4.2.2/libavcodec/nvdec_av1.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/nvdec_av1.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,352 @@ +/* + * AV1 HW decode acceleration through NVDEC + * + * Copyright (c) 2020 Timo Rothenpieler + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "nvdec.h" +#include "decode.h" +#include "internal.h" +#include "av1dec.h" + + +static int get_bit_depth_from_seq(const AV1RawSequenceHeader *seq) +{ + if (seq->seq_profile == 2 && seq->color_config.high_bitdepth) + return seq->color_config.twelve_bit ? 12 : 10; + else if (seq->seq_profile <= 2 && seq->color_config.high_bitdepth) + return 10; + else + return 8; +} + +static int nvdec_av1_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + const AV1DecContext *s = avctx->priv_data; + const AV1RawSequenceHeader *seq = s->raw_seq; + const AV1RawFrameHeader *frame_header = s->raw_frame_header; + const AV1RawFilmGrainParams *film_grain = &s->cur_frame.film_grain; + + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + CUVIDPICPARAMS *pp = &ctx->pic_params; + CUVIDAV1PICPARAMS *ppc = &pp->CodecSpecific.av1; + FrameDecodeData *fdd; + NVDECFrame *cf; + AVFrame *cur_frame = s->cur_frame.tf.f; + + unsigned char remap_lr_type[4] = { AV1_RESTORE_NONE, AV1_RESTORE_SWITCHABLE, AV1_RESTORE_WIENER, AV1_RESTORE_SGRPROJ }; + + int apply_grain = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && film_grain->apply_grain; + int ret, i, j; + + ret = ff_nvdec_start_frame_sep_ref(avctx, cur_frame, apply_grain); + if (ret < 0) + return ret; + + fdd = (FrameDecodeData*)cur_frame->private_ref->data; + cf = (NVDECFrame*)fdd->hwaccel_priv; + + *pp = (CUVIDPICPARAMS) { + .PicWidthInMbs = (cur_frame->width + 15) / 16, + .FrameHeightInMbs = (cur_frame->height + 15) / 16, + .CurrPicIdx = cf->idx, + .ref_pic_flag = !!frame_header->refresh_frame_flags, + .intra_pic_flag = frame_header->frame_type == AV1_FRAME_INTRA_ONLY || + frame_header->frame_type == AV1_FRAME_KEY, + + .CodecSpecific.av1 = { + .width = cur_frame->width, + .height = cur_frame->height, + + .frame_offset = frame_header->order_hint, + .decodePicIdx = cf->ref_idx, + + /* Sequence Header */ + .profile = seq->seq_profile, + .use_128x128_superblock = seq->use_128x128_superblock, + .subsampling_x = seq->color_config.subsampling_x, + .subsampling_y = seq->color_config.subsampling_y, + .mono_chrome = seq->color_config.mono_chrome, + .bit_depth_minus8 = get_bit_depth_from_seq(seq) - 8, + .enable_filter_intra = seq->enable_filter_intra, + .enable_intra_edge_filter = seq->enable_intra_edge_filter, + .enable_interintra_compound = seq->enable_interintra_compound, + .enable_masked_compound = seq->enable_masked_compound, + .enable_dual_filter = seq->enable_dual_filter, + .enable_order_hint = seq->enable_order_hint, + .order_hint_bits_minus1 = seq->order_hint_bits_minus_1, + .enable_jnt_comp = seq->enable_jnt_comp, + .enable_superres = seq->enable_superres, + .enable_cdef = seq->enable_cdef, + .enable_restoration = seq->enable_restoration, + .enable_fgs = seq->film_grain_params_present && + !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN), + + /* Frame Header */ + .frame_type = frame_header->frame_type, + .show_frame = frame_header->show_frame, + .disable_cdf_update = frame_header->disable_cdf_update, + .allow_screen_content_tools = frame_header->allow_screen_content_tools, + .force_integer_mv = frame_header->force_integer_mv || + frame_header->frame_type == AV1_FRAME_INTRA_ONLY || + frame_header->frame_type == AV1_FRAME_KEY, + .coded_denom = frame_header->coded_denom, + .allow_intrabc = frame_header->allow_intrabc, + .allow_high_precision_mv = frame_header->allow_high_precision_mv, + .interp_filter = frame_header->interpolation_filter, + .switchable_motion_mode = frame_header->is_motion_mode_switchable, + .use_ref_frame_mvs = frame_header->use_ref_frame_mvs, + .disable_frame_end_update_cdf = frame_header->disable_frame_end_update_cdf, + .delta_q_present = frame_header->delta_q_present, + .delta_q_res = frame_header->delta_q_res, + .using_qmatrix = frame_header->using_qmatrix, + .coded_lossless = s->cur_frame.coded_lossless, + .use_superres = frame_header->use_superres, + .tx_mode = frame_header->tx_mode, + .reference_mode = frame_header->reference_select, + .allow_warped_motion = frame_header->allow_warped_motion, + .reduced_tx_set = frame_header->reduced_tx_set, + .skip_mode = frame_header->skip_mode_present, + + /* Tiling Info */ + .num_tile_cols = frame_header->tile_cols, + .num_tile_rows = frame_header->tile_rows, + .context_update_tile_id = frame_header->context_update_tile_id, + + /* CDEF */ + .cdef_damping_minus_3 = frame_header->cdef_damping_minus_3, + .cdef_bits = frame_header->cdef_bits, + + /* SkipModeFrames */ + .SkipModeFrame0 = frame_header->skip_mode_present ? + s->cur_frame.skip_mode_frame_idx[0] : 0, + .SkipModeFrame1 = frame_header->skip_mode_present ? + s->cur_frame.skip_mode_frame_idx[1] : 0, + + /* QP Information */ + .base_qindex = frame_header->base_q_idx, + .qp_y_dc_delta_q = frame_header->delta_q_y_dc, + .qp_u_dc_delta_q = frame_header->delta_q_u_dc, + .qp_v_dc_delta_q = frame_header->delta_q_v_dc, + .qp_u_ac_delta_q = frame_header->delta_q_u_ac, + .qp_v_ac_delta_q = frame_header->delta_q_v_ac, + .qm_y = frame_header->qm_y, + .qm_u = frame_header->qm_u, + .qm_v = frame_header->qm_v, + + /* Segmentation */ + .segmentation_enabled = frame_header->segmentation_enabled, + .segmentation_update_map = frame_header->segmentation_update_map, + .segmentation_update_data = frame_header->segmentation_update_data, + .segmentation_temporal_update = frame_header->segmentation_temporal_update, + + /* Loopfilter */ + .loop_filter_level[0] = frame_header->loop_filter_level[0], + .loop_filter_level[1] = frame_header->loop_filter_level[1], + .loop_filter_level_u = frame_header->loop_filter_level[2], + .loop_filter_level_v = frame_header->loop_filter_level[3], + .loop_filter_sharpness = frame_header->loop_filter_sharpness, + .loop_filter_delta_enabled = frame_header->loop_filter_delta_enabled, + .loop_filter_delta_update = frame_header->loop_filter_delta_update, + .loop_filter_mode_deltas[0] = frame_header->loop_filter_mode_deltas[0], + .loop_filter_mode_deltas[1] = frame_header->loop_filter_mode_deltas[1], + .delta_lf_present = frame_header->delta_lf_present, + .delta_lf_res = frame_header->delta_lf_res, + .delta_lf_multi = frame_header->delta_lf_multi, + + /* Restoration */ + .lr_type[0] = remap_lr_type[frame_header->lr_type[0]], + .lr_type[1] = remap_lr_type[frame_header->lr_type[1]], + .lr_type[2] = remap_lr_type[frame_header->lr_type[2]], + .lr_unit_size[0] = 1 + frame_header->lr_unit_shift, + .lr_unit_size[1] = 1 + frame_header->lr_unit_shift - frame_header->lr_uv_shift, + .lr_unit_size[2] = 1 + frame_header->lr_unit_shift - frame_header->lr_uv_shift, + + /* Reference Frames */ + .temporal_layer_id = s->cur_frame.temporal_id, + .spatial_layer_id = s->cur_frame.spatial_id, + + /* Film Grain Params */ + .apply_grain = apply_grain, + .overlap_flag = film_grain->overlap_flag, + .scaling_shift_minus8 = film_grain->grain_scaling_minus_8, + .chroma_scaling_from_luma = film_grain->chroma_scaling_from_luma, + .ar_coeff_lag = film_grain->ar_coeff_lag, + .ar_coeff_shift_minus6 = film_grain->ar_coeff_shift_minus_6, + .grain_scale_shift = film_grain->grain_scale_shift, + .clip_to_restricted_range = film_grain->clip_to_restricted_range, + .num_y_points = film_grain->num_y_points, + .num_cb_points = film_grain->num_cb_points, + .num_cr_points = film_grain->num_cr_points, + .random_seed = film_grain->grain_seed, + .cb_mult = film_grain->cb_mult, + .cb_luma_mult = film_grain->cb_luma_mult, + .cb_offset = film_grain->cb_offset, + .cr_mult = film_grain->cr_mult, + .cr_luma_mult = film_grain->cr_luma_mult, + .cr_offset = film_grain->cr_offset + } + }; + + /* Tiling Info */ + for (i = 0; i < frame_header->tile_cols; ++i) { + ppc->tile_widths[i] = frame_header->width_in_sbs_minus_1[i] + 1; + } + for (i = 0; i < frame_header->tile_rows; ++i) { + ppc->tile_heights[i] = frame_header->height_in_sbs_minus_1[i] + 1; + } + + /* CDEF */ + for (i = 0; i < (1 << frame_header->cdef_bits); ++i) { + ppc->cdef_y_strength[i] = (frame_header->cdef_y_pri_strength[i] & 0x0F) | (frame_header->cdef_y_sec_strength[i] << 4); + ppc->cdef_uv_strength[i] = (frame_header->cdef_uv_pri_strength[i] & 0x0F) | (frame_header->cdef_uv_sec_strength[i] << 4); + } + + /* Segmentation */ + for (i = 0; i < AV1_MAX_SEGMENTS; ++i) { + ppc->segmentation_feature_mask[i] = 0; + for (j = 0; j < AV1_SEG_LVL_MAX; ++j) { + ppc->segmentation_feature_mask[i] |= frame_header->feature_enabled[i][j] << j; + ppc->segmentation_feature_data[i][j] = frame_header->feature_value[i][j]; + } + } + + for (i = 0; i < AV1_NUM_REF_FRAMES; ++i) { + /* Loopfilter */ + ppc->loop_filter_ref_deltas[i] = frame_header->loop_filter_ref_deltas[i]; + + /* Reference Frames */ + ppc->ref_frame_map[i] = ff_nvdec_get_ref_idx(s->ref[i].tf.f); + } + + if (frame_header->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + ppc->primary_ref_frame = -1; + } else { + int8_t pri_ref_idx = frame_header->ref_frame_idx[frame_header->primary_ref_frame]; + ppc->primary_ref_frame = ppc->ref_frame_map[pri_ref_idx]; + } + + for (i = 0; i < AV1_REFS_PER_FRAME; ++i) { + /* Ref Frame List */ + int8_t ref_idx = frame_header->ref_frame_idx[i]; + AVFrame *ref_frame = s->ref[ref_idx].tf.f; + + ppc->ref_frame[i].index = ppc->ref_frame_map[ref_idx]; + ppc->ref_frame[i].width = ref_frame->width; + ppc->ref_frame[i].height = ref_frame->height; + + /* Global Motion */ + ppc->global_motion[i].invalid = !frame_header->is_global[AV1_REF_FRAME_LAST + i]; + ppc->global_motion[i].wmtype = s->cur_frame.gm_type[AV1_REF_FRAME_LAST + i]; + for (j = 0; j < 6; ++j) { + ppc->global_motion[i].wmmat[j] = s->cur_frame.gm_params[AV1_REF_FRAME_LAST + i][j]; + } + } + + /* Film Grain Params */ + if (apply_grain) { + for (i = 0; i < 14; ++i) { + ppc->scaling_points_y[i][0] = film_grain->point_y_value[i]; + ppc->scaling_points_y[i][1] = film_grain->point_y_scaling[i]; + } + for (i = 0; i < 10; ++i) { + ppc->scaling_points_cb[i][0] = film_grain->point_cb_value[i]; + ppc->scaling_points_cb[i][1] = film_grain->point_cb_scaling[i]; + ppc->scaling_points_cr[i][0] = film_grain->point_cr_value[i]; + ppc->scaling_points_cr[i][1] = film_grain->point_cr_scaling[i]; + } + for (i = 0; i < 24; ++i) { + ppc->ar_coeffs_y[i] = (short)film_grain->ar_coeffs_y_plus_128[i] - 128; + } + for (i = 0; i < 25; ++i) { + ppc->ar_coeffs_cb[i] = (short)film_grain->ar_coeffs_cb_plus_128[i] - 128; + ppc->ar_coeffs_cr[i] = (short)film_grain->ar_coeffs_cr_plus_128[i] - 128; + } + } + + return 0; +} + +static int nvdec_av1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + const AV1DecContext *s = avctx->priv_data; + const AV1RawFrameHeader *frame_header = s->raw_frame_header; + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + void *tmp; + + ctx->nb_slices = frame_header->tile_cols * frame_header->tile_rows; + + tmp = av_fast_realloc(ctx->slice_offsets, &ctx->slice_offsets_allocated, + ctx->nb_slices * 2 * sizeof(*ctx->slice_offsets)); + if (!tmp) { + return AVERROR(ENOMEM); + } + ctx->slice_offsets = tmp; + + /* Shortcut if all tiles are in the same buffer */ + if (ctx->nb_slices == s->tg_end - s->tg_start + 1) { + ctx->bitstream = (uint8_t*)buffer; + ctx->bitstream_len = size; + + for (int i = 0; i < ctx->nb_slices; ++i) { + ctx->slice_offsets[i*2 ] = s->tile_group_info[i].tile_offset; + ctx->slice_offsets[i*2 + 1] = ctx->slice_offsets[i*2] + s->tile_group_info[i].tile_size; + } + + return 0; + } + + tmp = av_fast_realloc(ctx->bitstream_internal, &ctx->bitstream_allocated, + ctx->bitstream_len + size); + if (!tmp) { + return AVERROR(ENOMEM); + } + ctx->bitstream = ctx->bitstream_internal = tmp; + + memcpy(ctx->bitstream + ctx->bitstream_len, buffer, size); + + for (uint32_t tile_num = s->tg_start; tile_num <= s->tg_end; ++tile_num) { + ctx->slice_offsets[tile_num*2 ] = ctx->bitstream_len + s->tile_group_info[tile_num].tile_offset; + ctx->slice_offsets[tile_num*2 + 1] = ctx->slice_offsets[tile_num*2] + s->tile_group_info[tile_num].tile_size; + } + ctx->bitstream_len += size; + + return 0; +} + +static int nvdec_av1_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx) +{ + /* Maximum of 8 reference frames, but potentially stored twice due to film grain */ + return ff_nvdec_frame_params(avctx, hw_frames_ctx, 8 * 2, 0); +} + +const AVHWAccel ff_av1_nvdec_hwaccel = { + .name = "av1_nvdec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .pix_fmt = AV_PIX_FMT_CUDA, + .start_frame = nvdec_av1_start_frame, + .end_frame = ff_nvdec_simple_end_frame, + .decode_slice = nvdec_av1_decode_slice, + .frame_params = nvdec_av1_frame_params, + .init = ff_nvdec_decode_init, + .uninit = ff_nvdec_decode_uninit, + .priv_data_size = sizeof(NVDECContext), +}; diff -Nru ffmpeg-4.2.2/libavcodec/nvdec.c ffmpeg-4.4/libavcodec/nvdec.c --- ffmpeg-4.2.2/libavcodec/nvdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/nvdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -44,6 +44,7 @@ CUvideodecoder decoder; AVBufferRef *hw_device_ref; + AVBufferRef *real_hw_frames_ref; CUcontext cuda_ctx; CUstream stream; @@ -61,6 +62,9 @@ static int map_avcodec_id(enum AVCodecID id) { switch (id) { +#if CONFIG_AV1_NVDEC_HWACCEL + case AV_CODEC_ID_AV1: return cudaVideoCodec_AV1; +#endif case AV_CODEC_ID_H264: return cudaVideoCodec_H264; case AV_CODEC_ID_HEVC: return cudaVideoCodec_HEVC; case AV_CODEC_ID_MJPEG: return cudaVideoCodec_JPEG; @@ -79,6 +83,9 @@ { int shift_h = 0, shift_v = 0; + if (av_pix_fmt_count_planes(pix_fmt) == 1) + return cudaVideoChromaFormat_Monochrome; + av_pix_fmt_get_chroma_sub_sample(pix_fmt, &shift_h, &shift_v); if (shift_h == 1 && shift_v == 1) @@ -163,6 +170,7 @@ CHECK_CU(decoder->cudl->cuCtxPopCurrent(&dummy)); } + av_buffer_unref(&decoder->real_hw_frames_ref); av_buffer_unref(&decoder->hw_device_ref); cuvid_free_functions(&decoder->cvdl); @@ -234,7 +242,7 @@ return ret; } -static AVBufferRef *nvdec_decoder_frame_alloc(void *opaque, int size) +static AVBufferRef *nvdec_decoder_frame_alloc(void *opaque, buffer_size_t size) { NVDECFramePool *pool = opaque; AVBufferRef *ret; @@ -256,6 +264,7 @@ NVDECContext *ctx = avctx->internal->hwaccel_priv_data; av_freep(&ctx->bitstream); + av_freep(&ctx->bitstream_internal); ctx->bitstream_len = 0; ctx->bitstream_allocated = 0; @@ -269,10 +278,61 @@ return 0; } +static void nvdec_free_dummy(struct AVHWFramesContext *ctx) +{ + av_buffer_pool_uninit(&ctx->pool); +} + +static AVBufferRef *nvdec_alloc_dummy(buffer_size_t size) +{ + return av_buffer_create(NULL, 0, NULL, NULL, 0); +} + +static int nvdec_init_hwframes(AVCodecContext *avctx, AVBufferRef **out_frames_ref, int dummy) +{ + AVHWFramesContext *frames_ctx; + int ret; + + ret = avcodec_get_hw_frames_parameters(avctx, + avctx->hw_device_ctx, + avctx->hwaccel->pix_fmt, + out_frames_ref); + if (ret < 0) + return ret; + + frames_ctx = (AVHWFramesContext*)(*out_frames_ref)->data; + + if (dummy) { + // Copied from ff_decode_get_hw_frames_ctx for compatibility + frames_ctx->initial_pool_size += 3; + + frames_ctx->free = nvdec_free_dummy; + frames_ctx->pool = av_buffer_pool_init(0, nvdec_alloc_dummy); + + if (!frames_ctx->pool) { + av_buffer_unref(out_frames_ref); + return AVERROR(ENOMEM); + } + } else { + // This is normally not used to actually allocate frames from + frames_ctx->initial_pool_size = 0; + } + + ret = av_hwframe_ctx_init(*out_frames_ref); + if (ret < 0) { + av_buffer_unref(out_frames_ref); + return ret; + } + + return 0; +} + int ff_nvdec_decode_init(AVCodecContext *avctx) { NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + NVDECDecoder *decoder; + AVBufferRef *real_hw_frames_ref; NVDECFramePool *pool; AVHWFramesContext *frames_ctx; const AVPixFmtDescriptor *sw_desc; @@ -301,9 +361,17 @@ chroma_444 = ctx->supports_444 && cuvid_chroma_format == cudaVideoChromaFormat_444; if (!avctx->hw_frames_ctx) { - ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_CUDA); + ret = nvdec_init_hwframes(avctx, &avctx->hw_frames_ctx, 1); + if (ret < 0) + return ret; + + ret = nvdec_init_hwframes(avctx, &real_hw_frames_ref, 0); if (ret < 0) return ret; + } else { + real_hw_frames_ref = av_buffer_ref(avctx->hw_frames_ctx); + if (!real_hw_frames_ref) + return AVERROR(ENOMEM); } switch (sw_desc->comp[0].depth) { @@ -318,6 +386,7 @@ break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth\n"); + av_buffer_unref(&real_hw_frames_ref); return AVERROR(ENOSYS); } @@ -342,9 +411,14 @@ av_log(avctx, AV_LOG_WARNING, "Try lowering the amount of threads. Using %d right now.\n", avctx->thread_count); } + av_buffer_unref(&real_hw_frames_ref); return ret; } + decoder = (NVDECDecoder*)ctx->decoder_ref->data; + decoder->real_hw_frames_ref = real_hw_frames_ref; + real_hw_frames_ref = NULL; + pool = av_mallocz(sizeof(*pool)); if (!pool) { ret = AVERROR(ENOMEM); @@ -374,6 +448,7 @@ av_buffer_unref(&cf->idx_ref); av_buffer_unref(&cf->decoder_ref); + av_buffer_unref(&cf->ref_idx_ref); av_freep(&priv); } @@ -398,6 +473,7 @@ finish: av_buffer_unref(&unmap_data->idx_ref); av_buffer_unref(&unmap_data->decoder_ref); + av_buffer_unref(&unmap_data->ref_idx_ref); av_free(unmap_data); } @@ -447,6 +523,13 @@ goto copy_fail; } + av_buffer_unref(&frame->hw_frames_ctx); + frame->hw_frames_ctx = av_buffer_ref(decoder->real_hw_frames_ref); + if (!frame->hw_frames_ctx) { + ret = AVERROR(ENOMEM); + goto copy_fail; + } + unmap_data->idx = cf->idx; unmap_data->idx_ref = av_buffer_ref(cf->idx_ref); unmap_data->decoder_ref = av_buffer_ref(cf->decoder_ref); @@ -502,7 +585,7 @@ ret = AVERROR(ENOMEM); goto fail; } - cf->idx = *(unsigned int*)cf->idx_ref->data; + cf->ref_idx = cf->idx = *(unsigned int*)cf->idx_ref->data; fdd->hwaccel_priv = cf; fdd->hwaccel_priv_free = nvdec_fdd_priv_free; @@ -515,6 +598,40 @@ } +int ff_nvdec_start_frame_sep_ref(AVCodecContext *avctx, AVFrame *frame, int has_sep_ref) +{ + NVDECContext *ctx = avctx->internal->hwaccel_priv_data; + FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data; + NVDECFrame *cf; + int ret; + + ret = ff_nvdec_start_frame(avctx, frame); + if (ret < 0) + return ret; + + cf = fdd->hwaccel_priv; + + if (has_sep_ref) { + if (!cf->ref_idx_ref) { + cf->ref_idx_ref = av_buffer_pool_get(ctx->decoder_pool); + if (!cf->ref_idx_ref) { + av_log(avctx, AV_LOG_ERROR, "No decoder surfaces left\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + } + cf->ref_idx = *(unsigned int*)cf->ref_idx_ref->data; + } else { + av_buffer_unref(&cf->ref_idx_ref); + cf->ref_idx = cf->idx; + } + + return 0; +fail: + nvdec_fdd_priv_free(cf); + return ret; +} + int ff_nvdec_end_frame(AVCodecContext *avctx) { NVDECContext *ctx = avctx->internal->hwaccel_priv_data; @@ -575,16 +692,6 @@ return 0; } -static void nvdec_free_dummy(struct AVHWFramesContext *ctx) -{ - av_buffer_pool_uninit(&ctx->pool); -} - -static AVBufferRef *nvdec_alloc_dummy(int size) -{ - return av_buffer_create(NULL, 0, NULL, NULL, 0); -} - int ff_nvdec_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx, int dpb_size, @@ -620,12 +727,6 @@ */ frames_ctx->initial_pool_size = dpb_size + 2; - frames_ctx->free = nvdec_free_dummy; - frames_ctx->pool = av_buffer_pool_init(0, nvdec_alloc_dummy); - - if (!frames_ctx->pool) - return AVERROR(ENOMEM); - switch (sw_desc->comp[0].depth) { case 8: frames_ctx->sw_format = chroma_444 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_NV12; @@ -656,5 +757,5 @@ if (!cf) return -1; - return cf->idx; + return cf->ref_idx; } diff -Nru ffmpeg-4.2.2/libavcodec/nvdec.h ffmpeg-4.4/libavcodec/nvdec.h --- ffmpeg-4.2.2/libavcodec/nvdec.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/nvdec.h 2021-04-08 21:28:39.000000000 +0000 @@ -43,7 +43,9 @@ typedef struct NVDECFrame { unsigned int idx; + unsigned int ref_idx; AVBufferRef *idx_ref; + AVBufferRef *ref_idx_ref; AVBufferRef *decoder_ref; } NVDECFrame; @@ -57,6 +59,7 @@ uint8_t *bitstream; int bitstream_len; unsigned int bitstream_allocated; + uint8_t *bitstream_internal; unsigned *slice_offsets; int nb_slices; @@ -68,6 +71,7 @@ int ff_nvdec_decode_init(AVCodecContext *avctx); int ff_nvdec_decode_uninit(AVCodecContext *avctx); int ff_nvdec_start_frame(AVCodecContext *avctx, AVFrame *frame); +int ff_nvdec_start_frame_sep_ref(AVCodecContext *avctx, AVFrame *frame, int has_sep_ref); int ff_nvdec_end_frame(AVCodecContext *avctx); int ff_nvdec_simple_end_frame(AVCodecContext *avctx); int ff_nvdec_simple_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, diff -Nru ffmpeg-4.2.2/libavcodec/nvdec_mpeg12.c ffmpeg-4.4/libavcodec/nvdec_mpeg12.c --- ffmpeg-4.2.2/libavcodec/nvdec_mpeg12.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/nvdec_mpeg12.c 2020-07-11 10:39:30.000000000 +0000 @@ -50,6 +50,10 @@ .FrameHeightInMbs = (cur_frame->height + 15) / 16, .CurrPicIdx = cf->idx, + .field_pic_flag = s->picture_structure != PICT_FRAME, + .bottom_field_flag = s->picture_structure == PICT_BOTTOM_FIELD, + .second_field = s->picture_structure != PICT_FRAME && !s->first_field, + .intra_pic_flag = s->pict_type == AV_PICTURE_TYPE_I, .ref_pic_flag = s->pict_type == AV_PICTURE_TYPE_I || s->pict_type == AV_PICTURE_TYPE_P, diff -Nru ffmpeg-4.2.2/libavcodec/nvenc.c ffmpeg-4.4/libavcodec/nvenc.c --- ffmpeg-4.2.2/libavcodec/nvenc.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/nvenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "config.h" #include "nvenc.h" +#include "hevc_sei.h" #include "libavutil/hwcontext_cuda.h" #include "libavutil/hwcontext.h" @@ -30,7 +31,10 @@ #include "libavutil/avassert.h" #include "libavutil/mem.h" #include "libavutil/pixdesc.h" +#include "atsc_a53.h" +#include "encode.h" #include "internal.h" +#include "packet_internal.h" #define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, dl_fn->cuda_dl, x) @@ -55,6 +59,16 @@ AV_PIX_FMT_NONE }; +const AVCodecHWConfigInternal *const ff_nvenc_hw_configs[] = { + HW_CONFIG_ENCODER_FRAMES(CUDA, CUDA), + HW_CONFIG_ENCODER_DEVICE(NONE, CUDA), +#if CONFIG_D3D11VA + HW_CONFIG_ENCODER_FRAMES(D3D11, D3D11VA), + HW_CONFIG_ENCODER_DEVICE(NONE, D3D11VA), +#endif + NULL, +}; + #define IS_10BIT(pix_fmt) (pix_fmt == AV_PIX_FMT_P010 || \ pix_fmt == AV_PIX_FMT_P016 || \ pix_fmt == AV_PIX_FMT_YUV444P16) @@ -110,20 +124,42 @@ return AVERROR_UNKNOWN; } -static int nvenc_print_error(void *log_ctx, NVENCSTATUS err, +static int nvenc_print_error(AVCodecContext *avctx, NVENCSTATUS err, const char *error_string) { const char *desc; - int ret; - ret = nvenc_map_error(err, &desc); - av_log(log_ctx, AV_LOG_ERROR, "%s: %s (%d)\n", error_string, desc, err); + const char *details = "(no details)"; + int ret = nvenc_map_error(err, &desc); + +#ifdef NVENC_HAVE_GETLASTERRORSTRING + NvencContext *ctx = avctx->priv_data; + NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs; + + if (p_nvenc && ctx->nvencoder) + details = p_nvenc->nvEncGetLastErrorString(ctx->nvencoder); +#endif + + av_log(avctx, AV_LOG_ERROR, "%s: %s (%d): %s\n", error_string, desc, err, details); + return ret; } static void nvenc_print_driver_requirement(AVCodecContext *avctx, int level) { -#if NVENCAPI_CHECK_VERSION(9, 2) +#if NVENCAPI_CHECK_VERSION(11, 1) const char *minver = "(unknown)"; +#elif NVENCAPI_CHECK_VERSION(11, 0) +# if defined(_WIN32) || defined(__CYGWIN__) + const char *minver = "456.71"; +# else + const char *minver = "455.28"; +# endif +#elif NVENCAPI_CHECK_VERSION(10, 0) +# if defined(_WIN32) || defined(__CYGWIN__) + const char *minver = "450.51"; +# else + const char *minver = "445.87"; +# endif #elif NVENCAPI_CHECK_VERSION(9, 1) # if defined(_WIN32) || defined(__CYGWIN__) const char *minver = "436.15"; @@ -311,39 +347,39 @@ ret = nvenc_check_codec_support(avctx); if (ret < 0) { - av_log(avctx, AV_LOG_VERBOSE, "Codec not supported\n"); + av_log(avctx, AV_LOG_WARNING, "Codec not supported\n"); return ret; } ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_YUV444_ENCODE); if (IS_YUV444(ctx->data_pix_fmt) && ret <= 0) { - av_log(avctx, AV_LOG_VERBOSE, "YUV444P not supported\n"); + av_log(avctx, AV_LOG_WARNING, "YUV444P not supported\n"); return AVERROR(ENOSYS); } ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE); if (ctx->preset >= PRESET_LOSSLESS_DEFAULT && ret <= 0) { - av_log(avctx, AV_LOG_VERBOSE, "Lossless encoding not supported\n"); + av_log(avctx, AV_LOG_WARNING, "Lossless encoding not supported\n"); return AVERROR(ENOSYS); } ret = nvenc_check_cap(avctx, NV_ENC_CAPS_WIDTH_MAX); if (ret < avctx->width) { - av_log(avctx, AV_LOG_VERBOSE, "Width %d exceeds %d\n", + av_log(avctx, AV_LOG_WARNING, "Width %d exceeds %d\n", avctx->width, ret); return AVERROR(ENOSYS); } ret = nvenc_check_cap(avctx, NV_ENC_CAPS_HEIGHT_MAX); if (ret < avctx->height) { - av_log(avctx, AV_LOG_VERBOSE, "Height %d exceeds %d\n", + av_log(avctx, AV_LOG_WARNING, "Height %d exceeds %d\n", avctx->height, ret); return AVERROR(ENOSYS); } ret = nvenc_check_cap(avctx, NV_ENC_CAPS_NUM_MAX_BFRAMES); if (ret < avctx->max_b_frames) { - av_log(avctx, AV_LOG_VERBOSE, "Max B-frames %d exceed %d\n", + av_log(avctx, AV_LOG_WARNING, "Max B-frames %d exceed %d\n", avctx->max_b_frames, ret); return AVERROR(ENOSYS); @@ -351,7 +387,7 @@ ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_FIELD_ENCODING); if (ret < 1 && avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { - av_log(avctx, AV_LOG_VERBOSE, + av_log(avctx, AV_LOG_WARNING, "Interlaced encoding is not supported. Supported level: %d\n", ret); return AVERROR(ENOSYS); @@ -359,46 +395,59 @@ ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_10BIT_ENCODE); if (IS_10BIT(ctx->data_pix_fmt) && ret <= 0) { - av_log(avctx, AV_LOG_VERBOSE, "10 bit encode not supported\n"); + av_log(avctx, AV_LOG_WARNING, "10 bit encode not supported\n"); return AVERROR(ENOSYS); } ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOOKAHEAD); if (ctx->rc_lookahead > 0 && ret <= 0) { - av_log(avctx, AV_LOG_VERBOSE, "RC lookahead not supported\n"); + av_log(avctx, AV_LOG_WARNING, "RC lookahead not supported\n"); return AVERROR(ENOSYS); } ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_TEMPORAL_AQ); if (ctx->temporal_aq > 0 && ret <= 0) { - av_log(avctx, AV_LOG_VERBOSE, "Temporal AQ not supported\n"); + av_log(avctx, AV_LOG_WARNING, "Temporal AQ not supported\n"); return AVERROR(ENOSYS); } ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_WEIGHTED_PREDICTION); if (ctx->weighted_pred > 0 && ret <= 0) { - av_log (avctx, AV_LOG_VERBOSE, "Weighted Prediction not supported\n"); + av_log (avctx, AV_LOG_WARNING, "Weighted Prediction not supported\n"); return AVERROR(ENOSYS); } ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_CABAC); if (ctx->coder == NV_ENC_H264_ENTROPY_CODING_MODE_CABAC && ret <= 0) { - av_log(avctx, AV_LOG_VERBOSE, "CABAC entropy coding not supported\n"); + av_log(avctx, AV_LOG_WARNING, "CABAC entropy coding not supported\n"); return AVERROR(ENOSYS); } #ifdef NVENC_HAVE_BFRAME_REF_MODE ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_BFRAME_REF_MODE); - if (ctx->b_ref_mode == NV_ENC_BFRAME_REF_MODE_EACH && ret != 1) { - av_log(avctx, AV_LOG_VERBOSE, "Each B frame as reference is not supported\n"); + if (ctx->b_ref_mode == NV_ENC_BFRAME_REF_MODE_EACH && ret != 1 && ret != 3) { + av_log(avctx, AV_LOG_WARNING, "Each B frame as reference is not supported\n"); return AVERROR(ENOSYS); } else if (ctx->b_ref_mode != NV_ENC_BFRAME_REF_MODE_DISABLED && ret == 0) { - av_log(avctx, AV_LOG_VERBOSE, "B frames as references are not supported\n"); + av_log(avctx, AV_LOG_WARNING, "B frames as references are not supported\n"); return AVERROR(ENOSYS); } #else if (ctx->b_ref_mode != 0) { - av_log(avctx, AV_LOG_VERBOSE, "B frames as references need SDK 8.1 at build time\n"); + av_log(avctx, AV_LOG_WARNING, "B frames as references need SDK 8.1 at build time\n"); + return AVERROR(ENOSYS); + } +#endif + +#ifdef NVENC_HAVE_MULTIPLE_REF_FRAMES + ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_MULTIPLE_REF_FRAMES); + if(avctx->refs != NV_ENC_NUM_REF_FRAMES_AUTOSELECT && ret <= 0) { + av_log(avctx, AV_LOG_WARNING, "Multiple reference frames are not supported by the device\n"); + return AVERROR(ENOSYS); + } +#else + if(avctx->refs != 0) { + av_log(avctx, AV_LOG_WARNING, "Multiple reference frames need SDK 9.1 at build time\n"); return AVERROR(ENOSYS); } #endif @@ -447,6 +496,7 @@ goto fail; ctx->cu_context = ctx->cu_context_internal; + ctx->cu_stream = NULL; if ((ret = nvenc_pop_context(avctx)) < 0) goto fail2; @@ -533,6 +583,7 @@ if (cuda_device_hwctx) { ctx->cu_context = cuda_device_hwctx->cuda_ctx; + ctx->cu_stream = cuda_device_hwctx->stream; } #if CONFIG_D3D11VA else if (d3d11_device_hwctx) { @@ -576,7 +627,7 @@ return AVERROR_EXIT; if (!dl_fn->nvenc_device_count) { - av_log(avctx, AV_LOG_FATAL, "No NVENC capable devices found\n"); + av_log(avctx, AV_LOG_FATAL, "No capable devices found\n"); return AVERROR_EXTERNAL; } @@ -600,6 +651,28 @@ static void nvenc_map_preset(NvencContext *ctx) { GUIDTuple presets[] = { +#ifdef NVENC_HAVE_NEW_PRESETS + PRESET(P1), + PRESET(P2), + PRESET(P3), + PRESET(P4), + PRESET(P5), + PRESET(P6), + PRESET(P7), + PRESET_ALIAS(SLOW, P7, NVENC_TWO_PASSES), + PRESET_ALIAS(MEDIUM, P4, NVENC_ONE_PASS), + PRESET_ALIAS(FAST, P1, NVENC_ONE_PASS), + // Compat aliases + PRESET_ALIAS(DEFAULT, P4, NVENC_DEPRECATED_PRESET), + PRESET_ALIAS(HP, P1, NVENC_DEPRECATED_PRESET), + PRESET_ALIAS(HQ, P7, NVENC_DEPRECATED_PRESET), + PRESET_ALIAS(BD, P5, NVENC_DEPRECATED_PRESET), + PRESET_ALIAS(LOW_LATENCY_DEFAULT, P4, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY), + PRESET_ALIAS(LOW_LATENCY_HP, P1, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY), + PRESET_ALIAS(LOW_LATENCY_HQ, P7, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY), + PRESET_ALIAS(LOSSLESS_DEFAULT, P4, NVENC_DEPRECATED_PRESET | NVENC_LOSSLESS), + PRESET_ALIAS(LOSSLESS_HP, P1, NVENC_DEPRECATED_PRESET | NVENC_LOSSLESS), +#else PRESET(DEFAULT), PRESET(HP), PRESET(HQ), @@ -612,6 +685,7 @@ PRESET(LOW_LATENCY_HQ, NVENC_LOWLATENCY), PRESET(LOSSLESS_DEFAULT, NVENC_LOSSLESS), PRESET(LOSSLESS_HP, NVENC_LOSSLESS), +#endif }; GUIDTuple *t = &presets[ctx->preset]; @@ -821,6 +895,24 @@ if (avctx->rc_max_rate > 0) ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate; +#ifdef NVENC_HAVE_MULTIPASS + ctx->encode_config.rcParams.multiPass = ctx->multipass; + + if (ctx->flags & NVENC_ONE_PASS) + ctx->encode_config.rcParams.multiPass = NV_ENC_MULTI_PASS_DISABLED; + if (ctx->flags & NVENC_TWO_PASSES || ctx->twopass > 0) + ctx->encode_config.rcParams.multiPass = NV_ENC_TWO_PASS_FULL_RESOLUTION; + + if (ctx->rc < 0) { + if (ctx->cbr) { + ctx->rc = NV_ENC_PARAMS_RC_CBR; + } else if (ctx->cqp >= 0) { + ctx->rc = NV_ENC_PARAMS_RC_CONSTQP; + } else if (ctx->quality >= 0.0f) { + ctx->rc = NV_ENC_PARAMS_RC_VBR; + } + } +#else if (ctx->rc < 0) { if (ctx->flags & NVENC_ONE_PASS) ctx->twopass = 0; @@ -844,17 +936,20 @@ ctx->rc = NV_ENC_PARAMS_RC_VBR_MINQP; } } +#endif if (ctx->rc >= 0 && ctx->rc & RC_MODE_DEPRECATED) { av_log(avctx, AV_LOG_WARNING, "Specified rc mode is deprecated.\n"); - av_log(avctx, AV_LOG_WARNING, "\tll_2pass_quality -> cbr_ld_hq\n"); - av_log(avctx, AV_LOG_WARNING, "\tll_2pass_size -> cbr_hq\n"); - av_log(avctx, AV_LOG_WARNING, "\tvbr_2pass -> vbr_hq\n"); - av_log(avctx, AV_LOG_WARNING, "\tvbr_minqp -> (no replacement)\n"); + av_log(avctx, AV_LOG_WARNING, "Use -rc constqp/cbr/vbr, -tune and -multipass instead.\n"); ctx->rc &= ~RC_MODE_DEPRECATED; } +#ifdef NVENC_HAVE_LDKFS + if (ctx->ldkfs) + ctx->encode_config.rcParams.lowDelayKeyFrameScale = ctx->ldkfs; +#endif + if (ctx->flags & NVENC_LOSSLESS) { set_lossless(avctx); } else if (ctx->rc >= 0) { @@ -912,12 +1007,17 @@ if (ctx->zerolatency) ctx->encode_config.rcParams.zeroReorderDelay = 1; - if (ctx->quality) - { + if (ctx->quality) { //convert from float to fixed point 8.8 int tmp_quality = (int)(ctx->quality * 256.0f); ctx->encode_config.rcParams.targetQuality = (uint8_t)(tmp_quality >> 8); ctx->encode_config.rcParams.targetQualityLSB = (uint8_t)(tmp_quality & 0xff); + + av_log(avctx, AV_LOG_VERBOSE, "CQ(%d) mode enabled.\n", tmp_quality); + + //CQ mode shall discard avg bitrate & honor max bitrate; + ctx->encode_config.rcParams.averageBitRate = avctx->bit_rate = 0; + ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate; } } @@ -949,9 +1049,9 @@ h264->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1; h264->outputAUD = ctx->aud; - if (avctx->refs >= 0) { + if (ctx->dpb_size >= 0) { /* 0 means "let the hardware decide" */ - h264->maxNumRefFrames = avctx->refs; + h264->maxNumRefFrames = ctx->dpb_size; } if (avctx->gop_size >= 0) { h264->idrPeriod = cc->gopLength; @@ -1010,6 +1110,11 @@ h264->useBFramesAsRef = ctx->b_ref_mode; #endif +#ifdef NVENC_HAVE_MULTIPLE_REF_FRAMES + h264->numRefL0 = avctx->refs; + h264->numRefL1 = avctx->refs; +#endif + return 0; } @@ -1041,9 +1146,9 @@ hevc->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1; hevc->outputAUD = ctx->aud; - if (avctx->refs >= 0) { + if (ctx->dpb_size >= 0) { /* 0 means "let the hardware decide" */ - hevc->maxNumRefFramesInDPB = avctx->refs; + hevc->maxNumRefFramesInDPB = ctx->dpb_size; } if (avctx->gop_size >= 0) { hevc->idrPeriod = cc->gopLength; @@ -1094,6 +1199,11 @@ hevc->useBFramesAsRef = ctx->b_ref_mode; #endif +#ifdef NVENC_HAVE_MULTIPLE_REF_FRAMES + hevc->numRefL0 = avctx->refs; + hevc->numRefL1 = avctx->refs; +#endif + return 0; } @@ -1146,13 +1256,29 @@ nvenc_map_preset(ctx); + if (ctx->flags & NVENC_DEPRECATED_PRESET) + av_log(avctx, AV_LOG_WARNING, "The selected preset is deprecated. Use p1 to p7 + -tune or fast/medium/slow.\n"); + preset_config.version = NV_ENC_PRESET_CONFIG_VER; preset_config.presetCfg.version = NV_ENC_CONFIG_VER; +#ifdef NVENC_HAVE_NEW_PRESETS + ctx->init_encode_params.tuningInfo = ctx->tuning_info; + + if (ctx->flags & NVENC_LOWLATENCY) + ctx->init_encode_params.tuningInfo = NV_ENC_TUNING_INFO_LOW_LATENCY; + + nv_status = p_nvenc->nvEncGetEncodePresetConfigEx(ctx->nvencoder, + ctx->init_encode_params.encodeGUID, + ctx->init_encode_params.presetGUID, + ctx->init_encode_params.tuningInfo, + &preset_config); +#else nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder, - ctx->init_encode_params.encodeGUID, - ctx->init_encode_params.presetGUID, - &preset_config); + ctx->init_encode_params.encodeGUID, + ctx->init_encode_params.presetGUID, + &preset_config); +#endif if (nv_status != NV_ENC_SUCCESS) return nvenc_print_error(avctx, nv_status, "Cannot get the preset configuration"); @@ -1164,18 +1290,34 @@ ctx->init_encode_params.darHeight = dh; ctx->init_encode_params.darWidth = dw; - ctx->init_encode_params.frameRateNum = avctx->time_base.den; - ctx->init_encode_params.frameRateDen = avctx->time_base.num * avctx->ticks_per_frame; + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + ctx->init_encode_params.frameRateNum = avctx->framerate.num; + ctx->init_encode_params.frameRateDen = avctx->framerate.den; + } else { + ctx->init_encode_params.frameRateNum = avctx->time_base.den; + ctx->init_encode_params.frameRateDen = avctx->time_base.num * avctx->ticks_per_frame; + } ctx->init_encode_params.enableEncodeAsync = 0; ctx->init_encode_params.enablePTD = 1; +#ifdef NVENC_HAVE_NEW_PRESETS + /* If lookahead isn't set from CLI, use value from preset. + * P6 & P7 presets may enable lookahead for better quality. + * */ + if (ctx->rc_lookahead == 0 && ctx->encode_config.rcParams.enableLookahead) + ctx->rc_lookahead = ctx->encode_config.rcParams.lookaheadDepth; + + if (ctx->init_encode_params.tuningInfo == NV_ENC_TUNING_INFO_LOSSLESS) + ctx->flags |= NVENC_LOSSLESS; +#endif + if (ctx->weighted_pred == 1) ctx->init_encode_params.enableWeightedPrediction = 1; if (ctx->bluray_compat) { ctx->aud = 1; - avctx->refs = FFMIN(FFMAX(avctx->refs, 0), 6); + ctx->dpb_size = FFMIN(FFMAX(avctx->refs, 0), 6); avctx->max_b_frames = FFMIN(avctx->max_b_frames, 3); switch (avctx->codec->id) { case AV_CODEC_ID_H264: @@ -1200,9 +1342,6 @@ ctx->encode_config.gopLength = 1; } - ctx->initial_pts[0] = AV_NOPTS_VALUE; - ctx->initial_pts[1] = AV_NOPTS_VALUE; - nvenc_recalc_surfaces(avctx); nvenc_setup_rate_control(avctx); @@ -1222,15 +1361,25 @@ return res; nv_status = p_nvenc->nvEncInitializeEncoder(ctx->nvencoder, &ctx->init_encode_params); + if (nv_status != NV_ENC_SUCCESS) { + nvenc_pop_context(avctx); + return nvenc_print_error(avctx, nv_status, "InitializeEncoder failed"); + } + +#ifdef NVENC_HAVE_CUSTREAM_PTR + if (ctx->cu_context) { + nv_status = p_nvenc->nvEncSetIOCudaStreams(ctx->nvencoder, &ctx->cu_stream, &ctx->cu_stream); + if (nv_status != NV_ENC_SUCCESS) { + nvenc_pop_context(avctx); + return nvenc_print_error(avctx, nv_status, "SetIOCudaStreams failed"); + } + } +#endif res = nvenc_pop_context(avctx); if (res < 0) return res; - if (nv_status != NV_ENC_SUCCESS) { - return nvenc_print_error(avctx, nv_status, "InitializeEncoder failed"); - } - if (ctx->encode_config.frameIntervalP > 1) avctx->has_b_frames = 2; @@ -1320,7 +1469,6 @@ } ctx->surfaces[idx].output_surface = allocOut.bitstreamBuffer; - ctx->surfaces[idx].size = allocOut.size; av_fifo_generic_write(ctx->unused_surface_queue, &tmp_surface, sizeof(tmp_surface), NULL); @@ -1446,6 +1594,8 @@ av_freep(&ctx->surfaces); ctx->nb_surfaces = 0; + av_frame_free(&ctx->frame); + if (ctx->nvencoder) { p_nvenc->nvEncDestroyEncoder(ctx->nvencoder); @@ -1499,6 +1649,10 @@ ctx->data_pix_fmt = avctx->pix_fmt; } + ctx->frame = av_frame_alloc(); + if (!ctx->frame) + return AVERROR(ENOMEM); + if ((ret = nvenc_load_libraries(avctx)) < 0) return ret; @@ -1713,7 +1867,8 @@ static void nvenc_codec_specific_pic_params(AVCodecContext *avctx, NV_ENC_PIC_PARAMS *params, - NV_ENC_SEI_PAYLOAD *sei_data) + NV_ENC_SEI_PAYLOAD *sei_data, + int sei_count) { NvencContext *ctx = avctx->priv_data; @@ -1723,9 +1878,9 @@ ctx->encode_config.encodeCodecConfig.h264Config.sliceMode; params->codecPicParams.h264PicParams.sliceModeData = ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData; - if (sei_data) { + if (sei_count > 0) { params->codecPicParams.h264PicParams.seiPayloadArray = sei_data; - params->codecPicParams.h264PicParams.seiPayloadArrayCnt = 1; + params->codecPicParams.h264PicParams.seiPayloadArrayCnt = sei_count; } break; @@ -1734,9 +1889,9 @@ ctx->encode_config.encodeCodecConfig.hevcConfig.sliceMode; params->codecPicParams.hevcPicParams.sliceModeData = ctx->encode_config.encodeCodecConfig.hevcConfig.sliceModeData; - if (sei_data) { + if (sei_count > 0) { params->codecPicParams.hevcPicParams.seiPayloadArray = sei_data; - params->codecPicParams.hevcPicParams.seiPayloadArrayCnt = 1; + params->codecPicParams.hevcPicParams.seiPayloadArrayCnt = sei_count; } break; @@ -1764,30 +1919,10 @@ NvencContext *ctx = avctx->priv_data; pkt->pts = params->outputTimeStamp; - - /* generate the first dts by linearly extrapolating the - * first two pts values to the past */ - if (avctx->max_b_frames > 0 && !ctx->first_packet_output && - ctx->initial_pts[1] != AV_NOPTS_VALUE) { - int64_t ts0 = ctx->initial_pts[0], ts1 = ctx->initial_pts[1]; - int64_t delta; - - if ((ts0 < 0 && ts1 > INT64_MAX + ts0) || - (ts0 > 0 && ts1 < INT64_MIN + ts0)) - return AVERROR(ERANGE); - delta = ts1 - ts0; - - if ((delta < 0 && ts0 > INT64_MAX + delta) || - (delta > 0 && ts0 < INT64_MIN + delta)) - return AVERROR(ERANGE); - pkt->dts = ts0 - delta; - - ctx->first_packet_output = 1; - return 0; - } - pkt->dts = timestamp_queue_dequeue(ctx->timestamp_list); + pkt->dts -= FFMAX(ctx->encode_config.frameIntervalP - 1, 0) * FFMAX(avctx->ticks_per_frame, 1); + return 0; } @@ -1836,9 +1971,7 @@ goto error; } - res = pkt->data ? - ff_alloc_packet2(avctx, pkt, lock_params.bitstreamSizeInBytes, lock_params.bitstreamSizeInBytes) : - av_new_packet(pkt, lock_params.bitstreamSizeInBytes); + res = ff_get_encode_buffer(avctx, pkt, lock_params.bitstreamSizeInBytes, 0); if (res < 0) { p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface); @@ -1925,12 +2058,6 @@ NvencContext *ctx = avctx->priv_data; int nb_ready, nb_pending; - /* when B-frames are enabled, we wait for two initial timestamps to - * calculate the first dts */ - if (!flush && avctx->max_b_frames > 0 && - (ctx->initial_pts[0] == AV_NOPTS_VALUE || ctx->initial_pts[1] == AV_NOPTS_VALUE)) - return 0; - nb_ready = av_fifo_size(ctx->output_surface_ready_queue) / sizeof(NvencSurface*); nb_pending = av_fifo_size(ctx->output_surface_queue) / sizeof(NvencSurface*); if (flush) @@ -2030,13 +2157,14 @@ } } -int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) +static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) { NVENCSTATUS nv_status; NvencSurface *tmp_out_surf, *in_surf; int res, res2; - NV_ENC_SEI_PAYLOAD *sei_data = NULL; - size_t sei_size; + NV_ENC_SEI_PAYLOAD sei_data[8]; + int sei_count = 0; + int i; NvencContext *ctx = avctx->priv_data; NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs; @@ -2048,18 +2176,7 @@ if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder) return AVERROR(EINVAL); - if (ctx->encoder_flushing) { - if (avctx->internal->draining) - return AVERROR_EOF; - - ctx->encoder_flushing = 0; - ctx->first_packet_output = 0; - ctx->initial_pts[0] = AV_NOPTS_VALUE; - ctx->initial_pts[1] = AV_NOPTS_VALUE; - av_fifo_reset(ctx->timestamp_list); - } - - if (frame) { + if (frame && frame->buf[0]) { in_surf = get_free_frame(ctx); if (!in_surf) return AVERROR(EAGAIN); @@ -2105,21 +2222,40 @@ pic_params.inputTimeStamp = frame->pts; if (ctx->a53_cc && av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC)) { - if (ff_alloc_a53_sei(frame, sizeof(NV_ENC_SEI_PAYLOAD), (void**)&sei_data, &sei_size) < 0) { + void *a53_data = NULL; + size_t a53_size = 0; + + if (ff_alloc_a53_sei(frame, 0, (void**)&a53_data, &a53_size) < 0) { av_log(ctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n"); } - if (sei_data) { - sei_data->payloadSize = (uint32_t)sei_size; - sei_data->payloadType = 4; - sei_data->payload = (uint8_t*)(sei_data + 1); + if (a53_data) { + sei_data[sei_count].payloadSize = (uint32_t)a53_size; + sei_data[sei_count].payloadType = 4; + sei_data[sei_count].payload = (uint8_t*)a53_data; + sei_count ++; + } + } + + if (ctx->s12m_tc && av_frame_get_side_data(frame, AV_FRAME_DATA_S12M_TIMECODE)) { + void *tc_data = NULL; + size_t tc_size = 0; + + if (ff_alloc_timecode_sei(frame, avctx->framerate, 0, (void**)&tc_data, &tc_size) < 0) { + av_log(ctx, AV_LOG_ERROR, "Not enough memory for timecode sei, skipping\n"); + } + + if (tc_data) { + sei_data[sei_count].payloadSize = (uint32_t)tc_size; + sei_data[sei_count].payloadType = SEI_TYPE_TIME_CODE; + sei_data[sei_count].payload = (uint8_t*)tc_data; + sei_count ++; } } - nvenc_codec_specific_pic_params(avctx, &pic_params, sei_data); + nvenc_codec_specific_pic_params(avctx, &pic_params, sei_data, sei_count); } else { pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS; - ctx->encoder_flushing = 1; } res = nvenc_push_context(avctx); @@ -2127,7 +2263,9 @@ return res; nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params); - av_free(sei_data); + + for ( i = 0; i < sei_count; i++) + av_freep(&sei_data[i].payload); res = nvenc_pop_context(avctx); if (res < 0) @@ -2137,14 +2275,9 @@ nv_status != NV_ENC_ERR_NEED_MORE_INPUT) return nvenc_print_error(avctx, nv_status, "EncodePicture failed!"); - if (frame) { + if (frame && frame->buf[0]) { av_fifo_generic_write(ctx->output_surface_queue, &in_surf, sizeof(in_surf), NULL); timestamp_queue_enqueue(ctx->timestamp_list, frame->pts); - - if (ctx->initial_pts[0] == AV_NOPTS_VALUE) - ctx->initial_pts[0] = frame->pts; - else if (ctx->initial_pts[1] == AV_NOPTS_VALUE) - ctx->initial_pts[1] = frame->pts; } /* all the pending buffers are now ready for output */ @@ -2165,10 +2298,25 @@ NvencContext *ctx = avctx->priv_data; + AVFrame *frame = ctx->frame; + if ((!ctx->cu_context && !ctx->d3d11_device) || !ctx->nvencoder) return AVERROR(EINVAL); - if (output_ready(avctx, ctx->encoder_flushing)) { + if (!frame->buf[0]) { + res = ff_encode_get_frame(avctx, frame); + if (res < 0 && res != AVERROR_EOF) + return res; + } + + res = nvenc_send_frame(avctx, frame); + if (res < 0) { + if (res != AVERROR(EAGAIN)) + return res; + } else + av_frame_unref(frame); + + if (output_ready(avctx, avctx->internal->draining)) { av_fifo_generic_read(ctx->output_surface_ready_queue, &tmp_out_surf, sizeof(tmp_out_surf), NULL); res = nvenc_push_context(avctx); @@ -2185,7 +2333,7 @@ return res; av_fifo_generic_write(ctx->unused_surface_queue, &tmp_out_surf, sizeof(tmp_out_surf), NULL); - } else if (ctx->encoder_flushing) { + } else if (avctx->internal->draining) { return AVERROR_EOF; } else { return AVERROR(EAGAIN); @@ -2194,26 +2342,10 @@ return 0; } -int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, - const AVFrame *frame, int *got_packet) +av_cold void ff_nvenc_encode_flush(AVCodecContext *avctx) { NvencContext *ctx = avctx->priv_data; - int res; - if (!ctx->encoder_flushing) { - res = ff_nvenc_send_frame(avctx, frame); - if (res < 0) - return res; - } - - res = ff_nvenc_receive_packet(avctx, pkt); - if (res == AVERROR(EAGAIN) || res == AVERROR_EOF) { - *got_packet = 0; - } else if (res < 0) { - return res; - } else { - *got_packet = 1; - } - - return 0; + nvenc_send_frame(avctx, NULL); + av_fifo_reset(ctx->timestamp_list); } diff -Nru ffmpeg-4.2.2/libavcodec/nvenc.h ffmpeg-4.4/libavcodec/nvenc.h --- ffmpeg-4.2.2/libavcodec/nvenc.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/nvenc.h 2021-04-08 21:28:39.000000000 +0000 @@ -33,6 +33,7 @@ #include "compat/cuda/dynlink_loader.h" #include "libavutil/fifo.h" #include "libavutil/opt.h" +#include "hwconfig.h" #include "avcodec.h" @@ -54,6 +55,21 @@ #define NVENC_HAVE_HEVC_BFRAME_REF_MODE #endif +// SDK 9.1 compile time feature checks +#if NVENCAPI_CHECK_VERSION(9, 1) +#define NVENC_HAVE_MULTIPLE_REF_FRAMES +#define NVENC_HAVE_CUSTREAM_PTR +#define NVENC_HAVE_GETLASTERRORSTRING +#endif + +// SDK 10.0 compile time feature checks +#if NVENCAPI_CHECK_VERSION(10, 0) +#define NVENC_HAVE_NEW_PRESETS +#define NVENC_HAVE_MULTIPASS +#define NVENC_HAVE_LDKFS +#define NVENC_HAVE_H264_LVL6 +#endif + typedef struct NvencSurface { NV_ENC_INPUT_PTR input_surface; @@ -65,7 +81,6 @@ NV_ENC_OUTPUT_PTR output_surface; NV_ENC_BUFFER_FORMAT format; - int size; } NvencSurface; typedef struct NvencDynLoadFunctions @@ -90,6 +105,15 @@ PRESET_LOW_LATENCY_HP, PRESET_LOSSLESS_DEFAULT, // lossless presets must be the last ones PRESET_LOSSLESS_HP, +#ifdef NVENC_HAVE_NEW_PRESETS + PRESET_P1, + PRESET_P2, + PRESET_P3, + PRESET_P4, + PRESET_P5, + PRESET_P6, + PRESET_P7, +#endif }; enum { @@ -110,6 +134,8 @@ NVENC_LOSSLESS = 2, NVENC_ONE_PASS = 4, NVENC_TWO_PASSES = 8, + + NVENC_DEPRECATED_PRESET = 0x8000, }; enum { @@ -127,8 +153,11 @@ NV_ENC_CONFIG encode_config; CUcontext cu_context; CUcontext cu_context_internal; + CUstream cu_stream; ID3D11Device *d3d11_device; + AVFrame *frame; + int nb_surfaces; NvencSurface *surfaces; @@ -137,8 +166,6 @@ AVFifoBuffer *output_surface_ready_queue; AVFifoBuffer *timestamp_list; - int encoder_flushing; - struct { void *ptr; int ptr_index; @@ -152,11 +179,6 @@ * AVCodecContext.pix_fmt when using hwaccel frames on input */ enum AVPixelFormat data_pix_fmt; - /* timestamps of the first two frames, for computing the first dts - * when B-frames are present */ - int64_t initial_pts[2]; - int first_packet_output; - int support_dyn_bitrate; void *nvencoder; @@ -192,19 +214,22 @@ int coder; int b_ref_mode; int a53_cc; + int s12m_tc; + int dpb_size; + int tuning_info; + int multipass; + int ldkfs; } NvencContext; int ff_nvenc_encode_init(AVCodecContext *avctx); int ff_nvenc_encode_close(AVCodecContext *avctx); -int ff_nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame); - int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt); -int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, - const AVFrame *frame, int *got_packet); +void ff_nvenc_encode_flush(AVCodecContext *avctx); extern const enum AVPixelFormat ff_nvenc_pix_fmts[]; +extern const AVCodecHWConfigInternal *const ff_nvenc_hw_configs[]; #endif /* AVCODEC_NVENC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/nvenc_h264.c ffmpeg-4.4/libavcodec/nvenc_h264.c --- ffmpeg-4.2.2/libavcodec/nvenc_h264.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/nvenc_h264.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,7 +26,11 @@ #define OFFSET(x) offsetof(NvencContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { +#ifdef NVENC_HAVE_NEW_PRESETS + { "preset", "Set the encoding preset", OFFSET(preset), AV_OPT_TYPE_INT, { .i64 = PRESET_P4 }, PRESET_DEFAULT, PRESET_P7, VE, "preset" }, +#else { "preset", "Set the encoding preset", OFFSET(preset), AV_OPT_TYPE_INT, { .i64 = PRESET_MEDIUM }, PRESET_DEFAULT, PRESET_LOSSLESS_HP, VE, "preset" }, +#endif { "default", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_DEFAULT }, 0, 0, VE, "preset" }, { "slow", "hq 2 passes", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_SLOW }, 0, 0, VE, "preset" }, { "medium", "hq 1 pass", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_MEDIUM }, 0, 0, VE, "preset" }, @@ -39,12 +43,30 @@ { "llhp", "low latency hp", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOW_LATENCY_HP }, 0, 0, VE, "preset" }, { "lossless", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOSSLESS_DEFAULT }, 0, 0, VE, "preset" }, { "losslesshp", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOSSLESS_HP }, 0, 0, VE, "preset" }, +#ifdef NVENC_HAVE_NEW_PRESETS + { "p1", "fastest (lowest quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P1 }, 0, 0, VE, "preset" }, + { "p2", "faster (lower quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P2 }, 0, 0, VE, "preset" }, + { "p3", "fast (low quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P3 }, 0, 0, VE, "preset" }, + { "p4", "medium (default)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P4 }, 0, 0, VE, "preset" }, + { "p5", "slow (good quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P5 }, 0, 0, VE, "preset" }, + { "p6", "slower (better quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P6 }, 0, 0, VE, "preset" }, + { "p7", "slowest (best quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P7 }, 0, 0, VE, "preset" }, + { "tune", "Set the encoding tuning info", OFFSET(tuning_info), AV_OPT_TYPE_INT, { .i64 = NV_ENC_TUNING_INFO_HIGH_QUALITY }, NV_ENC_TUNING_INFO_HIGH_QUALITY, NV_ENC_TUNING_INFO_LOSSLESS, VE, "tune" }, + { "hq", "High quality", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TUNING_INFO_HIGH_QUALITY }, 0, 0, VE, "tune" }, + { "ll", "Low latency", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TUNING_INFO_LOW_LATENCY }, 0, 0, VE, "tune" }, + { "ull", "Ultra low latency", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY }, 0, 0, VE, "tune" }, + { "lossless", "Lossless", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TUNING_INFO_LOSSLESS }, 0, 0, VE, "tune" }, +#endif { "profile", "Set the encoding profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = NV_ENC_H264_PROFILE_MAIN }, NV_ENC_H264_PROFILE_BASELINE, NV_ENC_H264_PROFILE_HIGH_444P, VE, "profile" }, { "baseline", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_BASELINE }, 0, 0, VE, "profile" }, { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_MAIN }, 0, 0, VE, "profile" }, { "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH }, 0, 0, VE, "profile" }, { "high444p", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH_444P }, 0, 0, VE, "profile" }, - { "level", "Set the encoding level restriction", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, NV_ENC_LEVEL_AUTOSELECT, NV_ENC_LEVEL_H264_51, VE, "level" }, +#ifdef NVENC_HAVE_H264_LVL6 + { "level", "Set the encoding level restriction", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, NV_ENC_LEVEL_AUTOSELECT, NV_ENC_LEVEL_H264_62, VE, "level" }, +#else + { "level", "Set the encoding level restriction", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, NV_ENC_LEVEL_AUTOSELECT, NV_ENC_LEVEL_H264_52, VE, "level" }, +#endif { "auto", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, 0, 0, VE, "level" }, { "1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_1 }, 0, 0, VE, "level" }, { "1.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_1 }, 0, 0, VE, "level" }, @@ -68,6 +90,12 @@ { "5", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_5 }, 0, 0, VE, "level" }, { "5.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_5 }, 0, 0, VE, "level" }, { "5.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_51 }, 0, 0, VE, "level" }, + { "5.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_52 }, 0, 0, VE, "level" }, +#ifdef NVENC_HAVE_H264_LVL6 + { "6.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_60 }, 0, 0, VE, "level" }, + { "6.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_61 }, 0, 0, VE, "level" }, + { "6.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_62 }, 0, 0, VE, "level" }, +#endif { "rc", "Override the preset rate-control", OFFSET(rc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, "rc" }, { "constqp", "Constant QP mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CONSTQP }, 0, 0, VE, "rc" }, { "vbr", "Variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_VBR }, 0, 0, VE, "rc" }, @@ -78,9 +106,9 @@ { "ll_2pass_size", "Multi-pass optimized for constant frame size (deprecated)", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP) }, 0, 0, VE, "rc" }, { "vbr_2pass", "Multi-pass variable bitrate mode (deprecated)", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_2_PASS_VBR) }, 0, 0, VE, "rc" }, - { "cbr_ld_hq", "Constant bitrate low delay high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ }, 0, 0, VE, "rc" }, - { "cbr_hq", "Constant bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CBR_HQ }, 0, 0, VE, "rc" }, - { "vbr_hq", "Variable bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_VBR_HQ }, 0, 0, VE, "rc" }, + { "cbr_ld_hq", "Constant bitrate low delay high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ) }, 0, 0, VE, "rc" }, + { "cbr_hq", "Constant bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR_HQ) }, 0, 0, VE, "rc" }, + { "vbr_hq", "Variable bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR_HQ) }, 0, 0, VE, "rc" }, { "rc-lookahead", "Number of frames to look ahead for rate-control", OFFSET(rc_lookahead), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, { "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_REGISTERED_FRAMES, VE }, @@ -99,7 +127,9 @@ { "b_adapt", "When lookahead is enabled, set this to 0 to disable adaptive B-frame decision", OFFSET(b_adapt), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, { "spatial-aq", "set to 1 to enable Spatial AQ", OFFSET(aq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "spatial_aq", "set to 1 to enable Spatial AQ", OFFSET(aq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "temporal-aq", "set to 1 to enable Temporal AQ", OFFSET(temporal_aq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "temporal_aq", "set to 1 to enable Temporal AQ", OFFSET(temporal_aq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "zerolatency", "Set 1 to indicate zero latency operation (no reordering delay)", OFFSET(zerolatency), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "nonref_p", "Set this to 1 to enable automatic insertion of non-reference P-frames", @@ -138,6 +168,20 @@ { "middle", "", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, VE, "b_ref_mode" }, #endif { "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + { "dpb_size", "Specifies the DPB size used for encoding (0 means automatic)", + OFFSET(dpb_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, +#ifdef NVENC_HAVE_MULTIPASS + { "multipass", "Set the multipass encoding", OFFSET(multipass), AV_OPT_TYPE_INT, { .i64 = NV_ENC_MULTI_PASS_DISABLED }, NV_ENC_MULTI_PASS_DISABLED, NV_ENC_TWO_PASS_FULL_RESOLUTION, VE, "multipass" }, + { "disabled", "Single Pass", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_MULTI_PASS_DISABLED }, 0, 0, VE, "multipass" }, + { "qres", "Two Pass encoding is enabled where first Pass is quarter resolution", + 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TWO_PASS_QUARTER_RESOLUTION }, 0, 0, VE, "multipass" }, + { "fullres", "Two Pass encoding is enabled where first Pass is full resolution", + 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TWO_PASS_FULL_RESOLUTION }, 0, 0, VE, "multipass" }, +#endif +#ifdef NVENC_HAVE_LDKFS + { "ldkfs", "Low delay key frame scale; Specifies the Scene Change frame size increase allowed in case of single frame VBV and CBR", + OFFSET(ldkfs), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UCHAR_MAX, VE }, +#endif { NULL } }; @@ -149,7 +193,7 @@ { "qblur", "-1" }, { "qcomp", "-1" }, { "g", "250" }, - { "bf", "0" }, + { "bf", "-1" }, { "refs", "0" }, { NULL }, }; @@ -176,17 +220,18 @@ .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, .init = nvenc_old_init, - .send_frame = ff_nvenc_send_frame, .receive_packet = ff_nvenc_receive_packet, - .encode2 = ff_nvenc_encode_frame, .close = ff_nvenc_encode_close, + .flush = ff_nvenc_encode_flush, .priv_data_size = sizeof(NvencContext), .priv_class = &nvenc_class, .defaults = defaults, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_ENCODER_FLUSH, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = ff_nvenc_pix_fmts, .wrapper_name = "nvenc", + .hw_configs = ff_nvenc_hw_configs, }; #endif @@ -205,17 +250,18 @@ .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, .init = nvenc_old_init, - .send_frame = ff_nvenc_send_frame, .receive_packet = ff_nvenc_receive_packet, - .encode2 = ff_nvenc_encode_frame, .close = ff_nvenc_encode_close, + .flush = ff_nvenc_encode_flush, .priv_data_size = sizeof(NvencContext), .priv_class = &nvenc_h264_class, .defaults = defaults, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_ENCODER_FLUSH, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = ff_nvenc_pix_fmts, .wrapper_name = "nvenc", + .hw_configs = ff_nvenc_hw_configs, }; #endif @@ -234,15 +280,16 @@ .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, .init = ff_nvenc_encode_init, - .send_frame = ff_nvenc_send_frame, .receive_packet = ff_nvenc_receive_packet, - .encode2 = ff_nvenc_encode_frame, .close = ff_nvenc_encode_close, + .flush = ff_nvenc_encode_flush, .priv_data_size = sizeof(NvencContext), .priv_class = &h264_nvenc_class, .defaults = defaults, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = ff_nvenc_pix_fmts, .wrapper_name = "nvenc", + .hw_configs = ff_nvenc_hw_configs, }; diff -Nru ffmpeg-4.2.2/libavcodec/nvenc_hevc.c ffmpeg-4.4/libavcodec/nvenc_hevc.c --- ffmpeg-4.2.2/libavcodec/nvenc_hevc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/nvenc_hevc.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,7 +26,11 @@ #define OFFSET(x) offsetof(NvencContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { +#ifdef NVENC_HAVE_NEW_PRESETS + { "preset", "Set the encoding preset", OFFSET(preset), AV_OPT_TYPE_INT, { .i64 = PRESET_P4 }, PRESET_DEFAULT, PRESET_P7, VE, "preset" }, +#else { "preset", "Set the encoding preset", OFFSET(preset), AV_OPT_TYPE_INT, { .i64 = PRESET_MEDIUM }, PRESET_DEFAULT, PRESET_LOSSLESS_HP, VE, "preset" }, +#endif { "default", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_DEFAULT }, 0, 0, VE, "preset" }, { "slow", "hq 2 passes", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_SLOW }, 0, 0, VE, "preset" }, { "medium", "hq 1 pass", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_MEDIUM }, 0, 0, VE, "preset" }, @@ -39,6 +43,20 @@ { "llhp", "low latency hp", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOW_LATENCY_HP }, 0, 0, VE, "preset" }, { "lossless", "lossless", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOSSLESS_DEFAULT }, 0, 0, VE, "preset" }, { "losslesshp", "lossless hp", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOSSLESS_HP }, 0, 0, VE, "preset" }, +#ifdef NVENC_HAVE_NEW_PRESETS + { "p1", "fastest (lowest quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P1 }, 0, 0, VE, "preset" }, + { "p2", "faster (lower quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P2 }, 0, 0, VE, "preset" }, + { "p3", "fast (low quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P3 }, 0, 0, VE, "preset" }, + { "p4", "medium (default)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P4 }, 0, 0, VE, "preset" }, + { "p5", "slow (good quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P5 }, 0, 0, VE, "preset" }, + { "p6", "slower (better quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P6 }, 0, 0, VE, "preset" }, + { "p7", "slowest (best quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P7 }, 0, 0, VE, "preset" }, + { "tune", "Set the encoding tuning info", OFFSET(tuning_info), AV_OPT_TYPE_INT, { .i64 = NV_ENC_TUNING_INFO_HIGH_QUALITY }, NV_ENC_TUNING_INFO_HIGH_QUALITY, NV_ENC_TUNING_INFO_LOSSLESS, VE, "tune" }, + { "hq", "High quality", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TUNING_INFO_HIGH_QUALITY }, 0, 0, VE, "tune" }, + { "ll", "Low latency", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TUNING_INFO_LOW_LATENCY }, 0, 0, VE, "tune" }, + { "ull", "Ultra low latency", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY }, 0, 0, VE, "tune" }, + { "lossless", "Lossless", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TUNING_INFO_LOSSLESS }, 0, 0, VE, "tune" }, +#endif { "profile", "Set the encoding profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = NV_ENC_HEVC_PROFILE_MAIN }, NV_ENC_HEVC_PROFILE_MAIN, FF_PROFILE_HEVC_REXT, VE, "profile" }, { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_HEVC_PROFILE_MAIN }, 0, 0, VE, "profile" }, { "main10", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_HEVC_PROFILE_MAIN_10 }, 0, 0, VE, "profile" }, @@ -77,9 +95,9 @@ { "ll_2pass_size", "Multi-pass optimized for constant frame size (deprecated)", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP) }, 0, 0, VE, "rc" }, { "vbr_2pass", "Multi-pass variable bitrate mode (deprecated)", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_2_PASS_VBR) }, 0, 0, VE, "rc" }, - { "cbr_ld_hq", "Constant bitrate low delay high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ }, 0, 0, VE, "rc" }, - { "cbr_hq", "Constant bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CBR_HQ }, 0, 0, VE, "rc" }, - { "vbr_hq", "Variable bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_VBR_HQ }, 0, 0, VE, "rc" }, + { "cbr_ld_hq", "Constant bitrate low delay high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ) }, 0, 0, VE, "rc" }, + { "cbr_hq", "Constant bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_CBR_HQ) }, 0, 0, VE, "rc" }, + { "vbr_hq", "Variable bitrate high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = RCD(NV_ENC_PARAMS_RC_VBR_HQ) }, 0, 0, VE, "rc" }, { "rc-lookahead", "Number of frames to look ahead for rate-control", OFFSET(rc_lookahead), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, { "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_REGISTERED_FRAMES, VE }, @@ -96,7 +114,9 @@ { "forced-idr", "If forcing keyframes, force them as IDR frames.", OFFSET(forced_idr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, -1, 1, VE }, { "spatial_aq", "set to 1 to enable Spatial AQ", OFFSET(aq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "spatial-aq", "set to 1 to enable Spatial AQ", OFFSET(aq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "temporal_aq", "set to 1 to enable Temporal AQ", OFFSET(temporal_aq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "temporal-aq", "set to 1 to enable Temporal AQ", OFFSET(temporal_aq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "zerolatency", "Set 1 to indicate zero latency operation (no reordering delay)", OFFSET(zerolatency), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "nonref_p", "Set this to 1 to enable automatic insertion of non-reference P-frames", @@ -127,6 +147,22 @@ { "each", "", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "b_ref_mode" }, { "middle", "", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, VE, "b_ref_mode" }, #endif + { "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + { "s12m_tc", "Use timecode (if available)", OFFSET(s12m_tc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + { "dpb_size", "Specifies the DPB size used for encoding (0 means automatic)", + OFFSET(dpb_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, +#ifdef NVENC_HAVE_MULTIPASS + { "multipass", "Set the multipass encoding", OFFSET(multipass), AV_OPT_TYPE_INT, { .i64 = NV_ENC_MULTI_PASS_DISABLED }, NV_ENC_MULTI_PASS_DISABLED, NV_ENC_TWO_PASS_FULL_RESOLUTION, VE, "multipass" }, + { "disabled", "Single Pass", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_MULTI_PASS_DISABLED }, 0, 0, VE, "multipass" }, + { "qres", "Two Pass encoding is enabled where first Pass is quarter resolution", + 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TWO_PASS_QUARTER_RESOLUTION }, 0, 0, VE, "multipass" }, + { "fullres", "Two Pass encoding is enabled where first Pass is full resolution", + 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TWO_PASS_FULL_RESOLUTION }, 0, 0, VE, "multipass" }, +#endif +#ifdef NVENC_HAVE_LDKFS + { "ldkfs", "Low delay key frame scale; Specifies the Scene Change frame size increase allowed in case of single frame VBV and CBR", + OFFSET(ldkfs), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UCHAR_MAX, VE }, +#endif { NULL } }; @@ -138,7 +174,7 @@ { "qblur", "-1" }, { "qcomp", "-1" }, { "g", "250" }, - { "bf", "0" }, + { "bf", "-1" }, { "refs", "0" }, { NULL }, }; @@ -164,17 +200,18 @@ .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, .init = nvenc_old_init, - .send_frame = ff_nvenc_send_frame, .receive_packet = ff_nvenc_receive_packet, - .encode2 = ff_nvenc_encode_frame, .close = ff_nvenc_encode_close, + .flush = ff_nvenc_encode_flush, .priv_data_size = sizeof(NvencContext), .priv_class = &nvenc_hevc_class, .defaults = defaults, .pix_fmts = ff_nvenc_pix_fmts, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_ENCODER_FLUSH, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .wrapper_name = "nvenc", + .hw_configs = ff_nvenc_hw_configs, }; #endif @@ -192,15 +229,16 @@ .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_HEVC, .init = ff_nvenc_encode_init, - .send_frame = ff_nvenc_send_frame, .receive_packet = ff_nvenc_receive_packet, - .encode2 = ff_nvenc_encode_frame, .close = ff_nvenc_encode_close, + .flush = ff_nvenc_encode_flush, .priv_data_size = sizeof(NvencContext), .priv_class = &hevc_nvenc_class, .defaults = defaults, .pix_fmts = ff_nvenc_pix_fmts, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .wrapper_name = "nvenc", + .hw_configs = ff_nvenc_hw_configs, }; diff -Nru ffmpeg-4.2.2/libavcodec/omx.c ffmpeg-4.4/libavcodec/omx.c --- ffmpeg-4.2.2/libavcodec/omx.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/omx.c 2020-07-11 10:39:30.000000000 +0000 @@ -799,6 +799,26 @@ // Convert the timestamps to microseconds; some encoders can ignore // the framerate and do VFR bit allocation based on timestamps. buffer->nTimeStamp = to_omx_ticks(av_rescale_q(frame->pts, avctx->time_base, AV_TIME_BASE_Q)); + if (frame->pict_type == AV_PICTURE_TYPE_I) { +#if CONFIG_OMX_RPI + OMX_CONFIG_BOOLEANTYPE config = {0, }; + INIT_STRUCT(config); + config.bEnabled = OMX_TRUE; + err = OMX_SetConfig(s->handle, OMX_IndexConfigBrcmVideoRequestIFrame, &config); + if (err != OMX_ErrorNone) { + av_log(avctx, AV_LOG_ERROR, "OMX_SetConfig(RequestIFrame) failed: %x\n", err); + } +#else + OMX_CONFIG_INTRAREFRESHVOPTYPE config = {0, }; + INIT_STRUCT(config); + config.nPortIndex = s->out_port; + config.IntraRefreshVOP = OMX_TRUE; + err = OMX_SetConfig(s->handle, OMX_IndexConfigVideoIntraVOPRefresh, &config); + if (err != OMX_ErrorNone) { + av_log(avctx, AV_LOG_ERROR, "OMX_SetConfig(IntraVOPRefresh) failed: %x\n", err); + } +#endif + } err = OMX_EmptyThisBuffer(s->handle, buffer); if (err != OMX_ErrorNone) { append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer); diff -Nru ffmpeg-4.2.2/libavcodec/on2avc.c ffmpeg-4.4/libavcodec/on2avc.c --- ffmpeg-4.2.2/libavcodec/on2avc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/on2avc.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,8 @@ #include "libavutil/channel_layout.h" #include "libavutil/ffmath.h" #include "libavutil/float_dsp.h" +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "bytestream.h" #include "fft.h" @@ -169,7 +171,7 @@ scale = get_bits(gb, 7); first = 0; } else { - scale += get_vlc2(gb, c->scale_diff.table, 9, 3) - 60; + scale += get_vlc2(gb, c->scale_diff.table, 9, 3); } if (scale < 0 || scale > 127) { av_log(c->avctx, AV_LOG_ERROR, "Invalid scale value %d\n", @@ -195,7 +197,7 @@ int i, j, val, val1; for (i = 0; i < dst_size; i += 4) { - val = get_vlc2(gb, c->cb_vlc[type].table, 9, 3); + val = get_vlc2(gb, c->cb_vlc[type].table, 9, 2); for (j = 0; j < 4; j++) { val1 = sign_extend((val >> (12 - j * 4)) & 0xF, 4); @@ -228,7 +230,7 @@ int i, val, val1, val2, sign; for (i = 0; i < dst_size; i += 2) { - val = get_vlc2(gb, c->cb_vlc[type].table, 9, 3); + val = get_vlc2(gb, c->cb_vlc[type].table, 9, 2); val1 = sign_extend(val >> 8, 8); val2 = sign_extend(val & 0xFF, 8); @@ -906,7 +908,9 @@ static av_cold int on2avc_decode_init(AVCodecContext *avctx) { On2AVCContext *c = avctx->priv_data; - int i; + const uint8_t *lens = ff_on2avc_cb_lens; + const uint16_t *syms = ff_on2avc_cb_syms; + int i, ret; if (avctx->channels > 2U) { avpriv_request_sample(avctx, "Decoding more than 2 channels"); @@ -956,36 +960,26 @@ if (!c->fdsp) return AVERROR(ENOMEM); - if (init_vlc(&c->scale_diff, 9, ON2AVC_SCALE_DIFFS, - ff_on2avc_scale_diff_bits, 1, 1, - ff_on2avc_scale_diff_codes, 4, 4, 0)) { + ret = ff_init_vlc_from_lengths(&c->scale_diff, 9, ON2AVC_SCALE_DIFFS, + ff_on2avc_scale_diff_bits, 1, + ff_on2avc_scale_diff_syms, 1, 1, -60, 0, avctx); + if (ret < 0) goto vlc_fail; - } - for (i = 1; i < 9; i++) { + for (i = 1; i < 16; i++) { int idx = i - 1; - if (ff_init_vlc_sparse(&c->cb_vlc[i], 9, ff_on2avc_quad_cb_elems[idx], - ff_on2avc_quad_cb_bits[idx], 1, 1, - ff_on2avc_quad_cb_codes[idx], 4, 4, - ff_on2avc_quad_cb_syms[idx], 2, 2, 0)) { + ret = ff_init_vlc_from_lengths(&c->cb_vlc[i], 9, ff_on2avc_cb_elems[idx], + lens, 1, + syms, 2, 2, 0, 0, avctx); + if (ret < 0) goto vlc_fail; - } - } - for (i = 9; i < 16; i++) { - int idx = i - 9; - if (ff_init_vlc_sparse(&c->cb_vlc[i], 9, ff_on2avc_pair_cb_elems[idx], - ff_on2avc_pair_cb_bits[idx], 1, 1, - ff_on2avc_pair_cb_codes[idx], 2, 2, - ff_on2avc_pair_cb_syms[idx], 2, 2, 0)) { - goto vlc_fail; - } + lens += ff_on2avc_cb_elems[idx]; + syms += ff_on2avc_cb_elems[idx]; } return 0; vlc_fail: av_log(avctx, AV_LOG_ERROR, "Cannot init VLC\n"); - on2avc_free_vlcs(c); - av_freep(&c->fdsp); - return AVERROR(ENOMEM); + return ret; } static av_cold int on2avc_decode_close(AVCodecContext *avctx) diff -Nru ffmpeg-4.2.2/libavcodec/on2avcdata.c ffmpeg-4.4/libavcodec/on2avcdata.c --- ffmpeg-4.2.2/libavcodec/on2avcdata.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/on2avcdata.c 2021-04-08 21:28:39.000000000 +0000 @@ -110,6779 +110,2227 @@ { 1, 49, on2avc_swb_start_long }, }; -const uint32_t ff_on2avc_scale_diff_codes[ON2AVC_SCALE_DIFFS] = { - 0x6FFFF, 0xBFFF2, 0xBFFF3, 0xBFFF4, 0xBFFF5, 0xBFFF6, - 0xBFFF7, 0xBFFF8, 0xBFFF9, 0xBFFFA, 0xBFFFB, 0xBFFFC, - 0xBFFFD, 0xBFFFE, 0xBFFFF, 0xDF9A0, 0xDF9A1, 0xDF9A2, - 0xDF9A3, 0xDF9A4, 0xDF9A5, 0xDF9A6, 0xDF9A7, 0xDF9A8, - 0xDF9A9, 0x37FFE, 0x6FCDE, 0x6FFFA, 0x0BFF7, 0x0B7FF, - 0x0DF9F, 0x05FF8, 0x0B7FE, 0x05FF9, 0x06FCE, 0x05BFE, - 0x037FE, 0x02DFE, 0x00DFA, 0x00DFE, 0x017FC, 0x00DBE, - 0x00B7E, 0x005FE, 0x0037D, 0x002DE, 0x0017E, 0x0016C, - 0x000DE, 0x000BE, 0x0006C, 0x0005A, 0x0003E, 0x00034, - 0x0002C, 0x0001F, 0x0000E, 0x0000E, 0x00006, 0x00002, - 0x00000, 0x00004, 0x0000A, 0x0000C, 0x0001E, 0x0001E, - 0x0002E, 0x00035, 0x0003F, 0x0005E, 0x0006E, 0x000DA, - 0x0016D, 0x0016E, 0x001B6, 0x002FE, 0x0036E, 0x0037C, - 0x005BE, 0x006DE, 0x006FE, 0x00DBF, 0x00DFB, 0x016FE, - 0x017FD, 0x01BFE, 0x01BF2, 0x02FFE, 0x06FCC, 0x05FFE, - 0x05FFA, 0x06FFE, 0x0BFF6, 0x0BFFE, 0x0DF9E, 0x00DF8, - 0x0DFFE, 0x37FFC, 0x6FFFB, 0x5FFF8, 0xDF9AA, 0xDF9AB, - 0xDF9AC, 0xDF9AD, 0xDF9AE, 0xDF9AF, 0xDF9B0, 0xDF9B1, - 0xDF9B2, 0xDF9B3, 0x6FFFE, 0xDF9B4, 0xDF9B5, 0xDF9B6, - 0xDF9B7, 0xDF9B8, 0xDF9B9, 0xDF9BA, 0xDF9BB, 0xDF9BE, - 0xDF9BF, +const uint8_t ff_on2avc_scale_diff_syms[ON2AVC_SCALE_DIFFS] = { + 60, 59, 63, 53, 67, 50, 71, 74, 76, 79, 41, 81, 70, 48, 77, + 44, 95, 86, 88, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 111, 112, 113, 114, 115, 116, + 117, 118, 26, 119, 120, 34, 94, 30, 38, 82, 80, 39, 85, 36, 91, + 96, 97, 27, 98, 25, 110, 0, 56, 65, 52, 68, 61, 62, 54, 51, + 47, 72, 73, 45, 78, 42, 83, 37, 35, 32, 29, 66, 69, 49, 46, + 75, 43, 40, 84, 31, 33, 90, 92, 28, 87, 89, 93, 99, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 58, 57, 64, + 55 }; const uint8_t ff_on2avc_scale_diff_bits[ON2AVC_SCALE_DIFFS] = { - 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, - 20, 20, 20, 21, 21, 21, - 21, 21, 21, 21, 21, 21, - 21, 19, 20, 20, 16, 16, - 17, 15, 16, 15, 16, 15, - 15, 14, 13, 13, 13, 13, - 12, 11, 11, 10, 9, 9, - 9, 8, 8, 7, 7, 7, - 6, 5, 5, 4, 3, 3, - 2, 3, 4, 5, 5, 6, - 6, 7, 7, 7, 8, 9, - 9, 9, 10, 10, 11, 11, - 11, 12, 12, 13, 13, 13, - 13, 14, 14, 14, 16, 15, - 15, 16, 16, 16, 17, 13, - 17, 19, 20, 19, 21, 21, - 21, 21, 21, 21, 21, 21, - 21, 21, 20, 21, 21, 21, - 21, 21, 21, 21, 21, 21, - 21, -}; - -#define ON2AVC_CB1_CODES 41 -static const uint32_t on2avc_cb1_codes[ON2AVC_CB1_CODES] = { - 0x0000, 0x0022, 0x001C, 0x001B, 0x0024, 0x0030, - 0x0029, 0x0027, 0x0021, 0x002B, 0x002E, 0x0020, - 0x0026, 0x0033, 0x0031, 0x002C, 0x002A, 0x001E, - 0x0094, 0x01FF, 0x01F7, 0x012E, 0x001A, 0x01F5, - 0x007E, 0x012C, 0x01FC, 0x002D, 0x0032, 0x0028, - 0x002F, 0x001D, 0x01FD, 0x012D, 0x007C, 0x01F4, - 0x0023, 0x012F, 0x01F6, 0x01FE, 0x0095, -}; - -static const uint8_t on2avc_cb1_bits[ON2AVC_CB1_CODES] = { - 1, 6, 5, 5, 6, 6, - 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 5, - 8, 9, 9, 9, 5, 9, - 7, 9, 9, 6, 6, 6, - 6, 5, 9, 9, 7, 9, - 6, 9, 9, 9, 8, -}; - -static const uint16_t on2avc_cb1_syms[ON2AVC_CB1_CODES] = { - 0x0000, 0x0011, 0x001F, 0x00F1, 0x00FF, 0x0101, - 0x010F, 0x0110, 0x01F0, 0x0F01, 0x0F0F, 0x0F10, - 0x0FF0, 0x1001, 0x100F, 0x1010, 0x10F0, 0x1100, - 0x1111, 0x111F, 0x11F1, 0x11FF, 0x1F00, 0x1F11, - 0x1F1F, 0x1FF1, 0x1FFF, 0xF001, 0xF00F, 0xF010, - 0xF0F0, 0xF100, 0xF111, 0xF11F, 0xF1F1, 0xF1FF, - 0xFF00, 0xFF11, 0xFF1F, 0xFFF1, 0xFFFF, -}; - -#define ON2AVC_CB2_CODES 41 -static const uint32_t on2avc_cb2_codes[ON2AVC_CB2_CODES] = { - 0x0006, 0x0003, 0x001F, 0x001E, 0x0000, 0x0014, - 0x0009, 0x000E, 0x000D, 0x000C, 0x0015, 0x0008, - 0x0010, 0x000F, 0x0004, 0x0012, 0x0007, 0x0016, - 0x0005, 0x002F, 0x0017, 0x0006, 0x001D, 0x002C, - 0x005E, 0x0014, 0x0016, 0x0006, 0x0011, 0x000A, - 0x0013, 0x001C, 0x002D, 0x0015, 0x005F, 0x002E, - 0x0002, 0x0007, 0x005D, 0x005C, 0x0004, -}; - -static const uint8_t on2avc_cb2_bits[ON2AVC_CB2_CODES] = { - 3, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, - 7, 7, 7, 7, 5, 7, - 7, 7, 7, 5, 5, 5, - 5, 5, 7, 7, 7, 7, - 5, 7, 7, 7, 7, -}; - -static const uint16_t on2avc_cb2_syms[ON2AVC_CB2_CODES] = { - 0x0000, 0x0011, 0x001F, 0x00F1, 0x00FF, 0x0101, - 0x010F, 0x0110, 0x01F0, 0x0F01, 0x0F0F, 0x0F10, - 0x0FF0, 0x1001, 0x100F, 0x1010, 0x10F0, 0x1100, - 0x1111, 0x111F, 0x11F1, 0x11FF, 0x1F00, 0x1F11, - 0x1F1F, 0x1FF1, 0x1FFF, 0xF001, 0xF00F, 0xF010, - 0xF0F0, 0xF100, 0xF111, 0xF11F, 0xF1F1, 0xF1FF, - 0xFF00, 0xFF11, 0xFF1F, 0xFFF1, 0xFFFF, -}; - -#define ON2AVC_CB3_CODES 313 -static const uint32_t on2avc_cb3_codes[ON2AVC_CB3_CODES] = { - 0x00000, 0x00044, 0x00042, 0x00034, 0x0002E, 0x000CD, - 0x002DF, 0x0024A, 0x000CC, 0x0022E, 0x002D6, 0x00031, - 0x0003B, 0x00048, 0x00052, 0x00056, 0x001B8, 0x00160, - 0x001FA, 0x0015E, 0x0015C, 0x0014E, 0x0003C, 0x0010C, - 0x00166, 0x000CA, 0x0324C, 0x00FDA, 0x003DE, 0x002DB, - 0x0057F, 0x02C9E, 0x008BF, 0x0037F, 0x021DC, 0x00B1E, - 0x002DE, 0x002D2, 0x000C8, 0x014D6, 0x03576, 0x002CA, - 0x002CF, 0x003DB, 0x007FE, 0x01F7E, 0x005A3, 0x008BE, - 0x02D7E, 0x002D3, 0x0037E, 0x0004D, 0x0004C, 0x00041, - 0x0016A, 0x0010D, 0x0015D, 0x0011F, 0x00162, 0x0021E, - 0x00055, 0x00161, 0x001BE, 0x0004E, 0x0004A, 0x0004B, - 0x003EE, 0x00352, 0x0043A, 0x0033E, 0x0035C, 0x0036C, - 0x00050, 0x0032F, 0x003D6, 0x00039, 0x0067E, 0x00536, - 0x000FE, 0x001F4, 0x0036D, 0x007EF, 0x00CFE, 0x002D0, - 0x00F8C, 0x00D96, 0x001E9, 0x001F6, 0x00476, 0x00367, - 0x001F2, 0x01FF6, 0x016BB, 0x007FC, 0x00D5C, 0x00B24, - 0x00C92, 0x0014F, 0x01EA6, 0x01936, 0x00366, 0x0035E, - 0x00116, 0x00FBE, 0x01B5E, 0x0092F, 0x007EE, 0x00CEE, - 0x00B26, 0x0011E, 0x014DF, 0x035DE, 0x00030, 0x00473, - 0x005A2, 0x001BC, 0x000D6, 0x002DA, 0x00B5E, 0x007AA, - 0x002C8, 0x00D94, 0x00D97, 0x001AA, 0x001EE, 0x0003A, - 0x035DF, 0x03D4F, 0x0064F, 0x0064A, 0x02D73, 0x1ABBE, - 0x0B1CF, 0x00F8E, 0x06AFF, 0x0475E, 0x00472, 0x00596, - 0x003E7, 0x0036E, 0x00196, 0x0357E, 0x03F6E, 0x0324E, - 0x0324F, 0x0163B, 0x0192F, 0x001B4, 0x0326A, 0x02C9F, - 0x0021F, 0x0F8FF, 0x064D6, 0x007BE, 0x00DDF, 0x033BC, - 0x033BD, 0x06AEE, 0x00876, 0x07C7E, 0x0B1CE, 0x00D76, - 0x00DDC, 0x001EC, 0x0649B, 0x0B1CD, 0x00F8D, 0x007D6, - 0x01AEE, 0x0163F, 0x03E3E, 0x00A6A, 0x06D7E, 0x0DDDF, - 0x00F7E, 0x00DAE, 0x0036F, 0x00338, 0x0016C, 0x033BF, - 0x036BE, 0x01FF7, 0x01937, 0x01ABA, 0x014D7, 0x0014C, - 0x01F7F, 0x0475F, 0x00040, 0x07FFC, 0x03F6F, 0x00477, - 0x00496, 0x014DE, 0x0649A, 0x064D7, 0x02C9C, 0x0B1CC, - 0x1ABBF, 0x00648, 0x006BA, 0x00364, 0x0032E, 0x00126, - 0x03D4E, 0x02C72, 0x011D6, 0x01638, 0x01934, 0x02C9D, - 0x0016E, 0x021DD, 0x03DFF, 0x001F0, 0x07FFE, 0x043BF, - 0x00D5E, 0x00FAE, 0x0092E, 0x07FFF, 0x0F8FE, 0x02D7F, - 0x043BE, 0x06D7F, 0x008E9, 0x00FFA, 0x0021C, 0x06EEE, - 0x0D5DE, 0x00F57, 0x00CFF, 0x016BA, 0x07FFD, 0x06AFE, - 0x021DE, 0x0DDDE, 0x023AE, 0x00FAF, 0x006D6, 0x0037B, - 0x003E6, 0x001B9, 0x01F1E, 0x033BE, 0x0192E, 0x016BE, - 0x01FB6, 0x01BBA, 0x0019E, 0x03776, 0x03DFE, 0x00046, - 0x00051, 0x0004F, 0x003D7, 0x0033A, 0x00376, 0x00353, - 0x00356, 0x003EA, 0x00054, 0x00339, 0x003E2, 0x0002F, - 0x0064C, 0x00534, 0x00238, 0x001A8, 0x002C6, 0x00D95, - 0x00F52, 0x002CE, 0x007DE, 0x00B2F, 0x000D8, 0x001BA, - 0x0036A, 0x0035F, 0x00127, 0x01EFE, 0x016B8, 0x008EA, - 0x00CEC, 0x007EC, 0x00A6E, 0x00114, 0x01ABE, 0x00FFE, - 0x0037A, 0x0045E, 0x00124, 0x0163E, 0x02D72, 0x00CED, - 0x00B2E, 0x00C96, 0x007A8, 0x001FE, 0x0163A, 0x01FFE, - 0x00038, 0x0057E, 0x0064E, 0x001F8, 0x001E8, 0x002BE, - 0x00DDE, 0x00F56, 0x003DA, 0x00B25, 0x008E8, 0x001F9, - 0x00115, -}; - -static const uint8_t on2avc_cb3_bits[ON2AVC_CB3_CODES] = { - 1, 7, 7, 6, 6, 8, - 10, 10, 8, 10, 10, 6, - 6, 7, 7, 7, 9, 9, - 9, 9, 9, 9, 6, 9, - 9, 8, 14, 12, 10, 10, - 11, 14, 12, 10, 14, 12, - 10, 10, 8, 13, 14, 10, - 10, 10, 11, 13, 11, 12, - 14, 10, 10, 7, 7, 7, - 9, 9, 9, 9, 9, 10, - 7, 9, 9, 7, 7, 7, - 10, 10, 11, 10, 10, 10, - 7, 10, 10, 6, 11, 11, - 8, 9, 10, 11, 12, 10, - 12, 12, 9, 9, 11, 10, - 9, 13, 13, 11, 12, 12, - 12, 9, 13, 13, 10, 10, - 9, 12, 13, 12, 11, 12, - 12, 9, 13, 14, 6, 11, - 11, 9, 8, 10, 12, 11, - 10, 12, 12, 9, 9, 6, - 14, 14, 11, 11, 14, 17, - 16, 12, 15, 15, 11, 11, - 10, 10, 9, 14, 14, 14, - 14, 13, 13, 9, 14, 14, - 10, 16, 15, 11, 12, 14, - 14, 15, 12, 15, 16, 12, - 12, 9, 15, 16, 12, 11, - 13, 13, 14, 12, 15, 16, - 12, 12, 10, 10, 9, 14, - 14, 13, 13, 13, 13, 9, - 13, 15, 7, 15, 14, 11, - 11, 13, 15, 15, 14, 16, - 17, 11, 11, 10, 10, 9, - 14, 14, 13, 13, 13, 14, - 9, 14, 14, 9, 15, 15, - 12, 12, 12, 15, 16, 14, - 15, 15, 12, 12, 10, 15, - 16, 12, 12, 13, 15, 15, - 14, 16, 14, 12, 11, 10, - 10, 9, 13, 14, 13, 13, - 13, 13, 9, 14, 14, 7, - 7, 7, 10, 10, 10, 10, - 10, 10, 7, 10, 10, 6, - 11, 11, 10, 9, 10, 12, - 12, 10, 11, 12, 8, 9, - 10, 10, 9, 13, 13, 12, - 12, 11, 12, 9, 13, 12, - 10, 11, 9, 13, 14, 12, - 12, 12, 11, 9, 13, 13, - 6, 11, 11, 9, 9, 10, - 12, 12, 10, 12, 12, 9, - 9, -}; - -static const uint16_t on2avc_cb3_syms[ON2AVC_CB3_CODES] = { - 0x0000, 0x0002, 0x000E, 0x0011, 0x001F, 0x0020, - 0x0022, 0x002E, 0x00E0, 0x00E2, 0x00EE, 0x00F1, - 0x00FF, 0x0101, 0x010F, 0x0110, 0x0112, 0x011E, - 0x0121, 0x012F, 0x01E1, 0x01EF, 0x01F0, 0x01F2, - 0x01FE, 0x0200, 0x0202, 0x020E, 0x0211, 0x021F, - 0x0220, 0x0222, 0x022E, 0x02E0, 0x02E2, 0x02EE, - 0x02F1, 0x02FF, 0x0E00, 0x0E02, 0x0E0E, 0x0E11, - 0x0E1F, 0x0E20, 0x0E22, 0x0E2E, 0x0EE0, 0x0EE2, - 0x0EEE, 0x0EF1, 0x0EFF, 0x0F01, 0x0F0F, 0x0F10, - 0x0F12, 0x0F1E, 0x0F21, 0x0F2F, 0x0FE1, 0x0FEF, - 0x0FF0, 0x0FF2, 0x0FFE, 0x1001, 0x100F, 0x1010, - 0x1012, 0x101E, 0x1021, 0x102F, 0x10E1, 0x10EF, - 0x10F0, 0x10F2, 0x10FE, 0x1100, 0x1102, 0x110E, - 0x1111, 0x111F, 0x1120, 0x1122, 0x112E, 0x11E0, - 0x11E2, 0x11EE, 0x11F1, 0x11FF, 0x1201, 0x120F, - 0x1210, 0x1212, 0x121E, 0x1221, 0x122F, 0x12E1, - 0x12EF, 0x12F0, 0x12F2, 0x12FE, 0x1E01, 0x1E0F, - 0x1E10, 0x1E12, 0x1E1E, 0x1E21, 0x1E2F, 0x1EE1, - 0x1EEF, 0x1EF0, 0x1EF2, 0x1EFE, 0x1F00, 0x1F02, - 0x1F0E, 0x1F11, 0x1F1F, 0x1F20, 0x1F22, 0x1F2E, - 0x1FE0, 0x1FE2, 0x1FEE, 0x1FF1, 0x1FFF, 0x2000, - 0x2002, 0x200E, 0x2011, 0x201F, 0x2020, 0x2022, - 0x202E, 0x20E0, 0x20E2, 0x20EE, 0x20F1, 0x20FF, - 0x2101, 0x210F, 0x2110, 0x2112, 0x211E, 0x2121, - 0x212F, 0x21E1, 0x21EF, 0x21F0, 0x21F2, 0x21FE, - 0x2200, 0x2202, 0x220E, 0x2211, 0x221F, 0x2220, - 0x2222, 0x222E, 0x22E0, 0x22E2, 0x22EE, 0x22F1, - 0x22FF, 0x2E00, 0x2E02, 0x2E0E, 0x2E11, 0x2E1F, - 0x2E20, 0x2E22, 0x2E2E, 0x2EE0, 0x2EE2, 0x2EEE, - 0x2EF1, 0x2EFF, 0x2F01, 0x2F0F, 0x2F10, 0x2F12, - 0x2F1E, 0x2F21, 0x2F2F, 0x2FE1, 0x2FEF, 0x2FF0, - 0x2FF2, 0x2FFE, 0xE000, 0xE002, 0xE00E, 0xE011, - 0xE01F, 0xE020, 0xE022, 0xE02E, 0xE0E0, 0xE0E2, - 0xE0EE, 0xE0F1, 0xE0FF, 0xE101, 0xE10F, 0xE110, - 0xE112, 0xE11E, 0xE121, 0xE12F, 0xE1E1, 0xE1EF, - 0xE1F0, 0xE1F2, 0xE1FE, 0xE200, 0xE202, 0xE20E, - 0xE211, 0xE21F, 0xE220, 0xE222, 0xE22E, 0xE2E0, - 0xE2E2, 0xE2EE, 0xE2F1, 0xE2FF, 0xEE00, 0xEE02, - 0xEE0E, 0xEE11, 0xEE1F, 0xEE20, 0xEE22, 0xEE2E, - 0xEEE0, 0xEEE2, 0xEEEE, 0xEEF1, 0xEEFF, 0xEF01, - 0xEF0F, 0xEF10, 0xEF12, 0xEF1E, 0xEF21, 0xEF2F, - 0xEFE1, 0xEFEF, 0xEFF0, 0xEFF2, 0xEFFE, 0xF001, - 0xF00F, 0xF010, 0xF012, 0xF01E, 0xF021, 0xF02F, - 0xF0E1, 0xF0EF, 0xF0F0, 0xF0F2, 0xF0FE, 0xF100, - 0xF102, 0xF10E, 0xF111, 0xF11F, 0xF120, 0xF122, - 0xF12E, 0xF1E0, 0xF1E2, 0xF1EE, 0xF1F1, 0xF1FF, - 0xF201, 0xF20F, 0xF210, 0xF212, 0xF21E, 0xF221, - 0xF22F, 0xF2E1, 0xF2EF, 0xF2F0, 0xF2F2, 0xF2FE, - 0xFE01, 0xFE0F, 0xFE10, 0xFE12, 0xFE1E, 0xFE21, - 0xFE2F, 0xFEE1, 0xFEEF, 0xFEF0, 0xFEF2, 0xFEFE, - 0xFF00, 0xFF02, 0xFF0E, 0xFF11, 0xFF1F, 0xFF20, - 0xFF22, 0xFF2E, 0xFFE0, 0xFFE2, 0xFFEE, 0xFFF1, - 0xFFFF, -}; - -#define ON2AVC_CB4_CODES 313 -static const uint32_t on2avc_cb4_codes[ON2AVC_CB4_CODES] = { - 0x000A, 0x013B, 0x0127, 0x0004, 0x0015, 0x012C, - 0x065F, 0x08CD, 0x016A, 0x08E7, 0x06BA, 0x001B, - 0x001D, 0x0018, 0x000A, 0x0002, 0x00C0, 0x012B, - 0x00CE, 0x013C, 0x012A, 0x012D, 0x0020, 0x0128, - 0x0121, 0x00FC, 0x066B, 0x0472, 0x010A, 0x004E, - 0x06AE, 0x063F, 0x1ABF, 0x0B4E, 0x084E, 0x1ABE, - 0x010E, 0x0094, 0x00C8, 0x0464, 0x069A, 0x00C9, - 0x00FA, 0x041B, 0x2FDE, 0x08CB, 0x05B7, 0x1ABD, - 0x066A, 0x008D, 0x00F8, 0x0003, 0x001A, 0x001E, - 0x0120, 0x011E, 0x0138, 0x0125, 0x0170, 0x00C4, - 0x000B, 0x013E, 0x00C5, 0x000C, 0x000E, 0x001C, - 0x00FE, 0x009C, 0x010F, 0x0115, 0x009F, 0x008C, - 0x0008, 0x002E, 0x00CF, 0x001C, 0x0110, 0x002F, - 0x002C, 0x0002, 0x0116, 0x01FE, 0x032D, 0x00CB, - 0x030D, 0x02EC, 0x002E, 0x0037, 0x00CF, 0x0086, - 0x00C8, 0x032C, 0x031E, 0x01AC, 0x030C, 0x02ED, - 0x035C, 0x013A, 0x02FF, 0x02E2, 0x00BE, 0x00CE, - 0x0126, 0x0356, 0x034E, 0x0347, 0x025F, 0x0306, - 0x02DA, 0x0168, 0x02E7, 0x020F, 0x0016, 0x0081, - 0x0114, 0x0024, 0x001B, 0x010C, 0x03FE, 0x027F, - 0x0084, 0x02F9, 0x0237, 0x0000, 0x001A, 0x011A, - 0x05A6, 0x04A6, 0x00F9, 0x00CC, 0x05B6, 0x0BF6, - 0x0B96, 0x0446, 0x08CE, 0x007F, 0x002C, 0x000E, - 0x0080, 0x00C9, 0x00BA, 0x035E, 0x03EF, 0x0345, - 0x02FE, 0x02FB, 0x02E6, 0x00D2, 0x021C, 0x0238, - 0x06BB, 0x0B97, 0x007E, 0x01AA, 0x023A, 0x05BE, - 0x031D, 0x094E, 0x1ABC, 0x0948, 0x088E, 0x02E4, - 0x0273, 0x084C, 0x08CC, 0x094B, 0x02D2, 0x023B, - 0x043E, 0x2FDF, 0x063E, 0x109B, 0x08CA, 0x08E6, - 0x02DE, 0x02F4, 0x00D4, 0x002D, 0x00CA, 0x020E, - 0x0344, 0x02FD, 0x030F, 0x02EE, 0x02D6, 0x0123, - 0x02F7, 0x03ED, 0x009E, 0x05CA, 0x060E, 0x000D, - 0x004D, 0x0444, 0x043F, 0x094A, 0x05FA, 0x109A, - 0x0B4F, 0x00FD, 0x0117, 0x0096, 0x0082, 0x0122, - 0x025D, 0x0304, 0x034C, 0x027B, 0x035B, 0x02FC, - 0x00FC, 0x035F, 0x03EE, 0x088B, 0x0C1E, 0x088A, - 0x02F5, 0x0272, 0x17EE, 0x0C1F, 0x084F, 0x088F, - 0x069B, 0x0949, 0x023F, 0x02E3, 0x07FE, 0x041A, - 0x0B7E, 0x027A, 0x0336, 0x07FF, 0x08CF, 0x094F, - 0x065E, 0x0B7F, 0x02DD, 0x0212, 0x01FB, 0x00C6, - 0x0095, 0x00D0, 0x023E, 0x025C, 0x02FC, 0x032E, - 0x025E, 0x021E, 0x00BC, 0x021D, 0x035A, 0x0007, - 0x000F, 0x0006, 0x00C2, 0x000C, 0x00BD, 0x00CD, - 0x0113, 0x0118, 0x001D, 0x00CA, 0x008E, 0x0014, - 0x010D, 0x0085, 0x0001, 0x003E, 0x008F, 0x0236, - 0x030E, 0x00FF, 0x025E, 0x0337, 0x000A, 0x0026, - 0x010B, 0x009D, 0x012E, 0x025F, 0x02EF, 0x0305, - 0x02DC, 0x027E, 0x02FE, 0x0124, 0x034F, 0x003E, - 0x004F, 0x00BC, 0x016C, 0x02D7, 0x03EC, 0x02FA, - 0x02F8, 0x02F6, 0x01FA, 0x00CC, 0x02FF, 0x0334, - 0x001E, 0x004C, 0x0112, 0x0036, 0x0022, 0x00FE, - 0x031C, 0x0346, 0x0108, 0x020C, 0x001E, 0x0012, - 0x0026, -}; - -static const uint8_t on2avc_cb4_bits[ON2AVC_CB4_CODES] = { - 4, 9, 9, 6, 6, 9, - 11, 12, 9, 12, 11, 6, - 5, 6, 6, 6, 8, 9, - 8, 9, 9, 9, 6, 9, - 9, 9, 11, 11, 9, 9, - 11, 11, 13, 12, 12, 13, - 9, 9, 9, 11, 11, 9, - 9, 12, 14, 12, 11, 13, - 11, 9, 9, 6, 6, 6, - 9, 9, 9, 9, 9, 8, - 6, 9, 8, 6, 6, 6, - 8, 9, 9, 9, 9, 9, - 6, 9, 8, 5, 9, 9, - 6, 7, 9, 9, 10, 9, - 10, 10, 7, 6, 9, 9, - 8, 10, 10, 9, 10, 10, - 10, 9, 11, 10, 9, 9, - 9, 10, 10, 10, 10, 10, - 10, 9, 10, 11, 6, 9, - 9, 7, 7, 9, 10, 10, - 9, 10, 10, 7, 7, 9, - 11, 11, 9, 9, 11, 12, - 12, 11, 12, 12, 9, 9, - 9, 8, 8, 10, 11, 10, - 11, 10, 10, 8, 11, 10, - 11, 12, 12, 9, 10, 11, - 10, 12, 13, 12, 12, 10, - 10, 12, 12, 12, 10, 10, - 12, 14, 11, 13, 12, 12, - 10, 10, 8, 9, 8, 11, - 10, 11, 10, 10, 10, 9, - 10, 11, 9, 11, 11, 9, - 9, 11, 12, 12, 11, 13, - 12, 9, 9, 9, 9, 9, - 11, 10, 10, 10, 10, 11, - 8, 10, 11, 12, 12, 12, - 10, 10, 13, 12, 12, 12, - 11, 12, 10, 10, 11, 12, - 12, 10, 10, 11, 12, 12, - 11, 12, 10, 10, 9, 8, - 9, 8, 10, 11, 10, 10, - 11, 11, 8, 11, 10, 6, - 6, 6, 8, 9, 9, 9, - 9, 9, 6, 9, 9, 6, - 9, 9, 7, 6, 9, 10, - 10, 9, 10, 10, 7, 7, - 9, 9, 9, 11, 10, 10, - 10, 10, 10, 9, 10, 11, - 9, 9, 9, 10, 11, 10, - 10, 10, 9, 8, 10, 10, - 5, 9, 9, 6, 7, 9, - 10, 10, 9, 11, 10, 7, - 6, -}; - -static const uint16_t on2avc_cb4_syms[ON2AVC_CB4_CODES] = { - 0x0000, 0x0002, 0x000E, 0x0011, 0x001F, 0x0020, - 0x0022, 0x002E, 0x00E0, 0x00E2, 0x00EE, 0x00F1, - 0x00FF, 0x0101, 0x010F, 0x0110, 0x0112, 0x011E, - 0x0121, 0x012F, 0x01E1, 0x01EF, 0x01F0, 0x01F2, - 0x01FE, 0x0200, 0x0202, 0x020E, 0x0211, 0x021F, - 0x0220, 0x0222, 0x022E, 0x02E0, 0x02E2, 0x02EE, - 0x02F1, 0x02FF, 0x0E00, 0x0E02, 0x0E0E, 0x0E11, - 0x0E1F, 0x0E20, 0x0E22, 0x0E2E, 0x0EE0, 0x0EE2, - 0x0EEE, 0x0EF1, 0x0EFF, 0x0F01, 0x0F0F, 0x0F10, - 0x0F12, 0x0F1E, 0x0F21, 0x0F2F, 0x0FE1, 0x0FEF, - 0x0FF0, 0x0FF2, 0x0FFE, 0x1001, 0x100F, 0x1010, - 0x1012, 0x101E, 0x1021, 0x102F, 0x10E1, 0x10EF, - 0x10F0, 0x10F2, 0x10FE, 0x1100, 0x1102, 0x110E, - 0x1111, 0x111F, 0x1120, 0x1122, 0x112E, 0x11E0, - 0x11E2, 0x11EE, 0x11F1, 0x11FF, 0x1201, 0x120F, - 0x1210, 0x1212, 0x121E, 0x1221, 0x122F, 0x12E1, - 0x12EF, 0x12F0, 0x12F2, 0x12FE, 0x1E01, 0x1E0F, - 0x1E10, 0x1E12, 0x1E1E, 0x1E21, 0x1E2F, 0x1EE1, - 0x1EEF, 0x1EF0, 0x1EF2, 0x1EFE, 0x1F00, 0x1F02, - 0x1F0E, 0x1F11, 0x1F1F, 0x1F20, 0x1F22, 0x1F2E, - 0x1FE0, 0x1FE2, 0x1FEE, 0x1FF1, 0x1FFF, 0x2000, - 0x2002, 0x200E, 0x2011, 0x201F, 0x2020, 0x2022, - 0x202E, 0x20E0, 0x20E2, 0x20EE, 0x20F1, 0x20FF, - 0x2101, 0x210F, 0x2110, 0x2112, 0x211E, 0x2121, - 0x212F, 0x21E1, 0x21EF, 0x21F0, 0x21F2, 0x21FE, - 0x2200, 0x2202, 0x220E, 0x2211, 0x221F, 0x2220, - 0x2222, 0x222E, 0x22E0, 0x22E2, 0x22EE, 0x22F1, - 0x22FF, 0x2E00, 0x2E02, 0x2E0E, 0x2E11, 0x2E1F, - 0x2E20, 0x2E22, 0x2E2E, 0x2EE0, 0x2EE2, 0x2EEE, - 0x2EF1, 0x2EFF, 0x2F01, 0x2F0F, 0x2F10, 0x2F12, - 0x2F1E, 0x2F21, 0x2F2F, 0x2FE1, 0x2FEF, 0x2FF0, - 0x2FF2, 0x2FFE, 0xE000, 0xE002, 0xE00E, 0xE011, - 0xE01F, 0xE020, 0xE022, 0xE02E, 0xE0E0, 0xE0E2, - 0xE0EE, 0xE0F1, 0xE0FF, 0xE101, 0xE10F, 0xE110, - 0xE112, 0xE11E, 0xE121, 0xE12F, 0xE1E1, 0xE1EF, - 0xE1F0, 0xE1F2, 0xE1FE, 0xE200, 0xE202, 0xE20E, - 0xE211, 0xE21F, 0xE220, 0xE222, 0xE22E, 0xE2E0, - 0xE2E2, 0xE2EE, 0xE2F1, 0xE2FF, 0xEE00, 0xEE02, - 0xEE0E, 0xEE11, 0xEE1F, 0xEE20, 0xEE22, 0xEE2E, - 0xEEE0, 0xEEE2, 0xEEEE, 0xEEF1, 0xEEFF, 0xEF01, - 0xEF0F, 0xEF10, 0xEF12, 0xEF1E, 0xEF21, 0xEF2F, - 0xEFE1, 0xEFEF, 0xEFF0, 0xEFF2, 0xEFFE, 0xF001, - 0xF00F, 0xF010, 0xF012, 0xF01E, 0xF021, 0xF02F, - 0xF0E1, 0xF0EF, 0xF0F0, 0xF0F2, 0xF0FE, 0xF100, - 0xF102, 0xF10E, 0xF111, 0xF11F, 0xF120, 0xF122, - 0xF12E, 0xF1E0, 0xF1E2, 0xF1EE, 0xF1F1, 0xF1FF, - 0xF201, 0xF20F, 0xF210, 0xF212, 0xF21E, 0xF221, - 0xF22F, 0xF2E1, 0xF2EF, 0xF2F0, 0xF2F2, 0xF2FE, - 0xFE01, 0xFE0F, 0xFE10, 0xFE12, 0xFE1E, 0xFE21, - 0xFE2F, 0xFEE1, 0xFEEF, 0xFEF0, 0xFEF2, 0xFEFE, - 0xFF00, 0xFF02, 0xFF0E, 0xFF11, 0xFF1F, 0xFF20, - 0xFF22, 0xFF2E, 0xFFE0, 0xFFE2, 0xFFEE, 0xFFF1, - 0xFFFF, -}; - -#define ON2AVC_CB5_CODES 1201 -static const uint32_t on2avc_cb5_codes[ON2AVC_CB5_CODES] = { - 0x00000, 0x000D6, 0x000E2, 0x00044, 0x0009E, 0x0009A, - 0x0003A, 0x004E6, 0x00A29, 0x007FE, 0x0024A, 0x004EE, - 0x00496, 0x001EE, 0x001C8, 0x008FA, 0x0050F, 0x001EF, - 0x00486, 0x00906, 0x00904, 0x0003E, 0x00094, 0x000A6, - 0x00046, 0x00061, 0x0012A, 0x0020D, 0x00060, 0x00066, - 0x00452, 0x00692, 0x0087E, 0x00242, 0x0050C, 0x008BE, - 0x0024C, 0x0045A, 0x0025A, 0x001C6, 0x002EE, 0x00294, - 0x006CE, 0x001EC, 0x00492, 0x00690, 0x00055, 0x00474, - 0x0063E, 0x00524, 0x04802, 0x04DC5, 0x00DEF, 0x01A62, - 0x00E6A, 0x00A7F, 0x027FB, 0x034B5, 0x036C5, 0x00A3A, - 0x036C6, 0x0219B, 0x00296, 0x0090F, 0x027FA, 0x028C8, - 0x0052A, 0x0127E, 0x0598E, 0x034B4, 0x00C78, 0x0146E, - 0x00F5F, 0x00BAA, 0x00432, 0x0FF63, 0x0598F, 0x0091C, - 0x00257, 0x0240B, 0x014E6, 0x00E6B, 0x05173, 0x01647, - 0x007F9, 0x022F3, 0x04DC6, 0x022F2, 0x0087F, 0x036C7, - 0x01AB9, 0x00C79, 0x06944, 0x043C6, 0x0043E, 0x00218, - 0x031C4, 0x014E5, 0x0093E, 0x0FF62, 0x3FAE0, 0x00328, - 0x00228, 0x01428, 0x03FEA, 0x007A3, 0x034B3, 0x0D23B, - 0x00B29, 0x01AB8, 0x028C7, 0x0598D, 0x00B28, 0x0149B, - 0x0149A, 0x008EE, 0x027F9, 0x07FC0, 0x00CFE, 0x0025E, - 0x01CBB, 0x026EF, 0x00512, 0x0297B, 0x05172, 0x00D36, - 0x00FCA, 0x01EA5, 0x00D86, 0x01FC5, 0x031C3, 0x02CD6, - 0x00276, 0x01F8A, 0x04801, 0x00B2A, 0x00329, 0x00FC9, - 0x03F0C, 0x00D35, 0x01971, 0x04DC4, 0x036C4, 0x00A4F, - 0x00FEA, 0x01FC4, 0x0122A, 0x00058, 0x001CA, 0x0013A, - 0x0005E, 0x00054, 0x0053E, 0x0039E, 0x006C6, 0x00284, - 0x001C2, 0x0087A, 0x0020E, 0x0050E, 0x006F2, 0x00288, - 0x0029E, 0x00457, 0x006F9, 0x005D3, 0x00248, 0x008F7, - 0x00068, 0x0069D, 0x00497, 0x0005F, 0x0091D, 0x00738, - 0x00057, 0x0005A, 0x00A3E, 0x009CF, 0x00D3E, 0x00D87, - 0x00C6B, 0x00CBD, 0x003F6, 0x00A74, 0x00C6E, 0x0049C, - 0x012FE, 0x0137F, 0x00DBB, 0x010DA, 0x00CAB, 0x0127F, - 0x00056, 0x00A2A, 0x0083E, 0x00040, 0x00BAE, 0x00BA2, - 0x0012E, 0x006F0, 0x0096E, 0x0022C, 0x00FDE, 0x011EB, - 0x01ABE, 0x007EA, 0x014E7, 0x011F2, 0x00256, 0x009FC, - 0x0297C, 0x01C13, 0x006F4, 0x00B26, 0x0144E, 0x021EE, - 0x001C0, 0x00707, 0x00B3F, 0x00244, 0x00E0B, 0x02CD8, - 0x034B6, 0x00B2B, 0x00914, 0x027FD, 0x028CA, 0x01396, - 0x014EB, 0x01972, 0x01B71, 0x013BE, 0x00D9A, 0x00D3F, - 0x009C9, 0x014EA, 0x031C6, 0x022F5, 0x027FC, 0x0240D, - 0x0297D, 0x006F5, 0x02CD7, 0x0396A, 0x0018C, 0x04DC7, - 0x028CB, 0x007E7, 0x0D23C, 0x043C8, 0x008FC, 0x00C7A, - 0x031C7, 0x018EB, 0x0396B, 0x0D23D, 0x036C9, 0x01973, - 0x018EA, 0x07FC1, 0x08FD8, 0x01673, 0x0067C, 0x027FE, - 0x036C8, 0x004BE, 0x08FD9, 0x07FC2, 0x009B6, 0x00148, - 0x026F0, 0x05174, 0x0071C, 0x07279, 0x08FD7, 0x005D4, - 0x00E0A, 0x01A63, 0x01F8B, 0x0114E, 0x01ABA, 0x05990, - 0x043C7, 0x01BEE, 0x3FAE1, 0x1FE94, 0x01CBE, 0x006F3, - 0x018E7, 0x0240C, 0x006FA, 0x03967, 0x08FD6, 0x0045B, - 0x00DBA, 0x01A65, 0x03969, 0x00CFF, 0x0067E, 0x026F1, - 0x028C9, 0x022F4, 0x018D2, 0x01B70, 0x011EA, 0x00BBF, - 0x00B3E, 0x0144D, 0x00D3D, 0x0146F, 0x01A64, 0x01FFF, - 0x01B6F, 0x03968, 0x024EB, 0x00656, 0x031C5, 0x0727A, - 0x0003C, 0x00D22, 0x00D99, 0x0021A, 0x00706, 0x007EE, - 0x0013E, 0x00CBC, 0x01C12, 0x01A66, 0x0022E, 0x00E77, - 0x01672, 0x004D8, 0x006D3, 0x01CBF, 0x01ABB, 0x008BF, - 0x00E76, 0x01BEF, 0x01FC6, 0x001B2, 0x00736, 0x008FB, - 0x0021D, 0x000D7, 0x04804, 0x06948, 0x00D37, 0x0396E, - 0x06949, 0x0120A, 0x03F0F, 0x1437E, 0x043CB, 0x028D0, - 0x0A2BE, 0x08FDD, 0x05996, 0x022F6, 0x1FE96, 0x0FF64, - 0x026F2, 0x028CF, 0x04DCB, 0x03F0E, 0x00A3F, 0x05178, - 0x05995, 0x00BA3, 0x00A4A, 0x07FC8, 0x0727E, 0x007AA, - 0x003D0, 0x0599A, 0x02CDB, 0x034BB, 0x07FC9, 0x0D261, - 0x04805, 0x04806, 0x0727F, 0x022F7, 0x018FE, 0x0240F, - 0x02CDA, 0x031CB, 0x04DCC, 0x034BA, 0x036CB, 0x0052B, - 0x05997, 0x036CE, 0x00907, 0x08FDF, 0x043CD, 0x00E7E, - 0x0517A, 0x04DCD, 0x0197E, 0x0A2BF, 0x028D1, 0x04807, - 0x028D2, 0x04808, 0x0D262, 0x024ED, 0x01ABF, 0x072C0, - 0x1437F, 0x034BE, 0x05179, 0x144F0, 0x072C1, 0x029C1, - 0x08FDE, 0x043CC, 0x023AE, 0x00A3B, 0x1FE97, 0x08FE1, - 0x0142A, 0x006AC, 0x04809, 0x024EE, 0x00C7B, 0x3FAE3, - 0x08FE2, 0x01F8F, 0x0A2C0, 0x023AF, 0x08FE3, 0x02416, - 0x072C2, 0x0FF65, 0x00FCB, 0x08FE0, 0x144F1, 0x01EA6, - 0x00590, 0x04DCE, 0x0396F, 0x01FC7, 0x05991, 0x3FAE2, - 0x0096C, 0x00657, 0x034B8, 0x05992, 0x0240E, 0x0A2BC, - 0x08FDA, 0x0114F, 0x0727C, 0x06945, 0x05175, 0x01B72, - 0x0727B, 0x07FC3, 0x01472, 0x0A2BB, 0x0D23E, 0x00CBE, - 0x00636, 0x034B7, 0x043C9, 0x008AA, 0x08FDB, 0x0D23F, - 0x02852, 0x0727D, 0x05994, 0x00E3E, 0x031CA, 0x06947, - 0x04DC8, 0x02CD9, 0x1FE95, 0x0D260, 0x028CD, 0x024EC, - 0x04803, 0x07FC4, 0x01976, 0x028CC, 0x05993, 0x07FC5, - 0x027FF, 0x06946, 0x03FEB, 0x03F0D, 0x0096D, 0x08FDC, - 0x04DC9, 0x0097E, 0x003D3, 0x0A2BD, 0x0286E, 0x07FC6, - 0x07FC7, 0x034B9, 0x029C0, 0x01F8E, 0x04DCA, 0x05177, - 0x01977, 0x03FEE, 0x0297E, 0x028CE, 0x036CA, 0x05176, - 0x0297F, 0x00596, 0x02853, 0x043CA, 0x0090E, 0x144FA, - 0x0D26A, 0x008AB, 0x000CE, 0x072C3, 0x034BF, 0x02417, - 0x3FAF0, 0x3FAEF, 0x026F3, 0x1FEA0, 0x3FAF1, 0x1FE9F, - 0x0D269, 0x0FF6A, 0x1FE9D, 0x029C6, 0x3FAEE, 0x1FE9E, - 0x036CF, 0x001AA, 0x0480E, 0x0A2C7, 0x000A0, 0x07FCE, - 0x3FAF4, 0x008F8, 0x3FAF5, 0x144FB, 0x00A16, 0x024EF, - 0x04DD3, 0x0694E, 0x1FEA2, 0x3FAF7, 0x3FAF6, 0x0D26B, - 0x04DD2, 0x3FAF2, 0x1FEA1, 0x08FE6, 0x0122B, 0x08FE7, - 0x0480F, 0x00C6F, 0x0FF6B, 0x3FAF3, 0x008EF, 0x00C7E, - 0x3FAF8, 0x1FEA4, 0x00DF6, 0x00362, 0x0694F, 0x0599B, - 0x0142B, 0x1FEA6, 0x1FEA5, 0x03FEF, 0x07FCF, 0x1FEA7, - 0x3FAF9, 0x029C7, 0x0D26E, 0x144FE, 0x01C3E, 0x1FEA3, - 0x0A2CA, 0x01CE6, 0x0049E, 0x043CF, 0x04EFE, 0x0036B, - 0x3FAFE, 0x11F32, 0x01EAE, 0x1FEAA, 0x0D26F, 0x049D2, - 0x02EAE, 0x0356A, 0x08FEA, 0x07ABE, 0x08FEB, 0x3FAFF, - 0x1FEAB, 0x0292E, 0x144FF, 0x3FAFA, 0x08FE8, 0x01EA7, - 0x0B27A, 0x0A2CB, 0x0164E, 0x3FAFB, 0x08FE9, 0x021EF, - 0x00A76, 0x1FE9A, 0x144F2, 0x029C3, 0x3FAE8, 0x3FAE7, - 0x014EE, 0x03F12, 0x0D264, 0x08FE4, 0x0FF67, 0x1FE9B, - 0x144F3, 0x0FF66, 0x0D263, 0x3FAE5, 0x3FAE4, 0x029C2, - 0x031FE, 0x0A2C1, 0x1FE98, 0x01FD6, 0x3FAE6, 0x1FE99, - 0x01473, 0x00D9B, 0x144F5, 0x144F4, 0x00FD2, 0x0036A, - 0x043CE, 0x03F13, 0x0517B, 0x0D267, 0x144F6, 0x01756, - 0x0A2C2, 0x144F8, 0x144F7, 0x0480A, 0x0FF68, 0x0D265, - 0x01B73, 0x0D266, 0x3FAE9, 0x01A67, 0x00493, 0x0694B, - 0x0694A, 0x00082, 0x03F7E, 0x04DCF, 0x009B7, 0x3FAEB, - 0x1FE9C, 0x0071D, 0x028D3, 0x0D268, 0x0A2C5, 0x0A2C6, - 0x3FAED, 0x3FAEC, 0x08FE5, 0x07FCA, 0x3FAEA, 0x144F9, - 0x0A2C3, 0x00D3C, 0x07FCB, 0x0480B, 0x009CA, 0x0FF69, - 0x0A2C4, 0x0091E, 0x007EB, 0x1FE85, 0x0FF56, 0x0091F, - 0x0019E, 0x0693A, 0x0593E, 0x020FC, 0x1FE86, 0x0FF57, - 0x027F4, 0x0146A, 0x04BFC, 0x0CBF9, 0x0CBF8, 0x1FE83, - 0x3F7F5, 0x08F9E, 0x3F7F6, 0x1FE84, 0x036C0, 0x00098, - 0x0593C, 0x071F9, 0x0006E, 0x0593F, 0x03963, 0x00A3C, - 0x13BFD, 0x1FE89, 0x007F2, 0x00FD3, 0x03F08, 0x03D5E, - 0x034A9, 0x13BFF, 0x13BFE, 0x071FA, 0x011E8, 0x1FE87, - 0x3F7F7, 0x0FF58, 0x01B66, 0x07FB8, 0x05168, 0x0070E, - 0x0FF59, 0x1FE88, 0x009B3, 0x00BBC, 0x1FE8B, 0x3F7F8, - 0x00FE6, 0x004FC, 0x0CBFC, 0x03FE6, 0x022F0, 0x1FE8C, - 0x0CBFD, 0x01CE7, 0x08F9F, 0x0FF5A, 0x071FD, 0x1FE8A, - 0x071FB, 0x14378, 0x01AB4, 0x0CBFB, 0x0CBFA, 0x036C1, - 0x0037E, 0x05980, 0x071FC, 0x00D5E, 0x3F7FC, 0x08FD0, - 0x014EF, 0x3F7FE, 0x3F7FD, 0x01CFE, 0x01FBE, 0x05982, - 0x1437A, 0x04BFD, 0x1FE8E, 0x3F7FF, 0x071FF, 0x0FF5B, - 0x1FE8D, 0x3F7F9, 0x14379, 0x047F7, 0x05981, 0x071FE, - 0x014E2, 0x3F7FB, 0x3F7FA, 0x02CCE, 0x0037F, 0x0A27E, - 0x3D5FA, 0x02CCC, 0x1FE80, 0x1FD7E, 0x01496, 0x018E4, - 0x3D5FB, 0x05164, 0x070FD, 0x3D5FC, 0x11F33, 0x0277E, - 0x0FF54, 0x08F98, 0x07FB6, 0x070FC, 0x026E8, 0x07FB7, - 0x034A6, 0x0356B, 0x3D5F9, 0x3D5F8, 0x034A8, 0x0114C, - 0x3F7F0, 0x3D5FF, 0x00C74, 0x0024D, 0x05167, 0x049D3, - 0x0292F, 0x08F9C, 0x3F7F1, 0x01CB6, 0x03962, 0x070FF, - 0x08F9D, 0x08F9A, 0x3D5FD, 0x0A2B0, 0x024E8, 0x070FE, - 0x3D5FE, 0x01A5E, 0x00392, 0x08F9B, 0x05166, 0x00099, - 0x06939, 0x06938, 0x009B2, 0x0C7FE, 0x3F7F4, 0x007F7, - 0x011D6, 0x02EAF, 0x028BE, 0x071F8, 0x0C7FF, 0x1FE82, - 0x047F6, 0x06936, 0x3F7F3, 0x3F7F2, 0x1FE81, 0x026EA, - 0x0C7FC, 0x0B27B, 0x009FA, 0x0C7FD, 0x13BFC, 0x007A8, - 0x000D4, 0x08FD1, 0x0D234, 0x00D34, 0x07274, 0x05988, - 0x00F5C, 0x0516D, 0x0516E, 0x0516C, 0x036C3, 0x0A2B4, - 0x0D235, 0x036C2, 0x034AC, 0x0D233, 0x07FBA, 0x034AB, - 0x0A2B3, 0x1437D, 0x1437C, 0x00B3B, 0x07273, 0x0516B, - 0x00D84, 0x009FB, 0x0693F, 0x0598A, 0x007F8, 0x005D6, - 0x047FB, 0x024EA, 0x026EC, 0x0516F, 0x047FC, 0x031A7, - 0x01397, 0x026ED, 0x02975, 0x02CD1, 0x034AD, 0x07275, - 0x027F6, 0x05989, 0x043C1, 0x0693E, 0x00454, 0x034AE, - 0x043C2, 0x007F6, 0x0A2B7, 0x07FBB, 0x02408, 0x0598B, - 0x047FD, 0x01B6A, 0x04DC1, 0x0FF5F, 0x07FBC, 0x01B6B, - 0x07277, 0x0D236, 0x020FD, 0x01B68, 0x0A2B5, 0x0FF5E, - 0x02976, 0x043C3, 0x02977, 0x0A2B6, 0x012DE, 0x07276, - 0x03FE9, 0x01B69, 0x00A4C, 0x0FF60, 0x1FE93, 0x013BC, - 0x00592, 0x02978, 0x02CD3, 0x00D8E, 0x0D237, 0x05170, - 0x01FC1, 0x028C2, 0x06941, 0x0D238, 0x07278, 0x034AF, - 0x06940, 0x00E5E, 0x08FD2, 0x07FBD, 0x020FE, 0x007E6, - 0x043C4, 0x02CD2, 0x0166E, 0x0CBFF, 0x0CBFE, 0x00A5C, - 0x005D0, 0x026EB, 0x047F8, 0x01F88, 0x1FE90, 0x1FE8F, - 0x00C68, 0x021EC, 0x0A2B1, 0x0D230, 0x04BFE, 0x0693B, - 0x028BF, 0x028C0, 0x07270, 0x0FF5C, 0x00E08, 0x00360, - 0x0436C, 0x05983, 0x009BE, 0x0FF5D, 0x1FE91, 0x01A60, - 0x04BFF, 0x0A2B2, 0x0436E, 0x03F0A, 0x07FB9, 0x05984, - 0x01FC0, 0x1FE92, 0x1437B, 0x01646, 0x03F09, 0x0693C, - 0x027F5, 0x047F9, 0x034AA, 0x0D231, 0x0436D, 0x01AB6, - 0x047FA, 0x07271, 0x00CFA, 0x006CF, 0x07272, 0x05986, - 0x00B3A, 0x00654, 0x028C1, 0x0436F, 0x02CD0, 0x03FE8, - 0x05987, 0x043C0, 0x0146B, 0x02974, 0x031A6, 0x02CCF, - 0x03964, 0x04DC0, 0x0516A, 0x05985, 0x05169, 0x02406, - 0x003D6, 0x0D232, 0x0693D, 0x0005C, 0x006F6, 0x0086E, - 0x00062, 0x0005B, 0x006F1, 0x007E0, 0x00D98, 0x00BBE, - 0x00E72, 0x00D8F, 0x004DA, 0x0137B, 0x0137A, 0x00386, - 0x00A7E, 0x00C6A, 0x00CBA, 0x00F5E, 0x00F5D, 0x013BD, - 0x00064, 0x009CE, 0x008EC, 0x0003B, 0x00F56, 0x00CAA, - 0x00246, 0x008ED, 0x0086C, 0x001ED, 0x00C77, 0x0240A, - 0x01B6D, 0x0086F, 0x02CD5, 0x01FC3, 0x0073E, 0x005D2, - 0x01970, 0x014E4, 0x00456, 0x00B22, 0x0114D, 0x02198, - 0x00138, 0x0069C, 0x00737, 0x0020C, 0x00A4E, 0x04DC2, - 0x018E6, 0x00E1E, 0x006D2, 0x047FF, 0x02979, 0x01FFE, - 0x04800, 0x021ED, 0x028C6, 0x00917, 0x01671, 0x01CFF, - 0x00CFB, 0x00FE7, 0x00A1A, 0x0146D, 0x01670, 0x01B6E, - 0x0137E, 0x006D1, 0x01FFD, 0x028C5, 0x00176, 0x05171, - 0x0219A, 0x0023C, 0x0A2BA, 0x043C5, 0x006F8, 0x006DF, - 0x01EA4, 0x01CBA, 0x027F8, 0x0FF61, 0x08FD5, 0x0177B, - 0x02199, 0x0D23A, 0x03966, 0x0297A, 0x00A38, 0x0177A, - 0x01A61, 0x00597, 0x07FBF, 0x04DC3, 0x007F4, 0x00196, - 0x034B0, 0x03F0B, 0x008F6, 0x0598C, 0x08FD3, 0x003D2, - 0x006D0, 0x01FC2, 0x031C1, 0x026EE, 0x0A2B9, 0x0D239, - 0x0175F, 0x0175E, 0x031C0, 0x06942, 0x01FF6, 0x00A3D, - 0x0166F, 0x027F7, 0x009C8, 0x0A2B8, 0x07FBE, 0x00734, - 0x00FC6, 0x03965, 0x06943, 0x010CF, 0x006DE, 0x02CD4, - 0x08FD4, 0x034B2, 0x01CB8, 0x028C3, 0x01FFC, 0x0041E, - 0x0146C, 0x01B6C, 0x00C76, 0x00B3C, 0x010CE, 0x022F1, - 0x0144C, 0x012DF, 0x01436, 0x0073A, 0x034B1, 0x031C2, - 0x00042, 0x00DEE, 0x00B3D, 0x001CC, 0x00A17, 0x007E8, - 0x0021C, 0x00A28, 0x01CB9, 0x02409, 0x00916, 0x020FF, - 0x047FE, 0x00726, 0x00238, 0x011E9, 0x01AB7, 0x0071E, - 0x00FC8, 0x028C4, 0x00D85, 0x00239, 0x008EA, 0x007A2, - 0x0012C, -}; - -static const uint8_t on2avc_cb5_bits[ON2AVC_CB5_CODES] = { - 1, 8, 8, 7, 8, 8, - 6, 11, 12, 11, 10, 11, - 11, 9, 9, 12, 11, 9, - 11, 12, 12, 6, 8, 8, - 7, 7, 9, 10, 7, 7, - 11, 11, 12, 10, 11, 12, - 10, 11, 10, 9, 10, 10, - 11, 9, 11, 11, 7, 11, - 11, 11, 15, 15, 12, 13, - 12, 12, 14, 14, 14, 12, - 14, 14, 10, 12, 14, 14, - 11, 13, 15, 14, 12, 13, - 12, 12, 11, 16, 15, 12, - 10, 14, 13, 12, 15, 13, - 11, 14, 15, 14, 12, 14, - 13, 12, 15, 15, 11, 10, - 14, 13, 12, 16, 18, 10, - 10, 13, 14, 11, 14, 16, - 12, 13, 14, 15, 12, 13, - 13, 12, 14, 15, 12, 10, - 13, 14, 11, 14, 15, 12, - 12, 13, 12, 13, 14, 14, - 10, 13, 15, 12, 10, 12, - 14, 12, 13, 15, 14, 12, - 12, 13, 13, 7, 9, 9, - 7, 7, 11, 10, 11, 10, - 9, 12, 10, 11, 11, 10, - 10, 11, 11, 11, 10, 12, - 7, 11, 11, 7, 12, 11, - 7, 7, 12, 12, 12, 12, - 12, 12, 10, 12, 12, 11, - 13, 13, 12, 13, 12, 13, - 7, 12, 12, 7, 12, 12, - 9, 11, 12, 10, 12, 13, - 13, 11, 13, 13, 10, 12, - 14, 13, 11, 12, 13, 14, - 9, 11, 12, 10, 12, 14, - 14, 12, 12, 14, 14, 13, - 13, 13, 13, 13, 12, 12, - 12, 13, 14, 14, 14, 14, - 14, 11, 14, 14, 9, 15, - 14, 11, 16, 15, 12, 12, - 14, 13, 14, 16, 14, 13, - 13, 15, 16, 13, 11, 14, - 14, 11, 16, 15, 12, 9, - 14, 15, 11, 15, 16, 11, - 12, 13, 13, 13, 13, 15, - 15, 13, 18, 17, 13, 11, - 13, 14, 11, 14, 16, 11, - 12, 13, 14, 12, 11, 14, - 14, 14, 13, 13, 13, 12, - 12, 13, 12, 13, 13, 13, - 13, 14, 14, 11, 14, 15, - 6, 12, 12, 10, 11, 11, - 9, 12, 13, 13, 10, 12, - 13, 11, 11, 13, 13, 12, - 12, 13, 13, 9, 11, 12, - 10, 8, 15, 15, 12, 14, - 15, 13, 14, 17, 15, 14, - 16, 16, 15, 14, 17, 16, - 14, 14, 15, 14, 12, 15, - 15, 12, 12, 15, 15, 11, - 10, 15, 14, 14, 15, 16, - 15, 15, 15, 14, 13, 14, - 14, 14, 15, 14, 14, 11, - 15, 14, 12, 16, 15, 12, - 15, 15, 13, 16, 14, 15, - 14, 15, 16, 14, 13, 15, - 17, 14, 15, 17, 15, 14, - 16, 15, 14, 12, 17, 16, - 13, 11, 15, 14, 12, 18, - 16, 13, 16, 14, 16, 14, - 15, 16, 12, 16, 17, 13, - 11, 15, 14, 13, 15, 18, - 12, 11, 14, 15, 14, 16, - 16, 13, 15, 15, 15, 13, - 15, 15, 13, 16, 16, 12, - 11, 14, 15, 12, 16, 16, - 14, 15, 15, 12, 14, 15, - 15, 14, 17, 16, 14, 14, - 15, 15, 13, 14, 15, 15, - 14, 15, 14, 14, 12, 16, - 15, 12, 10, 16, 14, 15, - 15, 14, 14, 13, 15, 15, - 13, 14, 14, 14, 14, 15, - 14, 11, 14, 15, 12, 17, - 16, 12, 8, 15, 14, 14, - 18, 18, 14, 17, 18, 17, - 16, 16, 17, 14, 18, 17, - 14, 9, 15, 16, 8, 15, - 18, 12, 18, 17, 12, 14, - 15, 15, 17, 18, 18, 16, - 15, 18, 17, 16, 13, 16, - 15, 12, 16, 18, 12, 12, - 18, 17, 12, 10, 15, 15, - 13, 17, 17, 14, 15, 17, - 18, 14, 16, 17, 13, 17, - 16, 13, 11, 15, 15, 10, - 18, 17, 13, 17, 16, 15, - 14, 14, 16, 15, 16, 18, - 17, 14, 17, 18, 16, 13, - 16, 16, 13, 18, 16, 14, - 12, 17, 17, 14, 18, 18, - 13, 14, 16, 16, 16, 17, - 17, 16, 16, 18, 18, 14, - 14, 16, 17, 13, 18, 17, - 13, 12, 17, 17, 12, 10, - 15, 14, 15, 16, 17, 13, - 16, 17, 17, 15, 16, 16, - 13, 16, 18, 13, 11, 15, - 15, 8, 14, 15, 12, 18, - 17, 11, 14, 16, 16, 16, - 18, 18, 16, 15, 18, 17, - 16, 12, 15, 15, 12, 16, - 16, 12, 11, 17, 16, 12, - 9, 15, 15, 14, 17, 16, - 14, 13, 15, 16, 16, 17, - 18, 16, 18, 17, 14, 8, - 15, 15, 7, 15, 14, 12, - 17, 17, 11, 12, 14, 14, - 14, 17, 17, 15, 13, 17, - 18, 16, 13, 15, 15, 11, - 16, 17, 12, 12, 17, 18, - 12, 11, 16, 14, 14, 17, - 16, 13, 16, 16, 15, 17, - 15, 17, 13, 16, 16, 14, - 10, 15, 15, 12, 18, 16, - 13, 18, 18, 13, 13, 15, - 17, 15, 17, 18, 15, 16, - 17, 18, 17, 15, 15, 15, - 13, 18, 18, 14, 10, 16, - 18, 14, 17, 17, 13, 13, - 18, 15, 15, 18, 17, 14, - 16, 16, 15, 15, 14, 15, - 14, 14, 18, 18, 14, 13, - 18, 18, 12, 10, 15, 15, - 14, 16, 18, 13, 14, 15, - 16, 16, 18, 16, 14, 15, - 18, 13, 10, 16, 15, 8, - 15, 15, 12, 16, 18, 11, - 13, 14, 14, 15, 16, 17, - 15, 15, 18, 18, 17, 14, - 16, 16, 12, 16, 17, 11, - 8, 16, 16, 12, 15, 15, - 12, 15, 15, 15, 14, 16, - 16, 14, 14, 16, 15, 14, - 16, 17, 17, 12, 15, 15, - 12, 12, 15, 15, 11, 11, - 15, 14, 14, 15, 15, 14, - 13, 14, 14, 14, 14, 15, - 14, 15, 15, 15, 11, 14, - 15, 11, 16, 15, 14, 15, - 15, 13, 15, 16, 15, 13, - 15, 16, 14, 13, 16, 16, - 14, 15, 14, 16, 13, 15, - 14, 13, 12, 16, 17, 13, - 11, 14, 14, 12, 16, 15, - 13, 14, 15, 16, 15, 14, - 15, 12, 16, 15, 14, 11, - 15, 14, 13, 16, 16, 12, - 11, 14, 15, 13, 17, 17, - 12, 14, 16, 16, 15, 15, - 14, 14, 15, 16, 12, 10, - 15, 15, 12, 16, 17, 13, - 15, 16, 15, 14, 15, 15, - 13, 17, 17, 13, 14, 15, - 14, 15, 14, 16, 15, 13, - 15, 15, 12, 11, 15, 15, - 12, 11, 14, 15, 14, 14, - 15, 15, 13, 14, 14, 14, - 14, 15, 15, 15, 15, 14, - 10, 16, 15, 7, 11, 12, - 7, 7, 11, 11, 12, 12, - 12, 12, 11, 13, 13, 10, - 12, 12, 12, 12, 12, 13, - 7, 12, 12, 6, 12, 12, - 10, 12, 12, 9, 12, 14, - 13, 12, 14, 13, 11, 11, - 13, 13, 11, 12, 13, 14, - 9, 11, 11, 10, 12, 15, - 13, 12, 11, 15, 14, 13, - 15, 14, 14, 12, 13, 13, - 12, 12, 12, 13, 13, 13, - 13, 11, 13, 14, 9, 15, - 14, 10, 16, 15, 11, 11, - 13, 13, 14, 16, 16, 13, - 14, 16, 14, 14, 12, 13, - 13, 11, 15, 15, 11, 9, - 14, 14, 12, 15, 16, 10, - 11, 13, 14, 14, 16, 16, - 13, 13, 14, 15, 13, 12, - 13, 14, 12, 16, 15, 11, - 12, 14, 15, 13, 11, 14, - 16, 14, 13, 14, 13, 11, - 13, 13, 12, 12, 13, 14, - 13, 13, 13, 11, 14, 14, - 7, 12, 12, 9, 12, 11, - 10, 12, 13, 14, 12, 14, - 15, 11, 10, 13, 13, 11, - 12, 14, 12, 10, 12, 11, - 9, -}; - -static const uint16_t on2avc_cb5_syms[ON2AVC_CB5_CODES] = { - 0x0000, 0x0002, 0x000E, 0x0011, 0x0013, 0x001D, - 0x001F, 0x0020, 0x0022, 0x002E, 0x0031, 0x0033, - 0x003D, 0x003F, 0x00D1, 0x00D3, 0x00DD, 0x00DF, - 0x00E0, 0x00E2, 0x00EE, 0x00F1, 0x00F3, 0x00FD, - 0x00FF, 0x0101, 0x0103, 0x010D, 0x010F, 0x0110, - 0x0112, 0x011E, 0x0121, 0x0123, 0x012D, 0x012F, - 0x0130, 0x0132, 0x013E, 0x01D0, 0x01D2, 0x01DE, - 0x01E1, 0x01E3, 0x01ED, 0x01EF, 0x01F0, 0x01F2, - 0x01FE, 0x0200, 0x0202, 0x020E, 0x0211, 0x0213, - 0x021D, 0x021F, 0x0220, 0x0222, 0x022E, 0x0231, - 0x0233, 0x023D, 0x023F, 0x02D1, 0x02D3, 0x02DD, - 0x02DF, 0x02E0, 0x02E2, 0x02EE, 0x02F1, 0x02F3, - 0x02FD, 0x02FF, 0x0301, 0x0303, 0x030D, 0x030F, - 0x0310, 0x0312, 0x031E, 0x0321, 0x0323, 0x032D, - 0x032F, 0x0330, 0x0332, 0x033E, 0x03D0, 0x03D2, - 0x03DE, 0x03E1, 0x03E3, 0x03ED, 0x03EF, 0x03F0, - 0x03F2, 0x03FE, 0x0D01, 0x0D03, 0x0D0D, 0x0D0F, - 0x0D10, 0x0D12, 0x0D1E, 0x0D21, 0x0D23, 0x0D2D, - 0x0D2F, 0x0D30, 0x0D32, 0x0D3E, 0x0DD0, 0x0DD2, - 0x0DDE, 0x0DE1, 0x0DE3, 0x0DED, 0x0DEF, 0x0DF0, - 0x0DF2, 0x0DFE, 0x0E00, 0x0E02, 0x0E0E, 0x0E11, - 0x0E13, 0x0E1D, 0x0E1F, 0x0E20, 0x0E22, 0x0E2E, - 0x0E31, 0x0E33, 0x0E3D, 0x0E3F, 0x0ED1, 0x0ED3, - 0x0EDD, 0x0EDF, 0x0EE0, 0x0EE2, 0x0EEE, 0x0EF1, - 0x0EF3, 0x0EFD, 0x0EFF, 0x0F01, 0x0F03, 0x0F0D, - 0x0F0F, 0x0F10, 0x0F12, 0x0F1E, 0x0F21, 0x0F23, - 0x0F2D, 0x0F2F, 0x0F30, 0x0F32, 0x0F3E, 0x0FD0, - 0x0FD2, 0x0FDE, 0x0FE1, 0x0FE3, 0x0FED, 0x0FEF, - 0x0FF0, 0x0FF2, 0x0FFE, 0x1001, 0x1003, 0x100D, - 0x100F, 0x1010, 0x1012, 0x101E, 0x1021, 0x1023, - 0x102D, 0x102F, 0x1030, 0x1032, 0x103E, 0x10D0, - 0x10D2, 0x10DE, 0x10E1, 0x10E3, 0x10ED, 0x10EF, - 0x10F0, 0x10F2, 0x10FE, 0x1100, 0x1102, 0x110E, - 0x1111, 0x1113, 0x111D, 0x111F, 0x1120, 0x1122, - 0x112E, 0x1131, 0x1133, 0x113D, 0x113F, 0x11D1, - 0x11D3, 0x11DD, 0x11DF, 0x11E0, 0x11E2, 0x11EE, - 0x11F1, 0x11F3, 0x11FD, 0x11FF, 0x1201, 0x1203, - 0x120D, 0x120F, 0x1210, 0x1212, 0x121E, 0x1221, - 0x1223, 0x122D, 0x122F, 0x1230, 0x1232, 0x123E, - 0x12D0, 0x12D2, 0x12DE, 0x12E1, 0x12E3, 0x12ED, - 0x12EF, 0x12F0, 0x12F2, 0x12FE, 0x1300, 0x1302, - 0x130E, 0x1311, 0x1313, 0x131D, 0x131F, 0x1320, - 0x1322, 0x132E, 0x1331, 0x1333, 0x133D, 0x133F, - 0x13D1, 0x13D3, 0x13DD, 0x13DF, 0x13E0, 0x13E2, - 0x13EE, 0x13F1, 0x13F3, 0x13FD, 0x13FF, 0x1D00, - 0x1D02, 0x1D0E, 0x1D11, 0x1D13, 0x1D1D, 0x1D1F, - 0x1D20, 0x1D22, 0x1D2E, 0x1D31, 0x1D33, 0x1D3D, - 0x1D3F, 0x1DD1, 0x1DD3, 0x1DDD, 0x1DDF, 0x1DE0, - 0x1DE2, 0x1DEE, 0x1DF1, 0x1DF3, 0x1DFD, 0x1DFF, - 0x1E01, 0x1E03, 0x1E0D, 0x1E0F, 0x1E10, 0x1E12, - 0x1E1E, 0x1E21, 0x1E23, 0x1E2D, 0x1E2F, 0x1E30, - 0x1E32, 0x1E3E, 0x1ED0, 0x1ED2, 0x1EDE, 0x1EE1, - 0x1EE3, 0x1EED, 0x1EEF, 0x1EF0, 0x1EF2, 0x1EFE, - 0x1F00, 0x1F02, 0x1F0E, 0x1F11, 0x1F13, 0x1F1D, - 0x1F1F, 0x1F20, 0x1F22, 0x1F2E, 0x1F31, 0x1F33, - 0x1F3D, 0x1F3F, 0x1FD1, 0x1FD3, 0x1FDD, 0x1FDF, - 0x1FE0, 0x1FE2, 0x1FEE, 0x1FF1, 0x1FF3, 0x1FFD, - 0x1FFF, 0x2000, 0x2002, 0x200E, 0x2011, 0x2013, - 0x201D, 0x201F, 0x2020, 0x2022, 0x202E, 0x2031, - 0x2033, 0x203D, 0x203F, 0x20D1, 0x20D3, 0x20DD, - 0x20DF, 0x20E0, 0x20E2, 0x20EE, 0x20F1, 0x20F3, - 0x20FD, 0x20FF, 0x2101, 0x2103, 0x210D, 0x210F, - 0x2110, 0x2112, 0x211E, 0x2121, 0x2123, 0x212D, - 0x212F, 0x2130, 0x2132, 0x213E, 0x21D0, 0x21D2, - 0x21DE, 0x21E1, 0x21E3, 0x21ED, 0x21EF, 0x21F0, - 0x21F2, 0x21FE, 0x2200, 0x2202, 0x220E, 0x2211, - 0x2213, 0x221D, 0x221F, 0x2220, 0x2222, 0x222E, - 0x2231, 0x2233, 0x223D, 0x223F, 0x22D1, 0x22D3, - 0x22DD, 0x22DF, 0x22E0, 0x22E2, 0x22EE, 0x22F1, - 0x22F3, 0x22FD, 0x22FF, 0x2301, 0x2303, 0x230D, - 0x230F, 0x2310, 0x2312, 0x231E, 0x2321, 0x2323, - 0x232D, 0x232F, 0x2330, 0x2332, 0x233E, 0x23D0, - 0x23D2, 0x23DE, 0x23E1, 0x23E3, 0x23ED, 0x23EF, - 0x23F0, 0x23F2, 0x23FE, 0x2D01, 0x2D03, 0x2D0D, - 0x2D0F, 0x2D10, 0x2D12, 0x2D1E, 0x2D21, 0x2D23, - 0x2D2D, 0x2D2F, 0x2D30, 0x2D32, 0x2D3E, 0x2DD0, - 0x2DD2, 0x2DDE, 0x2DE1, 0x2DE3, 0x2DED, 0x2DEF, - 0x2DF0, 0x2DF2, 0x2DFE, 0x2E00, 0x2E02, 0x2E0E, - 0x2E11, 0x2E13, 0x2E1D, 0x2E1F, 0x2E20, 0x2E22, - 0x2E2E, 0x2E31, 0x2E33, 0x2E3D, 0x2E3F, 0x2ED1, - 0x2ED3, 0x2EDD, 0x2EDF, 0x2EE0, 0x2EE2, 0x2EEE, - 0x2EF1, 0x2EF3, 0x2EFD, 0x2EFF, 0x2F01, 0x2F03, - 0x2F0D, 0x2F0F, 0x2F10, 0x2F12, 0x2F1E, 0x2F21, - 0x2F23, 0x2F2D, 0x2F2F, 0x2F30, 0x2F32, 0x2F3E, - 0x2FD0, 0x2FD2, 0x2FDE, 0x2FE1, 0x2FE3, 0x2FED, - 0x2FEF, 0x2FF0, 0x2FF2, 0x2FFE, 0x3001, 0x3003, - 0x300D, 0x300F, 0x3010, 0x3012, 0x301E, 0x3021, - 0x3023, 0x302D, 0x302F, 0x3030, 0x3032, 0x303E, - 0x30D0, 0x30D2, 0x30DE, 0x30E1, 0x30E3, 0x30ED, - 0x30EF, 0x30F0, 0x30F2, 0x30FE, 0x3100, 0x3102, - 0x310E, 0x3111, 0x3113, 0x311D, 0x311F, 0x3120, - 0x3122, 0x312E, 0x3131, 0x3133, 0x313D, 0x313F, - 0x31D1, 0x31D3, 0x31DD, 0x31DF, 0x31E0, 0x31E2, - 0x31EE, 0x31F1, 0x31F3, 0x31FD, 0x31FF, 0x3201, - 0x3203, 0x320D, 0x320F, 0x3210, 0x3212, 0x321E, - 0x3221, 0x3223, 0x322D, 0x322F, 0x3230, 0x3232, - 0x323E, 0x32D0, 0x32D2, 0x32DE, 0x32E1, 0x32E3, - 0x32ED, 0x32EF, 0x32F0, 0x32F2, 0x32FE, 0x3300, - 0x3302, 0x330E, 0x3311, 0x3313, 0x331D, 0x331F, - 0x3320, 0x3322, 0x332E, 0x3331, 0x3333, 0x333D, - 0x333F, 0x33D1, 0x33D3, 0x33DD, 0x33DF, 0x33E0, - 0x33E2, 0x33EE, 0x33F1, 0x33F3, 0x33FD, 0x33FF, - 0x3D00, 0x3D02, 0x3D0E, 0x3D11, 0x3D13, 0x3D1D, - 0x3D1F, 0x3D20, 0x3D22, 0x3D2E, 0x3D31, 0x3D33, - 0x3D3D, 0x3D3F, 0x3DD1, 0x3DD3, 0x3DDD, 0x3DDF, - 0x3DE0, 0x3DE2, 0x3DEE, 0x3DF1, 0x3DF3, 0x3DFD, - 0x3DFF, 0x3E01, 0x3E03, 0x3E0D, 0x3E0F, 0x3E10, - 0x3E12, 0x3E1E, 0x3E21, 0x3E23, 0x3E2D, 0x3E2F, - 0x3E30, 0x3E32, 0x3E3E, 0x3ED0, 0x3ED2, 0x3EDE, - 0x3EE1, 0x3EE3, 0x3EED, 0x3EEF, 0x3EF0, 0x3EF2, - 0x3EFE, 0x3F00, 0x3F02, 0x3F0E, 0x3F11, 0x3F13, - 0x3F1D, 0x3F1F, 0x3F20, 0x3F22, 0x3F2E, 0x3F31, - 0x3F33, 0x3F3D, 0x3F3F, 0x3FD1, 0x3FD3, 0x3FDD, - 0x3FDF, 0x3FE0, 0x3FE2, 0x3FEE, 0x3FF1, 0x3FF3, - 0x3FFD, 0x3FFF, 0xD001, 0xD003, 0xD00D, 0xD00F, - 0xD010, 0xD012, 0xD01E, 0xD021, 0xD023, 0xD02D, - 0xD02F, 0xD030, 0xD032, 0xD03E, 0xD0D0, 0xD0D2, - 0xD0DE, 0xD0E1, 0xD0E3, 0xD0ED, 0xD0EF, 0xD0F0, - 0xD0F2, 0xD0FE, 0xD100, 0xD102, 0xD10E, 0xD111, - 0xD113, 0xD11D, 0xD11F, 0xD120, 0xD122, 0xD12E, - 0xD131, 0xD133, 0xD13D, 0xD13F, 0xD1D1, 0xD1D3, - 0xD1DD, 0xD1DF, 0xD1E0, 0xD1E2, 0xD1EE, 0xD1F1, - 0xD1F3, 0xD1FD, 0xD1FF, 0xD201, 0xD203, 0xD20D, - 0xD20F, 0xD210, 0xD212, 0xD21E, 0xD221, 0xD223, - 0xD22D, 0xD22F, 0xD230, 0xD232, 0xD23E, 0xD2D0, - 0xD2D2, 0xD2DE, 0xD2E1, 0xD2E3, 0xD2ED, 0xD2EF, - 0xD2F0, 0xD2F2, 0xD2FE, 0xD300, 0xD302, 0xD30E, - 0xD311, 0xD313, 0xD31D, 0xD31F, 0xD320, 0xD322, - 0xD32E, 0xD331, 0xD333, 0xD33D, 0xD33F, 0xD3D1, - 0xD3D3, 0xD3DD, 0xD3DF, 0xD3E0, 0xD3E2, 0xD3EE, - 0xD3F1, 0xD3F3, 0xD3FD, 0xD3FF, 0xDD00, 0xDD02, - 0xDD0E, 0xDD11, 0xDD13, 0xDD1D, 0xDD1F, 0xDD20, - 0xDD22, 0xDD2E, 0xDD31, 0xDD33, 0xDD3D, 0xDD3F, - 0xDDD1, 0xDDD3, 0xDDDD, 0xDDDF, 0xDDE0, 0xDDE2, - 0xDDEE, 0xDDF1, 0xDDF3, 0xDDFD, 0xDDFF, 0xDE01, - 0xDE03, 0xDE0D, 0xDE0F, 0xDE10, 0xDE12, 0xDE1E, - 0xDE21, 0xDE23, 0xDE2D, 0xDE2F, 0xDE30, 0xDE32, - 0xDE3E, 0xDED0, 0xDED2, 0xDEDE, 0xDEE1, 0xDEE3, - 0xDEED, 0xDEEF, 0xDEF0, 0xDEF2, 0xDEFE, 0xDF00, - 0xDF02, 0xDF0E, 0xDF11, 0xDF13, 0xDF1D, 0xDF1F, - 0xDF20, 0xDF22, 0xDF2E, 0xDF31, 0xDF33, 0xDF3D, - 0xDF3F, 0xDFD1, 0xDFD3, 0xDFDD, 0xDFDF, 0xDFE0, - 0xDFE2, 0xDFEE, 0xDFF1, 0xDFF3, 0xDFFD, 0xDFFF, - 0xE000, 0xE002, 0xE00E, 0xE011, 0xE013, 0xE01D, - 0xE01F, 0xE020, 0xE022, 0xE02E, 0xE031, 0xE033, - 0xE03D, 0xE03F, 0xE0D1, 0xE0D3, 0xE0DD, 0xE0DF, - 0xE0E0, 0xE0E2, 0xE0EE, 0xE0F1, 0xE0F3, 0xE0FD, - 0xE0FF, 0xE101, 0xE103, 0xE10D, 0xE10F, 0xE110, - 0xE112, 0xE11E, 0xE121, 0xE123, 0xE12D, 0xE12F, - 0xE130, 0xE132, 0xE13E, 0xE1D0, 0xE1D2, 0xE1DE, - 0xE1E1, 0xE1E3, 0xE1ED, 0xE1EF, 0xE1F0, 0xE1F2, - 0xE1FE, 0xE200, 0xE202, 0xE20E, 0xE211, 0xE213, - 0xE21D, 0xE21F, 0xE220, 0xE222, 0xE22E, 0xE231, - 0xE233, 0xE23D, 0xE23F, 0xE2D1, 0xE2D3, 0xE2DD, - 0xE2DF, 0xE2E0, 0xE2E2, 0xE2EE, 0xE2F1, 0xE2F3, - 0xE2FD, 0xE2FF, 0xE301, 0xE303, 0xE30D, 0xE30F, - 0xE310, 0xE312, 0xE31E, 0xE321, 0xE323, 0xE32D, - 0xE32F, 0xE330, 0xE332, 0xE33E, 0xE3D0, 0xE3D2, - 0xE3DE, 0xE3E1, 0xE3E3, 0xE3ED, 0xE3EF, 0xE3F0, - 0xE3F2, 0xE3FE, 0xED01, 0xED03, 0xED0D, 0xED0F, - 0xED10, 0xED12, 0xED1E, 0xED21, 0xED23, 0xED2D, - 0xED2F, 0xED30, 0xED32, 0xED3E, 0xEDD0, 0xEDD2, - 0xEDDE, 0xEDE1, 0xEDE3, 0xEDED, 0xEDEF, 0xEDF0, - 0xEDF2, 0xEDFE, 0xEE00, 0xEE02, 0xEE0E, 0xEE11, - 0xEE13, 0xEE1D, 0xEE1F, 0xEE20, 0xEE22, 0xEE2E, - 0xEE31, 0xEE33, 0xEE3D, 0xEE3F, 0xEED1, 0xEED3, - 0xEEDD, 0xEEDF, 0xEEE0, 0xEEE2, 0xEEEE, 0xEEF1, - 0xEEF3, 0xEEFD, 0xEEFF, 0xEF01, 0xEF03, 0xEF0D, - 0xEF0F, 0xEF10, 0xEF12, 0xEF1E, 0xEF21, 0xEF23, - 0xEF2D, 0xEF2F, 0xEF30, 0xEF32, 0xEF3E, 0xEFD0, - 0xEFD2, 0xEFDE, 0xEFE1, 0xEFE3, 0xEFED, 0xEFEF, - 0xEFF0, 0xEFF2, 0xEFFE, 0xF001, 0xF003, 0xF00D, - 0xF00F, 0xF010, 0xF012, 0xF01E, 0xF021, 0xF023, - 0xF02D, 0xF02F, 0xF030, 0xF032, 0xF03E, 0xF0D0, - 0xF0D2, 0xF0DE, 0xF0E1, 0xF0E3, 0xF0ED, 0xF0EF, - 0xF0F0, 0xF0F2, 0xF0FE, 0xF100, 0xF102, 0xF10E, - 0xF111, 0xF113, 0xF11D, 0xF11F, 0xF120, 0xF122, - 0xF12E, 0xF131, 0xF133, 0xF13D, 0xF13F, 0xF1D1, - 0xF1D3, 0xF1DD, 0xF1DF, 0xF1E0, 0xF1E2, 0xF1EE, - 0xF1F1, 0xF1F3, 0xF1FD, 0xF1FF, 0xF201, 0xF203, - 0xF20D, 0xF20F, 0xF210, 0xF212, 0xF21E, 0xF221, - 0xF223, 0xF22D, 0xF22F, 0xF230, 0xF232, 0xF23E, - 0xF2D0, 0xF2D2, 0xF2DE, 0xF2E1, 0xF2E3, 0xF2ED, - 0xF2EF, 0xF2F0, 0xF2F2, 0xF2FE, 0xF300, 0xF302, - 0xF30E, 0xF311, 0xF313, 0xF31D, 0xF31F, 0xF320, - 0xF322, 0xF32E, 0xF331, 0xF333, 0xF33D, 0xF33F, - 0xF3D1, 0xF3D3, 0xF3DD, 0xF3DF, 0xF3E0, 0xF3E2, - 0xF3EE, 0xF3F1, 0xF3F3, 0xF3FD, 0xF3FF, 0xFD00, - 0xFD02, 0xFD0E, 0xFD11, 0xFD13, 0xFD1D, 0xFD1F, - 0xFD20, 0xFD22, 0xFD2E, 0xFD31, 0xFD33, 0xFD3D, - 0xFD3F, 0xFDD1, 0xFDD3, 0xFDDD, 0xFDDF, 0xFDE0, - 0xFDE2, 0xFDEE, 0xFDF1, 0xFDF3, 0xFDFD, 0xFDFF, - 0xFE01, 0xFE03, 0xFE0D, 0xFE0F, 0xFE10, 0xFE12, - 0xFE1E, 0xFE21, 0xFE23, 0xFE2D, 0xFE2F, 0xFE30, - 0xFE32, 0xFE3E, 0xFED0, 0xFED2, 0xFEDE, 0xFEE1, - 0xFEE3, 0xFEED, 0xFEEF, 0xFEF0, 0xFEF2, 0xFEFE, - 0xFF00, 0xFF02, 0xFF0E, 0xFF11, 0xFF13, 0xFF1D, - 0xFF1F, 0xFF20, 0xFF22, 0xFF2E, 0xFF31, 0xFF33, - 0xFF3D, 0xFF3F, 0xFFD1, 0xFFD3, 0xFFDD, 0xFFDF, - 0xFFE0, 0xFFE2, 0xFFEE, 0xFFF1, 0xFFF3, 0xFFFD, - 0xFFFF, -}; - -#define ON2AVC_CB6_CODES 1201 -static const uint32_t on2avc_cb6_codes[ON2AVC_CB6_CODES] = { - 0x0018, 0x0088, 0x0082, 0x0024, 0x05B4, 0x08DF, - 0x0044, 0x0197, 0x01DE, 0x021F, 0x0D77, 0x0A72, - 0x7E77, 0x0B8B, 0x03F1, 0x0433, 0x073F, 0x1E5C, - 0x016A, 0x01C5, 0x00D2, 0x0062, 0x0CE4, 0x0096, - 0x0020, 0x0052, 0x00B7, 0x0127, 0x003A, 0x0041, - 0x00CC, 0x01B6, 0x0124, 0x07D3, 0x01AE, 0x01C4, - 0x00DA, 0x03D8, 0x03F3, 0x1638, 0x03F2, 0x12FC, - 0x01E2, 0x0DBC, 0x026C, 0x008A, 0x0054, 0x01A6, - 0x0195, 0x0164, 0x01E2, 0x026D, 0x0051, 0x049F, - 0x01B3, 0x01E0, 0x01B4, 0x026E, 0x07DE, 0x0129, - 0x0292, 0x0DBD, 0x013E, 0x00F3, 0x05B5, 0x09A6, - 0x01FB, 0x02CF, 0x01FF, 0x037C, 0x004A, 0x067E, - 0x016B, 0x002A, 0x09A7, 0x10EE, 0x1639, 0x0135, - 0x0CCA, 0x016A, 0x011B, 0x03EE, 0x07A2, 0x0D7E, - 0x028F, 0x0FE2, 0x07DA, 0x0357, 0x92F6, 0x0F31, - 0x0217, 0x036A, 0x0CE5, 0x07A1, 0x0229, 0x03D9, - 0x0377, 0x00B7, 0x01A6, 0x0655, 0x012E, 0x002B, - 0x002E, 0x00F2, 0x06F2, 0x02D0, 0x0F98, 0x07A0, - 0x009C, 0x0332, 0x0014, 0x01BD, 0x017E, 0x0331, - 0x0371, 0x025B, 0x0498, 0x161F, 0x039E, 0x0654, - 0x00C2, 0x06BA, 0x0140, 0x021E, 0x02F8, 0x01B4, - 0x0134, 0x03FF, 0x0066, 0x0477, 0x01DF, 0x01FE, - 0x0A14, 0x029E, 0x0356, 0x038F, 0x035A, 0x3CB3, - 0x01B2, 0x016A, 0x011A, 0x00B6, 0x02DE, 0x01DD, - 0x017C, 0x0376, 0x002F, 0x0039, 0x03D7, 0x01BE, - 0x0056, 0x0050, 0x017C, 0x01CC, 0x0034, 0x0B3E, - 0x0499, 0x0014, 0x08DE, 0x037B, 0x03EB, 0x08BF, - 0x186E, 0x050F, 0x0030, 0x0169, 0x07F2, 0x00F6, - 0x0042, 0x0198, 0x00BC, 0x002E, 0x023A, 0x01E3, - 0x0036, 0x004C, 0x012E, 0x01A1, 0x007D, 0x00C3, - 0x0392, 0x0063, 0x0F33, 0x016C, 0x01A7, 0x0E77, - 0x01DF, 0x0177, 0x0032, 0x03FE, 0x0322, 0x01AC, - 0x0030, 0x017E, 0x011E, 0x0022, 0x01FB, 0x012A, - 0x002B, 0x0068, 0x00D4, 0x006E, 0x0015, 0x001C, - 0x00E5, 0x01A9, 0x0436, 0x053F, 0x05AE, 0x00B2, - 0x072A, 0x02EA, 0x008E, 0x0175, 0x02BE, 0x018E, - 0x0002, 0x005E, 0x01D6, 0x0055, 0x006A, 0x07F3, - 0x02F9, 0x01D4, 0x016E, 0x03AB, 0x00FF, 0x003C, - 0x0192, 0x01D6, 0x0256, 0x0137, 0x0148, 0x022A, - 0x039C, 0x016D, 0x0116, 0x038A, 0x033E, 0x0156, - 0x03CF, 0x004B, 0x00E6, 0x018F, 0x1E5D, 0x03DA, - 0x0292, 0x0108, 0x06F5, 0x03DB, 0x0092, 0x0178, - 0x014A, 0x03FF, 0x03EE, 0x0A79, 0x0A16, 0x00F7, - 0x01B5, 0x0A15, 0x0D7F, 0x02FA, 0x01E4, 0x0157, - 0x01E2, 0x0185, 0x057E, 0x07DB, 0x0098, 0x0DBE, - 0x019A, 0x05FE, 0x003B, 0x03F5, 0x01BF, 0x01E4, - 0x011E, 0x001B, 0x03AA, 0x0337, 0x1F9C, 0x0942, - 0x05AB, 0x0430, 0x24BF, 0x163A, 0x037E, 0x014E, - 0x00F4, 0x0217, 0x0059, 0x0F32, 0x03F4, 0x01F2, - 0x0031, 0x0136, 0x05C6, 0x0076, 0x0006, 0x02FE, - 0x03FB, 0x009D, 0x013F, 0x002E, 0x02E6, 0x00AD, - 0x0234, 0x021E, 0x0253, 0x012A, 0x0346, 0x029A, - 0x012B, 0x021C, 0x02DA, 0x0004, 0x013C, 0x00F5, - 0x004E, 0x017D, 0x01F8, 0x0006, 0x01FA, 0x01F9, - 0x007A, 0x0067, 0x033B, 0x033A, 0x0586, 0x05C7, - 0x05FF, 0x00C8, 0x014B, 0x024F, 0x02C5, 0x00E7, - 0x014C, 0x035C, 0x00A2, 0x006A, 0x01F3, 0x0071, - 0x005E, 0x0084, 0x063A, 0x03EF, 0x0064, 0x02FE, - 0x0255, 0x003A, 0x061A, 0x0333, 0x037F, 0x00FE, - 0x115B, 0x0F9A, 0x00A6, 0x027D, 0x0B5F, 0x013F, - 0x029E, 0x0293, 0x07B6, 0x000F, 0x0196, 0x02FB, - 0x033F, 0x01FE, 0x019E, 0x01B3, 0x037F, 0x00C4, - 0x00DE, 0x02D2, 0x007A, 0x03CA, 0x01E3, 0x02F7, - 0x00AE, 0x05AF, 0x02FF, 0x026F, 0x00CA, 0x0356, - 0x02C7, 0x02D1, 0x0256, 0x006B, 0x0141, 0x012C, - 0x03BE, 0x0026, 0x00F0, 0x03A3, 0x02D6, 0x005F, - 0x00FF, 0x03F2, 0x00AE, 0x0257, 0x01FE, 0x035E, - 0x01B6, 0x00EE, 0x0658, 0x008F, 0x0232, 0x0657, - 0x12FD, 0x00AF, 0x00E6, 0x0426, 0x0666, 0x009E, - 0x0467, 0x003F, 0x014A, 0x02D3, 0x12FE, 0x099A, - 0x03BF, 0x00DD, 0x04DF, 0x009F, 0x00B8, 0x0863, - 0x06F7, 0x01B8, 0x0346, 0x0179, 0x0FE3, 0x0667, - 0x0659, 0x01CE, 0x00B3, 0x0372, 0x065A, 0x025E, - 0x01AA, 0x0276, 0x027E, 0x02DB, 0x0CE6, 0x115A, - 0x02E7, 0x0139, 0x03DA, 0x01FA, 0x021C, 0x0943, - 0x0862, 0x011F, 0x08B6, 0x07E6, 0x029F, 0x00E5, - 0x0656, 0x049A, 0x000E, 0x0F99, 0x06F6, 0x00DC, - 0x00EC, 0x014B, 0x0230, 0x04A2, 0x0016, 0x02EB, - 0x03AE, 0x02DF, 0x01AA, 0x033E, 0x0196, 0x092E, - 0x06F3, 0x00E7, 0x0B5E, 0x03F2, 0x0086, 0x0347, - 0x022A, 0x0A17, 0x01EF, 0x067F, 0x004A, 0x037E, - 0x02EE, 0x015E, 0x0696, 0x006A, 0x01CD, 0x0077, - 0x073F, 0x0016, 0x01E3, 0x012E, 0x00DB, 0x03BD, - 0x0496, 0x01C6, 0x0323, 0x005E, 0x02F6, 0x027C, - 0x0235, 0x0231, 0x00DA, 0x01EB, 0x0232, 0x02C6, - 0x01F2, 0x016F, 0x02C6, 0x036B, 0x0050, 0x0AFE, - 0x0F9B, 0x00C6, 0x014E, 0x02BC, 0x01CA, 0x027F, - 0x07A5, 0x0DE1, 0x01F1, 0x039E, 0x0DE2, 0x1E5E, - 0x065E, 0x0DE0, 0x115F, 0x00F7, 0x02AB, 0x116E, - 0x019B, 0x04CE, 0x00D3, 0x01C7, 0x02D6, 0x01F3, - 0x016F, 0x014E, 0x05B7, 0x0FA3, 0x0118, 0x025F, - 0x017E, 0x0437, 0x049B, 0x05AE, 0x497A, 0x0D2E, - 0x05B6, 0x1E5F, 0x0DE3, 0x0512, 0x031A, 0x01F2, - 0x007E, 0x015C, 0x035E, 0x04CF, 0x01C8, 0x0194, - 0x12FF, 0x1F7F, 0x00E0, 0x01A2, 0x012F, 0x0087, - 0x014C, 0x0643, 0x0D5E, 0x017F, 0x07A6, 0x0513, - 0x0D5F, 0x022B, 0x065F, 0x03F6, 0x022E, 0x03F7, - 0x0642, 0x036E, 0x00D0, 0x01CB, 0x0378, 0x125EE, - 0x035F, 0x014F, 0x035F, 0x116F, 0x0A4F, 0x0102, - 0x032A, 0x0173, 0x0536, 0x03A7, 0x075E, 0x1F9F, - 0x163B, 0x14DA, 0x526E, 0x165F, 0x0A6E, 0x0596, - 0x07A7, 0x042A, 0x0172, 0x19C2, 0x07E6, 0x04A3, - 0x0327, 0x02A8, 0x07A3, 0x046E, 0x012F, 0x2EFF, - 0x01D7, 0x0266, 0x0BBE, 0x066E, 0x186F, 0x0A73, - 0x1336, 0x02A9, 0x0373, 0x017F, 0x1F9E, 0x0B62, - 0x03A6, 0x0DBF, 0x035B, 0x063B, 0x053B, 0x10EF, - 0x016E, 0x011B, 0x115D, 0x115C, 0x00F2, 0x0176, - 0x0393, 0x034A, 0x0107, 0x115E, 0x0B63, 0x023F, - 0x002A, 0x0CE7, 0x0A7A, 0x06FA, 0x06FB, 0x02AA, - 0x02C2, 0x065B, 0x07A4, 0x02D4, 0x0130, 0x0106, - 0x01FB, 0x0B3F, 0x01B7, 0x00F6, 0x0056, 0x053F, - 0x0126, 0x0048, 0x0233, 0x017D, 0x00A4, 0x08BE, - 0x165E, 0x165D, 0x0A7B, 0x0427, 0x078F, 0x1F7E, - 0x0641, 0x02E4, 0x01E6, 0x01DA, 0x00F8, 0x043A, - 0x02BE, 0x011C, 0x006F, 0x036D, 0x19C3, 0x0020, - 0x06AE, 0x0372, 0x0288, 0x00C0, 0x079D, 0x036E, - 0x0117, 0x02FB, 0x0538, 0x06F2, 0x12F9, 0x1337, - 0x1E58, 0x0214, 0x005E, 0x0CE0, 0x01EE, 0x0A6E, - 0x0215, 0x01C2, 0x12FA, 0x033A, 0x009A, 0x0174, - 0x0CE2, 0x09A1, 0x00FE, 0x0250, 0x02CA, 0x035E, - 0x03A2, 0x0D7D, 0x2EFE, 0x02E8, 0x24BE, 0x1F7C, - 0x10EC, 0x04A2, 0x0052, 0x010D, 0x0277, 0x003A, - 0x0CDE, 0x0A6F, 0x0086, 0x00E4, 0x12FB, 0x14DE, - 0x009E, 0x0062, 0x03CA, 0x03BC, 0x02CA, 0x14DF, - 0x0FE0, 0x030C, 0x03F0, 0x06F3, 0x0796, 0x0B1E, - 0x05B0, 0x15FE, 0x013A, 0x0CDF, 0x079E, 0x01E2, - 0x0166, 0x02BD, 0x0151, 0x0153, 0x0650, 0x0940, - 0x010F, 0x3CB2, 0x10ED, 0x057E, 0x03D4, 0x029E, - 0x0358, 0x06F4, 0x7E76, 0x017C, 0x15FF, 0x047D, - 0x1158, 0x3F3A, 0x0CE3, 0x005F, 0x043A, 0x032F, - 0x010E, 0x1E5A, 0x0A4C, 0x0152, 0x125EF, 0x0B88, - 0x057F, 0x059E, 0x042B, 0x2936, 0x0138, 0x03A1, - 0x03C6, 0x0E56, 0x12F8, 0x149A, 0x526F, 0x0F2E, - 0x079C, 0x02FA, 0x0476, 0x0267, 0x0636, 0x03A0, - 0x014E, 0x0092, 0x0D7C, 0x05AF, 0x010C, 0x011C, - 0x0A10, 0x177E, 0x0131, 0x09A0, 0x03EA, 0x02C2, - 0x02D6, 0x0B89, 0x032E, 0x01E8, 0x0F30, 0x01BA, - 0x0532, 0x0A6C, 0x0F6E, 0x04CC, 0x008E, 0x036C, - 0x0E57, 0x00D6, 0x0162, 0x0024, 0x0252, 0x0F6F, - 0x01AE, 0x0150, 0x0038, 0x07CE, 0x01BB, 0x01F6, - 0x026A, 0x038B, 0x01DB, 0x07CF, 0x14DB, 0x24BC, - 0x0272, 0x053E, 0x073E, 0x078E, 0x0C36, 0x0176, - 0x032B, 0x017A, 0x0190, 0x0CCB, 0x047C, 0x0170, - 0x0054, 0x03EC, 0x049D, 0x0197, 0x043B, 0x0432, - 0x0192, 0x026A, 0x01F0, 0x0076, 0x0216, 0x0A11, - 0x1F7D, 0x02C4, 0x0298, 0x1159, 0x0A4E, 0x0116, - 0x00E4, 0x0216, 0x029A, 0x000F, 0x04DA, 0x04D2, - 0x002B, 0x0011, 0x049E, 0x045A, 0x01BF, 0x01EF, - 0x03CE, 0x01F8, 0x026E, 0x0466, 0x02DC, 0x0168, - 0x030E, 0x00B4, 0x01C3, 0x03CC, 0x028D, 0x01AE, - 0x038E, 0x01B0, 0x0664, 0x0119, 0x01BE, 0x035B, - 0x035F, 0x028E, 0x0A78, 0x01DE, 0x0397, 0x03FE, - 0x01B1, 0x028E, 0x07D2, 0x09A2, 0x033C, 0x02C1, - 0x0FA0, 0x0359, 0x031E, 0x00C1, 0x03D6, 0x0A12, - 0x01C4, 0x0330, 0x075F, 0x0B1F, 0x025A, 0x027B, - 0x04DB, 0x02E5, 0x01FA, 0x036F, 0x0A13, 0x02BB, - 0x00FA, 0x01D4, 0x01F8, 0x018A, 0x161E, 0x0E75, - 0x026B, 0x05B3, 0x01BC, 0x05B2, 0x09A3, 0x0424, - 0x047E, 0x01EE, 0x0FE1, 0x161D, 0x024C, 0x017E, - 0x026B, 0x01DC, 0x00A5, 0x0F2F, 0x161C, 0x028B, - 0x0196, 0x0168, 0x01EF, 0x0394, 0x0E74, 0x013C, - 0x00C9, 0x032E, 0x0941, 0x0D76, 0x050C, 0x0228, - 0x006C, 0x0236, 0x0D2F, 0x0156, 0x00D2, 0x0B8A, - 0x0148, 0x028A, 0x028B, 0x033B, 0x0214, 0x01E9, - 0x03C2, 0x049C, 0x02BA, 0x02E9, 0x028C, 0x01FC, - 0x0103, 0x0B5C, 0x050D, 0x031C, 0x0268, 0x0651, - 0x013A, 0x013B, 0x0118, 0x03D5, 0x0252, 0x0044, - 0x0637, 0x01D2, 0x000E, 0x00F0, 0x0323, 0x02C3, - 0x019A, 0x016C, 0x0046, 0x03E3, 0x024A, 0x00AC, - 0x0269, 0x02C0, 0x0396, 0x027A, 0x0253, 0x0273, - 0x073E, 0x0322, 0x003A, 0x025E, 0x0336, 0x0257, - 0x00D6, 0x0026, 0x03C3, 0x0034, 0x019A, 0x00FB, - 0x0038, 0x0040, 0x0096, 0x01F0, 0x0184, 0x021A, - 0x003E, 0x0042, 0x050E, 0x03CE, 0x035E, 0x0FA1, - 0x017B, 0x02CD, 0x0058, 0x0326, 0x00E4, 0x002E, - 0x004F, 0x000C, 0x0164, 0x0048, 0x0048, 0x0194, - 0x0074, 0x006E, 0x0070, 0x006C, 0x01A4, 0x00A3, - 0x034F, 0x011E, 0x0374, 0x0157, 0x0138, 0x011D, - 0x03CF, 0x033D, 0x0132, 0x0050, 0x023E, 0x005A, - 0x0076, 0x01EC, 0x005D, 0x0008, 0x004C, 0x024E, - 0x0154, 0x001E, 0x01C6, 0x0027, 0x00FE, 0x01EA, - 0x02CE, 0x01DD, 0x02CB, 0x035A, 0x0318, 0x013E, - 0x009B, 0x0288, 0x0339, 0x024D, 0x031F, 0x0128, - 0x00B6, 0x0028, 0x028A, 0x0289, 0x029F, 0x01FD, - 0x029A, 0x00F6, 0x0FA2, 0x0347, 0x0080, 0x01A8, - 0x028F, 0x0326, 0x0327, 0x0370, 0x165C, 0x043F, - 0x0375, 0x013D, 0x1E5B, 0x04DE, 0x0155, 0x00D8, - 0x0319, 0x0096, 0x0640, 0x07E7, 0x007C, 0x0652, - 0x0373, 0x05DE, 0x00CF, 0x0E76, 0x0653, 0x01A0, - 0x0160, 0x0169, 0x01D5, 0x05AA, 0x053A, 0x0B5D, - 0x0254, 0x079A, 0x0533, 0x0425, 0x053E, 0x00A6, - 0x030F, 0x01A2, 0x00B0, 0x04A3, 0x079F, 0x011A, - 0x01EE, 0x02CC, 0x045E, 0x005C, 0x0024, 0x022C, - 0x001A, 0x0338, 0x0132, 0x026C, 0x004E, 0x047F, - 0x01B2, 0x0113, 0x043E, 0x0336, 0x00F0, 0x02CE, - 0x0112, 0x018B, 0x0010, 0x0114, 0x01BE, 0x03FA, - 0x002A, 0x00FA, 0x0033, 0x0060, 0x0146, 0x01DC, - 0x0000, 0x0025, 0x037A, 0x034E, 0x012E, 0x029B, - 0x079B, 0x00E6, 0x03CD, 0x02DD, 0x0117, 0x017A, - 0x002C, 0x03E2, 0x003E, 0x0070, 0x00CE, 0x00B1, - 0x003B, -}; - -static const uint8_t on2avc_cb6_bits[ON2AVC_CB6_CODES] = { - 7, 10, 10, 7, 12, 12, - 7, 10, 11, 11, 12, 15, - 17, 12, 13, 11, 15, 13, - 10, 11, 11, 7, 13, 13, - 7, 7, 12, 12, 7, 7, - 9, 9, 9, 11, 10, 9, - 12, 12, 13, 13, 13, 13, - 9, 12, 10, 10, 7, 9, - 9, 10, 12, 11, 10, 11, - 11, 9, 11, 11, 11, 11, - 12, 12, 13, 11, 12, 12, - 10, 11, 12, 12, 10, 11, - 11, 10, 12, 14, 13, 11, - 12, 12, 11, 10, 13, 14, - 10, 12, 12, 12, 16, 12, - 12, 10, 13, 13, 13, 12, - 11, 11, 11, 13, 14, 13, - 13, 11, 11, 10, 13, 13, - 11, 12, 12, 13, 16, 12, - 14, 10, 13, 13, 10, 13, - 11, 11, 10, 11, 11, 9, - 11, 11, 10, 11, 12, 12, - 13, 12, 12, 10, 13, 14, - 12, 11, 11, 12, 11, 9, - 11, 11, 10, 7, 12, 13, - 7, 7, 9, 9, 10, 12, - 13, 10, 12, 10, 10, 12, - 13, 12, 10, 10, 11, 9, - 7, 9, 9, 7, 10, 10, - 7, 7, 9, 9, 10, 11, - 10, 10, 12, 11, 11, 12, - 11, 11, 10, 10, 10, 9, - 7, 9, 9, 7, 9, 9, - 7, 10, 10, 7, 10, 10, - 11, 10, 11, 11, 11, 10, - 11, 12, 10, 9, 10, 10, - 8, 10, 9, 7, 10, 11, - 11, 9, 9, 10, 10, 10, - 10, 11, 10, 11, 10, 10, - 10, 11, 11, 10, 11, 11, - 10, 10, 11, 10, 13, 12, - 11, 10, 13, 12, 10, 11, - 11, 10, 11, 12, 13, 12, - 11, 13, 14, 11, 10, 11, - 11, 9, 13, 12, 10, 12, - 11, 11, 10, 13, 13, 9, - 11, 11, 10, 11, 15, 13, - 11, 11, 14, 13, 11, 10, - 11, 11, 10, 12, 13, 9, - 10, 11, 11, 10, 10, 10, - 10, 11, 11, 11, 10, 11, - 10, 10, 10, 11, 10, 10, - 11, 11, 10, 10, 10, 11, - 7, 9, 9, 8, 9, 9, - 7, 10, 10, 10, 11, 11, - 11, 10, 10, 12, 11, 10, - 9, 10, 10, 7, 9, 10, - 7, 10, 11, 11, 10, 11, - 11, 10, 11, 12, 12, 12, - 13, 13, 12, 11, 13, 13, - 11, 11, 11, 11, 9, 11, - 11, 9, 9, 12, 11, 9, - 9, 10, 11, 10, 11, 11, - 11, 11, 11, 11, 11, 11, - 11, 10, 11, 11, 10, 9, - 10, 10, 11, 12, 11, 10, - 12, 11, 10, 11, 10, 12, - 11, 11, 13, 11, 10, 13, - 13, 11, 12, 12, 11, 11, - 11, 11, 10, 10, 13, 13, - 10, 10, 11, 11, 10, 12, - 13, 10, 12, 11, 12, 11, - 13, 13, 10, 14, 13, 10, - 10, 11, 11, 10, 13, 13, - 10, 10, 10, 11, 10, 13, - 12, 10, 12, 12, 12, 12, - 13, 13, 11, 13, 13, 10, - 10, 11, 11, 11, 12, 12, - 10, 11, 11, 10, 12, 12, - 11, 11, 13, 12, 11, 10, - 13, 13, 10, 11, 12, 12, - 10, 11, 11, 11, 9, 12, - 11, 10, 9, 11, 11, 10, - 11, 11, 10, 12, 11, 11, - 10, 11, 11, 10, 11, 11, - 10, 9, 10, 10, 9, 12, - 13, 9, 13, 10, 11, 11, - 13, 14, 11, 14, 14, 13, - 13, 14, 13, 11, 13, 13, - 11, 12, 11, 11, 13, 11, - 11, 9, 12, 12, 9, 11, - 11, 11, 13, 14, 15, 12, - 12, 13, 14, 12, 10, 11, - 11, 9, 13, 12, 9, 10, - 13, 13, 10, 9, 11, 11, - 10, 12, 13, 11, 13, 12, - 13, 13, 13, 13, 10, 13, - 12, 10, 10, 11, 10, 17, - 13, 13, 11, 13, 14, 11, - 11, 11, 12, 12, 11, 15, - 13, 13, 17, 14, 13, 12, - 13, 13, 11, 14, 13, 11, - 10, 13, 13, 11, 14, 14, - 11, 12, 12, 11, 13, 15, - 14, 13, 14, 16, 15, 13, - 12, 12, 13, 11, 14, 14, - 11, 10, 13, 13, 10, 9, - 10, 10, 11, 13, 13, 10, - 13, 13, 12, 13, 13, 13, - 10, 13, 13, 10, 10, 11, - 11, 12, 11, 11, 9, 12, - 12, 9, 11, 11, 11, 12, - 14, 14, 12, 12, 14, 13, - 12, 10, 11, 11, 9, 12, - 12, 9, 10, 14, 14, 9, - 12, 11, 11, 11, 13, 14, - 11, 17, 14, 13, 13, 14, - 13, 11, 14, 13, 11, 12, - 11, 11, 13, 11, 11, 9, - 13, 12, 9, 10, 11, 10, - 12, 14, 14, 12, 14, 13, - 14, 12, 11, 11, 11, 9, - 12, 12, 9, 10, 13, 14, - 10, 10, 11, 10, 10, 14, - 12, 10, 13, 13, 12, 12, - 12, 13, 10, 12, 13, 10, - 9, 10, 11, 11, 13, 13, - 11, 14, 14, 11, 12, 13, - 13, 13, 17, 16, 13, 13, - 13, 16, 13, 12, 11, 13, - 11, 13, 14, 11, 17, 12, - 13, 11, 13, 16, 11, 12, - 13, 12, 13, 15, 17, 13, - 13, 17, 11, 12, 11, 12, - 11, 11, 14, 14, 11, 10, - 13, 13, 10, 12, 10, 11, - 10, 12, 13, 10, 12, 13, - 13, 12, 12, 12, 11, 14, - 12, 10, 9, 11, 11, 12, - 11, 11, 10, 12, 13, 9, - 10, 10, 11, 12, 13, 14, - 12, 12, 15, 14, 12, 11, - 11, 11, 9, 12, 13, 9, - 10, 11, 11, 9, 11, 11, - 9, 11, 11, 12, 11, 13, - 13, 11, 12, 13, 14, 12, - 12, 12, 12, 10, 11, 11, - 10, 10, 11, 11, 9, 9, - 10, 10, 10, 11, 11, 10, - 10, 11, 11, 11, 11, 12, - 10, 11, 11, 11, 9, 10, - 10, 11, 12, 12, 10, 11, - 11, 10, 11, 12, 11, 10, - 12, 13, 10, 11, 12, 13, - 11, 12, 11, 12, 10, 11, - 11, 10, 10, 14, 13, 10, - 10, 11, 11, 10, 13, 12, - 10, 12, 13, 12, 12, 12, - 13, 10, 12, 13, 10, 10, - 11, 11, 11, 13, 13, 10, - 10, 11, 11, 10, 12, 13, - 10, 12, 13, 12, 12, 13, - 11, 10, 12, 12, 10, 12, - 11, 11, 11, 11, 12, 10, - 10, 11, 10, 12, 11, 12, - 11, 13, 12, 10, 11, 13, - 11, 11, 11, 12, 10, 10, - 11, 11, 10, 9, 11, 11, - 9, 9, 10, 10, 10, 11, - 11, 10, 10, 11, 11, 12, - 11, 11, 11, 11, 11, 10, - 9, 11, 10, 7, 10, 10, - 7, 7, 9, 9, 9, 10, - 11, 10, 12, 11, 11, 12, - 11, 11, 10, 10, 11, 10, - 7, 10, 9, 7, 10, 9, - 7, 10, 10, 7, 9, 10, - 10, 10, 11, 12, 10, 10, - 11, 11, 10, 10, 10, 11, - 7, 9, 10, 8, 10, 12, - 11, 10, 9, 11, 10, 10, - 11, 11, 10, 10, 10, 11, - 11, 10, 10, 10, 10, 11, - 11, 10, 10, 10, 13, 12, - 11, 12, 12, 12, 10, 10, - 11, 11, 11, 14, 14, 11, - 11, 13, 13, 11, 11, 11, - 10, 10, 12, 12, 10, 13, - 11, 11, 10, 12, 13, 9, - 10, 11, 11, 11, 14, 13, - 11, 11, 13, 12, 11, 11, - 10, 11, 10, 12, 13, 10, - 9, 11, 11, 10, 10, 10, - 11, 10, 11, 11, 11, 13, - 11, 11, 11, 10, 10, 10, - 11, 10, 10, 9, 10, 10, - 7, 9, 10, 7, 9, 9, - 8, 10, 10, 10, 10, 12, - 11, 10, 11, 11, 12, 10, - 10, 10, 10, 7, 10, 10, - 7, -}; - -static const uint16_t on2avc_cb6_syms[ON2AVC_CB6_CODES] = { - 0x0000, 0x0002, 0x000E, 0x0011, 0x0013, 0x001D, - 0x001F, 0x0020, 0x0022, 0x002E, 0x0031, 0x0033, - 0x003D, 0x003F, 0x00D1, 0x00D3, 0x00DD, 0x00DF, - 0x00E0, 0x00E2, 0x00EE, 0x00F1, 0x00F3, 0x00FD, - 0x00FF, 0x0101, 0x0103, 0x010D, 0x010F, 0x0110, - 0x0112, 0x011E, 0x0121, 0x0123, 0x012D, 0x012F, - 0x0130, 0x0132, 0x013E, 0x01D0, 0x01D2, 0x01DE, - 0x01E1, 0x01E3, 0x01ED, 0x01EF, 0x01F0, 0x01F2, - 0x01FE, 0x0200, 0x0202, 0x020E, 0x0211, 0x0213, - 0x021D, 0x021F, 0x0220, 0x0222, 0x022E, 0x0231, - 0x0233, 0x023D, 0x023F, 0x02D1, 0x02D3, 0x02DD, - 0x02DF, 0x02E0, 0x02E2, 0x02EE, 0x02F1, 0x02F3, - 0x02FD, 0x02FF, 0x0301, 0x0303, 0x030D, 0x030F, - 0x0310, 0x0312, 0x031E, 0x0321, 0x0323, 0x032D, - 0x032F, 0x0330, 0x0332, 0x033E, 0x03D0, 0x03D2, - 0x03DE, 0x03E1, 0x03E3, 0x03ED, 0x03EF, 0x03F0, - 0x03F2, 0x03FE, 0x0D01, 0x0D03, 0x0D0D, 0x0D0F, - 0x0D10, 0x0D12, 0x0D1E, 0x0D21, 0x0D23, 0x0D2D, - 0x0D2F, 0x0D30, 0x0D32, 0x0D3E, 0x0DD0, 0x0DD2, - 0x0DDE, 0x0DE1, 0x0DE3, 0x0DED, 0x0DEF, 0x0DF0, - 0x0DF2, 0x0DFE, 0x0E00, 0x0E02, 0x0E0E, 0x0E11, - 0x0E13, 0x0E1D, 0x0E1F, 0x0E20, 0x0E22, 0x0E2E, - 0x0E31, 0x0E33, 0x0E3D, 0x0E3F, 0x0ED1, 0x0ED3, - 0x0EDD, 0x0EDF, 0x0EE0, 0x0EE2, 0x0EEE, 0x0EF1, - 0x0EF3, 0x0EFD, 0x0EFF, 0x0F01, 0x0F03, 0x0F0D, - 0x0F0F, 0x0F10, 0x0F12, 0x0F1E, 0x0F21, 0x0F23, - 0x0F2D, 0x0F2F, 0x0F30, 0x0F32, 0x0F3E, 0x0FD0, - 0x0FD2, 0x0FDE, 0x0FE1, 0x0FE3, 0x0FED, 0x0FEF, - 0x0FF0, 0x0FF2, 0x0FFE, 0x1001, 0x1003, 0x100D, - 0x100F, 0x1010, 0x1012, 0x101E, 0x1021, 0x1023, - 0x102D, 0x102F, 0x1030, 0x1032, 0x103E, 0x10D0, - 0x10D2, 0x10DE, 0x10E1, 0x10E3, 0x10ED, 0x10EF, - 0x10F0, 0x10F2, 0x10FE, 0x1100, 0x1102, 0x110E, - 0x1111, 0x1113, 0x111D, 0x111F, 0x1120, 0x1122, - 0x112E, 0x1131, 0x1133, 0x113D, 0x113F, 0x11D1, - 0x11D3, 0x11DD, 0x11DF, 0x11E0, 0x11E2, 0x11EE, - 0x11F1, 0x11F3, 0x11FD, 0x11FF, 0x1201, 0x1203, - 0x120D, 0x120F, 0x1210, 0x1212, 0x121E, 0x1221, - 0x1223, 0x122D, 0x122F, 0x1230, 0x1232, 0x123E, - 0x12D0, 0x12D2, 0x12DE, 0x12E1, 0x12E3, 0x12ED, - 0x12EF, 0x12F0, 0x12F2, 0x12FE, 0x1300, 0x1302, - 0x130E, 0x1311, 0x1313, 0x131D, 0x131F, 0x1320, - 0x1322, 0x132E, 0x1331, 0x1333, 0x133D, 0x133F, - 0x13D1, 0x13D3, 0x13DD, 0x13DF, 0x13E0, 0x13E2, - 0x13EE, 0x13F1, 0x13F3, 0x13FD, 0x13FF, 0x1D00, - 0x1D02, 0x1D0E, 0x1D11, 0x1D13, 0x1D1D, 0x1D1F, - 0x1D20, 0x1D22, 0x1D2E, 0x1D31, 0x1D33, 0x1D3D, - 0x1D3F, 0x1DD1, 0x1DD3, 0x1DDD, 0x1DDF, 0x1DE0, - 0x1DE2, 0x1DEE, 0x1DF1, 0x1DF3, 0x1DFD, 0x1DFF, - 0x1E01, 0x1E03, 0x1E0D, 0x1E0F, 0x1E10, 0x1E12, - 0x1E1E, 0x1E21, 0x1E23, 0x1E2D, 0x1E2F, 0x1E30, - 0x1E32, 0x1E3E, 0x1ED0, 0x1ED2, 0x1EDE, 0x1EE1, - 0x1EE3, 0x1EED, 0x1EEF, 0x1EF0, 0x1EF2, 0x1EFE, - 0x1F00, 0x1F02, 0x1F0E, 0x1F11, 0x1F13, 0x1F1D, - 0x1F1F, 0x1F20, 0x1F22, 0x1F2E, 0x1F31, 0x1F33, - 0x1F3D, 0x1F3F, 0x1FD1, 0x1FD3, 0x1FDD, 0x1FDF, - 0x1FE0, 0x1FE2, 0x1FEE, 0x1FF1, 0x1FF3, 0x1FFD, - 0x1FFF, 0x2000, 0x2002, 0x200E, 0x2011, 0x2013, - 0x201D, 0x201F, 0x2020, 0x2022, 0x202E, 0x2031, - 0x2033, 0x203D, 0x203F, 0x20D1, 0x20D3, 0x20DD, - 0x20DF, 0x20E0, 0x20E2, 0x20EE, 0x20F1, 0x20F3, - 0x20FD, 0x20FF, 0x2101, 0x2103, 0x210D, 0x210F, - 0x2110, 0x2112, 0x211E, 0x2121, 0x2123, 0x212D, - 0x212F, 0x2130, 0x2132, 0x213E, 0x21D0, 0x21D2, - 0x21DE, 0x21E1, 0x21E3, 0x21ED, 0x21EF, 0x21F0, - 0x21F2, 0x21FE, 0x2200, 0x2202, 0x220E, 0x2211, - 0x2213, 0x221D, 0x221F, 0x2220, 0x2222, 0x222E, - 0x2231, 0x2233, 0x223D, 0x223F, 0x22D1, 0x22D3, - 0x22DD, 0x22DF, 0x22E0, 0x22E2, 0x22EE, 0x22F1, - 0x22F3, 0x22FD, 0x22FF, 0x2301, 0x2303, 0x230D, - 0x230F, 0x2310, 0x2312, 0x231E, 0x2321, 0x2323, - 0x232D, 0x232F, 0x2330, 0x2332, 0x233E, 0x23D0, - 0x23D2, 0x23DE, 0x23E1, 0x23E3, 0x23ED, 0x23EF, - 0x23F0, 0x23F2, 0x23FE, 0x2D01, 0x2D03, 0x2D0D, - 0x2D0F, 0x2D10, 0x2D12, 0x2D1E, 0x2D21, 0x2D23, - 0x2D2D, 0x2D2F, 0x2D30, 0x2D32, 0x2D3E, 0x2DD0, - 0x2DD2, 0x2DDE, 0x2DE1, 0x2DE3, 0x2DED, 0x2DEF, - 0x2DF0, 0x2DF2, 0x2DFE, 0x2E00, 0x2E02, 0x2E0E, - 0x2E11, 0x2E13, 0x2E1D, 0x2E1F, 0x2E20, 0x2E22, - 0x2E2E, 0x2E31, 0x2E33, 0x2E3D, 0x2E3F, 0x2ED1, - 0x2ED3, 0x2EDD, 0x2EDF, 0x2EE0, 0x2EE2, 0x2EEE, - 0x2EF1, 0x2EF3, 0x2EFD, 0x2EFF, 0x2F01, 0x2F03, - 0x2F0D, 0x2F0F, 0x2F10, 0x2F12, 0x2F1E, 0x2F21, - 0x2F23, 0x2F2D, 0x2F2F, 0x2F30, 0x2F32, 0x2F3E, - 0x2FD0, 0x2FD2, 0x2FDE, 0x2FE1, 0x2FE3, 0x2FED, - 0x2FEF, 0x2FF0, 0x2FF2, 0x2FFE, 0x3001, 0x3003, - 0x300D, 0x300F, 0x3010, 0x3012, 0x301E, 0x3021, - 0x3023, 0x302D, 0x302F, 0x3030, 0x3032, 0x303E, - 0x30D0, 0x30D2, 0x30DE, 0x30E1, 0x30E3, 0x30ED, - 0x30EF, 0x30F0, 0x30F2, 0x30FE, 0x3100, 0x3102, - 0x310E, 0x3111, 0x3113, 0x311D, 0x311F, 0x3120, - 0x3122, 0x312E, 0x3131, 0x3133, 0x313D, 0x313F, - 0x31D1, 0x31D3, 0x31DD, 0x31DF, 0x31E0, 0x31E2, - 0x31EE, 0x31F1, 0x31F3, 0x31FD, 0x31FF, 0x3201, - 0x3203, 0x320D, 0x320F, 0x3210, 0x3212, 0x321E, - 0x3221, 0x3223, 0x322D, 0x322F, 0x3230, 0x3232, - 0x323E, 0x32D0, 0x32D2, 0x32DE, 0x32E1, 0x32E3, - 0x32ED, 0x32EF, 0x32F0, 0x32F2, 0x32FE, 0x3300, - 0x3302, 0x330E, 0x3311, 0x3313, 0x331D, 0x331F, - 0x3320, 0x3322, 0x332E, 0x3331, 0x3333, 0x333D, - 0x333F, 0x33D1, 0x33D3, 0x33DD, 0x33DF, 0x33E0, - 0x33E2, 0x33EE, 0x33F1, 0x33F3, 0x33FD, 0x33FF, - 0x3D00, 0x3D02, 0x3D0E, 0x3D11, 0x3D13, 0x3D1D, - 0x3D1F, 0x3D20, 0x3D22, 0x3D2E, 0x3D31, 0x3D33, - 0x3D3D, 0x3D3F, 0x3DD1, 0x3DD3, 0x3DDD, 0x3DDF, - 0x3DE0, 0x3DE2, 0x3DEE, 0x3DF1, 0x3DF3, 0x3DFD, - 0x3DFF, 0x3E01, 0x3E03, 0x3E0D, 0x3E0F, 0x3E10, - 0x3E12, 0x3E1E, 0x3E21, 0x3E23, 0x3E2D, 0x3E2F, - 0x3E30, 0x3E32, 0x3E3E, 0x3ED0, 0x3ED2, 0x3EDE, - 0x3EE1, 0x3EE3, 0x3EED, 0x3EEF, 0x3EF0, 0x3EF2, - 0x3EFE, 0x3F00, 0x3F02, 0x3F0E, 0x3F11, 0x3F13, - 0x3F1D, 0x3F1F, 0x3F20, 0x3F22, 0x3F2E, 0x3F31, - 0x3F33, 0x3F3D, 0x3F3F, 0x3FD1, 0x3FD3, 0x3FDD, - 0x3FDF, 0x3FE0, 0x3FE2, 0x3FEE, 0x3FF1, 0x3FF3, - 0x3FFD, 0x3FFF, 0xD001, 0xD003, 0xD00D, 0xD00F, - 0xD010, 0xD012, 0xD01E, 0xD021, 0xD023, 0xD02D, - 0xD02F, 0xD030, 0xD032, 0xD03E, 0xD0D0, 0xD0D2, - 0xD0DE, 0xD0E1, 0xD0E3, 0xD0ED, 0xD0EF, 0xD0F0, - 0xD0F2, 0xD0FE, 0xD100, 0xD102, 0xD10E, 0xD111, - 0xD113, 0xD11D, 0xD11F, 0xD120, 0xD122, 0xD12E, - 0xD131, 0xD133, 0xD13D, 0xD13F, 0xD1D1, 0xD1D3, - 0xD1DD, 0xD1DF, 0xD1E0, 0xD1E2, 0xD1EE, 0xD1F1, - 0xD1F3, 0xD1FD, 0xD1FF, 0xD201, 0xD203, 0xD20D, - 0xD20F, 0xD210, 0xD212, 0xD21E, 0xD221, 0xD223, - 0xD22D, 0xD22F, 0xD230, 0xD232, 0xD23E, 0xD2D0, - 0xD2D2, 0xD2DE, 0xD2E1, 0xD2E3, 0xD2ED, 0xD2EF, - 0xD2F0, 0xD2F2, 0xD2FE, 0xD300, 0xD302, 0xD30E, - 0xD311, 0xD313, 0xD31D, 0xD31F, 0xD320, 0xD322, - 0xD32E, 0xD331, 0xD333, 0xD33D, 0xD33F, 0xD3D1, - 0xD3D3, 0xD3DD, 0xD3DF, 0xD3E0, 0xD3E2, 0xD3EE, - 0xD3F1, 0xD3F3, 0xD3FD, 0xD3FF, 0xDD00, 0xDD02, - 0xDD0E, 0xDD11, 0xDD13, 0xDD1D, 0xDD1F, 0xDD20, - 0xDD22, 0xDD2E, 0xDD31, 0xDD33, 0xDD3D, 0xDD3F, - 0xDDD1, 0xDDD3, 0xDDDD, 0xDDDF, 0xDDE0, 0xDDE2, - 0xDDEE, 0xDDF1, 0xDDF3, 0xDDFD, 0xDDFF, 0xDE01, - 0xDE03, 0xDE0D, 0xDE0F, 0xDE10, 0xDE12, 0xDE1E, - 0xDE21, 0xDE23, 0xDE2D, 0xDE2F, 0xDE30, 0xDE32, - 0xDE3E, 0xDED0, 0xDED2, 0xDEDE, 0xDEE1, 0xDEE3, - 0xDEED, 0xDEEF, 0xDEF0, 0xDEF2, 0xDEFE, 0xDF00, - 0xDF02, 0xDF0E, 0xDF11, 0xDF13, 0xDF1D, 0xDF1F, - 0xDF20, 0xDF22, 0xDF2E, 0xDF31, 0xDF33, 0xDF3D, - 0xDF3F, 0xDFD1, 0xDFD3, 0xDFDD, 0xDFDF, 0xDFE0, - 0xDFE2, 0xDFEE, 0xDFF1, 0xDFF3, 0xDFFD, 0xDFFF, - 0xE000, 0xE002, 0xE00E, 0xE011, 0xE013, 0xE01D, - 0xE01F, 0xE020, 0xE022, 0xE02E, 0xE031, 0xE033, - 0xE03D, 0xE03F, 0xE0D1, 0xE0D3, 0xE0DD, 0xE0DF, - 0xE0E0, 0xE0E2, 0xE0EE, 0xE0F1, 0xE0F3, 0xE0FD, - 0xE0FF, 0xE101, 0xE103, 0xE10D, 0xE10F, 0xE110, - 0xE112, 0xE11E, 0xE121, 0xE123, 0xE12D, 0xE12F, - 0xE130, 0xE132, 0xE13E, 0xE1D0, 0xE1D2, 0xE1DE, - 0xE1E1, 0xE1E3, 0xE1ED, 0xE1EF, 0xE1F0, 0xE1F2, - 0xE1FE, 0xE200, 0xE202, 0xE20E, 0xE211, 0xE213, - 0xE21D, 0xE21F, 0xE220, 0xE222, 0xE22E, 0xE231, - 0xE233, 0xE23D, 0xE23F, 0xE2D1, 0xE2D3, 0xE2DD, - 0xE2DF, 0xE2E0, 0xE2E2, 0xE2EE, 0xE2F1, 0xE2F3, - 0xE2FD, 0xE2FF, 0xE301, 0xE303, 0xE30D, 0xE30F, - 0xE310, 0xE312, 0xE31E, 0xE321, 0xE323, 0xE32D, - 0xE32F, 0xE330, 0xE332, 0xE33E, 0xE3D0, 0xE3D2, - 0xE3DE, 0xE3E1, 0xE3E3, 0xE3ED, 0xE3EF, 0xE3F0, - 0xE3F2, 0xE3FE, 0xED01, 0xED03, 0xED0D, 0xED0F, - 0xED10, 0xED12, 0xED1E, 0xED21, 0xED23, 0xED2D, - 0xED2F, 0xED30, 0xED32, 0xED3E, 0xEDD0, 0xEDD2, - 0xEDDE, 0xEDE1, 0xEDE3, 0xEDED, 0xEDEF, 0xEDF0, - 0xEDF2, 0xEDFE, 0xEE00, 0xEE02, 0xEE0E, 0xEE11, - 0xEE13, 0xEE1D, 0xEE1F, 0xEE20, 0xEE22, 0xEE2E, - 0xEE31, 0xEE33, 0xEE3D, 0xEE3F, 0xEED1, 0xEED3, - 0xEEDD, 0xEEDF, 0xEEE0, 0xEEE2, 0xEEEE, 0xEEF1, - 0xEEF3, 0xEEFD, 0xEEFF, 0xEF01, 0xEF03, 0xEF0D, - 0xEF0F, 0xEF10, 0xEF12, 0xEF1E, 0xEF21, 0xEF23, - 0xEF2D, 0xEF2F, 0xEF30, 0xEF32, 0xEF3E, 0xEFD0, - 0xEFD2, 0xEFDE, 0xEFE1, 0xEFE3, 0xEFED, 0xEFEF, - 0xEFF0, 0xEFF2, 0xEFFE, 0xF001, 0xF003, 0xF00D, - 0xF00F, 0xF010, 0xF012, 0xF01E, 0xF021, 0xF023, - 0xF02D, 0xF02F, 0xF030, 0xF032, 0xF03E, 0xF0D0, - 0xF0D2, 0xF0DE, 0xF0E1, 0xF0E3, 0xF0ED, 0xF0EF, - 0xF0F0, 0xF0F2, 0xF0FE, 0xF100, 0xF102, 0xF10E, - 0xF111, 0xF113, 0xF11D, 0xF11F, 0xF120, 0xF122, - 0xF12E, 0xF131, 0xF133, 0xF13D, 0xF13F, 0xF1D1, - 0xF1D3, 0xF1DD, 0xF1DF, 0xF1E0, 0xF1E2, 0xF1EE, - 0xF1F1, 0xF1F3, 0xF1FD, 0xF1FF, 0xF201, 0xF203, - 0xF20D, 0xF20F, 0xF210, 0xF212, 0xF21E, 0xF221, - 0xF223, 0xF22D, 0xF22F, 0xF230, 0xF232, 0xF23E, - 0xF2D0, 0xF2D2, 0xF2DE, 0xF2E1, 0xF2E3, 0xF2ED, - 0xF2EF, 0xF2F0, 0xF2F2, 0xF2FE, 0xF300, 0xF302, - 0xF30E, 0xF311, 0xF313, 0xF31D, 0xF31F, 0xF320, - 0xF322, 0xF32E, 0xF331, 0xF333, 0xF33D, 0xF33F, - 0xF3D1, 0xF3D3, 0xF3DD, 0xF3DF, 0xF3E0, 0xF3E2, - 0xF3EE, 0xF3F1, 0xF3F3, 0xF3FD, 0xF3FF, 0xFD00, - 0xFD02, 0xFD0E, 0xFD11, 0xFD13, 0xFD1D, 0xFD1F, - 0xFD20, 0xFD22, 0xFD2E, 0xFD31, 0xFD33, 0xFD3D, - 0xFD3F, 0xFDD1, 0xFDD3, 0xFDDD, 0xFDDF, 0xFDE0, - 0xFDE2, 0xFDEE, 0xFDF1, 0xFDF3, 0xFDFD, 0xFDFF, - 0xFE01, 0xFE03, 0xFE0D, 0xFE0F, 0xFE10, 0xFE12, - 0xFE1E, 0xFE21, 0xFE23, 0xFE2D, 0xFE2F, 0xFE30, - 0xFE32, 0xFE3E, 0xFED0, 0xFED2, 0xFEDE, 0xFEE1, - 0xFEE3, 0xFEED, 0xFEEF, 0xFEF0, 0xFEF2, 0xFEFE, - 0xFF00, 0xFF02, 0xFF0E, 0xFF11, 0xFF13, 0xFF1D, - 0xFF1F, 0xFF20, 0xFF22, 0xFF2E, 0xFF31, 0xFF33, - 0xFF3D, 0xFF3F, 0xFFD1, 0xFFD3, 0xFFDD, 0xFFDF, - 0xFFE0, 0xFFE2, 0xFFEE, 0xFFF1, 0xFFF3, 0xFFFD, - 0xFFFF, -}; - -#define ON2AVC_CB7_CODES 3281 -static const uint32_t on2avc_cb7_codes[ON2AVC_CB7_CODES] = { - 0x00000, 0x000EA, 0x000E6, 0x000F4, 0x000F6, 0x00047, - 0x003E2, 0x004A7, 0x00044, 0x004D3, 0x0082A, 0x0026E, - 0x0020E, 0x008A5, 0x02603, 0x02895, 0x049B0, 0x02894, - 0x007BE, 0x0069E, 0x01154, 0x01153, 0x0095F, 0x0038E, - 0x004AC, 0x0128E, 0x00E5E, 0x00992, 0x02A84, 0x0386A, - 0x03F6F, 0x01C54, 0x005D4, 0x00AFB, 0x001BE, 0x00258, - 0x00A59, 0x00043, 0x004A6, 0x004D7, 0x00040, 0x0006C, - 0x007FF, 0x00D39, 0x0005B, 0x00066, 0x0034A, 0x00124, - 0x004B6, 0x00626, 0x0071F, 0x014A3, 0x014A2, 0x0083E, - 0x032D4, 0x049B3, 0x0045E, 0x00ED5, 0x02896, 0x00ABA, - 0x0107B, 0x009EC, 0x0082C, 0x0082B, 0x00D38, 0x0072B, - 0x004FC, 0x049B2, 0x050B1, 0x003FE, 0x009EB, 0x049B1, - 0x00966, 0x00F75, 0x03F70, 0x007BC, 0x00054, 0x00394, - 0x000E8, 0x0052F, 0x0057A, 0x00458, 0x0FB4B, 0x01C55, - 0x00948, 0x032D6, 0x00ED6, 0x0A05F, 0x050B3, 0x00BBD, - 0x0197E, 0x024FC, 0x020C6, 0x0094A, 0x0386B, 0x1F2FF, - 0x050B4, 0x0A060, 0x0FB4C, 0x009ED, 0x02A85, 0x0FB4D, - 0x02605, 0x00ABB, 0x009A2, 0x0145B, 0x0A05D, 0x03F71, - 0x00BFF, 0x1F2FE, 0x0FB49, 0x0FB48, 0x050B2, 0x01155, - 0x01FD6, 0x032D5, 0x00976, 0x02604, 0x00A5A, 0x0A05E, - 0x0FB4A, 0x00DB9, 0x0A063, 0x1F307, 0x0FB4F, 0x1F306, - 0x049B4, 0x0FB50, 0x0FB51, 0x050B6, 0x1F308, 0x050B7, - 0x1F30A, 0x1F309, 0x0A064, 0x1F30B, 0x0A066, 0x06535, - 0x020C7, 0x0A065, 0x032D7, 0x0FB52, 0x02897, 0x0077A, - 0x03F72, 0x0FB4E, 0x050B5, 0x0076E, 0x1F301, 0x1F302, - 0x06533, 0x01FD7, 0x1F300, 0x0A061, 0x1F304, 0x1F303, - 0x07E54, 0x024FD, 0x1F305, 0x06534, 0x02606, 0x0A062, - 0x007C0, 0x0A06A, 0x1F30F, 0x0FB54, 0x0386D, 0x009E6, - 0x1F310, 0x06538, 0x00DBA, 0x014A4, 0x050B9, 0x1F311, - 0x0A06B, 0x0128F, 0x07E55, 0x1F312, 0x0FB55, 0x01C56, - 0x07E56, 0x0FB56, 0x1F313, 0x050BA, 0x01C57, 0x02608, - 0x0A067, 0x1F30D, 0x1F30C, 0x02607, 0x0386C, 0x0A069, - 0x0A068, 0x01557, 0x00ED7, 0x06536, 0x1F30E, 0x0FB53, - 0x02609, 0x007BF, 0x050B8, 0x06537, 0x00DE5, 0x00392, - 0x03F69, 0x0A055, 0x0FB3C, 0x0A054, 0x00AB7, 0x050AB, - 0x0FB3D, 0x00CE6, 0x009E8, 0x014A1, 0x049A8, 0x1F2ED, - 0x02890, 0x009E9, 0x049A9, 0x1F2EE, 0x032D1, 0x020C4, - 0x049AA, 0x0A056, 0x0FB3E, 0x0FB3F, 0x0A051, 0x0A052, - 0x0A053, 0x0FB39, 0x0A050, 0x0096E, 0x0FB3A, 0x1F2EB, - 0x029FE, 0x007FE, 0x0128D, 0x049A7, 0x1F2EC, 0x07E50, - 0x00E36, 0x03867, 0x0FB3B, 0x006EA, 0x03F6B, 0x1F2F4, - 0x1F2F3, 0x03868, 0x049AB, 0x1F2F6, 0x029FF, 0x1F2F5, - 0x0A05A, 0x07E52, 0x1F2F7, 0x07E51, 0x03F6C, 0x1F2FA, - 0x07E53, 0x025FF, 0x1F2F8, 0x1F2F9, 0x009A0, 0x06532, - 0x0FB45, 0x024FB, 0x008B9, 0x01D7D, 0x0FB40, 0x01FD3, - 0x0FB42, 0x0A058, 0x050AC, 0x0A057, 0x0FB41, 0x0A059, - 0x1F2F0, 0x1F2EF, 0x0FB43, 0x03F6A, 0x0FB44, 0x020C5, - 0x1F2F1, 0x1F2F2, 0x004FE, 0x02601, 0x00A58, 0x01FD5, - 0x049AD, 0x00A46, 0x02A80, 0x050AD, 0x009E5, 0x01B56, - 0x02A81, 0x00A36, 0x01556, 0x032D3, 0x02A82, 0x0FB47, - 0x1F2FD, 0x050AE, 0x004BA, 0x00A6B, 0x03F6D, 0x049AE, - 0x01317, 0x009A1, 0x00AB8, 0x02891, 0x03869, 0x01FD4, - 0x049AC, 0x1F2FB, 0x0FB46, 0x0A05B, 0x02600, 0x032D2, - 0x0137E, 0x01C53, 0x02892, 0x00BFE, 0x0A05C, 0x1F2FC, - 0x00CE7, 0x00058, 0x00FF7, 0x009EA, 0x00068, 0x00060, - 0x004D2, 0x004BD, 0x000EE, 0x003A4, 0x006E2, 0x0137F, - 0x0197D, 0x006EB, 0x050B0, 0x03F6E, 0x00E37, 0x00316, - 0x02893, 0x004CB, 0x006EE, 0x01152, 0x008AE, 0x0067E, - 0x00991, 0x0145A, 0x00AB9, 0x049AF, 0x02A83, 0x00A6C, - 0x0045F, 0x02602, 0x006E1, 0x050AF, 0x012D2, 0x0073F, - 0x00061, 0x00526, 0x004D6, 0x0013E, 0x003AE, 0x0005E, - 0x01D7E, 0x0289F, 0x00059, 0x0006A, 0x0082D, 0x00F77, - 0x009EE, 0x006E3, 0x00D3F, 0x1F32B, 0x02A8B, 0x00D3E, - 0x032DE, 0x0FB60, 0x02A8C, 0x020CC, 0x03874, 0x0045B, - 0x00DE8, 0x0082E, 0x00636, 0x012D6, 0x049B9, 0x0260C, - 0x01157, 0x06540, 0x0A073, 0x02504, 0x0289D, 0x050C2, - 0x00AFE, 0x0260D, 0x0289E, 0x00A6F, 0x0004E, 0x006EF, - 0x0099C, 0x00EDA, 0x0062E, 0x00048, 0x00A3A, 0x01292, - 0x013C2, 0x00A72, 0x0012A, 0x028A0, 0x02507, 0x00174, - 0x00DE9, 0x00ABF, 0x00EDE, 0x01146, 0x013C3, 0x032E1, - 0x049BA, 0x03875, 0x03876, 0x00824, 0x0077B, 0x032E2, - 0x01050, 0x00677, 0x00EDB, 0x0145C, 0x02505, 0x032DF, - 0x019C0, 0x050C3, 0x06541, 0x0A074, 0x032E0, 0x00A37, - 0x02506, 0x00ABE, 0x00E78, 0x02A8D, 0x001B4, 0x02A8E, - 0x01D7F, 0x001A4, 0x00DEA, 0x1F32F, 0x050C5, 0x009EF, - 0x00977, 0x020CD, 0x01B60, 0x019C3, 0x017DE, 0x0131A, - 0x0260F, 0x0A075, 0x01C5C, 0x0FB61, 0x07E62, 0x00E79, - 0x02610, 0x0A076, 0x014A7, 0x02611, 0x009FA, 0x007C1, - 0x0145D, 0x1F32C, 0x049BB, 0x019C1, 0x06543, 0x1F32D, - 0x06544, 0x01FD8, 0x06542, 0x01B5E, 0x06545, 0x1F32E, - 0x019C2, 0x005F4, 0x0260E, 0x050C4, 0x01B5F, 0x01C5B, - 0x032E3, 0x1F339, 0x1F33A, 0x1F338, 0x0FB63, 0x028A1, - 0x1F33B, 0x0FB64, 0x049BC, 0x0A07A, 0x1F33C, 0x0A07B, - 0x032E4, 0x07E63, 0x1F33E, 0x07E64, 0x1F33D, 0x0FB65, - 0x028A2, 0x02612, 0x02613, 0x050C6, 0x00967, 0x0155A, - 0x03F78, 0x1F330, 0x0A077, 0x03877, 0x0A078, 0x1F333, - 0x1F331, 0x1F332, 0x03878, 0x1F335, 0x1F336, 0x06546, - 0x1F334, 0x06547, 0x1F337, 0x0A079, 0x0FB62, 0x006FE, - 0x1F342, 0x0FB69, 0x008A7, 0x009FB, 0x1F343, 0x1F344, - 0x050C7, 0x0654A, 0x020CF, 0x1F345, 0x020CE, 0x01FD9, - 0x028A5, 0x0A07C, 0x0A07D, 0x050C8, 0x013C6, 0x03F7A, - 0x0A07E, 0x0387B, 0x01C5D, 0x03879, 0x06548, 0x1F33F, - 0x028A3, 0x00DBE, 0x03F79, 0x1F340, 0x0FB66, 0x028A4, - 0x008B2, 0x0FB67, 0x0387A, 0x0131B, 0x005D5, 0x06549, - 0x1F341, 0x0FB68, 0x0155B, 0x00DE6, 0x07E59, 0x1F318, - 0x00266, 0x00823, 0x01B57, 0x0FB58, 0x1F319, 0x0386F, - 0x01B58, 0x02899, 0x050BB, 0x00DBB, 0x01B59, 0x032D9, - 0x050BC, 0x1F31A, 0x03F74, 0x032DA, 0x0A06D, 0x06539, - 0x03870, 0x0386E, 0x1F315, 0x1F314, 0x024FE, 0x0176A, - 0x032D8, 0x0A06C, 0x1F316, 0x07E57, 0x014A5, 0x049B5, - 0x07E58, 0x00D3A, 0x0075B, 0x02898, 0x1F317, 0x0FB57, - 0x03F73, 0x01B5A, 0x0FB5B, 0x050BE, 0x1F31F, 0x0FB5A, - 0x0653B, 0x1F320, 0x0FB5C, 0x07E5C, 0x07E5D, 0x1F322, - 0x050BF, 0x0A06F, 0x1F321, 0x0FB5D, 0x1F325, 0x1F323, - 0x1F324, 0x01C58, 0x00ED8, 0x0289A, 0x1F326, 0x03F77, - 0x013C0, 0x0653A, 0x03F75, 0x1F31B, 0x024FF, 0x03F76, - 0x0FB59, 0x07E5A, 0x0A06E, 0x02500, 0x07E5B, 0x02A86, - 0x050BD, 0x1F31C, 0x032DB, 0x1F31E, 0x1F31D, 0x049B6, - 0x00C49, 0x1F329, 0x1F328, 0x00BBE, 0x008A6, 0x03871, - 0x01B5B, 0x02A88, 0x01558, 0x020C9, 0x0FB5F, 0x049B7, - 0x014A6, 0x07E5F, 0x1F32A, 0x0197F, 0x01B5C, 0x03872, - 0x00726, 0x01156, 0x02501, 0x0104F, 0x00C48, 0x032DC, - 0x0653C, 0x0176B, 0x1F327, 0x0653D, 0x0289B, 0x07E5E, - 0x0FB5E, 0x0176E, 0x0A071, 0x0A070, 0x0260A, 0x00993, - 0x020C8, 0x0176F, 0x02A87, 0x0289C, 0x00042, 0x00CE8, - 0x01C5A, 0x00F76, 0x008BA, 0x001C8, 0x02A8A, 0x02503, - 0x00136, 0x00A6E, 0x020CB, 0x00A5B, 0x008AF, 0x00ED9, - 0x03873, 0x0653F, 0x07E61, 0x050C1, 0x007A9, 0x0067F, - 0x013C1, 0x01559, 0x00D3B, 0x00DE7, 0x01B5D, 0x050C0, - 0x0260B, 0x02A89, 0x0653E, 0x0A072, 0x07E60, 0x049B8, - 0x00A6D, 0x02502, 0x00E5F, 0x012D3, 0x020CA, 0x0015D, - 0x032DD, 0x01C59, 0x0018E, 0x000E0, 0x07E77, 0x07E78, - 0x07E76, 0x049C5, 0x00BEA, 0x0A090, 0x0A08F, 0x00A3B, - 0x03F80, 0x0655A, 0x0655B, 0x050D1, 0x0A091, 0x1F37E, - 0x1F37F, 0x1F37C, 0x1F37D, 0x0FB77, 0x0655D, 0x050D2, - 0x1F380, 0x0655C, 0x02618, 0x049C3, 0x1F379, 0x0A08D, - 0x07E72, 0x07E73, 0x1F37B, 0x1F37A, 0x0A08E, 0x0145E, - 0x06558, 0x06559, 0x07E74, 0x049C4, 0x0083F, 0x07E75, - 0x0FB76, 0x007AA, 0x008A8, 0x1F382, 0x0FB7B, 0x007AB, - 0x004B2, 0x050D5, 0x07E7C, 0x07E7B, 0x032E8, 0x0261A, - 0x07E7D, 0x1F383, 0x03F81, 0x1F384, 0x0655F, 0x0FB7C, - 0x0A094, 0x0A095, 0x020D3, 0x1F385, 0x050D6, 0x050D7, - 0x01B61, 0x0FB78, 0x07E79, 0x028A7, 0x07E7A, 0x0A092, - 0x1F381, 0x050D3, 0x0FB79, 0x032E7, 0x0655E, 0x0A093, - 0x01DA2, 0x0053B, 0x02619, 0x050D4, 0x0FB7A, 0x020D2, - 0x0094B, 0x0A09A, 0x0FB7F, 0x0FB7E, 0x03884, 0x00C4A, - 0x0FB80, 0x1F38B, 0x019C6, 0x032E9, 0x01C5F, 0x0FB82, - 0x1F38C, 0x0FB81, 0x050D9, 0x07E7E, 0x1F38D, 0x1F38E, - 0x03885, 0x050DB, 0x07E7F, 0x06562, 0x050DA, 0x00E7A, - 0x02A92, 0x1F386, 0x0A096, 0x06560, 0x06561, 0x1F389, - 0x1F387, 0x1F388, 0x050D8, 0x0A098, 0x0FB7D, 0x02A93, - 0x0A097, 0x01FDC, 0x1F38A, 0x0A099, 0x020D4, 0x07E82, - 0x0FB89, 0x1F394, 0x07E81, 0x0A09E, 0x0FB8B, 0x1F395, - 0x07E83, 0x0FB8A, 0x028A8, 0x1F397, 0x1F396, 0x0A09F, - 0x0FB8C, 0x03F82, 0x049C6, 0x1F398, 0x1F399, 0x06563, - 0x02508, 0x03886, 0x07E84, 0x012E6, 0x0A09B, 0x1F38F, - 0x032EA, 0x0FB85, 0x1F390, 0x0FB86, 0x0FB83, 0x0FB84, - 0x0A09C, 0x1F392, 0x1F391, 0x0FB87, 0x02A94, 0x1F393, - 0x0A09D, 0x07E80, 0x0FB88, 0x006B6, 0x1F39D, 0x1F39E, - 0x0A0A1, 0x0A0A2, 0x0155E, 0x1F39F, 0x0A0A3, 0x02509, - 0x020D5, 0x0A0A4, 0x1F3A0, 0x07E86, 0x06564, 0x01FDE, - 0x0FB90, 0x049C8, 0x06565, 0x050DE, 0x0A0A6, 0x07E87, - 0x0A0A5, 0x06566, 0x00E7B, 0x049C7, 0x1F39A, 0x0A0A0, - 0x050DC, 0x00DEC, 0x07E85, 0x0FB8D, 0x01FDD, 0x00CE9, - 0x050DD, 0x0FB8E, 0x1F39B, 0x03F83, 0x0051F, 0x1F39C, - 0x0FB8F, 0x01293, 0x009A3, 0x049BE, 0x1F34E, 0x1F34D, - 0x0654B, 0x0115A, 0x0A07F, 0x0654C, 0x00A47, 0x01C5E, - 0x049BF, 0x1F350, 0x1F34F, 0x0387C, 0x07E67, 0x1F351, - 0x07E66, 0x02A8F, 0x1F353, 0x07E68, 0x1F354, 0x1F352, - 0x0A080, 0x00BBF, 0x1F347, 0x1F348, 0x1F346, 0x0FB6A, - 0x032E5, 0x07E65, 0x1F349, 0x006E4, 0x012D7, 0x049BD, - 0x1F34A, 0x0FB6B, 0x050C9, 0x00DEB, 0x1F34C, 0x1F34B, - 0x0052E, 0x07E6A, 0x1F35F, 0x1F35E, 0x0A081, 0x0387D, - 0x1F361, 0x0654F, 0x1F360, 0x0A082, 0x0387E, 0x1F363, - 0x1F362, 0x050CA, 0x0A084, 0x1F365, 0x03F7D, 0x0A083, - 0x1F364, 0x032E6, 0x1F366, 0x0A085, 0x06550, 0x020D0, - 0x1F356, 0x1F355, 0x00A73, 0x1F357, 0x1F358, 0x1F359, - 0x07E69, 0x0654D, 0x1F35B, 0x0FB6C, 0x1F35A, 0x0654E, - 0x03F7B, 0x1F35D, 0x03F7C, 0x0FB6D, 0x1F35C, 0x009AA, - 0x03880, 0x1F36B, 0x0A086, 0x1F36A, 0x01FDA, 0x1F36C, - 0x0A087, 0x01051, 0x049C2, 0x0FB71, 0x07E6E, 0x0A088, - 0x03F7E, 0x06553, 0x1F36E, 0x1F36D, 0x06552, 0x028A6, - 0x02A90, 0x0A089, 0x1F36F, 0x03881, 0x0074A, 0x049C0, - 0x0FB6F, 0x0FB6E, 0x02614, 0x0FB70, 0x1F368, 0x1F367, - 0x07E6B, 0x0387F, 0x049C1, 0x07E6C, 0x06551, 0x050CB, - 0x014AA, 0x07E6D, 0x1F369, 0x02615, 0x0072C, 0x1F373, - 0x1F372, 0x008BB, 0x00450, 0x07E70, 0x1F375, 0x1F374, - 0x050CE, 0x03882, 0x1F376, 0x0FB74, 0x02617, 0x1F377, - 0x1F378, 0x07E71, 0x06557, 0x0FB75, 0x050CF, 0x050D0, - 0x0A08C, 0x03883, 0x02A91, 0x06555, 0x050CC, 0x06554, - 0x0A08A, 0x1F370, 0x050CD, 0x06556, 0x0FB72, 0x02616, - 0x07E6F, 0x0A08B, 0x01FDB, 0x0053A, 0x03F7F, 0x0FB73, - 0x1F371, 0x020D1, 0x01FE0, 0x1F3F9, 0x1F3F8, 0x02A98, - 0x00C4E, 0x0A0B6, 0x0FBB1, 0x1F3FA, 0x0FBB0, 0x1F3FC, - 0x1F3FD, 0x1F3FB, 0x0A0B7, 0x1F400, 0x1F401, 0x1F402, - 0x1F3FE, 0x1F3FF, 0x1F404, 0x1F405, 0x0FBB2, 0x1F403, - 0x1F3EF, 0x1F3F0, 0x1F3ED, 0x1F3EE, 0x1F3F3, 0x1F3F4, - 0x0FBAB, 0x1F3F1, 0x1F3F2, 0x0A0B5, 0x1F3F6, 0x1F3F5, - 0x0FBAC, 0x01052, 0x0FBAF, 0x1F3F7, 0x0FBAD, 0x0FBAE, - 0x004BC, 0x1F40D, 0x1F40E, 0x1F40C, 0x0FBB8, 0x049CC, - 0x1F410, 0x1F40F, 0x03F87, 0x0A0B9, 0x0A0BA, 0x1F412, - 0x0FBB9, 0x1F411, 0x1F415, 0x1F416, 0x1F413, 0x1F414, - 0x1F418, 0x0A0BB, 0x0FBBA, 0x1F417, 0x07E95, 0x07E93, - 0x1F406, 0x1F407, 0x0A0B8, 0x07E92, 0x0FBB5, 0x1F408, - 0x0FBB3, 0x0FBB4, 0x07E94, 0x0FBB7, 0x1F409, 0x0FBB6, - 0x03F86, 0x01DA3, 0x1F40B, 0x1F40A, 0x019C7, 0x06572, - 0x1F421, 0x1F420, 0x0250F, 0x00DBF, 0x1F422, 0x1F423, - 0x0FBBE, 0x050E2, 0x049CD, 0x1F425, 0x1F424, 0x07E97, - 0x1F427, 0x0FBC0, 0x1F428, 0x0FBBF, 0x1F426, 0x1F42A, - 0x1F42B, 0x1F429, 0x0A0C0, 0x013C7, 0x0A0BD, 0x1F419, - 0x0A0BC, 0x1F41C, 0x1F41D, 0x1F41E, 0x1F41A, 0x1F41B, - 0x0FBBC, 0x1F41F, 0x06571, 0x0FBBB, 0x01FE1, 0x0FBBD, - 0x0A0BF, 0x0A0BE, 0x07E96, 0x0FBC6, 0x1F437, 0x1F438, - 0x1F435, 0x1F436, 0x0A0C3, 0x1F43A, 0x1F439, 0x0FBC7, - 0x1F43B, 0x0FBC9, 0x0FBCA, 0x0FBC8, 0x07E99, 0x0A0C4, - 0x07E9A, 0x1F43C, 0x1F43D, 0x1F43E, 0x0A0C5, 0x050E4, - 0x0FBCB, 0x0FBCC, 0x050E3, 0x07E98, 0x0FBC2, 0x1F42C, - 0x0FBC1, 0x1F42F, 0x1F430, 0x1F42D, 0x1F42E, 0x0A0C1, - 0x1F432, 0x1F433, 0x0FBC3, 0x1F431, 0x0FBC5, 0x1F434, - 0x0FBC4, 0x0A0C2, 0x00AF6, 0x1F444, 0x0FBCF, 0x0261C, - 0x014AB, 0x0A0C8, 0x1F446, 0x1F445, 0x06573, 0x0261D, - 0x1F448, 0x1F447, 0x02A99, 0x0FBD1, 0x0A0C9, 0x1F449, - 0x0FBD0, 0x06574, 0x1F44C, 0x049CF, 0x1F44A, 0x1F44B, - 0x032EC, 0x1F440, 0x1F43F, 0x07E9B, 0x01B62, 0x0388A, - 0x1F441, 0x07E9C, 0x0A0C6, 0x00D6A, 0x0A0C7, 0x0FBCD, - 0x049CE, 0x00EDF, 0x0FBCE, 0x1F443, 0x1F442, 0x07E9D, - 0x03888, 0x0FB91, 0x1F3A8, 0x00E96, 0x00CEA, 0x0FB93, - 0x0FB94, 0x0FB92, 0x1F3A9, 0x03889, 0x0FB95, 0x0A0A7, - 0x0155F, 0x050E0, 0x0A0A8, 0x1F3AB, 0x1F3AA, 0x07E89, - 0x07E8A, 0x0A0AA, 0x0FB96, 0x0A0A9, 0x06567, 0x1F3A2, - 0x1F3A1, 0x02A95, 0x0250A, 0x06568, 0x1F3A4, 0x1F3A3, - 0x050DF, 0x02A96, 0x1F3A5, 0x06569, 0x00C4B, 0x00AFF, - 0x03887, 0x1F3A7, 0x1F3A6, 0x07E88, 0x0261B, 0x1F3BC, - 0x1F3BD, 0x1F3BA, 0x1F3BB, 0x0656C, 0x0FB97, 0x1F3BE, - 0x0656B, 0x1F3C0, 0x0FB98, 0x1F3C1, 0x07E8C, 0x1F3BF, - 0x1F3C2, 0x0FB9A, 0x0FB99, 0x0A0AC, 0x0656D, 0x0FB9B, - 0x1F3C4, 0x1F3C3, 0x07E8D, 0x049C9, 0x0A0AB, 0x1F3AE, - 0x1F3AC, 0x1F3AD, 0x1F3B1, 0x1F3B2, 0x1F3AF, 0x1F3B0, - 0x1F3B5, 0x1F3B6, 0x1F3B7, 0x1F3B3, 0x1F3B4, 0x0656A, - 0x1F3B9, 0x1F3B8, 0x07E8B, 0x03F84, 0x1F3CF, 0x1F3CE, - 0x032EB, 0x0250B, 0x0FB9E, 0x0A0AF, 0x1F3D0, 0x0A0AE, - 0x0A0B1, 0x1F3D1, 0x0A0B0, 0x049CA, 0x1F3D3, 0x1F3D4, - 0x0FBA0, 0x0FB9F, 0x1F3D2, 0x0FBA1, 0x0A0B2, 0x1F3D5, - 0x07E90, 0x07E8E, 0x1F3C6, 0x1F3C5, 0x0656E, 0x1F3C7, - 0x1F3C8, 0x0656F, 0x07E8F, 0x0FB9C, 0x0A0AD, 0x0FB9D, - 0x1F3C9, 0x050E1, 0x01FDF, 0x1F3CC, 0x1F3CD, 0x1F3CA, - 0x1F3CB, 0x00410, 0x0FBA9, 0x1F3DF, 0x1F3DE, 0x0FBA8, - 0x02A97, 0x1F3E1, 0x1F3E0, 0x0250E, 0x0FBAA, 0x1F3E3, - 0x1F3E4, 0x07E91, 0x1F3E2, 0x1F3E7, 0x1F3E8, 0x1F3E5, - 0x1F3E6, 0x1F3EA, 0x1F3EB, 0x1F3EC, 0x1F3E9, 0x0A0B4, - 0x03F85, 0x0FBA4, 0x1F3D6, 0x0FBA2, 0x0FBA3, 0x1F3D8, - 0x0FBA6, 0x1F3D7, 0x0FBA5, 0x1F3DB, 0x0A0B3, 0x1F3DC, - 0x1F3D9, 0x1F3DA, 0x049CB, 0x0FBA7, 0x1F3DD, 0x06570, - 0x0014C, 0x1F4A6, 0x1F4A7, 0x1F4A5, 0x0FBE7, 0x00DEF, - 0x1F4A9, 0x1F4A8, 0x01166, 0x050EB, 0x050EC, 0x1F4AB, - 0x1F4AA, 0x0A0D7, 0x0FBE8, 0x1F4AD, 0x1F4AC, 0x0A0D8, - 0x0A0D9, 0x1F4B0, 0x1F4B1, 0x1F4AE, 0x1F4AF, 0x0FBE6, - 0x1F49C, 0x1F49D, 0x1F49B, 0x0FBE5, 0x07EA2, 0x1F49F, - 0x1F49E, 0x0A0D6, 0x019F6, 0x1F4A1, 0x1F4A2, 0x1F4A0, - 0x050EA, 0x01C9E, 0x1F4A4, 0x1F4A3, 0x0133A, 0x00E4E, - 0x1F4BE, 0x1F4BD, 0x00BEE, 0x001AE, 0x050EE, 0x1F4C0, - 0x1F4BF, 0x050ED, 0x020DA, 0x1F4C2, 0x1F4C1, 0x050EF, - 0x0FBEB, 0x1F4C3, 0x1F4C4, 0x0FBE9, 0x0FBEA, 0x1F4C6, - 0x1F4C7, 0x1F4C5, 0x0A0DC, 0x1F4B4, 0x1F4B5, 0x1F4B2, - 0x1F4B3, 0x03F8A, 0x1F4B7, 0x1F4B8, 0x1F4B6, 0x0A0DA, - 0x02A9B, 0x1F4BA, 0x1F4B9, 0x0145F, 0x004AD, 0x0A0DB, - 0x1F4BC, 0x1F4BB, 0x03F8B, 0x003A6, 0x0A0DE, 0x1F4D1, - 0x1F4D0, 0x0FBED, 0x00DCA, 0x0FBEE, 0x1F4D2, 0x00EFE, - 0x02096, 0x0A0DF, 0x1F4D4, 0x1F4D3, 0x07EA6, 0x0FBEF, - 0x1F4D6, 0x1F4D5, 0x0A0E0, 0x1F4D9, 0x1F4DA, 0x1F4DB, - 0x1F4D7, 0x1F4D8, 0x07EA3, 0x1F4CA, 0x1F4CB, 0x1F4C8, - 0x1F4C9, 0x0388E, 0x0FBEC, 0x1F4CC, 0x049D8, 0x00CEB, - 0x0657A, 0x0A0DD, 0x1F4CD, 0x049D9, 0x00521, 0x1F4CF, - 0x1F4CE, 0x00CFA, 0x01B67, 0x1F4E4, 0x1F4E3, 0x032EF, - 0x00292, 0x0FBF2, 0x1F4E6, 0x1F4E5, 0x0FBF1, 0x014D2, - 0x0A0E5, 0x0A0E4, 0x028AA, 0x1F4E9, 0x0657F, 0x1F4EA, - 0x1F4E7, 0x1F4E8, 0x1F4ED, 0x1F4EE, 0x1F4EB, 0x1F4EC, - 0x0412E, 0x1F4DC, 0x0A0E1, 0x0A0E2, 0x049DA, 0x1F4DE, - 0x1F4DF, 0x1F4DD, 0x0657B, 0x01B66, 0x1F4E0, 0x0FBF0, - 0x0388F, 0x00522, 0x0A0E3, 0x1F4E2, 0x1F4E1, 0x0657E, - 0x007C2, 0x0A0EB, 0x1F4F8, 0x1F4F7, 0x0FBF5, 0x00F7A, - 0x1F4F9, 0x0FBF6, 0x020DB, 0x028AB, 0x1F4FB, 0x1F4FC, - 0x1F4FA, 0x0FBF7, 0x01DFE, 0x0BEFA, 0x1F4FD, 0x07EA7, - 0x1F502, 0x13FC2, 0x1F503, 0x1F4FE, 0x1F4FF, 0x1F4F1, - 0x0FBF3, 0x1F4F2, 0x1F4EF, 0x1F4F0, 0x02576, 0x0A0E7, - 0x1F4F3, 0x0A0E6, 0x07092, 0x0FBF4, 0x1F4F5, 0x1F4F4, - 0x049DB, 0x0096F, 0x1F4F6, 0x0A0EA, 0x02623, 0x006FF, - 0x1F45C, 0x1F45D, 0x1F45B, 0x07E9E, 0x03F88, 0x1F45F, - 0x1F45E, 0x020D7, 0x06575, 0x1F462, 0x0FBD2, 0x1F460, - 0x1F461, 0x1F464, 0x0FBD4, 0x0FBD3, 0x1F463, 0x1F467, - 0x1F468, 0x1F469, 0x1F465, 0x1F466, 0x1F44F, 0x1F450, - 0x1F451, 0x1F44D, 0x1F44E, 0x1F453, 0x1F454, 0x1F452, - 0x020D6, 0x0388B, 0x1F457, 0x1F458, 0x1F455, 0x1F456, - 0x028A9, 0x1F45A, 0x1F459, 0x00DED, 0x020D8, 0x1F472, - 0x1F471, 0x0261F, 0x006F0, 0x0FBD6, 0x1F474, 0x1F473, - 0x050E5, 0x049D3, 0x0FBD7, 0x1F475, 0x015EE, 0x1F477, - 0x0A0CD, 0x1F478, 0x1F476, 0x050E6, 0x1F47A, 0x1F47B, - 0x1F479, 0x0A0CE, 0x0A0CB, 0x1F46A, 0x0A0CA, 0x0261E, - 0x049D0, 0x0A0CC, 0x1F46C, 0x1F46B, 0x06576, 0x049D1, - 0x1F46E, 0x1F46D, 0x01FE2, 0x004DE, 0x049D2, 0x1F470, - 0x1F46F, 0x0FBD5, 0x00376, 0x0FBDB, 0x0FBDC, 0x1F482, - 0x0A0D0, 0x00C5E, 0x1F484, 0x1F483, 0x00BEB, 0x020D9, - 0x06578, 0x1F486, 0x1F485, 0x07E9F, 0x0A0D1, 0x1F487, - 0x07EA0, 0x050E8, 0x1F488, 0x0FBDF, 0x1F489, 0x0FBDD, - 0x0FBDE, 0x050E7, 0x0A0CF, 0x1F47D, 0x1F47C, 0x0FBD8, - 0x06577, 0x1F47F, 0x1F47E, 0x032ED, 0x012BA, 0x03F89, - 0x0FBD9, 0x1F480, 0x032EE, 0x00C4F, 0x1F481, 0x0FBDA, - 0x01B63, 0x00DEE, 0x0FBE1, 0x1F491, 0x0115B, 0x001CE, - 0x049D6, 0x1F493, 0x1F492, 0x0A0D4, 0x049D7, 0x1F495, - 0x1F494, 0x02A9A, 0x0A0D5, 0x0FBE3, 0x1F497, 0x1F496, - 0x0FBE2, 0x0FBE4, 0x1F49A, 0x1F498, 0x1F499, 0x049D4, - 0x1F48A, 0x0A0D2, 0x0FBE0, 0x049D5, 0x0A0D3, 0x1F48C, - 0x1F48B, 0x07EA1, 0x01FE3, 0x1F48E, 0x1F48D, 0x02622, - 0x00520, 0x050E9, 0x1F490, 0x1F48F, 0x06579, 0x0018A, - 0x09FE6, 0x1F0E6, 0x1F0E5, 0x0459C, 0x00DCB, 0x1F0E7, - 0x0FA96, 0x012D0, 0x020A6, 0x1F0E9, 0x1F0EA, 0x1F0E8, - 0x0FA97, 0x09FE7, 0x1F0EC, 0x1F0EB, 0x06370, 0x09FE8, - 0x1F0EE, 0x1F0EF, 0x0FA98, 0x1F0ED, 0x1F0DC, 0x1F0DD, - 0x1F0DE, 0x1F0DA, 0x1F0DB, 0x1F0DF, 0x1F0E0, 0x0FA93, - 0x0FA94, 0x0507C, 0x1F0E2, 0x1F0E3, 0x1F0E1, 0x0507B, - 0x00AAE, 0x1F0E4, 0x0FA95, 0x00F5D, 0x00DB4, 0x0FA9C, - 0x1F0F9, 0x00FF2, 0x003AC, 0x1F0FB, 0x1F0FC, 0x1F0FA, - 0x029E0, 0x025CF, 0x1F0FE, 0x1F0FD, 0x029E1, 0x029E2, - 0x09FE9, 0x1F180, 0x1F0FF, 0x07E04, 0x0FA9D, 0x1F183, - 0x1F181, 0x1F182, 0x0FA9A, 0x1F0F1, 0x0FA99, 0x1F0F0, - 0x0384C, 0x1F0F3, 0x1F0F4, 0x1F0F2, 0x0FA9B, 0x019F7, - 0x1F0F6, 0x1F0F5, 0x02878, 0x0018C, 0x06371, 0x1F0F8, - 0x1F0F7, 0x07E03, 0x002FC, 0x0507E, 0x1F18E, 0x1F18D, - 0x06373, 0x00D2C, 0x1F190, 0x1F18F, 0x01356, 0x01357, - 0x0FAA0, 0x1F192, 0x1F191, 0x0507F, 0x02879, 0x1F194, - 0x1F193, 0x0384D, 0x1F197, 0x0FAA1, 0x0FAA2, 0x1F195, - 0x1F196, 0x1F186, 0x1F187, 0x1F188, 0x1F184, 0x1F185, - 0x0507D, 0x1F189, 0x0FA9E, 0x06372, 0x020A7, 0x07E05, - 0x1F18B, 0x1F18A, 0x09FEA, 0x00AF8, 0x0FA9F, 0x1F18C, - 0x00A30, 0x0106F, 0x1F19F, 0x1F19E, 0x01AD6, 0x005F6, - 0x1F1A1, 0x1F1A2, 0x1F1A0, 0x0FAA8, 0x0099E, 0x0FAA9, - 0x1F1A3, 0x06375, 0x0459E, 0x07E07, 0x1F1A6, 0x1F1A4, - 0x1F1A5, 0x09FEC, 0x0FAAA, 0x1F1A7, 0x09FEB, 0x0FAA4, - 0x1F199, 0x1F198, 0x0FAA3, 0x0FAA6, 0x0459D, 0x1F19B, - 0x1F19A, 0x0FAA5, 0x01C49, 0x07E06, 0x1F19C, 0x03F56, - 0x0077E, 0x05080, 0x1F19D, 0x0FAA7, 0x06374, 0x008A2, - 0x1F1B3, 0x1F1B4, 0x0FAAE, 0x1F1B2, 0x00AB0, 0x1F1B6, - 0x1F1B5, 0x04980, 0x0384E, 0x0FAAF, 0x1F1B8, 0x1F1B7, - 0x06377, 0x04981, 0x1F1BA, 0x1F1B9, 0x07E09, 0x07E0A, - 0x1F1BC, 0x1F1BD, 0x1F1BB, 0x0FAB0, 0x1F1AA, 0x1F1AB, - 0x1F1AC, 0x1F1A8, 0x1F1A9, 0x0FAAC, 0x07E08, 0x0FAAB, - 0x1F1AD, 0x029E3, 0x06376, 0x0FAAD, 0x1F1AE, 0x1F1AF, - 0x0459F, 0x1F1B1, 0x1F1B0, 0x01AD7, 0x00822, 0x1DFF2, - 0x1DFF3, 0x1DFF1, 0x0FA82, 0x03F52, 0x1DFF5, 0x1DFF4, - 0x00BF6, 0x062F8, 0x07DFD, 0x1DFF7, 0x1DFF6, 0x09FE0, - 0x062F9, 0x1DFF9, 0x1DFF8, 0x029A6, 0x0FA83, 0x1DFFC, - 0x1DFFD, 0x1DFFA, 0x1DFFB, 0x13FC3, 0x17DF6, 0x17DF7, - 0x0FA80, 0x0412F, 0x05074, 0x1C24C, 0x05F7C, 0x05F7E, - 0x03848, 0x05F7F, 0x1C24E, 0x1C24D, 0x07DFC, 0x01FC6, - 0x1DFF0, 0x1C24F, 0x02577, 0x029A7, 0x1EF67, 0x1EF66, - 0x024EE, 0x003BE, 0x0FA88, 0x1EF69, 0x1EF68, 0x062FA, - 0x0384B, 0x1EF6B, 0x1EF6A, 0x015EF, 0x05076, 0x0FA89, - 0x1EF6D, 0x1EF6C, 0x07E00, 0x1EF6F, 0x0FA8A, 0x1EF6E, - 0x062FB, 0x1EF60, 0x0FA84, 0x1DFFE, 0x1DFFF, 0x07DFE, - 0x0FA85, 0x1EF62, 0x1EF61, 0x03F54, 0x0384A, 0x1EF63, - 0x0FA86, 0x00E30, 0x002EC, 0x0FA87, 0x1EF65, 0x1EF64, - 0x07DFF, 0x002FE, 0x09FE3, 0x1EF7C, 0x1EF7B, 0x07E01, - 0x0095C, 0x1EF7E, 0x1EF7D, 0x01456, 0x0133B, 0x05077, - 0x1F0C0, 0x1EF7F, 0x062FD, 0x05078, 0x1F0C2, 0x1F0C1, - 0x01C46, 0x03F55, 0x1F0C4, 0x1F0C5, 0x1F0C3, 0x0FA8D, - 0x1EF72, 0x1EF73, 0x1EF74, 0x1EF70, 0x1EF71, 0x062FC, - 0x1EF75, 0x0FA8B, 0x09FE2, 0x0154E, 0x1EF78, 0x0FA8C, - 0x1EF76, 0x1EF77, 0x00F5C, 0x1EF7A, 0x1EF79, 0x00DB2, - 0x0106E, 0x1F0D3, 0x1F0D2, 0x00ED0, 0x0045A, 0x07E02, - 0x0FA8F, 0x1F0D4, 0x1F0D5, 0x01C48, 0x0FA91, 0x0FA90, - 0x025CE, 0x032BE, 0x062FF, 0x1F0D7, 0x1F0D6, 0x0FA92, - 0x09FE5, 0x1F0D9, 0x1F0D8, 0x09FE4, 0x1F0C8, 0x1F0C9, - 0x1F0C6, 0x1F0C7, 0x05079, 0x1F0CB, 0x1F0CC, 0x1F0CA, - 0x0FA8E, 0x0507A, 0x1F0CE, 0x1F0CD, 0x024EF, 0x0018F, - 0x1F0D0, 0x1F0D1, 0x1F0CF, 0x062FE, 0x04986, 0x1F211, - 0x1F210, 0x029E5, 0x0149C, 0x09FFF, 0x1F212, 0x0FAD5, - 0x0FAD6, 0x0FAD8, 0x1F214, 0x1F213, 0x0FAD7, 0x0A000, - 0x0A001, 0x1F216, 0x1F215, 0x0FAD9, 0x0A003, 0x0FADA, - 0x1F217, 0x0A002, 0x0FAD1, 0x1F205, 0x1F203, 0x1F204, - 0x1F207, 0x1F208, 0x1F209, 0x1F206, 0x0FAD2, 0x1F20C, - 0x0FAD3, 0x1F20A, 0x1F20B, 0x00E31, 0x0FAD4, 0x1F20F, - 0x1F20D, 0x1F20E, 0x003BC, 0x1F221, 0x0FADD, 0x1F21F, - 0x1F220, 0x01D2E, 0x1F223, 0x1F222, 0x0384F, 0x0A007, - 0x1F225, 0x1F226, 0x07E18, 0x1F224, 0x1F229, 0x1F22A, - 0x1F227, 0x1F228, 0x01ADD, 0x0A009, 0x1F22B, 0x0A008, - 0x04987, 0x0FADC, 0x07E16, 0x1F218, 0x0FADB, 0x07E15, - 0x1F21B, 0x1F21C, 0x1F219, 0x1F21A, 0x0637A, 0x0A005, - 0x0A006, 0x07E17, 0x0A004, 0x025F0, 0x1F21E, 0x1F21D, - 0x01ADC, 0x05088, 0x1F235, 0x1F234, 0x05087, 0x01978, - 0x1F238, 0x07E1A, 0x1F236, 0x1F237, 0x07E1C, 0x1F239, - 0x0FAE2, 0x07E1B, 0x1F23B, 0x0A00D, 0x1F23C, 0x1F23A, - 0x0FAE3, 0x01979, 0x0A00E, 0x1F23D, 0x04989, 0x1F22E, - 0x1F22F, 0x1F22C, 0x1F22D, 0x1F231, 0x0A00A, 0x1F232, - 0x0FADE, 0x1F230, 0x04988, 0x0FADF, 0x1F233, 0x07E19, - 0x01ADE, 0x0A00C, 0x0FAE1, 0x0FAE0, 0x0A00B, 0x032C2, - 0x1F249, 0x1F24A, 0x1F248, 0x0A010, 0x05089, 0x1F24C, - 0x0A011, 0x1F24B, 0x0A012, 0x0FAEA, 0x1F24E, 0x0508A, - 0x1F24D, 0x0A014, 0x1F250, 0x0A013, 0x1F24F, 0x029E6, - 0x07E1D, 0x1F253, 0x1F251, 0x1F252, 0x0FAE4, 0x0FAE5, - 0x0FAE6, 0x1F23E, 0x1F23F, 0x1F242, 0x0A00F, 0x1F240, - 0x1F241, 0x0FAE8, 0x1F244, 0x1F245, 0x0FAE7, 0x1F243, - 0x0FAE9, 0x1F247, 0x1F246, 0x03850, 0x01286, 0x1F25E, - 0x1F25D, 0x03851, 0x00D2D, 0x1F260, 0x1F261, 0x1F25F, - 0x07E1E, 0x00A68, 0x1F262, 0x0A015, 0x0637C, 0x0508C, - 0x0498A, 0x1F265, 0x1F263, 0x1F264, 0x03852, 0x0FAEE, - 0x1F266, 0x0A016, 0x0FAEB, 0x0FAEC, 0x1F254, 0x1F255, - 0x1F258, 0x0637B, 0x1F259, 0x1F256, 0x1F257, 0x032C3, - 0x0FAED, 0x0508B, 0x03F59, 0x01310, 0x032C4, 0x1F25C, - 0x1F25A, 0x1F25B, 0x04982, 0x09FEE, 0x1F1C4, 0x00FF3, - 0x01457, 0x06378, 0x1F1C6, 0x1F1C5, 0x0FAB4, 0x0287B, - 0x0FAB6, 0x0FAB5, 0x00FF6, 0x03F57, 0x0FAB7, 0x09FEF, - 0x1F1C7, 0x05083, 0x09FF0, 0x1F1C8, 0x0FAB8, 0x01FC8, - 0x09FED, 0x0FAB2, 0x0FAB1, 0x1F1BE, 0x07E0B, 0x05081, - 0x0FAB3, 0x1F1BF, 0x024F0, 0x0287A, 0x1F1C1, 0x1F1C0, - 0x01FC7, 0x00E5A, 0x05082, 0x1F1C3, 0x1F1C2, 0x07E0C, - 0x032C0, 0x0FABE, 0x0FABF, 0x1F1D1, 0x1F1D2, 0x07E10, - 0x1F1D5, 0x1F1D3, 0x1F1D4, 0x0FAC2, 0x0FAC3, 0x1F1D6, - 0x0FAC0, 0x0FAC1, 0x1F1D9, 0x1F1DA, 0x1F1D7, 0x1F1D8, - 0x05085, 0x09FF2, 0x1F1DC, 0x1F1DB, 0x0FAC4, 0x0FAB9, - 0x0FABA, 0x1F1CA, 0x07E0D, 0x1F1C9, 0x1F1CB, 0x1F1CC, - 0x07E0E, 0x0FABB, 0x0FABD, 0x1F1CD, 0x1F1CE, 0x0FABC, - 0x09FF1, 0x07E0F, 0x1F1D0, 0x1F1CF, 0x05084, 0x0287C, - 0x1F1E6, 0x1F1E5, 0x03F58, 0x0287D, 0x09FF6, 0x1F1E9, - 0x1F1E7, 0x1F1E8, 0x07E13, 0x09FF8, 0x1F1EA, 0x09FF7, - 0x1F1ED, 0x09FF9, 0x0FAC8, 0x1F1EB, 0x1F1EC, 0x09FFB, - 0x04984, 0x09FFA, 0x04983, 0x09FF3, 0x1F1DE, 0x1F1DD, - 0x07E11, 0x1F1DF, 0x1F1E0, 0x0FAC6, 0x09FF4, 0x0FAC5, - 0x07E12, 0x1F1E2, 0x1F1E1, 0x05086, 0x00ED2, 0x09FF5, - 0x1F1E4, 0x1F1E3, 0x0FAC7, 0x004D4, 0x1F1F9, 0x1F1FA, - 0x09FFC, 0x0FACD, 0x029E4, 0x0FACE, 0x1F1FB, 0x0287E, - 0x09FFD, 0x0FAD0, 0x1F1FC, 0x0FACF, 0x06379, 0x1F1FE, - 0x1F1FF, 0x1F1FD, 0x09FFE, 0x04985, 0x07E14, 0x1F202, - 0x1F200, 0x1F201, 0x1F1EF, 0x1F1F0, 0x1F1F1, 0x1F1EE, - 0x0FAC9, 0x1F1F3, 0x1F1F4, 0x1F1F2, 0x0FACA, 0x032C1, - 0x1F1F6, 0x0FACC, 0x1F1F5, 0x0FACB, 0x01C9F, 0x1F1F8, - 0x1F1F7, 0x01FC9, 0x000EC, 0x0650B, 0x0650C, 0x07E2B, - 0x029EC, 0x00DB6, 0x0FB04, 0x1F298, 0x0098C, 0x01FCC, - 0x0650D, 0x07E2C, 0x0FB05, 0x0FB06, 0x0FB08, 0x1F29A, - 0x1F299, 0x0FB07, 0x00ED3, 0x05094, 0x1F29B, 0x07E2D, - 0x0FB09, 0x03855, 0x06508, 0x0FB02, 0x1F292, 0x0FB01, - 0x1F295, 0x1F296, 0x1F293, 0x1F294, 0x05093, 0x0FB03, - 0x0650A, 0x07E2A, 0x06509, 0x00BB6, 0x0A02B, 0x1F297, - 0x00A54, 0x00708, 0x1F2A2, 0x1F2A1, 0x007A8, 0x004CA, - 0x029EE, 0x07E2F, 0x05095, 0x0197B, 0x01C4A, 0x0A02D, - 0x07E30, 0x01FCD, 0x0FB0C, 0x0650F, 0x0FB0D, 0x1F2A3, - 0x0650E, 0x01D78, 0x06510, 0x07E31, 0x07E32, 0x04993, - 0x07E2E, 0x0A02C, 0x03F5D, 0x1F29E, 0x1F29F, 0x03856, - 0x1F29C, 0x1F29D, 0x03857, 0x0FB0A, 0x1F2A0, 0x029ED, - 0x004B8, 0x024F5, 0x03F5E, 0x0FB0B, 0x03858, 0x008AC, - 0x0FB13, 0x07E35, 0x0FB12, 0x06512, 0x01C4C, 0x07E36, - 0x0FB14, 0x01550, 0x02882, 0x07E37, 0x07E38, 0x06513, - 0x05096, 0x06514, 0x0A032, 0x1F2A7, 0x1F2A8, 0x006E7, - 0x032CA, 0x1F2A9, 0x0FB15, 0x029EF, 0x07E34, 0x0A02E, - 0x0A02F, 0x0FB0E, 0x07E33, 0x0FB10, 0x06511, 0x1F2A4, - 0x0FB0F, 0x04994, 0x02881, 0x0A031, 0x0A030, 0x0FB11, - 0x01289, 0x1F2A6, 0x1F2A5, 0x01C4B, 0x05098, 0x1F2AE, - 0x1F2AD, 0x07E3A, 0x06519, 0x1F2AF, 0x1F2B0, 0x0FB19, - 0x0A038, 0x05099, 0x1F2B2, 0x1F2B1, 0x07E3B, 0x0FB1A, - 0x1F2B4, 0x1F2B5, 0x04995, 0x1F2B3, 0x0149D, 0x03F60, - 0x0FB1B, 0x025F2, 0x0A033, 0x06516, 0x06515, 0x03F5F, - 0x0A035, 0x1F2AA, 0x07E39, 0x0A034, 0x0FB16, 0x06517, - 0x1F2AC, 0x1F2AB, 0x0FB17, 0x05097, 0x0A036, 0x0A037, - 0x0FB18, 0x06518, 0x0031A, 0x0A03C, 0x1F2BA, 0x1F2B9, - 0x07E3F, 0x0057E, 0x0FB1C, 0x1F2BB, 0x00F5E, 0x01551, - 0x025F3, 0x1F2BC, 0x07E40, 0x04996, 0x00BB8, 0x1F2BD, - 0x04997, 0x0385A, 0x00E32, 0x0651D, 0x1F2BF, 0x1F2BE, - 0x07E41, 0x0651A, 0x0A03A, 0x1F2B7, 0x1F2B6, 0x0A039, - 0x03859, 0x07E3D, 0x07E3C, 0x0509A, 0x029F0, 0x0651C, - 0x0A03B, 0x0651B, 0x07E3E, 0x0096A, 0x1F2B8, 0x0509B, - 0x01D79, 0x0073E, 0x0A01C, 0x1F26B, 0x1F26A, 0x0FAF0, - 0x01312, 0x0FAF1, 0x1F26C, 0x0074E, 0x00DE2, 0x0637D, - 0x0FAF2, 0x1F26D, 0x029E9, 0x025F1, 0x0508D, 0x1F26E, - 0x0072A, 0x01288, 0x1F270, 0x1F271, 0x1F26F, 0x0637E, - 0x1F267, 0x0A018, 0x0498B, 0x0A017, 0x029E7, 0x0A019, - 0x0A01A, 0x1F268, 0x029E8, 0x0175C, 0x0287F, 0x0A01B, - 0x1F269, 0x03F5A, 0x02880, 0x0498C, 0x0FAEF, 0x00DB5, - 0x07E1F, 0x1F27B, 0x1F27A, 0x0FAF4, 0x024F1, 0x1F27E, - 0x0A01F, 0x1F27C, 0x1F27D, 0x0FAF5, 0x1F280, 0x1F27F, - 0x06502, 0x0FAF6, 0x1F282, 0x07E21, 0x07E20, 0x1F281, - 0x029EA, 0x07E23, 0x07E22, 0x0154F, 0x0637F, 0x06500, - 0x0498D, 0x0FAF3, 0x1F272, 0x1F273, 0x0A01D, 0x0508E, - 0x032C5, 0x1F275, 0x1F276, 0x1F274, 0x06501, 0x03853, - 0x0A01E, 0x1F279, 0x1F277, 0x1F278, 0x0074F, 0x03854, - 0x032C7, 0x0FAFA, 0x1F286, 0x029EB, 0x07E25, 0x0A024, - 0x024F3, 0x01FCA, 0x0508F, 0x032C8, 0x1F287, 0x0A025, - 0x07E26, 0x0A026, 0x1F288, 0x1F289, 0x006E6, 0x0498E, - 0x1F28B, 0x1F28A, 0x032C9, 0x032C6, 0x0A021, 0x0A022, - 0x0A020, 0x03F5B, 0x1F283, 0x1F284, 0x06503, 0x0FAF7, - 0x024F2, 0x07E24, 0x1F285, 0x0FAF8, 0x01313, 0x01ADF, - 0x0FAF9, 0x0A023, 0x00AB1, 0x0055E, 0x1F28F, 0x1F28E, - 0x00972, 0x005FA, 0x024F4, 0x0FAFE, 0x1F290, 0x04990, - 0x020BC, 0x0FAFF, 0x1F291, 0x01D2F, 0x04991, 0x0A02A, - 0x05092, 0x0A029, 0x0FB00, 0x04992, 0x06507, 0x06506, - 0x01FCB, 0x03F5C, 0x05090, 0x06504, 0x0A027, 0x1F28C, - 0x1F28D, 0x07E28, 0x07E27, 0x0A028, 0x05091, 0x0FAFC, - 0x0FAFB, 0x0197A, 0x003D6, 0x0FAFD, 0x07E29, 0x0498F, - 0x06505, 0x00056, 0x020C0, 0x02888, 0x0005C, 0x0005A, - 0x0071E, 0x00CE4, 0x00A32, 0x005D6, 0x00A34, 0x0288A, - 0x02889, 0x00A33, 0x049A2, 0x0A046, 0x01D7A, 0x025F9, - 0x0A045, 0x01315, 0x01316, 0x07E4B, 0x01458, 0x00676, - 0x00F71, 0x01B51, 0x006FD, 0x07E4A, 0x06529, 0x01768, - 0x00AB3, 0x07E49, 0x009E4, 0x03F64, 0x050A1, 0x00DE3, - 0x00064, 0x008B8, 0x00AB4, 0x00BBB, 0x007FA, 0x0003C, - 0x009E7, 0x00AFA, 0x01459, 0x00AB5, 0x001AF, 0x03862, - 0x0288C, 0x0019E, 0x00BFD, 0x01C51, 0x0149F, 0x00F73, - 0x029FA, 0x07E4C, 0x0A047, 0x1F2D4, 0x03863, 0x00F74, - 0x01B52, 0x01B53, 0x050A2, 0x0137D, 0x006E8, 0x008A4, - 0x029F9, 0x00E33, 0x006E0, 0x03F65, 0x049A3, 0x1F2D3, - 0x03861, 0x00A35, 0x0197C, 0x00F72, 0x012D1, 0x0288B, - 0x0015C, 0x01FCF, 0x049A4, 0x001A6, 0x00BBC, 0x1F2D5, - 0x0A048, 0x00AB6, 0x0075A, 0x020C2, 0x03864, 0x0104E, - 0x050A5, 0x01D7B, 0x0A049, 0x1F2D6, 0x024F8, 0x0652B, - 0x1F2D7, 0x03865, 0x025FA, 0x07E4E, 0x014A0, 0x0652C, - 0x029FC, 0x00E5D, 0x00CE5, 0x0288D, 0x0098F, 0x006E9, - 0x0FB2C, 0x0652A, 0x01C52, 0x0104D, 0x0FB2B, 0x0128B, - 0x050A3, 0x07E4D, 0x029FB, 0x00990, 0x01FD0, 0x024F7, - 0x050A4, 0x020C1, 0x01B54, 0x1F2DD, 0x0FB30, 0x0FB2E, - 0x0FB2F, 0x049A6, 0x1F2DF, 0x1F2DE, 0x0288E, 0x029FD, - 0x0FB31, 0x025FD, 0x07E4F, 0x1F2E0, 0x0652E, 0x1F2E2, - 0x1F2E1, 0x0A04D, 0x0128C, 0x03F67, 0x0FB33, 0x0FB32, - 0x01B55, 0x025FC, 0x03F66, 0x0652D, 0x025FB, 0x0083C, - 0x1F2DA, 0x0FB2D, 0x1F2D8, 0x1F2D9, 0x0A04B, 0x050A6, - 0x050A7, 0x024F9, 0x0A04A, 0x0A04C, 0x1F2DC, 0x1F2DB, - 0x049A5, 0x00538, 0x0FB35, 0x0FB34, 0x01147, 0x0051E, - 0x03866, 0x0A04F, 0x1F2E7, 0x024FA, 0x002BC, 0x1F2E8, - 0x0FB36, 0x00DE4, 0x01555, 0x050AA, 0x1F2E9, 0x0FB37, - 0x0288F, 0x01FD2, 0x1F2EA, 0x0FB38, 0x032D0, 0x0652F, - 0x1F2E3, 0x020C3, 0x01FD1, 0x025FE, 0x03F68, 0x0A04E, - 0x06530, 0x01769, 0x01D7C, 0x1F2E4, 0x050A8, 0x00ED4, - 0x0099F, 0x050A9, 0x1F2E6, 0x1F2E5, 0x06531, 0x00F5F, - 0x0FB20, 0x0FB1F, 0x006B4, 0x0067C, 0x029F1, 0x1F2C2, - 0x1F2C1, 0x032CB, 0x0149E, 0x0509E, 0x1F2C3, 0x00A6A, - 0x00E5B, 0x025F4, 0x0FB21, 0x1F2C4, 0x1F2C5, 0x02883, - 0x0651F, 0x0FB22, 0x03F61, 0x0509C, 0x04998, 0x0FB1D, - 0x07E42, 0x0175D, 0x0107A, 0x0A03D, 0x07E43, 0x04999, - 0x01B50, 0x0509D, 0x0651E, 0x0104A, 0x0137C, 0x0499A, - 0x0FB1E, 0x1F2C0, 0x07E44, 0x0385C, 0x07E45, 0x0A040, - 0x1F2CA, 0x1F2CB, 0x032CC, 0x1F2CD, 0x1F2CC, 0x0385D, - 0x02884, 0x06523, 0x03F63, 0x1F2CE, 0x0FB24, 0x0FB25, - 0x1F2D1, 0x1F2CF, 0x1F2D0, 0x00F70, 0x07E46, 0x0FB26, - 0x1F2D2, 0x0499C, 0x03F62, 0x0095E, 0x01C4D, 0x0499B, - 0x00BF7, 0x06520, 0x1F2C6, 0x0FB23, 0x0A03E, 0x0A03F, - 0x1F2C7, 0x025F5, 0x0385B, 0x06521, 0x0509F, 0x1F2C9, - 0x1F2C8, 0x06522, 0x00AF9, 0x0A042, 0x0FB27, 0x00A56, - 0x006DE, 0x029F2, 0x029F3, 0x032CD, 0x032CE, 0x02886, - 0x0385E, 0x07E48, 0x0175F, 0x050A0, 0x0FB29, 0x01C4F, - 0x029F4, 0x0FB28, 0x01553, 0x0A043, 0x025F6, 0x01314, - 0x006FC, 0x0098E, 0x02885, 0x01552, 0x0A041, 0x06525, - 0x0128A, 0x020BD, 0x06524, 0x01C4E, 0x07E47, 0x0499D, - 0x00CE2, 0x0071A, 0x06526, 0x01FCE, 0x0175E, 0x024F6, - 0x00046, 0x009E2, 0x01C50, 0x00DB7, 0x00BB9, 0x00188, - 0x06527, 0x0499E, 0x0017C, 0x00D2F, 0x025F7, 0x00BBA, - 0x00DB8, 0x02887, 0x049A1, 0x06528, 0x0499F, 0x049A0, - 0x0104C, 0x020BF, 0x0FB2A, 0x029F8, 0x025F8, 0x00A31, - 0x0051C, 0x01554, 0x029F5, 0x00BFC, 0x032CF, 0x0A044, - 0x0385F, 0x029F6, 0x00AB2, 0x020BE, 0x00E5C, 0x00A57, - 0x00D2E, 0x001AC, 0x029F7, 0x03860, 0x00125, -}; - -static const uint8_t on2avc_cb7_bits[ON2AVC_CB7_CODES] = { - 1, 8, 8, 8, 8, 7, - 10, 11, 7, 11, 12, 10, - 10, 12, 14, 14, 15, 14, - 11, 11, 13, 13, 12, 10, - 11, 13, 12, 12, 14, 14, - 14, 13, 11, 12, 9, 10, - 12, 7, 11, 11, 7, 7, - 11, 12, 7, 7, 10, 9, - 11, 11, 11, 13, 13, 12, - 14, 15, 11, 12, 14, 12, - 13, 12, 12, 12, 12, 11, - 11, 15, 15, 10, 12, 15, - 12, 12, 14, 11, 7, 10, - 8, 11, 11, 11, 16, 13, - 12, 14, 12, 16, 15, 12, - 13, 14, 14, 12, 14, 17, - 15, 16, 16, 12, 14, 16, - 14, 12, 12, 13, 16, 14, - 12, 17, 16, 16, 15, 13, - 13, 14, 12, 14, 12, 16, - 16, 12, 16, 17, 16, 17, - 15, 16, 16, 15, 17, 15, - 17, 17, 16, 17, 16, 15, - 14, 16, 14, 16, 14, 11, - 14, 16, 15, 11, 17, 17, - 15, 13, 17, 16, 17, 17, - 15, 14, 17, 15, 14, 16, - 11, 16, 17, 16, 14, 12, - 17, 15, 12, 13, 15, 17, - 16, 13, 15, 17, 16, 13, - 15, 16, 17, 15, 13, 14, - 16, 17, 17, 14, 14, 16, - 16, 13, 12, 15, 17, 16, - 14, 11, 15, 15, 12, 10, - 14, 16, 16, 16, 12, 15, - 16, 12, 12, 13, 15, 17, - 14, 12, 15, 17, 14, 14, - 15, 16, 16, 16, 16, 16, - 16, 16, 16, 12, 16, 17, - 14, 11, 13, 15, 17, 15, - 12, 14, 16, 11, 14, 17, - 17, 14, 15, 17, 14, 17, - 16, 15, 17, 15, 14, 17, - 15, 14, 17, 17, 12, 15, - 16, 14, 12, 13, 16, 13, - 16, 16, 15, 16, 16, 16, - 17, 17, 16, 14, 16, 14, - 17, 17, 11, 14, 12, 13, - 15, 12, 14, 15, 12, 13, - 14, 12, 13, 14, 14, 16, - 17, 15, 11, 12, 14, 15, - 13, 12, 12, 14, 14, 13, - 15, 17, 16, 16, 14, 14, - 13, 13, 14, 12, 16, 17, - 12, 7, 12, 12, 7, 7, - 11, 11, 8, 10, 11, 13, - 13, 11, 15, 14, 12, 10, - 14, 11, 11, 13, 12, 11, - 12, 13, 12, 15, 14, 12, - 11, 14, 11, 15, 13, 11, - 7, 11, 11, 9, 10, 7, - 13, 14, 7, 7, 12, 12, - 12, 11, 12, 17, 14, 12, - 14, 16, 14, 14, 14, 11, - 12, 12, 11, 13, 15, 14, - 13, 15, 16, 14, 14, 15, - 12, 14, 14, 12, 7, 11, - 12, 12, 11, 7, 12, 13, - 13, 12, 9, 14, 14, 9, - 12, 12, 12, 13, 13, 14, - 15, 14, 14, 12, 11, 14, - 13, 11, 12, 13, 14, 14, - 13, 15, 15, 16, 14, 12, - 14, 12, 12, 14, 9, 14, - 13, 9, 12, 17, 15, 12, - 12, 14, 13, 13, 13, 13, - 14, 16, 13, 16, 15, 12, - 14, 16, 13, 14, 12, 11, - 13, 17, 15, 13, 15, 17, - 15, 13, 15, 13, 15, 17, - 13, 11, 14, 15, 13, 13, - 14, 17, 17, 17, 16, 14, - 17, 16, 15, 16, 17, 16, - 14, 15, 17, 15, 17, 16, - 14, 14, 14, 15, 12, 13, - 14, 17, 16, 14, 16, 17, - 17, 17, 14, 17, 17, 15, - 17, 15, 17, 16, 16, 11, - 17, 16, 12, 12, 17, 17, - 15, 15, 14, 17, 14, 13, - 14, 16, 16, 15, 13, 14, - 16, 14, 13, 14, 15, 17, - 14, 12, 14, 17, 16, 14, - 12, 16, 14, 13, 11, 15, - 17, 16, 13, 12, 15, 17, - 10, 12, 13, 16, 17, 14, - 13, 14, 15, 12, 13, 14, - 15, 17, 14, 14, 16, 15, - 14, 14, 17, 17, 14, 13, - 14, 16, 17, 15, 13, 15, - 15, 12, 11, 14, 17, 16, - 14, 13, 16, 15, 17, 16, - 15, 17, 16, 15, 15, 17, - 15, 16, 17, 16, 17, 17, - 17, 13, 12, 14, 17, 14, - 13, 15, 14, 17, 14, 14, - 16, 15, 16, 14, 15, 14, - 15, 17, 14, 17, 17, 15, - 12, 17, 17, 12, 12, 14, - 13, 14, 13, 14, 16, 15, - 13, 15, 17, 13, 13, 14, - 11, 13, 14, 13, 12, 14, - 15, 13, 17, 15, 14, 15, - 16, 13, 16, 16, 14, 12, - 14, 13, 14, 14, 7, 12, - 13, 12, 12, 9, 14, 14, - 9, 12, 14, 12, 12, 12, - 14, 15, 15, 15, 11, 11, - 13, 13, 12, 12, 13, 15, - 14, 14, 15, 16, 15, 15, - 12, 14, 12, 13, 14, 9, - 14, 13, 9, 8, 15, 15, - 15, 15, 12, 16, 16, 12, - 14, 15, 15, 15, 16, 17, - 17, 17, 17, 16, 15, 15, - 17, 15, 14, 15, 17, 16, - 15, 15, 17, 17, 16, 13, - 15, 15, 15, 15, 12, 15, - 16, 11, 12, 17, 16, 11, - 11, 15, 15, 15, 14, 14, - 15, 17, 14, 17, 15, 16, - 16, 16, 14, 17, 15, 15, - 13, 16, 15, 14, 15, 16, - 17, 15, 16, 14, 15, 16, - 13, 11, 14, 15, 16, 14, - 12, 16, 16, 16, 14, 12, - 16, 17, 13, 14, 13, 16, - 17, 16, 15, 15, 17, 17, - 14, 15, 15, 15, 15, 12, - 14, 17, 16, 15, 15, 17, - 17, 17, 15, 16, 16, 14, - 16, 13, 17, 16, 14, 15, - 16, 17, 15, 16, 16, 17, - 15, 16, 14, 17, 17, 16, - 16, 14, 15, 17, 17, 15, - 14, 14, 15, 13, 16, 17, - 14, 16, 17, 16, 16, 16, - 16, 17, 17, 16, 14, 17, - 16, 15, 16, 11, 17, 17, - 16, 16, 13, 17, 16, 14, - 14, 16, 17, 15, 15, 13, - 16, 15, 15, 15, 16, 15, - 16, 15, 12, 15, 17, 16, - 15, 12, 15, 16, 13, 12, - 15, 16, 17, 14, 11, 17, - 16, 13, 12, 15, 17, 17, - 15, 13, 16, 15, 12, 13, - 15, 17, 17, 14, 15, 17, - 15, 14, 17, 15, 17, 17, - 16, 12, 17, 17, 17, 16, - 14, 15, 17, 11, 13, 15, - 17, 16, 15, 12, 17, 17, - 11, 15, 17, 17, 16, 14, - 17, 15, 17, 16, 14, 17, - 17, 15, 16, 17, 14, 16, - 17, 14, 17, 16, 15, 14, - 17, 17, 12, 17, 17, 17, - 15, 15, 17, 16, 17, 15, - 14, 17, 14, 16, 17, 12, - 14, 17, 16, 17, 13, 17, - 16, 13, 15, 16, 15, 16, - 14, 15, 17, 17, 15, 14, - 14, 16, 17, 14, 11, 15, - 16, 16, 14, 16, 17, 17, - 15, 14, 15, 15, 15, 15, - 13, 15, 17, 14, 11, 17, - 17, 12, 11, 15, 17, 17, - 15, 14, 17, 16, 14, 17, - 17, 15, 15, 16, 15, 15, - 16, 14, 14, 15, 15, 15, - 16, 17, 15, 15, 16, 14, - 15, 16, 13, 11, 14, 16, - 17, 14, 13, 17, 17, 14, - 12, 16, 16, 17, 16, 17, - 17, 17, 16, 17, 17, 17, - 17, 17, 17, 17, 16, 17, - 17, 17, 17, 17, 17, 17, - 16, 17, 17, 16, 17, 17, - 16, 13, 16, 17, 16, 16, - 11, 17, 17, 17, 16, 15, - 17, 17, 14, 16, 16, 17, - 16, 17, 17, 17, 17, 17, - 17, 16, 16, 17, 15, 15, - 17, 17, 16, 15, 16, 17, - 16, 16, 15, 16, 17, 16, - 14, 13, 17, 17, 13, 15, - 17, 17, 14, 12, 17, 17, - 16, 15, 15, 17, 17, 15, - 17, 16, 17, 16, 17, 17, - 17, 17, 16, 13, 16, 17, - 16, 17, 17, 17, 17, 17, - 16, 17, 15, 16, 13, 16, - 16, 16, 15, 16, 17, 17, - 17, 17, 16, 17, 17, 16, - 17, 16, 16, 16, 15, 16, - 15, 17, 17, 17, 16, 15, - 16, 16, 15, 15, 16, 17, - 16, 17, 17, 17, 17, 16, - 17, 17, 16, 17, 16, 17, - 16, 16, 12, 17, 16, 14, - 13, 16, 17, 17, 15, 14, - 17, 17, 14, 16, 16, 17, - 16, 15, 17, 15, 17, 17, - 14, 17, 17, 15, 13, 14, - 17, 15, 16, 12, 16, 16, - 15, 12, 16, 17, 17, 15, - 14, 16, 17, 12, 12, 16, - 16, 16, 17, 14, 16, 16, - 13, 15, 16, 17, 17, 15, - 15, 16, 16, 16, 15, 17, - 17, 14, 14, 15, 17, 17, - 15, 14, 17, 15, 12, 12, - 14, 17, 17, 15, 14, 17, - 17, 17, 17, 15, 16, 17, - 15, 17, 16, 17, 15, 17, - 17, 16, 16, 16, 15, 16, - 17, 17, 15, 15, 16, 17, - 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 15, - 17, 17, 15, 14, 17, 17, - 14, 14, 16, 16, 17, 16, - 16, 17, 16, 15, 17, 17, - 16, 16, 17, 16, 16, 17, - 15, 15, 17, 17, 15, 17, - 17, 15, 15, 16, 16, 16, - 17, 15, 13, 17, 17, 17, - 17, 11, 16, 17, 17, 16, - 14, 17, 17, 14, 16, 17, - 17, 15, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 16, - 14, 16, 17, 16, 16, 17, - 16, 17, 16, 17, 16, 17, - 17, 17, 15, 16, 17, 15, - 9, 17, 17, 17, 16, 12, - 17, 17, 13, 15, 15, 17, - 17, 16, 16, 17, 17, 16, - 16, 17, 17, 17, 17, 16, - 17, 17, 17, 16, 15, 17, - 17, 16, 13, 17, 17, 17, - 15, 13, 17, 17, 13, 12, - 17, 17, 12, 9, 15, 17, - 17, 15, 14, 17, 17, 15, - 16, 17, 17, 16, 16, 17, - 17, 17, 16, 17, 17, 17, - 17, 14, 17, 17, 17, 16, - 14, 17, 17, 13, 11, 16, - 17, 17, 14, 10, 16, 17, - 17, 16, 12, 16, 17, 12, - 14, 16, 17, 17, 15, 16, - 17, 17, 16, 17, 17, 17, - 17, 17, 15, 17, 17, 17, - 17, 14, 16, 17, 15, 12, - 15, 16, 17, 15, 11, 17, - 17, 12, 13, 17, 17, 14, - 10, 16, 17, 17, 16, 13, - 16, 16, 14, 17, 15, 17, - 17, 17, 17, 17, 17, 17, - 15, 17, 16, 16, 15, 17, - 17, 17, 15, 13, 17, 16, - 14, 11, 16, 17, 17, 15, - 11, 16, 17, 17, 16, 12, - 17, 16, 14, 14, 17, 17, - 17, 16, 13, 16, 17, 15, - 17, 17, 17, 17, 17, 17, - 16, 17, 17, 17, 14, 16, - 17, 16, 15, 16, 17, 17, - 15, 12, 17, 16, 14, 11, - 17, 17, 17, 15, 14, 17, - 17, 14, 15, 17, 16, 17, - 17, 17, 16, 16, 17, 17, - 17, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 17, 17, - 14, 14, 17, 17, 17, 17, - 14, 17, 17, 12, 14, 17, - 17, 14, 11, 16, 17, 17, - 15, 15, 16, 17, 13, 17, - 16, 17, 17, 15, 17, 17, - 17, 16, 16, 17, 16, 14, - 15, 16, 17, 17, 15, 15, - 17, 17, 13, 11, 15, 17, - 17, 16, 10, 16, 16, 17, - 16, 12, 17, 17, 12, 14, - 15, 17, 17, 15, 16, 17, - 15, 15, 17, 16, 17, 16, - 16, 15, 16, 17, 17, 16, - 15, 17, 17, 14, 13, 14, - 16, 17, 14, 12, 17, 16, - 13, 12, 16, 17, 13, 9, - 15, 17, 17, 16, 15, 17, - 17, 14, 16, 16, 17, 17, - 16, 16, 17, 17, 17, 15, - 17, 16, 16, 15, 16, 17, - 17, 15, 13, 17, 17, 14, - 11, 15, 17, 17, 15, 9, - 16, 17, 17, 15, 12, 17, - 16, 13, 14, 17, 17, 17, - 16, 16, 17, 17, 15, 16, - 17, 17, 16, 17, 17, 17, - 17, 17, 17, 17, 17, 16, - 16, 15, 17, 17, 17, 15, - 12, 17, 16, 12, 12, 16, - 17, 12, 10, 17, 17, 17, - 14, 14, 17, 17, 14, 14, - 16, 17, 17, 15, 16, 17, - 17, 17, 16, 17, 16, 17, - 14, 17, 17, 17, 16, 13, - 17, 17, 14, 9, 15, 17, - 17, 15, 10, 15, 17, 17, - 15, 12, 17, 17, 13, 13, - 16, 17, 17, 15, 14, 17, - 17, 14, 17, 16, 16, 17, - 17, 17, 17, 17, 17, 17, - 15, 17, 16, 15, 14, 15, - 17, 17, 16, 12, 16, 17, - 12, 13, 17, 17, 13, 11, - 17, 17, 17, 16, 12, 16, - 17, 15, 15, 15, 17, 17, - 17, 16, 16, 17, 16, 16, - 17, 17, 16, 16, 15, 17, - 17, 16, 13, 15, 17, 14, - 11, 15, 17, 16, 15, 12, - 17, 17, 16, 17, 12, 17, - 17, 15, 14, 16, 17, 17, - 15, 15, 17, 17, 15, 15, - 17, 17, 17, 16, 17, 17, - 17, 17, 17, 16, 15, 16, - 17, 14, 15, 16, 17, 17, - 15, 17, 17, 13, 12, 17, - 17, 17, 16, 14, 17, 17, - 12, 15, 15, 17, 17, 16, - 15, 17, 17, 14, 16, 17, - 17, 17, 17, 17, 17, 17, - 16, 15, 15, 17, 15, 15, - 14, 15, 17, 17, 15, 13, - 17, 17, 14, 14, 17, 17, - 14, 10, 16, 17, 17, 15, - 14, 17, 17, 13, 15, 16, - 17, 17, 15, 17, 16, 17, - 15, 17, 16, 17, 17, 15, - 16, 17, 17, 14, 14, 17, - 16, 12, 10, 16, 17, 17, - 15, 10, 16, 17, 17, 15, - 12, 17, 17, 13, 13, 15, - 17, 17, 15, 15, 17, 17, - 13, 14, 17, 17, 17, 16, - 17, 17, 17, 17, 17, 15, - 17, 16, 16, 13, 17, 16, - 17, 17, 12, 17, 17, 12, - 13, 17, 17, 12, 11, 15, - 16, 17, 17, 13, 16, 16, - 14, 14, 15, 17, 17, 16, - 16, 17, 17, 16, 17, 17, - 17, 17, 15, 17, 17, 17, - 16, 15, 17, 17, 14, 9, - 17, 17, 17, 15, 15, 17, - 17, 14, 13, 16, 17, 16, - 16, 16, 17, 17, 16, 16, - 16, 17, 17, 16, 16, 16, - 17, 16, 16, 17, 17, 17, - 17, 17, 17, 17, 16, 17, - 16, 17, 17, 12, 16, 17, - 17, 17, 10, 17, 16, 17, - 17, 13, 17, 17, 14, 16, - 17, 17, 15, 17, 17, 17, - 17, 17, 13, 16, 17, 16, - 15, 16, 15, 17, 16, 15, - 17, 17, 17, 17, 15, 16, - 16, 15, 16, 14, 17, 17, - 13, 15, 17, 17, 15, 13, - 17, 15, 17, 17, 15, 17, - 16, 15, 17, 16, 17, 17, - 16, 13, 16, 17, 15, 17, - 17, 17, 17, 17, 16, 17, - 16, 17, 15, 16, 17, 15, - 13, 16, 16, 16, 16, 14, - 17, 17, 17, 16, 15, 17, - 16, 17, 16, 16, 17, 15, - 17, 16, 17, 16, 17, 14, - 15, 17, 17, 17, 16, 16, - 16, 17, 17, 17, 16, 17, - 17, 16, 17, 17, 16, 17, - 16, 17, 17, 14, 13, 17, - 17, 14, 12, 17, 17, 17, - 15, 12, 17, 16, 15, 15, - 15, 17, 17, 17, 14, 16, - 17, 16, 16, 16, 17, 17, - 17, 15, 17, 17, 17, 14, - 16, 15, 14, 13, 14, 17, - 17, 17, 15, 16, 17, 12, - 13, 15, 17, 17, 16, 14, - 16, 16, 12, 14, 16, 16, - 17, 15, 16, 17, 16, 13, - 16, 16, 16, 17, 15, 15, - 16, 17, 14, 14, 17, 17, - 13, 12, 15, 17, 17, 15, - 14, 16, 16, 17, 17, 15, - 17, 17, 17, 16, 16, 17, - 16, 16, 17, 17, 17, 17, - 15, 16, 17, 17, 16, 16, - 16, 17, 15, 17, 17, 17, - 15, 16, 16, 17, 17, 16, - 16, 15, 17, 17, 15, 14, - 17, 17, 14, 14, 16, 17, - 17, 17, 15, 16, 17, 16, - 17, 16, 16, 17, 17, 16, - 15, 16, 15, 16, 17, 17, - 15, 17, 17, 16, 16, 16, - 15, 17, 17, 15, 12, 16, - 17, 17, 16, 11, 17, 17, - 16, 16, 14, 16, 17, 14, - 16, 16, 17, 16, 15, 17, - 17, 17, 16, 15, 15, 17, - 17, 17, 17, 17, 17, 17, - 16, 17, 17, 17, 16, 14, - 17, 16, 17, 16, 13, 17, - 17, 13, 8, 15, 15, 15, - 14, 12, 16, 17, 12, 13, - 15, 15, 16, 16, 16, 17, - 17, 16, 12, 15, 17, 15, - 16, 14, 15, 16, 17, 16, - 17, 17, 17, 17, 15, 16, - 15, 15, 15, 12, 16, 17, - 12, 11, 17, 17, 11, 11, - 14, 15, 15, 13, 13, 16, - 15, 13, 16, 15, 16, 17, - 15, 13, 15, 15, 15, 15, - 15, 16, 14, 17, 17, 14, - 17, 17, 14, 16, 17, 14, - 11, 14, 14, 16, 14, 12, - 16, 15, 16, 15, 13, 15, - 16, 13, 14, 15, 15, 15, - 15, 15, 16, 17, 17, 11, - 14, 17, 16, 14, 15, 16, - 16, 16, 15, 16, 15, 17, - 16, 15, 14, 16, 16, 16, - 13, 17, 17, 13, 15, 17, - 17, 15, 15, 17, 17, 16, - 16, 15, 17, 17, 15, 16, - 17, 17, 15, 17, 13, 14, - 16, 14, 16, 15, 15, 14, - 16, 17, 15, 16, 16, 15, - 17, 17, 16, 15, 16, 16, - 16, 15, 10, 16, 17, 17, - 15, 11, 16, 17, 12, 13, - 14, 17, 15, 15, 12, 17, - 15, 14, 12, 15, 17, 17, - 15, 15, 16, 17, 17, 16, - 14, 15, 15, 15, 14, 15, - 16, 15, 15, 12, 17, 15, - 13, 11, 16, 17, 17, 16, - 13, 16, 17, 11, 12, 15, - 16, 17, 14, 14, 15, 17, - 11, 13, 17, 17, 17, 15, - 17, 16, 15, 16, 14, 16, - 16, 17, 14, 13, 14, 16, - 17, 14, 14, 15, 16, 12, - 15, 17, 17, 16, 14, 17, - 16, 17, 17, 16, 17, 17, - 15, 16, 17, 15, 15, 17, - 14, 15, 15, 13, 15, 15, - 15, 16, 17, 17, 16, 15, - 14, 17, 17, 17, 15, 14, - 16, 17, 17, 17, 11, 14, - 14, 16, 17, 14, 15, 16, - 14, 13, 15, 14, 17, 16, - 15, 16, 17, 17, 11, 15, - 17, 17, 14, 14, 16, 16, - 16, 14, 17, 17, 15, 16, - 14, 15, 17, 16, 13, 13, - 16, 16, 12, 11, 17, 17, - 12, 11, 14, 16, 17, 15, - 14, 16, 17, 13, 15, 16, - 15, 16, 16, 15, 15, 15, - 13, 14, 15, 15, 16, 17, - 17, 15, 15, 16, 15, 16, - 16, 13, 10, 16, 15, 15, - 15, 7, 14, 14, 7, 7, - 11, 12, 12, 11, 12, 14, - 14, 12, 15, 16, 13, 14, - 16, 13, 13, 15, 13, 11, - 12, 13, 11, 15, 15, 13, - 12, 15, 12, 14, 15, 12, - 7, 12, 12, 12, 11, 6, - 12, 12, 13, 12, 9, 14, - 14, 9, 12, 13, 13, 12, - 14, 15, 16, 17, 14, 12, - 13, 13, 15, 13, 11, 12, - 14, 12, 11, 14, 15, 17, - 14, 12, 13, 12, 13, 14, - 9, 13, 15, 9, 12, 17, - 16, 12, 11, 14, 14, 13, - 15, 13, 16, 17, 14, 15, - 17, 14, 14, 15, 13, 15, - 14, 12, 12, 14, 12, 11, - 16, 15, 13, 13, 16, 13, - 15, 15, 14, 12, 13, 14, - 15, 14, 13, 17, 16, 16, - 16, 15, 17, 17, 14, 14, - 16, 14, 15, 17, 15, 17, - 17, 16, 13, 14, 16, 16, - 13, 14, 14, 15, 14, 12, - 17, 16, 17, 17, 16, 15, - 15, 14, 16, 16, 17, 17, - 15, 11, 16, 16, 13, 11, - 14, 16, 17, 14, 10, 17, - 16, 12, 13, 15, 17, 16, - 14, 13, 17, 16, 14, 15, - 17, 14, 13, 14, 14, 16, - 15, 13, 13, 17, 15, 12, - 12, 15, 17, 17, 15, 12, - 16, 16, 11, 11, 14, 17, - 17, 14, 13, 15, 17, 12, - 12, 14, 16, 17, 17, 14, - 15, 16, 14, 15, 15, 16, - 15, 13, 13, 16, 15, 15, - 13, 15, 15, 13, 13, 15, - 16, 17, 15, 14, 15, 16, - 17, 17, 14, 17, 17, 14, - 14, 15, 14, 17, 16, 16, - 17, 17, 17, 12, 15, 16, - 17, 15, 14, 12, 13, 15, - 12, 15, 17, 16, 16, 16, - 17, 14, 14, 15, 15, 17, - 17, 15, 12, 16, 16, 12, - 11, 14, 14, 14, 14, 14, - 14, 15, 13, 15, 16, 13, - 14, 16, 13, 16, 14, 13, - 11, 12, 14, 13, 16, 15, - 13, 14, 15, 13, 15, 15, - 12, 11, 15, 13, 13, 14, - 7, 12, 13, 12, 12, 9, - 15, 15, 9, 12, 14, 12, - 12, 14, 15, 15, 15, 15, - 13, 14, 16, 14, 14, 12, - 11, 13, 14, 12, 14, 16, - 14, 14, 12, 14, 12, 12, - 12, 9, 14, 14, 9, -}; - -static const uint16_t on2avc_cb7_syms[ON2AVC_CB7_CODES] = { - 0x0000, 0x0002, 0x0004, 0x000C, 0x000E, 0x0011, - 0x0013, 0x001D, 0x001F, 0x0020, 0x0022, 0x0024, - 0x002C, 0x002E, 0x0031, 0x0033, 0x003D, 0x003F, - 0x0040, 0x0042, 0x0044, 0x004C, 0x004E, 0x00C0, - 0x00C2, 0x00C4, 0x00CC, 0x00CE, 0x00D1, 0x00D3, - 0x00DD, 0x00DF, 0x00E0, 0x00E2, 0x00E4, 0x00EC, - 0x00EE, 0x00F1, 0x00F3, 0x00FD, 0x00FF, 0x0101, - 0x0103, 0x010D, 0x010F, 0x0110, 0x0112, 0x0114, - 0x011C, 0x011E, 0x0121, 0x0123, 0x012D, 0x012F, - 0x0130, 0x0132, 0x0134, 0x013C, 0x013E, 0x0141, - 0x0143, 0x014D, 0x014F, 0x01C1, 0x01C3, 0x01CD, - 0x01CF, 0x01D0, 0x01D2, 0x01D4, 0x01DC, 0x01DE, - 0x01E1, 0x01E3, 0x01ED, 0x01EF, 0x01F0, 0x01F2, - 0x01F4, 0x01FC, 0x01FE, 0x0200, 0x0202, 0x0204, - 0x020C, 0x020E, 0x0211, 0x0213, 0x021D, 0x021F, - 0x0220, 0x0222, 0x0224, 0x022C, 0x022E, 0x0231, - 0x0233, 0x023D, 0x023F, 0x0240, 0x0242, 0x0244, - 0x024C, 0x024E, 0x02C0, 0x02C2, 0x02C4, 0x02CC, - 0x02CE, 0x02D1, 0x02D3, 0x02DD, 0x02DF, 0x02E0, - 0x02E2, 0x02E4, 0x02EC, 0x02EE, 0x02F1, 0x02F3, - 0x02FD, 0x02FF, 0x0301, 0x0303, 0x030D, 0x030F, - 0x0310, 0x0312, 0x0314, 0x031C, 0x031E, 0x0321, - 0x0323, 0x032D, 0x032F, 0x0330, 0x0332, 0x0334, - 0x033C, 0x033E, 0x0341, 0x0343, 0x034D, 0x034F, - 0x03C1, 0x03C3, 0x03CD, 0x03CF, 0x03D0, 0x03D2, - 0x03D4, 0x03DC, 0x03DE, 0x03E1, 0x03E3, 0x03ED, - 0x03EF, 0x03F0, 0x03F2, 0x03F4, 0x03FC, 0x03FE, - 0x0400, 0x0402, 0x0404, 0x040C, 0x040E, 0x0411, - 0x0413, 0x041D, 0x041F, 0x0420, 0x0422, 0x0424, - 0x042C, 0x042E, 0x0431, 0x0433, 0x043D, 0x043F, - 0x0440, 0x0442, 0x0444, 0x044C, 0x044E, 0x04C0, - 0x04C2, 0x04C4, 0x04CC, 0x04CE, 0x04D1, 0x04D3, - 0x04DD, 0x04DF, 0x04E0, 0x04E2, 0x04E4, 0x04EC, - 0x04EE, 0x04F1, 0x04F3, 0x04FD, 0x04FF, 0x0C00, - 0x0C02, 0x0C04, 0x0C0C, 0x0C0E, 0x0C11, 0x0C13, - 0x0C1D, 0x0C1F, 0x0C20, 0x0C22, 0x0C24, 0x0C2C, - 0x0C2E, 0x0C31, 0x0C33, 0x0C3D, 0x0C3F, 0x0C40, - 0x0C42, 0x0C44, 0x0C4C, 0x0C4E, 0x0CC0, 0x0CC2, - 0x0CC4, 0x0CCC, 0x0CCE, 0x0CD1, 0x0CD3, 0x0CDD, - 0x0CDF, 0x0CE0, 0x0CE2, 0x0CE4, 0x0CEC, 0x0CEE, - 0x0CF1, 0x0CF3, 0x0CFD, 0x0CFF, 0x0D01, 0x0D03, - 0x0D0D, 0x0D0F, 0x0D10, 0x0D12, 0x0D14, 0x0D1C, - 0x0D1E, 0x0D21, 0x0D23, 0x0D2D, 0x0D2F, 0x0D30, - 0x0D32, 0x0D34, 0x0D3C, 0x0D3E, 0x0D41, 0x0D43, - 0x0D4D, 0x0D4F, 0x0DC1, 0x0DC3, 0x0DCD, 0x0DCF, - 0x0DD0, 0x0DD2, 0x0DD4, 0x0DDC, 0x0DDE, 0x0DE1, - 0x0DE3, 0x0DED, 0x0DEF, 0x0DF0, 0x0DF2, 0x0DF4, - 0x0DFC, 0x0DFE, 0x0E00, 0x0E02, 0x0E04, 0x0E0C, - 0x0E0E, 0x0E11, 0x0E13, 0x0E1D, 0x0E1F, 0x0E20, - 0x0E22, 0x0E24, 0x0E2C, 0x0E2E, 0x0E31, 0x0E33, - 0x0E3D, 0x0E3F, 0x0E40, 0x0E42, 0x0E44, 0x0E4C, - 0x0E4E, 0x0EC0, 0x0EC2, 0x0EC4, 0x0ECC, 0x0ECE, - 0x0ED1, 0x0ED3, 0x0EDD, 0x0EDF, 0x0EE0, 0x0EE2, - 0x0EE4, 0x0EEC, 0x0EEE, 0x0EF1, 0x0EF3, 0x0EFD, - 0x0EFF, 0x0F01, 0x0F03, 0x0F0D, 0x0F0F, 0x0F10, - 0x0F12, 0x0F14, 0x0F1C, 0x0F1E, 0x0F21, 0x0F23, - 0x0F2D, 0x0F2F, 0x0F30, 0x0F32, 0x0F34, 0x0F3C, - 0x0F3E, 0x0F41, 0x0F43, 0x0F4D, 0x0F4F, 0x0FC1, - 0x0FC3, 0x0FCD, 0x0FCF, 0x0FD0, 0x0FD2, 0x0FD4, - 0x0FDC, 0x0FDE, 0x0FE1, 0x0FE3, 0x0FED, 0x0FEF, - 0x0FF0, 0x0FF2, 0x0FF4, 0x0FFC, 0x0FFE, 0x1001, - 0x1003, 0x100D, 0x100F, 0x1010, 0x1012, 0x1014, - 0x101C, 0x101E, 0x1021, 0x1023, 0x102D, 0x102F, - 0x1030, 0x1032, 0x1034, 0x103C, 0x103E, 0x1041, - 0x1043, 0x104D, 0x104F, 0x10C1, 0x10C3, 0x10CD, - 0x10CF, 0x10D0, 0x10D2, 0x10D4, 0x10DC, 0x10DE, - 0x10E1, 0x10E3, 0x10ED, 0x10EF, 0x10F0, 0x10F2, - 0x10F4, 0x10FC, 0x10FE, 0x1100, 0x1102, 0x1104, - 0x110C, 0x110E, 0x1111, 0x1113, 0x111D, 0x111F, - 0x1120, 0x1122, 0x1124, 0x112C, 0x112E, 0x1131, - 0x1133, 0x113D, 0x113F, 0x1140, 0x1142, 0x1144, - 0x114C, 0x114E, 0x11C0, 0x11C2, 0x11C4, 0x11CC, - 0x11CE, 0x11D1, 0x11D3, 0x11DD, 0x11DF, 0x11E0, - 0x11E2, 0x11E4, 0x11EC, 0x11EE, 0x11F1, 0x11F3, - 0x11FD, 0x11FF, 0x1201, 0x1203, 0x120D, 0x120F, - 0x1210, 0x1212, 0x1214, 0x121C, 0x121E, 0x1221, - 0x1223, 0x122D, 0x122F, 0x1230, 0x1232, 0x1234, - 0x123C, 0x123E, 0x1241, 0x1243, 0x124D, 0x124F, - 0x12C1, 0x12C3, 0x12CD, 0x12CF, 0x12D0, 0x12D2, - 0x12D4, 0x12DC, 0x12DE, 0x12E1, 0x12E3, 0x12ED, - 0x12EF, 0x12F0, 0x12F2, 0x12F4, 0x12FC, 0x12FE, - 0x1300, 0x1302, 0x1304, 0x130C, 0x130E, 0x1311, - 0x1313, 0x131D, 0x131F, 0x1320, 0x1322, 0x1324, - 0x132C, 0x132E, 0x1331, 0x1333, 0x133D, 0x133F, - 0x1340, 0x1342, 0x1344, 0x134C, 0x134E, 0x13C0, - 0x13C2, 0x13C4, 0x13CC, 0x13CE, 0x13D1, 0x13D3, - 0x13DD, 0x13DF, 0x13E0, 0x13E2, 0x13E4, 0x13EC, - 0x13EE, 0x13F1, 0x13F3, 0x13FD, 0x13FF, 0x1401, - 0x1403, 0x140D, 0x140F, 0x1410, 0x1412, 0x1414, - 0x141C, 0x141E, 0x1421, 0x1423, 0x142D, 0x142F, - 0x1430, 0x1432, 0x1434, 0x143C, 0x143E, 0x1441, - 0x1443, 0x144D, 0x144F, 0x14C1, 0x14C3, 0x14CD, - 0x14CF, 0x14D0, 0x14D2, 0x14D4, 0x14DC, 0x14DE, - 0x14E1, 0x14E3, 0x14ED, 0x14EF, 0x14F0, 0x14F2, - 0x14F4, 0x14FC, 0x14FE, 0x1C01, 0x1C03, 0x1C0D, - 0x1C0F, 0x1C10, 0x1C12, 0x1C14, 0x1C1C, 0x1C1E, - 0x1C21, 0x1C23, 0x1C2D, 0x1C2F, 0x1C30, 0x1C32, - 0x1C34, 0x1C3C, 0x1C3E, 0x1C41, 0x1C43, 0x1C4D, - 0x1C4F, 0x1CC1, 0x1CC3, 0x1CCD, 0x1CCF, 0x1CD0, - 0x1CD2, 0x1CD4, 0x1CDC, 0x1CDE, 0x1CE1, 0x1CE3, - 0x1CED, 0x1CEF, 0x1CF0, 0x1CF2, 0x1CF4, 0x1CFC, - 0x1CFE, 0x1D00, 0x1D02, 0x1D04, 0x1D0C, 0x1D0E, - 0x1D11, 0x1D13, 0x1D1D, 0x1D1F, 0x1D20, 0x1D22, - 0x1D24, 0x1D2C, 0x1D2E, 0x1D31, 0x1D33, 0x1D3D, - 0x1D3F, 0x1D40, 0x1D42, 0x1D44, 0x1D4C, 0x1D4E, - 0x1DC0, 0x1DC2, 0x1DC4, 0x1DCC, 0x1DCE, 0x1DD1, - 0x1DD3, 0x1DDD, 0x1DDF, 0x1DE0, 0x1DE2, 0x1DE4, - 0x1DEC, 0x1DEE, 0x1DF1, 0x1DF3, 0x1DFD, 0x1DFF, - 0x1E01, 0x1E03, 0x1E0D, 0x1E0F, 0x1E10, 0x1E12, - 0x1E14, 0x1E1C, 0x1E1E, 0x1E21, 0x1E23, 0x1E2D, - 0x1E2F, 0x1E30, 0x1E32, 0x1E34, 0x1E3C, 0x1E3E, - 0x1E41, 0x1E43, 0x1E4D, 0x1E4F, 0x1EC1, 0x1EC3, - 0x1ECD, 0x1ECF, 0x1ED0, 0x1ED2, 0x1ED4, 0x1EDC, - 0x1EDE, 0x1EE1, 0x1EE3, 0x1EED, 0x1EEF, 0x1EF0, - 0x1EF2, 0x1EF4, 0x1EFC, 0x1EFE, 0x1F00, 0x1F02, - 0x1F04, 0x1F0C, 0x1F0E, 0x1F11, 0x1F13, 0x1F1D, - 0x1F1F, 0x1F20, 0x1F22, 0x1F24, 0x1F2C, 0x1F2E, - 0x1F31, 0x1F33, 0x1F3D, 0x1F3F, 0x1F40, 0x1F42, - 0x1F44, 0x1F4C, 0x1F4E, 0x1FC0, 0x1FC2, 0x1FC4, - 0x1FCC, 0x1FCE, 0x1FD1, 0x1FD3, 0x1FDD, 0x1FDF, - 0x1FE0, 0x1FE2, 0x1FE4, 0x1FEC, 0x1FEE, 0x1FF1, - 0x1FF3, 0x1FFD, 0x1FFF, 0x2000, 0x2002, 0x2004, - 0x200C, 0x200E, 0x2011, 0x2013, 0x201D, 0x201F, - 0x2020, 0x2022, 0x2024, 0x202C, 0x202E, 0x2031, - 0x2033, 0x203D, 0x203F, 0x2040, 0x2042, 0x2044, - 0x204C, 0x204E, 0x20C0, 0x20C2, 0x20C4, 0x20CC, - 0x20CE, 0x20D1, 0x20D3, 0x20DD, 0x20DF, 0x20E0, - 0x20E2, 0x20E4, 0x20EC, 0x20EE, 0x20F1, 0x20F3, - 0x20FD, 0x20FF, 0x2101, 0x2103, 0x210D, 0x210F, - 0x2110, 0x2112, 0x2114, 0x211C, 0x211E, 0x2121, - 0x2123, 0x212D, 0x212F, 0x2130, 0x2132, 0x2134, - 0x213C, 0x213E, 0x2141, 0x2143, 0x214D, 0x214F, - 0x21C1, 0x21C3, 0x21CD, 0x21CF, 0x21D0, 0x21D2, - 0x21D4, 0x21DC, 0x21DE, 0x21E1, 0x21E3, 0x21ED, - 0x21EF, 0x21F0, 0x21F2, 0x21F4, 0x21FC, 0x21FE, - 0x2200, 0x2202, 0x2204, 0x220C, 0x220E, 0x2211, - 0x2213, 0x221D, 0x221F, 0x2220, 0x2222, 0x2224, - 0x222C, 0x222E, 0x2231, 0x2233, 0x223D, 0x223F, - 0x2240, 0x2242, 0x2244, 0x224C, 0x224E, 0x22C0, - 0x22C2, 0x22C4, 0x22CC, 0x22CE, 0x22D1, 0x22D3, - 0x22DD, 0x22DF, 0x22E0, 0x22E2, 0x22E4, 0x22EC, - 0x22EE, 0x22F1, 0x22F3, 0x22FD, 0x22FF, 0x2301, - 0x2303, 0x230D, 0x230F, 0x2310, 0x2312, 0x2314, - 0x231C, 0x231E, 0x2321, 0x2323, 0x232D, 0x232F, - 0x2330, 0x2332, 0x2334, 0x233C, 0x233E, 0x2341, - 0x2343, 0x234D, 0x234F, 0x23C1, 0x23C3, 0x23CD, - 0x23CF, 0x23D0, 0x23D2, 0x23D4, 0x23DC, 0x23DE, - 0x23E1, 0x23E3, 0x23ED, 0x23EF, 0x23F0, 0x23F2, - 0x23F4, 0x23FC, 0x23FE, 0x2400, 0x2402, 0x2404, - 0x240C, 0x240E, 0x2411, 0x2413, 0x241D, 0x241F, - 0x2420, 0x2422, 0x2424, 0x242C, 0x242E, 0x2431, - 0x2433, 0x243D, 0x243F, 0x2440, 0x2442, 0x2444, - 0x244C, 0x244E, 0x24C0, 0x24C2, 0x24C4, 0x24CC, - 0x24CE, 0x24D1, 0x24D3, 0x24DD, 0x24DF, 0x24E0, - 0x24E2, 0x24E4, 0x24EC, 0x24EE, 0x24F1, 0x24F3, - 0x24FD, 0x24FF, 0x2C00, 0x2C02, 0x2C04, 0x2C0C, - 0x2C0E, 0x2C11, 0x2C13, 0x2C1D, 0x2C1F, 0x2C20, - 0x2C22, 0x2C24, 0x2C2C, 0x2C2E, 0x2C31, 0x2C33, - 0x2C3D, 0x2C3F, 0x2C40, 0x2C42, 0x2C44, 0x2C4C, - 0x2C4E, 0x2CC0, 0x2CC2, 0x2CC4, 0x2CCC, 0x2CCE, - 0x2CD1, 0x2CD3, 0x2CDD, 0x2CDF, 0x2CE0, 0x2CE2, - 0x2CE4, 0x2CEC, 0x2CEE, 0x2CF1, 0x2CF3, 0x2CFD, - 0x2CFF, 0x2D01, 0x2D03, 0x2D0D, 0x2D0F, 0x2D10, - 0x2D12, 0x2D14, 0x2D1C, 0x2D1E, 0x2D21, 0x2D23, - 0x2D2D, 0x2D2F, 0x2D30, 0x2D32, 0x2D34, 0x2D3C, - 0x2D3E, 0x2D41, 0x2D43, 0x2D4D, 0x2D4F, 0x2DC1, - 0x2DC3, 0x2DCD, 0x2DCF, 0x2DD0, 0x2DD2, 0x2DD4, - 0x2DDC, 0x2DDE, 0x2DE1, 0x2DE3, 0x2DED, 0x2DEF, - 0x2DF0, 0x2DF2, 0x2DF4, 0x2DFC, 0x2DFE, 0x2E00, - 0x2E02, 0x2E04, 0x2E0C, 0x2E0E, 0x2E11, 0x2E13, - 0x2E1D, 0x2E1F, 0x2E20, 0x2E22, 0x2E24, 0x2E2C, - 0x2E2E, 0x2E31, 0x2E33, 0x2E3D, 0x2E3F, 0x2E40, - 0x2E42, 0x2E44, 0x2E4C, 0x2E4E, 0x2EC0, 0x2EC2, - 0x2EC4, 0x2ECC, 0x2ECE, 0x2ED1, 0x2ED3, 0x2EDD, - 0x2EDF, 0x2EE0, 0x2EE2, 0x2EE4, 0x2EEC, 0x2EEE, - 0x2EF1, 0x2EF3, 0x2EFD, 0x2EFF, 0x2F01, 0x2F03, - 0x2F0D, 0x2F0F, 0x2F10, 0x2F12, 0x2F14, 0x2F1C, - 0x2F1E, 0x2F21, 0x2F23, 0x2F2D, 0x2F2F, 0x2F30, - 0x2F32, 0x2F34, 0x2F3C, 0x2F3E, 0x2F41, 0x2F43, - 0x2F4D, 0x2F4F, 0x2FC1, 0x2FC3, 0x2FCD, 0x2FCF, - 0x2FD0, 0x2FD2, 0x2FD4, 0x2FDC, 0x2FDE, 0x2FE1, - 0x2FE3, 0x2FED, 0x2FEF, 0x2FF0, 0x2FF2, 0x2FF4, - 0x2FFC, 0x2FFE, 0x3001, 0x3003, 0x300D, 0x300F, - 0x3010, 0x3012, 0x3014, 0x301C, 0x301E, 0x3021, - 0x3023, 0x302D, 0x302F, 0x3030, 0x3032, 0x3034, - 0x303C, 0x303E, 0x3041, 0x3043, 0x304D, 0x304F, - 0x30C1, 0x30C3, 0x30CD, 0x30CF, 0x30D0, 0x30D2, - 0x30D4, 0x30DC, 0x30DE, 0x30E1, 0x30E3, 0x30ED, - 0x30EF, 0x30F0, 0x30F2, 0x30F4, 0x30FC, 0x30FE, - 0x3100, 0x3102, 0x3104, 0x310C, 0x310E, 0x3111, - 0x3113, 0x311D, 0x311F, 0x3120, 0x3122, 0x3124, - 0x312C, 0x312E, 0x3131, 0x3133, 0x313D, 0x313F, - 0x3140, 0x3142, 0x3144, 0x314C, 0x314E, 0x31C0, - 0x31C2, 0x31C4, 0x31CC, 0x31CE, 0x31D1, 0x31D3, - 0x31DD, 0x31DF, 0x31E0, 0x31E2, 0x31E4, 0x31EC, - 0x31EE, 0x31F1, 0x31F3, 0x31FD, 0x31FF, 0x3201, - 0x3203, 0x320D, 0x320F, 0x3210, 0x3212, 0x3214, - 0x321C, 0x321E, 0x3221, 0x3223, 0x322D, 0x322F, - 0x3230, 0x3232, 0x3234, 0x323C, 0x323E, 0x3241, - 0x3243, 0x324D, 0x324F, 0x32C1, 0x32C3, 0x32CD, - 0x32CF, 0x32D0, 0x32D2, 0x32D4, 0x32DC, 0x32DE, - 0x32E1, 0x32E3, 0x32ED, 0x32EF, 0x32F0, 0x32F2, - 0x32F4, 0x32FC, 0x32FE, 0x3300, 0x3302, 0x3304, - 0x330C, 0x330E, 0x3311, 0x3313, 0x331D, 0x331F, - 0x3320, 0x3322, 0x3324, 0x332C, 0x332E, 0x3331, - 0x3333, 0x333D, 0x333F, 0x3340, 0x3342, 0x3344, - 0x334C, 0x334E, 0x33C0, 0x33C2, 0x33C4, 0x33CC, - 0x33CE, 0x33D1, 0x33D3, 0x33DD, 0x33DF, 0x33E0, - 0x33E2, 0x33E4, 0x33EC, 0x33EE, 0x33F1, 0x33F3, - 0x33FD, 0x33FF, 0x3401, 0x3403, 0x340D, 0x340F, - 0x3410, 0x3412, 0x3414, 0x341C, 0x341E, 0x3421, - 0x3423, 0x342D, 0x342F, 0x3430, 0x3432, 0x3434, - 0x343C, 0x343E, 0x3441, 0x3443, 0x344D, 0x344F, - 0x34C1, 0x34C3, 0x34CD, 0x34CF, 0x34D0, 0x34D2, - 0x34D4, 0x34DC, 0x34DE, 0x34E1, 0x34E3, 0x34ED, - 0x34EF, 0x34F0, 0x34F2, 0x34F4, 0x34FC, 0x34FE, - 0x3C01, 0x3C03, 0x3C0D, 0x3C0F, 0x3C10, 0x3C12, - 0x3C14, 0x3C1C, 0x3C1E, 0x3C21, 0x3C23, 0x3C2D, - 0x3C2F, 0x3C30, 0x3C32, 0x3C34, 0x3C3C, 0x3C3E, - 0x3C41, 0x3C43, 0x3C4D, 0x3C4F, 0x3CC1, 0x3CC3, - 0x3CCD, 0x3CCF, 0x3CD0, 0x3CD2, 0x3CD4, 0x3CDC, - 0x3CDE, 0x3CE1, 0x3CE3, 0x3CED, 0x3CEF, 0x3CF0, - 0x3CF2, 0x3CF4, 0x3CFC, 0x3CFE, 0x3D00, 0x3D02, - 0x3D04, 0x3D0C, 0x3D0E, 0x3D11, 0x3D13, 0x3D1D, - 0x3D1F, 0x3D20, 0x3D22, 0x3D24, 0x3D2C, 0x3D2E, - 0x3D31, 0x3D33, 0x3D3D, 0x3D3F, 0x3D40, 0x3D42, - 0x3D44, 0x3D4C, 0x3D4E, 0x3DC0, 0x3DC2, 0x3DC4, - 0x3DCC, 0x3DCE, 0x3DD1, 0x3DD3, 0x3DDD, 0x3DDF, - 0x3DE0, 0x3DE2, 0x3DE4, 0x3DEC, 0x3DEE, 0x3DF1, - 0x3DF3, 0x3DFD, 0x3DFF, 0x3E01, 0x3E03, 0x3E0D, - 0x3E0F, 0x3E10, 0x3E12, 0x3E14, 0x3E1C, 0x3E1E, - 0x3E21, 0x3E23, 0x3E2D, 0x3E2F, 0x3E30, 0x3E32, - 0x3E34, 0x3E3C, 0x3E3E, 0x3E41, 0x3E43, 0x3E4D, - 0x3E4F, 0x3EC1, 0x3EC3, 0x3ECD, 0x3ECF, 0x3ED0, - 0x3ED2, 0x3ED4, 0x3EDC, 0x3EDE, 0x3EE1, 0x3EE3, - 0x3EED, 0x3EEF, 0x3EF0, 0x3EF2, 0x3EF4, 0x3EFC, - 0x3EFE, 0x3F00, 0x3F02, 0x3F04, 0x3F0C, 0x3F0E, - 0x3F11, 0x3F13, 0x3F1D, 0x3F1F, 0x3F20, 0x3F22, - 0x3F24, 0x3F2C, 0x3F2E, 0x3F31, 0x3F33, 0x3F3D, - 0x3F3F, 0x3F40, 0x3F42, 0x3F44, 0x3F4C, 0x3F4E, - 0x3FC0, 0x3FC2, 0x3FC4, 0x3FCC, 0x3FCE, 0x3FD1, - 0x3FD3, 0x3FDD, 0x3FDF, 0x3FE0, 0x3FE2, 0x3FE4, - 0x3FEC, 0x3FEE, 0x3FF1, 0x3FF3, 0x3FFD, 0x3FFF, - 0x4000, 0x4002, 0x4004, 0x400C, 0x400E, 0x4011, - 0x4013, 0x401D, 0x401F, 0x4020, 0x4022, 0x4024, - 0x402C, 0x402E, 0x4031, 0x4033, 0x403D, 0x403F, - 0x4040, 0x4042, 0x4044, 0x404C, 0x404E, 0x40C0, - 0x40C2, 0x40C4, 0x40CC, 0x40CE, 0x40D1, 0x40D3, - 0x40DD, 0x40DF, 0x40E0, 0x40E2, 0x40E4, 0x40EC, - 0x40EE, 0x40F1, 0x40F3, 0x40FD, 0x40FF, 0x4101, - 0x4103, 0x410D, 0x410F, 0x4110, 0x4112, 0x4114, - 0x411C, 0x411E, 0x4121, 0x4123, 0x412D, 0x412F, - 0x4130, 0x4132, 0x4134, 0x413C, 0x413E, 0x4141, - 0x4143, 0x414D, 0x414F, 0x41C1, 0x41C3, 0x41CD, - 0x41CF, 0x41D0, 0x41D2, 0x41D4, 0x41DC, 0x41DE, - 0x41E1, 0x41E3, 0x41ED, 0x41EF, 0x41F0, 0x41F2, - 0x41F4, 0x41FC, 0x41FE, 0x4200, 0x4202, 0x4204, - 0x420C, 0x420E, 0x4211, 0x4213, 0x421D, 0x421F, - 0x4220, 0x4222, 0x4224, 0x422C, 0x422E, 0x4231, - 0x4233, 0x423D, 0x423F, 0x4240, 0x4242, 0x4244, - 0x424C, 0x424E, 0x42C0, 0x42C2, 0x42C4, 0x42CC, - 0x42CE, 0x42D1, 0x42D3, 0x42DD, 0x42DF, 0x42E0, - 0x42E2, 0x42E4, 0x42EC, 0x42EE, 0x42F1, 0x42F3, - 0x42FD, 0x42FF, 0x4301, 0x4303, 0x430D, 0x430F, - 0x4310, 0x4312, 0x4314, 0x431C, 0x431E, 0x4321, - 0x4323, 0x432D, 0x432F, 0x4330, 0x4332, 0x4334, - 0x433C, 0x433E, 0x4341, 0x4343, 0x434D, 0x434F, - 0x43C1, 0x43C3, 0x43CD, 0x43CF, 0x43D0, 0x43D2, - 0x43D4, 0x43DC, 0x43DE, 0x43E1, 0x43E3, 0x43ED, - 0x43EF, 0x43F0, 0x43F2, 0x43F4, 0x43FC, 0x43FE, - 0x4400, 0x4402, 0x4404, 0x440C, 0x440E, 0x4411, - 0x4413, 0x441D, 0x441F, 0x4420, 0x4422, 0x4424, - 0x442C, 0x442E, 0x4431, 0x4433, 0x443D, 0x443F, - 0x4440, 0x4442, 0x4444, 0x444C, 0x444E, 0x44C0, - 0x44C2, 0x44C4, 0x44CC, 0x44CE, 0x44D1, 0x44D3, - 0x44DD, 0x44DF, 0x44E0, 0x44E2, 0x44E4, 0x44EC, - 0x44EE, 0x44F1, 0x44F3, 0x44FD, 0x44FF, 0x4C00, - 0x4C02, 0x4C04, 0x4C0C, 0x4C0E, 0x4C11, 0x4C13, - 0x4C1D, 0x4C1F, 0x4C20, 0x4C22, 0x4C24, 0x4C2C, - 0x4C2E, 0x4C31, 0x4C33, 0x4C3D, 0x4C3F, 0x4C40, - 0x4C42, 0x4C44, 0x4C4C, 0x4C4E, 0x4CC0, 0x4CC2, - 0x4CC4, 0x4CCC, 0x4CCE, 0x4CD1, 0x4CD3, 0x4CDD, - 0x4CDF, 0x4CE0, 0x4CE2, 0x4CE4, 0x4CEC, 0x4CEE, - 0x4CF1, 0x4CF3, 0x4CFD, 0x4CFF, 0x4D01, 0x4D03, - 0x4D0D, 0x4D0F, 0x4D10, 0x4D12, 0x4D14, 0x4D1C, - 0x4D1E, 0x4D21, 0x4D23, 0x4D2D, 0x4D2F, 0x4D30, - 0x4D32, 0x4D34, 0x4D3C, 0x4D3E, 0x4D41, 0x4D43, - 0x4D4D, 0x4D4F, 0x4DC1, 0x4DC3, 0x4DCD, 0x4DCF, - 0x4DD0, 0x4DD2, 0x4DD4, 0x4DDC, 0x4DDE, 0x4DE1, - 0x4DE3, 0x4DED, 0x4DEF, 0x4DF0, 0x4DF2, 0x4DF4, - 0x4DFC, 0x4DFE, 0x4E00, 0x4E02, 0x4E04, 0x4E0C, - 0x4E0E, 0x4E11, 0x4E13, 0x4E1D, 0x4E1F, 0x4E20, - 0x4E22, 0x4E24, 0x4E2C, 0x4E2E, 0x4E31, 0x4E33, - 0x4E3D, 0x4E3F, 0x4E40, 0x4E42, 0x4E44, 0x4E4C, - 0x4E4E, 0x4EC0, 0x4EC2, 0x4EC4, 0x4ECC, 0x4ECE, - 0x4ED1, 0x4ED3, 0x4EDD, 0x4EDF, 0x4EE0, 0x4EE2, - 0x4EE4, 0x4EEC, 0x4EEE, 0x4EF1, 0x4EF3, 0x4EFD, - 0x4EFF, 0x4F01, 0x4F03, 0x4F0D, 0x4F0F, 0x4F10, - 0x4F12, 0x4F14, 0x4F1C, 0x4F1E, 0x4F21, 0x4F23, - 0x4F2D, 0x4F2F, 0x4F30, 0x4F32, 0x4F34, 0x4F3C, - 0x4F3E, 0x4F41, 0x4F43, 0x4F4D, 0x4F4F, 0x4FC1, - 0x4FC3, 0x4FCD, 0x4FCF, 0x4FD0, 0x4FD2, 0x4FD4, - 0x4FDC, 0x4FDE, 0x4FE1, 0x4FE3, 0x4FED, 0x4FEF, - 0x4FF0, 0x4FF2, 0x4FF4, 0x4FFC, 0x4FFE, 0xC000, - 0xC002, 0xC004, 0xC00C, 0xC00E, 0xC011, 0xC013, - 0xC01D, 0xC01F, 0xC020, 0xC022, 0xC024, 0xC02C, - 0xC02E, 0xC031, 0xC033, 0xC03D, 0xC03F, 0xC040, - 0xC042, 0xC044, 0xC04C, 0xC04E, 0xC0C0, 0xC0C2, - 0xC0C4, 0xC0CC, 0xC0CE, 0xC0D1, 0xC0D3, 0xC0DD, - 0xC0DF, 0xC0E0, 0xC0E2, 0xC0E4, 0xC0EC, 0xC0EE, - 0xC0F1, 0xC0F3, 0xC0FD, 0xC0FF, 0xC101, 0xC103, - 0xC10D, 0xC10F, 0xC110, 0xC112, 0xC114, 0xC11C, - 0xC11E, 0xC121, 0xC123, 0xC12D, 0xC12F, 0xC130, - 0xC132, 0xC134, 0xC13C, 0xC13E, 0xC141, 0xC143, - 0xC14D, 0xC14F, 0xC1C1, 0xC1C3, 0xC1CD, 0xC1CF, - 0xC1D0, 0xC1D2, 0xC1D4, 0xC1DC, 0xC1DE, 0xC1E1, - 0xC1E3, 0xC1ED, 0xC1EF, 0xC1F0, 0xC1F2, 0xC1F4, - 0xC1FC, 0xC1FE, 0xC200, 0xC202, 0xC204, 0xC20C, - 0xC20E, 0xC211, 0xC213, 0xC21D, 0xC21F, 0xC220, - 0xC222, 0xC224, 0xC22C, 0xC22E, 0xC231, 0xC233, - 0xC23D, 0xC23F, 0xC240, 0xC242, 0xC244, 0xC24C, - 0xC24E, 0xC2C0, 0xC2C2, 0xC2C4, 0xC2CC, 0xC2CE, - 0xC2D1, 0xC2D3, 0xC2DD, 0xC2DF, 0xC2E0, 0xC2E2, - 0xC2E4, 0xC2EC, 0xC2EE, 0xC2F1, 0xC2F3, 0xC2FD, - 0xC2FF, 0xC301, 0xC303, 0xC30D, 0xC30F, 0xC310, - 0xC312, 0xC314, 0xC31C, 0xC31E, 0xC321, 0xC323, - 0xC32D, 0xC32F, 0xC330, 0xC332, 0xC334, 0xC33C, - 0xC33E, 0xC341, 0xC343, 0xC34D, 0xC34F, 0xC3C1, - 0xC3C3, 0xC3CD, 0xC3CF, 0xC3D0, 0xC3D2, 0xC3D4, - 0xC3DC, 0xC3DE, 0xC3E1, 0xC3E3, 0xC3ED, 0xC3EF, - 0xC3F0, 0xC3F2, 0xC3F4, 0xC3FC, 0xC3FE, 0xC400, - 0xC402, 0xC404, 0xC40C, 0xC40E, 0xC411, 0xC413, - 0xC41D, 0xC41F, 0xC420, 0xC422, 0xC424, 0xC42C, - 0xC42E, 0xC431, 0xC433, 0xC43D, 0xC43F, 0xC440, - 0xC442, 0xC444, 0xC44C, 0xC44E, 0xC4C0, 0xC4C2, - 0xC4C4, 0xC4CC, 0xC4CE, 0xC4D1, 0xC4D3, 0xC4DD, - 0xC4DF, 0xC4E0, 0xC4E2, 0xC4E4, 0xC4EC, 0xC4EE, - 0xC4F1, 0xC4F3, 0xC4FD, 0xC4FF, 0xCC00, 0xCC02, - 0xCC04, 0xCC0C, 0xCC0E, 0xCC11, 0xCC13, 0xCC1D, - 0xCC1F, 0xCC20, 0xCC22, 0xCC24, 0xCC2C, 0xCC2E, - 0xCC31, 0xCC33, 0xCC3D, 0xCC3F, 0xCC40, 0xCC42, - 0xCC44, 0xCC4C, 0xCC4E, 0xCCC0, 0xCCC2, 0xCCC4, - 0xCCCC, 0xCCCE, 0xCCD1, 0xCCD3, 0xCCDD, 0xCCDF, - 0xCCE0, 0xCCE2, 0xCCE4, 0xCCEC, 0xCCEE, 0xCCF1, - 0xCCF3, 0xCCFD, 0xCCFF, 0xCD01, 0xCD03, 0xCD0D, - 0xCD0F, 0xCD10, 0xCD12, 0xCD14, 0xCD1C, 0xCD1E, - 0xCD21, 0xCD23, 0xCD2D, 0xCD2F, 0xCD30, 0xCD32, - 0xCD34, 0xCD3C, 0xCD3E, 0xCD41, 0xCD43, 0xCD4D, - 0xCD4F, 0xCDC1, 0xCDC3, 0xCDCD, 0xCDCF, 0xCDD0, - 0xCDD2, 0xCDD4, 0xCDDC, 0xCDDE, 0xCDE1, 0xCDE3, - 0xCDED, 0xCDEF, 0xCDF0, 0xCDF2, 0xCDF4, 0xCDFC, - 0xCDFE, 0xCE00, 0xCE02, 0xCE04, 0xCE0C, 0xCE0E, - 0xCE11, 0xCE13, 0xCE1D, 0xCE1F, 0xCE20, 0xCE22, - 0xCE24, 0xCE2C, 0xCE2E, 0xCE31, 0xCE33, 0xCE3D, - 0xCE3F, 0xCE40, 0xCE42, 0xCE44, 0xCE4C, 0xCE4E, - 0xCEC0, 0xCEC2, 0xCEC4, 0xCECC, 0xCECE, 0xCED1, - 0xCED3, 0xCEDD, 0xCEDF, 0xCEE0, 0xCEE2, 0xCEE4, - 0xCEEC, 0xCEEE, 0xCEF1, 0xCEF3, 0xCEFD, 0xCEFF, - 0xCF01, 0xCF03, 0xCF0D, 0xCF0F, 0xCF10, 0xCF12, - 0xCF14, 0xCF1C, 0xCF1E, 0xCF21, 0xCF23, 0xCF2D, - 0xCF2F, 0xCF30, 0xCF32, 0xCF34, 0xCF3C, 0xCF3E, - 0xCF41, 0xCF43, 0xCF4D, 0xCF4F, 0xCFC1, 0xCFC3, - 0xCFCD, 0xCFCF, 0xCFD0, 0xCFD2, 0xCFD4, 0xCFDC, - 0xCFDE, 0xCFE1, 0xCFE3, 0xCFED, 0xCFEF, 0xCFF0, - 0xCFF2, 0xCFF4, 0xCFFC, 0xCFFE, 0xD001, 0xD003, - 0xD00D, 0xD00F, 0xD010, 0xD012, 0xD014, 0xD01C, - 0xD01E, 0xD021, 0xD023, 0xD02D, 0xD02F, 0xD030, - 0xD032, 0xD034, 0xD03C, 0xD03E, 0xD041, 0xD043, - 0xD04D, 0xD04F, 0xD0C1, 0xD0C3, 0xD0CD, 0xD0CF, - 0xD0D0, 0xD0D2, 0xD0D4, 0xD0DC, 0xD0DE, 0xD0E1, - 0xD0E3, 0xD0ED, 0xD0EF, 0xD0F0, 0xD0F2, 0xD0F4, - 0xD0FC, 0xD0FE, 0xD100, 0xD102, 0xD104, 0xD10C, - 0xD10E, 0xD111, 0xD113, 0xD11D, 0xD11F, 0xD120, - 0xD122, 0xD124, 0xD12C, 0xD12E, 0xD131, 0xD133, - 0xD13D, 0xD13F, 0xD140, 0xD142, 0xD144, 0xD14C, - 0xD14E, 0xD1C0, 0xD1C2, 0xD1C4, 0xD1CC, 0xD1CE, - 0xD1D1, 0xD1D3, 0xD1DD, 0xD1DF, 0xD1E0, 0xD1E2, - 0xD1E4, 0xD1EC, 0xD1EE, 0xD1F1, 0xD1F3, 0xD1FD, - 0xD1FF, 0xD201, 0xD203, 0xD20D, 0xD20F, 0xD210, - 0xD212, 0xD214, 0xD21C, 0xD21E, 0xD221, 0xD223, - 0xD22D, 0xD22F, 0xD230, 0xD232, 0xD234, 0xD23C, - 0xD23E, 0xD241, 0xD243, 0xD24D, 0xD24F, 0xD2C1, - 0xD2C3, 0xD2CD, 0xD2CF, 0xD2D0, 0xD2D2, 0xD2D4, - 0xD2DC, 0xD2DE, 0xD2E1, 0xD2E3, 0xD2ED, 0xD2EF, - 0xD2F0, 0xD2F2, 0xD2F4, 0xD2FC, 0xD2FE, 0xD300, - 0xD302, 0xD304, 0xD30C, 0xD30E, 0xD311, 0xD313, - 0xD31D, 0xD31F, 0xD320, 0xD322, 0xD324, 0xD32C, - 0xD32E, 0xD331, 0xD333, 0xD33D, 0xD33F, 0xD340, - 0xD342, 0xD344, 0xD34C, 0xD34E, 0xD3C0, 0xD3C2, - 0xD3C4, 0xD3CC, 0xD3CE, 0xD3D1, 0xD3D3, 0xD3DD, - 0xD3DF, 0xD3E0, 0xD3E2, 0xD3E4, 0xD3EC, 0xD3EE, - 0xD3F1, 0xD3F3, 0xD3FD, 0xD3FF, 0xD401, 0xD403, - 0xD40D, 0xD40F, 0xD410, 0xD412, 0xD414, 0xD41C, - 0xD41E, 0xD421, 0xD423, 0xD42D, 0xD42F, 0xD430, - 0xD432, 0xD434, 0xD43C, 0xD43E, 0xD441, 0xD443, - 0xD44D, 0xD44F, 0xD4C1, 0xD4C3, 0xD4CD, 0xD4CF, - 0xD4D0, 0xD4D2, 0xD4D4, 0xD4DC, 0xD4DE, 0xD4E1, - 0xD4E3, 0xD4ED, 0xD4EF, 0xD4F0, 0xD4F2, 0xD4F4, - 0xD4FC, 0xD4FE, 0xDC01, 0xDC03, 0xDC0D, 0xDC0F, - 0xDC10, 0xDC12, 0xDC14, 0xDC1C, 0xDC1E, 0xDC21, - 0xDC23, 0xDC2D, 0xDC2F, 0xDC30, 0xDC32, 0xDC34, - 0xDC3C, 0xDC3E, 0xDC41, 0xDC43, 0xDC4D, 0xDC4F, - 0xDCC1, 0xDCC3, 0xDCCD, 0xDCCF, 0xDCD0, 0xDCD2, - 0xDCD4, 0xDCDC, 0xDCDE, 0xDCE1, 0xDCE3, 0xDCED, - 0xDCEF, 0xDCF0, 0xDCF2, 0xDCF4, 0xDCFC, 0xDCFE, - 0xDD00, 0xDD02, 0xDD04, 0xDD0C, 0xDD0E, 0xDD11, - 0xDD13, 0xDD1D, 0xDD1F, 0xDD20, 0xDD22, 0xDD24, - 0xDD2C, 0xDD2E, 0xDD31, 0xDD33, 0xDD3D, 0xDD3F, - 0xDD40, 0xDD42, 0xDD44, 0xDD4C, 0xDD4E, 0xDDC0, - 0xDDC2, 0xDDC4, 0xDDCC, 0xDDCE, 0xDDD1, 0xDDD3, - 0xDDDD, 0xDDDF, 0xDDE0, 0xDDE2, 0xDDE4, 0xDDEC, - 0xDDEE, 0xDDF1, 0xDDF3, 0xDDFD, 0xDDFF, 0xDE01, - 0xDE03, 0xDE0D, 0xDE0F, 0xDE10, 0xDE12, 0xDE14, - 0xDE1C, 0xDE1E, 0xDE21, 0xDE23, 0xDE2D, 0xDE2F, - 0xDE30, 0xDE32, 0xDE34, 0xDE3C, 0xDE3E, 0xDE41, - 0xDE43, 0xDE4D, 0xDE4F, 0xDEC1, 0xDEC3, 0xDECD, - 0xDECF, 0xDED0, 0xDED2, 0xDED4, 0xDEDC, 0xDEDE, - 0xDEE1, 0xDEE3, 0xDEED, 0xDEEF, 0xDEF0, 0xDEF2, - 0xDEF4, 0xDEFC, 0xDEFE, 0xDF00, 0xDF02, 0xDF04, - 0xDF0C, 0xDF0E, 0xDF11, 0xDF13, 0xDF1D, 0xDF1F, - 0xDF20, 0xDF22, 0xDF24, 0xDF2C, 0xDF2E, 0xDF31, - 0xDF33, 0xDF3D, 0xDF3F, 0xDF40, 0xDF42, 0xDF44, - 0xDF4C, 0xDF4E, 0xDFC0, 0xDFC2, 0xDFC4, 0xDFCC, - 0xDFCE, 0xDFD1, 0xDFD3, 0xDFDD, 0xDFDF, 0xDFE0, - 0xDFE2, 0xDFE4, 0xDFEC, 0xDFEE, 0xDFF1, 0xDFF3, - 0xDFFD, 0xDFFF, 0xE000, 0xE002, 0xE004, 0xE00C, - 0xE00E, 0xE011, 0xE013, 0xE01D, 0xE01F, 0xE020, - 0xE022, 0xE024, 0xE02C, 0xE02E, 0xE031, 0xE033, - 0xE03D, 0xE03F, 0xE040, 0xE042, 0xE044, 0xE04C, - 0xE04E, 0xE0C0, 0xE0C2, 0xE0C4, 0xE0CC, 0xE0CE, - 0xE0D1, 0xE0D3, 0xE0DD, 0xE0DF, 0xE0E0, 0xE0E2, - 0xE0E4, 0xE0EC, 0xE0EE, 0xE0F1, 0xE0F3, 0xE0FD, - 0xE0FF, 0xE101, 0xE103, 0xE10D, 0xE10F, 0xE110, - 0xE112, 0xE114, 0xE11C, 0xE11E, 0xE121, 0xE123, - 0xE12D, 0xE12F, 0xE130, 0xE132, 0xE134, 0xE13C, - 0xE13E, 0xE141, 0xE143, 0xE14D, 0xE14F, 0xE1C1, - 0xE1C3, 0xE1CD, 0xE1CF, 0xE1D0, 0xE1D2, 0xE1D4, - 0xE1DC, 0xE1DE, 0xE1E1, 0xE1E3, 0xE1ED, 0xE1EF, - 0xE1F0, 0xE1F2, 0xE1F4, 0xE1FC, 0xE1FE, 0xE200, - 0xE202, 0xE204, 0xE20C, 0xE20E, 0xE211, 0xE213, - 0xE21D, 0xE21F, 0xE220, 0xE222, 0xE224, 0xE22C, - 0xE22E, 0xE231, 0xE233, 0xE23D, 0xE23F, 0xE240, - 0xE242, 0xE244, 0xE24C, 0xE24E, 0xE2C0, 0xE2C2, - 0xE2C4, 0xE2CC, 0xE2CE, 0xE2D1, 0xE2D3, 0xE2DD, - 0xE2DF, 0xE2E0, 0xE2E2, 0xE2E4, 0xE2EC, 0xE2EE, - 0xE2F1, 0xE2F3, 0xE2FD, 0xE2FF, 0xE301, 0xE303, - 0xE30D, 0xE30F, 0xE310, 0xE312, 0xE314, 0xE31C, - 0xE31E, 0xE321, 0xE323, 0xE32D, 0xE32F, 0xE330, - 0xE332, 0xE334, 0xE33C, 0xE33E, 0xE341, 0xE343, - 0xE34D, 0xE34F, 0xE3C1, 0xE3C3, 0xE3CD, 0xE3CF, - 0xE3D0, 0xE3D2, 0xE3D4, 0xE3DC, 0xE3DE, 0xE3E1, - 0xE3E3, 0xE3ED, 0xE3EF, 0xE3F0, 0xE3F2, 0xE3F4, - 0xE3FC, 0xE3FE, 0xE400, 0xE402, 0xE404, 0xE40C, - 0xE40E, 0xE411, 0xE413, 0xE41D, 0xE41F, 0xE420, - 0xE422, 0xE424, 0xE42C, 0xE42E, 0xE431, 0xE433, - 0xE43D, 0xE43F, 0xE440, 0xE442, 0xE444, 0xE44C, - 0xE44E, 0xE4C0, 0xE4C2, 0xE4C4, 0xE4CC, 0xE4CE, - 0xE4D1, 0xE4D3, 0xE4DD, 0xE4DF, 0xE4E0, 0xE4E2, - 0xE4E4, 0xE4EC, 0xE4EE, 0xE4F1, 0xE4F3, 0xE4FD, - 0xE4FF, 0xEC00, 0xEC02, 0xEC04, 0xEC0C, 0xEC0E, - 0xEC11, 0xEC13, 0xEC1D, 0xEC1F, 0xEC20, 0xEC22, - 0xEC24, 0xEC2C, 0xEC2E, 0xEC31, 0xEC33, 0xEC3D, - 0xEC3F, 0xEC40, 0xEC42, 0xEC44, 0xEC4C, 0xEC4E, - 0xECC0, 0xECC2, 0xECC4, 0xECCC, 0xECCE, 0xECD1, - 0xECD3, 0xECDD, 0xECDF, 0xECE0, 0xECE2, 0xECE4, - 0xECEC, 0xECEE, 0xECF1, 0xECF3, 0xECFD, 0xECFF, - 0xED01, 0xED03, 0xED0D, 0xED0F, 0xED10, 0xED12, - 0xED14, 0xED1C, 0xED1E, 0xED21, 0xED23, 0xED2D, - 0xED2F, 0xED30, 0xED32, 0xED34, 0xED3C, 0xED3E, - 0xED41, 0xED43, 0xED4D, 0xED4F, 0xEDC1, 0xEDC3, - 0xEDCD, 0xEDCF, 0xEDD0, 0xEDD2, 0xEDD4, 0xEDDC, - 0xEDDE, 0xEDE1, 0xEDE3, 0xEDED, 0xEDEF, 0xEDF0, - 0xEDF2, 0xEDF4, 0xEDFC, 0xEDFE, 0xEE00, 0xEE02, - 0xEE04, 0xEE0C, 0xEE0E, 0xEE11, 0xEE13, 0xEE1D, - 0xEE1F, 0xEE20, 0xEE22, 0xEE24, 0xEE2C, 0xEE2E, - 0xEE31, 0xEE33, 0xEE3D, 0xEE3F, 0xEE40, 0xEE42, - 0xEE44, 0xEE4C, 0xEE4E, 0xEEC0, 0xEEC2, 0xEEC4, - 0xEECC, 0xEECE, 0xEED1, 0xEED3, 0xEEDD, 0xEEDF, - 0xEEE0, 0xEEE2, 0xEEE4, 0xEEEC, 0xEEEE, 0xEEF1, - 0xEEF3, 0xEEFD, 0xEEFF, 0xEF01, 0xEF03, 0xEF0D, - 0xEF0F, 0xEF10, 0xEF12, 0xEF14, 0xEF1C, 0xEF1E, - 0xEF21, 0xEF23, 0xEF2D, 0xEF2F, 0xEF30, 0xEF32, - 0xEF34, 0xEF3C, 0xEF3E, 0xEF41, 0xEF43, 0xEF4D, - 0xEF4F, 0xEFC1, 0xEFC3, 0xEFCD, 0xEFCF, 0xEFD0, - 0xEFD2, 0xEFD4, 0xEFDC, 0xEFDE, 0xEFE1, 0xEFE3, - 0xEFED, 0xEFEF, 0xEFF0, 0xEFF2, 0xEFF4, 0xEFFC, - 0xEFFE, 0xF001, 0xF003, 0xF00D, 0xF00F, 0xF010, - 0xF012, 0xF014, 0xF01C, 0xF01E, 0xF021, 0xF023, - 0xF02D, 0xF02F, 0xF030, 0xF032, 0xF034, 0xF03C, - 0xF03E, 0xF041, 0xF043, 0xF04D, 0xF04F, 0xF0C1, - 0xF0C3, 0xF0CD, 0xF0CF, 0xF0D0, 0xF0D2, 0xF0D4, - 0xF0DC, 0xF0DE, 0xF0E1, 0xF0E3, 0xF0ED, 0xF0EF, - 0xF0F0, 0xF0F2, 0xF0F4, 0xF0FC, 0xF0FE, 0xF100, - 0xF102, 0xF104, 0xF10C, 0xF10E, 0xF111, 0xF113, - 0xF11D, 0xF11F, 0xF120, 0xF122, 0xF124, 0xF12C, - 0xF12E, 0xF131, 0xF133, 0xF13D, 0xF13F, 0xF140, - 0xF142, 0xF144, 0xF14C, 0xF14E, 0xF1C0, 0xF1C2, - 0xF1C4, 0xF1CC, 0xF1CE, 0xF1D1, 0xF1D3, 0xF1DD, - 0xF1DF, 0xF1E0, 0xF1E2, 0xF1E4, 0xF1EC, 0xF1EE, - 0xF1F1, 0xF1F3, 0xF1FD, 0xF1FF, 0xF201, 0xF203, - 0xF20D, 0xF20F, 0xF210, 0xF212, 0xF214, 0xF21C, - 0xF21E, 0xF221, 0xF223, 0xF22D, 0xF22F, 0xF230, - 0xF232, 0xF234, 0xF23C, 0xF23E, 0xF241, 0xF243, - 0xF24D, 0xF24F, 0xF2C1, 0xF2C3, 0xF2CD, 0xF2CF, - 0xF2D0, 0xF2D2, 0xF2D4, 0xF2DC, 0xF2DE, 0xF2E1, - 0xF2E3, 0xF2ED, 0xF2EF, 0xF2F0, 0xF2F2, 0xF2F4, - 0xF2FC, 0xF2FE, 0xF300, 0xF302, 0xF304, 0xF30C, - 0xF30E, 0xF311, 0xF313, 0xF31D, 0xF31F, 0xF320, - 0xF322, 0xF324, 0xF32C, 0xF32E, 0xF331, 0xF333, - 0xF33D, 0xF33F, 0xF340, 0xF342, 0xF344, 0xF34C, - 0xF34E, 0xF3C0, 0xF3C2, 0xF3C4, 0xF3CC, 0xF3CE, - 0xF3D1, 0xF3D3, 0xF3DD, 0xF3DF, 0xF3E0, 0xF3E2, - 0xF3E4, 0xF3EC, 0xF3EE, 0xF3F1, 0xF3F3, 0xF3FD, - 0xF3FF, 0xF401, 0xF403, 0xF40D, 0xF40F, 0xF410, - 0xF412, 0xF414, 0xF41C, 0xF41E, 0xF421, 0xF423, - 0xF42D, 0xF42F, 0xF430, 0xF432, 0xF434, 0xF43C, - 0xF43E, 0xF441, 0xF443, 0xF44D, 0xF44F, 0xF4C1, - 0xF4C3, 0xF4CD, 0xF4CF, 0xF4D0, 0xF4D2, 0xF4D4, - 0xF4DC, 0xF4DE, 0xF4E1, 0xF4E3, 0xF4ED, 0xF4EF, - 0xF4F0, 0xF4F2, 0xF4F4, 0xF4FC, 0xF4FE, 0xFC01, - 0xFC03, 0xFC0D, 0xFC0F, 0xFC10, 0xFC12, 0xFC14, - 0xFC1C, 0xFC1E, 0xFC21, 0xFC23, 0xFC2D, 0xFC2F, - 0xFC30, 0xFC32, 0xFC34, 0xFC3C, 0xFC3E, 0xFC41, - 0xFC43, 0xFC4D, 0xFC4F, 0xFCC1, 0xFCC3, 0xFCCD, - 0xFCCF, 0xFCD0, 0xFCD2, 0xFCD4, 0xFCDC, 0xFCDE, - 0xFCE1, 0xFCE3, 0xFCED, 0xFCEF, 0xFCF0, 0xFCF2, - 0xFCF4, 0xFCFC, 0xFCFE, 0xFD00, 0xFD02, 0xFD04, - 0xFD0C, 0xFD0E, 0xFD11, 0xFD13, 0xFD1D, 0xFD1F, - 0xFD20, 0xFD22, 0xFD24, 0xFD2C, 0xFD2E, 0xFD31, - 0xFD33, 0xFD3D, 0xFD3F, 0xFD40, 0xFD42, 0xFD44, - 0xFD4C, 0xFD4E, 0xFDC0, 0xFDC2, 0xFDC4, 0xFDCC, - 0xFDCE, 0xFDD1, 0xFDD3, 0xFDDD, 0xFDDF, 0xFDE0, - 0xFDE2, 0xFDE4, 0xFDEC, 0xFDEE, 0xFDF1, 0xFDF3, - 0xFDFD, 0xFDFF, 0xFE01, 0xFE03, 0xFE0D, 0xFE0F, - 0xFE10, 0xFE12, 0xFE14, 0xFE1C, 0xFE1E, 0xFE21, - 0xFE23, 0xFE2D, 0xFE2F, 0xFE30, 0xFE32, 0xFE34, - 0xFE3C, 0xFE3E, 0xFE41, 0xFE43, 0xFE4D, 0xFE4F, - 0xFEC1, 0xFEC3, 0xFECD, 0xFECF, 0xFED0, 0xFED2, - 0xFED4, 0xFEDC, 0xFEDE, 0xFEE1, 0xFEE3, 0xFEED, - 0xFEEF, 0xFEF0, 0xFEF2, 0xFEF4, 0xFEFC, 0xFEFE, - 0xFF00, 0xFF02, 0xFF04, 0xFF0C, 0xFF0E, 0xFF11, - 0xFF13, 0xFF1D, 0xFF1F, 0xFF20, 0xFF22, 0xFF24, - 0xFF2C, 0xFF2E, 0xFF31, 0xFF33, 0xFF3D, 0xFF3F, - 0xFF40, 0xFF42, 0xFF44, 0xFF4C, 0xFF4E, 0xFFC0, - 0xFFC2, 0xFFC4, 0xFFCC, 0xFFCE, 0xFFD1, 0xFFD3, - 0xFFDD, 0xFFDF, 0xFFE0, 0xFFE2, 0xFFE4, 0xFFEC, - 0xFFEE, 0xFFF1, 0xFFF3, 0xFFFD, 0xFFFF, -}; - -#define ON2AVC_CB8_CODES 3281 -static const uint32_t on2avc_cb8_codes[ON2AVC_CB8_CODES] = { - 0x028C, 0x05E6, 0xFAD9, 0x7DEF, 0x06CE, 0x004C, - 0x0178, 0x0A1D, 0x00AE, 0x046E, 0x03D5, 0x3F58, - 0x0EAA, 0x0233, 0x1A6A, 0x271F, 0x05CE, 0x0179, - 0x02FB, 0x0029, 0x237D, 0x7DF0, 0x03BA, 0xFAD6, - 0xFAD7, 0x7DEE, 0xFAD5, 0x0081, 0x033C, 0x1A69, - 0xFAD8, 0x05A1, 0x01F1, 0x063D, 0x237C, 0x003E, - 0x0323, 0x010C, 0x05A3, 0x05A2, 0x0051, 0x019D, - 0xFADB, 0x0EAB, 0x00AA, 0x003E, 0x01A6, 0x7DF2, - 0x0058, 0x01F1, 0x029B, 0x03C0, 0x122D, 0x0075, - 0x3F5A, 0x0B98, 0x0005, 0x058B, 0x0D68, 0x013F, - 0x00D0, 0x05CF, 0x01C0, 0x03BB, 0x046F, 0xFADA, - 0x01A0, 0x0972, 0x122C, 0x3F59, 0x0766, 0x05A4, - 0x00ED, 0x05A5, 0x0D67, 0x03D0, 0x0046, 0x01FF, - 0x7DF1, 0x00D6, 0x017C, 0x0034, 0x08B5, 0x0234, - 0x237E, 0x0033, 0x0083, 0x0B99, 0x0EAC, 0x0202, - 0x0714, 0x0715, 0x01C3, 0x05A6, 0x0324, 0x13EC, - 0x02F8, 0x7DF3, 0x13EB, 0x0140, 0x0470, 0x04F8, - 0x0007, 0x0377, 0x0208, 0x04A3, 0x13EA, 0x0006, - 0x0188, 0x033D, 0x122E, 0x1A6B, 0x0A1E, 0x0126, - 0x03C1, 0x05E7, 0x05D0, 0x04F7, 0x03DB, 0x033E, - 0x122F, 0x0082, 0x1A6F, 0x2380, 0x05D2, 0x0009, - 0x05A9, 0x1A70, 0x1233, 0x05A7, 0x05A8, 0x0975, - 0x2381, 0x1234, 0x0788, 0x2720, 0x1235, 0x05D3, - 0xFADD, 0x3F5B, 0x0789, 0x0D69, 0xFADE, 0xFADF, - 0x01C4, 0x0EAD, 0x0EA1, 0x1230, 0x0008, 0x13ED, - 0x1A6C, 0xFADC, 0x1231, 0x0973, 0x1232, 0x1A6D, - 0x13EE, 0x1A6E, 0x0974, 0x237F, 0x05D1, 0x033F, - 0x0267, 0x078A, 0xFAE3, 0xFAE2, 0x0B9A, 0x00FC, - 0x0EAE, 0x05D6, 0x0325, 0x0326, 0x0B9B, 0x3F5F, - 0x3F5E, 0x0471, 0x02F9, 0xFAE4, 0x1A72, 0x03C2, - 0x05D7, 0x2721, 0x3F60, 0xFAE5, 0x2382, 0xFAE0, - 0x7DF5, 0xFAE1, 0x7DF4, 0x000A, 0x0235, 0x3F5C, - 0x1A71, 0x0716, 0x036C, 0x0767, 0x05D4, 0x3F5D, - 0x0717, 0x01BF, 0x000B, 0x05D5, 0x0243, 0xFAD0, - 0x04F6, 0x7DE5, 0xFACF, 0x0E9E, 0x0074, 0x271A, - 0x1A61, 0x015B, 0x0046, 0x06CA, 0x237A, 0x7DE6, - 0x0070, 0x1A62, 0x1227, 0x7DE7, 0x0032, 0xFAD1, - 0x05CA, 0x7DE8, 0x237B, 0x13E6, 0x05C8, 0x1226, - 0x2377, 0x2719, 0x3F54, 0x3F55, 0x13E5, 0x2378, - 0x03BF, 0x05C9, 0x01C0, 0x7DE4, 0x7DE3, 0x0A19, - 0x0045, 0x1A60, 0x2379, 0x021B, 0x271C, 0x13E7, - 0x271B, 0x1A67, 0x059D, 0x0EA6, 0x0EA7, 0x0174, - 0x0EA5, 0x0A1A, 0x1FFD, 0x033A, 0x0E9F, 0x3F57, - 0x122B, 0xFAD2, 0x0D64, 0x05CC, 0x06CB, 0x1FFE, - 0x059E, 0x02F7, 0x1228, 0x7DE9, 0x059B, 0x096C, - 0x1A63, 0x1A64, 0x1A65, 0x1229, 0x0EA3, 0x059C, - 0x096D, 0x05CB, 0x003C, 0x1A66, 0x0D63, 0x3F56, - 0x122A, 0x0EA4, 0x0712, 0x0232, 0x13E8, 0x061E, - 0x08B4, 0x016E, 0x0176, 0x033B, 0x0028, 0x05E5, - 0x061F, 0x0000, 0x0376, 0x0071, 0x096F, 0x7DEB, - 0x0001, 0x05CD, 0xFAD3, 0x0186, 0x0EA9, 0x13E9, - 0x06CD, 0x7DEA, 0x0340, 0x271D, 0x0175, 0x01C1, - 0x0D65, 0x1FFF, 0x0B97, 0x0EA8, 0x06CC, 0x0375, - 0x05E4, 0x08B3, 0x05E3, 0x0341, 0x0EA0, 0x096E, - 0x03CF, 0x0056, 0x0970, 0x1A68, 0x029A, 0x010A, - 0x00A8, 0x01CA, 0x7DED, 0x00A5, 0x001E, 0x05A0, - 0x0D66, 0x0047, 0x0971, 0x0A1C, 0x02CE, 0xFAD4, - 0x0004, 0x010F, 0x271E, 0x0415, 0x0212, 0x019F, - 0x7DEC, 0x01C2, 0x0187, 0x059F, 0x0A1B, 0x0527, - 0x0002, 0x003D, 0x0041, 0x0177, 0x0713, 0x010E, - 0x0102, 0x02CF, 0x00CA, 0x0003, 0x01BF, 0x0120, - 0x05DE, 0x0043, 0x01D0, 0x018C, 0x00AB, 0x029F, - 0x03DF, 0x03C5, 0x0247, 0x08BB, 0x0013, 0x03D2, - 0x0015, 0x0EB0, 0x02FA, 0x05E8, 0x0014, 0x0EB1, - 0x0476, 0x1A78, 0x01F4, 0x06D1, 0x017C, 0x0042, - 0x063F, 0x0011, 0x0012, 0x01C7, 0x04FB, 0x1A77, - 0x01AA, 0x04FC, 0x0A21, 0x021D, 0x01EE, 0x02BC, - 0x01C2, 0x021E, 0x00AA, 0x00D6, 0x021F, 0x016F, - 0x0077, 0x01AB, 0x00AC, 0x0073, 0x078D, 0x00AF, - 0x002E, 0x0220, 0x0086, 0x0103, 0x0086, 0x0127, - 0x0BA0, 0x05DF, 0x0EA5, 0x03D3, 0x05E0, 0x017D, - 0xFAE7, 0x015A, 0x03C6, 0x0768, 0xFAE6, 0x3F65, - 0x01F3, 0x0B9F, 0x0016, 0x0EA4, 0x078C, 0x02BD, - 0x004D, 0x0116, 0x037A, 0x0076, 0x0056, 0x058E, - 0x06D2, 0x0014, 0x009F, 0x0A23, 0x0346, 0x014E, - 0x02BF, 0x00A7, 0x0528, 0x0378, 0x0106, 0x01C3, - 0x017E, 0x0044, 0x03C7, 0x097F, 0x04A5, 0x020B, - 0x05E9, 0x0A24, 0x03D9, 0x0661, 0x0660, 0x014F, - 0x02BE, 0x023B, 0x04FD, 0x0313, 0x0017, 0x08BC, - 0x0769, 0x0622, 0x0D6C, 0x03D7, 0x01C8, 0x0A22, - 0x01AB, 0x0203, 0x076A, 0x03D8, 0x02D1, 0x00A6, - 0x05E3, 0x1A79, 0x1A7A, 0x0981, 0x05B1, 0x04FF, - 0x0982, 0x0348, 0x0128, 0x08BD, 0x0D6D, 0x13F4, - 0x05B2, 0x0624, 0x05B3, 0x0EB2, 0x2729, 0x1237, - 0x05B4, 0x0129, 0x0349, 0x2386, 0x0019, 0x04FE, - 0x05B0, 0xFAE8, 0x3F66, 0x0623, 0x05E1, 0x05E2, - 0x3F67, 0x0980, 0x0347, 0x0BA1, 0x0046, 0x0045, - 0x0EA6, 0x01C9, 0x0018, 0x13F3, 0x078E, 0x0152, - 0x0983, 0x1238, 0x272B, 0x01F2, 0x028F, 0x05E5, - 0x3F69, 0x0418, 0x02FC, 0x017F, 0x0EB3, 0x00EF, - 0x0790, 0x0791, 0x1239, 0x05E6, 0x05E7, 0x1A7C, - 0x034A, 0x001A, 0x0984, 0x05B5, 0x272A, 0x1A7B, - 0x0EA7, 0x0529, 0x02FB, 0x2387, 0x3F68, 0x078F, - 0x006D, 0x0D6E, 0x05B6, 0x039F, 0x014E, 0x058F, - 0x13F5, 0x05E4, 0x020C, 0x0342, 0x1A73, 0x7DF7, - 0x2724, 0x0082, 0x0209, 0x1A74, 0x05DB, 0x03D6, - 0x001F, 0x0B9C, 0x04F9, 0x0096, 0x03C3, 0x0620, - 0x7DF9, 0x7DF8, 0x0EA2, 0x000C, 0x2725, 0x3F61, - 0x0977, 0x0976, 0x2723, 0x05D8, 0x2722, 0x058C, - 0x08B6, 0x05D9, 0x2383, 0x0236, 0x036D, 0x0A1F, - 0x05AA, 0x019C, 0x01C0, 0x0327, 0x05DA, 0x7DF6, - 0x02CF, 0x05DD, 0x0341, 0x05AE, 0x0EAF, 0x2384, - 0x0342, 0x13F0, 0x000D, 0x08B7, 0x000E, 0x003F, - 0x097B, 0x0343, 0x0D6A, 0x1A75, 0x000F, 0x3F63, - 0x05AF, 0x06CF, 0x06D0, 0x2385, 0x13F1, 0x058D, - 0x0237, 0x05AB, 0x7DFA, 0x0EA3, 0x03C4, 0x13EF, - 0x05DC, 0x2726, 0x1236, 0x017A, 0x0978, 0x05AD, - 0x05AC, 0x0340, 0x0238, 0x097A, 0x3F62, 0x0979, - 0x03DE, 0x0010, 0x0345, 0x002A, 0x03D1, 0x01A7, - 0x01F2, 0x009E, 0x020A, 0x0189, 0x0D6B, 0x03C6, - 0x00EE, 0x0A20, 0x017B, 0x04FA, 0x0472, 0x0040, - 0x00CB, 0x08B9, 0x02D0, 0x029E, 0x0020, 0x0344, - 0x0239, 0x02D0, 0x0B9D, 0x023A, 0x0B9E, 0x028D, - 0x03C5, 0x03BE, 0x08B8, 0x078B, 0x0337, 0x0246, - 0x004C, 0x0416, 0x0141, 0x04A4, 0x00E2, 0x0213, - 0x028E, 0x01A7, 0x021C, 0x00D4, 0x01C6, 0x0072, - 0x0067, 0x002B, 0x0473, 0x036F, 0x01E0, 0x036E, - 0x0041, 0x3F64, 0x097E, 0x0621, 0x02BB, 0x00D7, - 0x2728, 0x2727, 0x01C1, 0x0129, 0x0417, 0x13F2, - 0x097C, 0x0142, 0x097D, 0x1A76, 0x08BA, 0x063E, - 0x0100, 0x01AA, 0x018A, 0x00EA, 0x014D, 0x001E, - 0x01C5, 0x03C7, 0x0053, 0x05EC, 0x012D, 0x004C, - 0x0D71, 0x01D0, 0x0023, 0x0D72, 0x0185, 0x02D2, - 0x0719, 0x012F, 0x0502, 0x012E, 0x0A28, 0x098E, - 0x238B, 0x272D, 0x05EE, 0x05BE, 0x0130, 0xFAEE, - 0x272E, 0x0BA2, 0x05EB, 0x01CF, 0xFAED, 0x238A, - 0x01CE, 0x098C, 0x7DFD, 0x05BD, 0x004A, 0x0036, - 0x0037, 0x0628, 0x02FD, 0x048A, 0x017E, 0x004B, - 0x098D, 0x0153, 0x0216, 0x0D73, 0x1A82, 0x0042, - 0x017F, 0x026C, 0x020D, 0x0794, 0x0143, 0x007E, - 0x062A, 0x0798, 0x004F, 0x0EBA, 0x0BA4, 0x023E, - 0x05BF, 0x0EB9, 0x0592, 0x03CC, 0x004E, 0x018E, - 0x032C, 0x0629, 0x0BA3, 0x01F7, 0x0EB8, 0x004D, - 0x0990, 0x0350, 0x098F, 0x0343, 0x0023, 0x052B, - 0x004E, 0x0178, 0x04A6, 0x0291, 0x05ED, 0x00DC, - 0x032D, 0x0504, 0x0991, 0x0A29, 0x0593, 0x01F3, - 0x0A2A, 0x0505, 0x015B, 0x0666, 0x0087, 0x03DA, - 0x0BA5, 0x076D, 0x05C1, 0x03CD, 0x0024, 0x0992, - 0x04A7, 0x0131, 0x05C2, 0x272F, 0x01D1, 0x076B, - 0x076C, 0x1242, 0x05EF, 0x062B, 0x0EAE, 0x13FD, - 0x05C0, 0x0EBB, 0x023F, 0x0D74, 0x0503, 0x02FE, - 0x041A, 0x037B, 0x08BE, 0x0240, 0x0316, 0x0EBD, - 0x3F70, 0x0EBC, 0x0A2B, 0x0BA7, 0x0053, 0x05C5, - 0x13FE, 0x0506, 0x03CE, 0x0026, 0x0994, 0x0038, - 0x0027, 0x0132, 0x020E, 0x2731, 0x0EBE, 0x0796, - 0x018F, 0x05C6, 0x02FF, 0x0795, 0x1A83, 0x3F6E, - 0x0BA6, 0x0025, 0x1243, 0x3F6F, 0x004F, 0x2730, - 0x062C, 0x0993, 0x05C3, 0x05C4, 0x0051, 0x0052, - 0x0351, 0x062D, 0x0050, 0x01F6, 0x08BF, 0x3F71, - 0x238E, 0x05C7, 0x01F7, 0x05C8, 0x062E, 0x012A, - 0x032F, 0x0077, 0x1A86, 0x0EBF, 0x03DB, 0x04AA, - 0x0BA8, 0x13FF, 0x062F, 0xFAF2, 0x071A, 0x0054, - 0xFAF1, 0x2732, 0xFAF0, 0x238C, 0x238D, 0xFAEF, - 0x1A84, 0x0392, 0x1244, 0x0995, 0x0799, 0x007F, - 0x032E, 0x7DFE, 0x1A85, 0x05EE, 0x018A, 0x0996, - 0x0028, 0x0152, 0x025A, 0x0A25, 0x7DFC, 0x3F6B, - 0x023C, 0x018B, 0x05B7, 0x0180, 0x00FD, 0x01BA, - 0x05EA, 0x123D, 0x05E8, 0x002F, 0x0625, 0x05B9, - 0x05B8, 0x0477, 0x13F7, 0x0D6F, 0x3F6C, 0xFAEA, - 0x01CB, 0xFAE9, 0x0985, 0x2388, 0x7DFB, 0x034B, - 0x01CA, 0x0047, 0x123A, 0x3F6A, 0x017D, 0x0662, - 0x123C, 0x123B, 0x0379, 0x024A, 0x13F6, 0x1A7D, - 0x016A, 0x0EAA, 0x123F, 0xFAEC, 0x0EA9, 0x13FB, - 0x0182, 0x0792, 0x05BA, 0x0181, 0x0D70, 0x001F, - 0x001E, 0x05BB, 0x3F6D, 0x0020, 0x2389, 0x1240, - 0x0183, 0x0501, 0x1A7F, 0x06D6, 0x0663, 0x06D3, - 0x13F8, 0x034C, 0x0EB4, 0x123E, 0x1A7E, 0x13F9, - 0x001B, 0x05E9, 0x0EA8, 0x001C, 0xFAEB, 0x05EA, - 0x034D, 0x0500, 0x13FA, 0x001D, 0x0048, 0x0794, - 0x0075, 0x0795, 0x0793, 0x0074, 0x008A, 0x03C9, - 0x05EB, 0x0087, 0x0076, 0x012B, 0x012C, 0x037A, - 0x0718, 0x0022, 0x272C, 0x0988, 0x0EB5, 0x0328, - 0x03CA, 0x05EC, 0x0EAB, 0x06D7, 0x0021, 0x0664, - 0x1A80, 0x0986, 0x0419, 0x03C8, 0x034E, 0x0987, - 0x0626, 0x02FC, 0x00AE, 0x01CC, 0x023D, 0x012A, - 0x0021, 0x0A26, 0x05BC, 0x01F6, 0x0221, 0x0049, - 0x0EB6, 0x0042, 0x02D2, 0x00F2, 0x00AF, 0x0290, - 0x0043, 0x052A, 0x13FC, 0x0A27, 0x032A, 0x1241, - 0x0EB7, 0x0EAD, 0x034F, 0x0EAC, 0x0022, 0x05ED, - 0x0797, 0x032B, 0x0035, 0x0989, 0x0184, 0x037B, - 0x098A, 0x1A81, 0x098B, 0x0796, 0x01CD, 0x025B, - 0x03CB, 0x0627, 0x02DA, 0x010C, 0x02D1, 0x06EA, - 0x0665, 0x0329, 0x0D78, 0x7E05, 0x7E04, 0x140A, - 0x0EB3, 0x0ECF, 0x3F7C, 0x1256, 0x05FB, 0x05CF, - 0xFAFF, 0x3F7D, 0x0ED0, 0x7E06, 0x3F7E, 0x3F7F, - 0xFB00, 0x239B, 0x0ED2, 0x1257, 0x7E07, 0x0ED1, - 0x002D, 0x1255, 0x273A, 0x09A4, 0x239A, 0x0ECD, - 0x273B, 0x1A8C, 0x002E, 0x09A5, 0xFAFE, 0x273C, - 0x0BAF, 0x0BB0, 0x05CE, 0x09A6, 0x00D1, 0x0ECE, - 0x09A8, 0x0030, 0x1A8E, 0x0ED3, 0x09A7, 0x0667, - 0x1258, 0x2740, 0x0D79, 0x3F80, 0x0189, 0x09A9, - 0x0EB5, 0x0359, 0x0ED4, 0x125A, 0x239D, 0x1259, - 0x05D1, 0x0D7A, 0x7E0A, 0x7E09, 0x09AA, 0x273D, - 0x0EB4, 0x273E, 0x002F, 0x0354, 0x05FC, 0x239C, - 0x1A8D, 0x0355, 0x0357, 0x05D0, 0x0358, 0x0356, - 0x01D2, 0x0508, 0x7E08, 0x273F, 0x0302, 0x0ED7, - 0x239E, 0x3F84, 0x08C4, 0x01D3, 0x0BB1, 0x0509, - 0x239F, 0x0303, 0x0133, 0x035C, 0x125B, 0x03D1, - 0x0ED8, 0x035D, 0x035E, 0x2743, 0x2744, 0x09AD, - 0x018A, 0x0031, 0x09AC, 0x3F82, 0x2741, 0x3F81, - 0x035A, 0x3F83, 0x05FD, 0x09AB, 0x0ED5, 0x0ED6, - 0x0633, 0x2742, 0x0055, 0x08C3, 0x0636, 0x035B, - 0x05FE, 0x0D7B, 0x0039, 0xFB05, 0x7E0B, 0x7E0C, - 0x140D, 0x018B, 0x09AF, 0x2746, 0x0032, 0x0056, - 0x09B0, 0x03D2, 0x0A30, 0x2747, 0x0057, 0x0EDA, - 0x050A, 0x125E, 0x0033, 0x2748, 0x0D7C, 0x03D3, - 0x3F85, 0x0034, 0xFB01, 0x140B, 0xFB02, 0x05FF, - 0x125C, 0xFB03, 0x125D, 0x1A8F, 0x0600, 0x05D2, - 0x0602, 0x2745, 0x0601, 0x0ED9, 0x1A90, 0xFB04, - 0x140C, 0x09AE, 0x033A, 0x7E0F, 0x23A2, 0x0A31, - 0x0EB6, 0x0058, 0x3F8A, 0x23A3, 0x01D6, 0x04AB, - 0x0059, 0x0EDB, 0x02D3, 0x018C, 0x04C6, 0x1260, - 0x3F8B, 0x125F, 0x1261, 0x071E, 0x7E10, 0x2749, - 0x140E, 0x3F87, 0x3F86, 0x0035, 0x3F88, 0x3F89, - 0x7E0D, 0x23A0, 0x1A91, 0x0797, 0x0603, 0x1A92, - 0x050B, 0x066A, 0x0306, 0x7E0E, 0x23A1, 0x079B, - 0x0BAA, 0x3F73, 0x7E01, 0x0292, 0x0216, 0x0998, - 0x1247, 0x2390, 0x0301, 0x0999, 0x1400, 0x1A87, - 0x041E, 0x1401, 0x0EC1, 0x2391, 0x3F74, 0x0A2C, - 0x1248, 0x3F75, 0x05C9, 0x0EC2, 0x2733, 0x238F, - 0xFAF3, 0xFAF4, 0x0EC0, 0x0997, 0x3F72, 0xFAF5, - 0x1245, 0x08C0, 0x0BA9, 0x1246, 0x020F, 0x041B, - 0x0186, 0x7E00, 0x7DFF, 0x0300, 0xFAFA, 0x2734, - 0x05F2, 0x124D, 0x2395, 0x099A, 0x2735, 0x3F77, - 0x0EC4, 0x0EC5, 0x1403, 0x0EC6, 0x1402, 0x1A89, - 0x3F78, 0x05F5, 0x05F3, 0x05F4, 0x2736, 0x1404, - 0x7E02, 0x124E, 0x0D75, 0x0029, 0x2392, 0xFAF7, - 0xFAF6, 0x0EC3, 0x1249, 0x2394, 0x2393, 0x05F0, - 0xFAF8, 0x124B, 0x124C, 0x124A, 0x3F76, 0x05CA, - 0x05F1, 0xFAF9, 0x1A88, 0x0187, 0x05F7, 0x124F, - 0x0631, 0x0D76, 0x0EAF, 0x2737, 0x0BAC, 0x099D, - 0x0A2D, 0x1250, 0x1407, 0x0BAD, 0x3F7A, 0x2396, - 0x2397, 0x0353, 0x1A8B, 0x08C2, 0x05CD, 0x099E, - 0x05CC, 0x0352, 0x002A, 0x05CB, 0x03CF, 0x1A8A, - 0x1405, 0x1406, 0x099B, 0x0EC7, 0x0630, 0x002B, - 0x3F79, 0x08C1, 0x0BAB, 0x0507, 0x05F6, 0x0EC8, - 0x099C, 0x0EB0, 0x0A2F, 0x0EB1, 0x2739, 0x09A1, - 0x03D0, 0x1252, 0x7E03, 0x0241, 0x0188, 0x0EB2, - 0x0BAE, 0x05FA, 0x09A2, 0x1254, 0x2398, 0xFAFB, - 0x1253, 0x2399, 0x0ECC, 0xFAFD, 0xFAFC, 0x09A3, - 0x1408, 0x09A0, 0x05F8, 0x3F7B, 0x099F, 0x0D77, - 0x1409, 0x002C, 0x0EC9, 0x0ECB, 0x0A2E, 0x1251, - 0x0ECA, 0x079A, 0x071B, 0x05F9, 0x2738, 0x0632, - 0x002E, 0x0012, 0x7E25, 0xFB1C, 0x0262, 0x001C, - 0x03D6, 0x018E, 0x007C, 0x0342, 0x052E, 0x7E26, - 0xFB1D, 0x01D7, 0x0D7F, 0x126A, 0x2756, 0x09B6, - 0xFB20, 0x3F97, 0xFB21, 0xFB1E, 0xFB1F, 0x23AF, - 0xFB19, 0xFB1A, 0x23AE, 0x7E24, 0x1A95, 0x2755, - 0x2754, 0x05D7, 0x050D, 0x0EE3, 0xFB1B, 0x0EE2, - 0x0BB5, 0x00E3, 0x08CB, 0x05D8, 0x01B9, 0x00E7, - 0x1412, 0x1A96, 0x015A, 0x009A, 0x007B, 0xFB24, - 0x3F99, 0x026D, 0x0026, 0x0EE5, 0x0EE4, 0x0222, - 0x05D9, 0x0D82, 0x7E28, 0x3F9A, 0x0A36, 0xFB25, - 0xFB26, 0x23B1, 0x7E29, 0x126B, 0x7E27, 0x23B0, - 0xFB22, 0x1411, 0x0BB6, 0x3F98, 0x126C, 0x09B7, - 0x02C2, 0x0442, 0x0A33, 0x012B, 0x01C1, 0x0034, - 0xFB23, 0x126D, 0x03DF, 0x0084, 0x0EB7, 0x23B2, - 0x7E2A, 0x052F, 0x018D, 0x0B16, 0x7E2B, 0x01A2, - 0x0736, 0x00F3, 0x060F, 0x003B, 0x003B, 0x081A, - 0x003F, 0x1416, 0x003E, 0x3F9D, 0x126E, 0x7E2E, - 0x7E2C, 0x7E2D, 0x2757, 0x060E, 0xFB28, 0xFB27, - 0x3F9B, 0x050E, 0x0EE6, 0x018F, 0x05DA, 0x0136, - 0x071F, 0xFB29, 0x1413, 0x0137, 0x3F9C, 0x0EE7, - 0x05DB, 0x02DB, 0x05EF, 0x23B5, 0x0EBB, 0x0243, - 0xFB2D, 0x0307, 0xFB2E, 0x275A, 0x0293, 0x041F, - 0x0686, 0x3F9E, 0x0217, 0x0612, 0x05FA, 0x23B6, - 0x7E2F, 0x1A97, 0x275B, 0x0613, 0xFB2F, 0x7E30, - 0xFB2A, 0x23B4, 0x126F, 0x23B3, 0x1270, 0x2758, - 0xFB2B, 0x0610, 0x0BB7, 0x03D7, 0x2759, 0x0916, - 0x050F, 0x0EBA, 0x0BF6, 0xFB2C, 0x0611, 0x00D3, - 0x2C5E, 0x7E36, 0xFB34, 0xFB33, 0x3FA2, 0xFB35, - 0x2FDE, 0x1417, 0x0A37, 0x3FA3, 0x02A2, 0x7E37, - 0xFB36, 0x005E, 0x058A, 0x076F, 0x0886, 0x005F, - 0xFB3B, 0x0686, 0x0342, 0xFB37, 0xFB3A, 0x3F9F, - 0x3FA0, 0xFB31, 0xFB30, 0x23B7, 0x3FA1, 0x23BB, - 0x23BA, 0x1271, 0x0D83, 0x1036, 0x7E32, 0x1272, - 0x7E31, 0x7E33, 0x162E, 0x1273, 0xFB32, 0xFB0C, - 0x1262, 0xFB0D, 0xFB0B, 0x3F8F, 0x0037, 0x1263, - 0x3F90, 0x0EDD, 0x0038, 0x05D3, 0xFB0E, 0x23A7, - 0x0606, 0x1265, 0x3F91, 0x1264, 0x0039, 0xFB0F, - 0x7E14, 0xFB10, 0x274A, 0x274B, 0xFB07, 0xFB08, - 0x23A5, 0xFB06, 0x23A4, 0x0EDC, 0xFB0A, 0xFB09, - 0x7E11, 0x0036, 0x0605, 0x3F8C, 0x7E12, 0x0604, - 0x3F8E, 0x23A6, 0x7E13, 0x3F8D, 0x03DE, 0x7E19, - 0x7E18, 0x0242, 0x0097, 0x08C5, 0xFB13, 0x7E1A, - 0x005A, 0x079B, 0x0607, 0x09B2, 0x033B, 0x05D4, - 0x09B3, 0xFB14, 0x23A8, 0x0637, 0x7E1B, 0x23AA, - 0x23A9, 0x0608, 0x274C, 0xFB12, 0xFB11, 0x7E15, - 0x1266, 0x140F, 0x1267, 0x7E16, 0x274D, 0x079E, - 0x274E, 0x0EDE, 0x066B, 0x09B1, 0x0D7D, 0x3F92, - 0x7E17, 0x079A, 0x002A, 0x00D2, 0x23AC, 0x23AB, - 0x02F2, 0x00B6, 0x0BB2, 0x05D5, 0x0066, 0x03A2, - 0x003A, 0x060B, 0x060A, 0x0317, 0x079F, 0x0362, - 0x2750, 0x050C, 0x3F95, 0x7E1D, 0x7E1E, 0xFB15, - 0x23AD, 0x274F, 0x3F93, 0x3F94, 0x7E1C, 0x0609, - 0x08C6, 0x0EE0, 0x0EDF, 0x035F, 0x0136, 0x076E, - 0x1A93, 0x1268, 0x0A32, 0x024B, 0x08C7, 0x1410, - 0x01EC, 0x0036, 0x0EE1, 0x0363, 0x0072, 0x0030, - 0x003E, 0x2753, 0x7E21, 0x00D7, 0x0117, 0x003A, - 0x0BB4, 0x0126, 0x018D, 0x05D6, 0x7E22, 0xFB16, - 0x0D7E, 0x060D, 0xFB18, 0xFB17, 0x7E23, 0x7E1F, - 0x2752, 0x1269, 0x2751, 0x09B4, 0x08CA, 0x1A94, - 0x3F96, 0x0BB3, 0x0107, 0x09B5, 0x005B, 0x03D6, - 0x00B0, 0x0101, 0x7E20, 0x060C, 0x03D7, 0x0032, - 0x04DE, 0xFA91, 0x7DA8, 0x088E, 0x0374, 0x7DA9, - 0x054E, 0x007A, 0x0223, 0x0152, 0x3F26, 0x7DAA, - 0x0610, 0x1A36, 0x13B3, 0x0E58, 0x1A35, 0x7DAD, - 0x3F27, 0x7DAE, 0x7DAB, 0x7DAC, 0xFA8D, 0x2347, - 0xFA8E, 0xFA8C, 0x7DA6, 0x3F24, 0x2348, 0x7DA7, - 0x0E4F, 0x02C8, 0x0376, 0xFA90, 0xFA8F, 0x0116, - 0x008A, 0x059A, 0x3F25, 0x0044, 0x00AC, 0x1A37, - 0x0153, 0x0066, 0x01DE, 0x049C, 0xFA96, 0x3F28, - 0x0370, 0x00EA, 0x054F, 0x3F29, 0x006B, 0x093C, - 0x0570, 0x11E2, 0x26E0, 0x1A38, 0x26E1, 0x234A, - 0x7DB1, 0x093D, 0x1FD7, 0x2349, 0x7DAF, 0x7DB0, - 0x0310, 0x0775, 0xFA93, 0xFA92, 0x13B4, 0x009A, - 0x0022, 0x093B, 0x020E, 0x002A, 0x003C, 0xFA95, - 0xFA94, 0x033C, 0x00A8, 0x00C9, 0x26E3, 0xFA99, - 0x051D, 0x00FA, 0x0154, 0x093E, 0x00DE, 0x0371, - 0x002E, 0xFA9A, 0x11E3, 0x0377, 0x0776, 0x7DB2, - 0x11E4, 0x11E5, 0x7DB3, 0x3F2B, 0xFA9B, 0x234E, - 0x11E6, 0x26E2, 0x059B, 0xFA98, 0xFA97, 0x234B, - 0x0A0D, 0x059C, 0x234C, 0x0571, 0x006C, 0x075C, - 0x234D, 0x3F2A, 0x06C2, 0x00FE, 0x0311, 0x059D, - 0x010A, 0x031C, 0x059E, 0x11E8, 0x0587, 0x2352, - 0x0312, 0x7DB6, 0xFA9E, 0x04DF, 0x1FD8, 0x11E9, - 0x093F, 0x0A0E, 0x0E5A, 0x11EA, 0x2353, 0x1FD9, - 0x0573, 0x11EB, 0x7DB7, 0xFA9F, 0x0E5B, 0xFA9C, - 0xFA9D, 0x7DB4, 0x234F, 0x0E59, 0x0572, 0x2351, - 0x2350, 0x11E7, 0x049D, 0x3F2D, 0x3F2C, 0x0023, - 0x010D, 0x088F, 0x7DB5, 0x26E4, 0x0611, 0xFAA4, - 0x1A39, 0xFAA5, 0xFAA3, 0x26E7, 0xFAA6, 0x3F2F, - 0x2356, 0x2357, 0x0940, 0x13B8, 0xFAA7, 0x7DBC, - 0x1FDA, 0x2358, 0xFAA8, 0x3F30, 0x26E8, 0xFAA9, - 0xFAAA, 0xFAAB, 0x2359, 0x7DBD, 0x7DB9, 0x2354, - 0x11EC, 0xFAA0, 0x7DB8, 0x13B5, 0x11ED, 0x2355, - 0x7DBA, 0x13B6, 0x13B7, 0x7DBB, 0xFAA1, 0x26E5, - 0x0612, 0x3F2E, 0x26E6, 0xFAA2, 0x7D9E, 0x0590, - 0x7D9F, 0xBF7D, 0x0D0F, 0x13AF, 0x0591, 0x1A1C, - 0x1FD3, 0x17EE, 0x0592, 0x3F1A, 0xBF7E, 0x11DC, - 0x0593, 0x206F, 0x7DA0, 0x3F1C, 0xBF7F, 0x1A1E, - 0x3F1D, 0x1A1D, 0x245C, 0x110E, 0x110F, 0x58BE, - 0x0220, 0x0150, 0x1FD2, 0x7D9C, 0x04DC, 0x05E6, - 0x0D0E, 0x001E, 0xBF7C, 0x58BF, 0x0B80, 0x054C, - 0x13AE, 0x206E, 0x02A3, 0x051C, 0x1A30, 0x245F, - 0x0466, 0x7DA1, 0x030A, 0x3F1F, 0xFA82, 0x088C, - 0x05E7, 0x04DD, 0x13B0, 0x0790, 0x1A31, 0x1FD4, - 0x13B1, 0x7DA2, 0x2638, 0x1A32, 0x2341, 0x2340, - 0x2639, 0x3F1E, 0xFA80, 0x0594, 0x11DE, 0x11DF, - 0x0596, 0x1A1F, 0x0595, 0x02C4, 0x051A, 0x0E4D, - 0x0E4C, 0x040C, 0x245E, 0x0464, 0xFA81, 0x245D, - 0x0222, 0x0074, 0x031A, 0x3F21, 0x263B, 0x06EB, - 0x0254, 0x0774, 0x0020, 0x0078, 0x0410, 0x02EE, - 0x13B2, 0xFA84, 0x06C0, 0x0A0A, 0x0E4E, 0x0597, - 0xFA85, 0xFA87, 0x0598, 0x11E0, 0xFA86, 0x263C, - 0x1FD5, 0x2343, 0xFA83, 0x3F20, 0x2342, 0x030B, - 0x263A, 0x0B81, 0x0586, 0x040E, 0x040F, 0x2345, - 0x2344, 0x02C6, 0x0130, 0x030C, 0x054D, 0x01BE, - 0x0132, 0x0599, 0x3F23, 0x00FA, 0x012E, 0x03CE, - 0xFA8B, 0x263E, 0x02C7, 0x006A, 0x093A, 0x0E6E, - 0x0182, 0x0021, 0x00C8, 0x1A33, 0x7DA5, 0x0E6F, - 0x1FD6, 0x1A34, 0x2346, 0x263F, 0x3F22, 0x7DA4, - 0xFA88, 0x7DA3, 0x030D, 0x0A0C, 0xFA89, 0x11E1, - 0x088D, 0x0256, 0x030F, 0x030E, 0x02F8, 0x0060, - 0x02B8, 0xFA8A, 0x263D, 0x0257, 0x13BE, 0x7DCD, - 0xFAB4, 0x0E83, 0x13BF, 0x015B, 0x26F8, 0x26F7, - 0x0B89, 0x0947, 0x3F39, 0x11F9, 0x13C0, 0x26F9, - 0x05AF, 0x11FC, 0x11FA, 0x11FB, 0x0E84, 0x11FE, - 0xFAB5, 0x11FD, 0x26F5, 0xFAB2, 0x235F, 0x05AC, - 0x26F6, 0x05AD, 0x7DCB, 0x7DCA, 0x2360, 0x0946, - 0x7DCC, 0xFAB3, 0x057A, 0x0318, 0x11F8, 0x05AE, - 0x2361, 0x0B88, 0x26FB, 0x1203, 0x1204, 0x0E85, - 0x0E86, 0x0D4F, 0x0E87, 0x0948, 0x0A10, 0x1FE2, - 0x057C, 0x1A3F, 0x0D50, 0x015D, 0x057D, 0x1205, - 0x1A40, 0x13C2, 0x26FC, 0x26FD, 0x1206, 0x3F3A, - 0x1A41, 0x1FE1, 0x0E8E, 0x26FA, 0xFAB6, 0x11FF, - 0x1201, 0x7DCE, 0x1200, 0x05B0, 0x13C1, 0x089E, - 0x0319, 0x015C, 0x057B, 0x070A, 0x1A3E, 0x1202, - 0x011D, 0x031A, 0x7DCF, 0x1209, 0x0E90, 0x015F, - 0x002B, 0x05B1, 0x0D54, 0x04E5, 0x0160, 0x05B2, - 0x13C4, 0x0E88, 0x1FE5, 0x1FE6, 0x2362, 0x3F3B, - 0x13C5, 0x26FF, 0x0161, 0x057E, 0x0779, 0x0D51, - 0x13C3, 0x1A42, 0x04E4, 0x1208, 0x1A44, 0x1FE3, - 0x1207, 0x1A43, 0x0225, 0x26FE, 0x1FE4, 0x015E, - 0x0D53, 0x002A, 0x0E8F, 0x0D52, 0x0778, 0x2701, - 0x2363, 0x3F3E, 0x1FE8, 0xFAB8, 0x13C9, 0x2365, - 0x2364, 0x031B, 0x120A, 0x0E8B, 0x05B8, 0x0E8A, - 0x13CA, 0x3F3F, 0x2702, 0x1FE9, 0x120B, 0x7DD0, - 0x094A, 0x2366, 0xFAB9, 0x13CB, 0x1A45, 0x13C7, - 0x05B3, 0xFAB7, 0x13C6, 0x3F3D, 0x05B4, 0x3F3C, - 0x1FE7, 0x05B5, 0x13C8, 0x0E89, 0x1A46, 0x1A47, - 0x05B6, 0x05B7, 0x2700, 0x0949, 0x0122, 0x05B9, - 0x2704, 0x031D, 0x0469, 0x094C, 0xFABA, 0x120F, - 0x1A48, 0x0638, 0x1210, 0x13CC, 0x01B3, 0x3F42, - 0x1A49, 0xFABB, 0x3F41, 0x0E8C, 0x1A4A, 0x2367, - 0x3F43, 0x094D, 0x2703, 0x094B, 0x7DD1, 0x3F40, - 0x031C, 0x0226, 0x1FEA, 0x7DD2, 0x120C, 0x03DA, - 0x0B8A, 0x120D, 0x002C, 0x03CC, 0x04E6, 0x7DD3, - 0x120E, 0x089F, 0x04E2, 0x059F, 0xFAAD, 0x0117, - 0x0137, 0x0613, 0x235C, 0x3F31, 0x0899, 0x02EF, - 0x0025, 0x0942, 0x0468, 0x0E8C, 0x0A0F, 0x13BA, - 0x7DBE, 0x13B9, 0x05A0, 0x7DC0, 0x26EB, 0x7DBF, - 0x235A, 0x235B, 0x0372, 0x0313, 0x0941, 0x0898, - 0x26E9, 0x0574, 0x02C9, 0x051E, 0x0024, 0x1FDB, - 0x0467, 0x0791, 0x04E1, 0x26EA, 0xFAAC, 0x04E0, - 0x3F34, 0x0E5D, 0x26ED, 0xFAAE, 0x1FDC, 0x0575, - 0x0314, 0x7DC4, 0x1FDD, 0x1FDE, 0x05A1, 0x0E5E, - 0x26EE, 0x26EF, 0x7DC5, 0x11EE, 0xFAAF, 0x3F35, - 0x11EF, 0x26F0, 0x7DC6, 0xFAB0, 0x05A2, 0x7DC1, - 0x0E5C, 0x7DC2, 0x00CA, 0x01B0, 0x235D, 0x3F32, - 0x075E, 0x0B82, 0x0155, 0x0156, 0x3F33, 0x26EC, - 0x0708, 0x0B83, 0x1A3B, 0x7DC3, 0x1A3A, 0x089B, - 0x11F2, 0x05A5, 0x0E5F, 0x0027, 0x01B2, 0x089C, - 0x26F3, 0x0B85, 0x0157, 0x011C, 0x0944, 0x0577, - 0x7DC8, 0x13BB, 0x089D, 0x05A6, 0x0315, 0x0E8D, - 0xFAB1, 0x1A3C, 0x03AC, 0x0576, 0x7DC7, 0x0B84, - 0x05A3, 0x26F1, 0x26F2, 0x05A4, 0x0224, 0x0943, - 0x0D4C, 0x11F0, 0x1FDF, 0x089A, 0x02F0, 0x0D4D, - 0x0026, 0x11F1, 0x0777, 0x0E82, 0x0029, 0x05A8, - 0x1A3D, 0x0028, 0x00CB, 0x0159, 0x11F6, 0x0709, - 0x0614, 0x04E3, 0x015A, 0x0578, 0x0B87, 0x1FE0, - 0x05AA, 0x7DC9, 0x05A9, 0x05AB, 0x0579, 0x11F7, - 0x3F38, 0x0945, 0x13BC, 0x26F4, 0x235E, 0x3F36, - 0x0158, 0x05A7, 0x3F37, 0x0E80, 0x11F3, 0x13BD, - 0x0B86, 0x0E81, 0x0316, 0x0317, 0x0D4E, 0x11F5, - 0x11F4, 0x075F, 0x06C3, 0x08A6, 0x0B8D, 0x0584, - 0x022A, 0x02CA, 0x13D5, 0x0E93, 0x0217, 0x011F, - 0x0124, 0x0120, 0x0B8E, 0x06C4, 0x0326, 0x0327, - 0x05BC, 0x0B8F, 0xFAC1, 0x0955, 0x1217, 0x7DD9, - 0x0328, 0x0323, 0x0324, 0x2369, 0x7DD8, 0x0031, - 0x1FF3, 0x1216, 0xFAC0, 0x1215, 0x0032, 0x00CD, - 0x03AF, 0x0A12, 0x01BC, 0x0070, 0x0325, 0x0E92, - 0x038E, 0x02D7, 0x2708, 0x13D7, 0x0296, 0x039A, - 0x00FE, 0x070D, 0x01ED, 0x02D8, 0x0398, 0x077E, - 0x0167, 0x0244, 0x0329, 0x01BD, 0x0521, 0x022B, - 0x1A50, 0x0122, 0x08A9, 0x0A13, 0x05DD, 0x070C, - 0x04E9, 0x0033, 0x0121, 0x13D6, 0x0956, 0x08A7, - 0x0585, 0x0166, 0x0204, 0x08A8, 0x0586, 0x04A0, - 0x02CB, 0x003D, 0x0588, 0x0289, 0x03C2, 0x03B8, - 0x077F, 0x0587, 0x04EB, 0x00CF, 0x01A3, 0x13D9, - 0x0617, 0x01A2, 0x06C5, 0x0522, 0x03B9, 0x070E, - 0x0762, 0x08AA, 0x1A51, 0x0169, 0x03BA, 0x1218, - 0x0523, 0x04EC, 0x3F49, 0x0E96, 0x04EA, 0x02CA, - 0x0D59, 0x13D8, 0x03D2, 0x0E95, 0x0957, 0x0E94, - 0x0168, 0x0123, 0x031E, 0x0412, 0x032A, 0x00CE, - 0x039C, 0x0E95, 0x0D5A, 0x0071, 0x13DC, 0x7DDA, - 0x236C, 0x0E96, 0x13DD, 0x032C, 0x1A52, 0x0B90, - 0x0589, 0x032D, 0x2709, 0x1FF6, 0x058A, 0x1219, - 0x05BD, 0x058B, 0x0035, 0x270A, 0x05DE, 0x095A, - 0x1A53, 0x016B, 0x022C, 0x070F, 0x13DA, 0x0958, - 0x3F4A, 0x0588, 0x0D5B, 0x13DB, 0x236A, 0x0780, - 0x3F4B, 0x1FF4, 0x0959, 0x0034, 0x016A, 0x236B, - 0x1FF5, 0x032B, 0x270B, 0x02F3, 0xFAC4, 0x7DDC, - 0x1FF7, 0x0124, 0x095C, 0x016C, 0x0072, 0x016A, - 0x04EE, 0x270D, 0x270C, 0x022D, 0x04A1, 0x270E, - 0x0E97, 0x0618, 0xFAC5, 0x0E98, 0x3F4C, 0x236E, - 0x1A54, 0x05BF, 0x032E, 0x121A, 0xFAC2, 0x05BE, - 0x01EE, 0x04ED, 0x236D, 0x03BB, 0x0125, 0x00EC, - 0x7DDB, 0xFAC3, 0x05DF, 0x00C9, 0x08AB, 0x095B, - 0x013C, 0x01FE, 0x0B8B, 0xFABD, 0x7DD4, 0x0615, - 0x01EA, 0x0E91, 0x057F, 0x016E, 0x0156, 0x08A1, - 0x094E, 0x7DD5, 0x03D1, 0x01B6, 0x1FEC, 0x1FEB, - 0xFABE, 0x7DD6, 0x1212, 0x7DD7, 0xFABF, 0x1A4C, - 0x0E8D, 0x3F44, 0xFABC, 0x002D, 0x006A, 0x01B5, - 0x13CD, 0x08A0, 0x01B4, 0x03D0, 0x006B, 0x1211, - 0x3F45, 0x0227, 0x02FE, 0x077A, 0x1A4B, 0x014A, - 0x0E91, 0x1FED, 0x2705, 0x0162, 0x094F, 0x002E, - 0x04E8, 0x1FEE, 0x0A11, 0x0950, 0x0581, 0x1FEF, - 0x1FF0, 0x2706, 0x3F47, 0x1A4F, 0x0582, 0x05BA, - 0x002F, 0x031E, 0x13CF, 0x0760, 0x0580, 0x0E92, - 0x031D, 0x04E7, 0x1A4D, 0x1A4E, 0x0E8E, 0x01B7, - 0x02F1, 0x02F2, 0x3F46, 0x0E8F, 0x0616, 0x0D55, - 0x006C, 0x0E93, 0x0E90, 0x13CE, 0x049E, 0x0411, - 0x13D0, 0x08A2, 0x03AD, 0x02D3, 0x0228, 0x13D1, - 0x006D, 0x006D, 0x0792, 0x01B8, 0x077C, 0x0229, - 0x0320, 0x1FF1, 0x3F48, 0x0D56, 0x13D2, 0x01B9, - 0x2707, 0x2368, 0x0D57, 0x00CC, 0x0520, 0x1213, - 0x0163, 0x051F, 0x0951, 0x1214, 0x0E94, 0x0164, - 0x00FC, 0x070B, 0x077B, 0x0761, 0x00C6, 0x017A, - 0x031F, 0x0583, 0x01EE, 0x00D4, 0x0165, 0x0952, - 0x02C8, 0x00C8, 0x023A, 0x0030, 0x01EC, 0x00FD, - 0x02F9, 0x01BB, 0x0953, 0x01A0, 0x13D4, 0x08A5, - 0x0030, 0x08A4, 0x077D, 0x006E, 0x0D58, 0x0954, - 0x05DC, 0x0123, 0x0321, 0x01BA, 0x0288, 0x05BB, - 0x13D3, 0x0322, 0x03AE, 0x0B8C, 0x049F, 0x1FF2, - 0x08A3, 0x006E, 0x02D6, 0x006F, 0x011E, 0x0373, - 0x03BF, 0x01EA, 0x08AF, 0x0595, 0x0100, 0x0112, - 0x0050, 0x02B9, 0x014C, 0x01A4, 0x0258, 0x04F2, - 0x0596, 0x00A4, 0x13E1, 0x0124, 0x08B0, 0x04F3, - 0x0171, 0x0413, 0x2713, 0x0E9B, 0x046C, 0x00A2, - 0x0765, 0x05E0, 0x019C, 0x0964, 0x0335, 0x061C, - 0x3F4F, 0x0E9A, 0x009A, 0x0170, 0x0784, 0x003E, - 0x012F, 0x01A3, 0x023D, 0x01F0, 0x016B, 0x00A3, - 0x023F, 0x03C4, 0x03D4, 0x0377, 0x0052, 0x01BE, - 0x0031, 0x0012, 0x0157, 0x021A, 0x0242, 0x039E, - 0x04A2, 0x05E1, 0x02F6, 0x1A5D, 0x0336, 0x0126, - 0x05E2, 0x2374, 0x05C4, 0x046D, 0x0311, 0x01A5, - 0x04F4, 0xFAC8, 0x023E, 0x0A17, 0x0D5F, 0x05C3, - 0x08B1, 0x009C, 0x02CD, 0x0299, 0x036A, 0x0376, - 0x006C, 0x0037, 0x0785, 0x0076, 0x0040, 0x0965, - 0x13E2, 0x02CC, 0x0259, 0x0414, 0x06C6, 0x01A6, - 0x033F, 0x0334, 0x0E9C, 0x0786, 0x0127, 0x0966, - 0x06C7, 0x063B, 0x0039, 0x0172, 0x0374, 0x003A, - 0x0597, 0x0128, 0x00FF, 0x0526, 0x2375, 0x0044, - 0x0337, 0x0B95, 0x0230, 0x7DDE, 0x0D60, 0x0185, - 0x0D61, 0x0038, 0x0321, 0x003F, 0x009D, 0x0101, - 0x03B9, 0x0312, 0x0969, 0x1A5E, 0x1220, 0x2714, - 0x003B, 0x0598, 0x2715, 0x1FFB, 0x08B2, 0x096A, - 0x0EA1, 0x7DDF, 0x1FFC, 0x0A18, 0x1A5F, 0x1222, - 0x1221, 0x0173, 0x0793, 0x061D, 0x096B, 0x7DE0, - 0x0787, 0x0231, 0x0711, 0x0EA0, 0xFAC9, 0x121D, - 0x05C5, 0x121F, 0x121E, 0x3F50, 0x0E9D, 0x0338, - 0x0968, 0x0967, 0x04F5, 0x0B96, 0x05C7, 0x05C6, - 0x03BE, 0x01B8, 0x1225, 0x1224, 0x02CE, 0x0160, - 0x0102, 0xFACD, 0x3F51, 0x0322, 0xFACE, 0x0339, - 0x059A, 0x019E, 0x063C, 0x01BF, 0x7DE2, 0x3F52, - 0x0D62, 0x2718, 0x3F53, 0x2717, 0x0EA2, 0x0599, - 0x13E3, 0xFACA, 0xFACB, 0x06C8, 0x06C9, 0xFACC, - 0x7DE1, 0x0125, 0x01BC, 0x13E4, 0x1223, 0x0336, - 0x02BA, 0x028B, 0x2716, 0x2376, 0x02CD, 0x013D, - 0x095E, 0x05C0, 0x0016, 0x016F, 0x0525, 0x2371, - 0x2370, 0x0205, 0x01C8, 0x058C, 0x0B91, 0x00E6, - 0x0639, 0x0330, 0x2372, 0x3F4D, 0x0763, 0x016E, - 0x121B, 0x1FF9, 0x058D, 0x016D, 0x1A55, 0x270F, - 0x13DE, 0xFAC6, 0x1FF8, 0x236F, 0x1A56, 0x04EF, - 0x0298, 0x0E99, 0x095D, 0x01BE, 0x02CC, 0x0524, - 0x032F, 0x7DDD, 0x0589, 0x095F, 0x03BC, 0x1A59, - 0x0E9A, 0x0E9B, 0x061A, 0x13E0, 0x0E9C, 0x08AD, - 0x0332, 0x0A15, 0x0591, 0x0D5D, 0x0590, 0x0960, - 0x2373, 0x2711, 0x1A5A, 0x058A, 0x006F, 0x3F4E, - 0x2712, 0x0764, 0x08AC, 0x05C1, 0xFAC7, 0x0331, - 0x1FFA, 0x13DF, 0x2710, 0x1A57, 0x0E97, 0x058E, - 0x0619, 0x0A14, 0x1A58, 0x0D5C, 0x0782, 0x058F, - 0x121C, 0x0781, 0x0210, 0x0594, 0x0962, 0x0080, - 0x0399, 0x03C3, 0x02F5, 0x0184, 0x028A, 0x046B, - 0x0963, 0x0B92, 0x0100, 0x1A5B, 0x0A16, 0x0E9D, - 0x03BD, 0x0B93, 0x01A4, 0x0333, 0x0783, 0x033E, - 0x00FE, 0x0592, 0x031F, 0x046A, 0x0593, 0x0961, - 0x04F0, 0x00FF, 0x02F4, 0x0073, 0x0E98, 0x04F1, - 0x033D, 0x0266, 0x02FF, 0x03D3, 0x0320, 0x0206, - 0x004E, 0x023C, 0x01EF, 0x0211, 0x0027, 0x000C, - 0x063A, 0x08AE, 0x008C, 0x03CE, 0x02D9, 0x02FA, - 0x01A2, 0x01A5, 0x061B, 0x0E9E, 0x05C2, 0x022F, - 0x039D, 0x01F0, 0x1A5C, 0x0E9F, 0x02CB, 0x03B8, - 0x014B, 0x0B94, 0x0E99, 0x013E, 0x016F, 0x0036, - 0x0334, 0x0D5E, 0x0310, 0x0207, 0x0044, 0x017B, - 0x00DF, 0x0042, 0x022E, 0x0710, 0x007E, -}; - -static const uint8_t on2avc_cb8_bits[ON2AVC_CB8_CODES] = { - 11, 11, 16, 15, 11, 9, - 13, 12, 9, 11, 11, 14, - 13, 12, 13, 14, 14, 13, - 10, 11, 15, 15, 10, 16, - 16, 15, 16, 11, 13, 13, - 16, 13, 11, 11, 15, 13, - 11, 9, 13, 13, 10, 9, - 16, 13, 9, 10, 10, 15, - 10, 10, 10, 12, 14, 11, - 14, 12, 14, 11, 12, 11, - 12, 14, 10, 10, 11, 16, - 10, 13, 14, 14, 11, 13, - 11, 13, 12, 10, 10, 10, - 15, 10, 10, 12, 12, 12, - 15, 12, 11, 12, 13, 10, - 11, 11, 12, 13, 11, 13, - 12, 15, 13, 11, 11, 12, - 14, 11, 11, 11, 13, 14, - 11, 13, 14, 13, 12, 12, - 12, 11, 14, 12, 10, 13, - 14, 11, 13, 15, 14, 14, - 13, 13, 14, 13, 13, 13, - 15, 14, 12, 14, 14, 14, - 16, 14, 12, 12, 16, 16, - 12, 13, 12, 14, 14, 13, - 13, 16, 14, 13, 14, 13, - 13, 13, 13, 15, 14, 13, - 10, 12, 16, 16, 12, 10, - 13, 14, 11, 11, 12, 14, - 14, 11, 12, 16, 13, 12, - 14, 14, 14, 16, 15, 16, - 15, 16, 15, 14, 12, 14, - 13, 11, 10, 11, 14, 14, - 11, 9, 14, 14, 10, 16, - 12, 15, 16, 12, 11, 14, - 13, 9, 11, 11, 15, 15, - 12, 13, 14, 15, 12, 16, - 14, 15, 15, 13, 14, 14, - 15, 14, 14, 14, 13, 15, - 12, 14, 12, 15, 15, 12, - 11, 13, 15, 10, 14, 13, - 14, 13, 13, 13, 13, 13, - 13, 12, 13, 13, 12, 14, - 14, 16, 12, 14, 11, 13, - 13, 12, 14, 15, 13, 13, - 13, 13, 13, 14, 13, 13, - 13, 14, 13, 13, 12, 14, - 14, 13, 11, 12, 13, 12, - 12, 10, 13, 13, 11, 11, - 12, 14, 11, 12, 13, 15, - 14, 14, 16, 11, 13, 13, - 11, 15, 10, 14, 13, 12, - 12, 13, 12, 13, 11, 11, - 11, 12, 11, 10, 12, 13, - 10, 10, 13, 13, 10, 10, - 10, 10, 15, 11, 11, 13, - 12, 11, 13, 12, 11, 16, - 14, 10, 14, 11, 10, 10, - 15, 12, 11, 13, 12, 11, - 14, 13, 11, 13, 11, 10, - 9, 10, 10, 14, 10, 9, - 14, 13, 9, 9, 10, 10, - 10, 10, 10, 12, 14, 10, - 14, 13, 12, 11, 14, 13, - 11, 13, 9, 11, 13, 13, - 11, 14, 14, 12, 12, 13, - 10, 12, 12, 10, 9, 10, - 10, 10, 10, 9, 10, 10, - 11, 10, 8, 12, 12, 9, - 11, 10, 10, 11, 11, 12, - 12, 14, 12, 10, 14, 13, - 16, 10, 10, 11, 16, 14, - 11, 12, 14, 12, 12, 10, - 11, 10, 10, 11, 9, 11, - 11, 9, 11, 12, 13, 10, - 10, 11, 11, 11, 11, 10, - 13, 13, 10, 13, 11, 11, - 11, 12, 11, 11, 11, 10, - 10, 12, 12, 10, 14, 12, - 11, 12, 12, 11, 12, 12, - 11, 10, 11, 11, 11, 11, - 14, 13, 13, 13, 13, 12, - 13, 13, 12, 12, 12, 13, - 13, 12, 13, 13, 14, 14, - 13, 12, 13, 15, 14, 12, - 13, 16, 14, 12, 14, 14, - 14, 13, 13, 12, 13, 13, - 12, 12, 14, 13, 12, 10, - 13, 14, 14, 10, 11, 14, - 14, 11, 10, 13, 13, 11, - 12, 12, 14, 14, 14, 13, - 13, 14, 13, 13, 14, 13, - 12, 11, 12, 15, 14, 12, - 9, 12, 13, 10, 9, 11, - 13, 14, 11, 10, 13, 15, - 14, 10, 11, 13, 14, 11, - 11, 12, 12, 10, 12, 12, - 15, 15, 12, 14, 14, 14, - 13, 13, 14, 14, 14, 11, - 12, 14, 15, 12, 10, 12, - 13, 9, 9, 11, 14, 15, - 11, 14, 13, 13, 13, 15, - 13, 13, 14, 12, 14, 13, - 13, 13, 12, 13, 14, 14, - 13, 11, 11, 15, 13, 11, - 12, 13, 15, 12, 12, 13, - 14, 14, 14, 13, 13, 13, - 13, 13, 12, 13, 14, 13, - 10, 14, 13, 11, 10, 11, - 11, 11, 11, 11, 12, 12, - 11, 12, 13, 12, 11, 13, - 10, 12, 11, 10, 11, 13, - 12, 10, 12, 12, 12, 11, - 12, 10, 12, 12, 10, 10, - 11, 11, 11, 11, 9, 10, - 11, 10, 10, 9, 12, 12, - 9, 11, 11, 10, 9, 10, - 13, 14, 13, 12, 10, 10, - 14, 14, 10, 11, 11, 13, - 13, 11, 13, 13, 12, 11, - 10, 11, 11, 10, 10, 9, - 12, 12, 9, 11, 12, 13, - 12, 12, 11, 12, 13, 11, - 11, 12, 12, 12, 12, 13, - 15, 14, 14, 13, 12, 16, - 14, 12, 11, 12, 16, 15, - 12, 13, 15, 13, 13, 12, - 12, 12, 12, 11, 10, 13, - 13, 10, 10, 12, 13, 10, - 10, 10, 11, 11, 11, 11, - 12, 12, 11, 13, 12, 12, - 13, 13, 11, 12, 13, 11, - 11, 12, 12, 11, 13, 13, - 13, 13, 13, 10, 14, 11, - 11, 10, 11, 11, 11, 10, - 11, 12, 13, 12, 11, 10, - 12, 12, 10, 11, 10, 11, - 12, 11, 13, 12, 14, 13, - 11, 12, 13, 14, 12, 11, - 11, 14, 14, 12, 12, 13, - 13, 13, 12, 12, 12, 12, - 11, 10, 12, 12, 10, 13, - 14, 13, 12, 12, 13, 13, - 13, 12, 12, 14, 13, 12, - 14, 12, 11, 14, 13, 11, - 11, 13, 12, 11, 13, 14, - 12, 14, 14, 14, 13, 14, - 12, 13, 13, 13, 13, 13, - 13, 12, 13, 10, 12, 14, - 15, 13, 10, 13, 12, 11, - 11, 12, 13, 13, 11, 11, - 12, 13, 12, 16, 11, 13, - 16, 14, 16, 15, 15, 16, - 13, 11, 14, 13, 12, 11, - 11, 15, 13, 11, 9, 13, - 14, 11, 10, 12, 15, 14, - 12, 11, 13, 13, 10, 11, - 11, 14, 14, 11, 12, 13, - 13, 11, 13, 12, 14, 16, - 12, 16, 13, 15, 15, 13, - 12, 13, 14, 14, 10, 11, - 14, 14, 11, 10, 13, 13, - 9, 12, 14, 16, 12, 13, - 13, 12, 13, 13, 12, 14, - 14, 13, 14, 14, 15, 14, - 13, 12, 13, 11, 11, 11, - 13, 13, 13, 14, 13, 13, - 14, 14, 12, 14, 16, 14, - 13, 12, 13, 14, 13, 12, - 12, 12, 12, 12, 11, 12, - 14, 11, 12, 12, 12, 11, - 11, 14, 14, 13, 13, 11, - 12, 14, 12, 11, 14, 11, - 13, 13, 11, 12, 13, 13, - 12, 12, 11, 12, 12, 12, - 11, 12, 13, 11, 10, 13, - 13, 11, 10, 11, 11, 11, - 11, 11, 13, 12, 11, 14, - 13, 12, 13, 12, 11, 14, - 12, 11, 12, 13, 13, 11, - 13, 13, 13, 12, 12, 10, - 12, 12, 10, 10, 10, 11, - 11, 11, 12, 15, 15, 13, - 12, 13, 14, 14, 14, 13, - 16, 14, 13, 15, 14, 14, - 16, 15, 13, 14, 15, 13, - 14, 14, 14, 13, 15, 13, - 14, 13, 14, 13, 16, 14, - 12, 12, 13, 13, 12, 13, - 13, 14, 13, 13, 13, 11, - 14, 14, 12, 14, 13, 13, - 12, 13, 13, 14, 15, 14, - 13, 12, 15, 15, 13, 14, - 12, 14, 14, 13, 14, 15, - 13, 13, 13, 13, 13, 13, - 12, 12, 15, 14, 12, 13, - 15, 14, 12, 12, 12, 12, - 15, 12, 12, 13, 14, 12, - 13, 13, 13, 14, 14, 13, - 13, 14, 13, 14, 14, 14, - 13, 14, 14, 13, 13, 13, - 12, 14, 13, 12, 12, 13, - 14, 12, 12, 16, 15, 15, - 13, 13, 13, 14, 14, 13, - 13, 12, 12, 14, 13, 13, - 12, 14, 14, 14, 12, 12, - 14, 14, 16, 13, 16, 14, - 14, 16, 14, 13, 14, 13, - 14, 14, 14, 13, 13, 16, - 13, 13, 11, 15, 15, 12, - 12, 13, 14, 15, 12, 11, - 13, 13, 11, 13, 11, 14, - 14, 14, 14, 11, 15, 14, - 13, 14, 14, 14, 14, 14, - 15, 15, 13, 11, 14, 13, - 12, 11, 12, 15, 15, 12, - 12, 14, 15, 11, 11, 13, - 14, 15, 12, 13, 13, 13, - 11, 13, 13, 15, 14, 12, - 14, 14, 13, 13, 14, 15, - 16, 16, 13, 13, 14, 16, - 14, 12, 12, 14, 11, 11, - 13, 15, 15, 12, 16, 14, - 14, 14, 15, 13, 14, 14, - 13, 13, 13, 13, 13, 13, - 14, 14, 14, 14, 14, 13, - 15, 14, 12, 14, 15, 16, - 16, 13, 14, 15, 15, 14, - 16, 14, 14, 14, 14, 13, - 14, 16, 13, 13, 14, 14, - 12, 12, 12, 14, 12, 13, - 12, 14, 13, 12, 14, 15, - 15, 13, 13, 12, 13, 13, - 13, 13, 14, 13, 12, 13, - 13, 13, 13, 13, 12, 14, - 14, 12, 12, 12, 14, 13, - 13, 12, 12, 12, 14, 13, - 12, 14, 15, 12, 13, 12, - 12, 14, 13, 14, 15, 16, - 14, 15, 13, 16, 16, 13, - 13, 13, 14, 14, 13, 12, - 13, 14, 13, 13, 12, 14, - 13, 12, 11, 14, 14, 12, - 7, 10, 15, 16, 10, 7, - 12, 13, 7, 11, 11, 15, - 16, 12, 12, 14, 14, 13, - 16, 14, 16, 16, 16, 15, - 16, 16, 15, 15, 13, 14, - 14, 13, 12, 13, 16, 13, - 12, 9, 12, 13, 9, 9, - 13, 13, 9, 8, 10, 16, - 14, 10, 11, 13, 13, 10, - 13, 12, 15, 14, 12, 16, - 16, 15, 15, 14, 15, 15, - 16, 13, 12, 14, 14, 13, - 10, 13, 12, 11, 9, 11, - 16, 14, 11, 9, 12, 15, - 15, 11, 9, 13, 15, 9, - 11, 11, 14, 14, 12, 12, - 14, 13, 14, 14, 14, 15, - 15, 15, 14, 14, 16, 16, - 14, 12, 13, 13, 13, 11, - 11, 16, 13, 12, 14, 13, - 13, 10, 11, 15, 12, 12, - 16, 12, 16, 14, 11, 11, - 13, 14, 11, 14, 11, 15, - 15, 13, 14, 14, 16, 15, - 16, 15, 14, 15, 14, 14, - 16, 14, 12, 12, 14, 12, - 12, 12, 12, 16, 14, 12, - 15, 15, 16, 16, 14, 16, - 14, 13, 12, 14, 14, 15, - 16, 13, 12, 11, 14, 13, - 16, 12, 12, 16, 16, 14, - 14, 16, 16, 15, 14, 15, - 15, 14, 12, 13, 15, 14, - 15, 15, 14, 14, 16, 16, - 14, 16, 16, 14, 14, 14, - 14, 13, 14, 13, 16, 15, - 14, 14, 14, 14, 14, 16, - 15, 16, 14, 14, 16, 16, - 15, 16, 15, 13, 16, 16, - 15, 14, 14, 14, 15, 14, - 14, 15, 15, 14, 11, 15, - 15, 12, 10, 12, 16, 15, - 13, 11, 14, 13, 11, 13, - 13, 16, 15, 12, 15, 15, - 15, 14, 14, 16, 16, 15, - 14, 13, 14, 15, 14, 12, - 14, 13, 11, 13, 12, 14, - 15, 11, 9, 12, 15, 15, - 11, 9, 12, 13, 9, 10, - 12, 14, 14, 10, 12, 13, - 14, 12, 14, 15, 15, 16, - 15, 14, 14, 14, 15, 14, - 12, 13, 13, 13, 12, 11, - 13, 14, 12, 10, 12, 13, - 9, 7, 13, 13, 7, 6, - 9, 14, 15, 9, 10, 14, - 12, 9, 13, 13, 15, 16, - 12, 14, 16, 16, 15, 15, - 14, 14, 14, 13, 12, 13, - 14, 12, 11, 13, 13, 10, - 9, 10, 15, 14, 10, 6, - 12, 16, 15, 12, 10, 15, - 13, 10, 12, 13, 14, 15, - 12, 13, 13, 13, 13, 15, - 14, 15, 15, 15, 16, 15, - 16, 16, 15, 14, 15, 15, - 13, 11, 12, 16, 16, 12, - 9, 14, 14, 8, 9, 13, - 13, 8, 9, 11, 16, 14, - 11, 11, 13, 14, 11, 13, - 13, 14, 14, 13, 14, 15, - 15, 13, 13, 15, 15, 15, - 13, 12, 16, 16, 13, 10, - 13, 13, 10, 6, 11, 16, - 16, 10, 9, 12, 14, 16, - 11, 10, 13, 13, 10, 11, - 12, 16, 14, 12, 12, 15, - 14, 14, 15, 14, 16, 15, - 14, 14, 14, 16, 16, 15, - 12, 14, 15, 13, 11, 11, - 15, 14, 11, 9, 13, 14, - 9, 11, 14, 14, 11, 15, - 13, 15, 16, 12, 13, 14, - 13, 12, 13, 14, 15, 13, - 13, 14, 15, 16, 13, 16, - 16, 15, 15, 13, 13, 15, - 15, 14, 11, 14, 14, 13, - 10, 12, 15, 14, 12, 16, - 13, 16, 16, 14, 16, 14, - 15, 15, 13, 13, 16, 15, - 13, 15, 16, 14, 14, 16, - 16, 16, 15, 15, 15, 15, - 14, 16, 15, 13, 14, 15, - 15, 13, 13, 15, 16, 14, - 12, 14, 14, 16, 15, 14, - 15, 16, 13, 13, 14, 15, - 13, 13, 14, 14, 16, 14, - 14, 14, 15, 14, 16, 15, - 14, 15, 14, 15, 15, 16, - 12, 13, 13, 15, 12, 12, - 13, 13, 16, 16, 12, 13, - 13, 14, 14, 11, 13, 14, - 11, 15, 13, 14, 16, 12, - 12, 12, 13, 11, 13, 13, - 13, 15, 14, 13, 15, 15, - 14, 14, 16, 14, 14, 14, - 14, 15, 14, 11, 11, 13, - 13, 11, 14, 11, 16, 14, - 12, 9, 11, 14, 14, 11, - 10, 12, 13, 10, 11, 12, - 13, 16, 11, 12, 13, 14, - 16, 16, 14, 14, 16, 14, - 13, 15, 16, 14, 15, 13, - 14, 12, 11, 11, 11, 15, - 15, 11, 9, 13, 13, 9, - 9, 14, 14, 9, 9, 11, - 16, 14, 11, 11, 13, 12, - 11, 13, 12, 13, 15, 12, - 13, 13, 15, 14, 14, 15, - 16, 15, 13, 12, 16, 14, - 12, 10, 13, 13, 10, 8, - 10, 16, 14, 10, 13, 15, - 16, 13, 13, 13, 14, 14, - 12, 13, 14, 14, 13, 14, - 14, 14, 14, 14, 13, 14, - 16, 14, 14, 16, 15, 14, - 14, 14, 15, 15, 15, 13, - 15, 16, 13, 13, 14, 14, - 15, 12, 14, 14, 14, 13, - 13, 12, 13, 13, 12, 13, - 13, 13, 12, 13, 13, 14, - 13, 13, 14, 14, 14, 14, - 13, 13, 12, 14, 16, 14, - 14, 15, 14, 14, 13, 12, - 13, 13, 13, 11, 13, 14, - 12, 13, 15, 14, 12, 13, - 13, 14, 12, 12, 13, 14, - 13, 13, 13, 13, 15, 14, - 13, 14, 13, 13, 12, 12, - 13, 13, 12, 14, 13, 13, - 14, 13, 12, 14, 13, 13, - 12, 13, 12, 12, 12, 14, - 15, 14, 13, 16, 13, 15, - 15, 13, 14, 13, 14, 13, - 13, 14, 14, 13, 14, 15, - 13, 15, 16, 13, 13, 13, - 14, 16, 13, 14, 14, 14, - 13, 14, 13, 13, 13, 13, - 14, 14, 14, 13, 11, 14, - 14, 13, 11, 13, 16, 14, - 13, 11, 14, 13, 12, 14, - 13, 16, 14, 13, 13, 15, - 14, 13, 14, 13, 15, 14, - 13, 12, 13, 15, 14, 10, - 12, 14, 13, 10, 12, 15, - 14, 12, 12, 14, 16, 12, - 11, 12, 15, 14, 12, 12, - 13, 13, 11, 12, 12, 13, - 15, 13, 14, 15, 14, 15, - 15, 15, 11, 13, 13, 12, - 14, 13, 11, 11, 13, 13, - 11, 11, 12, 14, 16, 12, - 14, 13, 14, 16, 13, 13, - 13, 15, 13, 13, 14, 13, - 14, 14, 15, 14, 16, 14, - 14, 14, 15, 16, 14, 15, - 13, 15, 12, 12, 15, 14, - 11, 12, 13, 13, 14, 14, - 11, 12, 13, 15, 13, 12, - 14, 14, 13, 13, 12, 12, - 14, 12, 13, 12, 13, 13, - 15, 13, 12, 14, 13, 12, - 16, 13, 12, 13, 15, 12, - 14, 14, 14, 14, 12, 13, - 12, 14, 13, 12, 12, 12, - 13, 14, 12, 13, 13, 14, - 13, 13, 12, 13, 14, 11, - 12, 12, 13, 13, 12, 13, - 14, 15, 14, 14, 13, 14, - 14, 13, 13, 14, 15, 14, - 13, 14, 14, 13, 14, 13, - 12, 13, 13, 13, 12, 14, - 14, 11, 11, 12, 12, 13, - 12, 10, 13, 13, 10, 12, - 11, 12, 12, 11, 13, 13, - 14, 12, 16, 13, 14, 15, - 13, 13, 13, 15, 15, 13, - 13, 14, 16, 14, 13, 12, - 12, 12, 12, 11, 13, 13, - 10, 10, 14, 13, 10, 10, - 11, 11, 11, 10, 10, 12, - 13, 10, 13, 12, 11, 12, - 13, 12, 12, 12, 11, 11, - 12, 13, 12, 13, 13, 12, - 13, 13, 11, 12, 13, 11, - 10, 11, 11, 11, 10, 12, - 12, 13, 12, 12, 11, 13, - 12, 11, 11, 11, 12, 11, - 11, 12, 13, 13, 12, 14, - 11, 12, 14, 12, 12, 11, - 12, 13, 11, 12, 13, 13, - 13, 12, 11, 11, 13, 12, - 10, 13, 12, 11, 13, 15, - 15, 13, 13, 13, 13, 12, - 13, 13, 14, 13, 13, 14, - 14, 13, 13, 14, 11, 13, - 13, 13, 12, 11, 13, 13, - 14, 13, 12, 13, 15, 12, - 14, 13, 13, 13, 13, 15, - 13, 13, 14, 12, 16, 15, - 13, 9, 13, 13, 11, 10, - 12, 14, 14, 12, 11, 14, - 13, 12, 16, 13, 14, 15, - 13, 14, 13, 14, 16, 14, - 11, 12, 15, 12, 11, 11, - 15, 16, 11, 10, 12, 13, - 11, 10, 12, 16, 15, 12, - 11, 12, 13, 9, 10, 12, - 13, 15, 11, 12, 13, 13, - 16, 15, 14, 15, 16, 13, - 13, 14, 16, 13, 12, 12, - 13, 12, 12, 11, 12, 14, - 14, 12, 10, 12, 13, 10, - 13, 13, 14, 13, 13, 13, - 12, 13, 12, 13, 13, 13, - 13, 14, 14, 13, 13, 14, - 13, 13, 13, 11, 13, 12, - 11, 12, 13, 13, 13, 12, - 12, 12, 14, 13, 12, 12, - 12, 12, 13, 13, 11, 11, - 13, 12, 12, 10, 12, 13, - 11, 12, 11, 12, 12, 12, - 13, 13, 14, 12, 13, 12, - 14, 15, 12, 12, 11, 14, - 13, 11, 13, 14, 12, 13, - 11, 11, 12, 11, 10, 10, - 13, 13, 10, 10, 13, 13, - 10, 10, 10, 12, 11, 11, - 10, 12, 13, 11, 13, 12, - 13, 12, 12, 12, 12, 13, - 11, 11, 13, 12, 11, 14, - 13, 13, 12, 12, 11, 13, - 12, 11, 10, 11, 12, 11, - 10, 9, 12, 13, 9, 9, - 10, 10, 10, 10, 10, 12, - 13, 11, 13, 12, 12, 12, - 13, 11, 14, 12, 11, 10, - 11, 11, 10, 13, 13, 12, - 14, 12, 11, 13, 12, 11, - 9, 10, 10, 10, 10, 10, - 10, 10, 11, 10, 9, 12, - 12, 9, 10, 10, 10, 10, - 11, 11, 12, 13, 13, 11, - 11, 15, 14, 11, 10, 10, - 12, 16, 10, 12, 12, 14, - 12, 11, 10, 10, 10, 10, - 9, 13, 12, 9, 11, 13, - 13, 11, 10, 11, 11, 11, - 10, 10, 12, 12, 11, 13, - 11, 11, 13, 13, 11, 13, - 13, 11, 10, 11, 15, 10, - 13, 12, 12, 15, 12, 11, - 12, 13, 11, 11, 11, 11, - 10, 10, 13, 13, 14, 14, - 13, 13, 14, 13, 12, 13, - 13, 15, 13, 12, 13, 14, - 14, 13, 11, 12, 13, 15, - 12, 12, 11, 13, 16, 14, - 14, 14, 14, 14, 12, 13, - 13, 13, 12, 12, 14, 14, - 12, 9, 14, 14, 10, 9, - 11, 16, 14, 11, 16, 13, - 13, 10, 11, 12, 15, 14, - 12, 14, 14, 14, 13, 13, - 13, 16, 16, 11, 11, 16, - 15, 12, 9, 13, 14, 10, - 10, 11, 14, 15, 11, 11, - 13, 14, 10, 9, 11, 15, - 15, 11, 10, 13, 12, 9, - 11, 13, 15, 14, 11, 13, - 14, 13, 13, 13, 13, 14, - 13, 16, 13, 15, 13, 12, - 10, 13, 13, 10, 10, 11, - 13, 15, 11, 13, 12, 13, - 13, 13, 12, 13, 13, 12, - 13, 12, 13, 12, 13, 13, - 15, 14, 13, 11, 12, 14, - 14, 11, 12, 14, 16, 13, - 13, 13, 14, 13, 12, 13, - 12, 12, 13, 12, 12, 13, - 14, 12, 10, 13, 13, 11, - 10, 10, 12, 11, 11, 11, - 13, 12, 11, 13, 12, 13, - 12, 12, 11, 13, 12, 10, - 10, 13, 11, 11, 13, 13, - 12, 11, 12, 11, 12, 12, - 10, 10, 10, 11, 11, 11, - 9, 10, 11, 10, 11, 9, - 11, 12, 9, 10, 10, 10, - 10, 11, 12, 13, 14, 12, - 10, 11, 13, 13, 11, 10, - 10, 12, 12, 11, 13, 13, - 13, 12, 10, 11, 11, 10, - 10, 9, 12, 11, 8, -}; - -static const uint16_t on2avc_cb8_syms[ON2AVC_CB8_CODES] = { - 0x0000, 0x0002, 0x0004, 0x000C, 0x000E, 0x0011, - 0x0013, 0x001D, 0x001F, 0x0020, 0x0022, 0x0024, - 0x002C, 0x002E, 0x0031, 0x0033, 0x003D, 0x003F, - 0x0040, 0x0042, 0x0044, 0x004C, 0x004E, 0x00C0, - 0x00C2, 0x00C4, 0x00CC, 0x00CE, 0x00D1, 0x00D3, - 0x00DD, 0x00DF, 0x00E0, 0x00E2, 0x00E4, 0x00EC, - 0x00EE, 0x00F1, 0x00F3, 0x00FD, 0x00FF, 0x0101, - 0x0103, 0x010D, 0x010F, 0x0110, 0x0112, 0x0114, - 0x011C, 0x011E, 0x0121, 0x0123, 0x012D, 0x012F, - 0x0130, 0x0132, 0x0134, 0x013C, 0x013E, 0x0141, - 0x0143, 0x014D, 0x014F, 0x01C1, 0x01C3, 0x01CD, - 0x01CF, 0x01D0, 0x01D2, 0x01D4, 0x01DC, 0x01DE, - 0x01E1, 0x01E3, 0x01ED, 0x01EF, 0x01F0, 0x01F2, - 0x01F4, 0x01FC, 0x01FE, 0x0200, 0x0202, 0x0204, - 0x020C, 0x020E, 0x0211, 0x0213, 0x021D, 0x021F, - 0x0220, 0x0222, 0x0224, 0x022C, 0x022E, 0x0231, - 0x0233, 0x023D, 0x023F, 0x0240, 0x0242, 0x0244, - 0x024C, 0x024E, 0x02C0, 0x02C2, 0x02C4, 0x02CC, - 0x02CE, 0x02D1, 0x02D3, 0x02DD, 0x02DF, 0x02E0, - 0x02E2, 0x02E4, 0x02EC, 0x02EE, 0x02F1, 0x02F3, - 0x02FD, 0x02FF, 0x0301, 0x0303, 0x030D, 0x030F, - 0x0310, 0x0312, 0x0314, 0x031C, 0x031E, 0x0321, - 0x0323, 0x032D, 0x032F, 0x0330, 0x0332, 0x0334, - 0x033C, 0x033E, 0x0341, 0x0343, 0x034D, 0x034F, - 0x03C1, 0x03C3, 0x03CD, 0x03CF, 0x03D0, 0x03D2, - 0x03D4, 0x03DC, 0x03DE, 0x03E1, 0x03E3, 0x03ED, - 0x03EF, 0x03F0, 0x03F2, 0x03F4, 0x03FC, 0x03FE, - 0x0400, 0x0402, 0x0404, 0x040C, 0x040E, 0x0411, - 0x0413, 0x041D, 0x041F, 0x0420, 0x0422, 0x0424, - 0x042C, 0x042E, 0x0431, 0x0433, 0x043D, 0x043F, - 0x0440, 0x0442, 0x0444, 0x044C, 0x044E, 0x04C0, - 0x04C2, 0x04C4, 0x04CC, 0x04CE, 0x04D1, 0x04D3, - 0x04DD, 0x04DF, 0x04E0, 0x04E2, 0x04E4, 0x04EC, - 0x04EE, 0x04F1, 0x04F3, 0x04FD, 0x04FF, 0x0C00, - 0x0C02, 0x0C04, 0x0C0C, 0x0C0E, 0x0C11, 0x0C13, - 0x0C1D, 0x0C1F, 0x0C20, 0x0C22, 0x0C24, 0x0C2C, - 0x0C2E, 0x0C31, 0x0C33, 0x0C3D, 0x0C3F, 0x0C40, - 0x0C42, 0x0C44, 0x0C4C, 0x0C4E, 0x0CC0, 0x0CC2, - 0x0CC4, 0x0CCC, 0x0CCE, 0x0CD1, 0x0CD3, 0x0CDD, - 0x0CDF, 0x0CE0, 0x0CE2, 0x0CE4, 0x0CEC, 0x0CEE, - 0x0CF1, 0x0CF3, 0x0CFD, 0x0CFF, 0x0D01, 0x0D03, - 0x0D0D, 0x0D0F, 0x0D10, 0x0D12, 0x0D14, 0x0D1C, - 0x0D1E, 0x0D21, 0x0D23, 0x0D2D, 0x0D2F, 0x0D30, - 0x0D32, 0x0D34, 0x0D3C, 0x0D3E, 0x0D41, 0x0D43, - 0x0D4D, 0x0D4F, 0x0DC1, 0x0DC3, 0x0DCD, 0x0DCF, - 0x0DD0, 0x0DD2, 0x0DD4, 0x0DDC, 0x0DDE, 0x0DE1, - 0x0DE3, 0x0DED, 0x0DEF, 0x0DF0, 0x0DF2, 0x0DF4, - 0x0DFC, 0x0DFE, 0x0E00, 0x0E02, 0x0E04, 0x0E0C, - 0x0E0E, 0x0E11, 0x0E13, 0x0E1D, 0x0E1F, 0x0E20, - 0x0E22, 0x0E24, 0x0E2C, 0x0E2E, 0x0E31, 0x0E33, - 0x0E3D, 0x0E3F, 0x0E40, 0x0E42, 0x0E44, 0x0E4C, - 0x0E4E, 0x0EC0, 0x0EC2, 0x0EC4, 0x0ECC, 0x0ECE, - 0x0ED1, 0x0ED3, 0x0EDD, 0x0EDF, 0x0EE0, 0x0EE2, - 0x0EE4, 0x0EEC, 0x0EEE, 0x0EF1, 0x0EF3, 0x0EFD, - 0x0EFF, 0x0F01, 0x0F03, 0x0F0D, 0x0F0F, 0x0F10, - 0x0F12, 0x0F14, 0x0F1C, 0x0F1E, 0x0F21, 0x0F23, - 0x0F2D, 0x0F2F, 0x0F30, 0x0F32, 0x0F34, 0x0F3C, - 0x0F3E, 0x0F41, 0x0F43, 0x0F4D, 0x0F4F, 0x0FC1, - 0x0FC3, 0x0FCD, 0x0FCF, 0x0FD0, 0x0FD2, 0x0FD4, - 0x0FDC, 0x0FDE, 0x0FE1, 0x0FE3, 0x0FED, 0x0FEF, - 0x0FF0, 0x0FF2, 0x0FF4, 0x0FFC, 0x0FFE, 0x1001, - 0x1003, 0x100D, 0x100F, 0x1010, 0x1012, 0x1014, - 0x101C, 0x101E, 0x1021, 0x1023, 0x102D, 0x102F, - 0x1030, 0x1032, 0x1034, 0x103C, 0x103E, 0x1041, - 0x1043, 0x104D, 0x104F, 0x10C1, 0x10C3, 0x10CD, - 0x10CF, 0x10D0, 0x10D2, 0x10D4, 0x10DC, 0x10DE, - 0x10E1, 0x10E3, 0x10ED, 0x10EF, 0x10F0, 0x10F2, - 0x10F4, 0x10FC, 0x10FE, 0x1100, 0x1102, 0x1104, - 0x110C, 0x110E, 0x1111, 0x1113, 0x111D, 0x111F, - 0x1120, 0x1122, 0x1124, 0x112C, 0x112E, 0x1131, - 0x1133, 0x113D, 0x113F, 0x1140, 0x1142, 0x1144, - 0x114C, 0x114E, 0x11C0, 0x11C2, 0x11C4, 0x11CC, - 0x11CE, 0x11D1, 0x11D3, 0x11DD, 0x11DF, 0x11E0, - 0x11E2, 0x11E4, 0x11EC, 0x11EE, 0x11F1, 0x11F3, - 0x11FD, 0x11FF, 0x1201, 0x1203, 0x120D, 0x120F, - 0x1210, 0x1212, 0x1214, 0x121C, 0x121E, 0x1221, - 0x1223, 0x122D, 0x122F, 0x1230, 0x1232, 0x1234, - 0x123C, 0x123E, 0x1241, 0x1243, 0x124D, 0x124F, - 0x12C1, 0x12C3, 0x12CD, 0x12CF, 0x12D0, 0x12D2, - 0x12D4, 0x12DC, 0x12DE, 0x12E1, 0x12E3, 0x12ED, - 0x12EF, 0x12F0, 0x12F2, 0x12F4, 0x12FC, 0x12FE, - 0x1300, 0x1302, 0x1304, 0x130C, 0x130E, 0x1311, - 0x1313, 0x131D, 0x131F, 0x1320, 0x1322, 0x1324, - 0x132C, 0x132E, 0x1331, 0x1333, 0x133D, 0x133F, - 0x1340, 0x1342, 0x1344, 0x134C, 0x134E, 0x13C0, - 0x13C2, 0x13C4, 0x13CC, 0x13CE, 0x13D1, 0x13D3, - 0x13DD, 0x13DF, 0x13E0, 0x13E2, 0x13E4, 0x13EC, - 0x13EE, 0x13F1, 0x13F3, 0x13FD, 0x13FF, 0x1401, - 0x1403, 0x140D, 0x140F, 0x1410, 0x1412, 0x1414, - 0x141C, 0x141E, 0x1421, 0x1423, 0x142D, 0x142F, - 0x1430, 0x1432, 0x1434, 0x143C, 0x143E, 0x1441, - 0x1443, 0x144D, 0x144F, 0x14C1, 0x14C3, 0x14CD, - 0x14CF, 0x14D0, 0x14D2, 0x14D4, 0x14DC, 0x14DE, - 0x14E1, 0x14E3, 0x14ED, 0x14EF, 0x14F0, 0x14F2, - 0x14F4, 0x14FC, 0x14FE, 0x1C01, 0x1C03, 0x1C0D, - 0x1C0F, 0x1C10, 0x1C12, 0x1C14, 0x1C1C, 0x1C1E, - 0x1C21, 0x1C23, 0x1C2D, 0x1C2F, 0x1C30, 0x1C32, - 0x1C34, 0x1C3C, 0x1C3E, 0x1C41, 0x1C43, 0x1C4D, - 0x1C4F, 0x1CC1, 0x1CC3, 0x1CCD, 0x1CCF, 0x1CD0, - 0x1CD2, 0x1CD4, 0x1CDC, 0x1CDE, 0x1CE1, 0x1CE3, - 0x1CED, 0x1CEF, 0x1CF0, 0x1CF2, 0x1CF4, 0x1CFC, - 0x1CFE, 0x1D00, 0x1D02, 0x1D04, 0x1D0C, 0x1D0E, - 0x1D11, 0x1D13, 0x1D1D, 0x1D1F, 0x1D20, 0x1D22, - 0x1D24, 0x1D2C, 0x1D2E, 0x1D31, 0x1D33, 0x1D3D, - 0x1D3F, 0x1D40, 0x1D42, 0x1D44, 0x1D4C, 0x1D4E, - 0x1DC0, 0x1DC2, 0x1DC4, 0x1DCC, 0x1DCE, 0x1DD1, - 0x1DD3, 0x1DDD, 0x1DDF, 0x1DE0, 0x1DE2, 0x1DE4, - 0x1DEC, 0x1DEE, 0x1DF1, 0x1DF3, 0x1DFD, 0x1DFF, - 0x1E01, 0x1E03, 0x1E0D, 0x1E0F, 0x1E10, 0x1E12, - 0x1E14, 0x1E1C, 0x1E1E, 0x1E21, 0x1E23, 0x1E2D, - 0x1E2F, 0x1E30, 0x1E32, 0x1E34, 0x1E3C, 0x1E3E, - 0x1E41, 0x1E43, 0x1E4D, 0x1E4F, 0x1EC1, 0x1EC3, - 0x1ECD, 0x1ECF, 0x1ED0, 0x1ED2, 0x1ED4, 0x1EDC, - 0x1EDE, 0x1EE1, 0x1EE3, 0x1EED, 0x1EEF, 0x1EF0, - 0x1EF2, 0x1EF4, 0x1EFC, 0x1EFE, 0x1F00, 0x1F02, - 0x1F04, 0x1F0C, 0x1F0E, 0x1F11, 0x1F13, 0x1F1D, - 0x1F1F, 0x1F20, 0x1F22, 0x1F24, 0x1F2C, 0x1F2E, - 0x1F31, 0x1F33, 0x1F3D, 0x1F3F, 0x1F40, 0x1F42, - 0x1F44, 0x1F4C, 0x1F4E, 0x1FC0, 0x1FC2, 0x1FC4, - 0x1FCC, 0x1FCE, 0x1FD1, 0x1FD3, 0x1FDD, 0x1FDF, - 0x1FE0, 0x1FE2, 0x1FE4, 0x1FEC, 0x1FEE, 0x1FF1, - 0x1FF3, 0x1FFD, 0x1FFF, 0x2000, 0x2002, 0x2004, - 0x200C, 0x200E, 0x2011, 0x2013, 0x201D, 0x201F, - 0x2020, 0x2022, 0x2024, 0x202C, 0x202E, 0x2031, - 0x2033, 0x203D, 0x203F, 0x2040, 0x2042, 0x2044, - 0x204C, 0x204E, 0x20C0, 0x20C2, 0x20C4, 0x20CC, - 0x20CE, 0x20D1, 0x20D3, 0x20DD, 0x20DF, 0x20E0, - 0x20E2, 0x20E4, 0x20EC, 0x20EE, 0x20F1, 0x20F3, - 0x20FD, 0x20FF, 0x2101, 0x2103, 0x210D, 0x210F, - 0x2110, 0x2112, 0x2114, 0x211C, 0x211E, 0x2121, - 0x2123, 0x212D, 0x212F, 0x2130, 0x2132, 0x2134, - 0x213C, 0x213E, 0x2141, 0x2143, 0x214D, 0x214F, - 0x21C1, 0x21C3, 0x21CD, 0x21CF, 0x21D0, 0x21D2, - 0x21D4, 0x21DC, 0x21DE, 0x21E1, 0x21E3, 0x21ED, - 0x21EF, 0x21F0, 0x21F2, 0x21F4, 0x21FC, 0x21FE, - 0x2200, 0x2202, 0x2204, 0x220C, 0x220E, 0x2211, - 0x2213, 0x221D, 0x221F, 0x2220, 0x2222, 0x2224, - 0x222C, 0x222E, 0x2231, 0x2233, 0x223D, 0x223F, - 0x2240, 0x2242, 0x2244, 0x224C, 0x224E, 0x22C0, - 0x22C2, 0x22C4, 0x22CC, 0x22CE, 0x22D1, 0x22D3, - 0x22DD, 0x22DF, 0x22E0, 0x22E2, 0x22E4, 0x22EC, - 0x22EE, 0x22F1, 0x22F3, 0x22FD, 0x22FF, 0x2301, - 0x2303, 0x230D, 0x230F, 0x2310, 0x2312, 0x2314, - 0x231C, 0x231E, 0x2321, 0x2323, 0x232D, 0x232F, - 0x2330, 0x2332, 0x2334, 0x233C, 0x233E, 0x2341, - 0x2343, 0x234D, 0x234F, 0x23C1, 0x23C3, 0x23CD, - 0x23CF, 0x23D0, 0x23D2, 0x23D4, 0x23DC, 0x23DE, - 0x23E1, 0x23E3, 0x23ED, 0x23EF, 0x23F0, 0x23F2, - 0x23F4, 0x23FC, 0x23FE, 0x2400, 0x2402, 0x2404, - 0x240C, 0x240E, 0x2411, 0x2413, 0x241D, 0x241F, - 0x2420, 0x2422, 0x2424, 0x242C, 0x242E, 0x2431, - 0x2433, 0x243D, 0x243F, 0x2440, 0x2442, 0x2444, - 0x244C, 0x244E, 0x24C0, 0x24C2, 0x24C4, 0x24CC, - 0x24CE, 0x24D1, 0x24D3, 0x24DD, 0x24DF, 0x24E0, - 0x24E2, 0x24E4, 0x24EC, 0x24EE, 0x24F1, 0x24F3, - 0x24FD, 0x24FF, 0x2C00, 0x2C02, 0x2C04, 0x2C0C, - 0x2C0E, 0x2C11, 0x2C13, 0x2C1D, 0x2C1F, 0x2C20, - 0x2C22, 0x2C24, 0x2C2C, 0x2C2E, 0x2C31, 0x2C33, - 0x2C3D, 0x2C3F, 0x2C40, 0x2C42, 0x2C44, 0x2C4C, - 0x2C4E, 0x2CC0, 0x2CC2, 0x2CC4, 0x2CCC, 0x2CCE, - 0x2CD1, 0x2CD3, 0x2CDD, 0x2CDF, 0x2CE0, 0x2CE2, - 0x2CE4, 0x2CEC, 0x2CEE, 0x2CF1, 0x2CF3, 0x2CFD, - 0x2CFF, 0x2D01, 0x2D03, 0x2D0D, 0x2D0F, 0x2D10, - 0x2D12, 0x2D14, 0x2D1C, 0x2D1E, 0x2D21, 0x2D23, - 0x2D2D, 0x2D2F, 0x2D30, 0x2D32, 0x2D34, 0x2D3C, - 0x2D3E, 0x2D41, 0x2D43, 0x2D4D, 0x2D4F, 0x2DC1, - 0x2DC3, 0x2DCD, 0x2DCF, 0x2DD0, 0x2DD2, 0x2DD4, - 0x2DDC, 0x2DDE, 0x2DE1, 0x2DE3, 0x2DED, 0x2DEF, - 0x2DF0, 0x2DF2, 0x2DF4, 0x2DFC, 0x2DFE, 0x2E00, - 0x2E02, 0x2E04, 0x2E0C, 0x2E0E, 0x2E11, 0x2E13, - 0x2E1D, 0x2E1F, 0x2E20, 0x2E22, 0x2E24, 0x2E2C, - 0x2E2E, 0x2E31, 0x2E33, 0x2E3D, 0x2E3F, 0x2E40, - 0x2E42, 0x2E44, 0x2E4C, 0x2E4E, 0x2EC0, 0x2EC2, - 0x2EC4, 0x2ECC, 0x2ECE, 0x2ED1, 0x2ED3, 0x2EDD, - 0x2EDF, 0x2EE0, 0x2EE2, 0x2EE4, 0x2EEC, 0x2EEE, - 0x2EF1, 0x2EF3, 0x2EFD, 0x2EFF, 0x2F01, 0x2F03, - 0x2F0D, 0x2F0F, 0x2F10, 0x2F12, 0x2F14, 0x2F1C, - 0x2F1E, 0x2F21, 0x2F23, 0x2F2D, 0x2F2F, 0x2F30, - 0x2F32, 0x2F34, 0x2F3C, 0x2F3E, 0x2F41, 0x2F43, - 0x2F4D, 0x2F4F, 0x2FC1, 0x2FC3, 0x2FCD, 0x2FCF, - 0x2FD0, 0x2FD2, 0x2FD4, 0x2FDC, 0x2FDE, 0x2FE1, - 0x2FE3, 0x2FED, 0x2FEF, 0x2FF0, 0x2FF2, 0x2FF4, - 0x2FFC, 0x2FFE, 0x3001, 0x3003, 0x300D, 0x300F, - 0x3010, 0x3012, 0x3014, 0x301C, 0x301E, 0x3021, - 0x3023, 0x302D, 0x302F, 0x3030, 0x3032, 0x3034, - 0x303C, 0x303E, 0x3041, 0x3043, 0x304D, 0x304F, - 0x30C1, 0x30C3, 0x30CD, 0x30CF, 0x30D0, 0x30D2, - 0x30D4, 0x30DC, 0x30DE, 0x30E1, 0x30E3, 0x30ED, - 0x30EF, 0x30F0, 0x30F2, 0x30F4, 0x30FC, 0x30FE, - 0x3100, 0x3102, 0x3104, 0x310C, 0x310E, 0x3111, - 0x3113, 0x311D, 0x311F, 0x3120, 0x3122, 0x3124, - 0x312C, 0x312E, 0x3131, 0x3133, 0x313D, 0x313F, - 0x3140, 0x3142, 0x3144, 0x314C, 0x314E, 0x31C0, - 0x31C2, 0x31C4, 0x31CC, 0x31CE, 0x31D1, 0x31D3, - 0x31DD, 0x31DF, 0x31E0, 0x31E2, 0x31E4, 0x31EC, - 0x31EE, 0x31F1, 0x31F3, 0x31FD, 0x31FF, 0x3201, - 0x3203, 0x320D, 0x320F, 0x3210, 0x3212, 0x3214, - 0x321C, 0x321E, 0x3221, 0x3223, 0x322D, 0x322F, - 0x3230, 0x3232, 0x3234, 0x323C, 0x323E, 0x3241, - 0x3243, 0x324D, 0x324F, 0x32C1, 0x32C3, 0x32CD, - 0x32CF, 0x32D0, 0x32D2, 0x32D4, 0x32DC, 0x32DE, - 0x32E1, 0x32E3, 0x32ED, 0x32EF, 0x32F0, 0x32F2, - 0x32F4, 0x32FC, 0x32FE, 0x3300, 0x3302, 0x3304, - 0x330C, 0x330E, 0x3311, 0x3313, 0x331D, 0x331F, - 0x3320, 0x3322, 0x3324, 0x332C, 0x332E, 0x3331, - 0x3333, 0x333D, 0x333F, 0x3340, 0x3342, 0x3344, - 0x334C, 0x334E, 0x33C0, 0x33C2, 0x33C4, 0x33CC, - 0x33CE, 0x33D1, 0x33D3, 0x33DD, 0x33DF, 0x33E0, - 0x33E2, 0x33E4, 0x33EC, 0x33EE, 0x33F1, 0x33F3, - 0x33FD, 0x33FF, 0x3401, 0x3403, 0x340D, 0x340F, - 0x3410, 0x3412, 0x3414, 0x341C, 0x341E, 0x3421, - 0x3423, 0x342D, 0x342F, 0x3430, 0x3432, 0x3434, - 0x343C, 0x343E, 0x3441, 0x3443, 0x344D, 0x344F, - 0x34C1, 0x34C3, 0x34CD, 0x34CF, 0x34D0, 0x34D2, - 0x34D4, 0x34DC, 0x34DE, 0x34E1, 0x34E3, 0x34ED, - 0x34EF, 0x34F0, 0x34F2, 0x34F4, 0x34FC, 0x34FE, - 0x3C01, 0x3C03, 0x3C0D, 0x3C0F, 0x3C10, 0x3C12, - 0x3C14, 0x3C1C, 0x3C1E, 0x3C21, 0x3C23, 0x3C2D, - 0x3C2F, 0x3C30, 0x3C32, 0x3C34, 0x3C3C, 0x3C3E, - 0x3C41, 0x3C43, 0x3C4D, 0x3C4F, 0x3CC1, 0x3CC3, - 0x3CCD, 0x3CCF, 0x3CD0, 0x3CD2, 0x3CD4, 0x3CDC, - 0x3CDE, 0x3CE1, 0x3CE3, 0x3CED, 0x3CEF, 0x3CF0, - 0x3CF2, 0x3CF4, 0x3CFC, 0x3CFE, 0x3D00, 0x3D02, - 0x3D04, 0x3D0C, 0x3D0E, 0x3D11, 0x3D13, 0x3D1D, - 0x3D1F, 0x3D20, 0x3D22, 0x3D24, 0x3D2C, 0x3D2E, - 0x3D31, 0x3D33, 0x3D3D, 0x3D3F, 0x3D40, 0x3D42, - 0x3D44, 0x3D4C, 0x3D4E, 0x3DC0, 0x3DC2, 0x3DC4, - 0x3DCC, 0x3DCE, 0x3DD1, 0x3DD3, 0x3DDD, 0x3DDF, - 0x3DE0, 0x3DE2, 0x3DE4, 0x3DEC, 0x3DEE, 0x3DF1, - 0x3DF3, 0x3DFD, 0x3DFF, 0x3E01, 0x3E03, 0x3E0D, - 0x3E0F, 0x3E10, 0x3E12, 0x3E14, 0x3E1C, 0x3E1E, - 0x3E21, 0x3E23, 0x3E2D, 0x3E2F, 0x3E30, 0x3E32, - 0x3E34, 0x3E3C, 0x3E3E, 0x3E41, 0x3E43, 0x3E4D, - 0x3E4F, 0x3EC1, 0x3EC3, 0x3ECD, 0x3ECF, 0x3ED0, - 0x3ED2, 0x3ED4, 0x3EDC, 0x3EDE, 0x3EE1, 0x3EE3, - 0x3EED, 0x3EEF, 0x3EF0, 0x3EF2, 0x3EF4, 0x3EFC, - 0x3EFE, 0x3F00, 0x3F02, 0x3F04, 0x3F0C, 0x3F0E, - 0x3F11, 0x3F13, 0x3F1D, 0x3F1F, 0x3F20, 0x3F22, - 0x3F24, 0x3F2C, 0x3F2E, 0x3F31, 0x3F33, 0x3F3D, - 0x3F3F, 0x3F40, 0x3F42, 0x3F44, 0x3F4C, 0x3F4E, - 0x3FC0, 0x3FC2, 0x3FC4, 0x3FCC, 0x3FCE, 0x3FD1, - 0x3FD3, 0x3FDD, 0x3FDF, 0x3FE0, 0x3FE2, 0x3FE4, - 0x3FEC, 0x3FEE, 0x3FF1, 0x3FF3, 0x3FFD, 0x3FFF, - 0x4000, 0x4002, 0x4004, 0x400C, 0x400E, 0x4011, - 0x4013, 0x401D, 0x401F, 0x4020, 0x4022, 0x4024, - 0x402C, 0x402E, 0x4031, 0x4033, 0x403D, 0x403F, - 0x4040, 0x4042, 0x4044, 0x404C, 0x404E, 0x40C0, - 0x40C2, 0x40C4, 0x40CC, 0x40CE, 0x40D1, 0x40D3, - 0x40DD, 0x40DF, 0x40E0, 0x40E2, 0x40E4, 0x40EC, - 0x40EE, 0x40F1, 0x40F3, 0x40FD, 0x40FF, 0x4101, - 0x4103, 0x410D, 0x410F, 0x4110, 0x4112, 0x4114, - 0x411C, 0x411E, 0x4121, 0x4123, 0x412D, 0x412F, - 0x4130, 0x4132, 0x4134, 0x413C, 0x413E, 0x4141, - 0x4143, 0x414D, 0x414F, 0x41C1, 0x41C3, 0x41CD, - 0x41CF, 0x41D0, 0x41D2, 0x41D4, 0x41DC, 0x41DE, - 0x41E1, 0x41E3, 0x41ED, 0x41EF, 0x41F0, 0x41F2, - 0x41F4, 0x41FC, 0x41FE, 0x4200, 0x4202, 0x4204, - 0x420C, 0x420E, 0x4211, 0x4213, 0x421D, 0x421F, - 0x4220, 0x4222, 0x4224, 0x422C, 0x422E, 0x4231, - 0x4233, 0x423D, 0x423F, 0x4240, 0x4242, 0x4244, - 0x424C, 0x424E, 0x42C0, 0x42C2, 0x42C4, 0x42CC, - 0x42CE, 0x42D1, 0x42D3, 0x42DD, 0x42DF, 0x42E0, - 0x42E2, 0x42E4, 0x42EC, 0x42EE, 0x42F1, 0x42F3, - 0x42FD, 0x42FF, 0x4301, 0x4303, 0x430D, 0x430F, - 0x4310, 0x4312, 0x4314, 0x431C, 0x431E, 0x4321, - 0x4323, 0x432D, 0x432F, 0x4330, 0x4332, 0x4334, - 0x433C, 0x433E, 0x4341, 0x4343, 0x434D, 0x434F, - 0x43C1, 0x43C3, 0x43CD, 0x43CF, 0x43D0, 0x43D2, - 0x43D4, 0x43DC, 0x43DE, 0x43E1, 0x43E3, 0x43ED, - 0x43EF, 0x43F0, 0x43F2, 0x43F4, 0x43FC, 0x43FE, - 0x4400, 0x4402, 0x4404, 0x440C, 0x440E, 0x4411, - 0x4413, 0x441D, 0x441F, 0x4420, 0x4422, 0x4424, - 0x442C, 0x442E, 0x4431, 0x4433, 0x443D, 0x443F, - 0x4440, 0x4442, 0x4444, 0x444C, 0x444E, 0x44C0, - 0x44C2, 0x44C4, 0x44CC, 0x44CE, 0x44D1, 0x44D3, - 0x44DD, 0x44DF, 0x44E0, 0x44E2, 0x44E4, 0x44EC, - 0x44EE, 0x44F1, 0x44F3, 0x44FD, 0x44FF, 0x4C00, - 0x4C02, 0x4C04, 0x4C0C, 0x4C0E, 0x4C11, 0x4C13, - 0x4C1D, 0x4C1F, 0x4C20, 0x4C22, 0x4C24, 0x4C2C, - 0x4C2E, 0x4C31, 0x4C33, 0x4C3D, 0x4C3F, 0x4C40, - 0x4C42, 0x4C44, 0x4C4C, 0x4C4E, 0x4CC0, 0x4CC2, - 0x4CC4, 0x4CCC, 0x4CCE, 0x4CD1, 0x4CD3, 0x4CDD, - 0x4CDF, 0x4CE0, 0x4CE2, 0x4CE4, 0x4CEC, 0x4CEE, - 0x4CF1, 0x4CF3, 0x4CFD, 0x4CFF, 0x4D01, 0x4D03, - 0x4D0D, 0x4D0F, 0x4D10, 0x4D12, 0x4D14, 0x4D1C, - 0x4D1E, 0x4D21, 0x4D23, 0x4D2D, 0x4D2F, 0x4D30, - 0x4D32, 0x4D34, 0x4D3C, 0x4D3E, 0x4D41, 0x4D43, - 0x4D4D, 0x4D4F, 0x4DC1, 0x4DC3, 0x4DCD, 0x4DCF, - 0x4DD0, 0x4DD2, 0x4DD4, 0x4DDC, 0x4DDE, 0x4DE1, - 0x4DE3, 0x4DED, 0x4DEF, 0x4DF0, 0x4DF2, 0x4DF4, - 0x4DFC, 0x4DFE, 0x4E00, 0x4E02, 0x4E04, 0x4E0C, - 0x4E0E, 0x4E11, 0x4E13, 0x4E1D, 0x4E1F, 0x4E20, - 0x4E22, 0x4E24, 0x4E2C, 0x4E2E, 0x4E31, 0x4E33, - 0x4E3D, 0x4E3F, 0x4E40, 0x4E42, 0x4E44, 0x4E4C, - 0x4E4E, 0x4EC0, 0x4EC2, 0x4EC4, 0x4ECC, 0x4ECE, - 0x4ED1, 0x4ED3, 0x4EDD, 0x4EDF, 0x4EE0, 0x4EE2, - 0x4EE4, 0x4EEC, 0x4EEE, 0x4EF1, 0x4EF3, 0x4EFD, - 0x4EFF, 0x4F01, 0x4F03, 0x4F0D, 0x4F0F, 0x4F10, - 0x4F12, 0x4F14, 0x4F1C, 0x4F1E, 0x4F21, 0x4F23, - 0x4F2D, 0x4F2F, 0x4F30, 0x4F32, 0x4F34, 0x4F3C, - 0x4F3E, 0x4F41, 0x4F43, 0x4F4D, 0x4F4F, 0x4FC1, - 0x4FC3, 0x4FCD, 0x4FCF, 0x4FD0, 0x4FD2, 0x4FD4, - 0x4FDC, 0x4FDE, 0x4FE1, 0x4FE3, 0x4FED, 0x4FEF, - 0x4FF0, 0x4FF2, 0x4FF4, 0x4FFC, 0x4FFE, 0xC000, - 0xC002, 0xC004, 0xC00C, 0xC00E, 0xC011, 0xC013, - 0xC01D, 0xC01F, 0xC020, 0xC022, 0xC024, 0xC02C, - 0xC02E, 0xC031, 0xC033, 0xC03D, 0xC03F, 0xC040, - 0xC042, 0xC044, 0xC04C, 0xC04E, 0xC0C0, 0xC0C2, - 0xC0C4, 0xC0CC, 0xC0CE, 0xC0D1, 0xC0D3, 0xC0DD, - 0xC0DF, 0xC0E0, 0xC0E2, 0xC0E4, 0xC0EC, 0xC0EE, - 0xC0F1, 0xC0F3, 0xC0FD, 0xC0FF, 0xC101, 0xC103, - 0xC10D, 0xC10F, 0xC110, 0xC112, 0xC114, 0xC11C, - 0xC11E, 0xC121, 0xC123, 0xC12D, 0xC12F, 0xC130, - 0xC132, 0xC134, 0xC13C, 0xC13E, 0xC141, 0xC143, - 0xC14D, 0xC14F, 0xC1C1, 0xC1C3, 0xC1CD, 0xC1CF, - 0xC1D0, 0xC1D2, 0xC1D4, 0xC1DC, 0xC1DE, 0xC1E1, - 0xC1E3, 0xC1ED, 0xC1EF, 0xC1F0, 0xC1F2, 0xC1F4, - 0xC1FC, 0xC1FE, 0xC200, 0xC202, 0xC204, 0xC20C, - 0xC20E, 0xC211, 0xC213, 0xC21D, 0xC21F, 0xC220, - 0xC222, 0xC224, 0xC22C, 0xC22E, 0xC231, 0xC233, - 0xC23D, 0xC23F, 0xC240, 0xC242, 0xC244, 0xC24C, - 0xC24E, 0xC2C0, 0xC2C2, 0xC2C4, 0xC2CC, 0xC2CE, - 0xC2D1, 0xC2D3, 0xC2DD, 0xC2DF, 0xC2E0, 0xC2E2, - 0xC2E4, 0xC2EC, 0xC2EE, 0xC2F1, 0xC2F3, 0xC2FD, - 0xC2FF, 0xC301, 0xC303, 0xC30D, 0xC30F, 0xC310, - 0xC312, 0xC314, 0xC31C, 0xC31E, 0xC321, 0xC323, - 0xC32D, 0xC32F, 0xC330, 0xC332, 0xC334, 0xC33C, - 0xC33E, 0xC341, 0xC343, 0xC34D, 0xC34F, 0xC3C1, - 0xC3C3, 0xC3CD, 0xC3CF, 0xC3D0, 0xC3D2, 0xC3D4, - 0xC3DC, 0xC3DE, 0xC3E1, 0xC3E3, 0xC3ED, 0xC3EF, - 0xC3F0, 0xC3F2, 0xC3F4, 0xC3FC, 0xC3FE, 0xC400, - 0xC402, 0xC404, 0xC40C, 0xC40E, 0xC411, 0xC413, - 0xC41D, 0xC41F, 0xC420, 0xC422, 0xC424, 0xC42C, - 0xC42E, 0xC431, 0xC433, 0xC43D, 0xC43F, 0xC440, - 0xC442, 0xC444, 0xC44C, 0xC44E, 0xC4C0, 0xC4C2, - 0xC4C4, 0xC4CC, 0xC4CE, 0xC4D1, 0xC4D3, 0xC4DD, - 0xC4DF, 0xC4E0, 0xC4E2, 0xC4E4, 0xC4EC, 0xC4EE, - 0xC4F1, 0xC4F3, 0xC4FD, 0xC4FF, 0xCC00, 0xCC02, - 0xCC04, 0xCC0C, 0xCC0E, 0xCC11, 0xCC13, 0xCC1D, - 0xCC1F, 0xCC20, 0xCC22, 0xCC24, 0xCC2C, 0xCC2E, - 0xCC31, 0xCC33, 0xCC3D, 0xCC3F, 0xCC40, 0xCC42, - 0xCC44, 0xCC4C, 0xCC4E, 0xCCC0, 0xCCC2, 0xCCC4, - 0xCCCC, 0xCCCE, 0xCCD1, 0xCCD3, 0xCCDD, 0xCCDF, - 0xCCE0, 0xCCE2, 0xCCE4, 0xCCEC, 0xCCEE, 0xCCF1, - 0xCCF3, 0xCCFD, 0xCCFF, 0xCD01, 0xCD03, 0xCD0D, - 0xCD0F, 0xCD10, 0xCD12, 0xCD14, 0xCD1C, 0xCD1E, - 0xCD21, 0xCD23, 0xCD2D, 0xCD2F, 0xCD30, 0xCD32, - 0xCD34, 0xCD3C, 0xCD3E, 0xCD41, 0xCD43, 0xCD4D, - 0xCD4F, 0xCDC1, 0xCDC3, 0xCDCD, 0xCDCF, 0xCDD0, - 0xCDD2, 0xCDD4, 0xCDDC, 0xCDDE, 0xCDE1, 0xCDE3, - 0xCDED, 0xCDEF, 0xCDF0, 0xCDF2, 0xCDF4, 0xCDFC, - 0xCDFE, 0xCE00, 0xCE02, 0xCE04, 0xCE0C, 0xCE0E, - 0xCE11, 0xCE13, 0xCE1D, 0xCE1F, 0xCE20, 0xCE22, - 0xCE24, 0xCE2C, 0xCE2E, 0xCE31, 0xCE33, 0xCE3D, - 0xCE3F, 0xCE40, 0xCE42, 0xCE44, 0xCE4C, 0xCE4E, - 0xCEC0, 0xCEC2, 0xCEC4, 0xCECC, 0xCECE, 0xCED1, - 0xCED3, 0xCEDD, 0xCEDF, 0xCEE0, 0xCEE2, 0xCEE4, - 0xCEEC, 0xCEEE, 0xCEF1, 0xCEF3, 0xCEFD, 0xCEFF, - 0xCF01, 0xCF03, 0xCF0D, 0xCF0F, 0xCF10, 0xCF12, - 0xCF14, 0xCF1C, 0xCF1E, 0xCF21, 0xCF23, 0xCF2D, - 0xCF2F, 0xCF30, 0xCF32, 0xCF34, 0xCF3C, 0xCF3E, - 0xCF41, 0xCF43, 0xCF4D, 0xCF4F, 0xCFC1, 0xCFC3, - 0xCFCD, 0xCFCF, 0xCFD0, 0xCFD2, 0xCFD4, 0xCFDC, - 0xCFDE, 0xCFE1, 0xCFE3, 0xCFED, 0xCFEF, 0xCFF0, - 0xCFF2, 0xCFF4, 0xCFFC, 0xCFFE, 0xD001, 0xD003, - 0xD00D, 0xD00F, 0xD010, 0xD012, 0xD014, 0xD01C, - 0xD01E, 0xD021, 0xD023, 0xD02D, 0xD02F, 0xD030, - 0xD032, 0xD034, 0xD03C, 0xD03E, 0xD041, 0xD043, - 0xD04D, 0xD04F, 0xD0C1, 0xD0C3, 0xD0CD, 0xD0CF, - 0xD0D0, 0xD0D2, 0xD0D4, 0xD0DC, 0xD0DE, 0xD0E1, - 0xD0E3, 0xD0ED, 0xD0EF, 0xD0F0, 0xD0F2, 0xD0F4, - 0xD0FC, 0xD0FE, 0xD100, 0xD102, 0xD104, 0xD10C, - 0xD10E, 0xD111, 0xD113, 0xD11D, 0xD11F, 0xD120, - 0xD122, 0xD124, 0xD12C, 0xD12E, 0xD131, 0xD133, - 0xD13D, 0xD13F, 0xD140, 0xD142, 0xD144, 0xD14C, - 0xD14E, 0xD1C0, 0xD1C2, 0xD1C4, 0xD1CC, 0xD1CE, - 0xD1D1, 0xD1D3, 0xD1DD, 0xD1DF, 0xD1E0, 0xD1E2, - 0xD1E4, 0xD1EC, 0xD1EE, 0xD1F1, 0xD1F3, 0xD1FD, - 0xD1FF, 0xD201, 0xD203, 0xD20D, 0xD20F, 0xD210, - 0xD212, 0xD214, 0xD21C, 0xD21E, 0xD221, 0xD223, - 0xD22D, 0xD22F, 0xD230, 0xD232, 0xD234, 0xD23C, - 0xD23E, 0xD241, 0xD243, 0xD24D, 0xD24F, 0xD2C1, - 0xD2C3, 0xD2CD, 0xD2CF, 0xD2D0, 0xD2D2, 0xD2D4, - 0xD2DC, 0xD2DE, 0xD2E1, 0xD2E3, 0xD2ED, 0xD2EF, - 0xD2F0, 0xD2F2, 0xD2F4, 0xD2FC, 0xD2FE, 0xD300, - 0xD302, 0xD304, 0xD30C, 0xD30E, 0xD311, 0xD313, - 0xD31D, 0xD31F, 0xD320, 0xD322, 0xD324, 0xD32C, - 0xD32E, 0xD331, 0xD333, 0xD33D, 0xD33F, 0xD340, - 0xD342, 0xD344, 0xD34C, 0xD34E, 0xD3C0, 0xD3C2, - 0xD3C4, 0xD3CC, 0xD3CE, 0xD3D1, 0xD3D3, 0xD3DD, - 0xD3DF, 0xD3E0, 0xD3E2, 0xD3E4, 0xD3EC, 0xD3EE, - 0xD3F1, 0xD3F3, 0xD3FD, 0xD3FF, 0xD401, 0xD403, - 0xD40D, 0xD40F, 0xD410, 0xD412, 0xD414, 0xD41C, - 0xD41E, 0xD421, 0xD423, 0xD42D, 0xD42F, 0xD430, - 0xD432, 0xD434, 0xD43C, 0xD43E, 0xD441, 0xD443, - 0xD44D, 0xD44F, 0xD4C1, 0xD4C3, 0xD4CD, 0xD4CF, - 0xD4D0, 0xD4D2, 0xD4D4, 0xD4DC, 0xD4DE, 0xD4E1, - 0xD4E3, 0xD4ED, 0xD4EF, 0xD4F0, 0xD4F2, 0xD4F4, - 0xD4FC, 0xD4FE, 0xDC01, 0xDC03, 0xDC0D, 0xDC0F, - 0xDC10, 0xDC12, 0xDC14, 0xDC1C, 0xDC1E, 0xDC21, - 0xDC23, 0xDC2D, 0xDC2F, 0xDC30, 0xDC32, 0xDC34, - 0xDC3C, 0xDC3E, 0xDC41, 0xDC43, 0xDC4D, 0xDC4F, - 0xDCC1, 0xDCC3, 0xDCCD, 0xDCCF, 0xDCD0, 0xDCD2, - 0xDCD4, 0xDCDC, 0xDCDE, 0xDCE1, 0xDCE3, 0xDCED, - 0xDCEF, 0xDCF0, 0xDCF2, 0xDCF4, 0xDCFC, 0xDCFE, - 0xDD00, 0xDD02, 0xDD04, 0xDD0C, 0xDD0E, 0xDD11, - 0xDD13, 0xDD1D, 0xDD1F, 0xDD20, 0xDD22, 0xDD24, - 0xDD2C, 0xDD2E, 0xDD31, 0xDD33, 0xDD3D, 0xDD3F, - 0xDD40, 0xDD42, 0xDD44, 0xDD4C, 0xDD4E, 0xDDC0, - 0xDDC2, 0xDDC4, 0xDDCC, 0xDDCE, 0xDDD1, 0xDDD3, - 0xDDDD, 0xDDDF, 0xDDE0, 0xDDE2, 0xDDE4, 0xDDEC, - 0xDDEE, 0xDDF1, 0xDDF3, 0xDDFD, 0xDDFF, 0xDE01, - 0xDE03, 0xDE0D, 0xDE0F, 0xDE10, 0xDE12, 0xDE14, - 0xDE1C, 0xDE1E, 0xDE21, 0xDE23, 0xDE2D, 0xDE2F, - 0xDE30, 0xDE32, 0xDE34, 0xDE3C, 0xDE3E, 0xDE41, - 0xDE43, 0xDE4D, 0xDE4F, 0xDEC1, 0xDEC3, 0xDECD, - 0xDECF, 0xDED0, 0xDED2, 0xDED4, 0xDEDC, 0xDEDE, - 0xDEE1, 0xDEE3, 0xDEED, 0xDEEF, 0xDEF0, 0xDEF2, - 0xDEF4, 0xDEFC, 0xDEFE, 0xDF00, 0xDF02, 0xDF04, - 0xDF0C, 0xDF0E, 0xDF11, 0xDF13, 0xDF1D, 0xDF1F, - 0xDF20, 0xDF22, 0xDF24, 0xDF2C, 0xDF2E, 0xDF31, - 0xDF33, 0xDF3D, 0xDF3F, 0xDF40, 0xDF42, 0xDF44, - 0xDF4C, 0xDF4E, 0xDFC0, 0xDFC2, 0xDFC4, 0xDFCC, - 0xDFCE, 0xDFD1, 0xDFD3, 0xDFDD, 0xDFDF, 0xDFE0, - 0xDFE2, 0xDFE4, 0xDFEC, 0xDFEE, 0xDFF1, 0xDFF3, - 0xDFFD, 0xDFFF, 0xE000, 0xE002, 0xE004, 0xE00C, - 0xE00E, 0xE011, 0xE013, 0xE01D, 0xE01F, 0xE020, - 0xE022, 0xE024, 0xE02C, 0xE02E, 0xE031, 0xE033, - 0xE03D, 0xE03F, 0xE040, 0xE042, 0xE044, 0xE04C, - 0xE04E, 0xE0C0, 0xE0C2, 0xE0C4, 0xE0CC, 0xE0CE, - 0xE0D1, 0xE0D3, 0xE0DD, 0xE0DF, 0xE0E0, 0xE0E2, - 0xE0E4, 0xE0EC, 0xE0EE, 0xE0F1, 0xE0F3, 0xE0FD, - 0xE0FF, 0xE101, 0xE103, 0xE10D, 0xE10F, 0xE110, - 0xE112, 0xE114, 0xE11C, 0xE11E, 0xE121, 0xE123, - 0xE12D, 0xE12F, 0xE130, 0xE132, 0xE134, 0xE13C, - 0xE13E, 0xE141, 0xE143, 0xE14D, 0xE14F, 0xE1C1, - 0xE1C3, 0xE1CD, 0xE1CF, 0xE1D0, 0xE1D2, 0xE1D4, - 0xE1DC, 0xE1DE, 0xE1E1, 0xE1E3, 0xE1ED, 0xE1EF, - 0xE1F0, 0xE1F2, 0xE1F4, 0xE1FC, 0xE1FE, 0xE200, - 0xE202, 0xE204, 0xE20C, 0xE20E, 0xE211, 0xE213, - 0xE21D, 0xE21F, 0xE220, 0xE222, 0xE224, 0xE22C, - 0xE22E, 0xE231, 0xE233, 0xE23D, 0xE23F, 0xE240, - 0xE242, 0xE244, 0xE24C, 0xE24E, 0xE2C0, 0xE2C2, - 0xE2C4, 0xE2CC, 0xE2CE, 0xE2D1, 0xE2D3, 0xE2DD, - 0xE2DF, 0xE2E0, 0xE2E2, 0xE2E4, 0xE2EC, 0xE2EE, - 0xE2F1, 0xE2F3, 0xE2FD, 0xE2FF, 0xE301, 0xE303, - 0xE30D, 0xE30F, 0xE310, 0xE312, 0xE314, 0xE31C, - 0xE31E, 0xE321, 0xE323, 0xE32D, 0xE32F, 0xE330, - 0xE332, 0xE334, 0xE33C, 0xE33E, 0xE341, 0xE343, - 0xE34D, 0xE34F, 0xE3C1, 0xE3C3, 0xE3CD, 0xE3CF, - 0xE3D0, 0xE3D2, 0xE3D4, 0xE3DC, 0xE3DE, 0xE3E1, - 0xE3E3, 0xE3ED, 0xE3EF, 0xE3F0, 0xE3F2, 0xE3F4, - 0xE3FC, 0xE3FE, 0xE400, 0xE402, 0xE404, 0xE40C, - 0xE40E, 0xE411, 0xE413, 0xE41D, 0xE41F, 0xE420, - 0xE422, 0xE424, 0xE42C, 0xE42E, 0xE431, 0xE433, - 0xE43D, 0xE43F, 0xE440, 0xE442, 0xE444, 0xE44C, - 0xE44E, 0xE4C0, 0xE4C2, 0xE4C4, 0xE4CC, 0xE4CE, - 0xE4D1, 0xE4D3, 0xE4DD, 0xE4DF, 0xE4E0, 0xE4E2, - 0xE4E4, 0xE4EC, 0xE4EE, 0xE4F1, 0xE4F3, 0xE4FD, - 0xE4FF, 0xEC00, 0xEC02, 0xEC04, 0xEC0C, 0xEC0E, - 0xEC11, 0xEC13, 0xEC1D, 0xEC1F, 0xEC20, 0xEC22, - 0xEC24, 0xEC2C, 0xEC2E, 0xEC31, 0xEC33, 0xEC3D, - 0xEC3F, 0xEC40, 0xEC42, 0xEC44, 0xEC4C, 0xEC4E, - 0xECC0, 0xECC2, 0xECC4, 0xECCC, 0xECCE, 0xECD1, - 0xECD3, 0xECDD, 0xECDF, 0xECE0, 0xECE2, 0xECE4, - 0xECEC, 0xECEE, 0xECF1, 0xECF3, 0xECFD, 0xECFF, - 0xED01, 0xED03, 0xED0D, 0xED0F, 0xED10, 0xED12, - 0xED14, 0xED1C, 0xED1E, 0xED21, 0xED23, 0xED2D, - 0xED2F, 0xED30, 0xED32, 0xED34, 0xED3C, 0xED3E, - 0xED41, 0xED43, 0xED4D, 0xED4F, 0xEDC1, 0xEDC3, - 0xEDCD, 0xEDCF, 0xEDD0, 0xEDD2, 0xEDD4, 0xEDDC, - 0xEDDE, 0xEDE1, 0xEDE3, 0xEDED, 0xEDEF, 0xEDF0, - 0xEDF2, 0xEDF4, 0xEDFC, 0xEDFE, 0xEE00, 0xEE02, - 0xEE04, 0xEE0C, 0xEE0E, 0xEE11, 0xEE13, 0xEE1D, - 0xEE1F, 0xEE20, 0xEE22, 0xEE24, 0xEE2C, 0xEE2E, - 0xEE31, 0xEE33, 0xEE3D, 0xEE3F, 0xEE40, 0xEE42, - 0xEE44, 0xEE4C, 0xEE4E, 0xEEC0, 0xEEC2, 0xEEC4, - 0xEECC, 0xEECE, 0xEED1, 0xEED3, 0xEEDD, 0xEEDF, - 0xEEE0, 0xEEE2, 0xEEE4, 0xEEEC, 0xEEEE, 0xEEF1, - 0xEEF3, 0xEEFD, 0xEEFF, 0xEF01, 0xEF03, 0xEF0D, - 0xEF0F, 0xEF10, 0xEF12, 0xEF14, 0xEF1C, 0xEF1E, - 0xEF21, 0xEF23, 0xEF2D, 0xEF2F, 0xEF30, 0xEF32, - 0xEF34, 0xEF3C, 0xEF3E, 0xEF41, 0xEF43, 0xEF4D, - 0xEF4F, 0xEFC1, 0xEFC3, 0xEFCD, 0xEFCF, 0xEFD0, - 0xEFD2, 0xEFD4, 0xEFDC, 0xEFDE, 0xEFE1, 0xEFE3, - 0xEFED, 0xEFEF, 0xEFF0, 0xEFF2, 0xEFF4, 0xEFFC, - 0xEFFE, 0xF001, 0xF003, 0xF00D, 0xF00F, 0xF010, - 0xF012, 0xF014, 0xF01C, 0xF01E, 0xF021, 0xF023, - 0xF02D, 0xF02F, 0xF030, 0xF032, 0xF034, 0xF03C, - 0xF03E, 0xF041, 0xF043, 0xF04D, 0xF04F, 0xF0C1, - 0xF0C3, 0xF0CD, 0xF0CF, 0xF0D0, 0xF0D2, 0xF0D4, - 0xF0DC, 0xF0DE, 0xF0E1, 0xF0E3, 0xF0ED, 0xF0EF, - 0xF0F0, 0xF0F2, 0xF0F4, 0xF0FC, 0xF0FE, 0xF100, - 0xF102, 0xF104, 0xF10C, 0xF10E, 0xF111, 0xF113, - 0xF11D, 0xF11F, 0xF120, 0xF122, 0xF124, 0xF12C, - 0xF12E, 0xF131, 0xF133, 0xF13D, 0xF13F, 0xF140, - 0xF142, 0xF144, 0xF14C, 0xF14E, 0xF1C0, 0xF1C2, - 0xF1C4, 0xF1CC, 0xF1CE, 0xF1D1, 0xF1D3, 0xF1DD, - 0xF1DF, 0xF1E0, 0xF1E2, 0xF1E4, 0xF1EC, 0xF1EE, - 0xF1F1, 0xF1F3, 0xF1FD, 0xF1FF, 0xF201, 0xF203, - 0xF20D, 0xF20F, 0xF210, 0xF212, 0xF214, 0xF21C, - 0xF21E, 0xF221, 0xF223, 0xF22D, 0xF22F, 0xF230, - 0xF232, 0xF234, 0xF23C, 0xF23E, 0xF241, 0xF243, - 0xF24D, 0xF24F, 0xF2C1, 0xF2C3, 0xF2CD, 0xF2CF, - 0xF2D0, 0xF2D2, 0xF2D4, 0xF2DC, 0xF2DE, 0xF2E1, - 0xF2E3, 0xF2ED, 0xF2EF, 0xF2F0, 0xF2F2, 0xF2F4, - 0xF2FC, 0xF2FE, 0xF300, 0xF302, 0xF304, 0xF30C, - 0xF30E, 0xF311, 0xF313, 0xF31D, 0xF31F, 0xF320, - 0xF322, 0xF324, 0xF32C, 0xF32E, 0xF331, 0xF333, - 0xF33D, 0xF33F, 0xF340, 0xF342, 0xF344, 0xF34C, - 0xF34E, 0xF3C0, 0xF3C2, 0xF3C4, 0xF3CC, 0xF3CE, - 0xF3D1, 0xF3D3, 0xF3DD, 0xF3DF, 0xF3E0, 0xF3E2, - 0xF3E4, 0xF3EC, 0xF3EE, 0xF3F1, 0xF3F3, 0xF3FD, - 0xF3FF, 0xF401, 0xF403, 0xF40D, 0xF40F, 0xF410, - 0xF412, 0xF414, 0xF41C, 0xF41E, 0xF421, 0xF423, - 0xF42D, 0xF42F, 0xF430, 0xF432, 0xF434, 0xF43C, - 0xF43E, 0xF441, 0xF443, 0xF44D, 0xF44F, 0xF4C1, - 0xF4C3, 0xF4CD, 0xF4CF, 0xF4D0, 0xF4D2, 0xF4D4, - 0xF4DC, 0xF4DE, 0xF4E1, 0xF4E3, 0xF4ED, 0xF4EF, - 0xF4F0, 0xF4F2, 0xF4F4, 0xF4FC, 0xF4FE, 0xFC01, - 0xFC03, 0xFC0D, 0xFC0F, 0xFC10, 0xFC12, 0xFC14, - 0xFC1C, 0xFC1E, 0xFC21, 0xFC23, 0xFC2D, 0xFC2F, - 0xFC30, 0xFC32, 0xFC34, 0xFC3C, 0xFC3E, 0xFC41, - 0xFC43, 0xFC4D, 0xFC4F, 0xFCC1, 0xFCC3, 0xFCCD, - 0xFCCF, 0xFCD0, 0xFCD2, 0xFCD4, 0xFCDC, 0xFCDE, - 0xFCE1, 0xFCE3, 0xFCED, 0xFCEF, 0xFCF0, 0xFCF2, - 0xFCF4, 0xFCFC, 0xFCFE, 0xFD00, 0xFD02, 0xFD04, - 0xFD0C, 0xFD0E, 0xFD11, 0xFD13, 0xFD1D, 0xFD1F, - 0xFD20, 0xFD22, 0xFD24, 0xFD2C, 0xFD2E, 0xFD31, - 0xFD33, 0xFD3D, 0xFD3F, 0xFD40, 0xFD42, 0xFD44, - 0xFD4C, 0xFD4E, 0xFDC0, 0xFDC2, 0xFDC4, 0xFDCC, - 0xFDCE, 0xFDD1, 0xFDD3, 0xFDDD, 0xFDDF, 0xFDE0, - 0xFDE2, 0xFDE4, 0xFDEC, 0xFDEE, 0xFDF1, 0xFDF3, - 0xFDFD, 0xFDFF, 0xFE01, 0xFE03, 0xFE0D, 0xFE0F, - 0xFE10, 0xFE12, 0xFE14, 0xFE1C, 0xFE1E, 0xFE21, - 0xFE23, 0xFE2D, 0xFE2F, 0xFE30, 0xFE32, 0xFE34, - 0xFE3C, 0xFE3E, 0xFE41, 0xFE43, 0xFE4D, 0xFE4F, - 0xFEC1, 0xFEC3, 0xFECD, 0xFECF, 0xFED0, 0xFED2, - 0xFED4, 0xFEDC, 0xFEDE, 0xFEE1, 0xFEE3, 0xFEED, - 0xFEEF, 0xFEF0, 0xFEF2, 0xFEF4, 0xFEFC, 0xFEFE, - 0xFF00, 0xFF02, 0xFF04, 0xFF0C, 0xFF0E, 0xFF11, - 0xFF13, 0xFF1D, 0xFF1F, 0xFF20, 0xFF22, 0xFF24, - 0xFF2C, 0xFF2E, 0xFF31, 0xFF33, 0xFF3D, 0xFF3F, - 0xFF40, 0xFF42, 0xFF44, 0xFF4C, 0xFF4E, 0xFFC0, - 0xFFC2, 0xFFC4, 0xFFCC, 0xFFCE, 0xFFD1, 0xFFD3, - 0xFFDD, 0xFFDF, 0xFFE0, 0xFFE2, 0xFFE4, 0xFFEC, - 0xFFEE, 0xFFF1, 0xFFF3, 0xFFFD, 0xFFFF, -}; - -#define ON2AVC_CB9_CODES 121 -static const uint16_t on2avc_cb9_codes[ON2AVC_CB9_CODES] = { - 0x0000, 0x000F, 0x0098, 0x026E, 0x045C, 0x00A6, - 0x00AC, 0x045D, 0x027E, 0x009A, 0x0012, 0x000E, - 0x001A, 0x00DE, 0x022C, 0x053E, 0x00A2, 0x009E, - 0x0538, 0x01B2, 0x00BA, 0x0018, 0x00AD, 0x00BF, - 0x01BE, 0x037E, 0x05C6, 0x0132, 0x0112, 0x08B5, - 0x0457, 0x01B6, 0x00BC, 0x02AE, 0x022A, 0x045E, - 0x08B6, 0x08FA, 0x0147, 0x013E, 0x119F, 0x05C7, - 0x044F, 0x0170, 0x0456, 0x047F, 0x06C7, 0x0A72, - 0x0D8B, 0x0267, 0x0266, 0x0D8A, 0x08B7, 0x05CF, - 0x045F, 0x0054, 0x00A4, 0x0118, 0x0142, 0x0234, - 0x036F, 0x036E, 0x029E, 0x0156, 0x0114, 0x0088, - 0x00A0, 0x00A5, 0x00DA, 0x015F, 0x026F, 0x02E2, - 0x02E6, 0x0236, 0x015E, 0x0143, 0x00AA, 0x053A, - 0x0466, 0x04FE, 0x09FE, 0x119E, 0x0232, 0x0237, - 0x0A73, 0x09FF, 0x08B4, 0x046B, 0x02AF, 0x01B0, - 0x037F, 0x053F, 0x08FB, 0x0136, 0x0146, 0x08CE, - 0x05CE, 0x044E, 0x01B3, 0x008E, 0x00DD, 0x0226, - 0x047E, 0x06C6, 0x00AE, 0x011E, 0x06C4, 0x047C, - 0x0172, 0x00BE, 0x0010, 0x0016, 0x00BD, 0x0176, - 0x053B, 0x009D, 0x009C, 0x046A, 0x0177, 0x00DC, - 0x0019, -}; - -static const uint8_t on2avc_cb9_bits[ON2AVC_CB9_CODES] = { - 1, 4, 8, 10, 11, 8, - 8, 11, 10, 8, 5, 4, - 5, 8, 10, 11, 8, 8, - 11, 9, 8, 5, 8, 8, - 9, 10, 11, 9, 9, 12, - 11, 9, 8, 10, 10, 11, - 12, 12, 9, 9, 13, 11, - 11, 9, 11, 11, 11, 12, - 12, 10, 10, 12, 12, 11, - 11, 7, 8, 9, 9, 10, - 10, 10, 10, 9, 9, 8, - 8, 8, 8, 9, 10, 10, - 10, 10, 9, 9, 8, 11, - 11, 11, 12, 13, 10, 10, - 12, 12, 12, 11, 10, 9, - 10, 11, 12, 9, 9, 12, - 11, 11, 9, 8, 8, 10, - 11, 11, 8, 9, 11, 11, - 9, 8, 5, 5, 8, 9, - 11, 8, 8, 11, 9, 8, - 5, -}; - -static const uint16_t on2avc_cb9_syms[ON2AVC_CB9_CODES] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, - 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x0100, - 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x01FB, - 0x01FC, 0x01FD, 0x01FE, 0x01FF, 0x0200, 0x0201, - 0x0202, 0x0203, 0x0204, 0x0205, 0x02FB, 0x02FC, - 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, - 0x0303, 0x0304, 0x0305, 0x03FB, 0x03FC, 0x03FD, - 0x03FE, 0x03FF, 0x0400, 0x0401, 0x0402, 0x0403, - 0x0404, 0x0405, 0x04FB, 0x04FC, 0x04FD, 0x04FE, - 0x04FF, 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, - 0x0505, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, - 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0xFB05, - 0xFBFB, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, - 0xFC01, 0xFC02, 0xFC03, 0xFC04, 0xFC05, 0xFCFB, - 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, 0xFD00, 0xFD01, - 0xFD02, 0xFD03, 0xFD04, 0xFD05, 0xFDFB, 0xFDFC, - 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, 0xFE01, 0xFE02, - 0xFE03, 0xFE04, 0xFE05, 0xFEFB, 0xFEFC, 0xFEFD, - 0xFEFE, 0xFEFF, 0xFF00, 0xFF01, 0xFF02, 0xFF03, - 0xFF04, 0xFF05, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, - 0xFFFF, -}; - -#define ON2AVC_CB10_CODES 121 -static const uint16_t on2avc_cb10_codes[ON2AVC_CB10_CODES] = { - 0x002E, 0x001A, 0x003C, 0x001F, 0x006E, 0x002E, - 0x00AE, 0x006F, 0x002A, 0x003E, 0x0014, 0x0016, - 0x0002, 0x000E, 0x004E, 0x00F7, 0x0042, 0x0027, - 0x00F6, 0x0046, 0x0014, 0x0008, 0x0032, 0x0016, - 0x0030, 0x0012, 0x0056, 0x0018, 0x005F, 0x00DE, - 0x006E, 0x0036, 0x001A, 0x0023, 0x003D, 0x003F, - 0x007A, 0x008E, 0x0071, 0x0006, 0x0012, 0x000F, - 0x0043, 0x003E, 0x00AE, 0x0001, 0x00AB, 0x00C7, - 0x0013, 0x000A, 0x0002, 0x01CA, 0x0003, 0x0000, - 0x000F, 0x0022, 0x0016, 0x002A, 0x007F, 0x001C, - 0x0036, 0x00AF, 0x00C6, 0x000E, 0x0010, 0x0006, - 0x008F, 0x001E, 0x0054, 0x000D, 0x00AA, 0x0056, - 0x00AC, 0x001D, 0x0076, 0x0013, 0x004F, 0x0057, - 0x00E6, 0x00EE, 0x000E, 0x01CB, 0x00AF, 0x000B, - 0x0007, 0x00EF, 0x00AD, 0x00E4, 0x0008, 0x005E, - 0x0070, 0x001E, 0x00DF, 0x000C, 0x007E, 0x00CE, - 0x0002, 0x001A, 0x003C, 0x0002, 0x0020, 0x003A, - 0x004D, 0x00CF, 0x0066, 0x0026, 0x002F, 0x001F, - 0x0022, 0x001B, 0x0012, 0x000E, 0x0017, 0x0062, - 0x00E7, 0x0019, 0x0014, 0x0006, 0x004C, 0x0012, - 0x000C, -}; - -static const uint8_t on2avc_cb10_bits[ON2AVC_CB10_CODES] = { - 6, 5, 6, 8, 9, 8, - 8, 9, 8, 6, 5, 5, - 5, 6, 7, 8, 7, 7, - 8, 7, 6, 5, 6, 6, - 6, 7, 8, 7, 7, 8, - 7, 6, 6, 8, 7, 7, - 7, 8, 7, 8, 9, 8, - 7, 7, 9, 9, 8, 8, - 9, 8, 9, 9, 9, 9, - 9, 8, 7, 7, 7, 8, - 8, 9, 8, 8, 7, 6, - 8, 7, 7, 8, 8, 9, - 8, 8, 7, 7, 7, 9, - 8, 8, 9, 9, 8, 8, - 9, 8, 8, 8, 8, 7, - 7, 8, 8, 8, 7, 8, - 8, 7, 7, 7, 6, 6, - 7, 8, 7, 7, 8, 7, - 6, 6, 5, 5, 6, 7, - 8, 7, 7, 9, 7, 6, - 5, -}; - -static const uint16_t on2avc_cb10_syms[ON2AVC_CB10_CODES] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, - 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x0100, - 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x01FB, - 0x01FC, 0x01FD, 0x01FE, 0x01FF, 0x0200, 0x0201, - 0x0202, 0x0203, 0x0204, 0x0205, 0x02FB, 0x02FC, - 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, - 0x0303, 0x0304, 0x0305, 0x03FB, 0x03FC, 0x03FD, - 0x03FE, 0x03FF, 0x0400, 0x0401, 0x0402, 0x0403, - 0x0404, 0x0405, 0x04FB, 0x04FC, 0x04FD, 0x04FE, - 0x04FF, 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, - 0x0505, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, - 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0xFB05, - 0xFBFB, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, - 0xFC01, 0xFC02, 0xFC03, 0xFC04, 0xFC05, 0xFCFB, - 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, 0xFD00, 0xFD01, - 0xFD02, 0xFD03, 0xFD04, 0xFD05, 0xFDFB, 0xFDFC, - 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, 0xFE01, 0xFE02, - 0xFE03, 0xFE04, 0xFE05, 0xFEFB, 0xFEFC, 0xFEFD, - 0xFEFE, 0xFEFF, 0xFF00, 0xFF01, 0xFF02, 0xFF03, - 0xFF04, 0xFF05, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, - 0xFFFF, -}; - -#define ON2AVC_CB11_CODES 225 -static const uint16_t on2avc_cb11_codes[ON2AVC_CB11_CODES] = { - 0x0000, 0x000E, 0x0056, 0x00CD, 0x0173, 0x0232, - 0x00C7, 0x014F, 0x01AA, 0x00BE, 0x026F, 0x0192, - 0x00BC, 0x0058, 0x000F, 0x000C, 0x0010, 0x004E, - 0x0082, 0x0142, 0x01BF, 0x0098, 0x015E, 0x0136, - 0x0086, 0x01BB, 0x014E, 0x00BA, 0x003E, 0x0012, - 0x0054, 0x0036, 0x0050, 0x008F, 0x014B, 0x0262, - 0x00AA, 0x015C, 0x013E, 0x00B7, 0x02BE, 0x0176, - 0x00A2, 0x0058, 0x003C, 0x00C2, 0x00A6, 0x008A, - 0x00B2, 0x0122, 0x02AC, 0x00CA, 0x012F, 0x014A, - 0x00DC, 0x02DE, 0x017A, 0x0134, 0x0092, 0x00B4, - 0x0166, 0x0148, 0x016E, 0x013F, 0x0134, 0x02FF, - 0x014F, 0x019E, 0x0267, 0x016C, 0x02A6, 0x02CE, - 0x013A, 0x010A, 0x0108, 0x026E, 0x02CB, 0x028E, - 0x02CF, 0x020F, 0x02DF, 0x010B, 0x02AD, 0x0227, - 0x018A, 0x04DB, 0x02A7, 0x02FE, 0x0236, 0x026C, - 0x00C6, 0x009C, 0x00C4, 0x00CE, 0x00D6, 0x0135, - 0x0156, 0x025A, 0x02FF, 0x0286, 0x015F, 0x0132, - 0x00D7, 0x00AC, 0x00A2, 0x0176, 0x0118, 0x0123, - 0x0157, 0x01BC, 0x02AE, 0x02EE, 0x04DA, 0x0467, - 0x033F, 0x0287, 0x0193, 0x0182, 0x013B, 0x0112, - 0x0133, 0x017D, 0x0117, 0x0186, 0x026E, 0x025B, - 0x02EF, 0x0466, 0x0316, 0x0237, 0x02F6, 0x01BA, - 0x015D, 0x012E, 0x015A, 0x014A, 0x008E, 0x00B6, - 0x0135, 0x0100, 0x017B, 0x028C, 0x033E, 0x0297, - 0x015B, 0x0102, 0x0140, 0x00D4, 0x00BA, 0x0088, - 0x02EE, 0x0283, 0x02BF, 0x020E, 0x02CE, 0x0317, - 0x0172, 0x0296, 0x026F, 0x0101, 0x02CF, 0x02F7, - 0x01BD, 0x02EF, 0x028F, 0x0263, 0x0164, 0x011A, - 0x0147, 0x0292, 0x02FE, 0x015E, 0x02AF, 0x01AB, - 0x0130, 0x02CA, 0x0183, 0x014E, 0x017C, 0x017E, - 0x00C8, 0x00AA, 0x009E, 0x0132, 0x0152, 0x0226, - 0x00CC, 0x017E, 0x0187, 0x00CB, 0x0293, 0x0106, - 0x00C0, 0x0087, 0x00BC, 0x005C, 0x003D, 0x005A, - 0x00A8, 0x0103, 0x028D, 0x00A4, 0x0116, 0x0146, - 0x00B8, 0x01BE, 0x016D, 0x0093, 0x004A, 0x003F, - 0x000D, 0x0011, 0x004F, 0x00AE, 0x0166, 0x0266, - 0x0090, 0x0109, 0x012C, 0x00A6, 0x0282, 0x017A, - 0x00B5, 0x0034, 0x000E, -}; - -static const uint8_t on2avc_cb11_bits[ON2AVC_CB11_CODES] = { - 2, 4, 7, 9, 10, 11, - 9, 10, 10, 9, 11, 10, - 9, 7, 4, 4, 5, 7, - 9, 9, 10, 9, 10, 10, - 9, 10, 9, 8, 7, 5, - 7, 7, 8, 9, 9, 10, - 9, 10, 10, 9, 10, 9, - 9, 8, 7, 9, 8, 9, - 9, 10, 10, 9, 10, 10, - 9, 10, 10, 9, 9, 8, - 10, 9, 9, 10, 10, 10, - 9, 10, 10, 9, 11, 10, - 10, 10, 10, 11, 10, 10, - 10, 11, 10, 10, 10, 11, - 10, 11, 11, 10, 11, 10, - 9, 9, 9, 9, 9, 10, - 10, 11, 11, 10, 10, 10, - 9, 9, 8, 10, 10, 10, - 10, 10, 10, 10, 11, 12, - 11, 10, 10, 10, 10, 10, - 10, 9, 10, 10, 10, 11, - 11, 12, 11, 11, 10, 10, - 10, 10, 10, 9, 9, 9, - 9, 10, 10, 10, 11, 11, - 10, 10, 9, 9, 9, 9, - 11, 10, 10, 11, 11, 11, - 10, 11, 10, 10, 11, 10, - 10, 10, 10, 10, 9, 10, - 10, 10, 11, 9, 10, 10, - 9, 10, 10, 10, 9, 9, - 9, 8, 9, 9, 10, 11, - 9, 10, 10, 9, 10, 10, - 9, 9, 8, 7, 7, 8, - 9, 10, 10, 9, 10, 10, - 9, 10, 9, 9, 8, 7, - 4, 5, 7, 8, 9, 10, - 9, 10, 10, 9, 10, 9, - 8, 7, 5, -}; - -static const uint16_t on2avc_cb11_syms[ON2AVC_CB11_CODES] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, - 0x0006, 0x0007, 0x00F9, 0x00FA, 0x00FB, 0x00FC, - 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x0101, 0x0102, - 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x01F9, - 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, - 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, - 0x0206, 0x0207, 0x02F9, 0x02FA, 0x02FB, 0x02FC, - 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, - 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x03F9, - 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, - 0x0406, 0x0407, 0x04F9, 0x04FA, 0x04FB, 0x04FC, - 0x04FD, 0x04FE, 0x04FF, 0x0500, 0x0501, 0x0502, - 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x05F9, - 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, - 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, - 0x0606, 0x0607, 0x06F9, 0x06FA, 0x06FB, 0x06FC, - 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, - 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x07F9, - 0x07FA, 0x07FB, 0x07FC, 0x07FD, 0x07FE, 0x07FF, - 0xF900, 0xF901, 0xF902, 0xF903, 0xF904, 0xF905, - 0xF906, 0xF907, 0xF9F9, 0xF9FA, 0xF9FB, 0xF9FC, - 0xF9FD, 0xF9FE, 0xF9FF, 0xFA00, 0xFA01, 0xFA02, - 0xFA03, 0xFA04, 0xFA05, 0xFA06, 0xFA07, 0xFAF9, - 0xFAFA, 0xFAFB, 0xFAFC, 0xFAFD, 0xFAFE, 0xFAFF, - 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0xFB05, - 0xFB06, 0xFB07, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, - 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, 0xFC01, 0xFC02, - 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFCF9, - 0xFCFA, 0xFCFB, 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, - 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04, 0xFD05, - 0xFD06, 0xFD07, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, - 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, 0xFE01, 0xFE02, - 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFEF9, - 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0xFEFF, - 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, - 0xFF06, 0xFF07, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, - 0xFFFD, 0xFFFE, 0xFFFF, -}; - -#define ON2AVC_CB12_CODES 441 -static const uint16_t on2avc_cb12_codes[ON2AVC_CB12_CODES] = { - 0x0000, 0x000C, 0x004F, 0x0156, 0x02E6, 0x0462, - 0x044C, 0x086A, 0x0222, 0x0228, 0x047F, 0x037A, - 0x028F, 0x02B8, 0x0BB7, 0x04B7, 0x02DA, 0x0262, - 0x0124, 0x0052, 0x000F, 0x000D, 0x000E, 0x0058, - 0x00A2, 0x0129, 0x02C8, 0x0256, 0x044D, 0x016E, - 0x02AA, 0x02BE, 0x027F, 0x02A9, 0x016E, 0x0597, - 0x02EE, 0x02EE, 0x013A, 0x00A4, 0x004E, 0x000C, - 0x0056, 0x004B, 0x0058, 0x0125, 0x010E, 0x01A7, - 0x026A, 0x0415, 0x010C, 0x0228, 0x0446, 0x0232, - 0x017E, 0x0128, 0x0473, 0x035E, 0x026A, 0x015E, - 0x00DB, 0x005E, 0x0048, 0x017A, 0x00AE, 0x00BA, - 0x0172, 0x0229, 0x02FB, 0x0458, 0x05A4, 0x015A, - 0x0296, 0x05BE, 0x044E, 0x0216, 0x012A, 0x0423, - 0x053E, 0x02F0, 0x02F1, 0x011E, 0x0110, 0x009C, - 0x026B, 0x0112, 0x011B, 0x01B3, 0x01BF, 0x0263, - 0x057E, 0x04B8, 0x016B, 0x02DE, 0x04DE, 0x0416, - 0x02DB, 0x02AB, 0x06EE, 0x04CF, 0x025F, 0x02EB, - 0x022A, 0x011A, 0x010A, 0x05A5, 0x0238, 0x0217, - 0x02D6, 0x025A, 0x0282, 0x044F, 0x043D, 0x01AE, - 0x026B, 0x05C2, 0x043C, 0x044F, 0x02DB, 0x05A7, - 0x044E, 0x05BF, 0x0297, 0x022A, 0x026C, 0x02BD, - 0x0897, 0x0283, 0x02B6, 0x02B7, 0x0264, 0x0459, - 0x040B, 0x04DF, 0x0298, 0x0456, 0x0AFF, 0x06B7, - 0x0448, 0x0449, 0x08BE, 0x06EF, 0x04B9, 0x0597, - 0x049A, 0x02D2, 0x02F8, 0x08F7, 0x0476, 0x0452, - 0x0453, 0x045A, 0x05BE, 0x043E, 0x04D2, 0x02F2, - 0x02E4, 0x0477, 0x0AFE, 0x05A6, 0x02E3, 0x0BB6, - 0x0A7E, 0x05A6, 0x0A66, 0x08BF, 0x05FF, 0x0492, - 0x0170, 0x0106, 0x0140, 0x0142, 0x022E, 0x02CF, - 0x02B9, 0x02E2, 0x02F3, 0x05A0, 0x088E, 0x0DD7, - 0x04F6, 0x047E, 0x045B, 0x0347, 0x029E, 0x026D, - 0x01AC, 0x013B, 0x0104, 0x035F, 0x02EC, 0x026E, - 0x0233, 0x0207, 0x023E, 0x026E, 0x053F, 0x05A7, - 0x0456, 0x04AE, 0x0DD6, 0x0A67, 0x0493, 0x04BA, - 0x05D3, 0x05C3, 0x0246, 0x0247, 0x0202, 0x02E8, - 0x05AE, 0x0374, 0x0537, 0x05C6, 0x04BB, 0x0686, - 0x04D3, 0x04DE, 0x08C3, 0x05BF, 0x04F7, 0x14FB, - 0x0997, 0x0A7F, 0x08C2, 0x0417, 0x0434, 0x0477, - 0x037B, 0x0463, 0x02EF, 0x0592, 0x02E5, 0x049B, - 0x035A, 0x0436, 0x05AF, 0x0687, 0x0896, 0x095F, - 0x09BE, 0x0996, 0x0558, 0x088F, 0x0B8E, 0x057E, - 0x04CA, 0x05CE, 0x05F3, 0x047A, 0x05A1, 0x02E2, - 0x02FA, 0x0204, 0x022C, 0x020E, 0x0360, 0x02AE, - 0x05FC, 0x0457, 0x05DA, 0x086B, 0x14FA, 0x04B6, - 0x02FE, 0x040A, 0x02E6, 0x0576, 0x044A, 0x028C, - 0x0212, 0x0248, 0x02E0, 0x029A, 0x0126, 0x017E, - 0x0130, 0x024C, 0x0232, 0x0596, 0x0378, 0x053A, - 0x04CC, 0x0A7C, 0x0470, 0x0593, 0x02D8, 0x029C, - 0x02D9, 0x02BE, 0x01A0, 0x014E, 0x0120, 0x013C, - 0x06EC, 0x04CD, 0x0559, 0x06B6, 0x0420, 0x057F, - 0x0596, 0x09BF, 0x0532, 0x055A, 0x095E, 0x08BC, - 0x0472, 0x02CA, 0x05F2, 0x05FD, 0x047E, 0x05A2, - 0x06EA, 0x05CF, 0x04D2, 0x043F, 0x028E, 0x0422, - 0x0460, 0x05DE, 0x053B, 0x08F6, 0x0B8F, 0x02CE, - 0x0473, 0x06ED, 0x0421, 0x028D, 0x023C, 0x047F, - 0x05A3, 0x044C, 0x044D, 0x0457, 0x02CA, 0x02D8, - 0x027C, 0x029E, 0x023E, 0x027D, 0x0361, 0x0414, - 0x05BC, 0x08BD, 0x02DA, 0x024A, 0x0437, 0x055B, - 0x0379, 0x01BE, 0x05DF, 0x04D3, 0x0268, 0x0206, - 0x0213, 0x02BA, 0x0203, 0x0236, 0x0127, 0x0136, - 0x0268, 0x0242, 0x02CF, 0x05FE, 0x05D2, 0x0237, - 0x0243, 0x0472, 0x0362, 0x027A, 0x02AE, 0x0471, - 0x0474, 0x024B, 0x02AF, 0x01A6, 0x012C, 0x0166, - 0x0166, 0x00A6, 0x00AC, 0x0100, 0x01B2, 0x020F, - 0x0363, 0x0446, 0x016A, 0x022E, 0x0577, 0x02FF, - 0x022D, 0x0168, 0x0475, 0x027E, 0x0222, 0x01A2, - 0x017B, 0x00D2, 0x00BE, 0x0050, 0x0054, 0x006A, - 0x011A, 0x0143, 0x024F, 0x02E7, 0x0447, 0x0110, - 0x0233, 0x02D9, 0x02AF, 0x024E, 0x016A, 0x0536, - 0x0342, 0x02BC, 0x0176, 0x00DA, 0x0054, 0x004A, - 0x000E, 0x0010, 0x004C, 0x00DC, 0x0164, 0x023A, - 0x0476, 0x04CE, 0x0118, 0x02CE, 0x025E, 0x0346, - 0x02A8, 0x0122, 0x05BD, 0x022F, 0x02EA, 0x014A, - 0x00AA, 0x0051, 0x000F, -}; - -static const uint8_t on2avc_cb12_bits[ON2AVC_CB12_CODES] = { - 2, 4, 7, 9, 10, 11, - 12, 13, 10, 11, 11, 11, - 11, 10, 12, 12, 11, 11, - 9, 7, 4, 4, 5, 7, - 9, 10, 10, 11, 12, 10, - 10, 11, 11, 10, 9, 12, - 11, 10, 10, 9, 7, 5, - 7, 7, 8, 9, 10, 10, - 11, 12, 10, 10, 11, 11, - 10, 10, 12, 11, 10, 10, - 9, 8, 7, 9, 9, 9, - 9, 10, 10, 11, 11, 10, - 11, 11, 11, 11, 10, 12, - 11, 10, 10, 10, 9, 9, - 10, 10, 10, 10, 10, 11, - 11, 12, 10, 11, 11, 12, - 11, 10, 12, 12, 11, 10, - 10, 10, 10, 11, 10, 11, - 10, 11, 11, 12, 12, 10, - 11, 11, 12, 11, 10, 12, - 12, 11, 11, 11, 10, 10, - 12, 11, 11, 11, 11, 11, - 12, 12, 10, 11, 12, 12, - 11, 11, 12, 12, 12, 11, - 11, 11, 10, 12, 12, 12, - 12, 11, 12, 12, 12, 10, - 11, 12, 12, 11, 11, 12, - 13, 12, 12, 12, 11, 12, - 10, 10, 10, 10, 10, 10, - 10, 10, 10, 11, 12, 13, - 12, 12, 11, 11, 11, 10, - 10, 10, 10, 11, 10, 10, - 11, 11, 11, 11, 11, 11, - 12, 12, 13, 12, 12, 12, - 11, 11, 11, 11, 11, 10, - 11, 11, 11, 11, 12, 12, - 12, 12, 12, 12, 12, 14, - 13, 13, 12, 12, 12, 11, - 11, 11, 11, 11, 11, 11, - 11, 12, 11, 12, 12, 13, - 12, 13, 12, 12, 12, 12, - 12, 11, 11, 11, 11, 11, - 10, 11, 11, 11, 11, 11, - 11, 12, 11, 13, 14, 12, - 11, 12, 11, 11, 11, 11, - 11, 11, 10, 10, 10, 9, - 10, 10, 10, 11, 11, 11, - 12, 13, 12, 11, 10, 10, - 10, 10, 10, 10, 10, 10, - 12, 12, 12, 12, 12, 12, - 12, 12, 11, 12, 13, 12, - 11, 10, 11, 11, 11, 11, - 12, 11, 11, 12, 11, 12, - 11, 11, 11, 12, 12, 11, - 11, 12, 12, 11, 10, 12, - 11, 11, 11, 11, 11, 11, - 11, 10, 10, 11, 11, 12, - 11, 12, 10, 11, 12, 12, - 11, 10, 11, 11, 11, 11, - 11, 10, 11, 10, 10, 10, - 10, 11, 11, 11, 11, 10, - 11, 12, 11, 11, 10, 12, - 11, 11, 10, 10, 10, 10, - 9, 9, 9, 10, 10, 11, - 11, 12, 10, 11, 11, 11, - 11, 10, 11, 11, 11, 10, - 9, 9, 9, 7, 7, 8, - 9, 10, 10, 11, 12, 10, - 10, 11, 11, 10, 9, 11, - 11, 10, 10, 9, 8, 7, - 4, 5, 7, 9, 10, 11, - 11, 12, 10, 10, 11, 11, - 10, 10, 11, 11, 10, 10, - 9, 7, 5, -}; - -static const uint16_t on2avc_cb12_syms[ON2AVC_CB12_CODES] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, - 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x00F6, - 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, - 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x0101, 0x0102, - 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, - 0x0109, 0x010A, 0x01F6, 0x01F7, 0x01F8, 0x01F9, - 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, - 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, - 0x0206, 0x0207, 0x0208, 0x0209, 0x020A, 0x02F6, - 0x02F7, 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, - 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, - 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, - 0x0309, 0x030A, 0x03F6, 0x03F7, 0x03F8, 0x03F9, - 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, - 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x04F6, - 0x04F7, 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, - 0x04FD, 0x04FE, 0x04FF, 0x0500, 0x0501, 0x0502, - 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, - 0x0509, 0x050A, 0x05F6, 0x05F7, 0x05F8, 0x05F9, - 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, - 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, - 0x0606, 0x0607, 0x0608, 0x0609, 0x060A, 0x06F6, - 0x06F7, 0x06F8, 0x06F9, 0x06FA, 0x06FB, 0x06FC, - 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, - 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, - 0x0709, 0x070A, 0x07F6, 0x07F7, 0x07F8, 0x07F9, - 0x07FA, 0x07FB, 0x07FC, 0x07FD, 0x07FE, 0x07FF, - 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, - 0x0806, 0x0807, 0x0808, 0x0809, 0x080A, 0x08F6, - 0x08F7, 0x08F8, 0x08F9, 0x08FA, 0x08FB, 0x08FC, - 0x08FD, 0x08FE, 0x08FF, 0x0900, 0x0901, 0x0902, - 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, - 0x0909, 0x090A, 0x09F6, 0x09F7, 0x09F8, 0x09F9, - 0x09FA, 0x09FB, 0x09FC, 0x09FD, 0x09FE, 0x09FF, - 0x0A00, 0x0A01, 0x0A02, 0x0A03, 0x0A04, 0x0A05, - 0x0A06, 0x0A07, 0x0A08, 0x0A09, 0x0A0A, 0x0AF6, - 0x0AF7, 0x0AF8, 0x0AF9, 0x0AFA, 0x0AFB, 0x0AFC, - 0x0AFD, 0x0AFE, 0x0AFF, 0xF600, 0xF601, 0xF602, - 0xF603, 0xF604, 0xF605, 0xF606, 0xF607, 0xF608, - 0xF609, 0xF60A, 0xF6F6, 0xF6F7, 0xF6F8, 0xF6F9, - 0xF6FA, 0xF6FB, 0xF6FC, 0xF6FD, 0xF6FE, 0xF6FF, - 0xF700, 0xF701, 0xF702, 0xF703, 0xF704, 0xF705, - 0xF706, 0xF707, 0xF708, 0xF709, 0xF70A, 0xF7F6, - 0xF7F7, 0xF7F8, 0xF7F9, 0xF7FA, 0xF7FB, 0xF7FC, - 0xF7FD, 0xF7FE, 0xF7FF, 0xF800, 0xF801, 0xF802, - 0xF803, 0xF804, 0xF805, 0xF806, 0xF807, 0xF808, - 0xF809, 0xF80A, 0xF8F6, 0xF8F7, 0xF8F8, 0xF8F9, - 0xF8FA, 0xF8FB, 0xF8FC, 0xF8FD, 0xF8FE, 0xF8FF, - 0xF900, 0xF901, 0xF902, 0xF903, 0xF904, 0xF905, - 0xF906, 0xF907, 0xF908, 0xF909, 0xF90A, 0xF9F6, - 0xF9F7, 0xF9F8, 0xF9F9, 0xF9FA, 0xF9FB, 0xF9FC, - 0xF9FD, 0xF9FE, 0xF9FF, 0xFA00, 0xFA01, 0xFA02, - 0xFA03, 0xFA04, 0xFA05, 0xFA06, 0xFA07, 0xFA08, - 0xFA09, 0xFA0A, 0xFAF6, 0xFAF7, 0xFAF8, 0xFAF9, - 0xFAFA, 0xFAFB, 0xFAFC, 0xFAFD, 0xFAFE, 0xFAFF, - 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0xFB05, - 0xFB06, 0xFB07, 0xFB08, 0xFB09, 0xFB0A, 0xFBF6, - 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, - 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, 0xFC01, 0xFC02, - 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08, - 0xFC09, 0xFC0A, 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, - 0xFCFA, 0xFCFB, 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, - 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04, 0xFD05, - 0xFD06, 0xFD07, 0xFD08, 0xFD09, 0xFD0A, 0xFDF6, - 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, - 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, 0xFE01, 0xFE02, - 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, - 0xFE09, 0xFE0A, 0xFEF6, 0xFEF7, 0xFEF8, 0xFEF9, - 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0xFEFF, - 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, - 0xFF06, 0xFF07, 0xFF08, 0xFF09, 0xFF0A, 0xFFF6, - 0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, - 0xFFFD, 0xFFFE, 0xFFFF, -}; - -#define ON2AVC_CB13_CODES 625 -static const uint16_t on2avc_cb13_codes[ON2AVC_CB13_CODES] = { - 0x0000, 0x0015, 0x008E, 0x0338, 0x09FB, 0x0BEC, - 0x0C61, 0x13E1, 0x18A7, 0x313B, 0x61BB, 0x05D9, - 0x0896, 0x066B, 0x05C6, 0x18A6, 0x40E4, 0x2081, - 0x104F, 0x13E0, 0x0C22, 0x07E4, 0x03F7, 0x0087, - 0x0014, 0x0016, 0x001D, 0x009C, 0x02E2, 0x037E, - 0x0897, 0x0898, 0x0C63, 0x117D, 0x2082, 0x27AA, - 0x033B, 0x06C5, 0x04F2, 0x0331, 0x19EB, 0x18A8, - 0x13E2, 0x0DE7, 0x0C62, 0x06DF, 0x05C7, 0x02F4, - 0x0098, 0x001A, 0x007C, 0x0080, 0x0106, 0x02F5, - 0x03EC, 0x0617, 0x0621, 0x08F9, 0x1050, 0x117F, - 0x11E0, 0x036A, 0x045A, 0x06C6, 0x037F, 0x117E, - 0x2083, 0x0BED, 0x0C9E, 0x0658, 0x04F3, 0x0368, - 0x02EE, 0x00FA, 0x008D, 0x031C, 0x01FF, 0x0206, - 0x031E, 0x06C8, 0x0659, 0x09B5, 0x0C23, 0x0BEF, - 0x0C9F, 0x19EC, 0x04CC, 0x0623, 0x06C7, 0x0622, - 0x313C, 0x17BB, 0x11E1, 0x0C64, 0x0BEE, 0x07DC, - 0x04CB, 0x0375, 0x0205, 0x026E, 0x0C24, 0x06C9, - 0x0324, 0x04DF, 0x0642, 0x09B6, 0x0643, 0x0BF2, - 0x083B, 0x1051, 0x27AB, 0x036C, 0x0607, 0x06E2, - 0x045B, 0x313D, 0x2084, 0x18A9, 0x13E3, 0x0CA0, - 0x0899, 0x066E, 0x06E3, 0x0369, 0x0606, 0x0DE8, - 0x061A, 0x0453, 0x065A, 0x065B, 0x089B, 0x089C, - 0x09FD, 0x0BA5, 0x18AA, 0x11E2, 0x05C8, 0x09B7, - 0x066F, 0x06CA, 0x19ED, 0x2085, 0x2086, 0x0D83, - 0x1052, 0x1053, 0x09FC, 0x089A, 0x0644, 0x083E, - 0x13E4, 0x08FC, 0x0624, 0x1055, 0x0C65, 0x089D, - 0x0645, 0x08FD, 0x0C66, 0x0CA1, 0x1056, 0x05E1, - 0x089E, 0x08FA, 0x07E5, 0x313E, 0x2087, 0x11E3, - 0x19EE, 0x18AB, 0x1054, 0x19EF, 0x17BC, 0x08FB, - 0x07E6, 0x18AD, 0x0BF3, 0x07E7, 0x0C67, 0x1057, - 0x07EA, 0x08FF, 0x1058, 0x0DE9, 0x18AE, 0x19F0, - 0x0608, 0x089F, 0x08FE, 0x06CB, 0x313F, 0x2088, - 0x13E5, 0x3142, 0x11E4, 0x18AC, 0x11E5, 0x0CA2, - 0x065E, 0x13E6, 0x27AD, 0x19F1, 0x0D86, 0x0DEA, - 0x0CA3, 0x0DEB, 0x17BE, 0x0C2A, 0x13E8, 0x0CA6, - 0x0DEE, 0x05FD, 0x0992, 0x0C25, 0x063E, 0x40E5, - 0x11E6, 0x3143, 0x18AF, 0x27AC, 0x0C26, 0x17BD, - 0x13E7, 0x0C27, 0x11E7, 0x27B2, 0x40E8, 0x18B3, - 0x17C0, 0x18FE, 0x19F2, 0x19F3, 0x31FE, 0x17C1, - 0x19F6, 0x0BA6, 0x09FE, 0x0DEF, 0x17BF, 0x0C2B, - 0x40E6, 0x18B0, 0x40E7, 0x13E9, 0x2089, 0x27AE, - 0x27AF, 0x208A, 0x18B1, 0x18B2, 0x27B3, 0xBCEF, - 0x2F3A, 0x40EA, 0x17C5, 0x17C6, 0x17C7, 0x19F7, - 0x133E, 0x105A, 0x17CA, 0x065F, 0x0CA7, 0x0C7E, - 0x1059, 0xBCED, 0x40E9, 0xBCEE, 0x17C2, 0x63FE, - 0x208B, 0x208E, 0x208F, 0x17C3, 0x17C4, 0x0625, - 0x03ED, 0x045C, 0x04CD, 0x05DA, 0x05CE, 0x05FF, - 0x0626, 0x060A, 0x05E3, 0x083F, 0x0BA8, 0x0BA9, - 0x40EB, 0x13EA, 0x0CCA, 0x0BA7, 0x08A2, 0x0646, - 0x0609, 0x05E2, 0x041E, 0x05FE, 0x0373, 0x0376, - 0x099E, 0x05DE, 0x0647, 0x05E6, 0x06D6, 0x07EB, - 0x09FF, 0x1B5E, 0x0BAB, 0x08AE, 0x0C36, 0x0FBA, - 0x17CB, 0x4CFE, 0x105B, 0x0D87, 0x0DAE, 0x13EB, - 0x0BAA, 0x0993, 0x08A3, 0x085E, 0x0600, 0x0601, - 0x05DB, 0x0664, 0x04F0, 0x05F8, 0x0634, 0x085F, - 0x06F6, 0x08F4, 0x0C5A, 0x0CFC, 0x0DDC, 0x09F6, - 0x0C16, 0x115E, 0x13D8, 0x13DA, 0x0C94, 0x0CFA, - 0x082E, 0x0B9E, 0x06C2, 0x0BE4, 0x06DA, 0x05C0, - 0x0614, 0x05C9, 0x05DF, 0x033A, 0x0336, 0x05FA, - 0x04CE, 0x05C1, 0x0890, 0x0891, 0x0838, 0x0839, - 0x0CFD, 0x0BA0, 0x61B8, 0x07DE, 0x0635, 0x0B9F, - 0x0640, 0x06DB, 0x082F, 0x09AC, 0x04C8, 0x0666, - 0x04DE, 0x03F4, 0x0339, 0x2079, 0x267E, 0x179E, - 0x30DE, 0x63FF, 0x27A0, 0x1997, 0x36BF, 0x3EEC, - 0x99FE, 0x99FF, 0x0C95, 0x1048, 0x0C5B, 0x0636, - 0x0C5C, 0x2076, 0x13DB, 0x115F, 0x179C, 0x2077, - 0x1046, 0x36BE, 0x1996, 0x2078, 0x61B9, 0x1175, - 0x17B0, 0x3EED, 0x19E1, 0x19E2, 0x207A, 0x3EEE, - 0xBCEC, 0x3138, 0x3139, 0x07DF, 0x1176, 0x0892, - 0x0667, 0x18A0, 0x18A2, 0x13DC, 0x1174, 0x13DD, - 0x179F, 0x30DF, 0x19E0, 0x18A3, 0x1049, 0x17B2, - 0x207B, 0x17B3, 0x0C17, 0x19E3, 0x17B4, 0x207C, - 0x3EEF, 0x207D, 0x19E4, 0x27A1, 0x0C5F, 0x08F5, - 0x0DDD, 0x0652, 0x18A4, 0x0C96, 0x0C5D, 0x104A, - 0x1177, 0x0CFE, 0x0C5E, 0x0DDE, 0x09F7, 0x17B1, - 0x19E6, 0x0C1E, 0x09AE, 0x1179, 0x0DE0, 0x17B5, - 0x0BA2, 0x17B6, 0x27A3, 0x40E0, 0x40E1, 0x06DC, - 0x09AF, 0x09AD, 0x05C2, 0x19E5, 0x27A2, 0x0DDF, - 0x0C1C, 0x0C1D, 0x0BE6, 0x0BA1, 0x1178, 0x0654, - 0x13DE, 0x40E2, 0x0893, 0x0668, 0x07E1, 0x0BE7, - 0x08F6, 0x0DE1, 0x27A4, 0x104B, 0x19E7, 0x40E3, - 0x05D6, 0x09F9, 0x06DD, 0x04CA, 0x17B7, 0x17B8, - 0x0C97, 0x0C98, 0x07E0, 0x0C99, 0x0655, 0x09F8, - 0x0656, 0x0C9A, 0x0DE2, 0x0669, 0x04D3, 0x061C, - 0x0894, 0x13DF, 0x0C1F, 0x104C, 0x27A6, 0x61BA, - 0x27A7, 0x066A, 0x061D, 0x0637, 0x04D2, 0x27A5, - 0x117A, 0x0C9B, 0x09B0, 0x09B1, 0x05E0, 0x0602, - 0x05FB, 0x04F1, 0x08F7, 0x06FA, 0x0603, 0x037C, - 0x05C3, 0x0BE8, 0x0895, 0x0C60, 0x117B, 0x19E8, - 0x27A8, 0x19E9, 0x0657, 0x083A, 0x06C4, 0x05D7, - 0x17B9, 0x0CFF, 0x0DE3, 0x104D, 0x07E2, 0x0641, - 0x061E, 0x05D8, 0x0366, 0x0616, 0x032E, 0x0268, - 0x02E6, 0x0456, 0x0BA3, 0x06FB, 0x0D80, 0x0DE5, - 0x104E, 0x17BA, 0x27A9, 0x0330, 0x07E3, 0x061F, - 0x0367, 0x207E, 0x0C9C, 0x117C, 0x0DE4, 0x06DE, - 0x0620, 0x0450, 0x042E, 0x02F2, 0x0204, 0x0086, - 0x008C, 0x00FE, 0x022A, 0x0372, 0x05CA, 0x0452, - 0x08F8, 0x0BA4, 0x19EA, 0x18A5, 0x0306, 0x05FC, - 0x03F6, 0x0458, 0x0D81, 0x0BE9, 0x09B2, 0x0C20, - 0x09FA, 0x0604, 0x0370, 0x01FE, 0x010A, 0x0084, - 0x0012, 0x001C, 0x0088, 0x026A, 0x05CB, 0x063B, - 0x09B4, 0x0D82, 0x0DE6, 0x207F, 0x2080, 0x030C, - 0x0605, 0x0459, 0x0374, 0x313A, 0x0C9D, 0x0BEA, - 0x0BEB, 0x0C21, 0x09B3, 0x063A, 0x0216, 0x009D, - 0x001E, -}; - -static const uint8_t on2avc_cb13_bits[ON2AVC_CB13_CODES] = { - 1, 5, 8, 10, 12, 12, - 12, 13, 13, 14, 15, 11, - 12, 11, 11, 13, 15, 14, - 13, 13, 12, 11, 10, 8, - 5, 5, 5, 8, 10, 10, - 12, 12, 12, 13, 14, 14, - 10, 11, 11, 10, 13, 13, - 13, 12, 12, 11, 11, 10, - 8, 5, 7, 8, 9, 10, - 10, 11, 11, 12, 13, 13, - 13, 10, 11, 11, 10, 13, - 14, 12, 12, 11, 11, 10, - 10, 8, 8, 10, 9, 10, - 10, 11, 11, 12, 12, 12, - 12, 13, 11, 11, 11, 11, - 14, 13, 13, 12, 12, 11, - 11, 10, 10, 10, 12, 11, - 10, 11, 11, 12, 11, 12, - 12, 13, 14, 10, 11, 11, - 11, 14, 14, 13, 13, 12, - 12, 11, 11, 10, 11, 12, - 11, 11, 11, 11, 12, 12, - 12, 12, 13, 13, 11, 12, - 11, 11, 13, 14, 14, 12, - 13, 13, 12, 12, 11, 12, - 13, 12, 11, 13, 12, 12, - 11, 12, 12, 12, 13, 11, - 12, 12, 11, 14, 14, 13, - 13, 13, 13, 13, 13, 12, - 11, 13, 12, 11, 12, 13, - 11, 12, 13, 12, 13, 13, - 11, 12, 12, 11, 14, 14, - 13, 14, 13, 13, 13, 12, - 11, 13, 14, 13, 12, 12, - 12, 12, 13, 12, 13, 12, - 12, 11, 12, 12, 11, 15, - 13, 14, 13, 14, 12, 13, - 13, 12, 13, 14, 15, 13, - 13, 13, 13, 13, 14, 13, - 13, 12, 12, 12, 13, 12, - 15, 13, 15, 13, 14, 14, - 14, 14, 13, 13, 14, 16, - 14, 15, 13, 13, 13, 13, - 13, 13, 13, 11, 12, 12, - 13, 16, 15, 16, 13, 15, - 14, 14, 14, 13, 13, 11, - 10, 11, 11, 11, 11, 11, - 11, 11, 11, 12, 12, 12, - 15, 13, 12, 12, 12, 11, - 11, 11, 11, 11, 10, 10, - 12, 11, 11, 11, 11, 11, - 12, 13, 12, 12, 12, 12, - 13, 15, 13, 12, 12, 13, - 12, 12, 12, 12, 11, 11, - 11, 11, 11, 11, 11, 12, - 11, 12, 12, 12, 12, 12, - 12, 13, 13, 13, 12, 12, - 12, 12, 11, 12, 11, 11, - 11, 11, 11, 10, 10, 11, - 11, 11, 12, 12, 12, 12, - 12, 12, 15, 11, 11, 12, - 11, 11, 12, 12, 11, 11, - 11, 10, 10, 14, 14, 13, - 14, 15, 14, 13, 14, 14, - 16, 16, 12, 13, 12, 11, - 12, 14, 13, 13, 13, 14, - 13, 14, 13, 14, 15, 13, - 13, 14, 13, 13, 14, 14, - 16, 14, 14, 11, 13, 12, - 11, 13, 13, 13, 13, 13, - 13, 14, 13, 13, 13, 13, - 14, 13, 12, 13, 13, 14, - 14, 14, 13, 14, 12, 12, - 12, 11, 13, 12, 12, 13, - 13, 12, 12, 12, 12, 13, - 13, 12, 12, 13, 12, 13, - 12, 13, 14, 15, 15, 11, - 12, 12, 11, 13, 14, 12, - 12, 12, 12, 12, 13, 11, - 13, 15, 12, 11, 11, 12, - 12, 12, 14, 13, 13, 15, - 11, 12, 11, 11, 13, 13, - 12, 12, 11, 12, 11, 12, - 11, 12, 12, 11, 11, 11, - 12, 13, 12, 13, 14, 15, - 14, 11, 11, 11, 11, 14, - 13, 12, 12, 12, 11, 11, - 11, 11, 12, 11, 11, 10, - 11, 12, 12, 12, 13, 13, - 14, 13, 11, 12, 11, 11, - 13, 12, 12, 13, 11, 11, - 11, 11, 10, 11, 10, 10, - 10, 11, 12, 11, 12, 12, - 13, 13, 14, 10, 11, 11, - 10, 14, 12, 13, 12, 11, - 11, 11, 11, 10, 10, 8, - 8, 8, 10, 10, 11, 11, - 12, 12, 13, 13, 10, 11, - 10, 11, 12, 12, 12, 12, - 12, 11, 10, 9, 9, 8, - 5, 5, 8, 10, 11, 11, - 12, 12, 12, 14, 14, 10, - 11, 11, 10, 14, 12, 12, - 12, 12, 12, 11, 10, 8, - 5, -}; - -static const uint16_t on2avc_cb13_syms[ON2AVC_CB13_CODES] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, - 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, - 0x000C, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, - 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, - 0x00FF, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, - 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, - 0x010B, 0x010C, 0x01F4, 0x01F5, 0x01F6, 0x01F7, - 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, - 0x01FE, 0x01FF, 0x0200, 0x0201, 0x0202, 0x0203, - 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, - 0x020A, 0x020B, 0x020C, 0x02F4, 0x02F5, 0x02F6, - 0x02F7, 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, - 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, - 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, - 0x0309, 0x030A, 0x030B, 0x030C, 0x03F4, 0x03F5, - 0x03F6, 0x03F7, 0x03F8, 0x03F9, 0x03FA, 0x03FB, - 0x03FC, 0x03FD, 0x03FE, 0x03FF, 0x0400, 0x0401, - 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, - 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x04F4, - 0x04F5, 0x04F6, 0x04F7, 0x04F8, 0x04F9, 0x04FA, - 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, 0x0500, - 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, - 0x0507, 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, - 0x05F4, 0x05F5, 0x05F6, 0x05F7, 0x05F8, 0x05F9, - 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, - 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, - 0x0606, 0x0607, 0x0608, 0x0609, 0x060A, 0x060B, - 0x060C, 0x06F4, 0x06F5, 0x06F6, 0x06F7, 0x06F8, - 0x06F9, 0x06FA, 0x06FB, 0x06FC, 0x06FD, 0x06FE, - 0x06FF, 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, - 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, 0x070A, - 0x070B, 0x070C, 0x07F4, 0x07F5, 0x07F6, 0x07F7, - 0x07F8, 0x07F9, 0x07FA, 0x07FB, 0x07FC, 0x07FD, - 0x07FE, 0x07FF, 0x0800, 0x0801, 0x0802, 0x0803, - 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809, - 0x080A, 0x080B, 0x080C, 0x08F4, 0x08F5, 0x08F6, - 0x08F7, 0x08F8, 0x08F9, 0x08FA, 0x08FB, 0x08FC, - 0x08FD, 0x08FE, 0x08FF, 0x0900, 0x0901, 0x0902, - 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, - 0x0909, 0x090A, 0x090B, 0x090C, 0x09F4, 0x09F5, - 0x09F6, 0x09F7, 0x09F8, 0x09F9, 0x09FA, 0x09FB, - 0x09FC, 0x09FD, 0x09FE, 0x09FF, 0x0A00, 0x0A01, - 0x0A02, 0x0A03, 0x0A04, 0x0A05, 0x0A06, 0x0A07, - 0x0A08, 0x0A09, 0x0A0A, 0x0A0B, 0x0A0C, 0x0AF4, - 0x0AF5, 0x0AF6, 0x0AF7, 0x0AF8, 0x0AF9, 0x0AFA, - 0x0AFB, 0x0AFC, 0x0AFD, 0x0AFE, 0x0AFF, 0x0B00, - 0x0B01, 0x0B02, 0x0B03, 0x0B04, 0x0B05, 0x0B06, - 0x0B07, 0x0B08, 0x0B09, 0x0B0A, 0x0B0B, 0x0B0C, - 0x0BF4, 0x0BF5, 0x0BF6, 0x0BF7, 0x0BF8, 0x0BF9, - 0x0BFA, 0x0BFB, 0x0BFC, 0x0BFD, 0x0BFE, 0x0BFF, - 0x0C00, 0x0C01, 0x0C02, 0x0C03, 0x0C04, 0x0C05, - 0x0C06, 0x0C07, 0x0C08, 0x0C09, 0x0C0A, 0x0C0B, - 0x0C0C, 0x0CF4, 0x0CF5, 0x0CF6, 0x0CF7, 0x0CF8, - 0x0CF9, 0x0CFA, 0x0CFB, 0x0CFC, 0x0CFD, 0x0CFE, - 0x0CFF, 0xF400, 0xF401, 0xF402, 0xF403, 0xF404, - 0xF405, 0xF406, 0xF407, 0xF408, 0xF409, 0xF40A, - 0xF40B, 0xF40C, 0xF4F4, 0xF4F5, 0xF4F6, 0xF4F7, - 0xF4F8, 0xF4F9, 0xF4FA, 0xF4FB, 0xF4FC, 0xF4FD, - 0xF4FE, 0xF4FF, 0xF500, 0xF501, 0xF502, 0xF503, - 0xF504, 0xF505, 0xF506, 0xF507, 0xF508, 0xF509, - 0xF50A, 0xF50B, 0xF50C, 0xF5F4, 0xF5F5, 0xF5F6, - 0xF5F7, 0xF5F8, 0xF5F9, 0xF5FA, 0xF5FB, 0xF5FC, - 0xF5FD, 0xF5FE, 0xF5FF, 0xF600, 0xF601, 0xF602, - 0xF603, 0xF604, 0xF605, 0xF606, 0xF607, 0xF608, - 0xF609, 0xF60A, 0xF60B, 0xF60C, 0xF6F4, 0xF6F5, - 0xF6F6, 0xF6F7, 0xF6F8, 0xF6F9, 0xF6FA, 0xF6FB, - 0xF6FC, 0xF6FD, 0xF6FE, 0xF6FF, 0xF700, 0xF701, - 0xF702, 0xF703, 0xF704, 0xF705, 0xF706, 0xF707, - 0xF708, 0xF709, 0xF70A, 0xF70B, 0xF70C, 0xF7F4, - 0xF7F5, 0xF7F6, 0xF7F7, 0xF7F8, 0xF7F9, 0xF7FA, - 0xF7FB, 0xF7FC, 0xF7FD, 0xF7FE, 0xF7FF, 0xF800, - 0xF801, 0xF802, 0xF803, 0xF804, 0xF805, 0xF806, - 0xF807, 0xF808, 0xF809, 0xF80A, 0xF80B, 0xF80C, - 0xF8F4, 0xF8F5, 0xF8F6, 0xF8F7, 0xF8F8, 0xF8F9, - 0xF8FA, 0xF8FB, 0xF8FC, 0xF8FD, 0xF8FE, 0xF8FF, - 0xF900, 0xF901, 0xF902, 0xF903, 0xF904, 0xF905, - 0xF906, 0xF907, 0xF908, 0xF909, 0xF90A, 0xF90B, - 0xF90C, 0xF9F4, 0xF9F5, 0xF9F6, 0xF9F7, 0xF9F8, - 0xF9F9, 0xF9FA, 0xF9FB, 0xF9FC, 0xF9FD, 0xF9FE, - 0xF9FF, 0xFA00, 0xFA01, 0xFA02, 0xFA03, 0xFA04, - 0xFA05, 0xFA06, 0xFA07, 0xFA08, 0xFA09, 0xFA0A, - 0xFA0B, 0xFA0C, 0xFAF4, 0xFAF5, 0xFAF6, 0xFAF7, - 0xFAF8, 0xFAF9, 0xFAFA, 0xFAFB, 0xFAFC, 0xFAFD, - 0xFAFE, 0xFAFF, 0xFB00, 0xFB01, 0xFB02, 0xFB03, - 0xFB04, 0xFB05, 0xFB06, 0xFB07, 0xFB08, 0xFB09, - 0xFB0A, 0xFB0B, 0xFB0C, 0xFBF4, 0xFBF5, 0xFBF6, - 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, - 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, 0xFC01, 0xFC02, - 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08, - 0xFC09, 0xFC0A, 0xFC0B, 0xFC0C, 0xFCF4, 0xFCF5, - 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, 0xFCFA, 0xFCFB, - 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, 0xFD00, 0xFD01, - 0xFD02, 0xFD03, 0xFD04, 0xFD05, 0xFD06, 0xFD07, - 0xFD08, 0xFD09, 0xFD0A, 0xFD0B, 0xFD0C, 0xFDF4, - 0xFDF5, 0xFDF6, 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, - 0xFDFB, 0xFDFC, 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, - 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, - 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, - 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8, 0xFEF9, - 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0xFEFF, - 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, - 0xFF06, 0xFF07, 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, - 0xFF0C, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, 0xFFF8, - 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, - 0xFFFF, -}; - -#define ON2AVC_CB14_CODES 729 -static const uint16_t on2avc_cb14_codes[ON2AVC_CB14_CODES] = { - 0x0000, 0x0018, 0x009C, 0x033F, 0x06CF, 0x0860, - 0x3ED2, 0x15F8, 0x0CA3, 0x15F9, 0x3ED3, 0x3ED4, - 0x3ED5, 0x03B3, 0x0336, 0x3ECF, 0x3ED0, 0x15F5, - 0x15F6, 0x3ED1, 0x1FB6, 0x15F7, 0x0D6D, 0x074E, - 0x02A4, 0x008C, 0x0017, 0x0016, 0x0024, 0x00A8, - 0x02AB, 0x043C, 0x038D, 0x15FA, 0x0CA4, 0x1FB8, - 0x15FB, 0x3ED9, 0x1FB9, 0x15FC, 0x01D8, 0x01F1, - 0x3ED6, 0x1090, 0x1FB7, 0x0D6E, 0x3ED7, 0x3ED8, - 0x074F, 0x0D6F, 0x0750, 0x01F2, 0x0098, 0x0020, - 0x0070, 0x009D, 0x00E4, 0x026F, 0x03AE, 0x055D, - 0x06D0, 0x0862, 0x0667, 0x09ED, 0x1900, 0x3EDA, - 0x1901, 0x01DE, 0x026B, 0x15FD, 0x15FE, 0x1091, - 0x15FF, 0x0D70, 0x0666, 0x0689, 0x0861, 0x034E, - 0x026E, 0x00E8, 0x008E, 0x019E, 0x01BF, 0x01F3, - 0x02B5, 0x054E, 0x0669, 0x09EE, 0x09EF, 0x0D71, - 0x0CA5, 0x1FBB, 0x1FBC, 0x3EDF, 0x02A6, 0x01CA, - 0x3EDB, 0x3EDC, 0x3EDD, 0x3EDE, 0x1FBA, 0x1092, - 0x0863, 0x0751, 0x0668, 0x038E, 0x02B4, 0x01C4, - 0x068A, 0x0CA7, 0x06D1, 0x055F, 0x043E, 0x09F0, - 0x0865, 0x0866, 0x0867, 0x0752, 0x1902, 0x3EE2, - 0x1096, 0x0278, 0x02B6, 0x3EE0, 0x1FBD, 0x3EE1, - 0x0864, 0x1FBE, 0x0CA6, 0x1093, 0x1094, 0x1095, - 0x0478, 0x043D, 0x055E, 0x3EE5, 0x0CA9, 0x066A, - 0x0D75, 0x0560, 0x0561, 0x0868, 0x0D76, 0x0CAA, - 0x0CAB, 0x3EE6, 0x3EE7, 0x3EE8, 0x02AC, 0x038F, - 0x3EE3, 0x1FBF, 0x3EE4, 0x0D72, 0x0D73, 0x0D74, - 0x09F1, 0x068B, 0x0CA8, 0x0479, 0x06D2, 0x1097, - 0x1099, 0x09F3, 0x066B, 0x06D3, 0x0CAD, 0x109A, - 0x06D4, 0x068C, 0x06D5, 0x0D79, 0x0D7A, 0x109B, - 0x1FC1, 0x02B2, 0x0396, 0x3EE9, 0x1903, 0x3EEA, - 0x1904, 0x1905, 0x1FC0, 0x09F2, 0x0D77, 0x0D78, - 0x1098, 0x0562, 0x0CAC, 0x190C, 0x109C, 0x06D6, - 0x0D7C, 0x1FC4, 0x0D7D, 0x09F4, 0x06D7, 0x09F5, - 0x3EEE, 0x0CAE, 0x0D7E, 0x3EEF, 0x03AF, 0x043F, - 0x3EEB, 0x1906, 0x1FC2, 0x1907, 0x3EEC, 0x1908, - 0x1909, 0x190A, 0x1FC3, 0x3EED, 0x0D7B, 0x190B, - 0x1FC6, 0x10A1, 0x10A2, 0x0D7F, 0x0CB0, 0x190E, - 0x0D80, 0x10A3, 0x0869, 0x190F, 0x1910, 0x10A4, - 0x10A5, 0x0753, 0x068D, 0x3EF0, 0x3EF1, 0x190D, - 0x1FC5, 0x3EF2, 0x3EF3, 0x109D, 0x109E, 0x0CAF, - 0x109F, 0x3EF4, 0x10A0, 0x10A7, 0x3EFC, 0x0CB1, - 0x09F7, 0x1911, 0x10A8, 0x09F8, 0x10A9, 0x1912, - 0x06D9, 0x09F9, 0x3EFD, 0x1913, 0x068E, 0x06D8, - 0x3EF5, 0x3EF6, 0x3EF7, 0x3EF8, 0x3EF9, 0x0D81, - 0x3EFA, 0x1FC7, 0x1FC8, 0x10A6, 0x09F6, 0x3EFB, - 0x1FCE, 0x0CB2, 0x3F02, 0x10AA, 0x3F03, 0x1FCF, - 0x10AB, 0x10AC, 0x1916, 0x3F04, 0x09FA, 0x0D83, - 0x3F05, 0x068F, 0x086A, 0x1914, 0x3EFE, 0x1FC9, - 0x1FCA, 0x3EFF, 0x0D82, 0x1FCB, 0x1FCC, 0x3F00, - 0x1FCD, 0x3F01, 0x1915, 0x3F0F, 0x1918, 0x10AD, - 0x0CB3, 0x3F10, 0x1919, 0x3F11, 0x191A, 0x1FD2, - 0x0CB4, 0x0CB5, 0x10AE, 0x191B, 0x047A, 0x06DA, - 0x3F06, 0x3F07, 0x1917, 0x3F08, 0x3F09, 0x3F0A, - 0x3F0B, 0x3F0C, 0x3F0D, 0x3F0E, 0x1FD0, 0x1FD1, - 0x3F18, 0x191F, 0x1FDA, 0x3F19, 0x3F1A, 0x10AF, - 0x3F1B, 0x10B2, 0x1FDB, 0x0D86, 0x0D87, 0x10B3, - 0x0CB6, 0x086B, 0x09FB, 0x3F12, 0x1FD3, 0x1FD4, - 0x3F13, 0x1FD5, 0x191E, 0x1FD6, 0x3F14, 0x3F15, - 0x3F16, 0x1FD7, 0x3F17, 0x033A, 0x01AA, 0x02B8, - 0x01DF, 0x02B9, 0x02BA, 0x086F, 0x03BB, 0x03B2, - 0x046A, 0x066F, 0x08DE, 0x0563, 0x046B, 0x0CB7, - 0x11BE, 0x086E, 0x066E, 0x06DB, 0x047B, 0x03BA, - 0x0A9E, 0x02B7, 0x0340, 0x0264, 0x01CE, 0x01A9, - 0x0265, 0x01A8, 0x0266, 0x02A8, 0x036F, 0x03AB, - 0x037A, 0x04FE, 0x0683, 0x06C4, 0x0C90, 0x065D, - 0x0D3C, 0x0FEC, 0x0436, 0x06C2, 0x0682, 0x0C8E, - 0x055A, 0x033B, 0x065C, 0x0348, 0x03AA, 0x0234, - 0x036E, 0x01F0, 0x01A6, 0x3E86, 0x3E87, 0x153E, - 0x3E88, 0x3E89, 0x0FEF, 0x3E8A, 0x3E8B, 0x3E8C, - 0x3E8D, 0x3E8E, 0x3E8F, 0x3E90, 0x09E4, 0x03AC, - 0x11BF, 0x1F8E, 0x1F8F, 0x0FEE, 0x3E80, 0x3E81, - 0x3E82, 0x3E83, 0x3E84, 0x3E85, 0x1F90, 0x1F91, - 0x3E95, 0x3E96, 0x0C91, 0x3E97, 0x3E98, 0x3E99, - 0x3E9A, 0x3E9B, 0x3E9C, 0x3E9D, 0x3E9E, 0x3E9F, - 0x3EA0, 0x0858, 0x04FF, 0x0FF0, 0x0FF1, 0x153F, - 0x0FF2, 0x3E91, 0x1F92, 0x3E92, 0x1F93, 0x3E93, - 0x1F94, 0x3E94, 0x0D3D, 0x3EA3, 0x1F99, 0x0FF7, - 0x0D3E, 0x3EA4, 0x1F9A, 0x15D9, 0x0D3F, 0x3EA5, - 0x3EA6, 0x3EA7, 0x0D58, 0x3EA8, 0x06C5, 0x072E, - 0x3EA1, 0x1F95, 0x1F96, 0x0C92, 0x0FF3, 0x0FF4, - 0x0FF5, 0x15D8, 0x1F97, 0x0FF6, 0x1F98, 0x3EA2, - 0x3EAC, 0x0FF9, 0x1F9C, 0x15DB, 0x1F9D, 0x15DC, - 0x0FFA, 0x1F9E, 0x3EAD, 0x3EAE, 0x3EAF, 0x3EB0, - 0x3EB1, 0x065E, 0x055B, 0x3EA9, 0x0D59, 0x15DA, - 0x0FF8, 0x3EAA, 0x0D5A, 0x3EAB, 0x0D5B, 0x0D5C, - 0x0D5D, 0x072F, 0x1F9B, 0x3EB4, 0x1FA0, 0x073C, - 0x0D5F, 0x1FA1, 0x1FA2, 0x0FFE, 0x1FA3, 0x1FA4, - 0x3EB5, 0x3EB6, 0x3EB7, 0x3EB8, 0x065F, 0x06C6, - 0x3EB2, 0x15DD, 0x0FFB, 0x3EB3, 0x1F9F, 0x0D5E, - 0x0C93, 0x0C94, 0x0FFC, 0x0FFD, 0x15DE, 0x15DF, - 0x1FA7, 0x15E1, 0x06C7, 0x0D62, 0x15E2, 0x0C96, - 0x15E3, 0x1082, 0x15E4, 0x1FA8, 0x3EBA, 0x3EBB, - 0x3EBC, 0x0660, 0x046E, 0x3EB9, 0x1FA5, 0x0FFF, - 0x1FA6, 0x1080, 0x1081, 0x0D60, 0x0C95, 0x15E0, - 0x0D61, 0x073D, 0x085A, 0x15E6, 0x09E9, 0x085B, - 0x0C97, 0x1083, 0x0C98, 0x0D63, 0x0D64, 0x0C99, - 0x15E7, 0x15E8, 0x1FAC, 0x3EBE, 0x0684, 0x037B, - 0x1FA9, 0x1FAA, 0x3EBD, 0x073E, 0x1FAB, 0x15E5, - 0x06C8, 0x09E5, 0x09E6, 0x09E7, 0x0661, 0x09E8, - 0x1FAE, 0x0C9A, 0x06CA, 0x055C, 0x0C9B, 0x3EC0, - 0x15EB, 0x1085, 0x1086, 0x15EC, 0x1087, 0x3EC1, - 0x3EC2, 0x02A9, 0x02B3, 0x1FAD, 0x15E9, 0x3EBF, - 0x15EA, 0x1084, 0x0D65, 0x0662, 0x0D66, 0x06C9, - 0x0438, 0x054A, 0x073F, 0x085D, 0x0663, 0x0439, - 0x0686, 0x06CB, 0x0C9E, 0x0C9F, 0x1088, 0x15EF, - 0x3EC6, 0x1089, 0x1FAF, 0x3EC7, 0x0349, 0x0267, - 0x3EC3, 0x3EC4, 0x15ED, 0x15EE, 0x3EC5, 0x09EA, - 0x0C9C, 0x0C9D, 0x054B, 0x0685, 0x085C, 0x09EB, - 0x01BC, 0x01DC, 0x01BE, 0x03AD, 0x038A, 0x0749, - 0x0688, 0x0665, 0x074A, 0x0CA1, 0x0D68, 0x3EC8, - 0x1FB1, 0x0236, 0x034A, 0x1FB0, 0x108A, 0x108B, - 0x0CA0, 0x0D67, 0x0687, 0x0748, 0x0664, 0x038B, - 0x023E, 0x01DA, 0x01DB, 0x006E, 0x0094, 0x00E6, - 0x033E, 0x043A, 0x06CD, 0x085E, 0x085F, 0x0D69, - 0x0D6A, 0x1FB3, 0x1FB4, 0x3ECA, 0x034B, 0x023F, - 0x3EC9, 0x108C, 0x1FB2, 0x15F0, 0x15F1, 0x074B, - 0x06CC, 0x074C, 0x038C, 0x0268, 0x0136, 0x0095, - 0x0014, 0x001E, 0x0097, 0x019C, 0x074D, 0x0D6C, - 0x06CE, 0x0CA2, 0x108E, 0x09EC, 0x3ECD, 0x108F, - 0x3ECE, 0x026A, 0x02AA, 0x3ECB, 0x1FB5, 0x15F2, - 0x3ECC, 0x15F3, 0x15F4, 0x0D6B, 0x108D, 0x043B, - 0x0269, 0x0096, 0x0022, -}; - -static const uint8_t on2avc_cb14_bits[ON2AVC_CB14_CODES] = { - 1, 5, 8, 10, 11, 12, - 14, 13, 12, 13, 14, 14, - 14, 10, 10, 14, 14, 13, - 13, 14, 13, 13, 12, 11, - 10, 8, 5, 5, 6, 8, - 10, 11, 10, 13, 12, 13, - 13, 14, 13, 13, 9, 9, - 14, 13, 13, 12, 14, 14, - 11, 12, 11, 9, 8, 6, - 7, 8, 8, 10, 10, 11, - 11, 12, 11, 12, 13, 14, - 13, 9, 10, 13, 13, 13, - 13, 12, 11, 11, 12, 10, - 10, 8, 8, 9, 9, 9, - 10, 11, 11, 12, 12, 12, - 12, 13, 13, 14, 10, 9, - 14, 14, 14, 14, 13, 13, - 12, 11, 11, 10, 10, 9, - 11, 12, 11, 11, 11, 12, - 12, 12, 12, 11, 13, 14, - 13, 10, 10, 14, 13, 14, - 12, 13, 12, 13, 13, 13, - 11, 11, 11, 14, 12, 11, - 12, 11, 11, 12, 12, 12, - 12, 14, 14, 14, 10, 10, - 14, 13, 14, 12, 12, 12, - 12, 11, 12, 11, 11, 13, - 13, 12, 11, 11, 12, 13, - 11, 11, 11, 12, 12, 13, - 13, 10, 10, 14, 13, 14, - 13, 13, 13, 12, 12, 12, - 13, 11, 12, 13, 13, 11, - 12, 13, 12, 12, 11, 12, - 14, 12, 12, 14, 10, 11, - 14, 13, 13, 13, 14, 13, - 13, 13, 13, 14, 12, 13, - 13, 13, 13, 12, 12, 13, - 12, 13, 12, 13, 13, 13, - 13, 11, 11, 14, 14, 13, - 13, 14, 14, 13, 13, 12, - 13, 14, 13, 13, 14, 12, - 12, 13, 13, 12, 13, 13, - 11, 12, 14, 13, 11, 11, - 14, 14, 14, 14, 14, 12, - 14, 13, 13, 13, 12, 14, - 13, 12, 14, 13, 14, 13, - 13, 13, 13, 14, 12, 12, - 14, 11, 12, 13, 14, 13, - 13, 14, 12, 13, 13, 14, - 13, 14, 13, 14, 13, 13, - 12, 14, 13, 14, 13, 13, - 12, 12, 13, 13, 11, 11, - 14, 14, 13, 14, 14, 14, - 14, 14, 14, 14, 13, 13, - 14, 13, 13, 14, 14, 13, - 14, 13, 13, 12, 12, 13, - 12, 12, 12, 14, 13, 13, - 14, 13, 13, 13, 14, 14, - 14, 13, 14, 10, 9, 10, - 9, 10, 10, 12, 10, 10, - 11, 11, 12, 11, 11, 12, - 13, 12, 11, 11, 11, 10, - 12, 10, 10, 10, 9, 9, - 10, 9, 10, 10, 10, 10, - 10, 11, 11, 11, 12, 11, - 12, 12, 11, 11, 11, 12, - 11, 10, 11, 10, 10, 10, - 10, 9, 9, 14, 14, 13, - 14, 14, 12, 14, 14, 14, - 14, 14, 14, 14, 12, 10, - 13, 13, 13, 12, 14, 14, - 14, 14, 14, 14, 13, 13, - 14, 14, 12, 14, 14, 14, - 14, 14, 14, 14, 14, 14, - 14, 12, 11, 12, 12, 13, - 12, 14, 13, 14, 13, 14, - 13, 14, 12, 14, 13, 12, - 12, 14, 13, 13, 12, 14, - 14, 14, 12, 14, 11, 11, - 14, 13, 13, 12, 12, 12, - 12, 13, 13, 12, 13, 14, - 14, 12, 13, 13, 13, 13, - 12, 13, 14, 14, 14, 14, - 14, 11, 11, 14, 12, 13, - 12, 14, 12, 14, 12, 12, - 12, 11, 13, 14, 13, 11, - 12, 13, 13, 12, 13, 13, - 14, 14, 14, 14, 11, 11, - 14, 13, 12, 14, 13, 12, - 12, 12, 12, 12, 13, 13, - 13, 13, 11, 12, 13, 12, - 13, 13, 13, 13, 14, 14, - 14, 11, 11, 14, 13, 12, - 13, 13, 13, 12, 12, 13, - 12, 11, 12, 13, 12, 12, - 12, 13, 12, 12, 12, 12, - 13, 13, 13, 14, 11, 10, - 13, 13, 14, 11, 13, 13, - 11, 12, 12, 12, 11, 12, - 13, 12, 11, 11, 12, 14, - 13, 13, 13, 13, 13, 14, - 14, 10, 10, 13, 13, 14, - 13, 13, 12, 11, 12, 11, - 11, 11, 11, 12, 11, 11, - 11, 11, 12, 12, 13, 13, - 14, 13, 13, 14, 10, 10, - 14, 14, 13, 13, 14, 12, - 12, 12, 11, 11, 12, 12, - 9, 9, 9, 10, 10, 11, - 11, 11, 11, 12, 12, 14, - 13, 10, 10, 13, 13, 13, - 12, 12, 11, 11, 11, 10, - 10, 9, 9, 7, 8, 8, - 10, 11, 11, 12, 12, 12, - 12, 13, 13, 14, 10, 10, - 14, 13, 13, 13, 13, 11, - 11, 11, 10, 10, 9, 8, - 5, 5, 8, 9, 11, 12, - 11, 12, 13, 12, 14, 13, - 14, 10, 10, 14, 13, 13, - 14, 13, 13, 12, 13, 11, - 10, 8, 6, -}; - -static const uint16_t on2avc_cb14_syms[ON2AVC_CB14_CODES] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, - 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, - 0x000C, 0x000D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, - 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, - 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x0101, 0x0102, - 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, - 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x01F3, - 0x01F4, 0x01F5, 0x01F6, 0x01F7, 0x01F8, 0x01F9, - 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, - 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, - 0x0206, 0x0207, 0x0208, 0x0209, 0x020A, 0x020B, - 0x020C, 0x020D, 0x02F3, 0x02F4, 0x02F5, 0x02F6, - 0x02F7, 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, - 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, - 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, - 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x03F3, - 0x03F4, 0x03F5, 0x03F6, 0x03F7, 0x03F8, 0x03F9, - 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, - 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, - 0x040C, 0x040D, 0x04F3, 0x04F4, 0x04F5, 0x04F6, - 0x04F7, 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, - 0x04FD, 0x04FE, 0x04FF, 0x0500, 0x0501, 0x0502, - 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, - 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x05F3, - 0x05F4, 0x05F5, 0x05F6, 0x05F7, 0x05F8, 0x05F9, - 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, - 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, - 0x0606, 0x0607, 0x0608, 0x0609, 0x060A, 0x060B, - 0x060C, 0x060D, 0x06F3, 0x06F4, 0x06F5, 0x06F6, - 0x06F7, 0x06F8, 0x06F9, 0x06FA, 0x06FB, 0x06FC, - 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, - 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, - 0x0709, 0x070A, 0x070B, 0x070C, 0x070D, 0x07F3, - 0x07F4, 0x07F5, 0x07F6, 0x07F7, 0x07F8, 0x07F9, - 0x07FA, 0x07FB, 0x07FC, 0x07FD, 0x07FE, 0x07FF, - 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, - 0x0806, 0x0807, 0x0808, 0x0809, 0x080A, 0x080B, - 0x080C, 0x080D, 0x08F3, 0x08F4, 0x08F5, 0x08F6, - 0x08F7, 0x08F8, 0x08F9, 0x08FA, 0x08FB, 0x08FC, - 0x08FD, 0x08FE, 0x08FF, 0x0900, 0x0901, 0x0902, - 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, - 0x0909, 0x090A, 0x090B, 0x090C, 0x090D, 0x09F3, - 0x09F4, 0x09F5, 0x09F6, 0x09F7, 0x09F8, 0x09F9, - 0x09FA, 0x09FB, 0x09FC, 0x09FD, 0x09FE, 0x09FF, - 0x0A00, 0x0A01, 0x0A02, 0x0A03, 0x0A04, 0x0A05, - 0x0A06, 0x0A07, 0x0A08, 0x0A09, 0x0A0A, 0x0A0B, - 0x0A0C, 0x0A0D, 0x0AF3, 0x0AF4, 0x0AF5, 0x0AF6, - 0x0AF7, 0x0AF8, 0x0AF9, 0x0AFA, 0x0AFB, 0x0AFC, - 0x0AFD, 0x0AFE, 0x0AFF, 0x0B00, 0x0B01, 0x0B02, - 0x0B03, 0x0B04, 0x0B05, 0x0B06, 0x0B07, 0x0B08, - 0x0B09, 0x0B0A, 0x0B0B, 0x0B0C, 0x0B0D, 0x0BF3, - 0x0BF4, 0x0BF5, 0x0BF6, 0x0BF7, 0x0BF8, 0x0BF9, - 0x0BFA, 0x0BFB, 0x0BFC, 0x0BFD, 0x0BFE, 0x0BFF, - 0x0C00, 0x0C01, 0x0C02, 0x0C03, 0x0C04, 0x0C05, - 0x0C06, 0x0C07, 0x0C08, 0x0C09, 0x0C0A, 0x0C0B, - 0x0C0C, 0x0C0D, 0x0CF3, 0x0CF4, 0x0CF5, 0x0CF6, - 0x0CF7, 0x0CF8, 0x0CF9, 0x0CFA, 0x0CFB, 0x0CFC, - 0x0CFD, 0x0CFE, 0x0CFF, 0x0D00, 0x0D01, 0x0D02, - 0x0D03, 0x0D04, 0x0D05, 0x0D06, 0x0D07, 0x0D08, - 0x0D09, 0x0D0A, 0x0D0B, 0x0D0C, 0x0D0D, 0x0DF3, - 0x0DF4, 0x0DF5, 0x0DF6, 0x0DF7, 0x0DF8, 0x0DF9, - 0x0DFA, 0x0DFB, 0x0DFC, 0x0DFD, 0x0DFE, 0x0DFF, - 0xF300, 0xF301, 0xF302, 0xF303, 0xF304, 0xF305, - 0xF306, 0xF307, 0xF308, 0xF309, 0xF30A, 0xF30B, - 0xF30C, 0xF30D, 0xF3F3, 0xF3F4, 0xF3F5, 0xF3F6, - 0xF3F7, 0xF3F8, 0xF3F9, 0xF3FA, 0xF3FB, 0xF3FC, - 0xF3FD, 0xF3FE, 0xF3FF, 0xF400, 0xF401, 0xF402, - 0xF403, 0xF404, 0xF405, 0xF406, 0xF407, 0xF408, - 0xF409, 0xF40A, 0xF40B, 0xF40C, 0xF40D, 0xF4F3, - 0xF4F4, 0xF4F5, 0xF4F6, 0xF4F7, 0xF4F8, 0xF4F9, - 0xF4FA, 0xF4FB, 0xF4FC, 0xF4FD, 0xF4FE, 0xF4FF, - 0xF500, 0xF501, 0xF502, 0xF503, 0xF504, 0xF505, - 0xF506, 0xF507, 0xF508, 0xF509, 0xF50A, 0xF50B, - 0xF50C, 0xF50D, 0xF5F3, 0xF5F4, 0xF5F5, 0xF5F6, - 0xF5F7, 0xF5F8, 0xF5F9, 0xF5FA, 0xF5FB, 0xF5FC, - 0xF5FD, 0xF5FE, 0xF5FF, 0xF600, 0xF601, 0xF602, - 0xF603, 0xF604, 0xF605, 0xF606, 0xF607, 0xF608, - 0xF609, 0xF60A, 0xF60B, 0xF60C, 0xF60D, 0xF6F3, - 0xF6F4, 0xF6F5, 0xF6F6, 0xF6F7, 0xF6F8, 0xF6F9, - 0xF6FA, 0xF6FB, 0xF6FC, 0xF6FD, 0xF6FE, 0xF6FF, - 0xF700, 0xF701, 0xF702, 0xF703, 0xF704, 0xF705, - 0xF706, 0xF707, 0xF708, 0xF709, 0xF70A, 0xF70B, - 0xF70C, 0xF70D, 0xF7F3, 0xF7F4, 0xF7F5, 0xF7F6, - 0xF7F7, 0xF7F8, 0xF7F9, 0xF7FA, 0xF7FB, 0xF7FC, - 0xF7FD, 0xF7FE, 0xF7FF, 0xF800, 0xF801, 0xF802, - 0xF803, 0xF804, 0xF805, 0xF806, 0xF807, 0xF808, - 0xF809, 0xF80A, 0xF80B, 0xF80C, 0xF80D, 0xF8F3, - 0xF8F4, 0xF8F5, 0xF8F6, 0xF8F7, 0xF8F8, 0xF8F9, - 0xF8FA, 0xF8FB, 0xF8FC, 0xF8FD, 0xF8FE, 0xF8FF, - 0xF900, 0xF901, 0xF902, 0xF903, 0xF904, 0xF905, - 0xF906, 0xF907, 0xF908, 0xF909, 0xF90A, 0xF90B, - 0xF90C, 0xF90D, 0xF9F3, 0xF9F4, 0xF9F5, 0xF9F6, - 0xF9F7, 0xF9F8, 0xF9F9, 0xF9FA, 0xF9FB, 0xF9FC, - 0xF9FD, 0xF9FE, 0xF9FF, 0xFA00, 0xFA01, 0xFA02, - 0xFA03, 0xFA04, 0xFA05, 0xFA06, 0xFA07, 0xFA08, - 0xFA09, 0xFA0A, 0xFA0B, 0xFA0C, 0xFA0D, 0xFAF3, - 0xFAF4, 0xFAF5, 0xFAF6, 0xFAF7, 0xFAF8, 0xFAF9, - 0xFAFA, 0xFAFB, 0xFAFC, 0xFAFD, 0xFAFE, 0xFAFF, - 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0xFB05, - 0xFB06, 0xFB07, 0xFB08, 0xFB09, 0xFB0A, 0xFB0B, - 0xFB0C, 0xFB0D, 0xFBF3, 0xFBF4, 0xFBF5, 0xFBF6, - 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, - 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, 0xFC01, 0xFC02, - 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08, - 0xFC09, 0xFC0A, 0xFC0B, 0xFC0C, 0xFC0D, 0xFCF3, - 0xFCF4, 0xFCF5, 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, - 0xFCFA, 0xFCFB, 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, - 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04, 0xFD05, - 0xFD06, 0xFD07, 0xFD08, 0xFD09, 0xFD0A, 0xFD0B, - 0xFD0C, 0xFD0D, 0xFDF3, 0xFDF4, 0xFDF5, 0xFDF6, - 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, - 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, 0xFE01, 0xFE02, - 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, - 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFEF3, - 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8, 0xFEF9, - 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0xFEFF, - 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, - 0xFF06, 0xFF07, 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, - 0xFF0C, 0xFF0D, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, - 0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, - 0xFFFD, 0xFFFE, 0xFFFF, -}; - -#define ON2AVC_CB15_CODES 1089 -static const uint16_t on2avc_cb15_codes[ON2AVC_CB15_CODES] = { - 0x00000, 0x0000A, 0x00064, 0x00104, 0x0034B, 0x0047B, - 0x007D7, 0x00E14, 0x00957, 0x021FD, 0x013B0, 0x03F08, - 0x07A01, 0x0E579, 0x00E15, 0x013A1, 0x003A2, 0x00397, - 0x0137F, 0x01F96, 0x021FC, 0x034CD, 0x01E97, 0x01A82, - 0x013A0, 0x01A83, 0x0089D, 0x00F6B, 0x0076C, 0x0026A, - 0x00118, 0x0006E, 0x00008, 0x0000B, 0x00015, 0x00076, - 0x000EC, 0x001D2, 0x003A6, 0x00716, 0x00726, 0x01F98, - 0x00E77, 0x01BF0, 0x01A84, 0x021FE, 0x021FF, 0x00D93, - 0x01A85, 0x0036E, 0x003B4, 0x00FFE, 0x00FDF, 0x07A02, - 0x065AF, 0x01E98, 0x01F97, 0x00E16, 0x00F30, 0x00CF0, - 0x00846, 0x00398, 0x0020F, 0x000EB, 0x00074, 0x00012, - 0x0007C, 0x00049, 0x0009C, 0x00136, 0x00344, 0x0026D, - 0x0076E, 0x00847, 0x00F6C, 0x00958, 0x01A86, 0x00F6D, - 0x013A3, 0x013B1, 0x009F8, 0x00F31, 0x0032F, 0x00268, - 0x00FE0, 0x0076D, 0x01F99, 0x013A2, 0x03D05, 0x0111A, - 0x00FFF, 0x00CF1, 0x0080D, 0x004FA, 0x0040B, 0x0023E, - 0x0011B, 0x0008E, 0x00077, 0x0010A, 0x000F8, 0x001B0, - 0x001D4, 0x003D9, 0x004C6, 0x006AE, 0x007DE, 0x0080E, - 0x00F33, 0x00E78, 0x01BF1, 0x0111B, 0x034CE, 0x00959, - 0x0111C, 0x00262, 0x001FA, 0x00F32, 0x00FE1, 0x02200, - 0x01F9A, 0x013A4, 0x00E17, 0x00FE2, 0x004B7, 0x00FE3, - 0x00717, 0x00453, 0x00366, 0x001C6, 0x0011A, 0x0010E, - 0x0032B, 0x0023F, 0x00345, 0x0035A, 0x0036F, 0x007B6, - 0x00E19, 0x00705, 0x0076F, 0x0111D, 0x00E79, 0x00D57, - 0x01BF4, 0x01A87, 0x0095B, 0x0095C, 0x00216, 0x0039A, - 0x00F34, 0x0095A, 0x01BF2, 0x01BF3, 0x01000, 0x00F6E, - 0x00F6F, 0x00E18, 0x007DF, 0x008F1, 0x007BE, 0x003BD, - 0x003EB, 0x00342, 0x0022D, 0x00772, 0x007BF, 0x00454, - 0x00455, 0x0071E, 0x004FB, 0x00727, 0x0080F, 0x009E7, - 0x00E7C, 0x01BF6, 0x01A89, 0x01001, 0x01BF7, 0x0089E, - 0x00E1A, 0x0027F, 0x00334, 0x00F35, 0x00F36, 0x01BF5, - 0x01F9B, 0x013A5, 0x00E7A, 0x0095D, 0x00D58, 0x00E7B, - 0x01A88, 0x00FE4, 0x006CE, 0x0040E, 0x00687, 0x006D2, - 0x00E1C, 0x00706, 0x00747, 0x006B6, 0x0084E, 0x00CF2, - 0x006F2, 0x00D59, 0x00CF3, 0x01004, 0x013A6, 0x00F71, - 0x01A8B, 0x01E99, 0x00D5A, 0x00D94, 0x00335, 0x0022E, - 0x0095E, 0x00E1B, 0x01A8A, 0x01BF8, 0x01BF9, 0x01002, - 0x009F9, 0x00F70, 0x01003, 0x00773, 0x00F37, 0x00812, - 0x004D2, 0x004A3, 0x0089F, 0x013A9, 0x013AA, 0x00813, - 0x0081E, 0x00707, 0x008A0, 0x00E1E, 0x00D95, 0x008F2, - 0x009FB, 0x00E7D, 0x00E7E, 0x00F39, 0x01F9C, 0x00CF4, - 0x00F75, 0x00346, 0x0026E, 0x01005, 0x00F72, 0x013A7, - 0x0111E, 0x01BFA, 0x00F73, 0x013A8, 0x00F38, 0x00F74, - 0x009FA, 0x00FE5, 0x0084F, 0x0095F, 0x00E1D, 0x009EA, - 0x01A8D, 0x00E20, 0x00E21, 0x007CE, 0x00D96, 0x01008, - 0x00E22, 0x00960, 0x01121, 0x00E7F, 0x01122, 0x01A8E, - 0x01BFB, 0x01A8F, 0x008A1, 0x01009, 0x0035F, 0x00368, - 0x013B2, 0x01A8C, 0x01F9D, 0x02201, 0x01006, 0x0111F, - 0x013AB, 0x013AC, 0x01120, 0x00F76, 0x01007, 0x009FC, - 0x008F3, 0x00E1F, 0x01E9A, 0x01F9F, 0x013B3, 0x00F3B, - 0x00F77, 0x00F78, 0x00FE7, 0x009FD, 0x00FE8, 0x01123, - 0x00D97, 0x01BFF, 0x00E80, 0x01A93, 0x01124, 0x00D9E, - 0x00D5B, 0x003DA, 0x003A7, 0x00961, 0x01BFC, 0x01F9E, - 0x01BFD, 0x01BFE, 0x01A90, 0x01A91, 0x013AD, 0x00F3A, - 0x01A92, 0x00FE6, 0x00962, 0x0085E, 0x00963, 0x013AE, - 0x03D06, 0x01C01, 0x013B5, 0x00965, 0x01FA2, 0x02202, - 0x009FE, 0x00F79, 0x00F7A, 0x00E23, 0x00E26, 0x00966, - 0x013B1, 0x01E9C, 0x00F7B, 0x008A2, 0x003FE, 0x003AB, - 0x00964, 0x013B4, 0x01C00, 0x01E9B, 0x01FA0, 0x01FA1, - 0x0100A, 0x013AF, 0x03F09, 0x00E81, 0x01A94, 0x01125, - 0x01126, 0x01A95, 0x013B0, 0x03D08, 0x01E9E, 0x01FA3, - 0x013B4, 0x01A99, 0x0100B, 0x013B9, 0x00F3E, 0x00967, - 0x00E27, 0x0100C, 0x01E9F, 0x00968, 0x01C05, 0x00F3F, - 0x00E82, 0x0039B, 0x00386, 0x01A96, 0x01C02, 0x03D07, - 0x013B6, 0x01C03, 0x01E9D, 0x01127, 0x01A97, 0x01C04, - 0x013B2, 0x013B3, 0x013B7, 0x01A98, 0x013B8, 0x03F0A, - 0x0E57A, 0x07A03, 0x013BB, 0x01FA4, 0x01A9C, 0x01FA5, - 0x01FA6, 0x013BC, 0x0100D, 0x01FA7, 0x013B5, 0x0100E, - 0x01A9D, 0x0100F, 0x0096A, 0x01128, 0x00328, 0x003FF, - 0x00969, 0x01EA0, 0x01C06, 0x013BA, 0x01A9A, 0x034CF, - 0x00F7C, 0x02203, 0x034D2, 0x01EA1, 0x01C07, 0x02204, - 0x01A9B, 0x01EA2, 0x06982, 0x03D09, 0x0E57B, 0x01FA8, - 0x013C2, 0x013C3, 0x01129, 0x01FA9, 0x0112A, 0x01010, - 0x01FAA, 0x01EA6, 0x03F0F, 0x013B6, 0x00CF5, 0x0072A, - 0x00F7D, 0x00340, 0x0025F, 0x02205, 0x02206, 0x06983, - 0x01C08, 0x013BD, 0x013BE, 0x01EA3, 0x013BF, 0x034D3, - 0x01EA4, 0x02207, 0x01A9E, 0x01EA5, 0x03F0B, 0x03F0E, - 0x01AA2, 0x00E00, 0x00E3E, 0x00D9F, 0x00D5F, 0x00CF7, - 0x00CFE, 0x01011, 0x00E85, 0x00E01, 0x00E02, 0x0096B, - 0x00CFF, 0x00F92, 0x00D6E, 0x008CA, 0x00359, 0x00456, - 0x01CAE, 0x03D0A, 0x01A9F, 0x0112B, 0x00E83, 0x013B7, - 0x00F7E, 0x009FF, 0x00E84, 0x00FE9, 0x009EB, 0x00F7F, - 0x008A3, 0x00D5E, 0x00CF6, 0x0112E, 0x0112F, 0x01016, - 0x00F93, 0x01FAE, 0x00FEA, 0x00FEB, 0x009A6, 0x00E03, - 0x01C0A, 0x01017, 0x01C0B, 0x01FAF, 0x00F9E, 0x013BB, - 0x0196A, 0x0039C, 0x003F6, 0x0379A, 0x03D0B, 0x01FAB, - 0x01EA7, 0x013B8, 0x01012, 0x01AA3, 0x01C09, 0x013B9, - 0x01013, 0x00CB4, 0x00E86, 0x01F3E, 0x013BA, 0x00E87, - 0x007FB, 0x003CF, 0x0037A, 0x003AD, 0x00387, 0x0038A, - 0x003B5, 0x0039E, 0x0026F, 0x0038B, 0x00272, 0x0039F, - 0x00399, 0x0038E, 0x00252, 0x0039A, 0x00018, 0x0001B, - 0x003CE, 0x00457, 0x003E8, 0x0067E, 0x0041A, 0x003BE, - 0x003BF, 0x003EE, 0x00437, 0x0039D, 0x003AC, 0x00464, - 0x003C6, 0x003C7, 0x0041B, 0x007F6, 0x0042E, 0x0025C, - 0x0038C, 0x003BA, 0x003E9, 0x003EA, 0x00271, 0x003BB, - 0x0026A, 0x0025D, 0x0025E, 0x00389, 0x003EE, 0x004F4, - 0x00415, 0x0001A, 0x00017, 0x00388, 0x0038E, 0x003FC, - 0x00270, 0x00378, 0x0038A, 0x003AE, 0x003AA, 0x00398, - 0x003E8, 0x00358, 0x00414, 0x00384, 0x003B8, 0x006D3, - 0x01A6B, 0x00FEA, 0x01BCE, 0x009E4, 0x00E56, 0x01BCF, - 0x0131D, 0x009E5, 0x01BD8, 0x01BD9, 0x034C0, 0x01F86, - 0x01A6C, 0x01F3F, 0x065AC, 0x072BE, 0x00436, 0x0022C, - 0x009E0, 0x00F54, 0x009E2, 0x01104, 0x01105, 0x00FE8, - 0x009E3, 0x00FE9, 0x00F55, 0x0131C, 0x01A68, 0x01A6A, - 0x00E06, 0x01106, 0x01BCC, 0x00E6E, 0x00E3F, 0x00CB7, - 0x00F28, 0x00702, 0x0094E, 0x00F29, 0x00FEC, 0x00F2A, - 0x0131E, 0x00F56, 0x0131F, 0x00F57, 0x0110A, 0x0134E, - 0x01E86, 0x00712, 0x001F6, 0x0081F, 0x00D6F, 0x00FEB, - 0x01107, 0x00CB6, 0x0094C, 0x01BDA, 0x01108, 0x01109, - 0x009E6, 0x00E6C, 0x01F88, 0x00E6D, 0x00896, 0x0094D, - 0x03F00, 0x01E88, 0x0217C, 0x03F01, 0x03F02, 0x01399, - 0x01E89, 0x0E578, 0x0139A, 0x01E8A, 0x01F8A, 0x01F8B, - 0x01E8B, 0x03D02, 0x01F8C, 0x0139B, 0x00392, 0x0035E, - 0x00F58, 0x009DE, 0x0094F, 0x01358, 0x01359, 0x0135A, - 0x0134F, 0x01BDB, 0x0135B, 0x0379B, 0x01F89, 0x01398, - 0x034C2, 0x065AD, 0x01E87, 0x03F04, 0x07A00, 0x0217D, - 0x01A6D, 0x065AE, 0x01E8C, 0x0217E, 0x01BDD, 0x0135C, - 0x01A6E, 0x034C4, 0x01E8D, 0x03F05, 0x01E8E, 0x0217F, - 0x0139D, 0x003F7, 0x0032C, 0x034C3, 0x00E07, 0x0110B, - 0x009E7, 0x00F59, 0x03D03, 0x00D8A, 0x01F8D, 0x00E6F, - 0x00FED, 0x03F03, 0x00FEE, 0x01BDC, 0x0139C, 0x072BF, - 0x03F06, 0x021F2, 0x01A70, 0x021F3, 0x0135E, 0x0139E, - 0x01F8E, 0x01F8F, 0x0139F, 0x01E91, 0x013A0, 0x0135F, - 0x034C6, 0x0110E, 0x01A71, 0x021F4, 0x0026C, 0x00206, - 0x0110C, 0x009E8, 0x01BDE, 0x00F5A, 0x00FEF, 0x0135D, - 0x00FF0, 0x01E8F, 0x021F0, 0x009E9, 0x01E90, 0x021F1, - 0x01A6F, 0x0110D, 0x034C5, 0x021F5, 0x01A73, 0x01BE2, - 0x01BE3, 0x01F91, 0x01A74, 0x00E70, 0x021F6, 0x034C8, - 0x00FF3, 0x01F92, 0x013A1, 0x013A2, 0x013A3, 0x01A75, - 0x01372, 0x003BC, 0x00341, 0x034C7, 0x00950, 0x00FF1, - 0x00FF2, 0x009EA, 0x00F5B, 0x01370, 0x01BDF, 0x01371, - 0x01A72, 0x01BE0, 0x009EB, 0x01F90, 0x0110F, 0x01BE1, - 0x01E92, 0x013A6, 0x00D8B, 0x00FD8, 0x01BE5, 0x00FF4, - 0x00FF5, 0x01BE6, 0x013A7, 0x00F5F, 0x01BE7, 0x021F7, - 0x021F8, 0x034C9, 0x009EC, 0x013A8, 0x003EF, 0x00269, - 0x00CD8, 0x00FD6, 0x00F5C, 0x013A4, 0x00F5D, 0x00F2B, - 0x00E08, 0x01110, 0x01BE4, 0x00E09, 0x013A5, 0x00F2C, - 0x00898, 0x00F5E, 0x01A76, 0x013A9, 0x00D8C, 0x009DF, - 0x009E0, 0x00FF8, 0x00D8D, 0x01374, 0x01A78, 0x01112, - 0x01BE8, 0x01A79, 0x01F93, 0x01113, 0x01375, 0x00F61, - 0x01376, 0x00399, 0x0027C, 0x009ED, 0x00F60, 0x01373, - 0x01A77, 0x00951, 0x009EE, 0x00D50, 0x00CD9, 0x00FF6, - 0x00FD9, 0x00FF7, 0x00899, 0x007C8, 0x00D52, 0x01111, - 0x009EF, 0x007D3, 0x007D4, 0x0071E, 0x00CDB, 0x00746, - 0x00E0A, 0x00E0B, 0x021F9, 0x00FF9, 0x01A7A, 0x00952, - 0x013AB, 0x01377, 0x009F0, 0x01E93, 0x003AF, 0x0032E, - 0x009E1, 0x007CA, 0x013AA, 0x01114, 0x00F62, 0x00E71, - 0x008CB, 0x008CC, 0x0089A, 0x008CD, 0x00840, 0x00CDA, - 0x007D2, 0x009E2, 0x00E72, 0x00F63, 0x006D6, 0x00841, - 0x0079E, 0x00D53, 0x008CE, 0x00955, 0x00E0C, 0x0137A, - 0x00E74, 0x01115, 0x01F94, 0x01116, 0x01BEA, 0x00E0D, - 0x01A7B, 0x0038D, 0x0033E, 0x00CDC, 0x00D8E, 0x01BE9, - 0x01378, 0x01379, 0x00FDA, 0x00E73, 0x00953, 0x00954, - 0x009E3, 0x004D6, 0x007B7, 0x007BA, 0x007BB, 0x004A0, - 0x0089B, 0x006D7, 0x0047A, 0x00408, 0x007F7, 0x00E0E, - 0x009E4, 0x007D5, 0x00842, 0x00D90, 0x009F1, 0x034CA, - 0x01A7C, 0x01A7D, 0x00E0F, 0x01A7E, 0x00329, 0x0021E, - 0x00F64, 0x01117, 0x021FA, 0x01118, 0x013AC, 0x013AD, - 0x00D8F, 0x008CF, 0x008F0, 0x0071F, 0x004A1, 0x00686, - 0x00426, 0x00416, 0x007CB, 0x003D8, 0x00264, 0x00347, - 0x003DC, 0x004F6, 0x004D7, 0x00F2D, 0x00F65, 0x009F3, - 0x00FDB, 0x00E75, 0x009F4, 0x0137B, 0x013AE, 0x009E5, - 0x00E10, 0x0027E, 0x0020C, 0x00FFA, 0x00956, 0x01BEB, - 0x01E94, 0x01E95, 0x00D91, 0x009F2, 0x00D54, 0x007BC, - 0x007BD, 0x0040A, 0x00385, 0x0036A, 0x0022F, 0x0020E, - 0x000FC, 0x000F2, 0x001AE, 0x001C8, 0x0034A, 0x004F7, - 0x00452, 0x00CDE, 0x00843, 0x00E76, 0x00F2E, 0x00F67, - 0x0137C, 0x01A7F, 0x0080C, 0x00FDC, 0x0021A, 0x001FC, - 0x00E11, 0x009F5, 0x01BEC, 0x00F66, 0x013AF, 0x00CDD, - 0x00E12, 0x00D55, 0x00703, 0x0080A, 0x00394, 0x00265, - 0x001F6, 0x001B6, 0x0010C, 0x00078, 0x0004C, 0x000CC, - 0x001A4, 0x00212, 0x00396, 0x006C4, 0x0089C, 0x00CDF, - 0x01A80, 0x00F68, 0x00FFD, 0x0137D, 0x01F95, 0x00845, - 0x00E13, 0x00267, 0x00266, 0x00FFB, 0x009F6, 0x03D04, - 0x01BED, 0x01BEE, 0x034CB, 0x00FFC, 0x00844, 0x007D6, - 0x00704, 0x003C8, 0x0032A, 0x00130, 0x000CE, 0x00048, - 0x0000C, 0x00014, 0x0007A, 0x000F0, 0x001E6, 0x00417, - 0x004A2, 0x004B6, 0x00D92, 0x01A81, 0x009F7, 0x0137E, - 0x01E96, 0x03F07, 0x009E6, 0x00FDE, 0x003C9, 0x00268, - 0x00F2F, 0x00D56, 0x021FB, 0x034CC, 0x01BEF, 0x00F69, - 0x01119, 0x00F6A, 0x00FDD, 0x007FA, 0x003E6, 0x001E2, - 0x000EA, 0x00072, 0x00016, -}; - -static const uint8_t on2avc_cb15_bits[ON2AVC_CB15_CODES] = { - 2, 5, 7, 9, 10, 11, - 12, 12, 13, 14, 14, 14, - 16, 17, 12, 13, 11, 11, - 13, 13, 14, 14, 14, 13, - 13, 13, 12, 13, 12, 10, - 9, 7, 5, 5, 5, 7, - 9, 10, 11, 11, 12, 13, - 13, 13, 13, 14, 14, 12, - 13, 10, 11, 13, 12, 16, - 15, 14, 13, 12, 12, 12, - 12, 11, 10, 9, 7, 5, - 7, 8, 8, 9, 10, 11, - 12, 12, 13, 13, 13, 13, - 13, 14, 13, 12, 10, 10, - 12, 12, 13, 13, 15, 13, - 13, 12, 12, 11, 11, 10, - 9, 8, 7, 9, 9, 9, - 9, 10, 11, 11, 12, 12, - 12, 13, 13, 13, 14, 13, - 13, 10, 10, 12, 12, 14, - 13, 13, 12, 12, 12, 12, - 11, 11, 10, 10, 9, 9, - 10, 10, 10, 10, 10, 11, - 12, 12, 12, 13, 13, 12, - 13, 13, 13, 13, 10, 10, - 12, 13, 13, 13, 13, 13, - 13, 12, 12, 12, 11, 11, - 10, 10, 10, 12, 11, 11, - 11, 11, 11, 12, 12, 12, - 13, 13, 13, 13, 13, 12, - 12, 10, 10, 12, 12, 13, - 13, 13, 13, 13, 12, 13, - 13, 12, 11, 11, 11, 11, - 12, 12, 12, 11, 12, 12, - 11, 12, 12, 13, 13, 13, - 13, 14, 12, 12, 10, 10, - 13, 12, 13, 13, 13, 13, - 13, 13, 13, 12, 12, 12, - 12, 12, 12, 13, 13, 12, - 12, 12, 12, 12, 12, 12, - 13, 13, 13, 12, 13, 12, - 13, 10, 11, 13, 13, 13, - 13, 13, 13, 13, 12, 13, - 13, 12, 12, 13, 12, 12, - 13, 12, 12, 12, 12, 13, - 12, 13, 13, 13, 13, 13, - 13, 13, 12, 13, 10, 10, - 14, 13, 13, 14, 13, 13, - 13, 13, 13, 13, 13, 13, - 12, 12, 14, 13, 14, 12, - 13, 13, 12, 13, 12, 13, - 12, 13, 13, 13, 13, 12, - 12, 10, 11, 13, 13, 13, - 13, 13, 13, 13, 13, 12, - 13, 12, 13, 12, 13, 13, - 15, 13, 14, 13, 13, 14, - 13, 13, 13, 12, 12, 13, - 13, 14, 13, 12, 10, 10, - 13, 14, 13, 14, 13, 13, - 13, 13, 14, 13, 13, 13, - 13, 13, 13, 15, 14, 13, - 13, 13, 13, 14, 12, 13, - 12, 13, 14, 13, 13, 12, - 13, 10, 11, 13, 13, 15, - 14, 13, 14, 13, 13, 13, - 13, 13, 14, 13, 14, 14, - 17, 16, 14, 13, 13, 13, - 13, 14, 13, 13, 13, 13, - 13, 13, 13, 13, 10, 10, - 13, 14, 13, 14, 13, 14, - 13, 14, 14, 14, 13, 14, - 13, 14, 15, 15, 17, 13, - 14, 14, 13, 13, 13, 13, - 13, 14, 14, 13, 12, 12, - 13, 10, 11, 14, 14, 15, - 13, 14, 14, 14, 14, 14, - 14, 14, 13, 14, 14, 14, - 13, 13, 12, 12, 12, 12, - 12, 13, 13, 13, 13, 13, - 12, 13, 12, 12, 10, 11, - 14, 15, 13, 13, 13, 13, - 13, 13, 13, 12, 12, 13, - 12, 12, 12, 13, 13, 13, - 13, 13, 12, 12, 13, 13, - 13, 13, 13, 13, 13, 13, - 13, 10, 11, 14, 15, 13, - 14, 13, 13, 13, 13, 13, - 13, 12, 13, 14, 13, 13, - 11, 11, 10, 10, 11, 11, - 11, 10, 11, 11, 11, 10, - 11, 11, 11, 11, 5, 6, - 11, 11, 11, 11, 11, 11, - 11, 10, 11, 10, 10, 11, - 11, 11, 11, 11, 11, 11, - 10, 11, 10, 10, 11, 11, - 11, 11, 11, 11, 11, 11, - 11, 6, 5, 11, 10, 10, - 11, 10, 10, 10, 10, 10, - 10, 10, 11, 11, 11, 11, - 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 14, 13, - 13, 14, 15, 16, 11, 10, - 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, - 12, 13, 13, 13, 12, 12, - 12, 12, 13, 12, 13, 12, - 13, 13, 13, 13, 13, 14, - 14, 11, 10, 12, 12, 13, - 13, 12, 13, 13, 13, 13, - 13, 13, 13, 13, 12, 13, - 14, 14, 14, 14, 14, 14, - 14, 17, 14, 14, 13, 13, - 14, 15, 13, 14, 11, 10, - 13, 12, 13, 13, 13, 13, - 14, 13, 13, 14, 13, 14, - 14, 15, 14, 14, 16, 14, - 13, 15, 14, 14, 13, 13, - 13, 14, 14, 14, 14, 14, - 14, 11, 10, 14, 12, 13, - 13, 13, 15, 12, 13, 13, - 13, 14, 13, 13, 14, 16, - 14, 14, 13, 14, 13, 14, - 13, 13, 14, 14, 14, 13, - 14, 13, 13, 14, 11, 10, - 13, 13, 13, 13, 13, 13, - 13, 14, 14, 13, 14, 14, - 13, 13, 14, 14, 13, 13, - 13, 13, 13, 13, 14, 14, - 13, 13, 14, 14, 14, 13, - 13, 11, 10, 14, 13, 13, - 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, - 14, 14, 12, 12, 13, 13, - 13, 13, 14, 13, 13, 14, - 14, 14, 13, 14, 10, 10, - 12, 12, 13, 14, 13, 12, - 12, 13, 13, 12, 14, 12, - 12, 13, 13, 14, 12, 12, - 12, 13, 12, 13, 13, 13, - 13, 13, 13, 13, 13, 13, - 13, 10, 10, 13, 13, 13, - 13, 13, 13, 12, 12, 13, - 12, 13, 12, 12, 12, 13, - 13, 12, 12, 12, 12, 12, - 12, 12, 14, 13, 13, 13, - 14, 13, 13, 14, 10, 10, - 12, 12, 14, 13, 13, 13, - 12, 12, 12, 12, 12, 12, - 12, 12, 13, 13, 11, 12, - 11, 12, 12, 13, 12, 13, - 13, 13, 13, 13, 13, 12, - 13, 10, 10, 12, 12, 13, - 13, 13, 12, 13, 13, 13, - 12, 12, 11, 11, 11, 12, - 12, 11, 11, 11, 11, 12, - 12, 12, 12, 12, 13, 14, - 13, 13, 12, 13, 10, 10, - 13, 13, 14, 13, 14, 14, - 12, 12, 12, 12, 12, 11, - 11, 11, 12, 10, 10, 10, - 10, 11, 12, 12, 13, 13, - 12, 13, 13, 13, 14, 12, - 12, 10, 10, 13, 13, 13, - 14, 14, 12, 13, 12, 11, - 11, 11, 11, 10, 10, 10, - 9, 9, 9, 10, 10, 11, - 11, 12, 12, 13, 12, 13, - 13, 13, 12, 12, 10, 10, - 12, 13, 13, 13, 14, 12, - 12, 12, 12, 12, 11, 10, - 9, 9, 9, 7, 8, 8, - 9, 10, 11, 11, 12, 12, - 13, 13, 13, 13, 13, 12, - 12, 10, 10, 13, 13, 15, - 13, 13, 14, 13, 12, 12, - 12, 10, 10, 9, 8, 8, - 5, 5, 7, 9, 10, 11, - 12, 12, 12, 13, 13, 13, - 14, 14, 12, 12, 10, 11, - 12, 12, 14, 14, 13, 13, - 13, 13, 12, 11, 11, 10, - 9, 7, 5, -}; - -static const uint16_t on2avc_cb15_syms[ON2AVC_CB15_CODES] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, - 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, - 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x00F0, - 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, - 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, - 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x0101, 0x0102, - 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, - 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, - 0x010F, 0x0110, 0x01F0, 0x01F1, 0x01F2, 0x01F3, - 0x01F4, 0x01F5, 0x01F6, 0x01F7, 0x01F8, 0x01F9, - 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, - 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, - 0x0206, 0x0207, 0x0208, 0x0209, 0x020A, 0x020B, - 0x020C, 0x020D, 0x020E, 0x020F, 0x0210, 0x02F0, - 0x02F1, 0x02F2, 0x02F3, 0x02F4, 0x02F5, 0x02F6, - 0x02F7, 0x02F8, 0x02F9, 0x02FA, 0x02FB, 0x02FC, - 0x02FD, 0x02FE, 0x02FF, 0x0300, 0x0301, 0x0302, - 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, - 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, - 0x030F, 0x0310, 0x03F0, 0x03F1, 0x03F2, 0x03F3, - 0x03F4, 0x03F5, 0x03F6, 0x03F7, 0x03F8, 0x03F9, - 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, - 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, - 0x040C, 0x040D, 0x040E, 0x040F, 0x0410, 0x04F0, - 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, - 0x04F7, 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, - 0x04FD, 0x04FE, 0x04FF, 0x0500, 0x0501, 0x0502, - 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, - 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, - 0x050F, 0x0510, 0x05F0, 0x05F1, 0x05F2, 0x05F3, - 0x05F4, 0x05F5, 0x05F6, 0x05F7, 0x05F8, 0x05F9, - 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, - 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, - 0x0606, 0x0607, 0x0608, 0x0609, 0x060A, 0x060B, - 0x060C, 0x060D, 0x060E, 0x060F, 0x0610, 0x06F0, - 0x06F1, 0x06F2, 0x06F3, 0x06F4, 0x06F5, 0x06F6, - 0x06F7, 0x06F8, 0x06F9, 0x06FA, 0x06FB, 0x06FC, - 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, - 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, - 0x0709, 0x070A, 0x070B, 0x070C, 0x070D, 0x070E, - 0x070F, 0x0710, 0x07F0, 0x07F1, 0x07F2, 0x07F3, - 0x07F4, 0x07F5, 0x07F6, 0x07F7, 0x07F8, 0x07F9, - 0x07FA, 0x07FB, 0x07FC, 0x07FD, 0x07FE, 0x07FF, - 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, - 0x0806, 0x0807, 0x0808, 0x0809, 0x080A, 0x080B, - 0x080C, 0x080D, 0x080E, 0x080F, 0x0810, 0x08F0, - 0x08F1, 0x08F2, 0x08F3, 0x08F4, 0x08F5, 0x08F6, - 0x08F7, 0x08F8, 0x08F9, 0x08FA, 0x08FB, 0x08FC, - 0x08FD, 0x08FE, 0x08FF, 0x0900, 0x0901, 0x0902, - 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, - 0x0909, 0x090A, 0x090B, 0x090C, 0x090D, 0x090E, - 0x090F, 0x0910, 0x09F0, 0x09F1, 0x09F2, 0x09F3, - 0x09F4, 0x09F5, 0x09F6, 0x09F7, 0x09F8, 0x09F9, - 0x09FA, 0x09FB, 0x09FC, 0x09FD, 0x09FE, 0x09FF, - 0x0A00, 0x0A01, 0x0A02, 0x0A03, 0x0A04, 0x0A05, - 0x0A06, 0x0A07, 0x0A08, 0x0A09, 0x0A0A, 0x0A0B, - 0x0A0C, 0x0A0D, 0x0A0E, 0x0A0F, 0x0A10, 0x0AF0, - 0x0AF1, 0x0AF2, 0x0AF3, 0x0AF4, 0x0AF5, 0x0AF6, - 0x0AF7, 0x0AF8, 0x0AF9, 0x0AFA, 0x0AFB, 0x0AFC, - 0x0AFD, 0x0AFE, 0x0AFF, 0x0B00, 0x0B01, 0x0B02, - 0x0B03, 0x0B04, 0x0B05, 0x0B06, 0x0B07, 0x0B08, - 0x0B09, 0x0B0A, 0x0B0B, 0x0B0C, 0x0B0D, 0x0B0E, - 0x0B0F, 0x0B10, 0x0BF0, 0x0BF1, 0x0BF2, 0x0BF3, - 0x0BF4, 0x0BF5, 0x0BF6, 0x0BF7, 0x0BF8, 0x0BF9, - 0x0BFA, 0x0BFB, 0x0BFC, 0x0BFD, 0x0BFE, 0x0BFF, - 0x0C00, 0x0C01, 0x0C02, 0x0C03, 0x0C04, 0x0C05, - 0x0C06, 0x0C07, 0x0C08, 0x0C09, 0x0C0A, 0x0C0B, - 0x0C0C, 0x0C0D, 0x0C0E, 0x0C0F, 0x0C10, 0x0CF0, - 0x0CF1, 0x0CF2, 0x0CF3, 0x0CF4, 0x0CF5, 0x0CF6, - 0x0CF7, 0x0CF8, 0x0CF9, 0x0CFA, 0x0CFB, 0x0CFC, - 0x0CFD, 0x0CFE, 0x0CFF, 0x0D00, 0x0D01, 0x0D02, - 0x0D03, 0x0D04, 0x0D05, 0x0D06, 0x0D07, 0x0D08, - 0x0D09, 0x0D0A, 0x0D0B, 0x0D0C, 0x0D0D, 0x0D0E, - 0x0D0F, 0x0D10, 0x0DF0, 0x0DF1, 0x0DF2, 0x0DF3, - 0x0DF4, 0x0DF5, 0x0DF6, 0x0DF7, 0x0DF8, 0x0DF9, - 0x0DFA, 0x0DFB, 0x0DFC, 0x0DFD, 0x0DFE, 0x0DFF, - 0x0E00, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, - 0x0E06, 0x0E07, 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, - 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0EF0, - 0x0EF1, 0x0EF2, 0x0EF3, 0x0EF4, 0x0EF5, 0x0EF6, - 0x0EF7, 0x0EF8, 0x0EF9, 0x0EFA, 0x0EFB, 0x0EFC, - 0x0EFD, 0x0EFE, 0x0EFF, 0x0F00, 0x0F01, 0x0F02, - 0x0F03, 0x0F04, 0x0F05, 0x0F06, 0x0F07, 0x0F08, - 0x0F09, 0x0F0A, 0x0F0B, 0x0F0C, 0x0F0D, 0x0F0E, - 0x0F0F, 0x0F10, 0x0FF0, 0x0FF1, 0x0FF2, 0x0FF3, - 0x0FF4, 0x0FF5, 0x0FF6, 0x0FF7, 0x0FF8, 0x0FF9, - 0x0FFA, 0x0FFB, 0x0FFC, 0x0FFD, 0x0FFE, 0x0FFF, - 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, - 0x1006, 0x1007, 0x1008, 0x1009, 0x100A, 0x100B, - 0x100C, 0x100D, 0x100E, 0x100F, 0x1010, 0x10F0, - 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, - 0x10F7, 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, - 0x10FD, 0x10FE, 0x10FF, 0xF000, 0xF001, 0xF002, - 0xF003, 0xF004, 0xF005, 0xF006, 0xF007, 0xF008, - 0xF009, 0xF00A, 0xF00B, 0xF00C, 0xF00D, 0xF00E, - 0xF00F, 0xF010, 0xF0F0, 0xF0F1, 0xF0F2, 0xF0F3, - 0xF0F4, 0xF0F5, 0xF0F6, 0xF0F7, 0xF0F8, 0xF0F9, - 0xF0FA, 0xF0FB, 0xF0FC, 0xF0FD, 0xF0FE, 0xF0FF, - 0xF100, 0xF101, 0xF102, 0xF103, 0xF104, 0xF105, - 0xF106, 0xF107, 0xF108, 0xF109, 0xF10A, 0xF10B, - 0xF10C, 0xF10D, 0xF10E, 0xF10F, 0xF110, 0xF1F0, - 0xF1F1, 0xF1F2, 0xF1F3, 0xF1F4, 0xF1F5, 0xF1F6, - 0xF1F7, 0xF1F8, 0xF1F9, 0xF1FA, 0xF1FB, 0xF1FC, - 0xF1FD, 0xF1FE, 0xF1FF, 0xF200, 0xF201, 0xF202, - 0xF203, 0xF204, 0xF205, 0xF206, 0xF207, 0xF208, - 0xF209, 0xF20A, 0xF20B, 0xF20C, 0xF20D, 0xF20E, - 0xF20F, 0xF210, 0xF2F0, 0xF2F1, 0xF2F2, 0xF2F3, - 0xF2F4, 0xF2F5, 0xF2F6, 0xF2F7, 0xF2F8, 0xF2F9, - 0xF2FA, 0xF2FB, 0xF2FC, 0xF2FD, 0xF2FE, 0xF2FF, - 0xF300, 0xF301, 0xF302, 0xF303, 0xF304, 0xF305, - 0xF306, 0xF307, 0xF308, 0xF309, 0xF30A, 0xF30B, - 0xF30C, 0xF30D, 0xF30E, 0xF30F, 0xF310, 0xF3F0, - 0xF3F1, 0xF3F2, 0xF3F3, 0xF3F4, 0xF3F5, 0xF3F6, - 0xF3F7, 0xF3F8, 0xF3F9, 0xF3FA, 0xF3FB, 0xF3FC, - 0xF3FD, 0xF3FE, 0xF3FF, 0xF400, 0xF401, 0xF402, - 0xF403, 0xF404, 0xF405, 0xF406, 0xF407, 0xF408, - 0xF409, 0xF40A, 0xF40B, 0xF40C, 0xF40D, 0xF40E, - 0xF40F, 0xF410, 0xF4F0, 0xF4F1, 0xF4F2, 0xF4F3, - 0xF4F4, 0xF4F5, 0xF4F6, 0xF4F7, 0xF4F8, 0xF4F9, - 0xF4FA, 0xF4FB, 0xF4FC, 0xF4FD, 0xF4FE, 0xF4FF, - 0xF500, 0xF501, 0xF502, 0xF503, 0xF504, 0xF505, - 0xF506, 0xF507, 0xF508, 0xF509, 0xF50A, 0xF50B, - 0xF50C, 0xF50D, 0xF50E, 0xF50F, 0xF510, 0xF5F0, - 0xF5F1, 0xF5F2, 0xF5F3, 0xF5F4, 0xF5F5, 0xF5F6, - 0xF5F7, 0xF5F8, 0xF5F9, 0xF5FA, 0xF5FB, 0xF5FC, - 0xF5FD, 0xF5FE, 0xF5FF, 0xF600, 0xF601, 0xF602, - 0xF603, 0xF604, 0xF605, 0xF606, 0xF607, 0xF608, - 0xF609, 0xF60A, 0xF60B, 0xF60C, 0xF60D, 0xF60E, - 0xF60F, 0xF610, 0xF6F0, 0xF6F1, 0xF6F2, 0xF6F3, - 0xF6F4, 0xF6F5, 0xF6F6, 0xF6F7, 0xF6F8, 0xF6F9, - 0xF6FA, 0xF6FB, 0xF6FC, 0xF6FD, 0xF6FE, 0xF6FF, - 0xF700, 0xF701, 0xF702, 0xF703, 0xF704, 0xF705, - 0xF706, 0xF707, 0xF708, 0xF709, 0xF70A, 0xF70B, - 0xF70C, 0xF70D, 0xF70E, 0xF70F, 0xF710, 0xF7F0, - 0xF7F1, 0xF7F2, 0xF7F3, 0xF7F4, 0xF7F5, 0xF7F6, - 0xF7F7, 0xF7F8, 0xF7F9, 0xF7FA, 0xF7FB, 0xF7FC, - 0xF7FD, 0xF7FE, 0xF7FF, 0xF800, 0xF801, 0xF802, - 0xF803, 0xF804, 0xF805, 0xF806, 0xF807, 0xF808, - 0xF809, 0xF80A, 0xF80B, 0xF80C, 0xF80D, 0xF80E, - 0xF80F, 0xF810, 0xF8F0, 0xF8F1, 0xF8F2, 0xF8F3, - 0xF8F4, 0xF8F5, 0xF8F6, 0xF8F7, 0xF8F8, 0xF8F9, - 0xF8FA, 0xF8FB, 0xF8FC, 0xF8FD, 0xF8FE, 0xF8FF, - 0xF900, 0xF901, 0xF902, 0xF903, 0xF904, 0xF905, - 0xF906, 0xF907, 0xF908, 0xF909, 0xF90A, 0xF90B, - 0xF90C, 0xF90D, 0xF90E, 0xF90F, 0xF910, 0xF9F0, - 0xF9F1, 0xF9F2, 0xF9F3, 0xF9F4, 0xF9F5, 0xF9F6, - 0xF9F7, 0xF9F8, 0xF9F9, 0xF9FA, 0xF9FB, 0xF9FC, - 0xF9FD, 0xF9FE, 0xF9FF, 0xFA00, 0xFA01, 0xFA02, - 0xFA03, 0xFA04, 0xFA05, 0xFA06, 0xFA07, 0xFA08, - 0xFA09, 0xFA0A, 0xFA0B, 0xFA0C, 0xFA0D, 0xFA0E, - 0xFA0F, 0xFA10, 0xFAF0, 0xFAF1, 0xFAF2, 0xFAF3, - 0xFAF4, 0xFAF5, 0xFAF6, 0xFAF7, 0xFAF8, 0xFAF9, - 0xFAFA, 0xFAFB, 0xFAFC, 0xFAFD, 0xFAFE, 0xFAFF, - 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0xFB05, - 0xFB06, 0xFB07, 0xFB08, 0xFB09, 0xFB0A, 0xFB0B, - 0xFB0C, 0xFB0D, 0xFB0E, 0xFB0F, 0xFB10, 0xFBF0, - 0xFBF1, 0xFBF2, 0xFBF3, 0xFBF4, 0xFBF5, 0xFBF6, - 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, - 0xFBFD, 0xFBFE, 0xFBFF, 0xFC00, 0xFC01, 0xFC02, - 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08, - 0xFC09, 0xFC0A, 0xFC0B, 0xFC0C, 0xFC0D, 0xFC0E, - 0xFC0F, 0xFC10, 0xFCF0, 0xFCF1, 0xFCF2, 0xFCF3, - 0xFCF4, 0xFCF5, 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, - 0xFCFA, 0xFCFB, 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, - 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04, 0xFD05, - 0xFD06, 0xFD07, 0xFD08, 0xFD09, 0xFD0A, 0xFD0B, - 0xFD0C, 0xFD0D, 0xFD0E, 0xFD0F, 0xFD10, 0xFDF0, - 0xFDF1, 0xFDF2, 0xFDF3, 0xFDF4, 0xFDF5, 0xFDF6, - 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, - 0xFDFD, 0xFDFE, 0xFDFF, 0xFE00, 0xFE01, 0xFE02, - 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, 0xFE08, - 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, - 0xFE0F, 0xFE10, 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, - 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8, 0xFEF9, - 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0xFEFF, - 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, - 0xFF06, 0xFF07, 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, - 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F, 0xFF10, 0xFFF0, - 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, - 0xFFF7, 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, - 0xFFFD, 0xFFFE, 0xFFFF, -}; - -const uint32_t * const ff_on2avc_quad_cb_codes[] = { - on2avc_cb1_codes, on2avc_cb2_codes, on2avc_cb3_codes, on2avc_cb4_codes, - on2avc_cb5_codes, on2avc_cb6_codes, on2avc_cb7_codes, on2avc_cb8_codes -}; - -const uint8_t * const ff_on2avc_quad_cb_bits[] = { - on2avc_cb1_bits, on2avc_cb2_bits, on2avc_cb3_bits, on2avc_cb4_bits, - on2avc_cb5_bits, on2avc_cb6_bits, on2avc_cb7_bits, on2avc_cb8_bits -}; - -const uint16_t * const ff_on2avc_quad_cb_syms[] = { - on2avc_cb1_syms, on2avc_cb2_syms, on2avc_cb3_syms, on2avc_cb4_syms, - on2avc_cb5_syms, on2avc_cb6_syms, on2avc_cb7_syms, on2avc_cb8_syms -}; - -const int ff_on2avc_quad_cb_elems[] = { - ON2AVC_CB1_CODES, ON2AVC_CB2_CODES, ON2AVC_CB3_CODES, ON2AVC_CB4_CODES, - ON2AVC_CB5_CODES, ON2AVC_CB6_CODES, ON2AVC_CB7_CODES, ON2AVC_CB8_CODES, -}; - -const uint16_t * const ff_on2avc_pair_cb_codes[] = { - on2avc_cb9_codes, on2avc_cb10_codes, on2avc_cb11_codes, on2avc_cb12_codes, - on2avc_cb13_codes, on2avc_cb14_codes, on2avc_cb15_codes -}; - -const uint8_t * const ff_on2avc_pair_cb_bits[] = { - on2avc_cb9_bits, on2avc_cb10_bits, on2avc_cb11_bits, on2avc_cb12_bits, - on2avc_cb13_bits, on2avc_cb14_bits, on2avc_cb15_bits -}; - -const uint16_t * const ff_on2avc_pair_cb_syms[] = { - on2avc_cb9_syms, on2avc_cb10_syms, on2avc_cb11_syms, on2avc_cb12_syms, - on2avc_cb13_syms, on2avc_cb14_syms, on2avc_cb15_syms -}; - -const int ff_on2avc_pair_cb_elems[] = { - ON2AVC_CB9_CODES, ON2AVC_CB10_CODES, ON2AVC_CB11_CODES, ON2AVC_CB12_CODES, - ON2AVC_CB13_CODES, ON2AVC_CB14_CODES, ON2AVC_CB15_CODES, + 2, 3, 5, 7, 7, 8, 9, 10, 11, 12, 13, 13, 8, 9, 11, 11, 13, 14, 16, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 21, 21, 16, 17, 17, 13, 13, 12, 13, + 14, 15, 16, 17, 19, 20, 20, 19, 20, 20, 5, 6, 7, 7, 3, 4, 6, 7, 9, + 9, 9, 10, 11, 12, 13, 14, 15, 16, 16, 6, 7, 8, 9, 10, 11, 13, 13, 15, + 15, 15, 16, 16, 14, 15, 16, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 3, 4, 5, 5 +}; + +#define ON2AVC_CB_1_2_CODES 41 +#define ON2AVC_CB_3_4_CODES 313 +#define ON2AVC_CB_5_6_CODES 1201 +#define ON2AVC_CB_7_8_CODES 3281 +#define ON2AVC_CB_9_10_CODES 121 +#define ON2AVC_CB_11_CODES 225 +#define ON2AVC_CB_12_CODES 441 +#define ON2AVC_CB_13_CODES 625 +#define ON2AVC_CB_14_CODES 729 +#define ON2AVC_CB_15_CODES 1089 + +const uint8_t ff_on2avc_cb_lens[] = { + /* Codebook 1 - 41 entries */ + 1, 6, 6, 6, 6, 6, 8, 8, 9, 9, 9, 9, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 7, 9, 9, 9, 9, 7, 9, + 9, 9, 9, + /* Codebook 2 - 41 entries */ + 5, 7, 7, 7, 7, 5, 5, 5, 7, 7, 7, 7, 5, 5, 5, 5, 5, 7, 7, + 7, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 3, 5, + 5, 5, 5, + /* Codebook 3 - 313 entries */ + 1, 7, 7, 7, 9, 9, 10, 11, 12, 14, 14, 14, 15, 15, 10, 10, 7, 9, 9, + 9, 10, 11, 12, 12, 7, 10, 11, 11, 12, 12, 12, 13, 14, 15, 15, 11, 11, 9, + 9, 7, 9, 10, 11, 12, 12, 9, 9, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, + 11, 12, 13, 13, 11, 12, 13, 13, 9, 9, 7, 7, 7, 9, 9, 9, 10, 11, 11, + 9, 9, 9, 10, 13, 14, 16, 16, 16, 16, 13, 13, 12, 13, 13, 10, 12, 12, 12, + 14, 14, 14, 14, 10, 11, 12, 12, 9, 10, 10, 10, 11, 11, 10, 10, 9, 10, 13, + 14, 14, 13, 13, 12, 13, 14, 14, 9, 10, 10, 9, 10, 10, 6, 6, 6, 6, 8, + 11, 12, 14, 15, 15, 14, 14, 11, 12, 13, 13, 11, 13, 14, 15, 15, 13, 13, 11, + 11, 8, 9, 10, 10, 8, 8, 10, 10, 10, 12, 12, 12, 14, 14, 14, 14, 9, 10, + 11, 12, 12, 6, 9, 10, 10, 9, 10, 12, 13, 14, 15, 16, 17, 17, 12, 13, 14, + 15, 15, 8, 10, 11, 12, 13, 14, 14, 10, 10, 8, 10, 12, 12, 12, 12, 10, 10, + 9, 10, 11, 12, 13, 14, 15, 15, 10, 10, 10, 10, 9, 9, 9, 10, 12, 13, 14, + 15, 16, 16, 12, 12, 9, 10, 10, 9, 10, 10, 6, 6, 6, 6, 6, 9, 9, 11, + 12, 13, 14, 14, 11, 12, 12, 10, 10, 9, 10, 10, 9, 10, 11, 12, 13, 14, 14, + 9, 10, 12, 12, 12, 13, 14, 15, 16, 16, 9, 10, 10, 9, 10, 11, 12, 12, 9, + 10, 11, 12, 13, 13, 9, 9, 9, 11, 12, 13, 14, 14, 11, 11, 8, 9, 11, 12, + 13, 13, 11, 12, 13, 15, 15, 15, 15, + /* Codebook 4 - 313 entries */ + 7, 7, 7, 9, 9, 9, 10, 11, 12, 12, 6, 6, 6, 7, 9, 9, 9, 9, 6, + 6, 6, 7, 9, 9, 9, 9, 6, 6, 6, 7, 7, 6, 6, 9, 9, 9, 11, 12, + 12, 11, 11, 9, 9, 9, 11, 11, 11, 12, 12, 7, 9, 9, 9, 9, 7, 9, 9, + 9, 11, 11, 11, 11, 7, 9, 9, 9, 9, 6, 6, 6, 7, 9, 9, 9, 11, 11, + 11, 11, 6, 9, 9, 9, 9, 9, 9, 9, 9, 6, 6, 6, 6, 6, 9, 9, 9, + 11, 11, 11, 11, 9, 9, 9, 9, 6, 9, 10, 12, 13, 13, 12, 12, 9, 9, 9, + 9, 9, 9, 9, 11, 12, 12, 11, 12, 12, 9, 9, 9, 9, 9, 9, 9, 11, 12, + 12, 12, 12, 12, 12, 9, 10, 10, 10, 11, 12, 12, 10, 10, 9, 10, 10, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 12, 12, 12, 12, 11, 12, 12, 9, 9, 9, 9, 9, + 10, 10, 6, 9, 10, 10, 9, 9, 9, 10, 10, 9, 10, 10, 4, 6, 9, 10, 11, + 12, 12, 9, 10, 10, 9, 10, 11, 11, 10, 10, 10, 11, 12, 12, 9, 10, 10, 10, + 11, 12, 12, 10, 10, 8, 10, 10, 10, 10, 8, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 12, 13, 14, 14, 10, 10, 8, 10, 10, 10, 11, 12, 12, 8, 10, 10, 10, + 10, 8, 8, 8, 10, 10, 10, 11, 11, 8, 8, 8, 10, 10, 10, 11, 11, 8, 10, + 11, 11, 10, 10, 8, 8, 8, 10, 10, 10, 10, 8, 10, 11, 11, 10, 10, 8, 9, + 10, 11, 13, 13, 13, 13, 9, 10, 10, 10, 11, 11, 10, 10, 6, 6, 5, 5, 5, + 6, 8, 9, 9, 8, 9, 10, 11, 11, + /* Codebook 5 - 1201 entries */ + 1, 7, 8, 10, 10, 10, 11, 12, 14, 14, 14, 14, 7, 10, 11, 14, 14, 14, 14, + 13, 13, 10, 12, 13, 15, 15, 15, 15, 12, 12, 10, 10, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, 14, 14, 14, 14, 11, 12, 12, 7, + 10, 11, 13, 13, 13, 13, 11, 12, 12, 11, 11, 10, 11, 11, 10, 14, 14, 14, 14, + 14, 14, 14, 14, 12, 12, 7, 10, 10, 11, 12, 13, 14, 14, 12, 12, 12, 12, 10, + 13, 13, 13, 13, 12, 12, 12, 13, 16, 17, 17, 16, 16, 16, 16, 16, 16, 12, 12, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 14, 14, 14, + 14, 14, 14, 14, 14, 12, 13, 14, 14, 12, 12, 10, 11, 12, 12, 10, 12, 13, 13, + 12, 12, 10, 12, 12, 12, 12, 10, 11, 11, 10, 11, 11, 10, 10, 11, 14, 15, 15, + 14, 14, 14, 14, 14, 14, 11, 12, 13, 13, 8, 9, 10, 10, 9, 10, 12, 12, 12, + 13, 13, 9, 10, 11, 12, 13, 15, 15, 15, 15, 8, 8, 8, 11, 12, 12, 11, 12, + 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, + 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 12, 13, 13, 9, 12, 12, + 12, 13, 13, 11, 12, 12, 9, 10, 11, 13, 13, 13, 14, 15, 17, 17, 17, 17, 8, + 9, 11, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 8, 10, + 13, 14, 14, 13, 13, 12, 12, 11, 12, 13, 14, 17, 17, 17, 17, 17, 17, 17, 17, + 11, 11, 10, 11, 13, 13, 13, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 16, 17, 17, 12, 12, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 9, 11, 12, + 13, 14, 14, 12, 13, 13, 12, 12, 10, 11, 11, 10, 12, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 8, 14, 14, 14, 14, 13, 14, 14, 13, 13, 13, 13, 12, + 13, 13, 12, 13, 13, 10, 11, 12, 12, 7, 7, 7, 7, 7, 11, 12, 13, 13, 11, + 12, 13, 15, 16, 16, 15, 15, 12, 12, 12, 12, 11, 11, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, + 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, + 13, 13, 13, 12, 12, 12, 12, 12, 12, 7, 7, 7, 11, 12, 12, 11, 11, 11, 12, + 13, 14, 14, 11, 12, 13, 13, 9, 10, 12, 13, 13, 12, 12, 7, 7, 7, 7, 7, + 9, 12, 13, 14, 14, 12, 12, 11, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 13, + 14, 14, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 11, 12, 13, 14, 16, 16, + 16, 16, 7, 10, 10, 11, 12, 12, 11, 11, 9, 13, 13, 13, 13, 12, 13, 13, 12, + 12, 12, 13, 16, 16, 16, 16, 16, 16, 16, 16, 7, 8, 9, 11, 12, 12, 11, 12, + 12, 7, 11, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, + 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 13, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 11, + 11, 12, 12, 12, 12, 8, 9, 11, 13, 14, 14, 13, 13, 13, 13, 13, 13, 12, 13, + 13, 8, 8, 10, 12, 12, 12, 12, 10, 11, 12, 12, 9, 12, 12, 12, 12, 11, 11, + 11, 11, 11, 11, 10, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, + 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 11, 11, 7, + 11, 11, 11, 11, 11, 11, 11, 12, 12, 11, 11, 11, 12, 13, 13, 10, 10, 9, 12, + 13, 13, 12, 12, 11, 11, 9, 10, 11, 12, 13, 15, 15, 15, 15, 8, 9, 11, 11, + 11, 12, 15, 15, 15, 15, 15, 15, 15, 15, 9, 10, 11, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 9, 15, 15, 15, 15, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 13, 14, 14, 13, 13, 13, 13, 12, 13, 13, 9, 11, 12, + 12, 11, 11, 11, 12, 13, 13, 11, 12, 12, 10, 11, 12, 13, 13, 6, 6, 6, 10, + 11, 11, 10, 10, 11, 13, 13, 13, 13, 11, 12, 13, 14, 15, 18, 18, 18, 18, 18, + 18, 18, 18, 10, 12, 12, 12, 12, 9, 9, 9, 9, 6, 11, 14, 14, 14, 14, 14, + 14, 14, 14, 13, 14, 14, 13, 13, 12, 13, 13, 12, 12, 12, 12, 11, 11, 11, 12, + 12, 11, 11, 10, 11, 12, 13, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 13, 13, 13, 13, 13, 13, 13, 13, 11, 12, 12, 11, 12, 13, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, 18, 18, 11, 11, 11, 11, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 16, + 17, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 14, 14, 14, 14, 13, 14, 14, 11, + 13, 13, 13, 13, + /* Codebook 6 - 1201 entries */ + 8, 10, 12, 13, 13, 12, 13, 14, 16, 17, 17, 16, 16, 10, 11, 11, 8, 10, 11, + 11, 10, 10, 10, 10, 11, 12, 13, 14, 14, 11, 11, 10, 10, 10, 11, 12, 12, 8, + 10, 11, 12, 12, 10, 11, 11, 8, 10, 10, 10, 11, 13, 13, 13, 13, 10, 11, 12, + 13, 13, 10, 10, 10, 11, 12, 12, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 12, + 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 10, 12, 12, 12, 13, + 14, 15, 15, 10, 10, 10, 11, 12, 12, 10, 11, 12, 12, 9, 10, 11, 11, 10, 13, + 13, 13, 13, 12, 12, 10, 11, 11, 10, 11, 12, 12, 10, 10, 10, 11, 11, 11, 11, + 11, 11, 10, 10, 11, 11, 11, 14, 15, 15, 14, 14, 13, 13, 10, 13, 13, 13, 13, + 12, 12, 11, 11, 11, 11, 10, 10, 11, 12, 13, 14, 14, 11, 11, 10, 10, 10, 10, + 11, 11, 11, 11, 10, 10, 10, 11, 12, 13, 13, 10, 10, 10, 11, 11, 10, 13, 13, + 13, 13, 12, 13, 13, 11, 12, 12, 11, 11, 10, 10, 10, 10, 11, 11, 11, 11, 9, + 10, 11, 12, 12, 11, 12, 13, 14, 14, 11, 11, 11, 11, 11, 11, 10, 10, 13, 13, + 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 10, 11, 11, 10, 11, 11, 10, 12, 13, + 13, 12, 12, 11, 11, 11, 11, 10, 11, 11, 10, 11, 11, 11, 11, 11, 11, 10, 11, + 13, 13, 13, 13, 9, 10, 13, 13, 13, 13, 12, 12, 11, 11, 11, 11, 10, 11, 11, + 10, 11, 12, 12, 11, 11, 11, 11, 11, 12, 12, 11, 11, 10, 11, 11, 9, 10, 10, + 11, 12, 14, 15, 16, 17, 17, 14, 14, 11, 11, 12, 13, 13, 12, 12, 11, 12, 12, + 11, 11, 11, 11, 11, 11, 11, 11, 9, 10, 11, 12, 13, 13, 10, 10, 10, 10, 11, + 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 12, 12, 12, 12, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 7, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 12, 13, 13, 12, 12, 12, 12, 11, 11, 10, 10, 10, 11, 12, 12, 10, 11, 11, + 10, 11, 12, 12, 10, 11, 12, 14, 14, 14, 14, 11, 11, 11, 11, 11, 11, 11, 11, + 10, 10, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 10, 11, + 11, 11, 11, 11, 11, 10, 11, 11, 10, 10, 12, 12, 12, 12, 11, 12, 12, 11, 11, + 11, 11, 10, 11, 11, 11, 11, 11, 11, 10, 11, 11, 10, 11, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, + 11, 11, 10, 10, 11, 12, 13, 15, 16, 17, 17, 15, 15, 11, 11, 10, 10, 7, 10, + 12, 12, 12, 12, 11, 11, 11, 11, 9, 11, 12, 14, 14, 14, 14, 11, 11, 7, 11, + 11, 11, 11, 10, 10, 10, 10, 10, 10, 7, 13, 13, 13, 13, 12, 12, 11, 11, 11, + 11, 11, 11, 9, 10, 11, 11, 10, 10, 10, 12, 13, 14, 14, 12, 12, 11, 11, 11, + 11, 11, 11, 11, 11, 10, 10, 10, 11, 11, 10, 11, 11, 11, 11, 11, 11, 10, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 11, 12, 12, 11, 11, 11, 11, + 11, 11, 10, 11, 11, 10, 10, 10, 11, 12, 13, 14, 14, 10, 11, 12, 12, 7, 7, + 10, 11, 11, 11, 11, 11, 11, 10, 11, 12, 14, 14, 14, 14, 11, 11, 11, 11, 10, + 10, 10, 11, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, + 11, 7, 9, 10, 11, 11, 11, 11, 11, 11, 10, 11, 11, 7, 9, 10, 10, 9, 10, + 10, 12, 12, 12, 12, 11, 11, 10, 11, 11, 10, 11, 11, 10, 10, 9, 10, 11, 11, + 13, 14, 14, 13, 13, 13, 13, 13, 13, 11, 11, 11, 11, 11, 11, 7, 10, 10, 10, + 11, 12, 13, 13, 9, 10, 11, 11, 7, 10, 11, 11, 11, 11, 11, 11, 9, 10, 11, + 11, 7, 7, 7, 7, 9, 10, 10, 10, 11, 12, 13, 13, 11, 11, 11, 11, 10, 10, + 10, 10, 9, 10, 10, 9, 10, 13, 13, 13, 13, 12, 12, 9, 11, 12, 12, 11, 11, + 10, 11, 12, 12, 10, 10, 9, 10, 11, 11, 7, 7, 7, 11, 12, 12, 11, 11, 10, + 11, 11, 10, 11, 11, 10, 11, 11, 7, 9, 10, 13, 13, 13, 13, 13, 13, 13, 13, + 10, 11, 12, 13, 13, 10, 11, 12, 12, 9, 10, 11, 11, 10, 10, 10, 11, 12, 12, + 9, 10, 11, 11, 9, 10, 10, 7, 9, 10, 11, 12, 14, 15, 16, 17, 17, 14, 14, + 10, 10, 11, 11, 11, 11, 10, 11, 11, 10, 10, 9, 10, 10, 9, 10, 10, 9, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 7, 12, 12, 12, 12, 11, 12, 12, 10, 10, 10, + 11, 11, 10, 11, 11, 7, 7, 7, 10, 10, 10, 10, 9, 10, 10, 7, 9, 10, 12, + 13, 13, 12, 12, 9, 12, 12, 12, 12, 11, 11, 7, 7, 7, 9, 10, 10, 10, 10, + 10, 11, 12, 13, 13, 10, 10, 10, 11, 13, 13, 13, 13, 9, 10, 13, 13, 13, 13, + 12, 12, 9, 10, 10, 9, 10, 11, 12, 12, 10, 10, 10, 10, 10, 11, 11, 10, 11, + 11, 9, 10, 10, 9, 9, 9, 12, 12, 12, 12, 11, 11, 10, 10, 10, 10, 9, 9, + 9, 10, 11, 12, 13, 14, 14, 7, 9, 9, 9, 10, 11, 11, 7, 9, 9, 10, 11, + 12, 13, 13, 10, 10, 7, 10, 10, 10, 11, 11, 10, 11, 11, 10, 10, 9, 10, 10, + 9, 10, 10, 9, 9, 9, 9, 9, 11, 12, 12, 11, 11, 9, 10, 11, 12, 12, 10, + 10, 10, 10, 9, 10, 11, 11, 9, 9, 9, 10, 10, 9, 10, 11, 12, 12, 9, 10, + 10, 7, 9, 10, 10, 10, 11, 12, 12, 10, 10, 7, 9, 10, 10, 9, 10, 12, 12, + 12, 12, 7, 10, 11, 11, 10, 10, 9, 9, 7, 9, 10, 10, 9, 10, 10, 9, 10, + 10, 10, 11, 12, 12, 10, 10, 9, 9, 10, 12, 12, 12, 12, 10, 11, 11, 7, 9, + 10, 10, 9, 10, 11, 11, 7, 9, 9, 10, 10, 10, 10, 9, 10, 10, 9, 9, 9, + 10, 13, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 10, 10, 7, + 9, 10, 11, 12, 12, 9, 9, 9, 10, 10, 9, 9, 12, 12, 12, 12, 11, 11, 10, + 10, 9, 10, 11, 13, 13, 13, 13, 9, 9, 9, 9, 12, 12, 12, 12, 11, 11, 10, + 10, 9, 10, 10, + /* Codebook 7 - 3281 entries */ + 1, 7, 11, 12, 12, 12, 13, 14, 15, 15, 13, 13, 13, 13, 13, 13, 13, 14, 14, + 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, + 13, 10, 12, 13, 13, 12, 12, 7, 7, 7, 11, 12, 13, 13, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 11, 12, 13, 15, 15, 15, 15, 11, + 11, 12, 12, 12, 12, 11, 11, 7, 7, 7, 9, 9, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 13, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 11, 11, + 9, 11, 11, 12, 13, 14, 14, 12, 12, 10, 11, 12, 12, 13, 13, 13, 13, 12, 13, + 13, 11, 12, 12, 11, 12, 13, 14, 14, 11, 12, 12, 11, 11, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 13, 14, 14, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, + 12, 12, 12, 12, 11, 11, 10, 12, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, + 12, 13, 13, 11, 11, 9, 10, 11, 13, 13, 13, 13, 7, 13, 13, 13, 13, 12, 13, + 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 9, 11, 12, 12, 11, 16, + 17, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, + 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, + 12, 12, 12, 11, 12, 12, 11, 11, 11, 11, 11, 12, 12, 10, 11, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, + 9, 12, 13, 14, 14, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 11, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 7, 9, 9, 10, 11, + 12, 13, 13, 12, 12, 12, 12, 11, 12, 12, 7, 7, 7, 7, 7, 9, 11, 11, 11, + 13, 13, 13, 13, 10, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, + 12, 7, 9, 11, 12, 12, 11, 12, 13, 15, 16, 17, 17, 15, 15, 10, 11, 12, 12, + 10, 12, 12, 12, 12, 7, 7, 9, 12, 12, 12, 12, 11, 12, 12, 9, 10, 11, 12, + 15, 15, 15, 15, 15, 15, 15, 15, 9, 10, 11, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 9, 9, 7, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 14, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, + 13, 13, 13, 13, 7, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, + 12, 11, 11, 9, 11, 12, 13, 13, 11, 11, 7, 9, 10, 12, 12, 12, 12, 9, 12, + 12, 12, 12, 11, 12, 12, 7, 9, 11, 12, 13, 13, 11, 13, 13, 13, 13, 9, 9, + 7, 9, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 11, + 11, 11, 11, 12, 12, 11, 11, 11, 11, 11, 11, 10, 11, 11, 11, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 9, 11, 11, 11, 11, 8, 11, 14, 15, + 17, 17, 17, 17, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 12, 12, 12, 12, 11, 12, 12, 10, 11, 11, 9, 10, 11, 12, 13, 13, 10, + 11, 11, 11, 12, 12, 12, 12, 12, 12, 8, 9, 12, 12, 12, 12, 11, 11, 8, 10, + 11, 12, 13, 13, 10, 11, 11, 8, 10, 11, 11, 10, 13, 13, 13, 13, 13, 13, 13, + 13, 8, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 8, + 10, 11, 11, 10, 11, 12, 13, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 6, 8, 11, 11, 11, 11, 10, 12, 12, 12, 12, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 11, 12, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 11, 11, 11, 11, 11, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 10, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 16, 17, + 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 12, 12, 11, 12, 12, 10, 11, 11, + /* Codebook 8 - 3281 entries */ + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 13, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 10, 11, 11, 11, 11, 11, 11, 10, + 11, 11, 9, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 9, 11, 11, 11, 11, 9, 13, 14, + 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 9, 10, 11, 11, 11, 11, + 11, 11, 10, 11, 11, 10, 11, 12, 12, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, + 11, 11, 11, 10, 10, 11, 11, 11, 11, 9, 10, 11, 11, 10, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 11, 12, 12, 11, 11, 11, 11, 10, 11, 11, 10, 10, 9, 11, 11, 11, + 11, 11, 11, 11, 11, 10, 11, 11, 9, 10, 10, 12, 13, 14, 15, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 10, 10, 9, 10, 11, 11, 9, 11, 11, 11, 11, 11, 11, 11, 11, 10, + 10, 9, 9, 10, 11, 13, 13, 13, 13, 10, 10, 9, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, + 11, 10, 11, 11, 10, 10, 10, 10, 9, 9, 11, 12, 13, 15, 15, 15, 15, 11, 11, + 11, 11, 11, 11, 10, 11, 11, 10, 10, 9, 9, 10, 11, 12, 12, 10, 10, 7, 9, + 10, 12, 12, 12, 12, 9, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, + 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 10, 10, 10, 10, 10, 10, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 9, 10, 11, 11, 10, 10, 10, 10, 8, 9, + 10, 10, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 9, 10, 10, + 9, 10, 10, 9, 10, 10, 9, 9, 9, 11, 12, 13, 14, 15, 16, 16, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 10, 10, 7, 10, 11, + 12, 12, 10, 10, 10, 10, 10, 10, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 10, 11, 11, 10, 10, 10, 11, + 12, 13, 13, 10, 10, 10, 10, 10, 10, 9, 10, 10, 9, 9, 7, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 9, 9, 10, 11, 13, + 13, 13, 13, 10, 13, 13, 13, 13, 13, 13, 13, 13, 9, 9, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 10, 11, 11, 10, 10, 10, 10, 9, 10, 10, 8, 9, 10, 10, 9, 10, 10, + 9, 11, 12, 13, 14, 14, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 10, 11, 11, 10, 10, 10, 10, 9, 10, 10, 9, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 12, 12, 12, 12, 9, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, + 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 10, + 10, 10, 10, 9, 10, 10, 10, 11, 12, 14, 14, 14, 14, 10, 10, 9, 10, 10, 9, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 10, 10, 10, 10, + 10, 10, 9, 9, 9, 10, 11, 14, 14, 14, 14, 14, 14, 14, 14, 9, 10, 10, 8, + 10, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 10, 11, 11, 10, 10, 10, 10, 9, 10, 10, 6, 8, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 10, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 10, 10, 10, 10, + 10, 10, 9, 9, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 10, 10, 10, 10, 10, 11, 12, 13, 14, 16, 16, 16, 16, 10, 10, + 6, 10, 10, 10, 10, 9, 10, 10, 9, 9, 11, 11, 11, 11, 11, 11, 11, 11, 6, + 11, 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 10, 10, 9, 9, 10, 10, 10, 10, + 10, 10, 10, 10, 9, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 10, 10, 10, 10, 9, + 9, 10, 11, 11, 10, 10, 9, 10, 10, 9, 9, 9, 9, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 7, 10, + 10, 10, 11, 12, 12, 10, 10, 10, 10, 9, 10, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, + 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 10, 10, 10, 10, 9, 10, 10, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, + 11, 11, 11, 10, 11, 11, 10, 10, 10, 10, 10, 10, 9, 10, 10, 9, 10, 10, 9, + 10, 10, 7, 9, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, + 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, + 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + /* Codebook 9 - 121 entries */ + 1, 5, 8, 9, 10, 11, 11, 9, 10, 11, 11, 10, 12, 12, 12, 12, 11, 11, 11, + 11, 9, 10, 11, 12, 13, 13, 10, 11, 11, 10, 10, 8, 9, 11, 12, 12, 11, 11, + 5, 8, 9, 10, 10, 8, 9, 10, 10, 8, 8, 8, 9, 10, 11, 12, 12, 8, 9, + 9, 8, 9, 9, 8, 8, 8, 11, 12, 12, 11, 11, 10, 11, 11, 7, 8, 9, 10, + 10, 8, 8, 8, 9, 9, 5, 9, 10, 11, 11, 9, 10, 11, 11, 8, 9, 9, 8, + 8, 8, 8, 5, 5, 5, 9, 11, 12, 12, 11, 11, 9, 9, 8, 9, 10, 10, 8, + 8, 8, 9, 10, 10, 4, 4, + /* Codebook 10 - 121 entries */ + 9, 9, 9, 9, 8, 9, 9, 7, 8, 9, 9, 8, 9, 9, 8, 8, 8, 8, 8, + 8, 5, 6, 8, 8, 8, 8, 7, 8, 8, 7, 7, 7, 8, 9, 9, 7, 8, 8, + 7, 7, 7, 8, 9, 9, 6, 7, 7, 5, 6, 7, 7, 6, 7, 8, 9, 9, 6, + 6, 5, 6, 6, 5, 7, 7, 7, 7, 6, 7, 7, 6, 7, 8, 8, 5, 7, 7, + 7, 7, 5, 7, 8, 8, 8, 8, 8, 8, 5, 6, 7, 7, 6, 7, 8, 8, 6, + 7, 8, 8, 5, 6, 7, 8, 8, 7, 7, 8, 9, 9, 8, 8, 6, 7, 8, 8, + 6, 7, 8, 8, 6, 7, 7, + /* Codebook 11 - 225 entries */ + 2, 10, 10, 10, 10, 9, 10, 11, 11, 10, 10, 10, 10, 9, 9, 9, 10, 11, 11, + 9, 10, 10, 10, 11, 12, 12, 10, 11, 11, 9, 9, 9, 10, 10, 9, 9, 8, 10, + 11, 11, 10, 10, 9, 10, 10, 10, 10, 10, 11, 11, 9, 10, 10, 9, 10, 10, 8, + 9, 10, 10, 9, 10, 11, 11, 9, 10, 10, 9, 10, 11, 11, 9, 10, 10, 9, 10, + 10, 10, 10, 10, 10, 8, 9, 10, 11, 11, 8, 9, 9, 9, 10, 10, 9, 10, 11, + 11, 9, 10, 10, 9, 10, 11, 11, 9, 10, 10, 9, 10, 10, 9, 10, 11, 11, 9, + 9, 9, 10, 10, 9, 9, 9, 9, 9, 10, 11, 11, 7, 9, 10, 10, 9, 9, 7, + 9, 10, 10, 10, 10, 10, 10, 5, 7, 7, 7, 7, 5, 5, 5, 9, 10, 10, 9, + 10, 10, 9, 9, 10, 11, 11, 10, 10, 7, 7, 9, 10, 10, 9, 10, 10, 8, 10, + 10, 10, 10, 9, 10, 10, 9, 9, 8, 9, 9, 7, 8, 10, 10, 10, 10, 7, 8, + 9, 10, 10, 7, 9, 10, 10, 9, 10, 10, 8, 8, 9, 9, 9, 10, 10, 7, 8, + 9, 10, 10, 8, 9, 10, 10, 9, 9, 9, 10, 10, 4, 4, 4, 4, + /* Codebook 12 - 441 entries */ + 2, 10, 11, 11, 11, 12, 12, 11, 11, 10, 12, 12, 12, 12, 10, 11, 11, 12, 12, + 12, 12, 11, 11, 10, 11, 11, 10, 12, 13, 13, 12, 12, 10, 12, 12, 12, 12, 10, + 11, 12, 12, 10, 12, 12, 12, 12, 11, 12, 12, 11, 12, 12, 11, 11, 11, 11, 10, + 11, 11, 10, 10, 12, 12, 12, 12, 11, 12, 12, 10, 11, 12, 12, 10, 11, 11, 10, + 11, 11, 11, 12, 12, 11, 11, 10, 10, 10, 10, 10, 11, 12, 13, 13, 10, 11, 12, + 12, 12, 12, 12, 12, 11, 11, 10, 11, 11, 11, 12, 13, 13, 12, 12, 12, 12, 11, + 12, 12, 11, 11, 10, 11, 12, 12, 9, 10, 10, 10, 11, 12, 12, 11, 11, 11, 11, + 10, 11, 11, 10, 10, 9, 11, 11, 11, 11, 9, 10, 11, 11, 9, 10, 11, 13, 14, + 14, 13, 13, 8, 9, 12, 12, 12, 12, 11, 11, 9, 10, 11, 11, 9, 10, 11, 12, + 12, 8, 10, 11, 12, 12, 10, 11, 11, 10, 11, 12, 12, 10, 10, 11, 11, 11, 11, + 10, 11, 12, 12, 10, 11, 11, 11, 11, 11, 11, 9, 10, 11, 11, 8, 9, 10, 11, + 11, 5, 10, 11, 12, 12, 10, 11, 11, 9, 10, 10, 8, 10, 11, 12, 12, 10, 11, + 11, 11, 11, 11, 11, 10, 10, 9, 9, 9, 11, 12, 13, 13, 12, 12, 12, 12, 11, + 11, 11, 11, 10, 10, 5, 5, 5, 9, 10, 11, 12, 12, 11, 11, 11, 12, 12, 11, + 11, 11, 11, 10, 10, 10, 11, 11, 11, 11, 11, 11, 10, 12, 12, 12, 12, 11, 12, + 12, 11, 11, 10, 10, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, 10, 11, 12, 12, + 10, 11, 11, 7, 9, 9, 10, 11, 11, 10, 10, 7, 7, 7, 10, 11, 11, 10, 10, + 10, 10, 10, 11, 12, 12, 7, 7, 7, 7, 7, 10, 11, 12, 12, 10, 11, 11, 10, + 11, 11, 10, 11, 11, 7, 10, 10, 10, 10, 9, 10, 10, 7, 10, 10, 10, 11, 11, + 10, 10, 10, 11, 12, 12, 7, 10, 11, 11, 10, 11, 11, 9, 10, 10, 11, 11, 11, + 11, 11, 11, 11, 11, 9, 10, 11, 11, 10, 10, 10, 10, 9, 11, 11, 11, 11, 10, + 11, 11, 10, 11, 12, 12, 9, 10, 11, 11, 10, 11, 11, 10, 10, 10, 11, 12, 12, + 10, 11, 11, 10, 10, 10, 10, 9, 9, 10, 11, 11, 10, 10, 9, 11, 11, 11, 11, + 4, 4, 4, 4, + /* Codebook 13 - 625 entries */ + 1, 8, 10, 10, 10, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 13, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 12, 12, 9, 12, 12, 12, 12, 11, 12, 12, 8, 9, 10, 11, + 12, 12, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 11, 12, 12, 11, 11, 10, 11, 12, 13, 13, 11, 11, 11, 11, 11, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 8, 8, 8, 13, 13, 13, 13, 13, 13, + 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 5, 8, 11, 12, 12, + 11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 10, 11, 11, 10, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 10, 11, 11, 8, 8, 11, 11, 11, 11, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 5, 5, 5, 11, 11, 11, 11, 10, 11, 11, 11, 11, + 11, 11, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, + 11, 11, 11, 11, 11, 10, 11, 11, 11, 11, 11, 11, 10, 11, 13, 14, 16, 16, 16, + 16, 13, 13, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 12, 12, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 11, 12, 12, 11, 11, 10, 11, 12, 15, 15, 15, 15, 14, 14, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 10, 11, 11, + 10, 11, 12, 13, 14, 15, 15, 11, 11, 11, 11, 11, 11, 11, 11, 10, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 11, 11, + 11, 11, 11, 11, 11, 10, 11, 11, 10, 10, 11, 12, 13, 13, 11, 11, 11, 11, 11, + 11, 10, 11, 11, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 5, 12, 12, + 12, 12, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 11, + 12, 13, 14, 14, 10, 11, 11, 11, 11, 11, 11, 10, 11, 11, 10, 10, 10, 10, 10, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, + 10, 11, 11, 10, 10, 5, 5, 5, 7, 8, 10, 10, 11, 12, 14, 14, 14, 14, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 11, 11, 10, 10, 8, 9, 9, + /* Codebook 14 - 729 entries */ + 1, 6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 11, + 11, 11, 11, 11, 11, 11, 6, 8, 10, 11, 11, 10, 11, 12, 13, 13, 8, 11, 11, + 11, 11, 10, 10, 6, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 9, + 10, 10, 8, 8, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 5, 8, 10, 11, 11, 10, 11, + 12, 13, 13, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 5, 5, 5, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 10, 11, 11, 9, 10, 10, 9, 10, 10, 10, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 9, 10, 12, 12, 12, + 12, 9, 9, 9, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, + 10, 7, 9, 10, 10, 9, 9, 7, 9, 10, 10, 10, 10, 10, 10, 8, 9, 10, 11, + 11, 8, 9, 11, 11, 11, 11, 8, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 10, 10, 10, 10, 10, 10, 9, 10, 10, 9, 9, 9, 10, 10, 9, 9, 5, 9, + 9, 9, 9, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, + /* Codebook 15 - 1089 entries */ + 2, 5, 8, 8, 12, 12, 12, 12, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 12, 12, 11, 11, 11, 11, 8, 11, 12, 13, 14, 14, 11, 12, 12, 11, + 11, 11, 11, 11, 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 5, 5, 5, 6, 6, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 11, + 11, 11, 11, 11, 11, 11, 11, 10, 11, 12, 12, 10, 11, 12, 12, 11, 12, 13, 14, + 17, 17, 17, 17, 16, 16, 11, 11, 11, 11, 11, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 11, 12, 12, 10, 11, 11, 9, 9, 9, 11, 11, 12, 12, 12, 12, 11, 12, 12, + 11, 11, 11, 11, 11, 11, 9, 10, 11, 11, 9, 10, 11, 11, 16, 16, 16, 16, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 9, 12, 13, 13, 12, 12, 11, 12, + 13, 14, 14, 11, 12, 12, 12, 12, 12, 12, 10, 11, 12, 12, 9, 10, 11, 11, 10, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 11, 12, 12, 11, 11, 10, + 11, 12, 12, 9, 11, 11, 11, 11, 10, 11, 11, 10, 10, 12, 12, 12, 12, 12, 12, + 12, 12, 10, 11, 12, 12, 9, 10, 11, 12, 14, 14, 14, 14, 9, 10, 11, 11, 9, + 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 9, 11, 12, 12, 12, + 12, 12, 12, 9, 9, 8, 12, 12, 12, 12, 11, 11, 10, 10, 5, 9, 10, 11, 13, + 13, 13, 13, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 9, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 8, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, + 12, 11, 11, 10, 11, 11, 10, 10, 5, 5, 5, 5, 5, 7, 10, 10, 10, 10, 10, + 12, 13, 15, 15, 15, 15, 12, 12, 10, 10, 8, 10, 10, 12, 12, 12, 12, 12, 12, + 12, 12, 8, 12, 12, 12, 12, 12, 12, 12, 12, 10, 11, 12, 12, 10, 10, 10, 11, + 11, 10, 10, 10, 10, 9, 10, 10, 14, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 13, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 11, 12, 12, 10, 10, 10, 11, 12, 12, 9, 10, 10, 9, 11, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 10, 11, 12, 12, 10, 11, 11, 10, 11, 11, + 9, 10, 10, 7, 10, 11, 13, 14, 14, 13, 13, 10, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, + 12, 12, 10, 11, 11, 10, 10, 10, 11, 12, 12, 7, 10, 10, 10, 10, 10, 10, 10, + 10, 7, 9, 10, 10, 10, 10, 10, 10, 7, 7, 7, 10, 10, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 7, + 10, 10, 10, 11, 11, 10, 11, 11, 11, 11, 11, 11, 7, 10, 10, 10, 10, 9, 10, + 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 14, 14, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 13, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, + 11, 10, 11, 11, 10, 10 +}; + +const uint16_t ff_on2avc_cb_syms[] = { + /* Codebook 1 - 41 entries */ + 0x0000, 0x0F10, 0x01F0, 0x0011, 0xFF00, 0x00FF, 0x1111, 0xFFFF, 0x1FF1, + 0xF11F, 0x11FF, 0xFF11, 0x0FF0, 0x0110, 0xF010, 0x010F, 0x10F0, 0x0F01, + 0x1010, 0xF001, 0x0F0F, 0xF0F0, 0x0101, 0x100F, 0xF00F, 0x1001, 0x1F00, + 0x00F1, 0x001F, 0xF100, 0x1100, 0xF1F1, 0xF1FF, 0x1F11, 0xFF1F, 0x11F1, + 0x1F1F, 0x1FFF, 0xF111, 0xFFF1, 0x111F, + /* Codebook 2 - 41 entries */ + 0x00FF, 0xFFFF, 0x1111, 0x11FF, 0xFF11, 0xFF00, 0x0011, 0x100F, 0x1FF1, + 0xF11F, 0x1FFF, 0x11F1, 0xF001, 0x10F0, 0x0F10, 0x010F, 0xF010, 0x1F11, + 0xF111, 0xF1FF, 0x111F, 0x0F01, 0x01F0, 0x0110, 0x1001, 0x0FF0, 0xF00F, + 0x1010, 0xF0F0, 0x0101, 0x0F0F, 0x1100, 0xFFF1, 0xFF1F, 0x1F1F, 0xF1F1, + 0x0000, 0xF100, 0x1F00, 0x00F1, 0x001F, + /* Codebook 3 - 313 entries */ + 0x0000, 0xE000, 0x0F10, 0x000E, 0x01F2, 0x0F1E, 0xEE00, 0x1021, 0x22E0, + 0x02E2, 0xE1F2, 0xEEE0, 0xE2E2, 0xE20E, 0x0FEF, 0x2200, 0x0002, 0xF2F0, + 0xFFFF, 0x1E10, 0x00E2, 0xFE0F, 0x0EE2, 0x022E, 0xF001, 0xF111, 0x20F1, + 0x1F02, 0xFFEE, 0xE2F1, 0xF221, 0xE121, 0xEEEE, 0x20EE, 0x2FFE, 0x1201, + 0xE011, 0x1EF0, 0x0F2F, 0x0101, 0xFE10, 0x002E, 0xE01F, 0xE220, 0x1E21, + 0xE110, 0xF210, 0x100F, 0x1010, 0x0F0F, 0x0F01, 0x1001, 0xF010, 0x10F0, + 0xF00F, 0x010F, 0x2FF0, 0xF10E, 0x2EE0, 0x0E02, 0x2FEF, 0x110E, 0xF2EF, + 0xE020, 0x1EF2, 0x01EF, 0x12F0, 0xF0F0, 0x0FF0, 0x0110, 0x01E1, 0x0F21, + 0x012F, 0xFF20, 0xFF02, 0x0220, 0x011E, 0x0FF2, 0x0FE1, 0xF120, 0xE12F, + 0xE11E, 0xE0E2, 0x2E0E, 0x22EE, 0x202E, 0xFEF2, 0x21E1, 0x02EE, 0xFE12, + 0x2E22, 0x1FE0, 0x12E1, 0xFFE2, 0x1EEF, 0xE0E0, 0xE1EF, 0x0222, 0x21FE, + 0x0E11, 0x20FF, 0xFE2F, 0xF1EE, 0x01FE, 0xF1E0, 0x0E1F, 0x11E0, 0x1F0E, + 0x0EE0, 0x02FF, 0x0EF1, 0x0F12, 0x00EE, 0xF21E, 0xFE1E, 0x2020, 0xEE20, + 0x121E, 0x1F22, 0xEF2F, 0x0EEE, 0xE2E0, 0x2F10, 0x1F20, 0x021F, 0xE1F0, + 0x02F1, 0x0022, 0x001F, 0xF100, 0x1F00, 0x00F1, 0x0E00, 0xE0F1, 0x12EF, + 0x0202, 0xE022, 0x2E02, 0x2121, 0x212F, 0x201F, 0xFEE1, 0xEF21, 0x21EF, + 0xF102, 0xE1E1, 0x21F2, 0x220E, 0xE02E, 0x12FE, 0x2F2F, 0xFF0E, 0x2011, + 0x0200, 0x2110, 0xE10F, 0x10F2, 0x00E0, 0x0020, 0x2F0F, 0xF0F2, 0xF01E, + 0xF22F, 0xFE21, 0x1EE1, 0x2220, 0x2222, 0xEF1E, 0x2F12, 0xEFF0, 0x102F, + 0x1102, 0x112E, 0xEE1F, 0x0011, 0xF11F, 0x101E, 0xF02F, 0x1FF1, 0xF0E1, + 0x122F, 0x2FE1, 0x0E0E, 0x222E, 0xEE0E, 0x2022, 0xE0EE, 0xE211, 0xF2F2, + 0x2112, 0xEE2E, 0x20E2, 0x1F1F, 0x10E1, 0xE0FF, 0x22F1, 0x2E20, 0x1EFE, + 0x2002, 0x1E0F, 0xF20F, 0xF1F1, 0xE101, 0x1FE2, 0xF122, 0x11EE, 0x1FEE, + 0x1E01, 0x120F, 0x21F0, 0xF201, 0xEEFF, 0x2EFF, 0x1E1E, 0x2F1E, 0x2EE2, + 0xE2EE, 0x10EF, 0x1120, 0x210F, 0x2F01, 0x0112, 0xEF10, 0xF1FF, 0xF021, + 0x22FF, 0xEFEF, 0xEFF2, 0xEE02, 0xEEE2, 0x2EEE, 0xFF22, 0x221F, 0x1F11, + 0xFE01, 0xEF01, 0x0FFE, 0x0EFF, 0x02E0, 0xFF00, 0x1100, 0x2000, 0x00FF, + 0x01F0, 0xFF1F, 0x11F1, 0xFEEF, 0xF12E, 0x12F2, 0xE112, 0x200E, 0x1F2E, + 0xFF2E, 0xEE11, 0x10FE, 0xF012, 0x2E00, 0xFFE0, 0x0E20, 0x1FFF, 0x0211, + 0x2211, 0x2EF1, 0xF212, 0xEFFE, 0xE1FE, 0xE200, 0xF0FE, 0x11E2, 0x2E11, + 0x20E0, 0xEF12, 0x2E2E, 0x22E2, 0xE22E, 0x2202, 0x1210, 0xEF0F, 0x2101, + 0x111F, 0xF0EF, 0x2E1F, 0xE21F, 0xEEF1, 0x11FF, 0x1012, 0xF1E2, 0x1E12, + 0x0E2E, 0x2FF2, 0xFF11, 0xFFF1, 0x0121, 0xF2E1, 0x020E, 0xEFE1, 0x211E, + 0xE00E, 0x1E2F, 0x1122, 0x1111, 0xFEF0, 0x1221, 0xE2FF, 0x1212, 0x2F21, + 0x0E22, 0xF2FE, 0xFEFE, 0xE002, 0xEE22, 0xE202, 0xE222, + /* Codebook 4 - 313 entries */ + 0x1FF1, 0xF111, 0x111F, 0xF01E, 0xE011, 0x20FF, 0xFFEE, 0xF2FE, 0x220E, + 0x20EE, 0x0110, 0x0F01, 0x0011, 0xF1F1, 0x20F1, 0x2F0F, 0x10F2, 0x110E, + 0xF010, 0xF001, 0x10F0, 0xFFF1, 0xFF02, 0xE01F, 0x021F, 0xFE01, 0x010F, + 0x0FF0, 0x1001, 0x1FFF, 0x1F1F, 0x100F, 0xF00F, 0x2101, 0x1F02, 0xE10F, + 0xFFE2, 0xEE02, 0x0E20, 0x2F12, 0x1EFE, 0x1FE0, 0xF10E, 0x120F, 0x21F2, + 0xEFF2, 0xEFEF, 0x2E20, 0xE022, 0xFF1F, 0x10EF, 0x0EF1, 0xF0FE, 0xF120, + 0x1F11, 0x02FF, 0xEF0F, 0xE101, 0xEF1E, 0xE112, 0xEFE1, 0xF212, 0xF1FF, + 0x101E, 0xF20F, 0xE000, 0x10E1, 0xF100, 0x001F, 0x1F00, 0x11F1, 0xFE0F, + 0xF021, 0x1E01, 0xE1EF, 0x2F21, 0x212F, 0x12F2, 0x0101, 0x0E00, 0x0E11, + 0xF0F2, 0x11E0, 0x201F, 0xF02F, 0x1E0F, 0x1201, 0x0F0F, 0x00F1, 0x1010, + 0xF0F0, 0x0F10, 0x0EFF, 0x2011, 0x0E1F, 0xFE1E, 0x2FFE, 0xE1FE, 0x211E, + 0x0200, 0xE0F1, 0xFF20, 0xF1E0, 0x01F0, 0xFFE0, 0xEEF1, 0x2E00, 0xE0E2, + 0x2EE0, 0x02E2, 0xE22E, 0x0211, 0xF201, 0x1F20, 0xF102, 0x02F1, 0x1021, + 0x1102, 0xE020, 0xE20E, 0xE200, 0x20E0, 0x22EE, 0xE2E0, 0xFF0E, 0xF0E1, + 0x1F0E, 0x102F, 0x1120, 0xE0FF, 0xF0EF, 0x0E02, 0x2EE2, 0x0E2E, 0x2E02, + 0x002E, 0x20E2, 0xEE22, 0x2000, 0xF122, 0x1FEE, 0x21FE, 0x020E, 0x2EEE, + 0x00E2, 0x221F, 0x2E1F, 0x0F1E, 0xEF12, 0xE2F1, 0x0F12, 0x01FE, 0xE110, + 0x2FF0, 0xF2F0, 0x0F2F, 0x1E10, 0x000E, 0x01F2, 0x22E2, 0xE2EE, 0xE02E, + 0x2E0E, 0x200E, 0x222E, 0xEE2E, 0x01E1, 0x011E, 0x0020, 0x01EF, 0xF210, + 0xF1E2, 0x1E2F, 0xFFFF, 0x0F21, 0xE21F, 0x22FF, 0x12F0, 0x0002, 0x012F, + 0xEE11, 0xE12F, 0x0FF2, 0xF2E1, 0x1F2E, 0x0000, 0x1111, 0x1EF0, 0x2E11, + 0x2002, 0x02E0, 0xE0EE, 0x00E0, 0x2FEF, 0xFE12, 0xFE10, 0x1EEF, 0x2020, + 0x0EE0, 0xF22F, 0xEEEE, 0x2EF1, 0x2220, 0xEE0E, 0xEEE2, 0x0FE1, 0x12FE, + 0xE2FF, 0x22F1, 0xE002, 0x202E, 0x2202, 0x21EF, 0x1EF2, 0x2110, 0x11EE, + 0x12E1, 0x2FE1, 0xF21E, 0xEFF0, 0x2EFF, 0xE211, 0xFEE1, 0x2FF2, 0xFE2F, + 0x1FE2, 0xFE21, 0x21E1, 0xEF21, 0xE0E0, 0x2022, 0xE220, 0x0E22, 0x2E22, + 0xF2EF, 0xFEF2, 0x0112, 0xE11E, 0xF221, 0x1EE1, 0xE00E, 0xE202, 0xE222, + 0xF012, 0x122F, 0x11E2, 0xF12E, 0x2F2F, 0x0FEF, 0x0FFE, 0xEF01, 0xFF22, + 0x2222, 0x121E, 0x2E2E, 0x0222, 0x1210, 0x210F, 0x2F10, 0x1212, 0x112E, + 0xEF2F, 0xEEE0, 0x0022, 0xFEF0, 0xFEFE, 0x0EEE, 0x0202, 0xEE1F, 0xF1EE, + 0x0121, 0x10FE, 0xEF10, 0x2F1E, 0x2121, 0xFF2E, 0x1E21, 0x21F0, 0xE121, + 0x0E0E, 0xE2E2, 0x1E1E, 0xF2F2, 0x2F01, 0x2211, 0x1E12, 0x0220, 0x22E0, + 0x0EE2, 0x02EE, 0x022E, 0x1221, 0xEFFE, 0xE1E1, 0x12EF, 0x00EE, 0x2200, + 0x2112, 0xE1F2, 0xFF11, 0x11FF, 0x1100, 0x00FF, 0xFF00, 0xF11F, 0xE1F0, + 0xFEEF, 0xEEFF, 0x1012, 0x1122, 0x1F22, 0xEE00, 0xEE20, + /* Codebook 5 - 1201 entries */ + 0x0000, 0x1100, 0x3F00, 0xF1FF, 0x010D, 0x0F30, 0xFE30, 0x10FE, 0xD021, + 0xE23F, 0xE3EF, 0xFF33, 0xFF00, 0x03F0, 0x0301, 0xF1EE, 0xF3D1, 0xF30E, + 0x023D, 0xFEDE, 0xFE0F, 0x1F11, 0xF11D, 0x10E3, 0xEDF2, 0xEEEE, 0xEE1F, + 0xEF1E, 0xF00D, 0xF131, 0xFF1F, 0x1FFF, 0xEF2F, 0xE1ED, 0xE1FE, 0xE2E0, + 0xE3F2, 0xF31D, 0x03ED, 0x1D3F, 0x131D, 0x2DFE, 0x2FFE, 0x202E, 0x22FD, + 0x220E, 0x3E12, 0x32F2, 0x0F2F, 0xED30, 0xF22D, 0x11EE, 0x33FF, 0x03EF, + 0x0121, 0x03D0, 0x0011, 0x0D10, 0x0112, 0xDE01, 0xF1E2, 0x1D31, 0x2D2F, + 0xE1F0, 0x2E00, 0x300F, 0xF1DF, 0x0FDE, 0x111F, 0x0132, 0x1DFF, 0x1F31, + 0xD221, 0xFEE1, 0x033E, 0x0330, 0x1E21, 0x12E1, 0x20D1, 0x213E, 0x012F, + 0x1FDF, 0x00FF, 0xFFD1, 0xFFF1, 0x01F2, 0xFFF3, 0xDF20, 0x22FF, 0x2332, + 0xF0FE, 0xF113, 0x0DE1, 0x31FF, 0xF311, 0xD1D1, 0xFFD3, 0x1E2F, 0x1122, + 0xFD11, 0x0FEF, 0x3111, 0x113D, 0xDDD3, 0x330E, 0xDD3D, 0xDED0, 0xDEF2, + 0xDE23, 0xDE3E, 0xD0E1, 0xD230, 0x00D3, 0x1FFD, 0x131F, 0xD30E, 0xE002, + 0xE3E3, 0xFD1D, 0xFE1E, 0xF33D, 0x1DFD, 0x1D1D, 0x13DD, 0x13F3, 0x2D2D, + 0x2E02, 0x2F03, 0x203D, 0x22F3, 0x2202, 0x23E3, 0x230D, 0x232D, 0x233E, + 0x3D2E, 0x3F3F, 0x31DF, 0x31E2, 0x33DF, 0x33FD, 0x332E, 0x3333, 0xDF3F, + 0xD3E0, 0xED1E, 0xEEDF, 0xEEF3, 0xE112, 0xE12D, 0xE21D, 0xFF3D, 0xF212, + 0xF223, 0x0E3D, 0x0202, 0x2ED3, 0x2002, 0x212F, 0x2130, 0x222E, 0x2233, + 0x2312, 0x3ED0, 0x3FEE, 0xEFEF, 0x30F2, 0x31EE, 0xE211, 0xFF2E, 0xF122, + 0x0312, 0x1DEE, 0x12ED, 0x2D21, 0x21D2, 0x00EE, 0x201F, 0x23D0, 0x3021, + 0x00E2, 0x2200, 0x0123, 0x00E0, 0x3001, 0x02D1, 0x11FF, 0x1210, 0x0EFF, + 0x31E0, 0xFF31, 0xF230, 0xF111, 0x030F, 0x1003, 0x3FFF, 0xD00F, 0x0FED, + 0x01ED, 0x3EF0, 0x0031, 0x003D, 0x0FFE, 0x0130, 0xDE10, 0x10D0, 0xDEE1, + 0x331F, 0xDE1E, 0xE11E, 0x1EEF, 0x2ED1, 0x223F, 0x231E, 0x3120, 0x32F0, + 0x0D01, 0x02E0, 0x10EF, 0x00F3, 0x0103, 0x113F, 0x0310, 0xFFFF, 0x013E, + 0x2D0F, 0x2F01, 0x111D, 0xE2F1, 0xFEED, 0x1111, 0x0DF0, 0x13F1, 0x2F0F, + 0x10D2, 0xD032, 0xD331, 0xEDD0, 0xEE13, 0xD0F0, 0xDF00, 0x001D, 0x1F3F, + 0xDF11, 0xD1FF, 0xF030, 0x13FF, 0x3F11, 0xEFDE, 0xE220, 0xF203, 0xF3FD, + 0x0EE2, 0x020E, 0x0332, 0x1302, 0x2E2E, 0x2F0D, 0x2F32, 0x20E2, 0x21E3, + 0x221D, 0x23F2, 0x3F0E, 0xDDE0, 0x31D1, 0x3122, 0xDFE0, 0xED12, 0xE121, + 0xE132, 0xFD31, 0x0DFE, 0x1D02, 0x1E12, 0x20DF, 0x302F, 0xF03E, 0xF032, + 0xEE00, 0xF2EF, 0x10DE, 0xF1F1, 0xFDF1, 0x12D0, 0x3FF1, 0x1221, 0xE130, + 0x0020, 0xF0F2, 0x101E, 0x0F0D, 0x0E31, 0x0033, 0xE30F, 0xF0EF, 0x1230, + 0xDD3F, 0x32FE, 0xDFFD, 0xD113, 0xD13D, 0xD133, 0x0013, 0x1F1F, 0xD210, + 0xDFF1, 0xE101, 0x11D1, 0xD02F, 0xEEDD, 0xE1E1, 0xFDEE, 0xF331, 0x0DE3, + 0x02D3, 0x0220, 0x12E3, 0x1212, 0x13E2, 0x2EF1, 0x3100, 0x0F23, 0x0D12, + 0x2E11, 0x2FF2, 0x230F, 0x3221, 0x311F, 0xFF13, 0x012D, 0xF2DE, 0xFEEF, + 0x2F1E, 0xD2DE, 0xD3DF, 0xD32E, 0xEE3D, 0xE0EE, 0xE0E2, 0x2022, 0x22DD, + 0x0F32, 0x00DD, 0x0FD0, 0x0E00, 0xFEE3, 0x1E3E, 0x11E2, 0x22E2, 0x23ED, + 0x3D0E, 0x3D3D, 0x3E0D, 0x3E03, 0x3E2D, 0x3E3E, 0x3E32, 0x3FDD, 0x3003, + 0x311D, 0xDD02, 0x32DE, 0x33D3, 0xFF20, 0x0022, 0x10F2, 0xDEDE, 0xED32, + 0xEE1D, 0xE0E0, 0xE033, 0xE2D3, 0xE2EE, 0xE202, 0xFDF3, 0xFD33, 0xF313, + 0x2DE3, 0x2D23, 0x2F12, 0x2033, 0x2220, 0x2330, 0x3DE2, 0x3E30, 0x3FDF, + 0x3FFD, 0x3F2E, 0x3F31, 0x30FE, 0xDD2E, 0x32ED, 0x33EE, 0xDEFE, 0xDE12, + 0xD1EE, 0xEFED, 0xEFE1, 0xE0FD, 0xE02E, 0xE020, 0xE022, 0xE123, 0xE32D, + 0xF302, 0x0E0E, 0x0323, 0x1D0E, 0x2D3E, 0x2FED, 0x2F3E, 0x20F3, 0x22E0, + 0x2213, 0x3E21, 0xDF2E, 0xEDDE, 0xEDE1, 0xEF12, 0xE330, 0xFE2D, 0xFFE2, + 0xF2FE, 0xF22F, 0x0D32, 0x02DD, 0x1E1E, 0x121E, 0x130E, 0x2EE0, 0x2E3F, + 0x2FE1, 0x20E0, 0x2031, 0x2222, 0x2231, 0x3F20, 0xD030, 0xEF30, 0xFE32, + 0xF2E1, 0x02F3, 0x1ED2, 0xF3E0, 0x2DE1, 0x3DFF, 0x0231, 0x2301, 0xD111, + 0xFDE0, 0x1012, 0x20F1, 0x1D00, 0x0200, 0x2101, 0xDD1F, 0x33D1, 0xDE21, + 0xE301, 0x0DDE, 0x0DD2, 0xF201, 0x0EF1, 0x01DE, 0x02DF, 0x21F0, 0x023F, + 0xED0F, 0xEF32, 0xE13E, 0xE2DF, 0xE2E2, 0xE312, 0xF21E, 0xF3DF, 0x0E02, + 0x11D3, 0x12EF, 0x2FDE, 0x2FEF, 0x00FD, 0x2F2F, 0x22F1, 0x3DDF, 0x3D11, + 0xD3F1, 0x30E1, 0x32D0, 0xF1DD, 0x03FE, 0x031E, 0x1133, 0x1032, 0x12D2, + 0x1223, 0x3D00, 0x3D1F, 0xD311, 0x0FD2, 0x0F12, 0xF0D2, 0x021F, 0x0F10, + 0x01F0, 0x10F0, 0x100F, 0x0F01, 0x23F0, 0xF1E0, 0xEE3F, 0x032D, 0xE310, + 0x11E0, 0x33F1, 0xD0F2, 0x33E2, 0xDFEE, 0xD01E, 0xD102, 0x0DD0, 0x0D2F, + 0x0E3F, 0x120F, 0x2FF0, 0xF3F1, 0xD2F2, 0xD3E2, 0xD322, 0xEDFE, 0xEE2E, + 0xEFE3, 0xEF0D, 0xEF2D, 0xE01D, 0xE1E3, 0xE10D, 0xE213, 0xFD13, 0x0D3E, + 0x02E2, 0x030D, 0x1D3D, 0x2D03, 0x2D1E, 0x2EE2, 0x2E1D, 0x20FD, 0x203F, + 0x21F2, 0xDD11, 0x2112, 0x321E, 0xD3FF, 0xEFD0, 0xEF21, 0xE1D0, 0xE3FE, + 0xE31E, 0xFE12, 0xF133, 0x0E2E, 0x12F2, 0x1203, 0x2E31, 0x21DE, 0x211E, + 0xED01, 0xFDE2, 0xF2E3, 0xF232, 0x1F3D, 0x13DF, 0xEF0F, 0xE0F1, 0xFED2, + 0xFF0E, 0x1E32, 0x11FD, 0x1010, 0xF010, 0xF001, 0xED10, 0x110E, 0x20FF, + 0xF1D1, 0x0FE3, 0x1D1F, 0x02FF, 0x3E2F, 0x3320, 0xDF22, 0xE110, 0x1102, + 0xFDD1, 0xFD3F, 0xF300, 0x01D2, 0xD201, 0xF3E2, 0xF33F, 0xF023, 0x1E30, + 0x0F0F, 0x1001, 0x010F, 0x0101, 0xF00F, 0x1300, 0xED2F, 0x1E23, 0xEF3E, + 0xE12F, 0xF0DE, 0x102D, 0x2DF0, 0x103E, 0x31F1, 0xFDD3, 0xFD2E, 0xFEFE, + 0x0E22, 0x03F2, 0x1EF2, 0x12DE, 0x1322, 0xDD20, 0x2E20, 0x21E1, 0xF20D, + 0x1DE2, 0xDE0F, 0x13D1, 0x132E, 0xFED0, 0xF120, 0x02F1, 0x03E1, 0x1320, + 0x2321, 0x01FE, 0x3201, 0x21D0, 0x3DE0, 0xDFE2, 0xDFF3, 0xDF13, 0xDF33, + 0xF0F0, 0x0D0F, 0x0ED1, 0xEF10, 0xF10E, 0x10ED, 0x1EF0, 0x2D10, 0xFD00, + 0xF1D3, 0x0EE0, 0x122D, 0x133F, 0xF0E1, 0x2EDF, 0x2FD0, 0x1F20, 0x102F, + 0x2DEF, 0x221F, 0xD0D0, 0xD03E, 0xD2ED, 0xD2E3, 0xD212, 0xD22D, 0xED0D, + 0xED03, 0x0110, 0x3010, 0xD010, 0x13E0, 0xEEFF, 0xF2D0, 0x1E10, 0x0DEF, + 0x1E0F, 0x0FF0, 0x01EF, 0x1F02, 0xED3E, 0xEEE2, 0xEFF2, 0xE0D3, 0xE00E, + 0xE03D, 0xE23D, 0xE323, 0xE33E, 0xFD3D, 0xF3D3, 0x0D2D, 0x1313, 0x1333, + 0x2DED, 0x2E0E, 0x011E, 0x2E3D, 0x212D, 0x223D, 0x3DD1, 0x3D22, 0x3EDE, + 0x3EE3, 0x3E23, 0x3F22, 0x30D0, 0x300D, 0x313F, 0xDFD1, 0x32D2, 0x331D, + 0xDF0E, 0xDF02, 0xD012, 0xEDD2, 0xEED3, 0xEFFE, 0xE1EF, 0xE103, 0xE3DE, + 0xE332, 0xFDDD, 0xFE0D, 0x03E3, 0x2D32, 0x2EF3, 0x2E22, 0x200E, 0x201D, + 0x3EFE, 0x3EF2, 0xDDEE, 0x312E, 0x3212, 0xDDFF, 0xD131, 0xEEE0, 0xE0DF, + 0xE0D1, 0xE1D2, 0xE1F2, 0xE3D2, 0xFD02, 0xFEF2, 0xFE21, 0x0D23, 0x02EE, + 0x0222, 0x120D, 0x2DF2, 0x2D12, 0x2F2D, 0x21ED, 0x2121, 0xDEEF, 0x22DF, + 0x301E, 0xEE11, 0xF3EE, 0x0213, 0x1D22, 0x1EDE, 0x1E03, 0x1F2E, 0x3EEF, + 0xE011, 0x0EDF, 0x0E11, 0x2011, 0xF1F3, 0x0FF2, 0x3FE0, 0x1ED0, 0x1021, + 0x123E, 0xE000, 0x30F0, 0x2310, 0xD2E1, 0x3322, 0xDDF1, 0xEEF1, 0xFFDD, + 0x0D30, 0x03DE, 0x1D33, 0x1FDD, 0xD300, 0x112E, 0x22D1, 0x0002, 0x2000, + 0xEDF0, 0xE0FF, 0xFFEE, 0x0E1F, 0x1023, 0x3210, 0x0F21, 0xE321, 0xF02F, + 0x1FF1, 0xF021, 0x1F0E, 0x1232, 0x3E01, 0x01E1, 0xEF01, 0xFD20, 0xF2F0, + 0xF210, 0x1FD1, 0x3E10, 0x3300, 0xD0EF, 0xD2EF, 0xE03F, 0xE031, 0x0EEE, + 0x022E, 0x0233, 0x03D2, 0x13EE, 0x133D, 0x2FE3, 0x21EF, 0xD1E0, 0x21FE, + 0x30EF, 0xE2D1, 0xE2FF, 0xE21F, 0xE231, 0xFE3E, 0xF12E, 0xF2ED, 0x1EE3, + 0x1E2D, 0x122F, 0x2DD0, 0x3EE1, 0x1E01, 0x10E1, 0xFE10, 0xF320, 0xD100, + 0x1113, 0xF012, 0x0F3E, 0x1DE0, 0x11DF, 0x12F0, 0xF003, 0xFF02, 0x0211, + 0xF31F, 0x0FE1, 0x1DF1, 0x320F, 0x1DD1, 0x1FE2, 0xD2F0, 0xDD00, 0x11F1, + 0xEDEF, 0x1F22, 0x11DD, 0x1D20, 0x1201, 0x1F13, 0x11F3, 0x0F2D, 0xF0D0, + 0xD1F1, 0xF20F, 0x32E1, 0xDDDF, 0xDD31, 0xDEE3, 0xDE32, 0x000E, 0x01D0, + 0x1D11, 0x3F1F, 0xFFDF, 0x2E1F, 0xDF31, 0xD0FE, 0xD13F, 0xD2D2, 0xD2FE, + 0xD23E, 0xD3EE, 0xD33F, 0x00D1, 0xDEF0, 0xFF3F, 0xEDE3, 0xEEFD, 0xEF03, + 0xE0F3, 0xE013, 0xE1DE, 0xE2F3, 0xE233, 0xE3D0, 0x1D13, 0x1EFE, 0x2DD2, + 0x2D30, 0x2E13, 0x210D, 0x2132, 0x0F03, 0x22D3, 0x22EE, 0x23D2, 0x3012, + 0xDE30, 0xD10E, 0xEFD2, 0xFE03, 0xF3DD, 0x1DF3, 0x1EED, 0x1E0D, 0x12FE, + 0x1331, 0xDE2F, 0x2013, 0x23FE, 0xFE23, 0xFF22, 0xF32E, 0x0DF2, 0xE3E1, + 0x1DDF, 0x1FD3, 0xFF11, 0xFDFF, 0x021D, 0x0321, 0x1FF3, 0xF1FD, 0x100D, + 0xF02D, 0x32EF, 0xD22F, 0xFEF0, 0x1FE0, 0x1F33, 0x0F1E, 0xF13F, 0x2211, + 0xD31F, 0xF23E, 0x001F, 0xF100, 0x1F00, 0x2110, 0xFFFD, 0x0D21, 0xFD1F, + 0x2F10, 0xDFFF, 0xF322, 0x0E1D, 0x23EF, 0x33E0, 0x210F, 0xF102, 0x3311, + 0xD12E, 0x3331, 0xDDFD, 0xDDF3, 0xDD0E, 0xDD22, 0xDD33, 0xDED2, 0xDEED, + 0xDE0D, 0xEFF0, 0xE01F, 0xF0ED, 0xF0E3, 0x02FD, 0x01E3, 0xF11F, 0x003F, + 0x00DF, 0x00F1, 0xF01E, 0xD122, 0xEED1, 0xEE20, 0xFD0E, 0x0EDD, 0x2EFF, + 0x20EE, 0x2020, 0xED21, 0x3D20, 0x3E1E, 0x0E33, 0x1D2E, 0xFE01, 0x2F30, + 0x232F, 0xFFE0, 0x0ED3, 0x0E13, 0x23E1, 0xE3F0, 0x1311, 0xFF1D, 0x3E0F, + 0xD120, 0x1131, 0xD001, 0x1030, 0x1F1D, 0x1120, 0xD320, 0x3F02, 0xDE03, + 0xDE2D, 0xDFDD, 0xDFD3, 0xDF1D, 0xD0DE, 0xD0E3, 0xD1DD, 0xD20D, 0xD3DD, + 0xD3FD, 0xD3F3, 0xD302, 0xD31D, 0xD313, 0xD33D, 0xEE31, 0xE32F, 0xFD22, + 0xF13D, 0x0EFD, 0x0E20, 0x1FEE, 0x2D01, 0xD11F, 0xD20F, 0xF2D2, 0xF3FF, + 0x0EF3, 0x3DF1, 0x0D0D, 0x1DD3, 0x2D0D, 0x2323, 0x3DDD, 0x3DD3, 0x3DF3, + 0x3D1D, 0x3D13, 0x3EED, 0x3FD3, 0x3F13, 0x3F3D, 0x3F33, 0x30E3, 0x302D, + 0x3023, 0x3032, 0x31D3, 0x31FD, 0x310E, 0x3113, 0x313D, 0x3133, 0x3203, + 0x323E, 0x33DD, 0x33F3, 0xDD1D, 0x3302, 0x333D, 0xE200, 0xDF1F, 0xE10F, + 0x032F, 0xDD13, 0xDFDF, 0xDF3D, 0xD0D2, 0xD0ED, 0xD003, 0xD023, 0xD1D3, + 0xD1FD, 0xD11D, 0xD2D0, 0xD203, 0xD223, 0xD3D3, 0xD333, 0xED2D, 0xED23, + 0xEE0E, 0xEE33, 0xE30D, 0x1DDD, 0x2E33, 0x20D3, 0x2303, 0x3DEE, 0x3DFD, + 0x3D02, 0x3D33, 0x3F1D, 0x30DE, 0x30ED, 0x303E, 0x3030, 0x31DD, 0x3131, + 0x32E3, 0x320D, 0x322D, 0x3223, 0x3232, 0xDDD1, 0x3313, 0x333F, 0xD00D, + 0xD02D, 0xD1DF, 0xD1F3, 0xD232, 0xD3D1, 0xEDED, 0xEE02, 0xE2DD, 0xE222, + 0xE303, 0xF333, 0x0D03, 0x0303, 0x20DD, 0x23DE, 0x3D3F, 0x3D31, 0x3ED2, + 0x3FF3, 0x30D2, 0x31F3, 0xDDDD, 0xDDE2, 0xD1E2, 0xEE22, 0xE0DD, 0xE20E, + 0xE22E, 0xE3ED, 0xFDFD, 0xF3F3, 0x0DED, 0x13D3, 0x13FD, 0x2DDE, 0x2EDD, + 0x2EEE, 0x2F21, 0x2F23, 0x2103, 0x2123, 0x3FD1, 0x3FE2, 0xD21E, 0x3102, + 0x3230, 0xEF23, 0xE2FD, 0x0D1E, 0x2EFD, 0xFDDF, 0x2FD2, 0x322F, 0x002E, + 0xFE2F, 0xF2F2, 0xF221, 0x1EE1, + /* Codebook 6 - 1201 entries */ + 0xFF1F, 0x1EF0, 0x0D32, 0x3E30, 0x0D0F, 0x2E02, 0x0D10, 0xD0E3, 0xD33D, + 0xDDD3, 0xD030, 0x0DD0, 0x3DD3, 0x1E10, 0x2DE1, 0x20EE, 0x11F1, 0xF0F2, + 0xFE1E, 0x1D22, 0xEEFF, 0xE0F1, 0xFEEF, 0xE101, 0xDEF2, 0x2EE2, 0x00FD, + 0x0D0D, 0x3D13, 0xEFF2, 0xF212, 0x0F2F, 0x1120, 0x2F0F, 0x1E2D, 0x2F30, + 0xD3E0, 0x1F11, 0x1122, 0xEFE1, 0xE02E, 0x2F03, 0xF20F, 0xF02D, 0x22FD, + 0xF1FF, 0xFE10, 0xFF20, 0x21FE, 0xFE2F, 0xED2D, 0xF3D3, 0x023F, 0x20DD, + 0xF2F0, 0xD1E0, 0x203F, 0x3010, 0x330E, 0x02FF, 0xE0FF, 0xFFE0, 0xF1EE, + 0x0EE2, 0x0103, 0xF0EF, 0x0EFF, 0x0FE1, 0x1E01, 0x10E1, 0xFF0E, 0x0F21, + 0x2EFF, 0x21ED, 0xEDDE, 0x0130, 0xDEE3, 0xD003, 0xD02D, 0xE303, 0xF333, + 0x0DDE, 0x23E3, 0x3DD1, 0xDE32, 0xDF1D, 0xE332, 0x0D3E, 0x0F0D, 0x1D1D, + 0xDF11, 0xE0E0, 0x2DD0, 0x22E0, 0x23DE, 0x3030, 0xDFD3, 0x00DD, 0x201F, + 0x1D11, 0x1221, 0x211E, 0xF311, 0x133F, 0xFFEE, 0x31EE, 0x2031, 0x2213, + 0xD00F, 0xF02F, 0x2E3F, 0x321E, 0xEEF1, 0xEDD2, 0x03EF, 0x2ED3, 0x32D0, + 0xE0DF, 0xFFDD, 0xEF12, 0xDEE1, 0x223F, 0xF102, 0xDDF1, 0x3F1D, 0x010D, + 0x02F1, 0x12F0, 0xF201, 0xD10E, 0xF2D0, 0x0D2F, 0x1E21, 0x22F1, 0x231E, + 0xF1E0, 0x0211, 0x3F2E, 0xED01, 0xFDE0, 0xD032, 0x0033, 0x3D33, 0xFD33, + 0x3DF3, 0xD322, 0xF300, 0xE000, 0x3D02, 0x3D3F, 0x3EDE, 0x30E3, 0xEDED, + 0xF13D, 0xEF23, 0x1E30, 0x212F, 0x22DF, 0xF0E1, 0x1DF1, 0xE132, 0x0312, + 0x3100, 0x3133, 0xDDFD, 0xF2EF, 0x03FE, 0xFE0F, 0xF1FD, 0x11F3, 0x2211, + 0xD021, 0xE2D1, 0x0DF2, 0x1023, 0xD210, 0x102F, 0x2011, 0x21D0, 0x2E20, + 0xDE2D, 0xD3EE, 0x0E1F, 0x1F20, 0x1113, 0x00EE, 0x30F2, 0x1201, 0xD32E, + 0xE23D, 0x0ED1, 0x3DEE, 0xE1DE, 0x31F3, 0x3302, 0xF3E2, 0x0EDD, 0x2103, + 0x2FDE, 0x2F1E, 0xF113, 0xD001, 0xF11D, 0x1FFD, 0xF0ED, 0x112E, 0x12F2, + 0x2E31, 0xD1F1, 0x1E0F, 0x2233, 0xE20E, 0x0E22, 0x2200, 0x0202, 0xDD22, + 0xDFDD, 0x3FD3, 0x0D12, 0x02D1, 0x1DE2, 0x1EFE, 0x3F0E, 0x30E1, 0xF3FF, + 0x1021, 0xD230, 0x00D1, 0x01D2, 0x013E, 0x1DFD, 0x1D13, 0x32DE, 0x32E3, + 0xEE2E, 0xF302, 0x0E2E, 0x02E2, 0xF31F, 0x331F, 0xEE31, 0x000E, 0x3EF2, + 0x3E21, 0x2000, 0xEE0E, 0x33EE, 0xDD13, 0xE0E2, 0x03DE, 0xDDFF, 0xD1E2, + 0xD3F1, 0xD311, 0x0002, 0xFEE3, 0xFE3E, 0x01EF, 0x12DE, 0xD02F, 0xEEE0, + 0xE1EF, 0x0EE0, 0x031E, 0x11DF, 0x1D20, 0xDFFD, 0xD3D1, 0xE3DE, 0xFE30, + 0x3F1F, 0x131F, 0x0DE3, 0x0F2D, 0x2DDE, 0x3131, 0xF203, 0x1FD3, 0xF2ED, + 0x0231, 0x1ED2, 0x1EE3, 0xF3F1, 0x2F12, 0x3212, 0x13FF, 0xFE23, 0x3D20, + 0xDDDF, 0x0E13, 0x030F, 0x1E03, 0x1230, 0xDD1F, 0xDF3F, 0xEFD0, 0xEEDD, + 0xEEDF, 0xD20F, 0xF23E, 0x1E23, 0x3001, 0x1FEE, 0xF122, 0xEDF2, 0x0233, + 0xD3FD, 0xDD33, 0xDD1D, 0x33D3, 0xDD3D, 0xE0DD, 0x331D, 0x1322, 0x2DF2, + 0xE0D1, 0xDE3E, 0xFDD3, 0xE0EE, 0xFF33, 0xDDEE, 0x0E33, 0x2D3E, 0xDF0E, + 0xD2FE, 0xD3FF, 0xD300, 0xF20D, 0xF3E0, 0x12ED, 0x13E2, 0x3F11, 0x221F, + 0x2EF3, 0x3FFD, 0x13F3, 0xDD0E, 0xFDF1, 0xFFFD, 0x11D1, 0x23E1, 0xED12, + 0xFD22, 0x0EDF, 0x02FD, 0x1032, 0x12D2, 0x3DFF, 0x310E, 0x2321, 0x33F1, + 0x3322, 0xD13F, 0xEE20, 0x11DD, 0x2E0E, 0xDFE0, 0x10DE, 0x1320, 0x2332, + 0xDFEE, 0xF0D2, 0x0EF3, 0x3F22, 0x3122, 0x322F, 0x0000, 0x1F3F, 0xED2F, + 0xD302, 0xEED3, 0xFD00, 0xFD1D, 0x0DF0, 0x0D03, 0x2DD2, 0x22D3, 0x223D, + 0x23D2, 0x23ED, 0x3EE3, 0xED30, 0x30D0, 0x32D2, 0xE2E0, 0x0DD2, 0x0D30, + 0x2022, 0x1D02, 0x30EF, 0xFFF3, 0xFD11, 0x32F0, 0xFDEE, 0x2330, 0xF31D, + 0xEDEF, 0x0D01, 0x103E, 0x111D, 0x2E1D, 0x0E3D, 0x033E, 0xDEEF, 0xDF02, + 0x222E, 0xDDF3, 0xD133, 0x032D, 0x13DD, 0xE1E3, 0xE21D, 0xFE32, 0x021D, + 0x0220, 0x13D1, 0x2231, 0x3F02, 0x2DEF, 0x2310, 0x30D2, 0x302D, 0x3032, + 0x31DD, 0xD03E, 0xD232, 0xD331, 0x1313, 0x2DED, 0x232D, 0x02EE, 0x3ED0, + 0x3ED2, 0x2EEE, 0x202E, 0x320F, 0xD0FE, 0xE13E, 0xE2DF, 0x00E2, 0x2F2D, + 0x30FE, 0xD201, 0x301E, 0x32F2, 0xFF3F, 0x1FDF, 0xDDE2, 0xDD20, 0xD131, + 0x2202, 0xEEFD, 0x3DE0, 0x3331, 0xE312, 0xFD2E, 0x122D, 0x3D1F, 0x2DF0, + 0x3FEE, 0xDF2E, 0xE3FE, 0xF22D, 0x0022, 0x10D2, 0xFEDE, 0x13EE, 0x2123, + 0x3E0F, 0x3FE2, 0xDDD1, 0xD023, 0xD2ED, 0xFDFD, 0x0D2D, 0x03ED, 0x0323, + 0x3D0E, 0x3EED, 0x3023, 0x3230, 0x33E2, 0xD320, 0xEEE2, 0xE2D3, 0x0F03, + 0x0132, 0x03F0, 0x1302, 0x131D, 0xD0EF, 0xED1E, 0xE022, 0x302F, 0x31E2, + 0x3102, 0xE310, 0xF00D, 0xE31E, 0x2E3D, 0x33FD, 0x1D33, 0xD3DD, 0xD333, + 0x003D, 0x3DDD, 0x333D, 0x2D1E, 0x3EFE, 0xF21E, 0x121E, 0x00FF, 0x1311, + 0xE3D2, 0xFDDD, 0x22E2, 0x3FD1, 0xD0E1, 0xD0F2, 0xE031, 0x1DEE, 0xD1FF, + 0x1EED, 0x3FF3, 0xD1DD, 0xD31D, 0x0303, 0x3DFD, 0x0E02, 0x002E, 0x1100, + 0x2DFE, 0x2FD2, 0x2FE3, 0x3F20, 0xFDFF, 0x3E01, 0xDE01, 0xF1D1, 0xF131, + 0x2D2F, 0x0011, 0xD30E, 0xED32, 0x1D3D, 0x2D23, 0xD1DF, 0xFDF3, 0xDEFE, + 0xEF3E, 0xFD3F, 0x201D, 0x21E3, 0x2220, 0xF012, 0xFF31, 0xEFE3, 0x3120, + 0x3EF0, 0xDE0F, 0xF1DF, 0xDEDE, 0x230D, 0x3D3D, 0xD0D2, 0x30F0, 0x31FD, + 0xEED1, 0xEF2D, 0xE020, 0xE3F2, 0xFE2D, 0x020E, 0x0222, 0x213E, 0xF13F, + 0x2D10, 0xD2E1, 0x23F2, 0xD1EE, 0x1EF2, 0xEF32, 0xE2F3, 0x2F3E, 0x20D1, + 0x23FE, 0x3021, 0x0E00, 0x21EF, 0xDE03, 0xE033, 0xE2DD, 0xE30D, 0x0E31, + 0x13D3, 0x133D, 0x2EDD, 0xEDD0, 0xEE3D, 0xF030, 0x0FDE, 0xD01E, 0x31DF, + 0x3232, 0xEDFE, 0xEE00, 0xEE22, 0xE1D2, 0xE200, 0xF322, 0x1232, 0x130E, + 0x20E0, 0x22FF, 0x1FD1, 0x3221, 0xF30E, 0x332E, 0x33DF, 0xD20D, 0xD223, + 0x1DE0, 0x20DF, 0xDFD1, 0x3F13, 0xFF00, 0x1111, 0xFD20, 0xDE1E, 0xEF0D, + 0xE03F, 0x1FDD, 0x2FED, 0x21DE, 0x0200, 0xD122, 0x33E0, 0xF33D, 0x3F3D, + 0x3F33, 0x33DD, 0xFE03, 0xF0DE, 0xF223, 0x02E0, 0xE12F, 0x0FE3, 0x00E0, + 0x220E, 0xEE33, 0xFD3D, 0x2E33, 0x20D3, 0xD2D2, 0x3DDF, 0x3E2D, 0xE33E, + 0xE330, 0x0013, 0x02D3, 0x31D1, 0x3113, 0xE12D, 0xFFD3, 0x0EEE, 0x2E13, + 0x1001, 0x0FFE, 0xFFDF, 0x2F32, 0x212D, 0x0E0E, 0x120D, 0x13DF, 0x20F3, + 0xE3F0, 0x2013, 0x2132, 0x10F0, 0x210F, 0xE321, 0xFEED, 0x300F, 0x11EE, + 0x12FE, 0xF3F3, 0x3FDF, 0x32ED, 0x3223, 0xEFDE, 0xEF03, 0x1223, 0xF32E, + 0xF331, 0x3201, 0x3320, 0xDFE2, 0xED10, 0x0020, 0x0112, 0xF003, 0xEFED, + 0x1D31, 0xD0ED, 0x33F3, 0xD00D, 0xD113, 0xD3DF, 0x00F3, 0x03E3, 0x2D03, + 0x3E32, 0xD102, 0xEE02, 0xE22E, 0xF1DD, 0x12E3, 0x20FD, 0xF001, 0xF320, + 0x1131, 0x23F0, 0x21D2, 0xD010, 0x322D, 0x323E, 0xEFF0, 0x012D, 0xF03E, + 0x3311, 0x100F, 0x232F, 0xD012, 0xFD02, 0xF133, 0xF3D1, 0x0EFD, 0x03F2, + 0x2110, 0xFEF2, 0x1DDF, 0x210D, 0xF00F, 0x0F01, 0x010F, 0xFFFF, 0xEF01, + 0xD2EF, 0x100D, 0x13E0, 0xD212, 0xD23E, 0xDD3F, 0xED03, 0xE1D0, 0xFFD1, + 0xF032, 0xF1D3, 0xDE2F, 0xEE11, 0xF221, 0x2FE1, 0x0FEF, 0xE3E1, 0x2EDF, + 0x3FF1, 0x2FEF, 0x0D23, 0x2DE3, 0x203D, 0x300D, 0xDF13, 0xDF31, 0xFF02, + 0xE002, 0x0332, 0x13FD, 0x1331, 0x200E, 0xE11E, 0x221D, 0x2D32, 0xF3FD, + 0xE301, 0x02DF, 0xD11F, 0x2222, 0xE213, 0x0E1D, 0xF010, 0x0110, 0x0FF0, + 0x1DD1, 0x2D2D, 0x2323, 0xE01D, 0x00D3, 0xF023, 0x1133, 0x312E, 0x2D21, + 0xD3E2, 0xE013, 0x1E3E, 0xFED0, 0xF33F, 0x001F, 0xFEF0, 0x123E, 0xD3D3, + 0xE0D3, 0x2D0D, 0x2033, 0x3E0D, 0x3E03, 0x3E23, 0x30DE, 0xFE12, 0xE10D, + 0x2D30, 0x30ED, 0x3313, 0x32E1, 0xFE0D, 0x3F31, 0x0FD0, 0x311F, 0x22D1, + 0xE123, 0x22F3, 0x1E32, 0x2FD0, 0xEDE1, 0x3D11, 0x0F30, 0x001D, 0x3FFF, + 0x1003, 0xDDDD, 0x0E20, 0x10FE, 0xF1E2, 0x3E2F, 0xF100, 0x0121, 0xEF21, + 0x2F23, 0x2E22, 0xDF3D, 0x313D, 0x03D0, 0x3300, 0xDD00, 0xD1D1, 0x1DD3, + 0xE3EF, 0xF2E1, 0xEE1D, 0xE00E, 0xE103, 0x0213, 0xD120, 0x2E00, 0x33FF, + 0xEEEE, 0x1ED0, 0x110E, 0x122F, 0xEFEF, 0x21F0, 0xE2F1, 0x0DE1, 0x1012, + 0x23EF, 0xDD31, 0xD0D0, 0xD100, 0xD203, 0x01DE, 0x22DD, 0x2303, 0x3203, + 0x1010, 0xDE10, 0xD11D, 0xE222, 0xE3D0, 0xE0FD, 0x02DD, 0x0301, 0xDF20, + 0xE32F, 0x01ED, 0xE0F3, 0xE2FD, 0xE121, 0xF3DF, 0x2312, 0x1F00, 0xF0F0, + 0x0F10, 0xF2D2, 0xF2FE, 0xF2F2, 0xED0F, 0xFF13, 0xE21F, 0x032F, 0x0101, + 0x1FE0, 0x1EE1, 0xDED0, 0x33D1, 0xDF33, 0xD0F0, 0xD1FD, 0x3111, 0xE202, + 0x1333, 0x3E3E, 0x3F3F, 0xFDDF, 0x113D, 0x01F0, 0x11FF, 0x0F0F, 0x31F1, + 0xEE1F, 0xE30F, 0x3012, 0xD2F2, 0x11E2, 0xD31F, 0x3003, 0xD2DE, 0xD33F, + 0xEF2F, 0xE231, 0x3EE1, 0x1F31, 0xED0D, 0xE3ED, 0xE323, 0x0DED, 0xDEF0, + 0x2FF2, 0x01D0, 0x030D, 0x1DDD, 0x333F, 0xD2D0, 0xE2EE, 0xF0FE, 0xD221, + 0xF22F, 0xD2F0, 0xFEE1, 0xDD11, 0x0F23, 0x3F00, 0x0D21, 0x21E1, 0x2112, + 0x2301, 0x3EEF, 0xFD31, 0x1D3F, 0xDE21, 0x113F, 0x2130, 0xEF10, 0x1EEF, + 0x2D01, 0x1210, 0x2FF0, 0xDFFF, 0xDD02, 0xDE23, 0xEDF0, 0x003F, 0x1E0D, + 0x1F33, 0x3FE0, 0xE2FF, 0x1E2F, 0x2D0F, 0xD111, 0x11E0, 0x3E10, 0x2EF1, + 0xFD0E, 0x3D22, 0xDE0D, 0xD13D, 0x3D1D, 0x1FFF, 0x0F12, 0x1F02, 0x10F2, + 0x1E12, 0x1D0E, 0x1F3D, 0xFF11, 0xF021, 0x13F1, 0xD22F, 0x2020, 0xDFDF, + 0x0FD2, 0x3D31, 0xE130, 0xFDE2, 0x00F1, 0xF232, 0xF3EE, 0x31E0, 0xDDE0, + 0xEEF3, 0xEE3F, 0x2002, 0x3DF1, 0xE23F, 0xF2E3, 0xDFF1, 0x10ED, 0x2F2F, + 0xE01F, 0xF0E3, 0x3D00, 0xF10E, 0x01FE, 0x20F1, 0xE011, 0x0FF2, 0xE1ED, + 0x0310, 0xDFF3, 0x22EE, 0x23D0, 0xEF0F, 0xFED2, 0x3D2E, 0xD1F3, 0xD2E3, + 0xFE21, 0xF2DE, 0x1F2E, 0x1F22, 0x2101, 0x2E1F, 0x02F3, 0x2EE0, 0xFD1F, + 0x101E, 0x3210, 0x1EDE, 0x2ED1, 0xF120, 0x3E1E, 0x2EFD, 0x313F, 0xEDE3, + 0x01F2, 0xFF2E, 0xF12E, 0x1FF1, 0x10EF, 0xF230, 0xE1F2, 0x1FE2, 0x0DFE, + 0xED3E, 0x0031, 0xD12E, 0xE1FE, 0xF11F, 0x0E11, 0x03E1, 0x2FFE, 0x011E, + 0x32EF, 0x01E3, 0x023D, 0x1D00, 0x3DE2, 0x111F, 0x32FE, 0x0D1E, 0x2E2E, + 0xFF22, 0x0F32, 0xE1F0, 0xE10F, 0xFFF1, 0x012F, 0x12E1, 0xDF22, 0xF210, + 0xE1E1, 0x0E3F, 0x31FF, 0x102D, 0x3E12, 0xED21, 0x11D3, 0xDD2E, 0xDEED, + 0xEF30, 0xE211, 0x0F1E, 0x2F01, 0x12D0, 0xED23, 0xE32D, 0xFD13, 0x10D0, + 0x0DEF, 0xEFD2, 0x2F0D, 0xF111, 0x120F, 0x1D2E, 0x1212, 0x11FD, 0x2E11, + 0x3333, 0xE2E2, 0xF1F1, 0xFF1D, 0x0EF1, 0xD21E, 0x2F21, 0x21F2, 0x230F, + 0x021F, 0xEE13, 0xEFFE, 0x01E1, 0x2F10, 0x1D1F, 0x2121, 0xD0DE, 0xD313, + 0x0ED3, 0xD3F3, 0xF3DD, 0x00DF, 0x1300, 0x303E, 0x31D3, 0xDE30, 0x03D2, + 0x1DF3, 0x1030, 0xFDD1, 0xFF3D, 0xE112, 0x12EF, 0x1F1F, 0xF1F3, 0x2D12, + 0x20E2, 0xDED2, 0xDF00, 0xFE01, 0xE110, 0xF01E, 0xFFE2, 0xEF1E, 0x1DFF, + 0x1FF3, 0xE233, 0xF0D0, 0xF313, 0x311D, 0xE220, 0x0123, 0xDE12, 0x0F3E, + 0xDF1F, 0x0321, 0x022E, 0xD1D3, 0xE03D, 0x3FDD, 0x320D, 0x1F0E, 0x1F1D, + 0x1F13, 0x1102, 0xD22D, 0xE3E3, 0x0330, 0x233E, 0x0FED, 0x1203, 0xFEFE, + 0x1E1E, 0x20FF, 0x10E3, 0x132E, + /* Codebook 7 - 3281 entries */ + 0x0000, 0x00FF, 0x3F00, 0xCC00, 0x1C10, 0x1140, 0xFCEF, 0x4220, 0x43C1, + 0xCCCE, 0xFF40, 0xF2DC, 0xF21C, 0x1E4F, 0x114C, 0x2E1F, 0x30F0, 0xC020, + 0xC2E0, 0x0022, 0x01C1, 0x014F, 0x1012, 0x104D, 0xEF21, 0xFEDC, 0xFFE2, + 0xFF42, 0xF003, 0xF2FE, 0xF212, 0xF4CD, 0x0C40, 0x0DF4, 0x0224, 0x033C, + 0x1EF2, 0x1E21, 0x1FEE, 0x1F22, 0x103C, 0x1212, 0x142D, 0x1421, 0x2DC1, + 0x2FFE, 0x21FE, 0x2141, 0x22FF, 0x2420, 0x4CDF, 0x4C1F, 0x4D01, 0x4E20, + 0x4121, 0x441F, 0xCF01, 0xC301, 0x002C, 0xF3CE, 0xFCD2, 0x0143, 0x012F, + 0x20F1, 0x1F00, 0x00F1, 0x001F, 0x2F10, 0xC400, 0x112C, 0xF40F, 0xF1C2, + 0x002E, 0x1E10, 0x140F, 0x2101, 0x0F4D, 0x004C, 0x0044, 0x02E0, 0x1E43, + 0x10CF, 0xE200, 0x2C11, 0x4F0F, 0x0F4F, 0x1F2C, 0x0200, 0x14E1, 0x401F, + 0xC00E, 0xC3D2, 0xC330, 0xC4F1, 0xCF10, 0x1041, 0xF0F2, 0x0DC1, 0x1F0E, + 0x2F0F, 0x0134, 0x0FDC, 0xFF00, 0x0011, 0x1100, 0x0114, 0xFFFF, 0xC41F, + 0xC431, 0xDC01, 0xDE4F, 0xDE43, 0xDF40, 0xD001, 0xD14E, 0xD2E1, 0xD24F, + 0xD432, 0xECC4, 0xECF3, 0xEDCD, 0xEE42, 0xEFFC, 0xEF1E, 0xEF30, 0xEF41, + 0xE1C1, 0xE2E0, 0xE33C, 0xE42E, 0xE43D, 0xFCC3, 0xFCDE, 0xFCF2, 0xFDCC, + 0xFD4E, 0xFEED, 0xFF1D, 0xFF3D, 0xFF3F, 0xFF31, 0xF030, 0xF1D3, 0xF1FD, + 0xF3FF, 0xF311, 0x0CE4, 0x0C24, 0x0C33, 0x0C42, 0x0D10, 0x0ED1, 0x0E0E, + 0x0E4C, 0x0FD0, 0x003D, 0x01DE, 0x01D0, 0x0132, 0x0310, 0x1CE3, 0x1DFF, + 0x1E2D, 0x1FDF, 0x10C3, 0x1133, 0x12CD, 0x131F, 0x2CE2, 0x2C02, 0x2C22, + 0x2EC2, 0x2EE2, 0x2E20, 0x20C2, 0x20EE, 0x200E, 0x2334, 0x24C2, 0x243D, + 0x3DC0, 0x3E2F, 0x3FF1, 0x3111, 0x3221, 0x34EF, 0x3443, 0x4DD0, 0x4DE1, + 0x4DF2, 0x4D21, 0x4FC1, 0x4FD0, 0x4F12, 0x4F21, 0x42DF, 0x42EE, 0x43D0, + 0x44EE, 0xCD0F, 0xCFEF, 0xDCDE, 0xED10, 0xEEE0, 0xEE1F, 0xEF12, 0xE1F2, + 0xFEFE, 0xF2F4, 0xF22F, 0xF3EC, 0xF41E, 0x0D4F, 0x0222, 0x03F0, 0x1CCF, + 0x1DCE, 0x1DE0, 0x1E4D, 0x1FE2, 0x1F1D, 0x10D4, 0x11C4, 0x11E2, 0x111D, + 0x2343, 0x241F, 0x3CD0, 0x3E10, 0xD401, 0x3F1F, 0x320F, 0xEC40, 0xE2F1, + 0xFED4, 0xF2E1, 0xF340, 0x0CE2, 0x00C4, 0x042E, 0x020C, 0x1104, 0x24FF, + 0x022C, 0x2200, 0x00F3, 0x001D, 0x1111, 0x00C2, 0x41F0, 0xCE11, 0x4EE0, + 0x44D1, 0xCCFF, 0xFDC2, 0x004E, 0x00EC, 0x2110, 0x01E1, 0x134E, 0xC01F, + 0xF1EC, 0x0FED, 0x1FEC, 0xE4F1, 0x10C1, 0x2CE0, 0x011C, 0x0CD1, 0x44F1, + 0xE1F0, 0xEF0F, 0x23C1, 0xCF2F, 0xC121, 0x0E40, 0x02EC, 0x1210, 0x3100, + 0x0F14, 0xD1F1, 0xEC31, 0xE34F, 0xE422, 0xFC32, 0xFDE4, 0xFE4D, 0xFF22, + 0xFF4E, 0xF03C, 0xF23C, 0xF3CC, 0xF3C0, 0xF324, 0xF4D0, 0x0D34, 0x0EE0, + 0x0E02, 0x0FDE, 0x0031, 0x02EE, 0x024C, 0x03FC, 0x04CE, 0x04C0, 0x04EE, + 0x1EEF, 0x1FCC, 0x10CD, 0x10E3, 0x12F2, 0x1223, 0x123C, 0x1243, 0x1342, + 0x1344, 0x2ECE, 0x2EFF, 0x2FE1, 0x2F2F, 0x20C0, 0x21F2, 0x2121, 0x3D00, + 0x340F, 0x3421, 0x4DCF, 0x4D0F, 0xD4F0, 0x4FEF, 0x44FF, 0xEC11, 0xEEEE, + 0xFE4F, 0xF041, 0xF043, 0x0E4E, 0xE01F, 0x1221, 0x14EF, 0xFEC3, 0xF2CD, + 0xF2F0, 0x0FC3, 0x00CE, 0x1EF0, 0xE110, 0x0F41, 0x1C0F, 0x10F4, 0x40FF, + 0xCE20, 0xC321, 0xF4F0, 0x0D41, 0x0EC0, 0x02C0, 0x2C00, 0x0F12, 0x0020, + 0xDF00, 0x2E00, 0xC21F, 0xC220, 0x0FF4, 0x00FD, 0x1F1F, 0x0024, 0x4DF0, + 0xFCF0, 0xF14E, 0x0EE4, 0x0F23, 0x10F0, 0x1DC0, 0x1F44, 0x110C, 0x112E, + 0xFF02, 0x143E, 0x32C1, 0xF0E1, 0x0E1F, 0x0411, 0xF102, 0x0C20, 0x0C31, + 0x0F0D, 0x01DC, 0x014D, 0x0240, 0x101C, 0x120F, 0x0FFC, 0x01CF, 0x124D, + 0x1410, 0x0E00, 0xCC2E, 0x4442, 0xCCC0, 0xCEDF, 0xCE02, 0xCF4F, 0xCF41, + 0xC002, 0xC031, 0xC040, 0xC132, 0xC2EE, 0xC34F, 0xC341, 0xDCC1, 0xDC03, + 0xDC34, 0xDC41, 0xDDEE, 0xDD42, 0xDEC1, 0xDEDC, 0xDEF2, 0xDE12, 0xDE2F, + 0xDE23, 0xDE32, 0xDE4D, 0xDE41, 0xDF0C, 0xDF20, 0xDF3F, 0xD012, 0xD030, + 0xD032, 0xD04F, 0xD041, 0xD1EE, 0xD1E2, 0xD1E4, 0xD120, 0xD14C, 0xD142, + 0xD2D2, 0xD2FE, 0xD2F2, 0xD232, 0xD243, 0xD3D3, 0xD30E, 0xD31D, 0xD320, + 0xD33D, 0xD331, 0xD42D, 0xD44F, 0xECCC, 0xECC2, 0xECD1, 0xECD3, 0xECE4, + 0xEC02, 0xEDD4, 0xEDF2, 0xED14, 0xEECC, 0xEEC2, 0xEEC4, 0xEEFD, 0xEE1D, + 0xEE2E, 0xEE33, 0xEFCF, 0xEFDE, 0xEF3C, 0xEF32, 0xE0F3, 0xE1CD, 0xE123, + 0xE2C2, 0xE2C4, 0xE2EC, 0xE2E4, 0xE233, 0xE3C1, 0xE3DC, 0xE3D0, 0xE3F2, + 0xE3F4, 0xE31E, 0xE4CE, 0xE4C2, 0xE4E4, 0xE402, 0xFCD4, 0xFDDF, 0xFDE0, + 0xFD04, 0xFED0, 0xFE03, 0xFE43, 0xFFD3, 0xF03E, 0xF032, 0xF133, 0xF20D, + 0xF223, 0xF3EE, 0xF3E0, 0xF3F1, 0xF33F, 0xF4D4, 0xF414, 0x0CCE, 0x0CC0, + 0x0CC2, 0x0CC4, 0x0C0E, 0x0C04, 0x0C44, 0x0DDC, 0x0DD2, 0x0DE1, 0x0D1E, + 0x0EDF, 0x0EF3, 0x02C4, 0x02F3, 0x0213, 0x023D, 0x03E1, 0x03FE, 0x0301, + 0x032F, 0x033E, 0x0332, 0x04C2, 0x04DD, 0x04D3, 0x0402, 0x042C, 0x1CD4, + 0x1C43, 0x1DDF, 0x1D2C, 0x1EED, 0x1EE3, 0x1FD3, 0x10D2, 0x11DD, 0x122D, + 0x123E, 0x13CC, 0x13D1, 0x13FD, 0x1320, 0x1324, 0x1432, 0x1434, 0x1443, + 0x2C13, 0x2C4E, 0x2D0F, 0x2D1E, 0x2D3C, 0x2D30, 0x2D4D, 0x2E0C, 0x2E1D, + 0x2E2C, 0x2E44, 0x2FD0, 0x2FED, 0x2F4D, 0x20CC, 0x20DF, 0x201D, 0x2013, + 0x202E, 0x21D2, 0x21ED, 0x213C, 0x213E, 0x22CC, 0x22EE, 0x22E2, 0x22FD, + 0x2202, 0x23C3, 0x23E1, 0x23F4, 0x2310, 0x232F, 0x24CC, 0x240C, 0x240E, + 0x241D, 0x2422, 0x244C, 0x2442, 0x3C2D, 0x3C32, 0x3C4F, 0x3C43, 0x3DC2, + 0x3D3F, 0x3EE1, 0x3E1E, 0x3E14, 0x3E2D, 0x3E21, 0x3E43, 0x3FE2, 0x3F4E, + 0x30E1, 0x3012, 0x302F, 0x31CC, 0x3120, 0x3122, 0x3142, 0x32CF, 0x32C3, + 0x32FC, 0x32F4, 0x324F, 0x33E0, 0x33FF, 0x3311, 0x3331, 0x3342, 0x34DE, + 0x34E3, 0x3412, 0x3432, 0x4DCD, 0x4DC1, 0x4DD2, 0x4D32, 0x4D4F, 0x4EC2, + 0x4E0E, 0x4E31, 0x4FCD, 0x4FD2, 0x4F1E, 0x4F30, 0x40DF, 0x402E, 0x403F, + 0x4040, 0x41DE, 0x41F2, 0x414F, 0x42E4, 0x4202, 0x4222, 0x423F, 0x43CD, + 0x43CF, 0x43F2, 0x432D, 0x4323, 0x44DF, 0x44D3, 0xCCD1, 0x44FD, 0x4402, + 0xCD30, 0xCE22, 0xCE31, 0xCFD0, 0xCFE1, 0xC0EE, 0xC0E0, 0xC2D1, 0xC202, + 0xC22E, 0xC3F2, 0xDCD2, 0xDCF2, 0xDC3E, 0xDDFF, 0xDD40, 0xDEEF, 0xD20F, + 0xD201, 0xD311, 0xD32C, 0xD4ED, 0xD430, 0xEC33, 0xEDDC, 0xEE22, 0xEFC3, + 0xEFE1, 0xEF34, 0xE0E0, 0xE042, 0xE11C, 0xE22E, 0xE3F0, 0xE301, 0xE321, + 0xE4DF, 0xE4FD, 0xFCC1, 0xFCE3, 0xFC23, 0xFDF1, 0xFE30, 0xF0ED, 0xF14C, + 0xF2E3, 0xF2FC, 0xF21E, 0xF3E2, 0xF3E4, 0xF4ED, 0xF4F2, 0xF432, 0x0C13, + 0x0DD4, 0x0E1D, 0x0E3F, 0x0FE3, 0x0F30, 0x01D2, 0x02DF, 0x021D, 0x0233, + 0x03CD, 0x031C, 0x0321, 0x04F3, 0x0422, 0x044C, 0x1C2D, 0x1C34, 0x1DEC, + 0x1D04, 0x1D24, 0x1FC4, 0x1F3F, 0x10DE, 0x11D1, 0x12F4, 0x120D, 0x134C, + 0x141C, 0x143C, 0x2CEE, 0x2D2F, 0x2EEE, 0x2FCD, 0x2FD4, 0x2F1E, 0x2F41, + 0x2F43, 0x202C, 0x2044, 0x21DC, 0x21F4, 0x2112, 0x214D, 0x214F, 0x22E0, + 0x2231, 0x224E, 0x2242, 0x24CE, 0x24E2, 0x2440, 0x3CDE, 0x3C30, 0x3EEF, + 0x321E, 0x33C0, 0x3344, 0x4D1E, 0x4D3E, 0x4EC0, 0x4E3F, 0x4FF2, 0x40EE, + 0x4020, 0x4022, 0x411E, 0x4112, 0x412F, 0xC1EF, 0xC231, 0xDCE1, 0xDC21, + 0xDE01, 0xDE10, 0xDF1F, 0xECE2, 0xECF1, 0xE2E2, 0xE220, 0xFC41, 0xFD20, + 0xFECD, 0xFE21, 0xFF2E, 0xF00D, 0xF02D, 0xF023, 0xF1EE, 0xF11D, 0xF2C3, + 0xF31F, 0xF43E, 0x0C2E, 0x0EC4, 0x0EEE, 0x0F3E, 0x003F, 0x0033, 0x013E, + 0x034D, 0x1CF2, 0x1C23, 0x1D44, 0x1ED4, 0x1EFE, 0x10DC, 0x10ED, 0x100D, + 0x1113, 0x1311, 0x1340, 0x14CF, 0x14DE, 0x1430, 0x2E40, 0x21CF, 0x2321, + 0x4CF1, 0x432F, 0x4420, 0xCE1F, 0xDC10, 0xF04F, 0xF10C, 0x0FCD, 0x02C2, + 0x11C2, 0x12C1, 0x20E0, 0x41EF, 0xC2FF, 0xFFC0, 0xF01C, 0xF02F, 0xF021, + 0xF1E0, 0x0E24, 0x11E0, 0xFFC2, 0x1102, 0x201F, 0xF410, 0x24F1, 0x4FF0, + 0x42F1, 0x43F0, 0x0E11, 0x2C1F, 0x4310, 0x0FF2, 0xD010, 0xE341, 0xFC21, + 0xF124, 0xF241, 0x0C22, 0x012D, 0x0123, 0x0420, 0x1CE1, 0x1E2F, 0x1241, + 0xE0FF, 0x2EF1, 0x3410, 0xFE0F, 0xFFEC, 0x0E04, 0x00EE, 0x02F1, 0x1F24, + 0x2CFF, 0x01FC, 0x4000, 0xD421, 0x4321, 0xCC3F, 0xCD01, 0xFC2F, 0x0E42, + 0x0FD4, 0x1FE0, 0x1F20, 0x10EF, 0xF401, 0x110E, 0x2DCF, 0x2FF0, 0x21F0, + 0xC11E, 0xC12F, 0xC130, 0xC4E0, 0xDF11, 0xD00F, 0xD340, 0xECCE, 0xECDF, + 0xEC2E, 0xED41, 0xEE11, 0xE00E, 0xE1EF, 0xE112, 0xE24E, 0xE4E0, 0xFC12, + 0xFE12, 0xFE14, 0xFE3C, 0xFFCC, 0xFFDF, 0xFFF3, 0xFF4C, 0xF1C4, 0xF12E, + 0xF2EF, 0xF24D, 0xF320, 0x0CDF, 0x0D14, 0x01F0, 0x0E13, 0x0E22, 0x0E31, + 0x0FD2, 0x00D1, 0x0242, 0x1DE4, 0x1EFC, 0x1E1C, 0x1FCE, 0x1F13, 0x102D, + 0x1034, 0x11EE, 0x11F3, 0x2C3F, 0x2E42, 0x2FC1, 0x22C2, 0x22EC, 0x23F0, + 0x3CCF, 0x3CE1, 0x3F11, 0x300F, 0x342F, 0x4F2F, 0x41E1, 0xCEE0, 0xED4F, + 0xE21F, 0xE420, 0xFECF, 0xFE41, 0xFFC4, 0xF430, 0x0E2C, 0x04DF, 0x1E1E, + 0x1F4C, 0x13C0, 0x14FE, 0xC0F1, 0x2411, 0x3C2F, 0xC411, 0xEEFF, 0xFFE0, + 0xF0DC, 0xF0F4, 0xF10E, 0xF20F, 0x0C11, 0x0EC2, 0x0FCF, 0x0141, 0x024E, + 0xEF01, 0x11E4, 0x1122, 0xF001, 0xF1F1, 0x1FF1, 0xF421, 0x01FE, 0x3401, + 0x4D2F, 0xCD2F, 0xC2F1, 0xFE01, 0xF104, 0x00E2, 0xE411, 0x10E1, 0x3CF0, + 0x0F01, 0x100F, 0xF010, 0x010F, 0xF00F, 0x111F, 0x00E0, 0x14F0, 0xF01E, + 0xECE0, 0xFCD0, 0xFEFC, 0xFE2F, 0xCDF0, 0xF0D4, 0xF4DE, 0x1CD0, 0x1ECF, + 0xE0F1, 0x1EE1, 0x1EF4, 0xE431, 0xFF0E, 0xFF24, 0xF0FC, 0xF201, 0x021F, + 0x1E0F, 0x2CC0, 0x1001, 0xFF1F, 0x12F0, 0x2011, 0x4E1F, 0xC310, 0x410F, + 0x121E, 0xCCDD, 0x4433, 0xCCC2, 0xCCC4, 0xCCDF, 0xCCE2, 0xC200, 0xEF10, + 0xCC1F, 0xFDCE, 0xCE00, 0xFFCE, 0xF120, 0x0EF1, 0x02CE, 0x0F10, 0x0FF0, + 0xFF11, 0x1EC1, 0x1E01, 0x2211, 0x3CEF, 0x011E, 0x3010, 0x4EF1, 0xC000, + 0x0F3C, 0x10FE, 0x4E11, 0xCC20, 0xCC31, 0xCD1E, 0xCD4F, 0xCED1, 0xCE2E, + 0xCFFE, 0xCF32, 0xC1F0, 0xE400, 0x104F, 0xC03F, 0xC1F2, 0xC2DF, 0xC20E, + 0xC3FE, 0xC32F, 0xC4E2, 0xC42E, 0xDC12, 0xDF2E, 0xD1E0, 0xD4D2, 0xD42F, + 0xEC22, 0xEC4E, 0xEDC1, 0x1FFF, 0xCFF0, 0xF0F0, 0xEDC3, 0xEDEF, 0xED2F, + 0xEEDD, 0xEFCD, 0xEFFE, 0xEF4D, 0xEF43, 0xE0C2, 0xE0EE, 0xE0E4, 0xE002, + 0xE004, 0xE022, 0xE13E, 0xE132, 0xE143, 0xE2D3, 0xE20E, 0xE22C, 0xE231, + 0xE3CD, 0xE3C3, 0xE3E1, 0xE3FE, 0xE310, 0xE4C0, 0xE4EC, 0xE4E2, 0xE442, + 0xFCED, 0xFC43, 0xFDD1, 0xFDEE, 0xFDFF, 0xFD22, 0xFEDE, 0xFED2, 0xFEF2, + 0xFF13, 0xFF33, 0xF0D2, 0xF2D2, 0xF230, 0xF243, 0xF3C4, 0xF331, 0xF4C1, + 0xF4DC, 0xF4FE, 0x0D43, 0x03D4, 0x03F4, 0x0334, 0x04E2, 0x04FD, 0x041D, + 0x1C4D, 0x1DC2, 0x1D11, 0x1ECD, 0x1ED2, 0x1FD1, 0x1F33, 0x10D0, 0x11D3, + 0x12DE, 0x12D0, 0x12D4, 0x12E3, 0x13EC, 0x13F1, 0x14C3, 0x14F2, 0x141E, + 0x2C0E, 0x2C1D, 0x2DDE, 0x2DEF, 0x2D14, 0x2D4F, 0x2EEC, 0x2E3F, 0x2E31, + 0x2FCF, 0x2FC3, 0x2FDC, 0x2F3C, 0x20E2, 0x20E4, 0x2022, 0x2024, 0x204E, + 0x2042, 0x21E3, 0x2132, 0x22CE, 0x22D1, 0x224C, 0x2341, 0x242E, 0x243F, + 0x244E, 0x3CC1, 0x3CD2, 0x3CED, 0x3DF1, 0x3D1F, 0x3D11, 0x3D40, 0x3ECF, + 0x3ED4, 0x3FFF, 0x32ED, 0x3201, 0x341E, 0x343E, 0x4C20, 0x4DDE, 0x4ED1, + 0x4E22, 0x4FFE, 0x42E2, 0x43DE, 0xCF30, 0x43FE, 0x4332, 0xDD00, 0xDFE0, + 0xD300, 0xD4E1, 0xD4F2, 0xEDDE, 0xEEC0, 0xEE04, 0xEE24, 0xEE4E, 0xE242, + 0xFC1E, 0xFD11, 0xFE1C, 0xFE1E, 0xFFD1, 0xF44F, 0x0C3F, 0x0EE2, 0x0E2E, + 0x0130, 0x02E4, 0x020E, 0x0341, 0x1CD2, 0x1C32, 0x1C41, 0x1DF1, 0x1EC3, + 0x1FF3, 0x1030, 0x11CC, 0x11DF, 0x1131, 0x1144, 0x1300, 0x132C, 0x2CD1, + 0x2D41, 0x21E1, 0x211E, 0x2220, 0x23CF, 0x3E0F, 0x34C1, 0x4EDF, 0x4EEE, + 0x430F, 0xD210, 0xD241, 0xEFEF, 0xE11E, 0xF1E2, 0x0F2D, 0x0220, 0x1E34, + 0x0110, 0x11CE, 0x12CF, 0x12EF, 0x121C, 0xFEEF, 0x221F, 0x31FF, 0xF014, + 0xF2C1, 0x0C1F, 0x0EFF, 0x1F02, 0x24E0, 0x3C10, 0x42E0, 0xF0C1, 0x114E, + 0xF11F, 0xFC10, 0x42FF, 0x40E0, 0xC1E1, 0x0FC1, 0x1F42, 0x0F0F, 0x11FF, + 0x0112, 0xC211, 0xD410, 0xFFEE, 0xFF20, 0xF1FF, 0x01C3, 0x010D, 0x1CEF, + 0x1F4E, 0x0042, 0x102F, 0x1021, 0x1010, 0xFFF1, 0xFC0F, 0x34E1, 0xC30F, + 0xC4FF, 0x2400, 0xD1FF, 0xD140, 0xD2F0, 0xEEF1, 0x4110, 0xF111, 0x0101, + 0x11F1, 0xFCE1, 0xF0CD, 0xF142, 0xF144, 0xF300, 0xF34E, 0x0E20, 0x1C12, + 0x1C21, 0x1C30, 0x1D00, 0x1E14, 0x1E3C, 0x1FC2, 0x12E1, 0x12FC, 0x1214, + 0x21C1, 0x34D0, 0x4EFF, 0xCEFF, 0x43E1, 0x4301, 0xC101, 0xECFF, 0xE011, + 0xFF0C, 0xFF2C, 0x02FF, 0x041F, 0x1C2F, 0xFE10, 0x14D0, 0x3210, 0xF1CE, + 0x0FE1, 0x0F21, 0x101E, 0x2CDF, 0x4211, 0xC011, 0xEE40, 0xE240, 0xF1C0, + 0xF2CF, 0x0CFF, 0x0F2F, 0x4E00, 0x0F43, 0x10F2, 0x4D10, 0xEC20, 0xF0EF, + 0xF42F, 0x04FF, 0x1C01, 0x1FC0, 0x1043, 0x1120, 0x1201, 0x2CF1, 0x24D1, + 0x4CFF, 0x4F01, 0x4011, 0x00E4, 0xFEC1, 0xF0CF, 0x1401, 0x4C00, 0x2000, + 0xE101, 0xCCE0, 0x44E0, 0xCCD3, 0xCCEC, 0xCCE4, 0xCCFD, 0xCDE1, 0xCD21, + 0xC1D0, 0xC23F, 0xC420, 0xD11F, 0xD3FF, 0xD40F, 0xD441, 0xEDF0, 0xEE02, + 0xE0C0, 0xE1D4, 0xE1E1, 0xE1FE, 0xE4D1, 0xE43F, 0xFDEC, 0xFD00, 0xFD1F, + 0xFE23, 0xFFDD, 0xFFFD, 0xF1DF, 0xF113, 0xF13F, 0xF214, 0xF234, 0xF412, + 0x0CF3, 0x0D0F, 0x0ECC, 0x00D3, 0x022E, 0x04D1, 0x040E, 0x1CC1, 0x1C1E, + 0x1C4F, 0x1E12, 0x1E3E, 0x1F31, 0x103E, 0x113D, 0x113F, 0x13CE, 0x13E0, + 0x14C1, 0x14ED, 0x144D, 0x2C2E, 0x2D10, 0x2D21, 0x2EE0, 0x2E02, 0x2E4E, + 0x2F21, 0x2F4F, 0x220E, 0x2240, 0x234D, 0x3CF2, 0x3C01, 0x3C21, 0x34D2, + 0x4CE0, 0xCE3F, 0x42D1, 0x43EF, 0xCF21, 0xC3E1, 0xE121, 0xE2FF, 0xE211, + 0xFDC4, 0xFEE1, 0xFE34, 0xFF04, 0xF122, 0xF2D4, 0x0EEC, 0x00DF, 0x0204, + 0x043F, 0x044E, 0x1D40, 0x1FFD, 0x1F04, 0x12FE, 0x122F, 0x144F, 0x2C20, + 0x2222, 0xCDEF, 0xD0F0, 0xE440, 0xF1CC, 0xFEF0, 0x0CF1, 0x0F34, 0x00C0, + 0xF012, 0x0121, 0x1F11, 0x0C00, 0x1E41, 0x4101, 0x40F1, 0xDFF1, 0x01F2, + 0xEC3F, 0x01CD, 0x2F01, 0xDCF0, 0xFC30, 0xFFE4, 0xF24F, 0x00CC, 0x1FE4, + 0x0004, 0x4F10, 0x11EC, 0x1234, 0x22C0, 0x24C0, 0xEC00, 0x0FEF, 0x01F4, + 0x0F1E, 0x2EC0, 0x3C0F, 0xD111, 0xEF2F, 0x4200, 0xEC1F, 0xEE00, 0x0002, + 0xC110, 0xF210, 0x1CF0, 0x0FFE, 0xE141, 0xE4FF, 0xF034, 0xF221, 0xF4E1, + 0x0DC3, 0x1003, 0x11FD, 0xE000, 0xCF0F, 0x21EF, 0x31F1, 0xDEF0, 0xE040, + 0xF4EF, 0x013C, 0x0211, 0x04E0, 0x1D42, 0x1F2E, 0x10FC, 0x11C0, 0x03CF, + 0x1124, 0x34F0, 0x0F1C, 0xD100, 0x034F, 0x1142, 0xCD10, 0xC3F0, 0x421F, + 0x4431, 0xCCF3, 0xCC0C, 0xCC02, 0xCC04, 0xCC1D, 0xCC13, 0xCC2C, 0xCC24, + 0xCC3D, 0xCC33, 0xCC4C, 0xCC4E, 0xCC42, 0xCC44, 0xCDCD, 0xCDCF, 0xF100, + 0x000C, 0xE10F, 0x1F40, 0x20FF, 0x210F, 0xEFF0, 0xCEF1, 0xC0FF, 0xE41F, + 0xFC01, 0x000E, 0xFD40, 0xF0C3, 0xF1E4, 0xF12C, 0xF140, 0x01E3, 0x1F0C, + 0x1014, 0x01EF, 0x4411, 0xCDC1, 0xCDDC, 0xCDD4, 0xCDE3, 0xCDFC, 0xCDF4, + 0xCD0D, 0xCD03, 0xCD1C, 0xCD14, 0xCD2D, 0xCD23, 0xCD3C, 0xCD34, 0xCD4D, + 0xCD41, 0xCECC, 0xCECE, 0xCEC0, 0xCEC2, 0xCEC4, 0xCED3, 0xCEEC, 0xCEEE, + 0xCEE2, 0xCEFD, 0xCEF3, 0xCE0C, 0xCE04, 0xCE1D, 0xCE13, 0xCE2C, 0x0040, + 0x04F1, 0x0400, 0x124F, 0x4400, 0xCE24, 0xCE3D, 0xCE33, 0xCE4C, 0xCE42, + 0xCE44, 0xCFCD, 0xCFCF, 0xCFC1, 0xCFC3, 0xCFDC, 0xCFD2, 0xCFD4, 0xCFED, + 0xCFE3, 0xCFFC, 0xCFF2, 0xCFF4, 0xCF0D, 0xCF03, 0xCF1C, 0xCF1E, 0xCF3C, + 0xCF34, 0xCF4D, 0xCF43, 0xC0CC, 0xC0CE, 0xC0C0, 0xC0C2, 0xC0C4, 0xC0D1, + 0xC0D3, 0xC0EC, 0xC0E2, 0xC0E4, 0xC0F3, 0xC00C, 0xC004, 0xC013, 0xC02C, + 0xC022, 0xC024, 0xC03D, 0xC033, 0xC04E, 0xC042, 0xC044, 0xC1CF, 0xC1C3, + 0xC1DC, 0xC1D2, 0xC1D4, 0xC1ED, 0xC1E3, 0xC1FC, 0xC1F4, 0xC10D, 0xC11C, + 0xC112, 0xC114, 0xC12D, 0xC123, 0xC13C, 0x0013, 0xC134, 0xC14D, 0xC14F, + 0xC143, 0xC2CC, 0xC2CE, 0xC2C0, 0xC2C2, 0xC2C4, 0xC2D3, 0xC2EC, 0xC2E4, + 0xC2FD, 0xC20C, 0xC204, 0xC21D, 0xC213, 0xC22C, 0xC224, 0xC23D, 0xC233, + 0xC24C, 0xC24E, 0xC240, 0xC3CD, 0xC3C3, 0xC3DC, 0xC3D4, 0xC3ED, 0xC3F4, + 0xC30D, 0xC303, 0xC31C, 0xC312, 0xC314, 0xC32D, 0xC33C, 0xC33E, 0xC334, + 0xC34D, 0xC4CC, 0xC4CE, 0xC4C0, 0xC4C2, 0xC4C4, 0xC4DF, 0xC4EC, 0xC4EE, + 0xC4FD, 0xC4F3, 0xC40E, 0xC402, 0xC404, 0xC41D, 0xC413, 0xC42C, 0xC424, + 0xC43D, 0xC433, 0xC44C, 0xC442, 0xC444, 0xDCCF, 0xDCDC, 0xDCED, 0xDCE3, + 0xDCFC, 0xDCF4, 0xDC0D, 0xDC1C, 0xDC14, 0xDC3C, 0xDC43, 0xDDCE, 0xDDC4, + 0xDDD1, 0xDDD3, 0xDDE2, 0xDDE4, 0xDDFD, 0xDDF3, 0xDD0C, 0xDD0E, 0xDD1D, + 0xDD1F, 0xDD13, 0xDD24, 0xDD3D, 0xDD3F, 0xDD31, 0xDD33, 0xDD4C, 0xDD44, + 0xDECD, 0xDEC3, 0xDED0, 0xDED2, 0xDEED, 0xDEE3, 0xDEFC, 0xDEF4, 0xDE0D, + 0xDE03, 0xDE1C, 0xDE1E, 0xDE14, 0xDE2D, 0xDE3C, 0xDE3E, 0xDE30, 0xDFCC, + 0xDFC0, 0xDFC2, 0xDFC4, 0xDFDD, 0xDFD1, 0xDFD3, 0xDFEC, 0xDFE2, 0xDFFD, + 0xDFF3, 0xDF02, 0xDF04, 0xDF1D, 0xDF24, 0xDF3D, 0xDF31, 0xDF33, 0xDF4C, + 0xDF4E, 0xDF44, 0xD0CD, 0xD0CF, 0xD0C3, 0xD0DC, 0xD0D0, 0xD0D2, 0xD0D4, + 0xD0ED, 0xD0EF, 0xD0E1, 0xD0FC, 0xD0FE, 0xD0F4, 0xD00D, 0xD003, 0xD014, + 0xD02D, 0xD023, 0xD03C, 0xD034, 0xD04D, 0xD1C4, 0xD1DD, 0xD1DF, 0xD1D1, + 0xD1D3, 0xD1FD, 0xD1F3, 0xD10C, 0xD10E, 0xD102, 0xD11D, 0xD113, 0xD12E, + 0xD122, 0xD124, 0xD13D, 0xD13F, 0xD131, 0xD133, 0xD144, 0xD2CD, 0xD2CF, + 0xD2C1, 0xD2C3, 0xD2DE, 0xD2D0, 0xD2D4, 0xD2ED, 0xD20D, 0xD203, 0xD21C, + 0xD21E, 0xD212, 0xD223, 0xD23C, 0xD230, 0xD234, 0xD24D, 0xD3CC, 0xD3CE, + 0xD3DD, 0xD3DF, 0xD3D1, 0xD3EE, 0xD3E2, 0xD3E4, 0xD3FD, 0xD3F3, 0xD30C, + 0xD302, 0xD304, 0xD31F, 0xD313, 0xD32E, 0xD324, 0xD33F, 0xD333, 0xD34C, + 0xD34E, 0xD344, 0xD4CD, 0xD4CF, 0xD4DC, 0xD4DE, 0xD4D0, 0xD4D4, 0xD4FC, + 0xD4FE, 0xD4F4, 0xD40D, 0xD403, 0xD41C, 0xD412, 0xD414, 0xD423, 0xD43C, + 0xD43E, 0xD434, 0xD44D, 0xECC0, 0xECDD, 0xECEC, 0xEC0C, 0xEC04, 0xEC1D, + 0xEC2C, 0xEC3D, 0xEC4C, 0xEC42, 0xEC44, 0xEDD0, 0xEDD2, 0xEDED, 0xEDE1, + 0xEDE3, 0xEDFC, 0xEDFE, 0xEDF4, 0xED0D, 0xED03, 0xED1C, 0xED1E, 0xED12, + 0xED2D, 0xED23, 0xED3E, 0xED32, 0xEED1, 0xEED3, 0xEEE4, 0xEE0E, 0xEE2C, + 0xEE3D, 0xEE3F, 0xEE4C, 0xEE44, 0xEFD0, 0xEFD2, 0xEF0D, 0xEF03, 0xEF1C, + 0xEF2D, 0xE0CC, 0xE0DD, 0xE0DF, 0xE0D1, 0xE0D3, 0xE0FD, 0xE01D, 0xE03D, + 0xE033, 0xE044, 0xE1DC, 0xE1DE, 0xE1D0, 0xE1D2, 0xE1ED, 0xE10D, 0xE103, + 0xE13C, 0xE2DD, 0xE2FD, 0xE2F3, 0xE23D, 0xE23F, 0xE244, 0xE3D2, 0xE3ED, + 0xE3E3, 0xE30D, 0xE303, 0xE312, 0xE314, 0xE32D, 0xE323, 0xE33E, 0xE332, + 0xE334, 0xE4CC, 0xE4C4, 0xE4F3, 0xE40C, 0xE404, 0xE41D, 0xE424, 0xE433, + 0xE44C, 0xE444, 0xFCFC, 0xFC1C, 0xFC14, 0xFC2D, 0xFC3C, 0xFC3E, 0xFDD3, + 0xFDE2, 0xFDFD, 0xFDF3, 0xFD0C, 0xFD0E, 0xFD1D, 0xFD13, 0xFD2C, 0xFD3D, + 0xFD3F, 0xFD33, 0xFD4C, 0xF1DD, 0xF13D, 0xF203, 0xF22D, 0xF232, 0xF3DD, + 0xF3DF, 0xF3D1, 0xF3FD, 0xF3F3, 0xF302, 0xF31D, 0xF313, 0xF32E, 0xF33D, + 0xF333, 0xF4C3, 0xF4E3, 0xF4FC, 0xF4F4, 0xF41C, 0xF423, 0xF434, 0xF443, + 0x0CDD, 0x0CEC, 0x0C2C, 0x0C3D, 0x0DED, 0x0DE3, 0x0DFC, 0x0DFE, 0x0D0D, + 0x0D03, 0x0D1C, 0x0D12, 0x0D23, 0x0D3C, 0x0D3E, 0x0D30, 0x0ED3, 0x0EFD, + 0x0E3D, 0x02D1, 0x0231, 0x03DE, 0x03D0, 0x03D2, 0x03ED, 0x03E3, 0x03F2, + 0x030F, 0x0303, 0x031E, 0x032D, 0x0323, 0x0330, 0x04CC, 0x04C4, 0x04E4, + 0x0404, 0x0413, 0x0424, 0x0433, 0x0444, 0x1CCD, 0x1CC3, 0x1CDC, 0x1CF4, + 0x1C0D, 0x1C1C, 0x1C3C, 0x1DCC, 0x1DEE, 0x1DFD, 0x1DF3, 0x1D0C, 0x1D13, + 0x1D2E, 0x1D22, 0x1D3D, 0x1D3F, 0x1D33, 0x1D4C, 0x1ED0, 0x1E0D, 0x1E03, + 0x1E32, 0x1023, 0x12C3, 0x12D2, 0x12ED, 0x1203, 0x13C4, 0x13DD, 0x13DF, + 0x13D3, 0x13EE, 0x13E2, 0x13E4, 0x13F3, 0x130C, 0x1302, 0x1304, 0x1313, + 0x1322, 0x133D, 0x1331, 0x14CD, 0x14D4, 0x14F4, 0x1403, 0x1412, 0x1414, + 0x1423, 0x2CCC, 0x2CC2, 0x2CC4, 0x2CDD, 0x2CE4, 0x2CFD, 0x2CF3, 0x2C0C, + 0x2C04, 0x2C2C, 0x2C24, 0x2C33, 0x2C4C, 0x2C40, 0x2C44, 0x2DCD, 0x2DC3, + 0x2DD0, 0x2DD2, 0x2DD4, 0x2DED, 0x2DE1, 0x2DFE, 0x2DF2, 0x2D0D, 0x2D03, + 0x2D1C, 0x2D12, 0x2D2D, 0x2D23, 0x2D3E, 0x2D32, 0x2D43, 0x2EDD, 0x2ED3, + 0x2EFD, 0x2E0E, 0x2E04, 0x2E13, 0x2E3D, 0x2E33, 0x2E4C, 0x2FD2, 0x2FFC, + 0x2F0D, 0x2F03, 0x2F1C, 0x2F14, 0x2F23, 0x2F30, 0x2F32, 0x20C4, 0x20DD, + 0x20D3, 0x203D, 0x203F, 0x2031, 0x2033, 0x204C, 0x21D4, 0x2103, 0x212D, + 0x2130, 0x2143, 0x22C4, 0x22DD, 0x22DF, 0x22D3, 0x22F3, 0x221D, 0x222C, + 0x223D, 0x223F, 0x23CD, 0x23D2, 0x23ED, 0x23E3, 0x23F2, 0x230D, 0x2314, + 0x232D, 0x2323, 0x233C, 0x233E, 0x24C4, 0x24EC, 0x24F3, 0x2402, 0x2404, + 0x2413, 0x2424, 0x3CCD, 0x3CC3, 0x3CDC, 0x3CD4, 0x3CE3, 0x3CFC, 0x3CF4, + 0x3C0D, 0x3C1E, 0x3C3C, 0x3C34, 0x3DCC, 0x3DCE, 0x3DC4, 0x3DDD, 0x3DDF, + 0x3DD1, 0x3DD3, 0x3DEC, 0x3DEE, 0x3DE0, 0x3DE2, 0x3DE4, 0x3DFD, 0x3DF3, + 0x3D0C, 0x3D0E, 0x3D02, 0x3D04, 0x3D1D, 0x3D2E, 0x3D20, 0x3D24, 0x3D31, + 0x3D4C, 0x3D44, 0x3ECD, 0x3EC3, 0x3ED0, 0x3ED2, 0x3EED, 0x3EFC, 0x3EFE, + 0x3EF2, 0x3EF4, 0x3E0D, 0x3E03, 0x3E1C, 0x3E23, 0x3E3E, 0x3E30, 0x3E32, + 0x3E4D, 0x3FC4, 0x3FDD, 0x3FD1, 0x3FEC, 0x3FEE, 0x3FE0, 0x3FE4, 0x3FFD, + 0x3F0C, 0x3F04, 0x3F1D, 0x3F13, 0x3F2E, 0x3F22, 0x3F24, 0x3F3D, 0x3F3F, + 0x3F31, 0x3F33, 0x3F4C, 0x3F40, 0x3F42, 0x3F44, 0x30CD, 0x30CF, 0x30C1, + 0x30C3, 0x30DC, 0x30DE, 0x30D0, 0x30D2, 0x30ED, 0x30E3, 0x30F4, 0x300D, + 0x3003, 0x301C, 0x302D, 0x3021, 0x3023, 0x303C, 0x303E, 0x3030, 0x3032, + 0x3034, 0x304F, 0x3041, 0x3043, 0x31C2, 0x31C4, 0x31D3, 0x31E4, 0x31FD, + 0x31F3, 0x310C, 0x3102, 0x3104, 0x311D, 0x3113, 0x312E, 0x3124, 0x313D, + 0x313F, 0x3131, 0x3133, 0x314C, 0x3140, 0x32CD, 0x32DC, 0x32DE, 0x32D0, + 0x32D2, 0x32D4, 0x32E3, 0x320D, 0x3203, 0x3212, 0x3214, 0x322D, 0x3223, + 0x323E, 0x3230, 0x3234, 0x324D, 0x3241, 0x3243, 0x33CC, 0x33DD, 0x33DF, + 0x33D1, 0x33D3, 0x33EE, 0x33E2, 0x33E4, 0x33F3, 0x330C, 0x330E, 0x3302, + 0x3304, 0x331D, 0x3313, 0x3320, 0x333D, 0x333F, 0x3340, 0x34CD, 0x34C3, + 0x34D4, 0x34FC, 0x34F4, 0x3403, 0x341C, 0x3414, 0x342D, 0x3423, 0x3434, + 0x344D, 0x344F, 0x3441, 0x4CCC, 0x4CCE, 0x4CC0, 0x4CC2, 0x4CC4, 0x4CDD, + 0x4CD1, 0x4CD3, 0x4CEC, 0x4CEE, 0x4CE2, 0x4CE4, 0x4CFD, 0x4CF3, 0x4C0C, + 0x4C02, 0x4C04, 0x4C1D, 0x4C13, 0x4C2C, 0x4C2E, 0x4C22, 0x4C3F, 0x4C31, + 0x4C4C, 0x4C4E, 0x4C40, 0x4C42, 0x4C44, 0x4DC3, 0x4DDC, 0x4DD4, 0x4DED, + 0x4DE3, 0x4DFC, 0x4DF4, 0x4D0D, 0x4D03, 0x4D1C, 0x4D14, 0x4D2D, 0x4D3C, + 0x4D30, 0x4D34, 0x4D4D, 0x4D41, 0x4D43, 0x4ECC, 0x4EC4, 0x4EDD, 0x4ED3, + 0x4EEC, 0x4EF3, 0x4E0C, 0x4E1D, 0x4E13, 0x4E2C, 0x4E24, 0x4E33, 0x4E40, + 0x4E44, 0x4FC3, 0x4FDC, 0x4FD4, 0x4FED, 0x4FE3, 0x4FFC, 0x4FF4, 0x4F0D, + 0x4F1C, 0x4F14, 0x4F2D, 0x4F23, 0x4F3C, 0x4F34, 0x4F4D, 0x4F4F, 0x4F43, + 0x40CC, 0x40C2, 0x40C4, 0x40DD, 0x40D3, 0x40EC, 0x40E2, 0x40E4, 0x40FD, + 0x40F3, 0x400C, 0x4002, 0x4004, 0x401D, 0x4013, 0x402C, 0x4024, 0x403D, + 0x4033, 0x404C, 0x404E, 0x4042, 0x4044, 0x41CD, 0x41CF, 0x41C1, 0x41C3, + 0x41DC, 0x41D2, 0x41D4, 0x41ED, 0x41E3, 0x41FC, 0x41F4, 0x410D, 0x4103, + 0x411C, 0x4114, 0x412D, 0x4123, 0x4132, 0x4134, 0x414D, 0x4141, 0x4143, + 0x42CC, 0x42CE, 0x42C2, 0x42C4, 0x42DD, 0x42EC, 0x42FD, 0x42F3, 0x420C, + 0x4204, 0x421D, 0x422C, 0x4224, 0x423D, 0x4233, 0x424C, 0x424E, 0x4240, + 0x4242, 0x4244, 0x43C3, 0x43DC, 0x43D2, 0x43D4, 0x43E3, 0x43FC, 0x43F4, + 0x430D, 0x4303, 0x431C, 0x4314, 0x433C, 0x433E, 0x4330, 0x4334, 0x434D, + 0x434F, 0x4341, 0x4343, 0x44CC, 0x44CE, 0x44C0, 0x44C4, 0x44DD, 0x44EC, + 0x44E4, 0x44F3, 0x440C, 0x4404, 0x4413, 0x442C, 0x4422, 0x4424, 0x443D, + 0x444C, 0x444E, 0xCCCC, 0x4440, 0x4444, 0xCC0E, 0xCC40, 0xCDC3, 0xCDD2, + 0xCDED, 0xCDF2, 0xCD12, 0xCD32, 0xCD43, 0xCEDD, 0xCEE4, 0xCE4E, 0xCFDE, + 0xCF14, 0xCF2D, 0xCF23, 0xCF3E, 0xC0DD, 0xC0DF, 0xC0FD, 0xC01D, 0xC02E, + 0xC04C, 0xC1CD, 0xC1C1, 0xC1DE, 0xC103, 0xC141, 0xC2DD, 0xC2F3, 0xC222, + 0xC242, 0xC244, 0xC3CF, 0xC3C1, 0xC3DE, 0xC3D0, 0xC3FC, 0xC31E, 0xC323, + 0xC343, 0xC4DD, 0xC4D1, 0xC4E4, 0xC40C, 0xC422, 0xC44E, 0xDCCD, 0xDCC3, + 0xDCD4, 0xDC1E, 0xDC2D, 0xDC23, 0xDC32, 0xDC4D, 0xDDC0, 0xDDC2, 0xDDDF, + 0xDDEC, 0xDDE0, 0xDD02, 0xDD04, 0xDD2C, 0xDD2E, 0xDD20, 0xDD22, 0xDD4E, + 0xDEDE, 0xDED4, 0xDEFE, 0xDE34, 0xDFCE, 0xDFDF, 0xDFEE, 0xDFE4, 0xDF0E, + 0xDF13, 0xDF2C, 0xDF22, 0xD0C1, 0xD0DE, 0xD0E3, 0xD0F2, 0xD01C, 0xD01E, + 0xD02F, 0xD021, 0xD03E, 0xD043, 0xD1CC, 0xD1C0, 0xD104, 0xD2DC, 0xD2E3, + 0xD2FC, 0xD2F4, 0xD22D, 0xD23E, 0xD3C0, 0xD3C2, 0xD3C4, 0xD3EC, 0xD3E0, + 0xD3F1, 0xD322, 0xD4C1, 0xD4C3, 0xD4E3, 0xD443, 0xECFD, 0xEC0E, 0xEC13, + 0xEC24, 0xEDCF, 0xED0F, 0xED21, 0xED30, 0xEEDF, 0xEEEC, 0xEEF3, 0xEE0C, + 0xEFED, 0xEFE3, 0xEFF2, 0xEF14, 0xEF23, 0xEF3E, 0xE0CE, 0xE0C4, 0xE0E2, + 0xE013, 0xE02C, 0xE02E, 0xE03F, 0xE031, 0xE04E, 0xE1E3, 0xE1FC, 0xE130, + 0xE134, 0xE2CC, 0xE2DF, 0xE2D1, 0xE2EE, 0xE20C, 0xE202, 0xE21D, 0xE24C, + 0xE3DE, 0xE3EF, 0xE3FC, 0xE31C, 0xE330, 0xE34D, 0xE413, 0xFCCD, 0xFCF4, + 0xFC0D, 0xFC03, 0xFC34, 0xFC4D, 0xFDDD, 0xFD2E, 0xFD31, 0xFD44, 0xFE0D, + 0xFE3E, 0xFE32, 0xFF44, 0xF2DE, 0xF2D0, 0xF3D3, 0xF30C, 0xF30E, 0xF304, + 0xF322, 0xF34C, 0xF344, 0xF40D, 0xF403, 0xF42D, 0xF43C, 0xF44D, 0x0CCC, + 0x0CD3, 0x0CFD, 0x0C0C, 0x0C1D, 0x0C4C, 0x0C4E, 0x0DCD, 0x0DDE, 0x0DD0, + 0x0DEF, 0x0DF2, 0x0D4D, 0x0EDD, 0x0E33, 0x02DD, 0x02D3, 0x02FD, 0x0202, + 0x023F, 0x0244, 0x03C3, 0x030D, 0x0312, 0x0314, 0x0343, 0x04EC, 0x040C, + 0x043D, 0x0442, 0x1CFC, 0x1C14, 0x1DD3, 0x1D0E, 0x1D02, 0x1D1D, 0x1D31, + 0x1EDE, 0x1E23, 0x1032, 0x1230, 0x13FF, 0x130E, 0x131D, 0x133F, 0x14DC, + 0x14E3, 0x14FC, 0x140D, 0x2CCE, 0x2CEC, 0x2DE3, 0x2DFC, 0x2ECC, 0x2EC4, + 0x2ED1, 0x2E22, 0x2FDE, 0x2FF4, 0x2F2D, 0x2F3E, 0x20FD, 0x2040, 0x21C3, + 0x21DE, 0x21FC, 0x210D, 0x2134, 0x22E4, 0x220C, 0x2204, 0x2213, 0x222E, + 0x2224, 0x23DC, 0x23DE, 0x23D0, 0x23D4, 0x23EF, 0x23FE, 0x2303, 0x231E, + 0x2312, 0x2330, 0x24DD, 0x24E4, 0x24FD, 0x2433, 0x3C03, 0x3C1C, 0x3C12, + 0x3C14, 0x3C23, 0x3C4D, 0x3D13, 0x3D22, 0x3D3D, 0x3D33, 0x3D42, 0x3EDE, + 0x3EE3, 0x3E12, 0x3E3C, 0x3E34, 0x3E41, 0x3FCC, 0x3FCE, 0x3FC2, 0x3FDF, + 0x3FD3, 0x3FF3, 0x3F0E, 0x3F02, 0x3F20, 0x30D4, 0x30EF, 0x30FC, 0x30FE, + 0x30F2, 0x301E, 0x3014, 0x304D, 0x31DD, 0x31DF, 0x31D1, 0x31EC, 0x31E2, + 0x310E, 0x312C, 0x3144, 0x32EF, 0x32E1, 0x32F2, 0x321C, 0x323C, 0x3232, + 0x33CE, 0x33C4, 0x33EC, 0x33FD, 0x33F1, 0x3300, 0x331F, 0x332C, 0x3322, + 0x3324, 0x334C, 0x334E, 0x34ED, 0x34F2, 0x340D, 0x343C, 0x3430, 0x4C24, + 0x4C3D, 0x4C33, 0x4DFE, 0x4D12, 0x4D23, 0x4ECE, 0x4EE4, 0x4EFD, 0x4E02, + 0x4E04, 0x4E4C, 0x4E4E, 0x4E42, 0x4FCF, 0x4F03, 0x4F3E, 0x4F32, 0x4F41, + 0x40CE, 0x40C0, 0x400E, 0x4031, 0x413C, 0x413E, 0x4130, 0x42D3, 0x420E, + 0x4213, 0x4231, 0x43ED, 0x431E, 0x4312, 0x44C2, 0x44E2, 0x440E, 0x441D, + 0x442E, 0xCCEE, 0xCC22, 0xCDD0, 0xCDFE, 0xCD3E, 0xCE0E, 0xCF12, 0xC1FE, + 0xC13E, 0xC2E2, 0xC3E3, 0xC332, 0xC4D3, 0xC43F, 0xC440, 0xDCD0, 0xDCFE, + 0xDDCC, 0xDDDD, 0xDDF1, 0xDD11, 0xDECF, 0xDEE1, 0xDE21, 0xDF42, 0xD1CE, + 0xD1C2, 0xD1EC, 0xD12C, 0xD2EF, 0xD214, 0xD22F, 0xD221, 0xD342, 0xD41E, + 0xED01, 0xED3C, 0xED34, 0xED4D, 0xED43, 0xEEE2, 0xEE13, 0xEE31, 0xEFDC, + 0xEFD4, 0xEFF4, 0xE0EC, 0xE00C, 0xE024, 0xE04C, 0xE1C3, 0xE114, 0xE12D, + 0xE14D, 0xE14F, 0xE2CE, 0xE2C0, 0xE204, 0xE213, 0xE222, 0xE224, 0xE3D4, + 0xE30F, 0xE32F, 0xE4DD, 0xE4D3, 0xE4EE, 0xE40E, 0xE42C, 0xE44E, 0xFCCF, + 0xFCDC, 0xFCFE, 0xFD02, 0xFD42, 0xFEE3, 0xFE2D, 0xF0DE, 0xF0D0, 0xF04D, + 0xF131, 0xF2ED, 0xF23E, 0xF32C, 0x0CEE, 0x0D2D, 0x0D21, 0x0D32, 0x03EF, + 0x0431, 0x0440, 0x1CDE, 0x1CED, 0x1C03, 0x1DDD, 0x1DE2, 0x1D1F, 0x1D20, + 0x1EDC, 0x1E30, 0x1FDD, 0x1F3D, 0x1232, 0x132E, 0x1333, 0x2CD3, 0x2C3D, + 0x2C31, 0x2C42, 0x2DDC, 0x2D01, 0x2EDF, 0x2EE4, 0x2EF3, 0x2E24, 0x2FE3, + 0x2F12, 0x2F34, 0x20CE, 0x20D1, 0x20EC, 0x20F3, 0x200C, 0x2002, 0x2004, + 0x21CD, 0x21D0, 0x211C, 0x2114, 0x2123, 0x2233, 0x2244, 0x23FC, 0x230F, + 0x2301, 0x231C, 0x234F, 0x24D3, 0x242C, 0x2444, 0x3CFE, 0x3C3E, 0x3C41, + 0x3DFF, 0x3D2C, 0x3D4E, 0x3EC1, 0x3EDC, 0x3E4F, 0x3F2C, 0x31CE, 0x31C0, + 0x31E0, 0x314E, 0x32FE, 0x322F, 0x33C2, 0x332E, 0x3333, 0x34CF, 0x34DC, + 0x34FE, 0x4C0E, 0x4E2E, 0x4E3D, 0x4FDE, 0x40D1, 0x42C0, 0xCC11, 0x422E, + 0x443F, 0xCDDE, 0xCE40, 0xC3EF, 0xDC30, 0xDE0F, 0xD4EF, 0xECEE, 0xEECE, + 0xEFC1, 0xE1CF, 0xE1F4, 0xE3CF, 0xE343, 0xFC4F, 0xFDC0, 0xFD24, 0xF0E3, + 0xF1D1, 0xF3C2, 0xF342, 0xF4D2, 0x0C02, 0x0DF0, 0x0D01, 0x0D2F, 0x0E44, + 0x0F32, 0x00DD, 0x01ED, 0x02CC, 0x03C1, 0x1CFE, 0x1C3E, 0x1DC4, 0x1DD1, + 0x1D4E, 0x13C2, 0x14D2, 0x1441, 0x2DF0, 0x2DF4, 0x2D34, 0x2E2E, 0x2FF2, + 0x2020, 0x212F, 0x2332, 0x24EE, 0x3E01, 0x3FC0, 0x31EE, 0x311F, 0x4C11, + 0x4EE2, 0x41D0, 0x41FE, 0xCCF1, 0xDCEF, 0xDC4F, 0xDFFF, 0xEE20, 0xEF4F, + 0xE020, 0xE12F, 0xFEF4, 0xF1F3, 0xF2F2, 0xF4CF, 0xF441, 0x0DCF, 0x0ECE, + 0x0E0C, 0x02E2, 0x03DC, 0x12DC, 0x142F, 0x2E11, 0x2FEF, 0x22F1, 0x24DF, + 0x2431, 0x3EF0, 0x3001, 0x32F0, 0x4DEF, 0x4FE1, 0xC10F, 0xDC0F, 0xF0FE, + 0xDC2F, 0x0F03, 0x01D4, 0x0CE0, 0x0103, + /* Codebook 8 - 3281 entries */ + 0x0E24, 0x0E3D, 0x0FDC, 0x0FFC, 0x0F3E, 0x0134, 0x02CC, 0x024C, 0x03D0, + 0x030F, 0x04CE, 0x04F3, 0x1C41, 0x1D1D, 0x1D20, 0x1D33, 0x1E03, 0x10D0, + 0x10D2, 0x102D, 0x103E, 0x1030, 0x11D3, 0x12D0, 0x13F3, 0x134E, 0x144D, + 0x2DDC, 0x2DE3, 0x2DFC, 0x2D2D, 0x2D23, 0x2D32, 0x2EC0, 0x2E31, 0x21E3, + 0x223D, 0x23D0, 0x2323, 0x2330, 0x24FD, 0x3DC0, 0x3EC3, 0x3EE3, 0x3FDD, + 0x30C1, 0x30DE, 0x31CC, 0x3102, 0x324D, 0x331D, 0x333F, 0x334E, 0x34CF, + 0x4CE0, 0x4C11, 0x4C20, 0x4C3F, 0x4F23, 0x422C, 0xCCE2, 0x423F, 0x4233, + 0xCE1D, 0xCF30, 0xC1E3, 0xC3EF, 0xDCE3, 0xDC23, 0xDEF4, 0xDE10, 0xDF0E, + 0xDF02, 0xD2F2, 0xD212, 0xD4EF, 0xECCC, 0xED12, 0xED41, 0xEF34, 0xE0CE, + 0xE0E0, 0xE1CD, 0xE3F0, 0xE33C, 0xFFD3, 0xF1F3, 0xF2ED, 0xF23C, 0xF243, + 0xF30E, 0x0DEF, 0x0FDE, 0x00EC, 0x1D22, 0x1E3E, 0x1F31, 0x10CD, 0x100D, + 0x122D, 0x13EC, 0x13E4, 0x2CD3, 0x2DFE, 0x2F03, 0x20DF, 0x20F3, 0x2004, + 0x21D2, 0x214D, 0x23DC, 0x23FE, 0x23F0, 0x23F2, 0x2312, 0x2444, 0x32ED, + 0x331F, 0x332E, 0x3412, 0x3423, 0x4D1E, 0x4FED, 0xC222, 0x442E, 0x443F, + 0xEF14, 0xF11D, 0x0C3F, 0x020E, 0x0200, 0x2FC1, 0x20E0, 0x20E2, 0x232F, + 0x32FE, 0x4E22, 0x422E, 0x0F21, 0x1C21, 0x1EC1, 0x2EF1, 0x2F41, 0x2011, + 0x4002, 0x4121, 0xFF0E, 0x0E1F, 0x0042, 0x1E0F, 0x1F20, 0xFC0F, 0x1120, + 0x2C2E, 0xFF11, 0x41F2, 0xECCE, 0xECE2, 0xEDF2, 0xEE20, 0xEF41, 0xFD42, + 0x0C2E, 0x0E2E, 0x1F1D, 0x1113, 0x2E0E, 0x2E02, 0x2E20, 0x2422, 0xC1F2, + 0xE1F2, 0xF0EF, 0xF2F0, 0xF201, 0x0FE1, 0x2F0F, 0x2F1E, 0xFFE4, 0x0CF1, + 0x0C20, 0x0F2F, 0xF11F, 0x1EF2, 0x11E2, 0x21EF, 0x212F, 0x11FF, 0xCCCE, + 0x4422, 0xCCFF, 0xC022, 0xC10D, 0xC213, 0xDDE0, 0xDDE2, 0xDE21, 0xDFCE, + 0xDF13, 0xDF24, 0xD012, 0xD1EC, 0xD12E, 0xD2EF, 0xD210, 0xD221, 0xD243, + 0xED0F, 0xEECC, 0xEEDF, 0xEF03, 0xE1DE, 0xE12D, 0xE2DF, 0xE23D, 0xE3F2, + 0xE34F, 0xE41D, 0xFCC1, 0xFC41, 0xFFD1, 0xF0E3, 0xF03E, 0xF23E, 0xF33F, + 0x0D1C, 0x0ECC, 0x0E13, 0x0FE3, 0x0013, 0x003F, 0x1DE0, 0x1E32, 0x10C3, + 0x1144, 0x1223, 0x1423, 0x2C1D, 0x2D1E, 0x2D12, 0x2D3E, 0x2FCD, 0x201D, + 0x3CF2, 0x3E01, 0x3F20, 0x3122, 0x3243, 0x330E, 0x3430, 0x4F30, 0x401D, + 0x42DD, 0xCF32, 0xC202, 0xDDCC, 0xDF11, 0xEEC0, 0xE0E2, 0xE2EE, 0xE20E, + 0x0143, 0x30FC, 0x4E02, 0x43FE, 0xCF21, 0xC12F, 0xC2E0, 0xEE1F, 0xEFEF, + 0xEFF2, 0xE0F1, 0xE2FF, 0xE41F, 0xFEE1, 0x0C11, 0x012F, 0x11EE, 0x110C, + 0x1FF1, 0x0110, 0x2121, 0x24E0, 0xFE0F, 0x00CE, 0x02FF, 0x0211, 0x210F, + 0x112E, 0x2E1F, 0xF2CF, 0x2E11, 0xC0EE, 0xDC0F, 0x01F0, 0xDE23, 0xD1FF, + 0xEFF4, 0xE020, 0xE024, 0xE1CF, 0xE141, 0xE2E0, 0xF032, 0xF4DE, 0x02E0, + 0x1131, 0x131F, 0x1342, 0x2EEE, 0x2E22, 0x2E24, 0x2002, 0x202C, 0x2022, + 0x2042, 0x2242, 0x2332, 0x3221, 0xF0E1, 0x4EE0, 0x42EE, 0xF1E0, 0xF2F2, + 0x1E1C, 0x1201, 0xF012, 0x00FF, 0xF02F, 0x0F1E, 0x12FE, 0x1212, 0x4E00, + 0x0F01, 0x2EE2, 0x2F14, 0x011C, 0xCC02, 0xCC13, 0xCC22, 0xCC31, 0xCDCD, + 0xCDDC, 0xCDD2, 0xCE3D, 0xCE42, 0xCF03, 0xC0F3, 0xC2C2, 0xC2D3, 0xC2FD, + 0xC303, 0xDC03, 0xDC41, 0xDD22, 0xDD4E, 0xDECF, 0xDED4, 0xDE0D, 0xDE3C, + 0xDFD1, 0xDF04, 0xDF3F, 0xDF33, 0xDF40, 0xD0CF, 0xD0D2, 0xD0F4, 0xD032, + 0xD1DF, 0xD214, 0xD223, 0xD3C4, 0xD3D3, 0xD3E0, 0xD3F1, 0xD3F3, 0xD324, + 0xD403, 0xED3E, 0xEFD0, 0xE03D, 0xE332, 0xE4CE, 0xE4C0, 0xFC0D, 0xFDC2, + 0xFF3D, 0xF1DD, 0xF14C, 0xF3D1, 0xF3FD, 0xF3F3, 0x0CC0, 0x0CE0, 0x0C42, + 0x0DED, 0x0D3E, 0x0E3F, 0x003D, 0x014D, 0x02EC, 0x03FC, 0x030D, 0x0334, + 0x04E4, 0x04FD, 0x041D, 0x0440, 0x1CCD, 0x1CD4, 0x1CF4, 0x1C1C, 0x1DD3, + 0x1D00, 0x1003, 0x113D, 0x1142, 0x13D1, 0x13D3, 0x1300, 0x14FC, 0x1414, + 0x143C, 0x143E, 0x2C2C, 0x2DDE, 0x2DEF, 0x2E1D, 0x2E44, 0x2F43, 0x203F, + 0x22CC, 0x3DDF, 0x3DF3, 0x3D04, 0x3D3D, 0x3D3F, 0x3D33, 0x3EF4, 0x3E03, + 0x3FC4, 0x3FF3, 0x3F2C, 0x301E, 0x31D1, 0x32D2, 0x32F4, 0x33CC, 0x33DF, + 0x33EC, 0x33E2, 0x34E3, 0x4CEE, 0x4CE2, 0x4C2E, 0x4D23, 0x4D4F, 0x4ECE, + 0x4E2C, 0x4E24, 0x4FFC, 0x4F41, 0x42C2, 0x4224, 0x43DC, 0x43FC, 0x4330, + 0x4343, 0xCD12, 0xCED1, 0xCEF3, 0xCFD0, 0xCFED, 0xCFE3, 0xC1D0, 0xC2F3, + 0xC312, 0xDCCF, 0xDD13, 0xDE3E, 0xDFEC, 0xDFEE, 0xD0F0, 0xD1E4, 0xD201, + 0xD31F, 0xD4D0, 0xD40F, 0xED43, 0xEEF3, 0xEE31, 0xEFC3, 0xEFD4, 0xE0C0, + 0xE0C2, 0xE0F3, 0xE031, 0xE033, 0xE04E, 0xE130, 0xE2EC, 0xE3FE, 0xE312, + 0xE321, 0xE4C2, 0xFCF4, 0xFC32, 0xFDCC, 0xFD20, 0xFE43, 0xFFDD, 0xF0D2, + 0xF13F, 0xF2D0, 0xF3E2, 0xF423, 0x0D2D, 0x0E1D, 0x00D1, 0x02D1, 0x02F3, + 0x03FE, 0x1DEE, 0x1D02, 0x1D11, 0x1D2C, 0x1EC3, 0x1E0D, 0x120D, 0x13E0, + 0x131D, 0x1344, 0x1443, 0x2CCE, 0x2DCD, 0x2DF0, 0x2ED3, 0x2F3C, 0x21DC, + 0x23F4, 0x3EC1, 0x3E3C, 0x31CE, 0x31DF, 0x31EC, 0x31E0, 0x31E4, 0x312E, + 0x32CF, 0x32F2, 0x3223, 0x3232, 0x3234, 0x4EDF, 0xDDCE, 0x4E33, 0x4F0D, + 0xDE12, 0xD42F, 0xECDF, 0xECD1, 0xEC31, 0xEDDC, 0xEE24, 0xEE42, 0xEFCD, + 0xEF23, 0xE0EE, 0xE132, 0xF113, 0xF432, 0x0CE2, 0x0ECE, 0x0FCD, 0x0224, + 0x03C1, 0x1FF3, 0x1F13, 0x10D4, 0x12E3, 0x13F1, 0x2CD1, 0x2C4E, 0x2EE4, + 0x2FDE, 0x20CE, 0x20C2, 0x200E, 0x224E, 0x31EE, 0x3210, 0xC121, 0x341E, + 0x402E, 0xE4E2, 0x01E1, 0x1E2F, 0x142F, 0xCE1F, 0x2F12, 0x4222, 0xC01F, + 0x4112, 0x4F12, 0xEEE0, 0xEF1E, 0xE112, 0xFEDC, 0xFE2F, 0xF2F4, 0xF412, + 0x112C, 0x1C10, 0x121E, 0x4FE1, 0xFFF1, 0x1124, 0x2222, 0xCCCC, 0x41E3, + 0x443D, 0xCCC0, 0xCCC2, 0xCDFE, 0xC020, 0xDEDC, 0xD2E1, 0xD4D2, 0xECEE, + 0xEE13, 0xEE2E, 0xE00E, 0xE13C, 0xE3C1, 0xE42E, 0xFFF3, 0xFF3F, 0xF2D4, + 0xF3C0, 0x0E02, 0x002E, 0x0204, 0x04D1, 0x1CDE, 0x1DC0, 0x1DF1, 0x1ECD, + 0x1ED2, 0x12C3, 0x2C0E, 0x2EEC, 0x2134, 0x22E0, 0x22FD, 0x3F1F, 0x4D0F, + 0x430F, 0xD401, 0xEFC1, 0xE022, 0xE4E0, 0xF140, 0xF22F, 0xF24F, 0x1FC0, + 0x241F, 0x41EF, 0x1C2F, 0x4D10, 0x0011, 0xC1E1, 0x42E0, 0xDC10, 0xFF00, + 0xE4FF, 0xFC01, 0xFFCE, 0x0141, 0x0240, 0x1EFC, 0x1FCE, 0x211E, 0xF0C1, + 0xF100, 0xF111, 0x1FFF, 0x0F12, 0x24FF, 0xCCF1, 0xCEFD, 0xC01D, 0xC123, + 0x10FE, 0x1012, 0x11F1, 0xC132, 0xC2DF, 0xC3D2, 0xC33E, 0xDCDC, 0xDD11, + 0xDEC1, 0xDE2F, 0xDF2C, 0xDF42, 0xD0EF, 0xD1EE, 0xD122, 0xD131, 0xD24D, + 0xEC1D, 0xEDC1, 0xED23, 0xED3C, 0xEEFD, 0xE00C, 0xE1DC, 0xE1ED, 0xE204, + 0xE3D2, 0xE31E, 0xE32F, 0xE334, 0xFC23, 0xFC4F, 0xFDE0, 0xFDF3, 0xFD2E, + 0xFD24, 0xFEC3, 0xFED0, 0xFE03, 0xF00D, 0xF02D, 0xF24D, 0xF311, 0xF4C1, + 0xF42D, 0x0DCD, 0x0DE1, 0x0D10, 0x0D4D, 0x0FD0, 0x0F23, 0x00DF, 0x00FD, + 0x00F3, 0x01DE, 0x01E3, 0x022C, 0x031C, 0x031E, 0x0310, 0x1CED, 0x1DC2, + 0x1DEC, 0x1DE4, 0x1D04, 0x1D3F, 0x13C2, 0x130E, 0x132C, 0x1331, 0x1340, + 0x14C1, 0x14ED, 0x2C13, 0x2C3D, 0x2C33, 0x2D1C, 0x2D2F, 0x2EFD, 0x20DD, + 0x2040, 0x213C, 0x22DD, 0x2231, 0x2244, 0x23ED, 0x23EF, 0x2314, 0x234D, + 0x240E, 0x2413, 0x3C4D, 0x3DF1, 0x3ECD, 0x3E4F, 0x3E43, 0x30F2, 0x3021, + 0x31E2, 0x3140, 0x33E0, 0x4C22, 0x4D30, 0x4E1D, 0x4F32, 0x40DF, 0x40FD, + 0x4130, 0x42DF, 0x42FD, 0xCE22, 0xDC21, 0xDEF0, 0xEDDE, 0xEDE1, 0xE402, + 0xFEDE, 0xFE14, 0xF133, 0x0D4F, 0x0233, 0x0431, 0x1034, 0x14D2, 0x2EE0, + 0x20EC, 0x22EC, 0x234F, 0x3CFE, 0x3C1E, 0x31FF, 0x321E, 0xCF2F, 0x34F2, + 0x4312, 0xFE1C, 0xF2E1, 0x0E42, 0x0FCF, 0x02CE, 0x1E21, 0x1FE4, 0x2C11, + 0xEEEE, 0x214F, 0x2343, 0xEF10, 0xE4F1, 0x0FF4, 0x1E41, 0x4E1F, 0x1F1F, + 0xEF2F, 0x4444, 0x4323, 0xCC1D, 0xCC4C, 0xCC42, 0xCDD4, 0xE21F, 0xE211, + 0xFE41, 0xFF2E, 0xF21C, 0x1E12, 0xEF01, 0x1FE2, 0x12EF, 0x01FC, 0x1F42, + 0xF1F1, 0x14E1, 0x21FE, 0x2C20, 0xC0E2, 0xC22E, 0xC21F, 0xFFEE, 0x4011, + 0xCE00, 0x1FEC, 0xDE4F, 0xEE0E, 0xEFDC, 0xE0E4, 0xF1FF, 0xE200, 0xE224, + 0xE23F, 0xE4DF, 0xFD02, 0xFE3C, 0xF3FF, 0x0CDF, 0x0123, 0x02E2, 0x043F, + 0x1C30, 0x1DCE, 0x1EDE, 0x1E2D, 0x1FFD, 0x2ED1, 0x2E13, 0x2E42, 0x2FE3, + 0x2143, 0x2233, 0x2321, 0x3ECF, 0x3F11, 0x322F, 0x3322, 0x3344, 0xEC11, + 0x4013, 0x43E1, 0xEF1C, 0xE11C, 0xE4D1, 0xFF04, 0xFF42, 0x00E0, 0x1E14, + 0x11CE, 0xC211, 0x2EFF, 0x21CF, 0x0411, 0x2C1F, 0xFEC1, 0xF2C1, 0x1FE0, + 0x4FF2, 0xE1E1, 0xFC1E, 0xFEFE, 0xFFE2, 0x02C0, 0x1C12, 0x1E1E, 0x1234, + 0x14FE, 0x2114, 0x2334, 0x3CEF, 0x4200, 0x0F10, 0x3C10, 0x432F, 0x2FF0, + 0xC3F0, 0x0FEF, 0x0F41, 0xC0FF, 0xC0F1, 0x11E4, 0x4F21, 0xFF1F, 0xCD4D, + 0xCD43, 0xCECE, 0xCEC2, 0xCEEC, 0xCEE4, 0xCF4D, 0xC0C2, 0xC0D3, 0xC1C3, + 0xC143, 0xC2CE, 0xC2DD, 0xC2E4, 0xC24C, 0xC3CF, 0xC3DC, 0xC3D4, 0xC310, + 0xC334, 0xC4C2, 0xC4DD, 0xC41D, 0xC41F, 0xC431, 0xC44C, 0xDCC1, 0xDCC3, + 0xDC14, 0xDDD1, 0xDFC4, 0xD0CD, 0xD0DE, 0xD0FC, 0xD234, 0xD302, 0xD31D, + 0xD313, 0xD344, 0xD443, 0xEE4C, 0xE0C4, 0xE3DE, 0xE3F4, 0xE30D, 0xE4DD, + 0xE44C, 0xFCD4, 0xFC1C, 0xFC14, 0xFC34, 0xFD33, 0xF144, 0xF2CD, 0xF4FC, + 0x0CC4, 0x0CDD, 0x0CFD, 0x0C24, 0x0C4C, 0x00E4, 0x0044, 0x020C, 0x03F4, + 0x0303, 0x0323, 0x044E, 0x1CDC, 0x1D0E, 0x1D44, 0x134C, 0x14D4, 0x2CC4, + 0x2D34, 0x20CC, 0x2033, 0x24C2, 0x24C4, 0x240C, 0x3CC3, 0x3C1C, 0x3C34, + 0x3DC2, 0x3DDD, 0x3DD3, 0x3D0E, 0x3E32, 0x3E34, 0x3F33, 0x3F40, 0x30D0, + 0x303E, 0x31D3, 0x313D, 0x3203, 0x321C, 0x34DC, 0x34FC, 0x340D, 0x341C, + 0x4CCE, 0x4CC4, 0x4CF3, 0x4C2C, 0x4D3C, 0x4D4D, 0x4D43, 0x4E0C, 0x4E04, + 0x4E4E, 0x40CC, 0x40C0, 0x41CD, 0x414D, 0x4204, 0x43CF, 0x43C3, 0x4303, + 0x4334, 0x44CE, 0xCC2E, 0x44DD, 0x44D3, 0xCDCF, 0xCDD0, 0xCE44, 0xCFDC, + 0xC134, 0xC22C, 0xC23D, 0xC23F, 0xC24E, 0xC3DE, 0xC30D, 0xC323, 0xC332, + 0xC341, 0xC4C4, 0xC4D3, 0xDD33, 0xDD40, 0xDEE3, 0xDEFC, 0xDE03, 0xDFDF, + 0xDFFD, 0xDFF3, 0xDF1D, 0xDF44, 0xD0F2, 0xD02D, 0xD03C, 0xD03E, 0xD034, + 0xD04F, 0xD043, 0xD1CE, 0xD1DD, 0xD1D1, 0xD1FD, 0xD102, 0xD104, 0xD133, + 0xD144, 0xD2DC, 0xD2D0, 0xD20D, 0xD320, 0xD33F, 0xD4DE, 0xD4ED, 0xD4FC, + 0xD41C, 0xD423, 0xECE4, 0xEC42, 0xEEC4, 0xEED3, 0xE0DF, 0xE0D3, 0xE044, + 0xE240, 0xE330, 0xE4C4, 0xFC43, 0xFDFD, 0xF3CE, 0xF3DD, 0xF3D3, 0xF304, + 0xF33D, 0xF333, 0xF4ED, 0xF40D, 0xF403, 0x0CC2, 0x0C33, 0x0DC1, 0x0DDC, + 0x0DFC, 0x0D32, 0x01D2, 0x012D, 0x02D3, 0x02FD, 0x03CF, 0x03DE, 0x03E3, + 0x0314, 0x032D, 0x0332, 0x1DDF, 0x133F, 0x140D, 0x1434, 0x2CDD, 0x2CEC, + 0x2CE4, 0x2C24, 0x2DD0, 0x2D03, 0x2D3C, 0x2F30, 0x22C4, 0x23D2, 0x24D3, + 0x3CDE, 0x3CED, 0x3C14, 0x3C41, 0x3DD1, 0x3DEC, 0x3DE2, 0x3DE4, 0x3D0C, + 0x3D4C, 0x3E0D, 0x3E23, 0x3FE4, 0x3F13, 0x3F3F, 0x3F31, 0x30C3, 0x301C, + 0x3043, 0x3113, 0x313F, 0x3133, 0x322D, 0x33CE, 0x33D3, 0x333D, 0x343E, + 0x3434, 0x3441, 0x4C02, 0x4C13, 0x4C3D, 0x4C31, 0x4DD0, 0x4DD4, 0x4EEC, + 0x4FCD, 0x4033, 0x41C1, 0x41DC, 0x41FC, 0x4242, 0x43CD, 0x43D0, 0x44DF, + 0x44EC, 0x44FD, 0xCF23, 0xC1ED, 0xC130, 0xC14F, 0xC21D, 0xC32D, 0xC420, + 0xDCD0, 0xDC2D, 0xDEDE, 0xDE2D, 0xDF4E, 0xD0E1, 0xD021, 0xD11D, 0xD3FF, + 0xD342, 0xD4C3, 0xD412, 0xD44F, 0xEC24, 0xED10, 0xED21, 0xEED1, 0xEF0D, + 0xEF2D, 0xEF4D, 0xE042, 0xE1D2, 0xE2D3, 0xE3CF, 0xE3EF, 0xE343, 0xE4FD, + 0xE413, 0xFCED, 0xFC03, 0xFD00, 0xFD31, 0xFED2, 0xFE0D, 0xFE23, 0xF0D0, + 0xF203, 0xF230, 0xF3EC, 0xF3E4, 0xF300, 0xF320, 0xF344, 0x0DCF, 0x0DE3, + 0x0EFD, 0x0E31, 0x0F03, 0x0F30, 0x01D0, 0x03E1, 0x03F2, 0x0321, 0x1CC1, + 0x1C4F, 0x1DE2, 0x1DFF, 0x1DF3, 0x1D24, 0x1FCC, 0x1FD1, 0x1F3D, 0x1230, + 0x13DF, 0x130C, 0x1313, 0x1403, 0x144F, 0x2CC2, 0x2ECC, 0x2EDD, 0x2E3D, + 0x2FC3, 0x2FD0, 0x2FD4, 0x20D1, 0x20FD, 0x2031, 0x21DE, 0x21D4, 0x2204, + 0x223F, 0x23E3, 0x232D, 0x24DD, 0x24F3, 0x3CD2, 0x3C12, 0x3C21, 0x3D11, + 0x3EDC, 0x3EFE, 0x3E1E, 0x3E4D, 0x3FCE, 0x3FC2, 0x3F0E, 0x3F2E, 0x3F4E, + 0x30CF, 0x30E1, 0x30F4, 0x310E, 0x3100, 0x3124, 0x314E, 0x32D4, 0x324F, + 0x3241, 0x33FF, 0x3311, 0x3320, 0x4DF0, 0x4D2D, 0x4D32, 0x4FD0, 0x4FE3, + 0x403F, 0x41DE, 0xCCDD, 0xCD23, 0xC002, 0xC31E, 0xDCFE, 0xDCF2, 0xDC01, + 0xDF22, 0xD2CF, 0xD21E, 0xD4F2, 0xEDCF, 0xED14, 0xE1C3, 0xE2C0, 0xE20C, + 0xE244, 0xE4D3, 0xE422, 0xFCDE, 0xFED4, 0xFEED, 0xF023, 0xF03C, 0xF1C4, + 0xF3EE, 0x0C02, 0x02EE, 0x0244, 0x1C2D, 0x1E34, 0x10DC, 0x10E3, 0x12CD, + 0x13C0, 0x1311, 0x2DF2, 0x2D41, 0x2024, 0x22E4, 0x2202, 0x221D, 0x231E, + 0x3EF2, 0x31F1, 0x3214, 0x3333, 0x34EF, 0x4E3F, 0x40E0, 0x42D1, 0x43EF, + 0xEFCF, 0xE1FC, 0xFE1E, 0xF4F2, 0x0000, 0x1EDC, 0x1F04, 0x1412, 0x2F1C, + 0x21F4, 0x3C0F, 0x431E, 0xECFF, 0xFFC2, 0xF01C, 0x1FEE, 0x120F, 0x124F, + 0xC200, 0x1401, 0x20FF, 0x010F, 0xEC20, 0xF120, 0xC101, 0x114E, 0x221F, + 0x001F, 0x111F, 0x4FF0, 0xCDDE, 0x4431, 0x4213, 0x44F3, 0x4400, 0xCCC4, + 0xCCEC, 0xCEEE, 0xCF1E, 0xC0E0, 0xDCDE, 0xE2C2, 0xFF4E, 0xF20F, 0xF4FE, + 0x0F34, 0x1CFE, 0x1E4D, 0x12FC, 0x201F, 0x342F, 0xE420, 0xF0FE, 0x4E11, + 0x0E11, 0x1104, 0x4000, 0x21F0, 0x4E0E, 0xCCDF, 0xCD21, 0xEEF1, 0xFFEC, + 0x01FE, 0x2CE0, 0x20F1, 0x2110, 0xCFF0, 0xC02E, 0xC3FE, 0xC4F1, 0xDC12, + 0xDF20, 0xEC0E, 0xEDEF, 0xE21D, 0xE43F, 0xFDE2, 0xFD11, 0xFF31, 0xF0D4, + 0xF342, 0x0E0C, 0x0E22, 0x1C32, 0x1F3F, 0x12DC, 0x13CE, 0x132E, 0x2C31, + 0x2EDF, 0x2FED, 0x20E4, 0x21C3, 0x2123, 0x22CE, 0x23E1, 0x23FC, 0x241D, + 0x243F, 0x3EE1, 0x3E0F, 0x3FFF, 0x32E1, 0xCE02, 0x32F0, 0x4D3E, 0xC301, + 0xEDCD, 0xE2E2, 0xFECD, 0xFEFC, 0xF2EF, 0xF41E, 0x00EE, 0x022E, 0x041F, + 0x0420, 0x1CF2, 0x2E40, 0x2FFE, 0x2F2F, 0x2F4F, 0x21C1, 0x2200, 0x24E2, + 0x2420, 0xC10F, 0xF0CF, 0x3401, 0x4D2F, 0xF42F, 0x0FC1, 0x01CF, 0x4020, + 0x4442, 0xCCE0, 0xCC0E, 0xFF2C, 0xF0F2, 0xF01E, 0xF1C2, 0x0112, 0x1F0C, + 0x1F11, 0x10E1, 0x110E, 0x1100, 0x4F1E, 0x4F01, 0xC11E, 0xC220, 0xDCCD, + 0xEFFC, 0xF241, 0x0EE2, 0x0E2C, 0x024E, 0x121C, 0x2CEE, 0x2E2C, 0x2FCF, + 0xFCEF, 0x0FFE, 0x014F, 0x1F4E, 0x10F4, 0x1221, 0x1F00, 0x40F1, 0xFC21, + 0x24D1, 0xCDED, 0xCDE3, 0xCE33, 0xC0DF, 0x0F14, 0xC03D, 0xC3D0, 0xC330, + 0xC34F, 0xDDC2, 0xDD02, 0xDD24, 0xDE0F, 0xFC2F, 0x4101, 0xDFDD, 0xDFE4, + 0xDF00, 0xD00F, 0xD041, 0xD10C, 0xD10E, 0xD113, 0xD22F, 0xD3E4, 0xD32C, + 0xD322, 0xD43E, 0xECC0, 0xEDD4, 0xEDED, 0xEDFC, 0xED01, 0xE0FD, 0xE01D, + 0xE2DD, 0xE2F3, 0xE30F, 0xE43D, 0xE442, 0xFCE3, 0xFD0C, 0xFD0E, 0xFD1D, + 0xFE34, 0xFF33, 0xFF4C, 0xF3C4, 0xF322, 0xF44F, 0x0DDE, 0x0DFE, 0x0D1E, + 0x0D12, 0x0D14, 0x0EDF, 0x0E44, 0x002C, 0x010D, 0x021D, 0x03C3, 0x0413, + 0x1D0C, 0x1032, 0x1041, 0x1333, 0x142D, 0x2DCF, 0x2E3F, 0x2F0D, 0x2F32, + 0x21D0, 0x213E, 0x2130, 0x22DF, 0x230D, 0x2301, 0x233E, 0x242C, 0x3CD0, + 0x3C32, 0x3C4F, 0x3DCE, 0x3D1F, 0x3D20, 0x3D24, 0x3EDE, 0x3EFC, 0x3FDF, + 0x3FEC, 0x3FE0, 0x3F42, 0x30D2, 0x30FE, 0x3012, 0x302F, 0x304F, 0x3041, + 0x310C, 0x3131, 0x32DC, 0x32DE, 0x3201, 0x3230, 0x33EE, 0x3331, 0x342D, + 0x4CD1, 0x4C1F, 0x4DED, 0x4EDD, 0x4ED3, 0x4F03, 0x40EC, 0x40E2, 0x412D, + 0x4123, 0x42D3, 0x42F3, 0xCE13, 0xC1D2, 0xC231, 0xDEFE, 0xD2FE, 0xD24F, + 0xECF3, 0xEEE4, 0xEE2C, 0xEF3E, 0xE123, 0xE202, 0xE3E1, 0xFDFF, 0xFDF1, + 0xFE4D, 0xF0ED, 0xF1FD, 0xF22D, 0xF34E, 0x032F, 0x0341, 0x0402, 0x1EED, + 0x11DF, 0x111D, 0x13FF, 0x14DE, 0x1430, 0x1432, 0x2D14, 0x2E0C, 0x2E00, + 0x2E04, 0x2FDC, 0x2F4D, 0x212D, 0x24DF, 0x3FEE, 0x34FE, 0xCF12, 0x4DE1, + 0x4E31, 0xECE0, 0xEC2E, 0xE2CE, 0xFEF4, 0xF10C, 0x0022, 0x1C1E, 0x12E1, + 0x12F4, 0x1241, 0x2224, 0x242E, 0xEEFF, 0x4D01, 0x41FE, 0xF0FC, 0x011E, + 0x1410, 0x2211, 0xCF0F, 0x2400, 0x2411, 0xFFFF, 0xC2F1, 0xEC00, 0x01F2, + 0xF00F, 0x021F, 0x12F0, 0x0FF0, 0xCDEF, 0x4231, 0x44E2, 0xCCFD, 0xCC33, + 0xCEE0, 0xCEE2, 0xCE20, 0xEE02, 0xE2E4, 0xF041, 0xF212, 0x0F4D, 0x1EF4, + 0x1FC2, 0x141E, 0x2ECE, 0x22EE, 0x3CF0, 0xC1EF, 0x3C2F, 0x4321, 0xFE01, + 0xFF0C, 0x0F4F, 0x1F02, 0xC2FF, 0x2101, 0xE01F, 0x00F1, 0xF122, 0x0CFF, + 0x1F0E, 0x10EF, 0x10FC, 0x1102, 0x1122, 0x2F01, 0x412F, 0xCD1E, 0xCFDE, + 0xC00E, 0xC3F2, 0xF010, 0xDCD2, 0xDC1E, 0xDEEF, 0xDE01, 0xDE14, 0xDE34, + 0xD1E2, 0xD4FE, 0xECDD, 0xEC22, 0xEE0C, 0xEFED, 0xEF3C, 0xEF32, 0xE002, + 0xE1D4, 0xE1E3, 0xE143, 0xE231, 0xE4F3, 0xFDC0, 0xFD1F, 0xFF1D, 0xF003, + 0xF034, 0xF1DF, 0xF31F, 0x0EEC, 0x0E0E, 0x0202, 0x1CD2, 0x1D1F, 0x1EE3, + 0x1E43, 0x1FDD, 0x1023, 0x12D2, 0x1320, 0x22F3, 0x2402, 0x3CE1, 0x3EEF, + 0x3E41, 0x32EF, 0x320F, 0x4D12, 0x4ED1, 0x4EF3, 0xCDF2, 0x4FD2, 0x40F3, + 0xCD0F, 0xDCEF, 0xDC2F, 0xD410, 0xFECF, 0xFE21, 0xF04F, 0xF14E, 0x0020, + 0x01C3, 0x0242, 0x042E, 0x1E3C, 0x1F22, 0xEF12, 0x1043, 0x2C3F, 0xFF02, + 0xF0F4, 0xF1CE, 0xF102, 0x1001, 0xF124, 0x04FF, 0xE12F, 0x20EE, 0x43ED, + 0xCC4E, 0xCDFC, 0xCDF0, 0xCD0D, 0x1EF0, 0x1021, 0xE411, 0x2CF1, 0x4EF1, + 0x4F2F, 0xC112, 0xC3E1, 0xEE00, 0xEFE1, 0xE1EF, 0xE431, 0xF12E, 0x02C2, + 0x1EFE, 0x1232, 0x21F2, 0x2240, 0xCE11, 0x2431, 0x3421, 0xCFE1, 0xCFFE, + 0xF021, 0xF210, 0x2C00, 0x2FE1, 0xCF10, 0xF0F0, 0xCEF1, 0x400E, 0x3432, + 0xCD3E, 0xCD4F, 0xCED3, 0xCE0C, 0xCE4E, 0xCFFC, 0xCF1C, 0xCF4F, 0xCF01, + 0xFEF0, 0x0400, 0x4110, 0x2112, 0x411E, 0xC13C, 0xC141, 0xC2C0, 0xC204, + 0xC3FC, 0xC4EE, 0xC4FD, 0xC40E, 0xC43F, 0xDCD4, 0xDCF4, 0xDC4D, 0xDDEC, + 0xDD04, 0xDD2C, 0xDD2E, 0xDD42, 0xDED0, 0xDED2, 0xDE1C, 0xDFC2, 0xD0C1, + 0xD0D0, 0xD01C, 0xD014, 0xD030, 0xD1C4, 0xD100, 0xD140, 0xD142, 0xD2E3, + 0xD241, 0xD3FD, 0xD300, 0xD333, 0xD4C1, 0xD40D, 0xED0D, 0xED30, 0xEE44, + 0xE103, 0xE323, 0xE33E, 0xE400, 0xE42C, 0xE424, 0xE433, 0xFCCD, 0xFDD3, + 0xFD3D, 0xFD4C, 0xF043, 0xF30C, 0xF313, 0xF4F4, 0xF44D, 0xF441, 0x0CCC, + 0x0C13, 0x0D0D, 0x0D01, 0x0EC4, 0x0F43, 0x0033, 0x0330, 0x0442, 0x1CCF, + 0x1CC3, 0x1C0F, 0x1C43, 0x1DDD, 0x1F4C, 0x1F44, 0x133D, 0x14C3, 0x140F, + 0x2E33, 0x203D, 0x204C, 0x224C, 0x23DE, 0x233C, 0x244E, 0x3CC1, 0x3D02, + 0x3D13, 0x3D40, 0x3E14, 0x3FFD, 0x3F0C, 0x30CD, 0x30D4, 0x30ED, 0x31C0, + 0x31C4, 0x31FD, 0x311D, 0x32C3, 0x32E3, 0x323C, 0x323E, 0x33E4, 0x3313, + 0x332C, 0x3340, 0x344F, 0x4C4C, 0x4C4E, 0x4DC1, 0x4DDE, 0x4DE3, 0x4EC0, + 0x4E3D, 0x4FCF, 0x4FC3, 0x4F14, 0x40DD, 0x40D3, 0x403D, 0x42C0, 0x43D2, + 0x43E3, 0x431C, 0x4341, 0xCCF3, 0xCC11, 0xCD2D, 0xCD34, 0xCE24, 0xC033, + 0xC1DE, 0xC4D1, 0xC4E0, 0xC4E2, 0xC422, 0xDC3E, 0xDC34, 0xDE32, 0xDFC0, + 0xDFE0, 0xD001, 0xD010, 0xD02F, 0xD1E0, 0xD13F, 0xD2C3, 0xD22D, 0xD23E, + 0xD3CE, 0xD3C2, 0xD3E2, 0xD311, 0xD32E, 0xD34E, 0xD42D, 0xECD3, 0xEDFE, + 0xED4D, 0xEE04, 0xEE1D, 0xEE40, 0xEFD2, 0xEF30, 0xE013, 0xE1D0, 0xE10D, + 0xE2CC, 0xE213, 0xE3CD, 0xE3DC, 0xE301, 0xE310, 0xFCCF, 0xFDD1, 0xFD13, + 0xF030, 0xF20D, 0xF4C3, 0xF4E3, 0x0CD3, 0x0C4E, 0x0D03, 0x0E04, 0x0E4C, + 0x02C4, 0x023F, 0x0231, 0x03D2, 0x03EF, 0x1DD1, 0x1D13, 0x1D4C, 0x1FC4, + 0x13FD, 0x1324, 0x14F4, 0x2CF3, 0x2C40, 0x2DC3, 0x2DD4, 0x2DF4, 0x2D10, + 0x2F23, 0x22D3, 0x231C, 0x243D, 0x3C23, 0x3C30, 0x3D2C, 0x3D22, 0x3D42, + 0x3ED2, 0x3ED4, 0x3E2D, 0x3FC0, 0x3FD3, 0x300F, 0x33C2, 0x33FD, 0x330C, + 0x34C1, 0x4DD2, 0x4EFD, 0x41D0, 0x4103, 0x42EC, 0xCE31, 0x423D, 0x441D, + 0xCFD2, 0xC2D1, 0xC32F, 0xDC32, 0xD11F, 0xED1E, 0xE0EC, 0xE14D, 0xFDE4, + 0xFD22, 0xFE32, 0xF1D1, 0xF32E, 0x0CEE, 0x0D21, 0x0FD2, 0x0F32, 0x001D, + 0x02DF, 0x1CE3, 0x1E30, 0x10ED, 0x12ED, 0x1203, 0x123E, 0x2C02, 0x2EF3, + 0x2F2D, 0x202E, 0x220C, 0x2213, 0x230F, 0x3C3E, 0x3E21, 0x3FE2, 0x3F02, + 0x3324, 0x340F, 0x4EEE, 0x41ED, 0xCDE1, 0x413E, 0x441F, 0xCD01, 0xC20E, + 0xDCE1, 0xEECE, 0xEEC2, 0xE134, 0xE222, 0xE242, 0xFCF2, 0xFC12, 0xF2C3, + 0x0FD4, 0x1214, 0x14D0, 0x2F21, 0x21ED, 0xE10F, 0x4022, 0x420E, 0xFCE1, + 0xF1E4, 0x0F0F, 0x0121, 0x14F0, 0x1E4F, 0x1014, 0xC1F0, 0x1111, 0x410F, + 0x0C1F, 0xCFF2, 0xF014, 0xF4F0, 0x1F40, 0x10F2, 0x11E0, 0x12C1, 0x1210, + 0xF410, 0x41E1, 0xCEDF, 0xC30F, 0xE1F4, 0xFCFE, 0xFD40, 0x013C, 0x1CD0, + 0x1D4E, 0x11F3, 0x14F2, 0xEF0F, 0x2141, 0x220E, 0xE011, 0xE1F0, 0xFCF0, + 0xF1E2, 0xF40F, 0x0FF2, 0x1ECF, 0x2FF2, 0x2F10, 0xEE11, 0x2CFF, 0xEFF0, + 0xE101, 0xE11E, 0xFF22, 0x2FEF, 0x42FF, 0xEC1F, 0xFC10, 0xCCEE, 0xCEDD, + 0xDDDF, 0xDDF1, 0xDECD, 0xDE1E, 0xDFE2, 0xDF2E, 0xD0FE, 0xD01E, 0xD4E3, + 0xEC02, 0xEFDE, 0xE004, 0xE02C, 0xE03F, 0xE31C, 0xFC2D, 0xFE2D, 0xFE3E, + 0xFFC4, 0xF2D2, 0xF3F1, 0x0EDD, 0x0132, 0x0213, 0x040E, 0x0422, 0x1C23, + 0x1ED0, 0x1ED4, 0x11D1, 0x1133, 0x13E2, 0x204E, 0x21CD, 0x2132, 0x222C, + 0x23CF, 0x2310, 0x2433, 0x3CE3, 0x3C01, 0x3EF0, 0x3E1C, 0x3E2F, 0x3F24, + 0x30EF, 0x30F0, 0x3212, 0x4E13, 0x4FDE, 0x4F2D, 0x40EE, 0x41D2, 0x43DE, + 0xEF4F, 0xE14F, 0xE341, 0xE4EE, 0xF0CD, 0xF131, 0xF142, 0x0EEE, 0x0EE4, + 0x0E20, 0x0002, 0x02E4, 0x103C, 0x123C, 0x2C22, 0x20C0, 0x2000, 0x21FC, + 0x24EE, 0x4301, 0xCFEF, 0xEF21, 0xFF24, 0x0040, 0x1421, 0x4332, 0x43F2, + 0xCC20, 0x4413, 0xCCE4, 0xCC0C, 0xCC2C, 0xCC40, 0xECF1, 0xFEF2, 0x4F10, + 0xFFE0, 0xF1C0, 0xF2FE, 0x12CF, 0x24F1, 0x22FF, 0x4E2E, 0x1010, 0x4211, + 0xD421, 0xFC30, 0xFF13, 0xF234, 0xF430, 0x00E2, 0x1FDF, 0x10CF, 0xC000, + 0x124D, 0x1243, 0x2CE2, 0x2D4F, 0x2EC2, 0x2FFC, 0x2220, 0x3111, 0xF221, + 0x34F0, 0x4DEF, 0xF4EF, 0x1EEF, 0x1CEF, 0x0101, 0xC1FE, 0xFEEF, 0xFE4F, + 0xF21E, 0x0EC2, 0x0EF1, 0x1C01, 0x21E1, 0x421F, 0xCD03, 0xCD30, 0xCD41, + 0xCF34, 0xCF43, 0xC03F, 0xC031, 0xC103, 0xC13E, 0xC402, 0xDDFF, 0xDDF3, + 0xDE4D, 0xDF0C, 0xD1F3, 0xD124, 0xD13D, 0xD14E, 0xD2CD, 0xD2DE, 0xD2D2, + 0xD3C0, 0xD3EC, 0xD3EE, 0xD41E, 0xD432, 0xD441, 0xECFD, 0xEC4E, 0xEDD0, + 0xEDD2, 0xED34, 0xE13E, 0xE233, 0xE314, 0xE34D, 0xE44E, 0xFCC3, 0xFCDC, + 0xFDDD, 0xFDEC, 0xFD04, 0xFD3F, 0xFE30, 0xFF44, 0xF13D, 0xF302, 0xF331, + 0x0CF3, 0x0C1D, 0x0C31, 0x0DD0, 0x0DD2, 0x0DD4, 0x0DF0, 0x0D0F, 0x0F0D, + 0x00D3, 0x0031, 0x02DD, 0x03D4, 0x03ED, 0x03F0, 0x0301, 0x0312, 0x04DD, + 0x043D, 0x1C03, 0x1C14, 0x1D31, 0x1FD3, 0x10DE, 0x104D, 0x1302, 0x1304, + 0x14CD, 0x1441, 0x2CFD, 0x2DD2, 0x2D43, 0x2EC4, 0x2FD2, 0x210D, 0x23C3, + 0x24CE, 0x24EC, 0x2424, 0x3C2D, 0x3DFF, 0x3D2E, 0x3ED0, 0x3E3E, 0x30DC, + 0x31DD, 0x3104, 0x33DD, 0x33F1, 0x34DE, 0x34ED, 0x4EE4, 0x4FD4, 0x40D1, + 0x410D, 0x433E, 0xDEE1, 0xDEF2, 0xDFF1, 0xD111, 0xD12C, 0xD2C1, 0xD2FC, + 0xD2F0, 0xD21C, 0xEDF0, 0xEE3F, 0xEE4E, 0xEF43, 0xE2C4, 0xE2FD, 0xE3D4, + 0xFDEE, 0xFD2C, 0xFFDF, 0xF1D3, 0xF2DE, 0xF2E3, 0xF43E, 0x0DF2, 0x0D3C, + 0x0ED1, 0x0F2D, 0x01ED, 0x013E, 0x0343, 0x1D2E, 0x1E23, 0x12DE, 0x1322, + 0x14E3, 0x2C42, 0x2D21, 0x200C, 0x2013, 0x2103, 0x22E2, 0x3D4E, 0x3E10, + 0x3FD1, 0x3001, 0x311F, 0x3142, 0x32FC, 0x3342, 0x4DF2, 0x4F3E, 0x4031, + 0xCE2E, 0x4132, 0x44E0, 0xC2EE, 0xE000, 0xE02E, 0xE220, 0xF214, 0xF232, + 0xF4D0, 0xF4D2, 0x0C22, 0x0D41, 0x0EE0, 0x0E4E, 0x000E, 0x1D40, 0x1D42, + 0x10C1, 0x11FD, 0x2DC1, 0xF1EC, 0x2D4D, 0x2E4E, 0x04E0, 0x1CE1, 0x1F2E, + 0x1F24, 0xF401, 0x40FF, 0xC011, 0x2FF4, 0xCE0E, 0xF1EE, 0xF10E, 0xF4E1, + 0x11EC, 0x22F1, 0xCEFF, 0x04F1, 0x1CF0, 0x41F0, 0xDDEE, 0xDF1F, 0xD1F1, + 0xEEE2, 0xE1C1, 0xE114, 0xE22C, 0xE3C3, 0xFFFD, 0xF3C2, 0x0E00, 0x0FED, + 0x0220, 0x0222, 0x04DF, 0x04EE, 0x2E2E, 0x2020, 0x2442, 0x3FF1, 0xE0FF, + 0x3443, 0x42E2, 0x4F0F, 0xE121, 0xFE10, 0xE110, 0x4220, 0xCF2D, 0xCF3E, + 0xE2F1, 0xFF40, 0xF12C, 0x14EF, 0x100F, 0x4E20, 0xDC30, 0xDE41, 0xD1C2, + 0xD2F4, 0xD20F, 0xEC13, 0xEDC3, 0xEDF4, 0xEEDD, 0xE2D1, 0xE24E, 0xFDDF, + 0xFEE3, 0xFFCC, 0xF0DE, 0xF04D, 0xF223, 0xF3E0, 0x0C0E, 0x0D2F, 0x0EF3, + 0x03CD, 0x1C3E, 0x1DCC, 0x11DD, 0x113F, 0x13EE, 0x14CF, 0x2DE1, 0x2D0F, + 0x2D01, 0x2E4C, 0x2F3E, 0x2F34, 0x22D1, 0x3E12, 0x3F00, 0x3F04, 0x3F22, + 0x3010, 0x31C2, 0x312C, 0x3410, 0x4202, 0xC2E2, 0x43F0, 0x430D, 0xDDDD, + 0xDFFF, 0xED4F, 0xEEEC, 0xE22E, 0xFC3E, 0xFD4E, 0xF0C3, 0x01DC, 0x04E2, + 0x11C2, 0x12D4, 0x12F2, 0x22C0, 0x22C2, 0x222E, 0x4EE2, 0x4433, 0xFFC0, + 0xF2FC, 0x004E, 0x01C1, 0xC110, 0x1EE1, 0xEFFE, 0x1F2C, 0xE1FE, 0xFE12, + 0xF104, 0x101E, 0x11C0, 0x122F, 0xCD2F, 0xDCF0, 0xEE22, 0xF340, 0x211C, + 0x23C1, 0x2341, 0x34E1, 0xD4F0, 0x4DFE, 0x4D21, 0xFF20, 0x0EFF, 0x01EF, + 0x1E10, 0x102F, 0x1140, 0xF001, 0x4FEF, 0x4FFE, 0x4EFF, 0xD4E1, 0x02F1, + 0x10F0, 0x1E01, 0x101C, 0x401F, 0x104F, 0xCDC3, 0xCDF4, 0xCD1C, 0xCEC4, + 0xCE2C, 0xCE3F, 0xCE4C, 0xCE40, 0xCFCD, 0xCFD4, 0xCFF4, 0xCF14, 0xC0CC, + 0xC0C0, 0xC0C4, 0xC0EC, 0xC0E4, 0xC004, 0xC1DC, 0xC1D4, 0xC1FC, 0xC1F4, + 0xC114, 0xC2CC, 0xC2C4, 0xC20C, 0xC224, 0xC244, 0xC3C1, 0xC3C3, 0xC31C, + 0xC34D, 0xC4CC, 0xC4EC, 0xC4FF, 0xC40C, 0xC400, 0xC404, 0xC411, 0xC424, + 0xC433, 0xC440, 0xC442, 0xC444, 0xDCFC, 0xDC0D, 0xDD0C, 0xDD3D, 0xDD4C, + 0xDE43, 0xD0C3, 0xD0ED, 0xD00D, 0xD04D, 0xD1CC, 0xD3CC, 0xD30E, 0xD34C, + 0xD414, 0xD434, 0xECC4, 0xEC04, 0xEC3F, 0xEC4C, 0xE0DD, 0xE040, 0xE4CC, + 0xE4EC, 0xE404, 0xE440, 0xFCD0, 0xFDC4, 0xF1CC, 0xF3CC, 0xF4CD, 0xF4CF, + 0xF4D4, 0xF414, 0xF421, 0x0C0C, 0x0C00, 0x0C40, 0x0D34, 0x0E40, 0x0F3C, + 0x00CC, 0x00C0, 0x00C2, 0x00DD, 0x0004, 0x01CD, 0x0103, 0x03DC, 0x033C, + 0x034D, 0x034F, 0x04C0, 0x04C4, 0x040C, 0x0404, 0x0433, 0x044C, 0x11C4, + 0x114C, 0x13C4, 0x2CC0, 0x2C4C, 0x2DED, 0x2D0D, 0x20C4, 0x2044, 0x24CC, + 0x24C0, 0x244C, 0x2440, 0x3CCD, 0x3CCF, 0x3CDC, 0x3DCC, 0x3DC4, 0x3DE0, + 0x3DFD, 0x3D00, 0x3F3D, 0x3F4C, 0x3F44, 0x30E3, 0x3023, 0x303C, 0x33C0, + 0x33C4, 0x33D1, 0x33F3, 0x3300, 0x4CCC, 0x4CC0, 0x4CC2, 0x4CDD, 0x4CD3, + 0x4C0C, 0x4C00, 0x4C04, 0x4C24, 0x4C40, 0x4C44, 0x4DCD, 0x4DC3, 0x4D14, + 0x4D34, 0x4E4C, 0x4F3C, 0x4F4D, 0x4F43, 0x40C2, 0x40C4, 0x40E4, 0x400C, + 0x402C, 0x404C, 0x404E, 0x4040, 0x4044, 0x41CF, 0x41F4, 0x4114, 0x4141, + 0x4143, 0x42CC, 0x42C4, 0x42E4, 0x43C1, 0x43D4, 0x43F4, 0x4310, 0x4314, + 0x434D, 0x44CC, 0x44C4, 0x44FF, 0x440C, 0x4404, 0x4411, 0x442C, 0x444C, + 0xCCD3, 0x444E, 0x4440, 0xCC00, 0xCC04, 0xCC3D, 0xCD10, 0xCD3C, 0xCFCF, + 0xCFC3, 0xCF3C, 0xC0CE, 0xC0DD, 0xC00C, 0xC013, 0xC02C, 0xC04C, 0xC04E, + 0xC040, 0xC044, 0xC1CD, 0xC1CF, 0xC14D, 0xC233, 0xC240, 0xC3CD, 0xC3F4, + 0xC314, 0xC343, 0xC4CE, 0xC4C0, 0xC4DF, 0xC4E4, 0xC42C, 0xC44E, 0xDC3C, + 0xDC4F, 0xDC43, 0xDDC0, 0xDDC4, 0xDDFD, 0xDD1D, 0xDD31, 0xDD44, 0xDEC3, + 0xDE30, 0xDF3D, 0xD0DC, 0xD0D4, 0xD0E3, 0xD003, 0xD1D3, 0xD203, 0xD340, + 0xD4CD, 0xD4DC, 0xD4F4, 0xEC0C, 0xEC2C, 0xEC40, 0xEC44, 0xE0CC, 0xE04C, + 0xE303, 0xE4E4, 0xE40C, 0xFCFC, 0xF2DC, 0xF324, 0xF34C, 0xF4DC, 0xF434, + 0x0CEC, 0x0CE4, 0x0C04, 0x0C2C, 0x0C3D, 0x0C44, 0x0DC3, 0x0EC0, 0x0E33, + 0x0FC3, 0x0F1C, 0x00C4, 0x000C, 0x004C, 0x01F4, 0x0114, 0x023D, 0x04CC, + 0x04C2, 0x1CFC, 0x1C0D, 0x1C3C, 0x1C34, 0x1DC4, 0x2CCC, 0x2C04, 0x20D3, + 0x24E4, 0x3CFC, 0x3CF4, 0x3C0D, 0x3D44, 0x3F1D, 0x300D, 0x3003, 0x3030, + 0x304D, 0x31F3, 0x314C, 0x3144, 0x3302, 0x3304, 0x34D4, 0x34F4, 0x3403, + 0x344D, 0x4CDF, 0x4CEC, 0x4CFD, 0x4C42, 0x4DCF, 0x4DDC, 0x4DFC, 0x4D0D, + 0x4D03, 0x4D1C, 0x4D41, 0x4ECC, 0x4E42, 0x4E44, 0x4FC1, 0x4FF4, 0x4F1C, + 0x4F34, 0x4F4F, 0x40CE, 0x4004, 0x4024, 0x41C3, 0x4134, 0x414F, 0x420C, + 0x421D, 0x424C, 0x424E, 0x4244, 0x433C, 0x434F, 0x44EE, 0x44E4, 0x44F1, + 0xCC24, 0x4402, 0x4424, 0xCC3F, 0xCC44, 0xCDC1, 0xCD14, 0xCECC, 0xCE04, + 0xCFC1, 0xCF0D, 0xC0D1, 0xC0FD, 0xC024, 0xC042, 0xC11C, 0xC12D, 0xC2EC, + 0xC242, 0xC3ED, 0xC3E3, 0xC4F3, 0xC413, 0xC43D, 0xDC1C, 0xDDD3, 0xDDE4, + 0xDD00, 0xDD3F, 0xDFCC, 0xDFD3, 0xDF4C, 0xD023, 0xD14C, 0xD23C, 0xD3DD, + 0xD3D1, 0xD304, 0xD331, 0xD4CF, 0xD43C, 0xD430, 0xD44D, 0xECC2, 0xECEC, + 0xEDE3, 0xED32, 0xEE3D, 0xE24C, 0xE3D0, 0xE3E3, 0xE444, 0xFC3C, 0xFD44, + 0xF0DC, 0xF3DF, 0xF41C, 0xF43C, 0xF443, 0x0CCE, 0x0CD1, 0x0DF4, 0x0D30, + 0x0024, 0x01D4, 0x0130, 0x033E, 0x04D3, 0x04EC, 0x042C, 0x0424, 0x0444, + 0x1C4D, 0x1DFD, 0x1D3D, 0x1F33, 0x11CC, 0x13CC, 0x13DD, 0x14DC, 0x141C, + 0x2CDF, 0x2C0C, 0x2C44, 0x2D30, 0x23CD, 0x23D4, 0x2303, 0x2404, 0x3CD4, + 0x3C03, 0x3C3C, 0x3C43, 0x3DEE, 0x3D1D, 0x3D31, 0x3EED, 0x3E30, 0x3FCC, + 0x3014, 0x302D, 0x3032, 0x3034, 0x3120, 0x32CD, 0x32C1, 0x32D0, 0x320D, + 0x334C, 0x34CD, 0x34C3, 0x34D0, 0x34D2, 0x3414, 0x343C, 0x4CE4, 0x4CFF, + 0x4CF1, 0x4C0E, 0x4C1D, 0x4C33, 0x4DF4, 0x4EC2, 0x4EC4, 0x4E40, 0x4FDC, + 0x4042, 0x41D4, 0x411C, 0x413C, 0x42CE, 0x42F1, 0x4240, 0x432D, 0x44C0, + 0x44C2, 0x44D1, 0x440E, 0x4420, 0xCCD1, 0xCC1F, 0xCD32, 0xCEC0, 0xCF41, + 0xC1C1, 0xC321, 0xC33C, 0xC42E, 0xDCED, 0xDD0E, 0xDD1F, 0xDD20, 0xDEED, + 0xDF31, 0xD1C0, 0xD120, 0xD2D4, 0xD2ED, 0xD230, 0xD232, 0xD3DF, 0xD30C, + 0xD33D, 0xD4D4, 0xEC3D, 0xEC33, 0xED03, 0xED1C, 0xED2D, 0xED2F, 0xEE33, + 0xEFE3, 0xE0D1, 0xE3ED, 0xE3FC, 0xE32D, 0xE40E, 0xFCD2, 0xFC4D, 0xFDCE, + 0xF31D, 0xF32C, 0x0D23, 0x0D43, 0x0ED3, + /* Codebook 9 - 121 entries */ + 0x0000, 0xFF00, 0x05FF, 0x02FB, 0xFE02, 0xFDFE, 0x03FE, 0x05FE, 0x0301, + 0x0400, 0x02FD, 0x0103, 0xFCFE, 0x02FC, 0x0303, 0x04FD, 0x0004, 0x00FC, + 0x0302, 0x04FF, 0x0502, 0xFC05, 0xFC01, 0xFDFC, 0xFC04, 0x03FC, 0x0504, + 0xFFFC, 0xFCFF, 0xFBFC, 0xFCFB, 0xFE00, 0xFEFB, 0xFEFD, 0x0304, 0xFD04, + 0xFE03, 0x0401, 0x00FF, 0x0002, 0x0205, 0x04FB, 0x0405, 0x00FE, 0xFD05, + 0x0003, 0xFB04, 0xFFFB, 0xFF05, 0x01FB, 0x03FB, 0x00FD, 0xFC02, 0xFC03, + 0xFCFD, 0xFB00, 0x0503, 0xFBFE, 0x0105, 0xFDFB, 0x0305, 0x0501, 0xFB01, + 0x0005, 0x01FC, 0x0403, 0xFCFC, 0xFC00, 0xFF04, 0x05FC, 0x0104, 0xFD03, + 0x0500, 0xFBFF, 0x05FD, 0x0300, 0xFD00, 0x00FB, 0x0200, 0xFE05, 0xFBFD, + 0xFB03, 0xFF01, 0x03FF, 0xFB05, 0x0204, 0x03FD, 0xFEFE, 0xFBFB, 0xFDFD, + 0x04FE, 0x01FE, 0xFF03, 0xFFFD, 0x02FF, 0xFF02, 0xFEFF, 0x0201, 0x01FF, + 0xFFFF, 0x0101, 0xFD01, 0xFEFC, 0x04FC, 0x0404, 0xFE04, 0x0402, 0x01FD, + 0xFDFF, 0xFB02, 0x02FE, 0x05FB, 0x0505, 0xFFFE, 0xFE01, 0x0102, 0x0202, + 0x0203, 0xFD02, 0x0100, 0x0001, + /* Codebook 10 - 121 entries */ + 0x04FE, 0x0401, 0x04FB, 0x04FD, 0xFDFD, 0xFFFC, 0xFCFC, 0xFE00, 0x03FB, + 0xFC03, 0x04FF, 0xFD00, 0x03FC, 0x0404, 0x0405, 0xFCFB, 0xFD05, 0xFB03, + 0x05FD, 0x03FD, 0x0101, 0x05FF, 0x0504, 0xFBFC, 0xFD03, 0x0003, 0x05FE, + 0x0500, 0x0300, 0x0203, 0xFBFE, 0xFFFB, 0x00FD, 0xFB05, 0xFC00, 0x0501, + 0x0005, 0xFEFC, 0x0205, 0xFF05, 0xFDFE, 0x0505, 0x0004, 0x00FC, 0x0102, + 0xFB01, 0xFEFD, 0x01FF, 0xFFFE, 0xFEFB, 0x01FB, 0x01FE, 0x0502, 0x0204, + 0x0400, 0x05FB, 0x0201, 0xFF02, 0xFFFF, 0x02FF, 0xFEFF, 0xFF01, 0xFDFF, + 0x0301, 0x03FF, 0x0302, 0xFE01, 0x0105, 0x03FE, 0xFEFE, 0x01FD, 0x0304, + 0xFB00, 0xFF00, 0xFFFD, 0xFE03, 0x0103, 0xFBFF, 0x00FF, 0xFB02, 0xFB04, + 0x0402, 0xFBFB, 0xFCFE, 0x00FB, 0xFC05, 0x0100, 0x0000, 0xFD01, 0x02FB, + 0x0202, 0xFF03, 0x05FC, 0x0403, 0x0200, 0xFE05, 0xFDFC, 0xFE04, 0x0001, + 0x02FE, 0x02FD, 0x02FC, 0xFD04, 0xFD02, 0x0305, 0xFCFF, 0x04FC, 0xFC04, + 0xFC01, 0xFF04, 0xFE02, 0xFBFD, 0xFC02, 0xFCFD, 0x0002, 0x0303, 0x01FC, + 0x0104, 0x00FE, 0xFDFB, 0x0503, + /* Codebook 11 - 225 entries */ + 0x0000, 0xFA04, 0xFBFA, 0xFAFB, 0xFE04, 0x0103, 0xFDFC, 0xFB03, 0x0504, + 0x04FF, 0xFF07, 0x04FE, 0x0506, 0x01FA, 0xFDFE, 0xFAFF, 0x07FF, 0xFD05, + 0x05F9, 0x0302, 0xFE07, 0xF902, 0x0701, 0x0005, 0xF907, 0x07F9, 0xFC02, + 0x05FE, 0xF9FA, 0xFA01, 0x0203, 0xFF06, 0x0304, 0x0702, 0x03FE, 0xFEFD, + 0xFEFE, 0xFFF9, 0x0607, 0xF905, 0xF9FE, 0x0307, 0x0106, 0x06FC, 0xF900, + 0x0404, 0x0605, 0x01F9, 0x0500, 0x00FB, 0x0601, 0x04FD, 0x07FE, 0xFD02, + 0x02F9, 0x0403, 0x0202, 0x02FD, 0xFEF9, 0xFC03, 0xFE06, 0x03F9, 0xFB07, + 0xFAF9, 0xFFFA, 0xFCFD, 0x0007, 0xFE03, 0xFD04, 0x04FB, 0x05FC, 0x0206, + 0x0606, 0x0703, 0x06FE, 0xF9FF, 0xFAFA, 0x0207, 0xF9FD, 0x0107, 0x06FB, + 0x02FE, 0x0303, 0x0400, 0xFB04, 0xFBFB, 0xFE02, 0xFA02, 0x02FA, 0xFEFA, + 0xFB06, 0x0004, 0xFAFE, 0x0700, 0xFB00, 0xF906, 0x00FD, 0x03FC, 0xFA05, + 0x00FA, 0xFD07, 0xFC05, 0x06F9, 0xFDFD, 0x07FD, 0xFCFC, 0x0300, 0xF903, + 0xFDF9, 0x0602, 0x05FA, 0xF9F9, 0xFB05, 0x0600, 0x0006, 0xFD00, 0x00FC, + 0x07FC, 0x0306, 0xFDFA, 0xFD06, 0x0003, 0x0603, 0x0407, 0xFA07, 0x07FA, + 0xFFFE, 0xFAFD, 0x00F9, 0xFCF9, 0x0604, 0x06FD, 0x0201, 0x03FA, 0xF9FC, + 0x01FB, 0x0704, 0xFBFD, 0xFEFB, 0x0105, 0xFFFF, 0x02FF, 0xFE01, 0x01FE, + 0xFEFF, 0x0101, 0xFF01, 0x01FF, 0xFCFA, 0x0205, 0xFC00, 0xFD03, 0xFF05, + 0x04F9, 0x03FD, 0xFA03, 0x05FF, 0x0707, 0x05FB, 0xF904, 0xFBF9, 0x0102, + 0xFF02, 0xFAFC, 0xFFFB, 0xFB01, 0x0104, 0x06FA, 0x07FB, 0x06FF, 0xFA06, + 0xFE05, 0x0502, 0xFBFF, 0x0401, 0xFC04, 0xFDFB, 0xFA00, 0x0204, 0x0301, + 0x01FC, 0x0406, 0x0200, 0xFD01, 0x0305, 0x0507, 0x0705, 0xFC07, 0x0002, + 0xFF03, 0xFC06, 0x02FB, 0xFB02, 0x00FE, 0xFC01, 0xFCFB, 0x0501, 0xFF04, + 0x04FC, 0x0503, 0x03FF, 0xFFFD, 0x04FA, 0xFEFC, 0x0402, 0x03FB, 0x0505, + 0xFE00, 0x01FD, 0x02FC, 0x0706, 0xFBFE, 0xFDFF, 0xFFFC, 0xF9FB, 0xFBFC, + 0xFCFE, 0xF901, 0xFCFF, 0x05FD, 0x0405, 0x0100, 0xFF00, 0x0001, 0x00FF, + /* Codebook 12 - 441 entries */ + 0x0000, 0xFD03, 0x09FE, 0xFBFF, 0xF701, 0xF7F8, 0x0606, 0xFBFC, 0x0904, + 0x08FF, 0xFB05, 0x0207, 0x04F6, 0x0AFA, 0x0801, 0xF703, 0xFD05, 0xF904, + 0xFAF6, 0xFA02, 0x03F9, 0xF7FD, 0xFBFD, 0x04FF, 0x03F7, 0x0502, 0x0208, + 0x0AFB, 0x0007, 0xF709, 0xF604, 0xFB0A, 0x0204, 0x05F6, 0x0507, 0x0706, + 0xFA00, 0xFE08, 0xFDFB, 0xFD07, 0xFE07, 0x0401, 0x0006, 0x0107, 0x05FA, + 0x0506, 0x0009, 0x0702, 0x0703, 0x05FD, 0x0909, 0xF707, 0xF702, 0xFDF7, + 0xFD09, 0xFFFA, 0xFF08, 0x02F6, 0x0903, 0x04FE, 0x0402, 0xF8F6, 0xFCF9, + 0xFC0A, 0x02F9, 0xFF05, 0x0701, 0x070A, 0x03FD, 0x0905, 0x08F8, 0xFAF9, + 0xF8FE, 0xFC04, 0xFC09, 0xFFF8, 0x09FC, 0x09FD, 0xF7FE, 0x07FF, 0x09F8, + 0xFB09, 0xFCFB, 0xF801, 0xFC01, 0x02F8, 0x0104, 0x03F8, 0x0106, 0x090A, + 0xF90A, 0xF608, 0xFCFE, 0x0504, 0xF7F6, 0x00FA, 0x0407, 0x06FB, 0x09F9, + 0x0A04, 0xFF0A, 0x04FB, 0xF803, 0x00FC, 0x0405, 0x0604, 0xF6FA, 0xF60A, + 0x0AF7, 0xF809, 0xF901, 0xFF07, 0x04FA, 0xFBFB, 0x0707, 0x0A06, 0x0206, + 0x0509, 0xFC02, 0x0906, 0x0A07, 0x0607, 0x03FF, 0x01FC, 0x08FE, 0xF8FF, + 0xFCF7, 0x08F7, 0x0A0A, 0xFB00, 0xFB03, 0xFDFA, 0x01F6, 0x0802, 0x0505, + 0x0601, 0x0803, 0xFE04, 0x0103, 0xF7FC, 0xFAF7, 0xFA01, 0x00F7, 0x01FD, + 0xFFFC, 0x0309, 0x05FC, 0xFD01, 0xF8FD, 0x08FB, 0xF80A, 0xF70A, 0x0AF6, + 0x07FA, 0x0AF8, 0xFEFE, 0xFFFD, 0xF6F6, 0xF902, 0xF909, 0xFBF6, 0xF705, + 0xFEF6, 0xFD02, 0x0308, 0x0602, 0x0603, 0x0301, 0x02FC, 0x010A, 0xF6F9, + 0xF905, 0x0202, 0xFF04, 0xFAFE, 0xF906, 0x01F9, 0xFCFF, 0xFA08, 0xFC05, + 0xFDF8, 0x06FE, 0x07FB, 0x05F9, 0xFD08, 0x0408, 0xFAFF, 0xFE0A, 0x00FB, + 0x04F7, 0x0108, 0x0409, 0x0705, 0x0A09, 0x0800, 0xF6FF, 0x07F8, 0x0709, + 0xF601, 0xF7F9, 0xFE06, 0x0302, 0xFEFC, 0x01FA, 0x0AFF, 0x02FE, 0xFDFF, + 0x02F7, 0xF7F7, 0xFDF6, 0x01FF, 0xF8FC, 0xFEFA, 0x0A05, 0xF606, 0xFDFC, + 0xFFF6, 0x08FA, 0xFDFE, 0xFCFD, 0x0205, 0xFE02, 0x08FD, 0xF603, 0xF903, + 0x06F6, 0x0508, 0x02FA, 0x0900, 0xF704, 0xFB04, 0xFCF6, 0xFD06, 0xFD04, + 0x0403, 0xFEFD, 0x02FD, 0xFF03, 0x0A01, 0xF9FD, 0x09F6, 0x08F6, 0xF900, + 0xFA0A, 0x04F9, 0x06FA, 0xF807, 0xFBF7, 0x00F6, 0x0AFD, 0xFBF8, 0x0404, + 0x0101, 0xFFFF, 0xFF01, 0x03FE, 0x0008, 0x020A, 0x080A, 0xF6F7, 0x06F7, + 0x06F8, 0xF7FB, 0xF607, 0x0600, 0xFAFB, 0xFAFC, 0x03F6, 0x05F7, 0x0209, + 0x0304, 0x04FD, 0x0609, 0xFAFD, 0x0306, 0x0605, 0x0704, 0x08F9, 0x0804, + 0xF9F6, 0xFB07, 0x06F9, 0x07FD, 0xFA03, 0x0AF9, 0x0A08, 0x0005, 0x0AFE, + 0xF805, 0xFE09, 0xFE03, 0xFC00, 0xFC08, 0x0501, 0xF9F7, 0xFA09, 0xFCFA, + 0xFDF9, 0xFF06, 0x0AFC, 0xFAF8, 0xF6FD, 0xFA06, 0x0700, 0xFB02, 0xF9FB, + 0x000A, 0x02FF, 0x00FD, 0x0203, 0xF804, 0x06FD, 0xF602, 0xFEF7, 0xFE05, + 0xFEFF, 0x0201, 0xFF02, 0xFC03, 0xF9FF, 0xFBFA, 0x02FB, 0x0400, 0x05FE, + 0x08FC, 0x0902, 0x040A, 0xF609, 0xF907, 0x01FE, 0x0002, 0xFE00, 0xFFFE, + 0x00FE, 0x0608, 0xF908, 0x07FC, 0x09F7, 0xF800, 0xFEF9, 0x0A02, 0xF8F9, + 0xF808, 0xFA05, 0xFB01, 0x03FA, 0x0907, 0xFE01, 0xFFF7, 0x01F7, 0x0109, + 0x04F8, 0x0003, 0xFCF8, 0xFCFC, 0x0200, 0x00F8, 0x0806, 0xFBFE, 0xF7FA, + 0xFD0A, 0xFEFB, 0x05FF, 0xF8FB, 0x0406, 0x07F6, 0x060A, 0x0102, 0x0105, + 0xF600, 0xF8F7, 0xF9F8, 0xF806, 0x06FC, 0xFD00, 0xFF09, 0x0805, 0x0809, + 0xF6FE, 0xF9FC, 0xFAFA, 0x0307, 0x0500, 0x07F7, 0x0908, 0xFEF8, 0x0503, + 0x0A00, 0xF605, 0xF8F8, 0xF8FA, 0xFB08, 0x05F8, 0x01F8, 0xFB06, 0xFFF9, + 0x030A, 0x05FB, 0xF7FF, 0x050A, 0x09FB, 0x0807, 0x0A03, 0xF6F8, 0xFA07, + 0x0303, 0x0004, 0xF6FB, 0xF9FE, 0x09FF, 0xFC07, 0x09FA, 0xFFFB, 0x04FC, + 0x0901, 0xF708, 0x07F9, 0x00F9, 0x01FB, 0xFA04, 0xFBF9, 0x03FB, 0x03FC, + 0x0708, 0x0808, 0x0300, 0xFDFD, 0x06FF, 0xF9F9, 0xF6FC, 0xF700, 0x0305, + 0xF802, 0xF706, 0xF9FA, 0xFC06, 0x07FE, 0x0001, 0x0100, 0xFF00, 0x00FF, + /* Codebook 13 - 625 entries */ + 0x0000, 0x0201, 0xFDFF, 0x03FE, 0x0302, 0xF909, 0xF90A, 0xFA00, 0xFA0A, + 0x00F7, 0x08F6, 0x09F6, 0x09F8, 0x0901, 0x0AF7, 0x0A03, 0x0BF4, 0xF6F7, + 0xF6FB, 0xF6FF, 0xF600, 0xF706, 0xF801, 0xF806, 0xF808, 0xFDF6, 0xFF09, + 0xFF0A, 0x00F8, 0x0109, 0x02F7, 0x04F7, 0x05F7, 0x05F8, 0x06F7, 0x07F7, + 0x09FA, 0x09FD, 0x0AFB, 0xF6FC, 0x0AFC, 0x0AFD, 0xF60C, 0xF7FF, 0xF8F9, + 0xFA08, 0xFB07, 0xFCF9, 0xFD08, 0x00F9, 0x0208, 0x0409, 0x05FA, 0x05FB, + 0x06FB, 0x0603, 0x060A, 0x0704, 0x0707, 0x0AF5, 0x0A09, 0x0CF5, 0xF4F8, + 0xF5F9, 0x0202, 0xF508, 0xF509, 0xFC0C, 0x0408, 0x0BFC, 0x05FF, 0x0B0A, + 0xFEFF, 0xFEFE, 0xFFFD, 0xFDFD, 0x0CFC, 0xF404, 0xFE00, 0x00FE, 0xFF02, + 0xF506, 0xF507, 0xF7F4, 0xFA01, 0xFB04, 0xFC05, 0x000C, 0x0105, 0x0106, + 0x04FB, 0x05FD, 0x0505, 0x0506, 0x0605, 0x060C, 0x070C, 0xFDFC, 0x0BF8, + 0x0CFB, 0xFE06, 0x0502, 0xFE03, 0xFD03, 0x0C09, 0xF40C, 0xF6F9, 0xFEF5, + 0xFFF4, 0x020C, 0x04F5, 0x0B02, 0xF7F9, 0xF701, 0xF70C, 0xF8FA, 0xF9FD, + 0xF903, 0xFBF7, 0xFC07, 0xFDF8, 0x0108, 0x02F6, 0x0209, 0xFE01, 0x02FF, + 0x0002, 0x020A, 0x03F8, 0x050A, 0x06F8, 0x07FA, 0x07FC, 0x08F7, 0x08FF, + 0xF406, 0xF80C, 0xFA05, 0xFBFF, 0xFE07, 0x0207, 0x06F4, 0x06FE, 0x0601, + 0x0607, 0x07F4, 0x0706, 0xFF00, 0x01FE, 0xF5FB, 0x080C, 0x0CFA, 0xFAF5, + 0x03FC, 0x030B, 0x0B03, 0xF504, 0x0C00, 0x0A08, 0xF601, 0x0CF4, 0xF609, + 0xF60A, 0xFD01, 0xFBF5, 0xFB02, 0xFF03, 0xF5FA, 0xF9F4, 0xF902, 0xF90C, + 0xFBF9, 0xFBFA, 0xFEF8, 0xFFFB, 0xFF06, 0x0306, 0x0405, 0x050C, 0x03FF, + 0xF5FD, 0x0403, 0x0102, 0xFFFE, 0xF401, 0xFBFE, 0x01F4, 0x02FB, 0xF605, + 0xF80A, 0xF9F7, 0xF908, 0xFA07, 0xFBF6, 0xFB08, 0xFB0A, 0xFC09, 0xFD0A, + 0x010A, 0x040A, 0x08FA, 0x0800, 0x09FB, 0x09FC, 0xF4F4, 0x0900, 0x0A00, + 0xF4F5, 0xF6F8, 0xF7F8, 0xF7FA, 0xF9FF, 0xFB05, 0x00FA, 0x0007, 0x01F8, + 0x04F9, 0x0600, 0x07F8, 0x07FF, 0x08FD, 0x0808, 0x09F9, 0x0BF5, 0x0CF8, + 0xF40A, 0xF8FE, 0xFAFD, 0xFA0C, 0xFEFA, 0x0004, 0x05FC, 0x0507, 0x090B, + 0x0C06, 0x00FF, 0x0001, 0x0100, 0xF4FD, 0xF505, 0xF9F5, 0xFC03, 0x0103, + 0x00F5, 0x01FC, 0x050B, 0xF4FF, 0xFE05, 0xFF04, 0xFD02, 0x0B05, 0xF4F9, + 0xF5F6, 0xF50B, 0xF9FC, 0xF906, 0xFD04, 0xFE08, 0x0508, 0x090A, 0x0BF7, + 0x0B0B, 0x0B0C, 0x0CF9, 0x0C08, 0xFA0B, 0xFCF5, 0xFCFD, 0x000B, 0x0B04, + 0x0CFF, 0x02FD, 0x0C01, 0xF500, 0xFBFB, 0x060B, 0x0BFB, 0x0B09, 0xFDFE, + 0x0C03, 0xF6FA, 0x0A02, 0xF708, 0x0AF6, 0x0AF8, 0x0A01, 0xF602, 0xF7FB, + 0x01FD, 0x0203, 0xF702, 0xF8FF, 0xF800, 0xF802, 0xF805, 0xF905, 0xF907, + 0xFAF6, 0xFAF7, 0xFCF6, 0xFD09, 0x03F7, 0x06FD, 0x08FC, 0x0806, 0x09F4, + 0x0903, 0x0908, 0x0AF9, 0x0AFE, 0x0AFF, 0x0A04, 0x0A05, 0x0A06, 0xF4FB, + 0x0A0A, 0x0C0C, 0xF9FB, 0xFA04, 0xFC04, 0xFEF7, 0xFFF8, 0xFFF9, 0x0005, + 0x02F8, 0x03FA, 0x0308, 0xF402, 0x0407, 0x0701, 0xF503, 0xFBFD, 0xFE0C, + 0x080B, 0x0BFD, 0x0B06, 0x0CFD, 0x0CFE, 0xFBFC, 0xFC01, 0xFEFB, 0xFF0C, + 0x04FF, 0x040C, 0x070B, 0x0BFA, 0x0B08, 0xF40B, 0xF803, 0xFE0B, 0xF9F9, + 0xF9FA, 0xF901, 0xFB06, 0xFEF9, 0xFFFA, 0x00FB, 0x0307, 0x0400, 0x08F4, + 0x08FB, 0x08FE, 0xF4FE, 0x0807, 0x09F5, 0xFCFF, 0x0205, 0xFF0B, 0x0501, + 0x0C0A, 0xF50C, 0xF700, 0xFB09, 0x000A, 0xF603, 0xF7FC, 0xFB03, 0xFB0C, + 0xFCFC, 0xFDF4, 0xFDFB, 0x0206, 0x03F5, 0x030C, 0x0602, 0x0B00, 0x0B07, + 0xF709, 0xF70A, 0xFFF6, 0x0009, 0x03F6, 0x04F6, 0x06F6, 0x07F6, 0xF7F6, + 0x07F9, 0x08F8, 0xF7F7, 0xF7FE, 0xF8F6, 0xFE0A, 0x00F6, 0x0008, 0x01F7, + 0x04F8, 0x0509, 0x06FA, 0x07FB, 0x0700, 0x0709, 0x08F9, 0x09F7, 0x09FE, + 0x09FF, 0x0902, 0xF407, 0xF6F4, 0xF6F6, 0xF8F8, 0xF8FC, 0xF80B, 0xFC06, + 0x0006, 0x01FA, 0x0107, 0x03F9, 0x0604, 0x0608, 0x0703, 0xF403, 0xF5F5, + 0xF6F5, 0xFBF4, 0x0300, 0xFFFC, 0xFF05, 0x0303, 0x08F5, 0x0AF4, 0x0904, + 0x0907, 0x0AFA, 0xF604, 0xF5F7, 0xFCFB, 0x0404, 0x0406, 0x05FE, 0x0606, + 0x0BF9, 0x0C02, 0x0402, 0xF4F6, 0xF60B, 0xF8F7, 0xFAF8, 0xFAF9, 0xFAFB, + 0xFAFF, 0xFBF8, 0xFDF7, 0xFFF7, 0x02F9, 0x0309, 0x04FA, 0x0609, 0x07FD, + 0x0804, 0xF8F5, 0x0809, 0x0A0C, 0xF9FE, 0xFAFC, 0xFAFE, 0xFC0B, 0x02FA, + 0x0305, 0x0503, 0x0504, 0xFD00, 0x07FE, 0x0A0B, 0xFD0B, 0x01F5, 0xF400, + 0x0BF6, 0xF6FE, 0xF606, 0xF5FC, 0xF7F5, 0xFA02, 0xFB01, 0xFB0B, 0x00F4, + 0xF502, 0x04FC, 0x05F4, 0x0003, 0xF5FF, 0xF501, 0x010B, 0xF7FD, 0xF704, + 0xF705, 0xF804, 0xF809, 0xF9F6, 0xF900, 0xFA09, 0xFC08, 0xFC0A, 0xFE09, + 0x01F6, 0x030A, 0x05F6, 0x06F9, 0x06FC, 0x070A, 0x0801, 0x0905, 0x0906, + 0xF4F7, 0x0909, 0x0A07, 0xF408, 0xF50A, 0xF8FB, 0xFCF7, 0x01FF, 0xFD06, + 0xFEF6, 0xFF07, 0x05F9, 0xF4FA, 0x0802, 0x0CF6, 0xFCF4, 0x010C, 0x02F4, + 0x03F4, 0x0304, 0x0401, 0x05F5, 0x07F5, 0xFCFE, 0xFDF5, 0x02FC, 0x04FE, + 0x020B, 0x0C04, 0x0CF7, 0x0C07, 0xF6FD, 0xF607, 0x040B, 0xF4FC, 0xF5F8, + 0xF90B, 0xFAF4, 0xFDFA, 0x01FB, 0xFEFC, 0x04F4, 0x04FD, 0xFE04, 0x0BFE, + 0xFFF5, 0x03FD, 0x0BFF, 0xF409, 0xF8F4, 0xF8FD, 0xF9F8, 0xF904, 0xFA06, + 0xFB00, 0xFCF8, 0xFDF9, 0xFD07, 0xFF08, 0x01F9, 0x0500, 0x0708, 0x0803, + 0x0805, 0xF405, 0x080A, 0x090C, 0xFC02, 0xFC00, 0xFD05, 0x0104, 0x02F5, + 0xFF01, 0x0101, 0xFFFF, 0x0200, 0x02FE, 0x0204, 0x0B01, 0x03FB, 0x0C0B, + 0xF608, 0xF703, 0xF707, 0xF807, 0xF5F4, 0xF70B, 0xFAFA, 0xFA03, 0xFCFA, + 0xFD0C, 0x00FC, 0x06F5, 0x06FF, 0x0702, 0xF5FE, 0x0705, 0x0C05, 0xFEF4, + 0x00FD, 0xFE02, 0xFEFD, 0x0301, + /* Codebook 14 - 729 entries */ + 0x0000, 0x01FF, 0xF9F8, 0xF9F9, 0xF907, 0xFA04, 0xFBF8, 0xFB07, 0xFB08, + 0xFB0A, 0xFC07, 0xFC0A, 0xFDF5, 0xFDF6, 0xFEF5, 0xFFFB, 0xFF08, 0xFF0B, + 0x01F5, 0x02F6, 0x03F9, 0x04FA, 0x04FB, 0x04FC, 0x040C, 0x05FF, 0x06FD, + 0x0600, 0x0605, 0x060B, 0x0701, 0x08FA, 0x08FB, 0x08FD, 0x08FF, 0x0801, + 0x0802, 0x0807, 0x080B, 0x080C, 0x09FD, 0x0900, 0x0905, 0x0907, 0x0A03, + 0x0A06, 0x0A07, 0x0B02, 0x0B0B, 0x0C05, 0xF50D, 0x0C07, 0x0C0B, 0xF9FF, + 0xFA02, 0xFCFE, 0xFC00, 0xFE06, 0xFE07, 0x0005, 0x02FB, 0x0207, 0x03FA, + 0x04F7, 0x0406, 0x0407, 0x0408, 0x0506, 0x0808, 0x0AF3, 0x0C0D, 0xF3F3, + 0x0DF5, 0x0D06, 0xFBFD, 0xFC02, 0xFE04, 0xFFFC, 0x0104, 0x04FE, 0x0404, + 0x07F3, 0xFFFF, 0x00FE, 0xF3FC, 0x0D09, 0x0D0D, 0xFD0D, 0xF9F3, 0x0D0B, + 0x0DF4, 0xF4F4, 0x02FF, 0x04FD, 0x05FD, 0x0B0D, 0x0DF8, 0xFDFD, 0xFEF3, + 0x0101, 0xFE01, 0xFEFF, 0xFFFE, 0xFF02, 0x01FE, 0x0DFD, 0xF300, 0xF302, + 0xFCF3, 0xFEFD, 0xFFFD, 0xFF0D, 0x02F3, 0xFEFE, 0x02FD, 0x0203, 0x0002, + 0x0201, 0x040D, 0xF40D, 0xFAFB, 0xFAFC, 0xFAFD, 0xFAFF, 0xFA01, 0xFCF9, + 0xFCFF, 0xFF09, 0x0209, 0x0306, 0x0307, 0x0405, 0x05FA, 0x06FA, 0x0601, + 0x0706, 0x0708, 0x09FE, 0x0903, 0x0906, 0x090A, 0x0A0A, 0x0CF3, 0xF307, + 0xF5F3, 0xFF00, 0x0102, 0x00FD, 0xFBFE, 0xFCFC, 0x030D, 0x0304, 0x0DFA, + 0xF402, 0xF5F6, 0xF303, 0xFB0D, 0xFFF3, 0x0103, 0x050D, 0xF3F7, 0xF7F3, + 0xFB03, 0x0205, 0x04FF, 0x0403, 0x0504, 0x0505, 0x06FE, 0x0D0C, 0x060D, + 0xFBF3, 0x03FE, 0x0303, 0x04F3, 0x0DFB, 0x0D02, 0x0D04, 0x0D05, 0xF6FB, + 0xF606, 0xF7F6, 0xF703, 0xF705, 0xF8F5, 0xF8FE, 0xF8FF, 0xF9FC, 0xF901, + 0xF904, 0xF906, 0xF908, 0xFAF9, 0xFA00, 0xFA09, 0xFA0A, 0xFBF5, 0xFBF7, + 0xFB06, 0xFB09, 0xFCF6, 0xFCF7, 0xFC08, 0xFEF7, 0xFEF8, 0xFFF6, 0xFFF8, + 0xFFF9, 0x00F6, 0x00F7, 0x00FA, 0x0007, 0x0009, 0x0106, 0x0109, 0x010C, + 0x02F4, 0x02F5, 0x02F7, 0x0100, 0x00FF, 0x0001, 0x020A, 0x020C, 0x040A, + 0x06F5, 0x06F7, 0x06F8, 0x07F5, 0x07F7, 0x07F9, 0x07FA, 0x07FB, 0x07FF, + 0x0700, 0x08F6, 0x0805, 0x0809, 0x080A, 0x0904, 0x0908, 0x090C, 0x0AF4, + 0x0AFF, 0x0A08, 0x0BF6, 0x0B01, 0x0B05, 0x0B07, 0x0B0C, 0xF3F6, 0x0CF9, + 0x0C01, 0xF30A, 0xF502, 0xF6F7, 0xF8FA, 0xF8FB, 0xF9FB, 0xF905, 0xFA03, + 0xFA05, 0xFA08, 0xFB01, 0xFB04, 0xFCFA, 0xFCFB, 0xFC05, 0xFC06, 0xFDF7, + 0xFD09, 0xFF07, 0x0008, 0x0107, 0x0309, 0x04F9, 0x0401, 0x05FC, 0x0501, + 0x0508, 0x0509, 0x06FF, 0x0604, 0x070A, 0x08FC, 0x0804, 0x0902, 0x0A01, + 0x0B03, 0x0B09, 0x0B0A, 0x0C0C, 0x0DF3, 0xF3F9, 0xF30B, 0xF70D, 0xF80D, + 0xF90D, 0xFAFE, 0xFBFA, 0xFC01, 0xFDFB, 0xFD07, 0x02F9, 0x0208, 0x03FC, + 0x0305, 0x0502, 0x0602, 0x00F3, 0x0DF6, 0x0D0A, 0xFF03, 0x0D00, 0xF3F8, + 0x0300, 0xFE03, 0x0003, 0x0DFC, 0xF3F5, 0xF308, 0xFA0D, 0xFCFD, 0xFC03, + 0xFDF9, 0xFD06, 0x02FA, 0x0400, 0x05FB, 0x0607, 0x08F3, 0x090D, 0x0A0D, + 0xF3FA, 0xFC0D, 0xFDF3, 0xFE0D, 0xF3FF, 0x02FC, 0xF30C, 0xF5FF, 0xF603, + 0xF607, 0xF301, 0x0DFF, 0x0D01, 0xF60B, 0xF7F5, 0xF7F9, 0xF7FB, 0xF7FC, + 0xF7FD, 0xF8F9, 0xF803, 0xF9FA, 0xF9FD, 0xF903, 0xFA06, 0xFA07, 0xFBF9, + 0xFBFB, 0xFDF8, 0xFD0A, 0xFE08, 0xFE09, 0xFFFA, 0xFF05, 0x00FB, 0x01F7, + 0x01FB, 0x02F8, 0x0308, 0x05F7, 0x05F8, 0x05F9, 0x0503, 0x0507, 0x06FB, + 0x06FC, 0x0609, 0x060A, 0x07FE, 0x0703, 0x0705, 0x070B, 0x0803, 0x0806, + 0x09F9, 0x0AF9, 0x0A0B, 0xF3F4, 0x0C09, 0x0C0A, 0xF309, 0xF60D, 0xF8F3, + 0xF902, 0xFAFA, 0xFBFC, 0xFB02, 0xFC04, 0xFEFA, 0xFE05, 0xFF06, 0x0004, + 0x0206, 0x0402, 0x05FE, 0x0603, 0x0606, 0x0608, 0x0702, 0x0707, 0x09F3, + 0x0909, 0x0BF3, 0x0DF7, 0xF3FD, 0xF304, 0xFE00, 0xFD00, 0xF306, 0xFAF3, + 0xFD02, 0x0301, 0x0200, 0x03FF, 0xFD04, 0xFDFC, 0xFEFC, 0x0105, 0x03FD, + 0x05F3, 0x0202, 0x03F3, 0x06F3, 0xF6F3, 0xF7FE, 0xFE02, 0x0DFE, 0xF802, + 0xF9FE, 0xFAF7, 0xFBFF, 0x02FE, 0xFDFA, 0xFD05, 0xFD08, 0xFEF9, 0xFEFB, + 0xFF04, 0x00FC, 0x01FA, 0x01FC, 0x03FB, 0x0409, 0x080D, 0xF3FB, 0xF305, + 0xF4F3, 0xFD03, 0x0204, 0x070D, 0x010D, 0x0D08, 0x000D, 0xFDFE, 0xFDFF, + 0xFD01, 0x0DF9, 0x0D07, 0x020D, 0x0D03, 0xFF01, 0xF3FE, 0x01F3, 0x01FD, + 0x0302, 0xF4F8, 0xF4F9, 0xF4FA, 0xF4FB, 0xF4FC, 0xF4FD, 0xF400, 0xF401, + 0xF403, 0xF404, 0xF406, 0xF407, 0xF408, 0xF409, 0xF40A, 0xF40B, 0xF40C, + 0xF5F8, 0xF5FA, 0xF5FC, 0xF5FE, 0xF500, 0xF501, 0xF503, 0xF504, 0xF505, + 0xF506, 0xF507, 0xF508, 0xF509, 0xF50A, 0xF50B, 0xF50C, 0xF6F4, 0xF6FF, + 0xF600, 0xF604, 0xF608, 0xF609, 0xF60A, 0xF60C, 0xF7F4, 0xF7F8, 0xF7FA, + 0xF700, 0xF708, 0xF709, 0xF70A, 0xF70B, 0xF70C, 0xF8F4, 0xF8F7, 0xF800, + 0xF809, 0xF80A, 0xF80B, 0xF80C, 0xF9F4, 0xF90A, 0xF90B, 0xF90C, 0xFAF6, + 0xFA0C, 0xFBF6, 0xFB05, 0xFB0B, 0xFB0C, 0xFCF4, 0xFCF5, 0xFCF8, 0xFC09, + 0xFC0C, 0xFD0B, 0xFEF4, 0xFE0C, 0xFFF4, 0xFFF7, 0xFF0A, 0xFF0C, 0x00F4, + 0x00F5, 0x00F8, 0x0006, 0x000A, 0x000B, 0x000C, 0x01F4, 0x01F8, 0x01F9, + 0x010A, 0x020B, 0x03F4, 0x03F5, 0x03F6, 0x03F7, 0x030C, 0x04F4, 0x04F6, + 0x040B, 0x05F4, 0x05F6, 0x0500, 0x050A, 0x050B, 0x050C, 0x06F4, 0x06F6, + 0x07F4, 0x07F8, 0x07FD, 0x0709, 0x070C, 0x08F4, 0x08F5, 0x08F8, 0x08F9, + 0x08FE, 0x09F4, 0x09F5, 0x09F6, 0x09F7, 0x09F8, 0x09FA, 0x09FF, 0x0901, + 0x090B, 0x0AF5, 0x0AF8, 0x0AFC, 0x0AFE, 0x0A02, 0x0A04, 0x0A09, 0x0A0C, + 0x0BF4, 0x0BF5, 0x0BF7, 0x0BF8, 0x0BF9, 0x0BFA, 0x0BFB, 0x0BFC, 0x0BFD, + 0x0B00, 0x0B04, 0x0B06, 0x0CF4, 0x0CF7, 0x0CFB, 0x0CFC, 0x0CFD, 0x0CFF, + 0x0C00, 0x0C03, 0x0C04, 0x0C06, 0xF4F5, 0xF4F6, 0xF4FE, 0xF4FF, 0xF5F9, + 0xF5FB, 0xF5FD, 0xF6F5, 0xF6F6, 0xF6FC, 0xF6FE, 0xF601, 0xF605, 0xF7FF, + 0xF702, 0xF704, 0xF707, 0xF8F8, 0xF801, 0xF804, 0xF805, 0xF807, 0xF808, + 0xF9F5, 0xF9F7, 0xF900, 0xF909, 0xFAF4, 0xFAF5, 0xFAF8, 0xFA0B, 0xFBF4, + 0xFB00, 0xFC0B, 0xFDF4, 0xFD0C, 0xFEF6, 0xFE0A, 0xFE0B, 0xFFF5, 0x00F9, + 0x01F6, 0x0108, 0x010B, 0x03F8, 0x030A, 0x030B, 0x04F5, 0x04F8, 0x05F5, + 0x06F9, 0x060C, 0x07F6, 0x07FC, 0x0704, 0x08F7, 0x0800, 0x09FB, 0x09FC, + 0x0AF6, 0x0AF7, 0x0AFA, 0x0AFB, 0x0AFD, 0x0A00, 0x0A05, 0x0BFE, 0x0BFF, + 0x0B08, 0x0CF5, 0x0CF6, 0x0CF8, 0x0CFA, 0x0CFE, 0xF30D, 0x0C02, 0x0C08, + 0xF4F7, 0xF405, 0xF5F4, 0xF5F5, 0xF5F7, 0xF6F8, 0xF6F9, 0xF6FA, 0xF6FD, + 0xF602, 0xF7F7, 0xF701, 0xF706, 0xF8F6, 0xF8FC, 0xF8FD, 0xF806, 0xF9F6, + /* Codebook 15 - 1089 entries */ + 0x0000, 0x00FF, 0xFEFF, 0x0201, 0xFAFF, 0xFBFB, 0xFF06, 0x06FE, 0x100E, + 0xF2F6, 0xF2FF, 0xF205, 0xF3F3, 0xF6F2, 0xF8F5, 0xF90B, 0xFAF8, 0xFAF9, + 0xFA06, 0xFCF2, 0x0008, 0x0209, 0x030E, 0x04F2, 0x040E, 0x040F, 0x05F7, + 0x06F1, 0x07FD, 0x0807, 0x09F1, 0x09FC, 0x09FE, 0x0AF1, 0x0A03, 0x0A0B, + 0x0B08, 0x0B0C, 0x0CF1, 0x0C0E, 0x0E0B, 0xFF07, 0x03F8, 0xF002, 0xF00A, + 0xF00B, 0x0DF0, 0xFE01, 0xFFF0, 0x06FD, 0x0F07, 0xF20E, 0xF3F7, 0xF009, + 0xFAFB, 0xFC05, 0xF510, 0x0205, 0x07F0, 0x1008, 0xF0F4, 0xF007, 0x100A, + 0xF3FC, 0xF305, 0xF308, 0xF30F, 0xF4FE, 0xF40F, 0xF505, 0xF508, 0xF50A, + 0xF60B, 0xF60C, 0xF60D, 0xF7F4, 0xF7FB, 0xF701, 0xF708, 0xF70F, 0xF800, + 0xF9F3, 0xF90C, 0xFBF5, 0xFBF6, 0xFC0D, 0xFDF5, 0x000A, 0x020D, 0x08F1, + 0x0901, 0x0AF2, 0x0A02, 0x0BF4, 0x0BFC, 0x0BFE, 0x0B06, 0x0CF4, 0x0C02, + 0x0C07, 0x0DF5, 0x0DF6, 0x0DF8, 0xF1F1, 0x0D03, 0x0D04, 0xF1F3, 0xF1F7, + 0xF103, 0xF107, 0xF2FA, 0xF4F4, 0xF5F2, 0xF5FA, 0xF6F5, 0xF6FC, 0xF70E, + 0xF8F1, 0xF8F6, 0xF900, 0xF90E, 0xFB0A, 0xFCF7, 0xFC08, 0xFC0B, 0xFDF2, + 0xFEF2, 0xFF0A, 0x020E, 0x06F7, 0x07FA, 0x0709, 0x08FC, 0x0906, 0x0A06, + 0x0EF8, 0x0001, 0x0100, 0xFF00, 0xF010, 0x10F0, 0x0E01, 0x0E09, 0x0E0A, + 0x0F08, 0xF204, 0xFDF9, 0xFEFA, 0x0407, 0x0601, 0x0704, 0xF0FD, 0xFCFC, + 0x0BF0, 0x1004, 0xF0F1, 0xF00C, 0x1005, 0x1009, 0x03FD, 0x100D, 0xF903, + 0xFBFA, 0xFD03, 0xF310, 0x0107, 0x0506, 0xFDFB, 0x0D0E, 0xF104, 0x0EF1, + 0xF307, 0x000D, 0x0C00, 0x0D01, 0xF10F, 0xF4FF, 0xFE05, 0x00F0, 0x01FB, + 0x100C, 0x100F, 0xF2FB, 0xF2FD, 0xF200, 0xF4F9, 0xF606, 0xF9F6, 0xF9FF, + 0xFAF7, 0xFA09, 0xFC0A, 0xFD09, 0x0109, 0x030A, 0x040A, 0x05F6, 0x05F9, + 0x0509, 0x070A, 0x070B, 0x0809, 0x090B, 0x0AFA, 0x0B0F, 0x0EF5, 0x0EF9, + 0x0E08, 0x0FFC, 0x0FFF, 0x0010, 0xF905, 0x0602, 0x0104, 0x0105, 0x09F0, + 0xFFFD, 0x01FD, 0x0103, 0x01F0, 0x1006, 0x00FB, 0x02F2, 0x0206, 0x0408, + 0xF0FE, 0x0500, 0x06FA, 0xF004, 0xF008, 0xF610, 0x04FC, 0x10F6, 0x10F7, + 0xFF03, 0xFFFC, 0x10FD, 0x10FE, 0xFD01, 0xFF04, 0x10F1, 0x1001, 0xF401, + 0x000C, 0x01F3, 0x0C01, 0xF30D, 0xF4F6, 0xFEF3, 0x02F5, 0x0A00, 0x0BF3, + 0x0B00, 0x0D00, 0x0EF2, 0x0FF2, 0xF20F, 0xF3FF, 0xF301, 0xF306, 0xF309, + 0xF30C, 0xF405, 0xF40B, 0xF40D, 0xF5F8, 0xF5FB, 0xF509, 0xF700, 0xF90F, + 0xFCF4, 0xFCF5, 0xFF0C, 0x00F5, 0x01F5, 0x060D, 0x08FF, 0x0AF4, 0x0A0D, + 0x0BF6, 0x0B01, 0x0B0B, 0x0CF2, 0x0CFA, 0x0CFE, 0x0DF7, 0x0DFA, 0x0DFD, + 0x0D0A, 0x0FF4, 0xF1F2, 0xF1F9, 0xF20A, 0xF20C, 0xF3F1, 0xF4F5, 0xF5F4, + 0xF6F6, 0xF7F3, 0xF7F5, 0xF7FE, 0xF709, 0xF8F2, 0xF80E, 0xF9F5, 0xFA00, + 0xFBF1, 0xFC07, 0xFDF4, 0xFD0B, 0xFE0A, 0xFFF6, 0xFFF8, 0x00FA, 0x0208, + 0x020B, 0x04F6, 0x04F7, 0x06F8, 0x060B, 0x07F2, 0x07F6, 0x07F9, 0x070F, + 0x08FA, 0x0903, 0x0904, 0x0A07, 0x0A08, 0x0A0E, 0x0CF7, 0x0D0F, 0x0EF7, + 0x0EFC, 0x0301, 0xF8FD, 0x0E0D, 0x0F03, 0xF9F2, 0xFBFF, 0xFFFB, 0x0803, + 0x0F0D, 0x0FFD, 0xF10D, 0x10F3, 0xF9FD, 0xF901, 0xF902, 0xFB07, 0xFEF9, + 0x0006, 0xF2F0, 0xF00D, 0x0307, 0x04F9, 0xFD00, 0x03F0, 0x0FF0, 0xF410, + 0xFDF0, 0xF1F6, 0xF1F8, 0xF101, 0xF2F3, 0xF207, 0xF4FA, 0xF4FC, 0xF5F5, + 0xF5F7, 0xF6F3, 0xF6F4, 0xF609, 0xF705, 0xF706, 0xF8F9, 0xF8FB, 0xF804, + 0xF909, 0xFCF1, 0xFEF1, 0xFEF7, 0xFE0B, 0x01F1, 0x02F7, 0x04F5, 0x050C, + 0x06F6, 0x06F9, 0x0609, 0x07F1, 0x08F5, 0x08FB, 0x0805, 0x080F, 0x0AF7, + 0x0B05, 0x0B0A, 0x0C08, 0x0C0B, 0x0C0D, 0x0D08, 0x0E07, 0x0FF6, 0x0FFA, + 0xFDFA, 0x0F02, 0x0F0A, 0xFD0E, 0x02F9, 0x0308, 0x0507, 0xFB03, 0x06FC, + 0x0702, 0xFCFB, 0x02FB, 0xF5F0, 0x05FD, 0x0703, 0xF2F1, 0x0003, 0xF0FC, + 0xF00F, 0xFBFE, 0xFF05, 0xFCF0, 0x10F5, 0x10FF, 0xFCFF, 0x01FC, 0xF9FB, + 0xFA02, 0xFB08, 0xFD08, 0xFEF8, 0xFE0E, 0x01FA, 0x0207, 0xFE04, 0xFBFD, + 0x0604, 0x07FC, 0x0300, 0x0410, 0xF001, 0x09FD, 0xF302, 0xF402, 0xF406, + 0xF40E, 0xFDFF, 0xFD10, 0xF110, 0x10F9, 0x03FF, 0xFBF0, 0xF5F9, 0xF5FC, + 0xF501, 0xF503, 0xF50F, 0xF600, 0xF607, 0xF70B, 0xF70C, 0xF908, 0xFBF3, + 0xFFF3, 0x00F3, 0x0009, 0x010C, 0x010D, 0x03F3, 0x08F4, 0x0A05, 0x0CF8, + 0x0CFC, 0x0DF1, 0x0DF2, 0x0DFB, 0xF1F4, 0xF1F5, 0xF1FE, 0xF2F4, 0xF2F8, + 0xF2F9, 0xF20D, 0xF4F3, 0xF5F1, 0xF5FE, 0xF50D, 0xF6FE, 0xF7F8, 0xF8FF, + 0xF808, 0xF80C, 0xF9F4, 0xFA0A, 0xFA0C, 0xFBF2, 0xFBF4, 0xFFF7, 0x02F6, + 0x030C, 0x030F, 0x0409, 0x07F4, 0x08F6, 0x08F9, 0x0808, 0x080A, 0x0908, + 0x090D, 0x0AFC, 0x0AFD, 0x0BF7, 0x0C0F, 0x0D05, 0x0D07, 0x0EF4, 0xF2FE, + 0x0F00, 0x0F01, 0xF7FD, 0xF8FC, 0xF9F9, 0xFB00, 0xFE07, 0x00F9, 0x050E, + 0x06FF, 0x0705, 0x080E, 0x0A0F, 0x0EFD, 0xFD06, 0x03FB, 0x0502, 0x0503, + 0x0EF0, 0x10F2, 0xF1F0, 0x04FF, 0x06F0, 0xFCFE, 0x00FD, 0x10FC, 0x0E0F, + 0xF9F7, 0xF9F8, 0xF9FA, 0xFA05, 0xFBF8, 0x03FE, 0x02FD, 0x02FE, 0xFBF9, + 0x04FA, 0x0708, 0x08FD, 0xFB02, 0x0005, 0x02FC, 0x0401, 0x01FF, 0xFEFD, + 0x0310, 0x0305, 0xF1FA, 0xF106, 0xF209, 0xF20B, 0xFC01, 0xFDFC, 0xFEF0, + 0xFE10, 0x02F0, 0xF7F0, 0x00FC, 0xF3F4, 0xF3F5, 0xF3F6, 0xF3F9, 0xF408, + 0xF5F6, 0xF504, 0xF50B, 0x0203, 0xF6F7, 0xF6F9, 0xF60F, 0xF8F3, 0xF806, + 0xF80D, 0xF80F, 0xF90D, 0xFAF4, 0xFAF5, 0xFA08, 0xFC0C, 0xFD0C, 0xFE0C, + 0xFF0B, 0x00F1, 0x0202, 0x00F7, 0x000F, 0x02F4, 0x020C, 0x03F5, 0x05F5, + 0x060A, 0x07F3, 0x07F7, 0x0700, 0x0701, 0x08F7, 0x08F8, 0x09F8, 0x09FF, + 0x0AF8, 0x0AFF, 0x0A0C, 0x0BFA, 0x0BFB, 0x0B03, 0x0C0A, 0x0D0C, 0x0EF6, + 0x0FF5, 0x0FF9, 0x0FFE, 0x0F0E, 0xF3F2, 0xF802, 0xF803, 0xF9F1, 0xF9FE, + 0xFAFA, 0xFB06, 0xFC0E, 0xFF0E, 0x0508, 0xF00E, 0x07FF, 0x0EFB, 0xFC04, + 0xFD05, 0xF8F0, 0x02FA, 0x0505, 0xFC10, 0x0510, 0xFF01, 0x0101, 0xFFFF, + 0xF0F0, 0x1010, 0x0002, 0x0C10, 0xFB10, 0xFEFC, 0x0400, 0xF4F0, 0x0FFB, + 0x0F0F, 0xF10E, 0xF3FE, 0xF404, 0x01F4, 0xF2F5, 0xF202, 0xF9F0, 0x0210, + 0xFE02, 0x05F0, 0x0610, 0xF7F1, 0xF8F8, 0xF9FC, 0xF904, 0xFAF1, 0xFDF6, + 0xFD07, 0xFE08, 0xFEFE, 0x01F9, 0x02F8, 0x0605, 0x0608, 0x070E, 0x0D0D, + 0x0EFF, 0x0E05, 0xFAF0, 0x10F4, 0x0E06, 0x0E0C, 0x0D10, 0xF6F0, 0x04FE, + 0xFBFC, 0x05FE, 0x0204, 0x0402, 0x0710, 0xFC02, 0xFE03, 0xFD04, 0x0004, + 0xF10A, 0x0CFF, 0x0DF3, 0xF3FD, 0xF4F1, 0xF40A, 0xF5FF, 0xF50C, 0xF6F1, + 0xF608, 0xF70D, 0xFB0B, 0xFEF6, 0xFFF4, 0x00F4, 0x030D, 0x0CF6, 0xF1FB, + 0x0CF9, 0x0DF9, 0xF1FC, 0xF100, 0xF10C, 0xF403, 0xF409, 0xF5FD, 0xF502, + 0xF50E, 0xF6FA, 0xF601, 0xF605, 0xF60E, 0xF7FF, 0xF8F4, 0xF807, 0xF80A, + 0xF90A, 0xFA0F, 0xFB0C, 0xFB0D, 0xFB0F, 0xFD0D, 0xFE09, 0xFF09, 0x00F6, + 0x00F8, 0x010B, 0x010F, 0x020A, 0x040D, 0x05FA, 0x050B, 0x06F3, 0x060C, + 0x08F2, 0x0800, 0x080B, 0x080D, 0x09F6, 0x09F7, 0x09FA, 0x090C, 0x0AFB, + 0x0AFE, 0x0BF1, 0x0BF8, 0x0BFD, 0x0B04, 0x0CF5, 0x0CFD, 0x0C04, 0x0C0C, + 0x0DFC, 0x0EF3, 0xF8F7, 0x0E00, 0x0FF7, 0xF8FE, 0xFA04, 0xFCF8, 0xFDF8, + 0xFFF2, 0x040B, 0x05F8, 0x0607, 0x060E, 0x090F, 0x0306, 0x0EFE, 0x0E04, + 0xF0FB, 0x0E10, 0x0403, 0x0603, 0x0E0E, 0xF2F2, 0xFD02, 0xF3F0, 0x0810, + 0x0302, 0xFE06, 0xF4F7, 0xF702, 0xF801, 0xF805, 0xFAF2, 0xFBF7, 0xFB09, + 0xFCF6, 0xFF08, 0x010E, 0x060F, 0x0707, 0x0804, 0x0909, 0x03FC, 0x05FC, + 0x090E, 0x0E03, 0x08F0, 0x05FF, 0xF0FF, 0xFCFD, 0xFA01, 0xFB01, 0xFDFE, + 0x0110, 0x0404, 0x00FE, 0xF0F5, 0x0606, 0xF1FF, 0x0FF1, 0xF3FA, 0xF102, + 0xF105, 0x1002, 0xF108, 0xF109, 0xF2F7, 0xF3F8, 0xF4FD, 0xF407, 0xF5F3, + 0xF6F8, 0xF6FB, 0xF6FF, 0xF602, 0xF603, 0xF7F9, 0xF704, 0xF707, 0xF70A, + 0xF809, 0xFAF3, 0xFA0D, 0xFCF3, 0xFDF3, 0xFEF4, 0xFEF5, 0xFFF5, 0x010A, + 0x030B, 0x04F3, 0x04F4, 0x040C, 0x05F3, 0x050A, 0x050D, 0x06F4, 0x06F5, + 0x07F5, 0x080C, 0x09F2, 0x09F4, 0x09F5, 0x090A, 0x0AF3, 0x0A01, 0x0BF2, + 0x0BF5, 0x0BF9, 0x0B0D, 0x0CF3, 0x0CFB, 0x0DF4, 0x0FF8, 0x0F09, 0x0F0B, + 0xF1FD, 0xF4F2, 0xF7F7, 0xF7FA, 0xF906, 0xF907, 0xFA07, 0xFA0E, 0xFB05, + 0xFB0E, 0xFC0F, 0xFDF1, 0xFDF7, 0xFE0F, 0x0007, 0x000E, 0x01F7, 0x03F6, + 0x04F8, 0x0406, 0x050F, 0x06F2, 0x0600, 0x07FE, 0x0706, 0x08FE, 0x0801, + 0x0802, 0x0806, 0x0A09, 0xF210, 0x0A0A, 0x0B09, 0xF0F6, 0x0106, 0x03FA, + 0xF003, 0xFA10, 0xF0F2, 0x0504, 0x0E02, 0xF201, 0xFFFE, 0xF0F9, 0xF810, + 0x04F0, 0x0B10, 0x0F10, 0x10FA, 0x1007, 0x100B, 0x01FE, 0x0303, 0xF0F8, + 0x0AF0, 0x10FB, 0x1003, 0xF0F7, 0xF910, 0x0102, 0x02FF, 0xFE00, 0xFEFB, + 0xFF10, 0xF203, 0xF206, 0xF208, 0xF7F6, 0xF7FC, 0xFC06, 0xFD0A, 0xFFF1, + 0x01F8, 0x020F, 0x03F1, 0x0309, 0x04F1, 0x05F1, 0x05F2, 0x06FB, 0x07F8, + 0x070C, 0x09F9, 0x0902, 0xFA03, 0x0B07, 0x0B0E, 0xFF02, 0xFC00, 0x0304, + 0x0910, 0x0405, 0xFAFC, 0xFC03, 0xFAFD, 0xFAFE, 0xFCF9, 0xFCFA, 0x04FB, + 0x0501, 0x0200, 0xF0FA, 0xF005, 0xF006, 0x04FD, 0xFDFD, 0x10F8, 0xF710, + 0xF300, 0xF303, 0xF304, 0xF4FB, 0xF400, 0xF40C, 0xF500, 0xFF0D, 0x000B, + 0x0AF9, 0x0BFF, 0x0DFE, 0xF10B, 0x0DFF, 0x0D0B, 0xF2FC, 0xF3FB, 0xF30A, + 0xF30B, 0xF30E, 0xF4F8, 0xF506, 0xF507, 0xF6FD, 0xF604, 0xF60A, 0xF80B, + 0xFA0B, 0xFE0D, 0x00F2, 0x01F6, 0x0108, 0x02F3, 0x03F4, 0x05F4, 0x070D, + 0x08F3, 0x09F3, 0x0900, 0x0AF5, 0x0AF6, 0x0A04, 0x0B02, 0x0C03, 0x0C05, + 0x0C06, 0x0C09, 0x0D02, 0x0D06, 0x0D09, 0x0FF3, 0xF7F2, 0x0F04, 0x0F0C, + 0xF703, 0xF8FA, 0xFAF6, 0xFC09, 0xFD0F, 0xFFF9, 0xFF0F, 0x01F2, 0x02F1, + 0x03F2, 0x03F7, 0x03F9, 0x05FB, 0x07FB, 0x09FB, 0x0905, 0x0907, 0x0EFA, + 0x0F05, 0x0F06, 0xF000, 0xFB04, 0xF0F3, 0xFFFA, 0x1000, 0x0A10, 0x0CF0 +}; + +const int ff_on2avc_cb_elems[] = { + ON2AVC_CB_1_2_CODES, ON2AVC_CB_1_2_CODES, ON2AVC_CB_3_4_CODES, + ON2AVC_CB_3_4_CODES, ON2AVC_CB_5_6_CODES, ON2AVC_CB_5_6_CODES, + ON2AVC_CB_7_8_CODES, ON2AVC_CB_7_8_CODES, ON2AVC_CB_9_10_CODES, + ON2AVC_CB_9_10_CODES, ON2AVC_CB_11_CODES, ON2AVC_CB_12_CODES, + ON2AVC_CB_13_CODES, ON2AVC_CB_14_CODES, ON2AVC_CB_15_CODES }; const float ff_on2avc_window_long_32000[1024] = { diff -Nru ffmpeg-4.2.2/libavcodec/on2avcdata.h ffmpeg-4.4/libavcodec/on2avcdata.h --- ffmpeg-4.2.2/libavcodec/on2avcdata.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/on2avcdata.h 2021-04-08 21:28:39.000000000 +0000 @@ -38,17 +38,12 @@ extern const On2AVCMode ff_on2avc_modes_44[8]; #define ON2AVC_SCALE_DIFFS 121 -extern const uint32_t ff_on2avc_scale_diff_codes[]; -extern const uint8_t ff_on2avc_scale_diff_bits[]; +extern const uint8_t ff_on2avc_scale_diff_syms[]; +extern const uint8_t ff_on2avc_scale_diff_bits[]; -extern const uint32_t * const ff_on2avc_quad_cb_codes[]; -extern const uint8_t * const ff_on2avc_quad_cb_bits[]; -extern const uint16_t * const ff_on2avc_quad_cb_syms[]; -extern const int ff_on2avc_quad_cb_elems[]; -extern const uint16_t * const ff_on2avc_pair_cb_codes[]; -extern const uint8_t * const ff_on2avc_pair_cb_bits[]; -extern const uint16_t * const ff_on2avc_pair_cb_syms[]; -extern const int ff_on2avc_pair_cb_elems[]; +extern const uint8_t ff_on2avc_cb_lens[]; +extern const uint16_t ff_on2avc_cb_syms[]; +extern const int ff_on2avc_cb_elems[]; extern const float ff_on2avc_window_long_32000[1024]; extern const float ff_on2avc_window_long_24000[1024]; diff -Nru ffmpeg-4.2.2/libavcodec/options.c ffmpeg-4.4/libavcodec/options.c --- ffmpeg-4.2.2/libavcodec/options.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/options.c 2021-04-08 21:28:39.000000000 +0000 @@ -53,17 +53,30 @@ return NULL; } +#if FF_API_CHILD_CLASS_NEXT static const AVClass *codec_child_class_next(const AVClass *prev) { - AVCodec *c = NULL; + void *iter = NULL; + const AVCodec *c = NULL; /* find the codec that corresponds to prev */ - while (prev && (c = av_codec_next(c))) + while (prev && (c = av_codec_iterate(&iter))) if (c->priv_class == prev) break; /* find next codec with priv options */ - while (c = av_codec_next(c)) + while (c = av_codec_iterate(&iter)) + if (c->priv_class) + return c->priv_class; + return NULL; +} +#endif + +static const AVClass *codec_child_class_iterate(void **iter) +{ + const AVCodec *c; + /* find next codec with priv options */ + while (c = av_codec_iterate(iter)) if (c->priv_class) return c->priv_class; return NULL; @@ -83,7 +96,10 @@ .version = LIBAVUTIL_VERSION_INT, .log_level_offset_offset = offsetof(AVCodecContext, log_level_offset), .child_next = codec_child_next, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = codec_child_class_next, +#endif + .child_class_iterate = codec_child_class_iterate, .category = AV_CLASS_CATEGORY_ENCODER, .get_category = get_category, }; @@ -114,6 +130,7 @@ s->pkt_timebase = (AVRational){ 0, 1 }; s->get_buffer2 = avcodec_default_get_buffer2; s->get_format = avcodec_default_get_format; + s->get_encode_buffer = avcodec_default_get_encode_buffer; s->execute = avcodec_default_execute; s->execute2 = avcodec_default_execute2; s->sample_aspect_ratio = (AVRational){0,1}; @@ -296,6 +313,7 @@ return &av_codec_context_class; } +#if FF_API_GET_FRAME_CLASS #define FOFFSET(x) offsetof(AVFrame,x) static const AVOption frame_options[]={ @@ -322,6 +340,7 @@ { return &av_frame_class; } +#endif #define SROFFSET(x) offsetof(AVSubtitleRect,x) diff -Nru ffmpeg-4.2.2/libavcodec/options_table.h ffmpeg-4.4/libavcodec/options_table.h --- ffmpeg-4.2.2/libavcodec/options_table.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/options_table.h 2021-04-08 21:28:39.000000000 +0000 @@ -38,6 +38,7 @@ #define S AV_OPT_FLAG_SUBTITLE_PARAM #define E AV_OPT_FLAG_ENCODING_PARAM #define D AV_OPT_FLAG_DECODING_PARAM +#define CC AV_OPT_FLAG_CHILD_CONSTS #define AV_CODEC_DEFAULT_BITRATE 200*1000 @@ -68,7 +69,7 @@ {"cgop", "closed GOP", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_CLOSED_GOP }, INT_MIN, INT_MAX, V|E, "flags"}, {"output_corrupt", "Output even potentially corrupted frames", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_OUTPUT_CORRUPT }, INT_MIN, INT_MAX, V|D, "flags"}, {"drop_changed", "Drop frames whose parameters differ from first decoded frame", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_DROPCHANGED }, INT_MIN, INT_MAX, A|V|D, "flags"}, -{"flags2", NULL, OFFSET(flags2), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, V|A|E|D, "flags2"}, +{"flags2", NULL, OFFSET(flags2), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, V|A|E|D|S, "flags2"}, {"fast", "allow non-spec-compliant speedup tricks", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_FAST }, INT_MIN, INT_MAX, V|E, "flags2"}, {"noout", "skip bitstream encoding", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_NO_OUTPUT }, INT_MIN, INT_MAX, V|E, "flags2"}, {"ignorecrop", "ignore cropping information from sps", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_IGNORE_CROP }, INT_MIN, INT_MAX, V|D, "flags2"}, @@ -76,8 +77,13 @@ {"chunks", "Frame data might be split into multiple chunks", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_CHUNKS }, INT_MIN, INT_MAX, V|D, "flags2"}, {"showall", "Show all frames before the first keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_SHOW_ALL }, INT_MIN, INT_MAX, V|D, "flags2"}, {"export_mvs", "export motion vectors through frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_EXPORT_MVS}, INT_MIN, INT_MAX, V|D, "flags2"}, -{"skip_manual", "do not skip samples and export skip information as frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_SKIP_MANUAL}, INT_MIN, INT_MAX, V|D, "flags2"}, +{"skip_manual", "do not skip samples and export skip information as frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_SKIP_MANUAL}, INT_MIN, INT_MAX, A|D, "flags2"}, {"ass_ro_flush_noop", "do not reset ASS ReadOrder field on flush", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_RO_FLUSH_NOOP}, INT_MIN, INT_MAX, S|D, "flags2"}, +{"export_side_data", "Export metadata as side data", OFFSET(export_side_data), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, A|V|S|D|E, "export_side_data"}, +{"mvs", "export motion vectors through frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_EXPORT_DATA_MVS}, INT_MIN, INT_MAX, V|D, "export_side_data"}, +{"prft", "export Producer Reference Time through packet side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_EXPORT_DATA_PRFT}, INT_MIN, INT_MAX, A|V|S|E, "export_side_data"}, +{"venc_params", "export video encoding parameters through frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS}, INT_MIN, INT_MAX, V|D, "export_side_data"}, +{"film_grain", "export film grain parameters through frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_EXPORT_DATA_FILM_GRAIN}, INT_MIN, INT_MAX, V|D, "export_side_data"}, {"time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, INT_MAX}, {"g", "set the group of picture (GOP) size", OFFSET(gop_size), AV_OPT_TYPE_INT, {.i64 = 12 }, INT_MIN, INT_MAX, V|E}, {"ar", "set audio sampling rate (in Hz)", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, A|D|E}, @@ -134,15 +140,15 @@ {"unofficial", "allow unofficial extensions", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_UNOFFICIAL }, INT_MIN, INT_MAX, A|V|D|E, "strict"}, {"experimental", "allow non-standardized experimental things", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_EXPERIMENTAL }, INT_MIN, INT_MAX, A|V|D|E, "strict"}, {"b_qoffset", "QP offset between P- and B-frames", OFFSET(b_quant_offset), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E}, -{"err_detect", "set error detection flags", OFFSET(err_recognition), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, -{"crccheck", "verify embedded CRCs", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, -{"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, -{"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, -{"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, -{"ignore_err", "ignore errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_IGNORE_ERR }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, -{"careful", "consider things that violate the spec, are fast to check and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, -{"compliant", "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, -{"aggressive", "consider things that a sane encoder should not do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, +{"err_detect", "set error detection flags", OFFSET(err_recognition), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, INT_MIN, INT_MAX, A|V|S|D|E, "err_detect"}, +{"crccheck", "verify embedded CRCs", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|S|D|E, "err_detect"}, +{"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, A|V|S|D|E, "err_detect"}, +{"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, A|V|S|D|E, "err_detect"}, +{"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, A|V|S|D|E, "err_detect"}, +{"ignore_err", "ignore errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_IGNORE_ERR }, INT_MIN, INT_MAX, A|V|S|D|E, "err_detect"}, +{"careful", "consider things that violate the spec, are fast to check and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, A|V|S|D|E, "err_detect"}, +{"compliant", "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT | AV_EF_CAREFUL }, INT_MIN, INT_MAX, A|V|S|D|E, "err_detect"}, +{"aggressive", "consider things that a sane encoder should not do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE | AV_EF_COMPLIANT | AV_EF_CAREFUL}, INT_MIN, INT_MAX, A|V|S|D|E, "err_detect"}, {"has_b_frames", NULL, OFFSET(has_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX}, {"block_align", NULL, OFFSET(block_align), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX}, #if FF_API_PRIVATE_OPT @@ -202,9 +208,6 @@ {"bitstream", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BITSTREAM }, INT_MIN, INT_MAX, V|D, "debug"}, {"mb_type", "macroblock (MB) type", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MB_TYPE }, INT_MIN, INT_MAX, V|D, "debug"}, {"qp", "per-block quantization parameter (QP)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_QP }, INT_MIN, INT_MAX, V|D, "debug"}, -#if FF_API_DEBUG_MV -{"mv", "motion vector", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MV }, INT_MIN, INT_MAX, V|D, "debug"}, -#endif {"dct_coeff", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_DCT_COEFF }, INT_MIN, INT_MAX, V|D, "debug"}, {"green_metadata", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_GREEN_MD }, INT_MIN, INT_MAX, V|D, "debug"}, {"skip", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_SKIP }, INT_MIN, INT_MAX, V|D, "debug"}, @@ -212,10 +215,6 @@ {"er", "error recognition", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_ER }, INT_MIN, INT_MAX, V|D, "debug"}, {"mmco", "memory management control operations (H.264)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MMCO }, INT_MIN, INT_MAX, V|D, "debug"}, {"bugs", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BUGS }, INT_MIN, INT_MAX, V|D, "debug"}, -#if FF_API_DEBUG_MV -{"vis_qp", "visualize quantization parameter (QP), lower QP are tinted greener", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_QP }, INT_MIN, INT_MAX, V|D, "debug"}, -{"vis_mb_type", "visualize block types", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MB_TYPE }, INT_MIN, INT_MAX, V|D, "debug"}, -#endif {"buffers", "picture buffer allocations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BUFFERS }, INT_MIN, INT_MAX, V|D, "debug"}, {"thread_ops", "threading operations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_THREADS }, INT_MIN, INT_MAX, V|A|D, "debug"}, {"nomc", "skip motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_NOMC }, INT_MIN, INT_MAX, V|A|D, "debug"}, @@ -256,31 +255,11 @@ {"nssew", "nsse weight", OFFSET(nsse_weight), AV_OPT_TYPE_INT, {.i64 = 8 }, INT_MIN, INT_MAX, V|E}, {"skip_top", "number of macroblock rows at the top which are skipped", OFFSET(skip_top), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|D}, {"skip_bottom", "number of macroblock rows at the bottom which are skipped", OFFSET(skip_bottom), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|D}, -{"profile", NULL, OFFSET(profile), AV_OPT_TYPE_INT, {.i64 = FF_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "profile"}, -{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "profile"}, -{"aac_main", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_MAIN }, INT_MIN, INT_MAX, A|E, "profile"}, -{"aac_low", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_LOW }, INT_MIN, INT_MAX, A|E, "profile"}, -{"aac_ssr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_SSR }, INT_MIN, INT_MAX, A|E, "profile"}, -{"aac_ltp", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_LTP }, INT_MIN, INT_MAX, A|E, "profile"}, -{"aac_he", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_HE }, INT_MIN, INT_MAX, A|E, "profile"}, -{"aac_he_v2", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_HE_V2 }, INT_MIN, INT_MAX, A|E, "profile"}, -{"aac_ld", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_LD }, INT_MIN, INT_MAX, A|E, "profile"}, -{"aac_eld", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_ELD }, INT_MIN, INT_MAX, A|E, "profile"}, -{"mpeg2_aac_low", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG2_AAC_LOW }, INT_MIN, INT_MAX, A|E, "profile"}, -{"mpeg2_aac_he", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG2_AAC_HE }, INT_MIN, INT_MAX, A|E, "profile"}, -{"dts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS }, INT_MIN, INT_MAX, A|E, "profile"}, -{"dts_es", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_ES }, INT_MIN, INT_MAX, A|E, "profile"}, -{"dts_96_24", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_96_24 }, INT_MIN, INT_MAX, A|E, "profile"}, -{"dts_hd_hra", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_HD_HRA }, INT_MIN, INT_MAX, A|E, "profile"}, -{"dts_hd_ma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_HD_MA }, INT_MIN, INT_MAX, A|E, "profile"}, -{"mpeg4_sp", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG4_SIMPLE }, INT_MIN, INT_MAX, V|E, "profile"}, -{"mpeg4_core", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG4_CORE }, INT_MIN, INT_MAX, V|E, "profile"}, -{"mpeg4_main", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG4_MAIN }, INT_MIN, INT_MAX, V|E, "profile"}, -{"mpeg4_asp", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_MPEG4_ADVANCED_SIMPLE }, INT_MIN, INT_MAX, V|E, "profile"}, -{"main10", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_HEVC_MAIN_10 }, INT_MIN, INT_MAX, V|E, "profile"}, -{"msbc", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_SBC_MSBC }, INT_MIN, INT_MAX, A|E, "profile"}, -{"level", NULL, OFFSET(level), AV_OPT_TYPE_INT, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"}, -{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"}, +{"profile", NULL, OFFSET(profile), AV_OPT_TYPE_INT, {.i64 = FF_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, V|A|E|CC, "avctx.profile"}, +{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "avctx.profile"}, +{"main10", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_HEVC_MAIN_10 }, INT_MIN, INT_MAX, V|E, "avctx.profile"}, +{"level", NULL, OFFSET(level), AV_OPT_TYPE_INT, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E|CC, "avctx.level"}, +{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "avctx.level"}, {"lowres", "decode at 1= 1/2, 2=1/4, 3=1/8 resolutions", OFFSET(lowres), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|A|D}, #if FF_API_PRIVATE_OPT {"skip_threshold", "frame skip threshold", OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, @@ -366,6 +345,7 @@ {"smpte431", "SMPTE 431-2", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_SMPTE431 }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, {"smpte432", "SMPTE 422-1", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_SMPTE432 }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, {"jedec-p22", "JEDEC P22", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_JEDEC_P22 }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, +{"ebu3213", "EBU 3213-E", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_EBU3213 }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, {"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_PRI_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "color_primaries_type"}, {"color_trc", "color transfer characteristics", OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64 = AVCOL_TRC_UNSPECIFIED }, 1, INT_MAX, V|E|D, "color_trc_type"}, {"bt709", "BT.709", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT709 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, @@ -395,21 +375,24 @@ {"bt2020_12bit", "BT.2020 - 12 bit", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT2020_12 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, {"smpte428_1", "SMPTE 428-1", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_SMPTE428 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"}, {"colorspace", "color space", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = AVCOL_SPC_UNSPECIFIED }, 0, INT_MAX, V|E|D, "colorspace_type"}, -{"rgb", "RGB", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_RGB }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"bt709", "BT.709", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT709 }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"unknown", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"fcc", "FCC", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_FCC }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"bt470bg", "BT.470 BG", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT470BG }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"smpte170m", "SMPTE 170 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_SMPTE170M }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"smpte240m", "SMPTE 240 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_SMPTE240M }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"ycgco", "YCGCO", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_YCGCO }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"bt2020nc", "BT.2020 NCL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_NCL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"bt2020c", "BT.2020 CL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_CL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"smpte2085", "SMPTE 2085", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_SMPTE2085 }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"ycocg", "YCGCO", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_YCGCO }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"bt2020_ncl", "BT.2020 NCL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_NCL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, -{"bt2020_cl", "BT.2020 CL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_CL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"rgb", "RGB", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_RGB }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"bt709", "BT.709", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT709 }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"unknown", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"fcc", "FCC", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_FCC }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"bt470bg", "BT.470 BG", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT470BG }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"smpte170m", "SMPTE 170 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_SMPTE170M }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"smpte240m", "SMPTE 240 M", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_SMPTE240M }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"ycgco", "YCGCO", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_YCGCO }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"bt2020nc", "BT.2020 NCL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_NCL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"bt2020c", "BT.2020 CL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_CL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"smpte2085", "SMPTE 2085", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_SMPTE2085 }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"chroma-derived-nc", "Chroma-derived NCL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_CHROMA_DERIVED_NCL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"chroma-derived-c", "Chroma-derived CL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_CHROMA_DERIVED_CL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"ictcp", "ICtCp", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_ICTCP }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"ycocg", "YCGCO", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_YCGCO }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"bt2020_ncl", "BT.2020 NCL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_NCL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, +{"bt2020_cl", "BT.2020 CL", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT2020_CL }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"}, {"color_range", "color range", OFFSET(color_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, INT_MAX, V|E|D, "color_range_type"}, {"unknown", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "color_range_type"}, {"tv", "MPEG (219*2^(n-8))", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_RANGE_MPEG }, INT_MIN, INT_MAX, V|E|D, "color_range_type"}, @@ -443,7 +426,7 @@ {"ka", "Karaoke", 0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_KARAOKE }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, {"request_sample_fmt", "sample format audio decoders should prefer", OFFSET(request_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64=AV_SAMPLE_FMT_NONE}, -1, INT_MAX, A|D, "request_sample_fmt"}, {"pkt_timebase", NULL, OFFSET(pkt_timebase), AV_OPT_TYPE_RATIONAL, {.dbl = 0 }, 0, INT_MAX, 0}, -{"sub_charenc", "set input text subtitles character encoding", OFFSET(sub_charenc), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, S|D}, +{"sub_charenc", "set input text subtitles character encoding", OFFSET(sub_charenc), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, S|D}, {"sub_charenc_mode", "set input text subtitles character encoding mode", OFFSET(sub_charenc_mode), AV_OPT_TYPE_FLAGS, {.i64 = FF_SUB_CHARENC_MODE_AUTOMATIC}, -1, INT_MAX, S|D, "sub_charenc_mode"}, {"do_nothing", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_DO_NOTHING}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, {"auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_AUTOMATIC}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, @@ -458,7 +441,9 @@ #if FF_API_ASS_TIMING {"ass_with_timings", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS}, INT_MIN, INT_MAX, S|D, "sub_text_format"}, #endif +#if FF_API_OLD_ENCDEC {"refcounted_frames", NULL, OFFSET(refcounted_frames), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, A|V|D }, +#endif #if FF_API_SIDEDATA_ONLY_PKT {"side_data_only_packets", NULL, OFFSET(side_data_only_packets), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, A|V|E }, #endif @@ -470,11 +455,12 @@ {"bb", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_BB }, 0, 0, V|D|E, "field_order" }, {"tb", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_TB }, 0, 0, V|D|E, "field_order" }, {"bt", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_BT }, 0, 0, V|D|E, "field_order" }, -{"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, A|V|S|D|E}, -{"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, A|V|S|D }, +{"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, A|V|S|D|E}, +{"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, A|V|S|D }, {"pixel_format", "set pixel format", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64=AV_PIX_FMT_NONE}, -1, INT_MAX, 0 }, {"video_size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str=NULL}, 0, INT_MAX, 0 }, {"max_pixels", "Maximum number of pixels", OFFSET(max_pixels), AV_OPT_TYPE_INT64, {.i64 = INT_MAX }, 0, INT_MAX, A|V|S|D|E }, +{"max_samples", "Maximum number of samples", OFFSET(max_samples), AV_OPT_TYPE_INT64, {.i64 = INT_MAX }, 0, INT_MAX, A|D|E }, {"hwaccel_flags", NULL, OFFSET(hwaccel_flags), AV_OPT_TYPE_FLAGS, {.i64 = AV_HWACCEL_FLAG_IGNORE_LEVEL }, 0, UINT_MAX, V|D, "hwaccel_flags"}, {"ignore_level", "ignore level even if the codec level used is unknown or higher than the maximum supported level reported by the hardware driver", 0, AV_OPT_TYPE_CONST, { .i64 = AV_HWACCEL_FLAG_IGNORE_LEVEL }, INT_MIN, INT_MAX, V | D, "hwaccel_flags" }, {"allow_high_depth", "allow to output YUV pixel formats with a different chroma sampling than 4:2:0 and/or other than 8 bits per component", 0, AV_OPT_TYPE_CONST, {.i64 = AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH }, INT_MIN, INT_MAX, V | D, "hwaccel_flags"}, @@ -489,6 +475,7 @@ #undef S #undef E #undef D +#undef CC #undef DEFAULT #undef OFFSET diff -Nru ffmpeg-4.2.2/libavcodec/opus.c ffmpeg-4.4/libavcodec/opus.c --- ffmpeg-4.2.2/libavcodec/opus.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opus.c 2020-07-11 10:39:30.000000000 +0000 @@ -613,6 +613,8 @@ } /* Allocation trim */ + if (!encode) + f->alloc_trim = 5; if (opus_rc_tell_frac(rc) + (6 << 3) <= tbits_8ths) if (encode) ff_opus_rc_enc_cdf(rc, f->alloc_trim, ff_celt_model_alloc_trim); diff -Nru ffmpeg-4.2.2/libavcodec/opus_celt.c ffmpeg-4.4/libavcodec/opus_celt.c --- ffmpeg-4.2.2/libavcodec/opus_celt.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opus_celt.c 2020-07-11 10:39:30.000000000 +0000 @@ -507,7 +507,11 @@ memset(block->pf_gains_old, 0, sizeof(block->pf_gains_old)); memset(block->pf_gains_new, 0, sizeof(block->pf_gains_new)); - block->emph_coeff = 0.0; + /* libopus uses CELT_EMPH_COEFF on init, but 0 is better since there's + * a lesser discontinuity when seeking. + * The deemphasis functions differ from libopus in that they require + * an initial state divided by the coefficient. */ + block->emph_coeff = 0.0f / CELT_EMPH_COEFF; } f->seed = 0; diff -Nru ffmpeg-4.2.2/libavcodec/opus_celt.h ffmpeg-4.4/libavcodec/opus_celt.h --- ffmpeg-4.2.2/libavcodec/opus_celt.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opus_celt.h 2021-04-08 21:28:39.000000000 +0000 @@ -33,6 +33,7 @@ #include "mdct15.h" #include "libavutil/float_dsp.h" #include "libavutil/libm.h" +#include "libavutil/mem_internal.h" #define CELT_VECTORS 11 #define CELT_ALLOC_STEPS 6 diff -Nru ffmpeg-4.2.2/libavcodec/opusdec.c ffmpeg-4.4/libavcodec/opusdec.c --- ffmpeg-4.2.2/libavcodec/opusdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opusdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -87,7 +87,7 @@ int celt_size = av_audio_fifo_size(s->celt_delay); int ret, i; ret = swr_convert(s->swr, - (uint8_t**)s->out, nb_samples, + (uint8_t**)s->cur_out, nb_samples, NULL, 0); if (ret < 0) return ret; @@ -104,7 +104,7 @@ } av_audio_fifo_read(s->celt_delay, (void**)s->celt_output, nb_samples); for (i = 0; i < s->output_channels; i++) { - s->fdsp->vector_fmac_scalar(s->out[i], + s->fdsp->vector_fmac_scalar(s->cur_out[i], s->celt_output[i], 1.0, nb_samples); } @@ -112,15 +112,15 @@ if (s->redundancy_idx) { for (i = 0; i < s->output_channels; i++) - opus_fade(s->out[i], s->out[i], + opus_fade(s->cur_out[i], s->cur_out[i], s->redundancy_output[i] + 120 + s->redundancy_idx, ff_celt_window2 + s->redundancy_idx, 120 - s->redundancy_idx); s->redundancy_idx = 0; } - s->out[0] += nb_samples; - s->out[1] += nb_samples; - s->out_size -= nb_samples * sizeof(float); + s->cur_out[0] += nb_samples; + s->cur_out[1] += nb_samples; + s->remaining_out_size -= nb_samples * sizeof(float); return 0; } @@ -199,7 +199,7 @@ return samples; } samples = swr_convert(s->swr, - (uint8_t**)s->out, s->packet.frame_duration, + (uint8_t**)s->cur_out, s->packet.frame_duration, (const uint8_t**)s->silk_output, samples); if (samples < 0) { av_log(s->avctx, AV_LOG_ERROR, "Error resampling SILK data.\n"); @@ -240,7 +240,7 @@ /* decode the CELT frame */ if (s->packet.mode == OPUS_MODE_CELT || s->packet.mode == OPUS_MODE_HYBRID) { - float *out_tmp[2] = { s->out[0], s->out[1] }; + float *out_tmp[2] = { s->cur_out[0], s->cur_out[1] }; float **dst = (s->packet.mode == OPUS_MODE_CELT) ? out_tmp : s->celt_output; int celt_output_samples = samples; @@ -295,7 +295,7 @@ if (s->redundancy_idx) { for (i = 0; i < s->output_channels; i++) - opus_fade(s->out[i], s->out[i], + opus_fade(s->cur_out[i], s->cur_out[i], s->redundancy_output[i] + 120 + s->redundancy_idx, ff_celt_window2 + s->redundancy_idx, 120 - s->redundancy_idx); s->redundancy_idx = 0; @@ -308,8 +308,8 @@ return ret; for (i = 0; i < s->output_channels; i++) { - opus_fade(s->out[i] + samples - 120 + delayed_samples, - s->out[i] + samples - 120 + delayed_samples, + opus_fade(s->cur_out[i] + samples - 120 + delayed_samples, + s->cur_out[i] + samples - 120 + delayed_samples, s->redundancy_output[i] + 120, ff_celt_window2, 120 - delayed_samples); if (delayed_samples) @@ -317,10 +317,10 @@ } } else { for (i = 0; i < s->output_channels; i++) { - memcpy(s->out[i] + delayed_samples, s->redundancy_output[i], 120 * sizeof(float)); - opus_fade(s->out[i] + 120 + delayed_samples, + memcpy(s->cur_out[i] + delayed_samples, s->redundancy_output[i], 120 * sizeof(float)); + opus_fade(s->cur_out[i] + 120 + delayed_samples, s->redundancy_output[i] + 120, - s->out[i] + 120 + delayed_samples, + s->cur_out[i] + 120 + delayed_samples, ff_celt_window2, 120); } } @@ -331,16 +331,15 @@ static int opus_decode_subpacket(OpusStreamContext *s, const uint8_t *buf, int buf_size, - float **out, int out_size, int nb_samples) { int output_samples = 0; int flush_needed = 0; int i, j, ret; - s->out[0] = out[0]; - s->out[1] = out[1]; - s->out_size = out_size; + s->cur_out[0] = s->out[0]; + s->cur_out[1] = s->out[1]; + s->remaining_out_size = s->out_size; /* check if we need to flush the resampler */ if (swr_is_initialized(s->swr)) { @@ -357,15 +356,16 @@ return 0; /* use dummy output buffers if the channel is not mapped to anything */ - if (!s->out[0] || - (s->output_channels == 2 && !s->out[1])) { - av_fast_malloc(&s->out_dummy, &s->out_dummy_allocated_size, s->out_size); + if (!s->cur_out[0] || + (s->output_channels == 2 && !s->cur_out[1])) { + av_fast_malloc(&s->out_dummy, &s->out_dummy_allocated_size, + s->remaining_out_size); if (!s->out_dummy) return AVERROR(ENOMEM); - if (!s->out[0]) - s->out[0] = s->out_dummy; - if (!s->out[1]) - s->out[1] = s->out_dummy; + if (!s->cur_out[0]) + s->cur_out[0] = s->out_dummy; + if (!s->cur_out[1]) + s->cur_out[1] = s->out_dummy; } /* flush the resampler if necessary */ @@ -394,19 +394,19 @@ return samples; for (j = 0; j < s->output_channels; j++) - memset(s->out[j], 0, s->packet.frame_duration * sizeof(float)); + memset(s->cur_out[j], 0, s->packet.frame_duration * sizeof(float)); samples = s->packet.frame_duration; } output_samples += samples; for (j = 0; j < s->output_channels; j++) - s->out[j] += samples; - s->out_size -= samples * sizeof(float); + s->cur_out[j] += samples; + s->remaining_out_size -= samples * sizeof(float); } finish: - s->out[0] = s->out[1] = NULL; - s->out_size = 0; + s->cur_out[0] = s->cur_out[1] = NULL; + s->remaining_out_size = 0; return output_samples; } @@ -429,7 +429,7 @@ s->out[0] = s->out[1] = NULL; delayed_samples = FFMAX(delayed_samples, - s->delayed_samples + av_audio_fifo_size(c->sync_buffers[i])); + s->delayed_samples + av_audio_fifo_size(s->sync_buffer)); } /* decode the header of the first sub-packet to find out the sample count */ @@ -458,17 +458,17 @@ return ret; frame->nb_samples = 0; - memset(c->out, 0, c->nb_streams * 2 * sizeof(*c->out)); for (i = 0; i < avctx->channels; i++) { ChannelMap *map = &c->channel_maps[i]; if (!map->copy) - c->out[2 * map->stream_idx + map->channel_idx] = (float*)frame->extended_data[i]; + c->streams[map->stream_idx].out[map->channel_idx] = (float*)frame->extended_data[i]; } /* read the data from the sync buffers */ for (i = 0; i < c->nb_streams; i++) { - float **out = c->out + 2 * i; - int sync_size = av_audio_fifo_size(c->sync_buffers[i]); + OpusStreamContext *s = &c->streams[i]; + float **out = s->out; + int sync_size = av_audio_fifo_size(s->sync_buffer); float sync_dummy[32]; int out_dummy = (!out[0]) | ((!out[1]) << 1); @@ -480,7 +480,7 @@ if (out_dummy && sync_size > FF_ARRAY_ELEMS(sync_dummy)) return AVERROR_BUG; - ret = av_audio_fifo_read(c->sync_buffers[i], (void**)out, sync_size); + ret = av_audio_fifo_read(s->sync_buffer, (void**)out, sync_size); if (ret < 0) return ret; @@ -493,7 +493,7 @@ else out[1] += ret; - c->out_size[i] = frame->linesize[0] - ret * sizeof(float); + s->out_size = frame->linesize[0] - ret * sizeof(float); } /* decode each sub-packet */ @@ -516,10 +516,10 @@ } ret = opus_decode_subpacket(&c->streams[i], buf, s->packet.data_size, - c->out + 2 * i, c->out_size[i], coded_samples); + coded_samples); if (ret < 0) return ret; - c->decoded_samples[i] = ret; + s->decoded_samples = ret; decoded_samples = FFMIN(decoded_samples, ret); buf += s->packet.packet_size; @@ -528,13 +528,14 @@ /* buffer the extra samples */ for (i = 0; i < c->nb_streams; i++) { - int buffer_samples = c->decoded_samples[i] - decoded_samples; + OpusStreamContext *s = &c->streams[i]; + int buffer_samples = s->decoded_samples - decoded_samples; if (buffer_samples) { - float *buf[2] = { c->out[2 * i + 0] ? c->out[2 * i + 0] : (float*)frame->extended_data[0], - c->out[2 * i + 1] ? c->out[2 * i + 1] : (float*)frame->extended_data[0] }; + float *buf[2] = { s->out[0] ? s->out[0] : (float*)frame->extended_data[0], + s->out[1] ? s->out[1] : (float*)frame->extended_data[0] }; buf[0] += decoded_samples; buf[1] += decoded_samples; - ret = av_audio_fifo_write(c->sync_buffers[i], (void**)buf, buffer_samples); + ret = av_audio_fifo_write(s->sync_buffer, (void**)buf, buffer_samples); if (ret < 0) return ret; } @@ -576,11 +577,10 @@ memset(&s->packet, 0, sizeof(s->packet)); s->delayed_samples = 0; - if (s->celt_delay) - av_audio_fifo_drain(s->celt_delay, av_audio_fifo_size(s->celt_delay)); + av_audio_fifo_drain(s->celt_delay, av_audio_fifo_size(s->celt_delay)); swr_close(s->swr); - av_audio_fifo_drain(c->sync_buffers[i], av_audio_fifo_size(c->sync_buffers[i])); + av_audio_fifo_drain(s->sync_buffer, av_audio_fifo_size(s->sync_buffer)); ff_silk_flush(s->silk); ff_celt_flush(s->celt); @@ -601,21 +601,13 @@ av_freep(&s->out_dummy); s->out_dummy_allocated_size = 0; + av_audio_fifo_free(s->sync_buffer); av_audio_fifo_free(s->celt_delay); swr_free(&s->swr); } av_freep(&c->streams); - if (c->sync_buffers) { - for (i = 0; i < c->nb_streams; i++) - av_audio_fifo_free(c->sync_buffers[i]); - } - av_freep(&c->sync_buffers); - av_freep(&c->decoded_samples); - av_freep(&c->out); - av_freep(&c->out_size); - c->nb_streams = 0; av_freep(&c->channel_maps); @@ -638,21 +630,14 @@ /* find out the channel configuration */ ret = ff_opus_parse_extradata(avctx, c); - if (ret < 0) { - av_freep(&c->fdsp); + if (ret < 0) return ret; - } /* allocate and init each independent decoder */ c->streams = av_mallocz_array(c->nb_streams, sizeof(*c->streams)); - c->out = av_mallocz_array(c->nb_streams, 2 * sizeof(*c->out)); - c->out_size = av_mallocz_array(c->nb_streams, sizeof(*c->out_size)); - c->sync_buffers = av_mallocz_array(c->nb_streams, sizeof(*c->sync_buffers)); - c->decoded_samples = av_mallocz_array(c->nb_streams, sizeof(*c->decoded_samples)); - if (!c->streams || !c->sync_buffers || !c->decoded_samples || !c->out || !c->out_size) { + if (!c->streams) { c->nb_streams = 0; - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } for (i = 0; i < c->nb_streams; i++) { @@ -673,7 +658,7 @@ s->swr =swr_alloc(); if (!s->swr) - goto fail; + return AVERROR(ENOMEM); layout = (s->output_channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; av_opt_set_int(s->swr, "in_sample_fmt", avctx->sample_fmt, 0); @@ -685,31 +670,24 @@ ret = ff_silk_init(avctx, &s->silk, s->output_channels); if (ret < 0) - goto fail; + return ret; ret = ff_celt_init(avctx, &s->celt, s->output_channels, c->apply_phase_inv); if (ret < 0) - goto fail; + return ret; s->celt_delay = av_audio_fifo_alloc(avctx->sample_fmt, s->output_channels, 1024); - if (!s->celt_delay) { - ret = AVERROR(ENOMEM); - goto fail; - } + if (!s->celt_delay) + return AVERROR(ENOMEM); - c->sync_buffers[i] = av_audio_fifo_alloc(avctx->sample_fmt, - s->output_channels, 32); - if (!c->sync_buffers[i]) { - ret = AVERROR(ENOMEM); - goto fail; - } + s->sync_buffer = av_audio_fifo_alloc(avctx->sample_fmt, + s->output_channels, 32); + if (!s->sync_buffer) + return AVERROR(ENOMEM); } return 0; -fail: - opus_decode_close(avctx); - return ret; } #define OFFSET(x) offsetof(OpusContext, x) @@ -737,5 +715,6 @@ .close = opus_decode_close, .decode = opus_decode_packet, .flush = opus_decode_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/opusdsp.c ffmpeg-4.4/libavcodec/opusdsp.c --- ffmpeg-4.2.2/libavcodec/opusdsp.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opusdsp.c 2020-07-11 10:39:30.000000000 +0000 @@ -43,15 +43,10 @@ static float deemphasis_c(float *y, float *x, float coeff, int len) { - float state = coeff; + for (int i = 0; i < len; i++) + coeff = y[i] = x[i] + coeff*CELT_EMPH_COEFF; - for (int i = 0; i < len; i++) { - const float tmp = x[i] + state; - state = tmp * CELT_EMPH_COEFF; - y[i] = tmp; - } - - return state; + return coeff; } av_cold void ff_opus_dsp_init(OpusDSP *ctx) diff -Nru ffmpeg-4.2.2/libavcodec/opusenc.c ffmpeg-4.4/libavcodec/opusenc.c --- ffmpeg-4.2.2/libavcodec/opusenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opusenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,6 +25,7 @@ #include "opustab.h" #include "libavutil/float_dsp.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "internal.h" #include "bytestream.h" @@ -691,7 +692,7 @@ s->frame[i].avctx = s->avctx; s->frame[i].seed = 0; s->frame[i].pvq = s->pvq; - s->frame[i].apply_phase_inv = 1; + s->frame[i].apply_phase_inv = s->options.apply_phase_inv; s->frame[i].block[0].emph_coeff = s->frame[i].block[1].emph_coeff = 0.0f; } @@ -701,6 +702,7 @@ #define OPUSENC_FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM static const AVOption opusenc_options[] = { { "opus_delay", "Maximum delay in milliseconds", offsetof(OpusEncContext, options.max_delay_ms), AV_OPT_TYPE_FLOAT, { .dbl = OPUS_MAX_LOOKAHEAD }, 2.5f, OPUS_MAX_LOOKAHEAD, OPUSENC_FLAGS, "max_delay_ms" }, + { "apply_phase_inv", "Apply intensity stereo phase inversion", offsetof(OpusEncContext, options.apply_phase_inv), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, OPUSENC_FLAGS, "apply_phase_inv" }, { NULL }, }; diff -Nru ffmpeg-4.2.2/libavcodec/opusenc.h ffmpeg-4.4/libavcodec/opusenc.h --- ffmpeg-4.2.2/libavcodec/opusenc.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opusenc.h 2020-07-11 10:39:30.000000000 +0000 @@ -42,6 +42,7 @@ typedef struct OpusEncOptions { float max_delay_ms; + int apply_phase_inv; } OpusEncOptions; typedef struct OpusPacketInfo { diff -Nru ffmpeg-4.2.2/libavcodec/opusenc_psy.h ffmpeg-4.4/libavcodec/opusenc_psy.h --- ffmpeg-4.2.2/libavcodec/opusenc_psy.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opusenc_psy.h 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,8 @@ #ifndef AVCODEC_OPUSENC_PSY_H #define AVCODEC_OPUSENC_PSY_H +#include "libavutil/mem_internal.h" + #include "opusenc.h" #include "opusenc_utils.h" #include "libavfilter/window_func.h" diff -Nru ffmpeg-4.2.2/libavcodec/opus.h ffmpeg-4.4/libavcodec/opus.h --- ffmpeg-4.2.2/libavcodec/opus.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opus.h 2021-04-08 21:28:39.000000000 +0000 @@ -28,6 +28,7 @@ #include "libavutil/audio_fifo.h" #include "libavutil/float_dsp.h" #include "libavutil/frame.h" +#include "libavutil/mem_internal.h" #include "libswresample/swresample.h" @@ -101,6 +102,15 @@ AVCodecContext *avctx; int output_channels; + /* number of decoded samples for this stream */ + int decoded_samples; + /* current output buffers for this stream */ + float *out[2]; + int out_size; + /* Buffer with samples from this stream for synchronizing + * the streams when they have different resampling delays */ + AVAudioFifo *sync_buffer; + OpusRangeCoder rc; OpusRangeCoder redundancy_rc; SilkContext *silk; @@ -115,9 +125,9 @@ DECLARE_ALIGNED(32, float, redundancy_buf)[2][960]; float *redundancy_output[2]; - /* data buffers for the final output data */ - float *out[2]; - int out_size; + /* buffers for the next samples to be decoded */ + float *cur_out[2]; + int remaining_out_size; float *out_dummy; int out_dummy_allocated_size; @@ -154,15 +164,6 @@ OpusStreamContext *streams; int apply_phase_inv; - /* current output buffers for each streams */ - float **out; - int *out_size; - /* Buffers for synchronizing the streams when they have different - * resampling delays */ - AVAudioFifo **sync_buffers; - /* number of decoded samples for each stream */ - int *decoded_samples; - int nb_streams; int nb_stereo_streams; diff -Nru ffmpeg-4.2.2/libavcodec/opus_metadata_bsf.c ffmpeg-4.4/libavcodec/opus_metadata_bsf.c --- ffmpeg-4.2.2/libavcodec/opus_metadata_bsf.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opus_metadata_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,67 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "bsf_internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" + +typedef struct OpusBSFContext { + const AVClass *class; + int gain; +} OpusBSFContext; + +static int opus_metadata_init(AVBSFContext *bsfc) +{ + OpusBSFContext *s = bsfc->priv_data; + + if (bsfc->par_out->extradata_size < 19) + return AVERROR_INVALIDDATA; + + AV_WL16(bsfc->par_out->extradata + 16, s->gain); + + return 0; +} + +#define OFFSET(x) offsetof(OpusBSFContext, x) +#define FLAGS (AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_BSF_PARAM) +static const AVOption opus_metadata_options[] = { + { "gain", "Gain, actual amplification is pow(10, gain/(20.0*256))", OFFSET(gain), + AV_OPT_TYPE_INT, { .i64 = 0 }, -(INT16_MAX + 1), INT16_MAX, .flags = FLAGS }, + + { NULL }, +}; + +static const AVClass opus_metadata_class = { + .class_name = "opus_metadata_bsf", + .item_name = av_default_item_name, + .option = opus_metadata_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_OPUS, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_opus_metadata_bsf = { + .name = "opus_metadata", + .priv_data_size = sizeof(OpusBSFContext), + .priv_class = &opus_metadata_class, + .init = &opus_metadata_init, + .filter = &ff_bsf_get_packet_ref, + .codec_ids = codec_ids, +}; diff -Nru ffmpeg-4.2.2/libavcodec/opus_pvq.c ffmpeg-4.4/libavcodec/opus_pvq.c --- ffmpeg-4.2.2/libavcodec/opus_pvq.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opus_pvq.c 2020-07-11 10:39:30.000000000 +0000 @@ -627,7 +627,7 @@ } } else if (stereo) { if (quant) { - inv = itheta > 8192; + inv = f->apply_phase_inv ? itheta > 8192 : 0; if (inv) { for (i = 0; i < N; i++) Y[i] *= -1; diff -Nru ffmpeg-4.2.2/libavcodec/opus_pvq.h ffmpeg-4.4/libavcodec/opus_pvq.h --- ffmpeg-4.2.2/libavcodec/opus_pvq.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opus_pvq.h 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,8 @@ #ifndef AVCODEC_OPUS_PVQ_H #define AVCODEC_OPUS_PVQ_H +#include "libavutil/mem_internal.h" + #include "opus_celt.h" #define QUANT_FN(name) uint32_t (name)(struct CeltPVQ *pvq, CeltFrame *f, \ diff -Nru ffmpeg-4.2.2/libavcodec/opus_silk.c ffmpeg-4.4/libavcodec/opus_silk.c --- ffmpeg-4.2.2/libavcodec/opus_silk.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opus_silk.c 2021-02-20 20:27:47.000000000 +0000 @@ -506,7 +506,8 @@ #define LTP_ORDER 5 static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc, - int frame_num, int channel, int coded_channels, int active, int active1) + int frame_num, int channel, int coded_channels, + int active, int active1, int redundant) { /* per frame */ int voiced; // combines with active to indicate inactive, active, or active+voiced @@ -665,8 +666,9 @@ silk_decode_excitation(s, rc, residual + SILK_MAX_LAG, qoffset_high, active, voiced); - /* skip synthesising the side channel if we want mono-only */ - if (s->output_channels == channel) + /* skip synthesising the output if we do not need it */ + // TODO: implement error recovery + if (s->output_channels == channel || redundant) return; /* generate the output signal */ @@ -814,15 +816,27 @@ active[i][j] = ff_opus_rc_dec_log(rc, 1); redundancy[i] = ff_opus_rc_dec_log(rc, 1); - if (redundancy[i]) { - avpriv_report_missing_feature(s->avctx, "LBRR frames"); - return AVERROR_PATCHWELCOME; + } + + /* read the per-frame LBRR flags */ + for (i = 0; i < coded_channels; i++) + if (redundancy[i] && duration_ms > 20) { + redundancy[i] = ff_opus_rc_dec_cdf(rc, duration_ms == 40 ? + ff_silk_model_lbrr_flags_40 : ff_silk_model_lbrr_flags_60); } + + /* decode the LBRR frames */ + for (i = 0; i < nb_frames; i++) { + for (j = 0; j < coded_channels; j++) + if (redundancy[j] & (1 << i)) { + int active1 = (j == 0 && !(redundancy[1] & (1 << i))) ? 0 : 1; + silk_decode_frame(s, rc, i, j, coded_channels, 1, active1, 1); + } } for (i = 0; i < nb_frames; i++) { for (j = 0; j < coded_channels && !s->midonly; j++) - silk_decode_frame(s, rc, i, j, coded_channels, active[j][i], active[1][i]); + silk_decode_frame(s, rc, i, j, coded_channels, active[j][i], active[1][i], 0); /* reset the side channel if it is not coded */ if (s->midonly && s->frame[1].coded) diff -Nru ffmpeg-4.2.2/libavcodec/opustab.c ffmpeg-4.4/libavcodec/opustab.c --- ffmpeg-4.2.2/libavcodec/opustab.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opustab.c 2021-04-08 21:28:39.000000000 +0000 @@ -20,12 +20,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mem_internal.h" + #include "opustab.h" const uint8_t ff_opus_default_coupled_streams[] = { 0, 1, 1, 2, 2, 2, 2, 3 }; const uint8_t ff_celt_band_end[] = { 13, 17, 17, 19, 21 }; +const uint16_t ff_silk_model_lbrr_flags_40[] = { 256, 0, 53, 106, 256 }; +const uint16_t ff_silk_model_lbrr_flags_60[] = { 256, 0, 41, 61, 90, 131, 146, 174, 256 }; + const uint16_t ff_silk_model_stereo_s1[] = { 256, 7, 9, 10, 11, 12, 22, 46, 54, 55, 56, 59, 82, 174, 197, 200, 201, 202, 210, 234, 244, 245, 246, 247, 249, 256 @@ -947,7 +952,7 @@ 16384, 17866, 19483, 21247, 23170, 25267, 27554, 30048 }; -const uint32_t ff_celt_pvq_u[1272] = { +static const uint32_t celt_pvq_u[1272] = { /* N = 0, K = 0...176 */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1127,7 +1132,7 @@ 1.00000000f, 1.00000000f, 1.00000000f, }; -const float *ff_celt_window = &ff_celt_window_padded[8]; +const float *const ff_celt_window = &ff_celt_window_padded[8]; /* square of the window, used for the postfilter */ const float ff_celt_window2[120] = { @@ -1150,9 +1155,9 @@ }; const uint32_t * const ff_celt_pvq_u_row[15] = { - ff_celt_pvq_u + 0, ff_celt_pvq_u + 176, ff_celt_pvq_u + 351, - ff_celt_pvq_u + 525, ff_celt_pvq_u + 698, ff_celt_pvq_u + 870, - ff_celt_pvq_u + 1041, ff_celt_pvq_u + 1131, ff_celt_pvq_u + 1178, - ff_celt_pvq_u + 1207, ff_celt_pvq_u + 1226, ff_celt_pvq_u + 1240, - ff_celt_pvq_u + 1248, ff_celt_pvq_u + 1254, ff_celt_pvq_u + 1257 + celt_pvq_u + 0, celt_pvq_u + 176, celt_pvq_u + 351, + celt_pvq_u + 525, celt_pvq_u + 698, celt_pvq_u + 870, + celt_pvq_u + 1041, celt_pvq_u + 1131, celt_pvq_u + 1178, + celt_pvq_u + 1207, celt_pvq_u + 1226, celt_pvq_u + 1240, + celt_pvq_u + 1248, celt_pvq_u + 1254, celt_pvq_u + 1257 }; diff -Nru ffmpeg-4.2.2/libavcodec/opustab.h ffmpeg-4.4/libavcodec/opustab.h --- ffmpeg-4.2.2/libavcodec/opustab.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/opustab.h 2021-04-08 21:28:39.000000000 +0000 @@ -31,6 +31,9 @@ extern const uint8_t ff_opus_default_coupled_streams[]; +extern const uint16_t ff_silk_model_lbrr_flags_40[]; +extern const uint16_t ff_silk_model_lbrr_flags_60[]; + extern const uint16_t ff_silk_model_stereo_s1[]; extern const uint16_t ff_silk_model_stereo_s2[]; extern const uint16_t ff_silk_model_stereo_s3[]; @@ -149,12 +152,11 @@ extern const uint8_t ff_celt_hadamard_order[]; extern const uint16_t ff_celt_qn_exp2[]; -extern const uint32_t ff_celt_pvq_u[1272]; extern const float ff_celt_postfilter_taps[3][3]; extern const float ff_celt_window2[120]; -extern const float *ff_celt_window; +extern const float *const ff_celt_window; extern const uint32_t * const ff_celt_pvq_u_row[15]; diff -Nru ffmpeg-4.2.2/libavcodec/packet.h ffmpeg-4.4/libavcodec/packet.h --- ffmpeg-4.2.2/libavcodec/packet.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/packet.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,774 @@ +/* + * AVPacket public API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_PACKET_H +#define AVCODEC_PACKET_H + +#include +#include + +#include "libavutil/attributes.h" +#include "libavutil/buffer.h" +#include "libavutil/dict.h" +#include "libavutil/rational.h" + +#include "libavcodec/version.h" + +/** + * @defgroup lavc_packet AVPacket + * + * Types and functions for working with AVPacket. + * @{ + */ +enum AVPacketSideDataType { + /** + * An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE + * bytes worth of palette. This side data signals that a new palette is + * present. + */ + AV_PKT_DATA_PALETTE, + + /** + * The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format + * that the extradata buffer was changed and the receiving side should + * act upon it appropriately. The new extradata is embedded in the side + * data buffer and should be immediately used for processing the current + * frame or packet. + */ + AV_PKT_DATA_NEW_EXTRADATA, + + /** + * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows: + * @code + * u32le param_flags + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) + * s32le channel_count + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) + * u64le channel_layout + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) + * s32le sample_rate + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) + * s32le width + * s32le height + * @endcode + */ + AV_PKT_DATA_PARAM_CHANGE, + + /** + * An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of + * structures with info about macroblocks relevant to splitting the + * packet into smaller packets on macroblock edges (e.g. as for RFC 2190). + * That is, it does not necessarily contain info about all macroblocks, + * as long as the distance between macroblocks in the info is smaller + * than the target payload size. + * Each MB info structure is 12 bytes, and is laid out as follows: + * @code + * u32le bit offset from the start of the packet + * u8 current quantizer at the start of the macroblock + * u8 GOB number + * u16le macroblock address within the GOB + * u8 horizontal MV predictor + * u8 vertical MV predictor + * u8 horizontal MV predictor for block number 3 + * u8 vertical MV predictor for block number 3 + * @endcode + */ + AV_PKT_DATA_H263_MB_INFO, + + /** + * This side data should be associated with an audio stream and contains + * ReplayGain information in form of the AVReplayGain struct. + */ + AV_PKT_DATA_REPLAYGAIN, + + /** + * This side data contains a 3x3 transformation matrix describing an affine + * transformation that needs to be applied to the decoded video frames for + * correct presentation. + * + * See libavutil/display.h for a detailed description of the data. + */ + AV_PKT_DATA_DISPLAYMATRIX, + + /** + * This side data should be associated with a video stream and contains + * Stereoscopic 3D information in form of the AVStereo3D struct. + */ + AV_PKT_DATA_STEREO3D, + + /** + * This side data should be associated with an audio stream and corresponds + * to enum AVAudioServiceType. + */ + AV_PKT_DATA_AUDIO_SERVICE_TYPE, + + /** + * This side data contains quality related information from the encoder. + * @code + * u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad). + * u8 picture type + * u8 error count + * u16 reserved + * u64le[error count] sum of squared differences between encoder in and output + * @endcode + */ + AV_PKT_DATA_QUALITY_STATS, + + /** + * This side data contains an integer value representing the stream index + * of a "fallback" track. A fallback track indicates an alternate + * track to use when the current track can not be decoded for some reason. + * e.g. no decoder available for codec. + */ + AV_PKT_DATA_FALLBACK_TRACK, + + /** + * This side data corresponds to the AVCPBProperties struct. + */ + AV_PKT_DATA_CPB_PROPERTIES, + + /** + * Recommmends skipping the specified number of samples + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_PKT_DATA_SKIP_SAMPLES, + + /** + * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that + * the packet may contain "dual mono" audio specific to Japanese DTV + * and if it is true, recommends only the selected channel to be used. + * @code + * u8 selected channels (0=mail/left, 1=sub/right, 2=both) + * @endcode + */ + AV_PKT_DATA_JP_DUALMONO, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. + */ + AV_PKT_DATA_STRINGS_METADATA, + + /** + * Subtitle event position + * @code + * u32le x1 + * u32le y1 + * u32le x2 + * u32le y2 + * @endcode + */ + AV_PKT_DATA_SUBTITLE_POSITION, + + /** + * Data found in BlockAdditional element of matroska container. There is + * no end marker for the data, so it is required to rely on the side data + * size to recognize the end. 8 byte id (as found in BlockAddId) followed + * by data. + */ + AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + + /** + * The optional first identifier line of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_IDENTIFIER, + + /** + * The optional settings (rendering instructions) that immediately + * follow the timestamp specifier of a WebVTT cue. + */ + AV_PKT_DATA_WEBVTT_SETTINGS, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. This + * side data includes updated metadata which appeared in the stream. + */ + AV_PKT_DATA_METADATA_UPDATE, + + /** + * MPEGTS stream ID as uint8_t, this is required to pass the stream ID + * information from the demuxer to the corresponding muxer. + */ + AV_PKT_DATA_MPEGTS_STREAM_ID, + + /** + * Mastering display metadata (based on SMPTE-2086:2014). This metadata + * should be associated with a video stream and contains data in the form + * of the AVMasteringDisplayMetadata struct. + */ + AV_PKT_DATA_MASTERING_DISPLAY_METADATA, + + /** + * This side data should be associated with a video stream and corresponds + * to the AVSphericalMapping structure. + */ + AV_PKT_DATA_SPHERICAL, + + /** + * Content light level (based on CTA-861.3). This metadata should be + * associated with a video stream and contains data in the form of the + * AVContentLightMetadata struct. + */ + AV_PKT_DATA_CONTENT_LIGHT_LEVEL, + + /** + * ATSC A53 Part 4 Closed Captions. This metadata should be associated with + * a video stream. A53 CC bitstream is stored as uint8_t in AVPacketSideData.data. + * The number of bytes of CC data is AVPacketSideData.size. + */ + AV_PKT_DATA_A53_CC, + + /** + * This side data is encryption initialization data. + * The format is not part of ABI, use av_encryption_init_info_* methods to + * access. + */ + AV_PKT_DATA_ENCRYPTION_INIT_INFO, + + /** + * This side data contains encryption info for how to decrypt the packet. + * The format is not part of ABI, use av_encryption_info_* methods to access. + */ + AV_PKT_DATA_ENCRYPTION_INFO, + + /** + * Active Format Description data consisting of a single byte as specified + * in ETSI TS 101 154 using AVActiveFormatDescription enum. + */ + AV_PKT_DATA_AFD, + + /** + * Producer Reference Time data corresponding to the AVProducerReferenceTime struct, + * usually exported by some encoders (on demand through the prft flag set in the + * AVCodecContext export_side_data field). + */ + AV_PKT_DATA_PRFT, + + /** + * ICC profile data consisting of an opaque octet buffer following the + * format described by ISO 15076-1. + */ + AV_PKT_DATA_ICC_PROFILE, + + /** + * DOVI configuration + * ref: + * dolby-vision-bitstreams-within-the-iso-base-media-file-format-v2.1.2, section 2.2 + * dolby-vision-bitstreams-in-mpeg-2-transport-stream-multiplex-v1.2, section 3.3 + * Tags are stored in struct AVDOVIDecoderConfigurationRecord. + */ + AV_PKT_DATA_DOVI_CONF, + + /** + * Timecode which conforms to SMPTE ST 12-1:2014. The data is an array of 4 uint32_t + * where the first uint32_t describes how many (1-3) of the other timecodes are used. + * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.h. + */ + AV_PKT_DATA_S12M_TIMECODE, + + /** + * The number of side data types. + * This is not part of the public API/ABI in the sense that it may + * change when new side data types are added. + * This must stay the last enum value. + * If its value becomes huge, some code using it + * needs to be updated as it assumes it to be smaller than other limits. + */ + AV_PKT_DATA_NB +}; + +#define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED + +typedef struct AVPacketSideData { + uint8_t *data; +#if FF_API_BUFFER_SIZE_T + int size; +#else + size_t size; +#endif + enum AVPacketSideDataType type; +} AVPacketSideData; + +/** + * This structure stores compressed data. It is typically exported by demuxers + * and then passed as input to decoders, or received as output from encoders and + * then passed to muxers. + * + * For video, it should typically contain one compressed frame. For audio it may + * contain several compressed frames. Encoders are allowed to output empty + * packets, with no compressed data, containing only side data + * (e.g. to update some stream parameters at the end of encoding). + * + * The semantics of data ownership depends on the buf field. + * If it is set, the packet data is dynamically allocated and is + * valid indefinitely until a call to av_packet_unref() reduces the + * reference count to 0. + * + * If the buf field is not set av_packet_ref() would make a copy instead + * of increasing the reference count. + * + * The side data is always allocated with av_malloc(), copied by + * av_packet_ref() and freed by av_packet_unref(). + * + * sizeof(AVPacket) being a part of the public ABI is deprecated. once + * av_init_packet() is removed, new packets will only be able to be allocated + * with av_packet_alloc(), and new fields may be added to the end of the struct + * with a minor bump. + * + * @see av_packet_alloc + * @see av_packet_ref + * @see av_packet_unref + */ +typedef struct AVPacket { + /** + * A reference to the reference-counted buffer where the packet data is + * stored. + * May be NULL, then the packet data is not reference-counted. + */ + AVBufferRef *buf; + /** + * Presentation timestamp in AVStream->time_base units; the time at which + * the decompressed packet will be presented to the user. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + * pts MUST be larger or equal to dts as presentation cannot happen before + * decompression, unless one wants to view hex dumps. Some formats misuse + * the terms dts and pts/cts to mean something different. Such timestamps + * must be converted to true pts/dts before they are stored in AVPacket. + */ + int64_t pts; + /** + * Decompression timestamp in AVStream->time_base units; the time at which + * the packet is decompressed. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + */ + int64_t dts; + uint8_t *data; + int size; + int stream_index; + /** + * A combination of AV_PKT_FLAG values + */ + int flags; + /** + * Additional packet data that can be provided by the container. + * Packet can contain several types of side information. + */ + AVPacketSideData *side_data; + int side_data_elems; + + /** + * Duration of this packet in AVStream->time_base units, 0 if unknown. + * Equals next_pts - this_pts in presentation order. + */ + int64_t duration; + + int64_t pos; ///< byte position in stream, -1 if unknown + +#if FF_API_CONVERGENCE_DURATION + /** + * @deprecated Same as the duration field, but as int64_t. This was required + * for Matroska subtitles, whose duration values could overflow when the + * duration field was still an int. + */ + attribute_deprecated + int64_t convergence_duration; +#endif +} AVPacket; + +#if FF_API_INIT_PACKET +attribute_deprecated +typedef struct AVPacketList { + AVPacket pkt; + struct AVPacketList *next; +} AVPacketList; +#endif + +#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe +#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted +/** + * Flag is used to discard packets which are required to maintain valid + * decoder state but are not required for output and should be dropped + * after decoding. + **/ +#define AV_PKT_FLAG_DISCARD 0x0004 +/** + * The packet comes from a trusted source. + * + * Otherwise-unsafe constructs such as arbitrary pointers to data + * outside the packet may be followed. + */ +#define AV_PKT_FLAG_TRUSTED 0x0008 +/** + * Flag is used to indicate packets that contain frames that can + * be discarded by the decoder. I.e. Non-reference frames. + */ +#define AV_PKT_FLAG_DISPOSABLE 0x0010 + +enum AVSideDataParamChangeFlags { + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002, + AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004, + AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008, +}; + +/** + * Allocate an AVPacket and set its fields to default values. The resulting + * struct must be freed using av_packet_free(). + * + * @return An AVPacket filled with default values or NULL on failure. + * + * @note this only allocates the AVPacket itself, not the data buffers. Those + * must be allocated through other means such as av_new_packet. + * + * @see av_new_packet + */ +AVPacket *av_packet_alloc(void); + +/** + * Create a new packet that references the same data as src. + * + * This is a shortcut for av_packet_alloc()+av_packet_ref(). + * + * @return newly created AVPacket on success, NULL on error. + * + * @see av_packet_alloc + * @see av_packet_ref + */ +AVPacket *av_packet_clone(const AVPacket *src); + +/** + * Free the packet, if the packet is reference counted, it will be + * unreferenced first. + * + * @param pkt packet to be freed. The pointer will be set to NULL. + * @note passing NULL is a no-op. + */ +void av_packet_free(AVPacket **pkt); + +#if FF_API_INIT_PACKET +/** + * Initialize optional fields of a packet with default values. + * + * Note, this does not touch the data and size members, which have to be + * initialized separately. + * + * @param pkt packet + * + * @see av_packet_alloc + * @see av_packet_unref + * + * @deprecated This function is deprecated. Once it's removed, + sizeof(AVPacket) will not be a part of the ABI anymore. + */ +attribute_deprecated +void av_init_packet(AVPacket *pkt); +#endif + +/** + * Allocate the payload of a packet and initialize its fields with + * default values. + * + * @param pkt packet + * @param size wanted payload size + * @return 0 if OK, AVERROR_xxx otherwise + */ +int av_new_packet(AVPacket *pkt, int size); + +/** + * Reduce packet size, correctly zeroing padding + * + * @param pkt packet + * @param size new size + */ +void av_shrink_packet(AVPacket *pkt, int size); + +/** + * Increase packet size, correctly zeroing padding + * + * @param pkt packet + * @param grow_by number of bytes by which to increase the size of the packet + */ +int av_grow_packet(AVPacket *pkt, int grow_by); + +/** + * Initialize a reference-counted packet from av_malloc()ed data. + * + * @param pkt packet to be initialized. This function will set the data, size, + * and buf fields, all others are left untouched. + * @param data Data allocated by av_malloc() to be used as packet data. If this + * function returns successfully, the data is owned by the underlying AVBuffer. + * The caller may not access the data through other means. + * @param size size of data in bytes, without the padding. I.e. the full buffer + * size is assumed to be size + AV_INPUT_BUFFER_PADDING_SIZE. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size); + +#if FF_API_AVPACKET_OLD_API +/** + * @warning This is a hack - the packet memory allocation stuff is broken. The + * packet is allocated if it was not really allocated. + * + * @deprecated Use av_packet_ref or av_packet_make_refcounted + */ +attribute_deprecated +int av_dup_packet(AVPacket *pkt); +/** + * Copy packet, including contents + * + * @return 0 on success, negative AVERROR on fail + * + * @deprecated Use av_packet_ref + */ +attribute_deprecated +int av_copy_packet(AVPacket *dst, const AVPacket *src); + +/** + * Copy packet side data + * + * @return 0 on success, negative AVERROR on fail + * + * @deprecated Use av_packet_copy_props + */ +attribute_deprecated +int av_copy_packet_side_data(AVPacket *dst, const AVPacket *src); + +/** + * Free a packet. + * + * @deprecated Use av_packet_unref + * + * @param pkt packet to free + */ +attribute_deprecated +void av_free_packet(AVPacket *pkt); +#endif +/** + * Allocate new information of a packet. + * + * @param pkt packet + * @param type side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, +#if FF_API_BUFFER_SIZE_T + int size); +#else + size_t size); +#endif + +/** + * Wrap an existing array as a packet side data. + * + * @param pkt packet + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * pkt. + * @param size side information size + * @return a non-negative number on success, a negative AVERROR code on + * failure. On failure, the packet is unchanged and the data remains + * owned by the caller. + */ +int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + +/** + * Shrink the already allocated side data buffer + * + * @param pkt packet + * @param type side information type + * @param size new side information size + * @return 0 on success, < 0 on failure + */ +int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, +#if FF_API_BUFFER_SIZE_T + int size); +#else + size_t size); +#endif + +/** + * Get side information from packet. + * + * @param pkt packet + * @param type desired side information type + * @param size If supplied, *size will be set to the size of the side data + * or to zero if the desired side data is not present. + * @return pointer to data if present or NULL otherwise + */ +uint8_t* av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, +#if FF_API_BUFFER_SIZE_T + int *size); +#else + size_t *size); +#endif + +#if FF_API_MERGE_SD_API +attribute_deprecated +int av_packet_merge_side_data(AVPacket *pkt); + +attribute_deprecated +int av_packet_split_side_data(AVPacket *pkt); +#endif + +const char *av_packet_side_data_name(enum AVPacketSideDataType type); + +/** + * Pack a dictionary for use in side_data. + * + * @param dict The dictionary to pack. + * @param size pointer to store the size of the returned data + * @return pointer to data if successful, NULL otherwise + */ +#if FF_API_BUFFER_SIZE_T +uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size); +#else +uint8_t *av_packet_pack_dictionary(AVDictionary *dict, size_t *size); +#endif +/** + * Unpack a dictionary from side_data. + * + * @param data data from side_data + * @param size size of the data + * @param dict the metadata storage dictionary + * @return 0 on success, < 0 on failure + */ +#if FF_API_BUFFER_SIZE_T +int av_packet_unpack_dictionary(const uint8_t *data, int size, AVDictionary **dict); +#else +int av_packet_unpack_dictionary(const uint8_t *data, size_t size, + AVDictionary **dict); +#endif + +/** + * Convenience function to free all the side data stored. + * All the other fields stay untouched. + * + * @param pkt packet + */ +void av_packet_free_side_data(AVPacket *pkt); + +/** + * Setup a new reference to the data described by a given packet + * + * If src is reference-counted, setup dst as a new reference to the + * buffer in src. Otherwise allocate a new buffer in dst and copy the + * data from src into it. + * + * All the other fields are copied from src. + * + * @see av_packet_unref + * + * @param dst Destination packet. Will be completely overwritten. + * @param src Source packet + * + * @return 0 on success, a negative AVERROR on error. On error, dst + * will be blank (as if returned by av_packet_alloc()). + */ +int av_packet_ref(AVPacket *dst, const AVPacket *src); + +/** + * Wipe the packet. + * + * Unreference the buffer referenced by the packet and reset the + * remaining packet fields to their default values. + * + * @param pkt The packet to be unreferenced. + */ +void av_packet_unref(AVPacket *pkt); + +/** + * Move every field in src to dst and reset src. + * + * @see av_packet_unref + * + * @param src Source packet, will be reset + * @param dst Destination packet + */ +void av_packet_move_ref(AVPacket *dst, AVPacket *src); + +/** + * Copy only "properties" fields from src to dst. + * + * Properties for the purpose of this function are all the fields + * beside those related to the packet data (buf, data, size) + * + * @param dst Destination packet + * @param src Source packet + * + * @return 0 on success AVERROR on failure. + */ +int av_packet_copy_props(AVPacket *dst, const AVPacket *src); + +/** + * Ensure the data described by a given packet is reference counted. + * + * @note This function does not ensure that the reference will be writable. + * Use av_packet_make_writable instead for that purpose. + * + * @see av_packet_ref + * @see av_packet_make_writable + * + * @param pkt packet whose data should be made reference counted. + * + * @return 0 on success, a negative AVERROR on error. On failure, the + * packet is unchanged. + */ +int av_packet_make_refcounted(AVPacket *pkt); + +/** + * Create a writable reference for the data described by a given packet, + * avoiding data copy if possible. + * + * @param pkt Packet whose data should be made writable. + * + * @return 0 on success, a negative AVERROR on failure. On failure, the + * packet is unchanged. + */ +int av_packet_make_writable(AVPacket *pkt); + +/** + * Convert valid timing fields (timestamps / durations) in a packet from one + * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be + * ignored. + * + * @param pkt packet on which the conversion will be performed + * @param tb_src source timebase, in which the timing fields in pkt are + * expressed + * @param tb_dst destination timebase, to which the timing fields will be + * converted + */ +void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst); + +/** + * @} + */ + +#endif // AVCODEC_PACKET_H diff -Nru ffmpeg-4.2.2/libavcodec/packet_internal.h ffmpeg-4.4/libavcodec/packet_internal.h --- ffmpeg-4.2.2/libavcodec/packet_internal.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/packet_internal.h 2021-04-08 21:28:39.000000000 +0000 @@ -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 + */ + +#ifndef AVCODEC_PACKET_INTERNAL_H +#define AVCODEC_PACKET_INTERNAL_H + +#include + +#include "packet.h" + +typedef struct PacketList { + AVPacket pkt; + struct PacketList *next; +} PacketList; + +/** + * Append an AVPacket to the list. + * + * @param head List head element + * @param tail List tail element + * @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. + May be null, in which case the packet's reference will be + moved to the list. + * @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 (*copy)(AVPacket *dst, const AVPacket *src), + int flags); + +/** + * Remove the oldest AVPacket in the list and return it. + * + * @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 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); + +/** + * 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); + +int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type); + +int ff_side_data_set_prft(AVPacket *pkt, int64_t timestamp); + +#endif // AVCODEC_PACKET_INTERNAL_H diff -Nru ffmpeg-4.2.2/libavcodec/pafaudio.c ffmpeg-4.4/libavcodec/pafaudio.c --- ffmpeg-4.2.2/libavcodec/pafaudio.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pafaudio.c 2021-04-08 21:28:39.000000000 +0000 @@ -79,4 +79,5 @@ .init = paf_audio_init, .decode = paf_audio_decode, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/pafvideo.c ffmpeg-4.4/libavcodec/pafvideo.c --- ffmpeg-4.2.2/libavcodec/pafvideo.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pafvideo.c 2021-04-08 21:28:39.000000000 +0000 @@ -55,6 +55,7 @@ int current_frame; uint8_t *frame[4]; + int dirty[4]; int frame_size; int video_size; @@ -103,10 +104,8 @@ c->video_size = avctx->width * avctx->height; for (i = 0; i < 4; i++) { c->frame[i] = av_mallocz(c->frame_size); - if (!c->frame[i]) { - paf_video_close(avctx); + if (!c->frame[i]) return AVERROR(ENOMEM); - } } return 0; @@ -187,6 +186,7 @@ j = bytestream2_get_le16(&c->gb) + offset; if (bytestream2_get_bytes_left(&c->gb) < (j - offset) * 16) return AVERROR_INVALIDDATA; + c->dirty[page] = 1; do { offset++; if (dst + 3 * c->width + 4 > dend) @@ -289,7 +289,7 @@ c->video_size / 32 - (int64_t)bytestream2_get_bytes_left(&c->gb) > c->video_size / 32 * (int64_t)avctx->discard_damaged_percentage / 100) return AVERROR_INVALIDDATA; - if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) + if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) return ret; if (code & 0x20) { // frame is keyframe @@ -329,9 +329,13 @@ c->pic->palette_has_changed = 1; } + c->dirty[c->current_frame] = 1; if (code & 0x20) - for (i = 0; i < 4; i++) - memset(c->frame[i], 0, c->frame_size); + for (i = 0; i < 4; i++) { + if (c->dirty[i]) + memset(c->frame[i], 0, c->frame_size); + c->dirty[i] = 0; + } switch (code & 0x0F) { case 0: @@ -413,4 +417,5 @@ .close = paf_video_close, .decode = paf_video_decode, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/parser.c ffmpeg-4.4/libavcodec/parser.c --- ffmpeg-4.2.2/libavcodec/parser.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -179,6 +179,9 @@ /* offset of the next frame */ s->next_frame_offset = s->cur_offset + index; s->fetch_timestamp = 1; + } else { + /* Don't return a pointer to dummy_buf. */ + *poutbuf = NULL; } if (index < 0) index = 0; @@ -186,6 +189,7 @@ return index; } +#if FF_API_PARSER_CHANGE int av_parser_change(AVCodecParserContext *s, AVCodecContext *avctx, uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size, int keyframe) @@ -220,7 +224,7 @@ return 0; } - +#endif void av_parser_close(AVCodecParserContext *s) { if (s) { @@ -295,6 +299,10 @@ *buf = pc->buffer; } + if (next < -8) { + pc->overread += -8 - next; + next = -8; + } /* store overread bytes */ for (; next < 0; next++) { pc->state = pc->state << 8 | pc->buffer[pc->last_index + next]; diff -Nru ffmpeg-4.2.2/libavcodec/parsers.c ffmpeg-4.4/libavcodec/parsers.c --- ffmpeg-4.2.2/libavcodec/parsers.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/parsers.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,7 @@ #include "libavutil/thread.h" #include "avcodec.h" +#include "version.h" extern AVCodecParser ff_aac_parser; extern AVCodecParser ff_aac_latm_parser; @@ -28,12 +29,15 @@ extern AVCodecParser ff_adx_parser; extern AVCodecParser ff_av1_parser; extern AVCodecParser ff_avs2_parser; +extern AVCodecParser ff_avs3_parser; extern AVCodecParser ff_bmp_parser; extern AVCodecParser ff_cavsvideo_parser; extern AVCodecParser ff_cook_parser; +extern AVCodecParser ff_cri_parser; extern AVCodecParser ff_dca_parser; extern AVCodecParser ff_dirac_parser; extern AVCodecParser ff_dnxhd_parser; +extern AVCodecParser ff_dolby_e_parser; extern AVCodecParser ff_dpx_parser; extern AVCodecParser ff_dvaudio_parser; extern AVCodecParser ff_dvbsub_parser; @@ -48,6 +52,8 @@ extern AVCodecParser ff_h263_parser; extern AVCodecParser ff_h264_parser; extern AVCodecParser ff_hevc_parser; +extern AVCodecParser ff_ipu_parser; +extern AVCodecParser ff_jpeg2000_parser; extern AVCodecParser ff_mjpeg_parser; extern AVCodecParser ff_mlp_parser; extern AVCodecParser ff_mpeg4video_parser; @@ -66,10 +72,14 @@ extern AVCodecParser ff_vp3_parser; extern AVCodecParser ff_vp8_parser; extern AVCodecParser ff_vp9_parser; +extern AVCodecParser ff_webp_parser; +extern AVCodecParser ff_xbm_parser; extern AVCodecParser ff_xma_parser; #include "libavcodec/parser_list.c" +#if FF_API_NEXT +FF_DISABLE_DEPRECATION_WARNINGS static AVOnce av_parser_next_init = AV_ONCE_INIT; static void av_parser_init_next(void) @@ -93,6 +103,13 @@ return (AVCodecParser*)parser_list[0]; } +void av_register_codec_parser(AVCodecParser *parser) +{ + ff_thread_once(&av_parser_next_init, av_parser_init_next); +} +FF_ENABLE_DEPRECATION_WARNINGS +#endif + const AVCodecParser *av_parser_iterate(void **opaque) { uintptr_t i = (uintptr_t)*opaque; @@ -103,8 +120,3 @@ return p; } - -void av_register_codec_parser(AVCodecParser *parser) -{ - ff_thread_once(&av_parser_next_init, av_parser_init_next); -} diff -Nru ffmpeg-4.2.2/libavcodec/pcm-bluray.c ffmpeg-4.4/libavcodec/pcm-bluray.c --- ffmpeg-4.2.2/libavcodec/pcm-bluray.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pcm-bluray.c 2021-04-08 21:28:39.000000000 +0000 @@ -307,7 +307,7 @@ .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_PCM_BLURAY, .decode = pcm_bluray_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, diff -Nru ffmpeg-4.2.2/libavcodec/pcm.c ffmpeg-4.4/libavcodec/pcm.c --- ffmpeg-4.2.2/libavcodec/pcm.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pcm.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,8 +24,10 @@ * PCM codecs */ +#include "config.h" #include "libavutil/attributes.h" #include "libavutil/float_dsp.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "bytestream.h" #include "internal.h" @@ -35,19 +37,22 @@ static av_cold int pcm_encode_init(AVCodecContext *avctx) { avctx->frame_size = 0; +#if !CONFIG_HARDCODED_TABLES switch (avctx->codec->id) { - case AV_CODEC_ID_PCM_ALAW: - pcm_alaw_tableinit(); - break; - case AV_CODEC_ID_PCM_MULAW: - pcm_ulaw_tableinit(); - break; - case AV_CODEC_ID_PCM_VIDC: - pcm_vidc_tableinit(); - break; +#define INIT_ONCE(id, name) \ + case AV_CODEC_ID_PCM_ ## id: \ + if (CONFIG_PCM_ ## id ## _ENCODER) { \ + static AVOnce init_static_once = AV_ONCE_INIT; \ + ff_thread_once(&init_static_once, pcm_ ## name ## _tableinit); \ + } \ + break + INIT_ONCE(ALAW, alaw); + INIT_ONCE(MULAW, ulaw); + INIT_ONCE(VIDC, vidc); default: break; } +#endif avctx->bits_per_coded_sample = av_get_bits_per_sample(avctx->codec->id); avctx->block_align = avctx->channels * avctx->bits_per_coded_sample / 8; @@ -235,13 +240,15 @@ typedef struct PCMDecode { short table[256]; - AVFloatDSPContext *fdsp; + void (*vector_fmul_scalar)(float *dst, const float *src, float mul, + int len); float scale; } PCMDecode; static av_cold int pcm_decode_init(AVCodecContext *avctx) { PCMDecode *s = avctx->priv_data; + AVFloatDSPContext *fdsp; int i; if (avctx->channels <= 0) { @@ -268,9 +275,11 @@ return AVERROR_INVALIDDATA; s->scale = 1. / (1 << (avctx->bits_per_coded_sample - 1)); - s->fdsp = avpriv_float_dsp_alloc(0); - if (!s->fdsp) + fdsp = avpriv_float_dsp_alloc(0); + if (!fdsp) return AVERROR(ENOMEM); + s->vector_fmul_scalar = fdsp->vector_fmul_scalar; + av_free(fdsp); break; default: break; @@ -284,15 +293,6 @@ return 0; } -static av_cold int pcm_decode_close(AVCodecContext *avctx) -{ - PCMDecode *s = avctx->priv_data; - - av_freep(&s->fdsp); - - return 0; -} - /** * Read PCM samples macro * @param size Data size of native machine format @@ -303,23 +303,23 @@ * @param shift Bitshift (bits) * @param offset Sample value offset */ -#define DECODE(size, endian, src, dst, n, shift, offset) \ - for (; n > 0; n--) { \ - uint ## size ## _t v = bytestream_get_ ## endian(&src); \ - AV_WN ## size ## A(dst, (v - offset) << shift); \ - dst += size / 8; \ - } - -#define DECODE_PLANAR(size, endian, src, dst, n, shift, offset) \ - n /= avctx->channels; \ - for (c = 0; c < avctx->channels; c++) { \ - int i; \ - dst = frame->extended_data[c]; \ - for (i = n; i > 0; i--) { \ - uint ## size ## _t v = bytestream_get_ ## endian(&src); \ - AV_WN ## size ## A(dst, (v - offset) << shift); \ - dst += size / 8; \ - } \ +#define DECODE(size, endian, src, dst, n, shift, offset) \ + for (; n > 0; n--) { \ + uint ## size ## _t v = bytestream_get_ ## endian(&src); \ + AV_WN ## size ## A(dst, (uint ## size ## _t)(v - offset) << shift); \ + dst += size / 8; \ + } + +#define DECODE_PLANAR(size, endian, src, dst, n, shift, offset) \ + n /= avctx->channels; \ + for (c = 0; c < avctx->channels; c++) { \ + int i; \ + dst = frame->extended_data[c]; \ + for (i = n; i > 0; i--) { \ + uint ## size ## _t v = bytestream_get_ ## endian(&src); \ + AV_WN ## size ## A(dst, (uint ## size ##_t)(v - offset) << shift); \ + dst += size / 8; \ + } \ } static int pcm_decode_frame(AVCodecContext *avctx, void *data, @@ -419,6 +419,14 @@ for (; n > 0; n--) *samples++ = *src++ + 128; break; + case AV_CODEC_ID_PCM_SGA: + for (; n > 0; n--) { + int sign = *src >> 7; + int magn = *src & 0x7f; + *samples++ = sign ? 128 - magn : 128 + magn; + src++; + } + break; case AV_CODEC_ID_PCM_S8_PLANAR: n /= avctx->channels; for (c = 0; c < avctx->channels; c++) { @@ -491,14 +499,6 @@ bytestream_get_buffer(&src, samples, n * sample_size); } break; - case AV_CODEC_ID_PCM_ZORK: - for (; n > 0; n--) { - int v = *src++; - if (v < 128) - v = 128 - v; - *samples++ = v; - } - break; case AV_CODEC_ID_PCM_ALAW: case AV_CODEC_ID_PCM_MULAW: case AV_CODEC_ID_PCM_VIDC: @@ -515,13 +515,13 @@ dst_int32_t = (int32_t *)frame->extended_data[c]; for (i = 0; i < n; i++) { // extract low 20 bits and expand to 32 bits - *dst_int32_t++ = (src[2] << 28) | + *dst_int32_t++ = ((uint32_t)src[2]<<28) | (src[1] << 20) | (src[0] << 12) | ((src[2] & 0x0F) << 8) | src[1]; // extract high 20 bits and expand to 32 bits - *dst_int32_t++ = (src[4] << 24) | + *dst_int32_t++ = ((uint32_t)src[4]<<24) | (src[3] << 16) | ((src[2] & 0xF0) << 8) | (src[4] << 4) | @@ -537,9 +537,9 @@ if (avctx->codec_id == AV_CODEC_ID_PCM_F16LE || avctx->codec_id == AV_CODEC_ID_PCM_F24LE) { - s->fdsp->vector_fmul_scalar((float *)frame->extended_data[0], - (const float *)frame->extended_data[0], - s->scale, FFALIGN(frame->nb_samples * avctx->channels, 4)); + s->vector_fmul_scalar((float *)frame->extended_data[0], + (const float *)frame->extended_data[0], + s->scale, FFALIGN(frame->nb_samples * avctx->channels, 4)); emms_c(); } @@ -560,6 +560,7 @@ .capabilities = AV_CODEC_CAP_VARIABLE_FRAME_SIZE, \ .sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \ AV_SAMPLE_FMT_NONE }, \ + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \ } #define PCM_ENCODER_2(cf, id, sample_fmt, name, long_name) \ @@ -578,11 +579,11 @@ .id = AV_CODEC_ID_ ## id_, \ .priv_data_size = sizeof(PCMDecode), \ .init = pcm_decode_init, \ - .close = pcm_decode_close, \ .decode = pcm_decode_frame, \ .capabilities = AV_CODEC_CAP_DR1, \ .sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \ AV_SAMPLE_FMT_NONE }, \ + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \ } #define PCM_DECODER_2(cf, id, sample_fmt, name, long_name) \ @@ -626,7 +627,7 @@ PCM_CODEC (PCM_U24LE, AV_SAMPLE_FMT_S32, pcm_u24le, "PCM unsigned 24-bit little-endian"); PCM_CODEC (PCM_U32BE, AV_SAMPLE_FMT_S32, pcm_u32be, "PCM unsigned 32-bit big-endian"); PCM_CODEC (PCM_U32LE, AV_SAMPLE_FMT_S32, pcm_u32le, "PCM unsigned 32-bit little-endian"); -PCM_DECODER(PCM_ZORK, AV_SAMPLE_FMT_U8, pcm_zork, "PCM Zork"); PCM_CODEC (PCM_S64BE, AV_SAMPLE_FMT_S64, pcm_s64be, "PCM signed 64-bit big-endian"); PCM_CODEC (PCM_S64LE, AV_SAMPLE_FMT_S64, pcm_s64le, "PCM signed 64-bit little-endian"); PCM_CODEC (PCM_VIDC, AV_SAMPLE_FMT_S16, pcm_vidc, "PCM Archimedes VIDC"); +PCM_DECODER(PCM_SGA, AV_SAMPLE_FMT_U8, pcm_sga, "PCM SGA"); diff -Nru ffmpeg-4.2.2/libavcodec/pcm-dvd.c ffmpeg-4.4/libavcodec/pcm-dvd.c --- ffmpeg-4.2.2/libavcodec/pcm-dvd.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pcm-dvd.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,8 +34,9 @@ int last_block_size; // Size of the last block of samples in bytes int samples_per_block; // Number of samples per channel per block int groups_per_block; // Number of 20/24-bit sample groups per block - uint8_t *extra_samples; // Pointer to leftover samples from a frame int extra_sample_count; // Number of leftover samples in the buffer + uint8_t extra_samples[8 * 3 * 4]; // Space for leftover samples from a frame + // (8 channels, 3B/sample, 4 samples/block) } PCMDVDContext; static av_cold int pcm_dvd_decode_init(AVCodecContext *avctx) @@ -44,18 +45,6 @@ /* Invalid header to force parsing of the first header */ s->last_header = -1; - /* reserve space for 8 channels, 3 bytes/sample, 4 samples/block */ - if (!(s->extra_samples = av_malloc(8 * 3 * 4))) - return AVERROR(ENOMEM); - - return 0; -} - -static av_cold int pcm_dvd_decode_uninit(AVCodecContext *avctx) -{ - PCMDVDContext *s = avctx->priv_data; - - av_freep(&s->extra_samples); return 0; } @@ -310,9 +299,10 @@ .priv_data_size = sizeof(PCMDVDContext), .init = pcm_dvd_decode_init, .decode = pcm_dvd_decode_frame, - .close = pcm_dvd_decode_uninit, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE - } + }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/pcm-dvdenc.c ffmpeg-4.4/libavcodec/pcm-dvdenc.c --- ffmpeg-4.2.2/libavcodec/pcm-dvdenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pcm-dvdenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -170,11 +170,6 @@ return 0; } -static av_cold int pcm_dvd_encode_close(AVCodecContext *avctx) -{ - return 0; -} - AVCodec ff_pcm_dvd_encoder = { .name = "pcm_dvd", .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for DVD media"), @@ -182,7 +177,6 @@ .id = AV_CODEC_ID_PCM_DVD, .priv_data_size = sizeof(PCMDVDContext), .init = pcm_dvd_encode_init, - .close = pcm_dvd_encode_close, .encode2 = pcm_dvd_encode_frame, .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, .supported_samplerates = (const int[]) { 48000, 96000, 0}, @@ -194,4 +188,5 @@ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/pcm_rechunk_bsf.c ffmpeg-4.4/libavcodec/pcm_rechunk_bsf.c --- ffmpeg-4.2.2/libavcodec/pcm_rechunk_bsf.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pcm_rechunk_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2020 Marton Balint + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "bsf_internal.h" +#include "libavutil/avassert.h" +#include "libavutil/opt.h" + +typedef struct PCMContext { + const AVClass *class; + + int nb_out_samples; + int pad; + AVRational frame_rate; + + AVPacket *in_pkt; + AVPacket *out_pkt; + int sample_size; + int64_t n; +} PCMContext; + +static int init(AVBSFContext *ctx) +{ + PCMContext *s = ctx->priv_data; + AVRational sr = av_make_q(ctx->par_in->sample_rate, 1); + int64_t min_samples; + + if (ctx->par_in->channels <= 0 || ctx->par_in->sample_rate <= 0) + return AVERROR(EINVAL); + + ctx->time_base_out = av_inv_q(sr); + s->sample_size = ctx->par_in->channels * av_get_bits_per_sample(ctx->par_in->codec_id) / 8; + + if (s->frame_rate.num) { + min_samples = av_rescale_q_rnd(1, sr, s->frame_rate, AV_ROUND_DOWN); + } else { + min_samples = s->nb_out_samples; + } + if (min_samples <= 0 || min_samples > INT_MAX / s->sample_size - 1) + return AVERROR(EINVAL); + + s->in_pkt = av_packet_alloc(); + s->out_pkt = av_packet_alloc(); + if (!s->in_pkt || !s->out_pkt) + return AVERROR(ENOMEM); + + return 0; +} + +static void uninit(AVBSFContext *ctx) +{ + PCMContext *s = ctx->priv_data; + av_packet_free(&s->in_pkt); + av_packet_free(&s->out_pkt); +} + +static void flush(AVBSFContext *ctx) +{ + PCMContext *s = ctx->priv_data; + av_packet_unref(s->in_pkt); + av_packet_unref(s->out_pkt); + s->n = 0; +} + +static int send_packet(PCMContext *s, int nb_samples, AVPacket *pkt) +{ + pkt->duration = nb_samples; + s->n++; + return 0; +} + +static void drain_packet(AVPacket *pkt, int drain_data, int drain_samples) +{ + pkt->size -= drain_data; + pkt->data += drain_data; + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts += drain_samples; + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts += drain_samples; +} + +static int get_next_nb_samples(AVBSFContext *ctx) +{ + PCMContext *s = ctx->priv_data; + if (s->frame_rate.num) { + AVRational sr = av_make_q(ctx->par_in->sample_rate, 1); + return av_rescale_q(s->n + 1, sr, s->frame_rate) - av_rescale_q(s->n, sr, s->frame_rate); + } else { + return s->nb_out_samples; + } +} + +static int rechunk_filter(AVBSFContext *ctx, AVPacket *pkt) +{ + PCMContext *s = ctx->priv_data; + int nb_samples = get_next_nb_samples(ctx); + int data_size = nb_samples * s->sample_size; + int ret; + + do { + if (s->in_pkt->size) { + if (s->out_pkt->size || s->in_pkt->size < data_size) { + int drain = FFMIN(s->in_pkt->size, data_size - s->out_pkt->size); + if (!s->out_pkt->size) { + ret = av_new_packet(s->out_pkt, data_size); + if (ret < 0) + return ret; + ret = av_packet_copy_props(s->out_pkt, s->in_pkt); + if (ret < 0) { + av_packet_unref(s->out_pkt); + return ret; + } + s->out_pkt->size = 0; + } + memcpy(s->out_pkt->data + s->out_pkt->size, s->in_pkt->data, drain); + s->out_pkt->size += drain; + drain_packet(s->in_pkt, drain, drain / s->sample_size); + if (!s->in_pkt->size) + av_packet_unref(s->in_pkt); + if (s->out_pkt->size == data_size) { + av_packet_move_ref(pkt, s->out_pkt); + return send_packet(s, nb_samples, pkt); + } + } else if (s->in_pkt->size > data_size) { + ret = av_packet_ref(pkt, s->in_pkt); + if (ret < 0) + return ret; + pkt->size = data_size; + drain_packet(s->in_pkt, data_size, nb_samples); + return send_packet(s, nb_samples, pkt); + } else { + av_assert0(s->in_pkt->size == data_size); + av_packet_move_ref(pkt, s->in_pkt); + return send_packet(s, nb_samples, pkt); + } + } + + ret = ff_bsf_get_packet_ref(ctx, s->in_pkt); + if (ret == AVERROR_EOF && s->out_pkt->size) { + if (s->pad) { + memset(s->out_pkt->data + s->out_pkt->size, 0, data_size - s->out_pkt->size); + s->out_pkt->size = data_size; + } else { + nb_samples = s->out_pkt->size / s->sample_size; + } + av_packet_move_ref(pkt, s->out_pkt); + return send_packet(s, nb_samples, pkt); + } + if (ret >= 0) + av_packet_rescale_ts(s->in_pkt, ctx->time_base_in, ctx->time_base_out); + } while (ret >= 0); + + return ret; +} + +#define OFFSET(x) offsetof(PCMContext, x) +#define FLAGS (AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_BSF_PARAM) +static const AVOption options[] = { + { "nb_out_samples", "set the number of per-packet output samples", OFFSET(nb_out_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, FLAGS }, + { "n", "set the number of per-packet output samples", OFFSET(nb_out_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, FLAGS }, + { "pad", "pad last packet with zeros", OFFSET(pad), AV_OPT_TYPE_BOOL, {.i64=1} , 0, 1, FLAGS }, + { "p", "pad last packet with zeros", OFFSET(pad), AV_OPT_TYPE_BOOL, {.i64=1} , 0, 1, FLAGS }, + { "frame_rate", "set number of packets per second", OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS }, + { "r", "set number of packets per second", OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS }, + { NULL }, +}; + +static const AVClass pcm_rechunk_class = { + .class_name = "pcm_rechunk_bsf", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_PCM_S16LE, + AV_CODEC_ID_PCM_S16BE, + AV_CODEC_ID_PCM_S8, + AV_CODEC_ID_PCM_S32LE, + AV_CODEC_ID_PCM_S32BE, + AV_CODEC_ID_PCM_S24LE, + AV_CODEC_ID_PCM_S24BE, + AV_CODEC_ID_PCM_F32BE, + AV_CODEC_ID_PCM_F32LE, + AV_CODEC_ID_PCM_F64BE, + AV_CODEC_ID_PCM_F64LE, + AV_CODEC_ID_PCM_S64LE, + AV_CODEC_ID_PCM_S64BE, + AV_CODEC_ID_PCM_F16LE, + AV_CODEC_ID_PCM_F24LE, + AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_pcm_rechunk_bsf = { + .name = "pcm_rechunk", + .priv_data_size = sizeof(PCMContext), + .priv_class = &pcm_rechunk_class, + .filter = rechunk_filter, + .init = init, + .flush = flush, + .close = uninit, + .codec_ids = codec_ids, +}; diff -Nru ffmpeg-4.2.2/libavcodec/pcm_tablegen.h ffmpeg-4.4/libavcodec/pcm_tablegen.h --- ffmpeg-4.2.2/libavcodec/pcm_tablegen.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pcm_tablegen.h 2020-07-11 10:39:30.000000000 +0000 @@ -45,48 +45,48 @@ /* alaw2linear() - Convert an A-law value to 16-bit linear PCM */ static av_cold int alaw2linear(unsigned char a_val) { - int t; - int seg; + int t; + int seg; - a_val ^= 0x55; + a_val ^= 0x55; - t = a_val & QUANT_MASK; - seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; - if(seg) t= (t + t + 1 + 32) << (seg + 2); - else t= (t + t + 1 ) << 3; + t = a_val & QUANT_MASK; + seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; + if(seg) t= (t + t + 1 + 32) << (seg + 2); + else t= (t + t + 1 ) << 3; - return (a_val & SIGN_BIT) ? t : -t; + return (a_val & SIGN_BIT) ? t : -t; } static av_cold int ulaw2linear(unsigned char u_val) { - int t; + int t; - /* Complement to obtain normal u-law value. */ - u_val = ~u_val; + /* Complement to obtain normal u-law value. */ + u_val = ~u_val; - /* - * Extract and bias the quantization bits. Then - * shift up by the segment number and subtract out the bias. - */ - t = ((u_val & QUANT_MASK) << 3) + BIAS; - t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; + /* + * Extract and bias the quantization bits. Then + * shift up by the segment number and subtract out the bias. + */ + t = ((u_val & QUANT_MASK) << 3) + BIAS; + t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; - return (u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS); + return (u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS); } static av_cold int vidc2linear(unsigned char u_val) { - int t; + int t; - /* - * Extract and bias the quantization bits. Then - * shift up by the segment number and subtract out the bias. - */ - t = (((u_val & VIDC_QUANT_MASK) >> VIDC_QUANT_SHIFT) << 3) + BIAS; - t <<= ((unsigned)u_val & VIDC_SEG_MASK) >> VIDC_SEG_SHIFT; + /* + * Extract and bias the quantization bits. Then + * shift up by the segment number and subtract out the bias. + */ + t = (((u_val & VIDC_QUANT_MASK) >> VIDC_QUANT_SHIFT) << 3) + BIAS; + t <<= ((unsigned)u_val & VIDC_SEG_MASK) >> VIDC_SEG_SHIFT; - return (u_val & VIDC_SIGN_BIT) ? (BIAS - t) : (t - BIAS); + return (u_val & VIDC_SIGN_BIT) ? (BIAS - t) : (t - BIAS); } #if CONFIG_HARDCODED_TABLES diff -Nru ffmpeg-4.2.2/libavcodec/pgssubdec.c ffmpeg-4.4/libavcodec/pgssubdec.c --- ffmpeg-4.2.2/libavcodec/pgssubdec.c 2019-05-13 18:51:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pgssubdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -614,7 +614,7 @@ return 1; } -static int decode(AVCodecContext *avctx, void *data, int *data_size, +static int decode(AVCodecContext *avctx, void *data, int *got_sub_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; @@ -636,7 +636,7 @@ if (i & 15) ff_dlog(avctx, "\n"); - *data_size = 0; + *got_sub_ptr = 0; /* Ensure that we have received at a least a segment code and segment length */ if (buf_size < 3) @@ -676,14 +676,14 @@ */ break; case DISPLAY_SEGMENT: - if (*data_size) { + if (*got_sub_ptr) { av_log(avctx, AV_LOG_ERROR, "Duplicate display segment\n"); ret = AVERROR_INVALIDDATA; break; } ret = display_end_segment(avctx, data, buf, segment_length); if (ret >= 0) - *data_size = ret; + *got_sub_ptr = ret; break; default: av_log(avctx, AV_LOG_ERROR, "Unknown subtitle segment type 0x%x, length %d\n", @@ -691,8 +691,11 @@ ret = AVERROR_INVALIDDATA; break; } - if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) + if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) { + avsubtitle_free(data); + *got_sub_ptr = 0; return ret; + } buf += segment_length; } diff -Nru ffmpeg-4.2.2/libavcodec/pgxdec.c ffmpeg-4.4/libavcodec/pgxdec.c --- ffmpeg-4.2.2/libavcodec/pgxdec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pgxdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,168 @@ +/* + * PGX image format + * Copyright (c) 2020 Gautam Ramakrishnan + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "internal.h" +#include "bytestream.h" +#include "libavutil/imgutils.h" + +static int pgx_get_number(AVCodecContext *avctx, GetByteContext *g, int *number) { + int ret = AVERROR_INVALIDDATA; + char digit; + + *number = 0; + while (1) { + uint64_t temp; + if (!bytestream2_get_bytes_left(g)) + return AVERROR_INVALIDDATA; + digit = bytestream2_get_byte(g); + if (digit == ' ' || digit == 0xA || digit == 0xD) + break; + else if (digit < '0' || digit > '9') + return AVERROR_INVALIDDATA; + + temp = (uint64_t)10 * (*number) + (digit - '0'); + if (temp > INT_MAX) + return AVERROR_INVALIDDATA; + *number = temp; + ret = 0; + } + + return ret; +} + +static int pgx_decode_header(AVCodecContext *avctx, GetByteContext *g, + int *depth, int *width, int *height, + int *sign) +{ + int byte; + + if (bytestream2_get_bytes_left(g) < 6) { + return AVERROR_INVALIDDATA; + } + + bytestream2_skip(g, 6); + + // Is the component signed? + byte = bytestream2_peek_byte(g); + if (byte == '+') { + *sign = 0; + bytestream2_skip(g, 1); + } else if (byte == '-') { + *sign = 1; + bytestream2_skip(g, 1); + } else if (byte == 0) + goto error; + + byte = bytestream2_peek_byte(g); + if (byte == ' ') + bytestream2_skip(g, 1); + else if (byte == 0) + goto error; + + if (pgx_get_number(avctx, g, depth)) + goto error; + if (pgx_get_number(avctx, g, width)) + goto error; + if (pgx_get_number(avctx, g, height)) + goto error; + + if (bytestream2_peek_byte(g) == 0xA) + bytestream2_skip(g, 1); + return 0; + +error: + av_log(avctx, AV_LOG_ERROR, "Error in decoding header.\n"); + return AVERROR_INVALIDDATA; +} + +#define WRITE_FRAME(D, PIXEL, suffix) \ + static inline void write_frame_ ##D(AVFrame *frame, GetByteContext *g, \ + int width, int height, int sign, int depth) \ + { \ + int i, j; \ + for (i = 0; i < height; i++) { \ + PIXEL *line = (PIXEL*)frame->data[0] + i*frame->linesize[0]/sizeof(PIXEL); \ + for (j = 0; j < width; j++) { \ + unsigned val; \ + if (sign) \ + val = (PIXEL)bytestream2_get_ ##suffix(g) + (1 << (depth - 1)); \ + else \ + val = bytestream2_get_ ##suffix(g); \ + val <<= (D - depth); \ + *(line + j) = val; \ + } \ + } \ + } \ + +WRITE_FRAME(8, int8_t, byte) +WRITE_FRAME(16, int16_t, be16) + +static int pgx_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVFrame *p = data; + int ret; + int bpp; + int width, height, depth; + int sign = 0; + GetByteContext g; + bytestream2_init(&g, avpkt->data, avpkt->size); + + if ((ret = pgx_decode_header(avctx, &g, &depth, &width, &height, &sign)) < 0) + return ret; + + if ((ret = ff_set_dimensions(avctx, width, height)) < 0) + return ret; + + if (depth > 0 && depth <= 8) { + avctx->pix_fmt = AV_PIX_FMT_GRAY8; + bpp = 8; + } else if (depth > 0 && depth <= 16) { + avctx->pix_fmt = AV_PIX_FMT_GRAY16; + bpp = 16; + } else { + av_log(avctx, AV_LOG_ERROR, "depth %d is invalid or unsupported.\n", depth); + return AVERROR_PATCHWELCOME; + } + if (bytestream2_get_bytes_left(&g) < width * height * (bpp >> 3)) + return AVERROR_INVALIDDATA; + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + avctx->bits_per_raw_sample = depth; + if (bpp == 8) + write_frame_8(p, &g, width, height, sign, depth); + else if (bpp == 16) + write_frame_16(p, &g, width, height, sign, depth); + *got_frame = 1; + return 0; +} + +AVCodec ff_pgx_decoder = { + .name = "pgx", + .long_name = NULL_IF_CONFIG_SMALL("PGX (JPEG2000 Test Format)"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PGX, + .decode = pgx_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, +}; diff -Nru ffmpeg-4.2.2/libavcodec/photocd.c ffmpeg-4.4/libavcodec/photocd.c --- ffmpeg-4.2.2/libavcodec/photocd.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/photocd.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,473 @@ +/* + * Kodak PhotoCD (a.k.a. ImagePac) image decoder + * + * Copyright (c) 1996-2002 Gerd Knorr + * Copyright (c) 2010 Kenneth Vermeirsch + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Kodak PhotoCD (a.k.a. ImagePac) image decoder + * + * Supports resolutions up to 3072x2048. + */ + +#define CACHED_BITSTREAM_READER !ARCH_X86_32 + +#include "libavutil/avassert.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "bytestream.h" +#include "get_bits.h" +#include "internal.h" +#include "thread.h" + +typedef struct PhotoCDContext { + AVClass *class; + int lowres; + + GetByteContext gb; + int thumbnails; //* number of thumbnails; 0 for normal image */ + int resolution; + int orientation; + + int streampos; + + uint8_t bits[256]; + uint16_t codes[256]; + uint8_t syms[256]; + + VLC vlc[3]; +} PhotoCDContext; + +typedef struct ImageInfo { + uint32_t start; + uint16_t width, height; +} ImageInfo; + +static const ImageInfo img_info[6] = { + {8192, 192, 128}, + {47104, 384, 256}, + {196608, 768, 512}, + {0, 1536, 1024}, + {0, 3072, 2048}, + {0, 6144, 4096}, +}; + +static av_noinline void interp_lowres(PhotoCDContext *s, AVFrame *picture, + int width, int height) +{ + GetByteContext *gb = &s->gb; + int start = s->streampos + img_info[2].start; + uint8_t *ptr, *ptr1, *ptr2; + uint8_t *dst; + int fill; + + ptr = picture->data[0]; + ptr1 = picture->data[1]; + ptr2 = picture->data[2]; + + bytestream2_seek(gb, start, SEEK_SET); + + for (int y = 0; y < height; y += 2) { + dst = ptr; + for (int x = 0; x < width - 1; x++) { + fill = bytestream2_get_byte(gb); + *(dst++) = fill; + *(dst++) = (fill + bytestream2_peek_byte(gb) + 1) >> 1; + } + fill = bytestream2_get_byte(gb); + *(dst++) = fill; + *(dst++) = fill; + + ptr += picture->linesize[0] << 1; + + dst = ptr; + for (int x = 0; x < width - 1; x++) { + fill = bytestream2_get_byte(gb); + *(dst++) = fill; + *(dst++) = (fill + bytestream2_peek_byte(gb) + 1) >> 1; + } + fill = bytestream2_get_byte(gb); + *(dst++) = fill; + *(dst++) = fill; + + ptr += picture->linesize[0] << 1; + + dst = ptr1; + for (int x = 0; x < (width >> 1) - 1; x++) { + fill = bytestream2_get_byte(gb); + *(dst++) = fill; + *(dst++) = (fill + bytestream2_peek_byte(gb) + 1) >> 1; + } + fill = bytestream2_get_byte(gb); + *(dst++) = fill; + *(dst++) = fill; + + ptr1 += picture->linesize[1] << 1; + + dst = ptr2; + for (int x = 0; x < (width >> 1) - 1; x++) { + fill = bytestream2_get_byte(gb); + *(dst++) = fill; + *(dst++) = (fill + bytestream2_peek_byte(gb) + 1) >> 1; + } + fill = bytestream2_get_byte(gb); + *(dst++) = fill; + *(dst++) = fill; + + ptr2 += picture->linesize[2] << 1; + } + + s->streampos += bytestream2_tell(gb) - start; +} + +static av_noinline void interp_lines(uint8_t *ptr, int linesize, + int width, int height) +{ + const uint8_t *src1; + uint8_t *dst; + int x; + + for (int y = 0; y < height - 2; y += 2) { + const uint8_t *src1 = ptr; + uint8_t *dst = ptr + linesize; + const uint8_t *src2 = dst + linesize; + for (x = 0; x < width - 2; x += 2) { + dst[x] = (src1[x] + src2[x] + 1) >> 1; + dst[x + 1] = (src1[x] + src2[x] + src1[x + 2] + src2[x + 2] + 2) >> 2; + } + dst[x] = dst[x + 1] = (src1[x] + src2[x] + 1) >> 1; + + ptr += linesize << 1; + } + + src1 = ptr; + dst = ptr + linesize; + for (x = 0; x < width - 2; x += 2) { + dst[x] = src1[x]; + dst[x + 1] = (src1[x] + src1[x + 2] + 1) >> 1; + } + dst[x] = dst[x + 1] = src1[x]; +} + +static av_noinline void interp_pixels(uint8_t *ptr, int linesize, + int width, int height) +{ + for (int y = height - 2; y >= 0; y -= 2) { + const uint8_t *src = ptr + (y >> 1) * linesize; + uint8_t *dst = ptr + y * linesize; + + dst[width - 2] = dst[width - 1] = src[(width >> 1) - 1]; + for (int x = width - 4; x >= 0; x -= 2) { + dst[x] = src[x >> 1]; + dst[x + 1] = (src[x >> 1] + src[(x >> 1) + 1] + 1) >> 1; + } + } +} + +static av_noinline int read_hufftable(AVCodecContext *avctx, VLC *vlc) +{ + PhotoCDContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + int start = s->streampos; + int count, ret; + + bytestream2_seek(gb, start, SEEK_SET); + + count = bytestream2_get_byte(gb) + 1; + if (bytestream2_get_bytes_left(gb) < count * 4) + return AVERROR_INVALIDDATA; + + for (int j = 0; j < count; j++) { + const int bit = bytestream2_get_byteu(gb) + 1; + const int code = bytestream2_get_be16u(gb); + const int sym = bytestream2_get_byteu(gb); + + if (bit > 16) + return AVERROR_INVALIDDATA; + + s->bits[j] = bit; + s->codes[j] = code >> (16 - bit); + s->syms[j] = sym; + } + + ff_free_vlc(vlc); + ret = ff_init_vlc_sparse(vlc, 12, count, + s->bits, sizeof(*s->bits), sizeof(*s->bits), + s->codes, sizeof(*s->codes), sizeof(*s->codes), + s->syms, sizeof(*s->syms), sizeof(*s->syms), 0); + + s->streampos = bytestream2_tell(gb); + + return ret; +} + +static av_noinline int decode_huff(AVCodecContext *avctx, AVFrame *frame, + int target_res, int curr_res) +{ + PhotoCDContext *s = avctx->priv_data; + GetBitContext g; + GetByteContext *gb = &s->gb; + int ret, y = 0, type, height; + int start = s->streampos; + unsigned shiftreg; + const int scaling = target_res - curr_res; + const uint8_t type2idx[] = { 0, 0xff, 1, 2 }; + + bytestream2_seek(gb, start, SEEK_SET); + ret = init_get_bits8(&g, gb->buffer, bytestream2_get_bytes_left(gb)); + if (ret < 0) + return ret; + + height = img_info[curr_res].height; + + while (y < height) { + uint8_t *data; + int x2, idx; + + for (; get_bits_left(&g) > 0;) { + if (show_bits(&g, 12) == 0xfff) + break; + skip_bits(&g, 8); + } + + shiftreg = show_bits(&g, 24); + while (shiftreg != 0xfffffe) { + if (get_bits_left(&g) <= 0) + return AVERROR_INVALIDDATA; + skip_bits(&g, 1); + shiftreg = show_bits(&g, 24); + } + skip_bits(&g, 24); + y = show_bits(&g, 15) & 0x1fff; + if (y >= height) + break; + type = get_bits(&g, 2); + skip_bits(&g, 14); + + if (type == 1) + return AVERROR_INVALIDDATA; + idx = type2idx[type]; + + data = frame->data[idx] + (y >> !!idx) * frame->linesize[idx]; + + x2 = avctx->width >> (scaling + !!idx); + for (int x = 0; x < x2; x++) { + int m; + + if (get_bits_left(&g) <= 0) + return AVERROR_INVALIDDATA; + m = get_vlc2(&g, s->vlc[idx].table, s->vlc[idx].bits, 2); + if (m < 0) + return AVERROR_INVALIDDATA; + m = sign_extend(m, 8); + data[x] = av_clip_uint8(data[x] + m); + } + } + + s->streampos += (get_bits_count(&g) + 7) >> 3; + s->streampos = (s->streampos + 0x6000 + 2047) & ~0x7ff; + + return 0; +} + +static int photocd_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + PhotoCDContext *s = avctx->priv_data; + ThreadFrame frame = { .f = data }; + const uint8_t *buf = avpkt->data; + GetByteContext *gb = &s->gb; + AVFrame *p = data; + uint8_t *ptr, *ptr1, *ptr2; + int ret; + + if (avpkt->size < img_info[0].start) + return AVERROR_INVALIDDATA; + + if (!memcmp("PCD_OPA", buf, 7)) { + s->thumbnails = AV_RL16(buf + 10); + av_log(avctx, AV_LOG_WARNING, "this is a thumbnails file, " + "reading first thumbnail only\n"); + } else if (avpkt->size < 786432) { + return AVERROR_INVALIDDATA; + } else if (memcmp("PCD_IPI", buf + 0x800, 7)) { + return AVERROR_INVALIDDATA; + } + + s->orientation = s->thumbnails ? buf[12] & 3 : buf[0x48] & 3; + + if (s->thumbnails) + s->resolution = 0; + else if (avpkt->size <= 788480) + s->resolution = 2; + else + s->resolution = av_clip(4 - s->lowres, 0, 4); + + ret = ff_set_dimensions(avctx, img_info[s->resolution].width, img_info[s->resolution].height); + if (ret < 0) + return ret; + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + bytestream2_init(gb, avpkt->data, avpkt->size); + + if (s->resolution < 3) { + ptr = p->data[0]; + ptr1 = p->data[1]; + ptr2 = p->data[2]; + + if (s->thumbnails) + bytestream2_seek(gb, 10240, SEEK_SET); + else + bytestream2_seek(gb, img_info[s->resolution].start, SEEK_SET); + + for (int y = 0; y < avctx->height; y += 2) { + bytestream2_get_buffer(gb, ptr, avctx->width); + ptr += p->linesize[0]; + + bytestream2_get_buffer(gb, ptr, avctx->width); + ptr += p->linesize[0]; + + bytestream2_get_buffer(gb, ptr1, avctx->width >> 1); + ptr1 += p->linesize[1]; + + bytestream2_get_buffer(gb, ptr2, avctx->width >> 1); + ptr2 += p->linesize[2]; + } + } else { + s->streampos = 0; + ptr = p->data[0]; + ptr1 = p->data[1]; + ptr2 = p->data[2]; + + interp_lowres(s, p, img_info[2].width, img_info[2].height); + + interp_lines(ptr1, p->linesize[1], img_info[2].width, img_info[2].height); + interp_lines(ptr2, p->linesize[2], img_info[2].width, img_info[2].height); + + if (s->resolution == 4) { + interp_pixels(ptr1, p->linesize[1], img_info[3].width, img_info[3].height); + interp_lines (ptr1, p->linesize[1], img_info[3].width, img_info[3].height); + interp_pixels(ptr2, p->linesize[2], img_info[3].width, img_info[3].height); + interp_lines (ptr2, p->linesize[2], img_info[3].width, img_info[3].height); + } + + interp_lines(ptr, p->linesize[0], img_info[3].width, img_info[3].height); + + s->streampos = 0xc2000; + for (int n = 0; n < 3; n++) { + if ((ret = read_hufftable(avctx, &s->vlc[n])) < 0) + return ret; + } + s->streampos = (s->streampos + 2047) & ~0x3ff; + if (decode_huff(avctx, p, s->resolution, 3) < 0) + return AVERROR_INVALIDDATA; + + if (s->resolution == 4) { + interp_pixels(ptr, p->linesize[0], img_info[4].width, img_info[4].height); + interp_lines (ptr, p->linesize[0], img_info[4].width, img_info[4].height); + + for (int n = 0; n < 3; n++) { + if ((ret = read_hufftable(avctx, &s->vlc[n])) < 0) + return ret; + } + s->streampos = (s->streampos + 2047) & ~0x3ff; + if (decode_huff(avctx, p, 4, 4) < 0) + return AVERROR_INVALIDDATA; + } + } + + { + ptr1 = p->data[1]; + ptr2 = p->data[2]; + + for (int y = 0; y < avctx->height >> 1; y++) { + for (int x = 0; x < avctx->width >> 1; x++) { + ptr1[x] = av_clip_uint8(ptr1[x] - 28); + ptr2[x] = av_clip_uint8(ptr2[x] - 9); + } + + ptr1 += p->linesize[1]; + ptr2 += p->linesize[2]; + } + } + + *got_frame = 1; + + return 0; +} + +static av_cold int photocd_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + avctx->colorspace = AVCOL_SPC_BT709; + avctx->color_primaries = AVCOL_PRI_BT709; + avctx->color_trc = AVCOL_TRC_IEC61966_2_1; + avctx->color_range = AVCOL_RANGE_JPEG; + + return 0; +} + +static av_cold int photocd_decode_close(AVCodecContext *avctx) +{ + PhotoCDContext *s = avctx->priv_data; + + for (int i = 0; i < 3; i++) + ff_free_vlc(&s->vlc[i]); + + return 0; +} + +#define OFFSET(x) offsetof(PhotoCDContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM + +static const AVOption options[] = { + { "lowres", "Lower the decoding resolution by a power of two", + OFFSET(lowres), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 4, VD }, + { NULL }, +}; + +static const AVClass photocd_class = { + .class_name = "photocd", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_photocd_decoder = { + .name = "photocd", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PHOTOCD, + .priv_data_size = sizeof(PhotoCDContext), + .priv_class = &photocd_class, + .init = photocd_decode_init, + .close = photocd_decode_close, + .decode = photocd_decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("Kodak Photo CD"), + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff -Nru ffmpeg-4.2.2/libavcodec/pictordec.c ffmpeg-4.4/libavcodec/pictordec.c --- ffmpeg-4.2.2/libavcodec/pictordec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pictordec.c 2020-07-11 10:39:30.000000000 +0000 @@ -66,6 +66,7 @@ int xl = *x; int yl = *y; int planel = *plane; + int pixels_per_value = 8/bits_per_plane; value <<= shift; d = frame->data[0] + yl * frame->linesize[0]; @@ -74,7 +75,7 @@ for (j = 8-bits_per_plane; j >= 0; j -= bits_per_plane) { d[xl] |= (value >> j) & mask; xl += 1; - if (xl == s->width) { + while (xl == s->width) { yl -= 1; xl = 0; if (yl < 0) { @@ -86,6 +87,19 @@ mask <<= bits_per_plane; } d = frame->data[0] + yl * frame->linesize[0]; + if (s->nb_planes == 1 && + run*pixels_per_value >= s->width && + pixels_per_value < s->width && + s->width % pixels_per_value == 0 + ) { + for (; xl < pixels_per_value; xl ++) { + j = (j < bits_per_plane ? 8 : j) - bits_per_plane; + d[xl] |= (value >> j) & mask; + } + av_memcpy_backptr(d+xl, pixels_per_value, s->width - xl); + run -= s->width / pixels_per_value; + xl = s->width; + } } } run--; diff -Nru ffmpeg-4.2.2/libavcodec/pixblockdsp.c ffmpeg-4.4/libavcodec/pixblockdsp.c --- ffmpeg-4.2.2/libavcodec/pixblockdsp.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pixblockdsp.c 2020-07-11 10:39:30.000000000 +0000 @@ -90,15 +90,19 @@ case 10: case 12: case 14: + c->get_pixels_unaligned = c->get_pixels = get_pixels_16_c; break; default: if (avctx->bits_per_raw_sample<=8 || avctx->codec_type != AVMEDIA_TYPE_VIDEO) { + c->get_pixels_unaligned = c->get_pixels = get_pixels_8_c; } break; } + if (ARCH_AARCH64) + ff_pixblockdsp_init_aarch64(c, avctx, high_bit_depth); if (ARCH_ALPHA) ff_pixblockdsp_init_alpha(c, avctx, high_bit_depth); if (ARCH_ARM) diff -Nru ffmpeg-4.2.2/libavcodec/pixblockdsp.h ffmpeg-4.4/libavcodec/pixblockdsp.h --- ffmpeg-4.2.2/libavcodec/pixblockdsp.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pixblockdsp.h 2020-07-11 10:39:30.000000000 +0000 @@ -29,6 +29,9 @@ void (*get_pixels)(int16_t *av_restrict block /* align 16 */, const uint8_t *pixels /* align 8 */, ptrdiff_t stride); + void (*get_pixels_unaligned)(int16_t *av_restrict block /* align 16 */, + const uint8_t *pixels, + ptrdiff_t stride); void (*diff_pixels)(int16_t *av_restrict block /* align 16 */, const uint8_t *s1 /* align 8 */, const uint8_t *s2 /* align 8 */, @@ -41,6 +44,8 @@ } PixblockDSPContext; void ff_pixblockdsp_init(PixblockDSPContext *c, AVCodecContext *avctx); +void ff_pixblockdsp_init_aarch64(PixblockDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); void ff_pixblockdsp_init_alpha(PixblockDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth); void ff_pixblockdsp_init_arm(PixblockDSPContext *c, AVCodecContext *avctx, diff -Nru ffmpeg-4.2.2/libavcodec/pixlet.c ffmpeg-4.4/libavcodec/pixlet.c --- ffmpeg-4.2.2/libavcodec/pixlet.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pixlet.c 2021-04-08 21:28:39.000000000 +0000 @@ -58,6 +58,7 @@ int16_t *filter[2]; int16_t *prediction; int64_t scaling[4][2][NB_LEVELS]; + uint16_t lut[65536]; SubBand band[4][NB_LEVELS * 3 + 1]; } PixletContext; @@ -221,7 +222,7 @@ length = 25 - nbits; while (i < size) { - if (state >> 8 != -3) + if (((state >> 8) + 3) & 0xFFFFFFF) value = ff_clz((state >> 8) + 3) ^ 0x1F; else value = -1; @@ -462,11 +463,27 @@ } } -static void postprocess_luma(AVFrame *frame, int w, int h, int depth) +static void build_luma_lut(AVCodecContext *avctx, int depth) { + PixletContext *ctx = avctx->priv_data; + int max = (1 << depth) - 1; + + if (ctx->depth == depth) + return; + ctx->depth = depth; + + for (int i = 0; i < FF_ARRAY_ELEMS(ctx->lut); i++) + ctx->lut[i] = ((int64_t)i * i * 65535LL) / max / max; +} + +static void postprocess_luma(AVCodecContext *avctx, AVFrame *frame, + int w, int h, int depth) +{ + PixletContext *ctx = avctx->priv_data; uint16_t *dsty = (uint16_t *)frame->data[0]; int16_t *srcy = (int16_t *)frame->data[0]; ptrdiff_t stridey = frame->linesize[0] / 2; + uint16_t *lut = ctx->lut; int i, j; for (j = 0; j < h; j++) { @@ -476,8 +493,7 @@ else if (srcy[i] > ((1 << depth) - 1)) dsty[i] = 65535; else - dsty[i] = ((int64_t) srcy[i] * srcy[i] * 65535) / - ((1 << depth) - 1) / ((1 << depth) - 1); + dsty[i] = lut[srcy[i]]; } dsty += stridey; srcy += stridey; @@ -509,7 +525,7 @@ } static int decode_plane(AVCodecContext *avctx, int plane, - AVPacket *avpkt, AVFrame *frame) + const AVPacket *avpkt, AVFrame *frame) { PixletContext *ctx = avctx->priv_data; ptrdiff_t stride = frame->linesize[plane] / 2; @@ -591,7 +607,7 @@ int i, w, h, width, height, ret, version; AVFrame *p = data; ThreadFrame frame = { .f = data }; - uint32_t pktsize; + uint32_t pktsize, depth; bytestream2_init(&ctx->gb, avpkt->data, avpkt->size); @@ -623,12 +639,14 @@ ctx->levels = bytestream2_get_be32(&ctx->gb); if (ctx->levels != NB_LEVELS) return AVERROR_INVALIDDATA; - ctx->depth = bytestream2_get_be32(&ctx->gb); - if (ctx->depth < 8 || ctx->depth > 15) { - avpriv_request_sample(avctx, "Depth %d", ctx->depth); + depth = bytestream2_get_be32(&ctx->gb); + if (depth < 8 || depth > 15) { + avpriv_request_sample(avctx, "Depth %d", depth); return AVERROR_INVALIDDATA; } + build_luma_lut(avctx, depth); + ret = ff_set_dimensions(avctx, w, h); if (ret < 0) return ret; @@ -667,7 +685,7 @@ break; } - postprocess_luma(frame.f, ctx->w, ctx->h, ctx->depth); + postprocess_luma(avctx, frame.f, ctx->w, ctx->h, ctx->depth); postprocess_chroma(frame.f, ctx->w >> 1, ctx->h >> 1, ctx->depth); *got_frame = 1; @@ -675,28 +693,12 @@ return pktsize; } -#if HAVE_THREADS -static int pixlet_init_thread_copy(AVCodecContext *avctx) -{ - PixletContext *ctx = avctx->priv_data; - - ctx->filter[0] = NULL; - ctx->filter[1] = NULL; - ctx->prediction = NULL; - ctx->w = 0; - ctx->h = 0; - - return 0; -} -#endif /* HAVE_THREADS */ - AVCodec ff_pixlet_decoder = { .name = "pixlet", .long_name = NULL_IF_CONFIG_SMALL("Apple Pixlet"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PIXLET, .init = pixlet_init, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(pixlet_init_thread_copy), .close = pixlet_close, .decode = pixlet_decode_frame, .priv_data_size = sizeof(PixletContext), diff -Nru ffmpeg-4.2.2/libavcodec/pngdec.c ffmpeg-4.4/libavcodec/pngdec.c --- ffmpeg-4.2.2/libavcodec/pngdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pngdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,7 +23,9 @@ #include "libavutil/avassert.h" #include "libavutil/bprint.h" +#include "libavutil/crc.h" #include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" #include "libavutil/stereo3d.h" #include "libavutil/mastering_display_metadata.h" @@ -52,10 +54,21 @@ AVCodecContext *avctx; GetByteContext gb; - ThreadFrame previous_picture; ThreadFrame last_picture; ThreadFrame picture; + AVDictionary *frame_metadata; + + uint8_t iccp_name[82]; + uint8_t *iccp_data; + size_t iccp_data_len; + + int stereo_mode; + + int have_chrm; + uint32_t white_point[2]; + uint32_t display_primaries[3][2]; + enum PNGHeaderState hdr_state; enum PNGImageState pic_state; int width, height; @@ -76,8 +89,8 @@ int has_trns; uint8_t transparent_color_be[6]; - uint8_t *image_buf; - int image_linesize; + uint8_t *background_buf; + unsigned background_buf_allocated; uint32_t palette[256]; uint8_t *crow_buf; uint8_t *last_row; @@ -248,8 +261,8 @@ } /* NOTE: 'dst' can be equal to 'last' */ -static void png_filter_row(PNGDSPContext *dsp, uint8_t *dst, int filter_type, - uint8_t *src, uint8_t *last, int size, int bpp) +void ff_png_filter_row(PNGDSPContext *dsp, uint8_t *dst, int filter_type, + uint8_t *src, uint8_t *last, int size, int bpp) { int i, p, r, g, b, a; @@ -319,28 +332,37 @@ YUV2RGB(rgb8, uint8_t) YUV2RGB(rgb16, uint16_t) +static int percent_missing(PNGDecContext *s) +{ + if (s->interlace_type) { + return 100 - 100 * s->pass / (NB_PASSES - 1); + } else { + return 100 - 100 * s->y / s->cur_h; + } +} + /* process exactly one decompressed row */ -static void png_handle_row(PNGDecContext *s) +static void png_handle_row(PNGDecContext *s, uint8_t *dst, ptrdiff_t dst_stride) { uint8_t *ptr, *last_row; int got_line; if (!s->interlace_type) { - ptr = s->image_buf + s->image_linesize * (s->y + s->y_offset) + s->x_offset * s->bpp; + ptr = dst + dst_stride * (s->y + s->y_offset) + s->x_offset * s->bpp; if (s->y == 0) last_row = s->last_row; else - last_row = ptr - s->image_linesize; + last_row = ptr - dst_stride; - png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1, - last_row, s->row_size, s->bpp); + ff_png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1, + last_row, s->row_size, s->bpp); /* loco lags by 1 row so that it doesn't interfere with top prediction */ if (s->filter_type == PNG_FILTER_TYPE_LOCO && s->y > 0) { if (s->bit_depth == 16) { - deloco_rgb16((uint16_t *)(ptr - s->image_linesize), s->row_size / 2, + deloco_rgb16((uint16_t *)(ptr - dst_stride), s->row_size / 2, s->color_type == PNG_COLOR_TYPE_RGB_ALPHA); } else { - deloco_rgb8(ptr - s->image_linesize, s->row_size, + deloco_rgb8(ptr - dst_stride, s->row_size, s->color_type == PNG_COLOR_TYPE_RGB_ALPHA); } } @@ -360,14 +382,14 @@ } else { got_line = 0; for (;;) { - ptr = s->image_buf + s->image_linesize * (s->y + s->y_offset) + s->x_offset * s->bpp; + ptr = dst + dst_stride * (s->y + s->y_offset) + s->x_offset * s->bpp; if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) { /* if we already read one row, it is time to stop to * wait for the next one */ if (got_line) break; - png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1, - s->last_row, s->pass_row_size, s->bpp); + ff_png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1, + s->last_row, s->pass_row_size, s->bpp); FFSWAP(uint8_t *, s->last_row, s->tmp_row); FFSWAP(unsigned int, s->last_row_size, s->tmp_row_size); got_line = 1; @@ -401,11 +423,12 @@ } } -static int png_decode_idat(PNGDecContext *s, int length) +static int png_decode_idat(PNGDecContext *s, int length, + uint8_t *dst, ptrdiff_t dst_stride) { int ret; s->zstream.avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb)); - s->zstream.next_in = (unsigned char *)s->gb.buffer; + s->zstream.next_in = s->gb.buffer; bytestream2_skip(&s->gb, length); /* decode one line if possible */ @@ -417,13 +440,13 @@ } if (s->zstream.avail_out == 0) { if (!(s->pic_state & PNG_ALLIMAGE)) { - png_handle_row(s); + png_handle_row(s, dst, dst_stride); } s->zstream.avail_out = s->crow_size; s->zstream.next_out = s->crow_buf; } if (ret == Z_STREAM_END && s->zstream.avail_in > 0) { - av_log(NULL, AV_LOG_WARNING, + av_log(s->avctx, AV_LOG_WARNING, "%d undecompressed bytes left in buffer\n", s->zstream.avail_in); return 0; } @@ -444,7 +467,7 @@ zstream.opaque = NULL; if (inflateInit(&zstream) != Z_OK) return AVERROR_EXTERNAL; - zstream.next_in = (unsigned char *)data; + zstream.next_in = data; zstream.avail_in = data_end - data; av_bprint_init(bp, 0, AV_BPRINT_SIZE_UNLIMITED); @@ -499,8 +522,7 @@ return out; } -static int decode_text_chunk(PNGDecContext *s, uint32_t length, int compressed, - AVDictionary **dict) +static int decode_text_chunk(PNGDecContext *s, uint32_t length, int compressed) { int ret, method; const uint8_t *data = s->gb.buffer; @@ -542,7 +564,7 @@ return AVERROR(ENOMEM); } - av_dict_set(dict, kw_utf8, txt_utf8, + av_dict_set(&s->frame_metadata, kw_utf8, txt_utf8, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); return 0; } @@ -700,13 +722,10 @@ s->bpp += byte_depth; } + ff_thread_release_buffer(avctx, &s->picture); if ((ret = ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; - if (avctx->codec_id == AV_CODEC_ID_APNG && s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { - ff_thread_release_buffer(avctx, &s->previous_picture); - if ((ret = ff_thread_get_buffer(avctx, &s->previous_picture, AV_GET_BUFFER_FLAG_REF)) < 0) - return ret; - } + p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; p->interlaced_frame = !!s->interlace_type; @@ -725,8 +744,7 @@ } ff_dlog(avctx, "row_size=%d crow_size =%d\n", s->row_size, s->crow_size); - s->image_buf = p->data[0]; - s->image_linesize = p->linesize[0]; + /* copy the palette if needed */ if (avctx->pix_fmt == AV_PIX_FMT_PAL8) memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t)); @@ -757,7 +775,7 @@ if (s->has_trns && s->color_type != PNG_COLOR_TYPE_PALETTE) s->bpp -= byte_depth; - ret = png_decode_idat(s, length); + ret = png_decode_idat(s, length, p->data[0], p->linesize[0]); if (s->has_trns && s->color_type != PNG_COLOR_TYPE_PALETTE) s->bpp += byte_depth; @@ -844,21 +862,21 @@ static int decode_iccp_chunk(PNGDecContext *s, int length, AVFrame *f) { int ret, cnt = 0; - uint8_t *data, profile_name[82]; AVBPrint bp; - AVFrameSideData *sd; - while ((profile_name[cnt++] = bytestream2_get_byte(&s->gb)) && cnt < 81); + while ((s->iccp_name[cnt++] = bytestream2_get_byte(&s->gb)) && cnt < 81); if (cnt > 80) { av_log(s->avctx, AV_LOG_ERROR, "iCCP with invalid name!\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } length = FFMAX(length - cnt, 0); if (bytestream2_get_byte(&s->gb) != 0) { av_log(s->avctx, AV_LOG_ERROR, "iCCP with invalid compression!\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } length = FFMAX(length - 1, 0); @@ -866,24 +884,19 @@ if ((ret = decode_zbuf(&bp, s->gb.buffer, s->gb.buffer + length)) < 0) return ret; - ret = av_bprint_finalize(&bp, (char **)&data); + av_freep(&s->iccp_data); + ret = av_bprint_finalize(&bp, (char **)&s->iccp_data); if (ret < 0) return ret; - - sd = av_frame_new_side_data(f, AV_FRAME_DATA_ICC_PROFILE, bp.len); - if (!sd) { - av_free(data); - return AVERROR(ENOMEM); - } - - av_dict_set(&sd->metadata, "name", profile_name, 0); - memcpy(sd->data, data, bp.len); - av_free(data); + s->iccp_data_len = bp.len; /* ICC compressed data and CRC */ bytestream2_skip(&s->gb, length + 4); return 0; +fail: + s->iccp_name[0] = 0; + return ret; } static void handle_small_bpp(PNGDecContext *s, AVFrame *p) @@ -906,7 +919,7 @@ pd[8*i + 1]= (pd[i]>>6) & 1; pd[8*i + 0]= pd[i]>>7; } - pd += s->image_linesize; + pd += p->linesize[0]; } } else if (s->bits_per_pixel == 2) { int i, j; @@ -934,7 +947,7 @@ pd[4*i + 0]= ( pd[i]>>6 )*0x55; } } - pd += s->image_linesize; + pd += p->linesize[0]; } } else if (s->bits_per_pixel == 4) { int i, j; @@ -954,7 +967,7 @@ pd[2*i + 0] = (pd[i] >> 4) * 0x11; } } - pd += s->image_linesize; + pd += p->linesize[0]; } } } @@ -973,6 +986,11 @@ return AVERROR_INVALIDDATA; } + if (s->pic_state & PNG_IDAT) { + av_log(avctx, AV_LOG_ERROR, "fctl after IDAT\n"); + return AVERROR_INVALIDDATA; + } + s->last_w = s->cur_w; s->last_h = s->cur_h; s->last_x_offset = s->x_offset; @@ -1004,7 +1022,7 @@ return AVERROR_INVALIDDATA; } - if ((sequence_number == 0 || !s->previous_picture.f->data[0]) && + if ((sequence_number == 0 || !s->last_picture.f->data[0]) && dispose_op == APNG_DISPOSE_OP_PREVIOUS) { // No previous frame to revert to for the first frame // Spec says to just treat it as a APNG_DISPOSE_OP_BACKGROUND @@ -1044,8 +1062,8 @@ for (j = 0; j < s->height; j++) { for (i = 0; i < ls; i++) pd[i] += pd_last[i]; - pd += s->image_linesize; - pd_last += s->image_linesize; + pd += p->linesize[0]; + pd_last += s->last_picture.f->linesize[0]; } } @@ -1056,8 +1074,12 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, AVFrame *p) { + uint8_t *dst = p->data[0]; + ptrdiff_t dst_stride = p->linesize[0]; + const uint8_t *src = s->last_picture.f->data[0]; + ptrdiff_t src_stride = s->last_picture.f->linesize[0]; + size_t x, y; - uint8_t *buffer; if (s->blend_op == APNG_BLEND_OP_OVER && avctx->pix_fmt != AV_PIX_FMT_RGBA && @@ -1068,37 +1090,42 @@ return AVERROR_PATCHWELCOME; } - buffer = av_malloc_array(s->image_linesize, s->height); - if (!buffer) - return AVERROR(ENOMEM); + ff_thread_await_progress(&s->last_picture, INT_MAX, 0); + + // need to reset a rectangle to background: + if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) { + av_fast_malloc(&s->background_buf, &s->background_buf_allocated, + src_stride * p->height); + if (!s->background_buf) + return AVERROR(ENOMEM); + memcpy(s->background_buf, src, src_stride * p->height); - // Do the disposal operation specified by the last frame on the frame - if (s->last_dispose_op != APNG_DISPOSE_OP_PREVIOUS) { - ff_thread_await_progress(&s->last_picture, INT_MAX, 0); - memcpy(buffer, s->last_picture.f->data[0], s->image_linesize * s->height); - - if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) - for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; ++y) - memset(buffer + s->image_linesize * y + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); + for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; y++) { + memset(s->background_buf + src_stride * y + + s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); + } - memcpy(s->previous_picture.f->data[0], buffer, s->image_linesize * s->height); - ff_thread_report_progress(&s->previous_picture, INT_MAX, 0); - } else { - ff_thread_await_progress(&s->previous_picture, INT_MAX, 0); - memcpy(buffer, s->previous_picture.f->data[0], s->image_linesize * s->height); + src = s->background_buf; } - // Perform blending - if (s->blend_op == APNG_BLEND_OP_SOURCE) { - for (y = s->y_offset; y < s->y_offset + s->cur_h; ++y) { - size_t row_start = s->image_linesize * y + s->bpp * s->x_offset; - memcpy(buffer + row_start, p->data[0] + row_start, s->bpp * s->cur_w); - } - } else { // APNG_BLEND_OP_OVER + // copy unchanged rectangles from the last frame + for (y = 0; y < s->y_offset; y++) + memcpy(dst + y * dst_stride, src + y * src_stride, p->width * s->bpp); + for (y = s->y_offset; y < s->y_offset + s->cur_h; y++) { + memcpy(dst + y * dst_stride, src + y * src_stride, s->x_offset * s->bpp); + memcpy(dst + y * dst_stride + (s->x_offset + s->cur_w) * s->bpp, + src + y * src_stride + (s->x_offset + s->cur_w) * s->bpp, + (p->width - s->cur_w - s->x_offset) * s->bpp); + } + for (y = s->y_offset + s->cur_h; y < p->height; y++) + memcpy(dst + y * dst_stride, src + y * src_stride, p->width * s->bpp); + + if (s->blend_op == APNG_BLEND_OP_OVER) { + // Perform blending for (y = s->y_offset; y < s->y_offset + s->cur_h; ++y) { - uint8_t *foreground = p->data[0] + s->image_linesize * y + s->bpp * s->x_offset; - uint8_t *background = buffer + s->image_linesize * y + s->bpp * s->x_offset; + uint8_t *foreground = dst + dst_stride * y + s->bpp * s->x_offset; + const uint8_t *background = src + src_stride * y + s->bpp * s->x_offset; for (x = s->x_offset; x < s->x_offset + s->cur_w; ++x, foreground += s->bpp, background += s->bpp) { size_t b; uint8_t foreground_alpha, background_alpha, output_alpha; @@ -1125,18 +1152,17 @@ break; } - if (foreground_alpha == 0) + if (foreground_alpha == 255) continue; - if (foreground_alpha == 255) { - memcpy(background, foreground, s->bpp); + if (foreground_alpha == 0) { + memcpy(foreground, background, s->bpp); continue; } if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { // TODO: Alpha blending with PAL8 will likely need the entire image converted over to RGBA first avpriv_request_sample(avctx, "Alpha blending palette samples"); - background[0] = foreground[0]; continue; } @@ -1154,22 +1180,18 @@ } } output[b] = output_alpha; - memcpy(background, output, s->bpp); + memcpy(foreground, output, s->bpp); } } } - // Copy blended buffer into the frame and free - memcpy(p->data[0], buffer, s->image_linesize * s->height); - av_free(buffer); - return 0; } static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, - AVFrame *p, AVPacket *avpkt) + AVFrame *p, const AVPacket *avpkt) { - AVDictionary **metadatap = NULL; + const AVCRC *crc_tab = av_crc_get_table(AV_CRC_32_IEEE_LE); uint32_t tag, length; int decode_next_dat = 0; int i, ret; @@ -1198,11 +1220,26 @@ } length = bytestream2_get_be32(&s->gb); - if (length > 0x7fffffff || length > bytestream2_get_bytes_left(&s->gb)) { + if (length > 0x7fffffff || length + 8 > bytestream2_get_bytes_left(&s->gb)) { av_log(avctx, AV_LOG_ERROR, "chunk too big\n"); ret = AVERROR_INVALIDDATA; goto fail; } + if (avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_IGNORE_ERR)) { + uint32_t crc_sig = AV_RB32(s->gb.buffer + length + 4); + uint32_t crc_cal = ~av_crc(crc_tab, UINT32_MAX, s->gb.buffer, length + 4); + if (crc_sig ^ crc_cal) { + av_log(avctx, AV_LOG_ERROR, "CRC mismatch in chunk"); + if (avctx->err_recognition & AV_EF_EXPLODE) { + av_log(avctx, AV_LOG_ERROR, ", quitting\n"); + ret = AVERROR_INVALIDDATA; + goto fail; + } + av_log(avctx, AV_LOG_ERROR, ", skipping\n"); + bytestream2_skip(&s->gb, 4); /* tag */ + goto skip_tag; + } + } tag = bytestream2_get_le32(&s->gb); if (avctx->debug & FF_DEBUG_STARTCODE) av_log(avctx, AV_LOG_DEBUG, "png: tag=%s length=%u\n", @@ -1222,7 +1259,6 @@ } } - metadatap = &p->metadata; switch (tag) { case MKTAG('I', 'H', 'D', 'R'): if ((ret = decode_ihdr_chunk(avctx, s, length)) < 0) @@ -1242,7 +1278,7 @@ case MKTAG('f', 'd', 'A', 'T'): if (!CONFIG_APNG_DECODER || avctx->codec_id != AV_CODEC_ID_APNG) goto skip_tag; - if (!decode_next_dat) { + if (!decode_next_dat || length < 4) { ret = AVERROR_INVALIDDATA; goto fail; } @@ -1264,24 +1300,20 @@ goto skip_tag; break; case MKTAG('t', 'E', 'X', 't'): - if (decode_text_chunk(s, length, 0, metadatap) < 0) + if (decode_text_chunk(s, length, 0) < 0) av_log(avctx, AV_LOG_WARNING, "Broken tEXt chunk\n"); bytestream2_skip(&s->gb, length + 4); break; case MKTAG('z', 'T', 'X', 't'): - if (decode_text_chunk(s, length, 1, metadatap) < 0) + if (decode_text_chunk(s, length, 1) < 0) av_log(avctx, AV_LOG_WARNING, "Broken zTXt chunk\n"); bytestream2_skip(&s->gb, length + 4); break; case MKTAG('s', 'T', 'E', 'R'): { int mode = bytestream2_get_byte(&s->gb); - AVStereo3D *stereo3d = av_stereo3d_create_side_data(p); - if (!stereo3d) - goto fail; if (mode == 0 || mode == 1) { - stereo3d->type = AV_STEREO3D_SIDEBYSIDE; - stereo3d->flags = mode ? 0 : AV_STEREO3D_FLAG_INVERT; + s->stereo_mode = mode; } else { av_log(avctx, AV_LOG_WARNING, "Unknown value in sTER chunk (%d)\n", mode); @@ -1290,27 +1322,22 @@ break; } case MKTAG('i', 'C', 'C', 'P'): { - if (decode_iccp_chunk(s, length, p) < 0) + if ((ret = decode_iccp_chunk(s, length, p)) < 0) goto fail; break; } case MKTAG('c', 'H', 'R', 'M'): { - AVMasteringDisplayMetadata *mdm = av_mastering_display_metadata_create_side_data(p); - if (!mdm) { - ret = AVERROR(ENOMEM); - goto fail; - } + s->have_chrm = 1; - mdm->white_point[0] = av_make_q(bytestream2_get_be32(&s->gb), 100000); - mdm->white_point[1] = av_make_q(bytestream2_get_be32(&s->gb), 100000); + s->white_point[0] = bytestream2_get_be32(&s->gb); + s->white_point[1] = bytestream2_get_be32(&s->gb); /* RGB Primaries */ for (i = 0; i < 3; i++) { - mdm->display_primaries[i][0] = av_make_q(bytestream2_get_be32(&s->gb), 100000); - mdm->display_primaries[i][1] = av_make_q(bytestream2_get_be32(&s->gb), 100000); + s->display_primaries[i][0] = bytestream2_get_be32(&s->gb); + s->display_primaries[i][1] = bytestream2_get_be32(&s->gb); } - mdm->has_primaries = 1; bytestream2_skip(&s->gb, 4); /* crc */ break; } @@ -1325,7 +1352,7 @@ if (ret < 0) return ret; - av_dict_set(&p->metadata, "gamma", gamma_str, AV_DICT_DONT_STRDUP_VAL); + av_dict_set(&s->frame_metadata, "gamma", gamma_str, AV_DICT_DONT_STRDUP_VAL); bytestream2_skip(&s->gb, 4); /* crc */ break; @@ -1353,6 +1380,9 @@ return 0; } + if (percent_missing(s) > avctx->discard_damaged_percentage) + return AVERROR_INVALIDDATA; + if (s->bits_per_pixel <= 4) handle_small_bpp(s, p); @@ -1365,17 +1395,37 @@ av_assert0(s->bit_depth > 1); for (y = 0; y < s->height; ++y) { - uint8_t *row = &s->image_buf[s->image_linesize * y]; + uint8_t *row = &p->data[0][p->linesize[0] * y]; - /* since we're updating in-place, we have to go from right to left */ - for (x = s->width; x > 0; --x) { - uint8_t *pixel = &row[s->bpp * (x - 1)]; - memmove(pixel, &row[raw_bpp * (x - 1)], raw_bpp); + if (s->bpp == 2 && byte_depth == 1) { + uint8_t *pixel = &row[2 * s->width - 1]; + uint8_t *rowp = &row[1 * s->width - 1]; + int tcolor = s->transparent_color_be[0]; + for (x = s->width; x > 0; --x) { + *pixel-- = *rowp == tcolor ? 0 : 0xff; + *pixel-- = *rowp--; + } + } else if (s->bpp == 4 && byte_depth == 1) { + uint8_t *pixel = &row[4 * s->width - 1]; + uint8_t *rowp = &row[3 * s->width - 1]; + int tcolor = AV_RL24(s->transparent_color_be); + for (x = s->width; x > 0; --x) { + *pixel-- = AV_RL24(rowp-2) == tcolor ? 0 : 0xff; + *pixel-- = *rowp--; + *pixel-- = *rowp--; + *pixel-- = *rowp--; + } + } else { + /* since we're updating in-place, we have to go from right to left */ + for (x = s->width; x > 0; --x) { + uint8_t *pixel = &row[s->bpp * (x - 1)]; + memmove(pixel, &row[raw_bpp * (x - 1)], raw_bpp); - if (!memcmp(pixel, s->transparent_color_be, raw_bpp)) { - memset(&pixel[raw_bpp], 0, byte_depth); - } else { - memset(&pixel[raw_bpp], 0xff, byte_depth); + if (!memcmp(pixel, s->transparent_color_be, raw_bpp)) { + memset(&pixel[raw_bpp], 0, byte_depth); + } else { + memset(&pixel[raw_bpp], 0xff, byte_depth); + } } } } @@ -1391,22 +1441,88 @@ if (CONFIG_PNG_DECODER && avctx->codec_id != AV_CODEC_ID_APNG) handle_p_frame_png(s, p); else if (CONFIG_APNG_DECODER && - s->previous_picture.f->width == p->width && - s->previous_picture.f->height== p->height && - s->previous_picture.f->format== p->format && avctx->codec_id == AV_CODEC_ID_APNG && (ret = handle_p_frame_apng(avctx, s, p)) < 0) goto fail; } } ff_thread_report_progress(&s->picture, INT_MAX, 0); - ff_thread_report_progress(&s->previous_picture, INT_MAX, 0); return 0; fail: ff_thread_report_progress(&s->picture, INT_MAX, 0); - ff_thread_report_progress(&s->previous_picture, INT_MAX, 0); + return ret; +} + +static void clear_frame_metadata(PNGDecContext *s) +{ + av_freep(&s->iccp_data); + s->iccp_data_len = 0; + s->iccp_name[0] = 0; + + s->stereo_mode = -1; + + s->have_chrm = 0; + + av_dict_free(&s->frame_metadata); +} + +static int output_frame(PNGDecContext *s, AVFrame *f, + const AVFrame *src) +{ + int ret; + + ret = av_frame_ref(f, src); + if (ret < 0) + return ret; + + if (s->iccp_data) { + AVFrameSideData *sd = av_frame_new_side_data(f, AV_FRAME_DATA_ICC_PROFILE, s->iccp_data_len); + if (!sd) { + ret = AVERROR(ENOMEM); + goto fail; + } + memcpy(sd->data, s->iccp_data, s->iccp_data_len); + + av_dict_set(&sd->metadata, "name", s->iccp_name, 0); + } + + if (s->stereo_mode >= 0) { + AVStereo3D *stereo3d = av_stereo3d_create_side_data(f); + if (!stereo3d) { + ret = AVERROR(ENOMEM); + goto fail; + } + + stereo3d->type = AV_STEREO3D_SIDEBYSIDE; + stereo3d->flags = s->stereo_mode ? 0 : AV_STEREO3D_FLAG_INVERT; + } + + if (s->have_chrm) { + AVMasteringDisplayMetadata *mdm = av_mastering_display_metadata_create_side_data(f); + if (!mdm) { + ret = AVERROR(ENOMEM); + goto fail; + } + + mdm->white_point[0] = av_make_q(s->white_point[0], 100000); + mdm->white_point[1] = av_make_q(s->white_point[1], 100000); + + /* RGB Primaries */ + for (int i = 0; i < 3; i++) { + mdm->display_primaries[i][0] = av_make_q(s->display_primaries[i][0], 100000); + mdm->display_primaries[i][1] = av_make_q(s->display_primaries[i][1], 100000); + } + + mdm->has_primaries = 1; + } + + FFSWAP(AVDictionary*, f->metadata, s->frame_metadata); + + return 0; +fail: + av_frame_unref(f); return ret; } @@ -1418,13 +1534,12 @@ PNGDecContext *const s = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame *p; + AVFrame *dst_frame = data; + AVFrame *p = s->picture.f; int64_t sig; int ret; - ff_thread_release_buffer(avctx, &s->last_picture); - FFSWAP(ThreadFrame, s->picture, s->last_picture); - p = s->picture.f; + clear_frame_metadata(s); bytestream2_init(&s->gb, buf, buf_size); @@ -1459,9 +1574,15 @@ goto the_end; } - if ((ret = av_frame_ref(data, s->picture.f)) < 0) + ret = output_frame(s, dst_frame, s->picture.f); + if (ret < 0) goto the_end; + if (!(avctx->active_thread_type & FF_THREAD_FRAME)) { + ff_thread_release_buffer(avctx, &s->last_picture); + FFSWAP(ThreadFrame, s->picture, s->last_picture); + } + *got_frame = 1; ret = bytestream2_tell(&s->gb); @@ -1478,12 +1599,11 @@ AVPacket *avpkt) { PNGDecContext *const s = avctx->priv_data; + AVFrame *dst_frame = data; int ret; - AVFrame *p; + AVFrame *p = s->picture.f; - ff_thread_release_buffer(avctx, &s->last_picture); - FFSWAP(ThreadFrame, s->picture, s->last_picture); - p = s->picture.f; + clear_frame_metadata(s); if (!(s->hdr_state & PNG_IHDR)) { if (!avctx->extradata_size) @@ -1516,156 +1636,27 @@ ret = AVERROR_INVALIDDATA; goto end; } - if ((ret = av_frame_ref(data, s->picture.f)) < 0) - goto end; - *got_frame = 1; - ret = bytestream2_tell(&s->gb); - -end: - inflateEnd(&s->zstream); - return ret; -} -#endif - -#if CONFIG_LSCR_DECODER -static int decode_frame_lscr(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) -{ - PNGDecContext *const s = avctx->priv_data; - GetByteContext *gb = &s->gb; - AVFrame *frame = data; - int ret, nb_blocks, offset = 0; - - if (avpkt->size < 2) - return AVERROR_INVALIDDATA; - - bytestream2_init(gb, avpkt->data, avpkt->size); - - if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) - return ret; - - nb_blocks = bytestream2_get_le16(gb); - if (bytestream2_get_bytes_left(gb) < 2 + nb_blocks * (12 + 8)) - return AVERROR_INVALIDDATA; - - if (s->last_picture.f->data[0]) { - ret = av_frame_copy(frame, s->last_picture.f); - if (ret < 0) - return ret; - } - - for (int b = 0; b < nb_blocks; b++) { - int x, y, x2, y2, w, h, left; - uint32_t csize, size; - - s->zstream.zalloc = ff_png_zalloc; - s->zstream.zfree = ff_png_zfree; - s->zstream.opaque = NULL; - - if ((ret = inflateInit(&s->zstream)) != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret); - ret = AVERROR_EXTERNAL; - goto end; - } - - bytestream2_seek(gb, 2 + b * 12, SEEK_SET); - - x = bytestream2_get_le16(gb); - y = bytestream2_get_le16(gb); - x2 = bytestream2_get_le16(gb); - y2 = bytestream2_get_le16(gb); - s->width = s->cur_w = w = x2-x; - s->height = s->cur_h = h = y2-y; - - if (w <= 0 || x < 0 || x >= avctx->width || w + x > avctx->width || - h <= 0 || y < 0 || y >= avctx->height || h + y > avctx->height) { - ret = AVERROR_INVALIDDATA; - goto end; - } - - size = bytestream2_get_le32(gb); - - frame->key_frame = (nb_blocks == 1) && - (w == avctx->width) && - (h == avctx->height) && - (x == 0) && (y == 0); - - bytestream2_seek(gb, 2 + nb_blocks * 12 + offset, SEEK_SET); - csize = bytestream2_get_be32(gb); - if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T')) { - ret = AVERROR_INVALIDDATA; - goto end; - } - - offset += size; - left = size; - - s->y = 0; - s->row_size = w * 3; - - av_fast_padded_malloc(&s->buffer, &s->buffer_size, s->row_size + 16); - if (!s->buffer) { - ret = AVERROR(ENOMEM); - goto end; - } - - av_fast_padded_malloc(&s->last_row, &s->last_row_size, s->row_size); - if (!s->last_row) { - ret = AVERROR(ENOMEM); - goto end; - } - - s->crow_size = w * 3 + 1; - s->crow_buf = s->buffer + 15; - s->zstream.avail_out = s->crow_size; - s->zstream.next_out = s->crow_buf; - s->image_buf = frame->data[0] + (avctx->height - y - 1) * frame->linesize[0] + x * 3; - s->image_linesize =-frame->linesize[0]; - s->bpp = 3; - s->pic_state = 0; + ret = output_frame(s, dst_frame, s->picture.f); + if (ret < 0) + goto end; - while (left > 16) { - ret = png_decode_idat(s, csize); - if (ret < 0) - goto end; - left -= csize + 16; - if (left > 16) { - bytestream2_skip(gb, 4); - csize = bytestream2_get_be32(gb); - if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T')) { - ret = AVERROR_INVALIDDATA; - goto end; - } - } + if (!(avctx->active_thread_type & FF_THREAD_FRAME)) { + if (s->dispose_op == APNG_DISPOSE_OP_PREVIOUS) { + ff_thread_release_buffer(avctx, &s->picture); + } else if (s->dispose_op == APNG_DISPOSE_OP_NONE) { + ff_thread_release_buffer(avctx, &s->last_picture); + FFSWAP(ThreadFrame, s->picture, s->last_picture); } - - inflateEnd(&s->zstream); } - frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; - - av_frame_unref(s->last_picture.f); - if ((ret = av_frame_ref(s->last_picture.f, frame)) < 0) - return ret; - *got_frame = 1; + ret = bytestream2_tell(&s->gb); + end: inflateEnd(&s->zstream); - - if (ret < 0) - return ret; - return avpkt->size; -} - -static void decode_flush(AVCodecContext *avctx) -{ - PNGDecContext *s = avctx->priv_data; - - av_frame_unref(s->last_picture.f); + return ret; } - #endif #if HAVE_THREADS @@ -1673,16 +1664,14 @@ { PNGDecContext *psrc = src->priv_data; PNGDecContext *pdst = dst->priv_data; + ThreadFrame *src_frame = NULL; int ret; if (dst == src) return 0; - ff_thread_release_buffer(dst, &pdst->picture); - if (psrc->picture.f->data[0] && - (ret = ff_thread_ref_frame(&pdst->picture, &psrc->picture)) < 0) - return ret; if (CONFIG_APNG_DECODER && dst->codec_id == AV_CODEC_ID_APNG) { + pdst->width = psrc->width; pdst->height = psrc->height; pdst->bit_depth = psrc->bit_depth; @@ -1702,15 +1691,15 @@ memcpy(pdst->palette, psrc->palette, sizeof(pdst->palette)); pdst->hdr_state |= psrc->hdr_state; + } - ff_thread_release_buffer(dst, &pdst->last_picture); - if (psrc->last_picture.f->data[0] && - (ret = ff_thread_ref_frame(&pdst->last_picture, &psrc->last_picture)) < 0) - return ret; + src_frame = psrc->dispose_op == APNG_DISPOSE_OP_NONE ? + &psrc->picture : &psrc->last_picture; - ff_thread_release_buffer(dst, &pdst->previous_picture); - if (psrc->previous_picture.f->data[0] && - (ret = ff_thread_ref_frame(&pdst->previous_picture, &psrc->previous_picture)) < 0) + ff_thread_release_buffer(dst, &pdst->last_picture); + if (src_frame && src_frame->f->data[0]) { + ret = ff_thread_ref_frame(&pdst->last_picture, src_frame); + if (ret < 0) return ret; } @@ -1724,24 +1713,16 @@ avctx->color_range = AVCOL_RANGE_JPEG; - if (avctx->codec_id == AV_CODEC_ID_LSCR) - avctx->pix_fmt = AV_PIX_FMT_BGR24; - s->avctx = avctx; - s->previous_picture.f = av_frame_alloc(); s->last_picture.f = av_frame_alloc(); s->picture.f = av_frame_alloc(); - if (!s->previous_picture.f || !s->last_picture.f || !s->picture.f) { - av_frame_free(&s->previous_picture.f); + if (!s->last_picture.f || !s->picture.f) { av_frame_free(&s->last_picture.f); av_frame_free(&s->picture.f); return AVERROR(ENOMEM); } - if (!avctx->internal->is_copy) { - avctx->internal->allocate_progress = 1; - ff_pngdsp_init(&s->dsp); - } + ff_pngdsp_init(&s->dsp); return 0; } @@ -1750,8 +1731,6 @@ { PNGDecContext *s = avctx->priv_data; - ff_thread_release_buffer(avctx, &s->previous_picture); - av_frame_free(&s->previous_picture.f); ff_thread_release_buffer(avctx, &s->last_picture); av_frame_free(&s->last_picture.f); ff_thread_release_buffer(avctx, &s->picture); @@ -1762,6 +1741,10 @@ s->last_row_size = 0; av_freep(&s->tmp_row); s->tmp_row_size = 0; + av_freep(&s->background_buf); + + av_freep(&s->iccp_data); + av_dict_free(&s->frame_metadata); return 0; } @@ -1776,10 +1759,10 @@ .init = png_dec_init, .close = png_dec_end, .decode = decode_frame_apng, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(png_dec_init), .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_ALLOCATE_PROGRESS, }; #endif @@ -1793,25 +1776,9 @@ .init = png_dec_init, .close = png_dec_end, .decode = decode_frame_png, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(png_dec_init), .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_THREADSAFE, -}; -#endif - -#if CONFIG_LSCR_DECODER -AVCodec ff_lscr_decoder = { - .name = "lscr", - .long_name = NULL_IF_CONFIG_SMALL("LEAD Screen Capture"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_LSCR, - .priv_data_size = sizeof(PNGDecContext), - .init = png_dec_init, - .close = png_dec_end, - .decode = decode_frame_lscr, - .flush = decode_flush, - .capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_ALLOCATE_PROGRESS, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/pngenc.c ffmpeg-4.4/libavcodec/pngenc.c --- ffmpeg-4.2.2/libavcodec/pngenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pngenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -741,7 +741,7 @@ diffFrame->format = pict->format; diffFrame->width = pict->width; diffFrame->height = pict->height; - if ((ret = av_frame_get_buffer(diffFrame, 32)) < 0) + if ((ret = av_frame_get_buffer(diffFrame, 0)) < 0) goto fail; original_bytestream = s->bytestream; @@ -956,7 +956,7 @@ s->prev_frame->format = pict->format; s->prev_frame->width = pict->width; s->prev_frame->height = pict->height; - if ((ret = av_frame_get_buffer(s->prev_frame, 32)) < 0) + if ((ret = av_frame_get_buffer(s->prev_frame, 0)) < 0) return ret; } @@ -1146,7 +1146,7 @@ .init = png_enc_init, .close = png_enc_close, .encode2 = encode_png, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_RGBA64BE, @@ -1174,7 +1174,7 @@ AV_PIX_FMT_PAL8, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_YA16BE, - AV_PIX_FMT_MONOBLACK, AV_PIX_FMT_NONE + AV_PIX_FMT_NONE }, .priv_class = &apngenc_class, }; diff -Nru ffmpeg-4.2.2/libavcodec/png.h ffmpeg-4.4/libavcodec/png.h --- ffmpeg-4.2.2/libavcodec/png.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/png.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,8 @@ #include +#include "pngdsp.h" + #define PNG_COLOR_MASK_PALETTE 1 #define PNG_COLOR_MASK_COLOR 2 #define PNG_COLOR_MASK_ALPHA 4 @@ -61,4 +63,7 @@ void ff_add_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, int w, int bpp); +void ff_png_filter_row(PNGDSPContext *dsp, uint8_t *dst, int filter_type, + uint8_t *src, uint8_t *last, int size, int bpp); + #endif /* AVCODEC_PNG_H */ diff -Nru ffmpeg-4.2.2/libavcodec/png_parser.c ffmpeg-4.4/libavcodec/png_parser.c --- ffmpeg-4.2.2/libavcodec/png_parser.c 2016-03-29 02:25:21.000000000 +0000 +++ ffmpeg-4.4/libavcodec/png_parser.c 2020-07-11 10:39:30.000000000 +0000 @@ -45,6 +45,7 @@ s->pict_type = AV_PICTURE_TYPE_NONE; *poutbuf_size = 0; + *poutbuf = NULL; if (!ppc->pc.frame_start_found) { uint64_t state64 = ppc->pc.state64; diff -Nru ffmpeg-4.2.2/libavcodec/pnm.c ffmpeg-4.4/libavcodec/pnm.c --- ffmpeg-4.2.2/libavcodec/pnm.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pnm.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,7 +22,9 @@ #include #include +#include "libavutil/avassert.h" #include "libavutil/imgutils.h" +#include "libavutil/avstring.h" #include "avcodec.h" #include "internal.h" #include "pnm.h" @@ -57,8 +59,6 @@ c = *bs++; } *s = '\0'; - while (bs < end && !pnm_space(c)) - c = *bs++; sc->bytestream = bs; } @@ -68,12 +68,24 @@ int h, w, depth, maxval; int ret; - pnm_get(s, buf1, sizeof(buf1)); - if(buf1[0] != 'P') + if (s->bytestream_end - s->bytestream < 3 || + s->bytestream[0] != 'P' || + (s->bytestream[1] < '1' || + s->bytestream[1] > '7' && + s->bytestream[1] != 'f' && + s->bytestream[1] != 'F')) { + s->bytestream += s->bytestream_end > s->bytestream; + s->bytestream += s->bytestream_end > s->bytestream; return AVERROR_INVALIDDATA; + } + pnm_get(s, buf1, sizeof(buf1)); s->type= buf1[1]-'0'; - if (s->type==1 || s->type==4) { + if (buf1[1] == 'F') { + avctx->pix_fmt = AV_PIX_FMT_GBRPF32; + } else if (buf1[1] == 'f') { + avctx->pix_fmt = AV_PIX_FMT_GRAYF32; + } else if (s->type==1 || s->type==4) { avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; } else if (s->type==2 || s->type==5) { if (avctx->codec_id == AV_CODEC_ID_PGMYUV) @@ -155,7 +167,7 @@ } return 0; } else { - return AVERROR_INVALIDDATA; + av_assert0(0); } pnm_get(s, buf1, sizeof(buf1)); w = atoi(buf1); @@ -168,7 +180,16 @@ if (ret < 0) return ret; - if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE && avctx->pix_fmt != AV_PIX_FMT_MONOBLACK) { + if (avctx->pix_fmt == AV_PIX_FMT_GBRPF32 || avctx->pix_fmt == AV_PIX_FMT_GRAYF32) { + pnm_get(s, buf1, sizeof(buf1)); + if (av_sscanf(buf1, "%f", &s->scale) != 1 || s->scale == 0.0 || !isfinite(s->scale)) { + av_log(avctx, AV_LOG_ERROR, "Invalid scale.\n"); + return AVERROR_INVALIDDATA; + } + s->endian = s->scale < 0.f; + s->scale = fabsf(s->scale); + s->maxval = (1ULL << 32) - 1; + } else if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE && avctx->pix_fmt != AV_PIX_FMT_MONOBLACK) { pnm_get(s, buf1, sizeof(buf1)); s->maxval = atoi(buf1); if (s->maxval <= 0 || s->maxval > UINT16_MAX) { @@ -200,7 +221,8 @@ return AVERROR_INVALIDDATA; /* more check if YUV420 */ - if (av_pix_fmt_desc_get(avctx->pix_fmt)->flags & AV_PIX_FMT_FLAG_PLANAR) { + if ((av_pix_fmt_desc_get(avctx->pix_fmt)->flags & AV_PIX_FMT_FLAG_PLANAR) && + avctx->pix_fmt != AV_PIX_FMT_GBRPF32) { if ((avctx->width & 1) != 0) return AVERROR_INVALIDDATA; h = (avctx->height * 2); diff -Nru ffmpeg-4.2.2/libavcodec/pnmdec.c ffmpeg-4.4/libavcodec/pnmdec.c --- ffmpeg-4.2.2/libavcodec/pnmdec.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pnmdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -46,6 +46,7 @@ int i, j, k, n, linesize, h, upgrade = 0, is_mono = 0; unsigned char *ptr; int components, sample_len, ret; + float scale; s->bytestream_start = s->bytestream = (uint8_t *)buf; @@ -132,7 +133,7 @@ init_put_bits(&pb, ptr, linesize); for(j=0; jwidth * components; j++){ unsigned int c=0; - int v=0; + unsigned v=0; if(s->type < 4) while(s->bytestream < s->bytestream_end && (*s->bytestream < '0' || *s->bytestream > '9' )) s->bytestream++; @@ -143,7 +144,7 @@ v = (*s->bytestream++)&1; } else { /* read a sequence of digits */ - for (k = 0; k < 5 && c <= 9; k += 1) { + for (k = 0; k < 6 && c <= 9; k += 1) { v = 10*v + c; c = (*s->bytestream++) - '0'; } @@ -172,7 +173,7 @@ } else if (upgrade == 2) { unsigned int j, v, f = (65535 * 32768 + s->maxval / 2) / s->maxval; for (j = 0; j < n / 2; j++) { - v = av_be2ne16(((uint16_t *)s->bytestream)[j]); + v = AV_RB16(s->bytestream + 2*j); ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15; } } @@ -226,7 +227,7 @@ return AVERROR_INVALIDDATA; for (i = 0; i < avctx->height; i++) { for (j = 0; j < n / 2; j++) { - v = av_be2ne16(((uint16_t *)s->bytestream)[j]); + v = AV_RB16(s->bytestream + 2*j); ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15; } s->bytestream += n; @@ -238,13 +239,13 @@ h = avctx->height >> 1; for (i = 0; i < h; i++) { for (j = 0; j < n / 2; j++) { - v = av_be2ne16(((uint16_t *)s->bytestream)[j]); + v = AV_RB16(s->bytestream + 2*j); ptr1[j] = (v * f + 16384) >> 15; } s->bytestream += n; for (j = 0; j < n / 2; j++) { - v = av_be2ne16(((uint16_t *)s->bytestream)[j]); + v = AV_RB16(s->bytestream + 2*j); ptr2[j] = (v * f + 16384) >> 15; } s->bytestream += n; @@ -254,6 +255,72 @@ } } break; + case AV_PIX_FMT_GBRPF32: + if (avctx->width * avctx->height * 12 > s->bytestream_end - s->bytestream) + return AVERROR_INVALIDDATA; + scale = 1.f / s->scale; + if (s->endian) { + float *r, *g, *b; + + r = (float *)p->data[2]; + g = (float *)p->data[0]; + b = (float *)p->data[1]; + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + r[j] = av_int2float(AV_RL32(s->bytestream+0)) * scale; + g[j] = av_int2float(AV_RL32(s->bytestream+4)) * scale; + b[j] = av_int2float(AV_RL32(s->bytestream+8)) * scale; + s->bytestream += 12; + } + + r += p->linesize[2] / 4; + g += p->linesize[0] / 4; + b += p->linesize[1] / 4; + } + } else { + float *r, *g, *b; + + r = (float *)p->data[2]; + g = (float *)p->data[0]; + b = (float *)p->data[1]; + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + r[j] = av_int2float(AV_RB32(s->bytestream+0)) * scale; + g[j] = av_int2float(AV_RB32(s->bytestream+4)) * scale; + b[j] = av_int2float(AV_RB32(s->bytestream+8)) * scale; + s->bytestream += 12; + } + + r += p->linesize[2] / 4; + g += p->linesize[0] / 4; + b += p->linesize[1] / 4; + } + } + break; + case AV_PIX_FMT_GRAYF32: + if (avctx->width * avctx->height * 4 > s->bytestream_end - s->bytestream) + return AVERROR_INVALIDDATA; + scale = 1.f / s->scale; + if (s->endian) { + float *g = (float *)p->data[0]; + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + g[j] = av_int2float(AV_RL32(s->bytestream)) * scale; + s->bytestream += 4; + } + g += p->linesize[0] / 4; + } + } else { + float *g = (float *)p->data[0]; + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + g[j] = av_int2float(AV_RB32(s->bytestream)) * scale; + s->bytestream += 4; + } + g += p->linesize[0] / 4; + } + } + break; } *got_frame = 1; @@ -318,5 +385,17 @@ .priv_data_size = sizeof(PNMContext), .decode = pnm_decode_frame, .capabilities = AV_CODEC_CAP_DR1, +}; +#endif + +#if CONFIG_PFM_DECODER +AVCodec ff_pfm_decoder = { + .name = "pfm", + .long_name = NULL_IF_CONFIG_SMALL("PFM (Portable FloatMap) image"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PFM, + .priv_data_size = sizeof(PNMContext), + .decode = pnm_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/pnmenc.c ffmpeg-4.4/libavcodec/pnmenc.c --- ffmpeg-4.2.2/libavcodec/pnmenc.c 2018-07-17 09:27:41.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pnmenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" #include "avcodec.h" @@ -77,19 +78,46 @@ n = avctx->width * 2; h1 = (h * 3) / 2; break; + case AV_PIX_FMT_GBRPF32: + c = 'F'; + n = avctx->width * 4; + break; default: return -1; } snprintf(bytestream, bytestream_end - bytestream, "P%c\n%d %d\n", c, avctx->width, h1); bytestream += strlen(bytestream); - if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE) { + if (avctx->pix_fmt == AV_PIX_FMT_GBRPF32) + snprintf(bytestream, bytestream_end - bytestream, + "%f\n", avctx->pix_fmt == AV_PIX_FMT_GBRPF32BE ? 1.f: -1.f); + bytestream += strlen(bytestream); + if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE && + avctx->pix_fmt != AV_PIX_FMT_GBRPF32) { int maxdepth = (1 << av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth) - 1; snprintf(bytestream, bytestream_end - bytestream, "%d\n", maxdepth); bytestream += strlen(bytestream); } + if (avctx->pix_fmt == AV_PIX_FMT_GBRPF32) { + float *r = (float *)p->data[2]; + float *g = (float *)p->data[0]; + float *b = (float *)p->data[1]; + + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + AV_WN32(bytestream + 0, av_float2int(r[j])); + AV_WN32(bytestream + 4, av_float2int(g[j])); + AV_WN32(bytestream + 8, av_float2int(b[j])); + bytestream += 12; + } + + r += p->linesize[2] / 4; + g += p->linesize[0] / 4; + b += p->linesize[1] / 4; + } + } else { ptr = p->data[0]; linesize = p->linesize[0]; for (i = 0; i < h; i++) { @@ -97,6 +125,7 @@ bytestream += n; ptr += linesize; } + } if (avctx->pix_fmt == AV_PIX_FMT_YUV420P || avctx->pix_fmt == AV_PIX_FMT_YUV420P16BE) { h >>= 1; @@ -142,6 +171,7 @@ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif @@ -156,6 +186,7 @@ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif @@ -170,6 +201,7 @@ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif @@ -183,5 +215,20 @@ .encode2 = pnm_encode_frame, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; +#endif + +#if CONFIG_PFM_ENCODER +AVCodec ff_pfm_encoder = { + .name = "pfm", + .long_name = NULL_IF_CONFIG_SMALL("PFM (Portable FloatMap) image"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PFM, + .init = pnm_encode_init, + .encode2 = pnm_encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_GBRPF32, + AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/pnm.h ffmpeg-4.4/libavcodec/pnm.h --- ffmpeg-4.2.2/libavcodec/pnm.h 2016-03-29 02:25:21.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pnm.h 2020-07-11 10:39:30.000000000 +0000 @@ -30,6 +30,8 @@ uint8_t *bytestream_end; int maxval; ///< maximum value of a pixel int type; + int endian; + float scale; } PNMContext; int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s); diff -Nru ffmpeg-4.2.2/libavcodec/pnm_parser.c ffmpeg-4.4/libavcodec/pnm_parser.c --- ffmpeg-4.2.2/libavcodec/pnm_parser.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pnm_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -41,8 +41,11 @@ int next = END_NOT_FOUND; int skip = 0; - for (; pc->overread > 0; pc->overread--) { - pc->buffer[pc->index++]= pc->buffer[pc->overread_index++]; + if (pc->overread > 0) { + memmove(pc->buffer + pc->index, pc->buffer + pc->overread_index, pc->overread); + pc->index += pc->overread; + pc->overread_index += pc->overread; + pc->overread = 0; } if (pnmpc->remaining_bytes) { @@ -106,8 +109,10 @@ if (next == END_NOT_FOUND) pnmpc->ascii_scan = sync - pnmctx.bytestream + skip; } else { - next = pnmctx.bytestream - pnmctx.bytestream_start + skip - + av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1); + int ret = av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1); + next = pnmctx.bytestream - pnmctx.bytestream_start + skip; + if (ret >= 0 && next + (uint64_t)ret <= INT_MAX) + next += ret; } if (next != END_NOT_FOUND && pnmctx.bytestream_start != buf + skip) next -= pc->index; diff -Nru ffmpeg-4.2.2/libavcodec/ppc/h264chroma_template.c ffmpeg-4.4/libavcodec/ppc/h264chroma_template.c --- ffmpeg-4.2.2/libavcodec/ppc/h264chroma_template.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ppc/h264chroma_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavutil/ppc/util_altivec.h" /* this code assume that stride % 16 == 0 */ diff -Nru ffmpeg-4.2.2/libavcodec/ppc/h264dsp.c ffmpeg-4.4/libavcodec/ppc/h264dsp.c --- ffmpeg-4.2.2/libavcodec/ppc/h264dsp.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ppc/h264dsp.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,7 +26,7 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/intreadwrite.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavutil/ppc/cpu.h" #include "libavutil/ppc/util_altivec.h" diff -Nru ffmpeg-4.2.2/libavcodec/ppc/h264qpel.c ffmpeg-4.4/libavcodec/ppc/h264qpel.c --- ffmpeg-4.2.2/libavcodec/ppc/h264qpel.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ppc/h264qpel.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #include "libavutil/ppc/cpu.h" #include "libavutil/ppc/util_altivec.h" diff -Nru ffmpeg-4.2.2/libavcodec/ppc/mpegaudiodsp_altivec.c ffmpeg-4.4/libavcodec/ppc/mpegaudiodsp_altivec.c --- ffmpeg-4.2.2/libavcodec/ppc/mpegaudiodsp_altivec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ppc/mpegaudiodsp_altivec.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/ppc/cpu.h" #include "libavutil/ppc/util_altivec.h" #include "libavcodec/mpegaudiodsp.h" diff -Nru ffmpeg-4.2.2/libavcodec/ppc/mpegvideo_altivec.c ffmpeg-4.4/libavcodec/ppc/mpegvideo_altivec.c --- ffmpeg-4.2.2/libavcodec/ppc/mpegvideo_altivec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ppc/mpegvideo_altivec.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,6 +28,7 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" +#include "libavutil/mem_internal.h" #include "libavutil/ppc/cpu.h" #include "libavutil/ppc/util_altivec.h" diff -Nru ffmpeg-4.2.2/libavcodec/ppc/mpegvideodsp.c ffmpeg-4.4/libavcodec/ppc/mpegvideodsp.c --- ffmpeg-4.2.2/libavcodec/ppc/mpegvideodsp.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ppc/mpegvideodsp.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,7 +21,7 @@ */ #include "libavutil/cpu.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavutil/ppc/cpu.h" #include "libavutil/ppc/util_altivec.h" diff -Nru ffmpeg-4.2.2/libavcodec/ppc/vp8dsp_altivec.c ffmpeg-4.4/libavcodec/ppc/vp8dsp_altivec.c --- ffmpeg-4.2.2/libavcodec/ppc/vp8dsp_altivec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ppc/vp8dsp_altivec.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,7 +23,7 @@ #include "config.h" #include "libavutil/cpu.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavutil/ppc/cpu.h" #include "libavutil/ppc/util_altivec.h" diff -Nru ffmpeg-4.2.2/libavcodec/profiles.c ffmpeg-4.4/libavcodec/profiles.c --- ffmpeg-4.2.2/libavcodec/profiles.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/profiles.c 2021-04-08 21:28:39.000000000 +0000 @@ -74,6 +74,12 @@ { FF_PROFILE_UNKNOWN }, }; +const AVProfile ff_vvc_profiles[] = { + { FF_PROFILE_VVC_MAIN_10, "Main 10" }, + { FF_PROFILE_VVC_MAIN_10_444, "Main 10 4:4:4" }, + { FF_PROFILE_UNKNOWN }, +}; + const AVProfile ff_hevc_profiles[] = { { FF_PROFILE_HEVC_MAIN, "Main" }, { FF_PROFILE_HEVC_MAIN_10, "Main 10" }, @@ -99,7 +105,6 @@ { FF_PROFILE_MPEG2_MAIN, "Main" }, { FF_PROFILE_MPEG2_SIMPLE, "Simple" }, { FF_PROFILE_RESERVED, "Reserved" }, - { FF_PROFILE_RESERVED, "Reserved" }, { FF_PROFILE_UNKNOWN }, }; diff -Nru ffmpeg-4.2.2/libavcodec/profiles.h ffmpeg-4.4/libavcodec/profiles.h --- ffmpeg-4.2.2/libavcodec/profiles.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/profiles.h 2021-04-08 21:28:39.000000000 +0000 @@ -20,12 +20,48 @@ #define AVCODEC_PROFILES_H #include "avcodec.h" +#include "libavutil/opt.h" + +#define FF_AVCTX_PROFILE_OPTION(name, description, type, value) \ + {name, description, 0, AV_OPT_TYPE_CONST, {.i64 = value }, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_## type ##_PARAM, "avctx.profile"}, + +#define FF_AAC_PROFILE_OPTS \ + FF_AVCTX_PROFILE_OPTION("aac_main", NULL, AUDIO, FF_PROFILE_AAC_MAIN)\ + FF_AVCTX_PROFILE_OPTION("aac_low", NULL, AUDIO, FF_PROFILE_AAC_LOW)\ + FF_AVCTX_PROFILE_OPTION("aac_ssr", NULL, AUDIO, FF_PROFILE_AAC_SSR)\ + FF_AVCTX_PROFILE_OPTION("aac_ltp", NULL, AUDIO, FF_PROFILE_AAC_LTP)\ + FF_AVCTX_PROFILE_OPTION("aac_he", NULL, AUDIO, FF_PROFILE_AAC_HE)\ + FF_AVCTX_PROFILE_OPTION("aac_he_v2", NULL, AUDIO, FF_PROFILE_AAC_HE_V2)\ + FF_AVCTX_PROFILE_OPTION("aac_ld", NULL, AUDIO, FF_PROFILE_AAC_LD)\ + FF_AVCTX_PROFILE_OPTION("aac_eld", NULL, AUDIO, FF_PROFILE_AAC_ELD)\ + FF_AVCTX_PROFILE_OPTION("mpeg2_aac_low", NULL, AUDIO, FF_PROFILE_MPEG2_AAC_LOW)\ + FF_AVCTX_PROFILE_OPTION("mpeg2_aac_he", NULL, AUDIO, FF_PROFILE_MPEG2_AAC_HE)\ + +#define FF_MPEG4_PROFILE_OPTS \ + FF_AVCTX_PROFILE_OPTION("mpeg4_sp", NULL, VIDEO, FF_PROFILE_MPEG4_SIMPLE)\ + FF_AVCTX_PROFILE_OPTION("mpeg4_core", NULL, VIDEO, FF_PROFILE_MPEG4_CORE)\ + FF_AVCTX_PROFILE_OPTION("mpeg4_main", NULL, VIDEO, FF_PROFILE_MPEG4_MAIN)\ + FF_AVCTX_PROFILE_OPTION("mpeg4_asp", NULL, VIDEO, FF_PROFILE_MPEG4_ADVANCED_SIMPLE)\ + +#define FF_MPEG2_PROFILE_OPTS \ + FF_AVCTX_PROFILE_OPTION("422", NULL, VIDEO, FF_PROFILE_MPEG2_422)\ + FF_AVCTX_PROFILE_OPTION("high", NULL, VIDEO, FF_PROFILE_MPEG2_HIGH)\ + FF_AVCTX_PROFILE_OPTION("ss", NULL, VIDEO, FF_PROFILE_MPEG2_SS)\ + FF_AVCTX_PROFILE_OPTION("snr", NULL, VIDEO, FF_PROFILE_MPEG2_SNR_SCALABLE)\ + FF_AVCTX_PROFILE_OPTION("main", NULL, VIDEO, FF_PROFILE_MPEG2_MAIN)\ + FF_AVCTX_PROFILE_OPTION("simple", NULL, VIDEO, FF_PROFILE_MPEG2_SIMPLE)\ + +#define FF_AV1_PROFILE_OPTS \ + FF_AVCTX_PROFILE_OPTION("main", NULL, VIDEO, FF_PROFILE_AV1_MAIN)\ + FF_AVCTX_PROFILE_OPTION("high", NULL, VIDEO, FF_PROFILE_AV1_HIGH)\ + FF_AVCTX_PROFILE_OPTION("professional", NULL, VIDEO, FF_PROFILE_AV1_PROFESSIONAL)\ extern const AVProfile ff_aac_profiles[]; extern const AVProfile ff_dca_profiles[]; extern const AVProfile ff_dnxhd_profiles[]; extern const AVProfile ff_h264_profiles[]; extern const AVProfile ff_hevc_profiles[]; +extern const AVProfile ff_vvc_profiles[]; extern const AVProfile ff_jpeg2000_profiles[]; extern const AVProfile ff_mpeg2_video_profiles[]; extern const AVProfile ff_mpeg4_video_profiles[]; diff -Nru ffmpeg-4.2.2/libavcodec/proresdec2.c ffmpeg-4.4/libavcodec/proresdec2.c --- ffmpeg-4.2.2/libavcodec/proresdec2.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/proresdec2.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,8 @@ #define LONG_BITSTREAM_READER #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "get_bits.h" #include "idctdsp.h" @@ -289,7 +291,7 @@ } permute(ctx->qmat_chroma, ctx->prodsp.idct_permutation, ptr); } else { - memset(ctx->qmat_chroma, 4, 64); + memcpy(ctx->qmat_chroma, ctx->qmat_luma, 64); } return hdr_size; @@ -621,8 +623,8 @@ AVFrame *pic = ctx->frame; int i, hdr_size, qscale, log2_chroma_blocks_per_mb; int luma_stride, chroma_stride; - int y_data_size, u_data_size, v_data_size, a_data_size; - uint8_t *dest_y, *dest_u, *dest_v, *dest_a; + int y_data_size, u_data_size, v_data_size, a_data_size, offset; + uint8_t *dest_y, *dest_u, *dest_v; LOCAL_ALIGNED_16(int16_t, qmat_luma_scaled, [64]); LOCAL_ALIGNED_16(int16_t, qmat_chroma_scaled,[64]); int mb_x_shift; @@ -674,16 +676,16 @@ log2_chroma_blocks_per_mb = 1; } - dest_y = pic->data[0] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5); + offset = (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5); + dest_y = pic->data[0] + offset; dest_u = pic->data[1] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift); dest_v = pic->data[2] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift); - dest_a = pic->data[3] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5); if (ctx->frame_type && ctx->first_field ^ ctx->frame->top_field_first) { dest_y += pic->linesize[0]; dest_u += pic->linesize[1]; dest_v += pic->linesize[2]; - dest_a += pic->linesize[3]; + offset += pic->linesize[3]; } ret = decode_slice_luma(avctx, slice, (uint16_t*)dest_y, luma_stride, @@ -720,10 +722,12 @@ } /* decode alpha plane if available */ - if (ctx->alpha_info && pic->data[3] && a_data_size) + if (ctx->alpha_info && pic->data[3] && a_data_size) { + uint8_t *dest_a = pic->data[3] + offset; decode_slice_alpha(ctx, (uint16_t*)dest_a, luma_stride, buf + y_data_size + u_data_size + v_data_size, a_data_size, slice->mb_count); + } slice->ret = 0; return 0; @@ -807,17 +811,6 @@ return avpkt->size; } -#if HAVE_THREADS -static int decode_init_thread_copy(AVCodecContext *avctx) -{ - ProresContext *ctx = avctx->priv_data; - - ctx->slices = NULL; - - return 0; -} -#endif - static av_cold int decode_close(AVCodecContext *avctx) { ProresContext *ctx = avctx->priv_data; @@ -829,12 +822,11 @@ AVCodec ff_prores_decoder = { .name = "prores", - .long_name = NULL_IF_CONFIG_SMALL("ProRes (iCodec Pro)"), + .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_PRORES, .priv_data_size = sizeof(ProresContext), .init = decode_init, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), .close = decode_close, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, diff -Nru ffmpeg-4.2.2/libavcodec/proresenc_anatoliy.c ffmpeg-4.4/libavcodec/proresenc_anatoliy.c --- ffmpeg-4.2.2/libavcodec/proresenc_anatoliy.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/proresenc_anatoliy.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ * Known FOURCCs: 'ap4h' (444), 'apch' (HQ), 'apcn' (422), 'apcs' (LT), 'acpo' (Proxy) */ +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "avcodec.h" #include "dct.h" @@ -49,15 +50,16 @@ { FF_PROFILE_UNKNOWN } }; -static const int qp_start_table[6] = { 8, 3, 2, 1, 1, 1}; -static const int qp_end_table[6] = { 13, 9, 6, 6, 5, 4}; -static const int bitrate_table[6] = { 1000, 2100, 3500, 5400, 7000, 10000}; - -static const int valid_primaries[9] = { AVCOL_PRI_RESERVED0, AVCOL_PRI_BT709, AVCOL_PRI_UNSPECIFIED, AVCOL_PRI_BT470BG, - AVCOL_PRI_SMPTE170M, AVCOL_PRI_BT2020, AVCOL_PRI_SMPTE431, AVCOL_PRI_SMPTE432,INT_MAX }; -static const int valid_trc[4] = { AVCOL_TRC_RESERVED0, AVCOL_TRC_BT709, AVCOL_TRC_UNSPECIFIED, INT_MAX }; -static const int valid_colorspace[5] = { AVCOL_SPC_BT709, AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_SMPTE170M, - AVCOL_SPC_BT2020_NCL, INT_MAX }; +static const int qp_start_table[] = { 8, 3, 2, 1, 1, 1}; +static const int qp_end_table[] = { 13, 9, 6, 6, 5, 4}; +static const int bitrate_table[] = { 1000, 2100, 3500, 5400, 7000, 10000}; + +static const int valid_primaries[] = { AVCOL_PRI_RESERVED0, AVCOL_PRI_BT709, AVCOL_PRI_UNSPECIFIED, AVCOL_PRI_BT470BG, + AVCOL_PRI_SMPTE170M, AVCOL_PRI_BT2020, AVCOL_PRI_SMPTE431, AVCOL_PRI_SMPTE432, INT_MAX }; +static const int valid_trc[] = { AVCOL_TRC_RESERVED0, AVCOL_TRC_BT709, AVCOL_TRC_UNSPECIFIED, AVCOL_TRC_SMPTE2084, + AVCOL_TRC_ARIB_STD_B67, INT_MAX }; +static const int valid_colorspace[] = { AVCOL_SPC_BT709, AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_SMPTE170M, + AVCOL_SPC_BT2020_NCL, INT_MAX }; static const uint8_t QMAT_LUMA[6][64] = { { @@ -224,7 +226,7 @@ } #define QSCALE(qmat,ind,val) ((val) / ((qmat)[ind])) -#define TO_GOLOMB(val) (((val) << 1) ^ ((val) >> 31)) +#define TO_GOLOMB(val) (((val) * 2) ^ ((val) >> 31)) #define DIFF_SIGN(val, sign) (((val) >> 31) ^ (sign)) #define IS_NEGATIVE(val) ((((val) >> 31) ^ -1) + 1) #define TO_GOLOMB2(val,sign) ((val)==0 ? 0 : ((val) << 1) + (sign)) @@ -924,7 +926,7 @@ #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "vendor", "vendor ID", OFFSET(vendor), AV_OPT_TYPE_STRING, { .str = "fmpg" }, CHAR_MIN, CHAR_MAX, VE }, + { "vendor", "vendor ID", OFFSET(vendor), AV_OPT_TYPE_STRING, { .str = "fmpg" }, 0, 0, VE }, { NULL } }; @@ -952,9 +954,10 @@ .close = prores_encode_close, .encode2 = prores_encode_frame, .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE}, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .priv_class = &proresaw_enc_class, .profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; AVCodec ff_prores_encoder = { @@ -967,7 +970,8 @@ .close = prores_encode_close, .encode2 = prores_encode_frame, .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE}, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .priv_class = &prores_enc_class, .profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/proresenc_kostya.c ffmpeg-4.4/libavcodec/proresenc_kostya.c --- ffmpeg-4.2.2/libavcodec/proresenc_kostya.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/proresenc_kostya.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avcodec.h" @@ -1390,7 +1391,7 @@ { "4444xq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_4444XQ }, 0, 0, VE, "profile" }, { "vendor", "vendor ID", OFFSET(vendor), - AV_OPT_TYPE_STRING, { .str = "Lavc" }, CHAR_MIN, CHAR_MAX, VE }, + AV_OPT_TYPE_STRING, { .str = "Lavc" }, 0, 0, VE }, { "bits_per_mb", "desired bits per macroblock", OFFSET(bits_per_mb), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 8192, VE }, { "quant_mat", "quantiser matrix", OFFSET(quant_sel), AV_OPT_TYPE_INT, @@ -1428,7 +1429,7 @@ .init = encode_init, .close = encode_close, .encode2 = encode_frame, - .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE diff -Nru ffmpeg-4.2.2/libavcodec/prores_metadata_bsf.c ffmpeg-4.4/libavcodec/prores_metadata_bsf.c --- ffmpeg-4.2.2/libavcodec/prores_metadata_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/prores_metadata_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -28,7 +28,9 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" + #include "bsf.h" +#include "bsf_internal.h" typedef struct ProresMetadataContext { const AVClass *class; @@ -140,10 +142,12 @@ {"smpte431", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE431}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, {"smpte432", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE432}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, - {"color_trc", "select color transfer", OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_TRC_BT709, FLAGS, "color_trc"}, + {"color_trc", "select color transfer", OFFSET(transfer_characteristics), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_TRC_NB - 1, FLAGS, "color_trc"}, {"auto", "keep the same color transfer", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, FLAGS, "color_trc"}, {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, INT_MIN, INT_MAX, FLAGS, "color_trc"}, {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT709}, INT_MIN, INT_MAX, FLAGS, "color_trc"}, + {"smpte2084", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE2084}, INT_MIN, INT_MAX, FLAGS, "color_trc"}, + {"arib-std-b67", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_ARIB_STD_B67}, INT_MIN, INT_MAX, FLAGS, "color_trc"}, {"colorspace", "select colorspace", OFFSET(matrix_coefficients), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_SPC_BT2020_NCL, FLAGS, "colorspace"}, {"auto", "keep the same colorspace", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, FLAGS, "colorspace"}, diff -Nru ffmpeg-4.2.2/libavcodec/psd.c ffmpeg-4.4/libavcodec/psd.c --- ffmpeg-4.2.2/libavcodec/psd.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/psd.c 2020-07-11 10:39:30.000000000 +0000 @@ -211,11 +211,9 @@ case 2: avpriv_request_sample(s->avctx, "ZIP without predictor compression"); return AVERROR_PATCHWELCOME; - break; case 3: avpriv_request_sample(s->avctx, "ZIP with predictor compression"); return AVERROR_PATCHWELCOME; - break; default: av_log(s->avctx, AV_LOG_ERROR, "Unknown compression %d.\n", s->compression); return AVERROR_INVALIDDATA; diff -Nru ffmpeg-4.2.2/libavcodec/pthread.c ffmpeg-4.4/libavcodec/pthread.c --- ffmpeg-4.2.2/libavcodec/pthread.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pthread.c 2021-04-08 21:28:39.000000000 +0000 @@ -56,7 +56,7 @@ } else if (avctx->codec->capabilities & AV_CODEC_CAP_SLICE_THREADS && avctx->thread_type & FF_THREAD_SLICE) { avctx->active_thread_type = FF_THREAD_SLICE; - } else if (!(avctx->codec->capabilities & AV_CODEC_CAP_AUTO_THREADS)) { + } else if (!(avctx->codec->caps_internal & FF_CODEC_CAP_AUTO_THREADS)) { avctx->thread_count = 1; avctx->active_thread_type = 0; } diff -Nru ffmpeg-4.2.2/libavcodec/pthread_frame.c ffmpeg-4.4/libavcodec/pthread_frame.c --- ffmpeg-4.2.2/libavcodec/pthread_frame.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pthread_frame.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,7 +28,7 @@ #include #include "avcodec.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "internal.h" #include "pthread_internal.h" #include "thread.h" @@ -64,6 +64,12 @@ STATE_SETUP_FINISHED, }; +enum { + UNINITIALIZED, ///< Thread has not been created, AVCodec->close mustn't be called + NEEDS_CLOSE, ///< AVCodec->close needs to be called + INITIALIZED, ///< Thread has been properly set up +}; + /** * Context used by codec threads and stored in their AVCodecInternal thread_ctx. */ @@ -72,6 +78,7 @@ pthread_t thread; int thread_init; + unsigned pthread_init_cnt;///< Number of successfully initialized mutexes/conditions pthread_cond_t input_cond; ///< Used to wait for a new packet from the main thread. pthread_cond_t progress_cond; ///< Used by child threads to wait for progress to change. pthread_cond_t output_cond; ///< Used by the main thread to wait for frames to finish. @@ -81,7 +88,7 @@ AVCodecContext *avctx; ///< Context used to decode packets passed to this thread. - AVPacket avpkt; ///< Input packet (for decoding) or output (for encoding). + AVPacket *avpkt; ///< Input packet (for decoding) or output (for encoding). AVFrame *frame; ///< Output frame (for decoding) or input (for encoding). int got_frame; ///< The output of got_picture_ptr from the last avcodec_decode_video() call. @@ -89,19 +96,21 @@ atomic_int state; +#if FF_API_THREAD_SAFE_CALLBACKS /** * Array of frames passed to ff_thread_release_buffer(). * Frames are released after all threads referencing them are finished. */ - AVFrame *released_buffers; - int num_released_buffers; - int released_buffers_allocated; + AVFrame **released_buffers; + int num_released_buffers; + int released_buffers_allocated; AVFrame *requested_frame; ///< AVFrame the codec passed to get_buffer() int requested_flags; ///< flags passed to get_buffer() for requested_frame const enum AVPixelFormat *available_formats; ///< Format array for get_format() enum AVPixelFormat result_format; ///< get_format() result +#endif int die; ///< Set when the thread should exit. @@ -118,6 +127,7 @@ PerThreadContext *threads; ///< The contexts for each thread. PerThreadContext *prev_thread; ///< The last thread submit_packet() was called on. + unsigned pthread_init_cnt; ///< Number of successfully initialized mutexes/conditions pthread_mutex_t buffer_mutex; ///< Mutex used to protect get/release_buffer(). /** * This lock is used for ensuring threads run in serial when hwaccel @@ -137,8 +147,10 @@ */ } FrameThreadContext; +#if FF_API_THREAD_SAFE_CALLBACKS #define THREAD_SAFE_CALLBACKS(avctx) \ ((avctx)->thread_safe_callbacks || (avctx)->get_buffer2 == avcodec_default_get_buffer2) +#endif static void async_lock(FrameThreadContext *fctx) { @@ -178,8 +190,14 @@ if (p->die) break; - if (!codec->update_thread_context && THREAD_SAFE_CALLBACKS(avctx)) +FF_DISABLE_DEPRECATION_WARNINGS + if (!codec->update_thread_context +#if FF_API_THREAD_SAFE_CALLBACKS + && THREAD_SAFE_CALLBACKS(avctx) +#endif + ) ff_thread_finish_setup(avctx); +FF_ENABLE_DEPRECATION_WARNINGS /* If a decoder supports hwaccel, then it must call ff_get_format(). * Since that call must happen before ff_thread_finish_setup(), the @@ -198,10 +216,10 @@ av_frame_unref(p->frame); p->got_frame = 0; - p->result = codec->decode(avctx, p->frame, &p->got_frame, &p->avpkt); + p->result = codec->decode(avctx, p->frame, &p->got_frame, p->avpkt); if ((p->result < 0 || !p->got_frame) && p->frame->buf[0]) { - if (avctx->internal->allocate_progress) + if (avctx->codec->caps_internal & FF_CODEC_CAP_ALLOCATE_PROGRESS) av_log(avctx, AV_LOG_ERROR, "A frame threaded decoder did not " "free the frame on failure. This is a bug, please report it.\n"); av_frame_unref(p->frame); @@ -246,7 +264,7 @@ { int err = 0; - if (dst != src && (for_user || !(src->codec_descriptor->props & AV_CODEC_PROP_INTRA_ONLY))) { + if (dst != src && (for_user || src->codec->update_thread_context)) { dst->time_base = src->time_base; dst->framerate = src->framerate; dst->width = src->width; @@ -296,10 +314,13 @@ } dst->hwaccel_flags = src->hwaccel_flags; + + err = av_buffer_replace(&dst->internal->pool, src->internal->pool); + if (err < 0) + return err; } if (for_user) { - dst->delay = src->thread_count - 1; #if FF_API_CODED_FRAME FF_DISABLE_DEPRECATION_WARNINGS dst->coded_frame = src->coded_frame; @@ -322,7 +343,6 @@ */ static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) { -#define copy_fields(s, e) memcpy(&dst->s, &src->s, (char*)&dst->e - (char*)&dst->s); dst->flags = src->flags; dst->draw_horiz_band= src->draw_horiz_band; @@ -330,16 +350,22 @@ dst->opaque = src->opaque; dst->debug = src->debug; - dst->debug_mv = src->debug_mv; dst->slice_flags = src->slice_flags; dst->flags2 = src->flags2; + dst->export_side_data = src->export_side_data; - copy_fields(skip_loop_filter, subtitle_header); + dst->skip_loop_filter = src->skip_loop_filter; + dst->skip_idct = src->skip_idct; + dst->skip_frame = src->skip_frame; dst->frame_number = src->frame_number; dst->reordered_opaque = src->reordered_opaque; +#if FF_API_THREAD_SAFE_CALLBACKS +FF_DISABLE_DEPRECATION_WARNINGS dst->thread_safe_callbacks = src->thread_safe_callbacks; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (src->slice_count && src->slice_offset) { if (dst->slice_count < src->slice_count) { @@ -353,9 +379,9 @@ } dst->slice_count = src->slice_count; return 0; -#undef copy_fields } +#if FF_API_THREAD_SAFE_CALLBACKS /// Releases the buffers that this decoding thread was the last user of. static void release_delayed_buffers(PerThreadContext *p) { @@ -369,13 +395,14 @@ // fix extended data in case the caller screwed it up av_assert0(p->avctx->codec_type == AVMEDIA_TYPE_VIDEO || p->avctx->codec_type == AVMEDIA_TYPE_AUDIO); - f = &p->released_buffers[--p->num_released_buffers]; + f = p->released_buffers[--p->num_released_buffers]; f->extended_data = f->data; av_frame_unref(f); pthread_mutex_unlock(&fctx->buffer_mutex); } } +#endif static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx, AVPacket *avpkt) @@ -399,7 +426,9 @@ (p->avctx->debug & FF_DEBUG_THREADS) != 0, memory_order_relaxed); +#if FF_API_THREAD_SAFE_CALLBACKS release_delayed_buffers(p); +#endif if (prev_thread) { int err; @@ -417,8 +446,8 @@ } } - av_packet_unref(&p->avpkt); - ret = av_packet_ref(&p->avpkt, avpkt); + av_packet_unref(p->avpkt); + ret = av_packet_ref(p->avpkt, avpkt); if (ret < 0) { pthread_mutex_unlock(&p->mutex); av_log(p->avctx, AV_LOG_ERROR, "av_packet_ref() failed in submit_packet()\n"); @@ -429,6 +458,8 @@ pthread_cond_signal(&p->input_cond); pthread_mutex_unlock(&p->mutex); +#if FF_API_THREAD_SAFE_CALLBACKS +FF_DISABLE_DEPRECATION_WARNINGS /* * If the client doesn't have a thread-safe get_buffer(), * then decoding threads call back to the main thread, @@ -462,6 +493,8 @@ pthread_mutex_unlock(&p->progress_mutex); } } +FF_ENABLE_DEPRECATION_WARNINGS +#endif fctx->prev_thread = p; fctx->next_decoding++; @@ -525,7 +558,7 @@ av_frame_move_ref(picture, p->frame); *got_picture_ptr = p->got_frame; - picture->pkt_dts = p->avpkt.dts; + picture->pkt_dts = p->avpkt->dts; err = p->result; /* @@ -649,6 +682,59 @@ async_lock(fctx); } +#define SENTINEL 0 // This forbids putting a mutex/condition variable at the front. +#define OFFSET_ARRAY(...) __VA_ARGS__, SENTINEL +#define DEFINE_OFFSET_ARRAY(type, name, mutexes, conds) \ +static const unsigned name ## _offsets[] = { offsetof(type, pthread_init_cnt),\ + OFFSET_ARRAY mutexes, \ + OFFSET_ARRAY conds } + +#define OFF(member) offsetof(FrameThreadContext, member) +DEFINE_OFFSET_ARRAY(FrameThreadContext, thread_ctx, + (OFF(buffer_mutex), OFF(hwaccel_mutex), OFF(async_mutex)), + (OFF(async_cond))); +#undef OFF + +#define OFF(member) offsetof(PerThreadContext, member) +DEFINE_OFFSET_ARRAY(PerThreadContext, per_thread, + (OFF(progress_mutex), OFF(mutex)), + (OFF(input_cond), OFF(progress_cond), OFF(output_cond))); +#undef OFF + +static av_cold void free_pthread(void *obj, const unsigned offsets[]) +{ + unsigned cnt = *(unsigned*)((char*)obj + offsets[0]); + const unsigned *cur_offset = offsets; + + for (; *(++cur_offset) != SENTINEL && cnt; cnt--) + pthread_mutex_destroy((pthread_mutex_t*)((char*)obj + *cur_offset)); + for (; *(++cur_offset) != SENTINEL && cnt; cnt--) + pthread_cond_destroy ((pthread_cond_t *)((char*)obj + *cur_offset)); +} + +static av_cold int init_pthread(void *obj, const unsigned offsets[]) +{ + const unsigned *cur_offset = offsets; + unsigned cnt = 0; + int err; + +#define PTHREAD_INIT_LOOP(type) \ + for (; *(++cur_offset) != SENTINEL; cnt++) { \ + pthread_ ## type ## _t *dst = (void*)((char*)obj + *cur_offset); \ + err = pthread_ ## type ## _init(dst, NULL); \ + if (err) { \ + err = AVERROR(err); \ + goto fail; \ + } \ + } + PTHREAD_INIT_LOOP(mutex) + PTHREAD_INIT_LOOP(cond) + +fail: + *(unsigned*)((char*)obj + offsets[0]) = cnt; + return err; +} + void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) { FrameThreadContext *fctx = avctx->internal->thread_ctx; @@ -657,6 +743,13 @@ park_frame_worker_threads(fctx, thread_count); + if (fctx->prev_thread && avctx->internal->hwaccel_priv_data != + fctx->prev_thread->avctx->internal->hwaccel_priv_data) { + if (update_context_from_thread(avctx, fctx->prev_thread->avctx, 1) < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to update user thread.\n"); + } + } + if (fctx->prev_thread && fctx->prev_thread != fctx->threads) if (update_context_from_thread(fctx->threads->avctx, fctx->prev_thread->avctx, 0) < 0) { av_log(avctx, AV_LOG_ERROR, "Final thread update failed\n"); @@ -666,52 +759,49 @@ for (i = 0; i < thread_count; i++) { PerThreadContext *p = &fctx->threads[i]; + AVCodecContext *ctx = p->avctx; - pthread_mutex_lock(&p->mutex); - p->die = 1; - pthread_cond_signal(&p->input_cond); - pthread_mutex_unlock(&p->mutex); + if (ctx->internal) { + if (p->thread_init == INITIALIZED) { + pthread_mutex_lock(&p->mutex); + p->die = 1; + pthread_cond_signal(&p->input_cond); + pthread_mutex_unlock(&p->mutex); - if (p->thread_init) - pthread_join(p->thread, NULL); - p->thread_init=0; - - if (codec->close && p->avctx) - codec->close(p->avctx); + pthread_join(p->thread, NULL); + } + if (codec->close && p->thread_init != UNINITIALIZED) + codec->close(ctx); - release_delayed_buffers(p); - av_frame_free(&p->frame); - } +#if FF_API_THREAD_SAFE_CALLBACKS + release_delayed_buffers(p); + for (int j = 0; j < p->released_buffers_allocated; j++) + av_frame_free(&p->released_buffers[j]); + av_freep(&p->released_buffers); +#endif + if (ctx->priv_data) { + if (codec->priv_class) + av_opt_free(ctx->priv_data); + av_freep(&ctx->priv_data); + } - for (i = 0; i < thread_count; i++) { - PerThreadContext *p = &fctx->threads[i]; + av_freep(&ctx->slice_offset); - pthread_mutex_destroy(&p->mutex); - pthread_mutex_destroy(&p->progress_mutex); - pthread_cond_destroy(&p->input_cond); - pthread_cond_destroy(&p->progress_cond); - pthread_cond_destroy(&p->output_cond); - av_packet_unref(&p->avpkt); - av_freep(&p->released_buffers); - - if (i && p->avctx) { - av_freep(&p->avctx->priv_data); - av_freep(&p->avctx->slice_offset); - } - - if (p->avctx) { - av_freep(&p->avctx->internal); - av_buffer_unref(&p->avctx->hw_frames_ctx); + av_buffer_unref(&ctx->internal->pool); + av_freep(&ctx->internal); + av_buffer_unref(&ctx->hw_frames_ctx); } + av_frame_free(&p->frame); + + free_pthread(p, per_thread_offsets); + av_packet_free(&p->avpkt); + av_freep(&p->avctx); } av_freep(&fctx->threads); - pthread_mutex_destroy(&fctx->buffer_mutex); - pthread_mutex_destroy(&fctx->hwaccel_mutex); - pthread_mutex_destroy(&fctx->async_mutex); - pthread_cond_destroy(&fctx->async_cond); + free_pthread(fctx, thread_ctx_offsets); av_freep(&avctx->internal->thread_ctx); @@ -720,20 +810,92 @@ avctx->codec = NULL; } +static av_cold int init_thread(PerThreadContext *p, int *threads_to_free, + FrameThreadContext *fctx, AVCodecContext *avctx, + AVCodecContext *src, const AVCodec *codec, int first) +{ + AVCodecContext *copy; + int err; + + atomic_init(&p->state, STATE_INPUT_READY); + + copy = av_memdup(src, sizeof(*src)); + if (!copy) + return AVERROR(ENOMEM); + copy->priv_data = NULL; + + /* From now on, this PerThreadContext will be cleaned up by + * ff_frame_thread_free in case of errors. */ + (*threads_to_free)++; + + p->parent = fctx; + p->avctx = copy; + + copy->internal = av_memdup(src->internal, sizeof(*src->internal)); + if (!copy->internal) + return AVERROR(ENOMEM); + copy->internal->thread_ctx = p; + + copy->delay = avctx->delay; + + if (codec->priv_data_size) { + copy->priv_data = av_mallocz(codec->priv_data_size); + if (!copy->priv_data) + return AVERROR(ENOMEM); + + if (codec->priv_class) { + *(const AVClass **)copy->priv_data = codec->priv_class; + err = av_opt_copy(copy->priv_data, src->priv_data); + if (err < 0) + return err; + } + } + + err = init_pthread(p, per_thread_offsets); + if (err < 0) + return err; + + if (!(p->frame = av_frame_alloc()) || + !(p->avpkt = av_packet_alloc())) + return AVERROR(ENOMEM); + copy->internal->last_pkt_props = p->avpkt; + + if (!first) + copy->internal->is_copy = 1; + + if (codec->init) { + err = codec->init(copy); + if (err < 0) { + if (codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP) + p->thread_init = NEEDS_CLOSE; + return err; + } + } + p->thread_init = NEEDS_CLOSE; + + if (first) + update_context_from_thread(avctx, copy, 1); + + atomic_init(&p->debug_threads, (copy->debug & FF_DEBUG_THREADS) != 0); + + err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p)); + if (err < 0) + return err; + p->thread_init = INITIALIZED; + + return 0; +} + int ff_frame_thread_init(AVCodecContext *avctx) { int thread_count = avctx->thread_count; const AVCodec *codec = avctx->codec; AVCodecContext *src = avctx; FrameThreadContext *fctx; - int i, err = 0; + int err, i = 0; if (!thread_count) { int nb_cpus = av_cpu_count(); -#if FF_API_DEBUG_MV - if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || avctx->debug_mv) - nb_cpus = 1; -#endif // use number of cores + 1 as thread count if there is more than one if (nb_cpus > 1) thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS); @@ -750,92 +912,38 @@ if (!fctx) return AVERROR(ENOMEM); - fctx->threads = av_mallocz_array(thread_count, sizeof(PerThreadContext)); - if (!fctx->threads) { + err = init_pthread(fctx, thread_ctx_offsets); + if (err < 0) { + free_pthread(fctx, thread_ctx_offsets); av_freep(&avctx->internal->thread_ctx); - return AVERROR(ENOMEM); + return err; } - pthread_mutex_init(&fctx->buffer_mutex, NULL); - pthread_mutex_init(&fctx->hwaccel_mutex, NULL); - pthread_mutex_init(&fctx->async_mutex, NULL); - pthread_cond_init(&fctx->async_cond, NULL); - fctx->async_lock = 1; fctx->delaying = 1; - for (i = 0; i < thread_count; i++) { - AVCodecContext *copy = av_malloc(sizeof(AVCodecContext)); - PerThreadContext *p = &fctx->threads[i]; - - pthread_mutex_init(&p->mutex, NULL); - pthread_mutex_init(&p->progress_mutex, NULL); - pthread_cond_init(&p->input_cond, NULL); - pthread_cond_init(&p->progress_cond, NULL); - pthread_cond_init(&p->output_cond, NULL); - - p->frame = av_frame_alloc(); - if (!p->frame) { - av_freep(©); - err = AVERROR(ENOMEM); - goto error; - } - - p->parent = fctx; - p->avctx = copy; - - if (!copy) { - err = AVERROR(ENOMEM); - goto error; - } - - *copy = *src; - - copy->internal = av_malloc(sizeof(AVCodecInternal)); - if (!copy->internal) { - copy->priv_data = NULL; - err = AVERROR(ENOMEM); - goto error; - } - *copy->internal = *src->internal; - copy->internal->thread_ctx = p; - copy->internal->last_pkt_props = &p->avpkt; - - if (!i) { - src = copy; - - if (codec->init) - err = codec->init(copy); - - update_context_from_thread(avctx, copy, 1); - } else { - copy->priv_data = av_malloc(codec->priv_data_size); - if (!copy->priv_data) { - err = AVERROR(ENOMEM); - goto error; - } - memcpy(copy->priv_data, src->priv_data, codec->priv_data_size); - copy->internal->is_copy = 1; + if (codec->type == AVMEDIA_TYPE_VIDEO) + avctx->delay = src->thread_count - 1; - if (codec->init_thread_copy) - err = codec->init_thread_copy(copy); - } - - if (err) goto error; + fctx->threads = av_mallocz_array(thread_count, sizeof(PerThreadContext)); + if (!fctx->threads) { + err = AVERROR(ENOMEM); + goto error; + } - atomic_init(&p->debug_threads, (copy->debug & FF_DEBUG_THREADS) != 0); + for (; i < thread_count; ) { + PerThreadContext *p = &fctx->threads[i]; + int first = !i; - err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p)); - p->thread_init= !err; - if(!p->thread_init) + err = init_thread(p, &i, fctx, avctx, src, codec, first); + if (err < 0) goto error; } return 0; error: - ff_frame_thread_free(avctx, i+1); - + ff_frame_thread_free(avctx, i); return err; } @@ -862,7 +970,9 @@ av_frame_unref(p->frame); p->result = 0; +#if FF_API_THREAD_SAFE_CALLBACKS release_delayed_buffers(p); +#endif if (avctx->codec->flush) avctx->codec->flush(p->avctx); @@ -872,10 +982,16 @@ int ff_thread_can_start_frame(AVCodecContext *avctx) { PerThreadContext *p = avctx->internal->thread_ctx; +FF_DISABLE_DEPRECATION_WARNINGS if ((avctx->active_thread_type&FF_THREAD_FRAME) && atomic_load(&p->state) != STATE_SETTING_UP && - (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) { + (avctx->codec->update_thread_context +#if FF_API_THREAD_SAFE_CALLBACKS + || !THREAD_SAFE_CALLBACKS(avctx) +#endif + )) { return 0; } +FF_ENABLE_DEPRECATION_WARNINGS return 1; } @@ -889,13 +1005,19 @@ if (!(avctx->active_thread_type & FF_THREAD_FRAME)) return ff_get_buffer(avctx, f->f, flags); +FF_DISABLE_DEPRECATION_WARNINGS if (atomic_load(&p->state) != STATE_SETTING_UP && - (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) { + (avctx->codec->update_thread_context +#if FF_API_THREAD_SAFE_CALLBACKS + || !THREAD_SAFE_CALLBACKS(avctx) +#endif + )) { +FF_ENABLE_DEPRECATION_WARNINGS av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n"); return -1; } - if (avctx->internal->allocate_progress) { + if (avctx->codec->caps_internal & FF_CODEC_CAP_ALLOCATE_PROGRESS) { atomic_int *progress; f->progress = av_buffer_alloc(2 * sizeof(*progress)); if (!f->progress) { @@ -908,6 +1030,10 @@ } pthread_mutex_lock(&p->parent->buffer_mutex); +#if !FF_API_THREAD_SAFE_CALLBACKS + err = ff_get_buffer(avctx, f->f, flags); +#else +FF_DISABLE_DEPRECATION_WARNINGS if (THREAD_SAFE_CALLBACKS(avctx)) { err = ff_get_buffer(avctx, f->f, flags); } else { @@ -927,6 +1053,8 @@ } if (!THREAD_SAFE_CALLBACKS(avctx) && !avctx->codec->update_thread_context) ff_thread_finish_setup(avctx); +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (err) av_buffer_unref(&f->progress); @@ -935,6 +1063,8 @@ return err; } +#if FF_API_THREAD_SAFE_CALLBACKS +FF_DISABLE_DEPRECATION_WARNINGS enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) { enum AVPixelFormat res; @@ -960,6 +1090,8 @@ return res; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) { @@ -971,13 +1103,18 @@ void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) { +#if FF_API_THREAD_SAFE_CALLBACKS +FF_DISABLE_DEPRECATION_WARNINGS PerThreadContext *p = avctx->internal->thread_ctx; FrameThreadContext *fctx; - AVFrame *dst, *tmp; + AVFrame *dst; + int ret = 0; int can_direct_free = !(avctx->active_thread_type & FF_THREAD_FRAME) || THREAD_SAFE_CALLBACKS(avctx); +FF_ENABLE_DEPRECATION_WARNINGS +#endif - if (!f->f || !f->f->buf[0]) + if (!f->f) return; if (avctx->debug & FF_DEBUG_BUFFERS) @@ -986,7 +1123,11 @@ av_buffer_unref(&f->progress); f->owner[0] = f->owner[1] = NULL; - if (can_direct_free) { +#if !FF_API_THREAD_SAFE_CALLBACKS + av_frame_unref(f->f); +#else + // when the frame buffers are not allocated, just reset it to clean state + if (can_direct_free || !f->f->buf[0]) { av_frame_unref(f->f); return; } @@ -994,20 +1135,37 @@ fctx = p->parent; pthread_mutex_lock(&fctx->buffer_mutex); - if (p->num_released_buffers + 1 >= INT_MAX / sizeof(*p->released_buffers)) - goto fail; - tmp = av_fast_realloc(p->released_buffers, &p->released_buffers_allocated, - (p->num_released_buffers + 1) * - sizeof(*p->released_buffers)); - if (!tmp) - goto fail; - p->released_buffers = tmp; + if (p->num_released_buffers == p->released_buffers_allocated) { + AVFrame **tmp = av_realloc_array(p->released_buffers, p->released_buffers_allocated + 1, + sizeof(*p->released_buffers)); + if (tmp) { + tmp[p->released_buffers_allocated] = av_frame_alloc(); + p->released_buffers = tmp; + } + + if (!tmp || !tmp[p->released_buffers_allocated]) { + ret = AVERROR(ENOMEM); + goto fail; + } + p->released_buffers_allocated++; + } - dst = &p->released_buffers[p->num_released_buffers]; + dst = p->released_buffers[p->num_released_buffers]; av_frame_move_ref(dst, f->f); p->num_released_buffers++; fail: pthread_mutex_unlock(&fctx->buffer_mutex); + + // make sure the frame is clean even if we fail to free it + // this leaks, but it is better than crashing + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not queue a frame for freeing, this will leak\n"); + memset(f->f->buf, 0, sizeof(f->f->buf)); + if (f->f->extended_buf) + memset(f->f->extended_buf, 0, f->f->nb_extended_buf * sizeof(*f->f->extended_buf)); + av_frame_unref(f->f); + } +#endif } diff -Nru ffmpeg-4.2.2/libavcodec/pthread_slice.c ffmpeg-4.4/libavcodec/pthread_slice.c --- ffmpeg-4.2.2/libavcodec/pthread_slice.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/pthread_slice.c 2021-04-08 21:28:27.000000000 +0000 @@ -130,7 +130,7 @@ { SliceThreadContext *c; int thread_count = avctx->thread_count; - static void (*mainfunc)(void *); + void (*mainfunc)(void *); // We cannot do this in the encoder init as the threads are created before if (av_codec_is_encoder(avctx->codec) && diff -Nru ffmpeg-4.2.2/libavcodec/put_bits.h ffmpeg-4.4/libavcodec/put_bits.h --- ffmpeg-4.2.2/libavcodec/put_bits.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/put_bits.h 2021-04-08 21:28:39.000000000 +0000 @@ -29,11 +29,20 @@ #include #include +#include "config.h" #include "libavutil/intreadwrite.h" #include "libavutil/avassert.h" +#include "version.h" + +typedef uint32_t BitBuf; +#define AV_WBBUF AV_WB32 +#define AV_WLBUF AV_WL32 + +static const int BUF_BITS = 8 * sizeof(BitBuf); + typedef struct PutBitContext { - uint32_t bit_buf; + BitBuf bit_buf; int bit_left; uint8_t *buf, *buf_ptr, *buf_end; int size_in_bits; @@ -57,21 +66,29 @@ s->buf = buffer; s->buf_end = s->buf + buffer_size; s->buf_ptr = s->buf; - s->bit_left = 32; + s->bit_left = BUF_BITS; s->bit_buf = 0; } /** + * @return the total number of bits written to the bitstream. + */ +static inline int put_bits_count(PutBitContext *s) +{ + return (s->buf_ptr - s->buf) * 8 + BUF_BITS - s->bit_left; +} + +/** * Rebase the bit writer onto a reallocated buffer. * * @param buffer the buffer where to put bits * @param buffer_size the size in bytes of buffer, - * must be larger than the previous size + * must be large enough to hold everything written so far */ static inline void rebase_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size) { - av_assert0(8*buffer_size > s->size_in_bits); + av_assert0(8*buffer_size >= put_bits_count(s)); s->buf_end = buffer + buffer_size; s->buf_ptr = buffer + (s->buf_ptr - s->buf); @@ -80,19 +97,11 @@ } /** - * @return the total number of bits written to the bitstream. - */ -static inline int put_bits_count(PutBitContext *s) -{ - return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left; -} - -/** * @return the number of bits available in the bitstream. */ static inline int put_bits_left(PutBitContext* s) { - return (s->buf_end - s->buf_ptr) * 8 - 32 + s->bit_left; + return (s->buf_end - s->buf_ptr) * 8 - BUF_BITS + s->bit_left; } /** @@ -101,52 +110,52 @@ static inline void flush_put_bits(PutBitContext *s) { #ifndef BITSTREAM_WRITER_LE - if (s->bit_left < 32) + if (s->bit_left < BUF_BITS) s->bit_buf <<= s->bit_left; #endif - while (s->bit_left < 32) { + while (s->bit_left < BUF_BITS) { av_assert0(s->buf_ptr < s->buf_end); #ifdef BITSTREAM_WRITER_LE *s->buf_ptr++ = s->bit_buf; s->bit_buf >>= 8; #else - *s->buf_ptr++ = s->bit_buf >> 24; + *s->buf_ptr++ = s->bit_buf >> (BUF_BITS - 8); s->bit_buf <<= 8; #endif s->bit_left += 8; } - s->bit_left = 32; + s->bit_left = BUF_BITS; s->bit_buf = 0; } static inline void flush_put_bits_le(PutBitContext *s) { - while (s->bit_left < 32) { + while (s->bit_left < BUF_BITS) { av_assert0(s->buf_ptr < s->buf_end); *s->buf_ptr++ = s->bit_buf; s->bit_buf >>= 8; s->bit_left += 8; } - s->bit_left = 32; + s->bit_left = BUF_BITS; s->bit_buf = 0; } +#if FF_API_AVPRIV_PUT_BITS +void avpriv_align_put_bits(PutBitContext *s); +void avpriv_copy_bits(PutBitContext *pb, const uint8_t *src, int length); +#endif + #ifdef BITSTREAM_WRITER_LE -#define avpriv_align_put_bits align_put_bits_unsupported_here -#define avpriv_put_string ff_put_string_unsupported_here -#define avpriv_copy_bits avpriv_copy_bits_unsupported_here +#define ff_put_string ff_put_string_unsupported_here +#define ff_copy_bits ff_copy_bits_unsupported_here #else -/** - * Pad the bitstream with zeros up to the next byte boundary. - */ -void avpriv_align_put_bits(PutBitContext *s); /** * Put the string string in the bitstream. * * @param terminate_string 0-terminates the written string if value is 1 */ -void avpriv_put_string(PutBitContext *pb, const char *string, +void ff_put_string(PutBitContext *pb, const char *string, int terminate_string); /** @@ -154,36 +163,30 @@ * * @param length the number of bits of src to copy */ -void avpriv_copy_bits(PutBitContext *pb, const uint8_t *src, int length); +void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length); #endif -/** - * Write up to 31 bits into a bitstream. - * Use put_bits32 to write 32 bits. - */ -static inline void put_bits(PutBitContext *s, int n, unsigned int value) +static inline void put_bits_no_assert(PutBitContext *s, int n, BitBuf value) { - unsigned int bit_buf; + BitBuf bit_buf; int bit_left; - av_assert2(n <= 31 && value < (1U << n)); - bit_buf = s->bit_buf; bit_left = s->bit_left; /* XXX: optimize */ #ifdef BITSTREAM_WRITER_LE - bit_buf |= value << (32 - bit_left); + bit_buf |= value << (BUF_BITS - bit_left); if (n >= bit_left) { - if (3 < s->buf_end - s->buf_ptr) { - AV_WL32(s->buf_ptr, bit_buf); - s->buf_ptr += 4; + if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) { + AV_WLBUF(s->buf_ptr, bit_buf); + s->buf_ptr += sizeof(BitBuf); } else { av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n"); av_assert2(0); } bit_buf = value >> bit_left; - bit_left += 32; + bit_left += BUF_BITS; } bit_left -= n; #else @@ -193,14 +196,14 @@ } else { bit_buf <<= bit_left; bit_buf |= value >> (n - bit_left); - if (3 < s->buf_end - s->buf_ptr) { - AV_WB32(s->buf_ptr, bit_buf); - s->buf_ptr += 4; + if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) { + AV_WBBUF(s->buf_ptr, bit_buf); + s->buf_ptr += sizeof(BitBuf); } else { av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n"); av_assert2(0); } - bit_left += 32 - n; + bit_left += BUF_BITS - n; bit_buf = value; } #endif @@ -209,27 +212,37 @@ s->bit_left = bit_left; } -static inline void put_bits_le(PutBitContext *s, int n, unsigned int value) +/** + * Write up to 31 bits into a bitstream. + * Use put_bits32 to write 32 bits. + */ +static inline void put_bits(PutBitContext *s, int n, BitBuf value) { - unsigned int bit_buf; + av_assert2(n <= 31 && value < (1UL << n)); + put_bits_no_assert(s, n, value); +} + +static inline void put_bits_le(PutBitContext *s, int n, BitBuf value) +{ + BitBuf bit_buf; int bit_left; - av_assert2(n <= 31 && value < (1U << n)); + av_assert2(n <= 31 && value < (1UL << n)); bit_buf = s->bit_buf; bit_left = s->bit_left; - bit_buf |= value << (32 - bit_left); + bit_buf |= value << (BUF_BITS - bit_left); if (n >= bit_left) { - if (3 < s->buf_end - s->buf_ptr) { - AV_WL32(s->buf_ptr, bit_buf); - s->buf_ptr += 4; + if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) { + AV_WLBUF(s->buf_ptr, bit_buf); + s->buf_ptr += sizeof(BitBuf); } else { av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n"); av_assert2(0); } bit_buf = value >> bit_left; - bit_left += 32; + bit_left += BUF_BITS; } bit_left -= n; @@ -249,17 +262,22 @@ */ static void av_unused put_bits32(PutBitContext *s, uint32_t value) { - unsigned int bit_buf; + BitBuf bit_buf; int bit_left; + if (BUF_BITS > 32) { + put_bits_no_assert(s, 32, value); + return; + } + bit_buf = s->bit_buf; bit_left = s->bit_left; #ifdef BITSTREAM_WRITER_LE - bit_buf |= value << (32 - bit_left); - if (3 < s->buf_end - s->buf_ptr) { - AV_WL32(s->buf_ptr, bit_buf); - s->buf_ptr += 4; + bit_buf |= (BitBuf)value << (BUF_BITS - bit_left); + if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) { + AV_WLBUF(s->buf_ptr, bit_buf); + s->buf_ptr += sizeof(BitBuf); } else { av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n"); av_assert2(0); @@ -267,10 +285,10 @@ bit_buf = (uint64_t)value >> bit_left; #else bit_buf = (uint64_t)bit_buf << bit_left; - bit_buf |= value >> (32 - bit_left); - if (3 < s->buf_end - s->buf_ptr) { - AV_WB32(s->buf_ptr, bit_buf); - s->buf_ptr += 4; + bit_buf |= (BitBuf)value >> (BUF_BITS - bit_left); + if (s->buf_end - s->buf_ptr >= sizeof(BitBuf)) { + AV_WBBUF(s->buf_ptr, bit_buf); + s->buf_ptr += sizeof(BitBuf); } else { av_log(NULL, AV_LOG_ERROR, "Internal error, put_bits buffer too small\n"); av_assert2(0); @@ -333,7 +351,7 @@ static inline void skip_put_bytes(PutBitContext *s, int n) { av_assert2((put_bits_count(s) & 7) == 0); - av_assert2(s->bit_left == 32); + av_assert2(s->bit_left == BUF_BITS); av_assert0(n <= s->buf_end - s->buf_ptr); s->buf_ptr += n; } @@ -341,13 +359,13 @@ /** * Skip the given number of bits. * Must only be used if the actual values in the bitstream do not matter. - * If n is 0 the behavior is undefined. + * If n is < 0 the behavior is undefined. */ static inline void skip_put_bits(PutBitContext *s, int n) { - s->bit_left -= n; - s->buf_ptr -= 4 * (s->bit_left >> 5); - s->bit_left &= 31; + unsigned bits = BUF_BITS - s->bit_left + n; + s->buf_ptr += sizeof(BitBuf) * (bits / BUF_BITS); + s->bit_left = BUF_BITS - (bits & (BUF_BITS - 1)); } /** @@ -357,9 +375,20 @@ */ static inline void set_put_bits_buffer_size(PutBitContext *s, int size) { - av_assert0(size <= INT_MAX/8 - 32); + av_assert0(size <= INT_MAX/8 - BUF_BITS); s->buf_end = s->buf + size; s->size_in_bits = 8*size; } +/** + * Pad the bitstream with zeros up to the next byte boundary. + */ +static inline void align_put_bits(PutBitContext *s) +{ + put_bits(s, s->bit_left & 7, 0); +} + +#undef AV_WBBUF +#undef AV_WLBUF + #endif /* AVCODEC_PUT_BITS_H */ diff -Nru ffmpeg-4.2.2/libavcodec/qcelpdec.c ffmpeg-4.4/libavcodec/qcelpdec.c --- ffmpeg-4.2.2/libavcodec/qcelpdec.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qcelpdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -797,6 +797,6 @@ .id = AV_CODEC_ID_QCELP, .init = qcelp_decode_init, .decode = qcelp_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .priv_data_size = sizeof(QCELPContext), }; diff -Nru ffmpeg-4.2.2/libavcodec/qdm2.c ffmpeg-4.4/libavcodec/qdm2.c --- ffmpeg-4.2.2/libavcodec/qdm2.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qdm2.c 2021-04-08 21:28:39.000000000 +0000 @@ -36,6 +36,8 @@ #include #include "libavutil/channel_layout.h" +#include "libavutil/mem_internal.h" +#include "libavutil/thread.h" #define BITSTREAM_READER_LE #include "avcodec.h" @@ -205,7 +207,7 @@ value = get_vlc2(gb, vlc->table, vlc->bits, depth); /* stage-2, 3 bits exponent escape sequence */ - if (value-- == 0) + if (value < 0) value = get_bits(gb, get_bits(gb, 3) + 1); /* stage-3, optional */ @@ -1334,6 +1336,9 @@ if (q->frequency_range > (local_int_14 + 1)) { int sub_packet = (local_int_20 + local_int_28); + if (q->fft_coefs_index + stereo >= FF_ARRAY_ELEMS(q->fft_coefs)) + return; + qdm2_fft_init_coefficient(q, sub_packet, offset, duration, channel, exp, phase); if (stereo) @@ -1591,22 +1596,14 @@ /** * Init static data (does not depend on specific file) - * - * @param q context */ static av_cold void qdm2_init_static_data(void) { - static int done; - - if(done) - return; - qdm2_init_vlc(); - ff_mpa_synth_init_float(ff_mpa_synth_window_float); softclip_table_init(); rnd_table_init(); init_noise_samples(); - done = 1; + ff_mpa_synth_init_float(); } /** @@ -1614,12 +1611,11 @@ */ static av_cold int qdm2_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; QDM2Context *s = avctx->priv_data; int tmp_val, tmp, size; GetByteContext gb; - qdm2_init_static_data(); - /* extradata parsing Structure: @@ -1765,6 +1761,8 @@ avctx->sample_fmt = AV_SAMPLE_FMT_S16; + ff_thread_once(&init_static_once, qdm2_init_static_data); + return 0; } @@ -1880,5 +1878,6 @@ .init = qdm2_decode_init, .close = qdm2_decode_close, .decode = qdm2_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/qdm2data.h ffmpeg-4.4/libavcodec/qdm2data.h --- ffmpeg-4.2.2/libavcodec/qdm2data.h 2016-03-29 02:25:21.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qdm2data.h 2021-04-08 21:28:39.000000000 +0000 @@ -35,200 +35,130 @@ /** VLC TABLES **/ /* values in this table range from -1..23; adjust retrieved value by -1 */ -static const uint16_t vlc_tab_level_huffcodes[24] = { - 0x037c, 0x0004, 0x003c, 0x004c, 0x003a, 0x002c, 0x001c, 0x001a, - 0x0024, 0x0014, 0x0001, 0x0002, 0x0000, 0x0003, 0x0007, 0x0005, - 0x0006, 0x0008, 0x0009, 0x000a, 0x000c, 0x00fc, 0x007c, 0x017c -}; - -static const uint8_t vlc_tab_level_huffbits[24] = { - 10, 6, 7, 7, 6, 6, 6, 6, 6, 5, 4, 4, 4, 3, 3, 3, 3, 4, 4, 5, 7, 8, 9, 10 +static const uint8_t tab_level[24][2] = { + { 12, 4 }, { 17, 4 }, { 1, 6 }, { 8, 6 }, { 9, 5 }, { 20, 7 }, + { 3, 7 }, { 5, 6 }, { 6, 6 }, { 2, 7 }, { 22, 9 }, { 23, 10 }, + { 0, 10 }, { 21, 8 }, { 11, 4 }, { 19, 5 }, { 7, 6 }, { 4, 6 }, + { 16, 3 }, { 10, 4 }, { 18, 4 }, { 15, 3 }, { 13, 3 }, { 14, 3 }, }; /* values in this table range from -1..36; adjust retrieved value by -1 */ -static const uint16_t vlc_tab_diff_huffcodes[37] = { - 0x1c57, 0x0004, 0x0000, 0x0001, 0x0003, 0x0002, 0x000f, 0x000e, - 0x0007, 0x0016, 0x0037, 0x0027, 0x0026, 0x0066, 0x0006, 0x0097, - 0x0046, 0x01c6, 0x0017, 0x0786, 0x0086, 0x0257, 0x00d7, 0x0357, - 0x00c6, 0x0386, 0x0186, 0x0000, 0x0157, 0x0c57, 0x0057, 0x0000, - 0x0b86, 0x0000, 0x1457, 0x0000, 0x0457 -}; - -static const uint8_t vlc_tab_diff_huffbits[37] = { - 13, 3, 3, 2, 3, 3, 4, 4, 6, 5, 6, 6, 7, 7, 8, 8, - 8, 9, 8, 11, 9, 10, 8, 10, 9, 12, 10, 0, 10, 13, 11, 0, - 12, 0, 13, 0, 13 +static const uint8_t tab_diff[33][2] = { + { 2, 3 }, { 1, 3 }, { 5, 3 }, { 14, 8 }, { 20, 9 }, { 26, 10 }, + { 25, 12 }, { 32, 12 }, { 19, 11 }, { 16, 8 }, { 24, 9 }, { 17, 9 }, + { 12, 7 }, { 13, 7 }, { 9, 5 }, { 7, 4 }, { 3, 2 }, { 4, 3 }, + { 8, 6 }, { 11, 6 }, { 18, 8 }, { 15, 8 }, { 30, 11 }, { 36, 13 }, + { 34, 13 }, { 29, 13 }, { 0, 13 }, { 21, 10 }, { 28, 10 }, { 23, 10 }, + { 22, 8 }, { 10, 6 }, { 6, 4 }, }; /* values in this table range from -1..5; adjust retrieved value by -1 */ -static const uint8_t vlc_tab_run_huffcodes[6] = { - 0x1f, 0x00, 0x01, 0x03, 0x07, 0x0f -}; - -static const uint8_t vlc_tab_run_huffbits[6] = { - 5, 1, 2, 3, 4, 5 +static const uint8_t tab_run[6][2] = { + { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 0, 5 }, }; /* values in this table range from -1..19; adjust retrieved value by -1 */ -static const uint16_t vlc_tab_tone_level_idx_hi1_huffcodes[20] = { - 0x5714, 0x000c, 0x0002, 0x0001, 0x0000, 0x0004, 0x0034, 0x0054, - 0x0094, 0x0014, 0x0114, 0x0214, 0x0314, 0x0614, 0x0e14, 0x0f14, - 0x2714, 0x0714, 0x1714, 0x3714 -}; - -static const uint8_t vlc_tab_tone_level_idx_hi1_huffbits[20] = { - 15, 4, 2, 1, 3, 5, 6, 7, 8, 10, 10, 11, 11, 12, 12, 12, 14, 14, 15, 14 +static const uint8_t tab_tone_level_idx_hi1[20][2] = { + { 4, 3 }, { 5, 5 }, { 9, 10 }, { 11, 11 }, { 13, 12 }, { 14, 12 }, + { 10, 10 }, { 12, 11 }, { 17, 14 }, { 16, 14 }, { 18, 15 }, { 0, 15 }, + { 19, 14 }, { 15, 12 }, { 8, 8 }, { 7, 7 }, { 6, 6 }, { 1, 4 }, + { 2, 2 }, { 3, 1 }, }; /* values in this table range from -1..23; adjust retrieved value by -1 */ -static const uint16_t vlc_tab_tone_level_idx_mid_huffcodes[24] = { - 0x0fea, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x03ea, 0x00ea, 0x002a, 0x001a, - 0x0006, 0x0001, 0x0000, 0x0002, 0x000a, 0x006a, 0x01ea, 0x07ea -}; - -static const uint8_t vlc_tab_tone_level_idx_mid_huffbits[24] = { - 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 7, 5, 3, 1, 2, 4, 6, 8, 10, 12 +static const uint8_t tab_tone_level_idx_mid[13][2] = { + { 18, 2 }, { 19, 4 }, { 20, 6 }, { 14, 7 }, { 21, 8 }, { 13, 9 }, + { 22, 10 }, { 12, 11 }, { 23, 12 }, { 0, 12 }, { 15, 5 }, { 16, 3 }, + { 17, 1 }, }; /* values in this table range from -1..23; adjust retrieved value by -1 */ -static const uint16_t vlc_tab_tone_level_idx_hi2_huffcodes[24] = { - 0x0664, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0064, 0x00e4, - 0x00a4, 0x0068, 0x0004, 0x0008, 0x0014, 0x0018, 0x0000, 0x0001, - 0x0002, 0x0003, 0x000c, 0x0028, 0x0024, 0x0164, 0x0000, 0x0264 -}; - -static const uint8_t vlc_tab_tone_level_idx_hi2_huffbits[24] = { - 11, 0, 0, 0, 0, 0, 10, 8, 8, 7, 6, 6, 5, 5, 4, 2, 2, 2, 4, 7, 8, 9, 0, 11 +static const uint8_t tab_tone_level_idx_hi2[18][2] = { + { 14, 4 }, { 11, 6 }, { 19, 7 }, { 9, 7 }, { 13, 5 }, { 10, 6 }, + { 20, 8 }, { 8, 8 }, { 6, 10 }, { 23, 11 }, { 0, 11 }, { 21, 9 }, + { 7, 8 }, { 12, 5 }, { 18, 4 }, { 16, 2 }, { 15, 2 }, { 17, 2 }, }; /* values in this table range from -1..8; adjust retrieved value by -1 */ -static const uint8_t vlc_tab_type30_huffcodes[9] = { - 0x3c, 0x06, 0x00, 0x01, 0x03, 0x02, 0x04, 0x0c, 0x1c -}; - -static const uint8_t vlc_tab_type30_huffbits[9] = { - 6, 3, 3, 2, 2, 3, 4, 5, 6 +static const uint8_t tab_type30[9][2] = { + { 2, 3 }, { 6, 4 }, { 7, 5 }, { 8, 6 }, { 0, 6 }, { 5, 3 }, { 1, 3 }, + { 3, 2 }, { 4, 2 }, }; /* values in this table range from -1..9; adjust retrieved value by -1 */ -static const uint8_t vlc_tab_type34_huffcodes[10] = { - 0x18, 0x00, 0x01, 0x04, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08 -}; - -static const uint8_t vlc_tab_type34_huffbits[10] = { - 5, 4, 3, 3, 3, 3, 3, 3, 3, 5 -}; - -/* values in this table range from -1..22; adjust retrieved value by -1 */ -static const uint16_t vlc_tab_fft_tone_offset_0_huffcodes[23] = { - 0x038e, 0x0001, 0x0000, 0x0022, 0x000a, 0x0006, 0x0012, 0x0002, - 0x001e, 0x003e, 0x0056, 0x0016, 0x000e, 0x0032, 0x0072, 0x0042, - 0x008e, 0x004e, 0x00f2, 0x002e, 0x0036, 0x00c2, 0x018e -}; - -static const uint8_t vlc_tab_fft_tone_offset_0_huffbits[23] = { - 10, 1, 2, 6, 4, 5, 6, 7, 6, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 6, 6, 8, 10 -}; - -/* values in this table range from -1..27; adjust retrieved value by -1 */ -static const uint16_t vlc_tab_fft_tone_offset_1_huffcodes[28] = { - 0x07a4, 0x0001, 0x0020, 0x0012, 0x001c, 0x0008, 0x0006, 0x0010, - 0x0000, 0x0014, 0x0004, 0x0032, 0x0070, 0x000c, 0x0002, 0x003a, - 0x001a, 0x002c, 0x002a, 0x0022, 0x0024, 0x000a, 0x0064, 0x0030, - 0x0062, 0x00a4, 0x01a4, 0x03a4 -}; - -static const uint8_t vlc_tab_fft_tone_offset_1_huffbits[28] = { - 11, 1, 6, 6, 5, 4, 3, 6, 6, 5, 6, 6, 7, 6, 6, 6, - 6, 6, 6, 7, 8, 6, 7, 7, 7, 9, 10, 11 -}; - -/* values in this table range from -1..31; adjust retrieved value by -1 */ -static const uint16_t vlc_tab_fft_tone_offset_2_huffcodes[32] = { - 0x1760, 0x0001, 0x0000, 0x0082, 0x000c, 0x0006, 0x0003, 0x0007, - 0x0008, 0x0004, 0x0010, 0x0012, 0x0022, 0x001a, 0x0000, 0x0020, - 0x000a, 0x0040, 0x004a, 0x006a, 0x002a, 0x0042, 0x0002, 0x0060, - 0x00aa, 0x00e0, 0x00c2, 0x01c2, 0x0160, 0x0360, 0x0760, 0x0f60 -}; - -static const uint8_t vlc_tab_fft_tone_offset_2_huffbits[32] = { - 13, 2, 0, 8, 4, 3, 3, 3, 4, 4, 5, 5, 6, 5, 7, 7, - 7, 7, 7, 7, 8, 8, 8, 9, 8, 8, 9, 9, 10, 11, 13, 12 -}; - -/* values in this table range from -1..34; adjust retrieved value by -1 */ -static const uint16_t vlc_tab_fft_tone_offset_3_huffcodes[35] = { - 0x33ea, 0x0005, 0x0000, 0x000c, 0x0000, 0x0006, 0x0003, 0x0008, - 0x0002, 0x0001, 0x0004, 0x0007, 0x001a, 0x000f, 0x001c, 0x002c, - 0x000a, 0x001d, 0x002d, 0x002a, 0x000d, 0x004c, 0x008c, 0x006a, - 0x00cd, 0x004d, 0x00ea, 0x020c, 0x030c, 0x010c, 0x01ea, 0x07ea, - 0x0bea, 0x03ea, 0x13ea -}; - -static const uint8_t vlc_tab_fft_tone_offset_3_huffbits[35] = { - 14, 4, 0, 10, 4, 3, 3, 4, 4, 3, 4, 4, 5, 4, 5, 6, - 6, 5, 6, 7, 7, 7, 8, 8, 8, 8, 9, 10, 10, 10, 10, 11, - 12, 13, 14 -}; - -/* values in this table range from -1..37; adjust retrieved value by -1 */ -static const uint16_t vlc_tab_fft_tone_offset_4_huffcodes[38] = { - 0x5282, 0x0016, 0x0000, 0x0136, 0x0004, 0x0000, 0x0007, 0x000a, - 0x000e, 0x0003, 0x0001, 0x000d, 0x0006, 0x0009, 0x0012, 0x0005, - 0x0025, 0x0022, 0x0015, 0x0002, 0x0076, 0x0035, 0x0042, 0x00c2, - 0x0182, 0x00b6, 0x0036, 0x03c2, 0x0482, 0x01c2, 0x0682, 0x0882, - 0x0a82, 0x0082, 0x0282, 0x1282, 0x3282, 0x2282 -}; - -static const uint8_t vlc_tab_fft_tone_offset_4_huffbits[38] = { - 15, 6, 0, 9, 3, 3, 3, 4, 4, 3, 4, 4, 5, 4, 5, 6, - 6, 6, 6, 8, 7, 6, 8, 9, 9, 8, 9, 10, 11, 10, 11, 12, - 12, 12, 14, 15, 14, 14 +static const uint8_t tab_type34[10][2] = { + { 1, 4 }, { 9, 5 }, { 0, 5 }, { 3, 3 }, { 7, 3 }, { 8, 3 }, { 2, 3 }, + { 4, 3 }, { 6, 3 }, { 5, 3 }, +}; + +static const uint8_t tab_fft_tone_offset_sizes[] = { + 23, 28, 31, 34, 37 +}; + +static const uint8_t tab_fft_tone_offset[][2] = { + /* First table - 23 entries with range -1..21 */ + { 2, 2 }, { 7, 7 }, { 15, 8 }, { 21, 8 }, { 3, 6 }, { 6, 6 }, + { 13, 7 }, { 14, 8 }, { 18, 8 }, { 4, 4 }, { 5, 5 }, { 11, 7 }, + { 10, 7 }, { 20, 6 }, { 12, 8 }, { 16, 9 }, { 22, 10 }, { 0, 10 }, + { 17, 7 }, { 19, 6 }, { 8, 6 }, { 9, 6 }, { 1, 1 }, + /* Second table - 28 entries with range -1..26 */ + { 8, 6 }, { 2, 6 }, { 7, 6 }, { 23, 7 }, { 12, 7 }, { 5, 4 }, + { 10, 6 }, { 20, 8 }, { 25, 9 }, { 26, 10 }, { 27, 11 }, { 0, 11 }, + { 22, 7 }, { 9, 5 }, { 13, 6 }, { 17, 6 }, { 4, 5 }, { 14, 6 }, + { 19, 7 }, { 24, 7 }, { 3, 6 }, { 11, 6 }, { 21, 6 }, { 18, 6 }, + { 16, 6 }, { 15, 6 }, { 6, 3 }, { 1, 1 }, + /* Third table - 31 entries with range -1..30 (1 omitted) */ + { 14, 7 }, { 17, 7 }, { 15, 7 }, { 23, 9 }, { 28, 10 }, { 29, 11 }, + { 30, 13 }, { 0, 13 }, { 31, 12 }, { 25, 8 }, { 10, 5 }, { 8, 4 }, + { 9, 4 }, { 4, 4 }, { 22, 8 }, { 3, 8 }, { 21, 8 }, { 26, 9 }, + { 27, 9 }, { 12, 6 }, { 11, 5 }, { 16, 7 }, { 18, 7 }, { 20, 8 }, + { 24, 8 }, { 19, 7 }, { 13, 5 }, { 5, 3 }, { 1, 2 }, { 6, 3 }, + { 7, 3 }, + /* Fourth table - 34 entries with range -1..33 (1 omitted) */ + { 4, 4 }, { 7, 4 }, { 10, 4 }, { 3, 10 }, { 27, 10 }, { 29, 10 }, + { 28, 10 }, { 22, 8 }, { 21, 7 }, { 15, 6 }, { 14, 5 }, { 8, 4 }, + { 16, 6 }, { 19, 7 }, { 23, 8 }, { 26, 9 }, { 30, 10 }, { 33, 13 }, + { 34, 14 }, { 0, 14 }, { 32, 12 }, { 31, 11 }, { 12, 5 }, { 5, 3 }, + { 9, 3 }, { 1, 4 }, { 20, 7 }, { 25, 8 }, { 24, 8 }, { 18, 6 }, + { 17, 5 }, { 6, 3 }, { 11, 4 }, { 13, 4 }, + /* Fifth table - 37 entries with range -1..36 (1 omitted) */ + { 5, 3 }, { 4, 3 }, { 19, 8 }, { 33, 12 }, { 31, 12 }, { 28, 11 }, + { 34, 14 }, { 37, 14 }, { 35, 15 }, { 0, 15 }, { 36, 14 }, { 32, 12 }, + { 30, 11 }, { 24, 9 }, { 22, 8 }, { 23, 9 }, { 29, 10 }, { 27, 10 }, + { 17, 6 }, { 14, 5 }, { 7, 4 }, { 12, 5 }, { 1, 6 }, { 26, 9 }, + { 3, 9 }, { 25, 8 }, { 20, 7 }, { 8, 4 }, { 10, 4 }, { 13, 4 }, + { 15, 6 }, { 16, 6 }, { 18, 6 }, { 21, 6 }, { 11, 4 }, { 9, 3 }, + { 6, 3 }, }; /** FFT TABLES **/ /* values in this table range from -1..27; adjust retrieved value by -1 */ -static const uint16_t fft_level_exp_alt_huffcodes[28] = { - 0x1ec6, 0x0006, 0x00c2, 0x0142, 0x0242, 0x0246, 0x00c6, 0x0046, - 0x0042, 0x0146, 0x00a2, 0x0062, 0x0026, 0x0016, 0x000e, 0x0005, - 0x0004, 0x0003, 0x0000, 0x0001, 0x000a, 0x0012, 0x0002, 0x0022, - 0x01c6, 0x02c6, 0x06c6, 0x0ec6 -}; - -static const uint8_t fft_level_exp_alt_huffbits[28] = { - 13, 7, 8, 9, 10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, - 3, 2, 3, 3, 4, 5, 7, 8, 9, 11, 12, 13 +static const uint8_t fft_level_exp_alt[28][2] = { + { 18, 3 }, { 16, 3 }, { 22, 7 }, { 8, 10 }, { 4, 10 }, { 3, 9 }, + { 2, 8 }, { 23, 8 }, { 10, 8 }, { 11, 7 }, { 21, 5 }, { 20, 4 }, + { 1, 7 }, { 7, 10 }, { 5, 10 }, { 9, 9 }, { 6, 10 }, { 25, 11 }, + { 26, 12 }, { 27, 13 }, { 0, 13 }, { 24, 9 }, { 12, 6 }, { 13, 5 }, + { 14, 4 }, { 19, 3 }, { 15, 3 }, { 17, 2 }, }; /* values in this table range from -1..19; adjust retrieved value by -1 */ -static const uint16_t fft_level_exp_huffcodes[20] = { - 0x0f24, 0x0001, 0x0002, 0x0000, 0x0006, 0x0005, 0x0007, 0x000c, - 0x000b, 0x0014, 0x0013, 0x0004, 0x0003, 0x0023, 0x0064, 0x00a4, - 0x0024, 0x0124, 0x0324, 0x0724 -}; - -static const uint8_t fft_level_exp_huffbits[20] = { - 12, 3, 3, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 9, 10, 11, 12 +static const uint8_t fft_level_exp[20][2] = { + { 3, 3 }, { 11, 6 }, { 16, 9 }, { 17, 10 }, { 18, 11 }, { 19, 12 }, + { 0, 12 }, { 15, 8 }, { 14, 7 }, { 9, 5 }, { 7, 4 }, { 2, 3 }, + { 4, 3 }, { 1, 3 }, { 5, 3 }, { 12, 6 }, { 13, 6 }, { 10, 5 }, + { 8, 4 }, { 6, 3 }, }; /* values in this table range from -1..6; adjust retrieved value by -1 */ -static const uint8_t fft_stereo_exp_huffcodes[7] = { - 0x3e, 0x01, 0x00, 0x02, 0x06, 0x0e, 0x1e -}; - -static const uint8_t fft_stereo_exp_huffbits[7] = { - 6, 1, 2, 3, 4, 5, 6 +static const uint8_t fft_stereo_exp[7][2] = { + { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 0, 6 }, { 1, 1 }, }; /* values in this table range from -1..8; adjust retrieved value by -1 */ -static const uint8_t fft_stereo_phase_huffcodes[9] = { - 0x35, 0x02, 0x00, 0x01, 0x0d, 0x15, 0x05, 0x09, 0x03 -}; - -static const uint8_t fft_stereo_phase_huffbits[9] = { - 6, 2, 2, 4, 4, 6, 5, 4, 2 +static const uint8_t fft_stereo_phase[9][2] = { + { 2, 2 }, { 1, 2 }, { 3, 4 }, { 7, 4 }, { 6, 5 }, { 5, 6 }, { 0, 6 }, + { 4, 4 }, { 8, 2 }, }; static const int fft_cutoff_index_table[4][2] = { diff -Nru ffmpeg-4.2.2/libavcodec/qdm2_tablegen.h ffmpeg-4.4/libavcodec/qdm2_tablegen.h --- ffmpeg-4.2.2/libavcodec/qdm2_tablegen.h 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qdm2_tablegen.h 2021-04-08 21:28:39.000000000 +0000 @@ -109,151 +109,46 @@ static VLC vlc_tab_type34; static VLC vlc_tab_fft_tone_offset[5]; -static const uint16_t qdm2_vlc_offs[] = { - 0,260,566,598,894,1166,1230,1294,1678,1950,2214,2278,2310,2570,2834,3124,3448,3838, -}; - static VLC_TYPE qdm2_table[3838][2]; +static av_cold void build_vlc(VLC *vlc, int nb_bits, int nb_codes, + unsigned *offset, const uint8_t tab[][2]) +{ + vlc->table = &qdm2_table[*offset]; + vlc->table_allocated = FF_ARRAY_ELEMS(qdm2_table) - *offset; + ff_init_vlc_from_lengths(vlc, nb_bits, nb_codes, + &tab[0][1], 2, &tab[0][0], 2, 1, + -1, INIT_VLC_STATIC_OVERLONG | INIT_VLC_LE, NULL); + *offset += vlc->table_size; +} + static av_cold void qdm2_init_vlc(void) { - vlc_tab_level.table = &qdm2_table[qdm2_vlc_offs[0]]; - vlc_tab_level.table_allocated = qdm2_vlc_offs[1] - qdm2_vlc_offs[0]; - init_vlc(&vlc_tab_level, 8, 24, - vlc_tab_level_huffbits, 1, 1, - vlc_tab_level_huffcodes, 2, 2, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - vlc_tab_diff.table = &qdm2_table[qdm2_vlc_offs[1]]; - vlc_tab_diff.table_allocated = qdm2_vlc_offs[2] - qdm2_vlc_offs[1]; - init_vlc(&vlc_tab_diff, 8, 37, - vlc_tab_diff_huffbits, 1, 1, - vlc_tab_diff_huffcodes, 2, 2, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - vlc_tab_run.table = &qdm2_table[qdm2_vlc_offs[2]]; - vlc_tab_run.table_allocated = qdm2_vlc_offs[3] - qdm2_vlc_offs[2]; - init_vlc(&vlc_tab_run, 5, 6, - vlc_tab_run_huffbits, 1, 1, - vlc_tab_run_huffcodes, 1, 1, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - fft_level_exp_alt_vlc.table = &qdm2_table[qdm2_vlc_offs[3]]; - fft_level_exp_alt_vlc.table_allocated = qdm2_vlc_offs[4] - - qdm2_vlc_offs[3]; - init_vlc(&fft_level_exp_alt_vlc, 8, 28, - fft_level_exp_alt_huffbits, 1, 1, - fft_level_exp_alt_huffcodes, 2, 2, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - fft_level_exp_vlc.table = &qdm2_table[qdm2_vlc_offs[4]]; - fft_level_exp_vlc.table_allocated = qdm2_vlc_offs[5] - qdm2_vlc_offs[4]; - init_vlc(&fft_level_exp_vlc, 8, 20, - fft_level_exp_huffbits, 1, 1, - fft_level_exp_huffcodes, 2, 2, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - fft_stereo_exp_vlc.table = &qdm2_table[qdm2_vlc_offs[5]]; - fft_stereo_exp_vlc.table_allocated = qdm2_vlc_offs[6] - - qdm2_vlc_offs[5]; - init_vlc(&fft_stereo_exp_vlc, 6, 7, - fft_stereo_exp_huffbits, 1, 1, - fft_stereo_exp_huffcodes, 1, 1, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - fft_stereo_phase_vlc.table = &qdm2_table[qdm2_vlc_offs[6]]; - fft_stereo_phase_vlc.table_allocated = qdm2_vlc_offs[7] - - qdm2_vlc_offs[6]; - init_vlc(&fft_stereo_phase_vlc, 6, 9, - fft_stereo_phase_huffbits, 1, 1, - fft_stereo_phase_huffcodes, 1, 1, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - vlc_tab_tone_level_idx_hi1.table = - &qdm2_table[qdm2_vlc_offs[7]]; - vlc_tab_tone_level_idx_hi1.table_allocated = qdm2_vlc_offs[8] - - qdm2_vlc_offs[7]; - init_vlc(&vlc_tab_tone_level_idx_hi1, 8, 20, - vlc_tab_tone_level_idx_hi1_huffbits, 1, 1, - vlc_tab_tone_level_idx_hi1_huffcodes, 2, 2, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - vlc_tab_tone_level_idx_mid.table = - &qdm2_table[qdm2_vlc_offs[8]]; - vlc_tab_tone_level_idx_mid.table_allocated = qdm2_vlc_offs[9] - - qdm2_vlc_offs[8]; - init_vlc(&vlc_tab_tone_level_idx_mid, 8, 24, - vlc_tab_tone_level_idx_mid_huffbits, 1, 1, - vlc_tab_tone_level_idx_mid_huffcodes, 2, 2, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - vlc_tab_tone_level_idx_hi2.table = - &qdm2_table[qdm2_vlc_offs[9]]; - vlc_tab_tone_level_idx_hi2.table_allocated = qdm2_vlc_offs[10] - - qdm2_vlc_offs[9]; - init_vlc(&vlc_tab_tone_level_idx_hi2, 8, 24, - vlc_tab_tone_level_idx_hi2_huffbits, 1, 1, - vlc_tab_tone_level_idx_hi2_huffcodes, 2, 2, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - vlc_tab_type30.table = &qdm2_table[qdm2_vlc_offs[10]]; - vlc_tab_type30.table_allocated = qdm2_vlc_offs[11] - qdm2_vlc_offs[10]; - init_vlc(&vlc_tab_type30, 6, 9, - vlc_tab_type30_huffbits, 1, 1, - vlc_tab_type30_huffcodes, 1, 1, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - vlc_tab_type34.table = &qdm2_table[qdm2_vlc_offs[11]]; - vlc_tab_type34.table_allocated = qdm2_vlc_offs[12] - qdm2_vlc_offs[11]; - init_vlc(&vlc_tab_type34, 5, 10, - vlc_tab_type34_huffbits, 1, 1, - vlc_tab_type34_huffcodes, 1, 1, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - vlc_tab_fft_tone_offset[0].table = - &qdm2_table[qdm2_vlc_offs[12]]; - vlc_tab_fft_tone_offset[0].table_allocated = qdm2_vlc_offs[13] - - qdm2_vlc_offs[12]; - init_vlc(&vlc_tab_fft_tone_offset[0], 8, 23, - vlc_tab_fft_tone_offset_0_huffbits, 1, 1, - vlc_tab_fft_tone_offset_0_huffcodes, 2, 2, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - vlc_tab_fft_tone_offset[1].table = - &qdm2_table[qdm2_vlc_offs[13]]; - vlc_tab_fft_tone_offset[1].table_allocated = qdm2_vlc_offs[14] - - qdm2_vlc_offs[13]; - init_vlc(&vlc_tab_fft_tone_offset[1], 8, 28, - vlc_tab_fft_tone_offset_1_huffbits, 1, 1, - vlc_tab_fft_tone_offset_1_huffcodes, 2, 2, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - vlc_tab_fft_tone_offset[2].table = - &qdm2_table[qdm2_vlc_offs[14]]; - vlc_tab_fft_tone_offset[2].table_allocated = qdm2_vlc_offs[15] - - qdm2_vlc_offs[14]; - init_vlc(&vlc_tab_fft_tone_offset[2], 8, 32, - vlc_tab_fft_tone_offset_2_huffbits, 1, 1, - vlc_tab_fft_tone_offset_2_huffcodes, 2, 2, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - vlc_tab_fft_tone_offset[3].table = - &qdm2_table[qdm2_vlc_offs[15]]; - vlc_tab_fft_tone_offset[3].table_allocated = qdm2_vlc_offs[16] - - qdm2_vlc_offs[15]; - init_vlc(&vlc_tab_fft_tone_offset[3], 8, 35, - vlc_tab_fft_tone_offset_3_huffbits, 1, 1, - vlc_tab_fft_tone_offset_3_huffcodes, 2, 2, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); - - vlc_tab_fft_tone_offset[4].table = - &qdm2_table[qdm2_vlc_offs[16]]; - vlc_tab_fft_tone_offset[4].table_allocated = qdm2_vlc_offs[17] - - qdm2_vlc_offs[16]; - init_vlc(&vlc_tab_fft_tone_offset[4], 8, 38, - vlc_tab_fft_tone_offset_4_huffbits, 1, 1, - vlc_tab_fft_tone_offset_4_huffcodes, 2, 2, - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + const uint8_t (*tab)[2] = tab_fft_tone_offset; + unsigned offset = 0; + + build_vlc(&vlc_tab_level, 8, 24, &offset, tab_level); + build_vlc(&vlc_tab_diff, 8, 33, &offset, tab_diff); + build_vlc(&vlc_tab_run, 5, 6, &offset, tab_run); + + build_vlc(&fft_level_exp_alt_vlc, 8, 28, &offset, fft_level_exp_alt); + build_vlc(&fft_level_exp_vlc, 8, 20, &offset, fft_level_exp); + + build_vlc(&fft_stereo_exp_vlc, 6, 7, &offset, fft_stereo_exp); + build_vlc(&fft_stereo_phase_vlc, 6, 9, &offset, fft_stereo_phase); + + build_vlc(&vlc_tab_tone_level_idx_hi1, 8, 20, &offset, tab_tone_level_idx_hi1); + build_vlc(&vlc_tab_tone_level_idx_mid, 8, 13, &offset, tab_tone_level_idx_mid); + build_vlc(&vlc_tab_tone_level_idx_hi2, 8, 18, &offset, tab_tone_level_idx_hi2); + + build_vlc(&vlc_tab_type30, 6, 9, &offset, tab_type30); + build_vlc(&vlc_tab_type34, 5, 10, &offset, tab_type34); + + for (int i = 0; i < 5; i++) { + build_vlc(&vlc_tab_fft_tone_offset[i], 8, tab_fft_tone_offset_sizes[i], + &offset, tab); + tab += tab_fft_tone_offset_sizes[i]; + } } #endif /* CONFIG_HARDCODED_TABLES */ diff -Nru ffmpeg-4.2.2/libavcodec/qdmc.c ffmpeg-4.4/libavcodec/qdmc.c --- ffmpeg-4.2.2/libavcodec/qdmc.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qdmc.c 2021-04-08 21:28:39.000000000 +0000 @@ -119,109 +119,62 @@ 4, 3, 2, 1, 0, 0, 0, }; -static const uint8_t noise_value_bits[] = { - 12, 7, 9, 7, 10, 9, 11, 9, 9, 2, 9, 9, 9, 9, - 9, 3, 9, 10, 10, 12, 2, 3, 3, 5, 5, 6, 7, +static const uint8_t qdmc_hufftab[][2] = { + /* Noise value - 27 entries */ + { 1, 2 }, { 10, 7 }, { 26, 9 }, { 22, 9 }, { 24, 9 }, { 14, 9 }, + { 8, 6 }, { 6, 5 }, { 7, 5 }, { 9, 7 }, { 30, 9 }, { 32, 10 }, + { 13, 10 }, { 20, 9 }, { 28, 9 }, { 12, 7 }, { 15, 11 }, { 36, 12 }, + { 0, 12 }, { 34, 10 }, { 18, 9 }, { 11, 9 }, { 16, 9 }, { 5, 3 }, + { 2, 3 }, { 4, 3 }, { 3, 2 }, + /* Noise segment length - 12 entries */ + { 1, 1 }, { 2, 2 }, { 3, 4 }, { 8, 9 }, { 9, 10 }, { 0, 10 }, + { 13, 8 }, { 7, 7 }, { 6, 6 }, { 17, 5 }, { 4, 4 }, { 5, 4 }, + /* Amplitude - 28 entries */ + { 18, 3 }, { 16, 3 }, { 22, 7 }, { 8, 10 }, { 4, 10 }, { 3, 9 }, + { 2, 8 }, { 23, 8 }, { 10, 8 }, { 11, 7 }, { 21, 5 }, { 20, 4 }, + { 1, 7 }, { 7, 10 }, { 5, 10 }, { 9, 9 }, { 6, 10 }, { 25, 11 }, + { 26, 12 }, { 27, 13 }, { 0, 13 }, { 24, 9 }, { 12, 6 }, { 13, 5 }, + { 14, 4 }, { 19, 3 }, { 15, 3 }, { 17, 2 }, + /* Frequency differences - 47 entries */ + { 2, 4 }, { 14, 6 }, { 26, 7 }, { 31, 8 }, { 32, 9 }, { 35, 9 }, + { 7, 5 }, { 10, 5 }, { 22, 7 }, { 27, 7 }, { 19, 7 }, { 20, 7 }, + { 4, 5 }, { 13, 5 }, { 17, 6 }, { 15, 6 }, { 8, 5 }, { 5, 4 }, + { 28, 7 }, { 33, 9 }, { 36, 11 }, { 38, 12 }, { 42, 14 }, { 45, 16 }, + { 44, 18 }, { 0, 18 }, { 46, 17 }, { 43, 15 }, { 40, 13 }, { 37, 11 }, + { 39, 12 }, { 41, 12 }, { 34, 8 }, { 16, 6 }, { 11, 5 }, { 9, 4 }, + { 1, 2 }, { 3, 4 }, { 30, 7 }, { 29, 7 }, { 23, 6 }, { 24, 6 }, + { 18, 6 }, { 6, 4 }, { 12, 5 }, { 21, 6 }, { 25, 6 }, + /* Amplitude differences - 9 entries */ + { 1, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, + { 8, 8 }, { 0, 8 }, { 2, 1 }, + /* Phase differences - 9 entries */ + { 2, 2 }, { 1, 2 }, { 3, 4 }, { 7, 4 }, { 6, 5 }, { 5, 6 }, + { 0, 6 }, { 4, 4 }, { 8, 2 }, }; -static const uint8_t noise_value_symbols[] = { - 0, 10, 11, 12, 13, 14, 15, 16, 18, 1, 20, 22, 24, - 26, 28, 2, 30, 32, 34, 36, 3, 4, 5, 6, 7, 8, 9, +static const uint8_t huff_sizes[] = { + 27, 12, 28, 47, 9, 9 }; -static const uint16_t noise_value_codes[] = { - 0xC7A, 0x002, 0x0FA, 0x03A, 0x35A, 0x1C2, 0x07A, 0x1FA, - 0x17A, 0x000, 0x0DA, 0x142, 0x0C2, 0x042, 0x1DA, 0x001, - 0x05A, 0x15A, 0x27A, 0x47A, 0x003, 0x005, 0x006, 0x012, - 0x00A, 0x022, 0x01A, +static const uint8_t huff_bits[] = { + 12, 10, 12, 12, 8, 6 }; -static const uint8_t noise_segment_length_bits[] = { - 10, 8, 5, 1, 2, 4, 4, 4, 6, 7, 9, 10, -}; - -static const uint8_t noise_segment_length_symbols[] = { - 0, 13, 17, 1, 2, 3, 4, 5, 6, 7, 8, 9, -}; - -static const uint16_t noise_segment_length_codes[] = { - 0x30B, 0x8B, 0x1B, 0x0, 0x1, 0x3, 0x7, 0xF, 0x2b, 0x4B, 0xB, 0x10B, -}; - -static const uint8_t freq_diff_bits[] = { - 18, 2, 4, 4, 5, 4, 4, 5, 5, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 6, - 7, 6, 6, 6, 7, 7, 7, 7, 7, 8, 9, 9, 8, 9, 11, 11, 12, 12, 13, 12, - 14, 15, 18, 16, 17, -}; - -static const uint32_t freq_diff_codes[] = { - 0x2AD46, 0x1, 0x0, 0x3, 0xC, 0xA, 0x7, 0x18, 0x12, 0xE, 0x4, 0x16, - 0xF, 0x1C, 0x8, 0x22, 0x26, 0x2, 0x3B, 0x34, 0x74, 0x1F, 0x14, 0x2B, - 0x1B, 0x3F, 0x28, 0x54, 0x6, 0x4B, 0xB, 0x68, 0xE8, 0x46, 0xC6, 0x1E8, - 0x146, 0x346, 0x546, 0x746, 0x1D46, 0xF46, 0xD46, 0x6D46, 0xAD46, 0x2D46, - 0x1AD46, -}; - -static const uint8_t amplitude_bits[] = { - 13, 7, 8, 9, 10, 10, 10, 10, 10, 9, 8, 7, 6, - 5, 4, 3, 3, 2, 3, 3, 4, 5, 7, 8, 9, 11, 12, 13, -}; - -static const uint16_t amplitude_codes[] = { - 0x1EC6, 0x6, 0xC2, 0x142, 0x242, 0x246, 0xC6, 0x46, 0x42, 0x146, 0xA2, - 0x62, 0x26, 0x16, 0xE, 0x5, 0x4, 0x3, 0x0, 0x1, 0xA, 0x12, 0x2, 0x22, - 0x1C6, 0x2C6, 0x6C6, 0xEC6, -}; - -static const uint8_t amplitude_diff_bits[] = { - 8, 2, 1, 3, 4, 5, 6, 7, 8, -}; - -static const uint8_t amplitude_diff_codes[] = { - 0xFE, 0x0, 0x1, 0x2, 0x6, 0xE, 0x1E, 0x3E, 0x7E, -}; - -static const uint8_t phase_diff_bits[] = { - 6, 2, 2, 4, 4, 6, 5, 4, 2, -}; - -static const uint8_t phase_diff_codes[] = { - 0x35, 0x2, 0x0, 0x1, 0xD, 0x15, 0x5, 0x9, 0x3, -}; - -#define INIT_VLC_STATIC_LE(vlc, nb_bits, nb_codes, \ - bits, bits_wrap, bits_size, \ - codes, codes_wrap, codes_size, \ - symbols, symbols_wrap, symbols_size, \ - static_size) \ - do { \ - static VLC_TYPE table[static_size][2]; \ - (vlc)->table = table; \ - (vlc)->table_allocated = static_size; \ - ff_init_vlc_sparse(vlc, nb_bits, nb_codes, \ - bits, bits_wrap, bits_size, \ - codes, codes_wrap, codes_size, \ - symbols, symbols_wrap, symbols_size, \ - INIT_VLC_LE | INIT_VLC_USE_NEW_STATIC); \ - } while (0) - static av_cold void qdmc_init_static_data(void) { + const uint8_t (*hufftab)[2] = qdmc_hufftab; int i; - INIT_VLC_STATIC_LE(&vtable[0], 12, FF_ARRAY_ELEMS(noise_value_bits), - noise_value_bits, 1, 1, noise_value_codes, 2, 2, noise_value_symbols, 1, 1, 4096); - INIT_VLC_STATIC_LE(&vtable[1], 10, FF_ARRAY_ELEMS(noise_segment_length_bits), - noise_segment_length_bits, 1, 1, noise_segment_length_codes, 2, 2, - noise_segment_length_symbols, 1, 1, 1024); - INIT_VLC_STATIC_LE(&vtable[2], 13, FF_ARRAY_ELEMS(amplitude_bits), - amplitude_bits, 1, 1, amplitude_codes, 2, 2, NULL, 0, 0, 8192); - INIT_VLC_STATIC_LE(&vtable[3], 18, FF_ARRAY_ELEMS(freq_diff_bits), - freq_diff_bits, 1, 1, freq_diff_codes, 4, 4, NULL, 0, 0, 262144); - INIT_VLC_STATIC_LE(&vtable[4], 8, FF_ARRAY_ELEMS(amplitude_diff_bits), - amplitude_diff_bits, 1, 1, amplitude_diff_codes, 1, 1, NULL, 0, 0, 256); - INIT_VLC_STATIC_LE(&vtable[5], 6, FF_ARRAY_ELEMS(phase_diff_bits), - phase_diff_bits, 1, 1, phase_diff_codes, 1, 1, NULL, 0, 0, 64); + for (unsigned i = 0, offset = 0; i < FF_ARRAY_ELEMS(vtable); i++) { + static VLC_TYPE vlc_buffer[13698][2]; + vtable[i].table = &vlc_buffer[offset]; + vtable[i].table_allocated = FF_ARRAY_ELEMS(vlc_buffer) - offset; + ff_init_vlc_from_lengths(&vtable[i], huff_bits[i], huff_sizes[i], + &hufftab[0][1], 2, &hufftab[0][0], 2, 1, -1, + INIT_VLC_LE | INIT_VLC_STATIC_OVERLONG, NULL); + hufftab += huff_sizes[i]; + offset += vtable[i].table_size; + } for (i = 0; i < 512; i++) sin_table[i] = sin(2.0f * i * M_PI * 0.001953125f); @@ -369,12 +322,8 @@ if (get_bits_left(gb) < 1) return AVERROR_INVALIDDATA; - v = get_vlc2(gb, table->table, table->bits, 1); + v = get_vlc2(gb, table->table, table->bits, 2); if (v < 0) - return AVERROR_INVALIDDATA; - if (v) - v = v - 1; - else v = get_bits(gb, get_bits(gb, 3) + 1); if (flag) { @@ -786,5 +735,6 @@ .close = qdmc_decode_close, .decode = qdmc_decode_frame, .flush = qdmc_flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/qpeg.c ffmpeg-4.4/libavcodec/qpeg.c --- ffmpeg-4.2.2/libavcodec/qpeg.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qpeg.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,7 +30,7 @@ typedef struct QpegContext{ AVCodecContext *avctx; - AVFrame *pic, *ref; + AVFrame *ref; uint32_t pal[256]; GetByteContext buffer; } QpegContext; @@ -101,8 +101,11 @@ } else { if (bytestream2_get_bytes_left(&qctx->buffer) < copy) copy = bytestream2_get_bytes_left(&qctx->buffer); - for(i = 0; i < copy; i++) { - dst[filled++] = bytestream2_get_byte(&qctx->buffer); + while (copy > 0) { + int step = FFMIN(copy, width - filled); + bytestream2_get_bufferu(&qctx->buffer, dst + filled, step); + filled += step; + copy -= step; if (filled >= width) { filled = 0; dst -= stride; @@ -115,9 +118,9 @@ } } -static const int qpeg_table_h[16] = +static const uint8_t qpeg_table_h[16] = { 0x00, 0x20, 0x20, 0x20, 0x18, 0x10, 0x10, 0x20, 0x10, 0x08, 0x18, 0x08, 0x08, 0x18, 0x10, 0x04}; -static const int qpeg_table_w[16] = +static const uint8_t qpeg_table_w[16] = { 0x00, 0x20, 0x18, 0x08, 0x18, 0x10, 0x20, 0x10, 0x08, 0x10, 0x20, 0x20, 0x08, 0x10, 0x18, 0x04}; /* Decodes delta frames */ @@ -267,11 +270,11 @@ { uint8_t ctable[128]; QpegContext * const a = avctx->priv_data; - AVFrame * const p = a->pic; + AVFrame * const p = data; AVFrame * const ref = a->ref; uint8_t* outdata; - int delta, ret; - int pal_size; + int delta, intra, ret; + buffer_size_t pal_size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size); if (avpkt->size < 0x86) { @@ -281,9 +284,6 @@ bytestream2_init(&a->buffer, avpkt->data, avpkt->size); - av_frame_unref(ref); - av_frame_move_ref(ref, p); - if ((ret = ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; outdata = p->data[0]; @@ -292,7 +292,8 @@ bytestream2_skip(&a->buffer, 1); delta = bytestream2_get_byte(&a->buffer); - if(delta == 0x10) { + intra = delta == 0x10; + if (intra) { qpeg_decode_intra(a, outdata, p->linesize[0], avctx->width, avctx->height); } else { qpeg_decode_inter(a, outdata, p->linesize[0], avctx->width, avctx->height, delta, ctable, ref->data[0]); @@ -307,9 +308,13 @@ } memcpy(p->data[1], a->pal, AVPALETTE_SIZE); - if ((ret = av_frame_ref(data, p)) < 0) + av_frame_unref(ref); + if ((ret = av_frame_ref(ref, p)) < 0) return ret; + p->key_frame = intra; + p->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + *got_frame = 1; return avpkt->size; @@ -320,6 +325,8 @@ int i, pal_size; const uint8_t *pal_src; + av_frame_unref(a->ref); + pal_size = FFMIN(1024U, avctx->extradata_size); pal_src = avctx->extradata + avctx->extradata_size - pal_size; @@ -331,7 +338,6 @@ { QpegContext * const a = avctx->priv_data; - av_frame_free(&a->pic); av_frame_free(&a->ref); return 0; @@ -343,14 +349,11 @@ a->avctx = avctx; avctx->pix_fmt= AV_PIX_FMT_PAL8; - decode_flush(avctx); - - a->pic = av_frame_alloc(); a->ref = av_frame_alloc(); - if (!a->pic || !a->ref) { - decode_end(avctx); + if (!a->ref) return AVERROR(ENOMEM); - } + + decode_flush(avctx); return 0; } @@ -366,4 +369,6 @@ .decode = decode_frame, .flush = decode_flush, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/qsv.c ffmpeg-4.4/libavcodec/qsv.c --- ffmpeg-4.2.2/libavcodec/qsv.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsv.c 2021-04-08 21:28:39.000000000 +0000 @@ -60,63 +60,20 @@ #endif case AV_CODEC_ID_MJPEG: return MFX_CODEC_JPEG; - default: - break; - } - - return AVERROR(ENOSYS); -} - - -static const struct { - enum AVCodecID codec_id; - int codec_profile; - int mfx_profile; -} qsv_profile_map[] = { -#define MAP(c, p, v) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, MFX_PROFILE_ ## v } - MAP(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2_SIMPLE ), - MAP(MPEG2VIDEO, MPEG2_MAIN, MPEG2_MAIN ), - MAP(MPEG2VIDEO, MPEG2_HIGH, MPEG2_HIGH ), - - MAP(H264, H264_BASELINE, AVC_BASELINE ), - MAP(H264, H264_CONSTRAINED_BASELINE, AVC_BASELINE), -#if QSV_VERSION_ATLEAST(1, 3) - MAP(H264, H264_EXTENDED, AVC_EXTENDED ), -#endif - MAP(H264, H264_MAIN, AVC_MAIN ), - MAP(H264, H264_HIGH, AVC_HIGH ), - MAP(H264, H264_HIGH_422, AVC_HIGH_422 ), - -#if QSV_VERSION_ATLEAST(1, 8) - MAP(HEVC, HEVC_MAIN, HEVC_MAIN ), - MAP(HEVC, HEVC_MAIN_10, HEVC_MAIN10 ), - MAP(HEVC, HEVC_MAIN_STILL_PICTURE, HEVC_MAINSP ), +#if QSV_VERSION_ATLEAST(1, 19) + case AV_CODEC_ID_VP9: + return MFX_CODEC_VP9; #endif -#if QSV_VERSION_ATLEAST(1, 16) - MAP(HEVC, HEVC_REXT, HEVC_REXT ), +#if QSV_VERSION_ATLEAST(1, 34) + case AV_CODEC_ID_AV1: + return MFX_CODEC_AV1; #endif - MAP(VC1, VC1_SIMPLE, VC1_SIMPLE ), - MAP(VC1, VC1_MAIN, VC1_MAIN ), - MAP(VC1, VC1_COMPLEX, VC1_ADVANCED ), - MAP(VC1, VC1_ADVANCED, VC1_ADVANCED ), -#undef MAP -}; - -int ff_qsv_profile_to_mfx(enum AVCodecID codec_id, int profile) -{ - int i; - if (profile == FF_PROFILE_UNKNOWN) - return MFX_PROFILE_UNKNOWN; - - for (i = 0; i < FF_ARRAY_ELEMS(qsv_profile_map); i++) { - if (qsv_profile_map[i].codec_id != codec_id) - continue; - if (qsv_profile_map[i].codec_profile == profile) - return qsv_profile_map[i].mfx_profile; + default: + break; } - return MFX_PROFILE_UNKNOWN; + return AVERROR(ENOSYS); } int ff_qsv_level_to_mfx(enum AVCodecID codec_id, int level) @@ -133,6 +90,35 @@ } static const struct { + int mfx_iopattern; + const char *desc; +} qsv_iopatterns[] = { + {MFX_IOPATTERN_IN_VIDEO_MEMORY, "input is video memory surface" }, + {MFX_IOPATTERN_IN_SYSTEM_MEMORY, "input is system memory surface" }, + {MFX_IOPATTERN_IN_OPAQUE_MEMORY, "input is opaque memory surface" }, + {MFX_IOPATTERN_OUT_VIDEO_MEMORY, "output is video memory surface" }, + {MFX_IOPATTERN_OUT_SYSTEM_MEMORY, "output is system memory surface" }, + {MFX_IOPATTERN_OUT_OPAQUE_MEMORY, "output is opaque memory surface" }, +}; + +int ff_qsv_print_iopattern(void *log_ctx, int mfx_iopattern, + const char *extra_string) +{ + const char *desc = NULL; + + for (int i = 0; i < FF_ARRAY_ELEMS(qsv_iopatterns); i++) { + if (qsv_iopatterns[i].mfx_iopattern == mfx_iopattern) { + desc = qsv_iopatterns[i].desc; + } + } + if (!desc) + desc = "unknown iopattern"; + + av_log(log_ctx, AV_LOG_VERBOSE, "%s: %s\n", extra_string, desc); + return 0; +} + +static const struct { mfxStatus mfxerr; int averr; const char *desc; @@ -207,12 +193,18 @@ return ret; } -static enum AVPixelFormat qsv_map_fourcc(uint32_t fourcc) +enum AVPixelFormat ff_qsv_map_fourcc(uint32_t fourcc) { switch (fourcc) { case MFX_FOURCC_NV12: return AV_PIX_FMT_NV12; case MFX_FOURCC_P010: return AV_PIX_FMT_P010; case MFX_FOURCC_P8: return AV_PIX_FMT_PAL8; +#if CONFIG_VAAPI + case MFX_FOURCC_YUY2: return AV_PIX_FMT_YUYV422; +#if QSV_VERSION_ATLEAST(1, 27) + case MFX_FOURCC_Y210: return AV_PIX_FMT_Y210; +#endif +#endif } return AV_PIX_FMT_NONE; } @@ -229,6 +221,18 @@ case AV_PIX_FMT_P010: *fourcc = MFX_FOURCC_P010; return AV_PIX_FMT_P010; +#if CONFIG_VAAPI + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUYV422: + *fourcc = MFX_FOURCC_YUY2; + return AV_PIX_FMT_YUYV422; +#if QSV_VERSION_ATLEAST(1, 27) + case AV_PIX_FMT_YUV422P10: + case AV_PIX_FMT_Y210: + *fourcc = MFX_FOURCC_Y210; + return AV_PIX_FMT_Y210; +#endif +#endif default: return AVERROR(ENOSYS); } @@ -245,6 +249,24 @@ return AVERROR_BUG; } +enum AVFieldOrder ff_qsv_map_picstruct(int mfx_pic_struct) +{ + enum AVFieldOrder field = AV_FIELD_UNKNOWN; + switch (mfx_pic_struct & 0xF) { + case MFX_PICSTRUCT_PROGRESSIVE: + field = AV_FIELD_PROGRESSIVE; + break; + case MFX_PICSTRUCT_FIELD_TFF: + field = AV_FIELD_TT; + break; + case MFX_PICSTRUCT_FIELD_BFF: + field = AV_FIELD_BB; + break; + } + + return field; +} + enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type) { enum AVPictureType type; @@ -325,27 +347,72 @@ } -int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, - const char *load_plugins) +//This code is only required for Linux since a display handle is required. +//For Windows the session is complete and ready to use. + +#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE +static int ff_qsv_set_display_handle(AVCodecContext *avctx, QSVSession *qs) +{ + AVDictionary *child_device_opts = NULL; + AVVAAPIDeviceContext *hwctx; + int ret; + + av_dict_set(&child_device_opts, "kernel_driver", "i915", 0); + av_dict_set(&child_device_opts, "driver", "iHD", 0); + + ret = av_hwdevice_ctx_create(&qs->va_device_ref, AV_HWDEVICE_TYPE_VAAPI, NULL, child_device_opts, 0); + av_dict_free(&child_device_opts); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to create a VAAPI device.\n"); + return ret; + } else { + qs->va_device_ctx = (AVHWDeviceContext*)qs->va_device_ref->data; + hwctx = qs->va_device_ctx->hwctx; + + ret = MFXVideoCORE_SetHandle(qs->session, + (mfxHandleType)MFX_HANDLE_VA_DISPLAY, (mfxHDL)hwctx->display); + if (ret < 0) { + return ff_qsv_print_error(avctx, ret, "Error during set display handle\n"); + } + } + + return 0; +} +#endif //AVCODEC_QSV_LINUX_SESSION_HANDLE + +int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, + const char *load_plugins, int gpu_copy) { - mfxIMPL impl = MFX_IMPL_AUTO_ANY; - mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } }; + mfxIMPL impl = MFX_IMPL_AUTO_ANY; + mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } }; + mfxInitParam init_par = { MFX_IMPL_AUTO_ANY }; const char *desc; int ret; - ret = MFXInit(impl, &ver, session); +#if QSV_VERSION_ATLEAST(1, 16) + init_par.GPUCopy = gpu_copy; +#endif + init_par.Implementation = impl; + init_par.Version = ver; + ret = MFXInitEx(init_par, &qs->session); if (ret < 0) return ff_qsv_print_error(avctx, ret, "Error initializing an internal MFX session"); - ret = qsv_load_plugins(*session, load_plugins, avctx); +#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE + ret = ff_qsv_set_display_handle(avctx, qs); + if (ret < 0) + return ret; +#endif + + ret = qsv_load_plugins(qs->session, load_plugins, avctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n"); return ret; } - MFXQueryIMPL(*session, &impl); + MFXQueryIMPL(qs->session, &impl); switch (MFX_IMPL_BASETYPE(impl)) { case MFX_IMPL_SOFTWARE: @@ -500,7 +567,7 @@ frames_hwctx = frames_ctx->hwctx; frames_ctx->format = AV_PIX_FMT_QSV; - frames_ctx->sw_format = qsv_map_fourcc(i->FourCC); + frames_ctx->sw_format = ff_qsv_map_fourcc(i->FourCC); frames_ctx->width = i->Width; frames_ctx->height = i->Height; frames_ctx->initial_pool_size = req->NumFrameSuggested; @@ -620,7 +687,8 @@ } int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, - AVBufferRef *device_ref, const char *load_plugins) + AVBufferRef *device_ref, const char *load_plugins, + int gpu_copy) { static const mfxHandleType handle_types[] = { MFX_HANDLE_VA_DISPLAY, @@ -630,11 +698,12 @@ AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref->data; AVQSVDeviceContext *device_hwctx = device_ctx->hwctx; mfxSession parent_session = device_hwctx->session; + mfxInitParam init_par = { MFX_IMPL_AUTO_ANY }; + mfxHDL handle = NULL; mfxSession session; mfxVersion ver; mfxIMPL impl; - mfxHDL handle = NULL; mfxHandleType handle_type; mfxStatus err; @@ -660,7 +729,12 @@ "from the session\n"); } - err = MFXInit(impl, &ver, &session); +#if QSV_VERSION_ATLEAST(1, 16) + init_par.GPUCopy = gpu_copy; +#endif + init_par.Implementation = impl; + init_par.Version = ver; + err = MFXInitEx(init_par, &session); if (err != MFX_ERR_NONE) return ff_qsv_print_error(avctx, err, "Error initializing a child MFX session"); @@ -691,7 +765,7 @@ int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *psession, QSVFramesContext *qsv_frames_ctx, - const char *load_plugins, int opaque) + const char *load_plugins, int opaque, int gpu_copy) { mfxFrameAllocator frame_allocator = { .pthis = qsv_frames_ctx, @@ -711,7 +785,7 @@ int ret; ret = ff_qsv_init_session_device(avctx, &session, - frames_ctx->device_ref, load_plugins); + frames_ctx->device_ref, load_plugins, gpu_copy); if (ret < 0) return ret; @@ -735,3 +809,15 @@ *psession = session; return 0; } + +int ff_qsv_close_internal_session(QSVSession *qs) +{ + if (qs->session) { + MFXClose(qs->session); + qs->session = NULL; + } +#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE + av_buffer_unref(&qs->va_device_ref); +#endif + return 0; +} diff -Nru ffmpeg-4.2.2/libavcodec/qsvdec.c ffmpeg-4.4/libavcodec/qsvdec.c --- ffmpeg-4.2.2/libavcodec/qsvdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsvdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,27 +21,70 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include #include "libavutil/common.h" +#include "libavutil/fifo.h" +#include "libavutil/frame.h" #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_qsv.h" #include "libavutil/mem.h" #include "libavutil/log.h" -#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" #include "libavutil/pixfmt.h" #include "libavutil/time.h" +#include "libavutil/imgutils.h" #include "avcodec.h" #include "internal.h" +#include "decode.h" +#include "hwconfig.h" #include "qsv.h" #include "qsv_internal.h" -#include "qsvdec.h" -const AVCodecHWConfigInternal *ff_qsv_hw_configs[] = { +typedef struct QSVContext { + // the session used for decoding + mfxSession session; + + // the session we allocated internally, in case the caller did not provide + // one + QSVSession internal_qs; + + QSVFramesContext frames_ctx; + + /** + * a linked list of frames currently being used by QSV + */ + QSVFrame *work_frames; + + AVFifoBuffer *async_fifo; + int zero_consume_run; + int buffered_count; + int reinit_flag; + + enum AVPixelFormat orig_pix_fmt; + uint32_t fourcc; + mfxFrameInfo frame_info; + AVBufferPool *pool; + + int initialized; + + // options set by the caller + int async_depth; + int iopattern; + int gpu_copy; + + char *load_plugins; + + mfxExtBuffer **ext_buffers; + int nb_ext_buffers; +} QSVContext; + +static const AVCodecHWConfigInternal *const qsv_hw_configs[] = { &(const AVCodecHWConfigInternal) { .public = { .pix_fmt = AV_PIX_FMT_QSV, @@ -54,17 +97,61 @@ NULL }; +static int qsv_get_continuous_buffer(AVCodecContext *avctx, AVFrame *frame, + AVBufferPool *pool) +{ + int ret = 0; + + ff_decode_frame_props(avctx, frame); + + frame->width = avctx->width; + frame->height = avctx->height; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_NV12: + frame->linesize[0] = FFALIGN(avctx->width, 128); + break; + case AV_PIX_FMT_P010: + frame->linesize[0] = 2 * FFALIGN(avctx->width, 128); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format.\n"); + return AVERROR(EINVAL); + } + + frame->linesize[1] = frame->linesize[0]; + frame->buf[0] = av_buffer_pool_get(pool); + if (!frame->buf[0]) + return AVERROR(ENOMEM); + + frame->data[0] = frame->buf[0]->data; + frame->data[1] = frame->data[0] + + frame->linesize[0] * FFALIGN(avctx->height, 64); + + ret = ff_attach_decode_data(frame); + if (ret < 0) + return ret; + + return 0; +} + static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session, AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref) { int ret; + if (q->gpu_copy == MFX_GPUCOPY_ON && + !(q->iopattern & MFX_IOPATTERN_OUT_SYSTEM_MEMORY)) { + av_log(avctx, AV_LOG_WARNING, "GPU-accelerated memory copy " + "only works in system memory mode.\n"); + q->gpu_copy = MFX_GPUCOPY_OFF; + } if (session) { q->session = session; } else if (hw_frames_ref) { - if (q->internal_session) { - MFXClose(q->internal_session); - q->internal_session = NULL; + if (q->internal_qs.session) { + MFXClose(q->internal_qs.session); + q->internal_qs.session = NULL; } av_buffer_unref(&q->frames_ctx.hw_frames_ctx); @@ -72,36 +159,37 @@ if (!q->frames_ctx.hw_frames_ctx) return AVERROR(ENOMEM); - ret = ff_qsv_init_session_frames(avctx, &q->internal_session, + ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session, &q->frames_ctx, q->load_plugins, - q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY); + q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY, + q->gpu_copy); if (ret < 0) { av_buffer_unref(&q->frames_ctx.hw_frames_ctx); return ret; } - q->session = q->internal_session; + q->session = q->internal_qs.session; } else if (hw_device_ref) { - if (q->internal_session) { - MFXClose(q->internal_session); - q->internal_session = NULL; + if (q->internal_qs.session) { + MFXClose(q->internal_qs.session); + q->internal_qs.session = NULL; } - ret = ff_qsv_init_session_device(avctx, &q->internal_session, - hw_device_ref, q->load_plugins); + ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session, + hw_device_ref, q->load_plugins, q->gpu_copy); if (ret < 0) return ret; - q->session = q->internal_session; + q->session = q->internal_qs.session; } else { - if (!q->internal_session) { - ret = ff_qsv_init_internal_session(avctx, &q->internal_session, - q->load_plugins); + if (!q->internal_qs.session) { + ret = ff_qsv_init_internal_session(avctx, &q->internal_qs, + q->load_plugins, q->gpu_copy); if (ret < 0) return ret; } - q->session = q->internal_session; + q->session = q->internal_qs.session; } /* make sure the decoder is uninitialized */ @@ -120,46 +208,21 @@ return av_fifo_size(fifo) / qsv_fifo_item_size(); } -static int check_dec_param(AVCodecContext *avctx, QSVContext *q, mfxVideoParam *param_in) -{ - mfxVideoParam param_out = { .mfx.CodecId = param_in->mfx.CodecId }; - mfxStatus ret; - -#define CHECK_MATCH(x) \ - do { \ - if (param_out.mfx.x != param_in->mfx.x) { \ - av_log(avctx, AV_LOG_WARNING, "Required "#x" %d is unsupported\n", \ - param_in->mfx.x); \ - } \ - } while (0) - - ret = MFXVideoDECODE_Query(q->session, param_in, ¶m_out); - - if (ret < 0) { - CHECK_MATCH(CodecId); - CHECK_MATCH(CodecProfile); - CHECK_MATCH(CodecLevel); - CHECK_MATCH(FrameInfo.Width); - CHECK_MATCH(FrameInfo.Height); -#undef CHECK_MATCH - return 0; - } - return 1; -} - -static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q) +static int qsv_decode_preinit(AVCodecContext *avctx, QSVContext *q, enum AVPixelFormat pix_fmt, mfxVideoParam *param) { - const AVPixFmtDescriptor *desc; mfxSession session = NULL; int iopattern = 0; - mfxVideoParam param = { 0 }; - int frame_width = avctx->coded_width; - int frame_height = avctx->coded_height; int ret; + enum AVPixelFormat pix_fmts[3] = { + AV_PIX_FMT_QSV, /* opaque format in case of video memory output */ + pix_fmt, /* system memory format obtained from bitstream parser */ + AV_PIX_FMT_NONE }; - desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); - if (!desc) - return AVERROR_BUG; + ret = ff_get_format(avctx, pix_fmts); + if (ret < 0) { + q->orig_pix_fmt = avctx->pix_fmt = AV_PIX_FMT_NONE; + return ret; + } if (!q->async_fifo) { q->async_fifo = av_fifo_alloc(q->async_depth * qsv_fifo_item_size()); @@ -191,60 +254,85 @@ iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; q->iopattern = iopattern; + ff_qsv_print_iopattern(avctx, q->iopattern, "Decoder"); + ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx, avctx->hw_device_ctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n"); return ret; } - ret = ff_qsv_codec_id_to_mfx(avctx->codec_id); - if (ret < 0) - return ret; + param->IOPattern = q->iopattern; + param->AsyncDepth = q->async_depth; + param->ExtParam = q->ext_buffers; + param->NumExtParam = q->nb_ext_buffers; - param.mfx.CodecId = ret; - param.mfx.CodecProfile = ff_qsv_profile_to_mfx(avctx->codec_id, avctx->profile); - param.mfx.CodecLevel = ff_qsv_level_to_mfx(avctx->codec_id, avctx->level); - - param.mfx.FrameInfo.BitDepthLuma = desc->comp[0].depth; - param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth; - param.mfx.FrameInfo.Shift = desc->comp[0].depth > 8; - param.mfx.FrameInfo.FourCC = q->fourcc; - param.mfx.FrameInfo.Width = frame_width; - param.mfx.FrameInfo.Height = frame_height; - param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; - - switch (avctx->field_order) { - case AV_FIELD_PROGRESSIVE: - param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; - break; - case AV_FIELD_TT: - param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_FIELD_TFF; - break; - case AV_FIELD_BB: - param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_FIELD_BFF; - break; - default: - param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_UNKNOWN; - break; - } + return 0; + } - param.IOPattern = q->iopattern; - param.AsyncDepth = q->async_depth; - param.ExtParam = q->ext_buffers; - param.NumExtParam = q->nb_ext_buffers; - - if (!check_dec_param(avctx, q, ¶m)) { - //Just give a warning instead of an error since it is still decodable possibly. - av_log(avctx, AV_LOG_WARNING, - "Current input bitstream is not supported by QSV decoder.\n"); - } +static int qsv_decode_init_context(AVCodecContext *avctx, QSVContext *q, mfxVideoParam *param) +{ + int ret; + + avctx->width = param->mfx.FrameInfo.CropW; + avctx->height = param->mfx.FrameInfo.CropH; + avctx->coded_width = param->mfx.FrameInfo.Width; + avctx->coded_height = param->mfx.FrameInfo.Height; + avctx->level = param->mfx.CodecLevel; + avctx->profile = param->mfx.CodecProfile; + avctx->field_order = ff_qsv_map_picstruct(param->mfx.FrameInfo.PicStruct); + avctx->pix_fmt = ff_qsv_map_fourcc(param->mfx.FrameInfo.FourCC); - ret = MFXVideoDECODE_Init(q->session, ¶m); + ret = MFXVideoDECODE_Init(q->session, param); if (ret < 0) return ff_qsv_print_error(avctx, ret, "Error initializing the MFX video decoder"); - q->frame_info = param.mfx.FrameInfo; + q->frame_info = param->mfx.FrameInfo; + + if (!avctx->hw_frames_ctx) + q->pool = av_buffer_pool_init(av_image_get_buffer_size(avctx->pix_fmt, + FFALIGN(avctx->width, 128), FFALIGN(avctx->height, 64), 1), av_buffer_allocz); + return 0; +} + +static int qsv_decode_header(AVCodecContext *avctx, QSVContext *q, + const AVPacket *avpkt, enum AVPixelFormat pix_fmt, + mfxVideoParam *param) +{ + int ret; + + mfxBitstream bs = { 0 }; + + if (avpkt->size) { + bs.Data = avpkt->data; + bs.DataLength = avpkt->size; + bs.MaxLength = bs.DataLength; + bs.TimeStamp = avpkt->pts; + if (avctx->field_order == AV_FIELD_PROGRESSIVE) + bs.DataFlag |= MFX_BITSTREAM_COMPLETE_FRAME; + } else + return AVERROR_INVALIDDATA; + + + if(!q->session) { + ret = qsv_decode_preinit(avctx, q, pix_fmt, param); + if (ret < 0) + return ret; + } + + ret = ff_qsv_codec_id_to_mfx(avctx->codec_id); + if (ret < 0) + return ret; + + param->mfx.CodecId = ret; + ret = MFXVideoDECODE_DecodeHeader(q->session, &bs, param); + if (MFX_ERR_MORE_DATA == ret) { + return AVERROR(EAGAIN); + } + if (ret < 0) + return ff_qsv_print_error(avctx, ret, + "Error decoding stream header"); return 0; } @@ -253,7 +341,11 @@ { int ret; - ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF); + if (q->pool) + ret = qsv_get_continuous_buffer(avctx, frame->frame, q->pool); + else + ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF); + if (ret < 0) return ret; @@ -351,7 +443,7 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, AVFrame *frame, int *got_frame, - AVPacket *avpkt) + const AVPacket *avpkt) { QSVFrame *out_frame; mfxFrameSurface1 *insurf; @@ -482,7 +574,7 @@ return bs.DataOffset; } -int ff_qsv_decode_close(QSVContext *q) +static void qsv_decode_close_qsvcontext(QSVContext *q) { QSVFrame *cur = q->work_frames; @@ -509,60 +601,40 @@ av_fifo_free(q->async_fifo); q->async_fifo = NULL; - av_parser_close(q->parser); - avcodec_free_context(&q->avctx_internal); - - if (q->internal_session) - MFXClose(q->internal_session); + ff_qsv_close_internal_session(&q->internal_qs); av_buffer_unref(&q->frames_ctx.hw_frames_ctx); av_buffer_unref(&q->frames_ctx.mids_buf); - - return 0; + av_buffer_pool_uninit(&q->pool); } -int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, - AVFrame *frame, int *got_frame, AVPacket *pkt) +static int qsv_process_data(AVCodecContext *avctx, QSVContext *q, + AVFrame *frame, int *got_frame, const AVPacket *pkt) { - uint8_t *dummy_data; - int dummy_size; int ret; - const AVPixFmtDescriptor *desc; - - if (!q->avctx_internal) { - q->avctx_internal = avcodec_alloc_context3(NULL); - if (!q->avctx_internal) - return AVERROR(ENOMEM); - - q->avctx_internal->codec_id = avctx->codec_id; - - q->parser = av_parser_init(avctx->codec_id); - if (!q->parser) - return AVERROR(ENOMEM); - - q->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - q->orig_pix_fmt = AV_PIX_FMT_NONE; - } + mfxVideoParam param = { 0 }; + enum AVPixelFormat pix_fmt = AV_PIX_FMT_NV12; if (!pkt->size) return qsv_decode(avctx, q, frame, got_frame, pkt); - /* we assume the packets are already split properly and want - * just the codec parameters here */ - av_parser_parse2(q->parser, q->avctx_internal, - &dummy_data, &dummy_size, - pkt->data, pkt->size, pkt->pts, pkt->dts, - pkt->pos); - - avctx->field_order = q->parser->field_order; /* TODO: flush delayed frames on reinit */ - if (q->parser->format != q->orig_pix_fmt || - FFALIGN(q->parser->coded_width, 16) != FFALIGN(avctx->coded_width, 16) || - FFALIGN(q->parser->coded_height, 16) != FFALIGN(avctx->coded_height, 16)) { - enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_QSV, - AV_PIX_FMT_NONE, - AV_PIX_FMT_NONE }; - enum AVPixelFormat qsv_format; + + // sw_pix_fmt, coded_width/height should be set for ff_get_format(), + // assume sw_pix_fmt is NV12 and coded_width/height to be 1280x720, + // the assumption may be not corret but will be updated after header decoded if not true. + if (q->orig_pix_fmt != AV_PIX_FMT_NONE) + pix_fmt = q->orig_pix_fmt; + if (!avctx->coded_width) + avctx->coded_width = 1280; + if (!avctx->coded_height) + avctx->coded_height = 720; + + ret = qsv_decode_header(avctx, q, pkt, pix_fmt, ¶m); + + if (ret >= 0 && (q->orig_pix_fmt != ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC) || + avctx->coded_width != param.mfx.FrameInfo.Width || + avctx->coded_height != param.mfx.FrameInfo.Height)) { AVPacket zero_pkt = {0}; if (q->buffered_count) { @@ -571,55 +643,275 @@ q->buffered_count--; return qsv_decode(avctx, q, frame, got_frame, &zero_pkt); } - q->reinit_flag = 0; - qsv_format = ff_qsv_map_pixfmt(q->parser->format, &q->fourcc); - if (qsv_format < 0) { - av_log(avctx, AV_LOG_ERROR, - "Decoding pixel format '%s' is not supported\n", - av_get_pix_fmt_name(q->parser->format)); - ret = AVERROR(ENOSYS); - goto reinit_fail; - } + q->orig_pix_fmt = avctx->pix_fmt = pix_fmt = ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC); - q->orig_pix_fmt = q->parser->format; - avctx->pix_fmt = pix_fmts[1] = qsv_format; - avctx->width = q->parser->width; - avctx->height = q->parser->height; - avctx->coded_width = FFALIGN(q->parser->coded_width, 16); - avctx->coded_height = FFALIGN(q->parser->coded_height, 16); - avctx->level = q->avctx_internal->level; - avctx->profile = q->avctx_internal->profile; + avctx->coded_width = param.mfx.FrameInfo.Width; + avctx->coded_height = param.mfx.FrameInfo.Height; - ret = ff_get_format(avctx, pix_fmts); + ret = qsv_decode_preinit(avctx, q, pix_fmt, ¶m); if (ret < 0) goto reinit_fail; + q->initialized = 0; + } - avctx->pix_fmt = ret; - - desc = av_pix_fmt_desc_get(avctx->pix_fmt); - if (!desc) - goto reinit_fail; - - if (desc->comp[0].depth > 8) { - avctx->coded_width = FFALIGN(q->parser->coded_width, 32); - avctx->coded_height = FFALIGN(q->parser->coded_height, 32); - } - - ret = qsv_decode_init(avctx, q); + if (!q->initialized) { + ret = qsv_decode_init_context(avctx, q, ¶m); if (ret < 0) goto reinit_fail; + q->initialized = 1; } return qsv_decode(avctx, q, frame, got_frame, pkt); reinit_fail: - q->orig_pix_fmt = q->parser->format = avctx->pix_fmt = AV_PIX_FMT_NONE; + q->orig_pix_fmt = avctx->pix_fmt = AV_PIX_FMT_NONE; + return ret; +} + +enum LoadPlugin { + LOAD_PLUGIN_NONE, + LOAD_PLUGIN_HEVC_SW, + LOAD_PLUGIN_HEVC_HW, +}; + +typedef struct QSVDecContext { + AVClass *class; + QSVContext qsv; + + int load_plugin; + + AVFifoBuffer *packet_fifo; + + AVPacket buffer_pkt; +} QSVDecContext; + +static void qsv_clear_buffers(QSVDecContext *s) +{ + AVPacket pkt; + while (av_fifo_size(s->packet_fifo) >= sizeof(pkt)) { + av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL); + av_packet_unref(&pkt); + } + + av_packet_unref(&s->buffer_pkt); +} + +static av_cold int qsv_decode_close(AVCodecContext *avctx) +{ + QSVDecContext *s = avctx->priv_data; + + av_freep(&s->qsv.load_plugins); + + qsv_decode_close_qsvcontext(&s->qsv); + + qsv_clear_buffers(s); + + av_fifo_free(s->packet_fifo); + + return 0; +} + +static av_cold int qsv_decode_init(AVCodecContext *avctx) +{ + QSVDecContext *s = avctx->priv_data; + int ret; + const char *uid = NULL; + + if (avctx->codec_id == AV_CODEC_ID_VP8) { + uid = "f622394d8d87452f878c51f2fc9b4131"; + } else if (avctx->codec_id == AV_CODEC_ID_VP9) { + uid = "a922394d8d87452f878c51f2fc9b4131"; + } + else if (avctx->codec_id == AV_CODEC_ID_HEVC && s->load_plugin != LOAD_PLUGIN_NONE) { + static const char * const uid_hevcdec_sw = "15dd936825ad475ea34e35f3f54217a6"; + static const char * const uid_hevcdec_hw = "33a61c0b4c27454ca8d85dde757c6f8e"; + + if (s->qsv.load_plugins[0]) { + av_log(avctx, AV_LOG_WARNING, + "load_plugins is not empty, but load_plugin is not set to 'none'." + "The load_plugin value will be ignored.\n"); + } else { + if (s->load_plugin == LOAD_PLUGIN_HEVC_SW) + uid = uid_hevcdec_sw; + else + uid = uid_hevcdec_hw; + } + } + if (uid) { + av_freep(&s->qsv.load_plugins); + s->qsv.load_plugins = av_strdup(uid); + if (!s->qsv.load_plugins) + return AVERROR(ENOMEM); + } + + s->qsv.orig_pix_fmt = AV_PIX_FMT_NV12; + s->packet_fifo = av_fifo_alloc(sizeof(AVPacket)); + if (!s->packet_fifo) { + ret = AVERROR(ENOMEM); + goto fail; + } + + return 0; +fail: + qsv_decode_close(avctx); return ret; } -void ff_qsv_decode_flush(AVCodecContext *avctx, QSVContext *q) +static int qsv_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) { - q->orig_pix_fmt = AV_PIX_FMT_NONE; + QSVDecContext *s = avctx->priv_data; + AVFrame *frame = data; + int ret; + + /* buffer the input packet */ + if (avpkt->size) { + AVPacket input_ref; + + if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) { + ret = av_fifo_realloc2(s->packet_fifo, + av_fifo_size(s->packet_fifo) + sizeof(input_ref)); + if (ret < 0) + return ret; + } + + ret = av_packet_ref(&input_ref, avpkt); + if (ret < 0) + return ret; + av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); + } + + /* process buffered data */ + while (!*got_frame) { + /* prepare the input data */ + if (s->buffer_pkt.size <= 0) { + /* no more data */ + if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket)) + return avpkt->size ? avpkt->size : qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt); + /* in progress of reinit, no read from fifo and keep the buffer_pkt */ + if (!s->qsv.reinit_flag) { + av_packet_unref(&s->buffer_pkt); + av_fifo_generic_read(s->packet_fifo, &s->buffer_pkt, sizeof(s->buffer_pkt), NULL); + } + } + + ret = qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->buffer_pkt); + if (ret < 0){ + /* Drop buffer_pkt when failed to decode the packet. Otherwise, + the decoder will keep decoding the failure packet. */ + av_packet_unref(&s->buffer_pkt); + return ret; + } + if (s->qsv.reinit_flag) + continue; + + s->buffer_pkt.size -= ret; + s->buffer_pkt.data += ret; + } + + return avpkt->size; } + +static void qsv_decode_flush(AVCodecContext *avctx) +{ + QSVDecContext *s = avctx->priv_data; + + qsv_clear_buffers(s); + + s->qsv.orig_pix_fmt = AV_PIX_FMT_NONE; + s->qsv.initialized = 0; +} + +#define OFFSET(x) offsetof(QSVDecContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM + +#define DEFINE_QSV_DECODER_WITH_OPTION(x, X, bsf_name, opt) \ +static const AVClass x##_qsv_class = { \ + .class_name = #x "_qsv", \ + .item_name = av_default_item_name, \ + .option = opt, \ + .version = LIBAVUTIL_VERSION_INT, \ +}; \ +AVCodec ff_##x##_qsv_decoder = { \ + .name = #x "_qsv", \ + .long_name = NULL_IF_CONFIG_SMALL(#X " video (Intel Quick Sync Video acceleration)"), \ + .priv_data_size = sizeof(QSVDecContext), \ + .type = AVMEDIA_TYPE_VIDEO, \ + .id = AV_CODEC_ID_##X, \ + .init = qsv_decode_init, \ + .decode = qsv_decode_frame, \ + .flush = qsv_decode_flush, \ + .close = qsv_decode_close, \ + .bsfs = bsf_name, \ + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, \ + .priv_class = &x##_qsv_class, \ + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, \ + AV_PIX_FMT_P010, \ + AV_PIX_FMT_QSV, \ + AV_PIX_FMT_NONE }, \ + .hw_configs = qsv_hw_configs, \ + .wrapper_name = "qsv", \ +}; \ + +#define DEFINE_QSV_DECODER(x, X, bsf_name) DEFINE_QSV_DECODER_WITH_OPTION(x, X, bsf_name, options) + +#if CONFIG_HEVC_QSV_DECODER +static const AVOption hevc_options[] = { + { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD }, + + { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_HW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VD, "load_plugin" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VD, "load_plugin" }, + { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VD, "load_plugin" }, + { "hevc_hw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VD, "load_plugin" }, + + { "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, VD }, + + { "gpu_copy", "A GPU-accelerated copy between video and system memory", OFFSET(qsv.gpu_copy), AV_OPT_TYPE_INT, { .i64 = MFX_GPUCOPY_DEFAULT }, MFX_GPUCOPY_DEFAULT, MFX_GPUCOPY_OFF, VD, "gpu_copy"}, + { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_DEFAULT }, 0, 0, VD, "gpu_copy"}, + { "on", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_ON }, 0, 0, VD, "gpu_copy"}, + { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_OFF }, 0, 0, VD, "gpu_copy"}, + { NULL }, +}; +DEFINE_QSV_DECODER_WITH_OPTION(hevc, HEVC, "hevc_mp4toannexb", hevc_options) +#endif + +static const AVOption options[] = { + { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD }, + + { "gpu_copy", "A GPU-accelerated copy between video and system memory", OFFSET(qsv.gpu_copy), AV_OPT_TYPE_INT, { .i64 = MFX_GPUCOPY_DEFAULT }, MFX_GPUCOPY_DEFAULT, MFX_GPUCOPY_OFF, VD, "gpu_copy"}, + { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_DEFAULT }, 0, 0, VD, "gpu_copy"}, + { "on", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_ON }, 0, 0, VD, "gpu_copy"}, + { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_OFF }, 0, 0, VD, "gpu_copy"}, + { NULL }, +}; + +#if CONFIG_H264_QSV_DECODER +DEFINE_QSV_DECODER(h264, H264, "h264_mp4toannexb") +#endif + +#if CONFIG_MPEG2_QSV_DECODER +DEFINE_QSV_DECODER(mpeg2, MPEG2VIDEO, NULL) +#endif + +#if CONFIG_VC1_QSV_DECODER +DEFINE_QSV_DECODER(vc1, VC1, NULL) +#endif + +#if CONFIG_MJPEG_QSV_DECODER +DEFINE_QSV_DECODER(mjpeg, MJPEG, NULL) +#endif + +#if CONFIG_VP8_QSV_DECODER +DEFINE_QSV_DECODER(vp8, VP8, NULL) +#endif + +#if CONFIG_VP9_QSV_DECODER +DEFINE_QSV_DECODER(vp9, VP9, NULL) +#endif + +#if CONFIG_AV1_QSV_DECODER +DEFINE_QSV_DECODER(av1, AV1, NULL) +#endif diff -Nru ffmpeg-4.2.2/libavcodec/qsvdec.h ffmpeg-4.4/libavcodec/qsvdec.h --- ffmpeg-4.2.2/libavcodec/qsvdec.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsvdec.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -/* - * Intel MediaSDK QSV utility functions - * - * copyright (c) 2013 Luca Barbato - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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_QSVDEC_H -#define AVCODEC_QSVDEC_H - -#include -#include - -#include - -#include "libavutil/fifo.h" -#include "libavutil/frame.h" -#include "libavutil/pixfmt.h" - -#include "avcodec.h" -#include "hwaccel.h" -#include "qsv_internal.h" - -typedef struct QSVContext { - // the session used for decoding - mfxSession session; - - // the session we allocated internally, in case the caller did not provide - // one - mfxSession internal_session; - - QSVFramesContext frames_ctx; - - /** - * a linked list of frames currently being used by QSV - */ - QSVFrame *work_frames; - - AVFifoBuffer *async_fifo; - int zero_consume_run; - int buffered_count; - int reinit_flag; - - // the internal parser and codec context for parsing the data - AVCodecParserContext *parser; - AVCodecContext *avctx_internal; - enum AVPixelFormat orig_pix_fmt; - uint32_t fourcc; - mfxFrameInfo frame_info; - - // options set by the caller - int async_depth; - int iopattern; - - char *load_plugins; - - mfxExtBuffer **ext_buffers; - int nb_ext_buffers; -} QSVContext; - -extern const AVCodecHWConfigInternal *ff_qsv_hw_configs[]; - -int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, - AVFrame *frame, int *got_frame, AVPacket *pkt); - -void ff_qsv_decode_flush(AVCodecContext *avctx, QSVContext *q); - -int ff_qsv_decode_close(QSVContext *q); - -#endif /* AVCODEC_QSVDEC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/qsvdec_h2645.c ffmpeg-4.4/libavcodec/qsvdec_h2645.c --- ffmpeg-4.2.2/libavcodec/qsvdec_h2645.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsvdec_h2645.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,260 +0,0 @@ -/* - * Intel MediaSDK QSV based H.264 / HEVC decoder - * - * copyright (c) 2013 Luca Barbato - * copyright (c) 2015 Anton Khirnov - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include -#include - -#include - -#include "libavutil/common.h" -#include "libavutil/fifo.h" -#include "libavutil/opt.h" - -#include "avcodec.h" -#include "internal.h" -#include "qsv_internal.h" -#include "qsvdec.h" -#include "qsv.h" - -enum LoadPlugin { - LOAD_PLUGIN_NONE, - LOAD_PLUGIN_HEVC_SW, - LOAD_PLUGIN_HEVC_HW, -}; - -typedef struct QSVH2645Context { - AVClass *class; - QSVContext qsv; - - int load_plugin; - - AVFifoBuffer *packet_fifo; - - AVPacket buffer_pkt; -} QSVH2645Context; - -static void qsv_clear_buffers(QSVH2645Context *s) -{ - AVPacket pkt; - while (av_fifo_size(s->packet_fifo) >= sizeof(pkt)) { - av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL); - av_packet_unref(&pkt); - } - - av_packet_unref(&s->buffer_pkt); -} - -static av_cold int qsv_decode_close(AVCodecContext *avctx) -{ - QSVH2645Context *s = avctx->priv_data; - - ff_qsv_decode_close(&s->qsv); - - qsv_clear_buffers(s); - - av_fifo_free(s->packet_fifo); - - return 0; -} - -static av_cold int qsv_decode_init(AVCodecContext *avctx) -{ - QSVH2645Context *s = avctx->priv_data; - int ret; - - if (avctx->codec_id == AV_CODEC_ID_HEVC && s->load_plugin != LOAD_PLUGIN_NONE) { - static const char * const uid_hevcdec_sw = "15dd936825ad475ea34e35f3f54217a6"; - static const char * const uid_hevcdec_hw = "33a61c0b4c27454ca8d85dde757c6f8e"; - - if (s->qsv.load_plugins[0]) { - av_log(avctx, AV_LOG_WARNING, - "load_plugins is not empty, but load_plugin is not set to 'none'." - "The load_plugin value will be ignored.\n"); - } else { - av_freep(&s->qsv.load_plugins); - - if (s->load_plugin == LOAD_PLUGIN_HEVC_SW) - s->qsv.load_plugins = av_strdup(uid_hevcdec_sw); - else - s->qsv.load_plugins = av_strdup(uid_hevcdec_hw); - if (!s->qsv.load_plugins) - return AVERROR(ENOMEM); - } - } - - s->packet_fifo = av_fifo_alloc(sizeof(AVPacket)); - if (!s->packet_fifo) { - ret = AVERROR(ENOMEM); - goto fail; - } - - return 0; -fail: - qsv_decode_close(avctx); - return ret; -} - -static int qsv_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame, AVPacket *avpkt) -{ - QSVH2645Context *s = avctx->priv_data; - AVFrame *frame = data; - int ret; - - /* buffer the input packet */ - if (avpkt->size) { - AVPacket input_ref = { 0 }; - - if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) { - ret = av_fifo_realloc2(s->packet_fifo, - av_fifo_size(s->packet_fifo) + sizeof(input_ref)); - if (ret < 0) - return ret; - } - - ret = av_packet_ref(&input_ref, avpkt); - if (ret < 0) - return ret; - av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); - } - - /* process buffered data */ - while (!*got_frame) { - /* prepare the input data */ - if (s->buffer_pkt.size <= 0) { - /* no more data */ - if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket)) - return avpkt->size ? avpkt->size : ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt); - /* in progress of reinit, no read from fifo and keep the buffer_pkt */ - if (!s->qsv.reinit_flag) { - av_packet_unref(&s->buffer_pkt); - av_fifo_generic_read(s->packet_fifo, &s->buffer_pkt, sizeof(s->buffer_pkt), NULL); - } - } - - ret = ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->buffer_pkt); - if (ret < 0){ - /* Drop buffer_pkt when failed to decode the packet. Otherwise, - the decoder will keep decoding the failure packet. */ - av_packet_unref(&s->buffer_pkt); - return ret; - } - if (s->qsv.reinit_flag) - continue; - - s->buffer_pkt.size -= ret; - s->buffer_pkt.data += ret; - } - - return avpkt->size; -} - -static void qsv_decode_flush(AVCodecContext *avctx) -{ - QSVH2645Context *s = avctx->priv_data; - - qsv_clear_buffers(s); - ff_qsv_decode_flush(avctx, &s->qsv); -} - -#define OFFSET(x) offsetof(QSVH2645Context, x) -#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM - -#if CONFIG_HEVC_QSV_DECODER -static const AVOption hevc_options[] = { - { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD }, - - { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_HW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VD, "load_plugin" }, - { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VD, "load_plugin" }, - { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VD, "load_plugin" }, - { "hevc_hw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VD, "load_plugin" }, - - { "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, VD }, - { NULL }, -}; - -static const AVClass hevc_class = { - .class_name = "hevc_qsv", - .item_name = av_default_item_name, - .option = hevc_options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVCodec ff_hevc_qsv_decoder = { - .name = "hevc_qsv", - .long_name = NULL_IF_CONFIG_SMALL("HEVC (Intel Quick Sync Video acceleration)"), - .priv_data_size = sizeof(QSVH2645Context), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HEVC, - .init = qsv_decode_init, - .decode = qsv_decode_frame, - .flush = qsv_decode_flush, - .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, - .priv_class = &hevc_class, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, - AV_PIX_FMT_P010, - AV_PIX_FMT_QSV, - AV_PIX_FMT_NONE }, - .hw_configs = ff_qsv_hw_configs, - .bsfs = "hevc_mp4toannexb", - .wrapper_name = "qsv", -}; -#endif - -#if CONFIG_H264_QSV_DECODER -static const AVOption options[] = { - { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD }, - { NULL }, -}; - -static const AVClass class = { - .class_name = "h264_qsv", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVCodec ff_h264_qsv_decoder = { - .name = "h264_qsv", - .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration)"), - .priv_data_size = sizeof(QSVH2645Context), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .init = qsv_decode_init, - .decode = qsv_decode_frame, - .flush = qsv_decode_flush, - .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, - .priv_class = &class, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, - AV_PIX_FMT_P010, - AV_PIX_FMT_QSV, - AV_PIX_FMT_NONE }, - .hw_configs = ff_qsv_hw_configs, - .bsfs = "h264_mp4toannexb", - .wrapper_name = "qsv", -}; -#endif diff -Nru ffmpeg-4.2.2/libavcodec/qsvdec_other.c ffmpeg-4.4/libavcodec/qsvdec_other.c --- ffmpeg-4.2.2/libavcodec/qsvdec_other.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsvdec_other.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,257 +0,0 @@ -/* - * Intel MediaSDK QSV based MPEG-2, VC-1 and VP8 decoders - * - * copyright (c) 2015 Anton Khirnov - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include -#include - -#include - -#include "libavutil/common.h" -#include "libavutil/fifo.h" -#include "libavutil/opt.h" - -#include "avcodec.h" -#include "internal.h" -#include "qsv_internal.h" -#include "qsvdec.h" -#include "qsv.h" - -typedef struct QSVOtherContext { - AVClass *class; - QSVContext qsv; - - AVFifoBuffer *packet_fifo; - - AVPacket input_ref; -} QSVOtherContext; - -static void qsv_clear_buffers(QSVOtherContext *s) -{ - AVPacket pkt; - while (av_fifo_size(s->packet_fifo) >= sizeof(pkt)) { - av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL); - av_packet_unref(&pkt); - } - - av_packet_unref(&s->input_ref); -} - -static av_cold int qsv_decode_close(AVCodecContext *avctx) -{ - QSVOtherContext *s = avctx->priv_data; - -#if CONFIG_VP8_QSV_DECODER - if (avctx->codec_id == AV_CODEC_ID_VP8) - av_freep(&s->qsv.load_plugins); -#endif - - ff_qsv_decode_close(&s->qsv); - - qsv_clear_buffers(s); - - av_fifo_free(s->packet_fifo); - - return 0; -} - -static av_cold int qsv_decode_init(AVCodecContext *avctx) -{ - QSVOtherContext *s = avctx->priv_data; - int ret; - -#if CONFIG_VP8_QSV_DECODER - if (avctx->codec_id == AV_CODEC_ID_VP8) { - static const char *uid_vp8dec_hw = "f622394d8d87452f878c51f2fc9b4131"; - - av_freep(&s->qsv.load_plugins); - s->qsv.load_plugins = av_strdup(uid_vp8dec_hw); - if (!s->qsv.load_plugins) - return AVERROR(ENOMEM); - } -#endif - - s->packet_fifo = av_fifo_alloc(sizeof(AVPacket)); - if (!s->packet_fifo) { - ret = AVERROR(ENOMEM); - goto fail; - } - - return 0; -fail: - qsv_decode_close(avctx); - return ret; -} - -static int qsv_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame, AVPacket *avpkt) -{ - QSVOtherContext *s = avctx->priv_data; - AVFrame *frame = data; - int ret; - - /* buffer the input packet */ - if (avpkt->size) { - AVPacket input_ref = { 0 }; - - if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) { - ret = av_fifo_realloc2(s->packet_fifo, - av_fifo_size(s->packet_fifo) + sizeof(input_ref)); - if (ret < 0) - return ret; - } - - ret = av_packet_ref(&input_ref, avpkt); - if (ret < 0) - return ret; - av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); - } - - /* process buffered data */ - while (!*got_frame) { - if (s->input_ref.size <= 0) { - /* no more data */ - if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket)) - return avpkt->size ? avpkt->size : ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt); - /* in progress of reinit, no read from fifo and keep the buffer_pkt */ - if (!s->qsv.reinit_flag) { - av_packet_unref(&s->input_ref); - av_fifo_generic_read(s->packet_fifo, &s->input_ref, sizeof(s->input_ref), NULL); - } - } - - ret = ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->input_ref); - if (ret < 0) { - /* Drop input packet when failed to decode the packet. Otherwise, - the decoder will keep decoding the failure packet. */ - av_packet_unref(&s->input_ref); - - return ret; - } - if (s->qsv.reinit_flag) - continue; - - s->input_ref.size -= ret; - s->input_ref.data += ret; - } - - return avpkt->size; -} - -static void qsv_decode_flush(AVCodecContext *avctx) -{ - QSVOtherContext *s = avctx->priv_data; - - qsv_clear_buffers(s); - ff_qsv_decode_flush(avctx, &s->qsv); -} - -#define OFFSET(x) offsetof(QSVOtherContext, x) -#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM -static const AVOption options[] = { - { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD }, - { NULL }, -}; - -#if CONFIG_MPEG2_QSV_DECODER -static const AVClass mpeg2_qsv_class = { - .class_name = "mpeg2_qsv", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVCodec ff_mpeg2_qsv_decoder = { - .name = "mpeg2_qsv", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video (Intel Quick Sync Video acceleration)"), - .priv_data_size = sizeof(QSVOtherContext), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, - .init = qsv_decode_init, - .decode = qsv_decode_frame, - .flush = qsv_decode_flush, - .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, - .priv_class = &mpeg2_qsv_class, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, - AV_PIX_FMT_QSV, - AV_PIX_FMT_NONE }, - .hw_configs = ff_qsv_hw_configs, - .wrapper_name = "qsv", -}; -#endif - -#if CONFIG_VC1_QSV_DECODER -static const AVClass vc1_qsv_class = { - .class_name = "vc1_qsv", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVCodec ff_vc1_qsv_decoder = { - .name = "vc1_qsv", - .long_name = NULL_IF_CONFIG_SMALL("VC-1 video (Intel Quick Sync Video acceleration)"), - .priv_data_size = sizeof(QSVOtherContext), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VC1, - .init = qsv_decode_init, - .decode = qsv_decode_frame, - .flush = qsv_decode_flush, - .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, - .priv_class = &vc1_qsv_class, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, - AV_PIX_FMT_QSV, - AV_PIX_FMT_NONE }, - .hw_configs = ff_qsv_hw_configs, - .wrapper_name = "qsv", -}; -#endif - -#if CONFIG_VP8_QSV_DECODER -static const AVClass vp8_qsv_class = { - .class_name = "vp8_qsv", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVCodec ff_vp8_qsv_decoder = { - .name = "vp8_qsv", - .long_name = NULL_IF_CONFIG_SMALL("VP8 video (Intel Quick Sync Video acceleration)"), - .priv_data_size = sizeof(QSVOtherContext), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP8, - .init = qsv_decode_init, - .decode = qsv_decode_frame, - .flush = qsv_decode_flush, - .close = qsv_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, - .priv_class = &vp8_qsv_class, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, - AV_PIX_FMT_QSV, - AV_PIX_FMT_NONE }, - .hw_configs = ff_qsv_hw_configs, - .wrapper_name = "qsv", -}; -#endif diff -Nru ffmpeg-4.2.2/libavcodec/qsvenc.c ffmpeg-4.4/libavcodec/qsvenc.c --- ffmpeg-4.2.2/libavcodec/qsvenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsvenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -36,6 +36,7 @@ #include "avcodec.h" #include "internal.h" +#include "packet_internal.h" #include "qsv.h" #include "qsv_internal.h" #include "qsvenc.h" @@ -66,6 +67,7 @@ { MFX_PROFILE_HEVC_MAIN, "main" }, { MFX_PROFILE_HEVC_MAIN10, "main10" }, { MFX_PROFILE_HEVC_MAINSP, "mainsp" }, + { MFX_PROFILE_HEVC_REXT, "rext" }, #endif }; @@ -139,6 +141,9 @@ #if QSV_HAVE_CO3 mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2]; #endif +#if QSV_HAVE_EXT_HEVC_TILES + mfxExtHEVCTiles *exthevctiles = (mfxExtHEVCTiles *)coding_opts[3 + QSV_HAVE_CO_VPS]; +#endif av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n", print_profile(info->CodecProfile), info->CodecLevel); @@ -204,14 +209,20 @@ av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n", print_threestate(co->RateDistortionOpt)); +#if QSV_HAVE_EXT_HEVC_TILES + if (avctx->codec_id == AV_CODEC_ID_HEVC) + av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16"; NumTileRows: %"PRIu16"\n", + exthevctiles->NumTileColumns, exthevctiles->NumTileRows); +#endif + #if QSV_HAVE_CO2 av_log(avctx, AV_LOG_VERBOSE, "RecoveryPointSEI: %s IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n", print_threestate(co->RecoveryPointSEI), co2->IntRefType, co2->IntRefCycleSize, co2->IntRefQPDelta); - av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %"PRIu16"; ", co2->MaxFrameSize); + av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %d; ", co2->MaxFrameSize); #if QSV_HAVE_MAX_SLICE_SIZE - av_log(avctx, AV_LOG_VERBOSE, "MaxSliceSize: %"PRIu16"; ", co2->MaxSliceSize); + av_log(avctx, AV_LOG_VERBOSE, "MaxSliceSize: %d; ", co2->MaxSliceSize); #endif av_log(avctx, AV_LOG_VERBOSE, "\n"); @@ -461,6 +472,12 @@ q->param.mfx.Quality = av_clip(avctx->global_quality, 1, 100); q->param.mfx.RestartInterval = 0; + q->width_align = 16; + q->height_align = 16; + + q->param.mfx.FrameInfo.Width = FFALIGN(avctx->width, q->width_align); + q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, q->height_align); + return 0; } @@ -529,7 +546,8 @@ q->param.mfx.FrameInfo.CropH = avctx->height; q->param.mfx.FrameInfo.AspectRatioW = avctx->sample_aspect_ratio.num; q->param.mfx.FrameInfo.AspectRatioH = avctx->sample_aspect_ratio.den; - q->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; + q->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420 + + !desc->log2_chroma_w + !desc->log2_chroma_h; q->param.mfx.FrameInfo.BitDepthLuma = desc->comp[0].depth; q->param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth; q->param.mfx.FrameInfo.Shift = desc->comp[0].depth > 8; @@ -637,7 +655,8 @@ // The HEVC encoder plugin currently fails with some old libmfx version if coding options // are provided. Can't find the extract libmfx version which fixed it, just enable it from // V1.28 in order to keep compatibility security. - if ((avctx->codec_id != AV_CODEC_ID_HEVC) || QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 28)) { + if (((avctx->codec_id != AV_CODEC_ID_HEVC) || QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 28)) + && (avctx->codec_id != AV_CODEC_ID_VP9)) { q->extco.Header.BufferId = MFX_EXTBUFF_CODING_OPTION; q->extco.Header.BufferSz = sizeof(q->extco); @@ -671,11 +690,8 @@ q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco; - if (avctx->codec_id == AV_CODEC_ID_H264) { #if QSV_HAVE_CO2 - q->extco2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; - q->extco2.Header.BufferSz = sizeof(q->extco2); - + if (avctx->codec_id == AV_CODEC_ID_H264) { if (q->int_ref_type >= 0) q->extco2.IntRefType = q->int_ref_type; if (q->int_ref_cycle_size >= 0) @@ -687,8 +703,6 @@ q->extco2.BitrateLimit = q->bitrate_limit ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; if (q->mbbrc >= 0) q->extco2.MBBRC = q->mbbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; - if (q->extbrc >= 0) - q->extco2.ExtBRC = q->extbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; if (q->max_frame_size >= 0) q->extco2.MaxFrameSize = q->max_frame_size; @@ -721,6 +735,11 @@ if (q->adaptive_b >= 0) q->extco2.AdaptiveB = q->adaptive_b ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; #endif + } + + if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC) { + if (q->extbrc >= 0) + q->extco2.ExtBRC = q->extbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; #if QSV_VERSION_ATLEAST(1, 9) if (avctx->qmin >= 0 && avctx->qmax >= 0 && avctx->qmin > avctx->qmax) { @@ -736,9 +755,14 @@ q->extco2.MaxQPP = q->extco2.MaxQPB = q->extco2.MaxQPI; } #endif + q->extco2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; + q->extco2.Header.BufferSz = sizeof(q->extco2); + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco2; + } #endif + if (avctx->codec_id == AV_CODEC_ID_H264) { #if QSV_HAVE_MF if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 25)) { q->extmfp.Header.BufferId = MFX_EXTBUFF_MULTI_FRAME_PARAM; @@ -761,6 +785,25 @@ #endif } +#if QSV_HAVE_EXT_VP9_PARAM + if (avctx->codec_id == AV_CODEC_ID_VP9) { + q->extvp9param.Header.BufferId = MFX_EXTBUFF_VP9_PARAM; + q->extvp9param.Header.BufferSz = sizeof(q->extvp9param); + q->extvp9param.WriteIVFHeaders = MFX_CODINGOPTION_OFF; + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extvp9param; + } +#endif + +#if QSV_HAVE_EXT_HEVC_TILES + if (avctx->codec_id == AV_CODEC_ID_HEVC) { + q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES; + q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles); + q->exthevctiles.NumTileColumns = q->tile_cols; + q->exthevctiles.NumTileRows = q->tile_rows; + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->exthevctiles; + } +#endif + if (!check_enc_param(avctx,q)) { av_log(avctx, AV_LOG_ERROR, "some encoding parameters are not supported by the QSV " @@ -789,6 +832,55 @@ return 0; } +static int qsv_retrieve_enc_vp9_params(AVCodecContext *avctx, QSVEncContext *q) +{ + int ret = 0; +#if QSV_HAVE_EXT_VP9_PARAM + mfxExtVP9Param vp9_extend_buf = { + .Header.BufferId = MFX_EXTBUFF_VP9_PARAM, + .Header.BufferSz = sizeof(vp9_extend_buf), + }; +#endif + +#if QSV_HAVE_CO2 + mfxExtCodingOption2 co2 = { + .Header.BufferId = MFX_EXTBUFF_CODING_OPTION2, + .Header.BufferSz = sizeof(co2), + }; +#endif + +#if QSV_HAVE_CO3 + mfxExtCodingOption3 co3 = { + .Header.BufferId = MFX_EXTBUFF_CODING_OPTION3, + .Header.BufferSz = sizeof(co3), + }; +#endif + + mfxExtBuffer *ext_buffers[] = { +#if QSV_HAVE_EXT_VP9_PARAM + (mfxExtBuffer*)&vp9_extend_buf, +#endif +#if QSV_HAVE_CO2 + (mfxExtBuffer*)&co2, +#endif +#if QSV_HAVE_CO3 + (mfxExtBuffer*)&co3, +#endif + }; + + q->param.ExtParam = ext_buffers; + q->param.NumExtParam = FF_ARRAY_ELEMS(ext_buffers); + + ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, + "Error calling GetVideoParam"); + + q->packet_size = q->param.mfx.BufferSizeInKB * q->param.mfx.BRCParamMultiplier * 1000; + + return 0; +} + static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) { AVCPBProperties *cpb_props; @@ -830,7 +922,14 @@ }; #endif - mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS]; +#if QSV_HAVE_EXT_HEVC_TILES + mfxExtHEVCTiles hevc_tile_buf = { + .Header.BufferId = MFX_EXTBUFF_HEVC_TILES, + .Header.BufferSz = sizeof(hevc_tile_buf), + }; +#endif + + mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS + QSV_HAVE_EXT_HEVC_TILES]; int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO; int ret, ext_buf_num = 0, extradata_offset = 0; @@ -848,6 +947,10 @@ if (q->hevc_vps) ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata_vps; #endif +#if QSV_HAVE_EXT_HEVC_TILES + if (avctx->codec_id == AV_CODEC_ID_HEVC) + ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&hevc_tile_buf; +#endif q->param.ExtParam = ext_buffers; q->param.NumExtParam = ext_buf_num; @@ -954,29 +1057,31 @@ if (!q->frames_ctx.hw_frames_ctx) return AVERROR(ENOMEM); - ret = ff_qsv_init_session_frames(avctx, &q->internal_session, + ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session, &q->frames_ctx, q->load_plugins, - q->param.IOPattern == MFX_IOPATTERN_IN_OPAQUE_MEMORY); + q->param.IOPattern == MFX_IOPATTERN_IN_OPAQUE_MEMORY, + MFX_GPUCOPY_OFF); if (ret < 0) { av_buffer_unref(&q->frames_ctx.hw_frames_ctx); return ret; } - q->session = q->internal_session; + q->session = q->internal_qs.session; } else if (avctx->hw_device_ctx) { - ret = ff_qsv_init_session_device(avctx, &q->internal_session, - avctx->hw_device_ctx, q->load_plugins); + ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session, + avctx->hw_device_ctx, q->load_plugins, + MFX_GPUCOPY_OFF); if (ret < 0) return ret; - q->session = q->internal_session; + q->session = q->internal_qs.session; } else { - ret = ff_qsv_init_internal_session(avctx, &q->internal_session, - q->load_plugins); + ret = ff_qsv_init_internal_session(avctx, &q->internal_qs, + q->load_plugins, MFX_GPUCOPY_OFF); if (ret < 0) return ret; - q->session = q->internal_session; + q->session = q->internal_qs.session; } return 0; @@ -1027,6 +1132,7 @@ if (!iopattern) iopattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY; q->param.IOPattern = iopattern; + ff_qsv_print_iopattern(avctx, iopattern, "Encoder"); ret = qsvenc_init_session(avctx, q); if (ret < 0) @@ -1050,25 +1156,6 @@ if (ret < 0) return ret; - ret = MFXVideoENCODE_Query(q->session, &q->param, &q->param); - if (ret == MFX_WRN_PARTIAL_ACCELERATION) { - av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n"); - } else if (ret < 0) { - return ff_qsv_print_error(avctx, ret, - "Error querying encoder params"); - } - - ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req); - if (ret < 0) - return ff_qsv_print_error(avctx, ret, - "Error querying (IOSurf) the encoding parameters"); - - if (opaque_alloc) { - ret = qsv_init_opaque_alloc(avctx, q); - if (ret < 0) - return ret; - } - if (avctx->hwaccel_context) { AVQSVContext *qsv = avctx->hwaccel_context; int i, j; @@ -1098,6 +1185,25 @@ q->param.NumExtParam = q->nb_extparam_internal; } + ret = MFXVideoENCODE_Query(q->session, &q->param, &q->param); + if (ret == MFX_WRN_PARTIAL_ACCELERATION) { + av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n"); + } else if (ret < 0) { + return ff_qsv_print_error(avctx, ret, + "Error querying encoder params"); + } + + ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, + "Error querying (IOSurf) the encoding parameters"); + + if (opaque_alloc) { + ret = qsv_init_opaque_alloc(avctx, q); + if (ret < 0) + return ret; + } + ret = MFXVideoENCODE_Init(q->session, &q->param); if (ret < 0) return ff_qsv_print_error(avctx, ret, @@ -1110,6 +1216,9 @@ case AV_CODEC_ID_MJPEG: ret = qsv_retrieve_enc_jpeg_params(avctx, q); break; + case AV_CODEC_ID_VP9: + ret = qsv_retrieve_enc_vp9_params(avctx, q); + break; default: ret = qsv_retrieve_enc_params(avctx, q); break; @@ -1507,10 +1616,9 @@ if (q->session) MFXVideoENCODE_Close(q->session); - if (q->internal_session) - MFXClose(q->internal_session); + q->session = NULL; - q->internal_session = NULL; + ff_qsv_close_internal_session(&q->internal_qs); av_buffer_unref(&q->frames_ctx.hw_frames_ctx); av_buffer_unref(&q->frames_ctx.mids_buf); @@ -1547,3 +1655,10 @@ return 0; } + +const AVCodecHWConfigInternal *const ff_qsv_enc_hw_configs[] = { + HW_CONFIG_ENCODER_FRAMES(QSV, QSV), + HW_CONFIG_ENCODER_DEVICE(NV12, QSV), + HW_CONFIG_ENCODER_DEVICE(P010, QSV), + NULL, +}; diff -Nru ffmpeg-4.2.2/libavcodec/qsvenc.h ffmpeg-4.4/libavcodec/qsvenc.h --- ffmpeg-4.2.2/libavcodec/qsvenc.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsvenc.h 2021-04-08 21:28:39.000000000 +0000 @@ -32,12 +32,16 @@ #include "libavutil/fifo.h" #include "avcodec.h" +#include "hwconfig.h" #include "qsv_internal.h" #define QSV_HAVE_CO2 QSV_VERSION_ATLEAST(1, 6) #define QSV_HAVE_CO3 QSV_VERSION_ATLEAST(1, 11) #define QSV_HAVE_CO_VPS QSV_VERSION_ATLEAST(1, 17) +#define QSV_HAVE_EXT_HEVC_TILES QSV_VERSION_ATLEAST(1, 13) +#define QSV_HAVE_EXT_VP9_PARAM QSV_VERSION_ATLEAST(1, 26) + #define QSV_HAVE_TRELLIS QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_MAX_SLICE_SIZE QSV_VERSION_ATLEAST(1, 9) #define QSV_HAVE_BREF_TYPE QSV_VERSION_ATLEAST(1, 8) @@ -94,6 +98,8 @@ { "forced_idr", "Forcing I frames as IDR frames", OFFSET(qsv.forced_idr), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE }, \ { "low_power", "enable low power mode(experimental: many limitations by mfx version, BRC modes, etc.)", OFFSET(qsv.low_power), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, VE},\ +extern const AVCodecHWConfigInternal *const ff_qsv_enc_hw_configs[]; + typedef int SetEncodeCtrlCB (AVCodecContext *avctx, const AVFrame *frame, mfxEncodeCtrl* enc_ctrl); typedef struct QSVEncContext { @@ -102,7 +108,7 @@ QSVFrame *work_frames; mfxSession session; - mfxSession internal_session; + QSVSession internal_qs; int packet_size; int width_align; @@ -122,6 +128,13 @@ mfxExtMultiFrameParam extmfp; mfxExtMultiFrameControl extmfc; #endif +#if QSV_HAVE_EXT_HEVC_TILES + mfxExtHEVCTiles exthevctiles; +#endif +#if QSV_HAVE_EXT_VP9_PARAM + mfxExtVP9Param extvp9param; +#endif + mfxExtOpaqueSurfaceAlloc opaque_alloc; mfxFrameSurface1 **opaque_surfaces; AVBufferRef *opaque_alloc_buf; @@ -155,6 +168,9 @@ int max_frame_size; int max_slice_size; + int tile_cols; + int tile_rows; + int aud; int single_sei_nal_unit; diff -Nru ffmpeg-4.2.2/libavcodec/qsvenc_h264.c ffmpeg-4.4/libavcodec/qsvenc_h264.c --- ffmpeg-4.2.2/libavcodec/qsvenc_h264.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsvenc_h264.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,6 +34,7 @@ #include "qsv.h" #include "qsv_internal.h" #include "qsvenc.h" +#include "atsc_a53.h" typedef struct QSVH264EncContext { AVClass *class; @@ -197,4 +198,5 @@ .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .wrapper_name = "qsv", + .hw_configs = ff_qsv_enc_hw_configs, }; diff -Nru ffmpeg-4.2.2/libavcodec/qsvenc_hevc.c ffmpeg-4.4/libavcodec/qsvenc_hevc.c --- ffmpeg-4.2.2/libavcodec/qsvenc_hevc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsvenc_hevc.c 2021-04-08 21:28:39.000000000 +0000 @@ -240,9 +240,13 @@ { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, { "main10", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN10 }, INT_MIN, INT_MAX, VE, "profile" }, { "mainsp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAINSP }, INT_MIN, INT_MAX, VE, "profile" }, + { "rext", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_REXT }, INT_MIN, INT_MAX, VE, "profile" }, { "gpb", "1: GPB (generalized P/B frame); 0: regular P frame", OFFSET(qsv.gpb), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE}, + { "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 }, + { NULL }, }; @@ -259,6 +263,8 @@ // same as the x264 default { "g", "248" }, { "bf", "8" }, + { "qmin", "-1" }, + { "qmax", "-1" }, { "trellis", "-1" }, { "flags", "+cgop" }, #if FF_API_PRIVATE_OPT @@ -285,4 +291,5 @@ .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .wrapper_name = "qsv", + .hw_configs = ff_qsv_enc_hw_configs, }; diff -Nru ffmpeg-4.2.2/libavcodec/qsvenc_jpeg.c ffmpeg-4.4/libavcodec/qsvenc_jpeg.c --- ffmpeg-4.2.2/libavcodec/qsvenc_jpeg.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsvenc_jpeg.c 2020-07-11 10:39:30.000000000 +0000 @@ -95,4 +95,5 @@ .priv_class = &class, .defaults = qsv_enc_defaults, .wrapper_name = "qsv", + .hw_configs = ff_qsv_enc_hw_configs, }; diff -Nru ffmpeg-4.2.2/libavcodec/qsvenc_mpeg2.c ffmpeg-4.4/libavcodec/qsvenc_mpeg2.c --- ffmpeg-4.2.2/libavcodec/qsvenc_mpeg2.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsvenc_mpeg2.c 2020-07-11 10:39:30.000000000 +0000 @@ -112,4 +112,5 @@ .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .wrapper_name = "qsv", + .hw_configs = ff_qsv_enc_hw_configs, }; diff -Nru ffmpeg-4.2.2/libavcodec/qsvenc_vp9.c ffmpeg-4.4/libavcodec/qsvenc_vp9.c --- ffmpeg-4.2.2/libavcodec/qsvenc_vp9.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsvenc_vp9.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,114 @@ +/* + * Intel MediaSDK QSV based VP9 encoder + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include + +#include + +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "internal.h" +#include "qsv.h" +#include "qsv_internal.h" +#include "qsvenc.h" + +typedef struct QSVVP9EncContext { + AVClass *class; + QSVEncContext qsv; +} QSVVP9EncContext; + +static av_cold int qsv_enc_init(AVCodecContext *avctx) +{ + QSVVP9EncContext *q = avctx->priv_data; + q->qsv.low_power = 1; + + return ff_qsv_enc_init(avctx, &q->qsv); +} + +static int qsv_enc_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + QSVVP9EncContext *q = avctx->priv_data; + + return ff_qsv_encode(avctx, &q->qsv, pkt, frame, got_packet); +} + +static av_cold int qsv_enc_close(AVCodecContext *avctx) +{ + QSVVP9EncContext *q = avctx->priv_data; + + return ff_qsv_enc_close(avctx, &q->qsv); +} + +#define OFFSET(x) offsetof(QSVVP9EncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + QSV_COMMON_OPTS + + { "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" }, + { "profile0", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_VP9_0 }, INT_MIN, INT_MAX, VE, "profile" }, + { "profile1", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_VP9_1 }, INT_MIN, INT_MAX, VE, "profile" }, + { "profile2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_VP9_2 }, INT_MIN, INT_MAX, VE, "profile" }, + { "profile3", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_VP9_3 }, INT_MIN, INT_MAX, VE, "profile" }, + + { NULL }, +}; + +static const AVClass class = { + .class_name = "vp9_qsv encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault qsv_enc_defaults[] = { + { "b", "1M" }, + { "refs", "0" }, + { "g", "250" }, + { "trellis", "-1" }, + { "flags", "+cgop" }, + { NULL }, +}; + +AVCodec ff_vp9_qsv_encoder = { + .name = "vp9_qsv", + .long_name = NULL_IF_CONFIG_SMALL("VP9 video (Intel Quick Sync Video acceleration)"), + .priv_data_size = sizeof(QSVVP9EncContext), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP9, + .init = qsv_enc_init, + .encode2 = qsv_enc_frame, + .close = qsv_enc_close, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + AV_PIX_FMT_P010, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE }, + .priv_class = &class, + .defaults = qsv_enc_defaults, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "qsv", + .hw_configs = ff_qsv_enc_hw_configs, +}; diff -Nru ffmpeg-4.2.2/libavcodec/qsv_internal.h ffmpeg-4.4/libavcodec/qsv_internal.h --- ffmpeg-4.2.2/libavcodec/qsv_internal.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qsv_internal.h 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,24 @@ #ifndef AVCODEC_QSV_INTERNAL_H #define AVCODEC_QSV_INTERNAL_H +#include "config.h" + +#if CONFIG_VAAPI +#define AVCODEC_QSV_LINUX_SESSION_HANDLE +#endif //CONFIG_VAAPI + +#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include "libavutil/hwcontext_vaapi.h" +#endif + #include #include "libavutil/frame.h" @@ -64,6 +82,14 @@ struct QSVFrame *next; } QSVFrame; +typedef struct QSVSession { + mfxSession session; +#ifdef AVCODEC_QSV_LINUX_SESSION_HANDLE + AVBufferRef *va_device_ref; + AVHWDeviceContext *va_device_ctx; +#endif +} QSVSession; + typedef struct QSVFramesContext { AVBufferRef *hw_frames_ctx; void *logctx; @@ -77,6 +103,9 @@ int nb_mids; } QSVFramesContext; +int ff_qsv_print_iopattern(void *log_ctx, int mfx_iopattern, + const char *extra_string); + /** * Convert a libmfx error code into an ffmpeg error code. */ @@ -89,21 +118,27 @@ const char *warning_string); int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id); -int ff_qsv_profile_to_mfx(enum AVCodecID codec_id, int profile); int ff_qsv_level_to_mfx(enum AVCodecID codec_id, int level); +enum AVPixelFormat ff_qsv_map_fourcc(uint32_t fourcc); + int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc); enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type); -int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session, - const char *load_plugins); +enum AVFieldOrder ff_qsv_map_picstruct(int mfx_pic_struct); + +int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, + const char *load_plugins, int gpu_copy); + +int ff_qsv_close_internal_session(QSVSession *qs); int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, - AVBufferRef *device_ref, const char *load_plugins); + AVBufferRef *device_ref, const char *load_plugins, + int gpu_copy); int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *session, QSVFramesContext *qsv_frames_ctx, - const char *load_plugins, int opaque); + const char *load_plugins, int opaque, int gpu_copy); int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame); diff -Nru ffmpeg-4.2.2/libavcodec/qtrle.c ffmpeg-4.4/libavcodec/qtrle.c --- ffmpeg-4.2.2/libavcodec/qtrle.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qtrle.c 2021-04-08 21:28:39.000000000 +0000 @@ -36,6 +36,7 @@ #include #include "avcodec.h" +#include "decode.h" #include "bytestream.h" #include "internal.h" @@ -452,13 +453,16 @@ int header, start_line; int height, row_ptr; int has_palette = 0; + int duplicate = 0; int ret, size; bytestream2_init(&s->g, avpkt->data, avpkt->size); /* check if this frame is even supposed to change */ - if (avpkt->size < 8) - return avpkt->size; + if (avpkt->size < 8) { + duplicate = 1; + goto done; + } /* start after the chunk size */ size = bytestream2_get_be32(&s->g) & 0x3FFFFFFF; @@ -471,19 +475,23 @@ /* if a header is present, fetch additional decoding parameters */ if (header & 0x0008) { - if (avpkt->size < 14) - return avpkt->size; + if (avpkt->size < 14) { + duplicate = 1; + goto done; + } start_line = bytestream2_get_be16(&s->g); bytestream2_skip(&s->g, 2); height = bytestream2_get_be16(&s->g); bytestream2_skip(&s->g, 2); - if (height > s->avctx->height - start_line) - return avpkt->size; + if (height > s->avctx->height - start_line) { + duplicate = 1; + goto done; + } } else { start_line = 0; height = s->avctx->height; } - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; row_ptr = s->frame->linesize[0] * start_line; @@ -532,7 +540,7 @@ } if(has_palette) { - int size; + buffer_size_t size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size); if (pal && size == AVPALETTE_SIZE) { @@ -546,6 +554,17 @@ memcpy(s->frame->data[1], s->pal, AVPALETTE_SIZE); } +done: + if (!s->frame->data[0]) + return AVERROR_INVALIDDATA; + if (duplicate) { + // ff_reget_buffer() isn't needed when frames don't change, so just update + // frame props. + ret = ff_decode_frame_props(avctx, s->frame); + if (ret < 0) + return ret; + } + if ((ret = av_frame_ref(data, s->frame)) < 0) return ret; *got_frame = 1; @@ -554,6 +573,13 @@ return avpkt->size; } +static void qtrle_decode_flush(AVCodecContext *avctx) +{ + QtrleContext *s = avctx->priv_data; + + av_frame_unref(s->frame); +} + static av_cold int qtrle_decode_end(AVCodecContext *avctx) { QtrleContext *s = avctx->priv_data; @@ -572,5 +598,6 @@ .init = qtrle_decode_init, .close = qtrle_decode_end, .decode = qtrle_decode_frame, + .flush = qtrle_decode_flush, .capabilities = AV_CODEC_CAP_DR1, }; diff -Nru ffmpeg-4.2.2/libavcodec/qtrleenc.c ffmpeg-4.4/libavcodec/qtrleenc.c --- ffmpeg-4.2.2/libavcodec/qtrleenc.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/qtrleenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -155,10 +155,14 @@ int sec_lowest_bulk_cost; int sec_lowest_bulk_cost_index; - uint8_t *this_line = p-> data[0] + line*p-> linesize[0] + - (width - 1)*s->pixel_size; - uint8_t *prev_line = s->previous_frame->data[0] + line * s->previous_frame->linesize[0] + - (width - 1)*s->pixel_size; + const uint8_t *this_line = p->data[0] + line * p->linesize[0] + width * s->pixel_size; + /* There might be no earlier frame if the current frame is a keyframe. + * So just use a pointer to the current frame to avoid a check + * to avoid NULL - s->pixel_size (which is undefined behaviour). */ + const uint8_t *prev_line = s->key_frame ? this_line + : s->previous_frame->data[0] + + line * s->previous_frame->linesize[0] + + width * s->pixel_size; s->length_table[width] = 0; skipcount = 0; @@ -175,6 +179,9 @@ int prev_bulk_cost; + this_line -= s->pixel_size; + prev_line -= s->pixel_size; + /* If our lowest bulk cost index is too far away, replace it * with the next lowest bulk cost */ if (FFMIN(width, i + MAX_RLE_BULK) < lowest_bulk_cost_index) { @@ -259,9 +266,6 @@ /* These bulk costs increase every iteration */ lowest_bulk_cost += s->pixel_size; sec_lowest_bulk_cost += s->pixel_size; - - this_line -= s->pixel_size; - prev_line -= s->pixel_size; } /* Good! Now we have the best sequence for this line, let's output it. */ @@ -368,7 +372,8 @@ if ((ret = ff_alloc_packet2(avctx, pkt, s->max_buf_size, 0)) < 0) return ret; - if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) { + if (avctx->gop_size == 0 || !s->previous_frame->data[0] || + (s->avctx->frame_number % avctx->gop_size) == 0) { /* I-Frame */ s->key_frame = 1; } else { @@ -412,4 +417,5 @@ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB555BE, AV_PIX_FMT_ARGB, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/r210enc.c ffmpeg-4.4/libavcodec/r210enc.c --- ffmpeg-4.2.2/libavcodec/r210enc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/r210enc.c 2020-07-11 10:39:30.000000000 +0000 @@ -60,9 +60,9 @@ uint16_t *srcb = (uint16_t *)srcb_line; for (j = 0; j < avctx->width; j++) { uint32_t pixel; - uint16_t r = *srcr++; - uint16_t g = *srcg++; - uint16_t b = *srcb++; + unsigned r = *srcr++; + unsigned g = *srcg++; + unsigned b = *srcb++; if (avctx->codec_id == AV_CODEC_ID_R210) pixel = (r << 20) | (g << 10) | b; else @@ -94,7 +94,6 @@ .init = encode_init, .encode2 = encode_frame, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_GBRP10, AV_PIX_FMT_NONE }, - .capabilities = AV_CODEC_CAP_INTRA_ONLY, }; #endif #if CONFIG_R10K_ENCODER @@ -106,7 +105,6 @@ .init = encode_init, .encode2 = encode_frame, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_GBRP10, AV_PIX_FMT_NONE }, - .capabilities = AV_CODEC_CAP_INTRA_ONLY, }; #endif #if CONFIG_AVRP_ENCODER @@ -118,6 +116,5 @@ .init = encode_init, .encode2 = encode_frame, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_GBRP10, AV_PIX_FMT_NONE }, - .capabilities = AV_CODEC_CAP_INTRA_ONLY, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/ra144dec.c ffmpeg-4.4/libavcodec/ra144dec.c --- ffmpeg-4.2.2/libavcodec/ra144dec.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ra144dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -134,5 +134,5 @@ .priv_data_size = sizeof(RA144Context), .init = ra144_decode_init, .decode = ra144_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; diff -Nru ffmpeg-4.2.2/libavcodec/ra144enc.c ffmpeg-4.4/libavcodec/ra144enc.c --- ffmpeg-4.2.2/libavcodec/ra144enc.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ra144enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -65,14 +65,11 @@ ret = ff_lpc_init(&ractx->lpc_ctx, avctx->frame_size, LPC_ORDER, FF_LPC_TYPE_LEVINSON); if (ret < 0) - goto error; + return ret; ff_af_queue_init(avctx, &ractx->afq); return 0; -error: - ra144_encode_close(avctx); - return ret; } @@ -477,8 +474,8 @@ LPC_ORDER, 16, lpc_coefs, shift, FF_LPC_TYPE_LEVINSON, 0, ORDER_METHOD_EST, 0, 12, 0); for (i = 0; i < LPC_ORDER; i++) - block_coefs[NBLOCKS - 1][i] = -(lpc_coefs[LPC_ORDER - 1][i] << - (12 - shift[LPC_ORDER - 1])); + block_coefs[NBLOCKS - 1][i] = -lpc_coefs[LPC_ORDER - 1][i] + * (1 << (12 - shift[LPC_ORDER - 1])); /** * TODO: apply perceptual weighting of the input speech through bandwidth diff -Nru ffmpeg-4.2.2/libavcodec/ra144.h ffmpeg-4.4/libavcodec/ra144.h --- ffmpeg-4.2.2/libavcodec/ra144.h 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ra144.h 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,9 @@ #define AVCODEC_RA144_H #include + +#include "libavutil/mem_internal.h" + #include "lpc.h" #include "audio_frame_queue.h" #include "audiodsp.h" diff -Nru ffmpeg-4.2.2/libavcodec/ra288.c ffmpeg-4.4/libavcodec/ra288.c --- ffmpeg-4.2.2/libavcodec/ra288.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ra288.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/float_dsp.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #define BITSTREAM_READER_LE #include "avcodec.h" @@ -39,7 +40,8 @@ #define RA288_BLOCKS_PER_FRAME 32 typedef struct RA288Context { - AVFloatDSPContext *fdsp; + void (*vector_fmul)(float *dst, const float *src0, const float *src1, + int len); DECLARE_ALIGNED(32, float, sp_lpc)[FFALIGN(36, 16)]; ///< LPC coefficients for speech data (spec: A) DECLARE_ALIGNED(32, float, gain_lpc)[FFALIGN(10, 16)]; ///< LPC coefficients for gain (spec: GB) @@ -60,31 +62,25 @@ float gain_rec[11]; } RA288Context; -static av_cold int ra288_decode_close(AVCodecContext *avctx) -{ - RA288Context *ractx = avctx->priv_data; - - av_freep(&ractx->fdsp); - - return 0; -} - static av_cold int ra288_decode_init(AVCodecContext *avctx) { RA288Context *ractx = avctx->priv_data; + AVFloatDSPContext *fdsp; avctx->channels = 1; avctx->channel_layout = AV_CH_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_FLT; - if (avctx->block_align <= 0) { + if (avctx->block_align != 38) { av_log(avctx, AV_LOG_ERROR, "unsupported block align\n"); return AVERROR_PATCHWELCOME; } - ractx->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); - if (!ractx->fdsp) + fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); + if (!fdsp) return AVERROR(ENOMEM); + ractx->vector_fmul = fdsp->vector_fmul; + av_free(fdsp); return 0; } @@ -158,7 +154,7 @@ av_assert2(order>=0); - ractx->fdsp->vector_fmul(work, window, hist, FFALIGN(order + n + non_rec, 16)); + ractx->vector_fmul(work, window, hist, FFALIGN(order + n + non_rec, 16)); convolve(buffer1, work + order , n , order); convolve(buffer2, work + order + n, non_rec, order); @@ -185,7 +181,7 @@ do_hybrid_window(ractx, order, n, non_rec, temp, hist, rec, window); if (!compute_lpc_coefs(temp, order, lpc, 0, 1, 1)) - ractx->fdsp->vector_fmul(lpc, lpc, tab, FFALIGN(order, 16)); + ractx->vector_fmul(lpc, lpc, tab, FFALIGN(order, 16)); memmove(hist, hist + n, move_size*sizeof(*hist)); } @@ -249,6 +245,5 @@ .priv_data_size = sizeof(RA288Context), .init = ra288_decode_init, .decode = ra288_decode_frame, - .close = ra288_decode_close, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; diff -Nru ffmpeg-4.2.2/libavcodec/ra288.h ffmpeg-4.4/libavcodec/ra288.h --- ffmpeg-4.2.2/libavcodec/ra288.h 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ra288.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,7 @@ #include #include "libavutil/common.h" +#include "libavutil/mem_internal.h" static const float amptable[8]={ 0.515625, 0.90234375, 1.57910156, 2.76342773, diff -Nru ffmpeg-4.2.2/libavcodec/ralf.c ffmpeg-4.4/libavcodec/ralf.c --- ffmpeg-4.2.2/libavcodec/ralf.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ralf.c 2021-04-08 21:28:39.000000000 +0000 @@ -60,7 +60,7 @@ int filter_bits; ///< filter precision for the current channel data int32_t filter[64]; - int bias[2]; ///< a constant value added to channel data after filtering + unsigned bias[2]; ///< a constant value added to channel data after filtering int num_blocks; ///< number of blocks inside the frame int sample_offset; @@ -330,7 +330,7 @@ acc = (acc + bias - 1) >> ctx->filter_bits; acc = FFMAX(acc, min_clip); } else { - acc = (acc + bias) >> ctx->filter_bits; + acc = ((unsigned)acc + bias) >> ctx->filter_bits; acc = FFMIN(acc, max_clip); } audio[i] += acc; @@ -344,7 +344,8 @@ int len, ch, ret; int dmode, mode[2], bits[2]; int *ch0, *ch1; - int i, t, t2; + int i; + unsigned int t, t2; len = 12 - get_unary(gb, 0, 6); @@ -409,8 +410,8 @@ for (i = 0; i < len; i++) { t = ch1[i] + ctx->bias[1]; t2 = ((ch0[i] + ctx->bias[0]) * 2) | (t & 1); - dst0[i] = (t2 + t) / 2; - dst1[i] = (t2 - t) / 2; + dst0[i] = (int)(t2 + t) / 2; + dst1[i] = (int)(t2 - t) / 2; } break; } @@ -481,6 +482,8 @@ init_get_bits(&gb, src + 2, table_size); ctx->num_blocks = 0; while (get_bits_left(&gb) > 0) { + if (ctx->num_blocks >= FF_ARRAY_ELEMS(ctx->block_size)) + return AVERROR_INVALIDDATA; ctx->block_size[ctx->num_blocks] = get_bits(&gb, 13 + avctx->channels); if (get_bits1(&gb)) { ctx->block_pts[ctx->num_blocks] = get_bits(&gb, 9); @@ -532,7 +535,8 @@ .close = decode_close, .decode = decode_frame, .flush = decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, }; diff -Nru ffmpeg-4.2.2/libavcodec/rangecoder.c ffmpeg-4.4/libavcodec/rangecoder.c --- ffmpeg-4.2.2/libavcodec/rangecoder.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rangecoder.c 2021-04-08 21:28:39.000000000 +0000 @@ -121,22 +121,3 @@ return c->bytestream - c->bytestream_start; } - -int ff_rac_check_termination(RangeCoder *c, int version) -{ - if (version == 1) { - RangeCoder tmp = *c; - get_rac(c, (uint8_t[]) { 129 }); - - if (c->bytestream == tmp.bytestream && c->bytestream > c->bytestream_start) - tmp.low -= *--tmp.bytestream; - tmp.bytestream_end = tmp.bytestream; - - if (get_rac(&tmp, (uint8_t[]) { 129 })) - return AVERROR_INVALIDDATA; - } else { - if (c->bytestream_end != c->bytestream) - return AVERROR_INVALIDDATA; - } - return 0; -} diff -Nru ffmpeg-4.2.2/libavcodec/rangecoder.h ffmpeg-4.4/libavcodec/rangecoder.h --- ffmpeg-4.2.2/libavcodec/rangecoder.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rangecoder.h 2021-04-08 21:28:39.000000000 +0000 @@ -57,15 +57,6 @@ */ int ff_rac_terminate(RangeCoder *c, int version); -/** - * Check if at the current position there is a valid looking termination - * @param version version 0 requires the decoder to know the data size in bytes - * version 1 needs about 1 bit more space but does not need to - * carry the size from encoder to decoder - * @returns negative AVERROR code on error or non negative. - */ -int ff_rac_check_termination(RangeCoder *c, int version); - void ff_build_rac_states(RangeCoder *c, int factor, int max_p); static inline void renorm_encoder(RangeCoder *c) diff -Nru ffmpeg-4.2.2/libavcodec/rasc.c ffmpeg-4.4/libavcodec/rasc.c --- ffmpeg-4.2.2/libavcodec/rasc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rasc.c 2021-04-08 21:28:39.000000000 +0000 @@ -70,6 +70,9 @@ RASCContext *s = avctx->priv_data; uint8_t *dst = frame->data[0]; + if (!dst) + return; + for (int y = 0; y < avctx->height; y++) { memset(dst, 0, avctx->width * s->bpp); dst += frame->linesize[0]; @@ -109,7 +112,7 @@ } static int decode_fint(AVCodecContext *avctx, - AVPacket *avpkt, unsigned size) + const AVPacket *avpkt, unsigned size) { RASCContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; @@ -124,6 +127,8 @@ clear_plane(avctx, s->frame1); return 0; } + if (bytestream2_get_bytes_left(gb) < 72) + return AVERROR_INVALIDDATA; bytestream2_skip(gb, 8); w = bytestream2_get_le32(gb); @@ -166,7 +171,7 @@ return 0; } -static int decode_zlib(AVCodecContext *avctx, AVPacket *avpkt, +static int decode_zlib(AVCodecContext *avctx, const AVPacket *avpkt, unsigned size, unsigned uncompressed_size) { RASCContext *s = avctx->priv_data; @@ -200,7 +205,7 @@ } static int decode_move(AVCodecContext *avctx, - AVPacket *avpkt, unsigned size) + const AVPacket *avpkt, unsigned size) { RASCContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; @@ -324,7 +329,7 @@ len--; static int decode_dlta(AVCodecContext *avctx, - AVPacket *avpkt, unsigned size) + const AVPacket *avpkt, unsigned size) { RASCContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; @@ -466,7 +471,7 @@ } static int decode_kfrm(AVCodecContext *avctx, - AVPacket *avpkt, unsigned size) + const AVPacket *avpkt, unsigned size) { RASCContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; @@ -529,7 +534,7 @@ } static int decode_mous(AVCodecContext *avctx, - AVPacket *avpkt, unsigned size) + const AVPacket *avpkt, unsigned size) { RASCContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; @@ -569,7 +574,7 @@ } static int decode_mpos(AVCodecContext *avctx, - AVPacket *avpkt, unsigned size) + const AVPacket *avpkt, unsigned size) { RASCContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; diff -Nru ffmpeg-4.2.2/libavcodec/ratecontrol.c ffmpeg-4.4/libavcodec/ratecontrol.c --- ffmpeg-4.2.2/libavcodec/ratecontrol.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ratecontrol.c 2020-07-11 10:39:30.000000000 +0000 @@ -999,11 +999,11 @@ if (s->avctx->debug & FF_DEBUG_RC) { av_log(s->avctx, AV_LOG_DEBUG, - "%c qp:%d<%2.1f<%d %d want:%d total:%d comp:%f st_q:%2.2f " + "%c qp:%d<%2.1f<%d %d want:%"PRId64" total:%"PRId64" comp:%f st_q:%2.2f " "size:%d var:%"PRId64"/%"PRId64" br:%"PRId64" fps:%d\n", av_get_picture_type_char(pict_type), qmin, q, qmax, picture_number, - (int)wanted_bits / 1000, (int)s->total_bits / 1000, + wanted_bits / 1000, s->total_bits / 1000, br_compensation, short_term_q, s->frame_bits, pic->mb_var_sum, pic->mc_mb_var_sum, s->bit_rate / 1000, (int)fps); diff -Nru ffmpeg-4.2.2/libavcodec/raw.c ffmpeg-4.4/libavcodec/raw.c --- ffmpeg-4.2.2/libavcodec/raw.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/raw.c 2021-04-08 21:28:39.000000000 +0000 @@ -246,6 +246,7 @@ { AV_PIX_FMT_GRAY16BE,MKTAG('b', '1', '6', 'g') }, { AV_PIX_FMT_RGB48BE, MKTAG('b', '4', '8', 'r') }, { AV_PIX_FMT_RGBA64BE,MKTAG('b', '6', '4', 'a') }, + { AV_PIX_FMT_BAYER_RGGB16BE, MKTAG('B', 'G', 'G', 'R') }, /* vlc */ { AV_PIX_FMT_YUV410P, MKTAG('I', '4', '1', '0') }, diff -Nru ffmpeg-4.2.2/libavcodec/rawdec.c ffmpeg-4.4/libavcodec/rawdec.c --- ffmpeg-4.2.2/libavcodec/rawdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rawdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bswapdsp.h" +#include "decode.h" #include "get_bits.h" #include "internal.h" #include "raw.h" @@ -366,7 +367,7 @@ } if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { - int pal_size; + buffer_size_t pal_size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size); int ret; @@ -467,10 +468,13 @@ avctx->pix_fmt == AV_PIX_FMT_RGBA64BE) { uint8_t *dst = frame->data[0]; uint64_t v; - int x; - for (x = 0; x >> 3 < avctx->width * avctx->height; x += 8) { - v = AV_RB64(&dst[x]); - AV_WB64(&dst[x], v << 16 | v >> 48); + int x, y; + for (y = 0; y < avctx->height; y++) { + for (x = 0; x >> 3 < avctx->width; x += 8) { + v = AV_RB64(&dst[x]); + AV_WB64(&dst[x], v << 16 | v >> 48); + } + dst += frame->linesize[0]; } } @@ -489,6 +493,7 @@ RawVideoContext *context = avctx->priv_data; av_buffer_unref(&context->palette); + av_freep(&context->bitstream_buf); return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/remove_extradata_bsf.c ffmpeg-4.4/libavcodec/remove_extradata_bsf.c --- ffmpeg-4.2.2/libavcodec/remove_extradata_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/remove_extradata_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -23,6 +23,7 @@ #include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" enum RemoveFreq { REMOVE_FREQ_KEYFRAME, diff -Nru ffmpeg-4.2.2/libavcodec/rkmppdec.c ffmpeg-4.4/libavcodec/rkmppdec.c --- ffmpeg-4.2.2/libavcodec/rkmppdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rkmppdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,7 +28,7 @@ #include "avcodec.h" #include "decode.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "internal.h" #include "libavutil/buffer.h" #include "libavutil/common.h" @@ -548,7 +548,7 @@ av_log(avctx, AV_LOG_ERROR, "Failed to reset MPI (code = %d)\n", ret); } -static const AVCodecHWConfigInternal *rkmpp_hw_configs[] = { +static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = { HW_CONFIG_INTERNAL(DRM_PRIME), NULL }; diff -Nru ffmpeg-4.2.2/libavcodec/rl.c ffmpeg-4.4/libavcodec/rl.c --- ffmpeg-4.2.2/libavcodec/rl.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rl.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,27 +25,16 @@ #include "rl.h" -void ff_rl_free(RLTable *rl) -{ - int i; - - for (i = 0; i < 2; i++) { - av_freep(&rl->max_run[i]); - av_freep(&rl->max_level[i]); - av_freep(&rl->index_run[i]); - } -} - -av_cold int ff_rl_init(RLTable *rl, - uint8_t static_store[2][2 * MAX_RUN + MAX_LEVEL + 3]) +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 table is static, we can quit if rl->max_level[0] is not NULL */ - if (static_store && rl->max_level[0]) - return 0; + /* 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++) { @@ -70,36 +59,13 @@ if (run > max_run[level]) max_run[level] = run; } - if (static_store) - rl->max_level[last] = static_store[last]; - else { - rl->max_level[last] = av_malloc(MAX_RUN + 1); - if (!rl->max_level[last]) - goto fail; - } + rl->max_level[last] = static_store[last]; memcpy(rl->max_level[last], max_level, MAX_RUN + 1); - if (static_store) - rl->max_run[last] = static_store[last] + MAX_RUN + 1; - else { - rl->max_run[last] = av_malloc(MAX_LEVEL + 1); - if (!rl->max_run[last]) - goto fail; - } + rl->max_run[last] = static_store[last] + MAX_RUN + 1; memcpy(rl->max_run[last], max_run, MAX_LEVEL + 1); - if (static_store) - rl->index_run[last] = static_store[last] + MAX_RUN + MAX_LEVEL + 2; - else { - rl->index_run[last] = av_malloc(MAX_RUN + 1); - if (!rl->index_run[last]) - goto fail; - } + rl->index_run[last] = static_store[last] + MAX_RUN + MAX_LEVEL + 2; memcpy(rl->index_run[last], index_run, MAX_RUN + 1); } - return 0; - -fail: - ff_rl_free(rl); - return AVERROR(ENOMEM); } av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size) @@ -114,6 +80,9 @@ int qmul = q * 2; int qadd = (q - 1) | 1; + if (!rl->rl_vlc[q]) + return; + if (q == 0) { qmul = 1; qadd = 0; diff -Nru ffmpeg-4.2.2/libavcodec/rl.h ffmpeg-4.4/libavcodec/rl.h --- ffmpeg-4.2.2/libavcodec/rl.h 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rl.h 2021-04-08 21:28:39.000000000 +0000 @@ -49,17 +49,12 @@ } RLTable; /** - * @param static_store static uint8_t array[2][2*MAX_RUN + MAX_LEVEL + 3] which will hold - * the level and run tables, if this is NULL av_malloc() will be used + * @param static_store static uint8_t array[2][2*MAX_RUN + MAX_LEVEL + 3] + * to hold the level and run tables. */ -int ff_rl_init(RLTable *rl, uint8_t static_store[2][2*MAX_RUN + MAX_LEVEL + 3]); +void ff_rl_init(RLTable *rl, uint8_t static_store[2][2*MAX_RUN + MAX_LEVEL + 3]); void ff_rl_init_vlc(RLTable *rl, unsigned static_size); -/** - * Free the contents of a dynamically allocated table. - */ -void ff_rl_free(RLTable *rl); - #define INIT_VLC_RL(rl, static_size)\ {\ int q;\ @@ -73,6 +68,14 @@ }\ } +#define INIT_FIRST_VLC_RL(rl, static_size) \ +do { \ + static RL_VLC_ELEM rl_vlc_table[static_size]; \ + \ + rl.rl_vlc[0] = rl_vlc_table; \ + ff_rl_init_vlc(&rl, static_size); \ +} while (0) + static inline int get_rl_index(const RLTable *rl, int last, int run, int level) { int index; diff -Nru ffmpeg-4.2.2/libavcodec/roqaudioenc.c ffmpeg-4.4/libavcodec/roqaudioenc.c --- ffmpeg-4.2.2/libavcodec/roqaudioenc.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/roqaudioenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -53,7 +53,6 @@ static av_cold int roq_dpcm_encode_init(AVCodecContext *avctx) { ROQDPCMContext *context = avctx->priv_data; - int ret; if (avctx->channels > 2) { av_log(avctx, AV_LOG_ERROR, "Audio must be mono or stereo\n"); @@ -70,17 +69,12 @@ context->frame_buffer = av_malloc(8 * ROQ_FRAME_SIZE * avctx->channels * sizeof(*context->frame_buffer)); - if (!context->frame_buffer) { - ret = AVERROR(ENOMEM); - goto error; - } + if (!context->frame_buffer) + return AVERROR(ENOMEM); context->lastSample[0] = context->lastSample[1] = 0; return 0; -error: - roq_dpcm_encode_close(avctx); - return ret; } static unsigned char dpcm_predict(short *previous, short current) diff -Nru ffmpeg-4.2.2/libavcodec/roqvideodec.c ffmpeg-4.4/libavcodec/roqvideodec.c --- ffmpeg-4.2.2/libavcodec/roqvideodec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/roqvideodec.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,20 +33,19 @@ #include "internal.h" #include "roqvideo.h" -static void roqvideo_decode_frame(RoqContext *ri) +static void roqvideo_decode_frame(RoqContext *ri, GetByteContext *gb) { unsigned int chunk_id = 0, chunk_arg = 0; unsigned long chunk_size = 0; int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1; int vqid, xpos, ypos, xp, yp, x, y, mx, my; - int frame_stats[2][4] = {{0},{0}}; roq_qcell *qcell; int64_t chunk_start; - while (bytestream2_get_bytes_left(&ri->gb) >= 8) { - chunk_id = bytestream2_get_le16(&ri->gb); - chunk_size = bytestream2_get_le32(&ri->gb); - chunk_arg = bytestream2_get_le16(&ri->gb); + while (bytestream2_get_bytes_left(gb) >= 8) { + chunk_id = bytestream2_get_le16(gb); + chunk_size = bytestream2_get_le32(gb); + chunk_arg = bytestream2_get_le16(gb); if(chunk_id == RoQ_QUAD_VQ) break; @@ -56,54 +55,53 @@ if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size) nv2 = 256; for(i = 0; i < nv1; i++) { - ri->cb2x2[i].y[0] = bytestream2_get_byte(&ri->gb); - ri->cb2x2[i].y[1] = bytestream2_get_byte(&ri->gb); - ri->cb2x2[i].y[2] = bytestream2_get_byte(&ri->gb); - ri->cb2x2[i].y[3] = bytestream2_get_byte(&ri->gb); - ri->cb2x2[i].u = bytestream2_get_byte(&ri->gb); - ri->cb2x2[i].v = bytestream2_get_byte(&ri->gb); + ri->cb2x2[i].y[0] = bytestream2_get_byte(gb); + ri->cb2x2[i].y[1] = bytestream2_get_byte(gb); + ri->cb2x2[i].y[2] = bytestream2_get_byte(gb); + ri->cb2x2[i].y[3] = bytestream2_get_byte(gb); + ri->cb2x2[i].u = bytestream2_get_byte(gb); + ri->cb2x2[i].v = bytestream2_get_byte(gb); } for(i = 0; i < nv2; i++) for(j = 0; j < 4; j++) - ri->cb4x4[i].idx[j] = bytestream2_get_byte(&ri->gb); + ri->cb4x4[i].idx[j] = bytestream2_get_byte(gb); } } - chunk_start = bytestream2_tell(&ri->gb); + chunk_start = bytestream2_tell(gb); xpos = ypos = 0; - if (chunk_size > bytestream2_get_bytes_left(&ri->gb)) { + if (chunk_size > bytestream2_get_bytes_left(gb)) { av_log(ri->avctx, AV_LOG_ERROR, "Chunk does not fit in input buffer\n"); - chunk_size = bytestream2_get_bytes_left(&ri->gb); + chunk_size = bytestream2_get_bytes_left(gb); } - while (bytestream2_tell(&ri->gb) < chunk_start + chunk_size) { + while (bytestream2_tell(gb) < chunk_start + chunk_size) { for (yp = ypos; yp < ypos + 16; yp += 8) for (xp = xpos; xp < xpos + 16; xp += 8) { - if (bytestream2_tell(&ri->gb) >= chunk_start + chunk_size) { + if (bytestream2_tell(gb) >= chunk_start + chunk_size) { av_log(ri->avctx, AV_LOG_VERBOSE, "Chunk is too short\n"); return; } if (vqflg_pos < 0) { - vqflg = bytestream2_get_le16(&ri->gb); + vqflg = bytestream2_get_le16(gb); vqflg_pos = 7; } vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; - frame_stats[0][vqid]++; vqflg_pos--; switch(vqid) { case RoQ_ID_MOT: break; case RoQ_ID_FCC: { - int byte = bytestream2_get_byte(&ri->gb); + int byte = bytestream2_get_byte(gb); mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8)); my = 8 - (byte & 0xf) - ((signed char) chunk_arg); ff_apply_motion_8x8(ri, xp, yp, mx, my); break; } case RoQ_ID_SLD: - qcell = ri->cb4x4 + bytestream2_get_byte(&ri->gb); + qcell = ri->cb4x4 + bytestream2_get_byte(gb); ff_apply_vector_4x4(ri, xp, yp, ri->cb2x2 + qcell->idx[0]); ff_apply_vector_4x4(ri, xp + 4, yp, ri->cb2x2 + qcell->idx[1]); ff_apply_vector_4x4(ri, xp, yp + 4, ri->cb2x2 + qcell->idx[2]); @@ -115,39 +113,38 @@ if(k & 0x01) x += 4; if(k & 0x02) y += 4; - if (bytestream2_tell(&ri->gb) >= chunk_start + chunk_size) { + if (bytestream2_tell(gb) >= chunk_start + chunk_size) { av_log(ri->avctx, AV_LOG_VERBOSE, "Chunk is too short\n"); return; } if (vqflg_pos < 0) { - vqflg = bytestream2_get_le16(&ri->gb); + vqflg = bytestream2_get_le16(gb); vqflg_pos = 7; } vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; - frame_stats[1][vqid]++; vqflg_pos--; switch(vqid) { case RoQ_ID_MOT: break; case RoQ_ID_FCC: { - int byte = bytestream2_get_byte(&ri->gb); + int byte = bytestream2_get_byte(gb); mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8)); my = 8 - (byte & 0xf) - ((signed char) chunk_arg); ff_apply_motion_4x4(ri, x, y, mx, my); break; } case RoQ_ID_SLD: - qcell = ri->cb4x4 + bytestream2_get_byte(&ri->gb); + qcell = ri->cb4x4 + bytestream2_get_byte(gb); ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + qcell->idx[0]); ff_apply_vector_2x2(ri, x + 2, y, ri->cb2x2 + qcell->idx[1]); ff_apply_vector_2x2(ri, x, y + 2, ri->cb2x2 + qcell->idx[2]); ff_apply_vector_2x2(ri, x + 2, y + 2, ri->cb2x2 + qcell->idx[3]); break; case RoQ_ID_CCC: - ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + bytestream2_get_byte(&ri->gb)); - ff_apply_vector_2x2(ri, x + 2, y, ri->cb2x2 + bytestream2_get_byte(&ri->gb)); - ff_apply_vector_2x2(ri, x, y + 2, ri->cb2x2 + bytestream2_get_byte(&ri->gb)); - ff_apply_vector_2x2(ri, x + 2, y + 2, ri->cb2x2 + bytestream2_get_byte(&ri->gb)); + ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + bytestream2_get_byte(gb)); + ff_apply_vector_2x2(ri, x + 2, y, ri->cb2x2 + bytestream2_get_byte(gb)); + ff_apply_vector_2x2(ri, x, y + 2, ri->cb2x2 + bytestream2_get_byte(gb)); + ff_apply_vector_2x2(ri, x + 2, y + 2, ri->cb2x2 + bytestream2_get_byte(gb)); break; } } @@ -184,11 +181,8 @@ s->last_frame = av_frame_alloc(); s->current_frame = av_frame_alloc(); - if (!s->current_frame || !s->last_frame) { - av_frame_free(&s->current_frame); - av_frame_free(&s->last_frame); + if (!s->current_frame || !s->last_frame) return AVERROR(ENOMEM); - } avctx->pix_fmt = AV_PIX_FMT_YUVJ444P; avctx->color_range = AVCOL_RANGE_JPEG; @@ -204,9 +198,10 @@ int buf_size = avpkt->size; RoqContext *s = avctx->priv_data; int copy = !s->current_frame->data[0] && s->last_frame->data[0]; + GetByteContext gb; int ret; - if ((ret = ff_reget_buffer(avctx, s->current_frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->current_frame, 0)) < 0) return ret; if (copy) { @@ -215,8 +210,8 @@ return ret; } - bytestream2_init(&s->gb, buf, buf_size); - roqvideo_decode_frame(s); + bytestream2_init(&gb, buf, buf_size); + roqvideo_decode_frame(s, &gb); if ((ret = av_frame_ref(data, s->current_frame)) < 0) return ret; @@ -248,4 +243,5 @@ .close = roq_decode_end, .decode = roq_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/roqvideoenc.c ffmpeg-4.4/libavcodec/roqvideoenc.c --- ffmpeg-4.2.2/libavcodec/roqvideoenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/roqvideoenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -57,6 +57,7 @@ #include #include "libavutil/attributes.h" +#include "libavutil/lfg.h" #include "libavutil/opt.h" #include "roqvideo.h" #include "bytestream.h" @@ -77,6 +78,85 @@ /* The cast is useful when multiplying it by INT_MAX */ #define ROQ_LAMBDA_SCALE ((uint64_t) FF_LAMBDA_SCALE) +typedef struct RoqCodebooks { + int numCB4; + int numCB2; + int usedCB2[MAX_CBS_2x2]; + int usedCB4[MAX_CBS_4x4]; + uint8_t unpacked_cb2[MAX_CBS_2x2*2*2*3]; + uint8_t unpacked_cb4[MAX_CBS_4x4*4*4*3]; + uint8_t unpacked_cb4_enlarged[MAX_CBS_4x4*8*8*3]; +} RoqCodebooks; + +/** + * Temporary vars + */ +typedef struct RoqTempData +{ + int f2i4[MAX_CBS_4x4]; + int i2f4[MAX_CBS_4x4]; + int f2i2[MAX_CBS_2x2]; + int i2f2[MAX_CBS_2x2]; + + int mainChunkSize; + + int numCB4; + int numCB2; + + RoqCodebooks codebooks; + + int used_option[4]; +} RoqTempData; + +typedef struct SubcelEvaluation { + int eval_dist[4]; + int best_bit_use; + int best_coding; + + int subCels[4]; + motion_vect motion; + int cbEntry; +} SubcelEvaluation; + +typedef struct CelEvaluation { + int eval_dist[4]; + int best_coding; + + SubcelEvaluation subCels[4]; + + motion_vect motion; + int cbEntry; + + int sourceX, sourceY; +} CelEvaluation; + +typedef struct RoqEncContext { + RoqContext common; + AVLFG randctx; + uint64_t lambda; + + motion_vect *this_motion4; + motion_vect *last_motion4; + + motion_vect *this_motion8; + motion_vect *last_motion8; + + unsigned int framesSinceKeyframe; + + const AVFrame *frame_to_enc; + uint8_t *out_buf; + RoqTempData tmp_data; + roq_cell results4[4 * MAX_CBS_4x4]; + int tmp_codebook_buf[FFMAX(24 * MAX_CBS_4x4, 6 * MAX_CBS_2x2)]; + + CelEvaluation *cel_evals; + int *closest_cb; + int *points; // Allocated together with closest_cb + + int first_frame; + int quake3_compat; // Quake 3 compatibility option +} RoqEncContext; + /* Macroblock support functions */ static void unpack_roq_cell(roq_cell *cell, uint8_t u[4*3]) { @@ -143,9 +223,10 @@ return sse; } -static int eval_motion_dist(RoqContext *enc, int x, int y, motion_vect vect, +static int eval_motion_dist(RoqEncContext *enc, int x, int y, motion_vect vect, int size) { + RoqContext *const roq = &enc->common; int mx=vect.d[0]; int my=vect.d[1]; @@ -158,12 +239,12 @@ mx += x; my += y; - if ((unsigned) mx > enc->width-size || (unsigned) my > enc->height-size) + if ((unsigned) mx > roq->width-size || (unsigned) my > roq->height-size) return INT_MAX; - return block_sse(enc->frame_to_enc->data, enc->last_frame->data, x, y, + return block_sse(enc->frame_to_enc->data, roq->last_frame->data, x, y, mx, my, - enc->frame_to_enc->linesize, enc->last_frame->linesize, + enc->frame_to_enc->linesize, roq->last_frame->linesize, size); } @@ -184,78 +265,23 @@ return sdiff; } -typedef struct SubcelEvaluation { - int eval_dist[4]; - int best_bit_use; - int best_coding; - - int subCels[4]; - motion_vect motion; - int cbEntry; -} SubcelEvaluation; - -typedef struct CelEvaluation { - int eval_dist[4]; - int best_coding; - - SubcelEvaluation subCels[4]; - - motion_vect motion; - int cbEntry; - - int sourceX, sourceY; -} CelEvaluation; - -typedef struct RoqCodebooks { - int numCB4; - int numCB2; - int usedCB2[MAX_CBS_2x2]; - int usedCB4[MAX_CBS_4x4]; - uint8_t unpacked_cb2[MAX_CBS_2x2*2*2*3]; - uint8_t unpacked_cb4[MAX_CBS_4x4*4*4*3]; - uint8_t unpacked_cb4_enlarged[MAX_CBS_4x4*8*8*3]; -} RoqCodebooks; - -/** - * Temporary vars - */ -typedef struct RoqTempData -{ - CelEvaluation *cel_evals; - - int f2i4[MAX_CBS_4x4]; - int i2f4[MAX_CBS_4x4]; - int f2i2[MAX_CBS_2x2]; - int i2f2[MAX_CBS_2x2]; - - int mainChunkSize; - - int numCB4; - int numCB2; - - RoqCodebooks codebooks; - - int *closest_cb2; - int used_option[4]; -} RoqTempdata; - /** * Initialize cel evaluators and set their source coordinates */ -static int create_cel_evals(RoqContext *enc, RoqTempdata *tempData) +static int create_cel_evals(RoqEncContext *enc) { - int n=0, x, y, i; + RoqContext *const roq = &enc->common; - tempData->cel_evals = av_malloc_array(enc->width*enc->height/64, sizeof(CelEvaluation)); - if (!tempData->cel_evals) + enc->cel_evals = av_malloc_array(roq->width * roq->height / 64, sizeof(CelEvaluation)); + if (!enc->cel_evals) return AVERROR(ENOMEM); /* Map to the ROQ quadtree order */ - for (y=0; yheight; y+=16) - for (x=0; xwidth; x+=16) - for(i=0; i<4; i++) { - tempData->cel_evals[n ].sourceX = x + (i&1)*8; - tempData->cel_evals[n++].sourceY = y + (i&2)*4; + for (int y = 0, n = 0; y < roq->height; y += 16) + for (int x = 0; x < roq->width; x += 16) + for(int i = 0; i < 4; i++) { + enc->cel_evals[n ].sourceX = x + (i&1)*8; + enc->cel_evals[n++].sourceY = y + (i&2)*4; } return 0; @@ -307,7 +333,7 @@ } \ } while(0) -static void motion_search(RoqContext *enc, int blocksize) +static void motion_search(RoqEncContext *enc, int blocksize) { static const motion_vect offsets[8] = { {{ 0,-1}}, @@ -320,6 +346,7 @@ {{ 1, 1}}, }; + RoqContext *const roq = &enc->common; int diff, lowestdiff, oldbest; int off[3]; motion_vect bestpick = {{0,0}}; @@ -328,8 +355,7 @@ motion_vect *last_motion; motion_vect *this_motion; motion_vect vect, vect2; - - int max=(enc->width/blocksize)*enc->height/blocksize; + const int max = (roq->width / blocksize) * roq->height / blocksize; if (blocksize == 4) { last_motion = enc->last_motion4; @@ -339,17 +365,17 @@ this_motion = enc->this_motion8; } - for (i=0; iheight; i+=blocksize) - for (j=0; jwidth; j+=blocksize) { + for (i = 0; i< roq->height; i += blocksize) + for (j = 0; j < roq->width; j += blocksize) { lowestdiff = eval_motion_dist(enc, j, i, (motion_vect) {{0,0}}, blocksize); bestpick.d[0] = 0; bestpick.d[1] = 0; if (blocksize == 4) - EVAL_MOTION(enc->this_motion8[(i/8)*(enc->width/8) + j/8]); + EVAL_MOTION(enc->this_motion8[(i/8) * (roq->width/8) + j/8]); - offset = (i/blocksize)*enc->width/blocksize + j/blocksize; + offset = (i/blocksize) * roq->width / blocksize + j / blocksize; if (offset < max && offset >= 0) EVAL_MOTION(last_motion[offset]); @@ -357,12 +383,12 @@ if (offset < max && offset >= 0) EVAL_MOTION(last_motion[offset]); - offset = (i/blocksize + 1)*enc->width/blocksize + j/blocksize; + offset = (i/blocksize + 1) * roq->width / blocksize + j / blocksize; if (offset < max && offset >= 0) EVAL_MOTION(last_motion[offset]); - off[0]= (i/blocksize)*enc->width/blocksize + j/blocksize - 1; - off[1]= off[0] - enc->width/blocksize + 1; + off[0]= (i/blocksize) * roq->width / blocksize + j/blocksize - 1; + off[1]= off[0] - roq->width / blocksize + 1; off[2]= off[1] + 1; if (i) { @@ -391,7 +417,7 @@ } vect = bestpick; } - offset = (i/blocksize)*enc->width/blocksize + j/blocksize; + offset = (i/blocksize) * roq->width / blocksize + j/blocksize; this_motion[offset] = bestpick; } } @@ -400,8 +426,10 @@ * Get distortion for all options available to a subcel */ static void gather_data_for_subcel(SubcelEvaluation *subcel, int x, - int y, RoqContext *enc, RoqTempdata *tempData) + int y, RoqEncContext *enc) { + RoqContext *const roq = &enc->common; + RoqTempData *const tempData = &enc->tmp_data; uint8_t mb4[4*4*3]; uint8_t mb2[2*2*3]; int cluster_index; @@ -410,25 +438,25 @@ static const int bitsUsed[4] = {2, 10, 10, 34}; if (enc->framesSinceKeyframe >= 1) { - subcel->motion = enc->this_motion4[y*enc->width/16 + x/4]; + subcel->motion = enc->this_motion4[y * roq->width / 16 + x / 4]; subcel->eval_dist[RoQ_ID_FCC] = eval_motion_dist(enc, x, y, - enc->this_motion4[y*enc->width/16 + x/4], 4); + enc->this_motion4[y * roq->width / 16 + x / 4], 4); } else subcel->eval_dist[RoQ_ID_FCC] = INT_MAX; if (enc->framesSinceKeyframe >= 2) subcel->eval_dist[RoQ_ID_MOT] = block_sse(enc->frame_to_enc->data, - enc->current_frame->data, x, + roq->current_frame->data, x, y, x, y, enc->frame_to_enc->linesize, - enc->current_frame->linesize, + roq->current_frame->linesize, 4); else subcel->eval_dist[RoQ_ID_MOT] = INT_MAX; - cluster_index = y*enc->width/16 + x/4; + cluster_index = y * roq->width / 16 + x / 4; get_frame_mb(enc->frame_to_enc, x, y, mb4, 4); @@ -440,7 +468,7 @@ subcel->eval_dist[RoQ_ID_CCC] = 0; for(i=0;i<4;i++) { - subcel->subCels[i] = tempData->closest_cb2[cluster_index*4+i]; + subcel->subCels[i] = enc->closest_cb[cluster_index*4+i]; get_frame_mb(enc->frame_to_enc, x+2*(i&1), y+(i&2), mb2, 2); @@ -463,11 +491,12 @@ /** * Get distortion for all options available to a cel */ -static void gather_data_for_cel(CelEvaluation *cel, RoqContext *enc, - RoqTempdata *tempData) +static void gather_data_for_cel(CelEvaluation *cel, RoqEncContext *enc) { + RoqContext *const roq = &enc->common; + RoqTempData *const tempData = &enc->tmp_data; uint8_t mb8[8*8*3]; - int index = cel->sourceY*enc->width/64 + cel->sourceX/8; + int index = cel->sourceY * roq->width / 64 + cel->sourceX/8; int i, j, best_dist, divide_bit_use; int bitsUsed[4] = {2, 10, 10, 0}; @@ -483,11 +512,11 @@ if (enc->framesSinceKeyframe >= 2) cel->eval_dist[RoQ_ID_MOT] = block_sse(enc->frame_to_enc->data, - enc->current_frame->data, + roq->current_frame->data, cel->sourceX, cel->sourceY, cel->sourceX, cel->sourceY, enc->frame_to_enc->linesize, - enc->current_frame->linesize,8); + roq->current_frame->linesize,8); else cel->eval_dist[RoQ_ID_MOT] = INT_MAX; @@ -497,10 +526,10 @@ index_mb(mb8, tempData->codebooks.unpacked_cb4_enlarged, tempData->codebooks.numCB4, &cel->cbEntry, 8); - gather_data_for_subcel(cel->subCels + 0, cel->sourceX+0, cel->sourceY+0, enc, tempData); - gather_data_for_subcel(cel->subCels + 1, cel->sourceX+4, cel->sourceY+0, enc, tempData); - gather_data_for_subcel(cel->subCels + 2, cel->sourceX+0, cel->sourceY+4, enc, tempData); - gather_data_for_subcel(cel->subCels + 3, cel->sourceX+4, cel->sourceY+4, enc, tempData); + gather_data_for_subcel(cel->subCels + 0, cel->sourceX+0, cel->sourceY+0, enc); + gather_data_for_subcel(cel->subCels + 1, cel->sourceX+4, cel->sourceY+0, enc); + gather_data_for_subcel(cel->subCels + 2, cel->sourceX+0, cel->sourceY+4, enc); + gather_data_for_subcel(cel->subCels + 3, cel->sourceX+4, cel->sourceY+4, enc); cel->eval_dist[RoQ_ID_CCC] = 0; divide_bit_use = 0; @@ -537,8 +566,10 @@ } } -static void remap_codebooks(RoqContext *enc, RoqTempdata *tempData) +static void remap_codebooks(RoqEncContext *enc) { + RoqContext *const roq = &enc->common; + RoqTempData *const tempData = &enc->tmp_data; int i, j, idx=0; /* Make remaps for the final codebook usage */ @@ -547,7 +578,7 @@ tempData->i2f4[i] = idx; tempData->f2i4[idx] = i; for (j=0; j<4; j++) - tempData->codebooks.usedCB2[enc->cb4x4[i].idx[j]]++; + tempData->codebooks.usedCB2[roq->cb4x4[i].idx[j]]++; idx++; } } @@ -569,8 +600,10 @@ /** * Write codebook chunk */ -static void write_codebooks(RoqContext *enc, RoqTempdata *tempData) +static void write_codebooks(RoqEncContext *enc) { + RoqContext *const roq = &enc->common; + RoqTempData *const tempData = &enc->tmp_data; int i, j; uint8_t **outp= &enc->out_buf; @@ -581,14 +614,14 @@ bytestream_put_byte(outp, tempData->numCB2); for (i=0; inumCB2; i++) { - bytestream_put_buffer(outp, enc->cb2x2[tempData->f2i2[i]].y, 4); - bytestream_put_byte(outp, enc->cb2x2[tempData->f2i2[i]].u); - bytestream_put_byte(outp, enc->cb2x2[tempData->f2i2[i]].v); + bytestream_put_buffer(outp, roq->cb2x2[tempData->f2i2[i]].y, 4); + bytestream_put_byte(outp, roq->cb2x2[tempData->f2i2[i]].u); + bytestream_put_byte(outp, roq->cb2x2[tempData->f2i2[i]].v); } for (i=0; inumCB4; i++) for (j=0; j<4; j++) - bytestream_put_byte(outp, tempData->i2f2[enc->cb4x4[tempData->f2i4[i]].idx[j]]); + bytestream_put_byte(outp, tempData->i2f2[roq->cb4x4[tempData->f2i4[i]].idx[j]]); } } @@ -623,8 +656,11 @@ } } -static void reconstruct_and_encode_image(RoqContext *enc, RoqTempdata *tempData, int w, int h, int numBlocks) +static void reconstruct_and_encode_image(RoqEncContext *enc, + int w, int h, int numBlocks) { + RoqContext *const roq = &enc->common; + RoqTempData *const tempData = &enc->tmp_data; int i, j, k; int x, y; int subX, subY; @@ -650,7 +686,7 @@ bytestream_put_byte(&enc->out_buf, 0x0); for (i=0; icel_evals + i; + eval = enc->cel_evals + i; x = eval->sourceX; y = eval->sourceY; @@ -665,7 +701,7 @@ bytestream_put_byte(&spool.args, motion_arg(eval->motion)); write_typecode(&spool, RoQ_ID_FCC); - ff_apply_motion_8x8(enc, x, y, + ff_apply_motion_8x8(roq, x, y, eval->motion.d[0], eval->motion.d[1]); break; @@ -673,11 +709,11 @@ bytestream_put_byte(&spool.args, tempData->i2f4[eval->cbEntry]); write_typecode(&spool, RoQ_ID_SLD); - qcell = enc->cb4x4 + eval->cbEntry; - ff_apply_vector_4x4(enc, x , y , enc->cb2x2 + qcell->idx[0]); - ff_apply_vector_4x4(enc, x+4, y , enc->cb2x2 + qcell->idx[1]); - ff_apply_vector_4x4(enc, x , y+4, enc->cb2x2 + qcell->idx[2]); - ff_apply_vector_4x4(enc, x+4, y+4, enc->cb2x2 + qcell->idx[3]); + qcell = roq->cb4x4 + eval->cbEntry; + ff_apply_vector_4x4(roq, x , y , roq->cb2x2 + qcell->idx[0]); + ff_apply_vector_4x4(roq, x+4, y , roq->cb2x2 + qcell->idx[1]); + ff_apply_vector_4x4(roq, x , y+4, roq->cb2x2 + qcell->idx[2]); + ff_apply_vector_4x4(roq, x+4, y+4, roq->cb2x2 + qcell->idx[3]); break; case RoQ_ID_CCC: @@ -695,7 +731,7 @@ bytestream_put_byte(&spool.args, motion_arg(eval->subCels[j].motion)); - ff_apply_motion_4x4(enc, subX, subY, + ff_apply_motion_4x4(roq, subX, subY, eval->subCels[j].motion.d[0], eval->subCels[j].motion.d[1]); break; @@ -704,16 +740,16 @@ bytestream_put_byte(&spool.args, tempData->i2f4[eval->subCels[j].cbEntry]); - qcell = enc->cb4x4 + eval->subCels[j].cbEntry; + qcell = roq->cb4x4 + eval->subCels[j].cbEntry; - ff_apply_vector_2x2(enc, subX , subY , - enc->cb2x2 + qcell->idx[0]); - ff_apply_vector_2x2(enc, subX+2, subY , - enc->cb2x2 + qcell->idx[1]); - ff_apply_vector_2x2(enc, subX , subY+2, - enc->cb2x2 + qcell->idx[2]); - ff_apply_vector_2x2(enc, subX+2, subY+2, - enc->cb2x2 + qcell->idx[3]); + ff_apply_vector_2x2(roq, subX , subY , + roq->cb2x2 + qcell->idx[0]); + ff_apply_vector_2x2(roq, subX+2, subY , + roq->cb2x2 + qcell->idx[1]); + ff_apply_vector_2x2(roq, subX , subY+2, + roq->cb2x2 + qcell->idx[2]); + ff_apply_vector_2x2(roq, subX+2, subY+2, + roq->cb2x2 + qcell->idx[3]); break; case RoQ_ID_CCC: @@ -722,8 +758,8 @@ bytestream_put_byte(&spool.args, tempData->i2f2[cb_idx]); - ff_apply_vector_2x2(enc, subX + 2*(k&1), subY + (k&2), - enc->cb2x2 + cb_idx); + ff_apply_vector_2x2(roq, subX + 2*(k&1), subY + (k&2), + roq->cb2x2 + cb_idx); } break; } @@ -742,7 +778,7 @@ /** * Create a single YUV cell from a 2x2 section of the image */ -static inline void frame_block_to_cell(uint8_t *block, uint8_t * const *data, +static inline void frame_block_to_cell(int *block, uint8_t * const *data, int top, int left, const int *stride) { int i, j, u=0, v=0; @@ -756,14 +792,14 @@ v += data[2][x]; } - *block++ = (u+2)/4; - *block++ = (v+2)/4; + *block++ = (u + 2) / 4 * CHROMA_BIAS; + *block++ = (v + 2) / 4 * CHROMA_BIAS; } /** * Create YUV clusters for the entire image */ -static void create_clusters(const AVFrame *frame, int w, int h, uint8_t *yuvClusters) +static void create_clusters(const AVFrame *frame, int w, int h, int *points) { int i, j, k, l; @@ -771,42 +807,30 @@ for (j=0; jdata, + frame_block_to_cell(points + (l + 2*k)*6, frame->data, i+2*k, j+2*l, frame->linesize); - yuvClusters += 24; + points += 24; } } -static int generate_codebook(RoqContext *enc, RoqTempdata *tempdata, +static int generate_codebook(RoqEncContext *enc, int *points, int inputCount, roq_cell *results, int size, int cbsize) { int i, j, k, ret = 0; int c_size = size*size/4; int *buf; - int *codebook = av_malloc_array(6*c_size, cbsize*sizeof(int)); - int *closest_cb; - - if (!codebook) - return AVERROR(ENOMEM); - - if (size == 4) { - closest_cb = av_malloc_array(6*c_size, inputCount*sizeof(int)); - if (!closest_cb) { - ret = AVERROR(ENOMEM); - goto out; - } - } else - closest_cb = tempdata->closest_cb2; + int *codebook = enc->tmp_codebook_buf; + int *closest_cb = enc->closest_cb; ret = avpriv_init_elbg(points, 6 * c_size, inputCount, codebook, cbsize, 1, closest_cb, &enc->randctx); if (ret < 0) - goto out; + return ret; ret = avpriv_do_elbg(points, 6 * c_size, inputCount, codebook, cbsize, 1, closest_cb, &enc->randctx); if (ret < 0) - goto out; + return ret; buf = codebook; for (i=0; iv = (*buf++ + CHROMA_BIAS/2)/CHROMA_BIAS; results++; } -out: - if (size == 4) - av_free(closest_cb); - av_free(codebook); - return ret; + return 0; } -static int generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData) +static int generate_new_codebooks(RoqEncContext *enc) { int i, j, ret = 0; - RoqCodebooks *codebooks = &tempData->codebooks; - int max = enc->width*enc->height/16; + RoqCodebooks *codebooks = &enc->tmp_data.codebooks; + RoqContext *const roq = &enc->common; + int max = roq->width * roq->height / 16; uint8_t mb2[3*4]; - roq_cell *results4 = av_malloc(sizeof(roq_cell)*MAX_CBS_4x4*4); - uint8_t *yuvClusters=av_malloc_array(max, sizeof(int)*6*4); - int *points = av_malloc_array(max, 6*4*sizeof(int)); - int bias; - - if (!results4 || !yuvClusters || !points) { - ret = AVERROR(ENOMEM); - goto out; - } + int *points = enc->points; /* Subsample YUV data */ - create_clusters(enc->frame_to_enc, enc->width, enc->height, yuvClusters); - - /* Cast to integer and apply chroma bias */ - for (i=0; iquake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4))) < 0) - goto out; + create_clusters(enc->frame_to_enc, roq->width, roq->height, points); codebooks->numCB4 = (enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4); - tempData->closest_cb2 = av_malloc_array(max, 4*sizeof(int)); - if (!tempData->closest_cb2) { - ret = AVERROR(ENOMEM); - goto out; - } + /* Create 4x4 codebooks */ + if ((ret = generate_codebook(enc, points, max, enc->results4, + 4, codebooks->numCB4)) < 0) + return ret; /* Create 2x2 codebooks */ - if ((ret = generate_codebook(enc, tempData, points, max * 4, - enc->cb2x2, 2, MAX_CBS_2x2)) < 0) - goto out; + if ((ret = generate_codebook(enc, points, max * 4, + roq->cb2x2, 2, MAX_CBS_2x2)) < 0) + return ret; codebooks->numCB2 = MAX_CBS_2x2; /* Unpack 2x2 codebook clusters */ for (i=0; inumCB2; i++) - unpack_roq_cell(enc->cb2x2 + i, codebooks->unpacked_cb2 + i*2*2*3); + unpack_roq_cell(roq->cb2x2 + i, codebooks->unpacked_cb2 + i*2*2*3); /* Index all 4x4 entries to the 2x2 entries, unpack, and enlarge */ for (i=0; inumCB4; i++) { for (j=0; j<4; j++) { - unpack_roq_cell(&results4[4*i + j], mb2); + unpack_roq_cell(&enc->results4[4*i + j], mb2); index_mb(mb2, codebooks->unpacked_cb2, codebooks->numCB2, - &enc->cb4x4[i].idx[j], 2); + &roq->cb4x4[i].idx[j], 2); } - unpack_roq_qcell(codebooks->unpacked_cb2, enc->cb4x4 + i, + unpack_roq_qcell(codebooks->unpacked_cb2, roq->cb4x4 + i, codebooks->unpacked_cb4 + i*4*4*3); enlarge_roq_mb4(codebooks->unpacked_cb4 + i*4*4*3, codebooks->unpacked_cb4_enlarged + i*8*8*3); } -out: - av_free(yuvClusters); - av_free(points); - av_free(results4); - return ret; + + return 0; } -static int roq_encode_video(RoqContext *enc) +static int roq_encode_video(RoqEncContext *enc) { - RoqTempdata *tempData = enc->tmpData; - int i, ret; + RoqTempData *const tempData = &enc->tmp_data; + RoqContext *const roq = &enc->common; + int ret; memset(tempData, 0, sizeof(*tempData)); - ret = create_cel_evals(enc, tempData); - if (ret < 0) - return ret; - - ret = generate_new_codebooks(enc, tempData); + ret = generate_new_codebooks(enc); if (ret < 0) return ret; @@ -914,16 +909,16 @@ } retry_encode: - for (i=0; iwidth*enc->height/64; i++) - gather_data_for_cel(tempData->cel_evals + i, enc, tempData); + for (int i = 0; i < roq->width * roq->height / 64; i++) + gather_data_for_cel(enc->cel_evals + i, enc); /* Quake 3 can't handle chunks bigger than 65535 bytes */ if (tempData->mainChunkSize/8 > 65535 && enc->quake3_compat) { if (enc->lambda > 100000) { - av_log(enc->avctx, AV_LOG_ERROR, "Cannot encode video in Quake compatible form\n"); + av_log(roq->avctx, AV_LOG_ERROR, "Cannot encode video in Quake compatible form\n"); return AVERROR(EINVAL); } - av_log(enc->avctx, AV_LOG_ERROR, + av_log(roq->avctx, AV_LOG_ERROR, "Warning, generated a frame too big for Quake (%d > 65535), " "now switching to a bigger qscale value.\n", tempData->mainChunkSize/8); @@ -938,21 +933,18 @@ goto retry_encode; } - remap_codebooks(enc, tempData); + remap_codebooks(enc); - write_codebooks(enc, tempData); + write_codebooks(enc); - reconstruct_and_encode_image(enc, tempData, enc->width, enc->height, - enc->width*enc->height/64); + reconstruct_and_encode_image(enc, roq->width, roq->height, + roq->width * roq->height / 64); /* Rotate frame history */ - FFSWAP(AVFrame *, enc->current_frame, enc->last_frame); + FFSWAP(AVFrame *, roq->current_frame, roq->last_frame); FFSWAP(motion_vect *, enc->last_motion4, enc->this_motion4); FFSWAP(motion_vect *, enc->last_motion8, enc->this_motion8); - av_freep(&tempData->cel_evals); - av_freep(&tempData->closest_cb2); - enc->framesSinceKeyframe++; return 0; @@ -960,12 +952,13 @@ static av_cold int roq_encode_end(AVCodecContext *avctx) { - RoqContext *enc = avctx->priv_data; + RoqEncContext *const enc = avctx->priv_data; - av_frame_free(&enc->current_frame); - av_frame_free(&enc->last_frame); + av_frame_free(&enc->common.current_frame); + av_frame_free(&enc->common.last_frame); - av_freep(&enc->tmpData); + av_freep(&enc->cel_evals); + av_freep(&enc->closest_cb); av_freep(&enc->this_motion4); av_freep(&enc->last_motion4); av_freep(&enc->this_motion8); @@ -976,11 +969,12 @@ static av_cold int roq_encode_init(AVCodecContext *avctx) { - RoqContext *enc = avctx->priv_data; + RoqEncContext *const enc = avctx->priv_data; + RoqContext *const roq = &enc->common; av_lfg_init(&enc->randctx, 1); - enc->avctx = avctx; + roq->avctx = avctx; enc->framesSinceKeyframe = 0; if ((avctx->width & 0xf) || (avctx->height & 0xf)) { @@ -996,43 +990,44 @@ if (((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx->height-1))) av_log(avctx, AV_LOG_ERROR, "Warning: dimensions not power of two, this is not supported by quake\n"); - enc->width = avctx->width; - enc->height = avctx->height; + roq->width = avctx->width; + roq->height = avctx->height; enc->framesSinceKeyframe = 0; enc->first_frame = 1; - enc->last_frame = av_frame_alloc(); - enc->current_frame = av_frame_alloc(); - if (!enc->last_frame || !enc->current_frame) { - roq_encode_end(avctx); + roq->last_frame = av_frame_alloc(); + roq->current_frame = av_frame_alloc(); + if (!roq->last_frame || !roq->current_frame) return AVERROR(ENOMEM); - } - - enc->tmpData = av_malloc(sizeof(RoqTempdata)); enc->this_motion4 = - av_mallocz_array((enc->width*enc->height/16), sizeof(motion_vect)); + av_mallocz_array(roq->width * roq->height / 16, sizeof(motion_vect)); enc->last_motion4 = - av_malloc_array ((enc->width*enc->height/16), sizeof(motion_vect)); + av_malloc_array (roq->width * roq->height / 16, sizeof(motion_vect)); enc->this_motion8 = - av_mallocz_array((enc->width*enc->height/64), sizeof(motion_vect)); + av_mallocz_array(roq->width * roq->height / 64, sizeof(motion_vect)); enc->last_motion8 = - av_malloc_array ((enc->width*enc->height/64), sizeof(motion_vect)); + av_malloc_array (roq->width * roq->height / 64, sizeof(motion_vect)); - if (!enc->tmpData || !enc->this_motion4 || !enc->last_motion4 || - !enc->this_motion8 || !enc->last_motion8) { - roq_encode_end(avctx); + /* 4x4 codebook needs 6 * 4 * 4 / 4 * width * height / 16 * sizeof(int); + * and so does the points buffer. */ + enc->closest_cb = + av_malloc_array(roq->width * roq->height, 3 * sizeof(int)); + + if (!enc->this_motion4 || !enc->last_motion4 || + !enc->this_motion8 || !enc->last_motion8 || !enc->closest_cb) return AVERROR(ENOMEM); - } - return 0; + enc->points = enc->closest_cb + roq->width * roq->height * 3 / 2; + + return create_cel_evals(enc); } -static void roq_write_video_info_chunk(RoqContext *enc) +static void roq_write_video_info_chunk(RoqEncContext *enc) { /* ROQ info chunk */ bytestream_put_le16(&enc->out_buf, RoQ_INFO); @@ -1045,10 +1040,10 @@ bytestream_put_byte(&enc->out_buf, 0x00); /* Width */ - bytestream_put_le16(&enc->out_buf, enc->width); + bytestream_put_le16(&enc->out_buf, enc->common.width); /* Height */ - bytestream_put_le16(&enc->out_buf, enc->height); + bytestream_put_le16(&enc->out_buf, enc->common.height); /* Unused in Quake 3, mimics the output of the real encoder */ bytestream_put_byte(&enc->out_buf, 0x08); @@ -1060,10 +1055,11 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { - RoqContext *enc = avctx->priv_data; + RoqEncContext *const enc = avctx->priv_data; + RoqContext *const roq = &enc->common; int size, ret; - enc->avctx = avctx; + roq->avctx = avctx; enc->frame_to_enc = frame; @@ -1074,7 +1070,7 @@ /* 138 bits max per 8x8 block + * 256 codebooks*(6 bytes 2x2 + 4 bytes 4x4) + 8 bytes frame header */ - size = ((enc->width * enc->height / 64) * 138 + 7) / 8 + 256 * (6 + 4) + 8; + size = ((roq->width * roq->height / 64) * 138 + 7) / 8 + 256 * (6 + 4) + 8; if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0) return ret; enc->out_buf = pkt->data; @@ -1086,8 +1082,8 @@ if (enc->first_frame) { /* Alloc memory for the reconstruction data (we must know the stride for that) */ - if ((ret = ff_get_buffer(avctx, enc->current_frame, 0)) < 0 || - (ret = ff_get_buffer(avctx, enc->last_frame, 0)) < 0) + if ((ret = ff_get_buffer(avctx, roq->current_frame, 0)) < 0 || + (ret = ff_get_buffer(avctx, roq->last_frame, 0)) < 0) return ret; /* Before the first video frame, write a "video info" chunk */ @@ -1109,7 +1105,7 @@ return 0; } -#define OFFSET(x) offsetof(RoqContext, x) +#define OFFSET(x) offsetof(RoqEncContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "quake3_compat", "Whether to respect known limitations in Quake 3 decoder", OFFSET(quake3_compat), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, @@ -1128,11 +1124,12 @@ .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_ROQ, - .priv_data_size = sizeof(RoqContext), + .priv_data_size = sizeof(RoqEncContext), .init = roq_encode_init, .encode2 = roq_encode_frame, .close = roq_encode_end, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_NONE }, .priv_class = &roq_class, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/roqvideo.h ffmpeg-4.4/libavcodec/roqvideo.h --- ffmpeg-4.2.2/libavcodec/roqvideo.h 2016-03-29 02:25:21.000000000 +0000 +++ ffmpeg-4.4/libavcodec/roqvideo.h 2021-04-08 21:28:39.000000000 +0000 @@ -22,9 +22,7 @@ #ifndef AVCODEC_ROQVIDEO_H #define AVCODEC_ROQVIDEO_H -#include "libavutil/lfg.h" #include "avcodec.h" -#include "bytestream.h" typedef struct roq_cell { unsigned char y[4]; @@ -39,40 +37,15 @@ int d[2]; } motion_vect; -struct RoqTempData; - typedef struct RoqContext { - const AVClass *class; AVCodecContext *avctx; AVFrame *last_frame; AVFrame *current_frame; - int first_frame; + int width, height; roq_cell cb2x2[256]; roq_qcell cb4x4[256]; - - GetByteContext gb; - int width, height; - - /* Encoder only data */ - AVLFG randctx; - uint64_t lambda; - - motion_vect *this_motion4; - motion_vect *last_motion4; - - motion_vect *this_motion8; - motion_vect *last_motion8; - - unsigned int framesSinceKeyframe; - - const AVFrame *frame_to_enc; - uint8_t *out_buf; - struct RoqTempData *tmpData; - - int quake3_compat; // Quake 3 compatibility option - } RoqContext; #define RoQ_INFO 0x1001 diff -Nru ffmpeg-4.2.2/libavcodec/rpza.c ffmpeg-4.4/libavcodec/rpza.c --- ffmpeg-4.2.2/libavcodec/rpza.c 2019-03-29 00:49:21.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rpza.c 2020-07-11 10:39:30.000000000 +0000 @@ -108,7 +108,7 @@ if (total_blocks / 32 > bytestream2_get_bytes_left(&s->gb)) return AVERROR_INVALIDDATA; - if ((ret = ff_reget_buffer(s->avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(s->avctx, s->frame, 0)) < 0) return ret; pixels = (uint16_t *)s->frame->data[0]; stride = s->frame->linesize[0] / 2; diff -Nru ffmpeg-4.2.2/libavcodec/rpzaenc.c ffmpeg-4.4/libavcodec/rpzaenc.c --- ffmpeg-4.2.2/libavcodec/rpzaenc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rpzaenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,858 @@ +/* + * QuickTime RPZA Video Encoder + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file rpzaenc.c + * QT RPZA Video Encoder by Todd Kirby and David Adler + */ + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "avcodec.h" +#include "internal.h" +#include "put_bits.h" + +typedef struct RpzaContext { + AVClass *avclass; + + int skip_frame_thresh; + int start_one_color_thresh; + int continue_one_color_thresh; + int sixteen_color_thresh; + + AVFrame *prev_frame; // buffer for previous source frame + PutBitContext pb; // buffer for encoded frame data. + + int frame_width; // width in pixels of source frame + int frame_height; // height in pixesl of source frame + + int first_frame; // flag set to one when the first frame is being processed + // so that comparisons with previous frame data in not attempted +} RpzaContext; + +typedef enum channel_offset { + RED = 2, + GREEN = 1, + BLUE = 0, +} channel_offset; + +typedef struct rgb { + uint8_t r; + uint8_t g; + uint8_t b; +} rgb; + +#define SQR(x) ((x) * (x)) + +/* 15 bit components */ +#define GET_CHAN(color, chan) (((color) >> ((chan) * 5) & 0x1F) * 8) +#define R(color) GET_CHAN(color, RED) +#define G(color) GET_CHAN(color, GREEN) +#define B(color) GET_CHAN(color, BLUE) + +typedef struct BlockInfo { + int row; + int col; + int block_width; + int block_height; + int image_width; + int image_height; + int block_index; + uint16_t start; + int rowstride; + int blocks_per_row; + int total_blocks; +} BlockInfo; + +static void get_colors(uint8_t *min, uint8_t *max, uint8_t color4[4][3]) +{ + uint8_t step; + + color4[0][0] = min[0]; + color4[0][1] = min[1]; + color4[0][2] = min[2]; + + color4[3][0] = max[0]; + color4[3][1] = max[1]; + color4[3][2] = max[2]; + + // red components + step = (color4[3][0] - color4[0][0] + 1) / 3; + color4[1][0] = color4[0][0] + step; + color4[2][0] = color4[3][0] - step; + + // green components + step = (color4[3][1] - color4[0][1] + 1) / 3; + color4[1][1] = color4[0][1] + step; + color4[2][1] = color4[3][1] - step; + + // blue components + step = (color4[3][2] - color4[0][2] + 1) / 3; + color4[1][2] = color4[0][2] + step; + color4[2][2] = color4[3][2] - step; +} + +/* Fill BlockInfo struct with information about a 4x4 block of the image */ +static int get_block_info(BlockInfo *bi, int block) +{ + bi->row = block / bi->blocks_per_row; + bi->col = block % bi->blocks_per_row; + + // test for right edge block + if (bi->col == bi->blocks_per_row - 1 && (bi->image_width % 4) != 0) { + bi->block_width = bi->image_width % 4; + } else { + bi->block_width = 4; + } + + // test for bottom edge block + if (bi->row == (bi->image_height / 4) && (bi->image_height % 4) != 0) { + bi->block_height = bi->image_height % 4; + } else { + bi->block_height = 4; + } + + return block ? (bi->col * 4) + (bi->row * bi->rowstride * 4) : 0; +} + +static uint16_t rgb24_to_rgb555(uint8_t *rgb24) +{ + uint16_t rgb555 = 0; + uint32_t r, g, b; + + r = rgb24[0] >> 3; + g = rgb24[1] >> 3; + b = rgb24[2] >> 3; + + rgb555 |= (r << 10); + rgb555 |= (g << 5); + rgb555 |= (b << 0); + + return rgb555; +} + +/* + * Returns the total difference between two 24 bit color values + */ +static int diff_colors(uint8_t *colorA, uint8_t *colorB) +{ + int tot; + + tot = SQR(colorA[0] - colorB[0]); + tot += SQR(colorA[1] - colorB[1]); + tot += SQR(colorA[2] - colorB[2]); + + return tot; +} + +/* + * Returns the maximum channel difference + */ +static int max_component_diff(uint16_t *colorA, uint16_t *colorB) +{ + int diff, max = 0; + + diff = FFABS(R(colorA[0]) - R(colorB[0])); + if (diff > max) { + max = diff; + } + diff = FFABS(G(colorA[0]) - G(colorB[0])); + if (diff > max) { + max = diff; + } + diff = FFABS(B(colorA[0]) - B(colorB[0])); + if (diff > max) { + max = diff; + } + return max * 8; +} + +/* + * Find the channel that has the largest difference between minimum and maximum + * color values. Put the minimum value in min, maximum in max and the channel + * in chan. + */ +static void get_max_component_diff(BlockInfo *bi, uint16_t *block_ptr, + uint8_t *min, uint8_t *max, channel_offset *chan) +{ + int x, y; + uint8_t min_r, max_r, min_g, max_g, min_b, max_b; + uint8_t r, g, b; + + // fix warning about uninitialized vars + min_r = min_g = min_b = UINT8_MAX; + max_r = max_g = max_b = 0; + + // loop thru and compare pixels + for (y = 0; y < bi->block_height; y++) { + for (x = 0; x < bi->block_width; x++){ + // TODO: optimize + min_r = FFMIN(R(block_ptr[x]), min_r); + min_g = FFMIN(G(block_ptr[x]), min_g); + min_b = FFMIN(B(block_ptr[x]), min_b); + + max_r = FFMAX(R(block_ptr[x]), max_r); + max_g = FFMAX(G(block_ptr[x]), max_g); + max_b = FFMAX(B(block_ptr[x]), max_b); + } + block_ptr += bi->rowstride; + } + + r = max_r - min_r; + g = max_g - min_g; + b = max_b - min_b; + + if (r > g && r > b) { + *max = max_r; + *min = min_r; + *chan = RED; + } else if (g > b && g >= r) { + *max = max_g; + *min = min_g; + *chan = GREEN; + } else { + *max = max_b; + *min = min_b; + *chan = BLUE; + } +} + +/* + * Compare two 4x4 blocks to determine if the total difference between the + * blocks is greater than the thresh parameter. Returns -1 if difference + * exceeds threshold or zero otherwise. + */ +static int compare_blocks(uint16_t *block1, uint16_t *block2, BlockInfo *bi, int thresh) +{ + int x, y, diff = 0; + for (y = 0; y < bi->block_height; y++) { + for (x = 0; x < bi->block_width; x++) { + diff = max_component_diff(&block1[x], &block2[x]); + if (diff >= thresh) { + return -1; + } + } + block1 += bi->rowstride; + block2 += bi->rowstride; + } + return 0; +} + +/* + * Determine the fit of one channel to another within a 4x4 block. This + * is used to determine the best palette choices for 4-color encoding. + */ +static int leastsquares(uint16_t *block_ptr, BlockInfo *bi, + channel_offset xchannel, channel_offset ychannel, + double *slope, double *y_intercept, double *correlation_coef) +{ + double sumx = 0, sumy = 0, sumx2 = 0, sumy2 = 0, sumxy = 0, + sumx_sq = 0, sumy_sq = 0, tmp, tmp2; + int i, j, count; + uint8_t x, y; + + count = bi->block_height * bi->block_width; + + if (count < 2) + return -1; + + for (i = 0; i < bi->block_height; i++) { + for (j = 0; j < bi->block_width; j++){ + x = GET_CHAN(block_ptr[j], xchannel); + y = GET_CHAN(block_ptr[j], ychannel); + sumx += x; + sumy += y; + sumx2 += x * x; + sumy2 += y * y; + sumxy += x * y; + } + block_ptr += bi->rowstride; + } + + sumx_sq = sumx * sumx; + tmp = (count * sumx2 - sumx_sq); + + // guard against div/0 + if (tmp == 0) + return -2; + + sumy_sq = sumy * sumy; + + *slope = (sumx * sumy - sumxy) / tmp; + *y_intercept = (sumy - (*slope) * sumx) / count; + + tmp2 = count * sumy2 - sumy_sq; + if (tmp2 == 0) { + *correlation_coef = 0.0; + } else { + *correlation_coef = (count * sumxy - sumx * sumy) / + sqrt(tmp * tmp2); + } + + return 0; // success +} + +/* + * Determine the amount of error in the leastsquares fit. + */ +static int calc_lsq_max_fit_error(uint16_t *block_ptr, BlockInfo *bi, + int min, int max, int tmp_min, int tmp_max, + channel_offset xchannel, channel_offset ychannel) +{ + int i, j, x, y; + int err; + int max_err = 0; + + for (i = 0; i < bi->block_height; i++) { + for (j = 0; j < bi->block_width; j++){ + int x_inc, lin_y, lin_x; + x = GET_CHAN(block_ptr[j], xchannel); + y = GET_CHAN(block_ptr[j], ychannel); + + /* calculate x_inc as the 4-color index (0..3) */ + x_inc = floor( (x - min) * 3.0 / (max - min) + 0.5); + x_inc = FFMAX(FFMIN(3, x_inc), 0); + + /* calculate lin_y corresponding to x_inc */ + lin_y = (int)(tmp_min + (tmp_max - tmp_min) * x_inc / 3.0 + 0.5); + + err = FFABS(lin_y - y); + if (err > max_err) + max_err = err; + + /* calculate lin_x corresponding to x_inc */ + lin_x = (int)(min + (max - min) * x_inc / 3.0 + 0.5); + + err = FFABS(lin_x - x); + if (err > max_err) + max_err += err; + } + block_ptr += bi->rowstride; + } + + return max_err; +} + +/* + * Find the closest match to a color within the 4-color palette + */ +static int match_color(uint16_t *color, uint8_t colors[4][3]) +{ + int ret = 0; + int smallest_variance = INT_MAX; + uint8_t dithered_color[3]; + + for (int channel = 0; channel < 3; channel++) { + dithered_color[channel] = GET_CHAN(color[0], channel); + } + + for (int palette_entry = 0; palette_entry < 4; palette_entry++) { + int variance = diff_colors(dithered_color, colors[palette_entry]); + + if (variance < smallest_variance) { + smallest_variance = variance; + ret = palette_entry; + } + } + + return ret; +} + +/* + * Encode a block using the 4-color opcode and palette. return number of + * blocks encoded (until we implement multi-block 4 color runs this will + * always be 1) + */ +static int encode_four_color_block(uint8_t *min_color, uint8_t *max_color, + PutBitContext *pb, uint16_t *block_ptr, BlockInfo *bi) +{ + int x, y, idx; + uint8_t color4[4][3]; + uint16_t rounded_max, rounded_min; + + // round min and max wider + rounded_min = rgb24_to_rgb555(min_color); + rounded_max = rgb24_to_rgb555(max_color); + + // put a and b colors + // encode 4 colors = first 16 bit color with MSB zeroed and... + put_bits(pb, 16, rounded_max & ~0x8000); + // ...second 16 bit color with MSB on. + put_bits(pb, 16, rounded_min | 0x8000); + + get_colors(min_color, max_color, color4); + + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + idx = match_color(&block_ptr[x], color4); + put_bits(pb, 2, idx); + } + block_ptr += bi->rowstride; + } + return 1; // num blocks encoded +} + +/* + * Copy a 4x4 block from the current frame buffer to the previous frame buffer. + */ +static void update_block_in_prev_frame(const uint16_t *src_pixels, + uint16_t *dest_pixels, + const BlockInfo *bi, int block_counter) +{ + for (int y = 0; y < 4; y++) { + memcpy(dest_pixels, src_pixels, 8); + dest_pixels += bi->rowstride; + src_pixels += bi->rowstride; + } +} + +/* + * update statistics for the specified block. If first_block, + * it initializes the statistics. Otherwise it updates the statistics IF THIS + * BLOCK IS SUITABLE TO CONTINUE A 1-COLOR RUN. That is, it checks whether + * the range of colors (since the routine was called first_block != 0) are + * all close enough intensities to be represented by a single color. + + * The routine returns 0 if this block is too different to be part of + * the same run of 1-color blocks. The routine returns 1 if this + * block can be part of the same 1-color block run. + + * If the routine returns 1, it also updates its arguments to include + * the statistics of this block. Otherwise, the stats are unchanged + * and don't include the current block. + */ +static int update_block_stats(RpzaContext *s, BlockInfo *bi, uint16_t *block, + uint8_t min_color[3], uint8_t max_color[3], + int *total_rgb, int *total_pixels, + uint8_t avg_color[3], int first_block) +{ + int x, y; + int is_in_range; + int total_pixels_blk; + int threshold; + + uint8_t min_color_blk[3], max_color_blk[3]; + int total_rgb_blk[3]; + uint8_t avg_color_blk[3]; + + if (first_block) { + min_color[0] = UINT8_MAX; + min_color[1] = UINT8_MAX; + min_color[2] = UINT8_MAX; + max_color[0] = 0; + max_color[1] = 0; + max_color[2] = 0; + total_rgb[0] = 0; + total_rgb[1] = 0; + total_rgb[2] = 0; + *total_pixels = 0; + threshold = s->start_one_color_thresh; + } else { + threshold = s->continue_one_color_thresh; + } + + /* + The *_blk variables will include the current block. + Initialize them based on the blocks so far. + */ + min_color_blk[0] = min_color[0]; + min_color_blk[1] = min_color[1]; + min_color_blk[2] = min_color[2]; + max_color_blk[0] = max_color[0]; + max_color_blk[1] = max_color[1]; + max_color_blk[2] = max_color[2]; + total_rgb_blk[0] = total_rgb[0]; + total_rgb_blk[1] = total_rgb[1]; + total_rgb_blk[2] = total_rgb[2]; + total_pixels_blk = *total_pixels + bi->block_height * bi->block_width; + + /* + Update stats for this block's pixels + */ + for (y = 0; y < bi->block_height; y++) { + for (x = 0; x < bi->block_width; x++) { + total_rgb_blk[0] += R(block[x]); + total_rgb_blk[1] += G(block[x]); + total_rgb_blk[2] += B(block[x]); + + min_color_blk[0] = FFMIN(R(block[x]), min_color_blk[0]); + min_color_blk[1] = FFMIN(G(block[x]), min_color_blk[1]); + min_color_blk[2] = FFMIN(B(block[x]), min_color_blk[2]); + + max_color_blk[0] = FFMAX(R(block[x]), max_color_blk[0]); + max_color_blk[1] = FFMAX(G(block[x]), max_color_blk[1]); + max_color_blk[2] = FFMAX(B(block[x]), max_color_blk[2]); + } + block += bi->rowstride; + } + + /* + Calculate average color including current block. + */ + avg_color_blk[0] = total_rgb_blk[0] / total_pixels_blk; + avg_color_blk[1] = total_rgb_blk[1] / total_pixels_blk; + avg_color_blk[2] = total_rgb_blk[2] / total_pixels_blk; + + /* + Are all the pixels within threshold of the average color? + */ + is_in_range = (max_color_blk[0] - avg_color_blk[0] <= threshold && + max_color_blk[1] - avg_color_blk[1] <= threshold && + max_color_blk[2] - avg_color_blk[2] <= threshold && + avg_color_blk[0] - min_color_blk[0] <= threshold && + avg_color_blk[1] - min_color_blk[1] <= threshold && + avg_color_blk[2] - min_color_blk[2] <= threshold); + + if (is_in_range) { + /* + Set the output variables to include this block. + */ + min_color[0] = min_color_blk[0]; + min_color[1] = min_color_blk[1]; + min_color[2] = min_color_blk[2]; + max_color[0] = max_color_blk[0]; + max_color[1] = max_color_blk[1]; + max_color[2] = max_color_blk[2]; + total_rgb[0] = total_rgb_blk[0]; + total_rgb[1] = total_rgb_blk[1]; + total_rgb[2] = total_rgb_blk[2]; + *total_pixels = total_pixels_blk; + avg_color[0] = avg_color_blk[0]; + avg_color[1] = avg_color_blk[1]; + avg_color[2] = avg_color_blk[2]; + } + + return is_in_range; +} + +static void rpza_encode_stream(RpzaContext *s, const AVFrame *pict) +{ + BlockInfo bi; + int block_counter = 0; + int n_blocks; + int total_blocks; + int prev_block_offset; + int block_offset = 0; + uint8_t min = 0, max = 0; + channel_offset chan; + int i; + int tmp_min, tmp_max; + int total_rgb[3]; + uint8_t avg_color[3]; + int pixel_count; + uint8_t min_color[3], max_color[3]; + double slope, y_intercept, correlation_coef; + uint16_t *src_pixels = (uint16_t *)pict->data[0]; + uint16_t *prev_pixels = (uint16_t *)s->prev_frame->data[0]; + + /* Number of 4x4 blocks in frame. */ + total_blocks = ((s->frame_width + 3) / 4) * ((s->frame_height + 3) / 4); + + bi.image_width = s->frame_width; + bi.image_height = s->frame_height; + bi.rowstride = pict->linesize[0] / 2; + + bi.blocks_per_row = (s->frame_width + 3) / 4; + + while (block_counter < total_blocks) { + // SKIP CHECK + // make sure we have a valid previous frame and we're not writing + // a key frame + if (!s->first_frame) { + n_blocks = 0; + prev_block_offset = 0; + + while (n_blocks < 32 && block_counter + n_blocks < total_blocks) { + + block_offset = get_block_info(&bi, block_counter + n_blocks); + + // multi-block opcodes cannot span multiple rows. + // If we're starting a new row, break out and write the opcode + /* TODO: Should eventually use bi.row here to determine when a + row break occurs, but that is currently breaking the + quicktime player. This is probably due to a bug in the + way I'm calculating the current row. + */ + if (prev_block_offset && block_offset - prev_block_offset > 12) { + break; + } + + prev_block_offset = block_offset; + + if (compare_blocks(&prev_pixels[block_offset], + &src_pixels[block_offset], &bi, s->skip_frame_thresh) != 0) { + // write out skipable blocks + if (n_blocks) { + + // write skip opcode + put_bits(&s->pb, 8, 0x80 | (n_blocks - 1)); + block_counter += n_blocks; + + goto post_skip; + } + break; + } + + /* + * NOTE: we don't update skipped blocks in the previous frame buffer + * since skipped needs always to be compared against the first skipped + * block to avoid artifacts during gradual fade in/outs. + */ + + // update_block_in_prev_frame(&src_pixels[block_offset], + // &prev_pixels[block_offset], &bi, block_counter + n_blocks); + + n_blocks++; + } + + // we're either at the end of the frame or we've reached the maximum + // of 32 blocks in a run. Write out the run. + if (n_blocks) { + // write skip opcode + put_bits(&s->pb, 8, 0x80 | (n_blocks - 1)); + block_counter += n_blocks; + + continue; + } + + } else { + block_offset = get_block_info(&bi, block_counter); + } +post_skip : + + // ONE COLOR CHECK + if (update_block_stats(s, &bi, &src_pixels[block_offset], + min_color, max_color, + total_rgb, &pixel_count, avg_color, 1)) { + prev_block_offset = block_offset; + + n_blocks = 1; + + /* update this block in the previous frame buffer */ + update_block_in_prev_frame(&src_pixels[block_offset], + &prev_pixels[block_offset], &bi, block_counter + n_blocks); + + // check for subsequent blocks with the same color + while (n_blocks < 32 && block_counter + n_blocks < total_blocks) { + block_offset = get_block_info(&bi, block_counter + n_blocks); + + // multi-block opcodes cannot span multiple rows. + // If we've hit end of a row, break out and write the opcode + if (block_offset - prev_block_offset > 12) { + break; + } + + if (!update_block_stats(s, &bi, &src_pixels[block_offset], + min_color, max_color, + total_rgb, &pixel_count, avg_color, 0)) { + break; + } + + prev_block_offset = block_offset; + + /* update this block in the previous frame buffer */ + update_block_in_prev_frame(&src_pixels[block_offset], + &prev_pixels[block_offset], &bi, block_counter + n_blocks); + + n_blocks++; + } + + // write one color opcode. + put_bits(&s->pb, 8, 0xa0 | (n_blocks - 1)); + // write color to encode. + put_bits(&s->pb, 16, rgb24_to_rgb555(avg_color)); + // skip past the blocks we've just encoded. + block_counter += n_blocks; + } else { // FOUR COLOR CHECK + int err = 0; + + // get max component diff for block + get_max_component_diff(&bi, &src_pixels[block_offset], &min, &max, &chan); + + min_color[0] = 0; + max_color[0] = 0; + min_color[1] = 0; + max_color[1] = 0; + min_color[2] = 0; + max_color[2] = 0; + + // run least squares against other two components + for (i = 0; i < 3; i++) { + if (i == chan) { + min_color[i] = min; + max_color[i] = max; + continue; + } + + slope = y_intercept = correlation_coef = 0; + + if (leastsquares(&src_pixels[block_offset], &bi, chan, i, + &slope, &y_intercept, &correlation_coef)) { + min_color[i] = GET_CHAN(src_pixels[block_offset], i); + max_color[i] = GET_CHAN(src_pixels[block_offset], i); + } else { + tmp_min = (int)(0.5 + min * slope + y_intercept); + tmp_max = (int)(0.5 + max * slope + y_intercept); + + av_assert0(tmp_min <= tmp_max); + // clamp min and max color values + tmp_min = av_clip_uint8(tmp_min); + tmp_max = av_clip_uint8(tmp_max); + + err = FFMAX(calc_lsq_max_fit_error(&src_pixels[block_offset], &bi, + min, max, tmp_min, tmp_max, chan, i), err); + + min_color[i] = tmp_min; + max_color[i] = tmp_max; + } + } + + if (err > s->sixteen_color_thresh) { // DO SIXTEEN COLOR BLOCK + uint16_t *row_ptr; + int rgb555; + + block_offset = get_block_info(&bi, block_counter); + + row_ptr = &src_pixels[block_offset]; + + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++){ + rgb555 = row_ptr[x] & ~0x8000; + + put_bits(&s->pb, 16, rgb555); + } + row_ptr += bi.rowstride; + } + + block_counter++; + } else { // FOUR COLOR BLOCK + block_counter += encode_four_color_block(min_color, max_color, + &s->pb, &src_pixels[block_offset], &bi); + } + + /* update this block in the previous frame buffer */ + update_block_in_prev_frame(&src_pixels[block_offset], + &prev_pixels[block_offset], &bi, block_counter); + } + } +} + +static int rpza_encode_init(AVCodecContext *avctx) +{ + RpzaContext *s = avctx->priv_data; + + s->frame_width = avctx->width; + s->frame_height = avctx->height; + + s->prev_frame = av_frame_alloc(); + if (!s->prev_frame) + return AVERROR(ENOMEM); + + return 0; +} + +static int rpza_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + RpzaContext *s = avctx->priv_data; + const AVFrame *pict = frame; + uint8_t *buf; + int ret; + + if ((ret = ff_alloc_packet2(avctx, pkt, 6LL * avctx->height * avctx->width, 0)) < 0) + return ret; + + init_put_bits(&s->pb, pkt->data, pkt->size); + + // skip 4 byte header, write it later once the size of the chunk is known + put_bits32(&s->pb, 0x00); + + if (!s->prev_frame->data[0]) { + s->first_frame = 1; + s->prev_frame->format = pict->format; + s->prev_frame->width = pict->width; + s->prev_frame->height = pict->height; + ret = av_frame_get_buffer(s->prev_frame, 0); + if (ret < 0) + return ret; + } else { + s->first_frame = 0; + } + + rpza_encode_stream(s, pict); + + flush_put_bits(&s->pb); + + av_shrink_packet(pkt, put_bits_count(&s->pb) >> 3); + buf = pkt->data; + + // write header opcode + buf[0] = 0xe1; // chunk opcode + + // write chunk length + AV_WB24(buf + 1, pkt->size); + + *got_packet = 1; + + return 0; +} + +static int rpza_encode_end(AVCodecContext *avctx) +{ + RpzaContext *s = (RpzaContext *)avctx->priv_data; + + av_frame_free(&s->prev_frame); + + return 0; +} + +#define OFFSET(x) offsetof(RpzaContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "skip_frame_thresh", NULL, OFFSET(skip_frame_thresh), AV_OPT_TYPE_INT, {.i64=1}, 0, 24, VE}, + { "start_one_color_thresh", NULL, OFFSET(start_one_color_thresh), AV_OPT_TYPE_INT, {.i64=1}, 0, 24, VE}, + { "continue_one_color_thresh", NULL, OFFSET(continue_one_color_thresh), AV_OPT_TYPE_INT, {.i64=0}, 0, 24, VE}, + { "sixteen_color_thresh", NULL, OFFSET(sixteen_color_thresh), AV_OPT_TYPE_INT, {.i64=1}, 0, 24, VE}, + { NULL }, +}; + +static const AVClass rpza_class = { + .class_name = "rpza", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_rpza_encoder = { + .name = "rpza", + .long_name = NULL_IF_CONFIG_SMALL("QuickTime video (RPZA)"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RPZA, + .priv_data_size = sizeof(RpzaContext), + .priv_class = &rpza_class, + .init = rpza_encode_init, + .encode2 = rpza_encode_frame, + .close = rpza_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB555, + AV_PIX_FMT_NONE}, +}; diff -Nru ffmpeg-4.2.2/libavcodec/rscc.c ffmpeg-4.4/libavcodec/rscc.c --- ffmpeg-4.2.2/libavcodec/rscc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rscc.c 2021-04-08 21:28:39.000000000 +0000 @@ -300,6 +300,10 @@ ret = AVERROR_INVALIDDATA; goto end; } + if (ctx->inflated_size < pixel_size) { + ret = AVERROR_INVALIDDATA; + goto end; + } ret = uncompress(ctx->inflated_buf, &len, gbc->buffer, packed_size); if (ret) { av_log(avctx, AV_LOG_ERROR, "Pixel deflate error %d.\n", ret); @@ -310,7 +314,7 @@ } /* Allocate when needed */ - ret = ff_reget_buffer(avctx, ctx->reference); + ret = ff_reget_buffer(avctx, ctx->reference, 0); if (ret < 0) goto end; @@ -342,7 +346,7 @@ /* Palette handling */ if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { - int size; + buffer_size_t size; const uint8_t *palette = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size); diff -Nru ffmpeg-4.2.2/libavcodec/rtjpeg.h ffmpeg-4.4/libavcodec/rtjpeg.h --- ffmpeg-4.2.2/libavcodec/rtjpeg.h 2016-03-29 02:25:21.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rtjpeg.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,7 +24,7 @@ #include -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "idctdsp.h" #define RTJPEG_FILE_VERSION 0 diff -Nru ffmpeg-4.2.2/libavcodec/rv10.c ffmpeg-4.4/libavcodec/rv10.c --- ffmpeg-4.2.2/libavcodec/rv10.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rv10.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,6 +28,7 @@ #include #include "libavutil/imgutils.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "error_resilience.h" @@ -45,7 +46,8 @@ #define RV_GET_MINOR_VER(x) (((x) >> 20) & 0xFF) #define RV_GET_MICRO_VER(x) (((x) >> 12) & 0xFF) -#define DC_VLC_BITS 14 // FIXME find a better solution +#define MAX_VLC_ENTRIES 1023 // Note: Does not include the skip entries. +#define DC_VLC_BITS 9 typedef struct RVDecContext { MpegEncContext m; @@ -53,144 +55,25 @@ int orig_width, orig_height; } RVDecContext; -static const uint16_t rv_lum_code[256] = { - 0x3e7f, 0x0f00, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05, 0x0f06, - 0x0f07, 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e, - 0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f13, 0x0f14, 0x0f15, 0x0f16, - 0x0f17, 0x0f18, 0x0f19, 0x0f1a, 0x0f1b, 0x0f1c, 0x0f1d, 0x0f1e, - 0x0f1f, 0x0f20, 0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26, - 0x0f27, 0x0f28, 0x0f29, 0x0f2a, 0x0f2b, 0x0f2c, 0x0f2d, 0x0f2e, - 0x0f2f, 0x0f30, 0x0f31, 0x0f32, 0x0f33, 0x0f34, 0x0f35, 0x0f36, - 0x0f37, 0x0f38, 0x0f39, 0x0f3a, 0x0f3b, 0x0f3c, 0x0f3d, 0x0f3e, - 0x0f3f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, - 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x038c, 0x038d, 0x038e, - 0x038f, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, - 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, - 0x039f, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, - 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, - 0x00cf, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, - 0x0057, 0x0020, 0x0021, 0x0022, 0x0023, 0x000c, 0x000d, 0x0004, - 0x0000, 0x0005, 0x000e, 0x000f, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, - 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, - 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, - 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, - 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, - 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, - 0x0f40, 0x0f41, 0x0f42, 0x0f43, 0x0f44, 0x0f45, 0x0f46, 0x0f47, - 0x0f48, 0x0f49, 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4d, 0x0f4e, 0x0f4f, - 0x0f50, 0x0f51, 0x0f52, 0x0f53, 0x0f54, 0x0f55, 0x0f56, 0x0f57, - 0x0f58, 0x0f59, 0x0f5a, 0x0f5b, 0x0f5c, 0x0f5d, 0x0f5e, 0x0f5f, - 0x0f60, 0x0f61, 0x0f62, 0x0f63, 0x0f64, 0x0f65, 0x0f66, 0x0f67, - 0x0f68, 0x0f69, 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6d, 0x0f6e, 0x0f6f, - 0x0f70, 0x0f71, 0x0f72, 0x0f73, 0x0f74, 0x0f75, 0x0f76, 0x0f77, - 0x0f78, 0x0f79, 0x0f7a, 0x0f7b, 0x0f7c, 0x0f7d, 0x0f7e, 0x0f7f, +/* (run, length) encoded value for the symbols table. The actual symbols + * are run..run - length (mod 256). + * The last two entries in the following table apply to luma only. + * The skip values are not included in this list. */ +static const uint8_t rv_sym_run_len[][2] = { + { 0, 0 }, { 1, 0 }, { 255, 0 }, { 3, 1 }, { 254, 1 }, + { 7, 3 }, { 252, 3 }, { 15, 7 }, { 248, 7 }, { 31, 15 }, + { 240, 15 }, { 63, 31 }, { 224, 31 }, { 127, 63 }, { 192, 63 }, + { 255, 127 }, { 128, 127 }, { 127, 255 }, { 128, 255 }, }; -static const uint8_t rv_lum_bits[256] = { - 14, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 7, 7, 7, 7, 7, 7, 7, - 7, 6, 6, 6, 6, 5, 5, 4, - 2, 4, 5, 5, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, +/* entry[i] of the following tables gives + * the number of VLC codes of length i + 2. */ +static const uint16_t rv_lum_len_count[15] = { + 1, 0, 2, 4, 8, 16, 32, 0, 64, 0, 128, 0, 256, 0, 512, }; -static const uint16_t rv_chrom_code[256] = { - 0xfe7f, 0x3f00, 0x3f01, 0x3f02, 0x3f03, 0x3f04, 0x3f05, 0x3f06, - 0x3f07, 0x3f08, 0x3f09, 0x3f0a, 0x3f0b, 0x3f0c, 0x3f0d, 0x3f0e, - 0x3f0f, 0x3f10, 0x3f11, 0x3f12, 0x3f13, 0x3f14, 0x3f15, 0x3f16, - 0x3f17, 0x3f18, 0x3f19, 0x3f1a, 0x3f1b, 0x3f1c, 0x3f1d, 0x3f1e, - 0x3f1f, 0x3f20, 0x3f21, 0x3f22, 0x3f23, 0x3f24, 0x3f25, 0x3f26, - 0x3f27, 0x3f28, 0x3f29, 0x3f2a, 0x3f2b, 0x3f2c, 0x3f2d, 0x3f2e, - 0x3f2f, 0x3f30, 0x3f31, 0x3f32, 0x3f33, 0x3f34, 0x3f35, 0x3f36, - 0x3f37, 0x3f38, 0x3f39, 0x3f3a, 0x3f3b, 0x3f3c, 0x3f3d, 0x3f3e, - 0x3f3f, 0x0f80, 0x0f81, 0x0f82, 0x0f83, 0x0f84, 0x0f85, 0x0f86, - 0x0f87, 0x0f88, 0x0f89, 0x0f8a, 0x0f8b, 0x0f8c, 0x0f8d, 0x0f8e, - 0x0f8f, 0x0f90, 0x0f91, 0x0f92, 0x0f93, 0x0f94, 0x0f95, 0x0f96, - 0x0f97, 0x0f98, 0x0f99, 0x0f9a, 0x0f9b, 0x0f9c, 0x0f9d, 0x0f9e, - 0x0f9f, 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, - 0x03c7, 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, - 0x03cf, 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, - 0x00e7, 0x0030, 0x0031, 0x0032, 0x0033, 0x0008, 0x0009, 0x0002, - 0x0000, 0x0003, 0x000a, 0x000b, 0x0034, 0x0035, 0x0036, 0x0037, - 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, - 0x03d0, 0x03d1, 0x03d2, 0x03d3, 0x03d4, 0x03d5, 0x03d6, 0x03d7, - 0x03d8, 0x03d9, 0x03da, 0x03db, 0x03dc, 0x03dd, 0x03de, 0x03df, - 0x0fa0, 0x0fa1, 0x0fa2, 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa6, 0x0fa7, - 0x0fa8, 0x0fa9, 0x0faa, 0x0fab, 0x0fac, 0x0fad, 0x0fae, 0x0faf, - 0x0fb0, 0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7, - 0x0fb8, 0x0fb9, 0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf, - 0x3f40, 0x3f41, 0x3f42, 0x3f43, 0x3f44, 0x3f45, 0x3f46, 0x3f47, - 0x3f48, 0x3f49, 0x3f4a, 0x3f4b, 0x3f4c, 0x3f4d, 0x3f4e, 0x3f4f, - 0x3f50, 0x3f51, 0x3f52, 0x3f53, 0x3f54, 0x3f55, 0x3f56, 0x3f57, - 0x3f58, 0x3f59, 0x3f5a, 0x3f5b, 0x3f5c, 0x3f5d, 0x3f5e, 0x3f5f, - 0x3f60, 0x3f61, 0x3f62, 0x3f63, 0x3f64, 0x3f65, 0x3f66, 0x3f67, - 0x3f68, 0x3f69, 0x3f6a, 0x3f6b, 0x3f6c, 0x3f6d, 0x3f6e, 0x3f6f, - 0x3f70, 0x3f71, 0x3f72, 0x3f73, 0x3f74, 0x3f75, 0x3f76, 0x3f77, - 0x3f78, 0x3f79, 0x3f7a, 0x3f7b, 0x3f7c, 0x3f7d, 0x3f7e, 0x3f7f, -}; - -static const uint8_t rv_chrom_bits[256] = { - 16, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 8, 8, 8, 8, 8, 8, 8, - 8, 6, 6, 6, 6, 4, 4, 3, - 2, 3, 4, 4, 6, 6, 6, 6, - 8, 8, 8, 8, 8, 8, 8, 8, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, +static const uint16_t rv_chrom_len_count[15] = { + 1, 2, 4, 0, 8, 0, 16, 0, 32, 0, 64, 0, 128, 0, 256, }; static VLC rv_dc_lum, rv_dc_chrom; @@ -201,48 +84,14 @@ if (n < 4) { code = get_vlc2(&s->gb, rv_dc_lum.table, DC_VLC_BITS, 2); - if (code < 0) { - /* XXX: I don't understand why they use LONGER codes than - * necessary. The following code would be completely useless - * if they had thought about it !!! */ - code = get_bits(&s->gb, 7); - if (code == 0x7c) { - code = (int8_t) (get_bits(&s->gb, 7) + 1); - } else if (code == 0x7d) { - code = -128 + get_bits(&s->gb, 7); - } else if (code == 0x7e) { - if (get_bits1(&s->gb) == 0) - code = (int8_t) (get_bits(&s->gb, 8) + 1); - else - code = (int8_t) (get_bits(&s->gb, 8)); - } else if (code == 0x7f) { - skip_bits(&s->gb, 11); - code = 1; - } - } else { - code -= 128; - } } else { code = get_vlc2(&s->gb, rv_dc_chrom.table, DC_VLC_BITS, 2); - /* same remark */ if (code < 0) { - code = get_bits(&s->gb, 9); - if (code == 0x1fc) { - code = (int8_t) (get_bits(&s->gb, 7) + 1); - } else if (code == 0x1fd) { - code = -128 + get_bits(&s->gb, 7); - } else if (code == 0x1fe) { - skip_bits(&s->gb, 9); - code = 1; - } else { - av_log(s->avctx, AV_LOG_ERROR, "chroma dc error\n"); - return 0xffff; - } - } else { - code -= 128; + av_log(s->avctx, AV_LOG_ERROR, "chroma dc error\n"); + return -1; } } - return -code; + return code; } /* read RV 1.0 compatible frame header */ @@ -377,7 +226,7 @@ new_w = rv->orig_width; new_h = rv->orig_height; } - if (new_w != s->width || new_h != s->height) { + if (new_w != s->width || new_h != s->height || !s->context_initialized) { AVRational old_aspect = s->avctx->sample_aspect_ratio; av_log(s->avctx, AV_LOG_DEBUG, "attempting to change resolution to %dx%d\n", new_w, new_h); @@ -463,11 +312,58 @@ return s->mb_width * s->mb_height - mb_pos; } +static av_cold void rv10_build_vlc(VLC *vlc, const uint16_t len_count[15], + const uint8_t sym_rl[][2], int sym_rl_elems) +{ + uint16_t syms[MAX_VLC_ENTRIES]; + uint8_t lens[MAX_VLC_ENTRIES]; + unsigned nb_syms = 0, nb_lens = 0; + + for (unsigned i = 0; i < sym_rl_elems; i++) { + unsigned cur_sym = sym_rl[i][0]; + for (unsigned tmp = nb_syms + sym_rl[i][1]; nb_syms <= tmp; nb_syms++) + syms[nb_syms] = 0xFF & cur_sym--; + } + + for (unsigned i = 0; i < 15; i++) + for (unsigned tmp = nb_lens + len_count[i]; nb_lens < tmp; nb_lens++) + lens[nb_lens] = i + 2; + av_assert1(nb_lens == nb_syms); + ff_init_vlc_from_lengths(vlc, DC_VLC_BITS, nb_lens, lens, 1, + syms, 2, 2, 0, INIT_VLC_STATIC_OVERLONG, NULL); +} + +static av_cold void rv10_init_static(void) +{ + static VLC_TYPE table[1472 + 992][2]; + + rv_dc_lum.table = table; + rv_dc_lum.table_allocated = 1472; + rv10_build_vlc(&rv_dc_lum, rv_lum_len_count, + rv_sym_run_len, FF_ARRAY_ELEMS(rv_sym_run_len)); + for (int i = 0; i < 1 << (DC_VLC_BITS - 7 /* Length of skip prefix */); i++) { + /* All codes beginning with 0x7F have the same length and value. + * Modifying the table directly saves us the useless subtables. */ + rv_dc_lum.table[(0x7F << (DC_VLC_BITS - 7)) + i][0] = 255; + rv_dc_lum.table[(0x7F << (DC_VLC_BITS - 7)) + i][1] = 18; + } + rv_dc_chrom.table = &table[1472]; + rv_dc_chrom.table_allocated = 992; + rv10_build_vlc(&rv_dc_chrom, rv_chrom_len_count, + rv_sym_run_len, FF_ARRAY_ELEMS(rv_sym_run_len) - 2); + for (int i = 0; i < 1 << (DC_VLC_BITS - 9 /* Length of skip prefix */); i++) { + /* Same as above. */ + rv_dc_chrom.table[(0x1FE << (DC_VLC_BITS - 9)) + i][0] = 255; + rv_dc_chrom.table[(0x1FE << (DC_VLC_BITS - 9)) + i][1] = 18; + } + ff_h263_decode_init_vlc(); +} + static av_cold int rv10_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; RVDecContext *rv = avctx->priv_data; MpegEncContext *s = &rv->m; - static int done = 0; int major_ver, minor_ver, micro_ver, ret; if (avctx->extradata_size < 8) { @@ -478,7 +374,6 @@ avctx->coded_height, 0, avctx)) < 0) return ret; - ff_mpv_decode_defaults(s); ff_mpv_decode_init(s, avctx); s->out_format = FMT_H263; @@ -525,18 +420,9 @@ return ret; ff_h263dsp_init(&s->h263dsp); - ff_h263_decode_init_vlc(); - /* init rv vlc */ - if (!done) { - INIT_VLC_STATIC(&rv_dc_lum, DC_VLC_BITS, 256, - rv_lum_bits, 1, 1, - rv_lum_code, 2, 2, 16384); - INIT_VLC_STATIC(&rv_dc_chrom, DC_VLC_BITS, 256, - rv_chrom_bits, 1, 1, - rv_chrom_code, 2, 2, 16388); - done = 1; - } + /* init static VLCs */ + ff_thread_once(&init_static_once, rv10_init_static); return 0; } @@ -550,7 +436,7 @@ } static int rv10_decode_packet(AVCodecContext *avctx, const uint8_t *buf, - int buf_size, int buf_size2) + int buf_size, int buf_size2, int whole_size) { RVDecContext *rv = avctx->priv_data; MpegEncContext *s = &rv->m; @@ -580,6 +466,9 @@ return AVERROR_INVALIDDATA; } + if (whole_size < s->mb_width * s->mb_height / 8) + return AVERROR_INVALIDDATA; + if ((s->mb_x == 0 && s->mb_y == 0) || !s->current_picture_ptr) { // FIXME write parser so we always have complete frames? if (s->current_picture_ptr) { @@ -754,7 +643,7 @@ offset + FFMAX(size, size2) > buf_size) return AVERROR_INVALIDDATA; - if ((ret = rv10_decode_packet(avctx, buf + offset, size, size2)) < 0) + if ((ret = rv10_decode_packet(avctx, buf + offset, size, size2, buf_size)) < 0) return ret; if (ret > 8 * size) diff -Nru ffmpeg-4.2.2/libavcodec/rv10enc.c ffmpeg-4.4/libavcodec/rv10enc.c --- ffmpeg-4.2.2/libavcodec/rv10enc.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rv10enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,7 +33,7 @@ { int full_frame= 0; - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); put_bits(&s->pb, 1, 1); /* marker */ @@ -79,6 +79,7 @@ .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &rv10_class, }; diff -Nru ffmpeg-4.2.2/libavcodec/rv20enc.c ffmpeg-4.4/libavcodec/rv20enc.c --- ffmpeg-4.2.2/libavcodec/rv20enc.c 2017-12-31 22:35:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rv20enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -76,6 +76,7 @@ .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .priv_class = &rv20_class, }; diff -Nru ffmpeg-4.2.2/libavcodec/rv30.c ffmpeg-4.4/libavcodec/rv30.c --- ffmpeg-4.2.2/libavcodec/rv30.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rv30.c 2020-07-11 10:39:30.000000000 +0000 @@ -304,6 +304,6 @@ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_update_thread_context), + .caps_internal = FF_CODEC_CAP_ALLOCATE_PROGRESS, }; diff -Nru ffmpeg-4.2.2/libavcodec/rv34.c ffmpeg-4.4/libavcodec/rv34.c --- ffmpeg-4.2.2/libavcodec/rv34.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rv34.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,8 +24,12 @@ * RV30/40 decoder common data */ +#include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" +#include "libavutil/thread.h" +#include "libavutil/video_enc_params.h" #include "avcodec.h" #include "error_resilience.h" @@ -75,27 +79,6 @@ * @{ */ -static const int table_offs[] = { - 0, 1818, 3622, 4144, 4698, 5234, 5804, 5868, 5900, 5932, - 5996, 6252, 6316, 6348, 6380, 7674, 8944, 10274, 11668, 12250, - 14060, 15846, 16372, 16962, 17512, 18148, 18180, 18212, 18244, 18308, - 18564, 18628, 18660, 18692, 20036, 21314, 22648, 23968, 24614, 26384, - 28190, 28736, 29366, 29938, 30608, 30640, 30672, 30704, 30768, 31024, - 31088, 31120, 31184, 32570, 33898, 35236, 36644, 37286, 39020, 40802, - 41368, 42052, 42692, 43348, 43380, 43412, 43444, 43476, 43604, 43668, - 43700, 43732, 45100, 46430, 47778, 49160, 49802, 51550, 53340, 53972, - 54648, 55348, 55994, 56122, 56154, 56186, 56218, 56346, 56410, 56442, - 56474, 57878, 59290, 60636, 62036, 62682, 64460, 64524, 64588, 64716, - 64844, 66076, 67466, 67978, 68542, 69064, 69648, 70296, 72010, 72074, - 72138, 72202, 72330, 73572, 74936, 75454, 76030, 76566, 77176, 77822, - 79582, 79646, 79678, 79742, 79870, 81180, 82536, 83064, 83672, 84242, - 84934, 85576, 87384, 87448, 87480, 87544, 87672, 88982, 90340, 90902, - 91598, 92182, 92846, 93488, 95246, 95278, 95310, 95374, 95502, 96878, - 98266, 98848, 99542, 100234, 100884, 101524, 103320, 103352, 103384, 103416, - 103480, 104874, 106222, 106910, 107584, 108258, 108902, 109544, 111366, 111398, - 111430, 111462, 111494, 112878, 114320, 114988, 115660, 116310, 116950, 117592 -}; - static VLC_TYPE table_data[117592][2]; /** @@ -106,37 +89,34 @@ * @param insyms symbols for input codes (NULL for default ones) * @param num VLC table number (for static initialization) */ -static void rv34_gen_vlc(const uint8_t *bits, int size, VLC *vlc, const uint8_t *insyms, - const int num) +static void rv34_gen_vlc(const uint8_t *bits, int size, VLC *vlc, const uint8_t *syms, + int *offset) { - int i; int counts[17] = {0}, codes[17]; - uint16_t cw[MAX_VLC_SIZE], syms[MAX_VLC_SIZE]; - uint8_t bits2[MAX_VLC_SIZE]; - int maxbits = 0, realsize = 0; - - for(i = 0; i < size; i++){ - if(bits[i]){ - bits2[realsize] = bits[i]; - syms[realsize] = insyms ? insyms[i] : i; - realsize++; - maxbits = FFMAX(maxbits, bits[i]); - counts[bits[i]]++; - } - } + uint16_t cw[MAX_VLC_SIZE]; + int maxbits; + + for (int i = 0; i < size; i++) + counts[bits[i]]++; - codes[0] = 0; - for(i = 0; i < 16; i++) + /* bits[0] is zero for some tables, i.e. syms actually starts at 1. + * So we reset it here. The code assigned to this element is 0x00. */ + codes[0] = counts[0] = 0; + for (int i = 0; i < 16; i++) { codes[i+1] = (codes[i] + counts[i]) << 1; - for(i = 0; i < realsize; i++) - cw[i] = codes[bits2[i]]++; + if (counts[i]) + maxbits = i; + } + for (int i = 0; i < size; i++) + cw[i] = codes[bits[i]]++; - vlc->table = &table_data[table_offs[num]]; - vlc->table_allocated = table_offs[num + 1] - table_offs[num]; - ff_init_vlc_sparse(vlc, FFMIN(maxbits, 9), realsize, - bits2, 1, 1, + vlc->table = &table_data[*offset]; + vlc->table_allocated = FF_ARRAY_ELEMS(table_data) - *offset; + ff_init_vlc_sparse(vlc, FFMIN(maxbits, 9), size, + bits, 1, 1, cw, 2, 2, - syms, 2, 2, INIT_VLC_USE_NEW_STATIC); + syms, !!syms, !!syms, INIT_VLC_STATIC_OVERLONG); + *offset += vlc->table_size; } /** @@ -144,34 +124,46 @@ */ static av_cold void rv34_init_tables(void) { - int i, j, k; + int i, j, k, offset = 0; for(i = 0; i < NUM_INTRA_TABLES; i++){ for(j = 0; j < 2; j++){ - rv34_gen_vlc(rv34_table_intra_cbppat [i][j], CBPPAT_VLC_SIZE, &intra_vlcs[i].cbppattern[j], NULL, 19*i + 0 + j); - rv34_gen_vlc(rv34_table_intra_secondpat[i][j], OTHERBLK_VLC_SIZE, &intra_vlcs[i].second_pattern[j], NULL, 19*i + 2 + j); - rv34_gen_vlc(rv34_table_intra_thirdpat [i][j], OTHERBLK_VLC_SIZE, &intra_vlcs[i].third_pattern[j], NULL, 19*i + 4 + j); + rv34_gen_vlc(rv34_table_intra_cbppat [i][j], CBPPAT_VLC_SIZE, + &intra_vlcs[i].cbppattern[j], NULL, &offset); + rv34_gen_vlc(rv34_table_intra_secondpat[i][j], OTHERBLK_VLC_SIZE, + &intra_vlcs[i].second_pattern[j], NULL, &offset); + rv34_gen_vlc(rv34_table_intra_thirdpat [i][j], OTHERBLK_VLC_SIZE, + &intra_vlcs[i].third_pattern[j], NULL, &offset); for(k = 0; k < 4; k++){ - rv34_gen_vlc(rv34_table_intra_cbp[i][j+k*2], CBP_VLC_SIZE, &intra_vlcs[i].cbp[j][k], rv34_cbp_code, 19*i + 6 + j*4 + k); + rv34_gen_vlc(rv34_table_intra_cbp[i][j+k*2], CBP_VLC_SIZE, + &intra_vlcs[i].cbp[j][k], rv34_cbp_code, &offset); } } for(j = 0; j < 4; j++){ - rv34_gen_vlc(rv34_table_intra_firstpat[i][j], FIRSTBLK_VLC_SIZE, &intra_vlcs[i].first_pattern[j], NULL, 19*i + 14 + j); + rv34_gen_vlc(rv34_table_intra_firstpat[i][j], FIRSTBLK_VLC_SIZE, + &intra_vlcs[i].first_pattern[j], NULL, &offset); } - rv34_gen_vlc(rv34_intra_coeff[i], COEFF_VLC_SIZE, &intra_vlcs[i].coefficient, NULL, 19*i + 18); + rv34_gen_vlc(rv34_intra_coeff[i], COEFF_VLC_SIZE, + &intra_vlcs[i].coefficient, NULL, &offset); } for(i = 0; i < NUM_INTER_TABLES; i++){ - rv34_gen_vlc(rv34_inter_cbppat[i], CBPPAT_VLC_SIZE, &inter_vlcs[i].cbppattern[0], NULL, i*12 + 95); + rv34_gen_vlc(rv34_inter_cbppat[i], CBPPAT_VLC_SIZE, + &inter_vlcs[i].cbppattern[0], NULL, &offset); for(j = 0; j < 4; j++){ - rv34_gen_vlc(rv34_inter_cbp[i][j], CBP_VLC_SIZE, &inter_vlcs[i].cbp[0][j], rv34_cbp_code, i*12 + 96 + j); + rv34_gen_vlc(rv34_inter_cbp[i][j], CBP_VLC_SIZE, + &inter_vlcs[i].cbp[0][j], rv34_cbp_code, &offset); } for(j = 0; j < 2; j++){ - rv34_gen_vlc(rv34_table_inter_firstpat [i][j], FIRSTBLK_VLC_SIZE, &inter_vlcs[i].first_pattern[j], NULL, i*12 + 100 + j); - rv34_gen_vlc(rv34_table_inter_secondpat[i][j], OTHERBLK_VLC_SIZE, &inter_vlcs[i].second_pattern[j], NULL, i*12 + 102 + j); - rv34_gen_vlc(rv34_table_inter_thirdpat [i][j], OTHERBLK_VLC_SIZE, &inter_vlcs[i].third_pattern[j], NULL, i*12 + 104 + j); + rv34_gen_vlc(rv34_table_inter_firstpat [i][j], FIRSTBLK_VLC_SIZE, + &inter_vlcs[i].first_pattern[j], NULL, &offset); + rv34_gen_vlc(rv34_table_inter_secondpat[i][j], OTHERBLK_VLC_SIZE, + &inter_vlcs[i].second_pattern[j], NULL, &offset); + rv34_gen_vlc(rv34_table_inter_thirdpat [i][j], OTHERBLK_VLC_SIZE, + &inter_vlcs[i].third_pattern[j], NULL, &offset); } - rv34_gen_vlc(rv34_inter_coeff[i], COEFF_VLC_SIZE, &inter_vlcs[i].coefficient, NULL, i*12 + 106); + rv34_gen_vlc(rv34_inter_coeff[i], COEFF_VLC_SIZE, + &inter_vlcs[i].coefficient, NULL, &offset); } } @@ -343,8 +335,9 @@ { if(mod == 2 && quant < 19) quant += 10; else if(mod && quant < 26) quant += 5; - return type ? &inter_vlcs[rv34_quant_to_vlc_set[1][av_clip(quant, 0, 30)]] - : &intra_vlcs[rv34_quant_to_vlc_set[0][av_clip(quant, 0, 30)]]; + av_assert2(quant >= 0 && quant < 32); + return type ? &inter_vlcs[rv34_quant_to_vlc_set[1][quant]] + : &intra_vlcs[rv34_quant_to_vlc_set[0][quant]]; } /** @@ -1390,6 +1383,7 @@ if (!(r->cbp_chroma && r->cbp_luma && r->deblock_coefs && r->intra_types_hist && r->mb_type)) { + r->s.context_reinit = 1; rv34_decoder_free(r); return AVERROR(ENOMEM); } @@ -1491,11 +1485,11 @@ */ av_cold int ff_rv34_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; RV34DecContext *r = avctx->priv_data; MpegEncContext *s = &r->s; int ret; - ff_mpv_decode_defaults(s); ff_mpv_decode_init(s, avctx); s->out_format = FMT_H263; @@ -1523,38 +1517,7 @@ return ret; } - if(!intra_vlcs[0].cbppattern[0].bits) - rv34_init_tables(); - - avctx->internal->allocate_progress = 1; - - return 0; -} - -int ff_rv34_decode_init_thread_copy(AVCodecContext *avctx) -{ - int err; - RV34DecContext *r = avctx->priv_data; - - r->s.avctx = avctx; - - if (avctx->internal->is_copy) { - r->tmp_b_block_base = NULL; - r->cbp_chroma = NULL; - r->cbp_luma = NULL; - r->deblock_coefs = NULL; - r->intra_types_hist = NULL; - r->mb_type = NULL; - - ff_mpv_idct_init(&r->s); - - if ((err = ff_mpv_common_init(&r->s)) < 0) - return err; - if ((err = rv34_decoder_alloc(r)) < 0) { - ff_mpv_common_end(&r->s); - return err; - } - } + ff_thread_once(&init_static_once, rv34_init_tables); return 0; } @@ -1568,7 +1531,7 @@ if (dst == src || !s1->context_initialized) return 0; - if (s->height != s1->height || s->width != s1->width) { + if (s->height != s1->height || s->width != s1->width || s->context_reinit) { s->height = s1->height; s->width = s1->width; if ((err = ff_mpv_common_frame_size_change(s)) < 0) @@ -1705,11 +1668,12 @@ if (s->mb_num_left > 0 && s->current_picture_ptr) { av_log(avctx, AV_LOG_ERROR, "New frame but still %d MB left.\n", s->mb_num_left); - ff_er_frame_end(&s->er); + if (!s->context_reinit) + ff_er_frame_end(&s->er); ff_mpv_frame_end(s); } - if (s->width != si.width || s->height != si.height) { + if (s->width != si.width || s->height != si.height || s->context_reinit) { int err; av_log(s->avctx, AV_LOG_WARNING, "Changing dimensions to %dx%d\n", @@ -1727,7 +1691,6 @@ err = ff_set_dimensions(s->avctx, s->width, s->height); if (err < 0) return err; - if ((err = ff_mpv_common_frame_size_change(s)) < 0) return err; if ((err = rv34_decoder_realloc(r)) < 0) @@ -1782,6 +1745,10 @@ } s->mb_x = s->mb_y = 0; ff_thread_finish_setup(s->avctx); + } else if (s->context_reinit) { + av_log(s->avctx, AV_LOG_ERROR, "Decoder needs full frames to " + "reinitialize (start MB is %d).\n", si.start); + return AVERROR_INVALIDDATA; } else if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME)) { av_log(s->avctx, AV_LOG_ERROR, "Decoder needs full frames in frame " diff -Nru ffmpeg-4.2.2/libavcodec/rv34data.h ffmpeg-4.4/libavcodec/rv34data.h --- ffmpeg-4.2.2/libavcodec/rv34data.h 2016-03-29 02:25:21.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rv34data.h 2021-04-08 21:28:39.000000000 +0000 @@ -90,26 +90,13 @@ /** * tables used to translate a quantizer value into a VLC set for decoding - * The first table is used for intraframes. + * The first table is used for intraframes. The two last entries are invalid. */ -static const uint8_t rv34_quant_to_vlc_set[2][31] = { +static const uint8_t rv34_quant_to_vlc_set[2][32] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 0 }, + 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, - 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6 }, -}; - -/** - * table for obtaining the quantizer difference - * @todo Use with ff_modified_quant_tab from h263data.h. - */ -static const uint8_t rv34_dquant_tab[2][32]={ -// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 -{ - 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9,10,11,12,13,14,15,16,17,18,18,19,20,21,22,23,24,25,26,27,28 -},{ - 0, 2, 3, 4, 5, 6, 7, 8, 9,10,11,13,14,15,16,17,18,19,20,21,22,24,25,26,27,28,29,30,31,31,31,26 -} + 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6 }, }; /** diff -Nru ffmpeg-4.2.2/libavcodec/rv34.h ffmpeg-4.4/libavcodec/rv34.h --- ffmpeg-4.2.2/libavcodec/rv34.h 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rv34.h 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,8 @@ #ifndef AVCODEC_RV34_H #define AVCODEC_RV34_H +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "mpegvideo.h" @@ -136,7 +138,6 @@ int ff_rv34_decode_init(AVCodecContext *avctx); int ff_rv34_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt); int ff_rv34_decode_end(AVCodecContext *avctx); -int ff_rv34_decode_init_thread_copy(AVCodecContext *avctx); int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src); #endif /* AVCODEC_RV34_H */ diff -Nru ffmpeg-4.2.2/libavcodec/rv40.c ffmpeg-4.4/libavcodec/rv40.c --- ffmpeg-4.2.2/libavcodec/rv40.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rv40.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,8 @@ * RV40 decoder */ +#include "config.h" + #include "libavutil/imgutils.h" #include "avcodec.h" @@ -39,59 +41,61 @@ static VLC aic_mode1_vlc[AIC_MODE1_NUM], aic_mode2_vlc[AIC_MODE2_NUM]; static VLC ptype_vlc[NUM_PTYPE_VLCS], btype_vlc[NUM_BTYPE_VLCS]; -static const int16_t mode2_offs[] = { - 0, 614, 1222, 1794, 2410, 3014, 3586, 4202, 4792, 5382, 5966, 6542, - 7138, 7716, 8292, 8864, 9444, 10030, 10642, 11212, 11814 -}; +static av_cold void rv40_init_table(VLC *vlc, unsigned *offset, int nb_bits, + int nb_codes, const uint8_t (*tab)[2]) +{ + static VLC_TYPE vlc_buf[11776][2]; + + vlc->table = &vlc_buf[*offset]; + vlc->table_allocated = 1 << nb_bits; + *offset += 1 << nb_bits; + + ff_init_vlc_from_lengths(vlc, nb_bits, nb_codes, + &tab[0][1], 2, &tab[0][0], 2, 1, + 0, INIT_VLC_USE_NEW_STATIC, NULL); +} /** * Initialize all tables. */ static av_cold void rv40_init_tables(void) { - int i; - static VLC_TYPE aic_table[1 << AIC_TOP_BITS][2]; - static VLC_TYPE aic_mode1_table[AIC_MODE1_NUM << AIC_MODE1_BITS][2]; + int i, offset = 0; static VLC_TYPE aic_mode2_table[11814][2]; - static VLC_TYPE ptype_table[NUM_PTYPE_VLCS << PTYPE_VLC_BITS][2]; - static VLC_TYPE btype_table[NUM_BTYPE_VLCS << BTYPE_VLC_BITS][2]; - aic_top_vlc.table = aic_table; - aic_top_vlc.table_allocated = 1 << AIC_TOP_BITS; - init_vlc(&aic_top_vlc, AIC_TOP_BITS, AIC_TOP_SIZE, - rv40_aic_top_vlc_bits, 1, 1, - rv40_aic_top_vlc_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); + rv40_init_table(&aic_top_vlc, &offset, AIC_TOP_BITS, AIC_TOP_SIZE, + rv40_aic_top_vlc_tab); for(i = 0; i < AIC_MODE1_NUM; i++){ // Every tenth VLC table is empty if((i % 10) == 9) continue; - aic_mode1_vlc[i].table = &aic_mode1_table[i << AIC_MODE1_BITS]; - aic_mode1_vlc[i].table_allocated = 1 << AIC_MODE1_BITS; - init_vlc(&aic_mode1_vlc[i], AIC_MODE1_BITS, AIC_MODE1_SIZE, - aic_mode1_vlc_bits[i], 1, 1, - aic_mode1_vlc_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - } - for(i = 0; i < AIC_MODE2_NUM; i++){ - aic_mode2_vlc[i].table = &aic_mode2_table[mode2_offs[i]]; - aic_mode2_vlc[i].table_allocated = mode2_offs[i + 1] - mode2_offs[i]; - init_vlc(&aic_mode2_vlc[i], AIC_MODE2_BITS, AIC_MODE2_SIZE, - aic_mode2_vlc_bits[i], 1, 1, - aic_mode2_vlc_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + rv40_init_table(&aic_mode1_vlc[i], &offset, AIC_MODE1_BITS, + AIC_MODE1_SIZE, aic_mode1_vlc_tabs[i]); + } + for (unsigned i = 0, offset = 0; i < AIC_MODE2_NUM; i++){ + uint16_t syms[AIC_MODE2_SIZE]; + + for (int j = 0; j < AIC_MODE2_SIZE; j++) { + int first = aic_mode2_vlc_syms[i][j] >> 4; + int second = aic_mode2_vlc_syms[i][j] & 0xF; + if (HAVE_BIGENDIAN) + syms[j] = (first << 8) | second; + else + syms[j] = first | (second << 8); + } + aic_mode2_vlc[i].table = &aic_mode2_table[offset]; + aic_mode2_vlc[i].table_allocated = FF_ARRAY_ELEMS(aic_mode2_table) - offset; + ff_init_vlc_from_lengths(&aic_mode2_vlc[i], AIC_MODE2_BITS, AIC_MODE2_SIZE, + aic_mode2_vlc_bits[i], 1, + syms, 2, 2, 0, INIT_VLC_STATIC_OVERLONG, NULL); + offset += aic_mode2_vlc[i].table_size; } for(i = 0; i < NUM_PTYPE_VLCS; i++){ - ptype_vlc[i].table = &ptype_table[i << PTYPE_VLC_BITS]; - ptype_vlc[i].table_allocated = 1 << PTYPE_VLC_BITS; - ff_init_vlc_sparse(&ptype_vlc[i], PTYPE_VLC_BITS, PTYPE_VLC_SIZE, - ptype_vlc_bits[i], 1, 1, - ptype_vlc_codes[i], 1, 1, - ptype_vlc_syms, 1, 1, INIT_VLC_USE_NEW_STATIC); + rv40_init_table(&ptype_vlc[i], &offset, PTYPE_VLC_BITS, PTYPE_VLC_SIZE, + ptype_vlc_tabs[i]); } for(i = 0; i < NUM_BTYPE_VLCS; i++){ - btype_vlc[i].table = &btype_table[i << BTYPE_VLC_BITS]; - btype_vlc[i].table_allocated = 1 << BTYPE_VLC_BITS; - ff_init_vlc_sparse(&btype_vlc[i], BTYPE_VLC_BITS, BTYPE_VLC_SIZE, - btype_vlc_bits[i], 1, 1, - btype_vlc_codes[i], 1, 1, - btype_vlc_syms, 1, 1, INIT_VLC_USE_NEW_STATIC); + rv40_init_table(&btype_vlc[i], &offset, BTYPE_VLC_BITS, BTYPE_VLC_SIZE, + btype_vlc_tabs[i]); } } @@ -194,9 +198,8 @@ if(pattern == rv40_aic_table_index[k]) break; if(j < 3 && k < MODE2_PATTERNS_NUM){ //pattern is found, decoding 2 coefficients - v = get_vlc2(gb, aic_mode2_vlc[k].table, AIC_MODE2_BITS, 2); - *ptr++ = v/9; - *ptr++ = v%9; + AV_WN16(ptr, get_vlc2(gb, aic_mode2_vlc[k].table, AIC_MODE2_BITS, 2)); + ptr += 2; j++; }else{ if(B != -1 && C != -1) @@ -583,6 +586,6 @@ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_update_thread_context), + .caps_internal = FF_CODEC_CAP_ALLOCATE_PROGRESS, }; diff -Nru ffmpeg-4.2.2/libavcodec/rv40dsp.c ffmpeg-4.4/libavcodec/rv40dsp.c --- ffmpeg-4.2.2/libavcodec/rv40dsp.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rv40dsp.c 2020-07-09 09:17:46.000000000 +0000 @@ -385,7 +385,7 @@ \ for (j = 0; j < size; j++) {\ for (i = 0; i < size; i++)\ - dst[i] = (((w2 * src1[i]) >> 9) + ((w1 * src2[i]) >> 9) + 0x10) >> 5;\ + dst[i] = ((((unsigned)w2 * src1[i]) >> 9) + (((unsigned)w1 * src2[i]) >> 9) + 0x10) >> 5;\ src1 += stride;\ src2 += stride;\ dst += stride;\ @@ -397,7 +397,7 @@ \ for (j = 0; j < size; j++) {\ for (i = 0; i < size; i++)\ - dst[i] = (w2 * src1[i] + w1 * src2[i] + 0x10) >> 5;\ + dst[i] = ((unsigned)w2 * src1[i] + (unsigned)w1 * src2[i] + 0x10) >> 5;\ src1 += stride;\ src2 += stride;\ dst += stride;\ diff -Nru ffmpeg-4.2.2/libavcodec/rv40vlc2.h ffmpeg-4.4/libavcodec/rv40vlc2.h --- ffmpeg-4.2.2/libavcodec/rv40vlc2.h 2016-03-29 02:25:21.000000000 +0000 +++ ffmpeg-4.4/libavcodec/rv40vlc2.h 2021-04-08 21:28:39.000000000 +0000 @@ -33,15 +33,12 @@ * codes used for the first four block types */ //@{ -#define AIC_TOP_BITS 8 +#define AIC_TOP_BITS 7 #define AIC_TOP_SIZE 16 -static const uint8_t rv40_aic_top_vlc_codes[AIC_TOP_SIZE] = { - 0x01, 0x05, 0x01, 0x00, 0x03, 0x3D, 0x1D, 0x02, - 0x04, 0x3C, 0x3F, 0x1C, 0x0D, 0x3E, 0x0C, 0x01 -}; - -static const uint8_t rv40_aic_top_vlc_bits[AIC_TOP_SIZE] = { - 1, 4, 5, 5, 5, 7, 6, 5, 4, 7, 7, 6, 5, 7, 5, 3 +static const uint8_t rv40_aic_top_vlc_tab[AIC_TOP_SIZE][2] = { + { 0x3, 5 }, { 0x2, 5 }, { 0x7, 5 }, { 0x4, 5 }, { 0xF, 3 }, { 0x8, 4 }, + { 0x1, 4 }, { 0xE, 5 }, { 0xC, 5 }, { 0xB, 6 }, { 0x6, 6 }, { 0x9, 7 }, + { 0x5, 7 }, { 0xD, 7 }, { 0xA, 7 }, { 0x0, 1 }, }; //@} @@ -53,370 +50,330 @@ #define AIC_MODE2_SIZE 81 #define AIC_MODE2_BITS 9 -static const uint16_t aic_mode2_vlc_codes[AIC_MODE2_NUM][AIC_MODE2_SIZE] = { -{ 0x0001, 0x0001, 0x0005, 0x01F5, 0x0011, 0x0049, 0x0000, 0x0048, 0x004B, - 0x0035, 0x0003, 0x0034, 0x03C9, 0x01F4, 0x00C9, 0x004A, 0x0FD9, 0x03C8, - 0x0010, 0x0037, 0x0001, 0x00C8, 0x0075, 0x01F7, 0x00CB, 0x0074, 0x0002, - 0x01F6, 0x00CA, 0x01F1, 0x01F0, 0x1F81, 0x07F9, 0x1F80, 0x1F83, 0x07F8, - 0x0077, 0x00F5, 0x0036, 0x07FB, 0x0076, 0x1F82, 0x00F4, 0x00F7, 0x07FA, - 0x0071, 0x00F6, 0x03CB, 0x03CA, 0x0FD8, 0x00F1, 0x03F5, 0x1F8D, 0x07E5, - 0x0013, 0x0031, 0x00F0, 0x0FDB, 0x00F3, 0x07E4, 0x0030, 0x01F3, 0x07E7, - 0x03F4, 0x07E6, 0x0070, 0x3F19, 0x01F2, 0x3F18, 0x0FDA, 0x0033, 0x07E1, - 0x01FD, 0x01FC, 0x0073, 0x01FF, 0x0FC5, 0x0FC4, 0x0FC7, 0x03F7, 0x0072, }, -{ 0x0005, 0x0005, 0x0005, 0x0079, 0x0005, 0x000D, 0x001D, 0x0078, 0x0069, - 0x0004, 0x0001, 0x0007, 0x0068, 0x001C, 0x001F, 0x0004, 0x006B, 0x000C, - 0x0004, 0x001E, 0x0006, 0x006A, 0x0015, 0x000F, 0x0014, 0x0017, 0x0007, - 0x0016, 0x000E, 0x0011, 0x0009, 0x00D1, 0x00D0, 0x0181, 0x00D3, 0x007B, - 0x0010, 0x0013, 0x0004, 0x00D2, 0x0007, 0x0319, 0x0008, 0x007A, 0x00DD, - 0x0019, 0x0006, 0x000B, 0x0065, 0x00DC, 0x0012, 0x0064, 0x0180, 0x00DF, - 0x0006, 0x0018, 0x0001, 0x00DE, 0x001D, 0x00D9, 0x001B, 0x0067, 0x000A, - 0x00D8, 0x00DB, 0x001C, 0x0318, 0x00DA, 0x0635, 0x0183, 0x0000, 0x00C5, - 0x0066, 0x0061, 0x0035, 0x00C4, 0x0182, 0x0634, 0x031B, 0x00C7, 0x001F, }, -{ 0x0005, 0x0001, 0x001D, 0x01C1, 0x0035, 0x00F1, 0x006D, 0x00F0, 0x0049, - 0x0000, 0x0004, 0x0003, 0x00F3, 0x0048, 0x0034, 0x006C, 0x01C0, 0x01C3, - 0x0007, 0x0006, 0x0001, 0x006F, 0x0002, 0x004B, 0x006E, 0x001C, 0x0005, - 0x0069, 0x0068, 0x006B, 0x0037, 0x01C2, 0x00F2, 0x0395, 0x01CD, 0x00FD, - 0x006A, 0x0036, 0x0015, 0x01CC, 0x0014, 0x0394, 0x004A, 0x00FC, 0x00FF, - 0x0017, 0x0031, 0x00FE, 0x01CF, 0x0397, 0x00F9, 0x01CE, 0x0725, 0x0396, - 0x0016, 0x0030, 0x0075, 0x0724, 0x00F8, 0x0727, 0x0033, 0x0391, 0x0390, - 0x0011, 0x0032, 0x001F, 0x00FB, 0x0074, 0x0726, 0x00FA, 0x001E, 0x0077, - 0x0019, 0x0018, 0x0004, 0x0010, 0x003D, 0x0076, 0x0071, 0x0013, 0x0001, }, -{ 0x000D, 0x0019, 0x0011, 0x0015, 0x0061, 0x0019, 0x0014, 0x01AD, 0x0060, - 0x0018, 0x0001, 0x0005, 0x001B, 0x0010, 0x0019, 0x0005, 0x0017, 0x0018, - 0x0016, 0x0004, 0x0004, 0x0013, 0x000C, 0x0012, 0x001A, 0x0018, 0x0005, - 0x000F, 0x001B, 0x0004, 0x001D, 0x0011, 0x001C, 0x0010, 0x000E, 0x001B, - 0x0013, 0x001F, 0x001A, 0x0029, 0x0005, 0x0063, 0x001E, 0x0009, 0x0062, - 0x0008, 0x0007, 0x0007, 0x0019, 0x0004, 0x001A, 0x0018, 0x006D, 0x0007, - 0x001B, 0x0007, 0x001A, 0x006C, 0x0006, 0x0012, 0x0005, 0x006F, 0x000B, - 0x006E, 0x0069, 0x001D, 0x0359, 0x0028, 0x002B, 0x002A, 0x001C, 0x00D5, - 0x0358, 0x001F, 0x0001, 0x001E, 0x0068, 0x00D4, 0x00D7, 0x0019, 0x0000, }, -{ 0x00B9, 0x0061, 0x0060, 0x00B8, 0x02B5, 0x01AD, 0x00BB, 0x0AF5, 0x0151, - 0x0001, 0x0001, 0x0005, 0x0000, 0x0003, 0x0005, 0x0004, 0x0063, 0x0025, - 0x00BA, 0x0004, 0x0007, 0x0062, 0x00A5, 0x0024, 0x006D, 0x0002, 0x006C, - 0x02B4, 0x000D, 0x006F, 0x0027, 0x00A4, 0x0026, 0x01AC, 0x0150, 0x01AF, - 0x01AE, 0x0021, 0x006E, 0x02B7, 0x0020, 0x0153, 0x0023, 0x00A7, 0x0152, - 0x00A6, 0x0006, 0x000C, 0x0022, 0x01A9, 0x0019, 0x002D, 0x02B6, 0x01A8, - 0x000F, 0x0007, 0x000E, 0x00A1, 0x0069, 0x002C, 0x0001, 0x01AB, 0x00A0, - 0x02B1, 0x00A3, 0x002F, 0x0AF4, 0x02B0, 0x0AF7, 0x02B3, 0x0068, 0x015D, - 0x0AF6, 0x01AA, 0x0055, 0x015C, 0x02B2, 0x0579, 0x0578, 0x015F, 0x00A2, }, -{ 0x0905, 0x013D, 0x013C, 0x0904, 0x121D, 0x049D, 0x049C, 0x243D, 0x0907, - 0x00ED, 0x0001, 0x0015, 0x0041, 0x013F, 0x0031, 0x0014, 0x025D, 0x025C, - 0x013E, 0x000D, 0x0000, 0x0040, 0x0139, 0x0043, 0x0030, 0x0017, 0x0033, - 0x0906, 0x0032, 0x0042, 0x00EC, 0x025F, 0x00EF, 0x025E, 0x049F, 0x0138, - 0x0901, 0x013B, 0x0259, 0x121C, 0x049E, 0x0900, 0x0258, 0x243C, 0x121F, - 0x0903, 0x003D, 0x00EE, 0x025B, 0x025A, 0x004D, 0x013A, 0x0902, 0x0245, - 0x00E9, 0x0016, 0x00E8, 0x0499, 0x0125, 0x0244, 0x004C, 0x0498, 0x090D, - 0x00EB, 0x003C, 0x0011, 0x049B, 0x049A, 0x0485, 0x00EA, 0x003F, 0x0124, - 0x090C, 0x003E, 0x0039, 0x0095, 0x0247, 0x0246, 0x0484, 0x0094, 0x0038, }, -{ 0x0F09, 0x00CD, 0x01FD, 0x0791, 0x1E6D, 0x0790, 0x03D9, 0x3CD1, 0x3CD0, - 0x0075, 0x0001, 0x0001, 0x0035, 0x00CC, 0x0011, 0x0000, 0x03D8, 0x01FC, - 0x03DB, 0x0010, 0x0003, 0x00CF, 0x03DA, 0x00CE, 0x0074, 0x0034, 0x0077, - 0x0793, 0x0013, 0x0076, 0x0071, 0x03C5, 0x0070, 0x01FF, 0x0792, 0x01FE, - 0x01F9, 0x0037, 0x00C9, 0x0F08, 0x01F8, 0x03C4, 0x00C8, 0x0F0B, 0x079D, - 0x03C7, 0x0001, 0x0012, 0x0073, 0x00CB, 0x0005, 0x0036, 0x03C6, 0x0072, - 0x007D, 0x0002, 0x00CA, 0x079C, 0x01FB, 0x00F5, 0x0031, 0x079F, 0x0F0A, - 0x0F35, 0x079E, 0x01FA, 0x1E6C, 0x1E6F, 0x3CD3, 0x0799, 0x03C1, 0x1E6E, - 0x3CD2, 0x0030, 0x00F4, 0x007C, 0x03C0, 0x03C3, 0x0798, 0x01E5, 0x00F7, }, -{ 0x01A5, 0x0001, 0x001D, 0x0021, 0x00A1, 0x000D, 0x0061, 0x06B9, 0x00A0, - 0x0060, 0x0001, 0x0005, 0x000C, 0x0020, 0x001C, 0x0004, 0x01A4, 0x01A7, - 0x00A3, 0x001F, 0x001E, 0x0023, 0x0022, 0x002D, 0x002C, 0x0063, 0x0062, - 0x1A81, 0x01A6, 0x01A1, 0x06B8, 0x06BB, 0x00A2, 0x06BA, 0x0D59, 0x06A5, - 0x01A0, 0x000F, 0x006D, 0x06A4, 0x002F, 0x00AD, 0x006C, 0x06A7, 0x00AC, - 0x0D58, 0x000E, 0x01A3, 0x00AF, 0x00AE, 0x006F, 0x01A2, 0x0D5B, 0x00A9, - 0x0019, 0x0001, 0x0009, 0x00A8, 0x006E, 0x002E, 0x0000, 0x01AD, 0x00AB, - 0x00AA, 0x0355, 0x0029, 0x1A80, 0x1A83, 0x1A82, 0x0354, 0x01AC, 0x0D5A, - 0x1A8D, 0x01AF, 0x0357, 0x0D45, 0x0D44, 0x0D47, 0x1A8C, 0x06A6, 0x06A1, }, -{ 0x0001, 0x0011, 0x0005, 0x0775, 0x00F9, 0x00F8, 0x0031, 0x0030, 0x0049, - 0x00FB, 0x0010, 0x0033, 0x0EC9, 0x038D, 0x038C, 0x00FA, 0x038F, 0x0774, - 0x0048, 0x0032, 0x0000, 0x01D5, 0x00E5, 0x038E, 0x00E4, 0x0013, 0x000D, - 0x0389, 0x0777, 0x0388, 0x038B, 0x1DF9, 0x0EC8, 0x3BC9, 0x1DF8, 0x038A, - 0x03B5, 0x0776, 0x00E7, 0x3BC8, 0x01D4, 0x3BCB, 0x0ECB, 0x0771, 0x0ECA, - 0x01D7, 0x03B4, 0x01D6, 0x1DFB, 0x0EF5, 0x0770, 0x0EF4, 0x3BCA, 0x0773, - 0x00E6, 0x03B7, 0x004B, 0x1DFA, 0x03B6, 0x0EF7, 0x00E1, 0x0EF6, 0x0EF1, - 0x03B1, 0x01D1, 0x003D, 0x0EF0, 0x0772, 0x077D, 0x077C, 0x003C, 0x01D0, - 0x03B0, 0x01D3, 0x003F, 0x03B3, 0x01D2, 0x0EF3, 0x077F, 0x00E0, 0x004A, }, -{ 0x0015, 0x0049, 0x0014, 0x07D1, 0x03FD, 0x03FC, 0x01C1, 0x01C0, 0x00F1, - 0x0017, 0x0001, 0x0001, 0x01C3, 0x0048, 0x004B, 0x0016, 0x0031, 0x01C2, - 0x004A, 0x0011, 0x0000, 0x01CD, 0x00F0, 0x01CC, 0x0075, 0x0010, 0x000D, - 0x03FF, 0x01CF, 0x01CE, 0x07D0, 0x0F81, 0x07D3, 0x1F1D, 0x0F80, 0x07D2, - 0x01C9, 0x03FE, 0x0074, 0x07DD, 0x00F3, 0x1F1C, 0x07DC, 0x03F9, 0x07DF, - 0x00F2, 0x00FD, 0x0077, 0x07DE, 0x07D9, 0x01C8, 0x07D8, 0x0F83, 0x03F8, - 0x0030, 0x0076, 0x0013, 0x0F82, 0x00FC, 0x03FB, 0x0033, 0x03FA, 0x03E5, - 0x03E4, 0x01CB, 0x0032, 0x1F1F, 0x03E7, 0x07DB, 0x07DA, 0x003D, 0x01CA, - 0x07C5, 0x03E6, 0x0071, 0x0F8D, 0x07C4, 0x1F1E, 0x0F8C, 0x03E1, 0x01F5, }, -{ 0x0019, 0x0065, 0x0018, 0x0351, 0x0350, 0x0353, 0x0021, 0x0020, 0x0064, - 0x001D, 0x0005, 0x0005, 0x01A5, 0x0023, 0x0067, 0x0005, 0x0066, 0x0022, - 0x001B, 0x0004, 0x0001, 0x0004, 0x001C, 0x0061, 0x001A, 0x0005, 0x0004, - 0x0007, 0x002D, 0x0006, 0x002C, 0x01A4, 0x002F, 0x0352, 0x035D, 0x0060, - 0x0001, 0x002E, 0x001F, 0x035C, 0x0000, 0x06B1, 0x01A7, 0x0029, 0x01A6, - 0x0028, 0x0063, 0x0062, 0x035F, 0x01A1, 0x002B, 0x06B0, 0x06B3, 0x01A0, - 0x0003, 0x006D, 0x001E, 0x035E, 0x006C, 0x06B2, 0x0002, 0x01A3, 0x01A2, - 0x000D, 0x0005, 0x0007, 0x01AD, 0x006F, 0x002A, 0x006E, 0x0004, 0x0004, - 0x000C, 0x0007, 0x0006, 0x000F, 0x000E, 0x00D5, 0x0009, 0x0006, 0x0007, }, -{ 0x0065, 0x0181, 0x0064, 0x36C9, 0x06D5, 0x0DB5, 0x0379, 0x0180, 0x0183, - 0x00D5, 0x001D, 0x001C, 0x0DB4, 0x0182, 0x0378, 0x00D4, 0x00D7, 0x06D4, - 0x0067, 0x001F, 0x0001, 0x00D6, 0x00D1, 0x018D, 0x0066, 0x0001, 0x0000, - 0x037B, 0x06D7, 0x037A, 0x0DB7, 0x36C8, 0x06D6, 0x0DB6, 0x1B79, 0x0DB1, - 0x018C, 0x0365, 0x00D0, 0x1B78, 0x00D3, 0x1B7B, 0x0364, 0x06D1, 0x06D0, - 0x018F, 0x018E, 0x00D2, 0x36CB, 0x0367, 0x0366, 0x06D3, 0x0DB0, 0x06D2, - 0x0361, 0x06DD, 0x0189, 0x36CA, 0x0360, 0x36F5, 0x0188, 0x0DB3, 0x36F4, - 0x0009, 0x0008, 0x0005, 0x06DC, 0x00DD, 0x018B, 0x00DC, 0x0004, 0x000B, - 0x018A, 0x0061, 0x0003, 0x0363, 0x00DF, 0x06DF, 0x0362, 0x000A, 0x001E, }, -{ 0x001D, 0x0061, 0x000D, 0x0D55, 0x06B9, 0x06B8, 0x01A5, 0x0021, 0x0020, - 0x0023, 0x000C, 0x0060, 0x0D54, 0x00AD, 0x00AC, 0x0022, 0x00AF, 0x06BB, - 0x000F, 0x001C, 0x0001, 0x002D, 0x0063, 0x01A4, 0x000E, 0x0001, 0x0005, - 0x01A7, 0x06BA, 0x01A6, 0x06A5, 0x0D57, 0x0D56, 0x1ABD, 0x0D51, 0x00AE, - 0x002C, 0x00A9, 0x002F, 0x0D50, 0x01A1, 0x1ABC, 0x06A4, 0x06A7, 0x06A6, - 0x00A8, 0x06A1, 0x01A0, 0x1ABF, 0x0D53, 0x06A0, 0x0D52, 0x1ABE, 0x06A3, - 0x0062, 0x002E, 0x0009, 0x0D5D, 0x01A3, 0x0D5C, 0x006D, 0x00AB, 0x06A2, - 0x006C, 0x001F, 0x0001, 0x06AD, 0x0029, 0x01A2, 0x0028, 0x0004, 0x001E, - 0x01AD, 0x006F, 0x0000, 0x01AC, 0x01AF, 0x06AC, 0x00AA, 0x006E, 0x0019, }, -{ 0x0019, 0x007D, 0x0018, 0x01B5, 0x000D, 0x01B4, 0x007C, 0x007F, 0x01B7, - 0x000C, 0x001B, 0x001A, 0x01B6, 0x000F, 0x00D5, 0x0019, 0x007E, 0x00D4, - 0x0018, 0x001B, 0x0001, 0x000E, 0x0011, 0x0009, 0x0005, 0x0005, 0x0005, - 0x00D7, 0x01B1, 0x0008, 0x01B0, 0x0079, 0x06FD, 0x0371, 0x0370, 0x00D6, - 0x0078, 0x01B3, 0x0010, 0x0373, 0x0013, 0x06FC, 0x007B, 0x007A, 0x00D1, - 0x00D0, 0x00D3, 0x0065, 0x0372, 0x06FF, 0x0064, 0x06FE, 0x037D, 0x00D2, - 0x00DD, 0x0067, 0x0004, 0x037C, 0x0012, 0x01B2, 0x0007, 0x0066, 0x01BD, - 0x0006, 0x0061, 0x0004, 0x01BC, 0x001A, 0x0060, 0x001D, 0x0004, 0x001C, - 0x0063, 0x0001, 0x0007, 0x000B, 0x0000, 0x0062, 0x000A, 0x0005, 0x0007, }, -{ 0x0069, 0x0045, 0x0068, 0x04BD, 0x0255, 0x04BC, 0x00E5, 0x00E4, 0x0031, - 0x0030, 0x0019, 0x0001, 0x0121, 0x00E7, 0x00E6, 0x0033, 0x00E1, 0x00E0, - 0x006B, 0x0018, 0x0001, 0x0044, 0x0032, 0x0047, 0x006A, 0x001B, 0x0005, - 0x003D, 0x0046, 0x0015, 0x0041, 0x0120, 0x0123, 0x04BF, 0x0122, 0x0040, - 0x003C, 0x00E3, 0x0014, 0x0254, 0x0043, 0x0975, 0x012D, 0x00E2, 0x00ED, - 0x0042, 0x00EC, 0x004D, 0x0257, 0x0256, 0x0251, 0x04BE, 0x0974, 0x0250, - 0x00EF, 0x00EE, 0x004C, 0x04B9, 0x012C, 0x04B8, 0x004F, 0x04BB, 0x0253, - 0x003F, 0x0017, 0x0001, 0x0252, 0x00E9, 0x00E8, 0x00EB, 0x0000, 0x0003, - 0x0016, 0x0002, 0x0004, 0x004E, 0x003E, 0x00EA, 0x0049, 0x000D, 0x0007, }, -{ 0x000D, 0x01BD, 0x000C, 0x0D31, 0x0D30, 0x0D33, 0x0359, 0x0358, 0x002D, - 0x0065, 0x001D, 0x001C, 0x0D32, 0x035B, 0x035A, 0x002C, 0x01BC, 0x0345, - 0x000F, 0x001F, 0x0001, 0x002F, 0x0064, 0x01BF, 0x0067, 0x0001, 0x0005, - 0x0066, 0x002E, 0x0061, 0x0029, 0x0695, 0x0694, 0x0697, 0x0696, 0x0060, - 0x01BE, 0x0D3D, 0x0028, 0x1A49, 0x0344, 0x1A48, 0x1A4B, 0x0D3C, 0x0691, - 0x002B, 0x01B9, 0x002A, 0x0D3F, 0x0690, 0x0347, 0x0D3E, 0x1A4A, 0x0346, - 0x00D5, 0x0341, 0x0063, 0x0D39, 0x0340, 0x0D38, 0x01B8, 0x0D3B, 0x0D3A, - 0x00D4, 0x0062, 0x0000, 0x0693, 0x01BB, 0x0343, 0x0342, 0x001E, 0x000E, - 0x006D, 0x0009, 0x0001, 0x006C, 0x00D7, 0x034D, 0x01BA, 0x0008, 0x0004, }, -{ 0x0075, 0x00CD, 0x0035, 0x03C1, 0x03C0, 0x07F9, 0x03C3, 0x1F8D, 0x00CC, - 0x0074, 0x0011, 0x0010, 0x03C2, 0x0FD9, 0x01F1, 0x00CF, 0x03CD, 0x00CE, - 0x0034, 0x0001, 0x0001, 0x0037, 0x00C9, 0x00C8, 0x0036, 0x0000, 0x0001, - 0x0FD8, 0x03CC, 0x00CB, 0x01F0, 0x07F8, 0x03CF, 0x07FB, 0x07FA, 0x00CA, - 0x01F3, 0x03CE, 0x00F5, 0x0FDB, 0x00F4, 0x07E5, 0x07E4, 0x07E7, 0x01F2, - 0x07E6, 0x03C9, 0x01FD, 0x0FDA, 0x1F8C, 0x07E1, 0x1F8F, 0x1F8E, 0x03C8, - 0x03CB, 0x0077, 0x0076, 0x0FC5, 0x03CA, 0x07E0, 0x00F7, 0x0FC4, 0x03F5, - 0x00F6, 0x01FC, 0x0003, 0x03F4, 0x0071, 0x03F7, 0x00F1, 0x0013, 0x0031, - 0x0030, 0x0070, 0x0005, 0x0012, 0x0073, 0x01FF, 0x0072, 0x007D, 0x0002, }, -{ 0x0061, 0x0055, 0x0060, 0x02C9, 0x02C8, 0x02CB, 0x0171, 0x00B5, 0x0054, - 0x0001, 0x0001, 0x0001, 0x0057, 0x0001, 0x0063, 0x001D, 0x0062, 0x0039, - 0x006D, 0x0000, 0x0005, 0x0038, 0x0056, 0x00B4, 0x006C, 0x0003, 0x001C, - 0x006F, 0x003B, 0x0002, 0x003A, 0x0170, 0x00B7, 0x0173, 0x0051, 0x006E, - 0x0025, 0x0050, 0x0069, 0x02CA, 0x0024, 0x0027, 0x0172, 0x00B6, 0x00B1, - 0x000D, 0x000C, 0x001F, 0x017D, 0x0026, 0x0068, 0x0053, 0x017C, 0x006B, - 0x001E, 0x000F, 0x0004, 0x017F, 0x006A, 0x02F5, 0x0019, 0x0021, 0x0052, - 0x02F4, 0x02F7, 0x0020, 0x0BCD, 0x05E5, 0x05E4, 0x0BCC, 0x0023, 0x00B0, - 0x02F6, 0x00B3, 0x0022, 0x02F1, 0x02F0, 0x0BCF, 0x0BCE, 0x017E, 0x005D, }, -{ 0x00BD, 0x0025, 0x01A1, 0x0159, 0x0299, 0x00BC, 0x0024, 0x0505, 0x0504, - 0x01A0, 0x0001, 0x001D, 0x006D, 0x001C, 0x0001, 0x0005, 0x0027, 0x01A3, - 0x0158, 0x001F, 0x001E, 0x01A2, 0x0026, 0x0021, 0x000D, 0x0020, 0x0023, - 0x0298, 0x006C, 0x0022, 0x00BF, 0x00BE, 0x01AD, 0x002D, 0x029B, 0x00B9, - 0x01AC, 0x00B8, 0x01AF, 0x029A, 0x006F, 0x015B, 0x006E, 0x0285, 0x0284, - 0x01AE, 0x0019, 0x002C, 0x01A9, 0x01A8, 0x000C, 0x000F, 0x015A, 0x00BB, - 0x000E, 0x0000, 0x0069, 0x01AB, 0x0018, 0x01AA, 0x0004, 0x0055, 0x00BA, - 0x0507, 0x0145, 0x0054, 0x0506, 0x00A5, 0x0501, 0x00A4, 0x0057, 0x0500, - 0x0A05, 0x0144, 0x00A7, 0x0287, 0x0286, 0x0503, 0x0147, 0x0A04, 0x0146, }, -{ 0x0759, 0x0041, 0x00E5, 0x03BD, 0x0E9D, 0x012D, 0x012C, 0x3A1D, 0x03BC, - 0x012F, 0x000D, 0x0040, 0x00E4, 0x03BF, 0x0043, 0x0042, 0x0758, 0x03BE, - 0x00E7, 0x0001, 0x0000, 0x003D, 0x00E6, 0x0015, 0x0014, 0x0017, 0x003C, - 0x743D, 0x012E, 0x03B9, 0x03B8, 0x0E9C, 0x03BB, 0x075B, 0x3A1C, 0x0E9F, - 0x0129, 0x00E1, 0x0128, 0x0E9E, 0x012B, 0x075A, 0x00E0, 0x0E99, 0x0745, - 0x3A1F, 0x03BA, 0x0744, 0x0E98, 0x1D0D, 0x03A5, 0x0E9B, 0x743C, 0x0E9A, - 0x012A, 0x004D, 0x00E3, 0x0E85, 0x01D5, 0x0E84, 0x004C, 0x0747, 0x1D0C, - 0x01D4, 0x003F, 0x0016, 0x0746, 0x03A4, 0x0741, 0x004F, 0x003E, 0x01D7, - 0x0740, 0x000C, 0x0011, 0x004E, 0x00E2, 0x00ED, 0x00EC, 0x0049, 0x0048, }, +static const uint8_t aic_mode2_vlc_syms[AIC_MODE2_NUM][AIC_MODE2_SIZE] = { + { + 0x06, 0x01, 0x28, 0x11, 0x22, 0x20, 0x04, 0x07, 0x05, 0x16, 0x08, 0x60, + 0x02, 0x66, 0x61, 0x23, 0x15, 0x31, 0x26, 0x77, 0x12, 0x10, 0x42, 0x21, + 0x72, 0x50, 0x88, 0x82, 0x27, 0x24, 0x44, 0x40, 0x62, 0x55, 0x18, 0x13, + 0x53, 0x52, 0x64, 0x46, 0x41, 0x51, 0x47, 0x33, 0x32, 0x74, 0x67, 0x14, + 0x03, 0x30, 0x25, 0x36, 0x34, 0x45, 0x37, 0x78, 0x85, 0x84, 0x75, 0x73, + 0x57, 0x86, 0x65, 0x58, 0x71, 0x68, 0x70, 0x56, 0x54, 0x17, 0x76, 0x63, + 0x87, 0x81, 0x80, 0x38, 0x35, 0x48, 0x43, 0x83, 0x00, + }, + { + 0x77, 0x62, 0x46, 0x33, 0x68, 0x52, 0x18, 0x05, 0x31, 0x25, 0x42, 0x04, + 0x51, 0x44, 0x40, 0x32, 0x55, 0x41, 0x26, 0x24, 0x30, 0x27, 0x57, 0x36, + 0x84, 0x76, 0x81, 0x83, 0x78, 0x73, 0x45, 0x85, 0x75, 0x86, 0x87, 0x56, + 0x53, 0x80, 0x67, 0x35, 0x34, 0x43, 0x37, 0x82, 0x70, 0x65, 0x74, 0x71, + 0x54, 0x48, 0x63, 0x58, 0x72, 0x64, 0x07, 0x03, 0x47, 0x38, 0x88, 0x20, + 0x01, 0x60, 0x28, 0x16, 0x02, 0x61, 0x50, 0x13, 0x08, 0x23, 0x17, 0x66, + 0x14, 0x06, 0x21, 0x15, 0x10, 0x00, 0x22, 0x12, 0x11, + }, + { + 0x10, 0x01, 0x24, 0x12, 0x88, 0x83, 0x70, 0x14, 0x08, 0x46, 0x25, 0x87, + 0x44, 0x42, 0x60, 0x50, 0x61, 0x51, 0x71, 0x66, 0x15, 0x04, 0x41, 0x33, + 0x17, 0x03, 0x34, 0x18, 0x86, 0x68, 0x67, 0x63, 0x57, 0x75, 0x65, 0x45, + 0x36, 0x58, 0x54, 0x43, 0x37, 0x56, 0x53, 0x74, 0x62, 0x85, 0x78, 0x07, + 0x05, 0x35, 0x13, 0x84, 0x64, 0x55, 0x76, 0x73, 0x47, 0x38, 0x52, 0x48, + 0x11, 0x00, 0x21, 0x20, 0x82, 0x28, 0x81, 0x80, 0x31, 0x30, 0x40, 0x32, + 0x16, 0x06, 0x26, 0x23, 0x27, 0x02, 0x77, 0x72, 0x22, + }, + { + 0x88, 0x82, 0x50, 0x47, 0x74, 0x43, 0x76, 0x75, 0x68, 0x24, 0x00, 0x37, + 0x30, 0x54, 0x44, 0x64, 0x58, 0x36, 0x34, 0x65, 0x40, 0x06, 0x03, 0x20, + 0x17, 0x08, 0x04, 0x48, 0x45, 0x87, 0x84, 0x71, 0x85, 0x78, 0x80, 0x73, + 0x07, 0x86, 0x63, 0x57, 0x70, 0x67, 0x77, 0x72, 0x83, 0x81, 0x32, 0x28, + 0x18, 0x05, 0x42, 0x38, 0x52, 0x14, 0x02, 0x25, 0x23, 0x66, 0x56, 0x53, + 0x62, 0x60, 0x35, 0x33, 0x46, 0x41, 0x21, 0x12, 0x10, 0x01, 0x26, 0x13, + 0x61, 0x22, 0x16, 0x27, 0x15, 0x55, 0x31, 0x51, 0x11, + }, + { + 0x13, 0x10, 0x27, 0x14, 0x66, 0x44, 0x41, 0x53, 0x46, 0x25, 0x18, 0x35, + 0x33, 0x68, 0x63, 0x88, 0x71, 0x34, 0x24, 0x50, 0x47, 0x37, 0x08, 0x48, + 0x45, 0x82, 0x74, 0x70, 0x84, 0x76, 0x30, 0x04, 0x57, 0x43, 0x83, 0x78, + 0x86, 0x85, 0x73, 0x07, 0x80, 0x75, 0x87, 0x65, 0x56, 0x03, 0x00, 0x20, + 0x06, 0x72, 0x52, 0x31, 0x62, 0x60, 0x21, 0x15, 0x51, 0x22, 0x16, 0x12, + 0x02, 0x01, 0x23, 0x17, 0x55, 0x77, 0x64, 0x58, 0x54, 0x81, 0x67, 0x36, + 0x05, 0x40, 0x38, 0x28, 0x26, 0x42, 0x32, 0x61, 0x11, + }, + { + 0x22, 0x11, 0x23, 0x13, 0x32, 0x25, 0x72, 0x45, 0x40, 0x57, 0x50, 0x03, + 0x00, 0x30, 0x08, 0x86, 0x75, 0x80, 0x68, 0x43, 0x04, 0x47, 0x07, 0x48, + 0x65, 0x58, 0x85, 0x84, 0x78, 0x64, 0x67, 0x63, 0x74, 0x73, 0x06, 0x05, + 0x44, 0x37, 0x87, 0x83, 0x46, 0x42, 0x54, 0x53, 0x18, 0x17, 0x36, 0x34, + 0x66, 0x55, 0x38, 0x24, 0x56, 0x41, 0x02, 0x01, 0x20, 0x14, 0x16, 0x12, + 0x61, 0x27, 0x26, 0x15, 0x31, 0x28, 0x21, 0x88, 0x82, 0x62, 0x60, 0x76, + 0x70, 0x33, 0x10, 0x52, 0x35, 0x71, 0x51, 0x81, 0x77, + }, + { + 0x16, 0x12, 0x61, 0x22, 0x51, 0x21, 0x15, 0x52, 0x31, 0x55, 0x81, 0x66, + 0x46, 0x42, 0x62, 0x54, 0x14, 0x01, 0x25, 0x23, 0x27, 0x13, 0x56, 0x41, + 0x35, 0x33, 0x58, 0x53, 0x26, 0x10, 0x32, 0x28, 0x84, 0x77, 0x43, 0x00, + 0x68, 0x47, 0x85, 0x45, 0x34, 0x57, 0x50, 0x05, 0x03, 0x37, 0x30, 0x87, + 0x86, 0x76, 0x08, 0x07, 0x80, 0x75, 0x70, 0x73, 0x04, 0x78, 0x74, 0x63, + 0x48, 0x71, 0x67, 0x82, 0x65, 0x17, 0x06, 0x24, 0x20, 0x88, 0x83, 0x60, + 0x44, 0x40, 0x72, 0x64, 0x18, 0x02, 0x38, 0x36, 0x11, + }, + { + 0x66, 0x01, 0x14, 0x03, 0x24, 0x23, 0x62, 0x08, 0x04, 0x35, 0x20, 0x72, + 0x63, 0x58, 0x70, 0x68, 0x48, 0x45, 0x54, 0x53, 0x26, 0x25, 0x65, 0x44, + 0x13, 0x05, 0x51, 0x41, 0x61, 0x16, 0x12, 0x10, 0x06, 0x28, 0x27, 0x60, + 0x40, 0x32, 0x56, 0x52, 0x17, 0x00, 0x31, 0x18, 0x73, 0x30, 0x75, 0x74, + 0x88, 0x84, 0x83, 0x86, 0x80, 0x85, 0x43, 0x38, 0x87, 0x47, 0x76, 0x71, + 0x50, 0x37, 0x78, 0x57, 0x82, 0x77, 0x67, 0x33, 0x07, 0x36, 0x34, 0x81, + 0x46, 0x42, 0x64, 0x55, 0x15, 0x02, 0x22, 0x21, 0x11, + }, + { + 0x22, 0x00, 0x11, 0x01, 0x20, 0x08, 0x88, 0x62, 0x27, 0x02, 0x07, 0x06, + 0x21, 0x12, 0x28, 0x87, 0x66, 0x32, 0x30, 0x38, 0x33, 0x15, 0x14, 0x25, + 0x17, 0x26, 0x24, 0x60, 0x42, 0x78, 0x71, 0x84, 0x81, 0x44, 0x23, 0x52, + 0x50, 0x80, 0x70, 0x35, 0x13, 0x48, 0x46, 0x83, 0x51, 0x40, 0x64, 0x61, + 0x55, 0x47, 0x74, 0x58, 0x18, 0x03, 0x41, 0x31, 0x73, 0x68, 0x43, 0x36, + 0x57, 0x45, 0x85, 0x56, 0x54, 0x67, 0x65, 0x76, 0x75, 0x37, 0x34, 0x63, + 0x53, 0x86, 0x77, 0x72, 0x05, 0x04, 0x16, 0x10, 0x82, + }, + { + 0x22, 0x12, 0x27, 0x21, 0x14, 0x01, 0x20, 0x15, 0x62, 0x02, 0x00, 0x16, + 0x10, 0x60, 0x17, 0x72, 0x66, 0x28, 0x07, 0x06, 0x18, 0x13, 0x82, 0x55, + 0x40, 0x78, 0x71, 0x25, 0x23, 0x32, 0x31, 0x42, 0x26, 0x61, 0x52, 0x24, + 0x08, 0x50, 0x44, 0x77, 0x37, 0x34, 0x63, 0x57, 0x87, 0x84, 0x80, 0x86, + 0x83, 0x45, 0x36, 0x85, 0x73, 0x70, 0x68, 0x81, 0x74, 0x33, 0x03, 0x38, + 0x35, 0x88, 0x56, 0x54, 0x76, 0x75, 0x46, 0x43, 0x53, 0x48, 0x64, 0x51, + 0x58, 0x47, 0x67, 0x65, 0x05, 0x04, 0x41, 0x30, 0x11, + }, + { + 0x44, 0x40, 0x66, 0x60, 0x23, 0x16, 0x32, 0x30, 0x07, 0x06, 0x18, 0x14, + 0x86, 0x50, 0x47, 0x75, 0x55, 0x33, 0x31, 0x41, 0x35, 0x80, 0x70, 0x84, + 0x83, 0x78, 0x71, 0x87, 0x81, 0x77, 0x12, 0x38, 0x25, 0x52, 0x51, 0x08, + 0x01, 0x17, 0x15, 0x58, 0x54, 0x68, 0x67, 0x34, 0x13, 0x48, 0x46, 0x04, + 0x03, 0x36, 0x05, 0x85, 0x56, 0x45, 0x65, 0x57, 0x73, 0x43, 0x37, 0x63, + 0x53, 0x64, 0x61, 0x76, 0x74, 0x24, 0x10, 0x62, 0x42, 0x21, 0x11, 0x02, + 0x00, 0x26, 0x20, 0x88, 0x28, 0x27, 0x82, 0x72, 0x22, + }, + { + 0x28, 0x27, 0x71, 0x70, 0x87, 0x78, 0x82, 0x22, 0x77, 0x72, 0x07, 0x01, + 0x14, 0x08, 0x81, 0x66, 0x62, 0x80, 0x75, 0x40, 0x25, 0x51, 0x50, 0x02, + 0x00, 0x26, 0x20, 0x42, 0x24, 0x52, 0x44, 0x16, 0x10, 0x23, 0x17, 0x64, + 0x60, 0x86, 0x83, 0x46, 0x41, 0x55, 0x54, 0x48, 0x47, 0x58, 0x56, 0x18, + 0x04, 0x35, 0x31, 0x57, 0x38, 0x34, 0x03, 0x63, 0x53, 0x67, 0x13, 0x05, + 0x36, 0x33, 0x73, 0x61, 0x43, 0x37, 0x68, 0x65, 0x45, 0x85, 0x76, 0x74, + 0x15, 0x06, 0x32, 0x30, 0x84, 0x12, 0x11, 0x88, 0x21, + }, + { + 0x82, 0x27, 0x08, 0x07, 0x16, 0x10, 0x62, 0x76, 0x74, 0x50, 0x41, 0x86, + 0x67, 0x15, 0x14, 0x38, 0x17, 0x40, 0x23, 0x61, 0x42, 0x11, 0x02, 0x26, + 0x20, 0x72, 0x77, 0x28, 0x12, 0x01, 0x60, 0x24, 0x88, 0x52, 0x44, 0x75, + 0x64, 0x25, 0x06, 0x32, 0x30, 0x55, 0x51, 0x68, 0x58, 0x46, 0x33, 0x48, + 0x47, 0x43, 0x37, 0x56, 0x54, 0x13, 0x03, 0x35, 0x34, 0x85, 0x73, 0x65, + 0x63, 0x45, 0x36, 0x57, 0x53, 0x83, 0x80, 0x05, 0x04, 0x31, 0x18, 0x84, + 0x70, 0x66, 0x87, 0x81, 0x21, 0x00, 0x78, 0x71, 0x22, + }, + { + 0x84, 0x81, 0x32, 0x25, 0x86, 0x83, 0x10, 0x04, 0x23, 0x14, 0x62, 0x26, + 0x70, 0x66, 0x42, 0x24, 0x64, 0x44, 0x87, 0x75, 0x71, 0x85, 0x80, 0x55, + 0x52, 0x67, 0x61, 0x50, 0x48, 0x58, 0x51, 0x18, 0x15, 0x38, 0x30, 0x33, + 0x31, 0x65, 0x41, 0x05, 0x03, 0x13, 0x08, 0x37, 0x36, 0x53, 0x43, 0x60, + 0x73, 0x68, 0x63, 0x57, 0x45, 0x35, 0x56, 0x54, 0x78, 0x76, 0x40, 0x34, + 0x47, 0x46, 0x06, 0x01, 0x17, 0x07, 0x77, 0x28, 0x02, 0x00, 0x12, 0x11, + 0x88, 0x72, 0x27, 0x20, 0x16, 0x74, 0x21, 0x82, 0x22, + }, + { + 0x77, 0x12, 0x81, 0x78, 0x72, 0x38, 0x33, 0x50, 0x44, 0x23, 0x01, 0x31, + 0x25, 0x34, 0x13, 0x37, 0x35, 0x86, 0x58, 0x55, 0x73, 0x68, 0x43, 0x04, + 0x54, 0x53, 0x64, 0x46, 0x65, 0x63, 0x57, 0x45, 0x67, 0x05, 0x03, 0x56, + 0x36, 0x62, 0x52, 0x83, 0x66, 0x42, 0x32, 0x80, 0x71, 0x10, 0x08, 0x24, + 0x16, 0x87, 0x18, 0x17, 0x47, 0x41, 0x07, 0x06, 0x15, 0x14, 0x75, 0x74, + 0x85, 0x76, 0x51, 0x48, 0x61, 0x60, 0x40, 0x30, 0x84, 0x70, 0x22, 0x82, + 0x28, 0x21, 0x11, 0x02, 0x00, 0x26, 0x20, 0x27, 0x88, + }, + { + 0x72, 0x27, 0x87, 0x81, 0x42, 0x33, 0x52, 0x50, 0x16, 0x08, 0x31, 0x23, + 0x02, 0x00, 0x78, 0x20, 0x82, 0x88, 0x28, 0x38, 0x32, 0x71, 0x62, 0x24, + 0x10, 0x30, 0x26, 0x64, 0x61, 0x76, 0x75, 0x44, 0x18, 0x58, 0x55, 0x54, + 0x48, 0x45, 0x43, 0x57, 0x46, 0x73, 0x35, 0x34, 0x37, 0x36, 0x04, 0x03, + 0x13, 0x05, 0x85, 0x65, 0x63, 0x68, 0x67, 0x47, 0x41, 0x56, 0x53, 0x70, + 0x60, 0x07, 0x06, 0x15, 0x14, 0x84, 0x83, 0x80, 0x66, 0x51, 0x86, 0x74, + 0x17, 0x01, 0x40, 0x25, 0x12, 0x11, 0x77, 0x21, 0x22, + }, + { + 0x27, 0x21, 0x88, 0x72, 0x28, 0x12, 0x11, 0x83, 0x77, 0x82, 0x80, 0x78, + 0x25, 0x24, 0x38, 0x32, 0x08, 0x01, 0x18, 0x16, 0x20, 0x02, 0x26, 0x23, + 0x81, 0x74, 0x86, 0x84, 0x10, 0x00, 0x62, 0x61, 0x04, 0x03, 0x13, 0x06, + 0x76, 0x58, 0x51, 0x64, 0x60, 0x31, 0x17, 0x41, 0x35, 0x44, 0x42, 0x70, + 0x66, 0x33, 0x15, 0x48, 0x40, 0x87, 0x65, 0x55, 0x67, 0x63, 0x54, 0x07, + 0x57, 0x56, 0x46, 0x45, 0x50, 0x47, 0x73, 0x68, 0x30, 0x14, 0x53, 0x43, + 0x75, 0x71, 0x52, 0x34, 0x05, 0x37, 0x36, 0x85, 0x22, + }, + { + 0x21, 0x14, 0x32, 0x27, 0x10, 0x72, 0x67, 0x82, 0x77, 0x44, 0x40, 0x54, + 0x45, 0x41, 0x37, 0x68, 0x56, 0x08, 0x01, 0x24, 0x13, 0x78, 0x48, 0x04, + 0x03, 0x43, 0x05, 0x81, 0x25, 0x07, 0x47, 0x35, 0x34, 0x06, 0x46, 0x36, + 0x88, 0x84, 0x83, 0x75, 0x74, 0x76, 0x73, 0x86, 0x85, 0x70, 0x65, 0x80, + 0x71, 0x57, 0x53, 0x87, 0x63, 0x51, 0x50, 0x23, 0x18, 0x33, 0x31, 0x61, + 0x12, 0x62, 0x22, 0x02, 0x00, 0x17, 0x15, 0x66, 0x55, 0x42, 0x64, 0x58, + 0x26, 0x20, 0x38, 0x30, 0x28, 0x16, 0x60, 0x52, 0x11, + }, + { + 0x61, 0x15, 0x27, 0x25, 0x32, 0x28, 0x06, 0x01, 0x24, 0x17, 0x78, 0x75, + 0x87, 0x80, 0x85, 0x08, 0x07, 0x73, 0x70, 0x48, 0x47, 0x84, 0x83, 0x81, + 0x71, 0x88, 0x86, 0x76, 0x74, 0x30, 0x04, 0x43, 0x37, 0x82, 0x72, 0x67, + 0x20, 0x03, 0x57, 0x45, 0x77, 0x52, 0x36, 0x41, 0x38, 0x68, 0x58, 0x05, + 0x00, 0x34, 0x33, 0x55, 0x26, 0x60, 0x56, 0x11, 0x66, 0x16, 0x64, 0x51, + 0x10, 0x02, 0x23, 0x18, 0x62, 0x54, 0x53, 0x65, 0x63, 0x40, 0x35, 0x50, + 0x42, 0x31, 0x13, 0x46, 0x44, 0x14, 0x12, 0x22, 0x21, + }, + { + 0x22, 0x21, 0x12, 0x01, 0x16, 0x15, 0x82, 0x88, 0x87, 0x42, 0x40, 0x60, + 0x44, 0x06, 0x05, 0x31, 0x10, 0x66, 0x61, 0x83, 0x76, 0x26, 0x25, 0x72, + 0x27, 0x81, 0x11, 0x46, 0x41, 0x84, 0x62, 0x13, 0x02, 0x24, 0x20, 0x80, + 0x75, 0x65, 0x63, 0x68, 0x54, 0x37, 0x07, 0x57, 0x30, 0x50, 0x52, 0x48, + 0x73, 0x67, 0x74, 0x55, 0x53, 0x47, 0x58, 0x56, 0x34, 0x04, 0x43, 0x38, + 0x70, 0x64, 0x17, 0x00, 0x45, 0x36, 0x78, 0x86, 0x85, 0x33, 0x32, 0x51, + 0x35, 0x08, 0x03, 0x18, 0x14, 0x28, 0x23, 0x77, 0x71, + }, }; static const uint8_t aic_mode2_vlc_bits[AIC_MODE2_NUM][AIC_MODE2_SIZE] = { -{ 1, 5, 4, 10, 6, 8, 5, 8, 8, - 7, 5, 7, 11, 10, 9, 8, 13, 11, - 6, 7, 3, 9, 8, 10, 9, 8, 5, - 10, 9, 10, 10, 14, 12, 14, 14, 12, - 8, 9, 7, 12, 8, 14, 9, 9, 12, - 8, 9, 11, 11, 13, 9, 11, 14, 12, - 6, 7, 9, 13, 9, 12, 7, 10, 12, - 11, 12, 8, 15, 10, 15, 13, 7, 12, - 10, 10, 8, 10, 13, 13, 13, 11, 8, }, -{ 4, 6, 5, 11, 8, 10, 7, 11, 9, - 4, 1, 4, 9, 7, 7, 5, 9, 10, - 6, 7, 4, 9, 9, 10, 9, 9, 6, - 9, 10, 9, 10, 12, 12, 13, 12, 11, - 9, 9, 8, 12, 8, 14, 10, 11, 12, - 7, 8, 10, 11, 12, 9, 11, 13, 12, - 6, 7, 8, 12, 9, 12, 7, 11, 10, - 12, 12, 9, 14, 12, 15, 13, 8, 12, - 11, 11, 10, 12, 13, 15, 14, 12, 9, }, -{ 5, 7, 6, 12, 9, 11, 8, 11, 10, - 7, 5, 7, 11, 10, 9, 8, 12, 12, - 5, 5, 1, 8, 7, 10, 8, 6, 4, - 8, 8, 8, 9, 12, 11, 13, 12, 11, - 8, 9, 8, 12, 8, 13, 10, 11, 11, - 8, 9, 11, 12, 13, 11, 12, 14, 13, - 8, 9, 10, 14, 11, 14, 9, 13, 13, - 8, 9, 6, 11, 10, 14, 11, 6, 10, - 6, 6, 4, 8, 9, 10, 10, 8, 5, }, -{ 11, 7, 8, 10, 12, 9, 10, 14, 12, - 7, 1, 5, 7, 8, 6, 4, 10, 9, - 10, 5, 4, 8, 11, 8, 7, 6, 7, - 11, 6, 7, 8, 10, 8, 10, 11, 9, - 10, 8, 9, 13, 9, 12, 8, 11, 12, - 11, 4, 7, 8, 9, 6, 8, 12, 9, - 8, 5, 8, 12, 9, 10, 6, 12, 11, - 12, 12, 10, 15, 13, 13, 13, 10, 13, - 15, 10, 9, 10, 12, 13, 13, 10, 9, }, -{ 11, 8, 8, 11, 13, 10, 11, 15, 12, - 7, 1, 4, 7, 7, 5, 4, 8, 9, - 11, 5, 5, 8, 11, 9, 8, 7, 8, - 13, 7, 8, 9, 11, 9, 10, 12, 10, - 10, 9, 8, 13, 9, 12, 9, 11, 12, - 11, 5, 7, 9, 10, 6, 9, 13, 10, - 7, 4, 7, 11, 8, 9, 5, 10, 11, - 13, 11, 9, 15, 13, 15, 13, 8, 12, - 15, 10, 10, 12, 13, 14, 14, 12, 11, }, -{ 12, 9, 9, 12, 13, 11, 11, 14, 12, - 8, 2, 5, 7, 9, 6, 5, 10, 10, - 9, 4, 2, 7, 9, 7, 6, 5, 6, - 12, 6, 7, 8, 10, 8, 10, 11, 9, - 12, 9, 10, 13, 11, 12, 10, 14, 13, - 12, 6, 8, 10, 10, 7, 9, 12, 10, - 8, 5, 8, 11, 9, 10, 7, 11, 12, - 8, 6, 5, 11, 11, 11, 8, 6, 9, - 12, 6, 6, 8, 10, 10, 11, 8, 6, }, -{ 13, 9, 10, 12, 14, 12, 11, 15, 15, - 8, 1, 5, 7, 9, 6, 5, 11, 10, - 11, 6, 5, 9, 11, 9, 8, 7, 8, - 12, 6, 8, 8, 11, 8, 10, 12, 10, - 10, 7, 9, 13, 10, 11, 9, 13, 12, - 11, 3, 6, 8, 9, 4, 7, 11, 8, - 8, 5, 9, 12, 10, 9, 7, 12, 13, - 13, 12, 10, 14, 14, 15, 12, 11, 14, - 15, 7, 9, 8, 11, 11, 12, 10, 9, }, -{ 10, 5, 6, 9, 11, 7, 8, 12, 11, - 8, 1, 4, 7, 9, 6, 4, 10, 10, - 11, 6, 6, 9, 9, 9, 9, 8, 8, - 14, 10, 10, 12, 12, 11, 12, 13, 12, - 10, 7, 8, 12, 9, 11, 8, 12, 11, - 13, 7, 10, 11, 11, 8, 10, 13, 11, - 6, 3, 7, 11, 8, 9, 5, 10, 11, - 11, 11, 9, 14, 14, 14, 11, 10, 13, - 14, 10, 11, 13, 13, 13, 14, 12, 12, }, -{ 2, 5, 3, 11, 8, 8, 6, 6, 7, - 8, 5, 6, 12, 10, 10, 8, 10, 11, - 7, 6, 2, 9, 8, 10, 8, 5, 4, - 10, 11, 10, 10, 13, 12, 14, 13, 10, - 10, 11, 8, 14, 9, 14, 12, 11, 12, - 9, 10, 9, 13, 12, 11, 12, 14, 11, - 8, 10, 7, 13, 10, 12, 8, 12, 12, - 10, 9, 6, 12, 11, 11, 11, 6, 9, - 10, 9, 6, 10, 9, 12, 11, 8, 7, }, -{ 6, 8, 6, 12, 11, 11, 10, 10, 9, - 6, 1, 3, 10, 8, 8, 6, 7, 10, - 8, 6, 3, 10, 9, 10, 8, 6, 5, - 11, 10, 10, 12, 13, 12, 14, 13, 12, - 10, 11, 8, 12, 9, 14, 12, 11, 12, - 9, 9, 8, 12, 12, 10, 12, 13, 11, - 7, 8, 6, 13, 9, 11, 7, 11, 11, - 11, 10, 7, 14, 11, 12, 12, 7, 10, - 12, 11, 8, 13, 12, 14, 13, 11, 10, }, -{ 7, 10, 7, 13, 13, 13, 11, 11, 10, - 8, 5, 6, 12, 11, 10, 9, 10, 11, - 7, 5, 1, 9, 8, 10, 7, 4, 4, - 9, 11, 9, 11, 12, 11, 13, 13, 10, - 9, 11, 8, 13, 9, 14, 12, 11, 12, - 11, 10, 10, 13, 12, 11, 14, 14, 12, - 9, 10, 8, 13, 10, 14, 9, 12, 12, - 9, 7, 4, 12, 10, 11, 10, 6, 7, - 9, 7, 4, 9, 9, 11, 9, 7, 5, }, -{ 7, 9, 7, 14, 11, 12, 10, 9, 9, - 8, 5, 5, 12, 9, 10, 8, 8, 11, - 7, 5, 2, 8, 8, 9, 7, 4, 4, - 10, 11, 10, 12, 14, 11, 12, 13, 12, - 9, 10, 8, 13, 8, 13, 10, 11, 11, - 9, 9, 8, 14, 10, 10, 11, 12, 11, - 10, 11, 9, 14, 10, 14, 9, 12, 14, - 6, 6, 3, 11, 8, 9, 8, 3, 6, - 9, 7, 4, 10, 8, 11, 10, 6, 5, }, -{ 6, 8, 7, 13, 12, 12, 10, 9, 9, - 9, 7, 8, 13, 11, 11, 9, 11, 12, - 7, 6, 1, 9, 8, 10, 7, 5, 4, - 10, 12, 10, 12, 13, 13, 14, 13, 11, - 9, 11, 9, 13, 10, 14, 12, 12, 12, - 11, 12, 10, 14, 13, 12, 13, 14, 12, - 8, 9, 7, 13, 10, 13, 8, 11, 12, - 8, 6, 3, 12, 9, 10, 9, 4, 6, - 10, 8, 5, 10, 10, 12, 11, 8, 6, }, -{ 7, 10, 7, 12, 9, 12, 10, 10, 12, - 9, 7, 7, 12, 9, 11, 6, 10, 11, - 6, 6, 1, 9, 8, 9, 7, 4, 5, - 11, 12, 9, 12, 10, 14, 13, 13, 11, - 10, 12, 8, 13, 8, 14, 10, 10, 11, - 11, 11, 10, 13, 14, 10, 14, 13, 11, - 11, 10, 7, 13, 8, 12, 7, 10, 12, - 7, 10, 4, 12, 6, 10, 8, 5, 8, - 10, 7, 4, 9, 7, 10, 9, 6, 5, }, -{ 7, 9, 7, 13, 12, 13, 10, 10, 8, - 8, 5, 6, 11, 10, 10, 8, 10, 10, - 7, 5, 2, 9, 8, 9, 7, 5, 3, - 8, 9, 7, 9, 11, 11, 13, 11, 9, - 8, 10, 7, 12, 9, 14, 11, 10, 10, - 9, 10, 9, 12, 12, 12, 13, 14, 12, - 10, 10, 9, 13, 11, 13, 9, 13, 12, - 8, 7, 4, 12, 10, 10, 10, 6, 6, - 7, 6, 3, 9, 8, 10, 9, 6, 3, }, -{ 7, 10, 7, 13, 13, 13, 11, 11, 9, - 8, 6, 6, 13, 11, 11, 9, 10, 11, - 7, 6, 1, 9, 8, 10, 8, 5, 4, - 8, 9, 8, 9, 12, 12, 12, 12, 8, - 10, 13, 9, 14, 11, 14, 14, 13, 12, - 9, 10, 9, 13, 12, 11, 13, 14, 11, - 9, 11, 8, 13, 11, 13, 10, 13, 13, - 9, 8, 5, 12, 10, 11, 11, 6, 7, - 8, 7, 3, 8, 9, 11, 10, 7, 4, }, -{ 8, 9, 7, 11, 11, 12, 11, 14, 9, - 8, 6, 6, 11, 13, 10, 9, 11, 9, - 7, 5, 1, 7, 9, 9, 7, 5, 3, - 13, 11, 9, 10, 12, 11, 12, 12, 9, - 10, 11, 9, 13, 9, 12, 12, 12, 10, - 12, 11, 10, 13, 14, 12, 14, 14, 11, - 11, 8, 8, 13, 11, 12, 9, 13, 11, - 9, 10, 5, 11, 8, 11, 9, 6, 7, - 7, 8, 4, 6, 8, 10, 8, 8, 5, }, -{ 8, 10, 8, 13, 13, 13, 12, 11, 10, - 5, 1, 3, 10, 7, 8, 6, 8, 9, - 8, 7, 4, 9, 10, 11, 8, 7, 6, - 8, 9, 7, 9, 12, 11, 12, 10, 8, - 9, 10, 8, 13, 9, 9, 12, 11, 11, - 7, 7, 6, 12, 9, 8, 10, 12, 8, - 6, 7, 4, 12, 8, 13, 6, 9, 10, - 13, 13, 9, 15, 14, 14, 15, 9, 11, - 13, 11, 9, 13, 13, 15, 15, 12, 10, }, -{ 10, 8, 9, 11, 12, 10, 8, 13, 13, - 9, 2, 5, 7, 5, 4, 3, 8, 9, - 11, 5, 5, 9, 8, 8, 6, 8, 8, - 12, 7, 8, 10, 10, 9, 8, 12, 10, - 9, 10, 9, 12, 7, 11, 7, 12, 12, - 9, 5, 8, 9, 9, 6, 6, 11, 10, - 6, 4, 7, 9, 5, 9, 3, 9, 10, - 13, 11, 9, 13, 10, 13, 10, 9, 13, - 14, 11, 10, 12, 12, 13, 11, 14, 11, }, -{ 11, 7, 8, 10, 12, 9, 9, 14, 10, - 9, 4, 7, 8, 10, 7, 7, 11, 10, - 8, 2, 2, 6, 8, 5, 5, 5, 6, - 15, 9, 10, 10, 12, 10, 11, 14, 12, - 9, 8, 9, 12, 9, 11, 8, 12, 11, - 14, 10, 11, 12, 13, 10, 12, 15, 12, - 9, 7, 8, 12, 9, 12, 7, 11, 13, - 9, 6, 5, 11, 10, 11, 7, 6, 9, - 11, 4, 5, 7, 8, 8, 8, 7, 7, }, + { + 5, 5, 5, 5, 3, 6, 6, 8, 8, 8, 8, 6, 4, 7, 7, 9, 9, + 9, 9, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, + 11, 11, 11, 11, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, + 14, 14, 14, 14, 12, 13, 13, 15, 15, 14, 13, 12, 12, 12, 12, 11, 11, + 13, 13, 13, 13, 11, 10, 10, 12, 12, 12, 12, 10, 1, + }, + { + 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 13, 13, 13, 13, 11, 12, 12, 14, 14, 15, 15, 14, + 12, 11, 11, 11, 11, 12, 12, 12, 12, 10, 12, 12, 12, 12, 12, 12, 12, + 12, 9, 9, 11, 11, 11, 11, 9, 6, 6, 6, 6, 5, 5, 7, 7, 9, + 9, 9, 9, 7, 7, 7, 7, 7, 4, 4, 4, 4, 1, + }, + { + 7, 7, 7, 7, 5, 8, 8, 10, 10, 10, 10, 8, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 12, 12, 12, 12, 10, 13, 13, 14, 14, 14, + 14, 13, 13, 13, 13, 12, 12, 12, 12, 10, 10, 10, 10, 11, 11, 11, 11, + 9, 11, 11, 11, 11, 11, 11, 11, 11, 5, 5, 5, 5, 4, 4, 6, 6, + 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 6, 6, 1, + }, + { + 9, 9, 11, 11, 13, 13, 13, 13, 11, 11, 11, 11, 11, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 10, 12, 12, 13, 13, + 15, 15, 14, 13, 12, 12, 12, 12, 10, 10, 10, 10, 7, 7, 9, 9, 9, + 9, 7, 8, 8, 8, 8, 6, 8, 8, 8, 8, 8, 8, 8, 8, 5, 5, + 7, 7, 7, 7, 5, 4, 4, 6, 6, 6, 6, 4, 1, + }, + { + 7, 7, 7, 7, 5, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 12, 12, 10, 13, 13, 13, 13, 13, 13, 13, 13, + 12, 12, 14, 14, 15, 15, 15, 15, 12, 9, 9, 11, 11, 11, 11, 9, 7, + 7, 7, 7, 5, 5, 5, 5, 4, 4, 8, 8, 8, 8, 6, 8, 8, 10, + 10, 10, 10, 10, 10, 10, 10, 8, 8, 8, 8, 4, 1, + }, + { + 2, 2, 7, 7, 7, 7, 5, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, + 12, 12, 13, 13, 14, 14, 13, 10, 10, 10, 10, 9, 9, 11, 11, 11, 11, + 11, 11, 11, 11, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 7, 7, 9, + 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 6, 6, 6, 6, 4, 6, + 6, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 6, 6, + }, + { + 5, 5, 5, 5, 3, 6, 6, 6, 6, 4, 7, 7, 9, 9, 9, 9, 9, + 9, 9, 9, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 11, 11, + 13, 13, 13, 13, 11, 11, 11, 11, 11, 12, 12, 12, 12, 10, 12, 12, 15, + 15, 15, 15, 13, 14, 14, 14, 14, 12, 12, 12, 12, 9, 9, 11, 11, 11, + 11, 9, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 1, + }, + { + 5, 5, 9, 9, 9, 9, 7, 11, 11, 11, 11, 9, 11, 11, 11, 11, 11, + 11, 11, 11, 9, 9, 9, 9, 7, 7, 7, 7, 3, 4, 4, 8, 8, 8, + 8, 6, 10, 10, 10, 10, 10, 10, 10, 10, 14, 14, 14, 14, 12, 13, 13, + 14, 14, 13, 12, 12, 12, 12, 11, 11, 13, 13, 13, 13, 11, 10, 10, 12, + 12, 12, 12, 10, 8, 8, 8, 8, 6, 6, 6, 6, 1, + }, + { + 2, 2, 5, 5, 7, 7, 7, 7, 5, 3, 6, 6, 6, 6, 4, 8, 8, + 10, 10, 10, 10, 10, 10, 10, 10, 8, 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 10, 10, 12, 12, 12, 12, 10, 10, 10, 10, 10, 11, 11, 11, + 11, 11, 11, 11, 11, 12, 12, 14, 14, 14, 14, 12, 12, 12, 12, 12, 11, + 11, 13, 13, 13, 13, 11, 6, 6, 8, 8, 8, 8, 6, + }, + { + 3, 3, 6, 6, 8, 8, 8, 8, 6, 6, 6, 6, 6, 7, 7, 7, 7, + 5, 10, 10, 10, 10, 8, 10, 10, 10, 10, 10, 10, 10, 10, 8, 8, 8, + 8, 9, 9, 9, 9, 7, 13, 13, 13, 13, 11, 12, 12, 13, 13, 14, 14, + 14, 14, 11, 11, 11, 11, 12, 12, 12, 12, 10, 12, 12, 12, 12, 12, 12, + 12, 12, 9, 9, 11, 11, 11, 11, 11, 11, 11, 11, 1, + }, + { + 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 9, 11, 11, 11, 11, + 11, 11, 11, 11, 9, 9, 9, 9, 7, 7, 7, 7, 6, 6, 10, 10, 10, + 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, + 11, 14, 14, 14, 14, 12, 13, 13, 13, 13, 10, 10, 10, 10, 8, 8, 8, + 8, 5, 5, 7, 7, 7, 7, 5, 4, 4, 4, 4, 1, + }, + { + 4, 4, 6, 6, 6, 6, 4, 2, 3, 3, 9, 9, 9, 9, 7, 9, 9, + 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, + 8, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 14, 14, 14, 14, 12, 12, 12, 12, 12, 11, 11, 13, 13, 14, 14, + 13, 11, 8, 8, 10, 10, 10, 10, 8, 5, 5, 5, 5, + }, + { + 5, 5, 9, 9, 9, 9, 7, 9, 9, 11, 11, 11, 11, 11, 11, 11, 11, + 9, 9, 9, 9, 7, 7, 7, 7, 3, 4, 4, 8, 8, 8, 8, 6, 10, + 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, + 13, 13, 13, 13, 13, 13, 12, 12, 13, 13, 14, 14, 14, 14, 10, 10, 12, + 12, 12, 12, 10, 8, 8, 8, 8, 6, 6, 6, 6, 1, + }, + { + 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 8, 8, 8, + 8, 6, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 11, 12, 12, 13, + 13, 14, 14, 14, 14, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 5, 5, + 7, 7, 7, 7, 5, 4, 4, 6, 6, 6, 6, 4, 1, + }, + { + 6, 6, 6, 6, 4, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, + 9, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 13, 13, 14, 14, 13, 13, + 13, 13, 13, 9, 9, 9, 9, 7, 7, 7, 7, 8, 8, 8, 8, 6, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 8, 8, + 8, 8, 2, 3, 3, 5, 5, 7, 7, 7, 7, 5, 3, + }, + { + 5, 5, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 3, + 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11, 11, 11, + 11, 12, 12, 14, 14, 14, 14, 12, 12, 12, 12, 12, 13, 13, 13, 13, 11, + 13, 13, 13, 13, 13, 13, 13, 13, 9, 9, 11, 11, 11, 11, 9, 8, 8, + 10, 10, 10, 10, 10, 10, 10, 10, 6, 6, 6, 6, 1, + }, + { + 5, 5, 5, 5, 3, 6, 6, 6, 6, 4, 7, 7, 9, 9, 9, 9, 9, + 9, 9, 9, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 11, 11, + 11, 11, 9, 11, 11, 11, 11, 11, 11, 11, 11, 9, 9, 9, 9, 10, 10, + 10, 10, 8, 12, 12, 13, 13, 14, 14, 14, 14, 12, 12, 12, 12, 11, 11, + 13, 13, 13, 13, 11, 10, 10, 12, 12, 12, 12, 10, 1, + }, + { + 7, 7, 7, 7, 5, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, + 10, 10, 10, 10, 11, 11, 13, 13, 13, 13, 11, 11, 11, 11, 11, 12, 12, + 12, 12, 10, 13, 13, 14, 14, 15, 15, 15, 15, 13, 13, 13, 13, 12, 12, + 12, 12, 7, 7, 9, 9, 9, 9, 7, 3, 4, 4, 8, 8, 8, 8, 6, + 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 6, 6, 1, + }, + { + 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 13, 13, 14, 14, 13, 13, 13, + 13, 13, 12, 12, 12, 12, 11, 11, 11, 11, 10, 10, 12, 12, 12, 12, 10, + 9, 9, 11, 11, 11, 11, 9, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, + 6, 6, 6, 6, 2, 3, 3, 5, 5, 9, 9, 9, 9, 7, 9, 9, 9, + 9, 9, 9, 9, 9, 7, 7, 7, 7, 5, 5, 5, 5, + }, + { + 2, 2, 7, 7, 7, 7, 5, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, + 7, 7, 7, 7, 5, 5, 5, 5, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 8, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 14, 11, 11, 11, 11, 10, + 10, 12, 12, 12, 12, 12, 12, 12, 12, 9, 9, 11, 11, 11, 11, 9, 8, + 8, 10, 10, 10, 10, 10, 10, 10, 10, 6, 6, 6, 6, + }, }; //@} @@ -428,206 +385,178 @@ #define AIC_MODE1_SIZE 9 #define AIC_MODE1_BITS 7 -static const uint8_t aic_mode1_vlc_codes[AIC_MODE1_NUM][AIC_MODE1_SIZE] = { - { 0x01, 0x01, 0x01, 0x11, 0x00, 0x09, 0x03, 0x10, 0x05,}, - { 0x09, 0x01, 0x01, 0x05, 0x11, 0x00, 0x03, 0x21, 0x20,}, - { 0x01, 0x01, 0x01, 0x11, 0x09, 0x10, 0x05, 0x00, 0x03,}, - { 0x01, 0x01, 0x00, 0x03, 0x21, 0x05, 0x09, 0x20, 0x11,}, - { 0x01, 0x09, 0x00, 0x29, 0x08, 0x15, 0x03, 0x0B, 0x28,}, - { 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x03, 0x02,}, - { 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x01, 0x09, 0x08,}, - { 0x01, 0x01, 0x01, 0x09, 0x01, 0x08, 0x00, 0x03, 0x05,}, - { 0x01, 0x01, 0x01, 0x00, 0x05, 0x11, 0x09, 0x10, 0x03,}, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - - { 0x01, 0x01, 0x01, 0x05, 0x01, 0x00, 0x03, 0x09, 0x08,}, - { 0x09, 0x01, 0x01, 0x05, 0x11, 0x00, 0x03, 0x21, 0x20,}, - { 0x01, 0x01, 0x01, 0x0D, 0x05, 0x04, 0x00, 0x07, 0x0C,}, - { 0x01, 0x01, 0x00, 0x05, 0x11, 0x03, 0x09, 0x21, 0x20,}, - { 0x05, 0x01, 0x01, 0x11, 0x00, 0x09, 0x03, 0x21, 0x20,}, - { 0x09, 0x01, 0x01, 0x00, 0x05, 0x01, 0x03, 0x11, 0x10,}, - { 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x02,}, - { 0x01, 0x01, 0x01, 0x09, 0x00, 0x05, 0x01, 0x03, 0x08,}, - { 0x01, 0x01, 0x01, 0x09, 0x11, 0x05, 0x00, 0x10, 0x03,}, - { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - - { 0x01, 0x00, 0x01, 0x09, 0x08, 0x15, 0x14, 0x0B, 0x03,}, - { 0x0D, 0x01, 0x01, 0x05, 0x0C, 0x04, 0x01, 0x00, 0x07,}, - { 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x03, 0x01, 0x01,}, - { 0x05, 0x01, 0x01, 0x04, 0x19, 0x07, 0x18, 0x0D, 0x00,}, - { 0x11, 0x09, 0x01, 0x21, 0x05, 0x20, 0x01, 0x00, 0x03,}, - { 0x41, 0x01, 0x00, 0x05, 0x40, 0x03, 0x09, 0x21, 0x11,}, - { 0x29, 0x01, 0x00, 0x28, 0x09, 0x15, 0x03, 0x08, 0x0B,}, - { 0x01, 0x00, 0x01, 0x11, 0x09, 0x10, 0x05, 0x01, 0x03,}, - { 0x05, 0x01, 0x01, 0x04, 0x0D, 0x0C, 0x07, 0x00, 0x01,}, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - - { 0x01, 0x00, 0x03, 0x05, 0x11, 0x10, 0x25, 0x24, 0x13,}, - { 0x21, 0x01, 0x01, 0x00, 0x11, 0x03, 0x05, 0x20, 0x09,}, - { 0x01, 0x01, 0x01, 0x00, 0x09, 0x11, 0x10, 0x05, 0x03,}, - { 0x21, 0x05, 0x01, 0x01, 0x09, 0x00, 0x11, 0x20, 0x03,}, - { 0x05, 0x01, 0x00, 0x04, 0x01, 0x19, 0x07, 0x18, 0x0D,}, - { 0x11, 0x01, 0x00, 0x01, 0x09, 0x01, 0x03, 0x10, 0x05,}, - { 0x1D, 0x01, 0x05, 0x0D, 0x0C, 0x04, 0x00, 0x1C, 0x0F,}, - { 0x05, 0x19, 0x01, 0x04, 0x00, 0x18, 0x1B, 0x1A, 0x07,}, - { 0x09, 0x01, 0x00, 0x01, 0x05, 0x03, 0x11, 0x10, 0x01,}, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - - { 0x01, 0x00, 0x03, 0x41, 0x05, 0x40, 0x09, 0x11, 0x21,}, - { 0x05, 0x01, 0x01, 0x19, 0x04, 0x07, 0x00, 0x18, 0x0D,}, - { 0x01, 0x01, 0x01, 0x05, 0x01, 0x04, 0x01, 0x00, 0x03,}, - { 0x01, 0x05, 0x00, 0x0D, 0x01, 0x04, 0x07, 0x19, 0x18,}, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02,}, - { 0x31, 0x01, 0x05, 0x19, 0x04, 0x07, 0x00, 0x30, 0x0D,}, - { 0x01, 0x00, 0x03, 0x11, 0x01, 0x05, 0x01, 0x09, 0x10,}, - { 0x01, 0x05, 0x01, 0x11, 0x01, 0x10, 0x00, 0x03, 0x09,}, - { 0x01, 0x09, 0x00, 0x29, 0x03, 0x08, 0x28, 0x15, 0x0B,}, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - - { 0x01, 0x01, 0x00, 0x09, 0x15, 0x03, 0x08, 0x14, 0x0B,}, - { 0x11, 0x01, 0x01, 0x00, 0x09, 0x01, 0x03, 0x10, 0x05,}, - { 0x01, 0x00, 0x03, 0x25, 0x11, 0x05, 0x10, 0x24, 0x13,}, - { 0x11, 0x01, 0x00, 0x01, 0x09, 0x01, 0x05, 0x10, 0x03,}, - { 0x05, 0x01, 0x00, 0x0D, 0x0C, 0x04, 0x0F, 0x1D, 0x1C,}, - { 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x03, 0x02,}, - { 0x21, 0x01, 0x05, 0x09, 0x11, 0x00, 0x03, 0x41, 0x40,}, - { 0x05, 0x01, 0x00, 0x1D, 0x1C, 0x0D, 0x0C, 0x0F, 0x04,}, - { 0x05, 0x01, 0x00, 0x0D, 0x31, 0x04, 0x19, 0x30, 0x07,}, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - - { 0x01, 0x01, 0x00, 0x21, 0x05, 0x11, 0x03, 0x09, 0x20,}, - { 0x01, 0x01, 0x00, 0x11, 0x03, 0x05, 0x01, 0x09, 0x10,}, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02,}, - { 0x05, 0x01, 0x04, 0x19, 0x07, 0x0D, 0x00, 0x31, 0x30,}, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02,}, - { 0x05, 0x01, 0x01, 0x11, 0x09, 0x00, 0x03, 0x21, 0x20,}, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02,}, - { 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x01, 0x01, 0x02,}, - { 0x09, 0x01, 0x00, 0x29, 0x08, 0x15, 0x03, 0x28, 0x0B,}, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - - { 0x01, 0x01, 0x01, 0x05, 0x01, 0x04, 0x00, 0x01, 0x03,}, - { 0x09, 0x01, 0x00, 0x29, 0x28, 0x15, 0x08, 0x03, 0x0B,}, - { 0x01, 0x00, 0x01, 0x11, 0x05, 0x10, 0x09, 0x01, 0x03,}, - { 0x05, 0x04, 0x01, 0x1D, 0x0D, 0x0C, 0x1C, 0x00, 0x0F,}, - { 0x09, 0x11, 0x01, 0x41, 0x00, 0x40, 0x05, 0x03, 0x21,}, - { 0x0D, 0x05, 0x01, 0x1D, 0x1C, 0x0C, 0x04, 0x00, 0x0F,}, - { 0x41, 0x09, 0x01, 0x40, 0x00, 0x11, 0x05, 0x03, 0x21,}, - { 0x01, 0x01, 0x01, 0x05, 0x01, 0x04, 0x00, 0x01, 0x03,}, - { 0x05, 0x04, 0x01, 0x0D, 0x01, 0x0C, 0x07, 0x01, 0x00,}, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - - { 0x05, 0x04, 0x01, 0x07, 0x19, 0x31, 0x30, 0x0D, 0x00,}, - { 0x21, 0x01, 0x01, 0x00, 0x11, 0x09, 0x20, 0x05, 0x03,}, - { 0x05, 0x01, 0x01, 0x04, 0x07, 0x0D, 0x0C, 0x00, 0x01,}, - { 0x21, 0x09, 0x01, 0x00, 0x20, 0x05, 0x23, 0x22, 0x03,}, - { 0x31, 0x0D, 0x01, 0x19, 0x05, 0x30, 0x04, 0x07, 0x00,}, - { 0x31, 0x05, 0x01, 0x04, 0x19, 0x00, 0x0D, 0x30, 0x07,}, - { 0x31, 0x01, 0x00, 0x0D, 0x05, 0x19, 0x04, 0x30, 0x07,}, - { 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02, 0x01, 0x01,}, - { 0x01, 0x00, 0x01, 0x01, 0x05, 0x09, 0x08, 0x03, 0x01,}, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, -}; - -static const uint8_t aic_mode1_vlc_bits[AIC_MODE1_NUM][AIC_MODE1_SIZE] = { - { 1, 4, 2, 7, 4, 6, 4, 7, 5,}, - { 5, 1, 3, 4, 6, 3, 3, 7, 7,}, - { 1, 4, 2, 7, 6, 7, 5, 4, 4,}, - { 1, 3, 3, 3, 7, 4, 5, 7, 6,}, - { 2, 4, 2, 6, 4, 5, 2, 4, 6,}, - { 7, 2, 3, 4, 7, 1, 5, 7, 7,}, - { 5, 1, 3, 6, 5, 5, 2, 7, 7,}, - { 2, 5, 1, 7, 3, 7, 5, 5, 6,}, - { 2, 4, 1, 4, 5, 7, 6, 7, 4,}, - { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, - - { 2, 1, 3, 6, 5, 5, 5, 7, 7,}, - { 5, 1, 3, 4, 6, 3, 3, 7, 7,}, - { 4, 1, 2, 6, 5, 5, 4, 5, 6,}, - { 3, 1, 3, 4, 6, 3, 5, 7, 7,}, - { 4, 1, 3, 6, 3, 5, 3, 7, 7,}, - { 6, 1, 4, 4, 5, 2, 4, 7, 7,}, - { 7, 1, 5, 7, 4, 3, 2, 7, 7,}, - { 5, 3, 2, 7, 5, 6, 1, 5, 7,}, - { 4, 1, 2, 6, 7, 5, 4, 7, 4,}, - { 1, 0, 1, 0, 0, 0, 0, 0, 0,}, - - { 3, 3, 1, 5, 5, 6, 6, 5, 3,}, - { 6, 2, 1, 5, 6, 5, 4, 4, 5,}, - { 6, 4, 1, 7, 6, 7, 6, 3, 2,}, - { 4, 3, 1, 4, 6, 4, 6, 5, 3,}, - { 6, 5, 1, 7, 4, 7, 3, 3, 3,}, - { 7, 2, 2, 3, 7, 2, 4, 6, 5,}, - { 6, 2, 2, 6, 4, 5, 2, 4, 4,}, - { 4, 4, 1, 7, 6, 7, 5, 2, 4,}, - { 5, 4, 1, 5, 6, 6, 5, 4, 2,}, - { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, - - { 2, 2, 2, 3, 5, 5, 6, 6, 5,}, - { 7, 1, 3, 3, 6, 3, 4, 7, 5,}, - { 2, 4, 1, 4, 6, 7, 7, 5, 4,}, - { 7, 4, 3, 1, 5, 3, 6, 7, 3,}, - { 4, 3, 3, 4, 1, 6, 4, 6, 5,}, - { 7, 4, 4, 2, 6, 1, 4, 7, 5,}, - { 5, 2, 3, 4, 4, 3, 2, 5, 4,}, - { 3, 5, 2, 3, 2, 5, 5, 5, 3,}, - { 6, 4, 4, 2, 5, 4, 7, 7, 1,}, - { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, - - { 2, 2, 2, 7, 3, 7, 4, 5, 6,}, - { 4, 1, 3, 6, 4, 4, 3, 6, 5,}, - { 2, 4, 1, 7, 3, 7, 6, 6, 6,}, - { 3, 4, 3, 5, 1, 4, 4, 6, 6,}, - { 4, 5, 2, 7, 1, 7, 3, 7, 7,}, - { 6, 2, 3, 5, 3, 3, 2, 6, 4,}, - { 4, 4, 4, 7, 2, 5, 1, 6, 7,}, - { 4, 5, 2, 7, 1, 7, 4, 4, 6,}, - { 2, 4, 2, 6, 2, 4, 6, 5, 4,}, - { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, - - { 1, 3, 3, 5, 6, 3, 5, 6, 5,}, - { 7, 1, 4, 4, 6, 2, 4, 7, 5,}, - { 2, 2, 2, 6, 5, 3, 5, 6, 5,}, - { 7, 4, 4, 2, 6, 1, 5, 7, 4,}, - { 3, 2, 2, 4, 4, 3, 4, 5, 5,}, - { 7, 2, 5, 3, 7, 1, 4, 7, 7,}, - { 6, 2, 3, 4, 5, 2, 2, 7, 7,}, - { 3, 2, 2, 5, 5, 4, 4, 4, 3,}, - { 3, 2, 2, 4, 6, 3, 5, 6, 3,}, - { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, - - { 1, 3, 3, 7, 4, 6, 3, 5, 7,}, - { 4, 1, 4, 7, 4, 5, 2, 6, 7,}, - { 2, 4, 1, 7, 5, 7, 3, 7, 7,}, - { 3, 2, 3, 5, 3, 4, 2, 6, 6,}, - { 3, 5, 4, 7, 2, 7, 1, 7, 7,}, - { 4, 1, 3, 6, 5, 3, 3, 7, 7,}, - { 4, 2, 5, 7, 3, 7, 1, 7, 7,}, - { 7, 4, 1, 7, 3, 7, 2, 5, 7,}, - { 4, 2, 2, 6, 4, 5, 2, 6, 4,}, - { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, - - { 3, 4, 1, 7, 6, 7, 6, 2, 6,}, - { 4, 2, 2, 6, 6, 5, 4, 2, 4,}, - { 4, 4, 1, 7, 5, 7, 6, 2, 4,}, - { 3, 3, 2, 5, 4, 4, 5, 2, 4,}, - { 4, 5, 2, 7, 2, 7, 3, 2, 6,}, - { 4, 3, 2, 5, 5, 4, 3, 2, 4,}, - { 7, 4, 2, 7, 2, 5, 3, 2, 6,}, - { 4, 6, 2, 7, 3, 7, 6, 1, 6,}, - { 5, 5, 1, 6, 4, 6, 5, 2, 4,}, - { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, - - { 3, 3, 2, 3, 5, 6, 6, 4, 2,}, - { 7, 1, 3, 3, 6, 5, 7, 4, 3,}, - { 5, 4, 1, 5, 5, 6, 6, 4, 2,}, - { 6, 4, 2, 2, 6, 3, 6, 6, 2,}, - { 6, 4, 2, 5, 3, 6, 3, 3, 2,}, - { 6, 3, 2, 3, 5, 2, 4, 6, 3,}, - { 6, 2, 2, 4, 3, 5, 3, 6, 3,}, - { 7, 5, 1, 7, 4, 7, 7, 3, 2,}, - { 5, 5, 2, 3, 6, 7, 7, 5, 1,}, - { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, +static const uint8_t aic_mode1_vlc_tabs[AIC_MODE1_NUM][AIC_MODE1_SIZE][2] = { + { { 4, 4 }, { 1, 4 }, { 7, 7 }, { 3, 7 }, { 5, 6 }, + { 8, 5 }, { 6, 4 }, { 2, 2 }, { 0, 1 } }, + { { 5, 3 }, { 2, 3 }, { 8, 7 }, { 7, 7 }, { 4, 6 }, + { 0, 5 }, { 3, 4 }, { 6, 3 }, { 1, 1 } }, + { { 7, 4 }, { 1, 4 }, { 5, 7 }, { 3, 7 }, { 4, 6 }, + { 6, 5 }, { 8, 4 }, { 2, 2 }, { 0, 1 } }, + { { 2, 3 }, { 1, 3 }, { 7, 7 }, { 4, 7 }, { 8, 6 }, + { 6, 5 }, { 5, 4 }, { 3, 3 }, { 0, 1 } }, + { { 2, 2 }, { 0, 2 }, { 4, 4 }, { 1, 4 }, { 8, 6 }, + { 3, 6 }, { 5, 5 }, { 7, 4 }, { 6, 2 } }, + { { 4, 7 }, { 0, 7 }, { 8, 7 }, { 7, 7 }, { 6, 5 }, + { 3, 4 }, { 2, 3 }, { 1, 2 }, { 5, 1 } }, + { { 4, 5 }, { 0, 5 }, { 8, 7 }, { 7, 7 }, { 3, 6 }, + { 5, 5 }, { 2, 3 }, { 6, 2 }, { 1, 1 } }, + { { 6, 5 }, { 1, 5 }, { 5, 7 }, { 3, 7 }, { 8, 6 }, + { 7, 5 }, { 4, 3 }, { 0, 2 }, { 2, 1 } }, + { { 3, 4 }, { 1, 4 }, { 7, 7 }, { 5, 7 }, { 6, 6 }, + { 4, 5 }, { 8, 4 }, { 0, 2 }, { 2, 1 } }, + { { 0 } }, /* unused */ + { { 5, 5 }, { 4, 5 }, { 8, 7 }, { 7, 7 }, { 3, 6 }, + { 6, 5 }, { 2, 3 }, { 0, 2 }, { 1, 1 } }, + { { 5, 3 }, { 2, 3 }, { 8, 7 }, { 7, 7 }, { 4, 6 }, + { 0, 5 }, { 3, 4 }, { 6, 3 }, { 1, 1 } }, + { { 6, 4 }, { 0, 4 }, { 5, 5 }, { 4, 5 }, { 8, 6 }, + { 3, 6 }, { 7, 5 }, { 2, 2 }, { 1, 1 } }, + { { 2, 3 }, { 0, 3 }, { 8, 7 }, { 7, 7 }, { 4, 6 }, + { 6, 5 }, { 3, 4 }, { 5, 3 }, { 1, 1 } }, + { { 4, 3 }, { 2, 3 }, { 8, 7 }, { 7, 7 }, { 3, 6 }, + { 5, 5 }, { 0, 4 }, { 6, 3 }, { 1, 1 } }, + { { 3, 4 }, { 2, 4 }, { 8, 7 }, { 7, 7 }, { 0, 6 }, + { 4, 5 }, { 6, 4 }, { 5, 2 }, { 1, 1 } }, + { { 3, 7 }, { 0, 7 }, { 8, 7 }, { 7, 7 }, { 2, 5 }, + { 4, 4 }, { 5, 3 }, { 6, 2 }, { 1, 1 } }, + { { 4, 5 }, { 0, 5 }, { 8, 7 }, { 3, 7 }, { 5, 6 }, + { 7, 5 }, { 1, 3 }, { 2, 2 }, { 6, 1 } }, + { { 6, 4 }, { 0, 4 }, { 7, 7 }, { 4, 7 }, { 3, 6 }, + { 5, 5 }, { 8, 4 }, { 2, 2 }, { 1, 1 } }, + { { 2, 1 }, { 0, 1 } }, /* Unused */ + { { 1, 3 }, { 0, 3 }, { 4, 5 }, { 3, 5 }, { 6, 6 }, + { 5, 6 }, { 7, 5 }, { 8, 3 }, { 2, 1 } }, + { { 7, 4 }, { 6, 4 }, { 5, 5 }, { 3, 5 }, { 4, 6 }, + { 0, 6 }, { 8, 5 }, { 1, 2 }, { 2, 1 } }, + { { 4, 6 }, { 0, 6 }, { 5, 7 }, { 3, 7 }, { 6, 6 }, + { 1, 4 }, { 7, 3 }, { 8, 2 }, { 2, 1 } }, + { { 8, 3 }, { 1, 3 }, { 3, 4 }, { 0, 4 }, { 6, 6 }, + { 4, 6 }, { 7, 5 }, { 5, 4 }, { 2, 1 } }, + { { 7, 3 }, { 6, 3 }, { 5, 7 }, { 3, 7 }, { 0, 6 }, + { 1, 5 }, { 4, 4 }, { 8, 3 }, { 2, 1 } }, + { { 2, 2 }, { 1, 2 }, { 4, 7 }, { 0, 7 }, { 7, 6 }, + { 8, 5 }, { 6, 4 }, { 3, 3 }, { 5, 2 } }, + { { 2, 2 }, { 1, 2 }, { 7, 4 }, { 4, 4 }, { 3, 6 }, + { 0, 6 }, { 5, 5 }, { 8, 4 }, { 6, 2 } }, + { { 1, 4 }, { 0, 4 }, { 5, 7 }, { 3, 7 }, { 4, 6 }, + { 6, 5 }, { 8, 4 }, { 7, 2 }, { 2, 1 } }, + { { 7, 4 }, { 1, 4 }, { 3, 5 }, { 0, 5 }, { 5, 6 }, + { 4, 6 }, { 6, 5 }, { 8, 2 }, { 2, 1 } }, + { { 0 } }, /* unused */ + { { 1, 2 }, { 0, 2 }, { 5, 5 }, { 4, 5 }, { 7, 6 }, + { 6, 6 }, { 8, 5 }, { 3, 3 }, { 2, 2 } }, + { { 3, 3 }, { 2, 3 }, { 7, 7 }, { 0, 7 }, { 4, 6 }, + { 8, 5 }, { 6, 4 }, { 5, 3 }, { 1, 1 } }, + { { 3, 4 }, { 1, 4 }, { 6, 7 }, { 5, 7 }, { 4, 6 }, + { 7, 5 }, { 8, 4 }, { 0, 2 }, { 2, 1 } }, + { { 5, 3 }, { 2, 3 }, { 7, 7 }, { 0, 7 }, { 6, 6 }, + { 4, 5 }, { 1, 4 }, { 8, 3 }, { 3, 1 } }, + { { 2, 3 }, { 1, 3 }, { 3, 4 }, { 0, 4 }, { 7, 6 }, + { 5, 6 }, { 8, 5 }, { 6, 4 }, { 4, 1 } }, + { { 2, 4 }, { 1, 4 }, { 7, 7 }, { 0, 7 }, { 4, 6 }, + { 8, 5 }, { 6, 4 }, { 3, 2 }, { 5, 1 } }, + { { 6, 2 }, { 1, 2 }, { 5, 3 }, { 2, 3 }, { 4, 4 }, + { 3, 4 }, { 7, 5 }, { 0, 5 }, { 8, 4 } }, + { { 4, 2 }, { 2, 2 }, { 3, 3 }, { 0, 3 }, { 5, 5 }, + { 1, 5 }, { 7, 5 }, { 6, 5 }, { 8, 3 } }, + { { 2, 4 }, { 1, 4 }, { 7, 7 }, { 6, 7 }, { 0, 6 }, + { 4, 5 }, { 5, 4 }, { 3, 2 }, { 8, 1 } }, + { { 0 } }, /* unused */ + { { 1, 2 }, { 0, 2 }, { 5, 7 }, { 3, 7 }, { 8, 6 }, + { 7, 5 }, { 6, 4 }, { 4, 3 }, { 2, 2 } }, + { { 6, 3 }, { 2, 3 }, { 4, 4 }, { 0, 4 }, { 7, 6 }, + { 3, 6 }, { 8, 5 }, { 5, 4 }, { 1, 1 } }, + { { 7, 6 }, { 6, 6 }, { 5, 7 }, { 3, 7 }, { 8, 6 }, + { 1, 4 }, { 4, 3 }, { 0, 2 }, { 2, 1 } }, + { { 2, 3 }, { 0, 3 }, { 5, 4 }, { 1, 4 }, { 8, 6 }, + { 7, 6 }, { 3, 5 }, { 6, 4 }, { 4, 1 } }, + { { 5, 7 }, { 3, 7 }, { 8, 7 }, { 7, 7 }, { 1, 5 }, + { 0, 4 }, { 6, 3 }, { 2, 2 }, { 4, 1 } }, + { { 6, 2 }, { 1, 2 }, { 4, 3 }, { 2, 3 }, { 7, 6 }, + { 0, 6 }, { 3, 5 }, { 8, 4 }, { 5, 3 } }, + { { 1, 4 }, { 0, 4 }, { 8, 7 }, { 3, 7 }, { 7, 6 }, + { 5, 5 }, { 2, 4 }, { 4, 2 }, { 6, 1 } }, + { { 6, 4 }, { 0, 4 }, { 5, 7 }, { 3, 7 }, { 8, 6 }, + { 1, 5 }, { 7, 4 }, { 2, 2 }, { 4, 1 } }, + { { 2, 2 }, { 0, 2 }, { 5, 4 }, { 1, 4 }, { 6, 6 }, + { 3, 6 }, { 7, 5 }, { 8, 4 }, { 4, 2 } }, + { { 0 } }, /* unused */ + { { 2, 3 }, { 1, 3 }, { 6, 5 }, { 3, 5 }, { 7, 6 }, + { 4, 6 }, { 8, 5 }, { 5, 3 }, { 0, 1 } }, + { { 3, 4 }, { 2, 4 }, { 7, 7 }, { 0, 7 }, { 4, 6 }, + { 8, 5 }, { 6, 4 }, { 5, 2 }, { 1, 1 } }, + { { 1, 2 }, { 0, 2 }, { 6, 5 }, { 4, 5 }, { 7, 6 }, + { 3, 6 }, { 8, 5 }, { 5, 3 }, { 2, 2 } }, + { { 2, 4 }, { 1, 4 }, { 7, 7 }, { 0, 7 }, { 4, 6 }, + { 6, 5 }, { 8, 4 }, { 3, 2 }, { 5, 1 } }, + { { 2, 2 }, { 1, 2 }, { 5, 3 }, { 0, 3 }, { 4, 4 }, + { 3, 4 }, { 8, 5 }, { 7, 5 }, { 6, 4 } }, + { { 4, 7 }, { 0, 7 }, { 8, 7 }, { 7, 7 }, { 2, 5 }, + { 6, 4 }, { 3, 3 }, { 1, 2 }, { 5, 1 } }, + { { 5, 2 }, { 1, 2 }, { 8, 7 }, { 7, 7 }, { 0, 6 }, + { 4, 5 }, { 3, 4 }, { 2, 3 }, { 6, 2 } }, + { { 2, 2 }, { 1, 2 }, { 8, 3 }, { 0, 3 }, { 6, 4 }, + { 5, 4 }, { 4, 5 }, { 3, 5 }, { 7, 4 } }, + { { 2, 2 }, { 1, 2 }, { 5, 3 }, { 0, 3 }, { 7, 6 }, + { 4, 6 }, { 6, 5 }, { 3, 4 }, { 8, 3 } }, + { { 0 } }, /* unused */ + { { 2, 3 }, { 1, 3 }, { 8, 7 }, { 3, 7 }, { 5, 6 }, + { 7, 5 }, { 4, 4 }, { 6, 3 }, { 0, 1 } }, + { { 2, 4 }, { 0, 4 }, { 8, 7 }, { 3, 7 }, { 7, 6 }, + { 5, 5 }, { 4, 4 }, { 6, 2 }, { 1, 1 } }, + { { 5, 7 }, { 3, 7 }, { 8, 7 }, { 7, 7 }, { 4, 5 }, + { 1, 4 }, { 6, 3 }, { 0, 2 }, { 2, 1 } }, + { { 6, 2 }, { 1, 2 }, { 2, 3 }, { 0, 3 }, { 8, 6 }, + { 7, 6 }, { 3, 5 }, { 5, 4 }, { 4, 3 } }, + { { 5, 7 }, { 3, 7 }, { 8, 7 }, { 7, 7 }, { 1, 5 }, + { 2, 4 }, { 0, 3 }, { 4, 2 }, { 6, 1 } }, + { { 5, 3 }, { 2, 3 }, { 8, 7 }, { 7, 7 }, { 3, 6 }, + { 4, 5 }, { 0, 4 }, { 6, 3 }, { 1, 1 } }, + { { 5, 7 }, { 3, 7 }, { 8, 7 }, { 7, 7 }, { 2, 5 }, + { 0, 4 }, { 4, 3 }, { 1, 2 }, { 6, 1 } }, + { { 3, 7 }, { 0, 7 }, { 8, 7 }, { 5, 7 }, { 7, 5 }, + { 1, 4 }, { 4, 3 }, { 6, 2 }, { 2, 1 } }, + { { 2, 2 }, { 1, 2 }, { 4, 4 }, { 0, 4 }, { 7, 6 }, + { 3, 6 }, { 5, 5 }, { 8, 4 }, { 6, 2 } }, + { { 0 } }, /* unused */ + { { 6, 6 }, { 4, 6 }, { 5, 7 }, { 3, 7 }, { 8, 6 }, + { 1, 4 }, { 0, 3 }, { 7, 2 }, { 2, 1 } }, + { { 2, 2 }, { 1, 2 }, { 6, 4 }, { 0, 4 }, { 4, 6 }, + { 3, 6 }, { 5, 5 }, { 8, 4 }, { 7, 2 } }, + { { 1, 4 }, { 0, 4 }, { 5, 7 }, { 3, 7 }, { 6, 6 }, + { 4, 5 }, { 8, 4 }, { 7, 2 }, { 2, 1 } }, + { { 7, 2 }, { 2, 2 }, { 1, 3 }, { 0, 3 }, { 5, 4 }, + { 4, 4 }, { 6, 5 }, { 3, 5 }, { 8, 4 } }, + { { 4, 2 }, { 2, 2 }, { 5, 7 }, { 3, 7 }, { 8, 6 }, + { 1, 5 }, { 0, 4 }, { 6, 3 }, { 7, 2 } }, + { { 7, 2 }, { 2, 2 }, { 6, 3 }, { 1, 3 }, { 5, 4 }, + { 0, 4 }, { 4, 5 }, { 3, 5 }, { 8, 4 } }, + { { 4, 2 }, { 2, 2 }, { 3, 7 }, { 0, 7 }, { 8, 6 }, + { 5, 5 }, { 1, 4 }, { 6, 3 }, { 7, 2 } }, + { { 6, 6 }, { 1, 6 }, { 5, 7 }, { 3, 7 }, { 8, 6 }, + { 0, 4 }, { 4, 3 }, { 2, 2 }, { 7, 1 } }, + { { 8, 4 }, { 4, 4 }, { 1, 5 }, { 0, 5 }, { 5, 6 }, + { 3, 6 }, { 6, 5 }, { 7, 2 }, { 2, 1 } }, + { { 0 } }, /* unused */ + { { 8, 2 }, { 2, 2 }, { 1, 3 }, { 0, 3 }, { 6, 6 }, + { 5, 6 }, { 4, 5 }, { 7, 4 }, { 3, 3 } }, + { { 3, 3 }, { 2, 3 }, { 6, 7 }, { 0, 7 }, { 4, 6 }, + { 5, 5 }, { 7, 4 }, { 8, 3 }, { 1, 1 } }, + { { 7, 4 }, { 1, 4 }, { 3, 5 }, { 0, 5 }, { 6, 6 }, + { 5, 6 }, { 4, 5 }, { 8, 2 }, { 2, 1 } }, + { { 3, 2 }, { 2, 2 }, { 4, 6 }, { 0, 6 }, { 7, 6 }, + { 6, 6 }, { 1, 4 }, { 5, 3 }, { 8, 2 } }, + { { 8, 2 }, { 2, 2 }, { 6, 3 }, { 4, 3 }, { 5, 6 }, + { 0, 6 }, { 3, 5 }, { 1, 4 }, { 7, 3 } }, + { { 5, 2 }, { 2, 2 }, { 3, 3 }, { 1, 3 }, { 7, 6 }, + { 0, 6 }, { 4, 5 }, { 6, 4 }, { 8, 3 } }, + { { 2, 2 }, { 1, 2 }, { 6, 3 }, { 4, 3 }, { 7, 6 }, + { 0, 6 }, { 5, 5 }, { 3, 4 }, { 8, 3 } }, + { { 3, 7 }, { 0, 7 }, { 6, 7 }, { 5, 7 }, { 1, 5 }, + { 4, 4 }, { 7, 3 }, { 8, 2 }, { 2, 1 } }, + { { 1, 5 }, { 0, 5 }, { 6, 7 }, { 5, 7 }, { 4, 6 }, + { 7, 5 }, { 3, 3 }, { 2, 2 }, { 8, 1 } }, + { { 0 } }, /* unused */ }; //@} @@ -640,31 +569,23 @@ #define PTYPE_VLC_SIZE 8 #define PTYPE_VLC_BITS 7 -static const uint8_t ptype_vlc_codes[NUM_PTYPE_VLCS][PTYPE_VLC_SIZE] = { - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, - { 0x0D, 0x05, 0x01, 0x04, 0x01, 0x00, 0x07, 0x0C }, - { 0x09, 0x11, 0x01, 0x00, 0x05, 0x03, 0x21, 0x20 }, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 } -}; - -static const uint8_t ptype_vlc_bits[NUM_PTYPE_VLCS][PTYPE_VLC_SIZE] = { - { 1, 2, 3, 6, 5, 4, 7, 7 }, - { 3, 1, 2, 7, 6, 5, 4, 7 }, - { 5, 4, 1, 4, 3, 3, 4, 5 }, - { 4, 5, 2, 2, 3, 2, 6, 6 }, - { 5, 6, 1, 4, 2, 3, 7, 7 }, - { 5, 6, 1, 4, 3, 2, 7, 7 }, - { 6, 3, 2, 7, 5, 4, 1, 7 } +static const uint8_t ptype_vlc_tabs[NUM_PTYPE_VLCS][PTYPE_VLC_SIZE][2] = { + { { PBTYPE_ESCAPE, 7 }, { 11, 7 }, { 3, 6 }, { 8, 5 }, + { 9, 4 }, { 2, 3 }, { 1, 2 }, { 0, 1 } }, + { { PBTYPE_ESCAPE, 7 }, { 3, 7 }, { 8, 6 }, { 9, 5 }, + { 11, 4 }, { 0, 3 }, { 2, 2 }, { 1, 1 } }, + { { 9, 3 }, { 8, 3 }, { 3, 4 }, { 1, 4 }, { PBTYPE_ESCAPE, 5 }, + { 0, 5 }, { 11, 4 }, { 2, 1 } }, + { { 3, 2 }, { 2, 2 }, { PBTYPE_ESCAPE, 6 }, { 11, 6 }, + { 1, 5 }, { 0, 4 }, { 8, 3 }, { 9, 2 } }, + { { PBTYPE_ESCAPE, 7 }, { 11, 7 }, { 1, 6 }, { 0, 5 }, + { 3, 4 }, { 9, 3 }, { 8, 2 }, { 2, 1 } }, + { { PBTYPE_ESCAPE, 7 }, { 11, 7 }, { 1, 6 }, { 0, 5 }, + { 3, 4 }, { 8, 3 }, { 9, 2 }, { 2, 1 } }, + { { PBTYPE_ESCAPE, 7 }, { 3, 7 }, { 0, 6 }, { 8, 5 }, + { 9, 4 }, { 1, 3 }, { 2, 2 }, { 11, 1 } }, }; -static const uint8_t ptype_vlc_syms[PTYPE_VLC_SIZE] = { - 0, 1, 2, 3, 8, 9, 11, PBTYPE_ESCAPE -}; - -/** reverse of ptype_vlc_syms */ static const uint8_t block_num_to_ptype_vlc_num[12] = { 0, 1, 2, 3, 0, 0, 2, 0, 4, 5, 0, 6 }; @@ -676,29 +597,21 @@ #define BTYPE_VLC_SIZE 7 #define BTYPE_VLC_BITS 6 -static const uint8_t btype_vlc_codes[NUM_BTYPE_VLCS][BTYPE_VLC_SIZE] = { - { 0x01, 0x05, 0x00, 0x03, 0x11, 0x09, 0x10 }, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, - { 0x09, 0x01, 0x00, 0x01, 0x05, 0x03, 0x08 }, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 } -}; - -static const uint8_t btype_vlc_bits[NUM_BTYPE_VLCS][PTYPE_VLC_SIZE] = { - { 2, 3, 2, 2, 5, 4, 5 }, - { 4, 1, 3, 2, 6, 5, 6 }, - { 6, 4, 1, 2, 5, 3, 6 }, - { 5, 3, 3, 1, 4, 3, 5 }, - { 6, 5, 3, 2, 4, 1, 6 }, - { 6, 5, 3, 1, 4, 2, 6 } -}; - -static const uint8_t btype_vlc_syms[BTYPE_VLC_SIZE] = { - 0, 1, 4, 5, 10, 7, PBTYPE_ESCAPE +static const uint8_t btype_vlc_tabs[NUM_BTYPE_VLCS][BTYPE_VLC_SIZE][2] = { + { { 4, 2 }, { 0, 2 }, { PBTYPE_ESCAPE, 5 }, + { 10, 5 }, { 7, 4 }, { 1, 3 }, { 5, 2 } }, + { { PBTYPE_ESCAPE, 6 }, { 10, 6 }, { 7, 5 }, + { 0, 4 }, { 4, 3 }, { 5, 2 }, { 1, 1 } }, + { { PBTYPE_ESCAPE, 6 }, { 0, 6 }, { 10, 5 }, + { 1, 4 }, { 7, 3 }, { 5, 2 }, { 4, 1 } }, + { { 4, 3 }, { 1, 3 }, { PBTYPE_ESCAPE, 5 }, + { 0, 5 }, { 10, 4 }, { 7, 3 }, { 5, 1 } }, + { { PBTYPE_ESCAPE, 6 }, { 0, 6 }, { 1, 5 }, + { 10, 4 }, { 4, 3 }, { 5, 2 }, { 7, 1 } }, + { { PBTYPE_ESCAPE, 6 }, { 0, 6 }, { 1, 5 }, + { 10, 4 }, { 4, 3 }, { 7, 2 }, { 5, 1 } }, }; -/** reverse of btype_vlc_syms */ static const uint8_t block_num_to_btype_vlc_num[12] = { 0, 1, 0, 0, 2, 3, 0, 5, 0, 0, 4, 0 }; diff -Nru ffmpeg-4.2.2/libavcodec/s302m.c ffmpeg-4.4/libavcodec/s302m.c --- ffmpeg-4.2.2/libavcodec/s302m.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/s302m.c 2021-04-08 21:28:39.000000000 +0000 @@ -225,6 +225,7 @@ .id = AV_CODEC_ID_S302M, .priv_data_size = sizeof(S302Context), .decode = s302m_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, .priv_class = &s302m_class, }; diff -Nru ffmpeg-4.2.2/libavcodec/sbcdec.c ffmpeg-4.4/libavcodec/sbcdec.c --- ffmpeg-4.2.2/libavcodec/sbcdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sbcdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,10 +30,10 @@ * SBC decoder implementation */ -#include #include "avcodec.h" #include "internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #include "sbc.h" #include "sbcdec_data.h" @@ -324,6 +324,8 @@ SBCDecContext *sbc = avctx->priv_data; int i, ch; + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + sbc->frame.crc_ctx = av_crc_get_table(AV_CRC_8_EBU); memset(sbc->dsp.V, 0, sizeof(sbc->dsp.V)); @@ -348,9 +350,8 @@ if (frame_length <= 0) return frame_length; - avctx->channels = - frame->channels = sbc->frame.channels; - frame->format = AV_SAMPLE_FMT_S16P; + avctx->channels = sbc->frame.channels; + frame->nb_samples = sbc->frame.blocks * sbc->frame.subbands; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; @@ -370,7 +371,7 @@ .priv_data_size = sizeof(SBCDecContext), .init = sbc_decode_init, .decode = sbc_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, 0}, diff -Nru ffmpeg-4.2.2/libavcodec/sbcdsp_data.c ffmpeg-4.4/libavcodec/sbcdsp_data.c --- ffmpeg-4.2.2/libavcodec/sbcdsp_data.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sbcdsp_data.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,8 @@ * miscellaneous SBC tables */ +#include "libavutil/mem_internal.h" + #include "sbcdsp_data.h" #define F_PROTO(x) ((int32_t) (((x) * 2) * ((int32_t) 1 << 15) + 0.5)) diff -Nru ffmpeg-4.2.2/libavcodec/sbcdsp.h ffmpeg-4.4/libavcodec/sbcdsp.h --- ffmpeg-4.2.2/libavcodec/sbcdsp.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sbcdsp.h 2021-04-08 21:28:39.000000000 +0000 @@ -32,6 +32,8 @@ #ifndef AVCODEC_SBCDSP_H #define AVCODEC_SBCDSP_H +#include "libavutil/mem_internal.h" + #include "sbc.h" #include "sbcdsp_data.h" diff -Nru ffmpeg-4.2.2/libavcodec/sbcenc.c ffmpeg-4.4/libavcodec/sbcenc.c --- ffmpeg-4.2.2/libavcodec/sbcenc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sbcenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -30,7 +30,6 @@ * SBC encoder implementation */ -#include #include "libavutil/opt.h" #include "avcodec.h" #include "internal.h" @@ -95,7 +94,7 @@ * Returns the length of the packed frame. */ static size_t sbc_pack_frame(AVPacket *avpkt, struct sbc_frame *frame, - int joint, bool msbc) + int joint, int msbc) { PutBitContext pb; @@ -331,6 +330,7 @@ OFFSET(max_delay), AV_OPT_TYPE_DURATION, {.i64 = 13000}, 1000,13000, AE }, { "msbc", "use mSBC mode (wideband speech mono SBC)", OFFSET(msbc), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AE }, + FF_AVCTX_PROFILE_OPTION("msbc", NULL, AUDIO, FF_PROFILE_SBC_MSBC) { NULL }, }; diff -Nru ffmpeg-4.2.2/libavcodec/sbc.h ffmpeg-4.4/libavcodec/sbc.h --- ffmpeg-4.2.2/libavcodec/sbc.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sbc.h 2021-04-08 21:28:39.000000000 +0000 @@ -35,6 +35,7 @@ #include "avcodec.h" #include "libavutil/crc.h" +#include "libavutil/mem_internal.h" #define MSBC_BLOCKS 15 diff -Nru ffmpeg-4.2.2/libavcodec/sbc_parser.c ffmpeg-4.4/libavcodec/sbc_parser.c --- ffmpeg-4.2.2/libavcodec/sbc_parser.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sbc_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -42,7 +42,6 @@ if (data[0] == MSBC_SYNCWORD && data[1] == 0 && data[2] == 0) { avctx->channels = 1; - avctx->sample_fmt = AV_SAMPLE_FMT_S16; avctx->sample_rate = 16000; avctx->frame_size = 120; s->duration = avctx->frame_size; @@ -66,7 +65,6 @@ + (joint * subbands)) + 7) / 8; avctx->channels = channels; - avctx->sample_fmt = AV_SAMPLE_FMT_S16; avctx->sample_rate = sample_rates[sr]; avctx->frame_size = subbands * blocks; s->duration = avctx->frame_size; diff -Nru ffmpeg-4.2.2/libavcodec/sbr.h ffmpeg-4.4/libavcodec/sbr.h --- ffmpeg-4.2.2/libavcodec/sbr.h 2018-07-17 09:27:41.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sbr.h 2021-04-08 21:28:39.000000000 +0000 @@ -30,6 +30,9 @@ #define AVCODEC_SBR_H #include + +#include "libavutil/mem_internal.h" + #include "fft.h" #include "aacps.h" #include "sbrdsp.h" diff -Nru ffmpeg-4.2.2/libavcodec/scpr3.c ffmpeg-4.4/libavcodec/scpr3.c --- ffmpeg-4.2.2/libavcodec/scpr3.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/scpr3.c 2021-04-08 21:28:39.000000000 +0000 @@ -234,6 +234,8 @@ } p = (e + 127) >> 7; k = ((f + e - 1) >> 7) + 1; + if (k > FF_ARRAY_ELEMS(n.dectab)) + return AVERROR_INVALIDDATA; for (i = 0; i < k - p; i++) n.dectab[p + i] = j; e += f; @@ -522,32 +524,16 @@ static int update_model1_to_5(PixelModel3 *m, uint32_t val) { - PixelModel3 n = {0}; int i, size, freqs; uint32_t a; + update_model1_to_4(m, val); size = m->size; - n.size = size; - for (i = 0; i < size; i++) { - n.symbols[i] = m->symbols[i]; - } - AV_QSORT(n.symbols, size, uint8_t, cmpbytes); - size = n.size; - for (i = 0; i < size; i++) { - if (val == n.symbols[i]) { - n.freqs[i] = 100; - n.maxpos = i; - } else { - n.freqs[i] = 50; - } - } a = 256 - size; for (i = 0; i < size; i++, a += freqs) - freqs = n.freqs[i]; - n.type = 5; - n.cntsum = a; - - memcpy(m, &n, sizeof(n)); + freqs = m->freqs[i]; + m->type = 5; + m->cntsum = a; return 0; } @@ -702,7 +688,11 @@ e = d; n.cntsum += n.cnts[e]; n.freqs1[e] = c; - for (g = n.freqs[e], q = c + 128 - 1 >> 7, f = (c + g - 1 >> 7) + 1; q < f; q++) { + g = n.freqs[e]; + f = (c + g - 1 >> 7) + 1; + if (f > FF_ARRAY_ELEMS(n.dectab)) + return AVERROR_INVALIDDATA; + for (q = c + 128 - 1 >> 7; q < f; q++) { n.dectab[q] = e; } c += g; @@ -837,6 +827,7 @@ uint16_t a = 0, b = 0; uint32_t param; int type; + int ret; type = m->type; switch (type) { @@ -859,7 +850,9 @@ break; case 3: *value = bytestream2_get_byte(&s->gb); - decode_static3(m, *value); + ret = decode_static3(m, *value); + if (ret < 0) + return AVERROR_INVALIDDATA; sync_code3(gb, rc); break; case 4: @@ -877,7 +870,9 @@ break; case 6: if (!decode_adaptive6(m, code, value, &a, &b)) { - update_model6_to_7(m); + ret = update_model6_to_7(m); + if (ret < 0) + return AVERROR_INVALIDDATA; } decode3(gb, rc, a, b); sync_code3(gb, rc); diff -Nru ffmpeg-4.2.2/libavcodec/scpr.c ffmpeg-4.4/libavcodec/scpr.c --- ffmpeg-4.2.2/libavcodec/scpr.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/scpr.c 2020-07-11 10:39:30.000000000 +0000 @@ -504,7 +504,7 @@ return ret; } - if ((ret = ff_reget_buffer(avctx, s->current_frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->current_frame, 0)) < 0) return ret; bytestream2_init(gb, avpkt->data, avpkt->size); @@ -534,6 +534,9 @@ uint32_t clr, *dst = (uint32_t *)s->current_frame->data[0]; int y; + if (bytestream2_get_bytes_left(gb) < 3) + return AVERROR_INVALIDDATA; + frame->key_frame = 1; bytestream2_skip(gb, 1); if (avctx->bits_per_coded_sample == 16) { diff -Nru ffmpeg-4.2.2/libavcodec/screenpresso.c ffmpeg-4.4/libavcodec/screenpresso.c --- ffmpeg-4.2.2/libavcodec/screenpresso.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/screenpresso.c 2020-07-11 10:39:30.000000000 +0000 @@ -94,8 +94,9 @@ { int i; for (; height > 0; height--) { + const uint8_t *src1 = &src[(height - 1) * src_linesize]; for (i = 0; i < bytewidth; i++) - dst[i] += src[(height - 1) * src_linesize + i]; + dst[i] += src1[i]; dst += dst_linesize; } } @@ -145,7 +146,7 @@ return AVERROR_UNKNOWN; } - ret = ff_reget_buffer(avctx, ctx->current); + ret = ff_reget_buffer(avctx, ctx->current, 0); if (ret < 0) return ret; diff -Nru ffmpeg-4.2.2/libavcodec/sei.h ffmpeg-4.4/libavcodec/sei.h --- ffmpeg-4.2.2/libavcodec/sei.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sei.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,140 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_SEI_H +#define AVCODEC_SEI_H + +// SEI payload types form a common namespace between the H.264, H.265 +// and H.266 standards. A given payload type always has the same +// meaning, but some names have different payload types in different +// standards (e.g. scalable-nesting is 30 in H.264 but 133 in H.265). +// The content of the payload data depends on the standard, though +// many generic parts have the same interpretation everywhere (such as +// mastering-display-colour-volume and user-data-unregistered). +enum { + SEI_TYPE_BUFFERING_PERIOD = 0, + SEI_TYPE_PIC_TIMING = 1, + SEI_TYPE_PAN_SCAN_RECT = 2, + SEI_TYPE_FILLER_PAYLOAD = 3, + SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35 = 4, + SEI_TYPE_USER_DATA_UNREGISTERED = 5, + SEI_TYPE_RECOVERY_POINT = 6, + SEI_TYPE_DEC_REF_PIC_MARKING_REPETITION = 7, + SEI_TYPE_SPARE_PIC = 8, + SEI_TYPE_SCENE_INFO = 9, + SEI_TYPE_SUB_SEQ_INFO = 10, + SEI_TYPE_SUB_SEQ_LAYER_CHARACTERISTICS = 11, + SEI_TYPE_SUB_SEQ_CHARACTERISTICS = 12, + SEI_TYPE_FULL_FRAME_FREEZE = 13, + SEI_TYPE_FULL_FRAME_FREEZE_RELEASE = 14, + SEI_TYPE_FULL_FRAME_SNAPSHOT = 15, + SEI_TYPE_PROGRESSIVE_REFINEMENT_SEGMENT_START = 16, + SEI_TYPE_PROGRESSIVE_REFINEMENT_SEGMENT_END = 17, + SEI_TYPE_MOTION_CONSTRAINED_SLICE_GROUP_SET = 18, + SEI_TYPE_FILM_GRAIN_CHARACTERISTICS = 19, + SEI_TYPE_DEBLOCKING_FILTER_DISPLAY_PREFERENCE = 20, + SEI_TYPE_STEREO_VIDEO_INFO = 21, + SEI_TYPE_POST_FILTER_HINT = 22, + SEI_TYPE_TONE_MAPPING_INFO = 23, + SEI_TYPE_SCALABILITY_INFO = 24, + SEI_TYPE_SUB_PIC_SCALABLE_LAYER = 25, + SEI_TYPE_NON_REQUIRED_LAYER_REP = 26, + SEI_TYPE_PRIORITY_LAYER_INFO = 27, + SEI_TYPE_LAYERS_NOT_PRESENT_4 = 28, + SEI_TYPE_LAYER_DEPENDENCY_CHANGE = 29, + SEI_TYPE_SCALABLE_NESTING_4 = 30, + SEI_TYPE_BASE_LAYER_TEMPORAL_HRD = 31, + SEI_TYPE_QUALITY_LAYER_INTEGRITY_CHECK = 32, + SEI_TYPE_REDUNDANT_PIC_PROPERTY = 33, + SEI_TYPE_TL0_DEP_REP_INDEX = 34, + SEI_TYPE_TL_SWITCHING_POINT = 35, + SEI_TYPE_PARALLEL_DECODING_INFO = 36, + SEI_TYPE_MVC_SCALABLE_NESTING = 37, + SEI_TYPE_VIEW_SCALABILITY_INFO = 38, + SEI_TYPE_MULTIVIEW_SCENE_INFO_4 = 39, + SEI_TYPE_MULTIVIEW_ACQUISITION_INFO_4 = 40, + SEI_TYPE_NON_REQUIRED_VIEW_COMPONENT = 41, + SEI_TYPE_VIEW_DEPENDENCY_CHANGE = 42, + SEI_TYPE_OPERATION_POINTS_NOT_PRESENT = 43, + SEI_TYPE_BASE_VIEW_TEMPORAL_HRD = 44, + SEI_TYPE_FRAME_PACKING_ARRANGEMENT = 45, + SEI_TYPE_MULTIVIEW_VIEW_POSITION_4 = 46, + SEI_TYPE_DISPLAY_ORIENTATION = 47, + SEI_TYPE_MVCD_SCALABLE_NESTING = 48, + SEI_TYPE_MVCD_VIEW_SCALABILITY_INFO = 49, + SEI_TYPE_DEPTH_REPRESENTATION_INFO_4 = 50, + SEI_TYPE_THREE_DIMENSIONAL_REFERENCE_DISPLAYS_INFO_4 = 51, + SEI_TYPE_DEPTH_TIMING = 52, + SEI_TYPE_DEPTH_SAMPLING_INFO = 53, + SEI_TYPE_CONSTRAINED_DEPTH_PARAMETER_SET_IDENTIFIER = 54, + SEI_TYPE_GREEN_METADATA = 56, + SEI_TYPE_STRUCTURE_OF_PICTURES_INFO = 128, + SEI_TYPE_ACTIVE_PARAMETER_SETS = 129, + SEI_TYPE_PARAMETER_SETS_INCLUSION_INDICATION = SEI_TYPE_ACTIVE_PARAMETER_SETS, + SEI_TYPE_DECODING_UNIT_INFO = 130, + SEI_TYPE_TEMPORAL_SUB_LAYER_ZERO_IDX = 131, + SEI_TYPE_DECODED_PICTURE_HASH = 132, + SEI_TYPE_SCALABLE_NESTING_5 = 133, + SEI_TYPE_REGION_REFRESH_INFO = 134, + SEI_TYPE_NO_DISPLAY = 135, + SEI_TYPE_TIME_CODE = 136, + SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME = 137, + SEI_TYPE_SEGMENTED_RECT_FRAME_PACKING_ARRANGEMENT = 138, + SEI_TYPE_TEMPORAL_MOTION_CONSTRAINED_TILE_SETS = 139, + SEI_TYPE_CHROMA_RESAMPLING_FILTER_HINT = 140, + SEI_TYPE_KNEE_FUNCTION_INFO = 141, + SEI_TYPE_COLOUR_REMAPPING_INFO = 142, + SEI_TYPE_DEINTERLACED_FIELD_IDENTIFICATION = 143, + SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO = 144, + SEI_TYPE_DEPENDENT_RAP_INDICATION = 145, + SEI_TYPE_CODED_REGION_COMPLETION = 146, + SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS = 147, + SEI_TYPE_AMBIENT_VIEWING_ENVIRONMENT = 148, + SEI_TYPE_CONTENT_COLOUR_VOLUME = 149, + SEI_TYPE_EQUIRECTANGULAR_PROJECTION = 150, + SEI_TYPE_CUBEMAP_PROJECTION = 151, + SEI_TYPE_FISHEYE_VIDEO_INFO = 152, + SEI_TYPE_SPHERE_ROTATION = 154, + SEI_TYPE_REGIONWISE_PACKING = 155, + SEI_TYPE_OMNI_VIEWPORT = 156, + SEI_TYPE_REGIONAL_NESTING = 157, + SEI_TYPE_MCTS_EXTRACTION_INFO_SETS = 158, + SEI_TYPE_MCTS_EXTRACTION_INFO_NESTING = 159, + SEI_TYPE_LAYERS_NOT_PRESENT_5 = 160, + SEI_TYPE_INTER_LAYER_CONSTRAINED_TILE_SETS = 161, + SEI_TYPE_BSP_NESTING = 162, + SEI_TYPE_BSP_INITIAL_ARRIVAL_TIME = 163, + SEI_TYPE_SUB_BITSTREAM_PROPERTY = 164, + SEI_TYPE_ALPHA_CHANNEL_INFO = 165, + SEI_TYPE_OVERLAY_INFO = 166, + SEI_TYPE_TEMPORAL_MV_PREDICTION_CONSTRAINTS = 167, + SEI_TYPE_FRAME_FIELD_INFO = 168, + SEI_TYPE_THREE_DIMENSIONAL_REFERENCE_DISPLAYS_INFO = 176, + SEI_TYPE_DEPTH_REPRESENTATION_INFO_5 = 177, + SEI_TYPE_MULTIVIEW_SCENE_INFO_5 = 178, + SEI_TYPE_MULTIVIEW_ACQUISITION_INFO_5 = 179, + SEI_TYPE_MULTIVIEW_VIEW_POSITION_5 = 180, + SEI_TYPE_ALTERNATIVE_DEPTH_INFO = 181, + SEI_TYPE_SEI_MANIFEST = 200, + SEI_TYPE_SEI_PREFIX_INDICATION = 201, + SEI_TYPE_ANNOTATED_REGIONS = 202, + SEI_TYPE_SUBPIC_LEVEL_INFO = 203, + SEI_TYPE_SAMPLE_ASPECT_RATIO_INFO = 204, +}; + +#endif /* AVCODEC_SEI_H */ diff -Nru ffmpeg-4.2.2/libavcodec/setts_bsf.c ffmpeg-4.4/libavcodec/setts_bsf.c --- ffmpeg-4.2.2/libavcodec/setts_bsf.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/setts_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,221 @@ +/* + * 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 + */ + +/** + * @file + * Change the PTS/DTS timestamps. + */ + +#include "libavutil/opt.h" +#include "libavutil/eval.h" + +#include "avcodec.h" +#include "bsf.h" +#include "bsf_internal.h" + +static const char *const var_names[] = { + "N", ///< frame number (starting at zero) + "TS", + "POS", ///< original position in the file of the frame + "PREV_INPTS", ///< previous input PTS + "PREV_INDTS", ///< previous input DTS + "PREV_OUTPTS", ///< previous output PTS + "PREV_OUTDTS", ///< previous output DTS + "PTS", ///< original PTS in the file of the frame + "DTS", ///< original DTS in the file of the frame + "STARTPTS", ///< PTS at start of movie + "STARTDTS", ///< DTS at start of movie + "TB", ///< timebase of the stream + "SR", ///< sample rate of the stream + NULL +}; + +enum var_name { + VAR_N, + VAR_TS, + VAR_POS, + VAR_PREV_INPTS, + VAR_PREV_INDTS, + VAR_PREV_OUTPTS, + VAR_PREV_OUTDTS, + VAR_PTS, + VAR_DTS, + VAR_STARTPTS, + VAR_STARTDTS, + VAR_TB, + VAR_SR, + VAR_VARS_NB +}; + +typedef struct SetTSContext { + const AVClass *class; + + char *ts_str; + char *pts_str; + char *dts_str; + + int64_t frame_number; + + int64_t start_pts; + int64_t start_dts; + int64_t prev_inpts; + int64_t prev_indts; + int64_t prev_outpts; + int64_t prev_outdts; + + double var_values[VAR_VARS_NB]; + + AVExpr *ts_expr; + AVExpr *pts_expr; + AVExpr *dts_expr; +} SetTSContext; + +static int setts_init(AVBSFContext *ctx) +{ + SetTSContext *s = ctx->priv_data; + int ret; + + if ((ret = av_expr_parse(&s->ts_expr, s->ts_str, + var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Error while parsing ts expression '%s'\n", s->ts_str); + return ret; + } + + if (s->pts_str) { + if ((ret = av_expr_parse(&s->pts_expr, s->pts_str, + var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Error while parsing pts expression '%s'\n", s->pts_str); + return ret; + } + } + + if (s->dts_str) { + if ((ret = av_expr_parse(&s->dts_expr, s->dts_str, + var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Error while parsing dts expression '%s'\n", s->dts_str); + return ret; + } + } + + s->frame_number= 0; + s->start_pts = AV_NOPTS_VALUE; + s->start_dts = AV_NOPTS_VALUE; + s->prev_inpts = AV_NOPTS_VALUE; + s->prev_indts = AV_NOPTS_VALUE; + s->prev_outpts = AV_NOPTS_VALUE; + s->prev_outdts = AV_NOPTS_VALUE; + + return 0; +} + +static int setts_filter(AVBSFContext *ctx, AVPacket *pkt) +{ + SetTSContext *s = ctx->priv_data; + int64_t new_ts, new_pts, new_dts; + int ret; + + ret = ff_bsf_get_packet_ref(ctx, pkt); + if (ret < 0) + return ret; + + if (s->start_pts == AV_NOPTS_VALUE) + s->start_pts = pkt->pts; + + if (s->start_dts == AV_NOPTS_VALUE) + s->start_dts = pkt->dts; + + s->var_values[VAR_N] = s->frame_number++; + s->var_values[VAR_TS] = pkt->dts; + s->var_values[VAR_POS] = pkt->pos; + s->var_values[VAR_PTS] = pkt->pts; + s->var_values[VAR_DTS] = pkt->dts; + s->var_values[VAR_PREV_INPTS] = s->prev_inpts; + s->var_values[VAR_PREV_INDTS] = s->prev_indts; + s->var_values[VAR_PREV_OUTPTS] = s->prev_outpts; + s->var_values[VAR_PREV_OUTDTS] = s->prev_outdts; + s->var_values[VAR_STARTPTS] = s->start_pts; + s->var_values[VAR_STARTDTS] = s->start_dts; + s->var_values[VAR_TB] = ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0; + s->var_values[VAR_SR] = ctx->par_in->sample_rate; + + new_ts = llrint(av_expr_eval(s->ts_expr, s->var_values, NULL)); + + if (s->pts_str) { + s->var_values[VAR_TS] = pkt->pts; + new_pts = llrint(av_expr_eval(s->pts_expr, s->var_values, NULL)); + } else { + new_pts = new_ts; + } + + if (s->dts_str) { + s->var_values[VAR_TS] = pkt->dts; + new_dts = llrint(av_expr_eval(s->dts_expr, s->var_values, NULL)); + } else { + new_dts = new_ts; + } + + s->var_values[VAR_PREV_INPTS] = pkt->pts; + s->var_values[VAR_PREV_INDTS] = pkt->dts; + s->var_values[VAR_PREV_OUTPTS] = new_pts; + s->var_values[VAR_PREV_OUTDTS] = new_dts; + + pkt->pts = new_pts; + pkt->dts = new_dts; + + return ret; +} + +static void setts_close(AVBSFContext *bsf) +{ + SetTSContext *s = bsf->priv_data; + + av_expr_free(s->ts_expr); + s->ts_expr = NULL; + av_expr_free(s->pts_expr); + s->pts_expr = NULL; + av_expr_free(s->dts_expr); + s->dts_expr = NULL; +} + +#define OFFSET(x) offsetof(SetTSContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_SUBTITLE_PARAM|AV_OPT_FLAG_BSF_PARAM) + +static const AVOption options[] = { + { "ts", "set expression for packet PTS and DTS", OFFSET(ts_str), AV_OPT_TYPE_STRING, {.str="TS"}, 0, 0, FLAGS }, + { "pts", "set expression for packet PTS", OFFSET(pts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "dts", "set expression for packet DTS", OFFSET(dts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { NULL }, +}; + +static const AVClass setts_class = { + .class_name = "setts_bsf", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVBitStreamFilter ff_setts_bsf = { + .name = "setts", + .priv_data_size = sizeof(SetTSContext), + .priv_class = &setts_class, + .init = setts_init, + .close = setts_close, + .filter = setts_filter, +}; diff -Nru ffmpeg-4.2.2/libavcodec/sga.c ffmpeg-4.4/libavcodec/sga.c --- ffmpeg-4.2.2/libavcodec/sga.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sga.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,534 @@ +/* + * 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 "libavutil/avassert.h" +#include "libavutil/common.h" +#include "avcodec.h" +#include "get_bits.h" +#include "bytestream.h" +#include "internal.h" + +#define PALDATA_FOLLOWS_TILEDATA 4 +#define HAVE_COMPRESSED_TILEMAP 32 +#define HAVE_TILEMAP 128 + +typedef struct SGAVideoContext { + GetByteContext gb; + + int metadata_size; + int tiledata_size; + int tiledata_offset; + int tilemapdata_size; + int tilemapdata_offset; + int paldata_size; + int paldata_offset; + int palmapdata_offset; + int palmapdata_size; + + int flags; + int nb_pal; + int nb_tiles; + int tiles_w, tiles_h; + int shift; + int plus; + int swap; + + uint32_t pal[256]; + uint8_t *tileindex_data; + unsigned tileindex_size; + uint8_t *palmapindex_data; + unsigned palmapindex_size; + uint8_t uncompressed[65536]; +} SGAVideoContext; + +static av_cold int sga_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_PAL8; + return 0; +} + +static int decode_palette(GetByteContext *gb, uint32_t *pal) +{ + GetBitContext gbit; + + if (bytestream2_get_bytes_left(gb) < 18) + return AVERROR_INVALIDDATA; + + memset(pal, 0, 16 * sizeof(*pal)); + init_get_bits8(&gbit, gb->buffer, 18); + + for (int RGBIndex = 0; RGBIndex < 3; RGBIndex++) { + for (int index = 0; index < 16; index++) { + unsigned color = get_bits1(&gbit) << RGBIndex; + pal[15 - index] |= color << (5 + 16); + } + } + + for (int RGBIndex = 0; RGBIndex < 3; RGBIndex++) { + for (int index = 0; index < 16; index++) { + unsigned color = get_bits1(&gbit) << RGBIndex; + pal[15 - index] |= color << (5 + 8); + } + } + + for (int RGBIndex = 0; RGBIndex < 3; RGBIndex++) { + for (int index = 0; index < 16; index++) { + unsigned color = get_bits1(&gbit) << RGBIndex; + pal[15 - index] |= color << (5 + 0); + } + } + + for (int index = 0; index < 16; index++) + pal[index] = (0xFFU << 24) | pal[index] | (pal[index] >> 3); + + bytestream2_skip(gb, 18); + + return 0; +} + +static int decode_index_palmap(SGAVideoContext *s, AVFrame *frame) +{ + const uint8_t *tt = s->tileindex_data; + + for (int y = 0; y < s->tiles_h; y++) { + for (int x = 0; x < s->tiles_w; x++) { + int pal_idx = s->palmapindex_data[y * s->tiles_w + x] * 16; + uint8_t *dst = frame->data[0] + y * 8 * frame->linesize[0] + x * 8; + + for (int yy = 0; yy < 8; yy++) { + for (int xx = 0; xx < 8; xx++) + dst[xx] = pal_idx + tt[xx]; + tt += 8; + + dst += frame->linesize[0]; + } + } + } + + return 0; +} + +static int decode_index_tilemap(SGAVideoContext *s, AVFrame *frame) +{ + GetByteContext *gb = &s->gb; + GetBitContext pm; + + bytestream2_seek(gb, s->tilemapdata_offset, SEEK_SET); + if (bytestream2_get_bytes_left(gb) < s->tilemapdata_size) + return AVERROR_INVALIDDATA; + + init_get_bits8(&pm, gb->buffer, s->tilemapdata_size); + + for (int y = 0; y < s->tiles_h; y++) { + for (int x = 0; x < s->tiles_w; x++) { + uint8_t tile[64]; + int tilemap = get_bits(&pm, 16); + int flip_x = (tilemap >> 11) & 1; + int flip_y = (tilemap >> 12) & 1; + int tindex = av_clip((tilemap & 511) - 1, 0, s->nb_tiles - 1); + const uint8_t *tt = s->tileindex_data + tindex * 64; + int pal_idx = ((tilemap >> 13) & 3) * 16; + uint8_t *dst = frame->data[0] + y * 8 * frame->linesize[0] + x * 8; + + if (!flip_x && !flip_y) { + memcpy(tile, tt, 64); + } else if (flip_x && flip_y) { + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) + tile[i * 8 + j] = tt[(7 - i) * 8 + 7 - j]; + } + } else if (flip_x) { + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) + tile[i * 8 + j] = tt[i * 8 + 7 - j]; + } + } else { + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) + tile[i * 8 + j] = tt[(7 - i) * 8 + j]; + } + } + + for (int yy = 0; yy < 8; yy++) { + for (int xx = 0; xx < 8; xx++) + dst[xx] = pal_idx + tile[xx + yy * 8]; + + dst += frame->linesize[0]; + } + } + } + + return 0; +} + +static int decode_index(SGAVideoContext *s, AVFrame *frame) +{ + const uint8_t *src = s->tileindex_data; + uint8_t *dst = frame->data[0]; + + for (int y = 0; y < frame->height; y += 8) { + for (int x = 0; x < frame->width; x += 8) { + for (int yy = 0; yy < 8; yy++) { + for (int xx = 0; xx < 8; xx++) + dst[x + xx + yy * frame->linesize[0]] = src[xx]; + src += 8; + } + } + + dst += 8 * frame->linesize[0]; + } + + return 0; +} + +static int lzss_decompress(AVCodecContext *avctx, + GetByteContext *gb, uint8_t *dst, + int dst_size, int shift, int plus) +{ + int oi = 0; + + while (bytestream2_get_bytes_left(gb) > 0 && oi < dst_size) { + uint16_t displace, header = bytestream2_get_be16(gb); + int count, offset; + + for (int i = 0; i < 16; i++) { + switch (header >> 15) { + case 0: + if (oi + 2 < dst_size) { + dst[oi++] = bytestream2_get_byte(gb); + dst[oi++] = bytestream2_get_byte(gb); + } + break; + case 1: + displace = bytestream2_get_be16(gb); + count = displace >> shift; + offset = displace & ((1 << shift) - 1); + + if (displace == 0) { + while (bytestream2_get_bytes_left(gb) > 0 && + oi < dst_size) + dst[oi++] = bytestream2_get_byte(gb); + return oi; + } + + count += plus; + + if (offset <= 0) + offset = 1; + if (oi < offset || oi + count * 2 > dst_size) + return AVERROR_INVALIDDATA; + for (int j = 0; j < count * 2; j++) { + dst[oi] = dst[oi - offset]; + oi++; + } + break; + } + + header <<= 1; + } + } + + return AVERROR_INVALIDDATA; +} + +static int decode_palmapdata(AVCodecContext *avctx) +{ + SGAVideoContext *s = avctx->priv_data; + const int bits = (s->nb_pal + 1) / 2; + GetByteContext *gb = &s->gb; + GetBitContext pm; + + bytestream2_seek(gb, s->palmapdata_offset, SEEK_SET); + if (bytestream2_get_bytes_left(gb) < s->palmapdata_size) + return AVERROR_INVALIDDATA; + init_get_bits8(&pm, gb->buffer, s->palmapdata_size); + + for (int y = 0; y < s->tiles_h; y++) { + uint8_t *dst = s->palmapindex_data + y * s->tiles_w; + + for (int x = 0; x < s->tiles_w; x++) + dst[x] = get_bits(&pm, bits); + + dst += s->tiles_w; + } + + return 0; +} + +static int decode_tiledata(AVCodecContext *avctx) +{ + SGAVideoContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + GetBitContext tm; + + bytestream2_seek(gb, s->tiledata_offset, SEEK_SET); + if (bytestream2_get_bytes_left(gb) < s->tiledata_size) + return AVERROR_INVALIDDATA; + init_get_bits8(&tm, gb->buffer, s->tiledata_size); + + for (int n = 0; n < s->nb_tiles; n++) { + uint8_t *dst = s->tileindex_data + n * 64; + + for (int yy = 0; yy < 8; yy++) { + for (int xx = 0; xx < 8; xx++) + dst[xx] = get_bits(&tm, 4); + + dst += 8; + } + } + + for (int i = 0; i < s->nb_tiles && s->swap; i++) { + uint8_t *dst = s->tileindex_data + i * 64; + + for (int j = 8; j < 64; j += 16) { + for (int k = 0; k < 8; k += 2) + FFSWAP(uint8_t, dst[j + k], dst[j+k+1]); + } + } + + return 0; +} + +static int sga_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + SGAVideoContext *s = avctx->priv_data; + GetByteContext *gb = &s->gb; + AVFrame *frame = data; + int ret, type; + + if (avpkt->size <= 14) + return AVERROR_INVALIDDATA; + + s->flags = avpkt->data[8]; + s->nb_pal = avpkt->data[9]; + s->tiles_w = avpkt->data[10]; + s->tiles_h = avpkt->data[11]; + + if (s->nb_pal > 4) + return AVERROR_INVALIDDATA; + + if ((ret = ff_set_dimensions(avctx, + s->tiles_w * 8, + s->tiles_h * 8)) < 0) + return ret; + + av_fast_padded_malloc(&s->tileindex_data, &s->tileindex_size, + avctx->width * avctx->height); + if (!s->tileindex_data) + return AVERROR(ENOMEM); + + av_fast_padded_malloc(&s->palmapindex_data, &s->palmapindex_size, + s->tiles_w * s->tiles_h); + if (!s->palmapindex_data) + return AVERROR(ENOMEM); + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + bytestream2_init(gb, avpkt->data, avpkt->size); + + type = bytestream2_get_byte(gb); + s->metadata_size = 12 + ((!!(s->flags & HAVE_TILEMAP)) * 2); + s->nb_tiles = s->flags & HAVE_TILEMAP ? AV_RB16(avpkt->data + 12) : s->tiles_w * s->tiles_h; + if (s->nb_tiles > s->tiles_w * s->tiles_h) + return AVERROR_INVALIDDATA; + + av_log(avctx, AV_LOG_DEBUG, "type: %X flags: %X nb_tiles: %d\n", type, s->flags, s->nb_tiles); + + switch (type) { + case 0xE7: + case 0xCB: + case 0xCD: + s->swap = 1; + s->shift = 12; + s->plus = 1; + break; + case 0xC9: + s->swap = 1; + s->shift = 13; + s->plus = 1; + break; + case 0xC8: + s->swap = 1; + s->shift = 13; + s->plus = 0; + break; + case 0xC7: + s->swap = 0; + s->shift = 13; + s->plus = 1; + break; + case 0xC6: + s->swap = 0; + s->shift = 13; + s->plus = 0; + break; + } + + if (type == 0xE7) { + int offset = s->metadata_size, left; + int sizes[3]; + + bytestream2_seek(gb, s->metadata_size, SEEK_SET); + + for (int i = 0; i < 3; i++) + sizes[i] = bytestream2_get_be16(gb); + + for (int i = 0; i < 3; i++) { + int size = sizes[i]; + int raw = size >> 15; + + size &= (1 << 15) - 1; + + if (raw) { + if (bytestream2_get_bytes_left(gb) < size) + return AVERROR_INVALIDDATA; + + if (sizeof(s->uncompressed) - offset < size) + return AVERROR_INVALIDDATA; + + memcpy(s->uncompressed + offset, gb->buffer, size); + bytestream2_skip(gb, size); + } else { + GetByteContext gb2; + + if (bytestream2_get_bytes_left(gb) < size) + return AVERROR_INVALIDDATA; + + bytestream2_init(&gb2, gb->buffer, size); + ret = lzss_decompress(avctx, &gb2, s->uncompressed + offset, + sizeof(s->uncompressed) - offset, s->shift, s->plus); + if (ret < 0) + return ret; + bytestream2_skip(gb, size); + size = ret; + } + + offset += size; + } + + left = bytestream2_get_bytes_left(gb); + if (sizeof(s->uncompressed) - offset < left) + return AVERROR_INVALIDDATA; + + bytestream2_get_buffer(gb, s->uncompressed + offset, left); + + offset += left; + bytestream2_init(gb, s->uncompressed, offset); + } + + switch (type) { + case 0xCD: + case 0xCB: + case 0xC9: + case 0xC8: + case 0xC7: + case 0xC6: + bytestream2_seek(gb, s->metadata_size, SEEK_SET); + ret = lzss_decompress(avctx, gb, s->uncompressed + s->metadata_size, + sizeof(s->uncompressed) - s->metadata_size, s->shift, s->plus); + if (ret < 0) + return ret; + bytestream2_init(gb, s->uncompressed, ret + s->metadata_size); + case 0xE7: + case 0xC1: + s->tiledata_size = s->nb_tiles * 32; + s->paldata_size = s->nb_pal * 18; + s->tiledata_offset = s->flags & PALDATA_FOLLOWS_TILEDATA ? s->metadata_size : s->metadata_size + s->paldata_size; + s->paldata_offset = s->flags & PALDATA_FOLLOWS_TILEDATA ? s->metadata_size + s->tiledata_size : s->metadata_size; + s->palmapdata_offset = (s->flags & HAVE_TILEMAP) ? -1 : s->paldata_offset + s->paldata_size; + s->palmapdata_size = (s->flags & HAVE_TILEMAP) || s->nb_pal < 2 ? 0 : (s->tiles_w * s->tiles_h * ((s->nb_pal + 1) / 2) + 7) / 8; + s->tilemapdata_size = (s->flags & HAVE_TILEMAP) ? s->tiles_w * s->tiles_h * 2 : 0; + s->tilemapdata_offset = (s->flags & HAVE_TILEMAP) ? s->paldata_offset + s->paldata_size: -1; + + bytestream2_seek(gb, s->paldata_offset, SEEK_SET); + for (int n = 0; n < s->nb_pal; n++) { + ret = decode_palette(gb, s->pal + 16 * n); + if (ret < 0) + return ret; + } + + if (s->tiledata_size > 0) { + ret = decode_tiledata(avctx); + if (ret < 0) + return ret; + } + + if (s->palmapdata_size > 0) { + ret = decode_palmapdata(avctx); + if (ret < 0) + return ret; + } + + if (s->palmapdata_size > 0 && s->tiledata_size > 0) { + ret = decode_index_palmap(s, frame); + if (ret < 0) + return ret; + } else if (s->tilemapdata_size > 0 && s->tiledata_size > 0) { + ret = decode_index_tilemap(s, frame); + if (ret < 0) + return ret; + } else if (s->tiledata_size > 0) { + ret = decode_index(s, frame); + if (ret < 0) + return ret; + } + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown type: %X\n", type); + return AVERROR_INVALIDDATA; + } + + memcpy(frame->data[1], s->pal, AVPALETTE_SIZE); + frame->palette_has_changed = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int sga_decode_end(AVCodecContext *avctx) +{ + SGAVideoContext *s = avctx->priv_data; + + av_freep(&s->tileindex_data); + s->tileindex_size = 0; + + av_freep(&s->palmapindex_data); + s->palmapindex_size = 0; + + return 0; +} + +AVCodec ff_sga_decoder = { + .name = "sga", + .long_name = NULL_IF_CONFIG_SMALL("Digital Pictures SGA Video"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SGA_VIDEO, + .priv_data_size = sizeof(SGAVideoContext), + .init = sga_decode_init, + .decode = sga_decode_frame, + .close = sga_decode_end, + .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff -Nru ffmpeg-4.2.2/libavcodec/sgidec.c ffmpeg-4.4/libavcodec/sgidec.c --- ffmpeg-4.2.2/libavcodec/sgidec.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sgidec.c 2021-04-08 21:28:39.000000000 +0000 @@ -297,4 +297,5 @@ .decode = decode_frame, .init = sgi_decode_init, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/sgienc.c ffmpeg-4.4/libavcodec/sgienc.c --- ffmpeg-4.2.2/libavcodec/sgienc.c 2018-07-17 09:27:41.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sgienc.c 2021-04-08 21:28:39.000000000 +0000 @@ -39,9 +39,9 @@ static av_cold int encode_init(AVCodecContext *avctx) { if (avctx->width > 65535 || avctx->height > 65535) { - av_log(avctx, AV_LOG_ERROR, - "Unsupported resolution %dx%d.\n", avctx->width, avctx->height); - av_log(avctx, AV_LOG_ERROR, "SGI does not support resolutions above 65535x65535\n"); + av_log(avctx, AV_LOG_ERROR, "Unsupported resolution %dx%d. " + "SGI does not support resolutions above 65535x65535\n", + avctx->width, avctx->height); return AVERROR_INVALIDDATA; } @@ -219,7 +219,15 @@ bytestream2_put_be32(&taboff_pcb, bytestream2_tell_p(&pbc)); for (x = 0; x < width * bytes_per_channel; x += bytes_per_channel) - encode_buf[x] = in_buf[depth * x]; + if (bytes_per_channel == 1) { + encode_buf[x] = in_buf[depth * x]; + } else if (HAVE_BIGENDIAN ^ put_be) { + encode_buf[x + 1] = in_buf[depth * x]; + encode_buf[x] = in_buf[depth * x + 1]; + } else { + encode_buf[x] = in_buf[depth * x]; + encode_buf[x + 1] = in_buf[depth * x + 1]; + } length = sgi_rle_encode(&pbc, encode_buf, width, bytes_per_channel); @@ -292,4 +300,5 @@ AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/sgirledec.c ffmpeg-4.4/libavcodec/sgirledec.c --- ffmpeg-4.2.2/libavcodec/sgirledec.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sgirledec.c 2021-04-08 21:28:39.000000000 +0000 @@ -139,4 +139,5 @@ .init = sgirle_decode_init, .decode = sgirle_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/sheervideo.c ffmpeg-4.4/libavcodec/sheervideo.c --- ffmpeg-4.2.2/libavcodec/sheervideo.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sheervideo.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,9 @@ #include #include +#define CACHED_BITSTREAM_READER !ARCH_X86_32 +#define SHEER_VLC_BITS 12 + #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "get_bits.h" @@ -62,10 +65,10 @@ for (x = 0; x < avctx->width; x++) { int y, u, v, a; - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_a[x] = pred[3] = (a + pred[3]) & 0x3ff; dst_y[x] = pred[0] = (y + pred[0]) & 0x3ff; @@ -105,10 +108,10 @@ for (x = 0; x < avctx->width; x++) { int y, u, v, a; - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_a[x] = pred[3] = (a + pred[3]) & 0x3ff; dst_y[x] = pred[0] = (y + pred[0]) & 0x3ff; @@ -145,10 +148,10 @@ pred_T[2] = dst_v[-p->linesize[2] / 2 + x]; pred_T[3] = dst_a[-p->linesize[3] / 2 + x]; - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_a[x] = pred_L[3] = (a + ((3 * (pred_T[3] + pred_L[3]) - 2 * pred_TL[3]) >> 2)) & 0x3ff; dst_y[x] = pred_L[0] = (y + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0x3ff; @@ -192,9 +195,9 @@ for (x = 0; x < avctx->width; x++) { int y, u, v; - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x] = pred[0] = (y + pred[0]) & 0x3ff; dst_u[x] = pred[1] = (u + pred[1]) & 0x3ff; @@ -230,9 +233,9 @@ for (x = 0; x < avctx->width; x++) { int y, u, v; - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x] = pred[0] = (y + pred[0]) & 0x3ff; dst_u[x] = pred[1] = (u + pred[1]) & 0x3ff; @@ -264,9 +267,9 @@ pred_T[1] = dst_u[-p->linesize[1] / 2 + x]; pred_T[2] = dst_v[-p->linesize[2] / 2 + x]; - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x] = pred_L[0] = (y + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0x3ff; dst_u[x] = pred_L[1] = (u + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0x3ff; @@ -308,10 +311,10 @@ for (x = 0; x < avctx->width; x += 2) { int y1, y2, u, v; - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred[0] = (y1 + pred[0]) & 0x3ff; dst_u[x / 2] = pred[1] = (u + pred[1]) & 0x3ff; @@ -349,10 +352,10 @@ for (x = 0; x < avctx->width; x += 2) { int y1, y2, u, v; - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred[0] = (y1 + pred[0]) & 0x3ff; dst_u[x / 2] = pred[1] = (u + pred[1]) & 0x3ff; @@ -387,10 +390,10 @@ pred_T[1] = dst_u[-p->linesize[1] / 2 + x / 2]; pred_T[2] = dst_v[-p->linesize[2] / 2 + x / 2]; - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred_L[0] = (y1 + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0x3ff; dst_u[x / 2] = pred_L[1] = (u + (((pred_L[1] - pred_TL[1]) >> 1) + pred_T[1])) & 0x3ff; @@ -436,12 +439,12 @@ for (x = 0; x < avctx->width; x += 2) { int y1, y2, u, v, a1, a2; - a1 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - a2 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a1 = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + a2 = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred[0] = (y1 + pred[0]) & 0x3ff; dst_u[x / 2] = pred[1] = (u + pred[1]) & 0x3ff; @@ -485,12 +488,12 @@ for (x = 0; x < avctx->width; x += 2) { int y1, y2, u, v, a1, a2; - a1 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - a2 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a1 = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + a2 = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred[0] = (y1 + pred[0]) & 0x3ff; dst_u[x / 2] = pred[1] = (u + pred[1]) & 0x3ff; @@ -533,12 +536,12 @@ pred_T[4] = dst_a[-p->linesize[3] / 2 + x]; pred_T[5] = dst_a[-p->linesize[3] / 2 + x + 1]; - a1 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - a2 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a1 = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + a2 = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred_L[0] = (y1 + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0x3ff; dst_u[x / 2] = pred_L[1] = (u + (((pred_L[1] - pred_TL[1]) >> 1) + pred_T[1])) & 0x3ff; @@ -588,12 +591,12 @@ for (x = 0; x < avctx->width; x += 2) { int y1, y2, u, v, a1, a2; - a1 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - a2 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a1 = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + a2 = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred[0] = (y1 + pred[0]) & 0xff; dst_y[x + 1] = pred[0] = (y2 + pred[0]) & 0xff; @@ -637,12 +640,12 @@ for (x = 0; x < avctx->width; x += 2) { int y1, y2, u, v, a1, a2; - a1 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - a2 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a1 = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + a2 = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred[0] = (y1 + pred[0]) & 0xff; dst_u[x / 2] = pred[1] = (u + pred[1]) & 0xff; @@ -685,12 +688,12 @@ pred_T[4] = dst_a[-p->linesize[3] + x]; pred_T[5] = dst_a[-p->linesize[3] + x + 1]; - a1 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - a2 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a1 = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + a2 = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred_L[0] = (y1 + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff; dst_u[x / 2] = pred_L[1] = (u + (((pred_L[1] - pred_TL[1]) >> 1) + pred_T[1])) & 0xff; @@ -736,10 +739,10 @@ for (x = 0; x < avctx->width; x += 2) { int y1, y2, u, v; - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred[0] = (y1 + pred[0]) & 0xff; dst_u[x / 2] = pred[1] = (u + pred[1]) & 0xff; @@ -774,10 +777,10 @@ pred_T[1] = dst_u[-p->linesize[1] + x / 2]; pred_T[2] = dst_v[-p->linesize[2] + x / 2]; - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred_L[0] = (y1 + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff; dst_u[x / 2] = pred_L[1] = (u + (((pred_L[1] - pred_TL[1]) >> 1) + pred_T[1])) & 0xff; @@ -819,10 +822,10 @@ for (x = 0; x < avctx->width; x += 2) { int y1, y2, u, v; - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred[0] = (y1 + pred[0]) & 0xff; dst_u[x / 2] = pred[1] = (u + pred[1]) & 0xff; @@ -852,10 +855,10 @@ pred_L[2] = dst_v[-p->linesize[2]]; for (x = 0; x < avctx->width; x += 2) { - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred_L[0] = (y1 + pred_L[0]) & 0xff; dst_u[x / 2] = pred_L[1] = (u + pred_L[1]) & 0xff; @@ -893,10 +896,10 @@ for (x = 0; x < avctx->width; x += 2) { int y1, y2, u, v; - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred[0] = (y1 + pred[0]) & 0xff; dst_u[x / 2] = pred[1] = (u + pred[1]) & 0xff; @@ -931,10 +934,10 @@ pred_T[1] = dst_u[-p->linesize[1] + x / 2]; pred_T[2] = dst_v[-p->linesize[2] + x / 2]; - y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y1 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y2 = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x ] = pred_L[0] = (y1 + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff; dst_u[x / 2] = pred_L[1] = (u + (((pred_L[1] - pred_TL[1]) >> 1) + pred_T[1])) & 0xff; @@ -975,9 +978,9 @@ for (x = 0; x < avctx->width; x++) { int y, u, v; - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x] = pred[0] = (y + pred[0]) & 0xff; dst_u[x] = pred[1] = (u + pred[1]) & 0xff; @@ -1005,9 +1008,9 @@ pred_L[2] = dst_v[-p->linesize[2]]; for (x = 0; x < avctx->width; x++) { - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x] = pred_L[0] = (y + pred_L[0]) & 0xff; dst_u[x] = pred_L[1] = (u + pred_L[1]) & 0xff; @@ -1043,9 +1046,9 @@ for (x = 0; x < avctx->width; x++) { int y, u, v; - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x] = pred[0] = (y + pred[0]) & 0xff; dst_u[x] = pred[1] = (u + pred[1]) & 0xff; @@ -1077,9 +1080,9 @@ pred_T[1] = dst_u[-p->linesize[1] + x]; pred_T[2] = dst_v[-p->linesize[2] + x]; - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_y[x] = pred_L[0] = (y + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff; dst_u[x] = pred_L[1] = (u + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0xff; @@ -1121,10 +1124,10 @@ for (x = 0; x < avctx->width; x++) { int a, y, u, v; - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_a[x] = pred[0] = (a + pred[0]) & 0xff; dst_y[x] = pred[1] = (y + pred[1]) & 0xff; @@ -1156,10 +1159,10 @@ pred_L[3] = dst_v[-p->linesize[2]]; for (x = 0; x < avctx->width; x++) { - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_a[x] = pred_L[0] = (a + pred_L[0]) & 0xff; dst_y[x] = pred_L[1] = (y + pred_L[1]) & 0xff; @@ -1199,10 +1202,10 @@ for (x = 0; x < avctx->width; x++) { int a, y, u, v; - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_a[x] = pred[0] = (a + pred[0]) & 0xff; dst_y[x] = pred[1] = (y + pred[1]) & 0xff; @@ -1239,10 +1242,10 @@ pred_T[2] = dst_u[-p->linesize[1] + x]; pred_T[3] = dst_v[-p->linesize[2] + x]; - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + y = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + u = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + v = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_a[x] = pred_L[0] = (a + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff; dst_y[x] = pred_L[1] = (y + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0xff; @@ -1288,10 +1291,10 @@ for (x = 0; x < avctx->width; x++) { int r, g, b, a; - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_a[x] = pred[3] = (a + pred[3]) & 0x3ff; dst_r[x] = pred[0] = (r + pred[0]) & 0x3ff; @@ -1331,10 +1334,10 @@ for (x = 0; x < avctx->width; x++) { int r, g, b, a; - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_a[x] = pred[3] = (a + pred[3]) & 0x3ff; dst_r[x] = pred[0] = (r + pred[0]) & 0x3ff; @@ -1371,10 +1374,10 @@ pred_T[2] = dst_b[-p->linesize[1] / 2 + x]; pred_T[3] = dst_a[-p->linesize[3] / 2 + x]; - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_a[x] = pred_L[3] = (a + ((3 * (pred_T[3] + pred_L[3]) - 2 * pred_TL[3]) >> 2)) & 0x3ff; dst_r[x] = pred_L[0] = (r + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0x3ff; @@ -1418,9 +1421,9 @@ for (x = 0; x < avctx->width; x++) { int r, g, b; - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_r[x] = pred[0] = (r + pred[0]) & 0x3ff; dst_g[x] = pred[1] = (r + g + pred[1]) & 0x3ff; @@ -1456,9 +1459,9 @@ for (x = 0; x < avctx->width; x++) { int r, g, b; - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_r[x] = pred[0] = (r + pred[0]) & 0x3ff; dst_g[x] = pred[1] = (r + g + pred[1]) & 0x3ff; @@ -1490,9 +1493,9 @@ pred_T[1] = dst_g[-p->linesize[0] / 2 + x]; pred_T[2] = dst_b[-p->linesize[1] / 2 + x]; - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst_r[x] = pred_L[0] = (r + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0x3ff; dst_g[x] = pred_L[1] = (r + g + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0x3ff; @@ -1530,10 +1533,10 @@ for (x = 0; x < avctx->width; x++) { int a, r, g, b; - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst[4 * x + 0] = pred[0] = (a + pred[0]) & 0xff; dst[4 * x + 1] = pred[1] = (r + pred[1]) & 0xff; @@ -1561,10 +1564,10 @@ pred_L[3] = dst[-p->linesize[0] + 3]; for (x = 0; x < avctx->width; x++) { - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst[4 * x + 0] = pred_L[0] = (a + pred_L[0]) & 0xff; dst[4 * x + 1] = pred_L[1] = (r + pred_L[1]) & 0xff; @@ -1596,10 +1599,10 @@ for (x = 0; x < avctx->width; x++) { int a, r, g, b; - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst[4 * x + 0] = pred[0] = (a + pred[0]) & 0xff; dst[4 * x + 1] = pred[1] = (r + pred[1]) & 0xff; @@ -1632,10 +1635,10 @@ pred_T[2] = dst[-p->linesize[0] + 4 * x + 2]; pred_T[3] = dst[-p->linesize[0] + 4 * x + 3]; - a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + a = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst[4 * x + 0] = pred_L[0] = (a + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff; dst[4 * x + 1] = pred_L[1] = (r + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0xff; @@ -1671,9 +1674,9 @@ for (x = 0; x < avctx->width; x++) { int r, g, b; - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst[4 * x + 0] = pred[0] = (r + pred[0]) & 0xff; dst[4 * x + 1] = pred[1] = (r + g + pred[1]) & 0xff; @@ -1698,9 +1701,9 @@ pred_L[2] = dst[-p->linesize[0] + 2]; for (x = 0; x < avctx->width; x++) { - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst[4 * x + 0] = pred_L[0] = (r + pred_L[0]) & 0xff; dst[4 * x + 1] = pred_L[1] = (r + g + pred_L[1]) & 0xff; @@ -1730,9 +1733,9 @@ for (x = 0; x < avctx->width; x++) { int r, g, b; - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst[4 * x + 0] = pred[0] = (r + pred[0]) & 0xff; dst[4 * x + 1] = pred[1] = (r + g + pred[1]) & 0xff; @@ -1761,9 +1764,9 @@ pred_T[1] = dst[-p->linesize[0] + 4 * x + 1]; pred_T[2] = dst[-p->linesize[0] + 4 * x + 2]; - r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2); - g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); - b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2); + r = get_vlc2(gb, s->vlc[0].table, SHEER_VLC_BITS, 2); + g = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); + b = get_vlc2(gb, s->vlc[1].table, SHEER_VLC_BITS, 2); dst[4 * x + 0] = pred_L[0] = (r + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff; dst[4 * x + 1] = pred_L[1] = (r + g + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0xff; @@ -1778,27 +1781,28 @@ } } -static int build_vlc(VLC *vlc, const uint8_t *len, int count) +static av_cold int build_vlc(VLC *vlc, const SheerTable *table) { - uint32_t codes[1024]; - uint8_t bits[1024]; - uint16_t syms[1024]; - uint64_t index; - int i; - - index = 0; - for (i = 0; i < count; i++) { - codes[i] = index >> (32 - len[i]); - bits[i] = len[i]; - syms[i] = i; - index += 1ULL << (32 - len[i]); + const uint8_t *cur = table->lens; + uint8_t lens[1024]; + unsigned count = 0; + + for (int step = 1, len = 1; len > 0; len += step) { + unsigned new_count = count; + + if (len == 16) { + new_count += table->nb_16s; + step = -1; + } else + new_count += *cur++; + + for (; count < new_count; count++) + lens[count] = len; } ff_free_vlc(vlc); - return ff_init_vlc_sparse(vlc, 16, count, - bits, sizeof(*bits), sizeof(*bits), - codes, sizeof(*codes), sizeof(*codes), - syms, sizeof(*syms), sizeof(*syms), 0); + return ff_init_vlc_from_lengths(vlc, SHEER_VLC_BITS, count, + lens, sizeof(*lens), NULL, 0, 0, 0, 0, NULL); } static int decode_frame(AVCodecContext *avctx, @@ -1807,6 +1811,7 @@ { SheerVideoContext *s = avctx->priv_data; ThreadFrame frame = { .f = data }; + const SheerTable *table; AVFrame *p = data; GetBitContext gb; unsigned format; @@ -1826,226 +1831,153 @@ case MKTAG(' ', 'R', 'G', 'B'): avctx->pix_fmt = AV_PIX_FMT_RGB0; s->decode_frame = decode_rgb; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_r_rgb, 256); - ret |= build_vlc(&s->vlc[1], l_g_rgb, 256); - } + table = rgb; break; case MKTAG(' ', 'r', 'G', 'B'): avctx->pix_fmt = AV_PIX_FMT_RGB0; s->decode_frame = decode_rgbi; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_r_rgbi, 256); - ret |= build_vlc(&s->vlc[1], l_g_rgbi, 256); - } + table = rgbi; break; case MKTAG('A', 'R', 'G', 'X'): avctx->pix_fmt = AV_PIX_FMT_GBRAP10; s->decode_frame = decode_argx; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_r_rgbx, 1024); - ret |= build_vlc(&s->vlc[1], l_g_rgbx, 1024); - } + table = rgbx; break; case MKTAG('A', 'r', 'G', 'X'): avctx->pix_fmt = AV_PIX_FMT_GBRAP10; s->decode_frame = decode_argxi; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_r_rgbxi, 1024); - ret |= build_vlc(&s->vlc[1], l_g_rgbxi, 1024); - } + table = rgbxi; break; case MKTAG('R', 'G', 'B', 'X'): avctx->pix_fmt = AV_PIX_FMT_GBRP10; s->decode_frame = decode_rgbx; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_r_rgbx, 1024); - ret |= build_vlc(&s->vlc[1], l_g_rgbx, 1024); - } + table = rgbx; break; case MKTAG('r', 'G', 'B', 'X'): avctx->pix_fmt = AV_PIX_FMT_GBRP10; s->decode_frame = decode_rgbxi; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_r_rgbxi, 1024); - ret |= build_vlc(&s->vlc[1], l_g_rgbxi, 1024); - } + table = rgbxi; break; case MKTAG('A', 'R', 'G', 'B'): avctx->pix_fmt = AV_PIX_FMT_ARGB; s->decode_frame = decode_argb; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_r_rgb, 256); - ret |= build_vlc(&s->vlc[1], l_g_rgb, 256); - } + table = rgb; break; case MKTAG('A', 'r', 'G', 'B'): avctx->pix_fmt = AV_PIX_FMT_ARGB; s->decode_frame = decode_argbi; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_r_rgbi, 256); - ret |= build_vlc(&s->vlc[1], l_g_rgbi, 256); - } + table = rgbi; break; case MKTAG('A', 'Y', 'B', 'R'): s->alt = 1; case MKTAG('A', 'Y', 'b', 'R'): avctx->pix_fmt = AV_PIX_FMT_YUVA444P; s->decode_frame = decode_aybr; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_ybr, 256); - ret |= build_vlc(&s->vlc[1], l_u_ybr, 256); - } + table = ybr; break; case MKTAG('A', 'y', 'B', 'R'): s->alt = 1; case MKTAG('A', 'y', 'b', 'R'): avctx->pix_fmt = AV_PIX_FMT_YUVA444P; s->decode_frame = decode_aybri; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_ybri, 256); - ret |= build_vlc(&s->vlc[1], l_u_ybri, 256); - } + table = ybri; break; case MKTAG(' ', 'Y', 'B', 'R'): s->alt = 1; case MKTAG(' ', 'Y', 'b', 'R'): avctx->pix_fmt = AV_PIX_FMT_YUV444P; s->decode_frame = decode_ybr; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_ybr, 256); - ret |= build_vlc(&s->vlc[1], l_u_ybr, 256); - } + table = ybr; break; case MKTAG(' ', 'y', 'B', 'R'): s->alt = 1; case MKTAG(' ', 'y', 'b', 'R'): avctx->pix_fmt = AV_PIX_FMT_YUV444P; s->decode_frame = decode_ybri; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_ybri, 256); - ret |= build_vlc(&s->vlc[1], l_u_ybri, 256); - } + table = ybri; break; case MKTAG('Y', 'B', 'R', 0x0a): avctx->pix_fmt = AV_PIX_FMT_YUV444P10; s->decode_frame = decode_ybr10; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_ybr10, 1024); - ret |= build_vlc(&s->vlc[1], l_u_ybr10, 1024); - } + table = ybr10; break; case MKTAG('y', 'B', 'R', 0x0a): avctx->pix_fmt = AV_PIX_FMT_YUV444P10; s->decode_frame = decode_ybr10i; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_ybr10i, 1024); - ret |= build_vlc(&s->vlc[1], l_u_ybr10i, 1024); - } + table = ybr10i; break; case MKTAG('C', 'A', '4', 'p'): avctx->pix_fmt = AV_PIX_FMT_YUVA444P10; s->decode_frame = decode_ca4p; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_ybr10, 1024); - ret |= build_vlc(&s->vlc[1], l_u_ybr10, 1024); - } + table = ybr10; break; case MKTAG('C', 'A', '4', 'i'): avctx->pix_fmt = AV_PIX_FMT_YUVA444P10; s->decode_frame = decode_ca4i; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_ybr10i, 1024); - ret |= build_vlc(&s->vlc[1], l_u_ybr10i, 1024); - } + table = ybr10i; break; case MKTAG('B', 'Y', 'R', 'Y'): avctx->pix_fmt = AV_PIX_FMT_YUV422P; s->decode_frame = decode_byry; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_byry, 256); - ret |= build_vlc(&s->vlc[1], l_u_byry, 256); - } + table = byry; break; case MKTAG('B', 'Y', 'R', 'y'): avctx->pix_fmt = AV_PIX_FMT_YUV422P; s->decode_frame = decode_byryi; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_byryi, 256); - ret |= build_vlc(&s->vlc[1], l_u_byryi, 256); - } + table = byryi; break; case MKTAG('Y', 'b', 'Y', 'r'): avctx->pix_fmt = AV_PIX_FMT_YUV422P; s->decode_frame = decode_ybyr; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_ybyr, 256); - ret |= build_vlc(&s->vlc[1], l_u_ybyr, 256); - } + table = ybyr; break; case MKTAG('C', '8', '2', 'p'): avctx->pix_fmt = AV_PIX_FMT_YUVA422P; s->decode_frame = decode_c82p; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_byry, 256); - ret |= build_vlc(&s->vlc[1], l_u_byry, 256); - } + table = byry; break; case MKTAG('C', '8', '2', 'i'): avctx->pix_fmt = AV_PIX_FMT_YUVA422P; s->decode_frame = decode_c82i; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_byryi, 256); - ret |= build_vlc(&s->vlc[1], l_u_byryi, 256); - } + table = byryi; break; case MKTAG(0xa2, 'Y', 'R', 'Y'): avctx->pix_fmt = AV_PIX_FMT_YUV422P10; s->decode_frame = decode_yry10; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_yry10, 1024); - ret |= build_vlc(&s->vlc[1], l_u_yry10, 1024); - } + table = yry10; break; case MKTAG(0xa2, 'Y', 'R', 'y'): avctx->pix_fmt = AV_PIX_FMT_YUV422P10; s->decode_frame = decode_yry10i; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_yry10i, 1024); - ret |= build_vlc(&s->vlc[1], l_u_yry10i, 1024); - } + table = yry10i; break; case MKTAG('C', 'A', '2', 'p'): avctx->pix_fmt = AV_PIX_FMT_YUVA422P10; s->decode_frame = decode_ca2p; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_yry10, 1024); - ret |= build_vlc(&s->vlc[1], l_u_yry10, 1024); - } + table = yry10; break; case MKTAG('C', 'A', '2', 'i'): avctx->pix_fmt = AV_PIX_FMT_YUVA422P10; s->decode_frame = decode_ca2i; - if (s->format != format) { - ret = build_vlc(&s->vlc[0], l_y_yry10i, 1024); - ret |= build_vlc(&s->vlc[1], l_u_yry10i, 1024); - } + table = yry10i; break; default: avpriv_request_sample(avctx, "unsupported format: 0x%X", format); return AVERROR_PATCHWELCOME; } - if (avpkt->size < 20 + avctx->width * avctx->height / 16) { - av_log(avctx, AV_LOG_ERROR, "Input packet too small\n"); - return AVERROR_INVALIDDATA; - } - if (s->format != format) { - if (ret < 0) + if ((ret = build_vlc(&s->vlc[0], &table[0])) < 0 || + (ret = build_vlc(&s->vlc[1], &table[1])) < 0) { + s->format = 0; return ret; + } s->format = format; } + if (avpkt->size < 20 + avctx->width * avctx->height / 16) { + av_log(avctx, AV_LOG_ERROR, "Input packet too small\n"); + return AVERROR_INVALIDDATA; + } p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; @@ -2063,19 +1995,6 @@ return avpkt->size; } -#if HAVE_THREADS -static int decode_init_thread_copy(AVCodecContext *avctx) -{ - SheerVideoContext *s = avctx->priv_data; - - s->format = 0; - memset(&s->vlc[0], 0, sizeof(s->vlc[0])); - memset(&s->vlc[1], 0, sizeof(s->vlc[1])); - - return 0; -} -#endif - static av_cold int decode_end(AVCodecContext *avctx) { SheerVideoContext *s = avctx->priv_data; @@ -2092,7 +2011,6 @@ .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_SHEERVIDEO, .priv_data_size = sizeof(SheerVideoContext), - .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, diff -Nru ffmpeg-4.2.2/libavcodec/sheervideodata.h ffmpeg-4.4/libavcodec/sheervideodata.h --- ffmpeg-4.2.2/libavcodec/sheervideodata.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sheervideodata.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,1074 +24,152 @@ #include "libavutil/common.h" -static const uint8_t l_r_rgb[256] = { - 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, - 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, - 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 5, 5, 4, 4, 4, -}; - -static const uint8_t l_r_rgbi[256] = { - 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, - 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 4, 4, 4, -}; - -static const uint8_t l_g_rgbi[256] = { - 1, 3, 4, 5, 6, 7, 7, 8, 9, 9, 10, 10, 10, 10, 11, 11, - 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, - 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, - 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, - 11, 11, 11, 10, 10, 10, 9, 9, 9, 8, 8, 7, 6, 5, 5, 3, -}; - -static const uint8_t l_g_rgb[256] = { - 2, 2, 4, 4, 6, 7, 9, 9, 10, 11, 11, 11, 12, 12, 12, 13, - 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, - 13, 13, 12, 12, 12, 11, 11, 11, 10, 9, 9, 8, 6, 4, 3, 3, -}; - -static const uint8_t l_y_ybr[256] = { - 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, - 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 4, 4, 3, -}; - -static const uint8_t l_u_ybr[256] = { - 1, 2, 4, 6, 9, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, - 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, - 14, 14, 14, 14, 14, 13, 13, 13, 12, 12, 11, 11, 10, 8, 5, 3, -}; - -static const uint8_t l_y_ybyr[256] = { - 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, - 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, - 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 5, 5, 4, 4, 4, -}; - -static const uint8_t l_u_ybyr[256] = { - 1, 2, 4, 6, 8, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, - 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14, - 14, 14, 13, 13, 13, 12, 12, 11, 11, 10, 10, 9, 8, 7, 6, 3, -}; - -static const uint8_t l_y_byry[256] = { - 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, - 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, - 11, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 4, 4, 3, -}; - -static const uint8_t l_u_byry[256] = { - 1, 2, 4, 6, 8, 9, 9, 10, 11, 11, 12, 12, 13, 13, 13, 14, - 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, - 14, 14, 14, 13, 13, 12, 12, 12, 11, 11, 10, 9, 8, 7, 6, 3, -}; - -static const uint8_t l_y_ybr10i[1024] = { - 3, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, -}; - -static const uint8_t l_y_ybr10[1024] = { - 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, - 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, - 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, -}; - -static const uint8_t l_u_ybr10i[1024] = { - 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, - 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 6, 5, 5, 4, 4, 3, -}; - -static const uint8_t l_u_ybr10[1024] = { - 2, 3, 3, 4, 5, 5, 6, 7, 8, 9, 9, 10, 10, 10, 11, 11, - 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, - 12, 11, 11, 11, 10, 10, 9, 9, 8, 8, 7, 6, 5, 4, 4, 3, -}; - -static const uint8_t l_r_rgbx[1024] = { - 4, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, -}; - -static const uint8_t l_g_rgbx[1024] = { - 3, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, - 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, - 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, - 12, 12, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, - 8, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, -}; - -static const uint8_t l_y_yry10[1024] = { - 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, - 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, - 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, -}; - -static const uint8_t l_y_yry10i[1024] = { - 3, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, -}; - -static const uint8_t l_u_yry10[1024] = { - 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, - 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, - 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, - 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, - 10, 10, 10, 10, 9, 9, 9, 8, 8, 7, 7, 6, 5, 4, 4, 3, -}; - -static const uint8_t l_u_yry10i[1024] = { - 2, 4, 4, 4, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, - 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, - 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, - 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 9, 9, 9, - 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 5, 4, 4, 3, -}; - -static const uint8_t l_y_ybri[256] = { - 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 3, -}; - -static const uint8_t l_u_ybri[256] = { - 1, 3, 5, 6, 8, 8, 9, 10, 10, 11, 11, 12, 12, 13, 13, 13, - 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, - 14, 13, 13, 13, 12, 12, 11, 11, 10, 10, 9, 8, 8, 6, 5, 2, -}; - -static const uint8_t l_y_byryi[256] = { - 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, - 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, - 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, - 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 5, 4, 4, 3, -}; - -static const uint8_t l_u_byryi[256] = { - 1, 3, 4, 6, 6, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, - 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, - 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, - 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, - 12, 11, 11, 11, 10, 10, 10, 9, 9, 8, 8, 7, 7, 5, 4, 3, -}; - -static const uint8_t l_r_rgbxi[1024] = { - 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, - 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, - 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, 4, 4, 4, -}; - -static const uint8_t l_g_rgbxi[1024] = { - 2, 3, 4, 4, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, - 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, - 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, - 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, - 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 4, 4, 3, +typedef struct SheerTable { + uint8_t lens[2 * 15]; + uint16_t nb_16s; +} SheerTable; + +static const SheerTable rgb[2] = { + { + { 0, 0, 2, 2, 3, 3, 5, 5, 8, 8, 10, 9, 14, 15, 18, + 17, 16, 13, 10, 10, 8, 7, 6, 5, 3, 2, 3, 0, 0, 0 }, 54 + }, + { + { 0, 2, 0, 2, 0, 1, 1, 0, 2, 1, 3, 3, 4, 7, 13, + 11, 8, 4, 3, 3, 1, 2, 1, 0, 1, 0, 1, 2, 0, 0 }, 180 + } +}; + +static const SheerTable rgbi[2] = { + { + { 0, 0, 1, 3, 3, 3, 6, 8, 8, 11, 12, 15, 18, 21, 38, + 0, 22, 19, 15, 12, 11, 7, 8, 6, 4, 2, 3, 0, 0, 0 }, 0 + }, + { + { 1, 0, 1, 1, 1, 1, 2, 1, 2, 4, 3, 5, 5, 6, 12, + 14, 6, 6, 5, 3, 3, 3, 2, 1, 1, 2, 0, 1, 0, 0 }, 164 + } +}; + +static const SheerTable ybr[2] = { + { + { 0, 0, 2, 2, 2, 3, 5, 5, 7, 7, 8, 9, 13, 13, 19, + 16, 14, 12, 9, 9, 7, 6, 6, 4, 4, 1, 2, 1, 0, 0 }, 70 + }, + { + { 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 2, 2, 3, 5, 5, + 5, 5, 3, 2, 2, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0 }, 212 + } +}; + +static const SheerTable ybyr[2] = { + { + { 0, 0, 2, 2, 3, 3, 5, 5, 8, 8, 10, 10, 13, 15, 19, + 18, 15, 12, 10, 10, 8, 7, 6, 5, 3, 2, 3, 0, 0, 0 }, 54 + }, + { + { 1, 1, 0, 1, 0, 1, 0, 1, 1, 2, 2, 3, 2, 5, 5, + 5, 4, 3, 2, 2, 2, 1, 1, 1, 1, 0, 0, 1, 0, 0 }, 208 + } +}; + +static const SheerTable byry[2] = { + { + { 0, 0, 2, 2, 2, 3, 5, 5, 7, 7, 8, 11, 10, 14, 19, + 14, 16, 12, 10, 8, 7, 6, 6, 4, 4, 1, 2, 1, 0, 0 }, 70 + }, + { + { 1, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, 2, 3, 4, 6, + 6, 4, 2, 3, 2, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0 }, 208 + } +}; + +static const SheerTable ybr10i[2] = { + { + { 0, 0, 1, 0, 3, 8, 9, 12, 19, 27, 27, 39, 50, 63, 93, + 89, 64, 50, 38, 26, 26, 20, 12, 9, 8, 3, 0, 0, 0, 0 }, 328 + }, + { + { 0, 1, 1, 2, 2, 1, 2, 2, 4, 4, 6, 7, 9, 13, 28, + 28, 12, 11, 6, 7, 5, 3, 3, 1, 1, 2, 2, 1, 0, 0 }, 860 + } +}; + +static const SheerTable ybr10[2] = { + { + { 0, 0, 0, 1, 6, 6, 8, 12, 18, 21, 27, 29, 36, 47, 71, + 72, 46, 36, 29, 27, 21, 17, 13, 7, 7, 5, 0, 0, 0, 0 }, 462 + }, + { + { 0, 1, 2, 1, 2, 1, 1, 1, 2, 3, 2, 5, 6, 10, 20, + 20, 10, 6, 4, 3, 2, 2, 2, 1, 1, 1, 2, 1, 0, 0 }, 912 + } +}; + +static const SheerTable rgbx[2] = { + { + { 0, 0, 0, 1, 3, 9, 10, 13, 19, 26, 28, 35, 40, 53, 77, + 77, 50, 42, 34, 28, 25, 19, 13, 10, 8, 4, 0, 0, 0, 0 }, 400 + }, + { + { 0, 0, 1, 2, 6, 4, 3, 2, 3, 4, 6, 8, 10, 18, 39, + 39, 18, 11, 8, 6, 4, 4, 1, 3, 5, 4, 3, 0, 0, 0 }, 812 + } +}; + +static const SheerTable yry10[2] = { + { + { 0, 0, 0, 1, 6, 6, 8, 12, 18, 21, 27, 29, 36, 47, 71, + 72, 46, 36, 29, 27, 21, 17, 13, 7, 7, 5, 0, 0, 0, 0 }, 462 + }, + { + { 0, 1, 2, 1, 1, 1, 2, 3, 2, 4, 5, 5, 8, 14, 16, + 18, 11, 7, 7, 4, 4, 3, 2, 2, 1, 1, 2, 1, 0, 0 }, 896 + } +}; + +static const SheerTable yry10i[2] = { + { + { 0, 0, 1, 0, 3, 8, 9, 12, 19, 27, 27, 40, 48, 64, 93, + 89, 65, 49, 38, 26, 26, 20, 12, 9, 8, 3, 0, 0, 0, 0 }, 328 + }, + { + { 0, 1, 0, 3, 1, 3, 3, 3, 6, 7, 7, 12, 11, 19, 23, + 20, 18, 12, 12, 8, 6, 5, 4, 3, 2, 2, 2, 1, 0, 0 }, 830 + } +}; + +static const SheerTable ybri[2] = { + { + { 0, 0, 2, 2, 2, 3, 5, 5, 7, 10, 11, 13, 15, 13, 26, + 20, 16, 17, 12, 11, 9, 7, 5, 5, 3, 3, 1, 1, 0, 0 }, 32 + }, + { + { 1, 0, 1, 0, 1, 1, 0, 2, 1, 2, 2, 2, 3, 6, 6, + 5, 6, 3, 2, 2, 2, 1, 2, 0, 1, 1, 0, 0, 1, 0 }, 202 + } +}; + +static const SheerTable byryi[2] = { + { + { 0, 0, 2, 2, 2, 2, 6, 5, 8, 8, 12, 12, 16, 14, 24, + 20, 16, 18, 12, 12, 8, 7, 5, 6, 3, 1, 2, 1, 0, 0 }, 32 + }, + { + { 1, 0, 1, 1, 0, 2, 1, 2, 2, 3, 3, 4, 5, 4, 6, + 7, 5, 4, 4, 3, 3, 2, 2, 2, 0, 1, 1, 1, 0, 0 }, 186 + } +}; + +static const SheerTable rgbxi[2] = { + { + { 0, 0, 1, 3, 2, 3, 4, 6, 16, 23, 27, 29, 24, 29, 76, + 78, 29, 21, 29, 27, 23, 15, 7, 4, 3, 2, 3, 0, 0, 0 }, 540 + }, + { + { 0, 1, 1, 2, 0, 2, 6, 4, 3, 9, 7, 12, 13, 16, 29, + 32, 17, 14, 12, 7, 8, 4, 4, 6, 2, 0, 2, 1, 0, 0 }, 810 + } }; #endif /* AVCODEC_SHEERVIDEODATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/shorten.c ffmpeg-4.4/libavcodec/shorten.c --- ffmpeg-4.2.2/libavcodec/shorten.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/shorten.c 2021-04-08 21:28:39.000000000 +0000 @@ -808,8 +808,12 @@ .init = shorten_decode_init, .close = shorten_decode_close, .decode = shorten_decode_frame, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DELAY | + AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_SUBFRAMES , .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/simple_idct.c ffmpeg-4.4/libavcodec/simple_idct.c --- ffmpeg-4.2.2/libavcodec/simple_idct.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/simple_idct.c 2021-02-20 20:27:47.000000000 +0000 @@ -175,7 +175,8 @@ #define R_SHIFT 11 static inline void idct4row(int16_t *row) { - int c0, c1, c2, c3, a0, a1, a2, a3; + unsigned c0, c1, c2, c3; + int a0, a1, a2, a3; a0 = row[0]; a1 = row[1]; diff -Nru ffmpeg-4.2.2/libavcodec/simple_idct_template.c ffmpeg-4.4/libavcodec/simple_idct_template.c --- ffmpeg-4.2.2/libavcodec/simple_idct_template.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/simple_idct_template.c 2020-07-11 10:39:30.000000000 +0000 @@ -121,7 +121,7 @@ // TODO: Add DC-only support for int32_t input #if IN_IDCT_DEPTH == 16 #if HAVE_FAST_64BIT -#define ROW0_MASK (0xffffLL << 48 * HAVE_BIGENDIAN) +#define ROW0_MASK (0xffffULL << 48 * HAVE_BIGENDIAN) if (((AV_RN64A(row) & ~ROW0_MASK) | AV_RN64A(row+4)) == 0) { uint64_t temp; if (DC_SHIFT - extra_shift >= 0) { diff -Nru ffmpeg-4.2.2/libavcodec/sinewin.c ffmpeg-4.4/libavcodec/sinewin.c --- ffmpeg-4.2.2/libavcodec/sinewin.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sinewin.c 2021-04-08 21:28:39.000000000 +0000 @@ -16,6 +16,5 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#define USE_FIXED 0 #include "sinewin.h" #include "sinewin_tablegen.h" diff -Nru ffmpeg-4.2.2/libavcodec/sinewin_fixed.c ffmpeg-4.4/libavcodec/sinewin_fixed.c --- ffmpeg-4.2.2/libavcodec/sinewin_fixed.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sinewin_fixed.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +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 - */ - -#define USE_FIXED 1 -#include "sinewin.h" -#include "sinewin_tablegen.h" diff -Nru ffmpeg-4.2.2/libavcodec/sinewin_fixed_tablegen.c ffmpeg-4.4/libavcodec/sinewin_fixed_tablegen.c --- ffmpeg-4.2.2/libavcodec/sinewin_fixed_tablegen.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sinewin_fixed_tablegen.c 2021-04-08 21:28:39.000000000 +0000 @@ -20,5 +20,23 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#define USE_FIXED 1 -#include "sinewin_tablegen_template.c" +#include "tableprint.h" + +#define BUILD_TABLES +#define CONFIG_HARDCODED_TABLES 0 +#include "sinewin_fixed_tablegen.h" + +int main(void) +{ + write_fileheader(); + + init_sine_windows_fixed(); +#define PRINT_TABLE(size) \ + printf("SINETABLE("#size") = {\n"); \ + write_int32_t_array(sine_ ## size ## _fixed, size); \ + printf("};\n") + PRINT_TABLE(128); + PRINT_TABLE(512); + PRINT_TABLE(1024); + return 0; +} diff -Nru ffmpeg-4.2.2/libavcodec/sinewin_fixed_tablegen.h ffmpeg-4.4/libavcodec/sinewin_fixed_tablegen.h --- ffmpeg-4.2.2/libavcodec/sinewin_fixed_tablegen.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sinewin_fixed_tablegen.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,67 @@ +/* + * Header file for hardcoded sine windows + * + * Copyright (c) 2009 Reimar Döffinger + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_SINEWIN_FIXED_TABLEGEN_H +#define AVCODEC_SINEWIN_FIXED_TABLEGEN_H + +#ifdef BUILD_TABLES +#undef DECLARE_ALIGNED +#define DECLARE_ALIGNED(align, type, name) type name +#else +#include "libavutil/mem_internal.h" +#endif + +#define SINETABLE(size) \ + static SINETABLE_CONST DECLARE_ALIGNED(32, int, sine_##size##_fixed)[size] + +#if CONFIG_HARDCODED_TABLES +#define init_sine_windows_fixed() +#define SINETABLE_CONST const +#include "libavcodec/sinewin_fixed_tables.h" +#else +// do not use libavutil/libm.h since this is compiled both +// for the host and the target and config.h is only valid for the target +#include +#include "libavutil/attributes.h" + +#define SINETABLE_CONST +SINETABLE( 128); +SINETABLE( 512); +SINETABLE(1024); + +#define SIN_FIX(a) (int)floor((a) * 0x80000000 + 0.5) + +// Generate a sine window. +static av_cold void sine_window_init_fixed(int *window, int n) +{ + for (int i = 0; i < n; i++) + window[i] = SIN_FIX(sinf((i + 0.5) * (M_PI / (2.0 * n)))); +} + +static av_cold void init_sine_windows_fixed(void) +{ + sine_window_init_fixed(sine_128_fixed, 128); + sine_window_init_fixed(sine_512_fixed, 512); + sine_window_init_fixed(sine_1024_fixed, 1024); +} +#endif /* CONFIG_HARDCODED_TABLES */ +#endif /* AVCODEC_SINEWIN_FIXED_TABLEGEN_H */ diff -Nru ffmpeg-4.2.2/libavcodec/sinewin.h ffmpeg-4.4/libavcodec/sinewin.h --- ffmpeg-4.2.2/libavcodec/sinewin.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sinewin.h 2021-04-08 21:28:39.000000000 +0000 @@ -22,8 +22,7 @@ #define AVCODEC_SINEWIN_H #include "config.h" -#include "libavutil/mem.h" -#include "libavcodec/aac_defines.h" +#include "libavutil/mem_internal.h" #if CONFIG_HARDCODED_TABLES # define SINETABLE_CONST const @@ -31,40 +30,31 @@ # define SINETABLE_CONST #endif -#ifndef USE_FIXED -#define USE_FIXED 0 -#endif - #define SINETABLE(size) \ - SINETABLE_CONST DECLARE_ALIGNED(32, INTFLOAT, AAC_RENAME(ff_sine_##size))[size] - -#define SINETABLE120960(size) \ - DECLARE_ALIGNED(32, INTFLOAT, AAC_RENAME(ff_sine_##size))[size] + SINETABLE_CONST DECLARE_ALIGNED(32, float, ff_sine_##size)[size] /** * Generate a sine window. * @param window pointer to half window * @param n size of half window */ -void AAC_RENAME(ff_sine_window_init)(INTFLOAT *window, int n); +void ff_sine_window_init(float *window, int n); /** * initialize the specified entry of ff_sine_windows */ -void AAC_RENAME(ff_init_ff_sine_windows)(int index); +void ff_init_ff_sine_windows(int index); extern SINETABLE( 32); extern SINETABLE( 64); -extern SINETABLE120960(120); extern SINETABLE( 128); extern SINETABLE( 256); extern SINETABLE( 512); -extern SINETABLE120960(960); extern SINETABLE(1024); extern SINETABLE(2048); extern SINETABLE(4096); extern SINETABLE(8192); -extern SINETABLE_CONST INTFLOAT * const AAC_RENAME(ff_sine_windows)[16]; +extern SINETABLE_CONST float *const ff_sine_windows[]; #endif /* AVCODEC_SINEWIN_H */ diff -Nru ffmpeg-4.2.2/libavcodec/sinewin_tablegen.c ffmpeg-4.4/libavcodec/sinewin_tablegen.c --- ffmpeg-4.2.2/libavcodec/sinewin_tablegen.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sinewin_tablegen.c 2021-04-08 21:28:39.000000000 +0000 @@ -20,5 +20,26 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#define USE_FIXED 0 -#include "sinewin_tablegen_template.c" +#define CONFIG_HARDCODED_TABLES 0 +#define BUILD_TABLES + +#define SINETABLE_CONST +#define SINETABLE(size) \ + float ff_sine_##size[size] +#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) +#include "sinewin_tablegen.h" +#include "tableprint.h" + +int main(void) +{ + write_fileheader(); + + for (int i = 5; i <= 13; i++) { + ff_init_ff_sine_windows(i); + printf("SINETABLE(%4i) = {\n", 1 << i); + write_float_array(ff_sine_windows[i], 1 << i); + printf("};\n"); + } + + return 0; +} diff -Nru ffmpeg-4.2.2/libavcodec/sinewin_tablegen.h ffmpeg-4.4/libavcodec/sinewin_tablegen.h --- ffmpeg-4.2.2/libavcodec/sinewin_tablegen.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sinewin_tablegen.h 2021-04-08 21:28:39.000000000 +0000 @@ -27,15 +27,14 @@ // do not use libavutil/libm.h since this is compiled both // for the host and the target and config.h is only valid for the target #include -#include "libavcodec/aac_defines.h" #include "libavutil/attributes.h" #include "libavutil/common.h" -#if !USE_FIXED -SINETABLE120960(120); -SINETABLE120960(960); -#endif #if !CONFIG_HARDCODED_TABLES +#ifndef BUILD_TABLES +#include "libavutil/thread.h" +#endif + SINETABLE( 32); SINETABLE( 64); SINETABLE( 128); @@ -46,37 +45,68 @@ SINETABLE(4096); SINETABLE(8192); #else -#if USE_FIXED -#include "libavcodec/sinewin_fixed_tables.h" -#else #include "libavcodec/sinewin_tables.h" #endif -#endif -#if USE_FIXED -#define SIN_FIX(a) (int)floor((a) * 0x80000000 + 0.5) -#else -#define SIN_FIX(a) a -#endif - -SINETABLE_CONST INTFLOAT * const AAC_RENAME(ff_sine_windows)[] = { +SINETABLE_CONST float *const ff_sine_windows[] = { NULL, NULL, NULL, NULL, NULL, // unused - AAC_RENAME(ff_sine_32) , AAC_RENAME(ff_sine_64), AAC_RENAME(ff_sine_128), - AAC_RENAME(ff_sine_256), AAC_RENAME(ff_sine_512), AAC_RENAME(ff_sine_1024), - AAC_RENAME(ff_sine_2048), AAC_RENAME(ff_sine_4096), AAC_RENAME(ff_sine_8192), + ff_sine_32, ff_sine_64, ff_sine_128, + ff_sine_256, ff_sine_512, ff_sine_1024, + ff_sine_2048, ff_sine_4096, ff_sine_8192, }; // Generate a sine window. -av_cold void AAC_RENAME(ff_sine_window_init)(INTFLOAT *window, int n) { +av_cold void ff_sine_window_init(float *window, int n) +{ int i; for(i = 0; i < n; i++) - window[i] = SIN_FIX(sinf((i + 0.5) * (M_PI / (2.0 * n)))); + window[i] = sinf((i + 0.5) * (M_PI / (2.0 * n))); } -av_cold void AAC_RENAME(ff_init_ff_sine_windows)(int index) { - assert(index >= 0 && index < FF_ARRAY_ELEMS(AAC_RENAME(ff_sine_windows))); +#if !CONFIG_HARDCODED_TABLES && !defined(BUILD_TABLES) +#define INIT_FF_SINE_WINDOW_INIT_FUNC(index) \ +static void init_ff_sine_window_ ## index(void) \ +{ \ + ff_sine_window_init(ff_sine_windows[index], 1 << index);\ +} + +INIT_FF_SINE_WINDOW_INIT_FUNC(5) +INIT_FF_SINE_WINDOW_INIT_FUNC(6) +INIT_FF_SINE_WINDOW_INIT_FUNC(7) +INIT_FF_SINE_WINDOW_INIT_FUNC(8) +INIT_FF_SINE_WINDOW_INIT_FUNC(9) +INIT_FF_SINE_WINDOW_INIT_FUNC(10) +INIT_FF_SINE_WINDOW_INIT_FUNC(11) +INIT_FF_SINE_WINDOW_INIT_FUNC(12) +INIT_FF_SINE_WINDOW_INIT_FUNC(13) + +static void (*const sine_window_init_func_array[])(void) = { + init_ff_sine_window_5, + init_ff_sine_window_6, + init_ff_sine_window_7, + init_ff_sine_window_8, + init_ff_sine_window_9, + init_ff_sine_window_10, + init_ff_sine_window_11, + init_ff_sine_window_12, + init_ff_sine_window_13, +}; + +static AVOnce init_sine_window_once[9] = { + AV_ONCE_INIT, AV_ONCE_INIT, AV_ONCE_INIT, AV_ONCE_INIT, AV_ONCE_INIT, + AV_ONCE_INIT, AV_ONCE_INIT, AV_ONCE_INIT, AV_ONCE_INIT +}; +#endif + +av_cold void ff_init_ff_sine_windows(int index) +{ + assert(index >= 5 && index < FF_ARRAY_ELEMS(ff_sine_windows)); #if !CONFIG_HARDCODED_TABLES - AAC_RENAME(ff_sine_window_init)(AAC_RENAME(ff_sine_windows)[index], 1 << index); +#ifdef BUILD_TABLES + ff_sine_window_init(ff_sine_windows[index], 1 << index); +#else + ff_thread_once(&init_sine_window_once[index - 5], sine_window_init_func_array[index - 5]); +#endif #endif } diff -Nru ffmpeg-4.2.2/libavcodec/sinewin_tablegen_template.c ffmpeg-4.4/libavcodec/sinewin_tablegen_template.c --- ffmpeg-4.2.2/libavcodec/sinewin_tablegen_template.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sinewin_tablegen_template.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -/* - * Generate a header file for hardcoded sine windows - * - * Copyright (c) 2009 Reimar Döffinger - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include "libavcodec/aac_defines.h" -#define CONFIG_HARDCODED_TABLES 0 - -#if USE_FIXED -#define WRITE_FUNC write_int32_t_array -#else -#define WRITE_FUNC write_float_array -#endif - -#define SINETABLE_CONST -#define SINETABLE(size) \ - INTFLOAT AAC_RENAME(ff_sine_##size)[size] -#define SINETABLE120960(size) \ - INTFLOAT AAC_RENAME(ff_sine_##size)[size] -#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) -#include "sinewin_tablegen.h" -#include "tableprint.h" - -int main(void) -{ - int i; - - write_fileheader(); - - for (i = 5; i <= 13; i++) { - AAC_RENAME(ff_init_ff_sine_windows)(i); - printf("SINETABLE(%4i) = {\n", 1 << i); - WRITE_FUNC(AAC_RENAME(ff_sine_windows)[i], 1 << i); - printf("};\n"); - } - - return 0; -} diff -Nru ffmpeg-4.2.2/libavcodec/sipr.c ffmpeg-4.4/libavcodec/sipr.c --- ffmpeg-4.2.2/libavcodec/sipr.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sipr.c 2021-04-08 21:28:39.000000000 +0000 @@ -570,5 +570,6 @@ .priv_data_size = sizeof(SiprContext), .init = sipr_decoder_init, .decode = sipr_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/sipr.h ffmpeg-4.4/libavcodec/sipr.h --- ffmpeg-4.2.2/libavcodec/sipr.h 2016-03-29 02:25:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sipr.h 2021-04-08 21:28:39.000000000 +0000 @@ -26,7 +26,7 @@ #include "avcodec.h" #include "acelp_pitch_delay.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #define LP_FILTER_ORDER_16k 16 #define L_SUBFR_16k 80 diff -Nru ffmpeg-4.2.2/libavcodec/siren.c ffmpeg-4.4/libavcodec/siren.c --- ffmpeg-4.2.2/libavcodec/siren.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/siren.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,776 @@ +/* + * Siren audio decoder + * Copyright (c) 2012 Youness Alaoui + * Copyright (c) 2018 Paul B Mahol + * Copyright (c) 2019 Lynne + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/tx.h" +#include "libavutil/float_dsp.h" +#include "libavutil/mem_internal.h" + +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "mathops.h" + +static const uint8_t index_table[8] = {4, 4, 3, 3, 2, 2, 1, 0}; +static const uint8_t vector_dimension[8] = { 2, 2, 2, 4, 4, 5, 5, 1 }; +static const uint8_t number_of_vectors[8] = { 10, 10, 10, 5, 5, 4, 4, 20 }; +static const uint8_t expected_bits_table[8] = { 52, 47, 43, 37, 29, 22, 16, 0 }; +static const int8_t differential_decoder_tree[27][24][2] = { + { + {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, -12}, {-11, -10}, {-8, -9}, {-7, -6}, {-13, 12}, + {-5, -4}, {0, 13}, {-3, -14}, {-2, 14}, {-1, 15}, {-15, 16}, {-16, 17}, {-17, 18}, {19, 20}, + {21, 22}, {-18, -19}, {-20, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {5, 6}, {7, 8}, {-10, -9}, {-8, -11}, {-7, -6}, {9, -5}, {10, -12}, {-4, 11}, + {-13, -3}, {12, -2}, {13, -14}, {-1, 14}, {15, -15}, {0, 16}, {-16, 17}, {-17, 18}, {-18, 19}, + {20, 21},{22, -19}, {-20, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {-12, 11}, {-11, -13}, {-10, -9}, {12, -14}, {-8, -7}, + {-15, -6}, {13, -5}, {-16, -4}, {14, -17}, {15, -3}, {16, -18}, {-2, 17}, {18, -19}, {-1, 19}, + {-20, 20}, {0, 21}, {22, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {5, 6}, {-11, -10}, {7, -12}, {8, -9}, {9, -13}, {-14, 10}, {-8, -15}, {-16, 11}, + {-7, 12}, {-17, -6}, {13, 14}, {-18, 15}, {-5, -4}, {16, 17}, {-3, -2}, {-19, 18}, {-1, 19}, + {-20, 20}, {21, 22}, {0, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {5, 6}, {-12, -11}, {-13, 7}, {8, -14}, {-10, 9}, {10, -15}, {-9, 11}, {-8, 12}, + {-16, 13}, {-7, -6}, {-17, 14}, {-5, -18}, {15, -4}, {16, -19}, {17, -3}, {-20, 18}, {-2, 19}, + {-21, 20}, {0, 21}, {22, -1}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {5, 6}, {-11, 7}, {-12, -10}, {-13, -9}, {8, 9}, {-14, -8}, {10, -15}, {-7, 11}, + {-16, 12}, {-6, -17}, {13, 14}, {-5, 15}, {-18, 16}, {-4, 17}, {-3, -19}, {18, -2}, {-20, 19}, + {-1, 20}, {0, 21}, {22, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {5, -12}, {6, -11}, {-10, -13}, {-9, 7}, {8, -14}, {9, -8}, {-15, 10}, {-7, -16}, + {11, -6}, {12, -17}, {13, -5}, {-18, 14}, {15, -4}, {-19, 16}, {17, -3}, {-20, 18}, {19, 20}, + {21, 22}, {0, -2}, {-1, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {5, -12}, {6, -13}, {-11, -10}, {7, -14}, {8, -9}, {9, -15}, {-8, 10}, {-7, -16}, + {11, 12}, {-6, -17}, {-5, 13}, {14, 15}, {-18, -4}, {-19, 16}, {-3, 17}, {18, -2}, {-20, 19}, + {20, 21}, {22, 0}, {-1, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {5, 6}, {-11, -10}, {-12, -9}, {7, 8}, {-13, -8}, {9, -14}, {-7, 10}, {-6, -15}, + {11, 12}, {-5, -16}, {13, 14}, {-17, 15}, {-4, 16}, {17, -18}, {18, -3}, {-2, 19}, {-1, 0}, + {-19, 20}, {-20, 21}, {22, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {5, 6}, {-11, 7}, {-10, -12}, {-9, 8}, {-8, -13}, {9, -7}, {10, -14}, {-6, 11}, + {-15, 12}, {-5, 13}, {-16, -4}, {14, 15}, {-17, -3}, {-18, 16}, {17, -19}, {-2, 18}, {-20, 19}, + {-1, 20}, {21, 22}, {0, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {5, -12}, {6, -11}, {7, 8}, {-10, -13}, {-9, 9}, {-8, -14}, {10, -7}, {11, -15}, + {-6, 12}, {-5, 13}, {-4, -16}, {14, 15}, {-3, -17}, {16, 17}, {-18, -2}, {18, -19}, {-1, 19}, + {-20, 20}, {-21, 21}, {22, 0}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {5, -12}, {-13, 6}, {-11, 7}, {-14, 8}, {-10, 9}, {-15, -9}, {-8, 10}, {-7, -16}, + {11, -6}, {12, -5}, {-17, 13}, {14, -18}, {15, -4}, {16, -19}, {17, -3}, {18, -2}, {19, -1}, + {-20, 20}, {21, 22}, {0, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, + { + {1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, + {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, + {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32} + }, +}; + +static const uint16_t decoder_tree0[360] = { + 2, 1, 4, 6, 8, 10, 12, 14, 16, 18, 33, 3, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 35, 40, + 42, 44, 46, 5, 48, 65, 50, 52, 54, 56, 58, 60, 62, 64, 37, 66, 67, 68, 97, 70, 72, 74, 7, + 76, 78, 80, 82, 84, 86, 88, 99, 90, 39, 92, 94, 96, 129, 98, 9, 100, 102, 104, 106, 108, + 110, 112, 41, 161, 69, 114, 116, 118, 131, 120, 122, 11, 124, 126, 128, 193, 130, 132, 71, + 134, 43, 136, 138, 140, 163, 101, 13, 142, 144, 146, 148, 150, 152, 154, 225, 156, 158, 195, + 160, 162, 45, 164, 15, 166, 73, 168, 170, 133, 47, 172, 257, 174, 176, 178, 75, 103, 180, 165, + 182, 17, 227, 184, 105, 49, 135, 186, 289, 188, 259, 190, 192, 194, 196, 198, 291, 77, 200, + 202, 197, 107, 204, 19, 51, 229, 206, 167, 208, 210, 212, 214, 21, 79, 81, 109, 216, 218, 220, + 222, 53, 137, 224, 199, 226, 323, 321, 169, 228, 111, 230, 232, 139, 261, 234, 83, 236, 201, + 238, 240, 293, 242, 353, 231, 141, 244, 246, 113, 23, 355, 85, 248, 55, 115, 250, 263, 252, + 254, 203, 171, 256, 258, 233, 235, 143, 357, 325, 260, 295, 262, 173, 145, 177, 87, 264, 327, + 267, 266, 268, 175, 270, 272, 117, 297, 274, 265, 147, 179, 205, 276, 207, 237, 269, 278, 57, + 59, 387, 209, 280, 282, 149, 329, 385, 284, 25, 286, 239, 119, 288, 27, 290, 292, 299, 294, 359, + 89, 296, 298, 419, 181, 300, 331, 271, 417, 211, 361, 151, 389, 241, 302, 304, 303, 306, 308, + 421, 91, 310, 312, 391, 314, 121, 316, 333, 318, 275, 213, 301, 243, 183, 335, 320, 363, 322, + 215, 324, 393, 273, 337, 153, 326, 423, 365, 328, 367, 247, 395, 185, 123, 330, 425, 245, 155, + 332, 334, 305, 397, 336, 277, 217, 338, 340, 339, 427, 342, 344, 346, 307, 399, 187, 348, 309, + 341, 350, 369, 279, 311, 429, 249, 219, 352, 354, 356, 358, 431, 373, 401, 371, 313, 281, 433, + 343, 403, 251, 283 +}; + +static const uint16_t decoder_tree1[188] = { + 2, 1, 4, 6, 8, 10, 12, 14, 16, 3, 33, 18, 20, 22, 24, 26, 35, 28, 30, 32, 34, 36, 5, 65, 38, 40, + 37, 42, 44, 46, 67, 48, 50, 52, 54, 56, 58, 60, 7, 62, 39, 97, 64, 69, 66, 99, 68, 70, 72, 74, 76, + 78, 80, 129, 41, 131, 82, 9, 71, 84, 86, 101, 88, 90, 92, 94, 96, 161, 43, 11, 73, 98, 103, 100, + 163, 102, 104, 106, 108, 133, 110, 105, 112, 75, 114, 45, 13, 116, 165, 118, 195, 135, 193, 120, 77, + 122, 47, 124, 167, 225, 126, 79, 107, 227, 128, 137, 197, 15, 130, 169, 199, 132, 109, 134, 17, 139, + 49, 136, 229, 138, 140, 81, 259, 142, 144, 171, 146, 141, 148, 111, 150, 201, 231, 152, 51, 257, 289, + 154, 19, 113, 156, 261, 158, 203, 173, 263, 143, 160, 291, 235, 83, 162, 233, 265, 164, 205, 166, 293, + 145, 168, 175, 177, 237, 115, 295, 170, 207, 172, 267, 174, 176, 297, 147, 178, 180, 269, 182, 271, + 209, 299, 239, 179, 184, 301, 241, 211, 0, 0 +}; + +static const uint16_t decoder_tree2[96] = { + 2, 1, 4, 6, 8, 10, 12, 3, 17, 14, 19, 16, 18, 20, 22, 24, 26, 5, 21, 35, 33, 28, 30, 32, 34, 36, 38, 37, + 40, 23, 51, 42, 7, 49, 44, 46, 48, 50, 39, 53, 52, 54, 56, 25, 67, 9, 58, 60, 65, 55, 41, 62, 64, 69, 66, + 11, 27, 68, 57, 83, 70, 71, 81, 43, 72, 74, 13, 76, 85, 29, 73, 78, 99, 59, 87, 101, 80, 97, 45, 82, 84, + 75, 89, 61, 86, 103, 88, 77, 90, 105, 91, 92, 107, 93, 0, 0 +}; + +static const uint16_t decoder_tree3[1040] = { + 2, 4, 6, 8, 10, 1, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 3, 36, 1025, 38, 40, 42, 44, 46, 48, 50, + 129, 17, 52, 54, 1153, 19, 56, 58, 60, 62, 64, 66, 68, 145, 70, 72, 74, 76, 78, 1169, 1027, 147, 80, 82, 1171, + 84, 86, 131, 88, 1155, 1043, 1041, 90, 92, 5, 94, 96, 98, 100, 102, 104, 21, 106, 108, 2049, 2177, 110, 112, 114, + 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 33, 144, 163, 146, 148, 150, 152, 154, 161, + 156, 35, 158, 1297, 160, 162, 273, 257, 164, 166, 149, 168, 1281, 170, 172, 2193, 174, 176, 178, 1299, 180, 1045, + 182, 184, 1173, 186, 3201, 188, 190, 192, 194, 2195, 1187, 23, 2179, 196, 7, 198, 275, 200, 2051, 202, 2065, 204, + 206, 1029, 1185, 208, 210, 1157, 37, 3073, 2067, 133, 212, 214, 2321, 216, 165, 218, 1059, 220, 1283, 222, 2305, + 224, 226, 228, 230, 259, 232, 234, 2323, 236, 1409, 1057, 1315, 238, 240, 242, 244, 246, 1425, 248, 1313, 250, 252, + 254, 256, 258, 260, 289, 262, 264, 1189, 266, 268, 179, 151, 270, 272, 274, 276, 278, 291, 280, 282, 9, 385, 284, + 286, 177, 49, 401, 1061, 288, 290, 292, 51, 294, 296, 298, 300, 302, 304, 25, 306, 2083, 39, 308, 310, 3329, 167, + 312, 314, 1175, 316, 318, 1203, 135, 320, 322, 324, 326, 328, 2211, 2307, 330, 1301, 332, 334, 1047, 336, 338, 2449, + 3217, 340, 1427, 2209, 53, 342, 2339, 3345, 344, 346, 348, 403, 181, 4097, 2197, 350, 2181, 1285, 1317, 1031, 352, + 354, 356, 3089, 358, 360, 4225, 277, 362, 364, 366, 368, 2069, 370, 3203, 293, 1201, 305, 372, 3219, 307, 2433, 374, + 376, 378, 380, 2081, 1411, 382, 384, 3075, 1443, 513, 386, 387, 388, 390, 1331, 261, 392, 394, 396, 398, 400, 1441, + 1075, 67, 1159, 402, 404, 406, 408, 410, 412, 414, 3347, 2325, 416, 65, 418, 420, 422, 424, 426, 2053, 193, 1073, 428, + 430, 432, 1537, 1329, 2337, 2213, 434, 417, 183, 41, 436, 438, 440, 442, 444, 446, 448, 450, 195, 2435, 452, 2085, 1063, + 1191, 454, 456, 458, 460, 419, 2071, 1553, 3091, 55, 137, 462, 464, 466, 468, 470, 472, 474, 476, 478, 2309, 4113, 480, + 482, 484, 486, 2451, 2465, 1205, 153, 488, 490, 492, 494, 496, 498, 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, + 520, 522, 524, 1333, 526, 1555, 2467, 2227, 3205, 3331, 528, 530, 532, 534, 536, 538, 540, 542, 544, 546, 548, 529, 309, + 1303, 3473, 3457, 389, 1569, 1445, 1077, 69, 2199, 1539, 4353, 550, 552, 554, 556, 558, 560, 562, 1459, 4241, 3221, 1429, + 2341, 279, 3475, 169, 564, 545, 3105, 323, 2353, 2097, 3235, 421, 2229, 3107, 3233, 566, 568, 570, 572, 574, 576, 578, + 580, 582, 584, 586, 588, 590, 592, 594, 596, 2099, 1091, 531, 2437, 4227, 405, 197, 263, 1287, 2577, 1049, 1571, 598, 600, + 602, 604, 606, 608, 610, 612, 614, 616, 618, 620, 622, 624, 626, 628, 630, 632, 634, 636, 638, 640, 642, 644, 646, 648, 650, + 1345, 1219, 3077, 1457, 2225, 2579, 515, 2561, 2469, 433, 1221, 2183, 4243, 652, 654, 656, 658, 660, 662, 664, 666, 668, + 670, 1217, 3333, 3093, 435, 321, 4369, 1089, 2055, 4099, 3361, 1319, 547, 1161, 1177, 672, 2355, 4115, 1413, 4257, 3349, + 2453, 3109, 2357, 2215, 3363, 1079, 1207, 311, 1033, 1347, 1065, 674, 676, 678, 680, 682, 684, 686, 688, 690, 692, 694, 696, + 698, 700, 702, 704, 706, 708, 710, 712, 714, 716, 718, 720, 722, 724, 726, 728, 730, 732, 734, 736, 738, 740, 742, 744, 746, + 748, 750, 752, 754, 756, 758, 760, 762, 764, 766, 768, 770, 772, 774, 776, 778, 780, 782, 784, 786, 788, 790, 792, 794, 796, + 798, 800, 802, 804, 806, 808, 810, 812, 814, 2593, 2565, 4261, 3253, 437, 325, 3489, 2311, 4259, 1431, 2087, 2563, 295, 2343, + 449, 199, 265, 2201, 4371, 1193, 816, 533, 1557, 2581, 2241, 3365, 3491, 3603, 549, 2101, 1461, 1093, 2117, 3459, 3079, 4481, + 3095, 2327, 3461, 4129, 3249, 1447, 2471, 2231, 71, 4497, 2609, 1289, 393, 3251, 2073, 3097, 2371, 1305, 2089, 818, 820, 822, + 824, 826, 828, 830, 832, 834, 836, 838, 840, 842, 844, 846, 848, 850, 852, 854, 856, 858, 860, 862, 864, 866, 868, 870, 872, + 874, 876, 878, 880, 882, 884, 886, 888, 890, 892, 894, 896, 898, 900, 902, 904, 906, 908, 910, 912, 914, 916, 918, 920, 922, + 924, 926, 928, 930, 932, 934, 936, 938, 940, 942, 944, 946, 948, 950, 952, 954, 956, 958, 960, 962, 964, 966, 968, 970, 972, + 974, 976, 978, 980, 982, 984, 986, 988, 990, 992, 994, 996, 998, 1000, 1002, 1004, 1006, 1008, 1010, 1012, 1014, 1016, 1018, + 1020, 1022, 1024, 1026, 1028, 1030, 1032, 1034, 1036, 4161, 4273, 3507, 3493, 4517, 2497, 1573, 2597, 3621, 4531, 4627, 3523, + 3125, 4149, 4529, 3139, 4515, 451, 4277, 2113, 4163, 4499, 3381, 4405, 1473, 4373, 2485, 3509, 565, 1589, 2613, 3585, 3123, + 4403, 3141, 4147, 563, 2245, 3269, 4357, 1349, 2373, 3397, 453, 1477, 2501, 2481, 579, 1601, 3477, 4103, 3265, 2243, 1587, + 3207, 4231, 3267, 4501, 1475, 3335, 4359, 391, 1415, 2439, 3463, 4487, 519, 1543, 2567, 3591, 4609, 4289, 4611, 2499, 4119, + 4385, 4145, 4401, 3223, 4247, 3379, 577, 3393, 3351, 4375, 407, 1585, 2455, 3479, 4503, 535, 1559, 2583, 3607, 3605, 4513, + 4485, 3111, 4135, 3121, 517, 3377, 3239, 4263, 1541, 4291, 4229, 3367, 4391, 423, 2115, 4131, 3495, 551, 1575, 2599, 3635, 3395, + 2103, 3127, 4151, 3589, 4101, 1603, 3255, 4279, 3601, 1335, 2359, 3383, 439, 1463, 2487, 3511, 567, 1591, 4133, 1095, 2119, 3143, + 2369, 1223, 2247, 3271, 327, 1351, 2375, 455, 1479, 3137, 3521, 2057, 3081, 4105, 4387, 3505, 2185, 3209, 4233, 3587, 4355, 2313, + 3337, 3237, 1417, 2441, 3465, 521, 1545, 3617, 3633, 561, 4625, 4121, 2611, 2483, 2595, 3225, 4249, 281, 4245, 2329, 3353, 409, + 1433, 2457, 3481, 537, 1561, 4483, 3619, 4389, 3113, 4275, 4117, 2217, 3241, 297, 1321, 2345, 3369, 425, 1449, 2473, 57, 1081, + 2105, 3129, 185, 1209, 2233, 3257, 313, 1337, 2361, 441, 1465, 73, 1097, 201, 1225, 0, 0 +}; + +static const uint16_t decoder_tree4[416] = { + 2, 4, 6, 1, 8, 10, 12, 14, 16, 18, 20, 22, 24, 3, 129, 26, 28, 9, 33, 30, 32, + 34, 36, 11, 161, 38, 40, 42, 41, 44, 46, 131, 43, 169, 35, 48, 137, 50, 52, 54, 56, 139, + 163, 171, 58, 60, 62, 64, 5, 66, 68, 70, 257, 72, 74, 76, 13, 78, 80, 289, 82, 84, 17, + 86, 88, 65, 90, 201, 19, 92, 94, 51, 193, 96, 98, 49, 100, 73, 102, 104, 106, 45, 108, 110, + 297, 112, 114, 116, 37, 203, 118, 120, 179, 122, 177, 124, 265, 126, 75, 133, 259, 291, 147, 128, 67, + 195, 130, 141, 173, 299, 132, 145, 134, 165, 136, 138, 140, 142, 7, 144, 146, 21, 267, 148, 53, 150, + 321, 152, 154, 15, 156, 81, 158, 160, 385, 162, 417, 164, 166, 168, 83, 170, 172, 329, 174, 211, 176, + 27, 178, 180, 182, 209, 184, 186, 188, 190, 25, 192, 331, 194, 196, 105, 57, 198, 97, 200, 202, 323, + 225, 59, 149, 204, 206, 233, 307, 208, 77, 181, 210, 212, 214, 216, 218, 220, 222, 47, 224, 226, 69, + 228, 230, 197, 232, 425, 393, 205, 275, 293, 39, 234, 236, 238, 305, 135, 155, 301, 143, 240, 242, 235, + 395, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 273, 269, 185, 264, 266, 268, 270, 272, 274, 276, + 261, 153, 278, 280, 282, 187, 337, 387, 107, 284, 427, 227, 167, 419, 286, 288, 290, 292, 294, 296, 298, + 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 115, + 99, 85, 213, 29, 113, 23, 89, 241, 61, 449, 339, 175, 340, 342, 344, 346, 348, 350, 352, 354, 356, + 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, + 400, 402, 404, 406, 408, 410, 412, 414, 389, 361, 457, 465, 429, 451, 333, 109, 277, 243, 263, 295, 199, + 283, 151, 55, 183, 229, 357, 363, 123, 491, 397, 411, 251, 313, 441, 467, 345, 433, 461, 219, 237, 365, + 435, 353, 347, 405, 409, 217, 309, 437, 369, 371, 341, 117, 245, 249, 157, 285, 403, 189, 317, 93, 221, + 315, 401, 481, 391, 489, 121, 421, 423, 71, 483, 327, 103, 231, 443, 459, 271, 399, 355, 91, 303, 431, + 79, 207, 335, 111, 239, 281, 325, 279, 453, 101, 311, 87, 215, 31, 159, 63, 191 +}; + +static const uint16_t decoder_tree5[384] = { + 2, 4, 1, 6, 8, 10, 12, 14, 16, 18, 20, 22, 3, 513, 24, 26, 28, 9, 129, 33, 30, 32, 34, 36, 38, 40, 11, 42, 641, 44, 46, 41, + 161, 48, 515, 50, 52, 131, 54, 35, 545, 137, 56, 58, 60, 521, 62, 43, 673, 64, 169, 66, 68, 523, 70, 163, 643, 139, 553, 72, 649, 74, 547, + 76, 78, 80, 681, 171, 82, 84, 555, 86, 675, 88, 651, 5, 90, 92, 1025, 94, 96, 98, 683, 13, + 100, 17, 102, 104, 106, 65, 108, 110, 257, 112, 114, 1153, 19, 116, 118, 120, 122, 124, 49, 126, 128, + 769, 289, 130, 132, 134, 73, 136, 138, 140, 142, 193, 144, 146, 148, 150, 152, 154, 517, 156, 158, 37, + 51, 160, 201, 162, 145, 164, 166, 168, 133, 170, 801, 45, 172, 174, 1057, 176, 178, 67, 180, 1027, 577, + 182, 184, 186, 188, 190, 192, 194, 196, 198, 259, 200, 202, 204, 525, 177, 265, 141, 206, 208, 210, 212, + 195, 297, 214, 75, 216, 1033, 203, 585, 1155, 1185, 267, 1161, 549, 218, 220, 657, 777, 147, 222, 224, 226, + 228, 230, 232, 234, 236, 238, 240, 587, 645, 165, 242, 244, 246, 248, 250, 771, 291, 252, 579, 1065, 1035, + 705, 531, 529, 659, 173, 254, 561, 653, 256, 713, 677, 557, 258, 260, 262, 264, 266, 268, 270, 272, 274, + 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 707, 1059, 809, 715, 563, 179, 691, 1193, + 21, 779, 1067, 299, 1187, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, + 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, + 376, 378, 380, 83, 69, 1281, 803, 321, 1195, 1163, 811, 1323, 689, 1321, 1099, 305, 835, 1227, 331, 843, 785, + 593, 1043, 1291, 1283, 1171, 275, 787, 1217, 833, 1075, 1313, 1219, 1203, 307, 819, 841, 595, 211, 723, 721, 817, + 1029, 329, 81, 1157, 261, 773, 1097, 1089, 1061, 1169, 1091, 1189, 293, 805, 1201, 581, 197, 709, 1289, 273, 1037, + 1315, 1041, 1165, 269, 781, 209, 1073, 1069, 323, 685, 1197, 301, 813, 77, 589, 205, 717, 1225, 533, 149, 661, + 53, 565, 181, 693, 0, 0 +}; + +static const uint16_t decoder_tree6[62] = { + 2, 1, 4, 6, 8, 10, 12, 14, 16, 3, 33, 5, 17, 9, 18, 20, 22, 24, 26, 28, 30, 32, 34, 7, 49, 13, 25, 36, 38, 11, + 21, 41, 35, 37, 19, 40, 42, 44, 46, 48, 50, 15, 52, 57, 29, 27, 23, 53, 54, 51, 39, 45, 43, 56, 58, 31, 55, 60, + 61, 47, 59, 63 +}; + +static const uint16_t *const decoder_tables[7] = { + decoder_tree0, + decoder_tree1, + decoder_tree2, + decoder_tree3, + decoder_tree4, + decoder_tree5, + decoder_tree6, +}; + +static const int decoder_tables_elements[7] = { + FF_ARRAY_ELEMS(decoder_tree0), + FF_ARRAY_ELEMS(decoder_tree1), + FF_ARRAY_ELEMS(decoder_tree2), + FF_ARRAY_ELEMS(decoder_tree3), + FF_ARRAY_ELEMS(decoder_tree4), + FF_ARRAY_ELEMS(decoder_tree5), + FF_ARRAY_ELEMS(decoder_tree6), +}; + +static const float mlt_quant[7][14] = { + { 0.0f, 0.392f, 0.761f, 1.120f, 1.477f, 1.832f, 2.183f, 2.541f, 2.893f, 3.245f, 3.598f, 3.942f, 4.288f, 4.724f }, + { 0.0f, 0.544f, 1.060f, 1.563f, 2.068f, 2.571f, 3.072f, 3.562f, 4.070f, 4.620f, 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.746f, 1.464f, 2.180f, 2.882f, 3.584f, 4.316f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.006f, 2.000f, 2.993f, 3.985f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.321f, 2.703f, 3.983f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.657f, 3.491f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.964f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } +}; + +static const float noise_category5[21] = { + 0.70711f, 0.6179f, 0.5005f, 0.3220f, 0.17678f, 0.17678f, 0.17678f, 0.17678f, 0.17678f, 0.17678f, 0.17678f, + 0.17678f, 0.17678f, 0.17678f, 0.17678f, 0.17678f, 0.17678f, 0.17678f, 0.17678f, 0.17678f +}; + +static const float noise_category6[21] = { + 0.70711f, 0.5686f, 0.3563f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, + 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f +}; + +#define FRAME_SIZE 320 +#define REGION_SIZE 20 + +typedef struct SirenContext { + GetBitContext gb; + + int rate_control_possibilities; + int esf_adjustment; + int number_of_regions; + int scale_factor; + int sample_rate_bits; + + unsigned dw1, dw2, dw3, dw4; + + int absolute_region_power_index[32]; + float decoder_standard_deviation[32]; + int power_categories[32]; + int category_balance[32]; + float standard_deviation[64]; + float backup_frame[FRAME_SIZE]; + + AVFloatDSPContext *fdsp; + av_tx_fn tx_fn; + AVTXContext *tx_ctx; + + DECLARE_ALIGNED(32, float, imdct_buf)[4][FRAME_SIZE]; + float *window; + float *imdct_in; + float *imdct_out; + float *imdct_prev; +} SirenContext; + +static av_cold int siren_init(AVCodecContext *avctx) +{ + const float scale = 1.0f / (22.f * 32768.f); + SirenContext *s = avctx->priv_data; + int i; + + s->imdct_in = s->imdct_buf[0]; + s->imdct_out = s->imdct_buf[1]; + s->imdct_prev = s->imdct_buf[2]; + s->window = s->imdct_buf[3]; + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + + s->rate_control_possibilities = 16; + s->esf_adjustment = 7; + s->number_of_regions = 14; + s->scale_factor = 22; + s->dw1 = s->dw2 = s->dw3 = s->dw4 = 1; + + for (i = 0; i < 64; i++) { + float region_power = powf(10, (i - 24) * 0.3010299957); + + s->standard_deviation[i] = sqrtf(region_power); + } + + for (i = 0; i < FRAME_SIZE; i++) { + float angle = ((i + 0.5f) * M_PI_2) / 320.f; + s->window[i] = sinf(angle); + } + + s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); + if (!s->fdsp) + return AVERROR(ENOMEM); + + return av_tx_init(&s->tx_ctx, &s->tx_fn, AV_TX_FLOAT_MDCT, 1, FRAME_SIZE, &scale, 0); +} + +static int decode_envelope(SirenContext *s, GetBitContext *gb, + int number_of_regions, float *decoder_standard_deviation, + int *absolute_region_power_index, int esf_adjustment) +{ + absolute_region_power_index[0] = (int)get_bits(gb, 5) - esf_adjustment; + absolute_region_power_index[0] = av_clip(absolute_region_power_index[0], -24, 39); + decoder_standard_deviation[0] = s->standard_deviation[absolute_region_power_index[0] + 24]; + + for (int i = 1; i < number_of_regions; i++) { + int index = 0; + + do { + index = differential_decoder_tree[i - 1][index][get_bits1(gb)]; + } while (index > 0); + + absolute_region_power_index[i] = av_clip(absolute_region_power_index[i - 1] - index - 12, -24, 39); + decoder_standard_deviation[i] = s->standard_deviation[absolute_region_power_index[i] + 24]; + } + + return get_bits_count(gb); +} + +static int categorize_regions(int number_of_regions, int number_of_available_bits, + int *absolute_region_power_index, int *power_categories, + int *category_balance) +{ + int region, delta, i, temp; + int expected_number_of_code_bits; + int min, max; + int offset, num_rate_control_possibilities = 16, + raw_value, raw_max_idx = 0, raw_min_idx = 0; + int max_rate_categories[28]; + int min_rate_categories[28]; + int temp_category_balances[64]; + int *min_rate_ptr = NULL; + int *max_rate_ptr = NULL; + + offset = -32; + for (delta = 32; number_of_regions > 0 && delta > 0; delta /= 2) { + expected_number_of_code_bits = 0; + for (region = 0; region < number_of_regions; region++) { + i = (delta + offset - + absolute_region_power_index[region]) >> 1; + i = av_clip_uintp2(i, 3); + power_categories[region] = i; + expected_number_of_code_bits += expected_bits_table[i]; + + } + if (expected_number_of_code_bits >= number_of_available_bits - 32) + offset += delta; + } + + expected_number_of_code_bits = 0; + for (region = 0; region < number_of_regions; region++) { + i = (offset - absolute_region_power_index[region]) >> 1; + i = av_clip_uintp2(i, 3); + max_rate_categories[region] = min_rate_categories[region] = + power_categories[region] = i; + expected_number_of_code_bits += expected_bits_table[i]; + } + + min = max = expected_number_of_code_bits; + min_rate_ptr = max_rate_ptr = + temp_category_balances + num_rate_control_possibilities; + for (i = 0; i < num_rate_control_possibilities - 1; i++) { + if (min + max > number_of_available_bits * 2) { + raw_value = -99; + for (region = number_of_regions - 1; region >= 0; region--) { + if (min_rate_categories[region] < 7) { + temp = + offset - absolute_region_power_index[region] - + 2 * min_rate_categories[region]; + if (temp > raw_value) { + raw_value = temp; + raw_min_idx = region; + } + } + } + if (raw_value == -99) + return AVERROR_INVALIDDATA; + *min_rate_ptr++ = raw_min_idx; + min += + expected_bits_table[min_rate_categories[raw_min_idx] + 1] - + expected_bits_table[min_rate_categories[raw_min_idx]]; + min_rate_categories[raw_min_idx]++; + } else { + raw_value = 99; + for (region = 0; region < number_of_regions; region++) { + if (max_rate_categories[region] > 0) { + temp = + offset - absolute_region_power_index[region] - + 2 * max_rate_categories[region]; + if (temp < raw_value) { + raw_value = temp; + raw_max_idx = region; + } + } + } + if (raw_value == 99) + return AVERROR_INVALIDDATA; + + *--max_rate_ptr = raw_max_idx; + max += expected_bits_table[max_rate_categories[raw_max_idx] - 1] - + expected_bits_table[max_rate_categories[raw_max_idx]]; + max_rate_categories[raw_max_idx]--; + } + } + + for (region = 0; region < number_of_regions; region++) + power_categories[region] = max_rate_categories[region]; + + for (i = 0; i < num_rate_control_possibilities - 1; i++) + category_balance[i] = *max_rate_ptr++; + + return 0; +} + +static int get_dw(SirenContext *s) +{ + int ret = s->dw1 + s->dw4; + + if ((ret & 0x8000) != 0) + ret++; + + s->dw1 = s->dw2; + s->dw2 = s->dw3; + s->dw3 = s->dw4; + s->dw4 = ret; + + return ret; +} + +static int decode_vector(SirenContext *s, int number_of_regions, + int number_of_available_bits, float *decoder_standard_deviation, + int *power_categories, float *coefs, int scale_factor) +{ + GetBitContext *gb = &s->gb; + float *coefs_ptr; + float decoded_value; + float noise; + const uint16_t *decoder_tree; + int region; + int category; + int i, j; + int index; + int error = 0; + int dw1; + int dw2; + + for (region = 0; region < number_of_regions; region++) { + category = power_categories[region]; + coefs_ptr = coefs + (region * REGION_SIZE); + + if (category >= 0 && category < 7) { + decoder_tree = decoder_tables[category]; + + for (i = 0; i < number_of_vectors[category]; i++) { + index = 0; + do { + if (get_bits_left(gb) <= 0) { + error = 1; + break; + } + + if (index + show_bits1(gb) >= decoder_tables_elements[category]) { + error = 1; + break; + } + index = decoder_tree[index + get_bits1(gb)]; + } while ((index & 1) == 0); + + index >>= 1; + + if (error == 0 && get_bits_left(gb) >= 0) { + for (j = 0; j < vector_dimension[category]; j++) { + decoded_value = mlt_quant[category][index & ((1 << index_table[category]) - 1)]; + index >>= index_table[category]; + + if (decoded_value) { + if (!get_bits1(gb)) + decoded_value *= -decoder_standard_deviation[region]; + else + decoded_value *= decoder_standard_deviation[region]; + } + + *coefs_ptr++ = decoded_value * scale_factor; + } + } else { + error = 1; + break; + } + } + + if (error == 1) { + for (j = region + 1; j < number_of_regions; j++) + power_categories[j] = 7; + category = 7; + } + } + + coefs_ptr = coefs + (region * REGION_SIZE); + + if (category == 5 || category == 6) { + i = 0; + for (j = 0; j < REGION_SIZE; j++) { + if (*coefs_ptr != 0) + i++; + coefs_ptr++; + } + + if (category == 5) { + noise = decoder_standard_deviation[region] * noise_category5[i]; + } else + noise = decoder_standard_deviation[region] * noise_category6[i]; + } else if (category == 7) { + noise = decoder_standard_deviation[region] * 0.70711f; + } else { + noise = 0; + } + + coefs_ptr = coefs + (region * REGION_SIZE); + + if (category == 5 || category == 6 || category == 7) { + dw1 = get_dw(s); + dw2 = get_dw(s); + + for (j = 0; j < 10; j++) { + if (category == 7 || *coefs_ptr == 0) + *coefs_ptr = dw1 & 1 ? noise : -noise; + coefs_ptr++; + dw1 >>= 1; + + if (category == 7 || *coefs_ptr == 0) + *coefs_ptr = dw2 & 1 ? noise : -noise; + coefs_ptr++; + dw2 >>= 1; + } + } + } + + return error == 1 ? AVERROR_INVALIDDATA : get_bits_left(gb); +} + +static int siren_decode(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + SirenContext *s = avctx->priv_data; + GetBitContext *gb = &s->gb; + AVFrame *frame = data; + int ret, number_of_valid_coefs = 20 * s->number_of_regions; + int frame_error = 0, rate_control = 0; + + if ((ret = init_get_bits8(gb, avpkt->data, avpkt->size)) < 0) + return ret; + + decode_envelope(s, gb, s->number_of_regions, + s->decoder_standard_deviation, + s->absolute_region_power_index, s->esf_adjustment); + + rate_control = get_bits(gb, 4); + + ret = categorize_regions(s->number_of_regions, get_bits_left(gb), + s->absolute_region_power_index, s->power_categories, + s->category_balance); + if (ret < 0) + return ret; + + for (int i = 0; i < rate_control; i++) + s->power_categories[s->category_balance[i]]++; + + ret = decode_vector(s, s->number_of_regions, get_bits_left(gb), + s->decoder_standard_deviation, s->power_categories, + s->imdct_in, s->scale_factor); + if (ret < 0) + return ret; + + if (get_bits_left(gb) > 0) { + do { + frame_error |= !get_bits1(gb); + } while (get_bits_left(gb) > 0); + } else if (get_bits_left(gb) < 0 && + rate_control + 1 < s->rate_control_possibilities) { + frame_error = 1; + } + + for (int i = 0; i < s->number_of_regions; i++) { + if (s->absolute_region_power_index[i] > 33 || + s->absolute_region_power_index[i] < -31) + frame_error = 1; + } + + if (frame_error) { + memcpy(s->imdct_in, s->backup_frame, number_of_valid_coefs * sizeof(float)); + memset(s->backup_frame, 0, number_of_valid_coefs * sizeof(float)); + } else { + memcpy(s->backup_frame, s->imdct_in, number_of_valid_coefs * sizeof(float)); + } + + frame->nb_samples = FRAME_SIZE; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (int i = 0; i < 320; i += 2) + s->imdct_in[i] *= -1; + + s->tx_fn(s->tx_ctx, s->imdct_out, s->imdct_in, sizeof(float)); + s->fdsp->vector_fmul_window((float *)frame->data[0], + s->imdct_prev + (FRAME_SIZE >> 1), + s->imdct_out, s->window, + FRAME_SIZE >> 1); + FFSWAP(float *, s->imdct_out, s->imdct_prev); + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold void siren_flush(AVCodecContext *avctx) +{ + SirenContext *s = avctx->priv_data; + + memset(s->backup_frame, 0, sizeof(s->backup_frame)); + memset(s->imdct_prev, 0, FRAME_SIZE * sizeof(*s->imdct_prev)); + memset(s->imdct_out, 0, FRAME_SIZE * sizeof(*s->imdct_out)); +} + +static av_cold int siren_close(AVCodecContext *avctx) +{ + SirenContext *s = avctx->priv_data; + + av_freep(&s->fdsp); + av_tx_uninit(&s->tx_ctx); + + return 0; +} + +AVCodec ff_siren_decoder = { + .name = "siren", + .long_name = NULL_IF_CONFIG_SMALL("Siren"), + .priv_data_size = sizeof(SirenContext), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_SIREN, + .init = siren_init, + .close = siren_close, + .decode = siren_decode, + .flush = siren_flush, + .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff -Nru ffmpeg-4.2.2/libavcodec/smacker.c ffmpeg-4.4/libavcodec/smacker.c --- ffmpeg-4.2.2/libavcodec/smacker.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/smacker.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,19 +33,27 @@ #include "libavutil/channel_layout.h" -#define BITSTREAM_READER_LE #include "avcodec.h" -#include "bytestream.h" -#include "get_bits.h" -#include "internal.h" -#include "mathops.h" #define SMKTREE_BITS 9 #define SMK_NODE 0x80000000 -#define SMKTREE_DECODE_MAX_RECURSION 32 +#define SMKTREE_DECODE_MAX_RECURSION FFMIN(32, 3 * SMKTREE_BITS) #define SMKTREE_DECODE_BIG_MAX_RECURSION 500 +/* The maximum possible unchecked overread happens in decode_header_trees: + * Decoding the MMAP tree can overread by 6 * SMKTREE_BITS + 1, followed by + * three get_bits1, followed by at most 2 + 3 * 16 read bits when reading + * the TYPE tree before the next check. 64 is because of 64 bit reads. */ +#if (6 * SMKTREE_BITS + 1 + 3 + (2 + 3 * 16) + 64) <= 8 * AV_INPUT_BUFFER_PADDING_SIZE +#define UNCHECKED_BITSTREAM_READER 1 +#endif +#define BITSTREAM_READER_LE +#include "bytestream.h" +#include "get_bits.h" +#include "internal.h" +#include "mathops.h" + typedef struct SmackVContext { AVCodecContext *avctx; AVFrame *pic; @@ -54,25 +62,27 @@ int mmap_last[3], mclr_last[3], full_last[3], type_last[3]; } SmackVContext; +typedef struct HuffEntry { + uint8_t value; + uint8_t length; +} HuffEntry; + /** * Context used for code reconstructing */ typedef struct HuffContext { - int length; - int maxlength; int current; - uint32_t *bits; - int *lengths; - int *values; + HuffEntry entries[256]; } HuffContext; /* common parameters used for decode_bigtree */ typedef struct DBCtx { + int current, length; + int *values; VLC *v1, *v2; - int *recode1, *recode2; + uint8_t vals[2]; int escapes[3]; int *last; - int lcur; } DBCtx; /* possible runs of blocks */ @@ -94,8 +104,11 @@ /** * Decode local frame tree + * + * Can read SMKTREE_DECODE_MAX_RECURSION before the first check; + * does not overread gb on success. */ -static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t prefix, int length) +static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, int length) { if (length > SMKTREE_DECODE_MAX_RECURSION || length > 3 * SMKTREE_BITS) { av_log(NULL, AV_LOG_ERROR, "Maximum tree recursion level exceeded.\n"); @@ -103,37 +116,30 @@ } if(!get_bits1(gb)){ //Leaf - if(hc->current >= hc->length){ + if (hc->current >= 256) { av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); return AVERROR_INVALIDDATA; } - if(length){ - hc->bits[hc->current] = prefix; - hc->lengths[hc->current] = length; - } else { - hc->bits[hc->current] = 0; - hc->lengths[hc->current] = 0; - } - hc->values[hc->current] = get_bits(gb, 8); - hc->current++; - if(hc->maxlength < length) - hc->maxlength = length; + if (get_bits_left(gb) < 8) + return AVERROR_INVALIDDATA; + hc->entries[hc->current++] = (HuffEntry){ get_bits(gb, 8), length }; return 0; } else { //Node int r; length++; - r = smacker_decode_tree(gb, hc, prefix, length); + r = smacker_decode_tree(gb, hc, length); if(r) return r; - return smacker_decode_tree(gb, hc, prefix | (1 << (length - 1)), length); + return smacker_decode_tree(gb, hc, length); } } /** * Decode header tree + * + * Checks before the first read, can overread by 6 * SMKTREE_BITS on success. */ -static int smacker_decode_bigtree(GetBitContext *gb, HuffContext *hc, - DBCtx *ctx, int length) +static int smacker_decode_bigtree(GetBitContext *gb, DBCtx *ctx, int length) { // Larger length can cause segmentation faults due to too deep recursion. if (length > SMKTREE_DECODE_BIG_MAX_RECURSION) { @@ -141,40 +147,42 @@ return AVERROR_INVALIDDATA; } - if (hc->current + 1 >= hc->length) { + if (ctx->current >= ctx->length) { av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); return AVERROR_INVALIDDATA; } + if (get_bits_left(gb) <= 0) + return AVERROR_INVALIDDATA; if(!get_bits1(gb)){ //Leaf int val, i1, i2; - i1 = ctx->v1->table ? get_vlc2(gb, ctx->v1->table, SMKTREE_BITS, 3) : 0; - i2 = ctx->v2->table ? get_vlc2(gb, ctx->v2->table, SMKTREE_BITS, 3) : 0; - if (i1 < 0 || i2 < 0) - return AVERROR_INVALIDDATA; - val = ctx->recode1[i1] | (ctx->recode2[i2] << 8); + i1 = ctx->v1->table ? get_vlc2(gb, ctx->v1->table, SMKTREE_BITS, 3) + : ctx->vals[0]; + i2 = ctx->v2->table ? get_vlc2(gb, ctx->v2->table, SMKTREE_BITS, 3) + : ctx->vals[1]; + val = i1 | (i2 << 8); if(val == ctx->escapes[0]) { - ctx->last[0] = hc->current; + ctx->last[0] = ctx->current; val = 0; } else if(val == ctx->escapes[1]) { - ctx->last[1] = hc->current; + ctx->last[1] = ctx->current; val = 0; } else if(val == ctx->escapes[2]) { - ctx->last[2] = hc->current; + ctx->last[2] = ctx->current; val = 0; } - hc->values[hc->current++] = val; + ctx->values[ctx->current++] = val; return 1; } else { //Node int r = 0, r_new, t; - t = hc->current++; - r = smacker_decode_bigtree(gb, hc, ctx, length + 1); + t = ctx->current++; + r = smacker_decode_bigtree(gb, ctx, length + 1); if(r < 0) return r; - hc->values[t] = SMK_NODE | r; + ctx->values[t] = SMK_NODE | r; r++; - r_new = smacker_decode_bigtree(gb, hc, ctx, length + 1); + r_new = smacker_decode_bigtree(gb, ctx, length + 1); if (r_new < 0) return r_new; return r + r_new; @@ -183,82 +191,46 @@ /** * Store large tree as FFmpeg's vlc codes + * + * Can read FFMAX(1 + SMKTREE_DECODE_MAX_RECURSION, 2 + 3 * 16) bits + * before the first check; can overread by 6 * SMKTREE_BITS + 1 on success. */ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int **recodes, int *last, int size) { - int res; - HuffContext huff; - HuffContext tmp1, tmp2; VLC vlc[2] = { { 0 } }; int escapes[3]; DBCtx ctx; - int err = 0; + int err; if(size >= UINT_MAX>>4){ // (((size + 3) >> 2) + 3) << 2 must not overflow av_log(smk->avctx, AV_LOG_ERROR, "size too large\n"); return AVERROR_INVALIDDATA; } - tmp1.length = 256; - tmp1.maxlength = 0; - tmp1.current = 0; - tmp1.bits = av_mallocz(256 * 4); - tmp1.lengths = av_mallocz(256 * sizeof(int)); - tmp1.values = av_mallocz(256 * sizeof(int)); - - tmp2.length = 256; - tmp2.maxlength = 0; - tmp2.current = 0; - tmp2.bits = av_mallocz(256 * 4); - tmp2.lengths = av_mallocz(256 * sizeof(int)); - tmp2.values = av_mallocz(256 * sizeof(int)); - if (!tmp1.bits || !tmp1.lengths || !tmp1.values || - !tmp2.bits || !tmp2.lengths || !tmp2.values) { - err = AVERROR(ENOMEM); - goto error; - } - - if(get_bits1(gb)) { - res = smacker_decode_tree(gb, &tmp1, 0, 0); - if (res < 0) { - err = res; - goto error; + for (int i = 0; i < 2; i++) { + HuffContext h; + h.current = 0; + if (!get_bits1(gb)) { + ctx.vals[i] = 0; + av_log(smk->avctx, AV_LOG_ERROR, "Skipping %s bytes tree\n", + i ? "high" : "low"); + continue; } - skip_bits1(gb); - if(tmp1.current > 1) { - res = init_vlc(&vlc[0], SMKTREE_BITS, tmp1.length, - tmp1.lengths, sizeof(int), sizeof(int), - tmp1.bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE); - if(res < 0) { - av_log(smk->avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); - err = res; - goto error; - } - } - } - if (!vlc[0].table) { - av_log(smk->avctx, AV_LOG_ERROR, "Skipping low bytes tree\n"); - } - if(get_bits1(gb)){ - res = smacker_decode_tree(gb, &tmp2, 0, 0); - if (res < 0) { - err = res; + err = smacker_decode_tree(gb, &h, 0); + if (err < 0) goto error; - } skip_bits1(gb); - if(tmp2.current > 1) { - res = init_vlc(&vlc[1], SMKTREE_BITS, tmp2.length, - tmp2.lengths, sizeof(int), sizeof(int), - tmp2.bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE); - if(res < 0) { + if (h.current > 1) { + err = ff_init_vlc_from_lengths(&vlc[i], SMKTREE_BITS, h.current, + &h.entries[0].length, sizeof(*h.entries), + &h.entries[0].value, sizeof(*h.entries), 1, + 0, INIT_VLC_OUTPUT_LE, smk->avctx); + if (err < 0) { av_log(smk->avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); - err = res; goto error; } - } - } - if (!vlc[1].table) { - av_log(smk->avctx, AV_LOG_ERROR, "Skipping high bytes tree\n"); + } else + ctx.vals[i] = h.entries[0].value; } escapes[0] = get_bits(gb, 16); @@ -272,46 +244,29 @@ ctx.escapes[2] = escapes[2]; ctx.v1 = &vlc[0]; ctx.v2 = &vlc[1]; - ctx.recode1 = tmp1.values; - ctx.recode2 = tmp2.values; ctx.last = last; - - huff.length = ((size + 3) >> 2) + 4; - huff.maxlength = 0; - huff.current = 0; - huff.values = av_mallocz_array(huff.length, sizeof(int)); - if (!huff.values) { + ctx.length = (size + 3) >> 2; + ctx.current = 0; + ctx.values = av_malloc_array(ctx.length + 3, sizeof(ctx.values[0])); + if (!ctx.values) { err = AVERROR(ENOMEM); goto error; } + *recodes = ctx.values; - res = smacker_decode_bigtree(gb, &huff, &ctx, 0); - if (res < 0) - err = res; + err = smacker_decode_bigtree(gb, &ctx, 0); + if (err < 0) + goto error; skip_bits1(gb); - if(ctx.last[0] == -1) ctx.last[0] = huff.current++; - if(ctx.last[1] == -1) ctx.last[1] = huff.current++; - if(ctx.last[2] == -1) ctx.last[2] = huff.current++; - if (ctx.last[0] >= huff.length || - ctx.last[1] >= huff.length || - ctx.last[2] >= huff.length) { - av_log(smk->avctx, AV_LOG_ERROR, "Huffman codes out of range\n"); - err = AVERROR_INVALIDDATA; - } - - *recodes = huff.values; + if (ctx.last[0] == -1) ctx.last[0] = ctx.current++; + if (ctx.last[1] == -1) ctx.last[1] = ctx.current++; + if (ctx.last[2] == -1) ctx.last[2] = ctx.current++; + err = 0; error: - if(vlc[0].table) - ff_free_vlc(&vlc[0]); - if(vlc[1].table) - ff_free_vlc(&vlc[1]); - av_free(tmp1.bits); - av_free(tmp1.lengths); - av_free(tmp1.values); - av_free(tmp2.bits); - av_free(tmp2.lengths); - av_free(tmp2.values); + for (int i = 0; i < 2; i++) { + ff_free_vlc(&vlc[i]); + } return err; } @@ -319,6 +274,7 @@ static int decode_header_trees(SmackVContext *smk) { GetBitContext gb; int mmap_size, mclr_size, full_size, type_size, ret; + int skip = 0; mmap_size = AV_RL32(smk->avctx->extradata); mclr_size = AV_RL32(smk->avctx->extradata + 4); @@ -330,6 +286,7 @@ return ret; if(!get_bits1(&gb)) { + skip ++; av_log(smk->avctx, AV_LOG_INFO, "Skipping MMAP tree\n"); smk->mmap_tbl = av_malloc(sizeof(int) * 2); if (!smk->mmap_tbl) @@ -342,6 +299,7 @@ return ret; } if(!get_bits1(&gb)) { + skip ++; av_log(smk->avctx, AV_LOG_INFO, "Skipping MCLR tree\n"); smk->mclr_tbl = av_malloc(sizeof(int) * 2); if (!smk->mclr_tbl) @@ -354,6 +312,7 @@ return ret; } if(!get_bits1(&gb)) { + skip ++; av_log(smk->avctx, AV_LOG_INFO, "Skipping FULL tree\n"); smk->full_tbl = av_malloc(sizeof(int) * 2); if (!smk->full_tbl) @@ -366,6 +325,7 @@ return ret; } if(!get_bits1(&gb)) { + skip ++; av_log(smk->avctx, AV_LOG_INFO, "Skipping TYPE tree\n"); smk->type_tbl = av_malloc(sizeof(int) * 2); if (!smk->type_tbl) @@ -377,6 +337,8 @@ if (ret < 0) return ret; } + if (skip == 4 || get_bits_left(&gb) < 0) + return AVERROR_INVALIDDATA; return 0; } @@ -385,12 +347,15 @@ recode[last[0]] = recode[last[1]] = recode[last[2]] = 0; } -/* get code and update history */ +/* Get code and update history. + * Checks before reading, does not overread. */ static av_always_inline int smk_get_code(GetBitContext *gb, int *recode, int *last) { register int *table = recode; int v; while(*table & SMK_NODE) { + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; if(get_bits1(gb)) table += (*table) & (~SMK_NODE); table++; @@ -421,7 +386,7 @@ if (avpkt->size <= 769) return AVERROR_INVALIDDATA; - if ((ret = ff_reget_buffer(avctx, smk->pic)) < 0) + if ((ret = ff_reget_buffer(avctx, smk->pic, 0)) < 0) return ret; /* make the palette available on the way out */ @@ -455,6 +420,8 @@ uint16_t pix; type = smk_get_code(&gb, smk->type_tbl, smk->type_last); + if (type < 0) + return type; run = block_runs[(type >> 2) & 0x3F]; switch(type & 3){ case SMK_BLK_MONO: @@ -480,6 +447,8 @@ case SMK_BLK_FULL: mode = 0; if(avctx->codec_tag == MKTAG('S', 'M', 'K', '4')) { // In case of Smacker v4 we have three modes + if (get_bits_left(&gb) < 1) + return AVERROR_INVALIDDATA; if(get_bits1(&gb)) mode = 1; else if(get_bits1(&gb)) mode = 2; } @@ -587,15 +556,13 @@ return AVERROR(ENOMEM); /* decode huffman trees from extradata */ - if(avctx->extradata_size < 16){ + if (avctx->extradata_size <= 16){ av_log(avctx, AV_LOG_ERROR, "Extradata missing!\n"); - decode_end(avctx); return AVERROR(EINVAL); } ret = decode_header_trees(c); if (ret < 0) { - decode_end(avctx); return ret; } @@ -625,15 +592,14 @@ const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; GetBitContext gb; - HuffContext h[4] = { { 0 } }; VLC vlc[4] = { { 0 } }; int16_t *samples; uint8_t *samples8; - int val; + uint8_t values[4]; int i, res, ret; int unp_size; int bits, stereo; - int pred[2] = {0, 0}; + unsigned pred[2], val; if (buf_size <= 4) { av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); @@ -680,85 +646,48 @@ // Initialize for(i = 0; i < (1 << (bits + stereo)); i++) { - h[i].length = 256; - h[i].maxlength = 0; - h[i].current = 0; - h[i].bits = av_mallocz(256 * 4); - h[i].lengths = av_mallocz(256 * sizeof(int)); - h[i].values = av_mallocz(256 * sizeof(int)); - if (!h[i].bits || !h[i].lengths || !h[i].values) { - ret = AVERROR(ENOMEM); - goto error; - } + HuffContext h; + h.current = 0; skip_bits1(&gb); - if (smacker_decode_tree(&gb, &h[i], 0, 0) < 0) { - ret = AVERROR_INVALIDDATA; + if ((ret = smacker_decode_tree(&gb, &h, 0)) < 0) goto error; - } skip_bits1(&gb); - if(h[i].current > 1) { - res = init_vlc(&vlc[i], SMKTREE_BITS, h[i].length, - h[i].lengths, sizeof(int), sizeof(int), - h[i].bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE); - if(res < 0) { + if (h.current > 1) { + ret = ff_init_vlc_from_lengths(&vlc[i], SMKTREE_BITS, h.current, + &h.entries[0].length, sizeof(*h.entries), + &h.entries[0].value, sizeof(*h.entries), 1, + 0, INIT_VLC_OUTPUT_LE, avctx); + if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); - ret = AVERROR_INVALIDDATA; goto error; } - } + } else + values[i] = h.entries[0].value; } /* this codec relies on wraparound instead of clipping audio */ if(bits) { //decode 16-bit data for(i = stereo; i >= 0; i--) - pred[i] = sign_extend(av_bswap16(get_bits(&gb, 16)), 16); + pred[i] = av_bswap16(get_bits(&gb, 16)); for(i = 0; i <= stereo; i++) *samples++ = pred[i]; for(; i < unp_size / 2; i++) { - if(get_bits_left(&gb)<0) - return AVERROR_INVALIDDATA; - if(i & stereo) { - if(vlc[2].table) - res = get_vlc2(&gb, vlc[2].table, SMKTREE_BITS, 3); - else - res = 0; - if (res < 0) { - av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); - return AVERROR_INVALIDDATA; - } - val = h[2].values[res]; - if(vlc[3].table) - res = get_vlc2(&gb, vlc[3].table, SMKTREE_BITS, 3); - else - res = 0; - if (res < 0) { - av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); - return AVERROR_INVALIDDATA; - } - val |= h[3].values[res] << 8; - pred[1] += (unsigned)sign_extend(val, 16); - *samples++ = pred[1]; - } else { - if(vlc[0].table) - res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3); - else - res = 0; - if (res < 0) { - av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); - return AVERROR_INVALIDDATA; - } - val = h[0].values[res]; - if(vlc[1].table) - res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3); - else - res = 0; - if (res < 0) { - av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); - return AVERROR_INVALIDDATA; - } - val |= h[1].values[res] << 8; - pred[0] += (unsigned)sign_extend(val, 16); - *samples++ = pred[0]; + unsigned idx = 2 * (i & stereo); + if (get_bits_left(&gb) < 0) { + ret = AVERROR_INVALIDDATA; + goto error; } + if (vlc[idx].table) + res = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); + else + res = values[idx]; + val = res; + if (vlc[++idx].table) + res = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); + else + res = values[idx]; + val |= res << 8; + pred[idx / 2] += val; + *samples++ = pred[idx / 2]; } } else { //8-bit data for(i = stereo; i >= 0; i--) @@ -766,31 +695,17 @@ for(i = 0; i <= stereo; i++) *samples8++ = pred[i]; for(; i < unp_size; i++) { - if(get_bits_left(&gb)<0) - return AVERROR_INVALIDDATA; - if(i & stereo){ - if(vlc[1].table) - res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3); - else - res = 0; - if (res < 0) { - av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); - return AVERROR_INVALIDDATA; - } - pred[1] += sign_extend(h[1].values[res], 8); - *samples8++ = pred[1]; - } else { - if(vlc[0].table) - res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3); - else - res = 0; - if (res < 0) { - av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); - return AVERROR_INVALIDDATA; - } - pred[0] += sign_extend(h[0].values[res], 8); - *samples8++ = pred[0]; + unsigned idx = i & stereo; + if (get_bits_left(&gb) < 0) { + ret = AVERROR_INVALIDDATA; + goto error; } + if (vlc[idx].table) + val = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); + else + val = values[idx]; + pred[idx] += val; + *samples8++ = pred[idx]; } } @@ -799,11 +714,7 @@ error: for(i = 0; i < 4; i++) { - if(vlc[i].table) - ff_free_vlc(&vlc[i]); - av_free(h[i].bits); - av_free(h[i].lengths); - av_free(h[i].values); + ff_free_vlc(&vlc[i]); } return ret; @@ -819,6 +730,7 @@ .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; AVCodec ff_smackaud_decoder = { @@ -829,4 +741,5 @@ .init = smka_decode_init, .decode = smka_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/smc.c ffmpeg-4.4/libavcodec/smc.c --- ffmpeg-4.2.2/libavcodec/smc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/smc.c 2021-04-08 21:28:39.000000000 +0000 @@ -435,7 +435,7 @@ const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; SmcContext *s = avctx->priv_data; - int pal_size; + buffer_size_t pal_size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size); int ret; int total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4); @@ -445,7 +445,7 @@ bytestream2_init(&s->gb, buf, buf_size); - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; if (pal && pal_size == AVPALETTE_SIZE) { @@ -484,4 +484,5 @@ .close = smc_decode_end, .decode = smc_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/smvjpegdec.c ffmpeg-4.4/libavcodec/smvjpegdec.c --- ffmpeg-4.2.2/libavcodec/smvjpegdec.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/smvjpegdec.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,225 +0,0 @@ -/* - * SMV JPEG decoder - * Copyright (c) 2013 Ash Hughes - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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 - * SMV JPEG decoder. - */ - -// #define DEBUG -#include "avcodec.h" -#include "libavutil/opt.h" -#include "libavutil/imgutils.h" -#include "mjpegdec.h" -#include "internal.h" - -typedef struct SMVJpegDecodeContext { - MJpegDecodeContext jpg; - AVFrame *picture[2]; /* pictures array */ - AVCodecContext* avctx; - int frames_per_jpeg; - int mjpeg_data_size; -} SMVJpegDecodeContext; - -static inline void smv_img_pnt_plane(uint8_t **dst, uint8_t *src, - int src_linesize, int height, int nlines) -{ - if (!dst || !src) - return; - src += (nlines) * src_linesize * height; - *dst = src; -} - -static inline void smv_img_pnt(uint8_t *dst_data[4], uint8_t *src_data[4], - const int src_linesizes[4], - enum AVPixelFormat pix_fmt, int width, int height, - int nlines) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - int i, planes_nb = 0; - - if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) - return; - - 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 h = height; - if (i == 1 || i == 2) { - h = AV_CEIL_RSHIFT(height, desc->log2_chroma_h); - } - smv_img_pnt_plane(&dst_data[i], src_data[i], - src_linesizes[i], h, nlines); - } - if (desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & FF_PSEUDOPAL) - dst_data[1] = src_data[1]; -} - -static av_cold int smvjpeg_decode_end(AVCodecContext *avctx) -{ - SMVJpegDecodeContext *s = avctx->priv_data; - MJpegDecodeContext *jpg = &s->jpg; - int ret; - - jpg->picture_ptr = NULL; - av_frame_free(&s->picture[0]); - av_frame_free(&s->picture[1]); - ret = avcodec_close(s->avctx); - av_freep(&s->avctx); - return ret; -} - -static av_cold int smvjpeg_decode_init(AVCodecContext *avctx) -{ - SMVJpegDecodeContext *s = avctx->priv_data; - AVCodec *codec; - AVDictionary *thread_opt = NULL; - int ret = 0, r; - - s->frames_per_jpeg = 0; - - s->picture[0] = av_frame_alloc(); - if (!s->picture[0]) - return AVERROR(ENOMEM); - - s->picture[1] = av_frame_alloc(); - if (!s->picture[1]) { - av_frame_free(&s->picture[0]); - return AVERROR(ENOMEM); - } - - s->jpg.picture_ptr = s->picture[0]; - - if (avctx->extradata_size >= 4) - s->frames_per_jpeg = AV_RL32(avctx->extradata); - - if (s->frames_per_jpeg <= 0) { - av_log(avctx, AV_LOG_ERROR, "Invalid number of frames per jpeg.\n"); - ret = AVERROR_INVALIDDATA; - } - - codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG); - if (!codec) { - av_log(avctx, AV_LOG_ERROR, "MJPEG codec not found\n"); - smvjpeg_decode_end(avctx); - return AVERROR_DECODER_NOT_FOUND; - } - - s->avctx = avcodec_alloc_context3(codec); - - av_dict_set(&thread_opt, "threads", "1", 0); - s->avctx->refcounted_frames = 1; - s->avctx->flags = avctx->flags; - s->avctx->idct_algo = avctx->idct_algo; - if ((r = ff_codec_open2_recursive(s->avctx, codec, &thread_opt)) < 0) { - av_log(avctx, AV_LOG_ERROR, "MJPEG codec failed to open\n"); - ret = r; - } - av_dict_free(&thread_opt); - - if (ret < 0) - smvjpeg_decode_end(avctx); - return ret; -} - -static int smvjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size, - AVPacket *avpkt) -{ - const AVPixFmtDescriptor *desc; - SMVJpegDecodeContext *s = avctx->priv_data; - AVFrame* mjpeg_data = s->picture[0]; - int i, cur_frame = 0, ret = 0; - - cur_frame = avpkt->pts % s->frames_per_jpeg; - - /* cur_frame is later used to calculate the buffer offset, so it mustn't be negative */ - if (cur_frame < 0) - cur_frame += s->frames_per_jpeg; - - /* Are we at the start of a block? */ - if (!cur_frame) { - av_frame_unref(mjpeg_data); - ret = avcodec_decode_video2(s->avctx, mjpeg_data, &s->mjpeg_data_size, avpkt); - if (ret < 0) { - s->mjpeg_data_size = 0; - return ret; - } - } else if (!s->mjpeg_data_size) - return AVERROR(EINVAL); - - desc = av_pix_fmt_desc_get(s->avctx->pix_fmt); - av_assert0(desc); - - if (mjpeg_data->height % (s->frames_per_jpeg << desc->log2_chroma_h)) { - av_log(avctx, AV_LOG_ERROR, "Invalid height\n"); - return AVERROR_INVALIDDATA; - } - - /*use the last lot... */ - *data_size = s->mjpeg_data_size; - - avctx->pix_fmt = s->avctx->pix_fmt; - - /* We shouldn't get here if frames_per_jpeg <= 0 because this was rejected - in init */ - ret = ff_set_dimensions(avctx, mjpeg_data->width, mjpeg_data->height / s->frames_per_jpeg); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Failed to set dimensions\n"); - return ret; - } - - if (*data_size) { - s->picture[1]->extended_data = NULL; - s->picture[1]->width = avctx->width; - s->picture[1]->height = avctx->height; - s->picture[1]->format = avctx->pix_fmt; - smv_img_pnt(s->picture[1]->data, mjpeg_data->data, mjpeg_data->linesize, - avctx->pix_fmt, avctx->width, avctx->height, cur_frame); - for (i = 0; i < AV_NUM_DATA_POINTERS; i++) - s->picture[1]->linesize[i] = mjpeg_data->linesize[i]; - - ret = av_frame_ref(data, s->picture[1]); - if (ret < 0) - return ret; - } - - return avpkt->size; -} - -static const AVClass smvjpegdec_class = { - .class_name = "SMVJPEG decoder", - .item_name = av_default_item_name, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVCodec ff_smvjpeg_decoder = { - .name = "smvjpeg", - .long_name = NULL_IF_CONFIG_SMALL("SMV JPEG"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SMVJPEG, - .priv_data_size = sizeof(SMVJpegDecodeContext), - .init = smvjpeg_decode_init, - .close = smvjpeg_decode_end, - .decode = smvjpeg_decode_frame, - .priv_class = &smvjpegdec_class, -}; diff -Nru ffmpeg-4.2.2/libavcodec/snappy.c ffmpeg-4.4/libavcodec/snappy.c --- ffmpeg-4.2.2/libavcodec/snappy.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/snappy.c 2020-07-04 22:36:04.000000000 +0000 @@ -39,6 +39,8 @@ do { tmp = bytestream2_get_byte(gb); + if (shift > 31 || ((tmp & 127LL) << shift) > INT_MAX) + return AVERROR_INVALIDDATA; val |= (tmp & 127) << shift; shift += 7; } while (tmp & 128); diff -Nru ffmpeg-4.2.2/libavcodec/snow.c ffmpeg-4.4/libavcodec/snow.c --- ffmpeg-4.2.2/libavcodec/snow.c 2018-07-17 09:27:41.000000000 +0000 +++ ffmpeg-4.4/libavcodec/snow.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,7 @@ #include "libavutil/intmath.h" #include "libavutil/log.h" #include "libavutil/opt.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "me_cmp.h" #include "snow_dwt.h" @@ -427,10 +428,19 @@ mca( 0, 8,8) mca( 8, 8,8) +static av_cold void snow_static_init(void) +{ + for (int i = 0; i < MAX_REF_FRAMES; i++) + for (int j = 0; j < MAX_REF_FRAMES; j++) + ff_scale_mv_ref[i][j] = 256 * (i + 1) / (j + 1); + init_qexp(); +} + av_cold int ff_snow_common_init(AVCodecContext *avctx){ + static AVOnce init_static_once = AV_ONCE_INIT; SnowContext *s = avctx->priv_data; int width, height; - int i, j; + int i; s->avctx= avctx; s->max_ref_frames=1; //just make sure it's not an invalid value in case of no initial keyframe @@ -480,35 +490,32 @@ mcfh(0, 8) mcfh(8, 8) - init_qexp(); - // dec += FFMAX(s->chroma_h_shift, s->chroma_v_shift); width= s->avctx->width; height= s->avctx->height; - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->spatial_idwt_buffer, width, height * sizeof(IDWTELEM), fail); - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->spatial_dwt_buffer, width, height * sizeof(DWTELEM), fail); //FIXME this does not belong here - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->temp_dwt_buffer, width, sizeof(DWTELEM), fail); - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->temp_idwt_buffer, width, sizeof(IDWTELEM), fail); - FF_ALLOC_ARRAY_OR_GOTO(avctx, s->run_buffer, ((width + 1) >> 1), ((height + 1) >> 1) * sizeof(*s->run_buffer), fail); + if (!FF_ALLOCZ_TYPED_ARRAY(s->spatial_idwt_buffer, width * height) || + !FF_ALLOCZ_TYPED_ARRAY(s->spatial_dwt_buffer, width * height) || //FIXME this does not belong here + !FF_ALLOCZ_TYPED_ARRAY(s->temp_dwt_buffer, width) || + !FF_ALLOCZ_TYPED_ARRAY(s->temp_idwt_buffer, width) || + !FF_ALLOCZ_TYPED_ARRAY(s->run_buffer, ((width + 1) >> 1) * ((height + 1) >> 1))) + return AVERROR(ENOMEM); for(i=0; ilast_picture[i] = av_frame_alloc(); if (!s->last_picture[i]) - goto fail; + return AVERROR(ENOMEM); } s->mconly_picture = av_frame_alloc(); s->current_picture = av_frame_alloc(); if (!s->mconly_picture || !s->current_picture) - goto fail; + return AVERROR(ENOMEM); + + ff_thread_once(&init_static_once, snow_static_init); return 0; -fail: - return AVERROR(ENOMEM); } int ff_snow_common_init_after_header(AVCodecContext *avctx) { @@ -520,9 +527,10 @@ if ((ret = ff_get_buffer(s->avctx, s->mconly_picture, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->scratchbuf, FFMAX(s->mconly_picture->linesize[0], 2*avctx->width+256), 7*MB_SIZE, fail); emu_buf_size = FFMAX(s->mconly_picture->linesize[0], 2*avctx->width+256) * (2 * MB_SIZE + HTAPS_MAX - 1); - FF_ALLOC_OR_GOTO(avctx, s->emu_edge_buffer, emu_buf_size, fail); + if (!FF_ALLOCZ_TYPED_ARRAY(s->scratchbuf, FFMAX(s->mconly_picture->linesize[0], 2*avctx->width+256) * 7 * MB_SIZE) || + !FF_ALLOCZ_TYPED_ARRAY(s->emu_edge_buffer, emu_buf_size)) + return AVERROR(ENOMEM); } if(s->mconly_picture->format != avctx->pix_fmt) { @@ -571,7 +579,7 @@ av_freep(&b->x_coeff); b->x_coeff=av_mallocz_array(((b->width+1) * b->height+1), sizeof(x_and_coeff)); if (!b->x_coeff) - goto fail; + return AVERROR(ENOMEM); } w= (w+1)>>1; h= (h+1)>>1; @@ -579,8 +587,6 @@ } return 0; -fail: - return AVERROR(ENOMEM); } #define USE_HALFPEL_PLANE 0 diff -Nru ffmpeg-4.2.2/libavcodec/snowdec.c ffmpeg-4.4/libavcodec/snowdec.c --- ffmpeg-4.2.2/libavcodec/snowdec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/snowdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -117,7 +117,7 @@ static inline void decode_subband_slice_buffered(SnowContext *s, SubBand *b, slice_buffer * sb, int start_y, int h, int save_state[1]){ const int w= b->width; int y; - const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16); + const int qlog= av_clip(s->qlog + (int64_t)b->qlog, 0, QROOT*16); int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT); int qadd= (s->qbias*qmul)>>QBIAS_SHIFT; int new_index = 0; @@ -224,7 +224,7 @@ static void dequantize_slice_buffered(SnowContext *s, slice_buffer * sb, SubBand *b, IDWTELEM *src, int stride, int start_y, int end_y){ const int w= b->width; - const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16); + const int qlog= av_clip(s->qlog + (int64_t)b->qlog, 0, QROOT*16); const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT); const int qadd= (s->qbias*qmul)>>QBIAS_SHIFT; int x,y; @@ -369,7 +369,10 @@ htaps = htaps*2 + 2; p->htaps= htaps; for(i= htaps/2; i; i--){ - p->hcoeff[i]= get_symbol(&s->c, s->header_state, 0) * (1-2*(i&1)); + unsigned hcoeff = get_symbol(&s->c, s->header_state, 0); + if (hcoeff > 127) + return AVERROR_INVALIDDATA; + p->hcoeff[i]= hcoeff * (1-2*(i&1)); sum += p->hcoeff[i]; } p->hcoeff[0]= 32-sum; @@ -419,17 +422,6 @@ return 0; } -static av_cold int decode_init(AVCodecContext *avctx) -{ - int ret; - - if ((ret = ff_snow_common_init(avctx)) < 0) { - return ret; - } - - return 0; -} - static int decode_blocks(SnowContext *s){ int x, y; int w= s->b_width; @@ -502,7 +494,7 @@ ); av_assert0(!s->avmv); - if (s->avctx->flags2 & AV_CODEC_FLAG2_EXPORT_MVS) { + if (s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_MVS) { s->avmv = av_malloc_array(s->b_width * s->b_height, sizeof(AVMotionVector) << (s->block_max_depth*2)); } s->avmv_index = 0; @@ -662,7 +654,7 @@ .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_SNOW, .priv_data_size = sizeof(SnowContext), - .init = decode_init, + .init = ff_snow_common_init, .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, diff -Nru ffmpeg-4.2.2/libavcodec/snowenc.c ffmpeg-4.4/libavcodec/snowenc.c --- ffmpeg-4.2.2/libavcodec/snowenc.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/snowenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,6 +25,7 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" #include "internal.h" +#include "packet_internal.h" #include "snow_dwt.h" #include "snow.h" @@ -1624,10 +1625,22 @@ s->lambda = 0; }//else keep previous frame's qlog until after motion estimation +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS + av_frame_unref(avctx->coded_frame); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (s->current_picture->data[0]) { int w = s->avctx->width; int h = s->avctx->height; +#if FF_API_CODED_FRAME + ret = av_frame_make_writable(s->current_picture); + if (ret < 0) + return ret; +#endif + s->mpvencdsp.draw_edges(s->current_picture->data[0], s->current_picture->linesize[0], w , h , EDGE_WIDTH , EDGE_WIDTH , EDGE_TOP | EDGE_BOTTOM); @@ -1645,7 +1658,6 @@ ff_snow_frame_start(s); #if FF_API_CODED_FRAME FF_DISABLE_DEPRECATION_WARNINGS - av_frame_unref(avctx->coded_frame); ret = av_frame_ref(avctx->coded_frame, s->current_picture); FF_ENABLE_DEPRECATION_WARNINGS #endif @@ -1936,6 +1948,11 @@ { "pred", "Spatial decomposition type", OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 0 }, DWT_97, DWT_53, VE, "pred" }, { "dwt97", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "pred" }, { "dwt53", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "pred" }, + { "rc_eq", "Set rate control equation. When computing the expression, besides the standard functions " + "defined in the section 'Expression Evaluation', the following functions are available: " + "bits2qp(bits), qp2bits(qp). Also the following constants are available: iTex pTex tex mv " + "fCode iCount mcVar var isI isP isB avgQP qComp avgIITex avgPITex avgPPTex avgBPTex avgTex.", + OFFSET(m.rc_eq), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE }, { NULL }, }; diff -Nru ffmpeg-4.2.2/libavcodec/sonic.c ffmpeg-4.4/libavcodec/sonic.c --- ffmpeg-4.2.2/libavcodec/sonic.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sonic.c 2021-04-08 21:28:39.000000000 +0000 @@ -140,7 +140,8 @@ if(get_rac(c, state+0)) return 0; else{ - int i, e, a; + int i, e; + unsigned a; e= 0; while(get_rac(c, state+1 + FFMIN(e,9))){ //1..10 e++; @@ -457,8 +458,8 @@ for (j = 0, p = i+1; p < order; j++,p++) { - int tmp = x + shift_down(k[j] * state[p], LATTICE_SHIFT); - state[p] += shift_down(k[j]*x, LATTICE_SHIFT); + int tmp = x + shift_down(k[j] * (unsigned)state[p], LATTICE_SHIFT); + state[p] += shift_down(k[j]* (unsigned)x, LATTICE_SHIFT); x = tmp; } } @@ -466,7 +467,7 @@ static int predictor_calc_error(int *k, int *state, int order, int error) { - int i, x = error - shift_down(k[order-1] * state[order-1], LATTICE_SHIFT); + int i, x = error - shift_down(k[order-1] * (unsigned)state[order-1], LATTICE_SHIFT); #if 1 int *k_ptr = &(k[order-2]), @@ -474,13 +475,13 @@ for (i = order-2; i >= 0; i--, k_ptr--, state_ptr--) { int k_value = *k_ptr, state_value = *state_ptr; - x -= shift_down(k_value * state_value, LATTICE_SHIFT); + x -= (unsigned)shift_down(k_value * (unsigned)state_value, LATTICE_SHIFT); state_ptr[1] = state_value + shift_down(k_value * (unsigned)x, LATTICE_SHIFT); } #else for (i = order-2; i >= 0; i--) { - x -= shift_down(k[i] * state[i], LATTICE_SHIFT); + x -= (unsigned)shift_down(k[i] * state[i], LATTICE_SHIFT); state[i+1] = state[i] + shift_down(k[i] * x, LATTICE_SHIFT); } #endif @@ -499,16 +500,13 @@ // copes better with quantization, and calculates the // actual whitened result as it goes. -static int modified_levinson_durbin(int *window, int window_entries, +static void modified_levinson_durbin(int *window, int window_entries, int *out, int out_entries, int channels, int *tap_quant) { int i; - int *state = av_calloc(window_entries, sizeof(*state)); + int *state = window + window_entries; - if (!state) - return AVERROR(ENOMEM); - - memcpy(state, window, 4* window_entries); + memcpy(state, window, window_entries * sizeof(*state)); for (i = 0; i < out_entries; i++) { @@ -570,9 +568,6 @@ } #endif } - - av_free(state); - return 0; } static inline int code_samplerate(int samplerate) @@ -595,6 +590,7 @@ static av_cold int sonic_encode_init(AVCodecContext *avctx) { SonicContext *s = avctx->priv_data; + int *coded_samples; PutBitContext pb; int i; @@ -654,17 +650,16 @@ if (!s->predictor_k) return AVERROR(ENOMEM); - for (i = 0; i < s->channels; i++) - { - s->coded_samples[i] = av_calloc(s->block_align, sizeof(**s->coded_samples)); - if (!s->coded_samples[i]) - return AVERROR(ENOMEM); - } + coded_samples = av_calloc(s->block_align, s->channels * sizeof(**s->coded_samples)); + if (!coded_samples) + return AVERROR(ENOMEM); + for (i = 0; i < s->channels; i++, coded_samples += s->block_align) + s->coded_samples[i] = coded_samples; s->int_samples = av_calloc(s->frame_size, sizeof(*s->int_samples)); s->window_size = ((2*s->tail_size)+s->frame_size); - s->window = av_calloc(s->window_size, sizeof(*s->window)); + s->window = av_calloc(s->window_size, 2 * sizeof(*s->window)); if (!s->window || !s->int_samples) return AVERROR(ENOMEM); @@ -705,11 +700,8 @@ static av_cold int sonic_encode_close(AVCodecContext *avctx) { SonicContext *s = avctx->priv_data; - int i; - - for (i = 0; i < s->channels; i++) - av_freep(&s->coded_samples[i]); + av_freep(&s->coded_samples[0]); av_freep(&s->predictor_k); av_freep(&s->tail); av_freep(&s->tap_quant); @@ -763,7 +755,7 @@ break; } - memset(s->window, 0, 4* s->window_size); + memset(s->window, 0, s->window_size * sizeof(*s->window)); for (i = 0; i < s->tail_size; i++) s->window[x++] = s->tail[i]; @@ -778,10 +770,8 @@ s->tail[i] = s->int_samples[s->frame_size - s->tail_size + i]; // generate taps - ret = modified_levinson_durbin(s->window, s->window_size, + modified_levinson_durbin(s->window, s->window_size, s->predictor_k, s->num_taps, s->channels, s->tap_quant); - if (ret < 0) - return ret; if ((ret = intlist_write(&c, state, s->predictor_k, s->num_taps, 0)) < 0) return ret; @@ -858,6 +848,7 @@ static av_cold int sonic_decode_init(AVCodecContext *avctx) { SonicContext *s = avctx->priv_data; + int *tmp; GetBitContext gb; int i; int ret; @@ -950,19 +941,18 @@ s->predictor_k = av_calloc(s->num_taps, sizeof(*s->predictor_k)); - for (i = 0; i < s->channels; i++) - { - s->predictor_state[i] = av_calloc(s->num_taps, sizeof(**s->predictor_state)); - if (!s->predictor_state[i]) - return AVERROR(ENOMEM); - } + tmp = av_calloc(s->num_taps, s->channels * sizeof(**s->predictor_state)); + if (!tmp) + return AVERROR(ENOMEM); + for (i = 0; i < s->channels; i++, tmp += s->num_taps) + s->predictor_state[i] = tmp; + + tmp = av_calloc(s->block_align, s->channels * sizeof(**s->coded_samples)); + if (!tmp) + return AVERROR(ENOMEM); + for (i = 0; i < s->channels; i++, tmp += s->block_align) + s->coded_samples[i] = tmp; - for (i = 0; i < s->channels; i++) - { - s->coded_samples[i] = av_calloc(s->block_align, sizeof(**s->coded_samples)); - if (!s->coded_samples[i]) - return AVERROR(ENOMEM); - } s->int_samples = av_calloc(s->frame_size, sizeof(*s->int_samples)); if (!s->int_samples) return AVERROR(ENOMEM); @@ -974,17 +964,12 @@ static av_cold int sonic_decode_close(AVCodecContext *avctx) { SonicContext *s = avctx->priv_data; - int i; av_freep(&s->int_samples); av_freep(&s->tap_quant); av_freep(&s->predictor_k); - - for (i = 0; i < s->channels; i++) - { - av_freep(&s->predictor_state[i]); - av_freep(&s->coded_samples[i]); - } + av_freep(&s->predictor_state[0]); + av_freep(&s->coded_samples[0]); return 0; } @@ -1032,6 +1017,9 @@ { int x = ch; + if (c.overread > MAX_OVERREAD) + return AVERROR_INVALIDDATA; + predictor_init_state(s->predictor_k, s->predictor_state[ch], s->num_taps); intlist_read(&c, state, s->coded_samples[ch], s->block_align, 1); @@ -1044,7 +1032,7 @@ x += s->channels; } - s->int_samples[x] = predictor_calc_error(s->predictor_k, s->predictor_state[ch], s->num_taps, s->coded_samples[ch][i] * quant); + s->int_samples[x] = predictor_calc_error(s->predictor_k, s->predictor_state[ch], s->num_taps, s->coded_samples[ch][i] * (unsigned)quant); x += s->channels; } @@ -1093,7 +1081,8 @@ .init = sonic_decode_init, .close = sonic_decode_close, .decode = sonic_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; #endif /* CONFIG_SONIC_DECODER */ @@ -1108,6 +1097,7 @@ .encode2 = sonic_encode_frame, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .capabilities = AV_CODEC_CAP_EXPERIMENTAL, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .close = sonic_encode_close, }; #endif @@ -1123,6 +1113,7 @@ .encode2 = sonic_encode_frame, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .capabilities = AV_CODEC_CAP_EXPERIMENTAL, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .close = sonic_encode_close, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/sp5xdec.c ffmpeg-4.4/libavcodec/sp5xdec.c --- ffmpeg-4.2.2/libavcodec/sp5xdec.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sp5xdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,32 +30,29 @@ #include "mjpegdec.h" #include "sp5x.h" - -static int sp5x_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +int ff_sp5x_process_packet(AVCodecContext *avctx, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVPacket avpkt_recoded; - const int qscale = 5; + AVBufferRef *buf_recoded; uint8_t *recoded; int i = 0, j = 0; if (!avctx->width || !avctx->height) return -1; - recoded = av_mallocz(buf_size + 1024); - if (!recoded) + buf_recoded = av_buffer_allocz(buf_size + 1024); + if (!buf_recoded) return -1; + recoded = buf_recoded->data; /* SOI */ recoded[j++] = 0xFF; recoded[j++] = 0xD8; memcpy(recoded+j, &sp5x_data_dqt[0], sizeof(sp5x_data_dqt)); - memcpy(recoded+j+5, &sp5x_quant_table[qscale * 2], 64); - memcpy(recoded+j+70, &sp5x_quant_table[(qscale * 2) + 1], 64); + memcpy(recoded + j + 5, &sp5x_qscale_five_quant_table[0], 64); + memcpy(recoded + j + 70, &sp5x_qscale_five_quant_table[1], 64); j += sizeof(sp5x_data_dqt); memcpy(recoded+j, &sp5x_data_dht[0], sizeof(sp5x_data_dht)); @@ -84,14 +81,12 @@ recoded[j++] = 0xFF; recoded[j++] = 0xD9; - av_init_packet(&avpkt_recoded); - avpkt_recoded.data = recoded; - avpkt_recoded.size = j; - i = ff_mjpeg_decode_frame(avctx, data, got_frame, &avpkt_recoded); - - av_free(recoded); + av_buffer_unref(&avpkt->buf); + avpkt->buf = buf_recoded; + avpkt->data = recoded; + avpkt->size = j; - return i < 0 ? i : avpkt->size; + return 0; } #if CONFIG_SP5X_DECODER @@ -103,10 +98,11 @@ .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, - .decode = sp5x_decode_frame, + .receive_frame = ff_mjpeg_receive_frame, .capabilities = AV_CODEC_CAP_DR1, .max_lowres = 3, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_SETS_PKT_DTS, }; #endif #if CONFIG_AMV_DECODER @@ -118,9 +114,10 @@ .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, - .decode = sp5x_decode_frame, + .receive_frame = ff_mjpeg_receive_frame, .max_lowres = 3, .capabilities = AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_SETS_PKT_DTS, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/sp5x.h ffmpeg-4.4/libavcodec/sp5x.h --- ffmpeg-4.2.2/libavcodec/sp5x.h 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/sp5x.h 2021-04-08 21:28:39.000000000 +0000 @@ -132,58 +132,8 @@ }; -static const uint8_t sp5x_quant_table[20][64]= +static const uint8_t sp5x_qscale_five_quant_table[][64]= { - /* index 0, Q50 */ - { 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40, - 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51, - 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80,109, 81, 87, - 95, 98,103,104,103, 62, 77,113,121,112,100,120, 92,101,103, 99 }, - { 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }, - - /* index 1, Q70 */ - { 10, 7, 7, 8, 7, 6, 10, 8, 8, 8, 11, 10, 10, 11, 14, 24, - 16, 14, 13, 13, 14, 29, 21, 22, 17, 24, 35, 31, 37, 36, 34, 31, - 34, 33, 38, 43, 55, 47, 38, 41, 52, 41, 33, 34, 48, 65, 49, 52, - 57, 59, 62, 62, 62, 37, 46, 68, 73, 67, 60, 72, 55, 61, 62, 59 }, - { 10, 11, 11, 14, 13, 14, 28, 16, 16, 28, 59, 40, 34, 40, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59 }, - - /* index 2, Q80 */ - { 6, 4, 5, 6, 5, 4, 6, 6, 5, 6, 7, 7, 6, 8, 10, 16, - 10, 10, 9, 9, 10, 20, 14, 15, 12, 16, 23, 20, 24, 24, 23, 20, - 22, 22, 26, 29, 37, 31, 26, 27, 35, 28, 22, 22, 32, 44, 32, 35, - 38, 39, 41, 42, 41, 25, 31, 45, 48, 45, 40, 48, 37, 40, 41, 40 }, - { 7, 7, 7, 10, 8, 10, 19, 10, 10, 19, 40, 26, 22, 26, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40 }, - - /* index 3, Q85 */ - { 5, 3, 4, 4, 4, 3, 5, 4, 4, 4, 5, 5, 5, 6, 7, 12, - 8, 7, 7, 7, 7, 15, 11, 11, 9, 12, 17, 15, 18, 18, 17, 15, - 17, 17, 19, 22, 28, 23, 19, 20, 26, 21, 17, 17, 24, 33, 24, 26, - 29, 29, 31, 31, 31, 19, 23, 34, 36, 34, 30, 36, 28, 30, 31, 30 }, - { 5, 5, 5, 7, 6, 7, 14, 8, 8, 14, 30, 20, 17, 20, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, - - /* index 4, Q90 */ - { 3, 2, 2, 3, 2, 2, 3, 3, 3, 3, 4, 3, 3, 4, 5, 8, - 5, 5, 4, 4, 5, 10, 7, 7, 6, 8, 12, 10, 12, 12, 11, 10, - 11, 11, 13, 14, 18, 16, 13, 14, 17, 14, 11, 11, 16, 22, 16, 17, - 19, 20, 21, 21, 21, 12, 15, 23, 24, 22, 20, 24, 18, 20, 21, 20 }, - { 3, 4, 4, 5, 4, 5, 9, 5, 5, 9, 20, 13, 11, 13, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 }, - /* index 5, Q60 */ { 13, 9, 10, 11, 10, 8, 13, 11, 10, 11, 14, 14, 13, 15, 19, 32, 21, 19, 18, 18, 19, 39, 28, 30, 23, 32, 46, 41, 49, 48, 46, 41, @@ -193,46 +143,6 @@ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79 }, - - /* index 6, Q25 */ - { 32, 22, 24, 28, 24, 20, 32, 28, 26, 28, 36, 34, 32, 38, 48, 80, - 52, 48, 44, 44, 48, 98, 70, 74, 58, 80,116,102,122,120,114,102, - 112,110,128,144,184,156,128,136,174,138,110,112,160,218,162,174, - 190,196,206,208,206,124,154,226,242,224,200,240,184,202,206,198 }, - { 34, 36, 36, 48, 42, 48, 94, 52, 52, 94,198,132,112,132,198,198, - 198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, - 198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, - 198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198 }, - - /* index 7, Q95 */ - { 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 4, - 3, 2, 2, 2, 2, 5, 4, 4, 3, 4, 6, 5, 6, 6, 6, 5, - 6, 6, 6, 7, 9, 8, 6, 7, 9, 7, 6, 6, 8, 11, 8, 9, - 10, 10, 10, 10, 10, 6, 8, 11, 12, 11, 10, 12, 9, 10, 10, 10 }, - { 2, 2, 2, 2, 2, 2, 5, 3, 3, 5, 10, 7, 6, 7, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }, - - /* index 8, Q93 */ - { 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 3, 2, 2, 3, 3, 6, - 4, 3, 3, 3, 3, 7, 5, 5, 4, 6, 8, 7, 9, 8, 8, 7, - 8, 8, 9, 10, 13, 11, 9, 10, 12, 10, 8, 8, 11, 15, 11, 12, - 13, 14, 14, 15, 14, 9, 11, 16, 17, 16, 14, 17, 13, 14, 14, 14 }, - { 2, 3, 3, 3, 3, 3, 7, 4, 4, 7, 14, 9, 8, 9, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 }, - - /* index 9, Q40 */ - { 20, 14, 15, 18, 15, 13, 20, 18, 16, 18, 23, 21, 20, 24, 30, 50, - 33, 30, 28, 28, 30, 61, 44, 46, 36, 50, 73, 64, 76, 75, 71, 64, - 70, 69, 80, 90,115, 98, 80, 85,109, 86, 69, 70,100,136,101,109, - 119,123,129,130,129, 78, 96,141,151,140,125,150,115,126,129,124 }, - { 21, 23, 23, 30, 26, 30, 59, 33, 33, 59,124, 83, 70, 83,124,124, - 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, - 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, - 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124 } }; #endif /* AVCODEC_SP5X_H */ diff -Nru ffmpeg-4.2.2/libavcodec/speedhq.c ffmpeg-4.4/libavcodec/speedhq.c --- ffmpeg-4.2.2/libavcodec/speedhq.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/speedhq.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,7 +26,9 @@ #define BITSTREAM_READER_LE +#include "config.h" #include "libavutil/attributes.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "get_bits.h" @@ -132,14 +134,15 @@ 31, }; -static RLTable ff_rl_speedhq = { +RLTable ff_rl_speedhq = { 121, 121, - (const uint16_t (*)[])speedhq_vlc, + speedhq_vlc, speedhq_run, speedhq_level, }; +#if CONFIG_SPEEDHQ_DECODER /* NOTE: The first element is always 16, unscaled. */ static const uint8_t unscaled_quant_matrix[64] = { 16, 16, 19, 22, 26, 27, 29, 34, @@ -152,25 +155,21 @@ 27, 29, 35, 38, 46, 56, 69, 83 }; -static uint8_t ff_speedhq_static_rl_table_store[2][2*MAX_RUN + MAX_LEVEL + 3]; +static uint8_t speedhq_static_rl_table_store[2][2*MAX_RUN + MAX_LEVEL + 3]; -static VLC ff_dc_lum_vlc_le; -static VLC ff_dc_chroma_vlc_le; -static VLC ff_dc_alpha_run_vlc_le; -static VLC ff_dc_alpha_level_vlc_le; +static VLC dc_lum_vlc_le; +static VLC dc_chroma_vlc_le; +static VLC dc_alpha_run_vlc_le; +static VLC dc_alpha_level_vlc_le; static inline int decode_dc_le(GetBitContext *gb, int component) { int code, diff; if (component == 0 || component == 3) { - code = get_vlc2(gb, ff_dc_lum_vlc_le.table, DC_VLC_BITS, 2); + code = get_vlc2(gb, dc_lum_vlc_le.table, DC_VLC_BITS, 2); } else { - code = get_vlc2(gb, ff_dc_chroma_vlc_le.table, DC_VLC_BITS, 2); - } - if (code < 0) { - av_log(NULL, AV_LOG_ERROR, "invalid dc code at\n"); - return 0xffff; + code = get_vlc2(gb, dc_chroma_vlc_le.table, DC_VLC_BITS, 2); } if (!code) { diff = 0; @@ -194,7 +193,7 @@ int run, level; UPDATE_CACHE_LE(re, gb); - GET_VLC(run, re, gb, ff_dc_alpha_run_vlc_le.table, ALPHA_VLC_BITS, 2); + GET_VLC(run, re, gb, dc_alpha_run_vlc_le.table, ALPHA_VLC_BITS, 2); if (run < 0) break; i += run; @@ -202,7 +201,7 @@ return AVERROR_INVALIDDATA; UPDATE_CACHE_LE(re, gb); - GET_VLC(level, re, gb, ff_dc_alpha_level_vlc_le.table, ALPHA_VLC_BITS, 2); + GET_VLC(level, re, gb, dc_alpha_level_vlc_le.table, ALPHA_VLC_BITS, 2); block[i++] = level; } @@ -277,6 +276,78 @@ return 0; } +static int decode_speedhq_border(const SHQContext *s, GetBitContext *gb, AVFrame *frame, int field_number, int line_stride) +{ + int linesize_y = frame->linesize[0] * line_stride; + int linesize_cb = frame->linesize[1] * line_stride; + int linesize_cr = frame->linesize[2] * line_stride; + int linesize_a; + int ret; + + if (s->alpha_type != SHQ_NO_ALPHA) + linesize_a = frame->linesize[3] * line_stride; + + for (int y = 0; y < frame->height; y += 16 * line_stride) { + int last_dc[4] = { 1024, 1024, 1024, 1024 }; + uint8_t *dest_y, *dest_cb, *dest_cr, *dest_a; + uint8_t last_alpha[16]; + int x = frame->width - 8; + + dest_y = frame->data[0] + frame->linesize[0] * (y + field_number) + x; + 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) { + 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; + } + if (s->alpha_type != SHQ_NO_ALPHA) { + memset(last_alpha, 255, sizeof(last_alpha)); + dest_a = frame->data[3] + frame->linesize[3] * (y + field_number) + x; + } + + if ((ret = decode_dct_block(s, gb, last_dc, 0, dest_y, linesize_y)) < 0) + return ret; + if ((ret = decode_dct_block(s, gb, last_dc, 0, dest_y + 8, linesize_y)) < 0) + return ret; + if ((ret = decode_dct_block(s, gb, last_dc, 0, dest_y + 8 * linesize_y, linesize_y)) < 0) + return ret; + if ((ret = decode_dct_block(s, gb, last_dc, 0, dest_y + 8 * linesize_y + 8, linesize_y)) < 0) + return ret; + if ((ret = decode_dct_block(s, gb, last_dc, 1, dest_cb, linesize_cb)) < 0) + return ret; + if ((ret = decode_dct_block(s, gb, last_dc, 2, dest_cr, linesize_cr)) < 0) + return ret; + + if (s->subsampling != SHQ_SUBSAMPLING_420) { + if ((ret = decode_dct_block(s, gb, last_dc, 1, dest_cb + 8 * linesize_cb, linesize_cb)) < 0) + return ret; + if ((ret = decode_dct_block(s, gb, last_dc, 2, dest_cr + 8 * linesize_cr, linesize_cr)) < 0) + return ret; + } + + if (s->alpha_type == SHQ_RLE_ALPHA) { + /* Alpha coded using 16x8 RLE blocks. */ + if ((ret = decode_alpha_block(s, gb, last_alpha, dest_a, linesize_a)) < 0) + return ret; + if ((ret = decode_alpha_block(s, gb, last_alpha, dest_a + 8 * linesize_a, linesize_a)) < 0) + return ret; + } else if (s->alpha_type == SHQ_DCT_ALPHA) { + /* Alpha encoded exactly like luma. */ + if ((ret = decode_dct_block(s, gb, last_dc, 3, dest_a, linesize_a)) < 0) + return ret; + if ((ret = decode_dct_block(s, gb, last_dc, 3, dest_a + 8, linesize_a)) < 0) + return ret; + if ((ret = decode_dct_block(s, gb, last_dc, 3, dest_a + 8 * linesize_a, linesize_a)) < 0) + return ret; + if ((ret = decode_dct_block(s, gb, last_dc, 3, dest_a + 8 * linesize_a + 8, linesize_a)) < 0) + return ret; + } + } + + return 0; +} + static int decode_speedhq_field(const SHQContext *s, const uint8_t *buf, int buf_size, AVFrame *frame, int field_number, int start, int end, int line_stride) { int ret, slice_number, slice_offsets[5]; @@ -284,6 +355,7 @@ int linesize_cb = frame->linesize[1] * line_stride; int linesize_cr = frame->linesize[2] * line_stride; int linesize_a; + GetBitContext gb; if (s->alpha_type != SHQ_NO_ALPHA) linesize_a = frame->linesize[3] * line_stride; @@ -305,7 +377,6 @@ } for (slice_number = 0; slice_number < 4; slice_number++) { - GetBitContext gb; uint32_t slice_begin, slice_end; int x, y; @@ -334,7 +405,7 @@ dest_a = frame->data[3] + frame->linesize[3] * (y + field_number); } - for (x = 0; x < frame->width; x += 16) { + for (x = 0; x < frame->width - 8 * (s->subsampling != SHQ_SUBSAMPLING_444); x += 16) { /* Decode the four luma blocks. */ if ((ret = decode_dct_block(s, &gb, last_dc, 0, dest_y, linesize_y)) < 0) return ret; @@ -403,6 +474,9 @@ } } + if (s->subsampling != SHQ_SUBSAMPLING_444 && (frame->width & 15)) + return decode_speedhq_border(s, &gb, frame, field_number, line_stride); + return 0; } @@ -424,7 +498,7 @@ uint32_t second_field_offset; int ret; - if (buf_size < 4) + if (buf_size < 4 || avctx->width < 8) return AVERROR_INVALIDDATA; quality = buf[0]; @@ -447,7 +521,7 @@ } frame->key_frame = 1; - if (second_field_offset == 4) { + if (second_field_offset == 4 || second_field_offset == (buf_size-4)) { /* * Overlapping first and second fields is used to signal * encoding only a single field. In this case, "height" @@ -515,7 +589,7 @@ av_assert0(entry == FF_ARRAY_ELEMS(run_code)); - INIT_LE_VLC_SPARSE_STATIC(&ff_dc_alpha_run_vlc_le, ALPHA_VLC_BITS, + INIT_LE_VLC_SPARSE_STATIC(&dc_alpha_run_vlc_le, ALPHA_VLC_BITS, FF_ARRAY_ELEMS(run_code), run_bits, 1, 1, run_code, 2, 2, @@ -555,49 +629,26 @@ av_assert0(entry == FF_ARRAY_ELEMS(level_code)); - INIT_LE_VLC_SPARSE_STATIC(&ff_dc_alpha_level_vlc_le, ALPHA_VLC_BITS, + INIT_LE_VLC_SPARSE_STATIC(&dc_alpha_level_vlc_le, ALPHA_VLC_BITS, FF_ARRAY_ELEMS(level_code), level_bits, 1, 1, level_code, 2, 2, level_symbols, 2, 2, 288); } -static uint32_t reverse(uint32_t num, int bits) -{ - return bitswap_32(num) >> (32 - bits); -} - -static void reverse_code(const uint16_t *code, const uint8_t *bits, - uint16_t *reversed_code, int num_entries) -{ - int i; - for (i = 0; i < num_entries; i++) { - reversed_code[i] = reverse(code[i], bits[i]); - } -} - static av_cold void speedhq_static_init(void) { - uint16_t ff_mpeg12_vlc_dc_lum_code_reversed[12]; - uint16_t ff_mpeg12_vlc_dc_chroma_code_reversed[12]; - - /* Exactly the same as MPEG-2, except little-endian. */ - reverse_code(ff_mpeg12_vlc_dc_lum_code, - ff_mpeg12_vlc_dc_lum_bits, - ff_mpeg12_vlc_dc_lum_code_reversed, - 12); - INIT_LE_VLC_STATIC(&ff_dc_lum_vlc_le, DC_VLC_BITS, 12, - ff_mpeg12_vlc_dc_lum_bits, 1, 1, - ff_mpeg12_vlc_dc_lum_code_reversed, 2, 2, 512); - reverse_code(ff_mpeg12_vlc_dc_chroma_code, - ff_mpeg12_vlc_dc_chroma_bits, - ff_mpeg12_vlc_dc_chroma_code_reversed, - 12); - INIT_LE_VLC_STATIC(&ff_dc_chroma_vlc_le, DC_VLC_BITS, 12, - ff_mpeg12_vlc_dc_chroma_bits, 1, 1, - ff_mpeg12_vlc_dc_chroma_code_reversed, 2, 2, 514); + /* Exactly the same as MPEG-2, except for a little-endian reader. */ + INIT_CUSTOM_VLC_STATIC(&dc_lum_vlc_le, DC_VLC_BITS, 12, + ff_mpeg12_vlc_dc_lum_bits, 1, 1, + ff_mpeg12_vlc_dc_lum_code, 2, 2, + INIT_VLC_OUTPUT_LE, 512); + INIT_CUSTOM_VLC_STATIC(&dc_chroma_vlc_le, DC_VLC_BITS, 12, + ff_mpeg12_vlc_dc_chroma_bits, 1, 1, + ff_mpeg12_vlc_dc_chroma_code, 2, 2, + INIT_VLC_OUTPUT_LE, 514); - ff_rl_init(&ff_rl_speedhq, ff_speedhq_static_rl_table_store); + ff_rl_init(&ff_rl_speedhq, speedhq_static_rl_table_store); INIT_2D_VLC_RL(ff_rl_speedhq, 674, INIT_VLC_LE); compute_alpha_vlcs(); @@ -683,3 +734,4 @@ .decode = speedhq_decode_frame, .capabilities = AV_CODEC_CAP_DR1, }; +#endif /* CONFIG_SPEEDHQ_DECODER */ diff -Nru ffmpeg-4.2.2/libavcodec/speedhqenc.c ffmpeg-4.4/libavcodec/speedhqenc.c --- ffmpeg-4.2.2/libavcodec/speedhqenc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/speedhqenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,308 @@ +/* + * SpeedHQ encoder + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 Michael Niedermayer + * Copyright (c) 2020 FFmpeg + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * SpeedHQ encoder. + */ + +#include "libavutil/pixdesc.h" +#include "libavutil/thread.h" + +#include "avcodec.h" +#include "mpeg12.h" +#include "mpegvideo.h" +#include "speedhqenc.h" + +extern RLTable ff_rl_speedhq; +static uint8_t speedhq_static_rl_table_store[2][2*MAX_RUN + MAX_LEVEL + 3]; + +static uint16_t mpeg12_vlc_dc_lum_code_reversed[12]; +static uint16_t mpeg12_vlc_dc_chroma_code_reversed[12]; + +/* simple include everything table for dc, first byte is bits + * number next 3 are code */ +static uint32_t speedhq_lum_dc_uni[512]; +static uint32_t speedhq_chr_dc_uni[512]; + +static uint8_t uni_speedhq_ac_vlc_len[64 * 64 * 2]; + +static uint32_t reverse(uint32_t num, int bits) +{ + return bitswap_32(num) >> (32 - bits); +} + +static void reverse_code(const uint16_t *code, const uint8_t *bits, + uint16_t *reversed_code, int num_entries) +{ + for (int i = 0; i < num_entries; i++) + reversed_code[i] = reverse(code[i], bits[i]); +} + +static av_cold void speedhq_init_static_data(void) +{ + /* Exactly the same as MPEG-2, except little-endian. */ + reverse_code(ff_mpeg12_vlc_dc_lum_code, + ff_mpeg12_vlc_dc_lum_bits, + mpeg12_vlc_dc_lum_code_reversed, + 12); + reverse_code(ff_mpeg12_vlc_dc_chroma_code, + ff_mpeg12_vlc_dc_chroma_bits, + mpeg12_vlc_dc_chroma_code_reversed, + 12); + + ff_rl_init(&ff_rl_speedhq, speedhq_static_rl_table_store); + + /* build unified dc encoding tables */ + for (int i = -255; i < 256; i++) { + int adiff, index; + int bits, code; + int diff = i; + + adiff = FFABS(diff); + if (diff < 0) + diff--; + index = av_log2(2 * adiff); + + bits = ff_mpeg12_vlc_dc_lum_bits[index] + index; + code = mpeg12_vlc_dc_lum_code_reversed[index] + + (av_mod_uintp2(diff, index) << ff_mpeg12_vlc_dc_lum_bits[index]); + speedhq_lum_dc_uni[i + 255] = bits + (code << 8); + + bits = ff_mpeg12_vlc_dc_chroma_bits[index] + index; + code = mpeg12_vlc_dc_chroma_code_reversed[index] + + (av_mod_uintp2(diff, index) << ff_mpeg12_vlc_dc_chroma_bits[index]); + speedhq_chr_dc_uni[i + 255] = bits + (code << 8); + } + + ff_mpeg1_init_uni_ac_vlc(&ff_rl_speedhq, uni_speedhq_ac_vlc_len); +} + +av_cold int ff_speedhq_encode_init(MpegEncContext *s) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + + av_assert0(s->slice_context_count == 1); + + if (s->width > 65500 || s->height > 65500) { + av_log(s, AV_LOG_ERROR, "SpeedHQ does not support resolutions above 65500x65500\n"); + return AVERROR(EINVAL); + } + + s->min_qcoeff = -2048; + s->max_qcoeff = 2047; + + ff_thread_once(&init_static_once, speedhq_init_static_data); + + s->intra_ac_vlc_length = + s->intra_ac_vlc_last_length = + s->intra_chroma_ac_vlc_length = + s->intra_chroma_ac_vlc_last_length = uni_speedhq_ac_vlc_len; + + switch (s->avctx->pix_fmt) { + case AV_PIX_FMT_YUV420P: + s->avctx->codec_tag = MKTAG('S','H','Q','0'); + break; + case AV_PIX_FMT_YUV422P: + s->avctx->codec_tag = MKTAG('S','H','Q','2'); + break; + case AV_PIX_FMT_YUV444P: + s->avctx->codec_tag = MKTAG('S','H','Q','4'); + break; + default: + av_assert0(0); + } + + return 0; +} + +void ff_speedhq_encode_picture_header(MpegEncContext *s) +{ + put_bits_le(&s->pb, 8, 100 - s->qscale * 2); /* FIXME why doubled */ + put_bits_le(&s->pb, 24, 4); /* no second field */ + + /* length of first slice, will be filled out later */ + s->slice_start = 4; + put_bits_le(&s->pb, 24, 0); +} + +void ff_speedhq_end_slice(MpegEncContext *s) +{ + int slice_len; + + flush_put_bits_le(&s->pb); + slice_len = s->pb.buf_ptr - (s->pb.buf + s->slice_start); + AV_WL24(s->pb.buf + s->slice_start, slice_len); + + /* length of next slice, will be filled out later */ + s->slice_start = s->pb.buf_ptr - s->pb.buf; + put_bits_le(&s->pb, 24, 0); +} + +static inline void encode_dc(PutBitContext *pb, int diff, int component) +{ + unsigned int diff_u = diff + 255; + if (diff_u >= 511) { + int index; + + if (diff < 0) { + index = av_log2_16bit(-2 * diff); + diff--; + } else { + index = av_log2_16bit(2 * diff); + } + if (component == 0) + put_bits_le(pb, + ff_mpeg12_vlc_dc_lum_bits[index] + index, + mpeg12_vlc_dc_lum_code_reversed[index] + + (av_mod_uintp2(diff, index) << ff_mpeg12_vlc_dc_lum_bits[index])); + else + put_bits_le(pb, + ff_mpeg12_vlc_dc_chroma_bits[index] + index, + mpeg12_vlc_dc_chroma_code_reversed[index] + + (av_mod_uintp2(diff, index) << ff_mpeg12_vlc_dc_chroma_bits[index])); + } else { + if (component == 0) + put_bits_le(pb, + speedhq_lum_dc_uni[diff + 255] & 0xFF, + speedhq_lum_dc_uni[diff + 255] >> 8); + else + put_bits_le(pb, + speedhq_chr_dc_uni[diff + 255] & 0xFF, + speedhq_chr_dc_uni[diff + 255] >> 8); + } +} + +static void encode_block(MpegEncContext *s, int16_t *block, int n) +{ + int alevel, level, last_non_zero, dc, i, j, run, last_index, sign; + int code; + int component, val; + + /* DC coef */ + component = (n <= 3 ? 0 : (n&1) + 1); + dc = block[0]; /* overflow is impossible */ + val = s->last_dc[component] - dc; /* opposite of most codecs */ + encode_dc(&s->pb, val, component); + s->last_dc[component] = dc; + + /* now quantify & encode AC coefs */ + last_non_zero = 0; + last_index = s->block_last_index[n]; + + for (i = 1; i <= last_index; i++) { + j = s->intra_scantable.permutated[i]; + level = block[j]; + + /* encode using VLC */ + if (level != 0) { + run = i - last_non_zero - 1; + + alevel = level; + MASK_ABS(sign, alevel); + sign &= 1; + + if (alevel <= ff_rl_speedhq.max_level[0][run]) { + code = ff_rl_speedhq.index_run[0][run] + alevel - 1; + /* store the VLC & sign at once */ + 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: only clip in this case */ + put_bits_le(&s->pb, 6, run); + put_bits_le(&s->pb, 12, level + 2048); + } + 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]); +} + +void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]) +{ + int i; + for(i=0;i<6;i++) { + encode_block(s, block[i], i); + } + if (s->chroma_format == CHROMA_444) { + encode_block(s, block[8], 8); + encode_block(s, block[9], 9); + + encode_block(s, block[6], 6); + encode_block(s, block[7], 7); + + encode_block(s, block[10], 10); + encode_block(s, block[11], 11); + } else if (s->chroma_format == CHROMA_422) { + encode_block(s, block[6], 6); + encode_block(s, block[7], 7); + } + + s->i_tex_bits += get_bits_diff(s); +} + +static int ff_speedhq_mb_rows_in_slice(int slice_num, int mb_height) +{ + return mb_height / 4 + (slice_num < (mb_height % 4)); +} + +int ff_speedhq_mb_y_order_to_mb(int mb_y_order, int mb_height, int *first_in_slice) +{ + int slice_num = 0; + while (mb_y_order >= ff_speedhq_mb_rows_in_slice(slice_num, mb_height)) { + mb_y_order -= ff_speedhq_mb_rows_in_slice(slice_num, mb_height); + slice_num++; + } + *first_in_slice = (mb_y_order == 0); + return mb_y_order * 4 + slice_num; +} + +#if CONFIG_SPEEDHQ_ENCODER +static const AVClass speedhq_class = { + .class_name = "speedhq encoder", + .item_name = av_default_item_name, + .option = ff_mpv_generic_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_speedhq_encoder = { + .name = "speedhq", + .long_name = NULL_IF_CONFIG_SMALL("NewTek SpeedHQ"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SPEEDHQ, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_mpv_encode_init, + .encode2 = ff_mpv_encode_picture, + .close = ff_mpv_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_NONE + }, + .priv_class = &speedhq_class, +}; +#endif diff -Nru ffmpeg-4.2.2/libavcodec/speedhqenc.h ffmpeg-4.4/libavcodec/speedhqenc.h --- ffmpeg-4.2.2/libavcodec/speedhqenc.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/speedhqenc.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * SpeedHQ encoder + * 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 + */ + +/** + * @file + * SpeedHQ encoder. + */ + +#ifndef AVCODEC_SPEEDHQENC_H +#define AVCODEC_SPEEDHQENC_H + +#include + +#include "mjpeg.h" +#include "mjpegenc_common.h" +#include "mpegvideo.h" +#include "put_bits.h" + +int ff_speedhq_encode_init(MpegEncContext *s); +void ff_speedhq_encode_close(MpegEncContext *s); +void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]); + +void ff_speedhq_encode_picture_header(MpegEncContext *s); +void ff_speedhq_end_slice(MpegEncContext *s); + +int ff_speedhq_mb_y_order_to_mb(int mb_y_order, int mb_height, int *first_in_slice); + +#endif /* AVCODEC_SPEEDHQENC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/srtdec.c ffmpeg-4.4/libavcodec/srtdec.c --- ffmpeg-4.2.2/libavcodec/srtdec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/srtdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -58,7 +58,8 @@ AVSubtitle *sub = data; AVBPrint buffer; int x1 = -1, y1 = -1, x2 = -1, y2 = -1; - int size, ret; + int ret; + buffer_size_t size; const uint8_t *p = av_packet_get_side_data(avpkt, AV_PKT_DATA_SUBTITLE_POSITION, &size); FFASSDecoderContext *s = avctx->priv_data; diff -Nru ffmpeg-4.2.2/libavcodec/srtenc.c ffmpeg-4.4/libavcodec/srtenc.c --- ffmpeg-4.2.2/libavcodec/srtenc.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/srtenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -241,7 +241,7 @@ if (sub->rects[i]->type != SUBTITLE_ASS) { av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n"); - return AVERROR(ENOSYS); + return AVERROR(EINVAL); } #if FF_API_ASS_TIMING @@ -276,7 +276,7 @@ if (s->buffer.len > bufsize) { av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); - return -1; + return AVERROR_BUFFER_TOO_SMALL; } memcpy(buf, s->buffer.str, s->buffer.len); diff -Nru ffmpeg-4.2.2/libavcodec/svq13.c ffmpeg-4.4/libavcodec/svq13.c --- ffmpeg-4.2.2/libavcodec/svq13.c 2016-03-29 02:25:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/svq13.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -/* - * SVQ1/SVQ3 decoder common code - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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 "svq1.h" - -static const uint16_t checksum_table[256] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 -}; - -uint16_t ff_svq1_packet_checksum (const uint8_t *data, - const int length, int value) -{ - int i; - - for (i = 0; i < length; i++) - value = checksum_table[data[i] ^ (value >> 8)] ^ ((value & 0xFF) << 8); - - return value; -} diff -Nru ffmpeg-4.2.2/libavcodec/svq1_cb.h ffmpeg-4.4/libavcodec/svq1_cb.h --- ffmpeg-4.2.2/libavcodec/svq1_cb.h 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/svq1_cb.h 2021-04-08 21:28:39.000000000 +0000 @@ -34,7 +34,7 @@ #include #include -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" /* 6x16-entry codebook for inter-coded 4x2 vectors */ DECLARE_ALIGNED(4, static const int8_t, svq1_inter_codebook_4x2)[768] = { diff -Nru ffmpeg-4.2.2/libavcodec/svq1dec.c ffmpeg-4.4/libavcodec/svq1dec.c --- ffmpeg-4.2.2/libavcodec/svq1dec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/svq1dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,6 +32,9 @@ * http://www.pcisys.net/~melanson/codecs/ */ +#include "libavutil/crc.h" +#include "libavutil/thread.h" + #include "avcodec.h" #include "get_bits.h" #include "h263.h" @@ -40,6 +43,7 @@ #include "mathops.h" #include "svq1.h" +#define SVQ1_BLOCK_TYPE_VLC_BITS 3 static VLC svq1_block_type; static VLC svq1_motion_component; static VLC svq1_intra_multistage[6]; @@ -61,6 +65,9 @@ uint8_t *pkt_swapped; int pkt_swapped_allocated; + svq1_pmv *pmv; + int pmv_allocated; + int width; int height; int frame_code; @@ -453,7 +460,8 @@ int result = 0; /* get block type */ - block_type = get_vlc2(bitbuf, svq1_block_type.table, 2, 2); + block_type = get_vlc2(bitbuf, svq1_block_type.table, + SVQ1_BLOCK_TYPE_VLC_BITS, 1); /* reset motion vectors */ if (block_type == SVQ1_BLOCK_SKIP || block_type == SVQ1_BLOCK_INTRA) { @@ -546,9 +554,7 @@ if (s->frame_code == 0x50 || s->frame_code == 0x60) { int csum = get_bits(bitbuf, 16); - csum = ff_svq1_packet_checksum(bitbuf->buffer, - bitbuf->size_in_bits >> 3, - csum); + csum = av_bswap16(av_crc(av_crc_get_table(AV_CRC_16_CCITT), av_bswap16(csum), bitbuf->buffer, bitbuf->size_in_bits >> 3)); ff_dlog(avctx, "%s checksum (%02x) for packet data\n", (csum == 0) ? "correct" : "incorrect", csum); @@ -602,6 +608,8 @@ if (skip_1stop_8data_bits(bitbuf) < 0) return AVERROR_INVALIDDATA; } + if (get_bits_left(bitbuf) <= 0) + return AVERROR_INVALIDDATA; s->width = width; s->height = height; @@ -617,7 +625,6 @@ AVFrame *cur = data; uint8_t *current; int result, i, x, y, width, height; - svq1_pmv *pmv; int ret; /* initialize bit buffer */ @@ -677,8 +684,8 @@ if (result < 0) return result; - pmv = av_malloc((FFALIGN(s->width, 16) / 8 + 3) * sizeof(*pmv)); - if (!pmv) + av_fast_padded_malloc(&s->pmv, &s->pmv_allocated, (FFALIGN(s->width, 16) / 8 + 3) * sizeof(*s->pmv)); + if (!s->pmv) return AVERROR(ENOMEM); /* decode y, u and v components */ @@ -706,7 +713,7 @@ av_log(avctx, AV_LOG_ERROR, "Error in svq1_decode_block %i (keyframe)\n", result); - goto err; + return result; } } current += 16 * linesize; @@ -717,28 +724,27 @@ if (!previous || s->prev->width != s->width || s->prev->height != s->height) { av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n"); - result = AVERROR_INVALIDDATA; - goto err; + return AVERROR_INVALIDDATA; } - memset(pmv, 0, ((width / 8) + 3) * sizeof(svq1_pmv)); + memset(s->pmv, 0, ((width / 8) + 3) * sizeof(svq1_pmv)); for (y = 0; y < height; y += 16) { for (x = 0; x < width; x += 16) { result = svq1_decode_delta_block(avctx, &s->hdsp, &s->gb, ¤t[x], previous, linesize, - pmv, x, y, width, height); + s->pmv, x, y, width, height); if (result != 0) { ff_dlog(avctx, "Error in svq1_decode_delta_block %i\n", result); - goto err; + return result; } } - pmv[0].x = - pmv[0].y = 0; + s->pmv[0].x = + s->pmv[0].y = 0; current += 16 * linesize; } @@ -749,42 +755,26 @@ av_frame_unref(s->prev); result = av_frame_ref(s->prev, cur); if (result < 0) - goto err; + return result; } *got_frame = 1; result = buf_size; -err: - av_free(pmv); return result; } -static av_cold int svq1_decode_init(AVCodecContext *avctx) +static av_cold void svq1_static_init(void) { - SVQ1Context *s = avctx->priv_data; - int i; - int offset = 0; - - s->prev = av_frame_alloc(); - if (!s->prev) - return AVERROR(ENOMEM); - - s->width = avctx->width + 3 & ~3; - s->height = avctx->height + 3 & ~3; - avctx->pix_fmt = AV_PIX_FMT_YUV410P; - - ff_hpeldsp_init(&s->hdsp, avctx->flags); - - INIT_VLC_STATIC(&svq1_block_type, 2, 4, + INIT_VLC_STATIC(&svq1_block_type, SVQ1_BLOCK_TYPE_VLC_BITS, 4, &ff_svq1_block_type_vlc[0][1], 2, 1, - &ff_svq1_block_type_vlc[0][0], 2, 1, 6); + &ff_svq1_block_type_vlc[0][0], 2, 1, 8); INIT_VLC_STATIC(&svq1_motion_component, 7, 33, &ff_mvtab[0][1], 2, 1, &ff_mvtab[0][0], 2, 1, 176); - for (i = 0; i < 6; i++) { + for (int i = 0, offset = 0; i < 6; i++) { static const uint8_t sizes[2][6] = { { 14, 10, 14, 18, 16, 18 }, { 10, 10, 14, 14, 14, 16 } }; static VLC_TYPE table[168][2]; @@ -811,6 +801,24 @@ INIT_VLC_STATIC(&svq1_inter_mean, 9, 512, &ff_svq1_inter_mean_vlc[0][1], 4, 2, &ff_svq1_inter_mean_vlc[0][0], 4, 2, 1434); +} + +static av_cold int svq1_decode_init(AVCodecContext *avctx) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + SVQ1Context *s = avctx->priv_data; + + s->prev = av_frame_alloc(); + if (!s->prev) + return AVERROR(ENOMEM); + + s->width = avctx->width + 3 & ~3; + s->height = avctx->height + 3 & ~3; + avctx->pix_fmt = AV_PIX_FMT_YUV410P; + + ff_hpeldsp_init(&s->hdsp, avctx->flags); + + ff_thread_once(&init_static_once, svq1_static_init); return 0; } @@ -822,6 +830,8 @@ av_frame_free(&s->prev); av_freep(&s->pkt_swapped); s->pkt_swapped_allocated = 0; + av_freep(&s->pmv); + s->pmv_allocated = 0; return 0; } @@ -846,4 +856,5 @@ .flush = svq1_flush, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV410P, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/svq1enc.c ffmpeg-4.4/libavcodec/svq1enc.c --- ffmpeg-4.2.2/libavcodec/svq1enc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/svq1enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,6 +33,7 @@ #include "h263.h" #include "internal.h" #include "mpegutils.h" +#include "packet_internal.h" #include "svq1.h" #include "svq1enc.h" #include "svq1enc_cb.h" @@ -345,7 +346,7 @@ s->m.first_slice_line = 0; } - ff_fix_long_p_mvs(&s->m); + ff_fix_long_p_mvs(&s->m, CANDIDATE_MB_TYPE_INTRA); ff_fix_long_mvs(&s->m, NULL, 0, s->m.p_mv_table, s->m.f_code, CANDIDATE_MB_TYPE_INTER, 0); } @@ -471,7 +472,7 @@ if (best != 2) for (i = 5; i >= 0; i--) - avpriv_copy_bits(&s->pb, reorder_buffer[best][i], + ff_copy_bits(&s->pb, reorder_buffer[best][i], count[best][i]); if (best == 0) s->hdsp.put_pixels_tab[0][0](decoded, temp, stride, 16); @@ -528,7 +529,6 @@ s->current_picture = av_frame_alloc(); s->last_picture = av_frame_alloc(); if (!s->current_picture || !s->last_picture) { - svq1_encode_end(avctx); return AVERROR(ENOMEM); } @@ -545,7 +545,6 @@ s->m.avctx = avctx; if ((ret = ff_mpv_common_init(&s->m)) < 0) { - svq1_encode_end(avctx); return ret; } @@ -563,7 +562,6 @@ if (!s->m.me.temp || !s->m.me.scratchpad || !s->m.me.map || !s->m.me.score_map || !s->mb_type || !s->dummy) { - svq1_encode_end(avctx); return AVERROR(ENOMEM); } @@ -649,7 +647,7 @@ } } - // avpriv_align_put_bits(&s->pb); + // align_put_bits(&s->pb); while (put_bits_count(&s->pb) & 31) put_bits(&s->pb, 1, 0); @@ -691,6 +689,7 @@ .init = svq1_encode_init, .encode2 = svq1_encode_frame, .close = svq1_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV410P, AV_PIX_FMT_NONE }, }; diff -Nru ffmpeg-4.2.2/libavcodec/svq1enc.h ffmpeg-4.4/libavcodec/svq1enc.h --- ffmpeg-4.2.2/libavcodec/svq1enc.h 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/svq1enc.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,7 @@ #include #include "libavutil/frame.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "hpeldsp.h" diff -Nru ffmpeg-4.2.2/libavcodec/svq1.h ffmpeg-4.4/libavcodec/svq1.h --- ffmpeg-4.2.2/libavcodec/svq1.h 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/svq1.h 2020-07-11 10:39:30.000000000 +0000 @@ -42,9 +42,6 @@ #define SVQ1_BLOCK_INTER_4V 2 #define SVQ1_BLOCK_INTRA 3 -uint16_t ff_svq1_packet_checksum(const uint8_t *data, - const int length, int value); - extern const int8_t *const ff_svq1_inter_codebooks[6]; extern const int8_t *const ff_svq1_intra_codebooks[6]; diff -Nru ffmpeg-4.2.2/libavcodec/svq3.c ffmpeg-4.4/libavcodec/svq3.c --- ffmpeg-4.2.2/libavcodec/svq3.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/svq3.c 2021-04-08 21:28:39.000000000 +0000 @@ -43,6 +43,9 @@ #include #include "libavutil/attributes.h" +#include "libavutil/crc.h" +#include "libavutil/mem_internal.h" + #include "internal.h" #include "avcodec.h" #include "mpegutils.h" @@ -68,15 +71,10 @@ typedef struct SVQ3Frame { AVFrame *f; - AVBufferRef *motion_val_buf[2]; + int16_t (*motion_val_buf[2])[2]; int16_t (*motion_val[2])[2]; - AVBufferRef *mb_type_buf; - uint32_t *mb_type; - - - AVBufferRef *ref_index_buf[2]; - int8_t *ref_index[2]; + uint32_t *mb_type_buf, *mb_type; } SVQ3Frame; typedef struct SVQ3Context { @@ -145,6 +143,7 @@ DECLARE_ALIGNED(8, uint8_t, non_zero_count_cache)[15 * 8]; uint32_t dequant4_coeff[QP_MAX_NUM + 1][16]; int block_offset[2 * (16 * 3)]; + SVQ3Frame frames[3]; } SVQ3Context; #define FULLPEL_MODE 1 @@ -219,8 +218,6 @@ 61694, 68745, 77615, 89113, 100253, 109366, 126635, 141533 }; -static int svq3_decode_end(AVCodecContext *avctx); - static void svq3_luma_dc_dequant_idct_c(int16_t *output, int16_t *input, int qp) { const unsigned qmul = svq3_dequant_coeff[qp]; @@ -1133,13 +1130,9 @@ int marker_found = 0; int ret; - s->cur_pic = av_mallocz(sizeof(*s->cur_pic)); - s->last_pic = av_mallocz(sizeof(*s->last_pic)); - s->next_pic = av_mallocz(sizeof(*s->next_pic)); - if (!s->next_pic || !s->last_pic || !s->cur_pic) { - ret = AVERROR(ENOMEM); - goto fail; - } + s->cur_pic = &s->frames[0]; + s->last_pic = &s->frames[1]; + s->next_pic = &s->frames[2]; s->cur_pic->f = av_frame_alloc(); s->last_pic->f = av_frame_alloc(); @@ -1186,10 +1179,8 @@ int w,h; size = AV_RB32(&extradata[4]); - if (size > extradata_end - extradata - 8) { - ret = AVERROR_INVALIDDATA; - goto fail; - } + if (size > extradata_end - extradata - 8) + return AVERROR_INVALIDDATA; init_get_bits(&gb, extradata + 8, size * 8); /* 'frame size code' and optional 'width, height' */ @@ -1230,7 +1221,7 @@ } ret = ff_set_dimensions(avctx, w, h); if (ret < 0) - goto fail; + return ret; s->halfpel_flag = get_bits1(&gb); s->thirdpel_flag = get_bits1(&gb); @@ -1249,10 +1240,8 @@ av_log(avctx, AV_LOG_DEBUG, "Unknown fields %d %d %d %d %d\n", unk0, unk1, unk2, unk3, unk4); - if (skip_1stop_8data_bits(&gb) < 0) { - ret = AVERROR_INVALIDDATA; - goto fail; - } + if (skip_1stop_8data_bits(&gb) < 0) + return AVERROR_INVALIDDATA; s->has_watermark = get_bits1(&gb); avctx->has_b_frames = !s->low_delay; @@ -1270,16 +1259,13 @@ uint8_t *buf; if (watermark_height <= 0 || - (uint64_t)watermark_width * 4 > UINT_MAX / watermark_height) { - ret = -1; - goto fail; - } + (uint64_t)watermark_width * 4 > UINT_MAX / watermark_height) + return AVERROR_INVALIDDATA; buf = av_malloc(buf_len); - if (!buf) { - ret = AVERROR(ENOMEM); - goto fail; - } + if (!buf) + return AVERROR(ENOMEM); + av_log(avctx, AV_LOG_DEBUG, "watermark size: %ux%u\n", watermark_width, watermark_height); av_log(avctx, AV_LOG_DEBUG, @@ -1290,10 +1276,10 @@ av_log(avctx, AV_LOG_ERROR, "could not uncompress watermark logo\n"); av_free(buf); - ret = -1; - goto fail; + return -1; } - s->watermark_key = ff_svq1_packet_checksum(buf, buf_len, 0); + s->watermark_key = av_bswap16(av_crc(av_crc_get_table(AV_CRC_16_CCITT), 0, buf, buf_len)); + s->watermark_key = s->watermark_key << 16 | s->watermark_key; av_log(avctx, AV_LOG_DEBUG, "watermark key %#"PRIx32"\n", s->watermark_key); @@ -1301,8 +1287,7 @@ #else av_log(avctx, AV_LOG_ERROR, "this svq3 file contains watermark which need zlib support compiled in\n"); - ret = -1; - goto fail; + return AVERROR(ENOSYS); #endif } } @@ -1334,19 +1319,15 @@ init_dequant4_coeff_table(s); return 0; -fail: - svq3_decode_end(avctx); - return ret; } static void free_picture(AVCodecContext *avctx, SVQ3Frame *pic) { int i; for (i = 0; i < 2; i++) { - av_buffer_unref(&pic->motion_val_buf[i]); - av_buffer_unref(&pic->ref_index_buf[i]); + av_freep(&pic->motion_val_buf[i]); } - av_buffer_unref(&pic->mb_type_buf); + av_freep(&pic->mb_type_buf); av_frame_unref(pic->f); } @@ -1355,7 +1336,6 @@ { SVQ3Context *s = avctx->priv_data; const int big_mb_num = s->mb_stride * (s->mb_height + 1) + 1; - const int mb_array_size = s->mb_stride * s->mb_height; const int b4_stride = s->mb_width * 4 + 1; const int b4_array_size = b4_stride * s->mb_height * 4; int ret; @@ -1363,21 +1343,19 @@ if (!pic->motion_val_buf[0]) { int i; - pic->mb_type_buf = av_buffer_allocz((big_mb_num + s->mb_stride) * sizeof(uint32_t)); + pic->mb_type_buf = av_calloc(big_mb_num + s->mb_stride, sizeof(uint32_t)); if (!pic->mb_type_buf) return AVERROR(ENOMEM); - pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * s->mb_stride + 1; + pic->mb_type = pic->mb_type_buf + 2 * s->mb_stride + 1; for (i = 0; i < 2; i++) { - pic->motion_val_buf[i] = av_buffer_allocz(2 * (b4_array_size + 4) * sizeof(int16_t)); - pic->ref_index_buf[i] = av_buffer_allocz(4 * mb_array_size); - if (!pic->motion_val_buf[i] || !pic->ref_index_buf[i]) { + pic->motion_val_buf[i] = av_calloc(b4_array_size + 4, 2 * sizeof(int16_t)); + if (!pic->motion_val_buf[i]) { ret = AVERROR(ENOMEM); goto fail; } - pic->motion_val[i] = (int16_t (*)[2])pic->motion_val_buf[i]->data + 4; - pic->ref_index[i] = pic->ref_index_buf[i]->data; + pic->motion_val[i] = pic->motion_val_buf[i] + 4; } } @@ -1628,9 +1606,6 @@ av_frame_free(&s->cur_pic->f); av_frame_free(&s->next_pic->f); av_frame_free(&s->last_pic->f); - av_freep(&s->cur_pic); - av_freep(&s->next_pic); - av_freep(&s->last_pic); av_freep(&s->slice_buf); av_freep(&s->intra4x4_pred_mode); av_freep(&s->edge_emu_buffer); @@ -1657,4 +1632,5 @@ AV_CODEC_CAP_DELAY, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_NONE}, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/takdec.c ffmpeg-4.4/libavcodec/takdec.c --- ffmpeg-4.2.2/libavcodec/takdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/takdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,7 @@ */ #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/samplefmt.h" #define BITSTREAM_READER_LE @@ -915,13 +916,6 @@ } #if HAVE_THREADS -static int init_thread_copy(AVCodecContext *avctx) -{ - TAKDecContext *s = avctx->priv_data; - s->avctx = avctx; - return 0; -} - static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) { @@ -953,9 +947,8 @@ .init = tak_decode_init, .close = tak_decode_close, .decode = tak_decode_frame, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, diff -Nru ffmpeg-4.2.2/libavcodec/takdsp.c ffmpeg-4.4/libavcodec/takdsp.c --- ffmpeg-4.2.2/libavcodec/takdsp.c 2018-07-17 09:27:41.000000000 +0000 +++ ffmpeg-4.4/libavcodec/takdsp.c 2021-02-20 20:27:47.000000000 +0000 @@ -65,7 +65,7 @@ for (i = 0; i < length; i++) { int32_t a = p1[i]; int32_t b = p2[i]; - b = dfactor * (b >> dshift) + 128 >> 8 << dshift; + b = (unsigned)(dfactor * (b >> dshift) + 128 >> 8) << dshift; p1[i] = b - a; } } diff -Nru ffmpeg-4.2.2/libavcodec/tdsc.c ffmpeg-4.4/libavcodec/tdsc.c --- ffmpeg-4.2.2/libavcodec/tdsc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tdsc.c 2021-04-08 21:28:39.000000000 +0000 @@ -53,6 +53,7 @@ GetByteContext gbc; AVFrame *refframe; // full decoded frame (without cursor) + AVPacket *jpkt; // encoded JPEG tile AVFrame *jpgframe; // decoded JPEG tile uint8_t *tilebuffer; // buffer containing tile data @@ -80,6 +81,7 @@ av_frame_free(&ctx->refframe); av_frame_free(&ctx->jpgframe); + av_packet_free(&ctx->jpkt); av_freep(&ctx->deflatebuffer); av_freep(&ctx->tilebuffer); av_freep(&ctx->cursor); @@ -111,7 +113,8 @@ /* Allocate reference and JPEG frame */ ctx->refframe = av_frame_alloc(); ctx->jpgframe = av_frame_alloc(); - if (!ctx->refframe || !ctx->jpgframe) + ctx->jpkt = av_packet_alloc(); + if (!ctx->refframe || !ctx->jpgframe || !ctx->jpkt) return AVERROR(ENOMEM); /* Prepare everything needed for JPEG decoding */ @@ -125,7 +128,7 @@ ctx->jpeg_avctx->flags2 = avctx->flags2; ctx->jpeg_avctx->dct_algo = avctx->dct_algo; ctx->jpeg_avctx->idct_algo = avctx->idct_algo; - ret = ff_codec_open2_recursive(ctx->jpeg_avctx, codec, NULL); + ret = avcodec_open2(ctx->jpeg_avctx, codec, NULL); if (ret < 0) return ret; @@ -187,7 +190,7 @@ static int tdsc_load_cursor(AVCodecContext *avctx) { TDSCContext *ctx = avctx->priv_data; - int i, j, k, ret, bits, cursor_fmt; + int i, j, k, ret, cursor_fmt; uint8_t *dst; ctx->cursor_hot_x = bytestream2_get_le16(&ctx->gbc); @@ -231,7 +234,7 @@ case CUR_FMT_MONO: for (j = 0; j < ctx->cursor_h; j++) { for (i = 0; i < ctx->cursor_w; i += 32) { - bits = bytestream2_get_be32(&ctx->gbc); + uint32_t bits = bytestream2_get_be32(&ctx->gbc); for (k = 0; k < 32; k++) { dst[0] = !!(bits & 0x80000000); dst += 4; @@ -244,7 +247,7 @@ dst = ctx->cursor; for (j = 0; j < ctx->cursor_h; j++) { for (i = 0; i < ctx->cursor_w; i += 32) { - bits = bytestream2_get_be32(&ctx->gbc); + uint32_t bits = bytestream2_get_be32(&ctx->gbc); for (k = 0; k < 32; k++) { int mask_bit = !!(bits & 0x80000000); switch (dst[0] * 2 + mask_bit) { @@ -342,15 +345,14 @@ int x, int y, int w, int h) { TDSCContext *ctx = avctx->priv_data; - AVPacket jpkt; int ret; /* Prepare a packet and send to the MJPEG decoder */ - av_init_packet(&jpkt); - jpkt.data = ctx->tilebuffer; - jpkt.size = tile_size; + av_packet_unref(ctx->jpkt); + ctx->jpkt->data = ctx->tilebuffer; + ctx->jpkt->size = tile_size; - ret = avcodec_send_packet(ctx->jpeg_avctx, &jpkt); + ret = avcodec_send_packet(ctx->jpeg_avctx, ctx->jpkt); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); return ret; @@ -390,7 +392,7 @@ for (i = 0; i < number_tiles; i++) { int tile_size; int tile_mode; - int x, y, w, h; + int x, y, x2, y2, w, h; int ret; if (bytestream2_get_bytes_left(&ctx->gbc) < 4 || @@ -408,20 +410,19 @@ bytestream2_skip(&ctx->gbc, 4); // unknown x = bytestream2_get_le32(&ctx->gbc); y = bytestream2_get_le32(&ctx->gbc); - w = bytestream2_get_le32(&ctx->gbc) - x; - h = bytestream2_get_le32(&ctx->gbc) - y; + x2 = bytestream2_get_le32(&ctx->gbc); + y2 = bytestream2_get_le32(&ctx->gbc); - if (x >= ctx->width || y >= ctx->height) { + if (x < 0 || y < 0 || x2 <= x || y2 <= y || + x2 > ctx->width || y2 > ctx->height + ) { av_log(avctx, AV_LOG_ERROR, - "Invalid tile position (%d.%d outside %dx%d).\n", - x, y, ctx->width, ctx->height); - return AVERROR_INVALIDDATA; - } - if (x + w > ctx->width || y + h > ctx->height) { - av_log(avctx, AV_LOG_ERROR, - "Invalid tile size %dx%d\n", w, h); + "Invalid tile position (%d.%d %d.%d outside %dx%d).\n", + x, y, x2, y2, ctx->width, ctx->height); return AVERROR_INVALIDDATA; } + w = x2 - x; + h = y2 - y; ret = av_reallocp(&ctx->tilebuffer, tile_size); if (!ctx->tilebuffer) @@ -484,7 +485,7 @@ /* Allocate the reference frame if not already done or on size change */ if (init_refframe) { - ret = av_frame_get_buffer(ctx->refframe, 32); + ret = av_frame_get_buffer(ctx->refframe, 0); if (ret < 0) return ret; } @@ -530,10 +531,15 @@ /* Resize deflate buffer on resolution change */ if (ctx->width != avctx->width || ctx->height != avctx->height) { - ctx->deflatelen = avctx->width * avctx->height * (3 + 1); - ret = av_reallocp(&ctx->deflatebuffer, ctx->deflatelen); - if (ret < 0) - return ret; + int deflatelen = avctx->width * avctx->height * (3 + 1); + if (deflatelen != ctx->deflatelen) { + ctx->deflatelen =deflatelen; + ret = av_reallocp(&ctx->deflatebuffer, ctx->deflatelen); + if (ret < 0) { + ctx->deflatelen = 0; + return ret; + } + } } dlen = ctx->deflatelen; diff -Nru ffmpeg-4.2.2/libavcodec/tests/avpacket.c ffmpeg-4.4/libavcodec/tests/avpacket.c --- ffmpeg-4.2.2/libavcodec/tests/avpacket.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tests/avpacket.c 2021-04-08 21:28:39.000000000 +0000 @@ -63,9 +63,6 @@ const static uint8_t* data = "selftest for av_packet_clone(...)"; int ret = 0; - /* initialize avpkt */ - av_init_packet(avpkt); - /* set values for avpkt */ avpkt->pts = 17; avpkt->dts = 2; @@ -82,16 +79,24 @@ int main(void) { - AVPacket avpkt; + AVPacket *avpkt = NULL; AVPacket *avpkt_clone = NULL; int ret = 0; - if(initializations(&avpkt) < 0){ + /* test av_packet_alloc */ + avpkt = av_packet_alloc(); + if(!avpkt) { + av_log(NULL, AV_LOG_ERROR, "av_packet_alloc failed to allcoate AVPacket\n"); + return 1; + } + + if (initializations(avpkt) < 0) { printf("failed to initialize variables\n"); + av_packet_free(&avpkt); return 1; } /* test av_packet_clone*/ - avpkt_clone = av_packet_clone(&avpkt); + avpkt_clone = av_packet_clone(avpkt); if(!avpkt_clone) { av_log(NULL, AV_LOG_ERROR,"av_packet_clone failed to clone AVPacket\n"); @@ -121,7 +126,7 @@ } /*clean up*/ av_packet_free(&avpkt_clone); - av_packet_unref(&avpkt); + av_packet_free(&avpkt); return ret; diff -Nru ffmpeg-4.2.2/libavcodec/tests/cabac.c ffmpeg-4.4/libavcodec/tests/cabac.c --- ffmpeg-4.2.2/libavcodec/tests/cabac.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tests/cabac.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,41 +24,51 @@ #include "libavutil/lfg.h" #include "libavcodec/avcodec.h" +#include "libavcodec/put_bits.h" -static inline void put_cabac_bit(CABACContext *c, int b){ +typedef struct CABACTestContext { + CABACContext dec; + int outstanding_count; + PutBitContext pb; +} CABACTestContext; + +static inline void put_cabac_bit(CABACTestContext *c, int b) +{ put_bits(&c->pb, 1, b); for(;c->outstanding_count; c->outstanding_count--){ put_bits(&c->pb, 1, 1-b); } } -static inline void renorm_cabac_encoder(CABACContext *c){ - while(c->range < 0x100){ +static inline void renorm_cabac_encoder(CABACTestContext *c) +{ + while (c->dec.range < 0x100) { //FIXME optimize - if(c->low<0x100){ + if (c->dec.low < 0x100) { put_cabac_bit(c, 0); - }else if(c->low<0x200){ + } else if (c->dec.low < 0x200) { c->outstanding_count++; - c->low -= 0x100; + c->dec.low -= 0x100; }else{ put_cabac_bit(c, 1); - c->low -= 0x200; + c->dec.low -= 0x200; } - c->range+= c->range; - c->low += c->low; + c->dec.range += c->dec.range; + c->dec.low += c->dec.low; } } -static void put_cabac(CABACContext *c, uint8_t * const state, int bit){ - int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + *state]; +static void put_cabac(CABACTestContext *c, uint8_t * const state, int bit) +{ + int RangeLPS = ff_h264_lps_range[2 * (c->dec.range & 0xC0) + *state]; if(bit == ((*state)&1)){ - c->range -= RangeLPS; + c->dec.range -= RangeLPS; *state = ff_h264_mlps_state[128 + *state]; }else{ - c->low += c->range - RangeLPS; - c->range = RangeLPS; + c->dec.low += c->dec.range - RangeLPS; + c->dec.range = RangeLPS; *state= ff_h264_mlps_state[127 - *state]; } @@ -68,21 +78,22 @@ /** * @param bit 0 -> write zero bit, !=0 write one bit */ -static void put_cabac_bypass(CABACContext *c, int bit){ - c->low += c->low; +static void put_cabac_bypass(CABACTestContext *c, int bit) +{ + c->dec.low += c->dec.low; if(bit){ - c->low += c->range; + c->dec.low += c->dec.range; } //FIXME optimize - if(c->low<0x200){ + if (c->dec.low < 0x200) { put_cabac_bit(c, 0); - }else if(c->low<0x400){ + } else if (c->dec.low < 0x400) { c->outstanding_count++; - c->low -= 0x200; + c->dec.low -= 0x200; }else{ put_cabac_bit(c, 1); - c->low -= 0x400; + c->dec.low -= 0x400; } } @@ -90,20 +101,21 @@ * * @return the number of bytes written */ -static int put_cabac_terminate(CABACContext *c, int bit){ - c->range -= 2; +static int put_cabac_terminate(CABACTestContext *c, int bit) +{ + c->dec.range -= 2; if(!bit){ renorm_cabac_encoder(c); }else{ - c->low += c->range; - c->range= 2; + c->dec.low += c->dec.range; + c->dec.range = 2; renorm_cabac_encoder(c); - av_assert0(c->low <= 0x1FF); - put_cabac_bit(c, c->low>>9); - put_bits(&c->pb, 2, ((c->low>>7)&3)|1); + av_assert0(c->dec.low <= 0x1FF); + put_cabac_bit(c, c->dec.low >> 9); + put_bits(&c->pb, 2, ((c->dec.low >> 7) & 3) | 1); flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong } @@ -111,8 +123,21 @@ return (put_bits_count(&c->pb)+7)>>3; } +/** + * @param buf_size size of buf in bits + */ +static void init_cabac_encoder(CABACTestContext *c, uint8_t *buf, int buf_size) +{ + init_put_bits(&c->pb, buf, buf_size); + + c->dec.low = 0; + c->dec.range = 0x1FE; + c->outstanding_count = 0; + c->pb.bit_left++; //avoids firstBitFlag +} + int main(void){ - CABACContext c; + CABACTestContext c; uint8_t b[9*SIZE]; uint8_t r[9*SIZE]; int i, ret = 0; @@ -120,7 +145,7 @@ AVLFG prng; av_lfg_init(&prng, 1); - ff_init_cabac_encoder(&c, b, SIZE); + init_cabac_encoder(&c, b, SIZE); for(i=0; i - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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/options.c" - -static int dummy_init(AVCodecContext *ctx) -{ - //TODO: this code should set every possible pointer that could be set by codec and is not an option; - ctx->extradata_size = 8; - ctx->extradata = av_malloc(ctx->extradata_size); - return 0; -} - -static int dummy_close(AVCodecContext *ctx) -{ - av_freep(&ctx->extradata); - ctx->extradata_size = 0; - return 0; -} - -static int dummy_encode(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) -{ - return AVERROR(ENOSYS); -} - -typedef struct Dummy12Context { - AVClass *av_class; - int num; - char* str; -} Dummy12Context; - -typedef struct Dummy3Context { - void *fake_av_class; - int num; - char* str; -} Dummy3Context; - -#define OFFSET(x) offsetof(Dummy12Context, x) -#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM -static const AVOption dummy_options[] = { - { "str", "set str", OFFSET(str), AV_OPT_TYPE_STRING, { .str = "i'm src default value" }, 0, 0, VE}, - { "num", "set num", OFFSET(num), AV_OPT_TYPE_INT, { .i64 = 1500100900 }, 0, INT_MAX, VE}, - { NULL }, -}; - -static const AVClass dummy_v1_class = { - .class_name = "dummy_v1_class", - .item_name = av_default_item_name, - .option = dummy_options, - .version = LIBAVUTIL_VERSION_INT, -}; - -static const AVClass dummy_v2_class = { - .class_name = "dummy_v2_class", - .item_name = av_default_item_name, - .option = dummy_options, - .version = LIBAVUTIL_VERSION_INT, -}; - -/* codec with options */ -static AVCodec dummy_v1_encoder = { - .name = "dummy_v1_codec", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_NONE - 1, - .encode2 = dummy_encode, - .init = dummy_init, - .close = dummy_close, - .priv_class = &dummy_v1_class, - .priv_data_size = sizeof(Dummy12Context), -}; - -/* codec with options, different class */ -static AVCodec dummy_v2_encoder = { - .name = "dummy_v2_codec", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_NONE - 2, - .encode2 = dummy_encode, - .init = dummy_init, - .close = dummy_close, - .priv_class = &dummy_v2_class, - .priv_data_size = sizeof(Dummy12Context), -}; - -/* codec with priv data, but no class */ -static AVCodec dummy_v3_encoder = { - .name = "dummy_v3_codec", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_NONE - 3, - .encode2 = dummy_encode, - .init = dummy_init, - .close = dummy_close, - .priv_data_size = sizeof(Dummy3Context), -}; - -/* codec without priv data */ -static AVCodec dummy_v4_encoder = { - .name = "dummy_v4_codec", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_NONE - 4, - .encode2 = dummy_encode, - .init = dummy_init, - .close = dummy_close, -}; - -static void test_copy_print_codec(const AVCodecContext *ctx) -{ - printf("%-14s: %dx%d prv: %s", - ctx->codec ? ctx->codec->name : "NULL", - ctx->width, ctx->height, - ctx->priv_data ? "set" : "null"); - if (ctx->codec && ctx->codec->priv_class && ctx->codec->priv_data_size) { - int64_t i64; - char *str = NULL; - av_opt_get_int(ctx->priv_data, "num", 0, &i64); - av_opt_get(ctx->priv_data, "str", 0, (uint8_t**)&str); - printf(" opts: %"PRId64" %s", i64, str); - av_free(str); - } - printf("\n"); -} - -static void test_copy(const AVCodec *c1, const AVCodec *c2) -{ - AVCodecContext *ctx1, *ctx2; - printf("%s -> %s\nclosed:\n", c1 ? c1->name : "NULL", c2 ? c2->name : "NULL"); - ctx1 = avcodec_alloc_context3(c1); - ctx2 = avcodec_alloc_context3(c2); - ctx1->width = ctx1->height = 128; - ctx1->time_base = (AVRational){12,34}; - if (ctx2->codec && ctx2->codec->priv_class && ctx2->codec->priv_data_size) { - av_opt_set(ctx2->priv_data, "num", "667", 0); - av_opt_set(ctx2->priv_data, "str", "i'm dest value before copy", 0); - } - avcodec_copy_context(ctx2, ctx1); - test_copy_print_codec(ctx1); - test_copy_print_codec(ctx2); - if (ctx1->codec) { - int ret; - printf("opened:\n"); - ret = avcodec_open2(ctx1, ctx1->codec, NULL); - if (ret < 0) { - fprintf(stderr, "avcodec_open2 failed\n"); - exit(1); - } - if (ctx2->codec && ctx2->codec->priv_class && ctx2->codec->priv_data_size) { - av_opt_set(ctx2->priv_data, "num", "667", 0); - av_opt_set(ctx2->priv_data, "str", "i'm dest value before copy", 0); - } - avcodec_copy_context(ctx2, ctx1); - test_copy_print_codec(ctx1); - test_copy_print_codec(ctx2); - avcodec_close(ctx1); - } - avcodec_free_context(&ctx1); - avcodec_free_context(&ctx2); -} - -int main(void) -{ - AVCodec *dummy_codec[] = { - &dummy_v1_encoder, - &dummy_v2_encoder, - &dummy_v3_encoder, - &dummy_v4_encoder, - NULL, - }; - int i, j; - - for (i = 0; dummy_codec[i]; i++) - avcodec_register(dummy_codec[i]); - - printf("testing avcodec_copy_context()\n"); - for (i = 0; i < FF_ARRAY_ELEMS(dummy_codec); i++) - for (j = 0; j < FF_ARRAY_ELEMS(dummy_codec); j++) - test_copy(dummy_codec[i], dummy_codec[j]); - return 0; -} diff -Nru ffmpeg-4.2.2/libavcodec/tests/rangecoder.c ffmpeg-4.4/libavcodec/tests/rangecoder.c --- ffmpeg-4.2.2/libavcodec/tests/rangecoder.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tests/rangecoder.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,32 @@ #define SIZE 1240 +/** + * Check if at the current position there is a valid looking termination + * @param version version 0 requires the decoder to know the data size in bytes + * version 1 needs about 1 bit more space but does not need to + * carry the size from encoder to decoder + * @returns negative AVERROR code on error or non negative. + */ +static int rac_check_termination(RangeCoder *c, int version) +{ + if (version == 1) { + RangeCoder tmp = *c; + get_rac(c, (uint8_t[]) { 129 }); + + if (c->bytestream == tmp.bytestream && c->bytestream > c->bytestream_start) + tmp.low -= *--tmp.bytestream; + tmp.bytestream_end = tmp.bytestream; + + if (get_rac(&tmp, (uint8_t[]) { 129 })) + return AVERROR_INVALIDDATA; + } else { + if (c->bytestream_end != c->bytestream) + return AVERROR_INVALIDDATA; + } + return 0; +} + int main(void) { RangeCoder c; @@ -61,7 +87,7 @@ return 1; } - if (ff_rac_check_termination(&c, version) < 0) { + if (rac_check_termination(&c, version) < 0) { av_log(NULL, AV_LOG_ERROR, "rac failure at termination pass %d version %d\n", p, version); return 1; } diff -Nru ffmpeg-4.2.2/libavcodec/tests/utils.c ffmpeg-4.4/libavcodec/tests/utils.c --- ffmpeg-4.2.2/libavcodec/tests/utils.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tests/utils.c 2020-07-11 10:39:30.000000000 +0000 @@ -19,10 +19,11 @@ #include "libavcodec/avcodec.h" int main(void){ - AVCodec *codec = NULL; + void *iter = NULL; + const AVCodec *codec = NULL; int ret = 0; - while (codec = av_codec_next(codec)) { + while (codec = av_codec_iterate(&iter)) { if (av_codec_is_encoder(codec)) { if (codec->type == AVMEDIA_TYPE_AUDIO) { if (!codec->sample_fmts) { diff -Nru ffmpeg-4.2.2/libavcodec/tests/x86/dct.c ffmpeg-4.4/libavcodec/tests/x86/dct.c --- ffmpeg-4.2.2/libavcodec/tests/x86/dct.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tests/x86/dct.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,6 +18,8 @@ #include "config.h" +#include "libavutil/mem_internal.h" + #include "libavcodec/x86/fdct.h" #include "libavcodec/x86/xvididct.h" #include "libavcodec/x86/simple_idct.h" diff -Nru ffmpeg-4.2.2/libavcodec/thread.h ffmpeg-4.4/libavcodec/thread.h --- ffmpeg-4.2.2/libavcodec/thread.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/thread.h 2021-04-08 21:28:39.000000000 +0000 @@ -96,6 +96,7 @@ */ void ff_thread_await_progress(ThreadFrame *f, int progress, int field); +#if FF_API_THREAD_SAFE_CALLBACKS /** * Wrapper around get_format() for frame-multithreaded codecs. * Call this function instead of avctx->get_format(). @@ -105,6 +106,9 @@ * @param fmt The list of available formats. */ enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt); +#else +#define ff_thread_get_format ff_get_format +#endif /** * Wrapper around get_buffer() for frame-multithreaded codecs. @@ -129,7 +133,7 @@ */ void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f); -int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src); +int ff_thread_ref_frame(ThreadFrame *dst, const ThreadFrame *src); int ff_thread_init(AVCodecContext *s); int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx, diff -Nru ffmpeg-4.2.2/libavcodec/tiertexseqv.c ffmpeg-4.4/libavcodec/tiertexseqv.c --- ffmpeg-4.2.2/libavcodec/tiertexseqv.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tiertexseqv.c 2020-07-11 10:39:30.000000000 +0000 @@ -239,7 +239,7 @@ SeqVideoContext *seq = avctx->priv_data; - if ((ret = ff_reget_buffer(avctx, seq->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, seq->frame, 0)) < 0) return ret; if (seqvideo_decode(seq, buf, buf_size)) diff -Nru ffmpeg-4.2.2/libavcodec/tiff.c ffmpeg-4.4/libavcodec/tiff.c --- ffmpeg-4.2.2/libavcodec/tiff.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tiff.c 2021-04-08 21:28:39.000000000 +0000 @@ -35,6 +35,7 @@ #include "libavutil/attributes.h" #include "libavutil/avstring.h" +#include "libavutil/error.h" #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" @@ -46,6 +47,7 @@ #include "mathops.h" #include "tiff.h" #include "tiff_data.h" +#include "mjpegdec.h" #include "thread.h" #include "get_bits.h" @@ -54,6 +56,11 @@ AVCodecContext *avctx; GetByteContext gb; + /* JPEG decoding for DNG */ + AVCodecContext *avctx_mjpeg; // wrapper context for MJPEG + AVPacket *jpkt; // encoded JPEG tile + AVFrame *jpgframe; // decoded JPEG tile + int get_subimage; uint16_t get_page; int get_thumbnail; @@ -73,10 +80,13 @@ int fill_order; uint32_t res[4]; int is_thumbnail; + unsigned last_tag; int is_bayer; uint8_t pattern[4]; + unsigned black_level; unsigned white_level; + uint16_t dng_lut[65536]; uint32_t sub_ifd; uint16_t cur_page; @@ -86,6 +96,14 @@ int stripsizesoff, stripsize, stripoff, strippos; LZWState *lzw; + /* Tile support */ + int is_tiled; + int tile_byte_counts_offset, tile_offsets_offset; + int tile_width, tile_length; + int tile_count; + + int is_jpeg; + uint8_t *deinvert_buf; int deinvert_buf_size; uint8_t *yuv_line; @@ -115,8 +133,8 @@ #define RET_GEOKEY(TYPE, array, element)\ if (key >= TIFF_##TYPE##_KEY_ID_OFFSET &&\ - key - TIFF_##TYPE##_KEY_ID_OFFSET < FF_ARRAY_ELEMS(ff_tiff_##array##_name_type_map))\ - return ff_tiff_##array##_name_type_map[key - TIFF_##TYPE##_KEY_ID_OFFSET].element; + key - TIFF_##TYPE##_KEY_ID_OFFSET < FF_ARRAY_ELEMS(tiff_##array##_name_type_map))\ + return tiff_##array##_name_type_map[key - TIFF_##TYPE##_KEY_ID_OFFSET].element; static const char *get_geokey_name(int key) { @@ -163,8 +181,8 @@ #define RET_GEOKEY_VAL(TYPE, array)\ if (val >= TIFF_##TYPE##_OFFSET &&\ - val - TIFF_##TYPE##_OFFSET < FF_ARRAY_ELEMS(ff_tiff_##array##_codes))\ - return av_strdup(ff_tiff_##array##_codes[val - TIFF_##TYPE##_OFFSET]); + val - TIFF_##TYPE##_OFFSET < FF_ARRAY_ELEMS(tiff_##array##_codes))\ + return av_strdup(tiff_##array##_codes[val - TIFF_##TYPE##_OFFSET]); switch (key) { case TIFF_GT_MODEL_TYPE_GEOKEY: @@ -197,11 +215,11 @@ RET_GEOKEY_VAL(PRIME_MERIDIAN, prime_meridian); break; case TIFF_PROJECTED_CS_TYPE_GEOKEY: - ap = av_strdup(search_keyval(ff_tiff_proj_cs_type_codes, FF_ARRAY_ELEMS(ff_tiff_proj_cs_type_codes), val)); + ap = av_strdup(search_keyval(tiff_proj_cs_type_codes, FF_ARRAY_ELEMS(tiff_proj_cs_type_codes), val)); if(ap) return ap; break; case TIFF_PROJECTION_GEOKEY: - ap = av_strdup(search_keyval(ff_tiff_projection_codes, FF_ARRAY_ELEMS(ff_tiff_projection_codes), val)); + ap = av_strdup(search_keyval(tiff_projection_codes, FF_ARRAY_ELEMS(tiff_projection_codes), val)); if(ap) return ap; break; case TIFF_PROJ_COORD_TRANS_GEOKEY: @@ -257,6 +275,102 @@ }; } +/** + * Map stored raw sensor values into linear reference values (see: DNG Specification - Chapter 5) + */ +static uint16_t av_always_inline dng_process_color16(uint16_t value, + const uint16_t *lut, + uint16_t black_level, + float scale_factor) +{ + float value_norm; + + // Lookup table lookup + if (lut) + value = lut[value]; + + // Black level subtraction + value = av_clip_uint16_c((unsigned)value - black_level); + + // Color scaling + value_norm = (float)value * scale_factor; + + value = av_clip_uint16_c(value_norm * 65535); + + return value; +} + +static uint16_t av_always_inline dng_process_color8(uint16_t value, + const uint16_t *lut, + uint16_t black_level, + float scale_factor) +{ + return dng_process_color16(value, lut, black_level, scale_factor) >> 8; +} + +static void av_always_inline dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, + const uint8_t *src, int src_stride, int width, int height, + int is_single_comp, int is_u16) +{ + int line, col; + float scale_factor; + + scale_factor = 1.0f / (s->white_level - s->black_level); + + if (is_single_comp) { + if (!is_u16) + return; /* <= 8bpp unsupported */ + + /* Image is double the width and half the height we need, each row comprises 2 rows of the output + (split vertically in the middle). */ + for (line = 0; line < height / 2; line++) { + uint16_t *dst_u16 = (uint16_t *)dst; + uint16_t *src_u16 = (uint16_t *)src; + + /* Blit first half of input row row to initial row of output */ + for (col = 0; col < width; col++) + *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor); + + /* Advance the destination pointer by a row (source pointer remains in the same place) */ + dst += dst_stride * sizeof(uint16_t); + dst_u16 = (uint16_t *)dst; + + /* Blit second half of input row row to next row of output */ + for (col = 0; col < width; col++) + *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor); + + dst += dst_stride * sizeof(uint16_t); + src += src_stride * sizeof(uint16_t); + } + } else { + /* Input and output image are the same size and the MJpeg decoder has done per-component + deinterleaving, so blitting here is straightforward. */ + if (is_u16) { + for (line = 0; line < height; line++) { + uint16_t *dst_u16 = (uint16_t *)dst; + uint16_t *src_u16 = (uint16_t *)src; + + for (col = 0; col < width; col++) + *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor); + + dst += dst_stride * sizeof(uint16_t); + src += src_stride * sizeof(uint16_t); + } + } else { + for (line = 0; line < height; line++) { + uint8_t *dst_u8 = dst; + const uint8_t *src_u8 = src; + + for (col = 0; col < width; col++) + *dst_u8++ = dng_process_color8(*src_u8++, s->dng_lut, s->black_level, scale_factor); + + dst += dst_stride; + src += src_stride; + } + } + } +} + static void av_always_inline horizontal_fill(TiffContext *s, unsigned int bpp, uint8_t* dst, int usePtr, const uint8_t *src, @@ -289,14 +403,19 @@ dst[(width+offset)*2+0] = (usePtr ? src[width] : c) >> 4; } break; - case 12: { - uint16_t *dst16 = (uint16_t *)dst; - GetBitContext gb; - init_get_bits8(&gb, src, width); - for (int i = 0; i < s->width; i++) { - dst16[i] = get_bits(&gb, 12) << 4; - } - } + case 10: + case 12: + case 14: { + uint16_t *dst16 = (uint16_t *)dst; + int is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + uint8_t shift = is_dng ? 0 : 16 - bpp; + GetBitContext gb; + + init_get_bits8(&gb, src, width); + for (int i = 0; i < s->width; i++) { + dst16[i] = get_bits(&gb, bpp) << shift; + } + } break; default: if (usePtr) { @@ -368,7 +487,7 @@ z_stream zstream = { 0 }; int zret; - zstream.next_in = (uint8_t *)src; + zstream.next_in = src; zstream.avail_in = size; zstream.next_out = dst; zstream.avail_out = *len; @@ -526,6 +645,109 @@ return ret; } +static int dng_decode_jpeg(AVCodecContext *avctx, AVFrame *frame, + int tile_byte_count, int dst_x, int dst_y, int w, int h) +{ + TiffContext *s = avctx->priv_data; + uint8_t *dst_data, *src_data; + uint32_t dst_offset; /* offset from dst buffer in pixels */ + int is_single_comp, is_u16, pixel_size; + int ret; + + if (tile_byte_count < 0 || tile_byte_count > bytestream2_get_bytes_left(&s->gb)) + return AVERROR_INVALIDDATA; + + /* Prepare a packet and send to the MJPEG decoder */ + av_packet_unref(s->jpkt); + s->jpkt->data = (uint8_t*)s->gb.buffer; + s->jpkt->size = tile_byte_count; + + if (s->is_bayer) { + MJpegDecodeContext *mjpegdecctx = s->avctx_mjpeg->priv_data; + /* We have to set this information here, there is no way to know if a given JPEG is a DNG-embedded + image or not from its own data (and we need that information when decoding it). */ + mjpegdecctx->bayer = 1; + } + + ret = avcodec_send_packet(s->avctx_mjpeg, s->jpkt); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); + return ret; + } + + ret = avcodec_receive_frame(s->avctx_mjpeg, s->jpgframe); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "JPEG decoding error: %s.\n", av_err2str(ret)); + + /* Normally skip, error if explode */ + if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + else + return 0; + } + + is_u16 = (s->bpp > 8); + + /* Copy the outputted tile's pixels from 'jpgframe' to 'frame' (final buffer) */ + + if (s->jpgframe->width != s->avctx_mjpeg->width || + s->jpgframe->height != s->avctx_mjpeg->height || + s->jpgframe->format != s->avctx_mjpeg->pix_fmt) + return AVERROR_INVALIDDATA; + + /* See dng_blit for explanation */ + if (s->avctx_mjpeg->width == w * 2 && + s->avctx_mjpeg->height == h / 2 && + s->avctx_mjpeg->pix_fmt == AV_PIX_FMT_GRAY16LE) { + is_single_comp = 1; + } else if (s->avctx_mjpeg->width >= w && + s->avctx_mjpeg->height >= h && + s->avctx_mjpeg->pix_fmt == (is_u16 ? AV_PIX_FMT_GRAY16 : AV_PIX_FMT_GRAY8) + ) { + is_single_comp = 0; + } else + return AVERROR_INVALIDDATA; + + pixel_size = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t)); + + if (is_single_comp && !is_u16) { + av_log(s->avctx, AV_LOG_ERROR, "DNGs with bpp <= 8 and 1 component are unsupported\n"); + av_frame_unref(s->jpgframe); + return AVERROR_PATCHWELCOME; + } + + dst_offset = dst_x + frame->linesize[0] * dst_y / pixel_size; + dst_data = frame->data[0] + dst_offset * pixel_size; + src_data = s->jpgframe->data[0]; + + dng_blit(s, + dst_data, + frame->linesize[0] / pixel_size, + src_data, + s->jpgframe->linesize[0] / pixel_size, + w, + h, + is_single_comp, + is_u16); + + av_frame_unref(s->jpgframe); + + 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) { @@ -537,6 +759,7 @@ int is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) && (desc->flags & AV_PIX_FMT_FLAG_PLANAR) && desc->nb_components >= 3; + int is_dng; if (s->planar) width /= s->bppcount; @@ -561,7 +784,7 @@ av_assert0(s->bpp == 24); } if (s->is_bayer) { - width = (s->bpp * s->width + 7) >> 3; + av_assert0(width == (s->bpp * s->width + 7) >> 3); } if (p->format == AV_PIX_FMT_GRAY12) { av_fast_padded_malloc(&s->yuv_line, &s->yuv_line_size, width); @@ -638,6 +861,22 @@ bytestream2_init(&s->gb, src, size); bytestream2_init_writer(&pb, dst, is_yuv ? s->yuv_line_size : (stride * lines)); + is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + + /* Decode JPEG-encoded DNGs with strips */ + if (s->compr == TIFF_NEWJPEG && is_dng) { + if (s->strips > 1) { + 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) + return ret; + return 0; + } + + if (is_dng && stride == 0) + return AVERROR_INVALIDDATA; + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -660,6 +899,28 @@ for (i = 0; i < width; i++) dst[i] = ff_reverse[src[i]]; } + + /* Color processing for DNG images with uncompressed strips (non-tiled) */ + if (is_dng) { + int is_u16, pixel_size_bytes, pixel_size_bits, elements; + + is_u16 = (s->bpp / s->bppcount > 8); + pixel_size_bits = (is_u16 ? 16 : 8); + pixel_size_bytes = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t)); + + elements = width / pixel_size_bytes * pixel_size_bits / s->bpp * s->bppcount; // need to account for [1, 16] bpp + av_assert0 (elements * pixel_size_bytes <= FFABS(stride)); + dng_blit(s, + dst, + 0, // no stride, only 1 line + dst, + 0, // no stride, only 1 line + elements, + 1, + 0, // single-component variation is only preset in JPEG-encoded DNGs + is_u16); + } + src += width; break; case TIFF_PACKBITS: @@ -712,6 +973,82 @@ return 0; } +static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, + const AVPacket *avpkt) +{ + TiffContext *s = avctx->priv_data; + int tile_idx; + int tile_offset_offset, tile_offset; + int tile_byte_count_offset, tile_byte_count; + int tile_count_x, tile_count_y; + int tile_width, tile_length; + int has_width_leftover, has_height_leftover; + int tile_x = 0, tile_y = 0; + 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); + + /* Calculate tile counts (round up) */ + tile_count_x = (s->width + s->tile_width - 1) / s->tile_width; + tile_count_y = (s->height + s->tile_length - 1) / s->tile_length; + + /* Iterate over the number of tiles */ + for (tile_idx = 0; tile_idx < s->tile_count; tile_idx++) { + tile_x = tile_idx % tile_count_x; + tile_y = tile_idx / tile_count_x; + + if (has_width_leftover && tile_x == tile_count_x - 1) // If on the right-most tile + tile_width = s->width % s->tile_width; + else + tile_width = s->tile_width; + + if (has_height_leftover && tile_y == tile_count_y - 1) // If on the bottom-most tile + tile_length = s->height % s->tile_length; + else + tile_length = s->tile_length; + + /* Read tile offset */ + tile_offset_offset = s->tile_offsets_offset + tile_idx * sizeof(int); + bytestream2_seek(&s->gb, tile_offset_offset, SEEK_SET); + tile_offset = ff_tget_long(&s->gb, s->le); + + /* Read tile byte size */ + tile_byte_count_offset = s->tile_byte_counts_offset + tile_idx * sizeof(int); + bytestream2_seek(&s->gb, tile_byte_count_offset, SEEK_SET); + tile_byte_count = ff_tget_long(&s->gb, s->le); + + /* Seek to tile data */ + bytestream2_seek(&s->gb, tile_offset, SEEK_SET); + + /* Decode JPEG tile and copy it in the reference frame */ + ret = dng_decode_jpeg(avctx, frame, tile_byte_count, pos_x, pos_y, tile_width, tile_length); + + if (ret < 0) + return ret; + + /* Advance current positions */ + pos_x += tile_width; + if (tile_x == tile_count_x - 1) { // If on the right edge + pos_x = 0; + pos_y += tile_length; + } + } + + /* Frame is ready to be output */ + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + + return avpkt->size; +} + static int init_image(TiffContext *s, ThreadFrame *frame) { int ret; @@ -764,39 +1101,22 @@ return AVERROR_PATCHWELCOME; } break; + case 10101: case 10121: - switch (AV_RL32(s->pattern)) { - case 0x02010100: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_RGGB16LE : AV_PIX_FMT_BAYER_RGGB16BE; - break; - case 0x00010102: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_BGGR16LE : AV_PIX_FMT_BAYER_BGGR16BE; - break; - case 0x01000201: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_GBRG16LE : AV_PIX_FMT_BAYER_GBRG16BE; - break; - case 0x01020001: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_GRBG16LE : AV_PIX_FMT_BAYER_GRBG16BE; - break; - default: - av_log(s->avctx, AV_LOG_ERROR, "Unsupported Bayer pattern: 0x%X\n", - AV_RL32(s->pattern)); - return AVERROR_PATCHWELCOME; - } - break; + case 10141: case 10161: switch (AV_RL32(s->pattern)) { case 0x02010100: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_RGGB16LE : AV_PIX_FMT_BAYER_RGGB16BE; + s->avctx->pix_fmt = AV_PIX_FMT_BAYER_RGGB16; break; case 0x00010102: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_BGGR16LE : AV_PIX_FMT_BAYER_BGGR16BE; + s->avctx->pix_fmt = AV_PIX_FMT_BAYER_BGGR16; break; case 0x01000201: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_GBRG16LE : AV_PIX_FMT_BAYER_GBRG16BE; + s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GBRG16; break; case 0x01020001: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_GRBG16LE : AV_PIX_FMT_BAYER_GRBG16BE; + s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GRBG16; break; default: av_log(s->avctx, AV_LOG_ERROR, "Unsupported Bayer pattern: 0x%X\n", @@ -923,7 +1243,9 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) { - unsigned tag, type, count, off, value = 0, value2 = 0; + AVFrameSideData *sd; + GetByteContext gb_temp; + unsigned tag, type, count, off, value = 0, value2 = 1; // value2 is a denominator so init. to 1 int i, start; int pos; int ret; @@ -933,6 +1255,12 @@ if (ret < 0) { goto end; } + if (tag <= s->last_tag) + return AVERROR_INVALIDDATA; + + // We ignore TIFF_STRIP_SIZE as it is sometimes in the logic but wrong order around TIFF_STRIP_OFFS + if (tag != TIFF_STRIP_SIZE) + s->last_tag = tag; off = bytestream2_tell(&s->gb); if (count == 1) { @@ -945,6 +1273,11 @@ case TIFF_RATIONAL: value = ff_tget(&s->gb, TIFF_LONG, s->le); value2 = ff_tget(&s->gb, TIFF_LONG, s->le); + if (!value2) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid denominator in rational\n"); + return AVERROR_INVALIDDATA; + } + break; case TIFF_STRING: if (count <= 4) { @@ -958,6 +1291,7 @@ switch (tag) { case TIFF_SUBFILE: s->is_thumbnail = (value != 0); + break; case TIFF_WIDTH: s->width = value; break; @@ -965,7 +1299,7 @@ s->height = value; break; case TIFF_BPP: - if (count > 5U) { + if (count > 5 || count <= 0) { av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%d, %d components)\n", value, count); @@ -996,9 +1330,9 @@ "Samples per pixel requires a single value, many provided\n"); return AVERROR_INVALIDDATA; } - if (value > 5U) { + if (value > 5 || value <= 0) { av_log(s->avctx, AV_LOG_ERROR, - "Samples per pixel %d is too large\n", value); + "Invalid samples per pixel %d\n", value); return AVERROR_INVALIDDATA; } if (s->bppcount == 1) @@ -1029,8 +1363,8 @@ #endif case TIFF_JPEG: case TIFF_NEWJPEG: - avpriv_report_missing_feature(s->avctx, "JPEG compression"); - return AVERROR_PATCHWELCOME; + s->is_jpeg = 1; + break; case TIFF_LZMA: #if CONFIG_LZMA break; @@ -1085,12 +1419,19 @@ case TIFF_YRES: set_sar(s, tag, value, value2); break; + case TIFF_TILE_OFFSETS: + s->tile_offsets_offset = off; + s->tile_count = count; + s->is_tiled = 1; + break; case TIFF_TILE_BYTE_COUNTS: + s->tile_byte_counts_offset = off; + break; case TIFF_TILE_LENGTH: - case TIFF_TILE_OFFSETS: + s->tile_length = value; + break; case TIFF_TILE_WIDTH: - av_log(s->avctx, AV_LOG_ERROR, "Tiled images are not supported\n"); - return AVERROR_PATCHWELCOME; + s->tile_width = value; break; case TIFF_PREDICTOR: s->predictor = value; @@ -1101,6 +1442,30 @@ else if (count > 1) s->sub_ifd = ff_tget(&s->gb, TIFF_LONG, s->le); /** Only get the first SubIFD */ break; + case DNG_LINEARIZATION_TABLE: + if (count > FF_ARRAY_ELEMS(s->dng_lut)) + return AVERROR_INVALIDDATA; + for (int i = 0; i < count; i++) + s->dng_lut[i] = ff_tget(&s->gb, type, s->le); + break; + case DNG_BLACK_LEVEL: + if (count > 1) { /* Use the first value in the pattern (assume they're all the same) */ + if (type == TIFF_RATIONAL) { + value = ff_tget(&s->gb, TIFF_LONG, s->le); + value2 = ff_tget(&s->gb, TIFF_LONG, s->le); + if (!value2) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid black level denominator\n"); + return AVERROR_INVALIDDATA; + } + + s->black_level = value / value2; + } else + s->black_level = ff_tget(&s->gb, type, s->le); + av_log(s->avctx, AV_LOG_WARNING, "Assuming black level pattern values are identical\n"); + } else { + s->black_level = value / value2; + } + break; case DNG_WHITE_LEVEL: s->white_level = value; break; @@ -1127,6 +1492,7 @@ case TIFF_PHOTOMETRIC_SEPARATED: case TIFF_PHOTOMETRIC_YCBCR: case TIFF_PHOTOMETRIC_CFA: + case TIFF_PHOTOMETRIC_LINEAR_RAW: // Used by DNG images s->photometric = value; break; case TIFF_PHOTOMETRIC_ALPHA_MASK: @@ -1135,7 +1501,6 @@ case TIFF_PHOTOMETRIC_ITU_LAB: case TIFF_PHOTOMETRIC_LOG_L: case TIFF_PHOTOMETRIC_LOG_LUV: - case TIFF_PHOTOMETRIC_LINEAR_RAW: avpriv_report_missing_feature(s->avctx, "PhotometricInterpretation 0x%04X", value); @@ -1222,7 +1587,7 @@ break; case TIFF_GEO_KEY_DIRECTORY: if (s->geotag_count) { - avpriv_request_sample(s->avctx, "Multiple geo key directories\n"); + avpriv_request_sample(s->avctx, "Multiple geo key directories"); return AVERROR_INVALIDDATA; } ADD_METADATA(1, "GeoTIFF_Version", NULL); @@ -1313,6 +1678,19 @@ } } break; + case TIFF_ICC_PROFILE: + gb_temp = s->gb; + bytestream2_seek(&gb_temp, SEEK_SET, off); + + if (bytestream2_get_bytes_left(&gb_temp) < count) + return AVERROR_INVALIDDATA; + + sd = av_frame_new_side_data(frame, AV_FRAME_DATA_ICC_PROFILE, count); + if (!sd) + return AVERROR(ENOMEM); + + bytestream2_get_bufferu(&gb_temp, sd->data, count); + break; case TIFF_ARTIST: ADD_METADATA(count, "artist", NULL); break; @@ -1407,6 +1785,8 @@ GetByteContext stripsizes; GetByteContext stripdata; int retry_for_subifd, retry_for_page; + int is_dng; + int has_tile_bits, has_strip_bits; bytestream2_init(&s->gb, avpkt->data, avpkt->size); @@ -1420,6 +1800,8 @@ } s->le = le; // TIFF_BPP is not a required tag and defaults to 1 + + s->tiff_type = TIFF_TYPE_TIFF; again: s->is_thumbnail = 0; s->bppcount = s->bpp = 1; @@ -1428,8 +1810,14 @@ s->fill_order = 0; s->white_level = 0; s->is_bayer = 0; + s->is_tiled = 0; + s->is_jpeg = 0; s->cur_page = 0; - s->tiff_type = TIFF_TYPE_TIFF; + s->last_tag = 0; + + for (i = 0; i < 65536; i++) + s->dng_lut[i] = i; + free_geotags(s); // Reset these offsets so we can tell if they were set this frame @@ -1469,7 +1857,7 @@ return AVERROR_INVALIDDATA; } if (off <= last_off) { - avpriv_request_sample(s->avctx, "non increasing IFD offset\n"); + avpriv_request_sample(s->avctx, "non increasing IFD offset"); return AVERROR_INVALIDDATA; } if (off >= UINT_MAX - 14 || avpkt->size < off + 14) { @@ -1480,6 +1868,10 @@ goto again; } + /* At this point we've decided on which (Sub)IFD to process */ + + is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + for (i = 0; igeotag_count; i++) { const char *keyname = get_geokey_name(s->geotags[i].key); if (!keyname) { @@ -1497,37 +1889,97 @@ } } - if (!s->strippos && !s->stripoff) { + if (is_dng) { + int bps; + + if (s->bpp % s->bppcount) + return AVERROR_INVALIDDATA; + bps = s->bpp / s->bppcount; + if (bps < 8 || bps > 32) + return AVERROR_INVALIDDATA; + + if (s->white_level == 0) + s->white_level = (1LL << bps) - 1; /* Default value as per the spec */ + + if (s->white_level <= s->black_level) { + av_log(avctx, AV_LOG_ERROR, "BlackLevel (%"PRId32") must be less than WhiteLevel (%"PRId32")\n", + s->black_level, s->white_level); + return AVERROR_INVALIDDATA; + } + + if (s->planar) + return AVERROR_PATCHWELCOME; + } + + if (!s->is_tiled && !s->strippos && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return AVERROR_INVALIDDATA; } + + has_tile_bits = s->is_tiled || s->tile_byte_counts_offset || s->tile_offsets_offset || s->tile_width || s->tile_length || s->tile_count; + has_strip_bits = s->strippos || s->strips || s->stripoff || s->rps || s->sot || s->sstype || s->stripsize || s->stripsizesoff; + + if (has_tile_bits && has_strip_bits) { + int tiled_dng = s->is_tiled && is_dng; + av_log(avctx, tiled_dng ? AV_LOG_WARNING : AV_LOG_ERROR, "Tiled TIFF is not allowed to strip\n"); + if (!tiled_dng) + return AVERROR_INVALIDDATA; + } + /* now we have the data and may start decoding */ if ((ret = init_image(s, &frame)) < 0) return ret; - if (s->strips == 1 && !s->stripsize) { - av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); - s->stripsize = avpkt->size - s->stripoff; - } + if (!s->is_tiled || has_strip_bits) { + if (s->strips == 1 && !s->stripsize) { + av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); + s->stripsize = avpkt->size - s->stripoff; + } - if (s->stripsizesoff) { - if (s->stripsizesoff >= (unsigned)avpkt->size) + if (s->stripsizesoff) { + if (s->stripsizesoff >= (unsigned)avpkt->size) + return AVERROR_INVALIDDATA; + bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, + avpkt->size - s->stripsizesoff); + } + if (s->strippos) { + if (s->strippos >= (unsigned)avpkt->size) + return AVERROR_INVALIDDATA; + bytestream2_init(&stripdata, avpkt->data + s->strippos, + avpkt->size - s->strippos); + } + + if (s->rps <= 0 || s->rps % s->subsampling[1]) { + av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); return AVERROR_INVALIDDATA; - bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, - avpkt->size - s->stripsizesoff); + } } - if (s->strippos) { - if (s->strippos >= (unsigned)avpkt->size) - return AVERROR_INVALIDDATA; - bytestream2_init(&stripdata, avpkt->data + s->strippos, - avpkt->size - s->strippos); + + if (s->photometric == TIFF_PHOTOMETRIC_LINEAR_RAW || + s->photometric == TIFF_PHOTOMETRIC_CFA) { + p->color_trc = AVCOL_TRC_LINEAR; + } else if (s->photometric == TIFF_PHOTOMETRIC_BLACK_IS_ZERO) { + p->color_trc = AVCOL_TRC_GAMMA22; } - if (s->rps <= 0 || s->rps % s->subsampling[1]) { - av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); - return AVERROR_INVALIDDATA; + /* Handle DNG images with JPEG-compressed tiles */ + + if (is_dng && s->is_tiled) { + if (!s->is_jpeg) { + avpriv_report_missing_feature(avctx, "DNG uncompressed tiled images"); + return AVERROR_PATCHWELCOME; + } else if (!s->is_bayer) { + avpriv_report_missing_feature(avctx, "DNG JPG-compressed tiled non-bayer-encoded images"); + return AVERROR_PATCHWELCOME; + } else { + if ((ret = dng_decode_tiles(avctx, (AVFrame*)data, avpkt)) > 0) + *got_frame = 1; + return ret; + } } + /* Handle TIFF images and DNG images with uncompressed strips (non-tiled) */ + planes = s->planar ? s->bppcount : 1; for (plane = 0; plane < planes; plane++) { uint8_t *five_planes = NULL; @@ -1670,7 +2122,7 @@ FFSWAP(int, p->linesize[0], p->linesize[1]); } - if (s->is_bayer && s->white_level && s->bpp == 16) { + if (s->is_bayer && s->white_level && s->bpp == 16 && !is_dng) { uint16_t *dst = (uint16_t *)p->data[0]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) @@ -1687,6 +2139,8 @@ static av_cold int tiff_init(AVCodecContext *avctx) { TiffContext *s = avctx->priv_data; + const AVCodec *codec; + int ret; s->width = 0; s->height = 0; @@ -1698,6 +2152,28 @@ return AVERROR(ENOMEM); ff_ccitt_unpack_init(); + /* Allocate JPEG frame */ + s->jpgframe = av_frame_alloc(); + s->jpkt = av_packet_alloc(); + if (!s->jpgframe || !s->jpkt) + return AVERROR(ENOMEM); + + /* Prepare everything needed for JPEG decoding */ + codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG); + if (!codec) + return AVERROR_BUG; + s->avctx_mjpeg = avcodec_alloc_context3(codec); + if (!s->avctx_mjpeg) + return AVERROR(ENOMEM); + s->avctx_mjpeg->flags = avctx->flags; + s->avctx_mjpeg->flags2 = avctx->flags2; + s->avctx_mjpeg->dct_algo = avctx->dct_algo; + s->avctx_mjpeg->idct_algo = avctx->idct_algo; + ret = avcodec_open2(s->avctx_mjpeg, codec, NULL); + if (ret < 0) { + return ret; + } + return 0; } @@ -1714,6 +2190,9 @@ s->yuv_line_size = 0; av_freep(&s->fax_buffer); s->fax_buffer_size = 0; + av_frame_free(&s->jpgframe); + av_packet_free(&s->jpkt); + avcodec_free_context(&s->avctx_mjpeg); return 0; } @@ -1741,7 +2220,7 @@ .init = tiff_init, .close = tiff_end, .decode = decode_frame, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(tiff_init), .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .priv_class = &tiff_decoder_class, }; diff -Nru ffmpeg-4.2.2/libavcodec/tiff_common.h ffmpeg-4.4/libavcodec/tiff_common.h --- ffmpeg-4.2.2/libavcodec/tiff_common.h 2016-03-29 02:25:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tiff_common.h 2021-04-08 21:28:39.000000000 +0000 @@ -79,26 +79,6 @@ /** Reads a byte from the bytestream using given endianness. */ unsigned ff_tget(GetByteContext *gb, int type, int le); -/** Returns an allocated string containing count - * rational values using the given separator. - */ -char *ff_trationals2str(int *rp, int count, const char *sep); - -/** Returns an allocated string containing count - * long values using the given separator. - */ -char *ff_tlongs2str(int32_t *lp, int count, const char *sep); - -/** Returns an allocated string containing count - * double values using the given separator. - */ -char *ff_tdoubles2str(double *dp, int count, const char *sep); - -/** Returns an allocated string containing count - * short values using the given separator. - */ -char *ff_tshorts2str(int16_t *sp, int count, const char *sep); - /** Adds count rationals converted to a string * into the metadata dictionary. */ diff -Nru ffmpeg-4.2.2/libavcodec/tiff_data.c ffmpeg-4.4/libavcodec/tiff_data.c --- ffmpeg-4.2.2/libavcodec/tiff_data.c 2016-03-29 02:25:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tiff_data.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1870 +0,0 @@ -/* - * TIFF data tables - * Copyright (c) 2011 Thomas Kuehnel - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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 - * TIFF data tables - * @author Thomas Kuehnel - * @see GeoTIFF specification at - * http://www.remotesensing.org/geotiff/spec/geotiffhome.html - */ - -#include "tiff_data.h" - -const TiffGeoTagNameType ff_tiff_conf_name_type_map[] = { - {"GTModelTypeGeoKey", GEOTIFF_SHORT }, - {"GTRasterTypeGeoKey", GEOTIFF_SHORT }, - {"GTCitationGeoKey", GEOTIFF_STRING} -}; - -const TiffGeoTagNameType ff_tiff_geog_name_type_map[] = { - {"GeographicTypeGeoKey", GEOTIFF_SHORT }, - {"GeogCitationGeoKey", GEOTIFF_STRING}, - {"GeogGeodeticDatumGeoKey", GEOTIFF_SHORT }, - {"GeogPrimeMeridianGeoKey", GEOTIFF_SHORT }, - {"GeogLinearUnitsGeoKey", GEOTIFF_SHORT }, - {"GeogLinearUnitSizeGeoKey", GEOTIFF_DOUBLE}, - {"GeogAngularUnitsGeoKey", GEOTIFF_SHORT }, - {"GeogAngularUnitSizeGeoKey", GEOTIFF_DOUBLE}, - {"GeogEllipsoidGeoKey", GEOTIFF_SHORT }, - {"GeogSemiMajorAxisGeoKey", GEOTIFF_DOUBLE}, - {"GeogSemiMinorAxisGeoKey", GEOTIFF_DOUBLE}, - {"GeogInvFlatteningGeoKey", GEOTIFF_DOUBLE}, - {"GeogAzimuthUnitsGeoKey", GEOTIFF_SHORT }, - {"GeogPrimeMeridianLongGeoKey", GEOTIFF_DOUBLE} -}; - -const TiffGeoTagNameType ff_tiff_proj_name_type_map[] = { - {"ProjectedCSTypeGeoKey", GEOTIFF_SHORT }, - {"PCSCitationGeoKey", GEOTIFF_STRING}, - {"ProjectionGeoKey", GEOTIFF_SHORT }, - {"ProjCoordTransGeoKey", GEOTIFF_SHORT }, - {"ProjLinearUnitsGeoKey", GEOTIFF_SHORT }, - {"ProjLinearUnitSizeGeoKey", GEOTIFF_DOUBLE}, - {"ProjStdParallel1GeoKey", GEOTIFF_DOUBLE}, - {"ProjStdParallel2GeoKey", GEOTIFF_DOUBLE}, - {"ProjNatOriginLongGeoKey", GEOTIFF_DOUBLE}, - {"ProjNatOriginLatGeoKey", GEOTIFF_DOUBLE}, - {"ProjFalseEastingGeoKey", GEOTIFF_DOUBLE}, - {"ProjFalseNorthingGeoKey", GEOTIFF_DOUBLE}, - {"ProjFalseOriginLongGeoKey", GEOTIFF_DOUBLE}, - {"ProjFalseOriginLatGeoKey", GEOTIFF_DOUBLE}, - {"ProjFalseOriginEastingGeoKey", GEOTIFF_DOUBLE}, - {"ProjFalseOriginNorthingGeoKey", GEOTIFF_DOUBLE}, - {"ProjCenterLongGeoKey", GEOTIFF_DOUBLE}, - {"ProjCenterLatGeoKey", GEOTIFF_DOUBLE}, - {"ProjCenterEastingGeoKey", GEOTIFF_DOUBLE}, - {"ProjCenterNorthingGeoKey", GEOTIFF_DOUBLE}, - {"ProjScaleAtNatOriginGeoKey", GEOTIFF_DOUBLE}, - {"ProjScaleAtCenterGeoKey", GEOTIFF_DOUBLE}, - {"ProjAzimuthAngleGeoKey", GEOTIFF_DOUBLE}, - {"ProjStraightVertPoleLongGeoKey", GEOTIFF_DOUBLE} -}; - -const TiffGeoTagNameType ff_tiff_vert_name_type_map[] = { - {"VerticalCSTypeGeoKey", GEOTIFF_SHORT }, - {"VerticalCitationGeoKey", GEOTIFF_STRING}, - {"VerticalDatumGeoKey", GEOTIFF_SHORT }, - {"VerticalUnitsGeoKey", GEOTIFF_SHORT } -}; - -const char *const ff_tiff_gt_model_type_codes[] = { - "ModelTypeProjected", - "ModelTypeGeographic", - "ModelTypeGeocentric" -}; - -const char *const ff_tiff_gt_raster_type_codes[] = { - "RasterPixelIsArea", - "RasterPixelIsPoint" -}; - -const char *const ff_tiff_linear_unit_codes[] = { - "Linear_Meter", - "Linear_Foot", - "Linear_Foot_US_Survey", - "Linear_Foot_Modified_American", - "Linear_Foot_Clarke", - "Linear_Foot_Indian", - "Linear_Link", - "Linear_Link_Benoit", - "Linear_Link_Sears", - "Linear_Chain_Benoit", - "Linear_Chain_Sears", - "Linear_Yard_Sears", - "Linear_Yard_Indian", - "Linear_Fathom", - "Linear_Mile_International_Nautical" -}; - -const char *const ff_tiff_angular_unit_codes[] = { - "Angular_Radian", - "Angular_Degree", - "Angular_Arc_Minute", - "Angular_Arc_Second", - "Angular_Grad", - "Angular_Gon", - "Angular_DMS", - "Angular_DMS_Hemisphere" -}; - -const char *const ff_tiff_gcs_type_codes[] = { - "GCS_Adindan", - "GCS_AGD66", - "GCS_AGD84", - "GCS_Ain_el_Abd", - "GCS_Afgooye", - "GCS_Agadez", - "GCS_Lisbon", - "GCS_Aratu", - "GCS_Arc_1950", - "GCS_Arc_1960", - "GCS_Batavia", - "GCS_Barbados", - "GCS_Beduaram", - "GCS_Beijing_1954", - "GCS_Belge_1950", - "GCS_Bermuda_1957", - "GCS_Bern_1898", - "GCS_Bogota", - "GCS_Bukit_Rimpah", - "GCS_Camacupa", - "GCS_Campo_Inchauspe", - "GCS_Cape", - "GCS_Carthage", - "GCS_Chua", - "GCS_Corrego_Alegre", - "GCS_Cote_d_Ivoire", - "GCS_Deir_ez_Zor", - "GCS_Douala", - "GCS_Egypt_1907", - "GCS_ED50", - "GCS_ED87", - "GCS_Fahud", - "GCS_Gandajika_1970", - "GCS_Garoua", - "GCS_Guyane_Francaise", - "GCS_Hu_Tzu_Shan", - "GCS_HD72", - "GCS_ID74", - "GCS_Indian_1954", - "GCS_Indian_1975", - "GCS_Jamaica_1875", - "GCS_JAD69", - "GCS_Kalianpur", - "GCS_Kandawala", - "GCS_Kertau", - "GCS_KOC", - "GCS_La_Canoa", - "GCS_PSAD56", - "GCS_Lake", - "GCS_Leigon", - "GCS_Liberia_1964", - "GCS_Lome", - "GCS_Luzon_1911", - "GCS_Hito_XVIII_1963", - "GCS_Herat_North", - "GCS_Mahe_1971", - "GCS_Makassar", - "GCS_EUREF89", - "GCS_Malongo_1987", - "GCS_Manoca", - "GCS_Merchich", - "GCS_Massawa", - "GCS_Minna", - "GCS_Mhast", - "GCS_Monte_Mario", - "GCS_M_poraloko", - "GCS_NAD27", - "GCS_NAD_Michigan", - "GCS_NAD83", - "GCS_Nahrwan_1967", - "GCS_Naparima_1972", - "GCS_GD49", - "GCS_NGO_1948", - "GCS_Datum_73", - "GCS_NTF", - "GCS_NSWC_9Z_2", - "GCS_OSGB_1936", - "GCS_OSGB70", - "GCS_OS_SN80", - "GCS_Padang", - "GCS_Palestine_1923", - "GCS_Pointe_Noire", - "GCS_GDA94", - "GCS_Pulkovo_1942", - "GCS_Qatar", - "GCS_Qatar_1948", - "GCS_Qornoq", - "GCS_Loma_Quintana", - "GCS_Amersfoort", - "GCS_RT38", - "GCS_SAD69", - "GCS_Sapper_Hill_1943", - "GCS_Schwarzeck", - "GCS_Segora", - "GCS_Serindung", - "GCS_Sudan", - "GCS_Tananarive", - "GCS_Timbalai_1948", - "GCS_TM65", - "GCS_TM75", - "GCS_Tokyo", - "GCS_Trinidad_1903", - "GCS_TC_1948", - "GCS_Voirol_1875", - "GCS_Voirol_Unifie", - "GCS_Bern_1938", - "GCS_Nord_Sahara_1959", - "GCS_Stockholm_1938", - "GCS_Yacare", - "GCS_Yoff", - "GCS_Zanderij", - "GCS_MGI", - "GCS_Belge_1972", - "GCS_DHDN", - "GCS_Conakry_1905", - "GCS_WGS_72", - "GCS_WGS_72BE", - "GCS_WGS_84", - "GCS_Bern_1898_Bern", - "GCS_Bogota_Bogota", - "GCS_Lisbon_Lisbon", - "GCS_Makassar_Jakarta", - "GCS_MGI_Ferro", - "GCS_Monte_Mario_Rome", - "GCS_NTF_Paris", - "GCS_Padang_Jakarta", - "GCS_Belge_1950_Brussels", - "GCS_Tananarive_Paris", - "GCS_Voirol_1875_Paris", - "GCS_Voirol_Unifie_Paris", - "GCS_Batavia_Jakarta", - "GCS_ATF_Paris", - "GCS_NDG_Paris" -}; - -const char *const ff_tiff_gcse_type_codes[] = { - "GCSE_Airy1830", - "GCSE_AiryModified1849", - "GCSE_AustralianNationalSpheroid", - "GCSE_Bessel1841", - "GCSE_BesselModified", - "GCSE_BesselNamibia", - "GCSE_Clarke1858", - "GCSE_Clarke1866", - "GCSE_Clarke1866Michigan", - "GCSE_Clarke1880_Benoit", - "GCSE_Clarke1880_IGN", - "GCSE_Clarke1880_RGS", - "GCSE_Clarke1880_Arc", - "GCSE_Clarke1880_SGA1922", - "GCSE_Everest1830_1937Adjustment", - "GCSE_Everest1830_1967Definition", - "GCSE_Everest1830_1975Definition", - "GCSE_Everest1830Modified", - "GCSE_GRS1980", - "GCSE_Helmert1906", - "GCSE_IndonesianNationalSpheroid", - "GCSE_International1924", - "GCSE_International1967", - "GCSE_Krassowsky1940", - "GCSE_NWL9D", - "GCSE_NWL10D", - "GCSE_Plessis1817", - "GCSE_Struve1860", - "GCSE_WarOffice", - "GCSE_WGS84", - "GCSE_GEM10C", - "GCSE_OSU86F", - "GCSE_OSU91A", - "GCSE_Clarke1880", - "GCSE_Sphere" -}; - -const char *const ff_tiff_geodetic_datum_codes[] = { - "Datum_Adindan", - "Datum_Australian_Geodetic_Datum_1966", - "Datum_Australian_Geodetic_Datum_1984", - "Datum_Ain_el_Abd_1970", - "Datum_Afgooye", - "Datum_Agadez", - "Datum_Lisbon", - "Datum_Aratu", - "Datum_Arc_1950", - "Datum_Arc_1960", - "Datum_Batavia", - "Datum_Barbados", - "Datum_Beduaram", - "Datum_Beijing_1954", - "Datum_Reseau_National_Belge_1950", - "Datum_Bermuda_1957", - "Datum_Bern_1898", - "Datum_Bogota", - "Datum_Bukit_Rimpah", - "Datum_Camacupa", - "Datum_Campo_Inchauspe", - "Datum_Cape", - "Datum_Carthage", - "Datum_Chua", - "Datum_Corrego_Alegre", - "Datum_Cote_d_Ivoire", - "Datum_Deir_ez_Zor", - "Datum_Douala", - "Datum_Egypt_1907", - "Datum_European_Datum_1950", - "Datum_European_Datum_1987", - "Datum_Fahud", - "Datum_Gandajika_1970", - "Datum_Garoua", - "Datum_Guyane_Francaise", - "Datum_Hu_Tzu_Shan", - "Datum_Hungarian_Datum_1972", - "Datum_Indonesian_Datum_1974", - "Datum_Indian_1954", - "Datum_Indian_1975", - "Datum_Jamaica_1875", - "Datum_Jamaica_1969", - "Datum_Kalianpur", - "Datum_Kandawala", - "Datum_Kertau", - "Datum_Kuwait_Oil_Company", - "Datum_La_Canoa", - "Datum_Provisional_S_American_Datum_1956", - "Datum_Lake", - "Datum_Leigon", - "Datum_Liberia_1964", - "Datum_Lome", - "Datum_Luzon_1911", - "Datum_Hito_XVIII_1963", - "Datum_Herat_North", - "Datum_Mahe_1971", - "Datum_Makassar", - "Datum_European_Reference_System_1989", - "Datum_Malongo_1987", - "Datum_Manoca", - "Datum_Merchich", - "Datum_Massawa", - "Datum_Minna", - "Datum_Mhast", - "Datum_Monte_Mario", - "Datum_M_poraloko", - "Datum_North_American_Datum_1927", - "Datum_NAD_Michigan", - "Datum_North_American_Datum_1983", - "Datum_Nahrwan_1967", - "Datum_Naparima_1972", - "Datum_New_Zealand_Geodetic_Datum_1949", - "Datum_NGO_1948", - "Datum_Datum_73", - "Datum_Nouvelle_Triangulation_Francaise", - "Datum_NSWC_9Z_2", - "Datum_OSGB_1936", - "Datum_OSGB_1970_SN", - "Datum_OS_SN_1980", - "Datum_Padang_1884", - "Datum_Palestine_1923", - "Datum_Pointe_Noire", - "Datum_Geocentric_Datum_of_Australia_1994", - "Datum_Pulkovo_1942", - "Datum_Qatar", - "Datum_Qatar_1948", - "Datum_Qornoq", - "Datum_Loma_Quintana", - "Datum_Amersfoort", - "Datum_RT38", - "Datum_South_American_Datum_1969", - "Datum_Sapper_Hill_1943", - "Datum_Schwarzeck", - "Datum_Segora", - "Datum_Serindung", - "Datum_Sudan", - "Datum_Tananarive_1925", - "Datum_Timbalai_1948", - "Datum_TM65", - "Datum_TM75", - "Datum_Tokyo", - "Datum_Trinidad_1903", - "Datum_Trucial_Coast_1948", - "Datum_Voirol_1875", - "Datum_Voirol_Unifie_1960", - "Datum_Bern_1938", - "Datum_Nord_Sahara_1959", - "Datum_Stockholm_1938", - "Datum_Yacare", - "Datum_Yoff", - "Datum_Zanderij", - "Datum_Militar_Geographische_Institut", - "Datum_Reseau_National_Belge_1972", - "Datum_Deutsche_Hauptdreiecksnetz", - "Datum_Conakry_1905", - "Datum_WGS72", - "Datum_WGS72_Transit_Broadcast_Ephemeris", - "Datum_WGS84", - "Datum_Ancienne_Triangulation_Francaise", - "Datum_Nord_de_Guerre" -}; - -const char *const ff_tiff_geodetic_datum_e_codes[] = { - "DatumE_Airy1830", - "DatumE_AiryModified1849", - "DatumE_AustralianNationalSpheroid", - "DatumE_Bessel1841", - "DatumE_BesselModified", - "DatumE_BesselNamibia", - "DatumE_Clarke1858", - "DatumE_Clarke1866", - "DatumE_Clarke1866Michigan", - "DatumE_Clarke1880_Benoit", - "DatumE_Clarke1880_IGN", - "DatumE_Clarke1880_RGS", - "DatumE_Clarke1880_Arc", - "DatumE_Clarke1880_SGA1922", - "DatumE_Everest1830_1937Adjustment", - "DatumE_Everest1830_1967Definition", - "DatumE_Everest1830_1975Definition", - "DatumE_Everest1830Modified", - "DatumE_GRS1980", - "DatumE_Helmert1906", - "DatumE_IndonesianNationalSpheroid", - "DatumE_International1924", - "DatumE_International1967", - "DatumE_Krassowsky1960", - "DatumE_NWL9D", - "DatumE_NWL10D", - "DatumE_Plessis1817", - "DatumE_Struve1860", - "DatumE_WarOffice", - "DatumE_WGS84", - "DatumE_GEM10C", - "DatumE_OSU86F", - "DatumE_OSU91A", - "DatumE_Clarke1880", - "DatumE_Sphere" -}; - -const char *const ff_tiff_ellipsoid_codes[] = { - "Ellipse_Airy_1830", - "Ellipse_Airy_Modified_1849", - "Ellipse_Australian_National_Spheroid", - "Ellipse_Bessel_1841", - "Ellipse_Bessel_Modified", - "Ellipse_Bessel_Namibia", - "Ellipse_Clarke_1858", - "Ellipse_Clarke_1866", - "Ellipse_Clarke_1866_Michigan", - "Ellipse_Clarke_1880_Benoit", - "Ellipse_Clarke_1880_IGN", - "Ellipse_Clarke_1880_RGS", - "Ellipse_Clarke_1880_Arc", - "Ellipse_Clarke_1880_SGA_1922", - "Ellipse_Everest_1830_1937_Adjustment", - "Ellipse_Everest_1830_1967_Definition", - "Ellipse_Everest_1830_1975_Definition", - "Ellipse_Everest_1830_Modified", - "Ellipse_GRS_1980", - "Ellipse_Helmert_1906", - "Ellipse_Indonesian_National_Spheroid", - "Ellipse_International_1924", - "Ellipse_International_1967", - "Ellipse_Krassowsky_1940", - "Ellipse_NWL_9D", - "Ellipse_NWL_10D", - "Ellipse_Plessis_1817", - "Ellipse_Struve_1860", - "Ellipse_War_Office", - "Ellipse_WGS_84", - "Ellipse_GEM_10C", - "Ellipse_OSU86F", - "Ellipse_OSU91A", - "Ellipse_Clarke_1880", - "Ellipse_Sphere" -}; - -const char *const ff_tiff_prime_meridian_codes[] = { - "PM_Greenwich", - "PM_Lisbon", - "PM_Paris", - "PM_Bogota", - "PM_Madrid", - "PM_Rome", - "PM_Bern", - "PM_Jakarta", - "PM_Ferro", - "PM_Brussels", - "PM_Stockholm" -}; - -const TiffGeoTagKeyName ff_tiff_proj_cs_type_codes[] = { - {20137, "PCS_Adindan_UTM_zone_37N"}, - {20138, "PCS_Adindan_UTM_zone_38N"}, - {20248, "PCS_AGD66_AMG_zone_48"}, - {20249, "PCS_AGD66_AMG_zone_49"}, - {20250, "PCS_AGD66_AMG_zone_50"}, - {20251, "PCS_AGD66_AMG_zone_51"}, - {20252, "PCS_AGD66_AMG_zone_52"}, - {20253, "PCS_AGD66_AMG_zone_53"}, - {20254, "PCS_AGD66_AMG_zone_54"}, - {20255, "PCS_AGD66_AMG_zone_55"}, - {20256, "PCS_AGD66_AMG_zone_56"}, - {20257, "PCS_AGD66_AMG_zone_57"}, - {20258, "PCS_AGD66_AMG_zone_58"}, - {20348, "PCS_AGD84_AMG_zone_48"}, - {20349, "PCS_AGD84_AMG_zone_49"}, - {20350, "PCS_AGD84_AMG_zone_50"}, - {20351, "PCS_AGD84_AMG_zone_51"}, - {20352, "PCS_AGD84_AMG_zone_52"}, - {20353, "PCS_AGD84_AMG_zone_53"}, - {20354, "PCS_AGD84_AMG_zone_54"}, - {20355, "PCS_AGD84_AMG_zone_55"}, - {20356, "PCS_AGD84_AMG_zone_56"}, - {20357, "PCS_AGD84_AMG_zone_57"}, - {20358, "PCS_AGD84_AMG_zone_58"}, - {20437, "PCS_Ain_el_Abd_UTM_zone_37N"}, - {20438, "PCS_Ain_el_Abd_UTM_zone_38N"}, - {20439, "PCS_Ain_el_Abd_UTM_zone_39N"}, - {20499, "PCS_Ain_el_Abd_Bahrain_Grid"}, - {20538, "PCS_Afgooye_UTM_zone_38N"}, - {20539, "PCS_Afgooye_UTM_zone_39N"}, - {20700, "PCS_Lisbon_Portugese_Grid"}, - {20822, "PCS_Aratu_UTM_zone_22S"}, - {20823, "PCS_Aratu_UTM_zone_23S"}, - {20824, "PCS_Aratu_UTM_zone_24S"}, - {20973, "PCS_Arc_1950_Lo13"}, - {20975, "PCS_Arc_1950_Lo15"}, - {20977, "PCS_Arc_1950_Lo17"}, - {20979, "PCS_Arc_1950_Lo19"}, - {20981, "PCS_Arc_1950_Lo21"}, - {20983, "PCS_Arc_1950_Lo23"}, - {20985, "PCS_Arc_1950_Lo25"}, - {20987, "PCS_Arc_1950_Lo27"}, - {20989, "PCS_Arc_1950_Lo29"}, - {20991, "PCS_Arc_1950_Lo31"}, - {20993, "PCS_Arc_1950_Lo33"}, - {20995, "PCS_Arc_1950_Lo35"}, - {21100, "PCS_Batavia_NEIEZ"}, - {21148, "PCS_Batavia_UTM_zone_48S"}, - {21149, "PCS_Batavia_UTM_zone_49S"}, - {21150, "PCS_Batavia_UTM_zone_50S"}, - {21413, "PCS_Beijing_Gauss_zone_13"}, - {21414, "PCS_Beijing_Gauss_zone_14"}, - {21415, "PCS_Beijing_Gauss_zone_15"}, - {21416, "PCS_Beijing_Gauss_zone_16"}, - {21417, "PCS_Beijing_Gauss_zone_17"}, - {21418, "PCS_Beijing_Gauss_zone_18"}, - {21419, "PCS_Beijing_Gauss_zone_19"}, - {21420, "PCS_Beijing_Gauss_zone_20"}, - {21421, "PCS_Beijing_Gauss_zone_21"}, - {21422, "PCS_Beijing_Gauss_zone_22"}, - {21423, "PCS_Beijing_Gauss_zone_23"}, - {21473, "PCS_Beijing_Gauss_13N"}, - {21474, "PCS_Beijing_Gauss_14N"}, - {21475, "PCS_Beijing_Gauss_15N"}, - {21476, "PCS_Beijing_Gauss_16N"}, - {21477, "PCS_Beijing_Gauss_17N"}, - {21478, "PCS_Beijing_Gauss_18N"}, - {21479, "PCS_Beijing_Gauss_19N"}, - {21480, "PCS_Beijing_Gauss_20N"}, - {21481, "PCS_Beijing_Gauss_21N"}, - {21482, "PCS_Beijing_Gauss_22N"}, - {21483, "PCS_Beijing_Gauss_23N"}, - {21500, "PCS_Belge_Lambert_50"}, - {21790, "PCS_Bern_1898_Swiss_Old"}, - {21817, "PCS_Bogota_UTM_zone_17N"}, - {21818, "PCS_Bogota_UTM_zone_18N"}, - {21891, "PCS_Bogota_Colombia_3W"}, - {21892, "PCS_Bogota_Colombia_Bogota"}, - {21893, "PCS_Bogota_Colombia_3E"}, - {21894, "PCS_Bogota_Colombia_6E"}, - {22032, "PCS_Camacupa_UTM_32S"}, - {22033, "PCS_Camacupa_UTM_33S"}, - {22191, "PCS_C_Inchauspe_Argentina_1"}, - {22192, "PCS_C_Inchauspe_Argentina_2"}, - {22193, "PCS_C_Inchauspe_Argentina_3"}, - {22194, "PCS_C_Inchauspe_Argentina_4"}, - {22195, "PCS_C_Inchauspe_Argentina_5"}, - {22196, "PCS_C_Inchauspe_Argentina_6"}, - {22197, "PCS_C_Inchauspe_Argentina_7"}, - {22332, "PCS_Carthage_UTM_zone_32N"}, - {22391, "PCS_Carthage_Nord_Tunisie"}, - {22392, "PCS_Carthage_Sud_Tunisie"}, - {22523, "PCS_Corrego_Alegre_UTM_23S"}, - {22524, "PCS_Corrego_Alegre_UTM_24S"}, - {22832, "PCS_Douala_UTM_zone_32N"}, - {22992, "PCS_Egypt_1907_Red_Belt"}, - {22993, "PCS_Egypt_1907_Purple_Belt"}, - {22994, "PCS_Egypt_1907_Ext_Purple"}, - {23028, "PCS_ED50_UTM_zone_28N"}, - {23029, "PCS_ED50_UTM_zone_29N"}, - {23030, "PCS_ED50_UTM_zone_30N"}, - {23031, "PCS_ED50_UTM_zone_31N"}, - {23032, "PCS_ED50_UTM_zone_32N"}, - {23033, "PCS_ED50_UTM_zone_33N"}, - {23034, "PCS_ED50_UTM_zone_34N"}, - {23035, "PCS_ED50_UTM_zone_35N"}, - {23036, "PCS_ED50_UTM_zone_36N"}, - {23037, "PCS_ED50_UTM_zone_37N"}, - {23038, "PCS_ED50_UTM_zone_38N"}, - {23239, "PCS_Fahud_UTM_zone_39N"}, - {23240, "PCS_Fahud_UTM_zone_40N"}, - {23433, "PCS_Garoua_UTM_zone_33N"}, - {23846, "PCS_ID74_UTM_zone_46N"}, - {23847, "PCS_ID74_UTM_zone_47N"}, - {23848, "PCS_ID74_UTM_zone_48N"}, - {23849, "PCS_ID74_UTM_zone_49N"}, - {23850, "PCS_ID74_UTM_zone_50N"}, - {23851, "PCS_ID74_UTM_zone_51N"}, - {23852, "PCS_ID74_UTM_zone_52N"}, - {23853, "PCS_ID74_UTM_zone_53N"}, - {23886, "PCS_ID74_UTM_zone_46S"}, - {23887, "PCS_ID74_UTM_zone_47S"}, - {23888, "PCS_ID74_UTM_zone_48S"}, - {23889, "PCS_ID74_UTM_zone_49S"}, - {23890, "PCS_ID74_UTM_zone_50S"}, - {23891, "PCS_ID74_UTM_zone_51S"}, - {23892, "PCS_ID74_UTM_zone_52S"}, - {23893, "PCS_ID74_UTM_zone_53S"}, - {23894, "PCS_ID74_UTM_zone_54S"}, - {23947, "PCS_Indian_1954_UTM_47N"}, - {23948, "PCS_Indian_1954_UTM_48N"}, - {24047, "PCS_Indian_1975_UTM_47N"}, - {24048, "PCS_Indian_1975_UTM_48N"}, - {24100, "PCS_Jamaica_1875_Old_Grid"}, - {24200, "PCS_JAD69_Jamaica_Grid"}, - {24370, "PCS_Kalianpur_India_0"}, - {24371, "PCS_Kalianpur_India_I"}, - {24372, "PCS_Kalianpur_India_IIa"}, - {24373, "PCS_Kalianpur_India_IIIa"}, - {24374, "PCS_Kalianpur_India_IVa"}, - {24382, "PCS_Kalianpur_India_IIb"}, - {24383, "PCS_Kalianpur_India_IIIb"}, - {24384, "PCS_Kalianpur_India_IVb"}, - {24500, "PCS_Kertau_Singapore_Grid"}, - {24547, "PCS_Kertau_UTM_zone_47N"}, - {24548, "PCS_Kertau_UTM_zone_48N"}, - {24720, "PCS_La_Canoa_UTM_zone_20N"}, - {24721, "PCS_La_Canoa_UTM_zone_21N"}, - {24818, "PCS_PSAD56_UTM_zone_18N"}, - {24819, "PCS_PSAD56_UTM_zone_19N"}, - {24820, "PCS_PSAD56_UTM_zone_20N"}, - {24821, "PCS_PSAD56_UTM_zone_21N"}, - {24877, "PCS_PSAD56_UTM_zone_17S"}, - {24878, "PCS_PSAD56_UTM_zone_18S"}, - {24879, "PCS_PSAD56_UTM_zone_19S"}, - {24880, "PCS_PSAD56_UTM_zone_20S"}, - {24891, "PCS_PSAD56_Peru_west_zone"}, - {24892, "PCS_PSAD56_Peru_central"}, - {24893, "PCS_PSAD56_Peru_east_zone"}, - {25000, "PCS_Leigon_Ghana_Grid"}, - {25231, "PCS_Lome_UTM_zone_31N"}, - {25391, "PCS_Luzon_Philippines_I"}, - {25392, "PCS_Luzon_Philippines_II"}, - {25393, "PCS_Luzon_Philippines_III"}, - {25394, "PCS_Luzon_Philippines_IV"}, - {25395, "PCS_Luzon_Philippines_V"}, - {25700, "PCS_Makassar_NEIEZ"}, - {25932, "PCS_Malongo_1987_UTM_32S"}, - {26191, "PCS_Merchich_Nord_Maroc"}, - {26192, "PCS_Merchich_Sud_Maroc"}, - {26193, "PCS_Merchich_Sahara"}, - {26237, "PCS_Massawa_UTM_zone_37N"}, - {26331, "PCS_Minna_UTM_zone_31N"}, - {26332, "PCS_Minna_UTM_zone_32N"}, - {26391, "PCS_Minna_Nigeria_West"}, - {26392, "PCS_Minna_Nigeria_Mid_Belt"}, - {26393, "PCS_Minna_Nigeria_East"}, - {26432, "PCS_Mhast_UTM_zone_32S"}, - {26591, "PCS_Monte_Mario_Italy_1"}, - {26592, "PCS_Monte_Mario_Italy_2"}, - {26632, "PCS_M_poraloko_UTM_32N"}, - {26692, "PCS_M_poraloko_UTM_32S"}, - {26703, "PCS_NAD27_UTM_zone_3N"}, - {26704, "PCS_NAD27_UTM_zone_4N"}, - {26705, "PCS_NAD27_UTM_zone_5N"}, - {26706, "PCS_NAD27_UTM_zone_6N"}, - {26707, "PCS_NAD27_UTM_zone_7N"}, - {26708, "PCS_NAD27_UTM_zone_8N"}, - {26709, "PCS_NAD27_UTM_zone_9N"}, - {26710, "PCS_NAD27_UTM_zone_10N"}, - {26711, "PCS_NAD27_UTM_zone_11N"}, - {26712, "PCS_NAD27_UTM_zone_12N"}, - {26713, "PCS_NAD27_UTM_zone_13N"}, - {26714, "PCS_NAD27_UTM_zone_14N"}, - {26715, "PCS_NAD27_UTM_zone_15N"}, - {26716, "PCS_NAD27_UTM_zone_16N"}, - {26717, "PCS_NAD27_UTM_zone_17N"}, - {26718, "PCS_NAD27_UTM_zone_18N"}, - {26719, "PCS_NAD27_UTM_zone_19N"}, - {26720, "PCS_NAD27_UTM_zone_20N"}, - {26721, "PCS_NAD27_UTM_zone_21N"}, - {26722, "PCS_NAD27_UTM_zone_22N"}, - {26729, "PCS_NAD27_Alabama_East"}, - {26730, "PCS_NAD27_Alabama_West"}, - {26731, "PCS_NAD27_Alaska_zone_1"}, - {26732, "PCS_NAD27_Alaska_zone_2"}, - {26733, "PCS_NAD27_Alaska_zone_3"}, - {26734, "PCS_NAD27_Alaska_zone_4"}, - {26735, "PCS_NAD27_Alaska_zone_5"}, - {26736, "PCS_NAD27_Alaska_zone_6"}, - {26737, "PCS_NAD27_Alaska_zone_7"}, - {26738, "PCS_NAD27_Alaska_zone_8"}, - {26739, "PCS_NAD27_Alaska_zone_9"}, - {26740, "PCS_NAD27_Alaska_zone_10"}, - {26741, "PCS_NAD27_California_I"}, - {26742, "PCS_NAD27_California_II"}, - {26743, "PCS_NAD27_California_III"}, - {26744, "PCS_NAD27_California_IV"}, - {26745, "PCS_NAD27_California_V"}, - {26746, "PCS_NAD27_California_VI"}, - {26747, "PCS_NAD27_California_VII"}, - {26748, "PCS_NAD27_Arizona_East"}, - {26749, "PCS_NAD27_Arizona_Central"}, - {26750, "PCS_NAD27_Arizona_West"}, - {26751, "PCS_NAD27_Arkansas_North"}, - {26752, "PCS_NAD27_Arkansas_South"}, - {26753, "PCS_NAD27_Colorado_North"}, - {26754, "PCS_NAD27_Colorado_Central"}, - {26755, "PCS_NAD27_Colorado_South"}, - {26756, "PCS_NAD27_Connecticut"}, - {26757, "PCS_NAD27_Delaware"}, - {26758, "PCS_NAD27_Florida_East"}, - {26759, "PCS_NAD27_Florida_West"}, - {26760, "PCS_NAD27_Florida_North"}, - {26761, "PCS_NAD27_Hawaii_zone_1"}, - {26762, "PCS_NAD27_Hawaii_zone_2"}, - {26763, "PCS_NAD27_Hawaii_zone_3"}, - {26764, "PCS_NAD27_Hawaii_zone_4"}, - {26765, "PCS_NAD27_Hawaii_zone_5"}, - {26766, "PCS_NAD27_Georgia_East"}, - {26767, "PCS_NAD27_Georgia_West"}, - {26768, "PCS_NAD27_Idaho_East"}, - {26769, "PCS_NAD27_Idaho_Central"}, - {26770, "PCS_NAD27_Idaho_West"}, - {26771, "PCS_NAD27_Illinois_East"}, - {26772, "PCS_NAD27_Illinois_West"}, - {26773, "PCS_NAD27_Indiana_East"}, - {26774, "PCS_NAD27_BLM_14N_feet"}, - {26774, "PCS_NAD27_Indiana_West"}, - {26775, "PCS_NAD27_BLM_15N_feet"}, - {26775, "PCS_NAD27_Iowa_North"}, - {26776, "PCS_NAD27_BLM_16N_feet"}, - {26776, "PCS_NAD27_Iowa_South"}, - {26777, "PCS_NAD27_BLM_17N_feet"}, - {26777, "PCS_NAD27_Kansas_North"}, - {26778, "PCS_NAD27_Kansas_South"}, - {26779, "PCS_NAD27_Kentucky_North"}, - {26780, "PCS_NAD27_Kentucky_South"}, - {26781, "PCS_NAD27_Louisiana_North"}, - {26782, "PCS_NAD27_Louisiana_South"}, - {26783, "PCS_NAD27_Maine_East"}, - {26784, "PCS_NAD27_Maine_West"}, - {26785, "PCS_NAD27_Maryland"}, - {26786, "PCS_NAD27_Massachusetts"}, - {26787, "PCS_NAD27_Massachusetts_Is"}, - {26788, "PCS_NAD27_Michigan_North"}, - {26789, "PCS_NAD27_Michigan_Central"}, - {26790, "PCS_NAD27_Michigan_South"}, - {26791, "PCS_NAD27_Minnesota_North"}, - {26792, "PCS_NAD27_Minnesota_Cent"}, - {26793, "PCS_NAD27_Minnesota_South"}, - {26794, "PCS_NAD27_Mississippi_East"}, - {26795, "PCS_NAD27_Mississippi_West"}, - {26796, "PCS_NAD27_Missouri_East"}, - {26797, "PCS_NAD27_Missouri_Central"}, - {26798, "PCS_NAD27_Missouri_West"}, - {26801, "PCS_NAD_Michigan_Michigan_East"}, - {26802, "PCS_NAD_Michigan_Michigan_Old_Central"}, - {26803, "PCS_NAD_Michigan_Michigan_West"}, - {26903, "PCS_NAD83_UTM_zone_3N"}, - {26904, "PCS_NAD83_UTM_zone_4N"}, - {26905, "PCS_NAD83_UTM_zone_5N"}, - {26906, "PCS_NAD83_UTM_zone_6N"}, - {26907, "PCS_NAD83_UTM_zone_7N"}, - {26908, "PCS_NAD83_UTM_zone_8N"}, - {26909, "PCS_NAD83_UTM_zone_9N"}, - {26910, "PCS_NAD83_UTM_zone_10N"}, - {26911, "PCS_NAD83_UTM_zone_11N"}, - {26912, "PCS_NAD83_UTM_zone_12N"}, - {26913, "PCS_NAD83_UTM_zone_13N"}, - {26914, "PCS_NAD83_UTM_zone_14N"}, - {26915, "PCS_NAD83_UTM_zone_15N"}, - {26916, "PCS_NAD83_UTM_zone_16N"}, - {26917, "PCS_NAD83_UTM_zone_17N"}, - {26918, "PCS_NAD83_UTM_zone_18N"}, - {26919, "PCS_NAD83_UTM_zone_19N"}, - {26920, "PCS_NAD83_UTM_zone_20N"}, - {26921, "PCS_NAD83_UTM_zone_21N"}, - {26922, "PCS_NAD83_UTM_zone_22N"}, - {26923, "PCS_NAD83_UTM_zone_23N"}, - {26929, "PCS_NAD83_Alabama_East"}, - {26930, "PCS_NAD83_Alabama_West"}, - {26931, "PCS_NAD83_Alaska_zone_1"}, - {26932, "PCS_NAD83_Alaska_zone_2"}, - {26933, "PCS_NAD83_Alaska_zone_3"}, - {26934, "PCS_NAD83_Alaska_zone_4"}, - {26935, "PCS_NAD83_Alaska_zone_5"}, - {26936, "PCS_NAD83_Alaska_zone_6"}, - {26937, "PCS_NAD83_Alaska_zone_7"}, - {26938, "PCS_NAD83_Alaska_zone_8"}, - {26939, "PCS_NAD83_Alaska_zone_9"}, - {26940, "PCS_NAD83_Alaska_zone_10"}, - {26941, "PCS_NAD83_California_1"}, - {26942, "PCS_NAD83_California_2"}, - {26943, "PCS_NAD83_California_3"}, - {26944, "PCS_NAD83_California_4"}, - {26945, "PCS_NAD83_California_5"}, - {26946, "PCS_NAD83_California_6"}, - {26948, "PCS_NAD83_Arizona_East"}, - {26949, "PCS_NAD83_Arizona_Central"}, - {26950, "PCS_NAD83_Arizona_West"}, - {26951, "PCS_NAD83_Arkansas_North"}, - {26952, "PCS_NAD83_Arkansas_South"}, - {26953, "PCS_NAD83_Colorado_North"}, - {26954, "PCS_NAD83_Colorado_Central"}, - {26955, "PCS_NAD83_Colorado_South"}, - {26956, "PCS_NAD83_Connecticut"}, - {26957, "PCS_NAD83_Delaware"}, - {26958, "PCS_NAD83_Florida_East"}, - {26959, "PCS_NAD83_Florida_West"}, - {26960, "PCS_NAD83_Florida_North"}, - {26961, "PCS_NAD83_Hawaii_zone_1"}, - {26962, "PCS_NAD83_Hawaii_zone_2"}, - {26963, "PCS_NAD83_Hawaii_zone_3"}, - {26964, "PCS_NAD83_Hawaii_zone_4"}, - {26965, "PCS_NAD83_Hawaii_zone_5"}, - {26966, "PCS_NAD83_Georgia_East"}, - {26967, "PCS_NAD83_Georgia_West"}, - {26968, "PCS_NAD83_Idaho_East"}, - {26969, "PCS_NAD83_Idaho_Central"}, - {26970, "PCS_NAD83_Idaho_West"}, - {26971, "PCS_NAD83_Illinois_East"}, - {26972, "PCS_NAD83_Illinois_West"}, - {26973, "PCS_NAD83_Indiana_East"}, - {26974, "PCS_NAD83_Indiana_West"}, - {26975, "PCS_NAD83_Iowa_North"}, - {26976, "PCS_NAD83_Iowa_South"}, - {26977, "PCS_NAD83_Kansas_North"}, - {26978, "PCS_NAD83_Kansas_South"}, - {26979, "PCS_NAD83_Kentucky_North"}, - {26980, "PCS_NAD83_Kentucky_South"}, - {26981, "PCS_NAD83_Louisiana_North"}, - {26982, "PCS_NAD83_Louisiana_South"}, - {26983, "PCS_NAD83_Maine_East"}, - {26984, "PCS_NAD83_Maine_West"}, - {26985, "PCS_NAD83_Maryland"}, - {26986, "PCS_NAD83_Massachusetts"}, - {26987, "PCS_NAD83_Massachusetts_Is"}, - {26988, "PCS_NAD83_Michigan_North"}, - {26989, "PCS_NAD83_Michigan_Central"}, - {26990, "PCS_NAD83_Michigan_South"}, - {26991, "PCS_NAD83_Minnesota_North"}, - {26992, "PCS_NAD83_Minnesota_Cent"}, - {26993, "PCS_NAD83_Minnesota_South"}, - {26994, "PCS_NAD83_Mississippi_East"}, - {26995, "PCS_NAD83_Mississippi_West"}, - {26996, "PCS_NAD83_Missouri_East"}, - {26997, "PCS_NAD83_Missouri_Central"}, - {26998, "PCS_NAD83_Missouri_West"}, - {27038, "PCS_Nahrwan_1967_UTM_38N"}, - {27039, "PCS_Nahrwan_1967_UTM_39N"}, - {27040, "PCS_Nahrwan_1967_UTM_40N"}, - {27120, "PCS_Naparima_UTM_20N"}, - {27200, "PCS_GD49_NZ_Map_Grid"}, - {27291, "PCS_GD49_North_Island_Grid"}, - {27292, "PCS_GD49_South_Island_Grid"}, - {27429, "PCS_Datum_73_UTM_zone_29N"}, - {27500, "PCS_ATF_Nord_de_Guerre"}, - {27581, "PCS_NTF_France_I"}, - {27582, "PCS_NTF_France_II"}, - {27583, "PCS_NTF_France_III"}, - {27591, "PCS_NTF_Nord_France"}, - {27592, "PCS_NTF_Centre_France"}, - {27593, "PCS_NTF_Sud_France"}, - {27700, "PCS_British_National_Grid"}, - {28232, "PCS_Point_Noire_UTM_32S"}, - {28348, "PCS_GDA94_MGA_zone_48"}, - {28349, "PCS_GDA94_MGA_zone_49"}, - {28350, "PCS_GDA94_MGA_zone_50"}, - {28351, "PCS_GDA94_MGA_zone_51"}, - {28352, "PCS_GDA94_MGA_zone_52"}, - {28353, "PCS_GDA94_MGA_zone_53"}, - {28354, "PCS_GDA94_MGA_zone_54"}, - {28355, "PCS_GDA94_MGA_zone_55"}, - {28356, "PCS_GDA94_MGA_zone_56"}, - {28357, "PCS_GDA94_MGA_zone_57"}, - {28358, "PCS_GDA94_MGA_zone_58"}, - {28404, "PCS_Pulkovo_Gauss_zone_4"}, - {28405, "PCS_Pulkovo_Gauss_zone_5"}, - {28406, "PCS_Pulkovo_Gauss_zone_6"}, - {28407, "PCS_Pulkovo_Gauss_zone_7"}, - {28408, "PCS_Pulkovo_Gauss_zone_8"}, - {28409, "PCS_Pulkovo_Gauss_zone_9"}, - {28410, "PCS_Pulkovo_Gauss_zone_10"}, - {28411, "PCS_Pulkovo_Gauss_zone_11"}, - {28412, "PCS_Pulkovo_Gauss_zone_12"}, - {28413, "PCS_Pulkovo_Gauss_zone_13"}, - {28414, "PCS_Pulkovo_Gauss_zone_14"}, - {28415, "PCS_Pulkovo_Gauss_zone_15"}, - {28416, "PCS_Pulkovo_Gauss_zone_16"}, - {28417, "PCS_Pulkovo_Gauss_zone_17"}, - {28418, "PCS_Pulkovo_Gauss_zone_18"}, - {28419, "PCS_Pulkovo_Gauss_zone_19"}, - {28420, "PCS_Pulkovo_Gauss_zone_20"}, - {28421, "PCS_Pulkovo_Gauss_zone_21"}, - {28422, "PCS_Pulkovo_Gauss_zone_22"}, - {28423, "PCS_Pulkovo_Gauss_zone_23"}, - {28424, "PCS_Pulkovo_Gauss_zone_24"}, - {28425, "PCS_Pulkovo_Gauss_zone_25"}, - {28426, "PCS_Pulkovo_Gauss_zone_26"}, - {28427, "PCS_Pulkovo_Gauss_zone_27"}, - {28428, "PCS_Pulkovo_Gauss_zone_28"}, - {28429, "PCS_Pulkovo_Gauss_zone_29"}, - {28430, "PCS_Pulkovo_Gauss_zone_30"}, - {28431, "PCS_Pulkovo_Gauss_zone_31"}, - {28432, "PCS_Pulkovo_Gauss_zone_32"}, - {28464, "PCS_Pulkovo_Gauss_4N"}, - {28465, "PCS_Pulkovo_Gauss_5N"}, - {28466, "PCS_Pulkovo_Gauss_6N"}, - {28467, "PCS_Pulkovo_Gauss_7N"}, - {28468, "PCS_Pulkovo_Gauss_8N"}, - {28469, "PCS_Pulkovo_Gauss_9N"}, - {28470, "PCS_Pulkovo_Gauss_10N"}, - {28471, "PCS_Pulkovo_Gauss_11N"}, - {28472, "PCS_Pulkovo_Gauss_12N"}, - {28473, "PCS_Pulkovo_Gauss_13N"}, - {28474, "PCS_Pulkovo_Gauss_14N"}, - {28475, "PCS_Pulkovo_Gauss_15N"}, - {28476, "PCS_Pulkovo_Gauss_16N"}, - {28477, "PCS_Pulkovo_Gauss_17N"}, - {28478, "PCS_Pulkovo_Gauss_18N"}, - {28479, "PCS_Pulkovo_Gauss_19N"}, - {28480, "PCS_Pulkovo_Gauss_20N"}, - {28481, "PCS_Pulkovo_Gauss_21N"}, - {28482, "PCS_Pulkovo_Gauss_22N"}, - {28483, "PCS_Pulkovo_Gauss_23N"}, - {28484, "PCS_Pulkovo_Gauss_24N"}, - {28485, "PCS_Pulkovo_Gauss_25N"}, - {28486, "PCS_Pulkovo_Gauss_26N"}, - {28487, "PCS_Pulkovo_Gauss_27N"}, - {28488, "PCS_Pulkovo_Gauss_28N"}, - {28489, "PCS_Pulkovo_Gauss_29N"}, - {28490, "PCS_Pulkovo_Gauss_30N"}, - {28491, "PCS_Pulkovo_Gauss_31N"}, - {28492, "PCS_Pulkovo_Gauss_32N"}, - {28600, "PCS_Qatar_National_Grid"}, - {28991, "PCS_RD_Netherlands_Old"}, - {28992, "PCS_RD_Netherlands_New"}, - {29118, "PCS_SAD69_UTM_zone_18N"}, - {29119, "PCS_SAD69_UTM_zone_19N"}, - {29120, "PCS_SAD69_UTM_zone_20N"}, - {29121, "PCS_SAD69_UTM_zone_21N"}, - {29122, "PCS_SAD69_UTM_zone_22N"}, - {29177, "PCS_SAD69_UTM_zone_17S"}, - {29178, "PCS_SAD69_UTM_zone_18S"}, - {29179, "PCS_SAD69_UTM_zone_19S"}, - {29180, "PCS_SAD69_UTM_zone_20S"}, - {29181, "PCS_SAD69_UTM_zone_21S"}, - {29182, "PCS_SAD69_UTM_zone_22S"}, - {29183, "PCS_SAD69_UTM_zone_23S"}, - {29184, "PCS_SAD69_UTM_zone_24S"}, - {29185, "PCS_SAD69_UTM_zone_25S"}, - {29220, "PCS_Sapper_Hill_UTM_20S"}, - {29221, "PCS_Sapper_Hill_UTM_21S"}, - {29333, "PCS_Schwarzeck_UTM_33S"}, - {29635, "PCS_Sudan_UTM_zone_35N"}, - {29636, "PCS_Sudan_UTM_zone_36N"}, - {29700, "PCS_Tananarive_Laborde"}, - {29738, "PCS_Tananarive_UTM_38S"}, - {29739, "PCS_Tananarive_UTM_39S"}, - {29800, "PCS_Timbalai_1948_Borneo"}, - {29849, "PCS_Timbalai_1948_UTM_49N"}, - {29850, "PCS_Timbalai_1948_UTM_50N"}, - {29900, "PCS_TM65_Irish_Nat_Grid"}, - {30200, "PCS_Trinidad_1903_Trinidad"}, - {30339, "PCS_TC_1948_UTM_zone_39N"}, - {30340, "PCS_TC_1948_UTM_zone_40N"}, - {30491, "PCS_Voirol_N_Algerie_ancien"}, - {30492, "PCS_Voirol_S_Algerie_ancien"}, - {30591, "PCS_Voirol_Unifie_N_Algerie"}, - {30592, "PCS_Voirol_Unifie_S_Algerie"}, - {30600, "PCS_Bern_1938_Swiss_New"}, - {30729, "PCS_Nord_Sahara_UTM_29N"}, - {30730, "PCS_Nord_Sahara_UTM_30N"}, - {30731, "PCS_Nord_Sahara_UTM_31N"}, - {30732, "PCS_Nord_Sahara_UTM_32N"}, - {31028, "PCS_Yoff_UTM_zone_28N"}, - {31121, "PCS_Zanderij_UTM_zone_21N"}, - {31291, "PCS_MGI_Austria_West"}, - {31292, "PCS_MGI_Austria_Central"}, - {31293, "PCS_MGI_Austria_East"}, - {31300, "PCS_Belge_Lambert_72"}, - {31491, "PCS_DHDN_Germany_zone_1"}, - {31492, "PCS_DHDN_Germany_zone_2"}, - {31493, "PCS_DHDN_Germany_zone_3"}, - {31494, "PCS_DHDN_Germany_zone_4"}, - {31495, "PCS_DHDN_Germany_zone_5"}, - {32001, "PCS_NAD27_Montana_North"}, - {32002, "PCS_NAD27_Montana_Central"}, - {32003, "PCS_NAD27_Montana_South"}, - {32005, "PCS_NAD27_Nebraska_North"}, - {32006, "PCS_NAD27_Nebraska_South"}, - {32007, "PCS_NAD27_Nevada_East"}, - {32008, "PCS_NAD27_Nevada_Central"}, - {32009, "PCS_NAD27_Nevada_West"}, - {32010, "PCS_NAD27_New_Hampshire"}, - {32011, "PCS_NAD27_New_Jersey"}, - {32012, "PCS_NAD27_New_Mexico_East"}, - {32013, "PCS_NAD27_New_Mexico_Cent"}, - {32014, "PCS_NAD27_New_Mexico_West"}, - {32015, "PCS_NAD27_New_York_East"}, - {32016, "PCS_NAD27_New_York_Central"}, - {32017, "PCS_NAD27_New_York_West"}, - {32018, "PCS_NAD27_New_York_Long_Is"}, - {32019, "PCS_NAD27_North_Carolina"}, - {32020, "PCS_NAD27_North_Dakota_N"}, - {32021, "PCS_NAD27_North_Dakota_S"}, - {32022, "PCS_NAD27_Ohio_North"}, - {32023, "PCS_NAD27_Ohio_South"}, - {32024, "PCS_NAD27_Oklahoma_North"}, - {32025, "PCS_NAD27_Oklahoma_South"}, - {32026, "PCS_NAD27_Oregon_North"}, - {32027, "PCS_NAD27_Oregon_South"}, - {32028, "PCS_NAD27_Pennsylvania_N"}, - {32029, "PCS_NAD27_Pennsylvania_S"}, - {32030, "PCS_NAD27_Rhode_Island"}, - {32031, "PCS_NAD27_South_Carolina_N"}, - {32033, "PCS_NAD27_South_Carolina_S"}, - {32034, "PCS_NAD27_South_Dakota_N"}, - {32035, "PCS_NAD27_South_Dakota_S"}, - {32036, "PCS_NAD27_Tennessee"}, - {32037, "PCS_NAD27_Texas_North"}, - {32038, "PCS_NAD27_Texas_North_Cen"}, - {32039, "PCS_NAD27_Texas_Central"}, - {32040, "PCS_NAD27_Texas_South_Cen"}, - {32041, "PCS_NAD27_Texas_South"}, - {32042, "PCS_NAD27_Utah_North"}, - {32043, "PCS_NAD27_Utah_Central"}, - {32044, "PCS_NAD27_Utah_South"}, - {32045, "PCS_NAD27_Vermont"}, - {32046, "PCS_NAD27_Virginia_North"}, - {32047, "PCS_NAD27_Virginia_South"}, - {32048, "PCS_NAD27_Washington_North"}, - {32049, "PCS_NAD27_Washington_South"}, - {32050, "PCS_NAD27_West_Virginia_N"}, - {32051, "PCS_NAD27_West_Virginia_S"}, - {32052, "PCS_NAD27_Wisconsin_North"}, - {32053, "PCS_NAD27_Wisconsin_Cen"}, - {32054, "PCS_NAD27_Wisconsin_South"}, - {32055, "PCS_NAD27_Wyoming_East"}, - {32056, "PCS_NAD27_Wyoming_E_Cen"}, - {32057, "PCS_NAD27_Wyoming_W_Cen"}, - {32058, "PCS_NAD27_Wyoming_West"}, - {32059, "PCS_NAD27_Puerto_Rico"}, - {32060, "PCS_NAD27_St_Croix"}, - {32100, "PCS_NAD83_Montana"}, - {32104, "PCS_NAD83_Nebraska"}, - {32107, "PCS_NAD83_Nevada_East"}, - {32108, "PCS_NAD83_Nevada_Central"}, - {32109, "PCS_NAD83_Nevada_West"}, - {32110, "PCS_NAD83_New_Hampshire"}, - {32111, "PCS_NAD83_New_Jersey"}, - {32112, "PCS_NAD83_New_Mexico_East"}, - {32113, "PCS_NAD83_New_Mexico_Cent"}, - {32114, "PCS_NAD83_New_Mexico_West"}, - {32115, "PCS_NAD83_New_York_East"}, - {32116, "PCS_NAD83_New_York_Central"}, - {32117, "PCS_NAD83_New_York_West"}, - {32118, "PCS_NAD83_New_York_Long_Is"}, - {32119, "PCS_NAD83_North_Carolina"}, - {32120, "PCS_NAD83_North_Dakota_N"}, - {32121, "PCS_NAD83_North_Dakota_S"}, - {32122, "PCS_NAD83_Ohio_North"}, - {32123, "PCS_NAD83_Ohio_South"}, - {32124, "PCS_NAD83_Oklahoma_North"}, - {32125, "PCS_NAD83_Oklahoma_South"}, - {32126, "PCS_NAD83_Oregon_North"}, - {32127, "PCS_NAD83_Oregon_South"}, - {32128, "PCS_NAD83_Pennsylvania_N"}, - {32129, "PCS_NAD83_Pennsylvania_S"}, - {32130, "PCS_NAD83_Rhode_Island"}, - {32133, "PCS_NAD83_South_Carolina"}, - {32134, "PCS_NAD83_South_Dakota_N"}, - {32135, "PCS_NAD83_South_Dakota_S"}, - {32136, "PCS_NAD83_Tennessee"}, - {32137, "PCS_NAD83_Texas_North"}, - {32138, "PCS_NAD83_Texas_North_Cen"}, - {32139, "PCS_NAD83_Texas_Central"}, - {32140, "PCS_NAD83_Texas_South_Cen"}, - {32141, "PCS_NAD83_Texas_South"}, - {32142, "PCS_NAD83_Utah_North"}, - {32143, "PCS_NAD83_Utah_Central"}, - {32144, "PCS_NAD83_Utah_South"}, - {32145, "PCS_NAD83_Vermont"}, - {32146, "PCS_NAD83_Virginia_North"}, - {32147, "PCS_NAD83_Virginia_South"}, - {32148, "PCS_NAD83_Washington_North"}, - {32149, "PCS_NAD83_Washington_South"}, - {32150, "PCS_NAD83_West_Virginia_N"}, - {32151, "PCS_NAD83_West_Virginia_S"}, - {32152, "PCS_NAD83_Wisconsin_North"}, - {32153, "PCS_NAD83_Wisconsin_Cen"}, - {32154, "PCS_NAD83_Wisconsin_South"}, - {32155, "PCS_NAD83_Wyoming_East"}, - {32156, "PCS_NAD83_Wyoming_E_Cen"}, - {32157, "PCS_NAD83_Wyoming_W_Cen"}, - {32158, "PCS_NAD83_Wyoming_West"}, - {32161, "PCS_NAD83_Puerto_Rico_Virgin_Is"}, - {32201, "PCS_WGS72_UTM_zone_1N"}, - {32202, "PCS_WGS72_UTM_zone_2N"}, - {32203, "PCS_WGS72_UTM_zone_3N"}, - {32204, "PCS_WGS72_UTM_zone_4N"}, - {32205, "PCS_WGS72_UTM_zone_5N"}, - {32206, "PCS_WGS72_UTM_zone_6N"}, - {32207, "PCS_WGS72_UTM_zone_7N"}, - {32208, "PCS_WGS72_UTM_zone_8N"}, - {32209, "PCS_WGS72_UTM_zone_9N"}, - {32210, "PCS_WGS72_UTM_zone_10N"}, - {32211, "PCS_WGS72_UTM_zone_11N"}, - {32212, "PCS_WGS72_UTM_zone_12N"}, - {32213, "PCS_WGS72_UTM_zone_13N"}, - {32214, "PCS_WGS72_UTM_zone_14N"}, - {32215, "PCS_WGS72_UTM_zone_15N"}, - {32216, "PCS_WGS72_UTM_zone_16N"}, - {32217, "PCS_WGS72_UTM_zone_17N"}, - {32218, "PCS_WGS72_UTM_zone_18N"}, - {32219, "PCS_WGS72_UTM_zone_19N"}, - {32220, "PCS_WGS72_UTM_zone_20N"}, - {32221, "PCS_WGS72_UTM_zone_21N"}, - {32222, "PCS_WGS72_UTM_zone_22N"}, - {32223, "PCS_WGS72_UTM_zone_23N"}, - {32224, "PCS_WGS72_UTM_zone_24N"}, - {32225, "PCS_WGS72_UTM_zone_25N"}, - {32226, "PCS_WGS72_UTM_zone_26N"}, - {32227, "PCS_WGS72_UTM_zone_27N"}, - {32228, "PCS_WGS72_UTM_zone_28N"}, - {32229, "PCS_WGS72_UTM_zone_29N"}, - {32230, "PCS_WGS72_UTM_zone_30N"}, - {32231, "PCS_WGS72_UTM_zone_31N"}, - {32232, "PCS_WGS72_UTM_zone_32N"}, - {32233, "PCS_WGS72_UTM_zone_33N"}, - {32234, "PCS_WGS72_UTM_zone_34N"}, - {32235, "PCS_WGS72_UTM_zone_35N"}, - {32236, "PCS_WGS72_UTM_zone_36N"}, - {32237, "PCS_WGS72_UTM_zone_37N"}, - {32238, "PCS_WGS72_UTM_zone_38N"}, - {32239, "PCS_WGS72_UTM_zone_39N"}, - {32240, "PCS_WGS72_UTM_zone_40N"}, - {32241, "PCS_WGS72_UTM_zone_41N"}, - {32242, "PCS_WGS72_UTM_zone_42N"}, - {32243, "PCS_WGS72_UTM_zone_43N"}, - {32244, "PCS_WGS72_UTM_zone_44N"}, - {32245, "PCS_WGS72_UTM_zone_45N"}, - {32246, "PCS_WGS72_UTM_zone_46N"}, - {32247, "PCS_WGS72_UTM_zone_47N"}, - {32248, "PCS_WGS72_UTM_zone_48N"}, - {32249, "PCS_WGS72_UTM_zone_49N"}, - {32250, "PCS_WGS72_UTM_zone_50N"}, - {32251, "PCS_WGS72_UTM_zone_51N"}, - {32252, "PCS_WGS72_UTM_zone_52N"}, - {32253, "PCS_WGS72_UTM_zone_53N"}, - {32254, "PCS_WGS72_UTM_zone_54N"}, - {32255, "PCS_WGS72_UTM_zone_55N"}, - {32256, "PCS_WGS72_UTM_zone_56N"}, - {32257, "PCS_WGS72_UTM_zone_57N"}, - {32258, "PCS_WGS72_UTM_zone_58N"}, - {32259, "PCS_WGS72_UTM_zone_59N"}, - {32260, "PCS_WGS72_UTM_zone_60N"}, - {32301, "PCS_WGS72_UTM_zone_1S"}, - {32302, "PCS_WGS72_UTM_zone_2S"}, - {32303, "PCS_WGS72_UTM_zone_3S"}, - {32304, "PCS_WGS72_UTM_zone_4S"}, - {32305, "PCS_WGS72_UTM_zone_5S"}, - {32306, "PCS_WGS72_UTM_zone_6S"}, - {32307, "PCS_WGS72_UTM_zone_7S"}, - {32308, "PCS_WGS72_UTM_zone_8S"}, - {32309, "PCS_WGS72_UTM_zone_9S"}, - {32310, "PCS_WGS72_UTM_zone_10S"}, - {32311, "PCS_WGS72_UTM_zone_11S"}, - {32312, "PCS_WGS72_UTM_zone_12S"}, - {32313, "PCS_WGS72_UTM_zone_13S"}, - {32314, "PCS_WGS72_UTM_zone_14S"}, - {32315, "PCS_WGS72_UTM_zone_15S"}, - {32316, "PCS_WGS72_UTM_zone_16S"}, - {32317, "PCS_WGS72_UTM_zone_17S"}, - {32318, "PCS_WGS72_UTM_zone_18S"}, - {32319, "PCS_WGS72_UTM_zone_19S"}, - {32320, "PCS_WGS72_UTM_zone_20S"}, - {32321, "PCS_WGS72_UTM_zone_21S"}, - {32322, "PCS_WGS72_UTM_zone_22S"}, - {32323, "PCS_WGS72_UTM_zone_23S"}, - {32324, "PCS_WGS72_UTM_zone_24S"}, - {32325, "PCS_WGS72_UTM_zone_25S"}, - {32326, "PCS_WGS72_UTM_zone_26S"}, - {32327, "PCS_WGS72_UTM_zone_27S"}, - {32328, "PCS_WGS72_UTM_zone_28S"}, - {32329, "PCS_WGS72_UTM_zone_29S"}, - {32330, "PCS_WGS72_UTM_zone_30S"}, - {32331, "PCS_WGS72_UTM_zone_31S"}, - {32332, "PCS_WGS72_UTM_zone_32S"}, - {32333, "PCS_WGS72_UTM_zone_33S"}, - {32334, "PCS_WGS72_UTM_zone_34S"}, - {32335, "PCS_WGS72_UTM_zone_35S"}, - {32336, "PCS_WGS72_UTM_zone_36S"}, - {32337, "PCS_WGS72_UTM_zone_37S"}, - {32338, "PCS_WGS72_UTM_zone_38S"}, - {32339, "PCS_WGS72_UTM_zone_39S"}, - {32340, "PCS_WGS72_UTM_zone_40S"}, - {32341, "PCS_WGS72_UTM_zone_41S"}, - {32342, "PCS_WGS72_UTM_zone_42S"}, - {32343, "PCS_WGS72_UTM_zone_43S"}, - {32344, "PCS_WGS72_UTM_zone_44S"}, - {32345, "PCS_WGS72_UTM_zone_45S"}, - {32346, "PCS_WGS72_UTM_zone_46S"}, - {32347, "PCS_WGS72_UTM_zone_47S"}, - {32348, "PCS_WGS72_UTM_zone_48S"}, - {32349, "PCS_WGS72_UTM_zone_49S"}, - {32350, "PCS_WGS72_UTM_zone_50S"}, - {32351, "PCS_WGS72_UTM_zone_51S"}, - {32352, "PCS_WGS72_UTM_zone_52S"}, - {32353, "PCS_WGS72_UTM_zone_53S"}, - {32354, "PCS_WGS72_UTM_zone_54S"}, - {32355, "PCS_WGS72_UTM_zone_55S"}, - {32356, "PCS_WGS72_UTM_zone_56S"}, - {32357, "PCS_WGS72_UTM_zone_57S"}, - {32358, "PCS_WGS72_UTM_zone_58S"}, - {32359, "PCS_WGS72_UTM_zone_59S"}, - {32360, "PCS_WGS72_UTM_zone_60S"}, - {32401, "PCS_WGS72BE_UTM_zone_1N"}, - {32402, "PCS_WGS72BE_UTM_zone_2N"}, - {32403, "PCS_WGS72BE_UTM_zone_3N"}, - {32404, "PCS_WGS72BE_UTM_zone_4N"}, - {32405, "PCS_WGS72BE_UTM_zone_5N"}, - {32406, "PCS_WGS72BE_UTM_zone_6N"}, - {32407, "PCS_WGS72BE_UTM_zone_7N"}, - {32408, "PCS_WGS72BE_UTM_zone_8N"}, - {32409, "PCS_WGS72BE_UTM_zone_9N"}, - {32410, "PCS_WGS72BE_UTM_zone_10N"}, - {32411, "PCS_WGS72BE_UTM_zone_11N"}, - {32412, "PCS_WGS72BE_UTM_zone_12N"}, - {32413, "PCS_WGS72BE_UTM_zone_13N"}, - {32414, "PCS_WGS72BE_UTM_zone_14N"}, - {32415, "PCS_WGS72BE_UTM_zone_15N"}, - {32416, "PCS_WGS72BE_UTM_zone_16N"}, - {32417, "PCS_WGS72BE_UTM_zone_17N"}, - {32418, "PCS_WGS72BE_UTM_zone_18N"}, - {32419, "PCS_WGS72BE_UTM_zone_19N"}, - {32420, "PCS_WGS72BE_UTM_zone_20N"}, - {32421, "PCS_WGS72BE_UTM_zone_21N"}, - {32422, "PCS_WGS72BE_UTM_zone_22N"}, - {32423, "PCS_WGS72BE_UTM_zone_23N"}, - {32424, "PCS_WGS72BE_UTM_zone_24N"}, - {32425, "PCS_WGS72BE_UTM_zone_25N"}, - {32426, "PCS_WGS72BE_UTM_zone_26N"}, - {32427, "PCS_WGS72BE_UTM_zone_27N"}, - {32428, "PCS_WGS72BE_UTM_zone_28N"}, - {32429, "PCS_WGS72BE_UTM_zone_29N"}, - {32430, "PCS_WGS72BE_UTM_zone_30N"}, - {32431, "PCS_WGS72BE_UTM_zone_31N"}, - {32432, "PCS_WGS72BE_UTM_zone_32N"}, - {32433, "PCS_WGS72BE_UTM_zone_33N"}, - {32434, "PCS_WGS72BE_UTM_zone_34N"}, - {32435, "PCS_WGS72BE_UTM_zone_35N"}, - {32436, "PCS_WGS72BE_UTM_zone_36N"}, - {32437, "PCS_WGS72BE_UTM_zone_37N"}, - {32438, "PCS_WGS72BE_UTM_zone_38N"}, - {32439, "PCS_WGS72BE_UTM_zone_39N"}, - {32440, "PCS_WGS72BE_UTM_zone_40N"}, - {32441, "PCS_WGS72BE_UTM_zone_41N"}, - {32442, "PCS_WGS72BE_UTM_zone_42N"}, - {32443, "PCS_WGS72BE_UTM_zone_43N"}, - {32444, "PCS_WGS72BE_UTM_zone_44N"}, - {32445, "PCS_WGS72BE_UTM_zone_45N"}, - {32446, "PCS_WGS72BE_UTM_zone_46N"}, - {32447, "PCS_WGS72BE_UTM_zone_47N"}, - {32448, "PCS_WGS72BE_UTM_zone_48N"}, - {32449, "PCS_WGS72BE_UTM_zone_49N"}, - {32450, "PCS_WGS72BE_UTM_zone_50N"}, - {32451, "PCS_WGS72BE_UTM_zone_51N"}, - {32452, "PCS_WGS72BE_UTM_zone_52N"}, - {32453, "PCS_WGS72BE_UTM_zone_53N"}, - {32454, "PCS_WGS72BE_UTM_zone_54N"}, - {32455, "PCS_WGS72BE_UTM_zone_55N"}, - {32456, "PCS_WGS72BE_UTM_zone_56N"}, - {32457, "PCS_WGS72BE_UTM_zone_57N"}, - {32458, "PCS_WGS72BE_UTM_zone_58N"}, - {32459, "PCS_WGS72BE_UTM_zone_59N"}, - {32460, "PCS_WGS72BE_UTM_zone_60N"}, - {32501, "PCS_WGS72BE_UTM_zone_1S"}, - {32502, "PCS_WGS72BE_UTM_zone_2S"}, - {32503, "PCS_WGS72BE_UTM_zone_3S"}, - {32504, "PCS_WGS72BE_UTM_zone_4S"}, - {32505, "PCS_WGS72BE_UTM_zone_5S"}, - {32506, "PCS_WGS72BE_UTM_zone_6S"}, - {32507, "PCS_WGS72BE_UTM_zone_7S"}, - {32508, "PCS_WGS72BE_UTM_zone_8S"}, - {32509, "PCS_WGS72BE_UTM_zone_9S"}, - {32510, "PCS_WGS72BE_UTM_zone_10S"}, - {32511, "PCS_WGS72BE_UTM_zone_11S"}, - {32512, "PCS_WGS72BE_UTM_zone_12S"}, - {32513, "PCS_WGS72BE_UTM_zone_13S"}, - {32514, "PCS_WGS72BE_UTM_zone_14S"}, - {32515, "PCS_WGS72BE_UTM_zone_15S"}, - {32516, "PCS_WGS72BE_UTM_zone_16S"}, - {32517, "PCS_WGS72BE_UTM_zone_17S"}, - {32518, "PCS_WGS72BE_UTM_zone_18S"}, - {32519, "PCS_WGS72BE_UTM_zone_19S"}, - {32520, "PCS_WGS72BE_UTM_zone_20S"}, - {32521, "PCS_WGS72BE_UTM_zone_21S"}, - {32522, "PCS_WGS72BE_UTM_zone_22S"}, - {32523, "PCS_WGS72BE_UTM_zone_23S"}, - {32524, "PCS_WGS72BE_UTM_zone_24S"}, - {32525, "PCS_WGS72BE_UTM_zone_25S"}, - {32526, "PCS_WGS72BE_UTM_zone_26S"}, - {32527, "PCS_WGS72BE_UTM_zone_27S"}, - {32528, "PCS_WGS72BE_UTM_zone_28S"}, - {32529, "PCS_WGS72BE_UTM_zone_29S"}, - {32530, "PCS_WGS72BE_UTM_zone_30S"}, - {32531, "PCS_WGS72BE_UTM_zone_31S"}, - {32532, "PCS_WGS72BE_UTM_zone_32S"}, - {32533, "PCS_WGS72BE_UTM_zone_33S"}, - {32534, "PCS_WGS72BE_UTM_zone_34S"}, - {32535, "PCS_WGS72BE_UTM_zone_35S"}, - {32536, "PCS_WGS72BE_UTM_zone_36S"}, - {32537, "PCS_WGS72BE_UTM_zone_37S"}, - {32538, "PCS_WGS72BE_UTM_zone_38S"}, - {32539, "PCS_WGS72BE_UTM_zone_39S"}, - {32540, "PCS_WGS72BE_UTM_zone_40S"}, - {32541, "PCS_WGS72BE_UTM_zone_41S"}, - {32542, "PCS_WGS72BE_UTM_zone_42S"}, - {32543, "PCS_WGS72BE_UTM_zone_43S"}, - {32544, "PCS_WGS72BE_UTM_zone_44S"}, - {32545, "PCS_WGS72BE_UTM_zone_45S"}, - {32546, "PCS_WGS72BE_UTM_zone_46S"}, - {32547, "PCS_WGS72BE_UTM_zone_47S"}, - {32548, "PCS_WGS72BE_UTM_zone_48S"}, - {32549, "PCS_WGS72BE_UTM_zone_49S"}, - {32550, "PCS_WGS72BE_UTM_zone_50S"}, - {32551, "PCS_WGS72BE_UTM_zone_51S"}, - {32552, "PCS_WGS72BE_UTM_zone_52S"}, - {32553, "PCS_WGS72BE_UTM_zone_53S"}, - {32554, "PCS_WGS72BE_UTM_zone_54S"}, - {32555, "PCS_WGS72BE_UTM_zone_55S"}, - {32556, "PCS_WGS72BE_UTM_zone_56S"}, - {32557, "PCS_WGS72BE_UTM_zone_57S"}, - {32558, "PCS_WGS72BE_UTM_zone_58S"}, - {32559, "PCS_WGS72BE_UTM_zone_59S"}, - {32560, "PCS_WGS72BE_UTM_zone_60S"}, - {32601, "PCS_WGS84_UTM_zone_1N"}, - {32602, "PCS_WGS84_UTM_zone_2N"}, - {32603, "PCS_WGS84_UTM_zone_3N"}, - {32604, "PCS_WGS84_UTM_zone_4N"}, - {32605, "PCS_WGS84_UTM_zone_5N"}, - {32606, "PCS_WGS84_UTM_zone_6N"}, - {32607, "PCS_WGS84_UTM_zone_7N"}, - {32608, "PCS_WGS84_UTM_zone_8N"}, - {32609, "PCS_WGS84_UTM_zone_9N"}, - {32610, "PCS_WGS84_UTM_zone_10N"}, - {32611, "PCS_WGS84_UTM_zone_11N"}, - {32612, "PCS_WGS84_UTM_zone_12N"}, - {32613, "PCS_WGS84_UTM_zone_13N"}, - {32614, "PCS_WGS84_UTM_zone_14N"}, - {32615, "PCS_WGS84_UTM_zone_15N"}, - {32616, "PCS_WGS84_UTM_zone_16N"}, - {32617, "PCS_WGS84_UTM_zone_17N"}, - {32618, "PCS_WGS84_UTM_zone_18N"}, - {32619, "PCS_WGS84_UTM_zone_19N"}, - {32620, "PCS_WGS84_UTM_zone_20N"}, - {32621, "PCS_WGS84_UTM_zone_21N"}, - {32622, "PCS_WGS84_UTM_zone_22N"}, - {32623, "PCS_WGS84_UTM_zone_23N"}, - {32624, "PCS_WGS84_UTM_zone_24N"}, - {32625, "PCS_WGS84_UTM_zone_25N"}, - {32626, "PCS_WGS84_UTM_zone_26N"}, - {32627, "PCS_WGS84_UTM_zone_27N"}, - {32628, "PCS_WGS84_UTM_zone_28N"}, - {32629, "PCS_WGS84_UTM_zone_29N"}, - {32630, "PCS_WGS84_UTM_zone_30N"}, - {32631, "PCS_WGS84_UTM_zone_31N"}, - {32632, "PCS_WGS84_UTM_zone_32N"}, - {32633, "PCS_WGS84_UTM_zone_33N"}, - {32634, "PCS_WGS84_UTM_zone_34N"}, - {32635, "PCS_WGS84_UTM_zone_35N"}, - {32636, "PCS_WGS84_UTM_zone_36N"}, - {32637, "PCS_WGS84_UTM_zone_37N"}, - {32638, "PCS_WGS84_UTM_zone_38N"}, - {32639, "PCS_WGS84_UTM_zone_39N"}, - {32640, "PCS_WGS84_UTM_zone_40N"}, - {32641, "PCS_WGS84_UTM_zone_41N"}, - {32642, "PCS_WGS84_UTM_zone_42N"}, - {32643, "PCS_WGS84_UTM_zone_43N"}, - {32644, "PCS_WGS84_UTM_zone_44N"}, - {32645, "PCS_WGS84_UTM_zone_45N"}, - {32646, "PCS_WGS84_UTM_zone_46N"}, - {32647, "PCS_WGS84_UTM_zone_47N"}, - {32648, "PCS_WGS84_UTM_zone_48N"}, - {32649, "PCS_WGS84_UTM_zone_49N"}, - {32650, "PCS_WGS84_UTM_zone_50N"}, - {32651, "PCS_WGS84_UTM_zone_51N"}, - {32652, "PCS_WGS84_UTM_zone_52N"}, - {32653, "PCS_WGS84_UTM_zone_53N"}, - {32654, "PCS_WGS84_UTM_zone_54N"}, - {32655, "PCS_WGS84_UTM_zone_55N"}, - {32656, "PCS_WGS84_UTM_zone_56N"}, - {32657, "PCS_WGS84_UTM_zone_57N"}, - {32658, "PCS_WGS84_UTM_zone_58N"}, - {32659, "PCS_WGS84_UTM_zone_59N"}, - {32660, "PCS_WGS84_UTM_zone_60N"}, - {32701, "PCS_WGS84_UTM_zone_1S"}, - {32702, "PCS_WGS84_UTM_zone_2S"}, - {32703, "PCS_WGS84_UTM_zone_3S"}, - {32704, "PCS_WGS84_UTM_zone_4S"}, - {32705, "PCS_WGS84_UTM_zone_5S"}, - {32706, "PCS_WGS84_UTM_zone_6S"}, - {32707, "PCS_WGS84_UTM_zone_7S"}, - {32708, "PCS_WGS84_UTM_zone_8S"}, - {32709, "PCS_WGS84_UTM_zone_9S"}, - {32710, "PCS_WGS84_UTM_zone_10S"}, - {32711, "PCS_WGS84_UTM_zone_11S"}, - {32712, "PCS_WGS84_UTM_zone_12S"}, - {32713, "PCS_WGS84_UTM_zone_13S"}, - {32714, "PCS_WGS84_UTM_zone_14S"}, - {32715, "PCS_WGS84_UTM_zone_15S"}, - {32716, "PCS_WGS84_UTM_zone_16S"}, - {32717, "PCS_WGS84_UTM_zone_17S"}, - {32718, "PCS_WGS84_UTM_zone_18S"}, - {32719, "PCS_WGS84_UTM_zone_19S"}, - {32720, "PCS_WGS84_UTM_zone_20S"}, - {32721, "PCS_WGS84_UTM_zone_21S"}, - {32722, "PCS_WGS84_UTM_zone_22S"}, - {32723, "PCS_WGS84_UTM_zone_23S"}, - {32724, "PCS_WGS84_UTM_zone_24S"}, - {32725, "PCS_WGS84_UTM_zone_25S"}, - {32726, "PCS_WGS84_UTM_zone_26S"}, - {32727, "PCS_WGS84_UTM_zone_27S"}, - {32728, "PCS_WGS84_UTM_zone_28S"}, - {32729, "PCS_WGS84_UTM_zone_29S"}, - {32730, "PCS_WGS84_UTM_zone_30S"}, - {32731, "PCS_WGS84_UTM_zone_31S"}, - {32732, "PCS_WGS84_UTM_zone_32S"}, - {32733, "PCS_WGS84_UTM_zone_33S"}, - {32734, "PCS_WGS84_UTM_zone_34S"}, - {32735, "PCS_WGS84_UTM_zone_35S"}, - {32736, "PCS_WGS84_UTM_zone_36S"}, - {32737, "PCS_WGS84_UTM_zone_37S"}, - {32738, "PCS_WGS84_UTM_zone_38S"}, - {32739, "PCS_WGS84_UTM_zone_39S"}, - {32740, "PCS_WGS84_UTM_zone_40S"}, - {32741, "PCS_WGS84_UTM_zone_41S"}, - {32742, "PCS_WGS84_UTM_zone_42S"}, - {32743, "PCS_WGS84_UTM_zone_43S"}, - {32744, "PCS_WGS84_UTM_zone_44S"}, - {32745, "PCS_WGS84_UTM_zone_45S"}, - {32746, "PCS_WGS84_UTM_zone_46S"}, - {32747, "PCS_WGS84_UTM_zone_47S"}, - {32748, "PCS_WGS84_UTM_zone_48S"}, - {32749, "PCS_WGS84_UTM_zone_49S"}, - {32750, "PCS_WGS84_UTM_zone_50S"}, - {32751, "PCS_WGS84_UTM_zone_51S"}, - {32752, "PCS_WGS84_UTM_zone_52S"}, - {32753, "PCS_WGS84_UTM_zone_53S"}, - {32754, "PCS_WGS84_UTM_zone_54S"}, - {32755, "PCS_WGS84_UTM_zone_55S"}, - {32756, "PCS_WGS84_UTM_zone_56S"}, - {32757, "PCS_WGS84_UTM_zone_57S"}, - {32758, "PCS_WGS84_UTM_zone_58S"}, - {32759, "PCS_WGS84_UTM_zone_59S"}, - {32760, "PCS_WGS84_UTM_zone_60S"} -}; - -const TiffGeoTagKeyName ff_tiff_projection_codes[] = { - {10101, "Proj_Alabama_CS27_East"}, - {10102, "Proj_Alabama_CS27_West"}, - {10131, "Proj_Alabama_CS83_East"}, - {10132, "Proj_Alabama_CS83_West"}, - {10201, "Proj_Arizona_Coordinate_System_east"}, - {10202, "Proj_Arizona_Coordinate_System_Central"}, - {10203, "Proj_Arizona_Coordinate_System_west"}, - {10231, "Proj_Arizona_CS83_east"}, - {10232, "Proj_Arizona_CS83_Central"}, - {10233, "Proj_Arizona_CS83_west"}, - {10301, "Proj_Arkansas_CS27_North"}, - {10302, "Proj_Arkansas_CS27_South"}, - {10331, "Proj_Arkansas_CS83_North"}, - {10332, "Proj_Arkansas_CS83_South"}, - {10401, "Proj_California_CS27_I"}, - {10402, "Proj_California_CS27_II"}, - {10403, "Proj_California_CS27_III"}, - {10404, "Proj_California_CS27_IV"}, - {10405, "Proj_California_CS27_V"}, - {10406, "Proj_California_CS27_VI"}, - {10407, "Proj_California_CS27_VII"}, - {10431, "Proj_California_CS83_1"}, - {10432, "Proj_California_CS83_2"}, - {10433, "Proj_California_CS83_3"}, - {10434, "Proj_California_CS83_4"}, - {10435, "Proj_California_CS83_5"}, - {10436, "Proj_California_CS83_6"}, - {10501, "Proj_Colorado_CS27_North"}, - {10502, "Proj_Colorado_CS27_Central"}, - {10503, "Proj_Colorado_CS27_South"}, - {10531, "Proj_Colorado_CS83_North"}, - {10532, "Proj_Colorado_CS83_Central"}, - {10533, "Proj_Colorado_CS83_South"}, - {10600, "Proj_Connecticut_CS27"}, - {10630, "Proj_Connecticut_CS83"}, - {10700, "Proj_Delaware_CS27"}, - {10730, "Proj_Delaware_CS83"}, - {10901, "Proj_Florida_CS27_East"}, - {10902, "Proj_Florida_CS27_West"}, - {10903, "Proj_Florida_CS27_North"}, - {10931, "Proj_Florida_CS83_East"}, - {10932, "Proj_Florida_CS83_West"}, - {10933, "Proj_Florida_CS83_North"}, - {11001, "Proj_Georgia_CS27_East"}, - {11002, "Proj_Georgia_CS27_West"}, - {11031, "Proj_Georgia_CS83_East"}, - {11032, "Proj_Georgia_CS83_West"}, - {11101, "Proj_Idaho_CS27_East"}, - {11102, "Proj_Idaho_CS27_Central"}, - {11103, "Proj_Idaho_CS27_West"}, - {11131, "Proj_Idaho_CS83_East"}, - {11132, "Proj_Idaho_CS83_Central"}, - {11133, "Proj_Idaho_CS83_West"}, - {11201, "Proj_Illinois_CS27_East"}, - {11202, "Proj_Illinois_CS27_West"}, - {11231, "Proj_Illinois_CS83_East"}, - {11232, "Proj_Illinois_CS83_West"}, - {11301, "Proj_Indiana_CS27_East"}, - {11302, "Proj_Indiana_CS27_West"}, - {11331, "Proj_Indiana_CS83_East"}, - {11332, "Proj_Indiana_CS83_West"}, - {11401, "Proj_Iowa_CS27_North"}, - {11402, "Proj_Iowa_CS27_South"}, - {11431, "Proj_Iowa_CS83_North"}, - {11432, "Proj_Iowa_CS83_South"}, - {11501, "Proj_Kansas_CS27_North"}, - {11502, "Proj_Kansas_CS27_South"}, - {11531, "Proj_Kansas_CS83_North"}, - {11532, "Proj_Kansas_CS83_South"}, - {11601, "Proj_Kentucky_CS27_North"}, - {11602, "Proj_Kentucky_CS27_South"}, - {11631, "Proj_Kentucky_CS83_North"}, - {11632, "Proj_Kentucky_CS83_South"}, - {11701, "Proj_Louisiana_CS27_North"}, - {11702, "Proj_Louisiana_CS27_South"}, - {11731, "Proj_Louisiana_CS83_North"}, - {11732, "Proj_Louisiana_CS83_South"}, - {11801, "Proj_Maine_CS27_East"}, - {11802, "Proj_Maine_CS27_West"}, - {11831, "Proj_Maine_CS83_East"}, - {11832, "Proj_Maine_CS83_West"}, - {11900, "Proj_Maryland_CS27"}, - {11930, "Proj_Maryland_CS83"}, - {12001, "Proj_Massachusetts_CS27_Mainland"}, - {12002, "Proj_Massachusetts_CS27_Island"}, - {12031, "Proj_Massachusetts_CS83_Mainland"}, - {12032, "Proj_Massachusetts_CS83_Island"}, - {12101, "Proj_Michigan_State_Plane_East"}, - {12102, "Proj_Michigan_State_Plane_Old_Central"}, - {12103, "Proj_Michigan_State_Plane_West"}, - {12111, "Proj_Michigan_CS27_North"}, - {12112, "Proj_Michigan_CS27_Central"}, - {12113, "Proj_Michigan_CS27_South"}, - {12141, "Proj_Michigan_CS83_North"}, - {12142, "Proj_Michigan_CS83_Central"}, - {12143, "Proj_Michigan_CS83_South"}, - {12201, "Proj_Minnesota_CS27_North"}, - {12202, "Proj_Minnesota_CS27_Central"}, - {12203, "Proj_Minnesota_CS27_South"}, - {12231, "Proj_Minnesota_CS83_North"}, - {12232, "Proj_Minnesota_CS83_Central"}, - {12233, "Proj_Minnesota_CS83_South"}, - {12301, "Proj_Mississippi_CS27_East"}, - {12302, "Proj_Mississippi_CS27_West"}, - {12331, "Proj_Mississippi_CS83_East"}, - {12332, "Proj_Mississippi_CS83_West"}, - {12401, "Proj_Missouri_CS27_East"}, - {12402, "Proj_Missouri_CS27_Central"}, - {12403, "Proj_Missouri_CS27_West"}, - {12431, "Proj_Missouri_CS83_East"}, - {12432, "Proj_Missouri_CS83_Central"}, - {12433, "Proj_Missouri_CS83_West"}, - {12501, "Proj_Montana_CS27_North"}, - {12502, "Proj_Montana_CS27_Central"}, - {12503, "Proj_Montana_CS27_South"}, - {12530, "Proj_Montana_CS83"}, - {12601, "Proj_Nebraska_CS27_North"}, - {12602, "Proj_Nebraska_CS27_South"}, - {12630, "Proj_Nebraska_CS83"}, - {12701, "Proj_Nevada_CS27_East"}, - {12702, "Proj_Nevada_CS27_Central"}, - {12703, "Proj_Nevada_CS27_West"}, - {12731, "Proj_Nevada_CS83_East"}, - {12732, "Proj_Nevada_CS83_Central"}, - {12733, "Proj_Nevada_CS83_West"}, - {12800, "Proj_New_Hampshire_CS27"}, - {12830, "Proj_New_Hampshire_CS83"}, - {12900, "Proj_New_Jersey_CS27"}, - {12930, "Proj_New_Jersey_CS83"}, - {13001, "Proj_New_Mexico_CS27_East"}, - {13002, "Proj_New_Mexico_CS27_Central"}, - {13003, "Proj_New_Mexico_CS27_West"}, - {13031, "Proj_New_Mexico_CS83_East"}, - {13032, "Proj_New_Mexico_CS83_Central"}, - {13033, "Proj_New_Mexico_CS83_West"}, - {13101, "Proj_New_York_CS27_East"}, - {13102, "Proj_New_York_CS27_Central"}, - {13103, "Proj_New_York_CS27_West"}, - {13104, "Proj_New_York_CS27_Long_Island"}, - {13131, "Proj_New_York_CS83_East"}, - {13132, "Proj_New_York_CS83_Central"}, - {13133, "Proj_New_York_CS83_West"}, - {13134, "Proj_New_York_CS83_Long_Island"}, - {13200, "Proj_North_Carolina_CS27"}, - {13230, "Proj_North_Carolina_CS83"}, - {13301, "Proj_North_Dakota_CS27_North"}, - {13302, "Proj_North_Dakota_CS27_South"}, - {13331, "Proj_North_Dakota_CS83_North"}, - {13332, "Proj_North_Dakota_CS83_South"}, - {13401, "Proj_Ohio_CS27_North"}, - {13402, "Proj_Ohio_CS27_South"}, - {13431, "Proj_Ohio_CS83_North"}, - {13432, "Proj_Ohio_CS83_South"}, - {13501, "Proj_Oklahoma_CS27_North"}, - {13502, "Proj_Oklahoma_CS27_South"}, - {13531, "Proj_Oklahoma_CS83_North"}, - {13532, "Proj_Oklahoma_CS83_South"}, - {13601, "Proj_Oregon_CS27_North"}, - {13602, "Proj_Oregon_CS27_South"}, - {13631, "Proj_Oregon_CS83_North"}, - {13632, "Proj_Oregon_CS83_South"}, - {13701, "Proj_Pennsylvania_CS27_North"}, - {13702, "Proj_Pennsylvania_CS27_South"}, - {13731, "Proj_Pennsylvania_CS83_North"}, - {13732, "Proj_Pennsylvania_CS83_South"}, - {13800, "Proj_Rhode_Island_CS27"}, - {13830, "Proj_Rhode_Island_CS83"}, - {13901, "Proj_South_Carolina_CS27_North"}, - {13902, "Proj_South_Carolina_CS27_South"}, - {13930, "Proj_South_Carolina_CS83"}, - {14001, "Proj_South_Dakota_CS27_North"}, - {14002, "Proj_South_Dakota_CS27_South"}, - {14031, "Proj_South_Dakota_CS83_North"}, - {14032, "Proj_South_Dakota_CS83_South"}, - {14100, "Proj_Tennessee_CS27"}, - {14130, "Proj_Tennessee_CS83"}, - {14201, "Proj_Texas_CS27_North"}, - {14202, "Proj_Texas_CS27_North_Central"}, - {14203, "Proj_Texas_CS27_Central"}, - {14204, "Proj_Texas_CS27_South_Central"}, - {14205, "Proj_Texas_CS27_South"}, - {14231, "Proj_Texas_CS83_North"}, - {14232, "Proj_Texas_CS83_North_Central"}, - {14233, "Proj_Texas_CS83_Central"}, - {14234, "Proj_Texas_CS83_South_Central"}, - {14235, "Proj_Texas_CS83_South"}, - {14301, "Proj_Utah_CS27_North"}, - {14302, "Proj_Utah_CS27_Central"}, - {14303, "Proj_Utah_CS27_South"}, - {14331, "Proj_Utah_CS83_North"}, - {14332, "Proj_Utah_CS83_Central"}, - {14333, "Proj_Utah_CS83_South"}, - {14400, "Proj_Vermont_CS27"}, - {14430, "Proj_Vermont_CS83"}, - {14501, "Proj_Virginia_CS27_North"}, - {14502, "Proj_Virginia_CS27_South"}, - {14531, "Proj_Virginia_CS83_North"}, - {14532, "Proj_Virginia_CS83_South"}, - {14601, "Proj_Washington_CS27_North"}, - {14602, "Proj_Washington_CS27_South"}, - {14631, "Proj_Washington_CS83_North"}, - {14632, "Proj_Washington_CS83_South"}, - {14701, "Proj_West_Virginia_CS27_North"}, - {14702, "Proj_West_Virginia_CS27_South"}, - {14731, "Proj_West_Virginia_CS83_North"}, - {14732, "Proj_West_Virginia_CS83_South"}, - {14801, "Proj_Wisconsin_CS27_North"}, - {14802, "Proj_Wisconsin_CS27_Central"}, - {14803, "Proj_Wisconsin_CS27_South"}, - {14831, "Proj_Wisconsin_CS83_North"}, - {14832, "Proj_Wisconsin_CS83_Central"}, - {14833, "Proj_Wisconsin_CS83_South"}, - {14901, "Proj_Wyoming_CS27_East"}, - {14902, "Proj_Wyoming_CS27_East_Central"}, - {14903, "Proj_Wyoming_CS27_West_Central"}, - {14904, "Proj_Wyoming_CS27_West"}, - {14931, "Proj_Wyoming_CS83_East"}, - {14932, "Proj_Wyoming_CS83_East_Central"}, - {14933, "Proj_Wyoming_CS83_West_Central"}, - {14934, "Proj_Wyoming_CS83_West"}, - {15001, "Proj_Alaska_CS27_1"}, - {15002, "Proj_Alaska_CS27_2"}, - {15003, "Proj_Alaska_CS27_3"}, - {15004, "Proj_Alaska_CS27_4"}, - {15005, "Proj_Alaska_CS27_5"}, - {15006, "Proj_Alaska_CS27_6"}, - {15007, "Proj_Alaska_CS27_7"}, - {15008, "Proj_Alaska_CS27_8"}, - {15009, "Proj_Alaska_CS27_9"}, - {15010, "Proj_Alaska_CS27_10"}, - {15031, "Proj_Alaska_CS83_1"}, - {15032, "Proj_Alaska_CS83_2"}, - {15033, "Proj_Alaska_CS83_3"}, - {15034, "Proj_Alaska_CS83_4"}, - {15035, "Proj_Alaska_CS83_5"}, - {15036, "Proj_Alaska_CS83_6"}, - {15037, "Proj_Alaska_CS83_7"}, - {15038, "Proj_Alaska_CS83_8"}, - {15039, "Proj_Alaska_CS83_9"}, - {15040, "Proj_Alaska_CS83_10"}, - {15101, "Proj_Hawaii_CS27_1"}, - {15102, "Proj_Hawaii_CS27_2"}, - {15103, "Proj_Hawaii_CS27_3"}, - {15104, "Proj_Hawaii_CS27_4"}, - {15105, "Proj_Hawaii_CS27_5"}, - {15131, "Proj_Hawaii_CS83_1"}, - {15132, "Proj_Hawaii_CS83_2"}, - {15133, "Proj_Hawaii_CS83_3"}, - {15134, "Proj_Hawaii_CS83_4"}, - {15135, "Proj_Hawaii_CS83_5"}, - {15201, "Proj_Puerto_Rico_CS27"}, - {15202, "Proj_St_Croix"}, - {15230, "Proj_Puerto_Rico_Virgin_Is"}, - {15914, "Proj_BLM_14N_feet"}, - {15915, "Proj_BLM_15N_feet"}, - {15916, "Proj_BLM_16N_feet"}, - {15917, "Proj_BLM_17N_feet"}, - {17348, "Proj_Map_Grid_of_Australia_48"}, - {17349, "Proj_Map_Grid_of_Australia_49"}, - {17350, "Proj_Map_Grid_of_Australia_50"}, - {17351, "Proj_Map_Grid_of_Australia_51"}, - {17352, "Proj_Map_Grid_of_Australia_52"}, - {17353, "Proj_Map_Grid_of_Australia_53"}, - {17354, "Proj_Map_Grid_of_Australia_54"}, - {17355, "Proj_Map_Grid_of_Australia_55"}, - {17356, "Proj_Map_Grid_of_Australia_56"}, - {17357, "Proj_Map_Grid_of_Australia_57"}, - {17358, "Proj_Map_Grid_of_Australia_58"}, - {17448, "Proj_Australian_Map_Grid_48"}, - {17449, "Proj_Australian_Map_Grid_49"}, - {17450, "Proj_Australian_Map_Grid_50"}, - {17451, "Proj_Australian_Map_Grid_51"}, - {17452, "Proj_Australian_Map_Grid_52"}, - {17453, "Proj_Australian_Map_Grid_53"}, - {17454, "Proj_Australian_Map_Grid_54"}, - {17455, "Proj_Australian_Map_Grid_55"}, - {17456, "Proj_Australian_Map_Grid_56"}, - {17457, "Proj_Australian_Map_Grid_57"}, - {17458, "Proj_Australian_Map_Grid_58"}, - {18031, "Proj_Argentina_1"}, - {18032, "Proj_Argentina_2"}, - {18033, "Proj_Argentina_3"}, - {18034, "Proj_Argentina_4"}, - {18035, "Proj_Argentina_5"}, - {18036, "Proj_Argentina_6"}, - {18037, "Proj_Argentina_7"}, - {18051, "Proj_Colombia_3W"}, - {18052, "Proj_Colombia_Bogota"}, - {18053, "Proj_Colombia_3E"}, - {18054, "Proj_Colombia_6E"}, - {18072, "Proj_Egypt_Red_Belt"}, - {18073, "Proj_Egypt_Purple_Belt"}, - {18074, "Proj_Extended_Purple_Belt"}, - {18141, "Proj_New_Zealand_North_Island_Nat_Grid"}, - {18142, "Proj_New_Zealand_South_Island_Nat_Grid"}, - {19900, "Proj_Bahrain_Grid"}, - {19905, "Proj_Netherlands_E_Indies_Equatorial"}, - {19912, "Proj_RSO_Borneo"} -}; - -const char *const ff_tiff_coord_trans_codes[] = { - "CT_TransverseMercator", - "CT_TransvMercator_Modified_Alaska", - "CT_ObliqueMercator", - "CT_ObliqueMercator_Laborde", - "CT_ObliqueMercator_Rosenmund", - "CT_ObliqueMercator_Spherical", - "CT_Mercator", - "CT_LambertConfConic_2SP", - "CT_LambertConfConic_Helmert", - "CT_LambertAzimEqualArea", - "CT_AlbersEqualArea", - "CT_AzimuthalEquidistant", - "CT_EquidistantConic", - "CT_Stereographic", - "CT_PolarStereographic", - "CT_ObliqueStereographic", - "CT_Equirectangular", - "CT_CassiniSoldner", - "CT_Gnomonic", - "CT_MillerCylindrical", - "CT_Orthographic", - "CT_Polyconic", - "CT_Robinson", - "CT_Sinusoidal", - "CT_VanDerGrinten", - "CT_NewZealandMapGrid", - "CT_TransvMercator_SouthOriented" -}; - -const char *const ff_tiff_vert_cs_codes[] = { - "VertCS_Airy_1830_ellipsoid", - "VertCS_Airy_Modified_1849_ellipsoid", - "VertCS_ANS_ellipsoid", - "VertCS_Bessel_1841_ellipsoid", - "VertCS_Bessel_Modified_ellipsoid", - "VertCS_Bessel_Namibia_ellipsoid", - "VertCS_Clarke_1858_ellipsoid", - "VertCS_Clarke_1866_ellipsoid", - "VertCS_Clarke_1880_Benoit_ellipsoid", - "VertCS_Clarke_1880_IGN_ellipsoid", - "VertCS_Clarke_1880_RGS_ellipsoid", - "VertCS_Clarke_1880_Arc_ellipsoid", - "VertCS_Clarke_1880_SGA_1922_ellipsoid", - "VertCS_Everest_1830_1937_Adjustment_ellipsoid", - "VertCS_Everest_1830_1967_Definition_ellipsoid", - "VertCS_Everest_1830_1975_Definition_ellipsoid", - "VertCS_Everest_1830_Modified_ellipsoid", - "VertCS_GRS_1980_ellipsoid", - "VertCS_Helmert_1906_ellipsoid", - "VertCS_INS_ellipsoid", - "VertCS_International_1924_ellipsoid", - "VertCS_International_1967_ellipsoid", - "VertCS_Krassowsky_1940_ellipsoid", - "VertCS_NWL_9D_ellipsoid", - "VertCS_NWL_10D_ellipsoid", - "VertCS_Plessis_1817_ellipsoid", - "VertCS_Struve_1860_ellipsoid", - "VertCS_War_Office_ellipsoid", - "VertCS_WGS_84_ellipsoid", - "VertCS_GEM_10C_ellipsoid", - "VertCS_OSU86F_ellipsoid", - "VertCS_OSU91A_ellipsoid" -}; - -const char *const ff_tiff_ortho_vert_cs_codes[] = { - "VertCS_Newlyn", - "VertCS_North_American_Vertical_Datum_1929", - "VertCS_North_American_Vertical_Datum_1988", - "VertCS_Yellow_Sea_1956", - "VertCS_Baltic_Sea", - "VertCS_Caspian_Sea" -}; diff -Nru ffmpeg-4.2.2/libavcodec/tiff_data.h ffmpeg-4.4/libavcodec/tiff_data.h --- ffmpeg-4.2.2/libavcodec/tiff_data.h 2016-03-29 02:25:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tiff_data.h 2021-04-08 21:28:39.000000000 +0000 @@ -33,60 +33,1863 @@ #include "tiff.h" #define TIFF_CONF_KEY_ID_OFFSET 1024 -extern const TiffGeoTagNameType ff_tiff_conf_name_type_map[3]; +static const TiffGeoTagNameType tiff_conf_name_type_map[] = { + {"GTModelTypeGeoKey", GEOTIFF_SHORT }, + {"GTRasterTypeGeoKey", GEOTIFF_SHORT }, + {"GTCitationGeoKey", GEOTIFF_STRING} +}; #define TIFF_GEOG_KEY_ID_OFFSET 2048 -extern const TiffGeoTagNameType ff_tiff_geog_name_type_map[14]; +static const TiffGeoTagNameType tiff_geog_name_type_map[] = { + {"GeographicTypeGeoKey", GEOTIFF_SHORT }, + {"GeogCitationGeoKey", GEOTIFF_STRING}, + {"GeogGeodeticDatumGeoKey", GEOTIFF_SHORT }, + {"GeogPrimeMeridianGeoKey", GEOTIFF_SHORT }, + {"GeogLinearUnitsGeoKey", GEOTIFF_SHORT }, + {"GeogLinearUnitSizeGeoKey", GEOTIFF_DOUBLE}, + {"GeogAngularUnitsGeoKey", GEOTIFF_SHORT }, + {"GeogAngularUnitSizeGeoKey", GEOTIFF_DOUBLE}, + {"GeogEllipsoidGeoKey", GEOTIFF_SHORT }, + {"GeogSemiMajorAxisGeoKey", GEOTIFF_DOUBLE}, + {"GeogSemiMinorAxisGeoKey", GEOTIFF_DOUBLE}, + {"GeogInvFlatteningGeoKey", GEOTIFF_DOUBLE}, + {"GeogAzimuthUnitsGeoKey", GEOTIFF_SHORT }, + {"GeogPrimeMeridianLongGeoKey", GEOTIFF_DOUBLE} +}; #define TIFF_PROJ_KEY_ID_OFFSET 3072 -extern const TiffGeoTagNameType ff_tiff_proj_name_type_map[24]; +static const TiffGeoTagNameType tiff_proj_name_type_map[] = { + {"ProjectedCSTypeGeoKey", GEOTIFF_SHORT }, + {"PCSCitationGeoKey", GEOTIFF_STRING}, + {"ProjectionGeoKey", GEOTIFF_SHORT }, + {"ProjCoordTransGeoKey", GEOTIFF_SHORT }, + {"ProjLinearUnitsGeoKey", GEOTIFF_SHORT }, + {"ProjLinearUnitSizeGeoKey", GEOTIFF_DOUBLE}, + {"ProjStdParallel1GeoKey", GEOTIFF_DOUBLE}, + {"ProjStdParallel2GeoKey", GEOTIFF_DOUBLE}, + {"ProjNatOriginLongGeoKey", GEOTIFF_DOUBLE}, + {"ProjNatOriginLatGeoKey", GEOTIFF_DOUBLE}, + {"ProjFalseEastingGeoKey", GEOTIFF_DOUBLE}, + {"ProjFalseNorthingGeoKey", GEOTIFF_DOUBLE}, + {"ProjFalseOriginLongGeoKey", GEOTIFF_DOUBLE}, + {"ProjFalseOriginLatGeoKey", GEOTIFF_DOUBLE}, + {"ProjFalseOriginEastingGeoKey", GEOTIFF_DOUBLE}, + {"ProjFalseOriginNorthingGeoKey", GEOTIFF_DOUBLE}, + {"ProjCenterLongGeoKey", GEOTIFF_DOUBLE}, + {"ProjCenterLatGeoKey", GEOTIFF_DOUBLE}, + {"ProjCenterEastingGeoKey", GEOTIFF_DOUBLE}, + {"ProjCenterNorthingGeoKey", GEOTIFF_DOUBLE}, + {"ProjScaleAtNatOriginGeoKey", GEOTIFF_DOUBLE}, + {"ProjScaleAtCenterGeoKey", GEOTIFF_DOUBLE}, + {"ProjAzimuthAngleGeoKey", GEOTIFF_DOUBLE}, + {"ProjStraightVertPoleLongGeoKey", GEOTIFF_DOUBLE} +}; #define TIFF_VERT_KEY_ID_OFFSET 4096 -extern const TiffGeoTagNameType ff_tiff_vert_name_type_map[4]; +static const TiffGeoTagNameType tiff_vert_name_type_map[] = { + {"VerticalCSTypeGeoKey", GEOTIFF_SHORT }, + {"VerticalCitationGeoKey", GEOTIFF_STRING}, + {"VerticalDatumGeoKey", GEOTIFF_SHORT }, + {"VerticalUnitsGeoKey", GEOTIFF_SHORT } +}; #define TIFF_GEO_KEY_UNDEFINED 0 #define TIFF_GEO_KEY_USER_DEFINED 32767 #define TIFF_GT_MODEL_TYPE_OFFSET 1 -extern const char *const ff_tiff_gt_model_type_codes[3]; +static const char *const tiff_gt_model_type_codes[] = { + "ModelTypeProjected", + "ModelTypeGeographic", + "ModelTypeGeocentric" +}; #define TIFF_GT_RASTER_TYPE_OFFSET 1 -extern const char *const ff_tiff_gt_raster_type_codes[2]; +static const char *const tiff_gt_raster_type_codes[] = { + "RasterPixelIsArea", + "RasterPixelIsPoint" +}; #define TIFF_LINEAR_UNIT_OFFSET 9001 -extern const char *const ff_tiff_linear_unit_codes[15]; +static const char *const tiff_linear_unit_codes[] = { + "Linear_Meter", + "Linear_Foot", + "Linear_Foot_US_Survey", + "Linear_Foot_Modified_American", + "Linear_Foot_Clarke", + "Linear_Foot_Indian", + "Linear_Link", + "Linear_Link_Benoit", + "Linear_Link_Sears", + "Linear_Chain_Benoit", + "Linear_Chain_Sears", + "Linear_Yard_Sears", + "Linear_Yard_Indian", + "Linear_Fathom", + "Linear_Mile_International_Nautical" +}; #define TIFF_ANGULAR_UNIT_OFFSET 9101 -extern const char *const ff_tiff_angular_unit_codes[8]; +static const char *const tiff_angular_unit_codes[] = { + "Angular_Radian", + "Angular_Degree", + "Angular_Arc_Minute", + "Angular_Arc_Second", + "Angular_Grad", + "Angular_Gon", + "Angular_DMS", + "Angular_DMS_Hemisphere" +}; #define TIFF_GCS_TYPE_OFFSET 4201 -extern const char *const ff_tiff_gcs_type_codes[133]; +static const char *const tiff_gcs_type_codes[] = { + "GCS_Adindan", + "GCS_AGD66", + "GCS_AGD84", + "GCS_Ain_el_Abd", + "GCS_Afgooye", + "GCS_Agadez", + "GCS_Lisbon", + "GCS_Aratu", + "GCS_Arc_1950", + "GCS_Arc_1960", + "GCS_Batavia", + "GCS_Barbados", + "GCS_Beduaram", + "GCS_Beijing_1954", + "GCS_Belge_1950", + "GCS_Bermuda_1957", + "GCS_Bern_1898", + "GCS_Bogota", + "GCS_Bukit_Rimpah", + "GCS_Camacupa", + "GCS_Campo_Inchauspe", + "GCS_Cape", + "GCS_Carthage", + "GCS_Chua", + "GCS_Corrego_Alegre", + "GCS_Cote_d_Ivoire", + "GCS_Deir_ez_Zor", + "GCS_Douala", + "GCS_Egypt_1907", + "GCS_ED50", + "GCS_ED87", + "GCS_Fahud", + "GCS_Gandajika_1970", + "GCS_Garoua", + "GCS_Guyane_Francaise", + "GCS_Hu_Tzu_Shan", + "GCS_HD72", + "GCS_ID74", + "GCS_Indian_1954", + "GCS_Indian_1975", + "GCS_Jamaica_1875", + "GCS_JAD69", + "GCS_Kalianpur", + "GCS_Kandawala", + "GCS_Kertau", + "GCS_KOC", + "GCS_La_Canoa", + "GCS_PSAD56", + "GCS_Lake", + "GCS_Leigon", + "GCS_Liberia_1964", + "GCS_Lome", + "GCS_Luzon_1911", + "GCS_Hito_XVIII_1963", + "GCS_Herat_North", + "GCS_Mahe_1971", + "GCS_Makassar", + "GCS_EUREF89", + "GCS_Malongo_1987", + "GCS_Manoca", + "GCS_Merchich", + "GCS_Massawa", + "GCS_Minna", + "GCS_Mhast", + "GCS_Monte_Mario", + "GCS_M_poraloko", + "GCS_NAD27", + "GCS_NAD_Michigan", + "GCS_NAD83", + "GCS_Nahrwan_1967", + "GCS_Naparima_1972", + "GCS_GD49", + "GCS_NGO_1948", + "GCS_Datum_73", + "GCS_NTF", + "GCS_NSWC_9Z_2", + "GCS_OSGB_1936", + "GCS_OSGB70", + "GCS_OS_SN80", + "GCS_Padang", + "GCS_Palestine_1923", + "GCS_Pointe_Noire", + "GCS_GDA94", + "GCS_Pulkovo_1942", + "GCS_Qatar", + "GCS_Qatar_1948", + "GCS_Qornoq", + "GCS_Loma_Quintana", + "GCS_Amersfoort", + "GCS_RT38", + "GCS_SAD69", + "GCS_Sapper_Hill_1943", + "GCS_Schwarzeck", + "GCS_Segora", + "GCS_Serindung", + "GCS_Sudan", + "GCS_Tananarive", + "GCS_Timbalai_1948", + "GCS_TM65", + "GCS_TM75", + "GCS_Tokyo", + "GCS_Trinidad_1903", + "GCS_TC_1948", + "GCS_Voirol_1875", + "GCS_Voirol_Unifie", + "GCS_Bern_1938", + "GCS_Nord_Sahara_1959", + "GCS_Stockholm_1938", + "GCS_Yacare", + "GCS_Yoff", + "GCS_Zanderij", + "GCS_MGI", + "GCS_Belge_1972", + "GCS_DHDN", + "GCS_Conakry_1905", + "GCS_WGS_72", + "GCS_WGS_72BE", + "GCS_WGS_84", + "GCS_Bern_1898_Bern", + "GCS_Bogota_Bogota", + "GCS_Lisbon_Lisbon", + "GCS_Makassar_Jakarta", + "GCS_MGI_Ferro", + "GCS_Monte_Mario_Rome", + "GCS_NTF_Paris", + "GCS_Padang_Jakarta", + "GCS_Belge_1950_Brussels", + "GCS_Tananarive_Paris", + "GCS_Voirol_1875_Paris", + "GCS_Voirol_Unifie_Paris", + "GCS_Batavia_Jakarta", + "GCS_ATF_Paris", + "GCS_NDG_Paris" +}; #define TIFF_GCSE_TYPE_OFFSET 4001 -extern const char *const ff_tiff_gcse_type_codes[35]; +static const char *const tiff_gcse_type_codes[] = { + "GCSE_Airy1830", + "GCSE_AiryModified1849", + "GCSE_AustralianNationalSpheroid", + "GCSE_Bessel1841", + "GCSE_BesselModified", + "GCSE_BesselNamibia", + "GCSE_Clarke1858", + "GCSE_Clarke1866", + "GCSE_Clarke1866Michigan", + "GCSE_Clarke1880_Benoit", + "GCSE_Clarke1880_IGN", + "GCSE_Clarke1880_RGS", + "GCSE_Clarke1880_Arc", + "GCSE_Clarke1880_SGA1922", + "GCSE_Everest1830_1937Adjustment", + "GCSE_Everest1830_1967Definition", + "GCSE_Everest1830_1975Definition", + "GCSE_Everest1830Modified", + "GCSE_GRS1980", + "GCSE_Helmert1906", + "GCSE_IndonesianNationalSpheroid", + "GCSE_International1924", + "GCSE_International1967", + "GCSE_Krassowsky1940", + "GCSE_NWL9D", + "GCSE_NWL10D", + "GCSE_Plessis1817", + "GCSE_Struve1860", + "GCSE_WarOffice", + "GCSE_WGS84", + "GCSE_GEM10C", + "GCSE_OSU86F", + "GCSE_OSU91A", + "GCSE_Clarke1880", + "GCSE_Sphere" +}; #define TIFF_GEODETIC_DATUM_OFFSET 6201 -extern const char *const ff_tiff_geodetic_datum_codes[120]; +static const char *const tiff_geodetic_datum_codes[] = { + "Datum_Adindan", + "Datum_Australian_Geodetic_Datum_1966", + "Datum_Australian_Geodetic_Datum_1984", + "Datum_Ain_el_Abd_1970", + "Datum_Afgooye", + "Datum_Agadez", + "Datum_Lisbon", + "Datum_Aratu", + "Datum_Arc_1950", + "Datum_Arc_1960", + "Datum_Batavia", + "Datum_Barbados", + "Datum_Beduaram", + "Datum_Beijing_1954", + "Datum_Reseau_National_Belge_1950", + "Datum_Bermuda_1957", + "Datum_Bern_1898", + "Datum_Bogota", + "Datum_Bukit_Rimpah", + "Datum_Camacupa", + "Datum_Campo_Inchauspe", + "Datum_Cape", + "Datum_Carthage", + "Datum_Chua", + "Datum_Corrego_Alegre", + "Datum_Cote_d_Ivoire", + "Datum_Deir_ez_Zor", + "Datum_Douala", + "Datum_Egypt_1907", + "Datum_European_Datum_1950", + "Datum_European_Datum_1987", + "Datum_Fahud", + "Datum_Gandajika_1970", + "Datum_Garoua", + "Datum_Guyane_Francaise", + "Datum_Hu_Tzu_Shan", + "Datum_Hungarian_Datum_1972", + "Datum_Indonesian_Datum_1974", + "Datum_Indian_1954", + "Datum_Indian_1975", + "Datum_Jamaica_1875", + "Datum_Jamaica_1969", + "Datum_Kalianpur", + "Datum_Kandawala", + "Datum_Kertau", + "Datum_Kuwait_Oil_Company", + "Datum_La_Canoa", + "Datum_Provisional_S_American_Datum_1956", + "Datum_Lake", + "Datum_Leigon", + "Datum_Liberia_1964", + "Datum_Lome", + "Datum_Luzon_1911", + "Datum_Hito_XVIII_1963", + "Datum_Herat_North", + "Datum_Mahe_1971", + "Datum_Makassar", + "Datum_European_Reference_System_1989", + "Datum_Malongo_1987", + "Datum_Manoca", + "Datum_Merchich", + "Datum_Massawa", + "Datum_Minna", + "Datum_Mhast", + "Datum_Monte_Mario", + "Datum_M_poraloko", + "Datum_North_American_Datum_1927", + "Datum_NAD_Michigan", + "Datum_North_American_Datum_1983", + "Datum_Nahrwan_1967", + "Datum_Naparima_1972", + "Datum_New_Zealand_Geodetic_Datum_1949", + "Datum_NGO_1948", + "Datum_Datum_73", + "Datum_Nouvelle_Triangulation_Francaise", + "Datum_NSWC_9Z_2", + "Datum_OSGB_1936", + "Datum_OSGB_1970_SN", + "Datum_OS_SN_1980", + "Datum_Padang_1884", + "Datum_Palestine_1923", + "Datum_Pointe_Noire", + "Datum_Geocentric_Datum_of_Australia_1994", + "Datum_Pulkovo_1942", + "Datum_Qatar", + "Datum_Qatar_1948", + "Datum_Qornoq", + "Datum_Loma_Quintana", + "Datum_Amersfoort", + "Datum_RT38", + "Datum_South_American_Datum_1969", + "Datum_Sapper_Hill_1943", + "Datum_Schwarzeck", + "Datum_Segora", + "Datum_Serindung", + "Datum_Sudan", + "Datum_Tananarive_1925", + "Datum_Timbalai_1948", + "Datum_TM65", + "Datum_TM75", + "Datum_Tokyo", + "Datum_Trinidad_1903", + "Datum_Trucial_Coast_1948", + "Datum_Voirol_1875", + "Datum_Voirol_Unifie_1960", + "Datum_Bern_1938", + "Datum_Nord_Sahara_1959", + "Datum_Stockholm_1938", + "Datum_Yacare", + "Datum_Yoff", + "Datum_Zanderij", + "Datum_Militar_Geographische_Institut", + "Datum_Reseau_National_Belge_1972", + "Datum_Deutsche_Hauptdreiecksnetz", + "Datum_Conakry_1905", + "Datum_WGS72", + "Datum_WGS72_Transit_Broadcast_Ephemeris", + "Datum_WGS84", + "Datum_Ancienne_Triangulation_Francaise", + "Datum_Nord_de_Guerre" +}; #define TIFF_GEODETIC_DATUM_E_OFFSET 6001 -extern const char *const ff_tiff_geodetic_datum_e_codes[35]; +static const char *const tiff_geodetic_datum_e_codes[] = { + "DatumE_Airy1830", + "DatumE_AiryModified1849", + "DatumE_AustralianNationalSpheroid", + "DatumE_Bessel1841", + "DatumE_BesselModified", + "DatumE_BesselNamibia", + "DatumE_Clarke1858", + "DatumE_Clarke1866", + "DatumE_Clarke1866Michigan", + "DatumE_Clarke1880_Benoit", + "DatumE_Clarke1880_IGN", + "DatumE_Clarke1880_RGS", + "DatumE_Clarke1880_Arc", + "DatumE_Clarke1880_SGA1922", + "DatumE_Everest1830_1937Adjustment", + "DatumE_Everest1830_1967Definition", + "DatumE_Everest1830_1975Definition", + "DatumE_Everest1830Modified", + "DatumE_GRS1980", + "DatumE_Helmert1906", + "DatumE_IndonesianNationalSpheroid", + "DatumE_International1924", + "DatumE_International1967", + "DatumE_Krassowsky1960", + "DatumE_NWL9D", + "DatumE_NWL10D", + "DatumE_Plessis1817", + "DatumE_Struve1860", + "DatumE_WarOffice", + "DatumE_WGS84", + "DatumE_GEM10C", + "DatumE_OSU86F", + "DatumE_OSU91A", + "DatumE_Clarke1880", + "DatumE_Sphere" +}; #define TIFF_ELLIPSOID_OFFSET 7001 -extern const char *const ff_tiff_ellipsoid_codes[35]; +static const char *const tiff_ellipsoid_codes[] = { + "Ellipse_Airy_1830", + "Ellipse_Airy_Modified_1849", + "Ellipse_Australian_National_Spheroid", + "Ellipse_Bessel_1841", + "Ellipse_Bessel_Modified", + "Ellipse_Bessel_Namibia", + "Ellipse_Clarke_1858", + "Ellipse_Clarke_1866", + "Ellipse_Clarke_1866_Michigan", + "Ellipse_Clarke_1880_Benoit", + "Ellipse_Clarke_1880_IGN", + "Ellipse_Clarke_1880_RGS", + "Ellipse_Clarke_1880_Arc", + "Ellipse_Clarke_1880_SGA_1922", + "Ellipse_Everest_1830_1937_Adjustment", + "Ellipse_Everest_1830_1967_Definition", + "Ellipse_Everest_1830_1975_Definition", + "Ellipse_Everest_1830_Modified", + "Ellipse_GRS_1980", + "Ellipse_Helmert_1906", + "Ellipse_Indonesian_National_Spheroid", + "Ellipse_International_1924", + "Ellipse_International_1967", + "Ellipse_Krassowsky_1940", + "Ellipse_NWL_9D", + "Ellipse_NWL_10D", + "Ellipse_Plessis_1817", + "Ellipse_Struve_1860", + "Ellipse_War_Office", + "Ellipse_WGS_84", + "Ellipse_GEM_10C", + "Ellipse_OSU86F", + "Ellipse_OSU91A", + "Ellipse_Clarke_1880", + "Ellipse_Sphere" +}; #define TIFF_PRIME_MERIDIAN_OFFSET 8901 -extern const char *const ff_tiff_prime_meridian_codes[11]; +static const char *const tiff_prime_meridian_codes[] = { + "PM_Greenwich", + "PM_Lisbon", + "PM_Paris", + "PM_Bogota", + "PM_Madrid", + "PM_Rome", + "PM_Bern", + "PM_Jakarta", + "PM_Ferro", + "PM_Brussels", + "PM_Stockholm" +}; -extern const TiffGeoTagKeyName ff_tiff_proj_cs_type_codes[978]; +static const TiffGeoTagKeyName tiff_proj_cs_type_codes[] = { + {20137, "PCS_Adindan_UTM_zone_37N"}, + {20138, "PCS_Adindan_UTM_zone_38N"}, + {20248, "PCS_AGD66_AMG_zone_48"}, + {20249, "PCS_AGD66_AMG_zone_49"}, + {20250, "PCS_AGD66_AMG_zone_50"}, + {20251, "PCS_AGD66_AMG_zone_51"}, + {20252, "PCS_AGD66_AMG_zone_52"}, + {20253, "PCS_AGD66_AMG_zone_53"}, + {20254, "PCS_AGD66_AMG_zone_54"}, + {20255, "PCS_AGD66_AMG_zone_55"}, + {20256, "PCS_AGD66_AMG_zone_56"}, + {20257, "PCS_AGD66_AMG_zone_57"}, + {20258, "PCS_AGD66_AMG_zone_58"}, + {20348, "PCS_AGD84_AMG_zone_48"}, + {20349, "PCS_AGD84_AMG_zone_49"}, + {20350, "PCS_AGD84_AMG_zone_50"}, + {20351, "PCS_AGD84_AMG_zone_51"}, + {20352, "PCS_AGD84_AMG_zone_52"}, + {20353, "PCS_AGD84_AMG_zone_53"}, + {20354, "PCS_AGD84_AMG_zone_54"}, + {20355, "PCS_AGD84_AMG_zone_55"}, + {20356, "PCS_AGD84_AMG_zone_56"}, + {20357, "PCS_AGD84_AMG_zone_57"}, + {20358, "PCS_AGD84_AMG_zone_58"}, + {20437, "PCS_Ain_el_Abd_UTM_zone_37N"}, + {20438, "PCS_Ain_el_Abd_UTM_zone_38N"}, + {20439, "PCS_Ain_el_Abd_UTM_zone_39N"}, + {20499, "PCS_Ain_el_Abd_Bahrain_Grid"}, + {20538, "PCS_Afgooye_UTM_zone_38N"}, + {20539, "PCS_Afgooye_UTM_zone_39N"}, + {20700, "PCS_Lisbon_Portugese_Grid"}, + {20822, "PCS_Aratu_UTM_zone_22S"}, + {20823, "PCS_Aratu_UTM_zone_23S"}, + {20824, "PCS_Aratu_UTM_zone_24S"}, + {20973, "PCS_Arc_1950_Lo13"}, + {20975, "PCS_Arc_1950_Lo15"}, + {20977, "PCS_Arc_1950_Lo17"}, + {20979, "PCS_Arc_1950_Lo19"}, + {20981, "PCS_Arc_1950_Lo21"}, + {20983, "PCS_Arc_1950_Lo23"}, + {20985, "PCS_Arc_1950_Lo25"}, + {20987, "PCS_Arc_1950_Lo27"}, + {20989, "PCS_Arc_1950_Lo29"}, + {20991, "PCS_Arc_1950_Lo31"}, + {20993, "PCS_Arc_1950_Lo33"}, + {20995, "PCS_Arc_1950_Lo35"}, + {21100, "PCS_Batavia_NEIEZ"}, + {21148, "PCS_Batavia_UTM_zone_48S"}, + {21149, "PCS_Batavia_UTM_zone_49S"}, + {21150, "PCS_Batavia_UTM_zone_50S"}, + {21413, "PCS_Beijing_Gauss_zone_13"}, + {21414, "PCS_Beijing_Gauss_zone_14"}, + {21415, "PCS_Beijing_Gauss_zone_15"}, + {21416, "PCS_Beijing_Gauss_zone_16"}, + {21417, "PCS_Beijing_Gauss_zone_17"}, + {21418, "PCS_Beijing_Gauss_zone_18"}, + {21419, "PCS_Beijing_Gauss_zone_19"}, + {21420, "PCS_Beijing_Gauss_zone_20"}, + {21421, "PCS_Beijing_Gauss_zone_21"}, + {21422, "PCS_Beijing_Gauss_zone_22"}, + {21423, "PCS_Beijing_Gauss_zone_23"}, + {21473, "PCS_Beijing_Gauss_13N"}, + {21474, "PCS_Beijing_Gauss_14N"}, + {21475, "PCS_Beijing_Gauss_15N"}, + {21476, "PCS_Beijing_Gauss_16N"}, + {21477, "PCS_Beijing_Gauss_17N"}, + {21478, "PCS_Beijing_Gauss_18N"}, + {21479, "PCS_Beijing_Gauss_19N"}, + {21480, "PCS_Beijing_Gauss_20N"}, + {21481, "PCS_Beijing_Gauss_21N"}, + {21482, "PCS_Beijing_Gauss_22N"}, + {21483, "PCS_Beijing_Gauss_23N"}, + {21500, "PCS_Belge_Lambert_50"}, + {21790, "PCS_Bern_1898_Swiss_Old"}, + {21817, "PCS_Bogota_UTM_zone_17N"}, + {21818, "PCS_Bogota_UTM_zone_18N"}, + {21891, "PCS_Bogota_Colombia_3W"}, + {21892, "PCS_Bogota_Colombia_Bogota"}, + {21893, "PCS_Bogota_Colombia_3E"}, + {21894, "PCS_Bogota_Colombia_6E"}, + {22032, "PCS_Camacupa_UTM_32S"}, + {22033, "PCS_Camacupa_UTM_33S"}, + {22191, "PCS_C_Inchauspe_Argentina_1"}, + {22192, "PCS_C_Inchauspe_Argentina_2"}, + {22193, "PCS_C_Inchauspe_Argentina_3"}, + {22194, "PCS_C_Inchauspe_Argentina_4"}, + {22195, "PCS_C_Inchauspe_Argentina_5"}, + {22196, "PCS_C_Inchauspe_Argentina_6"}, + {22197, "PCS_C_Inchauspe_Argentina_7"}, + {22332, "PCS_Carthage_UTM_zone_32N"}, + {22391, "PCS_Carthage_Nord_Tunisie"}, + {22392, "PCS_Carthage_Sud_Tunisie"}, + {22523, "PCS_Corrego_Alegre_UTM_23S"}, + {22524, "PCS_Corrego_Alegre_UTM_24S"}, + {22832, "PCS_Douala_UTM_zone_32N"}, + {22992, "PCS_Egypt_1907_Red_Belt"}, + {22993, "PCS_Egypt_1907_Purple_Belt"}, + {22994, "PCS_Egypt_1907_Ext_Purple"}, + {23028, "PCS_ED50_UTM_zone_28N"}, + {23029, "PCS_ED50_UTM_zone_29N"}, + {23030, "PCS_ED50_UTM_zone_30N"}, + {23031, "PCS_ED50_UTM_zone_31N"}, + {23032, "PCS_ED50_UTM_zone_32N"}, + {23033, "PCS_ED50_UTM_zone_33N"}, + {23034, "PCS_ED50_UTM_zone_34N"}, + {23035, "PCS_ED50_UTM_zone_35N"}, + {23036, "PCS_ED50_UTM_zone_36N"}, + {23037, "PCS_ED50_UTM_zone_37N"}, + {23038, "PCS_ED50_UTM_zone_38N"}, + {23239, "PCS_Fahud_UTM_zone_39N"}, + {23240, "PCS_Fahud_UTM_zone_40N"}, + {23433, "PCS_Garoua_UTM_zone_33N"}, + {23846, "PCS_ID74_UTM_zone_46N"}, + {23847, "PCS_ID74_UTM_zone_47N"}, + {23848, "PCS_ID74_UTM_zone_48N"}, + {23849, "PCS_ID74_UTM_zone_49N"}, + {23850, "PCS_ID74_UTM_zone_50N"}, + {23851, "PCS_ID74_UTM_zone_51N"}, + {23852, "PCS_ID74_UTM_zone_52N"}, + {23853, "PCS_ID74_UTM_zone_53N"}, + {23886, "PCS_ID74_UTM_zone_46S"}, + {23887, "PCS_ID74_UTM_zone_47S"}, + {23888, "PCS_ID74_UTM_zone_48S"}, + {23889, "PCS_ID74_UTM_zone_49S"}, + {23890, "PCS_ID74_UTM_zone_50S"}, + {23891, "PCS_ID74_UTM_zone_51S"}, + {23892, "PCS_ID74_UTM_zone_52S"}, + {23893, "PCS_ID74_UTM_zone_53S"}, + {23894, "PCS_ID74_UTM_zone_54S"}, + {23947, "PCS_Indian_1954_UTM_47N"}, + {23948, "PCS_Indian_1954_UTM_48N"}, + {24047, "PCS_Indian_1975_UTM_47N"}, + {24048, "PCS_Indian_1975_UTM_48N"}, + {24100, "PCS_Jamaica_1875_Old_Grid"}, + {24200, "PCS_JAD69_Jamaica_Grid"}, + {24370, "PCS_Kalianpur_India_0"}, + {24371, "PCS_Kalianpur_India_I"}, + {24372, "PCS_Kalianpur_India_IIa"}, + {24373, "PCS_Kalianpur_India_IIIa"}, + {24374, "PCS_Kalianpur_India_IVa"}, + {24382, "PCS_Kalianpur_India_IIb"}, + {24383, "PCS_Kalianpur_India_IIIb"}, + {24384, "PCS_Kalianpur_India_IVb"}, + {24500, "PCS_Kertau_Singapore_Grid"}, + {24547, "PCS_Kertau_UTM_zone_47N"}, + {24548, "PCS_Kertau_UTM_zone_48N"}, + {24720, "PCS_La_Canoa_UTM_zone_20N"}, + {24721, "PCS_La_Canoa_UTM_zone_21N"}, + {24818, "PCS_PSAD56_UTM_zone_18N"}, + {24819, "PCS_PSAD56_UTM_zone_19N"}, + {24820, "PCS_PSAD56_UTM_zone_20N"}, + {24821, "PCS_PSAD56_UTM_zone_21N"}, + {24877, "PCS_PSAD56_UTM_zone_17S"}, + {24878, "PCS_PSAD56_UTM_zone_18S"}, + {24879, "PCS_PSAD56_UTM_zone_19S"}, + {24880, "PCS_PSAD56_UTM_zone_20S"}, + {24891, "PCS_PSAD56_Peru_west_zone"}, + {24892, "PCS_PSAD56_Peru_central"}, + {24893, "PCS_PSAD56_Peru_east_zone"}, + {25000, "PCS_Leigon_Ghana_Grid"}, + {25231, "PCS_Lome_UTM_zone_31N"}, + {25391, "PCS_Luzon_Philippines_I"}, + {25392, "PCS_Luzon_Philippines_II"}, + {25393, "PCS_Luzon_Philippines_III"}, + {25394, "PCS_Luzon_Philippines_IV"}, + {25395, "PCS_Luzon_Philippines_V"}, + {25700, "PCS_Makassar_NEIEZ"}, + {25932, "PCS_Malongo_1987_UTM_32S"}, + {26191, "PCS_Merchich_Nord_Maroc"}, + {26192, "PCS_Merchich_Sud_Maroc"}, + {26193, "PCS_Merchich_Sahara"}, + {26237, "PCS_Massawa_UTM_zone_37N"}, + {26331, "PCS_Minna_UTM_zone_31N"}, + {26332, "PCS_Minna_UTM_zone_32N"}, + {26391, "PCS_Minna_Nigeria_West"}, + {26392, "PCS_Minna_Nigeria_Mid_Belt"}, + {26393, "PCS_Minna_Nigeria_East"}, + {26432, "PCS_Mhast_UTM_zone_32S"}, + {26591, "PCS_Monte_Mario_Italy_1"}, + {26592, "PCS_Monte_Mario_Italy_2"}, + {26632, "PCS_M_poraloko_UTM_32N"}, + {26692, "PCS_M_poraloko_UTM_32S"}, + {26703, "PCS_NAD27_UTM_zone_3N"}, + {26704, "PCS_NAD27_UTM_zone_4N"}, + {26705, "PCS_NAD27_UTM_zone_5N"}, + {26706, "PCS_NAD27_UTM_zone_6N"}, + {26707, "PCS_NAD27_UTM_zone_7N"}, + {26708, "PCS_NAD27_UTM_zone_8N"}, + {26709, "PCS_NAD27_UTM_zone_9N"}, + {26710, "PCS_NAD27_UTM_zone_10N"}, + {26711, "PCS_NAD27_UTM_zone_11N"}, + {26712, "PCS_NAD27_UTM_zone_12N"}, + {26713, "PCS_NAD27_UTM_zone_13N"}, + {26714, "PCS_NAD27_UTM_zone_14N"}, + {26715, "PCS_NAD27_UTM_zone_15N"}, + {26716, "PCS_NAD27_UTM_zone_16N"}, + {26717, "PCS_NAD27_UTM_zone_17N"}, + {26718, "PCS_NAD27_UTM_zone_18N"}, + {26719, "PCS_NAD27_UTM_zone_19N"}, + {26720, "PCS_NAD27_UTM_zone_20N"}, + {26721, "PCS_NAD27_UTM_zone_21N"}, + {26722, "PCS_NAD27_UTM_zone_22N"}, + {26729, "PCS_NAD27_Alabama_East"}, + {26730, "PCS_NAD27_Alabama_West"}, + {26731, "PCS_NAD27_Alaska_zone_1"}, + {26732, "PCS_NAD27_Alaska_zone_2"}, + {26733, "PCS_NAD27_Alaska_zone_3"}, + {26734, "PCS_NAD27_Alaska_zone_4"}, + {26735, "PCS_NAD27_Alaska_zone_5"}, + {26736, "PCS_NAD27_Alaska_zone_6"}, + {26737, "PCS_NAD27_Alaska_zone_7"}, + {26738, "PCS_NAD27_Alaska_zone_8"}, + {26739, "PCS_NAD27_Alaska_zone_9"}, + {26740, "PCS_NAD27_Alaska_zone_10"}, + {26741, "PCS_NAD27_California_I"}, + {26742, "PCS_NAD27_California_II"}, + {26743, "PCS_NAD27_California_III"}, + {26744, "PCS_NAD27_California_IV"}, + {26745, "PCS_NAD27_California_V"}, + {26746, "PCS_NAD27_California_VI"}, + {26747, "PCS_NAD27_California_VII"}, + {26748, "PCS_NAD27_Arizona_East"}, + {26749, "PCS_NAD27_Arizona_Central"}, + {26750, "PCS_NAD27_Arizona_West"}, + {26751, "PCS_NAD27_Arkansas_North"}, + {26752, "PCS_NAD27_Arkansas_South"}, + {26753, "PCS_NAD27_Colorado_North"}, + {26754, "PCS_NAD27_Colorado_Central"}, + {26755, "PCS_NAD27_Colorado_South"}, + {26756, "PCS_NAD27_Connecticut"}, + {26757, "PCS_NAD27_Delaware"}, + {26758, "PCS_NAD27_Florida_East"}, + {26759, "PCS_NAD27_Florida_West"}, + {26760, "PCS_NAD27_Florida_North"}, + {26761, "PCS_NAD27_Hawaii_zone_1"}, + {26762, "PCS_NAD27_Hawaii_zone_2"}, + {26763, "PCS_NAD27_Hawaii_zone_3"}, + {26764, "PCS_NAD27_Hawaii_zone_4"}, + {26765, "PCS_NAD27_Hawaii_zone_5"}, + {26766, "PCS_NAD27_Georgia_East"}, + {26767, "PCS_NAD27_Georgia_West"}, + {26768, "PCS_NAD27_Idaho_East"}, + {26769, "PCS_NAD27_Idaho_Central"}, + {26770, "PCS_NAD27_Idaho_West"}, + {26771, "PCS_NAD27_Illinois_East"}, + {26772, "PCS_NAD27_Illinois_West"}, + {26773, "PCS_NAD27_Indiana_East"}, + {26774, "PCS_NAD27_BLM_14N_feet"}, + {26774, "PCS_NAD27_Indiana_West"}, + {26775, "PCS_NAD27_BLM_15N_feet"}, + {26775, "PCS_NAD27_Iowa_North"}, + {26776, "PCS_NAD27_BLM_16N_feet"}, + {26776, "PCS_NAD27_Iowa_South"}, + {26777, "PCS_NAD27_BLM_17N_feet"}, + {26777, "PCS_NAD27_Kansas_North"}, + {26778, "PCS_NAD27_Kansas_South"}, + {26779, "PCS_NAD27_Kentucky_North"}, + {26780, "PCS_NAD27_Kentucky_South"}, + {26781, "PCS_NAD27_Louisiana_North"}, + {26782, "PCS_NAD27_Louisiana_South"}, + {26783, "PCS_NAD27_Maine_East"}, + {26784, "PCS_NAD27_Maine_West"}, + {26785, "PCS_NAD27_Maryland"}, + {26786, "PCS_NAD27_Massachusetts"}, + {26787, "PCS_NAD27_Massachusetts_Is"}, + {26788, "PCS_NAD27_Michigan_North"}, + {26789, "PCS_NAD27_Michigan_Central"}, + {26790, "PCS_NAD27_Michigan_South"}, + {26791, "PCS_NAD27_Minnesota_North"}, + {26792, "PCS_NAD27_Minnesota_Cent"}, + {26793, "PCS_NAD27_Minnesota_South"}, + {26794, "PCS_NAD27_Mississippi_East"}, + {26795, "PCS_NAD27_Mississippi_West"}, + {26796, "PCS_NAD27_Missouri_East"}, + {26797, "PCS_NAD27_Missouri_Central"}, + {26798, "PCS_NAD27_Missouri_West"}, + {26801, "PCS_NAD_Michigan_Michigan_East"}, + {26802, "PCS_NAD_Michigan_Michigan_Old_Central"}, + {26803, "PCS_NAD_Michigan_Michigan_West"}, + {26903, "PCS_NAD83_UTM_zone_3N"}, + {26904, "PCS_NAD83_UTM_zone_4N"}, + {26905, "PCS_NAD83_UTM_zone_5N"}, + {26906, "PCS_NAD83_UTM_zone_6N"}, + {26907, "PCS_NAD83_UTM_zone_7N"}, + {26908, "PCS_NAD83_UTM_zone_8N"}, + {26909, "PCS_NAD83_UTM_zone_9N"}, + {26910, "PCS_NAD83_UTM_zone_10N"}, + {26911, "PCS_NAD83_UTM_zone_11N"}, + {26912, "PCS_NAD83_UTM_zone_12N"}, + {26913, "PCS_NAD83_UTM_zone_13N"}, + {26914, "PCS_NAD83_UTM_zone_14N"}, + {26915, "PCS_NAD83_UTM_zone_15N"}, + {26916, "PCS_NAD83_UTM_zone_16N"}, + {26917, "PCS_NAD83_UTM_zone_17N"}, + {26918, "PCS_NAD83_UTM_zone_18N"}, + {26919, "PCS_NAD83_UTM_zone_19N"}, + {26920, "PCS_NAD83_UTM_zone_20N"}, + {26921, "PCS_NAD83_UTM_zone_21N"}, + {26922, "PCS_NAD83_UTM_zone_22N"}, + {26923, "PCS_NAD83_UTM_zone_23N"}, + {26929, "PCS_NAD83_Alabama_East"}, + {26930, "PCS_NAD83_Alabama_West"}, + {26931, "PCS_NAD83_Alaska_zone_1"}, + {26932, "PCS_NAD83_Alaska_zone_2"}, + {26933, "PCS_NAD83_Alaska_zone_3"}, + {26934, "PCS_NAD83_Alaska_zone_4"}, + {26935, "PCS_NAD83_Alaska_zone_5"}, + {26936, "PCS_NAD83_Alaska_zone_6"}, + {26937, "PCS_NAD83_Alaska_zone_7"}, + {26938, "PCS_NAD83_Alaska_zone_8"}, + {26939, "PCS_NAD83_Alaska_zone_9"}, + {26940, "PCS_NAD83_Alaska_zone_10"}, + {26941, "PCS_NAD83_California_1"}, + {26942, "PCS_NAD83_California_2"}, + {26943, "PCS_NAD83_California_3"}, + {26944, "PCS_NAD83_California_4"}, + {26945, "PCS_NAD83_California_5"}, + {26946, "PCS_NAD83_California_6"}, + {26948, "PCS_NAD83_Arizona_East"}, + {26949, "PCS_NAD83_Arizona_Central"}, + {26950, "PCS_NAD83_Arizona_West"}, + {26951, "PCS_NAD83_Arkansas_North"}, + {26952, "PCS_NAD83_Arkansas_South"}, + {26953, "PCS_NAD83_Colorado_North"}, + {26954, "PCS_NAD83_Colorado_Central"}, + {26955, "PCS_NAD83_Colorado_South"}, + {26956, "PCS_NAD83_Connecticut"}, + {26957, "PCS_NAD83_Delaware"}, + {26958, "PCS_NAD83_Florida_East"}, + {26959, "PCS_NAD83_Florida_West"}, + {26960, "PCS_NAD83_Florida_North"}, + {26961, "PCS_NAD83_Hawaii_zone_1"}, + {26962, "PCS_NAD83_Hawaii_zone_2"}, + {26963, "PCS_NAD83_Hawaii_zone_3"}, + {26964, "PCS_NAD83_Hawaii_zone_4"}, + {26965, "PCS_NAD83_Hawaii_zone_5"}, + {26966, "PCS_NAD83_Georgia_East"}, + {26967, "PCS_NAD83_Georgia_West"}, + {26968, "PCS_NAD83_Idaho_East"}, + {26969, "PCS_NAD83_Idaho_Central"}, + {26970, "PCS_NAD83_Idaho_West"}, + {26971, "PCS_NAD83_Illinois_East"}, + {26972, "PCS_NAD83_Illinois_West"}, + {26973, "PCS_NAD83_Indiana_East"}, + {26974, "PCS_NAD83_Indiana_West"}, + {26975, "PCS_NAD83_Iowa_North"}, + {26976, "PCS_NAD83_Iowa_South"}, + {26977, "PCS_NAD83_Kansas_North"}, + {26978, "PCS_NAD83_Kansas_South"}, + {26979, "PCS_NAD83_Kentucky_North"}, + {26980, "PCS_NAD83_Kentucky_South"}, + {26981, "PCS_NAD83_Louisiana_North"}, + {26982, "PCS_NAD83_Louisiana_South"}, + {26983, "PCS_NAD83_Maine_East"}, + {26984, "PCS_NAD83_Maine_West"}, + {26985, "PCS_NAD83_Maryland"}, + {26986, "PCS_NAD83_Massachusetts"}, + {26987, "PCS_NAD83_Massachusetts_Is"}, + {26988, "PCS_NAD83_Michigan_North"}, + {26989, "PCS_NAD83_Michigan_Central"}, + {26990, "PCS_NAD83_Michigan_South"}, + {26991, "PCS_NAD83_Minnesota_North"}, + {26992, "PCS_NAD83_Minnesota_Cent"}, + {26993, "PCS_NAD83_Minnesota_South"}, + {26994, "PCS_NAD83_Mississippi_East"}, + {26995, "PCS_NAD83_Mississippi_West"}, + {26996, "PCS_NAD83_Missouri_East"}, + {26997, "PCS_NAD83_Missouri_Central"}, + {26998, "PCS_NAD83_Missouri_West"}, + {27038, "PCS_Nahrwan_1967_UTM_38N"}, + {27039, "PCS_Nahrwan_1967_UTM_39N"}, + {27040, "PCS_Nahrwan_1967_UTM_40N"}, + {27120, "PCS_Naparima_UTM_20N"}, + {27200, "PCS_GD49_NZ_Map_Grid"}, + {27291, "PCS_GD49_North_Island_Grid"}, + {27292, "PCS_GD49_South_Island_Grid"}, + {27429, "PCS_Datum_73_UTM_zone_29N"}, + {27500, "PCS_ATF_Nord_de_Guerre"}, + {27581, "PCS_NTF_France_I"}, + {27582, "PCS_NTF_France_II"}, + {27583, "PCS_NTF_France_III"}, + {27591, "PCS_NTF_Nord_France"}, + {27592, "PCS_NTF_Centre_France"}, + {27593, "PCS_NTF_Sud_France"}, + {27700, "PCS_British_National_Grid"}, + {28232, "PCS_Point_Noire_UTM_32S"}, + {28348, "PCS_GDA94_MGA_zone_48"}, + {28349, "PCS_GDA94_MGA_zone_49"}, + {28350, "PCS_GDA94_MGA_zone_50"}, + {28351, "PCS_GDA94_MGA_zone_51"}, + {28352, "PCS_GDA94_MGA_zone_52"}, + {28353, "PCS_GDA94_MGA_zone_53"}, + {28354, "PCS_GDA94_MGA_zone_54"}, + {28355, "PCS_GDA94_MGA_zone_55"}, + {28356, "PCS_GDA94_MGA_zone_56"}, + {28357, "PCS_GDA94_MGA_zone_57"}, + {28358, "PCS_GDA94_MGA_zone_58"}, + {28404, "PCS_Pulkovo_Gauss_zone_4"}, + {28405, "PCS_Pulkovo_Gauss_zone_5"}, + {28406, "PCS_Pulkovo_Gauss_zone_6"}, + {28407, "PCS_Pulkovo_Gauss_zone_7"}, + {28408, "PCS_Pulkovo_Gauss_zone_8"}, + {28409, "PCS_Pulkovo_Gauss_zone_9"}, + {28410, "PCS_Pulkovo_Gauss_zone_10"}, + {28411, "PCS_Pulkovo_Gauss_zone_11"}, + {28412, "PCS_Pulkovo_Gauss_zone_12"}, + {28413, "PCS_Pulkovo_Gauss_zone_13"}, + {28414, "PCS_Pulkovo_Gauss_zone_14"}, + {28415, "PCS_Pulkovo_Gauss_zone_15"}, + {28416, "PCS_Pulkovo_Gauss_zone_16"}, + {28417, "PCS_Pulkovo_Gauss_zone_17"}, + {28418, "PCS_Pulkovo_Gauss_zone_18"}, + {28419, "PCS_Pulkovo_Gauss_zone_19"}, + {28420, "PCS_Pulkovo_Gauss_zone_20"}, + {28421, "PCS_Pulkovo_Gauss_zone_21"}, + {28422, "PCS_Pulkovo_Gauss_zone_22"}, + {28423, "PCS_Pulkovo_Gauss_zone_23"}, + {28424, "PCS_Pulkovo_Gauss_zone_24"}, + {28425, "PCS_Pulkovo_Gauss_zone_25"}, + {28426, "PCS_Pulkovo_Gauss_zone_26"}, + {28427, "PCS_Pulkovo_Gauss_zone_27"}, + {28428, "PCS_Pulkovo_Gauss_zone_28"}, + {28429, "PCS_Pulkovo_Gauss_zone_29"}, + {28430, "PCS_Pulkovo_Gauss_zone_30"}, + {28431, "PCS_Pulkovo_Gauss_zone_31"}, + {28432, "PCS_Pulkovo_Gauss_zone_32"}, + {28464, "PCS_Pulkovo_Gauss_4N"}, + {28465, "PCS_Pulkovo_Gauss_5N"}, + {28466, "PCS_Pulkovo_Gauss_6N"}, + {28467, "PCS_Pulkovo_Gauss_7N"}, + {28468, "PCS_Pulkovo_Gauss_8N"}, + {28469, "PCS_Pulkovo_Gauss_9N"}, + {28470, "PCS_Pulkovo_Gauss_10N"}, + {28471, "PCS_Pulkovo_Gauss_11N"}, + {28472, "PCS_Pulkovo_Gauss_12N"}, + {28473, "PCS_Pulkovo_Gauss_13N"}, + {28474, "PCS_Pulkovo_Gauss_14N"}, + {28475, "PCS_Pulkovo_Gauss_15N"}, + {28476, "PCS_Pulkovo_Gauss_16N"}, + {28477, "PCS_Pulkovo_Gauss_17N"}, + {28478, "PCS_Pulkovo_Gauss_18N"}, + {28479, "PCS_Pulkovo_Gauss_19N"}, + {28480, "PCS_Pulkovo_Gauss_20N"}, + {28481, "PCS_Pulkovo_Gauss_21N"}, + {28482, "PCS_Pulkovo_Gauss_22N"}, + {28483, "PCS_Pulkovo_Gauss_23N"}, + {28484, "PCS_Pulkovo_Gauss_24N"}, + {28485, "PCS_Pulkovo_Gauss_25N"}, + {28486, "PCS_Pulkovo_Gauss_26N"}, + {28487, "PCS_Pulkovo_Gauss_27N"}, + {28488, "PCS_Pulkovo_Gauss_28N"}, + {28489, "PCS_Pulkovo_Gauss_29N"}, + {28490, "PCS_Pulkovo_Gauss_30N"}, + {28491, "PCS_Pulkovo_Gauss_31N"}, + {28492, "PCS_Pulkovo_Gauss_32N"}, + {28600, "PCS_Qatar_National_Grid"}, + {28991, "PCS_RD_Netherlands_Old"}, + {28992, "PCS_RD_Netherlands_New"}, + {29118, "PCS_SAD69_UTM_zone_18N"}, + {29119, "PCS_SAD69_UTM_zone_19N"}, + {29120, "PCS_SAD69_UTM_zone_20N"}, + {29121, "PCS_SAD69_UTM_zone_21N"}, + {29122, "PCS_SAD69_UTM_zone_22N"}, + {29177, "PCS_SAD69_UTM_zone_17S"}, + {29178, "PCS_SAD69_UTM_zone_18S"}, + {29179, "PCS_SAD69_UTM_zone_19S"}, + {29180, "PCS_SAD69_UTM_zone_20S"}, + {29181, "PCS_SAD69_UTM_zone_21S"}, + {29182, "PCS_SAD69_UTM_zone_22S"}, + {29183, "PCS_SAD69_UTM_zone_23S"}, + {29184, "PCS_SAD69_UTM_zone_24S"}, + {29185, "PCS_SAD69_UTM_zone_25S"}, + {29220, "PCS_Sapper_Hill_UTM_20S"}, + {29221, "PCS_Sapper_Hill_UTM_21S"}, + {29333, "PCS_Schwarzeck_UTM_33S"}, + {29635, "PCS_Sudan_UTM_zone_35N"}, + {29636, "PCS_Sudan_UTM_zone_36N"}, + {29700, "PCS_Tananarive_Laborde"}, + {29738, "PCS_Tananarive_UTM_38S"}, + {29739, "PCS_Tananarive_UTM_39S"}, + {29800, "PCS_Timbalai_1948_Borneo"}, + {29849, "PCS_Timbalai_1948_UTM_49N"}, + {29850, "PCS_Timbalai_1948_UTM_50N"}, + {29900, "PCS_TM65_Irish_Nat_Grid"}, + {30200, "PCS_Trinidad_1903_Trinidad"}, + {30339, "PCS_TC_1948_UTM_zone_39N"}, + {30340, "PCS_TC_1948_UTM_zone_40N"}, + {30491, "PCS_Voirol_N_Algerie_ancien"}, + {30492, "PCS_Voirol_S_Algerie_ancien"}, + {30591, "PCS_Voirol_Unifie_N_Algerie"}, + {30592, "PCS_Voirol_Unifie_S_Algerie"}, + {30600, "PCS_Bern_1938_Swiss_New"}, + {30729, "PCS_Nord_Sahara_UTM_29N"}, + {30730, "PCS_Nord_Sahara_UTM_30N"}, + {30731, "PCS_Nord_Sahara_UTM_31N"}, + {30732, "PCS_Nord_Sahara_UTM_32N"}, + {31028, "PCS_Yoff_UTM_zone_28N"}, + {31121, "PCS_Zanderij_UTM_zone_21N"}, + {31291, "PCS_MGI_Austria_West"}, + {31292, "PCS_MGI_Austria_Central"}, + {31293, "PCS_MGI_Austria_East"}, + {31300, "PCS_Belge_Lambert_72"}, + {31491, "PCS_DHDN_Germany_zone_1"}, + {31492, "PCS_DHDN_Germany_zone_2"}, + {31493, "PCS_DHDN_Germany_zone_3"}, + {31494, "PCS_DHDN_Germany_zone_4"}, + {31495, "PCS_DHDN_Germany_zone_5"}, + {32001, "PCS_NAD27_Montana_North"}, + {32002, "PCS_NAD27_Montana_Central"}, + {32003, "PCS_NAD27_Montana_South"}, + {32005, "PCS_NAD27_Nebraska_North"}, + {32006, "PCS_NAD27_Nebraska_South"}, + {32007, "PCS_NAD27_Nevada_East"}, + {32008, "PCS_NAD27_Nevada_Central"}, + {32009, "PCS_NAD27_Nevada_West"}, + {32010, "PCS_NAD27_New_Hampshire"}, + {32011, "PCS_NAD27_New_Jersey"}, + {32012, "PCS_NAD27_New_Mexico_East"}, + {32013, "PCS_NAD27_New_Mexico_Cent"}, + {32014, "PCS_NAD27_New_Mexico_West"}, + {32015, "PCS_NAD27_New_York_East"}, + {32016, "PCS_NAD27_New_York_Central"}, + {32017, "PCS_NAD27_New_York_West"}, + {32018, "PCS_NAD27_New_York_Long_Is"}, + {32019, "PCS_NAD27_North_Carolina"}, + {32020, "PCS_NAD27_North_Dakota_N"}, + {32021, "PCS_NAD27_North_Dakota_S"}, + {32022, "PCS_NAD27_Ohio_North"}, + {32023, "PCS_NAD27_Ohio_South"}, + {32024, "PCS_NAD27_Oklahoma_North"}, + {32025, "PCS_NAD27_Oklahoma_South"}, + {32026, "PCS_NAD27_Oregon_North"}, + {32027, "PCS_NAD27_Oregon_South"}, + {32028, "PCS_NAD27_Pennsylvania_N"}, + {32029, "PCS_NAD27_Pennsylvania_S"}, + {32030, "PCS_NAD27_Rhode_Island"}, + {32031, "PCS_NAD27_South_Carolina_N"}, + {32033, "PCS_NAD27_South_Carolina_S"}, + {32034, "PCS_NAD27_South_Dakota_N"}, + {32035, "PCS_NAD27_South_Dakota_S"}, + {32036, "PCS_NAD27_Tennessee"}, + {32037, "PCS_NAD27_Texas_North"}, + {32038, "PCS_NAD27_Texas_North_Cen"}, + {32039, "PCS_NAD27_Texas_Central"}, + {32040, "PCS_NAD27_Texas_South_Cen"}, + {32041, "PCS_NAD27_Texas_South"}, + {32042, "PCS_NAD27_Utah_North"}, + {32043, "PCS_NAD27_Utah_Central"}, + {32044, "PCS_NAD27_Utah_South"}, + {32045, "PCS_NAD27_Vermont"}, + {32046, "PCS_NAD27_Virginia_North"}, + {32047, "PCS_NAD27_Virginia_South"}, + {32048, "PCS_NAD27_Washington_North"}, + {32049, "PCS_NAD27_Washington_South"}, + {32050, "PCS_NAD27_West_Virginia_N"}, + {32051, "PCS_NAD27_West_Virginia_S"}, + {32052, "PCS_NAD27_Wisconsin_North"}, + {32053, "PCS_NAD27_Wisconsin_Cen"}, + {32054, "PCS_NAD27_Wisconsin_South"}, + {32055, "PCS_NAD27_Wyoming_East"}, + {32056, "PCS_NAD27_Wyoming_E_Cen"}, + {32057, "PCS_NAD27_Wyoming_W_Cen"}, + {32058, "PCS_NAD27_Wyoming_West"}, + {32059, "PCS_NAD27_Puerto_Rico"}, + {32060, "PCS_NAD27_St_Croix"}, + {32100, "PCS_NAD83_Montana"}, + {32104, "PCS_NAD83_Nebraska"}, + {32107, "PCS_NAD83_Nevada_East"}, + {32108, "PCS_NAD83_Nevada_Central"}, + {32109, "PCS_NAD83_Nevada_West"}, + {32110, "PCS_NAD83_New_Hampshire"}, + {32111, "PCS_NAD83_New_Jersey"}, + {32112, "PCS_NAD83_New_Mexico_East"}, + {32113, "PCS_NAD83_New_Mexico_Cent"}, + {32114, "PCS_NAD83_New_Mexico_West"}, + {32115, "PCS_NAD83_New_York_East"}, + {32116, "PCS_NAD83_New_York_Central"}, + {32117, "PCS_NAD83_New_York_West"}, + {32118, "PCS_NAD83_New_York_Long_Is"}, + {32119, "PCS_NAD83_North_Carolina"}, + {32120, "PCS_NAD83_North_Dakota_N"}, + {32121, "PCS_NAD83_North_Dakota_S"}, + {32122, "PCS_NAD83_Ohio_North"}, + {32123, "PCS_NAD83_Ohio_South"}, + {32124, "PCS_NAD83_Oklahoma_North"}, + {32125, "PCS_NAD83_Oklahoma_South"}, + {32126, "PCS_NAD83_Oregon_North"}, + {32127, "PCS_NAD83_Oregon_South"}, + {32128, "PCS_NAD83_Pennsylvania_N"}, + {32129, "PCS_NAD83_Pennsylvania_S"}, + {32130, "PCS_NAD83_Rhode_Island"}, + {32133, "PCS_NAD83_South_Carolina"}, + {32134, "PCS_NAD83_South_Dakota_N"}, + {32135, "PCS_NAD83_South_Dakota_S"}, + {32136, "PCS_NAD83_Tennessee"}, + {32137, "PCS_NAD83_Texas_North"}, + {32138, "PCS_NAD83_Texas_North_Cen"}, + {32139, "PCS_NAD83_Texas_Central"}, + {32140, "PCS_NAD83_Texas_South_Cen"}, + {32141, "PCS_NAD83_Texas_South"}, + {32142, "PCS_NAD83_Utah_North"}, + {32143, "PCS_NAD83_Utah_Central"}, + {32144, "PCS_NAD83_Utah_South"}, + {32145, "PCS_NAD83_Vermont"}, + {32146, "PCS_NAD83_Virginia_North"}, + {32147, "PCS_NAD83_Virginia_South"}, + {32148, "PCS_NAD83_Washington_North"}, + {32149, "PCS_NAD83_Washington_South"}, + {32150, "PCS_NAD83_West_Virginia_N"}, + {32151, "PCS_NAD83_West_Virginia_S"}, + {32152, "PCS_NAD83_Wisconsin_North"}, + {32153, "PCS_NAD83_Wisconsin_Cen"}, + {32154, "PCS_NAD83_Wisconsin_South"}, + {32155, "PCS_NAD83_Wyoming_East"}, + {32156, "PCS_NAD83_Wyoming_E_Cen"}, + {32157, "PCS_NAD83_Wyoming_W_Cen"}, + {32158, "PCS_NAD83_Wyoming_West"}, + {32161, "PCS_NAD83_Puerto_Rico_Virgin_Is"}, + {32201, "PCS_WGS72_UTM_zone_1N"}, + {32202, "PCS_WGS72_UTM_zone_2N"}, + {32203, "PCS_WGS72_UTM_zone_3N"}, + {32204, "PCS_WGS72_UTM_zone_4N"}, + {32205, "PCS_WGS72_UTM_zone_5N"}, + {32206, "PCS_WGS72_UTM_zone_6N"}, + {32207, "PCS_WGS72_UTM_zone_7N"}, + {32208, "PCS_WGS72_UTM_zone_8N"}, + {32209, "PCS_WGS72_UTM_zone_9N"}, + {32210, "PCS_WGS72_UTM_zone_10N"}, + {32211, "PCS_WGS72_UTM_zone_11N"}, + {32212, "PCS_WGS72_UTM_zone_12N"}, + {32213, "PCS_WGS72_UTM_zone_13N"}, + {32214, "PCS_WGS72_UTM_zone_14N"}, + {32215, "PCS_WGS72_UTM_zone_15N"}, + {32216, "PCS_WGS72_UTM_zone_16N"}, + {32217, "PCS_WGS72_UTM_zone_17N"}, + {32218, "PCS_WGS72_UTM_zone_18N"}, + {32219, "PCS_WGS72_UTM_zone_19N"}, + {32220, "PCS_WGS72_UTM_zone_20N"}, + {32221, "PCS_WGS72_UTM_zone_21N"}, + {32222, "PCS_WGS72_UTM_zone_22N"}, + {32223, "PCS_WGS72_UTM_zone_23N"}, + {32224, "PCS_WGS72_UTM_zone_24N"}, + {32225, "PCS_WGS72_UTM_zone_25N"}, + {32226, "PCS_WGS72_UTM_zone_26N"}, + {32227, "PCS_WGS72_UTM_zone_27N"}, + {32228, "PCS_WGS72_UTM_zone_28N"}, + {32229, "PCS_WGS72_UTM_zone_29N"}, + {32230, "PCS_WGS72_UTM_zone_30N"}, + {32231, "PCS_WGS72_UTM_zone_31N"}, + {32232, "PCS_WGS72_UTM_zone_32N"}, + {32233, "PCS_WGS72_UTM_zone_33N"}, + {32234, "PCS_WGS72_UTM_zone_34N"}, + {32235, "PCS_WGS72_UTM_zone_35N"}, + {32236, "PCS_WGS72_UTM_zone_36N"}, + {32237, "PCS_WGS72_UTM_zone_37N"}, + {32238, "PCS_WGS72_UTM_zone_38N"}, + {32239, "PCS_WGS72_UTM_zone_39N"}, + {32240, "PCS_WGS72_UTM_zone_40N"}, + {32241, "PCS_WGS72_UTM_zone_41N"}, + {32242, "PCS_WGS72_UTM_zone_42N"}, + {32243, "PCS_WGS72_UTM_zone_43N"}, + {32244, "PCS_WGS72_UTM_zone_44N"}, + {32245, "PCS_WGS72_UTM_zone_45N"}, + {32246, "PCS_WGS72_UTM_zone_46N"}, + {32247, "PCS_WGS72_UTM_zone_47N"}, + {32248, "PCS_WGS72_UTM_zone_48N"}, + {32249, "PCS_WGS72_UTM_zone_49N"}, + {32250, "PCS_WGS72_UTM_zone_50N"}, + {32251, "PCS_WGS72_UTM_zone_51N"}, + {32252, "PCS_WGS72_UTM_zone_52N"}, + {32253, "PCS_WGS72_UTM_zone_53N"}, + {32254, "PCS_WGS72_UTM_zone_54N"}, + {32255, "PCS_WGS72_UTM_zone_55N"}, + {32256, "PCS_WGS72_UTM_zone_56N"}, + {32257, "PCS_WGS72_UTM_zone_57N"}, + {32258, "PCS_WGS72_UTM_zone_58N"}, + {32259, "PCS_WGS72_UTM_zone_59N"}, + {32260, "PCS_WGS72_UTM_zone_60N"}, + {32301, "PCS_WGS72_UTM_zone_1S"}, + {32302, "PCS_WGS72_UTM_zone_2S"}, + {32303, "PCS_WGS72_UTM_zone_3S"}, + {32304, "PCS_WGS72_UTM_zone_4S"}, + {32305, "PCS_WGS72_UTM_zone_5S"}, + {32306, "PCS_WGS72_UTM_zone_6S"}, + {32307, "PCS_WGS72_UTM_zone_7S"}, + {32308, "PCS_WGS72_UTM_zone_8S"}, + {32309, "PCS_WGS72_UTM_zone_9S"}, + {32310, "PCS_WGS72_UTM_zone_10S"}, + {32311, "PCS_WGS72_UTM_zone_11S"}, + {32312, "PCS_WGS72_UTM_zone_12S"}, + {32313, "PCS_WGS72_UTM_zone_13S"}, + {32314, "PCS_WGS72_UTM_zone_14S"}, + {32315, "PCS_WGS72_UTM_zone_15S"}, + {32316, "PCS_WGS72_UTM_zone_16S"}, + {32317, "PCS_WGS72_UTM_zone_17S"}, + {32318, "PCS_WGS72_UTM_zone_18S"}, + {32319, "PCS_WGS72_UTM_zone_19S"}, + {32320, "PCS_WGS72_UTM_zone_20S"}, + {32321, "PCS_WGS72_UTM_zone_21S"}, + {32322, "PCS_WGS72_UTM_zone_22S"}, + {32323, "PCS_WGS72_UTM_zone_23S"}, + {32324, "PCS_WGS72_UTM_zone_24S"}, + {32325, "PCS_WGS72_UTM_zone_25S"}, + {32326, "PCS_WGS72_UTM_zone_26S"}, + {32327, "PCS_WGS72_UTM_zone_27S"}, + {32328, "PCS_WGS72_UTM_zone_28S"}, + {32329, "PCS_WGS72_UTM_zone_29S"}, + {32330, "PCS_WGS72_UTM_zone_30S"}, + {32331, "PCS_WGS72_UTM_zone_31S"}, + {32332, "PCS_WGS72_UTM_zone_32S"}, + {32333, "PCS_WGS72_UTM_zone_33S"}, + {32334, "PCS_WGS72_UTM_zone_34S"}, + {32335, "PCS_WGS72_UTM_zone_35S"}, + {32336, "PCS_WGS72_UTM_zone_36S"}, + {32337, "PCS_WGS72_UTM_zone_37S"}, + {32338, "PCS_WGS72_UTM_zone_38S"}, + {32339, "PCS_WGS72_UTM_zone_39S"}, + {32340, "PCS_WGS72_UTM_zone_40S"}, + {32341, "PCS_WGS72_UTM_zone_41S"}, + {32342, "PCS_WGS72_UTM_zone_42S"}, + {32343, "PCS_WGS72_UTM_zone_43S"}, + {32344, "PCS_WGS72_UTM_zone_44S"}, + {32345, "PCS_WGS72_UTM_zone_45S"}, + {32346, "PCS_WGS72_UTM_zone_46S"}, + {32347, "PCS_WGS72_UTM_zone_47S"}, + {32348, "PCS_WGS72_UTM_zone_48S"}, + {32349, "PCS_WGS72_UTM_zone_49S"}, + {32350, "PCS_WGS72_UTM_zone_50S"}, + {32351, "PCS_WGS72_UTM_zone_51S"}, + {32352, "PCS_WGS72_UTM_zone_52S"}, + {32353, "PCS_WGS72_UTM_zone_53S"}, + {32354, "PCS_WGS72_UTM_zone_54S"}, + {32355, "PCS_WGS72_UTM_zone_55S"}, + {32356, "PCS_WGS72_UTM_zone_56S"}, + {32357, "PCS_WGS72_UTM_zone_57S"}, + {32358, "PCS_WGS72_UTM_zone_58S"}, + {32359, "PCS_WGS72_UTM_zone_59S"}, + {32360, "PCS_WGS72_UTM_zone_60S"}, + {32401, "PCS_WGS72BE_UTM_zone_1N"}, + {32402, "PCS_WGS72BE_UTM_zone_2N"}, + {32403, "PCS_WGS72BE_UTM_zone_3N"}, + {32404, "PCS_WGS72BE_UTM_zone_4N"}, + {32405, "PCS_WGS72BE_UTM_zone_5N"}, + {32406, "PCS_WGS72BE_UTM_zone_6N"}, + {32407, "PCS_WGS72BE_UTM_zone_7N"}, + {32408, "PCS_WGS72BE_UTM_zone_8N"}, + {32409, "PCS_WGS72BE_UTM_zone_9N"}, + {32410, "PCS_WGS72BE_UTM_zone_10N"}, + {32411, "PCS_WGS72BE_UTM_zone_11N"}, + {32412, "PCS_WGS72BE_UTM_zone_12N"}, + {32413, "PCS_WGS72BE_UTM_zone_13N"}, + {32414, "PCS_WGS72BE_UTM_zone_14N"}, + {32415, "PCS_WGS72BE_UTM_zone_15N"}, + {32416, "PCS_WGS72BE_UTM_zone_16N"}, + {32417, "PCS_WGS72BE_UTM_zone_17N"}, + {32418, "PCS_WGS72BE_UTM_zone_18N"}, + {32419, "PCS_WGS72BE_UTM_zone_19N"}, + {32420, "PCS_WGS72BE_UTM_zone_20N"}, + {32421, "PCS_WGS72BE_UTM_zone_21N"}, + {32422, "PCS_WGS72BE_UTM_zone_22N"}, + {32423, "PCS_WGS72BE_UTM_zone_23N"}, + {32424, "PCS_WGS72BE_UTM_zone_24N"}, + {32425, "PCS_WGS72BE_UTM_zone_25N"}, + {32426, "PCS_WGS72BE_UTM_zone_26N"}, + {32427, "PCS_WGS72BE_UTM_zone_27N"}, + {32428, "PCS_WGS72BE_UTM_zone_28N"}, + {32429, "PCS_WGS72BE_UTM_zone_29N"}, + {32430, "PCS_WGS72BE_UTM_zone_30N"}, + {32431, "PCS_WGS72BE_UTM_zone_31N"}, + {32432, "PCS_WGS72BE_UTM_zone_32N"}, + {32433, "PCS_WGS72BE_UTM_zone_33N"}, + {32434, "PCS_WGS72BE_UTM_zone_34N"}, + {32435, "PCS_WGS72BE_UTM_zone_35N"}, + {32436, "PCS_WGS72BE_UTM_zone_36N"}, + {32437, "PCS_WGS72BE_UTM_zone_37N"}, + {32438, "PCS_WGS72BE_UTM_zone_38N"}, + {32439, "PCS_WGS72BE_UTM_zone_39N"}, + {32440, "PCS_WGS72BE_UTM_zone_40N"}, + {32441, "PCS_WGS72BE_UTM_zone_41N"}, + {32442, "PCS_WGS72BE_UTM_zone_42N"}, + {32443, "PCS_WGS72BE_UTM_zone_43N"}, + {32444, "PCS_WGS72BE_UTM_zone_44N"}, + {32445, "PCS_WGS72BE_UTM_zone_45N"}, + {32446, "PCS_WGS72BE_UTM_zone_46N"}, + {32447, "PCS_WGS72BE_UTM_zone_47N"}, + {32448, "PCS_WGS72BE_UTM_zone_48N"}, + {32449, "PCS_WGS72BE_UTM_zone_49N"}, + {32450, "PCS_WGS72BE_UTM_zone_50N"}, + {32451, "PCS_WGS72BE_UTM_zone_51N"}, + {32452, "PCS_WGS72BE_UTM_zone_52N"}, + {32453, "PCS_WGS72BE_UTM_zone_53N"}, + {32454, "PCS_WGS72BE_UTM_zone_54N"}, + {32455, "PCS_WGS72BE_UTM_zone_55N"}, + {32456, "PCS_WGS72BE_UTM_zone_56N"}, + {32457, "PCS_WGS72BE_UTM_zone_57N"}, + {32458, "PCS_WGS72BE_UTM_zone_58N"}, + {32459, "PCS_WGS72BE_UTM_zone_59N"}, + {32460, "PCS_WGS72BE_UTM_zone_60N"}, + {32501, "PCS_WGS72BE_UTM_zone_1S"}, + {32502, "PCS_WGS72BE_UTM_zone_2S"}, + {32503, "PCS_WGS72BE_UTM_zone_3S"}, + {32504, "PCS_WGS72BE_UTM_zone_4S"}, + {32505, "PCS_WGS72BE_UTM_zone_5S"}, + {32506, "PCS_WGS72BE_UTM_zone_6S"}, + {32507, "PCS_WGS72BE_UTM_zone_7S"}, + {32508, "PCS_WGS72BE_UTM_zone_8S"}, + {32509, "PCS_WGS72BE_UTM_zone_9S"}, + {32510, "PCS_WGS72BE_UTM_zone_10S"}, + {32511, "PCS_WGS72BE_UTM_zone_11S"}, + {32512, "PCS_WGS72BE_UTM_zone_12S"}, + {32513, "PCS_WGS72BE_UTM_zone_13S"}, + {32514, "PCS_WGS72BE_UTM_zone_14S"}, + {32515, "PCS_WGS72BE_UTM_zone_15S"}, + {32516, "PCS_WGS72BE_UTM_zone_16S"}, + {32517, "PCS_WGS72BE_UTM_zone_17S"}, + {32518, "PCS_WGS72BE_UTM_zone_18S"}, + {32519, "PCS_WGS72BE_UTM_zone_19S"}, + {32520, "PCS_WGS72BE_UTM_zone_20S"}, + {32521, "PCS_WGS72BE_UTM_zone_21S"}, + {32522, "PCS_WGS72BE_UTM_zone_22S"}, + {32523, "PCS_WGS72BE_UTM_zone_23S"}, + {32524, "PCS_WGS72BE_UTM_zone_24S"}, + {32525, "PCS_WGS72BE_UTM_zone_25S"}, + {32526, "PCS_WGS72BE_UTM_zone_26S"}, + {32527, "PCS_WGS72BE_UTM_zone_27S"}, + {32528, "PCS_WGS72BE_UTM_zone_28S"}, + {32529, "PCS_WGS72BE_UTM_zone_29S"}, + {32530, "PCS_WGS72BE_UTM_zone_30S"}, + {32531, "PCS_WGS72BE_UTM_zone_31S"}, + {32532, "PCS_WGS72BE_UTM_zone_32S"}, + {32533, "PCS_WGS72BE_UTM_zone_33S"}, + {32534, "PCS_WGS72BE_UTM_zone_34S"}, + {32535, "PCS_WGS72BE_UTM_zone_35S"}, + {32536, "PCS_WGS72BE_UTM_zone_36S"}, + {32537, "PCS_WGS72BE_UTM_zone_37S"}, + {32538, "PCS_WGS72BE_UTM_zone_38S"}, + {32539, "PCS_WGS72BE_UTM_zone_39S"}, + {32540, "PCS_WGS72BE_UTM_zone_40S"}, + {32541, "PCS_WGS72BE_UTM_zone_41S"}, + {32542, "PCS_WGS72BE_UTM_zone_42S"}, + {32543, "PCS_WGS72BE_UTM_zone_43S"}, + {32544, "PCS_WGS72BE_UTM_zone_44S"}, + {32545, "PCS_WGS72BE_UTM_zone_45S"}, + {32546, "PCS_WGS72BE_UTM_zone_46S"}, + {32547, "PCS_WGS72BE_UTM_zone_47S"}, + {32548, "PCS_WGS72BE_UTM_zone_48S"}, + {32549, "PCS_WGS72BE_UTM_zone_49S"}, + {32550, "PCS_WGS72BE_UTM_zone_50S"}, + {32551, "PCS_WGS72BE_UTM_zone_51S"}, + {32552, "PCS_WGS72BE_UTM_zone_52S"}, + {32553, "PCS_WGS72BE_UTM_zone_53S"}, + {32554, "PCS_WGS72BE_UTM_zone_54S"}, + {32555, "PCS_WGS72BE_UTM_zone_55S"}, + {32556, "PCS_WGS72BE_UTM_zone_56S"}, + {32557, "PCS_WGS72BE_UTM_zone_57S"}, + {32558, "PCS_WGS72BE_UTM_zone_58S"}, + {32559, "PCS_WGS72BE_UTM_zone_59S"}, + {32560, "PCS_WGS72BE_UTM_zone_60S"}, + {32601, "PCS_WGS84_UTM_zone_1N"}, + {32602, "PCS_WGS84_UTM_zone_2N"}, + {32603, "PCS_WGS84_UTM_zone_3N"}, + {32604, "PCS_WGS84_UTM_zone_4N"}, + {32605, "PCS_WGS84_UTM_zone_5N"}, + {32606, "PCS_WGS84_UTM_zone_6N"}, + {32607, "PCS_WGS84_UTM_zone_7N"}, + {32608, "PCS_WGS84_UTM_zone_8N"}, + {32609, "PCS_WGS84_UTM_zone_9N"}, + {32610, "PCS_WGS84_UTM_zone_10N"}, + {32611, "PCS_WGS84_UTM_zone_11N"}, + {32612, "PCS_WGS84_UTM_zone_12N"}, + {32613, "PCS_WGS84_UTM_zone_13N"}, + {32614, "PCS_WGS84_UTM_zone_14N"}, + {32615, "PCS_WGS84_UTM_zone_15N"}, + {32616, "PCS_WGS84_UTM_zone_16N"}, + {32617, "PCS_WGS84_UTM_zone_17N"}, + {32618, "PCS_WGS84_UTM_zone_18N"}, + {32619, "PCS_WGS84_UTM_zone_19N"}, + {32620, "PCS_WGS84_UTM_zone_20N"}, + {32621, "PCS_WGS84_UTM_zone_21N"}, + {32622, "PCS_WGS84_UTM_zone_22N"}, + {32623, "PCS_WGS84_UTM_zone_23N"}, + {32624, "PCS_WGS84_UTM_zone_24N"}, + {32625, "PCS_WGS84_UTM_zone_25N"}, + {32626, "PCS_WGS84_UTM_zone_26N"}, + {32627, "PCS_WGS84_UTM_zone_27N"}, + {32628, "PCS_WGS84_UTM_zone_28N"}, + {32629, "PCS_WGS84_UTM_zone_29N"}, + {32630, "PCS_WGS84_UTM_zone_30N"}, + {32631, "PCS_WGS84_UTM_zone_31N"}, + {32632, "PCS_WGS84_UTM_zone_32N"}, + {32633, "PCS_WGS84_UTM_zone_33N"}, + {32634, "PCS_WGS84_UTM_zone_34N"}, + {32635, "PCS_WGS84_UTM_zone_35N"}, + {32636, "PCS_WGS84_UTM_zone_36N"}, + {32637, "PCS_WGS84_UTM_zone_37N"}, + {32638, "PCS_WGS84_UTM_zone_38N"}, + {32639, "PCS_WGS84_UTM_zone_39N"}, + {32640, "PCS_WGS84_UTM_zone_40N"}, + {32641, "PCS_WGS84_UTM_zone_41N"}, + {32642, "PCS_WGS84_UTM_zone_42N"}, + {32643, "PCS_WGS84_UTM_zone_43N"}, + {32644, "PCS_WGS84_UTM_zone_44N"}, + {32645, "PCS_WGS84_UTM_zone_45N"}, + {32646, "PCS_WGS84_UTM_zone_46N"}, + {32647, "PCS_WGS84_UTM_zone_47N"}, + {32648, "PCS_WGS84_UTM_zone_48N"}, + {32649, "PCS_WGS84_UTM_zone_49N"}, + {32650, "PCS_WGS84_UTM_zone_50N"}, + {32651, "PCS_WGS84_UTM_zone_51N"}, + {32652, "PCS_WGS84_UTM_zone_52N"}, + {32653, "PCS_WGS84_UTM_zone_53N"}, + {32654, "PCS_WGS84_UTM_zone_54N"}, + {32655, "PCS_WGS84_UTM_zone_55N"}, + {32656, "PCS_WGS84_UTM_zone_56N"}, + {32657, "PCS_WGS84_UTM_zone_57N"}, + {32658, "PCS_WGS84_UTM_zone_58N"}, + {32659, "PCS_WGS84_UTM_zone_59N"}, + {32660, "PCS_WGS84_UTM_zone_60N"}, + {32701, "PCS_WGS84_UTM_zone_1S"}, + {32702, "PCS_WGS84_UTM_zone_2S"}, + {32703, "PCS_WGS84_UTM_zone_3S"}, + {32704, "PCS_WGS84_UTM_zone_4S"}, + {32705, "PCS_WGS84_UTM_zone_5S"}, + {32706, "PCS_WGS84_UTM_zone_6S"}, + {32707, "PCS_WGS84_UTM_zone_7S"}, + {32708, "PCS_WGS84_UTM_zone_8S"}, + {32709, "PCS_WGS84_UTM_zone_9S"}, + {32710, "PCS_WGS84_UTM_zone_10S"}, + {32711, "PCS_WGS84_UTM_zone_11S"}, + {32712, "PCS_WGS84_UTM_zone_12S"}, + {32713, "PCS_WGS84_UTM_zone_13S"}, + {32714, "PCS_WGS84_UTM_zone_14S"}, + {32715, "PCS_WGS84_UTM_zone_15S"}, + {32716, "PCS_WGS84_UTM_zone_16S"}, + {32717, "PCS_WGS84_UTM_zone_17S"}, + {32718, "PCS_WGS84_UTM_zone_18S"}, + {32719, "PCS_WGS84_UTM_zone_19S"}, + {32720, "PCS_WGS84_UTM_zone_20S"}, + {32721, "PCS_WGS84_UTM_zone_21S"}, + {32722, "PCS_WGS84_UTM_zone_22S"}, + {32723, "PCS_WGS84_UTM_zone_23S"}, + {32724, "PCS_WGS84_UTM_zone_24S"}, + {32725, "PCS_WGS84_UTM_zone_25S"}, + {32726, "PCS_WGS84_UTM_zone_26S"}, + {32727, "PCS_WGS84_UTM_zone_27S"}, + {32728, "PCS_WGS84_UTM_zone_28S"}, + {32729, "PCS_WGS84_UTM_zone_29S"}, + {32730, "PCS_WGS84_UTM_zone_30S"}, + {32731, "PCS_WGS84_UTM_zone_31S"}, + {32732, "PCS_WGS84_UTM_zone_32S"}, + {32733, "PCS_WGS84_UTM_zone_33S"}, + {32734, "PCS_WGS84_UTM_zone_34S"}, + {32735, "PCS_WGS84_UTM_zone_35S"}, + {32736, "PCS_WGS84_UTM_zone_36S"}, + {32737, "PCS_WGS84_UTM_zone_37S"}, + {32738, "PCS_WGS84_UTM_zone_38S"}, + {32739, "PCS_WGS84_UTM_zone_39S"}, + {32740, "PCS_WGS84_UTM_zone_40S"}, + {32741, "PCS_WGS84_UTM_zone_41S"}, + {32742, "PCS_WGS84_UTM_zone_42S"}, + {32743, "PCS_WGS84_UTM_zone_43S"}, + {32744, "PCS_WGS84_UTM_zone_44S"}, + {32745, "PCS_WGS84_UTM_zone_45S"}, + {32746, "PCS_WGS84_UTM_zone_46S"}, + {32747, "PCS_WGS84_UTM_zone_47S"}, + {32748, "PCS_WGS84_UTM_zone_48S"}, + {32749, "PCS_WGS84_UTM_zone_49S"}, + {32750, "PCS_WGS84_UTM_zone_50S"}, + {32751, "PCS_WGS84_UTM_zone_51S"}, + {32752, "PCS_WGS84_UTM_zone_52S"}, + {32753, "PCS_WGS84_UTM_zone_53S"}, + {32754, "PCS_WGS84_UTM_zone_54S"}, + {32755, "PCS_WGS84_UTM_zone_55S"}, + {32756, "PCS_WGS84_UTM_zone_56S"}, + {32757, "PCS_WGS84_UTM_zone_57S"}, + {32758, "PCS_WGS84_UTM_zone_58S"}, + {32759, "PCS_WGS84_UTM_zone_59S"}, + {32760, "PCS_WGS84_UTM_zone_60S"} +}; -extern const TiffGeoTagKeyName ff_tiff_projection_codes[298]; +static const TiffGeoTagKeyName tiff_projection_codes[] = { + {10101, "Proj_Alabama_CS27_East"}, + {10102, "Proj_Alabama_CS27_West"}, + {10131, "Proj_Alabama_CS83_East"}, + {10132, "Proj_Alabama_CS83_West"}, + {10201, "Proj_Arizona_Coordinate_System_east"}, + {10202, "Proj_Arizona_Coordinate_System_Central"}, + {10203, "Proj_Arizona_Coordinate_System_west"}, + {10231, "Proj_Arizona_CS83_east"}, + {10232, "Proj_Arizona_CS83_Central"}, + {10233, "Proj_Arizona_CS83_west"}, + {10301, "Proj_Arkansas_CS27_North"}, + {10302, "Proj_Arkansas_CS27_South"}, + {10331, "Proj_Arkansas_CS83_North"}, + {10332, "Proj_Arkansas_CS83_South"}, + {10401, "Proj_California_CS27_I"}, + {10402, "Proj_California_CS27_II"}, + {10403, "Proj_California_CS27_III"}, + {10404, "Proj_California_CS27_IV"}, + {10405, "Proj_California_CS27_V"}, + {10406, "Proj_California_CS27_VI"}, + {10407, "Proj_California_CS27_VII"}, + {10431, "Proj_California_CS83_1"}, + {10432, "Proj_California_CS83_2"}, + {10433, "Proj_California_CS83_3"}, + {10434, "Proj_California_CS83_4"}, + {10435, "Proj_California_CS83_5"}, + {10436, "Proj_California_CS83_6"}, + {10501, "Proj_Colorado_CS27_North"}, + {10502, "Proj_Colorado_CS27_Central"}, + {10503, "Proj_Colorado_CS27_South"}, + {10531, "Proj_Colorado_CS83_North"}, + {10532, "Proj_Colorado_CS83_Central"}, + {10533, "Proj_Colorado_CS83_South"}, + {10600, "Proj_Connecticut_CS27"}, + {10630, "Proj_Connecticut_CS83"}, + {10700, "Proj_Delaware_CS27"}, + {10730, "Proj_Delaware_CS83"}, + {10901, "Proj_Florida_CS27_East"}, + {10902, "Proj_Florida_CS27_West"}, + {10903, "Proj_Florida_CS27_North"}, + {10931, "Proj_Florida_CS83_East"}, + {10932, "Proj_Florida_CS83_West"}, + {10933, "Proj_Florida_CS83_North"}, + {11001, "Proj_Georgia_CS27_East"}, + {11002, "Proj_Georgia_CS27_West"}, + {11031, "Proj_Georgia_CS83_East"}, + {11032, "Proj_Georgia_CS83_West"}, + {11101, "Proj_Idaho_CS27_East"}, + {11102, "Proj_Idaho_CS27_Central"}, + {11103, "Proj_Idaho_CS27_West"}, + {11131, "Proj_Idaho_CS83_East"}, + {11132, "Proj_Idaho_CS83_Central"}, + {11133, "Proj_Idaho_CS83_West"}, + {11201, "Proj_Illinois_CS27_East"}, + {11202, "Proj_Illinois_CS27_West"}, + {11231, "Proj_Illinois_CS83_East"}, + {11232, "Proj_Illinois_CS83_West"}, + {11301, "Proj_Indiana_CS27_East"}, + {11302, "Proj_Indiana_CS27_West"}, + {11331, "Proj_Indiana_CS83_East"}, + {11332, "Proj_Indiana_CS83_West"}, + {11401, "Proj_Iowa_CS27_North"}, + {11402, "Proj_Iowa_CS27_South"}, + {11431, "Proj_Iowa_CS83_North"}, + {11432, "Proj_Iowa_CS83_South"}, + {11501, "Proj_Kansas_CS27_North"}, + {11502, "Proj_Kansas_CS27_South"}, + {11531, "Proj_Kansas_CS83_North"}, + {11532, "Proj_Kansas_CS83_South"}, + {11601, "Proj_Kentucky_CS27_North"}, + {11602, "Proj_Kentucky_CS27_South"}, + {11631, "Proj_Kentucky_CS83_North"}, + {11632, "Proj_Kentucky_CS83_South"}, + {11701, "Proj_Louisiana_CS27_North"}, + {11702, "Proj_Louisiana_CS27_South"}, + {11731, "Proj_Louisiana_CS83_North"}, + {11732, "Proj_Louisiana_CS83_South"}, + {11801, "Proj_Maine_CS27_East"}, + {11802, "Proj_Maine_CS27_West"}, + {11831, "Proj_Maine_CS83_East"}, + {11832, "Proj_Maine_CS83_West"}, + {11900, "Proj_Maryland_CS27"}, + {11930, "Proj_Maryland_CS83"}, + {12001, "Proj_Massachusetts_CS27_Mainland"}, + {12002, "Proj_Massachusetts_CS27_Island"}, + {12031, "Proj_Massachusetts_CS83_Mainland"}, + {12032, "Proj_Massachusetts_CS83_Island"}, + {12101, "Proj_Michigan_State_Plane_East"}, + {12102, "Proj_Michigan_State_Plane_Old_Central"}, + {12103, "Proj_Michigan_State_Plane_West"}, + {12111, "Proj_Michigan_CS27_North"}, + {12112, "Proj_Michigan_CS27_Central"}, + {12113, "Proj_Michigan_CS27_South"}, + {12141, "Proj_Michigan_CS83_North"}, + {12142, "Proj_Michigan_CS83_Central"}, + {12143, "Proj_Michigan_CS83_South"}, + {12201, "Proj_Minnesota_CS27_North"}, + {12202, "Proj_Minnesota_CS27_Central"}, + {12203, "Proj_Minnesota_CS27_South"}, + {12231, "Proj_Minnesota_CS83_North"}, + {12232, "Proj_Minnesota_CS83_Central"}, + {12233, "Proj_Minnesota_CS83_South"}, + {12301, "Proj_Mississippi_CS27_East"}, + {12302, "Proj_Mississippi_CS27_West"}, + {12331, "Proj_Mississippi_CS83_East"}, + {12332, "Proj_Mississippi_CS83_West"}, + {12401, "Proj_Missouri_CS27_East"}, + {12402, "Proj_Missouri_CS27_Central"}, + {12403, "Proj_Missouri_CS27_West"}, + {12431, "Proj_Missouri_CS83_East"}, + {12432, "Proj_Missouri_CS83_Central"}, + {12433, "Proj_Missouri_CS83_West"}, + {12501, "Proj_Montana_CS27_North"}, + {12502, "Proj_Montana_CS27_Central"}, + {12503, "Proj_Montana_CS27_South"}, + {12530, "Proj_Montana_CS83"}, + {12601, "Proj_Nebraska_CS27_North"}, + {12602, "Proj_Nebraska_CS27_South"}, + {12630, "Proj_Nebraska_CS83"}, + {12701, "Proj_Nevada_CS27_East"}, + {12702, "Proj_Nevada_CS27_Central"}, + {12703, "Proj_Nevada_CS27_West"}, + {12731, "Proj_Nevada_CS83_East"}, + {12732, "Proj_Nevada_CS83_Central"}, + {12733, "Proj_Nevada_CS83_West"}, + {12800, "Proj_New_Hampshire_CS27"}, + {12830, "Proj_New_Hampshire_CS83"}, + {12900, "Proj_New_Jersey_CS27"}, + {12930, "Proj_New_Jersey_CS83"}, + {13001, "Proj_New_Mexico_CS27_East"}, + {13002, "Proj_New_Mexico_CS27_Central"}, + {13003, "Proj_New_Mexico_CS27_West"}, + {13031, "Proj_New_Mexico_CS83_East"}, + {13032, "Proj_New_Mexico_CS83_Central"}, + {13033, "Proj_New_Mexico_CS83_West"}, + {13101, "Proj_New_York_CS27_East"}, + {13102, "Proj_New_York_CS27_Central"}, + {13103, "Proj_New_York_CS27_West"}, + {13104, "Proj_New_York_CS27_Long_Island"}, + {13131, "Proj_New_York_CS83_East"}, + {13132, "Proj_New_York_CS83_Central"}, + {13133, "Proj_New_York_CS83_West"}, + {13134, "Proj_New_York_CS83_Long_Island"}, + {13200, "Proj_North_Carolina_CS27"}, + {13230, "Proj_North_Carolina_CS83"}, + {13301, "Proj_North_Dakota_CS27_North"}, + {13302, "Proj_North_Dakota_CS27_South"}, + {13331, "Proj_North_Dakota_CS83_North"}, + {13332, "Proj_North_Dakota_CS83_South"}, + {13401, "Proj_Ohio_CS27_North"}, + {13402, "Proj_Ohio_CS27_South"}, + {13431, "Proj_Ohio_CS83_North"}, + {13432, "Proj_Ohio_CS83_South"}, + {13501, "Proj_Oklahoma_CS27_North"}, + {13502, "Proj_Oklahoma_CS27_South"}, + {13531, "Proj_Oklahoma_CS83_North"}, + {13532, "Proj_Oklahoma_CS83_South"}, + {13601, "Proj_Oregon_CS27_North"}, + {13602, "Proj_Oregon_CS27_South"}, + {13631, "Proj_Oregon_CS83_North"}, + {13632, "Proj_Oregon_CS83_South"}, + {13701, "Proj_Pennsylvania_CS27_North"}, + {13702, "Proj_Pennsylvania_CS27_South"}, + {13731, "Proj_Pennsylvania_CS83_North"}, + {13732, "Proj_Pennsylvania_CS83_South"}, + {13800, "Proj_Rhode_Island_CS27"}, + {13830, "Proj_Rhode_Island_CS83"}, + {13901, "Proj_South_Carolina_CS27_North"}, + {13902, "Proj_South_Carolina_CS27_South"}, + {13930, "Proj_South_Carolina_CS83"}, + {14001, "Proj_South_Dakota_CS27_North"}, + {14002, "Proj_South_Dakota_CS27_South"}, + {14031, "Proj_South_Dakota_CS83_North"}, + {14032, "Proj_South_Dakota_CS83_South"}, + {14100, "Proj_Tennessee_CS27"}, + {14130, "Proj_Tennessee_CS83"}, + {14201, "Proj_Texas_CS27_North"}, + {14202, "Proj_Texas_CS27_North_Central"}, + {14203, "Proj_Texas_CS27_Central"}, + {14204, "Proj_Texas_CS27_South_Central"}, + {14205, "Proj_Texas_CS27_South"}, + {14231, "Proj_Texas_CS83_North"}, + {14232, "Proj_Texas_CS83_North_Central"}, + {14233, "Proj_Texas_CS83_Central"}, + {14234, "Proj_Texas_CS83_South_Central"}, + {14235, "Proj_Texas_CS83_South"}, + {14301, "Proj_Utah_CS27_North"}, + {14302, "Proj_Utah_CS27_Central"}, + {14303, "Proj_Utah_CS27_South"}, + {14331, "Proj_Utah_CS83_North"}, + {14332, "Proj_Utah_CS83_Central"}, + {14333, "Proj_Utah_CS83_South"}, + {14400, "Proj_Vermont_CS27"}, + {14430, "Proj_Vermont_CS83"}, + {14501, "Proj_Virginia_CS27_North"}, + {14502, "Proj_Virginia_CS27_South"}, + {14531, "Proj_Virginia_CS83_North"}, + {14532, "Proj_Virginia_CS83_South"}, + {14601, "Proj_Washington_CS27_North"}, + {14602, "Proj_Washington_CS27_South"}, + {14631, "Proj_Washington_CS83_North"}, + {14632, "Proj_Washington_CS83_South"}, + {14701, "Proj_West_Virginia_CS27_North"}, + {14702, "Proj_West_Virginia_CS27_South"}, + {14731, "Proj_West_Virginia_CS83_North"}, + {14732, "Proj_West_Virginia_CS83_South"}, + {14801, "Proj_Wisconsin_CS27_North"}, + {14802, "Proj_Wisconsin_CS27_Central"}, + {14803, "Proj_Wisconsin_CS27_South"}, + {14831, "Proj_Wisconsin_CS83_North"}, + {14832, "Proj_Wisconsin_CS83_Central"}, + {14833, "Proj_Wisconsin_CS83_South"}, + {14901, "Proj_Wyoming_CS27_East"}, + {14902, "Proj_Wyoming_CS27_East_Central"}, + {14903, "Proj_Wyoming_CS27_West_Central"}, + {14904, "Proj_Wyoming_CS27_West"}, + {14931, "Proj_Wyoming_CS83_East"}, + {14932, "Proj_Wyoming_CS83_East_Central"}, + {14933, "Proj_Wyoming_CS83_West_Central"}, + {14934, "Proj_Wyoming_CS83_West"}, + {15001, "Proj_Alaska_CS27_1"}, + {15002, "Proj_Alaska_CS27_2"}, + {15003, "Proj_Alaska_CS27_3"}, + {15004, "Proj_Alaska_CS27_4"}, + {15005, "Proj_Alaska_CS27_5"}, + {15006, "Proj_Alaska_CS27_6"}, + {15007, "Proj_Alaska_CS27_7"}, + {15008, "Proj_Alaska_CS27_8"}, + {15009, "Proj_Alaska_CS27_9"}, + {15010, "Proj_Alaska_CS27_10"}, + {15031, "Proj_Alaska_CS83_1"}, + {15032, "Proj_Alaska_CS83_2"}, + {15033, "Proj_Alaska_CS83_3"}, + {15034, "Proj_Alaska_CS83_4"}, + {15035, "Proj_Alaska_CS83_5"}, + {15036, "Proj_Alaska_CS83_6"}, + {15037, "Proj_Alaska_CS83_7"}, + {15038, "Proj_Alaska_CS83_8"}, + {15039, "Proj_Alaska_CS83_9"}, + {15040, "Proj_Alaska_CS83_10"}, + {15101, "Proj_Hawaii_CS27_1"}, + {15102, "Proj_Hawaii_CS27_2"}, + {15103, "Proj_Hawaii_CS27_3"}, + {15104, "Proj_Hawaii_CS27_4"}, + {15105, "Proj_Hawaii_CS27_5"}, + {15131, "Proj_Hawaii_CS83_1"}, + {15132, "Proj_Hawaii_CS83_2"}, + {15133, "Proj_Hawaii_CS83_3"}, + {15134, "Proj_Hawaii_CS83_4"}, + {15135, "Proj_Hawaii_CS83_5"}, + {15201, "Proj_Puerto_Rico_CS27"}, + {15202, "Proj_St_Croix"}, + {15230, "Proj_Puerto_Rico_Virgin_Is"}, + {15914, "Proj_BLM_14N_feet"}, + {15915, "Proj_BLM_15N_feet"}, + {15916, "Proj_BLM_16N_feet"}, + {15917, "Proj_BLM_17N_feet"}, + {17348, "Proj_Map_Grid_of_Australia_48"}, + {17349, "Proj_Map_Grid_of_Australia_49"}, + {17350, "Proj_Map_Grid_of_Australia_50"}, + {17351, "Proj_Map_Grid_of_Australia_51"}, + {17352, "Proj_Map_Grid_of_Australia_52"}, + {17353, "Proj_Map_Grid_of_Australia_53"}, + {17354, "Proj_Map_Grid_of_Australia_54"}, + {17355, "Proj_Map_Grid_of_Australia_55"}, + {17356, "Proj_Map_Grid_of_Australia_56"}, + {17357, "Proj_Map_Grid_of_Australia_57"}, + {17358, "Proj_Map_Grid_of_Australia_58"}, + {17448, "Proj_Australian_Map_Grid_48"}, + {17449, "Proj_Australian_Map_Grid_49"}, + {17450, "Proj_Australian_Map_Grid_50"}, + {17451, "Proj_Australian_Map_Grid_51"}, + {17452, "Proj_Australian_Map_Grid_52"}, + {17453, "Proj_Australian_Map_Grid_53"}, + {17454, "Proj_Australian_Map_Grid_54"}, + {17455, "Proj_Australian_Map_Grid_55"}, + {17456, "Proj_Australian_Map_Grid_56"}, + {17457, "Proj_Australian_Map_Grid_57"}, + {17458, "Proj_Australian_Map_Grid_58"}, + {18031, "Proj_Argentina_1"}, + {18032, "Proj_Argentina_2"}, + {18033, "Proj_Argentina_3"}, + {18034, "Proj_Argentina_4"}, + {18035, "Proj_Argentina_5"}, + {18036, "Proj_Argentina_6"}, + {18037, "Proj_Argentina_7"}, + {18051, "Proj_Colombia_3W"}, + {18052, "Proj_Colombia_Bogota"}, + {18053, "Proj_Colombia_3E"}, + {18054, "Proj_Colombia_6E"}, + {18072, "Proj_Egypt_Red_Belt"}, + {18073, "Proj_Egypt_Purple_Belt"}, + {18074, "Proj_Extended_Purple_Belt"}, + {18141, "Proj_New_Zealand_North_Island_Nat_Grid"}, + {18142, "Proj_New_Zealand_South_Island_Nat_Grid"}, + {19900, "Proj_Bahrain_Grid"}, + {19905, "Proj_Netherlands_E_Indies_Equatorial"}, + {19912, "Proj_RSO_Borneo"} +}; #define TIFF_COORD_TRANS_OFFSET 1 -extern const char *const ff_tiff_coord_trans_codes[27]; +static const char *const tiff_coord_trans_codes[] = { + "CT_TransverseMercator", + "CT_TransvMercator_Modified_Alaska", + "CT_ObliqueMercator", + "CT_ObliqueMercator_Laborde", + "CT_ObliqueMercator_Rosenmund", + "CT_ObliqueMercator_Spherical", + "CT_Mercator", + "CT_LambertConfConic_2SP", + "CT_LambertConfConic_Helmert", + "CT_LambertAzimEqualArea", + "CT_AlbersEqualArea", + "CT_AzimuthalEquidistant", + "CT_EquidistantConic", + "CT_Stereographic", + "CT_PolarStereographic", + "CT_ObliqueStereographic", + "CT_Equirectangular", + "CT_CassiniSoldner", + "CT_Gnomonic", + "CT_MillerCylindrical", + "CT_Orthographic", + "CT_Polyconic", + "CT_Robinson", + "CT_Sinusoidal", + "CT_VanDerGrinten", + "CT_NewZealandMapGrid", + "CT_TransvMercator_SouthOriented" +}; #define TIFF_VERT_CS_OFFSET 5001 -extern const char *const ff_tiff_vert_cs_codes[32]; +static const char *const tiff_vert_cs_codes[] = { + "VertCS_Airy_1830_ellipsoid", + "VertCS_Airy_Modified_1849_ellipsoid", + "VertCS_ANS_ellipsoid", + "VertCS_Bessel_1841_ellipsoid", + "VertCS_Bessel_Modified_ellipsoid", + "VertCS_Bessel_Namibia_ellipsoid", + "VertCS_Clarke_1858_ellipsoid", + "VertCS_Clarke_1866_ellipsoid", + "VertCS_Clarke_1880_Benoit_ellipsoid", + "VertCS_Clarke_1880_IGN_ellipsoid", + "VertCS_Clarke_1880_RGS_ellipsoid", + "VertCS_Clarke_1880_Arc_ellipsoid", + "VertCS_Clarke_1880_SGA_1922_ellipsoid", + "VertCS_Everest_1830_1937_Adjustment_ellipsoid", + "VertCS_Everest_1830_1967_Definition_ellipsoid", + "VertCS_Everest_1830_1975_Definition_ellipsoid", + "VertCS_Everest_1830_Modified_ellipsoid", + "VertCS_GRS_1980_ellipsoid", + "VertCS_Helmert_1906_ellipsoid", + "VertCS_INS_ellipsoid", + "VertCS_International_1924_ellipsoid", + "VertCS_International_1967_ellipsoid", + "VertCS_Krassowsky_1940_ellipsoid", + "VertCS_NWL_9D_ellipsoid", + "VertCS_NWL_10D_ellipsoid", + "VertCS_Plessis_1817_ellipsoid", + "VertCS_Struve_1860_ellipsoid", + "VertCS_War_Office_ellipsoid", + "VertCS_WGS_84_ellipsoid", + "VertCS_GEM_10C_ellipsoid", + "VertCS_OSU86F_ellipsoid", + "VertCS_OSU91A_ellipsoid" +}; #define TIFF_ORTHO_VERT_CS_OFFSET 5101 -extern const char *const ff_tiff_ortho_vert_cs_codes[6]; +static const char *const tiff_ortho_vert_cs_codes[] = { + "VertCS_Newlyn", + "VertCS_North_American_Vertical_Datum_1929", + "VertCS_North_American_Vertical_Datum_1988", + "VertCS_Yellow_Sea_1956", + "VertCS_Baltic_Sea", + "VertCS_Caspian_Sea" +}; + #endif diff -Nru ffmpeg-4.2.2/libavcodec/tiffenc.c ffmpeg-4.4/libavcodec/tiffenc.c --- ffmpeg-4.2.2/libavcodec/tiffenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tiffenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -421,7 +421,7 @@ if (s->compr == TIFF_LZW) { ff_lzw_encode_init(s->lzws, ptr, s->buf_size - (*s->buf - s->buf_start), - 12, FF_LZW_TIFF, put_bits); + 12, FF_LZW_TIFF, 0); } s->strip_offsets[i / s->rps] = ptr - pkt->data; } @@ -440,7 +440,7 @@ ptr += ret; if (s->compr == TIFF_LZW && (i == s->height - 1 || i % s->rps == s->rps - 1)) { - ret = ff_lzw_encode_flush(s->lzws, flush_put_bits); + ret = ff_lzw_encode_flush(s->lzws); s->strip_sizes[(i / s->rps)] += ret; ptr += ret; } @@ -582,7 +582,7 @@ .priv_data_size = sizeof(TiffEncoderContext), .init = encode_init, .close = encode_close, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .encode2 = encode_frame, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48LE, AV_PIX_FMT_PAL8, diff -Nru ffmpeg-4.2.2/libavcodec/tiff.h ffmpeg-4.4/libavcodec/tiff.h --- ffmpeg-4.2.2/libavcodec/tiff.h 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tiff.h 2020-07-11 10:39:30.000000000 +0000 @@ -92,6 +92,7 @@ TIFF_MODEL_TIEPOINT = 0x8482, TIFF_MODEL_PIXEL_SCALE = 0x830E, TIFF_MODEL_TRANSFORMATION= 0x8480, + TIFF_ICC_PROFILE = 0x8773, TIFF_GEO_KEY_DIRECTORY = 0x87AF, TIFF_GEO_DOUBLE_PARAMS = 0x87B0, TIFF_GEO_ASCII_PARAMS = 0x87B1, @@ -101,6 +102,8 @@ enum DngTags { DNG_VERSION = 0xC612, DNG_BACKWARD_VERSION = 0xC613, + DNG_LINEARIZATION_TABLE = 0xC618, + DNG_BLACK_LEVEL = 0xC61A, DNG_WHITE_LEVEL = 0xC61D, }; diff -Nru ffmpeg-4.2.2/libavcodec/tmv.c ffmpeg-4.4/libavcodec/tmv.c --- ffmpeg-4.2.2/libavcodec/tmv.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tmv.c 2021-04-08 21:28:39.000000000 +0000 @@ -94,4 +94,5 @@ .init = tmv_decode_init, .decode = tmv_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/trace_headers_bsf.c ffmpeg-4.4/libavcodec/trace_headers_bsf.c --- ffmpeg-4.2.2/libavcodec/trace_headers_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/trace_headers_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/log.h" #include "bsf.h" +#include "bsf_internal.h" #include "cbs.h" @@ -51,7 +52,7 @@ err = ff_cbs_read_extradata(ctx->cbc, frag, bsf->par_in); - ff_cbs_fragment_reset(ctx->cbc, frag); + ff_cbs_fragment_reset(frag); } return err; @@ -61,7 +62,7 @@ { TraceHeadersContext *ctx = bsf->priv_data; - ff_cbs_fragment_free(ctx->cbc, &ctx->fragment); + ff_cbs_fragment_free(&ctx->fragment); ff_cbs_close(&ctx->cbc); } @@ -96,7 +97,7 @@ err = ff_cbs_read_packet(ctx->cbc, frag, pkt); - ff_cbs_fragment_reset(ctx->cbc, frag); + ff_cbs_fragment_reset(frag); if (err < 0) av_packet_unref(pkt); diff -Nru ffmpeg-4.2.2/libavcodec/truehd_core_bsf.c ffmpeg-4.4/libavcodec/truehd_core_bsf.c --- ffmpeg-4.2.2/libavcodec/truehd_core_bsf.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/truehd_core_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "get_bits.h" #include "mlp_parse.h" #include "mlp.h" @@ -31,8 +31,6 @@ } AccessUnit; typedef struct TrueHDCoreContext { - const AVClass *class; - MLPHeaderInfo hdr; } TrueHDCoreContext; diff -Nru ffmpeg-4.2.2/libavcodec/truemotion1.c ffmpeg-4.4/libavcodec/truemotion1.c --- ffmpeg-4.2.2/libavcodec/truemotion1.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/truemotion1.c 2021-04-08 21:28:39.000000000 +0000 @@ -491,10 +491,8 @@ /* there is a vertical predictor for each pixel in a line; each vertical * predictor is 0 to start with */ av_fast_malloc(&s->vert_pred, &s->vert_pred_size, s->avctx->width * sizeof(unsigned int)); - if (!s->vert_pred) { - av_frame_free(&s->frame); + if (!s->vert_pred) return AVERROR(ENOMEM); - } return 0; } @@ -884,7 +882,7 @@ if ((ret = truemotion1_decode_header(s)) < 0) return ret; - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; if (compression_types[s->compression].algorithm == ALGO_RGB24H) { @@ -922,4 +920,5 @@ .close = truemotion1_decode_end, .decode = truemotion1_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/truemotion2.c ffmpeg-4.4/libavcodec/truemotion2.c --- ffmpeg-4.2.2/libavcodec/truemotion2.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/truemotion2.c 2021-04-08 21:28:39.000000000 +0000 @@ -81,7 +81,7 @@ int *clast; /* data for current and previous frame */ - int *Y1_base, *U1_base, *V1_base, *Y2_base, *U2_base, *V2_base; + int *Y_base, *UV_base; int *Y1, *U1, *V1, *Y2, *U2, *V2; int y_stride, uv_stride; int cur; @@ -108,15 +108,14 @@ int num; ///< current number filled int max_num; ///< total number of codes int *nums; ///< literals - uint32_t *bits; ///< codes - int *lens; ///< codelengths + uint8_t *lens; ///< codelengths } TM2Huff; /** * * @returns the length of the longest code or an AVERROR code */ -static int tm2_read_tree(TM2Context *ctx, uint32_t prefix, int length, TM2Huff *huff) +static int tm2_read_tree(TM2Context *ctx, int length, TM2Huff *huff) { int ret, ret2; if (length > huff->max_bits) { @@ -134,14 +133,13 @@ return AVERROR_INVALIDDATA; } huff->nums[huff->num] = get_bits_long(&ctx->gb, huff->val_bits); - huff->bits[huff->num] = prefix; huff->lens[huff->num] = length; huff->num++; return length; } else { /* non-terminal node */ - if ((ret2 = tm2_read_tree(ctx, prefix << 1, length + 1, huff)) < 0) + if ((ret2 = tm2_read_tree(ctx, length + 1, huff)) < 0) return ret2; - if ((ret = tm2_read_tree(ctx, (prefix << 1) | 1, length + 1, huff)) < 0) + if ((ret = tm2_read_tree(ctx, length + 1, huff)) < 0) return ret; } return FFMAX(ret, ret2); @@ -155,7 +153,7 @@ huff.val_bits = get_bits(&ctx->gb, 5); huff.max_bits = get_bits(&ctx->gb, 5); huff.min_bits = get_bits(&ctx->gb, 5); - huff.nodes = get_bits_long(&ctx->gb, 17); + huff.nodes = get_bits(&ctx->gb, 17); huff.num = 0; /* check for correct codes parameters */ @@ -177,15 +175,14 @@ /* allocate space for codes - it is exactly ceil(nodes / 2) entries */ huff.max_num = (huff.nodes + 1) >> 1; huff.nums = av_calloc(huff.max_num, sizeof(int)); - huff.bits = av_calloc(huff.max_num, sizeof(uint32_t)); - huff.lens = av_calloc(huff.max_num, sizeof(int)); + huff.lens = av_mallocz(huff.max_num); - if (!huff.nums || !huff.bits || !huff.lens) { + if (!huff.nums || !huff.lens) { res = AVERROR(ENOMEM); goto out; } - res = tm2_read_tree(ctx, 0, 0, &huff); + res = tm2_read_tree(ctx, 0, &huff); if (res >= 0 && res != huff.max_bits) { av_log(ctx->avctx, AV_LOG_ERROR, "Got less bits than expected: %i of %i\n", @@ -200,30 +197,22 @@ /* convert codes to vlc_table */ if (res >= 0) { - int i; - - res = init_vlc(&code->vlc, huff.max_bits, huff.max_num, - huff.lens, sizeof(int), sizeof(int), - huff.bits, sizeof(uint32_t), sizeof(uint32_t), 0); + res = ff_init_vlc_from_lengths(&code->vlc, huff.max_bits, huff.max_num, + huff.lens, sizeof(huff.lens[0]), + NULL, 0, 0, 0, 0, ctx->avctx); if (res < 0) av_log(ctx->avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); else { code->bits = huff.max_bits; code->length = huff.max_num; - code->recode = av_malloc_array(code->length, sizeof(int)); - if (!code->recode) { - res = AVERROR(ENOMEM); - goto out; - } - for (i = 0; i < code->length; i++) - code->recode[i] = huff.nums[i]; + code->recode = huff.nums; + huff.nums = NULL; } } out: /* free allocated memory */ av_free(huff.nums); - av_free(huff.bits); av_free(huff.lens); return res; @@ -443,7 +432,7 @@ clast = ctx->clast + bx * 4; #define TM2_INIT_POINTERS_2() \ - int *Yo, *Uo, *Vo;\ + unsigned *Yo, *Uo, *Vo;\ int oYstride, oUstride, oVstride;\ \ TM2_INIT_POINTERS();\ @@ -616,7 +605,7 @@ for (i = 0; i < 16; i++) deltas[i] = 0; - ct = ctx->D[0] + ctx->D[1] + ctx->D[2] + ctx->D[3]; + ct = (unsigned)ctx->D[0] + ctx->D[1] + ctx->D[2] + ctx->D[3]; if (bx > 0) left = last[-1] - (unsigned)ct; @@ -687,8 +676,8 @@ /* update chroma */ for (j = 0; j < 2; j++) { for (i = 0; i < 2; i++) { - U[i] = Uo[i] + (unsigned)GET_TOK(ctx, TM2_UPD); - V[i] = Vo[i] + (unsigned)GET_TOK(ctx, TM2_UPD); + U[i] = Uo[i] + GET_TOK(ctx, TM2_UPD); + V[i] = Vo[i] + GET_TOK(ctx, TM2_UPD); } U += Ustride; V += Vstride; @@ -701,10 +690,10 @@ TM2_RECALC_BLOCK(V, Vstride, (clast + 2), (ctx->CD + 2)); /* update deltas */ - ctx->D[0] = (unsigned)Yo[3] - last[3]; - ctx->D[1] = (unsigned)Yo[3 + oYstride] - Yo[3]; - ctx->D[2] = (unsigned)Yo[3 + oYstride * 2] - Yo[3 + oYstride]; - ctx->D[3] = (unsigned)Yo[3 + oYstride * 3] - Yo[3 + oYstride * 2]; + ctx->D[0] = Yo[3] - last[3]; + ctx->D[1] = Yo[3 + oYstride] - Yo[3]; + ctx->D[2] = Yo[3 + oYstride * 2] - Yo[3 + oYstride]; + ctx->D[3] = Yo[3 + oYstride * 3] - Yo[3 + oYstride * 2]; for (j = 0; j < 4; j++) { d = last[3]; @@ -915,7 +904,7 @@ return AVERROR(ENOMEM); } - if ((ret = ff_reget_buffer(avctx, p)) < 0) + if ((ret = ff_reget_buffer(avctx, p, 0)) < 0) return ret; l->bdsp.bswap_buf((uint32_t *) l->buffer, (const uint32_t *) buf, @@ -957,7 +946,7 @@ static av_cold int decode_init(AVCodecContext *avctx) { TM2Context * const l = avctx->priv_data; - int i, w = avctx->width, h = avctx->height; + int w = avctx->width, h = avctx->height; if ((avctx->width & 3) || (avctx->height & 3)) { av_log(avctx, AV_LOG_ERROR, "Width and height must be multiple of 4\n"); @@ -973,47 +962,29 @@ ff_bswapdsp_init(&l->bdsp); - l->last = av_malloc_array(w >> 2, 4 * sizeof(*l->last) ); - l->clast = av_malloc_array(w >> 2, 4 * sizeof(*l->clast)); - - for (i = 0; i < TM2_NUM_STREAMS; i++) { - l->tokens[i] = NULL; - l->tok_lens[i] = 0; - } + l->last = av_malloc_array(w, 2 * sizeof(*l->last)); + if (!l->last) + return AVERROR(ENOMEM); + l->clast = l->last + w; w += 8; h += 8; - l->Y1_base = av_calloc(w * h, sizeof(*l->Y1_base)); - l->Y2_base = av_calloc(w * h, sizeof(*l->Y2_base)); + l->Y_base = av_calloc(w * h, 2 * sizeof(*l->Y_base)); + if (!l->Y_base) + return AVERROR(ENOMEM); l->y_stride = w; + l->Y1 = l->Y_base + l->y_stride * 4 + 4; + l->Y2 = l->Y1 + w * h; w = (w + 1) >> 1; h = (h + 1) >> 1; - l->U1_base = av_calloc(w * h, sizeof(*l->U1_base)); - l->V1_base = av_calloc(w * h, sizeof(*l->V1_base)); - l->U2_base = av_calloc(w * h, sizeof(*l->U2_base)); - l->V2_base = av_calloc(w * h, sizeof(*l->V1_base)); - l->uv_stride = w; - l->cur = 0; - if (!l->Y1_base || !l->Y2_base || !l->U1_base || - !l->V1_base || !l->U2_base || !l->V2_base || - !l->last || !l->clast) { - av_freep(&l->Y1_base); - av_freep(&l->Y2_base); - av_freep(&l->U1_base); - av_freep(&l->U2_base); - av_freep(&l->V1_base); - av_freep(&l->V2_base); - av_freep(&l->last); - av_freep(&l->clast); - av_frame_free(&l->pic); + l->UV_base = av_calloc(w * h, 4 * sizeof(*l->UV_base)); + if (!l->UV_base) return AVERROR(ENOMEM); - } - l->Y1 = l->Y1_base + l->y_stride * 4 + 4; - l->Y2 = l->Y2_base + l->y_stride * 4 + 4; - l->U1 = l->U1_base + l->uv_stride * 2 + 2; - l->U2 = l->U2_base + l->uv_stride * 2 + 2; - l->V1 = l->V1_base + l->uv_stride * 2 + 2; - l->V2 = l->V2_base + l->uv_stride * 2 + 2; + l->uv_stride = w; + l->U1 = l->UV_base + l->uv_stride * 2 + 2; + l->U2 = l->U1 + w * h; + l->V1 = l->U2 + w * h; + l->V2 = l->V1 + w * h; return 0; } @@ -1023,18 +994,12 @@ TM2Context * const l = avctx->priv_data; int i; - av_free(l->last); - av_free(l->clast); + av_freep(&l->last); for (i = 0; i < TM2_NUM_STREAMS; i++) av_freep(&l->tokens[i]); - if (l->Y1) { - av_freep(&l->Y1_base); - av_freep(&l->U1_base); - av_freep(&l->V1_base); - av_freep(&l->Y2_base); - av_freep(&l->U2_base); - av_freep(&l->V2_base); - } + + av_freep(&l->Y_base); + av_freep(&l->UV_base); av_freep(&l->buffer); l->buffer_size = 0; @@ -1053,4 +1018,5 @@ .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/truespeech.c ffmpeg-4.4/libavcodec/truespeech.c --- ffmpeg-4.2.2/libavcodec/truespeech.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/truespeech.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,8 @@ #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "bswapdsp.h" #include "get_bits.h" @@ -132,8 +134,7 @@ if(i > 0){ memcpy(tmp, dec->cvector, i * sizeof(*tmp)); for(j = 0; j < i; j++) - dec->cvector[j] = ((tmp[i - j - 1] * dec->vector[i]) + - (dec->cvector[j] << 15) + 0x4000) >> 15; + dec->cvector[j] += (tmp[i - j - 1] * dec->vector[i] + 0x4000) >> 15; } dec->cvector[i] = (8 - dec->vector[i]) >> 3; } @@ -255,8 +256,8 @@ for(i = 0; i < 60; i++){ int sum = 0; for(k = 0; k < 8; k++) - sum += ptr0[k] * ptr1[k]; - sum = (sum + (out[i] << 12) + 0x800) >> 12; + sum += ptr0[k] * (unsigned)ptr1[k]; + sum = out[i] + ((int)(sum + 0x800U) >> 12); out[i] = av_clip(sum, -0x7FFE, 0x7FFE); for(k = 7; k > 0; k--) ptr0[k] = ptr0[k - 1]; @@ -274,7 +275,7 @@ for(k = 7; k > 0; k--) ptr0[k] = ptr0[k - 1]; ptr0[0] = out[i]; - out[i] = ((out[i] << 12) - sum) >> 12; + out[i] += (- sum) >> 12; } for(i = 0; i < 8; i++) @@ -282,7 +283,7 @@ ptr0 = dec->tmp3; for(i = 0; i < 60; i++){ - int sum = out[i] << 12; + int sum = out[i] * (1 << 12); for(k = 0; k < 8; k++) sum += ptr0[k] * t[k]; for(k = 7; k > 0; k--) diff -Nru ffmpeg-4.2.2/libavcodec/tscc2.c ffmpeg-4.4/libavcodec/tscc2.c --- ffmpeg-4.2.2/libavcodec/tscc2.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tscc2.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,8 @@ #include +#include "libavutil/thread.h" + #define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" @@ -34,6 +36,8 @@ #include "mathops.h" #include "tscc2data.h" +#define TSCC2_VLC_BITS 9 + typedef struct TSCC2Context { AVCodecContext *avctx; AVFrame *pic; @@ -43,52 +47,43 @@ int q[2][3]; GetBitContext gb; - VLC dc_vlc, nc_vlc[NUM_VLC_SETS], ac_vlc[NUM_VLC_SETS]; int block[16]; } TSCC2Context; -static av_cold void free_vlcs(TSCC2Context *c) +static VLC dc_vlc, nc_vlc[NUM_VLC_SETS], ac_vlc[NUM_VLC_SETS]; + +static av_cold void tscc2_init_vlc(VLC *vlc, int *offset, int nb_codes, + const uint8_t *lens, const void *syms, + int sym_length) { - int i; + static VLC_TYPE vlc_buf[15442][2]; - ff_free_vlc(&c->dc_vlc); - for (i = 0; i < NUM_VLC_SETS; i++) { - ff_free_vlc(c->nc_vlc + i); - ff_free_vlc(c->ac_vlc + i); - } + vlc->table = &vlc_buf[*offset]; + vlc->table_allocated = FF_ARRAY_ELEMS(vlc_buf) - *offset; + ff_init_vlc_from_lengths(vlc, TSCC2_VLC_BITS, nb_codes, + lens, 1, syms, sym_length, sym_length, 0, + INIT_VLC_STATIC_OVERLONG | INIT_VLC_OUTPUT_LE, NULL); + *offset += vlc->table_size; } -static av_cold int init_vlcs(TSCC2Context *c) +static av_cold void tscc2_init_vlcs(void) { - int i, ret; + const uint16_t *ac_vlc_syms = tscc2_ac_vlc_syms; + const uint8_t *ac_vlc_lens = tscc2_ac_vlc_lens; + int i, offset = 0; - ret = ff_init_vlc_sparse(&c->dc_vlc, 9, DC_VLC_COUNT, - tscc2_dc_vlc_bits, 1, 1, - tscc2_dc_vlc_codes, 2, 2, - tscc2_dc_vlc_syms, 2, 2, INIT_VLC_LE); - if (ret) - return ret; + tscc2_init_vlc(&dc_vlc, &offset, DC_VLC_COUNT, + tscc2_dc_vlc_lens, tscc2_dc_vlc_syms, 2); for (i = 0; i < NUM_VLC_SETS; i++) { - ret = ff_init_vlc_sparse(c->nc_vlc + i, 9, 16, - tscc2_nc_vlc_bits[i], 1, 1, - tscc2_nc_vlc_codes[i], 2, 2, - tscc2_nc_vlc_syms, 1, 1, INIT_VLC_LE); - if (ret) { - free_vlcs(c); - return ret; - } - ret = ff_init_vlc_sparse(c->ac_vlc + i, 9, tscc2_ac_vlc_sizes[i], - tscc2_ac_vlc_bits[i], 1, 1, - tscc2_ac_vlc_codes[i], 2, 2, - tscc2_ac_vlc_syms[i], 2, 2, INIT_VLC_LE); - if (ret) { - free_vlcs(c); - return ret; - } - } + tscc2_init_vlc(&nc_vlc[i], &offset, 16, + tscc2_nc_vlc_lens[i], tscc2_nc_vlc_syms[i], 1); - return 0; + tscc2_init_vlc(&ac_vlc[i], &offset, tscc2_ac_vlc_sizes[i], + ac_vlc_lens, ac_vlc_syms, 2); + ac_vlc_lens += tscc2_ac_vlc_sizes[i]; + ac_vlc_syms += tscc2_ac_vlc_sizes[i]; + } } #define DEQUANT(val, q) (((q) * (val) + 0x80) >> 8) @@ -154,9 +149,7 @@ if (!(j | k)) { dc = get_bits(gb, 8); } else { - dc = get_vlc2(gb, c->dc_vlc.table, 9, 2); - if (dc == -1) - return AVERROR_INVALIDDATA; + dc = get_vlc2(gb, dc_vlc.table, TSCC2_VLC_BITS, 2); if (dc == 0x100) dc = get_bits(gb, 8); } @@ -164,16 +157,12 @@ prev_dc = dc; c->block[0] = dc; - nc = get_vlc2(gb, c->nc_vlc[vlc_set].table, 9, 1); - if (nc == -1) - return AVERROR_INVALIDDATA; + nc = get_vlc2(gb, nc_vlc[vlc_set].table, TSCC2_VLC_BITS, 1); bpos = 1; memset(c->block + 1, 0, 15 * sizeof(*c->block)); for (l = 0; l < nc; l++) { - ac = get_vlc2(gb, c->ac_vlc[vlc_set].table, 9, 2); - if (ac == -1) - return AVERROR_INVALIDDATA; + ac = get_vlc2(gb, ac_vlc[vlc_set].table, TSCC2_VLC_BITS, 2); if (ac == 0x1000) ac = get_bits(gb, 12); bpos += ac & 0xF; @@ -240,7 +229,7 @@ return buf_size; } - if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) { + if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) { return ret; } @@ -336,7 +325,6 @@ av_frame_free(&c->pic); av_freep(&c->slice_quants); - free_vlcs(c); return 0; } @@ -344,31 +332,25 @@ static av_cold int tscc2_decode_init(AVCodecContext *avctx) { TSCC2Context * const c = avctx->priv_data; - int ret; + static AVOnce init_static_once = AV_ONCE_INIT; c->avctx = avctx; avctx->pix_fmt = AV_PIX_FMT_YUV444P; - if ((ret = init_vlcs(c)) < 0) { - av_log(avctx, AV_LOG_ERROR, "Cannot initialise VLCs\n"); - return ret; - } - c->mb_width = FFALIGN(avctx->width, 16) >> 4; c->mb_height = FFALIGN(avctx->height, 8) >> 3; c->slice_quants = av_malloc(c->mb_width * c->mb_height); if (!c->slice_quants) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate slice information\n"); - free_vlcs(c); return AVERROR(ENOMEM); } c->pic = av_frame_alloc(); - if (!c->pic) { - tscc2_decode_end(avctx); + if (!c->pic) return AVERROR(ENOMEM); - } + + ff_thread_once(&init_static_once, tscc2_init_vlcs); return 0; } @@ -383,4 +365,5 @@ .close = tscc2_decode_end, .decode = tscc2_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/tscc2data.h ffmpeg-4.4/libavcodec/tscc2data.h --- ffmpeg-4.2.2/libavcodec/tscc2data.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tscc2data.h 2021-04-08 21:28:39.000000000 +0000 @@ -37,892 +37,399 @@ #define DC_VLC_COUNT 47 static const uint16_t tscc2_dc_vlc_syms[DC_VLC_COUNT] = { - 0x100, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, - 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, - 0xF0, 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0x17, - 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F, - 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, - 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, -}; - -static const uint16_t tscc2_dc_vlc_codes[DC_VLC_COUNT] = { - 0x000A, 0x0000, 0x0006, 0x002E, 0x0002, 0x000E, 0x001A, 0x007E, - 0x004E, 0x005A, 0x00E2, 0x01BE, 0x01BA, 0x00BA, 0x0072, 0x0022, - 0x02BE, 0x00BE, 0x033A, 0x03F2, 0x01F2, 0x03A2, 0x0122, 0x0322, - 0x01A2, 0x0172, 0x0372, 0x013A, 0x00CE, 0x02CE, 0x02FE, 0x00FE, - 0x00A2, 0x00F2, 0x003A, 0x01CE, 0x01FE, 0x0062, 0x00DA, 0x003E, - 0x0032, 0x007A, 0x0012, 0x001E, 0x0016, 0x0004, 0x0001, -}; - -static const uint8_t tscc2_dc_vlc_bits[DC_VLC_COUNT] = { - 5, 3, 5, 6, 6, 7, 7, 8, - 8, 8, 8, 9, 9, 9, 9, 9, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, - 9, 9, 9, 9, 9, 8, 8, 8, - 7, 7, 6, 6, 5, 3, 1, -}; - -static const uint8_t tscc2_nc_vlc_syms[16] = { - 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, - 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, -}; - -static const uint16_t tscc2_nc_vlc_codes[NUM_VLC_SETS][16] = { - { 0x0023, 0x0003, 0x0031, 0x0021, 0x0011, 0x0053, 0x0013, 0x0001, - 0x0009, 0x0029, 0x0033, 0x0019, 0x000B, 0x0005, 0x0007, 0x0000, }, - { 0x0030, 0x0022, 0x0028, 0x0020, 0x0008, 0x0000, 0x0032, 0x0072, - 0x0010, 0x0002, 0x0012, 0x0018, 0x000A, 0x0004, 0x0006, 0x0001, }, - { 0x0032, 0x0038, 0x0020, 0x0008, 0x0002, 0x0018, 0x0072, 0x0000, - 0x0028, 0x0022, 0x0012, 0x0010, 0x000A, 0x0004, 0x0006, 0x0001, }, - { 0x0032, 0x0010, 0x0072, 0x0030, 0x0022, 0x0038, 0x0008, 0x0028, - 0x0018, 0x0002, 0x0012, 0x0000, 0x000A, 0x0004, 0x0006, 0x0001, }, - { 0x0012, 0x0052, 0x0000, 0x0020, 0x0018, 0x0022, 0x0008, 0x0028, - 0x0038, 0x0002, 0x0032, 0x0010, 0x000A, 0x0004, 0x0006, 0x0001, }, - { 0x0016, 0x0096, 0x0006, 0x0046, 0x0056, 0x0002, 0x0036, 0x0076, - 0x0012, 0x0022, 0x0032, 0x0026, 0x000A, 0x000E, 0x0000, 0x0001, }, - { 0x001A, 0x009A, 0x0032, 0x0072, 0x005A, 0x007A, 0x003A, 0x0002, - 0x0012, 0x0022, 0x000A, 0x002A, 0x0006, 0x000E, 0x0000, 0x0001, }, - { 0x002A, 0x00AA, 0x0002, 0x0042, 0x006A, 0x003A, 0x007A, 0x0022, - 0x0032, 0x0012, 0x000A, 0x001A, 0x0006, 0x000E, 0x0000, 0x0001, }, - { 0x0042, 0x00C2, 0x0002, 0x000A, 0x004A, 0x003A, 0x007A, 0x0022, - 0x0012, 0x0032, 0x002A, 0x001A, 0x0006, 0x000E, 0x0000, 0x0001, }, - { 0x00BA, 0x01BA, 0x003A, 0x0012, 0x0052, 0x007A, 0x0002, 0x0022, - 0x0032, 0x000A, 0x002A, 0x001A, 0x0000, 0x0004, 0x0006, 0x0001, }, - { 0x00AA, 0x01AA, 0x002A, 0x0022, 0x0062, 0x006A, 0x0002, 0x0012, - 0x0032, 0x000A, 0x001A, 0x003A, 0x0000, 0x0004, 0x0006, 0x0001, }, - { 0x00AA, 0x01AA, 0x002A, 0x0022, 0x0062, 0x006A, 0x0002, 0x0012, - 0x0032, 0x000A, 0x003A, 0x001A, 0x0000, 0x0004, 0x0006, 0x0001, }, - { 0x008A, 0x018A, 0x000A, 0x0022, 0x0062, 0x004A, 0x0002, 0x0012, - 0x0032, 0x002A, 0x001A, 0x003A, 0x0000, 0x0004, 0x0006, 0x0001, }, -}; - -static const uint8_t tscc2_nc_vlc_bits[NUM_VLC_SETS][16] = { - { 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 5, 4, 3, 3, 1 }, - { 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 5, 4, 3, 3, 1 }, - { 7, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 5, 4, 3, 3, 1 }, - { 7, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 4, 3, 3, 1 }, - { 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 4, 3, 3, 1 }, - { 8, 8, 7, 7, 7, 6, 7, 7, 6, 6, 6, 6, 4, 4, 2, 1 }, - { 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 4, 4, 2, 1 }, - { 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 4, 4, 2, 1 }, - { 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 4, 4, 2, 1 }, - { 9, 9, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1 }, - { 9, 9, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1 }, - { 9, 9, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1 }, - { 9, 9, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1 }, -}; - -static const uint16_t ac_vlc_desc0_syms[172] = { - 0x1000, 0xFF8, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, 0xFF1, - 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, 0xFE0, - 0xFD6, 0xFD5, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC6, 0xFC5, - 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB5, 0xFB3, 0xFB2, 0xFB1, - 0xFB0, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF95, 0xF91, 0xF90, - 0xF83, 0xF81, 0xF80, 0xF73, 0xF71, 0xF70, 0xF61, 0xF60, - 0xF51, 0xF50, 0xF45, 0xF41, 0xF40, 0xF31, 0xF30, 0xF21, - 0xF20, 0xF10, 0xF00, 0xEF0, 0xEE0, 0xED5, 0xED1, 0xED0, - 0xEC0, 0xEB0, 0xEA0, 0xE90, 0xE80, 0xE70, 0xE60, 0xE50, - 0xE40, 0xE30, 0xE20, 0xE10, 0xE00, 0xDF0, 0xDE0, 0xDD0, - 0xDC0, 0xDB0, 0xDA0, 0xD90, 0xD80, 0xD60, 0xCD1, 0x280, - 0x270, 0x260, 0x250, 0x240, 0x230, 0x220, 0x210, 0x200, - 0x1F0, 0x1E0, 0x1D0, 0x1C0, 0x1B0, 0x1A1, 0x1A0, 0x190, - 0x180, 0x170, 0x160, 0x150, 0x140, 0x130, 0x121, 0x120, - 0x111, 0x110, 0x101, 0x100, 0x0F1, 0x0F0, 0x0E1, 0x0E0, - 0x0D1, 0x0D0, 0x0C1, 0x0C0, 0x0B1, 0x0B0, 0x0A5, 0x0A1, - 0x0A0, 0x091, 0x090, 0x081, 0x080, 0x075, 0x071, 0x070, - 0x065, 0x063, 0x061, 0x060, 0x055, 0x053, 0x052, 0x051, - 0x050, 0x046, 0x045, 0x043, 0x042, 0x041, 0x040, 0x036, - 0x035, 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, 0x024, - 0x023, 0x022, 0x021, 0x020, 0x018, 0x016, 0x015, 0x014, - 0x013, 0x012, 0x011, 0x010, -}; - -static const uint16_t ac_vlc_desc0_codes[172] = { - 0x001F, 0x0D71, 0x013F, 0x006C, 0x00A7, 0x0067, 0x001C, 0x0008, - 0x0005, 0x06F1, 0x002C, 0x04BA, 0x0072, 0x01AA, 0x0002, 0x0006, - 0x06AC, 0x02AF, 0x06EF, 0x018F, 0x000A, 0x0009, 0x02AC, 0x042A, - 0x06E1, 0x068F, 0x00B1, 0x0000, 0x0317, 0x0C17, 0x0612, 0x010F, - 0x0011, 0x0FBA, 0x002A, 0x0172, 0x000C, 0x05AC, 0x03D7, 0x0037, - 0x0E8F, 0x02F2, 0x0041, 0x0BE1, 0x057F, 0x004A, 0x00AF, 0x006F, - 0x06AA, 0x0097, 0x0101, 0x0012, 0x0081, 0x0571, 0x0092, 0x0EAF, - 0x01BF, 0x00D7, 0x0031, 0x0001, 0x01F2, 0x0F17, 0x053A, 0x00BF, - 0x038F, 0x0217, 0x0371, 0x01F1, 0x01BA, 0x022A, 0x02BF, 0x028F, - 0x008F, 0x03F1, 0x00E1, 0x00BA, 0x00F2, 0x0EBF, 0x06AF, 0x048F, - 0x0FE1, 0x0271, 0x07BA, 0x0D3A, 0x0C12, 0x08AC, 0x0717, 0x00AC, - 0x0412, 0x0901, 0x04E1, 0x07E1, 0x0417, 0x0CAF, 0x04AC, 0x01AC, - 0x04F2, 0x03BA, 0x05D7, 0x07F1, 0x01D7, 0x04AF, 0x04EF, 0x03AC, - 0x00AA, 0x01E1, 0x0071, 0x00F1, 0x012C, 0x03EF, 0x082A, 0x0112, - 0x03E1, 0x01FA, 0x0DAC, 0x0131, 0x0E12, 0x000F, 0x0B17, 0x007F, - 0x0AEF, 0x007A, 0x02AA, 0x0061, 0x0671, 0x0027, 0x013A, 0x058F, - 0x00FF, 0x033A, 0x0032, 0x0301, 0x0021, 0x0C8F, 0x037F, 0x0077, - 0x02F1, 0x02E1, 0x003A, 0x003C, 0x0212, 0x0817, 0x0CE1, 0x003F, - 0x0007, 0x0017, 0x0501, 0x02BA, 0x06BF, 0x0057, 0x0010, 0x02EF, - 0x0117, 0x017F, 0x00EF, 0x006A, 0x0019, 0x0171, 0x01EF, 0x06BA, - 0x012A, 0x00FA, 0x0022, 0x000E, 0x0AE1, 0x01AF, 0x0052, 0x002F, - 0x004F, 0x001A, 0x0004, 0x0003, -}; - -static const uint8_t ac_vlc_desc0_bits[172] = { - 6, 12, 9, 7, 8, 7, 6, 4, - 3, 11, 9, 11, 9, 9, 6, 4, - 11, 11, 11, 11, 7, 5, 11, 11, - 11, 12, 8, 5, 12, 12, 12, 9, - 6, 12, 12, 9, 6, 12, 10, 7, - 12, 10, 7, 12, 11, 7, 11, 8, - 11, 8, 12, 11, 8, 12, 8, 12, - 9, 9, 9, 9, 9, 12, 12, 10, - 10, 10, 10, 10, 10, 10, 11, 11, - 11, 11, 11, 11, 11, 12, 12, 12, - 12, 11, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 11, 11, - 11, 11, 11, 11, 11, 12, 11, 10, - 10, 10, 10, 10, 9, 10, 12, 9, - 12, 9, 12, 9, 12, 9, 12, 9, - 12, 8, 11, 8, 11, 8, 11, 11, - 8, 10, 7, 10, 7, 12, 10, 7, - 11, 12, 9, 6, 11, 12, 12, 9, - 6, 12, 11, 11, 12, 8, 5, 12, - 10, 11, 11, 7, 5, 11, 10, 11, - 9, 9, 6, 4, 12, 9, 7, 8, - 7, 6, 4, 3, -}; - -static const uint16_t ac_vlc_desc1_syms[169] = { - 0x1000, 0xFF8, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, 0xFF1, - 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, 0xFE0, - 0xFD6, 0xFD5, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC6, 0xFC5, - 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, 0xFB2, - 0xFB1, 0xFB0, 0xFA6, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF95, - 0xF93, 0xF91, 0xF90, 0xF85, 0xF81, 0xF80, 0xF71, 0xF70, - 0xF61, 0xF60, 0xF51, 0xF50, 0xF45, 0xF41, 0xF40, 0xF31, - 0xF30, 0xF21, 0xF20, 0xF11, 0xF10, 0xF01, 0xF00, 0xEF1, - 0xEF0, 0xEE1, 0xEE0, 0xED0, 0xEC6, 0xEC0, 0xEB6, 0xEB0, - 0xEA0, 0xE90, 0xE80, 0xE70, 0xE60, 0xE50, 0xE40, 0xE33, - 0xE31, 0xE30, 0xE20, 0xE10, 0xE00, 0xDF0, 0xDE1, 0xDE0, - 0xDC0, 0xDB0, 0xDA0, 0x250, 0x240, 0x1F0, 0x1E0, 0x1D0, - 0x1C0, 0x1B0, 0x1A0, 0x190, 0x180, 0x170, 0x160, 0x150, - 0x140, 0x130, 0x120, 0x111, 0x110, 0x101, 0x100, 0x0F1, - 0x0F0, 0x0E1, 0x0E0, 0x0D1, 0x0D0, 0x0C6, 0x0C1, 0x0C0, - 0x0B1, 0x0B0, 0x0A1, 0x0A0, 0x095, 0x091, 0x090, 0x085, - 0x081, 0x080, 0x075, 0x071, 0x070, 0x065, 0x063, 0x061, - 0x060, 0x055, 0x053, 0x052, 0x051, 0x050, 0x046, 0x045, - 0x043, 0x042, 0x041, 0x040, 0x036, 0x035, 0x033, 0x032, - 0x031, 0x030, 0x026, 0x025, 0x024, 0x023, 0x022, 0x021, - 0x020, 0x018, 0x016, 0x015, 0x014, 0x013, 0x012, 0x011, - 0x010, -}; - -static const uint16_t ac_vlc_desc1_codes[169] = { - 0x0019, 0x027D, 0x0084, 0x0044, 0x009D, 0x003D, 0x000A, 0x0002, - 0x0003, 0x00EA, 0x02FD, 0x017A, 0x01C6, 0x00B6, 0x0026, 0x000E, - 0x0095, 0x0260, 0x032A, 0x0360, 0x0006, 0x0005, 0x05B6, 0x036A, - 0x06F6, 0x0704, 0x00FA, 0x0010, 0x0279, 0x04D4, 0x00F6, 0x066A, - 0x001D, 0x0029, 0x05F9, 0x0846, 0x04F6, 0x01D4, 0x0038, 0x0446, - 0x0160, 0x031D, 0x0075, 0x0054, 0x02D4, 0x005A, 0x05FD, 0x0040, - 0x06EA, 0x0055, 0x0460, 0x009A, 0x052A, 0x00A0, 0x00D8, 0x0380, - 0x017D, 0x092A, 0x00F9, 0x0D7A, 0x0179, 0x0304, 0x002A, 0x0104, - 0x01A0, 0x0780, 0x007D, 0x03F9, 0x0C46, 0x03EA, 0x0E6A, 0x0204, - 0x01FD, 0x051D, 0x02AA, 0x05EA, 0x00AA, 0x0080, 0x067D, 0x09EA, - 0x0C95, 0x09F9, 0x07B6, 0x0DB6, 0x012A, 0x0904, 0x0454, 0x0FB6, - 0x0960, 0x08D4, 0x0495, 0x0F80, 0x0560, 0x0B04, 0x057A, 0x0079, - 0x0795, 0x0E7D, 0x0060, 0x076A, 0x03B6, 0x0395, 0x0180, 0x02A0, - 0x006A, 0x0195, 0x0295, 0x0646, 0x03FD, 0x01F9, 0x0154, 0x0DF9, - 0x00C6, 0x0F95, 0x01F6, 0x0480, 0x0000, 0x0A79, 0x04AA, 0x00E0, - 0x0246, 0x001A, 0x0479, 0x0015, 0x0D60, 0x0280, 0x0018, 0x01EA, - 0x037A, 0x003A, 0x011D, 0x00FD, 0x0035, 0x0A7D, 0x04A0, 0x0146, - 0x0024, 0x01B6, 0x0504, 0x0046, 0x0020, 0x0009, 0x00D4, 0x03AA, - 0x0679, 0x026A, 0x0036, 0x0008, 0x02F6, 0x01AA, 0x016A, 0x0254, - 0x0039, 0x000D, 0x0004, 0x0176, 0x02EA, 0x007A, 0x0076, 0x0016, - 0x0001, 0x0879, 0x0058, 0x0014, 0x00D5, 0x005D, 0x0034, 0x000C, - 0x0007, -}; - -static const uint8_t ac_vlc_desc1_bits[169] = { - 6, 12, 8, 7, 8, 7, 6, 4, - 3, 10, 10, 11, 9, 9, 6, 4, - 11, 10, 10, 10, 7, 5, 12, 11, - 11, 11, 8, 5, 12, 11, 11, 12, - 9, 6, 12, 12, 11, 9, 6, 12, - 12, 10, 7, 11, 10, 7, 11, 7, - 11, 8, 11, 8, 11, 11, 8, 11, - 9, 12, 9, 12, 9, 12, 9, 12, - 9, 12, 10, 10, 12, 10, 12, 10, - 11, 11, 10, 11, 11, 11, 12, 12, - 12, 12, 12, 12, 12, 12, 11, 12, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 11, 11, 11, 11, 10, 10, - 10, 10, 10, 11, 10, 12, 9, 12, - 9, 12, 9, 11, 8, 12, 11, 8, - 11, 8, 11, 8, 12, 10, 7, 12, - 10, 7, 11, 10, 7, 12, 11, 9, - 6, 11, 11, 12, 8, 6, 12, 10, - 11, 11, 8, 5, 11, 10, 10, 10, - 7, 5, 10, 9, 11, 9, 9, 6, - 4, 12, 8, 7, 8, 7, 6, 4, - 3, -}; - -static const uint16_t ac_vlc_desc2_syms[165] = { - 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, - 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, - 0xFE0, 0xFD6, 0xFD5, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC6, - 0xFC5, 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, - 0xFB2, 0xFB1, 0xFB0, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF95, - 0xF93, 0xF91, 0xF90, 0xF81, 0xF80, 0xF75, 0xF71, 0xF70, - 0xF61, 0xF60, 0xF51, 0xF50, 0xF41, 0xF40, 0xF36, 0xF31, - 0xF30, 0xF26, 0xF21, 0xF20, 0xF16, 0xF11, 0xF10, 0xF06, - 0xF01, 0xF00, 0xEF1, 0xEF0, 0xEE1, 0xEE0, 0xED0, 0xEC0, - 0xEB3, 0xEB1, 0xEB0, 0xEA3, 0xEA1, 0xEA0, 0xE90, 0xE81, - 0xE80, 0xE71, 0xE70, 0xE61, 0xE60, 0xE50, 0xE40, 0xE30, - 0xE10, 0xE00, 0x241, 0x240, 0x231, 0x1D0, 0x1C0, 0x1B3, - 0x1B0, 0x1A0, 0x190, 0x180, 0x170, 0x160, 0x150, 0x140, - 0x130, 0x120, 0x110, 0x100, 0x0F0, 0x0E0, 0x0D1, 0x0D0, - 0x0C1, 0x0C0, 0x0B1, 0x0B0, 0x0A5, 0x0A1, 0x0A0, 0x096, - 0x095, 0x091, 0x090, 0x086, 0x085, 0x081, 0x080, 0x075, - 0x071, 0x070, 0x065, 0x063, 0x061, 0x060, 0x055, 0x053, - 0x052, 0x051, 0x050, 0x045, 0x043, 0x042, 0x041, 0x040, - 0x036, 0x035, 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, - 0x024, 0x023, 0x022, 0x021, 0x020, 0x018, 0x016, 0x015, - 0x014, 0x013, 0x012, 0x011, 0x010, -}; - -static const uint16_t ac_vlc_desc2_codes[165] = { - 0x0034, 0x059C, 0x0280, 0x001C, 0x004C, 0x00BD, 0x0020, 0x003C, - 0x000A, 0x0003, 0x00FD, 0x008C, 0x0332, 0x01D5, 0x0055, 0x003E, - 0x0001, 0x07E4, 0x0264, 0x00B2, 0x00A2, 0x005C, 0x0005, 0x02A2, - 0x011D, 0x0132, 0x076C, 0x0012, 0x0018, 0x01E4, 0x05E4, 0x02B2, - 0x0432, 0x017D, 0x000E, 0x055D, 0x0955, 0x0164, 0x0028, 0x0D62, - 0x0B24, 0x02DE, 0x001E, 0x0340, 0x0014, 0x0555, 0x0180, 0x00DD, - 0x01B2, 0x0092, 0x036C, 0x00EC, 0x00E4, 0x00C0, 0x0C64, 0x095D, - 0x01DE, 0x0AE4, 0x0C32, 0x01A2, 0x06E4, 0x0832, 0x01A4, 0x015D, - 0x0732, 0x031D, 0x0F9C, 0x03E2, 0x09E2, 0x02FD, 0x0224, 0x051D, - 0x02E4, 0x019C, 0x05B2, 0x0355, 0x0064, 0x016C, 0x038C, 0x0880, - 0x0480, 0x06B2, 0x0540, 0x0080, 0x075D, 0x0155, 0x0424, 0x0680, - 0x0A62, 0x0A80, 0x078C, 0x0D9C, 0x0F8C, 0x0562, 0x0FF2, 0x0464, - 0x0B55, 0x01E2, 0x0032, 0x07F2, 0x0140, 0x03E4, 0x0662, 0x0755, - 0x0380, 0x026C, 0x0232, 0x001D, 0x0040, 0x00E2, 0x035D, 0x00F2, - 0x0162, 0x01FD, 0x03F2, 0x000C, 0x0EA2, 0x05F2, 0x0072, 0x04E4, - 0x0F32, 0x018C, 0x009D, 0x0324, 0x079C, 0x006C, 0x0054, 0x0F5D, - 0x021D, 0x0015, 0x0024, 0x06A2, 0x009C, 0x0004, 0x0062, 0x056C, - 0x0262, 0x0000, 0x002E, 0x01F2, 0x0124, 0x039C, 0x005E, 0x0010, - 0x0724, 0x00A4, 0x00DE, 0x0362, 0x0052, 0x000D, 0x03B2, 0x007D, - 0x05E2, 0x00D5, 0x005D, 0x0035, 0x0009, 0x099C, 0x0022, 0x002C, - 0x003D, 0x0008, 0x0002, 0x0006, 0x0007, -}; - -static const uint8_t ac_vlc_desc2_bits[165] = { - 6, 12, 12, 8, 7, 8, 6, 6, - 4, 3, 10, 9, 11, 9, 9, 6, - 4, 11, 10, 10, 10, 7, 5, 11, - 11, 10, 11, 8, 5, 11, 11, 11, - 12, 9, 6, 11, 12, 9, 6, 12, - 12, 10, 7, 10, 7, 11, 10, 8, - 11, 8, 11, 8, 11, 8, 12, 12, - 9, 12, 12, 9, 11, 12, 9, 12, - 12, 10, 12, 10, 12, 10, 10, 11, - 12, 12, 11, 12, 11, 11, 11, 12, - 11, 11, 11, 12, 12, 12, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 11, 11, 11, 11, - 10, 10, 10, 10, 9, 9, 11, 9, - 11, 9, 11, 8, 12, 11, 8, 11, - 12, 10, 8, 12, 12, 10, 7, 12, - 10, 7, 11, 12, 9, 6, 10, 11, - 12, 8, 6, 11, 10, 11, 8, 5, - 11, 9, 10, 10, 7, 5, 10, 9, - 11, 9, 9, 6, 4, 12, 8, 7, - 8, 6, 6, 4, 3, -}; - -static const uint16_t ac_vlc_desc3_syms[162] = { - 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, - 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, - 0xFE0, 0xFD6, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, - 0xFC6, 0xFC5, 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB5, 0xFB3, - 0xFB2, 0xFB1, 0xFB0, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF95, - 0xF93, 0xF91, 0xF90, 0xF85, 0xF83, 0xF81, 0xF80, 0xF71, - 0xF70, 0xF66, 0xF61, 0xF60, 0xF56, 0xF51, 0xF50, 0xF46, - 0xF41, 0xF40, 0xF36, 0xF31, 0xF30, 0xF26, 0xF21, 0xF20, - 0xF11, 0xF10, 0xF01, 0xF00, 0xEF3, 0xEF1, 0xEF0, 0xEE3, - 0xEE1, 0xEE0, 0xED3, 0xED1, 0xED0, 0xEC1, 0xEC0, 0xEB1, - 0xEB0, 0xEA0, 0xE90, 0xE80, 0xE70, 0x1E1, 0x1D1, 0x1D0, - 0x1C1, 0x1B1, 0x1A1, 0x180, 0x170, 0x163, 0x160, 0x150, - 0x140, 0x130, 0x123, 0x120, 0x113, 0x110, 0x100, 0x0F0, - 0x0E0, 0x0D1, 0x0D0, 0x0C1, 0x0C0, 0x0B1, 0x0B0, 0x0A1, - 0x0A0, 0x095, 0x091, 0x090, 0x085, 0x081, 0x080, 0x076, - 0x075, 0x073, 0x071, 0x070, 0x066, 0x065, 0x063, 0x061, - 0x060, 0x055, 0x053, 0x052, 0x051, 0x050, 0x045, 0x043, - 0x042, 0x041, 0x040, 0x036, 0x035, 0x034, 0x033, 0x032, - 0x031, 0x030, 0x026, 0x025, 0x024, 0x023, 0x022, 0x021, - 0x020, 0x018, 0x017, 0x016, 0x015, 0x014, 0x013, 0x012, - 0x011, 0x010, -}; - -static const uint16_t ac_vlc_desc3_codes[162] = { - 0x001D, 0x087C, 0x0AE8, 0x003A, 0x001C, 0x0008, 0x000C, 0x0032, - 0x0006, 0x0003, 0x03A5, 0x01EC, 0x01A5, 0x0080, 0x0030, 0x0005, - 0x0001, 0x0040, 0x03FC, 0x02D4, 0x0154, 0x02FC, 0x003C, 0x0015, - 0x051A, 0x0000, 0x02EC, 0x077C, 0x00D2, 0x0018, 0x03E8, 0x04EC, - 0x027C, 0x01FA, 0x0022, 0x0765, 0x0EA5, 0x0054, 0x0010, 0x08EC, - 0x0AAC, 0x03BA, 0x0042, 0x065D, 0x0AD4, 0x005C, 0x0028, 0x03C0, - 0x00E5, 0x035C, 0x04FA, 0x00DC, 0x06A5, 0x075C, 0x00C8, 0x05A5, - 0x04D4, 0x00BA, 0x01C0, 0x05E8, 0x012C, 0x00E8, 0x01B0, 0x00B0, - 0x025D, 0x002C, 0x0A52, 0x025C, 0x01E8, 0x00FA, 0x0348, 0x0652, - 0x0B7C, 0x0365, 0x031A, 0x0E52, 0x011A, 0x0200, 0x01BA, 0x02AC, - 0x06D4, 0x01FC, 0x05BA, 0x0DFC, 0x0248, 0x0EE8, 0x0B1A, 0x0CFC, - 0x0F65, 0x0B5C, 0x0DC0, 0x007C, 0x0548, 0x08A5, 0x00FC, 0x03B0, - 0x0148, 0x06AC, 0x0252, 0x071A, 0x02E8, 0x0240, 0x00AC, 0x021A, - 0x0140, 0x08E8, 0x01AC, 0x00EC, 0x0152, 0x00A5, 0x0068, 0x001A, - 0x006C, 0x05C0, 0x015C, 0x0025, 0x05B0, 0x017C, 0x0014, 0x047C, - 0x00D4, 0x06E8, 0x00C0, 0x0002, 0x0A5D, 0x04E8, 0x0A7C, 0x01D4, - 0x0020, 0x04A5, 0x07B0, 0x037C, 0x015D, 0x002A, 0x005D, 0x0048, - 0x067C, 0x007A, 0x0004, 0x04FC, 0x02FA, 0x0648, 0x0100, 0x0052, - 0x005A, 0x000D, 0x0165, 0x0065, 0x02A5, 0x0070, 0x00F0, 0x003D, - 0x0009, 0x05FC, 0x0E48, 0x009A, 0x0012, 0x00DD, 0x0034, 0x000A, - 0x000E, 0x0007, -}; - -static const uint8_t ac_vlc_desc3_bits[162] = { - 7, 12, 12, 8, 7, 7, 6, 6, - 4, 3, 10, 9, 11, 8, 8, 6, - 4, 10, 10, 12, 9, 10, 7, 5, - 11, 10, 10, 11, 8, 5, 10, 11, - 12, 9, 6, 12, 12, 9, 6, 12, - 12, 10, 7, 11, 12, 10, 7, 10, - 8, 12, 11, 8, 12, 11, 8, 11, - 11, 9, 11, 11, 9, 12, 11, 9, - 12, 9, 12, 10, 11, 11, 10, 12, - 12, 11, 12, 12, 11, 10, 11, 12, - 11, 11, 11, 12, 11, 12, 12, 12, - 12, 12, 12, 12, 11, 12, 11, 11, - 11, 11, 12, 11, 12, 10, 10, 10, - 9, 12, 9, 12, 9, 12, 8, 10, - 8, 12, 10, 8, 11, 10, 7, 11, - 11, 12, 9, 7, 12, 11, 12, 9, - 6, 11, 11, 12, 9, 6, 10, 10, - 11, 8, 5, 12, 10, 12, 9, 10, - 7, 5, 10, 9, 11, 8, 8, 6, - 4, 12, 12, 8, 7, 8, 6, 6, + 0x0FF, 0x001, 0x0FC, 0x0F1, 0x0EA, 0x017, 0x00E, 0x016, 0x0EB, 0x009, + 0x0F6, 0x004, 0x006, 0x0F2, 0x015, 0x014, 0x00D, 0x0EC, 0x0ED, 0x100, + 0x0FA, 0x0F7, 0x008, 0x00C, 0x013, 0x0EE, 0x0F3, 0x0F4, 0x005, 0x0FE, + 0x002, 0x0FB, 0x0F8, 0x012, 0x011, 0x00B, 0x0FD, 0x003, 0x007, 0x0EF, + 0x0F0, 0x0F5, 0x0F9, 0x00F, 0x010, 0x00A, 0x000, +}; + +static const uint8_t tscc2_dc_vlc_lens[DC_VLC_COUNT] = { + 3, 3, 6, 9, 10, 10, 9, 10, 10, 8, 8, 6, 7, 9, 10, 10, 9, 10, + 10, 5, 7, 8, 8, 9, 10, 10, 9, 9, 7, 5, 5, 7, 8, 10, 10, 9, + 6, 6, 8, 10, 10, 9, 8, 10, 10, 9, 1, +}; + +static const uint8_t tscc2_nc_vlc_syms[NUM_VLC_SETS][16] = { + { 0x00, 0x08, 0x0C, 0x0B, 0x0D, 0x07, 0x06, 0x04, + 0x02, 0x0E, 0x0F, 0x09, 0x0A, 0x05, 0x03, 0x01 }, + { 0x0A, 0x0C, 0x07, 0x0F, 0x0B, 0x0D, 0x04, 0x02, + 0x06, 0x0E, 0x05, 0x09, 0x08, 0x03, 0x01, 0x00 }, + { 0x08, 0x0D, 0x04, 0x0C, 0x07, 0x0A, 0x0E, 0x02, + 0x0B, 0x06, 0x05, 0x0F, 0x09, 0x03, 0x01, 0x00 }, + { 0x04, 0x0E, 0x0C, 0x09, 0x08, 0x07, 0x0A, 0x02, + 0x06, 0x0B, 0x05, 0x0F, 0x0D, 0x03, 0x01, 0x00 }, + { 0x0D, 0x0C, 0x04, 0x09, 0x08, 0x0B, 0x07, 0x02, + 0x06, 0x0A, 0x0F, 0x0E, 0x05, 0x03, 0x01, 0x00 }, + { 0x01, 0x0A, 0x06, 0x07, 0x05, 0x03, 0x0D, 0x0C, + 0x04, 0x0F, 0x0E, 0x0B, 0x09, 0x08, 0x02, 0x00 }, + { 0x01, 0x08, 0x06, 0x07, 0x0D, 0x0C, 0x05, 0x04, + 0x0F, 0x0E, 0x0B, 0x09, 0x0A, 0x03, 0x02, 0x00 }, + { 0x01, 0x0D, 0x0C, 0x08, 0x06, 0x07, 0x05, 0x0F, + 0x0E, 0x0B, 0x04, 0x0A, 0x09, 0x03, 0x02, 0x00 }, + { 0x01, 0x0D, 0x0F, 0x0E, 0x08, 0x07, 0x06, 0x0C, + 0x0B, 0x05, 0x04, 0x0A, 0x09, 0x03, 0x02, 0x00 }, + { 0x03, 0x02, 0x09, 0x08, 0x0C, 0x0B, 0x07, 0x06, + 0x05, 0x04, 0x0D, 0x0F, 0x0E, 0x0A, 0x01, 0x00 }, + { 0x03, 0x02, 0x09, 0x0C, 0x0B, 0x08, 0x07, 0x06, + 0x0D, 0x0F, 0x0E, 0x0A, 0x05, 0x04, 0x01, 0x00 }, + { 0x03, 0x02, 0x09, 0x0C, 0x0B, 0x08, 0x07, 0x06, + 0x0D, 0x0F, 0x0E, 0x0A, 0x04, 0x05, 0x01, 0x00 }, + { 0x03, 0x02, 0x09, 0x0C, 0x0B, 0x08, 0x07, 0x0D, + 0x0F, 0x0E, 0x0A, 0x06, 0x05, 0x04, 0x01, 0x00 }, +}; + +static const uint8_t tscc2_nc_vlc_lens[NUM_VLC_SETS][16] = { + { 1, 6, 6, 6, 6, 6, 6, 5, 3, 6, 6, 7, 7, 6, 4, 3 }, + { 6, 6, 6, 6, 6, 6, 5, 3, 6, 6, 6, 7, 7, 4, 3, 1 }, + { 6, 6, 5, 6, 6, 6, 6, 3, 6, 6, 6, 7, 7, 4, 3, 1 }, + { 5, 6, 6, 6, 6, 6, 6, 3, 6, 6, 6, 7, 7, 4, 3, 1 }, + { 6, 6, 5, 6, 6, 6, 6, 3, 6, 6, 7, 7, 6, 4, 3, 1 }, + { 2, 6, 6, 6, 6, 4, 7, 7, 6, 8, 8, 7, 7, 7, 4, 1 }, + { 2, 6, 6, 6, 7, 7, 6, 6, 8, 8, 7, 7, 7, 4, 4, 1 }, + { 2, 7, 7, 6, 6, 6, 6, 8, 8, 7, 6, 7, 7, 4, 4, 1 }, + { 2, 7, 8, 8, 6, 6, 6, 7, 7, 6, 6, 7, 7, 4, 4, 1 }, + { 3, 3, 6, 6, 7, 7, 6, 6, 6, 6, 8, 9, 9, 7, 3, 1 }, + { 3, 3, 6, 7, 7, 6, 6, 6, 8, 9, 9, 7, 6, 6, 3, 1 }, + { 3, 3, 6, 7, 7, 6, 6, 6, 8, 9, 9, 7, 6, 6, 3, 1 }, + { 3, 3, 6, 7, 7, 6, 6, 8, 9, 9, 7, 6, 6, 6, 3, 1 }, +}; + +static const uint16_t tscc2_ac_vlc_syms[] = { + /* Descriptor 0 - 172 entries */ + 0x0FC0, 0x0040, 0x0FF1, 0x0011, 0x0FA0, 0x0FE5, 0x0140, 0x0280, 0x0D60, + 0x0210, 0x0FC6, 0x0FD6, 0x0200, 0x0F95, 0x0101, 0x0190, 0x0FF5, 0x0FF2, + 0x0060, 0x0FE1, 0x0021, 0x0F41, 0x0270, 0x0D80, 0x0055, 0x0FB2, 0x00F1, + 0x0120, 0x0F30, 0x0015, 0x0090, 0x0FE3, 0x0FA1, 0x0E00, 0x01F0, 0x0F81, + 0x0EE0, 0x0FD1, 0x0F70, 0x0FA3, 0x0121, 0x0FC5, 0x0E70, 0x0023, 0x0180, + 0x00C1, 0x0F51, 0x0FE2, 0x0031, 0x0012, 0x0061, 0x00A5, 0x0ED1, 0x0D90, + 0x0091, 0x0E10, 0x0FE4, 0x0043, 0x0024, 0x0E80, 0x01E0, 0x0DA0, 0x0FA5, + 0x00D0, 0x0022, 0x0110, 0x0FE0, 0x0020, 0x0EF0, 0x0F45, 0x0260, 0x0045, + 0x0081, 0x0F40, 0x0F80, 0x0080, 0x00C0, 0x0E20, 0x0250, 0x0052, 0x0063, + 0x0018, 0x0FC3, 0x0170, 0x0111, 0x0F73, 0x0240, 0x0DC0, 0x0FB0, 0x0F00, + 0x0100, 0x0FC1, 0x0160, 0x0DB0, 0x00B1, 0x0026, 0x0F31, 0x0FF8, 0x0EA0, + 0x0150, 0x0065, 0x0FE6, 0x0E90, 0x0E30, 0x01C0, 0x0FD0, 0x0030, 0x0FF0, + 0x0010, 0x0050, 0x00B0, 0x0FF4, 0x0FF3, 0x0046, 0x0053, 0x0230, 0x0FB3, + 0x0EB0, 0x0035, 0x0FB5, 0x00E1, 0x0CD1, 0x0ED5, 0x0F50, 0x0041, 0x0F10, + 0x01B0, 0x01D0, 0x0F91, 0x0F90, 0x0070, 0x00F0, 0x0FB1, 0x0E40, 0x0DD0, + 0x0075, 0x0E50, 0x0FC2, 0x0F83, 0x0FD2, 0x00A1, 0x0EC0, 0x0013, 0x0014, + 0x0F61, 0x01A1, 0x0220, 0x0FD5, 0x0DE0, 0x0F21, 0x0016, 0x0F60, 0x0032, + 0x01A0, 0x0036, 0x00D1, 0x0FD3, 0x0025, 0x0130, 0x1000, 0x0051, 0x0FF6, + 0x0ED0, 0x0E60, 0x0042, 0x0DF0, 0x0F20, 0x00E0, 0x0033, 0x0F71, 0x0071, + 0x00A0, + /* Descriptor 1 - 169 entries */ + 0x00D0, 0x0E50, 0x00D1, 0x0091, 0x0160, 0x0F31, 0x0EE1, 0x0250, 0x0F70, + 0x0051, 0x0F41, 0x0063, 0x0150, 0x0EF0, 0x01A0, 0x0F51, 0x0FD5, 0x0F93, + 0x0DC0, 0x0240, 0x0095, 0x0FD2, 0x00C0, 0x0FC0, 0x0040, 0x0090, 0x0016, + 0x0F40, 0x0FA0, 0x0026, 0x0EB0, 0x0EF1, 0x0DF0, 0x0053, 0x0F01, 0x01F0, + 0x0FC2, 0x0FF6, 0x0FF5, 0x0060, 0x0015, 0x0F85, 0x0DE1, 0x0032, 0x0100, + 0x0046, 0x0DB0, 0x0FB5, 0x0F81, 0x0FA1, 0x0012, 0x0011, 0x0FF1, 0x0FF2, + 0x0F00, 0x0E00, 0x0F21, 0x0F45, 0x0FD3, 0x0E60, 0x00C1, 0x0E80, 0x0035, + 0x0045, 0x0140, 0x0042, 0x0FB2, 0x0EB6, 0x0033, 0x0FC5, 0x0190, 0x0FE6, + 0x0024, 0x0F61, 0x0085, 0x0E33, 0x0E70, 0x0EC0, 0x00B0, 0x0F50, 0x0F80, + 0x0080, 0x0023, 0x0FE4, 0x01E0, 0x0F11, 0x0081, 0x0FC1, 0x0FD1, 0x0052, + 0x0FA5, 0x0F95, 0x0EC6, 0x00B1, 0x0111, 0x0061, 0x00F0, 0x0FE3, 0x0FE1, + 0x0021, 0x0041, 0x0FE2, 0x0055, 0x0FC6, 0x0E10, 0x0180, 0x0E20, 0x0DE0, + 0x0022, 0x0025, 0x0FB3, 0x0FA3, 0x0036, 0x0FC3, 0x00E0, 0x0FE0, 0x0020, + 0x0050, 0x0FB0, 0x1000, 0x0031, 0x01D0, 0x0018, 0x00A1, 0x0FB6, 0x00C6, + 0x0043, 0x0F10, 0x0F20, 0x0101, 0x0E30, 0x0FA6, 0x00F1, 0x0ED0, 0x0FD0, + 0x00A0, 0x0FD6, 0x0DA0, 0x0E31, 0x0120, 0x0130, 0x0170, 0x01C0, 0x00E1, + 0x0F60, 0x0014, 0x0070, 0x0F90, 0x0030, 0x0FB1, 0x0075, 0x0E90, 0x0F91, + 0x0FF4, 0x0013, 0x0FF3, 0x0EE0, 0x0FF8, 0x0065, 0x0E40, 0x01B0, 0x0F30, + 0x0071, 0x0FE5, 0x0EA0, 0x0F71, 0x0110, 0x0FF0, 0x0010, + /* Descriptor 2 - 165 entries */ + 0x0051, 0x0E61, 0x0E81, 0x0E80, 0x0FF7, 0x0E00, 0x0E30, 0x0F71, 0x0130, + 0x00F0, 0x0170, 0x0E70, 0x0F81, 0x0F40, 0x0FF3, 0x0040, 0x0013, 0x0FA0, + 0x0FC0, 0x0060, 0x0065, 0x0E40, 0x0ED0, 0x0043, 0x0086, 0x0F93, 0x0036, + 0x0035, 0x0F10, 0x0EA1, 0x01B3, 0x0F36, 0x0FD5, 0x0FA1, 0x0F41, 0x0096, + 0x0EB3, 0x0F26, 0x0F16, 0x0FB6, 0x0FB5, 0x0160, 0x0FD6, 0x0F80, 0x0080, + 0x1000, 0x00B0, 0x0FE5, 0x0091, 0x0E90, 0x0241, 0x0231, 0x0FF5, 0x0015, + 0x0081, 0x0120, 0x0EA0, 0x0053, 0x0F51, 0x0FC2, 0x0F50, 0x0FF6, 0x0061, + 0x0EB1, 0x0018, 0x0FF8, 0x0240, 0x0042, 0x0085, 0x0EF1, 0x0FD1, 0x0FF2, + 0x0012, 0x0016, 0x0FD2, 0x0FC6, 0x0063, 0x00A5, 0x0F20, 0x0055, 0x0052, + 0x0E10, 0x0150, 0x00C1, 0x01D0, 0x0F95, 0x0032, 0x00E0, 0x01A0, 0x0EE1, + 0x0024, 0x0EF0, 0x0FC1, 0x0F60, 0x0031, 0x0190, 0x0F11, 0x0FB2, 0x0F21, + 0x0110, 0x0FC3, 0x0FE4, 0x0F01, 0x0095, 0x0FD3, 0x0FB3, 0x0E71, 0x0F61, + 0x0EB0, 0x0026, 0x00A0, 0x00D0, 0x0045, 0x00A1, 0x00B1, 0x0180, 0x01C0, + 0x0FF1, 0x0011, 0x0FB0, 0x0050, 0x0F90, 0x0041, 0x0033, 0x0F91, 0x0F30, + 0x0FE1, 0x0FE0, 0x0020, 0x0FD0, 0x0070, 0x0FE2, 0x0E50, 0x0FA3, 0x0F75, + 0x0EA3, 0x01B0, 0x0140, 0x0023, 0x0FE3, 0x0021, 0x0030, 0x0100, 0x0071, + 0x0FC5, 0x0EC0, 0x0F00, 0x0090, 0x0022, 0x0F06, 0x0F31, 0x0FA5, 0x00D1, + 0x0E60, 0x0075, 0x0F70, 0x0014, 0x0FF4, 0x0025, 0x0FB1, 0x0FE6, 0x0EE0, + 0x00C0, 0x0FF0, 0x0010, + /* Descriptor 3 - 162 entries */ + 0x0FC5, 0x0EC1, 0x0033, 0x0FE3, 0x0FD6, 0x0110, 0x00E0, 0x0071, 0x0F36, + 0x0095, 0x01A1, 0x0F71, 0x0060, 0x0FA0, 0x0FE2, 0x0F20, 0x0F21, 0x0085, + 0x0150, 0x0053, 0x0023, 0x0022, 0x0FF4, 0x0043, 0x0E70, 0x0034, 0x0017, + 0x0140, 0x0170, 0x0EF0, 0x0F50, 0x0F80, 0x00B0, 0x0F26, 0x00D1, 0x0065, + 0x0113, 0x0FF7, 0x0073, 0x01E1, 0x0EF3, 0x0F31, 0x0FB5, 0x0FC0, 0x0040, + 0x0080, 0x0FA1, 0x0FD3, 0x0075, 0x0F41, 0x0FD4, 0x0F83, 0x0EB0, 0x0061, + 0x0013, 0x0FF3, 0x0F10, 0x0F30, 0x0100, 0x0EB1, 0x0F93, 0x0130, 0x00D0, + 0x00A0, 0x00C1, 0x0F95, 0x0FB3, 0x0FC3, 0x0FE5, 0x0FF5, 0x0F81, 0x0F00, + 0x0091, 0x0F66, 0x01B1, 0x0F51, 0x0F60, 0x0FD1, 0x0180, 0x0FF8, 0x0076, + 0x0FB2, 0x0063, 0x0042, 0x0081, 0x0052, 0x0EE1, 0x0FC2, 0x0160, 0x0036, + 0x01D0, 0x0FD2, 0x0EA0, 0x0018, 0x0E80, 0x0FD5, 0x0070, 0x0F90, 0x0FB0, + 0x0015, 0x0032, 0x0123, 0x0F01, 0x0EE3, 0x0ED1, 0x00C0, 0x0FC1, 0x0FF2, + 0x0012, 0x0050, 0x00A1, 0x00F0, 0x0ED0, 0x0FC6, 0x0ED3, 0x01D1, 0x0120, + 0x0016, 0x0031, 0x0FF6, 0x0F40, 0x0EC0, 0x0E90, 0x0F91, 0x0041, 0x0EF1, + 0x0F61, 0x0035, 0x0FB1, 0x0FF1, 0x0011, 0x0FE0, 0x0020, 0x0FE1, 0x0090, + 0x00B1, 0x0163, 0x0055, 0x0024, 0x0F56, 0x0FA3, 0x0FE4, 0x0F46, 0x0FE6, + 0x0025, 0x0026, 0x0EE0, 0x0FA5, 0x01C1, 0x0F70, 0x0FD0, 0x0030, 0x1000, + 0x0045, 0x0F11, 0x0066, 0x0F85, 0x0051, 0x0014, 0x0021, 0x0FF0, 0x0010, + /* Descriptor 4 - 131 entries */ + 0x0010, 0x0FB0, 0x0050, 0x0070, 0x0FF5, 0x0FC1, 0x0090, 0x0FD1, 0x00E0, + 0x0161, 0x0085, 0x0F41, 0x0F20, 0x0FD6, 0x0F70, 0x0FD3, 0x0032, 0x0FD2, + 0x0055, 0x0191, 0x0063, 0x0091, 0x0081, 0x0F91, 0x0015, 0x0031, 0x0065, + 0x0036, 0x00B1, 0x0130, 0x0018, 0x0F93, 0x0F50, 0x0041, 0x0FD5, 0x0100, + 0x0F51, 0x00B0, 0x0FE6, 0x0FC5, 0x0F40, 0x0FF2, 0x0FE0, 0x0012, 0x0FE1, + 0x0043, 0x0F61, 0x0FA3, 0x0140, 0x0120, 0x0FB1, 0x0051, 0x0EE0, 0x0F21, + 0x0066, 0x0F03, 0x0F01, 0x0060, 0x0016, 0x0FF6, 0x0FA0, 0x0020, 0x0FF1, + 0x0FD0, 0x0030, 0x0011, 0x0021, 0x0071, 0x00D0, 0x0FE4, 0x0024, 0x0F30, + 0x0080, 0x0123, 0x00A1, 0x0F71, 0x0F00, 0x0180, 0x0EC0, 0x00F3, 0x0F31, + 0x0EF0, 0x0033, 0x0014, 0x0FC0, 0x0F80, 0x0FE3, 0x0FE2, 0x0025, 0x0FC3, + 0x00F0, 0x0053, 0x0075, 0x0F66, 0x0FF4, 0x0040, 0x0F60, 0x0022, 0x00A0, + 0x0ED0, 0x0F13, 0x0181, 0x0F76, 0x0F23, 0x0045, 0x1000, 0x0023, 0x00C0, + 0x0F56, 0x0171, 0x0F10, 0x0FA1, 0x0EB0, 0x0056, 0x0026, 0x0035, 0x0FB5, + 0x0FB3, 0x0EF1, 0x0FF3, 0x0013, 0x0F90, 0x0FA5, 0x0FC2, 0x0F11, 0x0F81, + 0x0110, 0x0042, 0x0061, 0x0FE5, 0x0FF0, + /* Descriptor 5 - 132 entries */ + 0x0010, 0x0F81, 0x0FC5, 0x0F20, 0x0F76, 0x0061, 0x0F41, 0x00D3, 0x0FB3, + 0x0023, 0x0F31, 0x0EC0, 0x00B1, 0x0045, 0x0F50, 0x0FF5, 0x0042, 0x00C1, + 0x0EC1, 0x00D0, 0x0F33, 0x0F93, 0x0FF8, 0x0EF0, 0x0140, 0x0035, 0x0071, + 0x0FD1, 0x0FE3, 0x0FC1, 0x0FF3, 0x0013, 0x0052, 0x0F85, 0x0F51, 0x0046, + 0x0065, 0x0F21, 0x0F30, 0x0041, 0x0031, 0x0034, 0x0FD4, 0x0F43, 0x0032, + 0x0FB5, 0x0FD2, 0x0FE5, 0x0EE0, 0x0120, 0x0F23, 0x0F00, 0x0015, 0x0FE1, + 0x0FE0, 0x0020, 0x1000, 0x0081, 0x0018, 0x0075, 0x0043, 0x00C3, 0x0121, + 0x00A0, 0x0080, 0x0FA0, 0x0060, 0x0FD0, 0x0030, 0x0FF2, 0x0012, 0x0FF1, + 0x0F80, 0x0F91, 0x0141, 0x00A1, 0x0F96, 0x0FB1, 0x00C0, 0x0111, 0x0F66, + 0x00F0, 0x0F40, 0x0FE6, 0x0016, 0x0021, 0x0FC0, 0x0051, 0x00E0, 0x0F86, + 0x0033, 0x0FF6, 0x0F75, 0x0F11, 0x0055, 0x0F61, 0x0FA3, 0x0131, 0x0FD5, + 0x0FA1, 0x0FC3, 0x0024, 0x0056, 0x0FD6, 0x0F60, 0x0011, 0x0040, 0x0025, + 0x0FE4, 0x0103, 0x0091, 0x0026, 0x0F10, 0x0014, 0x0FE2, 0x0022, 0x0070, + 0x0090, 0x0100, 0x0FC2, 0x0151, 0x0FD3, 0x0FF4, 0x0050, 0x0F70, 0x0053, + 0x0110, 0x0F71, 0x00B0, 0x0F90, 0x0FB0, 0x0FF0, + /* Descriptor 6 - 130 entries */ + 0x0010, 0x0FF4, 0x0F96, 0x0F71, 0x00D1, 0x0FF7, 0x00E3, 0x0045, 0x0FC1, + 0x1000, 0x00C0, 0x0042, 0x0120, 0x00A0, 0x0F80, 0x0FD1, 0x0F43, 0x0F63, + 0x0EF0, 0x0F86, 0x0F60, 0x0023, 0x0080, 0x00F0, 0x0FB3, 0x00E0, 0x0063, + 0x0110, 0x0F41, 0x0F93, 0x0FF8, 0x0081, 0x0FF5, 0x0041, 0x0FD2, 0x0F30, + 0x0F81, 0x00B1, 0x00E1, 0x0F00, 0x0031, 0x0060, 0x0035, 0x0F51, 0x0FB5, + 0x0FE3, 0x0FF3, 0x0013, 0x0FE0, 0x0032, 0x0075, 0x0FD4, 0x0046, 0x0F40, + 0x0F91, 0x0FE5, 0x00B3, 0x00C3, 0x0EE1, 0x0F31, 0x0FA0, 0x0FE1, 0x0FD0, + 0x0020, 0x0030, 0x0F10, 0x00A1, 0x0FA3, 0x0033, 0x0111, 0x0FA6, 0x0100, + 0x0F61, 0x0026, 0x0FB1, 0x0061, 0x0025, 0x0F95, 0x0FD6, 0x0036, 0x0034, + 0x0F20, 0x00B0, 0x0121, 0x0018, 0x0131, 0x0051, 0x0FF2, 0x0040, 0x0021, + 0x0FC0, 0x0015, 0x0090, 0x0043, 0x0FC5, 0x0056, 0x0055, 0x0016, 0x0FF1, + 0x0011, 0x0012, 0x0FF6, 0x0F50, 0x0FC2, 0x0053, 0x0F76, 0x0F85, 0x0FD3, + 0x0091, 0x0101, 0x0071, 0x0070, 0x0F90, 0x0FB0, 0x0FC3, 0x0065, 0x00F1, + 0x0F53, 0x00D0, 0x0FE2, 0x0FA1, 0x0024, 0x0FE4, 0x0022, 0x0050, 0x0FE6, + 0x0FD5, 0x0F70, 0x0014, 0x0FF0, + /* Descriptor 7 - 125 entries */ + 0x0010, 0x0022, 0x0FD5, 0x0F71, 0x0F63, 0x0052, 0x0F31, 0x0042, 0x0024, + 0x0FE4, 0x0F86, 0x0F93, 0x00C1, 0x0025, 0x0FD1, 0x0FE6, 0x0F95, 0x00D1, + 0x0FA6, 0x0FD2, 0x00E1, 0x0017, 0x0FF7, 0x0081, 0x0FB3, 0x0046, 0x0014, + 0x0FF4, 0x0FC1, 0x0023, 0x0031, 0x0060, 0x0FA0, 0x0061, 0x00B0, 0x00C3, + 0x0F00, 0x0121, 0x0F80, 0x0FF5, 0x0041, 0x0FF8, 0x0100, 0x0032, 0x0090, + 0x0F81, 0x0F30, 0x0045, 0x0F61, 0x00C0, 0x0063, 0x0FD4, 0x0055, 0x0F70, + 0x0FF3, 0x0FD0, 0x0030, 0x0FE0, 0x0020, 0x0013, 0x0FE1, 0x0FE3, 0x0FB1, + 0x0093, 0x00B1, 0x0026, 0x0F10, 0x00F0, 0x0FA5, 0x0FB5, 0x0070, 0x0F90, + 0x0FC0, 0x0040, 0x0033, 0x0F40, 0x0FE5, 0x00A1, 0x0034, 0x0036, 0x0F96, + 0x0F91, 0x0043, 0x0F01, 0x0053, 0x0FC5, 0x0035, 0x0F51, 0x00A3, 0x0FC2, + 0x0FA3, 0x0F50, 0x00F1, 0x0071, 0x0051, 0x0021, 0x0FF2, 0x0FF1, 0x0012, + 0x0015, 0x0016, 0x00A0, 0x0FD3, 0x0065, 0x0111, 0x0FC3, 0x0091, 0x0018, + 0x0F20, 0x0050, 0x1000, 0x0FF6, 0x0FB0, 0x0FA1, 0x0101, 0x0F53, 0x00E0, + 0x0080, 0x0F60, 0x00D0, 0x0F41, 0x0F73, 0x0FE2, 0x0011, 0x0FF0, + /* Descriptor 8 - 121 entries */ + 0x0010, 0x0F60, 0x0093, 0x00A3, 0x0F95, 0x0018, 0x0FE2, 0x0FA6, 0x0FA1, + 0x0022, 0x0090, 0x0042, 0x0F86, 0x0F93, 0x0036, 0x0FE6, 0x0F50, 0x0FD1, + 0x0060, 0x0FA0, 0x0025, 0x0FD2, 0x0046, 0x0F70, 0x0031, 0x0045, 0x0F40, + 0x0F81, 0x0FB3, 0x0111, 0x0073, 0x0023, 0x0FC1, 0x0FE4, 0x0024, 0x0081, + 0x0FA5, 0x0032, 0x0014, 0x0FF4, 0x0FD0, 0x0030, 0x0041, 0x0070, 0x0FF5, + 0x00E1, 0x0061, 0x0F73, 0x0063, 0x0F41, 0x00B3, 0x0FD5, 0x00F1, 0x0017, + 0x0FF7, 0x00A0, 0x0055, 0x00C1, 0x0F30, 0x0043, 0x0FD4, 0x0065, 0x0FF8, + 0x0FB1, 0x1000, 0x0020, 0x0FE0, 0x0040, 0x0FC0, 0x0FE1, 0x0FF3, 0x0013, + 0x0FE3, 0x0FA3, 0x0083, 0x0F96, 0x00D1, 0x0026, 0x0033, 0x0101, 0x00B1, + 0x0FB6, 0x0F90, 0x0080, 0x00E0, 0x0071, 0x0034, 0x0FC2, 0x0F20, 0x00A1, + 0x0021, 0x0050, 0x00B0, 0x0F71, 0x0FC5, 0x0F91, 0x0F80, 0x0035, 0x0F63, + 0x0053, 0x00C0, 0x0FF1, 0x0FF2, 0x0FB0, 0x0016, 0x0FB5, 0x0F51, 0x0091, + 0x0F21, 0x0FD3, 0x0FC3, 0x00D0, 0x0F83, 0x0F61, 0x0012, 0x0015, 0x0051, + 0x0FE5, 0x0FF6, 0x0011, 0x0FF0, + /* Descriptor 9 - 114 entries */ + 0x0010, 0x0015, 0x0042, 0x0091, 0x0FD2, 0x0036, 0x0FE2, 0x0022, 0x00C0, + 0x0121, 0x0065, 0x0F31, 0x0018, 0x0F60, 0x0FF6, 0x0070, 0x00B0, 0x0045, + 0x0F71, 0x0FD1, 0x0FC1, 0x0FA1, 0x0055, 0x0FB5, 0x0FB2, 0x0F93, 0x0FC5, + 0x0023, 0x0F70, 0x0083, 0x0061, 0x0031, 0x0025, 0x0FA5, 0x0FB3, 0x0032, + 0x0FD5, 0x0081, 0x0F61, 0x0FE4, 0x0F21, 0x0073, 0x0F73, 0x0024, 0x0041, + 0x0030, 0x0FD0, 0x0014, 0x0FF4, 0x0040, 0x0FE0, 0x0FC0, 0x0080, 0x0043, + 0x00E1, 0x00D1, 0x0FE3, 0x1000, 0x0F90, 0x0FE1, 0x0FB1, 0x0026, 0x0FD4, + 0x0063, 0x0034, 0x0FA3, 0x00A3, 0x0F80, 0x0F40, 0x0017, 0x0FF7, 0x0F83, + 0x0FF5, 0x0020, 0x0050, 0x0FB0, 0x0021, 0x0013, 0x0FF3, 0x0FF1, 0x0F51, + 0x0093, 0x0FF8, 0x0F91, 0x0F50, 0x0071, 0x00B1, 0x0051, 0x0033, 0x0090, + 0x00D0, 0x00F1, 0x0FC2, 0x0FE6, 0x0FA6, 0x0FB6, 0x0FA0, 0x0FF2, 0x0060, + 0x0FD3, 0x0F30, 0x00A1, 0x0F96, 0x0053, 0x0035, 0x00A0, 0x0016, 0x00C1, + 0x0FC3, 0x0F81, 0x0FE5, 0x0012, 0x0011, 0x0FF0, + /* Descriptor A - 110 entries */ + 0x0010, 0x0F60, 0x0051, 0x0F90, 0x0FE2, 0x0044, 0x0FA5, 0x0053, 0x00A1, + 0x0035, 0x0022, 0x0026, 0x0073, 0x0080, 0x0FD1, 0x0015, 0x0FE5, 0x0090, + 0x0091, 0x0055, 0x0F73, 0x0F51, 0x00D1, 0x0023, 0x0FA1, 0x0061, 0x0FB3, + 0x0FC5, 0x0031, 0x0FF6, 0x1000, 0x0FD5, 0x0F91, 0x0FC1, 0x0032, 0x0F41, + 0x00B0, 0x00B1, 0x0081, 0x0FB2, 0x0F96, 0x0FD0, 0x0030, 0x0040, 0x0025, + 0x0F81, 0x0F70, 0x0FE3, 0x0FB6, 0x00A0, 0x0018, 0x0FA3, 0x0F31, 0x0FE0, + 0x0FC0, 0x0FB0, 0x0050, 0x0FE1, 0x0014, 0x0F80, 0x0FE6, 0x0FE4, 0x0043, + 0x0083, 0x0024, 0x0FB1, 0x0020, 0x0FF4, 0x0041, 0x0F50, 0x0FF8, 0x0F93, + 0x00C1, 0x0033, 0x0021, 0x0FF5, 0x0060, 0x0063, 0x0034, 0x0FD4, 0x0FC2, + 0x0071, 0x0FC6, 0x0093, 0x0045, 0x0FA6, 0x00C0, 0x0013, 0x0FF1, 0x0FF3, + 0x0F71, 0x00E1, 0x0F40, 0x0FC3, 0x0FB5, 0x0070, 0x0042, 0x0F61, 0x0F83, + 0x0FF7, 0x0017, 0x0FD2, 0x0036, 0x0FD3, 0x0016, 0x0FA0, 0x0FF2, 0x0012, + 0x0011, 0x0FF0, + /* Descriptor B - 101 entries */ + 0x0010, 0x0012, 0x0023, 0x0091, 0x0061, 0x0FA1, 0x0FD1, 0x0015, 0x0030, + 0x0FD0, 0x0FB3, 0x0F71, 0x0F60, 0x0FA6, 0x0063, 0x0032, 0x0FC1, 0x0031, + 0x0040, 0x0080, 0x0FD5, 0x0FE3, 0x0050, 0x0FC0, 0x0FB0, 0x0FF6, 0x0F81, + 0x0FB6, 0x0F70, 0x0F91, 0x0025, 0x1000, 0x0FE1, 0x00A1, 0x0FA3, 0x00F1, + 0x0F61, 0x0F51, 0x0081, 0x00C1, 0x0018, 0x0060, 0x0041, 0x0073, 0x0FE4, + 0x0F80, 0x0FE0, 0x0020, 0x0021, 0x0FC5, 0x0055, 0x0042, 0x0026, 0x0070, + 0x0024, 0x0043, 0x00A0, 0x0033, 0x0FF8, 0x0071, 0x0014, 0x0FF4, 0x0FB1, + 0x0FB5, 0x0034, 0x0F41, 0x0036, 0x0F90, 0x0FC6, 0x0090, 0x0FF5, 0x0FA0, + 0x0FD4, 0x0F83, 0x0083, 0x0051, 0x00B1, 0x0FD3, 0x0FF1, 0x0013, 0x0FF3, + 0x0FF2, 0x0035, 0x0045, 0x0FC2, 0x00D1, 0x0FE2, 0x0016, 0x0FC3, 0x0FD2, + 0x00B0, 0x0FE6, 0x0F93, 0x0F50, 0x0FF7, 0x0017, 0x0053, 0x0022, 0x0FE5, + 0x0011, 0x0FF0, + /* Descriptor C - 96 entries */ + 0x0010, 0x0012, 0x0FC3, 0x00B1, 0x00A1, 0x0022, 0x0FE5, 0x0F93, 0x0090, + 0x0061, 0x0055, 0x0042, 0x0FE6, 0x0040, 0x0030, 0x0FD1, 0x0050, 0x0015, + 0x0FD0, 0x0FC0, 0x0023, 0x0FC1, 0x0017, 0x00C1, 0x0032, 0x0FB5, 0x0FF7, + 0x00A0, 0x0060, 0x0031, 0x0041, 0x0FE3, 0x0FD5, 0x0091, 0x0053, 0x0FF8, + 0x0FA0, 0x0FF6, 0x0FB0, 0x0070, 0x0080, 0x1000, 0x0FE1, 0x0FE0, 0x0020, + 0x0021, 0x0063, 0x0033, 0x0FA1, 0x0F60, 0x0F61, 0x0043, 0x0073, 0x0FC6, + 0x0FE4, 0x00E1, 0x0034, 0x0018, 0x0F91, 0x0F80, 0x0024, 0x0026, 0x0014, + 0x0FF4, 0x0FB1, 0x0FB6, 0x0071, 0x0FA6, 0x0FD4, 0x0035, 0x0F70, 0x0036, + 0x0051, 0x0FF5, 0x0FF1, 0x0FD3, 0x0045, 0x0F81, 0x0F90, 0x0083, 0x0081, + 0x0FA3, 0x0FE2, 0x0FC5, 0x0F51, 0x0F71, 0x0FD2, 0x0FB3, 0x0FC2, 0x0025, + 0x0016, 0x0013, 0x0FF3, 0x0FF2, 0x0011, 0x0FF0, +}; + +static const uint8_t tscc2_ac_vlc_lens[] = { + /* Descriptor 0 - 172 entries */ + 5, 5, 4, 4, 6, 9, 9, 12, 12, 11, 11, 11, 11, 12, 12, 10, 7, 6, + 6, 6, 6, 11, 12, 12, 11, 12, 12, 9, 8, 7, 7, 9, 9, 11, 11, 10, + 9, 7, 7, 12, 12, 11, 10, 9, 10, 11, 11, 9, 7, 6, 9, 11, 12, 12, + 10, 11, 11, 11, 11, 10, 11, 12, 12, 8, 9, 9, 4, 4, 9, 12, 12, 11, + 10, 8, 7, 7, 8, 11, 12, 12, 12, 12, 11, 10, 12, 12, 12, 12, 6, 9, + 9, 8, 10, 11, 11, 11, 12, 12, 10, 10, 11, 11, 10, 11, 11, 5, 5, 3, + 3, 6, 8, 8, 7, 12, 12, 12, 12, 10, 10, 12, 12, 12, 12, 8, 8, 9, + 11, 11, 10, 7, 7, 9, 9, 11, 12, 12, 11, 12, 12, 11, 11, 10, 7, 8, + 11, 12, 12, 11, 12, 12, 9, 8, 11, 11, 12, 12, 11, 10, 10, 6, 9, 9, + 10, 11, 12, 12, 9, 9, 11, 11, 10, 8, + /* Descriptor 1 - 169 entries */ + 8, 11, 11, 10, 10, 11, 12, 12, 7, 8, 11, 11, 10, 9, 11, 11, 10, 12, + 12, 12, 12, 10, 8, 5, 5, 7, 8, 8, 6, 10, 10, 12, 12, 11, 12, 12, + 11, 8, 7, 6, 7, 11, 11, 10, 9, 12, 12, 11, 10, 9, 6, 4, 4, 6, + 9, 12, 12, 11, 10, 11, 11, 10, 10, 10, 10, 11, 12, 12, 10, 11, 11, 10, + 11, 11, 12, 12, 11, 10, 8, 8, 7, 7, 9, 11, 12, 12, 10, 8, 7, 12, + 12, 12, 12, 11, 11, 9, 9, 9, 6, 6, 8, 9, 11, 12, 12, 11, 12, 12, + 9, 9, 11, 11, 11, 11, 9, 4, 4, 6, 6, 6, 7, 12, 12, 11, 12, 12, + 11, 9, 9, 12, 12, 12, 12, 10, 5, 8, 11, 12, 12, 10, 10, 11, 12, 12, + 8, 8, 7, 7, 5, 9, 11, 11, 10, 8, 7, 7, 10, 12, 12, 12, 12, 9, + 10, 10, 11, 11, 10, 3, 3, + /* Descriptor 2 - 165 entries */ + 8, 12, 12, 11, 12, 12, 11, 10, 10, 9, 11, 11, 10, 8, 6, 5, 6, 6, + 5, 6, 11, 11, 10, 10, 12, 12, 11, 9, 9, 11, 12, 12, 10, 9, 11, 11, + 12, 12, 11, 11, 11, 11, 11, 7, 7, 6, 8, 9, 10, 11, 12, 12, 7, 7, + 10, 10, 11, 11, 11, 11, 8, 8, 9, 12, 12, 12, 12, 11, 12, 12, 7, 6, + 6, 8, 10, 11, 12, 12, 9, 10, 12, 12, 11, 11, 12, 12, 10, 9, 12, 12, + 11, 10, 8, 8, 7, 12, 12, 12, 12, 10, 10, 11, 12, 12, 10, 11, 11, 11, + 11, 10, 8, 9, 11, 11, 11, 12, 12, 4, 4, 6, 6, 7, 8, 10, 10, 9, + 6, 4, 4, 5, 7, 9, 12, 12, 11, 12, 12, 11, 9, 9, 6, 5, 10, 10, + 11, 11, 10, 8, 9, 12, 12, 11, 11, 12, 12, 8, 8, 8, 9, 9, 10, 10, + 9, 3, 3, + /* Descriptor 3 - 162 entries */ + 10, 10, 9, 8, 10, 10, 9, 9, 11, 12, 12, 10, 6, 6, 8, 9, 11, 11, + 11, 11, 8, 8, 7, 10, 11, 12, 12, 11, 11, 10, 8, 7, 8, 12, 12, 11, + 12, 12, 12, 12, 11, 11, 10, 5, 5, 7, 9, 9, 11, 11, 12, 12, 11, 9, + 6, 6, 9, 9, 10, 12, 12, 11, 9, 8, 12, 12, 11, 10, 9, 7, 10, 10, + 10, 12, 12, 11, 8, 7, 12, 12, 11, 12, 12, 11, 10, 12, 12, 11, 11, 12, + 12, 10, 11, 12, 12, 10, 7, 7, 6, 7, 10, 12, 12, 12, 12, 9, 8, 6, + 6, 6, 10, 10, 11, 11, 12, 12, 11, 8, 7, 8, 9, 11, 11, 10, 8, 11, + 11, 10, 9, 4, 4, 4, 4, 6, 8, 12, 12, 11, 11, 12, 12, 11, 11, 10, + 9, 10, 11, 12, 12, 8, 5, 5, 7, 10, 12, 12, 11, 9, 8, 6, 3, 3, + /* Descriptor 4 - 131 entries */ + 2, 6, 6, 7, 7, 8, 8, 7, 10, 12, 12, 11, 10, 10, 8, 9, 10, 10, + 11, 12, 12, 10, 10, 10, 7, 7, 11, 12, 12, 11, 12, 12, 9, 8, 10, 11, + 11, 9, 10, 10, 9, 6, 4, 6, 6, 11, 11, 12, 12, 11, 9, 9, 11, 11, + 11, 12, 12, 7, 8, 8, 7, 4, 4, 5, 5, 4, 6, 10, 10, 11, 11, 10, + 8, 12, 12, 11, 11, 12, 12, 12, 12, 11, 10, 8, 6, 8, 9, 9, 9, 11, + 11, 12, 12, 11, 8, 6, 9, 9, 9, 11, 12, 12, 12, 12, 11, 7, 9, 10, + 12, 12, 11, 10, 12, 12, 11, 10, 12, 12, 11, 7, 7, 8, 11, 12, 12, 11, + 12, 12, 10, 10, 3, + /* Descriptor 5 - 132 entries */ + 2, 10, 10, 10, 10, 9, 10, 11, 11, 8, 11, 12, 12, 10, 9, 7, 11, 12, + 12, 10, 11, 12, 12, 11, 11, 9, 9, 7, 8, 8, 6, 6, 12, 12, 11, 11, + 11, 10, 10, 8, 7, 12, 12, 11, 10, 10, 10, 9, 11, 12, 12, 10, 7, 6, + 4, 4, 7, 11, 12, 12, 11, 12, 12, 9, 8, 7, 7, 5, 5, 6, 6, 4, + 8, 10, 11, 12, 12, 9, 10, 12, 12, 11, 10, 10, 8, 6, 6, 9, 11, 11, + 10, 8, 12, 12, 11, 11, 12, 12, 10, 10, 11, 11, 11, 11, 9, 4, 6, 9, + 11, 12, 12, 11, 11, 8, 9, 9, 8, 9, 11, 12, 12, 10, 8, 7, 9, 12, + 12, 11, 10, 8, 7, 3, + /* Descriptor 6 - 130 entries */ + 2, 7, 10, 10, 12, 12, 11, 10, 8, 7, 10, 11, 11, 9, 8, 7, 11, 12, + 12, 10, 9, 8, 8, 11, 11, 10, 12, 12, 11, 12, 12, 11, 7, 8, 10, 10, + 10, 12, 12, 11, 7, 7, 9, 10, 10, 8, 6, 6, 4, 10, 12, 12, 11, 10, + 10, 9, 11, 12, 12, 10, 7, 6, 5, 4, 5, 11, 12, 12, 10, 11, 12, 12, + 11, 11, 9, 9, 9, 12, 12, 12, 12, 10, 10, 11, 12, 12, 9, 6, 6, 6, + 6, 7, 9, 11, 11, 11, 11, 8, 4, 4, 6, 8, 10, 12, 12, 12, 12, 10, + 12, 12, 11, 8, 8, 7, 11, 12, 12, 11, 11, 9, 10, 11, 11, 9, 7, 10, + 10, 9, 8, 3, + /* Descriptor 7 - 125 entries */ + 2, 8, 9, 10, 10, 12, 12, 11, 10, 10, 11, 12, 12, 8, 7, 9, 11, 11, + 10, 10, 11, 12, 12, 11, 11, 10, 7, 7, 8, 8, 7, 7, 7, 9, 10, 11, + 12, 12, 8, 7, 8, 11, 11, 10, 9, 10, 10, 10, 10, 10, 12, 12, 11, 9, + 6, 5, 5, 4, 4, 6, 6, 8, 9, 12, 12, 11, 12, 12, 12, 12, 8, 8, + 6, 6, 10, 10, 9, 12, 12, 11, 10, 10, 11, 12, 12, 10, 10, 10, 11, 12, + 12, 10, 11, 11, 9, 6, 6, 4, 6, 7, 8, 10, 10, 12, 12, 11, 12, 12, + 11, 7, 8, 8, 7, 10, 11, 12, 12, 9, 10, 11, 12, 12, 9, 4, 3, + /* Descriptor 8 - 121 entries */ + 2, 9, 10, 12, 12, 11, 8, 9, 9, 8, 9, 11, 12, 12, 10, 9, 9, 7, + 7, 7, 8, 10, 10, 9, 7, 10, 10, 10, 11, 12, 12, 8, 8, 10, 10, 11, + 11, 10, 7, 7, 5, 5, 8, 8, 7, 10, 10, 10, 12, 12, 11, 10, 11, 12, + 12, 10, 11, 11, 11, 11, 12, 12, 11, 9, 8, 4, 4, 6, 6, 6, 6, 6, + 8, 12, 12, 11, 11, 11, 10, 12, 12, 11, 8, 9, 11, 11, 12, 12, 12, 12, + 6, 7, 10, 10, 10, 10, 9, 10, 12, 12, 11, 4, 6, 7, 8, 12, 12, 12, + 12, 10, 11, 12, 12, 10, 6, 7, 9, 9, 8, 4, 3, + /* Descriptor 9 - 114 entries */ + 2, 6, 11, 11, 10, 9, 8, 8, 11, 12, 12, 11, 11, 9, 7, 8, 10, 10, + 9, 7, 8, 9, 11, 11, 12, 12, 11, 8, 9, 10, 10, 7, 8, 11, 11, 10, + 9, 11, 11, 10, 12, 12, 11, 10, 8, 5, 5, 7, 7, 6, 4, 6, 9, 11, + 11, 10, 8, 8, 8, 6, 9, 11, 12, 12, 12, 12, 11, 9, 11, 12, 12, 10, + 7, 4, 7, 7, 6, 6, 6, 4, 12, 12, 11, 10, 10, 11, 11, 9, 10, 10, + 11, 12, 12, 10, 10, 10, 8, 6, 8, 10, 12, 12, 12, 12, 10, 10, 8, 11, + 11, 10, 9, 6, 4, 3, + /* Descriptor A - 110 entries */ + 2, 9, 9, 8, 8, 12, 12, 11, 10, 9, 8, 10, 10, 9, 7, 6, 8, 9, + 11, 11, 12, 12, 11, 8, 9, 10, 11, 11, 7, 7, 8, 9, 9, 8, 10, 11, + 11, 10, 11, 12, 12, 5, 5, 6, 8, 9, 9, 8, 9, 10, 11, 12, 12, 4, + 6, 7, 7, 6, 7, 9, 10, 10, 11, 11, 10, 9, 4, 7, 8, 11, 11, 10, + 10, 10, 6, 7, 8, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 6, 4, 6, + 11, 12, 12, 11, 11, 9, 12, 12, 11, 12, 12, 11, 10, 10, 8, 8, 6, 6, 4, 3, -}; - -static const uint16_t ac_vlc_desc4_syms[131] = { - 0x1000, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, 0xFF1, 0xFF0, - 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, 0xFE0, 0xFD6, - 0xFD5, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC5, 0xFC3, 0xFC2, - 0xFC1, 0xFC0, 0xFB5, 0xFB3, 0xFB1, 0xFB0, 0xFA5, 0xFA3, - 0xFA1, 0xFA0, 0xF93, 0xF91, 0xF90, 0xF81, 0xF80, 0xF76, - 0xF71, 0xF70, 0xF66, 0xF61, 0xF60, 0xF56, 0xF51, 0xF50, - 0xF41, 0xF40, 0xF31, 0xF30, 0xF23, 0xF21, 0xF20, 0xF13, - 0xF11, 0xF10, 0xF03, 0xF01, 0xF00, 0xEF1, 0xEF0, 0xEE0, - 0xED0, 0xEC0, 0xEB0, 0x191, 0x181, 0x180, 0x171, 0x161, - 0x140, 0x130, 0x123, 0x120, 0x110, 0x100, 0x0F3, 0x0F0, - 0x0E0, 0x0D0, 0x0C0, 0x0B1, 0x0B0, 0x0A1, 0x0A0, 0x091, - 0x090, 0x085, 0x081, 0x080, 0x075, 0x071, 0x070, 0x066, - 0x065, 0x063, 0x061, 0x060, 0x056, 0x055, 0x053, 0x051, - 0x050, 0x045, 0x043, 0x042, 0x041, 0x040, 0x036, 0x035, - 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, 0x024, 0x023, - 0x022, 0x021, 0x020, 0x018, 0x016, 0x015, 0x014, 0x013, - 0x012, 0x011, 0x010, -}; - -static const uint16_t ac_vlc_desc4_codes[131] = { - 0x006B, 0x00BE, 0x0052, 0x00F3, 0x005B, 0x003A, 0x0009, 0x0007, - 0x00DA, 0x03FB, 0x0123, 0x00B3, 0x01B3, 0x002E, 0x0006, 0x030A, - 0x005A, 0x004A, 0x034A, 0x0072, 0x0005, 0x02DA, 0x0173, 0x04FB, - 0x0032, 0x0013, 0x039B, 0x0B9B, 0x011E, 0x0002, 0x00FB, 0x021E, - 0x009B, 0x007E, 0x0E1A, 0x03CA, 0x007B, 0x02FB, 0x0033, 0x03AB, - 0x0463, 0x008A, 0x0773, 0x041E, 0x002B, 0x031B, 0x065A, 0x011A, - 0x060A, 0x01DA, 0x0963, 0x0323, 0x0BAB, 0x059E, 0x010A, 0x05AB, - 0x0CFB, 0x071B, 0x079E, 0x0F9E, 0x0263, 0x079B, 0x0563, 0x019E, - 0x01AB, 0x0E63, 0x029B, 0x04CA, 0x0DAB, 0x0663, 0x0B1B, 0x020A, - 0x0A1E, 0x021A, 0x0063, 0x061E, 0x06FB, 0x025A, 0x0163, 0x0573, - 0x000A, 0x0223, 0x011B, 0x0C1A, 0x015A, 0x0863, 0x00AB, 0x02CA, - 0x00B2, 0x0A0A, 0x01CA, 0x00A3, 0x0B73, 0x0023, 0x0012, 0x039E, - 0x001A, 0x0CCA, 0x01FB, 0x005E, 0x0A9B, 0x00CA, 0x0373, 0x009E, - 0x0022, 0x07AB, 0x001E, 0x0EFB, 0x009A, 0x000B, 0x041A, 0x019B, - 0x0363, 0x014A, 0x006A, 0x0015, 0x069B, 0x0073, 0x0523, 0x001B, - 0x012B, 0x0003, 0x0001, 0x061A, 0x003E, 0x002A, 0x00E3, 0x003B, - 0x000E, 0x000D, 0x0000, -}; - -static const uint8_t ac_vlc_desc4_bits[131] = { - 7, 8, 7, 8, 7, 6, 4, 3, - 10, 10, 11, 9, 9, 6, 4, 10, - 10, 9, 10, 7, 5, 10, 11, 12, - 8, 6, 12, 12, 9, 6, 11, 12, - 10, 7, 12, 10, 8, 11, 8, 12, - 11, 8, 11, 11, 9, 12, 11, 9, - 11, 9, 12, 10, 12, 11, 10, 12, - 12, 11, 12, 12, 11, 11, 11, 11, - 11, 12, 12, 12, 12, 12, 12, 12, - 12, 11, 12, 11, 12, 11, 12, 11, - 10, 10, 10, 12, 9, 12, 9, 10, - 8, 12, 10, 8, 12, 10, 7, 11, - 11, 12, 10, 7, 12, 11, 12, 9, - 6, 11, 11, 12, 8, 6, 12, 10, - 10, 10, 7, 5, 11, 9, 11, 9, - 9, 6, 4, 12, 8, 7, 8, 7, - 6, 4, 2, -}; - -static const uint16_t ac_vlc_desc5_syms[132] = { - 0x1000, 0xFF8, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, 0xFF1, - 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, 0xFE0, - 0xFD6, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC5, - 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB5, 0xFB3, 0xFB1, 0xFB0, - 0xFA3, 0xFA1, 0xFA0, 0xF96, 0xF93, 0xF91, 0xF90, 0xF86, - 0xF85, 0xF81, 0xF80, 0xF76, 0xF75, 0xF71, 0xF70, 0xF66, - 0xF61, 0xF60, 0xF51, 0xF50, 0xF43, 0xF41, 0xF40, 0xF33, - 0xF31, 0xF30, 0xF23, 0xF21, 0xF20, 0xF11, 0xF10, 0xF00, - 0xEF0, 0xEE0, 0xEC1, 0xEC0, 0x151, 0x141, 0x140, 0x131, - 0x121, 0x120, 0x111, 0x110, 0x103, 0x100, 0x0F0, 0x0E0, - 0x0D3, 0x0D0, 0x0C3, 0x0C1, 0x0C0, 0x0B1, 0x0B0, 0x0A1, - 0x0A0, 0x091, 0x090, 0x081, 0x080, 0x075, 0x071, 0x070, - 0x065, 0x061, 0x060, 0x056, 0x055, 0x053, 0x052, 0x051, - 0x050, 0x046, 0x045, 0x043, 0x042, 0x041, 0x040, 0x035, - 0x034, 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, 0x024, - 0x023, 0x022, 0x021, 0x020, 0x018, 0x016, 0x015, 0x014, - 0x013, 0x012, 0x011, 0x010, -}; - -static const uint16_t ac_vlc_desc5_codes[132] = { - 0x0001, 0x0D62, 0x00BD, 0x0022, 0x009B, 0x0032, 0x0019, 0x0005, - 0x0007, 0x034D, 0x009A, 0x012B, 0x0052, 0x006B, 0x003A, 0x0006, - 0x06FD, 0x017D, 0x081A, 0x031B, 0x031A, 0x0012, 0x0011, 0x0202, - 0x00FD, 0x051B, 0x00D2, 0x001D, 0x011A, 0x0782, 0x018D, 0x007B, - 0x067D, 0x037D, 0x0021, 0x0E8D, 0x0562, 0x008D, 0x00BB, 0x053D, - 0x082A, 0x0002, 0x000D, 0x0302, 0x007D, 0x053B, 0x003B, 0x0A4D, - 0x027D, 0x01FD, 0x042A, 0x01C2, 0x041A, 0x0182, 0x014D, 0x0162, - 0x00C2, 0x032A, 0x0D9A, 0x012A, 0x0102, 0x087D, 0x072B, 0x039A, - 0x0362, 0x019A, 0x0C62, 0x04C2, 0x0D1B, 0x028D, 0x0762, 0x0E7D, - 0x0E41, 0x059A, 0x024D, 0x093B, 0x052B, 0x011B, 0x064D, 0x013D, - 0x0382, 0x0262, 0x0641, 0x0462, 0x004D, 0x0CC2, 0x033B, 0x068D, - 0x0141, 0x0D2B, 0x001B, 0x0041, 0x00C1, 0x0C41, 0x01E2, 0x00EB, - 0x062A, 0x0082, 0x0061, 0x02FD, 0x047D, 0x013B, 0x002A, 0x003D, - 0x005B, 0x022A, 0x02C2, 0x0241, 0x0062, 0x00AA, 0x000B, 0x00E2, - 0x001A, 0x033D, 0x021A, 0x006A, 0x0009, 0x032B, 0x002B, 0x04FD, - 0x0042, 0x016B, 0x002D, 0x000E, 0x0441, 0x00CD, 0x005A, 0x00AB, - 0x000A, 0x0039, 0x0003, 0x0000, -}; - -static const uint8_t ac_vlc_desc5_bits[132] = { - 7, 12, 8, 7, 8, 6, 6, 4, - 3, 10, 9, 11, 8, 9, 6, 4, - 11, 10, 12, 10, 10, 7, 5, 10, - 11, 12, 8, 6, 10, 11, 9, 7, - 12, 10, 7, 12, 12, 10, 8, 11, - 12, 10, 8, 10, 12, 11, 9, 12, - 11, 9, 11, 9, 11, 10, 10, 11, - 11, 10, 12, 10, 10, 12, 11, 10, - 11, 11, 12, 12, 12, 11, 11, 12, - 12, 12, 12, 12, 12, 11, 11, 11, - 11, 10, 12, 12, 10, 12, 10, 12, - 9, 12, 9, 11, 8, 12, 9, 8, - 11, 9, 7, 11, 11, 12, 12, 9, - 7, 11, 10, 11, 11, 8, 6, 9, - 12, 10, 10, 7, 5, 11, 9, 11, - 8, 9, 6, 4, 12, 8, 7, 8, - 6, 6, 4, 2, -}; - -static const uint16_t ac_vlc_desc6_syms[130] = { - 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, - 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, - 0xFE0, 0xFD6, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, - 0xFC5, 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB5, 0xFB3, 0xFB1, - 0xFB0, 0xFA6, 0xFA3, 0xFA1, 0xFA0, 0xF96, 0xF95, 0xF93, - 0xF91, 0xF90, 0xF86, 0xF85, 0xF81, 0xF80, 0xF76, 0xF71, - 0xF70, 0xF63, 0xF61, 0xF60, 0xF53, 0xF51, 0xF50, 0xF43, - 0xF41, 0xF40, 0xF31, 0xF30, 0xF20, 0xF10, 0xF00, 0xEF0, - 0xEE1, 0x131, 0x121, 0x120, 0x111, 0x110, 0x101, 0x100, - 0x0F1, 0x0F0, 0x0E3, 0x0E1, 0x0E0, 0x0D1, 0x0D0, 0x0C3, - 0x0C0, 0x0B3, 0x0B1, 0x0B0, 0x0A1, 0x0A0, 0x091, 0x090, - 0x081, 0x080, 0x075, 0x071, 0x070, 0x065, 0x063, 0x061, - 0x060, 0x056, 0x055, 0x053, 0x051, 0x050, 0x046, 0x045, - 0x043, 0x042, 0x041, 0x040, 0x036, 0x035, 0x034, 0x033, - 0x032, 0x031, 0x030, 0x026, 0x025, 0x024, 0x023, 0x022, - 0x021, 0x020, 0x018, 0x016, 0x015, 0x014, 0x013, 0x012, - 0x011, 0x010, -}; - -static const uint16_t ac_vlc_desc6_codes[130] = { - 0x0022, 0x0BB2, 0x0942, 0x002B, 0x0072, 0x0002, 0x001A, 0x0039, - 0x000D, 0x0007, 0x007B, 0x008E, 0x06DB, 0x00EA, 0x015B, 0x002E, - 0x0006, 0x0959, 0x027B, 0x0A0E, 0x01AB, 0x008A, 0x0012, 0x001E, - 0x0575, 0x005B, 0x02AB, 0x00C2, 0x0015, 0x036A, 0x04B2, 0x0099, - 0x001B, 0x0519, 0x0C19, 0x00DB, 0x004E, 0x0042, 0x0159, 0x03B2, - 0x030E, 0x00EB, 0x0252, 0x0EAB, 0x018A, 0x00E2, 0x06AB, 0x0242, - 0x017B, 0x0452, 0x0319, 0x0152, 0x025B, 0x016A, 0x00AB, 0x0052, - 0x05B2, 0x010E, 0x038E, 0x028A, 0x0359, 0x0019, 0x078A, 0x0C52, - 0x0D8E, 0x0ED9, 0x02D9, 0x0662, 0x0119, 0x09B2, 0x0BAB, 0x0D19, - 0x0C5B, 0x00B2, 0x0542, 0x0B8A, 0x02B2, 0x0142, 0x065B, 0x058E, - 0x0062, 0x018E, 0x038A, 0x00D9, 0x0419, 0x0162, 0x03AB, 0x0075, - 0x07B2, 0x0032, 0x020E, 0x07AB, 0x006B, 0x045B, 0x01B2, 0x0199, - 0x002A, 0x0375, 0x0775, 0x0AAB, 0x01D9, 0x003B, 0x060E, 0x0342, - 0x0175, 0x0262, 0x000A, 0x0005, 0x0559, 0x006A, 0x0D59, 0x0219, - 0x000E, 0x004A, 0x0009, 0x0719, 0x0059, 0x02DB, 0x00D2, 0x01DB, - 0x0025, 0x0001, 0x06D9, 0x00F5, 0x0035, 0x00FB, 0x003A, 0x000B, - 0x0003, 0x0000, -}; - -static const uint8_t ac_vlc_desc6_bits[130] = { - 7, 12, 12, 8, 7, 7, 6, 6, - 4, 3, 10, 9, 11, 8, 9, 6, - 4, 12, 10, 12, 10, 10, 7, 5, - 11, 11, 12, 8, 6, 10, 11, 9, - 7, 12, 12, 10, 7, 10, 12, 12, - 10, 8, 10, 12, 10, 8, 12, 10, - 9, 12, 11, 9, 11, 10, 10, 11, - 11, 10, 10, 10, 10, 11, 11, 12, - 12, 12, 11, 11, 11, 12, 12, 12, - 12, 11, 11, 12, 10, 12, 11, 12, - 10, 11, 12, 10, 12, 9, 12, 9, - 11, 8, 12, 11, 8, 12, 12, 9, - 7, 11, 11, 12, 9, 7, 11, 10, - 11, 11, 8, 6, 12, 9, 12, 10, - 10, 7, 5, 11, 9, 11, 8, 9, - 6, 4, 12, 8, 7, 8, 6, 6, - 4, 2, -}; - -static const uint16_t ac_vlc_desc7_syms[125] = { - 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, - 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, - 0xFE0, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC5, - 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB5, 0xFB3, 0xFB1, 0xFB0, - 0xFA6, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF96, 0xF95, 0xF93, - 0xF91, 0xF90, 0xF86, 0xF81, 0xF80, 0xF73, 0xF71, 0xF70, - 0xF63, 0xF61, 0xF60, 0xF53, 0xF51, 0xF50, 0xF41, 0xF40, - 0xF31, 0xF30, 0xF20, 0xF10, 0xF01, 0xF00, 0x121, 0x111, - 0x101, 0x100, 0x0F1, 0x0F0, 0x0E1, 0x0E0, 0x0D1, 0x0D0, - 0x0C3, 0x0C1, 0x0C0, 0x0B1, 0x0B0, 0x0A3, 0x0A1, 0x0A0, - 0x093, 0x091, 0x090, 0x081, 0x080, 0x071, 0x070, 0x065, - 0x063, 0x061, 0x060, 0x055, 0x053, 0x052, 0x051, 0x050, - 0x046, 0x045, 0x043, 0x042, 0x041, 0x040, 0x036, 0x035, - 0x034, 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, 0x024, - 0x023, 0x022, 0x021, 0x020, 0x018, 0x017, 0x016, 0x015, - 0x014, 0x013, 0x012, 0x011, 0x010, -}; - -static const uint16_t ac_vlc_desc7_codes[125] = { - 0x0053, 0x009A, 0x0EE2, 0x00D3, 0x006A, 0x0052, 0x003A, 0x0035, - 0x000D, 0x0007, 0x0062, 0x0125, 0x0142, 0x0019, 0x01F3, 0x0029, - 0x000E, 0x0082, 0x0ADA, 0x02E3, 0x00E2, 0x0022, 0x0006, 0x0065, - 0x05E3, 0x0765, 0x0032, 0x0039, 0x0F99, 0x05E2, 0x0099, 0x0033, - 0x0362, 0x0799, 0x0F65, 0x0073, 0x004A, 0x02A5, 0x0162, 0x0742, - 0x01A5, 0x00D9, 0x0342, 0x005A, 0x00AA, 0x0EF3, 0x0182, 0x01DA, - 0x0382, 0x035A, 0x00F3, 0x0673, 0x0165, 0x00E5, 0x06F3, 0x0225, - 0x0842, 0x025A, 0x07E3, 0x0399, 0x07A5, 0x072A, 0x0F2A, 0x09E3, - 0x0273, 0x049A, 0x02E5, 0x0B99, 0x02E2, 0x0E73, 0x0562, 0x02F3, - 0x032A, 0x0F42, 0x00DA, 0x0999, 0x012A, 0x0365, 0x00A5, 0x00E3, - 0x0199, 0x03E3, 0x019A, 0x01E2, 0x0173, 0x06E5, 0x0059, 0x01E3, - 0x02DA, 0x002A, 0x000A, 0x06DA, 0x0FA5, 0x0042, 0x01E5, 0x0013, - 0x03E2, 0x015A, 0x03A5, 0x0442, 0x001A, 0x0005, 0x04A5, 0x0265, - 0x08A5, 0x0025, 0x029A, 0x0072, 0x0016, 0x0599, 0x00C2, 0x0242, - 0x00B2, 0x0002, 0x0015, 0x0001, 0x0BE3, 0x06E2, 0x0063, 0x0023, - 0x0012, 0x0009, 0x0003, 0x000B, 0x0000, -}; - -static const uint8_t ac_vlc_desc7_bits[125] = { - 8, 11, 12, 8, 7, 7, 6, 6, - 4, 3, 9, 9, 10, 8, 9, 6, - 4, 9, 12, 10, 10, 7, 5, 10, - 11, 12, 8, 6, 12, 11, 9, 7, - 10, 12, 12, 10, 7, 10, 11, 12, - 10, 8, 11, 10, 8, 12, 10, 9, - 10, 10, 10, 12, 10, 10, 12, 10, - 12, 10, 11, 12, 12, 12, 12, 12, - 11, 11, 11, 12, 11, 12, 11, 11, - 11, 12, 10, 12, 10, 11, 12, 10, - 12, 12, 9, 11, 9, 11, 8, 12, - 12, 9, 7, 11, 12, 12, 9, 7, - 10, 10, 11, 11, 8, 6, 11, 10, - 12, 10, 10, 7, 5, 11, 8, 10, - 8, 8, 6, 4, 12, 12, 8, 7, - 7, 6, 6, 4, 2, -}; - -static const uint16_t ac_vlc_desc8_syms[121] = { - 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, - 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, - 0xFE0, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC5, - 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, 0xFB1, - 0xFB0, 0xFA6, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF96, 0xF95, - 0xF93, 0xF91, 0xF90, 0xF86, 0xF83, 0xF81, 0xF80, 0xF73, - 0xF71, 0xF70, 0xF63, 0xF61, 0xF60, 0xF51, 0xF50, 0xF41, - 0xF40, 0xF30, 0xF21, 0xF20, 0x111, 0x101, 0x0F1, 0x0E1, - 0x0E0, 0x0D1, 0x0D0, 0x0C1, 0x0C0, 0x0B3, 0x0B1, 0x0B0, - 0x0A3, 0x0A1, 0x0A0, 0x093, 0x091, 0x090, 0x083, 0x081, - 0x080, 0x073, 0x071, 0x070, 0x065, 0x063, 0x061, 0x060, - 0x055, 0x053, 0x051, 0x050, 0x046, 0x045, 0x043, 0x042, - 0x041, 0x040, 0x036, 0x035, 0x034, 0x033, 0x032, 0x031, - 0x030, 0x026, 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, - 0x018, 0x017, 0x016, 0x015, 0x014, 0x013, 0x012, 0x011, - 0x010, -}; - -static const uint16_t ac_vlc_desc8_codes[121] = { - 0x00F6, 0x0676, 0x0EB6, 0x00F3, 0x0056, 0x006A, 0x0039, 0x0003, - 0x000D, 0x0007, 0x00A2, 0x0173, 0x00CA, 0x0025, 0x0082, 0x0019, - 0x0001, 0x00B6, 0x0276, 0x02E3, 0x00B2, 0x0062, 0x001A, 0x0175, - 0x01E3, 0x0BE5, 0x004A, 0x0029, 0x07A5, 0x00E3, 0x030A, 0x0176, - 0x0023, 0x0042, 0x05CA, 0x00A5, 0x0142, 0x0052, 0x04A5, 0x0B02, - 0x0D22, 0x0375, 0x0065, 0x0522, 0x0DE3, 0x010A, 0x00F5, 0x0136, - 0x0275, 0x01B2, 0x03F5, 0x03E3, 0x0002, 0x08E3, 0x01A2, 0x0B36, - 0x020A, 0x0076, 0x0CE3, 0x07E5, 0x070A, 0x03A5, 0x02B6, 0x0036, - 0x01E5, 0x02A5, 0x05E3, 0x07B6, 0x07F5, 0x0736, 0x0BA5, 0x0075, - 0x0302, 0x0FE5, 0x01B6, 0x0102, 0x04E3, 0x0022, 0x08A5, 0x01CA, - 0x00E5, 0x0F0A, 0x05E5, 0x0096, 0x0A76, 0x0336, 0x0236, 0x0012, - 0x03B6, 0x0BF5, 0x0073, 0x0035, 0x02B2, 0x000A, 0x0476, 0x0122, - 0x0016, 0x0009, 0x0322, 0x01F5, 0x03E5, 0x01A5, 0x03CA, 0x0072, - 0x0006, 0x06A5, 0x0032, 0x02CA, 0x008A, 0x00C2, 0x0015, 0x000E, - 0x0702, 0x06B6, 0x0063, 0x0033, 0x002A, 0x0005, 0x0013, 0x000B, - 0x0000, -}; - -static const uint8_t ac_vlc_desc8_bits[121] = { - 8, 11, 12, 8, 7, 7, 6, 6, - 4, 3, 9, 9, 10, 8, 8, 6, - 4, 10, 12, 10, 10, 7, 5, 10, - 11, 12, 8, 6, 11, 12, 11, 9, - 7, 9, 11, 12, 9, 7, 11, 12, - 12, 10, 8, 12, 12, 10, 9, 10, - 10, 9, 12, 10, 9, 12, 9, 12, - 10, 11, 12, 12, 12, 12, 11, 10, - 11, 11, 12, 11, 11, 11, 12, 10, - 12, 12, 10, 10, 12, 9, 12, 11, - 9, 12, 11, 8, 12, 12, 10, 7, - 11, 12, 9, 7, 10, 10, 11, 11, - 8, 6, 10, 10, 12, 10, 10, 7, - 5, 11, 8, 10, 8, 8, 6, 4, - 11, 12, 8, 7, 7, 6, 6, 4, - 2, -}; - -static const uint16_t ac_vlc_desc9_syms[114] = { - 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, - 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, - 0xFE0, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC5, - 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, 0xFB2, - 0xFB1, 0xFB0, 0xFA6, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF96, - 0xF93, 0xF91, 0xF90, 0xF83, 0xF81, 0xF80, 0xF73, 0xF71, - 0xF70, 0xF61, 0xF60, 0xF51, 0xF50, 0xF40, 0xF31, 0xF30, - 0xF21, 0x121, 0x0F1, 0x0E1, 0x0D1, 0x0D0, 0x0C1, 0x0C0, - 0x0B1, 0x0B0, 0x0A3, 0x0A1, 0x0A0, 0x093, 0x091, 0x090, - 0x083, 0x081, 0x080, 0x073, 0x071, 0x070, 0x065, 0x063, - 0x061, 0x060, 0x055, 0x053, 0x051, 0x050, 0x045, 0x043, - 0x042, 0x041, 0x040, 0x036, 0x035, 0x034, 0x033, 0x032, - 0x031, 0x030, 0x026, 0x025, 0x024, 0x023, 0x022, 0x021, - 0x020, 0x018, 0x017, 0x016, 0x015, 0x014, 0x013, 0x012, - 0x011, 0x010, -}; - -static const uint16_t ac_vlc_desc9_codes[114] = { - 0x0061, 0x0403, 0x0DB1, 0x0012, 0x0071, 0x0056, 0x0035, 0x0023, - 0x000D, 0x0007, 0x0243, 0x01D3, 0x026A, 0x00A1, 0x00A2, 0x0011, - 0x000E, 0x01AA, 0x0531, 0x0093, 0x0222, 0x0032, 0x0006, 0x07F2, - 0x04D3, 0x0C43, 0x0072, 0x0001, 0x0343, 0x05F2, 0x04AA, 0x03F2, - 0x0031, 0x0045, 0x0143, 0x00AA, 0x0B31, 0x00F2, 0x00C3, 0x0693, - 0x0BF2, 0x0203, 0x00E1, 0x03B1, 0x02D3, 0x00B1, 0x056A, 0x01D2, - 0x008A, 0x046A, 0x01E2, 0x0003, 0x0103, 0x01B1, 0x02E2, 0x0293, - 0x016A, 0x04E2, 0x0443, 0x0521, 0x0321, 0x0043, 0x00D3, 0x00E2, - 0x0703, 0x00D2, 0x0731, 0x0A93, 0x0393, 0x0803, 0x0422, 0x0383, - 0x018A, 0x006A, 0x0021, 0x096A, 0x0303, 0x0052, 0x0CE2, 0x0D31, - 0x038A, 0x0013, 0x01F2, 0x0E93, 0x0083, 0x0005, 0x02D2, 0x0121, - 0x0022, 0x00EA, 0x0036, 0x0122, 0x0193, 0x0331, 0x0183, 0x02AA, - 0x004A, 0x001A, 0x0131, 0x002A, 0x036A, 0x000A, 0x0062, 0x0025, - 0x0009, 0x06E2, 0x05B1, 0x0053, 0x0002, 0x0016, 0x0015, 0x0033, - 0x000B, 0x0000, -}; - -static const uint8_t ac_vlc_desc9_bits[114] = { - 8, 11, 12, 7, 7, 7, 6, 6, - 4, 3, 10, 9, 10, 8, 8, 6, - 4, 9, 12, 10, 10, 7, 5, 11, - 11, 12, 8, 6, 10, 11, 11, 12, - 9, 7, 10, 11, 12, 9, 8, 12, - 12, 10, 8, 10, 10, 9, 11, 9, - 9, 11, 9, 12, 10, 11, 11, 12, - 12, 12, 12, 11, 10, 11, 11, 11, - 11, 10, 11, 12, 10, 12, 11, 10, - 10, 11, 9, 12, 11, 8, 12, 12, - 10, 8, 11, 12, 9, 7, 10, 11, - 11, 8, 6, 9, 10, 12, 10, 10, - 7, 5, 11, 8, 10, 8, 8, 6, - 4, 11, 12, 8, 6, 7, 6, 6, - 4, 2, -}; - -static const uint16_t ac_vlc_descA_syms[110] = { - 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, - 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, - 0xFE0, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC6, - 0xFC5, 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, - 0xFB2, 0xFB1, 0xFB0, 0xFA6, 0xFA5, 0xFA3, 0xFA1, 0xFA0, - 0xF96, 0xF93, 0xF91, 0xF90, 0xF83, 0xF81, 0xF80, 0xF73, - 0xF71, 0xF70, 0xF61, 0xF60, 0xF51, 0xF50, 0xF41, 0xF40, - 0xF31, 0x0E1, 0x0D1, 0x0C1, 0x0C0, 0x0B1, 0x0B0, 0x0A1, - 0x0A0, 0x093, 0x091, 0x090, 0x083, 0x081, 0x080, 0x073, - 0x071, 0x070, 0x063, 0x061, 0x060, 0x055, 0x053, 0x051, - 0x050, 0x045, 0x044, 0x043, 0x042, 0x041, 0x040, 0x036, - 0x035, 0x034, 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, - 0x024, 0x023, 0x022, 0x021, 0x020, 0x018, 0x017, 0x016, - 0x015, 0x014, 0x013, 0x012, 0x011, 0x010, -}; - -static const uint16_t ac_vlc_descA_codes[110] = { - 0x002A, 0x04C5, 0x02A3, 0x004A, 0x0015, 0x0005, 0x0003, 0x0013, - 0x000D, 0x0007, 0x0171, 0x0032, 0x0371, 0x0076, 0x0042, 0x0011, - 0x000E, 0x00AA, 0x04D5, 0x03A3, 0x06A3, 0x0062, 0x001A, 0x06D5, - 0x07F2, 0x0223, 0x0CD5, 0x006A, 0x0001, 0x00F6, 0x0623, 0x03F2, - 0x07EA, 0x01F1, 0x0021, 0x03D5, 0x08C2, 0x07F6, 0x00F2, 0x00E3, - 0x0FEA, 0x02C5, 0x01AA, 0x0082, 0x04A3, 0x00B6, 0x0071, 0x03B2, - 0x0023, 0x01B6, 0x08A3, 0x0002, 0x0BB2, 0x00C5, 0x02EA, 0x0C23, - 0x0FF6, 0x0423, 0x07B2, 0x01C5, 0x07D5, 0x01EA, 0x06EA, 0x02C2, - 0x01F6, 0x01D5, 0x01B2, 0x00B2, 0x04F1, 0x03EA, 0x01A2, 0x02A2, - 0x02D5, 0x0123, 0x00D5, 0x01F2, 0x0055, 0x05B2, 0x04C2, 0x0102, - 0x0061, 0x05D5, 0x00C2, 0x00F1, 0x00A3, 0x0045, 0x0016, 0x01A3, - 0x01C2, 0x08D5, 0x03C5, 0x00EA, 0x000A, 0x0006, 0x00A2, 0x0036, - 0x02F1, 0x0072, 0x0022, 0x0025, 0x0009, 0x03F6, 0x0AA3, 0x0063, - 0x0012, 0x0031, 0x0035, 0x0033, 0x000B, 0x0000, -}; - -static const uint8_t ac_vlc_descA_bits[110] = { - 8, 11, 12, 7, 7, 7, 6, 6, - 4, 3, 10, 8, 10, 8, 8, 6, - 4, 9, 12, 10, 11, 7, 5, 11, - 11, 11, 12, 8, 6, 9, 11, 11, - 12, 9, 7, 11, 12, 12, 9, 8, - 12, 10, 9, 8, 11, 9, 9, 12, - 11, 9, 12, 9, 12, 11, 11, 12, - 12, 12, 11, 10, 11, 10, 11, 10, - 10, 11, 11, 9, 11, 11, 9, 10, - 11, 9, 12, 10, 8, 11, 11, 9, - 7, 11, 12, 11, 12, 8, 6, 10, - 9, 12, 10, 10, 7, 5, 10, 8, - 10, 8, 8, 6, 4, 11, 12, 8, - 6, 7, 6, 6, 4, 2, -}; - -static const uint16_t ac_vlc_descB_syms[101] = { - 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, - 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, - 0xFE0, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC6, - 0xFC5, 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, - 0xFB1, 0xFB0, 0xFA6, 0xFA3, 0xFA1, 0xFA0, 0xF93, 0xF91, - 0xF90, 0xF83, 0xF81, 0xF80, 0xF71, 0xF70, 0xF61, 0xF60, - 0xF51, 0xF50, 0xF41, 0x0F1, 0x0D1, 0x0C1, 0x0B1, 0x0B0, - 0x0A1, 0x0A0, 0x091, 0x090, 0x083, 0x081, 0x080, 0x073, - 0x071, 0x070, 0x063, 0x061, 0x060, 0x055, 0x053, 0x051, - 0x050, 0x045, 0x043, 0x042, 0x041, 0x040, 0x036, 0x035, - 0x034, 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, 0x024, - 0x023, 0x022, 0x021, 0x020, 0x018, 0x017, 0x016, 0x015, - 0x014, 0x013, 0x012, 0x011, 0x010, -}; - -static const uint16_t ac_vlc_descB_codes[101] = { - 0x00EE, 0x03A5, 0x0B73, 0x004E, 0x0035, 0x0015, 0x0023, 0x0013, - 0x000D, 0x0007, 0x0673, 0x01F3, 0x02FE, 0x0096, 0x0133, 0x001E, - 0x0001, 0x0116, 0x00F5, 0x03F5, 0x0473, 0x0052, 0x001A, 0x01D5, - 0x0025, 0x0073, 0x0633, 0x0086, 0x0036, 0x012E, 0x0155, 0x0006, - 0x0055, 0x000E, 0x0106, 0x023E, 0x0192, 0x0075, 0x0173, 0x01AE, - 0x00D5, 0x08F5, 0x002E, 0x01FE, 0x0406, 0x00AE, 0x0E3E, 0x0206, - 0x013E, 0x0373, 0x0D55, 0x063E, 0x0E33, 0x033E, 0x01F5, 0x0273, - 0x003E, 0x06A5, 0x0092, 0x03D5, 0x04F5, 0x053E, 0x0016, 0x00FE, - 0x07A5, 0x0125, 0x0506, 0x0292, 0x00BE, 0x0425, 0x0F73, 0x02F5, - 0x0056, 0x0233, 0x02A5, 0x0C25, 0x007E, 0x0026, 0x0355, 0x0033, - 0x0555, 0x01A5, 0x0306, 0x0046, 0x000A, 0x0225, 0x006E, 0x00A5, - 0x0012, 0x00F3, 0x0005, 0x0009, 0x073E, 0x0773, 0x00B3, 0x0032, - 0x0065, 0x0003, 0x0002, 0x000B, 0x0000, -}; - -static const uint8_t ac_vlc_descB_bits[101] = { - 8, 11, 12, 7, 7, 7, 6, 6, - 4, 3, 11, 9, 10, 8, 9, 6, - 4, 9, 12, 10, 11, 7, 5, 10, - 11, 11, 12, 8, 6, 9, 11, 11, - 9, 7, 11, 11, 9, 8, 10, 9, - 9, 12, 9, 9, 11, 9, 12, 10, - 11, 12, 12, 12, 12, 11, 10, 11, - 10, 11, 10, 10, 11, 11, 9, 10, - 11, 9, 11, 10, 8, 12, 12, 10, - 7, 11, 11, 12, 8, 6, 10, 10, - 12, 10, 10, 7, 5, 10, 8, 10, - 8, 9, 6, 4, 11, 12, 8, 6, - 7, 6, 5, 4, 2, -}; - -static const uint16_t ac_vlc_descC_syms[96] = { - 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, - 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, - 0xFE0, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC6, - 0xFC5, 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, - 0xFB1, 0xFB0, 0xFA6, 0xFA3, 0xFA1, 0xFA0, 0xF93, 0xF91, - 0xF90, 0xF81, 0xF80, 0xF71, 0xF70, 0xF61, 0xF60, 0xF51, - 0x0E1, 0x0C1, 0x0B1, 0x0A1, 0x0A0, 0x091, 0x090, 0x083, - 0x081, 0x080, 0x073, 0x071, 0x070, 0x063, 0x061, 0x060, - 0x055, 0x053, 0x051, 0x050, 0x045, 0x043, 0x042, 0x041, - 0x040, 0x036, 0x035, 0x034, 0x033, 0x032, 0x031, 0x030, - 0x026, 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x018, - 0x017, 0x016, 0x015, 0x014, 0x013, 0x012, 0x011, 0x010, -}; - -static const uint16_t ac_vlc_descC_codes[96] = { - 0x00DE, 0x072E, 0x0576, 0x006E, 0x0075, 0x0055, 0x0013, 0x0033, - 0x000D, 0x0007, 0x07D2, 0x0052, 0x0065, 0x00CE, 0x0183, 0x003E, - 0x0001, 0x002E, 0x0F35, 0x0003, 0x0243, 0x001A, 0x0006, 0x01A5, - 0x0043, 0x0012, 0x0E43, 0x00B6, 0x0016, 0x0135, 0x0176, 0x0643, - 0x0035, 0x001E, 0x0735, 0x0283, 0x0125, 0x00AE, 0x00D2, 0x0165, - 0x0103, 0x0603, 0x00E5, 0x0C43, 0x02B5, 0x04A5, 0x00A5, 0x0443, - 0x0265, 0x0476, 0x0212, 0x0112, 0x0376, 0x012E, 0x02D2, 0x0083, - 0x0483, 0x015E, 0x06A5, 0x0335, 0x005E, 0x0025, 0x01D2, 0x00F6, - 0x03D2, 0x032E, 0x03B5, 0x005A, 0x0203, 0x02A5, 0x0BD2, 0x004E, - 0x0032, 0x01B5, 0x00B5, 0x0A65, 0x0225, 0x0276, 0x000E, 0x000A, - 0x03E5, 0x0143, 0x01E5, 0x0036, 0x0092, 0x0005, 0x0009, 0x0665, - 0x0076, 0x00C3, 0x003A, 0x0015, 0x0023, 0x0002, 0x000B, 0x0000, -}; - -static const uint8_t ac_vlc_descC_bits[96] = { - 8, 11, 11, 7, 7, 7, 6, 6, - 4, 3, 11, 8, 10, 8, 9, 6, - 4, 9, 12, 10, 11, 7, 5, 9, - 11, 10, 12, 8, 6, 10, 11, 12, - 9, 7, 12, 10, 9, 8, 10, 9, - 9, 11, 9, 12, 10, 11, 11, 12, - 12, 11, 10, 9, 10, 10, 10, 11, - 11, 9, 11, 11, 9, 10, 10, 8, - 12, 11, 10, 7, 11, 11, 12, 8, - 6, 10, 10, 12, 10, 10, 7, 5, - 10, 9, 10, 8, 8, 6, 4, 11, - 11, 8, 6, 7, 6, 5, 4, 2, + /* Descriptor B - 101 entries */ + 2, 5, 8, 10, 10, 9, 7, 6, 5, 5, 11, 11, 10, 11, 11, 10, 8, 7, + 6, 9, 9, 8, 7, 6, 7, 7, 9, 9, 9, 9, 8, 8, 6, 10, 11, 12, + 12, 11, 11, 11, 11, 8, 8, 10, 10, 9, 4, 4, 6, 11, 12, 12, 10, 9, + 10, 11, 11, 10, 11, 11, 7, 7, 9, 11, 12, 12, 10, 9, 10, 10, 7, 8, + 12, 12, 11, 10, 10, 10, 4, 6, 6, 6, 10, 11, 12, 12, 9, 8, 11, 11, + 11, 11, 10, 12, 12, 12, 12, 9, 9, 4, 3, + /* Descriptor C - 96 entries */ + 2, 5, 10, 10, 9, 8, 8, 10, 10, 10, 12, 12, 11, 6, 5, 7, 7, 6, + 5, 6, 8, 8, 11, 11, 10, 11, 11, 10, 8, 7, 8, 8, 9, 10, 11, 11, + 8, 7, 7, 9, 9, 8, 6, 4, 4, 6, 10, 10, 9, 11, 11, 11, 11, 9, + 10, 12, 12, 11, 9, 9, 10, 10, 7, 7, 9, 10, 11, 12, 12, 10, 10, 10, + 10, 7, 4, 10, 11, 11, 9, 11, 11, 10, 9, 11, 12, 12, 11, 12, 12, 9, + 8, 6, 6, 6, 4, 3, }; static const int tscc2_ac_vlc_sizes[NUM_VLC_SETS] = { 172, 169, 165, 162, 131, 132, 130, 125, 121, 114, 110, 101, 96 }; -static const uint16_t * const tscc2_ac_vlc_syms[NUM_VLC_SETS] = { - ac_vlc_desc0_syms, ac_vlc_desc1_syms, ac_vlc_desc2_syms, ac_vlc_desc3_syms, - ac_vlc_desc4_syms, ac_vlc_desc5_syms, ac_vlc_desc6_syms, ac_vlc_desc7_syms, - ac_vlc_desc8_syms, ac_vlc_desc9_syms, ac_vlc_descA_syms, ac_vlc_descB_syms, - ac_vlc_descC_syms, -}; - -static const uint16_t * const tscc2_ac_vlc_codes[NUM_VLC_SETS] = { - ac_vlc_desc0_codes, ac_vlc_desc1_codes, ac_vlc_desc2_codes, - ac_vlc_desc3_codes, ac_vlc_desc4_codes, ac_vlc_desc5_codes, - ac_vlc_desc6_codes, ac_vlc_desc7_codes, ac_vlc_desc8_codes, - ac_vlc_desc9_codes, ac_vlc_descA_codes, ac_vlc_descB_codes, - ac_vlc_descC_codes, -}; - -static const uint8_t * const tscc2_ac_vlc_bits[NUM_VLC_SETS] = { - ac_vlc_desc0_bits, ac_vlc_desc1_bits, ac_vlc_desc2_bits, ac_vlc_desc3_bits, - ac_vlc_desc4_bits, ac_vlc_desc5_bits, ac_vlc_desc6_bits, ac_vlc_desc7_bits, - ac_vlc_desc8_bits, ac_vlc_desc9_bits, ac_vlc_descA_bits, ac_vlc_descB_bits, - ac_vlc_descC_bits, -}; - #endif /* AVCODEC_TSCC2DATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/tscc.c ffmpeg-4.4/libavcodec/tscc.c --- ffmpeg-4.2.2/libavcodec/tscc.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tscc.c 2021-04-08 21:28:39.000000000 +0000 @@ -72,7 +72,7 @@ int palette_has_changed = 0; if (c->avctx->pix_fmt == AV_PIX_FMT_PAL8) { - int size; + buffer_size_t size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size); if (pal && size == AVPALETTE_SIZE) { @@ -103,7 +103,7 @@ return AVERROR_UNKNOWN; } - if ((ret = ff_reget_buffer(avctx, frame)) < 0) + if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0) return ret; if (ret != Z_DATA_ERROR) { diff -Nru ffmpeg-4.2.2/libavcodec/tta.c ffmpeg-4.4/libavcodec/tta.c --- ffmpeg-4.2.2/libavcodec/tta.c 2019-12-31 21:35:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/tta.c 2021-04-08 21:28:39.000000000 +0000 @@ -129,7 +129,7 @@ s->avctx = avctx; - // 30bytes includes TTA1 header + // 22 bytes for a TTA1 header if (avctx->extradata_size < 22) return AVERROR_INVALIDDATA; @@ -389,13 +389,6 @@ return ret; } -static int init_thread_copy(AVCodecContext *avctx) -{ - TTAContext *s = avctx->priv_data; - s->avctx = avctx; - return allocate_buffers(avctx); -} - static av_cold int tta_decode_close(AVCodecContext *avctx) { TTAContext *s = avctx->priv_data; @@ -430,7 +423,6 @@ .init = tta_decode_init, .close = tta_decode_close, .decode = tta_decode_frame, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(init_thread_copy), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF, .priv_class = &tta_decoder_class, }; diff -Nru ffmpeg-4.2.2/libavcodec/ttadsp.c ffmpeg-4.4/libavcodec/ttadsp.c --- ffmpeg-4.2.2/libavcodec/ttadsp.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ttadsp.c 2020-07-09 09:17:46.000000000 +0000 @@ -20,9 +20,11 @@ #include "ttadsp.h" #include "config.h" -static void tta_filter_process_c(int32_t *qm, int32_t *dx, int32_t *dl, +static void tta_filter_process_c(int32_t *qmi, int32_t *dx, int32_t *dl, int32_t *error, int32_t *in, int32_t shift, int32_t round) { + uint32_t *qm = qmi; + if (*error < 0) { qm[0] -= dx[0]; qm[1] -= dx[1]; qm[2] -= dx[2]; qm[3] -= dx[3]; qm[4] -= dx[4]; qm[5] -= dx[5]; qm[6] -= dx[6]; qm[7] -= dx[7]; diff -Nru ffmpeg-4.2.2/libavcodec/ttaenc.c ffmpeg-4.4/libavcodec/ttaenc.c --- ffmpeg-4.2.2/libavcodec/ttaenc.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ttaenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -164,7 +164,7 @@ put_bits(&pb, 31, 0x7FFFFFFF); unary -= 31; } else { - put_bits(&pb, unary, (1 << unary) - 1); + put_bits(&pb, unary, (1U << unary) - 1); unary = 0; } } while (unary); @@ -209,7 +209,7 @@ .init = tta_encode_init, .close = tta_encode_close, .encode2 = tta_encode_frame, - .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_LOSSLESS, + .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, diff -Nru ffmpeg-4.2.2/libavcodec/ttmlenc.c ffmpeg-4.4/libavcodec/ttmlenc.c --- ffmpeg-4.2.2/libavcodec/ttmlenc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ttmlenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,210 @@ +/* + * TTML subtitle encoder + * Copyright (c) 2020 24i + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * TTML subtitle encoder + * @see https://www.w3.org/TR/ttml1/ + * @see https://www.w3.org/TR/ttml2/ + * @see https://www.w3.org/TR/ttml-imsc/rec + */ + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/avstring.h" +#include "libavutil/bprint.h" +#include "libavutil/internal.h" +#include "ass_split.h" +#include "ass.h" +#include "ttmlenc.h" + +typedef struct { + AVCodecContext *avctx; + ASSSplitContext *ass_ctx; + AVBPrint buffer; +} TTMLContext; + +static void ttml_text_cb(void *priv, const char *text, int len) +{ + TTMLContext *s = priv; + AVBPrint cur_line = { 0 }; + AVBPrint *buffer = &s->buffer; + + av_bprint_init(&cur_line, len, AV_BPRINT_SIZE_UNLIMITED); + + av_bprint_append_data(&cur_line, text, len); + if (!av_bprint_is_complete(&cur_line)) { + av_log(s->avctx, AV_LOG_ERROR, + "Failed to move the current subtitle dialog to AVBPrint!\n"); + av_bprint_finalize(&cur_line, NULL); + return; + } + + + av_bprint_escape(buffer, cur_line.str, NULL, AV_ESCAPE_MODE_XML, + 0); + + av_bprint_finalize(&cur_line, NULL); +} + +static void ttml_new_line_cb(void *priv, int forced) +{ + TTMLContext *s = priv; + + av_bprintf(&s->buffer, "
"); +} + +static const ASSCodesCallbacks ttml_callbacks = { + .text = ttml_text_cb, + .new_line = ttml_new_line_cb, +}; + +static int ttml_encode_frame(AVCodecContext *avctx, uint8_t *buf, + int bufsize, const AVSubtitle *sub) +{ + TTMLContext *s = avctx->priv_data; + ASSDialog *dialog; + int i; + + av_bprint_clear(&s->buffer); + + for (i=0; inum_rects; i++) { + const char *ass = sub->rects[i]->ass; + + if (sub->rects[i]->type != SUBTITLE_ASS) { + av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n"); + return AVERROR(EINVAL); + } + +#if FF_API_ASS_TIMING + if (!strncmp(ass, "Dialogue: ", 10)) { + int num; + dialog = ff_ass_split_dialog(s->ass_ctx, ass, 0, &num); + + for (; dialog && num--; dialog++) { + int ret = ff_ass_split_override_codes(&ttml_callbacks, s, + dialog->text); + int log_level = (ret != AVERROR_INVALIDDATA || + avctx->err_recognition & AV_EF_EXPLODE) ? + AV_LOG_ERROR : AV_LOG_WARNING; + + if (ret < 0) { + av_log(avctx, log_level, + "Splitting received ASS dialog failed: %s\n", + av_err2str(ret)); + + if (log_level == AV_LOG_ERROR) + return ret; + } + } + } else { +#endif + dialog = ff_ass_split_dialog2(s->ass_ctx, ass); + if (!dialog) + return AVERROR(ENOMEM); + + { + int ret = ff_ass_split_override_codes(&ttml_callbacks, s, + dialog->text); + int log_level = (ret != AVERROR_INVALIDDATA || + avctx->err_recognition & AV_EF_EXPLODE) ? + AV_LOG_ERROR : AV_LOG_WARNING; + + if (ret < 0) { + av_log(avctx, log_level, + "Splitting received ASS dialog text %s failed: %s\n", + dialog->text, + av_err2str(ret)); + + if (log_level == AV_LOG_ERROR) { + ff_ass_free_dialog(&dialog); + return ret; + } + } + + ff_ass_free_dialog(&dialog); + } +#if FF_API_ASS_TIMING + } +#endif + } + + if (!av_bprint_is_complete(&s->buffer)) + return AVERROR(ENOMEM); + if (!s->buffer.len) + return 0; + + // force null-termination, so in case our destination buffer is + // too small, the return value is larger than bufsize minus null. + if (av_strlcpy(buf, s->buffer.str, bufsize) > bufsize - 1) { + av_log(avctx, AV_LOG_ERROR, "Buffer too small for TTML event.\n"); + return AVERROR_BUFFER_TOO_SMALL; + } + + return s->buffer.len; +} + +static av_cold int ttml_encode_close(AVCodecContext *avctx) +{ + TTMLContext *s = avctx->priv_data; + + ff_ass_split_free(s->ass_ctx); + + av_bprint_finalize(&s->buffer, NULL); + + return 0; +} + +static av_cold int ttml_encode_init(AVCodecContext *avctx) +{ + TTMLContext *s = avctx->priv_data; + + s->avctx = avctx; + + if (!(s->ass_ctx = ff_ass_split(avctx->subtitle_header))) { + return AVERROR_INVALIDDATA; + } + + if (!(avctx->extradata = av_mallocz(TTMLENC_EXTRADATA_SIGNATURE_SIZE + + 1 + AV_INPUT_BUFFER_PADDING_SIZE))) { + return AVERROR(ENOMEM); + } + + avctx->extradata_size = TTMLENC_EXTRADATA_SIGNATURE_SIZE; + memcpy(avctx->extradata, TTMLENC_EXTRADATA_SIGNATURE, + TTMLENC_EXTRADATA_SIGNATURE_SIZE); + + av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED); + + return 0; +} + +AVCodec ff_ttml_encoder = { + .name = "ttml", + .long_name = NULL_IF_CONFIG_SMALL("TTML subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_TTML, + .priv_data_size = sizeof(TTMLContext), + .init = ttml_encode_init, + .encode_sub = ttml_encode_frame, + .close = ttml_encode_close, + .capabilities = FF_CODEC_CAP_INIT_CLEANUP, +}; diff -Nru ffmpeg-4.2.2/libavcodec/ttmlenc.h ffmpeg-4.4/libavcodec/ttmlenc.h --- ffmpeg-4.2.2/libavcodec/ttmlenc.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ttmlenc.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,28 @@ +/* + * TTML subtitle encoder shared functionality + * Copyright (c) 2020 24i + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_TTMLENC_H +#define AVCODEC_TTMLENC_H + +#define TTMLENC_EXTRADATA_SIGNATURE "lavc-ttmlenc" +#define TTMLENC_EXTRADATA_SIGNATURE_SIZE (sizeof(TTMLENC_EXTRADATA_SIGNATURE) - 1) + +#endif /* AVCODEC_TTMLENC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/twinvq.c ffmpeg-4.4/libavcodec/twinvq.c --- ffmpeg-4.2.2/libavcodec/twinvq.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/twinvq.c 2021-04-08 21:28:39.000000000 +0000 @@ -538,6 +538,7 @@ int size_m = mtab->size / mtab->fmode[TWINVQ_FT_MEDIUM].sub; int channels = tctx->avctx->channels; float norm = channels == 1 ? 2.0 : 1.0; + int table_size = 2 * mtab->size * channels; for (i = 0; i < 3; i++) { int bsize = tctx->mtab->size / tctx->mtab->fmode[i].sub; @@ -546,25 +547,17 @@ return ret; } - FF_ALLOC_ARRAY_OR_GOTO(tctx->avctx, tctx->tmp_buf, - mtab->size, sizeof(*tctx->tmp_buf), alloc_fail); - - FF_ALLOC_ARRAY_OR_GOTO(tctx->avctx, tctx->spectrum, - 2 * mtab->size, channels * sizeof(*tctx->spectrum), - alloc_fail); - FF_ALLOC_ARRAY_OR_GOTO(tctx->avctx, tctx->curr_frame, - 2 * mtab->size, channels * sizeof(*tctx->curr_frame), - alloc_fail); - FF_ALLOC_ARRAY_OR_GOTO(tctx->avctx, tctx->prev_frame, - 2 * mtab->size, channels * sizeof(*tctx->prev_frame), - alloc_fail); + if (!FF_ALLOC_TYPED_ARRAY(tctx->tmp_buf, mtab->size) || + !FF_ALLOC_TYPED_ARRAY(tctx->spectrum, table_size) || + !FF_ALLOC_TYPED_ARRAY(tctx->curr_frame, table_size) || + !FF_ALLOC_TYPED_ARRAY(tctx->prev_frame, table_size)) + return AVERROR(ENOMEM); for (i = 0; i < 3; i++) { int m = 4 * mtab->size / mtab->fmode[i].sub; double freq = 2 * M_PI / m; - FF_ALLOC_ARRAY_OR_GOTO(tctx->avctx, tctx->cos_tabs[i], - (m / 4), sizeof(*tctx->cos_tabs[i]), alloc_fail); - + if (!FF_ALLOC_TYPED_ARRAY(tctx->cos_tabs[i], m / 4)) + return AVERROR(ENOMEM); for (j = 0; j <= m / 8; j++) tctx->cos_tabs[i][j] = cos((2 * j + 1) * freq); for (j = 1; j < m / 8; j++) @@ -576,9 +569,6 @@ ff_init_ff_sine_windows(av_log2(mtab->size)); return 0; - -alloc_fail: - return AVERROR(ENOMEM); } /** diff -Nru ffmpeg-4.2.2/libavcodec/twinvq_data.h ffmpeg-4.4/libavcodec/twinvq_data.h --- ffmpeg-4.2.2/libavcodec/twinvq_data.h 2016-03-29 02:25:22.000000000 +0000 +++ ffmpeg-4.4/libavcodec/twinvq_data.h 2021-04-08 21:28:39.000000000 +0000 @@ -135,7 +135,6 @@ * without risking a segfault on malformed files. */ static const struct twinvq_data { - float lsp08[504]; int16_t fcb08l[640]; int16_t fcb08m[320]; int16_t fcb08s[320]; @@ -159,7 +158,6 @@ int16_t fcb11m[320]; int16_t fcb11s[320]; int16_t shape11[1280]; - float lsp11[1312]; int16_t cb1110l0[1280]; int16_t cb1110l1[1280]; @@ -172,7 +170,6 @@ int16_t fcb16m[320]; int16_t fcb16s[320]; int16_t shape16[1920]; - float lsp16[1400]; int16_t cb1616l0[1024]; int16_t cb1616l1[1024]; @@ -192,7 +189,6 @@ int16_t fcb22m_1[640]; int16_t fcb22s_1[640]; int16_t shape22_1[1152]; - float lsp22_1[1312]; int16_t cb2224l0[960]; int16_t cb2224l1[960]; @@ -225,7 +221,6 @@ int16_t fcb44m[640]; int16_t fcb44s[640]; int16_t shape44[1152]; - float lsp44[1640]; int16_t cb4448l0[896]; int16_t cb4448l1[896]; @@ -10036,584 +10031,6 @@ -3976, -66, -594, 6181, -110, 292, 1129, -591 }, -.lsp08 = { - 0.2702, 0.5096, 0.6437, 0.7672, 0.9639, 1.0696, 1.2625, 1.5789, - 1.9285, 2.2383, 2.5129, 2.8470, 0.1740, 0.3677, 0.6082, 0.8387, - 1.1084, 1.3721, 1.6362, 1.8733, 2.0640, 2.3442, 2.6087, 2.8548, - 0.1536, 0.3279, 0.5143, 0.6859, 0.9763, 1.2744, 1.5605, 1.8566, - 2.1007, 2.3450, 2.6075, 2.8850, 0.2075, 0.4533, 0.7709, 1.0377, - 1.2953, 1.5132, 1.7826, 2.0351, 2.2590, 2.4996, 2.6795, 2.8748, - 0.1393, 0.2453, 0.3754, 0.5453, 0.8148, 1.1289, 1.4389, 1.7592, - 2.0353, 2.3215, 2.5934, 2.8588, 0.1250, 0.3627, 0.7613, 1.1380, - 1.4163, 1.5565, 1.6920, 1.8130, 1.8678, 2.0427, 2.4318, 2.8544, - 0.2256, 0.4223, 0.6452, 0.8599, 1.0673, 1.3118, 1.5486, 1.8366, - 2.0759, 2.3026, 2.5284, 2.8030, 0.2304, 0.4404, 0.6891, 0.8964, - 1.1510, 1.4202, 1.6483, 1.8580, 2.1181, 2.3686, 2.6078, 2.9128, - 0.2230, 0.3816, 0.5520, 0.6062, 0.7909, 1.0988, 1.4330, 1.7846, - 2.0713, 2.3457, 2.6048, 2.8708, 0.2447, 0.5800, 0.8249, 0.9905, - 1.1721, 1.3990, 1.6694, 1.9064, 2.1307, 2.4255, 2.6815, 2.9117, - 0.1974, 0.3812, 0.5802, 0.7759, 0.9280, 1.1547, 1.4170, 1.6369, - 1.8890, 2.2587, 2.5626, 2.8239, 0.1209, 0.2510, 0.4841, 0.8048, - 1.1197, 1.3563, 1.6073, 1.8926, 2.1350, 2.3669, 2.6291, 2.8985, - 0.2352, 0.4347, 0.6582, 0.8178, 0.9548, 1.1654, 1.4942, 1.8812, - 2.1703, 2.3779, 2.6412, 2.8871, 0.2091, 0.4084, 0.6730, 0.9151, - 1.1259, 1.3262, 1.5937, 1.8129, 2.0237, 2.3317, 2.5778, 2.8620, - 0.1167, 0.2406, 0.4520, 0.7298, 0.9848, 1.2448, 1.5137, 1.7874, - 2.0280, 2.3020, 2.5914, 2.8794, 0.3003, 0.4966, 0.6520, 0.8505, - 1.1600, 1.3981, 1.5805, 1.8346, 2.0757, 2.3102, 2.5760, 2.8499, - 0.2451, 0.4163, 0.5960, 0.7805, 0.9507, 1.2438, 1.5587, 1.8581, - 2.0735, 2.3198, 2.5704, 2.8220, 0.3112, 0.5517, 0.7032, 0.8528, - 1.1489, 1.4257, 1.6848, 1.9388, 2.1577, 2.4265, 2.6678, 2.9051, - 0.2249, 0.3897, 0.5559, 0.7473, 1.0158, 1.3581, 1.6914, 1.9930, - 2.1843, 2.3534, 2.5512, 2.8065, 0.2600, 0.4574, 0.7349, 0.9691, - 1.1696, 1.3848, 1.6335, 1.9021, 2.1174, 2.3481, 2.5902, 2.8390, - 0.2246, 0.3372, 0.4560, 0.5249, 0.7056, 1.0273, 1.3810, 1.7132, - 1.9819, 2.2574, 2.5410, 2.8491, 0.1419, 0.4834, 0.8835, 1.1453, - 1.2839, 1.4224, 1.5593, 1.7877, 2.1285, 2.4070, 2.6043, 2.8511, - 0.1886, 0.3677, 0.5617, 0.8099, 1.1277, 1.3841, 1.5804, 1.8136, - 2.0307, 2.2805, 2.5399, 2.8322, 0.2351, 0.4151, 0.6675, 0.8713, - 1.0464, 1.3292, 1.6586, 1.9281, 2.1355, 2.3495, 2.6222, 2.8782, - 0.2700, 0.4489, 0.6206, 0.7121, 0.7737, 0.9848, 1.3658, 1.7433, - 2.0139, 2.2243, 2.4806, 2.8175, 0.2479, 0.4425, 0.6490, 0.8745, - 1.1161, 1.3849, 1.6773, 1.9566, 2.1491, 2.3624, 2.5685, 2.8114, - 0.2035, 0.3701, 0.5567, 0.7953, 1.0082, 1.2758, 1.5373, 1.7822, - 2.0175, 2.2601, 2.4759, 2.7771, 0.1856, 0.3461, 0.5998, 0.9041, - 1.2383, 1.4612, 1.6667, 1.9305, 2.1617, 2.4107, 2.6477, 2.8656, - 0.2107, 0.3715, 0.5289, 0.6651, 0.8420, 1.1168, 1.4401, 1.7230, - 1.9901, 2.2687, 2.5452, 2.8655, 0.1218, 0.2999, 0.6348, 0.9482, - 1.2745, 1.5876, 1.9129, 2.2348, 2.4020, 2.4922, 2.6351, 2.8357, - 0.1617, 0.3483, 0.5869, 0.8163, 1.0366, 1.2344, 1.4609, 1.7029, - 1.9476, 2.2337, 2.5258, 2.8442, 0.2505, 0.4894, 0.7510, 0.9152, - 1.0845, 1.3657, 1.6528, 1.8346, 2.0160, 2.2811, 2.5338, 2.8136, - 0.0947, 0.1158, 0.0578, -0.0337, -0.0066, 0.0104, -0.0447, -0.0505, --0.0778, -0.0293, 0.0251, -0.0143, 0.0349, -0.0227, -0.0909, 0.0523, - 0.0325, -0.0410, -0.1045, -0.0899, -0.0009, 0.0075, -0.0575, -0.0855, --0.0129, 0.0575, 0.0597, 0.0391, 0.0371, -0.0184, -0.0083, 0.0287, - 0.0143, 0.0167, 0.0120, -0.0168, 0.0452, 0.0223, -0.0352, 0.0119, --0.0496, -0.0965, -0.0661, -0.0072, 0.1099, 0.0843, -0.0087, -0.0478, --0.0128, -0.0120, -0.0004, 0.0731, 0.1047, 0.0630, 0.0196, -0.0103, --0.0399, -0.0986, -0.0912, -0.0390, -0.0247, -0.0694, -0.0749, -0.0066, - 0.0223, 0.0634, 0.0343, -0.0134, 0.0727, 0.0241, 0.0066, 0.0437, - 0.0610, 0.0364, 0.0248, -0.0358, -0.0686, -0.0104, 0.0426, 0.0088, --0.0137, -0.0165, 0.0671, 0.0815, -0.0863, -0.0644, -0.0088, 0.0023, - 0.0482, 0.1174, 0.1270, 0.0594, 0.0165, 0.0949, 0.1098, 0.0137, - 0.4951, 0.4999, 0.4958, 0.4907, 0.4984, 0.4965, 0.4958, 0.4996, - 0.4987, 0.4958, 0.4986, 0.4977, 0.2841, 0.2186, 0.1474, 0.1687, - 0.2217, 0.2632, 0.2706, 0.2624, 0.2162, 0.2453, 0.2460, 0.2531 -}, - -.lsp11 = { - 0.1103, 0.3862, 0.6863, 0.8447, 0.9231, 1.0261, 1.1248, 1.4057, - 1.6621, 1.8010, 1.8692, 2.0704, 2.3490, 2.6060, 2.7539, 2.8977, - 0.1273, 0.2407, 0.3812, 0.6004, 0.7767, 0.9383, 1.1344, 1.3351, - 1.5233, 1.7262, 1.9466, 2.1739, 2.3495, 2.5162, 2.7164, 2.9202, - 0.2010, 0.3330, 0.4488, 0.6465, 0.8046, 0.9889, 1.1479, 1.2964, - 1.4770, 1.6606, 1.8789, 2.1155, 2.3287, 2.5199, 2.7101, 2.9119, - 0.1168, 0.2197, 0.3279, 0.4691, 0.6268, 0.8251, 1.0533, 1.2714, - 1.4712, 1.6762, 1.8831, 2.1114, 2.3230, 2.5297, 2.7365, 2.9270, - 0.1405, 0.3109, 0.4986, 0.6891, 0.8634, 1.0583, 1.2594, 1.4349, - 1.6232, 1.8116, 1.9905, 2.1935, 2.3799, 2.5656, 2.7661, 2.9486, - 0.1703, 0.3057, 0.4403, 0.5225, 0.5969, 0.8110, 1.0729, 1.3215, - 1.5407, 1.7381, 1.9477, 2.1680, 2.3586, 2.5612, 2.7630, 2.9410, - 0.1128, 0.2628, 0.4523, 0.6495, 0.8176, 0.9816, 1.1746, 1.3710, - 1.5568, 1.7518, 1.9497, 2.1452, 2.3346, 2.5389, 2.7362, 2.9264, - 0.1809, 0.3287, 0.5205, 0.7264, 0.9298, 1.1217, 1.2970, 1.4894, - 1.6874, 1.8493, 2.0576, 2.2382, 2.4097, 2.6041, 2.7796, 2.9389, - 0.2502, 0.4709, 0.6892, 0.8346, 0.9209, 1.0455, 1.2399, 1.4616, - 1.6463, 1.8380, 2.0475, 2.2397, 2.4665, 2.6550, 2.7701, 2.8895, - 0.1040, 0.2340, 0.3964, 0.5740, 0.7764, 0.9941, 1.2000, 1.4014, - 1.6024, 1.7974, 1.9939, 2.1959, 2.3783, 2.5663, 2.7613, 2.9484, - 0.1912, 0.3393, 0.4743, 0.6313, 0.8014, 0.9879, 1.1855, 1.3922, - 1.5678, 1.7289, 1.9271, 2.1165, 2.3089, 2.5414, 2.7448, 2.9269, - 0.0965, 0.2025, 0.3398, 0.4990, 0.6934, 0.9386, 1.1730, 1.3766, - 1.5783, 1.7783, 1.9790, 2.1831, 2.3670, 2.5578, 2.7641, 2.9516, - 0.2126, 0.3652, 0.5545, 0.7170, 0.8674, 1.0640, 1.2558, 1.4061, - 1.5904, 1.8095, 1.9760, 2.1505, 2.3549, 2.5575, 2.7023, 2.8877, - 0.1827, 0.3426, 0.4894, 0.6488, 0.7960, 0.9535, 1.1217, 1.2798, - 1.4566, 1.6453, 1.8044, 2.0042, 2.2379, 2.4611, 2.6697, 2.8966, - 0.2034, 0.3822, 0.5231, 0.6960, 0.9200, 1.0394, 1.1616, 1.3772, - 1.5493, 1.7330, 1.9646, 2.1233, 2.3334, 2.5361, 2.7087, 2.9470, - 0.1050, 0.2060, 0.3705, 0.5998, 0.8337, 1.0577, 1.2559, 1.4327, - 1.6334, 1.8165, 1.9853, 2.2058, 2.4063, 2.5818, 2.7625, 2.9458, - 0.1419, 0.4053, 0.6660, 0.8911, 1.0405, 1.1547, 1.2506, 1.3926, - 1.5669, 1.7527, 1.9694, 2.2054, 2.3889, 2.5743, 2.7586, 2.9174, - 0.1514, 0.2825, 0.4309, 0.5772, 0.7470, 0.9703, 1.1462, 1.3316, - 1.5321, 1.7259, 1.9282, 2.1266, 2.3106, 2.5064, 2.7067, 2.9094, - 0.1693, 0.3156, 0.4878, 0.6635, 0.8206, 0.9569, 1.1154, 1.3064, - 1.5109, 1.7184, 1.9179, 2.1036, 2.2763, 2.4820, 2.6949, 2.9105, - 0.1432, 0.2718, 0.4241, 0.5564, 0.6939, 0.9011, 1.1582, 1.3948, - 1.6181, 1.8024, 1.9814, 2.1740, 2.3459, 2.5456, 2.7491, 2.9307, - 0.2294, 0.3857, 0.5590, 0.7434, 0.9189, 1.0941, 1.2740, 1.4456, - 1.6178, 1.7994, 1.9689, 2.1644, 2.3525, 2.5385, 2.7468, 2.9405, - 0.1667, 0.3109, 0.4612, 0.6032, 0.7375, 0.8866, 1.0840, 1.3053, - 1.4982, 1.7044, 1.9146, 2.1117, 2.2942, 2.4983, 2.7084, 2.9132, - 0.1810, 0.3205, 0.4696, 0.6231, 0.7641, 0.9959, 1.2427, 1.4361, - 1.5889, 1.7544, 1.9083, 2.0733, 2.2457, 2.4461, 2.6793, 2.9098, - 0.1164, 0.3753, 0.6068, 0.7503, 1.0100, 1.2131, 1.3793, 1.5302, - 1.6300, 1.7950, 1.9057, 2.1031, 2.3830, 2.5745, 2.6949, 2.8779, - 0.1571, 0.4378, 0.6735, 0.8312, 0.8944, 0.9818, 1.1622, 1.4094, - 1.6423, 1.8066, 1.9258, 2.1838, 2.4363, 2.6279, 2.7358, 2.8790, - 0.1398, 0.2686, 0.4248, 0.6156, 0.7870, 1.0035, 1.2012, 1.3689, - 1.5363, 1.7398, 1.9604, 2.1619, 2.3345, 2.5097, 2.7271, 2.9368, - 0.1913, 0.3338, 0.4987, 0.6446, 0.7852, 1.0163, 1.1886, 1.3610, - 1.5379, 1.7230, 1.8880, 2.0862, 2.2960, 2.4928, 2.7122, 2.9151, - 0.0908, 0.1752, 0.2899, 0.5365, 0.7761, 1.0100, 1.2124, 1.4060, - 1.6019, 1.8010, 1.9774, 2.1905, 2.3733, 2.5623, 2.7660, 2.9565, - 0.1773, 0.3179, 0.4925, 0.6864, 0.8452, 0.9897, 1.1860, 1.3722, - 1.5515, 1.7658, 1.9802, 2.1819, 2.3620, 2.5442, 2.7250, 2.9220, - 0.1286, 0.2341, 0.3689, 0.5364, 0.7176, 0.9350, 1.1083, 1.2943, - 1.4974, 1.7059, 1.9047, 2.1145, 2.3242, 2.5361, 2.7453, 2.9329, - 0.2273, 0.3834, 0.5565, 0.7192, 0.8431, 0.9962, 1.1763, 1.3571, - 1.5774, 1.7419, 1.9202, 2.1131, 2.2919, 2.4898, 2.6895, 2.9180, - 0.1775, 0.3058, 0.4274, 0.6023, 0.8151, 1.0734, 1.3211, 1.5178, - 1.6706, 1.8154, 1.9686, 2.1537, 2.3461, 2.5276, 2.7181, 2.9121, - 0.1653, 0.4304, 0.6361, 0.7824, 0.9183, 1.0452, 1.2071, 1.4077, - 1.6206, 1.8299, 2.0089, 2.1948, 2.3900, 2.5982, 2.7844, 2.9487, - 0.1492, 0.2609, 0.3820, 0.5485, 0.7243, 0.9319, 1.1538, 1.3579, - 1.5266, 1.7002, 1.8873, 2.1016, 2.3175, 2.5221, 2.7241, 2.9243, - 0.2074, 0.3781, 0.5209, 0.6869, 0.8577, 0.9875, 1.1849, 1.3568, - 1.4907, 1.7335, 1.8902, 2.1224, 2.3099, 2.4918, 2.7023, 2.8765, - 0.1359, 0.2254, 0.3286, 0.4432, 0.6586, 0.8964, 1.1125, 1.3523, - 1.5626, 1.7579, 1.9846, 2.1905, 2.3548, 2.5542, 2.7663, 2.9346, - 0.1430, 0.2966, 0.4685, 0.6493, 0.8315, 1.0304, 1.2220, 1.4082, - 1.5995, 1.7888, 1.9774, 2.1737, 2.3607, 2.5577, 2.7558, 2.9405, - 0.1477, 0.2694, 0.4056, 0.5626, 0.7051, 0.8647, 1.0491, 1.2488, - 1.4814, 1.7072, 1.9150, 2.1147, 2.3038, 2.5144, 2.7184, 2.9202, - 0.1690, 0.3033, 0.4580, 0.6686, 0.8536, 1.0293, 1.2124, 1.3998, - 1.5718, 1.7607, 1.9580, 2.1245, 2.2971, 2.4762, 2.6896, 2.9177, - 0.1092, 0.2779, 0.4853, 0.6880, 0.9011, 1.0953, 1.2752, 1.4618, - 1.6623, 1.8484, 2.0264, 2.2152, 2.4017, 2.5835, 2.7671, 2.9436, - 0.1497, 0.3637, 0.6014, 0.8032, 0.9963, 1.1835, 1.3741, 1.5698, - 1.7382, 1.9094, 2.0710, 2.2392, 2.4082, 2.5926, 2.7762, 2.9536, - 0.1434, 0.2492, 0.3966, 0.5934, 0.8033, 1.0657, 1.2796, 1.4276, - 1.5745, 1.7833, 1.9288, 2.1247, 2.3543, 2.5412, 2.7049, 2.8872, - 0.1612, 0.2926, 0.4574, 0.6387, 0.8265, 1.0180, 1.1808, 1.3526, - 1.5564, 1.7536, 1.9187, 2.1192, 2.3149, 2.5006, 2.7101, 2.9217, - 0.0828, 0.1863, 0.3235, 0.5050, 0.7250, 0.9867, 1.2093, 1.3941, - 1.5980, 1.7932, 1.9809, 2.1894, 2.3918, 2.5773, 2.7540, 2.9329, - 0.2001, 0.3655, 0.5290, 0.6761, 0.8027, 0.9972, 1.2090, 1.4255, - 1.6085, 1.7825, 1.9804, 2.1681, 2.3457, 2.5325, 2.7319, 2.9196, - 0.1505, 0.2767, 0.4254, 0.6054, 0.7821, 0.9567, 1.1294, 1.3080, - 1.4984, 1.6954, 1.8666, 2.0736, 2.2875, 2.4969, 2.7072, 2.9163, - 0.1589, 0.4151, 0.5749, 0.6651, 0.8061, 1.0470, 1.2616, 1.3690, - 1.4985, 1.7808, 1.9825, 2.1068, 2.2751, 2.5448, 2.7133, 2.8689, - 0.0916, 0.1846, 0.3788, 0.6329, 0.8774, 1.0687, 1.2653, 1.4561, - 1.6573, 1.8449, 2.0402, 2.2254, 2.3968, 2.5861, 2.7792, 2.9508, - 0.2282, 0.4159, 0.5834, 0.6899, 0.8108, 1.0321, 1.2795, 1.5262, - 1.6936, 1.8469, 2.0922, 2.2607, 2.3795, 2.5301, 2.7386, 2.9530, - 0.1651, 0.3004, 0.4555, 0.6179, 0.7891, 0.9584, 1.1372, 1.3707, - 1.5951, 1.7880, 1.9434, 2.1465, 2.3311, 2.5081, 2.6977, 2.8970, - 0.1279, 0.3828, 0.6330, 0.8323, 0.9652, 1.1175, 1.2319, 1.3511, - 1.5115, 1.6392, 1.7835, 1.9558, 2.2008, 2.4635, 2.6910, 2.9058, - 0.1193, 0.2185, 0.3521, 0.5311, 0.7378, 0.9239, 1.1105, 1.3217, - 1.5362, 1.7504, 1.9536, 2.1627, 2.3560, 2.5506, 2.7548, 2.9453, - 0.1806, 0.3432, 0.4981, 0.6948, 0.8928, 1.0527, 1.2467, 1.4140, - 1.6326, 1.7950, 1.9935, 2.1969, 2.3512, 2.5682, 2.7445, 2.9277, - 0.1846, 0.3112, 0.4568, 0.5891, 0.7317, 0.8493, 1.0204, 1.2022, - 1.3688, 1.6020, 1.8428, 2.0710, 2.2725, 2.4879, 2.7057, 2.9160, - 0.0880, 0.2514, 0.5332, 0.7272, 0.8906, 1.1354, 1.3199, 1.4941, - 1.6010, 1.7151, 1.8712, 2.0643, 2.2755, 2.5375, 2.7054, 2.8891, - 0.1382, 0.2833, 0.4658, 0.6897, 0.9071, 1.0716, 1.2469, 1.4143, - 1.5910, 1.7947, 1.9805, 2.1581, 2.3338, 2.5215, 2.7292, 2.9211, - 0.1061, 0.3494, 0.6327, 0.8570, 0.9748, 1.0560, 1.1529, 1.3250, - 1.6032, 1.8340, 1.9711, 2.1157, 2.3011, 2.5464, 2.8078, 2.9803, - 0.1603, 0.2839, 0.4307, 0.5980, 0.7980, 1.0399, 1.1971, 1.3524, - 1.5715, 1.7838, 1.9468, 2.1498, 2.3627, 2.5514, 2.7327, 2.9148, - 0.1691, 0.3117, 0.4796, 0.6895, 0.8732, 1.0164, 1.1916, 1.3707, - 1.5384, 1.7202, 1.8857, 2.0672, 2.2487, 2.4593, 2.6789, 2.8940, - 0.0965, 0.1702, 0.3191, 0.5721, 0.8100, 1.0241, 1.2272, 1.4196, - 1.6093, 1.8057, 1.9884, 2.2037, 2.3925, 2.5805, 2.7578, 2.9366, - 0.1950, 0.3519, 0.5272, 0.6973, 0.8732, 1.0656, 1.2112, 1.3959, - 1.6116, 1.7821, 1.9445, 2.1592, 2.3348, 2.5142, 2.7440, 2.9297, - 0.1388, 0.2557, 0.4120, 0.5727, 0.7354, 0.9196, 1.0985, 1.2805, - 1.4643, 1.6535, 1.8340, 2.0546, 2.2758, 2.4778, 2.6921, 2.9122, - 0.1823, 0.3336, 0.4957, 0.6771, 0.8563, 1.0137, 1.2299, 1.3849, - 1.5718, 1.7667, 1.9193, 2.1326, 2.3135, 2.5268, 2.7133, 2.8998, - 0.0790, 0.1901, 0.4083, 0.6456, 0.8463, 1.0285, 1.2297, 1.4181, - 1.6159, 1.8056, 1.9971, 2.1912, 2.3816, 2.5746, 2.7692, 2.9497, - 0.0049, 0.0116, 0.0045, 0.0039, -0.0010, -0.0122, -0.0205, -0.0034, --0.0140, -0.0041, 0.0191, -0.0322, 0.0002, -0.0124, -0.0269, 0.0059, - 0.0586, 0.0339, -0.0389, -0.0319, -0.0079, -0.0205, -0.0363, -0.0211, - 0.0241, 0.0595, 0.0469, 0.0283, 0.0176, -0.0183, -0.0173, -0.0004, - 0.0024, 0.0145, 0.0534, 0.0197, -0.0065, -0.0067, 0.0133, 0.0358, --0.0104, -0.0386, -0.0109, -0.0078, 0.0275, 0.0565, 0.0251, -0.0027, --0.0053, 0.0171, 0.0088, 0.0495, 0.0141, 0.0039, -0.0445, -0.0426, --0.0184, -0.0280, -0.0223, 0.0039, -0.0171, -0.0606, -0.0786, -0.0430, - 0.0544, 0.0595, 0.0320, -0.0012, 0.0108, 0.0185, 0.0066, 0.0408, - 0.0552, -0.0073, -0.0247, -0.0480, -0.0288, 0.0186, 0.0212, -0.0013, - 0.0403, 0.0598, 0.0690, 0.0516, -0.0298, -0.0177, 0.0278, 0.0168, --0.0106, 0.0251, 0.0386, 0.0331, -0.0052, 0.0133, 0.0291, -0.0158, --0.0329, -0.0367, 0.0287, 0.0462, -0.0176, 0.0049, 0.0242, -0.0034, - 0.0135, 0.0086, -0.0149, 0.0241, 0.0504, 0.0246, -0.0273, -0.0369, --0.0108, -0.0449, -0.0625, -0.0414, -0.0292, -0.0571, -0.0440, -0.0088, - 0.0098, 0.0009, -0.0004, 0.0007, -0.0314, -0.0208, -0.0138, -0.0277, --0.0044, 0.0522, 0.0315, -0.0270, -0.0277, -0.0256, -0.0103, -0.0201, --0.0287, -0.0279, -0.0182, 0.0472, 0.0613, 0.0450, 0.0413, 0.0333, - 0.0444, 0.0223, 0.0061, 0.0316, 0.0321, 0.0501, 0.0460, 0.0250, - 0.0227, 0.0235, 0.0099, 0.0185, -0.0347, -0.0684, -0.0189, 0.0242, --0.0190, -0.0273, -0.0012, -0.0253, 0.0293, -0.0231, -0.0219, -0.0010, - 0.0153, 0.0128, -0.0166, -0.0435, -0.0417, -0.0121, -0.0351, -0.0390, - 0.0077, -0.0278, -0.0355, 0.0092, -0.0063, 0.0005, 0.0216, 0.0461, - 0.0538, 0.0451, 0.0298, -0.0130, 0.0058, 0.0206, 0.0471, 0.0499, - 0.0280, 0.0086, -0.0007, -0.0317, 0.0259, 0.0176, 0.0043, 0.0212, - 0.0138, 0.0106, 0.0220, -0.0025, 0.0050, 0.0122, -0.0051, -0.0086, --0.0472, -0.0005, 0.0193, 0.0032, 0.0246, 0.0222, 0.0090, -0.0320, --0.0713, -0.0526, -0.0151, -0.0440, -0.0648, -0.0466, -0.0092, 0.0115, --0.0129, 0.0053, -0.0344, -0.0385, 0.0392, 0.0599, 0.0414, 0.0165, --0.0098, -0.0320, -0.0261, -0.0055, -0.0139, -0.0110, 0.0084, 0.0172, --0.0492, -0.0537, -0.0320, -0.0036, 0.0265, 0.0385, 0.0064, -0.0280, --0.0230, 0.0134, 0.0241, 0.0106, 0.0387, 0.0105, 0.0068, 0.0260, - 0.4940, 0.4911, 0.4849, 0.4820, 0.4837, 0.4839, 0.4824, 0.4799, - 0.4812, 0.4782, 0.4788, 0.4711, 0.4706, 0.4671, 0.4601, 0.4578, - 0.2954, 0.2121, 0.1859, 0.1958, 0.1474, 0.1086, 0.1351, 0.1362, - 0.1486, 0.1342, 0.1215, 0.1423, 0.1634, 0.1588, 0.1539, 0.1857 -}, - -.lsp16 = { - 0.1813, 0.3911, 0.6301, 0.8012, 1.0057, 1.2041, 1.4271, 1.6943, - 1.9402, 2.1733, 2.3521, 2.4989, 2.5839, 2.6846, 2.7634, 2.8950, - 0.1311, 0.3183, 0.4659, 0.5601, 0.6658, 0.7828, 1.0065, 1.2717, - 1.5185, 1.7339, 1.9530, 2.2189, 2.3739, 2.4991, 2.6984, 2.9256, - 0.1627, 0.4519, 0.6323, 0.7012, 0.7848, 0.9801, 1.1810, 1.3222, - 1.5413, 1.8129, 1.9338, 2.0809, 2.3180, 2.5189, 2.7066, 2.9514, - 0.1475, 0.2447, 0.4240, 0.5669, 0.7872, 0.9838, 1.1823, 1.3814, - 1.5358, 1.6820, 1.8794, 2.1419, 2.4132, 2.6112, 2.7911, 2.9511, - 0.1224, 0.2876, 0.5013, 0.6985, 0.8902, 1.0901, 1.2835, 1.4768, - 1.6596, 1.8538, 2.0467, 2.2304, 2.4124, 2.5942, 2.7729, 2.9531, - 0.1741, 0.3034, 0.4677, 0.5879, 0.7258, 0.9648, 1.1417, 1.3220, - 1.5081, 1.7151, 1.9212, 2.1286, 2.3208, 2.4938, 2.6765, 2.8891, - 0.1657, 0.3174, 0.4907, 0.6559, 0.8295, 1.0254, 1.2071, 1.3880, - 1.5737, 1.7845, 1.9027, 2.1139, 2.3323, 2.5157, 2.7323, 2.9015, - 0.1592, 0.2758, 0.4417, 0.6315, 0.8257, 0.9873, 1.1277, 1.2830, - 1.4337, 1.6315, 1.8899, 2.1356, 2.3572, 2.5632, 2.7468, 2.9420, - 0.1524, 0.4325, 0.5931, 0.7036, 0.7696, 0.8923, 1.1739, 1.4773, - 1.6609, 1.7911, 1.9666, 2.1972, 2.3754, 2.5045, 2.6613, 2.8882, - 0.2130, 0.3013, 0.3721, 0.4257, 0.5079, 0.7015, 0.9815, 1.2554, - 1.4648, 1.6966, 1.9138, 2.1075, 2.3318, 2.5292, 2.7453, 2.9347, - 0.1142, 0.3748, 0.6205, 0.7642, 0.8121, 0.9022, 0.9843, 1.1558, - 1.4467, 1.7422, 1.9574, 2.1302, 2.3812, 2.5898, 2.7720, 2.9583, - 0.1255, 0.2339, 0.3570, 0.5323, 0.7458, 1.0003, 1.1729, 1.3567, - 1.5217, 1.6977, 1.8924, 2.0942, 2.3145, 2.5408, 2.7553, 2.9337, - 0.1316, 0.2289, 0.4327, 0.6663, 0.8509, 0.9994, 1.1697, 1.3804, - 1.5609, 1.6903, 1.8572, 2.1019, 2.3687, 2.5789, 2.7715, 2.9472, - 0.1502, 0.2546, 0.3883, 0.5333, 0.6976, 0.9163, 1.1071, 1.3364, - 1.5420, 1.7525, 1.8948, 2.0839, 2.2819, 2.4651, 2.6875, 2.8987, - 0.1593, 0.3014, 0.4573, 0.6354, 0.8157, 0.9805, 1.1783, 1.3747, - 1.5678, 1.7326, 1.9286, 2.1340, 2.3253, 2.5280, 2.7180, 2.9298, - 0.1811, 0.3167, 0.4655, 0.6507, 0.8198, 1.0075, 1.1892, 1.3743, - 1.5227, 1.7090, 1.8849, 2.0743, 2.2750, 2.4830, 2.6896, 2.8953, - 0.1846, 0.3577, 0.5315, 0.7290, 0.9176, 1.1016, 1.2654, 1.4525, - 1.6315, 1.8268, 2.0238, 2.1934, 2.3868, 2.5753, 2.7682, 2.9469, - 0.0876, 0.1439, 0.2048, 0.3654, 0.6281, 0.8853, 1.0907, 1.2992, - 1.5227, 1.7373, 1.9395, 2.1419, 2.3488, 2.5486, 2.7466, 2.9348, - 0.1391, 0.4170, 0.6561, 0.7953, 0.8734, 0.9986, 1.1870, 1.4520, - 1.6042, 1.7910, 2.0135, 2.1870, 2.3358, 2.5066, 2.7409, 2.9955, - 0.0804, 0.1355, 0.2599, 0.4998, 0.7408, 0.9474, 1.1276, 1.3428, - 1.5556, 1.7712, 1.9699, 2.1535, 2.3605, 2.5548, 2.7489, 2.9325, - 0.1304, 0.3087, 0.4979, 0.6584, 0.8414, 1.0329, 1.2244, 1.4189, - 1.6118, 1.8200, 1.9985, 2.1893, 2.3915, 2.5794, 2.7647, 2.9344, - 0.1895, 0.2849, 0.3705, 0.4126, 0.6265, 0.9207, 1.1774, 1.3762, - 1.5757, 1.7728, 1.9568, 2.1662, 2.3615, 2.5575, 2.7561, 2.9416, - 0.1800, 0.3078, 0.4805, 0.6796, 0.8503, 1.0046, 1.1703, 1.3269, - 1.4862, 1.6502, 1.8454, 2.0873, 2.3175, 2.5356, 2.7516, 2.9469, - 0.1950, 0.3233, 0.4568, 0.5940, 0.7589, 0.9978, 1.1701, 1.3383, - 1.5017, 1.6565, 1.8243, 2.0605, 2.2938, 2.5147, 2.7419, 2.9396, - 0.2531, 0.4391, 0.5790, 0.7170, 0.8998, 1.1430, 1.3577, 1.5326, - 1.6328, 1.7627, 1.9726, 2.1762, 2.3563, 2.5478, 2.7385, 2.9067, - 0.1805, 0.2788, 0.3591, 0.3881, 0.5441, 0.8055, 1.0766, 1.3165, - 1.5316, 1.7508, 1.9477, 2.1374, 2.3438, 2.5484, 2.7501, 2.9410, - 0.2044, 0.3671, 0.5396, 0.7042, 0.8582, 0.9831, 1.1261, 1.3194, - 1.4769, 1.6979, 1.8717, 2.0463, 2.2620, 2.4739, 2.7054, 2.9208, - 0.1048, 0.2175, 0.4206, 0.5923, 0.7483, 0.9400, 1.1356, 1.3799, - 1.5958, 1.7320, 1.8984, 2.1296, 2.3594, 2.5492, 2.7387, 2.9305, - 0.0842, 0.1729, 0.3951, 0.6447, 0.8688, 1.0605, 1.2472, 1.4330, - 1.6232, 1.8144, 2.0216, 2.1915, 2.3878, 2.5763, 2.7685, 2.9464, - 0.1461, 0.2593, 0.4105, 0.5677, 0.7328, 0.8919, 1.0484, 1.2302, - 1.4386, 1.6635, 1.8873, 2.1024, 2.3116, 2.5268, 2.7273, 2.9269, - 0.1503, 0.3108, 0.4756, 0.6731, 0.8600, 1.0233, 1.2115, 1.3971, - 1.5915, 1.7892, 1.9517, 2.1603, 2.3487, 2.5460, 2.7308, 2.8998, - 0.2163, 0.3669, 0.5125, 0.6709, 0.8143, 0.9930, 1.2095, 1.4205, - 1.6176, 1.7112, 1.8398, 2.0896, 2.3513, 2.5290, 2.6667, 2.8960, - 0.2133, 0.4382, 0.6287, 0.8702, 1.1088, 1.3749, 1.6062, 1.7446, - 1.8333, 1.9122, 1.9614, 2.0669, 2.1789, 2.3449, 2.6038, 2.8849, - 0.1598, 0.2719, 0.3877, 0.4815, 0.5926, 0.7795, 1.0449, 1.3045, - 1.5210, 1.7391, 1.9462, 2.1397, 2.3553, 2.5458, 2.7540, 2.9392, - 0.2918, 0.5607, 0.6801, 0.7404, 0.8285, 0.9431, 1.1579, 1.4080, - 1.6332, 1.8472, 1.9738, 2.0771, 2.2890, 2.5178, 2.7445, 2.9830, - 0.1664, 0.2842, 0.3965, 0.5463, 0.8162, 1.0346, 1.1849, 1.3446, - 1.5122, 1.7563, 1.9960, 2.2002, 2.3796, 2.5689, 2.7712, 2.9550, - 0.0911, 0.2397, 0.5052, 0.7868, 1.0299, 1.1311, 1.2244, 1.3333, - 1.4395, 1.6790, 1.9369, 2.1717, 2.3689, 2.5538, 2.7340, 2.9326, - 0.1647, 0.2931, 0.3836, 0.4978, 0.6255, 0.9243, 1.1339, 1.3001, - 1.5269, 1.8010, 1.9715, 2.1419, 2.3784, 2.5503, 2.6719, 2.8745, - 0.2440, 0.3802, 0.4756, 0.6613, 0.8627, 1.0292, 1.2291, 1.4060, - 1.5198, 1.7354, 1.9044, 2.1010, 2.3147, 2.4996, 2.7171, 2.9041, - 0.1590, 0.2876, 0.4572, 0.5996, 0.7713, 0.9490, 1.1205, 1.2815, - 1.4516, 1.6385, 1.8179, 2.0457, 2.2759, 2.4785, 2.6861, 2.9080, - 0.2297, 0.4309, 0.5712, 0.6717, 0.8138, 1.0463, 1.2492, 1.4560, - 1.6796, 1.8458, 1.9642, 2.1452, 2.3636, 2.5395, 2.7456, 2.9495, - 0.2975, 0.4678, 0.4996, 0.5809, 0.6279, 0.6884, 0.8606, 1.1386, - 1.4412, 1.6876, 1.8760, 2.0932, 2.3178, 2.5166, 2.7345, 2.9280, - 0.1278, 0.3737, 0.6004, 0.7069, 0.8147, 1.0180, 1.2581, 1.3812, - 1.4855, 1.7268, 1.9970, 2.1258, 2.2936, 2.5702, 2.7563, 2.8983, - 0.1314, 0.2508, 0.3999, 0.5680, 0.7424, 0.9367, 1.1286, 1.3175, - 1.5336, 1.7404, 1.9317, 2.1404, 2.3514, 2.5562, 2.7510, 2.9402, - 0.1043, 0.2367, 0.4293, 0.6376, 0.8160, 0.9836, 1.1779, 1.3850, - 1.5835, 1.7875, 1.9765, 2.1593, 2.3654, 2.5577, 2.7465, 2.9398, - 0.1529, 0.2515, 0.3454, 0.4374, 0.7011, 0.9015, 1.0744, 1.3532, - 1.5699, 1.7545, 2.0021, 2.1259, 2.2278, 2.4546, 2.7264, 2.9425, - 0.1429, 0.2808, 0.4395, 0.6334, 0.8069, 0.9705, 1.1520, 1.3250, - 1.5109, 1.7285, 1.9356, 2.1469, 2.3479, 2.5554, 2.7512, 2.9348, - 0.1625, 0.3022, 0.4756, 0.6315, 0.8032, 0.9924, 1.1596, 1.3204, - 1.4994, 1.6929, 1.8955, 2.1090, 2.3025, 2.5018, 2.6908, 2.8980, - 0.1692, 0.3427, 0.5228, 0.7756, 0.9688, 1.0950, 1.3056, 1.4360, - 1.5675, 1.8049, 1.9376, 2.1151, 2.3407, 2.5012, 2.7192, 2.9258, - 0.0474, 0.1251, 0.1939, 0.3841, 0.6501, 0.9231, 1.1153, 1.3240, - 1.5478, 1.7599, 1.9651, 2.1510, 2.3645, 2.5552, 2.7542, 2.9393, - 0.2196, 0.4656, 0.7492, 0.9922, 1.1678, 1.2489, 1.3112, 1.3657, - 1.4223, 1.5302, 1.7212, 1.9996, 2.2523, 2.4844, 2.7036, 2.9145, - 0.1128, 0.2368, 0.3704, 0.5476, 0.7723, 0.9968, 1.1930, 1.3992, - 1.6013, 1.7957, 1.9888, 2.1857, 2.3825, 2.5705, 2.7616, 2.9434, - 0.1341, 0.2768, 0.4510, 0.6359, 0.8332, 1.0335, 1.2004, 1.3952, - 1.5762, 1.7681, 1.9815, 2.1735, 2.3657, 2.5552, 2.7514, 2.9498, - 0.1247, 0.2559, 0.3516, 0.4726, 0.6861, 0.9483, 1.1852, 1.3858, - 1.5851, 1.7815, 1.9778, 2.1737, 2.3729, 2.5664, 2.7620, 2.9429, - 0.1988, 0.3320, 0.4777, 0.6737, 0.8425, 1.0265, 1.1694, 1.3655, - 1.5463, 1.7135, 1.9385, 2.1650, 2.3529, 2.5367, 2.7545, 2.9585, - 0.1376, 0.2620, 0.4273, 0.6169, 0.7755, 0.9441, 1.1169, 1.3157, - 1.5179, 1.7020, 1.8931, 2.1059, 2.3112, 2.5136, 2.7169, 2.9198, - 0.2112, 0.4385, 0.6091, 0.7618, 0.9553, 1.1543, 1.3445, 1.5396, - 1.7153, 1.9192, 2.1263, 2.3593, 2.5958, 2.8171, 2.9394, 3.0409, - 0.1347, 0.2099, 0.2646, 0.3453, 0.5266, 0.7869, 1.0513, 1.2795, - 1.4880, 1.7181, 1.9294, 2.1332, 2.3362, 2.5442, 2.7433, 2.9362, - 0.3141, 0.5935, 0.7517, 0.8313, 0.8568, 0.9570, 1.0250, 1.1275, - 1.3422, 1.6303, 1.8577, 2.0705, 2.2957, 2.5095, 2.7244, 2.9262, - 0.0962, 0.2116, 0.3961, 0.5641, 0.7122, 0.8883, 1.1023, 1.3481, - 1.5623, 1.7554, 1.9618, 2.1675, 2.3706, 2.5556, 2.7430, 2.9337, - 0.0898, 0.1510, 0.3060, 0.5820, 0.8221, 1.0388, 1.2261, 1.4289, - 1.6054, 1.8103, 1.9941, 2.1844, 2.3742, 2.5711, 2.7632, 2.9474, - 0.1326, 0.2316, 0.3761, 0.5177, 0.6782, 0.8761, 1.0952, 1.3175, - 1.5078, 1.7034, 1.9051, 2.1245, 2.3424, 2.5484, 2.7444, 2.9389, - 0.1740, 0.3293, 0.5174, 0.6824, 0.8394, 1.0372, 1.2046, 1.3723, - 1.5656, 1.7444, 1.9442, 2.1386, 2.3139, 2.4960, 2.7071, 2.9297, - 0.2304, 0.3775, 0.4865, 0.6182, 0.7842, 0.9208, 1.1151, 1.2843, - 1.4641, 1.6988, 1.9209, 2.1260, 2.3099, 2.5229, 2.7414, 2.9276, - 0.0094, 0.0261, -0.0037, 0.0041, -0.0092, -0.0044, -0.0232, -0.0073, --0.0047, -0.0021, 0.0250, -0.0580, -0.0140, -0.0342, -0.0586, 0.0020, - 0.0449, 0.0155, -0.0523, -0.0279, 0.0299, -0.0183, -0.0736, -0.0639, --0.0017, 0.0336, 0.0209, 0.0046, 0.0077, -0.0148, -0.0114, -0.0120, - 0.0115, -0.0050, 0.0445, 0.0048, 0.0188, -0.0137, -0.0080, 0.0239, --0.0184, -0.0524, -0.0195, -0.0126, 0.0284, 0.0632, 0.0141, -0.0093, --0.0096, 0.0196, 0.0230, 0.0379, 0.0308, 0.0237, -0.0224, -0.0600, --0.0755, -0.1074, -0.0988, -0.0606, -0.1038, -0.1552, -0.1480, -0.0672, - 0.0504, 0.0676, 0.0336, -0.0042, 0.0729, 0.1013, 0.0868, 0.0846, - 0.0954, 0.0515, -0.0066, -0.0851, -0.0485, 0.0294, 0.0395, 0.0087, - 0.0078, 0.0446, 0.0881, 0.0672, -0.0384, -0.0025, 0.0415, 0.0353, - 0.0080, 0.0052, 0.0190, 0.0182, 0.0069, 0.0168, 0.0374, 0.0037, --0.0292, -0.0429, 0.0302, 0.0681, -0.0233, -0.0238, -0.0003, -0.0043, - 0.0054, -0.0029, -0.0149, 0.0642, 0.0622, 0.0341, -0.0232, -0.0461, --0.0082, -0.0469, -0.0618, -0.0326, -0.0452, -0.0649, -0.0597, -0.0398, --0.0318, -0.0116, 0.0011, 0.0009, -0.0384, -0.0384, -0.0156, -0.0260, --0.0007, 0.0473, 0.0111, -0.0358, -0.0484, -0.0204, -0.0029, -0.0090, --0.0285, -0.0495, -0.0376, 0.0917, 0.1192, 0.1026, 0.0745, 0.0397, - 0.0463, 0.0253, 0.0025, 0.0465, 0.0100, 0.0488, 0.0416, 0.0223, - 0.0263, 0.0072, -0.0053, 0.0595, 0.0060, -0.0518, -0.0316, -0.0043, --0.0133, -0.0233, -0.0075, -0.0251, 0.0277, -0.0067, -0.0136, -0.0004, - 0.0235, 0.0112, -0.0182, -0.0324, -0.0210, -0.0035, -0.0395, -0.0384, - 0.0005, -0.0150, -0.0356, 0.0127, -0.0033, -0.0034, 0.0205, 0.0747, - 0.1138, 0.1015, 0.0995, -0.0161, -0.0045, 0.0129, 0.0472, 0.0575, - 0.0222, 0.0091, 0.0037, -0.0471, 0.0371, 0.0132, 0.0208, 0.0247, - 0.0117, 0.0164, 0.0225, 0.0124, -0.0023, 0.0088, -0.0046, 0.0047, --0.0393, 0.0018, 0.0148, 0.0020, 0.0044, 0.0165, 0.0229, -0.0208, --0.0477, -0.0310, -0.0164, -0.0390, -0.0764, -0.0525, -0.0094, 0.0075, --0.0102, -0.0045, -0.0504, -0.0709, 0.0822, 0.0710, 0.0426, 0.0014, --0.0371, -0.0400, -0.0157, -0.0155, -0.0173, -0.0138, -0.0015, 0.0134, --0.0418, -0.0682, -0.0256, 0.0050, 0.0360, 0.0354, 0.0074, -0.0396, --0.0235, 0.0284, 0.0494, 0.0153, 0.0448, 0.0025, -0.0061, 0.0252, - 0.1000, 0.2260, 0.2158, 0.2116, 0.2198, 0.2055, 0.2110, 0.1873, - 0.1907, 0.2071, 0.2164, 0.2009, 0.2059, 0.2124, 0.2141, 0.2093, - 0.0875, 0.0981, 0.1177, 0.1071, 0.1033, 0.1248, 0.1048, 0.1238, - 0.1166, 0.1008, 0.1062, 0.0992, 0.0994, 0.1067, 0.0999, 0.1187, - 0.0750, 0.0794, 0.0828, 0.0854, 0.0859, 0.0801, 0.0891, 0.0933, - 0.0969, 0.0920, 0.0915, 0.0862, 0.0868, 0.0891, 0.0842, 0.0824, - 0.0625, 0.0930, 0.0815, 0.0853, 0.0898, 0.0828, 0.0822, 0.0910, - 0.0873, 0.0906, 0.0856, 0.0840, 0.0774, 0.0785, 0.0684, 0.0711, - 0.3319, 0.4219, 0.4588, 0.4090, 0.4092, 0.4014, 0.3548, 0.3353, - 0.3708, 0.3352, 0.3720, 0.3538, 0.4084, 0.4289, 0.4060, 0.4210, - 0.0588, 0.0209, -0.0082, -0.0115, -0.0343, -0.0621, -0.0541, -0.0346, --0.0346, -0.0366, -0.0220, -0.0265, -0.0102, 0.0374, 0.0306, 0.0404, - 0.0306, 0.0090, -0.0054, 0.0333, 0.0047, 0.0238, 0.0141, 0.0165, - 0.0306, 0.0420, 0.0159, 0.0124, 0.0414, 0.0158, -0.0237, 0.0141, - 0.0765, 0.0057, -0.0260, -0.0426, -0.0395, -0.0126, -0.0579, -0.0417 -}, - -.lsp22_1 = { - 0.0664, 0.1875, 0.4300, 0.6730, 0.8793, 1.0640, 1.2563, 1.4433, - 1.6394, 1.8176, 2.0029, 2.1921, 2.3796, 2.5671, 2.7595, 2.9536, - 0.2128, 0.4052, 0.5311, 0.6404, 0.7875, 0.8775, 1.0974, 1.3261, - 1.5563, 1.6790, 1.8339, 2.1195, 2.3226, 2.4609, 2.6440, 2.8947, - 0.2024, 0.3362, 0.4834, 0.6784, 0.9088, 1.0850, 1.2188, 1.4054, - 1.6102, 1.7767, 1.9679, 2.1436, 2.3445, 2.5467, 2.7429, 2.9320, - 0.1181, 0.2279, 0.4413, 0.6114, 0.7710, 0.9427, 1.1142, 1.2707, - 1.4892, 1.7416, 1.9526, 2.1466, 2.3629, 2.5445, 2.7293, 2.9205, - 0.1155, 0.2720, 0.4886, 0.6812, 0.8594, 1.0422, 1.2315, 1.4116, - 1.6137, 1.8020, 1.9758, 2.1743, 2.3602, 2.5568, 2.7472, 2.9374, - 0.1110, 0.3312, 0.4735, 0.5612, 0.7129, 0.8146, 1.0233, 1.3155, - 1.5765, 1.7746, 1.9574, 2.1416, 2.3220, 2.5384, 2.7334, 2.9318, - 0.1656, 0.3350, 0.4215, 0.5609, 0.6759, 0.8503, 1.1405, 1.4094, - 1.6057, 1.6860, 1.7639, 2.0031, 2.2680, 2.5076, 2.7263, 2.9368, - 0.1466, 0.3638, 0.4587, 0.5674, 0.7381, 0.8669, 0.9619, 1.1658, - 1.4667, 1.7440, 1.9335, 2.1018, 2.3022, 2.5281, 2.7359, 2.9261, - 0.1061, 0.2566, 0.4739, 0.6751, 0.8711, 1.0704, 1.2720, 1.4655, - 1.6605, 1.8494, 2.0290, 2.2197, 2.4008, 2.5912, 2.7772, 2.9513, - 0.1116, 0.2364, 0.3971, 0.6316, 0.8583, 1.0335, 1.1686, 1.3302, - 1.5612, 1.7877, 1.9829, 2.2052, 2.3596, 2.5460, 2.7341, 2.9290, - 0.2661, 0.4186, 0.5126, 0.6477, 0.8818, 1.1045, 1.2852, 1.4128, - 1.5851, 1.7593, 1.9399, 2.1757, 2.3684, 2.5136, 2.6927, 2.9064, - 0.1495, 0.2749, 0.4391, 0.6304, 0.8239, 1.0181, 1.1995, 1.3759, - 1.5669, 1.7722, 1.9671, 2.1635, 2.3586, 2.5528, 2.7445, 2.9311, - 0.0912, 0.1759, 0.3066, 0.5660, 0.8005, 0.9568, 1.1832, 1.4504, - 1.6259, 1.7948, 2.0113, 2.2002, 2.3654, 2.5583, 2.7929, 2.9735, - 0.1353, 0.2747, 0.4078, 0.5977, 0.7658, 0.9124, 1.1081, 1.3630, - 1.5875, 1.7847, 1.9323, 2.1181, 2.3321, 2.5046, 2.7183, 2.9225, - 0.1938, 0.4063, 0.4982, 0.6002, 0.7702, 0.9071, 1.1631, 1.3885, - 1.6043, 1.8118, 1.9306, 2.0893, 2.2724, 2.4609, 2.6283, 2.8802, - 0.1857, 0.3351, 0.4381, 0.6101, 0.7561, 0.8555, 1.0384, 1.3171, - 1.5667, 1.6904, 1.7552, 1.9689, 2.2597, 2.5260, 2.7272, 2.9337, - 0.1037, 0.2159, 0.4188, 0.6174, 0.8035, 1.0285, 1.2256, 1.4230, - 1.6400, 1.8322, 2.0144, 2.1988, 2.3810, 2.5682, 2.7613, 2.9438, - 0.1625, 0.2776, 0.4225, 0.6001, 0.7879, 0.9087, 1.0801, 1.2759, - 1.4899, 1.7448, 1.9911, 2.1770, 2.3723, 2.5777, 2.7971, 2.9444, - 0.2111, 0.3640, 0.5839, 0.7290, 0.8051, 1.0023, 1.2315, 1.4143, - 1.5878, 1.7755, 1.9804, 2.1498, 2.3312, 2.5350, 2.7613, 2.9472, - 0.1423, 0.2646, 0.4136, 0.6350, 0.8070, 0.9514, 1.1168, 1.3213, - 1.5776, 1.7721, 1.9404, 2.1545, 2.3385, 2.5137, 2.7396, 2.9553, - 0.1132, 0.2386, 0.4103, 0.5931, 0.7808, 0.9881, 1.1840, 1.3860, - 1.6021, 1.7990, 1.9922, 2.1885, 2.3852, 2.5717, 2.7640, 2.9510, - 0.1267, 0.2602, 0.3913, 0.5944, 0.7598, 0.9198, 1.0781, 1.2715, - 1.5299, 1.7573, 1.9308, 2.1346, 2.3267, 2.5419, 2.7466, 2.9320, - 0.2023, 0.3417, 0.4392, 0.6141, 0.7439, 0.8593, 1.1096, 1.3543, - 1.5185, 1.6553, 1.7862, 2.0341, 2.2718, 2.4834, 2.7103, 2.9466, - 0.1113, 0.2470, 0.3677, 0.5686, 0.7700, 0.9356, 1.0806, 1.2452, - 1.4830, 1.7344, 1.9268, 2.1404, 2.3371, 2.5169, 2.7329, 2.9012, - 0.1664, 0.3554, 0.5573, 0.7471, 0.9245, 1.0998, 1.2787, 1.4655, - 1.6654, 1.8346, 2.0179, 2.2159, 2.4096, 2.5946, 2.7790, 2.9530, - 0.1313, 0.2625, 0.4731, 0.6444, 0.8110, 0.9878, 1.1493, 1.3212, - 1.5719, 1.8138, 1.9861, 2.1943, 2.3714, 2.5578, 2.7346, 2.9296, - 0.1186, 0.3035, 0.5049, 0.6860, 0.8670, 0.9975, 1.1364, 1.3471, - 1.5695, 1.7412, 1.9346, 2.1506, 2.3413, 2.5531, 2.7794, 2.9627, - 0.1108, 0.2697, 0.4787, 0.6344, 0.7909, 0.9586, 1.1440, 1.3511, - 1.5686, 1.7601, 1.9246, 2.1241, 2.3293, 2.5390, 2.7315, 2.9333, - 0.0985, 0.2302, 0.3544, 0.5759, 0.7620, 0.9651, 1.1497, 1.3080, - 1.5500, 1.7845, 1.9518, 2.1734, 2.3565, 2.5665, 2.7605, 2.9102, - 0.1208, 0.2727, 0.4381, 0.5736, 0.7382, 0.8390, 1.0102, 1.2648, - 1.5100, 1.7440, 1.9619, 2.1430, 2.3307, 2.5159, 2.7264, 2.9211, - 0.1582, 0.2777, 0.4475, 0.6551, 0.8591, 1.0084, 1.1414, 1.3291, - 1.5902, 1.7826, 1.9543, 2.1659, 2.3233, 2.5044, 2.6935, 2.9199, - 0.1360, 0.2873, 0.4585, 0.6295, 0.7592, 0.9089, 1.0492, 1.2733, - 1.5391, 1.7768, 1.9372, 2.1329, 2.3168, 2.5015, 2.6857, 2.8837, - 0.0886, 0.1829, 0.3696, 0.6126, 0.8334, 1.0135, 1.2303, 1.4674, - 1.6743, 1.8564, 2.0530, 2.2370, 2.3960, 2.5787, 2.7756, 2.9377, - 0.2005, 0.3537, 0.4700, 0.6249, 0.7385, 0.9097, 1.1759, 1.3811, - 1.5314, 1.6705, 1.8546, 2.1229, 2.3292, 2.5251, 2.7951, 2.9646, - 0.1999, 0.3112, 0.4722, 0.7146, 0.8908, 1.0028, 1.1831, 1.3903, - 1.6125, 1.7514, 1.9083, 2.1248, 2.3271, 2.5339, 2.6945, 2.8918, - 0.1243, 0.2606, 0.4382, 0.5850, 0.7705, 0.9727, 1.1214, 1.3059, - 1.5218, 1.7406, 1.9137, 2.1353, 2.3354, 2.5299, 2.7287, 2.9068, - 0.1039, 0.2426, 0.4265, 0.6284, 0.8152, 0.9941, 1.2004, 1.4038, - 1.5912, 1.7763, 1.9650, 2.1598, 2.3474, 2.5488, 2.7419, 2.9322, - 0.1364, 0.2420, 0.3886, 0.5864, 0.7663, 0.8844, 1.0860, 1.3242, - 1.5518, 1.7893, 2.0004, 2.1562, 2.3619, 2.5516, 2.7687, 2.9181, - 0.1483, 0.2851, 0.4479, 0.6312, 0.7924, 0.9821, 1.1705, 1.3386, - 1.5375, 1.7226, 1.9053, 2.0991, 2.2898, 2.4953, 2.7000, 2.9146, - 0.2332, 0.4561, 0.5407, 0.6212, 0.7524, 0.8215, 0.9522, 1.1685, - 1.5216, 1.7132, 1.8291, 2.0647, 2.2811, 2.4857, 2.7071, 2.9281, - 0.1348, 0.3126, 0.5179, 0.7192, 0.9227, 1.1363, 1.3223, 1.4756, - 1.6509, 1.8191, 1.9991, 2.1976, 2.3877, 2.5768, 2.7590, 2.9386, - 0.1093, 0.2211, 0.4763, 0.6703, 0.8282, 0.9536, 1.1202, 1.3796, - 1.6043, 1.8031, 1.9832, 2.1604, 2.3578, 2.5856, 2.7650, 2.9291, - 0.1865, 0.3027, 0.4580, 0.6719, 0.8400, 1.0082, 1.1901, 1.3782, - 1.5448, 1.6885, 1.9477, 2.1381, 2.2797, 2.5113, 2.7465, 2.9414, - 0.1575, 0.3124, 0.4649, 0.6262, 0.8095, 0.9858, 1.1676, 1.3602, - 1.5646, 1.7582, 1.9550, 2.1671, 2.3628, 2.5734, 2.7670, 2.9519, - 0.1174, 0.2777, 0.4663, 0.6333, 0.8169, 1.0096, 1.1885, 1.3847, - 1.5803, 1.7571, 1.9380, 2.1398, 2.3414, 2.5407, 2.7360, 2.9375, - 0.1073, 0.2264, 0.4083, 0.5973, 0.7474, 0.9514, 1.1349, 1.3337, - 1.5433, 1.7348, 1.9380, 2.1436, 2.3441, 2.5438, 2.7457, 2.9383, - 0.1472, 0.2880, 0.4793, 0.6268, 0.8015, 1.0063, 1.1715, 1.3644, - 1.5525, 1.7410, 1.9258, 2.1227, 2.3214, 2.5149, 2.7148, 2.9196, - 0.1414, 0.2565, 0.4349, 0.6111, 0.7695, 0.9496, 1.1212, 1.3265, - 1.5218, 1.7209, 1.9015, 2.0887, 2.3158, 2.5077, 2.7233, 2.9421, - 0.1252, 0.2667, 0.4454, 0.6431, 0.8371, 1.0124, 1.2110, 1.4160, - 1.6240, 1.8242, 2.0047, 2.1974, 2.3902, 2.5778, 2.7637, 2.9481, - 0.1321, 0.2565, 0.3846, 0.5847, 0.7578, 0.9259, 1.0637, 1.2239, - 1.4690, 1.7346, 1.9750, 2.1882, 2.3712, 2.5509, 2.7280, 2.8885, - 0.1437, 0.2930, 0.4428, 0.6156, 0.8045, 0.9638, 1.1450, 1.3138, - 1.5144, 1.7355, 1.9469, 2.1534, 2.3414, 2.5452, 2.7353, 2.9334, - 0.1692, 0.2770, 0.3831, 0.6100, 0.7825, 0.9302, 1.0690, 1.2481, - 1.4615, 1.6799, 1.9165, 2.1739, 2.3435, 2.5349, 2.7520, 2.9163, - 0.1235, 0.2489, 0.4354, 0.6343, 0.8236, 1.0066, 1.1908, 1.3474, - 1.5656, 1.8275, 2.0620, 2.2548, 2.4135, 2.5913, 2.7639, 2.9334, - 0.1090, 0.1961, 0.3854, 0.5701, 0.7024, 0.8843, 1.1393, 1.3785, - 1.5940, 1.7797, 1.9442, 2.1740, 2.3853, 2.5773, 2.7727, 2.9406, - 0.1560, 0.3477, 0.5011, 0.6287, 0.7612, 0.9896, 1.1510, 1.3420, - 1.5435, 1.6816, 1.8731, 2.0651, 2.2613, 2.4999, 2.7027, 2.8971, - 0.1459, 0.2416, 0.3833, 0.5450, 0.7916, 0.9223, 1.0662, 1.1953, - 1.4029, 1.6616, 1.9320, 2.1459, 2.3386, 2.5081, 2.6799, 2.9195, - 0.1546, 0.3854, 0.6184, 0.8460, 1.0599, 1.2428, 1.3906, 1.5550, - 1.7388, 1.8945, 2.0757, 2.2386, 2.4014, 2.5705, 2.7574, 2.9400, - 0.1080, 0.2307, 0.4112, 0.6067, 0.7725, 0.9467, 1.1285, 1.3205, - 1.5348, 1.7609, 1.9937, 2.1878, 2.3583, 2.5515, 2.7199, 2.9049, - 0.1482, 0.3178, 0.4983, 0.6342, 0.7783, 0.9880, 1.2019, 1.3404, - 1.5223, 1.7296, 1.9211, 2.0943, 2.2928, 2.5008, 2.7136, 2.9224, - 0.1145, 0.2910, 0.4891, 0.6492, 0.8126, 0.9530, 1.1180, 1.3155, - 1.5054, 1.6893, 1.8899, 2.1188, 2.3389, 2.5512, 2.7313, 2.9224, - 0.0939, 0.1689, 0.3250, 0.5792, 0.7698, 0.9245, 1.1574, 1.3865, - 1.5959, 1.7977, 1.9821, 2.1528, 2.3326, 2.5540, 2.7553, 2.9179, - 0.1243, 0.2474, 0.3923, 0.6199, 0.7908, 0.9379, 1.1497, 1.3734, - 1.5582, 1.7420, 1.9539, 2.1385, 2.3240, 2.5277, 2.7311, 2.9178, - 0.1961, 0.3748, 0.5176, 0.6387, 0.8169, 1.0477, 1.2124, 1.3869, - 1.5604, 1.7225, 1.8770, 2.0837, 2.2960, 2.5103, 2.6945, 2.8862, - 0.1295, 0.2403, 0.4149, 0.6189, 0.7913, 0.9130, 1.0832, 1.2787, - 1.4860, 1.7112, 1.9502, 2.1348, 2.2776, 2.4982, 2.7431, 2.9522, - 0.0160, 0.0362, 0.0097, 0.0057, -0.0014, -0.0073, -0.0046, -0.0064, --0.0121, 0.0019, 0.0149, -0.0440, -0.0479, -0.0382, -0.0480, -0.0182, - 0.0170, 0.0114, -0.0298, -0.0175, -0.0033, -0.0354, -0.0510, -0.0025, - 0.0307, 0.0351, 0.0338, 0.0420, 0.0138, -0.0175, -0.0102, 0.0053, - 0.0084, -0.0003, 0.0412, -0.0027, 0.0145, -0.0039, 0.0083, 0.0400, - 0.0001, -0.0262, 0.0055, -0.0082, 0.0348, 0.0433, 0.0137, -0.0024, --0.0055, 0.0262, 0.0521, 0.0349, 0.0185, 0.0076, -0.0319, -0.0561, --0.0460, -0.0253, -0.0097, 0.0163, 0.0184, -0.0037, -0.0480, -0.0371, - 0.0628, 0.0665, 0.0296, -0.0057, 0.0253, 0.0227, 0.0350, 0.0692, - 0.0545, 0.0218, 0.0094, -0.0449, -0.0372, 0.0005, 0.0258, 0.0118, - 0.0285, 0.0760, 0.0822, 0.0527, -0.0299, -0.0049, 0.0170, 0.0195, - 0.0136, 0.0286, 0.0289, 0.0139, 0.0054, 0.0152, 0.0244, 0.0028, --0.0056, -0.0260, 0.0307, 0.0572, -0.0087, 0.0088, 0.0062, 0.0000, - 0.0125, 0.0000, -0.0292, 0.0820, 0.0872, 0.0646, 0.0346, 0.0076, --0.0022, -0.0253, -0.0567, -0.0188, -0.0336, -0.0673, -0.0549, -0.0166, --0.0259, -0.0140, 0.0040, -0.0029, -0.0430, -0.0531, -0.0253, -0.0019, --0.0071, 0.0393, 0.0072, -0.0327, -0.0236, -0.0235, -0.0177, -0.0186, --0.0280, -0.0201, -0.0077, 0.0383, 0.0418, 0.0321, 0.0294, 0.0169, - 0.0468, 0.0301, 0.0133, 0.0363, 0.0516, 0.0937, 0.1240, 0.1404, - 0.1325, 0.1178, 0.0999, 0.0251, -0.0037, -0.0495, -0.0703, -0.0219, --0.0261, -0.0304, -0.0204, -0.0372, 0.0355, 0.0131, -0.0093, -0.0099, --0.0069, -0.0034, -0.0065, -0.0208, -0.0231, -0.0117, -0.0211, -0.0243, - 0.0046, -0.0107, -0.0070, 0.0123, 0.0230, 0.0152, 0.0164, 0.0412, - 0.0619, 0.0858, 0.0862, -0.0056, 0.0125, 0.0182, 0.0347, 0.0388, - 0.0456, 0.0407, -0.0249, -0.0460, 0.0206, 0.0299, 0.0253, 0.0207, - 0.0177, 0.0238, 0.0253, 0.0030, 0.0042, 0.0020, -0.0081, -0.0136, --0.0290, -0.0042, 0.0122, 0.0051, 0.0107, 0.0228, 0.0211, -0.0068, --0.0436, -0.0299, -0.0078, -0.0779, -0.1157, -0.0679, 0.0172, 0.0150, --0.0051, 0.0081, -0.0512, -0.0616, 0.0576, 0.0799, 0.0803, 0.0336, - 0.0001, -0.0298, -0.0747, -0.0115, -0.0101, -0.0170, -0.0050, 0.0174, --0.0290, -0.0601, -0.0150, 0.0121, 0.0165, 0.0230, 0.0028, -0.0317, --0.0165, 0.0356, 0.0451, 0.0120, 0.0321, 0.0084, -0.0058, 0.0122, - 0.1935, 0.1802, 0.2195, 0.2410, 0.2201, 0.1915, 0.1840, 0.1935, - 0.2213, 0.2079, 0.1858, 0.1974, 0.2239, 0.2173, 0.1840, 0.2120, - 0.4912, 0.4777, 0.4607, 0.4395, 0.4426, 0.4388, 0.4416, 0.4345, - 0.4239, 0.4331, 0.4522, 0.4423, 0.4475, 0.4387, 0.4525, 0.4446 -}, - .lsp22_2 = { 0.0712, 0.1830, 0.4167, 0.6669, 0.8738, 1.0696, 1.2555, 1.4426, 1.6427, 1.8138, 1.9966, 2.1925, 2.3872, 2.5748, 2.7713, 2.9597, @@ -10781,213 +10198,6 @@ 0.4938, 0.4951, 0.4994, 0.4971, 0.4981, 0.4983, 0.4967, 0.4789 }, -.lsp44 = { - 0.0927, 0.2291, 0.4059, 0.5779, 0.7288, 0.8821, 1.0377, 1.1915, - 1.3433, 1.4931, 1.6475, 1.7989, 1.9381, 2.0858, 2.2321, 2.3765, - 2.5187, 2.6530, 2.7895, 2.9354, 0.0944, 0.1974, 0.3046, 0.4714, - 0.6116, 0.7829, 0.9027, 1.0375, 1.1869, 1.3488, 1.5036, 1.6781, - 1.8276, 1.9983, 2.1449, 2.3089, 2.4534, 2.6113, 2.7553, 2.9062, - 0.1168, 0.2843, 0.4907, 0.6706, 0.8100, 0.9417, 1.0753, 1.2014, - 1.3151, 1.4496, 1.5832, 1.7379, 1.8642, 2.0230, 2.1681, 2.3250, - 2.4676, 2.6242, 2.7602, 2.9066, 0.1353, 0.2335, 0.3370, 0.4380, - 0.5819, 0.7353, 0.8671, 1.0160, 1.1435, 1.2977, 1.4860, 1.6739, - 1.8412, 2.0028, 2.1537, 2.3124, 2.4741, 2.6272, 2.7862, 2.9536, - 0.1003, 0.2226, 0.3584, 0.4971, 0.6291, 0.7710, 0.9157, 1.0669, - 1.2143, 1.3624, 1.5104, 1.6681, 1.8164, 1.9823, 2.1394, 2.3082, - 2.4677, 2.6306, 2.7909, 2.9382, 0.1056, 0.2027, 0.2956, 0.4005, - 0.5215, 0.6708, 0.8545, 1.0557, 1.2344, 1.4023, 1.5676, 1.7278, - 1.8808, 2.0381, 2.1846, 2.3376, 2.4887, 2.6377, 2.7878, 2.9504, - 0.1015, 0.2462, 0.4122, 0.5783, 0.7233, 0.8833, 1.0377, 1.1903, - 1.3341, 1.4727, 1.6138, 1.7582, 1.8912, 2.0370, 2.1701, 2.3125, - 2.4500, 2.6006, 2.7507, 2.9166, 0.1787, 0.2418, 0.3265, 0.5379, - 0.6584, 0.7681, 0.9545, 1.1050, 1.2125, 1.3528, 1.4763, 1.6705, - 1.8136, 1.9594, 2.0936, 2.2724, 2.4394, 2.5919, 2.7037, 2.8747, - 0.0859, 0.1600, 0.2980, 0.4933, 0.6696, 0.8285, 0.9958, 1.1545, - 1.3107, 1.4591, 1.6127, 1.7652, 1.9143, 2.0680, 2.2171, 2.3643, - 2.5141, 2.6611, 2.8143, 2.9691, 0.0910, 0.2110, 0.3364, 0.4718, - 0.5856, 0.7298, 0.8910, 1.0514, 1.1988, 1.3572, 1.5178, 1.6861, - 1.8399, 2.0099, 2.1639, 2.3225, 2.4774, 2.6321, 2.7863, 2.9412, - 0.1904, 0.2874, 0.3681, 0.4981, 0.6248, 0.7880, 0.9121, 1.0750, - 1.2185, 1.3809, 1.5296, 1.7007, 1.8592, 2.0470, 2.1913, 2.3250, - 2.4519, 2.5984, 2.7408, 2.9023, 0.0917, 0.2067, 0.3246, 0.4961, - 0.6310, 0.8024, 0.9438, 1.1008, 1.2362, 1.3892, 1.5407, 1.7033, - 1.8427, 2.0061, 2.1498, 2.3117, 2.4550, 2.6053, 2.7462, 2.9029, - 0.0989, 0.2193, 0.3756, 0.5410, 0.6929, 0.8368, 0.9801, 1.1250, - 1.2677, 1.4184, 1.5677, 1.7292, 1.8770, 2.0311, 2.1803, 2.3306, - 2.4836, 2.6339, 2.7943, 2.9549, 0.0861, 0.1943, 0.3057, 0.4867, - 0.6194, 0.7592, 0.9184, 1.1052, 1.2486, 1.4064, 1.5609, 1.7273, - 1.8703, 2.0291, 2.1686, 2.3225, 2.4628, 2.6115, 2.7471, 2.9005, - 0.0932, 0.2110, 0.3737, 0.5479, 0.7120, 0.8570, 0.9975, 1.1364, - 1.2772, 1.4220, 1.5612, 1.7089, 1.8410, 1.9827, 2.1263, 2.2859, - 2.4459, 2.6172, 2.7788, 2.9395, 0.1193, 0.2341, 0.3523, 0.5029, - 0.6437, 0.7803, 0.9367, 1.1007, 1.2392, 1.3869, 1.5425, 1.7168, - 1.8709, 2.0248, 2.1584, 2.2949, 2.4308, 2.5823, 2.7235, 2.9034, - 0.0834, 0.1988, 0.3557, 0.5261, 0.6767, 0.8427, 1.0029, 1.1683, - 1.3138, 1.4527, 1.6046, 1.7583, 1.9011, 2.0517, 2.1928, 2.3397, - 2.4839, 2.6291, 2.7771, 2.9329, 0.0938, 0.1967, 0.3213, 0.4675, - 0.6068, 0.7664, 0.9418, 1.1120, 1.2535, 1.3932, 1.5243, 1.6801, - 1.8346, 1.9931, 2.1376, 2.3035, 2.4636, 2.6244, 2.7829, 2.9371, - 0.1017, 0.2552, 0.4327, 0.6017, 0.7467, 0.8797, 1.0097, 1.1442, - 1.2628, 1.4049, 1.5541, 1.7090, 1.8461, 1.9982, 2.1486, 2.3029, - 2.4513, 2.6075, 2.7594, 2.9209, 0.1031, 0.2295, 0.3747, 0.5122, - 0.6596, 0.7935, 0.9345, 1.1050, 1.2384, 1.3543, 1.4739, 1.6136, - 1.7447, 1.8914, 2.0434, 2.1916, 2.3557, 2.5396, 2.7419, 2.9401, - 0.1007, 0.2374, 0.3715, 0.5173, 0.6465, 0.8069, 0.9553, 1.1145, - 1.2594, 1.4143, 1.5617, 1.7166, 1.8457, 2.0012, 2.1462, 2.2864, - 2.4258, 2.5910, 2.7372, 2.9018, 0.0808, 0.1726, 0.2849, 0.4592, - 0.6118, 0.7853, 0.9588, 1.1256, 1.2751, 1.4392, 1.5898, 1.7514, - 1.8977, 2.0554, 2.1937, 2.3430, 2.4831, 2.6249, 2.7601, 2.9155, - 0.1669, 0.2574, 0.3694, 0.5569, 0.6773, 0.8061, 1.0160, 1.1667, - 1.2791, 1.4041, 1.5452, 1.7207, 1.8524, 2.0038, 2.1414, 2.3338, - 2.4747, 2.6157, 2.7303, 2.8848, 0.1598, 0.2521, 0.3416, 0.5149, - 0.6703, 0.7941, 0.9408, 1.1164, 1.2017, 1.3293, 1.4908, 1.6783, - 1.8438, 1.9927, 2.1149, 2.2698, 2.4420, 2.6193, 2.7583, 2.9103, - 0.0902, 0.1978, 0.3265, 0.4578, 0.5878, 0.7439, 0.9110, 1.0906, - 1.2556, 1.4125, 1.5688, 1.7295, 1.8829, 2.0472, 2.2058, 2.3537, - 2.5075, 2.6548, 2.8058, 2.9538, 0.0818, 0.1695, 0.2794, 0.4470, - 0.6069, 0.7641, 0.9313, 1.0946, 1.2411, 1.4072, 1.5640, 1.7186, - 1.8651, 2.0254, 2.1726, 2.3286, 2.4784, 2.6287, 2.7750, 2.9339, - 0.1980, 0.3134, 0.4099, 0.4975, 0.6491, 0.8376, 0.9441, 1.0298, - 1.1795, 1.3866, 1.5784, 1.7209, 1.8137, 1.9271, 2.0863, 2.2930, - 2.4696, 2.6184, 2.7587, 2.9251, 0.1338, 0.2341, 0.3566, 0.4797, - 0.6129, 0.7580, 0.9093, 1.0491, 1.1911, 1.3313, 1.4841, 1.6503, - 1.8035, 1.9685, 2.1128, 2.2694, 2.4093, 2.5728, 2.7206, 2.8994, - 0.0937, 0.2034, 0.3447, 0.5032, 0.6370, 0.7993, 0.9674, 1.1323, - 1.2830, 1.4199, 1.5492, 1.7010, 1.8513, 2.0087, 2.1550, 2.3115, - 2.4643, 2.6237, 2.7812, 2.9392, 0.1085, 0.2152, 0.3126, 0.4569, - 0.5718, 0.7213, 0.8837, 1.0604, 1.2053, 1.3755, 1.5397, 1.7001, - 1.8409, 2.0039, 2.1498, 2.3080, 2.4535, 2.6063, 2.7505, 2.9110, - 0.0562, 0.2066, 0.4034, 0.5490, 0.6682, 0.7924, 0.9495, 1.0800, - 1.1869, 1.3156, 1.4834, 1.6619, 1.8404, 2.0199, 2.1509, 2.2755, - 2.4072, 2.5580, 2.6993, 2.8913, 0.0939, 0.2303, 0.3742, 0.5260, - 0.6662, 0.8294, 0.9769, 1.1315, 1.2792, 1.4153, 1.5436, 1.6701, - 1.8215, 1.9920, 2.1310, 2.3005, 2.4534, 2.5786, 2.7204, 2.9068, - 0.1005, 0.2442, 0.3898, 0.5398, 0.6958, 0.8474, 1.0008, 1.1556, - 1.3020, 1.4456, 1.5954, 1.7470, 1.8922, 2.0500, 2.2019, 2.3492, - 2.4963, 2.6412, 2.7890, 2.9423, 0.1022, 0.2031, 0.3213, 0.4402, - 0.5637, 0.7117, 0.8673, 1.0242, 1.1727, 1.3206, 1.4846, 1.6465, - 1.8015, 1.9655, 2.1233, 2.2873, 2.4464, 2.6074, 2.7685, 2.9409, - 0.1985, 0.3497, 0.4622, 0.5982, 0.7489, 0.8752, 0.9925, 1.1679, - 1.3288, 1.4606, 1.5820, 1.7492, 1.8922, 2.0511, 2.1780, 2.3373, - 2.4760, 2.6233, 2.7466, 2.8978, 0.1284, 0.2433, 0.3630, 0.4852, - 0.6117, 0.7460, 0.8904, 1.0360, 1.1738, 1.3142, 1.4696, 1.6185, - 1.7719, 1.9318, 2.0961, 2.2697, 2.4408, 2.6046, 2.7681, 2.9451, - 0.1042, 0.2286, 0.3598, 0.5064, 0.6438, 0.7899, 0.9350, 1.0891, - 1.2323, 1.3807, 1.5225, 1.6747, 1.8153, 1.9669, 2.1145, 2.2832, - 2.4430, 2.6085, 2.7748, 2.9346, 0.0780, 0.1724, 0.2440, 0.3489, - 0.5280, 0.7426, 0.9272, 1.0914, 1.2562, 1.4188, 1.5804, 1.7376, - 1.8909, 2.0473, 2.1946, 2.3457, 2.4950, 2.6424, 2.7926, 2.9549, - 0.1103, 0.2608, 0.4087, 0.5538, 0.6923, 0.8418, 0.9940, 1.1507, - 1.2919, 1.4406, 1.5802, 1.7262, 1.8638, 2.0085, 2.1572, 2.2975, - 2.4329, 2.5866, 2.7380, 2.9107, 0.1297, 0.2532, 0.4003, 0.5329, - 0.6733, 0.7950, 0.9557, 1.0859, 1.2235, 1.3538, 1.5037, 1.6389, - 1.7964, 1.9285, 2.0898, 2.2541, 2.4231, 2.5711, 2.6875, 2.8947, - 0.0871, 0.1968, 0.3425, 0.4949, 0.6424, 0.7959, 0.9534, 1.1132, - 1.2656, 1.4229, 1.5785, 1.7271, 1.8729, 2.0355, 2.1998, 2.3562, - 2.5151, 2.6663, 2.8145, 2.9534, 0.1038, 0.2204, 0.3248, 0.4566, - 0.5947, 0.7443, 0.8811, 1.0379, 1.2031, 1.3772, 1.5430, 1.7092, - 1.8625, 2.0322, 2.1904, 2.3417, 2.4960, 2.6458, 2.7979, 2.9485, - 0.1329, 0.2763, 0.3943, 0.5147, 0.6512, 0.8071, 0.9410, 1.0879, - 1.2298, 1.3850, 1.5282, 1.6674, 1.8137, 1.9993, 2.1344, 2.2749, - 2.4257, 2.5863, 2.7410, 2.9184, 0.1052, 0.2142, 0.3584, 0.5033, - 0.6387, 0.7804, 0.9320, 1.0780, 1.2172, 1.3764, 1.5421, 1.6887, - 1.8246, 1.9833, 2.1245, 2.2797, 2.4237, 2.5779, 2.7257, 2.9097, - 0.1092, 0.2676, 0.4071, 0.5355, 0.6661, 0.8142, 0.9621, 1.1173, - 1.2628, 1.4185, 1.5696, 1.7220, 1.8595, 2.0178, 2.1720, 2.3221, - 2.4718, 2.6259, 2.7775, 2.9334, 0.0929, 0.2017, 0.3073, 0.4570, - 0.5775, 0.7635, 0.9299, 1.0832, 1.2334, 1.3935, 1.5420, 1.7112, - 1.8601, 2.0309, 2.1735, 2.3230, 2.4543, 2.6034, 2.7418, 2.8988, - 0.0775, 0.2005, 0.3490, 0.5200, 0.6747, 0.8383, 0.9885, 1.1738, - 1.3141, 1.4236, 1.5892, 1.7402, 1.8474, 2.0210, 2.1593, 2.2730, - 2.4235, 2.5604, 2.7128, 2.9005, 0.1104, 0.2292, 0.3353, 0.4732, - 0.6152, 0.7675, 0.9164, 1.0907, 1.2594, 1.4064, 1.5218, 1.6426, - 1.8018, 1.9937, 2.1362, 2.2961, 2.4523, 2.6083, 2.7613, 2.9202, - 0.0826, 0.2000, 0.3384, 0.5144, 0.6694, 0.8377, 0.9870, 1.1461, - 1.2950, 1.4495, 1.5872, 1.7387, 1.8793, 2.0329, 2.1723, 2.3114, - 2.4415, 2.5908, 2.7354, 2.9028, 0.1063, 0.2268, 0.3442, 0.4735, - 0.6116, 0.7507, 0.9028, 1.0768, 1.2426, 1.4052, 1.5566, 1.7015, - 1.8243, 1.9742, 2.1276, 2.2824, 2.4262, 2.5953, 2.7627, 2.9290, - 0.1150, 0.2814, 0.4543, 0.6095, 0.7373, 0.8592, 0.9908, 1.1108, - 1.2339, 1.3590, 1.4864, 1.6168, 1.7392, 1.8752, 2.0212, 2.1688, - 2.3128, 2.4869, 2.7019, 2.9239, 0.0948, 0.2074, 0.3433, 0.4943, - 0.6346, 0.7645, 0.8809, 1.0610, 1.2307, 1.3487, 1.4655, 1.6186, - 1.7534, 1.8859, 2.0486, 2.2200, 2.3835, 2.5581, 2.7565, 2.9502, - 0.1062, 0.2239, 0.3683, 0.5197, 0.6704, 0.8184, 0.9642, 1.1127, - 1.2556, 1.3976, 1.5405, 1.6940, 1.8375, 1.9888, 2.1377, 2.2980, - 2.4555, 2.6184, 2.7849, 2.9452, 0.0888, 0.2005, 0.2847, 0.4322, - 0.5763, 0.7577, 0.9262, 1.1095, 1.2719, 1.4331, 1.5843, 1.7452, - 1.8845, 2.0385, 2.1805, 2.3345, 2.4750, 2.6217, 2.7555, 2.9013, - 0.1713, 0.2617, 0.3868, 0.5859, 0.7073, 0.8535, 1.0593, 1.1778, - 1.3109, 1.4508, 1.5910, 1.7463, 1.8911, 2.0651, 2.2035, 2.3355, - 2.4947, 2.6440, 2.7424, 2.8943, 0.1346, 0.2549, 0.4089, 0.5488, - 0.6949, 0.8394, 0.9810, 1.1145, 1.2528, 1.4044, 1.5423, 1.6872, - 1.8274, 1.9726, 2.1403, 2.2809, 2.4128, 2.5564, 2.6887, 2.8895, - 0.0776, 0.1621, 0.2553, 0.4191, 0.5988, 0.7921, 0.9651, 1.1350, - 1.2930, 1.4475, 1.6011, 1.7585, 1.9068, 2.0638, 2.2102, 2.3594, - 2.5096, 2.6581, 2.8099, 2.9654, 0.0864, 0.1778, 0.2854, 0.4235, - 0.5568, 0.7220, 0.8963, 1.0609, 1.2217, 1.3830, 1.5422, 1.7018, - 1.8551, 2.0206, 2.1783, 2.3328, 2.4869, 2.6366, 2.7923, 2.9539, - 0.1144, 0.2576, 0.4186, 0.5594, 0.6875, 0.8221, 0.9598, 1.0944, - 1.2273, 1.3713, 1.5152, 1.6628, 1.8070, 1.9525, 2.0965, 2.2535, - 2.4132, 2.5725, 2.7250, 2.9150, 0.1079, 0.2221, 0.3334, 0.4845, - 0.6083, 0.7516, 0.9018, 1.0594, 1.2060, 1.3673, 1.5212, 1.6880, - 1.8208, 1.9831, 2.1269, 2.2909, 2.4366, 2.6027, 2.7339, 2.8924, - 0.0994, 0.2233, 0.3634, 0.5145, 0.6568, 0.8131, 0.9746, 1.1296, - 1.2666, 1.4116, 1.5748, 1.7264, 1.8649, 2.0217, 2.1716, 2.3293, - 2.4900, 2.6455, 2.7818, 2.9362, 0.1120, 0.2079, 0.3128, 0.4124, - 0.5291, 0.6816, 0.8478, 1.0150, 1.1772, 1.3456, 1.5208, 1.6882, - 1.8458, 2.0078, 2.1627, 2.3198, 2.4733, 2.6251, 2.7796, 2.9489, - 0.0853, 0.2030, 0.3669, 0.5326, 0.6678, 0.8086, 0.9526, 1.1142, - 1.2551, 1.4158, 1.5694, 1.7073, 1.8431, 1.9686, 2.1153, 2.2376, - 2.3686, 2.5591, 2.7320, 2.9104, 0.0905, 0.2166, 0.3539, 0.5201, - 0.6700, 0.8346, 0.9883, 1.1457, 1.2714, 1.3845, 1.5172, 1.6688, - 1.8008, 1.9535, 2.1019, 2.2708, 2.4135, 2.5974, 2.7486, 2.9033, - 0.0084, 0.0374, 0.0164, -0.0153, 0.0288, 0.0107, -0.0255, -0.0242, - 0.0000, -0.0055, -0.0081, -0.0075, -0.0022, -0.0052, -0.0069, -0.0017, - 0.0003, 0.0091, 0.0028, -0.0027, 0.0085, 0.0043, -0.0235, -0.0411, - 0.0202, 0.0359, 0.0376, 0.0321, 0.0306, -0.0358, -0.0276, -0.0090, - 0.0032, 0.0048, 0.0309, 0.0332, 0.0284, 0.0237, 0.0051, -0.0101, --0.0233, -0.0428, -0.0585, -0.0387, 0.0039, 0.0081, 0.0029, -0.0017, --0.0006, -0.0068, 0.0044, 0.0182, 0.0376, 0.0387, -0.0334, -0.0269, --0.0182, -0.0069, -0.0026, 0.0035, -0.0049, -0.0212, -0.0408, -0.0245, - 0.0186, 0.0189, 0.0153, 0.0120, 0.0157, 0.0055, -0.0046, 0.0179, - 0.0284, -0.0032, -0.0261, -0.0205, -0.0039, 0.0174, 0.0299, 0.0207, - 0.0012, -0.0056, 0.0010, 0.0141, -0.0119, 0.0190, 0.0315, 0.0033, --0.0128, 0.0300, 0.0328, 0.0308, 0.0353, 0.0266, 0.0066, -0.0328, --0.0273, 0.0054, 0.0145, 0.0175, 0.0015, -0.0171, 0.0062, -0.0164, - 0.0045, -0.0071, 0.0025, 0.0278, 0.0283, 0.0117, -0.0026, -0.0285, --0.0408, -0.0366, -0.0059, -0.0208, -0.0354, -0.0334, -0.0263, -0.0064, - 0.0072, -0.0006, -0.0235, -0.0037, -0.0307, -0.0294, -0.0163, -0.0197, --0.0235, 0.0192, 0.0013, -0.0219, -0.0123, -0.0004, -0.0081, -0.0096, --0.0123, -0.0101, 0.0021, 0.0151, 0.0106, 0.0151, 0.0292, 0.0033, - 0.0283, 0.0124, 0.0058, -0.0017, -0.0038, 0.0152, 0.0141, 0.0132, - 0.0178, 0.0157, 0.0073, 0.0176, 0.0141, 0.0097, -0.0092, -0.0163, --0.0230, -0.0134, -0.0099, -0.0147, 0.0040, -0.0183, -0.0175, -0.0080, --0.0083, -0.0290, -0.0417, -0.0398, -0.0269, -0.0199, -0.0143, -0.0053, --0.0099, -0.0054, -0.0199, -0.0219, -0.0170, 0.0107, 0.0194, 0.0035, - 0.0437, 0.0406, 0.0215, 0.0120, 0.0053, -0.0028, 0.0238, 0.0337, - 0.0217, 0.0011, 0.0227, 0.0244, 0.0327, 0.0378, 0.0437, 0.0356, --0.0033, 0.0113, 0.0407, 0.0334, -0.0125, -0.0003, -0.0141, -0.0273, --0.0137, -0.0079, -0.0145, -0.0071, 0.0114, 0.0181, 0.0150, 0.0085, --0.0077, -0.0038, -0.0219, -0.0263, -0.0187, -0.0233, 0.0133, 0.0265, --0.0156, -0.0091, -0.0110, -0.0016, 0.0143, 0.0177, 0.0240, 0.0082, --0.0143, -0.0257, -0.0014, 0.0002, 0.0082, 0.0180, 0.0325, 0.0340, --0.0153, -0.0389, -0.0240, 0.0082, 0.0140, 0.0046, -0.0138, -0.0378, --0.0366, 0.0297, 0.0252, 0.0078, 0.0063, 0.0006, 0.0044, 0.0074, - 0.0094, 0.0113, 0.0105, 0.0137, 0.0438, 0.0262, -0.0078, -0.0185, --0.0215, -0.0407, -0.0435, -0.0208, -0.0004, -0.0144, -0.0205, -0.0248, --0.0159, -0.0069, -0.0153, 0.0132, 0.0355, 0.0298, 0.0120, 0.0072, - 0.0236, 0.0526, 0.0479, 0.0233, -0.0133, -0.0283, -0.0468, -0.0549, --0.0370, 0.0032, 0.0056, 0.0023, 0.0050, 0.0024, 0.0279, 0.0116, --0.0045, -0.0012, 0.0107, 0.0190, 0.0253, 0.0191, 0.0043, 0.0193, --0.0348, -0.0246, 0.0123, 0.0210, 0.0135, -0.0096, -0.0109, -0.0076, --0.0156, -0.0290, 0.0160, 0.0194, 0.0219, 0.0259, 0.0250, 0.0195, - 0.4948, 0.4961, 0.4940, 0.4878, 0.4849, 0.4727, 0.4571, 0.4551, - 0.4534, 0.4468, 0.4412, 0.4354, 0.4298, 0.4272, 0.4498, 0.4506, - 0.4560, 0.4592, 0.4758, 0.4941, 0.2476, 0.1771, 0.1974, 0.1881, - 0.1667, 0.1826, 0.2067, 0.2031, 0.1734, 0.1534, 0.1415, 0.1761, - 0.1897, 0.1772, 0.1651, 0.1247, 0.1041, 0.1231, 0.1809, 0.2234 - }, }; static const uint8_t tab7[][35] = { diff -Nru ffmpeg-4.2.2/libavcodec/twinvqdec.c ffmpeg-4.4/libavcodec/twinvqdec.c --- ffmpeg-4.2.2/libavcodec/twinvqdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/twinvqdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ #include "get_bits.h" #include "internal.h" #include "twinvq.h" +#include "metasound_data.h" #include "twinvq_data.h" static const TwinVQModeTab mode_08_08 = { @@ -35,7 +36,7 @@ { 2, bark_tab_m08_256, 20, tab.fcb08m, 2, 5, tab.cb0808m0, tab.cb0808m1, 16 }, { 1, bark_tab_l08_512, 30, tab.fcb08l, 3, 6, tab.cb0808l0, tab.cb0808l1, 17 } }, - 512, 12, tab.lsp08, 1, 5, 3, 3, tab.shape08, 8, 28, 20, 6, 40 + 512, 12, ff_metasound_lsp8, 1, 5, 3, 3, tab.shape08, 8, 28, 20, 6, 40 }; static const TwinVQModeTab mode_11_08 = { @@ -44,7 +45,7 @@ { 2, bark_tab_m11_256, 20, tab.fcb11m, 2, 5, tab.cb1108m0, tab.cb1108m1, 24 }, { 1, bark_tab_l11_512, 30, tab.fcb11l, 3, 6, tab.cb1108l0, tab.cb1108l1, 27 } }, - 512, 16, tab.lsp11, 1, 6, 4, 3, tab.shape11, 9, 36, 30, 7, 90 + 512, 16, ff_metasound_lsp11, 1, 6, 4, 3, tab.shape11, 9, 36, 30, 7, 90 }; static const TwinVQModeTab mode_11_10 = { @@ -53,7 +54,7 @@ { 2, bark_tab_m11_256, 20, tab.fcb11m, 2, 5, tab.cb1110m0, tab.cb1110m1, 18 }, { 1, bark_tab_l11_512, 30, tab.fcb11l, 3, 6, tab.cb1110l0, tab.cb1110l1, 20 } }, - 512, 16, tab.lsp11, 1, 6, 4, 3, tab.shape11, 9, 36, 30, 7, 90 + 512, 16, ff_metasound_lsp11, 1, 6, 4, 3, tab.shape11, 9, 36, 30, 7, 90 }; static const TwinVQModeTab mode_16_16 = { @@ -62,7 +63,7 @@ { 2, bark_tab_m16_512, 20, tab.fcb16m, 2, 5, tab.cb1616m0, tab.cb1616m1, 15 }, { 1, bark_tab_l16_1024, 30, tab.fcb16l, 3, 6, tab.cb1616l0, tab.cb1616l1, 16 } }, - 1024, 16, tab.lsp16, 1, 6, 4, 3, tab.shape16, 9, 56, 60, 7, 180 + 1024, 16, ff_metasound_lsp16, 1, 6, 4, 3, tab.shape16, 9, 56, 60, 7, 180 }; static const TwinVQModeTab mode_22_20 = { @@ -71,7 +72,7 @@ { 2, bark_tab_m22_512, 20, tab.fcb22m_1, 2, 6, tab.cb2220m0, tab.cb2220m1, 17 }, { 1, bark_tab_l22_1024, 32, tab.fcb22l_1, 4, 6, tab.cb2220l0, tab.cb2220l1, 18 } }, - 1024, 16, tab.lsp22_1, 1, 6, 4, 3, tab.shape22_1, 9, 56, 36, 7, 144 + 1024, 16, ff_metasound_lsp22, 1, 6, 4, 3, tab.shape22_1, 9, 56, 36, 7, 144 }; static const TwinVQModeTab mode_22_24 = { @@ -80,7 +81,7 @@ { 2, bark_tab_m22_512, 20, tab.fcb22m_1, 2, 6, tab.cb2224m0, tab.cb2224m1, 14 }, { 1, bark_tab_l22_1024, 32, tab.fcb22l_1, 4, 6, tab.cb2224l0, tab.cb2224l1, 15 } }, - 1024, 16, tab.lsp22_1, 1, 6, 4, 3, tab.shape22_1, 9, 56, 36, 7, 144 + 1024, 16, ff_metasound_lsp22, 1, 6, 4, 3, tab.shape22_1, 9, 56, 36, 7, 144 }; static const TwinVQModeTab mode_22_32 = { @@ -98,7 +99,7 @@ { 4, bark_tab_m44_512, 20, tab.fcb44m, 2, 6, tab.cb4440m0, tab.cb4440m1, 17 }, { 1, bark_tab_l44_2048, 40, tab.fcb44l, 4, 6, tab.cb4440l0, tab.cb4440l1, 17 } }, - 2048, 20, tab.lsp44, 1, 6, 4, 4, tab.shape44, 9, 84, 54, 7, 432 + 2048, 20, ff_metasound_lsp44, 1, 6, 4, 4, tab.shape44, 9, 84, 54, 7, 432 }; static const TwinVQModeTab mode_44_48 = { @@ -107,7 +108,7 @@ { 4, bark_tab_m44_512, 20, tab.fcb44m, 2, 6, tab.cb4448m0, tab.cb4448m1, 14 }, { 1, bark_tab_l44_2048, 40, tab.fcb44l, 4, 6, tab.cb4448l0, tab.cb4448l1, 14 } }, - 2048, 20, tab.lsp44, 1, 6, 4, 4, tab.shape44, 9, 84, 54, 7, 432 + 2048, 20, ff_metasound_lsp44, 1, 6, 4, 4, tab.shape44, 9, 84, 54, 7, 432 }; /** @@ -422,7 +423,7 @@ .init = twinvq_decode_init, .close = ff_twinvq_decode_close, .decode = ff_twinvq_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff -Nru ffmpeg-4.2.2/libavcodec/txd.c ffmpeg-4.4/libavcodec/txd.c --- ffmpeg-4.2.2/libavcodec/txd.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/txd.c 2020-07-09 09:17:46.000000000 +0000 @@ -43,6 +43,9 @@ int i, j; int ret; + if (avpkt->size < 88) + return AVERROR_INVALIDDATA; + ff_texturedsp_init(&dxtc); bytestream2_init(&gb, avpkt->data, avpkt->size); diff -Nru ffmpeg-4.2.2/libavcodec/ulti.c ffmpeg-4.4/libavcodec/ulti.c --- ffmpeg-4.2.2/libavcodec/ulti.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ulti.c 2021-04-08 21:28:39.000000000 +0000 @@ -230,7 +230,7 @@ int skip; int tmp; - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) return ret; bytestream2_init(&s->gb, buf, buf_size); @@ -428,4 +428,5 @@ .close = ulti_decode_end, .decode = ulti_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/utils.c ffmpeg-4.4/libavcodec/utils.c --- ffmpeg-4.2.2/libavcodec/utils.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/utils.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,46 +26,26 @@ */ #include "config.h" -#include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" -#include "libavutil/bprint.h" -#include "libavutil/channel_layout.h" -#include "libavutil/crc.h" -#include "libavutil/frame.h" -#include "libavutil/hwcontext.h" -#include "libavutil/internal.h" -#include "libavutil/mathematics.h" +#include "libavutil/intreadwrite.h" #include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" #include "libavutil/imgutils.h" -#include "libavutil/samplefmt.h" -#include "libavutil/dict.h" -#include "libavutil/thread.h" +#include "libavutil/pixfmt.h" #include "avcodec.h" -#include "decode.h" -#include "hwaccel.h" -#include "libavutil/opt.h" -#include "mpegvideo.h" +#include "codec.h" +#include "hwconfig.h" #include "thread.h" -#include "frame_thread_encoder.h" #include "internal.h" +#include "put_bits.h" #include "raw.h" -#include "bytestream.h" #include "version.h" #include #include #include #include #include -#if CONFIG_ICONV -# include -#endif - -#include "libavutil/ffversion.h" -const char av_codec_ffversion[] = "FFmpeg version " FFMPEG_VERSION; - -static AVMutex codec_mutex = AV_MUTEX_INITIALIZER; void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size) { @@ -93,7 +73,7 @@ int av_codec_is_encoder(const AVCodec *codec) { - return codec && (codec->encode_sub || codec->encode2 ||codec->send_frame); + return codec && (codec->encode_sub || codec->encode2 || codec->receive_packet); } int av_codec_is_decoder(const AVCodec *codec) @@ -438,32 +418,6 @@ } } -int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2), void *arg, int *ret, int count, int size) -{ - int i; - - for (i = 0; i < count; i++) { - int r = func(c, (char *)arg + i * size); - if (ret) - ret[i] = r; - } - emms_c(); - return 0; -} - -int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int jobnr, int threadnr), void *arg, int *ret, int count) -{ - int i; - - for (i = 0; i < count; i++) { - int r = func(c, arg, i, 0); - if (ret) - ret[i] = r; - } - emms_c(); - return 0; -} - enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc) { @@ -497,676 +451,10 @@ return !!(codec->caps_internal & FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM); } -static int64_t get_bit_rate(AVCodecContext *ctx) -{ - int64_t bit_rate; - int bits_per_sample; - - switch (ctx->codec_type) { - case AVMEDIA_TYPE_VIDEO: - case AVMEDIA_TYPE_DATA: - case AVMEDIA_TYPE_SUBTITLE: - case AVMEDIA_TYPE_ATTACHMENT: - bit_rate = ctx->bit_rate; - break; - case AVMEDIA_TYPE_AUDIO: - bits_per_sample = av_get_bits_per_sample(ctx->codec_id); - bit_rate = bits_per_sample ? ctx->sample_rate * (int64_t)ctx->channels * bits_per_sample : ctx->bit_rate; - break; - default: - bit_rate = 0; - break; - } - return bit_rate; -} - - -static void ff_lock_avcodec(AVCodecContext *log_ctx, const AVCodec *codec) -{ - if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) - ff_mutex_lock(&codec_mutex); -} - -static void ff_unlock_avcodec(const AVCodec *codec) -{ - if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) - ff_mutex_unlock(&codec_mutex); -} - -int attribute_align_arg ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options) -{ - int ret = 0; - - ff_unlock_avcodec(codec); - - ret = avcodec_open2(avctx, codec, options); - - ff_lock_avcodec(avctx, codec); - return ret; -} - -int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options) -{ - int ret = 0; - int codec_init_ok = 0; - AVDictionary *tmp = NULL; - const AVPixFmtDescriptor *pixdesc; - - if (avcodec_is_open(avctx)) - return 0; - - if ((!codec && !avctx->codec)) { - av_log(avctx, AV_LOG_ERROR, "No codec provided to avcodec_open2()\n"); - return AVERROR(EINVAL); - } - if ((codec && avctx->codec && codec != avctx->codec)) { - av_log(avctx, AV_LOG_ERROR, "This AVCodecContext was allocated for %s, " - "but %s passed to avcodec_open2()\n", avctx->codec->name, codec->name); - return AVERROR(EINVAL); - } - if (!codec) - codec = avctx->codec; - - if (avctx->extradata_size < 0 || avctx->extradata_size >= FF_MAX_EXTRADATA_SIZE) - return AVERROR(EINVAL); - - if (options) - av_dict_copy(&tmp, *options, 0); - - ff_lock_avcodec(avctx, codec); - - avctx->internal = av_mallocz(sizeof(*avctx->internal)); - if (!avctx->internal) { - ret = AVERROR(ENOMEM); - goto end; - } - - avctx->internal->pool = av_mallocz(sizeof(*avctx->internal->pool)); - if (!avctx->internal->pool) { - ret = AVERROR(ENOMEM); - goto free_and_end; - } - - avctx->internal->to_free = av_frame_alloc(); - if (!avctx->internal->to_free) { - ret = AVERROR(ENOMEM); - goto free_and_end; - } - - avctx->internal->compat_decode_frame = av_frame_alloc(); - if (!avctx->internal->compat_decode_frame) { - ret = AVERROR(ENOMEM); - goto free_and_end; - } - - avctx->internal->buffer_frame = av_frame_alloc(); - if (!avctx->internal->buffer_frame) { - ret = AVERROR(ENOMEM); - goto free_and_end; - } - - avctx->internal->buffer_pkt = av_packet_alloc(); - if (!avctx->internal->buffer_pkt) { - ret = AVERROR(ENOMEM); - goto free_and_end; - } - - avctx->internal->ds.in_pkt = av_packet_alloc(); - if (!avctx->internal->ds.in_pkt) { - ret = AVERROR(ENOMEM); - goto free_and_end; - } - - avctx->internal->last_pkt_props = av_packet_alloc(); - if (!avctx->internal->last_pkt_props) { - ret = AVERROR(ENOMEM); - goto free_and_end; - } - - avctx->internal->skip_samples_multiplier = 1; - - if (codec->priv_data_size > 0) { - if (!avctx->priv_data) { - avctx->priv_data = av_mallocz(codec->priv_data_size); - if (!avctx->priv_data) { - ret = AVERROR(ENOMEM); - goto end; - } - if (codec->priv_class) { - *(const AVClass **)avctx->priv_data = codec->priv_class; - av_opt_set_defaults(avctx->priv_data); - } - } - if (codec->priv_class && (ret = av_opt_set_dict(avctx->priv_data, &tmp)) < 0) - goto free_and_end; - } else { - avctx->priv_data = NULL; - } - if ((ret = av_opt_set_dict(avctx, &tmp)) < 0) - goto free_and_end; - - if (avctx->codec_whitelist && av_match_list(codec->name, avctx->codec_whitelist, ',') <= 0) { - av_log(avctx, AV_LOG_ERROR, "Codec (%s) not on whitelist \'%s\'\n", codec->name, avctx->codec_whitelist); - ret = AVERROR(EINVAL); - goto free_and_end; - } - - // only call ff_set_dimensions() for non H.264/VP6F/DXV codecs so as not to overwrite previously setup dimensions - if (!(avctx->coded_width && avctx->coded_height && avctx->width && avctx->height && - (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_VP6F || avctx->codec_id == AV_CODEC_ID_DXV))) { - if (avctx->coded_width && avctx->coded_height) - ret = ff_set_dimensions(avctx, avctx->coded_width, avctx->coded_height); - else if (avctx->width && avctx->height) - ret = ff_set_dimensions(avctx, avctx->width, avctx->height); - if (ret < 0) - goto free_and_end; - } - - if ((avctx->coded_width || avctx->coded_height || avctx->width || avctx->height) - && ( av_image_check_size2(avctx->coded_width, avctx->coded_height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0 - || av_image_check_size2(avctx->width, avctx->height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0)) { - av_log(avctx, AV_LOG_WARNING, "Ignoring invalid width/height values\n"); - ff_set_dimensions(avctx, 0, 0); - } - - if (avctx->width > 0 && avctx->height > 0) { - if (av_image_check_sar(avctx->width, avctx->height, - avctx->sample_aspect_ratio) < 0) { - av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\n", - avctx->sample_aspect_ratio.num, - avctx->sample_aspect_ratio.den); - avctx->sample_aspect_ratio = (AVRational){ 0, 1 }; - } - } - - /* if the decoder init function was already called previously, - * free the already allocated subtitle_header before overwriting it */ - if (av_codec_is_decoder(codec)) - av_freep(&avctx->subtitle_header); - - if (avctx->channels > FF_SANE_NB_CHANNELS || avctx->channels < 0) { - av_log(avctx, AV_LOG_ERROR, "Too many or invalid channels: %d\n", avctx->channels); - ret = AVERROR(EINVAL); - goto free_and_end; - } - if (avctx->sample_rate < 0) { - av_log(avctx, AV_LOG_ERROR, "Invalid sample rate: %d\n", avctx->sample_rate); - ret = AVERROR(EINVAL); - goto free_and_end; - } - if (avctx->block_align < 0) { - av_log(avctx, AV_LOG_ERROR, "Invalid block align: %d\n", avctx->block_align); - ret = AVERROR(EINVAL); - goto free_and_end; - } - - avctx->codec = codec; - if ((avctx->codec_type == AVMEDIA_TYPE_UNKNOWN || avctx->codec_type == codec->type) && - avctx->codec_id == AV_CODEC_ID_NONE) { - avctx->codec_type = codec->type; - avctx->codec_id = codec->id; - } - if (avctx->codec_id != codec->id || (avctx->codec_type != codec->type - && avctx->codec_type != AVMEDIA_TYPE_ATTACHMENT)) { - av_log(avctx, AV_LOG_ERROR, "Codec type or id mismatches\n"); - ret = AVERROR(EINVAL); - goto free_and_end; - } - avctx->frame_number = 0; - avctx->codec_descriptor = avcodec_descriptor_get(avctx->codec_id); - - if ((avctx->codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) && - avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { - const char *codec_string = av_codec_is_encoder(codec) ? "encoder" : "decoder"; - AVCodec *codec2; - av_log(avctx, AV_LOG_ERROR, - "The %s '%s' is experimental but experimental codecs are not enabled, " - "add '-strict %d' if you want to use it.\n", - codec_string, codec->name, FF_COMPLIANCE_EXPERIMENTAL); - codec2 = av_codec_is_encoder(codec) ? avcodec_find_encoder(codec->id) : avcodec_find_decoder(codec->id); - if (!(codec2->capabilities & AV_CODEC_CAP_EXPERIMENTAL)) - av_log(avctx, AV_LOG_ERROR, "Alternatively use the non experimental %s '%s'.\n", - codec_string, codec2->name); - ret = AVERROR_EXPERIMENTAL; - goto free_and_end; - } - - if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && - (!avctx->time_base.num || !avctx->time_base.den)) { - avctx->time_base.num = 1; - avctx->time_base.den = avctx->sample_rate; - } - - if (!HAVE_THREADS) - av_log(avctx, AV_LOG_WARNING, "Warning: not compiled with thread support, using thread emulation\n"); - - if (CONFIG_FRAME_THREAD_ENCODER && av_codec_is_encoder(avctx->codec)) { - ff_unlock_avcodec(codec); //we will instantiate a few encoders thus kick the counter to prevent false detection of a problem - ret = ff_frame_thread_encoder_init(avctx, options ? *options : NULL); - ff_lock_avcodec(avctx, codec); - if (ret < 0) - goto free_and_end; - } - - if (av_codec_is_decoder(avctx->codec)) { - ret = ff_decode_bsfs_init(avctx); - if (ret < 0) - goto free_and_end; - } - - if (HAVE_THREADS - && !(avctx->internal->frame_thread_encoder && (avctx->active_thread_type&FF_THREAD_FRAME))) { - ret = ff_thread_init(avctx); - if (ret < 0) { - goto free_and_end; - } - } - if (!HAVE_THREADS && !(codec->capabilities & AV_CODEC_CAP_AUTO_THREADS)) - avctx->thread_count = 1; - - if (avctx->codec->max_lowres < avctx->lowres || avctx->lowres < 0) { - av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n", - avctx->codec->max_lowres); - avctx->lowres = avctx->codec->max_lowres; - } - - if (av_codec_is_encoder(avctx->codec)) { - int i; -#if FF_API_CODED_FRAME -FF_DISABLE_DEPRECATION_WARNINGS - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) { - ret = AVERROR(ENOMEM); - goto free_and_end; - } -FF_ENABLE_DEPRECATION_WARNINGS -#endif - - if (avctx->time_base.num <= 0 || avctx->time_base.den <= 0) { - av_log(avctx, AV_LOG_ERROR, "The encoder timebase is not set.\n"); - ret = AVERROR(EINVAL); - goto free_and_end; - } - - if (avctx->codec->sample_fmts) { - for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) { - if (avctx->sample_fmt == avctx->codec->sample_fmts[i]) - break; - if (avctx->channels == 1 && - av_get_planar_sample_fmt(avctx->sample_fmt) == - av_get_planar_sample_fmt(avctx->codec->sample_fmts[i])) { - avctx->sample_fmt = avctx->codec->sample_fmts[i]; - break; - } - } - if (avctx->codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) { - char buf[128]; - snprintf(buf, sizeof(buf), "%d", avctx->sample_fmt); - av_log(avctx, AV_LOG_ERROR, "Specified sample format %s is invalid or not supported\n", - (char *)av_x_if_null(av_get_sample_fmt_name(avctx->sample_fmt), buf)); - ret = AVERROR(EINVAL); - goto free_and_end; - } - } - if (avctx->codec->pix_fmts) { - for (i = 0; avctx->codec->pix_fmts[i] != AV_PIX_FMT_NONE; i++) - if (avctx->pix_fmt == avctx->codec->pix_fmts[i]) - break; - if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_NONE - && !((avctx->codec_id == AV_CODEC_ID_MJPEG || avctx->codec_id == AV_CODEC_ID_LJPEG) - && avctx->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL)) { - char buf[128]; - snprintf(buf, sizeof(buf), "%d", avctx->pix_fmt); - av_log(avctx, AV_LOG_ERROR, "Specified pixel format %s is invalid or not supported\n", - (char *)av_x_if_null(av_get_pix_fmt_name(avctx->pix_fmt), buf)); - ret = AVERROR(EINVAL); - goto free_and_end; - } - if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ420P || - avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ411P || - avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ422P || - avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ440P || - avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ444P) - avctx->color_range = AVCOL_RANGE_JPEG; - } - if (avctx->codec->supported_samplerates) { - for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++) - if (avctx->sample_rate == avctx->codec->supported_samplerates[i]) - break; - if (avctx->codec->supported_samplerates[i] == 0) { - av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n", - avctx->sample_rate); - ret = AVERROR(EINVAL); - goto free_and_end; - } - } - if (avctx->sample_rate < 0) { - av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n", - avctx->sample_rate); - ret = AVERROR(EINVAL); - goto free_and_end; - } - if (avctx->codec->channel_layouts) { - if (!avctx->channel_layout) { - av_log(avctx, AV_LOG_WARNING, "Channel layout not specified\n"); - } else { - for (i = 0; avctx->codec->channel_layouts[i] != 0; i++) - if (avctx->channel_layout == avctx->codec->channel_layouts[i]) - break; - if (avctx->codec->channel_layouts[i] == 0) { - char buf[512]; - av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); - av_log(avctx, AV_LOG_ERROR, "Specified channel layout '%s' is not supported\n", buf); - ret = AVERROR(EINVAL); - goto free_and_end; - } - } - } - if (avctx->channel_layout && avctx->channels) { - int channels = av_get_channel_layout_nb_channels(avctx->channel_layout); - if (channels != avctx->channels) { - char buf[512]; - av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); - av_log(avctx, AV_LOG_ERROR, - "Channel layout '%s' with %d channels does not match number of specified channels %d\n", - buf, channels, avctx->channels); - ret = AVERROR(EINVAL); - goto free_and_end; - } - } else if (avctx->channel_layout) { - avctx->channels = av_get_channel_layout_nb_channels(avctx->channel_layout); - } - if (avctx->channels < 0) { - av_log(avctx, AV_LOG_ERROR, "Specified number of channels %d is not supported\n", - avctx->channels); - ret = AVERROR(EINVAL); - goto free_and_end; - } - if(avctx->codec_type == AVMEDIA_TYPE_VIDEO) { - pixdesc = av_pix_fmt_desc_get(avctx->pix_fmt); - if ( avctx->bits_per_raw_sample < 0 - || (avctx->bits_per_raw_sample > 8 && pixdesc->comp[0].depth <= 8)) { - av_log(avctx, AV_LOG_WARNING, "Specified bit depth %d not possible with the specified pixel formats depth %d\n", - avctx->bits_per_raw_sample, pixdesc->comp[0].depth); - avctx->bits_per_raw_sample = pixdesc->comp[0].depth; - } - if (avctx->width <= 0 || avctx->height <= 0) { - av_log(avctx, AV_LOG_ERROR, "dimensions not set\n"); - ret = AVERROR(EINVAL); - goto free_and_end; - } - } - if ( (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO) - && avctx->bit_rate>0 && avctx->bit_rate<1000) { - av_log(avctx, AV_LOG_WARNING, "Bitrate %"PRId64" is extremely low, maybe you mean %"PRId64"k\n", avctx->bit_rate, avctx->bit_rate); - } - - if (!avctx->rc_initial_buffer_occupancy) - avctx->rc_initial_buffer_occupancy = avctx->rc_buffer_size * 3LL / 4; - - if (avctx->ticks_per_frame && avctx->time_base.num && - avctx->ticks_per_frame > INT_MAX / avctx->time_base.num) { - av_log(avctx, AV_LOG_ERROR, - "ticks_per_frame %d too large for the timebase %d/%d.", - avctx->ticks_per_frame, - avctx->time_base.num, - avctx->time_base.den); - goto free_and_end; - } - - if (avctx->hw_frames_ctx) { - AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - if (frames_ctx->format != avctx->pix_fmt) { - av_log(avctx, AV_LOG_ERROR, - "Mismatching AVCodecContext.pix_fmt and AVHWFramesContext.format\n"); - ret = AVERROR(EINVAL); - goto free_and_end; - } - if (avctx->sw_pix_fmt != AV_PIX_FMT_NONE && - avctx->sw_pix_fmt != frames_ctx->sw_format) { - av_log(avctx, AV_LOG_ERROR, - "Mismatching AVCodecContext.sw_pix_fmt (%s) " - "and AVHWFramesContext.sw_format (%s)\n", - av_get_pix_fmt_name(avctx->sw_pix_fmt), - av_get_pix_fmt_name(frames_ctx->sw_format)); - ret = AVERROR(EINVAL); - goto free_and_end; - } - avctx->sw_pix_fmt = frames_ctx->sw_format; - } - } - - avctx->pts_correction_num_faulty_pts = - avctx->pts_correction_num_faulty_dts = 0; - avctx->pts_correction_last_pts = - avctx->pts_correction_last_dts = INT64_MIN; - - if ( !CONFIG_GRAY && avctx->flags & AV_CODEC_FLAG_GRAY - && avctx->codec_descriptor->type == AVMEDIA_TYPE_VIDEO) - av_log(avctx, AV_LOG_WARNING, - "gray decoding requested but not enabled at configuration time\n"); - - if ( avctx->codec->init && (!(avctx->active_thread_type&FF_THREAD_FRAME) - || avctx->internal->frame_thread_encoder)) { - ret = avctx->codec->init(avctx); - if (ret < 0) { - goto free_and_end; - } - codec_init_ok = 1; - } - - ret=0; - - if (av_codec_is_decoder(avctx->codec)) { - if (!avctx->bit_rate) - avctx->bit_rate = get_bit_rate(avctx); - /* validate channel layout from the decoder */ - if (avctx->channel_layout) { - int channels = av_get_channel_layout_nb_channels(avctx->channel_layout); - if (!avctx->channels) - avctx->channels = channels; - else if (channels != avctx->channels) { - char buf[512]; - av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); - av_log(avctx, AV_LOG_WARNING, - "Channel layout '%s' with %d channels does not match specified number of channels %d: " - "ignoring specified channel layout\n", - buf, channels, avctx->channels); - avctx->channel_layout = 0; - } - } - if (avctx->channels && avctx->channels < 0 || - avctx->channels > FF_SANE_NB_CHANNELS) { - ret = AVERROR(EINVAL); - goto free_and_end; - } - if (avctx->bits_per_coded_sample < 0) { - ret = AVERROR(EINVAL); - goto free_and_end; - } - if (avctx->sub_charenc) { - if (avctx->codec_type != AVMEDIA_TYPE_SUBTITLE) { - av_log(avctx, AV_LOG_ERROR, "Character encoding is only " - "supported with subtitles codecs\n"); - ret = AVERROR(EINVAL); - goto free_and_end; - } else if (avctx->codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB) { - av_log(avctx, AV_LOG_WARNING, "Codec '%s' is bitmap-based, " - "subtitles character encoding will be ignored\n", - avctx->codec_descriptor->name); - avctx->sub_charenc_mode = FF_SUB_CHARENC_MODE_DO_NOTHING; - } else { - /* input character encoding is set for a text based subtitle - * codec at this point */ - if (avctx->sub_charenc_mode == FF_SUB_CHARENC_MODE_AUTOMATIC) - avctx->sub_charenc_mode = FF_SUB_CHARENC_MODE_PRE_DECODER; - - if (avctx->sub_charenc_mode == FF_SUB_CHARENC_MODE_PRE_DECODER) { -#if CONFIG_ICONV - iconv_t cd = iconv_open("UTF-8", avctx->sub_charenc); - if (cd == (iconv_t)-1) { - ret = AVERROR(errno); - av_log(avctx, AV_LOG_ERROR, "Unable to open iconv context " - "with input character encoding \"%s\"\n", avctx->sub_charenc); - goto free_and_end; - } - iconv_close(cd); -#else - av_log(avctx, AV_LOG_ERROR, "Character encoding subtitles " - "conversion needs a libavcodec built with iconv support " - "for this codec\n"); - ret = AVERROR(ENOSYS); - goto free_and_end; -#endif - } - } - } - -#if FF_API_AVCTX_TIMEBASE - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) - avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); -#endif - } - if (codec->priv_data_size > 0 && avctx->priv_data && codec->priv_class) { - av_assert0(*(const AVClass **)avctx->priv_data == codec->priv_class); - } - -end: - ff_unlock_avcodec(codec); - if (options) { - av_dict_free(options); - *options = tmp; - } - - return ret; -free_and_end: - if (avctx->codec && avctx->codec->close && - (codec_init_ok || - (avctx->codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP))) - avctx->codec->close(avctx); - - if (HAVE_THREADS && avctx->internal->thread_ctx) - ff_thread_free(avctx); - - if (codec->priv_class && codec->priv_data_size) - av_opt_free(avctx->priv_data); - av_opt_free(avctx); - -#if FF_API_CODED_FRAME -FF_DISABLE_DEPRECATION_WARNINGS - av_frame_free(&avctx->coded_frame); -FF_ENABLE_DEPRECATION_WARNINGS -#endif - - av_dict_free(&tmp); - av_freep(&avctx->priv_data); - av_freep(&avctx->subtitle_header); - if (avctx->internal) { - av_frame_free(&avctx->internal->to_free); - av_frame_free(&avctx->internal->compat_decode_frame); - av_frame_free(&avctx->internal->buffer_frame); - av_packet_free(&avctx->internal->buffer_pkt); - av_packet_free(&avctx->internal->last_pkt_props); - - av_packet_free(&avctx->internal->ds.in_pkt); - ff_decode_bsfs_uninit(avctx); - - av_freep(&avctx->internal->pool); - } - av_freep(&avctx->internal); - avctx->codec = NULL; - goto end; -} - -void avsubtitle_free(AVSubtitle *sub) -{ - int i; - - for (i = 0; i < sub->num_rects; i++) { - av_freep(&sub->rects[i]->data[0]); - av_freep(&sub->rects[i]->data[1]); - av_freep(&sub->rects[i]->data[2]); - av_freep(&sub->rects[i]->data[3]); - av_freep(&sub->rects[i]->text); - av_freep(&sub->rects[i]->ass); - av_freep(&sub->rects[i]); - } - - av_freep(&sub->rects); - - memset(sub, 0, sizeof(*sub)); -} - -av_cold int avcodec_close(AVCodecContext *avctx) -{ - int i; - - if (!avctx) - return 0; - - if (avcodec_is_open(avctx)) { - FramePool *pool = avctx->internal->pool; - if (CONFIG_FRAME_THREAD_ENCODER && - avctx->internal->frame_thread_encoder && avctx->thread_count > 1) { - ff_frame_thread_encoder_free(avctx); - } - if (HAVE_THREADS && avctx->internal->thread_ctx) - ff_thread_free(avctx); - if (avctx->codec && avctx->codec->close) - avctx->codec->close(avctx); - avctx->internal->byte_buffer_size = 0; - av_freep(&avctx->internal->byte_buffer); - av_frame_free(&avctx->internal->to_free); - av_frame_free(&avctx->internal->compat_decode_frame); - av_frame_free(&avctx->internal->buffer_frame); - av_packet_free(&avctx->internal->buffer_pkt); - av_packet_free(&avctx->internal->last_pkt_props); - - av_packet_free(&avctx->internal->ds.in_pkt); - - for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++) - av_buffer_pool_uninit(&pool->pools[i]); - av_freep(&avctx->internal->pool); - - if (avctx->hwaccel && avctx->hwaccel->uninit) - avctx->hwaccel->uninit(avctx); - av_freep(&avctx->internal->hwaccel_priv_data); - - ff_decode_bsfs_uninit(avctx); - - av_freep(&avctx->internal); - } - - for (i = 0; i < avctx->nb_coded_side_data; i++) - av_freep(&avctx->coded_side_data[i].data); - av_freep(&avctx->coded_side_data); - avctx->nb_coded_side_data = 0; - - av_buffer_unref(&avctx->hw_frames_ctx); - av_buffer_unref(&avctx->hw_device_ctx); - - if (avctx->priv_data && avctx->codec && avctx->codec->priv_class) - av_opt_free(avctx->priv_data); - av_opt_free(avctx); - av_freep(&avctx->priv_data); - if (av_codec_is_encoder(avctx->codec)) { - av_freep(&avctx->extradata); -#if FF_API_CODED_FRAME -FF_DISABLE_DEPRECATION_WARNINGS - av_frame_free(&avctx->coded_frame); -FF_ENABLE_DEPRECATION_WARNINGS -#endif - } - avctx->codec = NULL; - avctx->active_thread_type = 0; - - return 0; -} - const char *avcodec_get_name(enum AVCodecID id) { const AVCodecDescriptor *cd; - AVCodec *codec; + const AVCodec *codec; if (id == AV_CODEC_ID_NONE) return "none"; @@ -1183,6 +471,7 @@ return "unknown_codec"; } +#if FF_API_TAG_STRING size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_tag) { int i, len, ret = 0; @@ -1202,201 +491,7 @@ } return ret; } - -void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) -{ - const char *codec_type; - const char *codec_name; - const char *profile = NULL; - int64_t bitrate; - int new_line = 0; - AVRational display_aspect_ratio; - const char *separator = enc->dump_separator ? (const char *)enc->dump_separator : ", "; - - if (!buf || buf_size <= 0) - return; - codec_type = av_get_media_type_string(enc->codec_type); - codec_name = avcodec_get_name(enc->codec_id); - profile = avcodec_profile_name(enc->codec_id, enc->profile); - - snprintf(buf, buf_size, "%s: %s", codec_type ? codec_type : "unknown", - codec_name); - buf[0] ^= 'a' ^ 'A'; /* first letter in uppercase */ - - if (enc->codec && strcmp(enc->codec->name, codec_name)) - snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", enc->codec->name); - - if (profile) - snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", profile); - if ( enc->codec_type == AVMEDIA_TYPE_VIDEO - && av_log_get_level() >= AV_LOG_VERBOSE - && enc->refs) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", %d reference frame%s", - enc->refs, enc->refs > 1 ? "s" : ""); - - if (enc->codec_tag) - snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s / 0x%04X)", - av_fourcc2str(enc->codec_tag), enc->codec_tag); - - switch (enc->codec_type) { - case AVMEDIA_TYPE_VIDEO: - { - char detail[256] = "("; - - av_strlcat(buf, separator, buf_size); - - snprintf(buf + strlen(buf), buf_size - strlen(buf), - "%s", enc->pix_fmt == AV_PIX_FMT_NONE ? "none" : - av_get_pix_fmt_name(enc->pix_fmt)); - if (enc->bits_per_raw_sample && enc->pix_fmt != AV_PIX_FMT_NONE && - enc->bits_per_raw_sample < av_pix_fmt_desc_get(enc->pix_fmt)->comp[0].depth) - av_strlcatf(detail, sizeof(detail), "%d bpc, ", enc->bits_per_raw_sample); - if (enc->color_range != AVCOL_RANGE_UNSPECIFIED) - av_strlcatf(detail, sizeof(detail), "%s, ", - av_color_range_name(enc->color_range)); - - if (enc->colorspace != AVCOL_SPC_UNSPECIFIED || - enc->color_primaries != AVCOL_PRI_UNSPECIFIED || - enc->color_trc != AVCOL_TRC_UNSPECIFIED) { - if (enc->colorspace != (int)enc->color_primaries || - enc->colorspace != (int)enc->color_trc) { - new_line = 1; - av_strlcatf(detail, sizeof(detail), "%s/%s/%s, ", - av_color_space_name(enc->colorspace), - av_color_primaries_name(enc->color_primaries), - av_color_transfer_name(enc->color_trc)); - } else - av_strlcatf(detail, sizeof(detail), "%s, ", - av_get_colorspace_name(enc->colorspace)); - } - - if (enc->field_order != AV_FIELD_UNKNOWN) { - const char *field_order = "progressive"; - if (enc->field_order == AV_FIELD_TT) - field_order = "top first"; - else if (enc->field_order == AV_FIELD_BB) - field_order = "bottom first"; - else if (enc->field_order == AV_FIELD_TB) - field_order = "top coded first (swapped)"; - else if (enc->field_order == AV_FIELD_BT) - field_order = "bottom coded first (swapped)"; - - av_strlcatf(detail, sizeof(detail), "%s, ", field_order); - } - - if (av_log_get_level() >= AV_LOG_VERBOSE && - enc->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) - av_strlcatf(detail, sizeof(detail), "%s, ", - av_chroma_location_name(enc->chroma_sample_location)); - - if (strlen(detail) > 1) { - detail[strlen(detail) - 2] = 0; - av_strlcatf(buf, buf_size, "%s)", detail); - } - } - - if (enc->width) { - av_strlcat(buf, new_line ? separator : ", ", buf_size); - - snprintf(buf + strlen(buf), buf_size - strlen(buf), - "%dx%d", - enc->width, enc->height); - - if (av_log_get_level() >= AV_LOG_VERBOSE && - (enc->width != enc->coded_width || - enc->height != enc->coded_height)) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - " (%dx%d)", enc->coded_width, enc->coded_height); - - if (enc->sample_aspect_ratio.num) { - av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den, - enc->width * (int64_t)enc->sample_aspect_ratio.num, - enc->height * (int64_t)enc->sample_aspect_ratio.den, - 1024 * 1024); - snprintf(buf + strlen(buf), buf_size - strlen(buf), - " [SAR %d:%d DAR %d:%d]", - enc->sample_aspect_ratio.num, enc->sample_aspect_ratio.den, - display_aspect_ratio.num, display_aspect_ratio.den); - } - if (av_log_get_level() >= AV_LOG_DEBUG) { - int g = av_gcd(enc->time_base.num, enc->time_base.den); - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", %d/%d", - enc->time_base.num / g, enc->time_base.den / g); - } - } - if (encode) { - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", q=%d-%d", enc->qmin, enc->qmax); - } else { - if (enc->properties & FF_CODEC_PROPERTY_CLOSED_CAPTIONS) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", Closed Captions"); - if (enc->properties & FF_CODEC_PROPERTY_LOSSLESS) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", lossless"); - } - break; - case AVMEDIA_TYPE_AUDIO: - av_strlcat(buf, separator, buf_size); - - if (enc->sample_rate) { - snprintf(buf + strlen(buf), buf_size - strlen(buf), - "%d Hz, ", enc->sample_rate); - } - av_get_channel_layout_string(buf + strlen(buf), buf_size - strlen(buf), enc->channels, enc->channel_layout); - if (enc->sample_fmt != AV_SAMPLE_FMT_NONE) { - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", %s", av_get_sample_fmt_name(enc->sample_fmt)); - } - if ( enc->bits_per_raw_sample > 0 - && enc->bits_per_raw_sample != av_get_bytes_per_sample(enc->sample_fmt) * 8) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - " (%d bit)", enc->bits_per_raw_sample); - if (av_log_get_level() >= AV_LOG_VERBOSE) { - if (enc->initial_padding) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", delay %d", enc->initial_padding); - if (enc->trailing_padding) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", padding %d", enc->trailing_padding); - } - break; - case AVMEDIA_TYPE_DATA: - if (av_log_get_level() >= AV_LOG_DEBUG) { - int g = av_gcd(enc->time_base.num, enc->time_base.den); - if (g) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", %d/%d", - enc->time_base.num / g, enc->time_base.den / g); - } - break; - case AVMEDIA_TYPE_SUBTITLE: - if (enc->width) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", %dx%d", enc->width, enc->height); - break; - default: - return; - } - if (encode) { - if (enc->flags & AV_CODEC_FLAG_PASS1) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", pass 1"); - if (enc->flags & AV_CODEC_FLAG_PASS2) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", pass 2"); - } - bitrate = get_bit_rate(enc); - if (bitrate != 0) { - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", %"PRId64" kb/s", bitrate / 1000); - } else if (enc->rc_max_rate > 0) { - snprintf(buf + strlen(buf), buf_size - strlen(buf), - ", max. %"PRId64" kb/s", enc->rc_max_rate / 1000); - } -} +#endif const char *av_get_profile_name(const AVCodec *codec, int profile) { @@ -1426,37 +521,21 @@ return NULL; } -unsigned avcodec_version(void) -{ - av_assert0(AV_CODEC_ID_PCM_S8_PLANAR==65563); - av_assert0(AV_CODEC_ID_ADPCM_G722==69660); - av_assert0(AV_CODEC_ID_SRT==94216); - av_assert0(LIBAVCODEC_VERSION_MICRO >= 100); - - return LIBAVCODEC_VERSION_INT; -} - -const char *avcodec_configuration(void) -{ - return FFMPEG_CONFIGURATION; -} - -const char *avcodec_license(void) -{ -#define LICENSE_PREFIX "libavcodec license: " - return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; -} - int av_get_exact_bits_per_sample(enum AVCodecID codec_id) { switch (codec_id) { case AV_CODEC_ID_8SVX_EXP: case AV_CODEC_ID_8SVX_FIB: + case AV_CODEC_ID_ADPCM_ARGO: case AV_CODEC_ID_ADPCM_CT: + case AV_CODEC_ID_ADPCM_IMA_ALP: + case AV_CODEC_ID_ADPCM_IMA_AMV: case AV_CODEC_ID_ADPCM_IMA_APC: + case AV_CODEC_ID_ADPCM_IMA_APM: case AV_CODEC_ID_ADPCM_IMA_EA_SEAD: case AV_CODEC_ID_ADPCM_IMA_OKI: case AV_CODEC_ID_ADPCM_IMA_WS: + case AV_CODEC_ID_ADPCM_IMA_SSI: case AV_CODEC_ID_ADPCM_G722: case AV_CODEC_ID_ADPCM_YAMAHA: case AV_CODEC_ID_ADPCM_AICA: @@ -1470,9 +549,10 @@ case AV_CODEC_ID_PCM_VIDC: case AV_CODEC_ID_PCM_S8: case AV_CODEC_ID_PCM_S8_PLANAR: + case AV_CODEC_ID_PCM_SGA: case AV_CODEC_ID_PCM_U8: - case AV_CODEC_ID_PCM_ZORK: case AV_CODEC_ID_SDX2_DPCM: + case AV_CODEC_ID_DERF_DPCM: return 8; case AV_CODEC_ID_PCM_S16BE: case AV_CODEC_ID_PCM_S16BE_PLANAR: @@ -1510,7 +590,7 @@ enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be) { - static const enum AVCodecID map[AV_SAMPLE_FMT_NB][2] = { + static const enum AVCodecID map[][2] = { [AV_SAMPLE_FMT_U8 ] = { AV_CODEC_ID_PCM_U8, AV_CODEC_ID_PCM_U8 }, [AV_SAMPLE_FMT_S16 ] = { AV_CODEC_ID_PCM_S16LE, AV_CODEC_ID_PCM_S16BE }, [AV_SAMPLE_FMT_S32 ] = { AV_CODEC_ID_PCM_S32LE, AV_CODEC_ID_PCM_S32BE }, @@ -1523,7 +603,7 @@ [AV_SAMPLE_FMT_FLTP] = { AV_CODEC_ID_PCM_F32LE, AV_CODEC_ID_PCM_F32BE }, [AV_SAMPLE_FMT_DBLP] = { AV_CODEC_ID_PCM_F64LE, AV_CODEC_ID_PCM_F64BE }, }; - if (fmt < 0 || fmt >= AV_SAMPLE_FMT_NB) + if (fmt < 0 || fmt >= FF_ARRAY_ELEMS(map)) return AV_CODEC_ID_NONE; if (be < 0 || be > 1) be = AV_NE(1, 0); @@ -1575,7 +655,10 @@ case AV_CODEC_ID_MP1: return 384; case AV_CODEC_ID_ATRAC1: return 512; case AV_CODEC_ID_ATRAC9: - case AV_CODEC_ID_ATRAC3: return 1024 * framecount; + case AV_CODEC_ID_ATRAC3: + if (framecount > INT_MAX/1024) + return 0; + return 1024 * framecount; case AV_CODEC_ID_ATRAC3P: return 2048; case AV_CODEC_ID_MP2: case AV_CODEC_ID_MUSEPACK7: return 1152; @@ -1588,11 +671,10 @@ return 256 * sr / 245; else if (id == AV_CODEC_ID_DST) return 588 * sr / 44100; - - if (ch > 0) { - /* calc from sample rate and channels */ - if (id == AV_CODEC_ID_BINKAUDIO_DCT) - return (480 << (sr / 22050)) / ch; + else if (id == AV_CODEC_ID_BINKAUDIO_DCT) { + if (sr / 22050 > 22) + return 0; + return (480 << (sr / 22050)); } if (id == AV_CODEC_ID_MP3) @@ -1634,11 +716,18 @@ if (ch > 0 && ch < INT_MAX/16) { /* calc from frame_bytes and channels */ switch (id) { + case AV_CODEC_ID_FASTAUDIO: + return frame_bytes / (40 * ch) * 256; + case AV_CODEC_ID_ADPCM_IMA_MOFLEX: + return (frame_bytes - 4 * ch) / (128 * ch) * 256; case AV_CODEC_ID_ADPCM_AFC: return frame_bytes / (9 * ch) * 16; case AV_CODEC_ID_ADPCM_PSX: case AV_CODEC_ID_ADPCM_DTK: - return frame_bytes / (16 * ch) * 28; + frame_bytes /= 16 * ch; + if (frame_bytes > INT_MAX / 28) + return 0; + return frame_bytes * 28; case AV_CODEC_ID_ADPCM_4XM: case AV_CODEC_ID_ADPCM_IMA_DAT4: case AV_CODEC_ID_ADPCM_IMA_ISS: @@ -1646,7 +735,7 @@ case AV_CODEC_ID_ADPCM_IMA_SMJPEG: return (frame_bytes - 4) * 2 / ch; case AV_CODEC_ID_ADPCM_IMA_AMV: - return (frame_bytes - 8) * 2 / ch; + return (frame_bytes - 8) * 2; case AV_CODEC_ID_ADPCM_THP: case AV_CODEC_ID_ADPCM_THP_LE: if (extradata) @@ -1696,7 +785,7 @@ case AV_CODEC_ID_ADPCM_IMA_RAD: return blocks * ((ba - 4 * ch) * 2 / ch); case AV_CODEC_ID_ADPCM_MS: - return blocks * (2 + (ba - 7 * ch) * 2 / ch); + return blocks * (2 + (ba - 7 * ch) * 2LL / ch); case AV_CODEC_ID_ADPCM_MTAF: return blocks * (ba - 16) * 2 / ch; } @@ -1803,13 +892,6 @@ } #endif -#if FF_API_LOCKMGR -int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) -{ - return 0; -} -#endif - unsigned int avpriv_toupper4(unsigned int x) { return av_toupper(x & 0xFF) + @@ -1818,7 +900,7 @@ ((unsigned)av_toupper((x >> 24) & 0xFF) << 24); } -int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src) +int ff_thread_ref_frame(ThreadFrame *dst, const ThreadFrame *src) { int ret; @@ -1895,34 +977,6 @@ #endif -int avcodec_is_open(AVCodecContext *s) -{ - return !!s->internal; -} - -int avpriv_bprint_to_extradata(AVCodecContext *avctx, struct AVBPrint *buf) -{ - int ret; - char *str; - - ret = av_bprint_finalize(buf, &str); - if (ret < 0) - return ret; - if (!av_bprint_is_complete(buf)) { - av_free(str); - return AVERROR(ENOMEM); - } - - avctx->extradata = str; - /* Note: the string is NUL terminated (so extradata can be read as a - * string), but the ending character is not accounted in the size (in - * binary formats you are likely not supposed to mux that character). When - * extradata is copied, it is also padded with AV_INPUT_BUFFER_PADDING_SIZE - * zeros. */ - avctx->extradata_size = buf->len; - return 0; -} - const uint8_t *avpriv_find_start_code(const uint8_t *av_restrict p, const uint8_t *end, uint32_t *av_restrict state) @@ -1975,6 +1029,11 @@ AVPacketSideData *tmp; AVCPBProperties *props; size_t size; + int i; + + for (i = 0; i < avctx->nb_coded_side_data; i++) + if (avctx->coded_side_data[i].type == AV_PKT_DATA_CPB_PROPERTIES) + return (AVCPBProperties *)avctx->coded_side_data[i].data; props = av_cpb_properties_alloc(&size); if (!props) @@ -1996,218 +1055,75 @@ return props; } -static void codec_parameters_reset(AVCodecParameters *par) -{ - av_freep(&par->extradata); - - memset(par, 0, sizeof(*par)); - - par->codec_type = AVMEDIA_TYPE_UNKNOWN; - par->codec_id = AV_CODEC_ID_NONE; - par->format = -1; - par->field_order = AV_FIELD_UNKNOWN; - par->color_range = AVCOL_RANGE_UNSPECIFIED; - par->color_primaries = AVCOL_PRI_UNSPECIFIED; - par->color_trc = AVCOL_TRC_UNSPECIFIED; - par->color_space = AVCOL_SPC_UNSPECIFIED; - par->chroma_location = AVCHROMA_LOC_UNSPECIFIED; - par->sample_aspect_ratio = (AVRational){ 0, 1 }; - par->profile = FF_PROFILE_UNKNOWN; - par->level = FF_LEVEL_UNKNOWN; -} - -AVCodecParameters *avcodec_parameters_alloc(void) -{ - AVCodecParameters *par = av_mallocz(sizeof(*par)); - - if (!par) - return NULL; - codec_parameters_reset(par); - return par; -} - -void avcodec_parameters_free(AVCodecParameters **ppar) -{ - AVCodecParameters *par = *ppar; - - if (!par) - return; - codec_parameters_reset(par); - - av_freep(ppar); -} - -int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src) -{ - codec_parameters_reset(dst); - memcpy(dst, src, sizeof(*dst)); - - dst->extradata = NULL; - dst->extradata_size = 0; - if (src->extradata) { - dst->extradata = av_mallocz(src->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!dst->extradata) - return AVERROR(ENOMEM); - memcpy(dst->extradata, src->extradata, src->extradata_size); - dst->extradata_size = src->extradata_size; - } - - return 0; -} - -int avcodec_parameters_from_context(AVCodecParameters *par, - const AVCodecContext *codec) +static unsigned bcd2uint(uint8_t bcd) { - codec_parameters_reset(par); - - par->codec_type = codec->codec_type; - par->codec_id = codec->codec_id; - par->codec_tag = codec->codec_tag; - - par->bit_rate = codec->bit_rate; - par->bits_per_coded_sample = codec->bits_per_coded_sample; - par->bits_per_raw_sample = codec->bits_per_raw_sample; - par->profile = codec->profile; - par->level = codec->level; - - switch (par->codec_type) { - case AVMEDIA_TYPE_VIDEO: - par->format = codec->pix_fmt; - par->width = codec->width; - par->height = codec->height; - par->field_order = codec->field_order; - par->color_range = codec->color_range; - par->color_primaries = codec->color_primaries; - par->color_trc = codec->color_trc; - par->color_space = codec->colorspace; - par->chroma_location = codec->chroma_sample_location; - par->sample_aspect_ratio = codec->sample_aspect_ratio; - par->video_delay = codec->has_b_frames; - break; - case AVMEDIA_TYPE_AUDIO: - par->format = codec->sample_fmt; - par->channel_layout = codec->channel_layout; - par->channels = codec->channels; - par->sample_rate = codec->sample_rate; - par->block_align = codec->block_align; - par->frame_size = codec->frame_size; - par->initial_padding = codec->initial_padding; - par->trailing_padding = codec->trailing_padding; - par->seek_preroll = codec->seek_preroll; - break; - case AVMEDIA_TYPE_SUBTITLE: - par->width = codec->width; - par->height = codec->height; - break; - } - - if (codec->extradata) { - par->extradata = av_mallocz(codec->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!par->extradata) - return AVERROR(ENOMEM); - memcpy(par->extradata, codec->extradata, codec->extradata_size); - par->extradata_size = codec->extradata_size; - } - - return 0; -} - -int avcodec_parameters_to_context(AVCodecContext *codec, - const AVCodecParameters *par) -{ - codec->codec_type = par->codec_type; - codec->codec_id = par->codec_id; - codec->codec_tag = par->codec_tag; - - codec->bit_rate = par->bit_rate; - codec->bits_per_coded_sample = par->bits_per_coded_sample; - codec->bits_per_raw_sample = par->bits_per_raw_sample; - codec->profile = par->profile; - codec->level = par->level; - - switch (par->codec_type) { - case AVMEDIA_TYPE_VIDEO: - codec->pix_fmt = par->format; - codec->width = par->width; - codec->height = par->height; - codec->field_order = par->field_order; - codec->color_range = par->color_range; - codec->color_primaries = par->color_primaries; - codec->color_trc = par->color_trc; - codec->colorspace = par->color_space; - codec->chroma_sample_location = par->chroma_location; - codec->sample_aspect_ratio = par->sample_aspect_ratio; - codec->has_b_frames = par->video_delay; - break; - case AVMEDIA_TYPE_AUDIO: - codec->sample_fmt = par->format; - codec->channel_layout = par->channel_layout; - codec->channels = par->channels; - codec->sample_rate = par->sample_rate; - codec->block_align = par->block_align; - codec->frame_size = par->frame_size; - codec->delay = - codec->initial_padding = par->initial_padding; - codec->trailing_padding = par->trailing_padding; - codec->seek_preroll = par->seek_preroll; - break; - case AVMEDIA_TYPE_SUBTITLE: - codec->width = par->width; - codec->height = par->height; - break; - } - - if (par->extradata) { - av_freep(&codec->extradata); - codec->extradata = av_mallocz(par->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!codec->extradata) - return AVERROR(ENOMEM); - memcpy(codec->extradata, par->extradata, par->extradata_size); - codec->extradata_size = par->extradata_size; - } - - return 0; + unsigned low = bcd & 0xf; + unsigned high = bcd >> 4; + if (low > 9 || high > 9) + return 0; + return low + 10*high; } -int ff_alloc_a53_sei(const AVFrame *frame, size_t prefix_len, +int ff_alloc_timecode_sei(const AVFrame *frame, AVRational rate, size_t prefix_len, void **data, size_t *sei_size) { - AVFrameSideData *side_data = NULL; + AVFrameSideData *sd = NULL; uint8_t *sei_data; + PutBitContext pb; + uint32_t *tc; + int m; if (frame) - side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC); + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_S12M_TIMECODE); - if (!side_data) { + if (!sd) { *data = NULL; return 0; } + tc = (uint32_t*)sd->data; + m = tc[0] & 3; - *sei_size = side_data->size + 11; + *sei_size = sizeof(uint32_t) * 4; *data = av_mallocz(*sei_size + prefix_len); if (!*data) return AVERROR(ENOMEM); sei_data = (uint8_t*)*data + prefix_len; - // country code - sei_data[0] = 181; - sei_data[1] = 0; - sei_data[2] = 49; - - /** - * 'GA94' is standard in North America for ATSC, but hard coding - * this style may not be the right thing to do -- other formats - * do exist. This information is not available in the side_data - * so we are going with this right now. - */ - AV_WL32(sei_data + 3, MKTAG('G', 'A', '9', '4')); - sei_data[7] = 3; - sei_data[8] = ((side_data->size/3) & 0x1f) | 0x40; - sei_data[9] = 0; + init_put_bits(&pb, sei_data, *sei_size); + put_bits(&pb, 2, m); // num_clock_ts - memcpy(sei_data + 10, side_data->data, side_data->size); - - sei_data[side_data->size+10] = 255; + for (int j = 1; j <= m; j++) { + uint32_t tcsmpte = tc[j]; + unsigned hh = bcd2uint(tcsmpte & 0x3f); // 6-bit hours + unsigned mm = bcd2uint(tcsmpte>>8 & 0x7f); // 7-bit minutes + unsigned ss = bcd2uint(tcsmpte>>16 & 0x7f); // 7-bit seconds + unsigned ff = bcd2uint(tcsmpte>>24 & 0x3f); // 6-bit frames + unsigned drop = tcsmpte & 1<<30 && !0; // 1-bit drop if not arbitrary bit + + /* Calculate frame number of HEVC by SMPTE ST 12-1:2014 Sec 12.2 if rate > 30FPS */ + if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) { + unsigned pc; + ff *= 2; + if (av_cmp_q(rate, (AVRational) {50, 1}) == 0) + pc = !!(tcsmpte & 1 << 7); + else + pc = !!(tcsmpte & 1 << 23); + ff = (ff + pc) & 0x7f; + } + + put_bits(&pb, 1, 1); // clock_timestamp_flag + put_bits(&pb, 1, 1); // units_field_based_flag + put_bits(&pb, 5, 0); // counting_type + put_bits(&pb, 1, 1); // full_timestamp_flag + put_bits(&pb, 1, 0); // discontinuity_flag + put_bits(&pb, 1, drop); + put_bits(&pb, 9, ff); + put_bits(&pb, 6, ss); + put_bits(&pb, 6, mm); + put_bits(&pb, 5, hh); + put_bits(&pb, 5, 0); + } + flush_put_bits(&pb); return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/utvideo.c ffmpeg-4.4/libavcodec/utvideo.c --- ffmpeg-4.2.2/libavcodec/utvideo.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/utvideo.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -/* - * Common Ut Video code - * Copyright (c) 2011 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 - */ - -/** - * @file - * Common Ut Video code - */ - -#include "utvideo.h" - -#if FF_API_PRIVATE_OPT -const int ff_ut_pred_order[5] = { - PRED_LEFT, PRED_MEDIAN, PRED_MEDIAN, PRED_NONE, PRED_GRADIENT -}; -#endif - -const int ff_ut_rgb_order[4] = { 1, 2, 0, 3 }; // G, B, R, A - -int ff_ut_huff_cmp_len(const void *a, const void *b) -{ - const HuffEntry *aa = a, *bb = b; - return (aa->len - bb->len)*256 + aa->sym - bb->sym; -} - -int ff_ut10_huff_cmp_len(const void *a, const void *b) -{ - const HuffEntry *aa = a, *bb = b; - return (aa->len - bb->len)*1024 + aa->sym - bb->sym; -} diff -Nru ffmpeg-4.2.2/libavcodec/utvideodec.c ffmpeg-4.4/libavcodec/utvideodec.c --- ffmpeg-4.2.2/libavcodec/utvideodec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/utvideodec.c 2021-04-08 21:28:39.000000000 +0000 @@ -40,91 +40,51 @@ #include "thread.h" #include "utvideo.h" -static int build_huff10(const uint8_t *src, VLC *vlc, int *fsym) +typedef struct HuffEntry { + uint8_t len; + uint16_t sym; +} HuffEntry; + +static int build_huff(UtvideoContext *c, const uint8_t *src, VLC *vlc, + int *fsym, unsigned nb_elems) { int i; HuffEntry he[1024]; - int last; - uint32_t codes[1024]; uint8_t bits[1024]; - uint16_t syms[1024]; - uint32_t code; + uint16_t codes_count[33] = { 0 }; *fsym = -1; - for (i = 0; i < 1024; i++) { - he[i].sym = i; - he[i].len = *src++; - } - qsort(he, 1024, sizeof(*he), ff_ut10_huff_cmp_len); - - if (!he[0].len) { - *fsym = he[0].sym; - return 0; - } - - last = 1023; - while (he[last].len == 255 && last) - last--; - - if (he[last].len > 32) { - return -1; - } + for (i = 0; i < nb_elems; i++) { + if (src[i] == 0) { + *fsym = i; + return 0; + } else if (src[i] == 255) { + bits[i] = 0; + } else if (src[i] <= 32) { + bits[i] = src[i]; + } else + return AVERROR_INVALIDDATA; - code = 1; - for (i = last; i >= 0; i--) { - codes[i] = code >> (32 - he[i].len); - bits[i] = he[i].len; - syms[i] = he[i].sym; - code += 0x80000000u >> (he[i].len - 1); + codes_count[bits[i]]++; } -#define VLC_BITS 11 - return ff_init_vlc_sparse(vlc, VLC_BITS, last + 1, - bits, sizeof(*bits), sizeof(*bits), - codes, sizeof(*codes), sizeof(*codes), - syms, sizeof(*syms), sizeof(*syms), 0); -} + if (codes_count[0] == nb_elems) + return AVERROR_INVALIDDATA; -static int build_huff(const uint8_t *src, VLC *vlc, int *fsym) -{ - int i; - HuffEntry he[256]; - int last; - uint32_t codes[256]; - uint8_t bits[256]; - uint8_t syms[256]; - uint32_t code; + /* For Ut Video, longer codes are to the left of the tree and + * for codes with the same length the symbol is descending from + * left to right. So after the next loop --codes_count[i] will + * be the index of the first (lowest) symbol of length i when + * indexed by the position in the tree with left nodes being first. */ + for (int i = 31; i >= 0; i--) + codes_count[i] += codes_count[i + 1]; - *fsym = -1; - for (i = 0; i < 256; i++) { - he[i].sym = i; - he[i].len = *src++; - } - qsort(he, 256, sizeof(*he), ff_ut_huff_cmp_len); + for (unsigned i = 0; i < nb_elems; i++) + he[--codes_count[bits[i]]] = (HuffEntry) { bits[i], i }; - if (!he[0].len) { - *fsym = he[0].sym; - return 0; - } - - last = 255; - while (he[last].len == 255 && last) - last--; - - if (he[last].len > 32) - return -1; - - code = 1; - for (i = last; i >= 0; i--) { - codes[i] = code >> (32 - he[i].len); - bits[i] = he[i].len; - syms[i] = he[i].sym; - code += 0x80000000u >> (he[i].len - 1); - } - - return ff_init_vlc_sparse(vlc, VLC_BITS, last + 1, - bits, sizeof(*bits), sizeof(*bits), - codes, sizeof(*codes), sizeof(*codes), - syms, sizeof(*syms), sizeof(*syms), 0); +#define VLC_BITS 11 + return ff_init_vlc_from_lengths(vlc, VLC_BITS, codes_count[0], + &he[0].len, sizeof(*he), + &he[0].sym, sizeof(*he), 2, 0, 0, c->avctx); } static int decode_plane10(UtvideoContext *c, int plane_no, @@ -139,7 +99,7 @@ GetBitContext gb; int prev, fsym; - if ((ret = build_huff10(huff, &vlc, &fsym)) < 0) { + if ((ret = build_huff(c, huff, &vlc, &fsym, 1024)) < 0) { av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); return ret; } @@ -299,7 +259,7 @@ return 0; } - if (build_huff(src, &vlc, &fsym)) { + if (build_huff(c, src, &vlc, &fsym, 256)) { av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); return AVERROR_INVALIDDATA; } @@ -317,7 +277,7 @@ for (i = 0; i < width; i++) { pix = fsym; if (use_pred) { - prev += pix; + prev += (unsigned)pix; pix = prev; } dest[i] = pix; @@ -890,6 +850,15 @@ } } break; + case AV_PIX_FMT_YUV420P10: + for (i = 0; i < 3; i++) { + ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], frame.f->linesize[i] / 2, + avctx->width >> !!i, avctx->height >> !!i, + plane_start[i], plane_start[i + 1] - 1024, c->frame_pred == PRED_LEFT); + if (ret) + return ret; + } + break; case AV_PIX_FMT_YUV422P10: for (i = 0; i < 3; i++) { ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], frame.f->linesize[i] / 2, @@ -948,6 +917,11 @@ avctx->pix_fmt = AV_PIX_FMT_YUV444P; avctx->colorspace = AVCOL_SPC_BT470BG; break; + case MKTAG('U', 'Q', 'Y', '0'): + c->planes = 3; + c->pro = 1; + avctx->pix_fmt = AV_PIX_FMT_YUV420P10; + break; case MKTAG('U', 'Q', 'Y', '2'): c->planes = 3; c->pro = 1; diff -Nru ffmpeg-4.2.2/libavcodec/utvideoenc.c ffmpeg-4.4/libavcodec/utvideoenc.c --- ffmpeg-4.2.2/libavcodec/utvideoenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/utvideoenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -37,6 +37,25 @@ #include "utvideo.h" #include "huffman.h" +typedef struct HuffEntry { + uint16_t sym; + uint8_t len; + uint32_t code; +} HuffEntry; + +#if FF_API_PRIVATE_OPT +static const int ut_pred_order[5] = { + PRED_LEFT, PRED_MEDIAN, PRED_MEDIAN, PRED_NONE, PRED_GRADIENT +}; +#endif + +/* Compare huffman tree nodes */ +static int ut_huff_cmp_len(const void *a, const void *b) +{ + const HuffEntry *aa = a, *bb = b; + return (aa->len - bb->len)*256 + aa->sym - bb->sym; +} + /* Compare huffentry symbols */ static int huff_cmp_sym(const void *a, const void *b) { @@ -139,7 +158,7 @@ /* Convert from libavcodec prediction type to Ut Video's */ if (avctx->prediction_method) - c->frame_pred = ff_ut_pred_order[avctx->prediction_method]; + c->frame_pred = ut_pred_order[avctx->prediction_method]; FF_ENABLE_DEPRECATION_WARNINGS #endif @@ -340,13 +359,13 @@ int last, i; uint32_t code; - qsort(he, 256, sizeof(*he), ff_ut_huff_cmp_len); + qsort(he, 256, sizeof(*he), ut_huff_cmp_len); last = 255; while (he[last].len == 255 && last) last--; - code = 1; + code = 0; for (i = last; i >= 0; i--) { he[i].code = code >> (32 - he[i].len); code += 0x80000000u >> (he[i].len - 1); @@ -677,7 +696,7 @@ .init = utvideo_encode_init, .encode2 = utvideo_encode_frame, .close = utvideo_encode_close, - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE diff -Nru ffmpeg-4.2.2/libavcodec/utvideo.h ffmpeg-4.4/libavcodec/utvideo.h --- ffmpeg-4.2.2/libavcodec/utvideo.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/utvideo.h 2021-04-08 21:28:39.000000000 +0000 @@ -61,9 +61,6 @@ UTVIDEO_444 = MKTAG('Y', 'V', '2', '4'), }; -/* Mapping of libavcodec prediction modes to Ut Video's */ -extern const int ff_ut_pred_order[5]; - typedef struct UtvideoContext { const AVClass *class; AVCodecContext *avctx; @@ -91,14 +88,4 @@ size_t control_stream_size[4][256]; } UtvideoContext; -typedef struct HuffEntry { - uint16_t sym; - uint8_t len; - uint32_t code; -} HuffEntry; - -/* Compare huffman tree nodes */ -int ff_ut_huff_cmp_len(const void *a, const void *b); -int ff_ut10_huff_cmp_len(const void *a, const void *b); - #endif /* AVCODEC_UTVIDEO_H */ diff -Nru ffmpeg-4.2.2/libavcodec/v210dec.c ffmpeg-4.4/libavcodec/v210dec.c --- ffmpeg-4.2.2/libavcodec/v210dec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v210dec.c 2020-07-11 10:39:30.000000000 +0000 @@ -28,6 +28,7 @@ #include "libavutil/internal.h" #include "libavutil/mem.h" #include "libavutil/intreadwrite.h" +#include "thread.h" #define READ_PIXELS(a, b, c) \ do { \ @@ -37,6 +38,12 @@ *c++ = (val >> 20) & 0x3FF; \ } while (0) +typedef struct ThreadData { + AVFrame *frame; + uint8_t *buf; + int stride; +} ThreadData; + static void v210_planar_unpack_c(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width) { uint32_t val; @@ -64,21 +71,81 @@ avctx->pix_fmt = AV_PIX_FMT_YUV422P10; avctx->bits_per_raw_sample = 10; + s->thread_count = av_clip(avctx->thread_count, 1, avctx->height/4); s->aligned_input = 0; ff_v210dec_init(s); return 0; } +static int v210_decode_slice(AVCodecContext *avctx, void *arg, int jobnr, int threadnr) +{ + V210DecContext *s = avctx->priv_data; + int h, w; + ThreadData *td = arg; + AVFrame *frame = td->frame; + int stride = td->stride; + int slice_start = (avctx->height * jobnr) / s->thread_count; + int slice_end = (avctx->height * (jobnr+1)) / s->thread_count; + uint8_t *psrc = td->buf + stride * slice_start; + uint16_t *y, *u, *v; + + y = (uint16_t*)frame->data[0] + slice_start * frame->linesize[0] / 2; + u = (uint16_t*)frame->data[1] + slice_start * frame->linesize[1] / 2; + v = (uint16_t*)frame->data[2] + slice_start * frame->linesize[2] / 2; + for (h = slice_start; h < slice_end; h++) { + const uint32_t *src = (const uint32_t*)psrc; + uint32_t val; + + w = (avctx->width / 12) * 12; + s->unpack_frame(src, y, u, v, w); + + y += w; + u += w >> 1; + v += w >> 1; + src += (w << 1) / 3; + + if (w < avctx->width - 5) { + READ_PIXELS(u, y, v); + READ_PIXELS(y, u, y); + READ_PIXELS(v, y, u); + READ_PIXELS(y, v, y); + w += 6; + } + + if (w < avctx->width - 1) { + READ_PIXELS(u, y, v); + + val = av_le2ne32(*src++); + *y++ = val & 0x3FF; + if (w < avctx->width - 3) { + *u++ = (val >> 10) & 0x3FF; + *y++ = (val >> 20) & 0x3FF; + + val = av_le2ne32(*src++); + *v++ = val & 0x3FF; + *y++ = (val >> 10) & 0x3FF; + } + } + + psrc += stride; + y += frame->linesize[0] / 2 - avctx->width + (avctx->width & 1); + u += frame->linesize[1] / 2 - avctx->width / 2; + v += frame->linesize[2] / 2 - avctx->width / 2; + } + + return 0; +} + static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { V210DecContext *s = avctx->priv_data; - - int h, w, ret, stride, aligned_input; + ThreadData td; + int ret, stride, aligned_input; + ThreadFrame frame = { .f = data }; AVFrame *pic = data; const uint8_t *psrc = avpkt->data; - uint16_t *y, *u, *v; if (s->custom_stride ) stride = s->custom_stride; @@ -98,6 +165,7 @@ return AVERROR_INVALIDDATA; } } + td.stride = stride; if ( avctx->codec_tag == MKTAG('C', '2', '1', '0') && avpkt->size > 64 && AV_RN32(psrc) == AV_RN32("INFO") @@ -110,55 +178,15 @@ ff_v210dec_init(s); } - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; - y = (uint16_t*)pic->data[0]; - u = (uint16_t*)pic->data[1]; - v = (uint16_t*)pic->data[2]; pic->pict_type = AV_PICTURE_TYPE_I; pic->key_frame = 1; - for (h = 0; h < avctx->height; h++) { - const uint32_t *src = (const uint32_t*)psrc; - uint32_t val; - - w = (avctx->width / 12) * 12; - s->unpack_frame(src, y, u, v, w); - - y += w; - u += w >> 1; - v += w >> 1; - src += (w << 1) / 3; - - if (w < avctx->width - 5) { - READ_PIXELS(u, y, v); - READ_PIXELS(y, u, y); - READ_PIXELS(v, y, u); - READ_PIXELS(y, v, y); - w += 6; - } - - if (w < avctx->width - 1) { - READ_PIXELS(u, y, v); - - val = av_le2ne32(*src++); - *y++ = val & 0x3FF; - if (w < avctx->width - 3) { - *u++ = (val >> 10) & 0x3FF; - *y++ = (val >> 20) & 0x3FF; - - val = av_le2ne32(*src++); - *v++ = val & 0x3FF; - *y++ = (val >> 10) & 0x3FF; - } - } - - psrc += stride; - y += pic->linesize[0] / 2 - avctx->width + (avctx->width & 1); - u += pic->linesize[1] / 2 - avctx->width / 2; - v += pic->linesize[2] / 2 - avctx->width / 2; - } + td.buf = (uint8_t*)psrc; + td.frame = pic; + avctx->execute2(avctx, v210_decode_slice, &td, NULL, s->thread_count); if (avctx->field_order > AV_FIELD_PROGRESSIVE) { /* we have interlaced material flagged in container */ @@ -194,6 +222,8 @@ .priv_data_size = sizeof(V210DecContext), .init = decode_init, .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | + AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_FRAME_THREADS, .priv_class = &v210dec_class, }; diff -Nru ffmpeg-4.2.2/libavcodec/v210dec.h ffmpeg-4.4/libavcodec/v210dec.h --- ffmpeg-4.2.2/libavcodec/v210dec.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v210dec.h 2020-07-11 10:39:30.000000000 +0000 @@ -27,6 +27,7 @@ AVClass *av_class; int custom_stride; int aligned_input; + int thread_count; int stride_warning_shown; void (*unpack_frame)(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width); } V210DecContext; diff -Nru ffmpeg-4.2.2/libavcodec/v210enc.c ffmpeg-4.4/libavcodec/v210enc.c --- ffmpeg-4.2.2/libavcodec/v210enc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v210enc.c 2020-07-11 10:39:30.000000000 +0000 @@ -26,26 +26,25 @@ #include "internal.h" #include "v210enc.h" -#define CLIP(v) av_clip(v, 4, 1019) -#define CLIP8(v) av_clip(v, 1, 254) - -#define WRITE_PIXELS(a, b, c) \ - do { \ - val = CLIP(*a++); \ - val |= (CLIP(*b++) << 10) | \ - (CLIP(*c++) << 20); \ - AV_WL32(dst, val); \ - dst += 4; \ - } while (0) - -#define WRITE_PIXELS8(a, b, c) \ - do { \ - val = (CLIP8(*a++) << 2); \ - val |= (CLIP8(*b++) << 12) | \ - (CLIP8(*c++) << 22); \ - AV_WL32(dst, val); \ - dst += 4; \ - } while (0) +#define TYPE uint8_t +#define DEPTH 8 +#define BYTES_PER_PIXEL 1 +#define RENAME(a) a ## _ ## 8 +#include "v210_template.c" +#undef RENAME +#undef DEPTH +#undef BYTES_PER_PIXEL +#undef TYPE + +#define TYPE uint16_t +#define DEPTH 10 +#define BYTES_PER_PIXEL 2 +#define RENAME(a) a ## _ ## 10 +#include "v210_template.c" +#undef RENAME +#undef DEPTH +#undef BYTES_PER_PIXEL +#undef TYPE static void v210_planar_pack_8_c(const uint8_t *y, const uint8_t *u, const uint8_t *v, uint8_t *dst, @@ -56,14 +55,14 @@ /* unroll this to match the assembly */ for (i = 0; i < width - 11; i += 12) { - WRITE_PIXELS8(u, y, v); - WRITE_PIXELS8(y, u, y); - WRITE_PIXELS8(v, y, u); - WRITE_PIXELS8(y, v, y); - WRITE_PIXELS8(u, y, v); - WRITE_PIXELS8(y, u, y); - WRITE_PIXELS8(v, y, u); - WRITE_PIXELS8(y, v, y); + WRITE_PIXELS(u, y, v, 8); + WRITE_PIXELS(y, u, y, 8); + WRITE_PIXELS(v, y, u, 8); + WRITE_PIXELS(y, v, y, 8); + WRITE_PIXELS(u, y, v, 8); + WRITE_PIXELS(y, u, y, 8); + WRITE_PIXELS(v, y, u, 8); + WRITE_PIXELS(y, v, y, 8); } } @@ -75,10 +74,10 @@ int i; for (i = 0; i < width - 5; i += 6) { - WRITE_PIXELS(u, y, v); - WRITE_PIXELS(y, u, y); - WRITE_PIXELS(v, y, u); - WRITE_PIXELS(y, v, y); + WRITE_PIXELS(u, y, v, 10); + WRITE_PIXELS(y, u, y, 10); + WRITE_PIXELS(v, y, u, 10); + WRITE_PIXELS(y, v, y, 10); } } @@ -86,7 +85,7 @@ { s->pack_line_8 = v210_planar_pack_8_c; s->pack_line_10 = v210_planar_pack_10_c; - s->sample_factor_8 = 1; + s->sample_factor_8 = 2; s->sample_factor_10 = 1; if (ARCH_X86) @@ -119,12 +118,10 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pic, int *got_packet) { - V210EncContext *s = avctx->priv_data; int aligned_width = ((avctx->width + 47) / 48) * 48; int stride = aligned_width * 8 / 3; - int line_padding = stride - ((avctx->width * 8 + 11) / 12) * 4; AVFrameSideData *side_data; - int h, w, ret; + int ret; uint8_t *dst; ret = ff_alloc_packet2(avctx, pkt, avctx->height * stride, avctx->height * stride); @@ -134,105 +131,10 @@ } dst = pkt->data; - if (pic->format == AV_PIX_FMT_YUV422P10) { - const uint16_t *y = (const uint16_t *)pic->data[0]; - const uint16_t *u = (const uint16_t *)pic->data[1]; - const uint16_t *v = (const uint16_t *)pic->data[2]; - - const int sample_size = 6 * s->sample_factor_10; - const int sample_w = avctx->width / sample_size; - - for (h = 0; h < avctx->height; h++) { - uint32_t val; - w = sample_w * sample_size; - s->pack_line_10(y, u, v, dst, w); - - y += w; - u += w >> 1; - v += w >> 1; - dst += sample_w * 16 * s->sample_factor_10; - - for (; w < avctx->width - 5; w += 6) { - WRITE_PIXELS(u, y, v); - WRITE_PIXELS(y, u, y); - WRITE_PIXELS(v, y, u); - WRITE_PIXELS(y, v, y); - } - if (w < avctx->width - 1) { - WRITE_PIXELS(u, y, v); - - val = CLIP(*y++); - if (w == avctx->width - 2) { - AV_WL32(dst, val); - dst += 4; - } - } - if (w < avctx->width - 3) { - val |= (CLIP(*u++) << 10) | (CLIP(*y++) << 20); - AV_WL32(dst, val); - dst += 4; - - val = CLIP(*v++) | (CLIP(*y++) << 10); - AV_WL32(dst, val); - dst += 4; - } - - memset(dst, 0, line_padding); - dst += line_padding; - y += pic->linesize[0] / 2 - avctx->width; - u += pic->linesize[1] / 2 - avctx->width / 2; - v += pic->linesize[2] / 2 - avctx->width / 2; - } - } else if(pic->format == AV_PIX_FMT_YUV422P) { - const uint8_t *y = pic->data[0]; - const uint8_t *u = pic->data[1]; - const uint8_t *v = pic->data[2]; - - const int sample_size = 12 * s->sample_factor_8; - const int sample_w = avctx->width / sample_size; - - for (h = 0; h < avctx->height; h++) { - uint32_t val; - w = sample_w * sample_size; - s->pack_line_8(y, u, v, dst, w); - - y += w; - u += w >> 1; - v += w >> 1; - dst += sample_w * 32 * s->sample_factor_8; - - for (; w < avctx->width - 5; w += 6) { - WRITE_PIXELS8(u, y, v); - WRITE_PIXELS8(y, u, y); - WRITE_PIXELS8(v, y, u); - WRITE_PIXELS8(y, v, y); - } - if (w < avctx->width - 1) { - WRITE_PIXELS8(u, y, v); - - val = CLIP8(*y++) << 2; - if (w == avctx->width - 2) { - AV_WL32(dst, val); - dst += 4; - } - } - if (w < avctx->width - 3) { - val |= (CLIP8(*u++) << 12) | (CLIP8(*y++) << 22); - AV_WL32(dst, val); - dst += 4; - - val = (CLIP8(*v++) << 2) | (CLIP8(*y++) << 12); - AV_WL32(dst, val); - dst += 4; - } - memset(dst, 0, line_padding); - dst += line_padding; - - y += pic->linesize[0] - avctx->width; - u += pic->linesize[1] - avctx->width / 2; - v += pic->linesize[2] - avctx->width / 2; - } - } + if (pic->format == AV_PIX_FMT_YUV422P10) + v210_enc_10(avctx, dst, pic); + else if(pic->format == AV_PIX_FMT_YUV422P) + v210_enc_8(avctx, dst, pic); side_data = av_frame_get_side_data(pic, AV_FRAME_DATA_A53_CC); if (side_data && side_data->size) { diff -Nru ffmpeg-4.2.2/libavcodec/v210_template.c ffmpeg-4.4/libavcodec/v210_template.c --- ffmpeg-4.2.2/libavcodec/v210_template.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v210_template.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2009 Michael Niedermayer + * Copyright (c) 2009 Baptiste Coudurier + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "bytestream.h" +#include "internal.h" + +#define CLIP(v, depth) av_clip(v, 1<<(depth-8), ((1<priv_data; + int aligned_width = ((avctx->width + 47) / 48) * 48; + int stride = aligned_width * 8 / 3; + int line_padding = stride - ((avctx->width * 8 + 11) / 12) * 4; + int h, w; + const TYPE *y = (const TYPE *)pic->data[0]; + const TYPE *u = (const TYPE *)pic->data[1]; + const TYPE *v = (const TYPE *)pic->data[2]; + const int sample_size = 6 * s->RENAME(sample_factor); + const int sample_w = avctx->width / sample_size; + + for (h = 0; h < avctx->height; h++) { + uint32_t val; + w = sample_w * sample_size; + s->RENAME(pack_line)(y, u, v, dst, w); + + y += w; + u += w >> 1; + v += w >> 1; + dst += sample_w * 16 * s->RENAME(sample_factor); + + for (; w < avctx->width - 5; w += 6) { + WRITE_PIXELS(u, y, v, DEPTH); + WRITE_PIXELS(y, u, y, DEPTH); + WRITE_PIXELS(v, y, u, DEPTH); + WRITE_PIXELS(y, v, y, DEPTH); + } + if (w < avctx->width - 1) { + WRITE_PIXELS(u, y, v, DEPTH); + + val = CLIP(*y++, DEPTH) << (10-DEPTH); + if (w == avctx->width - 2) { + AV_WL32(dst, val); + dst += 4; + } + } + if (w < avctx->width - 3) { + val |= (CLIP(*u++, DEPTH) << (20-DEPTH)) | (CLIP(*y++, DEPTH) << (30-DEPTH)); + AV_WL32(dst, val); + dst += 4; + + val = CLIP(*v++, DEPTH) << (10-DEPTH) | (CLIP(*y++, DEPTH) << (20-DEPTH)); + AV_WL32(dst, val); + dst += 4; + } + + memset(dst, 0, line_padding); + dst += line_padding; + y += pic->linesize[0] / BYTES_PER_PIXEL - avctx->width; + u += pic->linesize[1] / BYTES_PER_PIXEL - avctx->width / 2; + v += pic->linesize[2] / BYTES_PER_PIXEL - avctx->width / 2; + } +} diff -Nru ffmpeg-4.2.2/libavcodec/v308enc.c ffmpeg-4.4/libavcodec/v308enc.c --- ffmpeg-4.2.2/libavcodec/v308enc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v308enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -68,11 +68,6 @@ return 0; } -static av_cold int v308_encode_close(AVCodecContext *avctx) -{ - return 0; -} - AVCodec ff_v308_encoder = { .name = "v308", .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:4:4"), @@ -80,7 +75,5 @@ .id = AV_CODEC_ID_V308, .init = v308_encode_init, .encode2 = v308_encode_frame, - .close = v308_encode_close, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, - .capabilities = AV_CODEC_CAP_INTRA_ONLY, }; diff -Nru ffmpeg-4.2.2/libavcodec/v408enc.c ffmpeg-4.4/libavcodec/v408enc.c --- ffmpeg-4.2.2/libavcodec/v408enc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v408enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -73,11 +73,6 @@ return 0; } -static av_cold int v408_encode_close(AVCodecContext *avctx) -{ - return 0; -} - #if CONFIG_AYUV_ENCODER AVCodec ff_ayuv_encoder = { .name = "ayuv", @@ -86,9 +81,7 @@ .id = AV_CODEC_ID_AYUV, .init = v408_encode_init, .encode2 = v408_encode_frame, - .close = v408_encode_close, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE }, - .capabilities = AV_CODEC_CAP_INTRA_ONLY, }; #endif #if CONFIG_V408_ENCODER @@ -99,8 +92,6 @@ .id = AV_CODEC_ID_V408, .init = v408_encode_init, .encode2 = v408_encode_frame, - .close = v408_encode_close, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE }, - .capabilities = AV_CODEC_CAP_INTRA_ONLY, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/v410dec.c ffmpeg-4.4/libavcodec/v410dec.c --- ffmpeg-4.2.2/libavcodec/v410dec.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v410dec.c 2020-07-11 10:39:30.000000000 +0000 @@ -24,6 +24,13 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "internal.h" +#include "thread.h" + +typedef struct ThreadData { + AVFrame *frame; + uint8_t *buf; + int stride; +} ThreadData; static av_cold int v410_decode_init(AVCodecContext *avctx) { @@ -42,31 +49,24 @@ return 0; } -static int v410_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame, AVPacket *avpkt) +static int v410_decode_slice(AVCodecContext *avctx, void *arg, int jobnr, int threadnr) { - AVFrame *pic = data; - uint8_t *src = avpkt->data; + ThreadData *td = arg; + AVFrame *pic = td->frame; + int stride = td->stride; + int thread_count = av_clip(avctx->thread_count, 1, avctx->height/4); + int slice_start = (avctx->height * jobnr) / thread_count; + int slice_end = (avctx->height * (jobnr+1)) / thread_count; + const uint8_t *src = td->buf + stride * slice_start; uint16_t *y, *u, *v; uint32_t val; - int i, j, ret; - - if (avpkt->size < 4 * avctx->height * avctx->width) { - av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n"); - return AVERROR(EINVAL); - } - - if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) - return ret; + int i, j; - pic->key_frame = 1; - pic->pict_type = AV_PICTURE_TYPE_I; + y = (uint16_t*)pic->data[0] + slice_start * (pic->linesize[0] >> 1); + u = (uint16_t*)pic->data[1] + slice_start * (pic->linesize[1] >> 1); + v = (uint16_t*)pic->data[2] + slice_start * (pic->linesize[2] >> 1); - y = (uint16_t *)pic->data[0]; - u = (uint16_t *)pic->data[1]; - v = (uint16_t *)pic->data[2]; - - for (i = 0; i < avctx->height; i++) { + for (i = slice_start; i < slice_end; i++) { for (j = 0; j < avctx->width; j++) { val = AV_RL32(src); @@ -82,6 +82,35 @@ v += pic->linesize[2] >> 1; } + return 0; +} + +static int v410_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + ThreadData td; + ThreadFrame frame = { .f = data }; + AVFrame *pic = data; + uint8_t *src = avpkt->data; + int ret; + int thread_count = av_clip(avctx->thread_count, 1, avctx->height/4); + + td.stride = avctx->width * 4; + if (avpkt->size < 4 * avctx->height * avctx->width) { + av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n"); + return AVERROR(EINVAL); + } + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + pic->key_frame = 1; + pic->pict_type = AV_PICTURE_TYPE_I; + + td.buf = src; + td.frame = pic; + avctx->execute2(avctx, v410_decode_slice, &td, NULL, thread_count); + *got_frame = 1; return avpkt->size; @@ -94,5 +123,6 @@ .id = AV_CODEC_ID_V410, .init = v410_decode_init, .decode = v410_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_FRAME_THREADS }; diff -Nru ffmpeg-4.2.2/libavcodec/v4l2_buffers.c ffmpeg-4.4/libavcodec/v4l2_buffers.c --- ffmpeg-4.2.2/libavcodec/v4l2_buffers.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v4l2_buffers.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,11 +29,13 @@ #include #include "libavcodec/avcodec.h" #include "libavcodec/internal.h" +#include "libavutil/pixdesc.h" #include "v4l2_context.h" #include "v4l2_buffers.h" #include "v4l2_m2m.h" #define USEC_PER_SEC 1000000 +static AVRational v4l2_timebase = { 1, USEC_PER_SEC }; static inline V4L2m2mContext *buf_to_m2mctx(V4L2Buffer *buf) { @@ -47,32 +49,37 @@ return buf_to_m2mctx(buf)->avctx; } +static inline AVRational v4l2_get_timebase(V4L2Buffer *avbuf) +{ + V4L2m2mContext *s = buf_to_m2mctx(avbuf); + + if (s->avctx->pkt_timebase.num) + return s->avctx->pkt_timebase; + return s->avctx->time_base; +} + static inline void v4l2_set_pts(V4L2Buffer *out, int64_t pts) { - V4L2m2mContext *s = buf_to_m2mctx(out); - AVRational v4l2_timebase = { 1, USEC_PER_SEC }; int64_t v4l2_pts; if (pts == AV_NOPTS_VALUE) pts = 0; /* convert pts to v4l2 timebase */ - v4l2_pts = av_rescale_q(pts, s->avctx->time_base, v4l2_timebase); + v4l2_pts = av_rescale_q(pts, v4l2_get_timebase(out), v4l2_timebase); out->buf.timestamp.tv_usec = v4l2_pts % USEC_PER_SEC; out->buf.timestamp.tv_sec = v4l2_pts / USEC_PER_SEC; } -static inline uint64_t v4l2_get_pts(V4L2Buffer *avbuf) +static inline int64_t v4l2_get_pts(V4L2Buffer *avbuf) { - V4L2m2mContext *s = buf_to_m2mctx(avbuf); - AVRational v4l2_timebase = { 1, USEC_PER_SEC }; int64_t v4l2_pts; /* convert pts back to encoder timebase */ v4l2_pts = (int64_t)avbuf->buf.timestamp.tv_sec * USEC_PER_SEC + avbuf->buf.timestamp.tv_usec; - return av_rescale_q(v4l2_pts, v4l2_timebase, s->avctx->time_base); + return av_rescale_q(v4l2_pts, v4l2_timebase, v4l2_get_timebase(avbuf)); } static enum AVColorPrimaries v4l2_get_color_primaries(V4L2Buffer *buf) @@ -215,7 +222,7 @@ if (!atomic_load(&s->refcount)) sem_post(&s->refsync); } else { - if (s->draining) { + if (s->draining && V4L2_TYPE_IS_OUTPUT(avbuf->context->type)) { /* no need to queue more buffers to the driver */ avbuf->status = V4L2BUF_AVAILABLE; } @@ -227,27 +234,17 @@ } } -static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) +static int v4l2_buf_increase_ref(V4L2Buffer *in) { V4L2m2mContext *s = buf_to_m2mctx(in); - if (plane >= in->num_planes) - return AVERROR(EINVAL); - - /* even though most encoders return 0 in data_offset encoding vp8 does require this value */ - *buf = av_buffer_create((char *)in->plane_info[plane].mm_addr + in->planes[plane].data_offset, - in->plane_info[plane].length, v4l2_free_buffer, in, 0); - if (!*buf) - return AVERROR(ENOMEM); - if (in->context_ref) atomic_fetch_add(&in->context_refcount, 1); else { in->context_ref = av_buffer_ref(s->self_ref); - if (!in->context_ref) { - av_buffer_unref(buf); + if (!in->context_ref) return AVERROR(ENOMEM); - } + in->context_refcount = 1; } @@ -257,17 +254,37 @@ return 0; } -static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, AVBufferRef* bref) +static int v4l2_buf_to_bufref(V4L2Buffer *in, int plane, AVBufferRef **buf) +{ + int ret; + + if (plane >= in->num_planes) + return AVERROR(EINVAL); + + /* even though most encoders return 0 in data_offset encoding vp8 does require this value */ + *buf = av_buffer_create((char *)in->plane_info[plane].mm_addr + in->planes[plane].data_offset, + in->plane_info[plane].length, v4l2_free_buffer, in, 0); + if (!*buf) + return AVERROR(ENOMEM); + + ret = v4l2_buf_increase_ref(in); + if (ret) + av_buffer_unref(buf); + + return ret; +} + +static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, int size, int offset) { unsigned int bytesused, length; if (plane >= out->num_planes) return AVERROR(EINVAL); - bytesused = FFMIN(size, out->plane_info[plane].length); length = out->plane_info[plane].length; + bytesused = FFMIN(size+offset, length); - memcpy(out->plane_info[plane].mm_addr, data, FFMIN(size, out->plane_info[plane].length)); + memcpy((uint8_t*)out->plane_info[plane].mm_addr+offset, data, FFMIN(size, length-offset)); if (V4L2_TYPE_IS_MULTIPLANAR(out->buf.type)) { out->planes[plane].bytesused = bytesused; @@ -280,35 +297,12 @@ return 0; } -/****************************************************************************** - * - * V4L2uffer interface - * - ******************************************************************************/ - -int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer* out) -{ - int i, ret; - - for(i = 0; i < out->num_planes; i++) { - ret = v4l2_bufref_to_buf(out, i, frame->buf[i]->data, frame->buf[i]->size, frame->buf[i]); - if (ret) - return ret; - } - - v4l2_set_pts(out, frame->pts); - - return 0; -} - -int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) +static int v4l2_buffer_buf_to_swframe(AVFrame *frame, V4L2Buffer *avbuf) { - V4L2m2mContext *s = buf_to_m2mctx(avbuf); int i, ret; - av_frame_unref(frame); + frame->format = avbuf->context->av_pix_fmt; - /* 1. get references to the actual data */ for (i = 0; i < avbuf->num_planes; i++) { ret = v4l2_buf_to_bufref(avbuf, i, &frame->buf[i]); if (ret) @@ -318,30 +312,134 @@ frame->data[i] = frame->buf[i]->data; } - /* 1.1 fixup special cases */ + /* fixup special cases */ switch (avbuf->context->av_pix_fmt) { case AV_PIX_FMT_NV12: + case AV_PIX_FMT_NV21: if (avbuf->num_planes > 1) break; frame->linesize[1] = avbuf->plane_info[0].bytesperline; frame->data[1] = frame->buf[0]->data + avbuf->plane_info[0].bytesperline * avbuf->context->format.fmt.pix_mp.height; break; + + case AV_PIX_FMT_YUV420P: + if (avbuf->num_planes > 1) + break; + frame->linesize[1] = avbuf->plane_info[0].bytesperline >> 1; + frame->linesize[2] = avbuf->plane_info[0].bytesperline >> 1; + frame->data[1] = frame->buf[0]->data + avbuf->plane_info[0].bytesperline * avbuf->context->format.fmt.pix_mp.height; + frame->data[2] = frame->data[1] + ((avbuf->plane_info[0].bytesperline * avbuf->context->format.fmt.pix_mp.height) >> 2); + break; + default: break; } + return 0; +} + +static int v4l2_buffer_swframe_to_buf(const AVFrame *frame, V4L2Buffer *out) +{ + int i, ret; + struct v4l2_format fmt = out->context->format; + int pixel_format = V4L2_TYPE_IS_MULTIPLANAR(fmt.type) ? + fmt.fmt.pix_mp.pixelformat : fmt.fmt.pix.pixelformat; + int height = V4L2_TYPE_IS_MULTIPLANAR(fmt.type) ? + fmt.fmt.pix_mp.height : fmt.fmt.pix.height; + int is_planar_format = 0; + + switch (pixel_format) { + case V4L2_PIX_FMT_YUV420M: + case V4L2_PIX_FMT_YVU420M: +#ifdef V4L2_PIX_FMT_YUV422M + case V4L2_PIX_FMT_YUV422M: +#endif +#ifdef V4L2_PIX_FMT_YVU422M + case V4L2_PIX_FMT_YVU422M: +#endif +#ifdef V4L2_PIX_FMT_YUV444M + case V4L2_PIX_FMT_YUV444M: +#endif +#ifdef V4L2_PIX_FMT_YVU444M + case V4L2_PIX_FMT_YVU444M: +#endif + case V4L2_PIX_FMT_NV12M: + case V4L2_PIX_FMT_NV21M: + case V4L2_PIX_FMT_NV12MT_16X16: + case V4L2_PIX_FMT_NV12MT: + case V4L2_PIX_FMT_NV16M: + case V4L2_PIX_FMT_NV61M: + is_planar_format = 1; + } + + if (!is_planar_format) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); + int planes_nb = 0; + int offset = 0; + + 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 size, h = height; + if (i == 1 || i == 2) { + h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); + } + size = frame->linesize[i] * h; + ret = v4l2_bufref_to_buf(out, 0, frame->data[i], size, offset); + if (ret) + return ret; + offset += size; + } + return 0; + } + + for (i = 0; i < out->num_planes; i++) { + ret = v4l2_bufref_to_buf(out, i, frame->buf[i]->data, frame->buf[i]->size, 0); + if (ret) + return ret; + } + + return 0; +} + +/****************************************************************************** + * + * V4L2Buffer interface + * + ******************************************************************************/ + +int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out) +{ + v4l2_set_pts(out, frame->pts); + + return v4l2_buffer_swframe_to_buf(frame, out); +} + +int ff_v4l2_buffer_buf_to_avframe(AVFrame *frame, V4L2Buffer *avbuf) +{ + int ret; + + av_frame_unref(frame); + + /* 1. get references to the actual data */ + ret = v4l2_buffer_buf_to_swframe(frame, avbuf); + if (ret) + return ret; + /* 2. get frame information */ frame->key_frame = !!(avbuf->buf.flags & V4L2_BUF_FLAG_KEYFRAME); - frame->format = avbuf->context->av_pix_fmt; frame->color_primaries = v4l2_get_color_primaries(avbuf); frame->colorspace = v4l2_get_color_space(avbuf); frame->color_range = v4l2_get_color_range(avbuf); frame->color_trc = v4l2_get_color_trc(avbuf); frame->pts = v4l2_get_pts(avbuf); + frame->pkt_dts = AV_NOPTS_VALUE; - /* these two values are updated also during re-init in v4l2_process_driver_event */ - frame->height = s->output.height; - frame->width = s->output.width; + /* these values are updated also during re-init in v4l2_process_driver_event */ + frame->height = avbuf->context->height; + frame->width = avbuf->context->width; + frame->sample_aspect_ratio = avbuf->context->sample_aspect_ratio; /* 3. report errors upstream */ if (avbuf->buf.flags & V4L2_BUF_FLAG_ERROR) { @@ -381,7 +479,7 @@ { int ret; - ret = v4l2_bufref_to_buf(out, 0, pkt->data, pkt->size, pkt->buf); + ret = v4l2_bufref_to_buf(out, 0, pkt->data, pkt->size, 0); if (ret) return ret; @@ -413,11 +511,9 @@ if (V4L2_TYPE_IS_MULTIPLANAR(ctx->type)) { avbuf->num_planes = 0; - for (;;) { - /* in MP, the V4L2 API states that buf.length means num_planes */ - if (avbuf->num_planes >= avbuf->buf.length) - break; - if (avbuf->buf.m.planes[avbuf->num_planes].length) + /* in MP, the V4L2 API states that buf.length means num_planes */ + for (i = 0; i < avbuf->buf.length; i++) { + if (avbuf->buf.m.planes[i].length) avbuf->num_planes++; } } else diff -Nru ffmpeg-4.2.2/libavcodec/v4l2_buffers.h ffmpeg-4.4/libavcodec/v4l2_buffers.h --- ffmpeg-4.2.2/libavcodec/v4l2_buffers.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v4l2_buffers.h 2020-07-11 10:39:30.000000000 +0000 @@ -106,7 +106,7 @@ * * @returns 0 in case of success, a negative AVERROR code otherwise */ -int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer* out); +int ff_v4l2_buffer_avframe_to_buf(const AVFrame *frame, V4L2Buffer *out); /** * Initializes a V4L2Buffer diff -Nru ffmpeg-4.2.2/libavcodec/v4l2_context.c ffmpeg-4.4/libavcodec/v4l2_context.c --- ffmpeg-4.2.2/libavcodec/v4l2_context.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v4l2_context.c 2021-04-08 21:28:39.000000000 +0000 @@ -63,6 +63,24 @@ return V4L2_TYPE_IS_MULTIPLANAR(fmt->type) ? fmt->fmt.pix_mp.height : fmt->fmt.pix.height; } +static AVRational v4l2_get_sar(V4L2Context *ctx) +{ + struct AVRational sar = { 0, 1 }; + struct v4l2_cropcap cropcap; + int ret; + + memset(&cropcap, 0, sizeof(cropcap)); + cropcap.type = ctx->type; + + ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_CROPCAP, &cropcap); + if (ret) + return sar; + + sar.num = cropcap.pixelaspect.numerator; + sar.den = cropcap.pixelaspect.denominator; + return sar; +} + static inline unsigned int v4l2_resolution_changed(V4L2Context *ctx, struct v4l2_format *fmt2) { struct v4l2_format *fmt1 = &ctx->format; @@ -96,7 +114,7 @@ const int SZ_4K = 0x1000; int size; - if (av_codec_is_decoder(s->avctx->codec)) + if (s->avctx && av_codec_is_decoder(s->avctx->codec)) return ((width * height * 3 / 2) / 2) + 128; /* encoder */ @@ -136,6 +154,7 @@ } /** + * handle resolution change event and end of stream event * returns 1 if reinit was successful, negative if it failed * returns 0 if reinit was not executed */ @@ -153,6 +172,11 @@ return 0; } + if (evt.type == V4L2_EVENT_EOS) { + ctx->done = 1; + return 0; + } + if (evt.type != V4L2_EVENT_SOURCE_CHANGE) return 0; @@ -172,12 +196,14 @@ 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) { 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); } if (full_reinit || reinit) @@ -187,20 +213,21 @@ ret = ff_v4l2_m2m_codec_full_reinit(s); if (ret) { av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_full_reinit\n"); - return -EINVAL; + return AVERROR(EINVAL); } goto reinit_run; } if (reinit) { - ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height); + 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 -EINVAL; + return AVERROR(EINVAL); } goto reinit_run; } @@ -226,6 +253,8 @@ /* DECODER_CMD is optional */ if (errno == ENOTTY) return ff_v4l2_context_set_status(ctx, VIDIOC_STREAMOFF); + else + return AVERROR(errno); } return 0; @@ -244,6 +273,8 @@ /* ENCODER_CMD is optional */ if (errno == ENOTTY) return ff_v4l2_context_set_status(ctx, VIDIOC_STREAMOFF); + else + return AVERROR(errno); } return 0; @@ -253,16 +284,34 @@ { struct v4l2_plane planes[VIDEO_MAX_PLANES]; struct v4l2_buffer buf = { 0 }; - V4L2Buffer* avbuf = NULL; + V4L2Buffer *avbuf; struct pollfd pfd = { .events = POLLIN | POLLRDNORM | POLLPRI | POLLOUT | POLLWRNORM, /* default blocking capture */ .fd = ctx_to_m2mctx(ctx)->fd, }; int i, ret; + if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx->buffers) { + for (i = 0; i < ctx->num_buffers; i++) { + if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER) + break; + } + if (i == ctx->num_buffers) + av_log(logger(ctx), AV_LOG_WARNING, "All capture buffers returned to " + "userspace. Increase num_capture_buffers " + "to prevent device deadlock or dropped " + "packets/frames.\n"); + } + /* if we are draining and there are no more capture buffers queued in the driver we are done */ if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) { for (i = 0; i < ctx->num_buffers; i++) { + /* capture buffer initialization happens during decode hence + * detection happens at runtime + */ + if (!ctx->buffers) + break; + if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER) goto start; } @@ -356,6 +405,19 @@ return NULL; } + if (ctx_to_m2mctx(ctx)->draining && !V4L2_TYPE_IS_OUTPUT(ctx->type)) { + int bytesused = V4L2_TYPE_IS_MULTIPLANAR(buf.type) ? + buf.m.planes[0].bytesused : buf.bytesused; + if (bytesused == 0) { + ctx->done = 1; + return NULL; + } +#ifdef V4L2_BUF_FLAG_LAST + if (buf.flags & V4L2_BUF_FLAG_LAST) + ctx->done = 1; +#endif + } + avbuf = &ctx->buffers[buf.index]; avbuf->status = V4L2BUF_AVAILABLE; avbuf->buf = buf; @@ -537,7 +599,7 @@ avbuf = v4l2_getfree_v4l2buf(ctx); if (!avbuf) - return AVERROR(ENOMEM); + return AVERROR(EAGAIN); ret = ff_v4l2_buffer_avframe_to_buf(frame, avbuf); if (ret) @@ -562,7 +624,7 @@ avbuf = v4l2_getfree_v4l2buf(ctx); if (!avbuf) - return AVERROR(ENOMEM); + return AVERROR(EAGAIN); ret = ff_v4l2_buffer_avpkt_to_buf(pkt, avbuf); if (ret) @@ -571,16 +633,16 @@ return ff_v4l2_buffer_enqueue(avbuf); } -int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame) +int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* frame, int timeout) { - V4L2Buffer* avbuf = NULL; + V4L2Buffer *avbuf; /* - * blocks until: + * timeout=-1 blocks until: * 1. decoded frame available * 2. an input buffer is ready to be dequeued */ - avbuf = v4l2_dequeue_v4l2buf(ctx, -1); + avbuf = v4l2_dequeue_v4l2buf(ctx, timeout); if (!avbuf) { if (ctx->done) return AVERROR_EOF; @@ -593,7 +655,7 @@ int ff_v4l2_context_dequeue_packet(V4L2Context* ctx, AVPacket* pkt) { - V4L2Buffer* avbuf = NULL; + V4L2Buffer *avbuf; /* * blocks until: @@ -611,7 +673,7 @@ return ff_v4l2_buffer_buf_to_avpkt(pkt, avbuf); } -int ff_v4l2_context_get_format(V4L2Context* ctx) +int ff_v4l2_context_get_format(V4L2Context* ctx, int probe) { struct v4l2_format_update fmt = { 0 }; int ret; @@ -621,7 +683,7 @@ if (ret) return ret; - fmt.update_avfmt = 1; + fmt.update_avfmt = !probe; v4l2_save_to_context(ctx, &fmt); /* format has been tried already */ @@ -654,8 +716,7 @@ if (ret) av_log(logger(ctx), AV_LOG_WARNING, "V4L2 failed to unmap the %s buffers\n", ctx->name); - av_free(ctx->buffers); - ctx->buffers = NULL; + av_freep(&ctx->buffers); } int ff_v4l2_context_init(V4L2Context* ctx) @@ -678,23 +739,24 @@ req.memory = V4L2_MEMORY_MMAP; req.type = ctx->type; ret = ioctl(s->fd, VIDIOC_REQBUFS, &req); - if (ret < 0) + if (ret < 0) { + av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_REQBUFS failed: %s\n", ctx->name, strerror(errno)); return AVERROR(errno); + } ctx->num_buffers = req.count; ctx->buffers = av_mallocz(ctx->num_buffers * sizeof(V4L2Buffer)); if (!ctx->buffers) { - av_log(logger(ctx), AV_LOG_ERROR, "%s malloc enomem\n", ctx->name); - return AVERROR(ENOMEM); + av_log(logger(ctx), AV_LOG_ERROR, "%s malloc enomem\n", ctx->name); + return AVERROR(ENOMEM); } for (i = 0; i < req.count; i++) { ctx->buffers[i].context = ctx; ret = ff_v4l2_buffer_initialize(&ctx->buffers[i], i); if (ret < 0) { - av_log(logger(ctx), AV_LOG_ERROR, "%s buffer initialization (%s)\n", ctx->name, av_err2str(ret)); - av_free(ctx->buffers); - return ret; + av_log(logger(ctx), AV_LOG_ERROR, "%s buffer[%d] initialization (%s)\n", ctx->name, i, av_err2str(ret)); + goto error; } } @@ -707,4 +769,11 @@ V4L2_TYPE_IS_MULTIPLANAR(ctx->type) ? ctx->format.fmt.pix_mp.plane_fmt[0].bytesperline : ctx->format.fmt.pix.bytesperline); return 0; + +error: + v4l2_release_buffers(ctx); + + av_freep(&ctx->buffers); + + return ret; } diff -Nru ffmpeg-4.2.2/libavcodec/v4l2_context.h ffmpeg-4.4/libavcodec/v4l2_context.h --- ffmpeg-4.2.2/libavcodec/v4l2_context.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v4l2_context.h 2020-07-11 10:39:30.000000000 +0000 @@ -69,6 +69,7 @@ * or accepts (in case of an output context, e.g. when encoding). */ int width, height; + AVRational sample_aspect_ratio; /** * Indexed array of V4L2Buffers @@ -113,9 +114,10 @@ * Queries the driver for a valid v4l2 format and copies it to the context. * * @param[in] ctx A pointer to a V4L2Context. See V4L2Context description for required variables. + * @param[in] probe Probe only and ignore changes to the format. * @return 0 in case of success, a negative value representing the error otherwise. */ -int ff_v4l2_context_get_format(V4L2Context* ctx); +int ff_v4l2_context_get_format(V4L2Context* ctx, int probe); /** * Releases a V4L2Context. @@ -153,9 +155,10 @@ * The frame must be non NULL. * @param[in] ctx The V4L2Context to dequeue from. * @param[inout] f The AVFrame to dequeue to. + * @param[in] timeout The timeout for dequeue (-1 to block, 0 to return immediately, or milliseconds) * @return 0 in case of success, AVERROR(EAGAIN) if no buffer was ready, another negative error in case of error. */ -int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* f); +int ff_v4l2_context_dequeue_frame(V4L2Context* ctx, AVFrame* f, int timeout); /** * Enqueues a buffer to a V4L2Context from an AVPacket diff -Nru ffmpeg-4.2.2/libavcodec/v4l2_m2m.c ffmpeg-4.4/libavcodec/v4l2_m2m.c --- ffmpeg-4.2.2/libavcodec/v4l2_m2m.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v4l2_m2m.c 2021-04-08 21:28:39.000000000 +0000 @@ -60,14 +60,15 @@ return 0; } -static int v4l2_prepare_contexts(V4L2m2mContext* s) +static int v4l2_prepare_contexts(V4L2m2mContext *s, int probe) { struct v4l2_capability cap; + void *log_ctx = s->avctx; int ret; s->capture.done = s->output.done = 0; s->capture.name = "capture"; - s->output.name = "output "; + s->output.name = "output"; atomic_init(&s->refcount, 0); sem_init(&s->refsync, 0, 0); @@ -76,7 +77,10 @@ if (ret < 0) return ret; - av_log(s->avctx, AV_LOG_INFO, "driver '%s' on card '%s'\n", cap.driver, cap.card); + av_log(log_ctx, probe ? AV_LOG_DEBUG : AV_LOG_INFO, + "driver '%s' on card '%s' in %s mode\n", cap.driver, cap.card, + v4l2_mplane_video(&cap) ? "mplane" : + v4l2_splane_video(&cap) ? "splane" : "unknown"); if (v4l2_mplane_video(&cap)) { s->capture.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; @@ -93,34 +97,35 @@ return AVERROR(EINVAL); } -static int v4l2_probe_driver(V4L2m2mContext* s) +static int v4l2_probe_driver(V4L2m2mContext *s) { + void *log_ctx = s->avctx; int ret; s->fd = open(s->devname, O_RDWR | O_NONBLOCK, 0); if (s->fd < 0) return AVERROR(errno); - ret = v4l2_prepare_contexts(s); + ret = v4l2_prepare_contexts(s, 1); if (ret < 0) goto done; - ret = ff_v4l2_context_get_format(&s->output); + ret = ff_v4l2_context_get_format(&s->output, 1); if (ret) { - av_log(s->avctx, AV_LOG_DEBUG, "v4l2 output format not supported\n"); + av_log(log_ctx, AV_LOG_DEBUG, "v4l2 output format not supported\n"); goto done; } - ret = ff_v4l2_context_get_format(&s->capture); + ret = ff_v4l2_context_get_format(&s->capture, 1); if (ret) { - av_log(s->avctx, AV_LOG_DEBUG, "v4l2 capture format not supported\n"); + av_log(log_ctx, AV_LOG_DEBUG, "v4l2 capture format not supported\n"); goto done; } done: if (close(s->fd) < 0) { ret = AVERROR(errno); - av_log(s->avctx, AV_LOG_ERROR, "failure closing %s (%s)\n", s->devname, av_err2str(AVERROR(errno))); + av_log(log_ctx, AV_LOG_ERROR, "failure closing %s (%s)\n", s->devname, av_err2str(AVERROR(errno))); } s->fd = -1; @@ -128,19 +133,30 @@ return ret; } -static int v4l2_configure_contexts(V4L2m2mContext* s) +static int v4l2_configure_contexts(V4L2m2mContext *s) { void *log_ctx = s->avctx; int ret; + struct v4l2_format ofmt, cfmt; s->fd = open(s->devname, O_RDWR | O_NONBLOCK, 0); if (s->fd < 0) return AVERROR(errno); - ret = v4l2_prepare_contexts(s); + ret = v4l2_prepare_contexts(s, 0); if (ret < 0) goto error; + ofmt = s->output.format; + cfmt = s->capture.format; + av_log(log_ctx, AV_LOG_INFO, "requesting formats: output=%s capture=%s\n", + av_fourcc2str(V4L2_TYPE_IS_MULTIPLANAR(ofmt.type) ? + ofmt.fmt.pix_mp.pixelformat : + ofmt.fmt.pix.pixelformat), + av_fourcc2str(V4L2_TYPE_IS_MULTIPLANAR(cfmt.type) ? + cfmt.fmt.pix_mp.pixelformat : + cfmt.fmt.pix.pixelformat)); + ret = ff_v4l2_context_set_format(&s->output); if (ret) { av_log(log_ctx, AV_LOG_ERROR, "can't set v4l2 output format\n"); @@ -160,7 +176,7 @@ } /* decoder's buffers need to be updated at a later stage */ - if (!av_codec_is_decoder(s->avctx->codec)) { + if (s->avctx && !av_codec_is_decoder(s->avctx->codec)) { ret = ff_v4l2_context_init(&s->capture); if (ret) { av_log(log_ctx, AV_LOG_ERROR, "no v4l2 capture context's buffers\n"); @@ -186,38 +202,39 @@ * V4L2 M2M Interface * ******************************************************************************/ -int ff_v4l2_m2m_codec_reinit(V4L2m2mContext* s) +int ff_v4l2_m2m_codec_reinit(V4L2m2mContext *s) { + void *log_ctx = s->avctx; int ret; - av_log(s->avctx, AV_LOG_DEBUG, "reinit context\n"); + av_log(log_ctx, AV_LOG_DEBUG, "reinit context\n"); /* 1. streamoff */ ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); if (ret) - av_log(s->avctx, AV_LOG_ERROR, "capture VIDIOC_STREAMOFF\n"); + av_log(log_ctx, AV_LOG_ERROR, "capture VIDIOC_STREAMOFF\n"); /* 2. unmap the capture buffers (v4l2 and ffmpeg): * we must wait for all references to be released before being allowed * to queue new buffers. */ - av_log(s->avctx, AV_LOG_DEBUG, "waiting for user to release AVBufferRefs\n"); + av_log(log_ctx, AV_LOG_DEBUG, "waiting for user to release AVBufferRefs\n"); if (atomic_load(&s->refcount)) while(sem_wait(&s->refsync) == -1 && errno == EINTR); ff_v4l2_context_release(&s->capture); /* 3. get the new capture format */ - ret = ff_v4l2_context_get_format(&s->capture); + ret = ff_v4l2_context_get_format(&s->capture, 0); if (ret) { - av_log(s->avctx, AV_LOG_ERROR, "query the new capture format\n"); + av_log(log_ctx, AV_LOG_ERROR, "query the new capture format\n"); return ret; } /* 4. set the capture format */ ret = ff_v4l2_context_set_format(&s->capture); if (ret) { - av_log(s->avctx, AV_LOG_ERROR, "setting capture format\n"); + av_log(log_ctx, AV_LOG_ERROR, "setting capture format\n"); return ret; } @@ -241,14 +258,14 @@ ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); if (ret) { - av_log(s->avctx, AV_LOG_ERROR, "output VIDIOC_STREAMOFF\n"); + av_log(log_ctx, AV_LOG_ERROR, "output VIDIOC_STREAMOFF\n"); goto error; } ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); if (ret) { - av_log(s->avctx, AV_LOG_ERROR, "capture VIDIOC_STREAMOFF\n"); - goto error; + av_log(log_ctx, AV_LOG_ERROR, "capture VIDIOC_STREAMOFF\n"); + goto error; } /* release and unmmap the buffers */ @@ -259,13 +276,13 @@ s->draining = 0; s->reinit = 0; - ret = ff_v4l2_context_get_format(&s->output); + ret = ff_v4l2_context_get_format(&s->output, 0); if (ret) { av_log(log_ctx, AV_LOG_DEBUG, "v4l2 output format not supported\n"); goto error; } - ret = ff_v4l2_context_get_format(&s->capture); + ret = ff_v4l2_context_get_format(&s->capture, 0); if (ret) { av_log(log_ctx, AV_LOG_DEBUG, "v4l2 capture format not supported\n"); goto error; @@ -290,7 +307,7 @@ } /* decoder's buffers need to be updated at a later stage */ - if (!av_codec_is_decoder(s->avctx->codec)) { + if (s->avctx && !av_codec_is_decoder(s->avctx->codec)) { ret = ff_v4l2_context_init(&s->capture); if (ret) { av_log(log_ctx, AV_LOG_ERROR, "no v4l2 capture context's buffers\n"); @@ -312,23 +329,30 @@ sem_destroy(&s->refsync); close(s->fd); + av_frame_unref(s->frame); + av_frame_free(&s->frame); + av_packet_unref(&s->buf_pkt); av_free(s); } -int ff_v4l2_m2m_codec_end(AVCodecContext *avctx) +int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv) { - V4L2m2mPriv *priv = avctx->priv_data; - V4L2m2mContext* s = priv->context; + V4L2m2mContext *s = priv->context; int ret; - ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); - if (ret) - av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name); + if (!s) + return 0; - ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); - if (ret) - av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name); + if (s->fd >= 0) { + ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); + if (ret) + av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name); + + ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); + if (ret) + av_log(s->avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name); + } ff_v4l2_context_release(&s->output); @@ -338,15 +362,13 @@ return 0; } -int ff_v4l2_m2m_codec_init(AVCodecContext *avctx) +int ff_v4l2_m2m_codec_init(V4L2m2mPriv *priv) { int ret = AVERROR(EINVAL); struct dirent *entry; - char node[PATH_MAX]; DIR *dirp; - V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; - s->avctx = avctx; + V4L2m2mContext *s = priv->context; dirp = opendir("/dev"); if (!dirp) @@ -357,12 +379,11 @@ if (strncmp(entry->d_name, "video", 5)) continue; - snprintf(node, sizeof(node), "/dev/%s", entry->d_name); - av_log(s->avctx, AV_LOG_DEBUG, "probing device %s\n", node); - strncpy(s->devname, node, strlen(node) + 1); + snprintf(s->devname, sizeof(s->devname), "/dev/%s", entry->d_name); + av_log(s->avctx, AV_LOG_DEBUG, "probing device %s\n", s->devname); ret = v4l2_probe_driver(s); if (!ret) - break; + break; } closedir(dirp); @@ -374,15 +395,13 @@ return ret; } - av_log(s->avctx, AV_LOG_INFO, "Using device %s\n", node); + av_log(s->avctx, AV_LOG_INFO, "Using device %s\n", s->devname); return v4l2_configure_contexts(s); } -int ff_v4l2_m2m_create_context(AVCodecContext *avctx, V4L2m2mContext **s) +int ff_v4l2_m2m_create_context(V4L2m2mPriv *priv, V4L2m2mContext **s) { - V4L2m2mPriv *priv = avctx->priv_data; - *s = av_mallocz(sizeof(V4L2m2mContext)); if (!*s) return AVERROR(ENOMEM); @@ -396,11 +415,20 @@ /* assign the context */ priv->context = *s; + (*s)->priv = priv; /* populate it */ priv->context->capture.num_buffers = priv->num_capture_buffers; priv->context->output.num_buffers = priv->num_output_buffers; priv->context->self_ref = priv->context_ref; + priv->context->fd = -1; + + priv->context->frame = av_frame_alloc(); + if (!priv->context->frame) { + av_buffer_unref(&priv->context_ref); + *s = NULL; /* freed when unreferencing context_ref */ + return AVERROR(ENOMEM); + } return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/v4l2_m2m_dec.c ffmpeg-4.4/libavcodec/v4l2_m2m_dec.c --- ffmpeg-4.2.2/libavcodec/v4l2_m2m_dec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v4l2_m2m_dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,6 +28,7 @@ #include "libavutil/opt.h" #include "libavcodec/avcodec.h" #include "libavcodec/decode.h" +#include "libavcodec/internal.h" #include "v4l2_context.h" #include "v4l2_m2m.h" @@ -38,7 +39,7 @@ V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; V4L2Context *const capture = &s->capture; V4L2Context *const output = &s->output; - struct v4l2_selection selection; + struct v4l2_selection selection = { 0 }; int ret; /* 1. start the output process */ @@ -86,8 +87,8 @@ if (!capture->buffers) { ret = ff_v4l2_context_init(capture); if (ret) { - av_log(avctx, AV_LOG_DEBUG, "can't request output buffers\n"); - return ret; + av_log(avctx, AV_LOG_ERROR, "can't request capture buffers\n"); + return AVERROR(ENOMEM); } } @@ -122,6 +123,13 @@ } } + memset(&sub, 0, sizeof(sub)); + sub.type = V4L2_EVENT_EOS; + ret = ioctl(s->fd, VIDIOC_SUBSCRIBE_EVENT, &sub); + if (ret < 0) + av_log(s->avctx, AV_LOG_WARNING, + "the v4l2 driver does not support end of stream VIDIOC_SUBSCRIBE_EVENT\n"); + return 0; } @@ -130,43 +138,50 @@ V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; V4L2Context *const capture = &s->capture; V4L2Context *const output = &s->output; - AVPacket avpkt = {0}; int ret; - ret = ff_decode_get_packet(avctx, &avpkt); - if (ret < 0 && ret != AVERROR_EOF) - return ret; + if (!s->buf_pkt.size) { + ret = ff_decode_get_packet(avctx, &s->buf_pkt); + if (ret < 0 && ret != AVERROR_EOF) + return ret; + } if (s->draining) goto dequeue; - ret = ff_v4l2_context_enqueue_packet(output, &avpkt); - if (ret < 0) { - if (ret != AVERROR(ENOMEM)) - return ret; - /* no input buffers available, continue dequeing */ - } + ret = ff_v4l2_context_enqueue_packet(output, &s->buf_pkt); + if (ret < 0 && ret != AVERROR(EAGAIN)) + goto fail; + + /* if EAGAIN don't unref packet and try to enqueue in the next iteration */ + if (ret != AVERROR(EAGAIN)) + av_packet_unref(&s->buf_pkt); - if (avpkt.size) { + if (!s->draining) { ret = v4l2_try_start(avctx); if (ret) { - av_packet_unref(&avpkt); - return 0; + /* cant recover */ + if (ret != AVERROR(ENOMEM)) + ret = 0; + goto fail; } } dequeue: - av_packet_unref(&avpkt); - return ff_v4l2_context_dequeue_frame(capture, frame); + return ff_v4l2_context_dequeue_frame(capture, frame, -1); +fail: + av_packet_unref(&s->buf_pkt); + return ret; } static av_cold int v4l2_decode_init(AVCodecContext *avctx) { V4L2Context *capture, *output; V4L2m2mContext *s; + V4L2m2mPriv *priv = avctx->priv_data; int ret; - ret = ff_v4l2_m2m_create_context(avctx, &s); + ret = ff_v4l2_m2m_create_context(priv, &s); if (ret < 0) return ret; @@ -186,19 +201,21 @@ capture->av_codec_id = AV_CODEC_ID_RAWVIDEO; capture->av_pix_fmt = avctx->pix_fmt; - ret = ff_v4l2_m2m_codec_init(avctx); + s->avctx = avctx; + ret = ff_v4l2_m2m_codec_init(priv); if (ret) { - V4L2m2mPriv *priv = avctx->priv_data; av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n"); - s->self_ref = NULL; - av_buffer_unref(&priv->context_ref); - return ret; } return v4l2_prepare_decoder(s); } +static av_cold int v4l2_decode_close(AVCodecContext *avctx) +{ + return ff_v4l2_m2m_codec_end(avctx->priv_data); +} + #define OFFSET(x) offsetof(V4L2m2mPriv, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM @@ -209,29 +226,31 @@ { NULL}, }; +#define M2MDEC_CLASS(NAME) \ + static const AVClass v4l2_m2m_ ## NAME ## _dec_class = { \ + .class_name = #NAME "_v4l2m2m_decoder", \ + .item_name = av_default_item_name, \ + .option = options, \ + .version = LIBAVUTIL_VERSION_INT, \ + }; + #define M2MDEC(NAME, LONGNAME, CODEC, bsf_name) \ -static const AVClass v4l2_m2m_ ## NAME ## _dec_class = {\ - .class_name = #NAME "_v4l2_m2m_decoder",\ - .item_name = av_default_item_name,\ - .option = options,\ - .version = LIBAVUTIL_VERSION_INT,\ -};\ -\ -AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \ - .name = #NAME "_v4l2m2m" ,\ - .long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " decoder wrapper"),\ - .type = AVMEDIA_TYPE_VIDEO,\ - .id = CODEC ,\ - .priv_data_size = sizeof(V4L2m2mPriv),\ - .priv_class = &v4l2_m2m_ ## NAME ## _dec_class,\ - .init = v4l2_decode_init,\ - .receive_frame = v4l2_receive_frame,\ - .close = ff_v4l2_m2m_codec_end,\ - .bsfs = bsf_name, \ - .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | \ - AV_CODEC_CAP_AVOID_PROBING, \ - .wrapper_name = "v4l2m2m", \ -}; + M2MDEC_CLASS(NAME) \ + AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \ + .name = #NAME "_v4l2m2m" , \ + .long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " decoder wrapper"), \ + .type = AVMEDIA_TYPE_VIDEO, \ + .id = CODEC , \ + .priv_data_size = sizeof(V4L2m2mPriv), \ + .priv_class = &v4l2_m2m_ ## NAME ## _dec_class, \ + .init = v4l2_decode_init, \ + .receive_frame = v4l2_receive_frame, \ + .close = v4l2_decode_close, \ + .bsfs = bsf_name, \ + .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ + .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \ + .wrapper_name = "v4l2m2m", \ + } M2MDEC(h264, "H.264", AV_CODEC_ID_H264, "h264_mp4toannexb"); M2MDEC(hevc, "HEVC", AV_CODEC_ID_HEVC, "hevc_mp4toannexb"); diff -Nru ffmpeg-4.2.2/libavcodec/v4l2_m2m_enc.c ffmpeg-4.4/libavcodec/v4l2_m2m_enc.c --- ffmpeg-4.2.2/libavcodec/v4l2_m2m_enc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v4l2_m2m_enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,12 +24,16 @@ #include #include #include +#include "encode.h" #include "libavcodec/avcodec.h" +#include "libavcodec/internal.h" #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" #include "libavutil/opt.h" +#include "profiles.h" #include "v4l2_context.h" #include "v4l2_m2m.h" +#include "v4l2_fmt.h" #define MPEG_CID(x) V4L2_CID_MPEG_VIDEO_##x #define MPEG_VIDEO(x) V4L2_MPEG_VIDEO_##x @@ -46,7 +50,7 @@ av_log(s->avctx, AV_LOG_WARNING, "Failed to set timeperframe"); } -static inline void v4l2_set_ext_ctrl(V4L2m2mContext *s, unsigned int id, signed int value, const char *name) +static inline void v4l2_set_ext_ctrl(V4L2m2mContext *s, unsigned int id, signed int value, const char *name, int log_warning) { struct v4l2_ext_controls ctrls = { { 0 } }; struct v4l2_ext_control ctrl = { 0 }; @@ -58,15 +62,16 @@ /* set ctrl*/ ctrl.value = value; - ctrl.id = id ; + ctrl.id = id; if (ioctl(s->fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0) - av_log(s->avctx, AV_LOG_WARNING, "Failed to set %s\n", name); + av_log(s->avctx, log_warning || errno != EINVAL ? AV_LOG_WARNING : AV_LOG_DEBUG, + "Failed to set %s: %s\n", name, strerror(errno)); else av_log(s->avctx, AV_LOG_DEBUG, "Encoder: %s = %d\n", name, value); } -static inline int v4l2_get_ext_ctrl(V4L2m2mContext *s, unsigned int id, signed int *value, const char *name) +static inline int v4l2_get_ext_ctrl(V4L2m2mContext *s, unsigned int id, signed int *value, const char *name, int log_warning) { struct v4l2_ext_controls ctrls = { { 0 } }; struct v4l2_ext_control ctrl = { 0 }; @@ -82,7 +87,8 @@ ret = ioctl(s->fd, VIDIOC_G_EXT_CTRLS, &ctrls); if (ret < 0) { - av_log(s->avctx, AV_LOG_WARNING, "Failed to set %s\n", name); + av_log(s->avctx, log_warning || errno != EINVAL ? AV_LOG_WARNING : AV_LOG_DEBUG, + "Failed to get %s\n", name); return ret; } @@ -144,8 +150,8 @@ if (s->avctx->max_b_frames) av_log(s->avctx, AV_LOG_WARNING, "Encoder does not support b-frames yet\n"); - v4l2_set_ext_ctrl(s, MPEG_CID(B_FRAMES), 0, "number of B-frames"); - v4l2_get_ext_ctrl(s, MPEG_CID(B_FRAMES), &s->avctx->max_b_frames, "number of B-frames"); + v4l2_set_ext_ctrl(s, MPEG_CID(B_FRAMES), 0, "number of B-frames", 0); + v4l2_get_ext_ctrl(s, MPEG_CID(B_FRAMES), &s->avctx->max_b_frames, "number of B-frames", 0); if (s->avctx->max_b_frames == 0) return 0; @@ -154,6 +160,17 @@ return AVERROR_PATCHWELCOME; } +static inline void v4l2_subscribe_eos_event(V4L2m2mContext *s) +{ + struct v4l2_event_subscription sub; + + memset(&sub, 0, sizeof(sub)); + sub.type = V4L2_EVENT_EOS; + if (ioctl(s->fd, VIDIOC_SUBSCRIBE_EVENT, &sub) < 0) + av_log(s->avctx, AV_LOG_WARNING, + "the v4l2 driver does not support end of stream VIDIOC_SUBSCRIBE_EVENT\n"); +} + static int v4l2_prepare_encoder(V4L2m2mContext *s) { AVCodecContext *avctx = s->avctx; @@ -163,6 +180,8 @@ /** * requirements */ + v4l2_subscribe_eos_event(s); + ret = v4l2_check_b_frame_support(s); if (ret) return ret; @@ -171,12 +190,13 @@ * settingss */ if (avctx->framerate.num || avctx->framerate.den) - v4l2_set_timeperframe(s, avctx->framerate.num, avctx->framerate.den); + v4l2_set_timeperframe(s, avctx->framerate.den, avctx->framerate.num); /* set ext ctrls */ - v4l2_set_ext_ctrl(s, MPEG_CID(HEADER_MODE), MPEG_VIDEO(HEADER_MODE_SEPARATE), "header mode"); - v4l2_set_ext_ctrl(s, MPEG_CID(BITRATE) , avctx->bit_rate, "bit rate"); - v4l2_set_ext_ctrl(s, MPEG_CID(GOP_SIZE), avctx->gop_size,"gop size"); + v4l2_set_ext_ctrl(s, MPEG_CID(HEADER_MODE), MPEG_VIDEO(HEADER_MODE_SEPARATE), "header mode", 0); + v4l2_set_ext_ctrl(s, MPEG_CID(BITRATE) , avctx->bit_rate, "bit rate", 1); + v4l2_set_ext_ctrl(s, MPEG_CID(FRAME_RC_ENABLE), 1, "frame level rate control", 0); + v4l2_set_ext_ctrl(s, MPEG_CID(GOP_SIZE), avctx->gop_size,"gop size", 1); av_log(avctx, AV_LOG_DEBUG, "Encoder Context: id (%d), profile (%d), frame rate(%d/%d), number b-frames (%d), " @@ -186,26 +206,30 @@ switch (avctx->codec_id) { case AV_CODEC_ID_H264: - val = v4l2_h264_profile_from_ff(avctx->profile); - if (val < 0) - av_log(avctx, AV_LOG_WARNING, "h264 profile not found\n"); - else - v4l2_set_ext_ctrl(s, MPEG_CID(H264_PROFILE), val, "h264 profile"); + if (avctx->profile != FF_PROFILE_UNKNOWN) { + val = v4l2_h264_profile_from_ff(avctx->profile); + if (val < 0) + av_log(avctx, AV_LOG_WARNING, "h264 profile not found\n"); + else + v4l2_set_ext_ctrl(s, MPEG_CID(H264_PROFILE), val, "h264 profile", 1); + } qmin_cid = MPEG_CID(H264_MIN_QP); qmax_cid = MPEG_CID(H264_MAX_QP); qmin = 0; qmax = 51; break; case AV_CODEC_ID_MPEG4: - val = v4l2_mpeg4_profile_from_ff(avctx->profile); - if (val < 0) - av_log(avctx, AV_LOG_WARNING, "mpeg4 profile not found\n"); - else - v4l2_set_ext_ctrl(s, MPEG_CID(MPEG4_PROFILE), val, "mpeg4 profile"); + if (avctx->profile != FF_PROFILE_UNKNOWN) { + val = v4l2_mpeg4_profile_from_ff(avctx->profile); + if (val < 0) + av_log(avctx, AV_LOG_WARNING, "mpeg4 profile not found\n"); + else + v4l2_set_ext_ctrl(s, MPEG_CID(MPEG4_PROFILE), val, "mpeg4 profile", 1); + } qmin_cid = MPEG_CID(MPEG4_MIN_QP); qmax_cid = MPEG_CID(MPEG4_MAX_QP); if (avctx->flags & AV_CODEC_FLAG_QPEL) - v4l2_set_ext_ctrl(s, MPEG_CID(MPEG4_QPEL), 1, "qpel"); + v4l2_set_ext_ctrl(s, MPEG_CID(MPEG4_QPEL), 1, "qpel", 1); qmin = 1; qmax = 31; break; @@ -231,11 +255,18 @@ return 0; } - if (qmin != avctx->qmin || qmax != avctx->qmax) - av_log(avctx, AV_LOG_WARNING, "Encoder adjusted: qmin (%d), qmax (%d)\n", qmin, qmax); + if (avctx->qmin >= 0 && avctx->qmax >= 0 && avctx->qmin > avctx->qmax) { + av_log(avctx, AV_LOG_WARNING, "Invalid qmin:%d qmax:%d. qmin should not " + "exceed qmax\n", avctx->qmin, avctx->qmax); + } else { + qmin = avctx->qmin >= 0 ? avctx->qmin : qmin; + qmax = avctx->qmax >= 0 ? avctx->qmax : qmax; + } - v4l2_set_ext_ctrl(s, qmin_cid, qmin, "minimum video quantizer scale"); - v4l2_set_ext_ctrl(s, qmax_cid, qmax, "maximum video quantizer scale"); + v4l2_set_ext_ctrl(s, qmin_cid, qmin, "minimum video quantizer scale", + avctx->qmin >= 0); + v4l2_set_ext_ctrl(s, qmax_cid, qmax, "maximum video quantizer scale", + avctx->qmax >= 0); return 0; } @@ -245,6 +276,11 @@ V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; V4L2Context *const output = &s->output; +#ifdef V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME + if (frame && frame->pict_type == AV_PICTURE_TYPE_I) + v4l2_set_ext_ctrl(s, MPEG_CID(FORCE_KEY_FRAME), 0, "force key frame", 1); +#endif + return ff_v4l2_context_enqueue_frame(output, frame); } @@ -253,15 +289,32 @@ V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; V4L2Context *const capture = &s->capture; V4L2Context *const output = &s->output; + AVFrame *frame = s->frame; int ret; if (s->draining) goto dequeue; + if (!frame->buf[0]) { + ret = ff_encode_get_frame(avctx, frame); + if (ret < 0 && ret != AVERROR_EOF) + return ret; + + if (ret == AVERROR_EOF) + frame = NULL; + } + + ret = v4l2_send_frame(avctx, frame); + if (ret != AVERROR(EAGAIN)) + av_frame_unref(frame); + + if (ret < 0 && ret != AVERROR(EAGAIN)) + return ret; + if (!output->streamon) { ret = ff_v4l2_context_set_status(output, VIDIOC_STREAMON); if (ret) { - av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF failed on output context\n"); + av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMON failed on output context\n"); return ret; } } @@ -282,9 +335,12 @@ { V4L2Context *capture, *output; V4L2m2mContext *s; + V4L2m2mPriv *priv = avctx->priv_data; + enum AVPixelFormat pix_fmt_output; + uint32_t v4l2_fmt_output; int ret; - ret = ff_v4l2_m2m_create_context(avctx, &s); + ret = ff_v4l2_m2m_create_context(priv, &s); if (ret < 0) return ret; @@ -303,50 +359,86 @@ capture->av_codec_id = avctx->codec_id; capture->av_pix_fmt = AV_PIX_FMT_NONE; - ret = ff_v4l2_m2m_codec_init(avctx); + s->avctx = avctx; + ret = ff_v4l2_m2m_codec_init(priv); if (ret) { av_log(avctx, AV_LOG_ERROR, "can't configure encoder\n"); return ret; } + if (V4L2_TYPE_IS_MULTIPLANAR(output->type)) + v4l2_fmt_output = output->format.fmt.pix_mp.pixelformat; + else + v4l2_fmt_output = output->format.fmt.pix.pixelformat; + + pix_fmt_output = ff_v4l2_format_v4l2_to_avfmt(v4l2_fmt_output, AV_CODEC_ID_RAWVIDEO); + if (pix_fmt_output != avctx->pix_fmt) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt_output); + av_log(avctx, AV_LOG_ERROR, "Encoder requires %s pixel format.\n", desc->name); + return AVERROR(EINVAL); + } + return v4l2_prepare_encoder(s); } +static av_cold int v4l2_encode_close(AVCodecContext *avctx) +{ + return ff_v4l2_m2m_codec_end(avctx->priv_data); +} + #define OFFSET(x) offsetof(V4L2m2mPriv, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +#define V4L_M2M_CAPTURE_OPTS \ + V4L_M2M_DEFAULT_OPTS,\ + { "num_capture_buffers", "Number of buffers in the capture context", \ + OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 4 }, 4, INT_MAX, FLAGS } + +static const AVOption mpeg4_options[] = { + V4L_M2M_CAPTURE_OPTS, + FF_MPEG4_PROFILE_OPTS + { NULL }, +}; + static const AVOption options[] = { - V4L_M2M_DEFAULT_OPTS, - { "num_capture_buffers", "Number of buffers in the capture context", - OFFSET(num_capture_buffers), AV_OPT_TYPE_INT, {.i64 = 4 }, 4, INT_MAX, FLAGS }, + V4L_M2M_CAPTURE_OPTS, { NULL }, }; -#define M2MENC(NAME, LONGNAME, CODEC) \ -static const AVClass v4l2_m2m_ ## NAME ## _enc_class = {\ - .class_name = #NAME "_v4l2_m2m_encoder",\ - .item_name = av_default_item_name,\ - .option = options,\ - .version = LIBAVUTIL_VERSION_INT,\ -};\ -\ -AVCodec ff_ ## NAME ## _v4l2m2m_encoder = { \ - .name = #NAME "_v4l2m2m" ,\ - .long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " encoder wrapper"),\ - .type = AVMEDIA_TYPE_VIDEO,\ - .id = CODEC ,\ - .priv_data_size = sizeof(V4L2m2mPriv),\ - .priv_class = &v4l2_m2m_ ## NAME ##_enc_class,\ - .init = v4l2_encode_init,\ - .send_frame = v4l2_send_frame,\ - .receive_packet = v4l2_receive_packet,\ - .close = ff_v4l2_m2m_codec_end,\ - .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \ - .wrapper_name = "v4l2m2m", \ +static const AVCodecDefault v4l2_m2m_defaults[] = { + { "qmin", "-1" }, + { "qmax", "-1" }, + { NULL }, }; -M2MENC(mpeg4,"MPEG4", AV_CODEC_ID_MPEG4); -M2MENC(h263, "H.263", AV_CODEC_ID_H263); -M2MENC(h264, "H.264", AV_CODEC_ID_H264); -M2MENC(hevc, "HEVC", AV_CODEC_ID_HEVC); -M2MENC(vp8, "VP8", AV_CODEC_ID_VP8); +#define M2MENC_CLASS(NAME, OPTIONS_NAME) \ + static const AVClass v4l2_m2m_ ## NAME ## _enc_class = { \ + .class_name = #NAME "_v4l2m2m_encoder", \ + .item_name = av_default_item_name, \ + .option = OPTIONS_NAME, \ + .version = LIBAVUTIL_VERSION_INT, \ + }; + +#define M2MENC(NAME, LONGNAME, OPTIONS_NAME, CODEC) \ + M2MENC_CLASS(NAME, OPTIONS_NAME) \ + AVCodec ff_ ## NAME ## _v4l2m2m_encoder = { \ + .name = #NAME "_v4l2m2m" , \ + .long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " encoder wrapper"), \ + .type = AVMEDIA_TYPE_VIDEO, \ + .id = CODEC , \ + .priv_data_size = sizeof(V4L2m2mPriv), \ + .priv_class = &v4l2_m2m_ ## NAME ##_enc_class, \ + .init = v4l2_encode_init, \ + .receive_packet = v4l2_receive_packet, \ + .close = v4l2_encode_close, \ + .defaults = v4l2_m2m_defaults, \ + .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \ + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \ + .wrapper_name = "v4l2m2m", \ + } + +M2MENC(mpeg4,"MPEG4", mpeg4_options, AV_CODEC_ID_MPEG4); +M2MENC(h263, "H.263", options, AV_CODEC_ID_H263); +M2MENC(h264, "H.264", options, AV_CODEC_ID_H264); +M2MENC(hevc, "HEVC", options, AV_CODEC_ID_HEVC); +M2MENC(vp8, "VP8", options, AV_CODEC_ID_VP8); diff -Nru ffmpeg-4.2.2/libavcodec/v4l2_m2m.h ffmpeg-4.4/libavcodec/v4l2_m2m.h --- ffmpeg-4.2.2/libavcodec/v4l2_m2m.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/v4l2_m2m.h 2021-04-08 21:28:39.000000000 +0000 @@ -56,13 +56,19 @@ /* null frame/packet received */ int draining; + AVPacket buf_pkt; + + /* Reference to a frame. Only used during encoding */ + AVFrame *frame; /* Reference to self; only valid while codec is active. */ AVBufferRef *self_ref; + + /* reference back to V4L2m2mPriv */ + void *priv; } V4L2m2mContext; -typedef struct V4L2m2mPriv -{ +typedef struct V4L2m2mPriv { AVClass *class; V4L2m2mContext *context; @@ -75,33 +81,33 @@ /** * Allocate a new context and references for a V4L2 M2M instance. * - * @param[in] ctx The AVCodecContext instantiated by the encoder/decoder. + * @param[in] ctx The V4L2m2mPriv instantiated by the encoder/decoder. * @param[out] ctx The V4L2m2mContext. * * @returns 0 in success, a negative error code otherwise. */ -int ff_v4l2_m2m_create_context(AVCodecContext *avctx, V4L2m2mContext **s); +int ff_v4l2_m2m_create_context(V4L2m2mPriv *priv, V4L2m2mContext **s); /** * Probes the video nodes looking for the required codec capabilities. * - * @param[in] ctx The AVCodecContext instantiated by the encoder/decoder. + * @param[in] ctx The V4L2m2mPriv instantiated by the encoder/decoder. * * @returns 0 if a driver is found, a negative number otherwise. */ -int ff_v4l2_m2m_codec_init(AVCodecContext *avctx); +int ff_v4l2_m2m_codec_init(V4L2m2mPriv *priv); /** * Releases all the codec resources if all AVBufferRefs have been returned to the * ctx. Otherwise keep the driver open. * - * @param[in] The AVCodecContext instantiated by the encoder/decoder. + * @param[in] The V4L2m2mPriv instantiated by the encoder/decoder. * * @returns 0 * */ -int ff_v4l2_m2m_codec_end(AVCodecContext *avctx); +int ff_v4l2_m2m_codec_end(V4L2m2mPriv *priv); /** * Reinitializes the V4L2m2mContext when the driver cannot continue processing diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_av1.c ffmpeg-4.4/libavcodec/vaapi_av1.c --- ffmpeg-4.2.2/libavcodec/vaapi_av1.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_av1.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,319 @@ +/* + * AV1 HW decode acceleration through VA API + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/pixdesc.h" +#include "hwconfig.h" +#include "vaapi_decode.h" +#include "av1dec.h" + +static VASurfaceID vaapi_av1_surface_id(AV1Frame *vf) +{ + if (vf) + return ff_vaapi_get_surface_id(vf->tf.f); + else + return VA_INVALID_SURFACE; +} + +static int8_t vaapi_av1_get_bit_depth_idx(AVCodecContext *avctx) +{ + AV1DecContext *s = avctx->priv_data; + const AV1RawSequenceHeader *seq = s->raw_seq; + int8_t bit_depth = 8; + + if (seq->seq_profile == 2 && seq->color_config.high_bitdepth) + bit_depth = seq->color_config.twelve_bit ? 12 : 10; + else if (seq->seq_profile <= 2) + bit_depth = seq->color_config.high_bitdepth ? 10 : 8; + else { + av_log(avctx, AV_LOG_ERROR, + "Couldn't get bit depth from profile:%d.\n", seq->seq_profile); + return -1; + } + return bit_depth == 8 ? 0 : bit_depth == 10 ? 1 : 2; +} + +static int vaapi_av1_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + AV1DecContext *s = avctx->priv_data; + const AV1RawSequenceHeader *seq = s->raw_seq; + const AV1RawFrameHeader *frame_header = s->raw_frame_header; + const AV1RawFilmGrainParams *film_grain = &s->cur_frame.film_grain; + VAAPIDecodePicture *pic = s->cur_frame.hwaccel_picture_private; + VADecPictureParameterBufferAV1 pic_param; + int8_t bit_depth_idx; + int err = 0; + int apply_grain = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && film_grain->apply_grain; + uint8_t remap_lr_type[4] = {AV1_RESTORE_NONE, AV1_RESTORE_SWITCHABLE, AV1_RESTORE_WIENER, AV1_RESTORE_SGRPROJ}; + + pic->output_surface = vaapi_av1_surface_id(&s->cur_frame); + + bit_depth_idx = vaapi_av1_get_bit_depth_idx(avctx); + if (bit_depth_idx < 0) + goto fail; + + memset(&pic_param, 0, sizeof(VADecPictureParameterBufferAV1)); + pic_param = (VADecPictureParameterBufferAV1) { + .profile = seq->seq_profile, + .order_hint_bits_minus_1 = seq->order_hint_bits_minus_1, + .bit_depth_idx = bit_depth_idx, + .current_frame = pic->output_surface, + .current_display_picture = pic->output_surface, + .frame_width_minus1 = frame_header->frame_width_minus_1, + .frame_height_minus1 = frame_header->frame_height_minus_1, + .primary_ref_frame = frame_header->primary_ref_frame, + .order_hint = frame_header->order_hint, + .tile_cols = frame_header->tile_cols, + .tile_rows = frame_header->tile_rows, + .context_update_tile_id = frame_header->context_update_tile_id, + .interp_filter = frame_header->interpolation_filter, + .filter_level[0] = frame_header->loop_filter_level[0], + .filter_level[1] = frame_header->loop_filter_level[1], + .filter_level_u = frame_header->loop_filter_level[2], + .filter_level_v = frame_header->loop_filter_level[3], + .base_qindex = frame_header->base_q_idx, + .cdef_damping_minus_3 = frame_header->cdef_damping_minus_3, + .cdef_bits = frame_header->cdef_bits, + .seq_info_fields.fields = { + .still_picture = seq->still_picture, + .use_128x128_superblock = seq->use_128x128_superblock, + .enable_filter_intra = seq->enable_filter_intra, + .enable_intra_edge_filter = seq->enable_intra_edge_filter, + .enable_interintra_compound = seq->enable_interintra_compound, + .enable_masked_compound = seq->enable_masked_compound, + .enable_dual_filter = seq->enable_dual_filter, + .enable_order_hint = seq->enable_order_hint, + .enable_jnt_comp = seq->enable_jnt_comp, + .enable_cdef = seq->enable_cdef, + .mono_chrome = seq->color_config.mono_chrome, + .color_range = seq->color_config.color_range, + .subsampling_x = seq->color_config.subsampling_x, + .subsampling_y = seq->color_config.subsampling_y, + .chroma_sample_position = seq->color_config.chroma_sample_position, + .film_grain_params_present = seq->film_grain_params_present && + !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN), + }, + .seg_info.segment_info_fields.bits = { + .enabled = frame_header->segmentation_enabled, + .update_map = frame_header->segmentation_update_map, + .temporal_update = frame_header->segmentation_temporal_update, + .update_data = frame_header->segmentation_update_data, + }, + .film_grain_info = { + .film_grain_info_fields.bits = { + .apply_grain = apply_grain, + .chroma_scaling_from_luma = film_grain->chroma_scaling_from_luma, + .grain_scaling_minus_8 = film_grain->grain_scaling_minus_8, + .ar_coeff_lag = film_grain->ar_coeff_lag, + .ar_coeff_shift_minus_6 = film_grain->ar_coeff_shift_minus_6, + .grain_scale_shift = film_grain->grain_scale_shift, + .overlap_flag = film_grain->overlap_flag, + .clip_to_restricted_range = film_grain->clip_to_restricted_range, + }, + .grain_seed = film_grain->grain_seed, + .num_y_points = film_grain->num_y_points, + .num_cb_points = film_grain->num_cb_points, + .num_cr_points = film_grain->num_cr_points, + .cb_mult = film_grain->cb_mult, + .cb_luma_mult = film_grain->cb_luma_mult, + .cb_offset = film_grain->cb_offset, + .cr_mult = film_grain->cr_mult, + .cr_luma_mult = film_grain->cr_luma_mult, + .cr_offset = film_grain->cr_offset, + }, + .pic_info_fields.bits = { + .frame_type = frame_header->frame_type, + .show_frame = frame_header->show_frame, + .showable_frame = frame_header->showable_frame, + .error_resilient_mode = frame_header->error_resilient_mode, + .disable_cdf_update = frame_header->disable_cdf_update, + .allow_screen_content_tools = frame_header->allow_screen_content_tools, + .force_integer_mv = frame_header->force_integer_mv, + .allow_intrabc = frame_header->allow_intrabc, + .use_superres = frame_header->use_superres, + .allow_high_precision_mv = frame_header->allow_high_precision_mv, + .is_motion_mode_switchable = frame_header->is_motion_mode_switchable, + .use_ref_frame_mvs = frame_header->use_ref_frame_mvs, + .disable_frame_end_update_cdf = frame_header->disable_frame_end_update_cdf, + .uniform_tile_spacing_flag = frame_header->uniform_tile_spacing_flag, + .allow_warped_motion = frame_header->allow_warped_motion, + }, + .loop_filter_info_fields.bits = { + .sharpness_level = frame_header->loop_filter_sharpness, + .mode_ref_delta_enabled = frame_header->loop_filter_delta_enabled, + .mode_ref_delta_update = frame_header->loop_filter_delta_update, + }, + .mode_control_fields.bits = { + .delta_q_present_flag = frame_header->delta_q_present, + .log2_delta_q_res = frame_header->delta_q_res, + .tx_mode = frame_header->tx_mode, + .reference_select = frame_header->reference_select, + .reduced_tx_set_used = frame_header->reduced_tx_set, + .skip_mode_present = frame_header->skip_mode_present, + }, + .loop_restoration_fields.bits = { + .yframe_restoration_type = remap_lr_type[frame_header->lr_type[0]], + .cbframe_restoration_type = remap_lr_type[frame_header->lr_type[1]], + .crframe_restoration_type = remap_lr_type[frame_header->lr_type[2]], + .lr_unit_shift = frame_header->lr_unit_shift, + .lr_uv_shift = frame_header->lr_uv_shift, + }, + .qmatrix_fields.bits = { + .using_qmatrix = frame_header->using_qmatrix, + } + }; + + for (int i = 0; i < AV1_NUM_REF_FRAMES; i++) { + if (pic_param.pic_info_fields.bits.frame_type == AV1_FRAME_KEY) + pic_param.ref_frame_map[i] = VA_INVALID_ID; + else + pic_param.ref_frame_map[i] = vaapi_av1_surface_id(&s->ref[i]); + } + for (int i = 0; i < AV1_REFS_PER_FRAME; i++) { + pic_param.ref_frame_idx[i] = frame_header->ref_frame_idx[i]; + } + for (int i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) { + pic_param.ref_deltas[i] = frame_header->loop_filter_ref_deltas[i]; + } + for (int i = 0; i < 2; i++) { + pic_param.mode_deltas[i] = frame_header->loop_filter_mode_deltas[i]; + } + for (int i = 0; i < (1 << frame_header->cdef_bits); i++) { + pic_param.cdef_y_strengths[i] = + (frame_header->cdef_y_pri_strength[i] << 2) + + frame_header->cdef_y_sec_strength[i]; + pic_param.cdef_uv_strengths[i] = + (frame_header->cdef_uv_pri_strength[i] << 2) + + frame_header->cdef_uv_sec_strength[i]; + } + for (int i = 0; i < frame_header->tile_cols; i++) { + pic_param.width_in_sbs_minus_1[i] = + frame_header->width_in_sbs_minus_1[i]; + } + for (int i = 0; i < frame_header->tile_rows; i++) { + pic_param.height_in_sbs_minus_1[i] = + frame_header->height_in_sbs_minus_1[i]; + } + for (int i = AV1_REF_FRAME_LAST; i <= AV1_REF_FRAME_ALTREF; i++) { + pic_param.wm[i - 1].wmtype = s->cur_frame.gm_type[i]; + for (int j = 0; j < 6; j++) + pic_param.wm[i - 1].wmmat[j] = s->cur_frame.gm_params[i][j]; + } + if (apply_grain) { + for (int i = 0; i < film_grain->num_y_points; i++) { + pic_param.film_grain_info.point_y_value[i] = + film_grain->point_y_value[i]; + pic_param.film_grain_info.point_y_scaling[i] = + film_grain->point_y_scaling[i]; + } + for (int i = 0; i < film_grain->num_cb_points; i++) { + pic_param.film_grain_info.point_cb_value[i] = + film_grain->point_cb_value[i]; + pic_param.film_grain_info.point_cb_scaling[i] = + film_grain->point_cb_scaling[i]; + } + for (int i = 0; i < film_grain->num_cr_points; i++) { + pic_param.film_grain_info.point_cr_value[i] = + film_grain->point_cr_value[i]; + pic_param.film_grain_info.point_cr_scaling[i] = + film_grain->point_cr_scaling[i]; + } + for (int i = 0; i < 24; i++) { + pic_param.film_grain_info.ar_coeffs_y[i] = + film_grain->ar_coeffs_y_plus_128[i] - 128; + } + for (int i = 0; i < 25; i++) { + pic_param.film_grain_info.ar_coeffs_cb[i] = + film_grain->ar_coeffs_cb_plus_128[i] - 128; + pic_param.film_grain_info.ar_coeffs_cr[i] = + film_grain->ar_coeffs_cr_plus_128[i] - 128; + } + } + err = ff_vaapi_decode_make_param_buffer(avctx, pic, + VAPictureParameterBufferType, + &pic_param, sizeof(pic_param)); + if (err < 0) + goto fail; + + return 0; + +fail: + ff_vaapi_decode_cancel(avctx, pic); + return err; +} + +static int vaapi_av1_end_frame(AVCodecContext *avctx) +{ + const AV1DecContext *s = avctx->priv_data; + VAAPIDecodePicture *pic = s->cur_frame.hwaccel_picture_private; + return ff_vaapi_decode_issue(avctx, pic); +} + +static int vaapi_av1_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + const AV1DecContext *s = avctx->priv_data; + VAAPIDecodePicture *pic = s->cur_frame.hwaccel_picture_private; + VASliceParameterBufferAV1 slice_param; + int err = 0; + + for (int i = s->tg_start; i <= s->tg_end; i++) { + memset(&slice_param, 0, sizeof(VASliceParameterBufferAV1)); + + slice_param = (VASliceParameterBufferAV1) { + .slice_data_size = s->tile_group_info[i].tile_size, + .slice_data_offset = s->tile_group_info[i].tile_offset, + .slice_data_flag = VA_SLICE_DATA_FLAG_ALL, + .tile_row = s->tile_group_info[i].tile_row, + .tile_column = s->tile_group_info[i].tile_column, + .tg_start = s->tg_start, + .tg_end = s->tg_end, + }; + + err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &slice_param, + sizeof(VASliceParameterBufferAV1), + buffer, + s->tile_group_info[i].tile_size); + if (err) { + ff_vaapi_decode_cancel(avctx, pic); + return err; + } + } + + return 0; +} + +const AVHWAccel ff_av1_vaapi_hwaccel = { + .name = "av1_vaapi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .pix_fmt = AV_PIX_FMT_VAAPI, + .start_frame = vaapi_av1_start_frame, + .end_frame = vaapi_av1_end_frame, + .decode_slice = vaapi_av1_decode_slice, + .frame_priv_data_size = sizeof(VAAPIDecodePicture), + .init = ff_vaapi_decode_init, + .uninit = ff_vaapi_decode_uninit, + .frame_params = ff_vaapi_common_frame_params, + .priv_data_size = sizeof(VAAPIDecodeContext), + .caps_internal = HWACCEL_CAP_ASYNC_SAFE, +}; diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_decode.c ffmpeg-4.4/libavcodec/vaapi_decode.c --- ffmpeg-4.2.2/libavcodec/vaapi_decode.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_decode.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,7 @@ #include "decode.h" #include "internal.h" #include "vaapi_decode.h" +#include "vaapi_hevc.h" int ff_vaapi_decode_make_param_buffer(AVCodecContext *avctx, @@ -256,6 +257,10 @@ #ifdef VA_FOURCC_YV16 MAP(YV16, YUV422P), #endif + MAP(YUY2, YUYV422), +#ifdef VA_FOURCC_Y210 + MAP(Y210, Y210), +#endif // 4:4:0 MAP(422V, YUV440P), // 4:4:4 @@ -364,8 +369,9 @@ enum AVCodecID codec_id; int codec_profile; VAProfile va_profile; + VAProfile (*profile_parser)(AVCodecContext *avctx); } vaapi_profile_map[] = { -#define MAP(c, p, v) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, VAProfile ## v } +#define MAP(c, p, v, ...) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, VAProfile ## v, __VA_ARGS__ } MAP(MPEG2VIDEO, MPEG2_SIMPLE, MPEG2Simple ), MAP(MPEG2VIDEO, MPEG2_MAIN, MPEG2Main ), MAP(H263, UNKNOWN, H263Baseline), @@ -380,6 +386,12 @@ #if VA_CHECK_VERSION(0, 37, 0) MAP(HEVC, HEVC_MAIN, HEVCMain ), MAP(HEVC, HEVC_MAIN_10, HEVCMain10 ), + MAP(HEVC, HEVC_MAIN_STILL_PICTURE, + HEVCMain ), +#endif +#if VA_CHECK_VERSION(1, 2, 0) && CONFIG_HEVC_VAAPI_HWACCEL + MAP(HEVC, HEVC_REXT, None, + ff_vaapi_parse_hevc_rext_profile ), #endif MAP(MJPEG, MJPEG_HUFFMAN_BASELINE_DCT, JPEGBaseline), @@ -398,6 +410,11 @@ #if VA_CHECK_VERSION(0, 39, 0) MAP(VP9, VP9_2, VP9Profile2 ), #endif +#if VA_CHECK_VERSION(1, 8, 0) + MAP(AV1, AV1_MAIN, AV1Profile0), + MAP(AV1, AV1_HIGH, AV1Profile1), +#endif + #undef MAP }; @@ -415,8 +432,8 @@ VAStatus vas; int err, i, j; const AVCodecDescriptor *codec_desc; - VAProfile *profile_list = NULL, matched_va_profile; - int profile_count, exact_match, matched_ff_profile; + VAProfile *profile_list = NULL, matched_va_profile, va_profile; + int profile_count, exact_match, matched_ff_profile, codec_profile; AVHWDeviceContext *device = (AVHWDeviceContext*)device_ref->data; AVVAAPIDeviceContext *hwctx = device->hwctx; @@ -454,15 +471,21 @@ if (avctx->profile == vaapi_profile_map[i].codec_profile || vaapi_profile_map[i].codec_profile == FF_PROFILE_UNKNOWN) profile_match = 1; + + va_profile = vaapi_profile_map[i].profile_parser ? + vaapi_profile_map[i].profile_parser(avctx) : + vaapi_profile_map[i].va_profile; + codec_profile = vaapi_profile_map[i].codec_profile; + for (j = 0; j < profile_count; j++) { - if (vaapi_profile_map[i].va_profile == profile_list[j]) { + if (va_profile == profile_list[j]) { exact_match = profile_match; break; } } if (j < profile_count) { - matched_va_profile = vaapi_profile_map[i].va_profile; - matched_ff_profile = vaapi_profile_map[i].codec_profile; + matched_va_profile = va_profile; + matched_ff_profile = codec_profile; if (exact_match) break; } @@ -557,6 +580,7 @@ frames->initial_pool_size += 16; break; case AV_CODEC_ID_VP9: + case AV_CODEC_ID_AV1: frames->initial_pool_size += 8; break; case AV_CODEC_ID_VP8: diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_encode.c ffmpeg-4.4/libavcodec/vaapi_encode.c --- ffmpeg-4.2.2/libavcodec/vaapi_encode.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_encode.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,12 +21,19 @@ #include "libavutil/avassert.h" #include "libavutil/common.h" +#include "libavutil/internal.h" #include "libavutil/log.h" #include "libavutil/pixdesc.h" #include "vaapi_encode.h" +#include "encode.h" #include "avcodec.h" +const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[] = { + HW_CONFIG_ENCODER_FRAMES(VAAPI, VAAPI), + NULL, +}; + static const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; static int vaapi_encode_make_packed_header(AVCodecContext *avctx, @@ -157,6 +164,88 @@ return 0; } +static int vaapi_encode_make_row_slice(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeSlice *slice; + int i, rounding; + + for (i = 0; i < pic->nb_slices; i++) + pic->slices[i].row_size = ctx->slice_size; + + rounding = ctx->slice_block_rows - ctx->nb_slices * ctx->slice_size; + if (rounding > 0) { + // Place rounding error at top and bottom of frame. + av_assert0(rounding < pic->nb_slices); + // Some Intel drivers contain a bug where the encoder will fail + // if the last slice is smaller than the one before it. Since + // that's straightforward to avoid here, just do so. + if (rounding <= 2) { + for (i = 0; i < rounding; i++) + ++pic->slices[i].row_size; + } else { + for (i = 0; i < (rounding + 1) / 2; i++) + ++pic->slices[pic->nb_slices - i - 1].row_size; + for (i = 0; i < rounding / 2; i++) + ++pic->slices[i].row_size; + } + } else if (rounding < 0) { + // Remove rounding error from last slice only. + av_assert0(rounding < ctx->slice_size); + pic->slices[pic->nb_slices - 1].row_size += rounding; + } + + for (i = 0; i < pic->nb_slices; i++) { + slice = &pic->slices[i]; + slice->index = i; + if (i == 0) { + slice->row_start = 0; + slice->block_start = 0; + } else { + const VAAPIEncodeSlice *prev = &pic->slices[i - 1]; + slice->row_start = prev->row_start + prev->row_size; + slice->block_start = prev->block_start + prev->block_size; + } + slice->block_size = slice->row_size * ctx->slice_block_cols; + + av_log(avctx, AV_LOG_DEBUG, "Slice %d: %d-%d (%d rows), " + "%d-%d (%d blocks).\n", i, slice->row_start, + slice->row_start + slice->row_size - 1, slice->row_size, + slice->block_start, slice->block_start + slice->block_size - 1, + slice->block_size); + } + + return 0; +} + +static int vaapi_encode_make_tile_slice(AVCodecContext *avctx, + VAAPIEncodePicture *pic) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeSlice *slice; + int i, j, index; + + for (i = 0; i < ctx->tile_cols; i++) { + for (j = 0; j < ctx->tile_rows; j++) { + index = j * ctx->tile_cols + i; + slice = &pic->slices[index]; + slice->index = index; + + pic->slices[index].block_start = ctx->col_bd[i] + + ctx->row_bd[j] * ctx->slice_block_cols; + pic->slices[index].block_size = ctx->row_height[j] * ctx->col_width[i]; + + av_log(avctx, AV_LOG_DEBUG, "Slice %2d: (%2d, %2d) start at: %4d " + "width:%2d height:%2d (%d blocks).\n", index, ctx->col_bd[i], + ctx->row_bd[j], slice->block_start, ctx->col_width[i], + ctx->row_height[j], slice->block_size); + } + } + + return 0; +} + static int vaapi_encode_issue(AVCodecContext *avctx, VAAPIEncodePicture *pic) { @@ -166,6 +255,7 @@ int err, i; char data[MAX_PARAM_BUFFER_SIZE]; size_t bit_len; + av_unused AVFrameSideData *sd; av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" " "as type %s.\n", pic->display_order, pic->encode_order, @@ -339,57 +429,20 @@ if (pic->nb_slices == 0) pic->nb_slices = ctx->nb_slices; if (pic->nb_slices > 0) { - int rounding; - pic->slices = av_mallocz_array(pic->nb_slices, sizeof(*pic->slices)); if (!pic->slices) { err = AVERROR(ENOMEM); goto fail; } - for (i = 0; i < pic->nb_slices; i++) - pic->slices[i].row_size = ctx->slice_size; - - rounding = ctx->slice_block_rows - ctx->nb_slices * ctx->slice_size; - if (rounding > 0) { - // Place rounding error at top and bottom of frame. - av_assert0(rounding < pic->nb_slices); - // Some Intel drivers contain a bug where the encoder will fail - // if the last slice is smaller than the one before it. Since - // that's straightforward to avoid here, just do so. - if (rounding <= 2) { - for (i = 0; i < rounding; i++) - ++pic->slices[i].row_size; - } else { - for (i = 0; i < (rounding + 1) / 2; i++) - ++pic->slices[pic->nb_slices - i - 1].row_size; - for (i = 0; i < rounding / 2; i++) - ++pic->slices[i].row_size; - } - } else if (rounding < 0) { - // Remove rounding error from last slice only. - av_assert0(rounding < ctx->slice_size); - pic->slices[pic->nb_slices - 1].row_size += rounding; - } + if (ctx->tile_rows && ctx->tile_cols) + vaapi_encode_make_tile_slice(avctx, pic); + else + vaapi_encode_make_row_slice(avctx, pic); } + for (i = 0; i < pic->nb_slices; i++) { slice = &pic->slices[i]; - slice->index = i; - if (i == 0) { - slice->row_start = 0; - slice->block_start = 0; - } else { - const VAAPIEncodeSlice *prev = &pic->slices[i - 1]; - slice->row_start = prev->row_start + prev->row_size; - slice->block_start = prev->block_start + prev->block_size; - } - slice->block_size = slice->row_size * ctx->slice_block_cols; - - av_log(avctx, AV_LOG_DEBUG, "Slice %d: %d-%d (%d rows), " - "%d-%d (%d blocks).\n", i, slice->row_start, - slice->row_start + slice->row_size - 1, slice->row_size, - slice->block_start, slice->block_start + slice->block_size - 1, - slice->block_size); if (ctx->codec->slice_params_size > 0) { slice->codec_slice_params = av_mallocz(ctx->codec->slice_params_size); @@ -435,6 +488,71 @@ } } +#if VA_CHECK_VERSION(1, 0, 0) + sd = av_frame_get_side_data(pic->input_image, + AV_FRAME_DATA_REGIONS_OF_INTEREST); + if (sd && ctx->roi_allowed) { + const AVRegionOfInterest *roi; + uint32_t roi_size; + VAEncMiscParameterBufferROI param_roi; + int nb_roi, i, v; + + roi = (const AVRegionOfInterest*)sd->data; + roi_size = roi->self_size; + av_assert0(roi_size && sd->size % roi_size == 0); + nb_roi = sd->size / roi_size; + if (nb_roi > ctx->roi_max_regions) { + if (!ctx->roi_warned) { + av_log(avctx, AV_LOG_WARNING, "More ROIs set than " + "supported by driver (%d > %d).\n", + nb_roi, ctx->roi_max_regions); + ctx->roi_warned = 1; + } + nb_roi = ctx->roi_max_regions; + } + + pic->roi = av_mallocz_array(nb_roi, sizeof(*pic->roi)); + if (!pic->roi) { + err = AVERROR(ENOMEM); + goto fail; + } + // For overlapping regions, the first in the array takes priority. + for (i = 0; i < nb_roi; i++) { + roi = (const AVRegionOfInterest*)(sd->data + roi_size * i); + + av_assert0(roi->qoffset.den != 0); + v = roi->qoffset.num * ctx->roi_quant_range / roi->qoffset.den; + av_log(avctx, AV_LOG_DEBUG, "ROI: (%d,%d)-(%d,%d) -> %+d.\n", + roi->top, roi->left, roi->bottom, roi->right, v); + + pic->roi[i] = (VAEncROI) { + .roi_rectangle = { + .x = roi->left, + .y = roi->top, + .width = roi->right - roi->left, + .height = roi->bottom - roi->top, + }, + .roi_value = av_clip_int8(v), + }; + } + + param_roi = (VAEncMiscParameterBufferROI) { + .num_roi = nb_roi, + .max_delta_qp = INT8_MAX, + .min_delta_qp = INT8_MIN, + .roi = pic->roi, + .roi_flags.bits.roi_value_is_qp_delta = 1, + }; + + err = vaapi_encode_make_misc_param_buffer(avctx, pic, + VAEncMiscParameterTypeROI, + ¶m_roi, + sizeof(param_roi)); + if (err < 0) + goto fail; + } +#endif + vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context, pic->input_surface); if (vas != VA_STATUS_SUCCESS) { @@ -490,16 +608,15 @@ fail: for(i = 0; i < pic->nb_param_buffers; i++) vaDestroyBuffer(ctx->hwctx->display, pic->param_buffers[i]); - for (i = 0; i < pic->nb_slices; i++) { - if (pic->slices) { - av_freep(&pic->slices[i].priv_data); + if (pic->slices) { + for (i = 0; i < pic->nb_slices; i++) av_freep(&pic->slices[i].codec_slice_params); - } } fail_at_end: av_freep(&pic->codec_picture_params); av_freep(&pic->param_buffers); av_freep(&pic->slices); + av_freep(&pic->roi); av_frame_free(&pic->recon_image); av_buffer_unref(&pic->output_buffer_ref); pic->output_buffer = VA_INVALID_ID; @@ -512,6 +629,8 @@ VAAPIEncodeContext *ctx = avctx->priv_data; VACodedBufferSegment *buf_list, *buf; VAStatus vas; + int total_size = 0; + uint8_t *ptr; int err; err = vaapi_encode_wait(avctx, pic); @@ -528,15 +647,21 @@ goto fail; } + for (buf = buf_list; buf; buf = buf->next) + total_size += buf->size; + + err = ff_get_encode_buffer(avctx, pkt, total_size, 0); + ptr = pkt->data; + + if (err < 0) + goto fail_mapped; + for (buf = buf_list; buf; buf = buf->next) { av_log(avctx, AV_LOG_DEBUG, "Output buffer: %u bytes " "(status %08x).\n", buf->size, buf->status); - err = av_new_packet(pkt, buf->size); - if (err < 0) - goto fail_mapped; - - memcpy(pkt->data, buf->buf, buf->size); + memcpy(ptr, buf->buf, buf->size); + ptr += buf->size; } if (pic->type == PICTURE_TYPE_IDR) @@ -616,11 +741,9 @@ if (pic->encode_issued) vaapi_encode_discard(avctx, pic); - for (i = 0; i < pic->nb_slices; i++) { - if (pic->slices) { - av_freep(&pic->slices[i].priv_data); + if (pic->slices) { + for (i = 0; i < pic->nb_slices; i++) av_freep(&pic->slices[i].codec_slice_params); - } } av_freep(&pic->codec_picture_params); @@ -634,6 +757,7 @@ av_freep(&pic->priv_data); av_freep(&pic->codec_picture_params); + av_freep(&pic->roi); av_free(pic); @@ -948,10 +1072,21 @@ ctx->crop_warned = 1; } + if (!ctx->roi_allowed) { + AVFrameSideData *sd = + av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST); + + if (sd && !ctx->roi_warned) { + av_log(avctx, AV_LOG_WARNING, "ROI side data on input " + "frames ignored due to lack of driver support.\n"); + ctx->roi_warned = 1; + } + } + return 0; } -int ff_vaapi_encode_send_frame(AVCodecContext *avctx, const AVFrame *frame) +static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; @@ -974,16 +1109,15 @@ err = AVERROR(ENOMEM); goto fail; } - err = av_frame_ref(pic->input_image, frame); - if (err < 0) - goto fail; - if (ctx->input_order == 0) + if (ctx->input_order == 0 || frame->pict_type == AV_PICTURE_TYPE_I) pic->force_idr = 1; pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->pts = frame->pts; + av_frame_move_ref(pic->input_image, frame); + if (ctx->input_order == 0) ctx->first_pts = pic->pts; if (ctx->input_order == ctx->decode_delay) @@ -1014,6 +1148,7 @@ return 0; fail: + vaapi_encode_free(avctx, pic); return err; } @@ -1021,8 +1156,20 @@ { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; + AVFrame *frame = ctx->frame; int err; + err = ff_encode_get_frame(avctx, frame); + if (err < 0 && err != AVERROR_EOF) + return err; + + if (err == AVERROR_EOF) + frame = NULL; + + err = vaapi_encode_send_frame(avctx, frame); + if (err < 0) + return err; + if (!ctx->pic_start) { if (ctx->end_of_stream) return AVERROR_EOF; @@ -1098,6 +1245,9 @@ { "YUV400", VA_RT_FORMAT_YUV400, 8, 1, }, { "YUV420", VA_RT_FORMAT_YUV420, 8, 3, 1, 1 }, { "YUV422", VA_RT_FORMAT_YUV422, 8, 3, 1, 0 }, +#if VA_CHECK_VERSION(1, 2, 0) + { "YUV422_10", VA_RT_FORMAT_YUV422_10, 10, 3, 1, 0 }, +#endif { "YUV444", VA_RT_FORMAT_YUV444, 8, 3, 0, 0 }, { "YUV411", VA_RT_FORMAT_YUV411, 8, 3, 2, 0 }, #if VA_CHECK_VERSION(0, 38, 1) @@ -1735,14 +1885,124 @@ return 0; } +static av_cold int vaapi_encode_init_row_slice_structure(AVCodecContext *avctx, + uint32_t slice_structure) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + int req_slices; + + // For fixed-size slices currently we only support whole rows, making + // rectangular slices. This could be extended to arbitrary runs of + // blocks, but since slices tend to be a conformance requirement and + // most cases (such as broadcast or bluray) want rectangular slices + // only it would need to be gated behind another option. + if (avctx->slices > ctx->slice_block_rows) { + av_log(avctx, AV_LOG_WARNING, "Not enough rows to use " + "configured number of slices (%d < %d); using " + "maximum.\n", ctx->slice_block_rows, avctx->slices); + req_slices = ctx->slice_block_rows; + } else { + req_slices = avctx->slices; + } + if (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS || + slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) { + ctx->nb_slices = req_slices; + ctx->slice_size = ctx->slice_block_rows / ctx->nb_slices; + } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) { + int k; + for (k = 1;; k *= 2) { + if (2 * k * (req_slices - 1) + 1 >= ctx->slice_block_rows) + break; + } + ctx->nb_slices = (ctx->slice_block_rows + k - 1) / k; + ctx->slice_size = k; +#if VA_CHECK_VERSION(1, 0, 0) + } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS) { + ctx->nb_slices = ctx->slice_block_rows; + ctx->slice_size = 1; +#endif + } else { + av_log(avctx, AV_LOG_ERROR, "Driver does not support any usable " + "slice structure modes (%#x).\n", slice_structure); + return AVERROR(EINVAL); + } + + return 0; +} + +static av_cold int vaapi_encode_init_tile_slice_structure(AVCodecContext *avctx, + uint32_t slice_structure) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + int i, req_tiles; + + if (!(slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS || + (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS && + ctx->tile_cols == 1))) { + av_log(avctx, AV_LOG_ERROR, "Supported slice structure (%#x) doesn't work for " + "current tile requirement.\n", slice_structure); + return AVERROR(EINVAL); + } + + if (ctx->tile_rows > ctx->slice_block_rows || + ctx->tile_cols > ctx->slice_block_cols) { + av_log(avctx, AV_LOG_WARNING, "Not enough block rows/cols (%d x %d) " + "for configured number of tile (%d x %d); ", + ctx->slice_block_rows, ctx->slice_block_cols, + ctx->tile_rows, ctx->tile_cols); + ctx->tile_rows = ctx->tile_rows > ctx->slice_block_rows ? + ctx->slice_block_rows : ctx->tile_rows; + ctx->tile_cols = ctx->tile_cols > ctx->slice_block_cols ? + ctx->slice_block_cols : ctx->tile_cols; + av_log(avctx, AV_LOG_WARNING, "using allowed maximum (%d x %d).\n", + ctx->tile_rows, ctx->tile_cols); + } + + req_tiles = ctx->tile_rows * ctx->tile_cols; + + // Tile slice is not allowed to cross the boundary of a tile due to + // the constraints of media-driver. Currently we support one slice + // per tile. This could be extended to multiple slices per tile. + if (avctx->slices != req_tiles) + av_log(avctx, AV_LOG_WARNING, "The number of requested slices " + "mismatches with configured number of tile (%d != %d); " + "using requested tile number for slice.\n", + avctx->slices, req_tiles); + + ctx->nb_slices = req_tiles; + + // Default in uniform spacing + // 6-3, 6-5 + for (i = 0; i < ctx->tile_cols; i++) { + ctx->col_width[i] = ( i + 1 ) * ctx->slice_block_cols / ctx->tile_cols - + i * ctx->slice_block_cols / ctx->tile_cols; + ctx->col_bd[i + 1] = ctx->col_bd[i] + ctx->col_width[i]; + } + // 6-4, 6-6 + for (i = 0; i < ctx->tile_rows; i++) { + ctx->row_height[i] = ( i + 1 ) * ctx->slice_block_rows / ctx->tile_rows - + i * ctx->slice_block_rows / ctx->tile_rows; + ctx->row_bd[i + 1] = ctx->row_bd[i] + ctx->row_height[i]; + } + + av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d x %d tile.\n", + ctx->tile_rows, ctx->tile_cols); + + return 0; +} + static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; - VAConfigAttrib attr[2] = { { VAConfigAttribEncMaxSlices }, - { VAConfigAttribEncSliceStructure } }; + VAConfigAttrib attr[3] = { { VAConfigAttribEncMaxSlices }, + { VAConfigAttribEncSliceStructure }, +#if VA_CHECK_VERSION(1, 1, 0) + { VAConfigAttribEncTileSupport }, +#endif + }; VAStatus vas; uint32_t max_slices, slice_structure; - int req_slices; + int ret; if (!(ctx->codec->flags & FLAG_SLICE_CONTROL)) { if (avctx->slices > 0) { @@ -1757,7 +2017,7 @@ ctx->slice_block_cols = (avctx->width + ctx->slice_block_width - 1) / ctx->slice_block_width; - if (avctx->slices <= 1) { + if (avctx->slices <= 1 && !ctx->tile_rows && !ctx->tile_cols) { ctx->nb_slices = 1; ctx->slice_size = ctx->slice_block_rows; return 0; @@ -1781,42 +2041,28 @@ return AVERROR(EINVAL); } - // For fixed-size slices currently we only support whole rows, making - // rectangular slices. This could be extended to arbitrary runs of - // blocks, but since slices tend to be a conformance requirement and - // most cases (such as broadcast or bluray) want rectangular slices - // only it would need to be gated behind another option. - if (avctx->slices > ctx->slice_block_rows) { - av_log(avctx, AV_LOG_WARNING, "Not enough rows to use " - "configured number of slices (%d < %d); using " - "maximum.\n", ctx->slice_block_rows, avctx->slices); - req_slices = ctx->slice_block_rows; - } else { - req_slices = avctx->slices; - } - if (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS || - slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) { - ctx->nb_slices = req_slices; - ctx->slice_size = ctx->slice_block_rows / ctx->nb_slices; - } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) { - int k; - for (k = 1;; k *= 2) { - if (2 * k * (req_slices - 1) + 1 >= ctx->slice_block_rows) - break; + if (ctx->tile_rows && ctx->tile_cols) { +#if VA_CHECK_VERSION(1, 1, 0) + uint32_t tile_support = attr[2].value; + if (tile_support == VA_ATTRIB_NOT_SUPPORTED) { + av_log(avctx, AV_LOG_ERROR, "Driver does not support encoding " + "pictures as multiple tiles.\n."); + return AVERROR(EINVAL); } - ctx->nb_slices = (ctx->slice_block_rows + k - 1) / k; - ctx->slice_size = k; -#if VA_CHECK_VERSION(1, 0, 0) - } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS) { - ctx->nb_slices = ctx->slice_block_rows; - ctx->slice_size = 1; -#endif - } else { - av_log(avctx, AV_LOG_ERROR, "Driver does not support any usable " - "slice structure modes (%#x).\n", slice_structure); +#else + av_log(avctx, AV_LOG_ERROR, "Tile encoding option is " + "not supported with this VAAPI version.\n"); return AVERROR(EINVAL); +#endif } + if (ctx->tile_rows && ctx->tile_cols) + ret = vaapi_encode_init_tile_slice_structure(avctx, slice_structure); + else + ret = vaapi_encode_init_row_slice_structure(avctx, slice_structure); + if (ret < 0) + return ret; + if (ctx->nb_slices > avctx->slices) { av_log(avctx, AV_LOG_WARNING, "Slice count rounded up to " "%d (from %d) due to driver constraints on slice " @@ -1829,9 +2075,8 @@ return AVERROR(EINVAL); } - av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices " - "(default size %d block rows).\n", - ctx->nb_slices, ctx->slice_size); + av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices.\n", + ctx->nb_slices); return 0; } @@ -1942,6 +2187,39 @@ return 0; } +static av_cold int vaapi_encode_init_roi(AVCodecContext *avctx) +{ +#if VA_CHECK_VERSION(1, 0, 0) + VAAPIEncodeContext *ctx = avctx->priv_data; + VAStatus vas; + VAConfigAttrib attr = { VAConfigAttribEncROI }; + + vas = vaGetConfigAttributes(ctx->hwctx->display, + ctx->va_profile, + ctx->va_entrypoint, + &attr, 1); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query ROI " + "config attribute: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR_EXTERNAL; + } + + if (attr.value == VA_ATTRIB_NOT_SUPPORTED) { + ctx->roi_allowed = 0; + } else { + VAConfigAttribValEncROI roi = { + .value = attr.value, + }; + + ctx->roi_max_regions = roi.bits.num_roi_regions; + ctx->roi_allowed = ctx->roi_max_regions > 0 && + (ctx->va_rc_mode == VA_RC_CQP || + roi.bits.roi_rc_qp_delta_support); + } +#endif + return 0; +} + static void vaapi_encode_free_output_buffer(void *opaque, uint8_t *data) { @@ -1957,7 +2235,7 @@ } static AVBufferRef *vaapi_encode_alloc_output_buffer(void *opaque, - int size) + buffer_size_t size) { AVCodecContext *avctx = opaque; VAAPIEncodeContext *ctx = avctx->priv_data; @@ -2088,6 +2366,11 @@ VAStatus vas; int err; + ctx->frame = av_frame_alloc(); + if (!ctx->frame) { + return AVERROR(ENOMEM); + } + if (!avctx->hw_frames_ctx) { av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is " "required to associate the encoding device.\n"); @@ -2132,6 +2415,10 @@ if (err < 0) goto fail; + err = vaapi_encode_init_roi(avctx); + if (err < 0) + goto fail; + if (avctx->compression_level >= 0) { err = vaapi_encode_init_quality(avctx); if (err < 0) @@ -2236,7 +2523,6 @@ return 0; fail: - ff_vaapi_encode_close(avctx); return err; } @@ -2262,6 +2548,8 @@ ctx->va_config = VA_INVALID_ID; } + av_frame_free(&ctx->frame); + av_freep(&ctx->codec_sequence_params); av_freep(&ctx->codec_picture_params); diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_encode.h ffmpeg-4.4/libavcodec/vaapi_encode.h --- ffmpeg-4.2.2/libavcodec/vaapi_encode.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_encode.h 2021-04-08 21:28:39.000000000 +0000 @@ -31,6 +31,7 @@ #include "libavutil/hwcontext_vaapi.h" #include "avcodec.h" +#include "hwconfig.h" struct VAAPIEncodeType; struct VAAPIEncodePicture; @@ -42,8 +43,14 @@ MAX_PICTURE_REFERENCES = 2, MAX_REORDER_DELAY = 16, MAX_PARAM_BUFFER_SIZE = 1024, + // A.4.1: table A.6 allows at most 22 tile rows for any level. + MAX_TILE_ROWS = 22, + // A.4.1: table A.6 allows at most 20 tile columns for any level. + MAX_TILE_COLS = 20, }; +extern const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[]; + enum { PICTURE_TYPE_IDR = 0, PICTURE_TYPE_I = 1, @@ -57,7 +64,6 @@ int row_size; int block_start; int block_size; - void *priv_data; void *codec_slice_params; } VAAPIEncodeSlice; @@ -69,6 +75,13 @@ int64_t pts; int force_idr; +#if VA_CHECK_VERSION(1, 0, 0) + // ROI regions. + VAEncROI *roi; +#else + void *roi; +#endif + int type; int b_depth; int encode_issued; @@ -292,6 +305,18 @@ int nb_slices; int slice_size; + // Tile encoding. + int tile_cols; + int tile_rows; + // Tile width of the i-th column. + int col_width[MAX_TILE_COLS]; + // Tile height of i-th row. + int row_height[MAX_TILE_ROWS]; + // Location of the i-th tile column boundary. + int col_bd[MAX_TILE_COLS + 1]; + // Location of the i-th tile row boundary. + int row_bd[MAX_TILE_ROWS + 1]; + // Frame type decision. int gop_size; int closed_gop; @@ -304,9 +329,22 @@ int gop_counter; int end_of_stream; + // Whether the driver supports ROI at all. + int roi_allowed; + // Maximum number of regions supported by the driver. + int roi_max_regions; + // Quantisation range for offset calculations. Set by codec-specific + // code, as it may change based on parameters. + int roi_quant_range; + // The encoder does not support cropping information, so warn about // it the first time we encounter any nonzero crop fields. int crop_warned; + // If the driver does not support ROI then warn the first time we + // encounter a frame with ROI side data. + int roi_warned; + + AVFrame *frame; } VAAPIEncodeContext; enum { @@ -398,7 +436,6 @@ } VAAPIEncodeType; -int ff_vaapi_encode_send_frame(AVCodecContext *avctx, const AVFrame *frame); int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_vaapi_encode_init(AVCodecContext *avctx); diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_encode_h264.c ffmpeg-4.4/libavcodec/vaapi_encode_h264.c --- ffmpeg-4.2.2/libavcodec/vaapi_encode_h264.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_encode_h264.c 2021-04-08 21:28:39.000000000 +0000 @@ -90,13 +90,12 @@ H264RawAUD raw_aud; H264RawSPS raw_sps; H264RawPPS raw_pps; - H264RawSEI raw_sei; H264RawSlice raw_slice; H264RawSEIBufferingPeriod sei_buffering_period; H264RawSEIPicTiming sei_pic_timing; H264RawSEIRecoveryPoint sei_recovery_point; - H264RawSEIUserDataUnregistered sei_identifier; + SEIRawUserDataUnregistered sei_identifier; char *sei_identifier_string; int aud_needed; @@ -135,11 +134,10 @@ CodedBitstreamFragment *au, void *nal_unit) { - VAAPIEncodeH264Context *priv = avctx->priv_data; H264RawNALUnitHeader *header = nal_unit; int err; - err = ff_cbs_insert_unit_content(priv->cbc, au, -1, + err = ff_cbs_insert_unit_content(au, -1, header->nal_unit_type, nal_unit, NULL); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " @@ -174,7 +172,7 @@ err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au); fail: - ff_cbs_fragment_reset(priv->cbc, au); + ff_cbs_fragment_reset(au); return err; } @@ -200,7 +198,7 @@ err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au); fail: - ff_cbs_fragment_reset(priv->cbc, au); + ff_cbs_fragment_reset(au); return err; } @@ -211,11 +209,9 @@ { VAAPIEncodeH264Context *priv = avctx->priv_data; CodedBitstreamFragment *au = &priv->current_access_unit; - int err, i; + int err; if (priv->sei_needed) { - H264RawSEI *sei = &priv->raw_sei; - if (priv->aud_needed) { err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_aud); if (err < 0) @@ -223,48 +219,42 @@ priv->aud_needed = 0; } - *sei = (H264RawSEI) { - .nal_unit_header = { - .nal_unit_type = H264_NAL_SEI, - }, - }; - - i = 0; - if (priv->sei_needed & SEI_IDENTIFIER) { - sei->payload[i].payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED; - sei->payload[i].payload.user_data_unregistered = priv->sei_identifier; - ++i; + err = ff_cbs_sei_add_message(priv->cbc, au, 1, + SEI_TYPE_USER_DATA_UNREGISTERED, + &priv->sei_identifier, NULL); + if (err < 0) + goto fail; } if (priv->sei_needed & SEI_TIMING) { if (pic->type == PICTURE_TYPE_IDR) { - sei->payload[i].payload_type = H264_SEI_TYPE_BUFFERING_PERIOD; - sei->payload[i].payload.buffering_period = priv->sei_buffering_period; - ++i; + err = ff_cbs_sei_add_message(priv->cbc, au, 1, + SEI_TYPE_BUFFERING_PERIOD, + &priv->sei_buffering_period, NULL); + if (err < 0) + goto fail; } - sei->payload[i].payload_type = H264_SEI_TYPE_PIC_TIMING; - sei->payload[i].payload.pic_timing = priv->sei_pic_timing; - ++i; + err = ff_cbs_sei_add_message(priv->cbc, au, 1, + SEI_TYPE_PIC_TIMING, + &priv->sei_pic_timing, NULL); + if (err < 0) + goto fail; } if (priv->sei_needed & SEI_RECOVERY_POINT) { - sei->payload[i].payload_type = H264_SEI_TYPE_RECOVERY_POINT; - sei->payload[i].payload.recovery_point = priv->sei_recovery_point; - ++i; + err = ff_cbs_sei_add_message(priv->cbc, au, 1, + SEI_TYPE_RECOVERY_POINT, + &priv->sei_recovery_point, NULL); + if (err < 0) + goto fail; } - sei->payload_count = i; - av_assert0(sei->payload_count > 0); - - err = vaapi_encode_h264_add_nal(avctx, au, sei); - if (err < 0) - goto fail; priv->sei_needed = 0; err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au); if (err < 0) goto fail; - ff_cbs_fragment_reset(priv->cbc, au); + ff_cbs_fragment_reset(au); *type = VAEncPackedHeaderRawData; return 0; @@ -286,7 +276,7 @@ } fail: - ff_cbs_fragment_reset(priv->cbc, au); + ff_cbs_fragment_reset(au); return err; } @@ -412,30 +402,20 @@ sps->vui.aspect_ratio_info_present_flag = 1; } - if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || - avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + // Unspecified video format, from table E-2. + sps->vui.video_format = 5; + sps->vui.video_full_range_flag = + avctx->color_range == AVCOL_RANGE_JPEG; + sps->vui.colour_primaries = avctx->color_primaries; + sps->vui.transfer_characteristics = avctx->color_trc; + sps->vui.matrix_coefficients = avctx->colorspace; + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || avctx->color_trc != AVCOL_TRC_UNSPECIFIED || - avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { + avctx->colorspace != AVCOL_SPC_UNSPECIFIED) + sps->vui.colour_description_present_flag = 1; + if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || + sps->vui.colour_description_present_flag) sps->vui.video_signal_type_present_flag = 1; - sps->vui.video_format = 5; // Unspecified. - sps->vui.video_full_range_flag = - avctx->color_range == AVCOL_RANGE_JPEG; - - if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || - avctx->color_trc != AVCOL_TRC_UNSPECIFIED || - avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { - sps->vui.colour_description_present_flag = 1; - sps->vui.colour_primaries = avctx->color_primaries; - sps->vui.transfer_characteristics = avctx->color_trc; - sps->vui.matrix_coefficients = avctx->colorspace; - } - } else { - sps->vui.video_format = 5; - sps->vui.video_full_range_flag = 0; - sps->vui.colour_primaries = avctx->color_primaries; - sps->vui.transfer_characteristics = avctx->color_trc; - sps->vui.matrix_coefficients = avctx->colorspace; - } if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { sps->vui.chroma_loc_info_present_flag = 1; @@ -1130,6 +1110,8 @@ } } + ctx->roi_quant_range = 51 + 6 * (ctx->profile->depth - 8); + return 0; } @@ -1240,7 +1222,7 @@ { VAAPIEncodeH264Context *priv = avctx->priv_data; - ff_cbs_fragment_free(priv->cbc, &priv->current_access_unit); + ff_cbs_fragment_free(&priv->current_access_unit); ff_cbs_close(&priv->cbc); av_freep(&priv->sei_identifier_string); @@ -1349,15 +1331,17 @@ .id = AV_CODEC_ID_H264, .priv_data_size = sizeof(VAAPIEncodeH264Context), .init = &vaapi_encode_h264_init, - .send_frame = &ff_vaapi_encode_send_frame, .receive_packet = &ff_vaapi_encode_receive_packet, .close = &vaapi_encode_h264_close, .priv_class = &vaapi_encode_h264_class, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_h264_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .hw_configs = ff_vaapi_encode_hw_configs, .wrapper_name = "vaapi", }; diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_encode_h265.c ffmpeg-4.4/libavcodec/vaapi_encode_h265.c --- ffmpeg-4.2.2/libavcodec/vaapi_encode_h265.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_encode_h265.c 2021-04-08 21:28:39.000000000 +0000 @@ -73,11 +73,10 @@ H265RawVPS raw_vps; H265RawSPS raw_sps; H265RawPPS raw_pps; - H265RawSEI raw_sei; H265RawSlice raw_slice; - H265RawSEIMasteringDisplayColourVolume sei_mastering_display; - H265RawSEIContentLightLevelInfo sei_content_light_level; + SEIRawMasteringDisplayColourVolume sei_mastering_display; + SEIRawContentLightLevelInfo sei_content_light_level; CodedBitstreamContext *cbc; CodedBitstreamFragment current_access_unit; @@ -116,11 +115,10 @@ CodedBitstreamFragment *au, void *nal_unit) { - VAAPIEncodeH265Context *priv = avctx->priv_data; H265RawNALUnitHeader *header = nal_unit; int err; - err = ff_cbs_insert_unit_content(priv->cbc, au, -1, + err = ff_cbs_insert_unit_content(au, -1, header->nal_unit_type, nal_unit, NULL); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: " @@ -159,7 +157,7 @@ err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); fail: - ff_cbs_fragment_reset(priv->cbc, au); + ff_cbs_fragment_reset(au); return err; } @@ -185,7 +183,7 @@ err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); fail: - ff_cbs_fragment_reset(priv->cbc, au); + ff_cbs_fragment_reset(au); return err; } @@ -196,11 +194,9 @@ { VAAPIEncodeH265Context *priv = avctx->priv_data; CodedBitstreamFragment *au = &priv->current_access_unit; - int err, i; + int err; if (priv->sei_needed) { - H265RawSEI *sei = &priv->raw_sei; - if (priv->aud_needed) { err = vaapi_encode_h265_add_nal(avctx, au, &priv->aud); if (err < 0) @@ -208,41 +204,29 @@ priv->aud_needed = 0; } - *sei = (H265RawSEI) { - .nal_unit_header = { - .nal_unit_type = HEVC_NAL_SEI_PREFIX, - .nuh_layer_id = 0, - .nuh_temporal_id_plus1 = 1, - }, - }; - - i = 0; - if (priv->sei_needed & SEI_MASTERING_DISPLAY) { - sei->payload[i].payload_type = HEVC_SEI_TYPE_MASTERING_DISPLAY_INFO; - sei->payload[i].payload.mastering_display = priv->sei_mastering_display; - ++i; + err = ff_cbs_sei_add_message(priv->cbc, au, 1, + SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME, + &priv->sei_mastering_display, NULL); + if (err < 0) + goto fail; } if (priv->sei_needed & SEI_CONTENT_LIGHT_LEVEL) { - sei->payload[i].payload_type = HEVC_SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO; - sei->payload[i].payload.content_light_level = priv->sei_content_light_level; - ++i; + err = ff_cbs_sei_add_message(priv->cbc, au, 1, + SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO, + &priv->sei_content_light_level, NULL); + if (err < 0) + goto fail; } - sei->payload_count = i; - av_assert0(sei->payload_count > 0); - - err = vaapi_encode_h265_add_nal(avctx, au, sei); - if (err < 0) - goto fail; priv->sei_needed = 0; err = vaapi_encode_h265_write_access_unit(avctx, data, data_len, au); if (err < 0) goto fail; - ff_cbs_fragment_reset(priv->cbc, au); + ff_cbs_fragment_reset(au); *type = VAEncPackedHeaderRawData; return 0; @@ -251,7 +235,7 @@ } fail: - ff_cbs_fragment_reset(priv->cbc, au); + ff_cbs_fragment_reset(au); return err; } @@ -345,7 +329,7 @@ level = ff_h265_guess_level(ptl, avctx->bit_rate, ctx->surface_width, ctx->surface_height, - ctx->nb_slices, 1, 1, + ctx->nb_slices, ctx->tile_rows, ctx->tile_cols, (ctx->b_per_p > 0) + 1); if (level) { av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name); @@ -410,10 +394,10 @@ sps->conformance_window_flag = 1; sps->conf_win_left_offset = 0; sps->conf_win_right_offset = - (ctx->surface_width - avctx->width) / 2; + (ctx->surface_width - avctx->width) >> desc->log2_chroma_w; sps->conf_win_top_offset = 0; sps->conf_win_bottom_offset = - (ctx->surface_height - avctx->height) / 2; + (ctx->surface_height - avctx->height) >> desc->log2_chroma_h; } else { sps->conformance_window_flag = 0; } @@ -489,30 +473,20 @@ vui->aspect_ratio_info_present_flag = 1; } - if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || - avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + // Unspecified video format, from table E-2. + vui->video_format = 5; + vui->video_full_range_flag = + avctx->color_range == AVCOL_RANGE_JPEG; + vui->colour_primaries = avctx->color_primaries; + vui->transfer_characteristics = avctx->color_trc; + vui->matrix_coefficients = avctx->colorspace; + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || avctx->color_trc != AVCOL_TRC_UNSPECIFIED || - avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { + avctx->colorspace != AVCOL_SPC_UNSPECIFIED) + vui->colour_description_present_flag = 1; + if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED || + vui->colour_description_present_flag) vui->video_signal_type_present_flag = 1; - vui->video_format = 5; // Unspecified. - vui->video_full_range_flag = - avctx->color_range == AVCOL_RANGE_JPEG; - - if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || - avctx->color_trc != AVCOL_TRC_UNSPECIFIED || - avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { - vui->colour_description_present_flag = 1; - vui->colour_primaries = avctx->color_primaries; - vui->transfer_characteristics = avctx->color_trc; - vui->matrix_coefficients = avctx->colorspace; - } - } else { - vui->video_format = 5; - vui->video_full_range_flag = 0; - vui->colour_primaries = avctx->color_primaries; - vui->transfer_characteristics = avctx->color_trc; - vui->matrix_coefficients = avctx->colorspace; - } if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { vui->chroma_loc_info_present_flag = 1; @@ -556,8 +530,41 @@ pps->cu_qp_delta_enabled_flag = (ctx->va_rc_mode != VA_RC_CQP); pps->diff_cu_qp_delta_depth = 0; - pps->pps_loop_filter_across_slices_enabled_flag = 1; + if (ctx->tile_rows && ctx->tile_cols) { + int uniform_spacing; + pps->tiles_enabled_flag = 1; + pps->num_tile_columns_minus1 = ctx->tile_cols - 1; + pps->num_tile_rows_minus1 = ctx->tile_rows - 1; + + // Test whether the spacing provided matches the H.265 uniform + // spacing, and set the flag if it does. + uniform_spacing = 1; + for (i = 0; i <= pps->num_tile_columns_minus1 && + uniform_spacing; i++) { + if (ctx->col_width[i] != + (i + 1) * ctx->slice_block_cols / ctx->tile_cols - + i * ctx->slice_block_cols / ctx->tile_cols) + uniform_spacing = 0; + } + for (i = 0; i <= pps->num_tile_rows_minus1 && + uniform_spacing; i++) { + if (ctx->row_height[i] != + (i + 1) * ctx->slice_block_rows / ctx->tile_rows - + i * ctx->slice_block_rows / ctx->tile_rows) + uniform_spacing = 0; + } + pps->uniform_spacing_flag = uniform_spacing; + + for (i = 0; i <= pps->num_tile_columns_minus1; i++) + pps->column_width_minus1[i] = ctx->col_width[i] - 1; + for (i = 0; i <= pps->num_tile_rows_minus1; i++) + pps->row_height_minus1[i] = ctx->row_height[i] - 1; + + pps->loop_filter_across_tiles_enabled_flag = 1; + } + + pps->pps_loop_filter_across_slices_enabled_flag = 1; // Fill VAAPI parameter buffers. @@ -666,6 +673,13 @@ }, }; + if (pps->tiles_enabled_flag) { + for (i = 0; i <= vpic->num_tile_rows_minus1; i++) + vpic->row_height_minus1[i] = pps->row_height_minus1[i]; + for (i = 0; i <= vpic->num_tile_columns_minus1; i++) + vpic->column_width_minus1[i] = pps->column_width_minus1[i]; + } + return 0; } @@ -752,7 +766,7 @@ // SEI is needed when both the primaries and luminance are set if (mdm->has_primaries && mdm->has_luminance) { - H265RawSEIMasteringDisplayColourVolume *mdcv = + SEIRawMasteringDisplayColourVolume *mdcv = &priv->sei_mastering_display; const int mapping[3] = {1, 2, 0}; const int chroma_den = 50000; @@ -797,7 +811,7 @@ if (sd) { AVContentLightMetadata *clm = (AVContentLightMetadata *)sd->data; - H265RawSEIContentLightLevelInfo *clli = + SEIRawContentLightLevelInfo *clli = &priv->sei_content_light_level; clli->max_content_light_level = FFMIN(clm->MaxCLL, 65535); @@ -1102,6 +1116,8 @@ priv->fixed_qp_b = 30; } + ctx->roi_quant_range = 51 + 6 * (ctx->profile->depth - 8); + return 0; } @@ -1112,6 +1128,10 @@ { FF_PROFILE_HEVC_MAIN_10, 10, 3, 1, 1, VAProfileHEVCMain10 }, { FF_PROFILE_HEVC_REXT, 10, 3, 1, 1, VAProfileHEVCMain10 }, #endif +#if VA_CHECK_VERSION(1, 2, 0) + { FF_PROFILE_HEVC_REXT, 8, 3, 1, 0, VAProfileHEVCMain422_10 }, + { FF_PROFILE_HEVC_REXT, 10, 3, 1, 0, VAProfileHEVCMain422_10 }, +#endif { FF_PROFILE_UNKNOWN } }; @@ -1186,7 +1206,7 @@ { VAAPIEncodeH265Context *priv = avctx->priv_data; - ff_cbs_fragment_free(priv->cbc, &priv->current_access_unit); + ff_cbs_fragment_free(&priv->current_access_unit); ff_cbs_close(&priv->cbc); return ff_vaapi_encode_close(avctx); @@ -1255,6 +1275,10 @@ { .i64 = SEI_MASTERING_DISPLAY | SEI_CONTENT_LIGHT_LEVEL }, INT_MIN, INT_MAX, FLAGS, "sei" }, + { "tiles", "Tile columns x rows", + OFFSET(common.tile_cols), AV_OPT_TYPE_IMAGE_SIZE, + { .str = NULL }, 0, 0, FLAGS }, + { NULL }, }; @@ -1285,15 +1309,17 @@ .id = AV_CODEC_ID_HEVC, .priv_data_size = sizeof(VAAPIEncodeH265Context), .init = &vaapi_encode_h265_init, - .send_frame = &ff_vaapi_encode_send_frame, .receive_packet = &ff_vaapi_encode_receive_packet, .close = &vaapi_encode_h265_close, .priv_class = &vaapi_encode_h265_class, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_h265_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .hw_configs = ff_vaapi_encode_hw_configs, .wrapper_name = "vaapi", }; diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_encode_mjpeg.c ffmpeg-4.4/libavcodec/vaapi_encode_mjpeg.c --- ffmpeg-4.2.2/libavcodec/vaapi_encode_mjpeg.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_encode_mjpeg.c 2021-04-08 21:28:39.000000000 +0000 @@ -90,34 +90,34 @@ int err; if (priv->jfif) { - err = ff_cbs_insert_unit_content(priv->cbc, frag, -1, + err = ff_cbs_insert_unit_content(frag, -1, JPEG_MARKER_APPN + 0, &priv->jfif_header, NULL); if (err < 0) goto fail; } - err = ff_cbs_insert_unit_content(priv->cbc, frag, -1, + err = ff_cbs_insert_unit_content(frag, -1, JPEG_MARKER_DQT, &priv->quant_tables, NULL); if (err < 0) goto fail; - err = ff_cbs_insert_unit_content(priv->cbc, frag, -1, + err = ff_cbs_insert_unit_content(frag, -1, JPEG_MARKER_SOF0, &priv->frame_header, NULL); if (err < 0) goto fail; if (priv->huffman) { - err = ff_cbs_insert_unit_content(priv->cbc, frag, -1, + err = ff_cbs_insert_unit_content(frag, -1, JPEG_MARKER_DHT, &priv->huffman_tables, NULL); if (err < 0) goto fail; } - err = ff_cbs_insert_unit_content(priv->cbc, frag, -1, + err = ff_cbs_insert_unit_content(frag, -1, JPEG_MARKER_SOS, &priv->scan, NULL); if (err < 0) @@ -142,7 +142,7 @@ err = 0; fail: - ff_cbs_fragment_reset(priv->cbc, frag); + ff_cbs_fragment_reset(frag); return err; } @@ -519,7 +519,7 @@ { VAAPIEncodeMJPEGContext *priv = avctx->priv_data; - ff_cbs_fragment_free(priv->cbc, &priv->current_fragment); + ff_cbs_fragment_free(&priv->current_fragment); ff_cbs_close(&priv->cbc); return ff_vaapi_encode_close(avctx); @@ -559,16 +559,16 @@ .id = AV_CODEC_ID_MJPEG, .priv_data_size = sizeof(VAAPIEncodeMJPEGContext), .init = &vaapi_encode_mjpeg_init, - .send_frame = &ff_vaapi_encode_send_frame, .receive_packet = &ff_vaapi_encode_receive_packet, .close = &vaapi_encode_mjpeg_close, .priv_class = &vaapi_encode_mjpeg_class, - .capabilities = AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_INTRA_ONLY, + .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_mjpeg_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .hw_configs = ff_vaapi_encode_hw_configs, .wrapper_name = "vaapi", }; diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_encode_mpeg2.c ffmpeg-4.4/libavcodec/vaapi_encode_mpeg2.c --- ffmpeg-4.2.2/libavcodec/vaapi_encode_mpeg2.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_encode_mpeg2.c 2021-04-08 21:28:39.000000000 +0000 @@ -93,10 +93,9 @@ CodedBitstreamFragment *frag, int type, void *header) { - VAAPIEncodeMPEG2Context *priv = avctx->priv_data; int err; - err = ff_cbs_insert_unit_content(priv->cbc, frag, -1, type, header, NULL); + err = ff_cbs_insert_unit_content(frag, -1, type, header, NULL); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to add header: " "type = %d.\n", type); @@ -135,7 +134,7 @@ err = vaapi_encode_mpeg2_write_fragment(avctx, data, data_len, frag); fail: - ff_cbs_fragment_reset(priv->cbc, frag); + ff_cbs_fragment_reset(frag); return 0; } @@ -159,7 +158,7 @@ err = vaapi_encode_mpeg2_write_fragment(avctx, data, data_len, frag); fail: - ff_cbs_fragment_reset(priv->cbc, frag); + ff_cbs_fragment_reset(frag); return 0; } @@ -293,17 +292,16 @@ priv->sequence_display_extension.extension_start_code_identifier = MPEG2_EXTENSION_SEQUENCE_DISPLAY; + // Unspecified video format, from table 6-6. sde->video_format = 5; - if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + + sde->colour_primaries = avctx->color_primaries; + sde->transfer_characteristics = avctx->color_trc; + sde->matrix_coefficients = avctx->colorspace; + sde->colour_description = + avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || avctx->color_trc != AVCOL_TRC_UNSPECIFIED || - avctx->colorspace != AVCOL_SPC_UNSPECIFIED) { - sde->colour_description = 1; - sde->colour_primaries = avctx->color_primaries; - sde->transfer_characteristics = avctx->color_trc; - sde->matrix_coefficients = avctx->colorspace; - } else { - sde->colour_description = 0; - } + avctx->colorspace != AVCOL_SPC_UNSPECIFIED; sde->display_horizontal_size = avctx->width; sde->display_vertical_size = avctx->height; @@ -552,6 +550,8 @@ ctx->nb_slices = ctx->slice_block_rows; ctx->slice_size = 1; + ctx->roi_quant_range = 31; + return 0; } @@ -631,7 +631,7 @@ { VAAPIEncodeMPEG2Context *priv = avctx->priv_data; - ff_cbs_fragment_free(priv->cbc, &priv->current_fragment); + ff_cbs_fragment_free(&priv->current_fragment); ff_cbs_close(&priv->cbc); return ff_vaapi_encode_close(avctx); @@ -695,15 +695,17 @@ .id = AV_CODEC_ID_MPEG2VIDEO, .priv_data_size = sizeof(VAAPIEncodeMPEG2Context), .init = &vaapi_encode_mpeg2_init, - .send_frame = &ff_vaapi_encode_send_frame, .receive_packet = &ff_vaapi_encode_receive_packet, .close = &vaapi_encode_mpeg2_close, .priv_class = &vaapi_encode_mpeg2_class, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_mpeg2_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .hw_configs = ff_vaapi_encode_hw_configs, .wrapper_name = "vaapi", }; diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_encode_vp8.c ffmpeg-4.4/libavcodec/vaapi_encode_vp8.c --- ffmpeg-4.2.2/libavcodec/vaapi_encode_vp8.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_encode_vp8.c 2021-04-08 21:28:39.000000000 +0000 @@ -173,6 +173,8 @@ else priv->q_index_i = priv->q_index_p; + ctx->roi_quant_range = VP8_MAX_QUANT; + return 0; } @@ -250,15 +252,17 @@ .id = AV_CODEC_ID_VP8, .priv_data_size = sizeof(VAAPIEncodeVP8Context), .init = &vaapi_encode_vp8_init, - .send_frame = &ff_vaapi_encode_send_frame, .receive_packet = &ff_vaapi_encode_receive_packet, .close = &ff_vaapi_encode_close, .priv_class = &vaapi_encode_vp8_class, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_vp8_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .hw_configs = ff_vaapi_encode_hw_configs, .wrapper_name = "vaapi", }; diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_encode_vp9.c ffmpeg-4.4/libavcodec/vaapi_encode_vp9.c --- ffmpeg-4.2.2/libavcodec/vaapi_encode_vp9.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_encode_vp9.c 2021-04-08 21:28:39.000000000 +0000 @@ -202,6 +202,8 @@ priv->q_idx_idr = priv->q_idx_p = priv->q_idx_b = 100; } + ctx->roi_quant_range = VP9_MAX_QUANT; + return 0; } @@ -284,15 +286,17 @@ .id = AV_CODEC_ID_VP9, .priv_data_size = sizeof(VAAPIEncodeVP9Context), .init = &vaapi_encode_vp9_init, - .send_frame = &ff_vaapi_encode_send_frame, .receive_packet = &ff_vaapi_encode_receive_packet, .close = &ff_vaapi_encode_close, .priv_class = &vaapi_encode_vp9_class, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_vp9_defaults, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, + .hw_configs = ff_vaapi_encode_hw_configs, .wrapper_name = "vaapi", }; diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_h264.c ffmpeg-4.4/libavcodec/vaapi_h264.c --- ffmpeg-4.2.2/libavcodec/vaapi_h264.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_h264.c 2020-07-11 10:39:30.000000000 +0000 @@ -22,7 +22,7 @@ #include "h264dec.h" #include "h264_ps.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "vaapi_decode.h" /** diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_hevc.c ffmpeg-4.4/libavcodec/vaapi_hevc.c --- ffmpeg-4.2.2/libavcodec/vaapi_hevc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_hevc.c 2020-07-11 10:39:30.000000000 +0000 @@ -25,12 +25,19 @@ #include "avcodec.h" #include "hevcdec.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "vaapi_decode.h" +#include "vaapi_hevc.h" +#include "h265_profile_level.h" typedef struct VAAPIDecodePictureHEVC { +#if VA_CHECK_VERSION(1, 2, 0) + VAPictureParameterBufferHEVCExtension pic_param; + VASliceParameterBufferHEVCExtension last_slice_param; +#else VAPictureParameterBufferHEVC pic_param; VASliceParameterBufferHEVC last_slice_param; +#endif const uint8_t *last_buffer; size_t last_size; @@ -117,11 +124,13 @@ const HEVCPPS *pps = h->ps.pps; const ScalingList *scaling_list = NULL; - int err, i; + int pic_param_size, err, i; + + VAPictureParameterBufferHEVC *pic_param = (VAPictureParameterBufferHEVC *)&pic->pic_param; pic->pic.output_surface = ff_vaapi_get_surface_id(h->ref->frame); - pic->pic_param = (VAPictureParameterBufferHEVC) { + *pic_param = (VAPictureParameterBufferHEVC) { .pic_width_in_luma_samples = sps->width, .pic_height_in_luma_samples = sps->height, .log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3, @@ -188,29 +197,61 @@ }, }; - fill_vaapi_pic(&pic->pic_param.CurrPic, h->ref, 0); - fill_vaapi_reference_frames(h, &pic->pic_param); + fill_vaapi_pic(&pic_param->CurrPic, h->ref, 0); + fill_vaapi_reference_frames(h, pic_param); if (pps->tiles_enabled_flag) { - pic->pic_param.num_tile_columns_minus1 = pps->num_tile_columns - 1; - pic->pic_param.num_tile_rows_minus1 = pps->num_tile_rows - 1; + pic_param->num_tile_columns_minus1 = pps->num_tile_columns - 1; + pic_param->num_tile_rows_minus1 = pps->num_tile_rows - 1; for (i = 0; i < pps->num_tile_columns; i++) - pic->pic_param.column_width_minus1[i] = pps->column_width[i] - 1; + pic_param->column_width_minus1[i] = pps->column_width[i] - 1; for (i = 0; i < pps->num_tile_rows; i++) - pic->pic_param.row_height_minus1[i] = pps->row_height[i] - 1; + pic_param->row_height_minus1[i] = pps->row_height[i] - 1; } if (h->sh.short_term_ref_pic_set_sps_flag == 0 && h->sh.short_term_rps) { - pic->pic_param.st_rps_bits = h->sh.short_term_ref_pic_set_size; + pic_param->st_rps_bits = h->sh.short_term_ref_pic_set_size; } else { - pic->pic_param.st_rps_bits = 0; + pic_param->st_rps_bits = 0; } +#if VA_CHECK_VERSION(1, 2, 0) + if (avctx->profile == FF_PROFILE_HEVC_REXT) { + pic->pic_param.rext = (VAPictureParameterBufferHEVCRext) { + .range_extension_pic_fields.bits = { + .transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled_flag, + .transform_skip_context_enabled_flag = sps->transform_skip_context_enabled_flag, + .implicit_rdpcm_enabled_flag = sps->implicit_rdpcm_enabled_flag, + .explicit_rdpcm_enabled_flag = sps->explicit_rdpcm_enabled_flag, + .extended_precision_processing_flag = sps->extended_precision_processing_flag, + .intra_smoothing_disabled_flag = sps->intra_smoothing_disabled_flag, + .high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled_flag, + .persistent_rice_adaptation_enabled_flag = sps->persistent_rice_adaptation_enabled_flag, + .cabac_bypass_alignment_enabled_flag = sps->cabac_bypass_alignment_enabled_flag, + .cross_component_prediction_enabled_flag = pps->cross_component_prediction_enabled_flag, + .chroma_qp_offset_list_enabled_flag = pps->chroma_qp_offset_list_enabled_flag, + }, + .diff_cu_chroma_qp_offset_depth = pps->diff_cu_chroma_qp_offset_depth, + .chroma_qp_offset_list_len_minus1 = pps->chroma_qp_offset_list_len_minus1, + .log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma, + .log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma, + .log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size - 2, + }; + + for (i = 0; i < 6; i++) + pic->pic_param.rext.cb_qp_offset_list[i] = pps->cb_qp_offset_list[i]; + for (i = 0; i < 6; i++) + pic->pic_param.rext.cr_qp_offset_list[i] = pps->cr_qp_offset_list[i]; + } +#endif + pic_param_size = avctx->profile == FF_PROFILE_HEVC_REXT ? + sizeof(pic->pic_param) : sizeof(VAPictureParameterBufferHEVC); + err = ff_vaapi_decode_make_param_buffer(avctx, &pic->pic, VAPictureParameterBufferType, - &pic->pic_param, sizeof(pic->pic_param)); + &pic->pic_param, pic_param_size); if (err < 0) goto fail; @@ -255,12 +296,16 @@ { const HEVCContext *h = avctx->priv_data; VAAPIDecodePictureHEVC *pic = h->ref->hwaccel_picture_private; + VASliceParameterBufferHEVC *last_slice_param = (VASliceParameterBufferHEVC *)&pic->last_slice_param; int ret; + int slice_param_size = avctx->profile == FF_PROFILE_HEVC_REXT ? + sizeof(pic->last_slice_param) : sizeof(VASliceParameterBufferHEVC); + if (pic->last_size) { - pic->last_slice_param.LongSliceFlags.fields.LastSliceOfPic = 1; + last_slice_param->LongSliceFlags.fields.LastSliceOfPic = 1; ret = ff_vaapi_decode_make_slice_buffer(avctx, &pic->pic, - &pic->last_slice_param, sizeof(pic->last_slice_param), + &pic->last_slice_param, slice_param_size, pic->last_buffer, pic->last_size); if (ret < 0) goto fail; @@ -330,7 +375,7 @@ static uint8_t get_ref_pic_index(const HEVCContext *h, const HEVCFrame *frame) { VAAPIDecodePictureHEVC *pic = h->ref->hwaccel_picture_private; - VAPictureParameterBufferHEVC *pp = &pic->pic_param; + VAPictureParameterBufferHEVC *pp = (VAPictureParameterBufferHEVC *)&pic->pic_param; uint8_t i; if (!frame) @@ -353,6 +398,10 @@ const HEVCContext *h = avctx->priv_data; const SliceHeader *sh = &h->sh; VAAPIDecodePictureHEVC *pic = h->ref->hwaccel_picture_private; + VASliceParameterBufferHEVC *last_slice_param = (VASliceParameterBufferHEVC *)&pic->last_slice_param; + + int slice_param_size = avctx->profile == FF_PROFILE_HEVC_REXT ? + sizeof(pic->last_slice_param) : sizeof(VASliceParameterBufferHEVC); int nb_list = (sh->slice_type == HEVC_SLICE_B) ? 2 : (sh->slice_type == HEVC_SLICE_I ? 0 : 1); @@ -361,7 +410,7 @@ if (!sh->first_slice_in_pic_flag) { err = ff_vaapi_decode_make_slice_buffer(avctx, &pic->pic, - &pic->last_slice_param, sizeof(pic->last_slice_param), + &pic->last_slice_param, slice_param_size, pic->last_buffer, pic->last_size); pic->last_buffer = NULL; pic->last_size = 0; @@ -371,7 +420,7 @@ } } - pic->last_slice_param = (VASliceParameterBufferHEVC) { + *last_slice_param = (VASliceParameterBufferHEVC) { .slice_data_size = size, .slice_data_offset = 0, .slice_data_flag = VA_SLICE_DATA_FLAG_ALL, @@ -404,16 +453,35 @@ }, }; - memset(pic->last_slice_param.RefPicList, 0xFF, sizeof(pic->last_slice_param.RefPicList)); + memset(last_slice_param->RefPicList, 0xFF, sizeof(last_slice_param->RefPicList)); for (list_idx = 0; list_idx < nb_list; list_idx++) { RefPicList *rpl = &h->ref->refPicList[list_idx]; for (i = 0; i < rpl->nb_refs; i++) - pic->last_slice_param.RefPicList[list_idx][i] = get_ref_pic_index(h, rpl->ref[i]); + last_slice_param->RefPicList[list_idx][i] = get_ref_pic_index(h, rpl->ref[i]); } - fill_pred_weight_table(h, sh, &pic->last_slice_param); + fill_pred_weight_table(h, sh, last_slice_param); + +#if VA_CHECK_VERSION(1, 2, 0) + if (avctx->profile == FF_PROFILE_HEVC_REXT) { + pic->last_slice_param.rext = (VASliceParameterBufferHEVCRext) { + .slice_ext_flags.bits = { + .cu_chroma_qp_offset_enabled_flag = sh->cu_chroma_qp_offset_enabled_flag, + }, + }; + + memcpy(pic->last_slice_param.rext.luma_offset_l0, pic->last_slice_param.base.luma_offset_l0, + sizeof(pic->last_slice_param.base.luma_offset_l0)); + memcpy(pic->last_slice_param.rext.luma_offset_l1, pic->last_slice_param.base.luma_offset_l1, + sizeof(pic->last_slice_param.base.luma_offset_l1)); + memcpy(pic->last_slice_param.rext.ChromaOffsetL0, pic->last_slice_param.base.ChromaOffsetL0, + sizeof(pic->last_slice_param.base.ChromaOffsetL0)); + memcpy(pic->last_slice_param.rext.ChromaOffsetL1, pic->last_slice_param.base.ChromaOffsetL1, + sizeof(pic->last_slice_param.base.ChromaOffsetL1)); + } +#endif pic->last_buffer = buffer; pic->last_size = size; @@ -421,6 +489,83 @@ return 0; } +static int ptl_convert(const PTLCommon *general_ptl, H265RawProfileTierLevel *h265_raw_ptl) +{ + h265_raw_ptl->general_profile_space = general_ptl->profile_space; + h265_raw_ptl->general_tier_flag = general_ptl->tier_flag; + h265_raw_ptl->general_profile_idc = general_ptl->profile_idc; + + memcpy(h265_raw_ptl->general_profile_compatibility_flag, + general_ptl->profile_compatibility_flag, 32 * sizeof(uint8_t)); + +#define copy_field(name) h265_raw_ptl->general_ ## name = general_ptl->name + copy_field(progressive_source_flag); + copy_field(interlaced_source_flag); + copy_field(non_packed_constraint_flag); + copy_field(frame_only_constraint_flag); + copy_field(max_12bit_constraint_flag); + copy_field(max_10bit_constraint_flag); + copy_field(max_8bit_constraint_flag); + copy_field(max_422chroma_constraint_flag); + copy_field(max_420chroma_constraint_flag); + copy_field(max_monochrome_constraint_flag); + copy_field(intra_constraint_flag); + copy_field(one_picture_only_constraint_flag); + copy_field(lower_bit_rate_constraint_flag); + copy_field(max_14bit_constraint_flag); + copy_field(inbld_flag); + copy_field(level_idc); +#undef copy_field + + return 0; +} + +/* + * Find exact va_profile for HEVC Range Extension + */ +VAProfile ff_vaapi_parse_hevc_rext_profile(AVCodecContext *avctx) +{ + const HEVCContext *h = avctx->priv_data; + const HEVCSPS *sps = h->ps.sps; + const PTL *ptl = &sps->ptl; + const PTLCommon *general_ptl = &ptl->general_ptl; + const H265ProfileDescriptor *profile; + H265RawProfileTierLevel h265_raw_ptl = {0}; + + /* convert PTLCommon to H265RawProfileTierLevel */ + ptl_convert(general_ptl, &h265_raw_ptl); + + profile = ff_h265_get_profile(&h265_raw_ptl); + if (!profile) { + av_log(avctx, AV_LOG_WARNING, "HEVC profile is not found.\n"); + goto end; + } else { + av_log(avctx, AV_LOG_VERBOSE, "HEVC profile %s is found.\n", profile->name); + } + +#if VA_CHECK_VERSION(1, 2, 0) + if (!strcmp(profile->name, "Main 4:2:2 10") || + !strcmp(profile->name, "Main 4:2:2 10 Intra")) + return VAProfileHEVCMain422_10; + else if (!strcmp(profile->name, "Main 4:4:4") || + !strcmp(profile->name, "Main 4:4:4 Intra")) + return VAProfileHEVCMain444; + else if (!strcmp(profile->name, "Main 4:4:4 10") || + !strcmp(profile->name, "Main 4:4:4 10 Intra")) + return VAProfileHEVCMain444_10; +#else + av_log(avctx, AV_LOG_WARNING, "HEVC profile %s is " + "not supported with this VA version.\n", profile->name); +#endif + +end: + if (avctx->hwaccel_flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH) { + // Default to selecting Main profile if profile mismatch is allowed + return VAProfileHEVCMain; + } else + return VAProfileNone; +} + const AVHWAccel ff_hevc_vaapi_hwaccel = { .name = "hevc_vaapi", .type = AVMEDIA_TYPE_VIDEO, diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_hevc.h ffmpeg-4.4/libavcodec/vaapi_hevc.h --- ffmpeg-4.2.2/libavcodec/vaapi_hevc.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_hevc.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,27 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_VAAPI_HEVC_H +#define AVCODEC_VAAPI_HEVC_H + +#include +#include "avcodec.h" + +VAProfile ff_vaapi_parse_hevc_rext_profile(AVCodecContext *avctx); + +#endif /* AVCODEC_VAAPI_HEVC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_mjpeg.c ffmpeg-4.4/libavcodec/vaapi_mjpeg.c --- ffmpeg-4.2.2/libavcodec/vaapi_mjpeg.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_mjpeg.c 2020-07-11 10:39:30.000000000 +0000 @@ -19,7 +19,7 @@ #include #include -#include "hwaccel.h" +#include "hwconfig.h" #include "vaapi_decode.h" #include "mjpegdec.h" diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_mpeg2.c ffmpeg-4.4/libavcodec/vaapi_mpeg2.c --- ffmpeg-4.2.2/libavcodec/vaapi_mpeg2.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_mpeg2.c 2020-07-11 10:39:30.000000000 +0000 @@ -20,7 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "hwaccel.h" +#include "hwconfig.h" #include "mpegutils.h" #include "mpegvideo.h" #include "internal.h" diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_mpeg4.c ffmpeg-4.4/libavcodec/vaapi_mpeg4.c --- ffmpeg-4.2.2/libavcodec/vaapi_mpeg4.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_mpeg4.c 2020-07-11 10:39:30.000000000 +0000 @@ -21,7 +21,7 @@ */ #include "h263.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "internal.h" #include "mpeg4video.h" #include "mpegvideo.h" diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_vc1.c ffmpeg-4.4/libavcodec/vaapi_vc1.c --- ffmpeg-4.2.2/libavcodec/vaapi_vc1.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_vc1.c 2020-07-11 10:39:30.000000000 +0000 @@ -20,7 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "hwaccel.h" +#include "hwconfig.h" #include "internal.h" #include "vaapi_decode.h" #include "vc1.h" diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_vp8.c ffmpeg-4.4/libavcodec/vaapi_vp8.c --- ffmpeg-4.2.2/libavcodec/vaapi_vp8.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_vp8.c 2020-07-11 10:39:30.000000000 +0000 @@ -19,7 +19,7 @@ #include #include -#include "hwaccel.h" +#include "hwconfig.h" #include "vaapi_decode.h" #include "vp8.h" diff -Nru ffmpeg-4.2.2/libavcodec/vaapi_vp9.c ffmpeg-4.4/libavcodec/vaapi_vp9.c --- ffmpeg-4.2.2/libavcodec/vaapi_vp9.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vaapi_vp9.c 2020-07-11 10:39:30.000000000 +0000 @@ -22,7 +22,7 @@ #include "libavutil/pixdesc.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "vaapi_decode.h" #include "vp9shared.h" diff -Nru ffmpeg-4.2.2/libavcodec/vb.c ffmpeg-4.4/libavcodec/vb.c --- ffmpeg-4.2.2/libavcodec/vb.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vb.c 2021-04-08 21:28:39.000000000 +0000 @@ -262,11 +262,8 @@ c->frame = av_mallocz(avctx->width * avctx->height); c->prev_frame = av_mallocz(avctx->width * avctx->height); - if (!c->frame || !c->prev_frame) { - av_freep(&c->frame); - av_freep(&c->prev_frame); + if (!c->frame || !c->prev_frame) return AVERROR(ENOMEM); - } return 0; } @@ -291,4 +288,5 @@ .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/vble.c ffmpeg-4.4/libavcodec/vble.c --- ffmpeg-4.2.2/libavcodec/vble.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vble.c 2021-04-08 21:28:39.000000000 +0000 @@ -197,7 +197,6 @@ if (!ctx->val) { av_log(avctx, AV_LOG_ERROR, "Could not allocate values buffer.\n"); - vble_decode_close(avctx); return AVERROR(ENOMEM); } @@ -214,6 +213,5 @@ .close = vble_decode_close, .decode = vble_decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(vble_decode_init), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/vc1_block.c ffmpeg-4.4/libavcodec/vc1_block.c --- ffmpeg-4.2.2/libavcodec/vc1_block.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vc1_block.c 2021-04-08 21:28:39.000000000 +0000 @@ -592,10 +592,6 @@ } else { dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); } - if (dcdiff < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); - return -1; - } if (dcdiff) { const int m = (v->pq == 1 || v->pq == 2) ? 3 - v->pq : 0; if (dcdiff == 119 /* ESC index value */) { @@ -740,10 +736,6 @@ } else { dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); } - if (dcdiff < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); - return -1; - } if (dcdiff) { const int m = (quant == 1 || quant == 2) ? 3 - quant : 0; if (dcdiff == 119 /* ESC index value */) { @@ -944,10 +936,6 @@ } else { dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); } - if (dcdiff < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); - return -1; - } if (dcdiff) { const int m = (quant == 1 || quant == 2) ? 3 - quant : 0; if (dcdiff == 119 /* ESC index value */) { @@ -1080,7 +1068,7 @@ q2 = FFABS(q2) * 2 + ((q2 < 0) ? 0 : v->halfpq) - 1; if (q2 && q1 != q2) { for (k = 1; k < 8; k++) - ac_val2[k] = (ac_val2[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + ac_val2[k] = (int)(ac_val2[k] * (unsigned)q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; } } } else { // top @@ -1093,7 +1081,7 @@ q2 = FFABS(q2) * 2 + ((q2 < 0) ? 0 : v->halfpq) - 1; if (q2 && q1 != q2) { for (k = 1; k < 8; k++) - ac_val2[k + 8] = (ac_val2[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + ac_val2[k + 8] = (int)(ac_val2[k + 8] * (unsigned)q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; } } } @@ -2632,10 +2620,10 @@ if (v->s.loop_filter) ff_vc1_i_loop_filter(v); - if (get_bits_count(&s->gb) > v->bits) { + if (get_bits_left(&s->gb) < 0) { ff_er_add_slice(&s->er, 0, 0, s->mb_x, s->mb_y, ER_MB_ERROR); av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", - get_bits_count(&s->gb), v->bits); + get_bits_count(&s->gb), s->gb.size_in_bits); return; } @@ -2661,7 +2649,7 @@ /** Decode blocks of I-frame for advanced profile */ -static void vc1_decode_i_blocks_adv(VC1Context *v) +static int vc1_decode_i_blocks_adv(VC1Context *v) { int k; MpegEncContext *s = &v->s; @@ -2672,6 +2660,9 @@ int mqdiff; GetBitContext *gb = &s->gb; + if (get_bits_left(gb) <= 1) + return AVERROR_INVALIDDATA; + /* select coding mode used for VLC tables selection */ switch (v->y_ac_table_index) { case 0: @@ -2725,6 +2716,11 @@ // do actual MB decoding and displaying if (v->fieldtx_is_raw) v->fieldtx_plane[mb_pos] = get_bits1(&v->s.gb); + if (get_bits_left(&v->s.gb) <= 1) { + ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); + return 0; + } + cbp = get_vlc2(&v->s.gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); if (v->acpred_is_raw) v->s.ac_pred = get_bits1(&v->s.gb); @@ -2770,12 +2766,12 @@ if (v->s.loop_filter) ff_vc1_i_loop_filter(v); - if (get_bits_count(&s->gb) > v->bits) { + if (get_bits_left(&s->gb) < 0) { // TODO: may need modification to handle slice coding ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", - get_bits_count(&s->gb), v->bits); - return; + get_bits_count(&s->gb), s->gb.size_in_bits); + return 0; } inc_blk_idx(v->topleft_blk_idx); inc_blk_idx(v->top_blk_idx); @@ -2793,6 +2789,7 @@ ff_mpeg_draw_horiz_band(s, (s->end_mb_y - 1) * 16, 16); ff_er_add_slice(&s->er, 0, s->start_mb_y << v->field_mode, s->mb_width - 1, (s->end_mb_y << v->field_mode) - 1, ER_MB_END); + return 0; } static void vc1_decode_p_blocks(VC1Context *v) @@ -2834,6 +2831,12 @@ for (; s->mb_x < s->mb_width; s->mb_x++) { ff_update_block_index(s); + if (v->fcm == ILACE_FIELD || (v->fcm == PROGRESSIVE && v->mv_type_is_raw) || v->skip_is_raw) + if (get_bits_left(&v->s.gb) <= 1) { + ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); + return; + } + if (v->fcm == ILACE_FIELD) { vc1_decode_p_mb_intfi(v); if (apply_loop_filter) @@ -2847,11 +2850,11 @@ if (apply_loop_filter) ff_vc1_p_loop_filter(v); } - if (get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) { + if (get_bits_left(&s->gb) < 0 || get_bits_count(&s->gb) < 0) { // TODO: may need modification to handle slice coding ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", - get_bits_count(&s->gb), v->bits, s->mb_x, s->mb_y); + get_bits_count(&s->gb), s->gb.size_in_bits, s->mb_x, s->mb_y); return; } inc_blk_idx(v->topleft_blk_idx); @@ -2917,6 +2920,12 @@ for (; s->mb_x < s->mb_width; s->mb_x++) { ff_update_block_index(s); + if (v->fcm == ILACE_FIELD || v->skip_is_raw || v->dmb_is_raw) + if (get_bits_left(&v->s.gb) <= 1) { + ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); + return; + } + if (v->fcm == ILACE_FIELD) { vc1_decode_b_mb_intfi(v); if (v->s.loop_filter) @@ -2930,11 +2939,11 @@ if (v->s.loop_filter) ff_vc1_i_loop_filter(v); } - if (get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) { + if (get_bits_left(&s->gb) < 0 || get_bits_count(&s->gb) < 0) { // TODO: may need modification to handle slice coding ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", - get_bits_count(&s->gb), v->bits, s->mb_x, s->mb_y); + get_bits_count(&s->gb), s->gb.size_in_bits, s->mb_x, s->mb_y); return; } } diff -Nru ffmpeg-4.2.2/libavcodec/vc1.c ffmpeg-4.4/libavcodec/vc1.c --- ffmpeg-4.2.2/libavcodec/vc1.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vc1.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ */ #include "libavutil/attributes.h" +#include "libavutil/thread.h" #include "internal.h" #include "avcodec.h" #include "mpegvideo.h" @@ -1576,21 +1577,11 @@ 31714, 31746, 31778, 32306, 32340, 32372 }; -/** - * Init VC-1 specific tables and VC1Context members - * @param v The VC1Context to initialize - * @return Status - */ -av_cold int ff_vc1_init_common(VC1Context *v) +static av_cold void vc1_init_static(void) { - static int done = 0; int i = 0; static VLC_TYPE vlc_table[32372][2]; - v->hrd_rate = v->hrd_buffer = NULL; - - /* VLC tables */ - if (!done) { INIT_VLC_STATIC(&ff_vc1_bfraction_vlc, VC1_BFRACTION_VLC_BITS, 23, ff_vc1_bfraction_bits, 1, 1, ff_vc1_bfraction_codes, 1, 1, 1 << VC1_BFRACTION_VLC_BITS); @@ -1697,14 +1688,27 @@ ff_vc1_if_1mv_mbmode_bits[i], 1, 1, ff_vc1_if_1mv_mbmode_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); } - done = 1; - } +} - /* Other defaults */ +/** + * Init VC-1 specific tables and VC1Context members + * @param v The VC1Context to initialize + * @return Status + */ +av_cold int ff_vc1_init_common(VC1Context *v) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + + v->hrd_rate = v->hrd_buffer = NULL; + + /* defaults */ v->pq = -1; v->mvrange = 0; /* 7.1.1.18, p80 */ ff_vc1dsp_init(&v->vc1dsp); + /* VLC tables */ + ff_thread_once(&init_static_once, vc1_init_static); + return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/vc1dec.c ffmpeg-4.4/libavcodec/vc1dec.c --- ffmpeg-4.2.2/libavcodec/vc1dec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vc1dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,7 +29,7 @@ #include "avcodec.h" #include "blockdsp.h" #include "get_bits.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "internal.h" #include "mpeg_er.h" #include "mpegvideo.h" @@ -384,7 +384,7 @@ if (s->avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || s->avctx->codec_id == AV_CODEC_ID_VC1IMAGE) { for (i = 0; i < 4; i++) if (!(v->sr_rows[i >> 1][i & 1] = av_malloc(v->output_width))) - return AVERROR(ENOMEM); + goto error; } ret = ff_intrax8_common_init(s->avctx, &v->x8, &s->idsp, @@ -539,12 +539,6 @@ ff_h264chroma_init(&v->h264chroma, 8); ff_qpeldsp_init(&s->qdsp); - // Must happen after calling ff_vc1_decode_end - // to avoid de-allocating the sprite_output_frame - v->sprite_output_frame = av_frame_alloc(); - if (!v->sprite_output_frame) - return AVERROR(ENOMEM); - avctx->has_b_frames = !!avctx->max_b_frames; if (v->color_prim == 1 || v->color_prim == 5 || v->color_prim == 6) @@ -577,20 +571,15 @@ v->sprite_height > 1 << 14 || v->output_width > 1 << 14 || v->output_height > 1 << 14) { - ret = AVERROR_INVALIDDATA; - goto error; + return AVERROR_INVALIDDATA; } if ((v->sprite_width&1) || (v->sprite_height&1)) { avpriv_request_sample(avctx, "odd sprites support"); - ret = AVERROR_PATCHWELCOME; - goto error; + return AVERROR_PATCHWELCOME; } } return 0; -error: - av_frame_free(&v->sprite_output_frame); - return ret; } /** Close a VC1/WMV3 decoder @@ -695,13 +684,13 @@ int buf_size3; if (avctx->hwaccel) buf_start_second_field = start; - tmp = av_realloc_array(slices, sizeof(*slices), (n_slices+1)); + tmp = av_realloc_array(slices, sizeof(*slices), n_slices+1); if (!tmp) { ret = AVERROR(ENOMEM); goto err; } slices = tmp; - slices[n_slices].buf = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE); + slices[n_slices].buf = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!slices[n_slices].buf) { ret = AVERROR(ENOMEM); goto err; @@ -724,13 +713,13 @@ break; case VC1_CODE_SLICE: { int buf_size3; - tmp = av_realloc_array(slices, sizeof(*slices), (n_slices+1)); + tmp = av_realloc_array(slices, sizeof(*slices), n_slices+1); if (!tmp) { ret = AVERROR(ENOMEM); goto err; } slices = tmp; - slices[n_slices].buf = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE); + slices[n_slices].buf = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!slices[n_slices].buf) { ret = AVERROR(ENOMEM); goto err; @@ -759,7 +748,7 @@ } else { // found field marker, unescape second field if (avctx->hwaccel) buf_start_second_field = divider; - tmp = av_realloc_array(slices, sizeof(*slices), (n_slices+1)); + tmp = av_realloc_array(slices, sizeof(*slices), n_slices+1); if (!tmp) { ret = AVERROR(ENOMEM); goto err; @@ -854,7 +843,12 @@ ret = AVERROR_INVALIDDATA; goto err; } - + if ((avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || avctx->codec_id == AV_CODEC_ID_VC1IMAGE) + && v->field_mode) { + av_log(v->s.avctx, AV_LOG_ERROR, "Sprite decoder: expected Frames not Fields\n"); + ret = AVERROR_INVALIDDATA; + goto err; + } if ((s->mb_height >> v->field_mode) == 0) { av_log(v->s.avctx, AV_LOG_ERROR, "image too short\n"); ret = AVERROR_INVALIDDATA; @@ -1033,7 +1027,6 @@ ff_mpeg_er_frame_start(s); - v->bits = buf_size * 8; v->end_mb_x = s->mb_width; if (v->field_mode) { s->current_picture.f->linesize[0] <<= 1; @@ -1107,8 +1100,9 @@ continue; } ff_vc1_decode_blocks(v); - if (i != n_slices) + if (i != n_slices) { s->gb = slices[i].gb; + } } if (v->field_mode) { v->second_field = 0; @@ -1142,6 +1136,11 @@ avctx->height = avctx->coded_height = v->output_height; if (avctx->skip_frame >= AVDISCARD_NONREF) goto end; + if (!v->sprite_output_frame && + !(v->sprite_output_frame = av_frame_alloc())) { + ret = AVERROR(ENOMEM); + goto err; + } #if CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER if ((ret = vc1_decode_sprites(v, &s->gb)) < 0) goto err; @@ -1212,7 +1211,7 @@ .flush = ff_mpeg_flush, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .pix_fmts = vc1_hwaccel_pixfmt_list_420, - .hw_configs = (const AVCodecHWConfigInternal*[]) { + .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_VC1_DXVA2_HWACCEL HWACCEL_DXVA2(vc1), #endif @@ -1249,7 +1248,7 @@ .flush = ff_mpeg_flush, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .pix_fmts = vc1_hwaccel_pixfmt_list_420, - .hw_configs = (const AVCodecHWConfigInternal*[]) { + .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_WMV3_DXVA2_HWACCEL HWACCEL_DXVA2(wmv3), #endif diff -Nru ffmpeg-4.2.2/libavcodec/vc1.h ffmpeg-4.4/libavcodec/vc1.h --- ffmpeg-4.2.2/libavcodec/vc1.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vc1.h 2020-07-11 10:39:30.000000000 +0000 @@ -176,8 +176,6 @@ H264ChromaContext h264chroma; VC1DSPContext vc1dsp; - int bits; - /** Simple/Main Profile sequence header */ //@{ int res_sprite; ///< reserved, sprite mode diff -Nru ffmpeg-4.2.2/libavcodec/vc2enc.c ffmpeg-4.4/libavcodec/vc2enc.c --- ffmpeg-4.2.2/libavcodec/vc2enc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vc2enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -229,12 +229,12 @@ { uint32_t cur_pos, dist; - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); cur_pos = put_bits_count(&s->pb) >> 3; /* Magic string */ - avpriv_put_string(&s->pb, "BBCD", 0); + ff_put_string(&s->pb, "BBCD", 0); /* Parse code */ put_bits(&s->pb, 8, pcode); @@ -399,7 +399,7 @@ /* VC-2 11 - sequence_header() */ static void encode_seq_header(VC2EncContext *s) { - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); encode_parse_params(s); put_vc2_ue_uint(&s->pb, s->base_vf); encode_source_params(s); @@ -409,7 +409,7 @@ /* VC-2 12.1 - picture_header() */ static void encode_picture_header(VC2EncContext *s) { - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); put_bits32(&s->pb, s->picture_number++); } @@ -423,7 +423,7 @@ } /* 1st idx = LL, second - vertical, third - horizontal, fourth - total */ -const uint8_t vc2_qm_col_tab[][4] = { +static const uint8_t vc2_qm_col_tab[][4] = { {20, 9, 15, 4}, { 0, 6, 6, 4}, { 0, 3, 3, 5}, @@ -431,7 +431,7 @@ { 0, 11, 10, 11} }; -const uint8_t vc2_qm_flat_tab[][4] = { +static const uint8_t vc2_qm_flat_tab[][4] = { { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, @@ -509,15 +509,15 @@ static void encode_wavelet_transform(VC2EncContext *s) { encode_transform_params(s); - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); } /* VC-2 12 - picture_parse() */ static void encode_picture_start(VC2EncContext *s) { - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); encode_picture_header(s); - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); encode_wavelet_transform(s); } @@ -753,7 +753,7 @@ quants[level][orientation]); } } - avpriv_align_put_bits(pb); + align_put_bits(pb); bytes_len = (put_bits_count(pb) >> 3) - bytes_start - 1; if (p == 2) { int len_diff = slice_bytes_max - (put_bits_count(pb) >> 3); @@ -780,7 +780,6 @@ int slice_x, slice_y, skip = 0; SliceArgs *enc_args = s->slice_args; - avpriv_align_put_bits(&s->pb); flush_put_bits(&s->pb); buf = put_bits_ptr(&s->pb); @@ -867,6 +866,7 @@ for (x = 0; x < p->width; x++) { buf[x] = pix[x] - s->diff_offset; } + memset(&buf[x], 0, (p->coef_stride - p->width)*sizeof(dwtcoef)); buf += p->coef_stride; pix += pix_stride; } @@ -876,6 +876,7 @@ for (x = 0; x < p->width; x++) { buf[x] = pix[x] - s->diff_offset; } + memset(&buf[x], 0, (p->coef_stride - p->width)*sizeof(dwtcoef)); buf += p->coef_stride; pix += pix_stride; } @@ -930,7 +931,7 @@ /* Encoder version */ if (aux_data) { encode_parse_info(s, DIRAC_PCODE_AUX); - avpriv_put_string(&s->pb, aux_data, 1); + ff_put_string(&s->pb, aux_data, 1); } /* Picture header */ diff -Nru ffmpeg-4.2.2/libavcodec/vc2enc_dwt.c ffmpeg-4.4/libavcodec/vc2enc_dwt.c --- ffmpeg-4.2.2/libavcodec/vc2enc_dwt.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vc2enc_dwt.c 2020-07-11 10:39:30.000000000 +0000 @@ -66,7 +66,7 @@ */ for (y = 0; y < synth_height; y++) { for (x = 0; x < synth_width; x++) - synthl[x] = datal[x] << 1; + synthl[x] = datal[x] * 2; synthl += synth_width; datal += stride; } diff -Nru ffmpeg-4.2.2/libavcodec/vdpau.c ffmpeg-4.4/libavcodec/vdpau.c --- ffmpeg-4.2.2/libavcodec/vdpau.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vdpau.c 2021-04-08 21:28:39.000000000 +0000 @@ -83,6 +83,8 @@ switch (avctx->sw_pix_fmt) { case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUVJ420P: + case AV_PIX_FMT_YUV420P10: + case AV_PIX_FMT_YUV420P12: t = VDP_CHROMA_TYPE_420; w = (w + 1) & ~1; h = (h + 3) & ~3; @@ -95,6 +97,8 @@ break; case AV_PIX_FMT_YUV444P: case AV_PIX_FMT_YUVJ444P: + case AV_PIX_FMT_YUV444P10: + case AV_PIX_FMT_YUV444P12: t = VDP_CHROMA_TYPE_444; h = (h + 1) & ~1; break; diff -Nru ffmpeg-4.2.2/libavcodec/vdpau_h264.c ffmpeg-4.4/libavcodec/vdpau_h264.c --- ffmpeg-4.2.2/libavcodec/vdpau_h264.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vdpau_h264.c 2020-07-11 10:39:30.000000000 +0000 @@ -27,7 +27,7 @@ #include "internal.h" #include "h264dec.h" #include "h264_ps.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "mpegutils.h" #include "vdpau.h" #include "vdpau_internal.h" diff -Nru ffmpeg-4.2.2/libavcodec/vdpau_hevc.c ffmpeg-4.4/libavcodec/vdpau_hevc.c --- ffmpeg-4.2.2/libavcodec/vdpau_hevc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vdpau_hevc.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,9 +26,11 @@ #include "internal.h" #include "hevc_data.h" #include "hevcdec.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "vdpau.h" #include "vdpau_internal.h" +#include "h265_profile_level.h" + static int vdpau_hevc_start_frame(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) @@ -429,10 +431,93 @@ return 0; } + + +static int ptl_convert(const PTLCommon *general_ptl, H265RawProfileTierLevel *h265_raw_ptl) +{ + h265_raw_ptl->general_profile_space = general_ptl->profile_space; + h265_raw_ptl->general_tier_flag = general_ptl->tier_flag; + h265_raw_ptl->general_profile_idc = general_ptl->profile_idc; + + memcpy(h265_raw_ptl->general_profile_compatibility_flag, + general_ptl->profile_compatibility_flag, 32 * sizeof(uint8_t)); + +#define copy_field(name) h265_raw_ptl->general_ ## name = general_ptl->name + copy_field(progressive_source_flag); + copy_field(interlaced_source_flag); + copy_field(non_packed_constraint_flag); + copy_field(frame_only_constraint_flag); + copy_field(max_12bit_constraint_flag); + copy_field(max_10bit_constraint_flag); + copy_field(max_8bit_constraint_flag); + copy_field(max_422chroma_constraint_flag); + copy_field(max_420chroma_constraint_flag); + copy_field(max_monochrome_constraint_flag); + copy_field(intra_constraint_flag); + copy_field(one_picture_only_constraint_flag); + copy_field(lower_bit_rate_constraint_flag); + copy_field(max_14bit_constraint_flag); + copy_field(inbld_flag); + copy_field(level_idc); +#undef copy_field + + return 0; +} + +/* + * Find exact vdpau_profile for HEVC Range Extension + */ +static int vdpau_hevc_parse_rext_profile(AVCodecContext *avctx, VdpDecoderProfile *vdp_profile) +{ + const HEVCContext *h = avctx->priv_data; + const HEVCSPS *sps = h->ps.sps; + const PTL *ptl = &sps->ptl; + const PTLCommon *general_ptl = &ptl->general_ptl; + const H265ProfileDescriptor *profile; + H265RawProfileTierLevel h265_raw_ptl = {0}; + + /* convert PTLCommon to H265RawProfileTierLevel */ + ptl_convert(general_ptl, &h265_raw_ptl); + + profile = ff_h265_get_profile(&h265_raw_ptl); + if (!profile) { + av_log(avctx, AV_LOG_WARNING, "HEVC profile is not found.\n"); + if (avctx->hwaccel_flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH) { + // Default to selecting Main profile if profile mismatch is allowed + *vdp_profile = VDP_DECODER_PROFILE_HEVC_MAIN; + return 0; + } else + return AVERROR(ENOTSUP); + } + + if (!strcmp(profile->name, "Main 12") || + !strcmp(profile->name, "Main 12 Intra")) + *vdp_profile = VDP_DECODER_PROFILE_HEVC_MAIN_12; +#ifdef VDP_DECODER_PROFILE_HEVC_MAIN_444 + else if (!strcmp(profile->name, "Main 4:4:4") || + !strcmp(profile->name, "Main 4:4:4 Intra")) + *vdp_profile = VDP_DECODER_PROFILE_HEVC_MAIN_444; +#endif +#ifdef VDP_DECODER_PROFILE_HEVC_MAIN_444_10 + else if (!strcmp(profile->name, "Main 4:4:4 10") || + !strcmp(profile->name, "Main 4:4:4 10 Intra")) + *vdp_profile = VDP_DECODER_PROFILE_HEVC_MAIN_444_10; + else if (!strcmp(profile->name, "Main 4:4:4 12") || + !strcmp(profile->name, "Main 4:4:4 12 Intra")) + *vdp_profile = VDP_DECODER_PROFILE_HEVC_MAIN_444_12; +#endif + else + return AVERROR(ENOTSUP); + + return 0; +} + + static int vdpau_hevc_init(AVCodecContext *avctx) { VdpDecoderProfile profile; uint32_t level = avctx->level; + int ret; switch (avctx->profile) { case FF_PROFILE_HEVC_MAIN: @@ -445,7 +530,9 @@ profile = VDP_DECODER_PROFILE_HEVC_MAIN_STILL; break; case FF_PROFILE_HEVC_REXT: - profile = VDP_DECODER_PROFILE_HEVC_MAIN_444; + ret = vdpau_hevc_parse_rext_profile(avctx, &profile); + if (ret) + return AVERROR(ENOTSUP); break; default: return AVERROR(ENOTSUP); diff -Nru ffmpeg-4.2.2/libavcodec/vdpau_internal.h ffmpeg-4.4/libavcodec/vdpau_internal.h --- ffmpeg-4.2.2/libavcodec/vdpau_internal.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vdpau_internal.h 2020-07-11 10:39:30.000000000 +0000 @@ -54,6 +54,9 @@ #ifdef VDP_YCBCR_FORMAT_Y_U_V_444 VdpPictureInfoHEVC444 hevc_444; #endif +#ifdef VDP_DECODER_PROFILE_VP9_PROFILE_0 + VdpPictureInfoVP9 vp9; +#endif }; typedef struct VDPAUHWContext { diff -Nru ffmpeg-4.2.2/libavcodec/vdpau_mpeg12.c ffmpeg-4.4/libavcodec/vdpau_mpeg12.c --- ffmpeg-4.2.2/libavcodec/vdpau_mpeg12.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vdpau_mpeg12.c 2020-07-11 10:39:30.000000000 +0000 @@ -24,7 +24,7 @@ #include #include "avcodec.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "mpegvideo.h" #include "vdpau.h" #include "vdpau_internal.h" diff -Nru ffmpeg-4.2.2/libavcodec/vdpau_mpeg4.c ffmpeg-4.4/libavcodec/vdpau_mpeg4.c --- ffmpeg-4.2.2/libavcodec/vdpau_mpeg4.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vdpau_mpeg4.c 2020-07-11 10:39:30.000000000 +0000 @@ -24,7 +24,7 @@ #include #include "avcodec.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "mpeg4video.h" #include "vdpau.h" #include "vdpau_internal.h" diff -Nru ffmpeg-4.2.2/libavcodec/vdpau_vc1.c ffmpeg-4.4/libavcodec/vdpau_vc1.c --- ffmpeg-4.2.2/libavcodec/vdpau_vc1.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vdpau_vc1.c 2020-07-11 10:39:30.000000000 +0000 @@ -24,7 +24,7 @@ #include #include "avcodec.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "vc1.h" #include "vdpau.h" #include "vdpau_internal.h" diff -Nru ffmpeg-4.2.2/libavcodec/vdpau_vp9.c ffmpeg-4.4/libavcodec/vdpau_vp9.c --- ffmpeg-4.2.2/libavcodec/vdpau_vp9.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vdpau_vp9.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,241 @@ +/* + * VP9 HW decode acceleration through VDPAU + * + * Copyright (c) 2019 Manoj Gupta Bonda + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "libavutil/pixdesc.h" +#include "avcodec.h" +#include "internal.h" +#include "vp9data.h" +#include "vp9dec.h" +#include "hwconfig.h" +#include "vdpau.h" +#include "vdpau_internal.h" + +static int vdpau_vp9_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + VP9Context *s = avctx->priv_data; + VP9SharedContext *h = &(s->s); + VP9Frame pic = h->frames[CUR_FRAME]; + struct vdpau_picture_context *pic_ctx = pic.hwaccel_picture_private; + int i; + + VdpPictureInfoVP9 *info = &pic_ctx->info.vp9; + const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); + if (!pixdesc) { + return AV_PIX_FMT_NONE; + } + + info->width = avctx->width; + info->height = avctx->height; + /* fill LvPictureInfoVP9 struct */ + info->lastReference = VDP_INVALID_HANDLE; + info->goldenReference = VDP_INVALID_HANDLE; + info->altReference = VDP_INVALID_HANDLE; + + if (h->refs[h->h.refidx[0]].f && h->refs[h->h.refidx[0]].f->private_ref) { + info->lastReference = ff_vdpau_get_surface_id(h->refs[h->h.refidx[0]].f); + } + if (h->refs[h->h.refidx[1]].f && h->refs[h->h.refidx[1]].f->private_ref) { + info->goldenReference = ff_vdpau_get_surface_id(h->refs[h->h.refidx[1]].f); + } + if (h->refs[h->h.refidx[2]].f && h->refs[h->h.refidx[2]].f->private_ref) { + info->altReference = ff_vdpau_get_surface_id(h->refs[h->h.refidx[2]].f); + } + + info->profile = h->h.profile; + info->frameContextIdx = h->h.framectxid; + info->keyFrame = h->h.keyframe; + info->showFrame = !h->h.invisible; + info->errorResilient = h->h.errorres; + info->frameParallelDecoding = h->h.parallelmode; + + info->subSamplingX = pixdesc->log2_chroma_w; + info->subSamplingY = pixdesc->log2_chroma_h; + + info->intraOnly = h->h.intraonly; + info->allowHighPrecisionMv = h->h.keyframe ? 0 : h->h.highprecisionmvs; + info->refreshEntropyProbs = h->h.refreshctx; + + info->bitDepthMinus8Luma = pixdesc->comp[0].depth - 8; + info->bitDepthMinus8Chroma = pixdesc->comp[1].depth - 8; + + info->loopFilterLevel = h->h.filter.level; + info->loopFilterSharpness = h->h.filter.sharpness; + info->modeRefLfEnabled = h->h.lf_delta.enabled; + + info->log2TileColumns = h->h.tiling.log2_tile_cols; + info->log2TileRows = h->h.tiling.log2_tile_rows; + + info->segmentEnabled = h->h.segmentation.enabled; + info->segmentMapUpdate = h->h.segmentation.update_map; + info->segmentMapTemporalUpdate = h->h.segmentation.temporal; + info->segmentFeatureMode = h->h.segmentation.absolute_vals; + + info->qpYAc = h->h.yac_qi; + info->qpYDc = h->h.ydc_qdelta; + info->qpChDc = h->h.uvdc_qdelta; + info->qpChAc = h->h.uvac_qdelta; + + info->resetFrameContext = h->h.resetctx; + info->mcompFilterType = h->h.filtermode ^ (h->h.filtermode <= 1); + info->uncompressedHeaderSize = h->h.uncompressed_header_size; + info->compressedHeaderSize = h->h.compressed_header_size; + info->refFrameSignBias[0] = 0; + + + for (i = 0; i < FF_ARRAY_ELEMS(info->mbModeLfDelta); i++) + info->mbModeLfDelta[i] = h->h.lf_delta.mode[i]; + + for (i = 0; i < FF_ARRAY_ELEMS(info->mbRefLfDelta); i++) + info->mbRefLfDelta[i] = h->h.lf_delta.ref[i]; + + for (i = 0; i < FF_ARRAY_ELEMS(info->mbSegmentTreeProbs); i++) + info->mbSegmentTreeProbs[i] = h->h.segmentation.prob[i]; + + for (i = 0; i < FF_ARRAY_ELEMS(info->activeRefIdx); i++) { + info->activeRefIdx[i] = h->h.refidx[i]; + info->segmentPredProbs[i] = h->h.segmentation.pred_prob[i]; + info->refFrameSignBias[i + 1] = h->h.signbias[i]; + } + + for (i = 0; i < FF_ARRAY_ELEMS(info->segmentFeatureEnable); i++) { + info->segmentFeatureEnable[i][0] = h->h.segmentation.feat[i].q_enabled; + info->segmentFeatureEnable[i][1] = h->h.segmentation.feat[i].lf_enabled; + info->segmentFeatureEnable[i][2] = h->h.segmentation.feat[i].ref_enabled; + info->segmentFeatureEnable[i][3] = h->h.segmentation.feat[i].skip_enabled; + + info->segmentFeatureData[i][0] = h->h.segmentation.feat[i].q_val; + info->segmentFeatureData[i][1] = h->h.segmentation.feat[i].lf_val; + info->segmentFeatureData[i][2] = h->h.segmentation.feat[i].ref_val; + info->segmentFeatureData[i][3] = 0; + } + + switch (avctx->colorspace) { + default: + case AVCOL_SPC_UNSPECIFIED: + info->colorSpace = 0; + break; + case AVCOL_SPC_BT470BG: + info->colorSpace = 1; + break; + case AVCOL_SPC_BT709: + info->colorSpace = 2; + break; + case AVCOL_SPC_SMPTE170M: + info->colorSpace = 3; + break; + case AVCOL_SPC_SMPTE240M: + info->colorSpace = 4; + break; + case AVCOL_SPC_BT2020_NCL: + info->colorSpace = 5; + break; + case AVCOL_SPC_RESERVED: + info->colorSpace = 6; + break; + case AVCOL_SPC_RGB: + info->colorSpace = 7; + break; + } + + return ff_vdpau_common_start_frame(pic_ctx, buffer, size); + +} + +static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 }; + +static int vdpau_vp9_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + VP9SharedContext *h = avctx->priv_data; + VP9Frame pic = h->frames[CUR_FRAME]; + struct vdpau_picture_context *pic_ctx = pic.hwaccel_picture_private; + + int val; + + val = ff_vdpau_add_buffer(pic_ctx, start_code_prefix, 3); + if (val) + return val; + + val = ff_vdpau_add_buffer(pic_ctx, buffer, size); + if (val) + return val; + + return 0; +} + +static int vdpau_vp9_end_frame(AVCodecContext *avctx) +{ + VP9SharedContext *h = avctx->priv_data; + VP9Frame pic = h->frames[CUR_FRAME]; + struct vdpau_picture_context *pic_ctx = pic.hwaccel_picture_private; + + int val; + + val = ff_vdpau_common_end_frame(avctx, pic.tf.f, pic_ctx); + if (val < 0) + return val; + + return 0; +} + +static int vdpau_vp9_init(AVCodecContext *avctx) +{ + VdpDecoderProfile profile; + uint32_t level = avctx->level; + + switch (avctx->profile) { + case FF_PROFILE_VP9_0: + profile = VDP_DECODER_PROFILE_VP9_PROFILE_0; + break; + case FF_PROFILE_VP9_1: + profile = VDP_DECODER_PROFILE_VP9_PROFILE_1; + break; + case FF_PROFILE_VP9_2: + profile = VDP_DECODER_PROFILE_VP9_PROFILE_2; + break; + case FF_PROFILE_VP9_3: + profile = VDP_DECODER_PROFILE_VP9_PROFILE_3; + break; + default: + return AVERROR(ENOTSUP); + } + + return ff_vdpau_common_init(avctx, profile, level); +} + +const AVHWAccel ff_vp9_vdpau_hwaccel = { + .name = "vp9_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP9, + .pix_fmt = AV_PIX_FMT_VDPAU, + .start_frame = vdpau_vp9_start_frame, + .end_frame = vdpau_vp9_end_frame, + .decode_slice = vdpau_vp9_decode_slice, + .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .init = vdpau_vp9_init, + .uninit = ff_vdpau_common_uninit, + .frame_params = ff_vdpau_common_frame_params, + .priv_data_size = sizeof(VDPAUContext), + .caps_internal = HWACCEL_CAP_ASYNC_SAFE, +}; diff -Nru ffmpeg-4.2.2/libavcodec/version.h ffmpeg-4.4/libavcodec/version.h --- ffmpeg-4.2.2/libavcodec/version.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/version.h 2021-04-08 21:28:39.000000000 +0000 @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 54 +#define LIBAVCODEC_VERSION_MINOR 134 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ @@ -51,12 +51,6 @@ * at once through the bump. This improves the git bisect-ability of the change. */ -#ifndef FF_API_LOWRES -#define FF_API_LOWRES (LIBAVCODEC_VERSION_MAJOR < 59) -#endif -#ifndef FF_API_DEBUG_MV -#define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 58) -#endif #ifndef FF_API_AVCTX_TIMEBASE #define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 59) #endif @@ -135,6 +129,44 @@ #ifndef FF_API_UNSANITIZED_BITRATES #define FF_API_UNSANITIZED_BITRATES (LIBAVCODEC_VERSION_MAJOR < 59) #endif - +#ifndef FF_API_OPENH264_SLICE_MODE +#define FF_API_OPENH264_SLICE_MODE (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_OPENH264_CABAC +#define FF_API_OPENH264_CABAC (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_UNUSED_CODEC_CAPS +#define FF_API_UNUSED_CODEC_CAPS (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_AVPRIV_PUT_BITS +#define FF_API_AVPRIV_PUT_BITS (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_OLD_ENCDEC +#define FF_API_OLD_ENCDEC (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_AVCODEC_PIX_FMT +#define FF_API_AVCODEC_PIX_FMT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_MPV_RC_STRATEGY +#define FF_API_MPV_RC_STRATEGY (LIBAVCODEC_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_PARSER_CHANGE +#define FF_API_PARSER_CHANGE (LIBAVCODEC_VERSION_MAJOR < 59) +#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 #endif /* AVCODEC_VERSION_H */ diff -Nru ffmpeg-4.2.2/libavcodec/videotoolbox.c ffmpeg-4.4/libavcodec/videotoolbox.c --- ffmpeg-4.2.2/libavcodec/videotoolbox.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/videotoolbox.c 2021-04-08 21:28:39.000000000 +0000 @@ -91,6 +91,11 @@ return AVERROR_EXTERNAL; } + frame->crop_right = 0; + frame->crop_left = 0; + frame->crop_top = 0; + frame->crop_bottom = 0; + frame->data[3] = (uint8_t*)ref->pixbuf; if (ref->hw_frames_ctx) { @@ -612,7 +617,7 @@ } if (!image_buffer) { - av_log(NULL, AV_LOG_DEBUG, "vt decoder cb: output image buffer is null\n"); + av_log(avctx, AV_LOG_DEBUG, "vt decoder cb: output image buffer is null\n"); return; } @@ -898,11 +903,6 @@ AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); VTContext *vtctx = avctx->internal->hwaccel_priv_data; - frame->crop_right = 0; - frame->crop_left = 0; - frame->crop_top = 0; - frame->crop_bottom = 0; - if (vtctx->reconfig_needed == true) { vtctx->reconfig_needed = false; av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox decoder needs reconfig, restarting..\n"); @@ -1084,10 +1084,17 @@ goto fail; } + bool full_range = avctx->color_range == AVCOL_RANGE_JPEG; vtctx->vt_ctx->cv_pix_fmt_type = - av_map_videotoolbox_format_from_pixfmt(hw_frames->sw_format); + av_map_videotoolbox_format_from_pixfmt2(hw_frames->sw_format, full_range); if (!vtctx->vt_ctx->cv_pix_fmt_type) { - av_log(avctx, AV_LOG_ERROR, "Unknown sw_format.\n"); + const AVPixFmtDescriptor *attempted_format = + av_pix_fmt_desc_get(hw_frames->sw_format); + av_log(avctx, AV_LOG_ERROR, + "Failed to map underlying FFmpeg pixel format %s (%s range) to " + "a VideoToolbox format!\n", + attempted_format ? attempted_format->name : "", + av_color_range_name(avctx->color_range)); err = AVERROR(EINVAL); goto fail; } @@ -1143,7 +1150,7 @@ .end_frame = videotoolbox_hevc_end_frame, .frame_params = videotoolbox_frame_params, .init = videotoolbox_common_init, - .uninit = ff_videotoolbox_uninit, + .uninit = videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; @@ -1208,14 +1215,15 @@ .priv_data_size = sizeof(VTContext), }; -static AVVideotoolboxContext *av_videotoolbox_alloc_context_with_pix_fmt(enum AVPixelFormat pix_fmt) +static AVVideotoolboxContext *av_videotoolbox_alloc_context_with_pix_fmt(enum AVPixelFormat pix_fmt, + bool full_range) { AVVideotoolboxContext *ret = av_mallocz(sizeof(*ret)); if (ret) { ret->output_callback = videotoolbox_decoder_callback; - OSType cv_pix_fmt_type = av_map_videotoolbox_format_from_pixfmt(pix_fmt); + OSType cv_pix_fmt_type = av_map_videotoolbox_format_from_pixfmt2(pix_fmt, full_range); if (cv_pix_fmt_type == 0) { cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; } @@ -1227,7 +1235,7 @@ AVVideotoolboxContext *av_videotoolbox_alloc_context(void) { - return av_videotoolbox_alloc_context_with_pix_fmt(AV_PIX_FMT_NONE); + return av_videotoolbox_alloc_context_with_pix_fmt(AV_PIX_FMT_NONE, false); } int av_videotoolbox_default_init(AVCodecContext *avctx) @@ -1237,7 +1245,9 @@ int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx) { - avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context_with_pix_fmt(videotoolbox_best_pixel_format(avctx)); + enum AVPixelFormat pix_fmt = videotoolbox_best_pixel_format(avctx); + bool full_range = avctx->color_range == AVCOL_RANGE_JPEG; + avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context_with_pix_fmt(pix_fmt, full_range); if (!avctx->hwaccel_context) return AVERROR(ENOMEM); return videotoolbox_start(avctx); diff -Nru ffmpeg-4.2.2/libavcodec/videotoolboxenc.c ffmpeg-4.4/libavcodec/videotoolboxenc.c --- ffmpeg-4.2.2/libavcodec/videotoolboxenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/videotoolboxenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -31,6 +31,7 @@ #include "libavutil/pixdesc.h" #include "internal.h" #include +#include "atsc_a53.h" #include "h264.h" #include "h264_sei.h" #include @@ -39,6 +40,10 @@ enum { kCMVideoCodecType_HEVC = 'hvc1' }; #endif +#if !HAVE_KCMVIDEOCODECTYPE_HEVCWITHALPHA +enum { kCMVideoCodecType_HEVCWithAlpha = 'muxa' }; +#endif + #if !HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE enum { kCVPixelFormatType_420YpCbCr10BiPlanarFullRange = 'xf20' }; enum { kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange = 'x420' }; @@ -80,11 +85,14 @@ CFStringRef kVTProfileLevel_H264_High_5_1; CFStringRef kVTProfileLevel_H264_High_5_2; CFStringRef kVTProfileLevel_H264_High_AutoLevel; + CFStringRef kVTProfileLevel_H264_Extended_5_0; + CFStringRef kVTProfileLevel_H264_Extended_AutoLevel; CFStringRef kVTProfileLevel_HEVC_Main_AutoLevel; CFStringRef kVTProfileLevel_HEVC_Main10_AutoLevel; CFStringRef kVTCompressionPropertyKey_RealTime; + CFStringRef kVTCompressionPropertyKey_TargetQualityForAlpha; CFStringRef kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder; CFStringRef kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder; @@ -137,11 +145,15 @@ GET_SYM(kVTProfileLevel_H264_High_5_1, "H264_High_5_1"); GET_SYM(kVTProfileLevel_H264_High_5_2, "H264_High_5_2"); GET_SYM(kVTProfileLevel_H264_High_AutoLevel, "H264_High_AutoLevel"); + GET_SYM(kVTProfileLevel_H264_Extended_5_0, "H264_Extended_5_0"); + GET_SYM(kVTProfileLevel_H264_Extended_AutoLevel, "H264_Extended_AutoLevel"); GET_SYM(kVTProfileLevel_HEVC_Main_AutoLevel, "HEVC_Main_AutoLevel"); GET_SYM(kVTProfileLevel_HEVC_Main10_AutoLevel, "HEVC_Main10_AutoLevel"); GET_SYM(kVTCompressionPropertyKey_RealTime, "RealTime"); + GET_SYM(kVTCompressionPropertyKey_TargetQualityForAlpha, + "TargetQualityForAlpha"); GET_SYM(kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder, "EnableHardwareAcceleratedVideoEncoder"); @@ -154,6 +166,7 @@ H264_PROF_BASELINE, H264_PROF_MAIN, H264_PROF_HIGH, + H264_PROF_EXTENDED, H264_PROF_COUNT } VT_H264Profile; @@ -216,11 +229,14 @@ int64_t allow_sw; int64_t require_sw; + double alpha_quality; bool flushing; - bool has_b_frames; + int has_b_frames; bool warned_color_range; - bool a53_cc; + + /* can't be bool type since AVOption will access it as int */ + int a53_cc; } VTEncContext; static int vtenc_populate_extradata(AVCodecContext *avctx, @@ -286,7 +302,7 @@ return 0; } - while (!vtctx->q_head && !vtctx->async_error && wait) { + while (!vtctx->q_head && !vtctx->async_error && wait && !vtctx->flushing) { pthread_cond_wait(&vtctx->cv_sample_sent, &vtctx->lock); } @@ -302,6 +318,7 @@ vtctx->q_tail = NULL; } + vtctx->frame_ct_out++; pthread_mutex_unlock(&vtctx->lock); *buf = info->cm_buffer; @@ -313,7 +330,6 @@ } av_free(info); - vtctx->frame_ct_out++; return 0; } @@ -332,7 +348,6 @@ info->next = NULL; pthread_mutex_lock(&vtctx->lock); - pthread_cond_signal(&vtctx->cv_sample_sent); if (!vtctx->q_head) { vtctx->q_head = info; @@ -342,6 +357,7 @@ vtctx->q_tail = info; + pthread_cond_signal(&vtctx->cv_sample_sent); pthread_mutex_unlock(&vtctx->lock); } @@ -384,11 +400,17 @@ return 0; } -static CMVideoCodecType get_cm_codec_type(enum AVCodecID id) +static CMVideoCodecType get_cm_codec_type(enum AVCodecID id, + enum AVPixelFormat fmt, + double alpha_quality) { switch (id) { case AV_CODEC_ID_H264: return kCMVideoCodecType_H264; - case AV_CODEC_ID_HEVC: return kCMVideoCodecType_HEVC; + case AV_CODEC_ID_HEVC: + if (fmt == AV_PIX_FMT_BGRA && alpha_quality > 0.0) { + return kCMVideoCodecType_HEVCWithAlpha; + } + return kCMVideoCodecType_HEVC; default: return 0; } } @@ -565,16 +587,19 @@ ExtraSEI *sei = sourceFrameCtx; if (vtctx->async_error) { - if(sample_buffer) CFRelease(sample_buffer); return; } - if (status || !sample_buffer) { + if (status) { av_log(avctx, AV_LOG_ERROR, "Error encoding frame: %d\n", (int)status); set_async_error(vtctx, AVERROR_EXTERNAL); return; } + if (!sample_buffer) { + return; + } + if (!avctx->extradata && (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) { int set_status = set_extradata(avctx, sample_buffer); if (set_status) { @@ -704,6 +729,14 @@ compat_keys.kVTProfileLevel_H264_High_5_2; break; } break; + case H264_PROF_EXTENDED: + switch (vtctx->level) { + case 0: *profile_level_val = + compat_keys.kVTProfileLevel_H264_Extended_AutoLevel; break; + case 50: *profile_level_val = + compat_keys.kVTProfileLevel_H264_Extended_5_0; break; + } + break; } if (!*profile_level_val) { @@ -767,11 +800,12 @@ *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; - *av_pixel_format = kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange; } else { return AVERROR(EINVAL); } @@ -877,6 +911,14 @@ *primaries = NULL; break; + case AVCOL_PRI_BT470BG: + *primaries = kCVImageBufferColorPrimaries_EBU_3213; + break; + + case AVCOL_PRI_SMPTE170M: + *primaries = kCVImageBufferColorPrimaries_SMPTE_C; + break; + case AVCOL_PRI_BT709: *primaries = kCVImageBufferColorPrimaries_ITU_R_709_2; break; @@ -915,6 +957,22 @@ *transfer_fnc = kCVImageBufferTransferFunction_SMPTE_240M_1995; break; +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_2084_PQ + case AVCOL_TRC_SMPTE2084: + *transfer_fnc = kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ; + break; +#endif +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_LINEAR + case AVCOL_TRC_LINEAR: + *transfer_fnc = kCVImageBufferTransferFunction_Linear; + break; +#endif +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG + case AVCOL_TRC_ARIB_STD_B67: + *transfer_fnc = kCVImageBufferTransferFunction_ITU_R_2100_HLG; + break; +#endif + case AVCOL_TRC_GAMMA22: gamma = 2.2; *transfer_fnc = kCVImageBufferTransferFunction_UseGamma; @@ -933,6 +991,7 @@ break; default: + *transfer_fnc = NULL; av_log(avctx, AV_LOG_ERROR, "Transfer function %s is not supported.\n", av_color_transfer_name(trc)); return -1; } @@ -971,6 +1030,12 @@ return 0; } +// constant quality only on Macs with Apple Silicon +static bool vtenc_qscale_enabled(void) +{ + return TARGET_OS_OSX && TARGET_CPU_ARM64; +} + static int vtenc_create_encoder(AVCodecContext *avctx, CMVideoCodecType codec_type, CFStringRef profile_level, @@ -982,7 +1047,9 @@ VTEncContext *vtctx = avctx->priv_data; SInt32 bit_rate = avctx->bit_rate; SInt32 max_rate = avctx->rc_max_rate; + Float32 quality = avctx->global_quality / FF_QP2LAMBDA; CFNumberRef bit_rate_num; + CFNumberRef quality_num; CFNumberRef bytes_per_second; CFNumberRef one_second; CFArrayRef data_rate_limits; @@ -1013,15 +1080,33 @@ return AVERROR_EXTERNAL; } - bit_rate_num = CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt32Type, - &bit_rate); - if (!bit_rate_num) return AVERROR(ENOMEM); - - status = VTSessionSetProperty(vtctx->session, - kVTCompressionPropertyKey_AverageBitRate, - bit_rate_num); - CFRelease(bit_rate_num); + if (avctx->flags & AV_CODEC_FLAG_QSCALE && !vtenc_qscale_enabled()) { + av_log(avctx, AV_LOG_ERROR, "Error: -q:v qscale not available for encoder. Use -b:v bitrate instead.\n"); + return AVERROR_EXTERNAL; + } + + if (avctx->flags & AV_CODEC_FLAG_QSCALE) { + quality = quality >= 100 ? 1.0 : quality / 100; + quality_num = CFNumberCreate(kCFAllocatorDefault, + kCFNumberFloat32Type, + &quality); + if (!quality_num) return AVERROR(ENOMEM); + + status = VTSessionSetProperty(vtctx->session, + kVTCompressionPropertyKey_Quality, + quality_num); + CFRelease(quality_num); + } else { + bit_rate_num = CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt32Type, + &bit_rate); + if (!bit_rate_num) return AVERROR(ENOMEM); + + status = VTSessionSetProperty(vtctx->session, + kVTCompressionPropertyKey_AverageBitRate, + bit_rate_num); + CFRelease(bit_rate_num); + } if (status) { av_log(avctx, AV_LOG_ERROR, "Error setting bitrate property: %d\n", status); @@ -1071,15 +1156,26 @@ } } - if (vtctx->codec_id == AV_CODEC_ID_H264) { - // kVTCompressionPropertyKey_ProfileLevel is not available for HEVC - if (profile_level) { + if (vtctx->codec_id == AV_CODEC_ID_HEVC) { + if (avctx->pix_fmt == AV_PIX_FMT_BGRA && vtctx->alpha_quality > 0.0) { + CFNumberRef alpha_quality_num = CFNumberCreate(kCFAllocatorDefault, + kCFNumberDoubleType, + &vtctx->alpha_quality); + if (!alpha_quality_num) return AVERROR(ENOMEM); + status = VTSessionSetProperty(vtctx->session, - kVTCompressionPropertyKey_ProfileLevel, - profile_level); - if (status) { - av_log(avctx, AV_LOG_ERROR, "Error setting profile/level property: %d\n", status); - } + compat_keys.kVTCompressionPropertyKey_TargetQualityForAlpha, + alpha_quality_num); + CFRelease(alpha_quality_num); + } + } + + if (profile_level) { + status = VTSessionSetProperty(vtctx->session, + kVTCompressionPropertyKey_ProfileLevel, + profile_level); + if (status) { + av_log(avctx, AV_LOG_ERROR, "Error setting profile/level property: %d. Output will be encoded using a supported profile/level combination.\n", status); } } @@ -1286,13 +1382,14 @@ CFNumberRef gamma_level = NULL; int status; - codec_type = get_cm_codec_type(avctx->codec_id); + codec_type = get_cm_codec_type(avctx->codec_id, avctx->pix_fmt, 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); } vtctx->codec_id = avctx->codec_id; + avctx->max_b_frames = 16; if (vtctx->codec_id == AV_CODEC_ID_H264) { vtctx->get_param_set_func = CMVideoFormatDescriptionGetH264ParameterSetAtIndex; @@ -1300,7 +1397,7 @@ vtctx->has_b_frames = avctx->max_b_frames > 0; if(vtctx->has_b_frames && vtctx->profile == H264_PROF_BASELINE){ av_log(avctx, AV_LOG_WARNING, "Cannot use B-frames with baseline profile. Output will not contain B-frames.\n"); - vtctx->has_b_frames = false; + vtctx->has_b_frames = 0; } if (vtctx->entropy == VT_CABAC && vtctx->profile == H264_PROF_BASELINE) { @@ -1313,6 +1410,8 @@ 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; } enc_info = CFDictionaryCreateMutable( @@ -1408,7 +1507,8 @@ if (!status && has_b_frames_cfbool) { //Some devices don't output B-frames for main profile, even if requested. - vtctx->has_b_frames = CFBooleanGetValue(has_b_frames_cfbool); + // HEVC has b-pyramid + vtctx->has_b_frames = (CFBooleanGetValue(has_b_frames_cfbool) && avctx->codec_id == AV_CODEC_ID_HEVC) ? 2 : 1; CFRelease(has_b_frames_cfbool); } avctx->has_b_frames = vtctx->has_b_frames; @@ -1711,7 +1811,7 @@ remaining_dst_size--; wrote_bytes = write_sei(sei, - H264_SEI_TYPE_USER_DATA_REGISTERED, + SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35, dst_data, remaining_dst_size); @@ -1767,7 +1867,7 @@ return status; wrote_bytes = write_sei(sei, - H264_SEI_TYPE_USER_DATA_REGISTERED, + SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35, new_sei, remaining_dst_size - old_sei_length); if (wrote_bytes < 0) @@ -1863,7 +1963,7 @@ if (sei) { size_t msg_size = get_sei_msg_bytes(sei, - H264_SEI_TYPE_USER_DATA_REGISTERED); + SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35); sei_nalu_size = sizeof(start_code) + 1 + msg_size + 1; } @@ -1996,6 +2096,14 @@ 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; @@ -2316,7 +2424,7 @@ if (vtctx->frame_ct_in == 0) { vtctx->first_pts = frame->pts; - } else if(vtctx->frame_ct_in == 1 && vtctx->has_b_frames) { + } else if(vtctx->frame_ct_in == vtctx->has_b_frames) { vtctx->dts_delta = frame->pts - vtctx->first_pts; } @@ -2451,14 +2559,17 @@ { VTEncContext *vtctx = avctx->priv_data; - pthread_cond_destroy(&vtctx->cv_sample_sent); - pthread_mutex_destroy(&vtctx->lock); - - if(!vtctx->session) return 0; + if(!vtctx->session) { + pthread_cond_destroy(&vtctx->cv_sample_sent); + pthread_mutex_destroy(&vtctx->lock); + return 0; + } VTCompressionSessionCompleteFrames(vtctx->session, kCMTimeIndefinite); clear_frame_queue(vtctx); + pthread_cond_destroy(&vtctx->cv_sample_sent); + pthread_mutex_destroy(&vtctx->lock); CFRelease(vtctx->session); vtctx->session = NULL; @@ -2491,6 +2602,7 @@ AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_BGRA, AV_PIX_FMT_P010LE, AV_PIX_FMT_NONE }; @@ -2514,6 +2626,7 @@ { "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" }, + { "extended", "Extend Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_EXTENDED }, INT_MIN, INT_MAX, VE, "profile" }, { "level", "Level", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 52, VE, "level" }, { "1.3", "Level 1.3, only available with Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = 13 }, INT_MIN, INT_MAX, VE, "level" }, @@ -2567,6 +2680,8 @@ { "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" }, + { "alpha_quality", "Compression quality for the alpha channel", OFFSET(alpha_quality), AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0.0, 1.0, VE }, + COMMON_OPTIONS { NULL }, }; diff -Nru ffmpeg-4.2.2/libavcodec/vima.c ffmpeg-4.4/libavcodec/vima.c --- ffmpeg-4.2.2/libavcodec/vima.c 2018-07-17 09:27:41.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vima.c 2021-04-08 21:28:39.000000000 +0000 @@ -214,5 +214,5 @@ .id = AV_CODEC_ID_ADPCM_VIMA, .init = decode_init, .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; diff -Nru ffmpeg-4.2.2/libavcodec/vlc.h ffmpeg-4.4/libavcodec/vlc.h --- ffmpeg-4.2.2/libavcodec/vlc.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vlc.h 2021-04-08 21:28:39.000000000 +0000 @@ -49,28 +49,73 @@ const void *codes, int codes_wrap, int codes_size, const void *symbols, int symbols_wrap, int symbols_size, int flags); + +/** + * Build VLC decoding tables suitable for use with get_vlc2() + * + * This function takes lengths and symbols and calculates the codes from them. + * For this the input lengths and symbols have to be sorted according to "left + * nodes in the corresponding tree first". + * + * @param[in,out] vlc The VLC to be initialized; table and table_allocated + * must have been set when initializing a static VLC, + * otherwise this will be treated as uninitialized. + * @param[in] nb_bits The number of bits to use for the VLC table; + * higher values take up more memory and cache, but + * allow to read codes with fewer reads. + * @param[in] nb_codes The number of provided length and (if supplied) symbol + * entries. + * @param[in] lens The lengths of the codes. Entries > 0 correspond to + * valid codes; entries == 0 will be skipped and entries + * with len < 0 indicate that the tree is incomplete and + * has an open end of length -len at this position. + * @param[in] lens_wrap Stride (in bytes) of the lengths. + * @param[in] symbols The symbols, i.e. what is returned from get_vlc2() + * when the corresponding code is encountered. + * May be NULL, then 0, 1, 2, 3, 4,... will be used. + * @param[in] symbols_wrap Stride (in bytes) of the symbols. + * @param[in] symbols_size Size of the symbols. 1 and 2 are supported. + * @param[in] offset An offset to apply to all the valid symbols. + * @param[in] flags A combination of the INIT_VLC_* flags; notice that + * INIT_VLC_INPUT_LE is pointless and ignored. + */ +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); + void ff_free_vlc(VLC *vlc); -#define INIT_VLC_LE 2 +/* If INIT_VLC_INPUT_LE is set, the LSB bit of the codes used to + * initialize the VLC table is the first bit to be read. */ +#define INIT_VLC_INPUT_LE 2 +/* If set the VLC is intended for a little endian bitstream reader. */ +#define INIT_VLC_OUTPUT_LE 8 +#define INIT_VLC_LE (INIT_VLC_INPUT_LE | INIT_VLC_OUTPUT_LE) #define INIT_VLC_USE_NEW_STATIC 4 +#define INIT_VLC_STATIC_OVERLONG (1 | INIT_VLC_USE_NEW_STATIC) -#define INIT_VLC_SPARSE_STATIC(vlc, bits, a, b, c, d, e, f, g, h, i, j, static_size) \ +#define INIT_CUSTOM_VLC_SPARSE_STATIC(vlc, bits, a, b, c, d, e, f, g, \ + h, i, j, flags, static_size) \ do { \ static VLC_TYPE table[static_size][2]; \ (vlc)->table = table; \ (vlc)->table_allocated = static_size; \ ff_init_vlc_sparse(vlc, bits, a, b, c, d, e, f, g, h, i, j, \ - INIT_VLC_USE_NEW_STATIC); \ + flags | INIT_VLC_USE_NEW_STATIC); \ } while (0) +#define INIT_VLC_SPARSE_STATIC(vlc, bits, a, b, c, d, e, f, g, h, i, j, static_size) \ + INIT_CUSTOM_VLC_SPARSE_STATIC(vlc, bits, a, b, c, d, e, f, g, \ + h, i, j, 0, static_size) + #define INIT_LE_VLC_SPARSE_STATIC(vlc, bits, a, b, c, d, e, f, g, h, i, j, static_size) \ - do { \ - static VLC_TYPE table[static_size][2]; \ - (vlc)->table = table; \ - (vlc)->table_allocated = static_size; \ - ff_init_vlc_sparse(vlc, bits, a, b, c, d, e, f, g, h, i, j, \ - INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); \ - } while (0) + INIT_CUSTOM_VLC_SPARSE_STATIC(vlc, bits, a, b, c, d, e, f, g, \ + h, i, j, INIT_VLC_LE, static_size) + +#define INIT_CUSTOM_VLC_STATIC(vlc, bits, a, b, c, d, e, f, g, flags, static_size) \ + INIT_CUSTOM_VLC_SPARSE_STATIC(vlc, bits, a, b, c, d, e, f, g, \ + NULL, 0, 0, flags, static_size) #define INIT_VLC_STATIC(vlc, bits, a, b, c, d, e, f, g, static_size) \ INIT_VLC_SPARSE_STATIC(vlc, bits, a, b, c, d, e, f, g, NULL, 0, 0, static_size) @@ -78,4 +123,17 @@ #define INIT_LE_VLC_STATIC(vlc, bits, a, b, c, d, e, f, g, static_size) \ INIT_LE_VLC_SPARSE_STATIC(vlc, bits, a, b, c, d, e, f, g, NULL, 0, 0, static_size) +#define INIT_VLC_STATIC_FROM_LENGTHS(vlc, bits, nb_codes, lens, len_wrap, \ + symbols, symbols_wrap, symbols_size, \ + offset, flags, static_size) \ + do { \ + static VLC_TYPE table[static_size][2]; \ + (vlc)->table = table; \ + (vlc)->table_allocated = static_size; \ + ff_init_vlc_from_lengths(vlc, bits, nb_codes, lens, len_wrap, \ + symbols, symbols_wrap, symbols_size, \ + offset, flags | INIT_VLC_USE_NEW_STATIC, \ + NULL); \ + } while (0) + #endif /* AVCODEC_VLC_H */ diff -Nru ffmpeg-4.2.2/libavcodec/vmdaudio.c ffmpeg-4.4/libavcodec/vmdaudio.c --- ffmpeg-4.2.2/libavcodec/vmdaudio.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vmdaudio.c 2020-07-04 22:36:04.000000000 +0000 @@ -76,7 +76,9 @@ av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); return AVERROR(EINVAL); } - if (avctx->block_align < 1 || avctx->block_align % avctx->channels) { + if (avctx->block_align < 1 || avctx->block_align % avctx->channels || + avctx->block_align > INT_MAX - avctx->channels + ) { av_log(avctx, AV_LOG_ERROR, "invalid block align\n"); return AVERROR(EINVAL); } diff -Nru ffmpeg-4.2.2/libavcodec/vmdvideo.c ffmpeg-4.4/libavcodec/vmdvideo.c --- ffmpeg-4.2.2/libavcodec/vmdvideo.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vmdvideo.c 2021-04-08 21:28:39.000000000 +0000 @@ -194,7 +194,7 @@ unsigned char len; int ofs; - int frame_x, frame_y; + int frame_x, frame_y, prev_linesize; int frame_width, frame_height; frame_x = AV_RL16(&s->buf[6]); @@ -226,7 +226,7 @@ frame_y + frame_height > s->avctx->height) { av_log(s->avctx, AV_LOG_ERROR, "Invalid vertical range %d-%d\n", - frame_x, frame_width); + frame_y, frame_height); return AVERROR_INVALIDDATA; } @@ -282,7 +282,13 @@ } dp = &frame->data[0][frame_y * frame->linesize[0] + frame_x]; - pp = &s->prev_frame->data[0][frame_y * s->prev_frame->linesize[0] + frame_x]; + if (s->prev_frame->data[0]) { + prev_linesize = s->prev_frame->linesize[0]; + pp = s->prev_frame->data[0] + frame_y * prev_linesize + frame_x; + } else { + pp = NULL; + prev_linesize = 0; + } switch (meth) { case 1: for (i = 0; i < frame_height; i++) { @@ -298,7 +304,7 @@ ofs += len; } else { /* interframe pixel copy */ - if (ofs + len + 1 > frame_width || !s->prev_frame->data[0]) + if (ofs + len + 1 > frame_width || !pp) return AVERROR_INVALIDDATA; memcpy(&dp[ofs], &pp[ofs], len + 1); ofs += len + 1; @@ -311,7 +317,7 @@ return AVERROR_INVALIDDATA; } dp += frame->linesize[0]; - pp += s->prev_frame->linesize[0]; + pp = FF_PTR_ADD(pp, prev_linesize); } break; @@ -319,7 +325,6 @@ for (i = 0; i < frame_height; i++) { bytestream2_get_buffer(&gb, dp, frame_width); dp += frame->linesize[0]; - pp += s->prev_frame->linesize[0]; } break; @@ -347,7 +352,7 @@ } } else { /* interframe pixel copy */ - if (ofs + len + 1 > frame_width || !s->prev_frame->data[0]) + if (ofs + len + 1 > frame_width || !pp) return AVERROR_INVALIDDATA; memcpy(&dp[ofs], &pp[ofs], len + 1); ofs += len + 1; @@ -360,7 +365,7 @@ return AVERROR_INVALIDDATA; } dp += frame->linesize[0]; - pp += s->prev_frame->linesize[0]; + pp = FF_PTR_ADD(pp, prev_linesize); } break; } diff -Nru ffmpeg-4.2.2/libavcodec/vmnc.c ffmpeg-4.4/libavcodec/vmnc.c --- ffmpeg-4.2.2/libavcodec/vmnc.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vmnc.c 2020-07-11 10:39:30.000000000 +0000 @@ -339,7 +339,7 @@ if (12LL * chunks > bytestream2_get_bytes_left(gb)) return AVERROR_INVALIDDATA; - if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) + if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) return ret; c->pic->key_frame = 0; diff -Nru ffmpeg-4.2.2/libavcodec/vorbis_data.c ffmpeg-4.4/libavcodec/vorbis_data.c --- ffmpeg-4.2.2/libavcodec/vorbis_data.c 2016-03-29 02:25:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vorbis_data.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,7 +19,8 @@ */ #include "libavutil/channel_layout.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" + #include "vorbis.h" const uint8_t ff_vorbis_channel_layout_offsets[8][8] = { @@ -33,17 +34,6 @@ { 0, 2, 1, 7, 5, 6, 3, 4 }, }; -const uint8_t ff_vorbis_encoding_channel_layout_offsets[8][8] = { - { 0 }, - { 0, 1 }, - { 0, 2, 1 }, - { 0, 1, 2, 3 }, - { 0, 2, 1, 3, 4 }, - { 0, 2, 1, 4, 5, 3 }, - { 0, 2, 1, 5, 6, 4, 3 }, - { 0, 2, 1, 6, 7, 4, 5, 3 }, -}; - const uint64_t ff_vorbis_channel_layouts[9] = { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, diff -Nru ffmpeg-4.2.2/libavcodec/vorbisdec.c ffmpeg-4.4/libavcodec/vorbisdec.c --- ffmpeg-4.2.2/libavcodec/vorbisdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vorbisdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -1890,7 +1890,7 @@ .close = vorbis_decode_close, .decode = vorbis_decode_frame, .flush = vorbis_decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .channel_layouts = ff_vorbis_channel_layouts, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, diff -Nru ffmpeg-4.2.2/libavcodec/vorbis.h ffmpeg-4.4/libavcodec/vorbis.h --- ffmpeg-4.2.2/libavcodec/vorbis.h 2016-03-29 02:25:23.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vorbis.h 2021-04-08 21:28:39.000000000 +0000 @@ -26,7 +26,6 @@ extern const float ff_vorbis_floor1_inverse_db_table[256]; extern const float * const ff_vorbis_vwin[8]; extern const uint8_t ff_vorbis_channel_layout_offsets[8][8]; -extern const uint8_t ff_vorbis_encoding_channel_layout_offsets[8][8]; extern const uint64_t ff_vorbis_channel_layouts[9]; typedef struct vorbis_floor1_entry { diff -Nru ffmpeg-4.2.2/libavcodec/vp3.c ffmpeg-4.4/libavcodec/vp3.c --- ffmpeg-4.2.2/libavcodec/vp3.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp3.c 2021-04-08 21:28:39.000000000 +0000 @@ -35,6 +35,7 @@ #include #include "libavutil/imgutils.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "get_bits.h" @@ -48,6 +49,10 @@ #include "vp3dsp.h" #include "xiph.h" +#define VP3_MV_VLC_BITS 6 +#define VP4_MV_VLC_BITS 6 +#define SUPERBLOCK_VLC_BITS 6 + #define FRAGMENT_PIXELS 8 // FIXME split things out into their own arrays @@ -155,6 +160,15 @@ #define MIN_DEQUANT_VAL 2 +typedef struct HuffEntry { + uint8_t len, sym; +} HuffEntry; + +typedef struct HuffTable { + HuffEntry entries[32]; + uint8_t nb_entries; +} HuffTable; + typedef struct Vp3DecodeContext { AVCodecContext *avctx; int theora, theora_tables, theora_header; @@ -257,11 +271,9 @@ int *nkf_coded_fragment_list; int num_kf_coded_fragment[3]; - VLC dc_vlc[16]; - VLC ac_vlc_1[16]; - VLC ac_vlc_2[16]; - VLC ac_vlc_3[16]; - VLC ac_vlc_4[16]; + /* The first 16 of the following VLCs are for the dc coefficients; + the others are four groups of 16 VLCs each for ac coefficients. */ + VLC coeff_vlc[5 * 16]; VLC superblock_run_length_vlc; /* version < 2 */ VLC fragment_run_length_vlc; /* version < 2 */ @@ -287,11 +299,7 @@ uint8_t *edge_emu_buffer; /* Huffman decode */ - int hti; - unsigned int hbits; - int entries; - int huff_code_size; - uint32_t huffman_table[80][32][2]; + HuffTable huffman_table[5 * 16]; uint8_t filter_limit_values[64]; DECLARE_ALIGNED(8, int, bounding_values_array)[256 + 2]; @@ -347,16 +355,8 @@ av_frame_free(&s->last_frame.f); av_frame_free(&s->golden_frame.f); - if (avctx->internal->is_copy) - return 0; - - for (i = 0; i < 16; i++) { - ff_free_vlc(&s->dc_vlc[i]); - ff_free_vlc(&s->ac_vlc_1[i]); - ff_free_vlc(&s->ac_vlc_2[i]); - ff_free_vlc(&s->ac_vlc_3[i]); - ff_free_vlc(&s->ac_vlc_4[i]); - } + for (i = 0; i < FF_ARRAY_ELEMS(s->coeff_vlc); i++) + ff_free_vlc(&s->coeff_vlc[i]); ff_free_vlc(&s->superblock_run_length_vlc); ff_free_vlc(&s->fragment_run_length_vlc); @@ -494,7 +494,7 @@ bit ^= 1; current_run = get_vlc2(gb, s->superblock_run_length_vlc.table, - 6, 2) + 1; + SUPERBLOCK_VLC_BITS, 2); if (current_run == 34) current_run += get_bits(gb, 12); @@ -528,7 +528,7 @@ bit ^= 1; current_run = get_vlc2(gb, s->superblock_run_length_vlc.table, - 6, 2) + 1; + SUPERBLOCK_VLC_BITS, 2); if (current_run == 34) current_run += get_bits(gb, 12); @@ -687,11 +687,6 @@ static int vp4_get_block_pattern(Vp3DecodeContext *s, GetBitContext *gb, int *next_block_pattern_table) { int v = get_vlc2(gb, s->block_pattern_vlc[*next_block_pattern_table].table, 3, 2); - if (v == -1) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid block pattern\n"); - *next_block_pattern_table = 0; - return 0; - } *next_block_pattern_table = vp4_block_pattern_table_selector[v]; return v + 1; } @@ -895,7 +890,8 @@ static int vp4_get_mv(Vp3DecodeContext *s, GetBitContext *gb, int axis, int last_motion) { - int v = get_vlc2(gb, s->vp4_mv_vlc[axis][vp4_mv_table_selector[FFABS(last_motion)]].table, 6, 2) - 31; + int v = get_vlc2(gb, s->vp4_mv_vlc[axis][vp4_mv_table_selector[FFABS(last_motion)]].table, + VP4_MV_VLC_BITS, 2); return last_motion < 0 ? -v : v; } @@ -952,8 +948,10 @@ case MODE_INTER_PLUS_MV: /* all 6 fragments use the same motion vector */ if (coding_mode == 0) { - motion_x[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; - motion_y[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; + motion_x[0] = get_vlc2(gb, s->motion_vector_vlc.table, + VP3_MV_VLC_BITS, 2); + motion_y[0] = get_vlc2(gb, s->motion_vector_vlc.table, + VP3_MV_VLC_BITS, 2); } else if (coding_mode == 1) { motion_x[0] = fixed_motion_vector_table[get_bits(gb, 6)]; motion_y[0] = fixed_motion_vector_table[get_bits(gb, 6)]; @@ -982,8 +980,10 @@ current_fragment = BLOCK_Y * s->fragment_width[0] + BLOCK_X; if (s->all_fragments[current_fragment].coding_method != MODE_COPY) { if (coding_mode == 0) { - motion_x[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; - motion_y[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; + motion_x[k] = get_vlc2(gb, s->motion_vector_vlc.table, + VP3_MV_VLC_BITS, 2); + motion_y[k] = get_vlc2(gb, s->motion_vector_vlc.table, + VP3_MV_VLC_BITS, 2); } else if (coding_mode == 1) { motion_x[k] = fixed_motion_vector_table[get_bits(gb, 6)]; motion_y[k] = fixed_motion_vector_table[get_bits(gb, 6)]; @@ -1114,7 +1114,8 @@ else bit ^= 1; - run_length = get_vlc2(gb, s->superblock_run_length_vlc.table, 6, 2) + 1; + run_length = get_vlc2(gb, s->superblock_run_length_vlc.table, + SUPERBLOCK_VLC_BITS, 2); if (run_length == 34) run_length += get_bits(gb, 12); blocks_decoded += run_length; @@ -1317,7 +1318,7 @@ dc_c_table = get_bits(gb, 4); /* unpack the Y plane DC coefficients */ - residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_y_table], 0, + residual_eob_run = unpack_vlcs(s, gb, &s->coeff_vlc[dc_y_table], 0, 0, residual_eob_run); if (residual_eob_run < 0) return residual_eob_run; @@ -1328,11 +1329,11 @@ reverse_dc_prediction(s, 0, s->fragment_width[0], s->fragment_height[0]); /* unpack the C plane DC coefficients */ - residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_c_table], 0, + residual_eob_run = unpack_vlcs(s, gb, &s->coeff_vlc[dc_c_table], 0, 1, residual_eob_run); if (residual_eob_run < 0) return residual_eob_run; - residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_c_table], 0, + residual_eob_run = unpack_vlcs(s, gb, &s->coeff_vlc[dc_c_table], 0, 2, residual_eob_run); if (residual_eob_run < 0) return residual_eob_run; @@ -1353,20 +1354,24 @@ /* build tables of AC VLC tables */ for (i = 1; i <= 5; i++) { - y_tables[i] = &s->ac_vlc_1[ac_y_table]; - c_tables[i] = &s->ac_vlc_1[ac_c_table]; + /* AC VLC table group 1 */ + y_tables[i] = &s->coeff_vlc[ac_y_table + 16]; + c_tables[i] = &s->coeff_vlc[ac_c_table + 16]; } for (i = 6; i <= 14; i++) { - y_tables[i] = &s->ac_vlc_2[ac_y_table]; - c_tables[i] = &s->ac_vlc_2[ac_c_table]; + /* AC VLC table group 2 */ + y_tables[i] = &s->coeff_vlc[ac_y_table + 32]; + c_tables[i] = &s->coeff_vlc[ac_c_table + 32]; } for (i = 15; i <= 27; i++) { - y_tables[i] = &s->ac_vlc_3[ac_y_table]; - c_tables[i] = &s->ac_vlc_3[ac_c_table]; + /* AC VLC table group 3 */ + y_tables[i] = &s->coeff_vlc[ac_y_table + 48]; + c_tables[i] = &s->coeff_vlc[ac_c_table + 48]; } for (i = 28; i <= 63; i++) { - y_tables[i] = &s->ac_vlc_4[ac_y_table]; - c_tables[i] = &s->ac_vlc_4[ac_c_table]; + /* AC VLC table group 4 */ + y_tables[i] = &s->coeff_vlc[ac_y_table + 64]; + c_tables[i] = &s->coeff_vlc[ac_c_table + 64]; } /* decode all AC coefficients */ @@ -1545,23 +1550,28 @@ /* build tables of DC/AC VLC tables */ - tables[0][0] = &s->dc_vlc[dc_y_table]; - tables[1][0] = &s->dc_vlc[dc_c_table]; + /* DC table group */ + tables[0][0] = &s->coeff_vlc[dc_y_table]; + tables[1][0] = &s->coeff_vlc[dc_c_table]; for (i = 1; i <= 5; i++) { - tables[0][i] = &s->ac_vlc_1[ac_y_table]; - tables[1][i] = &s->ac_vlc_1[ac_c_table]; + /* AC VLC table group 1 */ + tables[0][i] = &s->coeff_vlc[ac_y_table + 16]; + tables[1][i] = &s->coeff_vlc[ac_c_table + 16]; } for (i = 6; i <= 14; i++) { - tables[0][i] = &s->ac_vlc_2[ac_y_table]; - tables[1][i] = &s->ac_vlc_2[ac_c_table]; + /* AC VLC table group 2 */ + tables[0][i] = &s->coeff_vlc[ac_y_table + 32]; + tables[1][i] = &s->coeff_vlc[ac_c_table + 32]; } for (i = 15; i <= 27; i++) { - tables[0][i] = &s->ac_vlc_3[ac_y_table]; - tables[1][i] = &s->ac_vlc_3[ac_c_table]; + /* AC VLC table group 3 */ + tables[0][i] = &s->coeff_vlc[ac_y_table + 48]; + tables[1][i] = &s->coeff_vlc[ac_c_table + 48]; } for (i = 28; i <= 63; i++) { - tables[0][i] = &s->ac_vlc_4[ac_y_table]; - tables[1][i] = &s->ac_vlc_4[ac_c_table]; + /* AC VLC table group 4 */ + tables[0][i] = &s->coeff_vlc[ac_y_table + 64]; + tables[1][i] = &s->coeff_vlc[ac_c_table + 64]; } vp4_set_tokens_base(s); @@ -2031,11 +2041,17 @@ plane_width, plane_height); +#define safe_loop_filter(name, ptr, stride, bounding_values) \ + if ((uintptr_t)(ptr) & 7) \ + s->vp3dsp.name##_unaligned(ptr, stride, bounding_values); \ + else \ + s->vp3dsp.name(ptr, stride, bounding_values); + if (x_offset) - s->vp3dsp.h_loop_filter(loop + loop_stride + x_offset + 1, loop_stride, bounding_values); + safe_loop_filter(h_loop_filter, loop + loop_stride + x_offset + 1, loop_stride, bounding_values); if (y_offset) - s->vp3dsp.v_loop_filter(loop + (y_offset + 1)*loop_stride + 1, loop_stride, bounding_values); + safe_loop_filter(v_loop_filter, loop + (y_offset + 1)*loop_stride + 1, loop_stride, bounding_values); } for (i = 0; i < 9; i++) @@ -2284,7 +2300,6 @@ !s->superblock_fragments || !s->macroblock_coding || !s->dc_pred_row || !s->motion_val[0] || !s->motion_val[1]) { - vp3_decode_end(avctx); return -1; } @@ -2299,12 +2314,8 @@ s->last_frame.f = av_frame_alloc(); s->golden_frame.f = av_frame_alloc(); - if (!s->current_frame.f || !s->last_frame.f || !s->golden_frame.f) { - av_frame_free(&s->current_frame.f); - av_frame_free(&s->last_frame.f); - av_frame_free(&s->golden_frame.f); + if (!s->current_frame.f || !s->last_frame.f || !s->golden_frame.f) return AVERROR(ENOMEM); - } return 0; } @@ -2324,8 +2335,6 @@ if (ret < 0) return ret; - avctx->internal->allocate_progress = 1; - if (avctx->codec_tag == MKTAG('V', 'P', '4', '0')) s->version = 3; else if (avctx->codec_tag == MKTAG('V', 'P', '3', '0')) @@ -2416,131 +2425,84 @@ /* init VLC tables */ if (s->version < 2) { - for (i = 0; i < 16; i++) { - /* DC histograms */ - init_vlc(&s->dc_vlc[i], 11, 32, - &dc_bias[i][0][1], 4, 2, - &dc_bias[i][0][0], 4, 2, 0); - - /* group 1 AC histograms */ - init_vlc(&s->ac_vlc_1[i], 11, 32, - &ac_bias_0[i][0][1], 4, 2, - &ac_bias_0[i][0][0], 4, 2, 0); - - /* group 2 AC histograms */ - init_vlc(&s->ac_vlc_2[i], 11, 32, - &ac_bias_1[i][0][1], 4, 2, - &ac_bias_1[i][0][0], 4, 2, 0); - - /* group 3 AC histograms */ - init_vlc(&s->ac_vlc_3[i], 11, 32, - &ac_bias_2[i][0][1], 4, 2, - &ac_bias_2[i][0][0], 4, 2, 0); - - /* group 4 AC histograms */ - init_vlc(&s->ac_vlc_4[i], 11, 32, - &ac_bias_3[i][0][1], 4, 2, - &ac_bias_3[i][0][0], 4, 2, 0); - } + for (i = 0; i < FF_ARRAY_ELEMS(s->coeff_vlc); i++) { + ret = ff_init_vlc_from_lengths(&s->coeff_vlc[i], 11, 32, + &vp3_bias[i][0][1], 2, + &vp3_bias[i][0][0], 2, 1, + 0, 0, avctx); + if (ret < 0) + return ret; + } #if CONFIG_VP4_DECODER } else { /* version >= 2 */ - for (i = 0; i < 16; i++) { - /* DC histograms */ - init_vlc(&s->dc_vlc[i], 11, 32, - &vp4_dc_bias[i][0][1], 4, 2, - &vp4_dc_bias[i][0][0], 4, 2, 0); - - /* group 1 AC histograms */ - init_vlc(&s->ac_vlc_1[i], 11, 32, - &vp4_ac_bias_0[i][0][1], 4, 2, - &vp4_ac_bias_0[i][0][0], 4, 2, 0); - - /* group 2 AC histograms */ - init_vlc(&s->ac_vlc_2[i], 11, 32, - &vp4_ac_bias_1[i][0][1], 4, 2, - &vp4_ac_bias_1[i][0][0], 4, 2, 0); - - /* group 3 AC histograms */ - init_vlc(&s->ac_vlc_3[i], 11, 32, - &vp4_ac_bias_2[i][0][1], 4, 2, - &vp4_ac_bias_2[i][0][0], 4, 2, 0); - - /* group 4 AC histograms */ - init_vlc(&s->ac_vlc_4[i], 11, 32, - &vp4_ac_bias_3[i][0][1], 4, 2, - &vp4_ac_bias_3[i][0][0], 4, 2, 0); + for (i = 0; i < FF_ARRAY_ELEMS(s->coeff_vlc); i++) { + ret = ff_init_vlc_from_lengths(&s->coeff_vlc[i], 11, 32, + &vp4_bias[i][0][1], 2, + &vp4_bias[i][0][0], 2, 1, + 0, 0, avctx); + if (ret < 0) + return ret; } #endif } } else { - for (i = 0; i < 16; i++) { - /* DC histograms */ - if (init_vlc(&s->dc_vlc[i], 11, 32, - &s->huffman_table[i][0][1], 8, 4, - &s->huffman_table[i][0][0], 8, 4, 0) < 0) - goto vlc_fail; - - /* group 1 AC histograms */ - if (init_vlc(&s->ac_vlc_1[i], 11, 32, - &s->huffman_table[i + 16][0][1], 8, 4, - &s->huffman_table[i + 16][0][0], 8, 4, 0) < 0) - goto vlc_fail; - - /* group 2 AC histograms */ - if (init_vlc(&s->ac_vlc_2[i], 11, 32, - &s->huffman_table[i + 16 * 2][0][1], 8, 4, - &s->huffman_table[i + 16 * 2][0][0], 8, 4, 0) < 0) - goto vlc_fail; - - /* group 3 AC histograms */ - if (init_vlc(&s->ac_vlc_3[i], 11, 32, - &s->huffman_table[i + 16 * 3][0][1], 8, 4, - &s->huffman_table[i + 16 * 3][0][0], 8, 4, 0) < 0) - goto vlc_fail; - - /* group 4 AC histograms */ - if (init_vlc(&s->ac_vlc_4[i], 11, 32, - &s->huffman_table[i + 16 * 4][0][1], 8, 4, - &s->huffman_table[i + 16 * 4][0][0], 8, 4, 0) < 0) - goto vlc_fail; + for (i = 0; i < FF_ARRAY_ELEMS(s->coeff_vlc); i++) { + const HuffTable *tab = &s->huffman_table[i]; + + ret = ff_init_vlc_from_lengths(&s->coeff_vlc[i], 11, tab->nb_entries, + &tab->entries[0].len, sizeof(*tab->entries), + &tab->entries[0].sym, sizeof(*tab->entries), 1, + 0, 0, avctx); + if (ret < 0) + return ret; } } - init_vlc(&s->superblock_run_length_vlc, 6, 34, - &superblock_run_length_vlc_table[0][1], 4, 2, - &superblock_run_length_vlc_table[0][0], 4, 2, 0); - - init_vlc(&s->fragment_run_length_vlc, 5, 30, - &fragment_run_length_vlc_table[0][1], 4, 2, - &fragment_run_length_vlc_table[0][0], 4, 2, 0); - - init_vlc(&s->mode_code_vlc, 3, 8, - &mode_code_vlc_table[0][1], 2, 1, - &mode_code_vlc_table[0][0], 2, 1, 0); - - init_vlc(&s->motion_vector_vlc, 6, 63, - &motion_vector_vlc_table[0][1], 2, 1, - &motion_vector_vlc_table[0][0], 2, 1, 0); + ret = ff_init_vlc_from_lengths(&s->superblock_run_length_vlc, SUPERBLOCK_VLC_BITS, 34, + superblock_run_length_vlc_lens, 1, + NULL, 0, 0, 1, 0, avctx); + if (ret < 0) + return ret; + + ret = ff_init_vlc_from_lengths(&s->fragment_run_length_vlc, 5, 30, + fragment_run_length_vlc_len, 1, + NULL, 0, 0, 0, 0, avctx); + if (ret < 0) + return ret; + + ret = ff_init_vlc_from_lengths(&s->mode_code_vlc, 3, 8, + mode_code_vlc_len, 1, + NULL, 0, 0, 0, 0, avctx); + if (ret < 0) + return ret; + + ret = ff_init_vlc_from_lengths(&s->motion_vector_vlc, VP3_MV_VLC_BITS, 63, + &motion_vector_vlc_table[0][1], 2, + &motion_vector_vlc_table[0][0], 2, 1, + -31, 0, avctx); + if (ret < 0) + return ret; #if CONFIG_VP4_DECODER for (j = 0; j < 2; j++) - for (i = 0; i < 7; i++) - init_vlc(&s->vp4_mv_vlc[j][i], 6, 63, - &vp4_mv_vlc[j][i][0][1], 4, 2, - &vp4_mv_vlc[j][i][0][0], 4, 2, 0); + for (i = 0; i < 7; i++) { + ret = ff_init_vlc_from_lengths(&s->vp4_mv_vlc[j][i], VP4_MV_VLC_BITS, 63, + &vp4_mv_vlc[j][i][0][1], 2, + &vp4_mv_vlc[j][i][0][0], 2, 1, -31, + 0, avctx); + if (ret < 0) + return ret; + } /* version >= 2 */ for (i = 0; i < 2; i++) - init_vlc(&s->block_pattern_vlc[i], 3, 14, - &vp4_block_pattern_vlc[i][0][1], 2, 1, - &vp4_block_pattern_vlc[i][0][0], 2, 1, 0); + if ((ret = init_vlc(&s->block_pattern_vlc[i], 3, 14, + &vp4_block_pattern_vlc[i][0][1], 2, 1, + &vp4_block_pattern_vlc[i][0][0], 2, 1, 0)) < 0) + return ret; #endif return allocate_tables(avctx); - -vlc_fail: - av_log(avctx, AV_LOG_FATAL, "Invalid huffman table\n"); - return -1; } /// Release and shuffle frames after decode finishes @@ -2589,10 +2551,6 @@ Vp3DecodeContext *s = dst->priv_data, *s1 = src->priv_data; int qps_changed = 0, i, err; -#define copy_fields(to, from, start_field, end_field) \ - memcpy(&to->start_field, &from->start_field, \ - (char *) &to->end_field - (char *) &to->start_field) - if (!s1->current_frame.f->data[0] || s->width != s1->width || s->height != s1->height) { if (s != s1) @@ -2601,23 +2559,6 @@ } if (s != s1) { - if (!s->current_frame.f) - return AVERROR(ENOMEM); - // init tables if the first frame hasn't been decoded - if (!s->current_frame.f->data[0]) { - int y_fragment_count, c_fragment_count; - s->avctx = dst; - err = allocate_tables(dst); - if (err) - return err; - y_fragment_count = s->fragment_width[0] * s->fragment_height[0]; - c_fragment_count = s->fragment_width[1] * s->fragment_height[1]; - memcpy(s->motion_val[0], s1->motion_val[0], - y_fragment_count * sizeof(*s->motion_val[0])); - memcpy(s->motion_val[1], s1->motion_val[1], - c_fragment_count * sizeof(*s->motion_val[1])); - } - // copy previous frame data if ((err = ref_frames(s, s1)) < 0) return err; @@ -2636,9 +2577,11 @@ memcpy(&s->bounding_values_array, &s1->bounding_values_array, sizeof(s->bounding_values_array)); - if (qps_changed) - copy_fields(s, s1, qps, superblock_count); -#undef copy_fields + if (qps_changed) { + memcpy(s->qps, s1->qps, sizeof(s->qps)); + memcpy(s->last_qps, s1->last_qps, sizeof(s->last_qps)); + s->nqps = s1->nqps; + } } return update_frames(dst); @@ -2737,7 +2680,7 @@ s->current_frame.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; s->current_frame.f->key_frame = s->keyframe; - if (ff_thread_get_buffer(avctx, &s->current_frame, AV_GET_BUFFER_FLAG_REF) < 0) + if ((ret = ff_thread_get_buffer(avctx, &s->current_frame, AV_GET_BUFFER_FLAG_REF)) < 0) goto error; if (!s->edge_emu_buffer) @@ -2789,8 +2732,8 @@ "vp3: first frame not a keyframe\n"); s->golden_frame.f->pict_type = AV_PICTURE_TYPE_I; - if (ff_thread_get_buffer(avctx, &s->golden_frame, - AV_GET_BUFFER_FLAG_REF) < 0) + if ((ret = ff_thread_get_buffer(avctx, &s->golden_frame, + AV_GET_BUFFER_FLAG_REF)) < 0) goto error; ff_thread_release_buffer(avctx, &s->last_frame); if ((ret = ff_thread_ref_frame(&s->last_frame, @@ -2804,39 +2747,39 @@ ff_thread_finish_setup(avctx); if (s->version < 2) { - if (unpack_superblocks(s, &gb)) { - av_log(s->avctx, AV_LOG_ERROR, "error in unpack_superblocks\n"); - goto error; - } + if ((ret = unpack_superblocks(s, &gb)) < 0) { + av_log(s->avctx, AV_LOG_ERROR, "error in unpack_superblocks\n"); + goto error; + } #if CONFIG_VP4_DECODER } else { - if (vp4_unpack_macroblocks(s, &gb)) { + if ((ret = vp4_unpack_macroblocks(s, &gb)) < 0) { av_log(s->avctx, AV_LOG_ERROR, "error in vp4_unpack_macroblocks\n"); goto error; } #endif } - if (unpack_modes(s, &gb)) { + if ((ret = unpack_modes(s, &gb)) < 0) { av_log(s->avctx, AV_LOG_ERROR, "error in unpack_modes\n"); goto error; } - if (unpack_vectors(s, &gb)) { + if (ret = unpack_vectors(s, &gb)) { av_log(s->avctx, AV_LOG_ERROR, "error in unpack_vectors\n"); goto error; } - if (unpack_block_qpis(s, &gb)) { + if ((ret = unpack_block_qpis(s, &gb)) < 0) { av_log(s->avctx, AV_LOG_ERROR, "error in unpack_block_qpis\n"); goto error; } if (s->version < 2) { - if (unpack_dct_coeffs(s, &gb)) { - av_log(s->avctx, AV_LOG_ERROR, "error in unpack_dct_coeffs\n"); - goto error; - } + if ((ret = unpack_dct_coeffs(s, &gb)) < 0) { + av_log(s->avctx, AV_LOG_ERROR, "error in unpack_dct_coeffs\n"); + goto error; + } #if CONFIG_VP4_DECODER } else { - if (vp4_unpack_dct_coeffs(s, &gb)) { + if ((ret = vp4_unpack_dct_coeffs(s, &gb)) < 0) { av_log(s->avctx, AV_LOG_ERROR, "error in vp4_unpack_dct_coeffs\n"); goto error; } @@ -2857,10 +2800,10 @@ // filter the last row if (s->version < 2) - for (i = 0; i < 3; i++) { - int row = (s->height >> (3 + (i && s->chroma_y_shift))) - 1; - apply_loop_filter(s, i, row, row + 1); - } + for (i = 0; i < 3; i++) { + int row = (s->height >> (3 + (i && s->chroma_y_shift))) - 1; + apply_loop_filter(s, i, row, row + 1); + } vp3_draw_horiz_band(s, s->height); /* output frame, offset as needed */ @@ -2888,65 +2831,37 @@ if (!HAVE_THREADS || !(s->avctx->active_thread_type & FF_THREAD_FRAME)) av_frame_unref(s->current_frame.f); - return -1; + return ret; } -static int read_huffman_tree(AVCodecContext *avctx, GetBitContext *gb) +static int read_huffman_tree(HuffTable *huff, GetBitContext *gb, int length, + AVCodecContext *avctx) { - Vp3DecodeContext *s = avctx->priv_data; - if (get_bits1(gb)) { int token; - if (s->entries >= 32) { /* overflow */ + if (huff->nb_entries >= 32) { /* overflow */ av_log(avctx, AV_LOG_ERROR, "huffman tree overflow\n"); return -1; } token = get_bits(gb, 5); - ff_dlog(avctx, "hti %d hbits %x token %d entry : %d size %d\n", - s->hti, s->hbits, token, s->entries, s->huff_code_size); - s->huffman_table[s->hti][token][0] = s->hbits; - s->huffman_table[s->hti][token][1] = s->huff_code_size; - s->entries++; + ff_dlog(avctx, "code length %d, curr entry %d, token %d\n", + length, huff->nb_entries, token); + huff->entries[huff->nb_entries++] = (HuffEntry){ length, token }; } else { - if (s->huff_code_size >= 32) { /* overflow */ + /* The following bound follows from the fact that nb_entries <= 32. */ + if (length >= 31) { /* overflow */ av_log(avctx, AV_LOG_ERROR, "huffman tree overflow\n"); return -1; } - s->huff_code_size++; - s->hbits <<= 1; - if (read_huffman_tree(avctx, gb)) + length++; + if (read_huffman_tree(huff, gb, length, avctx)) return -1; - s->hbits |= 1; - if (read_huffman_tree(avctx, gb)) + if (read_huffman_tree(huff, gb, length, avctx)) return -1; - s->hbits >>= 1; - s->huff_code_size--; } return 0; } -#if HAVE_THREADS -static int vp3_init_thread_copy(AVCodecContext *avctx) -{ - Vp3DecodeContext *s = avctx->priv_data; - - s->superblock_coding = NULL; - s->all_fragments = NULL; - s->coded_fragment_list[0] = NULL; - s-> kf_coded_fragment_list= NULL; - s->nkf_coded_fragment_list= NULL; - s->dct_tokens_base = NULL; - s->superblock_fragments = NULL; - s->macroblock_coding = NULL; - s->motion_val[0] = NULL; - s->motion_val[1] = NULL; - s->edge_emu_buffer = NULL; - s->dc_pred_row = NULL; - - return init_frames(s); -} -#endif - #if CONFIG_THEORA_DECODER static const enum AVPixelFormat theora_pix_fmts[4] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P @@ -2960,8 +2875,11 @@ int ret; AVRational fps, aspect; + if (get_bits_left(gb) < 206) + return AVERROR_INVALIDDATA; + s->theora_header = 0; - s->theora = get_bits_long(gb, 24); + s->theora = get_bits(gb, 24); av_log(avctx, AV_LOG_DEBUG, "Theora bitstream version %X\n", s->theora); if (!s->theora) { s->theora = 1; @@ -2982,8 +2900,8 @@ s->height = get_bits(gb, 16) << 4; if (s->theora >= 0x030200) { - visible_width = get_bits_long(gb, 24); - visible_height = get_bits_long(gb, 24); + visible_width = get_bits(gb, 24); + visible_height = get_bits(gb, 24); offset_x = get_bits(gb, 8); /* offset x */ offset_y = get_bits(gb, 8); /* offset y, from bottom */ @@ -3011,8 +2929,8 @@ fps.den, fps.num, 1 << 30); } - aspect.num = get_bits_long(gb, 24); - aspect.den = get_bits_long(gb, 24); + aspect.num = get_bits(gb, 24); + aspect.den = get_bits(gb, 24); if (aspect.num && aspect.den) { av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den, @@ -3067,7 +2985,7 @@ static int theora_decode_tables(AVCodecContext *avctx, GetBitContext *gb) { Vp3DecodeContext *s = avctx->priv_data; - int i, n, matrices, inter, plane; + int i, n, matrices, inter, plane, ret; if (!s->theora_header) return AVERROR_INVALIDDATA; @@ -3159,17 +3077,10 @@ } /* Huffman tables */ - for (s->hti = 0; s->hti < 80; s->hti++) { - s->entries = 0; - s->huff_code_size = 1; - if (!get_bits1(gb)) { - s->hbits = 0; - if (read_huffman_tree(avctx, gb)) - return -1; - s->hbits = 1; - if (read_huffman_tree(avctx, gb)) - return -1; - } + for (int i = 0; i < FF_ARRAY_ELEMS(s->huffman_table); i++) { + s->huffman_table[i].nb_entries = 0; + if ((ret = read_huffman_tree(&s->huffman_table[i], gb, 0, avctx)) < 0) + return ret; } s->theora_tables = 1; @@ -3260,9 +3171,9 @@ .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, .flush = vp3_decode_flush, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp3_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp3_update_thread_context), - .caps_internal = FF_CODEC_CAP_EXPORTS_CROPPING, + .caps_internal = FF_CODEC_CAP_EXPORTS_CROPPING | FF_CODEC_CAP_ALLOCATE_PROGRESS | + FF_CODEC_CAP_INIT_CLEANUP, }; #endif @@ -3278,8 +3189,8 @@ .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, .flush = vp3_decode_flush, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp3_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp3_update_thread_context), + .caps_internal = FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_INIT_CLEANUP, }; #if CONFIG_VP4_DECODER @@ -3295,7 +3206,7 @@ .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, .flush = vp3_decode_flush, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp3_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp3_update_thread_context), + .caps_internal = FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_INIT_CLEANUP, }; #endif diff -Nru ffmpeg-4.2.2/libavcodec/vp3data.h ffmpeg-4.4/libavcodec/vp3data.h --- ffmpeg-4.2.2/libavcodec/vp3data.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp3data.h 2021-04-08 21:28:39.000000000 +0000 @@ -26,7 +26,7 @@ /* these coefficients dequantize intraframe Y plane coefficients * (note: same as JPEG) */ -static const int8_t vp31_intra_y_dequant[64] = { +static const uint8_t vp31_intra_y_dequant[64] = { 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, @@ -39,7 +39,7 @@ /* these coefficients dequantize intraframe C plane coefficients * (note: same as JPEG) */ -static const int8_t vp31_intra_c_dequant[64] = { +static const uint8_t vp31_intra_c_dequant[64] = { 17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, @@ -51,7 +51,7 @@ }; /* these coefficients dequantize interframe coefficients (all planes) */ -static const int8_t vp31_inter_dequant[64] = { +static const uint8_t vp31_inter_dequant[64] = { 16, 16, 16, 20, 24, 28, 32, 40, 16, 16, 20, 24, 28, 32, 40, 48, 16, 20, 24, 28, 32, 40, 48, 64, @@ -95,95 +95,34 @@ 0, 0, 0, 0, 0, 0, 0, 0 }; -static const uint16_t superblock_run_length_vlc_table[34][2] = { - { 0, 1 }, - - { 4, 3 }, { 5, 3 }, - - { 0xC, 4 }, { 0xD, 4 }, - - { 0x38, 6 }, { 0x39, 6 }, { 0x3A, 6 }, { 0x3B, 6 }, - - { 0xF0, 8 }, { 0xF1, 8 }, { 0xF2, 8 }, { 0xF3, 8 }, - { 0xF4, 8 }, { 0xF5, 8 }, { 0xF6, 8 }, { 0xF7, 8 }, - - { 0x3E0, 10 }, { 0x3E1, 10 }, { 0x3E2, 10 }, { 0x3E3, 10 }, - { 0x3E4, 10 }, { 0x3E5, 10 }, { 0x3E6, 10 }, { 0x3E7, 10 }, - { 0x3E8, 10 }, { 0x3E9, 10 }, { 0x3EA, 10 }, { 0x3EB, 10 }, - { 0x3EC, 10 }, { 0x3ED, 10 }, { 0x3EE, 10 }, { 0x3EF, 10 }, - - { 0x3F, 6 } /* this last VLC is a special case for reading 12 more - * bits from stream and adding the value 34 */ +static const uint8_t superblock_run_length_vlc_lens[34] = { + 1, 3, 3, 4, 4, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 6, /* This last value is a special case for reading 12 more + * bits from the stream and adding the value 34. */ }; -static const uint16_t fragment_run_length_vlc_table[30][2] = { - /* 1 -> 2 */ - { 0x0, 2 }, { 0x1, 2 }, - - /* 3 -> 4 */ - { 0x4, 3 }, { 0x5, 3 }, - - /* 5 -> 6 */ - { 0xC, 4 }, { 0xD, 4 }, - - /* 7 -> 10 */ - { 0x38, 6 }, { 0x39, 6 }, - { 0x3A, 6 }, { 0x3B, 6 }, - - /* 11 -> 14 */ - { 0x78, 7 }, { 0x79, 7 }, - { 0x7A, 7 }, { 0x7B, 7 }, - - /* 15 -> 30 */ - { 0x1F0, 9 }, { 0x1F1, 9 }, { 0x1F2, 9 }, { 0x1F3, 9 }, - { 0x1F4, 9 }, { 0x1F5, 9 }, { 0x1F6, 9 }, { 0x1F7, 9 }, - { 0x1F8, 9 }, { 0x1F9, 9 }, { 0x1FA, 9 }, { 0x1FB, 9 }, - { 0x1FC, 9 }, { 0x1FD, 9 }, { 0x1FE, 9 }, { 0x1FF, 9 } +static const uint8_t fragment_run_length_vlc_len[30] = { + 2, 2, 3, 3, 4, 4, 6, 6, 6, 6, 7, 7, 7, 7, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, }; -static const uint8_t mode_code_vlc_table[8][2] = { - { 0, 1 }, { 2, 2 }, - { 6, 3 }, { 14, 4 }, - { 30, 5 }, { 62, 6 }, - { 126, 7 }, { 127, 7 } +static const uint8_t mode_code_vlc_len[8] = { + 1, 2, 3, 4, 5, 6, 7, 7, }; static const uint8_t motion_vector_vlc_table[63][2] = { - { 0, 3 }, - { 1, 3 }, - { 2, 3 }, - - { 6, 4 }, { 7, 4 }, - - { 8, 4 }, { 9, 4 }, - - { 40, 6 }, { 41, 6 }, { 42, 6 }, { 43, 6 }, - { 44, 6 }, { 45, 6 }, { 46, 6 }, { 47, 6 }, - - { 96, 7 }, { 97, 7 }, { 98, 7 }, { 99, 7 }, - { 100, 7 }, { 101, 7 }, { 102, 7 }, { 103, 7 }, - { 104, 7 }, { 105, 7 }, { 106, 7 }, { 107, 7 }, - { 108, 7 }, { 109, 7 }, { 110, 7 }, { 111, 7 }, - - { 0xE0, 8 }, { 0xE1, 8 }, { 0xE2, 8 }, { 0xE3, 8 }, - { 0xE4, 8 }, { 0xE5, 8 }, { 0xE6, 8 }, { 0xE7, 8 }, - { 0xE8, 8 }, { 0xE9, 8 }, { 0xEA, 8 }, { 0xEB, 8 }, - { 0xEC, 8 }, { 0xED, 8 }, { 0xEE, 8 }, { 0xEF, 8 }, - - { 0xF0, 8 }, { 0xF1, 8 }, { 0xF2, 8 }, { 0xF3, 8 }, - { 0xF4, 8 }, { 0xF5, 8 }, { 0xF6, 8 }, { 0xF7, 8 }, - { 0xF8, 8 }, { 0xF9, 8 }, { 0xFA, 8 }, { 0xFB, 8 }, - { 0xFC, 8 }, { 0xFD, 8 }, { 0xFE, 8 }, { 0xFF, 8 } -}; - -static const int8_t motion_vector_table[63] = { - 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, 13, -13, 14, -14, 15, -15, - 16, -16, 17, -17, 18, -18, 19, -19, 20, -20, 21, -21, 22, -22, 23, -23, - 24, -24, 25, -25, 26, -26, 27, -27, 28, -28, 29, -29, 30, -30, 31, -31 + { 31, 3 }, { 32, 3 }, { 30, 3 }, { 33, 4 }, { 29, 4 }, { 34, 4 }, + { 28, 4 }, { 35, 6 }, { 27, 6 }, { 36, 6 }, { 26, 6 }, { 37, 6 }, + { 25, 6 }, { 38, 6 }, { 24, 6 }, { 39, 7 }, { 23, 7 }, { 40, 7 }, + { 22, 7 }, { 41, 7 }, { 21, 7 }, { 42, 7 }, { 20, 7 }, { 43, 7 }, + { 19, 7 }, { 44, 7 }, { 18, 7 }, { 45, 7 }, { 17, 7 }, { 46, 7 }, + { 16, 7 }, { 47, 8 }, { 15, 8 }, { 48, 8 }, { 14, 8 }, { 49, 8 }, + { 13, 8 }, { 50, 8 }, { 12, 8 }, { 51, 8 }, { 11, 8 }, { 52, 8 }, + { 10, 8 }, { 53, 8 }, { 9, 8 }, { 54, 8 }, { 8, 8 }, { 55, 8 }, + { 7, 8 }, { 56, 8 }, { 6, 8 }, { 57, 8 }, { 5, 8 }, { 58, 8 }, + { 4, 8 }, { 59, 8 }, { 3, 8 }, { 60, 8 }, { 2, 8 }, { 61, 8 }, + { 1, 8 }, { 62, 8 }, { 0, 8 }, }; static const int8_t fixed_motion_vector_table[64] = { @@ -240,8 +179,7 @@ static const int16_t coeff_table_token_16[2] = { 6, -6 }; static const int16_t coeff_table_token_23_24_25_26_27_28_29[2] = { 1, -1 }; -static const int16_t coeff_table_token_30[4] = { 2, 3, -2, -3 }; -static const int16_t coeff_table_token_31[4] = { 2, 3, -2, -3 }; +static const int16_t coeff_table_token_30_31[4] = { 2, 3, -2, -3 }; static const int16_t coeff_table_token_17[4] = { 7, 8, -7, -8 @@ -438,2743 +376,651 @@ coeff_table_token_23_24_25_26_27_28_29, coeff_table_token_23_24_25_26_27_28_29, coeff_table_token_23_24_25_26_27_28_29, - coeff_table_token_30, - coeff_table_token_31 + coeff_table_token_30_31, + coeff_table_token_30_31 }; -static const uint16_t dc_bias[16][32][2] = { +static const uint8_t vp3_bias[5 * 16][32][2] = { { /* DC bias table 0 */ - { 0x2D, 6 }, - { 0x26, 7 }, - { 0x166, 9 }, - { 0x4E, 8 }, - { 0x2CE, 10 }, - { 0x59E, 11 }, - { 0x27D, 11 }, - { 0x8, 5 }, - { 0x4F9, 12 }, - { 0xF, 4 }, - { 0xE, 4 }, - { 0x1B, 5 }, - { 0x6, 4 }, - { 0x8, 4 }, - { 0x5, 4 }, - { 0x1A, 5 }, - { 0x15, 5 }, - { 0x7, 4 }, - { 0xC, 4 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0x9, 4 }, - { 0x17, 5 }, - { 0x29, 6 }, - { 0x28, 6 }, - { 0xB2, 8 }, - { 0x4F8, 12 }, - { 0x59F, 11 }, - { 0x9E, 9 }, - { 0x13F, 10 }, - { 0x12, 6 }, - { 0x58, 7 } + { 20, 3 }, { 19, 3 }, { 7, 5 }, { 30, 6 }, { 1, 7 }, { 3, 8 }, + { 28, 9 }, { 26, 12 }, { 8, 12 }, { 6, 11 }, { 29, 10 }, { 14, 4 }, + { 12, 4 }, { 17, 4 }, { 13, 4 }, { 21, 4 }, { 24, 6 }, { 23, 6 }, + { 16, 5 }, { 31, 7 }, { 25, 8 }, { 2, 9 }, { 4, 10 }, { 5, 11 }, + { 27, 11 }, { 0, 6 }, { 22, 5 }, { 18, 4 }, { 15, 5 }, { 11, 5 }, + { 10, 4 }, { 9, 4 }, }, { /* DC bias table 1 */ - { 0x10, 5 }, - { 0x47, 7 }, - { 0x1FF, 9 }, - { 0x8C, 8 }, - { 0x3FC, 10 }, - { 0x46A, 11 }, - { 0x469, 11 }, - { 0x22, 6 }, - { 0x11A1, 13 }, - { 0xE, 4 }, - { 0xD, 4 }, - { 0x4, 4 }, - { 0x5, 4 }, - { 0x9, 4 }, - { 0x6, 4 }, - { 0x1E, 5 }, - { 0x16, 5 }, - { 0x7, 4 }, - { 0xC, 4 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xA, 4 }, - { 0x17, 5 }, - { 0x7D, 7 }, - { 0x7E, 7 }, - { 0x11B, 9 }, - { 0x8D1, 12 }, - { 0x3FD, 10 }, - { 0x46B, 11 }, - { 0x11A0, 13 }, - { 0x7C, 7 }, - { 0xFE, 8 } + { 20, 3 }, { 19, 3 }, { 11, 4 }, { 12, 4 }, { 14, 4 }, { 17, 4 }, + { 0, 5 }, { 7, 6 }, { 3, 8 }, { 29, 13 }, { 8, 13 }, { 26, 12 }, + { 6, 11 }, { 5, 11 }, { 28, 11 }, { 25, 9 }, { 1, 7 }, { 13, 4 }, + { 21, 4 }, { 16, 5 }, { 22, 5 }, { 18, 4 }, { 10, 4 }, { 9, 4 }, + { 15, 5 }, { 30, 7 }, { 23, 7 }, { 24, 7 }, { 31, 8 }, { 4, 10 }, + { 27, 10 }, { 2, 9 }, }, { /* DC bias table 2 */ - { 0x16, 5 }, - { 0x20, 6 }, - { 0x86, 8 }, - { 0x87, 8 }, - { 0x367, 10 }, - { 0x6CC, 11 }, - { 0x6CB, 11 }, - { 0x6E, 7 }, - { 0x366D, 14 }, - { 0xF, 4 }, - { 0xE, 4 }, - { 0x4, 4 }, - { 0x5, 4 }, - { 0xA, 4 }, - { 0x6, 4 }, - { 0x1A, 5 }, - { 0x11, 5 }, - { 0x7, 4 }, - { 0xC, 4 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0x9, 4 }, - { 0x17, 5 }, - { 0x6F, 7 }, - { 0x6D, 7 }, - { 0x364, 10 }, - { 0xD9A, 12 }, - { 0x6CA, 11 }, - { 0x1B37, 13 }, - { 0x366C, 14 }, - { 0x42, 7 }, - { 0xD8, 8 } + { 20, 3 }, { 19, 3 }, { 11, 4 }, { 12, 4 }, { 14, 4 }, { 17, 4 }, + { 1, 6 }, { 30, 7 }, { 2, 8 }, { 3, 8 }, { 16, 5 }, { 21, 4 }, + { 13, 4 }, { 0, 5 }, { 22, 5 }, { 18, 4 }, { 15, 5 }, { 31, 8 }, + { 25, 10 }, { 27, 11 }, { 6, 11 }, { 5, 11 }, { 26, 12 }, { 29, 14 }, + { 8, 14 }, { 28, 13 }, { 4, 10 }, { 24, 7 }, { 7, 7 }, { 23, 7 }, + { 10, 4 }, { 9, 4 }, }, { /* DC bias table 3 */ - { 0x0, 4 }, - { 0x2D, 6 }, - { 0xF7, 8 }, - { 0x58, 7 }, - { 0x167, 9 }, - { 0x2CB, 10 }, - { 0x2CA, 10 }, - { 0xE, 6 }, - { 0x1661, 13 }, - { 0x3, 3 }, - { 0x2, 3 }, - { 0x8, 4 }, - { 0x9, 4 }, - { 0xD, 4 }, - { 0x2, 4 }, - { 0x1F, 5 }, - { 0x17, 5 }, - { 0x1, 4 }, - { 0xC, 4 }, - { 0xE, 4 }, - { 0xA, 4 }, - { 0x6, 5 }, - { 0x78, 7 }, - { 0xF, 6 }, - { 0x7A, 7 }, - { 0x164, 9 }, - { 0x599, 11 }, - { 0x2CD, 10 }, - { 0xB31, 12 }, - { 0x1660, 13 }, - { 0x79, 7 }, - { 0xF6, 8 } + { 0, 4 }, { 17, 4 }, { 14, 4 }, { 21, 5 }, { 7, 6 }, { 23, 6 }, + { 10, 3 }, { 9, 3 }, { 11, 4 }, { 12, 4 }, { 20, 4 }, { 3, 7 }, + { 25, 9 }, { 6, 10 }, { 5, 10 }, { 29, 13 }, { 8, 13 }, { 28, 12 }, + { 26, 11 }, { 27, 10 }, { 4, 9 }, { 1, 6 }, { 16, 5 }, { 18, 4 }, + { 13, 4 }, { 19, 4 }, { 22, 7 }, { 30, 7 }, { 24, 7 }, { 31, 8 }, + { 2, 8 }, { 15, 5 }, }, { /* DC bias table 4 */ - { 0x3, 4 }, - { 0x3C, 6 }, - { 0xF, 7 }, - { 0x7A, 7 }, - { 0x1D, 8 }, - { 0x20, 9 }, - { 0x72, 10 }, - { 0x6, 6 }, - { 0x399, 13 }, - { 0x4, 3 }, - { 0x5, 3 }, - { 0x5, 4 }, - { 0x6, 4 }, - { 0xE, 4 }, - { 0x4, 4 }, - { 0x0, 4 }, - { 0x19, 5 }, - { 0x2, 4 }, - { 0xD, 4 }, - { 0x7, 4 }, - { 0x1F, 5 }, - { 0x30, 6 }, - { 0x11, 8 }, - { 0x31, 6 }, - { 0x5, 6 }, - { 0x21, 9 }, - { 0xE7, 11 }, - { 0x38, 9 }, - { 0x1CD, 12 }, - { 0x398, 13 }, - { 0x7B, 7 }, - { 0x9, 7 } + { 15, 4 }, { 5, 9 }, { 25, 9 }, { 22, 8 }, { 31, 7 }, { 24, 6 }, + { 7, 6 }, { 27, 9 }, { 6, 10 }, { 29, 13 }, { 8, 13 }, { 28, 12 }, + { 26, 11 }, { 4, 8 }, { 2, 7 }, { 17, 4 }, { 0, 4 }, { 14, 4 }, + { 11, 4 }, { 12, 4 }, { 19, 4 }, { 9, 3 }, { 10, 3 }, { 21, 6 }, + { 23, 6 }, { 16, 5 }, { 18, 4 }, { 13, 4 }, { 1, 6 }, { 3, 7 }, + { 30, 7 }, { 20, 5 }, }, { /* DC bias table 5 */ - { 0x9, 4 }, - { 0x2, 5 }, - { 0x74, 7 }, - { 0x7, 6 }, - { 0xEC, 8 }, - { 0xD1, 9 }, - { 0x1A6, 10 }, - { 0x6, 6 }, - { 0xD21, 13 }, - { 0x5, 3 }, - { 0x6, 3 }, - { 0x8, 4 }, - { 0x7, 4 }, - { 0xF, 4 }, - { 0x4, 4 }, - { 0x0, 4 }, - { 0x1C, 5 }, - { 0x2, 4 }, - { 0x5, 4 }, - { 0x3, 4 }, - { 0xC, 5 }, - { 0x35, 7 }, - { 0x1A7, 10 }, - { 0x1B, 6 }, - { 0x77, 7 }, - { 0x1A5, 10 }, - { 0x349, 11 }, - { 0xD0, 9 }, - { 0x691, 12 }, - { 0xD20, 13 }, - { 0x75, 7 }, - { 0xED, 8 } + { 15, 4 }, { 1, 5 }, { 7, 6 }, { 3, 6 }, { 17, 4 }, { 19, 4 }, + { 14, 4 }, { 18, 4 }, { 20, 5 }, { 27, 9 }, { 5, 9 }, { 29, 13 }, + { 8, 13 }, { 28, 12 }, { 26, 11 }, { 25, 10 }, { 6, 10 }, { 22, 10 }, + { 21, 7 }, { 23, 6 }, { 12, 4 }, { 11, 4 }, { 0, 4 }, { 9, 3 }, + { 10, 3 }, { 16, 5 }, { 2, 7 }, { 30, 7 }, { 4, 8 }, { 31, 8 }, + { 24, 7 }, { 13, 4 }, }, { /* DC bias table 6 */ - { 0xA, 4 }, - { 0xC, 5 }, - { 0x12, 6 }, - { 0x1B, 6 }, - { 0xB7, 8 }, - { 0x16C, 9 }, - { 0x99, 9 }, - { 0x5A, 7 }, - { 0x16D8, 13 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x0, 3 }, - { 0x5, 4 }, - { 0x17, 5 }, - { 0xE, 5 }, - { 0x2, 4 }, - { 0x3, 4 }, - { 0xF, 5 }, - { 0x1A, 6 }, - { 0x4D, 8 }, - { 0x2DB3, 14 }, - { 0x2C, 6 }, - { 0x11, 6 }, - { 0x2DA, 10 }, - { 0x5B7, 11 }, - { 0x98, 9 }, - { 0xB6D, 12 }, - { 0x2DB2, 14 }, - { 0x10, 6 }, - { 0x27, 7 } + { 13, 3 }, { 17, 4 }, { 18, 4 }, { 30, 6 }, { 24, 6 }, { 2, 6 }, + { 27, 9 }, { 6, 9 }, { 21, 8 }, { 31, 7 }, { 14, 4 }, { 1, 5 }, + { 20, 6 }, { 3, 6 }, { 16, 5 }, { 19, 5 }, { 12, 4 }, { 11, 4 }, + { 0, 4 }, { 23, 6 }, { 7, 7 }, { 5, 9 }, { 25, 10 }, { 8, 13 }, + { 29, 14 }, { 22, 14 }, { 28, 12 }, { 26, 11 }, { 4, 8 }, { 15, 5 }, + { 10, 3 }, { 9, 3 }, }, { /* DC bias table 7 */ - { 0xD, 4 }, - { 0xF, 5 }, - { 0x1D, 6 }, - { 0x8, 5 }, - { 0x51, 7 }, - { 0x56, 8 }, - { 0xAF, 9 }, - { 0x2A, 7 }, - { 0x148A, 13 }, - { 0x7, 3 }, - { 0x0, 2 }, - { 0x8, 4 }, - { 0x9, 4 }, - { 0xC, 4 }, - { 0x6, 4 }, - { 0x17, 5 }, - { 0xB, 5 }, - { 0x16, 5 }, - { 0x15, 5 }, - { 0x9, 5 }, - { 0x50, 7 }, - { 0xAE, 9 }, - { 0x2917, 14 }, - { 0x1C, 6 }, - { 0x14, 6 }, - { 0x290, 10 }, - { 0x523, 11 }, - { 0x149, 9 }, - { 0xA44, 12 }, - { 0x2916, 14 }, - { 0x53, 7 }, - { 0xA5, 8 } + { 10, 2 }, { 3, 5 }, { 19, 5 }, { 24, 6 }, { 7, 7 }, { 5, 8 }, + { 21, 9 }, { 6, 9 }, { 16, 5 }, { 14, 4 }, { 23, 6 }, { 2, 6 }, + { 1, 5 }, { 11, 4 }, { 12, 4 }, { 20, 7 }, { 4, 7 }, { 25, 10 }, + { 28, 12 }, { 8, 13 }, { 29, 14 }, { 22, 14 }, { 26, 11 }, { 27, 9 }, + { 31, 8 }, { 30, 7 }, { 18, 5 }, { 17, 5 }, { 15, 5 }, { 13, 4 }, + { 0, 4 }, { 9, 3 }, }, { /* DC bias table 8 */ - { 0x1, 4 }, - { 0x1D, 6 }, - { 0xF5, 8 }, - { 0xF4, 8 }, - { 0x24D, 10 }, - { 0x499, 11 }, - { 0x498, 11 }, - { 0x1, 5 }, - { 0x21, 6 }, - { 0x6, 3 }, - { 0x5, 3 }, - { 0x6, 4 }, - { 0x5, 4 }, - { 0x2, 4 }, - { 0x7, 5 }, - { 0x25, 6 }, - { 0x7B, 7 }, - { 0x1C, 6 }, - { 0x20, 6 }, - { 0xD, 6 }, - { 0x48, 7 }, - { 0x92, 8 }, - { 0x127, 9 }, - { 0xE, 4 }, - { 0x4, 4 }, - { 0x11, 5 }, - { 0xC, 6 }, - { 0x3C, 6 }, - { 0xF, 5 }, - { 0x0, 5 }, - { 0x1F, 5 }, - { 0x13, 5 } + { 29, 5 }, { 7, 5 }, { 0, 4 }, { 13, 4 }, { 26, 6 }, { 19, 6 }, + { 14, 5 }, { 24, 4 }, { 12, 4 }, { 11, 4 }, { 17, 6 }, { 1, 6 }, + { 28, 5 }, { 18, 6 }, { 8, 6 }, { 25, 5 }, { 20, 7 }, { 21, 8 }, + { 6, 11 }, { 5, 11 }, { 4, 10 }, { 22, 9 }, { 15, 6 }, { 31, 5 }, + { 10, 3 }, { 9, 3 }, { 23, 4 }, { 27, 6 }, { 3, 8 }, { 2, 8 }, + { 16, 7 }, { 30, 5 }, }, { /* DC bias table 9 */ - { 0x5, 4 }, - { 0x3C, 6 }, - { 0x40, 7 }, - { 0xD, 7 }, - { 0x31, 9 }, - { 0x61, 10 }, - { 0x60, 10 }, - { 0x2, 5 }, - { 0xF5, 8 }, - { 0x6, 3 }, - { 0x5, 3 }, - { 0x7, 4 }, - { 0x6, 4 }, - { 0x2, 4 }, - { 0x9, 5 }, - { 0x25, 6 }, - { 0x7, 6 }, - { 0x21, 6 }, - { 0x24, 6 }, - { 0x10, 6 }, - { 0x41, 7 }, - { 0xF4, 8 }, - { 0x19, 8 }, - { 0xE, 4 }, - { 0x3, 4 }, - { 0x11, 5 }, - { 0x11, 6 }, - { 0x3F, 6 }, - { 0x3E, 6 }, - { 0x7B, 7 }, - { 0x0, 4 }, - { 0x13, 5 } + { 30, 4 }, { 7, 5 }, { 6, 10 }, { 5, 10 }, { 4, 9 }, { 22, 8 }, + { 3, 7 }, { 16, 6 }, { 13, 4 }, { 24, 4 }, { 19, 6 }, { 26, 6 }, + { 14, 5 }, { 0, 4 }, { 12, 4 }, { 11, 4 }, { 2, 7 }, { 20, 7 }, + { 17, 6 }, { 25, 5 }, { 18, 6 }, { 15, 6 }, { 31, 5 }, { 10, 3 }, + { 9, 3 }, { 23, 4 }, { 1, 6 }, { 21, 8 }, { 8, 8 }, { 29, 7 }, + { 28, 6 }, { 27, 6 }, }, { /* DC bias table 10 */ - { 0xA, 4 }, - { 0x7, 5 }, - { 0x1, 6 }, - { 0x9, 6 }, - { 0x131, 9 }, - { 0x261, 10 }, - { 0x260, 10 }, - { 0x15, 6 }, - { 0x1, 7 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0x8, 4 }, - { 0x7, 4 }, - { 0x6, 4 }, - { 0x12, 5 }, - { 0x2F, 6 }, - { 0x14, 6 }, - { 0x27, 6 }, - { 0x2D, 6 }, - { 0x16, 6 }, - { 0x4D, 7 }, - { 0x99, 8 }, - { 0x0, 7 }, - { 0x4, 4 }, - { 0x1, 4 }, - { 0x5, 5 }, - { 0x17, 6 }, - { 0x2E, 6 }, - { 0x2C, 6 }, - { 0x8, 6 }, - { 0x6, 5 }, - { 0x1, 5 } + { 22, 7 }, { 8, 7 }, { 2, 6 }, { 31, 5 }, { 24, 4 }, { 29, 6 }, + { 3, 6 }, { 25, 5 }, { 30, 5 }, { 1, 5 }, { 23, 4 }, { 16, 6 }, + { 7, 6 }, { 19, 6 }, { 26, 6 }, { 13, 4 }, { 12, 4 }, { 11, 4 }, + { 14, 5 }, { 6, 10 }, { 5, 10 }, { 4, 9 }, { 21, 8 }, { 20, 7 }, + { 17, 6 }, { 0, 4 }, { 28, 6 }, { 18, 6 }, { 27, 6 }, { 15, 6 }, + { 10, 3 }, { 9, 3 }, }, { /* DC bias table 11 */ - { 0x0, 3 }, - { 0xE, 5 }, - { 0x17, 6 }, - { 0x2A, 6 }, - { 0x10, 7 }, - { 0xF9, 10 }, - { 0xF8, 10 }, - { 0x1E, 7 }, - { 0x3F, 8 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x6, 4 }, - { 0xF, 5 }, - { 0x5, 5 }, - { 0x16, 6 }, - { 0x29, 6 }, - { 0x2B, 6 }, - { 0x15, 6 }, - { 0x50, 7 }, - { 0x11, 7 }, - { 0x7D, 9 }, - { 0x4, 4 }, - { 0x17, 5 }, - { 0x6, 5 }, - { 0x14, 6 }, - { 0x2C, 6 }, - { 0x2D, 6 }, - { 0xE, 6 }, - { 0x9, 6 }, - { 0x51, 7 } + { 0, 3 }, { 4, 7 }, { 21, 7 }, { 30, 6 }, { 15, 5 }, { 25, 5 }, + { 29, 6 }, { 7, 7 }, { 6, 10 }, { 5, 10 }, { 22, 9 }, { 8, 8 }, + { 23, 4 }, { 26, 6 }, { 19, 6 }, { 16, 6 }, { 2, 6 }, { 13, 4 }, + { 1, 5 }, { 14, 5 }, { 12, 4 }, { 11, 4 }, { 20, 7 }, { 31, 7 }, + { 17, 6 }, { 3, 6 }, { 18, 6 }, { 27, 6 }, { 28, 6 }, { 24, 5 }, + { 10, 3 }, { 9, 3 }, }, { /* DC bias table 12 */ - { 0x2, 3 }, - { 0x18, 5 }, - { 0x2F, 6 }, - { 0xD, 5 }, - { 0x53, 7 }, - { 0x295, 10 }, - { 0x294, 10 }, - { 0xA4, 8 }, - { 0x7C, 8 }, - { 0x0, 2 }, - { 0x7, 3 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x1B, 5 }, - { 0xC, 5 }, - { 0x28, 6 }, - { 0x6A, 7 }, - { 0x1E, 6 }, - { 0x1D, 6 }, - { 0x69, 7 }, - { 0xD7, 8 }, - { 0x7D, 8 }, - { 0x14B, 9 }, - { 0x19, 5 }, - { 0x16, 5 }, - { 0x2E, 6 }, - { 0x1C, 6 }, - { 0x2B, 6 }, - { 0x2A, 6 }, - { 0x68, 7 }, - { 0x3F, 7 }, - { 0xD6, 8 } + { 9, 2 }, { 0, 3 }, { 14, 5 }, { 3, 5 }, { 26, 6 }, { 18, 6 }, + { 17, 6 }, { 8, 8 }, { 21, 8 }, { 30, 7 }, { 12, 4 }, { 11, 4 }, + { 15, 6 }, { 7, 8 }, { 6, 10 }, { 5, 10 }, { 22, 9 }, { 4, 7 }, + { 28, 6 }, { 27, 6 }, { 24, 5 }, { 25, 6 }, { 2, 6 }, { 1, 5 }, + { 23, 5 }, { 29, 7 }, { 19, 7 }, { 16, 7 }, { 31, 8 }, { 20, 8 }, + { 13, 5 }, { 10, 3 }, }, { /* DC bias table 13 */ - { 0x2, 3 }, - { 0x1B, 5 }, - { 0xC, 5 }, - { 0x18, 5 }, - { 0x29, 6 }, - { 0x7F, 8 }, - { 0x2F0, 10 }, - { 0x198, 9 }, - { 0x179, 9 }, - { 0x0, 2 }, - { 0x7, 3 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x1A, 5 }, - { 0xD, 5 }, - { 0x2A, 6 }, - { 0x64, 7 }, - { 0x1E, 6 }, - { 0x67, 7 }, - { 0x5F, 7 }, - { 0xCD, 8 }, - { 0x7E, 8 }, - { 0x2F1, 10 }, - { 0x16, 5 }, - { 0xE, 5 }, - { 0x2E, 6 }, - { 0x65, 7 }, - { 0x2B, 6 }, - { 0x28, 6 }, - { 0x3E, 7 }, - { 0xBD, 8 }, - { 0x199, 9 } + { 9, 2 }, { 0, 3 }, { 2, 5 }, { 14, 5 }, { 24, 5 }, { 17, 6 }, + { 29, 7 }, { 21, 8 }, { 5, 8 }, { 12, 4 }, { 11, 4 }, { 28, 6 }, + { 4, 6 }, { 15, 6 }, { 27, 6 }, { 23, 5 }, { 25, 6 }, { 6, 10 }, + { 22, 10 }, { 8, 9 }, { 30, 8 }, { 19, 7 }, { 3, 5 }, { 16, 7 }, + { 26, 7 }, { 7, 9 }, { 31, 9 }, { 20, 8 }, { 18, 7 }, { 13, 5 }, + { 1, 5 }, { 10, 3 }, }, { /* DC bias table 14 */ - { 0x2, 3 }, - { 0x7, 4 }, - { 0x16, 5 }, - { 0x6, 4 }, - { 0x36, 6 }, - { 0x5C, 7 }, - { 0x15D, 9 }, - { 0x15C, 9 }, - { 0x2BF, 10 }, - { 0x0, 2 }, - { 0x7, 3 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x18, 5 }, - { 0x34, 6 }, - { 0x2A, 6 }, - { 0x5E, 7 }, - { 0x6A, 7 }, - { 0x64, 7 }, - { 0x5D, 7 }, - { 0xCB, 8 }, - { 0xAD, 8 }, - { 0x2BE, 10 }, - { 0x14, 5 }, - { 0x33, 6 }, - { 0x6E, 7 }, - { 0x5F, 7 }, - { 0x6F, 7 }, - { 0x6B, 7 }, - { 0xCA, 8 }, - { 0xAC, 8 }, - { 0x15E, 9 } + { 9, 2 }, { 0, 3 }, { 3, 4 }, { 1, 4 }, { 12, 4 }, { 11, 4 }, + { 23, 5 }, { 15, 6 }, { 30, 8 }, { 21, 8 }, { 7, 9 }, { 6, 9 }, + { 31, 9 }, { 22, 10 }, { 8, 10 }, { 2, 5 }, { 5, 7 }, { 19, 7 }, + { 16, 7 }, { 26, 7 }, { 13, 5 }, { 18, 7 }, { 29, 8 }, { 20, 8 }, + { 24, 6 }, { 14, 6 }, { 17, 7 }, { 28, 7 }, { 4, 6 }, { 25, 7 }, + { 27, 7 }, { 10, 3 }, }, { /* DC bias table 15 */ - { 0xF, 4 }, - { 0x1D, 5 }, - { 0x18, 5 }, - { 0xB, 4 }, - { 0x19, 5 }, - { 0x29, 6 }, - { 0xD6, 8 }, - { 0x551, 11 }, - { 0xAA1, 12 }, - { 0x1, 2 }, - { 0x0, 2 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x1B, 5 }, - { 0x38, 6 }, - { 0x28, 6 }, - { 0x57, 7 }, - { 0x6A, 7 }, - { 0x68, 7 }, - { 0x56, 7 }, - { 0xE5, 8 }, - { 0x155, 9 }, - { 0xAA0, 12 }, - { 0x73, 7 }, - { 0x69, 7 }, - { 0xD7, 8 }, - { 0xAB, 8 }, - { 0xE4, 8 }, - { 0xA9, 8 }, - { 0x151, 9 }, - { 0x150, 9 }, - { 0x2A9, 10 } - } -}; - -static const uint16_t ac_bias_0[16][32][2] = { + { 10, 2 }, { 9, 2 }, { 12, 4 }, { 11, 4 }, { 15, 6 }, { 5, 6 }, + { 30, 9 }, { 29, 9 }, { 28, 8 }, { 22, 12 }, { 8, 12 }, { 7, 11 }, + { 31, 10 }, { 21, 9 }, { 26, 8 }, { 19, 7 }, { 16, 7 }, { 3, 4 }, + { 2, 5 }, { 4, 5 }, { 18, 7 }, { 24, 7 }, { 17, 7 }, { 6, 8 }, + { 25, 8 }, { 13, 5 }, { 14, 6 }, { 27, 8 }, { 20, 8 }, { 23, 7 }, + { 1, 5 }, { 0, 4 }, + }, { /* AC bias group 1, table 0 */ - { 0x8, 5 }, - { 0x25, 7 }, - { 0x17A, 9 }, - { 0x2F7, 10 }, - { 0xBDB, 12 }, - { 0x17B4, 13 }, - { 0x2F6B, 14 }, - { 0x1D, 5 }, - { 0x2F6A, 14 }, - { 0x8, 4 }, - { 0x7, 4 }, - { 0x1, 4 }, - { 0x2, 4 }, - { 0xA, 4 }, - { 0x6, 4 }, - { 0x0, 4 }, - { 0x1C, 5 }, - { 0x9, 4 }, - { 0xD, 4 }, - { 0xF, 4 }, - { 0xC, 4 }, - { 0x3, 4 }, - { 0xA, 5 }, - { 0x16, 5 }, - { 0x13, 6 }, - { 0x5D, 7 }, - { 0x24, 7 }, - { 0xBC, 8 }, - { 0x5C, 7 }, - { 0x5EC, 11 }, - { 0xB, 5 }, - { 0x5F, 7 } + { 15, 4 }, { 11, 4 }, { 12, 4 }, { 21, 4 }, { 0, 5 }, { 26, 7 }, + { 1, 7 }, { 24, 6 }, { 22, 5 }, { 30, 5 }, { 14, 4 }, { 10, 4 }, + { 9, 4 }, { 17, 4 }, { 13, 4 }, { 23, 5 }, { 28, 7 }, { 25, 7 }, + { 27, 8 }, { 2, 9 }, { 29, 11 }, { 5, 13 }, { 8, 14 }, { 6, 14 }, + { 4, 12 }, { 3, 10 }, { 31, 7 }, { 20, 4 }, { 18, 4 }, { 16, 5 }, + { 7, 5 }, { 19, 4 }, }, { /* AC bias group 1, table 1 */ - { 0xF, 5 }, - { 0x10, 6 }, - { 0x4B, 8 }, - { 0xC6, 8 }, - { 0x31D, 10 }, - { 0xC71, 12 }, - { 0xC70, 12 }, - { 0x1, 4 }, - { 0xC73, 12 }, - { 0x8, 4 }, - { 0x9, 4 }, - { 0x2, 4 }, - { 0x3, 4 }, - { 0xB, 4 }, - { 0x6, 4 }, - { 0x0, 4 }, - { 0x1C, 5 }, - { 0x5, 4 }, - { 0xD, 4 }, - { 0xF, 4 }, - { 0xA, 4 }, - { 0x19, 5 }, - { 0x13, 6 }, - { 0x1D, 5 }, - { 0x30, 6 }, - { 0x62, 7 }, - { 0x24, 7 }, - { 0x4A, 8 }, - { 0x18F, 9 }, - { 0xC72, 12 }, - { 0xE, 5 }, - { 0x11, 6 } + { 15, 4 }, { 7, 4 }, { 11, 4 }, { 12, 4 }, { 1, 6 }, { 31, 6 }, + { 26, 7 }, { 27, 8 }, { 2, 8 }, { 22, 6 }, { 17, 4 }, { 14, 4 }, + { 30, 5 }, { 0, 5 }, { 9, 4 }, { 10, 4 }, { 20, 4 }, { 13, 4 }, + { 24, 6 }, { 25, 7 }, { 3, 8 }, { 6, 12 }, { 5, 12 }, { 29, 12 }, + { 8, 12 }, { 4, 10 }, { 28, 9 }, { 21, 5 }, { 18, 4 }, { 16, 5 }, + { 23, 5 }, { 19, 4 }, }, { /* AC bias group 1, table 2 */ - { 0x1B, 5 }, - { 0x3, 6 }, - { 0x8D, 8 }, - { 0x40, 7 }, - { 0x239, 10 }, - { 0x471, 11 }, - { 0x8E0, 12 }, - { 0x3, 4 }, - { 0x11C3, 13 }, - { 0xA, 4 }, - { 0x9, 4 }, - { 0x4, 4 }, - { 0x5, 4 }, - { 0xE, 4 }, - { 0x7, 4 }, - { 0x1, 4 }, - { 0x1E, 5 }, - { 0x6, 4 }, - { 0xC, 4 }, - { 0xB, 4 }, - { 0x2, 4 }, - { 0x0, 5 }, - { 0x41, 7 }, - { 0x1F, 5 }, - { 0x22, 6 }, - { 0x2, 6 }, - { 0x8F, 8 }, - { 0x8C, 8 }, - { 0x11D, 9 }, - { 0x11C2, 13 }, - { 0x1A, 5 }, - { 0x21, 6 } + { 21, 5 }, { 25, 6 }, { 1, 6 }, { 15, 4 }, { 20, 4 }, { 7, 4 }, + { 11, 4 }, { 12, 4 }, { 17, 4 }, { 14, 4 }, { 3, 7 }, { 22, 7 }, + { 31, 6 }, { 24, 6 }, { 27, 8 }, { 2, 8 }, { 6, 12 }, { 29, 13 }, + { 8, 13 }, { 5, 11 }, { 4, 10 }, { 28, 9 }, { 26, 8 }, { 10, 4 }, + { 9, 4 }, { 19, 4 }, { 18, 4 }, { 30, 5 }, { 0, 5 }, { 13, 4 }, + { 16, 5 }, { 23, 5 }, }, { /* AC bias group 1, table 3 */ - { 0x1F, 5 }, - { 0x3, 6 }, - { 0x3, 7 }, - { 0x43, 7 }, - { 0xB, 9 }, - { 0x15, 10 }, - { 0x51, 12 }, - { 0x3, 4 }, - { 0x50, 12 }, - { 0xD, 4 }, - { 0xC, 4 }, - { 0x4, 4 }, - { 0x6, 4 }, - { 0xE, 4 }, - { 0xA, 4 }, - { 0x1, 4 }, - { 0x1E, 5 }, - { 0x5, 4 }, - { 0x9, 4 }, - { 0x7, 4 }, - { 0x11, 5 }, - { 0x2, 6 }, - { 0x4, 8 }, - { 0x2, 4 }, - { 0x2D, 6 }, - { 0x20, 6 }, - { 0x42, 7 }, - { 0x1, 7 }, - { 0x0, 7 }, - { 0x29, 11 }, - { 0x17, 5 }, - { 0x2C, 6 } + { 28, 7 }, { 27, 7 }, { 22, 8 }, { 8, 12 }, { 6, 12 }, { 29, 11 }, + { 5, 10 }, { 4, 9 }, { 2, 7 }, { 21, 6 }, { 1, 6 }, { 15, 4 }, + { 23, 4 }, { 7, 4 }, { 11, 4 }, { 17, 4 }, { 12, 4 }, { 19, 4 }, + { 25, 6 }, { 26, 7 }, { 3, 7 }, { 20, 5 }, { 18, 4 }, { 14, 4 }, + { 31, 6 }, { 24, 6 }, { 30, 5 }, { 10, 4 }, { 9, 4 }, { 13, 4 }, + { 16, 5 }, { 0, 5 }, }, { /* AC bias group 1, table 4 */ - { 0x3, 4 }, - { 0x1F, 6 }, - { 0x3A, 7 }, - { 0x5D, 7 }, - { 0x173, 9 }, - { 0x2E4, 10 }, - { 0x172D, 13 }, - { 0x4, 4 }, - { 0x172C, 13 }, - { 0xF, 4 }, - { 0xE, 4 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0xC, 4 }, - { 0xA, 4 }, - { 0x1, 4 }, - { 0x16, 5 }, - { 0x2, 4 }, - { 0x5, 4 }, - { 0x1A, 5 }, - { 0x2F, 6 }, - { 0x38, 7 }, - { 0x5CA, 11 }, - { 0x6, 4 }, - { 0x37, 6 }, - { 0x1E, 6 }, - { 0x3B, 7 }, - { 0x39, 7 }, - { 0xB8, 8 }, - { 0xB97, 12 }, - { 0x0, 4 }, - { 0x36, 6 } + { 30, 4 }, { 15, 4 }, { 17, 4 }, { 0, 4 }, { 7, 4 }, { 18, 4 }, + { 23, 4 }, { 21, 7 }, { 27, 7 }, { 2, 7 }, { 26, 7 }, { 25, 6 }, + { 1, 6 }, { 12, 4 }, { 11, 4 }, { 14, 4 }, { 16, 5 }, { 28, 8 }, + { 5, 10 }, { 22, 11 }, { 8, 13 }, { 6, 13 }, { 29, 12 }, { 4, 9 }, + { 3, 7 }, { 20, 6 }, { 13, 4 }, { 19, 5 }, { 31, 6 }, { 24, 6 }, + { 10, 4 }, { 9, 4 }, }, { /* AC bias group 1, table 5 */ - { 0x6, 4 }, - { 0x37, 6 }, - { 0x5D, 7 }, - { 0xC, 6 }, - { 0xB9, 8 }, - { 0x2E3, 10 }, - { 0x5C4, 11 }, - { 0x4, 4 }, - { 0x1715, 13 }, - { 0x0, 3 }, - { 0xF, 4 }, - { 0x8, 4 }, - { 0x7, 4 }, - { 0xC, 4 }, - { 0x9, 4 }, - { 0x1D, 5 }, - { 0x16, 5 }, - { 0x1C, 5 }, - { 0x1A, 5 }, - { 0xB, 5 }, - { 0x5E, 7 }, - { 0x170, 9 }, - { 0x1714, 13 }, - { 0xA, 4 }, - { 0xA, 5 }, - { 0x36, 6 }, - { 0x5F, 7 }, - { 0x1B, 7 }, - { 0x1A, 7 }, - { 0xB8B, 12 }, - { 0x2, 4 }, - { 0x7, 5 } + { 9, 3 }, { 30, 4 }, { 3, 6 }, { 28, 7 }, { 27, 7 }, { 31, 5 }, + { 7, 4 }, { 24, 5 }, { 19, 5 }, { 0, 4 }, { 12, 4 }, { 11, 4 }, + { 14, 4 }, { 23, 4 }, { 16, 5 }, { 21, 9 }, { 6, 11 }, { 22, 13 }, + { 8, 13 }, { 29, 12 }, { 5, 10 }, { 4, 8 }, { 2, 7 }, { 20, 7 }, + { 26, 7 }, { 13, 4 }, { 18, 5 }, { 25, 6 }, { 1, 6 }, { 17, 5 }, + { 15, 5 }, { 10, 4 }, }, { /* AC bias group 1, table 6 */ - { 0xC, 4 }, - { 0xB, 5 }, - { 0x79, 7 }, - { 0x22, 6 }, - { 0xF0, 8 }, - { 0x119, 9 }, - { 0x230, 10 }, - { 0x1D, 5 }, - { 0x8C4, 12 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xA, 4 }, - { 0x9, 4 }, - { 0xB, 4 }, - { 0x7, 4 }, - { 0x1C, 5 }, - { 0x3D, 6 }, - { 0xD, 5 }, - { 0x8, 5 }, - { 0x15, 6 }, - { 0x8D, 8 }, - { 0x118B, 13 }, - { 0x118A, 13 }, - { 0xD, 4 }, - { 0x10, 5 }, - { 0x9, 5 }, - { 0x14, 6 }, - { 0x47, 7 }, - { 0xF1, 8 }, - { 0x463, 11 }, - { 0x1F, 5 }, - { 0xC, 5 } + { 10, 3 }, { 9, 3 }, { 18, 5 }, { 25, 5 }, { 26, 6 }, { 19, 6 }, + { 1, 5 }, { 31, 5 }, { 17, 5 }, { 14, 4 }, { 24, 5 }, { 3, 6 }, + { 6, 10 }, { 8, 12 }, { 22, 13 }, { 21, 13 }, { 29, 11 }, { 5, 9 }, + { 20, 8 }, { 27, 7 }, { 12, 4 }, { 11, 4 }, { 13, 4 }, { 0, 4 }, + { 23, 4 }, { 15, 5 }, { 7, 5 }, { 4, 8 }, { 28, 8 }, { 2, 7 }, + { 16, 6 }, { 30, 5 }, }, { /* AC bias group 1, table 7 */ - { 0x0, 3 }, - { 0x1A, 5 }, - { 0x33, 6 }, - { 0xC, 5 }, - { 0x46, 7 }, - { 0x1E3, 9 }, - { 0x3C5, 10 }, - { 0x17, 5 }, - { 0x1E21, 13 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x9, 4 }, - { 0xA, 4 }, - { 0x7, 4 }, - { 0x1B, 5 }, - { 0x3D, 6 }, - { 0x1B, 6 }, - { 0x22, 6 }, - { 0x79, 7 }, - { 0xF0, 8 }, - { 0x1E20, 13 }, - { 0x1E23, 13 }, - { 0x1E22, 13 }, - { 0xE, 4 }, - { 0x16, 5 }, - { 0x18, 5 }, - { 0x32, 6 }, - { 0x1A, 6 }, - { 0x47, 7 }, - { 0x789, 11 }, - { 0x1F, 5 }, - { 0x10, 5 } + { 0, 3 }, { 10, 3 }, { 9, 3 }, { 3, 5 }, { 27, 6 }, { 16, 6 }, + { 13, 4 }, { 31, 5 }, { 17, 6 }, { 4, 7 }, { 28, 7 }, { 11, 4 }, + { 12, 4 }, { 24, 5 }, { 7, 5 }, { 25, 5 }, { 26, 6 }, { 2, 6 }, + { 1, 5 }, { 14, 5 }, { 23, 4 }, { 19, 8 }, { 20, 13 }, { 8, 13 }, + { 22, 13 }, { 21, 13 }, { 29, 11 }, { 6, 10 }, { 5, 9 }, { 18, 7 }, + { 15, 6 }, { 30, 5 }, }, { /* AC bias group 1, table 8 */ - { 0x1D, 5 }, - { 0x61, 7 }, - { 0x4E, 8 }, - { 0x9E, 9 }, - { 0x27C, 11 }, - { 0x9F5, 13 }, - { 0x9F4, 13 }, - { 0x3, 4 }, - { 0x60, 7 }, - { 0x0, 3 }, - { 0xF, 4 }, - { 0xB, 4 }, - { 0xA, 4 }, - { 0x9, 4 }, - { 0x5, 4 }, - { 0xD, 5 }, - { 0x31, 6 }, - { 0x8, 5 }, - { 0x38, 6 }, - { 0x12, 6 }, - { 0x26, 7 }, - { 0x13F, 10 }, - { 0x4FB, 12 }, - { 0xD, 4 }, - { 0x2, 4 }, - { 0xC, 5 }, - { 0x39, 6 }, - { 0x1C, 6 }, - { 0xF, 5 }, - { 0x1D, 6 }, - { 0x8, 4 }, - { 0x19, 5 } + { 9, 3 }, { 24, 4 }, { 7, 4 }, { 17, 5 }, { 19, 6 }, { 20, 7 }, + { 2, 8 }, { 3, 9 }, { 4, 11 }, { 6, 13 }, { 5, 13 }, { 22, 12 }, + { 21, 10 }, { 14, 4 }, { 25, 5 }, { 15, 5 }, { 27, 6 }, { 29, 6 }, + { 28, 5 }, { 30, 4 }, { 13, 4 }, { 12, 4 }, { 11, 4 }, { 8, 7 }, + { 1, 7 }, { 16, 6 }, { 31, 5 }, { 23, 4 }, { 18, 6 }, { 26, 6 }, + { 0, 5 }, { 10, 4 }, }, { /* AC bias group 1, table 9 */ - { 0x7, 4 }, - { 0x19, 6 }, - { 0xAB, 8 }, - { 0xAA, 8 }, - { 0x119, 10 }, - { 0x461, 12 }, - { 0x460, 12 }, - { 0x1B, 5 }, - { 0x47, 8 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xC, 4 }, - { 0xB, 4 }, - { 0x9, 4 }, - { 0x5, 4 }, - { 0xD, 5 }, - { 0x35, 6 }, - { 0x3D, 6 }, - { 0x3C, 6 }, - { 0x18, 6 }, - { 0x22, 7 }, - { 0x8D, 9 }, - { 0x231, 11 }, - { 0xE, 4 }, - { 0x1F, 5 }, - { 0x9, 5 }, - { 0x2B, 6 }, - { 0x10, 6 }, - { 0x34, 6 }, - { 0x54, 7 }, - { 0x8, 4 }, - { 0x14, 5 } + { 10, 3 }, { 9, 3 }, { 27, 6 }, { 20, 7 }, { 6, 12 }, { 5, 12 }, + { 22, 11 }, { 4, 10 }, { 21, 9 }, { 8, 8 }, { 25, 5 }, { 14, 4 }, + { 19, 6 }, { 1, 6 }, { 15, 5 }, { 0, 4 }, { 30, 4 }, { 13, 4 }, + { 31, 5 }, { 29, 7 }, { 3, 8 }, { 2, 8 }, { 26, 6 }, { 12, 4 }, + { 11, 4 }, { 28, 6 }, { 16, 6 }, { 7, 5 }, { 23, 4 }, { 18, 6 }, + { 17, 6 }, { 24, 5 }, }, { /* AC bias group 1, table 10 */ - { 0xC, 4 }, - { 0x5, 5 }, - { 0x8, 6 }, - { 0x5B, 7 }, - { 0x4D, 9 }, - { 0x131, 11 }, - { 0x261, 12 }, - { 0x1A, 5 }, - { 0x12, 7 }, - { 0x0, 3 }, - { 0xF, 4 }, - { 0xA, 4 }, - { 0x9, 4 }, - { 0x6, 4 }, - { 0x1B, 5 }, - { 0x6, 5 }, - { 0x1C, 6 }, - { 0x2C, 6 }, - { 0x15, 6 }, - { 0x5A, 7 }, - { 0x27, 8 }, - { 0x99, 10 }, - { 0x260, 12 }, - { 0xE, 4 }, - { 0x4, 4 }, - { 0xF, 5 }, - { 0x7, 5 }, - { 0x1D, 6 }, - { 0xB, 5 }, - { 0x14, 6 }, - { 0x8, 4 }, - { 0x17, 5 } + { 9, 3 }, { 2, 6 }, { 8, 7 }, { 22, 12 }, { 6, 12 }, { 5, 11 }, + { 21, 10 }, { 4, 9 }, { 20, 8 }, { 1, 5 }, { 15, 5 }, { 26, 5 }, + { 24, 4 }, { 29, 6 }, { 18, 6 }, { 28, 5 }, { 13, 4 }, { 16, 6 }, + { 27, 6 }, { 25, 5 }, { 30, 4 }, { 12, 4 }, { 11, 4 }, { 17, 6 }, + { 19, 7 }, { 3, 7 }, { 31, 5 }, { 0, 4 }, { 7, 5 }, { 14, 5 }, + { 23, 4 }, { 10, 4 }, }, { /* AC bias group 1, table 11 */ - { 0xF, 4 }, - { 0x13, 5 }, - { 0x75, 7 }, - { 0x24, 6 }, - { 0x95, 8 }, - { 0x251, 10 }, - { 0x4A0, 11 }, - { 0x10, 5 }, - { 0xC8, 8 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x1, 4 }, - { 0x0, 4 }, - { 0x1A, 5 }, - { 0x11, 5 }, - { 0x2C, 6 }, - { 0x65, 7 }, - { 0x74, 7 }, - { 0x4B, 7 }, - { 0xC9, 8 }, - { 0x129, 9 }, - { 0x943, 12 }, - { 0x942, 12 }, - { 0x3, 3 }, - { 0xA, 4 }, - { 0x1C, 5 }, - { 0x18, 5 }, - { 0x33, 6 }, - { 0x17, 5 }, - { 0x2D, 6 }, - { 0x1B, 5 }, - { 0x3B, 6 } + { 12, 4 }, { 11, 4 }, { 10, 3 }, { 9, 3 }, { 23, 3 }, { 7, 5 }, + { 14, 5 }, { 3, 6 }, { 6, 11 }, { 22, 12 }, { 21, 12 }, { 5, 10 }, + { 20, 9 }, { 4, 8 }, { 18, 7 }, { 1, 5 }, { 24, 4 }, { 15, 6 }, + { 29, 6 }, { 28, 5 }, { 26, 5 }, { 8, 8 }, { 19, 8 }, { 16, 7 }, + { 27, 6 }, { 13, 5 }, { 30, 5 }, { 25, 5 }, { 17, 7 }, { 2, 7 }, + { 31, 6 }, { 0, 4 }, }, { /* AC bias group 1, table 12 */ - { 0x3, 3 }, - { 0x1A, 5 }, - { 0x2D, 6 }, - { 0x38, 6 }, - { 0x28, 7 }, - { 0x395, 10 }, - { 0xE51, 12 }, - { 0x37, 6 }, - { 0xE4, 8 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0x1F, 5 }, - { 0x1E, 5 }, - { 0x17, 5 }, - { 0x3A, 6 }, - { 0x73, 7 }, - { 0x2A, 7 }, - { 0x2B, 7 }, - { 0x29, 7 }, - { 0x1CB, 9 }, - { 0x729, 11 }, - { 0x1CA1, 13 }, - { 0x1CA0, 13 }, - { 0x4, 3 }, - { 0xA, 4 }, - { 0x4, 4 }, - { 0x18, 5 }, - { 0x36, 6 }, - { 0xB, 5 }, - { 0x2C, 6 }, - { 0x19, 5 }, - { 0x3B, 6 } + { 10, 3 }, { 9, 3 }, { 25, 4 }, { 4, 7 }, { 18, 7 }, { 16, 7 }, + { 17, 7 }, { 28, 5 }, { 0, 3 }, { 23, 3 }, { 24, 4 }, { 29, 6 }, + { 2, 6 }, { 13, 5 }, { 26, 5 }, { 30, 5 }, { 1, 5 }, { 27, 6 }, + { 7, 6 }, { 3, 6 }, { 8, 8 }, { 22, 13 }, { 21, 13 }, { 6, 12 }, + { 20, 11 }, { 5, 10 }, { 19, 9 }, { 15, 7 }, { 14, 6 }, { 31, 6 }, + { 12, 5 }, { 11, 5 }, }, { /* AC bias group 1, table 13 */ - { 0x4, 3 }, - { 0x4, 4 }, - { 0x3F, 6 }, - { 0x17, 5 }, - { 0x75, 7 }, - { 0x1F5, 9 }, - { 0x7D1, 11 }, - { 0x17, 6 }, - { 0x1F6, 9 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0x1B, 5 }, - { 0x1A, 5 }, - { 0xA, 5 }, - { 0x32, 6 }, - { 0x74, 7 }, - { 0xF8, 8 }, - { 0xF9, 8 }, - { 0x1F7, 9 }, - { 0x3E9, 10 }, - { 0xFA0, 12 }, - { 0x1F43, 13 }, - { 0x1F42, 13 }, - { 0x3, 3 }, - { 0xA, 4 }, - { 0x1E, 5 }, - { 0x1C, 5 }, - { 0x3B, 6 }, - { 0x18, 5 }, - { 0x16, 6 }, - { 0x16, 5 }, - { 0x33, 6 } + { 10, 3 }, { 9, 3 }, { 1, 4 }, { 13, 5 }, { 29, 6 }, { 7, 6 }, + { 23, 3 }, { 0, 3 }, { 24, 4 }, { 30, 5 }, { 3, 5 }, { 28, 5 }, + { 14, 6 }, { 31, 6 }, { 12, 5 }, { 11, 5 }, { 26, 5 }, { 15, 7 }, + { 4, 7 }, { 27, 6 }, { 25, 5 }, { 16, 8 }, { 17, 8 }, { 20, 12 }, + { 22, 13 }, { 21, 13 }, { 6, 11 }, { 19, 10 }, { 5, 9 }, { 8, 9 }, + { 18, 9 }, { 2, 6 }, }, { /* AC bias group 1, table 14 */ - { 0x4, 3 }, - { 0x7, 4 }, - { 0x18, 5 }, - { 0x1E, 5 }, - { 0x36, 6 }, - { 0x31, 7 }, - { 0x177, 9 }, - { 0x77, 7 }, - { 0x176, 9 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0x1A, 5 }, - { 0x19, 5 }, - { 0x3A, 6 }, - { 0x19, 6 }, - { 0x5C, 7 }, - { 0xBA, 8 }, - { 0x61, 8 }, - { 0xC1, 9 }, - { 0x180, 10 }, - { 0x302, 11 }, - { 0x607, 12 }, - { 0x606, 12 }, - { 0x2, 3 }, - { 0xA, 4 }, - { 0x1F, 5 }, - { 0x1C, 5 }, - { 0x37, 6 }, - { 0x16, 5 }, - { 0x76, 7 }, - { 0xD, 5 }, - { 0x2F, 6 } + { 10, 3 }, { 9, 3 }, { 23, 3 }, { 19, 10 }, { 20, 11 }, { 22, 12 }, + { 21, 12 }, { 18, 9 }, { 17, 8 }, { 5, 7 }, { 14, 6 }, { 30, 5 }, + { 1, 4 }, { 0, 3 }, { 24, 4 }, { 28, 5 }, { 15, 7 }, { 16, 8 }, + { 8, 9 }, { 6, 9 }, { 31, 6 }, { 2, 5 }, { 12, 5 }, { 11, 5 }, + { 4, 6 }, { 27, 6 }, { 26, 5 }, { 13, 6 }, { 29, 7 }, { 7, 7 }, + { 3, 5 }, { 25, 5 }, }, { /* AC bias group 1, table 15 */ - { 0x0, 3 }, - { 0xA, 4 }, - { 0x1A, 5 }, - { 0xC, 4 }, - { 0x1D, 5 }, - { 0x39, 6 }, - { 0x78, 7 }, - { 0x5E, 7 }, - { 0x393, 11 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x16, 5 }, - { 0xF, 5 }, - { 0x2E, 6 }, - { 0x5F, 7 }, - { 0x73, 8 }, - { 0xE5, 9 }, - { 0x1C8, 10 }, - { 0xE4A, 13 }, - { 0x1C97, 14 }, - { 0x1C96, 14 }, - { 0xE49, 13 }, - { 0xE48, 13 }, - { 0x4, 3 }, - { 0x6, 4 }, - { 0x1F, 5 }, - { 0x1B, 5 }, - { 0x1D, 6 }, - { 0x38, 6 }, - { 0x38, 7 }, - { 0x3D, 6 }, - { 0x79, 7 } - } -}; - -static const uint16_t ac_bias_1[16][32][2] = { + { 0, 3 }, { 10, 3 }, { 9, 3 }, { 24, 4 }, { 29, 7 }, { 17, 10 }, + { 22, 13 }, { 21, 13 }, { 18, 13 }, { 20, 14 }, { 19, 14 }, { 8, 11 }, + { 16, 9 }, { 15, 8 }, { 27, 6 }, { 12, 5 }, { 23, 3 }, { 1, 4 }, + { 11, 5 }, { 13, 6 }, { 7, 7 }, { 14, 7 }, { 3, 4 }, { 2, 5 }, + { 26, 5 }, { 28, 6 }, { 5, 6 }, { 4, 5 }, { 6, 7 }, { 31, 7 }, + { 30, 6 }, { 25, 5 }, + }, { /* AC bias group 2, table 0 */ - { 0xB, 5 }, - { 0x2B, 7 }, - { 0x54, 8 }, - { 0x1B7, 9 }, - { 0x6D9, 11 }, - { 0xDB1, 12 }, - { 0xDB0, 12 }, - { 0x2, 4 }, - { 0xAB, 9 }, - { 0x9, 4 }, - { 0xA, 4 }, - { 0x7, 4 }, - { 0x8, 4 }, - { 0xF, 4 }, - { 0xC, 4 }, - { 0x3, 4 }, - { 0x1D, 5 }, - { 0x4, 4 }, - { 0xB, 4 }, - { 0x6, 4 }, - { 0x1A, 5 }, - { 0x3, 6 }, - { 0xAA, 9 }, - { 0x1, 4 }, - { 0x0, 5 }, - { 0x14, 6 }, - { 0x6C, 7 }, - { 0xDA, 8 }, - { 0x2, 6 }, - { 0x36D, 10 }, - { 0x1C, 5 }, - { 0x37, 6 } + { 24, 5 }, { 28, 6 }, { 21, 6 }, { 23, 4 }, { 7, 4 }, { 15, 4 }, + { 17, 4 }, { 25, 6 }, { 2, 8 }, { 22, 9 }, { 8, 9 }, { 1, 7 }, + { 0, 5 }, { 19, 4 }, { 11, 4 }, { 12, 4 }, { 9, 4 }, { 10, 4 }, + { 18, 4 }, { 14, 4 }, { 20, 5 }, { 26, 7 }, { 27, 8 }, { 6, 12 }, + { 5, 12 }, { 4, 11 }, { 29, 10 }, { 3, 9 }, { 31, 6 }, { 30, 5 }, + { 16, 5 }, { 13, 4 }, }, { /* AC bias group 2, table 1 */ - { 0x1D, 5 }, - { 0x4, 6 }, - { 0xB6, 8 }, - { 0x6A, 8 }, - { 0x5B9, 11 }, - { 0x16E1, 13 }, - { 0x16E0, 13 }, - { 0x7, 4 }, - { 0x16F, 9 }, - { 0xC, 4 }, - { 0xD, 4 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0xF, 4 }, - { 0xA, 4 }, - { 0x3, 4 }, - { 0x17, 5 }, - { 0x2, 4 }, - { 0x4, 4 }, - { 0x1C, 5 }, - { 0x2C, 6 }, - { 0x6B, 8 }, - { 0xB71, 12 }, - { 0x5, 4 }, - { 0x3, 5 }, - { 0x1B, 6 }, - { 0x5A, 7 }, - { 0x34, 7 }, - { 0x5, 6 }, - { 0x2DD, 10 }, - { 0x0, 4 }, - { 0xC, 5 } + { 30, 4 }, { 1, 6 }, { 28, 6 }, { 24, 5 }, { 17, 4 }, { 15, 4 }, + { 18, 4 }, { 23, 4 }, { 31, 5 }, { 27, 7 }, { 3, 8 }, { 21, 8 }, + { 25, 6 }, { 7, 4 }, { 12, 4 }, { 11, 4 }, { 14, 4 }, { 20, 6 }, + { 26, 7 }, { 2, 8 }, { 6, 13 }, { 5, 13 }, { 22, 12 }, { 4, 11 }, + { 29, 10 }, { 8, 9 }, { 16, 5 }, { 9, 4 }, { 10, 4 }, { 19, 5 }, + { 0, 5 }, { 13, 4 }, }, { /* AC bias group 2, table 2 */ - { 0x3, 4 }, - { 0x7F, 7 }, - { 0xA1, 8 }, - { 0xA0, 8 }, - { 0x20C, 10 }, - { 0x834, 12 }, - { 0x106B, 13 }, - { 0x7, 4 }, - { 0x82, 8 }, - { 0xE, 4 }, - { 0xD, 4 }, - { 0xB, 4 }, - { 0xC, 4 }, - { 0x0, 3 }, - { 0x9, 4 }, - { 0x2, 4 }, - { 0x11, 5 }, - { 0x1E, 5 }, - { 0x15, 5 }, - { 0x3E, 6 }, - { 0x40, 7 }, - { 0x41B, 11 }, - { 0x106A, 13 }, - { 0x6, 4 }, - { 0xA, 5 }, - { 0x29, 6 }, - { 0x7E, 7 }, - { 0x51, 7 }, - { 0x21, 6 }, - { 0x107, 9 }, - { 0x4, 4 }, - { 0xB, 5 } + { 13, 3 }, { 15, 4 }, { 0, 4 }, { 30, 4 }, { 24, 5 }, { 31, 5 }, + { 23, 4 }, { 7, 4 }, { 20, 7 }, { 8, 8 }, { 4, 10 }, { 5, 12 }, + { 22, 13 }, { 6, 13 }, { 21, 11 }, { 29, 9 }, { 28, 6 }, { 16, 5 }, + { 14, 4 }, { 3, 8 }, { 2, 8 }, { 27, 7 }, { 25, 6 }, { 18, 5 }, + { 11, 4 }, { 12, 4 }, { 10, 4 }, { 9, 4 }, { 17, 5 }, { 19, 6 }, + { 26, 7 }, { 1, 7 }, }, { /* AC bias group 2, table 3 */ - { 0x7, 4 }, - { 0x1B, 6 }, - { 0xF6, 8 }, - { 0xE9, 8 }, - { 0x3A1, 10 }, - { 0x740, 11 }, - { 0xE82, 12 }, - { 0x1F, 5 }, - { 0x1EF, 9 }, - { 0x1, 3 }, - { 0x2, 3 }, - { 0xB, 4 }, - { 0xC, 4 }, - { 0xD, 4 }, - { 0x8, 4 }, - { 0x1C, 5 }, - { 0x3, 5 }, - { 0x12, 5 }, - { 0x2, 5 }, - { 0x75, 7 }, - { 0x1D1, 9 }, - { 0x1D07, 13 }, - { 0x1D06, 13 }, - { 0xA, 4 }, - { 0x13, 5 }, - { 0x3B, 6 }, - { 0x1A, 6 }, - { 0x7A, 7 }, - { 0x3C, 6 }, - { 0x1EE, 9 }, - { 0x0, 4 }, - { 0xC, 5 } + { 30, 4 }, { 18, 5 }, { 16, 5 }, { 9, 3 }, { 10, 3 }, { 31, 5 }, + { 26, 6 }, { 1, 6 }, { 0, 4 }, { 14, 4 }, { 17, 5 }, { 24, 5 }, + { 23, 4 }, { 11, 4 }, { 12, 4 }, { 13, 4 }, { 15, 5 }, { 5, 11 }, + { 6, 12 }, { 22, 13 }, { 21, 13 }, { 4, 10 }, { 20, 9 }, { 3, 8 }, + { 19, 7 }, { 25, 6 }, { 28, 6 }, { 27, 7 }, { 2, 8 }, { 29, 9 }, + { 8, 9 }, { 7, 5 }, }, { /* AC bias group 2, table 4 */ - { 0xD, 4 }, - { 0x3D, 6 }, - { 0x42, 7 }, - { 0x37, 7 }, - { 0xD9, 9 }, - { 0x362, 11 }, - { 0x6C6, 12 }, - { 0x1F, 5 }, - { 0x86, 8 }, - { 0x1, 3 }, - { 0x2, 3 }, - { 0xC, 4 }, - { 0xB, 4 }, - { 0xA, 4 }, - { 0x1, 4 }, - { 0xF, 5 }, - { 0x25, 6 }, - { 0x3C, 6 }, - { 0x1A, 6 }, - { 0x87, 8 }, - { 0x1B0, 10 }, - { 0xD8F, 13 }, - { 0xD8E, 13 }, - { 0xE, 4 }, - { 0x13, 5 }, - { 0xC, 5 }, - { 0x24, 6 }, - { 0x20, 6 }, - { 0x11, 5 }, - { 0x6D, 8 }, - { 0x0, 4 }, - { 0xE, 5 } + { 30, 4 }, { 14, 4 }, { 9, 3 }, { 10, 3 }, { 25, 5 }, { 18, 6 }, + { 20, 10 }, { 5, 11 }, { 6, 12 }, { 22, 13 }, { 21, 13 }, { 4, 9 }, + { 29, 8 }, { 3, 7 }, { 31, 5 }, { 15, 5 }, { 27, 6 }, { 2, 7 }, + { 8, 8 }, { 19, 8 }, { 28, 5 }, { 26, 6 }, { 16, 6 }, { 24, 5 }, + { 13, 4 }, { 12, 4 }, { 11, 4 }, { 0, 4 }, { 23, 4 }, { 17, 6 }, + { 1, 6 }, { 7, 5 }, }, { /* AC bias group 2, table 5 */ - { 0x0, 3 }, - { 0x12, 5 }, - { 0x76, 7 }, - { 0x77, 7 }, - { 0x14D, 9 }, - { 0x533, 11 }, - { 0x14C9, 13 }, - { 0x13, 5 }, - { 0xA5, 8 }, - { 0x2, 3 }, - { 0x3, 3 }, - { 0xB, 4 }, - { 0xC, 4 }, - { 0x8, 4 }, - { 0x1A, 5 }, - { 0x2B, 6 }, - { 0x75, 7 }, - { 0x74, 7 }, - { 0xA7, 8 }, - { 0x298, 10 }, - { 0x14C8, 13 }, - { 0x14CB, 13 }, - { 0x14CA, 13 }, - { 0xF, 4 }, - { 0x1C, 5 }, - { 0x7, 5 }, - { 0x2A, 6 }, - { 0x28, 6 }, - { 0x1B, 5 }, - { 0xA4, 8 }, - { 0x2, 4 }, - { 0x6, 5 } + { 0, 3 }, { 30, 4 }, { 31, 5 }, { 25, 5 }, { 9, 3 }, { 10, 3 }, + { 13, 4 }, { 1, 5 }, { 7, 5 }, { 27, 6 }, { 29, 8 }, { 8, 8 }, + { 19, 10 }, { 20, 13 }, { 6, 13 }, { 22, 13 }, { 21, 13 }, { 5, 11 }, + { 4, 9 }, { 18, 8 }, { 26, 6 }, { 15, 6 }, { 11, 4 }, { 12, 4 }, + { 14, 5 }, { 28, 5 }, { 24, 5 }, { 17, 7 }, { 16, 7 }, { 2, 7 }, + { 3, 7 }, { 23, 4 }, }, { /* AC bias group 2, table 6 */ - { 0x2, 3 }, - { 0x1A, 5 }, - { 0x2B, 6 }, - { 0x3A, 6 }, - { 0xED, 8 }, - { 0x283, 10 }, - { 0xA0A, 12 }, - { 0x4, 5 }, - { 0xA1, 8 }, - { 0x4, 3 }, - { 0x3, 3 }, - { 0xB, 4 }, - { 0xC, 4 }, - { 0x1F, 5 }, - { 0x6, 5 }, - { 0x77, 7 }, - { 0xA3, 8 }, - { 0xA2, 8 }, - { 0x140, 9 }, - { 0x1417, 13 }, - { 0x1416, 13 }, - { 0xA09, 12 }, - { 0xA08, 12 }, - { 0x0, 3 }, - { 0x1E, 5 }, - { 0x7, 5 }, - { 0x2A, 6 }, - { 0x29, 6 }, - { 0x1C, 5 }, - { 0xEC, 8 }, - { 0x1B, 5 }, - { 0x5, 5 } + { 23, 3 }, { 7, 5 }, { 31, 5 }, { 14, 5 }, { 25, 5 }, { 0, 3 }, + { 10, 3 }, { 9, 3 }, { 18, 9 }, { 22, 12 }, { 21, 12 }, { 6, 12 }, + { 20, 13 }, { 19, 13 }, { 5, 10 }, { 8, 8 }, { 17, 8 }, { 16, 8 }, + { 27, 6 }, { 26, 6 }, { 2, 6 }, { 11, 4 }, { 12, 4 }, { 1, 5 }, + { 30, 5 }, { 28, 5 }, { 3, 6 }, { 29, 8 }, { 4, 8 }, { 15, 7 }, + { 24, 5 }, { 13, 5 }, }, { /* AC bias group 2, table 7 */ - { 0x2, 3 }, - { 0x2, 4 }, - { 0x18, 5 }, - { 0x1D, 5 }, - { 0x35, 6 }, - { 0xE4, 8 }, - { 0x1CF, 11 }, - { 0x1D, 7 }, - { 0x72, 9 }, - { 0x4, 3 }, - { 0x5, 3 }, - { 0x6, 4 }, - { 0x7, 4 }, - { 0x6, 5 }, - { 0x73, 7 }, - { 0x38, 8 }, - { 0x1CE, 11 }, - { 0x39B, 12 }, - { 0x398, 12 }, - { 0x733, 13 }, - { 0x732, 13 }, - { 0x735, 13 }, - { 0x734, 13 }, - { 0x0, 3 }, - { 0x1F, 5 }, - { 0x1B, 5 }, - { 0x34, 6 }, - { 0xF, 6 }, - { 0x1E, 5 }, - { 0xE5, 8 }, - { 0x19, 5 }, - { 0x38, 6 } + { 23, 3 }, { 1, 4 }, { 13, 5 }, { 15, 8 }, { 8, 9 }, { 18, 12 }, + { 20, 13 }, { 19, 13 }, { 22, 13 }, { 21, 13 }, { 17, 12 }, { 16, 11 }, + { 6, 11 }, { 7, 7 }, { 27, 6 }, { 0, 3 }, { 11, 4 }, { 12, 4 }, + { 9, 3 }, { 10, 3 }, { 2, 5 }, { 30, 5 }, { 26, 6 }, { 4, 6 }, + { 25, 5 }, { 31, 6 }, { 5, 8 }, { 29, 8 }, { 14, 7 }, { 3, 5 }, + { 28, 5 }, { 24, 5 }, }, { /* AC bias group 2, table 8 */ - { 0x16, 5 }, - { 0x50, 7 }, - { 0x172, 9 }, - { 0x2E7, 10 }, - { 0x1732, 13 }, - { 0x2E67, 14 }, - { 0x2E66, 14 }, - { 0x6, 4 }, - { 0x51, 7 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xD, 4 }, - { 0xC, 4 }, - { 0x9, 4 }, - { 0x1C, 5 }, - { 0x9, 5 }, - { 0x1C, 6 }, - { 0x1D, 6 }, - { 0x5D, 7 }, - { 0xB8, 8 }, - { 0x5CD, 11 }, - { 0x1731, 13 }, - { 0x1730, 13 }, - { 0xF, 4 }, - { 0x5, 4 }, - { 0xF, 5 }, - { 0x8, 5 }, - { 0x29, 6 }, - { 0x1D, 5 }, - { 0x2F, 6 }, - { 0x8, 4 }, - { 0x15, 5 } + { 10, 3 }, { 9, 3 }, { 26, 5 }, { 15, 5 }, { 24, 4 }, { 7, 4 }, + { 16, 6 }, { 17, 6 }, { 25, 5 }, { 30, 4 }, { 13, 4 }, { 1, 7 }, + { 8, 7 }, { 27, 6 }, { 31, 5 }, { 0, 5 }, { 19, 8 }, { 2, 9 }, + { 22, 13 }, { 21, 13 }, { 4, 13 }, { 6, 14 }, { 5, 14 }, { 20, 11 }, + { 3, 10 }, { 18, 7 }, { 29, 6 }, { 12, 4 }, { 11, 4 }, { 14, 5 }, + { 28, 5 }, { 23, 4 }, }, { /* AC bias group 2, table 9 */ - { 0x9, 4 }, - { 0x21, 6 }, - { 0x40, 7 }, - { 0xAD, 8 }, - { 0x2B0, 10 }, - { 0x1589, 13 }, - { 0x1588, 13 }, - { 0x1C, 5 }, - { 0x5F, 7 }, - { 0x0, 3 }, - { 0xF, 4 }, - { 0xD, 4 }, - { 0xC, 4 }, - { 0x6, 4 }, - { 0x11, 5 }, - { 0x2A, 6 }, - { 0x57, 7 }, - { 0x5E, 7 }, - { 0x41, 7 }, - { 0x159, 9 }, - { 0x563, 11 }, - { 0x158B, 13 }, - { 0x158A, 13 }, - { 0x1, 3 }, - { 0x5, 4 }, - { 0x14, 5 }, - { 0x3B, 6 }, - { 0x2E, 6 }, - { 0x4, 4 }, - { 0x3A, 6 }, - { 0x7, 4 }, - { 0x16, 5 } + { 9, 3 }, { 23, 3 }, { 28, 4 }, { 24, 4 }, { 13, 4 }, { 30, 4 }, + { 2, 7 }, { 18, 7 }, { 1, 6 }, { 14, 5 }, { 0, 4 }, { 25, 5 }, + { 15, 6 }, { 4, 10 }, { 6, 13 }, { 5, 13 }, { 22, 13 }, { 21, 13 }, + { 20, 11 }, { 19, 9 }, { 3, 8 }, { 16, 7 }, { 31, 5 }, { 27, 6 }, + { 17, 7 }, { 8, 7 }, { 12, 4 }, { 11, 4 }, { 7, 5 }, { 29, 6 }, + { 26, 6 }, { 10, 4 }, }, { /* AC bias group 2, table 10 */ - { 0xE, 4 }, - { 0x7, 5 }, - { 0x46, 7 }, - { 0x45, 7 }, - { 0x64, 9 }, - { 0x32A, 12 }, - { 0x657, 13 }, - { 0x18, 5 }, - { 0xD, 6 }, - { 0x0, 3 }, - { 0xF, 4 }, - { 0xA, 4 }, - { 0xB, 4 }, - { 0x1A, 5 }, - { 0x36, 6 }, - { 0x47, 7 }, - { 0x44, 7 }, - { 0x18, 7 }, - { 0x33, 8 }, - { 0xCB, 10 }, - { 0x656, 13 }, - { 0x329, 12 }, - { 0x328, 12 }, - { 0x2, 3 }, - { 0x6, 4 }, - { 0x19, 5 }, - { 0xE, 5 }, - { 0x37, 6 }, - { 0x9, 4 }, - { 0xF, 5 }, - { 0x2, 4 }, - { 0x10, 5 } + { 9, 3 }, { 30, 4 }, { 17, 7 }, { 4, 9 }, { 22, 12 }, { 21, 12 }, + { 5, 12 }, { 20, 13 }, { 6, 13 }, { 19, 10 }, { 18, 8 }, { 8, 6 }, + { 1, 5 }, { 23, 3 }, { 24, 4 }, { 26, 5 }, { 29, 5 }, { 31, 5 }, + { 16, 7 }, { 3, 7 }, { 2, 7 }, { 15, 7 }, { 28, 4 }, { 11, 4 }, + { 12, 4 }, { 7, 5 }, { 25, 5 }, { 13, 5 }, { 14, 6 }, { 27, 6 }, + { 0, 4 }, { 10, 4 }, }, { /* AC bias group 2, table 11 */ - { 0x3, 3 }, - { 0x18, 5 }, - { 0x23, 6 }, - { 0x77, 7 }, - { 0x194, 9 }, - { 0x1956, 13 }, - { 0x32AF, 14 }, - { 0x3A, 6 }, - { 0x76, 7 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x1F, 5 }, - { 0x1E, 5 }, - { 0x14, 5 }, - { 0x22, 6 }, - { 0x64, 7 }, - { 0x197, 9 }, - { 0x196, 9 }, - { 0x32B, 10 }, - { 0x654, 11 }, - { 0x32AE, 14 }, - { 0x1955, 13 }, - { 0x1954, 13 }, - { 0x0, 3 }, - { 0x9, 4 }, - { 0x1C, 5 }, - { 0x15, 5 }, - { 0x10, 5 }, - { 0xD, 4 }, - { 0x17, 5 }, - { 0x16, 5 }, - { 0x33, 6 } + { 23, 3 }, { 10, 3 }, { 9, 3 }, { 0, 3 }, { 27, 5 }, { 14, 6 }, + { 2, 6 }, { 24, 4 }, { 13, 5 }, { 26, 5 }, { 30, 5 }, { 29, 5 }, + { 1, 5 }, { 15, 7 }, { 4, 9 }, { 19, 11 }, { 22, 13 }, { 21, 13 }, + { 5, 13 }, { 20, 14 }, { 6, 14 }, { 18, 10 }, { 17, 9 }, { 16, 9 }, + { 31, 6 }, { 28, 4 }, { 25, 5 }, { 7, 6 }, { 8, 7 }, { 3, 7 }, + { 12, 5 }, { 11, 5 }, }, { /* AC bias group 2, table 12 */ - { 0x5, 3 }, - { 0x6, 4 }, - { 0x3E, 6 }, - { 0x10, 5 }, - { 0x48, 7 }, - { 0x93F, 12 }, - { 0x24FA, 14 }, - { 0x32, 6 }, - { 0x67, 7 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x1B, 5 }, - { 0x1E, 5 }, - { 0x34, 6 }, - { 0x66, 7 }, - { 0x92, 8 }, - { 0x126, 9 }, - { 0x24E, 10 }, - { 0x49E, 11 }, - { 0x49F7, 15 }, - { 0x49F6, 15 }, - { 0x24F9, 14 }, - { 0x24F8, 14 }, - { 0x0, 3 }, - { 0x7, 4 }, - { 0x18, 5 }, - { 0x11, 5 }, - { 0x3F, 6 }, - { 0xE, 4 }, - { 0x13, 5 }, - { 0x35, 6 }, - { 0x25, 6 } + { 23, 3 }, { 10, 3 }, { 9, 3 }, { 1, 4 }, { 24, 4 }, { 3, 5 }, + { 26, 5 }, { 4, 7 }, { 15, 8 }, { 16, 9 }, { 17, 10 }, { 18, 11 }, + { 22, 14 }, { 21, 14 }, { 6, 14 }, { 20, 15 }, { 19, 15 }, { 5, 12 }, + { 31, 6 }, { 29, 5 }, { 0, 3 }, { 25, 5 }, { 7, 6 }, { 14, 7 }, + { 8, 7 }, { 13, 6 }, { 30, 6 }, { 11, 5 }, { 28, 4 }, { 12, 5 }, + { 2, 6 }, { 27, 6 }, }, { /* AC bias group 2, table 13 */ - { 0x5, 3 }, - { 0x8, 4 }, - { 0x12, 5 }, - { 0x1C, 5 }, - { 0x1C, 6 }, - { 0xEA, 9 }, - { 0x1D75, 14 }, - { 0x1E, 6 }, - { 0x66, 7 }, - { 0x1, 3 }, - { 0x2, 3 }, - { 0x1B, 5 }, - { 0x1A, 5 }, - { 0x1F, 6 }, - { 0x3B, 7 }, - { 0x74, 8 }, - { 0x1D6, 10 }, - { 0x3AF, 11 }, - { 0x1D74, 14 }, - { 0x1D77, 14 }, - { 0x1D76, 14 }, - { 0xEB9, 13 }, - { 0xEB8, 13 }, - { 0xF, 4 }, - { 0x6, 4 }, - { 0x13, 5 }, - { 0x3B, 6 }, - { 0x3A, 6 }, - { 0x0, 3 }, - { 0x18, 5 }, - { 0x32, 6 }, - { 0x67, 7 } + { 28, 3 }, { 9, 3 }, { 10, 3 }, { 24, 4 }, { 4, 6 }, { 15, 8 }, + { 5, 9 }, { 16, 10 }, { 22, 13 }, { 21, 13 }, { 18, 14 }, { 6, 14 }, + { 20, 14 }, { 19, 14 }, { 17, 11 }, { 14, 7 }, { 7, 6 }, { 13, 6 }, + { 1, 4 }, { 2, 5 }, { 25, 5 }, { 0, 3 }, { 29, 5 }, { 30, 6 }, + { 8, 7 }, { 31, 7 }, { 12, 5 }, { 11, 5 }, { 3, 5 }, { 27, 6 }, + { 26, 6 }, { 23, 4 }, }, { /* AC bias group 2, table 14 */ - { 0x4, 3 }, - { 0xA, 4 }, - { 0x1B, 5 }, - { 0xC, 4 }, - { 0xD, 5 }, - { 0xE6, 8 }, - { 0x684, 11 }, - { 0x72, 7 }, - { 0xE7, 8 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x17, 5 }, - { 0x16, 5 }, - { 0x18, 6 }, - { 0xD1, 8 }, - { 0x1A0, 9 }, - { 0x686, 11 }, - { 0xD0F, 12 }, - { 0xD0A, 12 }, - { 0x1A17, 13 }, - { 0x1A16, 13 }, - { 0x1A1D, 13 }, - { 0x1A1C, 13 }, - { 0xF, 4 }, - { 0x1D, 5 }, - { 0xE, 5 }, - { 0x35, 6 }, - { 0x38, 6 }, - { 0x0, 3 }, - { 0xF, 5 }, - { 0x19, 6 }, - { 0x69, 7 } + { 28, 3 }, { 10, 3 }, { 9, 3 }, { 13, 6 }, { 30, 6 }, { 4, 5 }, + { 25, 5 }, { 29, 5 }, { 0, 3 }, { 1, 4 }, { 12, 5 }, { 11, 5 }, + { 3, 4 }, { 15, 9 }, { 6, 11 }, { 18, 12 }, { 20, 13 }, { 19, 13 }, + { 16, 11 }, { 22, 13 }, { 21, 13 }, { 17, 12 }, { 14, 8 }, { 31, 7 }, + { 26, 6 }, { 2, 5 }, { 27, 6 }, { 7, 7 }, { 5, 8 }, { 8, 8 }, + { 24, 5 }, { 23, 4 }, }, { /* AC bias group 2, table 15 */ - { 0x3, 3 }, - { 0xC, 4 }, - { 0x1B, 5 }, - { 0x0, 3 }, - { 0x3, 4 }, - { 0x2E, 6 }, - { 0x51, 9 }, - { 0xBC, 8 }, - { 0x53, 9 }, - { 0x4, 3 }, - { 0x2, 3 }, - { 0x16, 5 }, - { 0x15, 5 }, - { 0x15, 7 }, - { 0x50, 9 }, - { 0xA4, 10 }, - { 0x294, 12 }, - { 0x52B, 13 }, - { 0x52A, 13 }, - { 0x52D, 13 }, - { 0x52C, 13 }, - { 0x52F, 13 }, - { 0x52E, 13 }, - { 0xE, 4 }, - { 0x1A, 5 }, - { 0x4, 5 }, - { 0x28, 6 }, - { 0x29, 6 }, - { 0xF, 4 }, - { 0xB, 6 }, - { 0x5F, 7 }, - { 0xBD, 8 } - } -}; - -static const uint16_t ac_bias_2[16][32][2] = { + { 3, 3 }, { 25, 5 }, { 14, 9 }, { 6, 9 }, { 15, 10 }, { 16, 12 }, + { 18, 13 }, { 17, 13 }, { 20, 13 }, { 19, 13 }, { 22, 13 }, { 21, 13 }, + { 8, 9 }, { 13, 7 }, { 29, 6 }, { 4, 4 }, { 10, 3 }, { 0, 3 }, + { 9, 3 }, { 26, 6 }, { 27, 6 }, { 12, 5 }, { 11, 5 }, { 5, 6 }, + { 7, 8 }, { 31, 8 }, { 30, 7 }, { 1, 4 }, { 24, 5 }, { 2, 5 }, + { 23, 4 }, { 28, 4 }, + }, { /* AC bias group 3, table 0 */ - { 0x3, 4 }, - { 0x9, 6 }, - { 0xD0, 8 }, - { 0x1A3, 9 }, - { 0x344, 10 }, - { 0xD14, 12 }, - { 0x1A2B, 13 }, - { 0x4, 4 }, - { 0x15, 7 }, - { 0x0, 3 }, - { 0xF, 4 }, - { 0xB, 4 }, - { 0xC, 4 }, - { 0xE, 4 }, - { 0x9, 4 }, - { 0x1B, 5 }, - { 0xA, 5 }, - { 0x14, 5 }, - { 0xD, 5 }, - { 0x2A, 6 }, - { 0x14, 7 }, - { 0x68B, 11 }, - { 0x1A2A, 13 }, - { 0x8, 4 }, - { 0xB, 5 }, - { 0x2B, 6 }, - { 0xB, 6 }, - { 0x69, 7 }, - { 0x35, 6 }, - { 0x8, 6 }, - { 0x7, 4 }, - { 0xC, 5 } + { 9, 3 }, { 29, 6 }, { 1, 6 }, { 20, 7 }, { 8, 7 }, { 26, 6 }, + { 0, 4 }, { 7, 4 }, { 16, 5 }, { 24, 5 }, { 31, 5 }, { 18, 5 }, + { 30, 4 }, { 23, 4 }, { 14, 4 }, { 17, 5 }, { 19, 6 }, { 25, 6 }, + { 11, 4 }, { 12, 4 }, { 2, 8 }, { 4, 10 }, { 5, 12 }, { 22, 13 }, + { 6, 13 }, { 21, 11 }, { 3, 9 }, { 27, 7 }, { 28, 6 }, { 15, 5 }, + { 13, 4 }, { 10, 4 }, }, { /* AC bias group 3, table 1 */ - { 0xA, 4 }, - { 0x3C, 6 }, - { 0x32, 7 }, - { 0x30, 7 }, - { 0xC5, 9 }, - { 0x621, 12 }, - { 0x620, 12 }, - { 0x1F, 5 }, - { 0x33, 7 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xE, 4 }, - { 0xD, 4 }, - { 0xC, 4 }, - { 0x4, 4 }, - { 0xD, 5 }, - { 0x26, 6 }, - { 0x27, 6 }, - { 0x14, 6 }, - { 0x63, 8 }, - { 0x189, 10 }, - { 0x623, 12 }, - { 0x622, 12 }, - { 0xB, 4 }, - { 0x12, 5 }, - { 0x3D, 6 }, - { 0x22, 6 }, - { 0x15, 6 }, - { 0xB, 5 }, - { 0x23, 6 }, - { 0x7, 4 }, - { 0x10, 5 } + { 10, 3 }, { 9, 3 }, { 14, 4 }, { 18, 6 }, { 27, 6 }, { 28, 5 }, + { 3, 7 }, { 6, 12 }, { 5, 12 }, { 22, 12 }, { 21, 12 }, { 20, 10 }, + { 4, 9 }, { 19, 8 }, { 2, 7 }, { 8, 7 }, { 15, 5 }, { 30, 4 }, + { 31, 5 }, { 26, 6 }, { 29, 6 }, { 24, 5 }, { 16, 6 }, { 17, 6 }, + { 0, 4 }, { 23, 4 }, { 13, 4 }, { 12, 4 }, { 11, 4 }, { 1, 6 }, + { 25, 6 }, { 7, 5 }, }, { /* AC bias group 3, table 2 */ - { 0xF, 4 }, - { 0xC, 5 }, - { 0x43, 7 }, - { 0x10, 6 }, - { 0x44, 8 }, - { 0x114, 10 }, - { 0x455, 12 }, - { 0x18, 5 }, - { 0x23, 7 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xE, 4 }, - { 0xD, 4 }, - { 0x9, 4 }, - { 0x19, 5 }, - { 0x9, 5 }, - { 0x17, 6 }, - { 0x16, 6 }, - { 0x42, 7 }, - { 0x8B, 9 }, - { 0x454, 12 }, - { 0x457, 12 }, - { 0x456, 12 }, - { 0xB, 4 }, - { 0x15, 5 }, - { 0xA, 5 }, - { 0x29, 6 }, - { 0x20, 6 }, - { 0xD, 5 }, - { 0x28, 6 }, - { 0x7, 4 }, - { 0x11, 5 } + { 10, 3 }, { 9, 3 }, { 3, 6 }, { 4, 8 }, { 5, 10 }, { 20, 12 }, + { 6, 12 }, { 22, 12 }, { 21, 12 }, { 19, 9 }, { 8, 7 }, { 15, 5 }, + { 25, 5 }, { 17, 6 }, { 16, 6 }, { 1, 5 }, { 28, 5 }, { 30, 4 }, + { 27, 6 }, { 18, 7 }, { 2, 7 }, { 31, 5 }, { 13, 4 }, { 29, 6 }, + { 26, 6 }, { 24, 5 }, { 23, 4 }, { 7, 5 }, { 14, 5 }, { 12, 4 }, + { 11, 4 }, { 0, 4 }, }, { /* AC bias group 3, table 3 */ - { 0x1, 3 }, - { 0x1A, 5 }, - { 0x29, 6 }, - { 0x2A, 6 }, - { 0xA0, 8 }, - { 0x285, 10 }, - { 0x1425, 13 }, - { 0x2, 5 }, - { 0x0, 7 }, - { 0x2, 3 }, - { 0x3, 3 }, - { 0xC, 4 }, - { 0xB, 4 }, - { 0x8, 4 }, - { 0x12, 5 }, - { 0x1, 6 }, - { 0x51, 7 }, - { 0x1, 7 }, - { 0x143, 9 }, - { 0x508, 11 }, - { 0x1424, 13 }, - { 0x1427, 13 }, - { 0x1426, 13 }, - { 0xF, 4 }, - { 0x1C, 5 }, - { 0x3, 5 }, - { 0x37, 6 }, - { 0x2B, 6 }, - { 0x13, 5 }, - { 0x36, 6 }, - { 0x1D, 5 }, - { 0x1, 5 } + { 8, 7 }, { 17, 7 }, { 15, 6 }, { 31, 5 }, { 7, 5 }, { 25, 5 }, + { 0, 3 }, { 9, 3 }, { 10, 3 }, { 13, 4 }, { 14, 5 }, { 28, 5 }, + { 4, 8 }, { 19, 11 }, { 20, 13 }, { 6, 13 }, { 22, 13 }, { 21, 13 }, + { 5, 10 }, { 18, 9 }, { 16, 7 }, { 2, 6 }, { 3, 6 }, { 27, 6 }, + { 12, 4 }, { 11, 4 }, { 1, 5 }, { 29, 6 }, { 26, 6 }, { 24, 5 }, + { 30, 5 }, { 23, 4 }, }, { /* AC bias group 3, table 4 */ - { 0x4, 3 }, - { 0x1F, 5 }, - { 0x3D, 6 }, - { 0x6, 5 }, - { 0x16, 7 }, - { 0x53, 9 }, - { 0x14A, 11 }, - { 0x34, 6 }, - { 0x2A, 8 }, - { 0x2, 3 }, - { 0x3, 3 }, - { 0xB, 4 }, - { 0xC, 4 }, - { 0x1C, 5 }, - { 0x37, 6 }, - { 0x17, 7 }, - { 0x2B, 8 }, - { 0x28, 8 }, - { 0xA4, 10 }, - { 0x52D, 13 }, - { 0x52C, 13 }, - { 0x52F, 13 }, - { 0x52E, 13 }, - { 0x0, 3 }, - { 0x1D, 5 }, - { 0x7, 5 }, - { 0x4, 5 }, - { 0x35, 6 }, - { 0x14, 5 }, - { 0x36, 6 }, - { 0x15, 5 }, - { 0x3C, 6 } + { 23, 3 }, { 26, 5 }, { 17, 8 }, { 18, 10 }, { 6, 11 }, { 20, 13 }, + { 19, 13 }, { 22, 13 }, { 21, 13 }, { 5, 9 }, { 8, 8 }, { 16, 8 }, + { 4, 7 }, { 15, 7 }, { 3, 5 }, { 25, 5 }, { 9, 3 }, { 10, 3 }, + { 0, 3 }, { 28, 5 }, { 30, 5 }, { 11, 4 }, { 12, 4 }, { 7, 6 }, + { 27, 6 }, { 29, 6 }, { 14, 6 }, { 13, 5 }, { 24, 5 }, { 31, 6 }, + { 2, 6 }, { 1, 5 }, }, { /* AC bias group 3, table 5 */ - { 0x4, 3 }, - { 0xA, 4 }, - { 0x7, 5 }, - { 0x1D, 5 }, - { 0x9, 6 }, - { 0x1F3, 9 }, - { 0x7C7, 11 }, - { 0x8, 6 }, - { 0x1F0, 9 }, - { 0x3, 3 }, - { 0x2, 3 }, - { 0xD, 4 }, - { 0xC, 4 }, - { 0x17, 5 }, - { 0x7D, 7 }, - { 0x1F2, 9 }, - { 0x7C6, 11 }, - { 0x7C5, 11 }, - { 0x1F12, 13 }, - { 0x3E27, 14 }, - { 0x3E26, 14 }, - { 0x1F11, 13 }, - { 0x1F10, 13 }, - { 0x0, 3 }, - { 0x1E, 5 }, - { 0x6, 5 }, - { 0x39, 6 }, - { 0x38, 6 }, - { 0x3F, 6 }, - { 0x2C, 6 }, - { 0x5, 5 }, - { 0x2D, 6 } + { 23, 3 }, { 7, 6 }, { 4, 6 }, { 30, 5 }, { 25, 5 }, { 2, 5 }, + { 10, 3 }, { 9, 3 }, { 0, 3 }, { 1, 4 }, { 29, 6 }, { 31, 6 }, + { 13, 5 }, { 12, 4 }, { 11, 4 }, { 27, 6 }, { 26, 6 }, { 3, 5 }, + { 24, 5 }, { 8, 9 }, { 22, 13 }, { 21, 13 }, { 18, 13 }, { 20, 14 }, + { 19, 14 }, { 17, 11 }, { 16, 11 }, { 6, 11 }, { 15, 9 }, { 5, 9 }, + { 14, 7 }, { 28, 6 }, }, { /* AC bias group 3, table 6 */ - { 0x2, 3 }, - { 0x7, 4 }, - { 0x18, 5 }, - { 0x3, 4 }, - { 0x5, 5 }, - { 0x35, 7 }, - { 0x4F, 9 }, - { 0x12, 7 }, - { 0x4E5, 13 }, - { 0x5, 3 }, - { 0x4, 3 }, - { 0xD, 4 }, - { 0xE, 4 }, - { 0x33, 6 }, - { 0x26, 8 }, - { 0x9D, 10 }, - { 0x4E4, 13 }, - { 0x4E7, 13 }, - { 0x4E6, 13 }, - { 0x4E1, 13 }, - { 0x4E0, 13 }, - { 0x4E3, 13 }, - { 0x4E2, 13 }, - { 0x0, 3 }, - { 0x1F, 5 }, - { 0xC, 5 }, - { 0x3D, 6 }, - { 0x3C, 6 }, - { 0x32, 6 }, - { 0x34, 7 }, - { 0x1B, 6 }, - { 0x8, 6 } + { 23, 3 }, { 31, 6 }, { 7, 7 }, { 14, 8 }, { 20, 13 }, { 19, 13 }, + { 22, 13 }, { 21, 13 }, { 16, 13 }, { 8, 13 }, { 18, 13 }, { 17, 13 }, + { 15, 10 }, { 6, 9 }, { 4, 5 }, { 3, 4 }, { 0, 3 }, { 25, 5 }, + { 29, 7 }, { 5, 7 }, { 30, 6 }, { 1, 4 }, { 10, 3 }, { 9, 3 }, + { 2, 5 }, { 28, 6 }, { 13, 6 }, { 11, 4 }, { 12, 4 }, { 27, 6 }, + { 26, 6 }, { 24, 5 }, }, { /* AC bias group 3, table 7 */ - { 0x0, 3 }, - { 0x4, 4 }, - { 0x1C, 5 }, - { 0xF, 4 }, - { 0x2, 4 }, - { 0x7, 5 }, - { 0x75, 7 }, - { 0xE8, 8 }, - { 0x1D2A, 13 }, - { 0x5, 3 }, - { 0x4, 3 }, - { 0xD, 4 }, - { 0xC, 4 }, - { 0x77, 7 }, - { 0xE96, 12 }, - { 0x3A57, 14 }, - { 0x3A56, 14 }, - { 0x3A5D, 14 }, - { 0x3A5C, 14 }, - { 0x3A5F, 14 }, - { 0x3A5E, 14 }, - { 0x1D29, 13 }, - { 0x1D28, 13 }, - { 0x3, 3 }, - { 0x6, 5 }, - { 0xA, 5 }, - { 0x2C, 7 }, - { 0x17, 6 }, - { 0x76, 7 }, - { 0x1D3, 9 }, - { 0x3A4, 10 }, - { 0x2D, 7 } + { 0, 3 }, { 4, 4 }, { 24, 5 }, { 5, 5 }, { 1, 4 }, { 25, 5 }, + { 26, 7 }, { 31, 7 }, { 27, 6 }, { 23, 3 }, { 10, 3 }, { 9, 3 }, + { 12, 4 }, { 11, 4 }, { 2, 5 }, { 7, 8 }, { 30, 10 }, { 22, 13 }, + { 21, 13 }, { 8, 13 }, { 16, 14 }, { 15, 14 }, { 14, 12 }, { 18, 14 }, + { 17, 14 }, { 20, 14 }, { 19, 14 }, { 29, 9 }, { 6, 7 }, { 28, 7 }, + { 13, 7 }, { 3, 4 }, }, { /* AC bias group 3, table 8 */ - { 0xA, 4 }, - { 0x24, 6 }, - { 0xBF, 8 }, - { 0x85, 8 }, - { 0x211, 10 }, - { 0x842, 12 }, - { 0x1087, 13 }, - { 0x18, 5 }, - { 0x20, 6 }, - { 0x1, 3 }, - { 0x2, 3 }, - { 0xE, 4 }, - { 0xD, 4 }, - { 0x7, 4 }, - { 0x13, 5 }, - { 0x25, 6 }, - { 0x5E, 7 }, - { 0x43, 7 }, - { 0xBE, 8 }, - { 0x109, 9 }, - { 0x1086, 13 }, - { 0x841, 12 }, - { 0x840, 12 }, - { 0xF, 4 }, - { 0x1, 4 }, - { 0x11, 5 }, - { 0x0, 5 }, - { 0x2E, 6 }, - { 0x19, 5 }, - { 0x1, 5 }, - { 0x6, 4 }, - { 0x16, 5 } + { 26, 5 }, { 29, 5 }, { 24, 4 }, { 9, 3 }, { 10, 3 }, { 30, 4 }, + { 13, 4 }, { 8, 6 }, { 22, 12 }, { 21, 12 }, { 5, 12 }, { 20, 13 }, + { 6, 13 }, { 4, 10 }, { 19, 9 }, { 3, 8 }, { 17, 7 }, { 25, 5 }, + { 1, 6 }, { 15, 6 }, { 14, 5 }, { 0, 4 }, { 31, 5 }, { 27, 6 }, + { 16, 7 }, { 18, 8 }, { 2, 8 }, { 7, 5 }, { 28, 5 }, { 12, 4 }, + { 11, 4 }, { 23, 4 }, }, { /* AC bias group 3, table 9 */ - { 0x2, 3 }, - { 0xF, 5 }, - { 0x6F, 7 }, - { 0x61, 7 }, - { 0x374, 10 }, - { 0x1BA8, 13 }, - { 0x3753, 14 }, - { 0x12, 5 }, - { 0x36, 6 }, - { 0x0, 3 }, - { 0x1, 3 }, - { 0xA, 4 }, - { 0xB, 4 }, - { 0x1A, 5 }, - { 0x31, 6 }, - { 0x60, 7 }, - { 0xDC, 8 }, - { 0x1BB, 9 }, - { 0x6EB, 11 }, - { 0x1BAB, 13 }, - { 0x3752, 14 }, - { 0x3755, 14 }, - { 0x3754, 14 }, - { 0xE, 4 }, - { 0x6, 4 }, - { 0x13, 5 }, - { 0xE, 5 }, - { 0x3E, 6 }, - { 0x8, 4 }, - { 0x1E, 5 }, - { 0x19, 5 }, - { 0x3F, 6 } + { 9, 3 }, { 10, 3 }, { 0, 3 }, { 24, 4 }, { 26, 5 }, { 1, 5 }, + { 28, 4 }, { 7, 5 }, { 25, 5 }, { 11, 4 }, { 12, 4 }, { 15, 7 }, + { 3, 7 }, { 14, 6 }, { 30, 5 }, { 13, 5 }, { 8, 6 }, { 16, 8 }, + { 4, 10 }, { 5, 13 }, { 20, 14 }, { 6, 14 }, { 22, 14 }, { 21, 14 }, + { 19, 13 }, { 18, 11 }, { 17, 9 }, { 2, 7 }, { 23, 4 }, { 29, 5 }, + { 27, 6 }, { 31, 6 }, }, { /* AC bias group 3, table 10 */ - { 0x3, 3 }, - { 0x1C, 5 }, - { 0x25, 6 }, - { 0x24, 6 }, - { 0x1DA, 9 }, - { 0x1DBD, 13 }, - { 0x3B7C, 14 }, - { 0x3C, 6 }, - { 0x3D, 6 }, - { 0x0, 3 }, - { 0x1, 3 }, - { 0xB, 4 }, - { 0xA, 4 }, - { 0xB, 5 }, - { 0x77, 7 }, - { 0xEC, 8 }, - { 0x3B6, 10 }, - { 0x76E, 11 }, - { 0x1DBF, 13 }, - { 0x76FB, 15 }, - { 0x76FA, 15 }, - { 0x3B79, 14 }, - { 0x3B78, 14 }, - { 0xD, 4 }, - { 0x1F, 5 }, - { 0x13, 5 }, - { 0xA, 5 }, - { 0x8, 5 }, - { 0xC, 4 }, - { 0x8, 4 }, - { 0x9, 5 }, - { 0x3A, 6 } + { 9, 3 }, { 10, 3 }, { 27, 5 }, { 30, 5 }, { 26, 5 }, { 13, 5 }, + { 0, 3 }, { 29, 4 }, { 3, 6 }, { 2, 6 }, { 25, 5 }, { 12, 4 }, + { 11, 4 }, { 28, 4 }, { 23, 4 }, { 1, 5 }, { 31, 6 }, { 15, 8 }, + { 4, 9 }, { 16, 10 }, { 17, 11 }, { 22, 14 }, { 21, 14 }, { 5, 13 }, + { 6, 14 }, { 20, 15 }, { 19, 15 }, { 18, 13 }, { 14, 7 }, { 7, 6 }, + { 8, 6 }, { 24, 5 }, }, { /* AC bias group 3, table 11 */ - { 0x5, 3 }, - { 0x3, 4 }, - { 0x4, 5 }, - { 0x10, 5 }, - { 0x8F, 8 }, - { 0x475, 11 }, - { 0x11D1, 13 }, - { 0x79, 7 }, - { 0x27, 6 }, - { 0x2, 3 }, - { 0x3, 3 }, - { 0x1, 4 }, - { 0x0, 4 }, - { 0x26, 6 }, - { 0x46, 7 }, - { 0x11C, 9 }, - { 0x477, 11 }, - { 0x8ED, 12 }, - { 0x11D0, 13 }, - { 0x11D3, 13 }, - { 0x11D2, 13 }, - { 0x11D9, 13 }, - { 0x11D8, 13 }, - { 0xD, 4 }, - { 0x1F, 5 }, - { 0x12, 5 }, - { 0x5, 5 }, - { 0x3D, 6 }, - { 0xC, 4 }, - { 0xE, 4 }, - { 0x22, 6 }, - { 0x78, 7 } + { 12, 4 }, { 11, 4 }, { 2, 5 }, { 26, 5 }, { 1, 4 }, { 9, 3 }, + { 10, 3 }, { 3, 5 }, { 30, 6 }, { 14, 7 }, { 15, 9 }, { 18, 13 }, + { 6, 13 }, { 20, 13 }, { 19, 13 }, { 5, 11 }, { 22, 13 }, { 21, 13 }, + { 17, 12 }, { 16, 11 }, { 4, 8 }, { 25, 5 }, { 13, 6 }, { 8, 6 }, + { 0, 3 }, { 28, 4 }, { 23, 4 }, { 29, 4 }, { 31, 7 }, { 7, 7 }, + { 27, 6 }, { 24, 5 }, }, { /* AC bias group 3, table 12 */ - { 0x5, 3 }, - { 0xC, 4 }, - { 0x1B, 5 }, - { 0x0, 4 }, - { 0x6, 6 }, - { 0x3E2, 10 }, - { 0x3E3D, 14 }, - { 0xF, 7 }, - { 0x34, 6 }, - { 0x3, 3 }, - { 0x2, 3 }, - { 0x1E, 5 }, - { 0x1D, 5 }, - { 0x7D, 7 }, - { 0x1F0, 9 }, - { 0x7C6, 11 }, - { 0x3E3C, 14 }, - { 0x3E3F, 14 }, - { 0x3E3E, 14 }, - { 0x3E39, 14 }, - { 0x3E38, 14 }, - { 0x3E3B, 14 }, - { 0x3E3A, 14 }, - { 0x8, 4 }, - { 0x1C, 5 }, - { 0x2, 5 }, - { 0x3F, 6 }, - { 0x35, 6 }, - { 0x9, 4 }, - { 0x1, 3 }, - { 0xE, 7 }, - { 0xF9, 8 } + { 3, 4 }, { 25, 5 }, { 4, 6 }, { 30, 7 }, { 7, 7 }, { 29, 3 }, + { 10, 3 }, { 9, 3 }, { 23, 4 }, { 28, 4 }, { 0, 3 }, { 1, 4 }, + { 8, 6 }, { 27, 6 }, { 2, 5 }, { 24, 5 }, { 12, 5 }, { 11, 5 }, + { 14, 9 }, { 5, 10 }, { 15, 11 }, { 20, 14 }, { 19, 14 }, { 22, 14 }, + { 21, 14 }, { 16, 14 }, { 6, 14 }, { 18, 14 }, { 17, 14 }, { 31, 8 }, + { 13, 7 }, { 26, 6 }, }, { /* AC bias group 3, table 13 */ - { 0x4, 3 }, - { 0xB, 4 }, - { 0x1, 4 }, - { 0xA, 4 }, - { 0x1E, 6 }, - { 0xE0, 9 }, - { 0xE1E, 13 }, - { 0x71, 8 }, - { 0x39, 7 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0xD, 5 }, - { 0xC, 5 }, - { 0x20, 7 }, - { 0x1C2, 10 }, - { 0x1C3F, 14 }, - { 0x1C3E, 14 }, - { 0xE19, 13 }, - { 0xE18, 13 }, - { 0xE1B, 13 }, - { 0xE1A, 13 }, - { 0xE1D, 13 }, - { 0xE1C, 13 }, - { 0x0, 4 }, - { 0x9, 5 }, - { 0x1D, 6 }, - { 0x1F, 6 }, - { 0x11, 6 }, - { 0x5, 4 }, - { 0x1, 3 }, - { 0x43, 8 }, - { 0x42, 8 } + { 23, 4 }, { 2, 4 }, { 29, 3 }, { 13, 7 }, { 31, 8 }, { 30, 8 }, + { 27, 6 }, { 24, 5 }, { 28, 4 }, { 12, 5 }, { 11, 5 }, { 5, 9 }, + { 14, 10 }, { 18, 13 }, { 17, 13 }, { 20, 13 }, { 19, 13 }, { 22, 13 }, + { 21, 13 }, { 6, 13 }, { 16, 14 }, { 15, 14 }, { 7, 8 }, { 8, 7 }, + { 25, 6 }, { 4, 6 }, { 26, 6 }, { 0, 3 }, { 3, 4 }, { 1, 4 }, + { 10, 3 }, { 9, 3 }, }, { /* AC bias group 3, table 14 */ - { 0x4, 3 }, - { 0xD, 4 }, - { 0x7, 4 }, - { 0x2, 3 }, - { 0x14, 5 }, - { 0x16C, 9 }, - { 0x16D1, 13 }, - { 0x2DF, 10 }, - { 0x16E, 9 }, - { 0x0, 2 }, - { 0x7, 3 }, - { 0x2C, 6 }, - { 0x2B, 6 }, - { 0x2DE, 10 }, - { 0x16D0, 13 }, - { 0x16D3, 13 }, - { 0x16D2, 13 }, - { 0x2DB5, 14 }, - { 0x2DB4, 14 }, - { 0x2DB7, 14 }, - { 0x2DB6, 14 }, - { 0x16D9, 13 }, - { 0x16D8, 13 }, - { 0xC, 5 }, - { 0x2A, 6 }, - { 0x5A, 7 }, - { 0x1B, 6 }, - { 0x1A, 6 }, - { 0x17, 5 }, - { 0xC, 4 }, - { 0x5B7, 11 }, - { 0x5B5, 11 } + { 9, 2 }, { 3, 3 }, { 23, 5 }, { 27, 6 }, { 26, 6 }, { 2, 4 }, + { 0, 3 }, { 4, 5 }, { 24, 6 }, { 12, 6 }, { 11, 6 }, { 25, 7 }, + { 5, 9 }, { 14, 13 }, { 6, 13 }, { 16, 13 }, { 15, 13 }, { 31, 11 }, + { 22, 13 }, { 21, 13 }, { 18, 14 }, { 17, 14 }, { 20, 14 }, { 19, 14 }, + { 30, 11 }, { 8, 9 }, { 13, 10 }, { 7, 10 }, { 28, 5 }, { 29, 4 }, + { 1, 4 }, { 10, 3 }, }, { /* AC bias group 3, table 15 */ - { 0x2, 2 }, - { 0xF, 4 }, - { 0x1C, 5 }, - { 0xC, 4 }, - { 0x3B, 6 }, - { 0x1AC, 9 }, - { 0x1AD8, 13 }, - { 0x35B3, 14 }, - { 0x35B2, 14 }, - { 0x1, 2 }, - { 0x0, 2 }, - { 0x69, 7 }, - { 0x68, 7 }, - { 0x35BD, 14 }, - { 0x35BC, 14 }, - { 0x35BF, 14 }, - { 0x35BE, 14 }, - { 0x35B9, 14 }, - { 0x35B8, 14 }, - { 0x35BB, 14 }, - { 0x35BA, 14 }, - { 0x35B5, 14 }, - { 0x35B4, 14 }, - { 0x1A9, 9 }, - { 0x1A8, 9 }, - { 0x35A, 10 }, - { 0xD7, 8 }, - { 0xD5, 8 }, - { 0x3A, 6 }, - { 0x1B, 5 }, - { 0x35B7, 14 }, - { 0x35B6, 14 } - } -}; - -static const uint16_t ac_bias_3[16][32][2] = { + { 10, 2 }, { 9, 2 }, { 0, 2 }, { 3, 4 }, { 12, 7 }, { 11, 7 }, + { 24, 9 }, { 23, 9 }, { 27, 8 }, { 5, 9 }, { 25, 10 }, { 6, 13 }, + { 8, 14 }, { 7, 14 }, { 22, 14 }, { 21, 14 }, { 31, 14 }, { 30, 14 }, + { 18, 14 }, { 17, 14 }, { 20, 14 }, { 19, 14 }, { 14, 14 }, { 13, 14 }, + { 16, 14 }, { 15, 14 }, { 26, 8 }, { 29, 5 }, { 2, 5 }, { 28, 6 }, + { 4, 6 }, { 1, 4 }, + }, { /* AC bias group 4, table 0 */ - { 0x0, 3 }, - { 0x10, 5 }, - { 0x72, 7 }, - { 0x71, 7 }, - { 0x154, 9 }, - { 0xAAB, 12 }, - { 0xAA8, 12 }, - { 0x14, 5 }, - { 0x70, 7 }, - { 0x2, 3 }, - { 0x3, 3 }, - { 0xC, 4 }, - { 0xB, 4 }, - { 0x3, 4 }, - { 0x11, 5 }, - { 0x73, 7 }, - { 0x54, 7 }, - { 0xAB, 8 }, - { 0x2AB, 10 }, - { 0x1553, 13 }, - { 0x1552, 13 }, - { 0x1555, 13 }, - { 0x1554, 13 }, - { 0xD, 4 }, - { 0x1E, 5 }, - { 0x12, 5 }, - { 0x3E, 6 }, - { 0x2B, 6 }, - { 0x2, 4 }, - { 0x3F, 6 }, - { 0x1D, 5 }, - { 0x13, 5 } + { 0, 3 }, { 28, 4 }, { 13, 4 }, { 9, 3 }, { 10, 3 }, { 1, 5 }, + { 14, 5 }, { 25, 5 }, { 31, 5 }, { 7, 5 }, { 16, 7 }, { 4, 9 }, + { 6, 12 }, { 20, 13 }, { 19, 13 }, { 22, 13 }, { 21, 13 }, { 5, 12 }, + { 18, 10 }, { 17, 8 }, { 27, 6 }, { 12, 4 }, { 11, 4 }, { 23, 4 }, + { 8, 7 }, { 3, 7 }, { 2, 7 }, { 15, 7 }, { 30, 5 }, { 24, 5 }, + { 26, 6 }, { 29, 6 }, }, { /* AC bias group 4, table 1 */ - { 0x3, 3 }, - { 0x1F, 5 }, - { 0x29, 6 }, - { 0x3D, 6 }, - { 0xC, 7 }, - { 0x69, 10 }, - { 0x345, 13 }, - { 0x2, 5 }, - { 0x28, 6 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0xE, 4 }, - { 0xC, 4 }, - { 0x15, 5 }, - { 0x7, 6 }, - { 0x1B, 8 }, - { 0x6B, 10 }, - { 0x6A, 10 }, - { 0x344, 13 }, - { 0x347, 13 }, - { 0x346, 13 }, - { 0x1A1, 12 }, - { 0x1A0, 12 }, - { 0xB, 4 }, - { 0x1A, 5 }, - { 0x12, 5 }, - { 0x0, 5 }, - { 0x3C, 6 }, - { 0x8, 4 }, - { 0x1B, 5 }, - { 0x13, 5 }, - { 0x1, 5 } + { 26, 5 }, { 31, 5 }, { 7, 5 }, { 4, 7 }, { 22, 12 }, { 21, 12 }, + { 18, 13 }, { 6, 13 }, { 20, 13 }, { 19, 13 }, { 5, 10 }, { 17, 10 }, + { 16, 10 }, { 15, 8 }, { 14, 6 }, { 10, 3 }, { 9, 3 }, { 0, 3 }, + { 28, 4 }, { 25, 5 }, { 30, 5 }, { 8, 6 }, { 2, 6 }, { 13, 5 }, + { 23, 4 }, { 12, 4 }, { 24, 5 }, { 29, 5 }, { 11, 4 }, { 27, 6 }, + { 3, 6 }, { 1, 5 }, }, { /* AC bias group 4, table 2 */ - { 0x4, 3 }, - { 0x4, 4 }, - { 0x3F, 6 }, - { 0x14, 5 }, - { 0x56, 7 }, - { 0x15C, 9 }, - { 0x15D5, 13 }, - { 0x3C, 6 }, - { 0x2A, 6 }, - { 0x0, 3 }, - { 0x1, 3 }, - { 0xE, 4 }, - { 0xD, 4 }, - { 0xC, 5 }, - { 0xAF, 8 }, - { 0x2BB, 10 }, - { 0x15D4, 13 }, - { 0x15D7, 13 }, - { 0x15D6, 13 }, - { 0x15D1, 13 }, - { 0x15D0, 13 }, - { 0x15D3, 13 }, - { 0x15D2, 13 }, - { 0xB, 4 }, - { 0x19, 5 }, - { 0xD, 5 }, - { 0x3E, 6 }, - { 0x31, 6 }, - { 0x7, 4 }, - { 0x5, 4 }, - { 0x3D, 6 }, - { 0x30, 6 } + { 9, 3 }, { 10, 3 }, { 1, 4 }, { 29, 4 }, { 13, 5 }, { 25, 5 }, + { 28, 4 }, { 0, 3 }, { 3, 5 }, { 8, 6 }, { 4, 7 }, { 5, 9 }, + { 20, 13 }, { 19, 13 }, { 22, 13 }, { 21, 13 }, { 16, 13 }, { 6, 13 }, + { 18, 13 }, { 17, 13 }, { 15, 10 }, { 14, 8 }, { 23, 4 }, { 31, 6 }, + { 27, 6 }, { 24, 5 }, { 12, 4 }, { 11, 4 }, { 7, 6 }, { 30, 6 }, + { 26, 6 }, { 2, 6 }, }, { /* AC bias group 4, table 3 */ - { 0x5, 3 }, - { 0x8, 4 }, - { 0x1A, 5 }, - { 0x0, 4 }, - { 0x36, 6 }, - { 0x11, 8 }, - { 0x106, 12 }, - { 0xA, 7 }, - { 0x6E, 7 }, - { 0x2, 3 }, - { 0x3, 3 }, - { 0x3, 4 }, - { 0x2, 4 }, - { 0x6F, 7 }, - { 0x21, 9 }, - { 0x20F, 13 }, - { 0x20E, 13 }, - { 0x101, 12 }, - { 0x100, 12 }, - { 0x103, 12 }, - { 0x102, 12 }, - { 0x105, 12 }, - { 0x104, 12 }, - { 0xC, 4 }, - { 0x1E, 5 }, - { 0x3, 5 }, - { 0x3E, 6 }, - { 0x3F, 6 }, - { 0x9, 4 }, - { 0xE, 4 }, - { 0xB, 7 }, - { 0x9, 7 } + { 3, 4 }, { 18, 12 }, { 17, 12 }, { 20, 12 }, { 19, 12 }, { 22, 12 }, + { 21, 12 }, { 6, 12 }, { 16, 13 }, { 15, 13 }, { 14, 9 }, { 5, 8 }, + { 31, 7 }, { 7, 7 }, { 30, 7 }, { 25, 5 }, { 12, 4 }, { 11, 4 }, + { 9, 3 }, { 10, 3 }, { 1, 4 }, { 28, 4 }, { 0, 3 }, { 23, 4 }, + { 2, 5 }, { 4, 6 }, { 8, 7 }, { 13, 7 }, { 29, 4 }, { 24, 5 }, + { 26, 6 }, { 27, 6 }, }, { /* AC bias group 4, table 4 */ - { 0x2, 3 }, - { 0xE, 4 }, - { 0x1E, 5 }, - { 0xC, 4 }, - { 0x1F, 5 }, - { 0x6E, 7 }, - { 0xAD, 10 }, - { 0xAF, 10 }, - { 0x14, 7 }, - { 0x4, 3 }, - { 0x3, 3 }, - { 0x1A, 5 }, - { 0x17, 5 }, - { 0x2A, 8 }, - { 0x576, 13 }, - { 0xAEF, 14 }, - { 0xAEE, 14 }, - { 0x571, 13 }, - { 0x570, 13 }, - { 0x573, 13 }, - { 0x572, 13 }, - { 0x575, 13 }, - { 0x574, 13 }, - { 0x3, 4 }, - { 0x16, 5 }, - { 0x4, 5 }, - { 0x36, 6 }, - { 0xB, 6 }, - { 0xA, 4 }, - { 0x0, 3 }, - { 0x6F, 7 }, - { 0xAC, 10 } + { 29, 3 }, { 25, 5 }, { 8, 7 }, { 13, 8 }, { 31, 10 }, { 6, 10 }, + { 18, 13 }, { 17, 13 }, { 20, 13 }, { 19, 13 }, { 22, 13 }, { 21, 13 }, + { 14, 13 }, { 16, 14 }, { 15, 14 }, { 7, 10 }, { 27, 6 }, { 23, 4 }, + { 0, 3 }, { 10, 3 }, { 9, 3 }, { 28, 4 }, { 24, 5 }, { 12, 5 }, + { 3, 4 }, { 11, 5 }, { 26, 6 }, { 5, 7 }, { 30, 7 }, { 1, 4 }, + { 2, 5 }, { 4, 5 }, }, { /* AC bias group 4, table 5 */ - { 0x4, 3 }, - { 0x5, 4 }, - { 0x3, 3 }, - { 0x1, 3 }, - { 0x4, 4 }, - { 0x2F, 6 }, - { 0x526, 11 }, - { 0x1495, 13 }, - { 0xA6, 8 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0x2D, 6 }, - { 0x2C, 6 }, - { 0x1494, 13 }, - { 0x1497, 13 }, - { 0x1496, 13 }, - { 0x1491, 13 }, - { 0x1490, 13 }, - { 0x1493, 13 }, - { 0x1492, 13 }, - { 0x293D, 14 }, - { 0x293C, 14 }, - { 0x293F, 14 }, - { 0x0, 3 }, - { 0x28, 6 }, - { 0xA5, 8 }, - { 0x148, 9 }, - { 0xA7, 8 }, - { 0x2E, 6 }, - { 0x15, 5 }, - { 0xA4E, 12 }, - { 0x293E, 14 } + { 23, 3 }, { 3, 3 }, { 4, 4 }, { 1, 4 }, { 2, 3 }, { 0, 3 }, + { 24, 6 }, { 26, 9 }, { 17, 13 }, { 16, 13 }, { 19, 13 }, { 18, 13 }, + { 13, 13 }, { 7, 13 }, { 15, 13 }, { 14, 13 }, { 6, 11 }, { 30, 12 }, + { 21, 14 }, { 20, 14 }, { 31, 14 }, { 22, 14 }, { 25, 8 }, { 8, 8 }, + { 27, 8 }, { 29, 5 }, { 12, 6 }, { 11, 6 }, { 28, 6 }, { 5, 6 }, + { 10, 3 }, { 9, 3 }, }, { /* AC bias group 4, table 6 */ - { 0x4, 3 }, - { 0x5, 4 }, - { 0x3, 3 }, - { 0x1, 3 }, - { 0x4, 4 }, - { 0x2F, 6 }, - { 0x526, 11 }, - { 0x1495, 13 }, - { 0xA6, 8 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0x2D, 6 }, - { 0x2C, 6 }, - { 0x1494, 13 }, - { 0x1497, 13 }, - { 0x1496, 13 }, - { 0x1491, 13 }, - { 0x1490, 13 }, - { 0x1493, 13 }, - { 0x1492, 13 }, - { 0x293D, 14 }, - { 0x293C, 14 }, - { 0x293F, 14 }, - { 0x0, 3 }, - { 0x28, 6 }, - { 0xA5, 8 }, - { 0x148, 9 }, - { 0xA7, 8 }, - { 0x2E, 6 }, - { 0x15, 5 }, - { 0xA4E, 12 }, - { 0x293E, 14 } + { 23, 3 }, { 3, 3 }, { 4, 4 }, { 1, 4 }, { 2, 3 }, { 0, 3 }, + { 24, 6 }, { 26, 9 }, { 17, 13 }, { 16, 13 }, { 19, 13 }, { 18, 13 }, + { 13, 13 }, { 7, 13 }, { 15, 13 }, { 14, 13 }, { 6, 11 }, { 30, 12 }, + { 21, 14 }, { 20, 14 }, { 31, 14 }, { 22, 14 }, { 25, 8 }, { 8, 8 }, + { 27, 8 }, { 29, 5 }, { 12, 6 }, { 11, 6 }, { 28, 6 }, { 5, 6 }, + { 10, 3 }, { 9, 3 }, }, { /* AC bias group 4, table 7 */ - { 0x4, 3 }, - { 0x5, 4 }, - { 0x3, 3 }, - { 0x1, 3 }, - { 0x4, 4 }, - { 0x2F, 6 }, - { 0x526, 11 }, - { 0x1495, 13 }, - { 0xA6, 8 }, - { 0x7, 3 }, - { 0x6, 3 }, - { 0x2D, 6 }, - { 0x2C, 6 }, - { 0x1494, 13 }, - { 0x1497, 13 }, - { 0x1496, 13 }, - { 0x1491, 13 }, - { 0x1490, 13 }, - { 0x1493, 13 }, - { 0x1492, 13 }, - { 0x293D, 14 }, - { 0x293C, 14 }, - { 0x293F, 14 }, - { 0x0, 3 }, - { 0x28, 6 }, - { 0xA5, 8 }, - { 0x148, 9 }, - { 0xA7, 8 }, - { 0x2E, 6 }, - { 0x15, 5 }, - { 0xA4E, 12 }, - { 0x293E, 14 } + { 23, 3 }, { 3, 3 }, { 4, 4 }, { 1, 4 }, { 2, 3 }, { 0, 3 }, + { 24, 6 }, { 26, 9 }, { 17, 13 }, { 16, 13 }, { 19, 13 }, { 18, 13 }, + { 13, 13 }, { 7, 13 }, { 15, 13 }, { 14, 13 }, { 6, 11 }, { 30, 12 }, + { 21, 14 }, { 20, 14 }, { 31, 14 }, { 22, 14 }, { 25, 8 }, { 8, 8 }, + { 27, 8 }, { 29, 5 }, { 12, 6 }, { 11, 6 }, { 28, 6 }, { 5, 6 }, + { 10, 3 }, { 9, 3 }, }, { /* AC bias group 4, table 8 */ - { 0x3, 3 }, - { 0x11, 5 }, - { 0x20, 6 }, - { 0x74, 7 }, - { 0x10D, 9 }, - { 0x863, 12 }, - { 0x860, 12 }, - { 0xA, 5 }, - { 0x75, 7 }, - { 0x1, 3 }, - { 0x0, 3 }, - { 0xB, 4 }, - { 0xA, 4 }, - { 0x18, 5 }, - { 0x38, 6 }, - { 0x42, 7 }, - { 0x10F, 9 }, - { 0x10E, 9 }, - { 0x219, 10 }, - { 0x10C3, 13 }, - { 0x10C2, 13 }, - { 0x10C5, 13 }, - { 0x10C4, 13 }, - { 0xF, 4 }, - { 0x4, 4 }, - { 0x19, 5 }, - { 0xB, 5 }, - { 0x39, 6 }, - { 0x9, 4 }, - { 0x1B, 5 }, - { 0x1A, 5 }, - { 0x3B, 6 } + { 10, 3 }, { 9, 3 }, { 24, 4 }, { 7, 5 }, { 26, 5 }, { 0, 3 }, + { 2, 6 }, { 15, 7 }, { 6, 12 }, { 20, 13 }, { 19, 13 }, { 22, 13 }, + { 21, 13 }, { 5, 12 }, { 18, 10 }, { 4, 9 }, { 17, 9 }, { 16, 9 }, + { 1, 5 }, { 28, 4 }, { 12, 4 }, { 11, 4 }, { 13, 5 }, { 25, 5 }, + { 30, 5 }, { 29, 5 }, { 14, 6 }, { 27, 6 }, { 3, 7 }, { 8, 7 }, + { 31, 6 }, { 23, 4 }, }, { /* AC bias group 4, table 9 */ - { 0x5, 3 }, - { 0x1, 4 }, - { 0x3E, 6 }, - { 0x1, 5 }, - { 0xE2, 8 }, - { 0x1C6F, 13 }, - { 0x38D9, 14 }, - { 0x39, 6 }, - { 0x1F, 6 }, - { 0x2, 3 }, - { 0x1, 3 }, - { 0x9, 4 }, - { 0x8, 4 }, - { 0x0, 5 }, - { 0x70, 7 }, - { 0x1C7, 9 }, - { 0x38C, 10 }, - { 0x71A, 11 }, - { 0x38D8, 14 }, - { 0x38DB, 14 }, - { 0x38DA, 14 }, - { 0x38DD, 14 }, - { 0x38DC, 14 }, - { 0xD, 4 }, - { 0x1D, 5 }, - { 0xE, 5 }, - { 0x3F, 6 }, - { 0x3C, 6 }, - { 0xC, 4 }, - { 0x6, 4 }, - { 0x3D, 6 }, - { 0x1E, 6 } + { 13, 5 }, { 3, 5 }, { 1, 4 }, { 10, 3 }, { 9, 3 }, { 29, 4 }, + { 25, 5 }, { 31, 6 }, { 8, 6 }, { 12, 4 }, { 11, 4 }, { 0, 3 }, + { 28, 4 }, { 23, 4 }, { 14, 7 }, { 4, 8 }, { 16, 10 }, { 17, 11 }, + { 18, 14 }, { 6, 14 }, { 20, 14 }, { 19, 14 }, { 22, 14 }, { 21, 14 }, + { 5, 13 }, { 15, 9 }, { 7, 6 }, { 24, 5 }, { 27, 6 }, { 30, 6 }, + { 2, 6 }, { 26, 6 }, }, { /* AC bias group 4, table 10 */ - { 0x6, 3 }, - { 0xB, 4 }, - { 0x11, 5 }, - { 0x1E, 5 }, - { 0x74, 7 }, - { 0x3AA, 10 }, - { 0x1D5C, 13 }, - { 0x1, 6 }, - { 0x21, 6 }, - { 0x1, 3 }, - { 0x2, 3 }, - { 0x7, 4 }, - { 0x6, 4 }, - { 0x3E, 6 }, - { 0xEB, 8 }, - { 0x1D4, 9 }, - { 0xEAF, 12 }, - { 0x3ABB, 14 }, - { 0x3ABA, 14 }, - { 0x1D59, 13 }, - { 0x1D58, 13 }, - { 0x1D5B, 13 }, - { 0x1D5A, 13 }, - { 0xA, 4 }, - { 0x1C, 5 }, - { 0x1, 5 }, - { 0x3F, 6 }, - { 0x3B, 6 }, - { 0x1, 4 }, - { 0x9, 4 }, - { 0x20, 6 }, - { 0x0, 6 } + { 31, 6 }, { 7, 6 }, { 25, 5 }, { 28, 4 }, { 9, 3 }, { 10, 3 }, + { 12, 4 }, { 11, 4 }, { 30, 6 }, { 8, 6 }, { 2, 5 }, { 29, 4 }, + { 23, 4 }, { 1, 4 }, { 0, 3 }, { 24, 5 }, { 4, 7 }, { 15, 9 }, + { 5, 10 }, { 20, 13 }, { 19, 13 }, { 22, 13 }, { 21, 13 }, { 6, 13 }, + { 18, 14 }, { 17, 14 }, { 16, 12 }, { 14, 8 }, { 27, 6 }, { 3, 5 }, + { 13, 6 }, { 26, 6 }, }, { /* AC bias group 4, table 11 */ - { 0x4, 3 }, - { 0xA, 4 }, - { 0x17, 5 }, - { 0x4, 4 }, - { 0x16, 6 }, - { 0x16A, 9 }, - { 0x16B1, 13 }, - { 0x17, 7 }, - { 0x5B, 7 }, - { 0x6, 3 }, - { 0x7, 3 }, - { 0x1, 4 }, - { 0x0, 4 }, - { 0xA, 6 }, - { 0x2D7, 10 }, - { 0xB5A, 12 }, - { 0x16B0, 13 }, - { 0x16B3, 13 }, - { 0x16B2, 13 }, - { 0x2D6D, 14 }, - { 0x2D6C, 14 }, - { 0x2D6F, 14 }, - { 0x2D6E, 14 }, - { 0x6, 4 }, - { 0xA, 5 }, - { 0x4, 5 }, - { 0x2C, 6 }, - { 0x17, 6 }, - { 0x3, 4 }, - { 0x7, 4 }, - { 0x16, 7 }, - { 0xB4, 8 } + { 12, 4 }, { 11, 4 }, { 25, 5 }, { 13, 6 }, { 30, 7 }, { 7, 7 }, + { 28, 4 }, { 3, 4 }, { 24, 5 }, { 4, 6 }, { 27, 6 }, { 23, 4 }, + { 29, 4 }, { 0, 3 }, { 1, 4 }, { 26, 6 }, { 31, 8 }, { 5, 9 }, + { 16, 13 }, { 6, 13 }, { 18, 13 }, { 17, 13 }, { 15, 12 }, { 20, 14 }, + { 19, 14 }, { 22, 14 }, { 21, 14 }, { 14, 10 }, { 8, 7 }, { 2, 5 }, + { 9, 3 }, { 10, 3 }, }, { /* AC bias group 4, table 12 */ - { 0x5, 3 }, - { 0xD, 4 }, - { 0x5, 4 }, - { 0x9, 4 }, - { 0x33, 6 }, - { 0x193, 9 }, - { 0x192C, 13 }, - { 0x61, 8 }, - { 0x31, 7 }, - { 0x0, 2 }, - { 0x7, 3 }, - { 0x10, 5 }, - { 0x11, 5 }, - { 0xC8, 8 }, - { 0x192F, 13 }, - { 0x325B, 14 }, - { 0x325A, 14 }, - { 0x1929, 13 }, - { 0x1928, 13 }, - { 0x192B, 13 }, - { 0x192A, 13 }, - { 0x325D, 14 }, - { 0x325C, 14 }, - { 0x18, 5 }, - { 0x1A, 6 }, - { 0x1B, 6 }, - { 0x65, 7 }, - { 0x19, 6 }, - { 0x4, 4 }, - { 0x7, 4 }, - { 0x60, 8 }, - { 0x324, 10 } + { 9, 2 }, { 28, 4 }, { 2, 4 }, { 30, 8 }, { 7, 8 }, { 8, 7 }, + { 27, 6 }, { 24, 6 }, { 25, 6 }, { 29, 4 }, { 11, 5 }, { 12, 5 }, + { 3, 4 }, { 0, 3 }, { 23, 5 }, { 13, 8 }, { 31, 10 }, { 18, 13 }, + { 17, 13 }, { 20, 13 }, { 19, 13 }, { 6, 13 }, { 16, 14 }, { 15, 14 }, + { 22, 14 }, { 21, 14 }, { 14, 13 }, { 5, 9 }, { 26, 7 }, { 4, 6 }, + { 1, 4 }, { 10, 3 }, }, { /* AC bias group 4, table 13 */ - { 0x6, 3 }, - { 0x0, 3 }, - { 0x2, 4 }, - { 0xF, 4 }, - { 0x39, 6 }, - { 0x1D9, 9 }, - { 0x1D82, 13 }, - { 0x761, 11 }, - { 0x3BE, 10 }, - { 0x1, 2 }, - { 0x2, 2 }, - { 0xF, 6 }, - { 0xE, 6 }, - { 0x762, 11 }, - { 0x3B07, 14 }, - { 0x3B06, 14 }, - { 0x3B1D, 14 }, - { 0x3B1C, 14 }, - { 0x3B1F, 14 }, - { 0x3B1E, 14 }, - { 0x3B19, 14 }, - { 0x3B18, 14 }, - { 0x3B1B, 14 }, - { 0x38, 6 }, - { 0x1DE, 9 }, - { 0xED, 8 }, - { 0x3BF, 10 }, - { 0xEE, 8 }, - { 0x3A, 6 }, - { 0x6, 5 }, - { 0xEC0, 12 }, - { 0x3B1A, 14 } + { 1, 3 }, { 2, 4 }, { 29, 5 }, { 12, 6 }, { 11, 6 }, { 9, 2 }, + { 10, 2 }, { 0, 3 }, { 23, 6 }, { 4, 6 }, { 28, 6 }, { 30, 12 }, + { 6, 13 }, { 15, 14 }, { 14, 14 }, { 7, 11 }, { 13, 11 }, { 21, 14 }, + { 20, 14 }, { 31, 14 }, { 22, 14 }, { 17, 14 }, { 16, 14 }, { 19, 14 }, + { 18, 14 }, { 5, 9 }, { 25, 8 }, { 27, 8 }, { 24, 9 }, { 8, 10 }, + { 26, 10 }, { 3, 4 }, }, { /* AC bias group 4, table 14 */ - { 0x0, 2 }, - { 0x2, 3 }, - { 0xF, 5 }, - { 0x6, 4 }, - { 0x1C, 6 }, - { 0x1D0, 10 }, - { 0xE8C, 13 }, - { 0x1D1B, 14 }, - { 0x1D1A, 14 }, - { 0x3, 2 }, - { 0x2, 2 }, - { 0xEA, 9 }, - { 0xE9, 9 }, - { 0xE89, 13 }, - { 0xE88, 13 }, - { 0xE8B, 13 }, - { 0xE8A, 13 }, - { 0x1D65, 14 }, - { 0x1D64, 14 }, - { 0x1D67, 14 }, - { 0x1D66, 14 }, - { 0x1D61, 14 }, - { 0x1D60, 14 }, - { 0x3AD, 11 }, - { 0x1D63, 14 }, - { 0x1D62, 14 }, - { 0x1D1D, 14 }, - { 0x1D1C, 14 }, - { 0x3B, 7 }, - { 0x1D7, 10 }, - { 0x1D1F, 14 }, - { 0x1D1E, 14 } + { 0, 2 }, { 1, 3 }, { 3, 4 }, { 4, 6 }, { 5, 10 }, { 14, 13 }, + { 13, 13 }, { 16, 13 }, { 15, 13 }, { 6, 13 }, { 8, 14 }, { 7, 14 }, + { 27, 14 }, { 26, 14 }, { 31, 14 }, { 30, 14 }, { 12, 9 }, { 11, 9 }, + { 22, 14 }, { 21, 14 }, { 25, 14 }, { 24, 14 }, { 18, 14 }, { 17, 14 }, + { 20, 14 }, { 19, 14 }, { 23, 11 }, { 29, 10 }, { 28, 7 }, { 2, 5 }, + { 10, 2 }, { 9, 2 }, }, { /* AC bias group 4, table 15 */ - { 0x2, 2 }, - { 0xF, 4 }, - { 0x1C, 5 }, - { 0xC, 4 }, - { 0x3B, 6 }, - { 0x1AC, 9 }, - { 0x1AD8, 13 }, - { 0x35B3, 14 }, - { 0x35B2, 14 }, - { 0x1, 2 }, - { 0x0, 2 }, - { 0x69, 7 }, - { 0x68, 7 }, - { 0x35BD, 14 }, - { 0x35BC, 14 }, - { 0x35BF, 14 }, - { 0x35BE, 14 }, - { 0x35B9, 14 }, - { 0x35B8, 14 }, - { 0x35BB, 14 }, - { 0x35BA, 14 }, - { 0x35B5, 14 }, - { 0x35B4, 14 }, - { 0x1A9, 9 }, - { 0x1A8, 9 }, - { 0x35A, 10 }, - { 0xD7, 8 }, - { 0xD5, 8 }, - { 0x3A, 6 }, - { 0x1B, 5 }, - { 0x35B7, 14 }, - { 0x35B6, 14 } - } + { 10, 2 }, { 9, 2 }, { 0, 2 }, { 3, 4 }, { 12, 7 }, { 11, 7 }, + { 24, 9 }, { 23, 9 }, { 27, 8 }, { 5, 9 }, { 25, 10 }, { 6, 13 }, + { 8, 14 }, { 7, 14 }, { 22, 14 }, { 21, 14 }, { 31, 14 }, { 30, 14 }, + { 18, 14 }, { 17, 14 }, { 20, 14 }, { 19, 14 }, { 14, 14 }, { 13, 14 }, + { 16, 14 }, { 15, 14 }, { 26, 8 }, { 29, 5 }, { 2, 5 }, { 28, 6 }, + { 4, 6 }, { 1, 4 }, + }, }; #endif /* AVCODEC_VP3DATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/vp3dsp.c ffmpeg-4.4/libavcodec/vp3dsp.c --- ffmpeg-4.2.2/libavcodec/vp3dsp.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp3dsp.c 2021-02-20 20:27:47.000000000 +0000 @@ -449,8 +449,8 @@ c->idct_put = vp3_idct_put_c; c->idct_add = vp3_idct_add_c; c->idct_dc_add = vp3_idct_dc_add_c; - c->v_loop_filter = vp3_v_loop_filter_8_c; - c->h_loop_filter = vp3_h_loop_filter_8_c; + c->v_loop_filter = c->v_loop_filter_unaligned = vp3_v_loop_filter_8_c; + c->h_loop_filter = c->h_loop_filter_unaligned = vp3_h_loop_filter_8_c; if (ARCH_ARM) ff_vp3dsp_init_arm(c, flags); @@ -490,5 +490,5 @@ } if (value) bounding_values[128] = value; - bounding_values[129] = bounding_values[130] = filter_limit * 0x02020202; + bounding_values[129] = bounding_values[130] = filter_limit * 0x02020202U; } diff -Nru ffmpeg-4.2.2/libavcodec/vp3dsp.h ffmpeg-4.4/libavcodec/vp3dsp.h --- ffmpeg-4.2.2/libavcodec/vp3dsp.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp3dsp.h 2020-07-11 10:39:30.000000000 +0000 @@ -43,6 +43,8 @@ void (*idct_dc_add)(uint8_t *dest, ptrdiff_t stride, int16_t *block); void (*v_loop_filter)(uint8_t *src, ptrdiff_t stride, int *bounding_values); void (*h_loop_filter)(uint8_t *src, ptrdiff_t stride, int *bounding_values); + void (*v_loop_filter_unaligned)(uint8_t *src, ptrdiff_t stride, int *bounding_values); + void (*h_loop_filter_unaligned)(uint8_t *src, ptrdiff_t stride, int *bounding_values); } VP3DSPContext; void ff_vp3dsp_v_loop_filter_12(uint8_t *first_pixel, ptrdiff_t stride, int *bounding_values); diff -Nru ffmpeg-4.2.2/libavcodec/vp4data.h ffmpeg-4.4/libavcodec/vp4data.h --- ffmpeg-4.2.2/libavcodec/vp4data.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp4data.h 2021-04-08 21:28:39.000000000 +0000 @@ -109,1078 +109,864 @@ 6, 6, 6, 6, 6, 6, 6, 6, }; -static const uint16_t vp4_mv_vlc[2][7][63][2] = { +static const uint8_t vp4_mv_vlc[2][7][63][2] = { { /* x-axis tables */ { - { 0x6A, 7 }, { 0x11A, 9 }, { 0x18E, 9 }, { 0x237, 10 }, - { 0x4A, 8 }, { 0x236, 10 }, { 0x7A, 8 }, { 0xD6, 9 }, - { 0x7E, 8 }, { 0x1FD, 10 }, { 0x8C, 8 }, { 0xD7, 9 }, - { 0x87, 8 }, { 0x183, 9 }, { 0x3C, 7 }, { 0x61, 7 }, - { 0x47, 7 }, { 0x69, 8 }, { 0x40, 7 }, { 0x48, 8 }, - { 0x49, 7 }, { 0x86, 8 }, { 0x13, 6 }, { 0xD2, 8 }, - { 0x1C, 6 }, { 0x42, 7 }, { 0x25, 6 }, { 0x1B, 6 }, - { 0x13, 5 }, { 0x5, 4 }, { 0x0, 2 }, { 0x7, 3 }, - { 0x5, 3 }, { 0x1B, 5 }, { 0x19, 5 }, { 0x19, 6 }, - { 0x8, 5 }, { 0x45, 7 }, { 0x1D, 6 }, { 0xC6, 8 }, - { 0x68, 7 }, { 0x90, 8 }, { 0x41, 7 }, { 0x4B, 8 }, - { 0x31, 7 }, { 0x18F, 9 }, { 0x62, 7 }, { 0x3E, 7 }, - { 0x44, 7 }, { 0x68, 8 }, { 0x30, 7 }, { 0x182, 9 }, - { 0xC0, 8 }, { 0x1A7, 9 }, { 0x91, 8 }, { 0x92, 9 }, - { 0x7B, 8 }, { 0xFF, 9 }, { 0x1A6, 9 }, { 0x1FC, 10 }, - { 0x6A, 8 }, { 0x93, 9 }, { 0x6B, 7 } + { 30, 2 }, { 36, 5 }, { 19, 8 }, { 55, 9 }, { 61, 9 }, + { 4, 8 }, { 43, 8 }, { 22, 6 }, { 29, 4 }, { 50, 7 }, + { 44, 7 }, { 35, 6 }, { 49, 8 }, { 17, 8 }, { 60, 8 }, + { 7, 9 }, { 11, 9 }, { 27, 6 }, { 24, 6 }, { 38, 6 }, + { 14, 7 }, { 6, 8 }, { 56, 8 }, { 47, 7 }, { 8, 8 }, + { 59, 10 }, { 9, 10 }, { 57, 9 }, { 18, 7 }, { 42, 7 }, + { 25, 7 }, { 21, 8 }, { 12, 8 }, { 48, 7 }, { 37, 7 }, + { 10, 8 }, { 1, 9 }, { 5, 10 }, { 3, 10 }, { 16, 7 }, + { 41, 8 }, { 54, 8 }, { 20, 7 }, { 26, 6 }, { 28, 5 }, + { 32, 3 }, { 52, 8 }, { 51, 9 }, { 13, 9 }, { 15, 7 }, + { 46, 7 }, { 39, 8 }, { 2, 9 }, { 45, 9 }, { 34, 5 }, + { 40, 7 }, { 23, 8 }, { 58, 9 }, { 53, 9 }, { 0, 7 }, + { 62, 7 }, { 33, 5 }, { 31, 3 }, + }, + { + { 29, 4 }, { 27, 6 }, { 54, 8 }, { 19, 8 }, { 53, 9 }, + { 13, 9 }, { 60, 8 }, { 25, 7 }, { 6, 8 }, { 2, 8 }, + { 11, 9 }, { 61, 9 }, { 8, 8 }, { 48, 7 }, { 28, 4 }, + { 46, 7 }, { 16, 7 }, { 24, 6 }, { 40, 6 }, { 20, 7 }, + { 62, 7 }, { 33, 3 }, { 36, 5 }, { 52, 8 }, { 41, 8 }, + { 44, 7 }, { 10, 8 }, { 59, 10 }, { 7, 10 }, { 21, 9 }, + { 18, 7 }, { 23, 8 }, { 12, 8 }, { 0, 7 }, { 5, 10 }, + { 3, 10 }, { 17, 9 }, { 15, 8 }, { 37, 7 }, { 38, 6 }, + { 49, 9 }, { 45, 9 }, { 14, 8 }, { 50, 8 }, { 47, 8 }, + { 34, 4 }, { 35, 6 }, { 42, 7 }, { 55, 10 }, { 1, 10 }, + { 43, 9 }, { 58, 9 }, { 9, 11 }, { 57, 11 }, { 51, 10 }, + { 22, 7 }, { 39, 8 }, { 56, 9 }, { 4, 9 }, { 26, 6 }, + { 30, 3 }, { 32, 3 }, { 31, 3 }, + }, + { + { 32, 2 }, { 35, 4 }, { 6, 8 }, { 12, 8 }, { 0, 7 }, + { 20, 7 }, { 44, 7 }, { 29, 5 }, { 34, 3 }, { 37, 6 }, + { 57, 9 }, { 10, 9 }, { 21, 8 }, { 39, 7 }, { 50, 8 }, + { 47, 8 }, { 62, 7 }, { 26, 6 }, { 28, 5 }, { 7, 10 }, + { 55, 10 }, { 49, 10 }, { 3, 10 }, { 17, 9 }, { 58, 9 }, + { 15, 8 }, { 56, 9 }, { 45, 9 }, { 42, 7 }, { 54, 8 }, + { 41, 8 }, { 33, 3 }, { 60, 9 }, { 43, 9 }, { 18, 8 }, + { 22, 7 }, { 40, 7 }, { 48, 8 }, { 25, 8 }, { 36, 5 }, + { 31, 4 }, { 30, 4 }, { 24, 7 }, { 51, 10 }, { 13, 11 }, + { 59, 11 }, { 53, 10 }, { 1, 10 }, { 14, 8 }, { 19, 9 }, + { 11, 10 }, { 9, 10 }, { 46, 8 }, { 8, 9 }, { 5, 10 }, + { 61, 10 }, { 16, 8 }, { 27, 7 }, { 4, 9 }, { 2, 9 }, + { 52, 9 }, { 23, 9 }, { 38, 6 }, + }, + { + { 10, 7 }, { 15, 7 }, { 0, 6 }, { 41, 6 }, { 22, 6 }, + { 33, 4 }, { 31, 4 }, { 55, 8 }, { 19, 8 }, { 60, 7 }, + { 56, 7 }, { 54, 7 }, { 28, 5 }, { 37, 4 }, { 16, 7 }, + { 50, 7 }, { 44, 6 }, { 14, 7 }, { 7, 9 }, { 3, 9 }, + { 59, 9 }, { 13, 9 }, { 24, 6 }, { 46, 6 }, { 47, 7 }, + { 4, 8 }, { 2, 8 }, { 39, 5 }, { 30, 4 }, { 35, 4 }, + { 61, 9 }, { 53, 9 }, { 21, 8 }, { 52, 7 }, { 43, 7 }, + { 18, 7 }, { 9, 9 }, { 11, 9 }, { 6, 8 }, { 25, 7 }, + { 17, 9 }, { 5, 9 }, { 23, 8 }, { 12, 8 }, { 58, 8 }, + { 38, 4 }, { 32, 4 }, { 20, 7 }, { 45, 8 }, { 8, 8 }, + { 26, 6 }, { 40, 5 }, { 36, 4 }, { 27, 7 }, { 57, 9 }, + { 51, 9 }, { 49, 9 }, { 1, 9 }, { 48, 7 }, { 62, 7 }, + { 29, 6 }, { 42, 6 }, { 34, 4 }, + }, + { + { 37, 5 }, { 62, 5 }, { 28, 5 }, { 4, 7 }, { 19, 8 }, + { 13, 8 }, { 51, 7 }, { 8, 7 }, { 43, 5 }, { 54, 6 }, + { 22, 6 }, { 42, 4 }, { 25, 7 }, { 9, 8 }, { 2, 8 }, + { 6, 7 }, { 10, 7 }, { 48, 5 }, { 29, 6 }, { 12, 7 }, + { 60, 7 }, { 41, 5 }, { 38, 4 }, { 40, 4 }, { 39, 5 }, + { 3, 9 }, { 7, 9 }, { 17, 8 }, { 15, 7 }, { 0, 6 }, + { 52, 6 }, { 24, 6 }, { 57, 8 }, { 55, 8 }, { 27, 7 }, + { 33, 6 }, { 35, 6 }, { 26, 6 }, { 53, 8 }, { 59, 9 }, + { 5, 9 }, { 49, 7 }, { 47, 6 }, { 45, 6 }, { 56, 7 }, + { 21, 8 }, { 61, 8 }, { 31, 5 }, { 34, 5 }, { 46, 5 }, + { 30, 5 }, { 18, 7 }, { 58, 7 }, { 16, 7 }, { 20, 7 }, + { 50, 6 }, { 1, 9 }, { 11, 9 }, { 23, 8 }, { 14, 7 }, + { 44, 5 }, { 32, 5 }, { 36, 5 }, + }, + { + { 50, 4 }, { 56, 5 }, { 22, 6 }, { 27, 7 }, { 10, 7 }, + { 46, 4 }, { 20, 6 }, { 43, 6 }, { 18, 6 }, { 8, 7 }, + { 11, 8 }, { 7, 8 }, { 38, 5 }, { 40, 5 }, { 48, 4 }, + { 16, 6 }, { 24, 6 }, { 28, 6 }, { 57, 7 }, { 6, 7 }, + { 31, 5 }, { 30, 5 }, { 54, 5 }, { 60, 6 }, { 58, 6 }, + { 42, 5 }, { 53, 6 }, { 26, 6 }, { 32, 5 }, { 44, 5 }, + { 17, 8 }, { 1, 8 }, { 59, 8 }, { 19, 8 }, { 45, 6 }, + { 62, 5 }, { 37, 7 }, { 14, 7 }, { 5, 9 }, { 9, 9 }, + { 4, 8 }, { 29, 7 }, { 52, 5 }, { 51, 6 }, { 12, 7 }, + { 35, 7 }, { 34, 6 }, { 23, 8 }, { 2, 8 }, { 25, 8 }, + { 21, 8 }, { 47, 5 }, { 39, 7 }, { 55, 7 }, { 49, 6 }, + { 41, 7 }, { 15, 7 }, { 0, 6 }, { 33, 7 }, { 61, 8 }, + { 3, 9 }, { 13, 9 }, { 36, 6 }, + }, + { + { 47, 5 }, { 14, 6 }, { 53, 6 }, { 43, 7 }, { 5, 8 }, + { 23, 8 }, { 37, 6 }, { 50, 5 }, { 24, 6 }, { 27, 7 }, + { 35, 7 }, { 31, 5 }, { 16, 6 }, { 22, 6 }, { 41, 7 }, + { 12, 7 }, { 57, 6 }, { 62, 3 }, { 48, 5 }, { 30, 5 }, + { 52, 5 }, { 55, 6 }, { 2, 7 }, { 33, 7 }, { 46, 5 }, + { 61, 6 }, { 59, 6 }, { 32, 5 }, { 4, 7 }, { 21, 8 }, + { 19, 8 }, { 49, 7 }, { 29, 7 }, { 54, 5 }, { 0, 5 }, + { 26, 6 }, { 39, 7 }, { 7, 8 }, { 3, 9 }, { 13, 9 }, + { 45, 7 }, { 6, 7 }, { 38, 6 }, { 58, 5 }, { 34, 6 }, + { 28, 6 }, { 18, 7 }, { 10, 7 }, { 51, 7 }, { 15, 7 }, + { 44, 6 }, { 17, 8 }, { 1, 8 }, { 8, 7 }, { 56, 5 }, + { 42, 6 }, { 36, 6 }, { 60, 5 }, { 11, 9 }, { 9, 9 }, + { 25, 8 }, { 20, 7 }, { 40, 6 }, }, - { - { 0x39, 7 }, { 0x259, 10 }, { 0x1B, 8 }, { 0x1D1, 10 }, - { 0x137, 9 }, { 0x1D0, 10 }, { 0x1A, 8 }, { 0x1B5, 10 }, - { 0x1D, 8 }, { 0x4BC, 11 }, { 0x6C, 8 }, { 0x38, 9 }, - { 0x71, 8 }, { 0x2D, 9 }, { 0x7D, 8 }, { 0x75, 8 }, - { 0x19, 7 }, { 0xE9, 9 }, { 0x37, 7 }, { 0x15, 8 }, - { 0x1E, 7 }, { 0xDB, 9 }, { 0x4C, 7 }, { 0x70, 8 }, - { 0xD, 6 }, { 0xC, 7 }, { 0x27, 6 }, { 0x4, 6 }, - { 0x2, 4 }, { 0x0, 4 }, { 0x5, 3 }, { 0x7, 3 }, - { 0x6, 3 }, { 0x2, 3 }, { 0x8, 4 }, { 0x24, 6 }, - { 0xC, 5 }, { 0x3B, 7 }, { 0x1E, 6 }, { 0x9A, 8 }, - { 0xE, 6 }, { 0x69, 8 }, { 0x4A, 7 }, { 0x12D, 9 }, - { 0x35, 7 }, { 0xF9, 9 }, { 0x18, 7 }, { 0x7F, 8 }, - { 0xF, 7 }, { 0xF8, 9 }, { 0x7E, 8 }, { 0x25F, 10 }, - { 0x68, 8 }, { 0x2C, 9 }, { 0x14, 8 }, { 0x258, 10 }, - { 0x136, 9 }, { 0x4BD, 11 }, { 0x12E, 9 }, { 0x1B4, 10 }, - { 0x17, 8 }, { 0x39, 9 }, { 0x1F, 7 } - }, - { - { 0x29, 7 }, { 0x3CB, 10 }, { 0x1F5, 9 }, { 0x263, 10 }, - { 0x1F4, 9 }, { 0x3DA, 10 }, { 0x50, 8 }, { 0x260, 10 }, - { 0x1EC, 9 }, { 0x3D3, 10 }, { 0x109, 9 }, { 0x3D2, 10 }, - { 0x51, 8 }, { 0x792, 11 }, { 0xF3, 8 }, { 0x9A, 8 }, - { 0xF7, 8 }, { 0x132, 9 }, { 0xC1, 8 }, { 0x1E8, 9 }, - { 0x2A, 7 }, { 0x85, 8 }, { 0x61, 7 }, { 0x1F7, 9 }, - { 0x78, 7 }, { 0xC7, 8 }, { 0x23, 6 }, { 0x7C, 7 }, - { 0x12, 5 }, { 0xB, 5 }, { 0xE, 4 }, { 0xD, 4 }, - { 0x0, 2 }, { 0x5, 3 }, { 0x3, 3 }, { 0x4, 4 }, - { 0x19, 5 }, { 0x20, 6 }, { 0x3F, 6 }, { 0x43, 7 }, - { 0x62, 7 }, { 0x9F, 8 }, { 0x4E, 7 }, { 0x181, 9 }, - { 0x2B, 7 }, { 0x137, 9 }, { 0xF5, 8 }, { 0x89, 8 }, - { 0xC6, 8 }, { 0x262, 10 }, { 0x88, 8 }, { 0x3C8, 10 }, - { 0x1F6, 9 }, { 0x3CA, 10 }, { 0x9E, 8 }, { 0x261, 10 }, - { 0x136, 9 }, { 0x108, 9 }, { 0x133, 9 }, { 0x793, 11 }, - { 0x180, 9 }, { 0x3DB, 10 }, { 0x45, 7 } - }, - { - { 0x1, 6 }, { 0x1C7, 9 }, { 0x67, 8 }, { 0xB5, 9 }, - { 0x66, 8 }, { 0x139, 9 }, { 0x99, 8 }, { 0xB4, 9 }, - { 0xC3, 8 }, { 0x130, 9 }, { 0x0, 7 }, { 0x131, 9 }, - { 0x9E, 8 }, { 0xB7, 9 }, { 0x2C, 7 }, { 0x1, 7 }, - { 0x28, 7 }, { 0x138, 9 }, { 0x4B, 7 }, { 0x31, 8 }, - { 0x60, 7 }, { 0x91, 8 }, { 0x3, 6 }, { 0x9D, 8 }, - { 0x17, 6 }, { 0x4D, 7 }, { 0x31, 6 }, { 0x70, 7 }, - { 0x7, 5 }, { 0x3A, 6 }, { 0x7, 4 }, { 0x2, 4 }, - { 0xB, 4 }, { 0x1, 4 }, { 0xF, 4 }, { 0x8, 4 }, - { 0xD, 4 }, { 0x4, 4 }, { 0xA, 4 }, { 0xD, 5 }, - { 0x19, 5 }, { 0x2, 6 }, { 0x3B, 6 }, { 0x4A, 7 }, - { 0x15, 6 }, { 0xC2, 8 }, { 0x18, 6 }, { 0x32, 7 }, - { 0x72, 7 }, { 0x1C6, 9 }, { 0x29, 7 }, { 0x1C5, 9 }, - { 0x49, 7 }, { 0x121, 9 }, { 0x1B, 7 }, { 0x30, 8 }, - { 0x1A, 7 }, { 0x1C4, 9 }, { 0x9F, 8 }, { 0xB6, 9 }, - { 0x19, 7 }, { 0x120, 9 }, { 0x73, 7 } - }, - { - { 0x23, 6 }, { 0x1C8, 9 }, { 0x43, 8 }, { 0x110, 9 }, - { 0xC, 7 }, { 0x153, 9 }, { 0x22, 7 }, { 0x111, 9 }, - { 0xF, 7 }, { 0x42, 8 }, { 0x23, 7 }, { 0x1C9, 9 }, - { 0x2A, 7 }, { 0x1B, 8 }, { 0x73, 7 }, { 0x45, 7 }, - { 0x6E, 7 }, { 0x89, 8 }, { 0x6C, 7 }, { 0x1A, 8 }, - { 0x6F, 7 }, { 0xB6, 8 }, { 0xB, 6 }, { 0xE5, 8 }, - { 0x25, 6 }, { 0x20, 7 }, { 0x29, 6 }, { 0x4D, 7 }, - { 0x2, 5 }, { 0x14, 6 }, { 0x1A, 5 }, { 0x17, 5 }, - { 0x1E, 5 }, { 0x27, 6 }, { 0x18, 5 }, { 0x28, 6 }, - { 0x1F, 5 }, { 0x0, 5 }, { 0x6, 4 }, { 0x10, 5 }, - { 0x7, 4 }, { 0xB, 5 }, { 0x3, 4 }, { 0x4, 5 }, - { 0x1D, 5 }, { 0x2C, 6 }, { 0x19, 5 }, { 0x2B, 6 }, - { 0x9, 5 }, { 0x55, 7 }, { 0x38, 6 }, { 0xE, 7 }, - { 0x24, 6 }, { 0xA8, 8 }, { 0xA, 6 }, { 0x99, 8 }, - { 0x5A, 7 }, { 0x98, 8 }, { 0x6D, 7 }, { 0x152, 9 }, - { 0x2B, 7 }, { 0xB7, 8 }, { 0x1, 5 } - }, - { - { 0x3D, 6 }, { 0xB1, 8 }, { 0xDD, 8 }, { 0x1F6, 9 }, - { 0xC5, 8 }, { 0x188, 9 }, { 0x37, 7 }, { 0x3F, 8 }, - { 0x1E, 7 }, { 0x189, 9 }, { 0xF, 7 }, { 0x3E, 8 }, - { 0x6A, 7 }, { 0x1F7, 9 }, { 0x61, 7 }, { 0x79, 7 }, - { 0x18, 6 }, { 0xB0, 8 }, { 0xE, 6 }, { 0xB3, 8 }, - { 0xC, 6 }, { 0xDF, 8 }, { 0x6, 6 }, { 0xDC, 8 }, - { 0x19, 6 }, { 0xDE, 8 }, { 0x27, 6 }, { 0xE, 7 }, - { 0x1A, 6 }, { 0x63, 7 }, { 0xF, 5 }, { 0xE, 5 }, - { 0x14, 5 }, { 0x7C, 7 }, { 0x36, 6 }, { 0x6B, 7 }, - { 0x3F, 6 }, { 0x60, 7 }, { 0x8, 5 }, { 0x74, 7 }, - { 0x9, 5 }, { 0x78, 7 }, { 0x12, 5 }, { 0xD, 6 }, - { 0x15, 5 }, { 0x2D, 6 }, { 0x2, 4 }, { 0x1C, 5 }, - { 0x5, 4 }, { 0x3B, 6 }, { 0x0, 4 }, { 0x34, 6 }, - { 0x19, 5 }, { 0x26, 6 }, { 0x10, 5 }, { 0x75, 7 }, - { 0x2, 5 }, { 0x36, 7 }, { 0x23, 6 }, { 0xB2, 8 }, - { 0x22, 6 }, { 0xFA, 8 }, { 0x17, 5 } - }, - { - { 0x15, 5 }, { 0xDD, 8 }, { 0x3E, 7 }, { 0x16E, 9 }, - { 0x4C, 7 }, { 0x12, 8 }, { 0x5D, 7 }, { 0xB6, 8 }, - { 0x6F, 7 }, { 0x1F1, 9 }, { 0x69, 7 }, { 0x1F0, 9 }, - { 0x1D, 7 }, { 0x16F, 9 }, { 0x2, 6 }, { 0x6B, 7 }, - { 0xC, 6 }, { 0xDC, 8 }, { 0x68, 7 }, { 0x9B, 8 }, - { 0x7D, 7 }, { 0x9A, 8 }, { 0xD, 6 }, { 0x13, 8 }, - { 0x8, 6 }, { 0xF9, 8 }, { 0x2C, 6 }, { 0x12, 7 }, - { 0x33, 6 }, { 0x4F, 7 }, { 0xD, 5 }, { 0x5, 5 }, - { 0x12, 5 }, { 0x3F, 7 }, { 0x32, 6 }, { 0x13, 7 }, - { 0x3B, 6 }, { 0x5, 6 }, { 0x2F, 6 }, { 0x5A, 7 }, - { 0x3F, 6 }, { 0x1C, 7 }, { 0x3A, 6 }, { 0x8, 7 }, - { 0x36, 6 }, { 0x5C, 7 }, { 0x10, 5 }, { 0x0, 5 }, - { 0xC, 5 }, { 0x4E, 7 }, { 0x3, 5 }, { 0x6A, 7 }, - { 0xE, 5 }, { 0x3, 6 }, { 0x14, 5 }, { 0x1E, 6 }, - { 0x1C, 5 }, { 0xF, 6 }, { 0x18, 5 }, { 0x23, 6 }, - { 0x1E, 5 }, { 0x22, 6 }, { 0x2, 3 } - } }, { /* y-axis tables */ { - { 0x52, 7 }, { 0x14C, 9 }, { 0x1FA, 9 }, { 0x124, 9 }, - { 0x82, 8 }, { 0x29E, 10 }, { 0x8E, 8 }, { 0x24B, 10 }, - { 0x9C, 8 }, { 0x3F7, 10 }, { 0x86, 8 }, { 0x114, 9 }, - { 0x83, 8 }, { 0x3A5, 10 }, { 0xFA, 8 }, { 0x4F, 7 }, - { 0xFB, 8 }, { 0x13B, 9 }, { 0xFC, 8 }, { 0x172, 9 }, - { 0x44, 7 }, { 0x173, 9 }, { 0x51, 7 }, { 0x87, 8 }, - { 0x5F, 7 }, { 0xBA, 8 }, { 0x26, 6 }, { 0x5E, 7 }, - { 0x16, 5 }, { 0x15, 5 }, { 0x6, 3 }, { 0x1, 2 }, - { 0x0, 2 }, { 0x1C, 5 }, { 0x1E, 5 }, { 0x75, 7 }, - { 0x3B, 6 }, { 0xFF, 8 }, { 0x25, 6 }, { 0xBB, 8 }, - { 0x7C, 7 }, { 0x8B, 8 }, { 0x48, 7 }, { 0x171, 9 }, - { 0x42, 7 }, { 0x14E, 9 }, { 0x46, 7 }, { 0xFE, 8 }, - { 0x40, 7 }, { 0x13A, 9 }, { 0x93, 8 }, { 0x115, 9 }, - { 0x8F, 8 }, { 0x3F6, 10 }, { 0x170, 9 }, { 0x29F, 10 }, - { 0x1D1, 9 }, { 0x24A, 10 }, { 0x1D3, 9 }, { 0x3A4, 10 }, - { 0x1D0, 9 }, { 0x14D, 9 }, { 0x50, 7 } - }, - { - { 0xDE, 8 }, { 0x223, 10 }, { 0x136, 9 }, { 0x7C5, 11 }, - { 0x12F, 9 }, { 0x4A1, 11 }, { 0x3D7, 10 }, { 0x7AC, 11 }, - { 0x133, 9 }, { 0x7C4, 11 }, { 0x1B8, 9 }, { 0x222, 10 }, - { 0x96, 8 }, { 0x251, 10 }, { 0x95, 8 }, { 0x1F0, 9 }, - { 0xDA, 8 }, { 0x110, 9 }, { 0x9A, 8 }, { 0x360, 10 }, - { 0xDD, 8 }, { 0x12E, 9 }, { 0x48, 7 }, { 0x92, 8 }, - { 0x78, 7 }, { 0x98, 8 }, { 0x27, 6 }, { 0x45, 7 }, - { 0x1A, 5 }, { 0x10, 5 }, { 0x5, 3 }, { 0x0, 2 }, - { 0x1, 2 }, { 0xE, 4 }, { 0xC, 4 }, { 0x23, 6 }, - { 0x3F, 6 }, { 0xF4, 8 }, { 0x7D, 7 }, { 0x89, 8 }, - { 0x7B, 7 }, { 0x1BE, 9 }, { 0xF9, 8 }, { 0x3E3, 10 }, - { 0xF3, 8 }, { 0x127, 9 }, { 0xDB, 8 }, { 0x1EA, 9 }, - { 0xD9, 8 }, { 0x6E7, 11 }, { 0x1BF, 9 }, { 0x4A0, 11 }, - { 0x1B1, 9 }, { 0x6E6, 11 }, { 0x137, 9 }, { 0x7AD, 11 }, - { 0x126, 9 }, { 0x6C2, 11 }, { 0x132, 9 }, { 0x6C3, 11 }, - { 0x129, 9 }, { 0x372, 10 }, { 0xF2, 8 } - }, - { - { 0x16, 7 }, { 0x9C, 9 }, { 0x13C, 9 }, { 0x9E, 10 }, - { 0x12B, 9 }, { 0xBA, 10 }, { 0x181, 9 }, { 0x317, 10 }, - { 0x84, 8 }, { 0x4E, 9 }, { 0x26, 8 }, { 0x316, 10 }, - { 0x180, 9 }, { 0x5C, 9 }, { 0xC1, 8 }, { 0x2F, 8 }, - { 0x10, 7 }, { 0x45, 9 }, { 0x12, 7 }, { 0x189, 9 }, - { 0x24, 7 }, { 0x13D, 9 }, { 0x66, 7 }, { 0x23, 8 }, - { 0x67, 7 }, { 0xC6, 8 }, { 0x24, 6 }, { 0x4B, 7 }, - { 0x11, 5 }, { 0x32, 6 }, { 0xD, 4 }, { 0x0, 3 }, - { 0x7, 3 }, { 0x5, 3 }, { 0x3, 3 }, { 0x3, 4 }, - { 0x5, 4 }, { 0x20, 6 }, { 0x8, 5 }, { 0x25, 7 }, - { 0x26, 6 }, { 0x4F, 8 }, { 0x61, 7 }, { 0x2B, 8 }, - { 0x4E, 7 }, { 0x18A, 9 }, { 0x43, 7 }, { 0x9F, 8 }, - { 0x14, 7 }, { 0x254, 10 }, { 0x94, 8 }, { 0x310, 10 }, - { 0x85, 8 }, { 0x311, 10 }, { 0x2A, 8 }, { 0xBB, 10 }, - { 0x18F, 9 }, { 0x255, 10 }, { 0x9D, 9 }, { 0x9F, 10 }, - { 0x18E, 9 }, { 0x44, 9 }, { 0x26, 7 } - }, - { - { 0x61, 7 }, { 0x12A, 9 }, { 0xD, 8 }, { 0x3BD, 10 }, - { 0x89, 8 }, { 0x109, 9 }, { 0x18E, 9 }, { 0x210, 10 }, - { 0x1D3, 9 }, { 0x211, 10 }, { 0x88, 8 }, { 0x19, 9 }, - { 0x85, 8 }, { 0x18, 9 }, { 0xE8, 8 }, { 0xCE, 8 }, - { 0x40, 7 }, { 0x119, 9 }, { 0x45, 7 }, { 0x1D2, 9 }, - { 0x4B, 7 }, { 0x1DD, 9 }, { 0x62, 7 }, { 0x94, 8 }, - { 0x75, 7 }, { 0xC, 7 }, { 0x27, 6 }, { 0xD, 7 }, - { 0x2, 5 }, { 0x26, 6 }, { 0x6, 4 }, { 0x1E, 5 }, - { 0xD, 4 }, { 0x1F, 5 }, { 0x1, 3 }, { 0xA, 4 }, - { 0x2, 3 }, { 0x7, 4 }, { 0xB, 4 }, { 0x0, 5 }, - { 0x1C, 5 }, { 0x76, 7 }, { 0x32, 6 }, { 0x7, 7 }, - { 0x24, 6 }, { 0xC0, 8 }, { 0x7, 6 }, { 0x41, 7 }, - { 0x2, 6 }, { 0x18F, 9 }, { 0x47, 7 }, { 0x1DC, 9 }, - { 0x43, 7 }, { 0x12B, 9 }, { 0xCF, 8 }, { 0x118, 9 }, - { 0xC6, 8 }, { 0x3BC, 10 }, { 0x8D, 8 }, { 0x3BF, 10 }, - { 0xC1, 8 }, { 0x3BE, 10 }, { 0x66, 7 } - }, - { - { 0x7, 6 }, { 0x14D, 9 }, { 0xA0, 8 }, { 0x9E, 9 }, - { 0xCF, 8 }, { 0x39C, 10 }, { 0xA1, 8 }, { 0x39D, 10 }, - { 0xAB, 8 }, { 0x1C5, 9 }, { 0x26, 7 }, { 0x14C, 9 }, - { 0x25, 7 }, { 0x19C, 9 }, { 0x3F, 7 }, { 0xE1, 8 }, - { 0x66, 7 }, { 0x1CF, 9 }, { 0x3E, 7 }, { 0x1C4, 9 }, - { 0x72, 7 }, { 0x4E, 8 }, { 0x6, 6 }, { 0xAA, 8 }, - { 0x1C, 6 }, { 0xE6, 8 }, { 0x32, 6 }, { 0x51, 7 }, - { 0x3B, 6 }, { 0x5, 6 }, { 0x1F, 5 }, { 0x18, 5 }, - { 0x2, 4 }, { 0x3A, 6 }, { 0x0, 4 }, { 0x36, 6 }, - { 0x5, 4 }, { 0x8, 5 }, { 0x8, 4 }, { 0x16, 5 }, - { 0x9, 4 }, { 0xD, 5 }, { 0x3, 4 }, { 0x2F, 6 }, - { 0x1E, 5 }, { 0x2E, 6 }, { 0x1A, 5 }, { 0x2B, 6 }, - { 0xC, 5 }, { 0x24, 7 }, { 0x1E, 6 }, { 0xE0, 8 }, - { 0x4, 6 }, { 0xA7, 8 }, { 0x54, 7 }, { 0x1C7, 9 }, - { 0x52, 7 }, { 0x19D, 9 }, { 0x3A, 7 }, { 0x9F, 9 }, - { 0x3B, 7 }, { 0x1C6, 9 }, { 0x37, 6 } - }, - { - { 0x2A, 6 }, { 0x39, 8 }, { 0x25, 7 }, { 0x115, 9 }, - { 0x24, 7 }, { 0x1FA, 9 }, { 0x2F, 7 }, { 0x114, 9 }, - { 0x75, 7 }, { 0x38, 8 }, { 0xFC, 8 }, { 0x36, 8 }, - { 0x1E, 7 }, { 0x1FB, 9 }, { 0x7F, 7 }, { 0x68, 7 }, - { 0x16, 6 }, { 0x37, 8 }, { 0x1F, 7 }, { 0x5C, 8 }, - { 0x13, 6 }, { 0x8B, 8 }, { 0x1, 6 }, { 0xFB, 8 }, - { 0x21, 6 }, { 0x44, 7 }, { 0x2B, 6 }, { 0x6B, 7 }, - { 0x3B, 6 }, { 0xC, 6 }, { 0x1C, 5 }, { 0x19, 5 }, - { 0x1, 4 }, { 0x20, 6 }, { 0x16, 5 }, { 0x7C, 7 }, - { 0xC, 5 }, { 0x74, 7 }, { 0xA, 5 }, { 0x1C, 6 }, - { 0x12, 5 }, { 0x69, 7 }, { 0xF, 5 }, { 0x6A, 7 }, - { 0x14, 5 }, { 0x11, 6 }, { 0x1E, 5 }, { 0x17, 5 }, - { 0x2, 4 }, { 0x31, 6 }, { 0x1B, 5 }, { 0x30, 6 }, - { 0xD, 5 }, { 0x0, 6 }, { 0x1, 5 }, { 0x1D, 7 }, - { 0x23, 6 }, { 0x1A, 7 }, { 0x1D, 6 }, { 0x5D, 8 }, - { 0x10, 6 }, { 0xFA, 8 }, { 0x13, 5 } + { 32, 2 }, { 31, 2 }, { 48, 7 }, { 4, 8 }, { 12, 8 }, + { 44, 7 }, { 10, 8 }, { 23, 8 }, { 20, 7 }, { 11, 9 }, + { 51, 9 }, { 41, 8 }, { 46, 7 }, { 6, 8 }, { 52, 8 }, + { 42, 7 }, { 3, 9 }, { 57, 10 }, { 7, 10 }, { 50, 8 }, + { 38, 6 }, { 26, 6 }, { 8, 8 }, { 49, 9 }, { 17, 9 }, + { 15, 7 }, { 62, 7 }, { 22, 7 }, { 0, 7 }, { 1, 9 }, + { 61, 9 }, { 45, 9 }, { 5, 10 }, { 55, 10 }, { 29, 5 }, + { 28, 5 }, { 54, 9 }, { 43, 9 }, { 19, 9 }, { 21, 9 }, + { 25, 8 }, { 39, 8 }, { 27, 7 }, { 24, 7 }, { 30, 3 }, + { 33, 5 }, { 60, 9 }, { 56, 9 }, { 59, 10 }, { 13, 10 }, + { 58, 9 }, { 35, 7 }, { 36, 6 }, { 34, 5 }, { 40, 7 }, + { 14, 8 }, { 16, 8 }, { 18, 8 }, { 2, 9 }, { 53, 10 }, + { 9, 10 }, { 47, 8 }, { 37, 8 }, + }, + { + { 31, 2 }, { 32, 2 }, { 29, 5 }, { 17, 9 }, { 11, 10 }, + { 1, 10 }, { 39, 8 }, { 27, 7 }, { 35, 6 }, { 22, 7 }, + { 23, 8 }, { 56, 9 }, { 45, 9 }, { 51, 11 }, { 5, 11 }, + { 13, 10 }, { 60, 9 }, { 14, 8 }, { 12, 8 }, { 21, 9 }, + { 4, 9 }, { 25, 8 }, { 58, 9 }, { 8, 9 }, { 18, 8 }, + { 2, 9 }, { 54, 9 }, { 26, 6 }, { 30, 3 }, { 34, 4 }, + { 28, 5 }, { 19, 10 }, { 57, 11 }, { 59, 11 }, { 52, 9 }, + { 48, 8 }, { 16, 8 }, { 46, 8 }, { 10, 9 }, { 61, 10 }, + { 53, 11 }, { 49, 11 }, { 20, 8 }, { 0, 8 }, { 41, 9 }, + { 50, 9 }, { 33, 4 }, { 24, 7 }, { 62, 8 }, { 44, 8 }, + { 37, 8 }, { 47, 9 }, { 7, 11 }, { 55, 11 }, { 6, 10 }, + { 40, 7 }, { 15, 9 }, { 9, 11 }, { 3, 11 }, { 43, 10 }, + { 42, 8 }, { 38, 7 }, { 36, 6 }, + }, + { + { 31, 3 }, { 16, 7 }, { 61, 9 }, { 17, 9 }, { 23, 8 }, + { 18, 7 }, { 10, 8 }, { 9, 9 }, { 3, 10 }, { 59, 10 }, + { 48, 7 }, { 54, 8 }, { 43, 8 }, { 0, 7 }, { 13, 9 }, + { 5, 10 }, { 55, 10 }, { 15, 8 }, { 35, 4 }, { 38, 5 }, + { 20, 7 }, { 39, 7 }, { 62, 7 }, { 1, 9 }, { 58, 9 }, + { 41, 8 }, { 36, 4 }, { 34, 3 }, { 37, 6 }, { 8, 8 }, + { 52, 8 }, { 46, 7 }, { 28, 5 }, { 26, 6 }, { 50, 8 }, + { 49, 10 }, { 57, 10 }, { 4, 9 }, { 27, 7 }, { 40, 6 }, + { 44, 7 }, { 2, 9 }, { 21, 9 }, { 47, 8 }, { 33, 3 }, + { 12, 9 }, { 6, 9 }, { 14, 8 }, { 42, 7 }, { 51, 10 }, + { 53, 10 }, { 19, 9 }, { 45, 9 }, { 11, 10 }, { 7, 10 }, + { 25, 8 }, { 60, 9 }, { 56, 9 }, { 29, 6 }, { 22, 7 }, + { 24, 7 }, { 30, 4 }, { 32, 3 }, + }, + { + { 39, 5 }, { 48, 6 }, { 13, 9 }, { 11, 9 }, { 2, 8 }, + { 43, 7 }, { 28, 5 }, { 25, 7 }, { 27, 7 }, { 46, 6 }, + { 34, 3 }, { 36, 3 }, { 30, 4 }, { 37, 4 }, { 16, 7 }, + { 47, 7 }, { 7, 10 }, { 9, 10 }, { 5, 9 }, { 12, 8 }, + { 52, 7 }, { 10, 8 }, { 4, 8 }, { 18, 7 }, { 55, 9 }, + { 17, 9 }, { 58, 8 }, { 50, 7 }, { 44, 6 }, { 23, 8 }, + { 1, 9 }, { 53, 9 }, { 20, 7 }, { 29, 6 }, { 26, 6 }, + { 35, 4 }, { 38, 4 }, { 45, 8 }, { 60, 8 }, { 0, 7 }, + { 22, 7 }, { 56, 8 }, { 6, 9 }, { 49, 9 }, { 42, 6 }, + { 62, 7 }, { 15, 8 }, { 54, 8 }, { 32, 4 }, { 40, 5 }, + { 14, 8 }, { 19, 9 }, { 8, 9 }, { 24, 7 }, { 41, 7 }, + { 51, 9 }, { 21, 9 }, { 57, 10 }, { 3, 10 }, { 61, 10 }, + { 59, 10 }, { 31, 5 }, { 33, 5 }, + }, + { + { 34, 4 }, { 52, 6 }, { 29, 6 }, { 22, 6 }, { 0, 6 }, + { 32, 4 }, { 42, 4 }, { 37, 5 }, { 49, 7 }, { 12, 7 }, + { 10, 7 }, { 21, 8 }, { 3, 9 }, { 59, 9 }, { 36, 4 }, + { 48, 5 }, { 41, 5 }, { 24, 6 }, { 58, 7 }, { 60, 7 }, + { 50, 6 }, { 18, 7 }, { 14, 7 }, { 38, 4 }, { 40, 4 }, + { 2, 8 }, { 6, 8 }, { 27, 7 }, { 56, 7 }, { 11, 9 }, + { 1, 9 }, { 53, 8 }, { 54, 7 }, { 23, 8 }, { 8, 8 }, + { 47, 6 }, { 39, 5 }, { 45, 6 }, { 43, 6 }, { 31, 5 }, + { 26, 6 }, { 16, 7 }, { 13, 9 }, { 57, 9 }, { 4, 8 }, + { 46, 5 }, { 35, 6 }, { 62, 6 }, { 51, 8 }, { 15, 8 }, + { 19, 9 }, { 9, 9 }, { 61, 9 }, { 55, 9 }, { 20, 7 }, + { 25, 8 }, { 5, 10 }, { 7, 10 }, { 17, 9 }, { 33, 6 }, + { 28, 6 }, { 44, 5 }, { 30, 5 }, + }, + { + { 53, 6 }, { 22, 6 }, { 54, 5 }, { 32, 4 }, { 48, 4 }, + { 29, 6 }, { 57, 7 }, { 11, 8 }, { 17, 8 }, { 9, 8 }, + { 1, 8 }, { 55, 7 }, { 12, 7 }, { 18, 7 }, { 60, 6 }, + { 45, 6 }, { 4, 7 }, { 2, 7 }, { 20, 6 }, { 38, 5 }, + { 16, 6 }, { 19, 8 }, { 59, 8 }, { 6, 7 }, { 36, 5 }, + { 52, 5 }, { 39, 6 }, { 58, 6 }, { 42, 5 }, { 33, 6 }, + { 24, 6 }, { 25, 7 }, { 7, 9 }, { 3, 9 }, { 21, 8 }, + { 56, 6 }, { 40, 5 }, { 62, 5 }, { 44, 5 }, { 0, 6 }, + { 26, 6 }, { 34, 5 }, { 47, 5 }, { 51, 6 }, { 49, 6 }, + { 31, 5 }, { 15, 7 }, { 41, 7 }, { 43, 7 }, { 27, 7 }, + { 50, 5 }, { 30, 5 }, { 37, 7 }, { 8, 7 }, { 28, 6 }, + { 46, 5 }, { 35, 7 }, { 61, 8 }, { 23, 8 }, { 10, 8 }, + { 5, 9 }, { 13, 9 }, { 14, 7 }, + }, + { + { 62, 3 }, { 25, 7 }, { 3, 8 }, { 19, 8 }, { 59, 6 }, + { 29, 6 }, { 22, 6 }, { 14, 6 }, { 4, 7 }, { 23, 7 }, + { 48, 5 }, { 60, 5 }, { 61, 6 }, { 1, 7 }, { 39, 7 }, + { 46, 5 }, { 52, 5 }, { 40, 5 }, { 34, 5 }, { 58, 5 }, + { 21, 8 }, { 13, 8 }, { 49, 7 }, { 16, 6 }, { 12, 7 }, + { 2, 7 }, { 47, 6 }, { 56, 5 }, { 0, 5 }, { 6, 7 }, + { 45, 7 }, { 55, 6 }, { 54, 5 }, { 9, 8 }, { 5, 8 }, + { 15, 7 }, { 33, 6 }, { 10, 7 }, { 53, 7 }, { 24, 6 }, + { 8, 7 }, { 37, 7 }, { 43, 7 }, { 20, 7 }, { 44, 6 }, + { 36, 6 }, { 28, 6 }, { 42, 6 }, { 30, 5 }, { 17, 8 }, + { 7, 9 }, { 11, 9 }, { 27, 7 }, { 26, 6 }, { 38, 6 }, + { 50, 6 }, { 51, 8 }, { 41, 8 }, { 57, 7 }, { 18, 7 }, + { 35, 7 }, { 31, 5 }, { 32, 5 }, }, - { - { 0x12, 5 }, { 0x26, 7 }, { 0x41, 7 }, { 0x22, 8 }, - { 0x1A, 7 }, { 0xA9, 8 }, { 0x4C, 7 }, { 0x1B2, 9 }, - { 0x5C, 7 }, { 0xA8, 8 }, { 0x58, 7 }, { 0x1B3, 9 }, - { 0x40, 7 }, { 0x79, 8 }, { 0xC, 6 }, { 0x55, 7 }, - { 0x1F, 6 }, { 0xD8, 8 }, { 0x76, 7 }, { 0x23, 8 }, - { 0x5F, 7 }, { 0x78, 8 }, { 0xB, 6 }, { 0x1B, 7 }, - { 0x2D, 6 }, { 0x10, 7 }, { 0x37, 6 }, { 0x6D, 7 }, - { 0x32, 6 }, { 0xA, 6 }, { 0x1A, 5 }, { 0x1E, 5 }, - { 0x1F, 5 }, { 0x2B, 6 }, { 0xD, 5 }, { 0x77, 7 }, - { 0x31, 6 }, { 0x5D, 7 }, { 0x38, 6 }, { 0x27, 7 }, - { 0xC, 5 }, { 0xE9, 8 }, { 0x33, 6 }, { 0x5E, 7 }, - { 0x30, 6 }, { 0x4D, 7 }, { 0xA, 5 }, { 0x21, 6 }, - { 0x7, 5 }, { 0x3D, 7 }, { 0x39, 6 }, { 0xE8, 8 }, - { 0xB, 5 }, { 0x59, 7 }, { 0x14, 5 }, { 0x27, 6 }, - { 0x11, 5 }, { 0x75, 7 }, { 0xE, 5 }, { 0x9, 6 }, - { 0x8, 5 }, { 0x12, 6 }, { 0x0, 3 } - } } }; -static const uint16_t vp4_dc_bias[16][32][2] = { +static const uint8_t vp4_bias[5 * 16][32][2] = { { /* DC bias table 0 */ - { 0xC, 5 }, { 0x70, 7 }, { 0x1CA, 9 }, { 0x1CB, 9 }, - { 0x391, 10 }, { 0x1C9B, 13 }, { 0x3935, 14 }, { 0x71, 7 }, - { 0x3934, 14 }, { 0xB, 4 }, { 0xF, 4 }, { 0x19, 5 }, - { 0x2, 4 }, { 0x9, 4 }, { 0x3, 4 }, { 0x1D, 5 }, - { 0x18, 5 }, { 0x7, 4 }, { 0xD, 4 }, { 0x2, 3 }, - { 0x0, 3 }, { 0xA, 4 }, { 0x8, 4 }, { 0x1A, 6 }, - { 0x73, 7 }, { 0x6F, 8 }, { 0xE4C, 12 }, { 0x727, 11 }, - { 0x392, 10 }, { 0x390, 10 }, { 0x36, 7 }, { 0x6E, 8 } + { 20, 3 }, { 12, 4 }, { 14, 4 }, { 19, 3 }, { 0, 5 }, { 23, 6 }, + { 30, 7 }, { 31, 8 }, { 25, 8 }, { 17, 4 }, { 22, 4 }, { 13, 4 }, + { 21, 4 }, { 9, 4 }, { 16, 5 }, { 11, 5 }, { 18, 4 }, { 1, 7 }, + { 7, 7 }, { 29, 10 }, { 4, 10 }, { 28, 10 }, { 26, 12 }, { 8, 14 }, + { 6, 14 }, { 5, 13 }, { 27, 11 }, { 2, 9 }, { 3, 9 }, { 24, 7 }, + { 15, 5 }, { 10, 4 }, }, { /* DC bias table 1 */ - { 0x11, 5 }, { 0x7A, 7 }, { 0x83, 8 }, { 0x40, 7 }, - { 0x105, 9 }, { 0x413, 11 }, { 0x410, 11 }, { 0x7B, 7 }, - { 0x822, 12 }, { 0xE, 4 }, { 0x2, 3 }, { 0x2, 4 }, - { 0x6, 4 }, { 0xA, 4 }, { 0x7, 4 }, { 0x1F, 5 }, - { 0x17, 5 }, { 0x9, 4 }, { 0xD, 4 }, { 0x0, 3 }, - { 0xC, 4 }, { 0x3, 4 }, { 0x3C, 6 }, { 0x2C, 6 }, - { 0x21, 6 }, { 0x169, 9 }, { 0x412, 11 }, { 0x2D0, 10 }, - { 0x2D1, 10 }, { 0x823, 12 }, { 0x5B, 7 }, { 0xB5, 8 } + { 19, 3 }, { 11, 4 }, { 21, 4 }, { 10, 3 }, { 12, 4 }, { 14, 4 }, + { 3, 7 }, { 6, 11 }, { 8, 12 }, { 29, 12 }, { 26, 11 }, { 5, 11 }, + { 4, 9 }, { 2, 8 }, { 24, 6 }, { 0, 5 }, { 17, 4 }, { 13, 4 }, + { 23, 6 }, { 27, 10 }, { 28, 10 }, { 25, 9 }, { 31, 8 }, { 30, 7 }, + { 16, 5 }, { 20, 4 }, { 18, 4 }, { 9, 4 }, { 22, 6 }, { 1, 7 }, + { 7, 7 }, { 15, 5 }, }, { /* DC bias table 2 */ - { 0x17, 5 }, { 0x10, 6 }, { 0xB6, 8 }, { 0x22, 7 }, - { 0x16A, 9 }, { 0x2D0, 10 }, { 0xB48, 12 }, { 0x77, 7 }, - { 0x1692, 13 }, { 0x0, 3 }, { 0x3, 3 }, { 0x3, 4 }, - { 0x9, 4 }, { 0xC, 4 }, { 0x5, 4 }, { 0x2, 4 }, - { 0x1C, 5 }, { 0x8, 4 }, { 0xD, 4 }, { 0xF, 4 }, - { 0xA, 4 }, { 0x9, 5 }, { 0x23, 7 }, { 0x3A, 6 }, - { 0x2C, 6 }, { 0x16B, 9 }, { 0x5A5, 11 }, { 0x2D3, 10 }, - { 0x2D1, 10 }, { 0x1693, 13 }, { 0x76, 7 }, { 0xB7, 8 } + { 9, 3 }, { 15, 4 }, { 11, 4 }, { 1, 6 }, { 3, 7 }, { 22, 7 }, + { 21, 5 }, { 14, 4 }, { 10, 3 }, { 17, 4 }, { 12, 4 }, { 20, 4 }, + { 24, 6 }, { 5, 10 }, { 28, 10 }, { 6, 12 }, { 8, 13 }, { 29, 13 }, + { 26, 11 }, { 27, 10 }, { 4, 9 }, { 25, 9 }, { 2, 8 }, { 31, 8 }, + { 0, 5 }, { 13, 4 }, { 18, 4 }, { 16, 5 }, { 23, 6 }, { 30, 7 }, + { 7, 7 }, { 19, 4 }, }, { /* DC bias table 3 */ - { 0x1E, 5 }, { 0x13, 6 }, { 0xFB, 8 }, { 0x7C, 7 }, - { 0x46, 8 }, { 0x7D6, 11 }, { 0xFA9, 12 }, { 0x12, 6 }, - { 0x1F50, 13 }, { 0x1, 3 }, { 0x4, 3 }, { 0x5, 4 }, - { 0xA, 4 }, { 0xE, 4 }, { 0x7, 4 }, { 0x0, 4 }, - { 0x17, 5 }, { 0x6, 4 }, { 0xD, 4 }, { 0xC, 4 }, - { 0x1, 4 }, { 0x2C, 6 }, { 0x8F, 9 }, { 0x3F, 6 }, - { 0x2D, 6 }, { 0x1F4, 9 }, { 0x7D5, 11 }, { 0x8E, 9 }, - { 0x7D7, 11 }, { 0x1F51, 13 }, { 0x10, 6 }, { 0x22, 7 } + { 15, 4 }, { 20, 4 }, { 9, 3 }, { 30, 6 }, { 31, 7 }, { 4, 8 }, + { 27, 9 }, { 22, 9 }, { 7, 6 }, { 1, 6 }, { 11, 4 }, { 17, 4 }, + { 14, 4 }, { 10, 3 }, { 12, 4 }, { 21, 6 }, { 24, 6 }, { 16, 5 }, + { 19, 4 }, { 18, 4 }, { 13, 4 }, { 0, 5 }, { 3, 7 }, { 25, 9 }, + { 8, 13 }, { 29, 13 }, { 6, 12 }, { 26, 11 }, { 5, 11 }, { 28, 11 }, + { 2, 8 }, { 23, 6 }, }, { /* DC bias table 4 */ - { 0x1, 4 }, { 0x2B, 6 }, { 0x12, 7 }, { 0x55, 7 }, - { 0x27, 8 }, { 0x3B0, 10 }, { 0x762, 11 }, { 0x77, 7 }, - { 0x261, 12 }, { 0x2, 3 }, { 0x6, 3 }, { 0x7, 4 }, - { 0xB, 4 }, { 0xF, 4 }, { 0x8, 4 }, { 0x0, 4 }, - { 0x1C, 5 }, { 0x3, 4 }, { 0x9, 4 }, { 0x6, 4 }, - { 0x14, 5 }, { 0x54, 7 }, { 0x131, 11 }, { 0x5, 5 }, - { 0x3A, 6 }, { 0x1D9, 9 }, { 0x99, 10 }, { 0x4D, 9 }, - { 0x763, 11 }, { 0x260, 12 }, { 0x8, 6 }, { 0xED, 8 } + { 15, 4 }, { 0, 4 }, { 30, 6 }, { 2, 7 }, { 29, 12 }, { 8, 12 }, + { 22, 11 }, { 26, 10 }, { 27, 9 }, { 4, 8 }, { 23, 5 }, { 17, 4 }, + { 9, 3 }, { 19, 4 }, { 11, 4 }, { 14, 4 }, { 18, 4 }, { 20, 5 }, + { 21, 7 }, { 3, 7 }, { 1, 6 }, { 12, 4 }, { 10, 3 }, { 16, 5 }, + { 24, 6 }, { 5, 10 }, { 6, 11 }, { 28, 11 }, { 25, 9 }, { 31, 8 }, + { 7, 7 }, { 13, 4 }, }, { /* DC bias table 5 */ - { 0x4, 4 }, { 0x33, 6 }, { 0x60, 7 }, { 0x65, 7 }, - { 0xC2, 8 }, { 0x30D, 10 }, { 0x619, 11 }, { 0x64, 7 }, - { 0x1862, 13 }, { 0x4, 3 }, { 0x7, 3 }, { 0xA, 4 }, - { 0xB, 4 }, { 0xD, 4 }, { 0x6, 4 }, { 0x0, 4 }, - { 0xF, 5 }, { 0x3, 4 }, { 0x5, 4 }, { 0x2, 4 }, - { 0x2, 5 }, { 0x77, 8 }, { 0xC30, 12 }, { 0x3, 5 }, - { 0x31, 6 }, { 0x187, 9 }, { 0x1D9, 10 }, { 0xED, 9 }, - { 0x1D8, 10 }, { 0x1863, 13 }, { 0x1C, 6 }, { 0x3A, 7 } + { 15, 4 }, { 20, 5 }, { 23, 5 }, { 19, 4 }, { 17, 4 }, { 0, 4 }, + { 18, 4 }, { 14, 4 }, { 30, 6 }, { 31, 7 }, { 28, 10 }, { 26, 10 }, + { 27, 9 }, { 21, 8 }, { 16, 5 }, { 9, 3 }, { 11, 4 }, { 12, 4 }, + { 2, 7 }, { 4, 8 }, { 22, 12 }, { 8, 13 }, { 29, 13 }, { 6, 11 }, + { 5, 10 }, { 25, 9 }, { 24, 6 }, { 7, 7 }, { 3, 7 }, { 1, 6 }, + { 13, 4 }, { 10, 3 }, }, { /* DC bias table 6 */ - { 0x8, 4 }, { 0xA, 5 }, { 0x6A, 7 }, { 0x16, 6 }, - { 0x1E, 7 }, { 0x34E, 10 }, { 0x69F, 11 }, { 0x68, 7 }, - { 0xD28, 12 }, { 0x5, 3 }, { 0x7, 3 }, { 0x7, 4 }, - { 0xC, 4 }, { 0x0, 3 }, { 0x6, 4 }, { 0x1B, 5 }, - { 0x12, 5 }, { 0x2, 4 }, { 0x4, 4 }, { 0x13, 5 }, - { 0xE, 6 }, { 0x34B, 10 }, { 0x1A53, 13 }, { 0x6, 5 }, - { 0x17, 6 }, { 0x1A6, 9 }, { 0x69E, 11 }, { 0x1A4, 9 }, - { 0x695, 11 }, { 0x1A52, 13 }, { 0x6B, 7 }, { 0x1F, 7 } + { 13, 3 }, { 17, 4 }, { 23, 5 }, { 20, 6 }, { 4, 7 }, { 31, 7 }, + { 18, 4 }, { 1, 5 }, { 3, 6 }, { 24, 6 }, { 14, 4 }, { 11, 4 }, + { 0, 4 }, { 16, 5 }, { 19, 5 }, { 9, 3 }, { 12, 4 }, { 7, 7 }, + { 27, 9 }, { 8, 12 }, { 29, 13 }, { 22, 13 }, { 28, 11 }, { 21, 10 }, + { 25, 9 }, { 5, 10 }, { 26, 11 }, { 6, 11 }, { 2, 7 }, { 30, 7 }, + { 15, 5 }, { 10, 3 }, }, { /* DC bias table 7 */ - { 0xE, 4 }, { 0xF, 5 }, { 0x17, 6 }, { 0x25, 6 }, - { 0x9F, 8 }, { 0x138, 9 }, { 0x24B, 10 }, { 0x93, 8 }, - { 0x92A, 12 }, { 0x5, 3 }, { 0x0, 2 }, { 0x8, 4 }, - { 0xD, 4 }, { 0xF, 4 }, { 0x6, 4 }, { 0x4, 4 }, - { 0xE, 5 }, { 0x19, 5 }, { 0x18, 5 }, { 0xA, 5 }, - { 0x9E, 8 }, { 0x494, 11 }, { 0x1256, 13 }, { 0x26, 6 }, - { 0x16, 6 }, { 0x124, 9 }, { 0x4E5, 11 }, { 0x273, 10 }, - { 0x4E4, 11 }, { 0x1257, 13 }, { 0x48, 7 }, { 0x9D, 8 } + { 10, 2 }, { 15, 4 }, { 19, 5 }, { 24, 6 }, { 2, 6 }, { 14, 4 }, + { 16, 5 }, { 1, 5 }, { 11, 4 }, { 30, 7 }, { 25, 9 }, { 21, 11 }, + { 8, 12 }, { 22, 13 }, { 29, 13 }, { 6, 10 }, { 7, 8 }, { 3, 6 }, + { 23, 6 }, { 5, 9 }, { 28, 11 }, { 26, 11 }, { 27, 10 }, { 31, 8 }, + { 20, 8 }, { 4, 8 }, { 9, 3 }, { 18, 5 }, { 17, 5 }, { 12, 4 }, + { 0, 4 }, { 13, 4 }, }, { /* DC bias table 8 */ - { 0x4, 4 }, { 0x2C, 6 }, { 0x50, 7 }, { 0x1E, 7 }, - { 0x71, 9 }, { 0xE1, 10 }, { 0xE0, 10 }, { 0x1D, 7 }, - { 0x6, 6 }, { 0x7, 3 }, { 0x6, 3 }, { 0x7, 4 }, - { 0x5, 4 }, { 0x6, 4 }, { 0x15, 5 }, { 0x0, 5 }, - { 0x29, 6 }, { 0x2, 5 }, { 0x6, 5 }, { 0x1, 5 }, - { 0x23, 6 }, { 0x1F, 7 }, { 0x39, 8 }, { 0x9, 4 }, - { 0x2, 4 }, { 0x10, 5 }, { 0x7, 6 }, { 0x2D, 6 }, - { 0x2F, 6 }, { 0x2E, 6 }, { 0x22, 6 }, { 0x51, 7 } + { 15, 5 }, { 19, 5 }, { 17, 5 }, { 8, 6 }, { 26, 6 }, { 24, 4 }, + { 18, 5 }, { 6, 10 }, { 5, 10 }, { 4, 9 }, { 22, 8 }, { 7, 7 }, + { 3, 7 }, { 21, 7 }, { 0, 4 }, { 12, 4 }, { 13, 4 }, { 11, 4 }, + { 25, 5 }, { 30, 6 }, { 20, 6 }, { 23, 4 }, { 2, 7 }, { 31, 7 }, + { 16, 6 }, { 14, 5 }, { 1, 6 }, { 27, 6 }, { 29, 6 }, { 28, 6 }, + { 10, 3 }, { 9, 3 }, }, { /* DC bias table 9 */ - { 0x8, 4 }, { 0x2F, 6 }, { 0x51, 7 }, { 0x50, 7 }, - { 0x2ED, 10 }, { 0x5D9, 11 }, { 0x5D8, 11 }, { 0xBA, 8 }, - { 0x5C, 7 }, { 0x7, 3 }, { 0x6, 3 }, { 0x9, 4 }, - { 0x6, 4 }, { 0x7, 4 }, { 0x16, 5 }, { 0x5, 5 }, - { 0x2B, 6 }, { 0x6, 5 }, { 0xA, 5 }, { 0x1, 5 }, - { 0xF, 6 }, { 0x1D, 7 }, { 0x177, 9 }, { 0x4, 4 }, - { 0x1, 4 }, { 0x4, 5 }, { 0x1, 6 }, { 0x2A, 6 }, - { 0xB, 5 }, { 0x29, 6 }, { 0x0, 6 }, { 0x1C, 7 } + { 30, 6 }, { 26, 6 }, { 19, 5 }, { 24, 4 }, { 25, 5 }, { 15, 5 }, + { 17, 5 }, { 31, 7 }, { 21, 7 }, { 20, 6 }, { 23, 4 }, { 18, 5 }, + { 28, 5 }, { 12, 4 }, { 13, 4 }, { 0, 4 }, { 11, 4 }, { 3, 7 }, + { 2, 7 }, { 29, 6 }, { 27, 6 }, { 16, 6 }, { 14, 5 }, { 8, 7 }, + { 7, 8 }, { 6, 11 }, { 5, 11 }, { 4, 10 }, { 22, 9 }, { 1, 6 }, + { 10, 3 }, { 9, 3 }, }, { /* DC bias table 10 */ - { 0xA, 4 }, { 0x3C, 6 }, { 0x74, 7 }, { 0x4E, 7 }, - { 0x26D, 10 }, { 0x4D9, 11 }, { 0x4D8, 11 }, { 0x9A, 8 }, - { 0x4C, 7 }, { 0x0, 2 }, { 0x6, 3 }, { 0x8, 4 }, - { 0x7, 4 }, { 0x6, 4 }, { 0x16, 5 }, { 0x8, 5 }, - { 0x2E, 6 }, { 0xA, 5 }, { 0xB, 5 }, { 0x3D, 6 }, - { 0x24, 6 }, { 0xEB, 8 }, { 0x137, 9 }, { 0x1F, 5 }, - { 0x1C, 5 }, { 0x3B, 6 }, { 0x12, 6 }, { 0x25, 6 }, - { 0x2F, 6 }, { 0x13, 6 }, { 0x4F, 7 }, { 0xEA, 8 } + { 9, 2 }, { 15, 5 }, { 26, 6 }, { 29, 6 }, { 17, 5 }, { 18, 5 }, + { 13, 4 }, { 12, 4 }, { 11, 4 }, { 20, 6 }, { 27, 6 }, { 8, 7 }, + { 7, 8 }, { 6, 11 }, { 5, 11 }, { 4, 10 }, { 22, 9 }, { 3, 7 }, + { 30, 7 }, { 0, 4 }, { 14, 5 }, { 16, 6 }, { 28, 6 }, { 10, 3 }, + { 24, 5 }, { 2, 7 }, { 31, 8 }, { 21, 8 }, { 25, 6 }, { 1, 6 }, + { 19, 6 }, { 23, 5 }, }, { /* DC bias table 11 */ - { 0xA, 4 }, { 0xA, 5 }, { 0x3, 6 }, { 0x16, 6 }, - { 0x9, 8 }, { 0x21, 10 }, { 0x20, 10 }, { 0xB3, 8 }, - { 0x58, 7 }, { 0x7, 3 }, { 0x6, 3 }, { 0x7, 4 }, - { 0x6, 4 }, { 0x4, 4 }, { 0x13, 5 }, { 0x2, 5 }, - { 0x25, 6 }, { 0x0, 5 }, { 0x3, 5 }, { 0x2D, 6 }, - { 0x5D, 7 }, { 0xB2, 8 }, { 0x11, 9 }, { 0x8, 4 }, - { 0x2, 4 }, { 0x6, 5 }, { 0x17, 6 }, { 0x2F, 6 }, - { 0x7, 5 }, { 0x24, 6 }, { 0x5C, 7 }, { 0x5, 7 } + { 17, 5 }, { 6, 10 }, { 5, 10 }, { 22, 9 }, { 4, 8 }, { 31, 7 }, + { 2, 6 }, { 15, 5 }, { 18, 5 }, { 24, 4 }, { 25, 5 }, { 28, 5 }, + { 13, 4 }, { 1, 5 }, { 3, 6 }, { 26, 6 }, { 12, 4 }, { 11, 4 }, + { 23, 4 }, { 29, 6 }, { 16, 6 }, { 14, 5 }, { 0, 4 }, { 8, 7 }, + { 21, 8 }, { 7, 8 }, { 19, 6 }, { 30, 7 }, { 20, 7 }, { 27, 6 }, + { 10, 3 }, { 9, 3 }, }, { /* DC bias table 12 */ - { 0xB, 4 }, { 0x13, 5 }, { 0x1F, 6 }, { 0x31, 6 }, - { 0x21, 7 }, { 0x295, 10 }, { 0x528, 11 }, { 0xA4, 8 }, - { 0x3C, 7 }, { 0x0, 2 }, { 0x7, 3 }, { 0x6, 4 }, - { 0x5, 4 }, { 0x1B, 5 }, { 0x12, 5 }, { 0x32, 6 }, - { 0x1D, 6 }, { 0x2B, 6 }, { 0x30, 6 }, { 0x1C, 6 }, - { 0x3D, 7 }, { 0x14B, 9 }, { 0x529, 11 }, { 0x8, 4 }, - { 0x1A, 5 }, { 0x33, 6 }, { 0x11, 6 }, { 0x2A, 6 }, - { 0x9, 5 }, { 0x28, 6 }, { 0x53, 7 }, { 0x20, 7 } + { 9, 2 }, { 31, 7 }, { 4, 7 }, { 26, 6 }, { 28, 5 }, { 12, 4 }, + { 11, 4 }, { 19, 6 }, { 16, 6 }, { 8, 7 }, { 20, 7 }, { 2, 6 }, + { 23, 4 }, { 14, 5 }, { 1, 5 }, { 29, 6 }, { 7, 8 }, { 6, 11 }, + { 22, 11 }, { 5, 10 }, { 21, 9 }, { 30, 7 }, { 27, 6 }, { 17, 6 }, + { 0, 4 }, { 18, 6 }, { 3, 6 }, { 15, 6 }, { 25, 6 }, { 24, 5 }, + { 13, 5 }, { 10, 3 }, }, { /* DC bias table 13 */ - { 0xE, 4 }, { 0x15, 5 }, { 0x29, 6 }, { 0x3F, 6 }, - { 0x4D, 7 }, { 0x2F1, 10 }, { 0x5E0, 11 }, { 0x92, 8 }, - { 0x48, 7 }, { 0x0, 2 }, { 0x6, 3 }, { 0x6, 4 }, - { 0x5, 4 }, { 0x4, 4 }, { 0xF, 5 }, { 0x2E, 6 }, - { 0x1D, 6 }, { 0x28, 6 }, { 0x27, 6 }, { 0x5F, 7 }, - { 0xBD, 8 }, { 0x179, 9 }, { 0x5E1, 11 }, { 0x8, 4 }, - { 0x1E, 5 }, { 0x2D, 6 }, { 0x1C, 6 }, { 0x2C, 6 }, - { 0x3E, 6 }, { 0x25, 6 }, { 0x4C, 7 }, { 0x93, 8 } + { 9, 2 }, { 13, 4 }, { 12, 4 }, { 11, 4 }, { 26, 6 }, { 16, 6 }, + { 14, 5 }, { 23, 4 }, { 8, 7 }, { 7, 8 }, { 31, 8 }, { 29, 6 }, + { 30, 7 }, { 4, 7 }, { 18, 6 }, { 17, 6 }, { 2, 6 }, { 1, 5 }, + { 27, 6 }, { 25, 6 }, { 15, 6 }, { 6, 11 }, { 22, 11 }, { 5, 10 }, + { 21, 9 }, { 20, 8 }, { 19, 7 }, { 10, 3 }, { 0, 4 }, { 24, 5 }, + { 28, 6 }, { 3, 6 }, }, { /* DC bias table 14 */ - { 0xC, 4 }, { 0x17, 5 }, { 0x35, 6 }, { 0x13, 5 }, - { 0x21, 6 }, { 0xAD, 8 }, { 0x6F1, 11 }, { 0x1BD, 9 }, - { 0xD9, 8 }, { 0x0, 2 }, { 0x7, 3 }, { 0x7, 4 }, - { 0x6, 4 }, { 0x4, 4 }, { 0x11, 5 }, { 0x2A, 6 }, - { 0x6E, 7 }, { 0x25, 6 }, { 0x24, 6 }, { 0x57, 7 }, - { 0xD8, 8 }, { 0x379, 10 }, { 0x6F0, 11 }, { 0x5, 4 }, - { 0x16, 5 }, { 0x29, 6 }, { 0x6D, 7 }, { 0x28, 6 }, - { 0x34, 6 }, { 0x20, 6 }, { 0xDF, 8 }, { 0xAC, 8 } + { 9, 2 }, { 13, 4 }, { 23, 4 }, { 12, 4 }, { 11, 4 }, { 29, 6 }, + { 4, 6 }, { 14, 5 }, { 18, 6 }, { 17, 6 }, { 3, 5 }, { 27, 6 }, + { 25, 6 }, { 15, 6 }, { 31, 8 }, { 5, 8 }, { 19, 7 }, { 24, 5 }, + { 1, 5 }, { 0, 4 }, { 28, 6 }, { 2, 6 }, { 20, 8 }, { 8, 8 }, + { 26, 7 }, { 16, 7 }, { 22, 11 }, { 6, 11 }, { 21, 10 }, { 7, 9 }, + { 30, 8 }, { 10, 3 }, }, { /* DC bias table 15 */ - { 0x0, 3 }, { 0x1A, 5 }, { 0x6, 5 }, { 0x19, 5 }, - { 0x30, 6 }, { 0x5A, 7 }, { 0x18A, 9 }, { 0x2DD, 10 }, - { 0x18B, 9 }, { 0x1, 2 }, { 0x7, 3 }, { 0xA, 4 }, - { 0x9, 4 }, { 0x2, 4 }, { 0x10, 5 }, { 0x2E, 6 }, - { 0x6E, 7 }, { 0x2C, 6 }, { 0xE, 6 }, { 0x5E, 7 }, - { 0xC4, 8 }, { 0x5B9, 11 }, { 0x5B8, 11 }, { 0x11, 5 }, - { 0x36, 6 }, { 0x5F, 7 }, { 0x1E, 7 }, { 0x63, 7 }, - { 0x6F, 7 }, { 0x1F, 7 }, { 0xB6, 8 }, { 0x16F, 9 } - } -}; - -static const uint16_t vp4_ac_bias_0[16][32][2] = { + { 0, 3 }, { 13, 4 }, { 2, 5 }, { 18, 6 }, { 26, 7 }, { 29, 7 }, + { 9, 2 }, { 14, 5 }, { 23, 5 }, { 12, 4 }, { 11, 4 }, { 17, 6 }, + { 5, 7 }, { 30, 8 }, { 22, 11 }, { 21, 11 }, { 7, 10 }, { 31, 9 }, + { 15, 6 }, { 19, 7 }, { 25, 7 }, { 4, 6 }, { 20, 8 }, { 6, 9 }, + { 8, 9 }, { 27, 7 }, { 3, 5 }, { 1, 5 }, { 24, 6 }, { 16, 7 }, + { 28, 7 }, { 10, 3 }, + }, { /* AC bias group 1, table 0 */ - { 0x6, 5 }, { 0x1E, 7 }, { 0x1CC, 9 }, { 0x1CE, 9 }, - { 0x734, 11 }, { 0x1CD5, 13 }, { 0x1CD4, 13 }, { 0x18, 5 }, - { 0xE6B, 12 }, { 0x0, 3 }, { 0xF, 4 }, { 0x6, 4 }, - { 0x7, 4 }, { 0xD, 4 }, { 0x8, 4 }, { 0x2, 4 }, - { 0x19, 5 }, { 0x5, 4 }, { 0xB, 4 }, { 0xA, 4 }, - { 0x1D, 5 }, { 0x27, 6 }, { 0x1CF, 9 }, { 0x4, 4 }, - { 0x38, 6 }, { 0xE, 6 }, { 0x4C, 7 }, { 0x1F, 7 }, - { 0x4D, 7 }, { 0x39B, 10 }, { 0x12, 5 }, { 0x72, 7 } + { 9, 3 }, { 15, 4 }, { 0, 5 }, { 25, 6 }, { 1, 7 }, { 27, 7 }, + { 23, 4 }, { 17, 4 }, { 11, 4 }, { 12, 4 }, { 14, 4 }, { 30, 5 }, + { 26, 7 }, { 28, 7 }, { 21, 6 }, { 19, 4 }, { 18, 4 }, { 7, 5 }, + { 16, 5 }, { 13, 4 }, { 24, 6 }, { 31, 7 }, { 2, 9 }, { 4, 11 }, + { 6, 13 }, { 5, 13 }, { 8, 12 }, { 29, 10 }, { 3, 9 }, { 22, 9 }, + { 20, 5 }, { 10, 4 }, }, { /* AC bias group 1, table 1 */ - { 0x9, 5 }, { 0x4B, 7 }, { 0x90, 8 }, { 0x91, 8 }, - { 0x745, 11 }, { 0x1D11, 13 }, { 0x1D10, 13 }, { 0x19, 5 }, - { 0xE89, 12 }, { 0x0, 3 }, { 0xF, 4 }, { 0x8, 4 }, - { 0x7, 4 }, { 0xD, 4 }, { 0xB, 4 }, { 0x2, 4 }, - { 0x1C, 5 }, { 0x3, 4 }, { 0xA, 4 }, { 0x5, 4 }, - { 0x18, 5 }, { 0x10, 6 }, { 0x1D0, 9 }, { 0x6, 4 }, - { 0x3B, 6 }, { 0x11, 6 }, { 0x4A, 7 }, { 0x49, 7 }, - { 0xE9, 8 }, { 0x3A3, 10 }, { 0x13, 5 }, { 0x75, 7 } + { 9, 3 }, { 15, 4 }, { 17, 4 }, { 21, 6 }, { 25, 6 }, { 0, 5 }, + { 19, 4 }, { 23, 4 }, { 12, 4 }, { 11, 4 }, { 2, 8 }, { 3, 8 }, + { 27, 7 }, { 26, 7 }, { 1, 7 }, { 30, 5 }, { 18, 4 }, { 14, 4 }, + { 20, 5 }, { 7, 5 }, { 13, 4 }, { 16, 5 }, { 22, 9 }, { 6, 13 }, + { 5, 13 }, { 8, 12 }, { 4, 11 }, { 29, 10 }, { 28, 8 }, { 31, 7 }, + { 24, 6 }, { 10, 4 }, }, { /* AC bias group 1, table 2 */ - { 0x19, 5 }, { 0x74, 7 }, { 0x1D, 8 }, { 0xEA, 8 }, - { 0x73, 10 }, { 0x1CA, 12 }, { 0x396, 13 }, { 0x1C, 5 }, - { 0xE4, 11 }, { 0x2, 3 }, { 0x1, 3 }, { 0x7, 4 }, - { 0x8, 4 }, { 0xD, 4 }, { 0x9, 4 }, { 0x1F, 5 }, - { 0x18, 5 }, { 0x0, 4 }, { 0x6, 4 }, { 0x1E, 5 }, - { 0x3B, 6 }, { 0xEB, 8 }, { 0x397, 13 }, { 0xA, 4 }, - { 0x2, 5 }, { 0x2C, 6 }, { 0x5B, 7 }, { 0x5A, 7 }, - { 0xF, 7 }, { 0x38, 9 }, { 0x17, 5 }, { 0x6, 6 } + { 17, 4 }, { 24, 5 }, { 31, 6 }, { 29, 9 }, { 8, 11 }, { 5, 12 }, + { 6, 13 }, { 22, 13 }, { 4, 10 }, { 2, 8 }, { 28, 7 }, { 10, 3 }, + { 9, 3 }, { 18, 4 }, { 11, 4 }, { 12, 4 }, { 14, 4 }, { 23, 4 }, + { 25, 6 }, { 27, 7 }, { 26, 7 }, { 30, 5 }, { 16, 5 }, { 0, 5 }, + { 13, 4 }, { 7, 5 }, { 1, 7 }, { 3, 8 }, { 21, 8 }, { 20, 6 }, + { 19, 5 }, { 15, 5 }, }, { /* AC bias group 1, table 3 */ - { 0x1E, 5 }, { 0x6F, 7 }, { 0xAE, 8 }, { 0xAF, 8 }, - { 0x187, 10 }, { 0x61B, 12 }, { 0xC35, 13 }, { 0x1A, 5 }, - { 0x30C, 11 }, { 0x2, 3 }, { 0x1, 3 }, { 0x7, 4 }, - { 0x8, 4 }, { 0xE, 4 }, { 0x9, 4 }, { 0x1F, 5 }, - { 0x14, 5 }, { 0x0, 4 }, { 0x1, 4 }, { 0x19, 5 }, - { 0x2A, 6 }, { 0x60, 8 }, { 0xC34, 13 }, { 0xB, 4 }, - { 0xD, 5 }, { 0x36, 6 }, { 0x6E, 7 }, { 0x56, 7 }, - { 0x31, 7 }, { 0xC2, 9 }, { 0x18, 5 }, { 0x19, 6 } + { 17, 4 }, { 18, 4 }, { 10, 3 }, { 9, 3 }, { 21, 8 }, { 29, 9 }, + { 8, 11 }, { 22, 13 }, { 6, 13 }, { 5, 12 }, { 4, 10 }, { 28, 7 }, + { 31, 6 }, { 24, 5 }, { 11, 4 }, { 12, 4 }, { 14, 4 }, { 16, 5 }, + { 20, 6 }, { 27, 7 }, { 2, 8 }, { 3, 8 }, { 23, 4 }, { 30, 5 }, + { 19, 5 }, { 7, 5 }, { 25, 6 }, { 26, 7 }, { 1, 7 }, { 13, 4 }, + { 0, 5 }, { 15, 5 }, }, { /* AC bias group 1, table 4 */ - { 0x1, 4 }, { 0x2C, 6 }, { 0x5, 7 }, { 0x15, 7 }, - { 0x8, 8 }, { 0x97, 12 }, { 0x12D, 13 }, { 0x17, 5 }, - { 0x4A, 11 }, { 0x3, 3 }, { 0x2, 3 }, { 0x9, 4 }, - { 0xA, 4 }, { 0xE, 4 }, { 0x8, 4 }, { 0x1F, 5 }, - { 0x7, 5 }, { 0x1E, 5 }, { 0x1B, 5 }, { 0x4, 5 }, - { 0x5A, 7 }, { 0x24, 10 }, { 0x12C, 13 }, { 0xC, 4 }, - { 0x6, 5 }, { 0x0, 5 }, { 0x3, 6 }, { 0x5B, 7 }, - { 0x14, 7 }, { 0x13, 9 }, { 0x1A, 5 }, { 0xB, 6 } + { 25, 5 }, { 4, 8 }, { 21, 10 }, { 8, 11 }, { 22, 13 }, { 6, 13 }, + { 5, 12 }, { 29, 9 }, { 2, 7 }, { 26, 6 }, { 0, 4 }, { 19, 5 }, + { 28, 7 }, { 3, 7 }, { 31, 6 }, { 24, 5 }, { 16, 5 }, { 10, 3 }, + { 9, 3 }, { 14, 4 }, { 11, 4 }, { 12, 4 }, { 1, 6 }, { 20, 7 }, + { 27, 7 }, { 7, 5 }, { 23, 4 }, { 30, 5 }, { 18, 5 }, { 13, 4 }, + { 17, 5 }, { 15, 5 }, }, { /* AC bias group 1, table 5 */ - { 0x4, 4 }, { 0x0, 5 }, { 0x17, 7 }, { 0x63, 7 }, - { 0x18B, 9 }, { 0x310, 10 }, { 0xC44, 12 }, { 0x19, 5 }, - { 0x623, 11 }, { 0x4, 3 }, { 0x3, 3 }, { 0xA, 4 }, - { 0xB, 4 }, { 0xD, 4 }, { 0x3, 4 }, { 0x1C, 5 }, - { 0x3, 5 }, { 0xA, 5 }, { 0x4, 5 }, { 0x3, 6 }, - { 0x18A, 9 }, { 0x188B, 13 }, { 0x188A, 13 }, { 0xF, 4 }, - { 0xB, 5 }, { 0x2, 5 }, { 0xA, 6 }, { 0x2, 6 }, - { 0x16, 7 }, { 0x189, 9 }, { 0x1D, 5 }, { 0x30, 6 } + { 1, 5 }, { 27, 6 }, { 19, 6 }, { 25, 5 }, { 16, 5 }, { 18, 5 }, + { 26, 6 }, { 28, 7 }, { 2, 7 }, { 14, 4 }, { 0, 4 }, { 17, 5 }, + { 24, 5 }, { 10, 3 }, { 9, 3 }, { 11, 4 }, { 12, 4 }, { 31, 6 }, + { 5, 10 }, { 6, 12 }, { 22, 13 }, { 21, 13 }, { 8, 11 }, { 29, 9 }, + { 20, 9 }, { 4, 9 }, { 3, 7 }, { 7, 5 }, { 13, 4 }, { 15, 5 }, + { 30, 5 }, { 23, 4 }, }, { /* AC bias group 1, table 6 */ - { 0xD, 4 }, { 0x3, 5 }, { 0x77, 7 }, { 0xD, 6 }, - { 0x82, 8 }, { 0x20D, 10 }, { 0x830, 12 }, { 0x19, 5 }, - { 0x419, 11 }, { 0x3, 3 }, { 0x2, 3 }, { 0xA, 4 }, - { 0x9, 4 }, { 0xB, 4 }, { 0x2, 4 }, { 0x11, 5 }, - { 0x39, 6 }, { 0x2, 5 }, { 0x21, 6 }, { 0x40, 7 }, - { 0x1063, 13 }, { 0x20C5, 14 }, { 0x20C4, 14 }, { 0xF, 4 }, - { 0x18, 5 }, { 0x7, 5 }, { 0x38, 6 }, { 0xC, 6 }, - { 0x76, 7 }, { 0x107, 9 }, { 0x0, 4 }, { 0x3A, 6 } + { 30, 4 }, { 17, 5 }, { 1, 5 }, { 14, 4 }, { 27, 6 }, { 3, 6 }, + { 25, 5 }, { 10, 3 }, { 9, 3 }, { 19, 7 }, { 4, 8 }, { 6, 12 }, + { 22, 14 }, { 21, 14 }, { 20, 13 }, { 8, 11 }, { 5, 10 }, { 29, 9 }, + { 18, 6 }, { 15, 5 }, { 12, 4 }, { 11, 4 }, { 13, 4 }, { 24, 5 }, + { 7, 5 }, { 0, 4 }, { 26, 6 }, { 16, 6 }, { 31, 6 }, { 28, 7 }, + { 2, 7 }, { 23, 4 }, }, { /* AC bias group 1, table 7 */ - { 0xF, 4 }, { 0x1C, 5 }, { 0x36, 6 }, { 0x8, 5 }, - { 0x61, 7 }, { 0x91, 8 }, { 0x243, 10 }, { 0x9, 5 }, - { 0x120, 9 }, { 0x5, 3 }, { 0x3, 3 }, { 0x8, 4 }, - { 0x5, 4 }, { 0x1, 4 }, { 0x13, 5 }, { 0x31, 6 }, - { 0x76, 7 }, { 0x60, 7 }, { 0x93, 8 }, { 0x909, 12 }, - { 0x908, 12 }, { 0x90B, 12 }, { 0x90A, 12 }, { 0x1, 3 }, - { 0x1A, 5 }, { 0x19, 5 }, { 0x3A, 6 }, { 0x25, 6 }, - { 0x77, 7 }, { 0x92, 8 }, { 0x0, 4 }, { 0x37, 6 } + { 30, 4 }, { 13, 4 }, { 23, 3 }, { 3, 5 }, { 7, 5 }, { 12, 4 }, + { 10, 3 }, { 11, 4 }, { 8, 9 }, { 20, 12 }, { 19, 12 }, { 22, 12 }, + { 21, 12 }, { 6, 10 }, { 5, 8 }, { 29, 8 }, { 18, 8 }, { 27, 6 }, + { 14, 5 }, { 9, 3 }, { 17, 7 }, { 4, 7 }, { 15, 6 }, { 25, 5 }, + { 24, 5 }, { 2, 6 }, { 31, 6 }, { 1, 5 }, { 26, 6 }, { 16, 7 }, + { 28, 7 }, { 0, 4 }, }, { /* AC bias group 1, table 8 */ - { 0x1F, 5 }, { 0x79, 7 }, { 0xF1, 8 }, { 0xF0, 8 }, - { 0x11B, 10 }, { 0x469, 12 }, { 0x468, 12 }, { 0x3B, 6 }, - { 0x22, 7 }, { 0x5, 3 }, { 0x4, 3 }, { 0x7, 4 }, - { 0x5, 4 }, { 0x6, 4 }, { 0x1C, 5 }, { 0x1, 5 }, - { 0x35, 6 }, { 0x3D, 6 }, { 0x3A, 6 }, { 0x10, 6 }, - { 0x47, 8 }, { 0x8C, 9 }, { 0x235, 11 }, { 0x1, 3 }, - { 0x1, 4 }, { 0x19, 5 }, { 0x0, 5 }, { 0x30, 6 }, - { 0x9, 5 }, { 0x31, 6 }, { 0x1B, 5 }, { 0x34, 6 } + { 26, 5 }, { 15, 5 }, { 24, 4 }, { 23, 3 }, { 19, 6 }, { 8, 7 }, + { 21, 9 }, { 6, 12 }, { 5, 12 }, { 22, 11 }, { 4, 10 }, { 20, 8 }, + { 28, 5 }, { 12, 4 }, { 13, 4 }, { 11, 4 }, { 10, 3 }, { 9, 3 }, + { 27, 6 }, { 29, 6 }, { 25, 5 }, { 31, 6 }, { 16, 6 }, { 30, 5 }, + { 14, 5 }, { 18, 6 }, { 7, 6 }, { 3, 8 }, { 2, 8 }, { 1, 7 }, + { 17, 6 }, { 0, 5 }, }, { /* AC bias group 1, table 9 */ - { 0x3, 4 }, { 0x1B, 6 }, { 0xF3, 8 }, { 0xFD, 8 }, - { 0x3C9, 10 }, { 0xF20, 12 }, { 0x1E42, 13 }, { 0x3D, 6 }, - { 0xFC, 8 }, { 0x6, 3 }, { 0x4, 3 }, { 0x2, 4 }, - { 0x0, 4 }, { 0x1, 4 }, { 0x17, 5 }, { 0x3E, 6 }, - { 0x1A, 6 }, { 0x39, 6 }, { 0x2B, 6 }, { 0x78, 7 }, - { 0x1E5, 9 }, { 0x791, 11 }, { 0x1E43, 13 }, { 0x2, 3 }, - { 0x7, 4 }, { 0x1D, 5 }, { 0xC, 5 }, { 0x38, 6 }, - { 0x14, 5 }, { 0x7F, 7 }, { 0x16, 5 }, { 0x2A, 6 } + { 12, 4 }, { 13, 4 }, { 11, 4 }, { 0, 4 }, { 23, 3 }, { 26, 5 }, + { 16, 6 }, { 1, 6 }, { 24, 4 }, { 10, 3 }, { 28, 5 }, { 31, 6 }, + { 18, 6 }, { 30, 5 }, { 14, 5 }, { 9, 3 }, { 27, 6 }, { 17, 6 }, + { 25, 5 }, { 19, 7 }, { 5, 12 }, { 6, 13 }, { 22, 13 }, { 21, 11 }, + { 4, 10 }, { 20, 9 }, { 2, 8 }, { 7, 6 }, { 15, 6 }, { 8, 8 }, + { 3, 8 }, { 29, 7 }, }, { /* AC bias group 1, table 10 */ - { 0x7, 4 }, { 0x39, 6 }, { 0x51, 7 }, { 0x78, 7 }, - { 0x3CB, 10 }, { 0xF29, 12 }, { 0x1E51, 13 }, { 0x3D, 6 }, - { 0xF3, 8 }, { 0x6, 3 }, { 0x4, 3 }, { 0x2, 4 }, - { 0x0, 4 }, { 0x1, 4 }, { 0x17, 5 }, { 0x3E, 6 }, - { 0x7F, 7 }, { 0x2B, 6 }, { 0x7E, 7 }, { 0x50, 7 }, - { 0x1E4, 9 }, { 0x795, 11 }, { 0x1E50, 13 }, { 0x2, 3 }, - { 0x6, 4 }, { 0x1D, 5 }, { 0x6, 5 }, { 0x38, 6 }, - { 0x7, 5 }, { 0x29, 6 }, { 0x16, 5 }, { 0x2A, 6 } + { 12, 4 }, { 13, 4 }, { 11, 4 }, { 26, 5 }, { 28, 5 }, { 23, 3 }, + { 24, 4 }, { 0, 4 }, { 10, 3 }, { 19, 7 }, { 2, 7 }, { 29, 6 }, + { 31, 6 }, { 17, 6 }, { 30, 5 }, { 14, 5 }, { 9, 3 }, { 27, 6 }, + { 1, 6 }, { 25, 5 }, { 3, 7 }, { 20, 9 }, { 22, 13 }, { 6, 13 }, + { 5, 12 }, { 21, 11 }, { 4, 10 }, { 8, 8 }, { 7, 6 }, { 15, 6 }, + { 18, 7 }, { 16, 7 }, }, { /* AC bias group 1, table 11 */ - { 0x8, 4 }, { 0x3B, 6 }, { 0x1D, 7 }, { 0x72, 7 }, - { 0x1CC, 9 }, { 0x734, 11 }, { 0x1CD5, 13 }, { 0x3A, 6 }, - { 0x1C, 7 }, { 0x6, 3 }, { 0x5, 3 }, { 0x2, 4 }, - { 0x1, 4 }, { 0x0, 4 }, { 0x12, 5 }, { 0x3E, 6 }, - { 0x7F, 7 }, { 0x1E, 6 }, { 0x7E, 7 }, { 0xE7, 8 }, - { 0x39B, 10 }, { 0xE6B, 12 }, { 0x1CD4, 13 }, { 0x2, 3 }, - { 0x6, 4 }, { 0x1E, 5 }, { 0xE, 5 }, { 0x38, 6 }, - { 0x6, 5 }, { 0xF, 6 }, { 0x13, 5 }, { 0x1F, 6 } + { 13, 4 }, { 12, 4 }, { 11, 4 }, { 28, 5 }, { 8, 7 }, { 2, 7 }, + { 29, 6 }, { 23, 3 }, { 24, 4 }, { 26, 5 }, { 17, 6 }, { 31, 6 }, + { 0, 4 }, { 14, 5 }, { 30, 5 }, { 10, 3 }, { 9, 3 }, { 27, 6 }, + { 3, 7 }, { 4, 9 }, { 5, 11 }, { 22, 13 }, { 6, 13 }, { 21, 12 }, + { 20, 10 }, { 19, 8 }, { 7, 6 }, { 1, 6 }, { 25, 5 }, { 15, 6 }, + { 18, 7 }, { 16, 7 }, }, { /* AC bias group 1, table 12 */ - { 0xD, 4 }, { 0x3F, 6 }, { 0x73, 7 }, { 0xC, 6 }, - { 0xE4, 8 }, { 0x72B, 11 }, { 0xE54, 12 }, { 0x3A, 6 }, - { 0x1A, 7 }, { 0x5, 3 }, { 0x4, 3 }, { 0x2, 4 }, - { 0x1, 4 }, { 0x0, 4 }, { 0x7, 5 }, { 0x38, 6 }, - { 0x76, 7 }, { 0x77, 7 }, { 0x1B, 7 }, { 0x1CB, 9 }, - { 0x394, 10 }, { 0x1CAB, 13 }, { 0x1CAA, 13 }, { 0x2, 3 }, - { 0x6, 4 }, { 0x1E, 5 }, { 0xE, 5 }, { 0x3E, 6 }, - { 0x19, 5 }, { 0x1F, 6 }, { 0x18, 5 }, { 0x1E, 6 } + { 13, 4 }, { 12, 4 }, { 11, 4 }, { 3, 6 }, { 8, 7 }, { 18, 7 }, + { 14, 5 }, { 23, 3 }, { 24, 4 }, { 26, 5 }, { 31, 6 }, { 29, 6 }, + { 10, 3 }, { 9, 3 }, { 30, 5 }, { 28, 5 }, { 0, 4 }, { 15, 6 }, + { 4, 8 }, { 20, 10 }, { 6, 12 }, { 22, 13 }, { 21, 13 }, { 5, 11 }, + { 19, 9 }, { 2, 7 }, { 7, 6 }, { 16, 7 }, { 17, 7 }, { 25, 5 }, + { 27, 6 }, { 1, 6 }, }, { /* AC bias group 1, table 13 */ - { 0xE, 4 }, { 0x7, 5 }, { 0xC, 6 }, { 0x1C, 6 }, - { 0xBD, 8 }, { 0x2F3, 10 }, { 0xBC9, 12 }, { 0x1F, 6 }, - { 0xBF, 8 }, { 0x6, 3 }, { 0x4, 3 }, { 0x2, 4 }, - { 0x1, 4 }, { 0x1E, 5 }, { 0x1, 5 }, { 0xD, 6 }, - { 0x3A, 7 }, { 0x3B, 7 }, { 0xBE, 8 }, { 0x178, 9 }, - { 0x5E5, 11 }, { 0x1791, 13 }, { 0x1790, 13 }, { 0x2, 3 }, - { 0x6, 4 }, { 0x1F, 5 }, { 0x16, 5 }, { 0x0, 5 }, - { 0x15, 5 }, { 0x2E, 6 }, { 0x14, 5 }, { 0x1E, 6 } + { 27, 5 }, { 14, 5 }, { 12, 4 }, { 11, 4 }, { 2, 6 }, { 15, 6 }, + { 1, 5 }, { 23, 3 }, { 24, 4 }, { 3, 6 }, { 16, 7 }, { 17, 7 }, + { 31, 6 }, { 7, 6 }, { 10, 3 }, { 30, 5 }, { 28, 5 }, { 26, 5 }, + { 29, 6 }, { 19, 9 }, { 22, 13 }, { 21, 13 }, { 6, 12 }, { 20, 11 }, + { 5, 10 }, { 4, 8 }, { 18, 8 }, { 8, 8 }, { 9, 3 }, { 0, 4 }, + { 13, 5 }, { 25, 5 }, }, { /* AC bias group 1, table 14 */ - { 0x0, 3 }, { 0x1B, 5 }, { 0x31, 6 }, { 0x3A, 6 }, - { 0x60, 7 }, { 0x6F, 9 }, { 0x1B9, 11 }, { 0xE, 6 }, - { 0x1A, 7 }, { 0x5, 3 }, { 0x3, 3 }, { 0x2, 4 }, - { 0x1F, 5 }, { 0x1A, 5 }, { 0x39, 6 }, { 0xC, 6 }, - { 0xC3, 8 }, { 0xC2, 8 }, { 0x36, 8 }, { 0xDD, 10 }, - { 0x370, 12 }, { 0x6E3, 13 }, { 0x6E2, 13 }, { 0x2, 3 }, - { 0x8, 4 }, { 0x1E, 5 }, { 0x19, 5 }, { 0x3B, 6 }, - { 0x12, 5 }, { 0xF, 6 }, { 0x13, 5 }, { 0x38, 6 } + { 0, 3 }, { 11, 4 }, { 15, 6 }, { 8, 7 }, { 18, 8 }, { 20, 12 }, + { 22, 13 }, { 21, 13 }, { 6, 11 }, { 19, 10 }, { 5, 9 }, { 7, 6 }, + { 29, 6 }, { 23, 3 }, { 10, 3 }, { 24, 4 }, { 28, 5 }, { 30, 5 }, + { 9, 3 }, { 4, 7 }, { 17, 8 }, { 16, 8 }, { 2, 6 }, { 26, 5 }, + { 13, 5 }, { 1, 5 }, { 31, 6 }, { 14, 6 }, { 3, 6 }, { 27, 6 }, + { 25, 5 }, { 12, 5 }, }, { /* AC bias group 1, table 15 */ - { 0x2, 3 }, { 0x0, 4 }, { 0x3, 5 }, { 0x1C, 5 }, - { 0x32, 6 }, { 0x1C, 7 }, { 0x199, 9 }, { 0x4, 6 }, - { 0xCD, 8 }, { 0x4, 3 }, { 0x3, 3 }, { 0x1B, 5 }, - { 0x1A, 5 }, { 0x3D, 6 }, { 0x67, 7 }, { 0x3B, 8 }, - { 0x198, 9 }, { 0x75, 9 }, { 0xE9, 10 }, { 0x3A1, 12 }, - { 0x3A0, 12 }, { 0x3A3, 12 }, { 0x3A2, 12 }, { 0x5, 3 }, - { 0x2, 4 }, { 0x1F, 5 }, { 0x1D, 5 }, { 0x3C, 6 }, - { 0x18, 5 }, { 0xF, 6 }, { 0x6, 5 }, { 0x5, 6 } - } -}; - -static const uint16_t vp4_ac_bias_1[16][32][2] = { + { 1, 4 }, { 7, 6 }, { 31, 6 }, { 2, 5 }, { 24, 4 }, { 30, 5 }, + { 5, 7 }, { 20, 12 }, { 19, 12 }, { 22, 12 }, { 21, 12 }, { 18, 10 }, + { 17, 9 }, { 15, 8 }, { 29, 6 }, { 0, 3 }, { 10, 3 }, { 9, 3 }, + { 23, 3 }, { 28, 5 }, { 4, 6 }, { 16, 9 }, { 6, 9 }, { 8, 8 }, + { 14, 7 }, { 12, 5 }, { 11, 5 }, { 3, 5 }, { 26, 5 }, { 27, 6 }, + { 13, 6 }, { 25, 5 }, + }, { /* AC bias group 2, table 0 */ - { 0x4, 5 }, { 0xF5, 8 }, { 0x182, 9 }, { 0x60F, 11 }, - { 0x1839, 13 }, { 0x1838, 13 }, { 0x183B, 13 }, { 0x13, 5 }, - { 0xC0, 8 }, { 0x3, 3 }, { 0x2, 3 }, { 0xB, 4 }, - { 0xA, 4 }, { 0xE, 4 }, { 0x8, 4 }, { 0x1, 4 }, - { 0x12, 5 }, { 0x1F, 5 }, { 0x0, 4 }, { 0x6, 5 }, - { 0x7B, 7 }, { 0x306, 10 }, { 0x183A, 13 }, { 0xD, 4 }, - { 0x7, 5 }, { 0x31, 6 }, { 0xA, 6 }, { 0x61, 7 }, - { 0x3C, 6 }, { 0xF4, 8 }, { 0x19, 5 }, { 0xB, 6 } + { 18, 4 }, { 15, 4 }, { 0, 5 }, { 26, 6 }, { 31, 6 }, { 19, 5 }, + { 24, 5 }, { 10, 3 }, { 9, 3 }, { 14, 4 }, { 16, 5 }, { 7, 5 }, + { 12, 4 }, { 11, 4 }, { 8, 8 }, { 2, 9 }, { 21, 10 }, { 5, 13 }, + { 4, 13 }, { 22, 13 }, { 6, 13 }, { 3, 11 }, { 27, 7 }, { 25, 6 }, + { 30, 5 }, { 23, 4 }, { 13, 4 }, { 28, 6 }, { 29, 8 }, { 1, 8 }, + { 20, 7 }, { 17, 5 }, }, { /* AC bias group 2, table 1 */ - { 0xA, 5 }, { 0x1A, 7 }, { 0x1D8, 9 }, { 0x3B3, 10 }, - { 0xECA, 12 }, { 0x1D96, 13 }, { 0x3B2F, 14 }, { 0x14, 5 }, - { 0x36, 8 }, { 0x4, 3 }, { 0x3, 3 }, { 0xC, 4 }, - { 0xB, 4 }, { 0x0, 3 }, { 0x4, 4 }, { 0x1C, 5 }, - { 0x5, 5 }, { 0x15, 5 }, { 0x7, 5 }, { 0x17, 6 }, - { 0x37, 8 }, { 0x764, 11 }, { 0x3B2E, 14 }, { 0xF, 4 }, - { 0x1A, 5 }, { 0x3A, 6 }, { 0xC, 6 }, { 0x77, 7 }, - { 0x4, 5 }, { 0xED, 8 }, { 0x1B, 5 }, { 0x16, 6 } + { 13, 3 }, { 28, 5 }, { 16, 5 }, { 26, 6 }, { 1, 7 }, { 8, 8 }, + { 20, 8 }, { 18, 5 }, { 14, 4 }, { 0, 5 }, { 31, 6 }, { 19, 6 }, + { 10, 3 }, { 9, 3 }, { 7, 5 }, { 17, 5 }, { 12, 4 }, { 11, 4 }, + { 24, 5 }, { 30, 5 }, { 15, 5 }, { 25, 6 }, { 2, 9 }, { 21, 11 }, + { 4, 12 }, { 5, 13 }, { 22, 14 }, { 6, 14 }, { 3, 10 }, { 29, 8 }, + { 27, 7 }, { 23, 4 }, }, { /* AC bias group 2, table 2 */ - { 0x1A, 5 }, { 0x2D, 7 }, { 0x58, 8 }, { 0x1F4, 9 }, - { 0x7D4, 11 }, { 0x1F55, 13 }, { 0x1F54, 13 }, { 0x14, 5 }, - { 0x59, 8 }, { 0x4, 3 }, { 0x3, 3 }, { 0xB, 4 }, - { 0xC, 4 }, { 0xE, 4 }, { 0x4, 4 }, { 0x15, 5 }, - { 0x5, 5 }, { 0x7, 5 }, { 0x4, 5 }, { 0x7C, 7 }, - { 0x3EB, 10 }, { 0x1F57, 13 }, { 0x1F56, 13 }, { 0x0, 3 }, - { 0x1B, 5 }, { 0x3F, 6 }, { 0xD, 6 }, { 0xC, 6 }, - { 0xA, 5 }, { 0xFB, 8 }, { 0x1E, 5 }, { 0x17, 6 } + { 23, 3 }, { 18, 5 }, { 16, 5 }, { 27, 6 }, { 26, 6 }, { 17, 5 }, + { 14, 4 }, { 28, 5 }, { 2, 8 }, { 8, 8 }, { 1, 7 }, { 31, 6 }, + { 10, 3 }, { 9, 3 }, { 7, 5 }, { 15, 5 }, { 11, 4 }, { 12, 4 }, + { 0, 5 }, { 24, 5 }, { 13, 4 }, { 30, 5 }, { 19, 7 }, { 3, 9 }, + { 4, 11 }, { 6, 13 }, { 5, 13 }, { 22, 13 }, { 21, 13 }, { 20, 10 }, + { 29, 8 }, { 25, 6 }, }, { /* AC bias group 2, table 3 */ - { 0x0, 4 }, { 0x75, 7 }, { 0x4A, 8 }, { 0x97, 9 }, - { 0x25B, 11 }, { 0x969, 13 }, { 0x968, 13 }, { 0xB, 5 }, - { 0xE8, 8 }, { 0x5, 3 }, { 0x4, 3 }, { 0x7, 4 }, - { 0xC, 4 }, { 0xD, 4 }, { 0x1, 4 }, { 0xA, 5 }, - { 0x39, 6 }, { 0x3B, 6 }, { 0x18, 6 }, { 0xE9, 8 }, - { 0x12C, 10 }, { 0x96B, 13 }, { 0x96A, 13 }, { 0x1, 3 }, - { 0x1F, 5 }, { 0x8, 5 }, { 0x19, 6 }, { 0x13, 6 }, - { 0xD, 5 }, { 0x24, 7 }, { 0x1E, 5 }, { 0x38, 6 } + { 0, 4 }, { 14, 4 }, { 23, 3 }, { 25, 5 }, { 29, 7 }, { 2, 8 }, + { 20, 10 }, { 6, 13 }, { 5, 13 }, { 22, 13 }, { 21, 13 }, { 4, 11 }, + { 3, 9 }, { 27, 6 }, { 15, 5 }, { 7, 5 }, { 18, 6 }, { 26, 6 }, + { 28, 5 }, { 11, 4 }, { 10, 3 }, { 9, 3 }, { 12, 4 }, { 13, 4 }, + { 31, 6 }, { 16, 6 }, { 8, 8 }, { 19, 8 }, { 1, 7 }, { 17, 6 }, + { 30, 5 }, { 24, 5 }, }, { /* AC bias group 2, table 4 */ - { 0x4, 4 }, { 0x14, 6 }, { 0x6E, 8 }, { 0x57, 8 }, - { 0x159, 10 }, { 0x562, 12 }, { 0xAC7, 13 }, { 0xB, 5 }, - { 0x6F, 8 }, { 0x6, 3 }, { 0x5, 3 }, { 0x8, 4 }, - { 0x9, 4 }, { 0x7, 4 }, { 0x1E, 5 }, { 0x2, 5 }, - { 0x7, 6 }, { 0x6, 6 }, { 0x2A, 7 }, { 0xAD, 9 }, - { 0xAC6, 13 }, { 0x561, 12 }, { 0x560, 12 }, { 0x1, 3 }, - { 0x1F, 5 }, { 0xC, 5 }, { 0x39, 6 }, { 0x1A, 6 }, - { 0x0, 4 }, { 0x36, 7 }, { 0x1D, 5 }, { 0x38, 6 } + { 28, 4 }, { 15, 5 }, { 17, 6 }, { 16, 6 }, { 23, 3 }, { 0, 4 }, + { 1, 6 }, { 18, 7 }, { 22, 12 }, { 21, 12 }, { 5, 12 }, { 20, 13 }, + { 6, 13 }, { 4, 10 }, { 19, 9 }, { 3, 8 }, { 7, 5 }, { 25, 5 }, + { 27, 6 }, { 29, 7 }, { 2, 8 }, { 8, 8 }, { 13, 4 }, { 11, 4 }, + { 12, 4 }, { 10, 3 }, { 9, 3 }, { 31, 6 }, { 26, 6 }, { 30, 5 }, + { 14, 5 }, { 24, 5 }, }, { /* AC bias group 2, table 5 */ - { 0x7, 4 }, { 0x1B, 6 }, { 0xE, 7 }, { 0xD, 7 }, - { 0x3E1, 10 }, { 0x1F06, 13 }, { 0x3E0F, 14 }, { 0x2, 5 }, - { 0xF9, 8 }, { 0x5, 3 }, { 0x6, 3 }, { 0x8, 4 }, - { 0x9, 4 }, { 0x4, 4 }, { 0xC, 5 }, { 0x1A, 6 }, - { 0xF, 7 }, { 0xC, 7 }, { 0x1F1, 9 }, { 0x7C0, 11 }, - { 0x3E0E, 14 }, { 0x1F05, 13 }, { 0x1F04, 13 }, { 0x1, 3 }, - { 0x0, 4 }, { 0x1C, 5 }, { 0x3F, 6 }, { 0x3D, 6 }, - { 0x5, 4 }, { 0x7D, 7 }, { 0x1D, 5 }, { 0x3C, 6 } + { 24, 4 }, { 7, 5 }, { 17, 7 }, { 3, 7 }, { 2, 7 }, { 16, 7 }, + { 23, 3 }, { 13, 4 }, { 28, 4 }, { 14, 5 }, { 15, 6 }, { 1, 6 }, + { 0, 4 }, { 11, 4 }, { 12, 4 }, { 9, 3 }, { 10, 3 }, { 25, 5 }, + { 30, 5 }, { 31, 6 }, { 27, 6 }, { 19, 11 }, { 22, 13 }, { 21, 13 }, + { 5, 13 }, { 20, 14 }, { 6, 14 }, { 4, 10 }, { 18, 9 }, { 8, 8 }, + { 29, 7 }, { 26, 6 }, }, { /* AC bias group 2, table 6 */ - { 0xF, 4 }, { 0xA, 5 }, { 0x71, 7 }, { 0x6, 6 }, - { 0x1C2, 9 }, { 0x702, 11 }, { 0x1C0E, 13 }, { 0x2, 5 }, - { 0xE, 7 }, { 0x5, 3 }, { 0x4, 3 }, { 0x6, 4 }, - { 0x7, 4 }, { 0x1D, 5 }, { 0x17, 6 }, { 0xF, 7 }, - { 0x1C3, 9 }, { 0x1C1, 9 }, { 0x380, 10 }, { 0x381F, 14 }, - { 0x381E, 14 }, { 0x1C0D, 13 }, { 0x1C0C, 13 }, { 0x1, 3 }, - { 0x4, 4 }, { 0x18, 5 }, { 0x1, 5 }, { 0x0, 5 }, - { 0xD, 4 }, { 0x16, 6 }, { 0x19, 5 }, { 0x39, 6 } + { 27, 5 }, { 26, 5 }, { 7, 5 }, { 3, 6 }, { 8, 7 }, { 15, 7 }, + { 23, 3 }, { 24, 4 }, { 1, 5 }, { 29, 6 }, { 14, 6 }, { 11, 4 }, + { 12, 4 }, { 10, 3 }, { 9, 3 }, { 25, 5 }, { 30, 5 }, { 28, 4 }, + { 18, 10 }, { 5, 11 }, { 22, 13 }, { 21, 13 }, { 6, 13 }, { 20, 14 }, + { 19, 14 }, { 17, 9 }, { 4, 9 }, { 16, 9 }, { 2, 7 }, { 31, 6 }, + { 13, 5 }, { 0, 4 }, }, { /* AC bias group 2, table 7 */ - { 0x2, 3 }, { 0x1E, 5 }, { 0x3B, 6 }, { 0xD, 5 }, - { 0x61, 7 }, { 0x1FA, 9 }, { 0x1FB5, 13 }, { 0x31, 6 }, - { 0xFC, 8 }, { 0x4, 3 }, { 0x5, 3 }, { 0x1, 4 }, - { 0x7, 4 }, { 0x3A, 6 }, { 0x60, 7 }, { 0x3F7, 10 }, - { 0x7EC, 11 }, { 0x1FB7, 13 }, { 0x3F6C, 14 }, { 0x7EDB, 15 }, - { 0x7EDA, 15 }, { 0x3F69, 14 }, { 0x3F68, 14 }, { 0x1, 3 }, - { 0x0, 4 }, { 0x19, 5 }, { 0x3E, 6 }, { 0x39, 6 }, - { 0xD, 4 }, { 0x38, 6 }, { 0xC, 5 }, { 0x7F, 7 } + { 24, 4 }, { 11, 4 }, { 23, 3 }, { 0, 3 }, { 30, 5 }, { 3, 5 }, + { 12, 4 }, { 9, 3 }, { 10, 3 }, { 14, 7 }, { 4, 7 }, { 7, 6 }, + { 25, 5 }, { 28, 4 }, { 29, 6 }, { 27, 6 }, { 13, 6 }, { 2, 6 }, + { 1, 5 }, { 26, 6 }, { 8, 8 }, { 5, 9 }, { 16, 11 }, { 22, 14 }, + { 21, 14 }, { 6, 13 }, { 18, 14 }, { 20, 15 }, { 19, 15 }, { 17, 13 }, + { 15, 10 }, { 31, 7 }, }, { /* AC bias group 2, table 8 */ - { 0x1E, 5 }, { 0x70, 7 }, { 0x127, 9 }, { 0x126, 9 }, - { 0x492, 11 }, { 0x124D, 13 }, { 0x124C, 13 }, { 0x1, 5 }, - { 0x7F, 7 }, { 0x6, 3 }, { 0x5, 3 }, { 0x5, 4 }, - { 0x4, 4 }, { 0x1, 4 }, { 0x7, 5 }, { 0x25, 6 }, - { 0x71, 7 }, { 0x7E, 7 }, { 0x48, 7 }, { 0x125, 9 }, - { 0x248, 10 }, { 0x124F, 13 }, { 0x124E, 13 }, { 0x3, 3 }, - { 0x8, 4 }, { 0x1D, 5 }, { 0x6, 5 }, { 0x3E, 6 }, - { 0x2, 4 }, { 0x0, 5 }, { 0x13, 5 }, { 0x39, 6 } + { 29, 5 }, { 7, 5 }, { 13, 4 }, { 28, 4 }, { 26, 5 }, { 14, 5 }, + { 12, 4 }, { 11, 4 }, { 23, 3 }, { 24, 4 }, { 18, 7 }, { 20, 10 }, + { 4, 11 }, { 6, 13 }, { 5, 13 }, { 22, 13 }, { 21, 13 }, { 19, 9 }, + { 3, 9 }, { 2, 9 }, { 15, 6 }, { 30, 5 }, { 10, 3 }, { 9, 3 }, + { 1, 7 }, { 16, 7 }, { 31, 6 }, { 25, 5 }, { 0, 5 }, { 27, 6 }, + { 17, 7 }, { 8, 7 }, }, { /* AC bias group 2, table 9 */ - { 0x1, 4 }, { 0x1, 6 }, { 0xE7, 8 }, { 0x91, 8 }, - { 0x240, 10 }, { 0x120D, 13 }, { 0x120C, 13 }, { 0x3C, 6 }, - { 0x0, 6 }, { 0x6, 3 }, { 0x5, 3 }, { 0x5, 4 }, - { 0x4, 4 }, { 0x1F, 5 }, { 0x4, 5 }, { 0x25, 6 }, - { 0x72, 7 }, { 0x49, 7 }, { 0xE6, 8 }, { 0x121, 9 }, - { 0x482, 11 }, { 0x120F, 13 }, { 0x120E, 13 }, { 0x3, 3 }, - { 0x8, 4 }, { 0x1D, 5 }, { 0x5, 5 }, { 0x3D, 6 }, - { 0x3, 4 }, { 0x1, 5 }, { 0x13, 5 }, { 0x38, 6 } + { 8, 6 }, { 1, 6 }, { 29, 5 }, { 0, 4 }, { 14, 5 }, { 26, 5 }, + { 28, 4 }, { 12, 4 }, { 11, 4 }, { 23, 3 }, { 24, 4 }, { 4, 10 }, + { 20, 11 }, { 6, 13 }, { 5, 13 }, { 22, 13 }, { 21, 13 }, { 19, 9 }, + { 3, 8 }, { 17, 7 }, { 15, 6 }, { 30, 5 }, { 10, 3 }, { 9, 3 }, + { 31, 6 }, { 16, 7 }, { 18, 8 }, { 2, 8 }, { 25, 5 }, { 7, 6 }, + { 27, 6 }, { 13, 5 }, }, { /* AC bias group 2, table 10 */ - { 0x4, 4 }, { 0xF, 6 }, { 0xF4, 8 }, { 0x5B, 8 }, - { 0x2D3, 11 }, { 0xB4A, 13 }, { 0x1697, 14 }, { 0x3C, 6 }, - { 0xE, 6 }, { 0x6, 3 }, { 0x5, 3 }, { 0x2, 4 }, - { 0x1, 4 }, { 0x1D, 5 }, { 0x0, 5 }, { 0x7B, 7 }, - { 0x2C, 7 }, { 0xF5, 8 }, { 0xB5, 9 }, { 0x168, 10 }, - { 0x1696, 14 }, { 0xB49, 13 }, { 0xB48, 13 }, { 0x3, 3 }, - { 0x9, 4 }, { 0x1F, 5 }, { 0xA, 5 }, { 0x1, 5 }, - { 0x8, 4 }, { 0x6, 5 }, { 0x1C, 5 }, { 0x17, 6 } + { 14, 5 }, { 27, 5 }, { 12, 4 }, { 11, 4 }, { 29, 5 }, { 8, 6 }, + { 1, 6 }, { 0, 4 }, { 26, 5 }, { 16, 7 }, { 19, 10 }, { 22, 13 }, + { 21, 13 }, { 5, 13 }, { 20, 14 }, { 6, 14 }, { 4, 11 }, { 18, 9 }, + { 3, 8 }, { 31, 6 }, { 23, 3 }, { 28, 4 }, { 24, 4 }, { 10, 3 }, + { 9, 3 }, { 30, 5 }, { 13, 5 }, { 7, 6 }, { 2, 8 }, { 17, 8 }, + { 15, 7 }, { 25, 5 }, }, { /* AC bias group 2, table 11 */ - { 0x8, 4 }, { 0x39, 6 }, { 0x1A, 7 }, { 0x3, 7 }, - { 0xDB, 10 }, { 0x6D6, 13 }, { 0xDAF, 14 }, { 0x3C, 6 }, - { 0xC, 6 }, { 0x6, 3 }, { 0x5, 3 }, { 0x2, 4 }, - { 0x1, 4 }, { 0x1D, 5 }, { 0x3D, 6 }, { 0x0, 6 }, - { 0x2, 7 }, { 0x37, 8 }, { 0x6C, 9 }, { 0x1B4, 11 }, - { 0xDAE, 14 }, { 0x6D5, 13 }, { 0x6D4, 13 }, { 0x2, 3 }, - { 0x7, 4 }, { 0x1F, 5 }, { 0x7, 5 }, { 0x1, 5 }, - { 0x9, 4 }, { 0xD, 5 }, { 0xC, 5 }, { 0x38, 6 } + { 15, 6 }, { 16, 7 }, { 3, 7 }, { 27, 5 }, { 12, 4 }, { 11, 4 }, + { 8, 6 }, { 2, 7 }, { 18, 9 }, { 19, 11 }, { 22, 13 }, { 21, 13 }, + { 5, 13 }, { 20, 14 }, { 6, 14 }, { 4, 10 }, { 17, 8 }, { 26, 5 }, + { 23, 3 }, { 30, 5 }, { 29, 5 }, { 24, 4 }, { 0, 4 }, { 28, 4 }, + { 10, 3 }, { 9, 3 }, { 31, 6 }, { 1, 6 }, { 13, 5 }, { 7, 6 }, + { 14, 6 }, { 25, 5 }, }, { /* AC bias group 2, table 12 */ - { 0xF, 4 }, { 0x4, 5 }, { 0x2F, 7 }, { 0x2E, 7 }, - { 0x54, 9 }, { 0x555, 13 }, { 0x554, 13 }, { 0x16, 6 }, - { 0xE, 6 }, { 0x6, 3 }, { 0x5, 3 }, { 0x1, 4 }, - { 0x0, 4 }, { 0x9, 5 }, { 0xB, 6 }, { 0x14, 7 }, - { 0x57, 9 }, { 0x56, 9 }, { 0xAB, 10 }, { 0x557, 13 }, - { 0x556, 13 }, { 0x2A9, 12 }, { 0x2A8, 12 }, { 0x3, 3 }, - { 0x8, 4 }, { 0x13, 5 }, { 0xA, 5 }, { 0x8, 5 }, - { 0xE, 4 }, { 0x12, 5 }, { 0x6, 5 }, { 0xF, 6 } + { 12, 4 }, { 11, 4 }, { 1, 5 }, { 15, 7 }, { 4, 9 }, { 22, 12 }, + { 21, 12 }, { 6, 13 }, { 5, 13 }, { 20, 13 }, { 19, 13 }, { 18, 10 }, + { 17, 9 }, { 16, 9 }, { 14, 6 }, { 30, 5 }, { 8, 6 }, { 31, 6 }, + { 27, 5 }, { 13, 5 }, { 26, 5 }, { 7, 6 }, { 3, 7 }, { 2, 7 }, + { 23, 3 }, { 24, 4 }, { 29, 5 }, { 25, 5 }, { 10, 3 }, { 9, 3 }, + { 28, 4 }, { 0, 4 }, }, { /* AC bias group 2, table 13 */ - { 0x1, 3 }, { 0xE, 5 }, { 0x6, 6 }, { 0x4, 6 }, - { 0xDA, 9 }, { 0xDBE, 13 }, { 0x1B7E, 14 }, { 0x7, 6 }, - { 0x1A, 6 }, { 0x5, 3 }, { 0x4, 3 }, { 0x1C, 5 }, - { 0x1B, 5 }, { 0x3A, 6 }, { 0x37, 7 }, { 0x6C, 8 }, - { 0x1B6, 10 }, { 0x36E, 11 }, { 0xDBD, 13 }, { 0x36FF, 15 }, - { 0x36FE, 15 }, { 0x1B79, 14 }, { 0x1B78, 14 }, { 0x2, 3 }, - { 0xC, 4 }, { 0x0, 4 }, { 0xF, 5 }, { 0xC, 5 }, - { 0xF, 4 }, { 0x1A, 5 }, { 0x3B, 6 }, { 0x5, 6 } + { 25, 4 }, { 3, 6 }, { 31, 6 }, { 2, 6 }, { 7, 6 }, { 0, 3 }, + { 23, 3 }, { 27, 5 }, { 8, 6 }, { 15, 8 }, { 4, 9 }, { 16, 10 }, + { 17, 11 }, { 22, 14 }, { 21, 14 }, { 18, 13 }, { 5, 13 }, { 6, 14 }, + { 20, 15 }, { 19, 15 }, { 14, 7 }, { 1, 5 }, { 26, 5 }, { 10, 3 }, + { 9, 3 }, { 24, 4 }, { 29, 5 }, { 12, 5 }, { 11, 5 }, { 13, 6 }, + { 30, 6 }, { 28, 4 }, }, { /* AC bias group 2, table 14 */ - { 0x5, 3 }, { 0x1E, 5 }, { 0x3A, 6 }, { 0x3E, 6 }, - { 0xFC, 8 }, { 0xFD7, 12 }, { 0x3F55, 14 }, { 0x77, 7 }, - { 0x30, 6 }, { 0x3, 3 }, { 0x4, 3 }, { 0x1A, 5 }, - { 0x19, 5 }, { 0x7F, 7 }, { 0x1FB, 9 }, { 0x3F4, 10 }, - { 0xFD6, 12 }, { 0x1FA9, 13 }, { 0x3F54, 14 }, { 0x3F57, 14 }, - { 0x3F56, 14 }, { 0x3F51, 14 }, { 0x3F50, 14 }, { 0x1, 3 }, - { 0x4, 4 }, { 0x1C, 5 }, { 0xB, 5 }, { 0xA, 5 }, - { 0x0, 3 }, { 0x1B, 5 }, { 0x31, 6 }, { 0x76, 7 } + { 28, 3 }, { 23, 3 }, { 24, 4 }, { 27, 5 }, { 26, 5 }, { 9, 3 }, + { 10, 3 }, { 0, 3 }, { 8, 6 }, { 30, 6 }, { 12, 5 }, { 11, 5 }, + { 29, 5 }, { 25, 5 }, { 2, 6 }, { 31, 7 }, { 7, 7 }, { 1, 5 }, + { 3, 6 }, { 4, 8 }, { 15, 10 }, { 22, 14 }, { 21, 14 }, { 17, 13 }, + { 18, 14 }, { 6, 14 }, { 20, 14 }, { 19, 14 }, { 16, 12 }, { 5, 12 }, + { 14, 9 }, { 13, 7 }, }, { /* AC bias group 2, table 15 */ - { 0x5, 3 }, { 0xC, 4 }, { 0x1B, 5 }, { 0x8, 4 }, - { 0x38, 6 }, { 0x15, 8 }, { 0xA3, 11 }, { 0xE6, 8 }, - { 0x4, 6 }, { 0x1, 3 }, { 0x2, 3 }, { 0x12, 5 }, - { 0x3, 5 }, { 0xB, 7 }, { 0x29, 9 }, { 0xA0, 11 }, - { 0x142, 12 }, { 0x287, 13 }, { 0x286, 13 }, { 0x289, 13 }, - { 0x288, 13 }, { 0x28B, 13 }, { 0x28A, 13 }, { 0xF, 4 }, - { 0x1D, 5 }, { 0x13, 5 }, { 0x1, 5 }, { 0x0, 5 }, - { 0x3, 3 }, { 0x1A, 5 }, { 0x72, 7 }, { 0xE7, 8 } - } -}; - -static const uint16_t vp4_ac_bias_2[16][32][2] = { + { 27, 5 }, { 26, 5 }, { 8, 6 }, { 15, 11 }, { 16, 12 }, { 18, 13 }, + { 17, 13 }, { 20, 13 }, { 19, 13 }, { 22, 13 }, { 21, 13 }, { 6, 11 }, + { 14, 9 }, { 5, 8 }, { 13, 7 }, { 12, 5 }, { 9, 3 }, { 10, 3 }, + { 28, 3 }, { 3, 4 }, { 11, 5 }, { 25, 5 }, { 0, 3 }, { 1, 4 }, + { 29, 5 }, { 2, 5 }, { 4, 6 }, { 30, 7 }, { 7, 8 }, { 31, 8 }, + { 24, 5 }, { 23, 4 }, + }, { /* AC bias group 3, table 0 */ - { 0x9, 5 }, { 0x15, 7 }, { 0x28, 8 }, { 0x52, 9 }, - { 0x29A, 12 }, { 0x537, 13 }, { 0x536, 13 }, { 0xA, 5 }, - { 0x54, 7 }, { 0x4, 3 }, { 0x3, 3 }, { 0xC, 4 }, - { 0xB, 4 }, { 0xD, 4 }, { 0x3, 4 }, { 0x14, 5 }, - { 0x3A, 6 }, { 0x4, 5 }, { 0x38, 6 }, { 0x55, 7 }, - { 0xA7, 10 }, { 0x299, 12 }, { 0x298, 12 }, { 0x0, 3 }, - { 0x1E, 5 }, { 0x8, 5 }, { 0x2B, 6 }, { 0xB, 6 }, - { 0xB, 5 }, { 0x3B, 6 }, { 0x1F, 5 }, { 0x39, 6 } + { 23, 3 }, { 17, 5 }, { 2, 8 }, { 3, 9 }, { 22, 12 }, { 21, 12 }, + { 4, 12 }, { 6, 13 }, { 5, 13 }, { 20, 10 }, { 1, 7 }, { 27, 6 }, + { 14, 4 }, { 25, 5 }, { 0, 5 }, { 7, 5 }, { 28, 5 }, { 10, 3 }, + { 9, 3 }, { 15, 5 }, { 8, 7 }, { 19, 7 }, { 26, 6 }, { 12, 4 }, + { 11, 4 }, { 13, 4 }, { 18, 6 }, { 31, 6 }, { 16, 6 }, { 29, 6 }, + { 24, 5 }, { 30, 5 }, }, { /* AC bias group 3, table 1 */ - { 0x1D, 5 }, { 0x2F, 7 }, { 0x2, 8 }, { 0x7, 9 }, - { 0x19, 11 }, { 0x35, 12 }, { 0x34, 12 }, { 0x9, 5 }, - { 0x2E, 7 }, { 0x6, 3 }, { 0x5, 3 }, { 0x9, 4 }, - { 0x8, 4 }, { 0x7, 4 }, { 0x1F, 5 }, { 0x8, 5 }, - { 0x18, 6 }, { 0x19, 6 }, { 0x1, 6 }, { 0x0, 7 }, - { 0x18, 11 }, { 0x37, 12 }, { 0x36, 12 }, { 0x1, 3 }, - { 0x1, 4 }, { 0xA, 5 }, { 0x39, 6 }, { 0x16, 6 }, - { 0xD, 5 }, { 0x1, 5 }, { 0x1E, 5 }, { 0x38, 6 } + { 19, 7 }, { 2, 8 }, { 20, 11 }, { 4, 11 }, { 6, 12 }, { 5, 12 }, + { 22, 12 }, { 21, 12 }, { 3, 9 }, { 18, 6 }, { 29, 5 }, { 24, 4 }, + { 23, 3 }, { 15, 5 }, { 7, 5 }, { 25, 5 }, { 27, 6 }, { 8, 7 }, + { 1, 7 }, { 16, 6 }, { 17, 6 }, { 28, 5 }, { 13, 4 }, { 12, 4 }, + { 11, 4 }, { 10, 3 }, { 9, 3 }, { 31, 6 }, { 26, 6 }, { 0, 5 }, + { 30, 5 }, { 14, 5 }, }, { /* AC bias group 3, table 2 */ - { 0x1, 4 }, { 0x71, 7 }, { 0xE0, 8 }, { 0x1C3, 9 }, - { 0x708, 11 }, { 0x1C26, 13 }, { 0x384F, 14 }, { 0x1, 5 }, - { 0x31, 7 }, { 0x6, 3 }, { 0x5, 3 }, { 0x9, 4 }, - { 0x8, 4 }, { 0x5, 4 }, { 0xF, 5 }, { 0x39, 6 }, - { 0x77, 7 }, { 0x76, 7 }, { 0x30, 7 }, { 0x385, 10 }, - { 0x384E, 14 }, { 0x1C25, 13 }, { 0x1C24, 13 }, { 0x1, 3 }, - { 0x4, 4 }, { 0xD, 5 }, { 0x0, 5 }, { 0x19, 6 }, - { 0x1F, 5 }, { 0xE, 5 }, { 0x1E, 5 }, { 0x3A, 6 } + { 26, 5 }, { 7, 5 }, { 0, 4 }, { 23, 3 }, { 24, 4 }, { 13, 4 }, + { 18, 7 }, { 8, 7 }, { 27, 6 }, { 25, 5 }, { 29, 5 }, { 14, 5 }, + { 12, 4 }, { 11, 4 }, { 10, 3 }, { 9, 3 }, { 2, 8 }, { 4, 11 }, + { 22, 13 }, { 21, 13 }, { 5, 13 }, { 20, 14 }, { 6, 14 }, { 19, 10 }, + { 3, 9 }, { 1, 7 }, { 15, 6 }, { 31, 6 }, { 17, 7 }, { 16, 7 }, + { 30, 5 }, { 28, 5 }, }, { /* AC bias group 3, table 3 */ - { 0x6, 4 }, { 0xC, 6 }, { 0xD6, 8 }, { 0x7B, 8 }, - { 0x1E8, 10 }, { 0x7A4, 12 }, { 0xF4B, 13 }, { 0x36, 6 }, - { 0x6A, 7 }, { 0x7, 3 }, { 0x5, 3 }, { 0x8, 4 }, - { 0x9, 4 }, { 0x1, 4 }, { 0x7, 5 }, { 0xD, 6 }, - { 0x3C, 7 }, { 0xD7, 8 }, { 0xF5, 9 }, { 0x7A7, 12 }, - { 0xF4A, 13 }, { 0xF4D, 13 }, { 0xF4C, 13 }, { 0x2, 3 }, - { 0x2, 4 }, { 0xE, 5 }, { 0x37, 6 }, { 0x34, 6 }, - { 0x0, 4 }, { 0x19, 5 }, { 0x18, 5 }, { 0x1F, 6 } + { 28, 4 }, { 13, 4 }, { 24, 4 }, { 1, 6 }, { 15, 6 }, { 14, 5 }, + { 23, 3 }, { 0, 4 }, { 25, 5 }, { 16, 7 }, { 4, 10 }, { 5, 12 }, + { 20, 13 }, { 6, 13 }, { 22, 13 }, { 21, 13 }, { 19, 12 }, { 18, 9 }, + { 3, 8 }, { 31, 6 }, { 11, 4 }, { 12, 4 }, { 10, 3 }, { 30, 5 }, + { 29, 5 }, { 27, 6 }, { 8, 7 }, { 2, 8 }, { 17, 8 }, { 7, 6 }, + { 26, 6 }, { 9, 3 }, }, { /* AC bias group 3, table 4 */ - { 0xA, 4 }, { 0x27, 6 }, { 0xBF, 8 }, { 0xBE, 8 }, - { 0x224, 10 }, { 0x225D, 14 }, { 0x225C, 14 }, { 0x26, 6 }, - { 0x5E, 7 }, { 0x7, 3 }, { 0x6, 3 }, { 0x6, 4 }, - { 0x7, 4 }, { 0x16, 5 }, { 0x2E, 6 }, { 0x45, 7 }, - { 0x88, 8 }, { 0x113, 9 }, { 0x44A, 11 }, { 0x225F, 14 }, - { 0x225E, 14 }, { 0x112D, 13 }, { 0x112C, 13 }, { 0x2, 3 }, - { 0x2, 4 }, { 0x12, 5 }, { 0x3, 5 }, { 0x2, 5 }, - { 0x3, 4 }, { 0x0, 4 }, { 0x10, 5 }, { 0x23, 6 } + { 29, 4 }, { 27, 5 }, { 26, 5 }, { 24, 4 }, { 28, 4 }, { 23, 3 }, + { 11, 4 }, { 12, 4 }, { 30, 5 }, { 16, 8 }, { 4, 10 }, { 18, 11 }, + { 22, 13 }, { 21, 13 }, { 6, 14 }, { 5, 14 }, { 20, 14 }, { 19, 14 }, + { 17, 9 }, { 15, 7 }, { 31, 6 }, { 25, 5 }, { 7, 6 }, { 1, 6 }, + { 0, 4 }, { 13, 5 }, { 14, 6 }, { 8, 7 }, { 3, 8 }, { 2, 8 }, + { 10, 3 }, { 9, 3 }, }, { /* AC bias group 3, table 5 */ - { 0xF, 4 }, { 0x6, 5 }, { 0x75, 7 }, { 0x74, 7 }, - { 0xA, 9 }, { 0xBF, 13 }, { 0xB9, 13 }, { 0x22, 6 }, - { 0x3, 7 }, { 0x5, 3 }, { 0x6, 3 }, { 0x1, 4 }, - { 0x2, 4 }, { 0x7, 5 }, { 0x0, 6 }, { 0x4, 8 }, - { 0x16, 10 }, { 0x5E, 12 }, { 0xB8, 13 }, { 0xBB, 13 }, - { 0xBA, 13 }, { 0x17D, 14 }, { 0x17C, 14 }, { 0x2, 3 }, - { 0x6, 4 }, { 0x1C, 5 }, { 0x10, 5 }, { 0x3B, 6 }, - { 0x9, 4 }, { 0x7, 4 }, { 0x1, 5 }, { 0x23, 6 } + { 14, 6 }, { 15, 8 }, { 4, 9 }, { 16, 10 }, { 18, 13 }, { 6, 13 }, + { 20, 13 }, { 19, 13 }, { 17, 12 }, { 22, 14 }, { 21, 14 }, { 5, 13 }, + { 8, 7 }, { 30, 5 }, { 11, 4 }, { 12, 4 }, { 1, 5 }, { 13, 5 }, + { 23, 3 }, { 24, 4 }, { 29, 4 }, { 26, 5 }, { 7, 6 }, { 31, 6 }, + { 28, 4 }, { 9, 3 }, { 10, 3 }, { 25, 5 }, { 3, 7 }, { 2, 7 }, + { 27, 6 }, { 0, 4 }, }, { /* AC bias group 3, table 6 */ - { 0x1, 3 }, { 0x1C, 5 }, { 0x36, 6 }, { 0x3B, 6 }, - { 0xEA, 8 }, { 0x75B, 11 }, { 0x1D65, 13 }, { 0x19, 6 }, - { 0x74, 7 }, { 0x4, 3 }, { 0x5, 3 }, { 0x0, 4 }, - { 0x1, 4 }, { 0x37, 6 }, { 0x1D7, 9 }, { 0x75A, 11 }, - { 0x1D64, 13 }, { 0x1D67, 13 }, { 0x1D66, 13 }, { 0x1D61, 13 }, - { 0x1D60, 13 }, { 0x1D63, 13 }, { 0x1D62, 13 }, { 0x2, 3 }, - { 0x1F, 5 }, { 0x1A, 5 }, { 0xD, 5 }, { 0x3D, 6 }, - { 0xC, 4 }, { 0x7, 4 }, { 0x3C, 6 }, { 0x18, 6 } + { 11, 4 }, { 12, 4 }, { 0, 3 }, { 23, 3 }, { 31, 6 }, { 7, 6 }, + { 26, 5 }, { 29, 4 }, { 9, 3 }, { 10, 3 }, { 28, 4 }, { 25, 5 }, + { 2, 6 }, { 13, 6 }, { 1, 5 }, { 8, 7 }, { 4, 8 }, { 20, 13 }, + { 19, 13 }, { 22, 13 }, { 21, 13 }, { 16, 13 }, { 6, 13 }, { 18, 13 }, + { 17, 13 }, { 15, 11 }, { 5, 11 }, { 14, 9 }, { 3, 6 }, { 30, 6 }, + { 27, 6 }, { 24, 5 }, }, { /* AC bias group 3, table 7 */ - { 0x2, 3 }, { 0x1, 4 }, { 0x14, 5 }, { 0x0, 4 }, - { 0x2F, 6 }, { 0xBB, 8 }, { 0x2E4, 10 }, { 0x7D, 7 }, - { 0xBA, 8 }, { 0x3, 3 }, { 0x4, 3 }, { 0x16, 5 }, - { 0x1A, 5 }, { 0xB8, 8 }, { 0x172E, 13 }, { 0x2E5F, 14 }, - { 0x2E5E, 14 }, { 0x1729, 13 }, { 0x1728, 13 }, { 0x172B, 13 }, - { 0x172A, 13 }, { 0x172D, 13 }, { 0x172C, 13 }, { 0x1, 3 }, - { 0x1E, 5 }, { 0x15, 5 }, { 0x1B, 5 }, { 0x3F, 6 }, - { 0xC, 4 }, { 0xE, 4 }, { 0x7C, 7 }, { 0x173, 9 } + { 3, 4 }, { 1, 4 }, { 23, 3 }, { 0, 3 }, { 9, 3 }, { 10, 3 }, + { 2, 5 }, { 25, 5 }, { 11, 5 }, { 13, 8 }, { 6, 10 }, { 18, 13 }, + { 17, 13 }, { 20, 13 }, { 19, 13 }, { 22, 13 }, { 21, 13 }, { 14, 13 }, + { 16, 14 }, { 15, 14 }, { 31, 9 }, { 8, 8 }, { 5, 8 }, { 4, 6 }, + { 28, 4 }, { 12, 5 }, { 26, 5 }, { 29, 4 }, { 24, 5 }, { 30, 7 }, + { 7, 7 }, { 27, 6 }, }, { /* AC bias group 3, table 8 */ - { 0x3, 4 }, { 0x7B, 7 }, { 0x58, 8 }, { 0x1EA, 9 }, - { 0x1EB1, 13 }, { 0x1EB0, 13 }, { 0x1EB3, 13 }, { 0x13, 6 }, - { 0x12, 6 }, { 0x5, 3 }, { 0x6, 3 }, { 0x2, 4 }, - { 0x1, 4 }, { 0x13, 5 }, { 0x3C, 6 }, { 0x2D, 7 }, - { 0xF4, 8 }, { 0x59, 8 }, { 0x3D7, 10 }, { 0xF5B, 12 }, - { 0x1EB2, 13 }, { 0x1EB5, 13 }, { 0x1EB4, 13 }, { 0x3, 3 }, - { 0xE, 4 }, { 0x1F, 5 }, { 0x12, 5 }, { 0x8, 5 }, - { 0x8, 4 }, { 0x0, 4 }, { 0xA, 5 }, { 0x17, 6 } + { 29, 4 }, { 12, 4 }, { 11, 4 }, { 0, 4 }, { 27, 5 }, { 8, 6 }, + { 7, 6 }, { 30, 5 }, { 2, 8 }, { 17, 8 }, { 15, 7 }, { 31, 6 }, + { 23, 3 }, { 28, 4 }, { 26, 5 }, { 13, 5 }, { 9, 3 }, { 10, 3 }, + { 24, 4 }, { 14, 6 }, { 16, 8 }, { 3, 9 }, { 5, 13 }, { 4, 13 }, + { 20, 13 }, { 6, 13 }, { 22, 13 }, { 21, 13 }, { 19, 12 }, { 18, 10 }, + { 1, 7 }, { 25, 5 }, }, { /* AC bias group 3, table 9 */ - { 0x8, 4 }, { 0x3C, 6 }, { 0xF5, 8 }, { 0xF4, 8 }, - { 0x1EF7, 13 }, { 0x3DE9, 14 }, { 0x3DE8, 14 }, { 0x1C, 6 }, - { 0xD, 6 }, { 0x5, 3 }, { 0x6, 3 }, { 0x1, 4 }, - { 0x0, 4 }, { 0x7, 5 }, { 0xC, 6 }, { 0xF6, 8 }, - { 0x1EE, 9 }, { 0x3DF, 10 }, { 0x7BC, 11 }, { 0x3DEB, 14 }, - { 0x3DEA, 14 }, { 0x3DED, 14 }, { 0x3DEC, 14 }, { 0x2, 3 }, - { 0x9, 4 }, { 0x1F, 5 }, { 0xF, 5 }, { 0x5, 5 }, - { 0xE, 4 }, { 0x6, 4 }, { 0x4, 5 }, { 0x1D, 6 } + { 12, 4 }, { 11, 4 }, { 30, 5 }, { 27, 5 }, { 14, 6 }, { 8, 6 }, + { 13, 5 }, { 23, 3 }, { 29, 4 }, { 7, 6 }, { 31, 6 }, { 26, 5 }, + { 0, 4 }, { 24, 4 }, { 9, 3 }, { 10, 3 }, { 28, 4 }, { 1, 6 }, + { 3, 8 }, { 2, 8 }, { 15, 8 }, { 16, 9 }, { 18, 11 }, { 6, 14 }, + { 5, 14 }, { 20, 14 }, { 19, 14 }, { 22, 14 }, { 21, 14 }, { 4, 13 }, + { 17, 10 }, { 25, 5 }, }, { /* AC bias group 3, table 10 */ - { 0x9, 4 }, { 0x39, 6 }, { 0x19, 7 }, { 0x18, 7 }, - { 0x706, 11 }, { 0x383D, 14 }, { 0x383C, 14 }, { 0xD, 6 }, - { 0xF, 6 }, { 0x5, 3 }, { 0x6, 3 }, { 0x0, 4 }, - { 0x1D, 5 }, { 0x3, 5 }, { 0x71, 7 }, { 0xE1, 8 }, - { 0x1C0, 9 }, { 0x382, 10 }, { 0x1C1D, 13 }, { 0x383F, 14 }, - { 0x383E, 14 }, { 0x3839, 14 }, { 0x3838, 14 }, { 0x2, 3 }, - { 0x8, 4 }, { 0x2, 4 }, { 0xD, 5 }, { 0xC, 5 }, - { 0xF, 4 }, { 0x7, 4 }, { 0x2, 5 }, { 0xE, 6 } + { 11, 4 }, { 30, 5 }, { 13, 5 }, { 25, 4 }, { 3, 7 }, { 2, 7 }, + { 7, 6 }, { 31, 6 }, { 8, 6 }, { 23, 3 }, { 27, 5 }, { 26, 5 }, + { 29, 4 }, { 24, 4 }, { 0, 4 }, { 9, 3 }, { 10, 3 }, { 16, 9 }, + { 17, 10 }, { 4, 11 }, { 22, 14 }, { 21, 14 }, { 18, 13 }, { 6, 14 }, + { 5, 14 }, { 20, 14 }, { 19, 14 }, { 15, 8 }, { 14, 7 }, { 1, 6 }, + { 12, 5 }, { 28, 4 }, }, { /* AC bias group 3, table 11 */ - { 0x0, 3 }, { 0x6, 5 }, { 0x35, 7 }, { 0x34, 7 }, - { 0x777, 11 }, { 0x1DD4, 13 }, { 0x3BAB, 14 }, { 0xE, 6 }, - { 0xF, 6 }, { 0x5, 3 }, { 0x4, 3 }, { 0x1C, 5 }, - { 0x19, 5 }, { 0x3A, 6 }, { 0xEF, 8 }, { 0x1DC, 9 }, - { 0x776, 11 }, { 0x774, 11 }, { 0x3BAA, 14 }, { 0x3BAD, 14 }, - { 0x3BAC, 14 }, { 0x3BAF, 14 }, { 0x3BAE, 14 }, { 0x2, 3 }, - { 0x7, 4 }, { 0x2, 4 }, { 0x18, 5 }, { 0xC, 5 }, - { 0xF, 4 }, { 0xD, 4 }, { 0x1B, 6 }, { 0x76, 7 } + { 0, 3 }, { 25, 4 }, { 1, 5 }, { 7, 6 }, { 8, 6 }, { 23, 3 }, + { 27, 5 }, { 3, 7 }, { 2, 7 }, { 30, 6 }, { 24, 4 }, { 10, 3 }, + { 9, 3 }, { 26, 5 }, { 12, 5 }, { 29, 4 }, { 11, 5 }, { 13, 6 }, + { 31, 7 }, { 15, 9 }, { 17, 11 }, { 5, 13 }, { 18, 14 }, { 6, 14 }, + { 20, 14 }, { 19, 14 }, { 22, 14 }, { 21, 14 }, { 16, 11 }, { 4, 11 }, + { 14, 8 }, { 28, 4 }, }, { /* AC bias group 3, table 12 */ - { 0x2, 3 }, { 0x11, 5 }, { 0x6, 6 }, { 0x4F, 7 }, - { 0x130, 9 }, { 0x1319, 13 }, { 0x1318, 13 }, { 0x4E, 7 }, - { 0x7, 6 }, { 0x6, 3 }, { 0x5, 3 }, { 0x10, 5 }, - { 0xD, 5 }, { 0x5, 6 }, { 0x99, 8 }, { 0x262, 10 }, - { 0x98E, 12 }, { 0x131B, 13 }, { 0x131A, 13 }, { 0x263D, 14 }, - { 0x263C, 14 }, { 0x263F, 14 }, { 0x263E, 14 }, { 0x1, 3 }, - { 0x7, 4 }, { 0x0, 4 }, { 0x12, 5 }, { 0xC, 5 }, - { 0xE, 4 }, { 0xF, 4 }, { 0x4, 6 }, { 0x4D, 7 } + { 25, 4 }, { 30, 6 }, { 13, 6 }, { 2, 6 }, { 8, 6 }, { 23, 3 }, + { 0, 3 }, { 27, 5 }, { 12, 5 }, { 24, 4 }, { 11, 5 }, { 1, 5 }, + { 26, 5 }, { 4, 9 }, { 15, 10 }, { 6, 13 }, { 5, 13 }, { 18, 13 }, + { 17, 13 }, { 16, 12 }, { 20, 14 }, { 19, 14 }, { 22, 14 }, { 21, 14 }, + { 14, 8 }, { 31, 7 }, { 7, 7 }, { 3, 7 }, { 10, 3 }, { 9, 3 }, + { 28, 4 }, { 29, 4 }, }, { /* AC bias group 3, table 13 */ - { 0x3, 3 }, { 0x0, 4 }, { 0x2, 5 }, { 0x37, 6 }, - { 0x1B7, 9 }, { 0xDB5, 12 }, { 0x36DD, 14 }, { 0x6C, 7 }, - { 0x16, 6 }, { 0x5, 3 }, { 0x4, 3 }, { 0x3, 5 }, - { 0xA, 5 }, { 0x2E, 7 }, { 0x36C, 10 }, { 0xDB4, 12 }, - { 0x36DC, 14 }, { 0x36DF, 14 }, { 0x36DE, 14 }, { 0x36D9, 14 }, - { 0x36D8, 14 }, { 0x36DB, 14 }, { 0x36DA, 14 }, { 0xE, 4 }, - { 0x4, 4 }, { 0x1A, 5 }, { 0x19, 5 }, { 0x18, 5 }, - { 0xF, 4 }, { 0x1, 3 }, { 0x2F, 7 }, { 0xDA, 8 } + { 1, 4 }, { 2, 5 }, { 11, 5 }, { 29, 3 }, { 24, 4 }, { 12, 5 }, + { 8, 6 }, { 13, 7 }, { 30, 7 }, { 0, 3 }, { 10, 3 }, { 9, 3 }, + { 27, 5 }, { 26, 5 }, { 25, 5 }, { 7, 7 }, { 31, 8 }, { 14, 10 }, + { 15, 12 }, { 5, 12 }, { 20, 14 }, { 19, 14 }, { 22, 14 }, { 21, 14 }, + { 16, 14 }, { 6, 14 }, { 18, 14 }, { 17, 14 }, { 4, 9 }, { 3, 6 }, + { 23, 4 }, { 28, 4 }, }, { /* AC bias group 3, table 14 */ - { 0x6, 3 }, { 0x6, 4 }, { 0xF, 5 }, { 0x0, 4 }, - { 0x75, 7 }, { 0x3B8, 10 }, { 0x1DCA, 13 }, { 0x74, 7 }, - { 0x76, 7 }, { 0x4, 3 }, { 0x5, 3 }, { 0x3, 5 }, - { 0x2, 5 }, { 0x1DE, 9 }, { 0xEE6, 12 }, { 0x3B97, 14 }, - { 0x3B96, 14 }, { 0x3B9D, 14 }, { 0x3B9C, 14 }, { 0x3B9F, 14 }, - { 0x3B9E, 14 }, { 0x1DC9, 13 }, { 0x1DC8, 13 }, { 0x5, 4 }, - { 0x1C, 5 }, { 0x9, 5 }, { 0xE, 5 }, { 0x8, 5 }, - { 0xF, 4 }, { 0x1, 3 }, { 0x1DF, 9 }, { 0x1DD, 9 } + { 3, 4 }, { 12, 5 }, { 11, 5 }, { 29, 3 }, { 27, 5 }, { 25, 5 }, + { 23, 4 }, { 1, 4 }, { 26, 5 }, { 2, 5 }, { 9, 3 }, { 10, 3 }, + { 0, 3 }, { 24, 5 }, { 7, 7 }, { 4, 7 }, { 8, 7 }, { 5, 10 }, + { 22, 13 }, { 21, 13 }, { 6, 13 }, { 16, 14 }, { 15, 14 }, { 14, 12 }, + { 18, 14 }, { 17, 14 }, { 20, 14 }, { 19, 14 }, { 31, 9 }, { 13, 9 }, + { 30, 9 }, { 28, 4 }, }, { /* AC bias group 3, table 15 */ - { 0x4, 3 }, { 0xB, 4 }, { 0x1D, 5 }, { 0xC, 4 }, - { 0x14, 5 }, { 0xE0, 8 }, { 0x3875, 14 }, { 0x386, 10 }, - { 0x1C2, 9 }, { 0x0, 2 }, { 0x1, 2 }, { 0x71, 7 }, - { 0x72, 7 }, { 0x1C3F, 13 }, { 0x3874, 14 }, { 0x3877, 14 }, - { 0x3876, 14 }, { 0x3871, 14 }, { 0x3870, 14 }, { 0x3873, 14 }, - { 0x3872, 14 }, { 0x3879, 14 }, { 0x3878, 14 }, { 0x3C, 6 }, - { 0x73, 7 }, { 0x2A, 6 }, { 0x3D, 6 }, { 0x2B, 6 }, - { 0x1F, 5 }, { 0xD, 4 }, { 0x1C3E, 13 }, { 0x1C3D, 13 } - } -}; - -static const uint16_t vp4_ac_bias_3[16][32][2] = { + { 9, 2 }, { 10, 2 }, { 0, 3 }, { 4, 5 }, { 25, 6 }, { 27, 6 }, + { 1, 4 }, { 3, 4 }, { 29, 4 }, { 5, 8 }, { 8, 9 }, { 7, 10 }, + { 18, 14 }, { 17, 14 }, { 20, 14 }, { 19, 14 }, { 14, 14 }, { 6, 14 }, + { 16, 14 }, { 15, 14 }, { 22, 14 }, { 21, 14 }, { 31, 13 }, { 30, 13 }, + { 13, 13 }, { 11, 7 }, { 12, 7 }, { 24, 7 }, { 2, 5 }, { 23, 6 }, + { 26, 6 }, { 28, 5 }, + }, { /* AC bias group 4, table 0 */ - { 0x7, 4 }, { 0xF, 6 }, { 0xBB, 8 }, { 0xBA, 8 }, - { 0x5CF, 11 }, { 0x173A, 13 }, { 0x2E77, 14 }, { 0x29, 6 }, - { 0x172, 9 }, { 0x7, 3 }, { 0x6, 3 }, { 0x9, 4 }, - { 0x8, 4 }, { 0x1, 4 }, { 0x5, 5 }, { 0xD, 6 }, - { 0x1D, 7 }, { 0x1C, 7 }, { 0xB8, 8 }, { 0x2E6, 10 }, - { 0x2E76, 14 }, { 0x1739, 13 }, { 0x1738, 13 }, { 0x2, 3 }, - { 0x6, 4 }, { 0x16, 5 }, { 0x4, 5 }, { 0x28, 6 }, - { 0x15, 5 }, { 0xC, 6 }, { 0x0, 4 }, { 0x2F, 6 } + { 30, 4 }, { 13, 4 }, { 26, 5 }, { 14, 5 }, { 29, 6 }, { 15, 6 }, + { 17, 7 }, { 16, 7 }, { 1, 6 }, { 23, 3 }, { 24, 4 }, { 0, 4 }, + { 12, 4 }, { 11, 4 }, { 27, 6 }, { 7, 6 }, { 28, 5 }, { 25, 5 }, + { 18, 8 }, { 8, 9 }, { 19, 10 }, { 22, 13 }, { 21, 13 }, { 5, 13 }, + { 20, 14 }, { 6, 14 }, { 4, 11 }, { 3, 8 }, { 2, 8 }, { 31, 6 }, + { 10, 3 }, { 9, 3 }, }, { /* AC bias group 4, table 1 */ - { 0xB, 4 }, { 0x2, 5 }, { 0x54, 7 }, { 0x2F, 7 }, - { 0x2AC, 10 }, { 0x156B, 13 }, { 0x1568, 13 }, { 0x16, 6 }, - { 0x154, 9 }, { 0x7, 3 }, { 0x6, 3 }, { 0x4, 4 }, - { 0x3, 4 }, { 0x13, 5 }, { 0x28, 6 }, { 0x2E, 7 }, - { 0x157, 9 }, { 0x155, 9 }, { 0x55B, 11 }, { 0x2AD3, 14 }, - { 0x2AD2, 14 }, { 0x2AD5, 14 }, { 0x2AD4, 14 }, { 0x3, 3 }, - { 0x8, 4 }, { 0x0, 4 }, { 0xA, 5 }, { 0x3, 5 }, - { 0x2, 4 }, { 0x2B, 6 }, { 0x12, 5 }, { 0x29, 6 } + { 25, 4 }, { 1, 5 }, { 27, 5 }, { 28, 4 }, { 12, 4 }, { 11, 4 }, + { 26, 5 }, { 7, 6 }, { 15, 7 }, { 3, 7 }, { 23, 3 }, { 24, 4 }, + { 30, 5 }, { 13, 5 }, { 14, 6 }, { 31, 6 }, { 2, 7 }, { 8, 9 }, + { 17, 9 }, { 4, 10 }, { 6, 13 }, { 20, 14 }, { 19, 14 }, { 22, 14 }, + { 21, 14 }, { 5, 13 }, { 18, 11 }, { 16, 9 }, { 29, 6 }, { 0, 4 }, + { 10, 3 }, { 9, 3 }, }, { /* AC bias group 4, table 2 */ - { 0xF, 4 }, { 0x7, 5 }, { 0x1, 6 }, { 0x0, 6 }, - { 0x1C4, 9 }, { 0x703, 11 }, { 0xE02, 12 }, { 0x11, 6 }, - { 0xE1, 8 }, { 0x5, 3 }, { 0x6, 3 }, { 0x2, 4 }, - { 0x1, 4 }, { 0x9, 5 }, { 0x10, 6 }, { 0xE3, 8 }, - { 0x1C5, 9 }, { 0x1C1, 9 }, { 0x702, 11 }, { 0x1C07, 13 }, - { 0x1C06, 13 }, { 0xE01, 12 }, { 0xE00, 12 }, { 0x4, 3 }, - { 0x7, 4 }, { 0x1D, 5 }, { 0xD, 5 }, { 0x1, 5 }, - { 0x5, 4 }, { 0x6, 5 }, { 0xC, 5 }, { 0x39, 6 } + { 3, 6 }, { 2, 6 }, { 27, 5 }, { 12, 4 }, { 11, 4 }, { 29, 5 }, + { 1, 5 }, { 14, 6 }, { 7, 6 }, { 13, 5 }, { 28, 4 }, { 30, 5 }, + { 26, 5 }, { 24, 4 }, { 23, 3 }, { 9, 3 }, { 10, 3 }, { 22, 12 }, + { 21, 12 }, { 6, 12 }, { 20, 13 }, { 19, 13 }, { 18, 11 }, { 5, 11 }, + { 17, 9 }, { 8, 8 }, { 4, 9 }, { 16, 9 }, { 15, 8 }, { 31, 6 }, + { 25, 5 }, { 0, 4 }, }, { /* AC bias group 4, table 3 */ - { 0x1, 3 }, { 0x1C, 5 }, { 0x11, 6 }, { 0x13, 6 }, - { 0x42, 8 }, { 0x207, 11 }, { 0x815, 13 }, { 0x75, 7 }, - { 0x41, 8 }, { 0x5, 3 }, { 0x6, 3 }, { 0x0, 4 }, - { 0x1F, 5 }, { 0x3B, 6 }, { 0x74, 7 }, { 0x43, 8 }, - { 0x80, 9 }, { 0x206, 11 }, { 0x814, 13 }, { 0x817, 13 }, - { 0x816, 13 }, { 0x409, 12 }, { 0x408, 12 }, { 0x3, 3 }, - { 0x9, 4 }, { 0x1E, 5 }, { 0x11, 5 }, { 0x3, 5 }, - { 0x5, 4 }, { 0x10, 5 }, { 0x2, 5 }, { 0x12, 6 } + { 11, 4 }, { 30, 5 }, { 27, 5 }, { 0, 3 }, { 16, 9 }, { 22, 12 }, + { 21, 12 }, { 18, 13 }, { 6, 13 }, { 20, 13 }, { 19, 13 }, { 17, 11 }, + { 5, 11 }, { 8, 8 }, { 4, 8 }, { 15, 8 }, { 2, 6 }, { 31, 6 }, + { 3, 6 }, { 28, 4 }, { 23, 3 }, { 29, 5 }, { 26, 5 }, { 24, 4 }, + { 9, 3 }, { 10, 3 }, { 1, 5 }, { 14, 7 }, { 7, 7 }, { 13, 6 }, + { 25, 5 }, { 12, 5 }, }, { /* AC bias group 4, table 4 */ - { 0x1, 3 }, { 0x1F, 5 }, { 0x27, 6 }, { 0x1, 5 }, - { 0x4B, 8 }, { 0x123, 10 }, { 0x915, 13 }, { 0x0, 6 }, - { 0x49, 8 }, { 0x5, 3 }, { 0x6, 3 }, { 0x1D, 5 }, - { 0x1C, 5 }, { 0x13, 6 }, { 0x4A, 8 }, { 0x90, 9 }, - { 0x914, 13 }, { 0x917, 13 }, { 0x916, 13 }, { 0x911, 13 }, - { 0x910, 13 }, { 0x913, 13 }, { 0x912, 13 }, { 0x3, 3 }, - { 0x5, 4 }, { 0x1, 4 }, { 0x12, 5 }, { 0x8, 5 }, - { 0x8, 4 }, { 0x1E, 5 }, { 0x26, 6 }, { 0x1, 6 } + { 7, 6 }, { 31, 6 }, { 3, 5 }, { 25, 4 }, { 0, 3 }, { 27, 5 }, + { 15, 9 }, { 20, 13 }, { 19, 13 }, { 22, 13 }, { 21, 13 }, { 16, 13 }, + { 6, 13 }, { 18, 13 }, { 17, 13 }, { 5, 10 }, { 8, 8 }, { 14, 8 }, + { 4, 8 }, { 13, 6 }, { 24, 4 }, { 23, 3 }, { 28, 4 }, { 26, 5 }, + { 30, 6 }, { 2, 6 }, { 9, 3 }, { 10, 3 }, { 12, 5 }, { 11, 5 }, + { 29, 5 }, { 1, 5 }, }, { /* AC bias group 4, table 5 */ - { 0x3, 3 }, { 0x1, 4 }, { 0x3F, 6 }, { 0xB, 5 }, - { 0x4E, 7 }, { 0x132, 9 }, { 0x99A, 12 }, { 0x4F, 7 }, - { 0x98, 8 }, { 0x6, 3 }, { 0x5, 3 }, { 0x1D, 5 }, - { 0x1C, 5 }, { 0x7C, 7 }, { 0x267, 10 }, { 0x1331, 13 }, - { 0x1330, 13 }, { 0x1333, 13 }, { 0x1332, 13 }, { 0x266D, 14 }, - { 0x266C, 14 }, { 0x266F, 14 }, { 0x266E, 14 }, { 0x1, 3 }, - { 0x4, 4 }, { 0x1E, 5 }, { 0x12, 5 }, { 0xA, 5 }, - { 0x8, 4 }, { 0x0, 4 }, { 0x7D, 7 }, { 0x4D, 7 } + { 29, 4 }, { 1, 4 }, { 23, 3 }, { 24, 4 }, { 27, 5 }, { 3, 5 }, + { 0, 3 }, { 28, 4 }, { 26, 5 }, { 8, 8 }, { 5, 9 }, { 16, 13 }, + { 15, 13 }, { 18, 13 }, { 17, 13 }, { 6, 12 }, { 20, 14 }, { 19, 14 }, + { 22, 14 }, { 21, 14 }, { 14, 10 }, { 31, 7 }, { 4, 7 }, { 7, 7 }, + { 10, 3 }, { 9, 3 }, { 12, 5 }, { 11, 5 }, { 25, 5 }, { 13, 7 }, + { 30, 7 }, { 2, 6 }, }, { /* AC bias group 4, table 6 */ - { 0x2, 3 }, { 0x7, 4 }, { 0x15, 5 }, { 0x3, 4 }, - { 0x4, 5 }, { 0xA7, 8 }, { 0x536, 11 }, { 0x28, 6 }, - { 0x29A, 10 }, { 0x6, 3 }, { 0x4, 3 }, { 0x1C, 5 }, - { 0x17, 5 }, { 0xA4, 8 }, { 0x29BE, 14 }, { 0x537F, 15 }, - { 0x537E, 15 }, { 0x29B9, 14 }, { 0x29B8, 14 }, { 0x29BB, 14 }, - { 0x29BA, 14 }, { 0x29BD, 14 }, { 0x29BC, 14 }, { 0xF, 4 }, - { 0x0, 4 }, { 0x5, 5 }, { 0x16, 5 }, { 0x1D, 5 }, - { 0x6, 4 }, { 0x1, 4 }, { 0xA5, 8 }, { 0x14C, 9 } + { 24, 4 }, { 29, 4 }, { 4, 5 }, { 25, 5 }, { 3, 4 }, { 0, 3 }, + { 28, 4 }, { 1, 4 }, { 10, 3 }, { 7, 6 }, { 13, 8 }, { 30, 8 }, + { 31, 9 }, { 8, 10 }, { 6, 11 }, { 18, 14 }, { 17, 14 }, { 20, 14 }, + { 19, 14 }, { 22, 14 }, { 21, 14 }, { 14, 14 }, { 16, 15 }, { 15, 15 }, + { 5, 8 }, { 2, 5 }, { 26, 5 }, { 12, 5 }, { 9, 3 }, { 11, 5 }, + { 27, 5 }, { 23, 4 }, }, { /* AC bias group 4, table 7 */ - { 0x4, 3 }, { 0x7, 4 }, { 0x1A, 5 }, { 0xC, 4 }, - { 0x6, 4 }, { 0x29, 6 }, { 0x1BD, 9 }, { 0x1BE3, 13 }, - { 0x1BE0, 13 }, { 0x0, 2 }, { 0x7, 3 }, { 0x6E, 7 }, - { 0x1BC, 9 }, { 0x37C3, 14 }, { 0x37C2, 14 }, { 0x37CD, 14 }, - { 0x37CC, 14 }, { 0x37CF, 14 }, { 0x37CE, 14 }, { 0x37C9, 14 }, - { 0x37C8, 14 }, { 0x37CB, 14 }, { 0x37CA, 14 }, { 0x15, 5 }, - { 0x1BF, 9 }, { 0x37D, 10 }, { 0x36, 6 }, { 0x2, 3 }, - { 0xB, 4 }, { 0x28, 6 }, { 0x37C5, 14 }, { 0x37C4, 14 } + { 9, 2 }, { 27, 3 }, { 4, 4 }, { 1, 4 }, { 0, 3 }, { 29, 6 }, + { 5, 6 }, { 23, 5 }, { 28, 4 }, { 3, 4 }, { 2, 5 }, { 26, 6 }, + { 11, 7 }, { 12, 9 }, { 6, 9 }, { 8, 13 }, { 14, 14 }, { 13, 14 }, + { 31, 14 }, { 30, 14 }, { 7, 13 }, { 20, 14 }, { 19, 14 }, { 22, 14 }, + { 21, 14 }, { 16, 14 }, { 15, 14 }, { 18, 14 }, { 17, 14 }, { 25, 10 }, + { 24, 9 }, { 10, 3 }, }, { /* AC bias group 4, table 8 */ - { 0x1, 3 }, { 0x9, 5 }, { 0x3, 6 }, { 0x2, 6 }, - { 0x11F, 10 }, { 0x8E9, 13 }, { 0x8E8, 13 }, { 0x2D, 7 }, - { 0x22, 7 }, { 0x6, 3 }, { 0x7, 3 }, { 0x10, 5 }, - { 0x11, 5 }, { 0x17, 6 }, { 0x2C, 7 }, { 0x46, 8 }, - { 0x11E, 10 }, { 0x11C, 10 }, { 0x477, 12 }, { 0x8EB, 13 }, - { 0x8EA, 13 }, { 0x8ED, 13 }, { 0x8EC, 13 }, { 0x3, 3 }, - { 0xB, 4 }, { 0x1, 4 }, { 0x14, 5 }, { 0xA, 5 }, - { 0x9, 4 }, { 0x15, 5 }, { 0x0, 5 }, { 0x10, 6 } + { 30, 5 }, { 3, 6 }, { 2, 6 }, { 25, 4 }, { 0, 3 }, { 31, 6 }, + { 8, 7 }, { 15, 8 }, { 17, 10 }, { 6, 13 }, { 5, 13 }, { 20, 13 }, + { 19, 13 }, { 22, 13 }, { 21, 13 }, { 18, 12 }, { 16, 10 }, { 4, 10 }, + { 1, 5 }, { 27, 5 }, { 14, 7 }, { 7, 7 }, { 13, 6 }, { 23, 3 }, + { 11, 5 }, { 12, 5 }, { 28, 4 }, { 26, 5 }, { 29, 5 }, { 24, 4 }, + { 9, 3 }, { 10, 3 }, }, { /* AC bias group 4, table 9 */ - { 0x1, 3 }, { 0x1D, 5 }, { 0x22, 6 }, { 0x13, 6 }, - { 0x11E, 9 }, { 0x8FC, 12 }, { 0x23F5, 14 }, { 0x23, 7 }, - { 0x22, 7 }, { 0x5, 3 }, { 0x6, 3 }, { 0x10, 5 }, - { 0xB, 5 }, { 0x10, 6 }, { 0x8E, 8 }, { 0x23E, 10 }, - { 0x8FF, 12 }, { 0x11FD, 13 }, { 0x23F4, 14 }, { 0x23F7, 14 }, - { 0x23F6, 14 }, { 0x23F9, 14 }, { 0x23F8, 14 }, { 0x3, 3 }, - { 0x9, 4 }, { 0x0, 4 }, { 0x1C, 5 }, { 0xA, 5 }, - { 0xF, 4 }, { 0x1, 4 }, { 0x12, 6 }, { 0x46, 7 } + { 25, 4 }, { 29, 4 }, { 0, 3 }, { 13, 6 }, { 8, 7 }, { 7, 7 }, + { 30, 6 }, { 3, 6 }, { 27, 5 }, { 12, 5 }, { 23, 3 }, { 11, 5 }, + { 2, 6 }, { 31, 7 }, { 14, 8 }, { 4, 9 }, { 15, 10 }, { 5, 12 }, + { 18, 14 }, { 6, 14 }, { 20, 14 }, { 19, 14 }, { 22, 14 }, { 21, 14 }, + { 17, 13 }, { 16, 12 }, { 24, 4 }, { 9, 3 }, { 10, 3 }, { 26, 5 }, + { 1, 5 }, { 28, 4 }, }, { /* AC bias group 4, table 10 */ - { 0x3, 3 }, { 0x1F, 5 }, { 0x3C, 6 }, { 0x3D, 6 }, - { 0x86, 8 }, { 0x877, 12 }, { 0x10E8, 13 }, { 0x41, 7 }, - { 0x40, 7 }, { 0x5, 3 }, { 0x6, 3 }, { 0x7, 5 }, - { 0x6, 5 }, { 0x4, 6 }, { 0x10F, 9 }, { 0x21C, 10 }, - { 0x875, 12 }, { 0x21D3, 14 }, { 0x21D2, 14 }, { 0x21D9, 14 }, - { 0x21D8, 14 }, { 0x21DB, 14 }, { 0x21DA, 14 }, { 0x2, 3 }, - { 0x9, 4 }, { 0x0, 4 }, { 0x11, 5 }, { 0x3, 5 }, - { 0xE, 4 }, { 0x2, 4 }, { 0x5, 6 }, { 0x42, 7 } + { 25, 4 }, { 13, 6 }, { 30, 6 }, { 27, 5 }, { 29, 4 }, { 12, 5 }, + { 11, 5 }, { 23, 3 }, { 0, 3 }, { 8, 7 }, { 7, 7 }, { 31, 7 }, + { 4, 8 }, { 15, 10 }, { 6, 13 }, { 18, 14 }, { 17, 14 }, { 16, 12 }, + { 20, 14 }, { 19, 14 }, { 22, 14 }, { 21, 14 }, { 5, 12 }, { 14, 9 }, + { 26, 5 }, { 24, 4 }, { 9, 3 }, { 10, 3 }, { 28, 4 }, { 2, 6 }, + { 3, 6 }, { 1, 5 }, }, { /* AC bias group 4, table 11 */ - { 0x4, 3 }, { 0x1, 4 }, { 0x3D, 6 }, { 0x9, 5 }, - { 0xF3, 8 }, { 0x793, 11 }, { 0x1E45, 13 }, { 0x0, 7 }, - { 0x2, 7 }, { 0x5, 3 }, { 0x6, 3 }, { 0x8, 5 }, - { 0x1, 5 }, { 0x3, 7 }, { 0x1E5, 9 }, { 0x792, 11 }, - { 0x1E44, 13 }, { 0x1E47, 13 }, { 0x1E46, 13 }, { 0x1E41, 13 }, - { 0x1E40, 13 }, { 0x1E43, 13 }, { 0x1E42, 13 }, { 0x1, 3 }, - { 0x6, 4 }, { 0x1F, 5 }, { 0xF, 5 }, { 0xE, 5 }, - { 0xE, 4 }, { 0x5, 4 }, { 0x78, 7 }, { 0x1, 7 } + { 7, 7 }, { 31, 7 }, { 8, 7 }, { 13, 7 }, { 12, 5 }, { 1, 4 }, + { 23, 3 }, { 11, 5 }, { 3, 5 }, { 29, 4 }, { 24, 4 }, { 27, 5 }, + { 26, 5 }, { 0, 3 }, { 9, 3 }, { 10, 3 }, { 28, 4 }, { 30, 7 }, + { 20, 13 }, { 19, 13 }, { 22, 13 }, { 21, 13 }, { 16, 13 }, { 6, 13 }, + { 18, 13 }, { 17, 13 }, { 15, 11 }, { 5, 11 }, { 14, 9 }, { 4, 8 }, + { 2, 6 }, { 25, 5 }, }, { /* AC bias group 4, table 12 */ - { 0x4, 3 }, { 0x5, 4 }, { 0xE, 5 }, { 0x17, 5 }, - { 0x3E, 7 }, { 0xF0, 9 }, { 0xF1E, 13 }, { 0x7A, 8 }, - { 0x7F, 8 }, { 0x6, 3 }, { 0x7, 3 }, { 0x5, 5 }, - { 0x4, 5 }, { 0x7B, 8 }, { 0x1E2, 10 }, { 0x1E3F, 14 }, - { 0x1E3E, 14 }, { 0xF19, 13 }, { 0xF18, 13 }, { 0xF1B, 13 }, - { 0xF1A, 13 }, { 0xF1D, 13 }, { 0xF1C, 13 }, { 0x0, 3 }, - { 0x3, 4 }, { 0x16, 5 }, { 0x9, 5 }, { 0x8, 5 }, - { 0xA, 4 }, { 0x6, 4 }, { 0x7E, 8 }, { 0x79, 8 } + { 23, 3 }, { 12, 5 }, { 11, 5 }, { 24, 4 }, { 27, 5 }, { 26, 5 }, + { 1, 4 }, { 29, 4 }, { 2, 5 }, { 5, 9 }, { 14, 10 }, { 18, 13 }, + { 17, 13 }, { 20, 13 }, { 19, 13 }, { 22, 13 }, { 21, 13 }, { 6, 13 }, + { 16, 14 }, { 15, 14 }, { 31, 8 }, { 7, 8 }, { 13, 8 }, { 4, 7 }, + { 30, 8 }, { 8, 8 }, { 0, 3 }, { 28, 4 }, { 25, 5 }, { 3, 5 }, + { 9, 3 }, { 10, 3 }, }, { /* AC bias group 4, table 13 */ - { 0x5, 3 }, { 0xC, 4 }, { 0x1A, 5 }, { 0x4, 4 }, - { 0x1A, 6 }, { 0xDE, 9 }, { 0xDF4, 13 }, { 0xDD, 9 }, - { 0x6D, 8 }, { 0x0, 2 }, { 0x7, 3 }, { 0x25, 6 }, - { 0x24, 6 }, { 0xDC, 9 }, { 0xDF7, 13 }, { 0x1BEB, 14 }, - { 0x1BEA, 14 }, { 0xDF1, 13 }, { 0xDF0, 13 }, { 0xDF3, 13 }, - { 0xDF2, 13 }, { 0x1BED, 14 }, { 0x1BEC, 14 }, { 0x8, 4 }, - { 0x13, 5 }, { 0xC, 5 }, { 0x37, 6 }, { 0x36, 6 }, - { 0x5, 4 }, { 0x7, 4 }, { 0x6C, 8 }, { 0x1BF, 10 } + { 9, 2 }, { 3, 4 }, { 28, 4 }, { 25, 5 }, { 4, 6 }, { 30, 8 }, + { 8, 8 }, { 13, 9 }, { 7, 9 }, { 5, 9 }, { 18, 13 }, { 17, 13 }, + { 20, 13 }, { 19, 13 }, { 6, 13 }, { 16, 14 }, { 15, 14 }, { 22, 14 }, + { 21, 14 }, { 14, 13 }, { 31, 10 }, { 29, 4 }, { 23, 4 }, { 12, 6 }, + { 11, 6 }, { 24, 5 }, { 0, 3 }, { 1, 4 }, { 2, 5 }, { 27, 6 }, + { 26, 6 }, { 10, 3 }, }, { /* AC bias group 4, table 14 */ - { 0x5, 3 }, { 0xD, 4 }, { 0x1F, 5 }, { 0xC, 4 }, - { 0x3B, 6 }, { 0x40, 7 }, { 0x41A, 11 }, { 0x104, 9 }, - { 0x107, 9 }, { 0x1, 2 }, { 0x0, 2 }, { 0x24, 6 }, - { 0x21, 6 }, { 0x20B, 10 }, { 0x106E, 13 }, { 0x20DF, 14 }, - { 0x20DE, 14 }, { 0x1055, 13 }, { 0x1054, 13 }, { 0x1057, 13 }, - { 0x1056, 13 }, { 0x106D, 13 }, { 0x106C, 13 }, { 0x11, 5 }, - { 0x3A, 6 }, { 0x25, 6 }, { 0x38, 6 }, { 0x39, 6 }, - { 0x13, 5 }, { 0x1E, 5 }, { 0x20C, 10 }, { 0x414, 11 } + { 10, 2 }, { 9, 2 }, { 5, 7 }, { 7, 9 }, { 31, 11 }, { 18, 13 }, + { 17, 13 }, { 20, 13 }, { 19, 13 }, { 13, 10 }, { 30, 10 }, { 6, 11 }, + { 22, 13 }, { 21, 13 }, { 14, 13 }, { 16, 14 }, { 15, 14 }, { 8, 9 }, + { 12, 6 }, { 23, 5 }, { 11, 6 }, { 25, 6 }, { 28, 5 }, { 0, 3 }, + { 3, 4 }, { 1, 4 }, { 26, 6 }, { 27, 6 }, { 24, 6 }, { 4, 6 }, + { 29, 5 }, { 2, 5 }, }, { /* AC bias group 4, table 15 */ - { 0x0, 2 }, { 0x7, 4 }, { 0xD, 5 }, { 0x5, 4 }, - { 0x9, 5 }, { 0x22, 7 }, { 0xCD1, 13 }, { 0xCD0, 13 }, - { 0xCD3, 13 }, { 0x3, 2 }, { 0x2, 2 }, { 0x8D, 9 }, - { 0xCC, 9 }, { 0x66B, 12 }, { 0xCD2, 13 }, { 0x19B5, 14 }, - { 0x19B4, 14 }, { 0x19B7, 14 }, { 0x19B6, 14 }, { 0x19B1, 14 }, - { 0x19B0, 14 }, { 0x19B3, 14 }, { 0x19B2, 14 }, { 0x47, 8 }, - { 0x8C, 9 }, { 0x337, 11 }, { 0x67, 8 }, { 0x18, 6 }, - { 0x10, 6 }, { 0x32, 7 }, { 0xCD5, 13 }, { 0xCD4, 13 } - } + { 0, 2 }, { 28, 6 }, { 5, 7 }, { 24, 9 }, { 11, 9 }, { 23, 8 }, + { 4, 5 }, { 3, 4 }, { 27, 6 }, { 29, 7 }, { 12, 9 }, { 7, 13 }, + { 6, 13 }, { 14, 13 }, { 8, 13 }, { 31, 13 }, { 30, 13 }, { 13, 12 }, + { 20, 14 }, { 19, 14 }, { 22, 14 }, { 21, 14 }, { 16, 14 }, { 15, 14 }, + { 18, 14 }, { 17, 14 }, { 25, 11 }, { 26, 8 }, { 2, 5 }, { 1, 4 }, + { 10, 2 }, { 9, 2 }, + }, }; #endif /* AVCODEC_VP4DATA_H */ diff -Nru ffmpeg-4.2.2/libavcodec/vp56.h ffmpeg-4.4/libavcodec/vp56.h --- ffmpeg-4.2.2/libavcodec/vp56.h 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp56.h 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,8 @@ #ifndef AVCODEC_VP56_H #define AVCODEC_VP56_H +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "get_bits.h" #include "hpeldsp.h" diff -Nru ffmpeg-4.2.2/libavcodec/vp8.c ffmpeg-4.4/libavcodec/vp8.c --- ffmpeg-4.2.2/libavcodec/vp8.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp8.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,9 +25,10 @@ */ #include "libavutil/imgutils.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "internal.h" #include "mathops.h" #include "rectangle.h" @@ -187,7 +188,7 @@ int update_dimensions(VP8Context *s, int width, int height, int is_vp7) { AVCodecContext *avctx = s->avctx; - int i, ret; + int i, ret, dim_reset = 0; if (width != s->avctx->width || ((width+15)/16 != s->mb_width || (height+15)/16 != s->mb_height) && s->macroblocks_base || height != s->avctx->height) { @@ -196,9 +197,12 @@ ret = ff_set_dimensions(s->avctx, width, height); if (ret < 0) return ret; + + dim_reset = (s->macroblocks_base != NULL); } - if (!s->actually_webp && !is_vp7) { + if ((s->pix_fmt == AV_PIX_FMT_NONE || dim_reset) && + !s->actually_webp && !is_vp7) { s->pix_fmt = get_pixel_format(s); if (s->pix_fmt < 0) return AVERROR(EINVAL); @@ -501,15 +505,10 @@ } } -static int vp7_fade_frame(VP8Context *s, VP56RangeCoder *c) +static int vp7_fade_frame(VP8Context *s, int alpha, int beta) { - int alpha = (int8_t) vp8_rac_get_uint(c, 8); - int beta = (int8_t) vp8_rac_get_uint(c, 8); int ret; - if (c->end <= c->buffer && c->bits >= 0) - return AVERROR_INVALIDDATA; - if (!s->keyframe && (alpha || beta)) { int width = s->mb_width * 16; int height = s->mb_height * 16; @@ -549,6 +548,8 @@ int part1_size, hscale, vscale, i, j, ret; int width = s->avctx->width; int height = s->avctx->height; + int alpha = 0; + int beta = 0; if (buf_size < 4) { return AVERROR_INVALIDDATA; @@ -665,8 +666,8 @@ return AVERROR_INVALIDDATA; /* E. Fading information for previous frame */ if (s->fade_present && vp8_rac_get(c)) { - if ((ret = vp7_fade_frame(s ,c)) < 0) - return ret; + alpha = (int8_t) vp8_rac_get_uint(c, 8); + beta = (int8_t) vp8_rac_get_uint(c, 8); } /* F. Loop filter type */ @@ -696,6 +697,12 @@ vp78_update_pred16x16_pred8x8_mvc_probabilities(s, VP7_MVC_SIZE); } + if (vpX_rac_is_end(c)) + return AVERROR_INVALIDDATA; + + if ((ret = vp7_fade_frame(s, alpha, beta)) < 0) + return ret; + return 0; } @@ -2286,10 +2293,10 @@ s->mv_bounds.mv_min.x = -MARGIN; s->mv_bounds.mv_max.x = ((s->mb_width - 1) << 6) + MARGIN; - if (vpX_rac_is_end(&s->c)) { - return AVERROR_INVALIDDATA; - } for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) { + if (vpX_rac_is_end(&s->c)) { + return AVERROR_INVALIDDATA; + } if (mb_y == 0) AV_WN32A((mb - s->mb_width - 1)->intra4x4_pred_mode_top, DC_PRED * 0x01010101); @@ -2615,7 +2622,7 @@ static av_always_inline int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt, int is_vp7) + const AVPacket *avpkt, int is_vp7) { VP8Context *s = avctx->priv_data; int ret, i, referenced, num_jobs; @@ -2712,7 +2719,8 @@ s->next_framep[VP56_FRAME_CURRENT] = curframe; - ff_thread_finish_setup(avctx); + if (avctx->codec->update_thread_context) + ff_thread_finish_setup(avctx); if (avctx->hwaccel) { ret = avctx->hwaccel->start_frame(avctx, avpkt->data, avpkt->size); @@ -2849,7 +2857,6 @@ s->vp7 = avctx->codec->id == AV_CODEC_ID_VP7; s->pix_fmt = AV_PIX_FMT_NONE; avctx->pix_fmt = AV_PIX_FMT_YUV420P; - avctx->internal->allocate_progress = 1; ff_videodsp_init(&s->vdsp, 8); @@ -2891,21 +2898,6 @@ #if CONFIG_VP8_DECODER #if HAVE_THREADS -static av_cold int vp8_decode_init_thread_copy(AVCodecContext *avctx) -{ - VP8Context *s = avctx->priv_data; - int ret; - - s->avctx = avctx; - - if ((ret = vp8_init_frames(s)) < 0) { - ff_vp8_decode_free(avctx); - return ret; - } - - return 0; -} - #define REBASE(pic) ((pic) ? (pic) - &s_src->frames[0] + &s->frames[0] : NULL) static int vp8_decode_update_thread_context(AVCodecContext *dst, @@ -2973,9 +2965,8 @@ .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, .flush = vp8_decode_flush, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context), - .hw_configs = (const AVCodecHWConfigInternal*[]) { + .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_VP8_VAAPI_HWACCEL HWACCEL_VAAPI(vp8), #endif @@ -2984,5 +2975,6 @@ #endif NULL }, + .caps_internal = FF_CODEC_CAP_ALLOCATE_PROGRESS, }; #endif /* CONFIG_VP7_DECODER */ diff -Nru ffmpeg-4.2.2/libavcodec/vp8data.h ffmpeg-4.4/libavcodec/vp8data.h --- ffmpeg-4.2.2/libavcodec/vp8data.h 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp8data.h 2021-04-08 21:28:39.000000000 +0000 @@ -316,12 +316,6 @@ }, }; -static const int8_t vp8_segmentid_tree[][2] = { - { 1, 2 }, - { -0, -1 }, // '00', '01' - { -2, -3 }, // '10', '11' -}; - static const uint8_t vp8_coeff_band[16] = { 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7 }; diff -Nru ffmpeg-4.2.2/libavcodec/vp8.h ffmpeg-4.4/libavcodec/vp8.h --- ffmpeg-4.2.2/libavcodec/vp8.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp8.h 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,7 @@ #include #include "libavutil/buffer.h" +#include "libavutil/mem_internal.h" #include "libavutil/thread.h" #include "h264pred.h" diff -Nru ffmpeg-4.2.2/libavcodec/vp9block.c ffmpeg-4.4/libavcodec/vp9block.c --- ffmpeg-4.2.2/libavcodec/vp9block.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp9block.c 2020-07-11 10:39:30.000000000 +0000 @@ -1290,6 +1290,14 @@ b->uvtx = b->tx - ((s->ss_h && w4 * 2 == (1 << b->tx)) || (s->ss_v && h4 * 2 == (1 << b->tx))); + if (td->block_structure) { + td->block_structure[td->nb_block_structure].row = row; + td->block_structure[td->nb_block_structure].col = col; + td->block_structure[td->nb_block_structure].block_size_idx_x = av_log2(w4); + td->block_structure[td->nb_block_structure].block_size_idx_y = av_log2(h4); + td->nb_block_structure++; + } + if (!b->skip) { int has_coeffs; diff -Nru ffmpeg-4.2.2/libavcodec/vp9.c ffmpeg-4.4/libavcodec/vp9.c --- ffmpeg-4.2.2/libavcodec/vp9.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp9.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,7 +23,7 @@ #include "avcodec.h" #include "get_bits.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "internal.h" #include "profiles.h" #include "thread.h" @@ -34,6 +34,7 @@ #include "vp9dec.h" #include "libavutil/avassert.h" #include "libavutil/pixdesc.h" +#include "libavutil/video_enc_params.h" #define VP9_SYNCCODE 0x498342 @@ -93,6 +94,13 @@ static int vp9_alloc_entries(AVCodecContext *avctx, int n) { return 0; } #endif +static void vp9_tile_data_free(VP9TileData *td) +{ + av_freep(&td->b_base); + av_freep(&td->block_base); + av_freep(&td->block_structure); +} + static void vp9_frame_unref(AVCodecContext *avctx, VP9Frame *f) { ff_thread_release_buffer(avctx, &f->tf); @@ -112,10 +120,20 @@ return ret; sz = 64 * s->sb_cols * s->sb_rows; - f->extradata = av_buffer_allocz(sz * (1 + sizeof(VP9mvrefPair))); + if (sz != s->frame_extradata_pool_size) { + av_buffer_pool_uninit(&s->frame_extradata_pool); + s->frame_extradata_pool = av_buffer_pool_init(sz * (1 + sizeof(VP9mvrefPair)), NULL); + if (!s->frame_extradata_pool) { + s->frame_extradata_pool_size = 0; + goto fail; + } + s->frame_extradata_pool_size = sz; + } + f->extradata = av_buffer_pool_get(s->frame_extradata_pool); if (!f->extradata) { goto fail; } + memset(f->extradata->data, 0, f->extradata->size); f->segmentation_map = f->extradata->data; f->mv = (VP9mvrefPair *) (f->extradata->data + sz); @@ -173,7 +191,8 @@ #define HWACCEL_MAX (CONFIG_VP9_DXVA2_HWACCEL + \ CONFIG_VP9_D3D11VA_HWACCEL * 2 + \ CONFIG_VP9_NVDEC_HWACCEL + \ - CONFIG_VP9_VAAPI_HWACCEL) + CONFIG_VP9_VAAPI_HWACCEL + \ + CONFIG_VP9_VDPAU_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; VP9Context *s = avctx->priv_data; uint8_t *p; @@ -202,6 +221,9 @@ #if CONFIG_VP9_VAAPI_HWACCEL *fmtp++ = AV_PIX_FMT_VAAPI; #endif +#if CONFIG_VP9_VDPAU_HWACCEL + *fmtp++ = AV_PIX_FMT_VDPAU; +#endif break; case AV_PIX_FMT_YUV420P12: #if CONFIG_VP9_NVDEC_HWACCEL @@ -210,6 +232,9 @@ #if CONFIG_VP9_VAAPI_HWACCEL *fmtp++ = AV_PIX_FMT_VAAPI; #endif +#if CONFIG_VP9_VDPAU_HWACCEL + *fmtp++ = AV_PIX_FMT_VDPAU; +#endif break; } @@ -267,10 +292,8 @@ #undef assign if (s->td) { - for (i = 0; i < s->active_tile_cols; i++) { - av_freep(&s->td[i].b_base); - av_freep(&s->td[i].block_base); - } + for (i = 0; i < s->active_tile_cols; i++) + vp9_tile_data_free(&s->td[i]); } if (s->s.h.bpp != s->last_bpp) { @@ -292,8 +315,7 @@ if (td->b_base && td->block_base && s->block_alloc_using_2pass == s->s.frames[CUR_FRAME].uses_2pass) return 0; - av_free(td->b_base); - av_free(td->block_base); + vp9_tile_data_free(td); chroma_blocks = 64 * 64 >> (s->ss_h + s->ss_v); chroma_eobs = 16 * 16 >> (s->ss_h + s->ss_v); if (s->s.frames[CUR_FRAME].uses_2pass) { @@ -309,13 +331,16 @@ td->eob_base = (uint8_t *) (td->uvblock_base[1] + sbs * chroma_blocks * bytesperpixel); td->uveob_base[0] = td->eob_base + 16 * 16 * sbs; td->uveob_base[1] = td->uveob_base[0] + chroma_eobs * sbs; - } else { - for (i = 1; i < s->active_tile_cols; i++) { - if (s->td[i].b_base && s->td[i].block_base) { - av_free(s->td[i].b_base); - av_free(s->td[i].block_base); - } + + if (avctx->export_side_data & AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS) { + td->block_structure = av_malloc_array(s->cols * s->rows, sizeof(*td->block_structure)); + if (!td->block_structure) + return AVERROR(ENOMEM); } + } else { + for (i = 1; i < s->active_tile_cols; i++) + vp9_tile_data_free(&s->td[i]); + for (i = 0; i < s->active_tile_cols; i++) { s->td[i].b_base = av_malloc(sizeof(VP9Block)); s->td[i].block_base = av_mallocz((64 * 64 + 2 * chroma_blocks) * bytesperpixel * sizeof(int16_t) + @@ -327,6 +352,12 @@ s->td[i].eob_base = (uint8_t *) (s->td[i].uvblock_base[1] + chroma_blocks * bytesperpixel); s->td[i].uveob_base[0] = s->td[i].eob_base + 16 * 16; s->td[i].uveob_base[1] = s->td[i].uveob_base[0] + chroma_eobs; + + if (avctx->export_side_data & AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS) { + s->td[i].block_structure = av_malloc_array(s->cols * s->rows, sizeof(*td->block_structure)); + if (!s->td[i].block_structure) + return AVERROR(ENOMEM); + } } } s->block_alloc_using_2pass = s->s.frames[CUR_FRAME].uses_2pass; @@ -510,7 +541,7 @@ s->s.h.use_last_frame_mvs = !s->s.h.errorres && !last_invisible; if (s->s.h.keyframe) { - if (get_bits_long(&s->gb, 24) != VP9_SYNCCODE) { // synccode + if (get_bits(&s->gb, 24) != VP9_SYNCCODE) { // synccode av_log(avctx, AV_LOG_ERROR, "Invalid sync code\n"); return AVERROR_INVALIDDATA; } @@ -526,7 +557,7 @@ s->s.h.intraonly = s->s.h.invisible ? get_bits1(&s->gb) : 0; s->s.h.resetctx = s->s.h.errorres ? 0 : get_bits(&s->gb, 2); if (s->s.h.intraonly) { - if (get_bits_long(&s->gb, 24) != VP9_SYNCCODE) { // synccode + if (get_bits(&s->gb, 24) != VP9_SYNCCODE) { // synccode av_log(avctx, AV_LOG_ERROR, "Invalid sync code\n"); return AVERROR_INVALIDDATA; } @@ -759,10 +790,8 @@ VP56RangeCoder *rc; if (s->td) { - for (i = 0; i < s->active_tile_cols; i++) { - av_free(s->td[i].b_base); - av_free(s->td[i].block_base); - } + for (i = 0; i < s->active_tile_cols; i++) + vp9_tile_data_free(&s->td[i]); av_free(s->td); } @@ -790,6 +819,7 @@ /* check reference frames */ if (!s->s.h.keyframe && !s->s.h.intraonly) { + int valid_ref_frame = 0; for (i = 0; i < 3; i++) { AVFrame *ref = s->s.refs[s->s.h.refidx[i]].f; int refw = ref->width, refh = ref->height; @@ -803,17 +833,25 @@ } else if (refw == w && refh == h) { s->mvscale[i][0] = s->mvscale[i][1] = 0; } else { + /* Check to make sure at least one of frames that */ + /* this frame references has valid dimensions */ if (w * 2 < refw || h * 2 < refh || w > 16 * refw || h > 16 * refh) { - av_log(avctx, AV_LOG_ERROR, + av_log(avctx, AV_LOG_WARNING, "Invalid ref frame dimensions %dx%d for frame size %dx%d\n", refw, refh, w, h); - return AVERROR_INVALIDDATA; + s->mvscale[i][0] = s->mvscale[i][1] = REF_INVALID_SCALE; + continue; } s->mvscale[i][0] = (refw << 14) / w; s->mvscale[i][1] = (refh << 14) / h; s->mvstep[i][0] = 16 * s->mvscale[i][0] >> 14; s->mvstep[i][1] = 16 * s->mvscale[i][1] >> 14; } + valid_ref_frame++; + } + if (!valid_ref_frame) { + av_log(avctx, AV_LOG_ERROR, "No valid reference frame is found, bitstream not supported\n"); + return AVERROR_INVALIDDATA; } } @@ -859,6 +897,7 @@ } else { memset(&s->td[i].counts, 0, sizeof(s->td[0].counts)); } + s->td[i].nb_block_structure = 0; } /* FIXME is it faster to not copy here, but do it down in the fw updates @@ -1190,10 +1229,8 @@ int i; av_freep(&s->intra_pred_data[0]); - for (i = 0; i < s->active_tile_cols; i++) { - av_freep(&s->td[i].b_base); - av_freep(&s->td[i].block_base); - } + for (i = 0; i < s->active_tile_cols; i++) + vp9_tile_data_free(&s->td[i]); } static av_cold int vp9_decode_free(AVCodecContext *avctx) @@ -1202,16 +1239,14 @@ int i; for (i = 0; i < 3; i++) { - if (s->s.frames[i].tf.f->buf[0]) - vp9_frame_unref(avctx, &s->s.frames[i]); + vp9_frame_unref(avctx, &s->s.frames[i]); av_frame_free(&s->s.frames[i].tf.f); } + av_buffer_pool_uninit(&s->frame_extradata_pool); for (i = 0; i < 8; i++) { - if (s->s.refs[i].f->buf[0]) - ff_thread_release_buffer(avctx, &s->s.refs[i]); + ff_thread_release_buffer(avctx, &s->s.refs[i]); av_frame_free(&s->s.refs[i].f); - if (s->next_refs[i].f->buf[0]) - ff_thread_release_buffer(avctx, &s->next_refs[i]); + ff_thread_release_buffer(avctx, &s->next_refs[i]); av_frame_free(&s->next_refs[i].f); } @@ -1464,6 +1499,58 @@ } #endif +static int vp9_export_enc_params(VP9Context *s, VP9Frame *frame) +{ + AVVideoEncParams *par; + unsigned int tile, nb_blocks = 0; + + if (s->s.h.segmentation.enabled) { + for (tile = 0; tile < s->active_tile_cols; tile++) + nb_blocks += s->td[tile].nb_block_structure; + } + + par = av_video_enc_params_create_side_data(frame->tf.f, + AV_VIDEO_ENC_PARAMS_VP9, nb_blocks); + if (!par) + return AVERROR(ENOMEM); + + par->qp = s->s.h.yac_qi; + par->delta_qp[0][0] = s->s.h.ydc_qdelta; + par->delta_qp[1][0] = s->s.h.uvdc_qdelta; + par->delta_qp[2][0] = s->s.h.uvdc_qdelta; + par->delta_qp[1][1] = s->s.h.uvac_qdelta; + par->delta_qp[2][1] = s->s.h.uvac_qdelta; + + if (nb_blocks) { + unsigned int block = 0; + unsigned int tile, block_tile; + + for (tile = 0; tile < s->active_tile_cols; tile++) { + VP9TileData *td = &s->td[tile]; + + for (block_tile = 0; block_tile < td->nb_block_structure; block_tile++) { + AVVideoBlockParams *b = av_video_enc_params_block(par, block++); + unsigned int row = td->block_structure[block_tile].row; + unsigned int col = td->block_structure[block_tile].col; + uint8_t seg_id = frame->segmentation_map[row * 8 * s->sb_cols + col]; + + b->src_x = col * 8; + b->src_y = row * 8; + b->w = 1 << (3 + td->block_structure[block_tile].block_size_idx_x); + b->h = 1 << (3 + td->block_structure[block_tile].block_size_idx_y); + + if (s->s.h.segmentation.feat[seg_id].q_enabled) { + b->delta_qp = s->s.h.segmentation.feat[seg_id].q_val; + if (s->s.h.segmentation.absolute_vals) + b->delta_qp -= par->qp; + } + } + } + } + + return 0; +} + static int vp9_decode_frame(AVCodecContext *avctx, void *frame, int *got_frame, AVPacket *pkt) { @@ -1610,6 +1697,7 @@ s->td[i].eob = s->td[i].eob_base; s->td[i].uveob[0] = s->td[i].uveob_base[0]; s->td[i].uveob[1] = s->td[i].uveob_base[1]; + s->td[i].error_info = 0; } #if HAVE_THREADS @@ -1666,6 +1754,17 @@ } while (s->pass++ == 1); ff_thread_report_progress(&s->s.frames[CUR_FRAME].tf, INT_MAX, 0); + if (s->td->error_info < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to decode tile data\n"); + s->td->error_info = 0; + return AVERROR_INVALIDDATA; + } + if (avctx->export_side_data & AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS) { + ret = vp9_export_enc_params(s, &s->s.frames[CUR_FRAME]); + if (ret < 0) + return ret; + } + finish: // ref frame setup for (i = 0; i < 8; i++) { @@ -1726,7 +1825,6 @@ { VP9Context *s = avctx->priv_data; - avctx->internal->allocate_progress = 1; s->last_bpp = 0; s->s.h.filter.sharpness = -1; @@ -1734,11 +1832,6 @@ } #if HAVE_THREADS -static av_cold int vp9_decode_init_thread_copy(AVCodecContext *avctx) -{ - return init_frames(avctx); -} - static int vp9_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) { int i, ret; @@ -1795,13 +1888,13 @@ .close = vp9_decode_free, .decode = vp9_decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, - .caps_internal = FF_CODEC_CAP_SLICE_THREAD_HAS_MF, + .caps_internal = FF_CODEC_CAP_SLICE_THREAD_HAS_MF | + FF_CODEC_CAP_ALLOCATE_PROGRESS, .flush = vp9_decode_flush, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp9_decode_init_thread_copy), .update_thread_context = ONLY_IF_THREADS_ENABLED(vp9_decode_update_thread_context), .profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), .bsfs = "vp9_superframe_split", - .hw_configs = (const AVCodecHWConfigInternal*[]) { + .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_VP9_DXVA2_HWACCEL HWACCEL_DXVA2(vp9), #endif @@ -1817,6 +1910,9 @@ #if CONFIG_VP9_VAAPI_HWACCEL HWACCEL_VAAPI(vp9), #endif +#if CONFIG_VP9_VDPAU_HWACCEL + HWACCEL_VDPAU(vp9), +#endif NULL }, }; diff -Nru ffmpeg-4.2.2/libavcodec/vp9dec.h ffmpeg-4.4/libavcodec/vp9dec.h --- ffmpeg-4.2.2/libavcodec/vp9dec.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp9dec.h 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,7 @@ #include #include "libavutil/buffer.h" +#include "libavutil/mem_internal.h" #include "libavutil/thread.h" #include "libavutil/internal.h" @@ -36,6 +37,8 @@ #include "vp9dsp.h" #include "vp9shared.h" +#define REF_INVALID_SCALE 0xFFFF + enum MVJoint { MV_JOINT_ZERO, MV_JOINT_H, @@ -152,6 +155,10 @@ int block_alloc_using_2pass; uint16_t mvscale[3][2]; uint8_t mvstep[3][2]; + + // frame specific buffer pools + AVBufferPool *frame_extradata_pool; + int frame_extradata_pool_size; } VP9Context; struct VP9TileData { @@ -217,6 +224,16 @@ struct { int x, y; } min_mv, max_mv; int16_t *block_base, *block, *uvblock_base[2], *uvblock[2]; uint8_t *eob_base, *uveob_base[2], *eob, *uveob[2]; + + // error message + int error_info; + struct { + unsigned int row:13; + unsigned int col:13; + unsigned int block_size_idx_x:2; + unsigned int block_size_idx_y:2; + } *block_structure; + unsigned int nb_block_structure; }; void ff_vp9_fill_mv(VP9TileData *td, VP56mv *mv, int mode, int sb); diff -Nru ffmpeg-4.2.2/libavcodec/vp9dsp.c ffmpeg-4.4/libavcodec/vp9dsp.c --- ffmpeg-4.2.2/libavcodec/vp9dsp.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp9dsp.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,8 @@ #include "libavutil/avassert.h" #include "libavutil/common.h" +#include "libavutil/mem_internal.h" + #include "vp9dsp.h" const DECLARE_ALIGNED(16, int16_t, ff_vp9_subpel_filters)[3][16][8] = { diff -Nru ffmpeg-4.2.2/libavcodec/vp9dsp_template.c ffmpeg-4.4/libavcodec/vp9dsp_template.c --- ffmpeg-4.2.2/libavcodec/vp9dsp_template.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp9dsp_template.c 2021-02-20 20:27:47.000000000 +0000 @@ -1138,7 +1138,7 @@ for (j = 0; j < sz; j++) \ dst[j * stride] = av_clip_pixel(dst[j * stride] + \ (bits ? \ - (t + (1 << (bits - 1))) >> bits : \ + (int)(t + (1U << (bits - 1))) >> bits : \ t)); \ dst++; \ } \ @@ -1153,7 +1153,7 @@ for (j = 0; j < sz; j++) \ dst[j * stride] = av_clip_pixel(dst[j * stride] + \ (bits ? \ - (out[j] + (1 << (bits - 1))) >> bits : \ + (int)(out[j] + (1U << (bits - 1))) >> bits : \ out[j])); \ dst++; \ } \ @@ -1260,25 +1260,25 @@ t6 = (t2a - t6a + (1 << 13)) >> 14; t7 = (t3a - t7a + (1 << 13)) >> 14; - t4a = 15137 * t4 + 6270 * t5; - t5a = 6270 * t4 - 15137 * t5; - t6a = 15137 * t7 - 6270 * t6; - t7a = 6270 * t7 + 15137 * t6; + t4a = 15137U * t4 + 6270U * t5; + t5a = 6270U * t4 - 15137U * t5; + t6a = 15137U * t7 - 6270U * t6; + t7a = 6270U * t7 + 15137U * t6; out[0] = t0 + t2; out[7] = -(t1 + t3); t2 = t0 - t2; t3 = t1 - t3; - out[1] = -((t4a + t6a + (1 << 13)) >> 14); - out[6] = (t5a + t7a + (1 << 13)) >> 14; - t6 = (t4a - t6a + (1 << 13)) >> 14; - t7 = (t5a - t7a + (1 << 13)) >> 14; - - out[3] = -(((t2 + t3) * 11585 + (1 << 13)) >> 14); - out[4] = ((t2 - t3) * 11585 + (1 << 13)) >> 14; - out[2] = ((t6 + t7) * 11585 + (1 << 13)) >> 14; - out[5] = -(((t6 - t7) * 11585 + (1 << 13)) >> 14); + out[1] = -((dctint)((1U << 13) + t4a + t6a) >> 14); + out[6] = (dctint)((1U << 13) + t5a + t7a) >> 14; + t6 = (dctint)((1U << 13) + t4a - t6a) >> 14; + t7 = (dctint)((1U << 13) + t5a - t7a) >> 14; + + out[3] = -((dctint)((t2 + t3) * 11585U + (1 << 13)) >> 14); + out[4] = (dctint)((t2 - t3) * 11585U + (1 << 13)) >> 14; + out[2] = (dctint)((t6 + t7) * 11585U + (1 << 13)) >> 14; + out[5] = -((dctint)((t6 - t7) * 11585U + (1 << 13)) >> 14); } itxfm_wrap(8, 5) @@ -1290,22 +1290,22 @@ dctint t0a, t1a, t2a, t3a, t4a, t5a, t6a, t7a; dctint t8a, t9a, t10a, t11a, t12a, t13a, t14a, t15a; - t0a = ((IN(0) + IN(8)) * 11585 + (1 << 13)) >> 14; - t1a = ((IN(0) - IN(8)) * 11585 + (1 << 13)) >> 14; - t2a = (IN(4) * 6270 - IN(12) * 15137 + (1 << 13)) >> 14; - t3a = (IN(4) * 15137 + IN(12) * 6270 + (1 << 13)) >> 14; - t4a = (IN(2) * 3196 - IN(14) * 16069 + (1 << 13)) >> 14; - t7a = (IN(2) * 16069 + IN(14) * 3196 + (1 << 13)) >> 14; - t5a = (IN(10) * 13623 - IN(6) * 9102 + (1 << 13)) >> 14; - t6a = (IN(10) * 9102 + IN(6) * 13623 + (1 << 13)) >> 14; - t8a = (IN(1) * 1606 - IN(15) * 16305 + (1 << 13)) >> 14; - t15a = (IN(1) * 16305 + IN(15) * 1606 + (1 << 13)) >> 14; - t9a = (IN(9) * 12665 - IN(7) * 10394 + (1 << 13)) >> 14; - t14a = (IN(9) * 10394 + IN(7) * 12665 + (1 << 13)) >> 14; - t10a = (IN(5) * 7723 - IN(11) * 14449 + (1 << 13)) >> 14; - t13a = (IN(5) * 14449 + IN(11) * 7723 + (1 << 13)) >> 14; - t11a = (IN(13) * 15679 - IN(3) * 4756 + (1 << 13)) >> 14; - t12a = (IN(13) * 4756 + IN(3) * 15679 + (1 << 13)) >> 14; + t0a = (dctint)((IN(0) + IN(8)) * 11585U + (1 << 13)) >> 14; + t1a = (dctint)((IN(0) - IN(8)) * 11585U + (1 << 13)) >> 14; + t2a = (dctint)(IN(4) * 6270U - IN(12) * 15137U + (1 << 13)) >> 14; + t3a = (dctint)(IN(4) * 15137U + IN(12) * 6270U + (1 << 13)) >> 14; + t4a = (dctint)(IN(2) * 3196U - IN(14) * 16069U + (1 << 13)) >> 14; + t7a = (dctint)(IN(2) * 16069U + IN(14) * 3196U + (1 << 13)) >> 14; + t5a = (dctint)(IN(10) * 13623U - IN(6) * 9102U + (1 << 13)) >> 14; + t6a = (dctint)(IN(10) * 9102U + IN(6) * 13623U + (1 << 13)) >> 14; + t8a = (dctint)(IN(1) * 1606U - IN(15) * 16305U + (1 << 13)) >> 14; + t15a = (dctint)(IN(1) * 16305U + IN(15) * 1606U + (1 << 13)) >> 14; + t9a = (dctint)(IN(9) * 12665U - IN(7) * 10394U + (1 << 13)) >> 14; + t14a = (dctint)(IN(9) * 10394U + IN(7) * 12665U + (1 << 13)) >> 14; + t10a = (dctint)(IN(5) * 7723U - IN(11) * 14449U + (1 << 13)) >> 14; + t13a = (dctint)(IN(5) * 14449U + IN(11) * 7723U + (1 << 13)) >> 14; + t11a = (dctint)(IN(13) * 15679U - IN(3) * 4756U + (1 << 13)) >> 14; + t12a = (dctint)(IN(13) * 4756U + IN(3) * 15679U + (1 << 13)) >> 14; t0 = t0a + t3a; t1 = t1a + t2a; @@ -1324,12 +1324,12 @@ t14 = t15a - t14a; t15 = t15a + t14a; - t5a = ((t6 - t5) * 11585 + (1 << 13)) >> 14; - t6a = ((t6 + t5) * 11585 + (1 << 13)) >> 14; - t9a = ( t14 * 6270 - t9 * 15137 + (1 << 13)) >> 14; - t14a = ( t14 * 15137 + t9 * 6270 + (1 << 13)) >> 14; - t10a = (-(t13 * 15137 + t10 * 6270) + (1 << 13)) >> 14; - t13a = ( t13 * 6270 - t10 * 15137 + (1 << 13)) >> 14; + t5a = (dctint)((t6 - t5) * 11585U + (1 << 13)) >> 14; + t6a = (dctint)((t6 + t5) * 11585U + (1 << 13)) >> 14; + t9a = (dctint)( t14 * 6270U - t9 * 15137U + (1 << 13)) >> 14; + t14a = (dctint)( t14 * 15137U + t9 * 6270U + (1 << 13)) >> 14; + t10a = (dctint)(-(t13 * 15137U + t10 * 6270U) + (1 << 13)) >> 14; + t13a = (dctint)( t13 * 6270U - t10 * 15137U + (1 << 13)) >> 14; t0a = t0 + t7; t1a = t1 + t6a; @@ -1348,10 +1348,10 @@ t14 = t14a + t13a; t15a = t15 + t12; - t10a = ((t13 - t10) * 11585 + (1 << 13)) >> 14; - t13a = ((t13 + t10) * 11585 + (1 << 13)) >> 14; - t11 = ((t12a - t11a) * 11585 + (1 << 13)) >> 14; - t12 = ((t12a + t11a) * 11585 + (1 << 13)) >> 14; + t10a = (dctint)((t13 - t10) * 11585U + (1 << 13)) >> 14; + t13a = (dctint)((t13 + t10) * 11585U + (1 << 13)) >> 14; + t11 = (dctint)((t12a - t11a) * 11585U + (1 << 13)) >> 14; + t12 = (dctint)((t12a + t11a) * 11585U + (1 << 13)) >> 14; out[ 0] = t0a + t15a; out[ 1] = t1a + t14; @@ -1378,48 +1378,48 @@ dctint t0a, t1a, t2a, t3a, t4a, t5a, t6a, t7a; dctint t8a, t9a, t10a, t11a, t12a, t13a, t14a, t15a; - t0 = IN(15) * 16364 + IN(0) * 804; - t1 = IN(15) * 804 - IN(0) * 16364; - t2 = IN(13) * 15893 + IN(2) * 3981; - t3 = IN(13) * 3981 - IN(2) * 15893; - t4 = IN(11) * 14811 + IN(4) * 7005; - t5 = IN(11) * 7005 - IN(4) * 14811; - t6 = IN(9) * 13160 + IN(6) * 9760; - t7 = IN(9) * 9760 - IN(6) * 13160; - t8 = IN(7) * 11003 + IN(8) * 12140; - t9 = IN(7) * 12140 - IN(8) * 11003; - t10 = IN(5) * 8423 + IN(10) * 14053; - t11 = IN(5) * 14053 - IN(10) * 8423; - t12 = IN(3) * 5520 + IN(12) * 15426; - t13 = IN(3) * 15426 - IN(12) * 5520; - t14 = IN(1) * 2404 + IN(14) * 16207; - t15 = IN(1) * 16207 - IN(14) * 2404; - - t0a = (t0 + t8 + (1 << 13)) >> 14; - t1a = (t1 + t9 + (1 << 13)) >> 14; - t2a = (t2 + t10 + (1 << 13)) >> 14; - t3a = (t3 + t11 + (1 << 13)) >> 14; - t4a = (t4 + t12 + (1 << 13)) >> 14; - t5a = (t5 + t13 + (1 << 13)) >> 14; - t6a = (t6 + t14 + (1 << 13)) >> 14; - t7a = (t7 + t15 + (1 << 13)) >> 14; - t8a = (t0 - t8 + (1 << 13)) >> 14; - t9a = (t1 - t9 + (1 << 13)) >> 14; - t10a = (t2 - t10 + (1 << 13)) >> 14; - t11a = (t3 - t11 + (1 << 13)) >> 14; - t12a = (t4 - t12 + (1 << 13)) >> 14; - t13a = (t5 - t13 + (1 << 13)) >> 14; - t14a = (t6 - t14 + (1 << 13)) >> 14; - t15a = (t7 - t15 + (1 << 13)) >> 14; - - t8 = t8a * 16069 + t9a * 3196; - t9 = t8a * 3196 - t9a * 16069; - t10 = t10a * 9102 + t11a * 13623; - t11 = t10a * 13623 - t11a * 9102; - t12 = t13a * 16069 - t12a * 3196; - t13 = t13a * 3196 + t12a * 16069; - t14 = t15a * 9102 - t14a * 13623; - t15 = t15a * 13623 + t14a * 9102; + t0 = IN(15) * 16364U + IN(0) * 804U; + t1 = IN(15) * 804U - IN(0) * 16364U; + t2 = IN(13) * 15893U + IN(2) * 3981U; + t3 = IN(13) * 3981U - IN(2) * 15893U; + t4 = IN(11) * 14811U + IN(4) * 7005U; + t5 = IN(11) * 7005U - IN(4) * 14811U; + t6 = IN(9) * 13160U + IN(6) * 9760U; + t7 = IN(9) * 9760U - IN(6) * 13160U; + t8 = IN(7) * 11003U + IN(8) * 12140U; + t9 = IN(7) * 12140U - IN(8) * 11003U; + t10 = IN(5) * 8423U + IN(10) * 14053U; + t11 = IN(5) * 14053U - IN(10) * 8423U; + t12 = IN(3) * 5520U + IN(12) * 15426U; + t13 = IN(3) * 15426U - IN(12) * 5520U; + t14 = IN(1) * 2404U + IN(14) * 16207U; + t15 = IN(1) * 16207U - IN(14) * 2404U; + + t0a = (dctint)((1U << 13) + t0 + t8 ) >> 14; + t1a = (dctint)((1U << 13) + t1 + t9 ) >> 14; + t2a = (dctint)((1U << 13) + t2 + t10) >> 14; + t3a = (dctint)((1U << 13) + t3 + t11) >> 14; + t4a = (dctint)((1U << 13) + t4 + t12) >> 14; + t5a = (dctint)((1U << 13) + t5 + t13) >> 14; + t6a = (dctint)((1U << 13) + t6 + t14) >> 14; + t7a = (dctint)((1U << 13) + t7 + t15) >> 14; + t8a = (dctint)((1U << 13) + t0 - t8 ) >> 14; + t9a = (dctint)((1U << 13) + t1 - t9 ) >> 14; + t10a = (dctint)((1U << 13) + t2 - t10) >> 14; + t11a = (dctint)((1U << 13) + t3 - t11) >> 14; + t12a = (dctint)((1U << 13) + t4 - t12) >> 14; + t13a = (dctint)((1U << 13) + t5 - t13) >> 14; + t14a = (dctint)((1U << 13) + t6 - t14) >> 14; + t15a = (dctint)((1U << 13) + t7 - t15) >> 14; + + t8 = t8a * 16069U + t9a * 3196U; + t9 = t8a * 3196U - t9a * 16069U; + t10 = t10a * 9102U + t11a * 13623U; + t11 = t10a * 13623U - t11a * 9102U; + t12 = t13a * 16069U - t12a * 3196U; + t13 = t13a * 3196U + t12a * 16069U; + t14 = t15a * 9102U - t14a * 13623U; + t15 = t15a * 13623U + t14a * 9102U; t0 = t0a + t4a; t1 = t1a + t5a; @@ -1429,49 +1429,49 @@ t5 = t1a - t5a; t6 = t2a - t6a; t7 = t3a - t7a; - t8a = (t8 + t12 + (1 << 13)) >> 14; - t9a = (t9 + t13 + (1 << 13)) >> 14; - t10a = (t10 + t14 + (1 << 13)) >> 14; - t11a = (t11 + t15 + (1 << 13)) >> 14; - t12a = (t8 - t12 + (1 << 13)) >> 14; - t13a = (t9 - t13 + (1 << 13)) >> 14; - t14a = (t10 - t14 + (1 << 13)) >> 14; - t15a = (t11 - t15 + (1 << 13)) >> 14; - - t4a = t4 * 15137 + t5 * 6270; - t5a = t4 * 6270 - t5 * 15137; - t6a = t7 * 15137 - t6 * 6270; - t7a = t7 * 6270 + t6 * 15137; - t12 = t12a * 15137 + t13a * 6270; - t13 = t12a * 6270 - t13a * 15137; - t14 = t15a * 15137 - t14a * 6270; - t15 = t15a * 6270 + t14a * 15137; + t8a = (dctint)((1U << 13) + t8 + t12) >> 14; + t9a = (dctint)((1U << 13) + t9 + t13) >> 14; + t10a = (dctint)((1U << 13) + t10 + t14) >> 14; + t11a = (dctint)((1U << 13) + t11 + t15) >> 14; + t12a = (dctint)((1U << 13) + t8 - t12) >> 14; + t13a = (dctint)((1U << 13) + t9 - t13) >> 14; + t14a = (dctint)((1U << 13) + t10 - t14) >> 14; + t15a = (dctint)((1U << 13) + t11 - t15) >> 14; + + t4a = t4 * 15137U + t5 * 6270U; + t5a = t4 * 6270U - t5 * 15137U; + t6a = t7 * 15137U - t6 * 6270U; + t7a = t7 * 6270U + t6 * 15137U; + t12 = t12a * 15137U + t13a * 6270U; + t13 = t12a * 6270U - t13a * 15137U; + t14 = t15a * 15137U - t14a * 6270U; + t15 = t15a * 6270U + t14a * 15137U; out[ 0] = t0 + t2; out[15] = -(t1 + t3); t2a = t0 - t2; t3a = t1 - t3; - out[ 3] = -((t4a + t6a + (1 << 13)) >> 14); - out[12] = (t5a + t7a + (1 << 13)) >> 14; - t6 = (t4a - t6a + (1 << 13)) >> 14; - t7 = (t5a - t7a + (1 << 13)) >> 14; + out[ 3] = -((dctint)((1U << 13) + t4a + t6a) >> 14); + out[12] = (dctint)((1U << 13) + t5a + t7a) >> 14; + t6 = (dctint)((1U << 13) + t4a - t6a) >> 14; + t7 = (dctint)((1U << 13) + t5a - t7a) >> 14; out[ 1] = -(t8a + t10a); out[14] = t9a + t11a; t10 = t8a - t10a; t11 = t9a - t11a; - out[ 2] = (t12 + t14 + (1 << 13)) >> 14; - out[13] = -((t13 + t15 + (1 << 13)) >> 14); - t14a = (t12 - t14 + (1 << 13)) >> 14; - t15a = (t13 - t15 + (1 << 13)) >> 14; - - out[ 7] = ((t2a + t3a) * -11585 + (1 << 13)) >> 14; - out[ 8] = ((t2a - t3a) * 11585 + (1 << 13)) >> 14; - out[ 4] = ((t7 + t6) * 11585 + (1 << 13)) >> 14; - out[11] = ((t7 - t6) * 11585 + (1 << 13)) >> 14; - out[ 6] = ((t11 + t10) * 11585 + (1 << 13)) >> 14; - out[ 9] = ((t11 - t10) * 11585 + (1 << 13)) >> 14; - out[ 5] = ((t14a + t15a) * -11585 + (1 << 13)) >> 14; - out[10] = ((t14a - t15a) * 11585 + (1 << 13)) >> 14; + out[ 2] = (dctint)((1U << 13) + t12 + t14) >> 14; + out[13] = -((dctint)((1U << 13) + t13 + t15) >> 14); + t14a = (dctint)((1U << 13) + t12 - t14) >> 14; + t15a = (dctint)((1U << 13) + t13 - t15) >> 14; + + out[ 7] = (dctint)(-(t2a + t3a) * 11585U + (1 << 13)) >> 14; + out[ 8] = (dctint)( (t2a - t3a) * 11585U + (1 << 13)) >> 14; + out[ 4] = (dctint)( (t7 + t6) * 11585U + (1 << 13)) >> 14; + out[11] = (dctint)( (t7 - t6) * 11585U + (1 << 13)) >> 14; + out[ 6] = (dctint)( (t11 + t10) * 11585U + (1 << 13)) >> 14; + out[ 9] = (dctint)( (t11 - t10) * 11585U + (1 << 13)) >> 14; + out[ 5] = (dctint)(-(t14a + t15a) * 11585U + (1 << 13)) >> 14; + out[10] = (dctint)( (t14a - t15a) * 11585U + (1 << 13)) >> 14; } itxfm_wrap(16, 6) @@ -1479,38 +1479,38 @@ static av_always_inline void idct32_1d(const dctcoef *in, ptrdiff_t stride, dctcoef *out, int pass) { - dctint t0a = ((IN(0) + IN(16)) * 11585 + (1 << 13)) >> 14; - dctint t1a = ((IN(0) - IN(16)) * 11585 + (1 << 13)) >> 14; - dctint t2a = (IN( 8) * 6270 - IN(24) * 15137 + (1 << 13)) >> 14; - dctint t3a = (IN( 8) * 15137 + IN(24) * 6270 + (1 << 13)) >> 14; - dctint t4a = (IN( 4) * 3196 - IN(28) * 16069 + (1 << 13)) >> 14; - dctint t7a = (IN( 4) * 16069 + IN(28) * 3196 + (1 << 13)) >> 14; - dctint t5a = (IN(20) * 13623 - IN(12) * 9102 + (1 << 13)) >> 14; - dctint t6a = (IN(20) * 9102 + IN(12) * 13623 + (1 << 13)) >> 14; - dctint t8a = (IN( 2) * 1606 - IN(30) * 16305 + (1 << 13)) >> 14; - dctint t15a = (IN( 2) * 16305 + IN(30) * 1606 + (1 << 13)) >> 14; - dctint t9a = (IN(18) * 12665 - IN(14) * 10394 + (1 << 13)) >> 14; - dctint t14a = (IN(18) * 10394 + IN(14) * 12665 + (1 << 13)) >> 14; - dctint t10a = (IN(10) * 7723 - IN(22) * 14449 + (1 << 13)) >> 14; - dctint t13a = (IN(10) * 14449 + IN(22) * 7723 + (1 << 13)) >> 14; - dctint t11a = (IN(26) * 15679 - IN( 6) * 4756 + (1 << 13)) >> 14; - dctint t12a = (IN(26) * 4756 + IN( 6) * 15679 + (1 << 13)) >> 14; - dctint t16a = (IN( 1) * 804 - IN(31) * 16364 + (1 << 13)) >> 14; - dctint t31a = (IN( 1) * 16364 + IN(31) * 804 + (1 << 13)) >> 14; - dctint t17a = (IN(17) * 12140 - IN(15) * 11003 + (1 << 13)) >> 14; - dctint t30a = (IN(17) * 11003 + IN(15) * 12140 + (1 << 13)) >> 14; - dctint t18a = (IN( 9) * 7005 - IN(23) * 14811 + (1 << 13)) >> 14; - dctint t29a = (IN( 9) * 14811 + IN(23) * 7005 + (1 << 13)) >> 14; - dctint t19a = (IN(25) * 15426 - IN( 7) * 5520 + (1 << 13)) >> 14; - dctint t28a = (IN(25) * 5520 + IN( 7) * 15426 + (1 << 13)) >> 14; - dctint t20a = (IN( 5) * 3981 - IN(27) * 15893 + (1 << 13)) >> 14; - dctint t27a = (IN( 5) * 15893 + IN(27) * 3981 + (1 << 13)) >> 14; - dctint t21a = (IN(21) * 14053 - IN(11) * 8423 + (1 << 13)) >> 14; - dctint t26a = (IN(21) * 8423 + IN(11) * 14053 + (1 << 13)) >> 14; - dctint t22a = (IN(13) * 9760 - IN(19) * 13160 + (1 << 13)) >> 14; - dctint t25a = (IN(13) * 13160 + IN(19) * 9760 + (1 << 13)) >> 14; - dctint t23a = (IN(29) * 16207 - IN( 3) * 2404 + (1 << 13)) >> 14; - dctint t24a = (IN(29) * 2404 + IN( 3) * 16207 + (1 << 13)) >> 14; + dctint t0a = (dctint)((IN(0) + IN(16)) * 11585U + (1 << 13)) >> 14; + dctint t1a = (dctint)((IN(0) - IN(16)) * 11585U + (1 << 13)) >> 14; + dctint t2a = (dctint)(IN( 8) * 6270U - IN(24) * 15137U + (1 << 13)) >> 14; + dctint t3a = (dctint)(IN( 8) * 15137U + IN(24) * 6270U + (1 << 13)) >> 14; + dctint t4a = (dctint)(IN( 4) * 3196U - IN(28) * 16069U + (1 << 13)) >> 14; + dctint t7a = (dctint)(IN( 4) * 16069U + IN(28) * 3196U + (1 << 13)) >> 14; + dctint t5a = (dctint)(IN(20) * 13623U - IN(12) * 9102U + (1 << 13)) >> 14; + dctint t6a = (dctint)(IN(20) * 9102U + IN(12) * 13623U + (1 << 13)) >> 14; + dctint t8a = (dctint)(IN( 2) * 1606U - IN(30) * 16305U + (1 << 13)) >> 14; + dctint t15a = (dctint)(IN( 2) * 16305U + IN(30) * 1606U + (1 << 13)) >> 14; + dctint t9a = (dctint)(IN(18) * 12665U - IN(14) * 10394U + (1 << 13)) >> 14; + dctint t14a = (dctint)(IN(18) * 10394U + IN(14) * 12665U + (1 << 13)) >> 14; + dctint t10a = (dctint)(IN(10) * 7723U - IN(22) * 14449U + (1 << 13)) >> 14; + dctint t13a = (dctint)(IN(10) * 14449U + IN(22) * 7723U + (1 << 13)) >> 14; + dctint t11a = (dctint)(IN(26) * 15679U - IN( 6) * 4756U + (1 << 13)) >> 14; + dctint t12a = (dctint)(IN(26) * 4756U + IN( 6) * 15679U + (1 << 13)) >> 14; + dctint t16a = (dctint)(IN( 1) * 804U - IN(31) * 16364U + (1 << 13)) >> 14; + dctint t31a = (dctint)(IN( 1) * 16364U + IN(31) * 804U + (1 << 13)) >> 14; + dctint t17a = (dctint)(IN(17) * 12140U - IN(15) * 11003U + (1 << 13)) >> 14; + dctint t30a = (dctint)(IN(17) * 11003U + IN(15) * 12140U + (1 << 13)) >> 14; + dctint t18a = (dctint)(IN( 9) * 7005U - IN(23) * 14811U + (1 << 13)) >> 14; + dctint t29a = (dctint)(IN( 9) * 14811U + IN(23) * 7005U + (1 << 13)) >> 14; + dctint t19a = (dctint)(IN(25) * 15426U - IN( 7) * 5520U + (1 << 13)) >> 14; + dctint t28a = (dctint)(IN(25) * 5520U + IN( 7) * 15426U + (1 << 13)) >> 14; + dctint t20a = (dctint)(IN( 5) * 3981U - IN(27) * 15893U + (1 << 13)) >> 14; + dctint t27a = (dctint)(IN( 5) * 15893U + IN(27) * 3981U + (1 << 13)) >> 14; + dctint t21a = (dctint)(IN(21) * 14053U - IN(11) * 8423U + (1 << 13)) >> 14; + dctint t26a = (dctint)(IN(21) * 8423U + IN(11) * 14053U + (1 << 13)) >> 14; + dctint t22a = (dctint)(IN(13) * 9760U - IN(19) * 13160U + (1 << 13)) >> 14; + dctint t25a = (dctint)(IN(13) * 13160U + IN(19) * 9760U + (1 << 13)) >> 14; + dctint t23a = (dctint)(IN(29) * 16207U - IN( 3) * 2404U + (1 << 13)) >> 14; + dctint t24a = (dctint)(IN(29) * 2404U + IN( 3) * 16207U + (1 << 13)) >> 14; dctint t0 = t0a + t3a; dctint t1 = t1a + t2a; @@ -1545,20 +1545,20 @@ dctint t30 = t31a - t30a; dctint t31 = t31a + t30a; - t5a = ((t6 - t5) * 11585 + (1 << 13)) >> 14; - t6a = ((t6 + t5) * 11585 + (1 << 13)) >> 14; - t9a = ( t14 * 6270 - t9 * 15137 + (1 << 13)) >> 14; - t14a = ( t14 * 15137 + t9 * 6270 + (1 << 13)) >> 14; - t10a = (-(t13 * 15137 + t10 * 6270) + (1 << 13)) >> 14; - t13a = ( t13 * 6270 - t10 * 15137 + (1 << 13)) >> 14; - t17a = ( t30 * 3196 - t17 * 16069 + (1 << 13)) >> 14; - t30a = ( t30 * 16069 + t17 * 3196 + (1 << 13)) >> 14; - t18a = (-(t29 * 16069 + t18 * 3196) + (1 << 13)) >> 14; - t29a = ( t29 * 3196 - t18 * 16069 + (1 << 13)) >> 14; - t21a = ( t26 * 13623 - t21 * 9102 + (1 << 13)) >> 14; - t26a = ( t26 * 9102 + t21 * 13623 + (1 << 13)) >> 14; - t22a = (-(t25 * 9102 + t22 * 13623) + (1 << 13)) >> 14; - t25a = ( t25 * 13623 - t22 * 9102 + (1 << 13)) >> 14; + t5a = (dctint)((t6 - t5) * 11585U + (1 << 13)) >> 14; + t6a = (dctint)((t6 + t5) * 11585U + (1 << 13)) >> 14; + t9a = (dctint)( t14 * 6270U - t9 * 15137U + (1 << 13)) >> 14; + t14a = (dctint)( t14 * 15137U + t9 * 6270U + (1 << 13)) >> 14; + t10a = (dctint)(-(t13 * 15137U + t10 * 6270U) + (1 << 13)) >> 14; + t13a = (dctint)( t13 * 6270U - t10 * 15137U + (1 << 13)) >> 14; + t17a = (dctint)( t30 * 3196U - t17 * 16069U + (1 << 13)) >> 14; + t30a = (dctint)( t30 * 16069U + t17 * 3196U + (1 << 13)) >> 14; + t18a = (dctint)(-(t29 * 16069U + t18 * 3196U) + (1 << 13)) >> 14; + t29a = (dctint)( t29 * 3196U - t18 * 16069U + (1 << 13)) >> 14; + t21a = (dctint)( t26 * 13623U - t21 * 9102U + (1 << 13)) >> 14; + t26a = (dctint)( t26 * 9102U + t21 * 13623U + (1 << 13)) >> 14; + t22a = (dctint)(-(t25 * 9102U + t22 * 13623U) + (1 << 13)) >> 14; + t25a = (dctint)( t25 * 13623U - t22 * 9102U + (1 << 13)) >> 14; t0a = t0 + t7; t1a = t1 + t6a; @@ -1593,18 +1593,18 @@ t30 = t30a + t29a; t31a = t31 + t28; - t10a = ((t13 - t10) * 11585 + (1 << 13)) >> 14; - t13a = ((t13 + t10) * 11585 + (1 << 13)) >> 14; - t11 = ((t12a - t11a) * 11585 + (1 << 13)) >> 14; - t12 = ((t12a + t11a) * 11585 + (1 << 13)) >> 14; - t18a = ( t29 * 6270 - t18 * 15137 + (1 << 13)) >> 14; - t29a = ( t29 * 15137 + t18 * 6270 + (1 << 13)) >> 14; - t19 = ( t28a * 6270 - t19a * 15137 + (1 << 13)) >> 14; - t28 = ( t28a * 15137 + t19a * 6270 + (1 << 13)) >> 14; - t20 = (-(t27a * 15137 + t20a * 6270) + (1 << 13)) >> 14; - t27 = ( t27a * 6270 - t20a * 15137 + (1 << 13)) >> 14; - t21a = (-(t26 * 15137 + t21 * 6270) + (1 << 13)) >> 14; - t26a = ( t26 * 6270 - t21 * 15137 + (1 << 13)) >> 14; + t10a = (dctint)((t13 - t10) * 11585U + (1 << 13)) >> 14; + t13a = (dctint)((t13 + t10) * 11585U + (1 << 13)) >> 14; + t11 = (dctint)((t12a - t11a) * 11585U + (1 << 13)) >> 14; + t12 = (dctint)((t12a + t11a) * 11585U + (1 << 13)) >> 14; + t18a = (dctint)( t29 * 6270U - t18 * 15137U + (1 << 13)) >> 14; + t29a = (dctint)( t29 * 15137U + t18 * 6270U + (1 << 13)) >> 14; + t19 = (dctint)( t28a * 6270U - t19a * 15137U + (1 << 13)) >> 14; + t28 = (dctint)( t28a * 15137U + t19a * 6270U + (1 << 13)) >> 14; + t20 = (dctint)(-(t27a * 15137U + t20a * 6270U) + (1 << 13)) >> 14; + t27 = (dctint)( t27a * 6270U - t20a * 15137U + (1 << 13)) >> 14; + t21a = (dctint)(-(t26 * 15137U + t21 * 6270U) + (1 << 13)) >> 14; + t26a = (dctint)( t26 * 6270U - t21 * 15137U + (1 << 13)) >> 14; t0 = t0a + t15a; t1 = t1a + t14; @@ -1639,14 +1639,14 @@ t30a = t30 + t25; t31 = t31a + t24a; - t20 = ((t27a - t20a) * 11585 + (1 << 13)) >> 14; - t27 = ((t27a + t20a) * 11585 + (1 << 13)) >> 14; - t21a = ((t26 - t21 ) * 11585 + (1 << 13)) >> 14; - t26a = ((t26 + t21 ) * 11585 + (1 << 13)) >> 14; - t22 = ((t25a - t22a) * 11585 + (1 << 13)) >> 14; - t25 = ((t25a + t22a) * 11585 + (1 << 13)) >> 14; - t23a = ((t24 - t23 ) * 11585 + (1 << 13)) >> 14; - t24a = ((t24 + t23 ) * 11585 + (1 << 13)) >> 14; + t20 = (dctint)((t27a - t20a) * 11585U + (1 << 13)) >> 14; + t27 = (dctint)((t27a + t20a) * 11585U + (1 << 13)) >> 14; + t21a = (dctint)((t26 - t21 ) * 11585U + (1 << 13)) >> 14; + t26a = (dctint)((t26 + t21 ) * 11585U + (1 << 13)) >> 14; + t22 = (dctint)((t25a - t22a) * 11585U + (1 << 13)) >> 14; + t25 = (dctint)((t25a + t22a) * 11585U + (1 << 13)) >> 14; + t23a = (dctint)((t24 - t23 ) * 11585U + (1 << 13)) >> 14; + t24a = (dctint)((t24 + t23 ) * 11585U + (1 << 13)) >> 14; out[ 0] = t0 + t31; out[ 1] = t1 + t30a; diff -Nru ffmpeg-4.2.2/libavcodec/vp9_metadata_bsf.c ffmpeg-4.4/libavcodec/vp9_metadata_bsf.c --- ffmpeg-4.2.2/libavcodec/vp9_metadata_bsf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp9_metadata_bsf.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,86 +22,74 @@ #include "bsf.h" #include "cbs.h" +#include "cbs_bsf.h" #include "cbs_vp9.h" typedef struct VP9MetadataContext { - const AVClass *class; - - CodedBitstreamContext *cbc; - CodedBitstreamFragment fragment; + CBSBSFContext common; int color_space; int color_range; - int color_range_rgb_warned; + int color_warnings; } VP9MetadataContext; -static int vp9_metadata_filter(AVBSFContext *bsf, AVPacket *pkt) +static int vp9_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt, + CodedBitstreamFragment *frag) { VP9MetadataContext *ctx = bsf->priv_data; - CodedBitstreamFragment *frag = &ctx->fragment; - int err, i; - - err = ff_bsf_get_packet_ref(bsf, pkt); - if (err < 0) - return err; - - err = ff_cbs_read_packet(ctx->cbc, frag, pkt); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n"); - goto fail; - } + int i; for (i = 0; i < frag->nb_units; i++) { VP9RawFrame *frame = frag->units[i].content; VP9RawFrameHeader *header = &frame->header; + int profile = (header->profile_high_bit << 1) + header->profile_low_bit; - if (ctx->color_space >= 0) { - header->color_space = ctx->color_space; - } - if (ctx->color_range >= 0) { - if (ctx->color_range == 0 && - header->color_space == VP9_CS_RGB && - !ctx->color_range_rgb_warned) { - av_log(bsf, AV_LOG_WARNING, "Warning: color_range cannot " - "be set to limited in RGB streams.\n"); - ctx->color_range_rgb_warned = 1; - } else { + if (header->frame_type == VP9_KEY_FRAME || + header->intra_only && profile > 0) { + if (ctx->color_space >= 0) { + if (!(profile & 1) && ctx->color_space == VP9_CS_RGB) { + if (!(ctx->color_warnings & 2)) { + av_log(bsf, AV_LOG_WARNING, "Warning: RGB " + "incompatible with profiles 0 and 2.\n"); + ctx->color_warnings |= 2; + } + } else + header->color_space = ctx->color_space; + } + + if (ctx->color_range >= 0) header->color_range = ctx->color_range; + if (header->color_space == VP9_CS_RGB) { + if (!(ctx->color_warnings & 1) && !header->color_range) { + av_log(bsf, AV_LOG_WARNING, "Warning: Color space RGB " + "implicitly sets color range to PC range.\n"); + ctx->color_warnings |= 1; + } + header->color_range = 1; } + } else if (!(ctx->color_warnings & 4) && header->intra_only && !profile && + ctx->color_space >= 0 && ctx->color_space != VP9_CS_BT_601) { + av_log(bsf, AV_LOG_WARNING, "Warning: Intra-only frames in " + "profile 0 are automatically BT.601.\n"); + ctx->color_warnings |= 4; } } - err = ff_cbs_write_packet(ctx->cbc, pkt, frag); - if (err < 0) { - av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n"); - goto fail; - } - - err = 0; -fail: - ff_cbs_fragment_reset(ctx->cbc, frag); - - if (err < 0) - av_packet_unref(pkt); - - return err; + return 0; } -static int vp9_metadata_init(AVBSFContext *bsf) -{ - VP9MetadataContext *ctx = bsf->priv_data; - - return ff_cbs_init(&ctx->cbc, AV_CODEC_ID_VP9, bsf); -} +static const CBSBSFType vp9_metadata_type = { + .codec_id = AV_CODEC_ID_VP9, + .fragment_name = "superframe", + .unit_name = "frame", + .update_fragment = &vp9_metadata_update_fragment, +}; -static void vp9_metadata_close(AVBSFContext *bsf) +static int vp9_metadata_init(AVBSFContext *bsf) { - VP9MetadataContext *ctx = bsf->priv_data; - - ff_cbs_fragment_free(ctx->cbc, &ctx->fragment); - ff_cbs_close(&ctx->cbc); + return ff_cbs_bsf_generic_init(bsf, &vp9_metadata_type); } #define OFFSET(x) offsetof(VP9MetadataContext, x) @@ -152,7 +140,7 @@ .priv_data_size = sizeof(VP9MetadataContext), .priv_class = &vp9_metadata_class, .init = &vp9_metadata_init, - .close = &vp9_metadata_close, - .filter = &vp9_metadata_filter, + .close = &ff_cbs_bsf_generic_close, + .filter = &ff_cbs_bsf_generic_filter, .codec_ids = vp9_metadata_codec_ids, }; diff -Nru ffmpeg-4.2.2/libavcodec/vp9_raw_reorder_bsf.c ffmpeg-4.4/libavcodec/vp9_raw_reorder_bsf.c --- ffmpeg-4.2.2/libavcodec/vp9_raw_reorder_bsf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp9_raw_reorder_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -20,9 +20,9 @@ #include "libavutil/intmath.h" #include "libavutil/log.h" #include "libavutil/mem.h" -#include "libavutil/opt.h" #include "bsf.h" +#include "bsf_internal.h" #include "get_bits.h" #include "put_bits.h" @@ -292,7 +292,7 @@ return err; } - if (in->data[in->size - 1] & 0xe0 == 0xc0) { + if ((in->data[in->size - 1] & 0xe0) == 0xc0) { av_log(bsf, AV_LOG_ERROR, "Input in superframes is not " "supported.\n"); av_packet_free(&in); diff -Nru ffmpeg-4.2.2/libavcodec/vp9recon.c ffmpeg-4.4/libavcodec/vp9recon.c --- ffmpeg-4.2.2/libavcodec/vp9recon.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp9recon.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ */ #include "libavutil/avassert.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "internal.h" @@ -572,6 +573,16 @@ VP9Block *b = td->b; int row = td->row, col = td->col; + if (s->mvscale[b->ref[0]][0] == REF_INVALID_SCALE || + (b->comp && s->mvscale[b->ref[1]][0] == REF_INVALID_SCALE)) { + if (!s->td->error_info) { + s->td->error_info = AVERROR_INVALIDDATA; + av_log(NULL, AV_LOG_ERROR, "Bitstream not supported, " + "reference frame has invalid dimensions\n"); + } + return; + } + if (s->mvscale[b->ref[0]][0] || (b->comp && s->mvscale[b->ref[1]][0])) { if (bytesperpixel == 1) { inter_pred_scaled_8bpp(td); diff -Nru ffmpeg-4.2.2/libavcodec/vp9_superframe_bsf.c ffmpeg-4.4/libavcodec/vp9_superframe_bsf.c --- ffmpeg-4.2.2/libavcodec/vp9_superframe_bsf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp9_superframe_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -20,8 +20,9 @@ */ #include "libavutil/avassert.h" -#include "avcodec.h" + #include "bsf.h" +#include "bsf_internal.h" #include "get_bits.h" #define MAX_CACHE 8 @@ -97,26 +98,25 @@ return 0; } -static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out) +static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *pkt) { GetBitContext gb; VP9BSFContext *s = ctx->priv_data; - AVPacket *in; int res, invisible, profile, marker, uses_superframe_syntax = 0, n; - res = ff_bsf_get_packet(ctx, &in); + res = ff_bsf_get_packet_ref(ctx, pkt); if (res < 0) return res; - marker = in->data[in->size - 1]; + marker = pkt->data[pkt->size - 1]; if ((marker & 0xe0) == 0xc0) { int nbytes = 1 + ((marker >> 3) & 0x3); int n_frames = 1 + (marker & 0x7), idx_sz = 2 + n_frames * nbytes; - uses_superframe_syntax = in->size >= idx_sz && in->data[in->size - idx_sz] == marker; + uses_superframe_syntax = pkt->size >= idx_sz && pkt->data[pkt->size - idx_sz] == marker; } - if ((res = init_get_bits8(&gb, in->data, in->size)) < 0) + if ((res = init_get_bits8(&gb, pkt->data, pkt->size)) < 0) goto done; get_bits(&gb, 2); // frame marker @@ -138,8 +138,7 @@ goto done; } else if ((!invisible || uses_superframe_syntax) && !s->n_cache) { // passthrough - av_packet_move_ref(out, in); - goto done; + return 0; } else if (s->n_cache + 1 >= MAX_CACHE) { av_log(ctx, AV_LOG_ERROR, "Too many invisible frames\n"); @@ -147,19 +146,18 @@ goto done; } - av_packet_move_ref(s->cache[s->n_cache++], in); + av_packet_move_ref(s->cache[s->n_cache++], pkt); if (invisible) { - res = AVERROR(EAGAIN); - goto done; + return AVERROR(EAGAIN); } av_assert0(s->n_cache > 0); // build superframe - if ((res = merge_superframe(s->cache, s->n_cache, out)) < 0) + if ((res = merge_superframe(s->cache, s->n_cache, pkt)) < 0) goto done; - res = av_packet_copy_props(out, s->cache[s->n_cache - 1]); + res = av_packet_copy_props(pkt, s->cache[s->n_cache - 1]); if (res < 0) goto done; @@ -169,8 +167,7 @@ done: if (res < 0) - av_packet_unref(out); - av_packet_free(&in); + av_packet_unref(pkt); return res; } diff -Nru ffmpeg-4.2.2/libavcodec/vp9_superframe_split_bsf.c ffmpeg-4.4/libavcodec/vp9_superframe_split_bsf.c --- ffmpeg-4.2.2/libavcodec/vp9_superframe_split_bsf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vp9_superframe_split_bsf.c 2020-07-11 10:39:30.000000000 +0000 @@ -24,8 +24,8 @@ #include -#include "avcodec.h" #include "bsf.h" +#include "bsf_internal.h" #include "bytestream.h" #include "get_bits.h" diff -Nru ffmpeg-4.2.2/libavcodec/vqavideo.c ffmpeg-4.4/libavcodec/vqavideo.c --- ffmpeg-4.2.2/libavcodec/vqavideo.c 2019-12-01 22:46:47.000000000 +0000 +++ ffmpeg-4.4/libavcodec/vqavideo.c 2020-07-11 10:39:30.000000000 +0000 @@ -637,6 +637,11 @@ return 0; } +static const AVCodecDefault vqa_defaults[] = { + { "max_pixels", "320*240" }, + { NULL }, +}; + AVCodec ff_vqa_decoder = { .name = "vqavideo", .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios VQA (Vector Quantized Animation) video"), @@ -647,4 +652,5 @@ .close = vqa_decode_end, .decode = vqa_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .defaults = vqa_defaults, }; diff -Nru ffmpeg-4.2.2/libavcodec/wavpack.c ffmpeg-4.4/libavcodec/wavpack.c --- ffmpeg-4.2.2/libavcodec/wavpack.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wavpack.c 2021-04-08 21:28:39.000000000 +0000 @@ -1,6 +1,7 @@ /* * WavPack lossless audio decoder * Copyright (c) 2006,2011 Konstantin Shishkov + * Copyright (c) 2020 David Bryant * * This file is part of FFmpeg. * @@ -19,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/buffer.h" #include "libavutil/channel_layout.h" #define BITSTREAM_READER_LE @@ -29,18 +31,37 @@ #include "thread.h" #include "unary.h" #include "wavpack.h" +#include "dsd.h" /** * @file * WavPack lossless audio decoder */ -typedef struct SavedContext { - int offset; - int size; - int bits_used; - uint32_t crc; -} SavedContext; +#define DSD_BYTE_READY(low,high) (!(((low) ^ (high)) & 0xff000000)) + +#define PTABLE_BITS 8 +#define PTABLE_BINS (1<> 8) @@ -365,12 +398,6 @@ return value.f; } -static void wv_reset_saved_context(WavpackFrameContext *s) -{ - s->pos = 0; - s->sc.crc = s->extra_sc.crc = 0xFFFFFFFF; -} - static inline int wv_check_crc(WavpackFrameContext *s, uint32_t crc, uint32_t crc_extra_bits) { @@ -386,15 +413,372 @@ return 0; } +static void init_ptable(int *table, int rate_i, int rate_s) +{ + int value = 0x808000, rate = rate_i << 8; + + for (int c = (rate + 128) >> 8; c--;) + value += (DOWN - value) >> DECAY; + + for (int i = 0; i < PTABLE_BINS/2; i++) { + table[i] = value; + table[PTABLE_BINS-1-i] = 0x100ffff - value; + + if (value > 0x010000) { + rate += (rate * rate_s + 128) >> 8; + + for (int c = (rate + 64) >> 7; c--;) + value += (DOWN - value) >> DECAY; + } + } +} + +typedef struct { + int32_t value, fltr0, fltr1, fltr2, fltr3, fltr4, fltr5, fltr6, factor; + unsigned int byte; +} DSDfilters; + +static int wv_unpack_dsd_high(WavpackFrameContext *s, uint8_t *dst_left, uint8_t *dst_right) +{ + uint32_t checksum = 0xFFFFFFFF; + uint8_t *dst_l = dst_left, *dst_r = dst_right; + int total_samples = s->samples, stereo = dst_r ? 1 : 0; + DSDfilters filters[2], *sp = filters; + int rate_i, rate_s; + uint32_t low, high, value; + + if (bytestream2_get_bytes_left(&s->gbyte) < (stereo ? 20 : 13)) + return AVERROR_INVALIDDATA; + + rate_i = bytestream2_get_byte(&s->gbyte); + rate_s = bytestream2_get_byte(&s->gbyte); + + if (rate_s != RATE_S) + return AVERROR_INVALIDDATA; + + init_ptable(s->ptable, rate_i, rate_s); + + for (int channel = 0; channel < stereo + 1; channel++) { + DSDfilters *sp = filters + channel; + + sp->fltr1 = bytestream2_get_byte(&s->gbyte) << (PRECISION - 8); + sp->fltr2 = bytestream2_get_byte(&s->gbyte) << (PRECISION - 8); + sp->fltr3 = bytestream2_get_byte(&s->gbyte) << (PRECISION - 8); + sp->fltr4 = bytestream2_get_byte(&s->gbyte) << (PRECISION - 8); + sp->fltr5 = bytestream2_get_byte(&s->gbyte) << (PRECISION - 8); + sp->fltr6 = 0; + sp->factor = bytestream2_get_byte(&s->gbyte) & 0xff; + sp->factor |= (bytestream2_get_byte(&s->gbyte) << 8) & 0xff00; + sp->factor = (int32_t)((uint32_t)sp->factor << 16) >> 16; + } + + value = bytestream2_get_be32(&s->gbyte); + high = 0xffffffff; + low = 0x0; + + while (total_samples--) { + int bitcount = 8; + + sp[0].value = sp[0].fltr1 - sp[0].fltr5 + ((sp[0].fltr6 * sp[0].factor) >> 2); + + if (stereo) + sp[1].value = sp[1].fltr1 - sp[1].fltr5 + ((sp[1].fltr6 * sp[1].factor) >> 2); + + while (bitcount--) { + int32_t *pp = s->ptable + ((sp[0].value >> (PRECISION - PRECISION_USE)) & PTABLE_MASK); + uint32_t split = low + ((high - low) >> 8) * (*pp >> 16); + + if (value <= split) { + high = split; + *pp += (UP - *pp) >> DECAY; + sp[0].fltr0 = -1; + } else { + low = split + 1; + *pp += (DOWN - *pp) >> DECAY; + sp[0].fltr0 = 0; + } + + while (DSD_BYTE_READY(high, low) && bytestream2_get_bytes_left(&s->gbyte)) { + value = (value << 8) | bytestream2_get_byte(&s->gbyte); + high = (high << 8) | 0xff; + low <<= 8; + } + + sp[0].value += sp[0].fltr6 * 8; + sp[0].byte = (sp[0].byte << 1) | (sp[0].fltr0 & 1); + sp[0].factor += (((sp[0].value ^ sp[0].fltr0) >> 31) | 1) & + ((sp[0].value ^ (sp[0].value - (sp[0].fltr6 * 16))) >> 31); + sp[0].fltr1 += ((sp[0].fltr0 & VALUE_ONE) - sp[0].fltr1) >> 6; + sp[0].fltr2 += ((sp[0].fltr0 & VALUE_ONE) - sp[0].fltr2) >> 4; + sp[0].fltr3 += (sp[0].fltr2 - sp[0].fltr3) >> 4; + sp[0].fltr4 += (sp[0].fltr3 - sp[0].fltr4) >> 4; + sp[0].value = (sp[0].fltr4 - sp[0].fltr5) >> 4; + sp[0].fltr5 += sp[0].value; + sp[0].fltr6 += (sp[0].value - sp[0].fltr6) >> 3; + sp[0].value = sp[0].fltr1 - sp[0].fltr5 + ((sp[0].fltr6 * sp[0].factor) >> 2); + + if (!stereo) + continue; + + pp = s->ptable + ((sp[1].value >> (PRECISION - PRECISION_USE)) & PTABLE_MASK); + split = low + ((high - low) >> 8) * (*pp >> 16); + + if (value <= split) { + high = split; + *pp += (UP - *pp) >> DECAY; + sp[1].fltr0 = -1; + } else { + low = split + 1; + *pp += (DOWN - *pp) >> DECAY; + sp[1].fltr0 = 0; + } + + while (DSD_BYTE_READY(high, low) && bytestream2_get_bytes_left(&s->gbyte)) { + value = (value << 8) | bytestream2_get_byte(&s->gbyte); + high = (high << 8) | 0xff; + low <<= 8; + } + + sp[1].value += sp[1].fltr6 * 8; + sp[1].byte = (sp[1].byte << 1) | (sp[1].fltr0 & 1); + sp[1].factor += (((sp[1].value ^ sp[1].fltr0) >> 31) | 1) & + ((sp[1].value ^ (sp[1].value - (sp[1].fltr6 * 16))) >> 31); + sp[1].fltr1 += ((sp[1].fltr0 & VALUE_ONE) - sp[1].fltr1) >> 6; + sp[1].fltr2 += ((sp[1].fltr0 & VALUE_ONE) - sp[1].fltr2) >> 4; + sp[1].fltr3 += (sp[1].fltr2 - sp[1].fltr3) >> 4; + sp[1].fltr4 += (sp[1].fltr3 - sp[1].fltr4) >> 4; + sp[1].value = (sp[1].fltr4 - sp[1].fltr5) >> 4; + sp[1].fltr5 += sp[1].value; + sp[1].fltr6 += (sp[1].value - sp[1].fltr6) >> 3; + sp[1].value = sp[1].fltr1 - sp[1].fltr5 + ((sp[1].fltr6 * sp[1].factor) >> 2); + } + + checksum += (checksum << 1) + (*dst_l = sp[0].byte & 0xff); + sp[0].factor -= (sp[0].factor + 512) >> 10; + dst_l += 4; + + if (stereo) { + checksum += (checksum << 1) + (*dst_r = filters[1].byte & 0xff); + filters[1].factor -= (filters[1].factor + 512) >> 10; + dst_r += 4; + } + } + + if (wv_check_crc(s, checksum, 0)) { + if (s->avctx->err_recognition & AV_EF_CRCCHECK) + return AVERROR_INVALIDDATA; + + memset(dst_left, 0x69, s->samples * 4); + + if (dst_r) + memset(dst_right, 0x69, s->samples * 4); + } + + return 0; +} + +static int wv_unpack_dsd_fast(WavpackFrameContext *s, uint8_t *dst_left, uint8_t *dst_right) +{ + uint8_t *dst_l = dst_left, *dst_r = dst_right; + uint8_t history_bits, max_probability; + int total_summed_probabilities = 0; + int total_samples = s->samples; + uint8_t *vlb = s->value_lookup_buffer; + int history_bins, p0, p1, chan; + uint32_t checksum = 0xFFFFFFFF; + uint32_t low, high, value; + + if (!bytestream2_get_bytes_left(&s->gbyte)) + return AVERROR_INVALIDDATA; + + history_bits = bytestream2_get_byte(&s->gbyte); + + if (!bytestream2_get_bytes_left(&s->gbyte) || history_bits > MAX_HISTORY_BITS) + return AVERROR_INVALIDDATA; + + history_bins = 1 << history_bits; + max_probability = bytestream2_get_byte(&s->gbyte); + + if (max_probability < 0xff) { + uint8_t *outptr = (uint8_t *)s->probabilities; + uint8_t *outend = outptr + sizeof(*s->probabilities) * history_bins; + + while (outptr < outend && bytestream2_get_bytes_left(&s->gbyte)) { + int code = bytestream2_get_byte(&s->gbyte); + + if (code > max_probability) { + int zcount = code - max_probability; + + while (outptr < outend && zcount--) + *outptr++ = 0; + } else if (code) { + *outptr++ = code; + } + else { + break; + } + } + + if (outptr < outend || + (bytestream2_get_bytes_left(&s->gbyte) && bytestream2_get_byte(&s->gbyte))) + return AVERROR_INVALIDDATA; + } else if (bytestream2_get_bytes_left(&s->gbyte) > (int)sizeof(*s->probabilities) * history_bins) { + bytestream2_get_buffer(&s->gbyte, (uint8_t *)s->probabilities, + sizeof(*s->probabilities) * history_bins); + } else { + return AVERROR_INVALIDDATA; + } + + for (p0 = 0; p0 < history_bins; p0++) { + int32_t sum_values = 0; + + for (int i = 0; i < 256; i++) + s->summed_probabilities[p0][i] = sum_values += s->probabilities[p0][i]; + + if (sum_values) { + total_summed_probabilities += sum_values; + + if (total_summed_probabilities > history_bins * MAX_BIN_BYTES) + return AVERROR_INVALIDDATA; + + s->value_lookup[p0] = vlb; + + for (int i = 0; i < 256; i++) { + int c = s->probabilities[p0][i]; + + while (c--) + *vlb++ = i; + } + } + } + + if (bytestream2_get_bytes_left(&s->gbyte) < 4) + return AVERROR_INVALIDDATA; + + chan = p0 = p1 = 0; + low = 0; high = 0xffffffff; + value = bytestream2_get_be32(&s->gbyte); + + if (dst_r) + total_samples *= 2; + + while (total_samples--) { + unsigned int mult, index, code; + + if (!s->summed_probabilities[p0][255]) + return AVERROR_INVALIDDATA; + + mult = (high - low) / s->summed_probabilities[p0][255]; + + if (!mult) { + if (bytestream2_get_bytes_left(&s->gbyte) >= 4) + value = bytestream2_get_be32(&s->gbyte); + + low = 0; + high = 0xffffffff; + mult = high / s->summed_probabilities[p0][255]; + + if (!mult) + return AVERROR_INVALIDDATA; + } + + index = (value - low) / mult; + + if (index >= s->summed_probabilities[p0][255]) + return AVERROR_INVALIDDATA; + + if (!dst_r) { + if ((*dst_l = code = s->value_lookup[p0][index])) + low += s->summed_probabilities[p0][code-1] * mult; + + dst_l += 4; + } else { + if ((code = s->value_lookup[p0][index])) + low += s->summed_probabilities[p0][code-1] * mult; + + if (chan) { + *dst_r = code; + dst_r += 4; + } + else { + *dst_l = code; + dst_l += 4; + } + + chan ^= 1; + } + + high = low + s->probabilities[p0][code] * mult - 1; + checksum += (checksum << 1) + code; + + if (!dst_r) { + p0 = code & (history_bins-1); + } else { + p0 = p1; + p1 = code & (history_bins-1); + } + + while (DSD_BYTE_READY(high, low) && bytestream2_get_bytes_left(&s->gbyte)) { + value = (value << 8) | bytestream2_get_byte(&s->gbyte); + high = (high << 8) | 0xff; + low <<= 8; + } + } + + if (wv_check_crc(s, checksum, 0)) { + if (s->avctx->err_recognition & AV_EF_CRCCHECK) + return AVERROR_INVALIDDATA; + + memset(dst_left, 0x69, s->samples * 4); + + if (dst_r) + memset(dst_right, 0x69, s->samples * 4); + } + + return 0; +} + +static int wv_unpack_dsd_copy(WavpackFrameContext *s, uint8_t *dst_left, uint8_t *dst_right) +{ + uint8_t *dst_l = dst_left, *dst_r = dst_right; + int total_samples = s->samples; + uint32_t checksum = 0xFFFFFFFF; + + if (bytestream2_get_bytes_left(&s->gbyte) != total_samples * (dst_r ? 2 : 1)) + return AVERROR_INVALIDDATA; + + while (total_samples--) { + checksum += (checksum << 1) + (*dst_l = bytestream2_get_byte(&s->gbyte)); + dst_l += 4; + + if (dst_r) { + checksum += (checksum << 1) + (*dst_r = bytestream2_get_byte(&s->gbyte)); + dst_r += 4; + } + } + + if (wv_check_crc(s, checksum, 0)) { + if (s->avctx->err_recognition & AV_EF_CRCCHECK) + return AVERROR_INVALIDDATA; + + memset(dst_left, 0x69, s->samples * 4); + + if (dst_r) + memset(dst_right, 0x69, s->samples * 4); + } + + return 0; +} + static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb, void *dst_l, void *dst_r, const int type) { int i, j, count = 0; int last, t; int A, B, L, L2, R, R2; - int pos = s->pos; - uint32_t crc = s->sc.crc; - uint32_t crc_extra_bits = s->extra_sc.crc; + int pos = 0; + uint32_t crc = 0xFFFFFFFF; + uint32_t crc_extra_bits = 0xFFFFFFFF; int16_t *dst16_l = dst_l; int16_t *dst16_r = dst_r; int32_t *dst32_l = dst_l; @@ -504,8 +888,6 @@ count++; } while (!last && count < s->samples); - wv_reset_saved_context(s); - if (last && count < s->samples) { int size = av_get_bytes_per_sample(type); memset((uint8_t*)dst_l + count*size, 0, (s->samples-count)*size); @@ -525,9 +907,9 @@ int i, j, count = 0; int last, t; int A, S, T; - int pos = s->pos; - uint32_t crc = s->sc.crc; - uint32_t crc_extra_bits = s->extra_sc.crc; + int pos = 0; + uint32_t crc = 0xFFFFFFFF; + uint32_t crc_extra_bits = 0xFFFFFFFF; int16_t *dst16 = dst; int32_t *dst32 = dst; float *dstfl = dst; @@ -572,8 +954,6 @@ count++; } while (!last && count < s->samples); - wv_reset_saved_context(s); - if (last && count < s->samples) { int size = av_get_bytes_per_sample(type); memset((uint8_t*)dst + count*size, 0, (s->samples-count)*size); @@ -598,16 +978,62 @@ return -1; c->fdec_num++; c->fdec[c->fdec_num - 1]->avctx = c->avctx; - wv_reset_saved_context(c->fdec[c->fdec_num - 1]); + + return 0; +} + +static int wv_dsd_reset(WavpackContext *s, int channels) +{ + int i; + + s->dsdctx = NULL; + s->dsd_channels = 0; + av_buffer_unref(&s->dsd_ref); + + if (!channels) + return 0; + + if (channels > INT_MAX / sizeof(*s->dsdctx)) + return AVERROR(EINVAL); + + s->dsd_ref = av_buffer_allocz(channels * sizeof(*s->dsdctx)); + if (!s->dsd_ref) + return AVERROR(ENOMEM); + s->dsdctx = (DSDContext*)s->dsd_ref->data; + s->dsd_channels = channels; + + for (i = 0; i < channels; i++) + memset(s->dsdctx[i].buf, 0x69, sizeof(s->dsdctx[i].buf)); return 0; } #if HAVE_THREADS -static int init_thread_copy(AVCodecContext *avctx) +static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) { - WavpackContext *s = avctx->priv_data; - s->avctx = avctx; + WavpackContext *fsrc = src->priv_data; + WavpackContext *fdst = dst->priv_data; + int ret; + + if (dst == src) + return 0; + + ff_thread_release_buffer(dst, &fdst->curr_frame); + if (fsrc->curr_frame.f->data[0]) { + if ((ret = ff_thread_ref_frame(&fdst->curr_frame, &fsrc->curr_frame)) < 0) + return ret; + } + + fdst->dsdctx = NULL; + fdst->dsd_channels = 0; + ret = av_buffer_replace(&fdst->dsd_ref, fsrc->dsd_ref); + if (ret < 0) + return ret; + if (fsrc->dsd_ref) { + fdst->dsdctx = (DSDContext*)fdst->dsd_ref->data; + fdst->dsd_channels = fsrc->dsd_channels; + } + return 0; } #endif @@ -620,35 +1046,52 @@ s->fdec_num = 0; + s->curr_frame.f = av_frame_alloc(); + s->prev_frame.f = av_frame_alloc(); + + if (!s->curr_frame.f || !s->prev_frame.f) + return AVERROR(ENOMEM); + + ff_init_dsd_data(); + return 0; } static av_cold int wavpack_decode_end(AVCodecContext *avctx) { WavpackContext *s = avctx->priv_data; - int i; - for (i = 0; i < s->fdec_num; i++) + for (int i = 0; i < s->fdec_num; i++) av_freep(&s->fdec[i]); s->fdec_num = 0; + ff_thread_release_buffer(avctx, &s->curr_frame); + av_frame_free(&s->curr_frame.f); + + ff_thread_release_buffer(avctx, &s->prev_frame); + av_frame_free(&s->prev_frame.f); + + av_buffer_unref(&s->dsd_ref); + return 0; } static int wavpack_decode_block(AVCodecContext *avctx, int block_no, - AVFrame *frame, const uint8_t *buf, int buf_size) + const uint8_t *buf, int buf_size) { WavpackContext *wc = avctx->priv_data; - ThreadFrame tframe = { .f = frame }; WavpackFrameContext *s; GetByteContext gb; + enum AVSampleFormat sample_fmt; void *samples_l = NULL, *samples_r = NULL; int ret; int got_terms = 0, got_weights = 0, got_samples = 0, - got_entropy = 0, got_bs = 0, got_float = 0, got_hybrid = 0; + got_entropy = 0, got_pcm = 0, got_float = 0, got_hybrid = 0; + int got_dsd = 0; int i, j, id, size, ssize, weights, t; - int bpp, chan = 0, chmask = 0, orig_bpp, sample_rate = 0; + int bpp, chan = 0, orig_bpp, sample_rate = 0, rate_x = 1, dsd_mode = 0; int multiblock; + uint64_t chmask = 0; if (block_no >= wc->fdec_num && wv_alloc_frame_context(wc) < 0) { av_log(avctx, AV_LOG_ERROR, "Error creating frame decode context\n"); @@ -677,7 +1120,18 @@ return AVERROR_INVALIDDATA; } s->frame_flags = bytestream2_get_le32(&gb); - bpp = av_get_bytes_per_sample(avctx->sample_fmt); + + if (s->frame_flags & (WV_FLOAT_DATA | WV_DSD_DATA)) + sample_fmt = AV_SAMPLE_FMT_FLTP; + else if ((s->frame_flags & 0x03) <= 1) + sample_fmt = AV_SAMPLE_FMT_S16P; + else + sample_fmt = AV_SAMPLE_FMT_S32P; + + if (wc->ch_offset && avctx->sample_fmt != sample_fmt) + return AVERROR_INVALIDDATA; + + bpp = av_get_bytes_per_sample(sample_fmt); orig_bpp = ((s->frame_flags & 0x03) + 1) << 3; multiblock = (s->frame_flags & WV_SINGLE_BLOCK) != WV_SINGLE_BLOCK; @@ -698,10 +1152,8 @@ while (bytestream2_get_bytes_left(&gb)) { id = bytestream2_get_byte(&gb); size = bytestream2_get_byte(&gb); - if (id & WP_IDF_LONG) { - size |= (bytestream2_get_byte(&gb)) << 8; - size |= (bytestream2_get_byte(&gb)) << 16; - } + if (id & WP_IDF_LONG) + size |= (bytestream2_get_le16u(&gb)) << 8; size <<= 1; // size is specified in words ssize = size; if (id & WP_IDF_ODD) @@ -897,13 +1349,31 @@ bytestream2_skip(&gb, 1); break; case WP_ID_DATA: - s->sc.offset = bytestream2_tell(&gb); - s->sc.size = size * 8; if ((ret = init_get_bits8(&s->gb, gb.buffer, size)) < 0) return ret; - s->data_size = size * 8; bytestream2_skip(&gb, size); - got_bs = 1; + got_pcm = 1; + break; + case WP_ID_DSD_DATA: + if (size < 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid DSD_DATA, size = %i\n", + size); + bytestream2_skip(&gb, ssize); + continue; + } + rate_x = bytestream2_get_byte(&gb); + if (rate_x > 30) + return AVERROR_INVALIDDATA; + rate_x = 1 << rate_x; + dsd_mode = bytestream2_get_byte(&gb); + if (dsd_mode && dsd_mode != 1 && dsd_mode != 3) { + av_log(avctx, AV_LOG_ERROR, "Invalid DSD encoding mode: %d\n", + dsd_mode); + return AVERROR_INVALIDDATA; + } + bytestream2_init(&s->gbyte, gb.buffer, size-2); + bytestream2_skip(&gb, size-2); + got_dsd = 1; break; case WP_ID_EXTRABITS: if (size <= 4) { @@ -912,8 +1382,6 @@ bytestream2_skip(&gb, size); continue; } - s->extra_sc.offset = bytestream2_tell(&gb); - s->extra_sc.size = size * 8; if ((ret = init_get_bits8(&s->gb_extra_bits, gb.buffer, size)) < 0) return ret; s->crc_extra_bits = get_bits_long(&s->gb_extra_bits, 32); @@ -979,70 +1447,115 @@ bytestream2_skip(&gb, 1); } - if (!got_terms) { - av_log(avctx, AV_LOG_ERROR, "No block with decorrelation terms\n"); - return AVERROR_INVALIDDATA; - } - if (!got_weights) { - av_log(avctx, AV_LOG_ERROR, "No block with decorrelation weights\n"); - return AVERROR_INVALIDDATA; - } - if (!got_samples) { - av_log(avctx, AV_LOG_ERROR, "No block with decorrelation samples\n"); - return AVERROR_INVALIDDATA; - } - if (!got_entropy) { - av_log(avctx, AV_LOG_ERROR, "No block with entropy info\n"); - return AVERROR_INVALIDDATA; - } - if (s->hybrid && !got_hybrid) { - av_log(avctx, AV_LOG_ERROR, "Hybrid config not found\n"); - return AVERROR_INVALIDDATA; + if (got_pcm) { + if (!got_terms) { + av_log(avctx, AV_LOG_ERROR, "No block with decorrelation terms\n"); + return AVERROR_INVALIDDATA; + } + if (!got_weights) { + av_log(avctx, AV_LOG_ERROR, "No block with decorrelation weights\n"); + return AVERROR_INVALIDDATA; + } + if (!got_samples) { + av_log(avctx, AV_LOG_ERROR, "No block with decorrelation samples\n"); + return AVERROR_INVALIDDATA; + } + if (!got_entropy) { + av_log(avctx, AV_LOG_ERROR, "No block with entropy info\n"); + return AVERROR_INVALIDDATA; + } + if (s->hybrid && !got_hybrid) { + av_log(avctx, AV_LOG_ERROR, "Hybrid config not found\n"); + return AVERROR_INVALIDDATA; + } + if (!got_float && sample_fmt == AV_SAMPLE_FMT_FLTP) { + av_log(avctx, AV_LOG_ERROR, "Float information not found\n"); + return AVERROR_INVALIDDATA; + } + if (s->got_extra_bits && sample_fmt != AV_SAMPLE_FMT_FLTP) { + const int size = get_bits_left(&s->gb_extra_bits); + const int wanted = s->samples * s->extra_bits << s->stereo_in; + if (size < wanted) { + av_log(avctx, AV_LOG_ERROR, "Too small EXTRABITS\n"); + s->got_extra_bits = 0; + } + } } - if (!got_bs) { + + if (!got_pcm && !got_dsd) { av_log(avctx, AV_LOG_ERROR, "Packed samples not found\n"); return AVERROR_INVALIDDATA; } - if (!got_float && avctx->sample_fmt == AV_SAMPLE_FMT_FLTP) { - av_log(avctx, AV_LOG_ERROR, "Float information not found\n"); - return AVERROR_INVALIDDATA; - } - if (s->got_extra_bits && avctx->sample_fmt != AV_SAMPLE_FMT_FLTP) { - const int size = get_bits_left(&s->gb_extra_bits); - const int wanted = s->samples * s->extra_bits << s->stereo_in; - if (size < wanted) { - av_log(avctx, AV_LOG_ERROR, "Too small EXTRABITS\n"); - s->got_extra_bits = 0; - } + + if ((got_pcm && wc->modulation != MODULATION_PCM) || + (got_dsd && wc->modulation != MODULATION_DSD)) { + av_log(avctx, AV_LOG_ERROR, "Invalid PCM/DSD mix encountered\n"); + return AVERROR_INVALIDDATA; } if (!wc->ch_offset) { + int new_channels = avctx->channels; + uint64_t new_chmask = avctx->channel_layout; + int new_samplerate; int sr = (s->frame_flags >> 23) & 0xf; if (sr == 0xf) { if (!sample_rate) { av_log(avctx, AV_LOG_ERROR, "Custom sample rate missing.\n"); return AVERROR_INVALIDDATA; } - avctx->sample_rate = sample_rate; + new_samplerate = sample_rate; } else - avctx->sample_rate = wv_rates[sr]; + new_samplerate = wv_rates[sr]; + + if (new_samplerate * (uint64_t)rate_x > INT_MAX) + return AVERROR_INVALIDDATA; + new_samplerate *= rate_x; if (multiblock) { if (chan) - avctx->channels = chan; + new_channels = chan; if (chmask) - avctx->channel_layout = chmask; + new_chmask = chmask; } else { - avctx->channels = s->stereo ? 2 : 1; - avctx->channel_layout = s->stereo ? AV_CH_LAYOUT_STEREO : - AV_CH_LAYOUT_MONO; + new_channels = s->stereo ? 2 : 1; + new_chmask = s->stereo ? AV_CH_LAYOUT_STEREO : + AV_CH_LAYOUT_MONO; + } + + if (new_chmask && + av_get_channel_layout_nb_channels(new_chmask) != new_channels) { + av_log(avctx, AV_LOG_ERROR, "Channel mask does not match the channel count\n"); + return AVERROR_INVALIDDATA; } + /* clear DSD state if stream properties change */ + if (new_channels != wc->dsd_channels || + new_chmask != avctx->channel_layout || + new_samplerate != avctx->sample_rate || + !!got_dsd != !!wc->dsdctx) { + ret = wv_dsd_reset(wc, got_dsd ? new_channels : 0); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error reinitializing the DSD context\n"); + return ret; + } + ff_thread_release_buffer(avctx, &wc->curr_frame); + } + avctx->channels = new_channels; + avctx->channel_layout = new_chmask; + avctx->sample_rate = new_samplerate; + avctx->sample_fmt = sample_fmt; + avctx->bits_per_raw_sample = orig_bpp; + + ff_thread_release_buffer(avctx, &wc->prev_frame); + FFSWAP(ThreadFrame, wc->curr_frame, wc->prev_frame); + /* get output buffer */ - frame->nb_samples = s->samples + 1; - if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) + wc->curr_frame.f->nb_samples = s->samples; + if ((ret = ff_thread_get_buffer(avctx, &wc->curr_frame, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; - frame->nb_samples = s->samples; + + wc->frame = wc->curr_frame.f; + ff_thread_finish_setup(avctx); } if (wc->ch_offset + s->stereo >= avctx->channels) { @@ -1050,18 +1563,38 @@ return ((avctx->err_recognition & AV_EF_EXPLODE) || !wc->ch_offset) ? AVERROR_INVALIDDATA : 0; } - samples_l = frame->extended_data[wc->ch_offset]; + samples_l = wc->frame->extended_data[wc->ch_offset]; if (s->stereo) - samples_r = frame->extended_data[wc->ch_offset + 1]; + samples_r = wc->frame->extended_data[wc->ch_offset + 1]; wc->ch_offset += 1 + s->stereo; if (s->stereo_in) { - ret = wv_unpack_stereo(s, &s->gb, samples_l, samples_r, avctx->sample_fmt); + if (got_dsd) { + if (dsd_mode == 3) { + ret = wv_unpack_dsd_high(s, samples_l, samples_r); + } else if (dsd_mode == 1) { + ret = wv_unpack_dsd_fast(s, samples_l, samples_r); + } else { + ret = wv_unpack_dsd_copy(s, samples_l, samples_r); + } + } else { + ret = wv_unpack_stereo(s, &s->gb, samples_l, samples_r, avctx->sample_fmt); + } if (ret < 0) return ret; } else { - ret = wv_unpack_mono(s, &s->gb, samples_l, avctx->sample_fmt); + if (got_dsd) { + if (dsd_mode == 3) { + ret = wv_unpack_dsd_high(s, samples_l, NULL); + } else if (dsd_mode == 1) { + ret = wv_unpack_dsd_fast(s, samples_l, NULL); + } else { + ret = wv_unpack_dsd_copy(s, samples_l, NULL); + } + } else { + ret = wv_unpack_mono(s, &s->gb, samples_l, avctx->sample_fmt); + } if (ret < 0) return ret; @@ -1075,10 +1608,20 @@ static void wavpack_decode_flush(AVCodecContext *avctx) { WavpackContext *s = avctx->priv_data; - int i; - for (i = 0; i < s->fdec_num; i++) - wv_reset_saved_context(s->fdec[i]); + wv_dsd_reset(s, 0); +} + +static int dsd_channel(AVCodecContext *avctx, void *frmptr, int jobnr, int threadnr) +{ + WavpackContext *s = avctx->priv_data; + AVFrame *frame = frmptr; + + ff_dsd2pcm_translate (&s->dsdctx [jobnr], s->samples, 0, + (uint8_t *)frame->extended_data[jobnr], 4, + (float *)frame->extended_data[jobnr], 1); + + return 0; } static int wavpack_decode_frame(AVCodecContext *avctx, void *data, @@ -1087,12 +1630,12 @@ WavpackContext *s = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame *frame = data; int frame_size, ret, frame_flags; if (avpkt->size <= WV_HEADER_SIZE) return AVERROR_INVALIDDATA; + s->frame = NULL; s->block = 0; s->ch_offset = 0; @@ -1105,18 +1648,9 @@ return AVERROR_INVALIDDATA; } - if (frame_flags & 0x80) { - avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; - } else if ((frame_flags & 0x03) <= 1) { - avctx->sample_fmt = AV_SAMPLE_FMT_S16P; - } else { - avctx->sample_fmt = AV_SAMPLE_FMT_S32P; - avctx->bits_per_raw_sample = ((frame_flags & 0x03) + 1) << 3; - } + s->modulation = (frame_flags & WV_DSD_DATA) ? MODULATION_DSD : MODULATION_PCM; - while (buf_size > 0) { - if (buf_size <= WV_HEADER_SIZE) - break; + while (buf_size > WV_HEADER_SIZE) { frame_size = AV_RL32(buf + 4) - 12; buf += 20; buf_size -= 20; @@ -1124,14 +1658,11 @@ av_log(avctx, AV_LOG_ERROR, "Block %d has invalid size (size %d vs. %d bytes left)\n", s->block, frame_size, buf_size); - wavpack_decode_flush(avctx); - return AVERROR_INVALIDDATA; - } - if ((ret = wavpack_decode_block(avctx, s->block, - frame, buf, frame_size)) < 0) { - wavpack_decode_flush(avctx); - return ret; + ret = AVERROR_INVALIDDATA; + goto error; } + if ((ret = wavpack_decode_block(avctx, s->block, buf, frame_size)) < 0) + goto error; s->block++; buf += frame_size; buf_size -= frame_size; @@ -1139,12 +1670,33 @@ if (s->ch_offset != avctx->channels) { av_log(avctx, AV_LOG_ERROR, "Not enough channels coded in a packet.\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto error; } + ff_thread_await_progress(&s->prev_frame, INT_MAX, 0); + ff_thread_release_buffer(avctx, &s->prev_frame); + + if (s->modulation == MODULATION_DSD) + avctx->execute2(avctx, dsd_channel, s->frame, NULL, avctx->channels); + + ff_thread_report_progress(&s->curr_frame, INT_MAX, 0); + + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; + *got_frame_ptr = 1; return avpkt->size; + +error: + if (s->frame) { + ff_thread_await_progress(&s->prev_frame, INT_MAX, 0); + ff_thread_release_buffer(avctx, &s->prev_frame); + ff_thread_report_progress(&s->curr_frame, INT_MAX, 0); + } + + return ret; } AVCodec ff_wavpack_decoder = { @@ -1157,6 +1709,9 @@ .close = wavpack_decode_end, .decode = wavpack_decode_frame, .flush = wavpack_decode_flush, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(init_thread_copy), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | + FF_CODEC_CAP_ALLOCATE_PROGRESS, }; diff -Nru ffmpeg-4.2.2/libavcodec/wavpackdata.c ffmpeg-4.4/libavcodec/wavpackdata.c --- ffmpeg-4.2.2/libavcodec/wavpackdata.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wavpackdata.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * WavPack decoder/encoder common data + * Copyright (c) 2006,2011 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 "wavpack.h" + +const uint8_t ff_wp_exp2_table[256] = { + 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0b, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x16, + 0x17, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1f, 0x20, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x24, 0x25, 0x26, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3d, + 0x3e, 0x3f, 0x40, 0x41, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b, + 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, + 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, + 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, + 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, + 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc8, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf, 0xd0, 0xd2, 0xd3, 0xd4, + 0xd6, 0xd7, 0xd8, 0xd9, 0xdb, 0xdc, 0xdd, 0xde, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe8, 0xe9, + 0xea, 0xec, 0xed, 0xee, 0xf0, 0xf1, 0xf2, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xff +}; + +const uint8_t ff_wp_log2_table[256] = { + 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15, + 0x16, 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, + 0x2c, 0x2d, 0x2e, 0x2f, 0x31, 0x32, 0x33, 0x34, 0x36, 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, + 0x3f, 0x41, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x4f, 0x50, 0x51, + 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, + 0x64, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, + 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, + 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, + 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb2, + 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc0, + 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xce, + 0xcf, 0xd0, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xd9, 0xda, 0xdb, + 0xdc, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe4, 0xe5, 0xe6, 0xe7, 0xe7, + 0xe8, 0xe9, 0xea, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xee, 0xef, 0xf0, 0xf1, 0xf1, 0xf2, 0xf3, 0xf4, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf7, 0xf8, 0xf9, 0xf9, 0xfa, 0xfb, 0xfc, 0xfc, 0xfd, 0xfe, 0xff, 0xff +}; diff -Nru ffmpeg-4.2.2/libavcodec/wavpackenc.c ffmpeg-4.4/libavcodec/wavpackenc.c --- ffmpeg-4.2.2/libavcodec/wavpackenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wavpackenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -529,9 +529,9 @@ static int restore_weight(int8_t weight) { - int result; + int result = 8 * weight; - if ((result = (int) weight << 3) > 0) + if (result > 0) result += (result + 64) >> 7; return result; @@ -644,9 +644,9 @@ uint32_t dbits = count_bits(v); if ((v += v >> 9) < (1 << 8)) { - *result += (dbits << 8) + wp_log2_table[(v << (9 - dbits)) & 0xff]; + *result += (dbits << 8) + ff_wp_log2_table[(v << (9 - dbits)) & 0xff]; } else { - *result += dbits = (dbits << 8) + wp_log2_table[(v >> (dbits - 9)) & 0xff]; + *result += dbits = (dbits << 8) + ff_wp_log2_table[(v >> (dbits - 9)) & 0xff]; if (limit && dbits >= limit) return 1; @@ -2557,7 +2557,7 @@ ret = wv_mono(s, samples_l, !s->num_terms, 1); } else { for (i = 0; i < nb_samples; i++) - crc += (crc << 3) + (samples_l[i] << 1) + samples_l[i] + samples_r[i]; + crc += (crc << 3) + ((uint32_t)samples_l[i] << 1) + samples_l[i] + samples_r[i]; if (s->num_passes) ret = wv_stereo(s, samples_l, samples_r, !s->num_terms, 1); diff -Nru ffmpeg-4.2.2/libavcodec/wavpack.h ffmpeg-4.4/libavcodec/wavpack.h --- ffmpeg-4.2.2/libavcodec/wavpack.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wavpack.h 2021-04-08 21:28:39.000000000 +0000 @@ -35,6 +35,7 @@ #define WV_FLOAT_DATA 0x00000080 #define WV_INT32_DATA 0x00000100 #define WV_FALSE_STEREO 0x40000000 +#define WV_DSD_DATA 0x80000000 #define WV_HYBRID_MODE 0x00000008 #define WV_HYBRID_SHAPE 0x00000008 @@ -77,6 +78,7 @@ WP_ID_CORR, WP_ID_EXTRABITS, WP_ID_CHANINFO, + WP_ID_DSD_DATA, WP_ID_SAMPLE_RATE = 0x27, }; @@ -122,43 +124,8 @@ }; // exponent table copied from WavPack source -static const uint8_t wp_exp2_table[256] = { - 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0b, - 0x0b, 0x0c, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x16, - 0x17, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1f, 0x20, 0x20, 0x21, 0x22, 0x23, - 0x24, 0x24, 0x25, 0x26, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3d, - 0x3e, 0x3f, 0x40, 0x41, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b, - 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, - 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, - 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, - 0x9c, 0x9d, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, - 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, - 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc8, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf, 0xd0, 0xd2, 0xd3, 0xd4, - 0xd6, 0xd7, 0xd8, 0xd9, 0xdb, 0xdc, 0xdd, 0xde, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe8, 0xe9, - 0xea, 0xec, 0xed, 0xee, 0xf0, 0xf1, 0xf2, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xff -}; - -static const uint8_t wp_log2_table [] = { - 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15, - 0x16, 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, - 0x2c, 0x2d, 0x2e, 0x2f, 0x31, 0x32, 0x33, 0x34, 0x36, 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, - 0x3f, 0x41, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x4f, 0x50, 0x51, - 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, - 0x64, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, - 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, - 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, - 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, - 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb2, - 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc0, - 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xce, - 0xcf, 0xd0, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xd9, 0xda, 0xdb, - 0xdc, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe4, 0xe5, 0xe6, 0xe7, 0xe7, - 0xe8, 0xe9, 0xea, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xee, 0xef, 0xf0, 0xf1, 0xf1, 0xf2, 0xf3, 0xf4, - 0xf4, 0xf5, 0xf6, 0xf7, 0xf7, 0xf8, 0xf9, 0xf9, 0xfa, 0xfb, 0xfc, 0xfc, 0xfd, 0xfe, 0xff, 0xff -}; +extern const uint8_t ff_wp_exp2_table[256]; +extern const uint8_t ff_wp_log2_table[256]; static av_always_inline int wp_exp2(int16_t val) { @@ -169,7 +136,7 @@ neg = 1; } - res = wp_exp2_table[val & 0xFF] | 0x100; + res = ff_wp_exp2_table[val & 0xFF] | 0x100; val >>= 8; if (val > 31U) return INT_MIN; @@ -188,9 +155,9 @@ val += val >> 9; bits = av_log2(val) + 1; if (bits < 9) - return (bits << 8) + wp_log2_table[(val << (9 - bits)) & 0xFF]; + return (bits << 8) + ff_wp_log2_table[(val << (9 - bits)) & 0xFF]; else - return (bits << 8) + wp_log2_table[(val >> (bits - 9)) & 0xFF]; + return (bits << 8) + ff_wp_log2_table[(val >> (bits - 9)) & 0xFF]; } #endif /* AVCODEC_WAVPACK_H */ diff -Nru ffmpeg-4.2.2/libavcodec/wcmv.c ffmpeg-4.4/libavcodec/wcmv.c --- ffmpeg-4.2.2/libavcodec/wcmv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wcmv.c 2020-07-11 10:39:30.000000000 +0000 @@ -45,7 +45,7 @@ { WCMVContext *s = avctx->priv_data; AVFrame *frame = data; - int skip, blocks, zret, ret, intra = 0, bpp = s->bpp; + int skip, blocks, zret, ret, intra = 0, flags = 0, bpp = s->bpp; GetByteContext gb; uint8_t *dst; @@ -58,9 +58,9 @@ bytestream2_init(&gb, avpkt->data, avpkt->size); blocks = bytestream2_get_le16(&gb); if (!blocks) - return avpkt->size; + flags |= FF_REGET_BUFFER_FLAG_READONLY; - if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + if ((ret = ff_reget_buffer(avctx, s->prev_frame, flags)) < 0) return ret; if (blocks > 5) { @@ -157,13 +157,9 @@ if (bytestream2_get_bytes_left(&gb) < 8LL * blocks) return AVERROR_INVALIDDATA; - if (s->prev_frame->data[0]) { - ret = av_frame_copy(frame, s->prev_frame); - if (ret < 0) - return ret; - } else { - ptrdiff_t linesize[4] = { frame->linesize[0], 0, 0, 0 }; - av_image_fill_black(frame->data, linesize, avctx->pix_fmt, 0, + if (!avctx->frame_number) { + ptrdiff_t linesize[4] = { s->prev_frame->linesize[0], 0, 0, 0 }; + av_image_fill_black(s->prev_frame->data, linesize, avctx->pix_fmt, 0, avctx->width, avctx->height); } @@ -184,7 +180,7 @@ if (w > avctx->width || h > avctx->height) return AVERROR_INVALIDDATA; - dst = frame->data[0] + (avctx->height - y - 1) * frame->linesize[0] + x * bpp; + dst = s->prev_frame->data[0] + (avctx->height - y - 1) * s->prev_frame->linesize[0] + x * bpp; for (int i = 0; i < h; i++) { s->zstream.next_out = dst; s->zstream.avail_out = w * bpp; @@ -196,15 +192,14 @@ return AVERROR_INVALIDDATA; } - dst -= frame->linesize[0]; + dst -= s->prev_frame->linesize[0]; } } - frame->key_frame = intra; - frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + s->prev_frame->key_frame = intra; + s->prev_frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; - av_frame_unref(s->prev_frame); - if ((ret = av_frame_ref(s->prev_frame, frame)) < 0) + if ((ret = av_frame_ref(frame, s->prev_frame)) < 0) return ret; *got_frame = 1; diff -Nru ffmpeg-4.2.2/libavcodec/webp.c ffmpeg-4.4/libavcodec/webp.c --- ffmpeg-4.2.2/libavcodec/webp.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/webp.c 2021-04-08 21:28:39.000000000 +0000 @@ -189,6 +189,7 @@ VP8Context v; /* VP8 Context used for lossy decoding */ GetBitContext gb; /* bitstream reader for main image chunk */ AVFrame *alpha_frame; /* AVFrame for alpha data decompressed from VP8L */ + AVPacket *pkt; /* AVPacket to be passed to the underlying VP8 decoder */ AVCodecContext *avctx; /* parent AVCodecContext */ int initialized; /* set once the VP8 context is initialized */ int has_alpha; /* has a separate alpha chunk */ @@ -232,44 +233,6 @@ memset(img, 0, sizeof(*img)); } - -/* Differs from get_vlc2() in the following ways: - * - codes are bit-reversed - * - assumes 8-bit table to make reversal simpler - * - assumes max depth of 2 since the max code length for WebP is 15 - */ -static av_always_inline int webp_get_vlc(GetBitContext *gb, VLC_TYPE (*table)[2]) -{ - int n, nb_bits; - unsigned int index; - int code; - - OPEN_READER(re, gb); - UPDATE_CACHE(re, gb); - - index = SHOW_UBITS(re, gb, 8); - index = ff_reverse[index]; - code = table[index][0]; - n = table[index][1]; - - if (n < 0) { - LAST_SKIP_BITS(re, gb, 8); - UPDATE_CACHE(re, gb); - - nb_bits = -n; - - index = SHOW_UBITS(re, gb, nb_bits); - index = (ff_reverse[index] >> (8 - nb_bits)) + code; - code = table[index][0]; - n = table[index][1]; - } - SKIP_BITS(re, gb, n); - - CLOSE_READER(re, gb); - - return code; -} - static int huff_reader_get_symbol(HuffReader *r, GetBitContext *gb) { if (r->simple) { @@ -278,10 +241,10 @@ else return r->simple_symbols[get_bits1(gb)]; } else - return webp_get_vlc(gb, r->vlc.table); + return get_vlc2(gb, r->vlc.table, 8, 2); } -static int huff_reader_build_canonical(HuffReader *r, int *code_lengths, +static int huff_reader_build_canonical(HuffReader *r, const uint8_t *code_lengths, int alphabet_size) { int len = 0, sym, code = 0, ret; @@ -332,7 +295,7 @@ ret = init_vlc(&r->vlc, 8, alphabet_size, code_lengths, sizeof(*code_lengths), sizeof(*code_lengths), - codes, sizeof(*codes), sizeof(*codes), 0); + codes, sizeof(*codes), sizeof(*codes), INIT_VLC_OUTPUT_LE); if (ret < 0) { av_free(codes); return ret; @@ -362,13 +325,12 @@ int alphabet_size) { HuffReader code_len_hc = { { 0 }, 0, 0, { 0 } }; - int *code_lengths = NULL; - int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 }; + uint8_t *code_lengths; + uint8_t code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 }; int i, symbol, max_symbol, prev_code_len, ret; int num_codes = 4 + get_bits(&s->gb, 4); - if (num_codes > NUM_CODE_LENGTH_CODES) - return AVERROR_INVALIDDATA; + av_assert1(num_codes <= NUM_CODE_LENGTH_CODES); for (i = 0; i < num_codes; i++) code_length_code_lengths[code_length_code_order[i]] = get_bits(&s->gb, 3); @@ -376,9 +338,9 @@ ret = huff_reader_build_canonical(&code_len_hc, code_length_code_lengths, NUM_CODE_LENGTH_CODES); if (ret < 0) - goto finish; + return ret; - code_lengths = av_mallocz_array(alphabet_size, sizeof(*code_lengths)); + code_lengths = av_mallocz(alphabet_size); if (!code_lengths) { ret = AVERROR(ENOMEM); goto finish; @@ -1329,7 +1291,6 @@ unsigned int data_size) { WebPContext *s = avctx->priv_data; - AVPacket pkt; int ret; if (!s->initialized) { @@ -1345,11 +1306,11 @@ return AVERROR_PATCHWELCOME; } - av_init_packet(&pkt); - pkt.data = data_start; - pkt.size = data_size; + av_packet_unref(s->pkt); + s->pkt->data = data_start; + s->pkt->size = data_size; - ret = ff_vp8_decode_frame(avctx, p, got_frame, &pkt); + ret = ff_vp8_decode_frame(avctx, p, got_frame, s->pkt); if (ret < 0) return ret; @@ -1412,8 +1373,11 @@ return AVERROR_INVALIDDATA; chunk_size += chunk_size & 1; - if (bytestream2_get_bytes_left(&gb) < chunk_size) - return AVERROR_INVALIDDATA; + if (bytestream2_get_bytes_left(&gb) < chunk_size) { + /* we seem to be running out of data, but it could also be that the + bitstream has trailing junk leading to bogus chunk_size. */ + break; + } switch (chunk_type) { case MKTAG('V', 'P', '8', ' '): @@ -1563,10 +1527,23 @@ return avpkt->size; } +static av_cold int webp_decode_init(AVCodecContext *avctx) +{ + WebPContext *s = avctx->priv_data; + + s->pkt = av_packet_alloc(); + if (!s->pkt) + return AVERROR(ENOMEM); + + return 0; +} + static av_cold int webp_decode_close(AVCodecContext *avctx) { WebPContext *s = avctx->priv_data; + av_packet_free(&s->pkt); + if (s->initialized) return ff_vp8_decode_free(avctx); @@ -1579,6 +1556,7 @@ .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WEBP, .priv_data_size = sizeof(WebPContext), + .init = webp_decode_init, .decode = webp_decode_frame, .close = webp_decode_close, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, diff -Nru ffmpeg-4.2.2/libavcodec/webp_parser.c ffmpeg-4.4/libavcodec/webp_parser.c --- ffmpeg-4.2.2/libavcodec/webp_parser.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/webp_parser.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * WebP parser + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * WebP parser + */ + +#include "libavutil/bswap.h" +#include "libavutil/common.h" + +#include "parser.h" + +typedef struct WebPParseContext { + ParseContext pc; + uint32_t fsize; + uint32_t remaining_size; +} WebPParseContext; + +static int webp_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + WebPParseContext *ctx = s->priv_data; + uint64_t state = ctx->pc.state64; + int next = END_NOT_FOUND; + int i = 0; + + *poutbuf = NULL; + *poutbuf_size = 0; + +restart: + if (ctx->pc.frame_start_found <= 8) { + for (; i < buf_size; i++) { + state = (state << 8) | buf[i]; + if (ctx->pc.frame_start_found == 0) { + if ((state >> 32) == MKBETAG('R', 'I', 'F', 'F')) { + ctx->fsize = av_bswap32(state); + if (ctx->fsize > 15 && ctx->fsize <= UINT32_MAX - 10) { + ctx->pc.frame_start_found = 1; + ctx->fsize += 8; + } + } + } else if (ctx->pc.frame_start_found == 8) { + if ((state >> 32) != MKBETAG('W', 'E', 'B', 'P')) { + ctx->pc.frame_start_found = 0; + continue; + } + ctx->pc.frame_start_found++; + ctx->remaining_size = ctx->fsize + i - 15; + if (ctx->pc.index + i > 15) { + next = i - 15; + state = 0; + break; + } else { + ctx->pc.state64 = 0; + goto restart; + } + } else if (ctx->pc.frame_start_found) + ctx->pc.frame_start_found++; + } + ctx->pc.state64 = state; + } else { + if (ctx->remaining_size) { + i = FFMIN(ctx->remaining_size, buf_size); + ctx->remaining_size -= i; + if (ctx->remaining_size) + goto flush; + + ctx->pc.frame_start_found = 0; + goto restart; + } + } + +flush: + if (ff_combine_frame(&ctx->pc, next, &buf, &buf_size) < 0) + return buf_size; + + if (next != END_NOT_FOUND && next < 0) + ctx->pc.frame_start_found = FFMAX(ctx->pc.frame_start_found - i - 1, 0); + else + ctx->pc.frame_start_found = 0; + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_webp_parser = { + .codec_ids = { AV_CODEC_ID_WEBP }, + .priv_data_size = sizeof(WebPParseContext), + .parser_parse = webp_parse, + .parser_close = ff_parse_close, +}; diff -Nru ffmpeg-4.2.2/libavcodec/webvttenc.c ffmpeg-4.4/libavcodec/webvttenc.c --- ffmpeg-4.2.2/libavcodec/webvttenc.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/webvttenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -168,7 +168,7 @@ if (sub->rects[i]->type != SUBTITLE_ASS) { av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n"); - return AVERROR(ENOSYS); + return AVERROR(EINVAL); } #if FF_API_ASS_TIMING @@ -200,7 +200,7 @@ if (s->buffer.len > bufsize) { av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); - return -1; + return AVERROR_BUFFER_TOO_SMALL; } memcpy(buf, s->buffer.str, s->buffer.len); diff -Nru ffmpeg-4.2.2/libavcodec/wma.c ffmpeg-4.4/libavcodec/wma.c --- ffmpeg-4.2.2/libavcodec/wma.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wma.c 2021-04-08 21:28:39.000000000 +0000 @@ -39,19 +39,17 @@ const uint8_t *table_bits = vlc_table->huffbits; const uint32_t *table_codes = vlc_table->huffcodes; const uint16_t *levels_table = vlc_table->levels; - uint16_t *run_table, *level_table, *int_table; + uint16_t *run_table, *int_table; float *flevel_table; int i, l, j, k, level; init_vlc(vlc, VLCBITS, n, table_bits, 1, 1, table_codes, 4, 4, 0); run_table = av_malloc_array(n, sizeof(uint16_t)); - level_table = av_malloc_array(n, sizeof(uint16_t)); flevel_table = av_malloc_array(n, sizeof(*flevel_table)); int_table = av_malloc_array(n, sizeof(uint16_t)); - if (!run_table || !level_table || !flevel_table || !int_table) { + if (!run_table || !flevel_table || !int_table) { av_freep(&run_table); - av_freep(&level_table); av_freep(&flevel_table); av_freep(&int_table); return AVERROR(ENOMEM); @@ -64,7 +62,6 @@ l = levels_table[k++]; for (j = 0; j < l; j++) { run_table[i] = j; - level_table[i] = level; flevel_table[i] = level; i++; } @@ -73,7 +70,6 @@ *prun_table = run_table; *plevel_table = flevel_table; *pint_table = int_table; - av_free(level_table); return 0; } diff -Nru ffmpeg-4.2.2/libavcodec/wmadata.h ffmpeg-4.4/libavcodec/wmadata.h --- ffmpeg-4.2.2/libavcodec/wmadata.h 2016-03-29 02:25:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wmadata.h 2021-04-08 21:28:39.000000000 +0000 @@ -51,18 +51,14 @@ { 17, 4, 8, 8, 4, 12, 12, 8, 8, 24, 16, 20, 24, 32, 40, 60, 80, 152, }, }; -const uint16_t ff_wma_hgain_huffcodes[37] = { - 0x00003, 0x002e7, 0x00001, 0x005cd, 0x0005d, 0x005c9, 0x0005e, 0x00003, - 0x00016, 0x0000b, 0x00001, 0x00006, 0x00001, 0x00006, 0x00004, 0x00005, - 0x00004, 0x00007, 0x00003, 0x00007, 0x00004, 0x0000a, 0x0000a, 0x00002, - 0x00003, 0x00000, 0x00005, 0x00002, 0x0005f, 0x00004, 0x00003, 0x00002, - 0x005c8, 0x000b8, 0x005ca, 0x005cb, 0x005cc, -}; - -const uint8_t ff_wma_hgain_huffbits[37] = { - 10, 12, 10, 13, 9, 13, 9, 8, 7, 5, 5, 4, 4, 3, 3, 3, - 4, 3, 4, 4, 5, 5, 6, 8, 7, 10, 8, 10, 9, 8, 9, 9, - 13, 10, 13, 13, 13, +const uint8_t ff_wma_hgain_hufftab[37][2] = { + { 25, 10 }, { 2, 10 }, { 27, 10 }, { 0, 10 }, { 31, 9 }, { 30, 9 }, + { 23, 8 }, { 7, 8 }, { 29, 8 }, { 26, 8 }, { 24, 7 }, { 10, 5 }, + { 12, 4 }, { 20, 5 }, { 22, 6 }, { 8, 7 }, { 33, 10 }, { 32, 13 }, + { 5, 13 }, { 34, 13 }, { 35, 13 }, { 36, 13 }, { 3, 13 }, { 1, 12 }, + { 4, 9 }, { 6, 9 }, { 28, 9 }, { 18, 4 }, { 16, 4 }, { 21, 5 }, + { 9, 5 }, { 11, 4 }, { 19, 4 }, { 14, 3 }, { 15, 3 }, { 13, 3 }, + { 17, 3 }, }; const float ff_wma_lsp_codebook[NB_LSP_COEFS][16] = { diff -Nru ffmpeg-4.2.2/libavcodec/wmadec.c ffmpeg-4.4/libavcodec/wmadec.c --- ffmpeg-4.2.2/libavcodec/wmadec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wmadec.c 2021-04-08 21:28:39.000000000 +0000 @@ -110,9 +110,9 @@ ff_mdct_init(&s->mdct_ctx[i], s->frame_len_bits - i + 1, 1, 1.0 / 32768.0); if (s->use_noise_coding) { - init_vlc(&s->hgain_vlc, HGAINVLCBITS, sizeof(ff_wma_hgain_huffbits), - ff_wma_hgain_huffbits, 1, 1, - ff_wma_hgain_huffcodes, 2, 2, 0); + ff_init_vlc_from_lengths(&s->hgain_vlc, HGAINVLCBITS, FF_ARRAY_ELEMS(ff_wma_hgain_hufftab), + &ff_wma_hgain_hufftab[0][1], 2, + &ff_wma_hgain_hufftab[0][0], 2, 1, -18, 0, avctx); } if (s->use_exp_vlc) @@ -345,10 +345,6 @@ while (q < q_end) { code = get_vlc2(&s->gb, s->exp_vlc.table, EXPVLCBITS, EXPMAX); - if (code < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Exponent vlc invalid\n"); - return -1; - } /* NOTE: this offset is the same as MPEG-4 AAC! */ last_exp += code - 60; if ((unsigned) last_exp + 60 >= FF_ARRAY_ELEMS(pow_tab)) { @@ -549,7 +545,7 @@ } for (ch = 0; ch < s->avctx->channels; ch++) { if (s->channel_coded[ch]) { - int i, n, val, code; + int i, n, val; n = s->exponent_high_sizes[bsize]; val = (int) 0x80000000; @@ -558,14 +554,8 @@ if (val == (int) 0x80000000) { val = get_bits(&s->gb, 7) - 19; } else { - code = get_vlc2(&s->gb, s->hgain_vlc.table, + val += get_vlc2(&s->gb, s->hgain_vlc.table, HGAINVLCBITS, HGAINMAX); - if (code < 0) { - av_log(s->avctx, AV_LOG_ERROR, - "hgain vlc invalid\n"); - return -1; - } - val += code - 18; } s->high_band_values[ch][i] = val; } @@ -895,11 +885,11 @@ q = s->last_superframe + s->last_superframe_len; len = bit_offset; while (len > 7) { - *q++ = (get_bits) (&s->gb, 8); + *q++ = get_bits(&s->gb, 8); len -= 8; } if (len > 0) - *q++ = (get_bits) (&s->gb, len) << (8 - len); + *q++ = get_bits(&s->gb, len) << (8 - len); memset(q, 0, AV_INPUT_BUFFER_PADDING_SIZE); /* XXX: bit_offset bits into last frame */ diff -Nru ffmpeg-4.2.2/libavcodec/wmaenc.c ffmpeg-4.4/libavcodec/wmaenc.c --- ffmpeg-4.2.2/libavcodec/wmaenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wmaenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -343,7 +343,7 @@ s->coef_vlcs[tindex]->huffcodes[1]); } if (s->version == 1 && s->avctx->channels >= 2) - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); } return 0; } @@ -358,7 +358,7 @@ else if (encode_block(s, src_coefs, total_gain) < 0) return INT_MAX; - avpriv_align_put_bits(&s->pb); + align_put_bits(&s->pb); return put_bits_count(&s->pb) / 8 - s->avctx->block_align; } diff -Nru ffmpeg-4.2.2/libavcodec/wma.h ffmpeg-4.4/libavcodec/wma.h --- ffmpeg-4.2.2/libavcodec/wma.h 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wma.h 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ #define AVCODEC_WMA_H #include "libavutil/float_dsp.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "fft.h" @@ -139,8 +140,7 @@ #endif /* TRACE */ } WMACodecContext; -extern const uint16_t ff_wma_hgain_huffcodes[37]; -extern const uint8_t ff_wma_hgain_huffbits[37]; +extern const uint8_t ff_wma_hgain_hufftab[37][2]; extern const float ff_wma_lsp_codebook[NB_LSP_COEFS][16]; extern const uint32_t ff_aac_scalefactor_code[121]; extern const uint8_t ff_aac_scalefactor_bits[121]; diff -Nru ffmpeg-4.2.2/libavcodec/wmalosslessdec.c ffmpeg-4.4/libavcodec/wmalosslessdec.c --- ffmpeg-4.2.2/libavcodec/wmalosslessdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wmalosslessdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,7 @@ #include "libavutil/attributes.h" #include "libavutil/avassert.h" +#include "libavutil/mem_internal.h" #include "avcodec.h" #include "internal.h" @@ -164,7 +165,7 @@ int transient_pos[WMALL_MAX_CHANNELS]; int seekable_tile; - int ave_sum[WMALL_MAX_CHANNELS]; + unsigned ave_sum[WMALL_MAX_CHANNELS]; int channel_residues[WMALL_MAX_CHANNELS][WMALL_BLOCK_MAX_SIZE]; @@ -184,11 +185,18 @@ unsigned int channel_mask; int i, log2_max_num_subframes; - if (avctx->block_align <= 0) { + if (avctx->block_align <= 0 || avctx->block_align > (1<<21)) { av_log(avctx, AV_LOG_ERROR, "block_align is not set or invalid\n"); return AVERROR(EINVAL); } + av_assert0(avctx->channels >= 0); + if (avctx->channels > WMALL_MAX_CHANNELS) { + avpriv_request_sample(avctx, + "More than " AV_STRINGIFY(WMALL_MAX_CHANNELS) " channels"); + return AVERROR_PATCHWELCOME; + } + s->max_frame_size = MAX_FRAMESIZE * avctx->channels; s->frame_data = av_mallocz(s->max_frame_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!s->frame_data) @@ -267,16 +275,6 @@ ++s->lfe_channel; } - if (s->num_channels < 0) { - av_log(avctx, AV_LOG_ERROR, "invalid number of channels %"PRId8"\n", - s->num_channels); - return AVERROR_INVALIDDATA; - } else if (s->num_channels > WMALL_MAX_CHANNELS) { - avpriv_request_sample(avctx, - "More than %d channels", WMALL_MAX_CHANNELS); - return AVERROR_PATCHWELCOME; - } - s->frame = av_frame_alloc(); if (!s->frame) return AVERROR(ENOMEM); @@ -535,7 +533,8 @@ i++; } for (; i < tile_size; i++) { - int quo = 0, rem, rem_bits, residue; + int rem, rem_bits; + unsigned quo = 0, residue; while(get_bits1(&s->gb)) { quo++; if (get_bits_left(&s->gb) <= 0) @@ -678,7 +677,7 @@ for (i = 0; i < ich; i++) pred[ich] += (uint32_t)s->channel_residues[i][icoef] * s->mclms_coeffs_cur[i + num_channels * ich]; - pred[ich] += (1 << s->mclms_scaling) >> 1; + pred[ich] += (1U << s->mclms_scaling) >> 1; pred[ich] >>= s->mclms_scaling; s->channel_residues[ich][icoef] += (unsigned)pred[ich]; } @@ -760,7 +759,8 @@ static void revert_cdlms ## bits (WmallDecodeCtx *s, int ch, \ int coef_begin, int coef_end) \ { \ - int icoef, pred, ilms, num_lms, residue, input; \ + int icoef, ilms, num_lms, residue, input; \ + unsigned pred;\ \ num_lms = s->cdlms_ttl[ch]; \ for (ilms = num_lms - 1; ilms >= 0; ilms--) { \ @@ -774,7 +774,7 @@ s->cdlms[ch][ilms].recent, \ FFALIGN(s->cdlms[ch][ilms].order, ROUND), \ WMASIGN(residue)); \ - input = residue + (pred >> s->cdlms[ch][ilms].scaling); \ + input = residue + (unsigned)((int)pred >> s->cdlms[ch][ilms].scaling); \ lms_update ## bits(s, ch, ilms, input); \ s->channel_residues[ch][icoef] = input; \ } \ @@ -792,8 +792,8 @@ else if (s->is_channel_coded[0] || s->is_channel_coded[1]) { int icoef; for (icoef = 0; icoef < tile_size; icoef++) { - s->channel_residues[0][icoef] -= s->channel_residues[1][icoef] >> 1; - s->channel_residues[1][icoef] += s->channel_residues[0][icoef]; + s->channel_residues[0][icoef] -= (unsigned)(s->channel_residues[1][icoef] >> 1); + s->channel_residues[1][icoef] += (unsigned) s->channel_residues[0][icoef]; } } } @@ -825,8 +825,11 @@ pred >>= scaling; s->channel_residues[ich][i] += (unsigned)pred; } - for (j = 0; j < order; j++) - prevvalues[j] = s->channel_residues[ich][tile_size - j - 1]; + for (j = order - 1; j >= 0; j--) + if (tile_size <= j) { + prevvalues[j] = prevvalues[j - tile_size]; + }else + prevvalues[j] = s->channel_residues[ich][tile_size - j - 1]; } } @@ -930,6 +933,8 @@ s->do_lpc = 0; } + if (get_bits_left(&s->gb) < 1) + return AVERROR_INVALIDDATA; if (get_bits1(&s->gb)) padding_zeroes = get_bits(&s->gb, 5); @@ -991,7 +996,7 @@ if (s->bits_per_sample == 16) { *s->samples_16[c]++ = (int16_t) s->channel_residues[c][j] * (1 << padding_zeroes); } else { - *s->samples_32[c]++ = s->channel_residues[c][j] * (256 << padding_zeroes); + *s->samples_32[c]++ = s->channel_residues[c][j] * (256U << padding_zeroes); } } } @@ -1156,14 +1161,14 @@ s->num_saved_bits += len; if (!append) { - avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), + ff_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), s->num_saved_bits); } else { int align = 8 - (get_bits_count(gb) & 7); align = FFMIN(align, len); put_bits(&s->pb, align, get_bits(gb, align)); len -= align; - avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len); + ff_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len); } skip_bits_long(gb, len); @@ -1329,6 +1334,7 @@ .decode = decode_packet, .flush = flush, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, diff -Nru ffmpeg-4.2.2/libavcodec/wmaprodec.c ffmpeg-4.4/libavcodec/wmaprodec.c --- ffmpeg-4.2.2/libavcodec/wmaprodec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wmaprodec.c 2021-04-08 21:28:39.000000000 +0000 @@ -92,6 +92,8 @@ #include "libavutil/float_dsp.h" #include "libavutil/intfloat.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "internal.h" #include "get_bits.h" @@ -1579,14 +1581,14 @@ s->num_saved_bits += len; if (!append) { - avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), + ff_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), s->num_saved_bits); } else { int align = 8 - (get_bits_count(gb) & 7); align = FFMIN(align, len); put_bits(&s->pb, align, get_bits(gb, align)); len -= align; - avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len); + ff_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len); } skip_bits_long(gb, len); @@ -1719,6 +1721,12 @@ } } else { int frame_size; + + if (avpkt->size < s->next_packet_start) { + s->packet_loss = 1; + return AVERROR_INVALIDDATA; + } + s->buf_bit_size = (avpkt->size - s->next_packet_start) << 3; init_get_bits(gb, avpkt->data, s->buf_bit_size); skip_bits(gb, s->packet_offset); diff -Nru ffmpeg-4.2.2/libavcodec/wmavoice.c ffmpeg-4.4/libavcodec/wmavoice.c --- ffmpeg-4.2.2/libavcodec/wmavoice.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wmavoice.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,7 +29,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/float_dsp.h" -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavutil/thread.h" #include "avcodec.h" #include "internal.h" @@ -367,7 +367,7 @@ static av_cold int wmavoice_decode_init(AVCodecContext *ctx) { static AVOnce init_static_once = AV_ONCE_INIT; - int n, flags, pitch_range, lsp16_flag; + int n, flags, pitch_range, lsp16_flag, ret; WMAVoiceContext *s = ctx->priv_data; ff_thread_once(&init_static_once, wmavoice_init_static_data); @@ -386,7 +386,7 @@ ctx->extradata_size); return AVERROR_INVALIDDATA; } - if (ctx->block_align <= 0) { + if (ctx->block_align <= 0 || ctx->block_align > (1<<22)) { av_log(ctx, AV_LOG_ERROR, "Invalid block alignment %d.\n", ctx->block_align); return AVERROR_INVALIDDATA; } @@ -395,10 +395,11 @@ s->spillover_bitsize = 3 + av_ceil_log2(ctx->block_align); s->do_apf = flags & 0x1; if (s->do_apf) { - ff_rdft_init(&s->rdft, 7, DFT_R2C); - ff_rdft_init(&s->irdft, 7, IDFT_C2R); - ff_dct_init(&s->dct, 6, DCT_I); - ff_dct_init(&s->dst, 6, DST_I); + if ((ret = ff_rdft_init(&s->rdft, 7, DFT_R2C)) < 0 || + (ret = ff_rdft_init(&s->irdft, 7, IDFT_C2R)) < 0 || + (ret = ff_dct_init (&s->dct, 6, DCT_I)) < 0 || + (ret = ff_dct_init (&s->dst, 6, DST_I)) < 0) + return ret; ff_sine_window_init(s->cos, 256); memcpy(&s->sin[255], s->cos, 256 * sizeof(s->cos[0])); @@ -636,12 +637,14 @@ for (n = 0; n <= 64; n++) { float pwr; - idx = FFMAX(0, lrint((max - lpcs[n]) * irange) - 1); + idx = lrint((max - lpcs[n]) * irange - 1); + idx = FFMAX(0, idx); pwr = wmavoice_denoise_power_table[s->denoise_strength][idx]; lpcs[n] = angle_mul * pwr; /* 70.57 =~ 1/log10(1.0331663) */ - idx = (pwr * gain_mul - 0.0295) * 70.570526123; + idx = av_clipf((pwr * gain_mul - 0.0295) * 70.570526123, 0, INT_MAX / 2); + if (idx > 127) { // fall back if index falls outside table range coeffs[n] = wmavoice_energy_table[127] * powf(1.0331663, idx - 127); @@ -1863,7 +1866,7 @@ * @param size size of the source data, in bytes * @param gb bit I/O context specifying the current position in the source. * data. This function might use this to align the bit position to - * a whole-byte boundary before calling #avpriv_copy_bits() on aligned + * a whole-byte boundary before calling #ff_copy_bits() on aligned * source data * @param nbits the amount of bits to copy from source to target * @@ -1884,7 +1887,7 @@ rmn_bits &= 7; rmn_bytes >>= 3; if ((rmn_bits = FFMIN(rmn_bits, nbits)) > 0) put_bits(pb, rmn_bits, get_bits(gb, rmn_bits)); - avpriv_copy_bits(pb, data + size - rmn_bytes, + ff_copy_bits(pb, data + size - rmn_bytes, FFMIN(nbits - rmn_bits, rmn_bytes << 3)); } @@ -2004,5 +2007,6 @@ .close = wmavoice_decode_end, .decode = wmavoice_decode_packet, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .flush = wmavoice_flush, }; diff -Nru ffmpeg-4.2.2/libavcodec/wmv2dec.c ffmpeg-4.4/libavcodec/wmv2dec.c --- ffmpeg-4.2.2/libavcodec/wmv2dec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wmv2dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -278,22 +278,16 @@ return 0; } -static inline int wmv2_decode_motion(Wmv2Context *w, int *mx_ptr, int *my_ptr) +static inline void wmv2_decode_motion(Wmv2Context *w, int *mx_ptr, int *my_ptr) { MpegEncContext *const s = &w->s; - int ret; - - ret = ff_msmpeg4_decode_motion(s, mx_ptr, my_ptr); - if (ret < 0) - return ret; + ff_msmpeg4_decode_motion(s, mx_ptr, my_ptr); if ((((*mx_ptr) | (*my_ptr)) & 1) && s->mspel) w->hshift = get_bits1(&s->gb); else w->hshift = 0; - - return 0; } static int16_t *wmv2_pred_motion(Wmv2Context *w, int *px, int *py) @@ -409,8 +403,6 @@ code = get_vlc2(&s->gb, ff_mb_non_intra_vlc[w->cbp_table_index].table, MB_NON_INTRA_VLC_BITS, 3); - if (code < 0) - return AVERROR_INVALIDDATA; s->mb_intra = (~code & 0x40) >> 6; cbp = code & 0x3f; @@ -419,11 +411,6 @@ if (get_bits_left(&s->gb) <= 0) return AVERROR_INVALIDDATA; code = get_vlc2(&s->gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); - if (code < 0) { - av_log(s->avctx, AV_LOG_ERROR, - "II-cbp illegal at %d %d\n", s->mb_x, s->mb_y); - return AVERROR_INVALIDDATA; - } /* predict coded block pattern */ cbp = 0; for (i = 0; i < 6; i++) { @@ -456,8 +443,7 @@ w->per_block_abt = 0; } - if ((ret = wmv2_decode_motion(w, &mx, &my)) < 0) - return ret; + wmv2_decode_motion(w, &mx, &my); s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_16X16; @@ -537,6 +523,7 @@ .close = wmv2_decode_end, .decode = ff_h263_decode_frame, .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; diff -Nru ffmpeg-4.2.2/libavcodec/wmv2enc.c ffmpeg-4.4/libavcodec/wmv2enc.c --- ffmpeg-4.2.2/libavcodec/wmv2enc.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wmv2enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -231,6 +231,7 @@ .init = wmv2_encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; diff -Nru ffmpeg-4.2.2/libavcodec/wmv2.h ffmpeg-4.4/libavcodec/wmv2.h --- ffmpeg-4.2.2/libavcodec/wmv2.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wmv2.h 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,8 @@ #ifndef AVCODEC_WMV2_H #define AVCODEC_WMV2_H +#include "libavutil/mem_internal.h" + #include "avcodec.h" #include "intrax8.h" #include "mpegvideo.h" diff -Nru ffmpeg-4.2.2/libavcodec/wnv1.c ffmpeg-4.4/libavcodec/wnv1.c --- ffmpeg-4.2.2/libavcodec/wnv1.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/wnv1.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,89 +24,72 @@ * Winnov WNV1 codec. */ +#include "libavutil/thread.h" + +#define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" #include "internal.h" -#include "mathops.h" - - -typedef struct WNV1Context { - int shift; - GetBitContext gb; -} WNV1Context; -static const uint16_t code_tab[16][2] = { - { 0x1FD, 9 }, { 0xFD, 8 }, { 0x7D, 7 }, { 0x3D, 6 }, { 0x1D, 5 }, { 0x0D, 4 }, { 0x005, 3 }, - { 0x000, 1 }, - { 0x004, 3 }, { 0x0C, 4 }, { 0x1C, 5 }, { 0x3C, 6 }, { 0x7C, 7 }, { 0xFC, 8 }, { 0x1FC, 9 }, { 0xFF, 8 } +static const uint8_t code_tab[16][2] = { + { 7, 1 }, { 8, 3 }, { 6, 3 }, { 9, 4 }, { 5, 4 }, { 10, 5 }, { 4, 5 }, + { 11, 6 }, { 3, 6 }, { 12, 7 }, { 2, 7 }, { 13, 8 }, { 1, 8 }, { 14, 9 }, + { 0, 9 }, { 15, 8 } }; #define CODE_VLC_BITS 9 static VLC code_vlc; /* returns modified base_value */ -static inline int wnv1_get_code(WNV1Context *w, int base_value) +static inline int wnv1_get_code(GetBitContext *gb, int shift, int base_value) { - int v = get_vlc2(&w->gb, code_vlc.table, CODE_VLC_BITS, 1); + int v = get_vlc2(gb, code_vlc.table, CODE_VLC_BITS, 1); - if (v == 15) - return ff_reverse[get_bits(&w->gb, 8 - w->shift)]; + if (v == 8) + return get_bits(gb, 8 - shift) << shift; else - return base_value + ((v - 7U) << w->shift); + return base_value + v * (1 << shift); } static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { - WNV1Context * const l = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; AVFrame * const p = data; + GetBitContext gb; unsigned char *Y,*U,*V; - int i, j, ret; + int i, j, ret, shift; int prev_y = 0, prev_u = 0, prev_v = 0; - uint8_t *rbuf; if (buf_size < 8 + avctx->height * (avctx->width/2)/8) { av_log(avctx, AV_LOG_ERROR, "Packet size %d is too small\n", buf_size); return AVERROR_INVALIDDATA; } - rbuf = av_malloc(buf_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!rbuf) { - av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); - return AVERROR(ENOMEM); - } - memset(rbuf + buf_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); - - if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { - av_free(rbuf); + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; - } p->key_frame = 1; - for (i = 8; i < buf_size; i++) - rbuf[i] = ff_reverse[buf[i]]; - - if ((ret = init_get_bits8(&l->gb, rbuf + 8, buf_size - 8)) < 0) + if ((ret = init_get_bits8(&gb, buf + 8, buf_size - 8)) < 0) return ret; if (buf[2] >> 4 == 6) - l->shift = 2; + shift = 2; else { - l->shift = 8 - (buf[2] >> 4); - if (l->shift > 4) { + shift = 8 - (buf[2] >> 4); + if (shift > 4) { avpriv_request_sample(avctx, "Unknown WNV1 frame header value %i", buf[2] >> 4); - l->shift = 4; + shift = 4; } - if (l->shift < 1) { + if (shift < 1) { avpriv_request_sample(avctx, "Unknown WNV1 frame header value %i", buf[2] >> 4); - l->shift = 1; + shift = 1; } } @@ -115,10 +98,10 @@ V = p->data[2]; for (j = 0; j < avctx->height; j++) { for (i = 0; i < avctx->width / 2; i++) { - Y[i * 2] = wnv1_get_code(l, prev_y); - prev_u = U[i] = wnv1_get_code(l, prev_u); - prev_y = Y[(i * 2) + 1] = wnv1_get_code(l, Y[i * 2]); - prev_v = V[i] = wnv1_get_code(l, prev_v); + Y[i * 2] = wnv1_get_code(&gb, shift, prev_y); + prev_u = U[i] = wnv1_get_code(&gb, shift, prev_u); + prev_y = Y[(i * 2) + 1] = wnv1_get_code(&gb, shift, Y[i * 2]); + prev_v = V[i] = wnv1_get_code(&gb, shift, prev_v); } Y += p->linesize[0]; U += p->linesize[1]; @@ -127,22 +110,25 @@ *got_frame = 1; - av_free(rbuf); return buf_size; } +static av_cold void wnv1_init_static(void) +{ + INIT_VLC_STATIC_FROM_LENGTHS(&code_vlc, CODE_VLC_BITS, 16, + &code_tab[0][1], 2, + &code_tab[0][0], 2, 1, + -7, INIT_VLC_OUTPUT_LE, 1 << CODE_VLC_BITS); +} + static av_cold int decode_init(AVCodecContext *avctx) { - static VLC_TYPE code_table[1 << CODE_VLC_BITS][2]; + static AVOnce init_static_once = AV_ONCE_INIT; avctx->pix_fmt = AV_PIX_FMT_YUV422P; - code_vlc.table = code_table; - code_vlc.table_allocated = 1 << CODE_VLC_BITS; - init_vlc(&code_vlc, CODE_VLC_BITS, 16, - &code_tab[0][1], 4, 2, - &code_tab[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC); + ff_thread_once(&init_static_once, wnv1_init_static); return 0; } @@ -152,8 +138,8 @@ .long_name = NULL_IF_CONFIG_SMALL("Winnov WNV1"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_WNV1, - .priv_data_size = sizeof(WNV1Context), .init = decode_init, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/ws-snd1.c ffmpeg-4.4/libavcodec/ws-snd1.c --- ffmpeg-4.2.2/libavcodec/ws-snd1.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ws-snd1.c 2021-04-08 21:28:39.000000000 +0000 @@ -177,5 +177,6 @@ .id = AV_CODEC_ID_WESTWOOD_SND1, .init = ws_snd_decode_init, .decode = ws_snd_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/x86/ac3dsp.asm ffmpeg-4.4/libavcodec/x86/ac3dsp.asm --- ffmpeg-4.2.2/libavcodec/x86/ac3dsp.asm 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/ac3dsp.asm 2021-04-08 21:28:39.000000000 +0000 @@ -35,10 +35,6 @@ cextern pd_1 pd_151: times 4 dd 151 -; used in ff_apply_window_int16() -pb_revwords: SHUFFLE_MASK_W 7, 6, 5, 4, 3, 2, 1, 0 -pd_16384: times 4 dd 16384 - SECTION .text ;----------------------------------------------------------------------------- @@ -82,133 +78,6 @@ %undef LOOP_ALIGN ;----------------------------------------------------------------------------- -; int ff_ac3_max_msb_abs_int16(const int16_t *src, int len) -; -; This function uses 2 different methods to calculate a valid result. -; 1) logical 'or' of abs of each element -; This is used for ssse3 because of the pabsw instruction. -; It is also used for mmx because of the lack of min/max instructions. -; 2) calculate min/max for the array, then or(abs(min),abs(max)) -; This is used for mmxext and sse2 because they have pminsw/pmaxsw. -;----------------------------------------------------------------------------- - -; logical 'or' of 4 or 8 words in an mmx or xmm register into the low word -%macro OR_WORDS_HORIZ 2 ; src, tmp -%if cpuflag(sse2) - movhlps %2, %1 - por %1, %2 - pshuflw %2, %1, q0032 - por %1, %2 - pshuflw %2, %1, q0001 - por %1, %2 -%elif cpuflag(mmxext) - pshufw %2, %1, q0032 - por %1, %2 - pshufw %2, %1, q0001 - por %1, %2 -%else ; mmx - movq %2, %1 - psrlq %2, 32 - por %1, %2 - movq %2, %1 - psrlq %2, 16 - por %1, %2 -%endif -%endmacro - -%macro AC3_MAX_MSB_ABS_INT16 1 -cglobal ac3_max_msb_abs_int16, 2,2,5, src, len - pxor m2, m2 - pxor m3, m3 -.loop: -%ifidn %1, min_max - mova m0, [srcq] - mova m1, [srcq+mmsize] - pminsw m2, m0 - pminsw m2, m1 - pmaxsw m3, m0 - pmaxsw m3, m1 -%else ; or_abs -%if notcpuflag(ssse3) - mova m0, [srcq] - mova m1, [srcq+mmsize] - ABS2 m0, m1, m3, m4 -%else ; ssse3 - ; using memory args is faster for ssse3 - pabsw m0, [srcq] - pabsw m1, [srcq+mmsize] -%endif - por m2, m0 - por m2, m1 -%endif - add srcq, mmsize*2 - sub lend, mmsize - ja .loop -%ifidn %1, min_max - ABS2 m2, m3, m0, m1 - por m2, m3 -%endif - OR_WORDS_HORIZ m2, m0 - movd eax, m2 - and eax, 0xFFFF - RET -%endmacro - -INIT_MMX mmx -AC3_MAX_MSB_ABS_INT16 or_abs -INIT_MMX mmxext -AC3_MAX_MSB_ABS_INT16 min_max -INIT_XMM sse2 -AC3_MAX_MSB_ABS_INT16 min_max -INIT_XMM ssse3 -AC3_MAX_MSB_ABS_INT16 or_abs - -;----------------------------------------------------------------------------- -; macro used for ff_ac3_lshift_int16() and ff_ac3_rshift_int32() -;----------------------------------------------------------------------------- - -%macro AC3_SHIFT 3 ; l/r, 16/32, shift instruction, instruction set -cglobal ac3_%1shift_int%2, 3, 3, 5, src, len, shift - movd m0, shiftd -.loop: - mova m1, [srcq ] - mova m2, [srcq+mmsize ] - mova m3, [srcq+mmsize*2] - mova m4, [srcq+mmsize*3] - %3 m1, m0 - %3 m2, m0 - %3 m3, m0 - %3 m4, m0 - mova [srcq ], m1 - mova [srcq+mmsize ], m2 - mova [srcq+mmsize*2], m3 - mova [srcq+mmsize*3], m4 - add srcq, mmsize*4 - sub lend, mmsize*32/%2 - ja .loop -.end: - REP_RET -%endmacro - -;----------------------------------------------------------------------------- -; void ff_ac3_lshift_int16(int16_t *src, unsigned int len, unsigned int shift) -;----------------------------------------------------------------------------- - -INIT_MMX mmx -AC3_SHIFT l, 16, psllw -INIT_XMM sse2 -AC3_SHIFT l, 16, psllw - -;----------------------------------------------------------------------------- -; void ff_ac3_rshift_int32(int32_t *src, unsigned int len, unsigned int shift) -;----------------------------------------------------------------------------- - -INIT_MMX mmx -AC3_SHIFT r, 32, psrad -INIT_XMM sse2 -AC3_SHIFT r, 32, psrad - -;----------------------------------------------------------------------------- ; void ff_float_to_fixed24(int32_t *dst, const float *src, unsigned int len) ;----------------------------------------------------------------------------- @@ -423,130 +292,3 @@ INIT_XMM ssse3 AC3_EXTRACT_EXPONENTS %endif - -;----------------------------------------------------------------------------- -; void ff_apply_window_int16(int16_t *output, const int16_t *input, -; const int16_t *window, unsigned int len) -;----------------------------------------------------------------------------- - -%macro REVERSE_WORDS 1-2 -%if cpuflag(ssse3) && notcpuflag(atom) - pshufb %1, %2 -%elif cpuflag(sse2) - pshuflw %1, %1, 0x1B - pshufhw %1, %1, 0x1B - pshufd %1, %1, 0x4E -%elif cpuflag(mmxext) - pshufw %1, %1, 0x1B -%endif -%endmacro - -%macro MUL16FIXED 3 -%if cpuflag(ssse3) ; dst, src, unused -; dst = ((dst * src) + (1<<14)) >> 15 - pmulhrsw %1, %2 -%elif cpuflag(mmxext) ; dst, src, temp -; dst = (dst * src) >> 15 -; pmulhw cuts off the bottom bit, so we have to lshift by 1 and add it back -; in from the pmullw result. - mova %3, %1 - pmulhw %1, %2 - pmullw %3, %2 - psrlw %3, 15 - psllw %1, 1 - por %1, %3 -%endif -%endmacro - -%macro APPLY_WINDOW_INT16 1 ; %1 bitexact version -%if %1 -cglobal apply_window_int16, 4,5,6, output, input, window, offset, offset2 -%else -cglobal apply_window_int16_round, 4,5,6, output, input, window, offset, offset2 -%endif - lea offset2q, [offsetq-mmsize] -%if cpuflag(ssse3) && notcpuflag(atom) - mova m5, [pb_revwords] - ALIGN 16 -%elif %1 - mova m5, [pd_16384] -%endif -.loop: -%if cpuflag(ssse3) - ; This version does the 16x16->16 multiplication in-place without expanding - ; to 32-bit. The ssse3 version is bit-identical. - mova m0, [windowq+offset2q] - mova m1, [ inputq+offset2q] - pmulhrsw m1, m0 - REVERSE_WORDS m0, m5 - pmulhrsw m0, [ inputq+offsetq ] - mova [outputq+offset2q], m1 - mova [outputq+offsetq ], m0 -%elif %1 - ; This version expands 16-bit to 32-bit, multiplies by the window, - ; adds 16384 for rounding, right shifts 15, then repacks back to words to - ; save to the output. The window is reversed for the second half. - mova m3, [windowq+offset2q] - mova m4, [ inputq+offset2q] - pxor m0, m0 - punpcklwd m0, m3 - punpcklwd m1, m4 - pmaddwd m0, m1 - paddd m0, m5 - psrad m0, 15 - pxor m2, m2 - punpckhwd m2, m3 - punpckhwd m1, m4 - pmaddwd m2, m1 - paddd m2, m5 - psrad m2, 15 - packssdw m0, m2 - mova [outputq+offset2q], m0 - REVERSE_WORDS m3 - mova m4, [ inputq+offsetq] - pxor m0, m0 - punpcklwd m0, m3 - punpcklwd m1, m4 - pmaddwd m0, m1 - paddd m0, m5 - psrad m0, 15 - pxor m2, m2 - punpckhwd m2, m3 - punpckhwd m1, m4 - pmaddwd m2, m1 - paddd m2, m5 - psrad m2, 15 - packssdw m0, m2 - mova [outputq+offsetq], m0 -%else - ; This version does the 16x16->16 multiplication in-place without expanding - ; to 32-bit. The mmxext and sse2 versions do not use rounding, and - ; therefore are not bit-identical to the C version. - mova m0, [windowq+offset2q] - mova m1, [ inputq+offset2q] - mova m2, [ inputq+offsetq ] - MUL16FIXED m1, m0, m3 - REVERSE_WORDS m0 - MUL16FIXED m2, m0, m3 - mova [outputq+offset2q], m1 - mova [outputq+offsetq ], m2 -%endif - add offsetd, mmsize - sub offset2d, mmsize - jae .loop - REP_RET -%endmacro - -INIT_MMX mmxext -APPLY_WINDOW_INT16 0 -INIT_XMM sse2 -APPLY_WINDOW_INT16 0 - -INIT_MMX mmxext -APPLY_WINDOW_INT16 1 -INIT_XMM sse2 -APPLY_WINDOW_INT16 1 -INIT_XMM ssse3 -APPLY_WINDOW_INT16 1 -INIT_XMM ssse3, atom -APPLY_WINDOW_INT16 1 diff -Nru ffmpeg-4.2.2/libavcodec/x86/ac3dsp_init.c ffmpeg-4.4/libavcodec/x86/ac3dsp_init.c --- ffmpeg-4.2.2/libavcodec/x86/ac3dsp_init.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/ac3dsp_init.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,17 +30,6 @@ void ff_ac3_exponent_min_mmxext(uint8_t *exp, int num_reuse_blocks, int nb_coefs); void ff_ac3_exponent_min_sse2 (uint8_t *exp, int num_reuse_blocks, int nb_coefs); -int ff_ac3_max_msb_abs_int16_mmx (const int16_t *src, int len); -int ff_ac3_max_msb_abs_int16_mmxext(const int16_t *src, int len); -int ff_ac3_max_msb_abs_int16_sse2 (const int16_t *src, int len); -int ff_ac3_max_msb_abs_int16_ssse3(const int16_t *src, int len); - -void ff_ac3_lshift_int16_mmx (int16_t *src, unsigned int len, unsigned int shift); -void ff_ac3_lshift_int16_sse2(int16_t *src, unsigned int len, unsigned int shift); - -void ff_ac3_rshift_int32_mmx (int32_t *src, unsigned int len, unsigned int shift); -void ff_ac3_rshift_int32_sse2(int32_t *src, unsigned int len, unsigned int shift); - void ff_float_to_fixed24_3dnow(int32_t *dst, const float *src, unsigned int len); void ff_float_to_fixed24_sse (int32_t *dst, const float *src, unsigned int len); void ff_float_to_fixed24_sse2 (int32_t *dst, const float *src, unsigned int len); @@ -50,28 +39,12 @@ void ff_ac3_extract_exponents_sse2 (uint8_t *exp, int32_t *coef, int nb_coefs); void ff_ac3_extract_exponents_ssse3(uint8_t *exp, int32_t *coef, int nb_coefs); -void ff_apply_window_int16_round_mmxext(int16_t *output, const int16_t *input, - const int16_t *window, unsigned int len); -void ff_apply_window_int16_round_sse2(int16_t *output, const int16_t *input, - const int16_t *window, unsigned int len); -void ff_apply_window_int16_mmxext(int16_t *output, const int16_t *input, - const int16_t *window, unsigned int len); -void ff_apply_window_int16_sse2(int16_t *output, const int16_t *input, - const int16_t *window, unsigned int len); -void ff_apply_window_int16_ssse3(int16_t *output, const int16_t *input, - const int16_t *window, unsigned int len); -void ff_apply_window_int16_ssse3_atom(int16_t *output, const int16_t *input, - const int16_t *window, unsigned int len); - av_cold void ff_ac3dsp_init_x86(AC3DSPContext *c, int bit_exact) { int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_MMX(cpu_flags)) { c->ac3_exponent_min = ff_ac3_exponent_min_mmx; - c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_mmx; - c->ac3_lshift_int16 = ff_ac3_lshift_int16_mmx; - c->ac3_rshift_int32 = ff_ac3_rshift_int32_mmx; } if (EXTERNAL_AMD3DNOW(cpu_flags)) { if (!bit_exact) { @@ -80,43 +53,20 @@ } if (EXTERNAL_MMXEXT(cpu_flags)) { c->ac3_exponent_min = ff_ac3_exponent_min_mmxext; - c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_mmxext; - if (bit_exact) { - c->apply_window_int16 = ff_apply_window_int16_mmxext; - } else { - c->apply_window_int16 = ff_apply_window_int16_round_mmxext; - } } if (EXTERNAL_SSE(cpu_flags)) { c->float_to_fixed24 = ff_float_to_fixed24_sse; } if (EXTERNAL_SSE2(cpu_flags)) { c->ac3_exponent_min = ff_ac3_exponent_min_sse2; - c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_sse2; c->float_to_fixed24 = ff_float_to_fixed24_sse2; c->compute_mantissa_size = ff_ac3_compute_mantissa_size_sse2; c->extract_exponents = ff_ac3_extract_exponents_sse2; - if (bit_exact) { - c->apply_window_int16 = ff_apply_window_int16_sse2; - } - } - - if (EXTERNAL_SSE2_FAST(cpu_flags)) { - c->ac3_lshift_int16 = ff_ac3_lshift_int16_sse2; - c->ac3_rshift_int32 = ff_ac3_rshift_int32_sse2; - if (!bit_exact) { - c->apply_window_int16 = ff_apply_window_int16_round_sse2; - } } if (EXTERNAL_SSSE3(cpu_flags)) { - c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_ssse3; - if (cpu_flags & AV_CPU_FLAG_ATOM) { - c->apply_window_int16 = ff_apply_window_int16_ssse3_atom; - } else { + if (!(cpu_flags & AV_CPU_FLAG_ATOM)) c->extract_exponents = ff_ac3_extract_exponents_ssse3; - c->apply_window_int16 = ff_apply_window_int16_ssse3; - } } } diff -Nru ffmpeg-4.2.2/libavcodec/x86/cabac.h ffmpeg-4.4/libavcodec/x86/cabac.h --- ffmpeg-4.2.2/libavcodec/x86/cabac.h 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/cabac.h 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,8 @@ #ifndef AVCODEC_X86_CABAC_H #define AVCODEC_X86_CABAC_H +#include + #include "libavcodec/cabac.h" #include "libavutil/attributes.h" #include "libavutil/macros.h" diff -Nru ffmpeg-4.2.2/libavcodec/x86/cavsdsp.c ffmpeg-4.4/libavcodec/x86/cavsdsp.c --- ffmpeg-4.2.2/libavcodec/x86/cavsdsp.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/cavsdsp.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,6 +25,7 @@ #include "libavutil/attributes.h" #include "libavutil/common.h" #include "libavutil/cpu.h" +#include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/cavsdsp.h" diff -Nru ffmpeg-4.2.2/libavcodec/x86/cfhddsp.asm ffmpeg-4.4/libavcodec/x86/cfhddsp.asm --- ffmpeg-4.2.2/libavcodec/x86/cfhddsp.asm 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/cfhddsp.asm 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,697 @@ +;****************************************************************************** +;* x86-optimized functions for the CFHD decoder +;* Copyright (c) 2020 Paul B Mahol +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +factor_p1_n1: dw 1, -1, 1, -1, 1, -1, 1, -1, +factor_n1_p1: dw -1, 1, -1, 1, -1, 1, -1, 1, +factor_p11_n4: dw 11, -4, 11, -4, 11, -4, 11, -4, +factor_p5_p4: dw 5, 4, 5, 4, 5, 4, 5, 4, +pd_4: times 4 dd 4 +pw_1: times 8 dw 1 +pw_0: times 8 dw 0 +pw_1023: times 8 dw 1023 +pw_4095: times 8 dw 4095 + +SECTION .text + +%macro CFHD_HORIZ_FILTER 1 +%if %1 == 1023 +cglobal cfhd_horiz_filter_clip10, 5, 6, 8 + 4 * ARCH_X86_64, output, low, high, width, x, temp + shl widthd, 1 +%define ostrideq widthq +%define lwidthq widthq +%define hwidthq widthq +%elif %1 == 4095 +cglobal cfhd_horiz_filter_clip12, 5, 6, 8 + 4 * ARCH_X86_64, output, low, high, width, x, temp + shl widthd, 1 +%define ostrideq widthq +%define lwidthq widthq +%define hwidthq widthq +%else +%if ARCH_X86_64 +cglobal cfhd_horiz_filter, 8, 11, 12, output, ostride, low, lwidth, high, hwidth, width, height, x, y, temp + shl ostrided, 1 + shl lwidthd, 1 + shl hwidthd, 1 + shl widthd, 1 + + mov yd, heightd + neg yq +%else +cglobal cfhd_horiz_filter, 7, 7, 8, output, x, low, y, high, temp, width, height + shl xd, 1 + shl yd, 1 + shl tempd, 1 + shl widthd, 1 + + mov xmp, xq + mov ymp, yq + mov tempmp, tempq + + mov yd, r7m + neg yq + +%define ostrideq xm +%define lwidthq ym +%define hwidthq tempm +%endif +%endif + +%if ARCH_X86_64 + mova m8, [factor_p1_n1] + mova m9, [factor_n1_p1] + mova m10, [pw_1] + mova m11, [pd_4] +%endif + +%if %1 == 0 +.looph: +%endif + movsx xq, word [lowq] + imul xq, 11 + + movsx tempq, word [lowq + 2] + imul tempq, -4 + add tempq, xq + + movsx xq, word [lowq + 4] + add tempq, xq + add tempq, 4 + sar tempq, 3 + + movsx xq, word [highq] + add tempq, xq + sar tempq, 1 + +%if %1 + movd xm0, tempd + CLIPW m0, [pw_0], [pw_%1] + pextrw tempd, xm0, 0 +%endif + mov word [outputq], tempw + + movsx xq, word [lowq] + imul xq, 5 + + movsx tempq, word [lowq + 2] + imul tempq, 4 + add tempq, xq + + movsx xq, word [lowq + 4] + sub tempq, xq + add tempq, 4 + sar tempq, 3 + + movsx xq, word [highq] + sub tempq, xq + sar tempq, 1 + +%if %1 + movd xm0, tempd + CLIPW m0, [pw_0], [pw_%1] + pextrw tempd, xm0, 0 +%endif + mov word [outputq + 2], tempw + + mov xq, 0 + +.loop: + movu m4, [lowq + xq] + movu m1, [lowq + xq + 4] + + mova m5, m4 + punpcklwd m4, m1 + punpckhwd m5, m1 + + mova m6, m4 + mova m7, m5 + +%if ARCH_X86_64 + pmaddwd m4, m8 + pmaddwd m5, m8 + pmaddwd m6, m9 + pmaddwd m7, m9 + + paddd m4, m11 + paddd m5, m11 + paddd m6, m11 + paddd m7, m11 +%else + pmaddwd m4, [factor_p1_n1] + pmaddwd m5, [factor_p1_n1] + pmaddwd m6, [factor_n1_p1] + pmaddwd m7, [factor_n1_p1] + + paddd m4, [pd_4] + paddd m5, [pd_4] + paddd m6, [pd_4] + paddd m7, [pd_4] +%endif + + psrad m4, 3 + psrad m5, 3 + psrad m6, 3 + psrad m7, 3 + + movu m2, [lowq + xq + 2] + movu m3, [highq + xq + 2] + + mova m0, m2 + punpcklwd m2, m3 + punpckhwd m0, m3 + + mova m1, m2 + mova m3, m0 + +%if ARCH_X86_64 + pmaddwd m2, m10 + pmaddwd m0, m10 + pmaddwd m1, m8 + pmaddwd m3, m8 +%else + pmaddwd m2, [pw_1] + pmaddwd m0, [pw_1] + pmaddwd m1, [factor_p1_n1] + pmaddwd m3, [factor_p1_n1] +%endif + + paddd m2, m4 + paddd m0, m5 + paddd m1, m6 + paddd m3, m7 + + psrad m2, 1 + psrad m0, 1 + psrad m1, 1 + psrad m3, 1 + + packssdw m2, m0 + packssdw m1, m3 + + mova m0, m2 + punpcklwd m2, m1 + punpckhwd m0, m1 + +%if %1 + CLIPW m2, [pw_0], [pw_%1] + CLIPW m0, [pw_0], [pw_%1] +%endif + + movu [outputq + xq * 2 + 4], m2 + movu [outputq + xq * 2 + mmsize + 4], m0 + + add xq, mmsize + cmp xq, widthq + jl .loop + + add lowq, widthq + add highq, widthq + add outputq, widthq + add outputq, widthq + + movsx xq, word [lowq - 2] + imul xq, 5 + + movsx tempq, word [lowq - 4] + imul tempq, 4 + add tempq, xq + + movsx xq, word [lowq - 6] + sub tempq, xq + add tempq, 4 + sar tempq, 3 + + movsx xq, word [highq - 2] + add tempq, xq + sar tempq, 1 + +%if %1 + movd xm0, tempd + CLIPW m0, [pw_0], [pw_%1] + pextrw tempd, xm0, 0 +%endif + mov word [outputq - 4], tempw + + movsx xq, word [lowq - 2] + imul xq, 11 + + movsx tempq, word [lowq - 4] + imul tempq, -4 + add tempq, xq + + movsx xq, word [lowq - 6] + add tempq, xq + add tempq, 4 + sar tempq, 3 + + movsx xq, word [highq - 2] + sub tempq, xq + sar tempq, 1 + +%if %1 + movd xm0, tempd + CLIPW m0, [pw_0], [pw_%1] + pextrw tempd, xm0, 0 +%endif + mov word [outputq - 2], tempw + +%if %1 == 0 + sub lowq, widthq + sub highq, widthq + sub outputq, widthq + sub outputq, widthq + + add lowq, lwidthq + add highq, hwidthq + add outputq, ostrideq + add outputq, ostrideq + add yq, 1 + jl .looph +%endif + + RET +%endmacro + +INIT_XMM sse2 +CFHD_HORIZ_FILTER 0 + +INIT_XMM sse2 +CFHD_HORIZ_FILTER 1023 + +INIT_XMM sse2 +CFHD_HORIZ_FILTER 4095 + +INIT_XMM sse2 +%if ARCH_X86_64 +cglobal cfhd_vert_filter, 8, 11, 14, output, ostride, low, lwidth, high, hwidth, width, height, x, y, pos + shl ostrided, 1 + shl lwidthd, 1 + shl hwidthd, 1 + shl widthd, 1 + + dec heightd + + mova m8, [factor_p1_n1] + mova m9, [factor_n1_p1] + mova m10, [pw_1] + mova m11, [pd_4] + mova m12, [factor_p11_n4] + mova m13, [factor_p5_p4] +%else +cglobal cfhd_vert_filter, 7, 7, 8, output, x, low, y, high, pos, width, height + shl xd, 1 + shl yd, 1 + shl posd, 1 + shl widthd, 1 + + mov xmp, xq + mov ymp, yq + mov posmp, posq + + mov xq, r7m + dec xq + mov widthmp, xq + +%define ostrideq xm +%define lwidthq ym +%define hwidthq posm +%define heightq widthm + +%endif + + xor xq, xq +.loopw: + xor yq, yq + + mov posq, xq + movu m0, [lowq + posq] + add posq, lwidthq + movu m1, [lowq + posq] + mova m2, m0 + punpcklwd m0, m1 + punpckhwd m2, m1 + +%if ARCH_X86_64 + pmaddwd m0, m12 + pmaddwd m2, m12 +%else + pmaddwd m0, [factor_p11_n4] + pmaddwd m2, [factor_p11_n4] +%endif + + pxor m4, m4 + add posq, lwidthq + movu m1, [lowq + posq] + mova m3, m4 + punpcklwd m4, m1 + punpckhwd m3, m1 + + psrad m4, 16 + psrad m3, 16 + + paddd m0, m4 + paddd m2, m3 + + paddd m0, [pd_4] + paddd m2, [pd_4] + + psrad m0, 3 + psrad m2, 3 + + mov posq, xq + pxor m4, m4 + movu m1, [highq + posq] + mova m3, m4 + punpcklwd m4, m1 + punpckhwd m3, m1 + + psrad m4, 16 + psrad m3, 16 + + paddd m0, m4 + paddd m2, m3 + + psrad m0, 1 + psrad m2, 1 + + packssdw m0, m2 + + movu [outputq + posq], m0 + + movu m0, [lowq + posq] + add posq, lwidthq + movu m1, [lowq + posq] + mova m2, m0 + punpcklwd m0, m1 + punpckhwd m2, m1 + +%if ARCH_X86_64 + pmaddwd m0, m13 + pmaddwd m2, m13 +%else + pmaddwd m0, [factor_p5_p4] + pmaddwd m2, [factor_p5_p4] +%endif + + pxor m4, m4 + add posq, lwidthq + movu m1, [lowq + posq] + mova m3, m4 + punpcklwd m4, m1 + punpckhwd m3, m1 + + psrad m4, 16 + psrad m3, 16 + + psubd m0, m4 + psubd m2, m3 + + paddd m0, [pd_4] + paddd m2, [pd_4] + + psrad m0, 3 + psrad m2, 3 + + mov posq, xq + pxor m4, m4 + movu m1, [highq + posq] + mova m3, m4 + punpcklwd m4, m1 + punpckhwd m3, m1 + + psrad m4, 16 + psrad m3, 16 + + psubd m0, m4 + psubd m2, m3 + + psrad m0, 1 + psrad m2, 1 + + packssdw m0, m2 + + add posq, ostrideq + movu [outputq + posq], m0 + + add yq, 1 +.looph: + mov posq, lwidthq + imul posq, yq + sub posq, lwidthq + add posq, xq + + movu m4, [lowq + posq] + + add posq, lwidthq + add posq, lwidthq + movu m1, [lowq + posq] + + mova m5, m4 + punpcklwd m4, m1 + punpckhwd m5, m1 + + mova m6, m4 + mova m7, m5 + +%if ARCH_X86_64 + pmaddwd m4, m8 + pmaddwd m5, m8 + pmaddwd m6, m9 + pmaddwd m7, m9 + + paddd m4, m11 + paddd m5, m11 + paddd m6, m11 + paddd m7, m11 +%else + pmaddwd m4, [factor_p1_n1] + pmaddwd m5, [factor_p1_n1] + pmaddwd m6, [factor_n1_p1] + pmaddwd m7, [factor_n1_p1] + + paddd m4, [pd_4] + paddd m5, [pd_4] + paddd m6, [pd_4] + paddd m7, [pd_4] +%endif + + psrad m4, 3 + psrad m5, 3 + psrad m6, 3 + psrad m7, 3 + + sub posq, lwidthq + movu m0, [lowq + posq] + + mov posq, hwidthq + imul posq, yq + add posq, xq + movu m1, [highq + posq] + + mova m2, m0 + punpcklwd m0, m1 + punpckhwd m2, m1 + + mova m1, m0 + mova m3, m2 + +%if ARCH_X86_64 + pmaddwd m0, m10 + pmaddwd m2, m10 + pmaddwd m1, m8 + pmaddwd m3, m8 +%else + pmaddwd m0, [pw_1] + pmaddwd m2, [pw_1] + pmaddwd m1, [factor_p1_n1] + pmaddwd m3, [factor_p1_n1] +%endif + + paddd m0, m4 + paddd m2, m5 + paddd m1, m6 + paddd m3, m7 + + psrad m0, 1 + psrad m2, 1 + psrad m1, 1 + psrad m3, 1 + + packssdw m0, m2 + packssdw m1, m3 + + mov posq, ostrideq + imul posq, 2 + imul posq, yq + add posq, xq + + movu [outputq + posq], m0 + add posq, ostrideq + movu [outputq + posq], m1 + + add yq, 1 + cmp yq, heightq + jl .looph + + mov posq, lwidthq + imul posq, yq + add posq, xq + movu m0, [lowq + posq] + sub posq, lwidthq + movu m1, [lowq + posq] + mova m2, m0 + punpcklwd m0, m1 + punpckhwd m2, m1 + +%if ARCH_X86_64 + pmaddwd m0, m13 + pmaddwd m2, m13 +%else + pmaddwd m0, [factor_p5_p4] + pmaddwd m2, [factor_p5_p4] +%endif + + pxor m4, m4 + sub posq, lwidthq + movu m1, [lowq + posq] + mova m3, m4 + punpcklwd m4, m1 + punpckhwd m3, m1 + + psrad m4, 16 + psrad m3, 16 + + psubd m0, m4 + psubd m2, m3 + +%if ARCH_X86_64 + paddd m0, m11 + paddd m2, m11 +%else + paddd m0, [pd_4] + paddd m2, [pd_4] +%endif + + psrad m0, 3 + psrad m2, 3 + + mov posq, hwidthq + imul posq, yq + add posq, xq + pxor m4, m4 + movu m1, [highq + posq] + mova m3, m4 + punpcklwd m4, m1 + punpckhwd m3, m1 + + psrad m4, 16 + psrad m3, 16 + + paddd m0, m4 + paddd m2, m3 + + psrad m0, 1 + psrad m2, 1 + + packssdw m0, m2 + + mov posq, ostrideq + imul posq, 2 + imul posq, yq + add posq, xq + movu [outputq + posq], m0 + + mov posq, lwidthq + imul posq, yq + add posq, xq + movu m0, [lowq + posq] + sub posq, lwidthq + movu m1, [lowq + posq] + mova m2, m0 + punpcklwd m0, m1 + punpckhwd m2, m1 + +%if ARCH_X86_64 + pmaddwd m0, m12 + pmaddwd m2, m12 +%else + pmaddwd m0, [factor_p11_n4] + pmaddwd m2, [factor_p11_n4] +%endif + + pxor m4, m4 + sub posq, lwidthq + movu m1, [lowq + posq] + mova m3, m4 + punpcklwd m4, m1 + punpckhwd m3, m1 + + psrad m4, 16 + psrad m3, 16 + + paddd m0, m4 + paddd m2, m3 + +%if ARCH_X86_64 + paddd m0, m11 + paddd m2, m11 +%else + paddd m0, [pd_4] + paddd m2, [pd_4] +%endif + + psrad m0, 3 + psrad m2, 3 + + mov posq, hwidthq + imul posq, yq + add posq, xq + pxor m4, m4 + movu m1, [highq + posq] + mova m3, m4 + punpcklwd m4, m1 + punpckhwd m3, m1 + + psrad m4, 16 + psrad m3, 16 + + psubd m0, m4 + psubd m2, m3 + + psrad m0, 1 + psrad m2, 1 + + packssdw m0, m2 + + mov posq, ostrideq + imul posq, 2 + imul posq, yq + add posq, ostrideq + add posq, xq + movu [outputq + posq], m0 + + add xq, mmsize + cmp xq, widthq + jl .loopw + RET diff -Nru ffmpeg-4.2.2/libavcodec/x86/cfhddsp_init.c ffmpeg-4.4/libavcodec/x86/cfhddsp_init.c --- ffmpeg-4.2.2/libavcodec/x86/cfhddsp_init.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/cfhddsp_init.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/cfhddsp.h" + +void ff_cfhd_horiz_filter_sse2(int16_t *output, ptrdiff_t out_stride, + const int16_t *low, ptrdiff_t low_stride, + const int16_t *high, ptrdiff_t high_stride, + int width, int height); +void ff_cfhd_vert_filter_sse2(int16_t *output, ptrdiff_t out_stride, + const int16_t *low, ptrdiff_t low_stride, + const int16_t *high, ptrdiff_t high_stride, + int width, int height); +void ff_cfhd_horiz_filter_clip10_sse2(int16_t *output, const int16_t *low, const int16_t *high, int width, int bpc); +void ff_cfhd_horiz_filter_clip12_sse2(int16_t *output, const int16_t *low, const int16_t *high, int width, int bpc); + +av_cold void ff_cfhddsp_init_x86(CFHDDSPContext *c, int depth, int bayer) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_SSE2(cpu_flags)) { + c->horiz_filter = ff_cfhd_horiz_filter_sse2; + c->vert_filter = ff_cfhd_vert_filter_sse2; + if (depth == 10 && !bayer) + c->horiz_filter_clip = ff_cfhd_horiz_filter_clip10_sse2; + if (depth == 12 && !bayer) + c->horiz_filter_clip = ff_cfhd_horiz_filter_clip12_sse2; + } +} diff -Nru ffmpeg-4.2.2/libavcodec/x86/cfhdencdsp.asm ffmpeg-4.4/libavcodec/x86/cfhdencdsp.asm --- ffmpeg-4.2.2/libavcodec/x86/cfhdencdsp.asm 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/cfhdencdsp.asm 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,432 @@ +;****************************************************************************** +;* x86-optimized functions for the CFHD encoder +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA + +pw_p1_n1: dw 1, -1, 1, -1, 1, -1, 1, -1 +pw_n1_p1: dw -1, 1, -1, 1, -1, 1, -1, 1 +pw_p5_n11: dw 5, -11, 5, -11, 5, -11, 5, -11 +pw_n5_p11: dw -5, 11, -5, 11, -5, 11, -5, 11 +pw_p11_n5: dw 11, -5, 11, -5, 11, -5, 11, -5 +pw_n11_p5: dw -11, 5, -11, 5, -11, 5, -11, 5 +pd_4: times 4 dd 4 +pw_n4: times 8 dw -4 +cextern pw_m1 +cextern pw_1 +cextern pw_4 + +SECTION .text + +%if ARCH_X86_64 +INIT_XMM sse2 +cglobal cfhdenc_horiz_filter, 8, 10, 11, input, low, high, istride, lwidth, hwidth, width, y, x, temp + shl istrideq, 1 + shl lwidthq, 1 + shl hwidthq, 1 + mova m7, [pd_4] + mova m8, [pw_1] + mova m9, [pw_m1] + mova m10,[pw_p1_n1] + movsxdifnidn yq, yd + movsxdifnidn widthq, widthd + neg yq +.looph: + movsx xq, word [inputq] + + movsx tempq, word [inputq + 2] + add tempq, xq + + movd xm0, tempd + packssdw m0, m0 + movd tempd, m0 + mov word [lowq], tempw + + movsx xq, word [inputq] + imul xq, 5 + movsx tempq, word [inputq + 2] + imul tempq, -11 + add tempq, xq + + movsx xq, word [inputq + 4] + imul xq, 4 + add tempq, xq + + movsx xq, word [inputq + 6] + imul xq, 4 + add tempq, xq + + movsx xq, word [inputq + 8] + imul xq, -1 + add tempq, xq + + movsx xq, word [inputq + 10] + imul xq, -1 + add tempq, xq + + add tempq, 4 + sar tempq, 3 + + movd xm0, tempd + packssdw m0, m0 + movd tempd, m0 + mov word [highq], tempw + + mov xq, 2 + +.loopw: + movu m0, [inputq + xq * 2] + movu m1, [inputq + xq * 2 + mmsize] + + pmaddwd m0, m8 + pmaddwd m1, m8 + + packssdw m0, m1 + movu [lowq+xq], m0 + + movu m2, [inputq + xq * 2 - 4] + movu m3, [inputq + xq * 2 - 4 + mmsize] + + pmaddwd m2, m9 + pmaddwd m3, m9 + + movu m0, [inputq + xq * 2 + 4] + movu m1, [inputq + xq * 2 + 4 + mmsize] + + pmaddwd m0, m8 + pmaddwd m1, m8 + + paddd m0, m2 + paddd m1, m3 + + paddd m0, m7 + paddd m1, m7 + + psrad m0, 3 + psrad m1, 3 + + movu m5, [inputq + xq * 2 + 0] + movu m6, [inputq + xq * 2 + mmsize] + + pmaddwd m5, m10 + pmaddwd m6, m10 + + paddd m0, m5 + paddd m1, m6 + + packssdw m0, m1 + movu [highq+xq], m0 + + add xq, mmsize + cmp xq, widthq + jl .loopw + + add lowq, widthq + add highq, widthq + lea inputq, [inputq + widthq * 2] + + movsx xq, word [inputq - 4] + movsx tempq, word [inputq - 2] + add tempq, xq + + movd xm0, tempd + packssdw m0, m0 + movd tempd, m0 + mov word [lowq-2], tempw + + movsx tempq, word [inputq - 4] + imul tempq, 11 + movsx xq, word [inputq - 2] + imul xq, -5 + add tempq, xq + + movsx xq, word [inputq - 6] + imul xq, -4 + add tempq, xq + + movsx xq, word [inputq - 8] + imul xq, -4 + add tempq, xq + + movsx xq, word [inputq - 10] + add tempq, xq + + movsx xq, word [inputq - 12] + add tempq, xq + + add tempq, 4 + sar tempq, 3 + + movd xm0, tempd + packssdw m0, m0 + movd tempd, m0 + mov word [highq-2], tempw + + sub inputq, widthq + sub inputq, widthq + sub highq, widthq + sub lowq, widthq + + add lowq, lwidthq + add highq, hwidthq + add inputq, istrideq + add yq, 1 + jl .looph + + RET +%endif + +%if ARCH_X86_64 +INIT_XMM sse2 +cglobal cfhdenc_vert_filter, 8, 11, 14, input, low, high, istride, lwidth, hwidth, width, height, x, y, pos + shl istrideq, 1 + + shl widthd, 1 + sub heightd, 2 + + xor xq, xq + + mova m7, [pd_4] + mova m8, [pw_1] + mova m9, [pw_m1] + mova m10,[pw_p1_n1] + mova m11,[pw_n1_p1] + mova m12,[pw_4] + mova m13,[pw_n4] +.loopw: + mov yq, 2 + + mov posq, xq + movu m0, [inputq + posq] + add posq, istrideq + movu m1, [inputq + posq] + + paddsw m0, m1 + + movu [lowq + xq], m0 + + mov posq, xq + + movu m0, [inputq + posq] + add posq, istrideq + movu m1, [inputq + posq] + add posq, istrideq + movu m2, [inputq + posq] + add posq, istrideq + movu m3, [inputq + posq] + add posq, istrideq + movu m4, [inputq + posq] + add posq, istrideq + movu m5, [inputq + posq] + + mova m6, m0 + punpcklwd m0, m1 + punpckhwd m1, m6 + + mova m6, m2 + punpcklwd m2, m3 + punpckhwd m3, m6 + + mova m6, m4 + punpcklwd m4, m5 + punpckhwd m5, m6 + + pmaddwd m0, [pw_p5_n11] + pmaddwd m1, [pw_n11_p5] + pmaddwd m2, m12 + pmaddwd m3, m12 + pmaddwd m4, m9 + pmaddwd m5, m9 + + paddd m0, m2 + paddd m1, m3 + paddd m0, m4 + paddd m1, m5 + + paddd m0, m7 + paddd m1, m7 + + psrad m0, 3 + psrad m1, 3 + packssdw m0, m1 + + movu [highq + xq], m0 + +.looph: + + mov posq, istrideq + imul posq, yq + add posq, xq + + movu m0, [inputq + posq] + + add posq, istrideq + movu m1, [inputq + posq] + + paddsw m0, m1 + + mov posq, lwidthq + imul posq, yq + add posq, xq + + movu [lowq + posq], m0 + + add yq, -2 + + mov posq, istrideq + imul posq, yq + add posq, xq + + movu m0, [inputq + posq] + add posq, istrideq + movu m1, [inputq + posq] + add posq, istrideq + movu m2, [inputq + posq] + add posq, istrideq + movu m3, [inputq + posq] + add posq, istrideq + movu m4, [inputq + posq] + add posq, istrideq + movu m5, [inputq + posq] + + add yq, 2 + + mova m6, m0 + punpcklwd m0, m1 + punpckhwd m1, m6 + + mova m6, m2 + punpcklwd m2, m3 + punpckhwd m3, m6 + + mova m6, m4 + punpcklwd m4, m5 + punpckhwd m5, m6 + + pmaddwd m0, m9 + pmaddwd m1, m9 + pmaddwd m2, m10 + pmaddwd m3, m11 + pmaddwd m4, m8 + pmaddwd m5, m8 + + paddd m0, m4 + paddd m1, m5 + + paddd m0, m7 + paddd m1, m7 + + psrad m0, 3 + psrad m1, 3 + paddd m0, m2 + paddd m1, m3 + packssdw m0, m1 + + mov posq, hwidthq + imul posq, yq + add posq, xq + + movu [highq + posq], m0 + + add yq, 2 + cmp yq, heightq + jl .looph + + mov posq, istrideq + imul posq, yq + add posq, xq + + movu m0, [inputq + posq] + add posq, istrideq + movu m1, [inputq + posq] + + paddsw m0, m1 + + mov posq, lwidthq + imul posq, yq + add posq, xq + + movu [lowq + posq], m0 + + sub yq, 4 + + mov posq, istrideq + imul posq, yq + add posq, xq + + movu m0, [inputq + posq] + add posq, istrideq + movu m1, [inputq + posq] + add posq, istrideq + movu m2, [inputq + posq] + add posq, istrideq + movu m3, [inputq + posq] + add posq, istrideq + movu m4, [inputq + posq] + add posq, istrideq + movu m5, [inputq + posq] + + add yq, 4 + + mova m6, m0 + punpcklwd m0, m1 + punpckhwd m1, m6 + + mova m6, m2 + punpcklwd m2, m3 + punpckhwd m3, m6 + + mova m6, m4 + punpcklwd m4, m5 + punpckhwd m5, m6 + + pmaddwd m0, m8 + pmaddwd m1, m8 + pmaddwd m2, m13 + pmaddwd m3, m13 + pmaddwd m4, [pw_p11_n5] + pmaddwd m5, [pw_n5_p11] + + paddd m4, m2 + paddd m5, m3 + + paddd m4, m0 + paddd m5, m1 + + paddd m4, m7 + paddd m5, m7 + + psrad m4, 3 + psrad m5, 3 + packssdw m4, m5 + + mov posq, hwidthq + imul posq, yq + add posq, xq + + movu [highq + posq], m4 + + add xq, mmsize + cmp xq, widthq + jl .loopw + RET +%endif diff -Nru ffmpeg-4.2.2/libavcodec/x86/cfhdencdsp_init.c ffmpeg-4.4/libavcodec/x86/cfhdencdsp_init.c --- ffmpeg-4.2.2/libavcodec/x86/cfhdencdsp_init.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/cfhdencdsp_init.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/cfhdencdsp.h" + +void ff_cfhdenc_horiz_filter_sse2(int16_t *input, int16_t *low, int16_t *high, + ptrdiff_t in_stride, ptrdiff_t low_stride, + ptrdiff_t high_stride, + int width, int height); +void ff_cfhdenc_vert_filter_sse2(int16_t *input, int16_t *low, int16_t *high, + ptrdiff_t in_stride, ptrdiff_t low_stride, + ptrdiff_t high_stride, + int width, int height); + +av_cold void ff_cfhdencdsp_init_x86(CFHDEncDSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + +#if ARCH_X86_64 + if (EXTERNAL_SSE2(cpu_flags)) { + c->horiz_filter = ff_cfhdenc_horiz_filter_sse2; + c->vert_filter = ff_cfhdenc_vert_filter_sse2; + } +#endif +} diff -Nru ffmpeg-4.2.2/libavcodec/x86/constants.c ffmpeg-4.4/libavcodec/x86/constants.c --- ffmpeg-4.2.2/libavcodec/x86/constants.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/constants.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" // for xmm_reg #include "constants.h" @@ -34,7 +34,6 @@ DECLARE_ASM_ALIGNED(16, const xmm_reg, ff_pw_9) = { 0x0009000900090009ULL, 0x0009000900090009ULL }; DECLARE_ALIGNED(8, const uint64_t, ff_pw_15) = 0x000F000F000F000FULL; DECLARE_ALIGNED(16, const xmm_reg, ff_pw_16) = { 0x0010001000100010ULL, 0x0010001000100010ULL }; -DECLARE_ALIGNED(16, const xmm_reg, ff_pw_17) = { 0x0011001100110011ULL, 0x0011001100110011ULL }; DECLARE_ASM_ALIGNED(16, const xmm_reg, ff_pw_18) = { 0x0012001200120012ULL, 0x0012001200120012ULL }; DECLARE_ALIGNED(16, const xmm_reg, ff_pw_20) = { 0x0014001400140014ULL, 0x0014001400140014ULL }; DECLARE_ALIGNED(16, const xmm_reg, ff_pw_32) = { 0x0020002000200020ULL, 0x0020002000200020ULL }; diff -Nru ffmpeg-4.2.2/libavcodec/x86/diracdsp.asm ffmpeg-4.4/libavcodec/x86/diracdsp.asm --- ffmpeg-4.2.2/libavcodec/x86/diracdsp.asm 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/diracdsp.asm 2020-07-09 09:17:46.000000000 +0000 @@ -274,7 +274,7 @@ movd m3, qsd SPLATD m2 SPLATD m3 - mov r4, tot_hq + mov r4d, tot_hd mov r3, dstq .loop_v: @@ -294,8 +294,9 @@ add srcq, mmsize add dstq, mmsize - sub tot_hd, 4 + sub tot_hq, 4 jg .loop_h + lea srcq, [srcq + 4*tot_hq] add r3, strideq dec tot_vd diff -Nru ffmpeg-4.2.2/libavcodec/x86/diracdsp_init.c ffmpeg-4.4/libavcodec/x86/diracdsp_init.c --- ffmpeg-4.2.2/libavcodec/x86/diracdsp_init.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/diracdsp_init.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,15 +22,6 @@ #include "libavcodec/diracdsp.h" #include "fpel.h" -DECL_DIRAC_PIXOP(put, mmx); -DECL_DIRAC_PIXOP(avg, mmx); -DECL_DIRAC_PIXOP(avg, mmxext); - -void ff_put_dirac_pixels16_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h); -void ff_avg_dirac_pixels16_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h); -void ff_put_dirac_pixels32_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h); -void ff_avg_dirac_pixels32_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h); - void ff_add_rect_clamped_mmx(uint8_t *, const uint16_t *, int, const int16_t *, int, int, int); void ff_add_rect_clamped_sse2(uint8_t *, const uint16_t *, int, const int16_t *, int, int, int); @@ -72,89 +63,47 @@ } #define PIXFUNC(PFX, IDX, EXT) \ - /*MMXDISABLEDc->PFX ## _dirac_pixels_tab[0][IDX] = ff_ ## PFX ## _dirac_pixels8_ ## EXT;*/ \ - c->PFX ## _dirac_pixels_tab[1][IDX] = ff_ ## PFX ## _dirac_pixels16_ ## EXT; \ - c->PFX ## _dirac_pixels_tab[2][IDX] = ff_ ## PFX ## _dirac_pixels32_ ## EXT - -#define DIRAC_PIXOP(OPNAME2, OPNAME, EXT)\ -void ff_ ## OPNAME2 ## _dirac_pixels8_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ + /*MMXDISABLEDc->PFX ## _dirac_pixels_tab[0][IDX] = PFX ## _dirac_pixels8_ ## EXT;*/ \ + c->PFX ## _dirac_pixels_tab[1][IDX] = PFX ## _dirac_pixels16_ ## EXT; \ + c->PFX ## _dirac_pixels_tab[2][IDX] = PFX ## _dirac_pixels32_ ## EXT + +#define DIRAC_PIXOP(OPNAME, EXT)\ +static void OPNAME ## _dirac_pixels16_ ## EXT(uint8_t *dst, const uint8_t *src[5], \ + int stride, int h) \ {\ if (h&3)\ - ff_ ## OPNAME2 ## _dirac_pixels8_c(dst, src, stride, h);\ + ff_ ## OPNAME ## _dirac_pixels16_c(dst, src, stride, h);\ else\ - OPNAME ## _pixels8_ ## EXT(dst, src[0], stride, h);\ + ff_ ## OPNAME ## _pixels16_ ## EXT(dst, src[0], stride, h);\ }\ -void ff_ ## OPNAME2 ## _dirac_pixels16_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ -{\ - if (h&3)\ - ff_ ## OPNAME2 ## _dirac_pixels16_c(dst, src, stride, h);\ - else\ - OPNAME ## _pixels16_ ## EXT(dst, src[0], stride, h);\ -}\ -void ff_ ## OPNAME2 ## _dirac_pixels32_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +static void OPNAME ## _dirac_pixels32_ ## EXT(uint8_t *dst, const uint8_t *src[5], \ + int stride, int h) \ {\ if (h&3) {\ - ff_ ## OPNAME2 ## _dirac_pixels32_c(dst, src, stride, h);\ + ff_ ## OPNAME ## _dirac_pixels32_c(dst, src, stride, h);\ } else {\ - OPNAME ## _pixels16_ ## EXT(dst , src[0] , stride, h);\ - OPNAME ## _pixels16_ ## EXT(dst+16, src[0]+16, stride, h);\ + ff_ ## OPNAME ## _pixels16_ ## EXT(dst , src[0] , stride, h);\ + ff_ ## OPNAME ## _pixels16_ ## EXT(dst+16, src[0]+16, stride, h);\ }\ } -DIRAC_PIXOP(put, ff_put, mmx) -DIRAC_PIXOP(avg, ff_avg, mmx) -DIRAC_PIXOP(avg, ff_avg, mmxext) +DIRAC_PIXOP(put, mmx) +DIRAC_PIXOP(avg, mmx) +DIRAC_PIXOP(avg, mmxext) -void ff_put_dirac_pixels16_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h) -{ - if (h&3) - ff_put_dirac_pixels16_c(dst, src, stride, h); - else - ff_put_pixels16_sse2(dst, src[0], stride, h); -} -void ff_avg_dirac_pixels16_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h) -{ - if (h&3) - ff_avg_dirac_pixels16_c(dst, src, stride, h); - else - ff_avg_pixels16_sse2(dst, src[0], stride, h); -} -void ff_put_dirac_pixels32_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h) -{ - if (h&3) { - ff_put_dirac_pixels32_c(dst, src, stride, h); - } else { - ff_put_pixels16_sse2(dst , src[0] , stride, h); - ff_put_pixels16_sse2(dst+16, src[0]+16, stride, h); - } -} -void ff_avg_dirac_pixels32_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h) -{ - if (h&3) { - ff_avg_dirac_pixels32_c(dst, src, stride, h); - } else { - ff_avg_pixels16_sse2(dst , src[0] , stride, h); - ff_avg_pixels16_sse2(dst+16, src[0]+16, stride, h); - } -} - -#else // HAVE_X86ASM - -#define HPEL_FILTER(MMSIZE, EXT) \ - void dirac_hpel_filter_ ## EXT(uint8_t *dsth, uint8_t *dstv, uint8_t *dstc, \ - const uint8_t *src, int stride, int width, int height); - -#define PIXFUNC(PFX, IDX, EXT) do {} while (0) - -#endif // HAVE_X86ASM +DIRAC_PIXOP(put, sse2) +DIRAC_PIXOP(avg, sse2) #if !ARCH_X86_64 HPEL_FILTER(8, mmx) #endif HPEL_FILTER(16, sse2) +#endif // HAVE_X86ASM + void ff_diracdsp_init_x86(DiracDSPContext* c) { +#if HAVE_X86ASM int mm_flags = av_get_cpu_flags(); if (EXTERNAL_MMX(mm_flags)) { @@ -182,14 +131,15 @@ c->add_dirac_obmc[1] = ff_add_dirac_obmc16_sse2; c->add_dirac_obmc[2] = ff_add_dirac_obmc32_sse2; - c->put_dirac_pixels_tab[1][0] = ff_put_dirac_pixels16_sse2; - c->avg_dirac_pixels_tab[1][0] = ff_avg_dirac_pixels16_sse2; - c->put_dirac_pixels_tab[2][0] = ff_put_dirac_pixels32_sse2; - c->avg_dirac_pixels_tab[2][0] = ff_avg_dirac_pixels32_sse2; + c->put_dirac_pixels_tab[1][0] = put_dirac_pixels16_sse2; + c->avg_dirac_pixels_tab[1][0] = avg_dirac_pixels16_sse2; + c->put_dirac_pixels_tab[2][0] = put_dirac_pixels32_sse2; + c->avg_dirac_pixels_tab[2][0] = avg_dirac_pixels32_sse2; } if (EXTERNAL_SSE4(mm_flags)) { c->dequant_subband[1] = ff_dequant_subband_32_sse4; c->put_signed_rect_clamped[1] = ff_put_signed_rect_clamped_10_sse4; } +#endif } diff -Nru ffmpeg-4.2.2/libavcodec/x86/fdct.c ffmpeg-4.4/libavcodec/x86/fdct.c --- ffmpeg-4.2.2/libavcodec/x86/fdct.c 2016-03-29 02:25:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/fdct.c 2021-04-08 21:28:39.000000000 +0000 @@ -31,6 +31,7 @@ */ #include "libavutil/common.h" +#include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "fdct.h" diff -Nru ffmpeg-4.2.2/libavcodec/x86/h264_deblock.asm ffmpeg-4.4/libavcodec/x86/h264_deblock.asm --- ffmpeg-4.2.2/libavcodec/x86/h264_deblock.asm 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/h264_deblock.asm 2021-02-20 20:27:47.000000000 +0000 @@ -1185,7 +1185,7 @@ STORE_8_ROWS PASS8ROWS(pix_q - 2, r5 - 2, stride_q, r6) RET -cglobal deblock_h_chroma422_8, 5, 7, 8, 0-16, pix_, stride_, alpha_, beta_, tc0_, +cglobal deblock_h_chroma422_8, 5, 7, 8, 0-16, pix_, stride_, alpha_, beta_, tc0_ CHROMA_H_START_XMM r5, r6 LOAD_8_ROWS PASS8ROWS(pix_q - 2, r5 - 2, stride_q, r6) TRANSPOSE_8x4B_XMM diff -Nru ffmpeg-4.2.2/libavcodec/x86/h264_intrapred.asm ffmpeg-4.4/libavcodec/x86/h264_intrapred.asm --- ffmpeg-4.2.2/libavcodec/x86/h264_intrapred.asm 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/h264_intrapred.asm 2021-04-08 21:28:39.000000000 +0000 @@ -42,11 +42,7 @@ cextern pb_1 cextern pb_3 cextern pw_4 -cextern pw_5 cextern pw_8 -cextern pw_16 -cextern pw_17 -cextern pw_32 ;----------------------------------------------------------------------------- ; void ff_pred16x16_vertical_8(uint8_t *src, ptrdiff_t stride) diff -Nru ffmpeg-4.2.2/libavcodec/x86/h264_qpel.c ffmpeg-4.4/libavcodec/x86/h264_qpel.c --- ffmpeg-4.2.2/libavcodec/x86/h264_qpel.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/h264_qpel.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,7 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" +#include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/h264dec.h" diff -Nru ffmpeg-4.2.2/libavcodec/x86/hevc_add_res.asm ffmpeg-4.4/libavcodec/x86/hevc_add_res.asm --- ffmpeg-4.2.2/libavcodec/x86/hevc_add_res.asm 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/hevc_add_res.asm 2020-07-11 10:39:30.000000000 +0000 @@ -30,27 +30,26 @@ %macro ADD_RES_MMX_4_8 0 mova m0, [r1] mova m2, [r1+8] - pxor m1, m1 - pxor m3, m3 - psubw m1, m0 - psubw m3, m2 - packuswb m0, m2 - packuswb m1, m3 - movd m2, [r0] + movd m1, [r0] movd m3, [r0+r2] - punpckldq m2, m3 - paddusb m0, m2 - psubusb m0, m1 + punpcklbw m1, m4 + punpcklbw m3, m4 + + paddsw m0, m1 + paddsw m2, m3 + packuswb m0, m4 + packuswb m2, m4 + movd [r0], m0 - psrlq m0, 32 - movd [r0+r2], m0 + movd [r0+r2], m2 %endmacro INIT_MMX mmxext ; void ff_hevc_add_residual_4_8_mmxext(uint8_t *dst, int16_t *res, ptrdiff_t stride) cglobal hevc_add_residual_4_8, 3, 3, 6 + pxor m4, m4 ADD_RES_MMX_4_8 add r1, 16 lea r0, [r0+r2*2] @@ -58,69 +57,70 @@ RET %macro ADD_RES_SSE_8_8 0 - pxor m3, m3 - mova m4, [r1] - mova m6, [r1+16] - mova m0, [r1+32] - mova m2, [r1+48] - psubw m5, m3, m4 - psubw m7, m3, m6 - psubw m1, m3, m0 - packuswb m4, m0 - packuswb m5, m1 - psubw m3, m2 - packuswb m6, m2 - packuswb m7, m3 - movq m0, [r0] movq m1, [r0+r2] - movhps m0, [r0+r2*2] - movhps m1, [r0+r3] - paddusb m0, m4 - paddusb m1, m6 - psubusb m0, m5 - psubusb m1, m7 + punpcklbw m0, m4 + punpcklbw m1, m4 + mova m2, [r1] + mova m3, [r1+16] + paddsw m0, m2 + paddsw m1, m3 + packuswb m0, m1 + + movq m2, [r0+r2*2] + movq m3, [r0+r3] + punpcklbw m2, m4 + punpcklbw m3, m4 + mova m6, [r1+32] + mova m7, [r1+48] + paddsw m2, m6 + paddsw m3, m7 + packuswb m2, m3 + movq [r0], m0 - movq [r0+r2], m1 - movhps [r0+2*r2], m0 - movhps [r0+r3], m1 + movhps [r0+r2], m0 + movq [r0+r2*2], m2 + movhps [r0+r3], m2 %endmacro %macro ADD_RES_SSE_16_32_8 3 - mova xm2, [r1+%1] + mova m1, [%2] + mova m2, m1 + punpcklbw m1, m0 + punpckhbw m2, m0 + mova xm5, [r1+%1] mova xm6, [r1+%1+16] %if cpuflag(avx2) - vinserti128 m2, m2, [r1+%1+32], 1 + vinserti128 m5, m5, [r1+%1+32], 1 vinserti128 m6, m6, [r1+%1+48], 1 %endif - psubw m1, m0, m2 - psubw m5, m0, m6 - packuswb m2, m6 - packuswb m1, m5 + paddsw m1, m5 + paddsw m2, m6 - mova xm4, [r1+%1+mmsize*2] + mova m3, [%3] + mova m4, m3 + punpcklbw m3, m0 + punpckhbw m4, m0 + mova xm5, [r1+%1+mmsize*2] mova xm6, [r1+%1+mmsize*2+16] %if cpuflag(avx2) - vinserti128 m4, m4, [r1+%1+96 ], 1 + vinserti128 m5, m5, [r1+%1+96], 1 vinserti128 m6, m6, [r1+%1+112], 1 %endif - psubw m3, m0, m4 - psubw m5, m0, m6 - packuswb m4, m6 - packuswb m3, m5 - - paddusb m2, [%2] - paddusb m4, [%3] - psubusb m2, m1 - psubusb m4, m3 - mova [%2], m2 - mova [%3], m4 + paddsw m3, m5 + paddsw m4, m6 + + packuswb m1, m2 + packuswb m3, m4 + mova [%2], m1 + mova [%3], m3 %endmacro %macro TRANSFORM_ADD_8 0 ; void ff_hevc_add_residual_8_8_(uint8_t *dst, int16_t *res, ptrdiff_t stride) cglobal hevc_add_residual_8_8, 3, 4, 8 + pxor m4, m4 lea r3, [r2*3] ADD_RES_SSE_8_8 add r1, 64 diff -Nru ffmpeg-4.2.2/libavcodec/x86/hevcdsp_init.c ffmpeg-4.4/libavcodec/x86/hevcdsp_init.c --- ffmpeg-4.2.2/libavcodec/x86/hevcdsp_init.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/hevcdsp_init.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "config.h" #include "libavutil/cpu.h" +#include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/get_bits.h" /* required for hevcdsp.h GetBitContext */ diff -Nru ffmpeg-4.2.2/libavcodec/x86/Makefile ffmpeg-4.4/libavcodec/x86/Makefile --- ffmpeg-4.2.2/libavcodec/x86/Makefile 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/Makefile 2021-04-08 21:28:39.000000000 +0000 @@ -50,6 +50,8 @@ OBJS-$(CONFIG_ALAC_DECODER) += x86/alacdsp_init.o OBJS-$(CONFIG_APNG_DECODER) += x86/pngdsp_init.o OBJS-$(CONFIG_CAVS_DECODER) += x86/cavsdsp.o +OBJS-$(CONFIG_CFHD_DECODER) += x86/cfhddsp_init.o +OBJS-$(CONFIG_CFHD_ENCODER) += x86/cfhdencdsp_init.o OBJS-$(CONFIG_DCA_DECODER) += x86/dcadsp_init.o x86/synth_filter_init.o OBJS-$(CONFIG_DNXHD_ENCODER) += x86/dnxhdenc_init.o OBJS-$(CONFIG_EXR_DECODER) += x86/exrdsp_init.o @@ -153,6 +155,8 @@ X86ASM-OBJS-$(CONFIG_ALAC_DECODER) += x86/alacdsp.o X86ASM-OBJS-$(CONFIG_APNG_DECODER) += x86/pngdsp.o X86ASM-OBJS-$(CONFIG_CAVS_DECODER) += x86/cavsidct.o +X86ASM-OBJS-$(CONFIG_CFHD_ENCODER) += x86/cfhdencdsp.o +X86ASM-OBJS-$(CONFIG_CFHD_DECODER) += x86/cfhddsp.o X86ASM-OBJS-$(CONFIG_DCA_DECODER) += x86/dcadsp.o x86/synth_filter.o X86ASM-OBJS-$(CONFIG_DIRAC_DECODER) += x86/diracdsp.o \ x86/dirac_dwt.o diff -Nru ffmpeg-4.2.2/libavcodec/x86/me_cmp_init.c ffmpeg-4.4/libavcodec/x86/me_cmp_init.c --- ffmpeg-4.2.2/libavcodec/x86/me_cmp_init.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/me_cmp_init.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" +#include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/me_cmp.h" diff -Nru ffmpeg-4.2.2/libavcodec/x86/mpegaudiodsp.c ffmpeg-4.4/libavcodec/x86/mpegaudiodsp.c --- ffmpeg-4.2.2/libavcodec/x86/mpegaudiodsp.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/mpegaudiodsp.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/mpegaudiodsp.h" @@ -239,10 +240,8 @@ #endif #endif /* HAVE_X86ASM */ -av_cold void ff_mpadsp_init_x86(MPADSPContext *s) +av_cold void ff_mpadsp_init_x86_tabs(void) { - av_unused int cpu_flags = av_get_cpu_flags(); - int i, j; for (j = 0; j < 4; j++) { for (i = 0; i < 40; i ++) { @@ -256,6 +255,11 @@ mdct_win_sse[1][j][4*i + 3] = ff_mdct_win_float[j + 4][i]; } } +} + +av_cold void ff_mpadsp_init_x86(MPADSPContext *s) +{ + av_unused int cpu_flags = av_get_cpu_flags(); #if HAVE_6REGS && HAVE_SSE_INLINE if (INLINE_SSE(cpu_flags)) { diff -Nru ffmpeg-4.2.2/libavcodec/x86/mpegvideoenc.c ffmpeg-4.4/libavcodec/x86/mpegvideoenc.c --- ffmpeg-4.2.2/libavcodec/x86/mpegvideoenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/mpegvideoenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,7 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" +#include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/avcodec.h" diff -Nru ffmpeg-4.2.2/libavcodec/x86/mpegvideoenc_template.c ffmpeg-4.4/libavcodec/x86/mpegvideoenc_template.c --- ffmpeg-4.2.2/libavcodec/x86/mpegvideoenc_template.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/mpegvideoenc_template.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ #include #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "libavcodec/mpegutils.h" #include "libavcodec/mpegvideo.h" diff -Nru ffmpeg-4.2.2/libavcodec/x86/opusdsp.asm ffmpeg-4.4/libavcodec/x86/opusdsp.asm --- ffmpeg-4.2.2/libavcodec/x86/opusdsp.asm 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/opusdsp.asm 2020-07-11 10:39:30.000000000 +0000 @@ -64,7 +64,7 @@ add inq, mmsize add outq, mmsize - sub lenq, mmsize >> 2 + sub lend, mmsize >> 2 jg .loop %if ARCH_X86_64 == 0 @@ -80,7 +80,8 @@ VBROADCASTSS m1, [gainsq + 4] VBROADCASTSS m2, [gainsq + 8] - lea periodq, [periodq*4 + 8] + shl periodd, 2 + add periodq, 8 neg periodq movups m3, [dataq + periodq] @@ -104,7 +105,7 @@ movaps [dataq], m5 add dataq, mmsize - sub lenq, mmsize >> 2 + sub lend, mmsize >> 2 jg .loop RET diff -Nru ffmpeg-4.2.2/libavcodec/x86/opusdsp_init.c ffmpeg-4.4/libavcodec/x86/opusdsp_init.c --- ffmpeg-4.2.2/libavcodec/x86/opusdsp_init.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/opusdsp_init.c 2020-07-11 10:39:30.000000000 +0000 @@ -28,7 +28,7 @@ { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_FMA3_FAST(cpu_flags)) { + if (EXTERNAL_FMA3(cpu_flags)) { ctx->postfilter = ff_opus_postfilter_fma3; ctx->deemphasis = ff_opus_deemphasis_fma3; } diff -Nru ffmpeg-4.2.2/libavcodec/x86/pixblockdsp_init.c ffmpeg-4.4/libavcodec/x86/pixblockdsp_init.c --- ffmpeg-4.2.2/libavcodec/x86/pixblockdsp_init.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/pixblockdsp_init.c 2020-07-11 10:39:30.000000000 +0000 @@ -37,15 +37,19 @@ int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_MMX(cpu_flags)) { - if (!high_bit_depth) + if (!high_bit_depth) { + c->get_pixels_unaligned = c->get_pixels = ff_get_pixels_mmx; + } c->diff_pixels_unaligned = c->diff_pixels = ff_diff_pixels_mmx; } if (EXTERNAL_SSE2(cpu_flags)) { - if (!high_bit_depth) + if (!high_bit_depth) { + c->get_pixels_unaligned = c->get_pixels = ff_get_pixels_sse2; + } c->diff_pixels_unaligned = c->diff_pixels = ff_diff_pixels_sse2; } diff -Nru ffmpeg-4.2.2/libavcodec/x86/rv40dsp_init.c ffmpeg-4.4/libavcodec/x86/rv40dsp_init.c --- ffmpeg-4.2.2/libavcodec/x86/rv40dsp_init.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/rv40dsp_init.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,7 @@ #include "libavcodec/rv34dsp.h" #include "libavutil/attributes.h" #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavutil/x86/cpu.h" #include "hpeldsp.h" diff -Nru ffmpeg-4.2.2/libavcodec/x86/vc1dsp_mmx.c ffmpeg-4.4/libavcodec/x86/vc1dsp_mmx.c --- ffmpeg-4.2.2/libavcodec/x86/vc1dsp_mmx.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/vc1dsp_mmx.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,7 @@ #include "libavutil/cpu.h" #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" #include "libavcodec/vc1dsp.h" diff -Nru ffmpeg-4.2.2/libavcodec/x86/vp3dsp_init.c ffmpeg-4.4/libavcodec/x86/vp3dsp_init.c --- ffmpeg-4.2.2/libavcodec/x86/vp3dsp_init.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/vp3dsp_init.c 2020-07-11 10:39:30.000000000 +0000 @@ -59,8 +59,8 @@ c->idct_dc_add = ff_vp3_idct_dc_add_mmxext; if (!(flags & AV_CODEC_FLAG_BITEXACT)) { - c->v_loop_filter = ff_vp3_v_loop_filter_mmxext; - c->h_loop_filter = ff_vp3_h_loop_filter_mmxext; + c->v_loop_filter = c->v_loop_filter_unaligned = ff_vp3_v_loop_filter_mmxext; + c->h_loop_filter = c->v_loop_filter_unaligned = ff_vp3_h_loop_filter_mmxext; } } diff -Nru ffmpeg-4.2.2/libavcodec/x86/vp8dsp_init.c ffmpeg-4.4/libavcodec/x86/vp8dsp_init.c --- ffmpeg-4.2.2/libavcodec/x86/vp8dsp_init.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/vp8dsp_init.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavutil/x86/cpu.h" #include "libavcodec/vp8dsp.h" diff -Nru ffmpeg-4.2.2/libavcodec/x86/vp9dsp_init.h ffmpeg-4.4/libavcodec/x86/vp9dsp_init.h --- ffmpeg-4.2.2/libavcodec/x86/vp9dsp_init.h 2018-07-17 09:27:41.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/vp9dsp_init.h 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,8 @@ #ifndef AVCODEC_X86_VP9DSP_INIT_H #define AVCODEC_X86_VP9DSP_INIT_H +#include "libavutil/mem_internal.h" + #include "libavcodec/vp9dsp.h" // hack to force-expand BPC diff -Nru ffmpeg-4.2.2/libavcodec/x86/w64xmmtest.c ffmpeg-4.4/libavcodec/x86/w64xmmtest.c --- ffmpeg-4.2.2/libavcodec/x86/w64xmmtest.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/x86/w64xmmtest.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,6 +29,7 @@ testxmmclobbers(avcodec_open2, avctx, codec, options); } +#if FF_API_OLD_ENCDEC wrap(avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, @@ -47,15 +48,6 @@ got_picture_ptr, avpkt); } -wrap(avcodec_decode_subtitle2(AVCodecContext *avctx, - AVSubtitle *sub, - int *got_sub_ptr, - AVPacket *avpkt)) -{ - testxmmclobbers(avcodec_decode_subtitle2, avctx, sub, - got_sub_ptr, avpkt); -} - wrap(avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, @@ -65,6 +57,22 @@ got_packet_ptr); } +wrap(avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr)) +{ + testxmmclobbers(avcodec_encode_video2, avctx, avpkt, frame, got_packet_ptr); +} +#endif + +wrap(avcodec_decode_subtitle2(AVCodecContext *avctx, + AVSubtitle *sub, + int *got_sub_ptr, + AVPacket *avpkt)) +{ + testxmmclobbers(avcodec_decode_subtitle2, avctx, sub, + got_sub_ptr, avpkt); +} + wrap(avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, const AVSubtitle *sub)) @@ -72,12 +80,6 @@ testxmmclobbers(avcodec_encode_subtitle, avctx, buf, buf_size, sub); } -wrap(avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, - const AVFrame *frame, int *got_packet_ptr)) -{ - testxmmclobbers(avcodec_encode_video2, avctx, avpkt, frame, got_packet_ptr); -} - wrap(avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)) { testxmmclobbers(avcodec_send_packet, avctx, avpkt); diff -Nru ffmpeg-4.2.2/libavcodec/xan.c ffmpeg-4.4/libavcodec/xan.c --- ffmpeg-4.2.2/libavcodec/xan.c 2018-11-01 18:34:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/xan.c 2021-04-08 21:28:39.000000000 +0000 @@ -100,16 +100,12 @@ return AVERROR(ENOMEM); s->buffer2_size = avctx->width * avctx->height; s->buffer2 = av_malloc(s->buffer2_size + 130); - if (!s->buffer2) { - av_freep(&s->buffer1); + if (!s->buffer2) return AVERROR(ENOMEM); - } s->last_frame = av_frame_alloc(); - if (!s->last_frame) { - xan_decode_end(avctx); + if (!s->last_frame) return AVERROR(ENOMEM); - } return 0; } @@ -649,4 +645,5 @@ .close = xan_decode_end, .decode = xan_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/xbmdec.c ffmpeg-4.4/libavcodec/xbmdec.c --- ffmpeg-4.2.2/libavcodec/xbmdec.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/xbmdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,26 +26,31 @@ #include "internal.h" #include "mathops.h" -static int convert(uint8_t x) +static int get_nibble(uint8_t x) { - if (x >= 'a') - x -= 87; - else if (x >= 'A') - x -= 55; - else - x -= '0'; - return x; + int ret = 255; + + if (x <= '9') { + if (x >= '0') + ret = x - '0'; + } else if (x >= 'a') { + if (x <= 'f') + ret = x - ('a' - 10); + } else if (x >= 'A' && x <= 'F') + ret = x - ('A' - 10); + return ret; } -static int parse_str_int(const uint8_t *p, int len, const uint8_t *key) +static int parse_str_int(const uint8_t *p, const uint8_t *end, const uint8_t *key) { - const uint8_t *end = p + len; + int keylen = strlen(key); + const uint8_t *e = end - keylen; - for(; p= end) return INT_MIN; @@ -72,8 +77,8 @@ avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; end = avpkt->data + avpkt->size; - width = parse_str_int(avpkt->data, avpkt->size, "_width"); - height = parse_str_int(avpkt->data, avpkt->size, "_height"); + width = parse_str_int(avpkt->data, end, "_width"); + height = parse_str_int(avpkt->data, end, "_height"); if ((ret = ff_set_dimensions(avctx, width, height)) < 0) return ret; @@ -93,22 +98,26 @@ for (i = 0; i < avctx->height; i++) { dst = p->data[0] + i * p->linesize[0]; for (j = 0; j < linesize; j++) { - uint8_t val; + uint8_t nib, val; while (ptr < end && *ptr != 'x' && *ptr != '$') ptr++; ptr ++; - if (ptr < end && av_isxdigit(*ptr)) { - val = convert(*ptr++); - if (av_isxdigit(*ptr)) - val = (val << 4) + convert(*ptr++); + if (ptr < end && (val = get_nibble(*ptr)) <= 15) { + ptr++; + if ((nib = get_nibble(*ptr)) <= 15) { + val = (val << 4) + nib; + ptr++; + } *dst++ = ff_reverse[val]; - if (av_isxdigit(*ptr) && j+1 < linesize) { + if ((val = get_nibble(*ptr)) <= 15 && j+1 < linesize) { j++; - val = convert(*ptr++); - if (av_isxdigit(*ptr)) - val = (val << 4) + convert(*ptr++); + ptr++; + if ((nib = get_nibble(*ptr)) <= 15) { + val = (val << 4) + nib; + ptr++; + } *dst++ = ff_reverse[val]; } } else { diff -Nru ffmpeg-4.2.2/libavcodec/xbmenc.c ffmpeg-4.4/libavcodec/xbmenc.c --- ffmpeg-4.2.2/libavcodec/xbmenc.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/xbmenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,14 +24,25 @@ #include "internal.h" #include "mathops.h" +#define ANSI_MIN_READLINE 509 + static int xbm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *p, int *got_packet) { - int i, j, ret, size, linesize; + int i, j, l, commas, ret, size, linesize, lineout, rowsout; uint8_t *ptr, *buf; - linesize = (avctx->width + 7) / 8; - size = avctx->height * (linesize * 7 + 2) + 110; + linesize = lineout = (avctx->width + 7) / 8; + commas = avctx->height * linesize; + + /* ANSI worst case minimum readline is 509 chars. */ + rowsout = avctx->height; + if (lineout > (ANSI_MIN_READLINE / 6)) { + lineout = ANSI_MIN_READLINE / 6; + rowsout = (commas + lineout - 1) / lineout; + } + + size = rowsout * (lineout * 6 + 1) + 106; if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0) return ret; @@ -40,12 +51,21 @@ buf += snprintf(buf, 32, "#define image_width %u\n", avctx->width); buf += snprintf(buf, 33, "#define image_height %u\n", avctx->height); - buf += snprintf(buf, 40, "static unsigned char image_bits[] = {\n"); - for (i = 0; i < avctx->height; i++) { - for (j = 0; j < linesize; j++) - buf += snprintf(buf, 7, " 0x%02X,", ff_reverse[*ptr++]); + buf += snprintf(buf, 39, "static unsigned char image_bits[] = {\n"); + for (i = 0, l = lineout; i < avctx->height; i++) { + for (j = 0; j < linesize; j++) { + buf += snprintf(buf, 6, " 0x%02X", ff_reverse[*ptr++]); + if (--commas <= 0) { + buf += snprintf(buf, 2, "\n"); + break; + } + buf += snprintf(buf, 2, ","); + if (--l <= 0) { + buf += snprintf(buf, 2, "\n"); + l = lineout; + } + } ptr += p->linesize[0] - linesize; - buf += snprintf(buf, 2, "\n"); } buf += snprintf(buf, 5, " };\n"); diff -Nru ffmpeg-4.2.2/libavcodec/xbm_parser.c ffmpeg-4.4/libavcodec/xbm_parser.c --- ffmpeg-4.2.2/libavcodec/xbm_parser.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavcodec/xbm_parser.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,106 @@ +/* + * XBM parser + * 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 + */ + +/** + * @file + * XBM parser + */ + +#include "libavutil/common.h" + +#include "parser.h" + +typedef struct XBMParseContext { + ParseContext pc; + uint16_t state16; + int count; +} XBMParseContext; + +#define KEY (((uint64_t)'\n' << 56) | ((uint64_t)'#' << 48) | \ + ((uint64_t)'d' << 40) | ((uint64_t)'e' << 32) | \ + ((uint64_t)'f' << 24) | ('i' << 16) | ('n' << 8) | \ + ('e' << 0)) + +#define END ((';' << 8) | ('\n' << 0)) + +static int xbm_init(AVCodecParserContext *s) +{ + XBMParseContext *bpc = s->priv_data; + + bpc->count = 1; + + return 0; +} + +static int xbm_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + XBMParseContext *bpc = s->priv_data; + uint64_t state = bpc->pc.state64; + uint16_t state16 = bpc->state16; + int next = END_NOT_FOUND, i = 0; + + s->pict_type = AV_PICTURE_TYPE_I; + s->key_frame = 1; + s->duration = 1; + + *poutbuf_size = 0; + *poutbuf = NULL; + + for (; i < buf_size; i++) { + state = (state << 8) | buf[i]; + state16 = (state16 << 8) | buf[i]; + + if (state == KEY) + bpc->count++; + + if ((state == KEY && bpc->count == 1)) { + next = i - 6; + break; + } else if (state16 == END) { + next = i + 1; + bpc->count = 0; + break; + } + } + + bpc->pc.state64 = state; + bpc->state16 = state16; + if (ff_combine_frame(&bpc->pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +AVCodecParser ff_xbm_parser = { + .codec_ids = { AV_CODEC_ID_XBM }, + .priv_data_size = sizeof(XBMParseContext), + .parser_init = xbm_init, + .parser_parse = xbm_parse, + .parser_close = ff_parse_close, +}; diff -Nru ffmpeg-4.2.2/libavcodec/xfacedec.c ffmpeg-4.4/libavcodec/xfacedec.c --- ffmpeg-4.2.2/libavcodec/xfacedec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/xfacedec.c 2021-04-08 21:28:39.000000000 +0000 @@ -185,4 +185,5 @@ .init = xface_decode_init, .decode = xface_decode_frame, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/xfaceenc.c ffmpeg-4.4/libavcodec/xfaceenc.c --- ffmpeg-4.2.2/libavcodec/xfaceenc.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/xfaceenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -219,5 +219,4 @@ .priv_data_size = sizeof(XFaceContext), .encode2 = xface_encode_frame, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, - .capabilities = AV_CODEC_CAP_INTRA_ONLY, }; diff -Nru ffmpeg-4.2.2/libavcodec/xiph.c ffmpeg-4.4/libavcodec/xiph.c --- ffmpeg-4.2.2/libavcodec/xiph.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/xiph.c 2020-07-11 10:39:30.000000000 +0000 @@ -35,7 +35,7 @@ header_start[i] = extradata; extradata += header_len[i]; if (overall_len > extradata_size - header_len[i]) - return -1; + return AVERROR_INVALIDDATA; overall_len += header_len[i]; } } else if (extradata_size >= 3 && extradata_size < INT_MAX - 0x1ff && extradata[0] == 2) { @@ -50,7 +50,7 @@ header_len[i] += *extradata; overall_len += *extradata; if (overall_len > extradata_size) - return -1; + return AVERROR_INVALIDDATA; } header_len[2] = extradata_size - overall_len; header_start[0] = extradata; diff -Nru ffmpeg-4.2.2/libavcodec/xl.c ffmpeg-4.4/libavcodec/xl.c --- ffmpeg-4.2.2/libavcodec/xl.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/xl.c 2021-04-08 21:28:39.000000000 +0000 @@ -135,4 +135,5 @@ .init = decode_init, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/xsubdec.c ffmpeg-4.4/libavcodec/xsubdec.c --- ffmpeg-4.2.2/libavcodec/xsubdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavcodec/xsubdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,7 @@ #include "avcodec.h" #include "get_bits.h" #include "bytestream.h" +#include "internal.h" static av_cold int decode_init(AVCodecContext *avctx) { avctx->pix_fmt = AV_PIX_FMT_PAL8; @@ -46,7 +47,7 @@ return ms - packet_time; } -static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, +static int decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -169,7 +170,7 @@ bitmap += w; align_get_bits(&gb); } - *data_size = 1; + *got_sub_ptr = 1; return buf_size; } @@ -180,4 +181,5 @@ .id = AV_CODEC_ID_XSUB, .init = decode_init, .decode = decode_frame, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/xsubenc.c ffmpeg-4.4/libavcodec/xsubenc.c --- ffmpeg-4.2.2/libavcodec/xsubenc.c 2018-07-17 09:27:41.000000000 +0000 +++ ffmpeg-4.4/libavcodec/xsubenc.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "internal.h" #include "put_bits.h" /** @@ -63,7 +64,7 @@ while (x0 < w) { // Make sure we have enough room for at least one run and padding if (pb->size_in_bits - put_bits_count(pb) < 7*8) - return -1; + return AVERROR_BUFFER_TOO_SMALL; x1 = x0; color = bitmap[x1++] & 3; @@ -90,7 +91,7 @@ if (color != PADDING_COLOR && (PADDING + (w&1))) put_xsub_rle(pb, PADDING + (w&1), PADDING_COLOR); - avpriv_align_put_bits(pb); + align_put_bits(pb); bitmap += linesize; } @@ -124,7 +125,7 @@ if (bufsize < 27 + 7*2 + 4*3) { av_log(avctx, AV_LOG_ERROR, "Buffer too small for XSUB header.\n"); - return -1; + return AVERROR_BUFFER_TOO_SMALL; } // TODO: support multiple rects @@ -147,7 +148,7 @@ // TODO: render text-based subtitles into bitmaps if (!h->rects[0]->data[0] || !h->rects[0]->data[1]) { av_log(avctx, AV_LOG_WARNING, "No subtitle bitmap available.\n"); - return -1; + return AVERROR(EINVAL); } // TODO: color reduction, similar to dvdsub encoder @@ -160,7 +161,7 @@ if (make_tc(startTime, start_tc) || make_tc(endTime, end_tc)) { av_log(avctx, AV_LOG_WARNING, "Time code >= 100 hours.\n"); - return -1; + return AVERROR(EINVAL); } snprintf(buf, 28, @@ -195,18 +196,17 @@ if (xsub_encode_rle(&pb, h->rects[0]->data[0], h->rects[0]->linesize[0] * 2, h->rects[0]->w, (h->rects[0]->h + 1) >> 1)) - return -1; + return AVERROR_BUFFER_TOO_SMALL; bytestream_put_le16(&rlelenptr, put_bits_count(&pb) >> 3); // Length of first field if (xsub_encode_rle(&pb, h->rects[0]->data[0] + h->rects[0]->linesize[0], h->rects[0]->linesize[0] * 2, h->rects[0]->w, h->rects[0]->h >> 1)) - return -1; + return AVERROR_BUFFER_TOO_SMALL; // Enforce total height to be a multiple of 2 if (h->rects[0]->h & 1) { put_xsub_rle(&pb, h->rects[0]->w, PADDING_COLOR); - avpriv_align_put_bits(&pb); } flush_put_bits(&pb); @@ -231,4 +231,5 @@ .id = AV_CODEC_ID_XSUB, .init = xsub_encoder_init, .encode_sub = xsub_encode, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/xvididct.c ffmpeg-4.4/libavcodec/xvididct.c --- ffmpeg-4.2.2/libavcodec/xvididct.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/xvididct.c 2020-07-09 09:17:46.000000000 +0000 @@ -115,24 +115,24 @@ in[6] = a1; } else { const int k = c4 * in[0] + rnd; - const int a0 = k + c2 * in[2] + c4 * in[4] + c6 * in[6]; - const int a1 = k + c6 * in[2] - c4 * in[4] - c2 * in[6]; - const int a2 = k - c6 * in[2] - c4 * in[4] + c2 * in[6]; - const int a3 = k - c2 * in[2] + c4 * in[4] - c6 * in[6]; + const unsigned int a0 = k + c2 * in[2] + c4 * in[4] + c6 * in[6]; + const unsigned int a1 = k + c6 * in[2] - c4 * in[4] - c2 * in[6]; + const unsigned int a2 = k - c6 * in[2] - c4 * in[4] + c2 * in[6]; + const unsigned int a3 = k - c2 * in[2] + c4 * in[4] - c6 * in[6]; - const int b0 = c1 * in[1] + c3 * in[3] + c5 * in[5] + c7 * in[7]; - const int b1 = c3 * in[1] - c7 * in[3] - c1 * in[5] - c5 * in[7]; - const int b2 = c5 * in[1] - c1 * in[3] + c7 * in[5] + c3 * in[7]; - const int b3 = c7 * in[1] - c5 * in[3] + c3 * in[5] - c1 * in[7]; + const unsigned int b0 = c1 * in[1] + c3 * in[3] + c5 * in[5] + c7 * in[7]; + const unsigned int b1 = c3 * in[1] - c7 * in[3] - c1 * in[5] - c5 * in[7]; + const unsigned int b2 = c5 * in[1] - c1 * in[3] + c7 * in[5] + c3 * in[7]; + const unsigned int b3 = c7 * in[1] - c5 * in[3] + c3 * in[5] - c1 * in[7]; - in[0] = (a0 + b0) >> ROW_SHIFT; - in[1] = (a1 + b1) >> ROW_SHIFT; - in[2] = (a2 + b2) >> ROW_SHIFT; - in[3] = (a3 + b3) >> ROW_SHIFT; - in[4] = (a3 - b3) >> ROW_SHIFT; - in[5] = (a2 - b2) >> ROW_SHIFT; - in[6] = (a1 - b1) >> ROW_SHIFT; - in[7] = (a0 - b0) >> ROW_SHIFT; + in[0] = (int)(a0 + b0) >> ROW_SHIFT; + in[1] = (int)(a1 + b1) >> ROW_SHIFT; + in[2] = (int)(a2 + b2) >> ROW_SHIFT; + in[3] = (int)(a3 + b3) >> ROW_SHIFT; + in[4] = (int)(a3 - b3) >> ROW_SHIFT; + in[5] = (int)(a2 - b2) >> ROW_SHIFT; + in[6] = (int)(a1 - b1) >> ROW_SHIFT; + in[7] = (int)(a0 - b0) >> ROW_SHIFT; } return 1; } @@ -142,7 +142,7 @@ #define TAN3 0xAB0E #define SQRT2 0x5A82 -#define MULT(c, x, n) (((c) * (x)) >> (n)) +#define MULT(c, x, n) ((unsigned)((int)((c) * (unsigned)(x)) >> (n))) // 12b version => #define MULT(c,x, n) ((((c) >> 3) * (x)) >> ((n) - 3)) // 12b zero-testing version: diff -Nru ffmpeg-4.2.2/libavcodec/xxan.c ffmpeg-4.4/libavcodec/xxan.c --- ffmpeg-4.2.2/libavcodec/xxan.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavcodec/xxan.c 2021-04-08 21:28:39.000000000 +0000 @@ -71,16 +71,12 @@ if (!s->y_buffer) return AVERROR(ENOMEM); s->scratch_buffer = av_malloc(s->buffer_size + 130); - if (!s->scratch_buffer) { - xan_decode_end(avctx); + if (!s->scratch_buffer) return AVERROR(ENOMEM); - } s->pic = av_frame_alloc(); - if (!s->pic) { - xan_decode_end(avctx); + if (!s->pic) return AVERROR(ENOMEM); - } return 0; } @@ -410,7 +406,7 @@ int ftype; int ret; - if ((ret = ff_reget_buffer(avctx, s->pic)) < 0) + if ((ret = ff_reget_buffer(avctx, s->pic, 0)) < 0) return ret; bytestream2_init(&s->gb, avpkt->data, avpkt->size); @@ -447,4 +443,5 @@ .close = xan_decode_end, .decode = xan_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/y41pdec.c ffmpeg-4.4/libavcodec/y41pdec.c --- ffmpeg-4.2.2/libavcodec/y41pdec.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/y41pdec.c 2021-04-08 21:28:39.000000000 +0000 @@ -89,4 +89,5 @@ .init = y41p_decode_init, .decode = y41p_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/y41penc.c ffmpeg-4.4/libavcodec/y41penc.c --- ffmpeg-4.2.2/libavcodec/y41penc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/y41penc.c 2021-04-08 21:28:39.000000000 +0000 @@ -75,11 +75,6 @@ return 0; } -static av_cold int y41p_encode_close(AVCodecContext *avctx) -{ - return 0; -} - AVCodec ff_y41p_encoder = { .name = "y41p", .long_name = NULL_IF_CONFIG_SMALL("Uncompressed YUV 4:1:1 12-bit"), @@ -87,8 +82,7 @@ .id = AV_CODEC_ID_Y41P, .init = y41p_encode_init, .encode2 = y41p_encode_frame, - .close = y41p_encode_close, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, AV_PIX_FMT_NONE }, - .capabilities = AV_CODEC_CAP_INTRA_ONLY, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/ylc.c ffmpeg-4.4/libavcodec/ylc.c --- ffmpeg-4.2.2/libavcodec/ylc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/ylc.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,8 @@ #include #include +#define YLC_VLC_BITS 10 + #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" @@ -36,11 +38,9 @@ typedef struct YLCContext { VLC vlc[4]; - uint32_t table[1024]; - uint8_t *table_bits; - uint8_t *bitstream_bits; - int table_bits_size; - int bitstream_bits_size; + uint32_t table[256]; + uint8_t *buffer; + int buffer_size; BswapDSPContext bdsp; } YLCContext; @@ -56,7 +56,6 @@ typedef struct Node { int16_t sym; - int16_t n0; uint32_t count; int16_t l, r; } Node; @@ -97,7 +96,6 @@ for (i = 0; i < 256; i++) { nodes[i].count = table[i]; nodes[i].sym = i; - nodes[i].n0 = -2; nodes[i].l = i; nodes[i].r = i; } @@ -139,7 +137,6 @@ } nodes[cur_node].count = nd + st; nodes[cur_node].sym = -1; - nodes[cur_node].n0 = cur_node; nodes[cur_node].l = first_node; nodes[cur_node].r = second_node; cur_node++; @@ -149,7 +146,8 @@ get_tree_codes(bits, lens, xlat, nodes, cur_node - 1, 0, 0, &pos); - return ff_init_vlc_sparse(vlc, 10, pos, lens, 2, 2, bits, 4, 4, xlat, 1, 1, 0); + return ff_init_vlc_sparse(vlc, YLC_VLC_BITS, pos, lens, 2, 2, + bits, 4, 4, xlat, 1, 1, 0); } static const uint8_t table_y1[] = { @@ -312,50 +310,39 @@ if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) return ret; - av_fast_malloc(&s->table_bits, &s->table_bits_size, - boffset - toffset + AV_INPUT_BUFFER_PADDING_SIZE); - if (!s->table_bits) + av_fast_malloc(&s->buffer, &s->buffer_size, + FFMAX(boffset - toffset, avpkt->size - boffset) + + AV_INPUT_BUFFER_PADDING_SIZE); + if (!s->buffer) return AVERROR(ENOMEM); - memcpy(s->table_bits, avpkt->data + toffset, boffset - toffset); - memset(s->table_bits + boffset - toffset, 0, AV_INPUT_BUFFER_PADDING_SIZE); - s->bdsp.bswap_buf((uint32_t *) s->table_bits, - (uint32_t *) s->table_bits, + memcpy(s->buffer, avpkt->data + toffset, boffset - toffset); + memset(s->buffer + boffset - toffset, 0, AV_INPUT_BUFFER_PADDING_SIZE); + s->bdsp.bswap_buf((uint32_t *) s->buffer, + (uint32_t *) s->buffer, (boffset - toffset + 3) >> 2); - if ((ret = init_get_bits8(&gb, s->table_bits, boffset - toffset)) < 0) + if ((ret = init_get_bits8(&gb, s->buffer, boffset - toffset)) < 0) return ret; - for (x = 0; x < 1024; x++) { - unsigned len = get_unary(&gb, 1, 31); - uint32_t val = ((1U << len) - 1) + get_bits_long(&gb, len); - - s->table[x] = val; - } + for (int i = 0; i < 4; i++) { + for (x = 0; x < 256; x++) { + unsigned len = get_unary(&gb, 1, 31); + uint32_t val = ((1U << len) - 1) + get_bits_long(&gb, len); - ret = build_vlc(avctx, &s->vlc[0], &s->table[0 ]); - if (ret < 0) - return ret; - ret = build_vlc(avctx, &s->vlc[1], &s->table[256]); - if (ret < 0) - return ret; - ret = build_vlc(avctx, &s->vlc[2], &s->table[512]); - if (ret < 0) - return ret; - ret = build_vlc(avctx, &s->vlc[3], &s->table[768]); - if (ret < 0) - return ret; + s->table[x] = val; + } - av_fast_malloc(&s->bitstream_bits, &s->bitstream_bits_size, - avpkt->size - boffset + AV_INPUT_BUFFER_PADDING_SIZE); - if (!s->bitstream_bits) - return AVERROR(ENOMEM); + ret = build_vlc(avctx, &s->vlc[i], s->table); + if (ret < 0) + return ret; + } - memcpy(s->bitstream_bits, avpkt->data + boffset, avpkt->size - boffset); - memset(s->bitstream_bits + avpkt->size - boffset, 0, AV_INPUT_BUFFER_PADDING_SIZE); - s->bdsp.bswap_buf((uint32_t *) s->bitstream_bits, - (uint32_t *) s->bitstream_bits, + memcpy(s->buffer, avpkt->data + boffset, avpkt->size - boffset); + memset(s->buffer + avpkt->size - boffset, 0, AV_INPUT_BUFFER_PADDING_SIZE); + s->bdsp.bswap_buf((uint32_t *) s->buffer, + (uint32_t *) s->buffer, (avpkt->size - boffset) >> 2); - if ((ret = init_get_bits8(&gb, s->bitstream_bits, avpkt->size - boffset)) < 0) + if ((ret = init_get_bits8(&gb, s->buffer, avpkt->size - boffset)) < 0) return ret; dst = p->data[0]; @@ -371,7 +358,7 @@ return AVERROR_INVALIDDATA; if (get_bits1(&gb)) { - int val = get_vlc2(&gb, s->vlc[0].table, s->vlc[0].bits, 3); + int val = get_vlc2(&gb, s->vlc[0].table, YLC_VLC_BITS, 3); if (val < 0) { return AVERROR_INVALIDDATA; } else if (val < 0xE1) { @@ -394,10 +381,10 @@ } else { int y1, y2, u, v; - y1 = get_vlc2(&gb, s->vlc[1].table, s->vlc[1].bits, 3); - u = get_vlc2(&gb, s->vlc[2].table, s->vlc[2].bits, 3); - y2 = get_vlc2(&gb, s->vlc[1].table, s->vlc[1].bits, 3); - v = get_vlc2(&gb, s->vlc[3].table, s->vlc[3].bits, 3); + y1 = get_vlc2(&gb, s->vlc[1].table, YLC_VLC_BITS, 3); + u = get_vlc2(&gb, s->vlc[2].table, YLC_VLC_BITS, 3); + y2 = get_vlc2(&gb, s->vlc[1].table, YLC_VLC_BITS, 3); + v = get_vlc2(&gb, s->vlc[3].table, YLC_VLC_BITS, 3); if (y1 < 0 || y2 < 0 || u < 0 || v < 0) return AVERROR_INVALIDDATA; dst[x ] = y1; @@ -453,36 +440,14 @@ return avpkt->size; } -#if HAVE_THREADS -static int init_thread_copy(AVCodecContext *avctx) -{ - YLCContext *s = avctx->priv_data; - - memset(&s->vlc[0], 0, sizeof(VLC)); - memset(&s->vlc[1], 0, sizeof(VLC)); - memset(&s->vlc[2], 0, sizeof(VLC)); - memset(&s->vlc[3], 0, sizeof(VLC)); - s->table_bits = NULL; - s->table_bits_size = 0; - s->bitstream_bits = NULL; - s->bitstream_bits_size = 0; - - return 0; -} -#endif - static av_cold int decode_end(AVCodecContext *avctx) { YLCContext *s = avctx->priv_data; - ff_free_vlc(&s->vlc[0]); - ff_free_vlc(&s->vlc[1]); - ff_free_vlc(&s->vlc[2]); - ff_free_vlc(&s->vlc[3]); - av_freep(&s->table_bits); - s->table_bits_size = 0; - av_freep(&s->bitstream_bits); - s->bitstream_bits_size = 0; + for (int i = 0; i < FF_ARRAY_ELEMS(s->vlc); i++) + ff_free_vlc(&s->vlc[i]); + av_freep(&s->buffer); + s->buffer_size = 0; return 0; } @@ -494,7 +459,6 @@ .id = AV_CODEC_ID_YLC, .priv_data_size = sizeof(YLCContext), .init = decode_init, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(init_thread_copy), .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, diff -Nru ffmpeg-4.2.2/libavcodec/yop.c ffmpeg-4.4/libavcodec/yop.c --- ffmpeg-4.2.2/libavcodec/yop.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavcodec/yop.c 2021-04-08 21:28:39.000000000 +0000 @@ -204,7 +204,7 @@ return AVERROR_INVALIDDATA; } - if ((ret = ff_reget_buffer(avctx, frame)) < 0) + if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0) return ret; if (!avctx->frame_number) @@ -274,4 +274,5 @@ .init = yop_decode_init, .close = yop_decode_close, .decode = yop_decode_frame, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/yuv4dec.c ffmpeg-4.4/libavcodec/yuv4dec.c --- ffmpeg-4.2.2/libavcodec/yuv4dec.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/yuv4dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -81,4 +81,5 @@ .init = yuv4_decode_init, .decode = yuv4_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff -Nru ffmpeg-4.2.2/libavcodec/yuv4enc.c ffmpeg-4.4/libavcodec/yuv4enc.c --- ffmpeg-4.2.2/libavcodec/yuv4enc.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavcodec/yuv4enc.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,11 +23,6 @@ #include "avcodec.h" #include "internal.h" -static av_cold int yuv4_encode_init(AVCodecContext *avctx) -{ - return 0; -} - static int yuv4_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pic, int *got_packet) { @@ -62,19 +57,11 @@ return 0; } -static av_cold int yuv4_encode_close(AVCodecContext *avctx) -{ - return 0; -} - AVCodec ff_yuv4_encoder = { .name = "yuv4", .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_YUV4, - .init = yuv4_encode_init, .encode2 = yuv4_encode_frame, - .close = yuv4_encode_close, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .capabilities = AV_CODEC_CAP_INTRA_ONLY, }; diff -Nru ffmpeg-4.2.2/libavcodec/zerocodec.c ffmpeg-4.4/libavcodec/zerocodec.c --- ffmpeg-4.2.2/libavcodec/zerocodec.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavcodec/zerocodec.c 2020-07-11 10:39:30.000000000 +0000 @@ -131,14 +131,19 @@ } zc->previous_frame = av_frame_alloc(); - if (!zc->previous_frame) { - zerocodec_decode_close(avctx); + if (!zc->previous_frame) return AVERROR(ENOMEM); - } return 0; } +static void zerocodec_decode_flush(AVCodecContext *avctx) +{ + ZeroCodecContext *zc = avctx->priv_data; + + av_frame_unref(zc->previous_frame); +} + AVCodec ff_zerocodec_decoder = { .type = AVMEDIA_TYPE_VIDEO, .name = "zerocodec", @@ -147,7 +152,9 @@ .priv_data_size = sizeof(ZeroCodecContext), .init = zerocodec_decode_init, .decode = zerocodec_decode_frame, + .flush = zerocodec_decode_flush, .close = zerocodec_decode_close, .capabilities = AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, }; diff -Nru ffmpeg-4.2.2/libavcodec/zmbv.c ffmpeg-4.4/libavcodec/zmbv.c --- ffmpeg-4.2.2/libavcodec/zmbv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/zmbv.c 2020-07-11 10:39:30.000000000 +0000 @@ -69,8 +69,8 @@ int stride; int bw, bh, bx, by; int decomp_len; + int got_keyframe; z_stream zstream; - int (*decode_intra)(struct ZmbvContext *c); int (*decode_xor)(struct ZmbvContext *c); } ZmbvContext; @@ -425,8 +425,7 @@ c->flags = buf[0]; buf++; len--; if (c->flags & ZMBV_KEYFRAME) { - void *decode_intra = NULL; - c->decode_intra= NULL; + c->got_keyframe = 0; if (len < 6) return AVERROR_INVALIDDATA; @@ -436,7 +435,6 @@ c->fmt = buf[3]; c->bw = buf[4]; c->bh = buf[5]; - c->decode_intra = NULL; c->decode_xor = NULL; buf += 6; @@ -460,7 +458,6 @@ switch (c->fmt) { case ZMBV_FMT_8BPP: c->bpp = 8; - decode_intra = zmbv_decode_intra; c->decode_xor = zmbv_decode_xor_8; avctx->pix_fmt = AV_PIX_FMT_PAL8; c->stride = c->width; @@ -468,7 +465,6 @@ case ZMBV_FMT_15BPP: case ZMBV_FMT_16BPP: c->bpp = 16; - decode_intra = zmbv_decode_intra; c->decode_xor = zmbv_decode_xor_16; if (c->fmt == ZMBV_FMT_15BPP) avctx->pix_fmt = AV_PIX_FMT_RGB555LE; @@ -479,7 +475,6 @@ #ifdef ZMBV_ENABLE_24BPP case ZMBV_FMT_24BPP: c->bpp = 24; - decode_intra = zmbv_decode_intra; c->decode_xor = zmbv_decode_xor_24; avctx->pix_fmt = AV_PIX_FMT_BGR24; c->stride = c->width * 3; @@ -487,7 +482,6 @@ #endif //ZMBV_ENABLE_24BPP case ZMBV_FMT_32BPP: c->bpp = 32; - decode_intra = zmbv_decode_intra; c->decode_xor = zmbv_decode_xor_32; avctx->pix_fmt = AV_PIX_FMT_BGR0; c->stride = c->width * 4; @@ -517,7 +511,7 @@ } memset(c->cur, 0, avctx->width * avctx->height * (c->bpp / 8)); memset(c->prev, 0, avctx->width * avctx->height * (c->bpp / 8)); - c->decode_intra= decode_intra; + c->got_keyframe = 1; } if (c->flags & ZMBV_KEYFRAME) { expected_size = avctx->width * avctx->height * (c->bpp / 8); @@ -528,7 +522,7 @@ (c->flags & (ZMBV_DELTAPAL | ZMBV_KEYFRAME))) expected_size += 768; - if (!c->decode_intra) { + if (!c->got_keyframe) { av_log(avctx, AV_LOG_ERROR, "Error! Got no format or no keyframe!\n"); return AVERROR_INVALIDDATA; } @@ -542,7 +536,7 @@ c->decomp_len = len; } else { // ZLIB-compressed data c->zstream.total_in = c->zstream.total_out = 0; - c->zstream.next_in = (uint8_t*)buf; + c->zstream.next_in = buf; c->zstream.avail_in = len; c->zstream.next_out = c->decomp_buf; c->zstream.avail_out = c->decomp_size; @@ -564,7 +558,7 @@ if (c->flags & ZMBV_KEYFRAME) { frame->key_frame = 1; frame->pict_type = AV_PICTURE_TYPE_I; - c->decode_intra(c); + zmbv_decode_intra(c); } else { frame->key_frame = 0; frame->pict_type = AV_PICTURE_TYPE_P; diff -Nru ffmpeg-4.2.2/libavcodec/zmbvenc.c ffmpeg-4.4/libavcodec/zmbvenc.c --- ffmpeg-4.2.2/libavcodec/zmbvenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavcodec/zmbvenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -240,8 +240,8 @@ tprev = prev + x * c->bypp; zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored); - mv[0] = (mx << 1) | !!xored; - mv[1] = my << 1; + mv[0] = (mx * 2) | !!xored; + mv[1] = my * 2; tprev += mx * c->bypp + my * c->pstride; if(xored){ for(j = 0; j < bh2; j++){ @@ -409,7 +409,7 @@ */ c->pstride = FFALIGN((avctx->width + c->lrange) * c->bypp, 16); prev_size = FFALIGN(c->lrange * c->bypp, 16) + c->pstride * (c->lrange + avctx->height + c->urange); - prev_offset = FFALIGN(c->lrange, 16) + c->pstride * c->lrange; + prev_offset = FFALIGN(c->lrange * c->bypp, 16) + c->pstride * c->lrange; if (!(c->prev_buf = av_mallocz(prev_size))) { av_log(avctx, AV_LOG_ERROR, "Can't allocate picture.\n"); return AVERROR(ENOMEM); diff -Nru ffmpeg-4.2.2/libavdevice/alldevices.c ffmpeg-4.4/libavdevice/alldevices.c --- ffmpeg-4.2.2/libavdevice/alldevices.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/alldevices.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ extern AVInputFormat ff_alsa_demuxer; extern AVOutputFormat ff_alsa_muxer; extern AVInputFormat ff_android_camera_demuxer; +extern AVOutputFormat ff_audiotoolbox_muxer; extern AVInputFormat ff_avfoundation_demuxer; extern AVInputFormat ff_bktr_demuxer; extern AVOutputFormat ff_caca_muxer; @@ -66,3 +67,75 @@ { avpriv_register_devices(outdev_list, indev_list); } + +static void *next_input(const AVInputFormat *prev, AVClassCategory c2) +{ + const AVClass *pc; + const AVClassCategory c1 = AV_CLASS_CATEGORY_DEVICE_INPUT; + AVClassCategory category = AV_CLASS_CATEGORY_NA; + const AVInputFormat *fmt = NULL; + int i = 0; + + while (prev && (fmt = indev_list[i])) { + i++; + if (prev == fmt) + break; + } + + do { + fmt = indev_list[i++]; + if (!fmt) + break; + pc = fmt->priv_class; + if (!pc) + continue; + category = pc->category; + } while (category != c1 && category != c2); + return (AVInputFormat *)fmt; +} + +static void *next_output(const AVOutputFormat *prev, AVClassCategory c2) +{ + const AVClass *pc; + const AVClassCategory c1 = AV_CLASS_CATEGORY_DEVICE_OUTPUT; + AVClassCategory category = AV_CLASS_CATEGORY_NA; + const AVOutputFormat *fmt = NULL; + int i = 0; + + while (prev && (fmt = outdev_list[i])) { + i++; + if (prev == fmt) + break; + } + + do { + fmt = outdev_list[i++]; + if (!fmt) + break; + pc = fmt->priv_class; + if (!pc) + continue; + category = pc->category; + } while (category != c1 && category != c2); + return (AVOutputFormat *)fmt; +} + +AVInputFormat *av_input_audio_device_next(AVInputFormat *d) +{ + return next_input(d, AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT); +} + +AVInputFormat *av_input_video_device_next(AVInputFormat *d) +{ + return next_input(d, AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT); +} + +AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d) +{ + return next_output(d, AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT); +} + +AVOutputFormat *av_output_video_device_next(AVOutputFormat *d) +{ + return next_output(d, AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT); +} diff -Nru ffmpeg-4.2.2/libavdevice/alsa.c ffmpeg-4.4/libavdevice/alsa.c --- ffmpeg-4.2.2/libavdevice/alsa.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/alsa.c 2021-04-08 21:28:39.000000000 +0000 @@ -286,6 +286,10 @@ } } + s->pkt = av_packet_alloc(); + if (!s->pkt) + goto fail1; + s->h = h; return 0; @@ -308,6 +312,7 @@ if (CONFIG_ALSA_INDEV) ff_timefilter_destroy(s->timefilter); snd_pcm_close(s->h); + av_packet_free(&s->pkt); return 0; } diff -Nru ffmpeg-4.2.2/libavdevice/alsa_dec.c ffmpeg-4.4/libavdevice/alsa_dec.c --- ffmpeg-4.2.2/libavdevice/alsa_dec.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavdevice/alsa_dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -105,34 +105,36 @@ int64_t dts; snd_pcm_sframes_t delay = 0; - if (av_new_packet(pkt, s->period_size * s->frame_size) < 0) { - return AVERROR(EIO); + if (!s->pkt->data) { + int ret = av_new_packet(s->pkt, s->period_size * s->frame_size); + if (ret < 0) + return ret; + s->pkt->size = 0; } - while ((res = snd_pcm_readi(s->h, pkt->data, s->period_size)) < 0) { + do { + while ((res = snd_pcm_readi(s->h, s->pkt->data + s->pkt->size, s->period_size - s->pkt->size / s->frame_size)) < 0) { if (res == -EAGAIN) { - av_packet_unref(pkt); - return AVERROR(EAGAIN); } + s->pkt->size = 0; if (ff_alsa_xrun_recover(s1, res) < 0) { av_log(s1, AV_LOG_ERROR, "ALSA read error: %s\n", snd_strerror(res)); - av_packet_unref(pkt); - return AVERROR(EIO); } ff_timefilter_reset(s->timefilter); - } + } + s->pkt->size += res * s->frame_size; + } while (s->pkt->size < s->period_size * s->frame_size); + av_packet_move_ref(pkt, s->pkt); dts = av_gettime(); snd_pcm_delay(s->h, &delay); dts -= av_rescale(delay + res, 1000000, s->sample_rate); pkt->pts = ff_timefilter_update(s->timefilter, dts, s->last_period); s->last_period = res; - pkt->size = res * s->frame_size; - return 0; } @@ -148,7 +150,7 @@ }; static const AVClass alsa_demuxer_class = { - .class_name = "ALSA demuxer", + .class_name = "ALSA indev", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, diff -Nru ffmpeg-4.2.2/libavdevice/alsa_enc.c ffmpeg-4.4/libavdevice/alsa_enc.c --- ffmpeg-4.2.2/libavdevice/alsa_enc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavdevice/alsa_enc.c 2020-07-11 10:39:30.000000000 +0000 @@ -151,7 +151,7 @@ } static const AVClass alsa_muxer_class = { - .class_name = "ALSA muxer", + .class_name = "ALSA outdev", .item_name = av_default_item_name, .version = LIBAVUTIL_VERSION_INT, .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, diff -Nru ffmpeg-4.2.2/libavdevice/alsa.h ffmpeg-4.4/libavdevice/alsa.h --- ffmpeg-4.2.2/libavdevice/alsa.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/alsa.h 2021-04-08 21:28:39.000000000 +0000 @@ -58,6 +58,7 @@ void *reorder_buf; int reorder_buf_size; ///< in frames int64_t timestamp; ///< current timestamp, without latency applied. + AVPacket *pkt; } AlsaData; /** diff -Nru ffmpeg-4.2.2/libavdevice/audiotoolbox.m ffmpeg-4.4/libavdevice/audiotoolbox.m --- ffmpeg-4.2.2/libavdevice/audiotoolbox.m 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavdevice/audiotoolbox.m 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,308 @@ +/* + * AudioToolbox output device + * Copyright (c) 2020 Thilo Borgmann + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * AudioToolbox output device + * @author Thilo Borgmann + */ + +#import +#include + +#include "libavutil/opt.h" +#include "libavformat/internal.h" +#include "libavutil/internal.h" +#include "avdevice.h" + +typedef struct +{ + AVClass *class; + + AudioQueueBufferRef buffer[2]; + pthread_mutex_t buffer_lock[2]; + int cur_buf; + AudioQueueRef queue; + + int list_devices; + int audio_device_index; + +} ATContext; + +static int check_status(AVFormatContext *avctx, OSStatus *status, const char *msg) +{ + if (*status != noErr) { + av_log(avctx, AV_LOG_ERROR, "Error: %s (%i)\n", msg, *status); + return 1; + } else { + av_log(avctx, AV_LOG_DEBUG, " OK : %s\n", msg); + return 0; + } +} + +static void queue_callback(void* atctx, AudioQueueRef inAQ, + AudioQueueBufferRef inBuffer) +{ + // unlock the buffer that has just been consumed + ATContext *ctx = (ATContext*)atctx; + for (int i = 0; i < 2; i++) { + if (inBuffer == ctx->buffer[i]) { + pthread_mutex_unlock(&ctx->buffer_lock[i]); + } + } +} + +static av_cold int at_write_header(AVFormatContext *avctx) +{ + ATContext *ctx = (ATContext*)avctx->priv_data; + OSStatus err = noErr; + CFStringRef device_UID = NULL; + AudioDeviceID *devices; + int num_devices; + + + // get devices + UInt32 data_size = 0; + AudioObjectPropertyAddress prop; + prop.mSelector = kAudioHardwarePropertyDevices; + prop.mScope = kAudioObjectPropertyScopeGlobal; + prop.mElement = kAudioObjectPropertyElementMaster; + err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &prop, 0, NULL, &data_size); + if (check_status(avctx, &err, "AudioObjectGetPropertyDataSize devices")) + return AVERROR(EINVAL); + + num_devices = data_size / sizeof(AudioDeviceID); + + devices = (AudioDeviceID*)(av_malloc(data_size)); + err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &prop, 0, NULL, &data_size, devices); + if (check_status(avctx, &err, "AudioObjectGetPropertyData devices")) { + av_freep(&devices); + return AVERROR(EINVAL); + } + + // list devices + if (ctx->list_devices) { + CFStringRef device_name = NULL; + prop.mScope = kAudioDevicePropertyScopeInput; + + av_log(ctx, AV_LOG_INFO, "CoreAudio devices:\n"); + for(UInt32 i = 0; i < num_devices; ++i) { + // UID + data_size = sizeof(device_UID); + prop.mSelector = kAudioDevicePropertyDeviceUID; + err = AudioObjectGetPropertyData(devices[i], &prop, 0, NULL, &data_size, &device_UID); + if (check_status(avctx, &err, "AudioObjectGetPropertyData UID")) + continue; + + // name + data_size = sizeof(device_name); + prop.mSelector = kAudioDevicePropertyDeviceNameCFString; + err = AudioObjectGetPropertyData(devices[i], &prop, 0, NULL, &data_size, &device_name); + if (check_status(avctx, &err, "AudioObjecTGetPropertyData name")) + continue; + + av_log(ctx, AV_LOG_INFO, "[%d] %30s, %s\n", i, + CFStringGetCStringPtr(device_name, kCFStringEncodingMacRoman), + CFStringGetCStringPtr(device_UID, kCFStringEncodingMacRoman)); + } + } + + // get user-defined device UID or use default device + // -audio_device_index overrides any URL given + const char *stream_name = avctx->url; + if (stream_name && ctx->audio_device_index == -1) { + sscanf(stream_name, "%d", &ctx->audio_device_index); + } + + if (ctx->audio_device_index >= 0) { + // get UID of selected device + data_size = sizeof(device_UID); + prop.mSelector = kAudioDevicePropertyDeviceUID; + err = AudioObjectGetPropertyData(devices[ctx->audio_device_index], &prop, 0, NULL, &data_size, &device_UID); + if (check_status(avctx, &err, "AudioObjecTGetPropertyData UID")) { + av_freep(&devices); + return AVERROR(EINVAL); + } + } else { + // use default device + device_UID = NULL; + } + + av_log(ctx, AV_LOG_DEBUG, "stream_name: %s\n", stream_name); + av_log(ctx, AV_LOG_DEBUG, "audio_device_idnex: %i\n", ctx->audio_device_index); + av_log(ctx, AV_LOG_DEBUG, "UID: %s\n", CFStringGetCStringPtr(device_UID, kCFStringEncodingMacRoman)); + + // check input stream + if (avctx->nb_streams != 1 || avctx->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) { + av_log(ctx, AV_LOG_ERROR, "Only a single audio stream is supported.\n"); + return AVERROR(EINVAL); + } + + av_freep(&devices); + AVCodecParameters *codecpar = avctx->streams[0]->codecpar; + + // audio format + AudioStreamBasicDescription device_format = {0}; + device_format.mSampleRate = codecpar->sample_rate; + device_format.mFormatID = kAudioFormatLinearPCM; + device_format.mFormatFlags |= (codecpar->format == AV_SAMPLE_FMT_FLT) ? kLinearPCMFormatFlagIsFloat : 0; + device_format.mFormatFlags |= (codecpar->codec_id == AV_CODEC_ID_PCM_S8) ? kLinearPCMFormatFlagIsSignedInteger : 0; + device_format.mFormatFlags |= (codecpar->codec_id == AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE)) ? kLinearPCMFormatFlagIsSignedInteger : 0; + device_format.mFormatFlags |= (codecpar->codec_id == AV_NE(AV_CODEC_ID_PCM_S24BE, AV_CODEC_ID_PCM_S24LE)) ? kLinearPCMFormatFlagIsSignedInteger : 0; + device_format.mFormatFlags |= (codecpar->codec_id == AV_NE(AV_CODEC_ID_PCM_S32BE, AV_CODEC_ID_PCM_S32LE)) ? kLinearPCMFormatFlagIsSignedInteger : 0; + device_format.mFormatFlags |= (av_sample_fmt_is_planar(codecpar->format)) ? kAudioFormatFlagIsNonInterleaved : 0; + device_format.mFormatFlags |= (codecpar->codec_id == AV_CODEC_ID_PCM_F32BE) ? kAudioFormatFlagIsBigEndian : 0; + device_format.mFormatFlags |= (codecpar->codec_id == AV_CODEC_ID_PCM_S16BE) ? kAudioFormatFlagIsBigEndian : 0; + device_format.mFormatFlags |= (codecpar->codec_id == AV_CODEC_ID_PCM_S24BE) ? kAudioFormatFlagIsBigEndian : 0; + device_format.mFormatFlags |= (codecpar->codec_id == AV_CODEC_ID_PCM_S32BE) ? kAudioFormatFlagIsBigEndian : 0; + device_format.mChannelsPerFrame = codecpar->channels; + device_format.mBitsPerChannel = (codecpar->codec_id == AV_NE(AV_CODEC_ID_PCM_S24BE, AV_CODEC_ID_PCM_S24LE)) ? 24 : (av_get_bytes_per_sample(codecpar->format) << 3); + device_format.mBytesPerFrame = (device_format.mBitsPerChannel >> 3) * device_format.mChannelsPerFrame; + device_format.mFramesPerPacket = 1; + device_format.mBytesPerPacket = device_format.mBytesPerFrame * device_format.mFramesPerPacket; + device_format.mReserved = 0; + + av_log(ctx, AV_LOG_DEBUG, "device_format.mSampleRate = %i\n", codecpar->sample_rate); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFormatID = %s\n", "kAudioFormatLinearPCM"); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFormatFlags |= %s\n", (codecpar->format == AV_SAMPLE_FMT_FLT) ? "kLinearPCMFormatFlagIsFloat" : "0"); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFormatFlags |= %s\n", (codecpar->codec_id == AV_CODEC_ID_PCM_S8) ? "kLinearPCMFormatFlagIsSignedInteger" : "0"); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFormatFlags |= %s\n", (codecpar->codec_id == AV_NE(AV_CODEC_ID_PCM_S32BE, AV_CODEC_ID_PCM_S32LE)) ? "kLinearPCMFormatFlagIsSignedInteger" : "0"); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFormatFlags |= %s\n", (codecpar->codec_id == AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE)) ? "kLinearPCMFormatFlagIsSignedInteger" : "0"); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFormatFlags |= %s\n", (codecpar->codec_id == AV_NE(AV_CODEC_ID_PCM_S24BE, AV_CODEC_ID_PCM_S24LE)) ? "kLinearPCMFormatFlagIsSignedInteger" : "0"); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFormatFlags |= %s\n", (av_sample_fmt_is_planar(codecpar->format)) ? "kAudioFormatFlagIsNonInterleaved" : "0"); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFormatFlags |= %s\n", (codecpar->codec_id == AV_CODEC_ID_PCM_F32BE) ? "kAudioFormatFlagIsBigEndian" : "0"); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFormatFlags |= %s\n", (codecpar->codec_id == AV_CODEC_ID_PCM_S16BE) ? "kAudioFormatFlagIsBigEndian" : "0"); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFormatFlags |= %s\n", (codecpar->codec_id == AV_CODEC_ID_PCM_S24BE) ? "kAudioFormatFlagIsBigEndian" : "0"); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFormatFlags |= %s\n", (codecpar->codec_id == AV_CODEC_ID_PCM_S32BE) ? "kAudioFormatFlagIsBigEndian" : "0"); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFormatFlags == %i\n", device_format.mFormatFlags); + av_log(ctx, AV_LOG_DEBUG, "device_format.mChannelsPerFrame = %i\n", codecpar->channels); + av_log(ctx, AV_LOG_DEBUG, "device_format.mBitsPerChannel = %i\n", av_get_bytes_per_sample(codecpar->format) << 3); + av_log(ctx, AV_LOG_DEBUG, "device_format.mBytesPerFrame = %i\n", (device_format.mBitsPerChannel >> 3) * codecpar->channels); + av_log(ctx, AV_LOG_DEBUG, "device_format.mBytesPerPacket = %i\n", device_format.mBytesPerFrame); + av_log(ctx, AV_LOG_DEBUG, "device_format.mFramesPerPacket = %i\n", 1); + av_log(ctx, AV_LOG_DEBUG, "device_format.mReserved = %i\n", 0); + + // create new output queue for the device + err = AudioQueueNewOutput(&device_format, queue_callback, ctx, + NULL, kCFRunLoopCommonModes, + 0, &ctx->queue); + if (check_status(avctx, &err, "AudioQueueNewOutput")) { + if (err == kAudioFormatUnsupportedDataFormatError) + av_log(ctx, AV_LOG_ERROR, "Unsupported output format.\n"); + return AVERROR(EINVAL); + } + + // set user-defined device or leave untouched for default + if (device_UID != NULL) { + err = AudioQueueSetProperty(ctx->queue, kAudioQueueProperty_CurrentDevice, &device_UID, sizeof(device_UID)); + if (check_status(avctx, &err, "AudioQueueSetProperty output UID")) + return AVERROR(EINVAL); + } + + // start the queue + err = AudioQueueStart(ctx->queue, NULL); + if (check_status(avctx, &err, "AudioQueueStart")) + return AVERROR(EINVAL); + + // init the mutexes for double-buffering + pthread_mutex_init(&ctx->buffer_lock[0], NULL); + pthread_mutex_init(&ctx->buffer_lock[1], NULL); + + return 0; +} + +static int at_write_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + ATContext *ctx = (ATContext*)avctx->priv_data; + OSStatus err = noErr; + + // use the other buffer + ctx->cur_buf = !ctx->cur_buf; + + // lock for writing or wait for the buffer to be available + // will be unlocked by queue callback + pthread_mutex_lock(&ctx->buffer_lock[ctx->cur_buf]); + + // (re-)allocate the buffer if not existant or of different size + if (!ctx->buffer[ctx->cur_buf] || ctx->buffer[ctx->cur_buf]->mAudioDataBytesCapacity != pkt->size) { + err = AudioQueueAllocateBuffer(ctx->queue, pkt->size, &ctx->buffer[ctx->cur_buf]); + if (check_status(avctx, &err, "AudioQueueAllocateBuffer")) { + pthread_mutex_unlock(&ctx->buffer_lock[ctx->cur_buf]); + return AVERROR(ENOMEM); + } + } + + AudioQueueBufferRef buf = ctx->buffer[ctx->cur_buf]; + + // copy audio data into buffer and enqueue the buffer + memcpy(buf->mAudioData, pkt->data, buf->mAudioDataBytesCapacity); + buf->mAudioDataByteSize = buf->mAudioDataBytesCapacity; + err = AudioQueueEnqueueBuffer(ctx->queue, buf, 0, NULL); + if (check_status(avctx, &err, "AudioQueueEnqueueBuffer")) { + pthread_mutex_unlock(&ctx->buffer_lock[ctx->cur_buf]); + return AVERROR(EINVAL); + } + + return 0; +} + +static av_cold int at_write_trailer(AVFormatContext *avctx) +{ + ATContext *ctx = (ATContext*)avctx->priv_data; + OSStatus err = noErr; + + pthread_mutex_destroy(&ctx->buffer_lock[0]); + pthread_mutex_destroy(&ctx->buffer_lock[1]); + + err = AudioQueueFlush(ctx->queue); + check_status(avctx, &err, "AudioQueueFlush"); + err = AudioQueueDispose(ctx->queue, true); + check_status(avctx, &err, "AudioQueueDispose"); + + return 0; +} + +static const AVOption options[] = { + { "list_devices", "list available audio devices", offsetof(ATContext, list_devices), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, + { "audio_device_index", "select audio device by index (starts at 0)", offsetof(ATContext, audio_device_index), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, + { NULL }, +}; + +static const AVClass at_class = { + .class_name = "AudioToolbox", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, +}; + +AVOutputFormat ff_audiotoolbox_muxer = { + .name = "audiotoolbox", + .long_name = NULL_IF_CONFIG_SMALL("AudioToolbox output device"), + .priv_data_size = sizeof(ATContext), + .audio_codec = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), + .video_codec = AV_CODEC_ID_NONE, + .write_header = at_write_header, + .write_packet = at_write_packet, + .write_trailer = at_write_trailer, + .flags = AVFMT_NOFILE, + .priv_class = &at_class, +}; diff -Nru ffmpeg-4.2.2/libavdevice/avdevice.c ffmpeg-4.4/libavdevice/avdevice.c --- ffmpeg-4.2.2/libavdevice/avdevice.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/avdevice.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,39 +27,11 @@ #include "libavutil/ffversion.h" const char av_device_ffversion[] = "FFmpeg version " FFMPEG_VERSION; -#define E AV_OPT_FLAG_ENCODING_PARAM -#define D AV_OPT_FLAG_DECODING_PARAM -#define A AV_OPT_FLAG_AUDIO_PARAM -#define V AV_OPT_FLAG_VIDEO_PARAM -#define OFFSET(x) offsetof(AVDeviceCapabilitiesQuery, x) - +#if FF_API_DEVICE_CAPABILITIES const AVOption av_device_capabilities[] = { - { "codec", "codec", OFFSET(codec), AV_OPT_TYPE_INT, - {.i64 = AV_CODEC_ID_NONE}, AV_CODEC_ID_NONE, INT_MAX, E|D|A|V }, - { "sample_format", "sample format", OFFSET(sample_format), AV_OPT_TYPE_SAMPLE_FMT, - {.i64 = AV_SAMPLE_FMT_NONE}, AV_SAMPLE_FMT_NONE, INT_MAX, E|D|A }, - { "sample_rate", "sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, - {.i64 = -1}, -1, INT_MAX, E|D|A }, - { "channels", "channels", OFFSET(channels), AV_OPT_TYPE_INT, - {.i64 = -1}, -1, INT_MAX, E|D|A }, - { "channel_layout", "channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, - {.i64 = -1}, -1, INT_MAX, E|D|A }, - { "pixel_format", "pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT, - {.i64 = AV_PIX_FMT_NONE}, AV_PIX_FMT_NONE, INT_MAX, E|D|V }, - { "window_size", "window size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, - {.str = NULL}, -1, INT_MAX, E|D|V }, - { "frame_size", "frame size", OFFSET(frame_width), AV_OPT_TYPE_IMAGE_SIZE, - {.str = NULL}, -1, INT_MAX, E|D|V }, - { "fps", "fps", OFFSET(fps), AV_OPT_TYPE_RATIONAL, - {.dbl = -1}, -1, INT_MAX, E|D|V }, { NULL } }; - -#undef E -#undef D -#undef A -#undef V -#undef OFFSET +#endif unsigned avdevice_version(void) { @@ -75,53 +47,7 @@ const char * avdevice_license(void) { #define LICENSE_PREFIX "libavdevice license: " - return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; -} - -static void *device_next(void *prev, int output, - AVClassCategory c1, AVClassCategory c2) -{ - const AVClass *pc; - AVClassCategory category = AV_CLASS_CATEGORY_NA; - do { - if (output) { - if (!(prev = av_oformat_next(prev))) - break; - pc = ((AVOutputFormat *)prev)->priv_class; - } else { - if (!(prev = av_iformat_next(prev))) - break; - pc = ((AVInputFormat *)prev)->priv_class; - } - if (!pc) - continue; - category = pc->category; - } while (category != c1 && category != c2); - return prev; -} - -AVInputFormat *av_input_audio_device_next(AVInputFormat *d) -{ - return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, - AV_CLASS_CATEGORY_DEVICE_INPUT); -} - -AVInputFormat *av_input_video_device_next(AVInputFormat *d) -{ - return device_next(d, 0, AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, - AV_CLASS_CATEGORY_DEVICE_INPUT); -} - -AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d) -{ - return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, - AV_CLASS_CATEGORY_DEVICE_OUTPUT); -} - -AVOutputFormat *av_output_video_device_next(AVOutputFormat *d) -{ - return device_next(d, 1, AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT, - AV_CLASS_CATEGORY_DEVICE_OUTPUT); + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; } int avdevice_app_to_dev_control_message(struct AVFormatContext *s, enum AVAppToDevMessageType type, @@ -140,49 +66,18 @@ return s->control_message_cb(s, type, data, data_size); } +#if FF_API_DEVICE_CAPABILITIES int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s, AVDictionary **device_options) { - int ret; - av_assert0(s && caps); - av_assert0(s->iformat || s->oformat); - if ((s->oformat && !s->oformat->create_device_capabilities) || - (s->iformat && !s->iformat->create_device_capabilities)) - return AVERROR(ENOSYS); - *caps = av_mallocz(sizeof(**caps)); - if (!(*caps)) - return AVERROR(ENOMEM); - (*caps)->device_context = s; - if (((ret = av_opt_set_dict(s->priv_data, device_options)) < 0)) - goto fail; - if (s->iformat) { - if ((ret = s->iformat->create_device_capabilities(s, *caps)) < 0) - goto fail; - } else { - if ((ret = s->oformat->create_device_capabilities(s, *caps)) < 0) - goto fail; - } - av_opt_set_defaults(*caps); - return 0; - fail: - av_freep(caps); - return ret; + return AVERROR(ENOSYS); } void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s) { - if (!s || !caps || !(*caps)) - return; - av_assert0(s->iformat || s->oformat); - if (s->iformat) { - if (s->iformat->free_device_capabilities) - s->iformat->free_device_capabilities(s, *caps); - } else { - if (s->oformat->free_device_capabilities) - s->oformat->free_device_capabilities(s, *caps); - } - av_freep(caps); + return; } +#endif int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list) { diff -Nru ffmpeg-4.2.2/libavdevice/avdevice.h ffmpeg-4.4/libavdevice/avdevice.h --- ffmpeg-4.2.2/libavdevice/avdevice.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavdevice/avdevice.h 2021-04-08 21:28:39.000000000 +0000 @@ -321,6 +321,7 @@ enum AVDevToAppMessageType type, void *data, size_t data_size); +#if FF_API_DEVICE_CAPABILITIES /** * Following API allows user to probe device capabilities (supported codecs, * pixel formats, sample formats, resolutions, channel counts, etc). @@ -416,6 +417,7 @@ /** * AVOption table used by devices to implement device capabilities API. Should not be used by a user. */ +attribute_deprecated extern const AVOption av_device_capabilities[]; /** @@ -435,6 +437,7 @@ * * @return >= 0 on success, negative otherwise. */ +attribute_deprecated int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s, AVDictionary **device_options); @@ -444,7 +447,9 @@ * @param caps Device capabilities data to be freed. * @param s Context of the device. */ +attribute_deprecated void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s); +#endif /** * Structure describes basic parameters of the device. diff -Nru ffmpeg-4.2.2/libavdevice/avfoundation.m ffmpeg-4.4/libavdevice/avfoundation.m --- ffmpeg-4.2.2/libavdevice/avfoundation.m 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/avfoundation.m 2020-07-11 10:39:30.000000000 +0000 @@ -88,7 +88,6 @@ int64_t first_pts; int64_t first_audio_pts; pthread_mutex_t frame_lock; - pthread_cond_t frame_wait_cond; id avf_delegate; id avf_audio_delegate; @@ -98,7 +97,9 @@ int capture_cursor; int capture_mouse_clicks; int capture_raw_data; + int drop_late_frames; int video_is_muxed; + int video_is_screen; int list_devices; int video_device_index; @@ -129,6 +130,12 @@ AVCaptureAudioDataOutput *audio_output; CMSampleBufferRef current_frame; CMSampleBufferRef current_audio_frame; + + AVCaptureDevice *observed_device; +#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 + AVCaptureDeviceTransportControlsPlaybackMode observed_mode; +#endif + int observed_quit; } AVFContext; static void lock_frames(AVFContext* ctx) @@ -162,10 +169,58 @@ { if (self = [super init]) { _context = context; + + // start observing if a device is set for it +#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 + if (_context->observed_device) { + NSString *keyPath = NSStringFromSelector(@selector(transportControlsPlaybackMode)); + NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew; + + [_context->observed_device addObserver: self + forKeyPath: keyPath + options: options + context: _context]; + } +#endif } return self; } +- (void)dealloc { + // stop observing if a device is set for it +#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 + if (_context->observed_device) { + NSString *keyPath = NSStringFromSelector(@selector(transportControlsPlaybackMode)); + [_context->observed_device removeObserver: self forKeyPath: keyPath]; + } +#endif + [super dealloc]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if (context == _context) { +#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 + AVCaptureDeviceTransportControlsPlaybackMode mode = + [change[NSKeyValueChangeNewKey] integerValue]; + + if (mode != _context->observed_mode) { + if (mode == AVCaptureDeviceTransportControlsNotPlayingMode) { + _context->observed_quit = 1; + } + _context->observed_mode = mode; + } +#endif + } else { + [super observeValueForKeyPath: keyPath + ofObject: object + change: change + context: context]; + } +} + - (void) captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)videoFrame fromConnection:(AVCaptureConnection *)connection @@ -178,8 +233,6 @@ _context->current_frame = (CMSampleBufferRef)CFRetain(videoFrame); - pthread_cond_signal(&_context->frame_wait_cond); - unlock_frames(_context); ++_context->frames_captured; @@ -224,8 +277,6 @@ _context->current_audio_frame = (CMSampleBufferRef)CFRetain(audioFrame); - pthread_cond_signal(&_context->frame_wait_cond); - unlock_frames(_context); ++_context->audio_frames_captured; @@ -252,7 +303,6 @@ av_freep(&ctx->audio_buffer); pthread_mutex_destroy(&ctx->frame_lock); - pthread_cond_destroy(&ctx->frame_wait_cond); if (ctx->current_frame) { CFRelease(ctx->current_frame); @@ -496,7 +546,20 @@ [ctx->video_output setVideoSettings:capture_dict]; } - [ctx->video_output setAlwaysDiscardsLateVideoFrames:YES]; + [ctx->video_output setAlwaysDiscardsLateVideoFrames:ctx->drop_late_frames]; + +#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 + // check for transport control support and set observer device if supported + if (!ctx->video_is_screen) { + int trans_ctrl = [video_device transportControlsSupported]; + AVCaptureDeviceTransportControlsPlaybackMode trans_mode = [video_device transportControlsPlaybackMode]; + + if (trans_ctrl) { + ctx->observed_mode = trans_mode; + ctx->observed_device = video_device; + } + } +#endif ctx->avf_delegate = [[AVFFrameReceiver alloc] initWithContext:ctx]; @@ -694,7 +757,6 @@ static int avf_read_header(AVFormatContext *s) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - int capture_screen = 0; uint32_t num_screens = 0; AVFContext *ctx = (AVFContext*)s->priv_data; AVCaptureDevice *video_device = nil; @@ -708,7 +770,6 @@ ctx->first_audio_pts = av_gettime(); pthread_mutex_init(&ctx->frame_lock, NULL); - pthread_cond_init(&ctx->frame_wait_cond, NULL); #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 CGGetActiveDisplayList(0, NULL, &num_screens); @@ -792,7 +853,7 @@ } video_device = (AVCaptureDevice*) capture_screen_input; - capture_screen = 1; + ctx->video_is_screen = 1; #endif } else { av_log(ctx, AV_LOG_ERROR, "Invalid device index\n"); @@ -829,7 +890,7 @@ AVCaptureScreenInput* capture_screen_input = [[[AVCaptureScreenInput alloc] initWithDisplayID:screens[idx]] autorelease]; video_device = (AVCaptureDevice*) capture_screen_input; ctx->video_device_index = ctx->num_video_devices + idx; - capture_screen = 1; + ctx->video_is_screen = 1; if (ctx->framerate.num > 0) { capture_screen_input.minFrameDuration = CMTimeMake(ctx->framerate.den, ctx->framerate.num); @@ -920,7 +981,7 @@ /* Unlock device configuration only after the session is started so it * does not reset the capture formats */ - if (!capture_screen) { + if (!ctx->video_is_screen) { [video_device unlockForConfiguration]; } @@ -1109,7 +1170,12 @@ ctx->current_audio_frame = nil; } else { pkt->data = NULL; - pthread_cond_wait(&ctx->frame_wait_cond, &ctx->frame_lock); + unlock_frames(ctx); + if (ctx->observed_quit) { + return AVERROR_EOF; + } else { + return AVERROR(EAGAIN); + } } unlock_frames(ctx); @@ -1135,12 +1201,13 @@ { "capture_cursor", "capture the screen cursor", offsetof(AVFContext, capture_cursor), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, { "capture_mouse_clicks", "capture the screen mouse clicks", offsetof(AVFContext, capture_mouse_clicks), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, { "capture_raw_data", "capture the raw data from device connection", offsetof(AVFContext, capture_raw_data), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, + { "drop_late_frames", "drop frames that are available later than expected", offsetof(AVFContext, drop_late_frames), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, { NULL }, }; static const AVClass avf_class = { - .class_name = "AVFoundation input device", + .class_name = "AVFoundation indev", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, diff -Nru ffmpeg-4.2.2/libavdevice/bktr.c ffmpeg-4.4/libavdevice/bktr.c --- ffmpeg-4.2.2/libavdevice/bktr.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/bktr.c 2021-04-08 21:28:39.000000000 +0000 @@ -225,14 +225,14 @@ { uint64_t curtime; - curtime = av_gettime(); + curtime = av_gettime_relative(); if (!last_frame_time || ((last_frame_time + per_frame) > curtime)) { if (!usleep(last_frame_time + per_frame + per_frame / 8 - curtime)) { if (!nsignals) av_log(NULL, AV_LOG_INFO, "SLEPT NO signals - %d microseconds late\n", - (int)(av_gettime() - last_frame_time - per_frame)); + (int)(av_gettime_relative() - last_frame_time - per_frame)); } } nsignals = 0; @@ -341,7 +341,7 @@ }; static const AVClass bktr_class = { - .class_name = "BKTR grab interface", + .class_name = "BKTR grab indev", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, diff -Nru ffmpeg-4.2.2/libavdevice/caca.c ffmpeg-4.4/libavdevice/caca.c --- ffmpeg-4.2.2/libavdevice/caca.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/caca.c 2021-04-08 21:28:39.000000000 +0000 @@ -180,7 +180,7 @@ if (!c->window_title) c->window_title = av_strdup(s->url); caca_set_display_title(c->display, c->window_title); - caca_set_display_time(c->display, av_rescale_q(1, st->codec->time_base, AV_TIME_BASE_Q)); + caca_set_display_time(c->display, av_rescale_q(1, st->time_base, AV_TIME_BASE_Q)); return 0; @@ -220,7 +220,7 @@ }; static const AVClass caca_class = { - .class_name = "caca_outdev", + .class_name = "caca outdev", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, diff -Nru ffmpeg-4.2.2/libavdevice/decklink_common_c.h ffmpeg-4.4/libavdevice/decklink_common_c.h --- ffmpeg-4.2.2/libavdevice/decklink_common_c.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/decklink_common_c.h 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,8 @@ #ifndef AVDEVICE_DECKLINK_COMMON_C_H #define AVDEVICE_DECKLINK_COMMON_C_H +#include + typedef enum DecklinkPtsSource { PTS_SRC_AUDIO = 1, PTS_SRC_VIDEO = 2, @@ -40,9 +42,9 @@ /* Options */ int list_devices; int list_formats; + int enable_klv; int64_t teletext_lines; double preroll; - int v210; int audio_channels; int audio_depth; int duplex_mode; @@ -58,6 +60,7 @@ int copyts; int64_t timestamp_align; int timing_offset; + int wait_for_tc; }; #endif /* AVDEVICE_DECKLINK_COMMON_C_H */ diff -Nru ffmpeg-4.2.2/libavdevice/decklink_common.cpp ffmpeg-4.4/libavdevice/decklink_common.cpp --- ffmpeg-4.2.2/libavdevice/decklink_common.cpp 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/decklink_common.cpp 2021-04-08 21:28:39.000000000 +0000 @@ -70,9 +70,30 @@ #else iter = CreateDeckLinkIteratorInstance(); #endif - if (!iter) + if (!iter) { av_log(avctx, AV_LOG_ERROR, "Could not create DeckLink iterator. " "Make sure you have DeckLink drivers " BLACKMAGIC_DECKLINK_API_VERSION_STRING " or newer installed.\n"); + } else { + IDeckLinkAPIInformation *api; + int64_t version; +#ifdef _WIN32 + if (CoCreateInstance(CLSID_CDeckLinkAPIInformation, NULL, CLSCTX_ALL, + IID_IDeckLinkAPIInformation, (void**) &api) != S_OK) { + api = NULL; + } +#else + api = CreateDeckLinkAPIInformationInstance(); +#endif + if (api && api->GetInt(BMDDeckLinkAPIVersion, &version) == S_OK) { + if (version < BLACKMAGIC_DECKLINK_API_VERSION) + av_log(avctx, AV_LOG_WARNING, "Installed DeckLink drivers are too old and may be incompatible with the SDK this module was built against. " + "Make sure you have DeckLink drivers " BLACKMAGIC_DECKLINK_API_VERSION_STRING " or newer installed.\n"); + } else { + av_log(avctx, AV_LOG_ERROR, "Failed to check installed DeckLink API version.\n"); + } + if (api) + api->Release(); + } return iter; } @@ -200,7 +221,7 @@ int width, int height, int tb_num, int tb_den, enum AVFieldOrder field_order, - decklink_direction_t direction, int num) + decklink_direction_t direction) { struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; @@ -214,8 +235,8 @@ int i = 1; HRESULT res; - av_log(avctx, AV_LOG_DEBUG, "Trying to find mode for frame size %dx%d, frame timing %d/%d, field order %d, direction %d, mode number %d, format code %s\n", - width, height, tb_num, tb_den, field_order, direction, num, (cctx->format_code) ? cctx->format_code : "(unset)"); + av_log(avctx, AV_LOG_DEBUG, "Trying to find mode for frame size %dx%d, frame timing %d/%d, field order %d, direction %d, format code %s\n", + width, height, tb_num, tb_den, field_order, direction, cctx->format_code ? cctx->format_code : "(unset)"); if (direction == DIRECTION_IN) { res = ctx->dli->GetDisplayModeIterator (&itermode); @@ -248,7 +269,6 @@ bmd_height == height && !av_cmp_q(mode_tb, target_tb) && field_order_eq(field_order, bmd_field_dominance)) - || i == num || target_mode == bmd_mode) { ctx->bmd_mode = bmd_mode; ctx->bmd_width = bmd_width; @@ -270,9 +290,24 @@ if (ctx->bmd_mode == bmdModeUnknown) return -1; -#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000 +#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b050000 + if (direction == DIRECTION_IN) { + BMDDisplayMode actualMode = ctx->bmd_mode; + if (ctx->dli->DoesSupportVideoMode(ctx->video_input, ctx->bmd_mode, ctx->raw_format, + bmdNoVideoInputConversion, bmdSupportedVideoModeDefault, + &actualMode, &support) != S_OK || !support || ctx->bmd_mode != actualMode) + return -1; + } else { + BMDDisplayMode actualMode = ctx->bmd_mode; + if (ctx->dlo->DoesSupportVideoMode(bmdVideoConnectionUnspecified, ctx->bmd_mode, ctx->raw_format, + bmdNoVideoOutputConversion, bmdSupportedVideoModeDefault, + &actualMode, &support) != S_OK || !support || ctx->bmd_mode != actualMode) + return -1; + } + return 0; +#elif BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000 if (direction == DIRECTION_IN) { - if (ctx->dli->DoesSupportVideoMode(ctx->video_input, ctx->bmd_mode, (BMDPixelFormat) cctx->raw_format, + if (ctx->dli->DoesSupportVideoMode(ctx->video_input, ctx->bmd_mode, ctx->raw_format, bmdSupportedVideoModeDefault, &support) != S_OK) return -1; @@ -289,7 +324,7 @@ return 0; #else if (direction == DIRECTION_IN) { - if (ctx->dli->DoesSupportVideoMode(ctx->bmd_mode, (BMDPixelFormat) cctx->raw_format, + if (ctx->dli->DoesSupportVideoMode(ctx->bmd_mode, ctx->raw_format, bmdVideoOutputFlagDefault, &support, NULL) != S_OK) return -1; @@ -314,8 +349,8 @@ return -1; } -int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction, int num) { - return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction, num); +int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction) { + return ff_decklink_set_format(avctx, 0, 0, 0, 0, AV_FIELD_UNKNOWN, direction); } int ff_decklink_list_devices(AVFormatContext *avctx, diff -Nru ffmpeg-4.2.2/libavdevice/decklink_common.h ffmpeg-4.4/libavdevice/decklink_common.h --- ffmpeg-4.2.2/libavdevice/decklink_common.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/decklink_common.h 2021-04-08 21:28:39.000000000 +0000 @@ -75,7 +75,7 @@ class decklink_input_callback; typedef struct AVPacketQueue { - AVPacketList *first_pkt, *last_pkt; + PacketList *first_pkt, *last_pkt; int nb_packets; unsigned long long size; int abort_request; @@ -115,18 +115,19 @@ /* Status */ int playback_started; - int capture_started; int64_t last_pts; unsigned long frameCount; unsigned int dropped; AVStream *audio_st; AVStream *video_st; + AVStream *klv_st; AVStream *teletext_st; uint16_t cdp_sequence_num; /* Options */ int list_devices; int list_formats; + int enable_klv; int64_t teletext_lines; double preroll; int duplex_mode; @@ -149,20 +150,19 @@ int channels; int audio_depth; + unsigned long tc_seen; // used with option wait_for_tc }; typedef enum { DIRECTION_IN, DIRECTION_OUT} decklink_direction_t; -#ifdef _WIN32 -#if BLACKMAGIC_DECKLINK_API_VERSION < 0x0a040000 -typedef unsigned long buffercount_type; -#else -typedef unsigned int buffercount_type; -#endif -IDeckLinkIterator *CreateDeckLinkIteratorInstance(void); -#else -typedef uint32_t buffercount_type; -#endif +static const BMDPixelFormat decklink_raw_format_map[] = { + (BMDPixelFormat)0, + bmdFormat8BitYUV, + bmdFormat10BitYUV, + bmdFormat8BitARGB, + bmdFormat8BitBGRA, + bmdFormat10BitRGB, +}; static const BMDAudioConnection decklink_audio_connection_map[] = { (BMDAudioConnection)0, @@ -193,11 +193,16 @@ bmdTimecodeVITC, bmdTimecodeVITCField2, bmdTimecodeSerial, +#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000 + bmdTimecodeRP188HighFrameRate, +#else + (BMDTimecodeFormat)0, +#endif }; int ff_decklink_set_configs(AVFormatContext *avctx, decklink_direction_t direction); -int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, enum AVFieldOrder field_order, decklink_direction_t direction = DIRECTION_OUT, int num = 0); -int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction, int num); +int ff_decklink_set_format(AVFormatContext *avctx, int width, int height, int tb_num, int tb_den, enum AVFieldOrder field_order, decklink_direction_t direction = DIRECTION_OUT); +int ff_decklink_set_format(AVFormatContext *avctx, decklink_direction_t direction); int ff_decklink_list_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list, int show_inputs, int show_outputs); void ff_decklink_list_devices_legacy(AVFormatContext *avctx, int show_inputs, int show_outputs); int ff_decklink_list_formats(AVFormatContext *avctx, decklink_direction_t direction = DIRECTION_OUT); diff -Nru ffmpeg-4.2.2/libavdevice/decklink_dec_c.c ffmpeg-4.4/libavdevice/decklink_dec_c.c --- ffmpeg-4.2.2/libavdevice/decklink_dec_c.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/decklink_dec_c.c 2021-04-08 21:28:39.000000000 +0000 @@ -30,16 +30,17 @@ #define DEC AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { - { "list_devices", "list available devices" , OFFSET(list_devices), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 1, DEC }, + { "list_devices", "use ffmpeg -sources decklink instead", OFFSET(list_devices), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC | AV_OPT_FLAG_DEPRECATED}, { "list_formats", "list supported formats" , OFFSET(list_formats), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 1, DEC }, { "format_code", "set format by fourcc" , OFFSET(format_code), AV_OPT_TYPE_STRING, { .str = NULL}, 0, 0, DEC }, - { "bm_v210", "v210 10 bit per channel" , OFFSET(v210), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 1, DEC }, - { "raw_format", "pixel format to be returned by the card when capturing" , OFFSET(raw_format), AV_OPT_TYPE_INT, { .i64 = MKBETAG('2','v','u','y')}, 0, UINT_MAX, DEC, "raw_format" }, - { "uyvy422", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MKBETAG('2','v','u','y') }, 0, 0, DEC, "raw_format"}, - { "yuv422p10", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MKBETAG('v','2','1','0') }, 0, 0, DEC, "raw_format"}, - { "argb", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 32 }, 0, 0, DEC, "raw_format"}, - { "bgra", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MKBETAG('B','G','R','A') }, 0, 0, DEC, "raw_format"}, - { "rgb10", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MKBETAG('r','2','1','0') }, 0, 0, DEC, "raw_format"}, + { "raw_format", "pixel format to be returned by the card when capturing" , OFFSET(raw_format), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 5, DEC, "raw_format" }, + { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, DEC, "raw_format"}, + { "uyvy422", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, DEC, "raw_format"}, + { "yuv422p10", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, DEC, "raw_format"}, + { "argb", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, 0, 0, DEC, "raw_format"}, + { "bgra", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 4 }, 0, 0, DEC, "raw_format"}, + { "rgb10", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 5 }, 0, 0, DEC, "raw_format"}, + { "enable_klv", "output klv if present in vanc", OFFSET(enable_klv), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC }, { "teletext_lines", "teletext lines bitmask", OFFSET(teletext_lines), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, 0x7ffffffffLL, DEC, "teletext_lines"}, { "standard", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0x7fff9fffeLL}, 0, 0, DEC, "teletext_lines"}, { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0x7ffffffffLL}, 0, 0, DEC, "teletext_lines"}, @@ -48,7 +49,7 @@ { "unset", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0}, 0, 0, DEC, "duplex_mode"}, { "half", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0, DEC, "duplex_mode"}, { "full", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2}, 0, 0, DEC, "duplex_mode"}, - { "timecode_format", "timecode format", OFFSET(tc_format), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 7, DEC, "tc_format"}, + { "timecode_format", "timecode format", OFFSET(tc_format), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 8, DEC, "tc_format"}, { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0}, 0, 0, DEC, "tc_format"}, { "rp188vitc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0, DEC, "tc_format"}, { "rp188vitc2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2}, 0, 0, DEC, "tc_format"}, @@ -57,6 +58,9 @@ { "vitc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 5}, 0, 0, DEC, "tc_format"}, { "vitc2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 6}, 0, 0, DEC, "tc_format"}, { "serial", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 7}, 0, 0, DEC, "tc_format"}, +#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000 + { "rp188hfr", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 8}, 0, 0, DEC, "tc_format"}, +#endif { "video_input", "video input", OFFSET(video_input), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 6, DEC, "video_input"}, { "unset", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0}, 0, 0, DEC, "video_input"}, { "sdi", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0, DEC, "video_input"}, @@ -85,11 +89,12 @@ { "audio_depth", "audio bitdepth (16 or 32)", OFFSET(audio_depth), AV_OPT_TYPE_INT, { .i64 = 16}, 16, 32, DEC }, { "decklink_copyts", "copy timestamps, do not remove the initial offset", OFFSET(copyts), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC }, { "timestamp_align", "capture start time alignment (in seconds)", OFFSET(timestamp_align), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, DEC }, + { "wait_for_tc", "drop frames till a frame with timecode is received. TC format must be set", OFFSET(wait_for_tc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC }, { NULL }, }; static const AVClass decklink_demuxer_class = { - .class_name = "Blackmagic DeckLink demuxer", + .class_name = "Blackmagic DeckLink indev", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, diff -Nru ffmpeg-4.2.2/libavdevice/decklink_dec.cpp ffmpeg-4.4/libavdevice/decklink_dec.cpp --- ffmpeg-4.2.2/libavdevice/decklink_dec.cpp 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/decklink_dec.cpp 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ */ #include +#include using std::atomic; /* Include internal.h first to avoid conflict between winsock.h (used by @@ -34,13 +35,16 @@ extern "C" { #include "config.h" +#include "libavcodec/packet_internal.h" #include "libavformat/avformat.h" #include "libavutil/avassert.h" #include "libavutil/avutil.h" #include "libavutil/common.h" +#include "libavutil/internal.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "libavutil/time.h" +#include "libavutil/timecode.h" #include "libavutil/mathematics.h" #include "libavutil/reverse.h" #include "avdevice.h" @@ -479,7 +483,7 @@ static void avpacket_queue_flush(AVPacketQueue *q) { - AVPacketList *pkt, *pkt1; + PacketList *pkt, *pkt1; pthread_mutex_lock(&q->mutex); for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) { @@ -512,7 +516,7 @@ static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) { - AVPacketList *pkt1; + PacketList *pkt1; // Drop Packet if queue size is > maximum queue size if (avpacket_queue_size(q) > (uint64_t)q->max_q_size) { @@ -526,7 +530,7 @@ return -1; } - pkt1 = (AVPacketList *)av_malloc(sizeof(AVPacketList)); + pkt1 = (PacketList *)av_malloc(sizeof(PacketList)); if (!pkt1) { av_packet_unref(pkt); return -1; @@ -554,7 +558,7 @@ static int avpacket_queue_get(AVPacketQueue *q, AVPacket *pkt, int block) { - AVPacketList *pkt1; + PacketList *pkt1; int ret; pthread_mutex_lock(&q->mutex); @@ -583,6 +587,108 @@ return ret; } +static void handle_klv(AVFormatContext *avctx, decklink_ctx *ctx, IDeckLinkVideoInputFrame *videoFrame, int64_t pts) +{ + const uint8_t KLV_DID = 0x44; + const uint8_t KLV_IN_VANC_SDID = 0x04; + + struct KLVPacket + { + uint16_t sequence_counter; + std::vector data; + }; + + size_t total_size = 0; + std::vector> klv_packets(256); + + IDeckLinkVideoFrameAncillaryPackets *packets = nullptr; + if (videoFrame->QueryInterface(IID_IDeckLinkVideoFrameAncillaryPackets, (void**)&packets) != S_OK) + return; + + IDeckLinkAncillaryPacketIterator *it = nullptr; + if (packets->GetPacketIterator(&it) != S_OK) { + packets->Release(); + return; + } + + IDeckLinkAncillaryPacket *packet = nullptr; + while (it->Next(&packet) == S_OK) { + uint8_t *data = nullptr; + uint32_t size = 0; + + if (packet->GetDID() == KLV_DID && packet->GetSDID() == KLV_IN_VANC_SDID) { + av_log(avctx, AV_LOG_DEBUG, "Found KLV VANC packet on line: %d\n", packet->GetLineNumber()); + + if (packet->GetBytes(bmdAncillaryPacketFormatUInt8, (const void**) &data, &size) == S_OK) { + // MID and PSC + if (size > 3) { + uint8_t mid = data[0]; + uint16_t psc = data[1] << 8 | data[2]; + + av_log(avctx, AV_LOG_DEBUG, "KLV with MID: %d and PSC: %d\n", mid, psc); + + auto& list = klv_packets[mid]; + uint16_t expected_psc = list.size() + 1; + + if (psc == expected_psc) { + uint32_t data_len = size - 3; + total_size += data_len; + + KLVPacket packet{ psc }; + packet.data.resize(data_len); + memcpy(packet.data.data(), data + 3, data_len); + + list.push_back(std::move(packet)); + } else { + av_log(avctx, AV_LOG_WARNING, "Out of order PSC: %d for MID: %d\n", psc, mid); + + if (!list.empty()) { + for (auto& klv : list) + total_size -= klv.data.size(); + + list.clear(); + } + } + } + } + } + + packet->Release(); + } + + it->Release(); + packets->Release(); + + if (total_size > 0) { + std::vector klv; + klv.reserve(total_size); + + for (size_t i = 0; i < klv_packets.size(); ++i) { + auto& list = klv_packets[i]; + + if (list.empty()) + continue; + + av_log(avctx, AV_LOG_DEBUG, "Joining MID: %d\n", (int)i); + + for (auto& packet : list) + klv.insert(klv.end(), packet.data.begin(), packet.data.end()); + } + + AVPacket klv_packet = { 0 }; + klv_packet.pts = pts; + klv_packet.dts = pts; + klv_packet.flags |= AV_PKT_FLAG_KEY; + klv_packet.stream_index = ctx->klv_st->index; + klv_packet.data = klv.data(); + klv_packet.size = klv.size(); + + if (avpacket_queue_put(&ctx->queue, &klv_packet) < 0) { + ++ctx->dropped; + } + } +} + class decklink_input_callback : public IDeckLinkInputCallback { public: @@ -684,6 +790,52 @@ return pts; } +static int get_bmd_timecode(AVFormatContext *avctx, AVTimecode *tc, AVRational frame_rate, BMDTimecodeFormat tc_format, IDeckLinkVideoInputFrame *videoFrame) +{ + IDeckLinkTimecode *timecode; + int ret = AVERROR(ENOENT); +#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000 + int hfr = (tc_format == bmdTimecodeRP188HighFrameRate); +#else + int hfr = 0; +#endif + if (videoFrame->GetTimecode(tc_format, &timecode) == S_OK) { + uint8_t hh, mm, ss, ff; + if (timecode->GetComponents(&hh, &mm, &ss, &ff) == S_OK) { + int flags = (timecode->GetFlags() & bmdTimecodeIsDropFrame) ? AV_TIMECODE_FLAG_DROPFRAME : 0; + if (!hfr && av_cmp_q(frame_rate, av_make_q(30, 1)) == 1) + ff = ff << 1 | !!(timecode->GetFlags() & bmdTimecodeFieldMark); + ret = av_timecode_init_from_components(tc, frame_rate, flags, hh, mm, ss, ff, avctx); + } + timecode->Release(); + } + return ret; +} + +static int get_frame_timecode(AVFormatContext *avctx, decklink_ctx *ctx, AVTimecode *tc, IDeckLinkVideoInputFrame *videoFrame) +{ + AVRational frame_rate = ctx->video_st->r_frame_rate; + int ret; + /* 50/60 fps content has alternating VITC1 and VITC2 timecode (see SMPTE ST + * 12-2, section 7), so the native ordering of RP188Any (HFR, VITC1, LTC, + * VITC2) would not work because LTC might not contain the field flag. + * Therefore we query the types manually. */ + if (ctx->tc_format == bmdTimecodeRP188Any && av_cmp_q(frame_rate, av_make_q(30, 1)) == 1) { +#if BLACKMAGIC_DECKLINK_API_VERSION >= 0x0b000000 + ret = get_bmd_timecode(avctx, tc, frame_rate, bmdTimecodeRP188HighFrameRate, videoFrame); + if (ret == AVERROR(ENOENT)) +#endif + ret = get_bmd_timecode(avctx, tc, frame_rate, bmdTimecodeRP188VITC1, videoFrame); + if (ret == AVERROR(ENOENT)) + ret = get_bmd_timecode(avctx, tc, frame_rate, bmdTimecodeRP188VITC2, videoFrame); + if (ret == AVERROR(ENOENT)) + ret = get_bmd_timecode(avctx, tc, frame_rate, bmdTimecodeRP188LTC, videoFrame); + } else { + ret = get_bmd_timecode(avctx, tc, frame_rate, ctx->tc_format, videoFrame); + } + return ret; +} + HRESULT decklink_input_callback::VideoInputFrameArrived( IDeckLinkVideoInputFrame *videoFrame, IDeckLinkAudioInputPacket *audioFrame) { @@ -721,8 +873,7 @@ // Handle Video Frame if (videoFrame) { - AVPacket pkt; - av_init_packet(&pkt); + AVPacket pkt = { 0 }; if (ctx->frameCount % 25 == 0) { unsigned long long qsize = avpacket_queue_size(&ctx->queue); av_log(avctx, AV_LOG_DEBUG, @@ -765,25 +916,34 @@ // Handle Timecode (if requested) if (ctx->tc_format) { - IDeckLinkTimecode *timecode; - if (videoFrame->GetTimecode(ctx->tc_format, &timecode) == S_OK) { - const char *tc = NULL; - DECKLINK_STR decklink_tc; - if (timecode->GetString(&decklink_tc) == S_OK) { - tc = DECKLINK_STRDUP(decklink_tc); - DECKLINK_FREE(decklink_tc); - } - timecode->Release(); + AVTimecode tcr; + if (get_frame_timecode(avctx, ctx, &tcr, videoFrame) >= 0) { + char tcstr[AV_TIMECODE_STR_SIZE]; + const char *tc = av_timecode_make_string(&tcr, tcstr, 0); if (tc) { AVDictionary* metadata_dict = NULL; - int metadata_len; uint8_t* packed_metadata; - if (av_dict_set(&metadata_dict, "timecode", tc, AV_DICT_DONT_STRDUP_VAL) >= 0) { + + if (av_cmp_q(ctx->video_st->r_frame_rate, av_make_q(60, 1)) < 1) { + uint32_t tc_data = av_timecode_get_smpte_from_framenum(&tcr, 0); + int size = sizeof(uint32_t) * 4; + uint32_t *sd = (uint32_t *)av_packet_new_side_data(&pkt, AV_PKT_DATA_S12M_TIMECODE, size); + + if (sd) { + *sd = 1; // one TC + *(sd + 1) = tc_data; // TC + } + } + + if (av_dict_set(&metadata_dict, "timecode", tc, 0) >= 0) { + buffer_size_t metadata_len; packed_metadata = av_packet_pack_dictionary(metadata_dict, &metadata_len); av_dict_free(&metadata_dict); if (packed_metadata) { if (av_packet_add_side_data(&pkt, AV_PKT_DATA_STRINGS_METADATA, packed_metadata, metadata_len) < 0) av_freep(&packed_metadata); + else if (!ctx->tc_seen) + ctx->tc_seen = ctx->frameCount; } } } @@ -793,6 +953,14 @@ } } + if (ctx->tc_format && cctx->wait_for_tc && !ctx->tc_seen) { + + av_log(avctx, AV_LOG_WARNING, "No TC detected yet. wait_for_tc set. Dropping. \n"); + av_log(avctx, AV_LOG_WARNING, "Frame received (#%lu) - " + "- Frames dropped %u\n", ctx->frameCount, ++ctx->dropped); + return S_OK; + } + pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, abs_wallclock, ctx->video_pts_source, ctx->video_st->time_base, &initial_video_pts, cctx->copyts); pkt.dts = pkt.pts; @@ -807,19 +975,23 @@ if (!no_video) { IDeckLinkVideoFrameAncillary *vanc; - AVPacket txt_pkt; + AVPacket txt_pkt = { 0 }; uint8_t txt_buf0[3531]; // 35 * 46 bytes decoded teletext lines + 1 byte data_identifier + 1920 bytes OP47 decode buffer uint8_t *txt_buf = txt_buf0; + if (ctx->enable_klv) { + handle_klv(avctx, ctx, videoFrame, pkt.pts); + } + if (videoFrame->GetAncillaryData(&vanc) == S_OK) { int i; - int64_t line_mask = 1; BMDPixelFormat vanc_format = vanc->GetPixelFormat(); txt_buf[0] = 0x10; // data_identifier - EBU_data txt_buf++; #if CONFIG_LIBZVBI if (ctx->bmd_mode == bmdModePAL && ctx->teletext_lines && (vanc_format == bmdFormat8BitYUV || vanc_format == bmdFormat10BitYUV)) { + int64_t line_mask = 1; av_assert0(videoFrame->GetWidth() == 720); for (i = 6; i < 336; i++, line_mask <<= 1) { uint8_t *buf; @@ -862,7 +1034,6 @@ txt_buf[1] = 0x2c; // data_unit_length txt_buf += 46; } - av_init_packet(&txt_pkt); txt_pkt.pts = pkt.pts; txt_pkt.dts = pkt.dts; txt_pkt.stream_index = ctx->teletext_st->index; @@ -886,9 +1057,8 @@ // Handle Audio Frame if (audioFrame) { - AVPacket pkt; + AVPacket pkt = { 0 }; BMDTimeValue audio_pts; - av_init_packet(&pkt); //hack among hacks pkt.size = audioFrame->GetSampleFrameCount() * ctx->audio_st->codecpar->channels * (ctx->audio_depth / 8); @@ -912,9 +1082,13 @@ HRESULT decklink_input_callback::VideoInputFormatChanged( BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode, - BMDDetectedVideoInputFormatFlags) + BMDDetectedVideoInputFormatFlags formatFlags) { + struct decklink_cctx *cctx = (struct decklink_cctx *) avctx->priv_data; ctx->bmd_mode = mode->GetDisplayMode(); + // check the C context member to make sure we set both raw_format and bmd_mode with data from the same format change callback + if (!cctx->raw_format) + ctx->raw_format = (formatFlags & bmdDetectedVideoInputRGB444) ? bmdFormat8BitARGB : bmdFormat8BitYUV; return S_OK; } @@ -940,8 +1114,8 @@ return -1; } - // 1 second timeout - for (i = 0; i < 10; i++) { + // 3 second timeout + for (i = 0; i < 30; i++) { av_usleep(100000); /* Sometimes VideoInputFrameArrived is called without the * bmdFrameHasNoInputSource flag before VideoInputFormatChanged. @@ -973,7 +1147,7 @@ struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; - if (ctx->capture_started) { + if (ctx->dli) { ctx->dli->StopStreams(); ctx->dli->DisableVideoInput(); ctx->dli->DisableAudioInput(); @@ -995,9 +1169,6 @@ class decklink_input_callback *input_callback; AVStream *st; HRESULT result; - char fname[1024]; - char *tmp; - int mode_num = 0; int ret; ctx = (struct decklink_ctx *) av_mallocz(sizeof(struct decklink_ctx)); @@ -1005,6 +1176,7 @@ return AVERROR(ENOMEM); ctx->list_devices = cctx->list_devices; ctx->list_formats = cctx->list_formats; + ctx->enable_klv = cctx->enable_klv; ctx->teletext_lines = cctx->teletext_lines; ctx->preroll = cctx->preroll; ctx->duplex_mode = cctx->duplex_mode; @@ -1018,6 +1190,8 @@ ctx->video_pts_source = cctx->video_pts_source; ctx->draw_bars = cctx->draw_bars; ctx->audio_depth = cctx->audio_depth; + if (cctx->raw_format > 0 && (unsigned int)cctx->raw_format < FF_ARRAY_ELEMS(decklink_raw_format_map)) + ctx->raw_format = decklink_raw_format_map[cctx->raw_format]; cctx->ctx = ctx; /* Check audio channel option for valid values: 2, 8 or 16 */ @@ -1047,20 +1221,7 @@ return AVERROR_EXIT; } - if (cctx->v210) { - av_log(avctx, AV_LOG_WARNING, "The bm_v210 option is deprecated and will be removed. Please use the -raw_format yuv422p10.\n"); - cctx->raw_format = MKBETAG('v','2','1','0'); - } - - av_strlcpy(fname, avctx->url, sizeof(fname)); - tmp=strchr (fname, '@'); - if (tmp != NULL) { - av_log(avctx, AV_LOG_WARNING, "The @mode syntax is deprecated and will be removed. Please use the -format_code option.\n"); - mode_num = atoi (tmp+1); - *tmp = 0; - } - - ret = ff_decklink_init_device(avctx, fname); + ret = ff_decklink_init_device(avctx, avctx->url); if (ret < 0) return ret; @@ -1101,7 +1262,7 @@ goto error; } - if (mode_num == 0 && !cctx->format_code) { + if (!cctx->format_code) { if (decklink_autodetect(cctx) < 0) { av_log(avctx, AV_LOG_ERROR, "Cannot Autodetect input stream or No signal\n"); ret = AVERROR(EIO); @@ -1109,9 +1270,11 @@ } av_log(avctx, AV_LOG_INFO, "Autodetected the input mode\n"); } - if (ff_decklink_set_format(avctx, DIRECTION_IN, mode_num) < 0) { - av_log(avctx, AV_LOG_ERROR, "Could not set mode number %d or format code %s for %s\n", - mode_num, (cctx->format_code) ? cctx->format_code : "(unset)", fname); + if (ctx->raw_format == (BMDPixelFormat)0) + ctx->raw_format = bmdFormat8BitYUV; + if (ff_decklink_set_format(avctx, DIRECTION_IN) < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not set format code %s for %s\n", + cctx->format_code ? cctx->format_code : "(unset)", avctx->url); ret = AVERROR(EIO); goto error; } @@ -1152,40 +1315,34 @@ st->time_base.num = ctx->bmd_tb_num; st->r_frame_rate = av_make_q(st->time_base.den, st->time_base.num); - switch((BMDPixelFormat)cctx->raw_format) { + switch(ctx->raw_format) { case bmdFormat8BitYUV: st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; - st->codecpar->codec_tag = MKTAG('U', 'Y', 'V', 'Y'); st->codecpar->format = AV_PIX_FMT_UYVY422; st->codecpar->bit_rate = av_rescale(ctx->bmd_width * ctx->bmd_height * 16, st->time_base.den, st->time_base.num); break; case bmdFormat10BitYUV: st->codecpar->codec_id = AV_CODEC_ID_V210; - st->codecpar->codec_tag = MKTAG('V','2','1','0'); st->codecpar->bit_rate = av_rescale(ctx->bmd_width * ctx->bmd_height * 64, st->time_base.den, st->time_base.num * 3); - st->codecpar->bits_per_coded_sample = 10; break; case bmdFormat8BitARGB: st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; st->codecpar->format = AV_PIX_FMT_0RGB; - st->codecpar->codec_tag = avcodec_pix_fmt_to_codec_tag((enum AVPixelFormat)st->codecpar->format); st->codecpar->bit_rate = av_rescale(ctx->bmd_width * ctx->bmd_height * 32, st->time_base.den, st->time_base.num); break; case bmdFormat8BitBGRA: st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; st->codecpar->format = AV_PIX_FMT_BGR0; - st->codecpar->codec_tag = avcodec_pix_fmt_to_codec_tag((enum AVPixelFormat)st->codecpar->format); st->codecpar->bit_rate = av_rescale(ctx->bmd_width * ctx->bmd_height * 32, st->time_base.den, st->time_base.num); break; case bmdFormat10BitRGB: st->codecpar->codec_id = AV_CODEC_ID_R210; - st->codecpar->codec_tag = MKTAG('R','2','1','0'); - st->codecpar->format = AV_PIX_FMT_RGB48LE; st->codecpar->bit_rate = av_rescale(ctx->bmd_width * ctx->bmd_height * 30, st->time_base.den, st->time_base.num); - st->codecpar->bits_per_coded_sample = 10; break; default: - av_log(avctx, AV_LOG_ERROR, "Raw Format %.4s not supported\n", (char*) &cctx->raw_format); + char fourcc_str[AV_FOURCC_MAX_STRING_SIZE] = {0}; + av_fourcc_make_string(fourcc_str, ctx->raw_format); + av_log(avctx, AV_LOG_ERROR, "Raw Format %s not supported\n", fourcc_str); ret = AVERROR(EINVAL); goto error; } @@ -1207,6 +1364,20 @@ ctx->video_st=st; + if (ctx->enable_klv) { + st = avformat_new_stream(avctx, NULL); + if (!st) { + ret = AVERROR(ENOMEM); + goto error; + } + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; + st->time_base.den = ctx->bmd_tb_den; + st->time_base.num = ctx->bmd_tb_num; + st->codecpar->codec_id = AV_CODEC_ID_SMPTE_KLV; + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ + ctx->klv_st = st; + } + if (ctx->teletext_lines) { st = avformat_new_stream(avctx, NULL); if (!st) { @@ -1232,7 +1403,7 @@ } result = ctx->dli->EnableVideoInput(ctx->bmd_mode, - (BMDPixelFormat) cctx->raw_format, + ctx->raw_format, bmdVideoInputFlagDefault); if (result != S_OK) { @@ -1264,7 +1435,7 @@ avpacket_queue_get(&ctx->queue, pkt, 1); if (ctx->tc_format && !(av_dict_get(ctx->video_st->metadata, "timecode", NULL, 0))) { - int size; + buffer_size_t size; const uint8_t *side_metadata = av_packet_get_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, &size); if (side_metadata) { if (av_packet_unpack_dictionary(side_metadata, size, &ctx->video_st->metadata) < 0) diff -Nru ffmpeg-4.2.2/libavdevice/decklink_enc_c.c ffmpeg-4.4/libavdevice/decklink_enc_c.c --- ffmpeg-4.2.2/libavdevice/decklink_enc_c.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/decklink_enc_c.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,7 +28,7 @@ #define OFFSET(x) offsetof(struct decklink_cctx, x) #define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "list_devices", "list available devices" , OFFSET(list_devices), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 1, ENC }, + { "list_devices", "use ffmpeg -sinks decklink instead", OFFSET(list_devices), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC | AV_OPT_FLAG_DEPRECATED}, { "list_formats", "list supported formats" , OFFSET(list_formats), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 1, ENC }, { "preroll" , "video preroll in seconds", OFFSET(preroll ), AV_OPT_TYPE_DOUBLE, { .dbl = 0.5 }, 0, 5, ENC }, { "duplex_mode" , "duplex mode" , OFFSET(duplex_mode ), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 2, ENC, "duplex_mode"}, @@ -41,7 +41,7 @@ }; static const AVClass decklink_muxer_class = { - .class_name = "Blackmagic DeckLink muxer", + .class_name = "Blackmagic DeckLink outdev", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, diff -Nru ffmpeg-4.2.2/libavdevice/decklink_enc.cpp ffmpeg-4.4/libavdevice/decklink_enc.cpp --- ffmpeg-4.2.2/libavdevice/decklink_enc.cpp 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/decklink_enc.cpp 2021-04-08 21:28:39.000000000 +0000 @@ -32,6 +32,7 @@ extern "C" { #include "libavformat/avformat.h" +#include "libavutil/internal.h" #include "libavutil/imgutils.h" #include "avdevice.h" } @@ -312,7 +313,8 @@ uint16_t *cdp_words; uint16_t len; uint8_t cc_count; - int size, ret, i; + buffer_size_t size; + int ret, i; const uint8_t *data = av_packet_get_side_data(pkt, AV_PKT_DATA_A53_CC, &size); if (!data) @@ -436,7 +438,7 @@ AVFrame *avframe = NULL, *tmp = (AVFrame *)pkt->data; AVPacket *avpacket = NULL; decklink_frame *frame; - buffercount_type buffered; + uint32_t buffered; HRESULT hr; if (st->codecpar->codec_id == AV_CODEC_ID_WRAPPED_AVFRAME) { @@ -525,7 +527,7 @@ struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; int sample_count = pkt->size / (ctx->channels << 1); - buffercount_type buffered; + uint32_t buffered; ctx->dlo->GetBufferedAudioSampleFrameCount(&buffered); if (pkt->pts > 1 && !buffered) diff -Nru ffmpeg-4.2.2/libavdevice/dshow.c ffmpeg-4.4/libavdevice/dshow.c --- ffmpeg-4.2.2/libavdevice/dshow.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/dshow.c 2021-04-08 21:28:39.000000000 +0000 @@ -58,7 +58,7 @@ dshow_read_close(AVFormatContext *s) { struct dshow_ctx *ctx = s->priv_data; - AVPacketList *pktl; + PacketList *pktl; if (ctx->control) { IMediaControl_Stop(ctx->control); @@ -87,13 +87,13 @@ } if (ctx->capture_pin[VideoDevice]) - libAVPin_Release(ctx->capture_pin[VideoDevice]); + ff_dshow_pin_Release(ctx->capture_pin[VideoDevice]); if (ctx->capture_pin[AudioDevice]) - libAVPin_Release(ctx->capture_pin[AudioDevice]); + ff_dshow_pin_Release(ctx->capture_pin[AudioDevice]); if (ctx->capture_filter[VideoDevice]) - libAVFilter_Release(ctx->capture_filter[VideoDevice]); + ff_dshow_filter_Release(ctx->capture_filter[VideoDevice]); if (ctx->capture_filter[AudioDevice]) - libAVFilter_Release(ctx->capture_filter[AudioDevice]); + ff_dshow_filter_Release(ctx->capture_filter[AudioDevice]); if (ctx->device_pin[VideoDevice]) IPin_Release(ctx->device_pin[VideoDevice]); @@ -118,7 +118,7 @@ pktl = ctx->pktl; while (pktl) { - AVPacketList *next = pktl->next; + PacketList *next = pktl->next; av_packet_unref(&pktl->pkt); av_free(pktl); pktl = next; @@ -162,7 +162,7 @@ { AVFormatContext *s = priv_data; struct dshow_ctx *ctx = s->priv_data; - AVPacketList **ppktl, *pktl_next; + PacketList **ppktl, *pktl_next; // dump_videohdr(s, vdhdr); @@ -171,7 +171,7 @@ if(shall_we_drop(s, index, devtype)) goto fail; - pktl_next = av_mallocz(sizeof(AVPacketList)); + pktl_next = av_mallocz(sizeof(PacketList)); if(!pktl_next) goto fail; @@ -510,7 +510,7 @@ * Pops up a user dialog allowing them to adjust properties for the given filter, if possible. */ void -dshow_show_filter_properties(IBaseFilter *device_filter, AVFormatContext *avctx) { +ff_dshow_show_filter_properties(IBaseFilter *device_filter, AVFormatContext *avctx) { ISpecifyPropertyPages *property_pages = NULL; IUnknown *device_filter_iunknown = NULL; HRESULT hr; @@ -582,7 +582,7 @@ int should_show_properties = (devtype == VideoDevice) ? ctx->show_video_device_dialog : ctx->show_audio_device_dialog; if (should_show_properties) - dshow_show_filter_properties(device_filter, avctx); + ff_dshow_show_filter_properties(device_filter, avctx); r = IBaseFilter_EnumPins(device_filter, &pins); if (r != S_OK) { @@ -731,8 +731,8 @@ char *device_filter_unique_name = NULL; IGraphBuilder *graph = ctx->graph; IPin *device_pin = NULL; - libAVPin *capture_pin = NULL; - libAVFilter *capture_filter = NULL; + DShowPin *capture_pin = NULL; + DShowFilter *capture_filter = NULL; ICaptureGraphBuilder2 *graph_builder2 = NULL; int ret = AVERROR(EIO); int r; @@ -807,7 +807,7 @@ ctx->device_pin[devtype] = device_pin; - capture_filter = libAVFilter_Create(avctx, callback, devtype); + capture_filter = ff_dshow_filter_Create(avctx, callback, devtype); if (!capture_filter) { av_log(avctx, AV_LOG_ERROR, "Could not create grabber filter.\n"); goto error; @@ -863,7 +863,7 @@ goto error; } - libAVPin_AddRef(capture_filter->pin); + ff_dshow_pin_AddRef(capture_filter->pin); capture_pin = capture_filter->pin; ctx->capture_pin[devtype] = capture_pin; @@ -887,7 +887,7 @@ goto error; } - r = dshow_try_setup_crossbar_options(graph_builder2, device_filter, devtype, avctx); + r = ff_dshow_try_setup_crossbar_options(graph_builder2, device_filter, devtype, avctx); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not setup CrossBar\n"); @@ -953,7 +953,7 @@ ctx->capture_filter[devtype]->stream_index = st->index; - libAVPin_ConnectionMediaType(ctx->capture_pin[devtype], &type); + ff_dshow_pin_ConnectionMediaType(ctx->capture_pin[devtype], &type); par = st->codecpar; if (devtype == VideoDevice) { @@ -1262,7 +1262,7 @@ static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt) { struct dshow_ctx *ctx = s->priv_data; - AVPacketList *pktl = NULL; + PacketList *pktl = NULL; while (!ctx->eof && !pktl) { WaitForSingleObject(ctx->mutex, INFINITE); diff -Nru ffmpeg-4.2.2/libavdevice/dshow_capture.h ffmpeg-4.4/libavdevice/dshow_capture.h --- ffmpeg-4.2.2/libavdevice/dshow_capture.h 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavdevice/dshow_capture.h 2021-04-08 21:28:39.000000000 +0000 @@ -34,6 +34,7 @@ #include #include "libavcodec/internal.h" +#include "libavcodec/packet_internal.h" /* EC_DEVICE_LOST is not defined in MinGW dshow headers. */ #ifndef EC_DEVICE_LOST @@ -68,20 +69,20 @@ AudioSourceDevice = 1, }; -#define DECLARE_QUERYINTERFACE(class, ...) \ -long WINAPI \ -class##_QueryInterface(class *this, const GUID *riid, void **ppvObject) \ +#define DECLARE_QUERYINTERFACE(prefix, class, ...) \ +long \ +ff_dshow_##prefix##_QueryInterface(class *this, const GUID *riid, void **ppvObject) \ { \ struct GUIDoffset ifaces[] = __VA_ARGS__; \ int i; \ - dshowdebug(AV_STRINGIFY(class)"_QueryInterface(%p, %p, %p)\n", this, riid, ppvObject); \ + dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_QueryInterface(%p, %p, %p)\n", this, riid, ppvObject); \ ff_printGUID(riid); \ if (!ppvObject) \ return E_POINTER; \ for (i = 0; i < sizeof(ifaces)/sizeof(ifaces[0]); i++) { \ if (IsEqualGUID(riid, ifaces[i].iid)) { \ void *obj = (void *) ((uint8_t *) this + ifaces[i].offset); \ - class##_AddRef(this); \ + ff_dshow_##prefix##_AddRef(this); \ dshowdebug("\tfound %d with offset %d\n", i, ifaces[i].offset); \ *ppvObject = (void *) obj; \ return S_OK; \ @@ -91,28 +92,28 @@ *ppvObject = NULL; \ return E_NOINTERFACE; \ } -#define DECLARE_ADDREF(class) \ -unsigned long WINAPI \ -class##_AddRef(class *this) \ +#define DECLARE_ADDREF(prefix, class) \ +unsigned long \ +ff_dshow_##prefix##_AddRef(class *this) \ { \ - dshowdebug(AV_STRINGIFY(class)"_AddRef(%p)\t%ld\n", this, this->ref+1); \ + dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_AddRef(%p)\t%ld\n", this, this->ref+1); \ return InterlockedIncrement(&this->ref); \ } -#define DECLARE_RELEASE(class) \ -unsigned long WINAPI \ -class##_Release(class *this) \ +#define DECLARE_RELEASE(prefix, class) \ +unsigned long \ +ff_dshow_##prefix##_Release(class *this) \ { \ long ref = InterlockedDecrement(&this->ref); \ - dshowdebug(AV_STRINGIFY(class)"_Release(%p)\t%ld\n", this, ref); \ + dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_Release(%p)\t%ld\n", this, ref); \ if (!ref) \ - class##_Destroy(this); \ + ff_dshow_##prefix##_Destroy(this); \ return ref; \ } -#define DECLARE_DESTROY(class, func) \ -void class##_Destroy(class *this) \ +#define DECLARE_DESTROY(prefix, class, func) \ +void ff_dshow_##prefix##_Destroy(class *this) \ { \ - dshowdebug(AV_STRINGIFY(class)"_Destroy(%p)\n", this); \ + dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_Destroy(%p)\n", this); \ func(this); \ if (this) { \ if (this->vtbl) \ @@ -120,12 +121,12 @@ CoTaskMemFree(this); \ } \ } -#define DECLARE_CREATE(class, setup, ...) \ -class *class##_Create(__VA_ARGS__) \ +#define DECLARE_CREATE(prefix, class, setup, ...) \ +class *ff_dshow_##prefix##_Create(__VA_ARGS__) \ { \ class *this = CoTaskMemAlloc(sizeof(class)); \ void *vtbl = CoTaskMemAlloc(sizeof(*this->vtbl)); \ - dshowdebug(AV_STRINGIFY(class)"_Create(%p)\n", this); \ + dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_Create(%p)\n", this); \ if (!this || !vtbl) \ goto fail; \ ZeroMemory(this, sizeof(class)); \ @@ -134,123 +135,123 @@ this->vtbl = vtbl; \ if (!setup) \ goto fail; \ - dshowdebug("created "AV_STRINGIFY(class)" %p\n", this); \ + dshowdebug("created ff_dshow_"AV_STRINGIFY(prefix)" %p\n", this); \ return this; \ fail: \ - class##_Destroy(this); \ - dshowdebug("could not create "AV_STRINGIFY(class)"\n"); \ + ff_dshow_##prefix##_Destroy(this); \ + dshowdebug("could not create ff_dshow_"AV_STRINGIFY(prefix)"\n"); \ return NULL; \ } -#define SETVTBL(vtbl, class, fn) \ - do { (vtbl)->fn = (void *) class##_##fn; } while(0) +#define SETVTBL(vtbl, prefix, fn) \ + do { (vtbl)->fn = (void *) ff_dshow_##prefix##_##fn; } while(0) /***************************************************************************** * Forward Declarations ****************************************************************************/ -typedef struct libAVPin libAVPin; -typedef struct libAVMemInputPin libAVMemInputPin; -typedef struct libAVEnumPins libAVEnumPins; -typedef struct libAVEnumMediaTypes libAVEnumMediaTypes; -typedef struct libAVFilter libAVFilter; +typedef struct DShowPin DShowPin; +typedef struct DShowMemInputPin DShowMemInputPin; +typedef struct DShowEnumPins DShowEnumPins; +typedef struct DShowEnumMediaTypes DShowEnumMediaTypes; +typedef struct DShowFilter DShowFilter; /***************************************************************************** - * libAVPin + * DShowPin ****************************************************************************/ -struct libAVPin { +struct DShowPin { IPinVtbl *vtbl; long ref; - libAVFilter *filter; + DShowFilter *filter; IPin *connectedto; AM_MEDIA_TYPE type; IMemInputPinVtbl *imemvtbl; }; -long WINAPI libAVPin_QueryInterface (libAVPin *, const GUID *, void **); -unsigned long WINAPI libAVPin_AddRef (libAVPin *); -unsigned long WINAPI libAVPin_Release (libAVPin *); -long WINAPI libAVPin_Connect (libAVPin *, IPin *, const AM_MEDIA_TYPE *); -long WINAPI libAVPin_ReceiveConnection (libAVPin *, IPin *, const AM_MEDIA_TYPE *); -long WINAPI libAVPin_Disconnect (libAVPin *); -long WINAPI libAVPin_ConnectedTo (libAVPin *, IPin **); -long WINAPI libAVPin_ConnectionMediaType (libAVPin *, AM_MEDIA_TYPE *); -long WINAPI libAVPin_QueryPinInfo (libAVPin *, PIN_INFO *); -long WINAPI libAVPin_QueryDirection (libAVPin *, PIN_DIRECTION *); -long WINAPI libAVPin_QueryId (libAVPin *, wchar_t **); -long WINAPI libAVPin_QueryAccept (libAVPin *, const AM_MEDIA_TYPE *); -long WINAPI libAVPin_EnumMediaTypes (libAVPin *, IEnumMediaTypes **); -long WINAPI libAVPin_QueryInternalConnections(libAVPin *, IPin **, unsigned long *); -long WINAPI libAVPin_EndOfStream (libAVPin *); -long WINAPI libAVPin_BeginFlush (libAVPin *); -long WINAPI libAVPin_EndFlush (libAVPin *); -long WINAPI libAVPin_NewSegment (libAVPin *, REFERENCE_TIME, REFERENCE_TIME, double); - -long WINAPI libAVMemInputPin_QueryInterface (libAVMemInputPin *, const GUID *, void **); -unsigned long WINAPI libAVMemInputPin_AddRef (libAVMemInputPin *); -unsigned long WINAPI libAVMemInputPin_Release (libAVMemInputPin *); -long WINAPI libAVMemInputPin_GetAllocator (libAVMemInputPin *, IMemAllocator **); -long WINAPI libAVMemInputPin_NotifyAllocator (libAVMemInputPin *, IMemAllocator *, BOOL); -long WINAPI libAVMemInputPin_GetAllocatorRequirements(libAVMemInputPin *, ALLOCATOR_PROPERTIES *); -long WINAPI libAVMemInputPin_Receive (libAVMemInputPin *, IMediaSample *); -long WINAPI libAVMemInputPin_ReceiveMultiple (libAVMemInputPin *, IMediaSample **, long, long *); -long WINAPI libAVMemInputPin_ReceiveCanBlock (libAVMemInputPin *); +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 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 *); -void libAVPin_Destroy(libAVPin *); -libAVPin *libAVPin_Create (libAVFilter *filter); +void ff_dshow_pin_Destroy(DShowPin *); +DShowPin *ff_dshow_pin_Create (DShowFilter *filter); -void libAVMemInputPin_Destroy(libAVMemInputPin *); +void ff_dshow_meminputpin_Destroy(DShowMemInputPin *); /***************************************************************************** - * libAVEnumPins + * DShowEnumPins ****************************************************************************/ -struct libAVEnumPins { +struct DShowEnumPins { IEnumPinsVtbl *vtbl; long ref; int pos; - libAVPin *pin; - libAVFilter *filter; + DShowPin *pin; + DShowFilter *filter; }; -long WINAPI libAVEnumPins_QueryInterface(libAVEnumPins *, const GUID *, void **); -unsigned long WINAPI libAVEnumPins_AddRef (libAVEnumPins *); -unsigned long WINAPI libAVEnumPins_Release (libAVEnumPins *); -long WINAPI libAVEnumPins_Next (libAVEnumPins *, unsigned long, IPin **, unsigned long *); -long WINAPI libAVEnumPins_Skip (libAVEnumPins *, unsigned long); -long WINAPI libAVEnumPins_Reset (libAVEnumPins *); -long WINAPI libAVEnumPins_Clone (libAVEnumPins *, libAVEnumPins **); +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 **); -void libAVEnumPins_Destroy(libAVEnumPins *); -libAVEnumPins *libAVEnumPins_Create (libAVPin *pin, libAVFilter *filter); +void ff_dshow_enumpins_Destroy(DShowEnumPins *); +DShowEnumPins *ff_dshow_enumpins_Create (DShowPin *pin, DShowFilter *filter); /***************************************************************************** - * libAVEnumMediaTypes + * DShowEnumMediaTypes ****************************************************************************/ -struct libAVEnumMediaTypes { +struct DShowEnumMediaTypes { IEnumMediaTypesVtbl *vtbl; long ref; int pos; AM_MEDIA_TYPE type; }; -long WINAPI libAVEnumMediaTypes_QueryInterface(libAVEnumMediaTypes *, const GUID *, void **); -unsigned long WINAPI libAVEnumMediaTypes_AddRef (libAVEnumMediaTypes *); -unsigned long WINAPI libAVEnumMediaTypes_Release (libAVEnumMediaTypes *); -long WINAPI libAVEnumMediaTypes_Next (libAVEnumMediaTypes *, unsigned long, AM_MEDIA_TYPE **, unsigned long *); -long WINAPI libAVEnumMediaTypes_Skip (libAVEnumMediaTypes *, unsigned long); -long WINAPI libAVEnumMediaTypes_Reset (libAVEnumMediaTypes *); -long WINAPI libAVEnumMediaTypes_Clone (libAVEnumMediaTypes *, libAVEnumMediaTypes **); +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 **); -void libAVEnumMediaTypes_Destroy(libAVEnumMediaTypes *); -libAVEnumMediaTypes *libAVEnumMediaTypes_Create(const AM_MEDIA_TYPE *type); +void ff_dshow_enummediatypes_Destroy(DShowEnumMediaTypes *); +DShowEnumMediaTypes *ff_dshow_enummediatypes_Create(const AM_MEDIA_TYPE *type); /***************************************************************************** - * libAVFilter + * DShowFilter ****************************************************************************/ -struct libAVFilter { +struct DShowFilter { IBaseFilterVtbl *vtbl; long ref; const wchar_t *name; - libAVPin *pin; + DShowPin *pin; FILTER_INFO info; FILTER_STATE state; IReferenceClock *clock; @@ -261,24 +262,24 @@ void (*callback)(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType type); }; -long WINAPI libAVFilter_QueryInterface (libAVFilter *, const GUID *, void **); -unsigned long WINAPI libAVFilter_AddRef (libAVFilter *); -unsigned long WINAPI libAVFilter_Release (libAVFilter *); -long WINAPI libAVFilter_GetClassID (libAVFilter *, CLSID *); -long WINAPI libAVFilter_Stop (libAVFilter *); -long WINAPI libAVFilter_Pause (libAVFilter *); -long WINAPI libAVFilter_Run (libAVFilter *, REFERENCE_TIME); -long WINAPI libAVFilter_GetState (libAVFilter *, DWORD, FILTER_STATE *); -long WINAPI libAVFilter_SetSyncSource (libAVFilter *, IReferenceClock *); -long WINAPI libAVFilter_GetSyncSource (libAVFilter *, IReferenceClock **); -long WINAPI libAVFilter_EnumPins (libAVFilter *, IEnumPins **); -long WINAPI libAVFilter_FindPin (libAVFilter *, const wchar_t *, IPin **); -long WINAPI libAVFilter_QueryFilterInfo(libAVFilter *, FILTER_INFO *); -long WINAPI libAVFilter_JoinFilterGraph(libAVFilter *, IFilterGraph *, const wchar_t *); -long WINAPI libAVFilter_QueryVendorInfo(libAVFilter *, wchar_t **); +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 **); -void libAVFilter_Destroy(libAVFilter *); -libAVFilter *libAVFilter_Create (void *, void *, enum dshowDeviceType); +void ff_dshow_filter_Destroy(DShowFilter *); +DShowFilter *ff_dshow_filter_Create (void *, void *, enum dshowDeviceType); /***************************************************************************** * dshow_ctx @@ -314,13 +315,13 @@ IBaseFilter *device_filter[2]; IPin *device_pin[2]; - libAVFilter *capture_filter[2]; - libAVPin *capture_pin[2]; + DShowFilter *capture_filter[2]; + DShowPin *capture_pin[2]; HANDLE mutex; HANDLE event[2]; /* event[0] is set by DirectShow * event[1] is set by callback() */ - AVPacketList *pktl; + PacketList *pktl; int eof; @@ -346,9 +347,9 @@ /***************************************************************************** * CrossBar ****************************************************************************/ -HRESULT dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2, +HRESULT ff_dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter, enum dshowDeviceType devtype, AVFormatContext *avctx); -void dshow_show_filter_properties(IBaseFilter *pFilter, AVFormatContext *avctx); +void ff_dshow_show_filter_properties(IBaseFilter *pFilter, AVFormatContext *avctx); #endif /* AVDEVICE_DSHOW_CAPTURE_H */ diff -Nru ffmpeg-4.2.2/libavdevice/dshow_crossbar.c ffmpeg-4.4/libavdevice/dshow_crossbar.c --- ffmpeg-4.2.2/libavdevice/dshow_crossbar.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavdevice/dshow_crossbar.c 2021-04-08 21:28:39.000000000 +0000 @@ -137,7 +137,7 @@ * Given a fully constructed graph, check if there is a cross bar filter, and configure its pins if so. */ HRESULT -dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2, +ff_dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2, IBaseFilter *device_filter, enum dshowDeviceType devtype, AVFormatContext *avctx) { struct dshow_ctx *ctx = avctx->priv_data; @@ -163,7 +163,7 @@ hr = IAMCrossbar_QueryInterface(cross_bar, &IID_IBaseFilter, (void **) &cross_bar_base_filter); if (hr != S_OK) goto end; - dshow_show_filter_properties(cross_bar_base_filter, avctx); + ff_dshow_show_filter_properties(cross_bar_base_filter, avctx); } if (devtype == VideoDevice && ctx->show_analog_tv_tuner_dialog) { @@ -173,7 +173,7 @@ hr = IAMCrossbar_QueryInterface(tv_tuner_filter, &IID_IBaseFilter, (void **) &tv_tuner_base_filter); if (hr != S_OK) goto end; - dshow_show_filter_properties(tv_tuner_base_filter, avctx); + ff_dshow_show_filter_properties(tv_tuner_base_filter, avctx); } else { av_log(avctx, AV_LOG_WARNING, "unable to find a tv tuner to display dialog for!"); } @@ -185,7 +185,7 @@ hr = IAMCrossbar_QueryInterface(tv_audio_filter, &IID_IBaseFilter, (void **) &tv_audio_base_filter); if (hr != S_OK) goto end; - dshow_show_filter_properties(tv_audio_base_filter, avctx); + ff_dshow_show_filter_properties(tv_audio_base_filter, avctx); } else { av_log(avctx, AV_LOG_WARNING, "unable to find a tv audio tuner to display dialog for!"); } diff -Nru ffmpeg-4.2.2/libavdevice/dshow_enummediatypes.c ffmpeg-4.4/libavdevice/dshow_enummediatypes.c --- ffmpeg-4.2.2/libavdevice/dshow_enummediatypes.c 2018-07-17 09:27:41.000000000 +0000 +++ ffmpeg-4.4/libavdevice/dshow_enummediatypes.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,17 +21,16 @@ #include "dshow_capture.h" -DECLARE_QUERYINTERFACE(libAVEnumMediaTypes, +DECLARE_QUERYINTERFACE(enummediatypes, DShowEnumMediaTypes, { {&IID_IUnknown,0}, {&IID_IEnumMediaTypes,0} }) -DECLARE_ADDREF(libAVEnumMediaTypes) -DECLARE_RELEASE(libAVEnumMediaTypes) +DECLARE_ADDREF(enummediatypes, DShowEnumMediaTypes) +DECLARE_RELEASE(enummediatypes, DShowEnumMediaTypes) -long WINAPI -libAVEnumMediaTypes_Next(libAVEnumMediaTypes *this, unsigned long n, +long ff_dshow_enummediatypes_Next(DShowEnumMediaTypes *this, unsigned long n, AM_MEDIA_TYPE **types, unsigned long *fetched) { int count = 0; - dshowdebug("libAVEnumMediaTypes_Next(%p)\n", this); + dshowdebug("ff_dshow_enummediatypes_Next(%p)\n", this); if (!types) return E_POINTER; if (!this->pos && n == 1) { @@ -51,29 +50,26 @@ return S_FALSE; return S_OK; } -long WINAPI -libAVEnumMediaTypes_Skip(libAVEnumMediaTypes *this, unsigned long n) +long ff_dshow_enummediatypes_Skip(DShowEnumMediaTypes *this, unsigned long n) { - dshowdebug("libAVEnumMediaTypes_Skip(%p)\n", this); + 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 WINAPI -libAVEnumMediaTypes_Reset(libAVEnumMediaTypes *this) +long ff_dshow_enummediatypes_Reset(DShowEnumMediaTypes *this) { - dshowdebug("libAVEnumMediaTypes_Reset(%p)\n", this); + dshowdebug("ff_dshow_enummediatypes_Reset(%p)\n", this); this->pos = 0; return S_OK; } -long WINAPI -libAVEnumMediaTypes_Clone(libAVEnumMediaTypes *this, libAVEnumMediaTypes **enums) +long ff_dshow_enummediatypes_Clone(DShowEnumMediaTypes *this, DShowEnumMediaTypes **enums) { - libAVEnumMediaTypes *new; - dshowdebug("libAVEnumMediaTypes_Clone(%p)\n", this); + DShowEnumMediaTypes *new; + dshowdebug("ff_dshow_enummediatypes_Clone(%p)\n", this); if (!enums) return E_POINTER; - new = libAVEnumMediaTypes_Create(&this->type); + new = ff_dshow_enummediatypes_Create(&this->type); if (!new) return E_OUTOFMEMORY; new->pos = this->pos; @@ -81,17 +77,16 @@ return S_OK; } -static int -libAVEnumMediaTypes_Setup(libAVEnumMediaTypes *this, const AM_MEDIA_TYPE *type) +static int ff_dshow_enummediatypes_Setup(DShowEnumMediaTypes *this, const AM_MEDIA_TYPE *type) { IEnumMediaTypesVtbl *vtbl = this->vtbl; - SETVTBL(vtbl, libAVEnumMediaTypes, QueryInterface); - SETVTBL(vtbl, libAVEnumMediaTypes, AddRef); - SETVTBL(vtbl, libAVEnumMediaTypes, Release); - SETVTBL(vtbl, libAVEnumMediaTypes, Next); - SETVTBL(vtbl, libAVEnumMediaTypes, Skip); - SETVTBL(vtbl, libAVEnumMediaTypes, Reset); - SETVTBL(vtbl, libAVEnumMediaTypes, Clone); + SETVTBL(vtbl, enummediatypes, QueryInterface); + SETVTBL(vtbl, enummediatypes, AddRef); + SETVTBL(vtbl, enummediatypes, Release); + SETVTBL(vtbl, enummediatypes, Next); + SETVTBL(vtbl, enummediatypes, Skip); + SETVTBL(vtbl, enummediatypes, Reset); + SETVTBL(vtbl, enummediatypes, Clone); if (!type) { this->type.majortype = GUID_NULL; @@ -101,5 +96,5 @@ return 1; } -DECLARE_CREATE(libAVEnumMediaTypes, libAVEnumMediaTypes_Setup(this, type), const AM_MEDIA_TYPE *type) -DECLARE_DESTROY(libAVEnumMediaTypes, nothing) +DECLARE_CREATE(enummediatypes, DShowEnumMediaTypes, ff_dshow_enummediatypes_Setup(this, type), const AM_MEDIA_TYPE *type) +DECLARE_DESTROY(enummediatypes, DShowEnumMediaTypes, nothing) diff -Nru ffmpeg-4.2.2/libavdevice/dshow_enumpins.c ffmpeg-4.4/libavdevice/dshow_enumpins.c --- ffmpeg-4.2.2/libavdevice/dshow_enumpins.c 2016-03-29 02:25:25.000000000 +0000 +++ ffmpeg-4.4/libavdevice/dshow_enumpins.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,21 +21,20 @@ #include "dshow_capture.h" -DECLARE_QUERYINTERFACE(libAVEnumPins, +DECLARE_QUERYINTERFACE(enumpins, DShowEnumPins, { {&IID_IUnknown,0}, {&IID_IEnumPins,0} }) -DECLARE_ADDREF(libAVEnumPins) -DECLARE_RELEASE(libAVEnumPins) +DECLARE_ADDREF(enumpins, DShowEnumPins) +DECLARE_RELEASE(enumpins, DShowEnumPins) -long WINAPI -libAVEnumPins_Next(libAVEnumPins *this, unsigned long n, IPin **pins, +long ff_dshow_enumpins_Next(DShowEnumPins *this, unsigned long n, IPin **pins, unsigned long *fetched) { int count = 0; - dshowdebug("libAVEnumPins_Next(%p)\n", this); + dshowdebug("ff_dshow_enumpins_Next(%p)\n", this); if (!pins) return E_POINTER; if (!this->pos && n == 1) { - libAVPin_AddRef(this->pin); + ff_dshow_pin_AddRef(this->pin); *pins = (IPin *) this->pin; count = 1; this->pos = 1; @@ -46,29 +45,26 @@ return S_FALSE; return S_OK; } -long WINAPI -libAVEnumPins_Skip(libAVEnumPins *this, unsigned long n) +long ff_dshow_enumpins_Skip(DShowEnumPins *this, unsigned long n) { - dshowdebug("libAVEnumPins_Skip(%p)\n", this); + 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 WINAPI -libAVEnumPins_Reset(libAVEnumPins *this) +long ff_dshow_enumpins_Reset(DShowEnumPins *this) { - dshowdebug("libAVEnumPins_Reset(%p)\n", this); + dshowdebug("ff_dshow_enumpins_Reset(%p)\n", this); this->pos = 0; return S_OK; } -long WINAPI -libAVEnumPins_Clone(libAVEnumPins *this, libAVEnumPins **pins) +long ff_dshow_enumpins_Clone(DShowEnumPins *this, DShowEnumPins **pins) { - libAVEnumPins *new; - dshowdebug("libAVEnumPins_Clone(%p)\n", this); + DShowEnumPins *new; + dshowdebug("ff_dshow_enumpins_Clone(%p)\n", this); if (!pins) return E_POINTER; - new = libAVEnumPins_Create(this->pin, this->filter); + new = ff_dshow_enumpins_Create(this->pin, this->filter); if (!new) return E_OUTOFMEMORY; new->pos = this->pos; @@ -76,30 +72,28 @@ return S_OK; } -static int -libAVEnumPins_Setup(libAVEnumPins *this, libAVPin *pin, libAVFilter *filter) +static int ff_dshow_enumpins_Setup(DShowEnumPins *this, DShowPin *pin, DShowFilter *filter) { IEnumPinsVtbl *vtbl = this->vtbl; - SETVTBL(vtbl, libAVEnumPins, QueryInterface); - SETVTBL(vtbl, libAVEnumPins, AddRef); - SETVTBL(vtbl, libAVEnumPins, Release); - SETVTBL(vtbl, libAVEnumPins, Next); - SETVTBL(vtbl, libAVEnumPins, Skip); - SETVTBL(vtbl, libAVEnumPins, Reset); - SETVTBL(vtbl, libAVEnumPins, Clone); + SETVTBL(vtbl, enumpins, QueryInterface); + SETVTBL(vtbl, enumpins, AddRef); + SETVTBL(vtbl, enumpins, Release); + SETVTBL(vtbl, enumpins, Next); + SETVTBL(vtbl, enumpins, Skip); + SETVTBL(vtbl, enumpins, Reset); + SETVTBL(vtbl, enumpins, Clone); this->pin = pin; this->filter = filter; - libAVFilter_AddRef(this->filter); + ff_dshow_filter_AddRef(this->filter); return 1; } -static int -libAVEnumPins_Cleanup(libAVEnumPins *this) +static int ff_dshow_enumpins_Cleanup(DShowEnumPins *this) { - libAVFilter_Release(this->filter); + ff_dshow_filter_Release(this->filter); return 1; } -DECLARE_CREATE(libAVEnumPins, libAVEnumPins_Setup(this, pin, filter), - libAVPin *pin, libAVFilter *filter) -DECLARE_DESTROY(libAVEnumPins, libAVEnumPins_Cleanup) +DECLARE_CREATE(enumpins, DShowEnumPins, ff_dshow_enumpins_Setup(this, pin, filter), + DShowPin *pin, DShowFilter *filter) +DECLARE_DESTROY(enumpins, DShowEnumPins, ff_dshow_enumpins_Cleanup) diff -Nru ffmpeg-4.2.2/libavdevice/dshow_filter.c ffmpeg-4.4/libavdevice/dshow_filter.c --- ffmpeg-4.2.2/libavdevice/dshow_filter.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavdevice/dshow_filter.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,53 +21,47 @@ #include "dshow_capture.h" -DECLARE_QUERYINTERFACE(libAVFilter, +DECLARE_QUERYINTERFACE(filter, DShowFilter, { {&IID_IUnknown,0}, {&IID_IBaseFilter,0} }) -DECLARE_ADDREF(libAVFilter) -DECLARE_RELEASE(libAVFilter) +DECLARE_ADDREF(filter, DShowFilter) +DECLARE_RELEASE(filter, DShowFilter) -long WINAPI -libAVFilter_GetClassID(libAVFilter *this, CLSID *id) +long ff_dshow_filter_GetClassID(DShowFilter *this, CLSID *id) { - dshowdebug("libAVFilter_GetClassID(%p)\n", this); + dshowdebug("ff_dshow_filter_GetClassID(%p)\n", this); /* I'm not creating a ClassID just for this. */ return E_FAIL; } -long WINAPI -libAVFilter_Stop(libAVFilter *this) +long ff_dshow_filter_Stop(DShowFilter *this) { - dshowdebug("libAVFilter_Stop(%p)\n", this); + dshowdebug("ff_dshow_filter_Stop(%p)\n", this); this->state = State_Stopped; return S_OK; } -long WINAPI -libAVFilter_Pause(libAVFilter *this) +long ff_dshow_filter_Pause(DShowFilter *this) { - dshowdebug("libAVFilter_Pause(%p)\n", this); + dshowdebug("ff_dshow_filter_Pause(%p)\n", this); this->state = State_Paused; return S_OK; } -long WINAPI -libAVFilter_Run(libAVFilter *this, REFERENCE_TIME start) +long ff_dshow_filter_Run(DShowFilter *this, REFERENCE_TIME start) { - dshowdebug("libAVFilter_Run(%p) %"PRId64"\n", this, start); + dshowdebug("ff_dshow_filter_Run(%p) %"PRId64"\n", this, start); this->state = State_Running; this->start_time = start; return S_OK; } -long WINAPI -libAVFilter_GetState(libAVFilter *this, DWORD ms, FILTER_STATE *state) +long ff_dshow_filter_GetState(DShowFilter *this, DWORD ms, FILTER_STATE *state) { - dshowdebug("libAVFilter_GetState(%p)\n", this); + dshowdebug("ff_dshow_filter_GetState(%p)\n", this); if (!state) return E_POINTER; *state = this->state; return S_OK; } -long WINAPI -libAVFilter_SetSyncSource(libAVFilter *this, IReferenceClock *clock) +long ff_dshow_filter_SetSyncSource(DShowFilter *this, IReferenceClock *clock) { - dshowdebug("libAVFilter_SetSyncSource(%p)\n", this); + dshowdebug("ff_dshow_filter_SetSyncSource(%p)\n", this); if (this->clock != clock) { if (this->clock) @@ -79,10 +73,9 @@ return S_OK; } -long WINAPI -libAVFilter_GetSyncSource(libAVFilter *this, IReferenceClock **clock) +long ff_dshow_filter_GetSyncSource(DShowFilter *this, IReferenceClock **clock) { - dshowdebug("libAVFilter_GetSyncSource(%p)\n", this); + dshowdebug("ff_dshow_filter_GetSyncSource(%p)\n", this); if (!clock) return E_POINTER; @@ -92,32 +85,30 @@ return S_OK; } -long WINAPI -libAVFilter_EnumPins(libAVFilter *this, IEnumPins **enumpin) +long ff_dshow_filter_EnumPins(DShowFilter *this, IEnumPins **enumpin) { - libAVEnumPins *new; - dshowdebug("libAVFilter_EnumPins(%p)\n", this); + DShowEnumPins *new; + dshowdebug("ff_dshow_filter_EnumPins(%p)\n", this); if (!enumpin) return E_POINTER; - new = libAVEnumPins_Create(this->pin, this); + new = ff_dshow_enumpins_Create(this->pin, this); if (!new) return E_OUTOFMEMORY; *enumpin = (IEnumPins *) new; return S_OK; } -long WINAPI -libAVFilter_FindPin(libAVFilter *this, const wchar_t *id, IPin **pin) +long ff_dshow_filter_FindPin(DShowFilter *this, const wchar_t *id, IPin **pin) { - libAVPin *found = NULL; - dshowdebug("libAVFilter_FindPin(%p)\n", this); + DShowPin *found = NULL; + dshowdebug("ff_dshow_filter_FindPin(%p)\n", this); if (!id || !pin) return E_POINTER; if (!wcscmp(id, L"In")) { found = this->pin; - libAVPin_AddRef(found); + ff_dshow_pin_AddRef(found); } *pin = (IPin *) found; if (!found) @@ -125,10 +116,9 @@ return S_OK; } -long WINAPI -libAVFilter_QueryFilterInfo(libAVFilter *this, FILTER_INFO *info) +long ff_dshow_filter_QueryFilterInfo(DShowFilter *this, FILTER_INFO *info) { - dshowdebug("libAVFilter_QueryFilterInfo(%p)\n", this); + dshowdebug("ff_dshow_filter_QueryFilterInfo(%p)\n", this); if (!info) return E_POINTER; @@ -138,11 +128,10 @@ return S_OK; } -long WINAPI -libAVFilter_JoinFilterGraph(libAVFilter *this, IFilterGraph *graph, +long ff_dshow_filter_JoinFilterGraph(DShowFilter *this, IFilterGraph *graph, const wchar_t *name) { - dshowdebug("libAVFilter_JoinFilterGraph(%p)\n", this); + dshowdebug("ff_dshow_filter_JoinFilterGraph(%p)\n", this); this->info.pGraph = graph; if (name) @@ -150,10 +139,9 @@ return S_OK; } -long WINAPI -libAVFilter_QueryVendorInfo(libAVFilter *this, wchar_t **info) +long ff_dshow_filter_QueryVendorInfo(DShowFilter *this, wchar_t **info) { - dshowdebug("libAVFilter_QueryVendorInfo(%p)\n", this); + dshowdebug("ff_dshow_filter_QueryVendorInfo(%p)\n", this); if (!info) return E_POINTER; @@ -161,27 +149,27 @@ } static int -libAVFilter_Setup(libAVFilter *this, void *priv_data, void *callback, +ff_dshow_filter_Setup(DShowFilter *this, void *priv_data, void *callback, enum dshowDeviceType type) { IBaseFilterVtbl *vtbl = this->vtbl; - SETVTBL(vtbl, libAVFilter, QueryInterface); - SETVTBL(vtbl, libAVFilter, AddRef); - SETVTBL(vtbl, libAVFilter, Release); - SETVTBL(vtbl, libAVFilter, GetClassID); - SETVTBL(vtbl, libAVFilter, Stop); - SETVTBL(vtbl, libAVFilter, Pause); - SETVTBL(vtbl, libAVFilter, Run); - SETVTBL(vtbl, libAVFilter, GetState); - SETVTBL(vtbl, libAVFilter, SetSyncSource); - SETVTBL(vtbl, libAVFilter, GetSyncSource); - SETVTBL(vtbl, libAVFilter, EnumPins); - SETVTBL(vtbl, libAVFilter, FindPin); - SETVTBL(vtbl, libAVFilter, QueryFilterInfo); - SETVTBL(vtbl, libAVFilter, JoinFilterGraph); - SETVTBL(vtbl, libAVFilter, QueryVendorInfo); + SETVTBL(vtbl, filter, QueryInterface); + SETVTBL(vtbl, filter, AddRef); + SETVTBL(vtbl, filter, Release); + SETVTBL(vtbl, filter, GetClassID); + SETVTBL(vtbl, filter, Stop); + SETVTBL(vtbl, filter, Pause); + SETVTBL(vtbl, filter, Run); + SETVTBL(vtbl, filter, GetState); + SETVTBL(vtbl, filter, SetSyncSource); + SETVTBL(vtbl, filter, GetSyncSource); + SETVTBL(vtbl, filter, EnumPins); + SETVTBL(vtbl, filter, FindPin); + SETVTBL(vtbl, filter, QueryFilterInfo); + SETVTBL(vtbl, filter, JoinFilterGraph); + SETVTBL(vtbl, filter, QueryVendorInfo); - this->pin = libAVPin_Create(this); + this->pin = ff_dshow_pin_Create(this); this->priv_data = priv_data; this->callback = callback; @@ -189,12 +177,11 @@ return 1; } -static int -libAVFilter_Cleanup(libAVFilter *this) +static int ff_dshow_filter_Cleanup(DShowFilter *this) { - libAVPin_Release(this->pin); + ff_dshow_pin_Release(this->pin); return 1; } -DECLARE_CREATE(libAVFilter, libAVFilter_Setup(this, priv_data, callback, type), +DECLARE_CREATE(filter, DShowFilter, ff_dshow_filter_Setup(this, priv_data, callback, type), void *priv_data, void *callback, enum dshowDeviceType type) -DECLARE_DESTROY(libAVFilter, libAVFilter_Cleanup) +DECLARE_DESTROY(filter, DShowFilter, ff_dshow_filter_Cleanup) diff -Nru ffmpeg-4.2.2/libavdevice/dshow_pin.c ffmpeg-4.4/libavdevice/dshow_pin.c --- ffmpeg-4.2.2/libavdevice/dshow_pin.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/dshow_pin.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,26 +22,24 @@ #include "dshow_capture.h" #include -#define imemoffset offsetof(libAVPin, imemvtbl) +#define imemoffset offsetof(DShowPin, imemvtbl) -DECLARE_QUERYINTERFACE(libAVPin, +DECLARE_QUERYINTERFACE(pin, DShowPin, { {&IID_IUnknown,0}, {&IID_IPin,0}, {&IID_IMemInputPin,imemoffset} }) -DECLARE_ADDREF(libAVPin) -DECLARE_RELEASE(libAVPin) +DECLARE_ADDREF(pin, DShowPin) +DECLARE_RELEASE(pin, DShowPin) -long WINAPI -libAVPin_Connect(libAVPin *this, IPin *pin, const AM_MEDIA_TYPE *type) +long ff_dshow_pin_Connect(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type) { - dshowdebug("libAVPin_Connect(%p, %p, %p)\n", this, pin, type); + dshowdebug("ff_dshow_pin_Connect(%p, %p, %p)\n", this, pin, type); /* Input pins receive connections. */ return S_FALSE; } -long WINAPI -libAVPin_ReceiveConnection(libAVPin *this, IPin *pin, +long ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type) { enum dshowDeviceType devtype = this->filter->type; - dshowdebug("libAVPin_ReceiveConnection(%p)\n", this); + dshowdebug("ff_dshow_pin_ReceiveConnection(%p)\n", this); if (!pin) return E_POINTER; @@ -64,10 +62,9 @@ return S_OK; } -long WINAPI -libAVPin_Disconnect(libAVPin *this) +long ff_dshow_pin_Disconnect(DShowPin *this) { - dshowdebug("libAVPin_Disconnect(%p)\n", this); + dshowdebug("ff_dshow_pin_Disconnect(%p)\n", this); if (this->filter->state != State_Stopped) return VFW_E_NOT_STOPPED; @@ -78,10 +75,9 @@ return S_OK; } -long WINAPI -libAVPin_ConnectedTo(libAVPin *this, IPin **pin) +long ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin) { - dshowdebug("libAVPin_ConnectedTo(%p)\n", this); + dshowdebug("ff_dshow_pin_ConnectedTo(%p)\n", this); if (!pin) return E_POINTER; @@ -92,10 +88,9 @@ return S_OK; } -long WINAPI -libAVPin_ConnectionMediaType(libAVPin *this, AM_MEDIA_TYPE *type) +long ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type) { - dshowdebug("libAVPin_ConnectionMediaType(%p)\n", this); + dshowdebug("ff_dshow_pin_ConnectionMediaType(%p)\n", this); if (!type) return E_POINTER; @@ -104,16 +99,15 @@ return ff_copy_dshow_media_type(type, &this->type); } -long WINAPI -libAVPin_QueryPinInfo(libAVPin *this, PIN_INFO *info) +long ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info) { - dshowdebug("libAVPin_QueryPinInfo(%p)\n", this); + dshowdebug("ff_dshow_pin_QueryPinInfo(%p)\n", this); if (!info) return E_POINTER; if (this->filter) - libAVFilter_AddRef(this->filter); + ff_dshow_filter_AddRef(this->filter); info->pFilter = (IBaseFilter *) this->filter; info->dir = PINDIR_INPUT; @@ -121,19 +115,17 @@ return S_OK; } -long WINAPI -libAVPin_QueryDirection(libAVPin *this, PIN_DIRECTION *dir) +long ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir) { - dshowdebug("libAVPin_QueryDirection(%p)\n", this); + dshowdebug("ff_dshow_pin_QueryDirection(%p)\n", this); if (!dir) return E_POINTER; *dir = PINDIR_INPUT; return S_OK; } -long WINAPI -libAVPin_QueryId(libAVPin *this, wchar_t **id) +long ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id) { - dshowdebug("libAVPin_QueryId(%p)\n", this); + dshowdebug("ff_dshow_pin_QueryId(%p)\n", this); if (!id) return E_POINTER; @@ -142,67 +134,59 @@ return S_OK; } -long WINAPI -libAVPin_QueryAccept(libAVPin *this, const AM_MEDIA_TYPE *type) +long ff_dshow_pin_QueryAccept(DShowPin *this, const AM_MEDIA_TYPE *type) { - dshowdebug("libAVPin_QueryAccept(%p)\n", this); + dshowdebug("ff_dshow_pin_QueryAccept(%p)\n", this); return S_FALSE; } -long WINAPI -libAVPin_EnumMediaTypes(libAVPin *this, IEnumMediaTypes **enumtypes) +long ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes) { const AM_MEDIA_TYPE *type = NULL; - libAVEnumMediaTypes *new; - dshowdebug("libAVPin_EnumMediaTypes(%p)\n", this); + DShowEnumMediaTypes *new; + dshowdebug("ff_dshow_pin_EnumMediaTypes(%p)\n", this); if (!enumtypes) return E_POINTER; - new = libAVEnumMediaTypes_Create(type); + new = ff_dshow_enummediatypes_Create(type); if (!new) return E_OUTOFMEMORY; *enumtypes = (IEnumMediaTypes *) new; return S_OK; } -long WINAPI -libAVPin_QueryInternalConnections(libAVPin *this, IPin **pin, +long ff_dshow_pin_QueryInternalConnections(DShowPin *this, IPin **pin, unsigned long *npin) { - dshowdebug("libAVPin_QueryInternalConnections(%p)\n", this); + dshowdebug("ff_dshow_pin_QueryInternalConnections(%p)\n", this); return E_NOTIMPL; } -long WINAPI -libAVPin_EndOfStream(libAVPin *this) +long ff_dshow_pin_EndOfStream(DShowPin *this) { - dshowdebug("libAVPin_EndOfStream(%p)\n", this); + dshowdebug("ff_dshow_pin_EndOfStream(%p)\n", this); /* I don't care. */ return S_OK; } -long WINAPI -libAVPin_BeginFlush(libAVPin *this) +long ff_dshow_pin_BeginFlush(DShowPin *this) { - dshowdebug("libAVPin_BeginFlush(%p)\n", this); + dshowdebug("ff_dshow_pin_BeginFlush(%p)\n", this); /* I don't care. */ return S_OK; } -long WINAPI -libAVPin_EndFlush(libAVPin *this) +long ff_dshow_pin_EndFlush(DShowPin *this) { - dshowdebug("libAVPin_EndFlush(%p)\n", this); + dshowdebug("ff_dshow_pin_EndFlush(%p)\n", this); /* I don't care. */ return S_OK; } -long WINAPI -libAVPin_NewSegment(libAVPin *this, REFERENCE_TIME start, REFERENCE_TIME stop, +long ff_dshow_pin_NewSegment(DShowPin *this, REFERENCE_TIME start, REFERENCE_TIME stop, double rate) { - dshowdebug("libAVPin_NewSegment(%p)\n", this); + dshowdebug("ff_dshow_pin_NewSegment(%p)\n", this); /* I don't care. */ return S_OK; } -static int -libAVPin_Setup(libAVPin *this, libAVFilter *filter) +static int ff_dshow_pin_Setup(DShowPin *this, DShowFilter *filter) { IPinVtbl *vtbl = this->vtbl; IMemInputPinVtbl *imemvtbl; @@ -214,44 +198,43 @@ if (!imemvtbl) return 0; - SETVTBL(imemvtbl, libAVMemInputPin, QueryInterface); - SETVTBL(imemvtbl, libAVMemInputPin, AddRef); - SETVTBL(imemvtbl, libAVMemInputPin, Release); - SETVTBL(imemvtbl, libAVMemInputPin, GetAllocator); - SETVTBL(imemvtbl, libAVMemInputPin, NotifyAllocator); - SETVTBL(imemvtbl, libAVMemInputPin, GetAllocatorRequirements); - SETVTBL(imemvtbl, libAVMemInputPin, Receive); - SETVTBL(imemvtbl, libAVMemInputPin, ReceiveMultiple); - SETVTBL(imemvtbl, libAVMemInputPin, ReceiveCanBlock); + SETVTBL(imemvtbl, meminputpin, QueryInterface); + SETVTBL(imemvtbl, meminputpin, AddRef); + SETVTBL(imemvtbl, meminputpin, Release); + SETVTBL(imemvtbl, meminputpin, GetAllocator); + SETVTBL(imemvtbl, meminputpin, NotifyAllocator); + SETVTBL(imemvtbl, meminputpin, GetAllocatorRequirements); + SETVTBL(imemvtbl, meminputpin, Receive); + SETVTBL(imemvtbl, meminputpin, ReceiveMultiple); + SETVTBL(imemvtbl, meminputpin, ReceiveCanBlock); this->imemvtbl = imemvtbl; - SETVTBL(vtbl, libAVPin, QueryInterface); - SETVTBL(vtbl, libAVPin, AddRef); - SETVTBL(vtbl, libAVPin, Release); - SETVTBL(vtbl, libAVPin, Connect); - SETVTBL(vtbl, libAVPin, ReceiveConnection); - SETVTBL(vtbl, libAVPin, Disconnect); - SETVTBL(vtbl, libAVPin, ConnectedTo); - SETVTBL(vtbl, libAVPin, ConnectionMediaType); - SETVTBL(vtbl, libAVPin, QueryPinInfo); - SETVTBL(vtbl, libAVPin, QueryDirection); - SETVTBL(vtbl, libAVPin, QueryId); - SETVTBL(vtbl, libAVPin, QueryAccept); - SETVTBL(vtbl, libAVPin, EnumMediaTypes); - SETVTBL(vtbl, libAVPin, QueryInternalConnections); - SETVTBL(vtbl, libAVPin, EndOfStream); - SETVTBL(vtbl, libAVPin, BeginFlush); - SETVTBL(vtbl, libAVPin, EndFlush); - SETVTBL(vtbl, libAVPin, NewSegment); + SETVTBL(vtbl, pin, QueryInterface); + SETVTBL(vtbl, pin, AddRef); + SETVTBL(vtbl, pin, Release); + SETVTBL(vtbl, pin, Connect); + SETVTBL(vtbl, pin, ReceiveConnection); + SETVTBL(vtbl, pin, Disconnect); + SETVTBL(vtbl, pin, ConnectedTo); + SETVTBL(vtbl, pin, ConnectionMediaType); + SETVTBL(vtbl, pin, QueryPinInfo); + SETVTBL(vtbl, pin, QueryDirection); + SETVTBL(vtbl, pin, QueryId); + SETVTBL(vtbl, pin, QueryAccept); + SETVTBL(vtbl, pin, EnumMediaTypes); + SETVTBL(vtbl, pin, QueryInternalConnections); + SETVTBL(vtbl, pin, EndOfStream); + SETVTBL(vtbl, pin, BeginFlush); + SETVTBL(vtbl, pin, EndFlush); + SETVTBL(vtbl, pin, NewSegment); this->filter = filter; return 1; } -static void -libAVPin_Free(libAVPin *this) +static void ff_dshow_pin_Free(DShowPin *this) { if (!this) return; @@ -261,58 +244,51 @@ this->type.pbFormat = NULL; } } -DECLARE_CREATE(libAVPin, libAVPin_Setup(this, filter), libAVFilter *filter) -DECLARE_DESTROY(libAVPin, libAVPin_Free) +DECLARE_CREATE(pin, DShowPin, ff_dshow_pin_Setup(this, filter), DShowFilter *filter) +DECLARE_DESTROY(pin, DShowPin, ff_dshow_pin_Free) /***************************************************************************** - * libAVMemInputPin + * DShowMemInputPin ****************************************************************************/ -long WINAPI -libAVMemInputPin_QueryInterface(libAVMemInputPin *this, const GUID *riid, +long ff_dshow_meminputpin_QueryInterface(DShowMemInputPin *this, const GUID *riid, void **ppvObject) { - libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset); - dshowdebug("libAVMemInputPin_QueryInterface(%p)\n", this); - return libAVPin_QueryInterface(pin, riid, 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 WINAPI -libAVMemInputPin_AddRef(libAVMemInputPin *this) +unsigned long ff_dshow_meminputpin_AddRef(DShowMemInputPin *this) { - libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset); - dshowdebug("libAVMemInputPin_AddRef(%p)\n", this); - return libAVPin_AddRef(pin); + DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); + dshowdebug("ff_dshow_meminputpin_AddRef(%p)\n", this); + return ff_dshow_pin_AddRef(pin); } -unsigned long WINAPI -libAVMemInputPin_Release(libAVMemInputPin *this) +unsigned long ff_dshow_meminputpin_Release(DShowMemInputPin *this) { - libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset); - dshowdebug("libAVMemInputPin_Release(%p)\n", this); - return libAVPin_Release(pin); + DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); + dshowdebug("ff_dshow_meminputpin_Release(%p)\n", this); + return ff_dshow_pin_Release(pin); } -long WINAPI -libAVMemInputPin_GetAllocator(libAVMemInputPin *this, IMemAllocator **alloc) +long ff_dshow_meminputpin_GetAllocator(DShowMemInputPin *this, IMemAllocator **alloc) { - dshowdebug("libAVMemInputPin_GetAllocator(%p)\n", this); + dshowdebug("ff_dshow_meminputpin_GetAllocator(%p)\n", this); return VFW_E_NO_ALLOCATOR; } -long WINAPI -libAVMemInputPin_NotifyAllocator(libAVMemInputPin *this, IMemAllocator *alloc, +long ff_dshow_meminputpin_NotifyAllocator(DShowMemInputPin *this, IMemAllocator *alloc, BOOL rdwr) { - dshowdebug("libAVMemInputPin_NotifyAllocator(%p)\n", this); + dshowdebug("ff_dshow_meminputpin_NotifyAllocator(%p)\n", this); return S_OK; } -long WINAPI -libAVMemInputPin_GetAllocatorRequirements(libAVMemInputPin *this, +long ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *this, ALLOCATOR_PROPERTIES *props) { - dshowdebug("libAVMemInputPin_GetAllocatorRequirements(%p)\n", this); + dshowdebug("ff_dshow_meminputpin_GetAllocatorRequirements(%p)\n", this); return E_NOTIMPL; } -long WINAPI -libAVMemInputPin_Receive(libAVMemInputPin *this, IMediaSample *sample) +long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) { - libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset); + DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); enum dshowDeviceType devtype = pin->filter->type; void *priv_data; AVFormatContext *s; @@ -328,7 +304,7 @@ struct dshow_ctx *ctx; - dshowdebug("libAVMemInputPin_Receive(%p)\n", this); + dshowdebug("ff_dshow_meminputpin_Receive(%p)\n", this); if (!sample) return E_POINTER; @@ -366,31 +342,28 @@ return S_OK; } -long WINAPI -libAVMemInputPin_ReceiveMultiple(libAVMemInputPin *this, +long ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *this, IMediaSample **samples, long n, long *nproc) { int i; - dshowdebug("libAVMemInputPin_ReceiveMultiple(%p)\n", this); + dshowdebug("ff_dshow_meminputpin_ReceiveMultiple(%p)\n", this); for (i = 0; i < n; i++) - libAVMemInputPin_Receive(this, samples[i]); + ff_dshow_meminputpin_Receive(this, samples[i]); *nproc = n; return S_OK; } -long WINAPI -libAVMemInputPin_ReceiveCanBlock(libAVMemInputPin *this) +long ff_dshow_meminputpin_ReceiveCanBlock(DShowMemInputPin *this) { - dshowdebug("libAVMemInputPin_ReceiveCanBlock(%p)\n", this); + dshowdebug("ff_dshow_meminputpin_ReceiveCanBlock(%p)\n", this); /* I swear I will not block. */ return S_FALSE; } -void -libAVMemInputPin_Destroy(libAVMemInputPin *this) +void ff_dshow_meminputpin_Destroy(DShowMemInputPin *this) { - libAVPin *pin = (libAVPin *) ((uint8_t *) this - imemoffset); - dshowdebug("libAVMemInputPin_Destroy(%p)\n", this); - libAVPin_Destroy(pin); + DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); + dshowdebug("ff_dshow_meminputpin_Destroy(%p)\n", this); + ff_dshow_pin_Destroy(pin); } diff -Nru ffmpeg-4.2.2/libavdevice/fbdev_dec.c ffmpeg-4.4/libavdevice/fbdev_dec.c --- ffmpeg-4.2.2/libavdevice/fbdev_dec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/fbdev_dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -157,11 +157,11 @@ uint8_t *pin, *pout; if (fbdev->time_frame == AV_NOPTS_VALUE) - fbdev->time_frame = av_gettime(); + fbdev->time_frame = av_gettime_relative(); /* wait based on the frame rate */ while (1) { - curtime = av_gettime(); + curtime = av_gettime_relative(); delay = fbdev->time_frame - curtime; av_log(avctx, AV_LOG_TRACE, "time_frame:%"PRId64" curtime:%"PRId64" delay:%"PRId64"\n", @@ -186,7 +186,7 @@ "Error refreshing variable info: %s\n", av_err2str(AVERROR(errno))); } - pkt->pts = curtime; + pkt->pts = av_gettime(); /* compute visible data offset */ pin = fbdev->data + fbdev->bytes_per_pixel * fbdev->varinfo.xoffset + diff -Nru ffmpeg-4.2.2/libavdevice/gdigrab.c ffmpeg-4.4/libavdevice/gdigrab.c --- ffmpeg-4.2.2/libavdevice/gdigrab.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/gdigrab.c 2021-04-08 21:28:39.000000000 +0000 @@ -394,7 +394,7 @@ gdigrab->header_size = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (bpp <= 8 ? (1 << bpp) : 0) * sizeof(RGBQUAD) /* palette size */; gdigrab->time_base = av_inv_q(gdigrab->framerate); - gdigrab->time_frame = av_gettime() / av_q2d(gdigrab->time_base); + gdigrab->time_frame = av_gettime_relative() / av_q2d(gdigrab->time_base); gdigrab->hwnd = hwnd; gdigrab->source_hdc = source_hdc; @@ -551,7 +551,7 @@ /* wait based on the frame rate */ for (;;) { - curtime = av_gettime(); + curtime = av_gettime_relative(); delay = time_frame * av_q2d(time_base) - curtime; if (delay <= 0) { if (delay < INT64_C(-1000000) * av_q2d(time_base)) { @@ -568,7 +568,7 @@ if (av_new_packet(pkt, file_size) < 0) return AVERROR(ENOMEM); - pkt->pts = curtime; + pkt->pts = av_gettime(); /* Blit screen grab */ if (!BitBlt(dest_hdc, 0, 0, diff -Nru ffmpeg-4.2.2/libavdevice/kmsgrab.c ffmpeg-4.4/libavdevice/kmsgrab.c --- ffmpeg-4.2.2/libavdevice/kmsgrab.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/kmsgrab.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,11 @@ #include #include +// Required for compatibility when building against libdrm < 2.4.83. +#ifndef DRM_FORMAT_MOD_INVALID +#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) +#endif + #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_drm.h" #include "libavutil/internal.h" @@ -45,6 +50,7 @@ AVBufferRef *device_ref; AVHWDeviceContext *device; AVDRMDeviceContext *hwctx; + int fb2_available; AVBufferRef *frames_ref; AVHWFramesContext *frames; @@ -68,8 +74,10 @@ static void kmsgrab_free_desc(void *opaque, uint8_t *data) { AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor*)data; + int i; - close(desc->objects[0].fd); + for (i = 0; i < desc->nb_objects; i++) + close(desc->objects[i].fd); av_free(desc); } @@ -81,70 +89,44 @@ av_frame_free(&frame); } -static int kmsgrab_read_packet(AVFormatContext *avctx, AVPacket *pkt) +static int kmsgrab_get_fb(AVFormatContext *avctx, + drmModePlane *plane, + AVDRMFrameDescriptor *desc) { KMSGrabContext *ctx = avctx->priv_data; - drmModePlane *plane; - drmModeFB *fb; - AVDRMFrameDescriptor *desc; - AVFrame *frame; - int64_t now; + drmModeFB *fb = NULL; int err, fd; - now = av_gettime(); - if (ctx->frame_last) { - int64_t delay; - while (1) { - delay = ctx->frame_last + ctx->frame_delay - now; - if (delay <= 0) - break; - av_usleep(delay); - now = av_gettime(); - } - } - ctx->frame_last = now; - - plane = drmModeGetPlane(ctx->hwctx->fd, ctx->plane_id); - if (!plane) { - av_log(avctx, AV_LOG_ERROR, "Failed to get plane " - "%"PRIu32".\n", ctx->plane_id); - return AVERROR(EIO); - } - if (!plane->fb_id) { - av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" no longer has " - "an associated framebuffer.\n", ctx->plane_id); - return AVERROR(EIO); - } - fb = drmModeGetFB(ctx->hwctx->fd, plane->fb_id); if (!fb) { + err = errno; av_log(avctx, AV_LOG_ERROR, "Failed to get framebuffer " - "%"PRIu32".\n", plane->fb_id); - return AVERROR(EIO); + "%"PRIu32": %s.\n", plane->fb_id, strerror(err)); + err = AVERROR(err); + goto fail; } if (fb->width != ctx->width || fb->height != ctx->height) { av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer " "dimensions changed: now %"PRIu32"x%"PRIu32".\n", ctx->plane_id, fb->width, fb->height); - return AVERROR(EIO); + err = AVERROR(EIO); + goto fail; } if (!fb->handle) { av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer.\n"); - return AVERROR(EIO); + err = AVERROR(EIO); + goto fail; } err = drmPrimeHandleToFD(ctx->hwctx->fd, fb->handle, O_RDONLY, &fd); if (err < 0) { err = errno; av_log(avctx, AV_LOG_ERROR, "Failed to get PRIME fd from " - "framebuffer handle: %s.\n", strerror(errno)); - return AVERROR(err); + "framebuffer handle: %s.\n", strerror(err)); + err = AVERROR(err); + goto fail; } - desc = av_mallocz(sizeof(*desc)); - if (!desc) - return AVERROR(ENOMEM); - *desc = (AVDRMFrameDescriptor) { .nb_objects = 1, .objects[0] = { @@ -164,31 +146,206 @@ }, }; + err = 0; +fail: + drmModeFreeFB(fb); + return err; +} + +#if HAVE_LIBDRM_GETFB2 +static int kmsgrab_get_fb2(AVFormatContext *avctx, + drmModePlane *plane, + AVDRMFrameDescriptor *desc) +{ + KMSGrabContext *ctx = avctx->priv_data; + drmModeFB2 *fb; + int err, i, nb_objects; + uint64_t modifier = ctx->drm_format_modifier; + + fb = drmModeGetFB2(ctx->hwctx->fd, plane->fb_id); + if (!fb) { + err = errno; + av_log(avctx, AV_LOG_ERROR, "Failed to get framebuffer " + "%"PRIu32": %s.\n", plane->fb_id, strerror(err)); + return AVERROR(err); + } + if (fb->pixel_format != ctx->drm_format) { + av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer " + "format changed: now %"PRIx32".\n", + ctx->plane_id, fb->pixel_format); + err = AVERROR(EIO); + goto fail; + } + if (fb->width != ctx->width || fb->height != ctx->height) { + av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer " + "dimensions changed: now %"PRIu32"x%"PRIu32".\n", + ctx->plane_id, fb->width, fb->height); + err = AVERROR(EIO); + goto fail; + } + if (!fb->handles[0]) { + av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer.\n"); + err = AVERROR(EIO); + goto fail; + } + + if (fb->flags & DRM_MODE_FB_MODIFIERS) + modifier = fb->modifier; + + *desc = (AVDRMFrameDescriptor) { + .nb_layers = 1, + .layers[0] = { + .format = ctx->drm_format, + }, + }; + + nb_objects = 0; + for (i = 0; i < 4 && fb->handles[i]; i++) { + size_t size; + int dup = 0, j, obj; + + size = fb->offsets[i] + fb->height * fb->pitches[i]; + + for (j = 0; j < i; j++) { + if (fb->handles[i] == fb->handles[j]) { + dup = 1; + break; + } + } + if (dup) { + obj = desc->layers[0].planes[j].object_index; + + if (desc->objects[j].size < size) + desc->objects[j].size = size; + + desc->layers[0].planes[i] = (AVDRMPlaneDescriptor) { + .object_index = obj, + .offset = fb->offsets[i], + .pitch = fb->pitches[i], + }; + + } else { + int fd; + err = drmPrimeHandleToFD(ctx->hwctx->fd, fb->handles[i], + O_RDONLY, &fd); + if (err < 0) { + err = errno; + av_log(avctx, AV_LOG_ERROR, "Failed to get PRIME fd from " + "framebuffer handle: %s.\n", strerror(err)); + err = AVERROR(err); + goto fail; + } + + obj = nb_objects++; + desc->objects[obj] = (AVDRMObjectDescriptor) { + .fd = fd, + .size = size, + .format_modifier = modifier, + }; + desc->layers[0].planes[i] = (AVDRMPlaneDescriptor) { + .object_index = obj, + .offset = fb->offsets[i], + .pitch = fb->pitches[i], + }; + } + } + desc->nb_objects = nb_objects; + desc->layers[0].nb_planes = i; + + err = 0; +fail: + drmModeFreeFB2(fb); + return err; +} +#endif + +static int kmsgrab_read_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + KMSGrabContext *ctx = avctx->priv_data; + drmModePlane *plane = NULL; + AVDRMFrameDescriptor *desc = NULL; + AVFrame *frame = NULL; + int64_t now; + int err; + + now = av_gettime_relative(); + if (ctx->frame_last) { + int64_t delay; + while (1) { + delay = ctx->frame_last + ctx->frame_delay - now; + if (delay <= 0) + break; + av_usleep(delay); + now = av_gettime_relative(); + } + } + ctx->frame_last = now; + now = av_gettime(); + + plane = drmModeGetPlane(ctx->hwctx->fd, ctx->plane_id); + if (!plane) { + err = errno; + av_log(avctx, AV_LOG_ERROR, "Failed to get plane " + "%"PRIu32": %s.\n", ctx->plane_id, strerror(err)); + err = AVERROR(err); + goto fail; + } + if (!plane->fb_id) { + av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" no longer has " + "an associated framebuffer.\n", ctx->plane_id); + err = AVERROR(EIO); + goto fail; + } + + desc = av_mallocz(sizeof(*desc)); + if (!desc) { + err = AVERROR(ENOMEM); + goto fail; + } + +#if HAVE_LIBDRM_GETFB2 + if (ctx->fb2_available) + err = kmsgrab_get_fb2(avctx, plane, desc); + else +#endif + err = kmsgrab_get_fb(avctx, plane, desc); + if (err < 0) + goto fail; + frame = av_frame_alloc(); - if (!frame) - return AVERROR(ENOMEM); + if (!frame) { + err = AVERROR(ENOMEM); + goto fail; + } frame->hw_frames_ctx = av_buffer_ref(ctx->frames_ref); - if (!frame->hw_frames_ctx) - return AVERROR(ENOMEM); + if (!frame->hw_frames_ctx) { + err = AVERROR(ENOMEM); + goto fail; + } frame->buf[0] = av_buffer_create((uint8_t*)desc, sizeof(*desc), &kmsgrab_free_desc, avctx, 0); - if (!frame->buf[0]) - return AVERROR(ENOMEM); + if (!frame->buf[0]) { + err = AVERROR(ENOMEM); + goto fail; + } frame->data[0] = (uint8_t*)desc; frame->format = AV_PIX_FMT_DRM_PRIME; - frame->width = fb->width; - frame->height = fb->height; + frame->width = ctx->width; + frame->height = ctx->height; - drmModeFreeFB(fb); drmModeFreePlane(plane); + plane = NULL; + desc = NULL; pkt->buf = av_buffer_create((uint8_t*)frame, sizeof(*frame), &kmsgrab_free_frame, avctx, 0); - if (!pkt->buf) - return AVERROR(ENOMEM); + if (!pkt->buf) { + err = AVERROR(ENOMEM); + goto fail; + } pkt->data = (uint8_t*)frame; pkt->size = sizeof(*frame); @@ -196,12 +353,19 @@ pkt->flags |= AV_PKT_FLAG_TRUSTED; return 0; + +fail: + drmModeFreePlane(plane); + av_freep(&desc); + av_frame_free(&frame); + return err; } static const struct { enum AVPixelFormat pixfmt; uint32_t drm_format; } kmsgrab_formats[] = { + // Monochrome. #ifdef DRM_FORMAT_R8 { AV_PIX_FMT_GRAY8, DRM_FORMAT_R8 }, #endif @@ -209,6 +373,7 @@ { AV_PIX_FMT_GRAY16LE, DRM_FORMAT_R16 }, { AV_PIX_FMT_GRAY16BE, DRM_FORMAT_R16 | DRM_FORMAT_BIG_ENDIAN }, #endif + // <8-bit RGB. { AV_PIX_FMT_BGR8, DRM_FORMAT_BGR233 }, { AV_PIX_FMT_RGB555LE, DRM_FORMAT_XRGB1555 }, { AV_PIX_FMT_RGB555BE, DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN }, @@ -218,6 +383,7 @@ { AV_PIX_FMT_RGB565BE, DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN }, { AV_PIX_FMT_BGR565LE, DRM_FORMAT_BGR565 }, { AV_PIX_FMT_BGR565BE, DRM_FORMAT_BGR565 | DRM_FORMAT_BIG_ENDIAN }, + // 8-bit RGB. { AV_PIX_FMT_RGB24, DRM_FORMAT_RGB888 }, { AV_PIX_FMT_BGR24, DRM_FORMAT_BGR888 }, { AV_PIX_FMT_0RGB, DRM_FORMAT_BGRX8888 }, @@ -228,6 +394,12 @@ { AV_PIX_FMT_ABGR, DRM_FORMAT_RGBA8888 }, { AV_PIX_FMT_RGBA, DRM_FORMAT_ABGR8888 }, { AV_PIX_FMT_BGRA, DRM_FORMAT_ARGB8888 }, + // 10-bit RGB. + { AV_PIX_FMT_X2RGB10LE, DRM_FORMAT_XRGB2101010 }, + { AV_PIX_FMT_X2RGB10BE, DRM_FORMAT_XRGB2101010 | DRM_FORMAT_BIG_ENDIAN }, + // 8-bit YUV 4:2:0. + { AV_PIX_FMT_NV12, DRM_FORMAT_NV12 }, + // 8-bit YUV 4:2:2. { AV_PIX_FMT_YUYV422, DRM_FORMAT_YUYV }, { AV_PIX_FMT_YVYU422, DRM_FORMAT_YVYU }, { AV_PIX_FMT_UYVY422, DRM_FORMAT_UYVY }, @@ -239,21 +411,12 @@ drmModePlaneRes *plane_res = NULL; drmModePlane *plane = NULL; drmModeFB *fb = NULL; +#if HAVE_LIBDRM_GETFB2 + drmModeFB2 *fb2 = NULL; +#endif AVStream *stream; int err, i; - for (i = 0; i < FF_ARRAY_ELEMS(kmsgrab_formats); i++) { - if (kmsgrab_formats[i].pixfmt == ctx->format) { - ctx->drm_format = kmsgrab_formats[i].drm_format; - break; - } - } - if (i >= FF_ARRAY_ELEMS(kmsgrab_formats)) { - av_log(avctx, AV_LOG_ERROR, "Unsupported format %s.\n", - av_get_pix_fmt_name(ctx->format)); - return AVERROR(EINVAL); - } - err = av_hwdevice_ctx_create(&ctx->device_ref, AV_HWDEVICE_TYPE_DRM, ctx->device_path, NULL, 0); if (err < 0) { @@ -289,9 +452,10 @@ } else { plane_res = drmModeGetPlaneResources(ctx->hwctx->fd); if (!plane_res) { + err = errno; av_log(avctx, AV_LOG_ERROR, "Failed to get plane " - "resources: %s.\n", strerror(errno)); - err = AVERROR(EINVAL); + "resources: %s.\n", strerror(err)); + err = AVERROR(err); goto fail; } @@ -340,28 +504,119 @@ ctx->plane_id = plane->plane_id; - fb = drmModeGetFB(ctx->hwctx->fd, plane->fb_id); - if (!fb) { +#if HAVE_LIBDRM_GETFB2 + fb2 = drmModeGetFB2(ctx->hwctx->fd, plane->fb_id); + if (!fb2 && errno == ENOSYS) { + av_log(avctx, AV_LOG_INFO, "GETFB2 not supported, " + "will try to use GETFB instead.\n"); + } else if (!fb2) { err = errno; av_log(avctx, AV_LOG_ERROR, "Failed to get " "framebuffer %"PRIu32": %s.\n", plane->fb_id, strerror(err)); err = AVERROR(err); goto fail; + } else { + av_log(avctx, AV_LOG_INFO, "Template framebuffer is " + "%"PRIu32": %"PRIu32"x%"PRIu32" " + "format %"PRIx32" modifier %"PRIx64" flags %"PRIx32".\n", + fb2->fb_id, fb2->width, fb2->height, + fb2->pixel_format, fb2->modifier, fb2->flags); + + ctx->width = fb2->width; + ctx->height = fb2->height; + + if (!fb2->handles[0]) { + av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer: " + "maybe you need some additional capabilities?\n"); + err = AVERROR(EINVAL); + goto fail; + } + + for (i = 0; i < FF_ARRAY_ELEMS(kmsgrab_formats); i++) { + if (kmsgrab_formats[i].drm_format == fb2->pixel_format) { + if (ctx->format != AV_PIX_FMT_NONE && + ctx->format != kmsgrab_formats[i].pixfmt) { + av_log(avctx, AV_LOG_ERROR, "Framebuffer pixel format " + "%"PRIx32" does not match expected format.\n", + fb2->pixel_format); + err = AVERROR(EINVAL); + goto fail; + } + ctx->drm_format = fb2->pixel_format; + ctx->format = kmsgrab_formats[i].pixfmt; + break; + } + } + if (i == FF_ARRAY_ELEMS(kmsgrab_formats)) { + av_log(avctx, AV_LOG_ERROR, "Framebuffer pixel format " + "%"PRIx32" is not a known supported format.\n", + fb2->pixel_format); + err = AVERROR(EINVAL); + goto fail; + } + + if (fb2->flags & DRM_MODE_FB_MODIFIERS) { + if (ctx->drm_format_modifier != DRM_FORMAT_MOD_INVALID && + ctx->drm_format_modifier != fb2->modifier) { + av_log(avctx, AV_LOG_ERROR, "Framebuffer format modifier " + "%"PRIx64" does not match expected modifier.\n", + fb2->modifier); + err = AVERROR(EINVAL); + goto fail; + } else { + ctx->drm_format_modifier = fb2->modifier; + } + } + av_log(avctx, AV_LOG_VERBOSE, "Format is %s, from " + "DRM format %"PRIx32" modifier %"PRIx64".\n", + av_get_pix_fmt_name(ctx->format), + ctx->drm_format, ctx->drm_format_modifier); + + ctx->fb2_available = 1; } +#endif - av_log(avctx, AV_LOG_INFO, "Template framebuffer is %"PRIu32": " - "%"PRIu32"x%"PRIu32" %"PRIu32"bpp %"PRIu32"b depth.\n", - fb->fb_id, fb->width, fb->height, fb->bpp, fb->depth); + if (!ctx->fb2_available) { + if (ctx->format == AV_PIX_FMT_NONE) { + // Backward compatibility: assume BGR0 if no format supplied. + ctx->format = AV_PIX_FMT_BGR0; + } + for (i = 0; i < FF_ARRAY_ELEMS(kmsgrab_formats); i++) { + if (kmsgrab_formats[i].pixfmt == ctx->format) { + ctx->drm_format = kmsgrab_formats[i].drm_format; + break; + } + } + if (i >= FF_ARRAY_ELEMS(kmsgrab_formats)) { + av_log(avctx, AV_LOG_ERROR, "Unsupported format %s.\n", + av_get_pix_fmt_name(ctx->format)); + return AVERROR(EINVAL); + } - ctx->width = fb->width; - ctx->height = fb->height; + fb = drmModeGetFB(ctx->hwctx->fd, plane->fb_id); + if (!fb) { + err = errno; + av_log(avctx, AV_LOG_ERROR, "Failed to get " + "framebuffer %"PRIu32": %s.\n", + plane->fb_id, strerror(err)); + err = AVERROR(err); + goto fail; + } - if (!fb->handle) { - av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer: " - "maybe you need some additional capabilities?\n"); - err = AVERROR(EINVAL); - goto fail; + av_log(avctx, AV_LOG_INFO, "Template framebuffer is %"PRIu32": " + "%"PRIu32"x%"PRIu32" %"PRIu32"bpp %"PRIu32"b depth.\n", + fb->fb_id, fb->width, fb->height, fb->bpp, fb->depth); + + ctx->width = fb->width; + ctx->height = fb->height; + + if (!fb->handle) { + av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer: " + "maybe you need some additional capabilities?\n"); + err = AVERROR(EINVAL); + goto fail; + } } stream = avformat_new_stream(avctx, NULL); @@ -372,8 +627,8 @@ stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; stream->codecpar->codec_id = AV_CODEC_ID_WRAPPED_AVFRAME; - stream->codecpar->width = fb->width; - stream->codecpar->height = fb->height; + stream->codecpar->width = ctx->width; + stream->codecpar->height = ctx->height; stream->codecpar->format = AV_PIX_FMT_DRM_PRIME; avpriv_set_pts_info(stream, 64, 1, 1000000); @@ -387,8 +642,8 @@ ctx->frames->format = AV_PIX_FMT_DRM_PRIME; ctx->frames->sw_format = ctx->format, - ctx->frames->width = fb->width; - ctx->frames->height = fb->height; + ctx->frames->width = ctx->width; + ctx->frames->height = ctx->height; err = av_hwframe_ctx_init(ctx->frames_ref); if (err < 0) { @@ -402,13 +657,12 @@ err = 0; fail: - if (plane_res) - drmModeFreePlaneResources(plane_res); - if (plane) - drmModeFreePlane(plane); - if (fb) - drmModeFreeFB(fb); - + drmModeFreePlaneResources(plane_res); + drmModeFreePlane(plane); + drmModeFreeFB(fb); +#if HAVE_LIBDRM_GETFB2 + drmModeFreeFB2(fb2); +#endif return err; } @@ -430,10 +684,10 @@ { .str = "/dev/dri/card0" }, 0, 0, FLAGS }, { "format", "Pixel format for framebuffer", OFFSET(format), AV_OPT_TYPE_PIXEL_FMT, - { .i64 = AV_PIX_FMT_BGR0 }, 0, UINT32_MAX, FLAGS }, + { .i64 = AV_PIX_FMT_NONE }, -1, INT32_MAX, FLAGS }, { "format_modifier", "DRM format modifier for framebuffer", OFFSET(drm_format_modifier), AV_OPT_TYPE_INT64, - { .i64 = DRM_FORMAT_MOD_NONE }, 0, INT64_MAX, FLAGS }, + { .i64 = DRM_FORMAT_MOD_INVALID }, 0, INT64_MAX, FLAGS }, { "crtc_id", "CRTC ID to define capture source", OFFSET(source_crtc), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, UINT32_MAX, FLAGS }, diff -Nru ffmpeg-4.2.2/libavdevice/lavfi.c ffmpeg-4.4/libavdevice/lavfi.c --- ffmpeg-4.2.2/libavdevice/lavfi.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/lavfi.c 2021-04-08 21:28:39.000000000 +0000 @@ -69,7 +69,7 @@ count++; } - if (!(fmts = av_malloc((count+1) * sizeof(int)))) + if (!(fmts = av_malloc_array(count + 1, sizeof(*fmts)))) return NULL; for (j = 0, i = 0; i < n; i++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i); @@ -302,9 +302,13 @@ if (lavfi->dump_graph) { char *dump = avfilter_graph_dump(lavfi->graph, lavfi->dump_graph); - fputs(dump, stderr); - fflush(stderr); - av_free(dump); + if (dump != NULL) { + fputs(dump, stderr); + fflush(stderr); + av_free(dump); + } else { + FAIL(AVERROR(ENOMEM)); + } } /* fill each stream with the information in the corresponding sink */ @@ -358,16 +362,12 @@ { LavfiContext *lavfi = avctx->priv_data; AVFrameSideData *sd; - int stream_idx, i, ret; + int stream_idx, ret; if ((stream_idx = lavfi->sink_stream_subcc_map[sink_idx]) < 0) return 0; - for (i = 0; i < frame->nb_side_data; i++) - if (frame->side_data[i]->type == AV_FRAME_DATA_A53_CC) - break; - if (i >= frame->nb_side_data) + if (!(sd = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC))) return 0; - sd = frame->side_data[i]; if ((ret = av_new_packet(&lavfi->subcc_packet, sd->size)) < 0) return ret; memcpy(lavfi->subcc_packet.data, sd->data, sd->size); @@ -386,12 +386,10 @@ AVDictionary *frame_metadata; int ret, i; int size = 0; + AVStream *st; if (lavfi->subcc_packet.size) { - *pkt = lavfi->subcc_packet; - av_init_packet(&lavfi->subcc_packet); - lavfi->subcc_packet.size = 0; - lavfi->subcc_packet.data = NULL; + av_packet_move_ref(pkt, &lavfi->subcc_packet); return pkt->size; } @@ -429,57 +427,52 @@ av_buffersink_get_frame_flags(lavfi->sinks[min_pts_sink_idx], frame, 0); stream_idx = lavfi->sink_stream_map[min_pts_sink_idx]; + st = avctx->streams[stream_idx]; - if (frame->width /* FIXME best way of testing a video */) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { size = av_image_get_buffer_size(frame->format, frame->width, frame->height, 1); if ((ret = av_new_packet(pkt, size)) < 0) - return ret; + goto fail; av_image_copy_to_buffer(pkt->data, size, (const uint8_t **)frame->data, frame->linesize, frame->format, frame->width, frame->height, 1); - } else if (frame->channels /* FIXME test audio */) { + } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { size = frame->nb_samples * av_get_bytes_per_sample(frame->format) * frame->channels; if ((ret = av_new_packet(pkt, size)) < 0) - return ret; + goto fail; memcpy(pkt->data, frame->data[0], size); } frame_metadata = frame->metadata; if (frame_metadata) { - uint8_t *metadata; - AVDictionaryEntry *e = NULL; - AVBPrint meta_buf; - - av_bprint_init(&meta_buf, 0, AV_BPRINT_SIZE_UNLIMITED); - while ((e = av_dict_get(frame_metadata, "", e, AV_DICT_IGNORE_SUFFIX))) { - av_bprintf(&meta_buf, "%s", e->key); - av_bprint_chars(&meta_buf, '\0', 1); - av_bprintf(&meta_buf, "%s", e->value); - av_bprint_chars(&meta_buf, '\0', 1); - } - if (!av_bprint_is_complete(&meta_buf) || - !(metadata = av_packet_new_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, - meta_buf.len))) { - av_bprint_finalize(&meta_buf, NULL); - return AVERROR(ENOMEM); + buffer_size_t size; + uint8_t *metadata = av_packet_pack_dictionary(frame_metadata, &size); + + if (!metadata) { + ret = AVERROR(ENOMEM); + goto fail; + } + if ((ret = av_packet_add_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, + metadata, size)) < 0) { + av_freep(&metadata); + goto fail; } - memcpy(metadata, meta_buf.str, meta_buf.len); - av_bprint_finalize(&meta_buf, NULL); } if ((ret = create_subcc_packet(avctx, frame, min_pts_sink_idx)) < 0) { - av_frame_unref(frame); - av_packet_unref(pkt); - return ret; + goto fail; } pkt->stream_index = stream_idx; pkt->pts = frame->pts; pkt->pos = frame->pkt_pos; - pkt->size = size; av_frame_unref(frame); return size; +fail: + av_frame_unref(frame); + return ret; + } #define OFFSET(x) offsetof(LavfiContext, x) diff -Nru ffmpeg-4.2.2/libavdevice/Makefile ffmpeg-4.4/libavdevice/Makefile --- ffmpeg-4.2.2/libavdevice/Makefile 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/Makefile 2021-04-08 21:28:39.000000000 +0000 @@ -15,6 +15,7 @@ OBJS-$(CONFIG_ALSA_INDEV) += alsa_dec.o alsa.o timefilter.o OBJS-$(CONFIG_ALSA_OUTDEV) += alsa_enc.o alsa.o OBJS-$(CONFIG_ANDROID_CAMERA_INDEV) += android_camera.o +OBJS-$(CONFIG_AUDIOTOOLBOX_OUTDEV) += audiotoolbox.o OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_CACA_OUTDEV) += caca.o diff -Nru ffmpeg-4.2.2/libavdevice/openal-dec.c ffmpeg-4.4/libavdevice/openal-dec.c --- ffmpeg-4.2.2/libavdevice/openal-dec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/openal-dec.c 2020-07-11 10:39:30.000000000 +0000 @@ -241,7 +241,7 @@ }; static const AVClass class = { - .class_name = "openal", + .class_name = "openal indev", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, diff -Nru ffmpeg-4.2.2/libavdevice/opengl_enc.c ffmpeg-4.4/libavdevice/opengl_enc.c --- ffmpeg-4.2.2/libavdevice/opengl_enc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/opengl_enc.c 2020-07-11 10:39:30.000000000 +0000 @@ -568,8 +568,9 @@ matrix[15] = 1.0f; } -static av_cold int opengl_read_limits(OpenGLContext *opengl) +static av_cold int opengl_read_limits(AVFormatContext *h) { + OpenGLContext *opengl = h->priv_data; static const struct{ const char *extension; int major; @@ -587,17 +588,21 @@ version = glGetString(GL_VERSION); extensions = glGetString(GL_EXTENSIONS); + if (!version || !extensions) { + av_log(h, AV_LOG_ERROR, "No OpenGL context initialized for the current thread\n"); + return AVERROR(ENOSYS); + } - av_log(opengl, AV_LOG_DEBUG, "OpenGL version: %s\n", version); + av_log(h, AV_LOG_DEBUG, "OpenGL version: %s\n", version); sscanf(version, "%d.%d", &major, &minor); for (i = 0; required_extensions[i].extension; i++) { if (major < required_extensions[i].major && (major == required_extensions[i].major && minor < required_extensions[i].minor) && !strstr(extensions, required_extensions[i].extension)) { - av_log(opengl, AV_LOG_ERROR, "Required extension %s is not supported.\n", + av_log(h, AV_LOG_ERROR, "Required extension %s is not supported.\n", required_extensions[i].extension); - av_log(opengl, AV_LOG_DEBUG, "Supported extensions are: %s\n", extensions); + av_log(h, AV_LOG_DEBUG, "Supported extensions are: %s\n", extensions); return AVERROR(ENOSYS); } } @@ -610,10 +615,10 @@ opengl->unpack_subimage = 1; #endif - av_log(opengl, AV_LOG_DEBUG, "Non Power of 2 textures support: %s\n", opengl->non_pow_2_textures ? "Yes" : "No"); - av_log(opengl, AV_LOG_DEBUG, "Unpack Subimage extension support: %s\n", opengl->unpack_subimage ? "Yes" : "No"); - av_log(opengl, AV_LOG_DEBUG, "Max texture size: %dx%d\n", opengl->max_texture_size, opengl->max_texture_size); - av_log(opengl, AV_LOG_DEBUG, "Max viewport size: %dx%d\n", + av_log(h, AV_LOG_DEBUG, "Non Power of 2 textures support: %s\n", opengl->non_pow_2_textures ? "Yes" : "No"); + av_log(h, AV_LOG_DEBUG, "Unpack Subimage extension support: %s\n", opengl->unpack_subimage ? "Yes" : "No"); + av_log(h, AV_LOG_DEBUG, "Max texture size: %dx%d\n", opengl->max_texture_size, opengl->max_texture_size); + av_log(h, AV_LOG_DEBUG, "Max viewport size: %dx%d\n", opengl->max_viewport_width, opengl->max_viewport_height); OPENGL_ERROR_CHECK(opengl); @@ -1050,13 +1055,14 @@ static av_cold int opengl_write_header(AVFormatContext *h) { OpenGLContext *opengl = h->priv_data; + AVCodecParameters *par = h->streams[0]->codecpar; AVStream *st; int ret; if (h->nb_streams != 1 || - h->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO || - h->streams[0]->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO) { - av_log(opengl, AV_LOG_ERROR, "Only a single video stream is supported.\n"); + par->codec_type != AVMEDIA_TYPE_VIDEO || + (par->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME && par->codec_id != AV_CODEC_ID_RAWVIDEO)) { + av_log(opengl, AV_LOG_ERROR, "Only a single raw or wrapped avframe video stream is supported.\n"); return AVERROR(EINVAL); } st = h->streams[0]; @@ -1074,7 +1080,7 @@ if ((ret = opengl_create_window(h))) goto fail; - if ((ret = opengl_read_limits(opengl)) < 0) + if ((ret = opengl_read_limits(h)) < 0) goto fail; if (opengl->width > opengl->max_texture_size || opengl->height > opengl->max_texture_size) { @@ -1251,7 +1257,13 @@ static int opengl_write_packet(AVFormatContext *h, AVPacket *pkt) { - return opengl_draw(h, pkt, 0, 1); + AVCodecParameters *par = h->streams[0]->codecpar; + if (par->codec_id == AV_CODEC_ID_WRAPPED_AVFRAME) { + AVFrame *frame = (AVFrame *)pkt->data; + return opengl_draw(h, frame, 0, 0); + } else { + return opengl_draw(h, pkt, 0, 1); + } } static int opengl_write_frame(AVFormatContext *h, int stream_index, @@ -1265,7 +1277,7 @@ #define OFFSET(x) offsetof(OpenGLContext, x) #define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "background", "set background color", OFFSET(background), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, ENC }, + { "background", "set background color", OFFSET(background), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, ENC }, { "no_window", "disable default window", OFFSET(no_window), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, ENC }, { "window_title", "set window title", OFFSET(window_title), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, ENC }, { "window_size", "set window size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, ENC }, @@ -1285,7 +1297,7 @@ .long_name = NULL_IF_CONFIG_SMALL("OpenGL output"), .priv_data_size = sizeof(OpenGLContext), .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, .write_header = opengl_write_header, .write_packet = opengl_write_packet, .write_uncoded_frame = opengl_write_frame, diff -Nru ffmpeg-4.2.2/libavdevice/oss_dec.c ffmpeg-4.4/libavdevice/oss_dec.c --- ffmpeg-4.2.2/libavdevice/oss_dec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/oss_dec.c 2020-07-11 10:39:30.000000000 +0000 @@ -125,7 +125,7 @@ }; static const AVClass oss_demuxer_class = { - .class_name = "OSS demuxer", + .class_name = "OSS indev", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, diff -Nru ffmpeg-4.2.2/libavdevice/oss_enc.c ffmpeg-4.4/libavdevice/oss_enc.c --- ffmpeg-4.2.2/libavdevice/oss_enc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/oss_enc.c 2020-07-11 10:39:30.000000000 +0000 @@ -90,7 +90,7 @@ } static const AVClass oss_muxer_class = { - .class_name = "OSS muxer", + .class_name = "OSS outdev", .item_name = av_default_item_name, .version = LIBAVUTIL_VERSION_INT, .category = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, diff -Nru ffmpeg-4.2.2/libavdevice/pulse_audio_dec.c ffmpeg-4.4/libavdevice/pulse_audio_dec.c --- ffmpeg-4.2.2/libavdevice/pulse_audio_dec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/pulse_audio_dec.c 2021-04-08 21:28:39.000000000 +0000 @@ -48,6 +48,7 @@ pa_threaded_mainloop *mainloop; pa_context *context; pa_stream *stream; + size_t pa_frame_size; TimeFilter *timefilter; int last_period; @@ -149,6 +150,7 @@ pa_buffer_attr attr = { -1 }; pa_channel_map cmap; + const pa_buffer_attr *queried_attr; pa_channel_map_init_extend(&cmap, pd->channels, PA_CHANNEL_MAP_WAVEEX); @@ -217,7 +219,7 @@ ret = pa_stream_connect_record(pd->stream, device, &attr, PA_STREAM_INTERPOLATE_TIMING - |PA_STREAM_ADJUST_LATENCY + | (pd->fragment_size == -1 ? PA_STREAM_ADJUST_LATENCY : 0) |PA_STREAM_AUTO_TIMING_UPDATE); if (ret < 0) { @@ -242,6 +244,15 @@ pa_threaded_mainloop_wait(pd->mainloop); } + /* Query actual fragment size */ + queried_attr = pa_stream_get_buffer_attr(pd->stream); + if (!queried_attr || queried_attr->fragsize > INT_MAX/100) { + ret = AVERROR_EXTERNAL; + goto unlock_and_fail; + } + pd->fragment_size = queried_attr->fragsize; + pd->pa_frame_size = pa_frame_size(&ss); + pa_threaded_mainloop_unlock(pd->mainloop); /* take real parameters */ @@ -252,7 +263,7 @@ avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ pd->timefilter = ff_timefilter_new(1000000.0 / pd->sample_rate, - 1000, 1.5E-6); + pd->fragment_size / pd->pa_frame_size, 1.5E-6); if (!pd->timefilter) { pulse_close(s); @@ -277,12 +288,13 @@ int64_t dts; pa_usec_t latency; int negative; + ptrdiff_t pos = 0; pa_threaded_mainloop_lock(pd->mainloop); CHECK_DEAD_GOTO(pd, ret, unlock_and_fail); - while (!read_data) { + while (pos < pd->fragment_size) { int r; r = pa_stream_peek(pd->stream, &read_data, &read_length); @@ -296,43 +308,51 @@ * silence, but that wouldn't work for compressed streams. */ r = pa_stream_drop(pd->stream); CHECK_SUCCESS_GOTO(ret, r == 0, unlock_and_fail); + } else { + if (!pos) { + if (av_new_packet(pkt, pd->fragment_size) < 0) { + ret = AVERROR(ENOMEM); + goto unlock_and_fail; + } + + dts = av_gettime(); + pa_operation_unref(pa_stream_update_timing_info(pd->stream, NULL, NULL)); + + if (pa_stream_get_latency(pd->stream, &latency, &negative) >= 0) { + if (negative) { + dts += latency; + } else + dts -= latency; + } else { + av_log(s, AV_LOG_WARNING, "pa_stream_get_latency() failed\n"); + } + } + if (pkt->size - pos < read_length) { + if (pos) + break; + pa_stream_drop(pd->stream); + /* Oversized fragment??? */ + ret = AVERROR_EXTERNAL; + goto unlock_and_fail; + } + memcpy(pkt->data + pos, read_data, read_length); + pos += read_length; + pa_stream_drop(pd->stream); } } - if (av_new_packet(pkt, read_length) < 0) { - ret = AVERROR(ENOMEM); - goto unlock_and_fail; - } - - dts = av_gettime(); - pa_operation_unref(pa_stream_update_timing_info(pd->stream, NULL, NULL)); + pa_threaded_mainloop_unlock(pd->mainloop); - if (pa_stream_get_latency(pd->stream, &latency, &negative) >= 0) { - enum AVCodecID codec_id = - s->audio_codec_id == AV_CODEC_ID_NONE ? DEFAULT_CODEC_ID : s->audio_codec_id; - int frame_size = ((av_get_bits_per_sample(codec_id) >> 3) * pd->channels); - int frame_duration = read_length / frame_size; - - - if (negative) { - dts += latency; - } else - dts -= latency; - if (pd->wallclock) - pkt->pts = ff_timefilter_update(pd->timefilter, dts, pd->last_period); - - pd->last_period = frame_duration; - } else { - av_log(s, AV_LOG_WARNING, "pa_stream_get_latency() failed\n"); - } + av_shrink_packet(pkt, pos); - memcpy(pkt->data, read_data, read_length); - pa_stream_drop(pd->stream); + if (pd->wallclock) + pkt->pts = ff_timefilter_update(pd->timefilter, dts, pd->last_period); + pd->last_period = pkt->size / pd->pa_frame_size; - pa_threaded_mainloop_unlock(pd->mainloop); return 0; unlock_and_fail: + av_packet_unref(pkt); pa_threaded_mainloop_unlock(pd->mainloop); return ret; } @@ -359,7 +379,7 @@ }; static const AVClass pulse_demuxer_class = { - .class_name = "Pulse demuxer", + .class_name = "Pulse indev", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, diff -Nru ffmpeg-4.2.2/libavdevice/pulse_audio_enc.c ffmpeg-4.4/libavdevice/pulse_audio_enc.c --- ffmpeg-4.2.2/libavdevice/pulse_audio_enc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/pulse_audio_enc.c 2020-07-11 10:39:30.000000000 +0000 @@ -771,7 +771,7 @@ }; static const AVClass pulse_muxer_class = { - .class_name = "PulseAudio muxer", + .class_name = "PulseAudio outdev", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, diff -Nru ffmpeg-4.2.2/libavdevice/timefilter.h ffmpeg-4.4/libavdevice/timefilter.h --- ffmpeg-4.2.2/libavdevice/timefilter.h 2016-03-29 02:25:26.000000000 +0000 +++ ffmpeg-4.4/libavdevice/timefilter.h 2021-04-08 21:28:39.000000000 +0000 @@ -39,16 +39,6 @@ /** * Create a new Delay Locked Loop time filter * - * feedback2_factor and feedback3_factor are the factors used for the - * multiplications that are respectively performed in the second and third - * feedback paths of the loop. - * - * Unless you know what you are doing, you should set these as follow: - * - * o = 2 * M_PI * bandwidth * period_in_seconds - * feedback2_factor = sqrt(2) * o - * feedback3_factor = o * o - * * Where bandwidth is up to you to choose. Smaller values will filter out more * of the jitter, but also take a longer time for the loop to settle. A good * starting point is something between 0.3 and 3 Hz. @@ -59,11 +49,8 @@ * @param brandwidth filtering bandwidth, in Hz * * @return a pointer to a TimeFilter struct, or NULL on error - * - * For more details about these parameters and background concepts please see: - * http://www.kokkinizita.net/papers/usingdll.pdf */ -TimeFilter * ff_timefilter_new(double clock_period, double feedback2_factor, double feedback3_factor); +TimeFilter * ff_timefilter_new(double time_base, double period, double bandwidth); /** * Update the filter diff -Nru ffmpeg-4.2.2/libavdevice/v4l2.c ffmpeg-4.4/libavdevice/v4l2.c --- ffmpeg-4.2.2/libavdevice/v4l2.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/v4l2.c 2020-07-11 10:39:30.000000000 +0000 @@ -538,11 +538,10 @@ s->frame_size = buf.bytesused; if (s->frame_size > 0 && buf.bytesused != s->frame_size) { - av_log(ctx, AV_LOG_ERROR, + av_log(ctx, AV_LOG_WARNING, "Dequeued v4l2 buffer contains %d bytes, but %d were expected. Flags: 0x%08X.\n", buf.bytesused, s->frame_size, buf.flags); - enqueue_buffer(s, &buf); - return AVERROR_INVALIDDATA; + buf.bytesused = 0; } } @@ -812,7 +811,8 @@ } *codec_id = ff_fmt_v4l2codec(*desired_format); - av_assert0(*codec_id != AV_CODEC_ID_NONE); + if (*codec_id == AV_CODEC_ID_NONE) + av_assert0(ret == AVERROR(EINVAL)); return ret; } diff -Nru ffmpeg-4.2.2/libavdevice/v4l2enc.c ffmpeg-4.4/libavdevice/v4l2enc.c --- ffmpeg-4.2.2/libavdevice/v4l2enc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/v4l2enc.c 2020-07-11 10:39:30.000000000 +0000 @@ -47,8 +47,7 @@ } if (s1->nb_streams != 1 || - s1->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO || - s1->streams[0]->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO) { + s1->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) { av_log(s1, AV_LOG_ERROR, "V4L2 output device supports only a single raw video stream\n"); return AVERROR(EINVAL); @@ -56,7 +55,12 @@ par = s1->streams[0]->codecpar; - v4l2_pixfmt = ff_fmt_ff2v4l(par->format, AV_CODEC_ID_RAWVIDEO); + if(par->codec_id == AV_CODEC_ID_RAWVIDEO) { + v4l2_pixfmt = ff_fmt_ff2v4l(par->format, AV_CODEC_ID_RAWVIDEO); + } else { + v4l2_pixfmt = ff_fmt_ff2v4l(AV_PIX_FMT_NONE, par->codec_id); + } + if (!v4l2_pixfmt) { // XXX: try to force them one by one? av_log(s1, AV_LOG_ERROR, "Unknown V4L2 pixel format equivalent for %s\n", av_get_pix_fmt_name(par->format)); diff -Nru ffmpeg-4.2.2/libavdevice/version.h ffmpeg-4.4/libavdevice/version.h --- ffmpeg-4.2.2/libavdevice/version.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/version.h 2021-04-08 21:28:39.000000000 +0000 @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 58 -#define LIBAVDEVICE_VERSION_MINOR 8 +#define LIBAVDEVICE_VERSION_MINOR 13 #define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ @@ -46,5 +46,8 @@ * 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 -Nru ffmpeg-4.2.2/libavdevice/vfwcap.c ffmpeg-4.4/libavdevice/vfwcap.c --- ffmpeg-4.2.2/libavdevice/vfwcap.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/vfwcap.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavutil/opt.h" #include "libavutil/parseutils.h" +#include "libavcodec/packet_internal.h" #include "libavformat/internal.h" // windows.h must no be included before winsock2.h, and libavformat internal @@ -44,7 +45,7 @@ HWND hwnd; HANDLE mutex; HANDLE event; - AVPacketList *pktl; + PacketList *pktl; unsigned int curbufsize; unsigned int frame_num; char *video_size; /**< A string describing video size, set by a private option. */ @@ -178,7 +179,7 @@ { AVFormatContext *s; struct vfw_ctx *ctx; - AVPacketList **ppktl, *pktl_next; + PacketList **ppktl, *pktl_next; s = (AVFormatContext *) GetWindowLongPtr(hwnd, GWLP_USERDATA); ctx = s->priv_data; @@ -190,7 +191,7 @@ WaitForSingleObject(ctx->mutex, INFINITE); - pktl_next = av_mallocz(sizeof(AVPacketList)); + pktl_next = av_mallocz(sizeof(PacketList)); if(!pktl_next) goto fail; @@ -219,7 +220,7 @@ static int vfw_read_close(AVFormatContext *s) { struct vfw_ctx *ctx = s->priv_data; - AVPacketList *pktl; + PacketList *pktl; if(ctx->hwnd) { SendMessage(ctx->hwnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0); @@ -233,7 +234,7 @@ pktl = ctx->pktl; while (pktl) { - AVPacketList *next = pktl->next; + PacketList *next = pktl->next; av_packet_unref(&pktl->pkt); av_free(pktl); pktl = next; @@ -439,7 +440,7 @@ static int vfw_read_packet(AVFormatContext *s, AVPacket *pkt) { struct vfw_ctx *ctx = s->priv_data; - AVPacketList *pktl = NULL; + PacketList *pktl = NULL; while(!pktl) { WaitForSingleObject(ctx->mutex, INFINITE); diff -Nru ffmpeg-4.2.2/libavdevice/xcbgrab.c ffmpeg-4.4/libavdevice/xcbgrab.c --- ffmpeg-4.2.2/libavdevice/xcbgrab.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/xcbgrab.c 2021-04-08 21:28:39.000000000 +0000 @@ -22,6 +22,7 @@ #include "config.h" #include +#include #include #if CONFIG_LIBXCB_XFIXES @@ -49,17 +50,17 @@ typedef struct XCBGrabContext { const AVClass *class; - uint8_t *buffer; - xcb_connection_t *conn; xcb_screen_t *screen; xcb_window_t window; #if CONFIG_LIBXCB_SHM - xcb_shm_seg_t segment; + AVBufferPool *shm_pool; #endif int64_t time_frame; AVRational time_base; + int64_t frame_duration; + xcb_window_t window_id; int x, y; int width, height; int frame_size; @@ -70,8 +71,8 @@ int show_region; int region_border; int centered; + int select_region; - const char *video_size; const char *framerate; int has_shm; @@ -82,11 +83,12 @@ #define OFFSET(x) offsetof(XCBGrabContext, x) #define D AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { + { "window_id", "Window to capture.", OFFSET(window_id), AV_OPT_TYPE_INT, { .i64 = XCB_NONE }, 0, UINT32_MAX, D }, { "x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, { "y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, { "grab_x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, { "grab_y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, - { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = "vga" }, 0, 0, D }, + { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL }, 0, 0, D }, { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "ntsc" }, 0, 0, D }, { "draw_mouse", "Draw the mouse pointer.", OFFSET(draw_mouse), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, D }, { "follow_mouse", "Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.", @@ -94,6 +96,7 @@ { "centered", "Keep the mouse pointer at the center of grabbing region when following.", 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, D, "follow_mouse" }, { "show_region", "Show the grabbing region.", OFFSET(show_region), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D }, { "region_border", "Set the region border thickness.", OFFSET(region_border), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 128, D }, + { "select_region", "Select the grabbing region graphically using the pointer.", OFFSET(select_region), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D }, { NULL }, }; @@ -146,15 +149,20 @@ return 0; } +static void xcbgrab_image_reply_free(void *opaque, uint8_t *data) +{ + free(opaque); +} + static int xcbgrab_frame(AVFormatContext *s, AVPacket *pkt) { XCBGrabContext *c = s->priv_data; xcb_get_image_cookie_t iq; xcb_get_image_reply_t *img; - xcb_drawable_t drawable = c->screen->root; + xcb_drawable_t drawable = c->window_id; xcb_generic_error_t *e = NULL; uint8_t *data; - int length, ret; + int length; iq = xcb_get_image(c->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable, c->x, c->y, c->width, c->height, ~0); @@ -168,6 +176,7 @@ "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n", e->response_type, e->error_code, e->sequence, e->resource_id, e->minor_code, e->major_code); + free(e); return AVERROR(EACCES); } @@ -177,33 +186,34 @@ data = xcb_get_image_data(img); length = xcb_get_image_data_length(img); - ret = av_new_packet(pkt, length); - - if (!ret) - memcpy(pkt->data, data, length); + pkt->buf = av_buffer_create(data, length, xcbgrab_image_reply_free, img, 0); + if (!pkt->buf) { + free(img); + return AVERROR(ENOMEM); + } - free(img); + pkt->data = data; + pkt->size = length; - return ret; + return 0; } -static void wait_frame(AVFormatContext *s, AVPacket *pkt) +static int64_t wait_frame(AVFormatContext *s, AVPacket *pkt) { XCBGrabContext *c = s->priv_data; int64_t curtime, delay; - int64_t frame_time = av_rescale_q(1, c->time_base, AV_TIME_BASE_Q); - c->time_frame += frame_time; + c->time_frame += c->frame_duration; for (;;) { - curtime = av_gettime(); + curtime = av_gettime_relative(); delay = c->time_frame - curtime; if (delay <= 0) break; av_usleep(delay); } - pkt->pts = curtime; + return curtime; } #if CONFIG_LIBXCB_SHM @@ -221,31 +231,35 @@ return 0; } -static int allocate_shm(AVFormatContext *s) +static void free_shm_buffer(void *opaque, uint8_t *data) { - XCBGrabContext *c = s->priv_data; - int size = c->frame_size + AV_INPUT_BUFFER_PADDING_SIZE; + shmdt(data); +} + +static AVBufferRef *allocate_shm_buffer(void *opaque, buffer_size_t size) +{ + xcb_connection_t *conn = opaque; + xcb_shm_seg_t segment; + AVBufferRef *ref; uint8_t *data; int id; - if (c->buffer) - return 0; id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777); - if (id == -1) { - char errbuf[1024]; - int err = AVERROR(errno); - av_strerror(err, errbuf, sizeof(errbuf)); - av_log(s, AV_LOG_ERROR, "Cannot get %d bytes of shared memory: %s.\n", - size, errbuf); - return err; - } - xcb_shm_attach(c->conn, c->segment, id, 0); + if (id == -1) + return NULL; + + segment = xcb_generate_id(conn); + xcb_shm_attach(conn, segment, id, 0); data = shmat(id, NULL, 0); shmctl(id, IPC_RMID, 0); if ((intptr_t)data == -1 || !data) - return AVERROR(errno); - c->buffer = data; - return 0; + return NULL; + + ref = av_buffer_create(data, size, free_shm_buffer, (void *)(ptrdiff_t)segment, 0); + if (!ref) + shmdt(data); + + return ref; } static int xcbgrab_frame_shm(AVFormatContext *s, AVPacket *pkt) @@ -253,17 +267,21 @@ XCBGrabContext *c = s->priv_data; xcb_shm_get_image_cookie_t iq; xcb_shm_get_image_reply_t *img; - xcb_drawable_t drawable = c->screen->root; + xcb_drawable_t drawable = c->window_id; xcb_generic_error_t *e = NULL; - int ret; + AVBufferRef *buf; + xcb_shm_seg_t segment; - ret = allocate_shm(s); - if (ret < 0) - return ret; + buf = av_buffer_pool_get(c->shm_pool); + if (!buf) { + 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); iq = xcb_shm_get_image(c->conn, drawable, c->x, c->y, c->width, c->height, ~0, - XCB_IMAGE_FORMAT_Z_PIXMAP, c->segment, 0); + XCB_IMAGE_FORMAT_Z_PIXMAP, segment, 0); img = xcb_shm_get_image_reply(c->conn, iq, &e); xcb_flush(c->conn); @@ -276,12 +294,15 @@ e->response_type, e->error_code, e->sequence, e->resource_id, e->minor_code, e->major_code); + free(e); + av_buffer_unref(&buf); return AVERROR(EACCES); } free(img); - pkt->data = c->buffer; + pkt->buf = buf; + pkt->data = buf->data; pkt->size = c->frame_size; return 0; @@ -310,7 +331,8 @@ static void xcbgrab_draw_mouse(AVFormatContext *s, AVPacket *pkt, xcb_query_pointer_reply_t *p, - xcb_get_geometry_reply_t *geo) + xcb_get_geometry_reply_t *geo, + int win_x, int win_y) { XCBGrabContext *gr = s->priv_data; uint32_t *cursor; @@ -332,17 +354,17 @@ cx = ci->x - ci->xhot; cy = ci->y - ci->yhot; - x = FFMAX(cx, gr->x); - y = FFMAX(cy, gr->y); + x = FFMAX(cx, win_x + gr->x); + y = FFMAX(cy, win_y + gr->y); - w = FFMIN(cx + ci->width, gr->x + gr->width) - x; - h = FFMIN(cy + ci->height, gr->y + gr->height) - y; + w = FFMIN(cx + ci->width, win_x + gr->x + gr->width) - x; + h = FFMIN(cy + ci->height, win_y + gr->y + gr->height) - y; c_off = x - cx; - i_off = x - gr->x; + i_off = x - gr->x - win_x; cursor += (y - cy) * ci->width; - image += (y - gr->y) * gr->width * stride; + image += (y - gr->y - win_y) * gr->width * stride; for (y = 0; y < h; y++) { cursor += c_off; @@ -377,11 +399,11 @@ } #endif /* CONFIG_LIBXCB_XFIXES */ -static void xcbgrab_update_region(AVFormatContext *s) +static void xcbgrab_update_region(AVFormatContext *s, int win_x, int win_y) { XCBGrabContext *c = s->priv_data; - const uint32_t args[] = { c->x - c->region_border, - c->y - c->region_border }; + const uint32_t args[] = { win_x + c->x - c->region_border, + win_y + c->y - c->region_border }; xcb_configure_window(c->conn, c->window, @@ -394,35 +416,66 @@ XCBGrabContext *c = s->priv_data; xcb_query_pointer_cookie_t pc; xcb_get_geometry_cookie_t gc; + xcb_translate_coordinates_cookie_t tc; xcb_query_pointer_reply_t *p = NULL; xcb_get_geometry_reply_t *geo = NULL; + xcb_translate_coordinates_reply_t *translate = NULL; int ret = 0; + int64_t pts; + int win_x = 0, win_y = 0; wait_frame(s, pkt); + pts = av_gettime(); if (c->follow_mouse || c->draw_mouse) { - pc = xcb_query_pointer(c->conn, c->screen->root); - gc = xcb_get_geometry(c->conn, c->screen->root); + pc = xcb_query_pointer(c->conn, c->window_id); + gc = xcb_get_geometry(c->conn, c->window_id); p = xcb_query_pointer_reply(c->conn, pc, NULL); + if (!p) { + av_log(s, AV_LOG_ERROR, "Failed to query xcb pointer\n"); + return AVERROR_EXTERNAL; + } geo = xcb_get_geometry_reply(c->conn, gc, NULL); + if (!geo) { + av_log(s, AV_LOG_ERROR, "Failed to get xcb geometry\n"); + free(p); + return AVERROR_EXTERNAL; + } + } + if (c->window_id != c->screen->root) { + tc = xcb_translate_coordinates(c->conn, c->window_id, c->screen->root, 0, 0); + translate = xcb_translate_coordinates_reply(c->conn, tc, NULL); + if (!translate) { + free(p); + free(geo); + av_log(s, AV_LOG_ERROR, "Failed to translate xcb geometry\n"); + return AVERROR_EXTERNAL; + } + win_x = translate->dst_x; + win_y = translate->dst_y; + free(translate); } if (c->follow_mouse && p->same_screen) xcbgrab_reposition(s, p, geo); if (c->show_region) - xcbgrab_update_region(s); + xcbgrab_update_region(s, win_x, win_y); #if CONFIG_LIBXCB_SHM - if (c->has_shm && xcbgrab_frame_shm(s, pkt) < 0) + if (c->has_shm && xcbgrab_frame_shm(s, pkt) < 0) { + av_log(s, AV_LOG_WARNING, "Continuing without shared memory.\n"); c->has_shm = 0; + } #endif if (!c->has_shm) ret = xcbgrab_frame(s, pkt); + pkt->dts = pkt->pts = pts; + pkt->duration = c->frame_duration; #if CONFIG_LIBXCB_XFIXES if (ret >= 0 && c->draw_mouse && p->same_screen) - xcbgrab_draw_mouse(s, pkt, p, geo); + xcbgrab_draw_mouse(s, pkt, p, geo, win_x, win_y); #endif free(p); @@ -436,9 +489,7 @@ XCBGrabContext *ctx = s->priv_data; #if CONFIG_LIBXCB_SHM - if (ctx->buffer) { - shmdt(ctx->buffer); - } + av_buffer_pool_uninit(&ctx->shm_pool); #endif xcb_disconnect(ctx->conn); @@ -464,7 +515,7 @@ } static int pixfmt_from_pixmap_format(AVFormatContext *s, int depth, - int *pix_fmt) + int *pix_fmt, int *bpp) { XCBGrabContext *c = s->priv_data; const xcb_setup_t *setup = xcb_get_setup(c->conn); @@ -478,21 +529,26 @@ switch (depth) { case 32: if (fmt->bits_per_pixel == 32) - *pix_fmt = AV_PIX_FMT_0RGB; + *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ? + AV_PIX_FMT_BGR0 : AV_PIX_FMT_0RGB; break; case 24: if (fmt->bits_per_pixel == 32) - *pix_fmt = AV_PIX_FMT_0RGB32; + *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ? + AV_PIX_FMT_BGR0 : AV_PIX_FMT_0RGB; else if (fmt->bits_per_pixel == 24) - *pix_fmt = AV_PIX_FMT_RGB24; + *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ? + AV_PIX_FMT_BGR24 : AV_PIX_FMT_RGB24; break; case 16: if (fmt->bits_per_pixel == 16) - *pix_fmt = AV_PIX_FMT_RGB565; + *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ? + AV_PIX_FMT_RGB565LE : AV_PIX_FMT_RGB565BE; break; case 15: if (fmt->bits_per_pixel == 16) - *pix_fmt = AV_PIX_FMT_RGB555; + *pix_fmt = setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST ? + AV_PIX_FMT_RGB555LE : AV_PIX_FMT_RGB555BE; break; case 8: if (fmt->bits_per_pixel == 8) @@ -502,8 +558,7 @@ } if (*pix_fmt) { - c->bpp = fmt->bits_per_pixel; - c->frame_size = c->width * c->height * fmt->bits_per_pixel / 8; + *bpp = fmt->bits_per_pixel; return 0; } @@ -520,23 +575,29 @@ AVStream *st = avformat_new_stream(s, NULL); xcb_get_geometry_cookie_t gc; xcb_get_geometry_reply_t *geo; + int64_t frame_size_bits; int ret; if (!st) return AVERROR(ENOMEM); - ret = av_parse_video_size(&c->width, &c->height, c->video_size); - if (ret < 0) - return ret; - ret = av_parse_video_rate(&st->avg_frame_rate, c->framerate); if (ret < 0) return ret; avpriv_set_pts_info(st, 64, 1, 1000000); - gc = xcb_get_geometry(c->conn, c->screen->root); + gc = xcb_get_geometry(c->conn, c->window_id); geo = xcb_get_geometry_reply(c->conn, gc, NULL); + if (!geo) { + av_log(s, AV_LOG_ERROR, "Can't find window '0x%x', aborting.\n", c->window_id); + return AVERROR_EXTERNAL; + } + + if (!c->width || !c->height) { + c->width = geo->width; + c->height = geo->height; + } if (c->x + c->width > geo->width || c->y + c->height > geo->height) { @@ -546,21 +607,39 @@ c->width, c->height, c->x, c->y, geo->width, geo->height); + free(geo); return AVERROR(EINVAL); } c->time_base = (AVRational){ st->avg_frame_rate.den, st->avg_frame_rate.num }; - c->time_frame = av_gettime(); + c->frame_duration = av_rescale_q(1, c->time_base, AV_TIME_BASE_Q); + c->time_frame = av_gettime_relative(); + + ret = pixfmt_from_pixmap_format(s, geo->depth, &st->codecpar->format, &c->bpp); + free(geo); + if (ret < 0) + return ret; + + frame_size_bits = (int64_t)c->width * c->height * c->bpp; + if (frame_size_bits / 8 + AV_INPUT_BUFFER_PADDING_SIZE > INT_MAX) { + av_log(s, AV_LOG_ERROR, "Captured area is too large\n"); + return AVERROR_PATCHWELCOME; + } + c->frame_size = frame_size_bits / 8; + +#if CONFIG_LIBXCB_SHM + c->shm_pool = av_buffer_pool_init2(c->frame_size + AV_INPUT_BUFFER_PADDING_SIZE, + c->conn, allocate_shm_buffer, NULL); + if (!c->shm_pool) + return AVERROR(ENOMEM); +#endif st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; st->codecpar->width = c->width; st->codecpar->height = c->height; - - ret = pixfmt_from_pixmap_format(s, geo->depth, &st->codecpar->format); - - free(geo); + st->codecpar->bit_rate = av_rescale(frame_size_bits, st->avg_frame_rate.num, st->avg_frame_rate.den); return ret; } @@ -624,6 +703,117 @@ draw_rectangle(s); } +#define CROSSHAIR_CURSOR 34 + +static xcb_rectangle_t rectangle_from_corners(xcb_point_t *corner_a, + xcb_point_t *corner_b) +{ + xcb_rectangle_t rectangle; + rectangle.x = FFMIN(corner_a->x, corner_b->x); + rectangle.y = FFMIN(corner_a->y, corner_b->y); + rectangle.width = FFABS(corner_a->x - corner_b->x); + rectangle.height = FFABS(corner_a->y - corner_b->y); + return rectangle; +} + +static int select_region(AVFormatContext *s) +{ + XCBGrabContext *c = s->priv_data; + xcb_connection_t *conn = c->conn; + xcb_screen_t *screen = c->screen; + + int ret = 0, done = 0, was_pressed = 0; + xcb_cursor_t cursor; + xcb_font_t cursor_font; + xcb_point_t press_position; + xcb_generic_event_t *event; + xcb_rectangle_t rectangle = { 0 }; + xcb_grab_pointer_reply_t *reply; + xcb_grab_pointer_cookie_t cookie; + + xcb_window_t root_window = screen->root; + xcb_gcontext_t gc = xcb_generate_id(conn); + uint32_t mask = XCB_GC_FUNCTION | XCB_GC_SUBWINDOW_MODE; + uint32_t values[] = { XCB_GX_INVERT, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS }; + xcb_create_gc(conn, gc, root_window, mask, values); + + cursor_font = xcb_generate_id(conn); + xcb_open_font(conn, cursor_font, strlen("cursor"), "cursor"); + cursor = xcb_generate_id(conn); + xcb_create_glyph_cursor(conn, cursor, cursor_font, cursor_font, + CROSSHAIR_CURSOR, CROSSHAIR_CURSOR + 1, 0, 0, 0, + 0xFFFF, 0xFFFF, 0xFFFF); + cookie = xcb_grab_pointer(conn, 0, root_window, + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_BUTTON_MOTION, + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, + root_window, cursor, XCB_CURRENT_TIME); + reply = xcb_grab_pointer_reply(conn, cookie, NULL); + if (!reply || reply->status != XCB_GRAB_STATUS_SUCCESS) { + av_log(s, AV_LOG_ERROR, + "Failed to select region. Could not grab pointer.\n"); + ret = AVERROR(EIO); + free(reply); + goto fail; + } + free(reply); + + xcb_grab_server(conn); + + while (!done && (event = xcb_wait_for_event(conn))) { + switch (event->response_type & ~0x80) { + case XCB_BUTTON_PRESS: { + xcb_button_press_event_t *press = (xcb_button_press_event_t *)event; + press_position = (xcb_point_t){ press->event_x, press->event_y }; + rectangle.x = press_position.x; + rectangle.y = press_position.y; + xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle); + was_pressed = 1; + break; + } + case XCB_MOTION_NOTIFY: { + if (was_pressed) { + xcb_motion_notify_event_t *motion = + (xcb_motion_notify_event_t *)event; + xcb_point_t cursor_position = { motion->event_x, motion->event_y }; + xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle); + rectangle = rectangle_from_corners(&press_position, &cursor_position); + xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle); + } + break; + } + case XCB_BUTTON_RELEASE: { + xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle); + done = 1; + break; + } + default: + break; + } + xcb_flush(conn); + free(event); + } + c->width = rectangle.width; + c->height = rectangle.height; + if (c->width && c->height) { + c->x = rectangle.x; + c->y = rectangle.y; + } else { + c->x = 0; + c->y = 0; + } + xcb_ungrab_server(conn); + xcb_ungrab_pointer(conn, XCB_CURRENT_TIME); + xcb_flush(conn); + +fail: + xcb_free_cursor(conn, cursor); + xcb_close_font(conn, cursor_font); + xcb_free_gc(conn, gc); + return ret; +} + static av_cold int xcbgrab_read_header(AVFormatContext *s) { XCBGrabContext *c = s->priv_data; @@ -658,6 +848,27 @@ return AVERROR(EIO); } + if (c->window_id == XCB_NONE) + c->window_id = c->screen->root; + else { + if (c->select_region) { + av_log(s, AV_LOG_WARNING, "select_region ignored with window_id.\n"); + c->select_region = 0; + } + if (c->follow_mouse) { + av_log(s, AV_LOG_WARNING, "follow_mouse ignored with window_id.\n"); + c->follow_mouse = 0; + } + } + + if (c->select_region) { + ret = select_region(s); + if (ret < 0) { + xcbgrab_read_close(s); + return ret; + } + } + ret = create_stream(s); if (ret < 0) { @@ -666,8 +877,7 @@ } #if CONFIG_LIBXCB_SHM - if ((c->has_shm = check_shm(c->conn))) - c->segment = xcb_generate_id(c->conn); + c->has_shm = check_shm(c->conn); #endif #if CONFIG_LIBXCB_XFIXES diff -Nru ffmpeg-4.2.2/libavdevice/xv.c ffmpeg-4.4/libavdevice/xv.c --- ffmpeg-4.2.2/libavdevice/xv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavdevice/xv.c 2020-07-11 10:39:30.000000000 +0000 @@ -113,8 +113,8 @@ if ( s->nb_streams > 1 || par->codec_type != AVMEDIA_TYPE_VIDEO - || par->codec_id != AV_CODEC_ID_RAWVIDEO) { - av_log(s, AV_LOG_ERROR, "Only supports one rawvideo stream\n"); + || (par->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME && par->codec_id != AV_CODEC_ID_RAWVIDEO)) { + av_log(s, AV_LOG_ERROR, "Only a single raw or wrapped avframe video stream is supported.\n"); return AVERROR(EINVAL); } @@ -322,12 +322,18 @@ static int xv_write_packet(AVFormatContext *s, AVPacket *pkt) { AVCodecParameters *par = s->streams[0]->codecpar; - uint8_t *data[4]; - int linesize[4]; - av_image_fill_arrays(data, linesize, pkt->data, par->format, - par->width, par->height, 1); - return write_picture(s, data, linesize); + if (par->codec_id == AV_CODEC_ID_WRAPPED_AVFRAME) { + AVFrame *frame = (AVFrame *)pkt->data; + return write_picture(s, frame->data, frame->linesize); + } else { + uint8_t *data[4]; + int linesize[4]; + + av_image_fill_arrays(data, linesize, pkt->data, par->format, + par->width, par->height, 1); + return write_picture(s, data, linesize); + } } static int xv_write_frame(AVFormatContext *s, int stream_index, AVFrame **frame, @@ -375,7 +381,7 @@ .long_name = NULL_IF_CONFIG_SMALL("XV (XVideo) output device"), .priv_data_size = sizeof(XVContext), .audio_codec = AV_CODEC_ID_NONE, - .video_codec = AV_CODEC_ID_RAWVIDEO, + .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, .write_header = xv_write_header, .write_packet = xv_write_packet, .write_uncoded_frame = xv_write_frame, diff -Nru ffmpeg-4.2.2/libavfilter/aeval.c ffmpeg-4.4/libavfilter/aeval.c --- ffmpeg-4.2.2/libavfilter/aeval.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/aeval.c 2021-04-08 21:28:39.000000000 +0000 @@ -89,8 +89,8 @@ { "exprs", "set the '|'-separated list of channels expressions", OFFSET(exprs), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = FLAGS }, { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX, FLAGS }, { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX, FLAGS }, - { "sample_rate", "set the sample rate", OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "s", "set the sample rate", OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "sample_rate", "set the sample rate", OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, 0, 0, FLAGS }, + { "s", "set the sample rate", OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, 0, 0, FLAGS }, { "duration", "set audio duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS }, { "d", "set audio duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS }, { "channel_layout", "set channel layout", OFFSET(chlayout_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, @@ -258,7 +258,7 @@ if (ret < 0) return ret; - layouts = avfilter_make_format64_list(chlayouts); + layouts = ff_make_format64_list(chlayouts); if (!layouts) return AVERROR(ENOMEM); ret = ff_set_common_channel_layouts(ctx, layouts); @@ -362,7 +362,7 @@ // inlink supports any channel layout layouts = ff_all_channel_counts(); - if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; if (eval->same_chlayout) { @@ -376,7 +376,7 @@ eval->out_channel_layout ? eval->out_channel_layout : FF_COUNT2LAYOUT(eval->nb_channels))) < 0) return ret; - if ((ret = ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &outlink->incfg.channel_layouts)) < 0) return ret; } @@ -416,8 +416,6 @@ return 0; } -#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb)) - static int filter_frame(AVFilterLink *inlink, AVFrame *in) { EvalContext *eval = inlink->dst->priv; @@ -485,6 +483,7 @@ .inputs = aeval_inputs, .outputs = aeval_outputs, .priv_class = &aeval_class, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; #endif /* CONFIG_AEVAL_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/af_acopy.c ffmpeg-4.4/libavfilter/af_acopy.c --- ffmpeg-4.2.2/libavfilter/af_acopy.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_acopy.c 2020-07-11 10:39:30.000000000 +0000 @@ -24,15 +24,25 @@ { AVFilterLink *outlink = inlink->dst->outputs[0]; AVFrame *out = ff_get_audio_buffer(outlink, in->nb_samples); + int ret; if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); + ret = AVERROR(ENOMEM); + goto fail; } - av_frame_copy_props(out, in); - av_frame_copy(out, in); + + ret = av_frame_copy_props(out, in); + if (ret < 0) + goto fail; + ret = av_frame_copy(out, in); + if (ret < 0) + goto fail; av_frame_free(&in); return ff_filter_frame(outlink, out); +fail: + av_frame_free(&in); + av_frame_free(&out); + return ret; } static const AVFilterPad acopy_inputs[] = { diff -Nru ffmpeg-4.2.2/libavfilter/af_acrossover.c ffmpeg-4.4/libavfilter/af_acrossover.c --- ffmpeg-4.2.2/libavfilter/af_acrossover.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_acrossover.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/eval.h" +#include "libavutil/float_dsp.h" #include "libavutil/internal.h" #include "libavutil/opt.h" @@ -38,29 +39,46 @@ #define MAX_SPLITS 16 #define MAX_BANDS MAX_SPLITS + 1 -typedef struct BiquadContext { - double a0, a1, a2; - double b1, b2; - double i1, i2; - double o1, o2; -} BiquadContext; - -typedef struct CrossoverChannel { - BiquadContext lp[MAX_BANDS][4]; - BiquadContext hp[MAX_BANDS][4]; -} CrossoverChannel; +#define B0 0 +#define B1 1 +#define B2 2 +#define A1 3 +#define A2 4 + +typedef struct BiquadCoeffs { + double cd[5]; + float cf[5]; +} BiquadCoeffs; typedef struct AudioCrossoverContext { const AVClass *class; char *splits_str; - int order; + char *gains_str; + int order_opt; + float level_in; + int order; int filter_count; + int first_order; + int ap_filter_count; int nb_splits; - float *splits; + float splits[MAX_SPLITS]; + + float gains[MAX_BANDS]; + + BiquadCoeffs lp[MAX_BANDS][20]; + BiquadCoeffs hp[MAX_BANDS][20]; + BiquadCoeffs ap[MAX_BANDS][20]; + + AVFrame *xover; - CrossoverChannel *xover; + AVFrame *input_frame; + AVFrame *frames[MAX_BANDS]; + + int (*filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + + AVFloatDSPContext *fdsp; } AudioCrossoverContext; #define OFFSET(x) offsetof(AudioCrossoverContext, x) @@ -68,23 +86,67 @@ static const AVOption acrossover_options[] = { { "split", "set split frequencies", OFFSET(splits_str), AV_OPT_TYPE_STRING, {.str="500"}, 0, 0, AF }, - { "order", "set order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=1}, 0, 2, AF, "m" }, - { "2nd", "2nd order", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "m" }, - { "4th", "4th order", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "m" }, - { "8th", "8th order", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "m" }, + { "order", "set filter order", OFFSET(order_opt), AV_OPT_TYPE_INT, {.i64=1}, 0, 9, AF, "m" }, + { "2nd", "2nd order (12 dB/8ve)", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "m" }, + { "4th", "4th order (24 dB/8ve)", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "m" }, + { "6th", "6th order (36 dB/8ve)", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "m" }, + { "8th", "8th order (48 dB/8ve)", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "m" }, + { "10th", "10th order (60 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, AF, "m" }, + { "12th", "12th order (72 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=5}, 0, 0, AF, "m" }, + { "14th", "14th order (84 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=6}, 0, 0, AF, "m" }, + { "16th", "16th order (96 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=7}, 0, 0, AF, "m" }, + { "18th", "18th order (108 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=8}, 0, 0, AF, "m" }, + { "20th", "20th order (120 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=9}, 0, 0, AF, "m" }, + { "level", "set input gain", OFFSET(level_in), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, AF }, + { "gain", "set output bands gain", OFFSET(gains_str), AV_OPT_TYPE_STRING, {.str="1.f"}, 0, 0, AF }, { NULL } }; AVFILTER_DEFINE_CLASS(acrossover); +static int parse_gains(AVFilterContext *ctx) +{ + AudioCrossoverContext *s = ctx->priv; + char *p, *arg, *saveptr = NULL; + int i, ret = 0; + + saveptr = NULL; + p = s->gains_str; + for (i = 0; i < MAX_BANDS; i++) { + float gain; + char c[3] = { 0 }; + + if (!(arg = av_strtok(p, " |", &saveptr))) + break; + + p = NULL; + + if (av_sscanf(arg, "%f%2s", &gain, c) < 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid syntax for gain[%d].\n", i); + ret = AVERROR(EINVAL); + break; + } + + if (c[0] == 'd' && c[1] == 'B') + s->gains[i] = expf(gain * M_LN10 / 20.f); + else + s->gains[i] = gain; + } + + for (; i < MAX_BANDS; i++) + s->gains[i] = 1.f; + + return ret; +} + static av_cold int init(AVFilterContext *ctx) { AudioCrossoverContext *s = ctx->priv; char *p, *arg, *saveptr = NULL; int i, ret = 0; - s->splits = av_calloc(MAX_SPLITS, sizeof(*s->splits)); - if (!s->splits) + s->fdsp = avpriv_float_dsp_alloc(0); + if (!s->fdsp) return AVERROR(ENOMEM); p = s->splits_str; @@ -96,7 +158,10 @@ p = NULL; - av_sscanf(arg, "%f", &freq); + if (av_sscanf(arg, "%f", &freq) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid syntax for frequency[%d].\n", i); + return AVERROR(EINVAL); + } if (freq <= 0) { av_log(ctx, AV_LOG_ERROR, "Frequency %f must be positive number.\n", freq); return AVERROR(EINVAL); @@ -112,6 +177,10 @@ s->nb_splits = i; + ret = parse_gains(ctx); + if (ret < 0) + return ret; + for (i = 0; i <= s->nb_splits; i++) { AVFilterPad pad = { 0 }; char *name; @@ -131,81 +200,107 @@ return ret; } -static void set_lp(BiquadContext *b, float fc, float q, float sr) +static void set_lp(BiquadCoeffs *b, double fc, double q, double sr) { - double omega = (2.0 * M_PI * fc / sr); - double sn = sin(omega); - double cs = cos(omega); - double alpha = (sn / (2 * q)); - double inv = (1.0 / (1.0 + alpha)); - - b->a2 = b->a0 = (inv * (1.0 - cs) * 0.5); - b->a1 = b->a0 + b->a0; - b->b1 = -2. * cs * inv; - b->b2 = (1. - alpha) * inv; -} - -static void set_hp(BiquadContext *b, float fc, float q, float sr) -{ - double omega = 2 * M_PI * fc / sr; - double sn = sin(omega); - double cs = cos(omega); - double alpha = sn / (2 * q); - double inv = 1.0 / (1.0 + alpha); - - b->a0 = inv * (1. + cs) / 2.; - b->a1 = -2. * b->a0; - b->a2 = b->a0; - b->b1 = -2. * cs * inv; - b->b2 = (1. - alpha) * inv; + double omega = 2. * M_PI * fc / sr; + double cosine = cos(omega); + double alpha = sin(omega) / (2. * q); + + double b0 = (1. - cosine) / 2.; + double b1 = 1. - cosine; + double b2 = (1. - cosine) / 2.; + double a0 = 1. + alpha; + double a1 = -2. * cosine; + double a2 = 1. - alpha; + + b->cd[B0] = b0 / a0; + b->cd[B1] = b1 / a0; + b->cd[B2] = b2 / a0; + b->cd[A1] = -a1 / a0; + b->cd[A2] = -a2 / a0; + + b->cf[B0] = b->cd[B0]; + b->cf[B1] = b->cd[B1]; + b->cf[B2] = b->cd[B2]; + b->cf[A1] = b->cd[A1]; + b->cf[A2] = b->cd[A2]; } -static int config_input(AVFilterLink *inlink) +static void set_hp(BiquadCoeffs *b, double fc, double q, double sr) { - AVFilterContext *ctx = inlink->dst; - AudioCrossoverContext *s = ctx->priv; - int ch, band, sample_rate = inlink->sample_rate; - double q; + double omega = 2. * M_PI * fc / sr; + double cosine = cos(omega); + double alpha = sin(omega) / (2. * q); + + double b0 = (1. + cosine) / 2.; + double b1 = -1. - cosine; + double b2 = (1. + cosine) / 2.; + double a0 = 1. + alpha; + double a1 = -2. * cosine; + double a2 = 1. - alpha; + + b->cd[B0] = b0 / a0; + b->cd[B1] = b1 / a0; + b->cd[B2] = b2 / a0; + b->cd[A1] = -a1 / a0; + b->cd[A2] = -a2 / a0; + + b->cf[B0] = b->cd[B0]; + b->cf[B1] = b->cd[B1]; + b->cf[B2] = b->cd[B2]; + b->cf[A1] = b->cd[A1]; + b->cf[A2] = b->cd[A2]; +} - s->xover = av_calloc(inlink->channels, sizeof(*s->xover)); - if (!s->xover) - return AVERROR(ENOMEM); +static void set_ap(BiquadCoeffs *b, double fc, double q, double sr) +{ + double omega = 2. * M_PI * fc / sr; + double cosine = cos(omega); + double alpha = sin(omega) / (2. * q); + + double a0 = 1. + alpha; + double a1 = -2. * cosine; + double a2 = 1. - alpha; + double b0 = a2; + double b1 = a1; + double b2 = a0; + + b->cd[B0] = b0 / a0; + b->cd[B1] = b1 / a0; + b->cd[B2] = b2 / a0; + b->cd[A1] = -a1 / a0; + b->cd[A2] = -a2 / a0; + + b->cf[B0] = b->cd[B0]; + b->cf[B1] = b->cd[B1]; + b->cf[B2] = b->cd[B2]; + b->cf[A1] = b->cd[A1]; + b->cf[A2] = b->cd[A2]; +} - switch (s->order) { - case 0: - q = 0.5; - s->filter_count = 1; - break; - case 1: - q = M_SQRT1_2; - s->filter_count = 2; - break; - case 2: - q = 0.54; - s->filter_count = 4; - break; - } +static void set_ap1(BiquadCoeffs *b, double fc, double sr) +{ + double omega = 2. * M_PI * fc / sr; - for (ch = 0; ch < inlink->channels; ch++) { - for (band = 0; band <= s->nb_splits; band++) { - set_lp(&s->xover[ch].lp[band][0], s->splits[band], q, sample_rate); - set_hp(&s->xover[ch].hp[band][0], s->splits[band], q, sample_rate); - - if (s->order > 1) { - set_lp(&s->xover[ch].lp[band][1], s->splits[band], 1.34, sample_rate); - set_hp(&s->xover[ch].hp[band][1], s->splits[band], 1.34, sample_rate); - set_lp(&s->xover[ch].lp[band][2], s->splits[band], q, sample_rate); - set_hp(&s->xover[ch].hp[band][2], s->splits[band], q, sample_rate); - set_lp(&s->xover[ch].lp[band][3], s->splits[band], 1.34, sample_rate); - set_hp(&s->xover[ch].hp[band][3], s->splits[band], 1.34, sample_rate); - } else { - set_lp(&s->xover[ch].lp[band][1], s->splits[band], q, sample_rate); - set_hp(&s->xover[ch].hp[band][1], s->splits[band], q, sample_rate); - } - } - } + b->cd[A1] = exp(-omega); + b->cd[A2] = 0.; + b->cd[B0] = -b->cd[A1]; + b->cd[B1] = 1.; + b->cd[B2] = 0.; + + b->cf[B0] = b->cd[B0]; + b->cf[B1] = b->cd[B1]; + b->cf[B2] = b->cd[B2]; + b->cf[A1] = b->cd[A1]; + b->cf[A2] = b->cd[A2]; +} - return 0; +static void calc_q_factors(int order, double *q) +{ + double n = order / 2.; + + for (int i = 0; i < n / 2; i++) + q[i] = 1. / (-2. * cos(M_PI * (2. * (i + 1) + n - 1.) / (2. * n))); } static int query_formats(AVFilterContext *ctx) @@ -213,7 +308,7 @@ AVFilterFormats *formats; AVFilterChannelLayouts *layouts; static const enum AVSampleFormat sample_fmts[] = { - AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }; int ret; @@ -238,24 +333,185 @@ return ff_set_common_samplerates(ctx, formats); } -static double biquad_process(BiquadContext *b, double in) +#define BIQUAD_PROCESS(name, type) \ +static void biquad_process_## name(const type *const c, \ + type *b, \ + type *dst, const type *src, \ + int nb_samples) \ +{ \ + const type b0 = c[B0]; \ + const type b1 = c[B1]; \ + const type b2 = c[B2]; \ + const type a1 = c[A1]; \ + const type a2 = c[A2]; \ + type z1 = b[0]; \ + type z2 = b[1]; \ + \ + for (int n = 0; n + 1 < nb_samples; n++) { \ + type in = src[n]; \ + type out; \ + \ + out = in * b0 + z1; \ + z1 = b1 * in + z2 + a1 * out; \ + z2 = b2 * in + a2 * out; \ + dst[n] = out; \ + \ + n++; \ + in = src[n]; \ + out = in * b0 + z1; \ + z1 = b1 * in + z2 + a1 * out; \ + z2 = b2 * in + a2 * out; \ + dst[n] = out; \ + } \ + \ + if (nb_samples & 1) { \ + const int n = nb_samples - 1; \ + const type in = src[n]; \ + type out; \ + \ + out = in * b0 + z1; \ + z1 = b1 * in + z2 + a1 * out; \ + z2 = b2 * in + a2 * out; \ + dst[n] = out; \ + } \ + \ + b[0] = z1; \ + b[1] = z2; \ +} + +BIQUAD_PROCESS(fltp, float) +BIQUAD_PROCESS(dblp, double) + +#define XOVER_PROCESS(name, type, one, ff) \ +static int filter_channels_## name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ +{ \ + AudioCrossoverContext *s = ctx->priv; \ + AVFrame *in = s->input_frame; \ + AVFrame **frames = s->frames; \ + const int start = (in->channels * jobnr) / nb_jobs; \ + const int end = (in->channels * (jobnr+1)) / nb_jobs; \ + const int nb_samples = in->nb_samples; \ + const int nb_outs = ctx->nb_outputs; \ + const int first_order = s->first_order; \ + \ + for (int ch = start; ch < end; ch++) { \ + const type *src = (const type *)in->extended_data[ch]; \ + type *xover = (type *)s->xover->extended_data[ch]; \ + \ + s->fdsp->vector_## ff ##mul_scalar((type *)frames[0]->extended_data[ch], src, \ + s->level_in, FFALIGN(nb_samples, sizeof(type))); \ + \ + for (int band = 0; band < nb_outs; band++) { \ + for (int f = 0; band + 1 < nb_outs && f < s->filter_count; f++) { \ + const type *prv = (const type *)frames[band]->extended_data[ch]; \ + type *dst = (type *)frames[band + 1]->extended_data[ch]; \ + const type *hsrc = f == 0 ? prv : dst; \ + type *hp = xover + nb_outs * 20 + band * 20 + f * 2; \ + const type *const hpc = (type *)&s->hp[band][f].c ## ff; \ + \ + biquad_process_## name(hpc, hp, dst, hsrc, nb_samples); \ + } \ + \ + for (int f = 0; band + 1 < nb_outs && f < s->filter_count; f++) { \ + type *dst = (type *)frames[band]->extended_data[ch]; \ + const type *lsrc = dst; \ + type *lp = xover + band * 20 + f * 2; \ + const type *const lpc = (type *)&s->lp[band][f].c ## ff; \ + \ + biquad_process_## name(lpc, lp, dst, lsrc, nb_samples); \ + } \ + \ + for (int aband = band + 1; aband + 1 < nb_outs; aband++) { \ + if (first_order) { \ + const type *asrc = (const type *)frames[band]->extended_data[ch]; \ + type *dst = (type *)frames[band]->extended_data[ch]; \ + type *ap = xover + nb_outs * 40 + (aband * nb_outs + band) * 20; \ + const type *const apc = (type *)&s->ap[aband][0].c ## ff; \ + \ + biquad_process_## name(apc, ap, dst, asrc, nb_samples); \ + } \ + \ + for (int f = first_order; f < s->ap_filter_count; f++) { \ + const type *asrc = (const type *)frames[band]->extended_data[ch]; \ + type *dst = (type *)frames[band]->extended_data[ch]; \ + type *ap = xover + nb_outs * 40 + (aband * nb_outs + band) * 20 + f * 2;\ + const type *const apc = (type *)&s->ap[aband][f].c ## ff; \ + \ + biquad_process_## name(apc, ap, dst, asrc, nb_samples); \ + } \ + } \ + } \ + \ + for (int band = 0; band < nb_outs; band++) { \ + const type gain = s->gains[band] * ((band & 1 && first_order) ? -one : one); \ + type *dst = (type *)frames[band]->extended_data[ch]; \ + \ + s->fdsp->vector_## ff ##mul_scalar(dst, dst, gain, \ + FFALIGN(nb_samples, sizeof(type))); \ + } \ + } \ + \ + return 0; \ +} + +XOVER_PROCESS(fltp, float, 1.f, f) +XOVER_PROCESS(dblp, double, 1.0, d) + +static int config_input(AVFilterLink *inlink) { - double out = in * b->a0 + b->i1 * b->a1 + b->i2 * b->a2 - b->o1 * b->b1 - b->o2 * b->b2; + AVFilterContext *ctx = inlink->dst; + AudioCrossoverContext *s = ctx->priv; + int sample_rate = inlink->sample_rate; + double q[16]; - b->i2 = b->i1; - b->o2 = b->o1; - b->i1 = in; - b->o1 = out; + s->order = (s->order_opt + 1) * 2; + s->filter_count = s->order / 2; + s->first_order = s->filter_count & 1; + s->ap_filter_count = s->filter_count / 2 + s->first_order; + calc_q_factors(s->order, q); + + for (int band = 0; band <= s->nb_splits; band++) { + if (s->first_order) { + set_lp(&s->lp[band][0], s->splits[band], 0.5, sample_rate); + set_hp(&s->hp[band][0], s->splits[band], 0.5, sample_rate); + } + + for (int n = s->first_order; n < s->filter_count; n++) { + const int idx = s->filter_count / 2 - ((n + s->first_order) / 2 - s->first_order) - 1; + + set_lp(&s->lp[band][n], s->splits[band], q[idx], sample_rate); + set_hp(&s->hp[band][n], s->splits[band], q[idx], sample_rate); + } + + if (s->first_order) + set_ap1(&s->ap[band][0], s->splits[band], sample_rate); - return out; + for (int n = s->first_order; n < s->ap_filter_count; n++) { + const int idx = (s->filter_count / 2 - ((n * 2 + s->first_order) / 2 - s->first_order) - 1); + + set_ap(&s->ap[band][n], s->splits[band], q[idx], sample_rate); + } + } + + switch (inlink->format) { + case AV_SAMPLE_FMT_FLTP: s->filter_channels = filter_channels_fltp; break; + case AV_SAMPLE_FMT_DBLP: s->filter_channels = filter_channels_dblp; break; + } + + s->xover = ff_get_audio_buffer(inlink, 2 * (ctx->nb_outputs * 10 + ctx->nb_outputs * 10 + + ctx->nb_outputs * ctx->nb_outputs * 10)); + if (!s->xover) + return AVERROR(ENOMEM); + + return 0; } static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; AudioCrossoverContext *s = ctx->priv; - AVFrame *frames[MAX_BANDS] = { NULL }; - int i, f, ch, band, ret = 0; + AVFrame **frames = s->frames; + int i, ret = 0; for (i = 0; i < ctx->nb_outputs; i++) { frames[i] = ff_get_audio_buffer(ctx->outputs[i], in->nb_samples); @@ -271,39 +527,22 @@ if (ret < 0) goto fail; - for (ch = 0; ch < inlink->channels; ch++) { - const double *src = (const double *)in->extended_data[ch]; - CrossoverChannel *xover = &s->xover[ch]; - - for (band = 0; band < ctx->nb_outputs; band++) { - double *dst = (double *)frames[band]->extended_data[ch]; - - for (i = 0; i < in->nb_samples; i++) { - dst[i] = src[i]; - - for (f = 0; f < s->filter_count; f++) { - if (band + 1 < ctx->nb_outputs) { - BiquadContext *lp = &xover->lp[band][f]; - dst[i] = biquad_process(lp, dst[i]); - } - - if (band - 1 >= 0) { - BiquadContext *hp = &xover->hp[band - 1][f]; - dst[i] = biquad_process(hp, dst[i]); - } - } - } - } - } + s->input_frame = in; + ctx->internal->execute(ctx, s->filter_channels, NULL, NULL, FFMIN(inlink->channels, + ff_filter_get_nb_threads(ctx))); for (i = 0; i < ctx->nb_outputs; i++) { ret = ff_filter_frame(ctx->outputs[i], frames[i]); + frames[i] = NULL; if (ret < 0) break; } fail: + for (i = 0; i < ctx->nb_outputs; i++) + av_frame_free(&frames[i]); av_frame_free(&in); + s->input_frame = NULL; return ret; } @@ -313,7 +552,8 @@ AudioCrossoverContext *s = ctx->priv; int i; - av_freep(&s->splits); + av_freep(&s->fdsp); + av_frame_free(&s->xover); for (i = 0; i < ctx->nb_outputs; i++) av_freep(&ctx->output_pads[i].name); @@ -339,5 +579,6 @@ .query_formats = query_formats, .inputs = inputs, .outputs = NULL, - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | + AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_acrusher.c ffmpeg-4.4/libavfilter/af_acrusher.c --- ffmpeg-4.2.2/libavfilter/af_acrusher.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_acrusher.c 2021-04-08 21:28:39.000000000 +0000 @@ -68,7 +68,7 @@ } ACrusherContext; #define OFFSET(x) offsetof(ACrusherContext, x) -#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption acrusher_options[] = { { "level_in", "set level in", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, A }, @@ -325,13 +325,27 @@ s->lfo.srate = inlink->sample_rate; s->lfo.amount = .5; - s->sr = av_calloc(inlink->channels, sizeof(*s->sr)); + if (!s->sr) + s->sr = av_calloc(inlink->channels, sizeof(*s->sr)); if (!s->sr) return AVERROR(ENOMEM); return 0; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + AVFilterLink *inlink = ctx->inputs[0]; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_input(inlink); +} + static const AVFilterPad avfilter_af_acrusher_inputs[] = { { .name = "default", @@ -359,4 +373,5 @@ .query_formats = query_formats, .inputs = avfilter_af_acrusher_inputs, .outputs = avfilter_af_acrusher_outputs, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_adeclick.c ffmpeg-4.4/libavfilter/af_adeclick.c --- ffmpeg-4.2.2/libavfilter/af_adeclick.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_adeclick.c 2021-04-08 21:28:39.000000000 +0000 @@ -63,6 +63,7 @@ int hop_size; int overlap_skip; + AVFrame *enabled; AVFrame *in; AVFrame *out; AVFrame *buffer; @@ -77,6 +78,7 @@ int samples_left; int eof; + AVAudioFifo *efifo; AVAudioFifo *fifo; double *window_func_lut; @@ -90,13 +92,21 @@ #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption adeclick_options[] = { + { "window", "set window size", OFFSET(w), AV_OPT_TYPE_DOUBLE, {.dbl=55}, 10, 100, AF }, { "w", "set window size", OFFSET(w), AV_OPT_TYPE_DOUBLE, {.dbl=55}, 10, 100, AF }, + { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=75}, 50, 95, AF }, { "o", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=75}, 50, 95, AF }, + { "arorder", "set autoregression order", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, 25, AF }, { "a", "set autoregression order", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, 25, AF }, + { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 1, 100, AF }, { "t", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 1, 100, AF }, + { "burst", "set burst fusion", OFFSET(burst), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, 10, AF }, { "b", "set burst fusion", OFFSET(burst), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, 10, AF }, + { "method", "set overlap method", OFFSET(method), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "m" }, { "m", "set overlap method", OFFSET(method), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "m" }, + { "add", "overlap-add", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "m" }, { "a", "overlap-add", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "m" }, + { "save", "overlap-save", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "m" }, { "s", "overlap-save", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "m" }, { NULL } }; @@ -159,13 +169,17 @@ av_frame_free(&s->out); av_frame_free(&s->buffer); av_frame_free(&s->is); + s->enabled = ff_get_audio_buffer(inlink, s->window_size); s->in = ff_get_audio_buffer(inlink, s->window_size); s->out = ff_get_audio_buffer(inlink, s->window_size); s->buffer = ff_get_audio_buffer(inlink, s->window_size * 2); s->is = ff_get_audio_buffer(inlink, s->window_size); - if (!s->in || !s->out || !s->buffer || !s->is) + if (!s->in || !s->out || !s->buffer || !s->is || !s->enabled) return AVERROR(ENOMEM); + s->efifo = av_audio_fifo_alloc(inlink->format, 1, s->window_size); + if (!s->efifo) + return AVERROR(ENOMEM); s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->window_size); if (!s->fifo) return AVERROR(ENOMEM); @@ -513,14 +527,20 @@ nb_errors = s->detector(s, c, sigmae, c->detection, c->acoefficients, c->click, index, src, dst); if (nb_errors > 0) { + double *enabled = (double *)s->enabled->extended_data[0]; + ret = interpolation(c, src, s->ar_order, c->acoefficients, index, nb_errors, c->auxiliary, interpolated); if (ret < 0) return ret; + av_audio_fifo_peek(s->efifo, (void**)s->enabled->extended_data, s->window_size); + for (j = 0; j < nb_errors; j++) { - dst[index[j]] = interpolated[j]; - is[index[j]] = 1; + if (enabled[index[j]]) { + dst[index[j]] = interpolated[j]; + is[index[j]] = 1; + } } } } else { @@ -580,19 +600,20 @@ } av_audio_fifo_drain(s->fifo, s->hop_size); + av_audio_fifo_drain(s->efifo, s->hop_size); if (s->samples_left > 0) out->nb_samples = FFMIN(s->hop_size, s->samples_left); out->pts = s->pts; - s->pts += s->hop_size; + s->pts += av_rescale_q(s->hop_size, (AVRational){1, outlink->sample_rate}, outlink->time_base); s->detected_errors += detected_errors; s->nb_samples += out->nb_samples * inlink->channels; ret = ff_filter_frame(outlink, out); if (ret < 0) - goto fail; + return ret; if (s->samples_left > 0) { s->samples_left -= s->hop_size; @@ -621,11 +642,17 @@ if (ret < 0) return ret; if (ret > 0) { + double *e = (double *)s->enabled->extended_data[0]; + if (s->pts == AV_NOPTS_VALUE) s->pts = in->pts; ret = av_audio_fifo_write(s->fifo, (void **)in->extended_data, in->nb_samples); + for (int i = 0; i < in->nb_samples; i++) + e[i] = !ctx->is_disabled; + + av_audio_fifo_write(s->efifo, (void**)s->enabled->extended_data, in->nb_samples); av_frame_free(&in); if (ret < 0) return ret; @@ -684,7 +711,9 @@ s->nb_samples, 100. * s->detected_errors / s->nb_samples); av_audio_fifo_free(s->fifo); + av_audio_fifo_free(s->efifo); av_freep(&s->window_func_lut); + av_frame_free(&s->enabled); av_frame_free(&s->in); av_frame_free(&s->out); av_frame_free(&s->buffer); @@ -744,18 +773,26 @@ .uninit = uninit, .inputs = inputs, .outputs = outputs, - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; static const AVOption adeclip_options[] = { - { "w", "set window size", OFFSET(w), AV_OPT_TYPE_DOUBLE, {.dbl=55}, 10, 100, AF }, - { "o", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=75}, 50, 95, AF }, - { "a", "set autoregression order", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=8}, 0, 25, AF }, - { "t", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=10}, 1, 100, AF }, - { "n", "set histogram size", OFFSET(nb_hbins), AV_OPT_TYPE_INT, {.i64=1000}, 100, 9999, AF }, - { "m", "set overlap method", OFFSET(method), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "m" }, - { "a", "overlap-add", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "m" }, - { "s", "overlap-save", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "m" }, + { "window", "set window size", OFFSET(w), AV_OPT_TYPE_DOUBLE, {.dbl=55}, 10, 100, AF }, + { "w", "set window size", OFFSET(w), AV_OPT_TYPE_DOUBLE, {.dbl=55}, 10, 100, AF }, + { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=75}, 50, 95, AF }, + { "o", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=75}, 50, 95, AF }, + { "arorder", "set autoregression order", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=8}, 0, 25, AF }, + { "a", "set autoregression order", OFFSET(ar), AV_OPT_TYPE_DOUBLE, {.dbl=8}, 0, 25, AF }, + { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=10}, 1, 100, AF }, + { "t", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=10}, 1, 100, AF }, + { "hsize", "set histogram size", OFFSET(nb_hbins), AV_OPT_TYPE_INT, {.i64=1000}, 100, 9999, AF }, + { "n", "set histogram size", OFFSET(nb_hbins), AV_OPT_TYPE_INT, {.i64=1000}, 100, 9999, AF }, + { "method", "set overlap method", OFFSET(method), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "m" }, + { "m", "set overlap method", OFFSET(method), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "m" }, + { "add", "overlap-add", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "m" }, + { "a", "overlap-add", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "m" }, + { "save", "overlap-save", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "m" }, + { "s", "overlap-save", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "m" }, { NULL } }; @@ -772,5 +809,5 @@ .uninit = uninit, .inputs = inputs, .outputs = outputs, - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_adelay.c ffmpeg-4.4/libavfilter/af_adelay.c --- ffmpeg-4.2.2/libavfilter/af_adelay.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_adelay.c 2020-07-11 10:39:30.000000000 +0000 @@ -36,6 +36,7 @@ typedef struct AudioDelayContext { const AVClass *class; + int all; char *delays; ChanDelay *chandelay; int nb_delays; @@ -54,6 +55,7 @@ static const AVOption adelay_options[] = { { "delays", "set list of delays for each channel", OFFSET(delays), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, A }, + { "all", "use last available delay for remained channels", OFFSET(all), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A }, { NULL } }; @@ -153,7 +155,10 @@ ret = av_sscanf(arg, "%d%c", &d->delay, &type); if (ret != 2 || type != 'S') { div = type == 's' ? 1.0 : 1000.0; - av_sscanf(arg, "%f", &delay); + if (av_sscanf(arg, "%f", &delay) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid syntax for delay.\n"); + return AVERROR(EINVAL); + } d->delay = delay * inlink->sample_rate / div; } @@ -163,6 +168,11 @@ } } + if (s->all && i) { + for (int j = i; j < s->nb_delays; j++) + s->chandelay[j].delay = s->chandelay[i-1].delay; + } + s->padding = s->chandelay[0].delay; for (i = 1; i < s->nb_delays; i++) { ChanDelay *d = &s->chandelay[i]; diff -Nru ffmpeg-4.2.2/libavfilter/af_adenorm.c ffmpeg-4.4/libavfilter/af_adenorm.c --- ffmpeg-4.2.2/libavfilter/af_adenorm.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_adenorm.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,332 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" +#include "audio.h" +#include "avfilter.h" +#include "internal.h" + +enum FilterType { + DC_TYPE, + AC_TYPE, + SQ_TYPE, + PS_TYPE, + NB_TYPES, +}; + +typedef struct ADenormContext { + const AVClass *class; + + double level; + double level_db; + int type; + int64_t in_samples; + + void (*filter)(AVFilterContext *ctx, void *dst, + const void *src, int nb_samples); +} ADenormContext; + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *layouts = NULL; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE + }; + int ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_all_samplerates(); + return ff_set_common_samplerates(ctx, formats); +} + +static void dc_denorm_fltp(AVFilterContext *ctx, void *dstp, + const void *srcp, int nb_samples) +{ + ADenormContext *s = ctx->priv; + const float *src = (const float *)srcp; + float *dst = (float *)dstp; + const float dc = s->level; + + for (int n = 0; n < nb_samples; n++) { + dst[n] = src[n] + dc; + } +} + +static void dc_denorm_dblp(AVFilterContext *ctx, void *dstp, + const void *srcp, int nb_samples) +{ + ADenormContext *s = ctx->priv; + const double *src = (const double *)srcp; + double *dst = (double *)dstp; + const double dc = s->level; + + for (int n = 0; n < nb_samples; n++) { + dst[n] = src[n] + dc; + } +} + +static void ac_denorm_fltp(AVFilterContext *ctx, void *dstp, + const void *srcp, int nb_samples) +{ + ADenormContext *s = ctx->priv; + const float *src = (const float *)srcp; + float *dst = (float *)dstp; + const float dc = s->level; + const int64_t N = s->in_samples; + + for (int n = 0; n < nb_samples; n++) { + dst[n] = src[n] + dc * (((N + n) & 1) ? -1.f : 1.f); + } +} + +static void ac_denorm_dblp(AVFilterContext *ctx, void *dstp, + const void *srcp, int nb_samples) +{ + ADenormContext *s = ctx->priv; + const double *src = (const double *)srcp; + double *dst = (double *)dstp; + const double dc = s->level; + const int64_t N = s->in_samples; + + for (int n = 0; n < nb_samples; n++) { + dst[n] = src[n] + dc * (((N + n) & 1) ? -1. : 1.); + } +} + +static void sq_denorm_fltp(AVFilterContext *ctx, void *dstp, + const void *srcp, int nb_samples) +{ + ADenormContext *s = ctx->priv; + const float *src = (const float *)srcp; + float *dst = (float *)dstp; + const float dc = s->level; + const int64_t N = s->in_samples; + + for (int n = 0; n < nb_samples; n++) { + dst[n] = src[n] + dc * ((((N + n) >> 8) & 1) ? -1.f : 1.f); + } +} + +static void sq_denorm_dblp(AVFilterContext *ctx, void *dstp, + const void *srcp, int nb_samples) +{ + ADenormContext *s = ctx->priv; + const double *src = (const double *)srcp; + double *dst = (double *)dstp; + const double dc = s->level; + const int64_t N = s->in_samples; + + for (int n = 0; n < nb_samples; n++) { + dst[n] = src[n] + dc * ((((N + n) >> 8) & 1) ? -1. : 1.); + } +} + +static void ps_denorm_fltp(AVFilterContext *ctx, void *dstp, + const void *srcp, int nb_samples) +{ + ADenormContext *s = ctx->priv; + const float *src = (const float *)srcp; + float *dst = (float *)dstp; + const float dc = s->level; + const int64_t N = s->in_samples; + + for (int n = 0; n < nb_samples; n++) { + dst[n] = src[n] + dc * (((N + n) & 255) ? 0.f : 1.f); + } +} + +static void ps_denorm_dblp(AVFilterContext *ctx, void *dstp, + const void *srcp, int nb_samples) +{ + ADenormContext *s = ctx->priv; + const double *src = (const double *)srcp; + double *dst = (double *)dstp; + const double dc = s->level; + const int64_t N = s->in_samples; + + for (int n = 0; n < nb_samples; n++) { + dst[n] = src[n] + dc * (((N + n) & 255) ? 0. : 1.); + } +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + ADenormContext *s = ctx->priv; + + switch (s->type) { + case DC_TYPE: + switch (outlink->format) { + case AV_SAMPLE_FMT_FLTP: s->filter = dc_denorm_fltp; break; + case AV_SAMPLE_FMT_DBLP: s->filter = dc_denorm_dblp; break; + } + break; + case AC_TYPE: + switch (outlink->format) { + case AV_SAMPLE_FMT_FLTP: s->filter = ac_denorm_fltp; break; + case AV_SAMPLE_FMT_DBLP: s->filter = ac_denorm_dblp; break; + } + break; + case SQ_TYPE: + switch (outlink->format) { + case AV_SAMPLE_FMT_FLTP: s->filter = sq_denorm_fltp; break; + case AV_SAMPLE_FMT_DBLP: s->filter = sq_denorm_dblp; break; + } + break; + case PS_TYPE: + switch (outlink->format) { + case AV_SAMPLE_FMT_FLTP: s->filter = ps_denorm_fltp; break; + case AV_SAMPLE_FMT_DBLP: s->filter = ps_denorm_dblp; break; + } + break; + default: + av_assert0(0); + } + + return 0; +} + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ADenormContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + const int start = (in->channels * jobnr) / nb_jobs; + const int end = (in->channels * (jobnr+1)) / nb_jobs; + + for (int ch = start; ch < end; ch++) { + s->filter(ctx, out->extended_data[ch], + in->extended_data[ch], + in->nb_samples); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + ADenormContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + 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->level = exp(s->level_db / 20. * M_LN10); + td.in = in; td.out = out; + ctx->internal->execute(ctx, filter_channels, &td, NULL, FFMIN(inlink->channels, + ff_filter_get_nb_threads(ctx))); + + s->in_samples += in->nb_samples; + + 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) +{ + AVFilterLink *outlink = ctx->outputs[0]; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_output(outlink); +} + +static const AVFilterPad adenorm_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad adenorm_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(ADenormContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption adenorm_options[] = { + { "level", "set level", OFFSET(level_db), AV_OPT_TYPE_DOUBLE, {.dbl=-351}, -451, -90, FLAGS }, + { "type", "set type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=DC_TYPE}, 0, NB_TYPES-1, FLAGS, "type" }, + { "dc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=DC_TYPE}, 0, 0, FLAGS, "type"}, + { "ac", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AC_TYPE}, 0, 0, FLAGS, "type"}, + { "square",NULL, 0, AV_OPT_TYPE_CONST, {.i64=SQ_TYPE}, 0, 0, FLAGS, "type"}, + { "pulse", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PS_TYPE}, 0, 0, FLAGS, "type"}, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(adenorm); + +AVFilter ff_af_adenorm = { + .name = "adenorm", + .description = NULL_IF_CONFIG_SMALL("Remedy denormals by adding extremely low-level noise."), + .query_formats = query_formats, + .priv_size = sizeof(ADenormContext), + .inputs = adenorm_inputs, + .outputs = adenorm_outputs, + .priv_class = &adenorm_class, + .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS, +}; diff -Nru ffmpeg-4.2.2/libavfilter/af_aecho.c ffmpeg-4.4/libavfilter/af_aecho.c --- ffmpeg-4.2.2/libavfilter/af_aecho.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_aecho.c 2020-07-11 10:39:30.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavutil/samplefmt.h" #include "avfilter.h" #include "audio.h" +#include "filters.h" #include "internal.h" typedef struct AudioEchoContext { @@ -36,6 +37,7 @@ uint8_t **delayptrs; int max_samples, fade_out; int *samples; + int eof; int64_t next_pts; void (*echo_samples)(struct AudioEchoContext *ctx, uint8_t **delayptrs, @@ -302,42 +304,65 @@ { AVFilterContext *ctx = outlink->src; AudioEchoContext *s = ctx->priv; - int ret; + int nb_samples = FFMIN(s->fade_out, 2048); + AVFrame *frame = ff_get_audio_buffer(outlink, nb_samples); - ret = ff_request_frame(ctx->inputs[0]); + if (!frame) + return AVERROR(ENOMEM); + s->fade_out -= nb_samples; - if (ret == AVERROR_EOF && !ctx->is_disabled && s->fade_out) { - int nb_samples = FFMIN(s->fade_out, 2048); - AVFrame *frame; + av_samples_set_silence(frame->extended_data, 0, + frame->nb_samples, + outlink->channels, + frame->format); - frame = ff_get_audio_buffer(outlink, nb_samples); - if (!frame) - return AVERROR(ENOMEM); - s->fade_out -= nb_samples; + s->echo_samples(s, s->delayptrs, frame->extended_data, frame->extended_data, + frame->nb_samples, outlink->channels); - av_samples_set_silence(frame->extended_data, 0, - frame->nb_samples, - outlink->channels, - frame->format); + frame->pts = s->next_pts; + if (s->next_pts != AV_NOPTS_VALUE) + s->next_pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); - s->echo_samples(s, s->delayptrs, frame->extended_data, frame->extended_data, - frame->nb_samples, outlink->channels); + return ff_filter_frame(outlink, frame); +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + AudioEchoContext *s = ctx->priv; + AVFrame *in; + int ret, status; + int64_t pts; - frame->pts = s->next_pts; - if (s->next_pts != AV_NOPTS_VALUE) - s->next_pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - return ff_filter_frame(outlink, frame); + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; + if (ret > 0) + return filter_frame(inlink, in); + + if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) + s->eof = 1; } - return ret; + if (s->eof && s->fade_out <= 0) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->next_pts); + return 0; + } + + if (!s->eof) + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return request_frame(outlink); } static const AVFilterPad aecho_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, }, { NULL } }; @@ -345,7 +370,6 @@ static const AVFilterPad aecho_outputs[] = { { .name = "default", - .request_frame = request_frame, .config_props = config_output, .type = AVMEDIA_TYPE_AUDIO, }, @@ -359,6 +383,7 @@ .priv_size = sizeof(AudioEchoContext), .priv_class = &aecho_class, .init = init, + .activate = activate, .uninit = uninit, .inputs = aecho_inputs, .outputs = aecho_outputs, diff -Nru ffmpeg-4.2.2/libavfilter/af_aemphasis.c ffmpeg-4.4/libavfilter/af_aemphasis.c --- ffmpeg-4.2.2/libavfilter/af_aemphasis.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_aemphasis.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,13 +27,9 @@ double a0, a1, a2, b1, b2; } BiquadCoeffs; -typedef struct BiquadD2 { - double a0, a1, a2, b1, b2, w1, w2; -} BiquadD2; - typedef struct RIAACurve { - BiquadD2 r1; - BiquadD2 brickw; + BiquadCoeffs r1; + BiquadCoeffs brickw; int use_brickw; } RIAACurve; @@ -42,11 +38,13 @@ int mode, type; double level_in, level_out; - RIAACurve *rc; + RIAACurve rc; + + AVFrame *w; } AudioEmphasisContext; #define OFFSET(x) offsetof(AudioEmphasisContext, x) -#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption aemphasis_options[] = { { "level_in", "set input gain", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 64, FLAGS }, @@ -69,29 +67,69 @@ AVFILTER_DEFINE_CLASS(aemphasis); -static inline double biquad(BiquadD2 *bq, double in) +static inline void biquad_process(BiquadCoeffs *bq, double *dst, const double *src, int nb_samples, + double *w, double level_in, double level_out) { - double n = in; - double tmp = n - bq->w1 * bq->b1 - bq->w2 * bq->b2; - double out = tmp * bq->a0 + bq->w1 * bq->a1 + bq->w2 * bq->a2; + const double a0 = bq->a0; + const double a1 = bq->a1; + const double a2 = bq->a2; + const double b1 = bq->b1; + const double b2 = bq->b2; + double w1 = w[0]; + double w2 = w[1]; + + for (int i = 0; i < nb_samples; i++) { + double n = src[i] * level_in; + double tmp = n - w1 * b1 - w2 * b2; + double out = tmp * a0 + w1 * a1 + w2 * a2; - bq->w2 = bq->w1; - bq->w1 = tmp; + w2 = w1; + w1 = tmp; + + dst[i] = out * level_out; + } - return out; + w[0] = w1; + w[1] = w2; } -static int filter_frame(AVFilterLink *inlink, AVFrame *in) +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - AVFilterContext *ctx = inlink->dst; - AVFilterLink *outlink = ctx->outputs[0]; AudioEmphasisContext *s = ctx->priv; - const double *src = (const double *)in->data[0]; const double level_out = s->level_out; const double level_in = s->level_in; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + const int start = (in->channels * jobnr) / nb_jobs; + const int end = (in->channels * (jobnr+1)) / nb_jobs; + + for (int ch = start; ch < end; ch++) { + const double *src = (const double *)in->extended_data[ch]; + double *w = (double *)s->w->extended_data[ch]; + double *dst = (double *)out->extended_data[ch]; + + if (s->rc.use_brickw) { + biquad_process(&s->rc.brickw, dst, src, in->nb_samples, w + 2, level_in, 1.); + biquad_process(&s->rc.r1, dst, dst, in->nb_samples, w, 1., level_out); + } else { + biquad_process(&s->rc.r1, dst, src, in->nb_samples, w, level_in, level_out); + } + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + ThreadData td; AVFrame *out; - double *dst; - int n, c; if (av_frame_is_writable(in)) { out = in; @@ -103,14 +141,10 @@ } av_frame_copy_props(out, in); } - dst = (double *)out->data[0]; - for (n = 0; n < in->nb_samples; n++) { - for (c = 0; c < inlink->channels; c++) - dst[c] = level_out * biquad(&s->rc[c].r1, s->rc[c].use_brickw ? biquad(&s->rc[c].brickw, src[c] * level_in) : src[c] * level_in); - dst += inlink->channels; - src += inlink->channels; - } + td.in = in; td.out = out; + ctx->internal->execute(ctx, filter_channels, &td, NULL, FFMIN(inlink->channels, + ff_filter_get_nb_threads(ctx))); if (in != out) av_frame_free(&in); @@ -122,7 +156,7 @@ AVFilterChannelLayouts *layouts; AVFilterFormats *formats; static const enum AVSampleFormat sample_fmts[] = { - AV_SAMPLE_FMT_DBL, + AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }; int ret; @@ -147,7 +181,7 @@ return ff_set_common_samplerates(ctx, formats); } -static inline void set_highshelf_rbj(BiquadD2 *bq, double freq, double q, double peak, double sr) +static inline void set_highshelf_rbj(BiquadCoeffs *bq, double freq, double q, double peak, double sr) { double A = sqrt(peak); double w0 = freq * 2 * M_PI / sr; @@ -171,7 +205,7 @@ bq->a2 *= ib0; } -static inline void set_lp_rbj(BiquadD2 *bq, double fc, double q, double sr, double gain) +static inline void set_lp_rbj(BiquadCoeffs *bq, double fc, double q, double sr, double gain) { double omega = 2.0 * M_PI * fc / sr; double sn = sin(omega); @@ -205,10 +239,10 @@ AVFilterContext *ctx = inlink->dst; AudioEmphasisContext *s = ctx->priv; BiquadCoeffs coeffs; - int ch; - s->rc = av_calloc(inlink->channels, sizeof(*s->rc)); - if (!s->rc) + if (!s->w) + s->w = ff_get_audio_buffer(inlink, 4); + if (!s->w) return AVERROR(ENOMEM); switch (s->type) { @@ -282,12 +316,12 @@ if (s->type == 7) q = pow((sr / 4750.0) + 19.5, -0.25); if (s->mode == 0) - set_highshelf_rbj(&s->rc[0].r1, cfreq, q, 1. / gain, sr); + set_highshelf_rbj(&s->rc.r1, cfreq, q, 1. / gain, sr); else - set_highshelf_rbj(&s->rc[0].r1, cfreq, q, gain, sr); - s->rc[0].use_brickw = 0; + set_highshelf_rbj(&s->rc.r1, cfreq, q, gain, sr); + s->rc.use_brickw = 0; } else { - s->rc[0].use_brickw = 1; + s->rc.use_brickw = 1; if (s->mode == 0) { // Reproduction g = 1. / (4.+2.*i*t+2.*k*t+i*k*t*t); a0 = (2.*t+j*t*t)*g; @@ -316,27 +350,36 @@ gain1kHz = freq_gain(&coeffs, 1000.0, sr); // divide one filter's x[n-m] coefficients by that value gc = 1.0 / gain1kHz; - s->rc[0].r1.a0 = coeffs.a0 * gc; - s->rc[0].r1.a1 = coeffs.a1 * gc; - s->rc[0].r1.a2 = coeffs.a2 * gc; - s->rc[0].r1.b1 = coeffs.b1; - s->rc[0].r1.b2 = coeffs.b2; + s->rc.r1.a0 = coeffs.a0 * gc; + s->rc.r1.a1 = coeffs.a1 * gc; + s->rc.r1.a2 = coeffs.a2 * gc; + s->rc.r1.b1 = coeffs.b1; + s->rc.r1.b2 = coeffs.b2; } cutfreq = FFMIN(0.45 * sr, 21000.); - set_lp_rbj(&s->rc[0].brickw, cutfreq, 0.707, sr, 1.); - - for (ch = 1; ch < inlink->channels; ch++) { - memcpy(&s->rc[ch], &s->rc[0], sizeof(RIAACurve)); - } + set_lp_rbj(&s->rc.brickw, cutfreq, 0.707, sr, 1.); return 0; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + static av_cold void uninit(AVFilterContext *ctx) { AudioEmphasisContext *s = ctx->priv; - av_freep(&s->rc); + + av_frame_free(&s->w); } static const AVFilterPad avfilter_af_aemphasis_inputs[] = { @@ -366,4 +409,7 @@ .query_formats = query_formats, .inputs = avfilter_af_aemphasis_inputs, .outputs = avfilter_af_aemphasis_outputs, + .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_aexciter.c ffmpeg-4.4/libavfilter/af_aexciter.c --- ffmpeg-4.2.2/libavfilter/af_aexciter.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_aexciter.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,317 @@ +/* + * Copyright (c) Markus Schmidt and Christian Holschuh + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "avfilter.h" +#include "internal.h" +#include "audio.h" + +typedef struct ChannelParams { + double blend_old, drive_old; + double rdrive, rbdr, kpa, kpb, kna, knb, ap, + an, imr, kc, srct, sq, pwrq; + double prev_med, prev_out; + + double hp[5], lp[5]; + double hw[4][2], lw[2][2]; +} ChannelParams; + +typedef struct AExciterContext { + const AVClass *class; + + double level_in; + double level_out; + double amount; + double drive; + double blend; + double freq; + double ceil; + int listen; + + ChannelParams *cp; +} AExciterContext; + +#define OFFSET(x) offsetof(AExciterContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption aexciter_options[] = { + { "level_in", "set level in", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 64, A }, + { "level_out", "set level out", OFFSET(level_out), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 64, A }, + { "amount", "set amount", OFFSET(amount), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 64, A }, + { "drive", "set harmonics", OFFSET(drive), AV_OPT_TYPE_DOUBLE, {.dbl=8.5}, 0.1, 10, A }, + { "blend", "set blend harmonics", OFFSET(blend), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -10, 10, A }, + { "freq", "set scope", OFFSET(freq), AV_OPT_TYPE_DOUBLE, {.dbl=7500}, 2000, 12000, A }, + { "ceil", "set ceiling", OFFSET(ceil), AV_OPT_TYPE_DOUBLE, {.dbl=9999}, 9999, 20000, A }, + { "listen", "enable listen mode", OFFSET(listen), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(aexciter); + +static inline double M(double x) +{ + return (fabs(x) > 0.00000001) ? x : 0.0; +} + +static inline double D(double x) +{ + x = fabs(x); + + return (x > 0.00000001) ? sqrt(x) : 0.0; +} + +static void set_params(ChannelParams *p, + double blend, double drive, + double srate, double freq, + double ceil) +{ + double a0, a1, a2, b0, b1, b2, w0, alpha; + + p->rdrive = 12.0 / drive; + p->rbdr = p->rdrive / (10.5 - blend) * 780.0 / 33.0; + p->kpa = D(2.0 * (p->rdrive*p->rdrive) - 1.0) + 1.0; + p->kpb = (2.0 - p->kpa) / 2.0; + p->ap = ((p->rdrive*p->rdrive) - p->kpa + 1.0) / 2.0; + p->kc = p->kpa / D(2.0 * D(2.0 * (p->rdrive*p->rdrive) - 1.0) - 2.0 * p->rdrive*p->rdrive); + + p->srct = (0.1 * srate) / (0.1 * srate + 1.0); + p->sq = p->kc*p->kc + 1.0; + p->knb = -1.0 * p->rbdr / D(p->sq); + p->kna = 2.0 * p->kc * p->rbdr / D(p->sq); + p->an = p->rbdr*p->rbdr / p->sq; + p->imr = 2.0 * p->knb + D(2.0 * p->kna + 4.0 * p->an - 1.0); + p->pwrq = 2.0 / (p->imr + 1.0); + + w0 = 2 * M_PI * freq / srate; + alpha = sin(w0) / (2. * 0.707); + a0 = 1 + alpha; + a1 = -2 * cos(w0); + a2 = 1 - alpha; + b0 = (1 + cos(w0)) / 2; + b1 = -(1 + cos(w0)); + b2 = (1 + cos(w0)) / 2; + + p->hp[0] =-a1 / a0; + p->hp[1] =-a2 / a0; + p->hp[2] = b0 / a0; + p->hp[3] = b1 / a0; + p->hp[4] = b2 / a0; + + w0 = 2 * M_PI * ceil / srate; + alpha = sin(w0) / (2. * 0.707); + a0 = 1 + alpha; + a1 = -2 * cos(w0); + a2 = 1 - alpha; + b0 = (1 - cos(w0)) / 2; + b1 = 1 - cos(w0); + b2 = (1 - cos(w0)) / 2; + + p->lp[0] =-a1 / a0; + p->lp[1] =-a2 / a0; + p->lp[2] = b0 / a0; + p->lp[3] = b1 / a0; + p->lp[4] = b2 / a0; +} + +static double bprocess(double in, const double *const c, + double *w1, double *w2) +{ + double out = c[2] * in + *w1; + + *w1 = c[3] * in + *w2 + c[0] * out; + *w2 = c[4] * in + c[1] * out; + + return out; +} + +static double distortion_process(AExciterContext *s, ChannelParams *p, double in) +{ + double proc = in, med; + + proc = bprocess(proc, p->hp, &p->hw[0][0], &p->hw[0][1]); + proc = bprocess(proc, p->hp, &p->hw[1][0], &p->hw[1][1]); + + if (proc >= 0.0) { + med = (D(p->ap + proc * (p->kpa - proc)) + p->kpb) * p->pwrq; + } else { + med = (D(p->an - proc * (p->kna + proc)) + p->knb) * p->pwrq * -1.0; + } + + proc = p->srct * (med - p->prev_med + p->prev_out); + p->prev_med = M(med); + p->prev_out = M(proc); + + proc = bprocess(proc, p->hp, &p->hw[2][0], &p->hw[2][1]); + proc = bprocess(proc, p->hp, &p->hw[3][0], &p->hw[3][1]); + + if (s->ceil >= 10000.) { + proc = bprocess(proc, p->lp, &p->lw[0][0], &p->lw[0][1]); + proc = bprocess(proc, p->lp, &p->lw[1][0], &p->lw[1][1]); + } + + return proc; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AExciterContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + const double *src = (const double *)in->data[0]; + const double level_in = s->level_in; + const double level_out = s->level_out; + const double amount = s->amount; + const double listen = 1.0 - s->listen; + double *dst; + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_audio_buffer(inlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + dst = (double *)out->data[0]; + for (int n = 0; n < in->nb_samples; n++) { + for (int c = 0; c < inlink->channels; c++) { + double sample = src[c] * level_in; + + sample = distortion_process(s, &s->cp[c], sample); + sample = sample * amount + listen * src[c]; + + sample *= level_out; + if (ctx->is_disabled) + dst[c] = src[c]; + else + dst[c] = sample; + } + + src += inlink->channels; + dst += inlink->channels; + } + + if (in != out) + av_frame_free(&in); + + return ff_filter_frame(outlink, out); +} + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats; + AVFilterChannelLayouts *layouts; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_DBL, + AV_SAMPLE_FMT_NONE + }; + int ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + formats = ff_all_samplerates(); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_samplerates(ctx, formats); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AExciterContext *s = ctx->priv; + + av_freep(&s->cp); +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AExciterContext *s = ctx->priv; + + if (!s->cp) + s->cp = av_calloc(inlink->channels, sizeof(*s->cp)); + if (!s->cp) + return AVERROR(ENOMEM); + + for (int i = 0; i < inlink->channels; i++) + set_params(&s->cp[i], s->blend, s->drive, inlink->sample_rate, + s->freq, s->ceil); + + return 0; +} + +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + AVFilterLink *inlink = ctx->inputs[0]; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_input(inlink); +} + +static const AVFilterPad avfilter_af_aexciter_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_input, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad avfilter_af_aexciter_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_aexciter = { + .name = "aexciter", + .description = NULL_IF_CONFIG_SMALL("Enhance high frequency part of audio."), + .priv_size = sizeof(AExciterContext), + .priv_class = &aexciter_class, + .uninit = uninit, + .query_formats = query_formats, + .inputs = avfilter_af_aexciter_inputs, + .outputs = avfilter_af_aexciter_outputs, + .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, +}; diff -Nru ffmpeg-4.2.2/libavfilter/af_afade.c ffmpeg-4.4/libavfilter/af_afade.c --- ffmpeg-4.2.2/libavfilter/af_afade.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_afade.c 2021-04-08 21:28:39.000000000 +0000 @@ -51,10 +51,11 @@ int curve0, int curve1); } AudioFadeContext; -enum CurveType { TRI, QSIN, ESIN, HSIN, LOG, IPAR, QUA, CUB, SQU, CBR, PAR, EXP, IQSIN, IHSIN, DESE, DESI, LOSI, NONE, NB_CURVES }; +enum CurveType { NONE = -1, TRI, QSIN, ESIN, HSIN, LOG, IPAR, QUA, CUB, SQU, CBR, PAR, EXP, IQSIN, IHSIN, DESE, DESI, LOSI, SINC, ISINC, NB_CURVES }; #define OFFSET(x) offsetof(AudioFadeContext, x) #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define TFLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static int query_formats(AVFilterContext *ctx) { @@ -153,6 +154,12 @@ gain = (A - B) / (C - B); } break; + case SINC: + gain = gain >= 1.0 ? 1.0 : sin(M_PI * (1.0 - gain)) / (M_PI * (1.0 - gain)); + break; + case ISINC: + gain = gain <= 0.0 ? 0.0 : 1.0 - sin(M_PI * gain) / (M_PI * gain); + break; case NONE: gain = 1.0; break; @@ -223,8 +230,10 @@ if (s->duration) s->nb_samples = av_rescale(s->duration, outlink->sample_rate, AV_TIME_BASE); + s->duration = 0; if (s->start_time) s->start_sample = av_rescale(s->start_time, outlink->sample_rate, AV_TIME_BASE); + s->start_time = 0; return 0; } @@ -232,38 +241,40 @@ #if CONFIG_AFADE_FILTER static const AVOption afade_options[] = { - { "type", "set the fade direction", OFFSET(type), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FLAGS, "type" }, - { "t", "set the fade direction", OFFSET(type), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FLAGS, "type" }, - { "in", "fade-in", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "type" }, - { "out", "fade-out", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "type" }, - { "start_sample", "set number of first sample to start fading", OFFSET(start_sample), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, FLAGS }, - { "ss", "set number of first sample to start fading", OFFSET(start_sample), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, FLAGS }, - { "nb_samples", "set number of samples for fade duration", OFFSET(nb_samples), AV_OPT_TYPE_INT64, {.i64 = 44100}, 1, INT64_MAX, FLAGS }, - { "ns", "set number of samples for fade duration", OFFSET(nb_samples), AV_OPT_TYPE_INT64, {.i64 = 44100}, 1, INT64_MAX, FLAGS }, - { "start_time", "set time to start fading", OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, - { "st", "set time to start fading", OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, - { "duration", "set fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, - { "d", "set fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, - { "curve", "set fade curve type", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, 0, NB_CURVES - 1, FLAGS, "curve" }, - { "c", "set fade curve type", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, 0, NB_CURVES - 1, FLAGS, "curve" }, - { "tri", "linear slope", 0, AV_OPT_TYPE_CONST, {.i64 = TRI }, 0, 0, FLAGS, "curve" }, - { "qsin", "quarter of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = QSIN }, 0, 0, FLAGS, "curve" }, - { "esin", "exponential sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = ESIN }, 0, 0, FLAGS, "curve" }, - { "hsin", "half of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = HSIN }, 0, 0, FLAGS, "curve" }, - { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64 = LOG }, 0, 0, FLAGS, "curve" }, - { "ipar", "inverted parabola", 0, AV_OPT_TYPE_CONST, {.i64 = IPAR }, 0, 0, FLAGS, "curve" }, - { "qua", "quadratic", 0, AV_OPT_TYPE_CONST, {.i64 = QUA }, 0, 0, FLAGS, "curve" }, - { "cub", "cubic", 0, AV_OPT_TYPE_CONST, {.i64 = CUB }, 0, 0, FLAGS, "curve" }, - { "squ", "square root", 0, AV_OPT_TYPE_CONST, {.i64 = SQU }, 0, 0, FLAGS, "curve" }, - { "cbr", "cubic root", 0, AV_OPT_TYPE_CONST, {.i64 = CBR }, 0, 0, FLAGS, "curve" }, - { "par", "parabola", 0, AV_OPT_TYPE_CONST, {.i64 = PAR }, 0, 0, FLAGS, "curve" }, - { "exp", "exponential", 0, AV_OPT_TYPE_CONST, {.i64 = EXP }, 0, 0, FLAGS, "curve" }, - { "iqsin", "inverted quarter of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = IQSIN}, 0, 0, FLAGS, "curve" }, - { "ihsin", "inverted half of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = IHSIN}, 0, 0, FLAGS, "curve" }, - { "dese", "double-exponential seat", 0, AV_OPT_TYPE_CONST, {.i64 = DESE }, 0, 0, FLAGS, "curve" }, - { "desi", "double-exponential sigmoid", 0, AV_OPT_TYPE_CONST, {.i64 = DESI }, 0, 0, FLAGS, "curve" }, - { "losi", "logistic sigmoid", 0, AV_OPT_TYPE_CONST, {.i64 = LOSI }, 0, 0, FLAGS, "curve" }, - { "nofade", "no fade; keep audio as-is", 0, AV_OPT_TYPE_CONST, {.i64 = NONE }, 0, 0, FLAGS, "curve" }, + { "type", "set the fade direction", OFFSET(type), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, TFLAGS, "type" }, + { "t", "set the fade direction", OFFSET(type), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, TFLAGS, "type" }, + { "in", "fade-in", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, TFLAGS, "type" }, + { "out", "fade-out", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, TFLAGS, "type" }, + { "start_sample", "set number of first sample to start fading", OFFSET(start_sample), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, TFLAGS }, + { "ss", "set number of first sample to start fading", OFFSET(start_sample), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, TFLAGS }, + { "nb_samples", "set number of samples for fade duration", OFFSET(nb_samples), AV_OPT_TYPE_INT64, {.i64 = 44100}, 1, INT64_MAX, TFLAGS }, + { "ns", "set number of samples for fade duration", OFFSET(nb_samples), AV_OPT_TYPE_INT64, {.i64 = 44100}, 1, INT64_MAX, TFLAGS }, + { "start_time", "set time to start fading", OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, INT64_MAX, TFLAGS }, + { "st", "set time to start fading", OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, INT64_MAX, TFLAGS }, + { "duration", "set fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, INT64_MAX, TFLAGS }, + { "d", "set fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, INT64_MAX, TFLAGS }, + { "curve", "set fade curve type", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1, TFLAGS, "curve" }, + { "c", "set fade curve type", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1, TFLAGS, "curve" }, + { "nofade", "no fade; keep audio as-is", 0, AV_OPT_TYPE_CONST, {.i64 = NONE }, 0, 0, TFLAGS, "curve" }, + { "tri", "linear slope", 0, AV_OPT_TYPE_CONST, {.i64 = TRI }, 0, 0, TFLAGS, "curve" }, + { "qsin", "quarter of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = QSIN }, 0, 0, TFLAGS, "curve" }, + { "esin", "exponential sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = ESIN }, 0, 0, TFLAGS, "curve" }, + { "hsin", "half of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = HSIN }, 0, 0, TFLAGS, "curve" }, + { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64 = LOG }, 0, 0, TFLAGS, "curve" }, + { "ipar", "inverted parabola", 0, AV_OPT_TYPE_CONST, {.i64 = IPAR }, 0, 0, TFLAGS, "curve" }, + { "qua", "quadratic", 0, AV_OPT_TYPE_CONST, {.i64 = QUA }, 0, 0, TFLAGS, "curve" }, + { "cub", "cubic", 0, AV_OPT_TYPE_CONST, {.i64 = CUB }, 0, 0, TFLAGS, "curve" }, + { "squ", "square root", 0, AV_OPT_TYPE_CONST, {.i64 = SQU }, 0, 0, TFLAGS, "curve" }, + { "cbr", "cubic root", 0, AV_OPT_TYPE_CONST, {.i64 = CBR }, 0, 0, TFLAGS, "curve" }, + { "par", "parabola", 0, AV_OPT_TYPE_CONST, {.i64 = PAR }, 0, 0, TFLAGS, "curve" }, + { "exp", "exponential", 0, AV_OPT_TYPE_CONST, {.i64 = EXP }, 0, 0, TFLAGS, "curve" }, + { "iqsin", "inverted quarter of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = IQSIN}, 0, 0, TFLAGS, "curve" }, + { "ihsin", "inverted half of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = IHSIN}, 0, 0, TFLAGS, "curve" }, + { "dese", "double-exponential seat", 0, AV_OPT_TYPE_CONST, {.i64 = DESE }, 0, 0, TFLAGS, "curve" }, + { "desi", "double-exponential sigmoid", 0, AV_OPT_TYPE_CONST, {.i64 = DESI }, 0, 0, TFLAGS, "curve" }, + { "losi", "logistic sigmoid", 0, AV_OPT_TYPE_CONST, {.i64 = LOSI }, 0, 0, TFLAGS, "curve" }, + { "sinc", "sine cardinal function", 0, AV_OPT_TYPE_CONST, {.i64 = SINC }, 0, 0, TFLAGS, "curve" }, + { "isinc", "inverted sine cardinal function", 0, AV_OPT_TYPE_CONST, {.i64 = ISINC}, 0, 0, TFLAGS, "curve" }, { NULL } }; @@ -324,6 +335,18 @@ return ff_filter_frame(outlink, out_buf); } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_output(ctx->outputs[0]); +} + static const AVFilterPad avfilter_af_afade_inputs[] = { { .name = "default", @@ -351,6 +374,7 @@ .inputs = avfilter_af_afade_inputs, .outputs = avfilter_af_afade_outputs, .priv_class = &afade_class, + .process_command = process_command, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; @@ -361,12 +385,13 @@ static const AVOption acrossfade_options[] = { { "nb_samples", "set number of samples for cross fade duration", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 44100}, 1, INT32_MAX/10, FLAGS }, { "ns", "set number of samples for cross fade duration", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 44100}, 1, INT32_MAX/10, FLAGS }, - { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, 60000000, FLAGS }, - { "d", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, 60000000, FLAGS }, + { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, 60000000, FLAGS }, + { "d", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0 }, 0, 60000000, FLAGS }, { "overlap", "overlap 1st stream end with 2nd stream start", OFFSET(overlap), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, FLAGS }, { "o", "overlap 1st stream end with 2nd stream start", OFFSET(overlap), AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, FLAGS }, - { "curve1", "set fade curve type for 1st stream", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, 0, NB_CURVES - 1, FLAGS, "curve" }, - { "c1", "set fade curve type for 1st stream", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, 0, NB_CURVES - 1, FLAGS, "curve" }, + { "curve1", "set fade curve type for 1st stream", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1, FLAGS, "curve" }, + { "c1", "set fade curve type for 1st stream", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1, FLAGS, "curve" }, + { "nofade", "no fade; keep audio as-is", 0, AV_OPT_TYPE_CONST, {.i64 = NONE }, 0, 0, FLAGS, "curve" }, { "tri", "linear slope", 0, AV_OPT_TYPE_CONST, {.i64 = TRI }, 0, 0, FLAGS, "curve" }, { "qsin", "quarter of sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = QSIN }, 0, 0, FLAGS, "curve" }, { "esin", "exponential sine wave", 0, AV_OPT_TYPE_CONST, {.i64 = ESIN }, 0, 0, FLAGS, "curve" }, @@ -384,9 +409,10 @@ { "dese", "double-exponential seat", 0, AV_OPT_TYPE_CONST, {.i64 = DESE }, 0, 0, FLAGS, "curve" }, { "desi", "double-exponential sigmoid", 0, AV_OPT_TYPE_CONST, {.i64 = DESI }, 0, 0, FLAGS, "curve" }, { "losi", "logistic sigmoid", 0, AV_OPT_TYPE_CONST, {.i64 = LOSI }, 0, 0, FLAGS, "curve" }, - { "nofade", "no fade; keep audio as-is", 0, AV_OPT_TYPE_CONST, {.i64 = NONE }, 0, 0, FLAGS, "curve" }, - { "curve2", "set fade curve type for 2nd stream", OFFSET(curve2), AV_OPT_TYPE_INT, {.i64 = TRI }, 0, NB_CURVES - 1, FLAGS, "curve" }, - { "c2", "set fade curve type for 2nd stream", OFFSET(curve2), AV_OPT_TYPE_INT, {.i64 = TRI }, 0, NB_CURVES - 1, FLAGS, "curve" }, + { "sinc", "sine cardinal function", 0, AV_OPT_TYPE_CONST, {.i64 = SINC }, 0, 0, FLAGS, "curve" }, + { "isinc", "inverted sine cardinal function", 0, AV_OPT_TYPE_CONST, {.i64 = ISINC}, 0, 0, FLAGS, "curve" }, + { "curve2", "set fade curve type for 2nd stream", OFFSET(curve2), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1, FLAGS, "curve" }, + { "c2", "set fade curve type for 2nd stream", OFFSET(curve2), AV_OPT_TYPE_INT, {.i64 = TRI }, NONE, NB_CURVES - 1, FLAGS, "curve" }, { NULL } }; @@ -454,21 +480,22 @@ if (s->crossfade_is_over) { ret = ff_inlink_consume_frame(ctx->inputs[1], &in); - if (ret < 0) { + if (ret > 0) { + in->pts = s->pts; + s->pts += av_rescale_q(in->nb_samples, + (AVRational){ 1, outlink->sample_rate }, outlink->time_base); + return ff_filter_frame(outlink, in); + } else if (ret < 0) { return ret; } else if (ff_inlink_acknowledge_status(ctx->inputs[1], &status, &pts)) { ff_outlink_set_status(ctx->outputs[0], status, pts); return 0; - } else { - if (ff_outlink_frame_wanted(ctx->outputs[0]) && !in) { + } else if (!ret) { + if (ff_outlink_frame_wanted(ctx->outputs[0])) { ff_inlink_request_frame(ctx->inputs[1]); return 0; } } - in->pts = s->pts; - s->pts += av_rescale_q(in->nb_samples, - (AVRational){ 1, outlink->sample_rate }, outlink->time_base); - return ff_filter_frame(outlink, in); } if (ff_inlink_queued_samples(ctx->inputs[0]) > s->nb_samples) { @@ -483,7 +510,8 @@ s->pts += av_rescale_q(in->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); return ff_filter_frame(outlink, in); - } else if (ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples) { + } else if (ff_inlink_queued_samples(ctx->inputs[0]) >= s->nb_samples && + ff_inlink_queued_samples(ctx->inputs[1]) >= s->nb_samples && s->cf0_eof) { if (s->overlap) { out = ff_get_audio_buffer(outlink, s->nb_samples); if (!out) diff -Nru ffmpeg-4.2.2/libavfilter/af_afftdn.c ffmpeg-4.4/libavfilter/af_afftdn.c --- ffmpeg-4.2.2/libavfilter/af_afftdn.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_afftdn.c 2020-07-11 10:39:30.000000000 +0000 @@ -141,24 +141,25 @@ } AudioFFTDeNoiseContext; #define OFFSET(x) offsetof(AudioFFTDeNoiseContext, x) -#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define AFR AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption afftdn_options[] = { - { "nr", "set the noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_FLOAT, {.dbl = 12}, .01, 97, A }, - { "nf", "set the noise floor", OFFSET(noise_floor), AV_OPT_TYPE_FLOAT, {.dbl =-50}, -80,-20, A }, - { "nt", "set the noise type", OFFSET(noise_type), AV_OPT_TYPE_INT, {.i64 = WHITE_NOISE}, WHITE_NOISE, NB_NOISE-1, A, "type" }, - { "w", "white noise", 0, AV_OPT_TYPE_CONST, {.i64 = WHITE_NOISE}, 0, 0, A, "type" }, - { "v", "vinyl noise", 0, AV_OPT_TYPE_CONST, {.i64 = VINYL_NOISE}, 0, 0, A, "type" }, - { "s", "shellac noise", 0, AV_OPT_TYPE_CONST, {.i64 = SHELLAC_NOISE}, 0, 0, A, "type" }, - { "c", "custom noise", 0, AV_OPT_TYPE_CONST, {.i64 = CUSTOM_NOISE}, 0, 0, A, "type" }, - { "bn", "set the custom bands noise", OFFSET(band_noise_str), AV_OPT_TYPE_STRING, {.str = 0}, 0, 0, A }, - { "rf", "set the residual floor", OFFSET(residual_floor), AV_OPT_TYPE_FLOAT, {.dbl =-38}, -80,-20, A }, - { "tn", "track noise", OFFSET(track_noise), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, A }, - { "tr", "track residual", OFFSET(track_residual), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, A }, - { "om", "set output mode", OFFSET(output_mode), AV_OPT_TYPE_INT, {.i64 = OUT_MODE}, 0, NB_MODES-1, A, "mode" }, - { "i", "input", 0, AV_OPT_TYPE_CONST, {.i64 = IN_MODE}, 0, 0, A, "mode" }, - { "o", "output", 0, AV_OPT_TYPE_CONST, {.i64 = OUT_MODE}, 0, 0, A, "mode" }, - { "n", "noise", 0, AV_OPT_TYPE_CONST, {.i64 = NOISE_MODE}, 0, 0, A, "mode" }, + { "nr", "set the noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_FLOAT, {.dbl = 12}, .01, 97, AFR }, + { "nf", "set the noise floor", OFFSET(noise_floor), AV_OPT_TYPE_FLOAT, {.dbl =-50}, -80,-20, AFR }, + { "nt", "set the noise type", OFFSET(noise_type), AV_OPT_TYPE_INT, {.i64 = WHITE_NOISE}, WHITE_NOISE, NB_NOISE-1, AF, "type" }, + { "w", "white noise", 0, AV_OPT_TYPE_CONST, {.i64 = WHITE_NOISE}, 0, 0, AF, "type" }, + { "v", "vinyl noise", 0, AV_OPT_TYPE_CONST, {.i64 = VINYL_NOISE}, 0, 0, AF, "type" }, + { "s", "shellac noise", 0, AV_OPT_TYPE_CONST, {.i64 = SHELLAC_NOISE}, 0, 0, AF, "type" }, + { "c", "custom noise", 0, AV_OPT_TYPE_CONST, {.i64 = CUSTOM_NOISE}, 0, 0, AF, "type" }, + { "bn", "set the custom bands noise", OFFSET(band_noise_str), AV_OPT_TYPE_STRING, {.str = 0}, 0, 0, AF }, + { "rf", "set the residual floor", OFFSET(residual_floor), AV_OPT_TYPE_FLOAT, {.dbl =-38}, -80,-20, AFR }, + { "tn", "track noise", OFFSET(track_noise), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AFR }, + { "tr", "track residual", OFFSET(track_residual), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AFR }, + { "om", "set output mode", OFFSET(output_mode), AV_OPT_TYPE_INT, {.i64 = OUT_MODE}, 0, NB_MODES-1, AFR, "mode" }, + { "i", "input", 0, AV_OPT_TYPE_CONST, {.i64 = IN_MODE}, 0, 0, AFR, "mode" }, + { "o", "output", 0, AV_OPT_TYPE_CONST, {.i64 = OUT_MODE}, 0, 0, AFR, "mode" }, + { "n", "noise", 0, AV_OPT_TYPE_CONST, {.i64 = NOISE_MODE}, 0, 0, AFR, "mode" }, { NULL } }; @@ -1260,7 +1261,7 @@ ret = ff_filter_frame(outlink, out); if (ret < 0) goto end; - s->pts += s->sample_advance; + s->pts += av_rescale_q(s->sample_advance, (AVRational){1, outlink->sample_rate}, outlink->time_base); end: av_frame_free(&in); @@ -1375,6 +1376,7 @@ { AudioFFTDeNoiseContext *s = ctx->priv; int need_reset = 0; + int ret = 0; if (!strcmp(cmd, "sample_noise") || !strcmp(cmd, "sn")) { @@ -1386,31 +1388,11 @@ s->sample_noise_start = 0; s->sample_noise_end = 1; } - } else if (!strcmp(cmd, "nr") || - !strcmp(cmd, "noise_reduction")) { - float nr; - - if (av_sscanf(args, "%f", &nr) == 1) { - s->noise_reduction = av_clipf(nr, 0.01, 97); - need_reset = 1; - } - } else if (!strcmp(cmd, "nf") || - !strcmp(cmd, "noise_floor")) { - float nf; - - if (av_sscanf(args, "%f", &nf) == 1) { - s->noise_floor = av_clipf(nf, -80, -20); - need_reset = 1; - } - } else if (!strcmp(cmd, "output_mode") || - !strcmp(cmd, "om")) { - if (!strcmp(args, "i")) { - s->output_mode = IN_MODE; - } else if (!strcmp(args, "o")) { - s->output_mode = OUT_MODE; - } else if (!strcmp(args, "n")) { - s->output_mode = NOISE_MODE; - } + } else { + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + need_reset = 1; } if (need_reset) diff -Nru ffmpeg-4.2.2/libavfilter/af_afftfilt.c ffmpeg-4.4/libavfilter/af_afftfilt.c --- ffmpeg-4.2.2/libavfilter/af_afftfilt.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_afftfilt.c 2021-04-08 21:28:39.000000000 +0000 @@ -40,6 +40,7 @@ FFTComplex **fft_data; FFTComplex **fft_temp; int nb_exprs; + int channels; int window_size; AVExpr **real; AVExpr **imag; @@ -117,7 +118,7 @@ static double imagf(void *priv, double x, double ch) { return getimag(priv, x, ch); } static const char *const func2_names[] = { "real", "imag", NULL }; -double (*func2[])(void *, double, double) = { realf, imagf, NULL }; +static double (*const func2[])(void *, double, double) = { realf, imagf, NULL }; static int config_input(AVFilterLink *inlink) { @@ -129,6 +130,7 @@ char *args; const char *last_expr = "1"; + s->channels = inlink->channels; s->pts = AV_NOPTS_VALUE; s->fft_bits = av_log2(s->fft_size); s->fft = av_fft_init(s->fft_bits, 0); @@ -176,30 +178,32 @@ ret = av_expr_parse(&s->real[ch], arg ? arg : last_expr, var_names, NULL, NULL, func2_names, func2, 0, ctx); if (ret < 0) - break; + goto fail; if (arg) last_expr = arg; s->nb_exprs++; } - av_free(args); + av_freep(&args); args = av_strdup(s->img_str ? s->img_str : s->real_str); if (!args) return AVERROR(ENOMEM); + saveptr = NULL; + last_expr = "1"; for (ch = 0; ch < inlink->channels; ch++) { char *arg = av_strtok(ch == 0 ? args : NULL, "|", &saveptr); ret = av_expr_parse(&s->imag[ch], arg ? arg : last_expr, var_names, NULL, NULL, func2_names, func2, 0, ctx); if (ret < 0) - break; + goto fail; if (arg) last_expr = arg; } - av_free(args); + av_freep(&args); s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->window_size); if (!s->fifo) @@ -221,6 +225,9 @@ if (!s->buffer) return AVERROR(ENOMEM); +fail: + av_freep(&args); + return ret; } @@ -313,7 +320,7 @@ } out->pts = s->pts; - s->pts += s->hop_size; + s->pts += av_rescale_q(s->hop_size, (AVRational){1, outlink->sample_rate}, outlink->time_base); for (ch = 0; ch < inlink->channels; ch++) { float *dst = (float *)out->extended_data[ch]; @@ -430,7 +437,7 @@ av_fft_end(s->fft); av_fft_end(s->ifft); - for (i = 0; i < s->nb_exprs; i++) { + for (i = 0; i < s->channels; i++) { if (s->fft_data) av_freep(&s->fft_data[i]); if (s->fft_temp) diff -Nru ffmpeg-4.2.2/libavfilter/af_afir.c ffmpeg-4.4/libavfilter/af_afir.c --- ffmpeg-4.2.2/libavfilter/af_afir.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_afir.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,6 +25,7 @@ #include +#include "libavutil/avstring.h" #include "libavutil/common.h" #include "libavutil/float_dsp.h" #include "libavutil/intreadwrite.h" @@ -56,10 +57,27 @@ sum[2 * n] += t[2 * n] * c[2 * n]; } +static void direct(const float *in, const FFTComplex *ir, int len, float *out) +{ + for (int n = 0; n < len; n++) + for (int m = 0; m <= n; m++) + out[n] += ir[m].re * in[n - m]; +} + +static void fir_fadd(AudioFIRContext *s, float *dst, const float *src, int nb_samples) +{ + if ((nb_samples & 15) == 0 && nb_samples >= 16) { + s->fdsp->vector_fmac_scalar(dst, src, 1.f, nb_samples); + } else { + for (int n = 0; n < nb_samples; n++) + dst[n] += src[n]; + } +} + static int fir_quantum(AVFilterContext *ctx, AVFrame *out, int ch, int offset) { AudioFIRContext *s = ctx->priv; - const float *in = (const float *)s->in[0]->extended_data[ch] + offset; + const float *in = (const float *)s->in->extended_data[ch] + offset; float *block, *buf, *ptr = (float *)out->extended_data[ch] + offset; const int nb_samples = FFMIN(s->min_part_size, out->nb_samples - offset); int n, i, j; @@ -70,8 +88,13 @@ float *dst = (float *)seg->output->extended_data[ch]; float *sum = (float *)seg->sum->extended_data[ch]; - s->fdsp->vector_fmul_scalar(src + seg->input_offset, in, s->dry_gain, FFALIGN(nb_samples, 4)); - emms_c(); + if (s->min_part_size >= 8) { + s->fdsp->vector_fmul_scalar(src + seg->input_offset, in, s->dry_gain, FFALIGN(nb_samples, 4)); + emms_c(); + } else { + for (n = 0; n < nb_samples; n++) + src[seg->input_offset + n] = in[n] * s->dry_gain; + } seg->output_offset[ch] += s->min_part_size; if (seg->output_offset[ch] == seg->part_size) { @@ -80,6 +103,30 @@ memmove(src, src + s->min_part_size, (seg->input_size - s->min_part_size) * sizeof(*src)); dst += seg->output_offset[ch]; + fir_fadd(s, ptr, dst, nb_samples); + continue; + } + + if (seg->part_size < 8) { + memset(dst, 0, sizeof(*dst) * seg->part_size * seg->nb_partitions); + + j = seg->part_index[ch]; + + for (i = 0; i < seg->nb_partitions; i++) { + const int coffset = j * seg->coeff_size; + const FFTComplex *coeff = (const FFTComplex *)seg->coeff->extended_data[ch * !s->one2many] + coffset; + + direct(src, coeff, nb_samples, dst); + + if (j == 0) + j = seg->nb_partitions; + j--; + } + + seg->part_index[ch] = (seg->part_index[ch] + 1) % seg->nb_partitions; + + memmove(src, src + s->min_part_size, (seg->input_size - s->min_part_size) * sizeof(*src)); + for (n = 0; n < nb_samples; n++) { ptr[n] += dst[n]; } @@ -114,9 +161,7 @@ av_rdft_calc(seg->irdft[ch], sum); buf = (float *)seg->buffer->extended_data[ch]; - for (n = 0; n < seg->part_size; n++) { - buf[n] += sum[n]; - } + fir_fadd(s, buf, sum, seg->part_size); memcpy(dst, buf, seg->part_size * sizeof(*dst)); @@ -127,13 +172,16 @@ memmove(src, src + s->min_part_size, (seg->input_size - s->min_part_size) * sizeof(*src)); - for (n = 0; n < nb_samples; n++) { - ptr[n] += dst[n]; - } + fir_fadd(s, ptr, dst, nb_samples); } - s->fdsp->vector_fmul_scalar(ptr, ptr, s->wet_gain, FFALIGN(nb_samples, 4)); - emms_c(); + if (s->min_part_size >= 8) { + s->fdsp->vector_fmul_scalar(ptr, ptr, s->wet_gain, FFALIGN(nb_samples, 4)); + emms_c(); + } else { + for (n = 0; n < nb_samples; n++) + ptr[n] *= s->wet_gain; + } return 0; } @@ -175,7 +223,7 @@ if (s->pts == AV_NOPTS_VALUE) s->pts = in->pts; - s->in[0] = in; + s->in = in; ctx->internal->execute(ctx, fir_channels, out, NULL, FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx))); @@ -184,7 +232,7 @@ s->pts += av_rescale_q(out->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); av_frame_free(&in); - s->in[0] = NULL; + s->in = NULL; return ff_filter_frame(outlink, out); } @@ -255,9 +303,9 @@ if (!mag || !phase || !delay) goto end; - channel = av_clip(s->ir_channel, 0, s->in[1]->channels - 1); + channel = av_clip(s->ir_channel, 0, s->ir[s->selir]->channels - 1); for (i = 0; i < s->w; i++) { - const float *src = (const float *)s->in[1]->extended_data[channel]; + const float *src = (const float *)s->ir[s->selir]->extended_data[channel]; double w = i * M_PI / (s->w - 1); double div, real_num = 0., imag_num = 0., real = 0., imag = 0.; @@ -350,7 +398,7 @@ if (!seg->part_index || !seg->output_offset) return AVERROR(ENOMEM); - for (int ch = 0; ch < ctx->inputs[0]->channels; ch++) { + for (int ch = 0; ch < ctx->inputs[0]->channels && part_size >= 8; ch++) { seg->rdft[ch] = av_rdft_init(av_log2(2 * part_size), DFT_R2C); seg->irdft[ch] = av_rdft_init(av_log2(2 * part_size), IDFT_C2R); if (!seg->rdft[ch] || !seg->irdft[ch]) @@ -360,7 +408,7 @@ seg->sum = ff_get_audio_buffer(ctx->inputs[0], seg->fft_length); seg->block = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->block_size); seg->buffer = ff_get_audio_buffer(ctx->inputs[0], seg->part_size); - seg->coeff = ff_get_audio_buffer(ctx->inputs[1], seg->nb_partitions * seg->coeff_size * 2); + seg->coeff = ff_get_audio_buffer(ctx->inputs[1 + s->selir], seg->nb_partitions * seg->coeff_size * 2); seg->input = ff_get_audio_buffer(ctx->inputs[0], seg->input_size); seg->output = ff_get_audio_buffer(ctx->inputs[0], seg->part_size); if (!seg->buffer || !seg->sum || !seg->block || !seg->coeff || !seg->input || !seg->output) @@ -369,79 +417,116 @@ return 0; } +static void uninit_segment(AVFilterContext *ctx, AudioFIRSegment *seg) +{ + AudioFIRContext *s = ctx->priv; + + if (seg->rdft) { + for (int ch = 0; ch < s->nb_channels; ch++) { + av_rdft_end(seg->rdft[ch]); + } + } + av_freep(&seg->rdft); + + if (seg->irdft) { + for (int ch = 0; ch < s->nb_channels; ch++) { + av_rdft_end(seg->irdft[ch]); + } + } + av_freep(&seg->irdft); + + av_freep(&seg->output_offset); + av_freep(&seg->part_index); + + av_frame_free(&seg->block); + av_frame_free(&seg->sum); + av_frame_free(&seg->buffer); + av_frame_free(&seg->coeff); + av_frame_free(&seg->input); + av_frame_free(&seg->output); + seg->input_size = 0; +} + static int convert_coeffs(AVFilterContext *ctx) { AudioFIRContext *s = ctx->priv; - int left, offset = 0, part_size, max_part_size; - int ret, i, ch, n; + int ret, i, ch, n, cur_nb_taps; float power = 0; - s->nb_taps = ff_inlink_queued_samples(ctx->inputs[1]); - if (s->nb_taps <= 0) - return AVERROR(EINVAL); + if (!s->nb_taps) { + int part_size, max_part_size; + int left, offset = 0; - if (s->minp > s->maxp) { - s->maxp = s->minp; - } + s->nb_taps = ff_inlink_queued_samples(ctx->inputs[1 + s->selir]); + if (s->nb_taps <= 0) + return AVERROR(EINVAL); - left = s->nb_taps; - part_size = 1 << av_log2(s->minp); - max_part_size = 1 << av_log2(s->maxp); + if (s->minp > s->maxp) { + s->maxp = s->minp; + } + + left = s->nb_taps; + part_size = 1 << av_log2(s->minp); + max_part_size = 1 << av_log2(s->maxp); + + s->min_part_size = part_size; - s->min_part_size = part_size; + for (i = 0; left > 0; i++) { + int step = part_size == max_part_size ? INT_MAX : 1 + (i == 0); + int nb_partitions = FFMIN(step, (left + part_size - 1) / part_size); - for (i = 0; left > 0; i++) { - int step = part_size == max_part_size ? INT_MAX : 1 + (i == 0); - int nb_partitions = FFMIN(step, (left + part_size - 1) / part_size); + s->nb_segments = i + 1; + ret = init_segment(ctx, &s->seg[i], offset, nb_partitions, part_size); + if (ret < 0) + return ret; + offset += nb_partitions * part_size; + left -= nb_partitions * part_size; + part_size *= 2; + part_size = FFMIN(part_size, max_part_size); + } + } - s->nb_segments = i + 1; - ret = init_segment(ctx, &s->seg[i], offset, nb_partitions, part_size); + if (!s->ir[s->selir]) { + ret = ff_inlink_consume_samples(ctx->inputs[1 + s->selir], s->nb_taps, s->nb_taps, &s->ir[s->selir]); if (ret < 0) return ret; - offset += nb_partitions * part_size; - left -= nb_partitions * part_size; - part_size *= 2; - part_size = FFMIN(part_size, max_part_size); + if (ret == 0) + return AVERROR_BUG; } - ret = ff_inlink_consume_samples(ctx->inputs[1], s->nb_taps, s->nb_taps, &s->in[1]); - if (ret < 0) - return ret; - if (ret == 0) - return AVERROR_BUG; - if (s->response) draw_response(ctx, s->video); s->gain = 1; + cur_nb_taps = s->ir[s->selir]->nb_samples; switch (s->gtype) { case -1: /* nothing to do */ break; case 0: - for (ch = 0; ch < ctx->inputs[1]->channels; ch++) { - float *time = (float *)s->in[1]->extended_data[!s->one2many * ch]; + for (ch = 0; ch < ctx->inputs[1 + s->selir]->channels; ch++) { + float *time = (float *)s->ir[s->selir]->extended_data[!s->one2many * ch]; - for (i = 0; i < s->nb_taps; i++) + for (i = 0; i < cur_nb_taps; i++) power += FFABS(time[i]); } - s->gain = ctx->inputs[1]->channels / power; + s->gain = ctx->inputs[1 + s->selir]->channels / power; break; case 1: - for (ch = 0; ch < ctx->inputs[1]->channels; ch++) { - float *time = (float *)s->in[1]->extended_data[!s->one2many * ch]; + for (ch = 0; ch < ctx->inputs[1 + s->selir]->channels; ch++) { + float *time = (float *)s->ir[s->selir]->extended_data[!s->one2many * ch]; - for (i = 0; i < s->nb_taps; i++) + for (i = 0; i < cur_nb_taps; i++) power += time[i]; } - s->gain = ctx->inputs[1]->channels / power; + s->gain = ctx->inputs[1 + s->selir]->channels / power; break; case 2: - for (ch = 0; ch < ctx->inputs[1]->channels; ch++) { - float *time = (float *)s->in[1]->extended_data[!s->one2many * ch]; + for (ch = 0; ch < ctx->inputs[1 + s->selir]->channels; ch++) { + float *time = (float *)s->ir[s->selir]->extended_data[!s->one2many * ch]; - for (i = 0; i < s->nb_taps; i++) + for (i = 0; i < cur_nb_taps; i++) power += time[i] * time[i]; } s->gain = sqrtf(ch / power); @@ -452,17 +537,17 @@ s->gain = FFMIN(s->gain * s->ir_gain, 1.f); av_log(ctx, AV_LOG_DEBUG, "power %f, gain %f\n", power, s->gain); - for (ch = 0; ch < ctx->inputs[1]->channels; ch++) { - float *time = (float *)s->in[1]->extended_data[!s->one2many * ch]; + for (ch = 0; ch < ctx->inputs[1 + s->selir]->channels; ch++) { + float *time = (float *)s->ir[s->selir]->extended_data[!s->one2many * ch]; - s->fdsp->vector_fmul_scalar(time, time, s->gain, FFALIGN(s->nb_taps, 4)); + s->fdsp->vector_fmul_scalar(time, time, s->gain, FFALIGN(cur_nb_taps, 4)); } - av_log(ctx, AV_LOG_DEBUG, "nb_taps: %d\n", s->nb_taps); + av_log(ctx, AV_LOG_DEBUG, "nb_taps: %d\n", cur_nb_taps); av_log(ctx, AV_LOG_DEBUG, "nb_segments: %d\n", s->nb_segments); - for (ch = 0; ch < ctx->inputs[1]->channels; ch++) { - float *time = (float *)s->in[1]->extended_data[!s->one2many * ch]; + for (ch = 0; ch < ctx->inputs[1 + s->selir]->channels; ch++) { + float *time = (float *)s->ir[s->selir]->extended_data[!s->one2many * ch]; int toffset = 0; for (i = FFMAX(1, s->length * s->nb_taps); i < s->nb_taps; i++) @@ -483,6 +568,14 @@ const int remaining = s->nb_taps - toffset; const int size = remaining >= seg->part_size ? seg->part_size : remaining; + if (size < 8) { + for (n = 0; n < size; n++) + coeff[coffset + n].re = time[toffset + n]; + + toffset += size; + continue; + } + memset(block, 0, sizeof(*block) * seg->fft_length); memcpy(block, time + toffset, size * sizeof(*block)); @@ -510,13 +603,12 @@ } } - av_frame_free(&s->in[1]); s->have_coeffs = 1; return 0; } -static int check_ir(AVFilterLink *link, AVFrame *frame) +static int check_ir(AVFilterLink *link) { AVFilterContext *ctx = link->dst; AudioFIRContext *s = ctx->priv; @@ -543,26 +635,24 @@ FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); if (s->response) FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[1], ctx); - if (!s->eof_coeffs) { - AVFrame *ir = NULL; - - ret = check_ir(ctx->inputs[1], ir); + if (!s->eof_coeffs[s->selir]) { + ret = check_ir(ctx->inputs[1 + s->selir]); if (ret < 0) return ret; - if (ff_outlink_get_status(ctx->inputs[1]) == AVERROR_EOF) - s->eof_coeffs = 1; + if (ff_outlink_get_status(ctx->inputs[1 + s->selir]) == AVERROR_EOF) + s->eof_coeffs[s->selir] = 1; - if (!s->eof_coeffs) { + if (!s->eof_coeffs[s->selir]) { if (ff_outlink_frame_wanted(ctx->outputs[0])) - ff_inlink_request_frame(ctx->inputs[1]); + ff_inlink_request_frame(ctx->inputs[1 + s->selir]); else if (s->response && ff_outlink_frame_wanted(ctx->outputs[1])) - ff_inlink_request_frame(ctx->inputs[1]); + ff_inlink_request_frame(ctx->inputs[1 + s->selir]); return 0; } } - if (!s->have_coeffs && s->eof_coeffs) { + if (!s->have_coeffs && s->eof_coeffs[s->selir]) { ret = convert_coeffs(ctx); if (ret < 0) return ret; @@ -582,8 +672,12 @@ int64_t new_pts = av_rescale_q(s->pts, ctx->inputs[0]->time_base, ctx->outputs[1]->time_base); if (ff_outlink_frame_wanted(ctx->outputs[1]) && old_pts < new_pts) { + AVFrame *clone; s->video->pts = new_pts; - return ff_filter_frame(ctx->outputs[1], av_frame_clone(s->video)); + clone = av_frame_clone(s->video); + if (!clone) + return AVERROR(ENOMEM); + return ff_filter_frame(ctx->outputs[1], clone); } } @@ -635,7 +729,7 @@ if (s->response) { AVFilterLink *videolink = ctx->outputs[1]; formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &videolink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &videolink->incfg.formats)) < 0) return ret; } @@ -650,16 +744,18 @@ } else { AVFilterChannelLayouts *mono = NULL; - ret = ff_add_channel_layout(&mono, AV_CH_LAYOUT_MONO); - if (ret) - return ret; - - if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->outcfg.channel_layouts)) < 0) return ret; - if ((ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0) return ret; - if ((ret = ff_channel_layouts_ref(mono, &ctx->inputs[1]->out_channel_layouts)) < 0) + + ret = ff_add_channel_layout(&mono, AV_CH_LAYOUT_MONO); + if (ret) return ret; + for (int i = 1; i < ctx->nb_inputs; i++) { + if ((ret = ff_channel_layouts_ref(mono, &ctx->inputs[i]->outcfg.channel_layouts)) < 0) + return ret; + } } formats = ff_make_format_list(sample_fmts); @@ -675,49 +771,19 @@ AVFilterContext *ctx = outlink->src; AudioFIRContext *s = ctx->priv; - s->one2many = ctx->inputs[1]->channels == 1; + s->one2many = ctx->inputs[1 + s->selir]->channels == 1; outlink->sample_rate = ctx->inputs[0]->sample_rate; outlink->time_base = ctx->inputs[0]->time_base; outlink->channel_layout = ctx->inputs[0]->channel_layout; outlink->channels = ctx->inputs[0]->channels; s->nb_channels = outlink->channels; - s->nb_coef_channels = ctx->inputs[1]->channels; + s->nb_coef_channels = ctx->inputs[1 + s->selir]->channels; s->pts = AV_NOPTS_VALUE; return 0; } -static void uninit_segment(AVFilterContext *ctx, AudioFIRSegment *seg) -{ - AudioFIRContext *s = ctx->priv; - - if (seg->rdft) { - for (int ch = 0; ch < s->nb_channels; ch++) { - av_rdft_end(seg->rdft[ch]); - } - } - av_freep(&seg->rdft); - - if (seg->irdft) { - for (int ch = 0; ch < s->nb_channels; ch++) { - av_rdft_end(seg->irdft[ch]); - } - } - av_freep(&seg->irdft); - - av_freep(&seg->output_offset); - av_freep(&seg->part_index); - - av_frame_free(&seg->block); - av_frame_free(&seg->sum); - av_frame_free(&seg->buffer); - av_frame_free(&seg->coeff); - av_frame_free(&seg->input); - av_frame_free(&seg->output); - seg->input_size = 0; -} - static av_cold void uninit(AVFilterContext *ctx) { AudioFIRContext *s = ctx->priv; @@ -727,10 +793,14 @@ } av_freep(&s->fdsp); - av_frame_free(&s->in[1]); - for (int i = 0; i < ctx->nb_outputs; i++) - av_freep(&ctx->output_pads[i].name); + for (int i = 0; i < s->nb_irs; i++) { + av_frame_free(&s->ir[i]); + } + + for (unsigned i = 1; i < ctx->nb_inputs; i++) + av_freep(&ctx->input_pads[i].name); + av_frame_free(&s->video); } @@ -767,37 +837,51 @@ AVFilterPad pad, vpad; int ret; - pad = (AVFilterPad){ - .name = av_strdup("default"), - .type = AVMEDIA_TYPE_AUDIO, - .config_props = config_output, + pad = (AVFilterPad) { + .name = "main", + .type = AVMEDIA_TYPE_AUDIO, }; - if (!pad.name) - return AVERROR(ENOMEM); + ret = ff_insert_inpad(ctx, 0, &pad); + if (ret < 0) + return ret; - if (s->response) { - vpad = (AVFilterPad){ - .name = av_strdup("filter_response"), - .type = AVMEDIA_TYPE_VIDEO, - .config_props = config_video, + for (int n = 0; n < s->nb_irs; n++) { + pad = (AVFilterPad) { + .name = av_asprintf("ir%d", n), + .type = AVMEDIA_TYPE_AUDIO, }; - if (!vpad.name) + + if (!pad.name) return AVERROR(ENOMEM); + + ret = ff_insert_inpad(ctx, n + 1, &pad); + if (ret < 0) { + av_freep(&pad.name); + return ret; + } } + pad = (AVFilterPad) { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }; + ret = ff_insert_outpad(ctx, 0, &pad); - if (ret < 0) { - av_freep(&pad.name); + if (ret < 0) return ret; - } if (s->response) { + vpad = (AVFilterPad){ + .name = "filter_response", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_video, + }; + ret = ff_insert_outpad(ctx, 1, &vpad); - if (ret < 0) { - av_freep(&vpad.name); + if (ret < 0) return ret; - } } s->fdsp = avpriv_float_dsp_alloc(0); @@ -809,18 +893,31 @@ return 0; } -static const AVFilterPad afir_inputs[] = { - { - .name = "main", - .type = AVMEDIA_TYPE_AUDIO, - },{ - .name = "ir", - .type = AVMEDIA_TYPE_AUDIO, - }, - { NULL } -}; +static int process_command(AVFilterContext *ctx, + const char *cmd, + const char *arg, + char *res, + int res_len, + int flags) +{ + AudioFIRContext *s = ctx->priv; + int prev_ir = s->selir; + int ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags); + + if (ret < 0) + return ret; + + s->selir = FFMIN(s->nb_irs - 1, s->selir); + + if (prev_ir != s->selir) { + s->have_coeffs = 0; + } + + return 0; +} #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define AFR AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM #define VF AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM #define OFFSET(x) offsetof(AudioFIRContext, x) @@ -842,8 +939,10 @@ { "channel", "set IR channel to display frequency response", OFFSET(ir_channel), AV_OPT_TYPE_INT, {.i64=0}, 0, 1024, VF }, { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "hd720"}, 0, 0, VF }, { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT32_MAX, VF }, - { "minp", "set min partition size", OFFSET(minp), AV_OPT_TYPE_INT, {.i64=8192}, 8, 32768, AF }, + { "minp", "set min partition size", OFFSET(minp), AV_OPT_TYPE_INT, {.i64=8192}, 1, 32768, AF }, { "maxp", "set max partition size", OFFSET(maxp), AV_OPT_TYPE_INT, {.i64=8192}, 8, 32768, AF }, + { "nbirs", "set number of input IRs",OFFSET(nb_irs),AV_OPT_TYPE_INT, {.i64=1}, 1, 32, AF }, + { "ir", "select IR", OFFSET(selir), AV_OPT_TYPE_INT, {.i64=0}, 0, 31, AFR }, { NULL } }; @@ -851,14 +950,15 @@ AVFilter ff_af_afir = { .name = "afir", - .description = NULL_IF_CONFIG_SMALL("Apply Finite Impulse Response filter with supplied coefficients in 2nd stream."), + .description = NULL_IF_CONFIG_SMALL("Apply Finite Impulse Response filter with supplied coefficients in additional stream(s)."), .priv_size = sizeof(AudioFIRContext), .priv_class = &afir_class, .query_formats = query_formats, .init = init, .activate = activate, .uninit = uninit, - .inputs = afir_inputs, - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | + .process_command = process_command, + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | + AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_afir.h ffmpeg-4.4/libavfilter/af_afir.h --- ffmpeg-4.2.2/libavfilter/af_afir.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_afir.h 2020-07-11 10:39:30.000000000 +0000 @@ -74,10 +74,12 @@ int ir_channel; int minp; int maxp; + int nb_irs; + int selir; float gain; - int eof_coeffs; + int eof_coeffs[32]; int have_coeffs; int nb_taps; int nb_channels; @@ -87,7 +89,8 @@ AudioFIRSegment seg[1024]; int nb_segments; - AVFrame *in[2]; + AVFrame *in; + AVFrame *ir[32]; AVFrame *video; int min_part_size; int64_t pts; diff -Nru ffmpeg-4.2.2/libavfilter/af_aformat.c ffmpeg-4.4/libavfilter/af_aformat.c --- ffmpeg-4.2.2/libavfilter/af_aformat.c 2018-07-17 09:27:41.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_aformat.c 2021-04-08 21:28:39.000000000 +0000 @@ -50,14 +50,17 @@ #define F AV_OPT_FLAG_FILTERING_PARAM static const AVOption aformat_options[] = { { "sample_fmts", "A '|'-separated list of sample formats.", OFFSET(formats_str), AV_OPT_TYPE_STRING, .flags = A|F }, + { "f", "A '|'-separated list of sample formats.", OFFSET(formats_str), AV_OPT_TYPE_STRING, .flags = A|F }, { "sample_rates", "A '|'-separated list of sample rates.", OFFSET(sample_rates_str), AV_OPT_TYPE_STRING, .flags = A|F }, + { "r", "A '|'-separated list of sample rates.", OFFSET(sample_rates_str), AV_OPT_TYPE_STRING, .flags = A|F }, { "channel_layouts", "A '|'-separated list of channel layouts.", OFFSET(channel_layouts_str), AV_OPT_TYPE_STRING, .flags = A|F }, + { "cl", "A '|'-separated list of channel layouts.", OFFSET(channel_layouts_str), AV_OPT_TYPE_STRING, .flags = A|F }, { NULL } }; AVFILTER_DEFINE_CLASS(aformat); -#define PARSE_FORMATS(str, type, list, add_to_list, unref_fn, get_fmt, none, desc) \ +#define PARSE_FORMATS(str, type, list, add_to_list, get_fmt, none, desc) \ do { \ char *next, *cur = str, sep; \ int ret; \ @@ -80,7 +83,6 @@ return AVERROR(EINVAL); \ } \ if ((ret = add_to_list(&list, fmt)) < 0) { \ - unref_fn(&list); \ return ret; \ } \ \ @@ -99,16 +101,25 @@ AFormatContext *s = ctx->priv; PARSE_FORMATS(s->formats_str, enum AVSampleFormat, s->formats, - ff_add_format, ff_formats_unref, av_get_sample_fmt, AV_SAMPLE_FMT_NONE, "sample format"); - PARSE_FORMATS(s->sample_rates_str, int, s->sample_rates, ff_add_format, ff_formats_unref, + ff_add_format, av_get_sample_fmt, AV_SAMPLE_FMT_NONE, "sample format"); + PARSE_FORMATS(s->sample_rates_str, int, s->sample_rates, ff_add_format, get_sample_rate, 0, "sample rate"); PARSE_FORMATS(s->channel_layouts_str, uint64_t, s->channel_layouts, - ff_add_channel_layout, ff_channel_layouts_unref, av_get_channel_layout, 0, + ff_add_channel_layout, av_get_channel_layout, 0, "channel layout"); return 0; } +static av_cold void uninit(AVFilterContext *ctx) +{ + AFormatContext *s = ctx->priv; + + ff_formats_unref(&s->formats); + ff_formats_unref(&s->sample_rates); + ff_channel_layouts_unref(&s->channel_layouts); +} + static int query_formats(AVFilterContext *ctx) { AFormatContext *s = ctx->priv; @@ -116,14 +127,18 @@ ret = ff_set_common_formats(ctx, s->formats ? s->formats : ff_all_formats(AVMEDIA_TYPE_AUDIO)); + s->formats = NULL; if (ret < 0) return ret; ret = ff_set_common_samplerates(ctx, s->sample_rates ? s->sample_rates : ff_all_samplerates()); + s->sample_rates = NULL; if (ret < 0) return ret; - return ff_set_common_channel_layouts(ctx, s->channel_layouts ? s->channel_layouts : + ret = ff_set_common_channel_layouts(ctx, s->channel_layouts ? s->channel_layouts : ff_all_channel_counts()); + s->channel_layouts = NULL; + return ret; } static const AVFilterPad avfilter_af_aformat_inputs[] = { @@ -146,6 +161,7 @@ .name = "aformat", .description = NULL_IF_CONFIG_SMALL("Convert the input audio to one of the specified formats."), .init = init, + .uninit = uninit, .query_formats = query_formats, .priv_size = sizeof(AFormatContext), .priv_class = &aformat_class, diff -Nru ffmpeg-4.2.2/libavfilter/af_afreqshift.c ffmpeg-4.4/libavfilter/af_afreqshift.c --- ffmpeg-4.2.2/libavfilter/af_afreqshift.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_afreqshift.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,427 @@ +/* + * Copyright (c) Paul B Mahol + * Copyright (c) Laurent de Soras, 2005 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/ffmath.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "audio.h" +#include "formats.h" + +#define NB_COEFS 16 + +typedef struct AFreqShift { + const AVClass *class; + + double shift; + double level; + + double cd[NB_COEFS]; + float cf[NB_COEFS]; + + int64_t in_samples; + + AVFrame *i1, *o1; + AVFrame *i2, *o2; + + void (*filter_channel)(AVFilterContext *ctx, + int channel, + AVFrame *in, AVFrame *out); +} AFreqShift; + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *layouts = NULL; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE + }; + int ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_all_samplerates(); + return ff_set_common_samplerates(ctx, formats); +} + +#define PFILTER(name, type, sin, cos, cc) \ +static void pfilter_channel_## name(AVFilterContext *ctx, \ + int ch, \ + AVFrame *in, AVFrame *out) \ +{ \ + AFreqShift *s = ctx->priv; \ + const int nb_samples = in->nb_samples; \ + const type *src = (const type *)in->extended_data[ch]; \ + type *dst = (type *)out->extended_data[ch]; \ + type *i1 = (type *)s->i1->extended_data[ch]; \ + type *o1 = (type *)s->o1->extended_data[ch]; \ + type *i2 = (type *)s->i2->extended_data[ch]; \ + type *o2 = (type *)s->o2->extended_data[ch]; \ + const type *c = s->cc; \ + const type level = s->level; \ + type shift = s->shift * M_PI; \ + type cos_theta = cos(shift); \ + type sin_theta = sin(shift); \ + \ + for (int n = 0; n < nb_samples; n++) { \ + type xn1 = src[n], xn2 = src[n]; \ + type I, Q; \ + \ + for (int j = 0; j < NB_COEFS / 2; j++) { \ + I = c[j] * (xn1 + o2[j]) - i2[j]; \ + i2[j] = i1[j]; \ + i1[j] = xn1; \ + o2[j] = o1[j]; \ + o1[j] = I; \ + xn1 = I; \ + } \ + \ + for (int j = NB_COEFS / 2; j < NB_COEFS; j++) { \ + Q = c[j] * (xn2 + o2[j]) - i2[j]; \ + i2[j] = i1[j]; \ + i1[j] = xn2; \ + o2[j] = o1[j]; \ + o1[j] = Q; \ + xn2 = Q; \ + } \ + Q = o2[NB_COEFS - 1]; \ + \ + dst[n] = (I * cos_theta - Q * sin_theta) * level; \ + } \ +} + +PFILTER(flt, float, sin, cos, cf) +PFILTER(dbl, double, sin, cos, cd) + +#define FFILTER(name, type, sin, cos, fmod, cc) \ +static void ffilter_channel_## name(AVFilterContext *ctx, \ + int ch, \ + AVFrame *in, AVFrame *out) \ +{ \ + AFreqShift *s = ctx->priv; \ + const int nb_samples = in->nb_samples; \ + const type *src = (const type *)in->extended_data[ch]; \ + type *dst = (type *)out->extended_data[ch]; \ + type *i1 = (type *)s->i1->extended_data[ch]; \ + type *o1 = (type *)s->o1->extended_data[ch]; \ + type *i2 = (type *)s->i2->extended_data[ch]; \ + type *o2 = (type *)s->o2->extended_data[ch]; \ + const type *c = s->cc; \ + const type level = s->level; \ + type ts = 1. / in->sample_rate; \ + type shift = s->shift; \ + int64_t N = s->in_samples; \ + \ + for (int n = 0; n < nb_samples; n++) { \ + type xn1 = src[n], xn2 = src[n]; \ + type I, Q, theta; \ + \ + for (int j = 0; j < NB_COEFS / 2; j++) { \ + I = c[j] * (xn1 + o2[j]) - i2[j]; \ + i2[j] = i1[j]; \ + i1[j] = xn1; \ + o2[j] = o1[j]; \ + o1[j] = I; \ + xn1 = I; \ + } \ + \ + for (int j = NB_COEFS / 2; j < NB_COEFS; j++) { \ + Q = c[j] * (xn2 + o2[j]) - i2[j]; \ + i2[j] = i1[j]; \ + i1[j] = xn2; \ + o2[j] = o1[j]; \ + o1[j] = Q; \ + xn2 = Q; \ + } \ + Q = o2[NB_COEFS - 1]; \ + \ + theta = 2. * M_PI * fmod(shift * (N + n) * ts, 1.); \ + dst[n] = (I * cos(theta) - Q * sin(theta)) * level; \ + } \ +} + +FFILTER(flt, float, sinf, cosf, fmodf, cf) +FFILTER(dbl, double, sin, cos, fmod, cd) + +static void compute_transition_param(double *K, double *Q, double transition) +{ + double kksqrt, e, e2, e4, k, q; + + k = tan((1. - transition * 2.) * M_PI / 4.); + k *= k; + kksqrt = pow(1 - k * k, 0.25); + e = 0.5 * (1. - kksqrt) / (1. + kksqrt); + e2 = e * e; + e4 = e2 * e2; + q = e * (1. + e4 * (2. + e4 * (15. + 150. * e4))); + + *Q = q; + *K = k; +} + +static double ipowp(double x, int64_t n) +{ + double z = 1.; + + while (n != 0) { + if (n & 1) + z *= x; + n >>= 1; + x *= x; + } + + return z; +} + +static double compute_acc_num(double q, int order, int c) +{ + int64_t i = 0; + int j = 1; + double acc = 0.; + double q_ii1; + + do { + q_ii1 = ipowp(q, i * (i + 1)); + q_ii1 *= sin((i * 2 + 1) * c * M_PI / order) * j; + acc += q_ii1; + + j = -j; + i++; + } while (fabs(q_ii1) > 1e-100); + + return acc; +} + +static double compute_acc_den(double q, int order, int c) +{ + int64_t i = 1; + int j = -1; + double acc = 0.; + double q_i2; + + do { + q_i2 = ipowp(q, i * i); + q_i2 *= cos(i * 2 * c * M_PI / order) * j; + acc += q_i2; + + j = -j; + i++; + } while (fabs(q_i2) > 1e-100); + + return acc; +} + +static double compute_coef(int index, double k, double q, int order) +{ + const int c = index + 1; + const double num = compute_acc_num(q, order, c) * pow(q, 0.25); + const double den = compute_acc_den(q, order, c) + 0.5; + const double ww = num / den; + const double wwsq = ww * ww; + + const double x = sqrt((1 - wwsq * k) * (1 - wwsq / k)) / (1 + wwsq); + const double coef = (1 - x) / (1 + x); + + return coef; +} + +static void compute_coefs(double *coef_arrd, float *coef_arrf, int nbr_coefs, double transition) +{ + const int order = nbr_coefs * 2 + 1; + double k, q; + + compute_transition_param(&k, &q, transition); + + for (int n = 0; n < nbr_coefs; n++) { + const int idx = (n / 2) + (n & 1) * nbr_coefs / 2; + + coef_arrd[idx] = compute_coef(n, k, q, order); + coef_arrf[idx] = coef_arrd[idx]; + } +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AFreqShift *s = ctx->priv; + + compute_coefs(s->cd, s->cf, NB_COEFS, 2. * 20. / inlink->sample_rate); + + s->i1 = ff_get_audio_buffer(inlink, NB_COEFS); + s->o1 = ff_get_audio_buffer(inlink, NB_COEFS); + s->i2 = ff_get_audio_buffer(inlink, NB_COEFS); + s->o2 = ff_get_audio_buffer(inlink, NB_COEFS); + if (!s->i1 || !s->o1 || !s->i2 || !s->o2) + return AVERROR(ENOMEM); + + if (inlink->format == AV_SAMPLE_FMT_DBLP) { + if (!strcmp(ctx->filter->name, "afreqshift")) + s->filter_channel = ffilter_channel_dbl; + else + s->filter_channel = pfilter_channel_dbl; + } else { + if (!strcmp(ctx->filter->name, "afreqshift")) + s->filter_channel = ffilter_channel_flt; + else + s->filter_channel = pfilter_channel_flt; + } + + return 0; +} + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AFreqShift *s = ctx->priv; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + const int start = (in->channels * jobnr) / nb_jobs; + const int end = (in->channels * (jobnr+1)) / nb_jobs; + + for (int ch = start; ch < end; ch++) + s->filter_channel(ctx, ch, in, out); + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AFreqShift *s = ctx->priv; + AVFrame *out; + ThreadData td; + + 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); + } + + td.in = in; td.out = out; + ctx->internal->execute(ctx, filter_channels, &td, NULL, FFMIN(inlink->channels, + ff_filter_get_nb_threads(ctx))); + + s->in_samples += in->nb_samples; + + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AFreqShift *s = ctx->priv; + + av_frame_free(&s->i1); + av_frame_free(&s->o1); + av_frame_free(&s->i2); + av_frame_free(&s->o2); +} + +#define OFFSET(x) offsetof(AFreqShift, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption afreqshift_options[] = { + { "shift", "set frequency shift", OFFSET(shift), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -INT_MAX, INT_MAX, FLAGS }, + { "level", "set output level", OFFSET(level), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.0, 1.0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(afreqshift); + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_afreqshift = { + .name = "afreqshift", + .description = NULL_IF_CONFIG_SMALL("Apply frequency shifting to input audio."), + .query_formats = query_formats, + .priv_size = sizeof(AFreqShift), + .priv_class = &afreqshift_class, + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, + .process_command = ff_filter_process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS, +}; + +static const AVOption aphaseshift_options[] = { + { "shift", "set phase shift", OFFSET(shift), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1.0, 1.0, FLAGS }, + { "level", "set output level",OFFSET(level), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.0, 1.0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(aphaseshift); + +AVFilter ff_af_aphaseshift = { + .name = "aphaseshift", + .description = NULL_IF_CONFIG_SMALL("Apply phase shifting to input audio."), + .query_formats = query_formats, + .priv_size = sizeof(AFreqShift), + .priv_class = &aphaseshift_class, + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, + .process_command = ff_filter_process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS, +}; diff -Nru ffmpeg-4.2.2/libavfilter/af_agate.c ffmpeg-4.4/libavfilter/af_agate.c --- ffmpeg-4.2.2/libavfilter/af_agate.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_agate.c 2021-04-08 21:28:39.000000000 +0000 @@ -63,7 +63,7 @@ } AudioGateContext; #define OFFSET(x) offsetof(AudioGateContext, x) -#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption options[] = { { "level_in", "set input level", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, A }, @@ -268,6 +268,8 @@ .priv_class = &agate_class, .inputs = inputs, .outputs = outputs, + .process_command = ff_filter_process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; #endif /* CONFIG_AGATE_FILTER */ @@ -318,7 +320,7 @@ dst = (double *)out->data[0]; out->pts = s->pts; - s->pts += nb_samples; + s->pts += av_rescale_q(nb_samples, (AVRational){1, ctx->outputs[0]->sample_rate}, ctx->outputs[0]->time_base); gate(s, (double *)in[0]->data[0], dst, (double *)in[1]->data[0], nb_samples, @@ -353,20 +355,20 @@ }; int ret, i; - if (!ctx->inputs[0]->in_channel_layouts || - !ctx->inputs[0]->in_channel_layouts->nb_channel_layouts) { + if (!ctx->inputs[0]->incfg.channel_layouts || + !ctx->inputs[0]->incfg.channel_layouts->nb_channel_layouts) { av_log(ctx, AV_LOG_WARNING, "No channel layout for input 1\n"); return AVERROR(EAGAIN); } - if ((ret = ff_add_channel_layout(&layouts, ctx->inputs[0]->in_channel_layouts->channel_layouts[0])) < 0 || - (ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts)) < 0) + if ((ret = ff_add_channel_layout(&layouts, ctx->inputs[0]->incfg.channel_layouts->channel_layouts[0])) < 0 || + (ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0) return ret; for (i = 0; i < 2; i++) { layouts = ff_all_channel_counts(); - if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->outcfg.channel_layouts)) < 0) return ret; } @@ -445,5 +447,7 @@ .uninit = uninit, .inputs = sidechaingate_inputs, .outputs = sidechaingate_outputs, + .process_command = ff_filter_process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; #endif /* CONFIG_SIDECHAINGATE_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/af_aiir.c ffmpeg-4.4/libavfilter/af_aiir.c --- ffmpeg-4.2.2/libavfilter/af_aiir.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_aiir.c 2021-04-08 21:28:39.000000000 +0000 @@ -38,10 +38,9 @@ } Pair; typedef struct BiquadContext { - double a0, a1, a2; - double b0, b1, b2; - double i1, i2; - double o1, o2; + double a[3]; + double b[3]; + double w1, w2; } BiquadContext; typedef struct IIRChannel { @@ -49,6 +48,7 @@ double *ab[2]; double g; double *cache[2]; + double fir; BiquadContext *biquads; int clippings; } IIRChannel; @@ -58,6 +58,7 @@ char *a_str, *b_str, *g_str; double dry_gain, wet_gain; double mix; + int normalize; int format; int process; int precision; @@ -94,7 +95,7 @@ AVFilterLink *videolink = ctx->outputs[1]; formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &videolink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &videolink->incfg.formats)) < 0) return ret; } @@ -129,8 +130,8 @@ ThreadData *td = arg; \ AVFrame *in = td->in, *out = td->out; \ const type *src = (const type *)in->extended_data[ch]; \ - double *ic = (double *)s->iir[ch].cache[0]; \ - double *oc = (double *)s->iir[ch].cache[1]; \ + double *oc = (double *)s->iir[ch].cache[0]; \ + double *ic = (double *)s->iir[ch].cache[1]; \ const int nb_a = s->iir[ch].nb_ab[0]; \ const int nb_b = s->iir[ch].nb_ab[1]; \ const double *a = s->iir[ch].ab[0]; \ @@ -175,13 +176,15 @@ IIR_CH(fltp, float, -1., 1., 0) IIR_CH(dblp, double, -1., 1., 0) -#define SERIAL_IIR_CH(name, type, min, max, need_clipping) \ -static int iir_ch_serial_## name(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) \ +#define SERIAL_IIR_CH(name, type, min, max, need_clipping) \ +static int iir_ch_serial_## name(AVFilterContext *ctx, void *arg, \ + int ch, int nb_jobs) \ { \ AudioIIRContext *s = ctx->priv; \ const double ig = s->dry_gain; \ const double og = s->wet_gain; \ const double mix = s->mix; \ + const double imix = 1. - mix; \ ThreadData *td = arg; \ AVFrame *in = td->in, *out = td->out; \ const type *src = (const type *)in->extended_data[ch]; \ @@ -192,28 +195,24 @@ int nb_biquads = (FFMAX(iir->nb_ab[0], iir->nb_ab[1]) + 1) / 2; \ int n, i; \ \ - for (i = 0; i < nb_biquads; i++) { \ - const double a1 = -iir->biquads[i].a1; \ - const double a2 = -iir->biquads[i].a2; \ - const double b0 = iir->biquads[i].b0; \ - const double b1 = iir->biquads[i].b1; \ - const double b2 = iir->biquads[i].b2; \ - double i1 = iir->biquads[i].i1; \ - double i2 = iir->biquads[i].i2; \ - double o1 = iir->biquads[i].o1; \ - double o2 = iir->biquads[i].o2; \ + for (i = nb_biquads - 1; i >= 0; i--) { \ + const double a1 = -iir->biquads[i].a[1]; \ + const double a2 = -iir->biquads[i].a[2]; \ + const double b0 = iir->biquads[i].b[0]; \ + const double b1 = iir->biquads[i].b[1]; \ + const double b2 = iir->biquads[i].b[2]; \ + double w1 = iir->biquads[i].w1; \ + double w2 = iir->biquads[i].w2; \ \ for (n = 0; n < in->nb_samples; n++) { \ - double sample = ig * (i ? dst[n] : src[n]); \ - double o0 = sample * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \ + double i0 = ig * (i ? dst[n] : src[n]); \ + double o0 = i0 * b0 + w1; \ \ - i2 = i1; \ - i1 = src[n]; \ - o2 = o1; \ - o1 = o0; \ + w1 = b1 * i0 + w2 + a1 * o0; \ + w2 = b2 * i0 + a2 * o0; \ o0 *= og * g; \ \ - o0 = o0 * mix + (1. - mix) * sample; \ + o0 = o0 * mix + imix * i0; \ if (need_clipping && o0 < min) { \ (*clippings)++; \ dst[n] = min; \ @@ -224,10 +223,8 @@ dst[n] = o0; \ } \ } \ - iir->biquads[i].i1 = i1; \ - iir->biquads[i].i2 = i2; \ - iir->biquads[i].o1 = o1; \ - iir->biquads[i].o2 = o2; \ + iir->biquads[i].w1 = w1; \ + iir->biquads[i].w2 = w2; \ } \ \ return 0; \ @@ -238,6 +235,127 @@ SERIAL_IIR_CH(fltp, float, -1., 1., 0) SERIAL_IIR_CH(dblp, double, -1., 1., 0) +#define PARALLEL_IIR_CH(name, type, min, max, need_clipping) \ +static int iir_ch_parallel_## name(AVFilterContext *ctx, void *arg, \ + int ch, int nb_jobs) \ +{ \ + AudioIIRContext *s = ctx->priv; \ + const double ig = s->dry_gain; \ + const double og = s->wet_gain; \ + const double mix = s->mix; \ + const double imix = 1. - mix; \ + ThreadData *td = arg; \ + AVFrame *in = td->in, *out = td->out; \ + const type *src = (const type *)in->extended_data[ch]; \ + type *dst = (type *)out->extended_data[ch]; \ + IIRChannel *iir = &s->iir[ch]; \ + const double g = iir->g; \ + const double fir = iir->fir; \ + int *clippings = &iir->clippings; \ + int nb_biquads = (FFMAX(iir->nb_ab[0], iir->nb_ab[1]) + 1) / 2; \ + int n, i; \ + \ + for (i = 0; i < nb_biquads; i++) { \ + const double a1 = -iir->biquads[i].a[1]; \ + const double a2 = -iir->biquads[i].a[2]; \ + const double b1 = iir->biquads[i].b[1]; \ + const double b2 = iir->biquads[i].b[2]; \ + double w1 = iir->biquads[i].w1; \ + double w2 = iir->biquads[i].w2; \ + \ + for (n = 0; n < in->nb_samples; n++) { \ + double i0 = ig * src[n]; \ + double o0 = w1; \ + \ + w1 = b1 * i0 + w2 + a1 * o0; \ + w2 = b2 * i0 + a2 * o0; \ + o0 *= og * g; \ + o0 += dst[n]; \ + \ + if (need_clipping && o0 < min) { \ + (*clippings)++; \ + dst[n] = min; \ + } else if (need_clipping && o0 > max) { \ + (*clippings)++; \ + dst[n] = max; \ + } else { \ + dst[n] = o0; \ + } \ + } \ + iir->biquads[i].w1 = w1; \ + iir->biquads[i].w2 = w2; \ + } \ + \ + for (n = 0; n < in->nb_samples; n++) { \ + dst[n] += fir * src[n]; \ + dst[n] = dst[n] * mix + imix * src[n]; \ + } \ + \ + return 0; \ +} + +PARALLEL_IIR_CH(s16p, int16_t, INT16_MIN, INT16_MAX, 1) +PARALLEL_IIR_CH(s32p, int32_t, INT32_MIN, INT32_MAX, 1) +PARALLEL_IIR_CH(fltp, float, -1., 1., 0) +PARALLEL_IIR_CH(dblp, double, -1., 1., 0) + +#define LATTICE_IIR_CH(name, type, min, max, need_clipping) \ +static int iir_ch_lattice_## name(AVFilterContext *ctx, void *arg, \ + int ch, int nb_jobs) \ +{ \ + AudioIIRContext *s = ctx->priv; \ + const double ig = s->dry_gain; \ + const double og = s->wet_gain; \ + const double mix = s->mix; \ + ThreadData *td = arg; \ + AVFrame *in = td->in, *out = td->out; \ + const type *src = (const type *)in->extended_data[ch]; \ + double n0, n1, p0, *x = (double *)s->iir[ch].cache[0]; \ + const int nb_stages = s->iir[ch].nb_ab[1]; \ + const double *v = s->iir[ch].ab[0]; \ + const double *k = s->iir[ch].ab[1]; \ + const double g = s->iir[ch].g; \ + int *clippings = &s->iir[ch].clippings; \ + type *dst = (type *)out->extended_data[ch]; \ + int n; \ + \ + for (n = 0; n < in->nb_samples; n++) { \ + const double in = src[n] * ig; \ + double out = 0.; \ + \ + n1 = in; \ + for (int i = nb_stages - 1; i >= 0; i--) { \ + n0 = n1 - k[i] * x[i]; \ + p0 = n0 * k[i] + x[i]; \ + out += p0 * v[i+1]; \ + x[i] = p0; \ + n1 = n0; \ + } \ + \ + out += n1 * v[0]; \ + memmove(&x[1], &x[0], nb_stages * sizeof(*x)); \ + x[0] = n1; \ + out *= og * g; \ + out = out * mix + in * (1. - mix); \ + if (need_clipping && out < min) { \ + (*clippings)++; \ + dst[n] = min; \ + } else if (need_clipping && out > max) { \ + (*clippings)++; \ + dst[n] = max; \ + } else { \ + dst[n] = out; \ + } \ + } \ + \ + return 0; \ +} + +LATTICE_IIR_CH(s16p, int16_t, INT16_MIN, INT16_MAX, 1) +LATTICE_IIR_CH(s32p, int32_t, INT32_MIN, INT32_MAX, 1) +LATTICE_IIR_CH(fltp, float, -1., 1., 0) +LATTICE_IIR_CH(dblp, double, -1., 1., 0) + static void count_coefficients(char *item_str, int *nb_items) { char *p; @@ -271,7 +389,7 @@ } p = NULL; - if (sscanf(arg, "%lf", &s->iir[i].g) != 1) { + if (av_sscanf(arg, "%lf", &s->iir[i].g) != 1) { av_log(ctx, AV_LOG_ERROR, "Invalid gains supplied: %s\n", arg); av_freep(&old_str); return AVERROR(EINVAL); @@ -298,7 +416,7 @@ break; p = NULL; - if (sscanf(arg, "%lf", &dst[i]) != 1) { + if (av_sscanf(arg, "%lf", &dst[i]) != 1) { av_log(ctx, AV_LOG_ERROR, "Invalid coefficients supplied: %s\n", arg); av_freep(&old_str); return AVERROR(EINVAL); @@ -323,7 +441,7 @@ break; p = NULL; - if (sscanf(arg, format, &dst[i*2], &dst[i*2+1]) != 2) { + if (av_sscanf(arg, format, &dst[i*2], &dst[i*2+1]) != 2) { av_log(ctx, AV_LOG_ERROR, "Invalid coefficients supplied: %s\n", arg); av_freep(&old_str); return AVERROR(EINVAL); @@ -335,7 +453,7 @@ return 0; } -static const char *format[] = { "%lf", "%lf %lfi", "%lf %lfr", "%lf %lfd" }; +static const char *const format[] = { "%lf", "%lf %lfi", "%lf %lfr", "%lf %lfd", "%lf %lfi" }; static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, int ab) { @@ -367,7 +485,7 @@ return AVERROR(ENOMEM); } - if (s->format) { + if (s->format > 0) { ret = read_zp_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab], format[s->format]); } else { ret = read_tf_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab]); @@ -384,50 +502,65 @@ return 0; } -static void multiply(double wre, double wim, int npz, double *coeffs) +static void cmul(double re, double im, double re2, double im2, double *RE, double *IM) { - double nwre = -wre, nwim = -wim; - double cre, cim; - int i; + *RE = re * re2 - im * im2; + *IM = re * im2 + re2 * im; +} - for (i = npz; i >= 1; i--) { - cre = coeffs[2 * i + 0]; - cim = coeffs[2 * i + 1]; +static int expand(AVFilterContext *ctx, double *pz, int n, double *coefs) +{ + coefs[2 * n] = 1.0; + + for (int i = 1; i <= n; i++) { + for (int j = n - i; j < n; j++) { + double re, im; - coeffs[2 * i + 0] = (nwre * cre - nwim * cim) + coeffs[2 * (i - 1) + 0]; - coeffs[2 * i + 1] = (nwre * cim + nwim * cre) + coeffs[2 * (i - 1) + 1]; + cmul(coefs[2 * (j + 1)], coefs[2 * (j + 1) + 1], + pz[2 * (i - 1)], pz[2 * (i - 1) + 1], &re, &im); + + coefs[2 * j] -= re; + coefs[2 * j + 1] -= im; + } } - cre = coeffs[0]; - cim = coeffs[1]; - coeffs[0] = nwre * cre - nwim * cim; - coeffs[1] = nwre * cim + nwim * cre; + for (int i = 0; i < n + 1; i++) { + if (fabs(coefs[2 * i + 1]) > FLT_EPSILON) { + av_log(ctx, AV_LOG_ERROR, "coefs: %f of z^%d is not real; poles/zeros are not complex conjugates.\n", + coefs[2 * i + 1], i); + return AVERROR(EINVAL); + } + } + + return 0; } -static int expand(AVFilterContext *ctx, double *pz, int nb, double *coeffs) +static void normalize_coeffs(AVFilterContext *ctx, int ch) { - int i; + AudioIIRContext *s = ctx->priv; + IIRChannel *iir = &s->iir[ch]; + double sum_den = 0.; - coeffs[0] = 1.0; - coeffs[1] = 0.0; + if (!s->normalize) + return; - for (i = 0; i < nb; i++) { - coeffs[2 * (i + 1) ] = 0.0; - coeffs[2 * (i + 1) + 1] = 0.0; + for (int i = 0; i < iir->nb_ab[1]; i++) { + sum_den += iir->ab[1][i]; } - for (i = 0; i < nb; i++) - multiply(pz[2 * i], pz[2 * i + 1], nb, coeffs); + if (sum_den > 1e-6) { + double factor, sum_num = 0.; - for (i = 0; i < nb + 1; i++) { - if (fabs(coeffs[2 * i + 1]) > FLT_EPSILON) { - av_log(ctx, AV_LOG_ERROR, "coeff: %f of z^%d is not real; poles/zeros are not complex conjugates.\n", - coeffs[2 * i + 1], i); - return AVERROR(EINVAL); + for (int i = 0; i < iir->nb_ab[0]; i++) { + sum_num += iir->ab[0][i]; } - } - return 0; + factor = sum_num / sum_den; + + for (int i = 0; i < iir->nb_ab[1]; i++) { + iir->ab[1][i] *= factor; + } + } } static int convert_zp2tf(AVFilterContext *ctx, int channels) @@ -439,8 +572,8 @@ IIRChannel *iir = &s->iir[ch]; double *topc, *botc; - topc = av_calloc((iir->nb_ab[0] + 1) * 2, sizeof(*topc)); - botc = av_calloc((iir->nb_ab[1] + 1) * 2, sizeof(*botc)); + topc = av_calloc((iir->nb_ab[1] + 1) * 2, sizeof(*topc)); + botc = av_calloc((iir->nb_ab[0] + 1) * 2, sizeof(*botc)); if (!topc || !botc) { ret = AVERROR(ENOMEM); goto fail; @@ -466,6 +599,8 @@ } iir->nb_ab[0]++; + normalize_coeffs(ctx, ch); + fail: av_free(topc); av_free(botc); @@ -499,6 +634,7 @@ double a[6] = { 0 }; double min_distance = DBL_MAX; double max_mag = 0; + double factor; int i; for (i = 0; i < iir->nb_ab[0]; i++) { @@ -514,7 +650,7 @@ } } - for (i = 0; i < iir->nb_ab[1]; i++) { + for (i = 0; i < iir->nb_ab[0]; i++) { if (isnan(iir->ab[0][2 * i]) || isnan(iir->ab[0][2 * i + 1])) continue; @@ -593,20 +729,42 @@ iir->ab[1][2 * nearest_zero.a] = iir->ab[1][2 * nearest_zero.a + 1] = NAN; iir->ab[1][2 * nearest_zero.b] = iir->ab[1][2 * nearest_zero.b + 1] = NAN; - iir->biquads[current_biquad].a0 = 1.0; - iir->biquads[current_biquad].a1 = a[2] / a[4]; - iir->biquads[current_biquad].a2 = a[0] / a[4]; - iir->biquads[current_biquad].b0 = b[4] / a[4] * (current_biquad ? 1.0 : iir->g); - iir->biquads[current_biquad].b1 = b[2] / a[4] * (current_biquad ? 1.0 : iir->g); - iir->biquads[current_biquad].b2 = b[0] / a[4] * (current_biquad ? 1.0 : iir->g); + iir->biquads[current_biquad].a[0] = 1.; + iir->biquads[current_biquad].a[1] = a[2] / a[4]; + iir->biquads[current_biquad].a[2] = a[0] / a[4]; + iir->biquads[current_biquad].b[0] = b[4] / a[4]; + iir->biquads[current_biquad].b[1] = b[2] / a[4]; + iir->biquads[current_biquad].b[2] = b[0] / a[4]; + + if (s->normalize && + fabs(iir->biquads[current_biquad].b[0] + + iir->biquads[current_biquad].b[1] + + iir->biquads[current_biquad].b[2]) > 1e-6) { + factor = (iir->biquads[current_biquad].a[0] + + iir->biquads[current_biquad].a[1] + + iir->biquads[current_biquad].a[2]) / + (iir->biquads[current_biquad].b[0] + + iir->biquads[current_biquad].b[1] + + iir->biquads[current_biquad].b[2]); + + av_log(ctx, AV_LOG_VERBOSE, "factor=%f\n", factor); + + iir->biquads[current_biquad].b[0] *= factor; + iir->biquads[current_biquad].b[1] *= factor; + iir->biquads[current_biquad].b[2] *= factor; + } + + iir->biquads[current_biquad].b[0] *= (current_biquad ? 1.0 : iir->g); + iir->biquads[current_biquad].b[1] *= (current_biquad ? 1.0 : iir->g); + iir->biquads[current_biquad].b[2] *= (current_biquad ? 1.0 : iir->g); av_log(ctx, AV_LOG_VERBOSE, "a=%f %f %f:b=%f %f %f\n", - iir->biquads[current_biquad].a0, - iir->biquads[current_biquad].a1, - iir->biquads[current_biquad].a2, - iir->biquads[current_biquad].b0, - iir->biquads[current_biquad].b1, - iir->biquads[current_biquad].b2); + iir->biquads[current_biquad].a[0], + iir->biquads[current_biquad].a[1], + iir->biquads[current_biquad].a[2], + iir->biquads[current_biquad].b[0], + iir->biquads[current_biquad].b[1], + iir->biquads[current_biquad].b[2]); current_biquad++; } @@ -615,6 +773,128 @@ return 0; } +static void biquad_process(double *x, double *y, int length, + double b0, double b1, double b2, + double a1, double a2) +{ + double w1 = 0., w2 = 0.; + + a1 = -a1; + a2 = -a2; + + for (int n = 0; n < length; n++) { + double out, in = x[n]; + + y[n] = out = in * b0 + w1; + w1 = b1 * in + w2 + a1 * out; + w2 = b2 * in + a2 * out; + } +} + +static void solve(double *matrix, double *vector, int n, double *y, double *x, double *lu) +{ + double sum = 0.; + + for (int i = 0; i < n; i++) { + for (int j = i; j < n; j++) { + sum = 0.; + for (int k = 0; k < i; k++) + sum += lu[i * n + k] * lu[k * n + j]; + lu[i * n + j] = matrix[j * n + i] - sum; + } + for (int j = i + 1; j < n; j++) { + sum = 0.; + for (int k = 0; k < i; k++) + sum += lu[j * n + k] * lu[k * n + i]; + lu[j * n + i] = (1. / lu[i * n + i]) * (matrix[i * n + j] - sum); + } + } + + for (int i = 0; i < n; i++) { + sum = 0.; + for (int k = 0; k < i; k++) + sum += lu[i * n + k] * y[k]; + y[i] = vector[i] - sum; + } + + for (int i = n - 1; i >= 0; i--) { + sum = 0.; + for (int k = i + 1; k < n; k++) + sum += lu[i * n + k] * x[k]; + x[i] = (1 / lu[i * n + i]) * (y[i] - sum); + } +} + +static int convert_serial2parallel(AVFilterContext *ctx, int channels) +{ + AudioIIRContext *s = ctx->priv; + int ret = 0; + + for (int ch = 0; ch < channels; ch++) { + IIRChannel *iir = &s->iir[ch]; + int nb_biquads = (FFMAX(iir->nb_ab[0], iir->nb_ab[1]) + 1) / 2; + int length = nb_biquads * 2 + 1; + double *impulse = av_calloc(length, sizeof(*impulse)); + double *y = av_calloc(length, sizeof(*y)); + double *resp = av_calloc(length, sizeof(*resp)); + double *M = av_calloc((length - 1) * 2 * nb_biquads, sizeof(*M)); + double *W = av_calloc((length - 1) * 2 * nb_biquads, sizeof(*W)); + + if (!impulse || !y || !resp || !M) { + av_free(impulse); + av_free(y); + av_free(resp); + av_free(M); + av_free(W); + return AVERROR(ENOMEM); + } + + impulse[0] = 1.; + + for (int n = 0; n < nb_biquads; n++) { + BiquadContext *biquad = &iir->biquads[n]; + + biquad_process(n ? y : impulse, y, length, + biquad->b[0], biquad->b[1], biquad->b[2], + biquad->a[1], biquad->a[2]); + } + + for (int n = 0; n < nb_biquads; n++) { + BiquadContext *biquad = &iir->biquads[n]; + + biquad_process(impulse, resp, length - 1, + 1., 0., 0., biquad->a[1], biquad->a[2]); + + memcpy(M + n * 2 * (length - 1), resp, sizeof(*resp) * (length - 1)); + memcpy(M + n * 2 * (length - 1) + length, resp, sizeof(*resp) * (length - 2)); + memset(resp, 0, length * sizeof(*resp)); + } + + solve(M, &y[1], length - 1, &impulse[1], resp, W); + + iir->fir = y[0]; + + for (int n = 0; n < nb_biquads; n++) { + BiquadContext *biquad = &iir->biquads[n]; + + biquad->b[0] = 0.; + biquad->b[1] = resp[n * 2 + 0]; + biquad->b[2] = resp[n * 2 + 1]; + } + + av_free(impulse); + av_free(y); + av_free(resp); + av_free(M); + av_free(W); + + if (ret < 0) + return ret; + } + + return 0; +} + static void convert_pr2zp(AVFilterContext *ctx, int channels) { AudioIIRContext *s = ctx->priv; @@ -642,6 +922,87 @@ } } +static void convert_sp2zp(AVFilterContext *ctx, int channels) +{ + AudioIIRContext *s = ctx->priv; + int ch; + + for (ch = 0; ch < channels; ch++) { + IIRChannel *iir = &s->iir[ch]; + int n; + + for (n = 0; n < iir->nb_ab[0]; n++) { + double sr = iir->ab[0][2*n]; + double si = iir->ab[0][2*n+1]; + + iir->ab[0][2*n] = exp(sr) * cos(si); + iir->ab[0][2*n+1] = exp(sr) * sin(si); + } + + for (n = 0; n < iir->nb_ab[1]; n++) { + double sr = iir->ab[1][2*n]; + double si = iir->ab[1][2*n+1]; + + iir->ab[1][2*n] = exp(sr) * cos(si); + iir->ab[1][2*n+1] = exp(sr) * sin(si); + } + } +} + +static double fact(double i) +{ + if (i <= 0.) + return 1.; + return i * fact(i - 1.); +} + +static double coef_sf2zf(double *a, int N, int n) +{ + double z = 0.; + + for (int i = 0; i <= N; i++) { + double acc = 0.; + + for (int k = FFMAX(n - N + i, 0); k <= FFMIN(i, n); k++) { + acc += ((fact(i) * fact(N - i)) / + (fact(k) * fact(i - k) * fact(n - k) * fact(N - i - n + k))) * + ((k & 1) ? -1. : 1.); + } + + z += a[i] * pow(2., i) * acc; + } + + return z; +} + +static void convert_sf2tf(AVFilterContext *ctx, int channels) +{ + AudioIIRContext *s = ctx->priv; + int ch; + + for (ch = 0; ch < channels; ch++) { + IIRChannel *iir = &s->iir[ch]; + double *temp0 = av_calloc(iir->nb_ab[0], sizeof(*temp0)); + double *temp1 = av_calloc(iir->nb_ab[1], sizeof(*temp1)); + + if (!temp0 || !temp1) + goto next; + + memcpy(temp0, iir->ab[0], iir->nb_ab[0] * sizeof(*temp0)); + memcpy(temp1, iir->ab[1], iir->nb_ab[1] * sizeof(*temp1)); + + for (int n = 0; n < iir->nb_ab[0]; n++) + iir->ab[0][n] = coef_sf2zf(temp0, iir->nb_ab[0] - 1, n); + + for (int n = 0; n < iir->nb_ab[1]; n++) + iir->ab[1][n] = coef_sf2zf(temp1, iir->nb_ab[1] - 1, n); + +next: + av_free(temp0); + av_free(temp1); + } +} + static void convert_pd2zp(AVFilterContext *ctx, int channels) { AudioIIRContext *s = ctx->priv; @@ -669,6 +1030,25 @@ } } +static void check_stability(AVFilterContext *ctx, int channels) +{ + AudioIIRContext *s = ctx->priv; + int ch; + + for (ch = 0; ch < channels; ch++) { + IIRChannel *iir = &s->iir[ch]; + + for (int n = 0; n < iir->nb_ab[0]; n++) { + double pr = hypot(iir->ab[0][2*n], iir->ab[0][2*n+1]); + + if (pr >= 1.) { + av_log(ctx, AV_LOG_WARNING, "pole %d at channel %d is unstable\n", n, ch); + break; + } + } + } +} + static void drawtext(AVFrame *pic, int x, int y, const char *txt, uint32_t color) { const uint8_t *font; @@ -718,99 +1098,121 @@ } } -static void draw_response(AVFilterContext *ctx, AVFrame *out) +static double distance(double x0, double x1, double y0, double y1) +{ + return hypot(x0 - x1, y0 - y1); +} + +static void get_response(int channel, int format, double w, + const double *b, const double *a, + int nb_b, int nb_a, double *magnitude, double *phase) +{ + double realz, realp; + double imagz, imagp; + double real, imag; + double div; + + if (format == 0) { + realz = 0., realp = 0.; + imagz = 0., imagp = 0.; + for (int x = 0; x < nb_a; x++) { + realz += cos(-x * w) * a[x]; + imagz += sin(-x * w) * a[x]; + } + + for (int x = 0; x < nb_b; x++) { + realp += cos(-x * w) * b[x]; + imagp += sin(-x * w) * b[x]; + } + + div = realp * realp + imagp * imagp; + real = (realz * realp + imagz * imagp) / div; + imag = (imagz * realp - imagp * realz) / div; + + *magnitude = hypot(real, imag); + *phase = atan2(imag, real); + } else { + double p = 1., z = 1.; + double acc = 0.; + + for (int x = 0; x < nb_a; x++) { + z *= distance(cos(w), a[2 * x], sin(w), a[2 * x + 1]); + acc += atan2(sin(w) - a[2 * x + 1], cos(w) - a[2 * x]); + } + + for (int x = 0; x < nb_b; x++) { + p *= distance(cos(w), b[2 * x], sin(w), b[2 * x + 1]); + acc -= atan2(sin(w) - b[2 * x + 1], cos(w) - b[2 * x]); + } + + *magnitude = z / p; + *phase = acc; + } +} + +static void draw_response(AVFilterContext *ctx, AVFrame *out, int sample_rate) { AudioIIRContext *s = ctx->priv; - float *mag, *phase, *delay, min = FLT_MAX, max = FLT_MIN; - float min_delay = FLT_MAX, max_delay = FLT_MIN; + double *mag, *phase, *temp, *delay, min = DBL_MAX, max = -DBL_MAX; + double min_delay = DBL_MAX, max_delay = -DBL_MAX, min_phase, max_phase; int prev_ymag = -1, prev_yphase = -1, prev_ydelay = -1; char text[32]; - int ch, i, x; + int ch, i; memset(out->data[0], 0, s->h * out->linesize[0]); phase = av_malloc_array(s->w, sizeof(*phase)); + temp = av_malloc_array(s->w, sizeof(*temp)); mag = av_malloc_array(s->w, sizeof(*mag)); delay = av_malloc_array(s->w, sizeof(*delay)); - if (!mag || !phase || !delay) + if (!mag || !phase || !delay || !temp) goto end; ch = av_clip(s->ir_channel, 0, s->channels - 1); for (i = 0; i < s->w; i++) { const double *b = s->iir[ch].ab[0]; const double *a = s->iir[ch].ab[1]; + const int nb_b = s->iir[ch].nb_ab[0]; + const int nb_a = s->iir[ch].nb_ab[1]; double w = i * M_PI / (s->w - 1); - double realz, realp; - double imagz, imagp; - double real, imag, div; - - if (s->format == 0) { - realz = 0., realp = 0.; - imagz = 0., imagp = 0.; - for (x = 0; x < s->iir[ch].nb_ab[1]; x++) { - realz += cos(-x * w) * a[x]; - imagz += sin(-x * w) * a[x]; - } + double m, p; - for (x = 0; x < s->iir[ch].nb_ab[0]; x++) { - realp += cos(-x * w) * b[x]; - imagp += sin(-x * w) * b[x]; - } - - div = realp * realp + imagp * imagp; - real = (realz * realp + imagz * imagp) / div; - imag = (imagz * realp - imagp * realz) / div; - } else { - real = 1; - imag = 0; - for (x = 0; x < s->iir[ch].nb_ab[1]; x++) { - double ore, oim, re, im; - - re = cos(w) - a[2 * x]; - im = sin(w) - a[2 * x + 1]; - - ore = real; - oim = imag; - - real = ore * re - oim * im; - imag = ore * im + oim * re; - } - - for (x = 0; x < s->iir[ch].nb_ab[0]; x++) { - double ore, oim, re, im; + get_response(ch, s->format, w, b, a, nb_b, nb_a, &m, &p); - re = cos(w) - b[2 * x]; - im = sin(w) - b[2 * x + 1]; - - ore = real; - oim = imag; - div = re * re + im * im; + mag[i] = s->iir[ch].g * m; + phase[i] = p; + min = fmin(min, mag[i]); + max = fmax(max, mag[i]); + } - real = (ore * re + oim * im) / div; - imag = (oim * re - ore * im) / div; - } - } + temp[0] = 0.; + for (i = 0; i < s->w - 1; i++) { + double d = phase[i] - phase[i + 1]; + temp[i + 1] = ceil(fabs(d) / (2. * M_PI)) * 2. * M_PI * ((d > M_PI) - (d < -M_PI)); + } - mag[i] = s->iir[ch].g * hypot(real, imag); - phase[i] = atan2(imag, real); - min = fminf(min, mag[i]); - max = fmaxf(max, mag[i]); + min_phase = phase[0]; + max_phase = phase[0]; + for (i = 1; i < s->w; i++) { + temp[i] += temp[i - 1]; + phase[i] += temp[i]; + min_phase = fmin(min_phase, phase[i]); + max_phase = fmax(max_phase, phase[i]); } for (i = 0; i < s->w - 1; i++) { - float dw = M_PI / (s->w - 1); + double div = s->w / (double)sample_rate; - delay[i] = -(phase[i + 1] - phase[i]) / dw; - min_delay = fminf(min_delay, delay[i]); - max_delay = fmaxf(max_delay, delay[i]); + delay[i + 1] = -(phase[i] - phase[i + 1]) / div; + min_delay = fmin(min_delay, delay[i + 1]); + max_delay = fmax(max_delay, delay[i + 1]); } - - delay[i] = delay[i - 1]; + delay[0] = delay[1]; for (i = 0; i < s->w; i++) { int ymag = mag[i] / max * (s->h - 1); int ydelay = (delay[i] - min_delay) / (max_delay - min_delay) * (s->h - 1); - int yphase = (0.5 * (1. + phase[i] / M_PI)) * (s->h - 1); + int yphase = (phase[i] - min_phase) / (max_phase - min_phase) * (s->h - 1); ymag = s->h - 1 - av_clip(ymag, 0, s->h - 1); yphase = s->h - 1 - av_clip(yphase, 0, s->h - 1); @@ -841,17 +1243,26 @@ snprintf(text, sizeof(text), "%.2f", min); drawtext(out, 15 * 8 + 2, 12, text, 0xDDDDDDDD); - drawtext(out, 2, 22, "Max Delay:", 0xDDDDDDDD); + drawtext(out, 2, 22, "Max Phase:", 0xDDDDDDDD); + snprintf(text, sizeof(text), "%.2f", max_phase); + drawtext(out, 15 * 8 + 2, 22, text, 0xDDDDDDDD); + + drawtext(out, 2, 32, "Min Phase:", 0xDDDDDDDD); + snprintf(text, sizeof(text), "%.2f", min_phase); + drawtext(out, 15 * 8 + 2, 32, text, 0xDDDDDDDD); + + drawtext(out, 2, 42, "Max Delay:", 0xDDDDDDDD); snprintf(text, sizeof(text), "%.2f", max_delay); - drawtext(out, 11 * 8 + 2, 22, text, 0xDDDDDDDD); + drawtext(out, 11 * 8 + 2, 42, text, 0xDDDDDDDD); - drawtext(out, 2, 32, "Min Delay:", 0xDDDDDDDD); + drawtext(out, 2, 52, "Min Delay:", 0xDDDDDDDD); snprintf(text, sizeof(text), "%.2f", min_delay); - drawtext(out, 11 * 8 + 2, 32, text, 0xDDDDDDDD); + drawtext(out, 11 * 8 + 2, 52, text, 0xDDDDDDDD); } end: av_free(delay); + av_free(temp); av_free(phase); av_free(mag); } @@ -880,10 +1291,18 @@ if (ret < 0) return ret; - if (s->format == 2) { + if (s->format == -1) { + convert_sf2tf(ctx, inlink->channels); + s->format = 0; + } else if (s->format == 2) { convert_pr2zp(ctx, inlink->channels); } else if (s->format == 3) { convert_pd2zp(ctx, inlink->channels); + } else if (s->format == 4) { + convert_sp2zp(ctx, inlink->channels); + } + if (s->format > 0) { + check_stability(ctx, inlink->channels); } av_frame_free(&s->video); @@ -892,11 +1311,11 @@ if (!s->video) return AVERROR(ENOMEM); - draw_response(ctx, s->video); + draw_response(ctx, s->video, inlink->sample_rate); } if (s->format == 0) - av_log(ctx, AV_LOG_WARNING, "tf coefficients format is not recommended for too high number of zeros/poles.\n"); + av_log(ctx, AV_LOG_WARNING, "transfer function coefficients format is not recommended for too high number of zeros/poles.\n"); if (s->format > 0 && s->process == 0) { av_log(ctx, AV_LOG_WARNING, "Direct processsing is not recommended for zp coefficients format.\n"); @@ -904,16 +1323,37 @@ ret = convert_zp2tf(ctx, inlink->channels); if (ret < 0) return ret; - } else if (s->format == 0 && s->process == 1) { - av_log(ctx, AV_LOG_ERROR, "Serial cascading is not implemented for transfer function.\n"); + } else if (s->format == -2 && s->process > 0) { + av_log(ctx, AV_LOG_ERROR, "Only direct processing is implemented for lattice-ladder function.\n"); + return AVERROR_PATCHWELCOME; + } else if (s->format <= 0 && s->process == 1) { + av_log(ctx, AV_LOG_ERROR, "Serial processing is not implemented for transfer function.\n"); + return AVERROR_PATCHWELCOME; + } else if (s->format <= 0 && s->process == 2) { + av_log(ctx, AV_LOG_ERROR, "Parallel processing is not implemented for transfer function.\n"); return AVERROR_PATCHWELCOME; } else if (s->format > 0 && s->process == 1) { - if (inlink->format == AV_SAMPLE_FMT_S16P) - av_log(ctx, AV_LOG_WARNING, "Serial cascading is not recommended for i16 precision.\n"); - ret = decompose_zp2biquads(ctx, inlink->channels); if (ret < 0) return ret; + } else if (s->format > 0 && s->process == 2) { + if (s->precision > 1) + av_log(ctx, AV_LOG_WARNING, "Parallel processing is not recommended for fixed-point precisions.\n"); + ret = decompose_zp2biquads(ctx, inlink->channels); + if (ret < 0) + return ret; + ret = convert_serial2parallel(ctx, inlink->channels); + if (ret < 0) + return ret; + } + + for (ch = 0; s->format == -2 && ch < inlink->channels; ch++) { + IIRChannel *iir = &s->iir[ch]; + + if (iir->nb_ab[0] != iir->nb_ab[1] + 1) { + av_log(ctx, AV_LOG_ERROR, "Number of ladder coefficients must be one more than number of reflection coefficients.\n"); + return AVERROR(EINVAL); + } } for (ch = 0; s->format == 0 && ch < inlink->channels; ch++) { @@ -923,16 +1363,28 @@ iir->ab[0][i] /= iir->ab[0][0]; } + iir->ab[0][0] = 1.0; for (i = 0; i < iir->nb_ab[1]; i++) { - iir->ab[1][i] *= iir->g / iir->ab[0][0]; + iir->ab[1][i] *= iir->g; } + + normalize_coeffs(ctx, ch); } switch (inlink->format) { - case AV_SAMPLE_FMT_DBLP: s->iir_channel = s->process == 1 ? iir_ch_serial_dblp : iir_ch_dblp; break; - case AV_SAMPLE_FMT_FLTP: s->iir_channel = s->process == 1 ? iir_ch_serial_fltp : iir_ch_fltp; break; - case AV_SAMPLE_FMT_S32P: s->iir_channel = s->process == 1 ? iir_ch_serial_s32p : iir_ch_s32p; break; - case AV_SAMPLE_FMT_S16P: s->iir_channel = s->process == 1 ? iir_ch_serial_s16p : iir_ch_s16p; break; + case AV_SAMPLE_FMT_DBLP: s->iir_channel = s->process == 2 ? iir_ch_parallel_dblp : s->process == 1 ? iir_ch_serial_dblp : iir_ch_dblp; break; + case AV_SAMPLE_FMT_FLTP: s->iir_channel = s->process == 2 ? iir_ch_parallel_fltp : s->process == 1 ? iir_ch_serial_fltp : iir_ch_fltp; break; + case AV_SAMPLE_FMT_S32P: s->iir_channel = s->process == 2 ? iir_ch_parallel_s32p : s->process == 1 ? iir_ch_serial_s32p : iir_ch_s32p; break; + case AV_SAMPLE_FMT_S16P: s->iir_channel = s->process == 2 ? iir_ch_parallel_s16p : s->process == 1 ? iir_ch_serial_s16p : iir_ch_s16p; break; + } + + if (s->format == -2) { + switch (inlink->format) { + case AV_SAMPLE_FMT_DBLP: s->iir_channel = iir_ch_lattice_dblp; break; + case AV_SAMPLE_FMT_FLTP: s->iir_channel = iir_ch_lattice_fltp; break; + case AV_SAMPLE_FMT_S32P: s->iir_channel = iir_ch_lattice_s32p; break; + case AV_SAMPLE_FMT_S16P: s->iir_channel = iir_ch_lattice_s16p; break; + } } return 0; @@ -947,7 +1399,7 @@ AVFrame *out; int ch, ret; - if (av_frame_is_writable(in)) { + if (av_frame_is_writable(in) && s->process != 2) { out = in; } else { out = ff_get_audio_buffer(outlink, in->nb_samples); @@ -978,8 +1430,13 @@ int64_t new_pts = av_rescale_q(out->pts, ctx->inputs[0]->time_base, outlink->time_base); if (new_pts > old_pts) { + AVFrame *clone; + s->video->pts = new_pts; - ret = ff_filter_frame(outlink, av_frame_clone(s->video)); + clone = av_frame_clone(s->video); + if (!clone) + return AVERROR(ENOMEM); + ret = ff_filter_frame(outlink, clone); if (ret < 0) return ret; } @@ -1022,29 +1479,22 @@ } pad = (AVFilterPad){ - .name = av_strdup("default"), + .name = "default", .type = AVMEDIA_TYPE_AUDIO, .config_props = config_output, }; - if (!pad.name) - return AVERROR(ENOMEM); + ret = ff_insert_outpad(ctx, 0, &pad); + if (ret < 0) + return ret; if (s->response) { vpad = (AVFilterPad){ - .name = av_strdup("filter_response"), + .name = "filter_response", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_video, }; - if (!vpad.name) - return AVERROR(ENOMEM); - } - - ret = ff_insert_outpad(ctx, 0, &pad); - if (ret < 0) - return ret; - if (s->response) { ret = ff_insert_outpad(ctx, 1, &vpad); if (ret < 0) return ret; @@ -1070,9 +1520,6 @@ } av_freep(&s->iir); - av_freep(&ctx->output_pads[0].name); - if (s->response) - av_freep(&ctx->output_pads[1].name); av_frame_free(&s->video); } @@ -1090,24 +1537,36 @@ #define VF AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption aiir_options[] = { - { "z", "set B/numerator/zeros coefficients", OFFSET(b_str), AV_OPT_TYPE_STRING, {.str="1+0i 1-0i"}, 0, 0, AF }, - { "p", "set A/denominator/poles coefficients", OFFSET(a_str), AV_OPT_TYPE_STRING, {.str="1+0i 1-0i"}, 0, 0, AF }, + { "zeros", "set B/numerator/zeros/reflection coefficients", OFFSET(b_str), AV_OPT_TYPE_STRING, {.str="1+0i 1-0i"}, 0, 0, AF }, + { "z", "set B/numerator/zeros/reflection coefficients", OFFSET(b_str), AV_OPT_TYPE_STRING, {.str="1+0i 1-0i"}, 0, 0, AF }, + { "poles", "set A/denominator/poles/ladder coefficients", OFFSET(a_str), AV_OPT_TYPE_STRING, {.str="1+0i 1-0i"}, 0, 0, AF }, + { "p", "set A/denominator/poles/ladder coefficients", OFFSET(a_str), AV_OPT_TYPE_STRING, {.str="1+0i 1-0i"}, 0, 0, AF }, + { "gains", "set channels gains", OFFSET(g_str), AV_OPT_TYPE_STRING, {.str="1|1"}, 0, 0, AF }, { "k", "set channels gains", OFFSET(g_str), AV_OPT_TYPE_STRING, {.str="1|1"}, 0, 0, AF }, { "dry", "set dry gain", OFFSET(dry_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, { "wet", "set wet gain", OFFSET(wet_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, - { "f", "set coefficients format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=1}, 0, 3, AF, "format" }, - { "tf", "transfer function", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "format" }, + { "format", "set coefficients format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=1}, -2, 4, AF, "format" }, + { "f", "set coefficients format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=1}, -2, 4, AF, "format" }, + { "ll", "lattice-ladder function", 0, AV_OPT_TYPE_CONST, {.i64=-2}, 0, 0, AF, "format" }, + { "sf", "analog transfer function", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "format" }, + { "tf", "digital transfer function", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "format" }, { "zp", "Z-plane zeros/poles", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "format" }, { "pr", "Z-plane zeros/poles (polar radians)", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "format" }, { "pd", "Z-plane zeros/poles (polar degrees)", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "format" }, - { "r", "set kind of processing", OFFSET(process), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, AF, "process" }, + { "sp", "S-plane zeros/poles", 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, AF, "format" }, + { "process", "set kind of processing", OFFSET(process), AV_OPT_TYPE_INT, {.i64=1}, 0, 2, AF, "process" }, + { "r", "set kind of processing", OFFSET(process), AV_OPT_TYPE_INT, {.i64=1}, 0, 2, AF, "process" }, { "d", "direct", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "process" }, - { "s", "serial cascading", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "process" }, + { "s", "serial", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "process" }, + { "p", "parallel", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "process" }, + { "precision", "set filtering precision", OFFSET(precision),AV_OPT_TYPE_INT, {.i64=0}, 0, 3, AF, "precision" }, { "e", "set precision", OFFSET(precision),AV_OPT_TYPE_INT, {.i64=0}, 0, 3, AF, "precision" }, { "dbl", "double-precision floating-point", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision" }, { "flt", "single-precision floating-point", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision" }, { "i32", "32-bit integers", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision" }, { "i16", "16-bit integers", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision" }, + { "normalize", "normalize coefficients", OFFSET(normalize),AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, AF }, + { "n", "normalize coefficients", OFFSET(normalize),AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, AF }, { "mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, AF }, { "response", "show IR frequency response", OFFSET(response), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, VF }, { "channel", "set IR channel to display frequency response", OFFSET(ir_channel), AV_OPT_TYPE_INT, {.i64=0}, 0, 1024, VF }, diff -Nru ffmpeg-4.2.2/libavfilter/af_amerge.c ffmpeg-4.4/libavfilter/af_amerge.c --- ffmpeg-4.2.2/libavfilter/af_amerge.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_amerge.c 2021-04-08 21:28:39.000000000 +0000 @@ -58,17 +58,22 @@ static av_cold void uninit(AVFilterContext *ctx) { AMergeContext *s = ctx->priv; - int i; - for (i = 0; i < s->nb_inputs; i++) { - if (ctx->input_pads) - av_freep(&ctx->input_pads[i].name); - } av_freep(&s->in); + for (unsigned i = 0; i < ctx->nb_inputs; i++) + av_freep(&ctx->input_pads[i].name); } static int query_formats(AVFilterContext *ctx) { + static const enum AVSampleFormat packed_sample_fmts[] = { + AV_SAMPLE_FMT_U8, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_S32, + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_DBL, + AV_SAMPLE_FMT_NONE + }; AMergeContext *s = ctx->priv; int64_t inlayout[SWR_CH_MAX], outlayout = 0; AVFilterFormats *formats; @@ -76,14 +81,14 @@ int i, ret, overlap = 0, nb_ch = 0; for (i = 0; i < s->nb_inputs; i++) { - if (!ctx->inputs[i]->in_channel_layouts || - !ctx->inputs[i]->in_channel_layouts->nb_channel_layouts) { + if (!ctx->inputs[i]->incfg.channel_layouts || + !ctx->inputs[i]->incfg.channel_layouts->nb_channel_layouts) { av_log(ctx, AV_LOG_WARNING, "No channel layout for input %d\n", i + 1); return AVERROR(EAGAIN); } - inlayout[i] = ctx->inputs[i]->in_channel_layouts->channel_layouts[0]; - if (ctx->inputs[i]->in_channel_layouts->nb_channel_layouts > 1) { + inlayout[i] = ctx->inputs[i]->incfg.channel_layouts->channel_layouts[0]; + if (ctx->inputs[i]->incfg.channel_layouts->nb_channel_layouts > 1) { char buf[256]; av_get_channel_layout_string(buf, sizeof(buf), 0, inlayout[i]); av_log(ctx, AV_LOG_INFO, "Using \"%s\" for input %d\n", buf, i + 1); @@ -124,20 +129,20 @@ if ((inlayout[i] >> c) & 1) *(route[i]++) = out_ch_number++; } - formats = ff_make_format_list(ff_packed_sample_fmts_array); + formats = ff_make_format_list(packed_sample_fmts); if ((ret = ff_set_common_formats(ctx, formats)) < 0) return ret; for (i = 0; i < s->nb_inputs; i++) { layouts = NULL; if ((ret = ff_add_channel_layout(&layouts, inlayout[i])) < 0) return ret; - if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->outcfg.channel_layouts)) < 0) return ret; } layouts = NULL; if ((ret = ff_add_channel_layout(&layouts, outlayout)) < 0) return ret; - if ((ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0) return ret; return ff_set_common_samplerates(ctx, ff_all_samplerates()); diff -Nru ffmpeg-4.2.2/libavfilter/af_amix.c ffmpeg-4.4/libavfilter/af_amix.c --- ffmpeg-4.2.2/libavfilter/af_amix.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_amix.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,6 +34,7 @@ #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" +#include "libavutil/eval.h" #include "libavutil/float_dsp.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" @@ -163,6 +164,7 @@ int duration_mode; /**< mode for determining duration */ float dropout_transition; /**< transition time when an input drops out */ char *weights_str; /**< string for custom weights for every input */ + int normalize; /**< if inputs are scaled */ int nb_channels; /**< number of channels */ int sample_rate; /**< sample rate */ @@ -180,9 +182,10 @@ #define OFFSET(x) offsetof(MixContext, x) #define A AV_OPT_FLAG_AUDIO_PARAM #define F AV_OPT_FLAG_FILTERING_PARAM +#define T AV_OPT_FLAG_RUNTIME_PARAM static const AVOption amix_options[] = { { "inputs", "Number of inputs.", - OFFSET(nb_inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, 1024, A|F }, + OFFSET(nb_inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, INT16_MAX, A|F }, { "duration", "How to determine the end-of-stream.", OFFSET(duration_mode), AV_OPT_TYPE_INT, { .i64 = DURATION_LONGEST }, 0, 2, A|F, "duration" }, { "longest", "Duration of longest input.", 0, AV_OPT_TYPE_CONST, { .i64 = DURATION_LONGEST }, 0, 0, A|F, "duration" }, @@ -192,7 +195,9 @@ "renormalization when an input stream ends.", OFFSET(dropout_transition), AV_OPT_TYPE_FLOAT, { .dbl = 2.0 }, 0, INT_MAX, A|F }, { "weights", "Set weight for each input.", - OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, A|F }, + OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, A|F|T }, + { "normalize", "Scale inputs", + OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, A|F|T }, { NULL } }; @@ -212,23 +217,27 @@ for (i = 0; i < s->nb_inputs; i++) if (s->input_state[i] & INPUT_ON) - weight_sum += s->weights[i]; + weight_sum += FFABS(s->weights[i]); for (i = 0; i < s->nb_inputs; i++) { if (s->input_state[i] & INPUT_ON) { - if (s->scale_norm[i] > weight_sum / s->weights[i]) { - s->scale_norm[i] -= ((s->weight_sum / s->weights[i]) / s->nb_inputs) * + if (s->scale_norm[i] > weight_sum / FFABS(s->weights[i])) { + s->scale_norm[i] -= ((s->weight_sum / FFABS(s->weights[i])) / s->nb_inputs) * nb_samples / (s->dropout_transition * s->sample_rate); - s->scale_norm[i] = FFMAX(s->scale_norm[i], weight_sum / s->weights[i]); + s->scale_norm[i] = FFMAX(s->scale_norm[i], weight_sum / FFABS(s->weights[i])); } } } for (i = 0; i < s->nb_inputs; i++) { - if (s->input_state[i] & INPUT_ON) - s->input_scale[i] = 1.0f / s->scale_norm[i]; - else + if (s->input_state[i] & INPUT_ON) { + if (!s->normalize) + s->input_scale[i] = FFABS(s->weights[i]); + else + s->input_scale[i] = 1.0f / s->scale_norm[i] * FFSIGN(s->weights[i]); + } else { s->input_scale[i] = 0.0f; + } } } @@ -270,7 +279,7 @@ if (!s->input_scale || !s->scale_norm) return AVERROR(ENOMEM); for (i = 0; i < s->nb_inputs; i++) - s->scale_norm[i] = s->weight_sum / s->weights[i]; + s->scale_norm[i] = s->weight_sum / FFABS(s->weights[i]); calculate_scales(s, 0); av_get_channel_layout_string(buf, sizeof(buf), -1, outlink->channel_layout); @@ -307,6 +316,8 @@ } } } + + s->next_pts = frame_list_next_pts(s->frame_list); } else { /* first input closed: use the available samples */ nb_samples = INT_MAX; @@ -322,7 +333,6 @@ } } - s->next_pts = frame_list_next_pts(s->frame_list); frame_list_remove_samples(s->frame_list, nb_samples); calculate_scales(s, nb_samples); @@ -503,11 +513,36 @@ return 0; } -static av_cold int init(AVFilterContext *ctx) +static void parse_weights(AVFilterContext *ctx) { MixContext *s = ctx->priv; - char *p, *arg, *saveptr = NULL; float last_weight = 1.f; + char *p; + int i; + + s->weight_sum = 0.f; + p = s->weights_str; + for (i = 0; i < s->nb_inputs; i++) { + last_weight = av_strtod(p, &p); + s->weights[i] = last_weight; + s->weight_sum += FFABS(last_weight); + if (p && *p) { + p++; + } else { + i++; + break; + } + } + + for (; i < s->nb_inputs; i++) { + s->weights[i] = last_weight; + s->weight_sum += FFABS(last_weight); + } +} + +static av_cold int init(AVFilterContext *ctx) +{ + MixContext *s = ctx->priv; int i, ret; for (i = 0; i < s->nb_inputs; i++) { @@ -532,21 +567,7 @@ if (!s->weights) return AVERROR(ENOMEM); - p = s->weights_str; - for (i = 0; i < s->nb_inputs; i++) { - if (!(arg = av_strtok(p, " ", &saveptr))) - break; - - p = NULL; - sscanf(arg, "%f", &last_weight); - s->weights[i] = last_weight; - s->weight_sum += last_weight; - } - - for (; i < s->nb_inputs; i++) { - s->weights[i] = last_weight; - s->weight_sum += last_weight; - } + parse_weights(ctx); return 0; } @@ -575,30 +596,36 @@ static int query_formats(AVFilterContext *ctx) { - AVFilterFormats *formats = NULL; - AVFilterChannelLayouts *layouts; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE + }; int ret; - layouts = ff_all_channel_counts(); - if (!layouts) { - ret = AVERROR(ENOMEM); - goto fail; - } - - if ((ret = ff_add_format(&formats, AV_SAMPLE_FMT_FLT )) < 0 || - (ret = ff_add_format(&formats, AV_SAMPLE_FMT_FLTP)) < 0 || - (ret = ff_add_format(&formats, AV_SAMPLE_FMT_DBL )) < 0 || - (ret = ff_add_format(&formats, AV_SAMPLE_FMT_DBLP)) < 0 || - (ret = ff_set_common_formats (ctx, formats)) < 0 || - (ret = ff_set_common_channel_layouts(ctx, layouts)) < 0 || + if ((ret = ff_set_common_formats(ctx, ff_make_format_list(sample_fmts))) < 0 || (ret = ff_set_common_samplerates(ctx, ff_all_samplerates())) < 0) - goto fail; + return ret; + + return ff_set_common_channel_layouts(ctx, ff_all_channel_counts()); +} + +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + MixContext *s = ctx->priv; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + parse_weights(ctx); + for (int i = 0; i < s->nb_inputs; i++) + s->scale_norm[i] = s->weight_sum / FFABS(s->weights[i]); + calculate_scales(s, 0); + return 0; -fail: - if (layouts) - av_freep(&layouts->channel_layouts); - av_freep(&layouts); - return ret; } static const AVFilterPad avfilter_af_amix_outputs[] = { @@ -621,5 +648,6 @@ .query_formats = query_formats, .inputs = NULL, .outputs = avfilter_af_amix_outputs, + .process_command = process_command, .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_anequalizer.c ffmpeg-4.4/libavfilter/af_anequalizer.c --- ffmpeg-4.2.2/libavfilter/af_anequalizer.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_anequalizer.c 2021-04-08 21:28:39.000000000 +0000 @@ -192,35 +192,23 @@ int ret; pad = (AVFilterPad){ - .name = av_strdup("out0"), + .name = "out0", .type = AVMEDIA_TYPE_AUDIO, }; - if (!pad.name) - return AVERROR(ENOMEM); + ret = ff_insert_outpad(ctx, 0, &pad); + if (ret < 0) + return ret; if (s->draw_curves) { vpad = (AVFilterPad){ - .name = av_strdup("out1"), + .name = "out1", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_video, }; - if (!vpad.name) - return AVERROR(ENOMEM); - } - - ret = ff_insert_outpad(ctx, 0, &pad); - if (ret < 0) { - av_freep(&pad.name); - return ret; - } - - if (s->draw_curves) { ret = ff_insert_outpad(ctx, 1, &vpad); - if (ret < 0) { - av_freep(&vpad.name); + if (ret < 0) return ret; - } } return 0; @@ -243,23 +231,23 @@ if (s->draw_curves) { AVFilterLink *videolink = ctx->outputs[1]; formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &videolink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &videolink->incfg.formats)) < 0) return ret; } formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0 || - (ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0 || + (ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; layouts = ff_all_channel_counts(); - if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0 || - (ret = ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0 || + (ret = ff_channel_layouts_ref(layouts, &outlink->incfg.channel_layouts)) < 0) return ret; formats = ff_all_samplerates(); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0 || - (ret = ff_formats_ref(formats, &outlink->in_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0 || + (ret = ff_formats_ref(formats, &outlink->incfg.samplerates)) < 0) return ret; return 0; @@ -269,8 +257,6 @@ { AudioNEqualizerContext *s = ctx->priv; - for (int i = 0; i < ctx->nb_outputs; i++) - av_freep(&ctx->output_pads[i].name); av_frame_free(&s->video); av_freep(&s->filters); s->nb_filters = 0; @@ -564,7 +550,7 @@ static int add_filter(AudioNEqualizerContext *s, AVFilterLink *inlink) { equalizer(&s->filters[s->nb_filters], inlink->sample_rate); - if (s->nb_filters >= s->nb_allocated) { + if (s->nb_filters >= s->nb_allocated - 1) { EqualizatorFilter *filters; filters = av_calloc(s->nb_allocated, 2 * sizeof(*s->filters)); @@ -707,22 +693,26 @@ return p1; } -static int filter_frame(AVFilterLink *inlink, AVFrame *buf) +static int filter_channels(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) { - AVFilterContext *ctx = inlink->dst; AudioNEqualizerContext *s = ctx->priv; - AVFilterLink *outlink = ctx->outputs[0]; - double *bptr; - int i, n; + AVFrame *buf = arg; + const int start = (buf->channels * jobnr) / nb_jobs; + const int end = (buf->channels * (jobnr+1)) / nb_jobs; - for (i = 0; i < s->nb_filters; i++) { + for (int i = 0; i < s->nb_filters; i++) { EqualizatorFilter *f = &s->filters[i]; + double *bptr; if (f->gain == 0. || f->ignore) continue; + if (f->channel < start || + f->channel >= end) + continue; bptr = (double *)buf->extended_data[f->channel]; - for (n = 0; n < buf->nb_samples; n++) { + for (int n = 0; n < buf->nb_samples; n++) { double sample = bptr[n]; sample = process_sample(f->section, sample); @@ -730,14 +720,32 @@ } } + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *buf) +{ + AVFilterContext *ctx = inlink->dst; + AudioNEqualizerContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + if (!ctx->is_disabled) + ctx->internal->execute(ctx, filter_channels, buf, NULL, FFMIN(inlink->channels, + ff_filter_get_nb_threads(ctx))); + if (s->draw_curves) { + AVFrame *clone; + const int64_t pts = buf->pts + av_rescale_q(buf->nb_samples, (AVRational){ 1, inlink->sample_rate }, outlink->time_base); int ret; s->video->pts = pts; - ret = ff_filter_frame(ctx->outputs[1], av_frame_clone(s->video)); + clone = av_frame_clone(s->video); + if (!clone) + return AVERROR(ENOMEM); + ret = ff_filter_frame(ctx->outputs[1], clone); if (ret < 0) return ret; } @@ -766,6 +774,8 @@ .query_formats = query_formats, .inputs = inputs, .outputs = NULL, - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, .process_command = process_command, + .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | + AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_anlmdn.c ffmpeg-4.4/libavfilter/af_anlmdn.c --- ffmpeg-4.2.2/libavfilter/af_anlmdn.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_anlmdn.c 2021-04-08 21:28:39.000000000 +0000 @@ -72,17 +72,17 @@ }; #define OFFSET(x) offsetof(AudioNLMeansContext, x) -#define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define AFT AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption anlmdn_options[] = { - { "s", "set denoising strength", OFFSET(a), AV_OPT_TYPE_FLOAT, {.dbl=0.00001},0.00001, 10, AF }, - { "p", "set patch duration", OFFSET(pd), AV_OPT_TYPE_DURATION, {.i64=2000}, 1000, 100000, AF }, - { "r", "set research duration", OFFSET(rd), AV_OPT_TYPE_DURATION, {.i64=6000}, 2000, 300000, AF }, - { "o", "set output mode", OFFSET(om), AV_OPT_TYPE_INT, {.i64=OUT_MODE}, 0, NB_MODES-1, AF, "mode" }, - { "i", "input", 0, AV_OPT_TYPE_CONST, {.i64=IN_MODE}, 0, 0, AF, "mode" }, - { "o", "output", 0, AV_OPT_TYPE_CONST, {.i64=OUT_MODE}, 0, 0, AF, "mode" }, - { "n", "noise", 0, AV_OPT_TYPE_CONST, {.i64=NOISE_MODE},0, 0, AF, "mode" }, - { "m", "set smooth factor", OFFSET(m), AV_OPT_TYPE_FLOAT, {.dbl=11.}, 1, 15, AF }, + { "s", "set denoising strength", OFFSET(a), AV_OPT_TYPE_FLOAT, {.dbl=0.00001},0.00001, 10, AFT }, + { "p", "set patch duration", OFFSET(pd), AV_OPT_TYPE_DURATION, {.i64=2000}, 1000, 100000, AFT }, + { "r", "set research duration", OFFSET(rd), AV_OPT_TYPE_DURATION, {.i64=6000}, 2000, 300000, AFT }, + { "o", "set output mode", OFFSET(om), AV_OPT_TYPE_INT, {.i64=OUT_MODE}, 0, NB_MODES-1, AFT, "mode" }, + { "i", "input", 0, AV_OPT_TYPE_CONST, {.i64=IN_MODE}, 0, 0, AFT, "mode" }, + { "o", "output", 0, AV_OPT_TYPE_CONST, {.i64=OUT_MODE}, 0, 0, AFT, "mode" }, + { "n", "noise", 0, AV_OPT_TYPE_CONST, {.i64=NOISE_MODE},0, 0, AFT, "mode" }, + { "m", "set smooth factor", OFFSET(m), AV_OPT_TYPE_FLOAT, {.dbl=11.}, 1, 15, AFT }, { NULL } }; @@ -146,31 +146,72 @@ ff_anlmdn_init_x86(dsp); } -static int config_output(AVFilterLink *outlink) +static int config_filter(AVFilterContext *ctx) { - AVFilterContext *ctx = outlink->src; AudioNLMeansContext *s = ctx->priv; - int ret; + AVFilterLink *outlink = ctx->outputs[0]; + int newK, newS, newH, newN; + AVFrame *new_in, *new_cache; - s->K = av_rescale(s->pd, outlink->sample_rate, AV_TIME_BASE); - s->S = av_rescale(s->rd, outlink->sample_rate, AV_TIME_BASE); + newK = av_rescale(s->pd, outlink->sample_rate, AV_TIME_BASE); + newS = av_rescale(s->rd, outlink->sample_rate, AV_TIME_BASE); - s->eof_left = -1; - s->pts = AV_NOPTS_VALUE; - s->H = s->K * 2 + 1; - s->N = s->H + (s->K + s->S) * 2; + newH = newK * 2 + 1; + newN = newH + (newK + newS) * 2; - av_log(ctx, AV_LOG_DEBUG, "K:%d S:%d H:%d N:%d\n", s->K, s->S, s->H, s->N); + av_log(ctx, AV_LOG_DEBUG, "K:%d S:%d H:%d N:%d\n", newK, newS, newH, newN); + + if (!s->cache || s->cache->nb_samples < newS * 2) { + new_cache = ff_get_audio_buffer(outlink, newS * 2); + if (new_cache) { + av_frame_free(&s->cache); + s->cache = new_cache; + } else { + return AVERROR(ENOMEM); + } + } + if (!s->cache) + return AVERROR(ENOMEM); - av_frame_free(&s->in); - av_frame_free(&s->cache); - s->in = ff_get_audio_buffer(outlink, s->N); + s->pdiff_lut_scale = 1.f / s->m * WEIGHT_LUT_SIZE; + for (int i = 0; i < WEIGHT_LUT_SIZE; i++) { + float w = -i / s->pdiff_lut_scale; + + s->weight_lut[i] = expf(w); + } + + if (!s->in || s->in->nb_samples < newN) { + new_in = ff_get_audio_buffer(outlink, newN); + if (new_in) { + av_frame_free(&s->in); + s->in = new_in; + } else { + return AVERROR(ENOMEM); + } + } if (!s->in) return AVERROR(ENOMEM); - s->cache = ff_get_audio_buffer(outlink, s->S * 2); - if (!s->cache) - return AVERROR(ENOMEM); + s->K = newK; + s->S = newS; + s->H = newH; + s->N = newN; + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AudioNLMeansContext *s = ctx->priv; + int ret; + + s->eof_left = -1; + s->pts = AV_NOPTS_VALUE; + + ret = config_filter(ctx); + if (ret < 0) + return ret; s->fifo = av_audio_fifo_alloc(outlink->format, outlink->channels, s->N); if (!s->fifo) @@ -180,13 +221,6 @@ if (ret < 0) return ret; - s->pdiff_lut_scale = 1.f / s->m * WEIGHT_LUT_SIZE; - for (int i = 0; i < WEIGHT_LUT_SIZE; i++) { - float w = -i / s->pdiff_lut_scale; - - s->weight_lut[i] = expf(w); - } - ff_anlmdn_init(&s->dsp); return 0; @@ -297,7 +331,7 @@ out->nb_samples = FFMIN(s->eof_left, s->offset); s->eof_left -= out->nb_samples; } - s->pts += s->offset; + s->pts += av_rescale_q(s->offset, (AVRational){1, outlink->sample_rate}, outlink->time_base); return ff_filter_frame(outlink, out); } @@ -330,38 +364,31 @@ return ret; } -static av_cold void uninit(AVFilterContext *ctx) -{ - AudioNLMeansContext *s = ctx->priv; - - av_audio_fifo_free(s->fifo); - av_frame_free(&s->in); - av_frame_free(&s->cache); -} - static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags) { - AudioNLMeansContext *s = ctx->priv; + int ret; - if (!strcmp(cmd, "s")) { - float a; + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; - if (av_sscanf(args, "%f", &a) == 1) - s->a = av_clipf(a, 0.00001, 10); - } else if (!strcmp(cmd, "o")) { - if (!strcmp(args, "i")) { - s->om = IN_MODE; - } else if (!strcmp(args, "o")) { - s->om = OUT_MODE; - } else if (!strcmp(args, "n")) { - s->om = NOISE_MODE; - } - } + ret = config_filter(ctx); + if (ret < 0) + return ret; return 0; } +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioNLMeansContext *s = ctx->priv; + + av_audio_fifo_free(s->fifo); + av_frame_free(&s->in); + av_frame_free(&s->cache); +} + static const AVFilterPad inputs[] = { { .name = "default", diff -Nru ffmpeg-4.2.2/libavfilter/af_anlms.c ffmpeg-4.4/libavfilter/af_anlms.c --- ffmpeg-4.2.2/libavfilter/af_anlms.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_anlms.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2019 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/float_dsp.h" +#include "libavutil/opt.h" + +#include "audio.h" +#include "avfilter.h" +#include "formats.h" +#include "filters.h" +#include "internal.h" + +enum OutModes { + IN_MODE, + DESIRED_MODE, + OUT_MODE, + NOISE_MODE, + NB_OMODES +}; + +typedef struct AudioNLMSContext { + const AVClass *class; + + int order; + float mu; + float eps; + float leakage; + int output_mode; + + int kernel_size; + AVFrame *offset; + AVFrame *delay; + AVFrame *coeffs; + AVFrame *tmp; + + AVFrame *frame[2]; + + AVFloatDSPContext *fdsp; +} AudioNLMSContext; + +#define OFFSET(x) offsetof(AudioNLMSContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define AT AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption anlms_options[] = { + { "order", "set the filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=256}, 1, INT16_MAX, A }, + { "mu", "set the filter mu", OFFSET(mu), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 2, AT }, + { "eps", "set the filter eps", OFFSET(eps), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, AT }, + { "leakage", "set the filter leakage", OFFSET(leakage), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, AT }, + { "out_mode", "set output mode", OFFSET(output_mode), AV_OPT_TYPE_INT, {.i64=OUT_MODE}, 0, NB_OMODES-1, AT, "mode" }, + { "i", "input", 0, AV_OPT_TYPE_CONST, {.i64=IN_MODE}, 0, 0, AT, "mode" }, + { "d", "desired", 0, AV_OPT_TYPE_CONST, {.i64=DESIRED_MODE}, 0, 0, AT, "mode" }, + { "o", "output", 0, AV_OPT_TYPE_CONST, {.i64=OUT_MODE}, 0, 0, AT, "mode" }, + { "n", "noise", 0, AV_OPT_TYPE_CONST, {.i64=NOISE_MODE}, 0, 0, AT, "mode" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(anlms); + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats; + AVFilterChannelLayouts *layouts; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE + }; + int ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + formats = ff_all_samplerates(); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_samplerates(ctx, formats); +} + +static float fir_sample(AudioNLMSContext *s, float sample, float *delay, + float *coeffs, float *tmp, int *offset) +{ + const int order = s->order; + float output; + + delay[*offset] = sample; + + memcpy(tmp, coeffs + order - *offset, order * sizeof(float)); + + output = s->fdsp->scalarproduct_float(delay, tmp, s->kernel_size); + + if (--(*offset) < 0) + *offset = order - 1; + + return output; +} + +static float process_sample(AudioNLMSContext *s, float input, float desired, + float *delay, float *coeffs, float *tmp, int *offsetp) +{ + const int order = s->order; + const float leakage = s->leakage; + const float mu = s->mu; + const float a = 1.f - leakage * mu; + float sum, output, e, norm, b; + int offset = *offsetp; + + delay[offset + order] = input; + + output = fir_sample(s, input, delay, coeffs, tmp, offsetp); + e = desired - output; + + sum = s->fdsp->scalarproduct_float(delay, delay, s->kernel_size); + + norm = s->eps + sum; + b = mu * e / norm; + + memcpy(tmp, delay + offset, order * sizeof(float)); + + s->fdsp->vector_fmul_scalar(coeffs, coeffs, a, s->kernel_size); + + s->fdsp->vector_fmac_scalar(coeffs, tmp, b, s->kernel_size); + + memcpy(coeffs + order, coeffs, order * sizeof(float)); + + switch (s->output_mode) { + case IN_MODE: output = input; break; + case DESIRED_MODE: output = desired; break; + case OUT_MODE: /*output = output;*/ break; + case NOISE_MODE: output = desired - output; break; + } + return output; +} + +static int process_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AudioNLMSContext *s = ctx->priv; + AVFrame *out = arg; + const int start = (out->channels * jobnr) / nb_jobs; + const int end = (out->channels * (jobnr+1)) / nb_jobs; + + for (int c = start; c < end; c++) { + const float *input = (const float *)s->frame[0]->extended_data[c]; + const float *desired = (const float *)s->frame[1]->extended_data[c]; + float *delay = (float *)s->delay->extended_data[c]; + float *coeffs = (float *)s->coeffs->extended_data[c]; + float *tmp = (float *)s->tmp->extended_data[c]; + int *offset = (int *)s->offset->extended_data[c]; + float *output = (float *)out->extended_data[c]; + + for (int n = 0; n < out->nb_samples; n++) + output[n] = process_sample(s, input[n], desired[n], delay, coeffs, tmp, offset); + } + + return 0; +} + +static int activate(AVFilterContext *ctx) +{ + AudioNLMSContext *s = ctx->priv; + int i, ret, status; + int nb_samples; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); + + nb_samples = FFMIN(ff_inlink_queued_samples(ctx->inputs[0]), + ff_inlink_queued_samples(ctx->inputs[1])); + for (i = 0; i < ctx->nb_inputs && nb_samples > 0; i++) { + if (s->frame[i]) + continue; + + if (ff_inlink_check_available_samples(ctx->inputs[i], nb_samples) > 0) { + ret = ff_inlink_consume_samples(ctx->inputs[i], nb_samples, nb_samples, &s->frame[i]); + if (ret < 0) + return ret; + } + } + + if (s->frame[0] && s->frame[1]) { + AVFrame *out; + + out = ff_get_audio_buffer(ctx->outputs[0], s->frame[0]->nb_samples); + if (!out) { + av_frame_free(&s->frame[0]); + av_frame_free(&s->frame[1]); + return AVERROR(ENOMEM); + } + + ctx->internal->execute(ctx, process_channels, out, NULL, FFMIN(ctx->outputs[0]->channels, + ff_filter_get_nb_threads(ctx))); + + out->pts = s->frame[0]->pts; + + av_frame_free(&s->frame[0]); + av_frame_free(&s->frame[1]); + + ret = ff_filter_frame(ctx->outputs[0], out); + if (ret < 0) + return ret; + } + + if (!nb_samples) { + for (i = 0; i < 2; i++) { + if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) { + ff_outlink_set_status(ctx->outputs[0], status, pts); + return 0; + } + } + } + + if (ff_outlink_frame_wanted(ctx->outputs[0])) { + for (i = 0; i < 2; i++) { + if (ff_inlink_queued_samples(ctx->inputs[i]) > 0) + continue; + ff_inlink_request_frame(ctx->inputs[i]); + return 0; + } + } + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AudioNLMSContext *s = ctx->priv; + + s->kernel_size = FFALIGN(s->order, 16); + + if (!s->offset) + s->offset = ff_get_audio_buffer(outlink, 1); + if (!s->delay) + s->delay = ff_get_audio_buffer(outlink, 2 * s->kernel_size); + if (!s->coeffs) + s->coeffs = ff_get_audio_buffer(outlink, 2 * s->kernel_size); + if (!s->tmp) + s->tmp = ff_get_audio_buffer(outlink, s->kernel_size); + if (!s->delay || !s->coeffs || !s->offset || !s->tmp) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold int init(AVFilterContext *ctx) +{ + AudioNLMSContext *s = ctx->priv; + + s->fdsp = avpriv_float_dsp_alloc(0); + if (!s->fdsp) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioNLMSContext *s = ctx->priv; + + av_freep(&s->fdsp); + av_frame_free(&s->delay); + av_frame_free(&s->coeffs); + av_frame_free(&s->offset); + av_frame_free(&s->tmp); +} + +static const AVFilterPad inputs[] = { + { + .name = "input", + .type = AVMEDIA_TYPE_AUDIO, + }, + { + .name = "desired", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_af_anlms = { + .name = "anlms", + .description = NULL_IF_CONFIG_SMALL("Apply Normalized Least-Mean-Squares algorithm to first audio stream."), + .priv_size = sizeof(AudioNLMSContext), + .priv_class = &anlms_class, + .init = init, + .uninit = uninit, + .activate = activate, + .query_formats = query_formats, + .inputs = inputs, + .outputs = outputs, + .flags = AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/af_aresample.c ffmpeg-4.4/libavfilter/af_aresample.c --- ffmpeg-4.2.2/libavfilter/af_aresample.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_aresample.c 2021-04-08 21:28:39.000000000 +0000 @@ -95,15 +95,15 @@ av_opt_get_int(aresample->swr, "ocl", 0, &out_layout); in_formats = ff_all_formats(AVMEDIA_TYPE_AUDIO); - if ((ret = ff_formats_ref(in_formats, &inlink->out_formats)) < 0) + if ((ret = ff_formats_ref(in_formats, &inlink->outcfg.formats)) < 0) return ret; in_samplerates = ff_all_samplerates(); - if ((ret = ff_formats_ref(in_samplerates, &inlink->out_samplerates)) < 0) + if ((ret = ff_formats_ref(in_samplerates, &inlink->outcfg.samplerates)) < 0) return ret; in_layouts = ff_all_channel_counts(); - if ((ret = ff_channel_layouts_ref(in_layouts, &inlink->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(in_layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; if(out_rate > 0) { @@ -113,7 +113,7 @@ out_samplerates = ff_all_samplerates(); } - if ((ret = ff_formats_ref(out_samplerates, &outlink->in_samplerates)) < 0) + if ((ret = ff_formats_ref(out_samplerates, &outlink->incfg.samplerates)) < 0) return ret; if(out_format != AV_SAMPLE_FMT_NONE) { @@ -121,16 +121,16 @@ out_formats = ff_make_format_list(formatlist); } else out_formats = ff_all_formats(AVMEDIA_TYPE_AUDIO); - if ((ret = ff_formats_ref(out_formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(out_formats, &outlink->incfg.formats)) < 0) return ret; if(out_layout) { int64_t layout_list[] = { out_layout, -1 }; - out_layouts = avfilter_make_format64_list(layout_list); + out_layouts = ff_make_format64_list(layout_list); } else out_layouts = ff_all_channel_counts(); - return ff_channel_layouts_ref(out_layouts, &outlink->in_channel_layouts); + return ff_channel_layouts_ref(out_layouts, &outlink->incfg.channel_layouts); } @@ -293,10 +293,19 @@ return ret; } +#if FF_API_CHILD_CLASS_NEXT static const AVClass *resample_child_class_next(const AVClass *prev) { return prev ? NULL : swr_get_class(); } +#endif + +static const AVClass *resample_child_class_iterate(void **iter) +{ + const AVClass *c = *iter ? NULL : swr_get_class(); + *iter = (void*)(uintptr_t)c; + return c; +} static void *resample_child_next(void *obj, void *prev) { @@ -317,7 +326,10 @@ .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = resample_child_class_next, +#endif + .child_class_iterate = resample_child_class_iterate, .child_next = resample_child_next, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_arnndn.c ffmpeg-4.4/libavfilter/af_arnndn.c --- ffmpeg-4.2.2/libavfilter/af_arnndn.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_arnndn.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,1636 @@ +/* + * Copyright (c) 2018 Gregor Richards + * Copyright (c) 2017 Mozilla + * Copyright (c) 2005-2009 Xiph.Org Foundation + * Copyright (c) 2007-2008 CSIRO + * Copyright (c) 2008-2011 Octasic Inc. + * Copyright (c) Jean-Marc Valin + * Copyright (c) 2019 Paul B Mahol + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/float_dsp.h" +#include "libavutil/mem_internal.h" +#include "libavutil/opt.h" +#include "libavutil/tx.h" +#include "avfilter.h" +#include "audio.h" +#include "filters.h" +#include "formats.h" + +#define FRAME_SIZE_SHIFT 2 +#define FRAME_SIZE (120<name) { \ + av_free((void *) model->name->input_weights); \ + av_free((void *) model->name->bias); \ + av_free((void *) model->name); \ + } \ + } while (0) +#define FREE_GRU(name) do { \ + if (model->name) { \ + av_free((void *) model->name->input_weights); \ + av_free((void *) model->name->recurrent_weights); \ + av_free((void *) model->name->bias); \ + av_free((void *) model->name); \ + } \ + } while (0) + + if (!model) + return; + FREE_DENSE(input_dense); + FREE_GRU(vad_gru); + FREE_GRU(noise_gru); + FREE_GRU(denoise_gru); + FREE_DENSE(denoise_output); + FREE_DENSE(vad_output); + av_free(model); +} + +static int rnnoise_model_from_file(FILE *f, RNNModel **rnn) +{ + RNNModel *ret = NULL; + DenseLayer *input_dense; + GRULayer *vad_gru; + GRULayer *noise_gru; + GRULayer *denoise_gru; + DenseLayer *denoise_output; + DenseLayer *vad_output; + int in; + + if (fscanf(f, "rnnoise-nu model file version %d\n", &in) != 1 || in != 1) + return AVERROR_INVALIDDATA; + + ret = av_calloc(1, sizeof(RNNModel)); + if (!ret) + return AVERROR(ENOMEM); + +#define ALLOC_LAYER(type, name) \ + name = av_calloc(1, sizeof(type)); \ + if (!name) { \ + rnnoise_model_free(ret); \ + return AVERROR(ENOMEM); \ + } \ + ret->name = name + + ALLOC_LAYER(DenseLayer, input_dense); + ALLOC_LAYER(GRULayer, vad_gru); + ALLOC_LAYER(GRULayer, noise_gru); + ALLOC_LAYER(GRULayer, denoise_gru); + ALLOC_LAYER(DenseLayer, denoise_output); + ALLOC_LAYER(DenseLayer, vad_output); + +#define INPUT_VAL(name) do { \ + if (fscanf(f, "%d", &in) != 1 || in < 0 || in > 128) { \ + rnnoise_model_free(ret); \ + return AVERROR(EINVAL); \ + } \ + name = in; \ + } while (0) + +#define INPUT_ACTIVATION(name) do { \ + int activation; \ + INPUT_VAL(activation); \ + switch (activation) { \ + case F_ACTIVATION_SIGMOID: \ + name = ACTIVATION_SIGMOID; \ + break; \ + case F_ACTIVATION_RELU: \ + name = ACTIVATION_RELU; \ + break; \ + default: \ + name = ACTIVATION_TANH; \ + } \ + } while (0) + +#define INPUT_ARRAY(name, len) do { \ + float *values = av_calloc((len), sizeof(float)); \ + if (!values) { \ + rnnoise_model_free(ret); \ + return AVERROR(ENOMEM); \ + } \ + name = values; \ + for (int i = 0; i < (len); i++) { \ + if (fscanf(f, "%d", &in) != 1) { \ + rnnoise_model_free(ret); \ + return AVERROR(EINVAL); \ + } \ + values[i] = in; \ + } \ + } while (0) + +#define INPUT_ARRAY3(name, len0, len1, len2) do { \ + float *values = av_calloc(FFALIGN((len0), 4) * FFALIGN((len1), 4) * (len2), sizeof(float)); \ + if (!values) { \ + rnnoise_model_free(ret); \ + return AVERROR(ENOMEM); \ + } \ + name = values; \ + for (int k = 0; k < (len0); k++) { \ + for (int i = 0; i < (len2); i++) { \ + for (int j = 0; j < (len1); j++) { \ + if (fscanf(f, "%d", &in) != 1) { \ + rnnoise_model_free(ret); \ + return AVERROR(EINVAL); \ + } \ + values[j * (len2) * FFALIGN((len0), 4) + i * FFALIGN((len0), 4) + k] = in; \ + } \ + } \ + } \ + } while (0) + +#define NEW_LINE() do { \ + int c; \ + while ((c = fgetc(f)) != EOF) { \ + if (c == '\n') \ + break; \ + } \ + } while (0) + +#define INPUT_DENSE(name) do { \ + INPUT_VAL(name->nb_inputs); \ + INPUT_VAL(name->nb_neurons); \ + ret->name ## _size = name->nb_neurons; \ + INPUT_ACTIVATION(name->activation); \ + NEW_LINE(); \ + INPUT_ARRAY(name->input_weights, name->nb_inputs * name->nb_neurons); \ + NEW_LINE(); \ + INPUT_ARRAY(name->bias, name->nb_neurons); \ + NEW_LINE(); \ + } while (0) + +#define INPUT_GRU(name) do { \ + INPUT_VAL(name->nb_inputs); \ + INPUT_VAL(name->nb_neurons); \ + ret->name ## _size = name->nb_neurons; \ + INPUT_ACTIVATION(name->activation); \ + NEW_LINE(); \ + INPUT_ARRAY3(name->input_weights, name->nb_inputs, name->nb_neurons, 3); \ + NEW_LINE(); \ + INPUT_ARRAY3(name->recurrent_weights, name->nb_neurons, name->nb_neurons, 3); \ + NEW_LINE(); \ + INPUT_ARRAY(name->bias, name->nb_neurons * 3); \ + NEW_LINE(); \ + } while (0) + + INPUT_DENSE(input_dense); + INPUT_GRU(vad_gru); + INPUT_GRU(noise_gru); + INPUT_GRU(denoise_gru); + INPUT_DENSE(denoise_output); + INPUT_DENSE(vad_output); + + if (vad_output->nb_neurons != 1) { + rnnoise_model_free(ret); + return AVERROR(EINVAL); + } + + *rnn = ret; + + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *layouts = NULL; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE + }; + int ret, sample_rates[] = { 48000, -1 }; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_make_format_list(sample_rates); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_samplerates(ctx, formats); +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AudioRNNContext *s = ctx->priv; + int ret; + + s->channels = inlink->channels; + + if (!s->st) + s->st = av_calloc(s->channels, sizeof(DenoiseState)); + if (!s->st) + return AVERROR(ENOMEM); + + for (int i = 0; i < s->channels; i++) { + DenoiseState *st = &s->st[i]; + + st->rnn[0].model = s->model[0]; + st->rnn[0].vad_gru_state = av_calloc(sizeof(float), FFALIGN(s->model[0]->vad_gru_size, 16)); + st->rnn[0].noise_gru_state = av_calloc(sizeof(float), FFALIGN(s->model[0]->noise_gru_size, 16)); + st->rnn[0].denoise_gru_state = av_calloc(sizeof(float), FFALIGN(s->model[0]->denoise_gru_size, 16)); + if (!st->rnn[0].vad_gru_state || + !st->rnn[0].noise_gru_state || + !st->rnn[0].denoise_gru_state) + return AVERROR(ENOMEM); + } + + for (int i = 0; i < s->channels; i++) { + DenoiseState *st = &s->st[i]; + + if (!st->tx) + ret = av_tx_init(&st->tx, &st->tx_fn, AV_TX_FLOAT_FFT, 0, WINDOW_SIZE, NULL, 0); + if (ret < 0) + return ret; + + if (!st->txi) + ret = av_tx_init(&st->txi, &st->txi_fn, AV_TX_FLOAT_FFT, 1, WINDOW_SIZE, NULL, 0); + if (ret < 0) + return ret; + } + + return 0; +} + +static void biquad(float *y, float mem[2], const float *x, + const float *b, const float *a, int N) +{ + for (int i = 0; i < N; i++) { + float xi, yi; + + xi = x[i]; + yi = x[i] + mem[0]; + mem[0] = mem[1] + (b[0]*xi - a[0]*yi); + mem[1] = (b[1]*xi - a[1]*yi); + y[i] = yi; + } +} + +#define RNN_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) +#define RNN_CLEAR(dst, n) (memset((dst), 0, (n)*sizeof(*(dst)))) +#define RNN_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) + +static void forward_transform(DenoiseState *st, AVComplexFloat *out, const float *in) +{ + AVComplexFloat x[WINDOW_SIZE]; + AVComplexFloat y[WINDOW_SIZE]; + + for (int i = 0; i < WINDOW_SIZE; i++) { + x[i].re = in[i]; + x[i].im = 0; + } + + st->tx_fn(st->tx, y, x, sizeof(float)); + + RNN_COPY(out, y, FREQ_SIZE); +} + +static void inverse_transform(DenoiseState *st, float *out, const AVComplexFloat *in) +{ + AVComplexFloat x[WINDOW_SIZE]; + AVComplexFloat y[WINDOW_SIZE]; + + RNN_COPY(x, in, FREQ_SIZE); + + for (int i = FREQ_SIZE; i < WINDOW_SIZE; i++) { + x[i].re = x[WINDOW_SIZE - i].re; + x[i].im = -x[WINDOW_SIZE - i].im; + } + + st->txi_fn(st->txi, y, x, sizeof(float)); + + for (int i = 0; i < WINDOW_SIZE; i++) + out[i] = y[i].re / WINDOW_SIZE; +} + +static const uint8_t eband5ms[] = { +/*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 20k*/ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 34, 40, 48, 60, 78, 100 +}; + +static void compute_band_energy(float *bandE, const AVComplexFloat *X) +{ + float sum[NB_BANDS] = {0}; + + for (int i = 0; i < NB_BANDS - 1; i++) { + int band_size; + + band_size = (eband5ms[i + 1] - eband5ms[i]) << FRAME_SIZE_SHIFT; + for (int j = 0; j < band_size; j++) { + float tmp, frac = (float)j / band_size; + + tmp = SQUARE(X[(eband5ms[i] << FRAME_SIZE_SHIFT) + j].re); + tmp += SQUARE(X[(eband5ms[i] << FRAME_SIZE_SHIFT) + j].im); + sum[i] += (1.f - frac) * tmp; + sum[i + 1] += frac * tmp; + } + } + + sum[0] *= 2; + sum[NB_BANDS - 1] *= 2; + + for (int i = 0; i < NB_BANDS; i++) + bandE[i] = sum[i]; +} + +static void compute_band_corr(float *bandE, const AVComplexFloat *X, const AVComplexFloat *P) +{ + float sum[NB_BANDS] = { 0 }; + + for (int i = 0; i < NB_BANDS - 1; i++) { + int band_size; + + band_size = (eband5ms[i + 1] - eband5ms[i]) << FRAME_SIZE_SHIFT; + for (int j = 0; j < band_size; j++) { + float tmp, frac = (float)j / band_size; + + tmp = X[(eband5ms[i]<analysis_mem, FRAME_SIZE); + RNN_COPY(x + FRAME_SIZE, in, FRAME_SIZE); + RNN_COPY(st->analysis_mem, in, FRAME_SIZE); + s->fdsp->vector_fmul(x, x, s->window, WINDOW_SIZE); + forward_transform(st, X, x); + compute_band_energy(Ex, X); +} + +static void frame_synthesis(AudioRNNContext *s, DenoiseState *st, float *out, const AVComplexFloat *y) +{ + LOCAL_ALIGNED_32(float, x, [WINDOW_SIZE]); + const float *src = st->history; + const float mix = s->mix; + const float imix = 1.f - FFMAX(mix, 0.f); + + inverse_transform(st, x, y); + s->fdsp->vector_fmul(x, x, s->window, WINDOW_SIZE); + s->fdsp->vector_fmac_scalar(x, st->synthesis_mem, 1.f, FRAME_SIZE); + RNN_COPY(out, x, FRAME_SIZE); + RNN_COPY(st->synthesis_mem, &x[FRAME_SIZE], FRAME_SIZE); + + for (int n = 0; n < FRAME_SIZE; n++) + out[n] = out[n] * mix + src[n] * imix; +} + +static inline void xcorr_kernel(const float *x, const float *y, float sum[4], int len) +{ + float y_0, y_1, y_2, y_3 = 0; + int j; + + y_0 = *y++; + y_1 = *y++; + y_2 = *y++; + + for (j = 0; j < len - 3; j += 4) { + float tmp; + + tmp = *x++; + y_3 = *y++; + sum[0] += tmp * y_0; + sum[1] += tmp * y_1; + sum[2] += tmp * y_2; + sum[3] += tmp * y_3; + tmp = *x++; + y_0 = *y++; + sum[0] += tmp * y_1; + sum[1] += tmp * y_2; + sum[2] += tmp * y_3; + sum[3] += tmp * y_0; + tmp = *x++; + y_1 = *y++; + sum[0] += tmp * y_2; + sum[1] += tmp * y_3; + sum[2] += tmp * y_0; + sum[3] += tmp * y_1; + tmp = *x++; + y_2 = *y++; + sum[0] += tmp * y_3; + sum[1] += tmp * y_0; + sum[2] += tmp * y_1; + sum[3] += tmp * y_2; + } + + if (j++ < len) { + float tmp = *x++; + + y_3 = *y++; + sum[0] += tmp * y_0; + sum[1] += tmp * y_1; + sum[2] += tmp * y_2; + sum[3] += tmp * y_3; + } + + if (j++ < len) { + float tmp=*x++; + + y_0 = *y++; + sum[0] += tmp * y_1; + sum[1] += tmp * y_2; + sum[2] += tmp * y_3; + sum[3] += tmp * y_0; + } + + if (j < len) { + float tmp=*x++; + + y_1 = *y++; + sum[0] += tmp * y_2; + sum[1] += tmp * y_3; + sum[2] += tmp * y_0; + sum[3] += tmp * y_1; + } +} + +static inline float celt_inner_prod(const float *x, + const float *y, int N) +{ + float xy = 0.f; + + for (int i = 0; i < N; i++) + xy += x[i] * y[i]; + + return xy; +} + +static void celt_pitch_xcorr(const float *x, const float *y, + float *xcorr, int len, int max_pitch) +{ + int i; + + for (i = 0; i < max_pitch - 3; i += 4) { + float sum[4] = { 0, 0, 0, 0}; + + xcorr_kernel(x, y + i, sum, len); + + xcorr[i] = sum[0]; + xcorr[i + 1] = sum[1]; + xcorr[i + 2] = sum[2]; + xcorr[i + 3] = sum[3]; + } + /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */ + for (; i < max_pitch; i++) { + xcorr[i] = celt_inner_prod(x, y + i, len); + } +} + +static int celt_autocorr(const float *x, /* in: [0...n-1] samples x */ + float *ac, /* out: [0...lag-1] ac values */ + const float *window, + int overlap, + int lag, + int n) +{ + int fastN = n - lag; + int shift; + const float *xptr; + float xx[PITCH_BUF_SIZE>>1]; + + if (overlap == 0) { + xptr = x; + } else { + for (int i = 0; i < n; i++) + xx[i] = x[i]; + for (int i = 0; i < overlap; i++) { + xx[i] = x[i] * window[i]; + xx[n-i-1] = x[n-i-1] * window[i]; + } + xptr = xx; + } + + shift = 0; + celt_pitch_xcorr(xptr, xptr, ac, fastN, lag+1); + + for (int k = 0; k <= lag; k++) { + float d = 0.f; + + for (int i = k + fastN; i < n; i++) + d += xptr[i] * xptr[i-k]; + ac[k] += d; + } + + return shift; +} + +static void celt_lpc(float *lpc, /* out: [0...p-1] LPC coefficients */ + const float *ac, /* in: [0...p] autocorrelation values */ + int p) +{ + float r, error = ac[0]; + + RNN_CLEAR(lpc, p); + if (ac[0] != 0) { + for (int i = 0; i < p; i++) { + /* Sum up this iteration's reflection coefficient */ + float rr = 0; + for (int j = 0; j < i; j++) + rr += (lpc[j] * ac[i - j]); + rr += ac[i + 1]; + r = -rr/error; + /* Update LPC coefficients and total error */ + lpc[i] = r; + for (int j = 0; j < (i + 1) >> 1; j++) { + float tmp1, tmp2; + tmp1 = lpc[j]; + tmp2 = lpc[i-1-j]; + lpc[j] = tmp1 + (r*tmp2); + lpc[i-1-j] = tmp2 + (r*tmp1); + } + + error = error - (r * r *error); + /* Bail out once we get 30 dB gain */ + if (error < .001f * ac[0]) + break; + } + } +} + +static void celt_fir5(const float *x, + const float *num, + float *y, + int N, + float *mem) +{ + float num0, num1, num2, num3, num4; + float mem0, mem1, mem2, mem3, mem4; + + num0 = num[0]; + num1 = num[1]; + num2 = num[2]; + num3 = num[3]; + num4 = num[4]; + mem0 = mem[0]; + mem1 = mem[1]; + mem2 = mem[2]; + mem3 = mem[3]; + mem4 = mem[4]; + + for (int i = 0; i < N; i++) { + float sum = x[i]; + + sum += (num0*mem0); + sum += (num1*mem1); + sum += (num2*mem2); + sum += (num3*mem3); + sum += (num4*mem4); + mem4 = mem3; + mem3 = mem2; + mem2 = mem1; + mem1 = mem0; + mem0 = x[i]; + y[i] = sum; + } + + mem[0] = mem0; + mem[1] = mem1; + mem[2] = mem2; + mem[3] = mem3; + mem[4] = mem4; +} + +static void pitch_downsample(float *x[], float *x_lp, + int len, int C) +{ + float ac[5]; + float tmp=Q15ONE; + float lpc[4], mem[5]={0,0,0,0,0}; + float lpc2[5]; + float c1 = .8f; + + for (int i = 1; i < len >> 1; i++) + x_lp[i] = .5f * (.5f * (x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]); + x_lp[0] = .5f * (.5f * (x[0][1])+x[0][0]); + if (C==2) { + for (int i = 1; i < len >> 1; i++) + x_lp[i] += (.5f * (.5f * (x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i])); + x_lp[0] += .5f * (.5f * (x[1][1])+x[1][0]); + } + + celt_autocorr(x_lp, ac, NULL, 0, 4, len>>1); + + /* Noise floor -40 dB */ + ac[0] *= 1.0001f; + /* Lag windowing */ + for (int i = 1; i <= 4; i++) { + /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/ + ac[i] -= ac[i]*(.008f*i)*(.008f*i); + } + + celt_lpc(lpc, ac, 4); + for (int i = 0; i < 4; i++) { + tmp = .9f * tmp; + lpc[i] = (lpc[i] * tmp); + } + /* Add a zero */ + lpc2[0] = lpc[0] + .8f; + lpc2[1] = lpc[1] + (c1 * lpc[0]); + lpc2[2] = lpc[2] + (c1 * lpc[1]); + lpc2[3] = lpc[3] + (c1 * lpc[2]); + lpc2[4] = (c1 * lpc[3]); + celt_fir5(x_lp, lpc2, x_lp, len>>1, mem); +} + +static inline void dual_inner_prod(const float *x, const float *y01, const float *y02, + int N, float *xy1, float *xy2) +{ + float xy01 = 0, xy02 = 0; + + for (int i = 0; i < N; i++) { + xy01 += (x[i] * y01[i]); + xy02 += (x[i] * y02[i]); + } + + *xy1 = xy01; + *xy2 = xy02; +} + +static float compute_pitch_gain(float xy, float xx, float yy) +{ + return xy / sqrtf(1.f + xx * yy); +} + +static const uint8_t second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2}; +static float remove_doubling(float *x, int maxperiod, int minperiod, int N, + int *T0_, int prev_period, float prev_gain) +{ + int k, i, T, T0; + float g, g0; + float pg; + float xy,xx,yy,xy2; + float xcorr[3]; + float best_xy, best_yy; + int offset; + int minperiod0; + float yy_lookup[PITCH_MAX_PERIOD+1]; + + minperiod0 = minperiod; + maxperiod /= 2; + minperiod /= 2; + *T0_ /= 2; + prev_period /= 2; + N /= 2; + x += maxperiod; + if (*T0_>=maxperiod) + *T0_=maxperiod-1; + + T = T0 = *T0_; + dual_inner_prod(x, x, x-T0, N, &xx, &xy); + yy_lookup[0] = xx; + yy=xx; + for (i = 1; i <= maxperiod; i++) { + yy = yy+(x[-i] * x[-i])-(x[N-i] * x[N-i]); + yy_lookup[i] = FFMAX(0, yy); + } + yy = yy_lookup[T0]; + best_xy = xy; + best_yy = yy; + g = g0 = compute_pitch_gain(xy, xx, yy); + /* Look for any pitch at T/k */ + for (k = 2; k <= 15; k++) { + int T1, T1b; + float g1; + float cont=0; + float thresh; + T1 = (2*T0+k)/(2*k); + if (T1 < minperiod) + break; + /* Look for another strong correlation at T1b */ + if (k==2) + { + if (T1+T0>maxperiod) + T1b = T0; + else + T1b = T0+T1; + } else + { + T1b = (2*second_check[k]*T0+k)/(2*k); + } + dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2); + xy = .5f * (xy + xy2); + yy = .5f * (yy_lookup[T1] + yy_lookup[T1b]); + g1 = compute_pitch_gain(xy, xx, yy); + if (FFABS(T1-prev_period)<=1) + cont = prev_gain; + else if (FFABS(T1-prev_period)<=2 && 5 * k * k < T0) + cont = prev_gain * .5f; + else + cont = 0; + thresh = FFMAX(.3f, (.7f * g0) - cont); + /* Bias against very high pitch (very short period) to avoid false-positives + due to short-term correlation */ + if (T1<3*minperiod) + thresh = FFMAX(.4f, (.85f * g0) - cont); + else if (T1<2*minperiod) + thresh = FFMAX(.5f, (.9f * g0) - cont); + if (g1 > thresh) + { + best_xy = xy; + best_yy = yy; + T = T1; + g = g1; + } + } + best_xy = FFMAX(0, best_xy); + if (best_yy <= best_xy) + pg = Q15ONE; + else + pg = best_xy/(best_yy + 1); + + for (k = 0; k < 3; k++) + xcorr[k] = celt_inner_prod(x, x-(T+k-1), N); + if ((xcorr[2]-xcorr[0]) > .7f * (xcorr[1]-xcorr[0])) + offset = 1; + else if ((xcorr[0]-xcorr[2]) > (.7f * (xcorr[1] - xcorr[2]))) + offset = -1; + else + offset = 0; + if (pg > g) + pg = g; + *T0_ = 2*T+offset; + + if (*T0_0) { + float num; + float xcorr16; + + xcorr16 = xcorr[i]; + /* Considering the range of xcorr16, this should avoid both underflows + and overflows (inf) when squaring xcorr16 */ + xcorr16 *= 1e-12f; + num = xcorr16 * xcorr16; + if ((num * best_den[1]) > (best_num[1] * Syy)) { + if ((num * best_den[0]) > (best_num[0] * Syy)) { + best_num[1] = best_num[0]; + best_den[1] = best_den[0]; + best_pitch[1] = best_pitch[0]; + best_num[0] = num; + best_den[0] = Syy; + best_pitch[0] = i; + } else { + best_num[1] = num; + best_den[1] = Syy; + best_pitch[1] = i; + } + } + } + Syy += y[i+len]*y[i+len] - y[i] * y[i]; + Syy = FFMAX(1, Syy); + } +} + +static void pitch_search(const float *x_lp, float *y, + int len, int max_pitch, int *pitch) +{ + int lag; + int best_pitch[2]={0,0}; + int offset; + + float x_lp4[WINDOW_SIZE]; + float y_lp4[WINDOW_SIZE]; + float xcorr[WINDOW_SIZE]; + + lag = len+max_pitch; + + /* Downsample by 2 again */ + for (int j = 0; j < len >> 2; j++) + x_lp4[j] = x_lp[2*j]; + for (int j = 0; j < lag >> 2; j++) + y_lp4[j] = y[2*j]; + + /* Coarse search with 4x decimation */ + + celt_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2); + + find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch); + + /* Finer search with 2x decimation */ + for (int i = 0; i < max_pitch >> 1; i++) { + float sum; + xcorr[i] = 0; + if (FFABS(i-2*best_pitch[0])>2 && FFABS(i-2*best_pitch[1])>2) + continue; + sum = celt_inner_prod(x_lp, y+i, len>>1); + xcorr[i] = FFMAX(-1, sum); + } + + find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch); + + /* Refine by pseudo-interpolation */ + if (best_pitch[0] > 0 && best_pitch[0] < (max_pitch >> 1) - 1) { + float a, b, c; + + a = xcorr[best_pitch[0] - 1]; + b = xcorr[best_pitch[0]]; + c = xcorr[best_pitch[0] + 1]; + if (c - a > .7f * (b - a)) + offset = 1; + else if (a - c > .7f * (b-c)) + offset = -1; + else + offset = 0; + } else { + offset = 0; + } + + *pitch = 2 * best_pitch[0] - offset; +} + +static void dct(AudioRNNContext *s, float *out, const float *in) +{ + for (int i = 0; i < NB_BANDS; i++) { + float sum; + + sum = s->fdsp->scalarproduct_float(in, s->dct_table[i], FFALIGN(NB_BANDS, 4)); + out[i] = sum * sqrtf(2.f / 22); + } +} + +static int compute_frame_features(AudioRNNContext *s, DenoiseState *st, AVComplexFloat *X, AVComplexFloat *P, + float *Ex, float *Ep, float *Exp, float *features, const float *in) +{ + float E = 0; + float *ceps_0, *ceps_1, *ceps_2; + float spec_variability = 0; + LOCAL_ALIGNED_32(float, Ly, [NB_BANDS]); + LOCAL_ALIGNED_32(float, p, [WINDOW_SIZE]); + float pitch_buf[PITCH_BUF_SIZE>>1]; + int pitch_index; + float gain; + float *(pre[1]); + float tmp[NB_BANDS]; + float follow, logMax; + + frame_analysis(s, st, X, Ex, in); + RNN_MOVE(st->pitch_buf, &st->pitch_buf[FRAME_SIZE], PITCH_BUF_SIZE-FRAME_SIZE); + RNN_COPY(&st->pitch_buf[PITCH_BUF_SIZE-FRAME_SIZE], in, FRAME_SIZE); + pre[0] = &st->pitch_buf[0]; + pitch_downsample(pre, pitch_buf, PITCH_BUF_SIZE, 1); + pitch_search(pitch_buf+(PITCH_MAX_PERIOD>>1), pitch_buf, PITCH_FRAME_SIZE, + PITCH_MAX_PERIOD-3*PITCH_MIN_PERIOD, &pitch_index); + pitch_index = PITCH_MAX_PERIOD-pitch_index; + + gain = remove_doubling(pitch_buf, PITCH_MAX_PERIOD, PITCH_MIN_PERIOD, + PITCH_FRAME_SIZE, &pitch_index, st->last_period, st->last_gain); + st->last_period = pitch_index; + st->last_gain = gain; + + for (int i = 0; i < WINDOW_SIZE; i++) + p[i] = st->pitch_buf[PITCH_BUF_SIZE-WINDOW_SIZE-pitch_index+i]; + + s->fdsp->vector_fmul(p, p, s->window, WINDOW_SIZE); + forward_transform(st, P, p); + compute_band_energy(Ep, P); + compute_band_corr(Exp, X, P); + + for (int i = 0; i < NB_BANDS; i++) + Exp[i] = Exp[i] / sqrtf(.001f+Ex[i]*Ep[i]); + + dct(s, tmp, Exp); + + for (int i = 0; i < NB_DELTA_CEPS; i++) + features[NB_BANDS+2*NB_DELTA_CEPS+i] = tmp[i]; + + features[NB_BANDS+2*NB_DELTA_CEPS] -= 1.3; + features[NB_BANDS+2*NB_DELTA_CEPS+1] -= 0.9; + features[NB_BANDS+3*NB_DELTA_CEPS] = .01*(pitch_index-300); + logMax = -2; + follow = -2; + + for (int i = 0; i < NB_BANDS; i++) { + Ly[i] = log10f(1e-2f + Ex[i]); + Ly[i] = FFMAX(logMax-7, FFMAX(follow-1.5, Ly[i])); + logMax = FFMAX(logMax, Ly[i]); + follow = FFMAX(follow-1.5, Ly[i]); + E += Ex[i]; + } + + if (E < 0.04f) { + /* If there's no audio, avoid messing up the state. */ + RNN_CLEAR(features, NB_FEATURES); + return 1; + } + + dct(s, features, Ly); + features[0] -= 12; + features[1] -= 4; + ceps_0 = st->cepstral_mem[st->memid]; + ceps_1 = (st->memid < 1) ? st->cepstral_mem[CEPS_MEM+st->memid-1] : st->cepstral_mem[st->memid-1]; + ceps_2 = (st->memid < 2) ? st->cepstral_mem[CEPS_MEM+st->memid-2] : st->cepstral_mem[st->memid-2]; + + for (int i = 0; i < NB_BANDS; i++) + ceps_0[i] = features[i]; + + st->memid++; + for (int i = 0; i < NB_DELTA_CEPS; i++) { + features[i] = ceps_0[i] + ceps_1[i] + ceps_2[i]; + features[NB_BANDS+i] = ceps_0[i] - ceps_2[i]; + features[NB_BANDS+NB_DELTA_CEPS+i] = ceps_0[i] - 2*ceps_1[i] + ceps_2[i]; + } + /* Spectral variability features. */ + if (st->memid == CEPS_MEM) + st->memid = 0; + + for (int i = 0; i < CEPS_MEM; i++) { + float mindist = 1e15f; + for (int j = 0; j < CEPS_MEM; j++) { + float dist = 0.f; + for (int k = 0; k < NB_BANDS; k++) { + float tmp; + + tmp = st->cepstral_mem[i][k] - st->cepstral_mem[j][k]; + dist += tmp*tmp; + } + + if (j != i) + mindist = FFMIN(mindist, dist); + } + + spec_variability += mindist; + } + + features[NB_BANDS+3*NB_DELTA_CEPS+1] = spec_variability/CEPS_MEM-2.1; + + return 0; +} + +static void interp_band_gain(float *g, const float *bandE) +{ + memset(g, 0, sizeof(*g) * FREQ_SIZE); + + for (int i = 0; i < NB_BANDS - 1; i++) { + const int band_size = (eband5ms[i + 1] - eband5ms[i]) << FRAME_SIZE_SHIFT; + + for (int j = 0; j < band_size; j++) { + float frac = (float)j / band_size; + + g[(eband5ms[i] << FRAME_SIZE_SHIFT) + j] = (1.f - frac) * bandE[i] + frac * bandE[i + 1]; + } + } +} + +static void pitch_filter(AVComplexFloat *X, const AVComplexFloat *P, const float *Ex, const float *Ep, + const float *Exp, const float *g) +{ + float newE[NB_BANDS]; + float r[NB_BANDS]; + float norm[NB_BANDS]; + float rf[FREQ_SIZE] = {0}; + float normf[FREQ_SIZE]={0}; + + for (int i = 0; i < NB_BANDS; i++) { + if (Exp[i]>g[i]) r[i] = 1; + else r[i] = SQUARE(Exp[i])*(1-SQUARE(g[i]))/(.001 + SQUARE(g[i])*(1-SQUARE(Exp[i]))); + r[i] = sqrtf(av_clipf(r[i], 0, 1)); + r[i] *= sqrtf(Ex[i]/(1e-8+Ep[i])); + } + interp_band_gain(rf, r); + for (int i = 0; i < FREQ_SIZE; i++) { + X[i].re += rf[i]*P[i].re; + X[i].im += rf[i]*P[i].im; + } + compute_band_energy(newE, X); + for (int i = 0; i < NB_BANDS; i++) { + norm[i] = sqrtf(Ex[i] / (1e-8+newE[i])); + } + interp_band_gain(normf, norm); + for (int i = 0; i < FREQ_SIZE; i++) { + X[i].re *= normf[i]; + X[i].im *= normf[i]; + } +} + +static const float tansig_table[201] = { + 0.000000f, 0.039979f, 0.079830f, 0.119427f, 0.158649f, + 0.197375f, 0.235496f, 0.272905f, 0.309507f, 0.345214f, + 0.379949f, 0.413644f, 0.446244f, 0.477700f, 0.507977f, + 0.537050f, 0.564900f, 0.591519f, 0.616909f, 0.641077f, + 0.664037f, 0.685809f, 0.706419f, 0.725897f, 0.744277f, + 0.761594f, 0.777888f, 0.793199f, 0.807569f, 0.821040f, + 0.833655f, 0.845456f, 0.856485f, 0.866784f, 0.876393f, + 0.885352f, 0.893698f, 0.901468f, 0.908698f, 0.915420f, + 0.921669f, 0.927473f, 0.932862f, 0.937863f, 0.942503f, + 0.946806f, 0.950795f, 0.954492f, 0.957917f, 0.961090f, + 0.964028f, 0.966747f, 0.969265f, 0.971594f, 0.973749f, + 0.975743f, 0.977587f, 0.979293f, 0.980869f, 0.982327f, + 0.983675f, 0.984921f, 0.986072f, 0.987136f, 0.988119f, + 0.989027f, 0.989867f, 0.990642f, 0.991359f, 0.992020f, + 0.992631f, 0.993196f, 0.993718f, 0.994199f, 0.994644f, + 0.995055f, 0.995434f, 0.995784f, 0.996108f, 0.996407f, + 0.996682f, 0.996937f, 0.997172f, 0.997389f, 0.997590f, + 0.997775f, 0.997946f, 0.998104f, 0.998249f, 0.998384f, + 0.998508f, 0.998623f, 0.998728f, 0.998826f, 0.998916f, + 0.999000f, 0.999076f, 0.999147f, 0.999213f, 0.999273f, + 0.999329f, 0.999381f, 0.999428f, 0.999472f, 0.999513f, + 0.999550f, 0.999585f, 0.999617f, 0.999646f, 0.999673f, + 0.999699f, 0.999722f, 0.999743f, 0.999763f, 0.999781f, + 0.999798f, 0.999813f, 0.999828f, 0.999841f, 0.999853f, + 0.999865f, 0.999875f, 0.999885f, 0.999893f, 0.999902f, + 0.999909f, 0.999916f, 0.999923f, 0.999929f, 0.999934f, + 0.999939f, 0.999944f, 0.999948f, 0.999952f, 0.999956f, + 0.999959f, 0.999962f, 0.999965f, 0.999968f, 0.999970f, + 0.999973f, 0.999975f, 0.999977f, 0.999978f, 0.999980f, + 0.999982f, 0.999983f, 0.999984f, 0.999986f, 0.999987f, + 0.999988f, 0.999989f, 0.999990f, 0.999990f, 0.999991f, + 0.999992f, 0.999992f, 0.999993f, 0.999994f, 0.999994f, + 0.999994f, 0.999995f, 0.999995f, 0.999996f, 0.999996f, + 0.999996f, 0.999997f, 0.999997f, 0.999997f, 0.999997f, + 0.999997f, 0.999998f, 0.999998f, 0.999998f, 0.999998f, + 0.999998f, 0.999998f, 0.999999f, 0.999999f, 0.999999f, + 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, + 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, +}; + +static inline float tansig_approx(float x) +{ + float y, dy; + float sign=1; + int i; + + /* Tests are reversed to catch NaNs */ + if (!(x<8)) + return 1; + if (!(x>-8)) + return -1; + /* Another check in case of -ffast-math */ + + if (isnan(x)) + return 0; + + if (x < 0) { + x=-x; + sign=-1; + } + i = (int)floor(.5f+25*x); + x -= .04f*i; + y = tansig_table[i]; + dy = 1-y*y; + y = y + x*dy*(1 - y*x); + return sign*y; +} + +static inline float sigmoid_approx(float x) +{ + return .5f + .5f*tansig_approx(.5f*x); +} + +static void compute_dense(const DenseLayer *layer, float *output, const float *input) +{ + const int N = layer->nb_neurons, M = layer->nb_inputs, stride = N; + + for (int i = 0; i < N; i++) { + /* Compute update gate. */ + float sum = layer->bias[i]; + + for (int j = 0; j < M; j++) + sum += layer->input_weights[j * stride + i] * input[j]; + + output[i] = WEIGHTS_SCALE * sum; + } + + if (layer->activation == ACTIVATION_SIGMOID) { + for (int i = 0; i < N; i++) + output[i] = sigmoid_approx(output[i]); + } else if (layer->activation == ACTIVATION_TANH) { + for (int i = 0; i < N; i++) + output[i] = tansig_approx(output[i]); + } else if (layer->activation == ACTIVATION_RELU) { + for (int i = 0; i < N; i++) + output[i] = FFMAX(0, output[i]); + } else { + av_assert0(0); + } +} + +static void compute_gru(AudioRNNContext *s, const GRULayer *gru, float *state, const float *input) +{ + LOCAL_ALIGNED_32(float, z, [MAX_NEURONS]); + LOCAL_ALIGNED_32(float, r, [MAX_NEURONS]); + LOCAL_ALIGNED_32(float, h, [MAX_NEURONS]); + const int M = gru->nb_inputs; + const int N = gru->nb_neurons; + const int AN = FFALIGN(N, 4); + const int AM = FFALIGN(M, 4); + const int stride = 3 * AN, istride = 3 * AM; + + for (int i = 0; i < N; i++) { + /* Compute update gate. */ + float sum = gru->bias[i]; + + sum += s->fdsp->scalarproduct_float(gru->input_weights + i * istride, input, AM); + sum += s->fdsp->scalarproduct_float(gru->recurrent_weights + i * stride, state, AN); + z[i] = sigmoid_approx(WEIGHTS_SCALE * sum); + } + + for (int i = 0; i < N; i++) { + /* Compute reset gate. */ + float sum = gru->bias[N + i]; + + sum += s->fdsp->scalarproduct_float(gru->input_weights + AM + i * istride, input, AM); + sum += s->fdsp->scalarproduct_float(gru->recurrent_weights + AN + i * stride, state, AN); + r[i] = sigmoid_approx(WEIGHTS_SCALE * sum); + } + + for (int i = 0; i < N; i++) { + /* Compute output. */ + float sum = gru->bias[2 * N + i]; + + sum += s->fdsp->scalarproduct_float(gru->input_weights + 2 * AM + i * istride, input, AM); + for (int j = 0; j < N; j++) + sum += gru->recurrent_weights[2 * AN + i * stride + j] * state[j] * r[j]; + + if (gru->activation == ACTIVATION_SIGMOID) + sum = sigmoid_approx(WEIGHTS_SCALE * sum); + else if (gru->activation == ACTIVATION_TANH) + sum = tansig_approx(WEIGHTS_SCALE * sum); + else if (gru->activation == ACTIVATION_RELU) + sum = FFMAX(0, WEIGHTS_SCALE * sum); + else + av_assert0(0); + h[i] = z[i] * state[i] + (1.f - z[i]) * sum; + } + + RNN_COPY(state, h, N); +} + +#define INPUT_SIZE 42 + +static void compute_rnn(AudioRNNContext *s, RNNState *rnn, float *gains, float *vad, const float *input) +{ + LOCAL_ALIGNED_32(float, dense_out, [MAX_NEURONS]); + LOCAL_ALIGNED_32(float, noise_input, [MAX_NEURONS * 3]); + LOCAL_ALIGNED_32(float, denoise_input, [MAX_NEURONS * 3]); + + compute_dense(rnn->model->input_dense, dense_out, input); + compute_gru(s, rnn->model->vad_gru, rnn->vad_gru_state, dense_out); + compute_dense(rnn->model->vad_output, vad, rnn->vad_gru_state); + + memcpy(noise_input, dense_out, rnn->model->input_dense_size * sizeof(float)); + memcpy(noise_input + rnn->model->input_dense_size, + rnn->vad_gru_state, rnn->model->vad_gru_size * sizeof(float)); + memcpy(noise_input + rnn->model->input_dense_size + rnn->model->vad_gru_size, + input, INPUT_SIZE * sizeof(float)); + + compute_gru(s, rnn->model->noise_gru, rnn->noise_gru_state, noise_input); + + memcpy(denoise_input, rnn->vad_gru_state, rnn->model->vad_gru_size * sizeof(float)); + memcpy(denoise_input + rnn->model->vad_gru_size, + rnn->noise_gru_state, rnn->model->noise_gru_size * sizeof(float)); + memcpy(denoise_input + rnn->model->vad_gru_size + rnn->model->noise_gru_size, + input, INPUT_SIZE * sizeof(float)); + + compute_gru(s, rnn->model->denoise_gru, rnn->denoise_gru_state, denoise_input); + compute_dense(rnn->model->denoise_output, gains, rnn->denoise_gru_state); +} + +static float rnnoise_channel(AudioRNNContext *s, DenoiseState *st, float *out, const float *in, + int disabled) +{ + AVComplexFloat X[FREQ_SIZE]; + AVComplexFloat P[WINDOW_SIZE]; + float x[FRAME_SIZE]; + float Ex[NB_BANDS], Ep[NB_BANDS]; + LOCAL_ALIGNED_32(float, Exp, [NB_BANDS]); + float features[NB_FEATURES]; + float g[NB_BANDS]; + float gf[FREQ_SIZE]; + float vad_prob = 0; + float *history = st->history; + static const float a_hp[2] = {-1.99599, 0.99600}; + static const float b_hp[2] = {-2, 1}; + int silence; + + biquad(x, st->mem_hp_x, in, b_hp, a_hp, FRAME_SIZE); + silence = compute_frame_features(s, st, X, P, Ex, Ep, Exp, features, x); + + if (!silence && !disabled) { + compute_rnn(s, &st->rnn[0], g, &vad_prob, features); + pitch_filter(X, P, Ex, Ep, Exp, g); + for (int i = 0; i < NB_BANDS; i++) { + float alpha = .6f; + + g[i] = FFMAX(g[i], alpha * st->lastg[i]); + st->lastg[i] = g[i]; + } + + interp_band_gain(gf, g); + + for (int i = 0; i < FREQ_SIZE; i++) { + X[i].re *= gf[i]; + X[i].im *= gf[i]; + } + } + + frame_synthesis(s, st, out, X); + memcpy(history, in, FRAME_SIZE * sizeof(*history)); + + return vad_prob; +} + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int rnnoise_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AudioRNNContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + const int start = (out->channels * jobnr) / nb_jobs; + const int end = (out->channels * (jobnr+1)) / nb_jobs; + + for (int ch = start; ch < end; ch++) { + rnnoise_channel(s, &s->st[ch], + (float *)out->extended_data[ch], + (const float *)in->extended_data[ch], + ctx->is_disabled); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out = NULL; + ThreadData td; + + out = ff_get_audio_buffer(outlink, FRAME_SIZE); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + out->pts = in->pts; + + td.in = in; td.out = out; + ctx->internal->execute(ctx, rnnoise_channels, &td, NULL, FFMIN(outlink->channels, + ff_filter_get_nb_threads(ctx))); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *in = NULL; + int ret; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + ret = ff_inlink_consume_samples(inlink, FRAME_SIZE, FRAME_SIZE, &in); + if (ret < 0) + return ret; + + if (ret > 0) + return filter_frame(inlink, in); + + FF_FILTER_FORWARD_STATUS(inlink, outlink); + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; +} + +static int open_model(AVFilterContext *ctx, RNNModel **model) +{ + AudioRNNContext *s = ctx->priv; + int ret; + FILE *f; + + if (!s->model_name) + return AVERROR(EINVAL); + f = av_fopen_utf8(s->model_name, "r"); + if (!f) { + av_log(ctx, AV_LOG_ERROR, "Failed to open model file: %s\n", s->model_name); + return AVERROR(EINVAL); + } + + ret = rnnoise_model_from_file(f, model); + fclose(f); + if (!*model || ret < 0) + return ret; + + return 0; +} + +static av_cold int init(AVFilterContext *ctx) +{ + AudioRNNContext *s = ctx->priv; + int ret; + + s->fdsp = avpriv_float_dsp_alloc(0); + if (!s->fdsp) + return AVERROR(ENOMEM); + + ret = open_model(ctx, &s->model[0]); + if (ret < 0) + return ret; + + for (int i = 0; i < FRAME_SIZE; i++) { + s->window[i] = sin(.5*M_PI*sin(.5*M_PI*(i+.5)/FRAME_SIZE) * sin(.5*M_PI*(i+.5)/FRAME_SIZE)); + s->window[WINDOW_SIZE - 1 - i] = s->window[i]; + } + + for (int i = 0; i < NB_BANDS; i++) { + for (int j = 0; j < NB_BANDS; j++) { + s->dct_table[j][i] = cosf((i + .5f) * j * M_PI / NB_BANDS); + if (j == 0) + s->dct_table[j][i] *= sqrtf(.5); + } + } + + return 0; +} + +static void free_model(AVFilterContext *ctx, int n) +{ + AudioRNNContext *s = ctx->priv; + + rnnoise_model_free(s->model[n]); + s->model[n] = NULL; + + for (int ch = 0; ch < s->channels && s->st; ch++) { + av_freep(&s->st[ch].rnn[n].vad_gru_state); + av_freep(&s->st[ch].rnn[n].noise_gru_state); + av_freep(&s->st[ch].rnn[n].denoise_gru_state); + } +} + +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + AudioRNNContext *s = ctx->priv; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + ret = open_model(ctx, &s->model[1]); + if (ret < 0) + return ret; + + FFSWAP(RNNModel *, s->model[0], s->model[1]); + for (int ch = 0; ch < s->channels; ch++) + FFSWAP(RNNState, s->st[ch].rnn[0], s->st[ch].rnn[1]); + + ret = config_input(ctx->inputs[0]); + if (ret < 0) { + for (int ch = 0; ch < s->channels; ch++) + FFSWAP(RNNState, s->st[ch].rnn[0], s->st[ch].rnn[1]); + FFSWAP(RNNModel *, s->model[0], s->model[1]); + return ret; + } + + free_model(ctx, 1); + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioRNNContext *s = ctx->priv; + + av_freep(&s->fdsp); + free_model(ctx, 0); + for (int ch = 0; ch < s->channels && s->st; ch++) { + av_tx_uninit(&s->st[ch].tx); + av_tx_uninit(&s->st[ch].txi); + } + av_freep(&s->st); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(AudioRNNContext, x) +#define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption arnndn_options[] = { + { "model", "set model name", OFFSET(model_name), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, AF }, + { "m", "set model name", OFFSET(model_name), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, AF }, + { "mix", "set output vs input mix", OFFSET(mix), AV_OPT_TYPE_FLOAT, {.dbl=1.0},-1, 1, AF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(arnndn); + +AVFilter ff_af_arnndn = { + .name = "arnndn", + .description = NULL_IF_CONFIG_SMALL("Reduce noise from speech using Recurrent Neural Networks."), + .query_formats = query_formats, + .priv_size = sizeof(AudioRNNContext), + .priv_class = &arnndn_class, + .activate = activate, + .init = init, + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/af_asetrate.c ffmpeg-4.4/libavfilter/af_asetrate.c --- ffmpeg-4.2.2/libavfilter/af_asetrate.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_asetrate.c 2021-04-08 21:28:39.000000000 +0000 @@ -52,7 +52,7 @@ int sample_rates[] = { sr->sample_rate, -1 }; return ff_formats_ref(ff_make_format_list(sample_rates), - &ctx->outputs[0]->in_samplerates); + &ctx->outputs[0]->incfg.samplerates); } static av_cold int config_props(AVFilterLink *outlink) diff -Nru ffmpeg-4.2.2/libavfilter/af_asoftclip.c ffmpeg-4.4/libavfilter/af_asoftclip.c --- ffmpeg-4.2.2/libavfilter/af_asoftclip.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_asoftclip.c 2021-04-08 21:28:39.000000000 +0000 @@ -18,13 +18,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "libavutil/opt.h" +#include "libswresample/swresample.h" #include "avfilter.h" #include "audio.h" #include "formats.h" enum ASoftClipTypes { + ASC_HARD = -1, ASC_TANH, ASC_ATAN, ASC_CUBIC, @@ -32,6 +35,7 @@ ASC_ALG, ASC_QUINTIC, ASC_SIN, + ASC_ERF, NB_TYPES, }; @@ -39,17 +43,28 @@ const AVClass *class; int type; + int oversample; + int64_t delay; + double threshold; + double output; double param; + SwrContext *up_ctx; + SwrContext *down_ctx; + + AVFrame *frame; + void (*filter)(struct ASoftClipContext *s, void **dst, const void **src, - int nb_samples, int channels); + int nb_samples, int channels, int start, int end); } ASoftClipContext; #define OFFSET(x) offsetof(ASoftClipContext, x) -#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM +#define F AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption asoftclip_options[] = { - { "type", "set softclip type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TYPES-1, A, "types" }, + { "type", "set softclip type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, -1, NB_TYPES-1, A, "types" }, + { "hard", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ASC_HARD}, 0, 0, A, "types" }, { "tanh", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ASC_TANH}, 0, 0, A, "types" }, { "atan", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ASC_ATAN}, 0, 0, A, "types" }, { "cubic", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ASC_CUBIC}, 0, 0, A, "types" }, @@ -57,7 +72,11 @@ { "alg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ASC_ALG}, 0, 0, A, "types" }, { "quintic", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ASC_QUINTIC},0, 0, A, "types" }, { "sin", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ASC_SIN}, 0, 0, A, "types" }, + { "erf", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ASC_ERF}, 0, 0, A, "types" }, + { "threshold", "set softclip threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.000001, 1, A }, + { "output", "set softclip output gain", OFFSET(output), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.000001, 16, A }, { "param", "set softclip parameter", OFFSET(param), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.01, 3, A }, + { "oversample", "set oversample factor", OFFSET(oversample), AV_OPT_TYPE_INT, {.i64=1}, 1, 32, F }, { NULL } }; @@ -93,116 +112,186 @@ return ff_set_common_samplerates(ctx, formats); } -#define SQR(x) ((x) * (x)) - static void filter_flt(ASoftClipContext *s, void **dptr, const void **sptr, - int nb_samples, int channels) + int nb_samples, int channels, + int start, int end) { + float threshold = s->threshold; + float gain = s->output * threshold; + float factor = 1.f / threshold; float param = s->param; - for (int c = 0; c < channels; c++) { + for (int c = start; c < end; c++) { const float *src = sptr[c]; float *dst = dptr[c]; switch (s->type) { + case ASC_HARD: + for (int n = 0; n < nb_samples; n++) { + dst[n] = av_clipf(src[n] * factor, -1.f, 1.f); + dst[n] *= gain; + } + break; case ASC_TANH: for (int n = 0; n < nb_samples; n++) { - dst[n] = tanhf(src[n] * param); + dst[n] = tanhf(src[n] * factor * param); + dst[n] *= gain; } break; case ASC_ATAN: - for (int n = 0; n < nb_samples; n++) - dst[n] = 2.f / M_PI * atanf(src[n] * param); + for (int n = 0; n < nb_samples; n++) { + dst[n] = 2.f / M_PI * atanf(src[n] * factor * param); + dst[n] *= gain; + } break; case ASC_CUBIC: for (int n = 0; n < nb_samples; n++) { - if (FFABS(src[n]) >= 1.5f) - dst[n] = FFSIGN(src[n]); + float sample = src[n] * factor; + + if (FFABS(sample) >= 1.5f) + dst[n] = FFSIGN(sample); else - dst[n] = src[n] - 0.1481f * powf(src[n], 3.f); + dst[n] = sample - 0.1481f * powf(sample, 3.f); + dst[n] *= gain; } break; case ASC_EXP: - for (int n = 0; n < nb_samples; n++) - dst[n] = 2.f / (1.f + expf(-2.f * src[n])) - 1.; + for (int n = 0; n < nb_samples; n++) { + dst[n] = 2.f / (1.f + expf(-2.f * src[n] * factor)) - 1.; + dst[n] *= gain; + } break; case ASC_ALG: - for (int n = 0; n < nb_samples; n++) - dst[n] = src[n] / (sqrtf(param + src[n] * src[n])); + for (int n = 0; n < nb_samples; n++) { + float sample = src[n] * factor; + + dst[n] = sample / (sqrtf(param + sample * sample)); + dst[n] *= gain; + } break; case ASC_QUINTIC: for (int n = 0; n < nb_samples; n++) { - if (FFABS(src[n]) >= 1.25) - dst[n] = FFSIGN(src[n]); + float sample = src[n] * factor; + + if (FFABS(sample) >= 1.25) + dst[n] = FFSIGN(sample); else - dst[n] = src[n] - 0.08192f * powf(src[n], 5.f); + dst[n] = sample - 0.08192f * powf(sample, 5.f); + dst[n] *= gain; } break; case ASC_SIN: for (int n = 0; n < nb_samples; n++) { - if (FFABS(src[n]) >= M_PI_2) - dst[n] = FFSIGN(src[n]); + float sample = src[n] * factor; + + if (FFABS(sample) >= M_PI_2) + dst[n] = FFSIGN(sample); else - dst[n] = sinf(src[n]); + dst[n] = sinf(sample); + dst[n] *= gain; } break; + case ASC_ERF: + for (int n = 0; n < nb_samples; n++) { + dst[n] = erff(src[n] * factor); + dst[n] *= gain; + } + break; + default: + av_assert0(0); } } } static void filter_dbl(ASoftClipContext *s, void **dptr, const void **sptr, - int nb_samples, int channels) + int nb_samples, int channels, + int start, int end) { + double threshold = s->threshold; + double gain = s->output * threshold; + double factor = 1. / threshold; double param = s->param; - for (int c = 0; c < channels; c++) { + for (int c = start; c < end; c++) { const double *src = sptr[c]; double *dst = dptr[c]; switch (s->type) { + case ASC_HARD: + for (int n = 0; n < nb_samples; n++) { + dst[n] = av_clipd(src[n] * factor, -1., 1.); + dst[n] *= gain; + } + break; case ASC_TANH: for (int n = 0; n < nb_samples; n++) { - dst[n] = tanh(src[n] * param); + dst[n] = tanh(src[n] * factor * param); + dst[n] *= gain; } break; case ASC_ATAN: - for (int n = 0; n < nb_samples; n++) - dst[n] = 2. / M_PI * atan(src[n] * param); + for (int n = 0; n < nb_samples; n++) { + dst[n] = 2. / M_PI * atan(src[n] * factor * param); + dst[n] *= gain; + } break; case ASC_CUBIC: for (int n = 0; n < nb_samples; n++) { - if (FFABS(src[n]) >= 1.5) - dst[n] = FFSIGN(src[n]); + double sample = src[n] * factor; + + if (FFABS(sample) >= 1.5) + dst[n] = FFSIGN(sample); else - dst[n] = src[n] - 0.1481 * pow(src[n], 3.); + dst[n] = sample - 0.1481 * pow(sample, 3.); + dst[n] *= gain; } break; case ASC_EXP: - for (int n = 0; n < nb_samples; n++) - dst[n] = 2. / (1. + exp(-2. * src[n])) - 1.; + for (int n = 0; n < nb_samples; n++) { + dst[n] = 2. / (1. + exp(-2. * src[n] * factor)) - 1.; + dst[n] *= gain; + } break; case ASC_ALG: - for (int n = 0; n < nb_samples; n++) - dst[n] = src[n] / (sqrt(param + src[n] * src[n])); + for (int n = 0; n < nb_samples; n++) { + double sample = src[n] * factor; + + dst[n] = sample / (sqrt(param + sample * sample)); + dst[n] *= gain; + } break; case ASC_QUINTIC: for (int n = 0; n < nb_samples; n++) { - if (FFABS(src[n]) >= 1.25) - dst[n] = FFSIGN(src[n]); + double sample = src[n] * factor; + + if (FFABS(sample) >= 1.25) + dst[n] = FFSIGN(sample); else - dst[n] = src[n] - 0.08192 * pow(src[n], 5.); + dst[n] = sample - 0.08192 * pow(sample, 5.); + dst[n] *= gain; } break; case ASC_SIN: for (int n = 0; n < nb_samples; n++) { - if (FFABS(src[n]) >= M_PI_2) - dst[n] = FFSIGN(src[n]); + double sample = src[n] * factor; + + if (FFABS(sample) >= M_PI_2) + dst[n] = FFSIGN(sample); else - dst[n] = sin(src[n]); + dst[n] = sin(sample); + dst[n] *= gain; + } + break; + case ASC_ERF: + for (int n = 0; n < nb_samples; n++) { + dst[n] = erf(src[n] * factor); + dst[n] *= gain; } break; + default: + av_assert0(0); } } } @@ -211,23 +300,81 @@ { AVFilterContext *ctx = inlink->dst; ASoftClipContext *s = ctx->priv; + int ret; switch (inlink->format) { case AV_SAMPLE_FMT_FLT: case AV_SAMPLE_FMT_FLTP: s->filter = filter_flt; break; case AV_SAMPLE_FMT_DBL: case AV_SAMPLE_FMT_DBLP: s->filter = filter_dbl; break; + default: av_assert0(0); } + if (s->oversample <= 1) + return 0; + + s->up_ctx = swr_alloc(); + s->down_ctx = swr_alloc(); + if (!s->up_ctx || !s->down_ctx) + return AVERROR(ENOMEM); + + av_opt_set_int(s->up_ctx, "in_channel_layout", inlink->channel_layout, 0); + av_opt_set_int(s->up_ctx, "in_sample_rate", inlink->sample_rate, 0); + av_opt_set_sample_fmt(s->up_ctx, "in_sample_fmt", inlink->format, 0); + + av_opt_set_int(s->up_ctx, "out_channel_layout", inlink->channel_layout, 0); + av_opt_set_int(s->up_ctx, "out_sample_rate", inlink->sample_rate * s->oversample, 0); + av_opt_set_sample_fmt(s->up_ctx, "out_sample_fmt", inlink->format, 0); + + av_opt_set_int(s->down_ctx, "in_channel_layout", inlink->channel_layout, 0); + av_opt_set_int(s->down_ctx, "in_sample_rate", inlink->sample_rate * s->oversample, 0); + av_opt_set_sample_fmt(s->down_ctx, "in_sample_fmt", inlink->format, 0); + + av_opt_set_int(s->down_ctx, "out_channel_layout", inlink->channel_layout, 0); + av_opt_set_int(s->down_ctx, "out_sample_rate", inlink->sample_rate, 0); + av_opt_set_sample_fmt(s->down_ctx, "out_sample_fmt", inlink->format, 0); + + ret = swr_init(s->up_ctx); + if (ret < 0) + return ret; + + ret = swr_init(s->down_ctx); + if (ret < 0) + return ret; + + return 0; +} + +typedef struct ThreadData { + AVFrame *in, *out; + int nb_samples; + int channels; +} ThreadData; + +static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ASoftClipContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + const int channels = td->channels; + const int nb_samples = td->nb_samples; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; + + s->filter(s, (void **)out->extended_data, (const void **)in->extended_data, + nb_samples, channels, start, end); + return 0; } static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; - AVFilterLink *outlink = ctx->outputs[0]; ASoftClipContext *s = ctx->priv; - int nb_samples, channels; + AVFilterLink *outlink = ctx->outputs[0]; + int ret, nb_samples, channels; + ThreadData td; AVFrame *out; if (av_frame_is_writable(in)) { @@ -249,13 +396,64 @@ channels = 1; } - s->filter(s, (void **)out->extended_data, (const void **)in->extended_data, - nb_samples, channels); + if (s->oversample > 1) { + s->frame = ff_get_audio_buffer(outlink, in->nb_samples * s->oversample); + if (!s->frame) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = swr_convert(s->up_ctx, (uint8_t**)s->frame->extended_data, in->nb_samples * s->oversample, + (const uint8_t **)in->extended_data, in->nb_samples); + if (ret < 0) + goto fail; + + td.in = s->frame; + td.out = s->frame; + td.nb_samples = av_sample_fmt_is_planar(in->format) ? ret : ret * in->channels; + td.channels = channels; + ctx->internal->execute(ctx, filter_channels, &td, NULL, FFMIN(channels, + ff_filter_get_nb_threads(ctx))); + + ret = swr_convert(s->down_ctx, (uint8_t**)out->extended_data, out->nb_samples, + (const uint8_t **)s->frame->extended_data, ret); + if (ret < 0) + goto fail; + + if (out->pts) + out->pts -= s->delay; + s->delay += in->nb_samples - ret; + out->nb_samples = ret; + + av_frame_free(&s->frame); + } else { + td.in = in; + td.out = out; + td.nb_samples = nb_samples; + td.channels = channels; + ctx->internal->execute(ctx, filter_channels, &td, NULL, FFMIN(channels, + ff_filter_get_nb_threads(ctx))); + } if (out != in) av_frame_free(&in); return ff_filter_frame(outlink, out); +fail: + if (out != in) + av_frame_free(&out); + av_frame_free(&in); + av_frame_free(&s->frame); + + return ret; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + ASoftClipContext *s = ctx->priv; + + swr_free(&s->up_ctx); + swr_free(&s->down_ctx); } static const AVFilterPad inputs[] = { @@ -284,5 +482,8 @@ .priv_class = &asoftclip_class, .inputs = inputs, .outputs = outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .uninit = uninit, + .process_command = ff_filter_process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_astats.c ffmpeg-4.4/libavfilter/af_astats.c --- ffmpeg-4.2.2/libavfilter/af_astats.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_astats.c 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,9 @@ #include "avfilter.h" #include "internal.h" +#define HISTOGRAM_SIZE 8192 +#define HISTOGRAM_MAX (HISTOGRAM_SIZE-1) + #define MEASURE_ALL UINT_MAX #define MEASURE_NONE 0 @@ -52,6 +55,8 @@ #define MEASURE_NUMBER_OF_NANS (1 << 19) #define MEASURE_NUMBER_OF_INFS (1 << 20) #define MEASURE_NUMBER_OF_DENORMALS (1 << 21) +#define MEASURE_NOISE_FLOOR (1 << 22) +#define MEASURE_NOISE_FLOOR_COUNT (1 << 23) #define MEASURE_MINMAXPEAK (MEASURE_MIN_LEVEL | MEASURE_MAX_LEVEL | MEASURE_PEAK_LEVEL) @@ -70,11 +75,17 @@ double diff1_sum_x2; uint64_t mask, imask; uint64_t min_count, max_count; + uint64_t noise_floor_count; uint64_t zero_runs; uint64_t nb_samples; uint64_t nb_nans; uint64_t nb_infs; uint64_t nb_denormals; + double *win_samples; + unsigned histogram[HISTOGRAM_SIZE]; + int win_pos; + int max_index; + double noise_floor; } ChannelStats; typedef struct AudioStatsContext { @@ -122,6 +133,8 @@ { "Dynamic_range" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_DYNAMIC_RANGE }, 0, 0, FLAGS, "measure" }, { "Zero_crossings" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_ZERO_CROSSINGS }, 0, 0, FLAGS, "measure" }, { "Zero_crossings_rate" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_ZERO_CROSSINGS_RATE }, 0, 0, FLAGS, "measure" }, + { "Noise_floor" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NOISE_FLOOR }, 0, 0, FLAGS, "measure" }, + { "Noise_floor_count" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NOISE_FLOOR_COUNT }, 0, 0, FLAGS, "measure" }, { "Number_of_samples" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NUMBER_OF_SAMPLES }, 0, 0, FLAGS, "measure" }, { "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" }, @@ -197,6 +210,11 @@ p->nb_infs = 0; p->nb_denormals = 0; p->last = NAN; + p->noise_floor = NAN; + p->noise_floor_count = 0; + p->win_pos = 0; + memset(p->win_samples, 0, s->tc_samples * sizeof(*p->win_samples)); + memset(p->histogram, 0, sizeof(p->histogram)); } } @@ -207,9 +225,19 @@ s->chstats = av_calloc(sizeof(*s->chstats), outlink->channels); if (!s->chstats) return AVERROR(ENOMEM); + + s->tc_samples = 5 * s->time_constant * outlink->sample_rate + .5; s->nb_channels = outlink->channels; + + for (int i = 0; i < s->nb_channels; i++) { + ChannelStats *p = &s->chstats[i]; + + p->win_samples = av_calloc(s->tc_samples, sizeof(*p->win_samples)); + if (!p->win_samples) + return AVERROR(ENOMEM); + } + s->mult = exp((-1 / s->time_constant / outlink->sample_rate)); - s->tc_samples = 5 * s->time_constant * outlink->sample_rate + .5; s->nb_frames = 0; s->maxbitdepth = av_get_bytes_per_sample(outlink->format) * 8; s->is_double = outlink->format == AV_SAMPLE_FMT_DBL || @@ -249,6 +277,9 @@ static inline void update_stat(AudioStatsContext *s, ChannelStats *p, double d, double nd, int64_t i) { + double drop; + int index; + if (d < p->min) { p->min = d; p->nmin = nd; @@ -296,6 +327,44 @@ p->mask |= i; p->imask &= i; + drop = p->win_samples[p->win_pos]; + p->win_samples[p->win_pos] = nd; + index = av_clip(lrint(av_clipd(FFABS(nd), 0.0, 1.0) * HISTOGRAM_MAX), 0, HISTOGRAM_MAX); + p->max_index = FFMAX(p->max_index, index); + p->histogram[index]++; + if (!isnan(p->noise_floor)) + p->histogram[av_clip(lrint(av_clipd(FFABS(drop), 0.0, 1.0) * HISTOGRAM_MAX), 0, HISTOGRAM_MAX)]--; + p->win_pos++; + + while (p->histogram[p->max_index] == 0) + p->max_index--; + if (p->win_pos >= s->tc_samples || !isnan(p->noise_floor)) { + double noise_floor = 1.; + + for (int i = p->max_index; i >= 0; i--) { + if (p->histogram[i]) { + noise_floor = i / (double)HISTOGRAM_MAX; + break; + } + } + + if (isnan(p->noise_floor)) { + p->noise_floor = noise_floor; + p->noise_floor_count = 1; + } else { + if (noise_floor < p->noise_floor) { + p->noise_floor = noise_floor; + p->noise_floor_count = 1; + } else if (noise_floor == p->noise_floor) { + p->noise_floor_count++; + } + } + } + + if (p->win_pos >= s->tc_samples) { + p->win_pos = 0; + } + if (p->nb_samples >= s->tc_samples) { p->max_sigma_x2 = FFMAX(p->max_sigma_x2, p->avg_sigma_x2); p->min_sigma_x2 = FFMIN(p->min_sigma_x2, p->avg_sigma_x2); @@ -339,7 +408,7 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata) { - uint64_t mask = 0, imask = 0xFFFFFFFFFFFFFFFF, min_count = 0, max_count = 0, nb_samples = 0; + uint64_t mask = 0, imask = 0xFFFFFFFFFFFFFFFF, min_count = 0, max_count = 0, nb_samples = 0, noise_floor_count = 0; uint64_t nb_nans = 0, nb_infs = 0, nb_denormals = 0; double min_runs = 0, max_runs = 0, min = DBL_MAX, max =-DBL_MAX, min_diff = DBL_MAX, max_diff = 0, @@ -349,6 +418,7 @@ diff1_sum_x2 = 0, sigma_x = 0, sigma_x2 = 0, + noise_floor = 0, min_sigma_x2 = DBL_MAX, max_sigma_x2 =-DBL_MAX; AVRational depth; @@ -372,6 +442,8 @@ 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; min_count += p->min_count; max_count += p->max_count; min_runs += p->min_runs; @@ -413,6 +485,10 @@ set_meta(metadata, c + 1, "Flat_factor", "%f", LINEAR_TO_DB((p->min_runs + p->max_runs) / (p->min_count + p->max_count))); if (s->measure_perchannel & MEASURE_PEAK_COUNT) set_meta(metadata, c + 1, "Peak_count", "%f", (float)(p->min_count + p->max_count)); + if (s->measure_perchannel & MEASURE_NOISE_FLOOR) + set_meta(metadata, c + 1, "Noise_floor", "%f", LINEAR_TO_DB(p->noise_floor)); + if (s->measure_perchannel & MEASURE_NOISE_FLOOR_COUNT) + set_meta(metadata, c + 1, "Noise_floor_count", "%f", p->noise_floor_count); if (s->measure_perchannel & MEASURE_BIT_DEPTH) { bit_depth(s, p->mask, p->imask, &depth); set_meta(metadata, c + 1, "Bit_depth", "%f", depth.num); @@ -458,6 +534,10 @@ set_meta(metadata, 0, "Overall.Flat_factor", "%f", LINEAR_TO_DB((min_runs + max_runs) / (min_count + max_count))); if (s->measure_overall & MEASURE_PEAK_COUNT) set_meta(metadata, 0, "Overall.Peak_count", "%f", (float)(min_count + max_count) / (double)s->nb_channels); + if (s->measure_overall & MEASURE_NOISE_FLOOR) + set_meta(metadata, 0, "Overall.Noise_floor", "%f", LINEAR_TO_DB(noise_floor)); + if (s->measure_overall & MEASURE_NOISE_FLOOR_COUNT) + set_meta(metadata, 0, "Overall.Noise_floor_count", "%f", noise_floor_count / (double)s->nb_channels); if (s->measure_overall & MEASURE_BIT_DEPTH) { bit_depth(s, mask, imask, &depth); set_meta(metadata, 0, "Overall.Bit_depth", "%f", depth.num); @@ -474,7 +554,7 @@ } #define UPDATE_STATS_P(type, update_func, update_float, channel_func) \ - for (int c = 0; c < channels; c++) { \ + for (int c = start; c < end; c++) { \ ChannelStats *p = &s->chstats[c]; \ const type *src = (const type *)data[c]; \ const type * const srcend = src + samples; \ @@ -486,7 +566,7 @@ } #define UPDATE_STATS_I(type, update_func, update_float, channel_func) \ - for (int c = 0; c < channels; c++) { \ + for (int c = start; c < end; c++) { \ ChannelStats *p = &s->chstats[c]; \ const type *src = (const type *)data[0]; \ const type * const srcend = src + samples * channels; \ @@ -504,21 +584,16 @@ UPDATE_STATS_##planar(type, update_minmax(s, p, sample), , p->nmin = p->min normalizer_suffix; p->nmax = p->max normalizer_suffix;); \ } -static int filter_frame(AVFilterLink *inlink, AVFrame *buf) +static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - AudioStatsContext *s = inlink->dst->priv; - AVDictionary **metadata = &buf->metadata; + AudioStatsContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + AVFrame *buf = arg; + const uint8_t * const * const data = (const uint8_t * const *)buf->extended_data; const int channels = s->nb_channels; const int samples = buf->nb_samples; - const uint8_t * const * const data = (const uint8_t * const *)buf->extended_data; - - if (s->reset_count > 0) { - if (s->nb_frames >= s->reset_count) { - reset_stats(s); - s->nb_frames = 0; - } - s->nb_frames++; - } + const int start = (buf->channels * jobnr) / nb_jobs; + const int end = (buf->channels * (jobnr+1)) / nb_jobs; switch (inlink->format) { case AV_SAMPLE_FMT_DBLP: @@ -553,6 +628,25 @@ break; } + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *buf) +{ + AVFilterContext *ctx = inlink->dst; + AudioStatsContext *s = ctx->priv; + AVDictionary **metadata = &buf->metadata; + + if (s->reset_count > 0) { + if (s->nb_frames >= s->reset_count) { + reset_stats(s); + s->nb_frames = 0; + } + s->nb_frames++; + } + + ctx->internal->execute(ctx, filter_channel, buf, NULL, FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + if (s->metadata) set_metadata(s, metadata); @@ -562,7 +656,7 @@ static void print_stats(AVFilterContext *ctx) { AudioStatsContext *s = ctx->priv; - uint64_t mask = 0, imask = 0xFFFFFFFFFFFFFFFF, min_count = 0, max_count = 0, nb_samples = 0; + uint64_t mask = 0, imask = 0xFFFFFFFFFFFFFFFF, min_count = 0, max_count = 0, nb_samples = 0, noise_floor_count = 0; uint64_t nb_nans = 0, nb_infs = 0, nb_denormals = 0; double min_runs = 0, max_runs = 0, min = DBL_MAX, max =-DBL_MAX, min_diff = DBL_MAX, max_diff = 0, @@ -572,6 +666,7 @@ diff1_sum = 0, sigma_x = 0, sigma_x2 = 0, + noise_floor = 0, min_sigma_x2 = DBL_MAX, max_sigma_x2 =-DBL_MAX; AVRational depth; @@ -595,8 +690,10 @@ 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); min_count += p->min_count; max_count += p->max_count; + noise_floor_count += p->noise_floor_count; min_runs += p->min_runs; max_runs += p->max_runs; mask |= p->mask; @@ -638,6 +735,10 @@ av_log(ctx, AV_LOG_INFO, "Flat factor: %f\n", LINEAR_TO_DB((p->min_runs + p->max_runs) / (p->min_count + p->max_count))); if (s->measure_perchannel & MEASURE_PEAK_COUNT) av_log(ctx, AV_LOG_INFO, "Peak count: %"PRId64"\n", p->min_count + p->max_count); + if (s->measure_perchannel & MEASURE_NOISE_FLOOR) + av_log(ctx, AV_LOG_INFO, "Noise floor dB: %f\n", LINEAR_TO_DB(p->noise_floor)); + if (s->measure_perchannel & MEASURE_NOISE_FLOOR_COUNT) + av_log(ctx, AV_LOG_INFO, "Noise floor count: %"PRId64"\n", p->noise_floor_count); if (s->measure_perchannel & MEASURE_BIT_DEPTH) { bit_depth(s, p->mask, p->imask, &depth); av_log(ctx, AV_LOG_INFO, "Bit depth: %u/%u\n", depth.num, depth.den); @@ -684,6 +785,10 @@ av_log(ctx, AV_LOG_INFO, "Flat factor: %f\n", LINEAR_TO_DB((min_runs + max_runs) / (min_count + max_count))); if (s->measure_overall & MEASURE_PEAK_COUNT) av_log(ctx, AV_LOG_INFO, "Peak count: %f\n", (min_count + max_count) / (double)s->nb_channels); + if (s->measure_overall & MEASURE_NOISE_FLOOR) + av_log(ctx, AV_LOG_INFO, "Noise floor dB: %f\n", LINEAR_TO_DB(noise_floor)); + if (s->measure_overall & MEASURE_NOISE_FLOOR_COUNT) + av_log(ctx, AV_LOG_INFO, "Noise floor count: %f\n", noise_floor_count / (double)s->nb_channels); if (s->measure_overall & MEASURE_BIT_DEPTH) { bit_depth(s, mask, imask, &depth); av_log(ctx, AV_LOG_INFO, "Bit depth: %u/%u\n", depth.num, depth.den); @@ -704,6 +809,13 @@ if (s->nb_channels) print_stats(ctx); + if (s->chstats) { + for (int i = 0; i < s->nb_channels; i++) { + ChannelStats *p = &s->chstats[i]; + + av_freep(&p->win_samples); + } + } av_freep(&s->chstats); } @@ -734,4 +846,5 @@ .uninit = uninit, .inputs = astats_inputs, .outputs = astats_outputs, + .flags = AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_asubboost.c ffmpeg-4.4/libavfilter/af_asubboost.c --- ffmpeg-4.2.2/libavfilter/af_asubboost.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_asubboost.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,259 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/ffmath.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "audio.h" +#include "formats.h" + +typedef struct ASubBoostContext { + const AVClass *class; + + double dry_gain; + double wet_gain; + double feedback; + double decay; + double delay; + double cutoff; + double slope; + + double a0, a1, a2; + double b0, b1, b2; + + int *write_pos; + int buffer_samples; + + AVFrame *w; + AVFrame *buffer; +} ASubBoostContext; + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *layouts = NULL; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE + }; + int ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_all_samplerates(); + return ff_set_common_samplerates(ctx, formats); +} + +static int get_coeffs(AVFilterContext *ctx) +{ + ASubBoostContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + double w0 = 2 * M_PI * s->cutoff / inlink->sample_rate; + double alpha = sin(w0) / 2 * sqrt(2. * (1. / s->slope - 1.) + 2.); + + s->a0 = 1 + alpha; + s->a1 = -2 * cos(w0); + s->a2 = 1 - alpha; + s->b0 = (1 - cos(w0)) / 2; + s->b1 = 1 - cos(w0); + s->b2 = (1 - cos(w0)) / 2; + + s->a1 /= s->a0; + s->a2 /= s->a0; + s->b0 /= s->a0; + s->b1 /= s->a0; + s->b2 /= s->a0; + + s->buffer_samples = inlink->sample_rate * s->delay / 1000; + + return 0; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ASubBoostContext *s = ctx->priv; + + s->buffer = ff_get_audio_buffer(inlink, inlink->sample_rate / 10); + s->w = ff_get_audio_buffer(inlink, 2); + s->write_pos = av_calloc(inlink->channels, sizeof(*s->write_pos)); + if (!s->buffer || !s->w || !s->write_pos) + return AVERROR(ENOMEM); + + return get_coeffs(ctx); +} + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ASubBoostContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + const double mix = ctx->is_disabled ? 0. : 1.; + const double wet = ctx->is_disabled ? 1. : s->wet_gain; + const double dry = ctx->is_disabled ? 1. : s->dry_gain; + const double feedback = s->feedback, decay = s->decay; + const double b0 = s->b0; + const double b1 = s->b1; + const double b2 = s->b2; + const double a1 = -s->a1; + const double a2 = -s->a2; + const int start = (in->channels * jobnr) / nb_jobs; + const int end = (in->channels * (jobnr+1)) / nb_jobs; + const int buffer_samples = s->buffer_samples; + + for (int ch = start; ch < end; ch++) { + const double *src = (const double *)in->extended_data[ch]; + double *dst = (double *)out->extended_data[ch]; + double *buffer = (double *)s->buffer->extended_data[ch]; + double *w = (double *)s->w->extended_data[ch]; + int write_pos = s->write_pos[ch]; + + for (int n = 0; n < in->nb_samples; n++) { + double out_sample; + + out_sample = src[n] * b0 + w[0]; + w[0] = b1 * src[n] + w[1] + a1 * out_sample; + w[1] = b2 * src[n] + a2 * out_sample; + + buffer[write_pos] = buffer[write_pos] * decay + out_sample * feedback; + dst[n] = (src[n] * dry + buffer[write_pos] * mix) * wet; + + if (++write_pos >= buffer_samples) + write_pos = 0; + } + + s->write_pos[ch] = write_pos; + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + 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); + } + + td.in = in; td.out = out; + ctx->internal->execute(ctx, filter_channels, &td, NULL, FFMIN(inlink->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) +{ + ASubBoostContext *s = ctx->priv; + + av_frame_free(&s->buffer); + av_frame_free(&s->w); + av_freep(&s->write_pos); +} + +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return get_coeffs(ctx); +} + +#define OFFSET(x) offsetof(ASubBoostContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption asubboost_options[] = { + { "dry", "set dry gain", OFFSET(dry_gain), AV_OPT_TYPE_DOUBLE, {.dbl=0.7}, 0, 1, FLAGS }, + { "wet", "set wet gain", OFFSET(wet_gain), AV_OPT_TYPE_DOUBLE, {.dbl=0.7}, 0, 1, FLAGS }, + { "decay", "set decay", OFFSET(decay), AV_OPT_TYPE_DOUBLE, {.dbl=0.7}, 0, 1, FLAGS }, + { "feedback", "set feedback", OFFSET(feedback), AV_OPT_TYPE_DOUBLE, {.dbl=0.9}, 0, 1, FLAGS }, + { "cutoff", "set cutoff", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 50, 900, FLAGS }, + { "slope", "set slope", OFFSET(slope), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0.0001, 1, FLAGS }, + { "delay", "set delay", OFFSET(delay), AV_OPT_TYPE_DOUBLE, {.dbl=20}, 1, 100, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(asubboost); + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_asubboost = { + .name = "asubboost", + .description = NULL_IF_CONFIG_SMALL("Boost subwoofer frequencies."), + .query_formats = query_formats, + .priv_size = sizeof(ASubBoostContext), + .priv_class = &asubboost_class, + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, + .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS, +}; diff -Nru ffmpeg-4.2.2/libavfilter/af_asupercut.c ffmpeg-4.4/libavfilter/af_asupercut.c --- ffmpeg-4.2.2/libavfilter/af_asupercut.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_asupercut.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,448 @@ +/* + * Copyright (c) 2005 Boðaç Topaktaþ + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/ffmath.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "audio.h" +#include "formats.h" + +typedef struct BiquadCoeffs { + double a1, a2; + double b0, b1, b2; +} BiquadCoeffs; + +typedef struct ASuperCutContext { + const AVClass *class; + + double cutoff; + double level; + double qfactor; + int order; + + int filter_count; + int bypass; + + BiquadCoeffs coeffs[10]; + + AVFrame *w; + + int (*filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); +} ASuperCutContext; + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *layouts = NULL; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE + }; + int ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_all_samplerates(); + return ff_set_common_samplerates(ctx, formats); +} + +static void calc_q_factors(int n, double *q) +{ + for (int i = 0; i < n / 2; i++) + q[i] = 1. / (-2. * cos(M_PI * (2. * (i + 1) + n - 1.) / (2. * n))); +} + +static int get_coeffs(AVFilterContext *ctx) +{ + ASuperCutContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + double w0 = s->cutoff / inlink->sample_rate; + double K = tan(M_PI * w0); + double q[10]; + + s->bypass = w0 >= 0.5; + if (s->bypass) + return 0; + + if (!strcmp(ctx->filter->name, "asubcut")) { + s->filter_count = s->order / 2 + (s->order & 1); + + calc_q_factors(s->order, q); + + if (s->order & 1) { + BiquadCoeffs *coeffs = &s->coeffs[0]; + double omega = 2. * tan(M_PI * w0); + + coeffs->b0 = 2. / (2. + omega); + coeffs->b1 = -coeffs->b0; + coeffs->b2 = 0.; + coeffs->a1 = -(omega - 2.) / (2. + omega); + coeffs->a2 = 0.; + } + + for (int b = (s->order & 1); b < s->filter_count; b++) { + BiquadCoeffs *coeffs = &s->coeffs[b]; + const int idx = b - (s->order & 1); + double norm = 1.0 / (1.0 + K / q[idx] + K * K); + + coeffs->b0 = norm; + coeffs->b1 = -2.0 * coeffs->b0; + coeffs->b2 = coeffs->b0; + coeffs->a1 = -2.0 * (K * K - 1.0) * norm; + coeffs->a2 = -(1.0 - K / q[idx] + K * K) * norm; + } + } else if (!strcmp(ctx->filter->name, "asupercut")) { + s->filter_count = s->order / 2 + (s->order & 1); + + calc_q_factors(s->order, q); + + if (s->order & 1) { + BiquadCoeffs *coeffs = &s->coeffs[0]; + double omega = 2. * tan(M_PI * w0); + + coeffs->b0 = omega / (2. + omega); + coeffs->b1 = coeffs->b0; + coeffs->b2 = 0.; + coeffs->a1 = -(omega - 2.) / (2. + omega); + coeffs->a2 = 0.; + } + + for (int b = (s->order & 1); b < s->filter_count; b++) { + BiquadCoeffs *coeffs = &s->coeffs[b]; + const int idx = b - (s->order & 1); + double norm = 1.0 / (1.0 + K / q[idx] + K * K); + + coeffs->b0 = K * K * norm; + coeffs->b1 = 2.0 * coeffs->b0; + coeffs->b2 = coeffs->b0; + coeffs->a1 = -2.0 * (K * K - 1.0) * norm; + coeffs->a2 = -(1.0 - K / q[idx] + K * K) * norm; + } + } else if (!strcmp(ctx->filter->name, "asuperpass")) { + double alpha, beta, gamma, theta; + double theta_0 = 2. * M_PI * (s->cutoff / inlink->sample_rate); + double d_E; + + s->filter_count = s->order / 2; + d_E = (2. * tan(theta_0 / (2. * s->qfactor))) / sin(theta_0); + + for (int b = 0; b < s->filter_count; b += 2) { + double D = 2. * sin(((b + 1) * M_PI) / (2. * s->filter_count)); + double A = (1. + pow((d_E / 2.), 2)) / (D * d_E / 2.); + double d = sqrt((d_E * D) / (A + sqrt(A * A - 1.))); + double B = D * (d_E / 2.) / d; + double W = B + sqrt(B * B - 1.); + + for (int j = 0; j < 2; j++) { + BiquadCoeffs *coeffs = &s->coeffs[b + j]; + + if (j == 1) + theta = 2. * atan(tan(theta_0 / 2.) / W); + else + theta = 2. * atan(W * tan(theta_0 / 2.)); + + beta = 0.5 * ((1. - (d / 2.) * sin(theta)) / (1. + (d / 2.) * sin(theta))); + gamma = (0.5 + beta) * cos(theta); + alpha = 0.5 * (0.5 - beta) * sqrt(1. + pow((W - (1. / W)) / d, 2.)); + + coeffs->a1 = 2. * gamma; + coeffs->a2 = -2. * beta; + coeffs->b0 = 2. * alpha; + coeffs->b1 = 0.; + coeffs->b2 = -2. * alpha; + } + } + } else if (!strcmp(ctx->filter->name, "asuperstop")) { + double alpha, beta, gamma, theta; + double theta_0 = 2. * M_PI * (s->cutoff / inlink->sample_rate); + double d_E; + + s->filter_count = s->order / 2; + d_E = (2. * tan(theta_0 / (2. * s->qfactor))) / sin(theta_0); + + for (int b = 0; b < s->filter_count; b += 2) { + double D = 2. * sin(((b + 1) * M_PI) / (2. * s->filter_count)); + double A = (1. + pow((d_E / 2.), 2)) / (D * d_E / 2.); + double d = sqrt((d_E * D) / (A + sqrt(A * A - 1.))); + double B = D * (d_E / 2.) / d; + double W = B + sqrt(B * B - 1.); + + for (int j = 0; j < 2; j++) { + BiquadCoeffs *coeffs = &s->coeffs[b + j]; + + if (j == 1) + theta = 2. * atan(tan(theta_0 / 2.) / W); + else + theta = 2. * atan(W * tan(theta_0 / 2.)); + + beta = 0.5 * ((1. - (d / 2.) * sin(theta)) / (1. + (d / 2.) * sin(theta))); + gamma = (0.5 + beta) * cos(theta); + alpha = 0.5 * (0.5 + beta) * ((1. - cos(theta)) / (1. - cos(theta_0))); + + coeffs->a1 = 2. * gamma; + coeffs->a2 = -2. * beta; + coeffs->b0 = 2. * alpha; + coeffs->b1 = -4. * alpha * cos(theta_0); + coeffs->b2 = 2. * alpha; + } + } + } + + return 0; +} + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +#define FILTER(name, type) \ +static int filter_channels_## name(AVFilterContext *ctx, void *arg, \ + int jobnr, int nb_jobs) \ +{ \ + ASuperCutContext *s = ctx->priv; \ + ThreadData *td = arg; \ + AVFrame *out = td->out; \ + AVFrame *in = td->in; \ + const int start = (in->channels * jobnr) / nb_jobs; \ + const int end = (in->channels * (jobnr+1)) / nb_jobs; \ + const double level = s->level; \ + \ + for (int ch = start; ch < end; ch++) { \ + const type *src = (const type *)in->extended_data[ch]; \ + type *dst = (type *)out->extended_data[ch]; \ + \ + for (int b = 0; b < s->filter_count; b++) { \ + BiquadCoeffs *coeffs = &s->coeffs[b]; \ + const type a1 = coeffs->a1; \ + const type a2 = coeffs->a2; \ + const type b0 = coeffs->b0; \ + const type b1 = coeffs->b1; \ + const type b2 = coeffs->b2; \ + type *w = ((type *)s->w->extended_data[ch]) + b * 2; \ + \ + for (int n = 0; n < in->nb_samples; n++) { \ + type sin = b ? dst[n] : src[n] * level; \ + type sout = sin * b0 + w[0]; \ + \ + w[0] = b1 * sin + w[1] + a1 * sout; \ + w[1] = b2 * sin + a2 * sout; \ + \ + dst[n] = sout; \ + } \ + } \ + } \ + \ + return 0; \ +} + +FILTER(fltp, float) +FILTER(dblp, double) + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ASuperCutContext *s = ctx->priv; + + switch (inlink->format) { + case AV_SAMPLE_FMT_FLTP: s->filter_channels = filter_channels_fltp; break; + case AV_SAMPLE_FMT_DBLP: s->filter_channels = filter_channels_dblp; break; + } + + s->w = ff_get_audio_buffer(inlink, 2 * 10); + if (!s->w) + return AVERROR(ENOMEM); + + return get_coeffs(ctx); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + ASuperCutContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + ThreadData td; + AVFrame *out; + + if (s->bypass) + return ff_filter_frame(outlink, in); + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_audio_buffer(outlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + td.in = in; td.out = out; + ctx->internal->execute(ctx, s->filter_channels, &td, NULL, FFMIN(inlink->channels, + 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) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return get_coeffs(ctx); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + ASuperCutContext *s = ctx->priv; + + av_frame_free(&s->w); +} + +#define OFFSET(x) offsetof(ASuperCutContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption asupercut_options[] = { + { "cutoff", "set cutoff frequency", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, {.dbl=20000}, 20000, 192000, FLAGS }, + { "order", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=10}, 3, 20, FLAGS }, + { "level", "set input level", OFFSET(level), AV_OPT_TYPE_DOUBLE, {.dbl=1.}, 0., 1., FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(asupercut); + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_asupercut = { + .name = "asupercut", + .description = NULL_IF_CONFIG_SMALL("Cut super frequencies."), + .query_formats = query_formats, + .priv_size = sizeof(ASuperCutContext), + .priv_class = &asupercut_class, + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, + .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS, +}; + +static const AVOption asubcut_options[] = { + { "cutoff", "set cutoff frequency", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, {.dbl=20}, 2, 200, FLAGS }, + { "order", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=10}, 3, 20, FLAGS }, + { "level", "set input level", OFFSET(level), AV_OPT_TYPE_DOUBLE, {.dbl=1.}, 0., 1., FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(asubcut); + +AVFilter ff_af_asubcut = { + .name = "asubcut", + .description = NULL_IF_CONFIG_SMALL("Cut subwoofer frequencies."), + .query_formats = query_formats, + .priv_size = sizeof(ASuperCutContext), + .priv_class = &asubcut_class, + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, + .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS, +}; + +static const AVOption asuperpass_asuperstop_options[] = { + { "centerf","set center frequency", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, {.dbl=1000}, 2, 999999, FLAGS }, + { "order", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=4}, 4, 20, FLAGS }, + { "qfactor","set Q-factor", OFFSET(qfactor),AV_OPT_TYPE_DOUBLE, {.dbl=1.},0.01, 100., FLAGS }, + { "level", "set input level", OFFSET(level), AV_OPT_TYPE_DOUBLE, {.dbl=1.}, 0., 2., FLAGS }, + { NULL } +}; + +#define asuperpass_options asuperpass_asuperstop_options +AVFILTER_DEFINE_CLASS(asuperpass); + +AVFilter ff_af_asuperpass = { + .name = "asuperpass", + .description = NULL_IF_CONFIG_SMALL("Apply high order Butterworth band-pass filter."), + .query_formats = query_formats, + .priv_size = sizeof(ASuperCutContext), + .priv_class = &asuperpass_class, + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, + .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS, +}; + +#define asuperstop_options asuperpass_asuperstop_options +AVFILTER_DEFINE_CLASS(asuperstop); + +AVFilter ff_af_asuperstop = { + .name = "asuperstop", + .description = NULL_IF_CONFIG_SMALL("Apply high order Butterworth band-stop filter."), + .query_formats = query_formats, + .priv_size = sizeof(ASuperCutContext), + .priv_class = &asuperstop_class, + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, + .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS, +}; diff -Nru ffmpeg-4.2.2/libavfilter/af_atempo.c ffmpeg-4.4/libavfilter/af_atempo.c --- ffmpeg-4.2.2/libavfilter/af_atempo.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_atempo.c 2020-07-11 10:39:30.000000000 +0000 @@ -162,7 +162,7 @@ OFFSET(tempo), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, YAE_ATEMPO_MIN, YAE_ATEMPO_MAX, - AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM }, + AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM }, { NULL } }; @@ -328,28 +328,14 @@ return 0; } -static int yae_set_tempo(AVFilterContext *ctx, const char *arg_tempo) +static int yae_update(AVFilterContext *ctx) { const AudioFragment *prev; ATempoContext *atempo = ctx->priv; - char *tail = NULL; - double tempo = av_strtod(arg_tempo, &tail); - - if (tail && *tail) { - av_log(ctx, AV_LOG_ERROR, "Invalid tempo value '%s'\n", arg_tempo); - return AVERROR(EINVAL); - } - - if (tempo < YAE_ATEMPO_MIN || tempo > YAE_ATEMPO_MAX) { - av_log(ctx, AV_LOG_ERROR, "Tempo value %f exceeds [%f, %f] range\n", - tempo, YAE_ATEMPO_MIN, YAE_ATEMPO_MAX); - return AVERROR(EINVAL); - } prev = yae_prev_frag(atempo); atempo->origin[0] = prev->position[0] + atempo->window / 2; atempo->origin[1] = prev->position[1] + atempo->window / 2; - atempo->tempo = tempo; return 0; } @@ -1189,7 +1175,12 @@ int res_len, int flags) { - return !strcmp(cmd, "tempo") ? yae_set_tempo(ctx, arg) : AVERROR(ENOSYS); + int ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags); + + if (ret < 0) + return ret; + + return yae_update(ctx); } static const AVFilterPad atempo_inputs[] = { diff -Nru ffmpeg-4.2.2/libavfilter/af_axcorrelate.c ffmpeg-4.4/libavfilter/af_axcorrelate.c --- ffmpeg-4.2.2/libavfilter/af_axcorrelate.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_axcorrelate.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2019 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/audio_fifo.h" +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" + +#include "audio.h" +#include "avfilter.h" +#include "formats.h" +#include "filters.h" +#include "internal.h" + +typedef struct AudioXCorrelateContext { + const AVClass *class; + + int size; + int algo; + int64_t pts; + + AVAudioFifo *fifo[2]; + AVFrame *cache[2]; + AVFrame *mean_sum[2]; + AVFrame *num_sum; + AVFrame *den_sum[2]; + int used; + + int (*xcorrelate)(AVFilterContext *ctx, AVFrame *out); +} AudioXCorrelateContext; + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats; + AVFilterChannelLayouts *layouts; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE + }; + int ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + formats = ff_all_samplerates(); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_samplerates(ctx, formats); +} + +static float mean_sum(const float *in, int size) +{ + float mean_sum = 0.f; + + for (int i = 0; i < size; i++) + mean_sum += in[i]; + + return mean_sum; +} + +static float square_sum(const float *x, const float *y, int size) +{ + float square_sum = 0.f; + + for (int i = 0; i < size; i++) + square_sum += x[i] * y[i]; + + return square_sum; +} + +static float xcorrelate(const float *x, const float *y, float sumx, float sumy, int size) +{ + const float xm = sumx / size, ym = sumy / size; + float num = 0.f, den, den0 = 0.f, den1 = 0.f; + + for (int i = 0; i < size; i++) { + float xd = x[i] - xm; + float yd = y[i] - ym; + + num += xd * yd; + den0 += xd * xd; + den1 += yd * yd; + } + + num /= size; + den = sqrtf((den0 * den1) / (size * size)); + + return den <= 1e-6f ? 0.f : num / den; +} + +static int xcorrelate_slow(AVFilterContext *ctx, AVFrame *out) +{ + AudioXCorrelateContext *s = ctx->priv; + const int size = s->size; + int used; + + for (int ch = 0; ch < out->channels; ch++) { + const float *x = (const float *)s->cache[0]->extended_data[ch]; + const float *y = (const float *)s->cache[1]->extended_data[ch]; + float *sumx = (float *)s->mean_sum[0]->extended_data[ch]; + float *sumy = (float *)s->mean_sum[1]->extended_data[ch]; + float *dst = (float *)out->extended_data[ch]; + + used = s->used; + if (!used) { + sumx[0] = mean_sum(x, size); + sumy[0] = mean_sum(y, size); + used = 1; + } + + for (int n = 0; n < out->nb_samples; n++) { + dst[n] = xcorrelate(x + n, y + n, sumx[0], sumy[0], size); + + sumx[0] -= x[n]; + sumx[0] += x[n + size]; + sumy[0] -= y[n]; + sumy[0] += y[n + size]; + } + } + + return used; +} + +static int xcorrelate_fast(AVFilterContext *ctx, AVFrame *out) +{ + AudioXCorrelateContext *s = ctx->priv; + const int size = s->size; + int used; + + for (int ch = 0; ch < out->channels; ch++) { + const float *x = (const float *)s->cache[0]->extended_data[ch]; + const float *y = (const float *)s->cache[1]->extended_data[ch]; + float *num_sum = (float *)s->num_sum->extended_data[ch]; + float *den_sumx = (float *)s->den_sum[0]->extended_data[ch]; + float *den_sumy = (float *)s->den_sum[1]->extended_data[ch]; + float *dst = (float *)out->extended_data[ch]; + + used = s->used; + if (!used) { + num_sum[0] = square_sum(x, y, size); + den_sumx[0] = square_sum(x, x, size); + den_sumy[0] = square_sum(y, y, size); + used = 1; + } + + for (int n = 0; n < out->nb_samples; n++) { + float num, den; + + num = num_sum[0] / size; + den = sqrtf((den_sumx[0] * den_sumy[0]) / (size * size)); + + dst[n] = den <= 1e-6f ? 0.f : num / den; + + num_sum[0] -= x[n] * y[n]; + num_sum[0] += x[n + size] * y[n + size]; + den_sumx[0] -= x[n] * x[n]; + den_sumx[0] = FFMAX(den_sumx[0], 0.f); + den_sumx[0] += x[n + size] * x[n + size]; + den_sumy[0] -= y[n] * y[n]; + den_sumy[0] = FFMAX(den_sumy[0], 0.f); + den_sumy[0] += y[n + size] * y[n + size]; + } + } + + return used; +} + +static int activate(AVFilterContext *ctx) +{ + AudioXCorrelateContext *s = ctx->priv; + AVFrame *frame = NULL; + int ret, status; + int available; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); + + for (int i = 0; i < 2; i++) { + ret = ff_inlink_consume_frame(ctx->inputs[i], &frame); + if (ret > 0) { + if (s->pts == AV_NOPTS_VALUE) + s->pts = frame->pts; + ret = av_audio_fifo_write(s->fifo[i], (void **)frame->extended_data, + frame->nb_samples); + av_frame_free(&frame); + if (ret < 0) + return ret; + } + } + + available = FFMIN(av_audio_fifo_size(s->fifo[0]), av_audio_fifo_size(s->fifo[1])); + if (available > s->size) { + const int out_samples = available - s->size; + AVFrame *out; + + if (!s->cache[0] || s->cache[0]->nb_samples < available) { + av_frame_free(&s->cache[0]); + s->cache[0] = ff_get_audio_buffer(ctx->outputs[0], available); + if (!s->cache[0]) + return AVERROR(ENOMEM); + } + + if (!s->cache[1] || s->cache[1]->nb_samples < available) { + av_frame_free(&s->cache[1]); + s->cache[1] = ff_get_audio_buffer(ctx->outputs[0], available); + if (!s->cache[1]) + return AVERROR(ENOMEM); + } + + ret = av_audio_fifo_peek(s->fifo[0], (void **)s->cache[0]->extended_data, available); + if (ret < 0) + return ret; + + ret = av_audio_fifo_peek(s->fifo[1], (void **)s->cache[1]->extended_data, available); + if (ret < 0) + return ret; + + out = ff_get_audio_buffer(ctx->outputs[0], out_samples); + if (!out) + return AVERROR(ENOMEM); + + s->used = s->xcorrelate(ctx, out); + + out->pts = s->pts; + s->pts += out_samples; + + av_audio_fifo_drain(s->fifo[0], out_samples); + av_audio_fifo_drain(s->fifo[1], out_samples); + + return ff_filter_frame(ctx->outputs[0], out); + } + + if (av_audio_fifo_size(s->fifo[0]) > s->size && + av_audio_fifo_size(s->fifo[1]) > s->size) { + ff_filter_set_ready(ctx, 10); + return 0; + } + + for (int i = 0; i < 2; i++) { + if (ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts)) { + ff_outlink_set_status(ctx->outputs[0], status, pts); + return 0; + } + } + + if (ff_outlink_frame_wanted(ctx->outputs[0])) { + for (int i = 0; i < 2; i++) { + if (av_audio_fifo_size(s->fifo[i]) > s->size) + continue; + ff_inlink_request_frame(ctx->inputs[i]); + return 0; + } + } + + return FFERROR_NOT_READY; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; + AudioXCorrelateContext *s = ctx->priv; + + s->pts = AV_NOPTS_VALUE; + + outlink->format = inlink->format; + outlink->channels = inlink->channels; + s->fifo[0] = av_audio_fifo_alloc(outlink->format, outlink->channels, s->size); + s->fifo[1] = av_audio_fifo_alloc(outlink->format, outlink->channels, s->size); + if (!s->fifo[0] || !s->fifo[1]) + return AVERROR(ENOMEM); + + s->mean_sum[0] = ff_get_audio_buffer(outlink, 1); + s->mean_sum[1] = ff_get_audio_buffer(outlink, 1); + s->num_sum = ff_get_audio_buffer(outlink, 1); + s->den_sum[0] = ff_get_audio_buffer(outlink, 1); + s->den_sum[1] = ff_get_audio_buffer(outlink, 1); + if (!s->mean_sum[0] || !s->mean_sum[1] || !s->num_sum || + !s->den_sum[0] || !s->den_sum[1]) + return AVERROR(ENOMEM); + + switch (s->algo) { + case 0: s->xcorrelate = xcorrelate_slow; break; + case 1: s->xcorrelate = xcorrelate_fast; break; + } + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioXCorrelateContext *s = ctx->priv; + + av_audio_fifo_free(s->fifo[0]); + av_audio_fifo_free(s->fifo[1]); + av_frame_free(&s->cache[0]); + av_frame_free(&s->cache[1]); + av_frame_free(&s->mean_sum[0]); + av_frame_free(&s->mean_sum[1]); + av_frame_free(&s->num_sum); + av_frame_free(&s->den_sum[0]); + av_frame_free(&s->den_sum[1]); +} + +static const AVFilterPad inputs[] = { + { + .name = "axcorrelate0", + .type = AVMEDIA_TYPE_AUDIO, + }, + { + .name = "axcorrelate1", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }, + { NULL } +}; + +#define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define OFFSET(x) offsetof(AudioXCorrelateContext, x) + +static const AVOption axcorrelate_options[] = { + { "size", "set segment size", OFFSET(size), AV_OPT_TYPE_INT, {.i64=256}, 2, 131072, AF }, + { "algo", "set alghorithm", OFFSET(algo), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AF, "algo" }, + { "slow", "slow algorithm", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "algo" }, + { "fast", "fast algorithm", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "algo" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(axcorrelate); + +AVFilter ff_af_axcorrelate = { + .name = "axcorrelate", + .description = NULL_IF_CONFIG_SMALL("Cross-correlate two audio streams."), + .priv_size = sizeof(AudioXCorrelateContext), + .priv_class = &axcorrelate_class, + .query_formats = query_formats, + .activate = activate, + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, +}; diff -Nru ffmpeg-4.2.2/libavfilter/af_biquads.c ffmpeg-4.4/libavfilter/af_biquads.c --- ffmpeg-4.2.2/libavfilter/af_biquads.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_biquads.c 2021-04-08 21:28:39.000000000 +0000 @@ -93,6 +93,14 @@ NB_WTYPE, }; +enum TransformType { + DI, + DII, + TDII, + LATT, + NB_TTYPE, +}; + typedef struct ChanCache { double i1, i2; double o1, o2; @@ -106,16 +114,25 @@ int width_type; int poles; int csg; + int transform_type; + int precision; + + int bypass; double gain; double frequency; double width; double mix; uint64_t channels; + int normalize; + int order; double a0, a1, a2; double b0, b1, b2; + double oa0, oa1, oa2; + double ob0, ob1, ob2; + ChanCache *cache; int block_align; @@ -125,32 +142,22 @@ int disabled); } BiquadsContext; -static av_cold int init(AVFilterContext *ctx) -{ - BiquadsContext *s = ctx->priv; - - if (s->filter_type != biquad) { - if (s->frequency <= 0 || s->width <= 0) { - av_log(ctx, AV_LOG_ERROR, "Invalid frequency %f and/or width %f <= 0\n", - s->frequency, s->width); - return AVERROR(EINVAL); - } - } - - return 0; -} - static int query_formats(AVFilterContext *ctx) { + BiquadsContext *s = ctx->priv; AVFilterFormats *formats; AVFilterChannelLayouts *layouts; - static const enum AVSampleFormat sample_fmts[] = { + static const enum AVSampleFormat auto_sample_fmts[] = { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }; + enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE + }; int ret; layouts = ff_all_channel_counts(); @@ -160,7 +167,27 @@ if (ret < 0) return ret; - formats = ff_make_format_list(sample_fmts); + switch (s->precision) { + case 0: + sample_fmts[0] = AV_SAMPLE_FMT_S16P; + formats = ff_make_format_list(sample_fmts); + break; + case 1: + sample_fmts[0] = AV_SAMPLE_FMT_S32P; + formats = ff_make_format_list(sample_fmts); + break; + case 2: + sample_fmts[0] = AV_SAMPLE_FMT_FLTP; + formats = ff_make_format_list(sample_fmts); + break; + case 3: + sample_fmts[0] = AV_SAMPLE_FMT_DBLP; + formats = ff_make_format_list(sample_fmts); + break; + default: + formats = ff_make_format_list(auto_sample_fmts); + break; + } if (!formats) return AVERROR(ENOMEM); ret = ff_set_common_formats(ctx, formats); @@ -256,6 +283,173 @@ BIQUAD_FILTER(flt, float, -1., 1., 0) BIQUAD_FILTER(dbl, double, -1., 1., 0) +#define BIQUAD_DII_FILTER(name, type, min, max, need_clipping) \ +static void biquad_dii_## name (BiquadsContext *s, \ + const void *input, void *output, int len, \ + double *z1, double *z2, \ + double *unused1, double *unused2, \ + double b0, double b1, double b2, \ + double a1, double a2, int *clippings, \ + int disabled) \ +{ \ + const type *ibuf = input; \ + type *obuf = output; \ + double w1 = *z1; \ + double w2 = *z2; \ + double wet = s->mix; \ + double dry = 1. - wet; \ + double in, out, w0; \ + \ + a1 = -a1; \ + a2 = -a2; \ + \ + for (int i = 0; i < len; i++) { \ + in = ibuf[i]; \ + w0 = in + a1 * w1 + a2 * w2; \ + out = b0 * w0 + b1 * w1 + b2 * w2; \ + w2 = w1; \ + w1 = w0; \ + 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; \ + } \ + } \ + *z1 = w1; \ + *z2 = w2; \ +} + +BIQUAD_DII_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) +BIQUAD_DII_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) +BIQUAD_DII_FILTER(flt, float, -1., 1., 0) +BIQUAD_DII_FILTER(dbl, double, -1., 1., 0) + +#define BIQUAD_TDII_FILTER(name, type, min, max, need_clipping) \ +static void biquad_tdii_## name (BiquadsContext *s, \ + const void *input, void *output, int len, \ + double *z1, double *z2, \ + double *unused1, double *unused2, \ + double b0, double b1, double b2, \ + double a1, double a2, int *clippings, \ + int disabled) \ +{ \ + const type *ibuf = input; \ + type *obuf = output; \ + double w1 = *z1; \ + double w2 = *z2; \ + double wet = s->mix; \ + double dry = 1. - wet; \ + double in, out; \ + \ + a1 = -a1; \ + a2 = -a2; \ + \ + for (int i = 0; i < len; i++) { \ + in = ibuf[i]; \ + out = b0 * in + w1; \ + w1 = b1 * in + w2 + a1 * out; \ + w2 = b2 * in + a2 * out; \ + 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; \ + } \ + } \ + *z1 = w1; \ + *z2 = w2; \ +} + +BIQUAD_TDII_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) +BIQUAD_TDII_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) +BIQUAD_TDII_FILTER(flt, float, -1., 1., 0) +BIQUAD_TDII_FILTER(dbl, double, -1., 1., 0) + +#define BIQUAD_LATT_FILTER(name, type, min, max, need_clipping) \ +static void biquad_latt_## name (BiquadsContext *s, \ + const void *input, void *output, int len, \ + double *z1, double *z2, \ + double *unused1, double *unused2, \ + double v0, double v1, double v2, \ + double k0, double k1, int *clippings, \ + int disabled) \ +{ \ + const type *ibuf = input; \ + type *obuf = output; \ + double s0 = *z1; \ + double s1 = *z2; \ + double wet = s->mix; \ + double dry = 1. - wet; \ + double in, out; \ + double t0, t1; \ + \ + for (int i = 0; i < len; i++) { \ + out = 0.; \ + in = ibuf[i]; \ + t0 = in - k1 * s0; \ + t1 = t0 * k1 + s0; \ + out += t1 * v2; \ + \ + t0 = t0 - k0 * s1; \ + t1 = t0 * k0 + s1; \ + out += t1 * v1; \ + \ + out += t0 * v0; \ + s0 = t1; \ + s1 = t0; \ + \ + 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; \ + } \ + } \ + *z1 = s0; \ + *z2 = s1; \ +} + +BIQUAD_LATT_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) +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) + +static void convert_dir2latt(BiquadsContext *s) +{ + double k0, k1, v0, v1, v2; + + k1 = s->a2; + k0 = s->a1 / (1. + k1); + v2 = s->b2; + v1 = s->b1 - v2 * s->a1; + v0 = s->b0 - v1 * k0 - v2 * k1; + + s->a1 = k0; + s->a2 = k1; + s->b0 = v0; + s->b1 = v1; + s->b2 = v2; +} + static int config_filter(AVFilterLink *outlink, int reset) { AVFilterContext *ctx = outlink->src; @@ -263,15 +457,18 @@ AVFilterLink *inlink = ctx->inputs[0]; double A = ff_exp10(s->gain / 40); double w0 = 2 * M_PI * s->frequency / inlink->sample_rate; + double K = tan(w0 / 2.); double alpha, beta; - if (w0 > M_PI) { - av_log(ctx, AV_LOG_ERROR, - "Invalid frequency %f. Frequency must be less than half the sample-rate %d.\n", - s->frequency, inlink->sample_rate); - return AVERROR(EINVAL); + s->bypass = (((w0 > M_PI || w0 <= 0.) && reset) || (s->width <= 0.)) && (s->filter_type != biquad); + if (s->bypass) { + av_log(ctx, AV_LOG_WARNING, "Invalid frequency and/or width!\n"); + return 0; } + if ((w0 > M_PI || w0 <= 0.) && (s->filter_type != biquad)) + return AVERROR(EINVAL); + switch (s->width_type) { case NONE: alpha = 0.0; @@ -299,6 +496,12 @@ switch (s->filter_type) { case biquad: + s->a0 = s->oa0; + s->a1 = s->oa1; + s->a2 = s->oa2; + s->b0 = s->ob0; + s->b1 = s->ob1; + s->b2 = s->ob2; break; case equalizer: s->a0 = 1 + alpha / A; @@ -311,22 +514,54 @@ case bass: beta = sqrt((A * A + 1) - (A - 1) * (A - 1)); case lowshelf: - s->a0 = (A + 1) + (A - 1) * cos(w0) + beta * alpha; - s->a1 = -2 * ((A - 1) + (A + 1) * cos(w0)); - s->a2 = (A + 1) + (A - 1) * cos(w0) - beta * alpha; - s->b0 = A * ((A + 1) - (A - 1) * cos(w0) + beta * alpha); - s->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0)); - s->b2 = A * ((A + 1) - (A - 1) * cos(w0) - beta * alpha); + if (s->poles == 1) { + double A = ff_exp10(s->gain / 20); + double ro = -sin(w0 / 2. - M_PI_4) / sin(w0 / 2. + M_PI_4); + double n = (A + 1) / (A - 1); + double alpha1 = A == 1. ? 0. : n - FFSIGN(n) * sqrt(n * n - 1); + double beta0 = ((1 + A) + (1 - A) * alpha1) * 0.5; + double beta1 = ((1 - A) + (1 + A) * alpha1) * 0.5; + + s->a0 = 1 + ro * alpha1; + s->a1 = -ro - alpha1; + s->a2 = 0; + s->b0 = beta0 + ro * beta1; + s->b1 = -beta1 - ro * beta0; + s->b2 = 0; + } else { + s->a0 = (A + 1) + (A - 1) * cos(w0) + beta * alpha; + s->a1 = -2 * ((A - 1) + (A + 1) * cos(w0)); + s->a2 = (A + 1) + (A - 1) * cos(w0) - beta * alpha; + s->b0 = A * ((A + 1) - (A - 1) * cos(w0) + beta * alpha); + s->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0)); + s->b2 = A * ((A + 1) - (A - 1) * cos(w0) - beta * alpha); + } break; case treble: beta = sqrt((A * A + 1) - (A - 1) * (A - 1)); case highshelf: - s->a0 = (A + 1) - (A - 1) * cos(w0) + beta * alpha; - s->a1 = 2 * ((A - 1) - (A + 1) * cos(w0)); - s->a2 = (A + 1) - (A - 1) * cos(w0) - beta * alpha; - s->b0 = A * ((A + 1) + (A - 1) * cos(w0) + beta * alpha); - s->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0)); - s->b2 = A * ((A + 1) + (A - 1) * cos(w0) - beta * alpha); + if (s->poles == 1) { + double A = ff_exp10(s->gain / 20); + double ro = sin(w0 / 2. - M_PI_4) / sin(w0 / 2. + M_PI_4); + double n = (A + 1) / (A - 1); + double alpha1 = A == 1. ? 0. : n - FFSIGN(n) * sqrt(n * n - 1); + double beta0 = ((1 + A) + (1 - A) * alpha1) * 0.5; + double beta1 = ((1 - A) + (1 + A) * alpha1) * 0.5; + + s->a0 = 1 + ro * alpha1; + s->a1 = ro + alpha1; + s->a2 = 0; + s->b0 = beta0 + ro * beta1; + s->b1 = beta1 + ro * beta0; + s->b2 = 0; + } else { + s->a0 = (A + 1) - (A - 1) * cos(w0) + beta * alpha; + s->a1 = 2 * ((A - 1) - (A + 1) * cos(w0)); + s->a2 = (A + 1) - (A - 1) * cos(w0) - beta * alpha; + s->b0 = A * ((A + 1) + (A - 1) * cos(w0) + beta * alpha); + s->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0)); + s->b2 = A * ((A + 1) + (A - 1) * cos(w0) - beta * alpha); + } break; case bandpass: if (s->csg) { @@ -388,12 +623,24 @@ } break; case allpass: - s->a0 = 1 + alpha; - s->a1 = -2 * cos(w0); - s->a2 = 1 - alpha; - s->b0 = 1 - alpha; - s->b1 = -2 * cos(w0); - s->b2 = 1 + alpha; + switch (s->order) { + case 1: + s->a0 = 1.; + s->a1 = -(1. - K) / (1. + K); + s->a2 = 0.; + s->b0 = s->a1; + s->b1 = s->a0; + s->b2 = 0.; + break; + case 2: + s->a0 = 1 + alpha; + s->a1 = -2 * cos(w0); + s->a2 = 1 - alpha; + s->b0 = 1 - alpha; + s->b1 = -2 * cos(w0); + s->b2 = 1 + alpha; + break; + } break; default: av_assert0(0); @@ -408,21 +655,97 @@ s->b2 /= s->a0; s->a0 /= s->a0; + if (s->normalize && fabs(s->b0 + s->b1 + s->b2) > 1e-6) { + double factor = (s->a0 + s->a1 + s->a2) / (s->b0 + s->b1 + s->b2); + + s->b0 *= factor; + s->b1 *= factor; + s->b2 *= factor; + } + s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->channels); if (!s->cache) return AVERROR(ENOMEM); if (reset) memset(s->cache, 0, sizeof(ChanCache) * inlink->channels); - switch (inlink->format) { - case AV_SAMPLE_FMT_S16P: s->filter = biquad_s16; break; - case AV_SAMPLE_FMT_S32P: s->filter = biquad_s32; break; - case AV_SAMPLE_FMT_FLTP: s->filter = biquad_flt; break; - case AV_SAMPLE_FMT_DBLP: s->filter = biquad_dbl; break; - default: av_assert0(0); - } + switch (s->transform_type) { + case DI: + switch (inlink->format) { + case AV_SAMPLE_FMT_S16P: + s->filter = biquad_s16; + break; + case AV_SAMPLE_FMT_S32P: + s->filter = biquad_s32; + break; + case AV_SAMPLE_FMT_FLTP: + s->filter = biquad_flt; + break; + case AV_SAMPLE_FMT_DBLP: + s->filter = biquad_dbl; + break; + default: av_assert0(0); + } + break; + case DII: + switch (inlink->format) { + case AV_SAMPLE_FMT_S16P: + s->filter = biquad_dii_s16; + break; + case AV_SAMPLE_FMT_S32P: + s->filter = biquad_dii_s32; + break; + case AV_SAMPLE_FMT_FLTP: + s->filter = biquad_dii_flt; + break; + case AV_SAMPLE_FMT_DBLP: + s->filter = biquad_dii_dbl; + break; + default: av_assert0(0); + } + break; + case TDII: + switch (inlink->format) { + case AV_SAMPLE_FMT_S16P: + s->filter = biquad_tdii_s16; + break; + case AV_SAMPLE_FMT_S32P: + s->filter = biquad_tdii_s32; + break; + case AV_SAMPLE_FMT_FLTP: + s->filter = biquad_tdii_flt; + break; + case AV_SAMPLE_FMT_DBLP: + s->filter = biquad_tdii_dbl; + break; + default: av_assert0(0); + } + break; + case LATT: + switch (inlink->format) { + case AV_SAMPLE_FMT_S16P: + s->filter = biquad_latt_s16; + break; + case AV_SAMPLE_FMT_S32P: + s->filter = biquad_latt_s32; + break; + case AV_SAMPLE_FMT_FLTP: + s->filter = biquad_latt_flt; + break; + case AV_SAMPLE_FMT_DBLP: + s->filter = biquad_latt_dbl; + break; + default: av_assert0(0); + } + break; + default: + av_assert0(0); + } + + s->block_align = av_get_bytes_per_sample(inlink->format); - s->block_align = av_get_bytes_per_sample(inlink->format); + if (s->transform_type == LATT) + convert_dir2latt(s); return 0; } @@ -472,6 +795,9 @@ ThreadData td; int ch; + if (s->bypass) + return ff_filter_frame(outlink, buf); + if (av_frame_is_writable(buf)) { out_buf = buf; } else { @@ -503,127 +829,12 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags) { - BiquadsContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + int ret; - if ((!strcmp(cmd, "frequency") || !strcmp(cmd, "f")) && - (s->filter_type == equalizer || - s->filter_type == lowshelf || - s->filter_type == highshelf || - s->filter_type == bass || - s->filter_type == treble || - s->filter_type == bandpass || - s->filter_type == bandreject|| - s->filter_type == lowpass || - s->filter_type == highpass || - s->filter_type == allpass)) { - double freq; - - if (sscanf(args, "%lf", &freq) != 1) { - av_log(ctx, AV_LOG_ERROR, "Invalid frequency value.\n"); - return AVERROR(EINVAL); - } - - s->frequency = freq; - } else if ((!strcmp(cmd, "gain") || !strcmp(cmd, "g")) && - (s->filter_type == equalizer || - s->filter_type == lowshelf || - s->filter_type == highshelf || - s->filter_type == bass || - s->filter_type == treble)) { - double gain; - - if (sscanf(args, "%lf", &gain) != 1) { - av_log(ctx, AV_LOG_ERROR, "Invalid gain value.\n"); - return AVERROR(EINVAL); - } - - s->gain = av_clipd(gain, -900, 900); - } else if (!strcmp(cmd, "mix") || !strcmp(cmd, "m")) { - double mix; - - if (sscanf(args, "%lf", &mix) != 1) { - av_log(ctx, AV_LOG_ERROR, "Invalid mix value.\n"); - return AVERROR(EINVAL); - } - - s->mix = av_clipd(mix, 0, 1); - } else if ((!strcmp(cmd, "width") || !strcmp(cmd, "w")) && - (s->filter_type == equalizer || - s->filter_type == lowshelf || - s->filter_type == highshelf || - s->filter_type == bass || - s->filter_type == treble || - s->filter_type == bandpass || - s->filter_type == bandreject|| - s->filter_type == lowpass || - s->filter_type == highpass || - s->filter_type == allpass)) { - double width; - - if (sscanf(args, "%lf", &width) != 1) { - av_log(ctx, AV_LOG_ERROR, "Invalid width value.\n"); - return AVERROR(EINVAL); - } - - s->width = width; - } else if ((!strcmp(cmd, "width_type") || !strcmp(cmd, "t")) && - (s->filter_type == equalizer || - s->filter_type == lowshelf || - s->filter_type == highshelf || - s->filter_type == bass || - s->filter_type == treble || - s->filter_type == bandpass || - s->filter_type == bandreject|| - s->filter_type == lowpass || - s->filter_type == highpass || - s->filter_type == allpass)) { - char width_type; - - if (sscanf(args, "%c", &width_type) != 1) { - av_log(ctx, AV_LOG_ERROR, "Invalid width_type value.\n"); - return AVERROR(EINVAL); - } - - switch (width_type) { - case 'h': width_type = HERTZ; break; - case 'q': width_type = QFACTOR; break; - case 'o': width_type = OCTAVE; break; - case 's': width_type = SLOPE; break; - case 'k': width_type = KHERTZ; break; - default: - av_log(ctx, AV_LOG_ERROR, "Invalid width_type value: %c\n", width_type); - return AVERROR(EINVAL); - } - - s->width_type = width_type; - } else if ((!strcmp(cmd, "a0") || - !strcmp(cmd, "a1") || - !strcmp(cmd, "a2") || - !strcmp(cmd, "b0") || - !strcmp(cmd, "b1") || - !strcmp(cmd, "b2")) && - s->filter_type == biquad) { - double value; - - if (sscanf(args, "%lf", &value) != 1) { - av_log(ctx, AV_LOG_ERROR, "Invalid biquad value.\n"); - return AVERROR(EINVAL); - } - - if (!strcmp(cmd, "a0")) - s->a0 = value; - else if (!strcmp(cmd, "a1")) - s->a1 = value; - else if (!strcmp(cmd, "a2")) - s->a2 = value; - else if (!strcmp(cmd, "b0")) - s->b0 = value; - else if (!strcmp(cmd, "b1")) - s->b1 = value; - else if (!strcmp(cmd, "b2")) - s->b2 = value; - } + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; return config_filter(outlink, 0); } @@ -654,19 +865,19 @@ }; #define OFFSET(x) offsetof(BiquadsContext, x) -#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM +#define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM #define DEFINE_BIQUAD_FILTER(name_, description_) \ AVFILTER_DEFINE_CLASS(name_); \ -static av_cold int name_##_init(AVFilterContext *ctx) \ +static av_cold int name_##_init(AVFilterContext *ctx) \ { \ BiquadsContext *s = ctx->priv; \ - s->class = &name_##_class; \ s->filter_type = name_; \ - return init(ctx); \ + return 0; \ } \ \ -AVFilter ff_af_##name_ = { \ +AVFilter ff_af_##name_ = { \ .name = #name_, \ .description = NULL_IF_CONFIG_SMALL(description_), \ .priv_size = sizeof(BiquadsContext), \ @@ -699,13 +910,28 @@ {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, + {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, + {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, + {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, + {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, + {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, + {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, + {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, + {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, {NULL} }; DEFINE_BIQUAD_FILTER(equalizer, "Apply two-pole peaking equalization (EQ) filter."); #endif /* CONFIG_EQUALIZER_FILTER */ -#if CONFIG_BASS_FILTER -static const AVOption bass_options[] = { +#if CONFIG_BASS_FILTER || CONFIG_LOWSHELF_FILTER +static const AVOption bass_lowshelf_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS}, {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS}, {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, @@ -719,17 +945,42 @@ {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, + {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, + {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, + {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, + {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, + {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, + {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, + {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, + {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, + {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, + {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, {NULL} }; +#if CONFIG_BASS_FILTER +#define bass_options bass_lowshelf_options DEFINE_BIQUAD_FILTER(bass, "Boost or cut lower frequencies."); #endif /* CONFIG_BASS_FILTER */ -#if CONFIG_TREBLE_FILTER -static const AVOption treble_options[] = { + +#if CONFIG_LOWSHELF_FILTER +#define lowshelf_options bass_lowshelf_options +DEFINE_BIQUAD_FILTER(lowshelf, "Apply a low shelf filter."); +#endif /* CONFIG_LOWSHELF_FILTER */ +#endif /* CONFIG_BASS_FILTER || CONFIG LOWSHELF_FILTER */ +#if CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER +static const AVOption treble_highshelf_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, @@ -743,15 +994,40 @@ {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, + {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, + {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, + {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, + {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, + {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, + {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, + {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, + {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, + {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, + {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, {NULL} }; +#if CONFIG_TREBLE_FILTER +#define treble_options treble_highshelf_options DEFINE_BIQUAD_FILTER(treble, "Boost or cut upper frequencies."); #endif /* CONFIG_TREBLE_FILTER */ + +#if CONFIG_HIGHSHELF_FILTER +#define highshelf_options treble_highshelf_options +DEFINE_BIQUAD_FILTER(highshelf, "Apply a high shelf filter."); +#endif /* CONFIG_HIGHSHELF_FILTER */ +#endif /* CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER */ #if CONFIG_BANDPASS_FILTER static const AVOption bandpass_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, @@ -770,6 +1046,21 @@ {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, + {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, + {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, + {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, + {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, + {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, + {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, + {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, + {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, {NULL} }; @@ -792,6 +1083,21 @@ {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, + {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, + {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, + {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, + {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, + {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, + {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, + {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, + {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, {NULL} }; @@ -810,12 +1116,27 @@ {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, - {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, - {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, + {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, + {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, + {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, + {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, + {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, + {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, + {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, + {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, + {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, + {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, {NULL} }; @@ -834,12 +1155,27 @@ {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, - {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, - {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, + {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, + {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, + {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, + {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, + {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, + {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, + {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, + {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, + {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, + {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, {NULL} }; @@ -862,71 +1198,55 @@ {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, + {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"order", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, + {"o", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, + {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, + {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, + {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, + {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, + {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, + {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, + {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, + {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, {NULL} }; DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter."); #endif /* CONFIG_ALLPASS_FILTER */ -#if CONFIG_LOWSHELF_FILTER -static const AVOption lowshelf_options[] = { - {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS}, - {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS}, - {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, - {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, - {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, - {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, - {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, - {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, - {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, - {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, - {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, - {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, - {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, - {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, - {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, - {NULL} -}; - -DEFINE_BIQUAD_FILTER(lowshelf, "Apply a low shelf filter."); -#endif /* CONFIG_LOWSHELF_FILTER */ -#if CONFIG_HIGHSHELF_FILTER -static const AVOption highshelf_options[] = { - {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, - {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, - {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, - {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, - {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, - {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, - {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, - {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, - {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"}, - {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, - {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, - {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, - {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, - {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, - {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, - {NULL} -}; - -DEFINE_BIQUAD_FILTER(highshelf, "Apply a high shelf filter."); -#endif /* CONFIG_HIGHSHELF_FILTER */ #if CONFIG_BIQUAD_FILTER static const AVOption biquad_options[] = { - {"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, - {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, - {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, - {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, - {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, - {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"a0", NULL, OFFSET(oa0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS}, + {"a1", NULL, OFFSET(oa1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"a2", NULL, OFFSET(oa2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"b0", NULL, OFFSET(ob0), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"b1", NULL, OFFSET(ob1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, + {"b2", NULL, OFFSET(ob2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, + {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, + {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, + {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, + {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, + {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, + {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, + {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, + {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, + {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, + {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, + {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, {NULL} }; diff -Nru ffmpeg-4.2.2/libavfilter/af_channelmap.c ffmpeg-4.4/libavfilter/af_channelmap.c --- ffmpeg-4.2.2/libavfilter/af_channelmap.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_channelmap.c 2021-04-08 21:28:39.000000000 +0000 @@ -280,28 +280,18 @@ static int channelmap_query_formats(AVFilterContext *ctx) { ChannelMapContext *s = ctx->priv; - AVFilterChannelLayouts *layouts; AVFilterChannelLayouts *channel_layouts = NULL; int ret; - layouts = ff_all_channel_counts(); - if (!layouts) { - ret = AVERROR(ENOMEM); - goto fail; - } - if ((ret = ff_add_channel_layout (&channel_layouts, s->output_layout )) < 0 || - (ret = ff_set_common_formats (ctx , ff_planar_sample_fmts() )) < 0 || + if ((ret = ff_set_common_formats (ctx, ff_planar_sample_fmts())) < 0 || (ret = ff_set_common_samplerates (ctx , ff_all_samplerates() )) < 0 || - (ret = ff_channel_layouts_ref (layouts , &ctx->inputs[0]->out_channel_layouts)) < 0 || - (ret = ff_channel_layouts_ref (channel_layouts , &ctx->outputs[0]->in_channel_layouts)) < 0) - goto fail; + (ret = ff_add_channel_layout(&channel_layouts, s->output_layout)) < 0 || + (ret = ff_channel_layouts_ref(channel_layouts, + &ctx->outputs[0]->incfg.channel_layouts)) < 0) + return ret; - return 0; -fail: - if (layouts) - av_freep(&layouts->channel_layouts); - av_freep(&layouts); - return ret; + return ff_channel_layouts_ref(ff_all_channel_counts(), + &ctx->inputs[0]->outcfg.channel_layouts); } static int channelmap_filter_frame(AVFilterLink *inlink, AVFrame *buf) diff -Nru ffmpeg-4.2.2/libavfilter/af_channelsplit.c ffmpeg-4.4/libavfilter/af_channelsplit.c --- ffmpeg-4.2.2/libavfilter/af_channelsplit.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_channelsplit.c 2021-04-08 21:28:39.000000000 +0000 @@ -117,7 +117,7 @@ return ret; if ((ret = ff_add_channel_layout(&in_layouts, s->channel_layout)) < 0 || - (ret = ff_channel_layouts_ref(in_layouts, &ctx->inputs[0]->out_channel_layouts)) < 0) + (ret = ff_channel_layouts_ref(in_layouts, &ctx->inputs[0]->outcfg.channel_layouts)) < 0) return ret; for (i = 0; i < ctx->nb_outputs; i++) { @@ -125,7 +125,7 @@ uint64_t channel = av_channel_layout_extract_channel(s->channel_layout, s->map[i]); if ((ret = ff_add_channel_layout(&out_layouts, channel)) < 0 || - (ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->in_channel_layouts)) < 0) + (ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->incfg.channel_layouts)) < 0) return ret; } diff -Nru ffmpeg-4.2.2/libavfilter/af_compand.c ffmpeg-4.4/libavfilter/af_compand.c --- ffmpeg-4.2.2/libavfilter/af_compand.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_compand.c 2020-07-11 10:39:30.000000000 +0000 @@ -349,9 +349,10 @@ } if (nb_attacks > channels || nb_decays > channels) { - av_log(ctx, AV_LOG_ERROR, - "Number of attacks/decays bigger than number of channels.\n"); - return AVERROR(EINVAL); + av_log(ctx, AV_LOG_WARNING, + "Number of attacks/decays bigger than number of channels. Ignoring rest of entries.\n"); + nb_attacks = FFMIN(nb_attacks, channels); + nb_decays = FFMIN(nb_decays, channels); } uninit(ctx); @@ -534,7 +535,7 @@ s->delay_frame->nb_samples = s->delay_samples; s->delay_frame->channel_layout = outlink->channel_layout; - err = av_frame_get_buffer(s->delay_frame, 32); + err = av_frame_get_buffer(s->delay_frame, 0); if (err) return err; diff -Nru ffmpeg-4.2.2/libavfilter/af_compensationdelay.c ffmpeg-4.4/libavfilter/af_compensationdelay.c --- ffmpeg-4.2.2/libavfilter/af_compensationdelay.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_compensationdelay.c 2021-04-08 21:28:39.000000000 +0000 @@ -115,7 +115,7 @@ s->delay_frame->nb_samples = new_size; s->delay_frame->channel_layout = inlink->channel_layout; - return av_frame_get_buffer(s->delay_frame, 32); + return av_frame_get_buffer(s->delay_frame, 0); } static int filter_frame(AVFilterLink *inlink, AVFrame *in) @@ -127,7 +127,7 @@ const unsigned delay = s->delay; const double dry = s->dry; const double wet = s->wet; - unsigned r_ptr, w_ptr; + unsigned r_ptr, w_ptr = 0; AVFrame *out; int n, ch; diff -Nru ffmpeg-4.2.2/libavfilter/af_crossfeed.c ffmpeg-4.4/libavfilter/af_crossfeed.c --- ffmpeg-4.2.2/libavfilter/af_crossfeed.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_crossfeed.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,14 +28,14 @@ double range; double strength; + double slope; double level_in; double level_out; double a0, a1, a2; double b0, b1, b2; - double i1, i2; - double o1, o2; + double w1, w2; } CrossfeedContext; static int query_formats(AVFilterContext *ctx) @@ -62,7 +62,7 @@ double w0 = 2 * M_PI * (1. - s->range) * 2100 / inlink->sample_rate; double alpha; - alpha = sin(w0) / 2 * sqrt(2 * (1 / 0.5 - 1) + 2); + alpha = sin(w0) / 2 * sqrt((A + 1 / A) * (1 / s->slope - 1) + 2); s->a0 = (A + 1) + (A - 1) * cos(w0) + 2 * sqrt(A) * alpha; s->a1 = -2 * ((A - 1) + (A + 1) * cos(w0)); @@ -91,8 +91,8 @@ const double b0 = s->b0; const double b1 = s->b1; const double b2 = s->b2; - const double a1 = s->a1; - const double a2 = s->a2; + const double a1 = -s->a1; + const double a2 = -s->a2; AVFrame *out; double *dst; int n; @@ -112,12 +112,10 @@ for (n = 0; n < out->nb_samples; n++, src += 2, dst += 2) { double mid = (src[0] + src[1]) * level_in * .5; double side = (src[0] - src[1]) * level_in * .5; - double oside = side * b0 + s->i1 * b1 + s->i2 * b2 - s->o1 * a1 - s->o2 * a2; + double oside = side * b0 + s->w1; - s->i2 = s->i1; - s->i1 = side; - s->o2 = s->o1; - s->o1 = oside; + s->w1 = b1 * side + s->w2 + a1 * oside; + s->w2 = b2 * side + a2 * oside; if (ctx->is_disabled) { dst[0] = src[0]; @@ -133,12 +131,25 @@ 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) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + #define OFFSET(x) offsetof(CrossfeedContext, x) -#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption crossfeed_options[] = { { "strength", "set crossfeed strength", OFFSET(strength), AV_OPT_TYPE_DOUBLE, {.dbl=.2}, 0, 1, FLAGS }, { "range", "set soundstage wideness", OFFSET(range), AV_OPT_TYPE_DOUBLE, {.dbl=.5}, 0, 1, FLAGS }, + { "slope", "set curve slope", OFFSET(slope), AV_OPT_TYPE_DOUBLE, {.dbl=.5}, .01, 1, FLAGS }, { "level_in", "set level in", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=.9}, 0, 1, FLAGS }, { "level_out", "set level out", OFFSET(level_out), AV_OPT_TYPE_DOUBLE, {.dbl=1.}, 0, 1, FLAGS }, { NULL } @@ -173,4 +184,5 @@ .inputs = inputs, .outputs = outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_crystalizer.c ffmpeg-4.4/libavfilter/af_crystalizer.c --- ffmpeg-4.2.2/libavfilter/af_crystalizer.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_crystalizer.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,15 +29,14 @@ float mult; int clip; AVFrame *prev; - void (*filter)(void **dst, void **prv, const void **src, - int nb_samples, int channels, float mult, int clip); + int (*filter)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } CrystalizerContext; #define OFFSET(x) offsetof(CrystalizerContext, x) -#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption crystalizer_options[] = { - { "i", "set intensity", OFFSET(mult), AV_OPT_TYPE_FLOAT, {.dbl=2.0}, 0, 10, A }, + { "i", "set intensity", OFFSET(mult), AV_OPT_TYPE_FLOAT, {.dbl=2.0},-10, 10, A }, { "c", "enable clipping", OFFSET(clip), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, A }, { NULL } }; @@ -74,42 +73,71 @@ return ff_set_common_samplerates(ctx, formats); } -static void filter_flt(void **d, void **p, const void **s, - int nb_samples, int channels, - float mult, int clip) +typedef struct ThreadData { + void **d; + void **p; + const void **s; + int nb_samples; + int channels; + float mult; + int clip; +} ThreadData; + +static int filter_flt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - const float *src = s[0]; - float *dst = d[0]; + ThreadData *td = arg; + void **d = td->d; + void **p = td->p; + const void **s = td->s; + const int nb_samples = td->nb_samples; + const int channels = td->channels; + const float mult = td->mult; + const int clip = td->clip; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; float *prv = p[0]; int n, c; - for (n = 0; n < nb_samples; n++) { - for (c = 0; c < channels; c++) { - float current = src[c]; + for (c = start; c < end; c++) { + const float *src = s[0]; + float *dst = d[0]; + for (n = 0; n < nb_samples; n++) { + float current = src[c]; dst[c] = current + (current - prv[c]) * mult; prv[c] = current; if (clip) { dst[c] = av_clipf(dst[c], -1, 1); } - } - dst += c; - src += c; + dst += channels; + src += channels; + } } + + return 0; } -static void filter_dbl(void **d, void **p, const void **s, - int nb_samples, int channels, - float mult, int clip) +static int filter_dbl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - const double *src = s[0]; - double *dst = d[0]; + ThreadData *td = arg; + void **d = td->d; + void **p = td->p; + const void **s = td->s; + const int nb_samples = td->nb_samples; + const int channels = td->channels; + double mult = td->mult; + const int clip = td->clip; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; double *prv = p[0]; int n, c; - for (n = 0; n < nb_samples; n++) { - for (c = 0; c < channels; c++) { + for (c = start; c < end; c++) { + const double *src = s[0]; + double *dst = d[0]; + + for (n = 0; n < nb_samples; n++) { double current = src[c]; dst[c] = current + (current - prv[c]) * mult; @@ -117,20 +145,30 @@ if (clip) { dst[c] = av_clipd(dst[c], -1, 1); } - } - dst += c; - src += c; + dst += channels; + src += channels; + } } + + return 0; } -static void filter_fltp(void **d, void **p, const void **s, - int nb_samples, int channels, - float mult, int clip) +static int filter_fltp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { + ThreadData *td = arg; + void **d = td->d; + void **p = td->p; + const void **s = td->s; + const int nb_samples = td->nb_samples; + const int channels = td->channels; + float mult = td->mult; + const int clip = td->clip; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; int n, c; - for (c = 0; c < channels; c++) { + for (c = start; c < end; c++) { const float *src = s[c]; float *dst = d[c]; float *prv = p[c]; @@ -145,15 +183,25 @@ } } } + + return 0; } -static void filter_dblp(void **d, void **p, const void **s, - int nb_samples, int channels, - float mult, int clip) +static int filter_dblp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { + ThreadData *td = arg; + void **d = td->d; + void **p = td->p; + const void **s = td->s; + const int nb_samples = td->nb_samples; + const int channels = td->channels; + const double mult = td->mult; + const int clip = td->clip; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; int n, c; - for (c = 0; c < channels; c++) { + for (c = start; c < end; c++) { const double *src = s[c]; double *dst = d[c]; double *prv = p[c]; @@ -168,6 +216,149 @@ } } } + + return 0; +} + +static int ifilter_flt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ThreadData *td = arg; + void **d = td->d; + void **p = td->p; + const void **s = td->s; + const int nb_samples = td->nb_samples; + const int channels = td->channels; + const float mult = -td->mult; + const float div = -td->mult + 1.f; + const int clip = td->clip; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; + float *prv = p[0]; + int n, c; + + for (c = start; c < end; c++) { + const float *src = s[0]; + float *dst = d[0]; + + for (n = 0; n < nb_samples; n++) { + float current = src[c]; + dst[c] = (current + prv[c] * mult) / div; + prv[c] = dst[c]; + if (clip) { + dst[c] = av_clipf(dst[c], -1, 1); + } + + dst += channels; + src += channels; + } + } + + return 0; +} + +static int ifilter_dbl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ThreadData *td = arg; + void **d = td->d; + void **p = td->p; + const void **s = td->s; + const int nb_samples = td->nb_samples; + const int channels = td->channels; + const double mult = -td->mult; + const double div = -td->mult + 1.f; + const int clip = td->clip; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; + double *prv = p[0]; + int n, c; + + for (c = start; c < end; c++) { + const double *src = s[0]; + double *dst = d[0]; + + for (n = 0; n < nb_samples; n++) { + double current = src[c]; + + dst[c] = (current + prv[c] * mult) / div; + prv[c] = dst[c]; + if (clip) { + dst[c] = av_clipd(dst[c], -1, 1); + } + + dst += channels; + src += channels; + } + } + + return 0; +} + +static int ifilter_fltp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ThreadData *td = arg; + void **d = td->d; + void **p = td->p; + const void **s = td->s; + const int nb_samples = td->nb_samples; + const int channels = td->channels; + const float mult = -td->mult; + const float div = -td->mult + 1.f; + const int clip = td->clip; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; + int n, c; + + for (c = start; c < end; c++) { + const float *src = s[c]; + float *dst = d[c]; + float *prv = p[c]; + + for (n = 0; n < nb_samples; n++) { + float current = src[n]; + + dst[n] = (current + prv[0] * mult) / div; + prv[0] = dst[n]; + if (clip) { + dst[n] = av_clipf(dst[n], -1, 1); + } + } + } + + return 0; +} + +static int ifilter_dblp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ThreadData *td = arg; + void **d = td->d; + void **p = td->p; + const void **s = td->s; + const int nb_samples = td->nb_samples; + const int channels = td->channels; + const double mult = -td->mult; + const double div = -td->mult + 1.f; + const int clip = td->clip; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; + int n, c; + + for (c = start; c < end; c++) { + const double *src = s[c]; + double *dst = d[c]; + double *prv = p[c]; + + for (n = 0; n < nb_samples; n++) { + double current = src[n]; + + dst[n] = (current + prv[0] * mult) / div; + prv[0] = dst[n]; + if (clip) { + dst[n] = av_clipd(dst[n], -1, 1); + } + } + } + + return 0; } static int config_input(AVFilterLink *inlink) @@ -176,10 +367,10 @@ CrystalizerContext *s = ctx->priv; switch (inlink->format) { - case AV_SAMPLE_FMT_FLT: s->filter = filter_flt; break; - case AV_SAMPLE_FMT_DBL: s->filter = filter_dbl; break; - case AV_SAMPLE_FMT_FLTP: s->filter = filter_fltp; break; - case AV_SAMPLE_FMT_DBLP: s->filter = filter_dblp; break; + case AV_SAMPLE_FMT_FLT: s->filter = s->mult >= 0.f ? filter_flt : ifilter_flt; break; + case AV_SAMPLE_FMT_DBL: s->filter = s->mult >= 0.f ? filter_dbl : ifilter_dbl; break; + case AV_SAMPLE_FMT_FLTP: s->filter = s->mult >= 0.f ? filter_fltp : ifilter_fltp; break; + case AV_SAMPLE_FMT_DBLP: s->filter = s->mult >= 0.f ? filter_dblp : ifilter_dblp; break; } return 0; @@ -191,6 +382,7 @@ AVFilterLink *outlink = ctx->outputs[0]; CrystalizerContext *s = ctx->priv; AVFrame *out; + ThreadData td; if (!s->prev) { s->prev = ff_get_audio_buffer(inlink, 1); @@ -211,8 +403,15 @@ av_frame_copy_props(out, in); } - s->filter((void **)out->extended_data, (void **)s->prev->extended_data, (const void **)in->extended_data, - in->nb_samples, in->channels, s->mult, s->clip); + td.d = (void **)out->extended_data; + td.s = (const void **)in->extended_data; + td.p = (void **)s->prev->extended_data; + td.nb_samples = in->nb_samples; + td.channels = in->channels; + td.mult = ctx->is_disabled ? 0.f : s->mult; + td.clip = s->clip; + ctx->internal->execute(ctx, s->filter, &td, NULL, FFMIN(inlink->channels, + ff_filter_get_nb_threads(ctx))); if (out != in) av_frame_free(&in); @@ -227,6 +426,18 @@ av_frame_free(&s->prev); } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + static const AVFilterPad inputs[] = { { .name = "default", @@ -247,11 +458,14 @@ AVFilter ff_af_crystalizer = { .name = "crystalizer", - .description = NULL_IF_CONFIG_SMALL("Simple expand audio dynamic range filter."), + .description = NULL_IF_CONFIG_SMALL("Simple audio noise sharpening filter."), .query_formats = query_formats, .priv_size = sizeof(CrystalizerContext), .priv_class = &crystalizer_class, .uninit = uninit, .inputs = inputs, .outputs = outputs, + .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_dynaudnorm.c ffmpeg-4.4/libavfilter/af_dynaudnorm.c --- ffmpeg-4.2.2/libavfilter/af_dynaudnorm.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_dynaudnorm.c 2021-04-08 21:28:39.000000000 +0000 @@ -29,7 +29,10 @@ #include "libavutil/avassert.h" #include "libavutil/opt.h" -#define FF_BUFQUEUE_SIZE 302 +#define MIN_FILTER_SIZE 3 +#define MAX_FILTER_SIZE 301 + +#define FF_BUFQUEUE_SIZE (MAX_FILTER_SIZE + 1) #include "libavfilter/bufferqueue.h" #include "audio.h" @@ -37,11 +40,16 @@ #include "filters.h" #include "internal.h" +typedef struct local_gain { + double max_gain; + double threshold; +} local_gain; + typedef struct cqueue { double *elements; int size; + int max_size; int nb_elements; - int first; } cqueue; typedef struct DynamicAudioNormalizerContext { @@ -60,37 +68,48 @@ double max_amplification; double target_rms; double compress_factor; + double threshold; double *prev_amplification_factor; double *dc_correction_value; double *compress_threshold; - double *fade_factors[2]; double *weights; int channels; - int delay; int eof; int64_t pts; cqueue **gain_history_original; cqueue **gain_history_minimum; cqueue **gain_history_smoothed; + cqueue **threshold_history; cqueue *is_enabled; } DynamicAudioNormalizerContext; #define OFFSET(x) offsetof(DynamicAudioNormalizerContext, x) -#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption dynaudnorm_options[] = { - { "f", "set the frame length in msec", OFFSET(frame_len_msec), AV_OPT_TYPE_INT, {.i64 = 500}, 10, 8000, FLAGS }, - { "g", "set the filter size", OFFSET(filter_size), AV_OPT_TYPE_INT, {.i64 = 31}, 3, 301, FLAGS }, - { "p", "set the peak value", OFFSET(peak_value), AV_OPT_TYPE_DOUBLE, {.dbl = 0.95}, 0.0, 1.0, FLAGS }, - { "m", "set the max amplification", OFFSET(max_amplification), AV_OPT_TYPE_DOUBLE, {.dbl = 10.0}, 1.0, 100.0, FLAGS }, - { "r", "set the target RMS", OFFSET(target_rms), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS }, - { "n", "set channel coupling", OFFSET(channels_coupled), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, - { "c", "set DC correction", OFFSET(dc_correction), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, - { "b", "set alternative boundary mode", OFFSET(alt_boundary_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, - { "s", "set the compress factor", OFFSET(compress_factor), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 30.0, FLAGS }, + { "framelen", "set the frame length in msec", OFFSET(frame_len_msec), AV_OPT_TYPE_INT, {.i64 = 500}, 10, 8000, FLAGS }, + { "f", "set the frame length in msec", OFFSET(frame_len_msec), AV_OPT_TYPE_INT, {.i64 = 500}, 10, 8000, FLAGS }, + { "gausssize", "set the filter size", OFFSET(filter_size), AV_OPT_TYPE_INT, {.i64 = 31}, 3, 301, FLAGS }, + { "g", "set the filter size", OFFSET(filter_size), AV_OPT_TYPE_INT, {.i64 = 31}, 3, 301, FLAGS }, + { "peak", "set the peak value", OFFSET(peak_value), AV_OPT_TYPE_DOUBLE, {.dbl = 0.95}, 0.0, 1.0, FLAGS }, + { "p", "set the peak value", OFFSET(peak_value), AV_OPT_TYPE_DOUBLE, {.dbl = 0.95}, 0.0, 1.0, FLAGS }, + { "maxgain", "set the max amplification", OFFSET(max_amplification), AV_OPT_TYPE_DOUBLE, {.dbl = 10.0}, 1.0, 100.0, FLAGS }, + { "m", "set the max amplification", OFFSET(max_amplification), AV_OPT_TYPE_DOUBLE, {.dbl = 10.0}, 1.0, 100.0, FLAGS }, + { "targetrms", "set the target RMS", OFFSET(target_rms), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS }, + { "r", "set the target RMS", OFFSET(target_rms), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS }, + { "coupling", "set channel coupling", OFFSET(channels_coupled), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, + { "n", "set channel coupling", OFFSET(channels_coupled), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, + { "correctdc", "set DC correction", OFFSET(dc_correction), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, + { "c", "set DC correction", OFFSET(dc_correction), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, + { "altboundary", "set alternative boundary mode", OFFSET(alt_boundary_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, + { "b", "set alternative boundary mode", OFFSET(alt_boundary_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, + { "compress", "set the compress factor", OFFSET(compress_factor), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 30.0, FLAGS }, + { "s", "set the compress factor", OFFSET(compress_factor), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 30.0, FLAGS }, + { "threshold", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS }, + { "t", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS }, { NULL } }; @@ -101,8 +120,8 @@ DynamicAudioNormalizerContext *s = ctx->priv; if (!(s->filter_size & 1)) { - av_log(ctx, AV_LOG_ERROR, "filter size %d is invalid. Must be an odd value.\n", s->filter_size); - return AVERROR(EINVAL); + av_log(ctx, AV_LOG_WARNING, "filter size %d is invalid. Changing to an odd value.\n", s->filter_size); + s->filter_size |= 1; } return 0; @@ -144,30 +163,22 @@ return frame_size + (frame_size % 2); } -static void precalculate_fade_factors(double *fade_factors[2], int frame_len) -{ - const double step_size = 1.0 / frame_len; - int pos; - - for (pos = 0; pos < frame_len; pos++) { - fade_factors[0][pos] = 1.0 - (step_size * (pos + 1.0)); - fade_factors[1][pos] = 1.0 - fade_factors[0][pos]; - } -} - -static cqueue *cqueue_create(int size) +static cqueue *cqueue_create(int size, int max_size) { cqueue *q; + if (max_size < size) + return NULL; + q = av_malloc(sizeof(cqueue)); if (!q) return NULL; + q->max_size = max_size; q->size = size; q->nb_elements = 0; - q->first = 0; - q->elements = av_malloc_array(size, sizeof(double)); + q->elements = av_malloc_array(max_size, sizeof(double)); if (!q->elements) { av_free(q); return NULL; @@ -190,17 +201,14 @@ static int cqueue_empty(cqueue *q) { - return !q->nb_elements; + return q->nb_elements <= 0; } static int cqueue_enqueue(cqueue *q, double element) { - int i; - - av_assert2(q->nb_elements != q->size); + av_assert2(q->nb_elements < q->max_size); - i = (q->first + q->nb_elements) % q->size; - q->elements[i] = element; + q->elements[q->nb_elements] = element; q->nb_elements++; return 0; @@ -209,15 +217,15 @@ static double cqueue_peek(cqueue *q, int index) { av_assert2(index < q->nb_elements); - return q->elements[(q->first + index) % q->size]; + return q->elements[index]; } static int cqueue_dequeue(cqueue *q, double *element) { av_assert2(!cqueue_empty(q)); - *element = q->elements[q->first]; - q->first = (q->first + 1) % q->size; + *element = q->elements[0]; + memmove(&q->elements[0], &q->elements[1], (q->nb_elements - 1) * sizeof(double)); q->nb_elements--; return 0; @@ -227,12 +235,34 @@ { av_assert2(!cqueue_empty(q)); - q->first = (q->first + 1) % q->size; + memmove(&q->elements[0], &q->elements[1], (q->nb_elements - 1) * sizeof(double)); q->nb_elements--; return 0; } +static void cqueue_resize(cqueue *q, int new_size) +{ + av_assert2(q->max_size >= new_size); + av_assert2(MIN_FILTER_SIZE <= new_size); + + if (new_size > q->nb_elements) { + const int side = (new_size - q->nb_elements) / 2; + + memmove(q->elements + side, q->elements, sizeof(double) * q->nb_elements); + for (int i = 0; i < side; i++) + q->elements[i] = q->elements[side]; + q->nb_elements = new_size - 1 - side; + } else { + int count = (q->size - new_size + 1) / 2; + + while (count-- > 0) + cqueue_pop(q); + } + + q->size = new_size; +} + static void init_gaussian_filter(DynamicAudioNormalizerContext *s) { double total_weight = 0.0; @@ -268,8 +298,6 @@ av_freep(&s->prev_amplification_factor); av_freep(&s->dc_correction_value); av_freep(&s->compress_threshold); - av_freep(&s->fade_factors[0]); - av_freep(&s->fade_factors[1]); for (c = 0; c < s->channels; c++) { if (s->gain_history_original) @@ -278,11 +306,14 @@ cqueue_free(s->gain_history_minimum[c]); if (s->gain_history_smoothed) cqueue_free(s->gain_history_smoothed[c]); + if (s->threshold_history) + cqueue_free(s->threshold_history[c]); } av_freep(&s->gain_history_original); av_freep(&s->gain_history_minimum); av_freep(&s->gain_history_smoothed); + av_freep(&s->threshold_history); cqueue_free(s->is_enabled); s->is_enabled = NULL; @@ -300,51 +331,50 @@ uninit(ctx); + s->channels = inlink->channels; s->frame_len = frame_size(inlink->sample_rate, s->frame_len_msec); av_log(ctx, AV_LOG_DEBUG, "frame len %d\n", s->frame_len); - s->fade_factors[0] = av_malloc_array(s->frame_len, sizeof(*s->fade_factors[0])); - s->fade_factors[1] = av_malloc_array(s->frame_len, sizeof(*s->fade_factors[1])); - s->prev_amplification_factor = av_malloc_array(inlink->channels, sizeof(*s->prev_amplification_factor)); s->dc_correction_value = av_calloc(inlink->channels, sizeof(*s->dc_correction_value)); s->compress_threshold = av_calloc(inlink->channels, sizeof(*s->compress_threshold)); s->gain_history_original = av_calloc(inlink->channels, sizeof(*s->gain_history_original)); s->gain_history_minimum = av_calloc(inlink->channels, sizeof(*s->gain_history_minimum)); s->gain_history_smoothed = av_calloc(inlink->channels, sizeof(*s->gain_history_smoothed)); - s->weights = av_malloc_array(s->filter_size, sizeof(*s->weights)); - s->is_enabled = cqueue_create(s->filter_size); + s->threshold_history = av_calloc(inlink->channels, sizeof(*s->threshold_history)); + s->weights = av_malloc_array(MAX_FILTER_SIZE, sizeof(*s->weights)); + s->is_enabled = cqueue_create(s->filter_size, MAX_FILTER_SIZE); if (!s->prev_amplification_factor || !s->dc_correction_value || - !s->compress_threshold || !s->fade_factors[0] || !s->fade_factors[1] || + !s->compress_threshold || !s->gain_history_original || !s->gain_history_minimum || - !s->gain_history_smoothed || !s->is_enabled || !s->weights) + !s->gain_history_smoothed || !s->threshold_history || + !s->is_enabled || !s->weights) return AVERROR(ENOMEM); for (c = 0; c < inlink->channels; c++) { s->prev_amplification_factor[c] = 1.0; - s->gain_history_original[c] = cqueue_create(s->filter_size); - s->gain_history_minimum[c] = cqueue_create(s->filter_size); - s->gain_history_smoothed[c] = cqueue_create(s->filter_size); + s->gain_history_original[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE); + s->gain_history_minimum[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE); + s->gain_history_smoothed[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE); + s->threshold_history[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE); if (!s->gain_history_original[c] || !s->gain_history_minimum[c] || - !s->gain_history_smoothed[c]) + !s->gain_history_smoothed[c] || !s->threshold_history[c]) return AVERROR(ENOMEM); } - precalculate_fade_factors(s->fade_factors, s->frame_len); init_gaussian_filter(s); - s->channels = inlink->channels; - s->delay = s->filter_size; - return 0; } -static inline double fade(double prev, double next, int pos, - double *fade_factors[2]) +static inline double fade(double prev, double next, int pos, int length) { - return fade_factors[0][pos] * prev + fade_factors[1][pos] * next; + const double step_size = 1.0 / length; + const double f0 = 1.0 - (step_size * (pos + 1.0)); + const double f1 = 1.0 - f0; + return f0 * prev + f1 * next; } static inline double pow_2(const double value) @@ -407,12 +437,18 @@ return FFMAX(sqrt(rms_value), DBL_EPSILON); } -static double get_max_local_gain(DynamicAudioNormalizerContext *s, AVFrame *frame, - int channel) +static local_gain get_max_local_gain(DynamicAudioNormalizerContext *s, AVFrame *frame, + int channel) { - const double maximum_gain = s->peak_value / find_peak_magnitude(frame, channel); + const double peak_magnitude = find_peak_magnitude(frame, channel); + const double maximum_gain = s->peak_value / peak_magnitude; const double rms_gain = s->target_rms > DBL_EPSILON ? (s->target_rms / compute_frame_rms(frame, channel)) : DBL_MAX; - return bound(s->max_amplification, FFMIN(maximum_gain, rms_gain)); + local_gain gain; + + gain.threshold = peak_magnitude > s->threshold; + gain.max_gain = bound(s->max_amplification, FFMIN(maximum_gain, rms_gain)); + + return gain; } static double minimum_filter(cqueue *q) @@ -427,38 +463,41 @@ return min; } -static double gaussian_filter(DynamicAudioNormalizerContext *s, cqueue *q) +static double gaussian_filter(DynamicAudioNormalizerContext *s, cqueue *q, cqueue *tq) { - double result = 0.0; + double result = 0.0, tsum = 0.0; int i; for (i = 0; i < cqueue_size(q); i++) { - result += cqueue_peek(q, i) * s->weights[i]; + tsum += cqueue_peek(tq, i) * s->weights[i]; + result += cqueue_peek(q, i) * s->weights[i] * cqueue_peek(tq, i); } + if (tsum == 0.0) + result = 1.0; + return result; } static void update_gain_history(DynamicAudioNormalizerContext *s, int channel, - double current_gain_factor) + local_gain gain) { - if (cqueue_empty(s->gain_history_original[channel]) || - cqueue_empty(s->gain_history_minimum[channel])) { + if (cqueue_empty(s->gain_history_original[channel])) { const int pre_fill_size = s->filter_size / 2; - const double initial_value = s->alt_boundary_mode ? current_gain_factor : 1.0; + const double initial_value = s->alt_boundary_mode ? gain.max_gain : s->peak_value; s->prev_amplification_factor[channel] = initial_value; while (cqueue_size(s->gain_history_original[channel]) < pre_fill_size) { cqueue_enqueue(s->gain_history_original[channel], initial_value); + cqueue_enqueue(s->threshold_history[channel], gain.threshold); } } - cqueue_enqueue(s->gain_history_original[channel], current_gain_factor); + cqueue_enqueue(s->gain_history_original[channel], gain.max_gain); while (cqueue_size(s->gain_history_original[channel]) >= s->filter_size) { double minimum; - av_assert0(cqueue_size(s->gain_history_original[channel]) == s->filter_size); if (cqueue_empty(s->gain_history_minimum[channel])) { const int pre_fill_size = s->filter_size / 2; @@ -476,17 +515,22 @@ cqueue_enqueue(s->gain_history_minimum[channel], minimum); + cqueue_enqueue(s->threshold_history[channel], gain.threshold); + cqueue_pop(s->gain_history_original[channel]); } while (cqueue_size(s->gain_history_minimum[channel]) >= s->filter_size) { - double smoothed; - av_assert0(cqueue_size(s->gain_history_minimum[channel]) == s->filter_size); - smoothed = gaussian_filter(s, s->gain_history_minimum[channel]); + double smoothed, limit; + + smoothed = gaussian_filter(s, s->gain_history_minimum[channel], s->threshold_history[channel]); + limit = cqueue_peek(s->gain_history_original[channel], 0); + smoothed = FFMIN(smoothed, limit); cqueue_enqueue(s->gain_history_smoothed[channel], smoothed); cqueue_pop(s->gain_history_minimum[channel]); + cqueue_pop(s->threshold_history[channel]); } } @@ -514,7 +558,7 @@ s->dc_correction_value[c] = is_first_frame ? current_average_value : update_value(current_average_value, s->dc_correction_value[c], 0.1); for (i = 0; i < frame->nb_samples; i++) { - dst_ptr[i] -= fade(prev_value, s->dc_correction_value[c], i, s->fade_factors); + dst_ptr[i] -= fade(prev_value, s->dc_correction_value[c], i, frame->nb_samples); } } } @@ -587,7 +631,7 @@ for (c = 0; c < s->channels; c++) { double *const dst_ptr = (double *)frame->extended_data[c]; for (i = 0; i < frame->nb_samples; i++) { - const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, s->fade_factors); + const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, frame->nb_samples); dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]); } } @@ -606,7 +650,7 @@ dst_ptr = (double *)frame->extended_data[c]; for (i = 0; i < frame->nb_samples; i++) { - const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, s->fade_factors); + const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, frame->nb_samples); dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]); } } @@ -624,11 +668,11 @@ } if (s->channels_coupled) { - const double current_gain_factor = get_max_local_gain(s, frame, -1); + const local_gain gain = get_max_local_gain(s, frame, -1); int c; for (c = 0; c < s->channels; c++) - update_gain_history(s, c, current_gain_factor); + update_gain_history(s, c, gain); } else { int c; @@ -650,12 +694,9 @@ for (i = 0; i < frame->nb_samples && enabled; i++) { const double amplification_factor = fade(s->prev_amplification_factor[c], current_amplification_factor, i, - s->fade_factors); + frame->nb_samples); dst_ptr[i] *= amplification_factor; - - if (fabs(dst_ptr[i]) > s->peak_value) - dst_ptr[i] = copysign(s->peak_value, dst_ptr[i]); } s->prev_amplification_factor[c] = current_amplification_factor; @@ -666,23 +707,30 @@ { AVFilterContext *ctx = inlink->dst; DynamicAudioNormalizerContext *s = ctx->priv; - AVFilterLink *outlink = inlink->dst->outputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; int ret = 1; - if (!cqueue_empty(s->gain_history_smoothed[0])) { - double is_enabled; + while (((s->queue.available >= s->filter_size) || + (s->eof && s->queue.available)) && + !cqueue_empty(s->gain_history_smoothed[0])) { AVFrame *out = ff_bufqueue_get(&s->queue); + double is_enabled; cqueue_dequeue(s->is_enabled, &is_enabled); amplify_frame(s, out, is_enabled > 0.); + s->pts = out->pts + out->nb_samples; ret = ff_filter_frame(outlink, out); } av_frame_make_writable(in); - cqueue_enqueue(s->is_enabled, !ctx->is_disabled); analyze_frame(s, in); - ff_bufqueue_add(ctx, &s->queue, in); + if (!s->eof) { + ff_bufqueue_add(ctx, &s->queue, in); + cqueue_enqueue(s->is_enabled, !ctx->is_disabled); + } else { + av_frame_free(&in); + } return ret; } @@ -708,7 +756,6 @@ } } - s->delay--; return filter_frame(inlink, out); } @@ -723,9 +770,8 @@ } else if (s->queue.available) { AVFrame *out = ff_bufqueue_get(&s->queue); - s->pts = out->pts; + s->pts = out->pts + out->nb_samples; ret = ff_filter_frame(outlink, out); - s->delay = s->queue.available; } return ret; @@ -752,7 +798,7 @@ return ret; } - if (ff_inlink_queued_samples(inlink) >= s->frame_len) { + if (ff_inlink_check_available_samples(inlink, s->frame_len) > 0) { ff_filter_set_ready(ctx, 10); return 0; } @@ -763,10 +809,10 @@ s->eof = 1; } - if (s->eof && s->delay > 0) + if (s->eof && s->queue.available) return flush(outlink); - if (s->eof && s->delay <= 0) { + if (s->eof && !s->queue.available) { ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); return 0; } @@ -777,6 +823,34 @@ return FFERROR_NOT_READY; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + DynamicAudioNormalizerContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + int prev_filter_size = s->filter_size; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + s->filter_size |= 1; + if (prev_filter_size != s->filter_size) { + init_gaussian_filter(s); + + for (int c = 0; c < s->channels; c++) { + cqueue_resize(s->gain_history_original[c], s->filter_size); + cqueue_resize(s->gain_history_minimum[c], s->filter_size); + cqueue_resize(s->threshold_history[c], s->filter_size); + } + } + + s->frame_len = frame_size(inlink->sample_rate, s->frame_len_msec); + + return 0; +} + static const AVFilterPad avfilter_af_dynaudnorm_inputs[] = { { .name = "default", @@ -806,4 +880,5 @@ .outputs = avfilter_af_dynaudnorm_outputs, .priv_class = &dynaudnorm_class, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_earwax.c ffmpeg-4.4/libavfilter/af_earwax.c --- ffmpeg-4.2.2/libavfilter/af_earwax.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_earwax.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,9 +34,9 @@ #include "audio.h" #include "formats.h" -#define NUMTAPS 64 +#define NUMTAPS 32 -static const int8_t filt[NUMTAPS] = { +static const int8_t filt[NUMTAPS * 2] = { /* 30° 330° */ 4, -6, /* 32 tap stereo FIR filter. */ 4, -11, /* One side filters as if the */ @@ -72,7 +72,10 @@ 4, 0}; typedef struct EarwaxContext { - int16_t taps[NUMTAPS * 2]; + int16_t filter[2][NUMTAPS]; + int16_t taps[4][NUMTAPS * 2]; + + AVFrame *frame[2]; } EarwaxContext; static int query_formats(AVFilterContext *ctx) @@ -83,7 +86,7 @@ AVFilterFormats *formats = NULL; AVFilterChannelLayouts *layout = NULL; - if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_S16 )) < 0 || + if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_S16P )) < 0 || (ret = ff_set_common_formats (ctx , formats )) < 0 || (ret = ff_add_channel_layout (&layout , AV_CH_LAYOUT_STEREO )) < 0 || (ret = ff_set_common_channel_layouts (ctx , layout )) < 0 || @@ -94,7 +97,8 @@ } //FIXME: replace with DSPContext.scalarproduct_int16 -static inline int16_t *scalarproduct(const int16_t *in, const int16_t *endin, int16_t *out) +static inline int16_t *scalarproduct(const int16_t *in, const int16_t *endin, + const int16_t *filt, int16_t *out) { int32_t sample; int16_t j; @@ -103,7 +107,7 @@ sample = 0; for (j = 0; j < NUMTAPS; j++) sample += in[j] * filt[j]; - *out = av_clip_int16(sample >> 6); + *out = av_clip_int16(sample >> 7); out++; in++; } @@ -111,40 +115,102 @@ return out; } -static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) +static int config_input(AVFilterLink *inlink) { - AVFilterLink *outlink = inlink->dst->outputs[0]; - int16_t *taps, *endin, *in, *out; - AVFrame *outsamples = ff_get_audio_buffer(outlink, insamples->nb_samples); - int len; + EarwaxContext *s = inlink->dst->priv; - if (!outsamples) { - av_frame_free(&insamples); - return AVERROR(ENOMEM); + for (int i = 0; i < NUMTAPS; i++) { + s->filter[0][i] = filt[i * 2]; + s->filter[1][i] = filt[i * 2 + 1]; } - av_frame_copy_props(outsamples, insamples); - taps = ((EarwaxContext *)inlink->dst->priv)->taps; - out = (int16_t *)outsamples->data[0]; - in = (int16_t *)insamples ->data[0]; + return 0; +} + +static void convolve(AVFilterContext *ctx, AVFrame *in, + int input_ch, int output_ch, + int filter_ch, int tap_ch) +{ + EarwaxContext *s = ctx->priv; + int16_t *taps, *endin, *dst, *src; + int len; + + taps = s->taps[tap_ch]; + dst = (int16_t *)s->frame[input_ch]->data[output_ch]; + src = (int16_t *)in->data[input_ch]; - len = FFMIN(NUMTAPS, 2*insamples->nb_samples); + len = FFMIN(NUMTAPS, in->nb_samples); // copy part of new input and process with saved input - memcpy(taps+NUMTAPS, in, len * sizeof(*taps)); - out = scalarproduct(taps, taps + len, out); + memcpy(taps+NUMTAPS, src, len * sizeof(*taps)); + dst = scalarproduct(taps, taps + len, s->filter[filter_ch], dst); // process current input - if (2*insamples->nb_samples >= NUMTAPS ){ - endin = in + insamples->nb_samples * 2 - NUMTAPS; - scalarproduct(in, endin, out); + if (in->nb_samples >= NUMTAPS) { + endin = src + in->nb_samples - NUMTAPS; + scalarproduct(src, endin, s->filter[filter_ch], dst); // save part of input for next round memcpy(taps, endin, NUMTAPS * sizeof(*taps)); - } else - memmove(taps, taps + 2*insamples->nb_samples, NUMTAPS * sizeof(*taps)); + } else { + memmove(taps, taps + in->nb_samples, NUMTAPS * sizeof(*taps)); + } +} + +static void mix(AVFilterContext *ctx, AVFrame *out, + int output_ch, int f0, int f1, int i0, int i1) +{ + EarwaxContext *s = ctx->priv; + const int16_t *srcl = (const int16_t *)s->frame[f0]->data[i0]; + const int16_t *srcr = (const int16_t *)s->frame[f1]->data[i1]; + int16_t *dst = (int16_t *)out->data[output_ch]; + + for (int n = 0; n < out->nb_samples; n++) + dst[n] = av_clip_int16(srcl[n] + srcr[n]); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + EarwaxContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out = ff_get_audio_buffer(outlink, in->nb_samples); + + for (int ch = 0; ch < 2; ch++) { + if (!s->frame[ch] || s->frame[ch]->nb_samples < in->nb_samples) { + av_frame_free(&s->frame[ch]); + s->frame[ch] = ff_get_audio_buffer(outlink, in->nb_samples); + if (!s->frame[ch]) { + av_frame_free(&in); + av_frame_free(&out); + return AVERROR(ENOMEM); + } + } + } + + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + + convolve(ctx, in, 0, 0, 0, 0); + convolve(ctx, in, 0, 1, 1, 1); + convolve(ctx, in, 1, 0, 0, 2); + convolve(ctx, in, 1, 1, 1, 3); + + mix(ctx, out, 0, 0, 1, 1, 0); + mix(ctx, out, 1, 0, 1, 0, 1); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + EarwaxContext *s = ctx->priv; - av_frame_free(&insamples); - return ff_filter_frame(outlink, outsamples); + av_frame_free(&s->frame[0]); + av_frame_free(&s->frame[1]); } static const AVFilterPad earwax_inputs[] = { @@ -152,6 +218,7 @@ .name = "default", .type = AVMEDIA_TYPE_AUDIO, .filter_frame = filter_frame, + .config_props = config_input, }, { NULL } }; @@ -169,6 +236,7 @@ .description = NULL_IF_CONFIG_SMALL("Widen the stereo image."), .query_formats = query_formats, .priv_size = sizeof(EarwaxContext), + .uninit = uninit, .inputs = earwax_inputs, .outputs = earwax_outputs, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_extrastereo.c ffmpeg-4.4/libavfilter/af_extrastereo.c --- ffmpeg-4.2.2/libavfilter/af_extrastereo.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_extrastereo.c 2020-07-11 10:39:30.000000000 +0000 @@ -31,7 +31,7 @@ } ExtraStereoContext; #define OFFSET(x) offsetof(ExtraStereoContext, x) -#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption extrastereo_options[] = { { "m", "set the difference coefficient", OFFSET(mult), AV_OPT_TYPE_FLOAT, {.dbl=2.5}, -10, 10, A }, @@ -129,4 +129,5 @@ .inputs = inputs, .outputs = outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_firequalizer.c ffmpeg-4.4/libavfilter/af_firequalizer.c --- ffmpeg-4.2.2/libavfilter/af_firequalizer.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_firequalizer.c 2020-07-11 10:39:30.000000000 +0000 @@ -112,10 +112,11 @@ #define OFFSET(x) offsetof(FIREqualizerContext, x) #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define TFLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption firequalizer_options[] = { - { "gain", "set gain curve", OFFSET(gain), AV_OPT_TYPE_STRING, { .str = "gain_interpolate(f)" }, 0, 0, FLAGS }, - { "gain_entry", "set gain entry", OFFSET(gain_entry), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, + { "gain", "set gain curve", OFFSET(gain), AV_OPT_TYPE_STRING, { .str = "gain_interpolate(f)" }, 0, 0, TFLAGS }, + { "gain_entry", "set gain entry", OFFSET(gain_entry), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, TFLAGS }, { "delay", "set delay", OFFSET(delay), AV_OPT_TYPE_DOUBLE, { .dbl = 0.01 }, 0.0, 1e10, FLAGS }, { "accuracy", "set accuracy", OFFSET(accuracy), AV_OPT_TYPE_DOUBLE, { .dbl = 5.0 }, 0.0, 1e10, FLAGS }, { "wfunc", "set window function", OFFSET(wfunc), AV_OPT_TYPE_INT, { .i64 = WFUNC_HANN }, 0, NB_WFUNC-1, FLAGS, "wfunc" }, diff -Nru ffmpeg-4.2.2/libavfilter/af_flanger.c ffmpeg-4.4/libavfilter/af_flanger.c --- ffmpeg-4.2.2/libavfilter/af_flanger.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_flanger.c 2020-07-11 10:39:30.000000000 +0000 @@ -72,7 +72,7 @@ AVFILTER_DEFINE_CLASS(flanger); -static int init(AVFilterContext *ctx) +static av_cold int init(AVFilterContext *ctx) { FlangerContext *s = ctx->priv; diff -Nru ffmpeg-4.2.2/libavfilter/af_hdcd.c ffmpeg-4.4/libavfilter/af_hdcd.c --- ffmpeg-4.2.2/libavfilter/af_hdcd.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_hdcd.c 2021-04-08 21:28:39.000000000 +0000 @@ -1053,7 +1053,7 @@ for (j = result - 1; j >= 0; j--) { for (i = 0; i < channels; i++) - bits[i] |= (*(samples++) & 1) << j; + bits[i] |= (*(samples++) & 1U) << j; samples += stride - channels; } @@ -1210,7 +1210,7 @@ int32_t *samples_end = samples + stride * count; for (i = 0; i < count; i++) { - samples[i * stride] <<= 15; + samples[i * stride] *= 1 << 15; if (mode == HDCD_ANA_PE) { int pel = (samples[i * stride] >> 16) & 1; int32_t sample = samples[i * stride]; @@ -1284,13 +1284,13 @@ av_assert0(asample <= max_asample); sample = sample >= 0 ? peaktab[asample] : -peaktab[asample]; } else - sample <<= shft; + sample *= (1 << shft); samples[i * stride] = sample; } } else { for (i = 0; i < count; i++) - samples[i * stride] <<= shft; + samples[i * stride] *= (1 << shft); } if (gain <= target_gain) { @@ -1638,12 +1638,12 @@ return ret; in_formats = ff_make_format_list(sample_fmts_in); - ret = ff_formats_ref(in_formats, &inlink->out_formats); + ret = ff_formats_ref(in_formats, &inlink->outcfg.formats); if (ret < 0) return ret; out_formats = ff_make_format_list(sample_fmts_out); - ret = ff_formats_ref(out_formats, &outlink->in_formats); + ret = ff_formats_ref(out_formats, &outlink->incfg.formats); if (ret < 0) return ret; diff -Nru ffmpeg-4.2.2/libavfilter/af_headphone.c ffmpeg-4.4/libavfilter/af_headphone.c --- ffmpeg-4.2.2/libavfilter/af_headphone.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_headphone.c 2021-04-08 21:28:39.000000000 +0000 @@ -52,9 +52,7 @@ int ir_len; int air_len; - int mapping[64]; - - int nb_inputs; + int nb_hrir_inputs; int nb_irs; @@ -69,7 +67,6 @@ int size; int hrir_fmt; - int *delay[2]; float *data_ir[2]; float *temp_src[2]; FFTComplex *temp_fft[2]; @@ -78,82 +75,57 @@ FFTContext *fft[2], *ifft[2]; FFTComplex *data_hrtf[2]; - AVFloatDSPContext *fdsp; - struct headphone_inputs { - AVFrame *frame; + float (*scalarproduct_float)(const float *v1, const float *v2, int len); + struct hrir_inputs { int ir_len; - int delay_l; - int delay_r; int eof; - } *in; + } hrir_in[64]; + uint64_t mapping[64]; } HeadphoneContext; -static int parse_channel_name(HeadphoneContext *s, int x, char **arg, int *rchannel, char *buf) +static int parse_channel_name(const char *arg, uint64_t *rchannel) { - int len, i, channel_id = 0; - int64_t layout, layout0; + uint64_t layout = av_get_channel_layout(arg); - if (sscanf(*arg, "%7[A-Z]%n", buf, &len)) { - layout0 = layout = av_get_channel_layout(buf); - if (layout == AV_CH_LOW_FREQUENCY) - s->lfe_channel = x; - for (i = 32; i > 0; i >>= 1) { - if (layout >= 1LL << i) { - channel_id += i; - layout >>= i; - } - } - if (channel_id >= 64 || layout0 != 1LL << channel_id) - return AVERROR(EINVAL); - *rchannel = channel_id; - *arg += len; - return 0; - } - return AVERROR(EINVAL); + if (av_get_channel_layout_nb_channels(layout) != 1) + return AVERROR(EINVAL); + *rchannel = layout; + return 0; } static void parse_map(AVFilterContext *ctx) { HeadphoneContext *s = ctx->priv; - char *arg, *tokenizer, *p, *args = av_strdup(s->map); - int i; - - if (!args) - return; - p = args; - - s->lfe_channel = -1; - s->nb_inputs = 1; - - for (i = 0; i < 64; i++) { - s->mapping[i] = -1; - } + char *arg, *tokenizer, *p; + uint64_t used_channels = 0; + p = s->map; while ((arg = av_strtok(p, "|", &tokenizer))) { - int out_ch_id; - char buf[8]; + uint64_t out_channel; p = NULL; - if (parse_channel_name(s, s->nb_irs, &arg, &out_ch_id, buf)) { - av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", buf); + if (parse_channel_name(arg, &out_channel)) { + av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", arg); continue; } - s->mapping[s->nb_irs] = out_ch_id; + if (used_channels & out_channel) { + av_log(ctx, AV_LOG_WARNING, "Ignoring duplicate channel '%s'.\n", arg); + continue; + } + used_channels |= out_channel; + s->mapping[s->nb_irs] = out_channel; s->nb_irs++; } if (s->hrir_fmt == HRIR_MULTI) - s->nb_inputs = 2; + s->nb_hrir_inputs = 1; else - s->nb_inputs = s->nb_irs + 1; - - av_free(args); + s->nb_hrir_inputs = s->nb_irs; } typedef struct ThreadData { AVFrame *in, *out; int *write; - int **delay; float **ir; int *n_clippings; float **ringbuffer; @@ -169,7 +141,6 @@ AVFrame *in = td->in, *out = td->out; int offset = jobnr; int *write = &td->write[jobnr]; - const int *const delay = td->delay[jobnr]; const float *const ir = td->ir[jobnr]; int *n_clippings = &td->n_clippings[jobnr]; float *ringbuffer = td->ringbuffer[jobnr]; @@ -181,7 +152,7 @@ const int in_channels = in->channels; const int buffer_length = s->buffer_length; const uint32_t modulo = (uint32_t)buffer_length - 1; - float *buffer[16]; + float *buffer[64]; int wr = *write; int read; int i, l; @@ -192,23 +163,22 @@ } for (i = 0; i < in->nb_samples; i++) { - const float *temp_ir = ir; + const float *cur_ir = ir; *dst = 0; for (l = 0; l < in_channels; l++) { *(buffer[l] + wr) = src[l]; } - for (l = 0; l < in_channels; l++) { + for (l = 0; l < in_channels; cur_ir += air_len, l++) { const float *const bptr = buffer[l]; if (l == s->lfe_channel) { *dst += *(buffer[s->lfe_channel] + wr) * s->gain_lfe; - temp_ir += air_len; continue; } - read = (wr - *(delay + l) - (ir_len - 1) + buffer_length) & modulo; + read = (wr - (ir_len - 1)) & modulo; if (read + ir_len < buffer_length) { memcpy(temp_src, bptr + read, ir_len * sizeof(*temp_src)); @@ -219,8 +189,7 @@ memcpy(temp_src + len, bptr, (air_len - len) * sizeof(*temp_src)); } - dst[0] += s->fdsp->scalarproduct_float(temp_ir, temp_src, FFALIGN(ir_len, 32)); - temp_ir += air_len; + dst[0] += s->scalarproduct_float(cur_ir, temp_src, FFALIGN(ir_len, 32)); } if (fabsf(dst[0]) > 1) @@ -312,6 +281,8 @@ for (j = 0; j < in->nb_samples; j++) { dst[2 * j] += fft_acc[j].re * fft_scale; + if (fabsf(dst[2 * j]) > 1) + n_clippings[0]++; } for (j = 0; j < ir_len - 1; j++) { @@ -320,14 +291,6 @@ *(ringbuffer + write_pos) += fft_acc[in->nb_samples + j].re * fft_scale; } - for (i = 0; i < out->nb_samples; i++) { - if (fabsf(dst[0]) > 1) { - n_clippings[0]++; - } - - dst += 2; - } - *write = wr; return 0; @@ -345,7 +308,7 @@ av_log(ctx, AV_LOG_ERROR, "Too big length of IRs: %d > %d.\n", ir_len, max_ir_len); return AVERROR(EINVAL); } - s->in[input_number].ir_len = ir_len; + s->hrir_in[input_number].ir_len = ir_len; s->ir_len = FFMAX(ir_len, s->ir_len); return 0; @@ -366,7 +329,7 @@ out->pts = in->pts; td.in = in; td.out = out; td.write = s->write; - td.delay = s->delay; td.ir = s->data_ir; td.n_clippings = n_clippings; + td.ir = s->data_ir; td.n_clippings = n_clippings; td.ringbuffer = s->ringbuffer; td.temp_src = s->temp_src; td.temp_fft = s->temp_fft; td.temp_afft = s->temp_afft; @@ -391,37 +354,23 @@ { struct HeadphoneContext *s = ctx->priv; const int ir_len = s->ir_len; - int nb_irs = s->nb_irs; int nb_input_channels = ctx->inputs[0]->channels; float gain_lin = expf((s->gain - 3 * nb_input_channels) / 20 * M_LN10); - FFTComplex *data_hrtf_l = NULL; - FFTComplex *data_hrtf_r = NULL; - FFTComplex *fft_in_l = NULL; - FFTComplex *fft_in_r = NULL; - float *data_ir_l = NULL; - float *data_ir_r = NULL; - int offset = 0, ret = 0; + AVFrame *frame; + int ret = 0; int n_fft; int i, j, k; s->air_len = 1 << (32 - ff_clz(ir_len)); + if (s->type == TIME_DOMAIN) { + s->air_len = FFALIGN(s->air_len, 32); + } s->buffer_length = 1 << (32 - ff_clz(s->air_len)); s->n_fft = n_fft = 1 << (32 - ff_clz(ir_len + s->size)); if (s->type == FREQUENCY_DOMAIN) { - fft_in_l = av_calloc(n_fft, sizeof(*fft_in_l)); - fft_in_r = av_calloc(n_fft, sizeof(*fft_in_r)); - if (!fft_in_l || !fft_in_r) { - ret = AVERROR(ENOMEM); - goto fail; - } - - av_fft_end(s->fft[0]); - av_fft_end(s->fft[1]); s->fft[0] = av_fft_init(av_log2(s->n_fft), 0); s->fft[1] = av_fft_init(av_log2(s->n_fft), 0); - av_fft_end(s->ifft[0]); - av_fft_end(s->ifft[1]); s->ifft[0] = av_fft_init(av_log2(s->n_fft), 1); s->ifft[1] = av_fft_init(av_log2(s->n_fft), 1); @@ -432,11 +381,6 @@ } } - s->data_ir[0] = av_calloc(s->air_len, sizeof(float) * s->nb_irs); - s->data_ir[1] = av_calloc(s->air_len, sizeof(float) * s->nb_irs); - s->delay[0] = av_calloc(s->nb_irs, sizeof(float)); - s->delay[1] = av_calloc(s->nb_irs, sizeof(float)); - if (s->type == TIME_DOMAIN) { s->ringbuffer[0] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels); s->ringbuffer[1] = av_calloc(s->buffer_length, sizeof(float) * nb_input_channels); @@ -454,8 +398,7 @@ } } - if (!s->data_ir[0] || !s->data_ir[1] || - !s->ringbuffer[0] || !s->ringbuffer[1]) { + if (!s->ringbuffer[0] || !s->ringbuffer[1]) { ret = AVERROR(ENOMEM); goto fail; } @@ -464,153 +407,96 @@ s->temp_src[0] = av_calloc(s->air_len, sizeof(float)); s->temp_src[1] = av_calloc(s->air_len, sizeof(float)); - data_ir_l = av_calloc(nb_irs * s->air_len, sizeof(*data_ir_l)); - data_ir_r = av_calloc(nb_irs * s->air_len, sizeof(*data_ir_r)); - if (!data_ir_r || !data_ir_l || !s->temp_src[0] || !s->temp_src[1]) { + s->data_ir[0] = av_calloc(nb_input_channels * s->air_len, sizeof(*s->data_ir[0])); + s->data_ir[1] = av_calloc(nb_input_channels * s->air_len, sizeof(*s->data_ir[1])); + if (!s->data_ir[0] || !s->data_ir[1] || !s->temp_src[0] || !s->temp_src[1]) { ret = AVERROR(ENOMEM); goto fail; } } else { - data_hrtf_l = av_calloc(n_fft, sizeof(*data_hrtf_l) * nb_irs); - data_hrtf_r = av_calloc(n_fft, sizeof(*data_hrtf_r) * nb_irs); - if (!data_hrtf_r || !data_hrtf_l) { + s->data_hrtf[0] = av_calloc(n_fft, sizeof(*s->data_hrtf[0]) * nb_input_channels); + s->data_hrtf[1] = av_calloc(n_fft, sizeof(*s->data_hrtf[1]) * nb_input_channels); + if (!s->data_hrtf[0] || !s->data_hrtf[1]) { ret = AVERROR(ENOMEM); goto fail; } } - for (i = 0; i < s->nb_inputs - 1; i++) { - int len = s->in[i + 1].ir_len; - int delay_l = s->in[i + 1].delay_l; - int delay_r = s->in[i + 1].delay_r; + for (i = 0; i < s->nb_hrir_inputs; av_frame_free(&frame), i++) { + int len = s->hrir_in[i].ir_len; float *ptr; - ret = ff_inlink_consume_samples(ctx->inputs[i + 1], len, len, &s->in[i + 1].frame); + ret = ff_inlink_consume_samples(ctx->inputs[i + 1], len, len, &frame); if (ret < 0) goto fail; - ptr = (float *)s->in[i + 1].frame->extended_data[0]; + ptr = (float *)frame->extended_data[0]; if (s->hrir_fmt == HRIR_STEREO) { - int idx = -1; - - for (j = 0; j < inlink->channels; j++) { - if (s->mapping[i] < 0) { - continue; - } - - if ((av_channel_layout_extract_channel(inlink->channel_layout, j)) == (1LL << s->mapping[i])) { - idx = i; - break; - } - } - - if (idx == -1) + int idx = av_get_channel_layout_channel_index(inlink->channel_layout, + s->mapping[i]); + if (idx < 0) continue; if (s->type == TIME_DOMAIN) { - offset = idx * s->air_len; + float *data_ir_l = s->data_ir[0] + idx * s->air_len; + float *data_ir_r = s->data_ir[1] + idx * s->air_len; + for (j = 0; j < len; j++) { - data_ir_l[offset + j] = ptr[len * 2 - j * 2 - 2] * gain_lin; - data_ir_r[offset + j] = ptr[len * 2 - j * 2 - 1] * gain_lin; + data_ir_l[j] = ptr[len * 2 - j * 2 - 2] * gain_lin; + data_ir_r[j] = ptr[len * 2 - j * 2 - 1] * gain_lin; } } else { - memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l)); - memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r)); + FFTComplex *fft_in_l = s->data_hrtf[0] + idx * n_fft; + FFTComplex *fft_in_r = s->data_hrtf[1] + idx * n_fft; - offset = idx * n_fft; for (j = 0; j < len; j++) { - fft_in_l[delay_l + j].re = ptr[j * 2 ] * gain_lin; - fft_in_r[delay_r + j].re = ptr[j * 2 + 1] * gain_lin; + fft_in_l[j].re = ptr[j * 2 ] * gain_lin; + fft_in_r[j].re = ptr[j * 2 + 1] * gain_lin; } av_fft_permute(s->fft[0], fft_in_l); av_fft_calc(s->fft[0], fft_in_l); - memcpy(data_hrtf_l + offset, fft_in_l, n_fft * sizeof(*fft_in_l)); av_fft_permute(s->fft[0], fft_in_r); av_fft_calc(s->fft[0], fft_in_r); - memcpy(data_hrtf_r + offset, fft_in_r, n_fft * sizeof(*fft_in_r)); } } else { int I, N = ctx->inputs[1]->channels; for (k = 0; k < N / 2; k++) { - int idx = -1; - - for (j = 0; j < inlink->channels; j++) { - if (s->mapping[k] < 0) { - continue; - } - - if ((av_channel_layout_extract_channel(inlink->channel_layout, j)) == (1LL << s->mapping[k])) { - idx = k; - break; - } - } - if (idx == -1) + int idx = av_get_channel_layout_channel_index(inlink->channel_layout, + s->mapping[k]); + if (idx < 0) continue; - I = idx * 2; + I = k * 2; if (s->type == TIME_DOMAIN) { - offset = idx * s->air_len; + float *data_ir_l = s->data_ir[0] + idx * s->air_len; + float *data_ir_r = s->data_ir[1] + idx * s->air_len; + for (j = 0; j < len; j++) { - data_ir_l[offset + j] = ptr[len * N - j * N - N + I ] * gain_lin; - data_ir_r[offset + j] = ptr[len * N - j * N - N + I + 1] * gain_lin; + data_ir_l[j] = ptr[len * N - j * N - N + I ] * gain_lin; + data_ir_r[j] = ptr[len * N - j * N - N + I + 1] * gain_lin; } } else { - memset(fft_in_l, 0, n_fft * sizeof(*fft_in_l)); - memset(fft_in_r, 0, n_fft * sizeof(*fft_in_r)); + FFTComplex *fft_in_l = s->data_hrtf[0] + idx * n_fft; + FFTComplex *fft_in_r = s->data_hrtf[1] + idx * n_fft; - offset = idx * n_fft; for (j = 0; j < len; j++) { - fft_in_l[delay_l + j].re = ptr[j * N + I ] * gain_lin; - fft_in_r[delay_r + j].re = ptr[j * N + I + 1] * gain_lin; + fft_in_l[j].re = ptr[j * N + I ] * gain_lin; + fft_in_r[j].re = ptr[j * N + I + 1] * gain_lin; } av_fft_permute(s->fft[0], fft_in_l); av_fft_calc(s->fft[0], fft_in_l); - memcpy(data_hrtf_l + offset, fft_in_l, n_fft * sizeof(*fft_in_l)); av_fft_permute(s->fft[0], fft_in_r); av_fft_calc(s->fft[0], fft_in_r); - memcpy(data_hrtf_r + offset, fft_in_r, n_fft * sizeof(*fft_in_r)); } } } - - av_frame_free(&s->in[i + 1].frame); - } - - if (s->type == TIME_DOMAIN) { - memcpy(s->data_ir[0], data_ir_l, sizeof(float) * nb_irs * s->air_len); - memcpy(s->data_ir[1], data_ir_r, sizeof(float) * nb_irs * s->air_len); - } else { - s->data_hrtf[0] = av_calloc(n_fft * s->nb_irs, sizeof(FFTComplex)); - s->data_hrtf[1] = av_calloc(n_fft * s->nb_irs, sizeof(FFTComplex)); - if (!s->data_hrtf[0] || !s->data_hrtf[1]) { - ret = AVERROR(ENOMEM); - goto fail; - } - - memcpy(s->data_hrtf[0], data_hrtf_l, - sizeof(FFTComplex) * nb_irs * n_fft); - memcpy(s->data_hrtf[1], data_hrtf_r, - sizeof(FFTComplex) * nb_irs * n_fft); } s->have_hrirs = 1; fail: - - for (i = 0; i < s->nb_inputs - 1; i++) - av_frame_free(&s->in[i + 1].frame); - - av_freep(&data_ir_l); - av_freep(&data_ir_r); - - av_freep(&data_hrtf_l); - av_freep(&data_hrtf_r); - - av_freep(&fft_in_l); - av_freep(&fft_in_r); - return ret; } @@ -624,43 +510,38 @@ FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); if (!s->eof_hrirs) { - for (i = 1; i < s->nb_inputs; i++) { - if (s->in[i].eof) + int eof = 1; + for (i = 0; i < s->nb_hrir_inputs; i++) { + AVFilterLink *input = ctx->inputs[i + 1]; + + if (s->hrir_in[i].eof) continue; - if ((ret = check_ir(ctx->inputs[i], i)) < 0) + if ((ret = check_ir(input, i)) < 0) return ret; - if (!s->in[i].eof) { - if (ff_outlink_get_status(ctx->inputs[i]) == AVERROR_EOF) - s->in[i].eof = 1; - } - } - - for (i = 1; i < s->nb_inputs; i++) { - if (!s->in[i].eof) - break; - } - - if (i != s->nb_inputs) { - if (ff_outlink_frame_wanted(ctx->outputs[0])) { - for (i = 1; i < s->nb_inputs; i++) { - if (!s->in[i].eof) - ff_inlink_request_frame(ctx->inputs[i]); + if (ff_outlink_get_status(input) == AVERROR_EOF) { + if (!ff_inlink_queued_samples(input)) { + av_log(ctx, AV_LOG_ERROR, "No samples provided for " + "HRIR stream %d.\n", i); + return AVERROR_INVALIDDATA; } + s->hrir_in[i].eof = 1; + } else { + if (ff_outlink_frame_wanted(ctx->outputs[0])) + ff_inlink_request_frame(input); + eof = 0; } - - return 0; - } else { - s->eof_hrirs = 1; } - } + if (!eof) + return 0; + s->eof_hrirs = 1; - if (!s->have_hrirs && s->eof_hrirs) { ret = convert_coeffs(ctx, inlink); if (ret < 0) return ret; - } + } else if (!s->have_hrirs) + return AVERROR_EOF; if ((ret = ff_inlink_consume_samples(ctx->inputs[0], s->size, s->size, &in)) > 0) { ret = headphone_frame(s, in, outlink); @@ -698,33 +579,32 @@ if (!layouts) return AVERROR(ENOMEM); - ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->out_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->outcfg.channel_layouts); if (ret) return ret; ret = ff_add_channel_layout(&stereo_layout, AV_CH_LAYOUT_STEREO); if (ret) return ret; + ret = ff_channel_layouts_ref(stereo_layout, &ctx->outputs[0]->incfg.channel_layouts); + if (ret) + return ret; if (s->hrir_fmt == HRIR_MULTI) { hrir_layouts = ff_all_channel_counts(); if (!hrir_layouts) - ret = AVERROR(ENOMEM); - ret = ff_channel_layouts_ref(hrir_layouts, &ctx->inputs[1]->out_channel_layouts); + return AVERROR(ENOMEM); + ret = ff_channel_layouts_ref(hrir_layouts, &ctx->inputs[1]->outcfg.channel_layouts); if (ret) return ret; } else { - for (i = 1; i < s->nb_inputs; i++) { - ret = ff_channel_layouts_ref(stereo_layout, &ctx->inputs[i]->out_channel_layouts); + for (i = 1; i <= s->nb_hrir_inputs; i++) { + ret = ff_channel_layouts_ref(stereo_layout, &ctx->inputs[i]->outcfg.channel_layouts); if (ret) return ret; } } - ret = ff_channel_layouts_ref(stereo_layout, &ctx->outputs[0]->in_channel_layouts); - if (ret) - return ret; - formats = ff_all_samplerates(); if (!formats) return AVERROR(ENOMEM); @@ -741,6 +621,8 @@ return AVERROR(EINVAL); } + s->lfe_channel = av_get_channel_layout_channel_index(inlink->channel_layout, + AV_CH_LOW_FREQUENCY); return 0; } @@ -764,27 +646,27 @@ parse_map(ctx); - s->in = av_calloc(s->nb_inputs, sizeof(*s->in)); - if (!s->in) - return AVERROR(ENOMEM); - - for (i = 1; i < s->nb_inputs; i++) { - char *name = av_asprintf("hrir%d", i - 1); + for (i = 0; i < s->nb_hrir_inputs; i++) { + char *name = av_asprintf("hrir%d", i); AVFilterPad pad = { .name = name, .type = AVMEDIA_TYPE_AUDIO, }; if (!name) return AVERROR(ENOMEM); - if ((ret = ff_insert_inpad(ctx, i, &pad)) < 0) { + if ((ret = ff_insert_inpad(ctx, i + 1, &pad)) < 0) { av_freep(&pad.name); return ret; } } - s->fdsp = avpriv_float_dsp_alloc(0); - if (!s->fdsp) - return AVERROR(ENOMEM); + if (s->type == TIME_DOMAIN) { + AVFloatDSPContext *fdsp = avpriv_float_dsp_alloc(0); + if (!fdsp) + return AVERROR(ENOMEM); + s->scalarproduct_float = fdsp->scalarproduct_float; + av_free(fdsp); + } return 0; } @@ -812,14 +694,11 @@ static av_cold void uninit(AVFilterContext *ctx) { HeadphoneContext *s = ctx->priv; - int i; av_fft_end(s->ifft[0]); av_fft_end(s->ifft[1]); av_fft_end(s->fft[0]); av_fft_end(s->fft[1]); - av_freep(&s->delay[0]); - av_freep(&s->delay[1]); av_freep(&s->data_ir[0]); av_freep(&s->data_ir[1]); av_freep(&s->ringbuffer[0]); @@ -832,13 +711,9 @@ av_freep(&s->temp_afft[1]); av_freep(&s->data_hrtf[0]); av_freep(&s->data_hrtf[1]); - av_freep(&s->fdsp); - for (i = 0; i < s->nb_inputs; i++) { - if (ctx->input_pads && i) - av_freep(&ctx->input_pads[i].name); - } - av_freep(&s->in); + for (unsigned i = 1; i < ctx->nb_inputs; i++) + av_freep(&ctx->input_pads[i].name); } #define OFFSET(x) offsetof(HeadphoneContext, x) diff -Nru ffmpeg-4.2.2/libavfilter/af_join.c ffmpeg-4.4/libavfilter/af_join.c --- ffmpeg-4.2.2/libavfilter/af_join.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_join.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,6 +25,7 @@ */ #include "libavutil/avassert.h" +#include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "libavutil/opt.h" @@ -185,12 +186,10 @@ return ret; for (i = 0; i < s->inputs; i++) { - char name[32]; AVFilterPad pad = { 0 }; - snprintf(name, sizeof(name), "input%d", i); - pad.type = AVMEDIA_TYPE_AUDIO; - pad.name = av_strdup(name); + pad.type = AVMEDIA_TYPE_AUDIO; + pad.name = av_asprintf("input%d", i); if (!pad.name) return AVERROR(ENOMEM); @@ -208,9 +207,12 @@ JoinContext *s = ctx->priv; int i; + for (i = 0; i < s->inputs && s->input_frames; i++) { + av_frame_free(&s->input_frames[i]); + } + for (i = 0; i < ctx->nb_inputs; i++) { av_freep(&ctx->input_pads[i].name); - av_frame_free(&s->input_frames[i]); } av_freep(&s->channels); @@ -225,12 +227,12 @@ int i, ret; if ((ret = ff_add_channel_layout(&layouts, s->channel_layout)) < 0 || - (ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts)) < 0) + (ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0) return ret; for (i = 0; i < ctx->nb_inputs; i++) { layouts = ff_all_channel_layouts(); - if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->outcfg.channel_layouts)) < 0) return ret; } diff -Nru ffmpeg-4.2.2/libavfilter/af_ladspa.c ffmpeg-4.4/libavfilter/af_ladspa.c --- ffmpeg-4.2.2/libavfilter/af_ladspa.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_ladspa.c 2021-04-08 21:28:39.000000000 +0000 @@ -64,6 +64,9 @@ int nb_samples; int64_t pts; int64_t duration; + int in_trim; + int out_pad; + int latency; } LADSPAContext; #define OFFSET(x) offsetof(LADSPAContext, x) @@ -81,11 +84,28 @@ { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, FLAGS }, { "duration", "set audio duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=-1}, -1, INT64_MAX, FLAGS }, { "d", "set audio duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=-1}, -1, INT64_MAX, FLAGS }, + { "latency", "enable latency compensation", OFFSET(latency), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "l", "enable latency compensation", OFFSET(latency), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { NULL } }; AVFILTER_DEFINE_CLASS(ladspa); +static int find_latency(AVFilterContext *ctx, LADSPAContext *s) +{ + int latency = 0; + + for (int ctl = 0; ctl < s->nb_outputcontrols; ctl++) { + if (av_strcasecmp("latency", s->desc->PortNames[s->ocmap[ctl]])) + continue; + + latency = lrintf(s->octlv[ctl]); + break; + } + + return latency; +} + static void print_ctl_info(AVFilterContext *ctx, int level, LADSPAContext *s, int ctl, unsigned long *map, LADSPA_Data *values, int print) @@ -143,12 +163,13 @@ AVFilterContext *ctx = inlink->dst; LADSPAContext *s = ctx->priv; AVFrame *out; - int i, h, p; + int i, h, p, new_out_samples; av_assert0(in->channels == (s->nb_inputs * s->nb_handles)); if (!s->nb_outputs || (av_frame_is_writable(in) && s->nb_inputs == s->nb_outputs && + s->in_trim == 0 && s->out_pad == 0 && !(s->desc->Properties & LADSPA_PROPERTY_INPLACE_BROKEN))) { out = in; } else { @@ -176,6 +197,9 @@ } s->desc->run(s->handles[h], in->nb_samples); + if (s->latency) + s->in_trim = s->out_pad = find_latency(ctx, s); + s->latency = 0; } for (i = 0; i < s->nb_outputcontrols; i++) @@ -184,6 +208,25 @@ if (out != in) av_frame_free(&in); + new_out_samples = out->nb_samples; + if (s->in_trim > 0) { + int trim = FFMIN(new_out_samples, s->in_trim); + + new_out_samples -= trim; + s->in_trim -= trim; + } + + if (new_out_samples <= 0) { + av_frame_free(&out); + return 0; + } else if (new_out_samples < out->nb_samples) { + int offset = out->nb_samples - new_out_samples; + for (int ch = 0; ch < out->channels; ch++) + memmove(out->extended_data[ch], out->extended_data[ch] + sizeof(float) * offset, + sizeof(float) * new_out_samples); + out->nb_samples = new_out_samples; + } + return ff_filter_frame(ctx->outputs[0], out); } @@ -195,8 +238,19 @@ int64_t t; int i; - if (ctx->nb_inputs) - return ff_request_frame(ctx->inputs[0]); + if (ctx->nb_inputs) { + int ret = ff_request_frame(ctx->inputs[0]); + + if (ret == AVERROR_EOF && s->out_pad > 0) { + AVFrame *frame = ff_get_audio_buffer(outlink, FFMIN(2048, s->out_pad)); + if (!frame) + return AVERROR(ENOMEM); + + s->out_pad -= frame->nb_samples; + return filter_frame(ctx->inputs[0], frame); + } + return ret; + } t = av_rescale(s->pts, AV_TIME_BASE, s->sample_rate); if (s->duration >= 0 && t >= s->duration) @@ -415,6 +469,7 @@ } else { // argument is a shared object name char *paths = av_strdup(getenv("LADSPA_PATH")); + const char *home_path = getenv("HOME"); const char *separator = ":"; if (paths) { @@ -426,7 +481,12 @@ } av_free(paths); - if (!s->dl_handle && (paths = av_asprintf("%s/.ladspa/lib", getenv("HOME")))) { + if (!s->dl_handle && home_path && (paths = av_asprintf("%s/.ladspa", home_path))) { + s->dl_handle = try_load(paths, s->dl_name); + av_free(paths); + } + + if (!s->dl_handle && home_path && (paths = av_asprintf("%s/.ladspa/lib", home_path))) { s->dl_handle = try_load(paths, s->dl_name); av_free(paths); } @@ -654,12 +714,12 @@ ret = ff_add_channel_layout(&layouts, inlayout); if (ret < 0) return ret; - ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts); if (ret < 0) return ret; if (!s->nb_outputs) { - ret = ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &outlink->incfg.channel_layouts); if (ret < 0) return ret; } @@ -672,7 +732,7 @@ ret = ff_add_channel_layout(&layouts, outlayout); if (ret < 0) return ret; - ret = ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &outlink->incfg.channel_layouts); if (ret < 0) return ret; } diff -Nru ffmpeg-4.2.2/libavfilter/af_loudnorm.c ffmpeg-4.4/libavfilter/af_loudnorm.c --- ffmpeg-4.2.2/libavfilter/af_loudnorm.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_loudnorm.c 2021-04-08 21:28:39.000000000 +0000 @@ -453,10 +453,9 @@ true_peak = tmp; } - offset = s->target_i - global; - offset_tp = true_peak + offset; + offset = pow(10., (s->target_i - global) / 20.); + offset_tp = true_peak * offset; s->offset = offset_tp < s->target_tp ? offset : s->target_tp - true_peak; - s->offset = pow(10., s->offset / 20.); s->frame_type = LINEAR_MODE; } @@ -715,10 +714,10 @@ formats = ff_make_format_list(input_srate); if (!formats) return AVERROR(ENOMEM); - ret = ff_formats_ref(formats, &inlink->out_samplerates); + ret = ff_formats_ref(formats, &inlink->outcfg.samplerates); if (ret < 0) return ret; - ret = ff_formats_ref(formats, &outlink->in_samplerates); + ret = ff_formats_ref(formats, &outlink->incfg.samplerates); if (ret < 0) return ret; } diff -Nru ffmpeg-4.2.2/libavfilter/af_lv2.c ffmpeg-4.4/libavfilter/af_lv2.c --- ffmpeg-4.2.2/libavfilter/af_lv2.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_lv2.c 2021-04-08 21:28:39.000000000 +0000 @@ -524,12 +524,12 @@ ret = ff_add_channel_layout(&layouts, inlayout); if (ret < 0) return ret; - ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts); if (ret < 0) return ret; if (!s->nb_outputs) { - ret = ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &outlink->incfg.channel_layouts); if (ret < 0) return ret; } @@ -542,7 +542,7 @@ ret = ff_add_channel_layout(&layouts, outlayout); if (ret < 0) return ret; - ret = ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &outlink->incfg.channel_layouts); if (ret < 0) return ret; } diff -Nru ffmpeg-4.2.2/libavfilter/af_mcompand.c ffmpeg-4.4/libavfilter/af_mcompand.c --- ffmpeg-4.2.2/libavfilter/af_mcompand.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_mcompand.c 2021-04-08 21:28:39.000000000 +0000 @@ -361,10 +361,8 @@ char *p2, *p3, *saveptr2 = NULL, *saveptr3 = NULL; double radius; - if (!tstr) { - uninit(ctx); + if (!tstr) return AVERROR(EINVAL); - } p = NULL; p2 = tstr; @@ -372,7 +370,6 @@ tstr2 = av_strtok(p2, " ", &saveptr2); if (!tstr2) { av_log(ctx, AV_LOG_ERROR, "at least one attacks/decays rate is mandatory\n"); - uninit(ctx); return AVERROR(EINVAL); } p2 = NULL; @@ -381,7 +378,6 @@ count_items(tstr2, &nb_attacks, ','); if (!nb_attacks || nb_attacks & 1) { av_log(ctx, AV_LOG_ERROR, "number of attacks rate plus decays rate must be even\n"); - uninit(ctx); return AVERROR(EINVAL); } @@ -417,7 +413,6 @@ tstr2 = av_strtok(p2, " ", &saveptr2); if (!tstr2) { av_log(ctx, AV_LOG_ERROR, "transfer function curve in dB must be set\n"); - uninit(ctx); return AVERROR(EINVAL); } sscanf(tstr2, "%lf", &s->bands[i].transfer_fn.curve_dB); @@ -427,7 +422,6 @@ tstr2 = av_strtok(p2, " ", &saveptr2); if (!tstr2) { av_log(ctx, AV_LOG_ERROR, "transfer points missing\n"); - uninit(ctx); return AVERROR(EINVAL); } @@ -435,38 +429,31 @@ s->bands[i].transfer_fn.nb_segments = (nb_points + 4) * 2; s->bands[i].transfer_fn.segments = av_calloc(s->bands[i].transfer_fn.nb_segments, sizeof(CompandSegment)); - if (!s->bands[i].transfer_fn.segments) { - uninit(ctx); + if (!s->bands[i].transfer_fn.segments) return AVERROR(ENOMEM); - } ret = parse_points(tstr2, nb_points, radius, &s->bands[i].transfer_fn, ctx); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "transfer points parsing failed\n"); - uninit(ctx); return ret; } tstr2 = av_strtok(p2, " ", &saveptr2); if (!tstr2) { av_log(ctx, AV_LOG_ERROR, "crossover_frequency is missing\n"); - uninit(ctx); return AVERROR(EINVAL); } new_nb_items += sscanf(tstr2, "%lf", &s->bands[i].topfreq) == 1; if (s->bands[i].topfreq < 0 || s->bands[i].topfreq >= outlink->sample_rate / 2) { av_log(ctx, AV_LOG_ERROR, "crossover_frequency: %f, should be >=0 and lower than half of sample rate: %d.\n", s->bands[i].topfreq, outlink->sample_rate / 2); - uninit(ctx); return AVERROR(EINVAL); } if (s->bands[i].topfreq != 0) { ret = crossover_setup(outlink, &s->bands[i].filter, s->bands[i].topfreq); - if (ret < 0) { - uninit(ctx); + if (ret < 0) return ret; - } } tstr2 = av_strtok(p2, " ", &saveptr2); diff -Nru ffmpeg-4.2.2/libavfilter/af_pan.c ffmpeg-4.4/libavfilter/af_pan.c --- ffmpeg-4.2.2/libavfilter/af_pan.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_pan.c 2021-04-08 21:28:39.000000000 +0000 @@ -266,7 +266,7 @@ // inlink supports any channel layout layouts = ff_all_channel_counts(); - if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; // outlink supports only requested output channel layout @@ -275,7 +275,7 @@ pan->out_channel_layout ? pan->out_channel_layout : FF_COUNT2LAYOUT(pan->nb_output_channels))) < 0) return ret; - return ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts); + return ff_channel_layouts_ref(layouts, &outlink->incfg.channel_layouts); } static int config_props(AVFilterLink *link) @@ -424,7 +424,7 @@ #define OFFSET(x) offsetof(PanContext, x) static const AVOption pan_options[] = { - { "args", NULL, OFFSET(args), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM }, + { "args", NULL, OFFSET(args), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM }, { NULL } }; diff -Nru ffmpeg-4.2.2/libavfilter/af_replaygain.c ffmpeg-4.4/libavfilter/af_replaygain.c --- ffmpeg-4.2.2/libavfilter/af_replaygain.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_replaygain.c 2020-07-11 10:39:30.000000000 +0000 @@ -551,7 +551,7 @@ AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; ReplayGainContext *s = ctx->priv; - uint32_t level; + int64_t level; AVFrame *out; out = ff_get_audio_buffer(outlink, in->nb_samples); @@ -567,9 +567,9 @@ out->nb_samples); butter_filter_stereo_samples(s, (float *)out->data[0], out->nb_samples); - level = (uint32_t)floor(100 * calc_stereo_rms((float *)out->data[0], - out->nb_samples)); - level = av_clip(level, 0, HISTOGRAM_SLOTS - 1); + level = lrint(floor(100 * calc_stereo_rms((float *)out->data[0], + out->nb_samples))); + level = av_clip64(level, 0, HISTOGRAM_SLOTS - 1); s->histogram[level]++; diff -Nru ffmpeg-4.2.2/libavfilter/af_resample.c ffmpeg-4.4/libavfilter/af_resample.c --- ffmpeg-4.2.2/libavfilter/af_resample.c 2018-07-17 09:27:41.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_resample.c 2021-04-08 21:28:39.000000000 +0000 @@ -102,12 +102,12 @@ !(out_layouts = ff_all_channel_layouts ( ))) return AVERROR(ENOMEM); - if ((ret = ff_formats_ref (in_formats, &inlink->out_formats )) < 0 || - (ret = ff_formats_ref (out_formats, &outlink->in_formats )) < 0 || - (ret = ff_formats_ref (in_samplerates, &inlink->out_samplerates )) < 0 || - (ret = ff_formats_ref (out_samplerates, &outlink->in_samplerates )) < 0 || - (ret = ff_channel_layouts_ref (in_layouts, &inlink->out_channel_layouts)) < 0 || - (ret = ff_channel_layouts_ref (out_layouts, &outlink->in_channel_layouts)) < 0) + if ((ret = ff_formats_ref (in_formats, &inlink->outcfg.formats )) < 0 || + (ret = ff_formats_ref (out_formats, &outlink->incfg.formats )) < 0 || + (ret = ff_formats_ref (in_samplerates, &inlink->outcfg.samplerates )) < 0 || + (ret = ff_formats_ref (out_samplerates, &outlink->incfg.samplerates )) < 0 || + (ret = ff_channel_layouts_ref (in_layouts, &inlink->outcfg.channel_layouts)) < 0 || + (ret = ff_channel_layouts_ref (out_layouts, &outlink->incfg.channel_layouts)) < 0) return ret; return 0; @@ -306,10 +306,19 @@ return ret; } +#if FF_API_CHILD_CLASS_NEXT static const AVClass *resample_child_class_next(const AVClass *prev) { return prev ? NULL : avresample_get_class(); } +#endif + +static const AVClass *resample_child_class_iterate(void **iter) +{ + const AVClass *c = *iter ? NULL : avresample_get_class(); + *iter = (void*)(uintptr_t)c; + return c; +} static void *resample_child_next(void *obj, void *prev) { @@ -321,7 +330,10 @@ .class_name = "resample", .item_name = av_default_item_name, .version = LIBAVUTIL_VERSION_INT, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = resample_child_class_next, +#endif + .child_class_iterate = resample_child_class_iterate, .child_next = resample_child_next, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_rubberband.c ffmpeg-4.4/libavfilter/af_rubberband.c --- ffmpeg-4.2.2/libavfilter/af_rubberband.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_rubberband.c 2021-04-08 21:28:39.000000000 +0000 @@ -43,10 +43,11 @@ #define OFFSET(x) offsetof(RubberBandContext, x) #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define AT AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption rubberband_options[] = { - { "tempo", "set tempo scale factor", OFFSET(tempo), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.01, 100, A }, - { "pitch", "set pitch scale factor", OFFSET(pitch), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.01, 100, A }, + { "tempo", "set tempo scale factor", OFFSET(tempo), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.01, 100, AT }, + { "pitch", "set pitch scale factor", OFFSET(pitch), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.01, 100, AT }, { "transients", "set transients", OFFSET(transients), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, A, "transients" }, { "crisp", 0, 0, AV_OPT_TYPE_CONST, {.i64=RubberBandOptionTransientsCrisp}, 0, 0, A, "transients" }, { "mixed", 0, 0, AV_OPT_TYPE_CONST, {.i64=RubberBandOptionTransientsMixed}, 0, 0, A, "transients" }, @@ -120,8 +121,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) { - RubberBandContext *s = inlink->dst->priv; - AVFilterLink *outlink = inlink->dst->outputs[0]; + AVFilterContext *ctx = inlink->dst; + RubberBandContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; int ret = 0, nb_samples; @@ -148,7 +150,9 @@ } av_frame_free(&in); - return ret < 0 ? ret : nb_samples; + if (ff_inlink_queued_samples(inlink) >= s->nb_samples) + ff_filter_set_ready(ctx, 100); + return ret < 0 ? ret : nb_samples; } static int config_input(AVFilterLink *inlink) @@ -200,30 +204,15 @@ char *res, int res_len, int flags) { RubberBandContext *s = ctx->priv; + int ret; - if (!strcmp(cmd, "tempo")) { - double arg; - - sscanf(args, "%lf", &arg); - if (arg < 0.01 || arg > 100) { - av_log(ctx, AV_LOG_ERROR, - "Tempo scale factor '%f' out of range\n", arg); - return AVERROR(EINVAL); - } - rubberband_set_time_ratio(s->rbs, 1. / arg); - } - - if (!strcmp(cmd, "pitch")) { - double arg; + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; - sscanf(args, "%lf", &arg); - if (arg < 0.01 || arg > 100) { - av_log(ctx, AV_LOG_ERROR, - "Pitch scale factor '%f' out of range\n", arg); - return AVERROR(EINVAL); - } - rubberband_set_pitch_scale(s->rbs, arg); - } + rubberband_set_time_ratio(s->rbs, 1. / s->tempo); + rubberband_set_pitch_scale(s->rbs, s->pitch); + s->nb_samples = rubberband_get_samples_required(s->rbs); return 0; } diff -Nru ffmpeg-4.2.2/libavfilter/af_sidechaincompress.c ffmpeg-4.4/libavfilter/af_sidechaincompress.c --- ffmpeg-4.2.2/libavfilter/af_sidechaincompress.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_sidechaincompress.c 2021-04-08 21:28:39.000000000 +0000 @@ -70,26 +70,27 @@ #define OFFSET(x) offsetof(SidechainCompressContext, x) #define A AV_OPT_FLAG_AUDIO_PARAM #define F AV_OPT_FLAG_FILTERING_PARAM +#define R AV_OPT_FLAG_RUNTIME_PARAM static const AVOption options[] = { - { "level_in", "set input gain", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, A|F }, - { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, A|F, "mode" }, - { "downward",0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, A|F, "mode" }, - { "upward", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, A|F, "mode" }, - { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0.125}, 0.000976563, 1, A|F }, - { "ratio", "set ratio", OFFSET(ratio), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 1, 20, A|F }, - { "attack", "set attack", OFFSET(attack), AV_OPT_TYPE_DOUBLE, {.dbl=20}, 0.01, 2000, A|F }, - { "release", "set release", OFFSET(release), AV_OPT_TYPE_DOUBLE, {.dbl=250}, 0.01, 9000, A|F }, - { "makeup", "set make up gain", OFFSET(makeup), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 1, 64, A|F }, - { "knee", "set knee", OFFSET(knee), AV_OPT_TYPE_DOUBLE, {.dbl=2.82843}, 1, 8, A|F }, - { "link", "set link type", OFFSET(link), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, A|F, "link" }, - { "average", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, A|F, "link" }, - { "maximum", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, A|F, "link" }, - { "detection", "set detection", OFFSET(detection), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, A|F, "detection" }, - { "peak", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, A|F, "detection" }, - { "rms", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, A|F, "detection" }, - { "level_sc", "set sidechain gain", OFFSET(level_sc), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, A|F }, - { "mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, A|F }, + { "level_in", "set input gain", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, A|F|R }, + { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, A|F|R, "mode" }, + { "downward",0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, A|F|R, "mode" }, + { "upward", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, A|F|R, "mode" }, + { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0.125}, 0.000976563, 1, A|F|R }, + { "ratio", "set ratio", OFFSET(ratio), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 1, 20, A|F|R }, + { "attack", "set attack", OFFSET(attack), AV_OPT_TYPE_DOUBLE, {.dbl=20}, 0.01, 2000, A|F|R }, + { "release", "set release", OFFSET(release), AV_OPT_TYPE_DOUBLE, {.dbl=250}, 0.01, 9000, A|F|R }, + { "makeup", "set make up gain", OFFSET(makeup), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 1, 64, A|F|R }, + { "knee", "set knee", OFFSET(knee), AV_OPT_TYPE_DOUBLE, {.dbl=2.82843}, 1, 8, A|F|R }, + { "link", "set link type", OFFSET(link), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, A|F|R, "link" }, + { "average", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, A|F|R, "link" }, + { "maximum", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, A|F|R, "link" }, + { "detection", "set detection", OFFSET(detection), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, A|F|R, "detection" }, + { "peak", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, A|F|R, "detection" }, + { "rms", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, A|F|R, "detection" }, + { "level_sc", "set sidechain gain", OFFSET(level_sc), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, A|F|R }, + { "mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, A|F|R }, { NULL } }; @@ -214,6 +215,20 @@ } } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + compressor_config_output(ctx->outputs[0]); + + return 0; +} + #if CONFIG_SIDECHAINCOMPRESS_FILTER static int activate(AVFilterContext *ctx) { @@ -256,7 +271,7 @@ dst = (double *)out->data[0]; out->pts = s->pts; - s->pts += nb_samples; + s->pts += av_rescale_q(nb_samples, (AVRational){1, ctx->outputs[0]->sample_rate}, ctx->outputs[0]->time_base); compressor(s, (double *)in[0]->data[0], dst, (double *)in[1]->data[0], nb_samples, @@ -291,20 +306,20 @@ }; int ret, i; - if (!ctx->inputs[0]->in_channel_layouts || - !ctx->inputs[0]->in_channel_layouts->nb_channel_layouts) { + if (!ctx->inputs[0]->incfg.channel_layouts || + !ctx->inputs[0]->incfg.channel_layouts->nb_channel_layouts) { av_log(ctx, AV_LOG_WARNING, "No channel layout for input 1\n"); return AVERROR(EAGAIN); } - if ((ret = ff_add_channel_layout(&layouts, ctx->inputs[0]->in_channel_layouts->channel_layouts[0])) < 0 || - (ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts)) < 0) + if ((ret = ff_add_channel_layout(&layouts, ctx->inputs[0]->incfg.channel_layouts->channel_layouts[0])) < 0 || + (ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0) return ret; for (i = 0; i < 2; i++) { layouts = ff_all_channel_counts(); - if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->outcfg.channel_layouts)) < 0) return ret; } @@ -382,6 +397,7 @@ .uninit = uninit, .inputs = sidechaincompress_inputs, .outputs = sidechaincompress_outputs, + .process_command = process_command, }; #endif /* CONFIG_SIDECHAINCOMPRESS_FILTER */ @@ -475,5 +491,6 @@ .query_formats = acompressor_query_formats, .inputs = acompressor_inputs, .outputs = acompressor_outputs, + .process_command = process_command, }; #endif /* CONFIG_ACOMPRESSOR_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/af_silencedetect.c ffmpeg-4.4/libavfilter/af_silencedetect.c --- ffmpeg-4.2.2/libavfilter/af_silencedetect.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_silencedetect.c 2020-07-11 10:39:30.000000000 +0000 @@ -35,7 +35,7 @@ typedef struct SilenceDetectContext { const AVClass *class; double noise; ///< noise amplitude ratio - double duration; ///< minimum duration of silence until notification + int64_t duration; ///< minimum duration of silence until notification int mono; ///< mono mode : check each channel separately (default = check when ALL channels are silent) int channels; ///< number of channels int independent_channels; ///< number of entries in following arrays (always 1 in mono mode) @@ -50,15 +50,16 @@ AVRational time_base); } SilenceDetectContext; +#define MAX_DURATION (24*3600*1000000LL) #define OFFSET(x) offsetof(SilenceDetectContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM static const AVOption silencedetect_options[] = { { "n", "set noise tolerance", OFFSET(noise), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0, DBL_MAX, FLAGS }, { "noise", "set noise tolerance", OFFSET(noise), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0, DBL_MAX, FLAGS }, - { "d", "set minimum duration in seconds", OFFSET(duration), AV_OPT_TYPE_DOUBLE, {.dbl=2.}, 0, 24*60*60, FLAGS }, - { "duration", "set minimum duration in seconds", OFFSET(duration), AV_OPT_TYPE_DOUBLE, {.dbl=2.}, 0, 24*60*60, FLAGS }, - { "mono", "check each channel separately", OFFSET(mono), AV_OPT_TYPE_BOOL, {.i64=0.}, 0, 1, FLAGS }, - { "m", "check each channel separately", OFFSET(mono), AV_OPT_TYPE_BOOL, {.i64=0.}, 0, 1, FLAGS }, + { "d", "set minimum duration in seconds", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=2000000}, 0, MAX_DURATION,FLAGS }, + { "duration", "set minimum duration in seconds", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=2000000}, 0, MAX_DURATION,FLAGS }, + { "mono", "check each channel separately", OFFSET(mono), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "m", "check each channel separately", OFFSET(mono), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { NULL } }; @@ -142,6 +143,7 @@ int c; s->channels = inlink->channels; + s->duration = av_rescale(s->duration, inlink->sample_rate, AV_TIME_BASE); s->independent_channels = s->mono ? s->channels : 1; s->nb_null_samples = av_mallocz_array(sizeof(*s->nb_null_samples), s->independent_channels); if (!s->nb_null_samples) @@ -174,7 +176,7 @@ const int nb_channels = inlink->channels; const int srate = inlink->sample_rate; const int nb_samples = insamples->nb_samples * nb_channels; - const int64_t nb_samples_notify = srate * s->duration * (s->mono ? 1 : nb_channels); + const int64_t nb_samples_notify = s->duration * (s->mono ? 1 : nb_channels); int c; // scale number of null samples to the new sample rate @@ -187,7 +189,6 @@ s->frame_end = insamples->pts + av_rescale_q(insamples->nb_samples, (AVRational){ 1, s->last_sample_rate }, inlink->time_base); - // TODO: document metadata s->silencedetect(s, insamples, nb_samples, nb_samples_notify, inlink->time_base); diff -Nru ffmpeg-4.2.2/libavfilter/af_sofalizer.c ffmpeg-4.4/libavfilter/af_sofalizer.c --- ffmpeg-4.2.2/libavfilter/af_sofalizer.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_sofalizer.c 2021-04-08 21:28:39.000000000 +0000 @@ -183,10 +183,11 @@ return 0; } -static int parse_channel_name(char **arg, int *rchannel, char *buf) +static int parse_channel_name(AVFilterContext *ctx, char **arg, int *rchannel) { int len, i, channel_id = 0; int64_t layout, layout0; + char buf[8] = {0}; /* try to parse a channel name, e.g. "FL" */ if (av_sscanf(*arg, "%7[A-Z]%n", buf, &len)) { @@ -199,8 +200,18 @@ } } /* reject layouts that are not a single channel */ - if (channel_id >= 64 || layout0 != 1LL << channel_id) + if (channel_id >= 64 || layout0 != 1LL << channel_id) { + av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", buf); + return AVERROR(EINVAL); + } + *rchannel = channel_id; + *arg += len; + return 0; + } else if (av_sscanf(*arg, "%d%n", &channel_id, &len) == 1) { + if (channel_id < 0 || channel_id >= 64) { + av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%d\' as channel number.\n", channel_id); return AVERROR(EINVAL); + } *rchannel = channel_id; *arg += len; return 0; @@ -218,13 +229,11 @@ p = args; while ((arg = av_strtok(p, "|", &tokenizer))) { - char buf[8]; float azim, elev; int out_ch_id; p = NULL; - if (parse_channel_name(&arg, &out_ch_id, buf)) { - av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", buf); + if (parse_channel_name(ctx, &arg, &out_ch_id)) { continue; } if (av_sscanf(arg, "%f %f", &azim, &elev) == 2) { @@ -246,11 +255,11 @@ { struct SOFAlizerContext *s = ctx->priv; uint64_t channels_layout = ctx->inputs[0]->channel_layout; - float azim[16] = { 0 }; - float elev[16] = { 0 }; + float azim[64] = { 0 }; + float elev[64] = { 0 }; int m, ch, n_conv = ctx->inputs[0]->channels; /* get no. input channels */ - if (n_conv > 16) + if (n_conv < 0 || n_conv > 64) return AVERROR(EINVAL); s->lfe_channel = -1; @@ -351,7 +360,7 @@ const int buffer_length = s->buffer_length; /* -1 for AND instead of MODULO (applied to powers of 2): */ const uint32_t modulo = (uint32_t)buffer_length - 1; - float *buffer[16]; /* holds ringbuffer for each input channel */ + float *buffer[64]; /* holds ringbuffer for each input channel */ int wr = *write; int read; int i, l; @@ -652,7 +661,7 @@ if (!layouts) return AVERROR(ENOMEM); - ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->out_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->outcfg.channel_layouts); if (ret) return ret; @@ -661,7 +670,7 @@ if (ret) return ret; - ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts); if (ret) return ret; diff -Nru ffmpeg-4.2.2/libavfilter/af_speechnorm.c ffmpeg-4.4/libavfilter/af_speechnorm.c --- ffmpeg-4.2.2/libavfilter/af_speechnorm.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_speechnorm.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2020 Paul B Mahol + * + * Speech Normalizer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * Speech Normalizer + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/opt.h" + +#define FF_BUFQUEUE_SIZE (1024) +#include "bufferqueue.h" + +#include "audio.h" +#include "avfilter.h" +#include "filters.h" +#include "internal.h" + +#define MAX_ITEMS 882000 +#define MIN_PEAK (1. / 32768.) + +typedef struct PeriodItem { + int size; + int type; + double max_peak; +} PeriodItem; + +typedef struct ChannelContext { + int state; + int bypass; + PeriodItem pi[MAX_ITEMS]; + double gain_state; + double pi_max_peak; + int pi_start; + int pi_end; + int pi_size; +} ChannelContext; + +typedef struct SpeechNormalizerContext { + const AVClass *class; + + double peak_value; + double max_expansion; + double max_compression; + double threshold_value; + double raise_amount; + double fall_amount; + uint64_t channels; + int invert; + int link; + + ChannelContext *cc; + double prev_gain; + + int max_period; + int eof; + int64_t pts; + + struct FFBufQueue queue; + + void (*analyze_channel)(AVFilterContext *ctx, ChannelContext *cc, + const uint8_t *srcp, int nb_samples); + void (*filter_channels[2])(AVFilterContext *ctx, + AVFrame *in, int nb_samples); +} SpeechNormalizerContext; + +#define OFFSET(x) offsetof(SpeechNormalizerContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption speechnorm_options[] = { + { "peak", "set the peak value", OFFSET(peak_value), AV_OPT_TYPE_DOUBLE, {.dbl=0.95}, 0.0, 1.0, FLAGS }, + { "p", "set the peak value", OFFSET(peak_value), AV_OPT_TYPE_DOUBLE, {.dbl=0.95}, 0.0, 1.0, FLAGS }, + { "expansion", "set the max expansion factor", OFFSET(max_expansion), AV_OPT_TYPE_DOUBLE, {.dbl=2.0}, 1.0, 50.0, FLAGS }, + { "e", "set the max expansion factor", OFFSET(max_expansion), AV_OPT_TYPE_DOUBLE, {.dbl=2.0}, 1.0, 50.0, FLAGS }, + { "compression", "set the max compression factor", OFFSET(max_compression), AV_OPT_TYPE_DOUBLE, {.dbl=2.0}, 1.0, 50.0, FLAGS }, + { "c", "set the max compression factor", OFFSET(max_compression), AV_OPT_TYPE_DOUBLE, {.dbl=2.0}, 1.0, 50.0, FLAGS }, + { "threshold", "set the threshold value", OFFSET(threshold_value), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0.0, 1.0, FLAGS }, + { "t", "set the threshold value", OFFSET(threshold_value), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0.0, 1.0, FLAGS }, + { "raise", "set the expansion raising amount", OFFSET(raise_amount), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0.0, 1.0, FLAGS }, + { "r", "set the expansion raising amount", OFFSET(raise_amount), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0.0, 1.0, FLAGS }, + { "fall", "set the compression raising amount", OFFSET(fall_amount), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0.0, 1.0, FLAGS }, + { "f", "set the compression raising amount", OFFSET(fall_amount), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0.0, 1.0, FLAGS }, + { "channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS }, + { "h", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS }, + { "invert", "set inverted filtering", OFFSET(invert), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "i", "set inverted filtering", OFFSET(invert), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "link", "set linked channels filtering", OFFSET(link), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "l", "set linked channels filtering", OFFSET(link), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(speechnorm); + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats; + AVFilterChannelLayouts *layouts; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE + }; + int ret; + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats(ctx, formats); + if (ret < 0) + return ret; + + formats = ff_all_samplerates(); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_samplerates(ctx, formats); +} + +static int get_pi_samples(PeriodItem *pi, int start, int end, int remain) +{ + int sum; + + if (pi[start].type == 0) + return remain; + + sum = remain; + while (start != end) { + start++; + if (start >= MAX_ITEMS) + start = 0; + if (pi[start].type == 0) + break; + av_assert0(pi[start].size > 0); + sum += pi[start].size; + } + + return sum; +} + +static int available_samples(AVFilterContext *ctx) +{ + SpeechNormalizerContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + int min_pi_nb_samples; + + min_pi_nb_samples = get_pi_samples(s->cc[0].pi, s->cc[0].pi_start, s->cc[0].pi_end, s->cc[0].pi_size); + for (int ch = 1; ch < inlink->channels && min_pi_nb_samples > 0; ch++) { + ChannelContext *cc = &s->cc[ch]; + + min_pi_nb_samples = FFMIN(min_pi_nb_samples, get_pi_samples(cc->pi, cc->pi_start, cc->pi_end, cc->pi_size)); + } + + return min_pi_nb_samples; +} + +static void consume_pi(ChannelContext *cc, int nb_samples) +{ + if (cc->pi_size >= nb_samples) { + cc->pi_size -= nb_samples; + } else { + av_assert0(0); + } +} + +static double next_gain(AVFilterContext *ctx, double pi_max_peak, int bypass, double state) +{ + SpeechNormalizerContext *s = ctx->priv; + const double expansion = FFMIN(s->max_expansion, s->peak_value / pi_max_peak); + const double compression = 1. / s->max_compression; + const int type = s->invert ? pi_max_peak <= s->threshold_value : pi_max_peak >= s->threshold_value; + + if (bypass) { + return 1.; + } else if (type) { + return FFMIN(expansion, state + s->raise_amount); + } else { + return FFMIN(expansion, FFMAX(compression, state - s->fall_amount)); + } +} + +static void next_pi(AVFilterContext *ctx, ChannelContext *cc, int bypass) +{ + av_assert0(cc->pi_size >= 0); + if (cc->pi_size == 0) { + SpeechNormalizerContext *s = ctx->priv; + int start = cc->pi_start; + + av_assert0(cc->pi[start].size > 0); + av_assert0(cc->pi[start].type > 0 || s->eof); + cc->pi_size = cc->pi[start].size; + cc->pi_max_peak = cc->pi[start].max_peak; + av_assert0(cc->pi_start != cc->pi_end || s->eof); + start++; + if (start >= MAX_ITEMS) + start = 0; + cc->pi_start = start; + cc->gain_state = next_gain(ctx, cc->pi_max_peak, bypass, cc->gain_state); + } +} + +static double min_gain(AVFilterContext *ctx, ChannelContext *cc, int max_size) +{ + SpeechNormalizerContext *s = ctx->priv; + double min_gain = s->max_expansion; + double gain_state = cc->gain_state; + int size = cc->pi_size; + int idx = cc->pi_start; + + min_gain = FFMIN(min_gain, gain_state); + while (size <= max_size) { + if (idx == cc->pi_end) + break; + gain_state = next_gain(ctx, cc->pi[idx].max_peak, 0, gain_state); + min_gain = FFMIN(min_gain, gain_state); + size += cc->pi[idx].size; + idx++; + if (idx >= MAX_ITEMS) + idx = 0; + } + + return min_gain; +} + +#define ANALYZE_CHANNEL(name, ptype, zero) \ +static void analyze_channel_## name (AVFilterContext *ctx, ChannelContext *cc, \ + const uint8_t *srcp, int nb_samples) \ +{ \ + SpeechNormalizerContext *s = ctx->priv; \ + const ptype *src = (const ptype *)srcp; \ + int n = 0; \ + \ + if (cc->state < 0) \ + cc->state = src[0] >= zero; \ + \ + while (n < nb_samples) { \ + if ((cc->state != (src[n] >= zero)) || \ + (cc->pi[cc->pi_end].size > s->max_period)) { \ + double max_peak = cc->pi[cc->pi_end].max_peak; \ + int state = cc->state; \ + cc->state = src[n] >= zero; \ + av_assert0(cc->pi[cc->pi_end].size > 0); \ + if (cc->pi[cc->pi_end].max_peak >= MIN_PEAK || \ + cc->pi[cc->pi_end].size > s->max_period) { \ + cc->pi[cc->pi_end].type = 1; \ + cc->pi_end++; \ + if (cc->pi_end >= MAX_ITEMS) \ + cc->pi_end = 0; \ + if (cc->state != state) \ + cc->pi[cc->pi_end].max_peak = DBL_MIN; \ + else \ + cc->pi[cc->pi_end].max_peak = max_peak; \ + cc->pi[cc->pi_end].type = 0; \ + cc->pi[cc->pi_end].size = 0; \ + av_assert0(cc->pi_end != cc->pi_start); \ + } \ + } \ + \ + if (cc->state) { \ + while (src[n] >= zero) { \ + cc->pi[cc->pi_end].max_peak = FFMAX(cc->pi[cc->pi_end].max_peak, src[n]); \ + cc->pi[cc->pi_end].size++; \ + n++; \ + if (n >= nb_samples) \ + break; \ + } \ + } else { \ + while (src[n] < zero) { \ + cc->pi[cc->pi_end].max_peak = FFMAX(cc->pi[cc->pi_end].max_peak, -src[n]); \ + cc->pi[cc->pi_end].size++; \ + n++; \ + if (n >= nb_samples) \ + break; \ + } \ + } \ + } \ +} + +ANALYZE_CHANNEL(dbl, double, 0.0) +ANALYZE_CHANNEL(flt, float, 0.f) + +#define FILTER_CHANNELS(name, ptype) \ +static void filter_channels_## name (AVFilterContext *ctx, \ + AVFrame *in, int nb_samples) \ +{ \ + SpeechNormalizerContext *s = ctx->priv; \ + AVFilterLink *inlink = ctx->inputs[0]; \ + \ + for (int ch = 0; ch < inlink->channels; ch++) { \ + ChannelContext *cc = &s->cc[ch]; \ + ptype *dst = (ptype *)in->extended_data[ch]; \ + const int bypass = !(av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels); \ + int n = 0; \ + \ + while (n < nb_samples) { \ + ptype gain; \ + int size; \ + \ + next_pi(ctx, cc, bypass); \ + size = FFMIN(nb_samples - n, cc->pi_size); \ + av_assert0(size > 0); \ + gain = cc->gain_state; \ + consume_pi(cc, size); \ + for (int i = n; i < n + size; i++) \ + dst[i] *= gain; \ + n += size; \ + } \ + } \ +} + +FILTER_CHANNELS(dbl, double) +FILTER_CHANNELS(flt, float) + +static double lerp(double min, double max, double mix) +{ + return min + (max - min) * mix; +} + +#define FILTER_LINK_CHANNELS(name, ptype) \ +static void filter_link_channels_## name (AVFilterContext *ctx, \ + AVFrame *in, int nb_samples) \ +{ \ + SpeechNormalizerContext *s = ctx->priv; \ + AVFilterLink *inlink = ctx->inputs[0]; \ + int n = 0; \ + \ + while (n < nb_samples) { \ + int min_size = nb_samples - n; \ + int max_size = 1; \ + ptype gain = s->max_expansion; \ + \ + for (int ch = 0; ch < inlink->channels; ch++) { \ + ChannelContext *cc = &s->cc[ch]; \ + \ + cc->bypass = !(av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels); \ + \ + next_pi(ctx, cc, cc->bypass); \ + min_size = FFMIN(min_size, cc->pi_size); \ + max_size = FFMAX(max_size, cc->pi_size); \ + } \ + \ + av_assert0(min_size > 0); \ + for (int ch = 0; ch < inlink->channels; ch++) { \ + ChannelContext *cc = &s->cc[ch]; \ + \ + if (cc->bypass) \ + continue; \ + gain = FFMIN(gain, min_gain(ctx, cc, max_size)); \ + } \ + \ + for (int ch = 0; ch < inlink->channels; ch++) { \ + ChannelContext *cc = &s->cc[ch]; \ + ptype *dst = (ptype *)in->extended_data[ch]; \ + \ + consume_pi(cc, min_size); \ + if (cc->bypass) \ + continue; \ + \ + for (int i = n; i < n + min_size; i++) { \ + ptype g = lerp(s->prev_gain, gain, (i - n) / (double)min_size); \ + dst[i] *= g; \ + } \ + } \ + \ + s->prev_gain = gain; \ + n += min_size; \ + } \ +} + +FILTER_LINK_CHANNELS(dbl, double) +FILTER_LINK_CHANNELS(flt, float) + +static int filter_frame(AVFilterContext *ctx) +{ + SpeechNormalizerContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFilterLink *inlink = ctx->inputs[0]; + int ret; + + while (s->queue.available > 0) { + int min_pi_nb_samples; + AVFrame *in; + + in = ff_bufqueue_peek(&s->queue, 0); + if (!in) + break; + + min_pi_nb_samples = available_samples(ctx); + if (min_pi_nb_samples < in->nb_samples && !s->eof) + break; + + in = ff_bufqueue_get(&s->queue); + + av_frame_make_writable(in); + + s->filter_channels[s->link](ctx, in, in->nb_samples); + + s->pts = in->pts + in->nb_samples; + + return ff_filter_frame(outlink, in); + } + + for (int f = 0; f < ff_inlink_queued_frames(inlink); f++) { + AVFrame *in; + + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; + if (ret == 0) + break; + + ff_bufqueue_add(ctx, &s->queue, in); + + for (int ch = 0; ch < inlink->channels; ch++) { + ChannelContext *cc = &s->cc[ch]; + + s->analyze_channel(ctx, cc, in->extended_data[ch], in->nb_samples); + } + } + + return 1; +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + SpeechNormalizerContext *s = ctx->priv; + int ret, status; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + ret = filter_frame(ctx); + if (ret <= 0) + return ret; + + if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) + s->eof = 1; + } + + if (s->eof && ff_inlink_queued_samples(inlink) == 0 && + s->queue.available == 0) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + return 0; + } + + if (s->queue.available > 0) { + AVFrame *in = ff_bufqueue_peek(&s->queue, 0); + const int nb_samples = available_samples(ctx); + + if (nb_samples >= in->nb_samples || s->eof) { + ff_filter_set_ready(ctx, 10); + return 0; + } + } + + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + SpeechNormalizerContext *s = ctx->priv; + + s->max_period = inlink->sample_rate / 10; + + s->prev_gain = 1.; + s->cc = av_calloc(inlink->channels, sizeof(*s->cc)); + if (!s->cc) + return AVERROR(ENOMEM); + + for (int ch = 0; ch < inlink->channels; ch++) { + ChannelContext *cc = &s->cc[ch]; + + cc->state = -1; + cc->gain_state = 1.; + } + + switch (inlink->format) { + case AV_SAMPLE_FMT_FLTP: + s->analyze_channel = analyze_channel_flt; + s->filter_channels[0] = filter_channels_flt; + s->filter_channels[1] = filter_link_channels_flt; + break; + case AV_SAMPLE_FMT_DBLP: + s->analyze_channel = analyze_channel_dbl; + s->filter_channels[0] = filter_channels_dbl; + s->filter_channels[1] = filter_link_channels_dbl; + break; + default: + av_assert0(0); + } + + return 0; +} + +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + SpeechNormalizerContext *s = ctx->priv; + int link = s->link; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + if (link != s->link) + s->prev_gain = 1.; + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + SpeechNormalizerContext *s = ctx->priv; + + ff_bufqueue_discard_all(&s->queue); + av_freep(&s->cc); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_speechnorm = { + .name = "speechnorm", + .description = NULL_IF_CONFIG_SMALL("Speech Normalizer."), + .query_formats = query_formats, + .priv_size = sizeof(SpeechNormalizerContext), + .priv_class = &speechnorm_class, + .activate = activate, + .uninit = uninit, + .inputs = inputs, + .outputs = outputs, + .process_command = process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/af_stereotools.c ffmpeg-4.4/libavfilter/af_stereotools.c --- ffmpeg-4.2.2/libavfilter/af_stereotools.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_stereotools.c 2021-04-08 21:28:39.000000000 +0000 @@ -57,7 +57,7 @@ } StereoToolsContext; #define OFFSET(x) offsetof(StereoToolsContext, x) -#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption stereotools_options[] = { { "level_in", "set level in", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, A }, @@ -69,7 +69,7 @@ { "muter", "mute R", OFFSET(mute_r), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A }, { "phasel", "phase L", OFFSET(phase_l), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A }, { "phaser", "phase R", OFFSET(phase_r), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A }, - { "mode", "set stereo mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 8, A, "mode" }, + { "mode", "set stereo mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 10, A, "mode" }, { "lr>lr", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, A, "mode" }, { "lr>ms", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, A, "mode" }, { "ms>lr", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, A, "mode" }, @@ -79,6 +79,8 @@ { "lr>rl", 0, 0, AV_OPT_TYPE_CONST, {.i64=6}, 0, 0, A, "mode" }, { "ms>ll", 0, 0, AV_OPT_TYPE_CONST, {.i64=7}, 0, 0, A, "mode" }, { "ms>rr", 0, 0, AV_OPT_TYPE_CONST, {.i64=8}, 0, 0, A, "mode" }, + { "ms>rl", 0, 0, AV_OPT_TYPE_CONST, {.i64=9}, 0, 0, A, "mode" }, + { "lr>l-r", 0, 0, AV_OPT_TYPE_CONST, {.i64=10}, 0, 0, A, "mode" }, { "slev", "set side level", OFFSET(slev), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, A }, { "sbal", "set side balance", OFFSET(sbal), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, A }, { "mlev", "set middle level", OFFSET(mlev), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, A }, @@ -118,12 +120,9 @@ AVFilterContext *ctx = inlink->dst; StereoToolsContext *s = ctx->priv; - s->length = 2 * inlink->sample_rate * 0.05; - if (s->length <= 1 || s->length & 1) { - av_log(ctx, AV_LOG_ERROR, "sample rate is too small\n"); - return AVERROR(EINVAL); - } - s->buffer = av_calloc(s->length, sizeof(*s->buffer)); + s->length = FFALIGN(inlink->sample_rate / 10, 2); + if (!s->buffer) + s->buffer = av_calloc(s->length, sizeof(*s->buffer)); if (!s->buffer) return AVERROR(ENOMEM); @@ -235,7 +234,7 @@ L = R; break; case 5: - L = (L + R) / 2; + L = (L + R) * 0.5; R = L; break; case 6: @@ -259,6 +258,16 @@ L = r; R = r; break; + case 9: + l = L * mlev * FFMIN(1., 2. - mpan) + R * slev * FFMIN(1., 2. - sbal); + r = L * mlev * FFMIN(1., mpan) - R * slev * FFMIN(1., sbal); + L = r; + R = l; + break; + case 10: + L = (L - R) * 0.5; + R = L; + break; } L *= 1. - mute_l; @@ -315,8 +324,13 @@ L *= level_out; R *= level_out; - dst[0] = L; - dst[1] = R; + if (ctx->is_disabled) { + dst[0] = src[0]; + dst[1] = src[1]; + } else { + dst[0] = L; + dst[1] = R; + } } if (out != in) @@ -324,6 +338,18 @@ 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) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + static av_cold void uninit(AVFilterContext *ctx) { StereoToolsContext *s = ctx->priv; @@ -358,4 +384,6 @@ .uninit = uninit, .inputs = inputs, .outputs = outputs, + .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_stereowiden.c ffmpeg-4.4/libavfilter/af_stereowiden.c --- ffmpeg-4.2.2/libavfilter/af_stereowiden.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_stereowiden.c 2020-07-11 10:39:30.000000000 +0000 @@ -39,13 +39,14 @@ } StereoWidenContext; #define OFFSET(x) offsetof(StereoWidenContext, x) -#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define AT AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption stereowiden_options[] = { { "delay", "set delay time", OFFSET(delay), AV_OPT_TYPE_FLOAT, {.dbl=20}, 1, 100, A }, - { "feedback", "set feedback gain", OFFSET(feedback), AV_OPT_TYPE_FLOAT, {.dbl=.3}, 0, 0.9, A }, - { "crossfeed", "set cross feed", OFFSET(crossfeed), AV_OPT_TYPE_FLOAT, {.dbl=.3}, 0, 0.8, A }, - { "drymix", "set dry-mix", OFFSET(drymix), AV_OPT_TYPE_FLOAT, {.dbl=.8}, 0, 1.0, A }, + { "feedback", "set feedback gain", OFFSET(feedback), AV_OPT_TYPE_FLOAT, {.dbl=.3}, 0, 0.9, AT }, + { "crossfeed", "set cross feed", OFFSET(crossfeed), AV_OPT_TYPE_FLOAT, {.dbl=.3}, 0, 0.8, AT }, + { "drymix", "set dry-mix", OFFSET(drymix), AV_OPT_TYPE_FLOAT, {.dbl=.8}, 0, 1.0, AT }, { NULL } }; @@ -165,4 +166,5 @@ .inputs = inputs, .outputs = outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/af_surround.c ffmpeg-4.4/libavfilter/af_surround.c --- ffmpeg-4.2.2/libavfilter/af_surround.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_surround.c 2021-04-08 21:28:39.000000000 +0000 @@ -175,7 +175,7 @@ if (ret) return ret; - ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts); if (ret) return ret; @@ -184,7 +184,7 @@ if (ret) return ret; - ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->out_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->outcfg.channel_layouts); if (ret) return ret; @@ -1372,7 +1372,7 @@ } } -static int init(AVFilterContext *ctx) +static av_cold int init(AVFilterContext *ctx) { AudioSurroundContext *s = ctx->priv; float overlap; diff -Nru ffmpeg-4.2.2/libavfilter/af_tremolo.c ffmpeg-4.4/libavfilter/af_tremolo.c --- ffmpeg-4.2.2/libavfilter/af_tremolo.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_tremolo.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,6 +28,7 @@ double freq; double depth; double *table; + int table_size; int index; } TremoloContext; @@ -72,7 +73,7 @@ dst += channels; src += channels; s->index++; - if (s->index >= inlink->sample_rate / s->freq) + if (s->index >= s->table_size) s->index = 0; } @@ -125,11 +126,12 @@ const double offset = 1. - s->depth / 2.; int i; - s->table = av_malloc_array(inlink->sample_rate / s->freq, sizeof(*s->table)); + s->table_size = lrint(inlink->sample_rate / s->freq + 0.5); + s->table = av_malloc_array(s->table_size, sizeof(*s->table)); if (!s->table) return AVERROR(ENOMEM); - for (i = 0; i < inlink->sample_rate / s->freq; i++) { + for (i = 0; i < s->table_size; i++) { double env = s->freq * i / inlink->sample_rate; env = sin(2 * M_PI * fmod(env + 0.25, 1.0)); s->table[i] = env * (1 - fabs(offset)) + offset; diff -Nru ffmpeg-4.2.2/libavfilter/af_vibrato.c ffmpeg-4.4/libavfilter/af_vibrato.c --- ffmpeg-4.2.2/libavfilter/af_vibrato.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_vibrato.c 2021-04-08 21:28:39.000000000 +0000 @@ -162,7 +162,7 @@ s->buf = av_calloc(inlink->channels, sizeof(*s->buf)); if (!s->buf) return AVERROR(ENOMEM); - s->buf_size = inlink->sample_rate * 0.005; + s->buf_size = lrint(inlink->sample_rate * 0.005 + 0.5); for (c = 0; c < s->channels; c++) { s->buf[c] = av_malloc_array(s->buf_size, sizeof(*s->buf[c])); if (!s->buf[c]) @@ -170,7 +170,7 @@ } s->buf_index = 0; - s->wave_table_size = inlink->sample_rate / s->freq; + s->wave_table_size = lrint(inlink->sample_rate / s->freq + 0.5); s->wave_table = av_malloc_array(s->wave_table_size, sizeof(*s->wave_table)); if (!s->wave_table) return AVERROR(ENOMEM); diff -Nru ffmpeg-4.2.2/libavfilter/af_volume.c ffmpeg-4.4/libavfilter/af_volume.c --- ffmpeg-4.2.2/libavfilter/af_volume.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/af_volume.c 2021-04-08 21:28:39.000000000 +0000 @@ -62,10 +62,11 @@ #define OFFSET(x) offsetof(VolumeContext, x) #define A AV_OPT_FLAG_AUDIO_PARAM #define F AV_OPT_FLAG_FILTERING_PARAM +#define T AV_OPT_FLAG_RUNTIME_PARAM static const AVOption volume_options[] = { { "volume", "set volume adjustment expression", - OFFSET(volume_expr), AV_OPT_TYPE_STRING, { .str = "1.0" }, .flags = A|F }, + OFFSET(volume_expr), AV_OPT_TYPE_STRING, { .str = "1.0" }, .flags = A|F|T }, { "precision", "select mathematical precision", OFFSET(precision), AV_OPT_TYPE_INT, { .i64 = PRECISION_FLOAT }, PRECISION_FIXED, PRECISION_DOUBLE, A|F, "precision" }, { "fixed", "select 8-bit fixed-point", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FIXED }, INT_MIN, INT_MAX, A|F, "precision" }, @@ -334,10 +335,6 @@ return ret; } -#define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d)) -#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) -#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb)) - static int filter_frame(AVFilterLink *inlink, AVFrame *buf) { AVFilterContext *ctx = inlink->dst; diff -Nru ffmpeg-4.2.2/libavfilter/all_channel_layouts.inc ffmpeg-4.4/libavfilter/all_channel_layouts.inc --- ffmpeg-4.2.2/libavfilter/all_channel_layouts.inc 2016-03-29 02:25:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/all_channel_layouts.inc 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -AV_CH_FRONT_CENTER, -AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY, -AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER, -AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_CENTER, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER, -AV_CH_FRONT_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, -AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, diff -Nru ffmpeg-4.2.2/libavfilter/allfilters.c ffmpeg-4.4/libavfilter/allfilters.c --- ffmpeg-4.2.2/libavfilter/allfilters.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/allfilters.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,15 +34,18 @@ extern AVFilter ff_af_adeclick; extern AVFilter ff_af_adeclip; extern AVFilter ff_af_adelay; +extern AVFilter ff_af_adenorm; extern AVFilter ff_af_aderivative; extern AVFilter ff_af_aecho; extern AVFilter ff_af_aemphasis; extern AVFilter ff_af_aeval; +extern AVFilter ff_af_aexciter; extern AVFilter ff_af_afade; extern AVFilter ff_af_afftdn; extern AVFilter ff_af_afftfilt; extern AVFilter ff_af_afir; extern AVFilter ff_af_aformat; +extern AVFilter ff_af_afreqshift; extern AVFilter ff_af_agate; extern AVFilter ff_af_aiir; extern AVFilter ff_af_aintegral; @@ -56,14 +59,17 @@ extern AVFilter ff_af_amultiply; extern AVFilter ff_af_anequalizer; extern AVFilter ff_af_anlmdn; +extern AVFilter ff_af_anlms; extern AVFilter ff_af_anull; extern AVFilter ff_af_apad; extern AVFilter ff_af_aperms; extern AVFilter ff_af_aphaser; +extern AVFilter ff_af_aphaseshift; extern AVFilter ff_af_apulsator; extern AVFilter ff_af_arealtime; extern AVFilter ff_af_aresample; extern AVFilter ff_af_areverse; +extern AVFilter ff_af_arnndn; extern AVFilter ff_af_aselect; extern AVFilter ff_af_asendcmd; extern AVFilter ff_af_asetnsamples; @@ -77,14 +83,21 @@ extern AVFilter ff_af_asr; extern AVFilter ff_af_astats; extern AVFilter ff_af_astreamselect; +extern AVFilter ff_af_asubboost; +extern AVFilter ff_af_asubcut; +extern AVFilter ff_af_asupercut; +extern AVFilter ff_af_asuperpass; +extern AVFilter ff_af_asuperstop; extern AVFilter ff_af_atempo; extern AVFilter ff_af_atrim; +extern AVFilter ff_af_axcorrelate; extern AVFilter ff_af_azmq; extern AVFilter ff_af_bandpass; extern AVFilter ff_af_bandreject; extern AVFilter ff_af_bass; extern AVFilter ff_af_biquad; extern AVFilter ff_af_bs2b; +extern AVFilter ff_vf_chromaber_vulkan; extern AVFilter ff_af_channelmap; extern AVFilter ff_af_channelsplit; extern AVFilter ff_af_chorus; @@ -123,6 +136,7 @@ extern AVFilter ff_af_silencedetect; extern AVFilter ff_af_silenceremove; extern AVFilter ff_af_sofalizer; +extern AVFilter ff_af_speechnorm; extern AVFilter ff_af_stereotools; extern AVFilter ff_af_stereowiden; extern AVFilter ff_af_superequalizer; @@ -134,6 +148,7 @@ extern AVFilter ff_af_volumedetect; extern AVFilter ff_asrc_aevalsrc; +extern AVFilter ff_asrc_afirsrc; extern AVFilter ff_asrc_anoisesrc; extern AVFilter ff_asrc_anullsrc; extern AVFilter ff_asrc_flite; @@ -143,6 +158,7 @@ extern AVFilter ff_asink_anullsink; +extern AVFilter ff_vf_addroi; extern AVFilter ff_vf_alphaextract; extern AVFilter ff_vf_alphamerge; extern AVFilter ff_vf_amplify; @@ -150,8 +166,10 @@ extern AVFilter ff_vf_atadenoise; extern AVFilter ff_vf_avgblur; extern AVFilter ff_vf_avgblur_opencl; +extern AVFilter ff_vf_avgblur_vulkan; extern AVFilter ff_vf_bbox; extern AVFilter ff_vf_bench; +extern AVFilter ff_vf_bilateral; extern AVFilter ff_vf_bitplanenoise; extern AVFilter ff_vf_blackdetect; extern AVFilter ff_vf_blackframe; @@ -160,19 +178,25 @@ extern AVFilter ff_vf_boxblur; extern AVFilter ff_vf_boxblur_opencl; extern AVFilter ff_vf_bwdif; +extern AVFilter ff_vf_cas; extern AVFilter ff_vf_chromahold; extern AVFilter ff_vf_chromakey; +extern AVFilter ff_vf_chromanr; extern AVFilter ff_vf_chromashift; extern AVFilter ff_vf_ciescope; extern AVFilter ff_vf_codecview; extern AVFilter ff_vf_colorbalance; extern AVFilter ff_vf_colorchannelmixer; +extern AVFilter ff_vf_colorcontrast; +extern AVFilter ff_vf_colorcorrect; +extern AVFilter ff_vf_colorize; extern AVFilter ff_vf_colorkey; extern AVFilter ff_vf_colorkey_opencl; extern AVFilter ff_vf_colorhold; extern AVFilter ff_vf_colorlevels; extern AVFilter ff_vf_colormatrix; extern AVFilter ff_vf_colorspace; +extern AVFilter ff_vf_colortemperature; extern AVFilter ff_vf_convolution; extern AVFilter ff_vf_convolution_opencl; extern AVFilter ff_vf_convolve; @@ -184,6 +208,7 @@ extern AVFilter ff_vf_cue; extern AVFilter ff_vf_curves; extern AVFilter ff_vf_datascope; +extern AVFilter ff_vf_dblur; extern AVFilter ff_vf_dctdnoiz; extern AVFilter ff_vf_deband; extern AVFilter ff_vf_deblock; @@ -199,11 +224,13 @@ extern AVFilter ff_vf_denoise_vaapi; extern AVFilter ff_vf_derain; extern AVFilter ff_vf_deshake; +extern AVFilter ff_vf_deshake_opencl; extern AVFilter ff_vf_despill; extern AVFilter ff_vf_detelecine; extern AVFilter ff_vf_dilation; extern AVFilter ff_vf_dilation_opencl; extern AVFilter ff_vf_displace; +extern AVFilter ff_vf_dnn_processing; extern AVFilter ff_vf_doubleweave; extern AVFilter ff_vf_drawbox; extern AVFilter ff_vf_drawgraph; @@ -212,9 +239,12 @@ extern AVFilter ff_vf_edgedetect; extern AVFilter ff_vf_elbg; extern AVFilter ff_vf_entropy; +extern AVFilter ff_vf_epx; extern AVFilter ff_vf_eq; extern AVFilter ff_vf_erosion; extern AVFilter ff_vf_erosion_opencl; +extern AVFilter ff_vf_estdif; +extern AVFilter ff_vf_exposure; extern AVFilter ff_vf_extractplanes; extern AVFilter ff_vf_fade; extern AVFilter ff_vf_fftdnoiz; @@ -232,6 +262,7 @@ extern AVFilter ff_vf_framerate; extern AVFilter ff_vf_framestep; extern AVFilter ff_vf_freezedetect; +extern AVFilter ff_vf_freezeframes; extern AVFilter ff_vf_frei0r; extern AVFilter ff_vf_fspp; extern AVFilter ff_vf_gblur; @@ -252,12 +283,14 @@ extern AVFilter ff_vf_hwupload; extern AVFilter ff_vf_hwupload_cuda; extern AVFilter ff_vf_hysteresis; +extern AVFilter ff_vf_identity; extern AVFilter ff_vf_idet; extern AVFilter ff_vf_il; extern AVFilter ff_vf_inflate; extern AVFilter ff_vf_interlace; extern AVFilter ff_vf_interleave; extern AVFilter ff_vf_kerndeint; +extern AVFilter ff_vf_kirsch; extern AVFilter ff_vf_lagfun; extern AVFilter ff_vf_lenscorrection; extern AVFilter ff_vf_lensfun; @@ -272,16 +305,22 @@ extern AVFilter ff_vf_lutrgb; extern AVFilter ff_vf_lutyuv; extern AVFilter ff_vf_maskedclamp; +extern AVFilter ff_vf_maskedmax; extern AVFilter ff_vf_maskedmerge; +extern AVFilter ff_vf_maskedmin; +extern AVFilter ff_vf_maskedthreshold; extern AVFilter ff_vf_maskfun; extern AVFilter ff_vf_mcdeint; +extern AVFilter ff_vf_median; extern AVFilter ff_vf_mergeplanes; extern AVFilter ff_vf_mestimate; extern AVFilter ff_vf_metadata; extern AVFilter ff_vf_midequalizer; extern AVFilter ff_vf_minterpolate; extern AVFilter ff_vf_mix; +extern AVFilter ff_vf_monochrome; extern AVFilter ff_vf_mpdecimate; +extern AVFilter ff_vf_msad; extern AVFilter ff_vf_negate; extern AVFilter ff_vf_nlmeans; extern AVFilter ff_vf_nlmeans_opencl; @@ -296,13 +335,17 @@ extern AVFilter ff_vf_overlay; extern AVFilter ff_vf_overlay_opencl; extern AVFilter ff_vf_overlay_qsv; +extern AVFilter ff_vf_overlay_vulkan; +extern AVFilter ff_vf_overlay_cuda; extern AVFilter ff_vf_owdenoise; extern AVFilter ff_vf_pad; +extern AVFilter ff_vf_pad_opencl; extern AVFilter ff_vf_palettegen; extern AVFilter ff_vf_paletteuse; extern AVFilter ff_vf_perms; extern AVFilter ff_vf_perspective; extern AVFilter ff_vf_phase; +extern AVFilter ff_vf_photosensitivity; extern AVFilter ff_vf_pixdesctest; extern AVFilter ff_vf_pixscope; extern AVFilter ff_vf_pp; @@ -335,7 +378,10 @@ extern AVFilter ff_vf_scale_npp; extern AVFilter ff_vf_scale_qsv; extern AVFilter ff_vf_scale_vaapi; +extern AVFilter ff_vf_scale_vulkan; extern AVFilter ff_vf_scale2ref; +extern AVFilter ff_vf_scdet; +extern AVFilter ff_vf_scroll; extern AVFilter ff_vf_select; extern AVFilter ff_vf_selectivecolor; extern AVFilter ff_vf_sendcmd; @@ -348,9 +394,11 @@ extern AVFilter ff_vf_setsar; extern AVFilter ff_vf_settb; extern AVFilter ff_vf_sharpness_vaapi; +extern AVFilter ff_vf_shear; extern AVFilter ff_vf_showinfo; extern AVFilter ff_vf_showpalette; extern AVFilter ff_vf_shuffleframes; +extern AVFilter ff_vf_shufflepixels; extern AVFilter ff_vf_shuffleplanes; extern AVFilter ff_vf_sidedata; extern AVFilter ff_vf_signalstats; @@ -370,15 +418,19 @@ extern AVFilter ff_vf_swapuv; extern AVFilter ff_vf_tblend; extern AVFilter ff_vf_telecine; +extern AVFilter ff_vf_thistogram; extern AVFilter ff_vf_threshold; extern AVFilter ff_vf_thumbnail; extern AVFilter ff_vf_thumbnail_cuda; extern AVFilter ff_vf_tile; extern AVFilter ff_vf_tinterlace; extern AVFilter ff_vf_tlut2; +extern AVFilter ff_vf_tmedian; +extern AVFilter ff_vf_tmidequalizer; extern AVFilter ff_vf_tmix; extern AVFilter ff_vf_tonemap; extern AVFilter ff_vf_tonemap_opencl; +extern AVFilter ff_vf_tonemap_vaapi; extern AVFilter ff_vf_tpad; extern AVFilter ff_vf_transpose; extern AVFilter ff_vf_transpose_npp; @@ -388,7 +440,9 @@ extern AVFilter ff_vf_unpremultiply; extern AVFilter ff_vf_unsharp; extern AVFilter ff_vf_unsharp_opencl; +extern AVFilter ff_vf_untile; extern AVFilter ff_vf_uspp; +extern AVFilter ff_vf_v360; extern AVFilter ff_vf_vaguedenoiser; extern AVFilter ff_vf_vectorscope; extern AVFilter ff_vf_vflip; @@ -396,6 +450,7 @@ extern AVFilter ff_vf_vibrance; extern AVFilter ff_vf_vidstabdetect; extern AVFilter ff_vf_vidstabtransform; +extern AVFilter ff_vf_vif; extern AVFilter ff_vf_vignette; extern AVFilter ff_vf_vmafmotion; extern AVFilter ff_vf_vpp_qsv; @@ -404,10 +459,13 @@ extern AVFilter ff_vf_waveform; extern AVFilter ff_vf_weave; extern AVFilter ff_vf_xbr; +extern AVFilter ff_vf_xfade; +extern AVFilter ff_vf_xfade_opencl; extern AVFilter ff_vf_xmedian; extern AVFilter ff_vf_xstack; extern AVFilter ff_vf_yadif; extern AVFilter ff_vf_yadif_cuda; +extern AVFilter ff_vf_yaepblur; extern AVFilter ff_vf_zmq; extern AVFilter ff_vf_zoompan; extern AVFilter ff_vf_zscale; @@ -418,6 +476,7 @@ extern AVFilter ff_vsrc_color; extern AVFilter ff_vsrc_coreimagesrc; extern AVFilter ff_vsrc_frei0r_src; +extern AVFilter ff_vsrc_gradients; extern AVFilter ff_vsrc_haldclutsrc; extern AVFilter ff_vsrc_life; extern AVFilter ff_vsrc_mandelbrot; @@ -427,6 +486,7 @@ extern AVFilter ff_vsrc_pal75bars; extern AVFilter ff_vsrc_pal100bars; extern AVFilter ff_vsrc_rgbtestsrc; +extern AVFilter ff_vsrc_sierpinski; extern AVFilter ff_vsrc_smptebars; extern AVFilter ff_vsrc_smptehdbars; extern AVFilter ff_vsrc_testsrc; @@ -492,7 +552,7 @@ while ((f = av_filter_iterate(&opaque))) if (!strcmp(f->name, name)) - return (AVFilter *)f; + return f; return NULL; } diff -Nru ffmpeg-4.2.2/libavfilter/asink_anullsink.c ffmpeg-4.4/libavfilter/asink_anullsink.c --- ffmpeg-4.2.2/libavfilter/asink_anullsink.c 2016-03-29 02:25:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/asink_anullsink.c 2020-07-11 10:39:30.000000000 +0000 @@ -40,9 +40,7 @@ AVFilter ff_asink_anullsink = { .name = "anullsink", .description = NULL_IF_CONFIG_SMALL("Do absolutely nothing with the input audio."), - - .priv_size = 0, - - .inputs = avfilter_asink_anullsink_inputs, - .outputs = NULL, + .priv_size = 0, + .inputs = avfilter_asink_anullsink_inputs, + .outputs = NULL, }; diff -Nru ffmpeg-4.2.2/libavfilter/asrc_afirsrc.c ffmpeg-4.4/libavfilter/asrc_afirsrc.c --- ffmpeg-4.2.2/libavfilter/asrc_afirsrc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/asrc_afirsrc.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/eval.h" +#include "libavutil/opt.h" +#include "libavutil/tx.h" +#include "audio.h" +#include "avfilter.h" +#include "internal.h" +#include "window_func.h" + +typedef struct AudioFIRSourceContext { + const AVClass *class; + + char *freq_points_str; + char *magnitude_str; + char *phase_str; + int nb_taps; + int sample_rate; + int nb_samples; + int win_func; + + AVComplexFloat *complexf; + float *freq; + float *magnitude; + float *phase; + int freq_size; + int magnitude_size; + int phase_size; + int nb_freq; + int nb_magnitude; + int nb_phase; + + float *taps; + float *win; + int64_t pts; + + AVTXContext *tx_ctx; + av_tx_fn tx_fn; +} AudioFIRSourceContext; + +#define OFFSET(x) offsetof(AudioFIRSourceContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption afirsrc_options[] = { + { "taps", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=1025}, 9, UINT16_MAX, FLAGS }, + { "t", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=1025}, 9, UINT16_MAX, FLAGS }, + { "frequency", "set frequency points", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str="0 1"}, 0, 0, FLAGS }, + { "f", "set frequency points", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str="0 1"}, 0, 0, FLAGS }, + { "magnitude", "set magnitude values", OFFSET(magnitude_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, FLAGS }, + { "m", "set magnitude values", OFFSET(magnitude_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, FLAGS }, + { "phase", "set phase values", OFFSET(phase_str), AV_OPT_TYPE_STRING, {.str="0 0"}, 0, 0, FLAGS }, + { "p", "set phase values", OFFSET(phase_str), AV_OPT_TYPE_STRING, {.str="0 0"}, 0, 0, FLAGS }, + { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS }, + { "r", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS }, + { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS }, + { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS }, + { "win_func", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64=WFUNC_BLACKMAN}, 0, NB_WFUNC-1, FLAGS, "win_func" }, + { "w", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64=WFUNC_BLACKMAN}, 0, NB_WFUNC-1, FLAGS, "win_func" }, + { "rect", "Rectangular", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_RECT}, 0, 0, FLAGS, "win_func" }, + { "bartlett", "Bartlett", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BARTLETT}, 0, 0, FLAGS, "win_func" }, + { "hanning", "Hanning", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HANNING}, 0, 0, FLAGS, "win_func" }, + { "hamming", "Hamming", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HAMMING}, 0, 0, FLAGS, "win_func" }, + { "blackman", "Blackman", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BLACKMAN}, 0, 0, FLAGS, "win_func" }, + { "welch", "Welch", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_WELCH}, 0, 0, FLAGS, "win_func" }, + { "flattop", "Flat-top", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_FLATTOP}, 0, 0, FLAGS, "win_func" }, + { "bharris", "Blackman-Harris", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BHARRIS}, 0, 0, FLAGS, "win_func" }, + { "bnuttall", "Blackman-Nuttall", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BNUTTALL}, 0, 0, FLAGS, "win_func" }, + { "bhann", "Bartlett-Hann", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BHANN}, 0, 0, FLAGS, "win_func" }, + { "sine", "Sine", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_SINE}, 0, 0, FLAGS, "win_func" }, + { "nuttall", "Nuttall", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_NUTTALL}, 0, 0, FLAGS, "win_func" }, + { "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_LANCZOS}, 0, 0, FLAGS, "win_func" }, + { "gauss", "Gauss", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_GAUSS}, 0, 0, FLAGS, "win_func" }, + { "tukey", "Tukey", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_TUKEY}, 0, 0, FLAGS, "win_func" }, + { "dolph", "Dolph-Chebyshev", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_DOLPH}, 0, 0, FLAGS, "win_func" }, + { "cauchy", "Cauchy", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_CAUCHY}, 0, 0, FLAGS, "win_func" }, + { "parzen", "Parzen", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_PARZEN}, 0, 0, FLAGS, "win_func" }, + { "poisson", "Poisson", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_POISSON}, 0, 0, FLAGS, "win_func" }, + { "bohman" , "Bohman", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BOHMAN}, 0, 0, FLAGS, "win_func" }, + {NULL} +}; + +AVFILTER_DEFINE_CLASS(afirsrc); + +static av_cold int init(AVFilterContext *ctx) +{ + AudioFIRSourceContext *s = ctx->priv; + + if (!(s->nb_taps & 1)) { + av_log(s, AV_LOG_WARNING, "Number of taps %d must be odd length.\n", s->nb_taps); + s->nb_taps |= 1; + } + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioFIRSourceContext *s = ctx->priv; + + av_freep(&s->win); + av_freep(&s->taps); + av_freep(&s->freq); + av_freep(&s->magnitude); + av_freep(&s->phase); + av_freep(&s->complexf); + av_tx_uninit(&s->tx_ctx); +} + +static av_cold int query_formats(AVFilterContext *ctx) +{ + AudioFIRSourceContext *s = ctx->priv; + static const int64_t chlayouts[] = { AV_CH_LAYOUT_MONO, -1 }; + int sample_rates[] = { s->sample_rate, -1 }; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_NONE + }; + + AVFilterFormats *formats; + AVFilterChannelLayouts *layouts; + int ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + ret = ff_set_common_formats (ctx, formats); + if (ret < 0) + return ret; + + layouts = ff_make_format64_list(chlayouts); + if (!layouts) + return AVERROR(ENOMEM); + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + formats = ff_make_format_list(sample_rates); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_samplerates(ctx, formats); +} + +static int parse_string(char *str, float **items, int *nb_items, int *items_size) +{ + float *new_items; + char *tail; + + new_items = av_fast_realloc(NULL, items_size, 1 * sizeof(float)); + if (!new_items) + return AVERROR(ENOMEM); + *items = new_items; + + tail = str; + if (!tail) + return AVERROR(EINVAL); + + do { + (*items)[(*nb_items)++] = av_strtod(tail, &tail); + new_items = av_fast_realloc(*items, items_size, (*nb_items + 1) * sizeof(float)); + if (!new_items) + return AVERROR(ENOMEM); + *items = new_items; + if (tail && *tail) + tail++; + } while (tail && *tail); + + return 0; +} + +static void lininterp(AVComplexFloat *complexf, + const float *freq, + const float *magnitude, + const float *phase, + int m, int minterp) +{ + for (int i = 0; i < minterp; i++) { + for (int j = 1; j < m; j++) { + const float x = i / (float)minterp; + + if (x <= freq[j]) { + const float mg = (x - freq[j-1]) / (freq[j] - freq[j-1]) * (magnitude[j] - magnitude[j-1]) + magnitude[j-1]; + const float ph = (x - freq[j-1]) / (freq[j] - freq[j-1]) * (phase[j] - phase[j-1]) + phase[j-1]; + + complexf[i].re = mg * cosf(ph); + complexf[i].im = mg * sinf(ph); + break; + } + } + } +} + +static av_cold int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AudioFIRSourceContext *s = ctx->priv; + float overlap, scale = 1.f, compensation; + int fft_size, middle, ret; + + s->nb_freq = s->nb_magnitude = s->nb_phase = 0; + + ret = parse_string(s->freq_points_str, &s->freq, &s->nb_freq, &s->freq_size); + if (ret < 0) + return ret; + + ret = parse_string(s->magnitude_str, &s->magnitude, &s->nb_magnitude, &s->magnitude_size); + if (ret < 0) + return ret; + + ret = parse_string(s->phase_str, &s->phase, &s->nb_phase, &s->phase_size); + if (ret < 0) + return ret; + + if (s->nb_freq != s->nb_magnitude && s->nb_freq != s->nb_phase && s->nb_freq >= 2) { + av_log(ctx, AV_LOG_ERROR, "Number of frequencies, magnitudes and phases must be same and >= 2.\n"); + return AVERROR(EINVAL); + } + + for (int i = 0; i < s->nb_freq; i++) { + if (i == 0 && s->freq[i] != 0.f) { + av_log(ctx, AV_LOG_ERROR, "First frequency must be 0.\n"); + return AVERROR(EINVAL); + } + + if (i == s->nb_freq - 1 && s->freq[i] != 1.f) { + av_log(ctx, AV_LOG_ERROR, "Last frequency must be 1.\n"); + return AVERROR(EINVAL); + } + + if (i && s->freq[i] < s->freq[i-1]) { + av_log(ctx, AV_LOG_ERROR, "Frequencies must be in increasing order.\n"); + return AVERROR(EINVAL); + } + } + + fft_size = 1 << (av_log2(s->nb_taps) + 1); + s->complexf = av_calloc(fft_size * 2, sizeof(*s->complexf)); + if (!s->complexf) + return AVERROR(ENOMEM); + + ret = av_tx_init(&s->tx_ctx, &s->tx_fn, AV_TX_FLOAT_FFT, 1, fft_size, &scale, 0); + if (ret < 0) + return ret; + + s->taps = av_calloc(s->nb_taps, sizeof(*s->taps)); + if (!s->taps) + return AVERROR(ENOMEM); + + s->win = av_calloc(s->nb_taps, sizeof(*s->win)); + if (!s->win) + return AVERROR(ENOMEM); + + generate_window_func(s->win, s->nb_taps, s->win_func, &overlap); + + lininterp(s->complexf, s->freq, s->magnitude, s->phase, s->nb_freq, fft_size / 2); + + s->tx_fn(s->tx_ctx, s->complexf + fft_size, s->complexf, sizeof(float)); + + compensation = 2.f / fft_size; + middle = s->nb_taps / 2; + + for (int i = 0; i <= middle; i++) { + s->taps[ i] = s->complexf[fft_size + middle - i].re * compensation * s->win[i]; + s->taps[middle + i] = s->complexf[fft_size + i].re * compensation * s->win[middle + i]; + } + + s->pts = 0; + + return 0; +} + +static int request_frame(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AudioFIRSourceContext *s = ctx->priv; + AVFrame *frame; + int nb_samples; + + nb_samples = FFMIN(s->nb_samples, s->nb_taps - s->pts); + if (!nb_samples) + return AVERROR_EOF; + + if (!(frame = ff_get_audio_buffer(outlink, nb_samples))) + return AVERROR(ENOMEM); + + memcpy(frame->data[0], s->taps + s->pts, nb_samples * sizeof(float)); + + frame->pts = s->pts; + s->pts += nb_samples; + return ff_filter_frame(outlink, frame); +} + +static const AVFilterPad afirsrc_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .request_frame = request_frame, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_asrc_afirsrc = { + .name = "afirsrc", + .description = NULL_IF_CONFIG_SMALL("Generate a FIR coefficients audio stream."), + .query_formats = query_formats, + .init = init, + .uninit = uninit, + .priv_size = sizeof(AudioFIRSourceContext), + .inputs = NULL, + .outputs = afirsrc_outputs, + .priv_class = &afirsrc_class, +}; diff -Nru ffmpeg-4.2.2/libavfilter/asrc_anoisesrc.c ffmpeg-4.4/libavfilter/asrc_anoisesrc.c --- ffmpeg-4.2.2/libavfilter/asrc_anoisesrc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/asrc_anoisesrc.c 2021-04-08 21:28:39.000000000 +0000 @@ -21,6 +21,7 @@ #include "libavutil/opt.h" #include "audio.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" #include "libavutil/lfg.h" #include "libavutil/random_seed.h" @@ -30,13 +31,13 @@ int sample_rate; double amplitude; int64_t duration; - int64_t color; + int color; int64_t seed; int nb_samples; int64_t pts; int infinite; - double (*filter)(double white, double *buf); + double (*filter)(double white, double *buf, double half_amplitude); double buf[7]; AVLFG c; } ANoiseSrcContext; @@ -47,6 +48,7 @@ NM_BROWN, NM_BLUE, NM_VIOLET, + NM_VELVET, NM_NB }; @@ -68,6 +70,7 @@ { "brown", 0, 0, AV_OPT_TYPE_CONST, {.i64 = NM_BROWN}, 0, 0, FLAGS, "color" }, { "blue", 0, 0, AV_OPT_TYPE_CONST, {.i64 = NM_BLUE}, 0, 0, FLAGS, "color" }, { "violet", 0, 0, AV_OPT_TYPE_CONST, {.i64 = NM_VIOLET}, 0, 0, FLAGS, "color" }, + { "velvet", 0, 0, AV_OPT_TYPE_CONST, {.i64 = NM_VELVET}, 0, 0, FLAGS, "color" }, { "seed", "set random seed", OFFSET(seed), AV_OPT_TYPE_INT64, {.i64 = -1}, -1, UINT_MAX, FLAGS }, { "s", "set random seed", OFFSET(seed), AV_OPT_TYPE_INT64, {.i64 = -1}, -1, UINT_MAX, FLAGS }, { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS }, @@ -98,7 +101,7 @@ if (ret < 0) return ret; - layouts = avfilter_make_format64_list(chlayouts); + layouts = ff_make_format64_list(chlayouts); if (!layouts) return AVERROR(ENOMEM); ret = ff_set_common_channel_layouts(ctx, layouts); @@ -111,12 +114,12 @@ return ff_set_common_samplerates(ctx, formats); } -static double white_filter(double white, double *buf) +static double white_filter(double white, double *buf, double ha) { return white; } -static double pink_filter(double white, double *buf) +static double pink_filter(double white, double *buf, double ha) { double pink; @@ -132,7 +135,7 @@ return pink * 0.11; } -static double blue_filter(double white, double *buf) +static double blue_filter(double white, double *buf, double ha) { double blue; @@ -148,7 +151,7 @@ return blue * 0.11; } -static double brown_filter(double white, double *buf) +static double brown_filter(double white, double *buf, double ha) { double brown; @@ -157,7 +160,7 @@ return brown * 3.5; } -static double violet_filter(double white, double *buf) +static double violet_filter(double white, double *buf, double ha) { double violet; @@ -166,6 +169,11 @@ return violet * 3.5; } +static double velvet_filter(double white, double *buf, double ha) +{ + return 2. * ha * ((white > ha) - (white < -ha)); +} + static av_cold int config_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -185,21 +193,26 @@ case NM_BROWN: s->filter = brown_filter; break; case NM_BLUE: s->filter = blue_filter; break; case NM_VIOLET: s->filter = violet_filter; break; + case NM_VELVET: s->filter = velvet_filter; break; } return 0; } -static int request_frame(AVFilterLink *outlink) +static int activate(AVFilterContext *ctx) { - AVFilterContext *ctx = outlink->src; + AVFilterLink *outlink = ctx->outputs[0]; ANoiseSrcContext *s = ctx->priv; AVFrame *frame; int nb_samples, i; double *dst; + if (!ff_outlink_frame_wanted(outlink)) + return FFERROR_NOT_READY; + if (!s->infinite && s->duration <= 0) { - return AVERROR_EOF; + ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + return 0; } else if (!s->infinite && s->duration < s->nb_samples) { nb_samples = s->duration; } else { @@ -213,7 +226,7 @@ for (i = 0; i < nb_samples; i++) { double white; white = s->amplitude * ((2 * ((double) av_lfg_get(&s->c) / 0xffffffff)) - 1); - dst[i] = s->filter(white, s->buf); + dst[i] = s->filter(white, s->buf, s->amplitude * 0.5); } if (!s->infinite) @@ -228,7 +241,6 @@ { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .request_frame = request_frame, .config_props = config_props, }, { NULL } @@ -240,6 +252,7 @@ .query_formats = query_formats, .priv_size = sizeof(ANoiseSrcContext), .inputs = NULL, + .activate = activate, .outputs = anoisesrc_outputs, .priv_class = &anoisesrc_class, }; diff -Nru ffmpeg-4.2.2/libavfilter/asrc_anullsrc.c ffmpeg-4.4/libavfilter/asrc_anullsrc.c --- ffmpeg-4.2.2/libavfilter/asrc_anullsrc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/asrc_anullsrc.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,6 +32,7 @@ #include "libavutil/opt.h" #include "audio.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" typedef struct ANullContext { @@ -40,6 +41,7 @@ uint64_t channel_layout; char *sample_rate_str; int sample_rate; + int64_t duration; int nb_samples; ///< number of samples per requested frame int64_t pts; } ANullContext; @@ -52,8 +54,10 @@ { "cl", "set channel_layout", OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, {.str = "stereo"}, 0, 0, FLAGS }, { "sample_rate", "set sample rate", OFFSET(sample_rate_str) , AV_OPT_TYPE_STRING, {.str = "44100"}, 0, 0, FLAGS }, { "r", "set sample rate", OFFSET(sample_rate_str) , AV_OPT_TYPE_STRING, {.str = "44100"}, 0, 0, FLAGS }, - { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX, FLAGS }, - { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX, FLAGS }, + { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, UINT16_MAX, FLAGS }, + { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, UINT16_MAX, FLAGS }, + { "duration", "set the audio duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS }, + { "d", "set the audio duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS }, { NULL } }; @@ -83,47 +87,45 @@ int ret; if ((ret = ff_set_common_formats (ctx, ff_all_formats (AVMEDIA_TYPE_AUDIO))) < 0 || - (ret = ff_set_common_channel_layouts (ctx, avfilter_make_format64_list (chlayouts ))) < 0 || (ret = ff_set_common_samplerates (ctx, ff_make_format_list (sample_rates ))) < 0) return ret; - return 0; + return ff_set_common_channel_layouts(ctx, ff_make_format64_list(chlayouts)); } -static int config_props(AVFilterLink *outlink) +static av_cold int config_props(AVFilterLink *outlink) { ANullContext *null = outlink->src->priv; - char buf[128]; - av_get_channel_layout_string(buf, sizeof(buf), 0, null->channel_layout); - av_log(outlink->src, AV_LOG_VERBOSE, - "sample_rate:%d channel_layout:'%s' nb_samples:%d\n", - null->sample_rate, buf, null->nb_samples); + if (null->duration >= 0) + null->duration = av_rescale(null->duration, null->sample_rate, AV_TIME_BASE); return 0; } -static int request_frame(AVFilterLink *outlink) +static int activate(AVFilterContext *ctx) { - int ret; - ANullContext *null = outlink->src->priv; - AVFrame *samplesref; + ANullContext *null = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; - samplesref = ff_get_audio_buffer(outlink, null->nb_samples); - if (!samplesref) - return AVERROR(ENOMEM); - - samplesref->pts = null->pts; - samplesref->channel_layout = null->channel_layout; - samplesref->sample_rate = outlink->sample_rate; - - ret = ff_filter_frame(outlink, av_frame_clone(samplesref)); - av_frame_free(&samplesref); - if (ret < 0) - return ret; + if (null->duration >= 0 && null->pts >= null->duration) { + ff_outlink_set_status(outlink, AVERROR_EOF, null->pts); + return 0; + } + + if (ff_outlink_frame_wanted(outlink)) { + AVFrame *samplesref = ff_get_audio_buffer(outlink, null->duration >= 0 ? FFMIN(null->nb_samples, null->duration - null->pts) : null->nb_samples); + + if (!samplesref) + return AVERROR(ENOMEM); + + samplesref->pts = null->pts; + null->pts += samplesref->nb_samples; + + return ff_filter_frame(outlink, samplesref); + } - null->pts += null->nb_samples; - return ret; + return FFERROR_NOT_READY; } static const AVFilterPad avfilter_asrc_anullsrc_outputs[] = { @@ -131,7 +133,6 @@ .name = "default", .type = AVMEDIA_TYPE_AUDIO, .config_props = config_props, - .request_frame = request_frame, }, { NULL } }; @@ -144,5 +145,6 @@ .priv_size = sizeof(ANullContext), .inputs = NULL, .outputs = avfilter_asrc_anullsrc_outputs, + .activate = activate, .priv_class = &anullsrc_class, }; diff -Nru ffmpeg-4.2.2/libavfilter/asrc_flite.c ffmpeg-4.4/libavfilter/asrc_flite.c --- ffmpeg-4.2.2/libavfilter/asrc_flite.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/asrc_flite.c 2020-07-11 10:39:30.000000000 +0000 @@ -54,10 +54,10 @@ { "list_voices", "list voices and exit", OFFSET(list_voices), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { "nb_samples", "set number of samples per frame", OFFSET(frame_nb_samples), AV_OPT_TYPE_INT, {.i64=512}, 0, INT_MAX, FLAGS }, { "n", "set number of samples per frame", OFFSET(frame_nb_samples), AV_OPT_TYPE_INT, {.i64=512}, 0, INT_MAX, FLAGS }, - { "text", "set text to speak", OFFSET(text), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "textfile", "set filename of the text to speak", OFFSET(textfile), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "v", "set voice", OFFSET(voice_str), AV_OPT_TYPE_STRING, {.str="kal"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "voice", "set voice", OFFSET(voice_str), AV_OPT_TYPE_STRING, {.str="kal"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "text", "set text to speak", OFFSET(text), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "textfile", "set filename of the text to speak", OFFSET(textfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "v", "set voice", OFFSET(voice_str), AV_OPT_TYPE_STRING, {.str="kal"}, 0, 0, FLAGS }, + { "voice", "set voice", OFFSET(voice_str), AV_OPT_TYPE_STRING, {.str="kal"}, 0, 0, FLAGS }, { NULL } }; diff -Nru ffmpeg-4.2.2/libavfilter/asrc_hilbert.c ffmpeg-4.4/libavfilter/asrc_hilbert.c --- ffmpeg-4.2.2/libavfilter/asrc_hilbert.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/asrc_hilbert.c 2021-04-08 21:28:39.000000000 +0000 @@ -113,7 +113,7 @@ if (ret < 0) return ret; - layouts = avfilter_make_format64_list(chlayouts); + layouts = ff_make_format64_list(chlayouts); if (!layouts) return AVERROR(ENOMEM); ret = ff_set_common_channel_layouts(ctx, layouts); diff -Nru ffmpeg-4.2.2/libavfilter/asrc_sinc.c ffmpeg-4.4/libavfilter/asrc_sinc.c --- ffmpeg-4.2.2/libavfilter/asrc_sinc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/asrc_sinc.c 2021-04-08 21:28:39.000000000 +0000 @@ -84,7 +84,7 @@ if (ret < 0) return ret; - layouts = avfilter_make_format64_list(chlayouts); + layouts = ff_make_format64_list(chlayouts); if (!layouts) return AVERROR(ENOMEM); ret = ff_set_common_channel_layouts(ctx, layouts); @@ -227,10 +227,11 @@ for (i = *len, work_len = 2 * 2 * 8; i > 1; work_len <<= 1, i >>= 1); - work = av_calloc(work_len + 2, sizeof(*work)); /* +2: (UN)PACK */ - pi_wraps = av_calloc(((work_len + 2) / 2), sizeof(*pi_wraps)); - if (!work || !pi_wraps) + /* The first part is for work (+2 for (UN)PACK), the latter for pi_wraps. */ + work = av_calloc((work_len + 2) + (work_len / 2 + 1), sizeof(float)); + if (!work) return AVERROR(ENOMEM); + pi_wraps = &work[work_len + 2]; memcpy(work, *h, *len * sizeof(*work)); @@ -239,8 +240,10 @@ s->rdft = s->irdft = NULL; s->rdft = av_rdft_init(av_log2(work_len), DFT_R2C); s->irdft = av_rdft_init(av_log2(work_len), IDFT_C2R); - if (!s->rdft || !s->irdft) + if (!s->rdft || !s->irdft) { + av_free(work); return AVERROR(ENOMEM); + } av_rdft_calc(s->rdft, work); /* Cepstral: */ UNPACK(work, work_len); @@ -320,7 +323,6 @@ *len = end - begin; *h = av_realloc_f(*h, *len, sizeof(**h)); if (!*h) { - av_free(pi_wraps); av_free(work); return AVERROR(ENOMEM); } @@ -335,7 +337,6 @@ work_len, pi_wraps[work_len >> 1] / M_PI, peak, peak_imp_sum, imp_peak, work[imp_peak], *len, *post_len, 100.f - 100.f * *post_len / (*len - 1)); - av_free(pi_wraps); av_free(work); return 0; diff -Nru ffmpeg-4.2.2/libavfilter/asrc_sine.c ffmpeg-4.4/libavfilter/asrc_sine.c --- ffmpeg-4.2.2/libavfilter/asrc_sine.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/asrc_sine.c 2021-04-08 21:28:39.000000000 +0000 @@ -194,7 +194,7 @@ if (ret < 0) return ret; - layouts = avfilter_make_format64_list(chlayouts); + layouts = ff_make_format64_list(chlayouts); if (!layouts) return AVERROR(ENOMEM); ret = ff_set_common_channel_layouts(ctx, layouts); @@ -247,7 +247,7 @@ samples[i] = sine->sin[sine->phi >> (32 - LOG_PERIOD)]; sine->phi += sine->dphi; if (sine->beep_index < sine->beep_length) { - samples[i] += sine->sin[sine->phi_beep >> (32 - LOG_PERIOD)] << 1; + samples[i] += sine->sin[sine->phi_beep >> (32 - LOG_PERIOD)] * 2; sine->phi_beep += sine->dphi_beep; } if (++sine->beep_index == sine->beep_period) diff -Nru ffmpeg-4.2.2/libavfilter/atadenoise.h ffmpeg-4.4/libavfilter/atadenoise.h --- ffmpeg-4.2.2/libavfilter/atadenoise.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/atadenoise.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,42 @@ + /* + * Copyright (c) 2019 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_ATADENOISE_H +#define AVFILTER_ATADENOISE_H + +#include +#include + +enum ATAAlgorithm { + PARALLEL, + SERIAL, + NB_ATAA +}; + +typedef struct ATADenoiseDSPContext { + void (*filter_row[4])(const uint8_t *src, uint8_t *dst, + const uint8_t **srcf, + int w, int mid, int size, + int thra, int thrb, const float *weight); +} ATADenoiseDSPContext; + +void ff_atadenoise_init_x86(ATADenoiseDSPContext *dsp, int depth, int algorithm, const float *sigma); + +#endif /* AVFILTER_ATADENOISE_H */ diff -Nru ffmpeg-4.2.2/libavfilter/audio.h ffmpeg-4.4/libavfilter/audio.h --- ffmpeg-4.2.2/libavfilter/audio.h 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavfilter/audio.h 2021-04-08 21:28:39.000000000 +0000 @@ -25,24 +25,6 @@ #include "avfilter.h" #include "internal.h" -static const enum AVSampleFormat ff_packed_sample_fmts_array[] = { - AV_SAMPLE_FMT_U8, - AV_SAMPLE_FMT_S16, - AV_SAMPLE_FMT_S32, - AV_SAMPLE_FMT_FLT, - AV_SAMPLE_FMT_DBL, - AV_SAMPLE_FMT_NONE -}; - -static const enum AVSampleFormat ff_planar_sample_fmts_array[] = { - AV_SAMPLE_FMT_U8P, - AV_SAMPLE_FMT_S16P, - AV_SAMPLE_FMT_S32P, - AV_SAMPLE_FMT_FLTP, - AV_SAMPLE_FMT_DBLP, - AV_SAMPLE_FMT_NONE -}; - /** default handler for get_audio_buffer() for audio inputs */ AVFrame *ff_default_get_audio_buffer(AVFilterLink *link, int nb_samples); diff -Nru ffmpeg-4.2.2/libavfilter/avf_abitscope.c ffmpeg-4.4/libavfilter/avf_abitscope.c --- ffmpeg-4.2.2/libavfilter/avf_abitscope.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avf_abitscope.c 2021-04-08 21:28:39.000000000 +0000 @@ -69,21 +69,21 @@ int ret; formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0) return ret; layouts = ff_all_channel_counts(); if (!layouts) return AVERROR(ENOMEM); - if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; formats = ff_all_samplerates(); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0) return ret; formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; return 0; @@ -142,7 +142,7 @@ int i; for (i = 0; i < max; i++) { - if (sample & (1 << i)) + if (sample & (1U << i)) s->counter[i]++; } } diff -Nru ffmpeg-4.2.2/libavfilter/avf_ahistogram.c ffmpeg-4.4/libavfilter/avf_ahistogram.c --- ffmpeg-4.2.2/libavfilter/avf_ahistogram.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avf_ahistogram.c 2021-04-08 21:28:39.000000000 +0000 @@ -99,17 +99,17 @@ int ret = AVERROR(EINVAL); formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref (formats, &inlink->out_formats )) < 0 || + if ((ret = ff_formats_ref (formats, &inlink->outcfg.formats )) < 0 || (layouts = ff_all_channel_counts()) == NULL || - (ret = ff_channel_layouts_ref (layouts, &inlink->out_channel_layouts)) < 0) + (ret = ff_channel_layouts_ref (layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; formats = ff_all_samplerates(); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0) return ret; formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; return 0; @@ -163,6 +163,7 @@ const int w = s->w; int c, y, n, p, bin; uint64_t acmax = 1; + AVFrame *clone; if (!s->out || s->out->width != outlink->w || s->out->height != outlink->h) { @@ -363,7 +364,11 @@ s->ypos = H; } - return ff_filter_frame(outlink, av_frame_clone(s->out)); + clone = av_frame_clone(s->out); + if (!clone) + return AVERROR(ENOMEM); + + return ff_filter_frame(outlink, clone); } static int activate(AVFilterContext *ctx) diff -Nru ffmpeg-4.2.2/libavfilter/avf_aphasemeter.c ffmpeg-4.4/libavfilter/avf_aphasemeter.c --- ffmpeg-4.2.2/libavfilter/avf_aphasemeter.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avf_aphasemeter.c 2021-04-08 21:28:39.000000000 +0000 @@ -28,26 +28,43 @@ #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" +#include "libavutil/timestamp.h" #include "avfilter.h" #include "formats.h" #include "audio.h" #include "video.h" #include "internal.h" +#include "float.h" typedef struct AudioPhaseMeterContext { const AVClass *class; AVFrame *out; int do_video; + int do_phasing_detection; int w, h; AVRational frame_rate; int contrast[4]; uint8_t *mpc_str; uint8_t mpc[4]; int draw_median_phase; + int is_mono; + int is_out_phase; + int start_mono_presence; + int start_out_phase_presence; + float tolerance; + float angle; + float phase; + AVRational time_base; + int64_t duration; + int64_t frame_end; + int64_t mono_idx[2]; + int64_t out_phase_idx[2]; } AudioPhaseMeterContext; +#define MAX_DURATION (24*60*60*1000000LL) #define OFFSET(x) offsetof(AudioPhaseMeterContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define get_duration(index) (index[1] - index[0]) static const AVOption aphasemeter_options[] = { { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS }, @@ -59,6 +76,13 @@ { "bc", "set blue contrast", OFFSET(contrast[2]), AV_OPT_TYPE_INT, {.i64=1}, 0, 255, FLAGS }, { "mpc", "set median phase color", OFFSET(mpc_str), AV_OPT_TYPE_STRING, {.str = "none"}, 0, 0, FLAGS }, { "video", "set video output", OFFSET(do_video), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, + { "phasing", "set mono and out-of-phase detection output", OFFSET(do_phasing_detection), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, + { "tolerance", "set phase tolerance for mono detection", OFFSET(tolerance), AV_OPT_TYPE_FLOAT, {.dbl = 0.}, 0, 1, FLAGS }, + { "t", "set phase tolerance for mono detection", OFFSET(tolerance), AV_OPT_TYPE_FLOAT, {.dbl = 0.}, 0, 1, FLAGS }, + { "angle", "set angle threshold for out-of-phase detection", OFFSET(angle), AV_OPT_TYPE_FLOAT, {.dbl = 170.}, 90, 180, FLAGS }, + { "a", "set angle threshold for out-of-phase detection", OFFSET(angle), AV_OPT_TYPE_FLOAT, {.dbl = 170.}, 90, 180, FLAGS }, + { "duration", "set minimum mono or out-of-phase duration in seconds", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=2000000}, 0, MAX_DURATION, FLAGS }, + { "d", "set minimum mono or out-of-phase duration in seconds", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=2000000}, 0, MAX_DURATION, FLAGS }, { NULL } }; @@ -76,23 +100,23 @@ int ret; formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref (formats, &inlink->out_formats )) < 0 || - (ret = ff_formats_ref (formats, &outlink->in_formats )) < 0 || + if ((ret = ff_formats_ref (formats, &inlink->outcfg.formats )) < 0 || + (ret = ff_formats_ref (formats, &outlink->incfg.formats )) < 0 || (ret = ff_add_channel_layout (&layout, AV_CH_LAYOUT_STEREO )) < 0 || - (ret = ff_channel_layouts_ref (layout , &inlink->out_channel_layouts)) < 0 || - (ret = ff_channel_layouts_ref (layout , &outlink->in_channel_layouts)) < 0) + (ret = ff_channel_layouts_ref (layout , &inlink->outcfg.channel_layouts)) < 0 || + (ret = ff_channel_layouts_ref (layout , &outlink->incfg.channel_layouts)) < 0) return ret; formats = ff_all_samplerates(); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0 || - (ret = ff_formats_ref(formats, &outlink->in_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0 || + (ret = ff_formats_ref(formats, &outlink->incfg.samplerates)) < 0) return ret; if (s->do_video) { AVFilterLink *outlink = ctx->outputs[1]; formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; } @@ -104,6 +128,7 @@ AVFilterContext *ctx = inlink->dst; AudioPhaseMeterContext *s = ctx->priv; int nb_samples; + s->duration = av_rescale(s->duration, inlink->sample_rate, AV_TIME_BASE); if (s->do_video) { nb_samples = FFMAX(1, av_rescale(inlink->sample_rate, s->frame_rate.den, s->frame_rate.num)); @@ -140,6 +165,76 @@ return (phase + 1.) / 2. * (w - 1); } +static inline void add_metadata(AVFrame *insamples, const char *key, char *value) +{ + char buf[128]; + + snprintf(buf, sizeof(buf), "lavfi.aphasemeter.%s", key); + av_dict_set(&insamples->metadata, buf, value, 0); +} + +static inline void update_mono_detection(AudioPhaseMeterContext *s, AVFrame *insamples, int mono_measurement) +{ + int64_t mono_duration; + if (!s->is_mono && mono_measurement) { + s->is_mono = 1; + s->start_mono_presence = 1; + s->mono_idx[0] = insamples->pts; + } + if (s->is_mono && mono_measurement && s->start_mono_presence) { + s->mono_idx[1] = s->frame_end; + mono_duration = get_duration(s->mono_idx); + if (mono_duration >= s->duration) { + add_metadata(insamples, "mono_start", av_ts2timestr(s->mono_idx[0], &s->time_base)); + av_log(s, AV_LOG_INFO, "mono_start: %s\n", av_ts2timestr(s->mono_idx[0], &s->time_base)); + s->start_mono_presence = 0; + } + } + if (s->is_mono && !mono_measurement) { + s->mono_idx[1] = insamples ? insamples->pts : s->frame_end; + mono_duration = get_duration(s->mono_idx); + if (mono_duration >= s->duration) { + if (insamples) { + add_metadata(insamples, "mono_end", av_ts2timestr(s->mono_idx[1], &s->time_base)); + add_metadata(insamples, "mono_duration", av_ts2timestr(mono_duration, &s->time_base)); + } + av_log(s, AV_LOG_INFO, "mono_end: %s | mono_duration: %s\n", av_ts2timestr(s->mono_idx[1], &s->time_base), av_ts2timestr(mono_duration, &s->time_base)); + } + s->is_mono = 0; + } +} + +static inline void update_out_phase_detection(AudioPhaseMeterContext *s, AVFrame *insamples, int out_phase_measurement) +{ + int64_t out_phase_duration; + if (!s->is_out_phase && out_phase_measurement) { + s->is_out_phase = 1; + s->start_out_phase_presence = 1; + s->out_phase_idx[0] = insamples->pts; + } + if (s->is_out_phase && out_phase_measurement && s->start_out_phase_presence) { + s->out_phase_idx[1] = s->frame_end; + out_phase_duration = get_duration(s->out_phase_idx); + if (out_phase_duration >= s->duration) { + add_metadata(insamples, "out_phase_start", av_ts2timestr(s->out_phase_idx[0], &s->time_base)); + av_log(s, AV_LOG_INFO, "out_phase_start: %s\n", av_ts2timestr(s->out_phase_idx[0], &s->time_base)); + s->start_out_phase_presence = 0; + } + } + if (s->is_out_phase && !out_phase_measurement) { + s->out_phase_idx[1] = insamples ? insamples->pts : s->frame_end; + out_phase_duration = get_duration(s->out_phase_idx); + if (out_phase_duration >= s->duration) { + if (insamples) { + add_metadata(insamples, "out_phase_end", av_ts2timestr(s->out_phase_idx[1], &s->time_base)); + add_metadata(insamples, "out_phase_duration", av_ts2timestr(out_phase_duration, &s->time_base)); + } + av_log(s, AV_LOG_INFO, "out_phase_end: %s | out_phase_duration: %s\n", av_ts2timestr(s->out_phase_idx[1], &s->time_base), av_ts2timestr(out_phase_duration, &s->time_base)); + } + s->is_out_phase = 0; + } +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; @@ -154,6 +249,10 @@ AVFrame *out; uint8_t *dst; int i; + int mono_measurement; + int out_phase_measurement; + float tolerance = 1.0f - s->tolerance; + float angle = cosf(s->angle/180.0f*M_PI); if (s->do_video && (!s->out || s->out->width != outlink->w || s->out->height != outlink->h)) { @@ -193,6 +292,7 @@ fphase += phase; } fphase /= in->nb_samples; + s->phase = fphase; if (s->do_video) { if (s->draw_median_phase) { @@ -209,12 +309,29 @@ uint8_t value[128]; snprintf(value, sizeof(value), "%f", fphase); - av_dict_set(metadata, "lavfi.aphasemeter.phase", value, 0); + add_metadata(in, "phase", value); + } + + if (s->do_phasing_detection) { + s->time_base = inlink->time_base; + s->frame_end = in->pts + av_rescale_q(in->nb_samples, + (AVRational){ 1, in->sample_rate }, inlink->time_base); + + mono_measurement = (tolerance - fphase) < FLT_EPSILON; + out_phase_measurement = (angle - fphase) > FLT_EPSILON; + + update_mono_detection(s, in, mono_measurement); + update_out_phase_detection(s, in, out_phase_measurement); } if (s->do_video) { + AVFrame *clone; + s->out->pts = in->pts; - ff_filter_frame(outlink, av_frame_clone(s->out)); + clone = av_frame_clone(s->out); + if (!clone) + return AVERROR(ENOMEM); + ff_filter_frame(outlink, clone); } return ff_filter_frame(aoutlink, in); } @@ -222,11 +339,12 @@ static av_cold void uninit(AVFilterContext *ctx) { AudioPhaseMeterContext *s = ctx->priv; - int i; + if (s->do_phasing_detection) { + update_mono_detection(s, NULL, 0); + update_out_phase_detection(s, NULL, 0); + } av_frame_free(&s->out); - for (i = 0; i < ctx->nb_outputs; i++) - av_freep(&ctx->output_pads[i].name); } static av_cold int init(AVFilterContext *ctx) @@ -236,30 +354,22 @@ int ret; pad = (AVFilterPad){ - .name = av_strdup("out0"), + .name = "out0", .type = AVMEDIA_TYPE_AUDIO, }; - if (!pad.name) - return AVERROR(ENOMEM); ret = ff_insert_outpad(ctx, 0, &pad); - if (ret < 0) { - av_freep(&pad.name); + if (ret < 0) return ret; - } if (s->do_video) { pad = (AVFilterPad){ - .name = av_strdup("out1"), + .name = "out1", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_video_output, }; - if (!pad.name) - return AVERROR(ENOMEM); ret = ff_insert_outpad(ctx, 1, &pad); - if (ret < 0) { - av_freep(&pad.name); + if (ret < 0) return ret; - } } return 0; diff -Nru ffmpeg-4.2.2/libavfilter/avf_avectorscope.c ffmpeg-4.4/libavfilter/avf_avectorscope.c --- ffmpeg-4.2.2/libavfilter/avf_avectorscope.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avf_avectorscope.c 2021-04-08 21:28:39.000000000 +0000 @@ -190,17 +190,17 @@ int ret; formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref (formats, &inlink->out_formats )) < 0 || + if ((ret = ff_formats_ref (formats, &inlink->outcfg.formats )) < 0 || (ret = ff_add_channel_layout (&layout, AV_CH_LAYOUT_STEREO )) < 0 || - (ret = ff_channel_layouts_ref (layout , &inlink->out_channel_layouts)) < 0) + (ret = ff_channel_layouts_ref (layout , &inlink->outcfg.channel_layouts)) < 0) return ret; formats = ff_all_samplerates(); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0) return ret; formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; return 0; @@ -238,6 +238,7 @@ AudioVectorScopeContext *s = ctx->priv; const int hw = s->hw; const int hh = s->hh; + AVFrame *clone; unsigned x, y; unsigned prev_x = s->prev_x, prev_y = s->prev_y; double zoom = s->zoom; @@ -360,7 +361,11 @@ s->prev_x = x, s->prev_y = y; av_frame_free(&insamples); - return ff_filter_frame(outlink, av_frame_clone(s->outpicref)); + clone = av_frame_clone(s->outpicref); + if (!clone) + return AVERROR(ENOMEM); + + return ff_filter_frame(outlink, clone); } static int activate(AVFilterContext *ctx) diff -Nru ffmpeg-4.2.2/libavfilter/avf_concat.c ffmpeg-4.4/libavfilter/avf_concat.c --- ffmpeg-4.2.2/libavfilter/avf_concat.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avf_concat.c 2021-04-08 21:28:39.000000000 +0000 @@ -87,25 +87,25 @@ /* Set the output formats */ formats = ff_all_formats(type); - if ((ret = ff_formats_ref(formats, &ctx->outputs[idx]->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &ctx->outputs[idx]->incfg.formats)) < 0) return ret; if (type == AVMEDIA_TYPE_AUDIO) { rates = ff_all_samplerates(); - if ((ret = ff_formats_ref(rates, &ctx->outputs[idx]->in_samplerates)) < 0) + if ((ret = ff_formats_ref(rates, &ctx->outputs[idx]->incfg.samplerates)) < 0) return ret; layouts = ff_all_channel_layouts(); - if ((ret = ff_channel_layouts_ref(layouts, &ctx->outputs[idx]->in_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &ctx->outputs[idx]->incfg.channel_layouts)) < 0) return ret; } /* Set the same formats for each corresponding input */ for (seg = 0; seg < cat->nb_segments; seg++) { - if ((ret = ff_formats_ref(formats, &ctx->inputs[idx]->out_formats)) < 0) + if ((ret = ff_formats_ref(formats, &ctx->inputs[idx]->outcfg.formats)) < 0) return ret; if (type == AVMEDIA_TYPE_AUDIO) { - if ((ret = ff_formats_ref(rates, &ctx->inputs[idx]->out_samplerates)) < 0 || - (ret = ff_channel_layouts_ref(layouts, &ctx->inputs[idx]->out_channel_layouts)) < 0) + if ((ret = ff_formats_ref(rates, &ctx->inputs[idx]->outcfg.samplerates)) < 0 || + (ret = ff_channel_layouts_ref(layouts, &ctx->inputs[idx]->outcfg.channel_layouts)) < 0) return ret; } idx += ctx->nb_outputs; @@ -131,8 +131,21 @@ outlink->h = inlink->h; outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; outlink->format = inlink->format; + outlink->frame_rate = inlink->frame_rate; + + for (seg = 1; seg < cat->nb_segments; seg++) { + inlink = ctx->inputs[in_no + seg * ctx->nb_outputs]; + if (outlink->frame_rate.num != inlink->frame_rate.num || + outlink->frame_rate.den != inlink->frame_rate.den) { + av_log(ctx, AV_LOG_VERBOSE, + "Video inputs have different frame rates, output will be VFR\n"); + outlink->frame_rate = av_make_q(1, 0); + break; + } + } + for (seg = 1; seg < cat->nb_segments; seg++) { - inlink = ctx->inputs[in_no += ctx->nb_outputs]; + inlink = ctx->inputs[in_no + seg * ctx->nb_outputs]; if (!outlink->sample_aspect_ratio.num) outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; /* possible enhancement: unsafe mode, do not check */ @@ -238,6 +251,10 @@ if (!rate_tb.den) return AVERROR_BUG; + if (cat->in[in_no].pts < INT64_MIN + seg_delta) + return AVERROR_INVALIDDATA; + if (seg_delta < cat->in[in_no].pts) + return AVERROR_INVALIDDATA; nb_samples = av_rescale_q(seg_delta - cat->in[in_no].pts, outlink->time_base, rate_tb); frame_nb_samples = FFMAX(9600, rate_tb.den / 5); /* arbitrary */ diff -Nru ffmpeg-4.2.2/libavfilter/avfilter.c ffmpeg-4.4/libavfilter/avfilter.c --- ffmpeg-4.2.2/libavfilter/avfilter.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avfilter.c 2021-04-08 21:28:39.000000000 +0000 @@ -88,7 +88,7 @@ const char *avfilter_license(void) { #define LICENSE_PREFIX "libavfilter license: " - return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; } void ff_command_queue_pop(AVFilterContext *filter) @@ -232,11 +232,12 @@ ff_filter_set_ready(link->src, 200); } +#if FF_API_FILTER_LINK_SET_CLOSED void avfilter_link_set_closed(AVFilterLink *link, int closed) { ff_avfilter_link_set_out_status(link, closed ? AVERROR_EOF : 0, AV_NOPTS_VALUE); } - +#endif int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, unsigned filt_srcpad_idx, unsigned filt_dstpad_idx) { @@ -261,15 +262,15 @@ /* if any information on supported media formats already exists on the * link, we need to preserve that */ - if (link->out_formats) - ff_formats_changeref(&link->out_formats, - &filt->outputs[filt_dstpad_idx]->out_formats); - if (link->out_samplerates) - ff_formats_changeref(&link->out_samplerates, - &filt->outputs[filt_dstpad_idx]->out_samplerates); - if (link->out_channel_layouts) - ff_channel_layouts_changeref(&link->out_channel_layouts, - &filt->outputs[filt_dstpad_idx]->out_channel_layouts); + if (link->outcfg.formats) + ff_formats_changeref(&link->outcfg.formats, + &filt->outputs[filt_dstpad_idx]->outcfg.formats); + if (link->outcfg.samplerates) + ff_formats_changeref(&link->outcfg.samplerates, + &filt->outputs[filt_dstpad_idx]->outcfg.samplerates); + if (link->outcfg.channel_layouts) + ff_channel_layouts_changeref(&link->outcfg.channel_layouts, + &filt->outputs[filt_dstpad_idx]->outcfg.channel_layouts); return 0; } @@ -467,24 +468,6 @@ return ret; } -int ff_poll_frame(AVFilterLink *link) -{ - int i, min = INT_MAX; - - if (link->srcpad->poll_frame) - return link->srcpad->poll_frame(link); - - for (i = 0; i < link->src->nb_inputs; i++) { - int val; - if (!link->src->inputs[i]) - return AVERROR(EINVAL); - val = ff_poll_frame(link->src->inputs[i]); - min = FFMIN(min, val); - } - - return min; -} - static const char *const var_names[] = { "t", "n", @@ -601,6 +584,7 @@ return NULL; } +#if FF_API_CHILD_CLASS_NEXT static const AVClass *filter_child_class_next(const AVClass *prev) { void *opaque = NULL; @@ -622,14 +606,27 @@ return NULL; } +#endif + +static const AVClass *filter_child_class_iterate(void **iter) +{ + const AVFilter *f; + + while ((f = av_filter_iterate(iter))) + if (f->priv_class) + return f->priv_class; + + return NULL; +} #define OFFSET(x) offsetof(AVFilterContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption avfilter_options[] = { { "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, "thread_type" }, { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .flags = FLAGS, .unit = "thread_type" }, - { "enable", "set enable expression", OFFSET(enable_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS }, + { "enable", "set enable expression", OFFSET(enable_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = TFLAGS }, { "threads", "Allowed number of threads", OFFSET(nb_threads), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, { "extra_hw_frames", "Number of extra hardware frames to allocate for the user", @@ -643,7 +640,10 @@ .version = LIBAVUTIL_VERSION_INT, .category = AV_CLASS_CATEGORY_FILTER, .child_next = filter_child_next, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = filter_child_class_next, +#endif + .child_class_iterate = filter_child_class_iterate, .option = avfilter_options, }; @@ -748,12 +748,12 @@ av_buffer_unref(&link->hw_frames_ctx); - ff_formats_unref(&link->in_formats); - ff_formats_unref(&link->out_formats); - ff_formats_unref(&link->in_samplerates); - ff_formats_unref(&link->out_samplerates); - ff_channel_layouts_unref(&link->in_channel_layouts); - ff_channel_layouts_unref(&link->out_channel_layouts); + ff_formats_unref(&link->incfg.formats); + ff_formats_unref(&link->outcfg.formats); + ff_formats_unref(&link->incfg.samplerates); + ff_formats_unref(&link->outcfg.samplerates); + ff_channel_layouts_unref(&link->incfg.channel_layouts); + ff_channel_layouts_unref(&link->outcfg.channel_layouts); avfilter_link_free(&link); } @@ -801,9 +801,9 @@ int ff_filter_get_nb_threads(AVFilterContext *ctx) { - if (ctx->nb_threads > 0) - return FFMIN(ctx->nb_threads, ctx->graph->nb_threads); - return ctx->graph->nb_threads; + if (ctx->nb_threads > 0) + return FFMIN(ctx->nb_threads, ctx->graph->nb_threads); + return ctx->graph->nb_threads; } static int process_options(AVFilterContext *ctx, AVDictionary **options, @@ -859,31 +859,39 @@ return ret; } } else { - av_dict_set(options, key, value, 0); - if ((ret = av_opt_set(ctx->priv, key, value, AV_OPT_SEARCH_CHILDREN)) < 0) { - if (!av_opt_find(ctx->priv, key, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) { - if (ret == AVERROR_OPTION_NOT_FOUND) - av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key); - av_free(value); - av_free(parsed_key); - return ret; + av_dict_set(options, key, value, 0); + if ((ret = av_opt_set(ctx->priv, key, value, AV_OPT_SEARCH_CHILDREN)) < 0) { + if (!av_opt_find(ctx->priv, key, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) { + if (ret == AVERROR_OPTION_NOT_FOUND) + av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key); + av_free(value); + av_free(parsed_key); + return ret; + } } } - } av_free(value); av_free(parsed_key); count++; } - if (ctx->enable_str) { - ret = set_enable_expr(ctx, ctx->enable_str); - if (ret < 0) - return ret; - } return count; } +int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, + const char *arg, char *res, int res_len, int flags) +{ + const AVOption *o; + + if (!ctx->filter->priv_class) + return 0; + o = av_opt_find2(ctx->priv, cmd, NULL, AV_OPT_FLAG_RUNTIME_PARAM | AV_OPT_FLAG_FILTERING_PARAM, AV_OPT_SEARCH_CHILDREN, NULL); + if (!o) + return AVERROR(ENOSYS); + return av_opt_set(ctx->priv, cmd, arg, 0); +} + int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options) { int ret = 0; @@ -918,6 +926,12 @@ else if (ctx->filter->init_dict) ret = ctx->filter->init_dict(ctx, options); + if (ctx->enable_str) { + ret = set_enable_expr(ctx, ctx->enable_str); + if (ret < 0) + return ret; + } + return ret; } @@ -1413,9 +1427,6 @@ Rationale: checking frame_blocked_in is necessary to avoid requesting repeatedly on a blocked input if another is not blocked (example: [buffersrc1][testsrc1][buffersrc2][testsrc2]concat=v=2). - - TODO: respect needs_fifo and remove auto-inserted fifos. - */ int ff_filter_activate(AVFilterContext *filter) diff -Nru ffmpeg-4.2.2/libavfilter/avfiltergraph.c ffmpeg-4.4/libavfilter/avfiltergraph.c --- ffmpeg-4.2.2/libavfilter/avfiltergraph.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avfiltergraph.c 2021-04-08 21:28:39.000000000 +0000 @@ -313,6 +313,53 @@ } } +static int filter_link_check_formats(void *log, AVFilterLink *link, AVFilterFormatsConfig *cfg) +{ + int ret; + + switch (link->type) { + + case AVMEDIA_TYPE_VIDEO: + if ((ret = ff_formats_check_pixel_formats(log, cfg->formats)) < 0) + return ret; + break; + + case AVMEDIA_TYPE_AUDIO: + if ((ret = ff_formats_check_sample_formats(log, cfg->formats)) < 0 || + (ret = ff_formats_check_sample_rates(log, cfg->samplerates)) < 0 || + (ret = ff_formats_check_channel_layouts(log, cfg->channel_layouts)) < 0) + return ret; + break; + + default: + av_assert0(!"reached"); + } + return 0; +} + +/** + * Check the validity of the formats / etc. lists set by query_formats(). + * + * In particular, check they do not contain any redundant element. + */ +static int filter_check_formats(AVFilterContext *ctx) +{ + unsigned i; + int ret; + + for (i = 0; i < ctx->nb_inputs; i++) { + ret = filter_link_check_formats(ctx, ctx->inputs[i], &ctx->inputs[i]->outcfg); + if (ret < 0) + return ret; + } + for (i = 0; i < ctx->nb_outputs; i++) { + ret = filter_link_check_formats(ctx, ctx->outputs[i], &ctx->outputs[i]->incfg); + if (ret < 0) + return ret; + } + return 0; +} + static int filter_query_formats(AVFilterContext *ctx) { int ret, i; @@ -329,11 +376,14 @@ ctx->name, av_err2str(ret)); return ret; } + ret = filter_check_formats(ctx); + if (ret < 0) + return ret; for (i = 0; i < ctx->nb_inputs; i++) - sanitize_channel_layouts(ctx, ctx->inputs[i]->out_channel_layouts); + sanitize_channel_layouts(ctx, ctx->inputs[i]->outcfg.channel_layouts); for (i = 0; i < ctx->nb_outputs; i++) - sanitize_channel_layouts(ctx, ctx->outputs[i]->in_channel_layouts); + sanitize_channel_layouts(ctx, ctx->outputs[i]->incfg.channel_layouts); formats = ff_all_formats(type); if ((ret = ff_set_common_formats(ctx, formats)) < 0) @@ -354,79 +404,24 @@ int i; for (i = 0; i < f->nb_inputs; i++) { - if (!f->inputs[i]->out_formats) + if (!f->inputs[i]->outcfg.formats) return 0; if (f->inputs[i]->type == AVMEDIA_TYPE_AUDIO && - !(f->inputs[i]->out_samplerates && - f->inputs[i]->out_channel_layouts)) + !(f->inputs[i]->outcfg.samplerates && + f->inputs[i]->outcfg.channel_layouts)) return 0; } for (i = 0; i < f->nb_outputs; i++) { - if (!f->outputs[i]->in_formats) + if (!f->outputs[i]->incfg.formats) return 0; if (f->outputs[i]->type == AVMEDIA_TYPE_AUDIO && - !(f->outputs[i]->in_samplerates && - f->outputs[i]->in_channel_layouts)) + !(f->outputs[i]->incfg.samplerates && + f->outputs[i]->incfg.channel_layouts)) return 0; } return 1; } -static AVFilterFormats *clone_filter_formats(AVFilterFormats *arg) -{ - AVFilterFormats *a = av_memdup(arg, sizeof(*arg)); - if (a) { - a->refcount = 0; - a->refs = NULL; - a->formats = av_memdup(a->formats, sizeof(*a->formats) * a->nb_formats); - if (!a->formats && arg->formats) - av_freep(&a); - } - return a; -} - -static int can_merge_formats(AVFilterFormats *a_arg, - AVFilterFormats *b_arg, - enum AVMediaType type, - int is_sample_rate) -{ - AVFilterFormats *a, *b, *ret; - if (a_arg == b_arg) - return 1; - a = clone_filter_formats(a_arg); - b = clone_filter_formats(b_arg); - - if (!a || !b) { - if (a) - av_freep(&a->formats); - if (b) - av_freep(&b->formats); - - av_freep(&a); - av_freep(&b); - - return 0; - } - - if (is_sample_rate) { - ret = ff_merge_samplerates(a, b); - } else { - ret = ff_merge_formats(a, b, type); - } - if (ret) { - av_freep(&ret->formats); - av_freep(&ret->refs); - av_freep(&ret); - return 1; - } else { - av_freep(&a->formats); - av_freep(&b->formats); - av_freep(&a); - av_freep(&b); - return 0; - } -} - /** * Perform one round of query_formats() and merging formats lists on the * filter graph. @@ -471,47 +466,42 @@ if (!link) continue; - if (link->in_formats != link->out_formats - && link->in_formats && link->out_formats) - if (!can_merge_formats(link->in_formats, link->out_formats, - link->type, 0)) + if (link->incfg.formats != link->outcfg.formats + && link->incfg.formats && link->outcfg.formats) + if (!ff_can_merge_formats(link->incfg.formats, link->outcfg.formats, + link->type)) convert_needed = 1; if (link->type == AVMEDIA_TYPE_AUDIO) { - if (link->in_samplerates != link->out_samplerates - && link->in_samplerates && link->out_samplerates) - if (!can_merge_formats(link->in_samplerates, - link->out_samplerates, - 0, 1)) + if (link->incfg.samplerates != link->outcfg.samplerates + && link->incfg.samplerates && link->outcfg.samplerates) + if (!ff_can_merge_samplerates(link->incfg.samplerates, + link->outcfg.samplerates)) convert_needed = 1; } -#define MERGE_DISPATCH(field, statement) \ - if (!(link->in_ ## field && link->out_ ## field)) { \ +#define CHECKED_MERGE(field, ...) ((ret = ff_merge_ ## field(__VA_ARGS__)) <= 0) +#define MERGE_DISPATCH(field, ...) \ + if (!(link->incfg.field && link->outcfg.field)) { \ count_delayed++; \ - } else if (link->in_ ## field == link->out_ ## field) { \ + } else if (link->incfg.field == link->outcfg.field) { \ count_already_merged++; \ } else if (!convert_needed) { \ count_merged++; \ - statement \ + if (CHECKED_MERGE(field, __VA_ARGS__)) { \ + if (ret < 0) \ + return ret; \ + convert_needed = 1; \ + } \ } if (link->type == AVMEDIA_TYPE_AUDIO) { - MERGE_DISPATCH(channel_layouts, - if (!ff_merge_channel_layouts(link->in_channel_layouts, - link->out_channel_layouts)) - convert_needed = 1; - ) - MERGE_DISPATCH(samplerates, - if (!ff_merge_samplerates(link->in_samplerates, - link->out_samplerates)) - convert_needed = 1; - ) + MERGE_DISPATCH(channel_layouts, link->incfg.channel_layouts, + link->outcfg.channel_layouts) + MERGE_DISPATCH(samplerates, link->incfg.samplerates, + link->outcfg.samplerates) } - MERGE_DISPATCH(formats, - if (!ff_merge_formats(link->in_formats, link->out_formats, - link->type)) - convert_needed = 1; - ) + MERGE_DISPATCH(formats, link->incfg.formats, + link->outcfg.formats, link->type) #undef MERGE_DISPATCH if (convert_needed) { @@ -571,41 +561,40 @@ inlink = convert->inputs[0]; outlink = convert->outputs[0]; - av_assert0( inlink-> in_formats->refcount > 0); - av_assert0( inlink->out_formats->refcount > 0); - av_assert0(outlink-> in_formats->refcount > 0); - av_assert0(outlink->out_formats->refcount > 0); + av_assert0( inlink->incfg.formats->refcount > 0); + av_assert0( inlink->outcfg.formats->refcount > 0); + av_assert0(outlink->incfg.formats->refcount > 0); + av_assert0(outlink->outcfg.formats->refcount > 0); if (outlink->type == AVMEDIA_TYPE_AUDIO) { - av_assert0( inlink-> in_samplerates->refcount > 0); - av_assert0( inlink->out_samplerates->refcount > 0); - av_assert0(outlink-> in_samplerates->refcount > 0); - av_assert0(outlink->out_samplerates->refcount > 0); - av_assert0( inlink-> in_channel_layouts->refcount > 0); - av_assert0( inlink->out_channel_layouts->refcount > 0); - av_assert0(outlink-> in_channel_layouts->refcount > 0); - av_assert0(outlink->out_channel_layouts->refcount > 0); + av_assert0( inlink-> incfg.samplerates->refcount > 0); + av_assert0( inlink->outcfg.samplerates->refcount > 0); + av_assert0(outlink-> incfg.samplerates->refcount > 0); + av_assert0(outlink->outcfg.samplerates->refcount > 0); + av_assert0( inlink-> incfg.channel_layouts->refcount > 0); + av_assert0( inlink->outcfg.channel_layouts->refcount > 0); + av_assert0(outlink-> incfg.channel_layouts->refcount > 0); + av_assert0(outlink->outcfg.channel_layouts->refcount > 0); } - if (!ff_merge_formats( inlink->in_formats, inlink->out_formats, inlink->type) || - !ff_merge_formats(outlink->in_formats, outlink->out_formats, outlink->type)) - ret = AVERROR(ENOSYS); - if (inlink->type == AVMEDIA_TYPE_AUDIO && - (!ff_merge_samplerates(inlink->in_samplerates, - inlink->out_samplerates) || - !ff_merge_channel_layouts(inlink->in_channel_layouts, - inlink->out_channel_layouts))) - ret = AVERROR(ENOSYS); - if (outlink->type == AVMEDIA_TYPE_AUDIO && - (!ff_merge_samplerates(outlink->in_samplerates, - outlink->out_samplerates) || - !ff_merge_channel_layouts(outlink->in_channel_layouts, - outlink->out_channel_layouts))) - ret = AVERROR(ENOSYS); - - if (ret < 0) { + if (CHECKED_MERGE(formats, inlink->incfg.formats, + inlink->outcfg.formats, inlink->type) || + CHECKED_MERGE(formats, outlink->incfg.formats, + outlink->outcfg.formats, outlink->type) || + inlink->type == AVMEDIA_TYPE_AUDIO && + (CHECKED_MERGE(samplerates, inlink->incfg.samplerates, + inlink->outcfg.samplerates) || + CHECKED_MERGE(channel_layouts, inlink->incfg.channel_layouts, + inlink->outcfg.channel_layouts)) || + outlink->type == AVMEDIA_TYPE_AUDIO && + (CHECKED_MERGE(samplerates, outlink->incfg.samplerates, + outlink->outcfg.samplerates) || + CHECKED_MERGE(channel_layouts, outlink->incfg.channel_layouts, + outlink->outcfg.channel_layouts))) { + if (ret < 0) + return ret; av_log(log_ctx, AV_LOG_ERROR, "Impossible to convert between the formats supported by the filter " "'%s' and the filter '%s'\n", link->src->name, link->dst->name); - return ret; + return AVERROR(ENOSYS); } } } @@ -674,7 +663,7 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) { - if (!link || !link->in_formats) + if (!link || !link->incfg.formats) return 0; if (link->type == AVMEDIA_TYPE_VIDEO) { @@ -683,98 +672,98 @@ int has_alpha= av_pix_fmt_desc_get(ref->format)->nb_components % 2 == 0; enum AVPixelFormat best= AV_PIX_FMT_NONE; int i; - for (i=0; iin_formats->nb_formats; i++) { - enum AVPixelFormat p = link->in_formats->formats[i]; + for (i = 0; i < link->incfg.formats->nb_formats; i++) { + enum AVPixelFormat p = link->incfg.formats->formats[i]; best= av_find_best_pix_fmt_of_2(best, p, ref->format, has_alpha, NULL); } av_log(link->src,AV_LOG_DEBUG, "picking %s out of %d ref:%s alpha:%d\n", - av_get_pix_fmt_name(best), link->in_formats->nb_formats, + av_get_pix_fmt_name(best), link->incfg.formats->nb_formats, av_get_pix_fmt_name(ref->format), has_alpha); - link->in_formats->formats[0] = best; + link->incfg.formats->formats[0] = best; } } else if (link->type == AVMEDIA_TYPE_AUDIO) { if(ref && ref->type == AVMEDIA_TYPE_AUDIO){ enum AVSampleFormat best= AV_SAMPLE_FMT_NONE; int i; - for (i=0; iin_formats->nb_formats; i++) { - enum AVSampleFormat p = link->in_formats->formats[i]; + for (i = 0; i < link->incfg.formats->nb_formats; i++) { + enum AVSampleFormat p = link->incfg.formats->formats[i]; best = find_best_sample_fmt_of_2(best, p, ref->format); } av_log(link->src,AV_LOG_DEBUG, "picking %s out of %d ref:%s\n", - av_get_sample_fmt_name(best), link->in_formats->nb_formats, + av_get_sample_fmt_name(best), link->incfg.formats->nb_formats, av_get_sample_fmt_name(ref->format)); - link->in_formats->formats[0] = best; + link->incfg.formats->formats[0] = best; } } - link->in_formats->nb_formats = 1; - link->format = link->in_formats->formats[0]; + link->incfg.formats->nb_formats = 1; + link->format = link->incfg.formats->formats[0]; if (link->type == AVMEDIA_TYPE_AUDIO) { - if (!link->in_samplerates->nb_formats) { + if (!link->incfg.samplerates->nb_formats) { av_log(link->src, AV_LOG_ERROR, "Cannot select sample rate for" " the link between filters %s and %s.\n", link->src->name, link->dst->name); return AVERROR(EINVAL); } - link->in_samplerates->nb_formats = 1; - link->sample_rate = link->in_samplerates->formats[0]; + link->incfg.samplerates->nb_formats = 1; + link->sample_rate = link->incfg.samplerates->formats[0]; - if (link->in_channel_layouts->all_layouts) { + if (link->incfg.channel_layouts->all_layouts) { av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for" " the link between filters %s and %s.\n", link->src->name, link->dst->name); - if (!link->in_channel_layouts->all_counts) + if (!link->incfg.channel_layouts->all_counts) av_log(link->src, AV_LOG_ERROR, "Unknown channel layouts not " "supported, try specifying a channel layout using " "'aformat=channel_layouts=something'.\n"); return AVERROR(EINVAL); } - link->in_channel_layouts->nb_channel_layouts = 1; - link->channel_layout = link->in_channel_layouts->channel_layouts[0]; + link->incfg.channel_layouts->nb_channel_layouts = 1; + link->channel_layout = link->incfg.channel_layouts->channel_layouts[0]; if ((link->channels = FF_LAYOUT2COUNT(link->channel_layout))) link->channel_layout = 0; else link->channels = av_get_channel_layout_nb_channels(link->channel_layout); } - ff_formats_unref(&link->in_formats); - ff_formats_unref(&link->out_formats); - ff_formats_unref(&link->in_samplerates); - ff_formats_unref(&link->out_samplerates); - ff_channel_layouts_unref(&link->in_channel_layouts); - ff_channel_layouts_unref(&link->out_channel_layouts); + ff_formats_unref(&link->incfg.formats); + ff_formats_unref(&link->outcfg.formats); + ff_formats_unref(&link->incfg.samplerates); + ff_formats_unref(&link->outcfg.samplerates); + ff_channel_layouts_unref(&link->incfg.channel_layouts); + ff_channel_layouts_unref(&link->outcfg.channel_layouts); return 0; } -#define REDUCE_FORMATS(fmt_type, list_type, list, var, nb, add_format, unref_format) \ +#define REDUCE_FORMATS(fmt_type, list_type, list, var, nb, add_format) \ do { \ for (i = 0; i < filter->nb_inputs; i++) { \ AVFilterLink *link = filter->inputs[i]; \ fmt_type fmt; \ \ - if (!link->out_ ## list || link->out_ ## list->nb != 1) \ + if (!link->outcfg.list || link->outcfg.list->nb != 1) \ continue; \ - fmt = link->out_ ## list->var[0]; \ + fmt = link->outcfg.list->var[0]; \ \ for (j = 0; j < filter->nb_outputs; j++) { \ AVFilterLink *out_link = filter->outputs[j]; \ list_type *fmts; \ \ if (link->type != out_link->type || \ - out_link->in_ ## list->nb == 1) \ + out_link->incfg.list->nb == 1) \ continue; \ - fmts = out_link->in_ ## list; \ + fmts = out_link->incfg.list; \ \ - if (!out_link->in_ ## list->nb) { \ - if ((ret = add_format(&out_link->in_ ##list, fmt)) < 0)\ + if (!out_link->incfg.list->nb) { \ + if ((ret = add_format(&out_link->incfg.list, fmt)) < 0)\ return ret; \ ret = 1; \ break; \ } \ \ - for (k = 0; k < out_link->in_ ## list->nb; k++) \ + for (k = 0; k < out_link->incfg.list->nb; k++) \ if (fmts->var[k] == fmt) { \ fmts->var[0] = fmt; \ fmts->nb = 1; \ @@ -790,25 +779,25 @@ int i, j, k, ret = 0; REDUCE_FORMATS(int, AVFilterFormats, formats, formats, - nb_formats, ff_add_format, ff_formats_unref); + nb_formats, ff_add_format); REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats, - nb_formats, ff_add_format, ff_formats_unref); + nb_formats, ff_add_format); /* reduce channel layouts */ for (i = 0; i < filter->nb_inputs; i++) { AVFilterLink *inlink = filter->inputs[i]; uint64_t fmt; - if (!inlink->out_channel_layouts || - inlink->out_channel_layouts->nb_channel_layouts != 1) + if (!inlink->outcfg.channel_layouts || + inlink->outcfg.channel_layouts->nb_channel_layouts != 1) continue; - fmt = inlink->out_channel_layouts->channel_layouts[0]; + fmt = inlink->outcfg.channel_layouts->channel_layouts[0]; for (j = 0; j < filter->nb_outputs; j++) { AVFilterLink *outlink = filter->outputs[j]; AVFilterChannelLayouts *fmts; - fmts = outlink->in_channel_layouts; + fmts = outlink->incfg.channel_layouts; if (inlink->type != outlink->type || fmts->nb_channel_layouts == 1) continue; @@ -816,12 +805,12 @@ (!FF_LAYOUT2COUNT(fmt) || fmts->all_counts)) { /* Turn the infinite list into a singleton */ fmts->all_layouts = fmts->all_counts = 0; - if (ff_add_channel_layout(&outlink->in_channel_layouts, fmt) < 0) + if (ff_add_channel_layout(&outlink->incfg.channel_layouts, fmt) < 0) ret = 1; break; } - for (k = 0; k < outlink->in_channel_layouts->nb_channel_layouts; k++) { + for (k = 0; k < outlink->incfg.channel_layouts->nb_channel_layouts; k++) { if (fmts->channel_layouts[k] == fmt) { fmts->channel_layouts[0] = fmt; fmts->nb_channel_layouts = 1; @@ -862,24 +851,24 @@ link = filter->inputs[i]; if (link->type == AVMEDIA_TYPE_AUDIO && - link->out_samplerates->nb_formats== 1) + link->outcfg.samplerates->nb_formats== 1) break; } if (i == filter->nb_inputs) return; - sample_rate = link->out_samplerates->formats[0]; + sample_rate = link->outcfg.samplerates->formats[0]; for (i = 0; i < filter->nb_outputs; i++) { AVFilterLink *outlink = filter->outputs[i]; int best_idx, best_diff = INT_MAX; if (outlink->type != AVMEDIA_TYPE_AUDIO || - outlink->in_samplerates->nb_formats < 2) + outlink->incfg.samplerates->nb_formats < 2) continue; - for (j = 0; j < outlink->in_samplerates->nb_formats; j++) { - int diff = abs(sample_rate - outlink->in_samplerates->formats[j]); + for (j = 0; j < outlink->incfg.samplerates->nb_formats; j++) { + int diff = abs(sample_rate - outlink->incfg.samplerates->formats[j]); av_assert0(diff < INT_MAX); // This would lead to the use of uninitialized best_diff but is only possible with invalid sample rates @@ -888,8 +877,8 @@ best_idx = j; } } - FFSWAP(int, outlink->in_samplerates->formats[0], - outlink->in_samplerates->formats[best_idx]); + FFSWAP(int, outlink->incfg.samplerates->formats[0], + outlink->incfg.samplerates->formats[best_idx]); } } @@ -944,7 +933,7 @@ link = filter->inputs[i]; if (link->type == AVMEDIA_TYPE_AUDIO && - link->out_channel_layouts->nb_channel_layouts == 1) + link->outcfg.channel_layouts->nb_channel_layouts == 1) break; } if (i == filter->nb_inputs) @@ -955,12 +944,12 @@ int best_idx = -1, best_score = INT_MIN, best_count_diff = INT_MAX; if (outlink->type != AVMEDIA_TYPE_AUDIO || - outlink->in_channel_layouts->nb_channel_layouts < 2) + outlink->incfg.channel_layouts->nb_channel_layouts < 2) continue; - for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) { - uint64_t in_chlayout = link->out_channel_layouts->channel_layouts[0]; - uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j]; + for (j = 0; j < outlink->incfg.channel_layouts->nb_channel_layouts; j++) { + uint64_t in_chlayout = link->outcfg.channel_layouts->channel_layouts[0]; + uint64_t out_chlayout = outlink->incfg.channel_layouts->channel_layouts[j]; int in_channels = av_get_channel_layout_nb_channels(in_chlayout); int out_channels = av_get_channel_layout_nb_channels(out_chlayout); int count_diff = out_channels - in_channels; @@ -1018,8 +1007,8 @@ } } av_assert0(best_idx >= 0); - FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0], - outlink->in_channel_layouts->channel_layouts[best_idx]); + FFSWAP(uint64_t, outlink->incfg.channel_layouts->channel_layouts[0], + outlink->incfg.channel_layouts->channel_layouts[best_idx]); } } @@ -1042,13 +1031,13 @@ link = filter->inputs[i]; if (link->type == AVMEDIA_TYPE_AUDIO && - link->out_formats->nb_formats == 1) + link->outcfg.formats->nb_formats == 1) break; } if (i == filter->nb_inputs) return; - format = link->out_formats->formats[0]; + format = link->outcfg.formats->formats[0]; bps = av_get_bytes_per_sample(format); for (i = 0; i < filter->nb_outputs; i++) { @@ -1056,11 +1045,11 @@ int best_idx = -1, best_score = INT_MIN; if (outlink->type != AVMEDIA_TYPE_AUDIO || - outlink->in_formats->nb_formats < 2) + outlink->incfg.formats->nb_formats < 2) continue; - for (j = 0; j < outlink->in_formats->nb_formats; j++) { - int out_format = outlink->in_formats->formats[j]; + for (j = 0; j < outlink->incfg.formats->nb_formats; j++) { + int out_format = outlink->incfg.formats->formats[j]; int out_bps = av_get_bytes_per_sample(out_format); int score; @@ -1087,8 +1076,8 @@ } } av_assert0(best_idx >= 0); - FFSWAP(int, outlink->in_formats->formats[0], - outlink->in_formats->formats[best_idx]); + FFSWAP(int, outlink->incfg.formats->formats[0], + outlink->incfg.formats->formats[best_idx]); } } @@ -1112,7 +1101,7 @@ AVFilterContext *filter = graph->filters[i]; if (filter->nb_inputs){ for (j = 0; j < filter->nb_inputs; j++){ - if(filter->inputs[j]->in_formats && filter->inputs[j]->in_formats->nb_formats == 1) { + if (filter->inputs[j]->incfg.formats && filter->inputs[j]->incfg.formats->nb_formats == 1) { if ((ret = pick_format(filter->inputs[j], NULL)) < 0) return ret; change = 1; @@ -1121,7 +1110,7 @@ } if (filter->nb_outputs){ for (j = 0; j < filter->nb_outputs; j++){ - if(filter->outputs[j]->in_formats && filter->outputs[j]->in_formats->nb_formats == 1) { + if (filter->outputs[j]->incfg.formats && filter->outputs[j]->incfg.formats->nb_formats == 1) { if ((ret = pick_format(filter->outputs[j], NULL)) < 0) return ret; change = 1; @@ -1130,7 +1119,7 @@ } if (filter->nb_inputs && filter->nb_outputs && filter->inputs[0]->format>=0) { for (j = 0; j < filter->nb_outputs; j++) { - if(filter->outputs[j]->format<0) { + if (filter->outputs[j]->format<0) { if ((ret = pick_format(filter->outputs[j], filter->inputs[0])) < 0) return ret; change = 1; @@ -1226,52 +1215,12 @@ return 0; } -static int graph_insert_fifos(AVFilterGraph *graph, AVClass *log_ctx) -{ - AVFilterContext *f; - int i, j, ret; - int fifo_count = 0; - - for (i = 0; i < graph->nb_filters; i++) { - f = graph->filters[i]; - - for (j = 0; j < f->nb_inputs; j++) { - AVFilterLink *link = f->inputs[j]; - AVFilterContext *fifo_ctx; - const AVFilter *fifo; - char name[32]; - - if (!link->dstpad->needs_fifo) - continue; - - fifo = f->inputs[j]->type == AVMEDIA_TYPE_VIDEO ? - avfilter_get_by_name("fifo") : - avfilter_get_by_name("afifo"); - - snprintf(name, sizeof(name), "auto_fifo_%d", fifo_count++); - - ret = avfilter_graph_create_filter(&fifo_ctx, fifo, name, NULL, - NULL, graph); - if (ret < 0) - return ret; - - ret = avfilter_insert_filter(link, fifo_ctx, 0, 0); - if (ret < 0) - return ret; - } - } - - return 0; -} - int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx) { int ret; if ((ret = graph_check_validity(graphctx, log_ctx))) return ret; - if ((ret = graph_insert_fifos(graphctx, log_ctx)) < 0) - return ret; if ((ret = graph_config_formats(graphctx, log_ctx))) return ret; if ((ret = graph_config_links(graphctx, log_ctx))) diff -Nru ffmpeg-4.2.2/libavfilter/avfilter.h ffmpeg-4.4/libavfilter/avfilter.h --- ffmpeg-4.2.2/libavfilter/avfilter.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avfilter.h 2021-04-08 21:28:39.000000000 +0000 @@ -68,6 +68,7 @@ typedef struct AVFilterLink AVFilterLink; typedef struct AVFilterPad AVFilterPad; typedef struct AVFilterFormats AVFilterFormats; +typedef struct AVFilterChannelLayouts AVFilterChannelLayouts; /** * Get the number of elements in a NULL-terminated array of AVFilterPads (e.g. @@ -79,7 +80,7 @@ * Get the name of an AVFilterPad. * * @param pads an array of AVFilterPads - * @param pad_idx index of the pad in the array it; is the caller's + * @param pad_idx index of the pad in the array; it is the caller's * responsibility to ensure the index is valid * * @return name of the pad_idx'th pad in pads @@ -264,13 +265,13 @@ * and outputs are fixed), shortly before the format negotiation. This * callback may be called more than once. * - * This callback must set AVFilterLink.out_formats on every input link and - * AVFilterLink.in_formats on every output link to a list of pixel/sample + * This callback must set AVFilterLink.outcfg.formats on every input link and + * AVFilterLink.incfg.formats on every output link to a list of pixel/sample * formats that the filter supports on that link. For audio links, this - * filter must also set @ref AVFilterLink.in_samplerates "in_samplerates" / - * @ref AVFilterLink.out_samplerates "out_samplerates" and - * @ref AVFilterLink.in_channel_layouts "in_channel_layouts" / - * @ref AVFilterLink.out_channel_layouts "out_channel_layouts" analogously. + * filter must also set @ref AVFilterLink.incfg.samplerates "in_samplerates" / + * @ref AVFilterLink.outcfg.samplerates "out_samplerates" and + * @ref AVFilterLink.incfg.channel_layouts "in_channel_layouts" / + * @ref AVFilterLink.outcfg.channel_layouts "out_channel_layouts" analogously. * * This callback may be NULL for filters with one input, in which case * libavfilter assumes that it supports all input formats and preserves @@ -285,11 +286,13 @@ int flags_internal; ///< Additional flags for avfilter internal use only. +#if FF_API_NEXT /** * Used by the filter registration system. Must not be touched by any other * code. */ struct AVFilter *next; +#endif /** * Make the filter instance process a command. @@ -425,6 +428,35 @@ }; /** + * Lists of formats / etc. supported by an end of a link. + * + * This structure is directly part of AVFilterLink, in two copies: + * one for the source filter, one for the destination filter. + + * These lists are used for negotiating the format to actually be used, + * which will be loaded into the format and channel_layout members of + * AVFilterLink, when chosen. + */ +typedef struct AVFilterFormatsConfig { + + /** + * List of supported formats (pixel or sample). + */ + AVFilterFormats *formats; + + /** + * Lists of supported sample rates, only for audio. + */ + AVFilterFormats *samplerates; + + /** + * Lists of supported channel layouts, only for audio. + */ + AVFilterChannelLayouts *channel_layouts; + +} AVFilterFormatsConfig; + +/** * A link between two filters. This contains pointers to the source and * destination filters between which this link exists, and the indexes of * the pads involved. In addition, this link also contains the parameters @@ -471,33 +503,16 @@ * New public fields should be added right above. ***************************************************************** */ - /** - * Lists of formats and channel layouts supported by the input and output - * filters respectively. These lists are used for negotiating the format - * to actually be used, which will be loaded into the format and - * channel_layout members, above, when chosen. - * - */ - AVFilterFormats *in_formats; - AVFilterFormats *out_formats; /** - * Lists of channel layouts and sample rates used for automatic - * negotiation. + * Lists of supported formats / etc. supported by the input filter. */ - AVFilterFormats *in_samplerates; - AVFilterFormats *out_samplerates; - struct AVFilterChannelLayouts *in_channel_layouts; - struct AVFilterChannelLayouts *out_channel_layouts; + AVFilterFormatsConfig incfg; /** - * Audio only, the destination filter sets this to a non-zero value to - * request that buffers with the given number of samples should be sent to - * it. AVFilterPad.needs_fifo must also be set on the corresponding input - * pad. - * Last buffer before EOF will be padded with silence. + * Lists of supported formats / etc. supported by the output filter. */ - int request_samples; + AVFilterFormatsConfig outcfg; /** stage of the initialization of the link properties (dimensions, etc) */ enum { @@ -573,11 +588,6 @@ int channels; /** - * Link processing flags. - */ - unsigned flags; - - /** * Number of past frames sent through the link. */ int64_t frame_count_in, frame_count_out; @@ -671,7 +681,7 @@ attribute_deprecated int avfilter_link_get_channels(AVFilterLink *link); #endif - +#if FF_API_FILTER_LINK_SET_CLOSED /** * Set the closed field of a link. * @deprecated applications are not supposed to mess with links, they should @@ -679,7 +689,7 @@ */ attribute_deprecated void avfilter_link_set_closed(AVFilterLink *link, int closed); - +#endif /** * Negotiate the media format, dimensions, etc of all inputs to a filter. * @@ -947,7 +957,7 @@ /** * Create and add a filter instance into an existing graph. * The filter instance is created from the filter filt and inited - * with the parameters args and opaque. + * with the parameter args. opaque is currently ignored. * * In case of success put in *filt_ctx the pointer to the created * filter instance, otherwise set *filt_ctx to NULL. diff -Nru ffmpeg-4.2.2/libavfilter/avf_showcqt.c ffmpeg-4.4/libavfilter/avf_showcqt.c --- ffmpeg-4.2.2/libavfilter/avf_showcqt.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avf_showcqt.c 2021-04-08 21:28:39.000000000 +0000 @@ -67,10 +67,10 @@ { "axis_h", "set axis height", OFFSET(axis_h), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, { "sono_h", "set sonogram height", OFFSET(sono_h), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, { "fullhd", "set fullhd size", OFFSET(fullhd), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS }, - { "sono_v", "set sonogram volume", OFFSET(sono_v), AV_OPT_TYPE_STRING, { .str = "16" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "volume", "set sonogram volume", OFFSET(sono_v), AV_OPT_TYPE_STRING, { .str = "16" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "bar_v", "set bargraph volume", OFFSET(bar_v), AV_OPT_TYPE_STRING, { .str = "sono_v" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "volume2", "set bargraph volume", OFFSET(bar_v), AV_OPT_TYPE_STRING, { .str = "sono_v" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "sono_v", "set sonogram volume", OFFSET(sono_v), AV_OPT_TYPE_STRING, { .str = "16" }, 0, 0, FLAGS }, + { "volume", "set sonogram volume", OFFSET(sono_v), AV_OPT_TYPE_STRING, { .str = "16" }, 0, 0, FLAGS }, + { "bar_v", "set bargraph volume", OFFSET(bar_v), AV_OPT_TYPE_STRING, { .str = "sono_v" }, 0, 0, FLAGS }, + { "volume2", "set bargraph volume", OFFSET(bar_v), AV_OPT_TYPE_STRING, { .str = "sono_v" }, 0, 0, FLAGS }, { "sono_g", "set sonogram gamma", OFFSET(sono_g), AV_OPT_TYPE_FLOAT, { .dbl = 3.0 }, 1.0, 7.0, FLAGS }, { "gamma", "set sonogram gamma", OFFSET(sono_g), AV_OPT_TYPE_FLOAT, { .dbl = 3.0 }, 1.0, 7.0, FLAGS }, { "bar_g", "set bargraph gamma", OFFSET(bar_g), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 1.0, 7.0, FLAGS }, @@ -82,13 +82,13 @@ { "basefreq", "set base frequency", OFFSET(basefreq), AV_OPT_TYPE_DOUBLE, { .dbl = BASEFREQ }, 10.0, 100000.0, FLAGS }, { "endfreq", "set end frequency", OFFSET(endfreq), AV_OPT_TYPE_DOUBLE, { .dbl = ENDFREQ }, 10.0, 100000.0, FLAGS }, { "coeffclamp", "set coeffclamp", OFFSET(coeffclamp), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.1, 10.0, FLAGS }, - { "tlength", "set tlength", OFFSET(tlength), AV_OPT_TYPE_STRING, { .str = TLENGTH }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "tlength", "set tlength", OFFSET(tlength), AV_OPT_TYPE_STRING, { .str = TLENGTH }, 0, 0, FLAGS }, { "count", "set transform count", OFFSET(count), AV_OPT_TYPE_INT, { .i64 = 6 }, 1, 30, FLAGS }, { "fcount", "set frequency count", OFFSET(fcount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 10, FLAGS }, - { "fontfile", "set axis font file", OFFSET(fontfile), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "font", "set axis font", OFFSET(font), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "fontcolor", "set font color", OFFSET(fontcolor), AV_OPT_TYPE_STRING, { .str = FONTCOLOR }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "axisfile", "set axis image", OFFSET(axisfile), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "fontfile", "set axis font file", OFFSET(fontfile), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, + { "font", "set axis font", OFFSET(font), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, + { "fontcolor", "set font color", OFFSET(fontcolor), AV_OPT_TYPE_STRING, { .str = FONTCOLOR }, 0, 0, FLAGS }, + { "axisfile", "set axis image", OFFSET(axisfile), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, { "axis", "draw axis", OFFSET(axis), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS }, { "text", "draw axis", OFFSET(axis), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS }, { "csp", "set color space", OFFSET(csp), AV_OPT_TYPE_INT, { .i64 = AVCOL_SPC_UNSPECIFIED }, 0, INT_MAX, FLAGS, "csp" }, @@ -99,7 +99,7 @@ { "smpte170m", "smpte170m", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_SPC_SMPTE170M }, 0, 0, FLAGS, "csp" }, { "smpte240m", "smpte240m", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_SPC_SMPTE240M }, 0, 0, FLAGS, "csp" }, { "bt2020ncl", "bt2020ncl", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_SPC_BT2020_NCL }, 0, 0, FLAGS, "csp" }, - { "cscheme", "set color scheme", OFFSET(cscheme), AV_OPT_TYPE_STRING, { .str = CSCHEME }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "cscheme", "set color scheme", OFFSET(cscheme), AV_OPT_TYPE_STRING, { .str = CSCHEME }, 0, 0, FLAGS }, { NULL } }; @@ -365,7 +365,7 @@ out->format = format; out->width = w; out->height = h; - if (av_frame_get_buffer(out, 32) < 0) { + if (av_frame_get_buffer(out, 0) < 0) { av_frame_free(&out); return NULL; } @@ -1133,11 +1133,11 @@ int64_t last_time, cur_time; #define UPDATE_TIME(t) \ - cur_time = av_gettime(); \ + cur_time = av_gettime_relative(); \ t += cur_time - last_time; \ last_time = cur_time - last_time = av_gettime(); + last_time = av_gettime_relative(); memcpy(s->fft_result, s->fft_data, s->fft_len * sizeof(*s->fft_data)); if (s->attack_data) { @@ -1321,30 +1321,30 @@ AVFilterChannelLayouts *layouts = NULL; AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; - enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }; - enum AVPixelFormat pix_fmts[] = { + static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }; + static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE }; - int64_t channel_layouts[] = { AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_STEREO_DOWNMIX, -1 }; + static const int64_t channel_layouts[] = { AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_STEREO_DOWNMIX, -1 }; int ret; /* set input audio formats */ formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0) return ret; - layouts = avfilter_make_format64_list(channel_layouts); - if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0) + layouts = ff_make_format64_list(channel_layouts); + if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; formats = ff_all_samplerates(); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0) return ret; /* set output video format */ formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; return 0; diff -Nru ffmpeg-4.2.2/libavfilter/avf_showfreqs.c ffmpeg-4.4/libavfilter/avf_showfreqs.c --- ffmpeg-4.2.2/libavfilter/avf_showfreqs.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avf_showfreqs.c 2021-04-08 21:28:39.000000000 +0000 @@ -36,6 +36,7 @@ #include "internal.h" #include "window_func.h" +enum DataMode { MAGNITUDE, PHASE, DELAY, NB_DATA }; enum DisplayMode { LINE, BAR, DOT, NB_MODES }; enum ChannelMode { COMBINED, SEPARATE, NB_CMODES }; enum FrequencyScale { FS_LINEAR, FS_LOG, FS_RLOG, NB_FSCALES }; @@ -45,6 +46,7 @@ const AVClass *class; int w, h; int mode; + int data_mode; int cmode; int fft_size; int fft_bits; @@ -115,6 +117,10 @@ { "combined", "show all channels in same window", 0, AV_OPT_TYPE_CONST, {.i64=COMBINED}, 0, 0, FLAGS, "cmode" }, { "separate", "show each channel in own window", 0, AV_OPT_TYPE_CONST, {.i64=SEPARATE}, 0, 0, FLAGS, "cmode" }, { "minamp", "set minimum amplitude", OFFSET(minamp), AV_OPT_TYPE_FLOAT, {.dbl=1e-6}, FLT_MIN, 1e-6, FLAGS }, + { "data", "set data mode", OFFSET(data_mode), AV_OPT_TYPE_INT, {.i64=MAGNITUDE}, 0, NB_DATA-1, FLAGS, "data" }, + { "magnitude", "show magnitude", 0, AV_OPT_TYPE_CONST, {.i64=MAGNITUDE}, 0, 0, FLAGS, "data" }, + { "phase", "show phase", 0, AV_OPT_TYPE_CONST, {.i64=PHASE}, 0, 0, FLAGS, "data" }, + { "delay", "show group delay",0, AV_OPT_TYPE_CONST, {.i64=DELAY}, 0, 0, FLAGS, "data" }, { NULL } }; @@ -132,20 +138,20 @@ /* set input audio formats */ formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0) return ret; layouts = ff_all_channel_layouts(); - if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; formats = ff_all_samplerates(); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0) return ret; /* set output video format */ formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; return 0; @@ -195,7 +201,7 @@ if (!s->fft_data) return AVERROR(ENOMEM); s->avg_data = av_calloc(s->nb_channels, sizeof(*s->avg_data)); - if (!s->fft_data) + if (!s->avg_data) return AVERROR(ENOMEM); for (i = 0; i < s->nb_channels; i++) { s->fft_data[i] = av_calloc(s->win_size, sizeof(**s->fft_data)); @@ -397,6 +403,7 @@ #define RE(x, ch) s->fft_data[ch][x].re #define IM(x, ch) s->fft_data[ch][x].im #define M(a, b) (sqrt((a) * (a) + (b) * (b))) +#define P(a, b) (atan2((b), (a))) colors = av_strdup(s->colors); if (!colors) { @@ -413,13 +420,37 @@ if (color) av_parse_color(fg, color, -1, ctx); - a = av_clipd(M(RE(0, ch), 0) / s->scale, 0, 1); - plot_freq(s, ch, a, 0, fg, &prev_y, out, outlink); - - for (f = 1; f < s->nb_freq; f++) { - a = av_clipd(M(RE(f, ch), IM(f, ch)) / s->scale, 0, 1); - - plot_freq(s, ch, a, f, fg, &prev_y, out, outlink); + switch (s->data_mode) { + case MAGNITUDE: + a = av_clipd(M(RE(0, ch), 0) / s->scale, 0, 1); + plot_freq(s, ch, a, 0, fg, &prev_y, out, outlink); + + for (f = 1; f < s->nb_freq; f++) { + a = av_clipd(M(RE(f, ch), IM(f, ch)) / s->scale, 0, 1); + + plot_freq(s, ch, a, f, fg, &prev_y, out, outlink); + } + break; + case PHASE: + a = av_clipd((M_PI + P(RE(0, ch), 0)) / (2. * M_PI), 0, 1); + plot_freq(s, ch, a, 0, fg, &prev_y, out, outlink); + + for (f = 1; f < s->nb_freq; f++) { + a = av_clipd((M_PI + P(RE(f, ch), IM(f, ch))) / (2. * M_PI), 0, 1); + + plot_freq(s, ch, a, f, fg, &prev_y, out, outlink); + } + break; + case DELAY: + plot_freq(s, ch, 0, 0, fg, &prev_y, out, outlink); + + for (f = 1; f < s->nb_freq; f++) { + a = av_clipd((M_PI - P(IM(f, ch) * RE(f-1, ch) - IM(f-1, ch) * RE(f, ch), + RE(f, ch) * RE(f-1, ch) + IM(f, ch) * IM(f-1, ch))) / (2. * M_PI), 0, 1); + + plot_freq(s, ch, a, f, fg, &prev_y, out, outlink); + } + break; } } @@ -475,6 +506,7 @@ av_audio_fifo_write(s->fifo, (void **)in->extended_data, in->nb_samples); if (s->pts == AV_NOPTS_VALUE) s->pts = in->pts; + av_frame_free(&in); } if (av_audio_fifo_size(s->fifo) >= s->win_size) { diff -Nru ffmpeg-4.2.2/libavfilter/avf_showspatial.c ffmpeg-4.4/libavfilter/avf_showspatial.c --- ffmpeg-4.2.2/libavfilter/avf_showspatial.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avf_showspatial.c 2021-04-08 21:28:39.000000000 +0000 @@ -114,17 +114,17 @@ int ret; formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref (formats, &inlink->out_formats )) < 0 || + if ((ret = ff_formats_ref (formats, &inlink->outcfg.formats )) < 0 || (ret = ff_add_channel_layout (&layout, AV_CH_LAYOUT_STEREO )) < 0 || - (ret = ff_channel_layouts_ref (layout , &inlink->out_channel_layouts)) < 0) + (ret = ff_channel_layouts_ref (layout , &inlink->outcfg.channel_layouts)) < 0) return ret; formats = ff_all_samplerates(); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0) return ret; formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; return 0; diff -Nru ffmpeg-4.2.2/libavfilter/avf_showspectrum.c ffmpeg-4.4/libavfilter/avf_showspectrum.c --- ffmpeg-4.2.2/libavfilter/avf_showspectrum.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avf_showspectrum.c 2021-04-08 21:28:39.000000000 +0000 @@ -355,20 +355,20 @@ /* set input audio formats */ formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0) return ret; layouts = ff_all_channel_layouts(); - if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; formats = ff_all_samplerates(); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0) return ret; /* set output video format */ formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; return 0; @@ -695,17 +695,20 @@ inlink->channel_layout); text = av_asprintf("%d Hz | %s", inlink->sample_rate, chlayout_str); + if (!text) + return AVERROR(ENOMEM); drawtext(s->outpicref, 2, outlink->h - 10, "CREATED BY LIBAVFILTER", 0); drawtext(s->outpicref, outlink->w - 2 - strlen(text) * 10, outlink->h - 10, text, 0); + av_freep(&text); if (s->stop) { - char *text = av_asprintf("Zoom: %d Hz - %d Hz", s->start, s->stop); + text = av_asprintf("Zoom: %d Hz - %d Hz", s->start, s->stop); + if (!text) + return AVERROR(ENOMEM); drawtext(s->outpicref, outlink->w - 2 - strlen(text) * 10, 3, text, 0); av_freep(&text); } - av_freep(&text); - dst = s->outpicref->data[0] + (s->start_y - 1) * s->outpicref->linesize[0] + s->start_x - 1; for (x = 0; x < s->w + 1; x++) dst[x] = 200; @@ -766,6 +769,8 @@ for (x = 0; x < s->w && s->single_pic; x+=80) { float seconds = x * spp / inlink->sample_rate; char *units = get_time(ctx, seconds, x); + if (!units) + return AVERROR(ENOMEM); drawtext(s->outpicref, s->start_x + x - 4 * strlen(units), s->h + s->start_y + 6, units, 0); drawtext(s->outpicref, s->start_x + x - 4 * strlen(units), s->start_y - 12, units, 0); @@ -822,6 +827,8 @@ for (y = 0; y < s->h && s->single_pic; y+=40) { float seconds = y * spp / inlink->sample_rate; char *units = get_time(ctx, seconds, x); + if (!units) + return AVERROR(ENOMEM); drawtext(s->outpicref, s->start_x - 8 * strlen(units) - 4, s->start_y + y - 4, units, 0); av_free(units); @@ -1358,8 +1365,12 @@ s->xpos = 0; if (!s->single_pic && (s->sliding != FULLFRAME || s->xpos == 0)) { if (s->old_pts < outpicref->pts) { + AVFrame *clone; + if (s->legend) { char *units = get_time(ctx, insamples->pts /(float)inlink->sample_rate, x); + if (!units) + return AVERROR(ENOMEM); if (s->orientation == VERTICAL) { for (y = 0; y < 10; y++) { @@ -1384,7 +1395,10 @@ av_free(units); } s->old_pts = outpicref->pts; - ret = ff_filter_frame(outlink, av_frame_clone(s->outpicref)); + clone = av_frame_clone(s->outpicref); + if (!clone) + return AVERROR(ENOMEM); + ret = ff_filter_frame(outlink, clone); if (ret < 0) return ret; return 0; @@ -1420,7 +1434,8 @@ } } - if (s->outpicref && av_audio_fifo_size(s->fifo) >= s->win_size) { + if (s->outpicref && (av_audio_fifo_size(s->fifo) >= s->win_size || + ff_outlink_get_status(inlink))) { AVFrame *fin = ff_get_audio_buffer(inlink, s->win_size); if (!fin) return AVERROR(ENOMEM); @@ -1448,7 +1463,7 @@ av_frame_free(&fin); av_audio_fifo_drain(s->fifo, s->hop_size); - if (ret <= 0) + if (ret <= 0 && !ff_outlink_get_status(inlink)) return ret; } @@ -1479,15 +1494,18 @@ } FF_FILTER_FORWARD_STATUS(inlink, outlink); - if (ff_outlink_frame_wanted(outlink) && av_audio_fifo_size(s->fifo) < s->win_size) { - ff_inlink_request_frame(inlink); + if (av_audio_fifo_size(s->fifo) >= s->win_size || + ff_outlink_get_status(inlink) == AVERROR_EOF) { + ff_filter_set_ready(ctx, 10); return 0; } - if (av_audio_fifo_size(s->fifo) >= s->win_size) { - ff_filter_set_ready(ctx, 10); + if (ff_outlink_frame_wanted(outlink) && av_audio_fifo_size(s->fifo) < s->win_size && + ff_outlink_get_status(inlink) != AVERROR_EOF) { + ff_inlink_request_frame(inlink); return 0; } + return FFERROR_NOT_READY; } diff -Nru ffmpeg-4.2.2/libavfilter/avf_showvolume.c ffmpeg-4.4/libavfilter/avf_showvolume.c --- ffmpeg-4.2.2/libavfilter/avf_showvolume.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avf_showvolume.c 2021-04-08 21:28:39.000000000 +0000 @@ -82,7 +82,7 @@ { "t", "display channel names", OFFSET(draw_text), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, { "v", "display volume value", OFFSET(draw_volume), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, { "dm", "duration for max value display", OFFSET(draw_persistent_duration), AV_OPT_TYPE_DOUBLE, {.dbl=0.}, 0, 9000, FLAGS}, - { "dmc","set color of the max value line", OFFSET(persistant_max_rgba), AV_OPT_TYPE_COLOR, {.str = "orange"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "dmc","set color of the max value line", OFFSET(persistant_max_rgba), AV_OPT_TYPE_COLOR, {.str = "orange"}, 0, 0, FLAGS }, { "o", "set orientation", OFFSET(orientation), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "orientation" }, { "h", "horizontal", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "orientation" }, { "v", "vertical", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "orientation" }, @@ -125,19 +125,19 @@ int ret; formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0) return ret; layouts = ff_all_channel_counts(); - if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; formats = ff_all_samplerates(); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0) return ret; formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; return 0; diff -Nru ffmpeg-4.2.2/libavfilter/avf_showwaves.c ffmpeg-4.4/libavfilter/avf_showwaves.c --- ffmpeg-4.2.2/libavfilter/avf_showwaves.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/avf_showwaves.c 2021-04-08 21:28:39.000000000 +0000 @@ -57,6 +57,12 @@ DRAW_NB, }; +enum ShowWavesFilterMode { + FILTER_AVERAGE, + FILTER_PEAK, + FILTER_NB, +}; + struct frame_node { AVFrame *frame; struct frame_node *next; @@ -77,6 +83,7 @@ int scale; ///< ShowWavesScale int draw_mode; ///< ShowWavesDrawMode int split_channels; + int filter_mode; uint8_t *fg; int (*get_h)(int16_t sample, int height); @@ -154,20 +161,20 @@ /* set input audio formats */ formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0) return ret; layouts = ff_all_channel_layouts(); - if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; formats = ff_all_samplerates(); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0) return ret; /* set output video format */ formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; return 0; @@ -590,12 +597,21 @@ int64_t max_samples = col == outlink->w - 1 ? last_column_samples: column_max_samples; int ch; - for (ch = 0; ch < nb_channels; ch++) - sum[ch] += abs(p[ch + i*nb_channels]) << 1; + switch (showwaves->filter_mode) { + case FILTER_AVERAGE: + for (ch = 0; ch < nb_channels; ch++) + sum[ch] += abs(p[ch + i*nb_channels]) << 1; + break; + case FILTER_PEAK: + for (ch = 0; ch < nb_channels; ch++) + sum[ch] = FFMAX(sum[ch], abs(p[ch + i*nb_channels])); + break; + } + n++; if (n == max_samples) { for (ch = 0; ch < nb_channels; ch++) { - int16_t sample = sum[ch] / max_samples; + int16_t sample = sum[ch] / (showwaves->filter_mode == FILTER_AVERAGE ? max_samples : 1); uint8_t *buf = out->data[0] + col * pixstep; int h; @@ -792,6 +808,9 @@ { "draw", "set draw mode", OFFSET(draw_mode), AV_OPT_TYPE_INT, {.i64 = DRAW_SCALE}, 0, DRAW_NB-1, FLAGS, .unit="draw" }, { "scale", "scale pixel values for each drawn sample", 0, AV_OPT_TYPE_CONST, {.i64=DRAW_SCALE}, .flags=FLAGS, .unit="draw"}, { "full", "draw every pixel for sample directly", 0, AV_OPT_TYPE_CONST, {.i64=DRAW_FULL}, .flags=FLAGS, .unit="draw"}, + { "filter", "set filter mode", OFFSET(filter_mode), AV_OPT_TYPE_INT, {.i64 = FILTER_AVERAGE}, 0, FILTER_NB-1, FLAGS, .unit="filter" }, + { "average", "use average samples", 0, AV_OPT_TYPE_CONST, {.i64=FILTER_AVERAGE}, .flags=FLAGS, .unit="filter"}, + { "peak", "use peak samples", 0, AV_OPT_TYPE_CONST, {.i64=FILTER_PEAK}, .flags=FLAGS, .unit="filter"}, { NULL } }; diff -Nru ffmpeg-4.2.2/libavfilter/bbox.c ffmpeg-4.4/libavfilter/bbox.c --- ffmpeg-4.2.2/libavfilter/bbox.c 2016-03-29 02:25:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/bbox.c 2021-04-08 21:28:39.000000000 +0000 @@ -20,56 +20,71 @@ #include "bbox.h" -int ff_calculate_bounding_box(FFBoundingBox *bbox, - const uint8_t *data, int linesize, int w, int h, - int min_val) -{ - int x, y; - int start_x; - int start_y; - int end_x; - int end_y; - const uint8_t *line; - - /* left bound */ - for (start_x = 0; start_x < w; start_x++) - for (y = 0; y < h; y++) - if ((data[y * linesize + start_x] > min_val)) - goto outl; -outl: - if (start_x == w) /* no points found */ - return 0; - - /* right bound */ - for (end_x = w - 1; end_x >= start_x; end_x--) - for (y = 0; y < h; y++) - if ((data[y * linesize + end_x] > min_val)) - goto outr; -outr: - - /* top bound */ - line = data; - for (start_y = 0; start_y < h; start_y++) { - for (x = 0; x < w; x++) - if (line[x] > min_val) - goto outt; - line += linesize; - } -outt: +#define BBOX(type, name) \ +static int bbox_##name(FFBoundingBox *bbox, \ + const type *data, int linesize, int w, int h, \ + int min_val) \ +{ \ + int x, y; \ + int start_x; \ + int start_y; \ + int end_x; \ + int end_y; \ + const type *line; \ + \ + /* left bound */ \ + for (start_x = 0; start_x < w; start_x++) \ + for (y = 0; y < h; y++) \ + if ((data[y * linesize + start_x] > min_val)) \ + goto outl; \ +outl: \ + if (start_x == w) /* no points found */ \ + return 0; \ + \ + /* right bound */ \ + for (end_x = w - 1; end_x >= start_x; end_x--) \ + for (y = 0; y < h; y++) \ + if ((data[y * linesize + end_x] > min_val)) \ + goto outr; \ +outr: \ + \ + /* top bound */ \ + line = data; \ + for (start_y = 0; start_y < h; start_y++) { \ + for (x = 0; x < w; x++) \ + if (line[x] > min_val) \ + goto outt; \ + line += linesize; \ + } \ +outt: \ + \ + /* bottom bound */ \ + line = data + (h-1)*linesize; \ + for (end_y = h - 1; end_y >= start_y; end_y--) { \ + for (x = 0; x < w; x++) \ + if (line[x] > min_val) \ + goto outb; \ + line -= linesize; \ + } \ +outb: \ + \ + bbox->x1 = start_x; \ + bbox->y1 = start_y; \ + bbox->x2 = end_x; \ + bbox->y2 = end_y; \ + return 1; \ +} - /* bottom bound */ - line = data + (h-1)*linesize; - for (end_y = h - 1; end_y >= start_y; end_y--) { - for (x = 0; x < w; x++) - if (line[x] > min_val) - goto outb; - line -= linesize; - } -outb: +BBOX(uint8_t, 8) +BBOX(uint16_t, 16) - bbox->x1 = start_x; - bbox->y1 = start_y; - bbox->x2 = end_x; - bbox->y2 = end_y; - return 1; +int ff_calculate_bounding_box(FFBoundingBox *bbox, + const uint8_t *data, int linesize, + int w, int h, + int min_val, int depth) +{ + if (depth <= 8) + return bbox_8(bbox, data, linesize, w, h, min_val); + else + return bbox_16(bbox, (const uint16_t *)data, linesize / 2, w, h, min_val); } diff -Nru ffmpeg-4.2.2/libavfilter/bbox.h ffmpeg-4.4/libavfilter/bbox.h --- ffmpeg-4.2.2/libavfilter/bbox.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/bbox.h 2021-04-08 21:28:39.000000000 +0000 @@ -39,6 +39,6 @@ */ int ff_calculate_bounding_box(FFBoundingBox *bbox, const uint8_t *data, int linesize, - int w, int h, int min_val); + int w, int h, int min_val, int depth); #endif /* AVFILTER_BBOX_H */ diff -Nru ffmpeg-4.2.2/libavfilter/boxblur.c ffmpeg-4.4/libavfilter/boxblur.c --- ffmpeg-4.2.2/libavfilter/boxblur.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/boxblur.c 2020-07-11 10:39:30.000000000 +0000 @@ -91,7 +91,7 @@ NULL, NULL, NULL, NULL, NULL, 0, ctx); \ comp->radius = res; \ if (ret < 0) { \ - av_log(NULL, AV_LOG_ERROR, \ + av_log(ctx, AV_LOG_ERROR, \ "Error when evaluating " #comp " radius expression '%s'\n", expr); \ return ret; \ } diff -Nru ffmpeg-4.2.2/libavfilter/buffersink.c ffmpeg-4.4/libavfilter/buffersink.c --- ffmpeg-4.2.2/libavfilter/buffersink.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/buffersink.c 2021-04-08 21:28:39.000000000 +0000 @@ -61,8 +61,29 @@ } BufferSinkContext; #define NB_ITEMS(list) (list ## _size / sizeof(*list)) -#define FIFO_INIT_SIZE 8 -#define FIFO_INIT_ELEMENT_SIZE sizeof(void *) + +static void cleanup_redundant_layouts(AVFilterContext *ctx) +{ + BufferSinkContext *buf = ctx->priv; + int nb_layouts = NB_ITEMS(buf->channel_layouts); + int nb_counts = NB_ITEMS(buf->channel_counts); + uint64_t counts = 0; + int i, lc, n; + + for (i = 0; i < nb_counts; i++) + if (buf->channel_counts[i] < 64) + counts |= (uint64_t)1 << buf->channel_counts[i]; + for (i = lc = 0; i < nb_layouts; i++) { + n = av_get_channel_layout_nb_channels(buf->channel_layouts[i]); + if (n < 64 && (counts & ((uint64_t)1 << n))) + av_log(ctx, AV_LOG_WARNING, + "Removing channel layout 0x%"PRIx64", redundant with %d channels\n", + buf->channel_layouts[i], n); + else + buf->channel_layouts[lc++] = buf->channel_layouts[i]; + } + buf->channel_layouts_size = lc * sizeof(*buf->channel_layouts); +} int attribute_align_arg av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame) { @@ -127,6 +148,7 @@ return get_frame_internal(ctx, frame, 0, nb_samples); } +#if FF_API_BUFFERSINK_ALLOC AVBufferSinkParams *av_buffersink_params_alloc(void) { static const int pixel_fmts[] = { AV_PIX_FMT_NONE }; @@ -146,6 +168,7 @@ return NULL; return params; } +#endif static av_cold int common_init(AVFilterContext *ctx) { @@ -201,20 +224,6 @@ MAKE_AVFILTERLINK_ACCESSOR(AVBufferRef * , hw_frames_ctx ) -static av_cold int vsink_init(AVFilterContext *ctx, void *opaque) -{ - BufferSinkContext *buf = ctx->priv; - AVBufferSinkParams *params = opaque; - int ret; - - if (params) { - if ((ret = av_opt_set_int_list(buf, "pix_fmts", params->pixel_fmts, AV_PIX_FMT_NONE, 0)) < 0) - return ret; - } - - return common_init(ctx); -} - #define CHECK_LIST_SIZE(field) \ if (buf->field ## _size % sizeof(*buf->field)) { \ av_log(ctx, AV_LOG_ERROR, "Invalid size for " #field ": %d, " \ @@ -244,23 +253,6 @@ return 0; } -static av_cold int asink_init(AVFilterContext *ctx, void *opaque) -{ - BufferSinkContext *buf = ctx->priv; - AVABufferSinkParams *params = opaque; - int ret; - - if (params) { - if ((ret = av_opt_set_int_list(buf, "sample_fmts", params->sample_fmts, AV_SAMPLE_FMT_NONE, 0)) < 0 || - (ret = av_opt_set_int_list(buf, "sample_rates", params->sample_rates, -1, 0)) < 0 || - (ret = av_opt_set_int_list(buf, "channel_layouts", params->channel_layouts, -1, 0)) < 0 || - (ret = av_opt_set_int_list(buf, "channel_counts", params->channel_counts, -1, 0)) < 0 || - (ret = av_opt_set_int(buf, "all_channel_counts", params->all_channel_counts, 0)) < 0) - return ret; - } - return common_init(ctx); -} - static int asink_query_formats(AVFilterContext *ctx) { BufferSinkContext *buf = ctx->priv; @@ -284,6 +276,7 @@ if (buf->channel_layouts_size || buf->channel_counts_size || buf->all_channel_counts) { + cleanup_redundant_layouts(ctx); for (i = 0; i < NB_ITEMS(buf->channel_layouts); i++) if ((ret = ff_add_channel_layout(&layouts, buf->channel_layouts[i])) < 0) return ret; @@ -336,42 +329,40 @@ static const AVFilterPad avfilter_vsink_buffer_inputs[] = { { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, }, { NULL } }; AVFilter ff_vsink_buffer = { - .name = "buffersink", - .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."), - .priv_size = sizeof(BufferSinkContext), - .priv_class = &buffersink_class, - .init_opaque = vsink_init, - + .name = "buffersink", + .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."), + .priv_size = sizeof(BufferSinkContext), + .priv_class = &buffersink_class, + .init = common_init, .query_formats = vsink_query_formats, - .activate = activate, - .inputs = avfilter_vsink_buffer_inputs, - .outputs = NULL, + .activate = activate, + .inputs = avfilter_vsink_buffer_inputs, + .outputs = NULL, }; static const AVFilterPad avfilter_asink_abuffer_inputs[] = { { - .name = "default", - .type = AVMEDIA_TYPE_AUDIO, + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, }, { NULL } }; AVFilter ff_asink_abuffer = { - .name = "abuffersink", - .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."), - .priv_class = &abuffersink_class, - .priv_size = sizeof(BufferSinkContext), - .init_opaque = asink_init, - + .name = "abuffersink", + .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."), + .priv_class = &abuffersink_class, + .priv_size = sizeof(BufferSinkContext), + .init = common_init, .query_formats = asink_query_formats, - .activate = activate, - .inputs = avfilter_asink_abuffer_inputs, - .outputs = NULL, + .activate = activate, + .inputs = avfilter_asink_abuffer_inputs, + .outputs = NULL, }; diff -Nru ffmpeg-4.2.2/libavfilter/buffersink.h ffmpeg-4.4/libavfilter/buffersink.h --- ffmpeg-4.2.2/libavfilter/buffersink.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/buffersink.h 2021-04-08 21:28:39.000000000 +0000 @@ -31,6 +31,42 @@ * @defgroup lavfi_buffersink Buffer sink API * @ingroup lavfi * @{ + * + * The buffersink and abuffersink filters are there to connect filter graphs + * to applications. They have a single input, connected to the graph, and no + * output. Frames must be extracted using av_buffersink_get_frame() or + * av_buffersink_get_samples(). + * + * The format negotiated by the graph during configuration can be obtained + * using the accessor functions: + * - av_buffersink_get_time_base(), + * - av_buffersink_get_format(), + * - av_buffersink_get_frame_rate(), + * - av_buffersink_get_w(), + * - av_buffersink_get_h(), + * - av_buffersink_get_sample_aspect_ratio(), + * - av_buffersink_get_channels(), + * - av_buffersink_get_channel_layout(), + * - av_buffersink_get_sample_rate(). + * + * The format can be constrained by setting options, using av_opt_set() and + * related functions with the AV_OPT_SEARCH_CHILDREN flag. + * - pix_fmts (int list), + * - sample_fmts (int list), + * - sample_rates (int list), + * - channel_layouts (int64_t), + * - channel_counts (int list), + * - all_channel_counts (bool). + * Most of these options are of type binary, and should be set using + * av_opt_set_int_list() or av_opt_set_bin(). If they are not set, all + * corresponding formats are accepted. + * + * As a special case, if neither channel_layouts nor channel_counts is set, + * all valid channel layouts are accepted, but channel counts without a + * layout are not, unless all_channel_counts is set. + * Also, channel_layouts must not contain a channel layout already accepted + * by a value in channel_counts; for example, if channel_counts contains 2, + * then channel_layouts must not contain stereo. */ /** @@ -59,8 +95,9 @@ */ #define AV_BUFFERSINK_FLAG_NO_REQUEST 2 +#if FF_API_BUFFERSINK_ALLOC /** - * Struct to use for initializing a buffersink context. + * Deprecated and unused struct to use for initializing a buffersink context. */ typedef struct AVBufferSinkParams { const enum AVPixelFormat *pixel_fmts; ///< list of allowed pixel formats, terminated by AV_PIX_FMT_NONE @@ -71,10 +108,11 @@ * * Must be freed with av_free(). */ +attribute_deprecated AVBufferSinkParams *av_buffersink_params_alloc(void); /** - * Struct to use for initializing an abuffersink context. + * Deprecated and unused struct to use for initializing an abuffersink context. */ typedef struct AVABufferSinkParams { const enum AVSampleFormat *sample_fmts; ///< list of allowed sample formats, terminated by AV_SAMPLE_FMT_NONE @@ -89,7 +127,9 @@ * * Must be freed with av_free(). */ +attribute_deprecated AVABufferSinkParams *av_abuffersink_params_alloc(void); +#endif /** * Set the frame size for an audio buffer sink. diff -Nru ffmpeg-4.2.2/libavfilter/buffersrc.c ffmpeg-4.4/libavfilter/buffersrc.c --- ffmpeg-4.2.2/libavfilter/buffersrc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/buffersrc.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,9 +25,9 @@ #include +#include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" -#include "libavutil/fifo.h" #include "libavutil/frame.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" @@ -43,17 +43,17 @@ typedef struct BufferSourceContext { const AVClass *class; - AVFifoBuffer *fifo; AVRational time_base; ///< time_base to set in the output link AVRational frame_rate; ///< frame_rate to set in the output link unsigned nb_failed_requests; - unsigned warning_limit; /* video only */ int w, h; enum AVPixelFormat pix_fmt; AVRational pixel_aspect; +#if FF_API_SWS_PARAM_OPTION char *sws_param; +#endif AVBufferRef *hw_frames_ctx; @@ -64,7 +64,6 @@ uint64_t channel_layout; char *channel_layout_str; - int got_format_from_params; int eof; } BufferSourceContext; @@ -106,7 +105,6 @@ switch (ctx->filter->outputs[0].type) { case AVMEDIA_TYPE_VIDEO: if (param->format != AV_PIX_FMT_NONE) { - s->got_format_from_params = 1; s->pix_fmt = param->format; } if (param->width > 0) @@ -126,7 +124,6 @@ break; case AVMEDIA_TYPE_AUDIO: if (param->format != AV_SAMPLE_FMT_NONE) { - s->got_format_from_params = 1; s->sample_fmt = param->format; } if (param->sample_rate > 0) @@ -152,33 +149,6 @@ return av_buffersrc_add_frame_flags(ctx, frame, 0); } -static int av_buffersrc_add_frame_internal(AVFilterContext *ctx, - AVFrame *frame, int flags); - -int attribute_align_arg av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags) -{ - AVFrame *copy = NULL; - int ret = 0; - - if (frame && frame->channel_layout && - av_get_channel_layout_nb_channels(frame->channel_layout) != frame->channels) { - av_log(ctx, AV_LOG_ERROR, "Layout indicates a different number of channels than actually present\n"); - return AVERROR(EINVAL); - } - - if (!(flags & AV_BUFFERSRC_FLAG_KEEP_REF) || !frame) - return av_buffersrc_add_frame_internal(ctx, frame, flags); - - if (!(copy = av_frame_alloc())) - return AVERROR(ENOMEM); - ret = av_frame_ref(copy, frame); - if (ret >= 0) - ret = av_buffersrc_add_frame_internal(ctx, copy, flags); - - av_frame_free(©); - return ret; -} - static int push_frame(AVFilterGraph *graph) { int ret; @@ -193,13 +163,18 @@ return 0; } -static int av_buffersrc_add_frame_internal(AVFilterContext *ctx, - AVFrame *frame, int flags) +int attribute_align_arg av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags) { BufferSourceContext *s = ctx->priv; AVFrame *copy; int refcounted, ret; + if (frame && frame->channel_layout && + av_get_channel_layout_nb_channels(frame->channel_layout) != frame->channels) { + av_log(ctx, AV_LOG_ERROR, "Layout indicates a different number of channels than actually present\n"); + return AVERROR(EINVAL); + } + s->nb_failed_requests = 0; if (!frame) @@ -229,15 +204,10 @@ } - if (!av_fifo_space(s->fifo) && - (ret = av_fifo_realloc2(s->fifo, av_fifo_size(s->fifo) + - sizeof(copy))) < 0) - return ret; - if (!(copy = av_frame_alloc())) return AVERROR(ENOMEM); - if (refcounted) { + if (refcounted && !(flags & AV_BUFFERSRC_FLAG_KEEP_REF)) { av_frame_move_ref(copy, frame); } else { ret = av_frame_ref(copy, frame); @@ -247,14 +217,8 @@ } } - if ((ret = av_fifo_generic_write(s->fifo, ©, sizeof(copy), NULL)) < 0) { - if (refcounted) - av_frame_move_ref(frame, copy); - av_frame_free(©); - return ret; - } - - if ((ret = ctx->output_pads[0].request_frame(ctx->outputs[0])) < 0) + ret = ff_filter_frame(ctx->outputs[0], copy); + if (ret < 0) return ret; if ((flags & AV_BUFFERSRC_FLAG_PUSH)) { @@ -279,20 +243,22 @@ { BufferSourceContext *c = ctx->priv; - if (!(c->pix_fmt != AV_PIX_FMT_NONE || c->got_format_from_params) || !c->w || !c->h || + if (c->pix_fmt == AV_PIX_FMT_NONE || !c->w || !c->h || av_q2d(c->time_base) <= 0) { av_log(ctx, AV_LOG_ERROR, "Invalid parameters provided.\n"); return AVERROR(EINVAL); } - if (!(c->fifo = av_fifo_alloc(sizeof(AVFrame*)))) - return AVERROR(ENOMEM); - - av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d fr:%d/%d sar:%d/%d sws_param:%s\n", + av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d fr:%d/%d sar:%d/%d\n", c->w, c->h, av_get_pix_fmt_name(c->pix_fmt), c->time_base.num, c->time_base.den, c->frame_rate.num, c->frame_rate.den, - c->pixel_aspect.num, c->pixel_aspect.den, (char *)av_x_if_null(c->sws_param, "")); - c->warning_limit = 100; + c->pixel_aspect.num, c->pixel_aspect.den); + +#if FF_API_SWS_PARAM_OPTION + if (c->sws_param) + av_log(ctx, AV_LOG_WARNING, "sws_param option is deprecated and ignored\n"); +#endif + return 0; } @@ -314,7 +280,9 @@ { "pixel_aspect", "sample aspect ratio", OFFSET(pixel_aspect), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V }, { "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V }, { "frame_rate", NULL, OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V }, +#if FF_API_SWS_PARAM_OPTION { "sws_param", NULL, OFFSET(sws_param), AV_OPT_TYPE_STRING, .flags = V }, +#endif { NULL }, }; @@ -336,7 +304,7 @@ BufferSourceContext *s = ctx->priv; int ret = 0; - if (!(s->sample_fmt != AV_SAMPLE_FMT_NONE || s->got_format_from_params)) { + if (s->sample_fmt == AV_SAMPLE_FMT_NONE) { av_log(ctx, AV_LOG_ERROR, "Sample format was not set or was invalid\n"); return AVERROR(EINVAL); } @@ -369,9 +337,6 @@ return AVERROR(EINVAL); } - if (!(s->fifo = av_fifo_alloc(sizeof(AVFrame*)))) - return AVERROR(ENOMEM); - if (!s->time_base.num) s->time_base = (AVRational){1, s->sample_rate}; @@ -379,7 +344,6 @@ "tb:%d/%d samplefmt:%s samplerate:%d chlayout:%s\n", s->time_base.num, s->time_base.den, av_get_sample_fmt_name(s->sample_fmt), s->sample_rate, s->channel_layout_str); - s->warning_limit = 100; return ret; } @@ -387,13 +351,7 @@ static av_cold void uninit(AVFilterContext *ctx) { BufferSourceContext *s = ctx->priv; - while (s->fifo && av_fifo_size(s->fifo)) { - AVFrame *frame; - av_fifo_generic_read(s->fifo, &frame, sizeof(frame), NULL); - av_frame_free(&frame); - } av_buffer_unref(&s->hw_frames_ctx); - av_fifo_freep(&s->fifo); } static int query_formats(AVFilterContext *ctx) @@ -463,29 +421,11 @@ static int request_frame(AVFilterLink *link) { BufferSourceContext *c = link->src->priv; - AVFrame *frame; - int ret; - - if (!av_fifo_size(c->fifo)) { - if (c->eof) - return AVERROR_EOF; - c->nb_failed_requests++; - return AVERROR(EAGAIN); - } - av_fifo_generic_read(c->fifo, &frame, sizeof(frame), NULL); - - ret = ff_filter_frame(link, frame); - return ret; -} - -static int poll_frame(AVFilterLink *link) -{ - BufferSourceContext *c = link->src->priv; - int size = av_fifo_size(c->fifo); - if (!size && c->eof) + if (c->eof) return AVERROR_EOF; - return size/sizeof(AVFrame*); + c->nb_failed_requests++; + return AVERROR(EAGAIN); } static const AVFilterPad avfilter_vsrc_buffer_outputs[] = { @@ -493,7 +433,6 @@ .name = "default", .type = AVMEDIA_TYPE_VIDEO, .request_frame = request_frame, - .poll_frame = poll_frame, .config_props = config_props, }, { NULL } @@ -518,7 +457,6 @@ .name = "default", .type = AVMEDIA_TYPE_AUDIO, .request_frame = request_frame, - .poll_frame = poll_frame, .config_props = config_props, }, { NULL } diff -Nru ffmpeg-4.2.2/libavfilter/convolution.h ffmpeg-4.4/libavfilter/convolution.h --- ffmpeg-4.2.2/libavfilter/convolution.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/convolution.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2012-2013 Oka Motofumi (chikuzen.mo at gmail dot com) + * Copyright (c) 2015 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef AVFILTER_CONVOLUTION_H +#define AVFILTER_CONVOLUTION_H +#include "avfilter.h" + +enum MatrixMode { + MATRIX_SQUARE, + MATRIX_ROW, + MATRIX_COLUMN, + MATRIX_NBMODES, +}; + +typedef struct ConvolutionContext { + const AVClass *class; + + char *matrix_str[4]; + float rdiv[4]; + float bias[4]; + int mode[4]; + float scale; + float delta; + int planes; + + int size[4]; + int depth; + int max; + int bpc; + int nb_planes; + int nb_threads; + int planewidth[4]; + int planeheight[4]; + int matrix[4][49]; + int matrix_length[4]; + int copy[4]; + + void (*setup[4])(int radius, const uint8_t *c[], const uint8_t *src, int stride, + int x, int width, int y, int height, int bpc); + void (*filter[4])(uint8_t *dst, int width, + float rdiv, float bias, const int *const matrix, + const uint8_t *c[], int peak, int radius, + int dstride, int stride, int size); +} ConvolutionContext; + +void ff_convolution_init_x86(ConvolutionContext *s); +#endif diff -Nru ffmpeg-4.2.2/libavfilter/cuda/vector_helpers.cuh ffmpeg-4.4/libavfilter/cuda/vector_helpers.cuh --- ffmpeg-4.2.2/libavfilter/cuda/vector_helpers.cuh 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/cuda/vector_helpers.cuh 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * This file is part of FFmpeg. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef AVFILTER_CUDA_VECTORHELPERS_H +#define AVFILTER_CUDA_VECTORHELPERS_H + +typedef unsigned char uchar; +typedef unsigned short ushort; + +template struct vector_helper { }; +template<> struct vector_helper { typedef float ftype; typedef int itype; }; +template<> struct vector_helper { typedef float2 ftype; typedef int2 itype; }; +template<> struct vector_helper { typedef float4 ftype; typedef int4 itype; }; +template<> struct vector_helper { typedef float ftype; typedef int itype; }; +template<> struct vector_helper { typedef float2 ftype; typedef int2 itype; }; +template<> struct vector_helper { typedef float4 ftype; typedef int4 itype; }; +template<> struct vector_helper { typedef float ftype; typedef int itype; }; +template<> struct vector_helper { typedef float2 ftype; typedef int2 itype; }; +template<> struct vector_helper { typedef float4 ftype; typedef int4 itype; }; + +#define floatT typename vector_helper::ftype +#define intT typename vector_helper::itype + +template inline __device__ V to_floatN(const T &a) { return (V)a; } +template inline __device__ T from_floatN(const V &a) { return (T)a; } + +#define OPERATORS2(T) \ + template inline __device__ T operator+(const T &a, const V &b) { return make_ ## T (a.x + b.x, a.y + b.y); } \ + template inline __device__ T operator-(const T &a, const V &b) { return make_ ## T (a.x - b.x, a.y - b.y); } \ + template inline __device__ T operator*(const T &a, V b) { return make_ ## T (a.x * b, a.y * b); } \ + template inline __device__ T operator/(const T &a, V b) { return make_ ## T (a.x / b, a.y / b); } \ + template inline __device__ T operator>>(const T &a, V b) { return make_ ## T (a.x >> b, a.y >> b); } \ + template inline __device__ T operator<<(const T &a, V b) { return make_ ## T (a.x << b, a.y << b); } \ + template inline __device__ T &operator+=(T &a, const V &b) { a.x += b.x; a.y += b.y; return a; } \ + template inline __device__ void vec_set(T &a, const V &b) { a.x = b.x; a.y = b.y; } \ + template inline __device__ void vec_set_scalar(T &a, V b) { a.x = b; a.y = b; } \ + template<> inline __device__ float2 to_floatN(const T &a) { return make_float2(a.x, a.y); } \ + template<> inline __device__ T from_floatN(const float2 &a) { return make_ ## T(a.x, a.y); } +#define OPERATORS4(T) \ + template inline __device__ T operator+(const T &a, const V &b) { return make_ ## T (a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); } \ + template inline __device__ T operator-(const T &a, const V &b) { return make_ ## T (a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); } \ + template inline __device__ T operator*(const T &a, V b) { return make_ ## T (a.x * b, a.y * b, a.z * b, a.w * b); } \ + template inline __device__ T operator/(const T &a, V b) { return make_ ## T (a.x / b, a.y / b, a.z / b, a.w / b); } \ + template inline __device__ T operator>>(const T &a, V b) { return make_ ## T (a.x >> b, a.y >> b, a.z >> b, a.w >> b); } \ + template inline __device__ T operator<<(const T &a, V b) { return make_ ## T (a.x << b, a.y << b, a.z << b, a.w << b); } \ + template inline __device__ T &operator+=(T &a, const V &b) { a.x += b.x; a.y += b.y; a.z += b.z; a.w += b.w; return a; } \ + template inline __device__ void vec_set(T &a, const V &b) { a.x = b.x; a.y = b.y; a.z = b.z; a.w = b.w; } \ + template inline __device__ void vec_set_scalar(T &a, V b) { a.x = b; a.y = b; a.z = b; a.w = b; } \ + template<> inline __device__ float4 to_floatN(const T &a) { return make_float4(a.x, a.y, a.z, a.w); } \ + template<> inline __device__ T from_floatN(const float4 &a) { return make_ ## T(a.x, a.y, a.z, a.w); } + +OPERATORS2(int2) +OPERATORS2(uchar2) +OPERATORS2(ushort2) +OPERATORS2(float2) +OPERATORS4(int4) +OPERATORS4(uchar4) +OPERATORS4(ushort4) +OPERATORS4(float4) + +template inline __device__ void vec_set(int &a, V b) { a = b; } +template inline __device__ void vec_set(float &a, V b) { a = b; } +template inline __device__ void vec_set(uchar &a, V b) { a = b; } +template inline __device__ void vec_set(ushort &a, V b) { a = b; } +template inline __device__ void vec_set_scalar(int &a, V b) { a = b; } +template inline __device__ void vec_set_scalar(float &a, V b) { a = b; } +template inline __device__ void vec_set_scalar(uchar &a, V b) { a = b; } +template inline __device__ void vec_set_scalar(ushort &a, V b) { a = b; } + +template +inline __device__ T lerp_scalar(T v0, T v1, float t) { + return t*v1 + (1.0f - t)*v0; +} + +template<> +inline __device__ float2 lerp_scalar(float2 v0, float2 v1, float t) { + return make_float2( + lerp_scalar(v0.x, v1.x, t), + lerp_scalar(v0.y, v1.y, t) + ); +} + +template<> +inline __device__ float4 lerp_scalar(float4 v0, float4 v1, float t) { + return make_float4( + lerp_scalar(v0.x, v1.x, t), + lerp_scalar(v0.y, v1.y, t), + lerp_scalar(v0.z, v1.z, t), + lerp_scalar(v0.w, v1.w, t) + ); +} + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native.c ffmpeg-4.4/libavfilter/dnn/dnn_backend_native.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2018 Sergey Lavrushkin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN native backend implementation. + */ + +#include "dnn_backend_native.h" +#include "libavutil/avassert.h" +#include "dnn_backend_native_layer_conv2d.h" +#include "dnn_backend_native_layers.h" +#include "dnn_io_proc.h" + +#define OFFSET(x) offsetof(NativeContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM +static const AVOption dnn_native_options[] = { + { "conv2d_threads", "threads num for conv2d layer", OFFSET(options.conv2d_threads), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS }, + { NULL }, +}; + +static const AVClass dnn_native_class = { + .class_name = "dnn_native", + .item_name = av_default_item_name, + .option = dnn_native_options, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_FILTER, +}; + +static DNNReturnType execute_model_native(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame, + int do_ioproc); + +static DNNReturnType get_input_native(void *model, DNNData *input, const char *input_name) +{ + NativeModel *native_model = model; + NativeContext *ctx = &native_model->ctx; + + for (int i = 0; i < native_model->operands_num; ++i) { + DnnOperand *oprd = &native_model->operands[i]; + if (strcmp(oprd->name, input_name) == 0) { + if (oprd->type != DOT_INPUT) { + av_log(ctx, AV_LOG_ERROR, "Found \"%s\" in model, but it is not input node\n", input_name); + return DNN_ERROR; + } + input->dt = oprd->data_type; + av_assert0(oprd->dims[0] == 1); + input->height = oprd->dims[1]; + input->width = oprd->dims[2]; + input->channels = oprd->dims[3]; + return DNN_SUCCESS; + } + } + + // do not find the input operand + av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model\n", input_name); + return DNN_ERROR; +} + +static DNNReturnType get_output_native(void *model, const char *input_name, int input_width, int input_height, + const char *output_name, int *output_width, int *output_height) +{ + DNNReturnType ret; + NativeModel *native_model = model; + NativeContext *ctx = &native_model->ctx; + AVFrame *in_frame = av_frame_alloc(); + AVFrame *out_frame = NULL; + + if (!in_frame) { + av_log(ctx, AV_LOG_ERROR, "Could not allocate memory for input frame\n"); + return DNN_ERROR; + } + + out_frame = av_frame_alloc(); + + if (!out_frame) { + av_log(ctx, AV_LOG_ERROR, "Could not allocate memory for output frame\n"); + av_frame_free(&in_frame); + return DNN_ERROR; + } + + in_frame->width = input_width; + in_frame->height = input_height; + + ret = execute_model_native(native_model->model, input_name, in_frame, &output_name, 1, out_frame, 0); + *output_width = out_frame->width; + *output_height = out_frame->height; + + av_frame_free(&out_frame); + av_frame_free(&in_frame); + return ret; +} + +// Loads model and its parameters that are stored in a binary file with following structure: +// layers_num,layer_type,layer_parameterss,layer_type,layer_parameters... +// For CONV layer: activation_function, input_num, output_num, kernel_size, kernel, biases +// For DEPTH_TO_SPACE layer: block_size +DNNModel *ff_dnn_load_model_native(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx) +{ +#define DNN_NATIVE_MAGIC "FFMPEGDNNNATIVE" + DNNModel *model = NULL; + // sizeof - 1 to skip the terminating '\0' which is not written in the file + char buf[sizeof(DNN_NATIVE_MAGIC) - 1]; + int version, header_size, major_version_expected = 1; + NativeModel *native_model = NULL; + AVIOContext *model_file_context; + int file_size, dnn_size, parsed_size; + int32_t layer; + DNNLayerType layer_type; + + if (avio_open(&model_file_context, model_filename, AVIO_FLAG_READ) < 0){ + return NULL; + } + file_size = avio_size(model_file_context); + + model = av_mallocz(sizeof(DNNModel)); + if (!model){ + goto fail; + } + + /** + * check file header with string and version + */ + if (avio_read(model_file_context, buf, sizeof(buf)) != sizeof(buf) || + memcmp(buf, DNN_NATIVE_MAGIC, sizeof(buf))) + goto fail; + dnn_size = sizeof(buf); + + version = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + if (version != major_version_expected) { + goto fail; + } + + // currently no need to check minor version + version = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + header_size = dnn_size; + + native_model = av_mallocz(sizeof(NativeModel)); + if (!native_model){ + goto fail; + } + model->model = native_model; + + native_model->ctx.class = &dnn_native_class; + model->options = options; + if (av_opt_set_from_string(&native_model->ctx, model->options, NULL, "=", "&") < 0) + goto fail; + native_model->model = model; + +#if !HAVE_PTHREAD_CANCEL + if (native_model->ctx.options.conv2d_threads > 1){ + av_log(&native_model->ctx, AV_LOG_WARNING, "'conv2d_threads' option was set but it is not supported " + "on this build (pthread support is required)\n"); + } +#endif + + avio_seek(model_file_context, file_size - 8, SEEK_SET); + native_model->layers_num = (int32_t)avio_rl32(model_file_context); + native_model->operands_num = (int32_t)avio_rl32(model_file_context); + dnn_size += 8; + avio_seek(model_file_context, header_size, SEEK_SET); + + native_model->layers = av_mallocz(native_model->layers_num * sizeof(Layer)); + if (!native_model->layers){ + goto fail; + } + + native_model->operands = av_mallocz(native_model->operands_num * sizeof(DnnOperand)); + if (!native_model->operands){ + goto fail; + } + + for (layer = 0; layer < native_model->layers_num; ++layer){ + layer_type = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + + if (layer_type >= DLT_COUNT) { + goto fail; + } + + native_model->layers[layer].type = layer_type; + parsed_size = ff_layer_funcs[layer_type].pf_load(&native_model->layers[layer], model_file_context, file_size, native_model->operands_num); + if (!parsed_size) { + goto fail; + } + dnn_size += parsed_size; + } + + for (int32_t i = 0; i < native_model->operands_num; ++i){ + DnnOperand *oprd; + int32_t name_len; + int32_t operand_index = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + + if (operand_index >= native_model->operands_num) { + goto fail; + } + + oprd = &native_model->operands[operand_index]; + name_len = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + + avio_get_str(model_file_context, name_len, oprd->name, sizeof(oprd->name)); + dnn_size += name_len; + + oprd->type = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + + oprd->data_type = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + + for (int32_t dim = 0; dim < 4; ++dim) { + oprd->dims[dim] = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + } + if (oprd->type == DOT_INPUT && oprd->dims[0] != 1) + goto fail; + + oprd->isNHWC = 1; + } + + avio_closep(&model_file_context); + + if (dnn_size != file_size){ + ff_dnn_free_model_native(&model); + return NULL; + } + + model->get_input = &get_input_native; + model->get_output = &get_output_native; + model->filter_ctx = filter_ctx; + model->func_type = func_type; + + return model; + +fail: + ff_dnn_free_model_native(&model); + avio_closep(&model_file_context); + return NULL; +} + +static DNNReturnType execute_model_native(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame, + int do_ioproc) +{ + NativeModel *native_model = model->model; + NativeContext *ctx = &native_model->ctx; + int32_t layer; + DNNData input, output; + DnnOperand *oprd = NULL; + + if (native_model->layers_num <= 0 || native_model->operands_num <= 0) { + av_log(ctx, AV_LOG_ERROR, "No operands or layers in model\n"); + return DNN_ERROR; + } + + for (int i = 0; i < native_model->operands_num; ++i) { + oprd = &native_model->operands[i]; + if (strcmp(oprd->name, input_name) == 0) { + if (oprd->type != DOT_INPUT) { + av_log(ctx, AV_LOG_ERROR, "Found \"%s\" in model, but it is not input node\n", input_name); + return DNN_ERROR; + } + break; + } + oprd = NULL; + } + if (!oprd) { + av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model\n", input_name); + return DNN_ERROR; + } + + oprd->dims[1] = in_frame->height; + oprd->dims[2] = in_frame->width; + + av_freep(&oprd->data); + oprd->length = ff_calculate_operand_data_length(oprd); + if (oprd->length <= 0) { + av_log(ctx, AV_LOG_ERROR, "The input data length overflow\n"); + return DNN_ERROR; + } + oprd->data = av_malloc(oprd->length); + if (!oprd->data) { + av_log(ctx, AV_LOG_ERROR, "Failed to malloc memory for input data\n"); + return DNN_ERROR; + } + + input.height = oprd->dims[1]; + input.width = oprd->dims[2]; + input.channels = oprd->dims[3]; + input.data = oprd->data; + input.dt = oprd->data_type; + if (do_ioproc) { + if (native_model->model->pre_proc != NULL) { + native_model->model->pre_proc(in_frame, &input, native_model->model->filter_ctx); + } else { + ff_proc_from_frame_to_dnn(in_frame, &input, native_model->model->func_type, ctx); + } + } + + if (nb_output != 1) { + // currently, the filter does not need multiple outputs, + // so we just pending the support until we really need it. + avpriv_report_missing_feature(ctx, "multiple outputs"); + return DNN_ERROR; + } + + for (layer = 0; layer < native_model->layers_num; ++layer){ + DNNLayerType layer_type = native_model->layers[layer].type; + if (ff_layer_funcs[layer_type].pf_exec(native_model->operands, + native_model->layers[layer].input_operand_indexes, + native_model->layers[layer].output_operand_index, + native_model->layers[layer].params, + &native_model->ctx) == DNN_ERROR) { + av_log(ctx, AV_LOG_ERROR, "Failed to execute model\n"); + return DNN_ERROR; + } + } + + for (uint32_t i = 0; i < nb_output; ++i) { + DnnOperand *oprd = NULL; + const char *output_name = output_names[i]; + for (int j = 0; j < native_model->operands_num; ++j) { + if (strcmp(native_model->operands[j].name, output_name) == 0) { + oprd = &native_model->operands[j]; + break; + } + } + + if (oprd == NULL) { + av_log(ctx, AV_LOG_ERROR, "Could not find output in model\n"); + return DNN_ERROR; + } + + output.data = oprd->data; + output.height = oprd->dims[1]; + output.width = oprd->dims[2]; + output.channels = oprd->dims[3]; + output.dt = oprd->data_type; + + if (do_ioproc) { + if (native_model->model->post_proc != NULL) { + native_model->model->post_proc(out_frame, &output, native_model->model->filter_ctx); + } else { + ff_proc_from_dnn_to_frame(out_frame, &output, ctx); + } + } else { + out_frame->width = output.width; + out_frame->height = output.height; + } + } + + return DNN_SUCCESS; +} + +DNNReturnType ff_dnn_execute_model_native(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame) +{ + NativeModel *native_model = model->model; + NativeContext *ctx = &native_model->ctx; + + if (!in_frame) { + av_log(ctx, AV_LOG_ERROR, "in frame is NULL when execute model.\n"); + return DNN_ERROR; + } + + if (!out_frame) { + av_log(ctx, AV_LOG_ERROR, "out frame is NULL when execute model.\n"); + return DNN_ERROR; + } + + return execute_model_native(model, input_name, in_frame, output_names, nb_output, out_frame, 1); +} + +int32_t ff_calculate_operand_dims_count(const DnnOperand *oprd) +{ + int32_t result = 1; + for (int i = 0; i < 4; ++i) + result *= oprd->dims[i]; + + return result; +} + +int32_t ff_calculate_operand_data_length(const DnnOperand* oprd) +{ + // currently, we just support DNN_FLOAT + uint64_t len = sizeof(float); + for (int i = 0; i < 4; i++) { + len *= oprd->dims[i]; + if (len > INT32_MAX) + return 0; + } + return len; +} + +void ff_dnn_free_model_native(DNNModel **model) +{ + NativeModel *native_model; + ConvolutionalParams *conv_params; + int32_t layer; + + if (*model) + { + if ((*model)->model) { + native_model = (*model)->model; + if (native_model->layers) { + for (layer = 0; layer < native_model->layers_num; ++layer){ + if (native_model->layers[layer].type == DLT_CONV2D){ + conv_params = (ConvolutionalParams *)native_model->layers[layer].params; + av_freep(&conv_params->kernel); + av_freep(&conv_params->biases); + } + av_freep(&native_model->layers[layer].params); + } + av_freep(&native_model->layers); + } + + if (native_model->operands) { + for (uint32_t operand = 0; operand < native_model->operands_num; ++operand) + av_freep(&native_model->operands[operand].data); + av_freep(&native_model->operands); + } + + av_freep(&native_model); + } + av_freep(model); + } +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native.h ffmpeg-4.4/libavfilter/dnn/dnn_backend_native.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2018 Sergey Lavrushkin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN inference functions interface for native backend. + */ + + +#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_H +#define AVFILTER_DNN_DNN_BACKEND_NATIVE_H + +#include "../dnn_interface.h" +#include "libavformat/avio.h" +#include "libavutil/opt.h" + +/** + * the enum value of DNNLayerType should not be changed, + * the same values are used in convert_from_tensorflow.py + * and, it is used to index the layer execution/load function pointer. + */ +typedef enum { + DLT_INPUT = 0, + DLT_CONV2D = 1, + DLT_DEPTH_TO_SPACE = 2, + DLT_MIRROR_PAD = 3, + DLT_MAXIMUM = 4, + DLT_MATH_BINARY = 5, + DLT_MATH_UNARY = 6, + DLT_AVG_POOL = 7, + DLT_DENSE = 8, + DLT_COUNT +} DNNLayerType; + +typedef enum {DOT_INPUT = 1, DOT_OUTPUT = 2, DOT_INTERMEDIATE = DOT_INPUT | DOT_OUTPUT} DNNOperandType; +typedef enum {VALID, SAME, SAME_CLAMP_TO_EDGE} DNNPaddingParam; +typedef enum {RELU, TANH, SIGMOID, NONE, LEAKY_RELU} DNNActivationFunc; + +typedef struct Layer{ + DNNLayerType type; + /** + * a layer can have multiple inputs and one output. + * 4 is just a big enough number for input operands (increase it if necessary), + * do not use 'int32_t *input_operand_indexes', so we don't worry about mem leaks. + */ + int32_t input_operand_indexes[4]; + int32_t output_operand_index; + void *params; +} Layer; + +typedef struct DnnOperand{ + /** + * there are two memory layouts, NHWC or NCHW, so we use dims, + * dims[0] is Number. + */ + int32_t dims[4]; + + /** + * input/output/intermediate operand of the network + */ + DNNOperandType type; + + /** + * support different kinds of data type such as float, half float, int8 etc, + * first support float now. + */ + DNNDataType data_type; + + /** + * NHWC if 1, otherwise NCHW. + * let's first support NHWC only, this flag is for extensive usage. + */ + int8_t isNHWC; + + /** + * to avoid possible memory leak, do not use char *name + */ + char name[128]; + + /** + * data pointer with data length in bytes. + * usedNumbersLeft is only valid for intermediate operand, + * it means how many layers still depend on this operand, + * todo: the memory can be reused when usedNumbersLeft is zero. + */ + void *data; + int32_t length; + int32_t usedNumbersLeft; +}DnnOperand; + +typedef struct InputParams{ + int height, width, channels; +} InputParams; + +typedef struct NativeOptions{ + uint32_t conv2d_threads; +} NativeOptions; + +typedef struct NativeContext { + const AVClass *class; + NativeOptions options; +} NativeContext; + +// Represents simple feed-forward convolutional network. +typedef struct NativeModel{ + NativeContext ctx; + DNNModel *model; + Layer *layers; + int32_t layers_num; + DnnOperand *operands; + int32_t operands_num; +} NativeModel; + +DNNModel *ff_dnn_load_model_native(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx); + +DNNReturnType ff_dnn_execute_model_native(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame); + +void ff_dnn_free_model_native(DNNModel **model); + +// NOTE: User must check for error (return value <= 0) to handle +// case like integer overflow. +int32_t ff_calculate_operand_data_length(const DnnOperand *oprd); +int32_t ff_calculate_operand_dims_count(const DnnOperand *oprd); +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_avgpool.c ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_avgpool.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_avgpool.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_avgpool.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN native backend implementation. + */ + +#include "libavutil/avassert.h" +#include "dnn_backend_native_layer_avgpool.h" + +int ff_dnn_load_layer_avg_pool(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) +{ + AvgPoolParams *avgpool_params; + int dnn_size = 0; + avgpool_params = av_malloc(sizeof(*avgpool_params)); + if(!avgpool_params) + return 0; + + avgpool_params->strides = (int32_t)avio_rl32(model_file_context); + avgpool_params->padding_method = (int32_t)avio_rl32(model_file_context); + avgpool_params->kernel_size = (int32_t)avio_rl32(model_file_context); + dnn_size += 12; + + if (dnn_size > file_size || avgpool_params->kernel_size <= 0 || avgpool_params->strides <=0){ + av_freep(&avgpool_params); + return 0; + } + + layer->params = avgpool_params; + layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); + layer->output_operand_index = (int32_t)avio_rl32(model_file_context); + dnn_size += 8; + + if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { + return 0; + } + return dnn_size; +} + +int ff_dnn_execute_layer_avg_pool(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx) +{ + float *output; + int height_end, width_end, height_radius, width_radius, output_height, output_width, kernel_area; + int32_t input_operand_index = input_operand_indexes[0]; + int number = operands[input_operand_index].dims[0]; + int height = operands[input_operand_index].dims[1]; + int width = operands[input_operand_index].dims[2]; + int channel = operands[input_operand_index].dims[3]; + const float *input = operands[input_operand_index].data; + const AvgPoolParams *avgpool_params = parameters; + + int kernel_strides = avgpool_params->strides; + int src_linesize = width * channel; + DnnOperand *output_operand = &operands[output_operand_index]; + + /** + * When padding_method = SAME, the tensorflow will only padding the hald number of 0 pxiels + * except the remainders. + * Eg: assuming the input height = 1080, the strides = 11, so the remainders = 1080 % 11 = 2 + * and if ksize = 5: it will fill (5 - 2) >> 1 = 1 line before the first line of input image, + * and 5 - 2 - 1 = 2 lines after the last line of input image. + * and if ksize = 7: it will fill (7 - 2) >> 1 = 2 lines before the first line of input image, + * and 7 - 2 - 2 = 3 lines after the last line of input image. + */ + if (avgpool_params->padding_method == SAME) { + height_end = height; + width_end = width; + height_radius = avgpool_params->kernel_size - ((height - 1) % kernel_strides + 1); + width_radius = avgpool_params->kernel_size - ((width - 1) % kernel_strides + 1); + height_radius = height_radius < 0 ? 0 : height_radius >> 1; + width_radius = width_radius < 0 ? 0 : width_radius >> 1; + output_height = ceil(height / (kernel_strides * 1.0)); + output_width = ceil(width / (kernel_strides * 1.0)); + } else { + av_assert0(avgpool_params->padding_method == VALID); + height_end = height - avgpool_params->kernel_size + 1; + width_end = width - avgpool_params->kernel_size + 1; + height_radius = 0; + width_radius = 0; + output_height = ceil((height - avgpool_params->kernel_size + 1) / (kernel_strides * 1.0)); + output_width = ceil((width - avgpool_params->kernel_size + 1) / (kernel_strides * 1.0)); + } + + output_operand->dims[0] = number; + output_operand->dims[1] = output_height; + output_operand->dims[2] = output_width; + // not support pooling in channel dimension now + output_operand->dims[3] = channel; + output_operand->data_type = operands[input_operand_index].data_type; + output_operand->length = ff_calculate_operand_data_length(output_operand); + if (output_operand->length <= 0) { + av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); + return DNN_ERROR; + } + output_operand->data = av_realloc(output_operand->data, output_operand->length); + if (!output_operand->data) { + av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); + return DNN_ERROR; + } + output = output_operand->data; + + for (int y = 0; y < height_end; y += kernel_strides) { + for (int x = 0; x < width_end; x += kernel_strides) { + for (int n_channel = 0; n_channel < channel; ++n_channel) { + output[n_channel] = 0.0; + kernel_area = 0; + for (int kernel_y = 0; kernel_y < avgpool_params->kernel_size; ++kernel_y) { + for (int kernel_x = 0; kernel_x < avgpool_params->kernel_size; ++kernel_x) { + float input_pel; + int y_pos = y + (kernel_y - height_radius); + int x_pos = x + (kernel_x - width_radius); + if (x_pos < 0 || x_pos >= width || y_pos < 0 || y_pos >= height) { + input_pel = 0.0; + } else { + kernel_area++; + input_pel = input[y_pos * src_linesize + x_pos * channel + n_channel]; + } + output[n_channel] += input_pel; + } + } + output[n_channel] /= kernel_area; + } + output += channel; + } + } + + return 0; +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_avgpool.h ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_avgpool.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_avgpool.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_avgpool.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN inference functions interface for native backend. + */ + +#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_AVGPOOL_H +#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_AVGPOOL_H + +#include "dnn_backend_native.h" + +typedef struct AvgPoolParams{ + int32_t strides, kernel_size; + DNNPaddingParam padding_method; +} AvgPoolParams; + +int ff_dnn_load_layer_avg_pool(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); +int ff_dnn_execute_layer_avg_pool(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx); + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_conv2d.c ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_conv2d.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_conv2d.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_conv2d.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2018 Sergey Lavrushkin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/thread.h" +#include "libavutil/cpu.h" +#include "dnn_backend_native_layer_conv2d.h" + +#define CLAMP_TO_EDGE(x, w) ((x) < 0 ? 0 : ((x) >= (w) ? (w - 1) : (x))) + +//struct to pass parameters +typedef struct ThreadCommonParam{ + DnnOperand *operands; + const int32_t *input_operand_indexes; + int32_t output_operand_index; + const void *parameters; + NativeContext *ctx; + float *output_data; +} ThreadCommonParam; + +typedef struct ThreadParam{ + ThreadCommonParam *thread_common_param; + int thread_start, thread_end; +#if HAVE_PTHREAD_CANCEL + pthread_t thread; +#endif +} ThreadParam; + +int ff_dnn_load_layer_conv2d(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) +{ + ConvolutionalParams *conv_params; + int kernel_size; + int dnn_size = 0; + conv_params = av_malloc(sizeof(*conv_params)); + if (!conv_params) + return 0; + + conv_params->dilation = (int32_t)avio_rl32(model_file_context); + conv_params->padding_method = (int32_t)avio_rl32(model_file_context); + conv_params->activation = (int32_t)avio_rl32(model_file_context); + conv_params->input_num = (int32_t)avio_rl32(model_file_context); + conv_params->output_num = (int32_t)avio_rl32(model_file_context); + conv_params->kernel_size = (int32_t)avio_rl32(model_file_context); + conv_params->has_bias = (int32_t)avio_rl32(model_file_context); + dnn_size += 28; + + kernel_size = conv_params->input_num * conv_params->output_num * + conv_params->kernel_size * conv_params->kernel_size; + dnn_size += kernel_size * 4; + if (conv_params->has_bias) + dnn_size += conv_params->output_num * 4; + + if (dnn_size > file_size || conv_params->input_num <= 0 || + conv_params->output_num <= 0 || conv_params->kernel_size <= 0){ + av_freep(&conv_params); + return 0; + } + + conv_params->kernel = av_malloc_array(kernel_size, sizeof(*conv_params->kernel)); + if (!conv_params->kernel) { + av_freep(&conv_params); + return 0; + } + for (int i = 0; i < kernel_size; ++i) { + conv_params->kernel[i] = av_int2float(avio_rl32(model_file_context)); + } + + conv_params->biases = NULL; + if (conv_params->has_bias) { + conv_params->biases = av_malloc_array(conv_params->output_num, sizeof(*conv_params->biases)); + if (!conv_params->biases){ + av_freep(&conv_params->kernel); + av_freep(&conv_params); + return 0; + } + for (int i = 0; i < conv_params->output_num; ++i){ + conv_params->biases[i] = av_int2float(avio_rl32(model_file_context)); + } + } + + layer->params = conv_params; + + layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); + layer->output_operand_index = (int32_t)avio_rl32(model_file_context); + dnn_size += 8; + + if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { + return 0; + } + + return dnn_size; +} + +static void * dnn_execute_layer_conv2d_thread(void *threadarg) +{ + //pass parameters + ThreadParam *thread_param = threadarg; + ThreadCommonParam *thread_common_param = thread_param->thread_common_param; + DnnOperand *operands = thread_common_param->operands; + int32_t input_operand_index = thread_common_param->input_operand_indexes[0]; + int height = operands[input_operand_index].dims[1]; + int width = operands[input_operand_index].dims[2]; + int channel = operands[input_operand_index].dims[3]; + const float *input = operands[input_operand_index].data; + const ConvolutionalParams *conv_params = thread_common_param->parameters; + + int radius = conv_params->kernel_size >> 1; + int src_linesize = width * conv_params->input_num; + int filter_linesize = conv_params->kernel_size * conv_params->input_num; + int filter_size = conv_params->kernel_size * filter_linesize; + int pad_size = (conv_params->padding_method == VALID) ? (conv_params->kernel_size - 1) / 2 * conv_params->dilation : 0; + + float *output = thread_common_param->output_data; + output += (conv_params->output_num) * (width - 2 * pad_size) * (thread_param->thread_start - pad_size); + + av_assert0(channel == conv_params->input_num); + + for (int y = thread_param->thread_start; y < thread_param->thread_end; ++y) { + for (int x = pad_size; x < width - pad_size; ++x) { + for (int n_filter = 0; n_filter < conv_params->output_num; ++n_filter) { + if (conv_params->has_bias) + output[n_filter] = conv_params->biases[n_filter]; + else + output[n_filter] = 0.f; + + for (int ch = 0; ch < conv_params->input_num; ++ch) { + for (int kernel_y = 0; kernel_y < conv_params->kernel_size; ++kernel_y) { + for (int kernel_x = 0; kernel_x < conv_params->kernel_size; ++kernel_x) { + float input_pel; + if (conv_params->padding_method == SAME_CLAMP_TO_EDGE) { + int y_pos = CLAMP_TO_EDGE(y + (kernel_y - radius) * conv_params->dilation, height); + int x_pos = CLAMP_TO_EDGE(x + (kernel_x - radius) * conv_params->dilation, width); + input_pel = input[y_pos * src_linesize + x_pos * conv_params->input_num + ch]; + } else { + int y_pos = y + (kernel_y - radius) * conv_params->dilation; + int x_pos = x + (kernel_x - radius) * conv_params->dilation; + input_pel = (x_pos < 0 || x_pos >= width || y_pos < 0 || y_pos >= height) ? 0.0 : + input[y_pos * src_linesize + x_pos * conv_params->input_num + ch]; + } + + + output[n_filter] += input_pel * conv_params->kernel[n_filter * filter_size + kernel_y * filter_linesize + + kernel_x * conv_params->input_num + ch]; + } + } + } + switch (conv_params->activation){ + case RELU: + output[n_filter] = FFMAX(output[n_filter], 0.0); + break; + case TANH: + output[n_filter] = 2.0f / (1.0f + exp(-2.0f * output[n_filter])) - 1.0f; + break; + case SIGMOID: + output[n_filter] = 1.0f / (1.0f + exp(-output[n_filter])); + break; + case NONE: + break; + case LEAKY_RELU: + output[n_filter] = FFMAX(output[n_filter], 0.0) + 0.2 * FFMIN(output[n_filter], 0.0); + } + } + output += conv_params->output_num; + } + } + return NULL; +} + + +int ff_dnn_execute_layer_conv2d(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx) +{ +#if HAVE_PTHREAD_CANCEL + int thread_num = (ctx->options.conv2d_threads <= 0 || ctx->options.conv2d_threads > av_cpu_count()) + ? (av_cpu_count() + 1) : (ctx->options.conv2d_threads); + int ret = DNN_SUCCESS, thread_stride; + ThreadParam *thread_param; +#else + ThreadParam thread_param = { 0 }; +#endif + ThreadCommonParam thread_common_param; + const ConvolutionalParams *conv_params = parameters; + int height = operands[input_operand_indexes[0]].dims[1]; + int width = operands[input_operand_indexes[0]].dims[2]; + int pad_size = (conv_params->padding_method == VALID) ? (conv_params->kernel_size - 1) / 2 * conv_params->dilation : 0; + DnnOperand *output_operand = &operands[output_operand_index]; + void *tmp; + + output_operand->dims[0] = operands[input_operand_indexes[0]].dims[0]; + output_operand->dims[1] = height - pad_size * 2; + output_operand->dims[2] = width - pad_size * 2; + output_operand->dims[3] = conv_params->output_num; + output_operand->data_type = operands[input_operand_indexes[0]].data_type; + output_operand->length = ff_calculate_operand_data_length(output_operand); + if (output_operand->length <= 0) { + av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); + return DNN_ERROR; + } + tmp = av_realloc(output_operand->data, output_operand->length); + if (!tmp) { + av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); + return DNN_ERROR; + } + output_operand->data = tmp; + thread_common_param.output_data = output_operand->data; + thread_common_param.operands = operands; + thread_common_param.input_operand_indexes = input_operand_indexes; + thread_common_param.output_operand_index = output_operand_index; + thread_common_param.parameters = parameters; + thread_common_param.ctx = ctx; + +#if HAVE_PTHREAD_CANCEL + thread_param = av_malloc_array(thread_num, sizeof(*thread_param)); + if (!thread_param) + return DNN_ERROR; + thread_stride = (height - pad_size * 2) / thread_num; + //create threads + for (int i = 0; i < thread_num; i++){ + thread_param[i].thread_common_param = &thread_common_param; + thread_param[i].thread_start = thread_stride * i + pad_size; + thread_param[i].thread_end = (i == thread_num - 1) ? (height - pad_size) : (thread_param[i].thread_start + thread_stride); + if (pthread_create(&thread_param[i].thread, NULL, + dnn_execute_layer_conv2d_thread, &thread_param[i])) { + thread_num = i; + ret = DNN_ERROR; + break; + } + } + + for (int i = 0; i < thread_num; i++){ + pthread_join(thread_param[i].thread, NULL); + } + + //release memory + av_freep(&thread_param); + + return ret; +#else + thread_param.thread_common_param = &thread_common_param; + thread_param.thread_start = pad_size; + thread_param.thread_end = height - pad_size; + dnn_execute_layer_conv2d_thread(&thread_param); + + return DNN_SUCCESS; +#endif +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_conv2d.h ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_conv2d.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_conv2d.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_conv2d.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Sergey Lavrushkin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_DNN_DNN_BACKEND_NATIVE_LAYER_CONV2D_H +#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_CONV2D_H + +#include "dnn_backend_native.h" + + +typedef struct ConvolutionalParams{ + int32_t input_num, output_num, kernel_size; + DNNActivationFunc activation; + DNNPaddingParam padding_method; + int32_t dilation; + int32_t has_bias; + float *kernel; + float *biases; +} ConvolutionalParams; + +int ff_dnn_load_layer_conv2d(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); +int ff_dnn_execute_layer_conv2d(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx); +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_dense.c ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_dense.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_dense.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_dense.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "dnn_backend_native_layer_dense.h" + +int ff_dnn_load_layer_dense(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) +{ + DenseParams *dense_params; + int kernel_size; + int dnn_size = 0; + dense_params = av_malloc(sizeof(*dense_params)); + if (!dense_params) + return 0; + + dense_params->activation = (int32_t)avio_rl32(model_file_context); + dense_params->input_num = (int32_t)avio_rl32(model_file_context); + dense_params->output_num = (int32_t)avio_rl32(model_file_context); + dense_params->has_bias = (int32_t)avio_rl32(model_file_context); + dnn_size += 16; + + kernel_size = dense_params->input_num * dense_params->output_num; + dnn_size += kernel_size * 4; + if (dense_params->has_bias) + dnn_size += dense_params->output_num * 4; + + if (dnn_size > file_size || dense_params->input_num <= 0 || + dense_params->output_num <= 0){ + av_freep(&dense_params); + return 0; + } + + dense_params->kernel = av_malloc(kernel_size * sizeof(float)); + if (!dense_params->kernel) { + av_freep(&dense_params); + return 0; + } + for (int i = 0; i < kernel_size; ++i) { + dense_params->kernel[i] = av_int2float(avio_rl32(model_file_context)); + } + + dense_params->biases = NULL; + if (dense_params->has_bias) { + dense_params->biases = av_malloc(dense_params->output_num * sizeof(float)); + if (!dense_params->biases){ + av_freep(&dense_params->kernel); + av_freep(&dense_params); + return 0; + } + for (int i = 0; i < dense_params->output_num; ++i){ + dense_params->biases[i] = av_int2float(avio_rl32(model_file_context)); + } + } + + layer->params = dense_params; + + layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); + layer->output_operand_index = (int32_t)avio_rl32(model_file_context); + dnn_size += 8; + + if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { + return 0; + } + + return dnn_size; +} + +int ff_dnn_execute_layer_dense(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx) +{ + float *output; + int32_t input_operand_index = input_operand_indexes[0]; + int number = operands[input_operand_index].dims[0]; + int height = operands[input_operand_index].dims[1]; + int width = operands[input_operand_index].dims[2]; + int channel = operands[input_operand_index].dims[3]; + const float *input = operands[input_operand_index].data; + const DenseParams *dense_params = parameters; + + int src_linesize = width * channel; + DnnOperand *output_operand = &operands[output_operand_index]; + output_operand->dims[0] = number; + output_operand->dims[1] = height; + output_operand->dims[2] = width; + output_operand->dims[3] = dense_params->output_num; + output_operand->data_type = operands[input_operand_index].data_type; + output_operand->length = ff_calculate_operand_data_length(output_operand); + if (output_operand->length <= 0) { + av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); + return DNN_ERROR; + } + output_operand->data = av_realloc(output_operand->data, output_operand->length); + if (!output_operand->data) { + av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); + return DNN_ERROR; + } + output = output_operand->data; + + av_assert0(channel == dense_params->input_num); + + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + for (int n_filter = 0; n_filter < dense_params->output_num; ++n_filter) { + if (dense_params->has_bias) + output[n_filter] = dense_params->biases[n_filter]; + else + output[n_filter] = 0.f; + + for (int ch = 0; ch < dense_params->input_num; ++ch) { + float input_pel; + input_pel = input[y * src_linesize + x * dense_params->input_num + ch]; + output[n_filter] += input_pel * dense_params->kernel[n_filter*dense_params->input_num + ch]; + } + switch (dense_params->activation){ + case RELU: + output[n_filter] = FFMAX(output[n_filter], 0.0); + break; + case TANH: + output[n_filter] = 2.0f / (1.0f + exp(-2.0f * output[n_filter])) - 1.0f; + break; + case SIGMOID: + output[n_filter] = 1.0f / (1.0f + exp(-output[n_filter])); + break; + case NONE: + break; + case LEAKY_RELU: + output[n_filter] = FFMAX(output[n_filter], 0.0) + 0.2 * FFMIN(output[n_filter], 0.0); + } + } + output += dense_params->output_num; + } + } + return 0; +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_dense.h ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_dense.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_dense.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_dense.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_DNN_DNN_BACKEND_NATIVE_LAYER_DENSE_H +#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_DENSE_H + +#include "dnn_backend_native.h" + +typedef struct DenseParams{ + int32_t input_num, output_num; + DNNActivationFunc activation; + int32_t has_bias; + float *kernel; + float *biases; +} DenseParams; + +int ff_dnn_load_layer_dense(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); +int ff_dnn_execute_layer_dense(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx); +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_depth2space.c ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_depth2space.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_depth2space.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_depth2space.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018 Sergey Lavrushkin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN native backend implementation. + */ + +#include "dnn_backend_native.h" +#include "libavutil/avassert.h" +#include "dnn_backend_native_layer_depth2space.h" + +int ff_dnn_load_layer_depth2space(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) +{ + DepthToSpaceParams *params; + int dnn_size = 0; + params = av_malloc(sizeof(*params)); + if (!params) + return 0; + + params->block_size = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); + layer->output_operand_index = (int32_t)avio_rl32(model_file_context); + dnn_size += 8; + layer->params = params; + + if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { + return 0; + } + + return dnn_size; +} + +int ff_dnn_execute_layer_depth2space(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx) +{ + float *output; + const DepthToSpaceParams *params = parameters; + int block_size = params->block_size; + int32_t input_operand_index = input_operand_indexes[0]; + int number = operands[input_operand_index].dims[0]; + int height = operands[input_operand_index].dims[1]; + int width = operands[input_operand_index].dims[2]; + int channels = operands[input_operand_index].dims[3]; + const float *input = operands[input_operand_index].data; + + int y, x, by, bx, ch; + int new_channels = channels / (block_size * block_size); + int output_linesize = width * channels; + int by_linesize = output_linesize / block_size; + int x_linesize = new_channels * block_size; + + DnnOperand *output_operand = &operands[output_operand_index]; + output_operand->dims[0] = number; + output_operand->dims[1] = height * block_size; + output_operand->dims[2] = width * block_size; + output_operand->dims[3] = new_channels; + output_operand->data_type = operands[input_operand_index].data_type; + output_operand->length = ff_calculate_operand_data_length(output_operand); + if (output_operand->length <= 0) { + av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); + return DNN_ERROR; + } + output_operand->data = av_realloc(output_operand->data, output_operand->length); + if (!output_operand->data) { + av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); + return DNN_ERROR; + } + output = output_operand->data; + + for (y = 0; y < height; ++y){ + for (x = 0; x < width; ++x){ + for (by = 0; by < block_size; ++by){ + for (bx = 0; bx < block_size; ++bx){ + for (ch = 0; ch < new_channels; ++ch){ + output[by * by_linesize + x * x_linesize + bx * new_channels + ch] = input[ch]; + } + input += new_channels; + } + } + } + output += output_linesize; + } + return 0; +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_depth2space.h ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_depth2space.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_depth2space.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_depth2space.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018 Sergey Lavrushkin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN inference functions interface for native backend. + */ + + +#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_DEPTH2SPACE_H +#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_DEPTH2SPACE_H + +#include "../dnn_interface.h" +#include "libavformat/avio.h" + +typedef struct DepthToSpaceParams{ + int block_size; +} DepthToSpaceParams; + +int ff_dnn_load_layer_depth2space(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); +int ff_dnn_execute_layer_depth2space(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx); + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_mathbinary.c ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_mathbinary.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_mathbinary.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_mathbinary.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN native backend implementation. + */ + +#include "dnn_backend_native.h" +#include "libavutil/avassert.h" +#include "dnn_backend_native_layer_mathbinary.h" + +typedef float (*FunType)(float src0, float src1); + +static float sub(float src0, float src1) +{ + return src0 - src1; +} +static float add(float src0, float src1) +{ + return src0 + src1; +} +static float mul(float src0, float src1) +{ + return src0 * src1; +} +static float realdiv(float src0, float src1) +{ + return src0 / src1; +} +static float minimum(float src0, float src1) +{ + return FFMIN(src0, src1); +} +static float floormod(float src0, float src1) +{ + return (float)((int)(src0) % (int)(src1)); +} + +static void math_binary_commutative(FunType pfun, const DnnLayerMathBinaryParams *params, const DnnOperand *input, DnnOperand *output, DnnOperand *operands, const int32_t *input_operand_indexes) +{ + int dims_count; + const float *src; + float *dst; + dims_count = ff_calculate_operand_dims_count(output); + src = input->data; + dst = output->data; + if (params->input0_broadcast || params->input1_broadcast) { + for (int i = 0; i < dims_count; ++i) { + dst[i] = pfun(params->v, src[i]); + } + } else { + const DnnOperand *input1 = &operands[input_operand_indexes[1]]; + const float *src1 = input1->data; + for (int i = 0; i < dims_count; ++i) { + dst[i] = pfun(src[i], src1[i]); + } + } +} +static void math_binary_not_commutative(FunType pfun, const DnnLayerMathBinaryParams *params, const DnnOperand *input, DnnOperand *output, DnnOperand *operands, const int32_t *input_operand_indexes) +{ + int dims_count; + const float *src; + float *dst; + dims_count = ff_calculate_operand_dims_count(output); + src = input->data; + dst = output->data; + if (params->input0_broadcast) { + for (int i = 0; i < dims_count; ++i) { + dst[i] = pfun(params->v, src[i]); + } + } else if (params->input1_broadcast) { + for (int i = 0; i < dims_count; ++i) { + dst[i] = pfun(src[i], params->v); + } + } else { + const DnnOperand *input1 = &operands[input_operand_indexes[1]]; + const float *src1 = input1->data; + for (int i = 0; i < dims_count; ++i) { + dst[i] = pfun(src[i], src1[i]); + } + } +} +int ff_dnn_load_layer_math_binary(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) +{ + DnnLayerMathBinaryParams params = { 0 }; + int dnn_size = 0; + int input_index = 0; + + params.bin_op = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + + params.input0_broadcast = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + if (params.input0_broadcast) { + params.v = av_int2float(avio_rl32(model_file_context)); + } else { + layer->input_operand_indexes[input_index] = (int32_t)avio_rl32(model_file_context); + if (layer->input_operand_indexes[input_index] >= operands_num) { + return 0; + } + input_index++; + } + dnn_size += 4; + + params.input1_broadcast = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + if (params.input1_broadcast) { + params.v = av_int2float(avio_rl32(model_file_context)); + } else { + layer->input_operand_indexes[input_index] = (int32_t)avio_rl32(model_file_context); + if (layer->input_operand_indexes[input_index] >= operands_num) { + return 0; + } + input_index++; + } + dnn_size += 4; + + layer->output_operand_index = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + + if (layer->output_operand_index >= operands_num) { + return 0; + } + layer->params = av_memdup(¶ms, sizeof(params)); + if (!layer->params) + return 0; + + return dnn_size; +} + +int ff_dnn_execute_layer_math_binary(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx) +{ + const DnnOperand *input = &operands[input_operand_indexes[0]]; + DnnOperand *output = &operands[output_operand_index]; + const DnnLayerMathBinaryParams *params = parameters; + + for (int i = 0; i < 4; ++i) + output->dims[i] = input->dims[i]; + + output->data_type = input->data_type; + output->length = ff_calculate_operand_data_length(output); + if (output->length <= 0) { + av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); + return DNN_ERROR; + } + output->data = av_realloc(output->data, output->length); + if (!output->data) { + av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); + return DNN_ERROR; + } + + switch (params->bin_op) { + case DMBO_SUB: + math_binary_not_commutative(sub, params, input, output, operands, input_operand_indexes); + return 0; + case DMBO_ADD: + math_binary_commutative(add, params, input, output, operands, input_operand_indexes); + return 0; + case DMBO_MUL: + math_binary_commutative(mul, params, input, output, operands, input_operand_indexes); + return 0; + case DMBO_REALDIV: + math_binary_not_commutative(realdiv, params, input, output, operands, input_operand_indexes); + return 0; + case DMBO_MINIMUM: + math_binary_commutative(minimum, params, input, output, operands, input_operand_indexes); + return 0; + case DMBO_FLOORMOD: + math_binary_not_commutative(floormod, params, input, output, operands, input_operand_indexes); + return 0; + default: + av_log(ctx, AV_LOG_ERROR, "Unmatch math binary operator\n"); + return DNN_ERROR; + } +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_mathbinary.h ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_mathbinary.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_mathbinary.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_mathbinary.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN inference functions interface for native backend. + */ + + +#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_MATHBINARY_H +#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_MATHBINARY_H + +#include "libavformat/avio.h" +#include "dnn_backend_native.h" + +typedef enum { + DMBO_SUB = 0, + DMBO_ADD = 1, + DMBO_MUL = 2, + DMBO_REALDIV = 3, + DMBO_MINIMUM = 4, + DMBO_FLOORMOD = 5, + DMBO_COUNT +} DNNMathBinaryOperation; + +typedef struct DnnLayerMathBinaryParams{ + DNNMathBinaryOperation bin_op; + int input0_broadcast; + int input1_broadcast; + float v; +} DnnLayerMathBinaryParams; + +int ff_dnn_load_layer_math_binary(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); +int ff_dnn_execute_layer_math_binary(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx); + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_mathunary.c ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_mathunary.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_mathunary.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_mathunary.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN native backend implementation. + */ + +#include + +#include "dnn_backend_native.h" +#include "libavutil/avassert.h" +#include "dnn_backend_native_layer_mathunary.h" + +int ff_dnn_load_layer_math_unary(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) +{ + DnnLayerMathUnaryParams *params; + int dnn_size = 0; + params = av_malloc(sizeof(*params)); + if(!params) + return 0; + + params->un_op = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + layer->params = params; + layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); + layer->output_operand_index = (int32_t)avio_rl32(model_file_context); + dnn_size += 8; + + if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { + return 0; + } + + return dnn_size; + +} + +int ff_dnn_execute_layer_math_unary(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx) +{ + const DnnOperand *input = &operands[input_operand_indexes[0]]; + DnnOperand *output = &operands[output_operand_index]; + const DnnLayerMathUnaryParams *params = parameters; + int dims_count; + const float *src; + float *dst; + + for (int i = 0; i < 4; ++i) + output->dims[i] = input->dims[i]; + + output->data_type = input->data_type; + output->length = ff_calculate_operand_data_length(output); + if (output->length <= 0) { + av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); + return DNN_ERROR; + } + output->data = av_realloc(output->data, output->length); + if (!output->data) { + av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); + return DNN_ERROR; + } + + dims_count = ff_calculate_operand_dims_count(output); + src = input->data; + dst = output->data; + + switch (params->un_op) { + case DMUO_ABS: + for (int i = 0; i < dims_count; ++i) + dst[i] = FFABS(src[i]); + return 0; + case DMUO_SIN: + for (int i = 0; i < dims_count; ++i) + dst[i] = sin(src[i]); + return 0; + case DMUO_COS: + for (int i = 0; i < dims_count; ++i) + dst[i] = cos(src[i]); + return 0; + case DMUO_TAN: + for (int i = 0; i < dims_count; ++i) + dst[i] = tan(src[i]); + return 0; + case DMUO_ASIN: + for (int i = 0; i < dims_count; ++i) + dst[i] = asin(src[i]); + return 0; + case DMUO_ACOS: + for (int i = 0; i < dims_count; ++i) + dst[i] = acos(src[i]); + return 0; + case DMUO_ATAN: + for (int i = 0; i < dims_count; ++i) + dst[i] = atan(src[i]); + return 0; + case DMUO_SINH: + for (int i = 0; i < dims_count; ++i) + dst[i] = sinh(src[i]); + return 0; + case DMUO_COSH: + for (int i = 0; i < dims_count; ++i) + dst[i] = cosh(src[i]); + return 0; + case DMUO_TANH: + for (int i = 0; i < dims_count; ++i) + dst[i] = tanh(src[i]); + return 0; + case DMUO_ASINH: + for (int i = 0; i < dims_count; ++i) + dst[i] = asinh(src[i]); + return 0; + case DMUO_ACOSH: + for (int i = 0; i < dims_count; ++i) + dst[i] = acosh(src[i]); + return 0; + case DMUO_ATANH: + for (int i = 0; i < dims_count; ++i) + dst[i] = atanh(src[i]); + return 0; + case DMUO_CEIL: + for (int i = 0; i < dims_count; ++i) + dst[i] = ceil(src[i]); + return 0; + case DMUO_FLOOR: + for (int i = 0; i < dims_count; ++i) + dst[i] = floor(src[i]); + return 0; + case DMUO_ROUND: + for (int i = 0; i < dims_count; ++i) + dst[i] = round(src[i]); + return 0; + default: + av_log(ctx, AV_LOG_ERROR, "Unmatch math unary operator\n"); + return DNN_ERROR; + } +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_mathunary.h ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_mathunary.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_mathunary.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_mathunary.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN inference functions interface for native backend. + */ + +#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_MATHUNARY_H +#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_MATHUNARY_H + +#include "libavformat/avio.h" +#include "dnn_backend_native.h" + +typedef enum { + DMUO_ABS = 0, + DMUO_SIN = 1, + DMUO_COS = 2, + DMUO_TAN = 3, + DMUO_ASIN = 4, + DMUO_ACOS = 5, + DMUO_ATAN = 6, + DMUO_SINH = 7, + DMUO_COSH = 8, + DMUO_TANH = 9, + DMUO_ASINH = 10, + DMUO_ACOSH = 11, + DMUO_ATANH = 12, + DMUO_CEIL = 13, + DMUO_FLOOR = 14, + DMUO_ROUND = 15, + DMUO_COUNT +} DNNMathUnaryOperation; + +typedef struct DnnLayerMathUnaryParams{ + DNNMathUnaryOperation un_op; +} DnnLayerMathUnaryParams; + +int ff_dnn_load_layer_math_unary(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); +int ff_dnn_execute_layer_math_unary(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx); + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_maximum.c ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_maximum.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_maximum.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_maximum.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019 Guo Yejun + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN native backend implementation. + */ + +#include "dnn_backend_native.h" +#include "libavutil/avassert.h" +#include "dnn_backend_native_layer_maximum.h" + +int ff_dnn_load_layer_maximum(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) +{ + DnnLayerMaximumParams *params; + int dnn_size = 0; + params = av_malloc(sizeof(*params)); + if (!params) + return 0; + + params->val.u32 = avio_rl32(model_file_context); + dnn_size += 4; + layer->params = params; + layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); + layer->output_operand_index = (int32_t)avio_rl32(model_file_context); + dnn_size += 8; + + if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { + return 0; + } + + return dnn_size; +} + +int ff_dnn_execute_layer_maximum(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx) +{ + const DnnOperand *input = &operands[input_operand_indexes[0]]; + DnnOperand *output = &operands[output_operand_index]; + const DnnLayerMaximumParams *params = parameters; + int dims_count; + const float *src; + float *dst; + + for (int i = 0; i < 4; ++i) + output->dims[i] = input->dims[i]; + + output->data_type = input->data_type; + output->length = ff_calculate_operand_data_length(output); + if (output->length <= 0) { + av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); + return DNN_ERROR; + } + output->data = av_realloc(output->data, output->length); + if (!output->data) { + av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); + return DNN_ERROR; + } + + dims_count = ff_calculate_operand_dims_count(output); + src = input->data; + dst = output->data; + for (int i = 0; i < dims_count; ++i) + dst[i] = FFMAX(src[i], params->val.y); + + return 0; +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_maximum.h ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_maximum.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_maximum.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_maximum.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 Guo Yejun + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN inference functions interface for native backend. + */ + + +#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_MAXIMUM_H +#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_MAXIMUM_H + +#include "libavformat/avio.h" +#include "dnn_backend_native.h" + +typedef struct DnnLayerMaximumParams{ + union { + uint32_t u32; + float y; + }val; +} DnnLayerMaximumParams; + +int ff_dnn_load_layer_maximum(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); +int ff_dnn_execute_layer_maximum(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx); + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_pad.c ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_pad.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_pad.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_pad.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2019 Guo Yejun + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "dnn_backend_native_layer_pad.h" + +int ff_dnn_load_layer_pad(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num) +{ + LayerPadParams *params; + int dnn_size = 0; + params = av_malloc(sizeof(*params)); + if (!params) + return 0; + + params->mode = (int32_t)avio_rl32(model_file_context); + dnn_size += 4; + for (int i = 0; i < 4; ++i) { + params->paddings[i][0] = avio_rl32(model_file_context); + params->paddings[i][1] = avio_rl32(model_file_context); + dnn_size += 8; + } + layer->input_operand_indexes[0] = (int32_t)avio_rl32(model_file_context); + layer->output_operand_index = (int32_t)avio_rl32(model_file_context); + dnn_size += 8; + layer->params = params; + + if (layer->input_operand_indexes[0] >= operands_num || layer->output_operand_index >= operands_num) { + return 0; + } + + return dnn_size; +} + +static int before_get_buddy(int given, int paddings, LayerPadModeParam mode) +{ + if (mode == LPMP_SYMMETRIC) { + return (2 * paddings - 1 - given); + } else if (mode == LPMP_REFLECT) { + return (2 * paddings - given); + } else { + av_assert0(!"should not reach here"); + return 0; + } +} + +static int after_get_buddy(int given, int border, LayerPadModeParam mode) +{ + if (mode == LPMP_SYMMETRIC) { + int offset = given - border; + return (border - 1 - offset); + } else if (mode == LPMP_REFLECT) { + int offset = given - border; + return (border - 2 - offset); + } else { + av_assert0(!"should not reach here"); + return 0; + } +} + +int ff_dnn_execute_layer_pad(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx) +{ + int32_t before_paddings; + int32_t after_paddings; + float* output; + const LayerPadParams *params = parameters; + + // suppose format is + int32_t input_operand_index = input_operand_indexes[0]; + int number = operands[input_operand_index].dims[0]; + int height = operands[input_operand_index].dims[1]; + int width = operands[input_operand_index].dims[2]; + int channel = operands[input_operand_index].dims[3]; + const float *input = operands[input_operand_index].data; + + int new_number = number + params->paddings[0][0] + params->paddings[0][1]; + int new_height = height + params->paddings[1][0] + params->paddings[1][1]; + int new_width = width + params->paddings[2][0] + params->paddings[2][1]; + int new_channel = channel + params->paddings[3][0] + params->paddings[3][1]; + + int c_stride = channel; + int wc_stride = c_stride * width; + int hwc_stride = wc_stride * height; + + int new_c_stride = new_channel; + int new_wc_stride = new_c_stride * new_width; + int new_hwc_stride = new_wc_stride * new_height; + + DnnOperand *output_operand = &operands[output_operand_index]; + output_operand->dims[0] = new_number; + output_operand->dims[1] = new_height; + output_operand->dims[2] = new_width; + output_operand->dims[3] = new_channel; + output_operand->data_type = operands[input_operand_index].data_type; + output_operand->length = ff_calculate_operand_data_length(output_operand); + if (output_operand->length <= 0) { + av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); + return DNN_ERROR; + } + output_operand->data = av_realloc(output_operand->data, output_operand->length); + if (!output_operand->data) { + av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); + return DNN_ERROR; + } + output = output_operand->data; + + // copy the original data + for (int n = 0; n < number; n++) { + for (int h = 0; h < height; h++) { + for (int w = 0; w < width; w++) { + const float *src = input + n * hwc_stride + h * wc_stride + w * c_stride; + float *dst = output + (n + params->paddings[0][0]) * new_hwc_stride + + (h + params->paddings[1][0]) * new_wc_stride + + (w + params->paddings[2][0]) * new_c_stride + + params->paddings[3][0]; + memcpy(dst, src, channel * sizeof(float)); + } + } + } + + // handle the first dimension + before_paddings = params->paddings[0][0]; + after_paddings = params->paddings[0][1]; + for (int n = 0; n < before_paddings; n++) { + float *dst = output + n * new_hwc_stride; + if (params->mode == LPMP_CONSTANT) { + for (int i = 0; i < new_hwc_stride; i++) { + dst[i] = params->constant_values; + } + } + else { + int buddy = before_get_buddy(n, before_paddings, params->mode); + float *src = output + buddy * new_hwc_stride; + memcpy(dst, src, new_hwc_stride * sizeof(float)); + } + } + for (int n = 0; n < after_paddings; n++) { + int given = number + before_paddings + n; + float *dst = output + given * new_hwc_stride; + if (params->mode == LPMP_CONSTANT) { + for (int i = 0; i < new_hwc_stride; i++) { + dst[i] = params->constant_values; + } + } else { + int buddy = after_get_buddy(given, number + before_paddings, params->mode); + float *src = output + buddy * new_hwc_stride; + memcpy(dst, src, new_hwc_stride * sizeof(float)); + } + } + + // handle the second dimension + before_paddings = params->paddings[1][0]; + after_paddings = params->paddings[1][1]; + for (int n = 0; n < new_number; n++) { + float *start = output + n * new_hwc_stride; + for (int h = 0; h < before_paddings; h++) { + float *dst = start + h * new_wc_stride; + if (params->mode == LPMP_CONSTANT) { + for (int i = 0; i < new_wc_stride; i++) { + dst[i] = params->constant_values; + } + } else { + int buddy = before_get_buddy(h, before_paddings, params->mode); + float *src = start + buddy * new_wc_stride; + memcpy(dst, src, new_wc_stride * sizeof(float)); + } + } + for (int h = 0; h < after_paddings; h++) { + int given = height + before_paddings + h; + float *dst = start + given * new_wc_stride; + if (params->mode == LPMP_CONSTANT) { + for (int i = 0; i < new_wc_stride; i++) { + dst[i] = params->constant_values; + } + } else { + int buddy = after_get_buddy(given, height + before_paddings, params->mode); + float *src = start + buddy * new_wc_stride; + memcpy(dst, src, new_wc_stride * sizeof(float)); + } + } + } + + // handle the third dimension + before_paddings = params->paddings[2][0]; + after_paddings = params->paddings[2][1]; + for (int n = 0; n < new_number; n++) { + for (int h = 0; h < new_height; h++) { + float *start = output + n * new_hwc_stride + h * new_wc_stride; + for (int w = 0; w < before_paddings; w++) { + float *dst = start + w * new_c_stride; + if (params->mode == LPMP_CONSTANT) { + for (int i = 0; i < new_c_stride; i++) { + dst[i] = params->constant_values; + } + } else { + int buddy = before_get_buddy(w, before_paddings, params->mode); + float *src = start + buddy * new_c_stride; + memcpy(dst, src, new_c_stride * sizeof(float)); + } + } + for (int w = 0; w < after_paddings; w++) { + int given = width + before_paddings + w; + float *dst = start + given * new_c_stride; + if (params->mode == LPMP_CONSTANT) { + for (int i = 0; i < new_c_stride; i++) { + dst[i] = params->constant_values; + } + } else { + int buddy = after_get_buddy(given, width + before_paddings, params->mode); + float *src = start + buddy * new_c_stride; + memcpy(dst, src, new_c_stride * sizeof(float)); + } + } + } + } + + // handle the fourth dimension + before_paddings = params->paddings[3][0]; + after_paddings = params->paddings[3][1]; + for (int n = 0; n < new_number; n++) { + for (int h = 0; h < new_height; h++) { + for (int w = 0; w < new_width; w++) { + float *start = output + n * new_hwc_stride + h * new_wc_stride + w * new_c_stride; + for (int c = 0; c < before_paddings; c++) { + float *dst = start + c; + if (params->mode == LPMP_CONSTANT) { + *dst = params->constant_values; + } else { + int buddy = before_get_buddy(c, before_paddings, params->mode); + float *src = start + buddy; + *dst = *src; + } + } + for (int c = 0; c < after_paddings; c++) { + int given = channel + before_paddings + c; + float *dst = start + given; + if (params->mode == LPMP_CONSTANT) { + *dst = params->constant_values; + } else { + int buddy = after_get_buddy(given, channel + before_paddings, params->mode); + float *src = start + buddy; + *dst = *src; + } + } + } + } + } + + return 0; +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_pad.h ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_pad.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layer_pad.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layer_pad.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 Guo Yejun + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * layer pad (equivalent to tf.pad) for native backend. + */ +#ifndef AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_PAD_H +#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYER_PAD_H + +#include +#include "dnn_backend_native.h" + +typedef enum {LPMP_CONSTANT, LPMP_REFLECT, LPMP_SYMMETRIC} LayerPadModeParam; + +typedef struct LayerPadParams{ + int32_t paddings[4][2]; + LayerPadModeParam mode; + float constant_values; +} LayerPadParams; + +int ff_dnn_load_layer_pad(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); +int ff_dnn_execute_layer_pad(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx); + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layers.c ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layers.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layers.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layers.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 Guo Yejun + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "dnn_backend_native_layers.h" +#include "dnn_backend_native_layer_pad.h" +#include "dnn_backend_native_layer_conv2d.h" +#include "dnn_backend_native_layer_depth2space.h" +#include "dnn_backend_native_layer_maximum.h" +#include "dnn_backend_native_layer_mathbinary.h" +#include "dnn_backend_native_layer_mathunary.h" +#include "dnn_backend_native_layer_avgpool.h" +#include "dnn_backend_native_layer_dense.h" + +const LayerFunc ff_layer_funcs[DLT_COUNT] = { + {NULL, NULL}, + {ff_dnn_execute_layer_conv2d, ff_dnn_load_layer_conv2d}, + {ff_dnn_execute_layer_depth2space, ff_dnn_load_layer_depth2space}, + {ff_dnn_execute_layer_pad, ff_dnn_load_layer_pad}, + {ff_dnn_execute_layer_maximum, ff_dnn_load_layer_maximum}, + {ff_dnn_execute_layer_math_binary, ff_dnn_load_layer_math_binary}, + {ff_dnn_execute_layer_math_unary, ff_dnn_load_layer_math_unary}, + {ff_dnn_execute_layer_avg_pool, ff_dnn_load_layer_avg_pool}, + {ff_dnn_execute_layer_dense, ff_dnn_load_layer_dense}, +}; diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layers.h ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layers.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_native_layers.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_native_layers.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019 Guo Yejun + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_DNN_DNN_BACKEND_NATIVE_LAYERS_H +#define AVFILTER_DNN_DNN_BACKEND_NATIVE_LAYERS_H + +#include +#include "dnn_backend_native.h" + +typedef int (*LAYER_EXEC_FUNC)(DnnOperand *operands, const int32_t *input_operand_indexes, + int32_t output_operand_index, const void *parameters, NativeContext *ctx); +typedef int (*LAYER_LOAD_FUNC)(Layer *layer, AVIOContext *model_file_context, int file_size, int operands_num); + +typedef struct LayerFunc { + LAYER_EXEC_FUNC pf_exec; + LAYER_LOAD_FUNC pf_load; +}LayerFunc; + +extern const LayerFunc ff_layer_funcs[DLT_COUNT]; + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_openvino.c ffmpeg-4.4/libavfilter/dnn/dnn_backend_openvino.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_openvino.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_openvino.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,814 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN OpenVINO backend implementation. + */ + +#include "dnn_backend_openvino.h" +#include "dnn_io_proc.h" +#include "libavformat/avio.h" +#include "libavutil/avassert.h" +#include "libavutil/opt.h" +#include "libavutil/avstring.h" +#include "../internal.h" +#include "queue.h" +#include "safe_queue.h" +#include + +typedef struct OVOptions{ + char *device_type; + int nireq; + int batch_size; + int input_resizable; +} OVOptions; + +typedef struct OVContext { + const AVClass *class; + OVOptions options; +} OVContext; + +typedef struct OVModel{ + OVContext ctx; + DNNModel *model; + ie_core_t *core; + ie_network_t *network; + ie_executable_network_t *exe_network; + ie_infer_request_t *infer_request; + + /* for async execution */ + SafeQueue *request_queue; // holds RequestItem + Queue *task_queue; // holds TaskItem +} OVModel; + +typedef struct TaskItem { + OVModel *ov_model; + const char *input_name; + AVFrame *in_frame; + const char *output_name; + AVFrame *out_frame; + int do_ioproc; + int async; + int done; +} TaskItem; + +typedef struct RequestItem { + ie_infer_request_t *infer_request; + TaskItem **tasks; + int task_count; + ie_complete_call_back_t callback; +} RequestItem; + +#define APPEND_STRING(generated_string, iterate_string) \ + generated_string = generated_string ? av_asprintf("%s %s", generated_string, iterate_string) : \ + av_asprintf("%s", iterate_string); + +#define OFFSET(x) offsetof(OVContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM +static const AVOption dnn_openvino_options[] = { + { "device", "device to run model", OFFSET(options.device_type), AV_OPT_TYPE_STRING, { .str = "CPU" }, 0, 0, FLAGS }, + { "nireq", "number of request", OFFSET(options.nireq), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { "batch_size", "batch size per request", OFFSET(options.batch_size), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 1000, FLAGS}, + { "input_resizable", "can input be resizable or not", OFFSET(options.input_resizable), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(dnn_openvino); + +static DNNDataType precision_to_datatype(precision_e precision) +{ + switch (precision) + { + case FP32: + return DNN_FLOAT; + case U8: + return DNN_UINT8; + default: + av_assert0(!"not supported yet."); + return DNN_FLOAT; + } +} + +static int get_datatype_size(DNNDataType dt) +{ + switch (dt) + { + case DNN_FLOAT: + return sizeof(float); + case DNN_UINT8: + return sizeof(uint8_t); + default: + av_assert0(!"not supported yet."); + return 1; + } +} + +static DNNReturnType fill_model_input_ov(OVModel *ov_model, RequestItem *request) +{ + dimensions_t dims; + precision_e precision; + ie_blob_buffer_t blob_buffer; + OVContext *ctx = &ov_model->ctx; + IEStatusCode status; + DNNData input; + ie_blob_t *input_blob = NULL; + TaskItem *task = request->tasks[0]; + + status = ie_infer_request_get_blob(request->infer_request, task->input_name, &input_blob); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to get input blob with name %s\n", task->input_name); + return DNN_ERROR; + } + + status |= ie_blob_get_dims(input_blob, &dims); + status |= ie_blob_get_precision(input_blob, &precision); + if (status != OK) { + ie_blob_free(&input_blob); + av_log(ctx, AV_LOG_ERROR, "Failed to get input blob dims/precision\n"); + return DNN_ERROR; + } + + status = ie_blob_get_buffer(input_blob, &blob_buffer); + if (status != OK) { + ie_blob_free(&input_blob); + av_log(ctx, AV_LOG_ERROR, "Failed to get input blob buffer\n"); + return DNN_ERROR; + } + + input.height = dims.dims[2]; + input.width = dims.dims[3]; + input.channels = dims.dims[1]; + input.data = blob_buffer.buffer; + input.dt = precision_to_datatype(precision); + // all models in openvino open model zoo use BGR as input, + // change to be an option when necessary. + input.order = DCO_BGR; + + av_assert0(request->task_count <= dims.dims[0]); + for (int i = 0; i < request->task_count; ++i) { + task = request->tasks[i]; + if (task->do_ioproc) { + if (ov_model->model->pre_proc != NULL) { + ov_model->model->pre_proc(task->in_frame, &input, ov_model->model->filter_ctx); + } else { + ff_proc_from_frame_to_dnn(task->in_frame, &input, ov_model->model->func_type, ctx); + } + } + input.data = (uint8_t *)input.data + + input.width * input.height * input.channels * get_datatype_size(input.dt); + } + ie_blob_free(&input_blob); + + return DNN_SUCCESS; +} + +static void infer_completion_callback(void *args) +{ + dimensions_t dims; + precision_e precision; + IEStatusCode status; + RequestItem *request = args; + TaskItem *task = request->tasks[0]; + SafeQueue *requestq = task->ov_model->request_queue; + ie_blob_t *output_blob = NULL; + ie_blob_buffer_t blob_buffer; + DNNData output; + OVContext *ctx = &task->ov_model->ctx; + + status = ie_infer_request_get_blob(request->infer_request, task->output_name, &output_blob); + if (status != OK) { + //incorrect output name + char *model_output_name = NULL; + char *all_output_names = NULL; + size_t model_output_count = 0; + av_log(ctx, AV_LOG_ERROR, "Failed to get model output data\n"); + status = ie_network_get_outputs_number(task->ov_model->network, &model_output_count); + for (size_t i = 0; i < model_output_count; i++) { + status = ie_network_get_output_name(task->ov_model->network, i, &model_output_name); + APPEND_STRING(all_output_names, model_output_name) + } + av_log(ctx, AV_LOG_ERROR, + "output \"%s\" may not correct, all output(s) are: \"%s\"\n", + task->output_name, all_output_names); + return; + } + + status = ie_blob_get_buffer(output_blob, &blob_buffer); + if (status != OK) { + ie_blob_free(&output_blob); + av_log(ctx, AV_LOG_ERROR, "Failed to access output memory\n"); + return; + } + + status |= ie_blob_get_dims(output_blob, &dims); + status |= ie_blob_get_precision(output_blob, &precision); + if (status != OK) { + ie_blob_free(&output_blob); + av_log(ctx, AV_LOG_ERROR, "Failed to get dims or precision of output\n"); + return; + } + + output.channels = dims.dims[1]; + output.height = dims.dims[2]; + output.width = dims.dims[3]; + output.dt = precision_to_datatype(precision); + output.data = blob_buffer.buffer; + + av_assert0(request->task_count <= dims.dims[0]); + av_assert0(request->task_count >= 1); + for (int i = 0; i < request->task_count; ++i) { + task = request->tasks[i]; + if (task->do_ioproc) { + if (task->ov_model->model->post_proc != NULL) { + task->ov_model->model->post_proc(task->out_frame, &output, task->ov_model->model->filter_ctx); + } else { + ff_proc_from_dnn_to_frame(task->out_frame, &output, ctx); + } + } else { + task->out_frame->width = output.width; + task->out_frame->height = output.height; + } + task->done = 1; + output.data = (uint8_t *)output.data + + output.width * output.height * output.channels * get_datatype_size(output.dt); + } + ie_blob_free(&output_blob); + + request->task_count = 0; + + if (task->async) { + if (ff_safe_queue_push_back(requestq, request) < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to push back request_queue.\n"); + return; + } + } +} + +static DNNReturnType init_model_ov(OVModel *ov_model, const char *input_name, const char *output_name) +{ + OVContext *ctx = &ov_model->ctx; + IEStatusCode status; + ie_available_devices_t a_dev; + ie_config_t config = {NULL, NULL, NULL}; + char *all_dev_names = NULL; + + // batch size + if (ctx->options.batch_size <= 0) { + ctx->options.batch_size = 1; + } + + if (ctx->options.batch_size > 1) { + input_shapes_t input_shapes; + status = ie_network_get_input_shapes(ov_model->network, &input_shapes); + if (status != OK) + goto err; + for (int i = 0; i < input_shapes.shape_num; i++) + input_shapes.shapes[i].shape.dims[0] = ctx->options.batch_size; + status = ie_network_reshape(ov_model->network, input_shapes); + ie_network_input_shapes_free(&input_shapes); + if (status != OK) + goto err; + } + + // The order of dims in the openvino is fixed and it is always NCHW for 4-D data. + // while we pass NHWC data from FFmpeg to openvino + status = ie_network_set_input_layout(ov_model->network, input_name, NHWC); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to set layout as NHWC for input %s\n", input_name); + goto err; + } + status = ie_network_set_output_layout(ov_model->network, output_name, NHWC); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to set layout as NHWC for output %s\n", output_name); + goto err; + } + + // all models in openvino open model zoo use BGR with range [0.0f, 255.0f] as input, + // we don't have a AVPixelFormat to descibe it, so we'll use AV_PIX_FMT_BGR24 and + // ask openvino to do the conversion internally. + // the current supported SR model (frame processing) is generated from tensorflow model, + // and its input is Y channel as float with range [0.0f, 1.0f], so do not set for this case. + // TODO: we need to get a final clear&general solution with all backends/formats considered. + if (ov_model->model->func_type != DFT_PROCESS_FRAME) { + status = ie_network_set_input_precision(ov_model->network, input_name, U8); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to set input precision as U8 for %s\n", input_name); + goto err; + } + } + + status = ie_core_load_network(ov_model->core, ov_model->network, ctx->options.device_type, &config, &ov_model->exe_network); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to load OpenVINO model network\n"); + status = ie_core_get_available_devices(ov_model->core, &a_dev); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to get available devices\n"); + goto err; + } + for (int i = 0; i < a_dev.num_devices; i++) { + APPEND_STRING(all_dev_names, a_dev.devices[i]) + } + av_log(ctx, AV_LOG_ERROR,"device %s may not be supported, all available devices are: \"%s\"\n", + ctx->options.device_type, all_dev_names); + goto err; + } + + // create infer_request for sync execution + status = ie_exec_network_create_infer_request(ov_model->exe_network, &ov_model->infer_request); + if (status != OK) + goto err; + + // create infer_requests for async execution + if (ctx->options.nireq <= 0) { + // the default value is a rough estimation + ctx->options.nireq = av_cpu_count() / 2 + 1; + } + + ov_model->request_queue = ff_safe_queue_create(); + if (!ov_model->request_queue) { + goto err; + } + + for (int i = 0; i < ctx->options.nireq; i++) { + RequestItem *item = av_mallocz(sizeof(*item)); + if (!item) { + goto err; + } + + item->callback.completeCallBackFunc = infer_completion_callback; + item->callback.args = item; + if (ff_safe_queue_push_back(ov_model->request_queue, item) < 0) { + av_freep(&item); + goto err; + } + + status = ie_exec_network_create_infer_request(ov_model->exe_network, &item->infer_request); + if (status != OK) { + goto err; + } + + item->tasks = av_malloc_array(ctx->options.batch_size, sizeof(*item->tasks)); + if (!item->tasks) { + goto err; + } + item->task_count = 0; + } + + ov_model->task_queue = ff_queue_create(); + if (!ov_model->task_queue) { + goto err; + } + + return DNN_SUCCESS; + +err: + ff_dnn_free_model_ov(&ov_model->model); + return DNN_ERROR; +} + +static DNNReturnType execute_model_ov(RequestItem *request) +{ + IEStatusCode status; + DNNReturnType ret; + TaskItem *task = request->tasks[0]; + OVContext *ctx = &task->ov_model->ctx; + + if (task->async) { + if (request->task_count < ctx->options.batch_size) { + if (ff_safe_queue_push_front(task->ov_model->request_queue, request) < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to push back request_queue.\n"); + return DNN_ERROR; + } + return DNN_SUCCESS; + } + ret = fill_model_input_ov(task->ov_model, request); + if (ret != DNN_SUCCESS) { + return ret; + } + status = ie_infer_set_completion_callback(request->infer_request, &request->callback); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to set completion callback for inference\n"); + return DNN_ERROR; + } + status = ie_infer_request_infer_async(request->infer_request); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to start async inference\n"); + return DNN_ERROR; + } + return DNN_SUCCESS; + } else { + ret = fill_model_input_ov(task->ov_model, request); + if (ret != DNN_SUCCESS) { + return ret; + } + status = ie_infer_request_infer(request->infer_request); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to start synchronous model inference\n"); + return DNN_ERROR; + } + infer_completion_callback(request); + return task->done ? DNN_SUCCESS : DNN_ERROR; + } +} + +static DNNReturnType get_input_ov(void *model, DNNData *input, const char *input_name) +{ + OVModel *ov_model = model; + OVContext *ctx = &ov_model->ctx; + char *model_input_name = NULL; + char *all_input_names = NULL; + IEStatusCode status; + size_t model_input_count = 0; + dimensions_t dims; + precision_e precision; + int input_resizable = ctx->options.input_resizable; + + status = ie_network_get_inputs_number(ov_model->network, &model_input_count); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to get input count\n"); + return DNN_ERROR; + } + + for (size_t i = 0; i < model_input_count; i++) { + status = ie_network_get_input_name(ov_model->network, i, &model_input_name); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to get No.%d input's name\n", (int)i); + return DNN_ERROR; + } + if (strcmp(model_input_name, input_name) == 0) { + ie_network_name_free(&model_input_name); + status |= ie_network_get_input_dims(ov_model->network, input_name, &dims); + status |= ie_network_get_input_precision(ov_model->network, input_name, &precision); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to get No.%d input's dims or precision\n", (int)i); + return DNN_ERROR; + } + + input->channels = dims.dims[1]; + input->height = input_resizable ? -1 : dims.dims[2]; + input->width = input_resizable ? -1 : dims.dims[3]; + input->dt = precision_to_datatype(precision); + return DNN_SUCCESS; + } else { + //incorrect input name + APPEND_STRING(all_input_names, model_input_name) + } + + ie_network_name_free(&model_input_name); + } + + av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model, all input(s) are: \"%s\"\n", input_name, all_input_names); + return DNN_ERROR; +} + +static DNNReturnType get_output_ov(void *model, const char *input_name, int input_width, int input_height, + const char *output_name, int *output_width, int *output_height) +{ + DNNReturnType ret; + OVModel *ov_model = model; + OVContext *ctx = &ov_model->ctx; + TaskItem task; + RequestItem request; + AVFrame *in_frame = NULL; + AVFrame *out_frame = NULL; + TaskItem *ptask = &task; + IEStatusCode status; + input_shapes_t input_shapes; + + if (ctx->options.input_resizable) { + status = ie_network_get_input_shapes(ov_model->network, &input_shapes); + input_shapes.shapes->shape.dims[2] = input_height; + input_shapes.shapes->shape.dims[3] = input_width; + status |= ie_network_reshape(ov_model->network, input_shapes); + ie_network_input_shapes_free(&input_shapes); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to reshape input size for %s\n", input_name); + return DNN_ERROR; + } + } + + if (!ov_model->exe_network) { + if (init_model_ov(ov_model, input_name, output_name) != DNN_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed init OpenVINO exectuable network or inference request\n"); + return DNN_ERROR; + } + } + + in_frame = av_frame_alloc(); + if (!in_frame) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for input frame\n"); + return DNN_ERROR; + } + in_frame->width = input_width; + in_frame->height = input_height; + + out_frame = av_frame_alloc(); + if (!out_frame) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for output frame\n"); + av_frame_free(&in_frame); + return DNN_ERROR; + } + + task.done = 0; + task.do_ioproc = 0; + task.async = 0; + task.input_name = input_name; + task.in_frame = in_frame; + task.output_name = output_name; + task.out_frame = out_frame; + task.ov_model = ov_model; + + request.infer_request = ov_model->infer_request; + request.task_count = 1; + request.tasks = &ptask; + + ret = execute_model_ov(&request); + *output_width = out_frame->width; + *output_height = out_frame->height; + + av_frame_free(&out_frame); + av_frame_free(&in_frame); + return ret; +} + +DNNModel *ff_dnn_load_model_ov(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx) +{ + DNNModel *model = NULL; + OVModel *ov_model = NULL; + OVContext *ctx = NULL; + IEStatusCode status; + + model = av_mallocz(sizeof(DNNModel)); + if (!model){ + return NULL; + } + + ov_model = av_mallocz(sizeof(OVModel)); + if (!ov_model) { + av_freep(&model); + return NULL; + } + model->model = ov_model; + ov_model->model = model; + ov_model->ctx.class = &dnn_openvino_class; + ctx = &ov_model->ctx; + + //parse options + av_opt_set_defaults(ctx); + if (av_opt_set_from_string(ctx, options, NULL, "=", "&") < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to parse options \"%s\"\n", options); + goto err; + } + + status = ie_core_create("", &ov_model->core); + if (status != OK) + goto err; + + status = ie_core_read_network(ov_model->core, model_filename, NULL, &ov_model->network); + if (status != OK) { + ie_version_t ver; + ver = ie_c_api_version(); + av_log(ctx, AV_LOG_ERROR, "Failed to read the network from model file %s,\n" + "Please check if the model version matches the runtime OpenVINO %s\n", + model_filename, ver.api_version); + ie_version_free(&ver); + goto err; + } + + model->get_input = &get_input_ov; + model->get_output = &get_output_ov; + model->options = options; + model->filter_ctx = filter_ctx; + model->func_type = func_type; + + return model; + +err: + ff_dnn_free_model_ov(&model); + return NULL; +} + +DNNReturnType ff_dnn_execute_model_ov(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame) +{ + OVModel *ov_model = model->model; + OVContext *ctx = &ov_model->ctx; + TaskItem task; + RequestItem request; + TaskItem *ptask = &task; + + if (!in_frame) { + av_log(ctx, AV_LOG_ERROR, "in frame is NULL when execute model.\n"); + return DNN_ERROR; + } + + if (!out_frame && model->func_type == DFT_PROCESS_FRAME) { + av_log(ctx, AV_LOG_ERROR, "out frame is NULL when execute model.\n"); + return DNN_ERROR; + } + + if (nb_output != 1) { + // currently, the filter does not need multiple outputs, + // so we just pending the support until we really need it. + avpriv_report_missing_feature(ctx, "multiple outputs"); + return DNN_ERROR; + } + + if (ctx->options.batch_size > 1) { + avpriv_report_missing_feature(ctx, "batch mode for sync execution"); + return DNN_ERROR; + } + + if (!ov_model->exe_network) { + if (init_model_ov(ov_model, input_name, output_names[0]) != DNN_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed init OpenVINO exectuable network or inference request\n"); + return DNN_ERROR; + } + } + + task.done = 0; + task.do_ioproc = 1; + task.async = 0; + task.input_name = input_name; + task.in_frame = in_frame; + task.output_name = output_names[0]; + task.out_frame = out_frame; + task.ov_model = ov_model; + + request.infer_request = ov_model->infer_request; + request.task_count = 1; + request.tasks = &ptask; + + return execute_model_ov(&request); +} + +DNNReturnType ff_dnn_execute_model_async_ov(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame) +{ + OVModel *ov_model = model->model; + OVContext *ctx = &ov_model->ctx; + RequestItem *request; + TaskItem *task; + + if (!in_frame) { + av_log(ctx, AV_LOG_ERROR, "in frame is NULL when async execute model.\n"); + return DNN_ERROR; + } + + if (!out_frame && model->func_type == DFT_PROCESS_FRAME) { + av_log(ctx, AV_LOG_ERROR, "out frame is NULL when async execute model.\n"); + return DNN_ERROR; + } + + if (!ov_model->exe_network) { + if (init_model_ov(ov_model, input_name, output_names[0]) != DNN_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed init OpenVINO exectuable network or inference request\n"); + return DNN_ERROR; + } + } + + task = av_malloc(sizeof(*task)); + if (!task) { + av_log(ctx, AV_LOG_ERROR, "unable to alloc memory for task item.\n"); + return DNN_ERROR; + } + + task->done = 0; + task->do_ioproc = 1; + task->async = 1; + task->input_name = input_name; + task->in_frame = in_frame; + task->output_name = output_names[0]; + task->out_frame = out_frame; + task->ov_model = ov_model; + if (ff_queue_push_back(ov_model->task_queue, task) < 0) { + av_freep(&task); + av_log(ctx, AV_LOG_ERROR, "unable to push back task_queue.\n"); + return DNN_ERROR; + } + + request = ff_safe_queue_pop_front(ov_model->request_queue); + if (!request) { + av_log(ctx, AV_LOG_ERROR, "unable to get infer request.\n"); + return DNN_ERROR; + } + + request->tasks[request->task_count++] = task; + return execute_model_ov(request); +} + +DNNAsyncStatusType ff_dnn_get_async_result_ov(const DNNModel *model, AVFrame **in, AVFrame **out) +{ + OVModel *ov_model = model->model; + TaskItem *task = ff_queue_peek_front(ov_model->task_queue); + + if (!task) { + return DAST_EMPTY_QUEUE; + } + + if (!task->done) { + return DAST_NOT_READY; + } + + *in = task->in_frame; + *out = task->out_frame; + ff_queue_pop_front(ov_model->task_queue); + av_freep(&task); + + return DAST_SUCCESS; +} + +DNNReturnType ff_dnn_flush_ov(const DNNModel *model) +{ + OVModel *ov_model = model->model; + OVContext *ctx = &ov_model->ctx; + RequestItem *request; + IEStatusCode status; + DNNReturnType ret; + + request = ff_safe_queue_pop_front(ov_model->request_queue); + if (!request) { + av_log(ctx, AV_LOG_ERROR, "unable to get infer request.\n"); + return DNN_ERROR; + } + + if (request->task_count == 0) { + // no pending task need to flush + if (ff_safe_queue_push_back(ov_model->request_queue, request) < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to push back request_queue.\n"); + return DNN_ERROR; + } + return DNN_SUCCESS; + } + + ret = fill_model_input_ov(ov_model, request); + if (ret != DNN_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to fill model input.\n"); + return ret; + } + status = ie_infer_set_completion_callback(request->infer_request, &request->callback); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to set completion callback for inference\n"); + return DNN_ERROR; + } + status = ie_infer_request_infer_async(request->infer_request); + if (status != OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to start async inference\n"); + return DNN_ERROR; + } + + return DNN_SUCCESS; +} + +void ff_dnn_free_model_ov(DNNModel **model) +{ + if (*model){ + OVModel *ov_model = (*model)->model; + while (ff_safe_queue_size(ov_model->request_queue) != 0) { + RequestItem *item = ff_safe_queue_pop_front(ov_model->request_queue); + if (item && item->infer_request) { + ie_infer_request_free(&item->infer_request); + } + av_freep(&item->tasks); + av_freep(&item); + } + ff_safe_queue_destroy(ov_model->request_queue); + + while (ff_queue_size(ov_model->task_queue) != 0) { + TaskItem *item = ff_queue_pop_front(ov_model->task_queue); + av_frame_free(&item->in_frame); + av_frame_free(&item->out_frame); + av_freep(&item); + } + ff_queue_destroy(ov_model->task_queue); + + if (ov_model->infer_request) + ie_infer_request_free(&ov_model->infer_request); + if (ov_model->exe_network) + ie_exec_network_free(&ov_model->exe_network); + if (ov_model->network) + ie_network_free(&ov_model->network); + if (ov_model->core) + ie_core_free(&ov_model->core); + av_freep(&ov_model); + av_freep(model); + } +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_openvino.h ffmpeg-4.4/libavfilter/dnn/dnn_backend_openvino.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_openvino.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_openvino.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN inference functions interface for OpenVINO backend. + */ + + +#ifndef AVFILTER_DNN_DNN_BACKEND_OPENVINO_H +#define AVFILTER_DNN_DNN_BACKEND_OPENVINO_H + +#include "../dnn_interface.h" + +DNNModel *ff_dnn_load_model_ov(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx); + +DNNReturnType ff_dnn_execute_model_ov(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame); +DNNReturnType ff_dnn_execute_model_async_ov(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame); +DNNAsyncStatusType ff_dnn_get_async_result_ov(const DNNModel *model, AVFrame **in, AVFrame **out); +DNNReturnType ff_dnn_flush_ov(const DNNModel *model); + +void ff_dnn_free_model_ov(DNNModel **model); + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_tf.c ffmpeg-4.4/libavfilter/dnn/dnn_backend_tf.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_tf.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_tf.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,861 @@ +/* + * Copyright (c) 2018 Sergey Lavrushkin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN tensorflow backend implementation. + */ + +#include "dnn_backend_tf.h" +#include "dnn_backend_native.h" +#include "dnn_backend_native_layer_conv2d.h" +#include "dnn_backend_native_layer_depth2space.h" +#include "libavformat/avio.h" +#include "libavutil/avassert.h" +#include "../internal.h" +#include "dnn_backend_native_layer_pad.h" +#include "dnn_backend_native_layer_maximum.h" +#include "dnn_io_proc.h" + +#include + +typedef struct TFOptions{ + char *sess_config; +} TFOptions; + +typedef struct TFContext { + const AVClass *class; + TFOptions options; +} TFContext; + +typedef struct TFModel{ + TFContext ctx; + DNNModel *model; + TF_Graph *graph; + TF_Session *session; + TF_Status *status; +} TFModel; + +#define OFFSET(x) offsetof(TFContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM +static const AVOption dnn_tensorflow_options[] = { + { "sess_config", "config for SessionOptions", OFFSET(options.sess_config), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(dnn_tensorflow); + +static DNNReturnType execute_model_tf(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame, + int do_ioproc); + +static void free_buffer(void *data, size_t length) +{ + av_freep(&data); +} + +static TF_Buffer *read_graph(const char *model_filename) +{ + TF_Buffer *graph_buf; + unsigned char *graph_data = NULL; + AVIOContext *model_file_context; + long size, bytes_read; + + if (avio_open(&model_file_context, model_filename, AVIO_FLAG_READ) < 0){ + return NULL; + } + + size = avio_size(model_file_context); + + graph_data = av_malloc(size); + if (!graph_data){ + avio_closep(&model_file_context); + return NULL; + } + bytes_read = avio_read(model_file_context, graph_data, size); + avio_closep(&model_file_context); + if (bytes_read != size){ + av_freep(&graph_data); + return NULL; + } + + graph_buf = TF_NewBuffer(); + graph_buf->data = graph_data; + graph_buf->length = size; + graph_buf->data_deallocator = free_buffer; + + return graph_buf; +} + +static TF_Tensor *allocate_input_tensor(const DNNData *input) +{ + TF_DataType dt; + size_t size; + int64_t input_dims[] = {1, input->height, input->width, input->channels}; + switch (input->dt) { + case DNN_FLOAT: + dt = TF_FLOAT; + size = sizeof(float); + break; + case DNN_UINT8: + dt = TF_UINT8; + size = 1; + break; + default: + av_assert0(!"should not reach here"); + } + + return TF_AllocateTensor(dt, input_dims, 4, + input_dims[1] * input_dims[2] * input_dims[3] * size); +} + +static DNNReturnType get_input_tf(void *model, DNNData *input, const char *input_name) +{ + TFModel *tf_model = model; + TFContext *ctx = &tf_model->ctx; + TF_Status *status; + int64_t dims[4]; + + TF_Output tf_output; + tf_output.oper = TF_GraphOperationByName(tf_model->graph, input_name); + if (!tf_output.oper) { + av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model\n", input_name); + return DNN_ERROR; + } + + tf_output.index = 0; + input->dt = TF_OperationOutputType(tf_output); + + status = TF_NewStatus(); + TF_GraphGetTensorShape(tf_model->graph, tf_output, dims, 4, status); + if (TF_GetCode(status) != TF_OK){ + TF_DeleteStatus(status); + av_log(ctx, AV_LOG_ERROR, "Failed to get input tensor shape: number of dimension incorrect\n"); + return DNN_ERROR; + } + TF_DeleteStatus(status); + + // currently only NHWC is supported + av_assert0(dims[0] == 1); + input->height = dims[1]; + input->width = dims[2]; + input->channels = dims[3]; + + return DNN_SUCCESS; +} + +static DNNReturnType get_output_tf(void *model, const char *input_name, int input_width, int input_height, + const char *output_name, int *output_width, int *output_height) +{ + DNNReturnType ret; + TFModel *tf_model = model; + TFContext *ctx = &tf_model->ctx; + AVFrame *in_frame = av_frame_alloc(); + AVFrame *out_frame = NULL; + + if (!in_frame) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for input frame\n"); + return DNN_ERROR; + } + + out_frame = av_frame_alloc(); + if (!out_frame) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for output frame\n"); + av_frame_free(&in_frame); + return DNN_ERROR; + } + + in_frame->width = input_width; + in_frame->height = input_height; + + ret = execute_model_tf(tf_model->model, input_name, in_frame, &output_name, 1, out_frame, 0); + *output_width = out_frame->width; + *output_height = out_frame->height; + + av_frame_free(&out_frame); + av_frame_free(&in_frame); + return ret; +} + +static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename) +{ + TFContext *ctx = &tf_model->ctx; + TF_Buffer *graph_def; + TF_ImportGraphDefOptions *graph_opts; + TF_SessionOptions *sess_opts; + const TF_Operation *init_op; + uint8_t *sess_config = NULL; + int sess_config_length = 0; + + // prepare the sess config data + if (tf_model->ctx.options.sess_config != NULL) { + /* + tf_model->ctx.options.sess_config is hex to present the serialized proto + required by TF_SetConfig below, so we need to first generate the serialized + proto in a python script, the following is a script example to generate + serialized proto which specifies one GPU, we can change the script to add + more options. + + import tensorflow as tf + gpu_options = tf.GPUOptions(visible_device_list='0') + config = tf.ConfigProto(gpu_options=gpu_options) + s = config.SerializeToString() + b = ''.join("%02x" % int(ord(b)) for b in s[::-1]) + print('0x%s' % b) + + the script output looks like: 0xab...cd, and then pass 0xab...cd to sess_config. + */ + char tmp[3]; + tmp[2] = '\0'; + + if (strncmp(tf_model->ctx.options.sess_config, "0x", 2) != 0) { + av_log(ctx, AV_LOG_ERROR, "sess_config should start with '0x'\n"); + return DNN_ERROR; + } + + sess_config_length = strlen(tf_model->ctx.options.sess_config); + if (sess_config_length % 2 != 0) { + av_log(ctx, AV_LOG_ERROR, "the length of sess_config is not even (%s), " + "please re-generate the config.\n", + tf_model->ctx.options.sess_config); + return DNN_ERROR; + } + + sess_config_length -= 2; //ignore the first '0x' + sess_config_length /= 2; //get the data length in byte + + sess_config = av_malloc(sess_config_length); + if (!sess_config) { + av_log(ctx, AV_LOG_ERROR, "failed to allocate memory\n"); + return DNN_ERROR; + } + + for (int i = 0; i < sess_config_length; i++) { + int index = 2 + (sess_config_length - 1 - i) * 2; + tmp[0] = tf_model->ctx.options.sess_config[index]; + tmp[1] = tf_model->ctx.options.sess_config[index + 1]; + sess_config[i] = strtol(tmp, NULL, 16); + } + } + + graph_def = read_graph(model_filename); + if (!graph_def){ + av_log(ctx, AV_LOG_ERROR, "Failed to read model \"%s\" graph\n", model_filename); + av_freep(&sess_config); + return DNN_ERROR; + } + tf_model->graph = TF_NewGraph(); + tf_model->status = TF_NewStatus(); + graph_opts = TF_NewImportGraphDefOptions(); + TF_GraphImportGraphDef(tf_model->graph, graph_def, graph_opts, tf_model->status); + TF_DeleteImportGraphDefOptions(graph_opts); + TF_DeleteBuffer(graph_def); + if (TF_GetCode(tf_model->status) != TF_OK){ + TF_DeleteGraph(tf_model->graph); + TF_DeleteStatus(tf_model->status); + av_log(ctx, AV_LOG_ERROR, "Failed to import serialized graph to model graph\n"); + av_freep(&sess_config); + return DNN_ERROR; + } + + init_op = TF_GraphOperationByName(tf_model->graph, "init"); + sess_opts = TF_NewSessionOptions(); + + if (sess_config) { + TF_SetConfig(sess_opts, sess_config, sess_config_length,tf_model->status); + av_freep(&sess_config); + if (TF_GetCode(tf_model->status) != TF_OK) { + av_log(ctx, AV_LOG_ERROR, "Failed to set config for sess options with %s\n", + tf_model->ctx.options.sess_config); + return DNN_ERROR; + } + } + + tf_model->session = TF_NewSession(tf_model->graph, sess_opts, tf_model->status); + TF_DeleteSessionOptions(sess_opts); + if (TF_GetCode(tf_model->status) != TF_OK) + { + av_log(ctx, AV_LOG_ERROR, "Failed to create new session with model graph\n"); + return DNN_ERROR; + } + + // Run initialization operation with name "init" if it is present in graph + if (init_op){ + TF_SessionRun(tf_model->session, NULL, + NULL, NULL, 0, + NULL, NULL, 0, + &init_op, 1, NULL, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK) + { + av_log(ctx, AV_LOG_ERROR, "Failed to run session when initializing\n"); + return DNN_ERROR; + } + } + + return DNN_SUCCESS; +} + +#define NAME_BUFFER_SIZE 256 + +static DNNReturnType add_conv_layer(TFModel *tf_model, TF_Operation *transpose_op, TF_Operation **cur_op, + ConvolutionalParams* params, const int layer) +{ + TFContext *ctx = &tf_model->ctx; + TF_Operation *op; + TF_OperationDescription *op_desc; + TF_Output input; + int64_t strides[] = {1, 1, 1, 1}; + TF_Tensor *tensor; + int64_t dims[4]; + int dims_len; + char name_buffer[NAME_BUFFER_SIZE]; + int32_t size; + + size = params->input_num * params->output_num * params->kernel_size * params->kernel_size; + input.index = 0; + + snprintf(name_buffer, NAME_BUFFER_SIZE, "conv_kernel%d", layer); + op_desc = TF_NewOperation(tf_model->graph, "Const", name_buffer); + TF_SetAttrType(op_desc, "dtype", TF_FLOAT); + dims[0] = params->output_num; + dims[1] = params->kernel_size; + dims[2] = params->kernel_size; + dims[3] = params->input_num; + dims_len = 4; + tensor = TF_AllocateTensor(TF_FLOAT, dims, dims_len, size * sizeof(float)); + memcpy(TF_TensorData(tensor), params->kernel, size * sizeof(float)); + TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to set value for kernel of conv layer %d\n", layer); + return DNN_ERROR; + } + op = TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to add kernel to conv layer %d\n", layer); + return DNN_ERROR; + } + + snprintf(name_buffer, NAME_BUFFER_SIZE, "transpose%d", layer); + op_desc = TF_NewOperation(tf_model->graph, "Transpose", name_buffer); + input.oper = op; + TF_AddInput(op_desc, input); + input.oper = transpose_op; + TF_AddInput(op_desc, input); + TF_SetAttrType(op_desc, "T", TF_FLOAT); + TF_SetAttrType(op_desc, "Tperm", TF_INT32); + op = TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to add transpose to conv layer %d\n", layer); + return DNN_ERROR; + } + + snprintf(name_buffer, NAME_BUFFER_SIZE, "conv2d%d", layer); + op_desc = TF_NewOperation(tf_model->graph, "Conv2D", name_buffer); + input.oper = *cur_op; + TF_AddInput(op_desc, input); + input.oper = op; + TF_AddInput(op_desc, input); + TF_SetAttrType(op_desc, "T", TF_FLOAT); + TF_SetAttrIntList(op_desc, "strides", strides, 4); + TF_SetAttrString(op_desc, "padding", "VALID", 5); + *cur_op = TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to add conv2d to conv layer %d\n", layer); + return DNN_ERROR; + } + + snprintf(name_buffer, NAME_BUFFER_SIZE, "conv_biases%d", layer); + op_desc = TF_NewOperation(tf_model->graph, "Const", name_buffer); + TF_SetAttrType(op_desc, "dtype", TF_FLOAT); + dims[0] = params->output_num; + dims_len = 1; + tensor = TF_AllocateTensor(TF_FLOAT, dims, dims_len, params->output_num * sizeof(float)); + memcpy(TF_TensorData(tensor), params->biases, params->output_num * sizeof(float)); + TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to set value for conv_biases of conv layer %d\n", layer); + return DNN_ERROR; + } + op = TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to add conv_biases to conv layer %d\n", layer); + return DNN_ERROR; + } + + snprintf(name_buffer, NAME_BUFFER_SIZE, "bias_add%d", layer); + op_desc = TF_NewOperation(tf_model->graph, "BiasAdd", name_buffer); + input.oper = *cur_op; + TF_AddInput(op_desc, input); + input.oper = op; + TF_AddInput(op_desc, input); + TF_SetAttrType(op_desc, "T", TF_FLOAT); + *cur_op = TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to add bias_add to conv layer %d\n", layer); + return DNN_ERROR; + } + + snprintf(name_buffer, NAME_BUFFER_SIZE, "activation%d", layer); + switch (params->activation){ + case RELU: + op_desc = TF_NewOperation(tf_model->graph, "Relu", name_buffer); + break; + case TANH: + op_desc = TF_NewOperation(tf_model->graph, "Tanh", name_buffer); + break; + case SIGMOID: + op_desc = TF_NewOperation(tf_model->graph, "Sigmoid", name_buffer); + break; + default: + avpriv_report_missing_feature(ctx, "convolutional activation function %d", params->activation); + return DNN_ERROR; + } + input.oper = *cur_op; + TF_AddInput(op_desc, input); + TF_SetAttrType(op_desc, "T", TF_FLOAT); + *cur_op = TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to add activation function to conv layer %d\n", layer); + return DNN_ERROR; + } + + return DNN_SUCCESS; +} + +static DNNReturnType add_depth_to_space_layer(TFModel *tf_model, TF_Operation **cur_op, + DepthToSpaceParams *params, const int layer) +{ + TFContext *ctx = &tf_model->ctx; + TF_OperationDescription *op_desc; + TF_Output input; + char name_buffer[NAME_BUFFER_SIZE]; + + snprintf(name_buffer, NAME_BUFFER_SIZE, "depth_to_space%d", layer); + op_desc = TF_NewOperation(tf_model->graph, "DepthToSpace", name_buffer); + input.oper = *cur_op; + input.index = 0; + TF_AddInput(op_desc, input); + TF_SetAttrType(op_desc, "T", TF_FLOAT); + TF_SetAttrInt(op_desc, "block_size", params->block_size); + *cur_op = TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to add depth_to_space to layer %d\n", layer); + return DNN_ERROR; + } + + return DNN_SUCCESS; +} + +static DNNReturnType add_pad_layer(TFModel *tf_model, TF_Operation **cur_op, + LayerPadParams *params, const int layer) +{ + TFContext *ctx = &tf_model->ctx; + TF_Operation *op; + TF_Tensor *tensor; + TF_OperationDescription *op_desc; + TF_Output input; + int32_t *pads; + int64_t pads_shape[] = {4, 2}; + + char name_buffer[NAME_BUFFER_SIZE]; + snprintf(name_buffer, NAME_BUFFER_SIZE, "pad%d", layer); + + op_desc = TF_NewOperation(tf_model->graph, "Const", name_buffer); + TF_SetAttrType(op_desc, "dtype", TF_INT32); + tensor = TF_AllocateTensor(TF_INT32, pads_shape, 2, 4 * 2 * sizeof(int32_t)); + pads = (int32_t *)TF_TensorData(tensor); + pads[0] = params->paddings[0][0]; + pads[1] = params->paddings[0][1]; + pads[2] = params->paddings[1][0]; + pads[3] = params->paddings[1][1]; + pads[4] = params->paddings[2][0]; + pads[5] = params->paddings[2][1]; + pads[6] = params->paddings[3][0]; + pads[7] = params->paddings[3][1]; + TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to set value for pad of layer %d\n", layer); + return DNN_ERROR; + } + op = TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to add pad to layer %d\n", layer); + return DNN_ERROR; + } + + op_desc = TF_NewOperation(tf_model->graph, "MirrorPad", "mirror_pad"); + input.oper = *cur_op; + input.index = 0; + TF_AddInput(op_desc, input); + input.oper = op; + TF_AddInput(op_desc, input); + TF_SetAttrType(op_desc, "T", TF_FLOAT); + TF_SetAttrType(op_desc, "Tpaddings", TF_INT32); + TF_SetAttrString(op_desc, "mode", "SYMMETRIC", 9); + *cur_op = TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to add mirror_pad to layer %d\n", layer); + return DNN_ERROR; + } + + return DNN_SUCCESS; +} + +static DNNReturnType add_maximum_layer(TFModel *tf_model, TF_Operation **cur_op, + DnnLayerMaximumParams *params, const int layer) +{ + TFContext *ctx = &tf_model->ctx; + TF_Operation *op; + TF_Tensor *tensor; + TF_OperationDescription *op_desc; + TF_Output input; + float *y; + + char name_buffer[NAME_BUFFER_SIZE]; + snprintf(name_buffer, NAME_BUFFER_SIZE, "maximum/y%d", layer); + + op_desc = TF_NewOperation(tf_model->graph, "Const", name_buffer); + TF_SetAttrType(op_desc, "dtype", TF_FLOAT); + tensor = TF_AllocateTensor(TF_FLOAT, NULL, 0, TF_DataTypeSize(TF_FLOAT)); + y = (float *)TF_TensorData(tensor); + *y = params->val.y; + TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to set value for maximum/y of layer %d", layer); + return DNN_ERROR; + } + op = TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to add maximum/y to layer %d\n", layer); + return DNN_ERROR; + } + + snprintf(name_buffer, NAME_BUFFER_SIZE, "maximum%d", layer); + op_desc = TF_NewOperation(tf_model->graph, "Maximum", name_buffer); + input.oper = *cur_op; + input.index = 0; + TF_AddInput(op_desc, input); + input.oper = op; + TF_AddInput(op_desc, input); + TF_SetAttrType(op_desc, "T", TF_FLOAT); + *cur_op = TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + av_log(ctx, AV_LOG_ERROR, "Failed to add maximum to layer %d\n", layer); + return DNN_ERROR; + } + + return DNN_SUCCESS; +} + +static DNNReturnType load_native_model(TFModel *tf_model, const char *model_filename) +{ + TFContext *ctx = &tf_model->ctx; + int32_t layer; + TF_OperationDescription *op_desc; + TF_Operation *op; + TF_Operation *transpose_op; + TF_Tensor *tensor; + TF_Output input; + int32_t *transpose_perm; + int64_t transpose_perm_shape[] = {4}; + int64_t input_shape[] = {1, -1, -1, -1}; + DNNReturnType layer_add_res; + DNNModel *model = NULL; + NativeModel *native_model; + + model = ff_dnn_load_model_native(model_filename, DFT_PROCESS_FRAME, NULL, NULL); + if (!model){ + av_log(ctx, AV_LOG_ERROR, "Failed to load native model\n"); + return DNN_ERROR; + } + + native_model = model->model; + tf_model->graph = TF_NewGraph(); + tf_model->status = TF_NewStatus(); + +#define CLEANUP_ON_ERROR(tf_model) \ + { \ + TF_DeleteGraph(tf_model->graph); \ + TF_DeleteStatus(tf_model->status); \ + av_log(ctx, AV_LOG_ERROR, "Failed to set value or add operator to layer\n"); \ + return DNN_ERROR; \ + } + + op_desc = TF_NewOperation(tf_model->graph, "Placeholder", "x"); + TF_SetAttrType(op_desc, "dtype", TF_FLOAT); + TF_SetAttrShape(op_desc, "shape", input_shape, 4); + op = TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + CLEANUP_ON_ERROR(tf_model); + } + + op_desc = TF_NewOperation(tf_model->graph, "Const", "transpose_perm"); + TF_SetAttrType(op_desc, "dtype", TF_INT32); + tensor = TF_AllocateTensor(TF_INT32, transpose_perm_shape, 1, 4 * sizeof(int32_t)); + transpose_perm = (int32_t *)TF_TensorData(tensor); + transpose_perm[0] = 1; + transpose_perm[1] = 2; + transpose_perm[2] = 3; + transpose_perm[3] = 0; + TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + CLEANUP_ON_ERROR(tf_model); + } + transpose_op = TF_FinishOperation(op_desc, tf_model->status); + + for (layer = 0; layer < native_model->layers_num; ++layer){ + switch (native_model->layers[layer].type){ + case DLT_INPUT: + layer_add_res = DNN_SUCCESS; + break; + case DLT_CONV2D: + layer_add_res = add_conv_layer(tf_model, transpose_op, &op, + (ConvolutionalParams *)native_model->layers[layer].params, layer); + break; + case DLT_DEPTH_TO_SPACE: + layer_add_res = add_depth_to_space_layer(tf_model, &op, + (DepthToSpaceParams *)native_model->layers[layer].params, layer); + break; + case DLT_MIRROR_PAD: + layer_add_res = add_pad_layer(tf_model, &op, + (LayerPadParams *)native_model->layers[layer].params, layer); + break; + case DLT_MAXIMUM: + layer_add_res = add_maximum_layer(tf_model, &op, + (DnnLayerMaximumParams *)native_model->layers[layer].params, layer); + break; + default: + CLEANUP_ON_ERROR(tf_model); + } + + if (layer_add_res != DNN_SUCCESS){ + CLEANUP_ON_ERROR(tf_model); + } + } + + op_desc = TF_NewOperation(tf_model->graph, "Identity", "y"); + input.oper = op; + input.index = 0; + TF_AddInput(op_desc, input); + TF_FinishOperation(op_desc, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK){ + CLEANUP_ON_ERROR(tf_model); + } + + ff_dnn_free_model_native(&model); + + return DNN_SUCCESS; +} + +DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx) +{ + DNNModel *model = NULL; + TFModel *tf_model = NULL; + + model = av_mallocz(sizeof(DNNModel)); + if (!model){ + return NULL; + } + + tf_model = av_mallocz(sizeof(TFModel)); + if (!tf_model){ + av_freep(&model); + return NULL; + } + tf_model->ctx.class = &dnn_tensorflow_class; + tf_model->model = model; + + //parse options + av_opt_set_defaults(&tf_model->ctx); + if (av_opt_set_from_string(&tf_model->ctx, options, NULL, "=", "&") < 0) { + av_log(&tf_model->ctx, AV_LOG_ERROR, "Failed to parse options \"%s\"\n", options); + av_freep(&tf_model); + av_freep(&model); + return NULL; + } + + if (load_tf_model(tf_model, model_filename) != DNN_SUCCESS){ + if (load_native_model(tf_model, model_filename) != DNN_SUCCESS){ + av_freep(&tf_model); + av_freep(&model); + + return NULL; + } + } + + model->model = tf_model; + model->get_input = &get_input_tf; + model->get_output = &get_output_tf; + model->options = options; + model->filter_ctx = filter_ctx; + model->func_type = func_type; + + return model; +} + +static DNNReturnType execute_model_tf(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame, + int do_ioproc) +{ + TF_Output *tf_outputs; + TFModel *tf_model = model->model; + TFContext *ctx = &tf_model->ctx; + DNNData input, output; + TF_Tensor **output_tensors; + TF_Output tf_input; + TF_Tensor *input_tensor; + + if (get_input_tf(tf_model, &input, input_name) != DNN_SUCCESS) + return DNN_ERROR; + input.height = in_frame->height; + input.width = in_frame->width; + + tf_input.oper = TF_GraphOperationByName(tf_model->graph, input_name); + if (!tf_input.oper){ + av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model\n", input_name); + return DNN_ERROR; + } + tf_input.index = 0; + input_tensor = allocate_input_tensor(&input); + if (!input_tensor){ + av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for input tensor\n"); + return DNN_ERROR; + } + input.data = (float *)TF_TensorData(input_tensor); + + if (do_ioproc) { + if (tf_model->model->pre_proc != NULL) { + tf_model->model->pre_proc(in_frame, &input, tf_model->model->filter_ctx); + } else { + ff_proc_from_frame_to_dnn(in_frame, &input, tf_model->model->func_type, ctx); + } + } + + if (nb_output != 1) { + // currently, the filter does not need multiple outputs, + // so we just pending the support until we really need it. + avpriv_report_missing_feature(ctx, "multiple outputs"); + return DNN_ERROR; + } + + tf_outputs = av_malloc_array(nb_output, sizeof(*tf_outputs)); + if (tf_outputs == NULL) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for *tf_outputs\n"); \ + return DNN_ERROR; + } + + output_tensors = av_mallocz_array(nb_output, sizeof(*output_tensors)); + if (!output_tensors) { + av_freep(&tf_outputs); + av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for output tensor\n"); \ + return DNN_ERROR; + } + + for (int i = 0; i < nb_output; ++i) { + tf_outputs[i].oper = TF_GraphOperationByName(tf_model->graph, output_names[i]); + if (!tf_outputs[i].oper) { + av_freep(&tf_outputs); + av_freep(&output_tensors); + av_log(ctx, AV_LOG_ERROR, "Could not find output \"%s\" in model\n", output_names[i]); \ + return DNN_ERROR; + } + tf_outputs[i].index = 0; + } + + TF_SessionRun(tf_model->session, NULL, + &tf_input, &input_tensor, 1, + tf_outputs, output_tensors, nb_output, + NULL, 0, NULL, tf_model->status); + if (TF_GetCode(tf_model->status) != TF_OK) { + av_freep(&tf_outputs); + av_freep(&output_tensors); + av_log(ctx, AV_LOG_ERROR, "Failed to run session when executing model\n"); + return DNN_ERROR; + } + + for (uint32_t i = 0; i < nb_output; ++i) { + output.height = TF_Dim(output_tensors[i], 1); + output.width = TF_Dim(output_tensors[i], 2); + output.channels = TF_Dim(output_tensors[i], 3); + output.data = TF_TensorData(output_tensors[i]); + output.dt = TF_TensorType(output_tensors[i]); + + if (do_ioproc) { + if (tf_model->model->post_proc != NULL) { + tf_model->model->post_proc(out_frame, &output, tf_model->model->filter_ctx); + } else { + ff_proc_from_dnn_to_frame(out_frame, &output, ctx); + } + } else { + out_frame->width = output.width; + out_frame->height = output.height; + } + } + + for (uint32_t i = 0; i < nb_output; ++i) { + if (output_tensors[i]) { + TF_DeleteTensor(output_tensors[i]); + } + } + TF_DeleteTensor(input_tensor); + av_freep(&output_tensors); + av_freep(&tf_outputs); + return DNN_SUCCESS; +} + +DNNReturnType ff_dnn_execute_model_tf(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame) +{ + TFModel *tf_model = model->model; + TFContext *ctx = &tf_model->ctx; + + if (!in_frame) { + av_log(ctx, AV_LOG_ERROR, "in frame is NULL when execute model.\n"); + return DNN_ERROR; + } + + if (!out_frame) { + av_log(ctx, AV_LOG_ERROR, "out frame is NULL when execute model.\n"); + return DNN_ERROR; + } + + return execute_model_tf(model, input_name, in_frame, output_names, nb_output, out_frame, 1); +} + +void ff_dnn_free_model_tf(DNNModel **model) +{ + TFModel *tf_model; + + if (*model){ + tf_model = (*model)->model; + if (tf_model->graph){ + TF_DeleteGraph(tf_model->graph); + } + if (tf_model->session){ + TF_CloseSession(tf_model->session, tf_model->status); + TF_DeleteSession(tf_model->session, tf_model->status); + } + if (tf_model->status){ + TF_DeleteStatus(tf_model->status); + } + av_freep(&tf_model); + av_freep(model); + } +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_tf.h ffmpeg-4.4/libavfilter/dnn/dnn_backend_tf.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_backend_tf.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_backend_tf.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 Sergey Lavrushkin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN inference functions interface for TensorFlow backend. + */ + + +#ifndef AVFILTER_DNN_DNN_BACKEND_TF_H +#define AVFILTER_DNN_DNN_BACKEND_TF_H + +#include "../dnn_interface.h" + +DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx); + +DNNReturnType ff_dnn_execute_model_tf(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame); + +void ff_dnn_free_model_tf(DNNModel **model); + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_interface.c ffmpeg-4.4/libavfilter/dnn/dnn_interface.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_interface.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_interface.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018 Sergey Lavrushkin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * Implements DNN module initialization with specified backend. + */ + +#include "../dnn_interface.h" +#include "dnn_backend_native.h" +#include "dnn_backend_tf.h" +#include "dnn_backend_openvino.h" +#include "libavutil/mem.h" + +DNNModule *ff_get_dnn_module(DNNBackendType backend_type) +{ + DNNModule *dnn_module; + + dnn_module = av_mallocz(sizeof(DNNModule)); + if(!dnn_module){ + return NULL; + } + + switch(backend_type){ + case DNN_NATIVE: + dnn_module->load_model = &ff_dnn_load_model_native; + dnn_module->execute_model = &ff_dnn_execute_model_native; + dnn_module->free_model = &ff_dnn_free_model_native; + break; + case DNN_TF: + #if (CONFIG_LIBTENSORFLOW == 1) + dnn_module->load_model = &ff_dnn_load_model_tf; + dnn_module->execute_model = &ff_dnn_execute_model_tf; + dnn_module->free_model = &ff_dnn_free_model_tf; + #else + av_freep(&dnn_module); + return NULL; + #endif + break; + case DNN_OV: + #if (CONFIG_LIBOPENVINO == 1) + dnn_module->load_model = &ff_dnn_load_model_ov; + dnn_module->execute_model = &ff_dnn_execute_model_ov; + dnn_module->execute_model_async = &ff_dnn_execute_model_async_ov; + dnn_module->get_async_result = &ff_dnn_get_async_result_ov; + dnn_module->flush = &ff_dnn_flush_ov; + dnn_module->free_model = &ff_dnn_free_model_ov; + #else + av_freep(&dnn_module); + return NULL; + #endif + break; + default: + av_log(NULL, AV_LOG_ERROR, "Module backend_type is not native or tensorflow\n"); + av_freep(&dnn_module); + return NULL; + } + + return dnn_module; +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_io_proc.c ffmpeg-4.4/libavfilter/dnn/dnn_io_proc.c --- ffmpeg-4.2.2/libavfilter/dnn/dnn_io_proc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_io_proc.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "dnn_io_proc.h" +#include "libavutil/imgutils.h" +#include "libswscale/swscale.h" +#include "libavutil/avassert.h" + +DNNReturnType ff_proc_from_dnn_to_frame(AVFrame *frame, DNNData *output, void *log_ctx) +{ + struct SwsContext *sws_ctx; + int bytewidth = av_image_get_linesize(frame->format, frame->width, 0); + if (output->dt != DNN_FLOAT) { + avpriv_report_missing_feature(log_ctx, "data type rather than DNN_FLOAT"); + return DNN_ERROR; + } + + switch (frame->format) { + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_BGR24: + sws_ctx = sws_getContext(frame->width * 3, + frame->height, + AV_PIX_FMT_GRAYF32, + frame->width * 3, + frame->height, + AV_PIX_FMT_GRAY8, + 0, NULL, NULL, NULL); + if (!sws_ctx) { + av_log(log_ctx, AV_LOG_ERROR, "Impossible to create scale context for the conversion " + "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n", + av_get_pix_fmt_name(AV_PIX_FMT_GRAYF32), frame->width * 3, frame->height, + av_get_pix_fmt_name(AV_PIX_FMT_GRAY8), frame->width * 3, frame->height); + return DNN_ERROR; + } + sws_scale(sws_ctx, (const uint8_t *[4]){(const uint8_t *)output->data, 0, 0, 0}, + (const int[4]){frame->width * 3 * sizeof(float), 0, 0, 0}, 0, frame->height, + (uint8_t * const*)frame->data, frame->linesize); + sws_freeContext(sws_ctx); + return DNN_SUCCESS; + case AV_PIX_FMT_GRAYF32: + av_image_copy_plane(frame->data[0], frame->linesize[0], + output->data, bytewidth, + bytewidth, frame->height); + return DNN_SUCCESS; + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUV410P: + case AV_PIX_FMT_YUV411P: + case AV_PIX_FMT_GRAY8: + case AV_PIX_FMT_NV12: + sws_ctx = sws_getContext(frame->width, + frame->height, + AV_PIX_FMT_GRAYF32, + frame->width, + frame->height, + AV_PIX_FMT_GRAY8, + 0, NULL, NULL, NULL); + if (!sws_ctx) { + av_log(log_ctx, AV_LOG_ERROR, "Impossible to create scale context for the conversion " + "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n", + av_get_pix_fmt_name(AV_PIX_FMT_GRAYF32), frame->width, frame->height, + av_get_pix_fmt_name(AV_PIX_FMT_GRAY8), frame->width, frame->height); + return DNN_ERROR; + } + sws_scale(sws_ctx, (const uint8_t *[4]){(const uint8_t *)output->data, 0, 0, 0}, + (const int[4]){frame->width * sizeof(float), 0, 0, 0}, 0, frame->height, + (uint8_t * const*)frame->data, frame->linesize); + sws_freeContext(sws_ctx); + return DNN_SUCCESS; + default: + avpriv_report_missing_feature(log_ctx, "%s", av_get_pix_fmt_name(frame->format)); + return DNN_ERROR; + } + + return DNN_SUCCESS; +} + +static DNNReturnType proc_from_frame_to_dnn_frameprocessing(AVFrame *frame, DNNData *input, void *log_ctx) +{ + struct SwsContext *sws_ctx; + int bytewidth = av_image_get_linesize(frame->format, frame->width, 0); + if (input->dt != DNN_FLOAT) { + avpriv_report_missing_feature(log_ctx, "data type rather than DNN_FLOAT"); + return DNN_ERROR; + } + + switch (frame->format) { + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_BGR24: + sws_ctx = sws_getContext(frame->width * 3, + frame->height, + AV_PIX_FMT_GRAY8, + frame->width * 3, + frame->height, + AV_PIX_FMT_GRAYF32, + 0, NULL, NULL, NULL); + if (!sws_ctx) { + av_log(log_ctx, AV_LOG_ERROR, "Impossible to create scale context for the conversion " + "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n", + av_get_pix_fmt_name(AV_PIX_FMT_GRAY8), frame->width * 3, frame->height, + av_get_pix_fmt_name(AV_PIX_FMT_GRAYF32),frame->width * 3, frame->height); + return DNN_ERROR; + } + sws_scale(sws_ctx, (const uint8_t **)frame->data, + frame->linesize, 0, frame->height, + (uint8_t * const*)(&input->data), + (const int [4]){frame->width * 3 * sizeof(float), 0, 0, 0}); + sws_freeContext(sws_ctx); + break; + case AV_PIX_FMT_GRAYF32: + av_image_copy_plane(input->data, bytewidth, + frame->data[0], frame->linesize[0], + bytewidth, frame->height); + break; + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUV410P: + case AV_PIX_FMT_YUV411P: + case AV_PIX_FMT_GRAY8: + case AV_PIX_FMT_NV12: + sws_ctx = sws_getContext(frame->width, + frame->height, + AV_PIX_FMT_GRAY8, + frame->width, + frame->height, + AV_PIX_FMT_GRAYF32, + 0, NULL, NULL, NULL); + if (!sws_ctx) { + av_log(log_ctx, AV_LOG_ERROR, "Impossible to create scale context for the conversion " + "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n", + av_get_pix_fmt_name(AV_PIX_FMT_GRAY8), frame->width, frame->height, + av_get_pix_fmt_name(AV_PIX_FMT_GRAYF32),frame->width, frame->height); + return DNN_ERROR; + } + sws_scale(sws_ctx, (const uint8_t **)frame->data, + frame->linesize, 0, frame->height, + (uint8_t * const*)(&input->data), + (const int [4]){frame->width * sizeof(float), 0, 0, 0}); + sws_freeContext(sws_ctx); + break; + default: + avpriv_report_missing_feature(log_ctx, "%s", av_get_pix_fmt_name(frame->format)); + return DNN_ERROR; + } + + return DNN_SUCCESS; +} + +static enum AVPixelFormat get_pixel_format(DNNData *data) +{ + if (data->dt == DNN_UINT8 && data->order == DCO_BGR) { + return AV_PIX_FMT_BGR24; + } + + av_assert0(!"not supported yet.\n"); + return AV_PIX_FMT_BGR24; +} + +static DNNReturnType proc_from_frame_to_dnn_analytics(AVFrame *frame, DNNData *input, void *log_ctx) +{ + struct SwsContext *sws_ctx; + int linesizes[4]; + enum AVPixelFormat fmt = get_pixel_format(input); + sws_ctx = sws_getContext(frame->width, frame->height, frame->format, + input->width, input->height, fmt, + SWS_FAST_BILINEAR, NULL, NULL, NULL); + if (!sws_ctx) { + av_log(log_ctx, AV_LOG_ERROR, "Impossible to create scale context for the conversion " + "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n", + av_get_pix_fmt_name(frame->format), frame->width, frame->height, + av_get_pix_fmt_name(fmt), input->width, input->height); + return DNN_ERROR; + } + + if (av_image_fill_linesizes(linesizes, fmt, input->width) < 0) { + av_log(log_ctx, AV_LOG_ERROR, "unable to get linesizes with av_image_fill_linesizes"); + sws_freeContext(sws_ctx); + return DNN_ERROR; + } + + sws_scale(sws_ctx, (const uint8_t *const *)frame->data, frame->linesize, 0, frame->height, + (uint8_t *const *)(&input->data), linesizes); + + sws_freeContext(sws_ctx); + return DNN_SUCCESS; +} + +DNNReturnType ff_proc_from_frame_to_dnn(AVFrame *frame, DNNData *input, DNNFunctionType func_type, void *log_ctx) +{ + switch (func_type) + { + case DFT_PROCESS_FRAME: + return proc_from_frame_to_dnn_frameprocessing(frame, input, log_ctx); + case DFT_ANALYTICS_DETECT: + return proc_from_frame_to_dnn_analytics(frame, input, log_ctx); + default: + avpriv_report_missing_feature(log_ctx, "model function type %d", func_type); + return DNN_ERROR; + } +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/dnn_io_proc.h ffmpeg-4.4/libavfilter/dnn/dnn_io_proc.h --- ffmpeg-4.2.2/libavfilter/dnn/dnn_io_proc.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/dnn_io_proc.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DNN input&output process between AVFrame and DNNData. + */ + + +#ifndef AVFILTER_DNN_DNN_IO_PROC_H +#define AVFILTER_DNN_DNN_IO_PROC_H + +#include "../dnn_interface.h" +#include "libavutil/frame.h" + +DNNReturnType ff_proc_from_frame_to_dnn(AVFrame *frame, DNNData *input, DNNFunctionType func_type, void *log_ctx); +DNNReturnType ff_proc_from_dnn_to_frame(AVFrame *frame, DNNData *output, void *log_ctx); + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/Makefile ffmpeg-4.4/libavfilter/dnn/Makefile --- ffmpeg-4.2.2/libavfilter/dnn/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/Makefile 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,19 @@ +OBJS-$(CONFIG_DNN) += dnn/dnn_interface.o +OBJS-$(CONFIG_DNN) += dnn/dnn_io_proc.o +OBJS-$(CONFIG_DNN) += dnn/queue.o +OBJS-$(CONFIG_DNN) += dnn/safe_queue.o +OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native.o +OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layers.o +OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_avgpool.o +OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_dense.o +OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_pad.o +OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_conv2d.o +OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_depth2space.o +OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_maximum.o +OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_mathbinary.o +OBJS-$(CONFIG_DNN) += dnn/dnn_backend_native_layer_mathunary.o + +DNN-OBJS-$(CONFIG_LIBTENSORFLOW) += dnn/dnn_backend_tf.o +DNN-OBJS-$(CONFIG_LIBOPENVINO) += dnn/dnn_backend_openvino.o + +OBJS-$(CONFIG_DNN) += $(DNN-OBJS-yes) diff -Nru ffmpeg-4.2.2/libavfilter/dnn/queue.c ffmpeg-4.4/libavfilter/dnn/queue.c --- ffmpeg-4.2.2/libavfilter/dnn/queue.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/queue.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "queue.h" +#include "libavutil/mem.h" +#include "libavutil/avassert.h" + +typedef struct QueueEntry QueueEntry; + +struct QueueEntry { + void *value; + QueueEntry *prev; + QueueEntry *next; +}; + +struct Queue { + QueueEntry *head; + QueueEntry *tail; + size_t length; +}; + +static inline QueueEntry *create_entry(void *val) +{ + QueueEntry *entry = av_malloc(sizeof(*entry)); + if (entry) + entry->value = val; + return entry; +} + +Queue* ff_queue_create(void) +{ + Queue *q = av_malloc(sizeof(*q)); + if (!q) + return NULL; + + q->head = create_entry(q); + q->tail = create_entry(q); + + if (!q->head || !q->tail) { + av_freep(&q->head); + av_freep(&q->tail); + av_freep(&q); + return NULL; + } + + q->head->next = q->tail; + q->tail->prev = q->head; + q->head->prev = NULL; + q->tail->next = NULL; + q->length = 0; + + return q; +} + +void ff_queue_destroy(Queue *q) +{ + QueueEntry *entry; + if (!q) + return; + + entry = q->head; + while (entry != NULL) { + QueueEntry *temp = entry; + entry = entry->next; + av_freep(&temp); + } + + av_freep(&q); +} + +size_t ff_queue_size(Queue *q) +{ + return q ? q->length : 0; +} + +void *ff_queue_peek_front(Queue *q) +{ + if (!q || q->length == 0) + return NULL; + + return q->head->next->value; +} + +void *ff_queue_peek_back(Queue *q) +{ + if (!q || q->length == 0) + return NULL; + + return q->tail->prev->value; +} + +int ff_queue_push_front(Queue *q, void *v) +{ + QueueEntry *new_entry; + QueueEntry *original_next; + if (!q) + return 0; + + new_entry = create_entry(v); + if (!new_entry) + return -1; + original_next = q->head->next; + + q->head->next = new_entry; + original_next->prev = new_entry; + new_entry->prev = q->head; + new_entry->next = original_next; + q->length++; + + return q->length; +} + +int ff_queue_push_back(Queue *q, void *v) +{ + QueueEntry *new_entry; + QueueEntry *original_prev; + if (!q) + return 0; + + new_entry = create_entry(v); + if (!new_entry) + return -1; + original_prev = q->tail->prev; + + q->tail->prev = new_entry; + original_prev->next = new_entry; + new_entry->next = q->tail; + new_entry->prev = original_prev; + q->length++; + + return q->length; +} + +void *ff_queue_pop_front(Queue *q) +{ + QueueEntry *front; + QueueEntry *new_head_next; + void *ret; + + if (!q || q->length == 0) + return NULL; + + front = q->head->next; + new_head_next = front->next; + ret = front->value; + + q->head->next = new_head_next; + new_head_next->prev = q->head; + + av_freep(&front); + q->length--; + return ret; +} + +void *ff_queue_pop_back(Queue *q) +{ + QueueEntry *back; + QueueEntry *new_tail_prev; + void *ret; + + if (!q || q->length == 0) + return NULL; + + back = q->tail->prev; + new_tail_prev = back->prev; + ret = back->value; + + q->tail->prev = new_tail_prev; + new_tail_prev->next = q->tail; + + av_freep(&back); + q->length--; + return ret; +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/queue.h ffmpeg-4.4/libavfilter/dnn/queue.h --- ffmpeg-4.2.2/libavfilter/dnn/queue.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/queue.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_DNN_QUEUE_H +#define AVFILTER_DNN_QUEUE_H + +typedef struct Queue Queue; + +Queue *ff_queue_create(void); +void ff_queue_destroy(Queue *q); + +size_t ff_queue_size(Queue *q); + +void *ff_queue_peek_front(Queue *q); +void *ff_queue_peek_back(Queue *q); + +int ff_queue_push_front(Queue *q, void *v); +int ff_queue_push_back(Queue *q, void *v); + +void *ff_queue_pop_front(Queue *q); +void *ff_queue_pop_back(Queue *q); + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn/safe_queue.c ffmpeg-4.4/libavfilter/dnn/safe_queue.c --- ffmpeg-4.2.2/libavfilter/dnn/safe_queue.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/safe_queue.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "queue.h" +#include "safe_queue.h" +#include "libavutil/mem.h" +#include "libavutil/avassert.h" +#include "libavutil/thread.h" + +#if HAVE_PTHREAD_CANCEL +#define DNNCond pthread_cond_t +#define dnn_cond_init pthread_cond_init +#define dnn_cond_destroy pthread_cond_destroy +#define dnn_cond_signal pthread_cond_signal +#define dnn_cond_wait pthread_cond_wait +#else +#define DNNCond char +static inline int dnn_cond_init(DNNCond *cond, const void *attr) { return 0; } +static inline int dnn_cond_destroy(DNNCond *cond) { return 0; } +static inline int dnn_cond_signal(DNNCond *cond) { return 0; } +static inline int dnn_cond_wait(DNNCond *cond, AVMutex *mutex) +{ + av_assert0(!"should not reach here"); + return 0; +} +#endif + +struct SafeQueue { + Queue *q; + AVMutex mutex; + DNNCond cond; +}; + +SafeQueue *ff_safe_queue_create(void) +{ + SafeQueue *sq = av_malloc(sizeof(*sq)); + if (!sq) + return NULL; + + sq->q = ff_queue_create(); + if (!sq->q) { + av_freep(&sq); + return NULL; + } + + ff_mutex_init(&sq->mutex, NULL); + dnn_cond_init(&sq->cond, NULL); + return sq; +} + +void ff_safe_queue_destroy(SafeQueue *sq) +{ + if (!sq) + return; + + ff_queue_destroy(sq->q); + ff_mutex_destroy(&sq->mutex); + dnn_cond_destroy(&sq->cond); + av_freep(&sq); +} + +size_t ff_safe_queue_size(SafeQueue *sq) +{ + return sq ? ff_queue_size(sq->q) : 0; +} + +int ff_safe_queue_push_front(SafeQueue *sq, void *v) +{ + int ret; + ff_mutex_lock(&sq->mutex); + ret = ff_queue_push_front(sq->q, v); + dnn_cond_signal(&sq->cond); + ff_mutex_unlock(&sq->mutex); + return ret; +} + +int ff_safe_queue_push_back(SafeQueue *sq, void *v) +{ + int ret; + ff_mutex_lock(&sq->mutex); + ret = ff_queue_push_back(sq->q, v); + dnn_cond_signal(&sq->cond); + ff_mutex_unlock(&sq->mutex); + return ret; +} + +void *ff_safe_queue_pop_front(SafeQueue *sq) +{ + void *value; + ff_mutex_lock(&sq->mutex); + while (ff_queue_size(sq->q) == 0) { + dnn_cond_wait(&sq->cond, &sq->mutex); + } + value = ff_queue_pop_front(sq->q); + dnn_cond_signal(&sq->cond); + ff_mutex_unlock(&sq->mutex); + return value; +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn/safe_queue.h ffmpeg-4.4/libavfilter/dnn/safe_queue.h --- ffmpeg-4.2.2/libavfilter/dnn/safe_queue.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn/safe_queue.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_DNN_SAFE_QUEUE_H +#define AVFILTER_DNN_SAFE_QUEUE_H + +typedef struct SafeQueue SafeQueue; + +SafeQueue *ff_safe_queue_create(void); +void ff_safe_queue_destroy(SafeQueue *sq); + +size_t ff_safe_queue_size(SafeQueue *sq); + +int ff_safe_queue_push_front(SafeQueue *sq, void *v); +int ff_safe_queue_push_back(SafeQueue *sq, void *v); + +void *ff_safe_queue_pop_front(SafeQueue *sq); + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn_backend_native.c ffmpeg-4.4/libavfilter/dnn_backend_native.c --- ffmpeg-4.2.2/libavfilter/dnn_backend_native.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn_backend_native.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,389 +0,0 @@ -/* - * Copyright (c) 2018 Sergey Lavrushkin - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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 - * DNN native backend implementation. - */ - -#include "dnn_backend_native.h" -#include "libavutil/avassert.h" - -static DNNReturnType set_input_output_native(void *model, DNNInputData *input, const char *input_name, const char **output_names, uint32_t nb_output) -{ - ConvolutionalNetwork *network = (ConvolutionalNetwork *)model; - InputParams *input_params; - ConvolutionalParams *conv_params; - DepthToSpaceParams *depth_to_space_params; - int cur_width, cur_height, cur_channels; - int32_t layer; - - if (network->layers_num <= 0 || network->layers[0].type != INPUT){ - return DNN_ERROR; - } - else{ - input_params = (InputParams *)network->layers[0].params; - input_params->width = cur_width = input->width; - input_params->height = cur_height = input->height; - input_params->channels = cur_channels = input->channels; - if (input->data){ - av_freep(&input->data); - } - av_assert0(input->dt == DNN_FLOAT); - network->layers[0].output = input->data = av_malloc(cur_height * cur_width * cur_channels * sizeof(float)); - if (!network->layers[0].output){ - return DNN_ERROR; - } - } - - for (layer = 1; layer < network->layers_num; ++layer){ - switch (network->layers[layer].type){ - case CONV: - conv_params = (ConvolutionalParams *)network->layers[layer].params; - if (conv_params->input_num != cur_channels){ - return DNN_ERROR; - } - cur_channels = conv_params->output_num; - - if (conv_params->padding_method == VALID) { - int pad_size = (conv_params->kernel_size - 1) * conv_params->dilation; - cur_height -= pad_size; - cur_width -= pad_size; - } - break; - case DEPTH_TO_SPACE: - depth_to_space_params = (DepthToSpaceParams *)network->layers[layer].params; - if (cur_channels % (depth_to_space_params->block_size * depth_to_space_params->block_size) != 0){ - return DNN_ERROR; - } - cur_channels = cur_channels / (depth_to_space_params->block_size * depth_to_space_params->block_size); - cur_height *= depth_to_space_params->block_size; - cur_width *= depth_to_space_params->block_size; - break; - default: - return DNN_ERROR; - } - if (network->layers[layer].output){ - av_freep(&network->layers[layer].output); - } - - if (cur_height <= 0 || cur_width <= 0) - return DNN_ERROR; - - network->layers[layer].output = av_malloc(cur_height * cur_width * cur_channels * sizeof(float)); - if (!network->layers[layer].output){ - return DNN_ERROR; - } - } - - return DNN_SUCCESS; -} - -// Loads model and its parameters that are stored in a binary file with following structure: -// layers_num,layer_type,layer_parameterss,layer_type,layer_parameters... -// For CONV layer: activation_function, input_num, output_num, kernel_size, kernel, biases -// For DEPTH_TO_SPACE layer: block_size -DNNModel *ff_dnn_load_model_native(const char *model_filename) -{ - DNNModel *model = NULL; - ConvolutionalNetwork *network = NULL; - AVIOContext *model_file_context; - int file_size, dnn_size, kernel_size, i; - int32_t layer; - DNNLayerType layer_type; - ConvolutionalParams *conv_params; - DepthToSpaceParams *depth_to_space_params; - - model = av_malloc(sizeof(DNNModel)); - if (!model){ - return NULL; - } - - if (avio_open(&model_file_context, model_filename, AVIO_FLAG_READ) < 0){ - av_freep(&model); - return NULL; - } - file_size = avio_size(model_file_context); - - network = av_malloc(sizeof(ConvolutionalNetwork)); - if (!network){ - avio_closep(&model_file_context); - av_freep(&model); - return NULL; - } - model->model = (void *)network; - - network->layers_num = 1 + (int32_t)avio_rl32(model_file_context); - dnn_size = 4; - - network->layers = av_malloc(network->layers_num * sizeof(Layer)); - if (!network->layers){ - av_freep(&network); - avio_closep(&model_file_context); - av_freep(&model); - return NULL; - } - - for (layer = 0; layer < network->layers_num; ++layer){ - network->layers[layer].output = NULL; - network->layers[layer].params = NULL; - } - network->layers[0].type = INPUT; - network->layers[0].params = av_malloc(sizeof(InputParams)); - if (!network->layers[0].params){ - avio_closep(&model_file_context); - ff_dnn_free_model_native(&model); - return NULL; - } - - for (layer = 1; layer < network->layers_num; ++layer){ - layer_type = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - switch (layer_type){ - case CONV: - conv_params = av_malloc(sizeof(ConvolutionalParams)); - if (!conv_params){ - avio_closep(&model_file_context); - ff_dnn_free_model_native(&model); - return NULL; - } - conv_params->dilation = (int32_t)avio_rl32(model_file_context); - conv_params->padding_method = (int32_t)avio_rl32(model_file_context); - conv_params->activation = (int32_t)avio_rl32(model_file_context); - conv_params->input_num = (int32_t)avio_rl32(model_file_context); - conv_params->output_num = (int32_t)avio_rl32(model_file_context); - conv_params->kernel_size = (int32_t)avio_rl32(model_file_context); - kernel_size = conv_params->input_num * conv_params->output_num * - conv_params->kernel_size * conv_params->kernel_size; - dnn_size += 24 + (kernel_size + conv_params->output_num << 2); - if (dnn_size > file_size || conv_params->input_num <= 0 || - conv_params->output_num <= 0 || conv_params->kernel_size <= 0){ - avio_closep(&model_file_context); - ff_dnn_free_model_native(&model); - return NULL; - } - conv_params->kernel = av_malloc(kernel_size * sizeof(float)); - conv_params->biases = av_malloc(conv_params->output_num * sizeof(float)); - if (!conv_params->kernel || !conv_params->biases){ - avio_closep(&model_file_context); - ff_dnn_free_model_native(&model); - return NULL; - } - for (i = 0; i < kernel_size; ++i){ - conv_params->kernel[i] = av_int2float(avio_rl32(model_file_context)); - } - for (i = 0; i < conv_params->output_num; ++i){ - conv_params->biases[i] = av_int2float(avio_rl32(model_file_context)); - } - network->layers[layer].type = CONV; - network->layers[layer].params = conv_params; - break; - case DEPTH_TO_SPACE: - depth_to_space_params = av_malloc(sizeof(DepthToSpaceParams)); - if (!depth_to_space_params){ - avio_closep(&model_file_context); - ff_dnn_free_model_native(&model); - return NULL; - } - depth_to_space_params->block_size = (int32_t)avio_rl32(model_file_context); - dnn_size += 4; - network->layers[layer].type = DEPTH_TO_SPACE; - network->layers[layer].params = depth_to_space_params; - break; - default: - avio_closep(&model_file_context); - ff_dnn_free_model_native(&model); - return NULL; - } - } - - avio_closep(&model_file_context); - - if (dnn_size != file_size){ - ff_dnn_free_model_native(&model); - return NULL; - } - - model->set_input_output = &set_input_output_native; - - return model; -} - -#define CLAMP_TO_EDGE(x, w) ((x) < 0 ? 0 : ((x) >= (w) ? (w - 1) : (x))) - -static void convolve(const float *input, float *output, const ConvolutionalParams *conv_params, int width, int height) -{ - int radius = conv_params->kernel_size >> 1; - int src_linesize = width * conv_params->input_num; - int filter_linesize = conv_params->kernel_size * conv_params->input_num; - int filter_size = conv_params->kernel_size * filter_linesize; - int pad_size = (conv_params->padding_method == VALID) ? (conv_params->kernel_size - 1) / 2 * conv_params->dilation : 0; - - for (int y = pad_size; y < height - pad_size; ++y) { - for (int x = pad_size; x < width - pad_size; ++x) { - for (int n_filter = 0; n_filter < conv_params->output_num; ++n_filter) { - output[n_filter] = conv_params->biases[n_filter]; - - for (int ch = 0; ch < conv_params->input_num; ++ch) { - for (int kernel_y = 0; kernel_y < conv_params->kernel_size; ++kernel_y) { - for (int kernel_x = 0; kernel_x < conv_params->kernel_size; ++kernel_x) { - float input_pel; - if (conv_params->padding_method == SAME_CLAMP_TO_EDGE) { - int y_pos = CLAMP_TO_EDGE(y + (kernel_y - radius) * conv_params->dilation, height); - int x_pos = CLAMP_TO_EDGE(x + (kernel_x - radius) * conv_params->dilation, width); - input_pel = input[y_pos * src_linesize + x_pos * conv_params->input_num + ch]; - } else { - int y_pos = y + (kernel_y - radius) * conv_params->dilation; - int x_pos = x + (kernel_x - radius) * conv_params->dilation; - input_pel = (x_pos < 0 || x_pos >= width || y_pos < 0 || y_pos >= height) ? 0.0 : - input[y_pos * src_linesize + x_pos * conv_params->input_num + ch]; - } - - - output[n_filter] += input_pel * conv_params->kernel[n_filter * filter_size + kernel_y * filter_linesize + - kernel_x * conv_params->input_num + ch]; - } - } - } - switch (conv_params->activation){ - case RELU: - output[n_filter] = FFMAX(output[n_filter], 0.0); - break; - case TANH: - output[n_filter] = 2.0f / (1.0f + exp(-2.0f * output[n_filter])) - 1.0f; - break; - case SIGMOID: - output[n_filter] = 1.0f / (1.0f + exp(-output[n_filter])); - break; - case NONE: - break; - case LEAKY_RELU: - output[n_filter] = FFMAX(output[n_filter], 0.0) + 0.2 * FFMIN(output[n_filter], 0.0); - } - } - output += conv_params->output_num; - } - } -} - -static void depth_to_space(const float *input, float *output, int block_size, int width, int height, int channels) -{ - int y, x, by, bx, ch; - int new_channels = channels / (block_size * block_size); - int output_linesize = width * channels; - int by_linesize = output_linesize / block_size; - int x_linesize = new_channels * block_size; - - for (y = 0; y < height; ++y){ - for (x = 0; x < width; ++x){ - for (by = 0; by < block_size; ++by){ - for (bx = 0; bx < block_size; ++bx){ - for (ch = 0; ch < new_channels; ++ch){ - output[by * by_linesize + x * x_linesize + bx * new_channels + ch] = input[ch]; - } - input += new_channels; - } - } - } - output += output_linesize; - } -} - -DNNReturnType ff_dnn_execute_model_native(const DNNModel *model, DNNData *outputs, uint32_t nb_output) -{ - ConvolutionalNetwork *network = (ConvolutionalNetwork *)model->model; - int cur_width, cur_height, cur_channels; - int32_t layer; - InputParams *input_params; - ConvolutionalParams *conv_params; - DepthToSpaceParams *depth_to_space_params; - - if (network->layers_num <= 0 || network->layers[0].type != INPUT || !network->layers[0].output){ - return DNN_ERROR; - } - else{ - input_params = (InputParams *)network->layers[0].params; - cur_width = input_params->width; - cur_height = input_params->height; - cur_channels = input_params->channels; - } - - for (layer = 1; layer < network->layers_num; ++layer){ - if (!network->layers[layer].output){ - return DNN_ERROR; - } - switch (network->layers[layer].type){ - case CONV: - conv_params = (ConvolutionalParams *)network->layers[layer].params; - convolve(network->layers[layer - 1].output, network->layers[layer].output, conv_params, cur_width, cur_height); - cur_channels = conv_params->output_num; - if (conv_params->padding_method == VALID) { - int pad_size = (conv_params->kernel_size - 1) * conv_params->dilation; - cur_height -= pad_size; - cur_width -= pad_size; - } - break; - case DEPTH_TO_SPACE: - depth_to_space_params = (DepthToSpaceParams *)network->layers[layer].params; - depth_to_space(network->layers[layer - 1].output, network->layers[layer].output, - depth_to_space_params->block_size, cur_width, cur_height, cur_channels); - cur_height *= depth_to_space_params->block_size; - cur_width *= depth_to_space_params->block_size; - cur_channels /= depth_to_space_params->block_size * depth_to_space_params->block_size; - break; - case INPUT: - return DNN_ERROR; - } - } - - // native mode does not support multiple outputs yet - if (nb_output > 1) - return DNN_ERROR; - outputs[0].data = network->layers[network->layers_num - 1].output; - outputs[0].height = cur_height; - outputs[0].width = cur_width; - outputs[0].channels = cur_channels; - - return DNN_SUCCESS; -} - -void ff_dnn_free_model_native(DNNModel **model) -{ - ConvolutionalNetwork *network; - ConvolutionalParams *conv_params; - int32_t layer; - - if (*model) - { - network = (ConvolutionalNetwork *)(*model)->model; - for (layer = 0; layer < network->layers_num; ++layer){ - av_freep(&network->layers[layer].output); - if (network->layers[layer].type == CONV){ - conv_params = (ConvolutionalParams *)network->layers[layer].params; - av_freep(&conv_params->kernel); - av_freep(&conv_params->biases); - } - av_freep(&network->layers[layer].params); - } - av_freep(&network->layers); - av_freep(&network); - av_freep(model); - } -} diff -Nru ffmpeg-4.2.2/libavfilter/dnn_backend_native.h ffmpeg-4.4/libavfilter/dnn_backend_native.h --- ffmpeg-4.2.2/libavfilter/dnn_backend_native.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn_backend_native.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2018 Sergey Lavrushkin - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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 - * DNN inference functions interface for native backend. - */ - - -#ifndef AVFILTER_DNN_BACKEND_NATIVE_H -#define AVFILTER_DNN_BACKEND_NATIVE_H - -#include "dnn_interface.h" -#include "libavformat/avio.h" - -typedef enum {INPUT, CONV, DEPTH_TO_SPACE} DNNLayerType; - -typedef enum {RELU, TANH, SIGMOID, NONE, LEAKY_RELU} DNNActivationFunc; - -typedef enum {VALID, SAME, SAME_CLAMP_TO_EDGE} DNNConvPaddingParam; - -typedef struct Layer{ - DNNLayerType type; - float *output; - void *params; -} Layer; - -typedef struct ConvolutionalParams{ - int32_t input_num, output_num, kernel_size; - DNNActivationFunc activation; - DNNConvPaddingParam padding_method; - int32_t dilation; - float *kernel; - float *biases; -} ConvolutionalParams; - -typedef struct InputParams{ - int height, width, channels; -} InputParams; - -typedef struct DepthToSpaceParams{ - int block_size; -} DepthToSpaceParams; - -// Represents simple feed-forward convolutional network. -typedef struct ConvolutionalNetwork{ - Layer *layers; - int32_t layers_num; -} ConvolutionalNetwork; - -DNNModel *ff_dnn_load_model_native(const char *model_filename); - -DNNReturnType ff_dnn_execute_model_native(const DNNModel *model, DNNData *outputs, uint32_t nb_output); - -void ff_dnn_free_model_native(DNNModel **model); - -#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn_backend_tf.c ffmpeg-4.4/libavfilter/dnn_backend_tf.c --- ffmpeg-4.2.2/libavfilter/dnn_backend_tf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn_backend_tf.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,603 +0,0 @@ -/* - * Copyright (c) 2018 Sergey Lavrushkin - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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 - * DNN tensorflow backend implementation. - */ - -#include "dnn_backend_tf.h" -#include "dnn_backend_native.h" -#include "libavformat/avio.h" -#include "libavutil/avassert.h" - -#include - -typedef struct TFModel{ - TF_Graph *graph; - TF_Session *session; - TF_Status *status; - TF_Output input; - TF_Tensor *input_tensor; - TF_Output *outputs; - TF_Tensor **output_tensors; - uint32_t nb_output; -} TFModel; - -static void free_buffer(void *data, size_t length) -{ - av_freep(&data); -} - -static TF_Buffer *read_graph(const char *model_filename) -{ - TF_Buffer *graph_buf; - unsigned char *graph_data = NULL; - AVIOContext *model_file_context; - long size, bytes_read; - - if (avio_open(&model_file_context, model_filename, AVIO_FLAG_READ) < 0){ - return NULL; - } - - size = avio_size(model_file_context); - - graph_data = av_malloc(size); - if (!graph_data){ - avio_closep(&model_file_context); - return NULL; - } - bytes_read = avio_read(model_file_context, graph_data, size); - avio_closep(&model_file_context); - if (bytes_read != size){ - av_freep(&graph_data); - return NULL; - } - - graph_buf = TF_NewBuffer(); - graph_buf->data = (void *)graph_data; - graph_buf->length = size; - graph_buf->data_deallocator = free_buffer; - - return graph_buf; -} - -static TF_Tensor *allocate_input_tensor(const DNNInputData *input) -{ - TF_DataType dt; - size_t size; - int64_t input_dims[] = {1, input->height, input->width, input->channels}; - switch (input->dt) { - case DNN_FLOAT: - dt = TF_FLOAT; - size = sizeof(float); - break; - case DNN_UINT8: - dt = TF_UINT8; - size = sizeof(char); - break; - default: - av_assert0(!"should not reach here"); - } - - return TF_AllocateTensor(dt, input_dims, 4, - input_dims[1] * input_dims[2] * input_dims[3] * size); -} - -static DNNReturnType set_input_output_tf(void *model, DNNInputData *input, const char *input_name, const char **output_names, uint32_t nb_output) -{ - TFModel *tf_model = (TFModel *)model; - TF_SessionOptions *sess_opts; - const TF_Operation *init_op = TF_GraphOperationByName(tf_model->graph, "init"); - - // Input operation - tf_model->input.oper = TF_GraphOperationByName(tf_model->graph, input_name); - if (!tf_model->input.oper){ - return DNN_ERROR; - } - tf_model->input.index = 0; - if (tf_model->input_tensor){ - TF_DeleteTensor(tf_model->input_tensor); - } - tf_model->input_tensor = allocate_input_tensor(input); - if (!tf_model->input_tensor){ - return DNN_ERROR; - } - input->data = (float *)TF_TensorData(tf_model->input_tensor); - - // Output operation - if (nb_output == 0) - return DNN_ERROR; - - av_freep(&tf_model->outputs); - tf_model->outputs = av_malloc_array(nb_output, sizeof(*tf_model->outputs)); - if (!tf_model->outputs) - return DNN_ERROR; - for (int i = 0; i < nb_output; ++i) { - tf_model->outputs[i].oper = TF_GraphOperationByName(tf_model->graph, output_names[i]); - if (!tf_model->outputs[i].oper){ - av_freep(&tf_model->outputs); - return DNN_ERROR; - } - tf_model->outputs[i].index = 0; - } - - if (tf_model->output_tensors) { - for (uint32_t i = 0; i < tf_model->nb_output; ++i) { - if (tf_model->output_tensors[i]) { - TF_DeleteTensor(tf_model->output_tensors[i]); - tf_model->output_tensors[i] = NULL; - } - } - } - av_freep(&tf_model->output_tensors); - tf_model->output_tensors = av_mallocz_array(nb_output, sizeof(*tf_model->output_tensors)); - if (!tf_model->output_tensors) { - av_freep(&tf_model->outputs); - return DNN_ERROR; - } - - tf_model->nb_output = nb_output; - - if (tf_model->session){ - TF_CloseSession(tf_model->session, tf_model->status); - TF_DeleteSession(tf_model->session, tf_model->status); - } - - sess_opts = TF_NewSessionOptions(); - tf_model->session = TF_NewSession(tf_model->graph, sess_opts, tf_model->status); - TF_DeleteSessionOptions(sess_opts); - if (TF_GetCode(tf_model->status) != TF_OK) - { - return DNN_ERROR; - } - - // Run initialization operation with name "init" if it is present in graph - if (init_op){ - TF_SessionRun(tf_model->session, NULL, - NULL, NULL, 0, - NULL, NULL, 0, - &init_op, 1, NULL, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK) - { - return DNN_ERROR; - } - } - - return DNN_SUCCESS; -} - -static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename) -{ - TF_Buffer *graph_def; - TF_ImportGraphDefOptions *graph_opts; - - graph_def = read_graph(model_filename); - if (!graph_def){ - return DNN_ERROR; - } - tf_model->graph = TF_NewGraph(); - tf_model->status = TF_NewStatus(); - graph_opts = TF_NewImportGraphDefOptions(); - TF_GraphImportGraphDef(tf_model->graph, graph_def, graph_opts, tf_model->status); - TF_DeleteImportGraphDefOptions(graph_opts); - TF_DeleteBuffer(graph_def); - if (TF_GetCode(tf_model->status) != TF_OK){ - TF_DeleteGraph(tf_model->graph); - TF_DeleteStatus(tf_model->status); - return DNN_ERROR; - } - - return DNN_SUCCESS; -} - -#define NAME_BUFFER_SIZE 256 - -static DNNReturnType add_conv_layer(TFModel *tf_model, TF_Operation *transpose_op, TF_Operation **cur_op, - ConvolutionalParams* params, const int layer) -{ - TF_Operation *op; - TF_OperationDescription *op_desc; - TF_Output input; - int64_t strides[] = {1, 1, 1, 1}; - TF_Tensor *tensor; - int64_t dims[4]; - int dims_len; - char name_buffer[NAME_BUFFER_SIZE]; - int32_t size; - - size = params->input_num * params->output_num * params->kernel_size * params->kernel_size; - input.index = 0; - - snprintf(name_buffer, NAME_BUFFER_SIZE, "conv_kernel%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "Const", name_buffer); - TF_SetAttrType(op_desc, "dtype", TF_FLOAT); - dims[0] = params->output_num; - dims[1] = params->kernel_size; - dims[2] = params->kernel_size; - dims[3] = params->input_num; - dims_len = 4; - tensor = TF_AllocateTensor(TF_FLOAT, dims, dims_len, size * sizeof(float)); - memcpy(TF_TensorData(tensor), params->kernel, size * sizeof(float)); - TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - - snprintf(name_buffer, NAME_BUFFER_SIZE, "transpose%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "Transpose", name_buffer); - input.oper = op; - TF_AddInput(op_desc, input); - input.oper = transpose_op; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - TF_SetAttrType(op_desc, "Tperm", TF_INT32); - op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - - snprintf(name_buffer, NAME_BUFFER_SIZE, "conv2d%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "Conv2D", name_buffer); - input.oper = *cur_op; - TF_AddInput(op_desc, input); - input.oper = op; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - TF_SetAttrIntList(op_desc, "strides", strides, 4); - TF_SetAttrString(op_desc, "padding", "VALID", 5); - *cur_op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - - snprintf(name_buffer, NAME_BUFFER_SIZE, "conv_biases%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "Const", name_buffer); - TF_SetAttrType(op_desc, "dtype", TF_FLOAT); - dims[0] = params->output_num; - dims_len = 1; - tensor = TF_AllocateTensor(TF_FLOAT, dims, dims_len, params->output_num * sizeof(float)); - memcpy(TF_TensorData(tensor), params->biases, params->output_num * sizeof(float)); - TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - - snprintf(name_buffer, NAME_BUFFER_SIZE, "bias_add%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "BiasAdd", name_buffer); - input.oper = *cur_op; - TF_AddInput(op_desc, input); - input.oper = op; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - *cur_op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - - snprintf(name_buffer, NAME_BUFFER_SIZE, "activation%d", layer); - switch (params->activation){ - case RELU: - op_desc = TF_NewOperation(tf_model->graph, "Relu", name_buffer); - break; - case TANH: - op_desc = TF_NewOperation(tf_model->graph, "Tanh", name_buffer); - break; - case SIGMOID: - op_desc = TF_NewOperation(tf_model->graph, "Sigmoid", name_buffer); - break; - default: - return DNN_ERROR; - } - input.oper = *cur_op; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - *cur_op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - - return DNN_SUCCESS; -} - -static DNNReturnType add_depth_to_space_layer(TFModel *tf_model, TF_Operation **cur_op, - DepthToSpaceParams *params, const int layer) -{ - TF_OperationDescription *op_desc; - TF_Output input; - char name_buffer[NAME_BUFFER_SIZE]; - - snprintf(name_buffer, NAME_BUFFER_SIZE, "depth_to_space%d", layer); - op_desc = TF_NewOperation(tf_model->graph, "DepthToSpace", name_buffer); - input.oper = *cur_op; - input.index = 0; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - TF_SetAttrInt(op_desc, "block_size", params->block_size); - *cur_op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - - return DNN_SUCCESS; -} - -static int calculate_pad(const ConvolutionalNetwork *conv_network) -{ - ConvolutionalParams *params; - int32_t layer; - int pad = 0; - - for (layer = 0; layer < conv_network->layers_num; ++layer){ - if (conv_network->layers[layer].type == CONV){ - params = (ConvolutionalParams *)conv_network->layers[layer].params; - pad += params->kernel_size >> 1; - } - } - - return pad; -} - -static DNNReturnType add_pad_op(TFModel *tf_model, TF_Operation **cur_op, const int32_t pad) -{ - TF_Operation *op; - TF_Tensor *tensor; - TF_OperationDescription *op_desc; - TF_Output input; - int32_t *pads; - int64_t pads_shape[] = {4, 2}; - - input.index = 0; - - op_desc = TF_NewOperation(tf_model->graph, "Const", "pads"); - TF_SetAttrType(op_desc, "dtype", TF_INT32); - tensor = TF_AllocateTensor(TF_INT32, pads_shape, 2, 4 * 2 * sizeof(int32_t)); - pads = (int32_t *)TF_TensorData(tensor); - pads[0] = 0; pads[1] = 0; - pads[2] = pad; pads[3] = pad; - pads[4] = pad; pads[5] = pad; - pads[6] = 0; pads[7] = 0; - TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - - op_desc = TF_NewOperation(tf_model->graph, "MirrorPad", "mirror_pad"); - input.oper = *cur_op; - TF_AddInput(op_desc, input); - input.oper = op; - TF_AddInput(op_desc, input); - TF_SetAttrType(op_desc, "T", TF_FLOAT); - TF_SetAttrType(op_desc, "Tpaddings", TF_INT32); - TF_SetAttrString(op_desc, "mode", "SYMMETRIC", 9); - *cur_op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - - return DNN_SUCCESS; -} - -static DNNReturnType load_native_model(TFModel *tf_model, const char *model_filename) -{ - int32_t layer; - TF_OperationDescription *op_desc; - TF_Operation *op; - TF_Operation *transpose_op; - TF_Tensor *tensor; - TF_Output input; - int32_t *transpose_perm; - int64_t transpose_perm_shape[] = {4}; - int64_t input_shape[] = {1, -1, -1, -1}; - int32_t pad; - DNNReturnType layer_add_res; - DNNModel *native_model = NULL; - ConvolutionalNetwork *conv_network; - - native_model = ff_dnn_load_model_native(model_filename); - if (!native_model){ - return DNN_ERROR; - } - - conv_network = (ConvolutionalNetwork *)native_model->model; - pad = calculate_pad(conv_network); - tf_model->graph = TF_NewGraph(); - tf_model->status = TF_NewStatus(); - -#define CLEANUP_ON_ERROR(tf_model) \ - { \ - TF_DeleteGraph(tf_model->graph); \ - TF_DeleteStatus(tf_model->status); \ - return DNN_ERROR; \ - } - - op_desc = TF_NewOperation(tf_model->graph, "Placeholder", "x"); - TF_SetAttrType(op_desc, "dtype", TF_FLOAT); - TF_SetAttrShape(op_desc, "shape", input_shape, 4); - op = TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - CLEANUP_ON_ERROR(tf_model); - } - - if (add_pad_op(tf_model, &op, pad) != DNN_SUCCESS){ - CLEANUP_ON_ERROR(tf_model); - } - - op_desc = TF_NewOperation(tf_model->graph, "Const", "transpose_perm"); - TF_SetAttrType(op_desc, "dtype", TF_INT32); - tensor = TF_AllocateTensor(TF_INT32, transpose_perm_shape, 1, 4 * sizeof(int32_t)); - transpose_perm = (int32_t *)TF_TensorData(tensor); - transpose_perm[0] = 1; - transpose_perm[1] = 2; - transpose_perm[2] = 3; - transpose_perm[3] = 0; - TF_SetAttrTensor(op_desc, "value", tensor, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - CLEANUP_ON_ERROR(tf_model); - } - transpose_op = TF_FinishOperation(op_desc, tf_model->status); - - for (layer = 0; layer < conv_network->layers_num; ++layer){ - switch (conv_network->layers[layer].type){ - case INPUT: - layer_add_res = DNN_SUCCESS; - break; - case CONV: - layer_add_res = add_conv_layer(tf_model, transpose_op, &op, - (ConvolutionalParams *)conv_network->layers[layer].params, layer); - break; - case DEPTH_TO_SPACE: - layer_add_res = add_depth_to_space_layer(tf_model, &op, - (DepthToSpaceParams *)conv_network->layers[layer].params, layer); - break; - default: - CLEANUP_ON_ERROR(tf_model); - } - - if (layer_add_res != DNN_SUCCESS){ - CLEANUP_ON_ERROR(tf_model); - } - } - - op_desc = TF_NewOperation(tf_model->graph, "Identity", "y"); - input.oper = op; - TF_AddInput(op_desc, input); - TF_FinishOperation(op_desc, tf_model->status); - if (TF_GetCode(tf_model->status) != TF_OK){ - CLEANUP_ON_ERROR(tf_model); - } - - ff_dnn_free_model_native(&native_model); - - return DNN_SUCCESS; -} - -DNNModel *ff_dnn_load_model_tf(const char *model_filename) -{ - DNNModel *model = NULL; - TFModel *tf_model = NULL; - - model = av_malloc(sizeof(DNNModel)); - if (!model){ - return NULL; - } - - tf_model = av_mallocz(sizeof(TFModel)); - if (!tf_model){ - av_freep(&model); - return NULL; - } - - if (load_tf_model(tf_model, model_filename) != DNN_SUCCESS){ - if (load_native_model(tf_model, model_filename) != DNN_SUCCESS){ - av_freep(&tf_model); - av_freep(&model); - - return NULL; - } - } - - model->model = (void *)tf_model; - model->set_input_output = &set_input_output_tf; - - return model; -} - - - -DNNReturnType ff_dnn_execute_model_tf(const DNNModel *model, DNNData *outputs, uint32_t nb_output) -{ - TFModel *tf_model = (TFModel *)model->model; - uint32_t nb = FFMIN(nb_output, tf_model->nb_output); - if (nb == 0) - return DNN_ERROR; - - av_assert0(tf_model->output_tensors); - for (uint32_t i = 0; i < tf_model->nb_output; ++i) { - if (tf_model->output_tensors[i]) { - TF_DeleteTensor(tf_model->output_tensors[i]); - tf_model->output_tensors[i] = NULL; - } - } - - TF_SessionRun(tf_model->session, NULL, - &tf_model->input, &tf_model->input_tensor, 1, - tf_model->outputs, tf_model->output_tensors, nb, - NULL, 0, NULL, tf_model->status); - - if (TF_GetCode(tf_model->status) != TF_OK){ - return DNN_ERROR; - } - - for (uint32_t i = 0; i < nb; ++i) { - outputs[i].height = TF_Dim(tf_model->output_tensors[i], 1); - outputs[i].width = TF_Dim(tf_model->output_tensors[i], 2); - outputs[i].channels = TF_Dim(tf_model->output_tensors[i], 3); - outputs[i].data = TF_TensorData(tf_model->output_tensors[i]); - } - - return DNN_SUCCESS; -} - -void ff_dnn_free_model_tf(DNNModel **model) -{ - TFModel *tf_model; - - if (*model){ - tf_model = (TFModel *)(*model)->model; - if (tf_model->graph){ - TF_DeleteGraph(tf_model->graph); - } - if (tf_model->session){ - TF_CloseSession(tf_model->session, tf_model->status); - TF_DeleteSession(tf_model->session, tf_model->status); - } - if (tf_model->status){ - TF_DeleteStatus(tf_model->status); - } - if (tf_model->input_tensor){ - TF_DeleteTensor(tf_model->input_tensor); - } - if (tf_model->output_tensors) { - for (uint32_t i = 0; i < tf_model->nb_output; ++i) { - if (tf_model->output_tensors[i]) { - TF_DeleteTensor(tf_model->output_tensors[i]); - tf_model->output_tensors[i] = NULL; - } - } - } - av_freep(&tf_model->outputs); - av_freep(&tf_model->output_tensors); - av_freep(&tf_model); - av_freep(model); - } -} diff -Nru ffmpeg-4.2.2/libavfilter/dnn_backend_tf.h ffmpeg-4.4/libavfilter/dnn_backend_tf.h --- ffmpeg-4.2.2/libavfilter/dnn_backend_tf.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn_backend_tf.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2018 Sergey Lavrushkin - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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 - * DNN inference functions interface for TensorFlow backend. - */ - - -#ifndef AVFILTER_DNN_BACKEND_TF_H -#define AVFILTER_DNN_BACKEND_TF_H - -#include "dnn_interface.h" - -DNNModel *ff_dnn_load_model_tf(const char *model_filename); - -DNNReturnType ff_dnn_execute_model_tf(const DNNModel *model, DNNData *outputs, uint32_t nb_output); - -void ff_dnn_free_model_tf(DNNModel **model); - -#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn_filter_common.c ffmpeg-4.4/libavfilter/dnn_filter_common.c --- ffmpeg-4.2.2/libavfilter/dnn_filter_common.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn_filter_common.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,106 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "dnn_filter_common.h" + +int ff_dnn_init(DnnContext *ctx, DNNFunctionType func_type, AVFilterContext *filter_ctx) +{ + if (!ctx->model_filename) { + av_log(filter_ctx, AV_LOG_ERROR, "model file for network is not specified\n"); + return AVERROR(EINVAL); + } + if (!ctx->model_inputname) { + av_log(filter_ctx, AV_LOG_ERROR, "input name of the model network is not specified\n"); + return AVERROR(EINVAL); + } + if (!ctx->model_outputname) { + av_log(filter_ctx, AV_LOG_ERROR, "output name of the model network is not specified\n"); + return AVERROR(EINVAL); + } + + ctx->dnn_module = ff_get_dnn_module(ctx->backend_type); + if (!ctx->dnn_module) { + av_log(filter_ctx, AV_LOG_ERROR, "could not create DNN module for requested backend\n"); + return AVERROR(ENOMEM); + } + if (!ctx->dnn_module->load_model) { + av_log(filter_ctx, AV_LOG_ERROR, "load_model for network is not specified\n"); + return AVERROR(EINVAL); + } + + ctx->model = (ctx->dnn_module->load_model)(ctx->model_filename, func_type, ctx->backend_options, filter_ctx); + if (!ctx->model) { + av_log(filter_ctx, AV_LOG_ERROR, "could not load DNN model\n"); + return AVERROR(EINVAL); + } + + if (!ctx->dnn_module->execute_model_async && ctx->async) { + ctx->async = 0; + av_log(filter_ctx, AV_LOG_WARNING, "this backend does not support async execution, roll back to sync.\n"); + } + +#if !HAVE_PTHREAD_CANCEL + if (ctx->async) { + ctx->async = 0; + av_log(filter_ctx, AV_LOG_WARNING, "pthread is not supported, roll back to sync.\n"); + } +#endif + + return 0; +} + +DNNReturnType ff_dnn_get_input(DnnContext *ctx, DNNData *input) +{ + return ctx->model->get_input(ctx->model->model, input, ctx->model_inputname); +} + +DNNReturnType ff_dnn_get_output(DnnContext *ctx, int input_width, int input_height, int *output_width, int *output_height) +{ + return ctx->model->get_output(ctx->model->model, ctx->model_inputname, input_width, input_height, + ctx->model_outputname, output_width, output_height); +} + +DNNReturnType ff_dnn_execute_model(DnnContext *ctx, AVFrame *in_frame, AVFrame *out_frame) +{ + return (ctx->dnn_module->execute_model)(ctx->model, ctx->model_inputname, in_frame, + (const char **)&ctx->model_outputname, 1, out_frame); +} + +DNNReturnType ff_dnn_execute_model_async(DnnContext *ctx, AVFrame *in_frame, AVFrame *out_frame) +{ + return (ctx->dnn_module->execute_model_async)(ctx->model, ctx->model_inputname, in_frame, + (const char **)&ctx->model_outputname, 1, out_frame); +} + +DNNAsyncStatusType ff_dnn_get_async_result(DnnContext *ctx, AVFrame **in_frame, AVFrame **out_frame) +{ + return (ctx->dnn_module->get_async_result)(ctx->model, in_frame, out_frame); +} + +DNNReturnType ff_dnn_flush(DnnContext *ctx) +{ + return (ctx->dnn_module->flush)(ctx->model); +} + +void ff_dnn_uninit(DnnContext *ctx) +{ + if (ctx->dnn_module) { + (ctx->dnn_module->free_model)(&ctx->model); + av_freep(&ctx->dnn_module); + } +} diff -Nru ffmpeg-4.2.2/libavfilter/dnn_filter_common.h ffmpeg-4.4/libavfilter/dnn_filter_common.h --- ffmpeg-4.2.2/libavfilter/dnn_filter_common.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn_filter_common.h 2021-04-08 21:28:39.000000000 +0000 @@ -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 + */ + +/** + * @file + * common functions for the dnn based filters + */ + +#ifndef AVFILTER_DNN_FILTER_COMMON_H +#define AVFILTER_DNN_FILTER_COMMON_H + +#include "dnn_interface.h" + +typedef struct DnnContext { + char *model_filename; + DNNBackendType backend_type; + char *model_inputname; + char *model_outputname; + char *backend_options; + int async; + + DNNModule *dnn_module; + DNNModel *model; +} DnnContext; + +#define DNN_COMMON_OPTIONS \ + { "model", "path to model file", OFFSET(model_filename), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },\ + { "input", "input name of the model", OFFSET(model_inputname), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },\ + { "output", "output name of the model", OFFSET(model_outputname), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },\ + { "backend_configs", "backend configs", OFFSET(backend_options), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },\ + { "options", "backend configs", OFFSET(backend_options), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },\ + { "async", "use DNN async inference", OFFSET(async), AV_OPT_TYPE_BOOL, { .i64 = 1}, 0, 1, FLAGS}, + + +int ff_dnn_init(DnnContext *ctx, DNNFunctionType func_type, AVFilterContext *filter_ctx); +DNNReturnType ff_dnn_get_input(DnnContext *ctx, DNNData *input); +DNNReturnType ff_dnn_get_output(DnnContext *ctx, int input_width, int input_height, int *output_width, int *output_height); +DNNReturnType ff_dnn_execute_model(DnnContext *ctx, AVFrame *in_frame, AVFrame *out_frame); +DNNReturnType ff_dnn_execute_model_async(DnnContext *ctx, AVFrame *in_frame, AVFrame *out_frame); +DNNAsyncStatusType ff_dnn_get_async_result(DnnContext *ctx, AVFrame **in_frame, AVFrame **out_frame); +DNNReturnType ff_dnn_flush(DnnContext *ctx); +void ff_dnn_uninit(DnnContext *ctx); + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/dnn_interface.c ffmpeg-4.4/libavfilter/dnn_interface.c --- ffmpeg-4.2.2/libavfilter/dnn_interface.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn_interface.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2018 Sergey Lavrushkin - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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 - * Implements DNN module initialization with specified backend. - */ - -#include "dnn_interface.h" -#include "dnn_backend_native.h" -#include "dnn_backend_tf.h" -#include "libavutil/mem.h" - -DNNModule *ff_get_dnn_module(DNNBackendType backend_type) -{ - DNNModule *dnn_module; - - dnn_module = av_malloc(sizeof(DNNModule)); - if(!dnn_module){ - return NULL; - } - - switch(backend_type){ - case DNN_NATIVE: - dnn_module->load_model = &ff_dnn_load_model_native; - dnn_module->execute_model = &ff_dnn_execute_model_native; - dnn_module->free_model = &ff_dnn_free_model_native; - break; - case DNN_TF: - #if (CONFIG_LIBTENSORFLOW == 1) - dnn_module->load_model = &ff_dnn_load_model_tf; - dnn_module->execute_model = &ff_dnn_execute_model_tf; - dnn_module->free_model = &ff_dnn_free_model_tf; - #else - av_freep(&dnn_module); - return NULL; - #endif - break; - default: - av_log(NULL, AV_LOG_ERROR, "Module backend_type is not native or tensorflow\n"); - av_freep(&dnn_module); - return NULL; - } - - return dnn_module; -} diff -Nru ffmpeg-4.2.2/libavfilter/dnn_interface.h ffmpeg-4.4/libavfilter/dnn_interface.h --- ffmpeg-4.2.2/libavfilter/dnn_interface.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/dnn_interface.h 2021-04-08 21:28:39.000000000 +0000 @@ -27,38 +27,79 @@ #define AVFILTER_DNN_INTERFACE_H #include +#include "libavutil/frame.h" +#include "avfilter.h" typedef enum {DNN_SUCCESS, DNN_ERROR} DNNReturnType; -typedef enum {DNN_NATIVE, DNN_TF} DNNBackendType; +typedef enum {DNN_NATIVE, DNN_TF, DNN_OV} DNNBackendType; -typedef enum {DNN_FLOAT, DNN_UINT8} DNNDataType; +typedef enum {DNN_FLOAT = 1, DNN_UINT8 = 4} DNNDataType; -typedef struct DNNInputData{ - void *data; - DNNDataType dt; - int width, height, channels; -} DNNInputData; +typedef enum { + DCO_NONE, + DCO_BGR, +} DNNColorOrder; + +typedef enum { + DAST_FAIL, // something wrong + DAST_EMPTY_QUEUE, // no more inference result to get + DAST_NOT_READY, // all queued inferences are not finished + DAST_SUCCESS // got a result frame successfully +} DNNAsyncStatusType; + +typedef enum { + DFT_NONE, + DFT_PROCESS_FRAME, // process the whole frame + DFT_ANALYTICS_DETECT, // detect from the whole frame + // we can add more such as detect_from_crop, classify_from_bbox, etc. +}DNNFunctionType; typedef struct DNNData{ - float *data; + void *data; int width, height, channels; + // dt and order together decide the color format + DNNDataType dt; + DNNColorOrder order; } DNNData; typedef struct DNNModel{ // Stores model that can be different for different backends. void *model; - // Sets model input and output. - // Should be called at least once before model execution. - DNNReturnType (*set_input_output)(void *model, DNNInputData *input, const char *input_name, const char **output_names, uint32_t nb_output); + // Stores options when the model is executed by the backend + const char *options; + // Stores FilterContext used for the interaction between AVFrame and DNNData + AVFilterContext *filter_ctx; + // Stores function type of the model + DNNFunctionType func_type; + // Gets model input information + // Just reuse struct DNNData here, actually the DNNData.data field is not needed. + DNNReturnType (*get_input)(void *model, DNNData *input, const char *input_name); + // Gets model output width/height with given input w/h + DNNReturnType (*get_output)(void *model, const char *input_name, int input_width, int input_height, + const char *output_name, int *output_width, int *output_height); + // set the pre process to transfer data from AVFrame to DNNData + // the default implementation within DNN is used if it is not provided by the filter + int (*pre_proc)(AVFrame *frame_in, DNNData *model_input, AVFilterContext *filter_ctx); + // set the post process to transfer data from DNNData to AVFrame + // the default implementation within DNN is used if it is not provided by the filter + int (*post_proc)(AVFrame *frame_out, DNNData *model_output, AVFilterContext *filter_ctx); } DNNModel; // Stores pointers to functions for loading, executing, freeing DNN models for one of the backends. typedef struct DNNModule{ // Loads model and parameters from given file. Returns NULL if it is not possible. - DNNModel *(*load_model)(const char *model_filename); + DNNModel *(*load_model)(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx); // Executes model with specified input and output. Returns DNN_ERROR otherwise. - DNNReturnType (*execute_model)(const DNNModel *model, DNNData *outputs, uint32_t nb_output); + DNNReturnType (*execute_model)(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame); + // Executes model with specified input and output asynchronously. Returns DNN_ERROR otherwise. + DNNReturnType (*execute_model_async)(const DNNModel *model, const char *input_name, AVFrame *in_frame, + const char **output_names, uint32_t nb_output, AVFrame *out_frame); + // Retrieve inference result. + DNNAsyncStatusType (*get_async_result)(const DNNModel *model, AVFrame **in, AVFrame **out); + // Flush all the pending tasks. + DNNReturnType (*flush)(const DNNModel *model); // Frees memory allocated for model. void (*free_model)(DNNModel **model); } DNNModule; diff -Nru ffmpeg-4.2.2/libavfilter/drawutils.c ffmpeg-4.4/libavfilter/drawutils.c --- ffmpeg-4.2.2/libavfilter/drawutils.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/drawutils.c 2021-04-08 21:28:39.000000000 +0000 @@ -70,6 +70,10 @@ 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 */ return AVERROR(EINVAL); @@ -77,104 +81,6 @@ return 0; } -int ff_fill_line_with_color(uint8_t *line[4], int pixel_step[4], int w, uint8_t dst_color[4], - enum AVPixelFormat pix_fmt, uint8_t rgba_color[4], - int *is_packed_rgba, uint8_t rgba_map_ptr[4]) -{ - uint8_t rgba_map[4] = {0}; - int i; - const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(pix_fmt); - int hsub; - - av_assert0(pix_desc); - - hsub = pix_desc->log2_chroma_w; - - *is_packed_rgba = ff_fill_rgba_map(rgba_map, pix_fmt) >= 0; - - if (*is_packed_rgba) { - pixel_step[0] = (av_get_bits_per_pixel(pix_desc))>>3; - for (i = 0; i < 4; i++) - dst_color[rgba_map[i]] = rgba_color[i]; - - line[0] = av_malloc_array(w, pixel_step[0]); - if (!line[0]) - return AVERROR(ENOMEM); - for (i = 0; i < w; i++) - memcpy(line[0] + i * pixel_step[0], dst_color, pixel_step[0]); - if (rgba_map_ptr) - memcpy(rgba_map_ptr, rgba_map, sizeof(rgba_map[0]) * 4); - } else { - int plane; - - dst_color[0] = RGB_TO_Y_CCIR(rgba_color[0], rgba_color[1], rgba_color[2]); - dst_color[1] = RGB_TO_U_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0); - dst_color[2] = RGB_TO_V_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0); - dst_color[3] = rgba_color[3]; - - for (plane = 0; plane < 4; plane++) { - int line_size; - int hsub1 = (plane == 1 || plane == 2) ? hsub : 0; - - pixel_step[plane] = 1; - line_size = AV_CEIL_RSHIFT(w, hsub1) * pixel_step[plane]; - line[plane] = av_malloc(line_size); - if (!line[plane]) { - while(plane && line[plane-1]) - av_freep(&line[--plane]); - return AVERROR(ENOMEM); - } - memset(line[plane], dst_color[plane], line_size); - } - } - - return 0; -} - -void ff_draw_rectangle(uint8_t *dst[4], int dst_linesize[4], - uint8_t *src[4], int pixelstep[4], - int hsub, int vsub, int x, int y, int w, int h) -{ - int i, plane; - uint8_t *p; - - for (plane = 0; plane < 4 && dst[plane]; plane++) { - int hsub1 = plane == 1 || plane == 2 ? hsub : 0; - int vsub1 = plane == 1 || plane == 2 ? vsub : 0; - int width = AV_CEIL_RSHIFT(w, hsub1); - int height = AV_CEIL_RSHIFT(h, vsub1); - - p = dst[plane] + (y >> vsub1) * dst_linesize[plane]; - for (i = 0; i < height; i++) { - memcpy(p + (x >> hsub1) * pixelstep[plane], - src[plane], width * pixelstep[plane]); - p += dst_linesize[plane]; - } - } -} - -void ff_copy_rectangle(uint8_t *dst[4], int dst_linesize[4], - uint8_t *src[4], int src_linesize[4], int pixelstep[4], - int hsub, int vsub, int x, int y, int y2, int w, int h) -{ - int i, plane; - uint8_t *p; - - for (plane = 0; plane < 4 && dst[plane]; plane++) { - int hsub1 = plane == 1 || plane == 2 ? hsub : 0; - int vsub1 = plane == 1 || plane == 2 ? vsub : 0; - int width = AV_CEIL_RSHIFT(w, hsub1); - int height = AV_CEIL_RSHIFT(h, vsub1); - - p = dst[plane] + (y >> vsub1) * dst_linesize[plane]; - for (i = 0; i < height; i++) { - memcpy(p + (x >> hsub1) * pixelstep[plane], - src[plane] + src_linesize[plane]*(i+(y2>>vsub1)), width * pixelstep[plane]); - p += dst_linesize[plane]; - } - } -} - int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format); diff -Nru ffmpeg-4.2.2/libavfilter/drawutils.h ffmpeg-4.4/libavfilter/drawutils.h --- ffmpeg-4.2.2/libavfilter/drawutils.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/drawutils.h 2021-04-08 21:28:39.000000000 +0000 @@ -30,19 +30,6 @@ int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt); -int ff_fill_line_with_color(uint8_t *line[4], int pixel_step[4], int w, - uint8_t dst_color[4], - enum AVPixelFormat pix_fmt, uint8_t rgba_color[4], - int *is_packed_rgba, uint8_t rgba_map[4]); - -void ff_draw_rectangle(uint8_t *dst[4], int dst_linesize[4], - uint8_t *src[4], int pixelstep[4], - int hsub, int vsub, int x, int y, int w, int h); - -void ff_copy_rectangle(uint8_t *dst[4], int dst_linesize[4], - uint8_t *src[4], int src_linesize[4], int pixelstep[4], - int hsub, int vsub, int x, int y, int y2, int w, int h); - #define MAX_PLANES 4 typedef struct FFDrawContext { diff -Nru ffmpeg-4.2.2/libavfilter/ebur128.c ffmpeg-4.4/libavfilter/ebur128.c --- ffmpeg-4.2.2/libavfilter/ebur128.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/ebur128.c 2021-04-08 21:28:39.000000000 +0000 @@ -49,6 +49,7 @@ #include "libavutil/common.h" #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavutil/thread.h" #define CHECK_ERROR(condition, errorcode, goto_point) \ @@ -155,7 +156,7 @@ { size_t i; st->d->channel_map = - (int *) av_malloc_array(st->channels, sizeof(int)); + (int *) av_malloc_array(st->channels, sizeof(*st->d->channel_map)); if (!st->d->channel_map) return AVERROR(ENOMEM); if (st->channels == 4) { @@ -221,17 +222,17 @@ int errcode; FFEBUR128State *st; - st = (FFEBUR128State *) av_malloc(sizeof(FFEBUR128State)); + st = (FFEBUR128State *) av_malloc(sizeof(*st)); CHECK_ERROR(!st, 0, exit) st->d = (struct FFEBUR128StateInternal *) - av_malloc(sizeof(struct FFEBUR128StateInternal)); + av_malloc(sizeof(*st->d)); CHECK_ERROR(!st->d, 0, free_state) st->channels = channels; errcode = ebur128_init_channel_map(st); CHECK_ERROR(errcode, 0, free_internal) st->d->sample_peak = - (double *) av_mallocz_array(channels, sizeof(double)); + (double *) av_mallocz_array(channels, sizeof(*st->d->sample_peak)); CHECK_ERROR(!st->d->sample_peak, 0, free_channel_map) st->samplerate = samplerate; @@ -253,16 +254,16 @@ } st->d->audio_data = (double *) av_mallocz_array(st->d->audio_data_frames, - st->channels * sizeof(double)); + st->channels * sizeof(*st->d->audio_data)); CHECK_ERROR(!st->d->audio_data, 0, free_sample_peak) ebur128_init_filter(st); st->d->block_energy_histogram = - av_mallocz(1000 * sizeof(unsigned long)); + av_mallocz(1000 * sizeof(*st->d->block_energy_histogram)); CHECK_ERROR(!st->d->block_energy_histogram, 0, free_audio_data) st->d->short_term_block_energy_histogram = - av_mallocz(1000 * sizeof(unsigned long)); + av_mallocz(1000 * sizeof(*st->d->short_term_block_energy_histogram)); CHECK_ERROR(!st->d->short_term_block_energy_histogram, 0, free_block_energy_histogram) st->d->short_term_frame_counter = 0; @@ -275,7 +276,7 @@ if (ff_thread_once(&histogram_init, &init_histogram) != 0) goto free_short_term_block_energy_histogram; - st->d->data_ptrs = av_malloc_array(channels, sizeof(void *)); + st->d->data_ptrs = av_malloc_array(channels, sizeof(*st->d->data_ptrs)); CHECK_ERROR(!st->d->data_ptrs, 0, free_short_term_block_energy_histogram); @@ -361,9 +362,6 @@ st->d->v[ci][1] = fabs(st->d->v[ci][1]) < DBL_MIN ? 0.0 : st->d->v[ci][1]; \ } \ } -EBUR128_FILTER(short, -((double)SHRT_MIN)) -EBUR128_FILTER(int, -((double)INT_MIN)) -EBUR128_FILTER(float, 1.0) EBUR128_FILTER(double, 1.0) static double ebur128_energy_to_loudness(double energy) @@ -458,8 +456,8 @@ } static int ebur128_energy_shortterm(FFEBUR128State * st, double *out); -#define FF_EBUR128_ADD_FRAMES_PLANAR(type) \ -void ff_ebur128_add_frames_planar_##type(FFEBUR128State* st, const type** srcs, \ +#define EBUR128_ADD_FRAMES_PLANAR(type) \ +static void ebur128_add_frames_planar_##type(FFEBUR128State* st, const type** srcs, \ size_t frames, int stride) { \ size_t src_index = 0; \ while (frames > 0) { \ @@ -501,10 +499,7 @@ } \ } \ } -FF_EBUR128_ADD_FRAMES_PLANAR(short) -FF_EBUR128_ADD_FRAMES_PLANAR(int) -FF_EBUR128_ADD_FRAMES_PLANAR(float) -FF_EBUR128_ADD_FRAMES_PLANAR(double) +EBUR128_ADD_FRAMES_PLANAR(double) #define FF_EBUR128_ADD_FRAMES(type) \ void ff_ebur128_add_frames_##type(FFEBUR128State* st, const type* src, \ size_t frames) { \ @@ -512,11 +507,8 @@ const type **buf = (const type**)st->d->data_ptrs; \ for (i = 0; i < st->channels; i++) \ buf[i] = src + i; \ - ff_ebur128_add_frames_planar_##type(st, buf, frames, st->channels); \ + ebur128_add_frames_planar_##type(st, buf, frames, st->channels); \ } -FF_EBUR128_ADD_FRAMES(short) -FF_EBUR128_ADD_FRAMES(int) -FF_EBUR128_ADD_FRAMES(float) FF_EBUR128_ADD_FRAMES(double) static int ebur128_calc_relative_threshold(FFEBUR128State **sts, size_t size, @@ -605,12 +597,6 @@ return ebur128_gated_loudness(&st, 1, out); } -int ff_ebur128_loudness_global_multiple(FFEBUR128State ** sts, size_t size, - double *out) -{ - return ebur128_gated_loudness(sts, size, out); -} - static int ebur128_energy_in_interval(FFEBUR128State * st, size_t interval_frames, double *out) { @@ -627,21 +613,6 @@ out); } -int ff_ebur128_loudness_momentary(FFEBUR128State * st, double *out) -{ - double energy; - int error = ebur128_energy_in_interval(st, st->d->samples_in_100ms * 4, - &energy); - if (error) { - return error; - } else if (energy <= 0.0) { - *out = -HUGE_VAL; - return 0; - } - *out = ebur128_energy_to_loudness(energy); - return 0; -} - int ff_ebur128_loudness_shortterm(FFEBUR128State * st, double *out) { double energy; @@ -649,22 +620,6 @@ if (error) { return error; } else if (energy <= 0.0) { - *out = -HUGE_VAL; - return 0; - } - *out = ebur128_energy_to_loudness(energy); - return 0; -} - -int ff_ebur128_loudness_window(FFEBUR128State * st, - unsigned long window, double *out) -{ - double energy; - size_t interval_frames = st->samplerate * window / 1000; - int error = ebur128_energy_in_interval(st, interval_frames, &energy); - if (error) { - return error; - } else if (energy <= 0.0) { *out = -HUGE_VAL; return 0; } diff -Nru ffmpeg-4.2.2/libavfilter/ebur128.h ffmpeg-4.4/libavfilter/ebur128.h --- ffmpeg-4.2.2/libavfilter/ebur128.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/ebur128.h 2021-04-08 21:28:39.000000000 +0000 @@ -81,7 +81,7 @@ * modes that suit your needs, as performance will be better. */ enum mode { - /** can call ff_ebur128_loudness_momentary */ + /** can resurrrect and call ff_ebur128_loudness_momentary */ FF_EBUR128_MODE_M = (1 << 0), /** can call ff_ebur128_loudness_shortterm */ FF_EBUR128_MODE_S = (1 << 1) | FF_EBUR128_MODE_M, @@ -151,41 +151,9 @@ * @param src array of source frames. Channels must be interleaved. * @param frames number of frames. Not number of samples! */ -void ff_ebur128_add_frames_short(FFEBUR128State * st, - const short *src, size_t frames); -/** \brief See \ref ebur128_add_frames_short */ -void ff_ebur128_add_frames_int(FFEBUR128State * st, - const int *src, size_t frames); -/** \brief See \ref ebur128_add_frames_short */ -void ff_ebur128_add_frames_float(FFEBUR128State * st, - const float *src, size_t frames); -/** \brief See \ref ebur128_add_frames_short */ void ff_ebur128_add_frames_double(FFEBUR128State * st, const double *src, size_t frames); -/** \brief Add frames to be processed. - * - * @param st library state. - * @param srcs array of source frame channel data pointers - * @param frames number of frames. Not number of samples! - * @param stride number of samples to skip to for the next sample of the same channel - */ -void ff_ebur128_add_frames_planar_short(FFEBUR128State * st, - const short **srcs, - size_t frames, int stride); -/** \brief See \ref ebur128_add_frames_planar_short */ -void ff_ebur128_add_frames_planar_int(FFEBUR128State * st, - const int **srcs, - size_t frames, int stride); -/** \brief See \ref ebur128_add_frames_planar_short */ -void ff_ebur128_add_frames_planar_float(FFEBUR128State * st, - const float **srcs, - size_t frames, int stride); -/** \brief See \ref ebur128_add_frames_planar_short */ -void ff_ebur128_add_frames_planar_double(FFEBUR128State * st, - const double **srcs, - size_t frames, int stride); - /** \brief Get global integrated loudness in LUFS. * * @param st library state. @@ -196,28 +164,7 @@ * - AVERROR(EINVAL) if mode "FF_EBUR128_MODE_I" has not been set. */ int ff_ebur128_loudness_global(FFEBUR128State * st, double *out); -/** \brief Get global integrated loudness in LUFS across multiple instances. - * - * @param sts array of library states. - * @param size length of sts - * @param out integrated loudness in LUFS. -HUGE_VAL if result is negative - * infinity. - * @return - * - 0 on success. - * - AVERROR(EINVAL) if mode "FF_EBUR128_MODE_I" has not been set. - */ -int ff_ebur128_loudness_global_multiple(FFEBUR128State ** sts, - size_t size, double *out); -/** \brief Get momentary loudness (last 400ms) in LUFS. - * - * @param st library state. - * @param out momentary loudness in LUFS. -HUGE_VAL if result is negative - * infinity. - * @return - * - 0 on success. - */ -int ff_ebur128_loudness_momentary(FFEBUR128State * st, double *out); /** \brief Get short-term loudness (last 3s) in LUFS. * * @param st library state. @@ -229,20 +176,6 @@ */ int ff_ebur128_loudness_shortterm(FFEBUR128State * st, double *out); -/** \brief Get loudness of the specified window in LUFS. - * - * window must not be larger than the current window set in st. - * - * @param st library state. - * @param window window in ms to calculate loudness. - * @param out loudness in LUFS. -HUGE_VAL if result is negative infinity. - * @return - * - 0 on success. - * - AVERROR(EINVAL) if window larger than current window in st. - */ -int ff_ebur128_loudness_window(FFEBUR128State * st, - unsigned long window, double *out); - /** \brief Get loudness range (LRA) of programme in LU. * * Calculates loudness range according to EBU 3342. diff -Nru ffmpeg-4.2.2/libavfilter/f_drawgraph.c ffmpeg-4.4/libavfilter/f_drawgraph.c --- ffmpeg-4.2.2/libavfilter/f_drawgraph.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_drawgraph.c 2021-04-08 21:28:39.000000000 +0000 @@ -40,6 +40,7 @@ int mode; int slide; int w, h; + AVRational frame_rate; AVFrame *out; int x; @@ -48,21 +49,22 @@ float *values[4]; int values_size[4]; int nb_values; + int64_t prev_pts; } DrawGraphContext; #define OFFSET(x) offsetof(DrawGraphContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption drawgraph_options[] = { - { "m1", "set 1st metadata key", OFFSET(key[0]), AV_OPT_TYPE_STRING, {.str=""}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "fg1", "set 1st foreground color expression", OFFSET(fg_str[0]), AV_OPT_TYPE_STRING, {.str="0xffff0000"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "m2", "set 2nd metadata key", OFFSET(key[1]), AV_OPT_TYPE_STRING, {.str=""}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "fg2", "set 2nd foreground color expression", OFFSET(fg_str[1]), AV_OPT_TYPE_STRING, {.str="0xff00ff00"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "m3", "set 3rd metadata key", OFFSET(key[2]), AV_OPT_TYPE_STRING, {.str=""}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "fg3", "set 3rd foreground color expression", OFFSET(fg_str[2]), AV_OPT_TYPE_STRING, {.str="0xffff00ff"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "m4", "set 4th metadata key", OFFSET(key[3]), AV_OPT_TYPE_STRING, {.str=""}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "fg4", "set 4th foreground color expression", OFFSET(fg_str[3]), AV_OPT_TYPE_STRING, {.str="0xffffff00"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "bg", "set background color", OFFSET(bg), AV_OPT_TYPE_COLOR, {.str="white"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "m1", "set 1st metadata key", OFFSET(key[0]), AV_OPT_TYPE_STRING, {.str=""}, 0, 0, FLAGS }, + { "fg1", "set 1st foreground color expression", OFFSET(fg_str[0]), AV_OPT_TYPE_STRING, {.str="0xffff0000"}, 0, 0, FLAGS }, + { "m2", "set 2nd metadata key", OFFSET(key[1]), AV_OPT_TYPE_STRING, {.str=""}, 0, 0, FLAGS }, + { "fg2", "set 2nd foreground color expression", OFFSET(fg_str[1]), AV_OPT_TYPE_STRING, {.str="0xff00ff00"}, 0, 0, FLAGS }, + { "m3", "set 3rd metadata key", OFFSET(key[2]), AV_OPT_TYPE_STRING, {.str=""}, 0, 0, FLAGS }, + { "fg3", "set 3rd foreground color expression", OFFSET(fg_str[2]), AV_OPT_TYPE_STRING, {.str="0xffff00ff"}, 0, 0, FLAGS }, + { "m4", "set 4th metadata key", OFFSET(key[3]), AV_OPT_TYPE_STRING, {.str=""}, 0, 0, FLAGS }, + { "fg4", "set 4th foreground color expression", OFFSET(fg_str[3]), AV_OPT_TYPE_STRING, {.str="0xffffff00"}, 0, 0, FLAGS }, + { "bg", "set background color", OFFSET(bg), AV_OPT_TYPE_COLOR, {.str="white"}, 0, 0, FLAGS }, { "min", "set minimal value", OFFSET(min), AV_OPT_TYPE_FLOAT, {.dbl=-1.}, INT_MIN, INT_MAX, FLAGS }, { "max", "set maximal value", OFFSET(max), AV_OPT_TYPE_FLOAT, {.dbl=1.}, INT_MIN, INT_MAX, FLAGS }, { "mode", "set graph mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=2}, 0, 2, FLAGS, "mode" }, @@ -77,6 +79,8 @@ {"picture", "display graph in single frame", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, FLAGS, "slide"}, { "size", "set graph size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="900x256"}, 0, 0, FLAGS }, { "s", "set graph size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="900x256"}, 0, 0, FLAGS }, + { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS }, + { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS }, { NULL } }; @@ -130,7 +134,7 @@ int ret; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(fmts_list, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(fmts_list, &outlink->incfg.formats)) < 0) return ret; return 0; @@ -159,6 +163,8 @@ AVDictionary *metadata; AVDictionaryEntry *e; AVFrame *out = s->out; + AVFrame *clone = NULL; + int64_t in_pts, out_pts; int i; if (s->slide == 4 && s->nb_values >= s->values_size[0] / sizeof(float)) { @@ -309,12 +315,24 @@ s->nb_values++; s->x++; + in_pts = in->pts; + av_frame_free(&in); if (s->slide == 4) return 0; - return ff_filter_frame(outlink, av_frame_clone(s->out)); + out_pts = av_rescale_q(in_pts, inlink->time_base, outlink->time_base); + + if (out_pts == s->prev_pts) + return 0; + + clone = av_frame_clone(s->out); + if (!clone) + return AVERROR(ENOMEM); + + clone->pts = s->prev_pts = out_pts; + return ff_filter_frame(outlink, clone); } static int request_frame(AVFilterLink *outlink) @@ -406,6 +424,9 @@ outlink->w = s->w; outlink->h = s->h; outlink->sample_aspect_ratio = (AVRational){1,1}; + outlink->frame_rate = s->frame_rate; + outlink->time_base = av_inv_q(outlink->frame_rate); + s->prev_pts = AV_NOPTS_VALUE; return 0; } diff -Nru ffmpeg-4.2.2/libavfilter/f_ebur128.c ffmpeg-4.4/libavfilter/f_ebur128.c --- ffmpeg-4.2.2/libavfilter/f_ebur128.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_ebur128.c 2021-04-08 21:28:39.000000000 +0000 @@ -527,30 +527,22 @@ /* insert output pads */ if (ebur128->do_video) { pad = (AVFilterPad){ - .name = av_strdup("out0"), + .name = "out0", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_video_output, }; - if (!pad.name) - return AVERROR(ENOMEM); ret = ff_insert_outpad(ctx, 0, &pad); - if (ret < 0) { - av_freep(&pad.name); + if (ret < 0) return ret; - } } pad = (AVFilterPad){ - .name = av_asprintf("out%d", ebur128->do_video), + .name = ebur128->do_video ? "out1" : "out0", .type = AVMEDIA_TYPE_AUDIO, .config_props = config_audio_output, }; - if (!pad.name) - return AVERROR(ENOMEM); ret = ff_insert_outpad(ctx, ebur128->do_video, &pad); - if (ret < 0) { - av_freep(&pad.name); + if (ret < 0) return ret; - } /* summary */ av_log(ctx, AV_LOG_VERBOSE, "EBU +%d scale\n", ebur128->meter); @@ -774,6 +766,7 @@ /* push one video frame */ if (ebur128->do_video) { + AVFrame *clone; int x, y, ret; uint8_t *p; double gauge_value; @@ -823,7 +816,10 @@ /* set pts and push frame */ pic->pts = pts; - ret = ff_filter_frame(outlink, av_frame_clone(pic)); + clone = av_frame_clone(pic); + if (!clone) + return AVERROR(ENOMEM); + ret = ff_filter_frame(outlink, clone); if (ret < 0) return ret; } @@ -906,7 +902,7 @@ /* set optional output video format */ if (ebur128->do_video) { formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; outlink = ctx->outputs[1]; } @@ -915,18 +911,18 @@ * Note: ff_set_common_* functions are not used because they affect all the * links, and thus break the video format negotiation */ formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0 || - (ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0 || + (ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; layouts = ff_all_channel_layouts(); - if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0 || - (ret = ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0 || + (ret = ff_channel_layouts_ref(layouts, &outlink->incfg.channel_layouts)) < 0) return ret; formats = ff_make_format_list(input_srate); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0 || - (ret = ff_formats_ref(formats, &outlink->in_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0 || + (ret = ff_formats_ref(formats, &outlink->incfg.samplerates)) < 0) return ret; return 0; @@ -986,8 +982,6 @@ av_freep(&ebur128->i400.cache[i]); av_freep(&ebur128->i3000.cache[i]); } - for (i = 0; i < ctx->nb_outputs; i++) - av_freep(&ctx->output_pads[i].name); av_frame_free(&ebur128->outpicref); #if CONFIG_SWRESAMPLE av_freep(&ebur128->swr_buf); diff -Nru ffmpeg-4.2.2/libavfilter/f_graphmonitor.c ffmpeg-4.4/libavfilter/f_graphmonitor.c --- ffmpeg-4.2.2/libavfilter/f_graphmonitor.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_graphmonitor.c 2021-04-08 21:28:39.000000000 +0000 @@ -42,10 +42,12 @@ AVRational frame_rate; int64_t pts; + int64_t next_pts; uint8_t white[4]; uint8_t yellow[4]; uint8_t red[4]; uint8_t green[4]; + uint8_t blue[4]; uint8_t bg[4]; } GraphMonitorContext; @@ -59,6 +61,7 @@ MODE_FMT = 1 << 6, MODE_SIZE = 1 << 7, MODE_RATE = 1 << 8, + MODE_EOF = 1 << 9, }; #define OFFSET(x) offsetof(GraphMonitorContext, x) @@ -84,6 +87,7 @@ { "format", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FMT}, 0, 0, VF, "flags" }, { "size", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SIZE}, 0, 0, VF, "flags" }, { "rate", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_RATE}, 0, 0, VF, "flags" }, + { "eof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_EOF}, 0, 0, VF, "flags" }, { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, { NULL } @@ -99,7 +103,7 @@ int ret; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(fmts_list, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(fmts_list, &outlink->incfg.formats)) < 0) return ret; return 0; @@ -235,6 +239,11 @@ drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } + if (s->flags & MODE_EOF && ff_outlink_get_status(l)) { + snprintf(buffer, sizeof(buffer)-1, " | eof"); + drawtext(out, xpos, ypos, buffer, s->blue); + xpos += strlen(buffer) * 8; + } } static int create_frame(AVFilterContext *ctx, int64_t pts) @@ -300,7 +309,7 @@ } out->pts = pts; - s->pts = pts; + s->pts = pts + 1; return ff_filter_frame(outlink, out); } @@ -328,10 +337,14 @@ if (pts != AV_NOPTS_VALUE) { pts = av_rescale_q(pts, inlink->time_base, outlink->time_base); - if (s->pts < pts && ff_outlink_frame_wanted(outlink)) - return create_frame(ctx, pts); + if (s->pts == AV_NOPTS_VALUE) + s->pts = pts; + s->next_pts = pts; } + if (s->pts < s->next_pts && ff_outlink_frame_wanted(outlink)) + return create_frame(ctx, s->pts); + FF_FILTER_FORWARD_STATUS(inlink, outlink); FF_FILTER_FORWARD_WANTED(outlink, inlink); @@ -347,6 +360,9 @@ s->yellow[0] = s->yellow[1] = 255; s->red[0] = 255; s->green[1] = 255; + s->blue[2] = 255; + s->pts = AV_NOPTS_VALUE; + s->next_pts = AV_NOPTS_VALUE; outlink->w = s->w; outlink->h = s->h; outlink->sample_aspect_ratio = (AVRational){1,1}; diff -Nru ffmpeg-4.2.2/libavfilter/fifo.c ffmpeg-4.4/libavfilter/fifo.c --- ffmpeg-4.2.2/libavfilter/fifo.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/fifo.c 2021-04-08 21:28:39.000000000 +0000 @@ -23,20 +23,16 @@ * FIFO buffering filter */ -#include "libavutil/avassert.h" -#include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "libavutil/mathematics.h" -#include "libavutil/samplefmt.h" #include "audio.h" #include "avfilter.h" #include "internal.h" -#include "video.h" typedef struct Buf { AVFrame *frame; - struct Buf *next; + struct Buf *next; } Buf; typedef struct FifoContext { @@ -53,38 +49,38 @@ static av_cold int init(AVFilterContext *ctx) { - FifoContext *fifo = ctx->priv; - fifo->last = &fifo->root; + FifoContext *s = ctx->priv; + s->last = &s->root; return 0; } static av_cold void uninit(AVFilterContext *ctx) { - FifoContext *fifo = ctx->priv; + FifoContext *s = ctx->priv; Buf *buf, *tmp; - for (buf = fifo->root.next; buf; buf = tmp) { + for (buf = s->root.next; buf; buf = tmp) { tmp = buf->next; av_frame_free(&buf->frame); av_free(buf); } - av_frame_free(&fifo->out); + av_frame_free(&s->out); } static int add_to_queue(AVFilterLink *inlink, AVFrame *frame) { - FifoContext *fifo = inlink->dst->priv; + FifoContext *s = inlink->dst->priv; - fifo->last->next = av_mallocz(sizeof(Buf)); - if (!fifo->last->next) { + s->last->next = av_mallocz(sizeof(Buf)); + if (!s->last->next) { av_frame_free(&frame); return AVERROR(ENOMEM); } - fifo->last = fifo->last->next; - fifo->last->frame = frame; + s->last = s->last->next; + s->last->frame = frame; return 0; } @@ -98,165 +94,27 @@ s->root.next = tmp; } -/** - * Move data pointers and pts offset samples forward. - */ -static void buffer_offset(AVFilterLink *link, AVFrame *frame, - int offset) -{ - int nb_channels = link->channels; - int planar = av_sample_fmt_is_planar(link->format); - int planes = planar ? nb_channels : 1; - int block_align = av_get_bytes_per_sample(link->format) * (planar ? 1 : nb_channels); - int i; - - av_assert0(frame->nb_samples > offset); - - for (i = 0; i < planes; i++) - frame->extended_data[i] += block_align * offset; - if (frame->data != frame->extended_data) - memcpy(frame->data, frame->extended_data, - FFMIN(planes, FF_ARRAY_ELEMS(frame->data)) * sizeof(*frame->data)); - frame->linesize[0] -= block_align*offset; - frame->nb_samples -= offset; - - if (frame->pts != AV_NOPTS_VALUE) { - frame->pts += av_rescale_q(offset, (AVRational){1, link->sample_rate}, - link->time_base); - } -} - -static int calc_ptr_alignment(AVFrame *frame) -{ - int planes = av_sample_fmt_is_planar(frame->format) ? - frame->channels : 1; - int min_align = 128; - int p; - - for (p = 0; p < planes; p++) { - int cur_align = 128; - while ((intptr_t)frame->extended_data[p] % cur_align) - cur_align >>= 1; - if (cur_align < min_align) - min_align = cur_align; - } - return min_align; -} - -static int return_audio_frame(AVFilterContext *ctx) -{ - AVFilterLink *link = ctx->outputs[0]; - FifoContext *s = ctx->priv; - AVFrame *head = s->root.next ? s->root.next->frame : NULL; - AVFrame *out; - int ret; - - /* if head is NULL then we're flushing the remaining samples in out */ - if (!head && !s->out) - return AVERROR_EOF; - - if (!s->out && - head->nb_samples >= link->request_samples && - calc_ptr_alignment(head) >= 32) { - if (head->nb_samples == link->request_samples) { - out = head; - queue_pop(s); - } else { - out = av_frame_clone(head); - if (!out) - return AVERROR(ENOMEM); - - out->nb_samples = link->request_samples; - buffer_offset(link, head, link->request_samples); - } - } else { - int nb_channels = link->channels; - - if (!s->out) { - s->out = ff_get_audio_buffer(link, link->request_samples); - if (!s->out) - return AVERROR(ENOMEM); - - s->out->nb_samples = 0; - s->out->pts = head->pts; - s->allocated_samples = link->request_samples; - } else if (link->request_samples != s->allocated_samples) { - av_log(ctx, AV_LOG_ERROR, "request_samples changed before the " - "buffer was returned.\n"); - return AVERROR(EINVAL); - } - - while (s->out->nb_samples < s->allocated_samples) { - int len; - - if (!s->root.next) { - ret = ff_request_frame(ctx->inputs[0]); - if (ret == AVERROR_EOF) { - av_samples_set_silence(s->out->extended_data, - s->out->nb_samples, - s->allocated_samples - - s->out->nb_samples, - nb_channels, link->format); - s->out->nb_samples = s->allocated_samples; - break; - } else if (ret < 0) - return ret; - if (!s->root.next) - return 0; - } - head = s->root.next->frame; - - len = FFMIN(s->allocated_samples - s->out->nb_samples, - head->nb_samples); - - av_samples_copy(s->out->extended_data, head->extended_data, - s->out->nb_samples, 0, len, nb_channels, - link->format); - s->out->nb_samples += len; - - if (len == head->nb_samples) { - av_frame_free(&head); - queue_pop(s); - } else { - buffer_offset(link, head, len); - } - } - out = s->out; - s->out = NULL; - } - return ff_filter_frame(link, out); -} - static int request_frame(AVFilterLink *outlink) { - FifoContext *fifo = outlink->src->priv; + FifoContext *s = outlink->src->priv; int ret = 0; - if (!fifo->root.next) { - if ((ret = ff_request_frame(outlink->src->inputs[0])) < 0) { - if (ret == AVERROR_EOF && outlink->request_samples) - return return_audio_frame(outlink->src); + if (!s->root.next) { + if ((ret = ff_request_frame(outlink->src->inputs[0])) < 0) return ret; - } - if (!fifo->root.next) + if (!s->root.next) return 0; } - - if (outlink->request_samples) { - return return_audio_frame(outlink->src); - } else { - ret = ff_filter_frame(outlink, fifo->root.next->frame); - queue_pop(fifo); - } - + ret = ff_filter_frame(outlink, s->root.next->frame); + queue_pop(s); return ret; } static const AVFilterPad avfilter_vf_fifo_inputs[] = { { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = add_to_queue, + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = add_to_queue, }, { NULL } }; @@ -271,23 +129,20 @@ }; AVFilter ff_vf_fifo = { - .name = "fifo", + .name = "fifo", .description = NULL_IF_CONFIG_SMALL("Buffer input images and send them when they are requested."), - - .init = init, - .uninit = uninit, - - .priv_size = sizeof(FifoContext), - - .inputs = avfilter_vf_fifo_inputs, - .outputs = avfilter_vf_fifo_outputs, + .init = init, + .uninit = uninit, + .priv_size = sizeof(FifoContext), + .inputs = avfilter_vf_fifo_inputs, + .outputs = avfilter_vf_fifo_outputs, }; static const AVFilterPad avfilter_af_afifo_inputs[] = { { - .name = "default", - .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = add_to_queue, + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = add_to_queue, }, { NULL } }; @@ -304,12 +159,9 @@ AVFilter ff_af_afifo = { .name = "afifo", .description = NULL_IF_CONFIG_SMALL("Buffer input frames and send them when they are requested."), - - .init = init, - .uninit = uninit, - - .priv_size = sizeof(FifoContext), - - .inputs = avfilter_af_afifo_inputs, - .outputs = avfilter_af_afifo_outputs, + .init = init, + .uninit = uninit, + .priv_size = sizeof(FifoContext), + .inputs = avfilter_af_afifo_inputs, + .outputs = avfilter_af_afifo_outputs, }; diff -Nru ffmpeg-4.2.2/libavfilter/f_interleave.c ffmpeg-4.4/libavfilter/f_interleave.c --- ffmpeg-4.2.2/libavfilter/f_interleave.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_interleave.c 2021-04-08 21:28:39.000000000 +0000 @@ -37,15 +37,25 @@ typedef struct InterleaveContext { const AVClass *class; int nb_inputs; + int duration_mode; int64_t pts; } InterleaveContext; +#define DURATION_LONGEST 0 +#define DURATION_SHORTEST 1 +#define DURATION_FIRST 2 + #define OFFSET(x) offsetof(InterleaveContext, x) #define DEFINE_OPTIONS(filt_name, flags_) \ static const AVOption filt_name##_options[] = { \ { "nb_inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, .flags = flags_ }, \ { "n", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, .flags = flags_ }, \ + { "duration", "how to determine the end-of-stream", \ + OFFSET(duration_mode), AV_OPT_TYPE_INT, { .i64 = DURATION_LONGEST }, 0, 2, flags_, "duration" }, \ + { "longest", "Duration of longest input", 0, AV_OPT_TYPE_CONST, { .i64 = DURATION_LONGEST }, 0, 0, flags_, "duration" }, \ + { "shortest", "Duration of shortest input", 0, AV_OPT_TYPE_CONST, { .i64 = DURATION_SHORTEST }, 0, 0, flags_, "duration" }, \ + { "first", "Duration of first input", 0, AV_OPT_TYPE_CONST, { .i64 = DURATION_FIRST }, 0, 0, flags_, "duration" }, \ { NULL } \ } @@ -55,20 +65,39 @@ InterleaveContext *s = ctx->priv; int64_t q_pts, pts = INT64_MAX; int i, nb_eofs = 0, input_idx = -1; + int first_eof = 0; + int64_t rpts; + int status; + int nb_inputs_with_frames = 0; FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); for (i = 0; i < ctx->nb_inputs; i++) { - if (!ff_outlink_get_status(ctx->inputs[i]) && - !ff_inlink_queued_frames(ctx->inputs[i])) - break; + int is_eof = !!ff_inlink_acknowledge_status(ctx->inputs[i], &status, &rpts); + + nb_eofs += is_eof; + if (i == 0) + first_eof = is_eof; + } + + if ((nb_eofs > 0 && s->duration_mode == DURATION_SHORTEST) || + (nb_eofs == ctx->nb_inputs && s->duration_mode == DURATION_LONGEST) || + (first_eof && s->duration_mode == DURATION_FIRST)) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + return 0; } - if (i == ctx->nb_inputs) { + for (i = 0; i < ctx->nb_inputs; i++) { + if (!ff_inlink_queued_frames(ctx->inputs[i])) + continue; + nb_inputs_with_frames++; + } + + if (nb_inputs_with_frames >= ctx->nb_inputs - nb_eofs) { for (i = 0; i < ctx->nb_inputs; i++) { AVFrame *frame; - if (ff_outlink_get_status(ctx->inputs[i])) + if (ff_inlink_queued_frames(ctx->inputs[i]) == 0) continue; frame = ff_inlink_peek_frame(ctx->inputs[i], 0); @@ -112,11 +141,10 @@ ff_inlink_request_frame(ctx->inputs[i]); return 0; } - nb_eofs++; } - if (nb_eofs == ctx->nb_inputs) { - ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + if (i == ctx->nb_inputs - nb_eofs && ff_outlink_frame_wanted(outlink)) { + ff_filter_set_ready(ctx, 100); return 0; } diff -Nru ffmpeg-4.2.2/libavfilter/f_loop.c ffmpeg-4.4/libavfilter/f_loop.c --- ffmpeg-4.2.2/libavfilter/f_loop.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_loop.c 2020-07-11 10:39:30.000000000 +0000 @@ -107,7 +107,7 @@ } out->pts = s->pts; out->nb_samples = ret; - s->pts += out->nb_samples; + s->pts += av_rescale_q(out->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); i += out->nb_samples; s->current_sample += out->nb_samples; @@ -116,6 +116,7 @@ return ret; if (s->current_sample >= s->nb_samples) { + s->duration = s->pts; s->current_sample = 0; if (s->loop > 0) @@ -145,7 +146,7 @@ drain = FFMAX(0, s->start - s->ignored_samples); s->pts = frame->pts; av_audio_fifo_drain(s->fifo, drain); - s->pts += s->start - s->ignored_samples; + s->pts += av_rescale_q(s->start - s->ignored_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); } s->nb_samples += ret - drain; drain = frame->nb_samples - written; @@ -158,7 +159,7 @@ av_audio_fifo_drain(s->left, drain); } frame->nb_samples = ret; - s->pts += ret; + s->pts += av_rescale_q(ret, (AVRational){1, outlink->sample_rate}, outlink->time_base); ret = ff_filter_frame(outlink, frame); } else { int nb_samples = frame->nb_samples; @@ -169,7 +170,7 @@ } else { s->ignored_samples += frame->nb_samples; frame->pts = s->pts; - s->pts += frame->nb_samples; + s->pts += av_rescale_q(frame->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); ret = ff_filter_frame(outlink, frame); } @@ -195,7 +196,7 @@ return AVERROR(ENOMEM); av_audio_fifo_read(s->left, (void **)out->extended_data, nb_samples); out->pts = s->pts; - s->pts += nb_samples; + s->pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); ret = ff_filter_frame(outlink, out); if (ret < 0) return ret; @@ -205,13 +206,55 @@ ret = push_samples(ctx, 1024); } - if (ret == AVERROR_EOF && s->nb_samples > 0 && s->loop != 0) { - ret = push_samples(ctx, outlink->sample_rate); + if (s->eof && s->nb_samples > 0 && s->loop != 0) { + ret = push_samples(ctx, 1024); } return ret; } +static int aactivate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + LoopContext *s = ctx->priv; + AVFrame *frame = NULL; + int ret, status; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + if (!s->eof && (s->nb_samples < s->size || !s->loop || !s->size)) { + ret = ff_inlink_consume_frame(inlink, &frame); + if (ret < 0) + return ret; + if (ret > 0) + return afilter_frame(inlink, frame); + } + + if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) { + s->size = s->nb_samples; + s->eof = 1; + } + } + + if (s->eof && (!s->loop || !s->size)) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->duration); + return 0; + } + + if (!s->eof && (!s->size || + (s->nb_samples < s->size) || + (s->nb_samples >= s->size && s->loop == 0))) { + FF_FILTER_FORWARD_WANTED(outlink, inlink); + } else if (s->loop && s->nb_samples == s->size) { + return arequest_frame(outlink); + } + + return FFERROR_NOT_READY; +} + static const AVOption aloop_options[] = { { "loop", "number of loops", OFFSET(loop), AV_OPT_TYPE_INT, {.i64 = 0 }, -1, INT_MAX, AFLAGS }, { "size", "max number of samples to loop", OFFSET(size), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT32_MAX, AFLAGS }, @@ -225,7 +268,6 @@ { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = afilter_frame, .config_props = aconfig_input, }, { NULL } @@ -235,7 +277,6 @@ { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .request_frame = arequest_frame, }, { NULL } }; @@ -245,6 +286,7 @@ .description = NULL_IF_CONFIG_SMALL("Loop audio samples."), .priv_size = sizeof(LoopContext), .priv_class = &aloop_class, + .activate = aactivate, .uninit = auninit, .inputs = ainputs, .outputs = aoutputs, diff -Nru ffmpeg-4.2.2/libavfilter/f_metadata.c ffmpeg-4.4/libavfilter/f_metadata.c --- ffmpeg-4.2.2/libavfilter/f_metadata.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_metadata.c 2020-07-11 10:39:30.000000000 +0000 @@ -54,6 +54,7 @@ METADATAF_EQUAL, METADATAF_GREATER, METADATAF_EXPR, + METADATAF_ENDS_WITH, METADATAF_NB }; @@ -87,6 +88,8 @@ int (*compare)(struct MetadataContext *s, const char *value1, const char *value2); void (*print)(AVFilterContext *ctx, const char *msg, ...) av_printf_format(2, 3); + + int direct; // reduces buffering when printing to user-supplied URL } MetadataContext; #define OFFSET(x) offsetof(MetadataContext, x) @@ -107,8 +110,10 @@ { "equal", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = METADATAF_EQUAL }, 0, 3, FLAGS, "function" }, \ { "greater", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = METADATAF_GREATER }, 0, 3, FLAGS, "function" }, \ { "expr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = METADATAF_EXPR }, 0, 3, FLAGS, "function" }, \ + { "ends_with", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = METADATAF_ENDS_WITH }, 0, 0, FLAGS, "function" }, \ { "expr", "set expression for expr function", OFFSET(expr_str), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, FLAGS }, \ { "file", "set file where to print metadata information", OFFSET(file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, \ + { "direct", "reduce buffering when printing to user-set file or pipe", OFFSET(direct), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, \ { NULL } \ } @@ -122,6 +127,14 @@ return !strncmp(value1, value2, strlen(value2)); } +static int ends_with(MetadataContext *s, const char *value1, const char *value2) +{ + const int len1 = strlen(value1); + const int len2 = strlen(value2); + + return !strncmp(value1 + FFMAX(len1 - len2, 0), value2, len2); +} + static int equal(MetadataContext *s, const char *value1, const char *value2) { float f1, f2; @@ -212,6 +225,9 @@ case METADATAF_STARTS_WITH: s->compare = starts_with; break; + case METADATAF_ENDS_WITH: + s->compare = ends_with; + break; case METADATAF_LESS: s->compare = less; break; @@ -261,6 +277,9 @@ s->file_str, buf); return ret; } + + if (s->direct) + s->avio_context->direct = AVIO_FLAG_DIRECT; } return 0; @@ -270,6 +289,8 @@ { MetadataContext *s = ctx->priv; + av_expr_free(s->expr); + s->expr = NULL; if (s->avio_context) { avio_closep(&s->avio_context); } @@ -283,7 +304,7 @@ AVDictionary **metadata = &frame->metadata; AVDictionaryEntry *e; - if (!*metadata) + if (!*metadata && s->mode != METADATA_ADD) return ff_filter_frame(outlink, frame); e = av_dict_get(*metadata, !s->key ? "" : s->key, NULL, @@ -305,13 +326,11 @@ av_dict_set(metadata, s->key, s->value, 0); } return ff_filter_frame(outlink, frame); - break; case METADATA_MODIFY: if (e && e->value) { av_dict_set(metadata, s->key, s->value, 0); } return ff_filter_frame(outlink, frame); - break; case METADATA_PRINT: if (!s->key && e) { s->print(ctx, "frame:%-4"PRId64" pts:%-7s pts_time:%s\n", @@ -326,7 +345,6 @@ s->print(ctx, "%s=%s\n", s->key, e->value); } return ff_filter_frame(outlink, frame); - break; case METADATA_DELETE: if (!s->key) { av_dict_free(metadata); @@ -334,7 +352,6 @@ av_dict_set(metadata, s->key, NULL, 0); } return ff_filter_frame(outlink, frame); - break; default: av_assert0(0); }; diff -Nru ffmpeg-4.2.2/libavfilter/formats.c ffmpeg-4.4/libavfilter/formats.c --- ffmpeg-4.2.2/libavfilter/formats.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/formats.c 2021-04-08 21:28:39.000000000 +0000 @@ -24,7 +24,6 @@ #include "libavutil/common.h" #include "libavutil/eval.h" #include "libavutil/pixdesc.h" -#include "libavutil/parseutils.h" #include "avfilter.h" #include "internal.h" #include "formats.h" @@ -34,14 +33,14 @@ /** * Add all refs from a to ret and destroy a. */ -#define MERGE_REF(ret, a, fmts, type, fail) \ +#define MERGE_REF(ret, a, fmts, type, fail_statement) \ do { \ type ***tmp; \ int i; \ \ if (!(tmp = av_realloc_array(ret->refs, ret->refcount + a->refcount, \ sizeof(*tmp)))) \ - goto fail; \ + { fail_statement } \ ret->refs = tmp; \ \ for (i = 0; i < a->refcount; i ++) { \ @@ -55,50 +54,54 @@ } while (0) /** - * Add all formats common for a and b to ret, copy the refs and destroy - * a and b. + * Add all formats common to a and b to a, add b's refs to a and destroy b. + * If check is set, nothing is modified and it is only checked whether + * the formats are compatible. + * If empty_allowed is set and one of a,b->nb is zero, the lists are + * merged; otherwise, it is treated as error. */ -#define MERGE_FORMATS(ret, a, b, fmts, nb, type, fail) \ -do { \ - int i, j, k = 0, count = FFMIN(a->nb, b->nb); \ - \ - if (!(ret = av_mallocz(sizeof(*ret)))) \ - goto fail; \ - \ - if (count) { \ - if (!(ret->fmts = av_malloc_array(count, sizeof(*ret->fmts)))) \ - goto fail; \ - for (i = 0; i < a->nb; i++) \ - for (j = 0; j < b->nb; j++) \ - if (a->fmts[i] == b->fmts[j]) { \ - if(k >= FFMIN(a->nb, b->nb)){ \ - av_log(NULL, AV_LOG_ERROR, "Duplicate formats in %s detected\n", __FUNCTION__); \ - av_free(ret->fmts); \ - av_free(ret); \ - return NULL; \ - } \ - ret->fmts[k++] = a->fmts[i]; \ - } \ - } \ - ret->nb = k; \ - /* check that there was at least one common format */ \ - if (!ret->nb) \ - goto fail; \ - \ - MERGE_REF(ret, a, fmts, type, fail); \ - MERGE_REF(ret, b, fmts, type, fail); \ +#define MERGE_FORMATS(a, b, fmts, nb, type, check, empty_allowed) \ +do { \ + int i, j, k = 0, skip = 0; \ + \ + if (empty_allowed) { \ + if (!a->nb || !b->nb) { \ + if (check) \ + return 1; \ + if (!a->nb) \ + FFSWAP(type *, a, b); \ + skip = 1; \ + } \ + } \ + if (!skip) { \ + for (i = 0; i < a->nb; i++) \ + for (j = 0; j < b->nb; j++) \ + if (a->fmts[i] == b->fmts[j]) { \ + if (check) \ + return 1; \ + a->fmts[k++] = a->fmts[i]; \ + break; \ + } \ + /* Check that there was at least one common format. \ + * Notice that both a and b are unchanged if not. */ \ + if (!k) \ + return 0; \ + av_assert2(!check); \ + a->nb = k; \ + } \ + \ + MERGE_REF(a, b, fmts, type, return AVERROR(ENOMEM);); \ } while (0) -AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b, - enum AVMediaType type) +static int merge_formats_internal(AVFilterFormats *a, AVFilterFormats *b, + enum AVMediaType type, int check) { - AVFilterFormats *ret = NULL; int i, j; int alpha1=0, alpha2=0; int chroma1=0, chroma2=0; if (a == b) - return a; + return 1; /* Do not lose chroma or alpha in merging. It happens if both lists have formats with chroma (resp. alpha), but @@ -122,56 +125,58 @@ // If chroma or alpha can be lost through merging then do not merge if (alpha2 > alpha1 || chroma2 > chroma1) - return NULL; + return 0; - MERGE_FORMATS(ret, a, b, formats, nb_formats, AVFilterFormats, fail); + MERGE_FORMATS(a, b, formats, nb_formats, AVFilterFormats, check, 0); - return ret; -fail: - if (ret) { - av_freep(&ret->refs); - av_freep(&ret->formats); - } - av_freep(&ret); - return NULL; + return 1; } -AVFilterFormats *ff_merge_samplerates(AVFilterFormats *a, - AVFilterFormats *b) +int ff_can_merge_formats(const AVFilterFormats *a, const AVFilterFormats *b, + enum AVMediaType type) { - AVFilterFormats *ret = NULL; + return merge_formats_internal((AVFilterFormats *)a, + (AVFilterFormats *)b, type, 1); +} - if (a == b) return a; +int ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b, + enum AVMediaType type) +{ + av_assert2(a->refcount && b->refcount); + return merge_formats_internal(a, b, type, 0); +} - if (a->nb_formats && b->nb_formats) { - MERGE_FORMATS(ret, a, b, formats, nb_formats, AVFilterFormats, fail); - } else if (a->nb_formats) { - MERGE_REF(a, b, formats, AVFilterFormats, fail); - ret = a; - } else { - MERGE_REF(b, a, formats, AVFilterFormats, fail); - ret = b; - } +static int merge_samplerates_internal(AVFilterFormats *a, + AVFilterFormats *b, int check) +{ + if (a == b) return 1; - return ret; -fail: - if (ret) { - av_freep(&ret->refs); - av_freep(&ret->formats); - } - av_freep(&ret); - return NULL; + MERGE_FORMATS(a, b, formats, nb_formats, AVFilterFormats, check, 1); + return 1; } -AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a, - AVFilterChannelLayouts *b) +int ff_can_merge_samplerates(const AVFilterFormats *a, const AVFilterFormats *b) { - AVFilterChannelLayouts *ret = NULL; + return merge_samplerates_internal((AVFilterFormats *)a, (AVFilterFormats *)b, 1); +} + +int ff_merge_samplerates(AVFilterFormats *a, AVFilterFormats *b) +{ + av_assert2(a->refcount && b->refcount); + return merge_samplerates_internal(a, b, 0); +} + +int ff_merge_channel_layouts(AVFilterChannelLayouts *a, + AVFilterChannelLayouts *b) +{ + uint64_t *channel_layouts; unsigned a_all = a->all_layouts + a->all_counts; unsigned b_all = b->all_layouts + b->all_counts; int ret_max, ret_nb = 0, i, j, round; - if (a == b) return a; + av_assert2(a->refcount && b->refcount); + + if (a == b) return 1; /* Put the most generic set in a, to avoid doing everything twice */ if (a_all < b_all) { @@ -187,18 +192,16 @@ /* Not optimal: the unknown layouts of b may become known after another merge. */ if (!j) - return NULL; + return 0; b->nb_channel_layouts = j; } - MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, fail); - return b; + MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, return AVERROR(ENOMEM);); + return 1; } ret_max = a->nb_channel_layouts + b->nb_channel_layouts; - if (!(ret = av_mallocz(sizeof(*ret))) || - !(ret->channel_layouts = av_malloc_array(ret_max, - sizeof(*ret->channel_layouts)))) - goto fail; + if (!(channel_layouts = av_malloc_array(ret_max, sizeof(*channel_layouts)))) + return AVERROR(ENOMEM); /* a[known] intersect b[known] */ for (i = 0; i < a->nb_channel_layouts; i++) { @@ -206,8 +209,9 @@ continue; for (j = 0; j < b->nb_channel_layouts; j++) { if (a->channel_layouts[i] == b->channel_layouts[j]) { - ret->channel_layouts[ret_nb++] = a->channel_layouts[i]; + channel_layouts[ret_nb++] = a->channel_layouts[i]; a->channel_layouts[i] = b->channel_layouts[j] = 0; + break; } } } @@ -221,7 +225,7 @@ bfmt = FF_COUNT2LAYOUT(av_get_channel_layout_nb_channels(fmt)); for (j = 0; j < b->nb_channel_layouts; j++) if (b->channel_layouts[j] == bfmt) - ret->channel_layouts[ret_nb++] = a->channel_layouts[i]; + channel_layouts[ret_nb++] = a->channel_layouts[i]; } /* 1st round: swap to prepare 2nd round; 2nd round: put it back */ FFSWAP(AVFilterChannelLayouts *, a, b); @@ -232,23 +236,23 @@ continue; for (j = 0; j < b->nb_channel_layouts; j++) if (a->channel_layouts[i] == b->channel_layouts[j]) - ret->channel_layouts[ret_nb++] = a->channel_layouts[i]; + channel_layouts[ret_nb++] = a->channel_layouts[i]; } - ret->nb_channel_layouts = ret_nb; - if (!ret->nb_channel_layouts) - goto fail; - MERGE_REF(ret, a, channel_layouts, AVFilterChannelLayouts, fail); - MERGE_REF(ret, b, channel_layouts, AVFilterChannelLayouts, fail); - return ret; - -fail: - if (ret) { - av_freep(&ret->refs); - av_freep(&ret->channel_layouts); + if (!ret_nb) { + av_free(channel_layouts); + return 0; } - av_freep(&ret); - return NULL; + + if (a->refcount > b->refcount) + FFSWAP(AVFilterChannelLayouts *, a, b); + + MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, + { av_free(channel_layouts); return AVERROR(ENOMEM); }); + av_freep(&b->channel_layouts); + b->channel_layouts = channel_layouts; + b->nb_channel_layouts = ret_nb; + return 1; } int ff_fmt_is_in(int fmt, const int *fmts) @@ -289,7 +293,7 @@ return formats; } -AVFilterChannelLayouts *ff_make_formatu64_list(const uint64_t *fmts) +AVFilterChannelLayouts *ff_make_format64_list(const int64_t *fmts) { MAKE_FORMAT_LIST(AVFilterChannelLayouts, channel_layouts, nb_channel_layouts); @@ -300,24 +304,18 @@ return formats; } +#if LIBAVFILTER_VERSION_MAJOR < 8 AVFilterChannelLayouts *avfilter_make_format64_list(const int64_t *fmts) { - MAKE_FORMAT_LIST(AVFilterChannelLayouts, - channel_layouts, nb_channel_layouts); - if (count) - memcpy(formats->channel_layouts, fmts, - sizeof(*formats->channel_layouts) * count); - - return formats; + return ff_make_format64_list(fmts); } +#endif #define ADD_FORMAT(f, fmt, unref_fn, type, list, nb) \ do { \ type *fmts; \ - void *oldf = *f; \ \ if (!(*f) && !(*f = av_mallocz(sizeof(**f)))) { \ - unref_fn(f); \ return AVERROR(ENOMEM); \ } \ \ @@ -325,8 +323,6 @@ sizeof(*(*f)->list)); \ if (!fmts) { \ unref_fn(f); \ - if (!oldf) \ - av_freep(f); \ return AVERROR(ENOMEM); \ } \ \ @@ -369,15 +365,46 @@ return ret; } -const int64_t avfilter_all_channel_layouts[] = { -#include "all_channel_layouts.inc" - -1 -}; - -// AVFilterFormats *avfilter_make_all_channel_layouts(void) -// { -// return avfilter_make_format64_list(avfilter_all_channel_layouts); -// } +int ff_formats_pixdesc_filter(AVFilterFormats **rfmts, unsigned want, unsigned rej) +{ + unsigned nb_formats, fmt, flags; + AVFilterFormats *formats = NULL; + + while (1) { + nb_formats = 0; + for (fmt = 0;; fmt++) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); + if (!desc) + break; + flags = desc->flags; + if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL) && + !(desc->flags & AV_PIX_FMT_FLAG_PLANAR) && + (desc->log2_chroma_w || desc->log2_chroma_h)) + flags |= FF_PIX_FMT_FLAG_SW_FLAT_SUB; + if ((flags & (want | rej)) != want) + continue; + if (formats) + formats->formats[nb_formats] = fmt; + nb_formats++; + } + if (formats) { + av_assert0(formats->nb_formats == nb_formats); + *rfmts = formats; + return 0; + } + formats = av_mallocz(sizeof(*formats)); + if (!formats) + return AVERROR(ENOMEM); + formats->nb_formats = nb_formats; + if (nb_formats) { + formats->formats = av_malloc_array(nb_formats, sizeof(*formats->formats)); + if (!formats->formats) { + av_freep(&formats); + return AVERROR(ENOMEM); + } + } + } +} AVFilterFormats *ff_planar_sample_fmts(void) { @@ -419,7 +446,7 @@ #define FORMATS_REF(f, ref, unref_fn) \ void *tmp; \ \ - if (!f || !ref) \ + if (!f) \ return AVERROR(ENOMEM); \ \ tmp = av_realloc_array(f->refs, sizeof(*f->refs), f->refcount + 1); \ @@ -456,16 +483,17 @@ do { \ int idx = -1; \ \ - if (!*ref || !(*ref)->refs) \ + if (!*ref) \ return; \ \ FIND_REF_INDEX(ref, idx); \ \ - if (idx >= 0) \ + if (idx >= 0) { \ memmove((*ref)->refs + idx, (*ref)->refs + idx + 1, \ sizeof(*(*ref)->refs) * ((*ref)->refcount - idx - 1)); \ - \ - if(!--(*ref)->refcount) { \ + --(*ref)->refcount; \ + } \ + if (!(*ref)->refcount) { \ av_free((*ref)->list); \ av_free((*ref)->refs); \ av_free(*ref); \ @@ -507,31 +535,25 @@ FORMATS_CHANGEREF(oldref, newref); } -#define SET_COMMON_FORMATS(ctx, fmts, in_fmts, out_fmts, ref_fn, unref_fn, list) \ +#define SET_COMMON_FORMATS(ctx, fmts, ref_fn, unref_fn) \ int count = 0, i; \ \ if (!fmts) \ return AVERROR(ENOMEM); \ \ for (i = 0; i < ctx->nb_inputs; i++) { \ - if (ctx->inputs[i] && !ctx->inputs[i]->out_fmts) { \ - int ret = ref_fn(fmts, &ctx->inputs[i]->out_fmts); \ + if (ctx->inputs[i] && !ctx->inputs[i]->outcfg.fmts) { \ + int ret = ref_fn(fmts, &ctx->inputs[i]->outcfg.fmts); \ if (ret < 0) { \ - unref_fn(&fmts); \ - av_freep(&fmts->list); \ - av_freep(&fmts); \ return ret; \ } \ count++; \ } \ } \ for (i = 0; i < ctx->nb_outputs; i++) { \ - if (ctx->outputs[i] && !ctx->outputs[i]->in_fmts) { \ - int ret = ref_fn(fmts, &ctx->outputs[i]->in_fmts); \ + if (ctx->outputs[i] && !ctx->outputs[i]->incfg.fmts) { \ + int ret = ref_fn(fmts, &ctx->outputs[i]->incfg.fmts); \ if (ret < 0) { \ - unref_fn(&fmts); \ - av_freep(&fmts->list); \ - av_freep(&fmts); \ return ret; \ } \ count++; \ @@ -539,25 +561,23 @@ } \ \ if (!count) { \ - av_freep(&fmts->list); \ - av_freep(&fmts->refs); \ - av_freep(&fmts); \ + unref_fn(&fmts); \ } \ \ return 0; int ff_set_common_channel_layouts(AVFilterContext *ctx, - AVFilterChannelLayouts *layouts) + AVFilterChannelLayouts *channel_layouts) { - SET_COMMON_FORMATS(ctx, layouts, in_channel_layouts, out_channel_layouts, - ff_channel_layouts_ref, ff_channel_layouts_unref, channel_layouts); + SET_COMMON_FORMATS(ctx, channel_layouts, + ff_channel_layouts_ref, ff_channel_layouts_unref); } int ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates) { - SET_COMMON_FORMATS(ctx, samplerates, in_samplerates, out_samplerates, - ff_formats_ref, ff_formats_unref, formats); + SET_COMMON_FORMATS(ctx, samplerates, + ff_formats_ref, ff_formats_unref); } /** @@ -567,23 +587,22 @@ */ int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats) { - SET_COMMON_FORMATS(ctx, formats, in_formats, out_formats, - ff_formats_ref, ff_formats_unref, formats); + SET_COMMON_FORMATS(ctx, formats, + ff_formats_ref, ff_formats_unref); } -static int default_query_formats_common(AVFilterContext *ctx, - AVFilterChannelLayouts *(layouts)(void)) +int ff_default_query_formats(AVFilterContext *ctx) { int ret; - enum AVMediaType type = ctx->inputs && ctx->inputs [0] ? ctx->inputs [0]->type : - ctx->outputs && ctx->outputs[0] ? ctx->outputs[0]->type : + enum AVMediaType type = ctx->nb_inputs ? ctx->inputs [0]->type : + ctx->nb_outputs ? ctx->outputs[0]->type : AVMEDIA_TYPE_VIDEO; ret = ff_set_common_formats(ctx, ff_all_formats(type)); if (ret < 0) return ret; if (type == AVMEDIA_TYPE_AUDIO) { - ret = ff_set_common_channel_layouts(ctx, layouts()); + ret = ff_set_common_channel_layouts(ctx, ff_all_channel_counts()); if (ret < 0) return ret; ret = ff_set_common_samplerates(ctx, ff_all_samplerates()); @@ -594,16 +613,6 @@ return 0; } -int ff_default_query_formats(AVFilterContext *ctx) -{ - return default_query_formats_common(ctx, ff_all_channel_counts); -} - -int ff_query_formats_all_layouts(AVFilterContext *ctx) -{ - return default_query_formats_common(ctx, ff_all_channel_layouts); -} - /* internal functions for parsing audio format arguments */ int ff_parse_pixel_format(enum AVPixelFormat *ret, const char *arg, void *log_ctx) @@ -621,32 +630,6 @@ return 0; } -int ff_parse_sample_format(int *ret, const char *arg, void *log_ctx) -{ - char *tail; - int sfmt = av_get_sample_fmt(arg); - if (sfmt == AV_SAMPLE_FMT_NONE) { - sfmt = strtol(arg, &tail, 0); - if (*tail || av_get_bytes_per_sample(sfmt)<=0) { - av_log(log_ctx, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg); - return AVERROR(EINVAL); - } - } - *ret = sfmt; - return 0; -} - -int ff_parse_time_base(AVRational *ret, const char *arg, void *log_ctx) -{ - AVRational r; - if(av_parse_ratio(&r, arg, INT_MAX, 0, log_ctx) < 0 ||r.num<=0 ||r.den<=0) { - av_log(log_ctx, AV_LOG_ERROR, "Invalid time base '%s'\n", arg); - return AVERROR(EINVAL); - } - *ret = r; - return 0; -} - int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx) { char *tail; @@ -679,3 +662,73 @@ return 0; } + +static int check_list(void *log, const char *name, const AVFilterFormats *fmts) +{ + unsigned i, j; + + if (!fmts) + return 0; + if (!fmts->nb_formats) { + av_log(log, AV_LOG_ERROR, "Empty %s list\n", name); + return AVERROR(EINVAL); + } + for (i = 0; i < fmts->nb_formats; i++) { + for (j = i + 1; j < fmts->nb_formats; j++) { + if (fmts->formats[i] == fmts->formats[j]) { + av_log(log, AV_LOG_ERROR, "Duplicated %s\n", name); + return AVERROR(EINVAL); + } + } + } + return 0; +} + +int ff_formats_check_pixel_formats(void *log, const AVFilterFormats *fmts) +{ + return check_list(log, "pixel format", fmts); +} + +int ff_formats_check_sample_formats(void *log, const AVFilterFormats *fmts) +{ + return check_list(log, "sample format", fmts); +} + +int ff_formats_check_sample_rates(void *log, const AVFilterFormats *fmts) +{ + if (!fmts || !fmts->nb_formats) + return 0; + return check_list(log, "sample rate", fmts); +} + +static int layouts_compatible(uint64_t a, uint64_t b) +{ + return a == b || + (KNOWN(a) && !KNOWN(b) && av_get_channel_layout_nb_channels(a) == FF_LAYOUT2COUNT(b)) || + (KNOWN(b) && !KNOWN(a) && av_get_channel_layout_nb_channels(b) == FF_LAYOUT2COUNT(a)); +} + +int ff_formats_check_channel_layouts(void *log, const AVFilterChannelLayouts *fmts) +{ + unsigned i, j; + + if (!fmts) + return 0; + if (fmts->all_layouts < fmts->all_counts) { + av_log(log, AV_LOG_ERROR, "Inconsistent generic list\n"); + return AVERROR(EINVAL); + } + if (!fmts->all_layouts && !fmts->nb_channel_layouts) { + av_log(log, AV_LOG_ERROR, "Empty channel layout list\n"); + return AVERROR(EINVAL); + } + for (i = 0; i < fmts->nb_channel_layouts; i++) { + for (j = i + 1; j < fmts->nb_channel_layouts; j++) { + if (layouts_compatible(fmts->channel_layouts[i], fmts->channel_layouts[j])) { + av_log(log, AV_LOG_ERROR, "Duplicated or redundant channel layout\n"); + return AVERROR(EINVAL); + } + } + } + return 0; +} diff -Nru ffmpeg-4.2.2/libavfilter/formats.h ffmpeg-4.4/libavfilter/formats.h --- ffmpeg-4.2.2/libavfilter/formats.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/formats.h 2021-04-08 21:28:39.000000000 +0000 @@ -20,6 +20,7 @@ #define AVFILTER_FORMATS_H #include "avfilter.h" +#include "version.h" /** * A list of supported formats for one end of a filter link. This is used @@ -82,7 +83,7 @@ * channel count with unknown disposition with the same number of channels * (e.g. AV_CH_LAYOUT_STEREO and FF_COUNT2LAYOUT(2). */ -typedef struct AVFilterChannelLayouts { +struct AVFilterChannelLayouts { uint64_t *channel_layouts; ///< list of channel layouts int nb_channel_layouts; ///< number of channel layouts char all_layouts; ///< accept any known channel layout @@ -90,7 +91,7 @@ unsigned refcount; ///< number of references to this list struct AVFilterChannelLayouts ***refs; ///< references to this list -} AVFilterChannelLayouts; +}; /** * Encode a channel count as a channel layout. @@ -109,17 +110,32 @@ (int)((l) & 0x7FFFFFFF) : 0) /** - * Return a channel layouts/samplerates list which contains the intersection of - * the layouts/samplerates of a and b. Also, all the references of a, all the - * references of b, and a and b themselves will be deallocated. - * - * If a and b do not share any common elements, neither is modified, and NULL - * is returned. - */ -AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a, - AVFilterChannelLayouts *b); -AVFilterFormats *ff_merge_samplerates(AVFilterFormats *a, - AVFilterFormats *b); + * Check the formats/samplerates lists for compatibility for merging + * without actually merging. + * + * @return 1 if they are compatible, 0 if not. + */ +int ff_can_merge_formats(const AVFilterFormats *a, const AVFilterFormats *b, + enum AVMediaType type); +int ff_can_merge_samplerates(const AVFilterFormats *a, const AVFilterFormats *b); + +/** + * Merge the formats/channel layouts/samplerates lists if they are compatible + * and update all the references of a and b to point to the combined list and + * free the old lists as needed. The combined list usually contains the + * intersection of the lists of a and b. + * + * Both a and b must have owners (i.e. refcount > 0) for these functions. + * + * @return 1 if merging succeeded, 0 if a and b are incompatible + * and negative AVERROR code on failure. + * a and b are unmodified if 0 is returned. + */ +int ff_merge_channel_layouts(AVFilterChannelLayouts *a, + AVFilterChannelLayouts *b); +int ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b, + enum AVMediaType type); +int ff_merge_samplerates(AVFilterFormats *a, AVFilterFormats *b); /** * Construct an empty AVFilterChannelLayouts/AVFilterFormats struct -- @@ -139,11 +155,11 @@ AVFilterChannelLayouts *ff_all_channel_counts(void); av_warn_unused_result -AVFilterChannelLayouts *avfilter_make_format64_list(const int64_t *fmts); - -av_warn_unused_result -AVFilterChannelLayouts *ff_make_formatu64_list(const uint64_t *fmts); +AVFilterChannelLayouts *ff_make_format64_list(const int64_t *fmts); +#if LIBAVFILTER_VERSION_MAJOR < 8 +AVFilterChannelLayouts *avfilter_make_format64_list(const int64_t *fmts); +#endif /** * A helper for query_formats() which sets all links to the same list of channel @@ -186,14 +202,6 @@ av_warn_unused_result int ff_default_query_formats(AVFilterContext *ctx); - /** - * Set the formats list to all known channel layouts. This function behaves - * like ff_default_query_formats(), except it only accepts known channel - * layouts. It should only be used with audio filters. - */ -av_warn_unused_result -int ff_query_formats_all_layouts(AVFilterContext *ctx); - /** * Create a list of supported formats. This is intended for use in * AVFilter->query_formats(). @@ -222,21 +230,20 @@ AVFilterFormats *ff_all_formats(enum AVMediaType type); /** - * Construct a formats list containing all planar sample formats. + * Construct a formats list containing all pixel formats with certain + * properties */ av_warn_unused_result -AVFilterFormats *ff_planar_sample_fmts(void); +int ff_formats_pixdesc_filter(AVFilterFormats **rfmts, unsigned want, unsigned rej); + +//* format is software, non-planar with sub-sampling +#define FF_PIX_FMT_FLAG_SW_FLAT_SUB (1 << 24) /** - * Return a format list which contains the intersection of the formats of - * a and b. Also, all the references of a, all the references of b, and - * a and b themselves will be deallocated. - * - * If a and b do not share any common formats, neither is modified, and NULL - * is returned. + * Construct a formats list containing all planar sample formats. */ -AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b, - enum AVMediaType type); +av_warn_unused_result +AVFilterFormats *ff_planar_sample_fmts(void); /** * Add *ref as a new reference to formats. @@ -284,4 +291,32 @@ */ void ff_formats_changeref(AVFilterFormats **oldref, AVFilterFormats **newref); +/** + * Check that fmts is a valid pixel formats list. + * + * In particular, check for duplicates. + */ +int ff_formats_check_pixel_formats(void *log, const AVFilterFormats *fmts); + +/** + * Check that fmts is a valid sample formats list. + * + * In particular, check for duplicates. + */ +int ff_formats_check_sample_formats(void *log, const AVFilterFormats *fmts); + +/** + * Check that fmts is a valid sample rates list. + * + * In particular, check for duplicates. + */ +int ff_formats_check_sample_rates(void *log, const AVFilterFormats *fmts); + +/** + * Check that fmts is a valid channel layouts list. + * + * In particular, check for duplicates. + */ +int ff_formats_check_channel_layouts(void *log, const AVFilterChannelLayouts *fmts); + #endif /* AVFILTER_FORMATS_H */ diff -Nru ffmpeg-4.2.2/libavfilter/f_perms.c ffmpeg-4.4/libavfilter/f_perms.c --- ffmpeg-4.2.2/libavfilter/f_perms.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_perms.c 2021-04-08 21:28:39.000000000 +0000 @@ -141,6 +141,7 @@ .inputs = aperms_inputs, .outputs = aperms_outputs, .priv_class = &aperms_class, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; #endif /* CONFIG_APERMS_FILTER */ @@ -174,5 +175,6 @@ .inputs = perms_inputs, .outputs = perms_outputs, .priv_class = &perms_class, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; #endif /* CONFIG_PERMS_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/framepool.c ffmpeg-4.4/libavfilter/framepool.c --- ffmpeg-4.2.2/libavfilter/framepool.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/framepool.c 2021-04-08 21:28:39.000000000 +0000 @@ -48,7 +48,7 @@ }; -FFFramePool *ff_frame_pool_video_init(AVBufferRef* (*alloc)(int size), +FFFramePool *ff_frame_pool_video_init(AVBufferRef* (*alloc)(buffer_size_t size), int width, int height, enum AVPixelFormat format, @@ -116,7 +116,7 @@ return NULL; } -FFFramePool *ff_frame_pool_audio_init(AVBufferRef* (*alloc)(int size), +FFFramePool *ff_frame_pool_audio_init(AVBufferRef* (*alloc)(buffer_size_t size), int channels, int nb_samples, enum AVSampleFormat format, diff -Nru ffmpeg-4.2.2/libavfilter/framepool.h ffmpeg-4.4/libavfilter/framepool.h --- ffmpeg-4.2.2/libavfilter/framepool.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/framepool.h 2021-04-08 21:28:39.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/buffer.h" #include "libavutil/frame.h" +#include "libavutil/internal.h" /** * Frame pool. This structure is opaque and not meant to be accessed @@ -43,7 +44,7 @@ * @param align buffers alignement of each frame in this pool * @return newly created video frame pool on success, NULL on error. */ -FFFramePool *ff_frame_pool_video_init(AVBufferRef* (*alloc)(int size), +FFFramePool *ff_frame_pool_video_init(AVBufferRef* (*alloc)(buffer_size_t size), int width, int height, enum AVPixelFormat format, @@ -61,7 +62,7 @@ * @param align buffers alignement of each frame in this pool * @return newly created audio frame pool on success, NULL on error. */ -FFFramePool *ff_frame_pool_audio_init(AVBufferRef* (*alloc)(int size), +FFFramePool *ff_frame_pool_audio_init(AVBufferRef* (*alloc)(buffer_size_t size), int channels, int samples, enum AVSampleFormat format, diff -Nru ffmpeg-4.2.2/libavfilter/framerate.h ffmpeg-4.4/libavfilter/framerate.h --- ffmpeg-4.2.2/libavfilter/framerate.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/framerate.h 2020-07-11 10:39:30.000000000 +0000 @@ -28,8 +28,7 @@ ptrdiff_t width, ptrdiff_t height, \ int factor1, int factor2, int half -#define BLEND_FACTOR_DEPTH8 7 -#define BLEND_FACTOR_DEPTH16 15 +#define BLEND_FACTOR_DEPTH(n) (n-1) typedef void (*blend_func)(BLEND_FUNC_PARAMS); @@ -43,6 +42,7 @@ int interp_end; ///< end of range to apply linear interpolation int line_size[4]; ///< bytes of pixel data per line for each plane + int height[4]; ///< height of each plane int vsub; AVRational srce_time_base; ///< timebase of source diff -Nru ffmpeg-4.2.2/libavfilter/framesync.c ffmpeg-4.4/libavfilter/framesync.c --- ffmpeg-4.2.2/libavfilter/framesync.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/framesync.c 2021-04-08 21:28:39.000000000 +0000 @@ -53,6 +53,13 @@ .parent_log_context_offset = OFFSET(parent), }; +const AVClass *ff_framesync_child_class_iterate(void **iter) +{ + const AVClass *c = *iter ? NULL : &framesync_class; + *iter = (void *)(uintptr_t)c; + return c; +} + enum { STATE_BOF, STATE_RUN, @@ -117,7 +124,6 @@ int ff_framesync_configure(FFFrameSync *fs) { unsigned i; - int64_t gcd, lcm; if (!fs->opt_repeatlast || fs->opt_eof_action == EOF_ACTION_PASS) { fs->opt_repeatlast = 0; @@ -142,17 +148,8 @@ for (i = 0; i < fs->nb_in; i++) { if (fs->in[i].sync) { if (fs->time_base.num) { - gcd = av_gcd(fs->time_base.den, fs->in[i].time_base.den); - lcm = (fs->time_base.den / gcd) * fs->in[i].time_base.den; - if (lcm < AV_TIME_BASE / 2) { - fs->time_base.den = lcm; - fs->time_base.num = av_gcd(fs->time_base.num, - fs->in[i].time_base.num); - } else { - fs->time_base.num = 1; - fs->time_base.den = AV_TIME_BASE; - break; - } + fs->time_base = av_gcd_q(fs->time_base, fs->in[i].time_base, + AV_TIME_BASE / 2, AV_TIME_BASE_Q); } else { fs->time_base = fs->in[i].time_base; } diff -Nru ffmpeg-4.2.2/libavfilter/framesync.h ffmpeg-4.4/libavfilter/framesync.h --- ffmpeg-4.2.2/libavfilter/framesync.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/framesync.h 2021-04-08 21:28:39.000000000 +0000 @@ -297,6 +297,8 @@ */ int ff_framesync_dualinput_get_writable(FFFrameSync *fs, AVFrame **f0, AVFrame **f1); +const AVClass *ff_framesync_child_class_iterate(void **iter); + #define FRAMESYNC_DEFINE_CLASS(name, context, field) \ static int name##_framesync_preinit(AVFilterContext *ctx) { \ context *s = ctx->priv; \ @@ -318,6 +320,7 @@ .version = LIBAVUTIL_VERSION_INT, \ .category = AV_CLASS_CATEGORY_FILTER, \ .child_class_next = name##_child_class_next, \ + .child_class_iterate = ff_framesync_child_class_iterate, \ .child_next = name##_child_next, \ } diff -Nru ffmpeg-4.2.2/libavfilter/f_reverse.c ffmpeg-4.4/libavfilter/f_reverse.c --- ffmpeg-4.2.2/libavfilter/f_reverse.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_reverse.c 2020-07-11 10:39:30.000000000 +0000 @@ -58,6 +58,11 @@ { ReverseContext *s = ctx->priv; + while (s->nb_frames > 0) { + av_frame_free(&s->frames[s->nb_frames - 1]); + s->nb_frames--; + } + av_freep(&s->pts); av_freep(&s->frames); } @@ -103,6 +108,7 @@ AVFrame *out = s->frames[s->nb_frames - 1]; out->pts = s->pts[s->flush_idx++]; ret = ff_filter_frame(outlink, out); + s->frames[s->nb_frames - 1] = NULL; s->nb_frames--; } @@ -262,6 +268,7 @@ else reverse_samples_packed(out); ret = ff_filter_frame(outlink, out); + s->frames[s->nb_frames - 1] = NULL; s->nb_frames--; } diff -Nru ffmpeg-4.2.2/libavfilter/f_select.c ffmpeg-4.4/libavfilter/f_select.c --- ffmpeg-4.2.2/libavfilter/f_select.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_select.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,8 +26,10 @@ #include "libavutil/avstring.h" #include "libavutil/eval.h" #include "libavutil/fifo.h" +#include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/opt.h" +#include "libavutil/pixdesc.h" #include "avfilter.h" #include "audio.h" #include "formats.h" @@ -144,6 +146,10 @@ char *expr_str; AVExpr *expr; double var_values[VAR_VARS_NB]; + int bitdepth; + int nb_planes; + ptrdiff_t width[4]; + ptrdiff_t height[4]; int do_scene_detect; ///< 1 if the expression requires scene detection variables, 0 otherwise ff_scene_sad_fn sad; ///< Sum of the absolute difference function (scene detect only) double prev_mafd; ///< previous MAFD (scene detect only) @@ -202,6 +208,21 @@ static int config_input(AVFilterLink *inlink) { SelectContext *select = inlink->dst->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) && + (desc->flags & AV_PIX_FMT_FLAG_PLANAR) && + desc->nb_components >= 3; + + select->bitdepth = desc->comp[0].depth; + select->nb_planes = is_yuv ? 1 : av_pix_fmt_count_planes(inlink->format); + + for (int plane = 0; plane < select->nb_planes; plane++) { + ptrdiff_t line_size = av_image_get_linesize(inlink->format, inlink->w, plane); + int vsub = desc->log2_chroma_h; + + select->width[plane] = line_size >> (select->bitdepth > 8); + select->height[plane] = plane == 1 || plane == 2 ? AV_CEIL_RSHIFT(inlink->h, vsub) : inlink->h; + } select->var_values[VAR_N] = 0.0; select->var_values[VAR_SELECTED_N] = 0.0; @@ -242,7 +263,7 @@ inlink->type == AVMEDIA_TYPE_AUDIO ? inlink->sample_rate : NAN; if (CONFIG_SELECT_FILTER && select->do_scene_detect) { - select->sad = ff_scene_sad_get_fn(8); + select->sad = ff_scene_sad_get_fn(select->bitdepth == 8 ? 8 : 16); if (!select->sad) return AVERROR(EINVAL); } @@ -258,12 +279,21 @@ if (prev_picref && frame->height == prev_picref->height && frame->width == prev_picref->width) { - uint64_t sad; + uint64_t sad = 0; double mafd, diff; + uint64_t count = 0; + + for (int plane = 0; plane < select->nb_planes; plane++) { + uint64_t plane_sad; + select->sad(prev_picref->data[plane], prev_picref->linesize[plane], + frame->data[plane], frame->linesize[plane], + select->width[plane], select->height[plane], &plane_sad); + sad += plane_sad; + count += select->width[plane] * select->height[plane]; + } - select->sad(prev_picref->data[0], prev_picref->linesize[0], frame->data[0], frame->linesize[0], frame->width * 3, frame->height, &sad); emms_c(); - mafd = (double)sad / (frame->width * 3 * frame->height); + mafd = (double)sad / count / (1ULL << (select->bitdepth - 8)); diff = fabs(mafd - select->prev_mafd); ret = av_clipf(FFMIN(mafd, diff) / 100., 0, 1); select->prev_mafd = mafd; @@ -295,9 +325,6 @@ return NAN; } -#define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d)) -#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) - static void select_frame(AVFilterContext *ctx, AVFrame *frame) { SelectContext *select = ctx->priv; @@ -472,7 +499,11 @@ } else { int ret; static const enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, AV_PIX_FMT_RGBA, + AV_PIX_FMT_ABGR, AV_PIX_FMT_BGRA, AV_PIX_FMT_GRAY8, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_NONE }; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); diff -Nru ffmpeg-4.2.2/libavfilter/f_sendcmd.c ffmpeg-4.4/libavfilter/f_sendcmd.c --- ffmpeg-4.2.2/libavfilter/f_sendcmd.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_sendcmd.c 2021-04-08 21:28:39.000000000 +0000 @@ -25,6 +25,7 @@ #include "libavutil/avstring.h" #include "libavutil/bprint.h" +#include "libavutil/eval.h" #include "libavutil/file.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" @@ -35,10 +36,33 @@ #define COMMAND_FLAG_ENTER 1 #define COMMAND_FLAG_LEAVE 2 +#define COMMAND_FLAG_EXPR 4 + +static const char *const var_names[] = { + "N", /* frame number */ + "T", /* frame time in seconds */ + "POS", /* original position in the file of the frame */ + "PTS", /* frame pts */ + "TS", /* interval start time in seconds */ + "TE", /* interval end time in seconds */ + "TI", /* interval interpolated value: TI = (T - TS) / (TE - TS) */ + NULL +}; + +enum var_name { + VAR_N, + VAR_T, + VAR_POS, + VAR_PTS, + VAR_TS, + VAR_TE, + VAR_TI, + VAR_VARS_NB +}; static inline char *make_command_flags_str(AVBPrint *pbuf, int flags) { - static const char * const flag_strings[] = { "enter", "leave" }; + static const char * const flag_strings[] = { "enter", "leave", "expr" }; int i, is_first = 1; av_bprint_init(pbuf, 0, AV_BPRINT_SIZE_AUTOMATIC); @@ -129,6 +153,7 @@ if (!strncmp(*buf, "enter", strlen("enter"))) cmd->flags |= COMMAND_FLAG_ENTER; else if (!strncmp(*buf, "leave", strlen("leave"))) cmd->flags |= COMMAND_FLAG_LEAVE; + else if (!strncmp(*buf, "expr", strlen("expr"))) cmd->flags |= COMMAND_FLAG_EXPR; else { char flag_buf[64]; av_strlcpy(flag_buf, *buf, sizeof(flag_buf)); @@ -476,6 +501,8 @@ flags += COMMAND_FLAG_LEAVE; interval->enabled = 0; } + if (interval->enabled) + flags += COMMAND_FLAG_EXPR; if (flags) { AVBPrint pbuf; @@ -487,19 +514,49 @@ for (j = 0; flags && j < interval->nb_commands; j++) { Command *cmd = &interval->commands[j]; + char *cmd_arg = cmd->arg; char buf[1024]; if (cmd->flags & flags) { + if (cmd->flags & COMMAND_FLAG_EXPR) { + double var_values[VAR_VARS_NB], res; + double start = TS2T(interval->start_ts, AV_TIME_BASE_Q); + double end = TS2T(interval->end_ts, AV_TIME_BASE_Q); + double current = TS2T(ref->pts, inlink->time_base); + + var_values[VAR_N] = inlink->frame_count_in; + var_values[VAR_POS] = ref->pkt_pos == -1 ? NAN : ref->pkt_pos; + var_values[VAR_PTS] = TS2D(ref->pts); + var_values[VAR_T] = current; + var_values[VAR_TS] = start; + var_values[VAR_TE] = end; + var_values[VAR_TI] = (current - start) / (end - start); + + if ((ret = av_expr_parse_and_eval(&res, cmd->arg, var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, NULL)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid expression '%s' for command argument.\n", cmd->arg); + av_frame_free(&ref); + return AVERROR(EINVAL); + } + + cmd_arg = av_asprintf("%g", res); + if (!cmd_arg) { + av_frame_free(&ref); + return AVERROR(ENOMEM); + } + } av_log(ctx, AV_LOG_VERBOSE, "Processing command #%d target:%s command:%s arg:%s\n", - cmd->index, cmd->target, cmd->command, cmd->arg); + cmd->index, cmd->target, cmd->command, cmd_arg); ret = avfilter_graph_send_command(inlink->graph, - cmd->target, cmd->command, cmd->arg, + cmd->target, cmd->command, cmd_arg, buf, sizeof(buf), AVFILTER_CMD_FLAG_ONE); av_log(ctx, AV_LOG_VERBOSE, "Command reply for command #%d: ret:%s res:%s\n", cmd->index, av_err2str(ret), buf); + if (cmd->flags & COMMAND_FLAG_EXPR) + av_freep(&cmd_arg); } } } diff -Nru ffmpeg-4.2.2/libavfilter/f_sidedata.c ffmpeg-4.4/libavfilter/f_sidedata.c --- ffmpeg-4.2.2/libavfilter/f_sidedata.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_sidedata.c 2021-04-08 21:28:39.000000000 +0000 @@ -39,7 +39,7 @@ const AVClass *class; int mode; - enum AVFrameSideDataType type; + int type; // enum AVFrameSideDataType or -1 for delete side data mode } SideDataContext; #define OFFSET(x) offsetof(SideDataContext, x) @@ -71,6 +71,7 @@ { "S12M_TIMECOD", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_S12M_TIMECODE }, 0, 0, FLAGS, "type" }, \ { "DYNAMIC_HDR_PLUS", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_DYNAMIC_HDR_PLUS }, 0, 0, FLAGS, "type" }, \ { "REGIONS_OF_INTEREST", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_REGIONS_OF_INTEREST }, 0, 0, FLAGS, "type" }, \ + { "SEI_UNREGISTERED", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_SEI_UNREGISTERED }, 0, 0, FLAGS, "type" }, \ { NULL } \ } #else @@ -99,6 +100,7 @@ { "S12M_TIMECOD", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_S12M_TIMECODE }, 0, 0, FLAGS, "type" }, \ { "DYNAMIC_HDR_PLUS", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_DYNAMIC_HDR_PLUS }, 0, 0, FLAGS, "type" }, \ { "REGIONS_OF_INTEREST", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_REGIONS_OF_INTEREST }, 0, 0, FLAGS, "type" }, \ + { "SEI_UNREGISTERED", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_SEI_UNREGISTERED }, 0, 0, FLAGS, "type" }, \ { NULL } \ } #endif diff -Nru ffmpeg-4.2.2/libavfilter/f_streamselect.c ffmpeg-4.4/libavfilter/f_streamselect.c --- ffmpeg-4.2.2/libavfilter/f_streamselect.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_streamselect.c 2020-07-11 10:39:30.000000000 +0000 @@ -21,6 +21,7 @@ #include "libavutil/opt.h" #include "avfilter.h" #include "audio.h" +#include "filters.h" #include "formats.h" #include "framesync.h" #include "internal.h" @@ -40,9 +41,10 @@ #define OFFSET(x) offsetof(StreamSelectContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +#define TFLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption streamselect_options[] = { { "inputs", "number of input streams", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags=FLAGS }, - { "map", "input indexes to remap to outputs", OFFSET(map_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags=FLAGS }, + { "map", "input indexes to remap to outputs", OFFSET(map_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags=TFLAGS }, { NULL } }; @@ -53,7 +55,7 @@ AVFilterContext *ctx = fs->parent; StreamSelectContext *s = fs->opaque; AVFrame **in = s->frames; - int i, j, ret = 0; + int i, j, ret = 0, have_out = 0; for (i = 0; i < ctx->nb_inputs; i++) { if ((ret = ff_framesync_get_frame(&s->fs, i, &in[i], 0)) < 0) @@ -75,12 +77,15 @@ out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, ctx->outputs[i]->time_base); s->last_pts[j] = in[j]->pts; ret = ff_filter_frame(ctx->outputs[i], out); + have_out = 1; if (ret < 0) return ret; } } } + if (!have_out) + ff_filter_set_ready(ctx, 100); return ret; } @@ -290,6 +295,12 @@ av_freep(&s->map); av_freep(&s->frames); ff_framesync_uninit(&s->fs); + + for (int i = 0; i < ctx->nb_inputs; i++) + av_freep(&ctx->input_pads[i].name); + + for (int i = 0; i < ctx->nb_outputs; i++) + av_freep(&ctx->output_pads[i].name); } static int query_formats(AVFilterContext *ctx) diff -Nru ffmpeg-4.2.2/libavfilter/f_zmq.c ffmpeg-4.4/libavfilter/f_zmq.c --- ffmpeg-4.2.2/libavfilter/f_zmq.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/f_zmq.c 2020-07-11 10:39:30.000000000 +0000 @@ -139,7 +139,7 @@ ret = AVERROR(ENOMEM); goto end; } - memcpy(*buf, zmq_msg_data(&msg), *buf_size); + memcpy(*buf, zmq_msg_data(&msg), *buf_size - 1); (*buf)[*buf_size-1] = 0; end: diff -Nru ffmpeg-4.2.2/libavfilter/gblur.h ffmpeg-4.4/libavfilter/gblur.h --- ffmpeg-4.2.2/libavfilter/gblur.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/gblur.h 2021-04-08 21:28:39.000000000 +0000 @@ -37,6 +37,7 @@ int steps; int planes; + int flt; int depth; int planewidth[4]; int planeheight[4]; @@ -49,7 +50,9 @@ float nuV; int nb_planes; void (*horiz_slice)(float *buffer, int width, int height, int steps, float nu, float bscale); + void (*postscale_slice)(float *buffer, int length, float postscale, float min, float max); } GBlurContext; + void ff_gblur_init(GBlurContext *s); void ff_gblur_init_x86(GBlurContext *s); #endif diff -Nru ffmpeg-4.2.2/libavfilter/glslang.cpp ffmpeg-4.4/libavfilter/glslang.cpp --- ffmpeg-4.2.2/libavfilter/glslang.cpp 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/glslang.cpp 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,241 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 -Nru ffmpeg-4.2.2/libavfilter/glslang.h ffmpeg-4.4/libavfilter/glslang.h --- ffmpeg-4.2.2/libavfilter/glslang.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/glslang.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_GLSLANG_H +#define AVFILTER_GLSLANG_H + +#include + +#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, +}; + +/* 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 -Nru ffmpeg-4.2.2/libavfilter/graphdump.c ffmpeg-4.4/libavfilter/graphdump.c --- ffmpeg-4.2.2/libavfilter/graphdump.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/graphdump.c 2020-07-11 10:39:30.000000000 +0000 @@ -154,7 +154,7 @@ char *avfilter_graph_dump(AVFilterGraph *graph, const char *options) { AVBPrint buf; - char *dump; + char *dump = NULL; av_bprint_init(&buf, 0, AV_BPRINT_SIZE_COUNT_ONLY); avfilter_graph_dump_to_buf(&buf, graph); diff -Nru ffmpeg-4.2.2/libavfilter/graphparser.c ffmpeg-4.4/libavfilter/graphparser.c --- ffmpeg-4.2.2/libavfilter/graphparser.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/graphparser.c 2021-04-08 21:28:27.000000000 +0000 @@ -63,7 +63,7 @@ name = av_get_token(buf, "]"); if (!name) - goto fail; + return NULL; if (!name[0]) { av_log(log_ctx, AV_LOG_ERROR, @@ -71,12 +71,14 @@ goto fail; } - if (*(*buf)++ != ']') { + if (**buf != ']') { av_log(log_ctx, AV_LOG_ERROR, "Mismatched '[' found in the following: \"%s\".\n", start); fail: av_freep(&name); + return NULL; } + (*buf)++; return name; } @@ -184,9 +186,16 @@ char *name = av_get_token(buf, "=,;["); int ret; + if (!name) + return AVERROR(ENOMEM); + if (**buf == '=') { (*buf)++; opts = av_get_token(buf, "[],;"); + if (!opts) { + av_free(name); + return AVERROR(ENOMEM); + } } ret = create_filter(filt_ctx, graph, index, name, opts, log_ctx); @@ -303,8 +312,10 @@ char *name = parse_link_name(buf, log_ctx); AVFilterInOut *match; - if (!name) + if (!name) { + avfilter_inout_free(&parsed_inputs); return AVERROR(EINVAL); + } /* First check if the label is not in the open_outputs list */ match = extract_inout(name, open_outputs); @@ -314,6 +325,7 @@ } else { /* Not in the list, so add it as an input */ if (!(match = av_mallocz(sizeof(AVFilterInOut)))) { + avfilter_inout_free(&parsed_inputs); av_free(name); return AVERROR(ENOMEM); } @@ -360,15 +372,14 @@ match = extract_inout(name, open_inputs); if (match) { - if ((ret = link_filter(input->filter_ctx, input->pad_idx, - match->filter_ctx, match->pad_idx, log_ctx)) < 0) { - av_free(name); - return ret; - } + ret = link_filter(input->filter_ctx, input->pad_idx, + match->filter_ctx, match->pad_idx, log_ctx); av_freep(&match->name); av_freep(&name); av_freep(&match); av_freep(&input); + if (ret < 0) + return ret; } else { /* Not in the list, so add the first input as an open_output */ input->name = name; diff -Nru ffmpeg-4.2.2/libavfilter/hflip.h ffmpeg-4.4/libavfilter/hflip.h --- ffmpeg-4.2.2/libavfilter/hflip.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/hflip.h 2021-04-08 21:28:39.000000000 +0000 @@ -27,6 +27,7 @@ typedef struct FlipContext { const AVClass *class; int max_step[4]; ///< max pixel step for each plane, expressed as a number of bytes + int bayer_plus1; ///< 1 .. not a Bayer input format, 2 .. Bayer input format int planewidth[4]; ///< width of each plane int planeheight[4]; ///< height of each plane diff -Nru ffmpeg-4.2.2/libavfilter/internal.h ffmpeg-4.4/libavfilter/internal.h --- ffmpeg-4.2.2/libavfilter/internal.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/internal.h 2021-04-08 21:28:39.000000000 +0000 @@ -93,17 +93,6 @@ int (*filter_frame)(AVFilterLink *link, AVFrame *frame); /** - * Frame poll callback. This returns the number of immediately available - * samples. It should return a positive value if the next request_frame() - * is guaranteed to return one frame (with no delay). - * - * Defaults to just calling the source poll_frame() method. - * - * Output pads only. - */ - int (*poll_frame)(AVFilterLink *link); - - /** * Frame request callback. A call to this should result in some progress * towards producing output over the given link. This should return zero * on success, and another value on error. @@ -129,14 +118,6 @@ int (*config_props)(AVFilterLink *link); /** - * The filter expects a fifo to be inserted on its input link, - * typically because it has a delay. - * - * input pads only. - */ - int needs_fifo; - - /** * The filter expects writable frames from its input link, * duplicating data buffers if needed. * @@ -191,28 +172,6 @@ int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx); /** - * Parse a time base. - * - * @param ret unsigned AVRational pointer to where the value should be written - * @param arg string to parse - * @param log_ctx log context - * @return >= 0 in case of success, a negative AVERROR code on error - */ -av_warn_unused_result -int ff_parse_time_base(AVRational *ret, const char *arg, void *log_ctx); - -/** - * Parse a sample format name or a corresponding integer representation. - * - * @param ret integer pointer to where the value should be written - * @param arg string to parse - * @param log_ctx log context - * @return >= 0 in case of success, a negative AVERROR code on error - */ -av_warn_unused_result -int ff_parse_sample_format(int *ret, const char *arg, void *log_ctx); - -/** * Parse a channel layout or a corresponding integer representation. * * @param ret 64bit integer pointer to where the value should be written. @@ -245,6 +204,10 @@ void ff_command_queue_pop(AVFilterContext *filter); +#define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d)) +#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) +#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts) * av_q2d(tb)) + /* misc trace functions */ #define FF_TPRINTF_START(ctx, func) ff_tlog(NULL, "%-16s: ", #func) @@ -290,15 +253,6 @@ } /** - * Poll a frame from the filter chain. - * - * @param link the input link - * @return the number of immediately available frames, a negative - * number in case of error - */ -int ff_poll_frame(AVFilterLink *link); - -/** * Request an input frame from the filter at the other end of the link. * * This function must not be used by filters using the activate callback, @@ -412,6 +366,15 @@ int ff_filter_get_nb_threads(AVFilterContext *ctx); /** + * Generic processing of user supplied commands that are set + * in the same way as the filter options. + * NOTE: 'enable' option is handled separately, and not by + * this function. + */ +int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, + const char *arg, char *res, int res_len, int flags); + +/** * Perform any additional setup required for hardware frames. * * link->hw_frames_ctx must be set before calling this function. diff -Nru ffmpeg-4.2.2/libavfilter/lavfutils.c ffmpeg-4.4/libavfilter/lavfutils.c --- ffmpeg-4.2.2/libavfilter/lavfutils.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/lavfutils.c 2021-04-08 21:28:39.000000000 +0000 @@ -19,6 +19,7 @@ */ #include "libavutil/imgutils.h" +#include "libavformat/avformat.h" #include "lavfutils.h" int ff_load_image(uint8_t *data[4], int linesize[4], @@ -27,16 +28,14 @@ { AVInputFormat *iformat = NULL; AVFormatContext *format_ctx = NULL; - AVCodec *codec; - AVCodecContext *codec_ctx; + const AVCodec *codec; + AVCodecContext *codec_ctx = NULL; AVCodecParameters *par; - AVFrame *frame; - int frame_decoded, ret = 0; + AVFrame *frame = NULL; + int ret = 0; AVPacket pkt; AVDictionary *opt=NULL; - av_init_packet(&pkt); - iformat = av_find_input_format("image2pipe"); if ((ret = avformat_open_input(&format_ctx, filename, iformat, NULL)) < 0) { av_log(log_ctx, AV_LOG_ERROR, @@ -46,7 +45,7 @@ if ((ret = avformat_find_stream_info(format_ctx, NULL)) < 0) { av_log(log_ctx, AV_LOG_ERROR, "Find stream info failed\n"); - return ret; + goto end; } par = format_ctx->streams[0]->codecpar; @@ -88,11 +87,16 @@ goto end; } - ret = avcodec_decode_video2(codec_ctx, frame, &frame_decoded, &pkt); - if (ret < 0 || !frame_decoded) { + ret = avcodec_send_packet(codec_ctx, &pkt); + av_packet_unref(&pkt); + if (ret < 0) { + av_log(log_ctx, AV_LOG_ERROR, "Error submitting a packet to decoder\n"); + goto end; + } + + ret = avcodec_receive_frame(codec_ctx, frame); + if (ret < 0) { av_log(log_ctx, AV_LOG_ERROR, "Failed to decode image from file\n"); - if (ret >= 0) - ret = -1; goto end; } @@ -107,7 +111,6 @@ av_image_copy(data, linesize, (const uint8_t **)frame->data, frame->linesize, *pix_fmt, *w, *h); end: - av_packet_unref(&pkt); avcodec_free_context(&codec_ctx); avformat_close_input(&format_ctx); av_frame_free(&frame); diff -Nru ffmpeg-4.2.2/libavfilter/lavfutils.h ffmpeg-4.4/libavfilter/lavfutils.h --- ffmpeg-4.2.2/libavfilter/lavfutils.h 2016-03-29 02:25:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/lavfutils.h 2021-04-08 21:28:39.000000000 +0000 @@ -24,7 +24,8 @@ #ifndef AVFILTER_LAVFUTILS_H #define AVFILTER_LAVFUTILS_H -#include "libavformat/avformat.h" +#include +#include "libavutil/pixfmt.h" /** * Load image from filename and put the resulting image in data. diff -Nru ffmpeg-4.2.2/libavfilter/Makefile ffmpeg-4.4/libavfilter/Makefile --- ffmpeg-4.2.2/libavfilter/Makefile 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/Makefile 2021-04-08 21:28:39.000000000 +0000 @@ -26,9 +26,9 @@ # subsystems OBJS-$(CONFIG_QSVVPP) += qsvvpp.o -DNN-OBJS-$(CONFIG_LIBTENSORFLOW) += dnn_backend_tf.o -OBJS-$(CONFIG_DNN) += dnn_interface.o dnn_backend_native.o $(DNN-OBJS-yes) OBJS-$(CONFIG_SCENE_SAD) += scene_sad.o +OBJS-$(CONFIG_DNN) += dnn_filter_common.o +include $(SRC_PATH)/libavfilter/dnn/Makefile # audio filters OBJS-$(CONFIG_ABENCH_FILTER) += f_bench.o @@ -42,15 +42,18 @@ OBJS-$(CONFIG_ADECLICK_FILTER) += af_adeclick.o OBJS-$(CONFIG_ADECLIP_FILTER) += af_adeclick.o OBJS-$(CONFIG_ADELAY_FILTER) += af_adelay.o +OBJS-$(CONFIG_ADENORM_FILTER) += af_adenorm.o OBJS-$(CONFIG_ADERIVATIVE_FILTER) += af_aderivative.o OBJS-$(CONFIG_AECHO_FILTER) += af_aecho.o OBJS-$(CONFIG_AEMPHASIS_FILTER) += af_aemphasis.o OBJS-$(CONFIG_AEVAL_FILTER) += aeval.o +OBJS-$(CONFIG_AEXCITER_FILTER) += af_aexciter.o OBJS-$(CONFIG_AFADE_FILTER) += af_afade.o OBJS-$(CONFIG_AFFTDN_FILTER) += af_afftdn.o OBJS-$(CONFIG_AFFTFILT_FILTER) += af_afftfilt.o OBJS-$(CONFIG_AFIR_FILTER) += af_afir.o OBJS-$(CONFIG_AFORMAT_FILTER) += af_aformat.o +OBJS-$(CONFIG_AFREQSHIFT_FILTER) += af_afreqshift.o OBJS-$(CONFIG_AGATE_FILTER) += af_agate.o OBJS-$(CONFIG_AIIR_FILTER) += af_aiir.o OBJS-$(CONFIG_AINTEGRAL_FILTER) += af_aderivative.o @@ -64,14 +67,17 @@ OBJS-$(CONFIG_AMULTIPLY_FILTER) += af_amultiply.o OBJS-$(CONFIG_ANEQUALIZER_FILTER) += af_anequalizer.o OBJS-$(CONFIG_ANLMDN_FILTER) += af_anlmdn.o +OBJS-$(CONFIG_ANLMS_FILTER) += af_anlms.o OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o OBJS-$(CONFIG_APAD_FILTER) += af_apad.o OBJS-$(CONFIG_APERMS_FILTER) += f_perms.o OBJS-$(CONFIG_APHASER_FILTER) += af_aphaser.o generate_wave_table.o +OBJS-$(CONFIG_APHASESHIFT_FILTER) += af_afreqshift.o OBJS-$(CONFIG_APULSATOR_FILTER) += af_apulsator.o OBJS-$(CONFIG_AREALTIME_FILTER) += f_realtime.o OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o OBJS-$(CONFIG_AREVERSE_FILTER) += f_reverse.o +OBJS-$(CONFIG_ARNNDN_FILTER) += af_arnndn.o OBJS-$(CONFIG_ASELECT_FILTER) += f_select.o OBJS-$(CONFIG_ASENDCMD_FILTER) += f_sendcmd.o OBJS-$(CONFIG_ASETNSAMPLES_FILTER) += af_asetnsamples.o @@ -85,8 +91,14 @@ OBJS-$(CONFIG_ASR_FILTER) += af_asr.o OBJS-$(CONFIG_ASTATS_FILTER) += af_astats.o OBJS-$(CONFIG_ASTREAMSELECT_FILTER) += f_streamselect.o framesync.o +OBJS-$(CONFIG_ASUBBOOST_FILTER) += af_asubboost.o +OBJS-$(CONFIG_ASUBCUT_FILTER) += af_asupercut.o +OBJS-$(CONFIG_ASUPERCUT_FILTER) += af_asupercut.o +OBJS-$(CONFIG_ASUPERPASS_FILTER) += af_asupercut.o +OBJS-$(CONFIG_ASUPERSTOP_FILTER) += af_asupercut.o OBJS-$(CONFIG_ATEMPO_FILTER) += af_atempo.o OBJS-$(CONFIG_ATRIM_FILTER) += trim.o +OBJS-$(CONFIG_AXCORRELATE_FILTER) += af_axcorrelate.o OBJS-$(CONFIG_AZMQ_FILTER) += f_zmq.o OBJS-$(CONFIG_BANDPASS_FILTER) += af_biquads.o OBJS-$(CONFIG_BANDREJECT_FILTER) += af_biquads.o @@ -131,6 +143,7 @@ OBJS-$(CONFIG_SILENCEDETECT_FILTER) += af_silencedetect.o OBJS-$(CONFIG_SILENCEREMOVE_FILTER) += af_silenceremove.o OBJS-$(CONFIG_SOFALIZER_FILTER) += af_sofalizer.o +OBJS-$(CONFIG_SPEECHNORM_FILTER) += af_speechnorm.o OBJS-$(CONFIG_STEREOTOOLS_FILTER) += af_stereotools.o OBJS-$(CONFIG_STEREOWIDEN_FILTER) += af_stereowiden.o OBJS-$(CONFIG_SUPEREQUALIZER_FILTER) += af_superequalizer.o @@ -142,6 +155,7 @@ OBJS-$(CONFIG_VOLUMEDETECT_FILTER) += af_volumedetect.o OBJS-$(CONFIG_AEVALSRC_FILTER) += aeval.o +OBJS-$(CONFIG_AFIRSRC_FILTER) += asrc_afirsrc.o OBJS-$(CONFIG_ANOISESRC_FILTER) += asrc_anoisesrc.o OBJS-$(CONFIG_ANULLSRC_FILTER) += asrc_anullsrc.o OBJS-$(CONFIG_FLITE_FILTER) += asrc_flite.o @@ -152,32 +166,41 @@ OBJS-$(CONFIG_ANULLSINK_FILTER) += asink_anullsink.o # video filters +OBJS-$(CONFIG_ADDROI_FILTER) += vf_addroi.o OBJS-$(CONFIG_ALPHAEXTRACT_FILTER) += vf_extractplanes.o -OBJS-$(CONFIG_ALPHAMERGE_FILTER) += vf_alphamerge.o +OBJS-$(CONFIG_ALPHAMERGE_FILTER) += vf_alphamerge.o framesync.o OBJS-$(CONFIG_AMPLIFY_FILTER) += vf_amplify.o OBJS-$(CONFIG_ASS_FILTER) += vf_subtitles.o OBJS-$(CONFIG_ATADENOISE_FILTER) += vf_atadenoise.o OBJS-$(CONFIG_AVGBLUR_FILTER) += vf_avgblur.o OBJS-$(CONFIG_AVGBLUR_OPENCL_FILTER) += vf_avgblur_opencl.o opencl.o \ opencl/avgblur.o boxblur.o +OBJS-$(CONFIG_AVGBLUR_VULKAN_FILTER) += vf_avgblur_vulkan.o vulkan.o OBJS-$(CONFIG_BBOX_FILTER) += bbox.o vf_bbox.o OBJS-$(CONFIG_BENCH_FILTER) += f_bench.o +OBJS-$(CONFIG_BILATERAL_FILTER) += vf_bilateral.o 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_BM3D_FILTER) += vf_bm3d.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_CHROMAHOLD_FILTER) += vf_chromakey.o OBJS-$(CONFIG_CHROMAKEY_FILTER) += vf_chromakey.o +OBJS-$(CONFIG_CHROMANR_FILTER) += vf_chromanr.o OBJS-$(CONFIG_CHROMASHIFT_FILTER) += vf_chromashift.o OBJS-$(CONFIG_CIESCOPE_FILTER) += vf_ciescope.o -OBJS-$(CONFIG_CODECVIEW_FILTER) += vf_codecview.o +OBJS-$(CONFIG_CODECVIEW_FILTER) += vf_codecview.o qp_table.o OBJS-$(CONFIG_COLORBALANCE_FILTER) += vf_colorbalance.o OBJS-$(CONFIG_COLORCHANNELMIXER_FILTER) += vf_colorchannelmixer.o +OBJS-$(CONFIG_COLORCONTRAST_FILTER) += vf_colorcontrast.o +OBJS-$(CONFIG_COLORCORRECT_FILTER) += vf_colorcorrect.o +OBJS-$(CONFIG_COLORIZE_FILTER) += vf_colorize.o OBJS-$(CONFIG_COLORKEY_FILTER) += vf_colorkey.o OBJS-$(CONFIG_COLORKEY_OPENCL_FILTER) += vf_colorkey_opencl.o opencl.o \ opencl/colorkey.o @@ -185,6 +208,7 @@ OBJS-$(CONFIG_COLORLEVELS_FILTER) += vf_colorlevels.o OBJS-$(CONFIG_COLORMATRIX_FILTER) += vf_colormatrix.o OBJS-$(CONFIG_COLORSPACE_FILTER) += vf_colorspace.o colorspace.o colorspacedsp.o +OBJS-$(CONFIG_COLORTEMPERATURE_FILTER) += vf_colortemperature.o OBJS-$(CONFIG_CONVOLUTION_FILTER) += vf_convolution.o OBJS-$(CONFIG_CONVOLUTION_OPENCL_FILTER) += vf_convolution_opencl.o opencl.o \ opencl/convolution.o @@ -197,6 +221,7 @@ OBJS-$(CONFIG_CUE_FILTER) += f_cue.o OBJS-$(CONFIG_CURVES_FILTER) += vf_curves.o OBJS-$(CONFIG_DATASCOPE_FILTER) += vf_datascope.o +OBJS-$(CONFIG_DBLUR_FILTER) += vf_dblur.o OBJS-$(CONFIG_DCTDNOIZ_FILTER) += vf_dctdnoiz.o OBJS-$(CONFIG_DEBAND_FILTER) += vf_deband.o OBJS-$(CONFIG_DEBLOCK_FILTER) += vf_deblock.o @@ -211,6 +236,8 @@ OBJS-$(CONFIG_DEJUDDER_FILTER) += vf_dejudder.o OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o OBJS-$(CONFIG_DENOISE_VAAPI_FILTER) += vf_misc_vaapi.o vaapi_vpp.o +OBJS-$(CONFIG_DESHAKE_OPENCL_FILTER) += vf_deshake_opencl.o opencl.o \ + opencl/deshake.o OBJS-$(CONFIG_DESHAKE_FILTER) += vf_deshake.o OBJS-$(CONFIG_DESPILL_FILTER) += vf_despill.o OBJS-$(CONFIG_DETELECINE_FILTER) += vf_detelecine.o @@ -218,6 +245,7 @@ OBJS-$(CONFIG_DILATION_OPENCL_FILTER) += vf_neighbor_opencl.o opencl.o \ opencl/neighbor.o OBJS-$(CONFIG_DISPLACE_FILTER) += vf_displace.o framesync.o +OBJS-$(CONFIG_DNN_PROCESSING_FILTER) += vf_dnn_processing.o OBJS-$(CONFIG_DOUBLEWEAVE_FILTER) += vf_weave.o OBJS-$(CONFIG_DRAWBOX_FILTER) += vf_drawbox.o OBJS-$(CONFIG_DRAWGRAPH_FILTER) += f_drawgraph.o @@ -226,10 +254,13 @@ OBJS-$(CONFIG_EDGEDETECT_FILTER) += vf_edgedetect.o OBJS-$(CONFIG_ELBG_FILTER) += vf_elbg.o OBJS-$(CONFIG_ENTROPY_FILTER) += vf_entropy.o +OBJS-$(CONFIG_EPX_FILTER) += vf_epx.o OBJS-$(CONFIG_EQ_FILTER) += vf_eq.o OBJS-$(CONFIG_EROSION_FILTER) += vf_neighbor.o OBJS-$(CONFIG_EROSION_OPENCL_FILTER) += vf_neighbor_opencl.o opencl.o \ opencl/neighbor.o +OBJS-$(CONFIG_ESTDIF_FILTER) += vf_estdif.o +OBJS-$(CONFIG_EXPOSURE_FILTER) += vf_exposure.o OBJS-$(CONFIG_EXTRACTPLANES_FILTER) += vf_extractplanes.o OBJS-$(CONFIG_FADE_FILTER) += vf_fade.o OBJS-$(CONFIG_FFTDNOIZ_FILTER) += vf_fftdnoiz.o @@ -247,8 +278,9 @@ OBJS-$(CONFIG_FRAMERATE_FILTER) += vf_framerate.o OBJS-$(CONFIG_FRAMESTEP_FILTER) += vf_framestep.o OBJS-$(CONFIG_FREEZEDETECT_FILTER) += vf_freezedetect.o +OBJS-$(CONFIG_FREEZEFRAMES_FILTER) += vf_freezeframes.o OBJS-$(CONFIG_FREI0R_FILTER) += vf_frei0r.o -OBJS-$(CONFIG_FSPP_FILTER) += vf_fspp.o +OBJS-$(CONFIG_FSPP_FILTER) += vf_fspp.o qp_table.o OBJS-$(CONFIG_GBLUR_FILTER) += vf_gblur.o OBJS-$(CONFIG_GEQ_FILTER) += vf_geq.o OBJS-$(CONFIG_GRADFUN_FILTER) += vf_gradfun.o @@ -267,12 +299,14 @@ OBJS-$(CONFIG_HWUPLOAD_CUDA_FILTER) += vf_hwupload_cuda.o OBJS-$(CONFIG_HWUPLOAD_FILTER) += vf_hwupload.o OBJS-$(CONFIG_HYSTERESIS_FILTER) += vf_hysteresis.o framesync.o +OBJS-$(CONFIG_IDENTITY_FILTER) += vf_identity.o OBJS-$(CONFIG_IDET_FILTER) += vf_idet.o OBJS-$(CONFIG_IL_FILTER) += vf_il.o OBJS-$(CONFIG_INFLATE_FILTER) += vf_neighbor.o OBJS-$(CONFIG_INTERLACE_FILTER) += vf_tinterlace.o OBJS-$(CONFIG_INTERLEAVE_FILTER) += f_interleave.o OBJS-$(CONFIG_KERNDEINT_FILTER) += vf_kerndeint.o +OBJS-$(CONFIG_KIRSCH_FILTER) += vf_convolution.o OBJS-$(CONFIG_LAGFUN_FILTER) += vf_lagfun.o OBJS-$(CONFIG_LENSCORRECTION_FILTER) += vf_lenscorrection.o OBJS-$(CONFIG_LENSFUN_FILTER) += vf_lensfun.o @@ -283,19 +317,24 @@ OBJS-$(CONFIG_LUT1D_FILTER) += vf_lut3d.o OBJS-$(CONFIG_LUT_FILTER) += vf_lut.o OBJS-$(CONFIG_LUT2_FILTER) += vf_lut2.o framesync.o -OBJS-$(CONFIG_LUT3D_FILTER) += vf_lut3d.o +OBJS-$(CONFIG_LUT3D_FILTER) += vf_lut3d.o framesync.o OBJS-$(CONFIG_LUTRGB_FILTER) += vf_lut.o OBJS-$(CONFIG_LUTYUV_FILTER) += vf_lut.o OBJS-$(CONFIG_MASKEDCLAMP_FILTER) += vf_maskedclamp.o framesync.o +OBJS-$(CONFIG_MASKEDMAX_FILTER) += vf_maskedminmax.o framesync.o OBJS-$(CONFIG_MASKEDMERGE_FILTER) += vf_maskedmerge.o framesync.o +OBJS-$(CONFIG_MASKEDMIN_FILTER) += vf_maskedminmax.o framesync.o +OBJS-$(CONFIG_MASKEDTHRESHOLD_FILTER) += vf_maskedthreshold.o framesync.o OBJS-$(CONFIG_MASKFUN_FILTER) += vf_maskfun.o OBJS-$(CONFIG_MCDEINT_FILTER) += vf_mcdeint.o +OBJS-$(CONFIG_MEDIAN_FILTER) += vf_median.o OBJS-$(CONFIG_MERGEPLANES_FILTER) += vf_mergeplanes.o framesync.o OBJS-$(CONFIG_MESTIMATE_FILTER) += vf_mestimate.o motion_estimation.o OBJS-$(CONFIG_METADATA_FILTER) += f_metadata.o OBJS-$(CONFIG_MIDEQUALIZER_FILTER) += vf_midequalizer.o framesync.o OBJS-$(CONFIG_MINTERPOLATE_FILTER) += vf_minterpolate.o motion_estimation.o -OBJS-$(CONFIG_MIX_FILTER) += vf_mix.o +OBJS-$(CONFIG_MIX_FILTER) += vf_mix.o framesync.o +OBJS-$(CONFIG_MONOCHROME_FILTER) += vf_monochrome.o OBJS-$(CONFIG_MPDECIMATE_FILTER) += vf_mpdecimate.o OBJS-$(CONFIG_NEGATE_FILTER) += vf_lut.o OBJS-$(CONFIG_NLMEANS_FILTER) += vf_nlmeans.o @@ -309,20 +348,24 @@ OBJS-$(CONFIG_OCV_FILTER) += vf_libopencv.o OBJS-$(CONFIG_OSCILLOSCOPE_FILTER) += vf_datascope.o OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o framesync.o +OBJS-$(CONFIG_OVERLAY_CUDA_FILTER) += vf_overlay_cuda.o framesync.o vf_overlay_cuda.ptx.o OBJS-$(CONFIG_OVERLAY_OPENCL_FILTER) += vf_overlay_opencl.o opencl.o \ opencl/overlay.o framesync.o OBJS-$(CONFIG_OVERLAY_QSV_FILTER) += vf_overlay_qsv.o framesync.o +OBJS-$(CONFIG_OVERLAY_VULKAN_FILTER) += vf_overlay_vulkan.o vulkan.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 OBJS-$(CONFIG_PALETTEGEN_FILTER) += vf_palettegen.o OBJS-$(CONFIG_PALETTEUSE_FILTER) += vf_paletteuse.o framesync.o OBJS-$(CONFIG_PERMS_FILTER) += f_perms.o OBJS-$(CONFIG_PERSPECTIVE_FILTER) += vf_perspective.o OBJS-$(CONFIG_PHASE_FILTER) += vf_phase.o +OBJS-$(CONFIG_PHOTOSENSITIVITY_FILTER) += vf_photosensitivity.o OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o OBJS-$(CONFIG_PIXSCOPE_FILTER) += vf_datascope.o -OBJS-$(CONFIG_PP_FILTER) += vf_pp.o -OBJS-$(CONFIG_PP7_FILTER) += vf_pp7.o +OBJS-$(CONFIG_PP_FILTER) += vf_pp.o qp_table.o +OBJS-$(CONFIG_PP7_FILTER) += vf_pp7.o qp_table.o OBJS-$(CONFIG_PREMULTIPLY_FILTER) += vf_premultiply.o framesync.o OBJS-$(CONFIG_PREWITT_FILTER) += vf_convolution.o OBJS-$(CONFIG_PREWITT_OPENCL_FILTER) += vf_convolution_opencl.o opencl.o \ @@ -348,12 +391,16 @@ opencl/convolution.o OBJS-$(CONFIG_ROTATE_FILTER) += vf_rotate.o OBJS-$(CONFIG_SAB_FILTER) += vf_sab.o -OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o scale.o -OBJS-$(CONFIG_SCALE_CUDA_FILTER) += vf_scale_cuda.o vf_scale_cuda.ptx.o -OBJS-$(CONFIG_SCALE_NPP_FILTER) += vf_scale_npp.o scale.o +OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o scale_eval.o +OBJS-$(CONFIG_SCALE_CUDA_FILTER) += vf_scale_cuda.o scale_eval.o \ + vf_scale_cuda.ptx.o vf_scale_cuda_bicubic.ptx.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.o vaapi_vpp.o -OBJS-$(CONFIG_SCALE2REF_FILTER) += vf_scale.o scale.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_SCALE2REF_FILTER) += vf_scale.o scale_eval.o +OBJS-$(CONFIG_SCDET_FILTER) += vf_scdet.o +OBJS-$(CONFIG_SCROLL_FILTER) += vf_scroll.o OBJS-$(CONFIG_SELECT_FILTER) += f_select.o OBJS-$(CONFIG_SELECTIVECOLOR_FILTER) += vf_selectivecolor.o OBJS-$(CONFIG_SENDCMD_FILTER) += f_sendcmd.o @@ -366,9 +413,11 @@ OBJS-$(CONFIG_SETSAR_FILTER) += vf_aspect.o OBJS-$(CONFIG_SETTB_FILTER) += settb.o OBJS-$(CONFIG_SHARPNESS_VAAPI_FILTER) += vf_misc_vaapi.o vaapi_vpp.o +OBJS-$(CONFIG_SHEAR_FILTER) += vf_shear.o OBJS-$(CONFIG_SHOWINFO_FILTER) += vf_showinfo.o OBJS-$(CONFIG_SHOWPALETTE_FILTER) += vf_showpalette.o OBJS-$(CONFIG_SHUFFLEFRAMES_FILTER) += vf_shuffleframes.o +OBJS-$(CONFIG_SHUFFLEPIXELS_FILTER) += vf_shufflepixels.o OBJS-$(CONFIG_SHUFFLEPLANES_FILTER) += vf_shuffleplanes.o OBJS-$(CONFIG_SIDEDATA_FILTER) += f_sidedata.o OBJS-$(CONFIG_SIGNALSTATS_FILTER) += vf_signalstats.o @@ -378,7 +427,7 @@ OBJS-$(CONFIG_SOBEL_OPENCL_FILTER) += vf_convolution_opencl.o opencl.o \ opencl/convolution.o OBJS-$(CONFIG_SPLIT_FILTER) += split.o -OBJS-$(CONFIG_SPP_FILTER) += vf_spp.o +OBJS-$(CONFIG_SPP_FILTER) += vf_spp.o qp_table.o OBJS-$(CONFIG_SR_FILTER) += vf_sr.o OBJS-$(CONFIG_SSIM_FILTER) += vf_ssim.o framesync.o OBJS-$(CONFIG_STEREO3D_FILTER) += vf_stereo3d.o @@ -389,16 +438,20 @@ OBJS-$(CONFIG_SWAPUV_FILTER) += vf_swapuv.o OBJS-$(CONFIG_TBLEND_FILTER) += vf_blend.o framesync.o OBJS-$(CONFIG_TELECINE_FILTER) += vf_telecine.o +OBJS-$(CONFIG_THISTOGRAM_FILTER) += vf_histogram.o OBJS-$(CONFIG_THRESHOLD_FILTER) += vf_threshold.o framesync.o OBJS-$(CONFIG_THUMBNAIL_FILTER) += vf_thumbnail.o OBJS-$(CONFIG_THUMBNAIL_CUDA_FILTER) += vf_thumbnail_cuda.o vf_thumbnail_cuda.ptx.o OBJS-$(CONFIG_TILE_FILTER) += vf_tile.o OBJS-$(CONFIG_TINTERLACE_FILTER) += vf_tinterlace.o OBJS-$(CONFIG_TLUT2_FILTER) += vf_lut2.o framesync.o +OBJS-$(CONFIG_TMEDIAN_FILTER) += vf_xmedian.o framesync.o +OBJS-$(CONFIG_TMIDEQUALIZER_FILTER) += vf_tmidequalizer.o OBJS-$(CONFIG_TMIX_FILTER) += vf_mix.o framesync.o OBJS-$(CONFIG_TONEMAP_FILTER) += vf_tonemap.o colorspace.o OBJS-$(CONFIG_TONEMAP_OPENCL_FILTER) += vf_tonemap_opencl.o colorspace.o opencl.o \ opencl/tonemap.o opencl/colorspace_common.o +OBJS-$(CONFIG_TONEMAP_VAAPI_FILTER) += vf_tonemap_vaapi.o vaapi_vpp.o OBJS-$(CONFIG_TPAD_FILTER) += vf_tpad.o OBJS-$(CONFIG_TRANSPOSE_FILTER) += vf_transpose.o OBJS-$(CONFIG_TRANSPOSE_NPP_FILTER) += vf_transpose_npp.o @@ -409,7 +462,9 @@ OBJS-$(CONFIG_UNSHARP_FILTER) += vf_unsharp.o OBJS-$(CONFIG_UNSHARP_OPENCL_FILTER) += vf_unsharp_opencl.o opencl.o \ opencl/unsharp.o -OBJS-$(CONFIG_USPP_FILTER) += vf_uspp.o +OBJS-$(CONFIG_UNTILE_FILTER) += vf_untile.o +OBJS-$(CONFIG_USPP_FILTER) += vf_uspp.o qp_table.o +OBJS-$(CONFIG_V360_FILTER) += vf_v360.o OBJS-$(CONFIG_VAGUEDENOISER_FILTER) += vf_vaguedenoiser.o OBJS-$(CONFIG_VECTORSCOPE_FILTER) += vf_vectorscope.o OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o @@ -417,6 +472,7 @@ OBJS-$(CONFIG_VIBRANCE_FILTER) += vf_vibrance.o OBJS-$(CONFIG_VIDSTABDETECT_FILTER) += vidstabutils.o vf_vidstabdetect.o OBJS-$(CONFIG_VIDSTABTRANSFORM_FILTER) += vidstabutils.o vf_vidstabtransform.o +OBJS-$(CONFIG_VIF_FILTER) += vf_vif.o framesync.o OBJS-$(CONFIG_VIGNETTE_FILTER) += vf_vignette.o OBJS-$(CONFIG_VMAFMOTION_FILTER) += vf_vmafmotion.o framesync.o OBJS-$(CONFIG_VPP_QSV_FILTER) += vf_vpp_qsv.o @@ -425,11 +481,14 @@ OBJS-$(CONFIG_WAVEFORM_FILTER) += vf_waveform.o OBJS-$(CONFIG_WEAVE_FILTER) += vf_weave.o OBJS-$(CONFIG_XBR_FILTER) += vf_xbr.o +OBJS-$(CONFIG_XFADE_FILTER) += vf_xfade.o +OBJS-$(CONFIG_XFADE_OPENCL_FILTER) += vf_xfade_opencl.o opencl.o opencl/xfade.o OBJS-$(CONFIG_XMEDIAN_FILTER) += vf_xmedian.o framesync.o 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 +OBJS-$(CONFIG_YAEPBLUR_FILTER) += vf_yaepblur.o OBJS-$(CONFIG_ZMQ_FILTER) += f_zmq.o OBJS-$(CONFIG_ZOOMPAN_FILTER) += vf_zoompan.o OBJS-$(CONFIG_ZSCALE_FILTER) += vf_zscale.o @@ -440,6 +499,7 @@ OBJS-$(CONFIG_COLOR_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 OBJS-$(CONFIG_HALDCLUTSRC_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_LIFE_FILTER) += vsrc_life.o OBJS-$(CONFIG_MANDELBROT_FILTER) += vsrc_mandelbrot.o @@ -449,6 +509,7 @@ OBJS-$(CONFIG_PAL75BARS_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_PAL100BARS_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_RGBTESTSRC_FILTER) += vsrc_testsrc.o +OBJS-$(CONFIG_SIERPINSKI_FILTER) += vsrc_sierpinski.o OBJS-$(CONFIG_SMPTEBARS_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_SMPTEHDBARS_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_TESTSRC_FILTER) += vsrc_testsrc.o @@ -489,6 +550,9 @@ 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 TOOLS = graph2dot TESTPROGS = drawutils filtfmts formats integral @@ -496,7 +560,7 @@ TOOLS-$(CONFIG_LIBZMQ) += zmqsend clean:: - $(RM) $(CLEANSUFFIXES:%=libavfilter/libmpcodecs/%) + $(RM) $(CLEANSUFFIXES:%=libavfilter/dnn/%) $(CLEANSUFFIXES:%=libavfilter/opencl/%) OPENCL = $(subst $(SRC_PATH)/,,$(wildcard $(SRC_PATH)/libavfilter/opencl/*.cl)) .SECONDARY: $(OPENCL:.cl=.c) diff -Nru ffmpeg-4.2.2/libavfilter/maskedclamp.h ffmpeg-4.4/libavfilter/maskedclamp.h --- ffmpeg-4.2.2/libavfilter/maskedclamp.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/maskedclamp.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,35 @@ + /* + * Copyright (c) 2019 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFILTER_MASKEDCLAMP_H +#define AVFILTER_MASKEDCLAMP_H + +#include +#include + +typedef struct MaskedClampDSPContext { + void (*maskedclamp)(const uint8_t *bsrc, uint8_t *dst, + const uint8_t *darksrc, const uint8_t *brightsrc, + int w, int undershoot, int overshoot); +} MaskedClampDSPContext; + +void ff_maskedclamp_init_x86(MaskedClampDSPContext *dsp, int depth); + +#endif /* AVFILTER_MASKEDCLAMP_H */ diff -Nru ffmpeg-4.2.2/libavfilter/median.h ffmpeg-4.4/libavfilter/median.h --- ffmpeg-4.2.2/libavfilter/median.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/median.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019 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 + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + */ + +#ifndef AVFILTER_MEDIAN_H +#define AVFILTER_MEDIAN_H + +#include "avfilter.h" + +typedef struct MedianContext { + const AVClass *class; + + int planes; + int radius; + int radiusV; + float percentile; + + int planewidth[4]; + int planeheight[4]; + int depth; + int nb_planes; + int nb_threads; + + uint16_t **coarse, **fine; + int coarse_size, fine_size; + int bins; + int t; + + void (*hadd)(uint16_t *dst, const uint16_t *src, int bins); + void (*hsub)(uint16_t *dst, const uint16_t *src, int bins); + void (*hmuladd)(uint16_t *dst, const uint16_t *src, int f, int bins); + + void (*filter_plane)(AVFilterContext *ctx, const uint8_t *ssrc, int src_linesize, + uint8_t *ddst, int dst_linesize, int width, int height, + int slice_h_start, int slice_h_end, int jobnr); +} MedianContext; + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/median_template.c ffmpeg-4.4/libavfilter/median_template.c --- ffmpeg-4.2.2/libavfilter/median_template.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/median_template.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2019 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 + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + */ + +#include "libavutil/avassert.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +#undef pixel +#if DEPTH == 8 +#define pixel uint8_t +#else +#define pixel uint16_t +#endif + +#undef htype +#define htype uint16_t + +#undef fn +#undef fn2 +#undef fn3 +#define SHIFT ((DEPTH + 1) / 2) +#define BINS (1 << SHIFT) +#define MASK (BINS - 1) +#define fn3(a,b) a##_##b +#define fn2(a,b) fn3(a,b) +#define fn(a) fn2(a, DEPTH) + +#define PICK_COARSE_BIN(x, y) (BINS * (x) + ((y) >> SHIFT)) +#define PICK_FINE_BIN(x, y, z) (BINS * ((x) * ((y) >> SHIFT) + (z)) + ((y) & MASK)) + +static void fn(filter_plane)(AVFilterContext *ctx, const uint8_t *ssrc, int src_linesize, + uint8_t *ddst, int dst_linesize, int width, int height, + int slice_h_start, int slice_h_end, int jobnr) +{ + MedianContext *s = ctx->priv; + htype *ccoarse = s->coarse[jobnr]; + htype *cfine = s->fine[jobnr]; + const int radius = s->radius; + const int radiusV = s->radiusV; + const int t = s->t; + const pixel *src = (const pixel *)ssrc; + pixel *dst = (pixel *)ddst; + const pixel *srcp; + const pixel *p; + + src_linesize /= sizeof(pixel); + dst_linesize /= sizeof(pixel); + + memset(cfine, 0, s->fine_size * sizeof(*cfine)); + memset(ccoarse, 0, s->coarse_size * sizeof(*ccoarse)); + + srcp = src + FFMAX(0, slice_h_start - radiusV) * src_linesize; + if (jobnr == 0) { + for (int i = 0; i < width; i++) { + cfine[PICK_FINE_BIN(width, srcp[i], i)] += radiusV + 1; + ccoarse[PICK_COARSE_BIN(i, srcp[i])] += radiusV + 1; + } + } + + srcp = src + FFMAX(0, slice_h_start - radiusV - (jobnr != 0)) * src_linesize; + for (int i = 0; i < radiusV + (jobnr != 0) * (1 + radiusV); i++) { + for (int j = 0; j < width; j++) { + cfine[PICK_FINE_BIN(width, srcp[j], j)]++; + ccoarse[PICK_COARSE_BIN(j, srcp[j])]++; + } + srcp += src_linesize; + } + + srcp = src; + + for (int i = slice_h_start; i < slice_h_end; i++) { + htype coarse[BINS] = { 0 }; + htype fine[BINS][BINS] = { { 0 } }; + htype luc[BINS] = { 0 }; + + p = srcp + src_linesize * FFMAX(0, i - radiusV - 1); + for (int j = 0; j < width; j++) { + cfine[PICK_FINE_BIN(width, p[j], j)]--; + ccoarse[PICK_COARSE_BIN(j, p[j])]--; + } + + p = srcp + src_linesize * FFMIN(height - 1, i + radiusV); + for (int j = 0; j < width; j++) { + cfine[PICK_FINE_BIN(width, p[j], j)]++; + ccoarse[PICK_COARSE_BIN(j, p[j])]++; + } + + s->hmuladd(coarse, &ccoarse[0], radius, BINS); + for (int j = 0; j < radius; j++) + s->hadd(coarse, &ccoarse[BINS * j], BINS); + for (int k = 0; k < BINS; k++) + s->hmuladd(&fine[k][0], &cfine[BINS * width * k], 2 * radius + 1, BINS); + + for (int j = 0; j < width; j++) { + int sum = 0, k, b; + htype *segment; + + s->hadd(coarse, &ccoarse[BINS * FFMIN(j + radius, width - 1)], BINS); + + for (k = 0; k < BINS; k++) { + sum += coarse[k]; + if (sum > t) { + sum -= coarse[k]; + break; + } + } + av_assert0(k < BINS); + + if (luc[k] <= j - radius) { + memset(&fine[k], 0, BINS * sizeof(htype)); + for (luc[k] = j - radius; luc[k] < FFMIN(j + radius + 1, width); luc[k]++) + s->hadd(fine[k], &cfine[BINS * (width * k + luc[k])], BINS); + if (luc[k] < j + radius + 1) { + s->hmuladd(&fine[k][0], &cfine[BINS * (width * k + width - 1)], j + radius + 1 - width, BINS); + luc[k] = j + radius + 1; + } + } else { + for (; luc[k] < j + radius + 1; luc[k]++) { + s->hsub(fine[k], &cfine[BINS * (width * k + FFMAX(luc[k] - 2 * radius - 1, 0))], BINS); + s->hadd(fine[k], &cfine[BINS * (width * k + FFMIN(luc[k], width - 1))], BINS); + } + } + + s->hsub(coarse, &ccoarse[BINS * FFMAX(j - radius, 0)], BINS); + + segment = fine[k]; + for (b = 0; b < BINS; b++) { + sum += segment[b]; + if (sum > t) { + dst[j] = BINS * k + b; + break; + } + } + av_assert0(b < BINS); + } + + dst += dst_linesize; + } +} diff -Nru ffmpeg-4.2.2/libavfilter/opencl/deshake.cl ffmpeg-4.4/libavfilter/opencl/deshake.cl --- ffmpeg-4.2.2/libavfilter/opencl/deshake.cl 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/opencl/deshake.cl 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,647 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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) 2000, Intel Corporation, all rights reserved. + * Copyright (C) 2013, OpenCV Foundation, all rights reserved. + * Third party copyrights are property of their respective owners. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistribution's of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistribution's 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. + * + * * The name of the copyright holders may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * This software is provided by the copyright holders and contributors "as is" and + * any express or implied warranties, including, but not limited to, the implied + * warranties of merchantability and fitness for a particular purpose are disclaimed. + * In no event shall the Intel Corporation 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. + */ + +#define HARRIS_THRESHOLD 3.0f +// Block size over which to compute harris response +// +// Note that changing this will require fiddling with the local array sizes in +// harris_response +#define HARRIS_RADIUS 2 +#define DISTANCE_THRESHOLD 80 + +// Sub-pixel refinement window for feature points +#define REFINE_WIN_HALF_W 5 +#define REFINE_WIN_HALF_H 5 +#define REFINE_WIN_W 11 // REFINE_WIN_HALF_W * 2 + 1 +#define REFINE_WIN_H 11 + +// Non-maximum suppression window size +#define NONMAX_WIN 30 +#define NONMAX_WIN_HALF 15 // NONMAX_WIN / 2 + +typedef struct PointPair { + // Previous frame + float2 p1; + // Current frame + float2 p2; +} PointPair; + +typedef struct SmoothedPointPair { + // Non-smoothed point in current frame + int2 p1; + // Smoothed point in current frame + float2 p2; +} SmoothedPointPair; + +typedef struct MotionVector { + PointPair p; + // Used to mark vectors as potential outliers + int should_consider; +} MotionVector; + +const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | + CLK_ADDRESS_CLAMP_TO_EDGE | + CLK_FILTER_NEAREST; + +const sampler_t sampler_linear = CLK_NORMALIZED_COORDS_FALSE | + CLK_ADDRESS_CLAMP_TO_EDGE | + CLK_FILTER_LINEAR; + +const sampler_t sampler_linear_mirror = CLK_NORMALIZED_COORDS_TRUE | + CLK_ADDRESS_MIRRORED_REPEAT | + CLK_FILTER_LINEAR; + +// Writes to a 1D array at loc, treating it as a 2D array with the same +// dimensions as the global work size. +static void write_to_1d_arrf(__global float *buf, int2 loc, float val) { + buf[loc.x + loc.y * get_global_size(0)] = val; +} + +static void write_to_1d_arrul8(__global ulong8 *buf, int2 loc, ulong8 val) { + buf[loc.x + loc.y * get_global_size(0)] = val; +} + +static void write_to_1d_arrvec(__global MotionVector *buf, int2 loc, MotionVector val) { + buf[loc.x + loc.y * get_global_size(0)] = val; +} + +static void write_to_1d_arrf2(__global float2 *buf, int2 loc, float2 val) { + buf[loc.x + loc.y * get_global_size(0)] = val; +} + +static ulong8 read_from_1d_arrul8(__global const ulong8 *buf, int2 loc) { + return buf[loc.x + loc.y * get_global_size(0)]; +} + +static float2 read_from_1d_arrf2(__global const float2 *buf, int2 loc) { + return buf[loc.x + loc.y * get_global_size(0)]; +} + +// Returns the grayscale value at the given point. +static float pixel_grayscale(__read_only image2d_t src, int2 loc) { + float4 pixel = read_imagef(src, sampler, loc); + return (pixel.x + pixel.y + pixel.z) / 3.0f; +} + +static float convolve( + __local const float *grayscale, + int local_idx_x, + int local_idx_y, + float mask[3][3] +) { + float ret = 0; + + // These loops touch each pixel surrounding loc as well as loc itself + for (int i = 1, i2 = 0; i >= -1; --i, ++i2) { + for (int j = -1, j2 = 0; j <= 1; ++j, ++j2) { + ret += mask[i2][j2] * grayscale[(local_idx_x + 3 + j) + (local_idx_y + 3 + i) * 14]; + } + } + + return ret; +} + +// Sums dx * dy for all pixels within radius of loc +static float sum_deriv_prod( + __local const float *grayscale, + float mask_x[3][3], + float mask_y[3][3] +) { + float ret = 0; + + for (int i = HARRIS_RADIUS; i >= -HARRIS_RADIUS; --i) { + for (int j = -HARRIS_RADIUS; j <= HARRIS_RADIUS; ++j) { + ret += convolve(grayscale, get_local_id(0) + j, get_local_id(1) + i, mask_x) * + convolve(grayscale, get_local_id(0) + j, get_local_id(1) + i, mask_y); + } + } + + return ret; +} + +// Sums d<>^2 (determined by mask) for all pixels within radius of loc +static float sum_deriv_pow(__local const float *grayscale, float mask[3][3]) +{ + float ret = 0; + + for (int i = HARRIS_RADIUS; i >= -HARRIS_RADIUS; --i) { + for (int j = -HARRIS_RADIUS; j <= HARRIS_RADIUS; ++j) { + float deriv = convolve(grayscale, get_local_id(0) + j, get_local_id(1) + i, mask); + ret += deriv * deriv; + } + } + + return ret; +} + +// Fills a box with the given radius and pixel around loc +static void draw_box(__write_only image2d_t dst, int2 loc, float4 pixel, int radius) +{ + for (int i = -radius; i <= radius; ++i) { + for (int j = -radius; j <= radius; ++j) { + write_imagef( + dst, + (int2)( + // Clamp to avoid writing outside image bounds + clamp(loc.x + i, 0, get_image_dim(dst).x - 1), + clamp(loc.y + j, 0, get_image_dim(dst).y - 1) + ), + pixel + ); + } + } +} + +// Converts the src image to grayscale +__kernel void grayscale( + __read_only image2d_t src, + __write_only image2d_t grayscale +) { + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + write_imagef(grayscale, loc, (float4)(pixel_grayscale(src, loc), 0.0f, 0.0f, 1.0f)); +} + +// This kernel computes the harris response for the given grayscale src image +// within the given radius and writes it to harris_buf +__kernel void harris_response( + __read_only image2d_t grayscale, + __global float *harris_buf +) { + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + + if (loc.x > get_image_width(grayscale) - 1 || loc.y > get_image_height(grayscale) - 1) { + write_to_1d_arrf(harris_buf, loc, 0); + return; + } + + float scale = 1.0f / ((1 << 2) * HARRIS_RADIUS * 255.0f); + + float sobel_mask_x[3][3] = { + {-1, 0, 1}, + {-2, 0, 2}, + {-1, 0, 1} + }; + + float sobel_mask_y[3][3] = { + { 1, 2, 1}, + { 0, 0, 0}, + {-1, -2, -1} + }; + + // 8 x 8 local work + 3 pixels around each side (needed to accomodate for the + // block size radius of 2) + __local float grayscale_data[196]; + + int idx = get_group_id(0) * get_local_size(0); + int idy = get_group_id(1) * get_local_size(1); + + for (int i = idy - 3, it = 0; i < idy + (int)get_local_size(1) + 3; i++, it++) { + for (int j = idx - 3, jt = 0; j < idx + (int)get_local_size(0) + 3; j++, jt++) { + grayscale_data[jt + it * 14] = read_imagef(grayscale, sampler, (int2)(j, i)).x; + } + } + + barrier(CLK_LOCAL_MEM_FENCE); + + float sumdxdy = sum_deriv_prod(grayscale_data, sobel_mask_x, sobel_mask_y); + float sumdx2 = sum_deriv_pow(grayscale_data, sobel_mask_x); + float sumdy2 = sum_deriv_pow(grayscale_data, sobel_mask_y); + + float trace = sumdx2 + sumdy2; + // r = det(M) - k(trace(M))^2 + // k usually between 0.04 to 0.06 + float r = (sumdx2 * sumdy2 - sumdxdy * sumdxdy) - 0.04f * (trace * trace) * pown(scale, 4); + + // Threshold the r value + harris_buf[loc.x + loc.y * get_image_width(grayscale)] = r * step(HARRIS_THRESHOLD, r); +} + +// Gets a patch centered around a float coordinate from a grayscale image using +// bilinear interpolation +static void get_rect_sub_pix( + __read_only image2d_t grayscale, + float *buffer, + int size_x, + int size_y, + float2 center +) { + float2 offset = ((float2)(size_x, size_y) - 1.0f) * 0.5f; + + for (int i = 0; i < size_y; i++) { + for (int j = 0; j < size_x; j++) { + buffer[i * size_x + j] = read_imagef( + grayscale, + sampler_linear, + (float2)(j, i) + center - offset + ).x * 255.0f; + } + } +} + +// Refines detected features at a sub-pixel level +// +// This function is ported from OpenCV +static float2 corner_sub_pix( + __read_only image2d_t grayscale, + float2 feature, + float *mask +) { + float2 init = feature; + int src_width = get_global_size(0); + int src_height = get_global_size(1); + + const int max_iters = 40; + const float eps = 0.001f * 0.001f; + int i, j, k; + + int iter = 0; + float err = 0; + float subpix[(REFINE_WIN_W + 2) * (REFINE_WIN_H + 2)]; + const float flt_epsilon = 0x1.0p-23f; + + do { + float2 feature_tmp; + float a = 0, b = 0, c = 0, bb1 = 0, bb2 = 0; + + get_rect_sub_pix(grayscale, subpix, REFINE_WIN_W + 2, REFINE_WIN_H + 2, feature); + float *subpix_ptr = subpix; + subpix_ptr += REFINE_WIN_W + 2 + 1; + + // process gradient + for (i = 0, k = 0; i < REFINE_WIN_H; i++, subpix_ptr += REFINE_WIN_W + 2) { + float py = i - REFINE_WIN_HALF_H; + + for (j = 0; j < REFINE_WIN_W; j++, k++) { + float m = mask[k]; + float tgx = subpix_ptr[j + 1] - subpix_ptr[j - 1]; + float tgy = subpix_ptr[j + REFINE_WIN_W + 2] - subpix_ptr[j - REFINE_WIN_W - 2]; + float gxx = tgx * tgx * m; + float gxy = tgx * tgy * m; + float gyy = tgy * tgy * m; + float px = j - REFINE_WIN_HALF_W; + + a += gxx; + b += gxy; + c += gyy; + + bb1 += gxx * px + gxy * py; + bb2 += gxy * px + gyy * py; + } + } + + float det = a * c - b * b; + if (fabs(det) <= flt_epsilon * flt_epsilon) { + break; + } + + // 2x2 matrix inversion + float scale = 1.0f / det; + feature_tmp.x = (float)(feature.x + (c * scale * bb1) - (b * scale * bb2)); + feature_tmp.y = (float)(feature.y - (b * scale * bb1) + (a * scale * bb2)); + err = dot(feature_tmp - feature, feature_tmp - feature); + + feature = feature_tmp; + if (feature.x < 0 || feature.x >= src_width || feature.y < 0 || feature.y >= src_height) { + break; + } + } while (++iter < max_iters && err > eps); + + // Make sure new point isn't too far from the initial point (indicates poor convergence) + if (fabs(feature.x - init.x) > REFINE_WIN_HALF_W || fabs(feature.y - init.y) > REFINE_WIN_HALF_H) { + feature = init; + } + + return feature; +} + +// Performs non-maximum suppression on the harris response and writes the resulting +// feature locations to refined_features. +// +// Assumes that refined_features and the global work sizes are set up such that the image +// is split up into a grid of 32x32 blocks where each block has a single slot in the +// refined_features buffer. This kernel finds the best corner in each block (if the +// block has any) and writes it to the corresponding slot in the buffer. +// +// If subpixel_refine is true, the features are additionally refined at a sub-pixel +// level for increased precision. +__kernel void refine_features( + __read_only image2d_t grayscale, + __global const float *harris_buf, + __global float2 *refined_features, + int subpixel_refine +) { + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + // The location in the grayscale buffer rather than the compacted grid + int2 loc_i = (int2)(loc.x * 32, loc.y * 32); + + float new_val; + float max_val = 0; + float2 loc_max = (float2)(-1, -1); + + int end_x = min(loc_i.x + 32, (int)get_image_dim(grayscale).x - 1); + int end_y = min(loc_i.y + 32, (int)get_image_dim(grayscale).y - 1); + + for (int i = loc_i.x; i < end_x; ++i) { + for (int j = loc_i.y; j < end_y; ++j) { + new_val = harris_buf[i + j * get_image_dim(grayscale).x]; + + if (new_val > max_val) { + max_val = new_val; + loc_max = (float2)(i, j); + } + } + } + + if (max_val == 0) { + // There are no features in this part of the frame + write_to_1d_arrf2(refined_features, loc, loc_max); + return; + } + + if (subpixel_refine) { + float mask[REFINE_WIN_H * REFINE_WIN_W]; + for (int i = 0; i < REFINE_WIN_H; i++) { + float y = (float)(i - REFINE_WIN_HALF_H) / REFINE_WIN_HALF_H; + float vy = exp(-y * y); + + for (int j = 0; j < REFINE_WIN_W; j++) { + float x = (float)(j - REFINE_WIN_HALF_W) / REFINE_WIN_HALF_W; + mask[i * REFINE_WIN_W + j] = (float)(vy * exp(-x * x)); + } + } + + loc_max = corner_sub_pix(grayscale, loc_max, mask); + } + + write_to_1d_arrf2(refined_features, loc, loc_max); +} + +// Extracts BRIEF descriptors from the grayscale src image for the given features +// using the provided sampler. +__kernel void brief_descriptors( + __read_only image2d_t grayscale, + __global const float2 *refined_features, + // for 512 bit descriptors + __global ulong8 *desc_buf, + __global const PointPair *brief_pattern +) { + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + float2 feature = read_from_1d_arrf2(refined_features, loc); + + // There was no feature in this part of the frame + if (feature.x == -1) { + write_to_1d_arrul8(desc_buf, loc, (ulong8)(0)); + return; + } + + ulong8 desc = 0; + ulong *p = &desc; + + for (int i = 0; i < 8; ++i) { + for (int j = 0; j < 64; ++j) { + PointPair pair = brief_pattern[j * (i + 1)]; + float l1 = read_imagef(grayscale, sampler_linear, feature + pair.p1).x; + float l2 = read_imagef(grayscale, sampler_linear, feature + pair.p2).x; + + if (l1 < l2) { + p[i] |= 1UL << j; + } + } + } + + write_to_1d_arrul8(desc_buf, loc, desc); +} + +// Given buffers with descriptors for the current and previous frame, determines +// which ones match, writing correspondences to matches_buf. +// +// Feature and descriptor buffers are assumed to be compacted (each element sourced +// from a 32x32 block in the frame being processed). +__kernel void match_descriptors( + __global const float2 *prev_refined_features, + __global const float2 *refined_features, + __global const ulong8 *desc_buf, + __global const ulong8 *prev_desc_buf, + __global MotionVector *matches_buf +) { + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + ulong8 desc = read_from_1d_arrul8(desc_buf, loc); + const int search_radius = 3; + + MotionVector invalid_vector = (MotionVector) { + (PointPair) { + (float2)(-1, -1), + (float2)(-1, -1) + }, + 0 + }; + + if (desc.s0 == 0 && desc.s1 == 0) { + // There was no feature in this part of the frame + write_to_1d_arrvec( + matches_buf, + loc, + invalid_vector + ); + return; + } + + int2 start = max(loc - search_radius, 0); + int2 end = min(loc + search_radius, (int2)(get_global_size(0) - 1, get_global_size(1) - 1)); + + for (int i = start.x; i < end.x; ++i) { + for (int j = start.y; j < end.y; ++j) { + int2 prev_point = (int2)(i, j); + int total_dist = 0; + + ulong8 prev_desc = read_from_1d_arrul8(prev_desc_buf, prev_point); + + if (prev_desc.s0 == 0 && prev_desc.s1 == 0) { + continue; + } + + ulong *prev_desc_p = &prev_desc; + ulong *desc_p = &desc; + + for (int i = 0; i < 8; i++) { + total_dist += popcount(desc_p[i] ^ prev_desc_p[i]); + } + + if (total_dist < DISTANCE_THRESHOLD) { + write_to_1d_arrvec( + matches_buf, + loc, + (MotionVector) { + (PointPair) { + read_from_1d_arrf2(prev_refined_features, prev_point), + read_from_1d_arrf2(refined_features, loc) + }, + 1 + } + ); + + return; + } + } + } + + // There is no found match for this point + write_to_1d_arrvec( + matches_buf, + loc, + invalid_vector + ); +} + +// Returns the position of the given point after the transform is applied +static float2 transformed_point(float2 p, __global const float *transform) { + float2 ret; + + ret.x = p.x * transform[0] + p.y * transform[1] + transform[2]; + ret.y = p.x * transform[3] + p.y * transform[4] + transform[5]; + + return ret; +} + + +// Performs the given transform on the src image +__kernel void transform( + __read_only image2d_t src, + __write_only image2d_t dst, + __global const float *transform +) { + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + float2 norm = convert_float2(get_image_dim(src)); + + write_imagef( + dst, + loc, + read_imagef( + src, + sampler_linear_mirror, + transformed_point((float2)(loc.x, loc.y), transform) / norm + ) + ); +} + +// Returns the new location of the given point using the given crop bounding box +// and the width and height of the original frame. +static float2 cropped_point( + float2 p, + float2 top_left, + float2 bottom_right, + int2 orig_dim +) { + float2 ret; + + float crop_width = bottom_right.x - top_left.x; + float crop_height = bottom_right.y - top_left.y; + + float width_norm = p.x / (float)orig_dim.x; + float height_norm = p.y / (float)orig_dim.y; + + ret.x = (width_norm * crop_width) + top_left.x; + ret.y = (height_norm * crop_height) + ((float)orig_dim.y - bottom_right.y); + + return ret; +} + +// Upscales the given cropped region to the size of the original frame +__kernel void crop_upscale( + __read_only image2d_t src, + __write_only image2d_t dst, + float2 top_left, + float2 bottom_right +) { + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + + write_imagef( + dst, + loc, + read_imagef( + src, + sampler_linear, + cropped_point((float2)(loc.x, loc.y), top_left, bottom_right, get_image_dim(dst)) + ) + ); +} + +// Draws boxes to represent the given point matches and uses the given transform +// and crop info to make sure their positions are accurate on the transformed frame. +// +// model_matches is an array of three points that were used by the RANSAC process +// to generate the given transform +__kernel void draw_debug_info( + __write_only image2d_t dst, + __global const MotionVector *matches, + __global const MotionVector *model_matches, + int num_model_matches, + __global const float *transform +) { + int loc = get_global_id(0); + MotionVector vec = matches[loc]; + // Black box: matched point that RANSAC considered an outlier + float4 big_rect_color = (float4)(0.1f, 0.1f, 0.1f, 1.0f); + + if (vec.should_consider) { + // Green box: matched point that RANSAC considered an inlier + big_rect_color = (float4)(0.0f, 1.0f, 0.0f, 1.0f); + } + + for (int i = 0; i < num_model_matches; i++) { + if (vec.p.p2.x == model_matches[i].p.p2.x && vec.p.p2.y == model_matches[i].p.p2.y) { + // Orange box: point used to calculate model + big_rect_color = (float4)(1.0f, 0.5f, 0.0f, 1.0f); + } + } + + float2 transformed_p1 = transformed_point(vec.p.p1, transform); + float2 transformed_p2 = transformed_point(vec.p.p2, transform); + + draw_box(dst, (int2)(transformed_p2.x, transformed_p2.y), big_rect_color, 5); + // Small light blue box: the point in the previous frame + draw_box(dst, (int2)(transformed_p1.x, transformed_p1.y), (float4)(0.0f, 0.3f, 0.7f, 1.0f), 3); +} diff -Nru ffmpeg-4.2.2/libavfilter/opencl/pad.cl ffmpeg-4.4/libavfilter/opencl/pad.cl --- ffmpeg-4.2.2/libavfilter/opencl/pad.cl 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/opencl/pad.cl 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_NEAREST; + +__kernel void pad ( + __read_only image2d_t src, + __write_only image2d_t dst, + float4 color, + int2 xy) +{ + int2 size_src = get_image_dim(src); + int2 loc = (int2)(get_global_id(0), get_global_id(1)); + int2 src_pos = (int2)(get_global_id(0) - xy.x, get_global_id(1) - xy.y); + float4 pixel = loc.x >= size_src.x + xy.x || + loc.y >= size_src.y + xy.y || + loc.x < xy.x || + loc.y < xy.y ? color : read_imagef(src, sampler, src_pos); + write_imagef(dst, loc, pixel); +} diff -Nru ffmpeg-4.2.2/libavfilter/opencl/xfade.cl ffmpeg-4.4/libavfilter/opencl/xfade.cl --- ffmpeg-4.2.2/libavfilter/opencl/xfade.cl 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/opencl/xfade.cl 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,145 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +const sampler_t sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_NEAREST); + +__kernel void fade(__write_only image2d_t dst, + __read_only image2d_t src1, + __read_only image2d_t src2, + float progress) +{ + int2 p = (int2)(get_global_id(0), get_global_id(1)); + + float4 val1 = read_imagef(src1, sampler, p); + float4 val2 = read_imagef(src2, sampler, p); + + write_imagef(dst, p, mix(val2, val1, progress)); +} + +__kernel void wipeleft(__write_only image2d_t dst, + __read_only image2d_t src1, + __read_only image2d_t src2, + float progress) +{ + int s = (int)(get_image_dim(src1).x * progress); + int2 p = (int2)(get_global_id(0), get_global_id(1)); + + float4 val1 = read_imagef(src1, sampler, p); + float4 val2 = read_imagef(src2, sampler, p); + + write_imagef(dst, p, p.x > s ? val2 : val1); +} + +__kernel void wiperight(__write_only image2d_t dst, + __read_only image2d_t src1, + __read_only image2d_t src2, + float progress) +{ + int s = (int)(get_image_dim(src1).x * (1.f - progress)); + int2 p = (int2)(get_global_id(0), get_global_id(1)); + + float4 val1 = read_imagef(src1, sampler, p); + float4 val2 = read_imagef(src2, sampler, p); + + write_imagef(dst, p, p.x > s ? val1 : val2); +} + +__kernel void wipeup(__write_only image2d_t dst, + __read_only image2d_t src1, + __read_only image2d_t src2, + float progress) +{ + int s = (int)(get_image_dim(src1).y * progress); + int2 p = (int2)(get_global_id(0), get_global_id(1)); + + float4 val1 = read_imagef(src1, sampler, p); + float4 val2 = read_imagef(src2, sampler, p); + + write_imagef(dst, p, p.y > s ? val2 : val1); +} + +__kernel void wipedown(__write_only image2d_t dst, + __read_only image2d_t src1, + __read_only image2d_t src2, + float progress) +{ + int s = (int)(get_image_dim(src1).y * (1.f - progress)); + int2 p = (int2)(get_global_id(0), get_global_id(1)); + + float4 val1 = read_imagef(src1, sampler, p); + float4 val2 = read_imagef(src2, sampler, p); + + write_imagef(dst, p, p.y > s ? val1 : val2); +} + +void slide(__write_only image2d_t dst, + __read_only image2d_t src1, + __read_only image2d_t src2, + float progress, + int2 direction) +{ + int w = get_image_dim(src1).x; + int h = get_image_dim(src1).y; + int2 wh = (int2)(w, h); + int2 uv = (int2)(get_global_id(0), get_global_id(1)); + int2 pi = (int2)(progress * w, progress * h); + int2 p = uv + pi * direction; + int2 f = p % wh; + + f = f + (int2)(w, h) * (int2)(f.x < 0, f.y < 0); + float4 val1 = read_imagef(src1, sampler, f); + float4 val2 = read_imagef(src2, sampler, f); + write_imagef(dst, uv, mix(val1, val2, (p.y >= 0) * (h > p.y) * (p.x >= 0) * (w > p.x))); +} + +__kernel void slidedown(__write_only image2d_t dst, + __read_only image2d_t src1, + __read_only image2d_t src2, + float progress) +{ + int2 direction = (int2)(0, 1); + slide(dst, src1, src2, progress, direction); +} + +__kernel void slideup(__write_only image2d_t dst, + __read_only image2d_t src1, + __read_only image2d_t src2, + float progress) +{ + int2 direction = (int2)(0, -1); + slide(dst, src1, src2, progress, direction); +} + +__kernel void slideleft(__write_only image2d_t dst, + __read_only image2d_t src1, + __read_only image2d_t src2, + float progress) +{ + int2 direction = (int2)(-1, 0); + slide(dst, src1, src2, progress, direction); +} + +__kernel void slideright(__write_only image2d_t dst, + __read_only image2d_t src1, + __read_only image2d_t src2, + float progress) +{ + int2 direction = (int2)(1, 0); + slide(dst, src1, src2, progress, direction); +} diff -Nru ffmpeg-4.2.2/libavfilter/opencl.c ffmpeg-4.4/libavfilter/opencl.c --- ffmpeg-4.2.2/libavfilter/opencl.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/opencl.c 2020-07-11 10:39:30.000000000 +0000 @@ -225,7 +225,7 @@ const char *src_const; int err; - file = fopen(filename, "r"); + file = av_fopen_utf8(filename, "r"); if (!file) { av_log(avctx, AV_LOG_ERROR, "Unable to open program " "source file \"%s\".\n", filename); @@ -350,3 +350,13 @@ } av_bprintf(buf, "};\n"); } + +cl_ulong ff_opencl_get_event_time(cl_event event) { + cl_ulong time_start; + cl_ulong time_end; + + clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START, sizeof(time_start), &time_start, NULL); + clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END, sizeof(time_end), &time_end, NULL); + + return time_end - time_start; +} diff -Nru ffmpeg-4.2.2/libavfilter/opencl.h ffmpeg-4.4/libavfilter/opencl.h --- ffmpeg-4.2.2/libavfilter/opencl.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/opencl.h 2020-07-11 10:39:30.000000000 +0000 @@ -47,6 +47,11 @@ int output_height; } OpenCLFilterContext; +// Groups together information about a kernel argument +typedef struct OpenCLKernelArg { + size_t arg_size; + const void *arg_val; +} OpenCLKernelArg; /** * set argument to specific Kernel. @@ -73,9 +78,26 @@ goto fail; \ } \ } while(0) + +/** + * Create a kernel with the given name. + * + * The kernel variable in the context structure must have a name of the form + * kernel_. + * + * The OpenCLFilterContext variable in the context structure must be named ocf. + * + * Requires the presence of a local cl_int variable named cle and a fail label for error + * handling. + */ +#define CL_CREATE_KERNEL(ctx, kernel_name) do { \ + ctx->kernel_ ## kernel_name = clCreateKernel(ctx->ocf.program, #kernel_name, &cle); \ + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create %s kernel: %d.\n", #kernel_name, cle); \ +} while(0) + /** - * release an OpenCL Kernel - */ + * release an OpenCL Kernel + */ #define CL_RELEASE_KERNEL(k) \ do { \ if (k) { \ @@ -87,8 +109,8 @@ } while(0) /** - * release an OpenCL Memory Object - */ + * release an OpenCL Memory Object + */ #define CL_RELEASE_MEMORY(m) \ do { \ if (m) { \ @@ -100,8 +122,8 @@ } while(0) /** - * release an OpenCL Command Queue - */ + * release an OpenCL Command Queue + */ #define CL_RELEASE_QUEUE(q) \ do { \ if (q) { \ @@ -113,6 +135,108 @@ } while(0) /** + * Enqueue a kernel with the given information. + * + * Kernel arguments are provided as KernelArg structures and are set in the order + * that they are passed. + * + * Requires the presence of a local cl_int variable named cle and a fail label for error + * handling. + */ +#define CL_ENQUEUE_KERNEL_WITH_ARGS(queue, kernel, global_work_size, local_work_size, event, ...) \ +do { \ + OpenCLKernelArg args[] = {__VA_ARGS__}; \ + for (int i = 0; i < FF_ARRAY_ELEMS(args); i++) { \ + cle = clSetKernelArg(kernel, i, args[i].arg_size, args[i].arg_val); \ + if (cle != CL_SUCCESS) { \ + av_log(avctx, AV_LOG_ERROR, "Failed to set kernel " \ + "argument %d: error %d.\n", i, cle); \ + err = AVERROR(EIO); \ + goto fail; \ + } \ + } \ + \ + cle = clEnqueueNDRangeKernel( \ + queue, \ + kernel, \ + FF_ARRAY_ELEMS(global_work_size), \ + NULL, \ + global_work_size, \ + local_work_size, \ + 0, \ + NULL, \ + event \ + ); \ + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to enqueue kernel: %d.\n", cle); \ +} while (0) + +/** + * Uses the above macro to enqueue the given kernel and then additionally runs it to + * completion via clFinish. + * + * Requires the presence of a local cl_int variable named cle and a fail label for error + * handling. + */ +#define CL_RUN_KERNEL_WITH_ARGS(queue, kernel, global_work_size, local_work_size, event, ...) do { \ + CL_ENQUEUE_KERNEL_WITH_ARGS( \ + queue, kernel, global_work_size, local_work_size, event, __VA_ARGS__ \ + ); \ + \ + cle = clFinish(queue); \ + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to finish command queue: %d.\n", cle); \ +} while (0) + +/** + * Create a buffer with the given information. + * + * The buffer variable in the context structure must be named . + * + * Requires the presence of a local cl_int variable named cle and a fail label for error + * handling. + */ +#define CL_CREATE_BUFFER_FLAGS(ctx, buffer_name, flags, size, host_ptr) do { \ + ctx->buffer_name = clCreateBuffer( \ + ctx->ocf.hwctx->context, \ + flags, \ + size, \ + host_ptr, \ + &cle \ + ); \ + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create buffer %s: %d.\n", #buffer_name, cle); \ +} while(0) + +/** + * Perform a blocking write to a buffer. + * + * Requires the presence of a local cl_int variable named cle and a fail label for error + * handling. + */ +#define CL_BLOCKING_WRITE_BUFFER(queue, buffer, size, host_ptr, event) do { \ + cle = clEnqueueWriteBuffer( \ + queue, \ + buffer, \ + CL_TRUE, \ + 0, \ + size, \ + host_ptr, \ + 0, \ + NULL, \ + event \ + ); \ + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to write buffer to device: %d.\n", cle); \ +} while(0) + +/** + * Create a buffer with the given information. + * + * The buffer variable in the context structure must be named . + * + * Requires the presence of a local cl_int variable named cle and a fail label for error + * handling. + */ +#define CL_CREATE_BUFFER(ctx, buffer_name, size) CL_CREATE_BUFFER_FLAGS(ctx, buffer_name, 0, size, NULL) + +/** * Return that all inputs and outputs support only AV_PIX_FMT_OPENCL. */ int ff_opencl_filter_query_formats(AVFilterContext *avctx); @@ -171,4 +295,10 @@ void ff_opencl_print_const_matrix_3x3(AVBPrint *buf, const char *name_str, double mat[3][3]); +/** + * Gets the command start and end times for the given event and returns the + * difference (the time that the event took). + */ +cl_ulong ff_opencl_get_event_time(cl_event event); + #endif /* AVFILTER_OPENCL_H */ diff -Nru ffmpeg-4.2.2/libavfilter/opencl_source.h ffmpeg-4.4/libavfilter/opencl_source.h --- ffmpeg-4.2.2/libavfilter/opencl_source.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/opencl_source.h 2020-07-11 10:39:30.000000000 +0000 @@ -23,11 +23,14 @@ extern const char *ff_opencl_source_colorkey; extern const char *ff_opencl_source_colorspace_common; extern const char *ff_opencl_source_convolution; +extern const char *ff_opencl_source_deshake; extern const char *ff_opencl_source_neighbor; extern const char *ff_opencl_source_nlmeans; extern const char *ff_opencl_source_overlay; +extern const char *ff_opencl_source_pad; extern const char *ff_opencl_source_tonemap; extern const char *ff_opencl_source_transpose; extern const char *ff_opencl_source_unsharp; +extern const char *ff_opencl_source_xfade; #endif /* AVFILTER_OPENCL_SOURCE_H */ diff -Nru ffmpeg-4.2.2/libavfilter/phase_template.c ffmpeg-4.4/libavfilter/phase_template.c --- ffmpeg-4.2.2/libavfilter/phase_template.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/phase_template.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2004 Ville Saari + * + * 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 "libavutil/avassert.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +#undef pixel +#undef accumulator +#if DEPTH == 8 +#define pixel uint8_t +#define accumulator int +#else +#define pixel uint16_t +#define accumulator int64_t +#endif + +#define fn3(a,b) a##_##b +#define fn2(a,b) fn3(a,b) +#define fn(a) fn2(a, DEPTH) + +/* + * This macro interpolates the value of both fields at a point halfway + * between lines and takes the squared difference. In field resolution + * the point is a quarter pixel below a line in one field and a quarter + * pixel above a line in other. + * + * (The result is actually multiplied by 25) + */ +#define DIFF(a, as, b, bs) ((t) = ((*(a) - (b)[bs]) << 2) + (a)[(as) << 1] - (b)[-(bs)], (t) * (t)) + +/* + * Find which field combination has the smallest average squared difference + * between the fields. + */ +static enum PhaseMode fn(analyze_plane)(void *ctx, enum PhaseMode mode, AVFrame *old, AVFrame *new) +{ + double bdiff, tdiff, pdiff; + + if (mode == AUTO) { + mode = new->interlaced_frame ? new->top_field_first ? + TOP_FIRST : BOTTOM_FIRST : PROGRESSIVE; + } else if (mode == AUTO_ANALYZE) { + mode = new->interlaced_frame ? new->top_field_first ? + TOP_FIRST_ANALYZE : BOTTOM_FIRST_ANALYZE : FULL_ANALYZE; + } + + if (mode <= BOTTOM_FIRST) { + bdiff = pdiff = tdiff = 65536.0; + } else { + const double factor = 1. / (25. * (1 << (DEPTH - 8)) * (1 << (DEPTH - 8))); + const int ns = new->linesize[0] / sizeof(pixel); + const int os = old->linesize[0] / sizeof(pixel); + const pixel *nptr = (pixel *)new->data[0]; + const pixel *optr = (pixel *)old->data[0]; + const int h = new->height; + const int w = new->width; + accumulator bdif, tdif, pdif; + double scale; + + int top = 0, t; + const pixel *rend, *end = nptr + (h - 2) * ns; + + bdiff = pdiff = tdiff = 0.0; + + nptr += ns; + optr += os; + while (nptr < end) { + pdif = tdif = bdif = 0; + + switch (mode) { + case TOP_FIRST_ANALYZE: + if (top) { + for (rend = nptr + w; nptr < rend; nptr++, optr++) { + pdif += DIFF(nptr, ns, nptr, ns); + tdif += DIFF(nptr, ns, optr, os); + } + } else { + for (rend = nptr + w; nptr < rend; nptr++, optr++) { + pdif += DIFF(nptr, ns, nptr, ns); + tdif += DIFF(optr, os, nptr, ns); + } + } + break; + case BOTTOM_FIRST_ANALYZE: + if (top) { + for (rend = nptr + w; nptr < rend; nptr++, optr++) { + pdif += DIFF(nptr, ns, nptr, ns); + bdif += DIFF(optr, os, nptr, ns); + } + } else { + for (rend = nptr + w; nptr < rend; nptr++, optr++) { + pdif += DIFF(nptr, ns, nptr, ns); + bdif += DIFF(nptr, ns, optr, os); + } + } + break; + case ANALYZE: + if (top) { + for (rend = nptr + w; nptr < rend; nptr++, optr++) { + tdif += DIFF(nptr, ns, optr, os); + bdif += DIFF(optr, os, nptr, ns); + } + } else { + for (rend = nptr + w; nptr < rend; nptr++, optr++) { + bdif += DIFF(nptr, ns, optr, os); + tdif += DIFF(optr, os, nptr, ns); + } + } + break; + case FULL_ANALYZE: + if (top) { + for (rend = nptr + w; nptr < rend; nptr++, optr++) { + pdif += DIFF(nptr, ns, nptr, ns); + tdif += DIFF(nptr, ns, optr, os); + bdif += DIFF(optr, os, nptr, ns); + } + } else { + for (rend = nptr + w; nptr < rend; nptr++, optr++) { + pdif += DIFF(nptr, ns, nptr, ns); + bdif += DIFF(nptr, ns, optr, os); + tdif += DIFF(optr, os, nptr, ns); + } + } + break; + default: + av_assert0(0); + } + + pdiff += (double)pdif; + tdiff += (double)tdif; + bdiff += (double)bdif; + nptr += ns - w; + optr += os - w; + top ^= 1; + } + + scale = 1.0 / (w * (h - 3)) * factor; + pdiff *= scale; + tdiff *= scale; + bdiff *= scale; + + if (mode == TOP_FIRST_ANALYZE) { + bdiff = 65536.0; + } else if (mode == BOTTOM_FIRST_ANALYZE) { + tdiff = 65536.0; + } else if (mode == ANALYZE) { + pdiff = 65536.0; + } + + if (bdiff < pdiff && bdiff < tdiff) { + mode = BOTTOM_FIRST; + } else if (tdiff < pdiff && tdiff < bdiff) { + mode = TOP_FIRST; + } else { + mode = PROGRESSIVE; + } + } + + av_log(ctx, AV_LOG_DEBUG, "mode=%c tdiff=%f bdiff=%f pdiff=%f\n", + mode == BOTTOM_FIRST ? 'b' : mode == TOP_FIRST ? 't' : 'p', + tdiff, bdiff, pdiff); + return mode; +} diff -Nru ffmpeg-4.2.2/libavfilter/qp_table.c ffmpeg-4.4/libavfilter/qp_table.c --- ffmpeg-4.2.2/libavfilter/qp_table.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/qp_table.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * 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 + +// for FF_QSCALE_TYPE_* +#include "libavcodec/internal.h" + +#include "libavutil/frame.h" +#include "libavutil/mem.h" +#include "libavutil/video_enc_params.h" + +#include "qp_table.h" + +int ff_qp_table_extract(AVFrame *frame, int8_t **table, int *table_w, int *table_h, + int *qscale_type) +{ + AVFrameSideData *sd; + AVVideoEncParams *par; + unsigned int mb_h = (frame->height + 15) / 16; + unsigned int mb_w = (frame->width + 15) / 16; + unsigned int nb_mb = mb_h * mb_w; + unsigned int block_idx; + + *table = NULL; + + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_VIDEO_ENC_PARAMS); + if (!sd) + return 0; + par = (AVVideoEncParams*)sd->data; + if (par->type != AV_VIDEO_ENC_PARAMS_MPEG2 || + (par->nb_blocks != 0 && par->nb_blocks != nb_mb)) + return AVERROR(ENOSYS); + + *table = av_malloc(nb_mb); + if (!*table) + return AVERROR(ENOMEM); + if (table_w) + *table_w = mb_w; + if (table_h) + *table_h = mb_h; + if (qscale_type) + *qscale_type = FF_QSCALE_TYPE_MPEG2; + + if (par->nb_blocks == 0) { + memset(*table, par->qp, nb_mb); + return 0; + } + + for (block_idx = 0; block_idx < nb_mb; block_idx++) { + AVVideoBlockParams *b = av_video_enc_params_block(par, block_idx); + (*table)[block_idx] = par->qp + b->delta_qp; + } + + return 0; +} + diff -Nru ffmpeg-4.2.2/libavfilter/qp_table.h ffmpeg-4.4/libavfilter/qp_table.h --- ffmpeg-4.2.2/libavfilter/qp_table.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/qp_table.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#ifndef AVFILTER_QP_TABLE_H +#define AVFILTER_QP_TABLE_H + +#include + +#include "libavutil/frame.h" + +/** + * Extract a libpostproc-compatible QP table - an 8-bit QP value per 16x16 + * macroblock, stored in raster order - from AVVideoEncParams side data. + */ +int ff_qp_table_extract(AVFrame *frame, int8_t **table, int *table_w, int *table_h, + int *qscale_type); + +#endif // AVFILTER_QP_TABLE_H diff -Nru ffmpeg-4.2.2/libavfilter/qsvvpp.c ffmpeg-4.4/libavfilter/qsvvpp.c --- ffmpeg-4.2.2/libavfilter/qsvvpp.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/qsvvpp.c 2021-04-08 21:28:39.000000000 +0000 @@ -76,6 +76,110 @@ static const AVRational default_tb = { 1, 90000 }; +static const struct { + int mfx_iopattern; + const char *desc; +} qsv_iopatterns[] = { + {MFX_IOPATTERN_IN_VIDEO_MEMORY, "input is video memory surface" }, + {MFX_IOPATTERN_IN_SYSTEM_MEMORY, "input is system memory surface" }, + {MFX_IOPATTERN_IN_OPAQUE_MEMORY, "input is opaque memory surface" }, + {MFX_IOPATTERN_OUT_VIDEO_MEMORY, "output is video memory surface" }, + {MFX_IOPATTERN_OUT_SYSTEM_MEMORY, "output is system memory surface" }, + {MFX_IOPATTERN_OUT_OPAQUE_MEMORY, "output is opaque memory surface" }, +}; + +int ff_qsvvpp_print_iopattern(void *log_ctx, int mfx_iopattern, + const char *extra_string) +{ + const char *desc = NULL; + + for (int i = 0; i < FF_ARRAY_ELEMS(qsv_iopatterns); i++) { + if (qsv_iopatterns[i].mfx_iopattern == mfx_iopattern) { + desc = qsv_iopatterns[i].desc; + } + } + if (!desc) + desc = "unknown iopattern"; + + av_log(log_ctx, AV_LOG_VERBOSE, "%s: %s\n", extra_string, desc); + return 0; +} + +static const struct { + mfxStatus mfxerr; + int averr; + const char *desc; +} qsv_errors[] = { + { MFX_ERR_NONE, 0, "success" }, + { MFX_ERR_UNKNOWN, AVERROR_UNKNOWN, "unknown error" }, + { MFX_ERR_NULL_PTR, AVERROR(EINVAL), "NULL pointer" }, + { MFX_ERR_UNSUPPORTED, AVERROR(ENOSYS), "unsupported" }, + { MFX_ERR_MEMORY_ALLOC, AVERROR(ENOMEM), "failed to allocate memory" }, + { MFX_ERR_NOT_ENOUGH_BUFFER, AVERROR(ENOMEM), "insufficient input/output buffer" }, + { MFX_ERR_INVALID_HANDLE, AVERROR(EINVAL), "invalid handle" }, + { MFX_ERR_LOCK_MEMORY, AVERROR(EIO), "failed to lock the memory block" }, + { MFX_ERR_NOT_INITIALIZED, AVERROR_BUG, "not initialized" }, + { MFX_ERR_NOT_FOUND, AVERROR(ENOSYS), "specified object was not found" }, + /* the following 3 errors should always be handled explicitly, so those "mappings" + * are for completeness only */ + { MFX_ERR_MORE_DATA, AVERROR_UNKNOWN, "expect more data at input" }, + { MFX_ERR_MORE_SURFACE, AVERROR_UNKNOWN, "expect more surface at output" }, + { MFX_ERR_MORE_BITSTREAM, AVERROR_UNKNOWN, "expect more bitstream at output" }, + { MFX_ERR_ABORTED, AVERROR_UNKNOWN, "operation aborted" }, + { MFX_ERR_DEVICE_LOST, AVERROR(EIO), "device lost" }, + { MFX_ERR_INCOMPATIBLE_VIDEO_PARAM, AVERROR(EINVAL), "incompatible video parameters" }, + { MFX_ERR_INVALID_VIDEO_PARAM, AVERROR(EINVAL), "invalid video parameters" }, + { MFX_ERR_UNDEFINED_BEHAVIOR, AVERROR_BUG, "undefined behavior" }, + { MFX_ERR_DEVICE_FAILED, AVERROR(EIO), "device failed" }, + { MFX_ERR_INCOMPATIBLE_AUDIO_PARAM, AVERROR(EINVAL), "incompatible audio parameters" }, + { MFX_ERR_INVALID_AUDIO_PARAM, AVERROR(EINVAL), "invalid audio parameters" }, + + { MFX_WRN_IN_EXECUTION, 0, "operation in execution" }, + { MFX_WRN_DEVICE_BUSY, 0, "device busy" }, + { MFX_WRN_VIDEO_PARAM_CHANGED, 0, "video parameters changed" }, + { MFX_WRN_PARTIAL_ACCELERATION, 0, "partial acceleration" }, + { MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, 0, "incompatible video parameters" }, + { MFX_WRN_VALUE_NOT_CHANGED, 0, "value is saturated" }, + { MFX_WRN_OUT_OF_RANGE, 0, "value out of range" }, + { MFX_WRN_FILTER_SKIPPED, 0, "filter skipped" }, + { MFX_WRN_INCOMPATIBLE_AUDIO_PARAM, 0, "incompatible audio parameters" }, +}; + +static int qsv_map_error(mfxStatus mfx_err, const char **desc) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(qsv_errors); i++) { + if (qsv_errors[i].mfxerr == mfx_err) { + if (desc) + *desc = qsv_errors[i].desc; + return qsv_errors[i].averr; + } + } + if (desc) + *desc = "unknown error"; + return AVERROR_UNKNOWN; +} + +int ff_qsvvpp_print_error(void *log_ctx, mfxStatus err, + const char *error_string) +{ + const char *desc; + int ret; + ret = qsv_map_error(err, &desc); + av_log(log_ctx, AV_LOG_ERROR, "%s: %s (%d)\n", error_string, desc, err); + return ret; +} + +int ff_qsvvpp_print_warning(void *log_ctx, mfxStatus err, + const char *warning_string) +{ + const char *desc; + int ret; + ret = qsv_map_error(err, &desc); + av_log(log_ctx, AV_LOG_WARNING, "%s: %s (%d)\n", warning_string, desc, err); + return ret; +} + /* functions for frameAlloc */ static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameAllocResponse *resp) @@ -505,15 +609,19 @@ } } - if (ret != MFX_ERR_NONE) { - av_log(avctx, AV_LOG_ERROR, "Error getting the session handle\n"); + if (ret < 0) + return ff_qsvvpp_print_error(avctx, ret, "Error getting the session handle"); + else if (ret > 0) { + ff_qsvvpp_print_warning(avctx, ret, "Warning in getting the session handle"); return AVERROR_UNKNOWN; } /* create a "slave" session with those same properties, to be used for vpp */ ret = MFXInit(impl, &ver, &s->session); - if (ret != MFX_ERR_NONE) { - av_log(avctx, AV_LOG_ERROR, "Error initializing a session for scaling\n"); + if (ret < 0) + return ff_qsvvpp_print_error(avctx, ret, "Error initializing a session"); + else if (ret > 0) { + ff_qsvvpp_print_warning(avctx, ret, "Warning in session initialization"); return AVERROR_UNKNOWN; } @@ -646,11 +754,16 @@ else if (IS_OPAQUE_MEMORY(s->out_mem_mode)) s->vpp_param.IOPattern |= MFX_IOPATTERN_OUT_OPAQUE_MEMORY; + /* Print input memory mode */ + ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0x0F, "VPP"); + /* Print output memory mode */ + ff_qsvvpp_print_iopattern(avctx, s->vpp_param.IOPattern & 0xF0, "VPP"); ret = MFXVideoVPP_Init(s->session, &s->vpp_param); if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Failed to create a qsvvpp, ret = %d.\n", ret); + ret = ff_qsvvpp_print_error(avctx, ret, "Failed to create a qsvvpp"); goto failed; - } + } else if (ret > 0) + ff_qsvvpp_print_warning(avctx, ret, "Warning When creating qsvvpp"); *vpp = s; return 0; diff -Nru ffmpeg-4.2.2/libavfilter/qsvvpp.h ffmpeg-4.4/libavfilter/qsvvpp.h --- ffmpeg-4.2.2/libavfilter/qsvvpp.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/qsvvpp.h 2021-04-08 21:28:39.000000000 +0000 @@ -71,4 +71,13 @@ /* vpp filter frame and call the cb if needed */ int ff_qsvvpp_filter_frame(QSVVPPContext *vpp, AVFilterLink *inlink, AVFrame *frame); +int ff_qsvvpp_print_iopattern(void *log_ctx, int mfx_iopattern, + const char *extra_string); + +int ff_qsvvpp_print_error(void *log_ctx, mfxStatus err, + const char *error_string); + +int ff_qsvvpp_print_warning(void *log_ctx, mfxStatus err, + const char *warning_string); + #endif /* AVFILTER_QSVVPP_H */ diff -Nru ffmpeg-4.2.2/libavfilter/scale.c ffmpeg-4.4/libavfilter/scale.c --- ffmpeg-4.2.2/libavfilter/scale.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/scale.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2007 Bobby Bingham - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General 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 "scale.h" -#include "libavutil/eval.h" -#include "libavutil/mathematics.h" -#include "libavutil/pixdesc.h" - -static const char *const var_names[] = { - "PI", - "PHI", - "E", - "in_w", "iw", - "in_h", "ih", - "out_w", "ow", - "out_h", "oh", - "a", - "sar", - "dar", - "hsub", - "vsub", - "ohsub", - "ovsub", - NULL -}; - -enum var_name { - VAR_PI, - VAR_PHI, - VAR_E, - 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_HSUB, - VAR_VSUB, - VAR_OHSUB, - VAR_OVSUB, - VARS_NB -}; - -/** - * This must be kept in sync with var_names so that it is always a - * complete list of var_names with the scale2ref specific names - * appended. scale2ref values must appear in the order they appear - * in the var_name_scale2ref enum but also be below all of the - * non-scale2ref specific values. - */ -static const char *const var_names_scale2ref[] = { - "PI", - "PHI", - "E", - "in_w", "iw", - "in_h", "ih", - "out_w", "ow", - "out_h", "oh", - "a", - "sar", - "dar", - "hsub", - "vsub", - "ohsub", - "ovsub", - "main_w", - "main_h", - "main_a", - "main_sar", - "main_dar", "mdar", - "main_hsub", - "main_vsub", - NULL -}; - -enum var_name_scale2ref { - 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_HSUB, - VAR_S2R_MAIN_VSUB, - VARS_S2R_NB -}; - -int ff_scale_eval_dimensions(void *log_ctx, - const char *w_expr, const char *h_expr, - AVFilterLink *inlink, AVFilterLink *outlink, - int *ret_w, int *ret_h) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format); - const char *expr; - int w, h; - int factor_w, factor_h; - int eval_w, eval_h; - int ret; - const char scale2ref = outlink->src->nb_inputs == 2 && outlink->src->inputs[1] == inlink; - double var_values[VARS_NB + VARS_S2R_NB], res; - const AVPixFmtDescriptor *main_desc; - const AVFilterLink *main_link; - const char *const *names = scale2ref ? var_names_scale2ref : var_names; - - if (scale2ref) { - main_link = outlink->src->inputs[0]; - main_desc = av_pix_fmt_desc_get(main_link->format); - } - - var_values[VAR_PI] = M_PI; - var_values[VAR_PHI] = M_PHI; - var_values[VAR_E] = M_E; - var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w; - var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h; - var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN; - var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN; - var_values[VAR_A] = (double) inlink->w / inlink->h; - var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? - (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; - var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; - var_values[VAR_HSUB] = 1 << desc->log2_chroma_w; - var_values[VAR_VSUB] = 1 << desc->log2_chroma_h; - var_values[VAR_OHSUB] = 1 << out_desc->log2_chroma_w; - var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h; - - if (scale2ref) { - var_values[VARS_NB + VAR_S2R_MAIN_W] = main_link->w; - var_values[VARS_NB + VAR_S2R_MAIN_H] = main_link->h; - var_values[VARS_NB + VAR_S2R_MAIN_A] = (double) main_link->w / main_link->h; - var_values[VARS_NB + VAR_S2R_MAIN_SAR] = main_link->sample_aspect_ratio.num ? - (double) main_link->sample_aspect_ratio.num / main_link->sample_aspect_ratio.den : 1; - var_values[VARS_NB + VAR_S2R_MAIN_DAR] = var_values[VARS_NB + VAR_S2R_MDAR] = - var_values[VARS_NB + VAR_S2R_MAIN_A] * var_values[VARS_NB + VAR_S2R_MAIN_SAR]; - var_values[VARS_NB + VAR_S2R_MAIN_HSUB] = 1 << main_desc->log2_chroma_w; - var_values[VARS_NB + VAR_S2R_MAIN_VSUB] = 1 << main_desc->log2_chroma_h; - } - - /* evaluate width and height */ - av_expr_parse_and_eval(&res, (expr = w_expr), - names, var_values, - NULL, NULL, NULL, NULL, NULL, 0, log_ctx); - eval_w = var_values[VAR_OUT_W] = var_values[VAR_OW] = (int) res == 0 ? inlink->w : (int) res; - - if ((ret = av_expr_parse_and_eval(&res, (expr = h_expr), - names, var_values, - NULL, NULL, NULL, NULL, NULL, 0, log_ctx)) < 0) - goto fail; - eval_h = var_values[VAR_OUT_H] = var_values[VAR_OH] = (int) res == 0 ? inlink->h : (int) res; - /* evaluate again the width, as it may depend on the output height */ - if ((ret = av_expr_parse_and_eval(&res, (expr = w_expr), - names, var_values, - NULL, NULL, NULL, NULL, NULL, 0, log_ctx)) < 0) - goto fail; - eval_w = (int) res == 0 ? inlink->w : (int) res; - - w = eval_w; - h = eval_h; - - /* Check if it is requested that the result has to be divisible by a some - * factor (w or h = -n with n being the factor). */ - factor_w = 1; - factor_h = 1; - if (w < -1) { - factor_w = -w; - } - if (h < -1) { - factor_h = -h; - } - - if (w < 0 && h < 0) { - w = inlink->w; - h = inlink->h; - } - - /* Make sure that the result is divisible by the factor we determined - * earlier. If no factor was set, it is nothing will happen as the default - * factor is 1 */ - if (w < 0) - w = av_rescale(h, inlink->w, inlink->h * factor_w) * factor_w; - if (h < 0) - h = av_rescale(w, inlink->h, inlink->w * factor_h) * factor_h; - - *ret_w = w; - *ret_h = h; - - return 0; - -fail: - av_log(log_ctx, AV_LOG_ERROR, - "Error when evaluating the expression '%s'.\n" - "Maybe the expression for out_w:'%s' or for out_h:'%s' is self-referencing.\n", - expr, w_expr, h_expr); - return ret; -} diff -Nru ffmpeg-4.2.2/libavfilter/scale_eval.c ffmpeg-4.4/libavfilter/scale_eval.c --- ffmpeg-4.2.2/libavfilter/scale_eval.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/scale_eval.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2007 Bobby Bingham + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "scale_eval.h" +#include "libavutil/eval.h" +#include "libavutil/mathematics.h" +#include "libavutil/pixdesc.h" + +static const char *const var_names[] = { + "in_w", "iw", + "in_h", "ih", + "out_w", "ow", + "out_h", "oh", + "a", + "sar", + "dar", + "hsub", + "vsub", + "ohsub", + "ovsub", + 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_HSUB, + VAR_VSUB, + VAR_OHSUB, + VAR_OVSUB, + VARS_NB +}; + +int ff_scale_eval_dimensions(void *log_ctx, + const char *w_expr, const char *h_expr, + AVFilterLink *inlink, AVFilterLink *outlink, + int *ret_w, int *ret_h) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format); + const char *expr; + int eval_w, eval_h; + int ret; + double var_values[VARS_NB], res; + + var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w; + var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h; + var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN; + var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN; + var_values[VAR_A] = (double) inlink->w / inlink->h; + var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? + (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; + var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; + var_values[VAR_HSUB] = 1 << desc->log2_chroma_w; + var_values[VAR_VSUB] = 1 << desc->log2_chroma_h; + var_values[VAR_OHSUB] = 1 << out_desc->log2_chroma_w; + var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h; + + /* evaluate width and height */ + av_expr_parse_and_eval(&res, (expr = w_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, log_ctx); + eval_w = var_values[VAR_OUT_W] = var_values[VAR_OW] = (int) res == 0 ? inlink->w : (int) res; + + if ((ret = av_expr_parse_and_eval(&res, (expr = h_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, log_ctx)) < 0) + goto fail; + eval_h = var_values[VAR_OUT_H] = var_values[VAR_OH] = (int) res == 0 ? inlink->h : (int) res; + /* evaluate again the width, as it may depend on the output height */ + if ((ret = av_expr_parse_and_eval(&res, (expr = w_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, log_ctx)) < 0) + goto fail; + eval_w = (int) res == 0 ? inlink->w : (int) res; + + *ret_w = eval_w; + *ret_h = eval_h; + + return 0; + +fail: + av_log(log_ctx, AV_LOG_ERROR, + "Error when evaluating the expression '%s'.\n" + "Maybe the expression for out_w:'%s' or for out_h:'%s' is self-referencing.\n", + expr, w_expr, h_expr); + return ret; +} + +int ff_scale_adjust_dimensions(AVFilterLink *inlink, + int *ret_w, int *ret_h, + int force_original_aspect_ratio, int force_divisible_by) +{ + int w, h; + int factor_w, factor_h; + + w = *ret_w; + h = *ret_h; + + /* Check if it is requested that the result has to be divisible by some + * factor (w or h = -n with n being the factor). */ + factor_w = 1; + factor_h = 1; + if (w < -1) { + factor_w = -w; + } + if (h < -1) { + factor_h = -h; + } + + if (w < 0 && h < 0) { + w = inlink->w; + h = inlink->h; + } + + /* Make sure that the result is divisible by the factor we determined + * earlier. If no factor was set, nothing will happen as the default + * factor is 1 */ + if (w < 0) + w = av_rescale(h, inlink->w, inlink->h * factor_w) * factor_w; + if (h < 0) + h = av_rescale(w, inlink->h, inlink->w * factor_h) * factor_h; + + /* Note that force_original_aspect_ratio may overwrite the previous set + * dimensions so that it is not divisible by the set factors anymore + * unless force_divisible_by is defined as well */ + if (force_original_aspect_ratio) { + int tmp_w = av_rescale(h, inlink->w, inlink->h); + int tmp_h = av_rescale(w, inlink->h, inlink->w); + + if (force_original_aspect_ratio == 1) { + w = FFMIN(tmp_w, w); + h = FFMIN(tmp_h, h); + if (force_divisible_by > 1) { + // round down + w = w / force_divisible_by * force_divisible_by; + h = h / force_divisible_by * force_divisible_by; + } + } else { + w = FFMAX(tmp_w, w); + h = FFMAX(tmp_h, h); + if (force_divisible_by > 1) { + // round up + w = (w + force_divisible_by - 1) / force_divisible_by * force_divisible_by; + h = (h + force_divisible_by - 1) / force_divisible_by * force_divisible_by; + } + } + } + + *ret_w = w; + *ret_h = h; + + return 0; +} diff -Nru ffmpeg-4.2.2/libavfilter/scale_eval.h ffmpeg-4.4/libavfilter/scale_eval.h --- ffmpeg-4.2.2/libavfilter/scale_eval.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/scale_eval.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_SCALE_EVAL_H +#define AVFILTER_SCALE_EVAL_H + +#include "avfilter.h" + +/** + * Parse and evaluate string expressions for width and height. Upon success, + * ff_scale_adjust_dimensions must be called with evaluated width and height + * to obtain actual target dimensions. + * + * Returns 0 upon success, negative value if one of the expressions could + * not be parsed or if NaN was the result of their evaluation. + */ +int ff_scale_eval_dimensions(void *ctx, + const char *w_expr, const char *h_expr, + AVFilterLink *inlink, AVFilterLink *outlink, + int *ret_w, int *ret_h); + +/** + * Transform evaluated width and height obtained from ff_scale_eval_dimensions + * into actual target width and height for scaling. Adjustment can occur if one + * or both of the evaluated values are of the form '-n' or if + * force_original_aspect_ratio is set. + * + * Returns 0. + */ +int ff_scale_adjust_dimensions(AVFilterLink *inlink, + int *ret_w, int *ret_h, + int force_original_aspect_ratio, int force_divisible_by); +#endif diff -Nru ffmpeg-4.2.2/libavfilter/scale.h ffmpeg-4.4/libavfilter/scale.h --- ffmpeg-4.2.2/libavfilter/scale.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/scale.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVFILTER_SCALE_H -#define AVFILTER_SCALE_H - -#include "avfilter.h" - -int ff_scale_eval_dimensions(void *ctx, - const char *w_expr, const char *h_expr, - AVFilterLink *inlink, AVFilterLink *outlink, - int *ret_w, int *ret_h); -#endif diff -Nru ffmpeg-4.2.2/libavfilter/setpts.c ffmpeg-4.4/libavfilter/setpts.c --- ffmpeg-4.2.2/libavfilter/setpts.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/setpts.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,6 +33,7 @@ #include "libavutil/time.h" #include "audio.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" #include "video.h" @@ -141,10 +142,6 @@ return 0; } -#define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d)) -#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) -#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb)) - #define BUF_SIZE 64 static inline char *double2int64str(char *buf, double v) @@ -154,6 +151,28 @@ return buf; } +static double eval_pts(SetPTSContext *setpts, AVFilterLink *inlink, AVFrame *frame, int64_t pts) +{ + if (isnan(setpts->var_values[VAR_STARTPTS])) { + setpts->var_values[VAR_STARTPTS] = TS2D(pts); + setpts->var_values[VAR_STARTT ] = TS2T(pts, inlink->time_base); + } + setpts->var_values[VAR_PTS ] = TS2D(pts); + setpts->var_values[VAR_T ] = TS2T(pts, inlink->time_base); + setpts->var_values[VAR_POS ] = !frame || frame->pkt_pos == -1 ? NAN : frame->pkt_pos; + setpts->var_values[VAR_RTCTIME ] = av_gettime(); + + if (frame) { + if (inlink->type == AVMEDIA_TYPE_VIDEO) { + setpts->var_values[VAR_INTERLACED] = frame->interlaced_frame; + } else if (inlink->type == AVMEDIA_TYPE_AUDIO) { + setpts->var_values[VAR_S] = frame->nb_samples; + setpts->var_values[VAR_NB_SAMPLES] = frame->nb_samples; + } + } + + return av_expr_eval(setpts->expr, setpts->var_values, NULL); +} #define d2istr(v) double2int64str((char[BUF_SIZE]){0}, v) static int filter_frame(AVFilterLink *inlink, AVFrame *frame) @@ -162,23 +181,7 @@ int64_t in_pts = frame->pts; double d; - if (isnan(setpts->var_values[VAR_STARTPTS])) { - setpts->var_values[VAR_STARTPTS] = TS2D(frame->pts); - setpts->var_values[VAR_STARTT ] = TS2T(frame->pts, inlink->time_base); - } - setpts->var_values[VAR_PTS ] = TS2D(frame->pts); - setpts->var_values[VAR_T ] = TS2T(frame->pts, inlink->time_base); - setpts->var_values[VAR_POS ] = frame->pkt_pos == -1 ? NAN : frame->pkt_pos; - setpts->var_values[VAR_RTCTIME ] = av_gettime(); - - if (inlink->type == AVMEDIA_TYPE_VIDEO) { - setpts->var_values[VAR_INTERLACED] = frame->interlaced_frame; - } else if (inlink->type == AVMEDIA_TYPE_AUDIO) { - setpts->var_values[VAR_S] = frame->nb_samples; - setpts->var_values[VAR_NB_SAMPLES] = frame->nb_samples; - } - - d = av_expr_eval(setpts->expr, setpts->var_values, NULL); + d = eval_pts(setpts, inlink, frame, frame->pts); frame->pts = D2TS(d); av_log(inlink->dst, AV_LOG_TRACE, @@ -216,6 +219,41 @@ return ff_filter_frame(inlink->dst->outputs[0], frame); } +static int activate(AVFilterContext *ctx) +{ + SetPTSContext *setpts = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *in; + int status; + int64_t pts; + int ret; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; + if (ret > 0) + return filter_frame(inlink, in); + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + double d = eval_pts(setpts, inlink, NULL, pts); + + av_log(ctx, AV_LOG_TRACE, "N:EOF PTS:%s T:%f POS:%s -> PTS:%s T:%f\n", + d2istr(setpts->var_values[VAR_PTS]), + setpts->var_values[VAR_T], + d2istr(setpts->var_values[VAR_POS]), + d2istr(d), TS2T(d, inlink->time_base)); + ff_outlink_set_status(outlink, status, D2TS(d)); + return 0; + } + + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; +} + static av_cold void uninit(AVFilterContext *ctx) { SetPTSContext *setpts = ctx->priv; @@ -224,14 +262,15 @@ } #define OFFSET(x) offsetof(SetPTSContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM -static const AVOption options[] = { - { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = FLAGS }, - { NULL } -}; +#define V AV_OPT_FLAG_VIDEO_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM +#define F AV_OPT_FLAG_FILTERING_PARAM #if CONFIG_SETPTS_FILTER -#define setpts_options options +static const AVOption setpts_options[] = { + { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = V|F }, + { NULL } +}; AVFILTER_DEFINE_CLASS(setpts); static const AVFilterPad avfilter_vf_setpts_inputs[] = { @@ -239,7 +278,6 @@ .name = "default", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_input, - .filter_frame = filter_frame, }, { NULL } }; @@ -256,6 +294,7 @@ .name = "setpts", .description = NULL_IF_CONFIG_SMALL("Set PTS for the output video frame."), .init = init, + .activate = activate, .uninit = uninit, .priv_size = sizeof(SetPTSContext), @@ -268,7 +307,10 @@ #if CONFIG_ASETPTS_FILTER -#define asetpts_options options +static const AVOption asetpts_options[] = { + { "expr", "Expression determining the frame timestamp", OFFSET(expr_str), AV_OPT_TYPE_STRING, { .str = "PTS" }, .flags = A|F }, + { NULL } +}; AVFILTER_DEFINE_CLASS(asetpts); static const AVFilterPad asetpts_inputs[] = { @@ -276,7 +318,6 @@ .name = "default", .type = AVMEDIA_TYPE_AUDIO, .config_props = config_input, - .filter_frame = filter_frame, }, { NULL } }; @@ -293,6 +334,7 @@ .name = "asetpts", .description = NULL_IF_CONFIG_SMALL("Set PTS for the output audio frame."), .init = init, + .activate = activate, .uninit = uninit, .priv_size = sizeof(SetPTSContext), .priv_class = &asetpts_class, diff -Nru ffmpeg-4.2.2/libavfilter/settb.c ffmpeg-4.4/libavfilter/settb.c --- ffmpeg-4.2.2/libavfilter/settb.c 2016-03-29 02:25:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/settb.c 2020-07-11 10:39:30.000000000 +0000 @@ -34,6 +34,7 @@ #include "libavutil/rational.h" #include "audio.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" #include "video.h" @@ -104,22 +105,58 @@ return 0; } -static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +static int64_t rescale_pts(AVFilterLink *inlink, AVFilterLink *outlink, int64_t orig_pts) { AVFilterContext *ctx = inlink->dst; - AVFilterLink *outlink = ctx->outputs[0]; + int64_t new_pts = orig_pts; if (av_cmp_q(inlink->time_base, outlink->time_base)) { - int64_t orig_pts = frame->pts; - frame->pts = av_rescale_q(frame->pts, inlink->time_base, outlink->time_base); + new_pts = av_rescale_q(orig_pts, inlink->time_base, outlink->time_base); av_log(ctx, AV_LOG_DEBUG, "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n", inlink ->time_base.num, inlink ->time_base.den, orig_pts, - outlink->time_base.num, outlink->time_base.den, frame->pts); + outlink->time_base.num, outlink->time_base.den, new_pts); } + return new_pts; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + + frame->pts = rescale_pts(inlink, outlink, frame->pts); + return ff_filter_frame(outlink, frame); } +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *in; + int status; + int64_t pts; + int ret; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; + if (ret > 0) + return filter_frame(inlink, in); + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + ff_outlink_set_status(outlink, status, rescale_pts(inlink, outlink, pts)); + return 0; + } + + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; +} + #if CONFIG_SETTB_FILTER DEFINE_OPTIONS(settb, VIDEO); @@ -129,7 +166,6 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = filter_frame, }, { NULL } }; @@ -150,6 +186,7 @@ .priv_class = &settb_class, .inputs = avfilter_vf_settb_inputs, .outputs = avfilter_vf_settb_outputs, + .activate = activate, }; #endif /* CONFIG_SETTB_FILTER */ @@ -162,7 +199,6 @@ { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, }, { NULL } }; @@ -183,5 +219,6 @@ .inputs = avfilter_af_asettb_inputs, .outputs = avfilter_af_asettb_outputs, .priv_class = &asettb_class, + .activate = activate, }; #endif /* CONFIG_ASETTB_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/split.c ffmpeg-4.4/libavfilter/split.c --- ffmpeg-4.2.2/libavfilter/split.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/split.c 2020-07-11 10:39:30.000000000 +0000 @@ -26,6 +26,7 @@ #include #include "libavutil/attributes.h" +#include "libavutil/avstring.h" #include "libavutil/internal.h" #include "libavutil/mem.h" #include "libavutil/opt.h" @@ -48,12 +49,10 @@ int i, ret; for (i = 0; i < s->nb_outputs; i++) { - char name[32]; AVFilterPad pad = { 0 }; - snprintf(name, sizeof(name), "output%d", i); pad.type = ctx->filter->inputs[0].type; - pad.name = av_strdup(name); + pad.name = av_asprintf("output%d", i); if (!pad.name) return AVERROR(ENOMEM); diff -Nru ffmpeg-4.2.2/libavfilter/src_movie.c ffmpeg-4.4/libavfilter/src_movie.c --- ffmpeg-4.2.2/libavfilter/src_movie.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/src_movie.c 2021-04-08 21:28:39.000000000 +0000 @@ -51,7 +51,6 @@ typedef struct MovieStream { AVStream *st; AVCodecContext *codec_ctx; - int done; int64_t discontinuity_threshold; int64_t last_pts; } MovieStream; @@ -70,8 +69,6 @@ int64_t ts_offset; AVFormatContext *format_ctx; - int eof; - AVPacket pkt, pkt0; int max_stream_index; /**< max stream # actually used for output */ MovieStream *st; /**< array of all streams, one per output */ @@ -89,8 +86,8 @@ { "si", "set stream index", OFFSET(stream_index), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, { "seek_point", "set seekpoint (seconds)", OFFSET(seek_point_d), AV_OPT_TYPE_DOUBLE, { .dbl = 0 }, 0, (INT64_MAX-1) / 1000000, FLAGS }, { "sp", "set seekpoint (seconds)", OFFSET(seek_point_d), AV_OPT_TYPE_DOUBLE, { .dbl = 0 }, 0, (INT64_MAX-1) / 1000000, FLAGS }, - { "streams", "set streams", OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str = 0}, CHAR_MAX, CHAR_MAX, FLAGS }, - { "s", "set streams", OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str = 0}, CHAR_MAX, CHAR_MAX, FLAGS }, + { "streams", "set streams", OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str = 0}, 0, 0, FLAGS }, + { "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 }, { NULL }, @@ -153,14 +150,14 @@ return found; } -static int open_stream(void *log, MovieStream *st) +static int open_stream(AVFilterContext *ctx, MovieStream *st) { - AVCodec *codec; + const AVCodec *codec; int ret; codec = avcodec_find_decoder(st->st->codecpar->codec_id); if (!codec) { - av_log(log, AV_LOG_ERROR, "Failed to find any codec\n"); + av_log(ctx, AV_LOG_ERROR, "Failed to find any codec\n"); return AVERROR(EINVAL); } @@ -172,10 +169,10 @@ if (ret < 0) return ret; - st->codec_ctx->refcounted_frames = 1; + st->codec_ctx->thread_count = ff_filter_get_nb_threads(ctx); if ((ret = avcodec_open2(st->codec_ctx, codec, NULL)) < 0) { - av_log(log, AV_LOG_ERROR, "Failed to open codec\n"); + av_log(ctx, AV_LOG_ERROR, "Failed to open codec\n"); return ret; } @@ -212,7 +209,6 @@ int64_t timestamp; int nb_streams = 1, ret, i; char default_streams[16], *stream_specs, *spec, *cursor; - char name[16]; AVStream *st; if (!movie->file_name) { @@ -304,9 +300,8 @@ for (i = 0; i < nb_streams; i++) { AVFilterPad pad = { 0 }; movie->out_index[movie->st[i].st->index] = i; - snprintf(name, sizeof(name), "out%d", i); pad.type = movie->st[i].st->codecpar->codec_type; - pad.name = av_strdup(name); + pad.name = av_asprintf("out%d", i); if (!pad.name) return AVERROR(ENOMEM); pad.config_props = movie_config_output_props; @@ -364,19 +359,19 @@ switch (c->codec_type) { case AVMEDIA_TYPE_VIDEO: list[0] = c->format; - if ((ret = ff_formats_ref(ff_make_format_list(list), &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(list), &outlink->incfg.formats)) < 0) return ret; break; case AVMEDIA_TYPE_AUDIO: list[0] = c->format; - if ((ret = ff_formats_ref(ff_make_format_list(list), &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(list), &outlink->incfg.formats)) < 0) return ret; list[0] = c->sample_rate; - if ((ret = ff_formats_ref(ff_make_format_list(list), &outlink->in_samplerates)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(list), &outlink->incfg.samplerates)) < 0) return ret; list64[0] = c->channel_layout; - if ((ret = ff_channel_layouts_ref(avfilter_make_format64_list(list64), - &outlink->in_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(ff_make_format64_list(list64), + &outlink->incfg.channel_layouts)) < 0) return ret; break; } @@ -451,113 +446,69 @@ for (i = 0; i < ctx->nb_outputs; i++) { avcodec_flush_buffers(movie->st[i].codec_ctx); - movie->st[i].done = 0; } - movie->eof = 0; return 0; } +static int movie_decode_packet(AVFilterContext *ctx) +{ + MovieContext *movie = ctx->priv; + AVPacket pkt = { 0 }; + int pkt_out_id, ret; + + /* read a new packet from input stream */ + ret = av_read_frame(movie->format_ctx, &pkt); + if (ret == AVERROR_EOF) { + /* EOF -> set all decoders for flushing */ + for (int i = 0; i < ctx->nb_outputs; i++) { + ret = avcodec_send_packet(movie->st[i].codec_ctx, NULL); + if (ret < 0 && ret != AVERROR_EOF) + return ret; + } + + return 0; + } else if (ret < 0) + return ret; + + /* send the packet to its decoder, if any */ + pkt_out_id = pkt.stream_index > movie->max_stream_index ? -1 : + movie->out_index[pkt.stream_index]; + if (pkt_out_id >= 0) + ret = avcodec_send_packet(movie->st[pkt_out_id].codec_ctx, &pkt); + av_packet_unref(&pkt); + + return ret; +} + /** * Try to push a frame to the requested output. * * @param ctx filter context * @param out_id number of output where a frame is wanted; - * if the frame is read from file, used to set the return value; - * if the codec is being flushed, flush the corresponding stream - * @return 1 if a frame was pushed on the requested output, - * 0 if another attempt is possible, - * <0 AVERROR code + * @return 0 if a frame was pushed on the requested output, + * AVERROR(EAGAIN) if the decoder requires more input + * AVERROR(EOF) if the decoder has been completely flushed + * <0 AVERROR code */ static int movie_push_frame(AVFilterContext *ctx, unsigned out_id) { - MovieContext *movie = ctx->priv; - AVPacket *pkt = &movie->pkt; - enum AVMediaType frame_type; - MovieStream *st; - int ret, got_frame = 0, pkt_out_id; - AVFilterLink *outlink; + MovieContext *movie = ctx->priv; + MovieStream *st = &movie->st[out_id]; + AVFilterLink *outlink = ctx->outputs[out_id]; AVFrame *frame; - - if (!pkt->size) { - if (movie->eof) { - if (movie->st[out_id].done) { - if (movie->loop_count != 1) { - ret = rewind_file(ctx); - if (ret < 0) - return ret; - movie->loop_count -= movie->loop_count > 1; - av_log(ctx, AV_LOG_VERBOSE, "Stream finished, looping.\n"); - return 0; /* retry */ - } - return AVERROR_EOF; - } - pkt->stream_index = movie->st[out_id].st->index; - /* packet is already ready for flushing */ - } else { - ret = av_read_frame(movie->format_ctx, &movie->pkt0); - if (ret < 0) { - av_init_packet(&movie->pkt0); /* ready for flushing */ - *pkt = movie->pkt0; - if (ret == AVERROR_EOF) { - movie->eof = 1; - return 0; /* start flushing */ - } - return ret; - } - *pkt = movie->pkt0; - } - } - - pkt_out_id = pkt->stream_index > movie->max_stream_index ? -1 : - movie->out_index[pkt->stream_index]; - if (pkt_out_id < 0) { - av_packet_unref(&movie->pkt0); - pkt->size = 0; /* ready for next run */ - pkt->data = NULL; - return 0; - } - st = &movie->st[pkt_out_id]; - outlink = ctx->outputs[pkt_out_id]; + int ret; frame = av_frame_alloc(); if (!frame) return AVERROR(ENOMEM); - frame_type = st->st->codecpar->codec_type; - switch (frame_type) { - case AVMEDIA_TYPE_VIDEO: - ret = avcodec_decode_video2(st->codec_ctx, frame, &got_frame, pkt); - break; - case AVMEDIA_TYPE_AUDIO: - ret = avcodec_decode_audio4(st->codec_ctx, frame, &got_frame, pkt); - break; - default: - ret = AVERROR(ENOSYS); - break; - } + ret = avcodec_receive_frame(st->codec_ctx, frame); if (ret < 0) { - av_log(ctx, AV_LOG_WARNING, "Decode error: %s\n", av_err2str(ret)); - av_frame_free(&frame); - av_packet_unref(&movie->pkt0); - movie->pkt.size = 0; - movie->pkt.data = NULL; - return 0; - } - if (!ret || st->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) - ret = pkt->size; + if (ret != AVERROR_EOF && ret != AVERROR(EAGAIN)) + av_log(ctx, AV_LOG_WARNING, "Decode error: %s\n", av_err2str(ret)); - pkt->data += ret; - pkt->size -= ret; - if (pkt->size <= 0) { - av_packet_unref(&movie->pkt0); - pkt->size = 0; /* ready for next run */ - pkt->data = NULL; - } - if (!got_frame) { - if (!ret) - st->done = 1; av_frame_free(&frame); - return 0; + return ret; } frame->pts = frame->best_effort_timestamp; @@ -568,7 +519,7 @@ if (st->last_pts != AV_NOPTS_VALUE) { int64_t diff = frame->pts - st->last_pts; if (diff < 0 || diff > st->discontinuity_threshold) { - av_log(ctx, AV_LOG_VERBOSE, "Discontinuity in stream:%d diff:%"PRId64"\n", pkt_out_id, diff); + av_log(ctx, AV_LOG_VERBOSE, "Discontinuity in stream:%d diff:%"PRId64"\n", out_id, diff); movie->ts_offset += av_rescale_q_rnd(-diff, outlink->time_base, AV_TIME_BASE_Q, AV_ROUND_UP); frame->pts -= diff; } @@ -577,7 +528,8 @@ st->last_pts = frame->pts; } ff_dlog(ctx, "movie_push_frame(): file:'%s' %s\n", movie->file_name, - describe_frame_to_str((char[1024]){0}, 1024, frame, frame_type, outlink)); + describe_frame_to_str((char[1024]){0}, 1024, frame, + st->st->codecpar->codec_type, outlink)); if (st->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (frame->format != outlink->format) { @@ -593,19 +545,49 @@ if (ret < 0) return ret; - return pkt_out_id == out_id; + return 0; } static int movie_request_frame(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; + MovieContext *movie = ctx->priv; unsigned out_id = FF_OUTLINK_IDX(outlink); - int ret; while (1) { - ret = movie_push_frame(ctx, out_id); - if (ret) - return FFMIN(ret, 0); + int got_eagain = 0, got_eof = 0; + int ret = 0; + + /* check all decoders for available output */ + for (int i = 0; i < ctx->nb_outputs; i++) { + ret = movie_push_frame(ctx, i); + if (ret == AVERROR(EAGAIN)) + got_eagain++; + else if (ret == AVERROR_EOF) + got_eof++; + else if (ret < 0) + return ret; + else if (i == out_id) + return 0; + } + + if (got_eagain) { + /* all decoders require more input -> read a new packet */ + ret = movie_decode_packet(ctx); + if (ret < 0) + return ret; + } else if (got_eof) { + /* all decoders flushed */ + if (movie->loop_count != 1) { + ret = rewind_file(ctx); + if (ret < 0) + return ret; + movie->loop_count -= movie->loop_count > 1; + av_log(ctx, AV_LOG_VERBOSE, "Stream finished, looping.\n"); + continue; + } + return AVERROR_EOF; + } } } @@ -629,7 +611,6 @@ for (i = 0; i < ctx->nb_outputs; i++) { avcodec_flush_buffers(movie->st[i].codec_ctx); - movie->st[i].done = 0; } return ret; } else if (!strcmp(cmd, "get_duration")) { diff -Nru ffmpeg-4.2.2/libavfilter/ssim.h ffmpeg-4.4/libavfilter/ssim.h --- ffmpeg-4.2.2/libavfilter/ssim.h 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavfilter/ssim.h 2020-07-11 10:39:30.000000000 +0000 @@ -28,7 +28,7 @@ void (*ssim_4x4_line)(const uint8_t *buf, ptrdiff_t buf_stride, const uint8_t *ref, ptrdiff_t ref_stride, int (*sums)[4], int w); - float (*ssim_end_line)(const int (*sum0)[4], const int (*sum1)[4], int w); + double (*ssim_end_line)(const int (*sum0)[4], const int (*sum1)[4], int w); } SSIMDSPContext; void ff_ssim_init_x86(SSIMDSPContext *dsp); diff -Nru ffmpeg-4.2.2/libavfilter/tests/filtfmts.c ffmpeg-4.4/libavfilter/tests/filtfmts.c --- ffmpeg-4.2.2/libavfilter/tests/filtfmts.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/tests/filtfmts.c 2021-04-08 21:28:39.000000000 +0000 @@ -40,7 +40,7 @@ for (i = 0; i < filter_ctx->nb_##inout##puts; i++) { \ if (filter_ctx->inout##puts[i]->type == AVMEDIA_TYPE_VIDEO) { \ AVFilterFormats *fmts = \ - filter_ctx->inout##puts[i]->outin##_formats; \ + filter_ctx->inout##puts[i]->outin##cfg.formats; \ for (j = 0; j < fmts->nb_formats; j++) \ if(av_get_pix_fmt_name(fmts->formats[j])) \ printf(#INOUT "PUT[%d] %s: fmt:%s\n", \ @@ -50,13 +50,13 @@ AVFilterFormats *fmts; \ AVFilterChannelLayouts *layouts; \ \ - fmts = filter_ctx->inout##puts[i]->outin##_formats; \ + fmts = filter_ctx->inout##puts[i]->outin##cfg.formats; \ for (j = 0; j < fmts->nb_formats; j++) \ printf(#INOUT "PUT[%d] %s: fmt:%s\n", \ i, avfilter_pad_get_name(filter_ctx->inout##put_pads, i), \ av_get_sample_fmt_name(fmts->formats[j])); \ \ - layouts = filter_ctx->inout##puts[i]->outin##_channel_layouts; \ + layouts = filter_ctx->inout##puts[i]->outin##cfg.channel_layouts; \ for (j = 0; j < layouts->nb_channel_layouts; j++) { \ char buf[256]; \ av_get_channel_layout_string(buf, sizeof(buf), -1, \ diff -Nru ffmpeg-4.2.2/libavfilter/tests/formats.c ffmpeg-4.4/libavfilter/tests/formats.c --- ffmpeg-4.2.2/libavfilter/tests/formats.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/tests/formats.c 2020-07-11 10:39:30.000000000 +0000 @@ -22,6 +22,78 @@ #undef printf +const int64_t avfilter_all_channel_layouts[] = { + AV_CH_FRONT_CENTER, + AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY, + AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER, + AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_CENTER, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER, + AV_CH_FRONT_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_CENTER|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_LOW_FREQUENCY|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT|AV_CH_FRONT_CENTER|AV_CH_BACK_CENTER|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT, + -1 +}; + int main(void) { const int64_t *cl; diff -Nru ffmpeg-4.2.2/libavfilter/tinterlace.h ffmpeg-4.4/libavfilter/tinterlace.h --- ffmpeg-4.2.2/libavfilter/tinterlace.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/tinterlace.h 2021-04-08 21:28:39.000000000 +0000 @@ -36,6 +36,13 @@ #define TINTERLACE_FLAG_VLPF 01 #define TINTERLACE_FLAG_CVLPF 2 #define TINTERLACE_FLAG_EXACT_TB 4 +#define TINTERLACE_FLAG_BYPASS_IL 8 + +enum VLPFilter { + VLPF_OFF = 0, + VLPF_LIN = 1, + VLPF_CMP = 2, +}; enum TInterlaceMode { MODE_MERGE = 0, @@ -59,7 +66,7 @@ int mode; ///< TInterlaceMode, interlace mode selected AVRational preout_time_base; int flags; ///< flags affecting interlacing algorithm - int frame; ///< number of the output frame + int lowpass; ///< legacy interlace filter lowpass mode int vsub; ///< chroma vertical subsampling AVFrame *cur; AVFrame *next; diff -Nru ffmpeg-4.2.2/libavfilter/transform.c ffmpeg-4.4/libavfilter/transform.c --- ffmpeg-4.2.2/libavfilter/transform.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavfilter/transform.c 2020-07-11 10:39:30.000000000 +0000 @@ -103,12 +103,19 @@ } } -void avfilter_get_matrix(float x_shift, float y_shift, float angle, float zoom, float *matrix) { - matrix[0] = zoom * cos(angle); +void ff_get_matrix( + float x_shift, + float y_shift, + float angle, + float scale_x, + float scale_y, + float *matrix +) { + matrix[0] = scale_x * cos(angle); matrix[1] = -sin(angle); matrix[2] = x_shift; matrix[3] = -matrix[1]; - matrix[4] = matrix[0]; + matrix[4] = scale_y * cos(angle); matrix[5] = y_shift; matrix[6] = 0; matrix[7] = 0; diff -Nru ffmpeg-4.2.2/libavfilter/transform.h ffmpeg-4.4/libavfilter/transform.h --- ffmpeg-4.2.2/libavfilter/transform.h 2016-03-29 02:25:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/transform.h 2020-07-11 10:39:30.000000000 +0000 @@ -60,20 +60,28 @@ #define FILL_DEFAULT FILL_ORIGINAL /** - * Get an affine transformation matrix from a given translation, rotation, and - * zoom factor. The matrix will look like: + * Get an affine transformation matrix from given translation, rotation, and + * zoom factors. The matrix will look like: * - * [ zoom * cos(angle), -sin(angle), x_shift, - * sin(angle), zoom * cos(angle), y_shift, - * 0, 0, 1 ] + * [ scale_x * cos(angle), -sin(angle), x_shift, + * sin(angle), scale_y * cos(angle), y_shift, + * 0, 0, 1 ] * - * @param x_shift horizontal translation - * @param y_shift vertical translation - * @param angle rotation in radians - * @param zoom scale percent (1.0 = 100%) - * @param matrix 9-item affine transformation matrix + * @param x_shift horizontal translation + * @param y_shift vertical translation + * @param angle rotation in radians + * @param scale_x x scale percent (1.0 = 100%) + * @param scale_y y scale percent (1.0 = 100%) + * @param matrix 9-item affine transformation matrix */ -void avfilter_get_matrix(float x_shift, float y_shift, float angle, float zoom, float *matrix); +void ff_get_matrix( + float x_shift, + float y_shift, + float angle, + float scale_x, + float scale_y, + float *matrix +); /** * Add two matrices together. result = m1 + m2. diff -Nru ffmpeg-4.2.2/libavfilter/transpose.h ffmpeg-4.4/libavfilter/transpose.h --- ffmpeg-4.2.2/libavfilter/transpose.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/transpose.h 2020-07-11 10:39:30.000000000 +0000 @@ -18,6 +18,9 @@ #ifndef AVFILTER_TRANSPOSE_H #define AVFILTER_TRANSPOSE_H +#include +#include + enum PassthroughType { TRANSPOSE_PT_TYPE_NONE, TRANSPOSE_PT_TYPE_LANDSCAPE, @@ -34,4 +37,14 @@ TRANSPOSE_VFLIP, }; +typedef struct TransVtable { + void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize, + uint8_t *dst, ptrdiff_t dst_linesize); + void (*transpose_block)(uint8_t *src, ptrdiff_t src_linesize, + uint8_t *dst, ptrdiff_t dst_linesize, + int w, int h); +} TransVtable; + +void ff_transpose_init_x86(TransVtable *v, int pixstep); + #endif diff -Nru ffmpeg-4.2.2/libavfilter/trim.c ffmpeg-4.4/libavfilter/trim.c --- ffmpeg-4.2.2/libavfilter/trim.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/trim.c 2020-07-11 10:39:30.000000000 +0000 @@ -300,7 +300,8 @@ s->nb_samples += frame->nb_samples; start_sample = FFMAX(0, start_sample); end_sample = FFMIN(frame->nb_samples, end_sample); - av_assert0(start_sample < end_sample || (start_sample == end_sample && !frame->nb_samples)); + if (start_sample >= end_sample || !frame->nb_samples) + goto drop; if (start_sample) { AVFrame *out = ff_get_audio_buffer(ctx->outputs[0], end_sample - start_sample); diff -Nru ffmpeg-4.2.2/libavfilter/unsharp.h ffmpeg-4.4/libavfilter/unsharp.h --- ffmpeg-4.2.2/libavfilter/unsharp.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/unsharp.h 2021-04-08 21:28:39.000000000 +0000 @@ -48,9 +48,12 @@ UnsharpFilterParam luma; ///< luma parameters (width, height, amount) UnsharpFilterParam chroma; ///< chroma parameters (width, height, amount) int hsub, vsub; + int bitdepth; + int bps; int nb_threads; int opencl; int (* apply_unsharp)(AVFilterContext *ctx, AVFrame *in, AVFrame *out); + int (* unsharp_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } UnsharpContext; #endif /* AVFILTER_UNSHARP_H */ diff -Nru ffmpeg-4.2.2/libavfilter/v360.h ffmpeg-4.4/libavfilter/v360.h --- ffmpeg-4.2.2/libavfilter/v360.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/v360.h 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2019 Eugene Lyapustin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_V360_H +#define AVFILTER_V360_H +#include "avfilter.h" + +enum StereoFormats { + STEREO_2D, + STEREO_SBS, + STEREO_TB, + NB_STEREO_FMTS, +}; + +enum Projections { + EQUIRECTANGULAR, + CUBEMAP_3_2, + CUBEMAP_6_1, + EQUIANGULAR, + FLAT, + DUAL_FISHEYE, + BARREL, + CUBEMAP_1_6, + STEREOGRAPHIC, + MERCATOR, + BALL, + HAMMER, + SINUSOIDAL, + FISHEYE, + PANNINI, + CYLINDRICAL, + PERSPECTIVE, + TETRAHEDRON, + BARREL_SPLIT, + TSPYRAMID, + HEQUIRECTANGULAR, + EQUISOLID, + ORTHOGRAPHIC, + OCTAHEDRON, + NB_PROJECTIONS, +}; + +enum InterpMethod { + NEAREST, + BILINEAR, + LAGRANGE9, + BICUBIC, + LANCZOS, + SPLINE16, + GAUSSIAN, + MITCHELL, + NB_INTERP_METHODS, +}; + +enum Faces { + TOP_LEFT, + TOP_MIDDLE, + TOP_RIGHT, + BOTTOM_LEFT, + BOTTOM_MIDDLE, + BOTTOM_RIGHT, + NB_FACES, +}; + +enum Direction { + RIGHT, ///< Axis +X + LEFT, ///< Axis -X + UP, ///< Axis +Y + DOWN, ///< Axis -Y + FRONT, ///< Axis -Z + BACK, ///< Axis +Z + NB_DIRECTIONS, +}; + +enum Rotation { + ROT_0, + ROT_90, + ROT_180, + ROT_270, + NB_ROTATIONS, +}; + +enum RotationOrder { + YAW, + PITCH, + ROLL, + NB_RORDERS, +}; + +typedef struct XYRemap { + int16_t u[4][4]; + int16_t v[4][4]; + float ker[4][4]; +} XYRemap; + +typedef struct SliceXYRemap { + int16_t *u[2], *v[2]; + int16_t *ker[2]; + uint8_t *mask; +} SliceXYRemap; + +typedef struct V360Context { + const AVClass *class; + int in, out; + int interp; + int alpha; + int width, height; + char *in_forder; + char *out_forder; + char *in_frot; + char *out_frot; + char *rorder; + + int in_cubemap_face_order[6]; + int out_cubemap_direction_order[6]; + int in_cubemap_face_rotation[6]; + int out_cubemap_face_rotation[6]; + int rotation_order[3]; + + int in_stereo, out_stereo; + + float in_pad, out_pad; + int fin_pad, fout_pad; + + float yaw, pitch, roll; + + int ih_flip, iv_flip; + int h_flip, v_flip, d_flip; + int in_transpose, out_transpose; + + float h_fov, v_fov, d_fov; + float ih_fov, iv_fov, id_fov; + float flat_range[2]; + float iflat_range[2]; + + float rot_quaternion[2][4]; + + float output_mirror_modifier[3]; + + int in_width, in_height; + int out_width, out_height; + + int pr_width[4], pr_height[4]; + + int in_offset_w[4], in_offset_h[4]; + int out_offset_w[4], out_offset_h[4]; + + int planewidth[4], planeheight[4]; + int inplanewidth[4], inplaneheight[4]; + int uv_linesize[4]; + int nb_planes; + int nb_allocated; + int elements; + int mask_size; + int max_value; + int nb_threads; + + SliceXYRemap *slice_remap; + unsigned map[4]; + + int (*in_transform)(const struct V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv); + + int (*out_transform)(const struct V360Context *s, + int i, int j, int width, int height, + float *vec); + + void (*calculate_kernel)(float du, float dv, const XYRemap *rmap, + int16_t *u, int16_t *v, int16_t *ker); + + int (*remap_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + + void (*remap_line)(uint8_t *dst, int width, const uint8_t *const src, ptrdiff_t in_linesize, + const int16_t *const u, const int16_t *const v, const int16_t *const ker); +} V360Context; + +void ff_v360_init(V360Context *s, int depth); +void ff_v360_init_x86(V360Context *s, int depth); + +#endif /* AVFILTER_V360_H */ diff -Nru ffmpeg-4.2.2/libavfilter/vaapi_vpp.c ffmpeg-4.4/libavfilter/vaapi_vpp.c --- ffmpeg-4.2.2/libavfilter/vaapi_vpp.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vaapi_vpp.c 2021-04-08 21:28:39.000000000 +0000 @@ -32,10 +32,10 @@ int err; if ((err = ff_formats_ref(ff_make_format_list(pix_fmts), - &avctx->inputs[0]->out_formats)) < 0) + &avctx->inputs[0]->outcfg.formats)) < 0) return err; if ((err = ff_formats_ref(ff_make_format_list(pix_fmts), - &avctx->outputs[0]->in_formats)) < 0) + &avctx->outputs[0]->incfg.formats)) < 0) return err; return 0; diff -Nru ffmpeg-4.2.2/libavfilter/vaf_spectrumsynth.c ffmpeg-4.4/libavfilter/vaf_spectrumsynth.c --- ffmpeg-4.2.2/libavfilter/vaf_spectrumsynth.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vaf_spectrumsynth.c 2021-04-08 21:28:39.000000000 +0000 @@ -34,6 +34,7 @@ #include "formats.h" #include "audio.h" #include "video.h" +#include "filters.h" #include "internal.h" #include "window_func.h" @@ -114,28 +115,28 @@ int ret, sample_rates[] = { 48000, -1 }; formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref (formats, &outlink->in_formats )) < 0 || + if ((ret = ff_formats_ref (formats, &outlink->incfg.formats )) < 0 || (ret = ff_add_channel_layout (&layout, FF_COUNT2LAYOUT(s->channels))) < 0 || - (ret = ff_channel_layouts_ref (layout , &outlink->in_channel_layouts)) < 0) + (ret = ff_channel_layouts_ref (layout , &outlink->incfg.channel_layouts)) < 0) return ret; sample_rates[0] = s->sample_rate; formats = ff_make_format_list(sample_rates); if (!formats) return AVERROR(ENOMEM); - if ((ret = ff_formats_ref(formats, &outlink->in_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.samplerates)) < 0) return ret; formats = ff_make_format_list(pix_fmts); if (!formats) return AVERROR(ENOMEM); - if ((ret = ff_formats_ref(formats, &magnitude->out_formats)) < 0) + if ((ret = ff_formats_ref(formats, &magnitude->outcfg.formats)) < 0) return ret; formats = ff_make_format_list(pix_fmts); if (!formats) return AVERROR(ENOMEM); - if ((ret = ff_formats_ref(formats, &phase->out_formats)) < 0) + if ((ret = ff_formats_ref(formats, &phase->outcfg.formats)) < 0) return ret; return 0; @@ -222,25 +223,6 @@ return 0; } -static int request_frame(AVFilterLink *outlink) -{ - AVFilterContext *ctx = outlink->src; - SpectrumSynthContext *s = ctx->priv; - int ret; - - if (!s->magnitude) { - ret = ff_request_frame(ctx->inputs[0]); - if (ret < 0) - return ret; - } - if (!s->phase) { - ret = ff_request_frame(ctx->inputs[1]); - if (ret < 0) - return ret; - } - return 0; -} - static void read16_fft_bin(SpectrumSynthContext *s, int x, int y, int f, int ch) { @@ -470,22 +452,43 @@ return ret; } -static int filter_frame_magnitude(AVFilterLink *inlink, AVFrame *magnitude) +static int activate(AVFilterContext *ctx) { - AVFilterContext *ctx = inlink->dst; SpectrumSynthContext *s = ctx->priv; + AVFrame **staging[2] = { &s->magnitude, &s->phase }; + int64_t pts; + int i, ret; - s->magnitude = magnitude; - return try_push_frames(ctx); -} + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); -static int filter_frame_phase(AVFilterLink *inlink, AVFrame *phase) -{ - AVFilterContext *ctx = inlink->dst; - SpectrumSynthContext *s = ctx->priv; + for (i = 0; i < 2; i++) { + if (*staging[i]) + continue; + ret = ff_inlink_consume_frame(ctx->inputs[i], staging[i]); + if (ret < 0) + return ret; + if (ret) { + ff_filter_set_ready(ctx, 10); + return try_push_frames(ctx); + } + } + + for (i = 0; i < 2; i++) { + if (ff_inlink_acknowledge_status(ctx->inputs[i], &ret, &pts)) { + ff_outlink_set_status(ctx->outputs[0], ret, pts); + ff_inlink_set_status(ctx->inputs[1 - i], ret); + return 0; + } + } + + if (ff_outlink_frame_wanted(ctx->outputs[0])) { + for (i = 0; i < 2; i++) { + if (!*staging[i]) + ff_inlink_request_frame(ctx->inputs[i]); + } + } - s->phase = phase; - return try_push_frames(ctx); + return FFERROR_NOT_READY; } static av_cold void uninit(AVFilterContext *ctx) @@ -509,14 +512,10 @@ { .name = "magnitude", .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = filter_frame_magnitude, - .needs_fifo = 1, }, { .name = "phase", .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = filter_frame_phase, - .needs_fifo = 1, }, { NULL } }; @@ -526,7 +525,6 @@ .name = "default", .type = AVMEDIA_TYPE_AUDIO, .config_props = config_output, - .request_frame = request_frame, }, { NULL } }; @@ -536,6 +534,7 @@ .description = NULL_IF_CONFIG_SMALL("Convert input spectrum videos to audio output."), .uninit = uninit, .query_formats = query_formats, + .activate = activate, .priv_size = sizeof(SpectrumSynthContext), .inputs = spectrumsynth_inputs, .outputs = spectrumsynth_outputs, diff -Nru ffmpeg-4.2.2/libavfilter/version.h ffmpeg-4.4/libavfilter/version.h --- ffmpeg-4.2.2/libavfilter/version.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/version.h 2021-04-08 21:28:39.000000000 +0000 @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 57 +#define LIBAVFILTER_VERSION_MINOR 110 #define LIBAVFILTER_VERSION_MICRO 100 @@ -59,8 +59,17 @@ #ifndef FF_API_FILTER_GET_SET #define FF_API_FILTER_GET_SET (LIBAVFILTER_VERSION_MAJOR < 8) #endif +#ifndef FF_API_SWS_PARAM_OPTION +#define FF_API_SWS_PARAM_OPTION (LIBAVFILTER_VERSION_MAJOR < 8) +#endif #ifndef FF_API_NEXT #define FF_API_NEXT (LIBAVFILTER_VERSION_MAJOR < 8) #endif +#ifndef FF_API_FILTER_LINK_SET_CLOSED +#define FF_API_FILTER_LINK_SET_CLOSED (LIBAVFILTER_VERSION_MAJOR < 8) +#endif +#ifndef FF_API_BUFFERSINK_ALLOC +#define FF_API_BUFFERSINK_ALLOC (LIBAVFILTER_VERSION_MAJOR < 9) +#endif #endif /* AVFILTER_VERSION_H */ diff -Nru ffmpeg-4.2.2/libavfilter/vf_addroi.c ffmpeg-4.4/libavfilter/vf_addroi.c --- ffmpeg-4.2.2/libavfilter/vf_addroi.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_addroi.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,269 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/eval.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "internal.h" + +enum { + X, Y, W, H, + NB_PARAMS, +}; +static const char addroi_param_names[] = { + 'x', 'y', 'w', 'h', +}; + +enum { + VAR_IW, + VAR_IH, + NB_VARS, +}; +static const char *const addroi_var_names[] = { + "iw", + "ih", +}; + +typedef struct AddROIContext { + const AVClass *class; + + char *region_str[NB_PARAMS]; + AVExpr *region_expr[NB_PARAMS]; + + int region[NB_PARAMS]; + AVRational qoffset; + + int clear; +} AddROIContext; + +static int addroi_config_input(AVFilterLink *inlink) +{ + AVFilterContext *avctx = inlink->dst; + AddROIContext *ctx = avctx->priv; + int i; + double vars[NB_VARS]; + double val; + + vars[VAR_IW] = inlink->w; + vars[VAR_IH] = inlink->h; + + for (i = 0; i < NB_PARAMS; i++) { + int max_value; + switch (i) { + case X: max_value = inlink->w; break; + case Y: max_value = inlink->h; break; + case W: max_value = inlink->w - ctx->region[X]; break; + case H: max_value = inlink->h - ctx->region[Y]; break; + } + + val = av_expr_eval(ctx->region_expr[i], vars, NULL); + if (val < 0.0) { + av_log(avctx, AV_LOG_WARNING, "Calculated value %g for %c is " + "less than zero - using zero instead.\n", val, + addroi_param_names[i]); + val = 0.0; + } else if (val > max_value) { + av_log(avctx, AV_LOG_WARNING, "Calculated value %g for %c is " + "greater than maximum allowed value %d - " + "using %d instead.\n", val, addroi_param_names[i], + max_value, max_value); + val = max_value; + } + ctx->region[i] = val; + } + + return 0; +} + +static int addroi_filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *avctx = inlink->dst; + AVFilterLink *outlink = avctx->outputs[0]; + AddROIContext *ctx = avctx->priv; + AVRegionOfInterest *roi; + AVFrameSideData *sd; + int err; + + if (ctx->clear) { + av_frame_remove_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST); + sd = NULL; + } else { + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST); + } + if (sd) { + const AVRegionOfInterest *old_roi; + uint32_t old_roi_size; + AVBufferRef *roi_ref; + int nb_roi, i; + + old_roi = (const AVRegionOfInterest*)sd->data; + old_roi_size = old_roi->self_size; + av_assert0(old_roi_size && sd->size % old_roi_size == 0); + nb_roi = sd->size / old_roi_size + 1; + + roi_ref = av_buffer_alloc(sizeof(*roi) * nb_roi); + if (!roi_ref) { + err = AVERROR(ENOMEM); + goto fail; + } + roi = (AVRegionOfInterest*)roi_ref->data; + + for (i = 0; i < nb_roi - 1; i++) { + old_roi = (const AVRegionOfInterest*) + (sd->data + old_roi_size * i); + + roi[i] = (AVRegionOfInterest) { + .self_size = sizeof(*roi), + .top = old_roi->top, + .bottom = old_roi->bottom, + .left = old_roi->left, + .right = old_roi->right, + .qoffset = old_roi->qoffset, + }; + } + + roi[nb_roi - 1] = (AVRegionOfInterest) { + .self_size = sizeof(*roi), + .top = ctx->region[Y], + .bottom = ctx->region[Y] + ctx->region[H], + .left = ctx->region[X], + .right = ctx->region[X] + ctx->region[W], + .qoffset = ctx->qoffset, + }; + + av_frame_remove_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST); + + sd = av_frame_new_side_data_from_buf(frame, + AV_FRAME_DATA_REGIONS_OF_INTEREST, + roi_ref); + if (!sd) { + av_buffer_unref(&roi_ref); + err = AVERROR(ENOMEM); + goto fail; + } + + } else { + sd = av_frame_new_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST, + sizeof(AVRegionOfInterest)); + if (!sd) { + err = AVERROR(ENOMEM); + goto fail; + } + roi = (AVRegionOfInterest*)sd->data; + *roi = (AVRegionOfInterest) { + .self_size = sizeof(*roi), + .top = ctx->region[Y], + .bottom = ctx->region[Y] + ctx->region[H], + .left = ctx->region[X], + .right = ctx->region[X] + ctx->region[W], + .qoffset = ctx->qoffset, + }; + } + + return ff_filter_frame(outlink, frame); + +fail: + av_frame_free(&frame); + return err; +} + +static av_cold int addroi_init(AVFilterContext *avctx) +{ + AddROIContext *ctx = avctx->priv; + int i, err; + + for (i = 0; i < NB_PARAMS; i++) { + err = av_expr_parse(&ctx->region_expr[i], ctx->region_str[i], + addroi_var_names, NULL, NULL, NULL, NULL, + 0, avctx); + if (err < 0) { + av_log(ctx, AV_LOG_ERROR, + "Error parsing %c expression '%s'.\n", + addroi_param_names[i], ctx->region_str[i]); + return err; + } + } + + return 0; +} + +static av_cold void addroi_uninit(AVFilterContext *avctx) +{ + AddROIContext *ctx = avctx->priv; + int i; + + for (i = 0; i < NB_PARAMS; i++) { + av_expr_free(ctx->region_expr[i]); + ctx->region_expr[i] = NULL; + } +} + +#define OFFSET(x) offsetof(AddROIContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +static const AVOption addroi_options[] = { + { "x", "Region distance from left edge of frame.", + OFFSET(region_str[X]), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS }, + { "y", "Region distance from top edge of frame.", + OFFSET(region_str[Y]), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS }, + { "w", "Region width.", + OFFSET(region_str[W]), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS }, + { "h", "Region height.", + OFFSET(region_str[H]), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS }, + + { "qoffset", "Quantisation offset to apply in the region.", + OFFSET(qoffset), AV_OPT_TYPE_RATIONAL, { .dbl = -0.1 }, -1, +1, FLAGS }, + + { "clear", "Remove any existing regions of interest before adding the new one.", + OFFSET(clear), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, + + { NULL } +}; + +AVFILTER_DEFINE_CLASS(addroi); + +static const AVFilterPad addroi_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = addroi_config_input, + .filter_frame = addroi_filter_frame, + }, + { NULL } +}; + +static const AVFilterPad addroi_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_addroi = { + .name = "addroi", + .description = NULL_IF_CONFIG_SMALL("Add region of interest to frame."), + .init = addroi_init, + .uninit = addroi_uninit, + + .priv_size = sizeof(AddROIContext), + .priv_class = &addroi_class, + + .inputs = addroi_inputs, + .outputs = addroi_outputs, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_alphamerge.c ffmpeg-4.4/libavfilter/vf_alphamerge.c --- ffmpeg-4.2.2/libavfilter/vf_alphamerge.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_alphamerge.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,23 +26,71 @@ #include #include "libavutil/imgutils.h" +#include "libavutil/opt.h" #include "libavutil/pixfmt.h" #include "avfilter.h" #include "drawutils.h" #include "formats.h" #include "filters.h" +#include "framesync.h" #include "internal.h" #include "video.h" enum { Y, U, V, A }; typedef struct AlphaMergeContext { + const AVClass *class; + int is_packed_rgb; uint8_t rgba_map[4]; - AVFrame *main_frame; - AVFrame *alpha_frame; + + FFFrameSync fs; } AlphaMergeContext; +static int do_alphamerge(FFFrameSync *fs) +{ + AVFilterContext *ctx = fs->parent; + AlphaMergeContext *s = ctx->priv; + AVFrame *main_buf, *alpha_buf; + int ret; + + ret = ff_framesync_dualinput_get_writable(fs, &main_buf, &alpha_buf); + if (ret < 0) + return ret; + if (!alpha_buf) + return ff_filter_frame(ctx->outputs[0], main_buf); + + if (s->is_packed_rgb) { + int x, y; + uint8_t *pin, *pout; + for (y = 0; y < main_buf->height; y++) { + pin = alpha_buf->data[0] + y * alpha_buf->linesize[0]; + pout = main_buf->data[0] + y * main_buf->linesize[0] + s->rgba_map[A]; + for (x = 0; x < main_buf->width; x++) { + *pout = *pin; + pin += 1; + pout += 4; + } + } + } else { + const int main_linesize = main_buf->linesize[A]; + const int alpha_linesize = alpha_buf->linesize[Y]; + av_image_copy_plane(main_buf->data[A], main_linesize, + alpha_buf->data[Y], alpha_linesize, + FFMIN(main_linesize, alpha_linesize), alpha_buf->height); + } + + return ff_filter_frame(ctx->outputs[0], main_buf); +} + +static av_cold int init(AVFilterContext *ctx) +{ + AlphaMergeContext *s = ctx->priv; + + s->fs.on_event = do_alphamerge; + return 0; +} + static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat main_fmts[] = { @@ -52,34 +100,22 @@ AV_PIX_FMT_NONE }; static const enum AVPixelFormat alpha_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }; - AVFilterFormats *main_formats = NULL, *alpha_formats = NULL; + AVFilterFormats *main_formats = ff_make_format_list(main_fmts); int ret; - if (!(main_formats = ff_make_format_list(main_fmts)) || - !(alpha_formats = ff_make_format_list(alpha_fmts))) { - ret = AVERROR(ENOMEM); - goto fail; - } - if ((ret = ff_formats_ref(main_formats , &ctx->inputs[0]->out_formats)) < 0 || - (ret = ff_formats_ref(alpha_formats, &ctx->inputs[1]->out_formats)) < 0 || - (ret = ff_formats_ref(main_formats , &ctx->outputs[0]->in_formats)) < 0) - goto fail; - return 0; -fail: - if (main_formats) - av_freep(&main_formats->formats); - av_freep(&main_formats); - if (alpha_formats) - av_freep(&alpha_formats->formats); - av_freep(&alpha_formats); - return ret; + if ((ret = ff_formats_ref(main_formats, &ctx->inputs[0]->outcfg.formats)) < 0 || + (ret = ff_formats_ref(main_formats, &ctx->outputs[0]->incfg.formats)) < 0) + return ret; + + return ff_formats_ref(ff_make_format_list(alpha_fmts), + &ctx->inputs[1]->outcfg.formats); } static int config_input_main(AVFilterLink *inlink) { - AlphaMergeContext *merge = inlink->dst->priv; - merge->is_packed_rgb = - ff_fill_rgba_map(merge->rgba_map, inlink->format) >= 0 && + AlphaMergeContext *s = inlink->dst->priv; + s->is_packed_rgb = + ff_fill_rgba_map(s->rgba_map, inlink->format) >= 0 && inlink->format != AV_PIX_FMT_GBRAP; return 0; } @@ -87,8 +123,11 @@ static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; + AlphaMergeContext *s = ctx->priv; AVFilterLink *mainlink = ctx->inputs[0]; AVFilterLink *alphalink = ctx->inputs[1]; + int ret; + if (mainlink->w != alphalink->w || mainlink->h != alphalink->h) { av_log(ctx, AV_LOG_ERROR, "Input frame sizes do not match (%dx%d vs %dx%d).\n", @@ -97,88 +136,29 @@ return AVERROR(EINVAL); } + if ((ret = ff_framesync_init_dualinput(&s->fs, ctx)) < 0) + return ret; + outlink->w = mainlink->w; outlink->h = mainlink->h; outlink->time_base = mainlink->time_base; outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio; outlink->frame_rate = mainlink->frame_rate; - return 0; -} - -static void draw_frame(AVFilterContext *ctx, - AVFrame *main_buf, - AVFrame *alpha_buf) -{ - AlphaMergeContext *merge = ctx->priv; - int h = main_buf->height; - if (merge->is_packed_rgb) { - int x, y; - uint8_t *pin, *pout; - for (y = 0; y < h; y++) { - pin = alpha_buf->data[0] + y * alpha_buf->linesize[0]; - pout = main_buf->data[0] + y * main_buf->linesize[0] + merge->rgba_map[A]; - for (x = 0; x < main_buf->width; x++) { - *pout = *pin; - pin += 1; - pout += 4; - } - } - } else { - const int main_linesize = main_buf->linesize[A]; - const int alpha_linesize = alpha_buf->linesize[Y]; - av_image_copy_plane(main_buf->data[A], main_linesize, - alpha_buf->data[Y], alpha_linesize, - FFMIN(main_linesize, alpha_linesize), alpha_buf->height); - } + return ff_framesync_configure(&s->fs); } static int activate(AVFilterContext *ctx) { - AVFilterLink *outlink = ctx->outputs[0]; AlphaMergeContext *s = ctx->priv; - int ret; - - FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); - - if (!s->main_frame) { - ret = ff_inlink_consume_frame(ctx->inputs[0], &s->main_frame); - if (ret < 0) - return ret; - } - - if (!s->alpha_frame) { - ret = ff_inlink_consume_frame(ctx->inputs[1], &s->alpha_frame); - if (ret < 0) - return ret; - } - - if (s->main_frame && s->alpha_frame) { - draw_frame(ctx, s->main_frame, s->alpha_frame); - ret = ff_filter_frame(outlink, s->main_frame); - av_frame_free(&s->alpha_frame); - s->main_frame = NULL; - return ret; - } - - FF_FILTER_FORWARD_STATUS(ctx->inputs[0], outlink); - FF_FILTER_FORWARD_STATUS(ctx->inputs[1], outlink); - - if (ff_outlink_frame_wanted(ctx->outputs[0]) && - !ff_outlink_get_status(ctx->inputs[0]) && - !s->main_frame) { - ff_inlink_request_frame(ctx->inputs[0]); - return 0; - } + return ff_framesync_activate(&s->fs); +} - if (ff_outlink_frame_wanted(ctx->outputs[0]) && - !ff_outlink_get_status(ctx->inputs[1]) && - !s->alpha_frame) { - ff_inlink_request_frame(ctx->inputs[1]); - return 0; - } +static av_cold void uninit(AVFilterContext *ctx) +{ + AlphaMergeContext *s = ctx->priv; - return FFERROR_NOT_READY; + ff_framesync_uninit(&s->fs); } static const AVFilterPad alphamerge_inputs[] = { @@ -186,7 +166,6 @@ .name = "main", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_input_main, - .needs_writable = 1, },{ .name = "alpha", .type = AVMEDIA_TYPE_VIDEO, @@ -203,13 +182,24 @@ { NULL } }; +static const AVOption alphamerge_options[] = { + { NULL } +}; + +FRAMESYNC_DEFINE_CLASS(alphamerge, AlphaMergeContext, fs); + AVFilter ff_vf_alphamerge = { .name = "alphamerge", .description = NULL_IF_CONFIG_SMALL("Copy the luma value of the second " "input into the alpha channel of the first input."), + .preinit = alphamerge_framesync_preinit, .priv_size = sizeof(AlphaMergeContext), + .priv_class = &alphamerge_class, + .init = init, .query_formats = query_formats, .inputs = alphamerge_inputs, .outputs = alphamerge_outputs, + .uninit = uninit, .activate = activate, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_amplify.c ffmpeg-4.4/libavfilter/vf_amplify.c --- ffmpeg-4.2.2/libavfilter/vf_amplify.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_amplify.c 2020-07-11 10:39:30.000000000 +0000 @@ -71,6 +71,11 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; AVFilterFormats *formats = ff_make_format_list(pixel_fmts); @@ -231,7 +236,7 @@ if (s->frames) { for (i = 0; i < s->nb_frames; i++) - av_frame_free(&s->frames[i]); + av_frame_free(&s->frames[i]); } av_freep(&s->frames); } @@ -254,29 +259,37 @@ s->frames[s->nb_inputs - 1] = in; } - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) - return AVERROR(ENOMEM); - out->pts = s->frames[0]->pts; - - td.out = out; - td.in = s->frames; - ctx->internal->execute(ctx, amplify_frame, &td, NULL, FFMIN(s->height[1], ff_filter_get_nb_threads(ctx))); + if (!ctx->is_disabled) { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) + return AVERROR(ENOMEM); + av_frame_copy_props(out, s->frames[0]); + + td.out = out; + td.in = s->frames; + ctx->internal->execute(ctx, amplify_frame, &td, NULL, FFMIN(s->height[1], ff_filter_get_nb_threads(ctx))); + } else { + out = av_frame_clone(s->frames[s->radius]); + if (!out) + return AVERROR(ENOMEM); + out->pts = s->frames[0]->pts; + } return ff_filter_frame(outlink, out); } #define OFFSET(x) offsetof(AmplifyContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +#define VFT AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption amplify_options[] = { { "radius", "set radius", OFFSET(radius), AV_OPT_TYPE_INT, {.i64=2}, 1, 63, .flags = FLAGS }, - { "factor", "set factor", OFFSET(factor), AV_OPT_TYPE_FLOAT, {.dbl=2}, 0, UINT16_MAX, .flags = FLAGS }, - { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_FLOAT, {.dbl=10}, 0, UINT16_MAX, .flags = FLAGS }, - { "tolerance", "set tolerance", OFFSET(tolerance), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, UINT16_MAX, .flags = FLAGS }, - { "low", "set low limit for amplification", OFFSET(llimit), AV_OPT_TYPE_INT, {.i64=UINT16_MAX}, 0, UINT16_MAX, .flags = FLAGS }, - { "high", "set high limit for amplification", OFFSET(hlimit), AV_OPT_TYPE_INT, {.i64=UINT16_MAX}, 0, UINT16_MAX, .flags = FLAGS }, - { "planes", "set what planes to filter", OFFSET(planes), AV_OPT_TYPE_FLAGS, {.i64=7}, 0, 15, FLAGS }, + { "factor", "set factor", OFFSET(factor), AV_OPT_TYPE_FLOAT, {.dbl=2}, 0, UINT16_MAX, .flags = VFT }, + { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_FLOAT, {.dbl=10}, 0, UINT16_MAX, .flags = VFT }, + { "tolerance", "set tolerance", OFFSET(tolerance), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, UINT16_MAX, .flags = VFT }, + { "low", "set low limit for amplification", OFFSET(llimit), AV_OPT_TYPE_INT, {.i64=UINT16_MAX}, 0, UINT16_MAX, .flags = VFT }, + { "high", "set high limit for amplification", OFFSET(hlimit), AV_OPT_TYPE_INT, {.i64=UINT16_MAX}, 0, UINT16_MAX, .flags = VFT }, + { "planes", "set what planes to filter", OFFSET(planes), AV_OPT_TYPE_FLAGS, {.i64=7}, 0, 15, VFT }, { NULL }, }; @@ -310,5 +323,6 @@ .inputs = inputs, .init = init, .uninit = uninit, - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_aspect.c ffmpeg-4.4/libavfilter/vf_aspect.c --- ffmpeg-4.2.2/libavfilter/vf_aspect.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_aspect.c 2020-07-09 09:17:46.000000000 +0000 @@ -78,7 +78,7 @@ static inline void compute_dar(AVRational *dar, AVRational sar, int w, int h) { if (sar.num && sar.den) { - av_reduce(&dar->num, &dar->den, sar.num * w, sar.den * h, INT_MAX); + av_reduce(&dar->num, &dar->den, sar.num * (int64_t)w, sar.den * (int64_t)h, INT_MAX); } else { av_reduce(&dar->num, &dar->den, w, h, INT_MAX); } diff -Nru ffmpeg-4.2.2/libavfilter/vf_atadenoise.c ffmpeg-4.4/libavfilter/vf_atadenoise.c --- ffmpeg-4.2.2/libavfilter/vf_atadenoise.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_atadenoise.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,6 +33,7 @@ #define FF_BUFQUEUE_SIZE 129 #include "bufferqueue.h" +#include "atadenoise.h" #include "formats.h" #include "internal.h" #include "video.h" @@ -43,7 +44,9 @@ const AVClass *class; float fthra[4], fthrb[4]; + float sigma[4]; int thra[4], thrb[4]; + int algorithm; int planes; int nb_planes; @@ -53,14 +56,18 @@ struct FFBufQueue q; void *data[4][SIZE]; int linesize[4][SIZE]; - int size, mid; + float weights[4][SIZE]; + int size, mid, radius; int available; int (*filter_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + + ATADenoiseDSPContext dsp; } ATADenoiseContext; #define OFFSET(x) offsetof(ATADenoiseContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM +#define VF AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption atadenoise_options[] = { { "0a", "set threshold A for 1st plane", OFFSET(fthra[0]), AV_OPT_TYPE_FLOAT, {.dbl=0.02}, 0, 0.3, FLAGS }, @@ -69,8 +76,14 @@ { "1b", "set threshold B for 2nd plane", OFFSET(fthrb[1]), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 5.0, FLAGS }, { "2a", "set threshold A for 3rd plane", OFFSET(fthra[2]), AV_OPT_TYPE_FLOAT, {.dbl=0.02}, 0, 0.3, FLAGS }, { "2b", "set threshold B for 3rd plane", OFFSET(fthrb[2]), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 5.0, FLAGS }, - { "s", "set how many frames to use", OFFSET(size), AV_OPT_TYPE_INT, {.i64=9}, 5, SIZE, FLAGS }, + { "s", "set how many frames to use", OFFSET(size), AV_OPT_TYPE_INT, {.i64=9}, 5, SIZE, VF }, { "p", "set what planes to filter", OFFSET(planes), AV_OPT_TYPE_FLAGS, {.i64=7}, 0, 15, FLAGS }, + { "a", "set variant of algorithm", OFFSET(algorithm),AV_OPT_TYPE_INT, {.i64=PARALLEL}, 0, NB_ATAA-1, FLAGS, "a" }, + { "p", "parallel", 0, AV_OPT_TYPE_CONST, {.i64=PARALLEL}, 0, 0, FLAGS, "a" }, + { "s", "serial", 0, AV_OPT_TYPE_CONST, {.i64=SERIAL}, 0, 0, FLAGS, "a" }, + { "0s", "set sigma for 1st plane", OFFSET(sigma[0]), AV_OPT_TYPE_FLOAT, {.dbl=INT16_MAX}, 0, INT16_MAX, FLAGS }, + { "1s", "set sigma for 2nd plane", OFFSET(sigma[1]), AV_OPT_TYPE_FLOAT, {.dbl=INT16_MAX}, 0, INT16_MAX, FLAGS }, + { "2s", "set sigma for 3rd plane", OFFSET(sigma[2]), AV_OPT_TYPE_FLOAT, {.dbl=INT16_MAX}, 0, INT16_MAX, FLAGS }, { NULL } }; @@ -100,6 +113,11 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; AVFilterFormats *formats = ff_make_format_list(pixel_fmts); @@ -116,7 +134,8 @@ av_log(ctx, AV_LOG_WARNING, "size %d is invalid. Must be an odd value, setting it to %d.\n", s->size, s->size|1); s->size |= 1; } - s->mid = s->size / 2 + 1; + s->radius = s->size / 2; + s->mid = s->radius; return 0; } @@ -125,7 +144,207 @@ AVFrame *in, *out; } ThreadData; -static int filter_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +#define WFILTER_ROW(type, name) \ +static void fweight_row##name(const uint8_t *ssrc, uint8_t *ddst, \ + const uint8_t *ssrcf[SIZE], \ + int w, int mid, int size, \ + int thra, int thrb, const float *weights) \ +{ \ + const type *src = (const type *)ssrc; \ + const type **srcf = (const type **)ssrcf; \ + type *dst = (type *)ddst; \ + \ + for (int x = 0; x < w; x++) { \ + const int srcx = src[x]; \ + unsigned lsumdiff = 0, rsumdiff = 0; \ + unsigned ldiff, rdiff; \ + float sum = srcx; \ + float wsum = 1.f; \ + int l = 0, r = 0; \ + int srcjx, srcix; \ + \ + for (int j = mid - 1, i = mid + 1; j >= 0 && i < size; j--, i++) { \ + srcjx = srcf[j][x]; \ + \ + ldiff = FFABS(srcx - srcjx); \ + lsumdiff += ldiff; \ + if (ldiff > thra || \ + lsumdiff > thrb) \ + break; \ + l++; \ + sum += srcjx * weights[j]; \ + wsum += weights[j]; \ + \ + srcix = srcf[i][x]; \ + \ + rdiff = FFABS(srcx - srcix); \ + rsumdiff += rdiff; \ + if (rdiff > thra || \ + rsumdiff > thrb) \ + break; \ + r++; \ + sum += srcix * weights[i]; \ + wsum += weights[i]; \ + } \ + \ + dst[x] = lrintf(sum / wsum); \ + } \ +} + +WFILTER_ROW(uint8_t, 8) +WFILTER_ROW(uint16_t, 16) + +#define WFILTER_ROW_SERIAL(type, name) \ +static void fweight_row##name##_serial(const uint8_t *ssrc, uint8_t *ddst, \ + const uint8_t *ssrcf[SIZE], \ + int w, int mid, int size, \ + int thra, int thrb, \ + const float *weights) \ +{ \ + const type *src = (const type *)ssrc; \ + const type **srcf = (const type **)ssrcf; \ + type *dst = (type *)ddst; \ + \ + for (int x = 0; x < w; x++) { \ + const int srcx = src[x]; \ + unsigned lsumdiff = 0, rsumdiff = 0; \ + unsigned ldiff, rdiff; \ + float sum = srcx; \ + float wsum = 1.f; \ + int l = 0, r = 0; \ + int srcjx, srcix; \ + \ + for (int j = mid - 1; j >= 0; j--) { \ + srcjx = srcf[j][x]; \ + \ + ldiff = FFABS(srcx - srcjx); \ + lsumdiff += ldiff; \ + if (ldiff > thra || \ + lsumdiff > thrb) \ + break; \ + l++; \ + sum += srcjx * weights[j]; \ + wsum += weights[j]; \ + } \ + \ + for (int i = mid + 1; i < size; i++) { \ + srcix = srcf[i][x]; \ + \ + rdiff = FFABS(srcx - srcix); \ + rsumdiff += rdiff; \ + if (rdiff > thra || \ + rsumdiff > thrb) \ + break; \ + r++; \ + sum += srcix * weights[i]; \ + wsum += weights[i]; \ + } \ + \ + dst[x] = lrintf(sum / wsum); \ + } \ +} + +WFILTER_ROW_SERIAL(uint8_t, 8) +WFILTER_ROW_SERIAL(uint16_t, 16) + +#define FILTER_ROW(type, name) \ +static void filter_row##name(const uint8_t *ssrc, uint8_t *ddst, \ + const uint8_t *ssrcf[SIZE], \ + int w, int mid, int size, \ + int thra, int thrb, const float *weights) \ +{ \ + const type *src = (const type *)ssrc; \ + const type **srcf = (const type **)ssrcf; \ + type *dst = (type *)ddst; \ + \ + for (int x = 0; x < w; x++) { \ + const int srcx = src[x]; \ + unsigned lsumdiff = 0, rsumdiff = 0; \ + unsigned ldiff, rdiff; \ + unsigned sum = srcx; \ + int l = 0, r = 0; \ + int srcjx, srcix; \ + \ + for (int j = mid - 1, i = mid + 1; j >= 0 && i < size; j--, i++) { \ + srcjx = srcf[j][x]; \ + \ + ldiff = FFABS(srcx - srcjx); \ + lsumdiff += ldiff; \ + if (ldiff > thra || \ + lsumdiff > thrb) \ + break; \ + l++; \ + sum += srcjx; \ + \ + srcix = srcf[i][x]; \ + \ + rdiff = FFABS(srcx - srcix); \ + rsumdiff += rdiff; \ + if (rdiff > thra || \ + rsumdiff > thrb) \ + break; \ + r++; \ + sum += srcix; \ + } \ + \ + dst[x] = (sum + ((r + l + 1) >> 1)) / (r + l + 1); \ + } \ +} + +FILTER_ROW(uint8_t, 8) +FILTER_ROW(uint16_t, 16) + +#define FILTER_ROW_SERIAL(type, name) \ +static void filter_row##name##_serial(const uint8_t *ssrc, uint8_t *ddst, \ + const uint8_t *ssrcf[SIZE], \ + int w, int mid, int size, \ + int thra, int thrb, \ + const float *weights) \ +{ \ + const type *src = (const type *)ssrc; \ + const type **srcf = (const type **)ssrcf; \ + type *dst = (type *)ddst; \ + \ + for (int x = 0; x < w; x++) { \ + const int srcx = src[x]; \ + unsigned lsumdiff = 0, rsumdiff = 0; \ + unsigned ldiff, rdiff; \ + unsigned sum = srcx; \ + int l = 0, r = 0; \ + int srcjx, srcix; \ + \ + for (int j = mid - 1; j >= 0; j--) { \ + srcjx = srcf[j][x]; \ + \ + ldiff = FFABS(srcx - srcjx); \ + lsumdiff += ldiff; \ + if (ldiff > thra || \ + lsumdiff > thrb) \ + break; \ + l++; \ + sum += srcjx; \ + } \ + \ + for (int i = mid + 1; i < size; i++) { \ + srcix = srcf[i][x]; \ + \ + rdiff = FFABS(srcx - srcix); \ + rsumdiff += rdiff; \ + if (rdiff > thra || \ + rsumdiff > thrb) \ + break; \ + r++; \ + sum += srcix; \ + } \ + \ + dst[x] = (sum + ((r + l + 1) >> 1)) / (r + l + 1); \ + } \ +} + +FILTER_ROW_SERIAL(uint8_t, 8) +FILTER_ROW_SERIAL(uint16_t, 16) + +static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ATADenoiseContext *s = ctx->priv; ThreadData *td = arg; @@ -133,9 +352,10 @@ AVFrame *out = td->out; const int size = s->size; const int mid = s->mid; - int p, x, y, i, j; + int p, y, i; for (p = 0; p < s->nb_planes; p++) { + const float *weights = s->weights[p]; const int h = s->planeheight[p]; const int w = s->planewidth[p]; const int slice_start = (h * jobnr) / nb_jobs; @@ -158,38 +378,7 @@ srcf[i] = data[i] + slice_start * linesize[i]; for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < w; x++) { - const int srcx = src[x]; - unsigned lsumdiff = 0, rsumdiff = 0; - unsigned ldiff, rdiff; - unsigned sum = srcx; - int l = 0, r = 0; - int srcjx, srcix; - - for (j = mid - 1, i = mid + 1; j >= 0 && i < size; j--, i++) { - srcjx = srcf[j][x]; - - ldiff = FFABS(srcx - srcjx); - lsumdiff += ldiff; - if (ldiff > thra || - lsumdiff > thrb) - break; - l++; - sum += srcjx; - - srcix = srcf[i][x]; - - rdiff = FFABS(srcx - srcix); - rsumdiff += rdiff; - if (rdiff > thra || - rsumdiff > thrb) - break; - r++; - sum += srcix; - } - - dst[x] = sum / (r + l + 1); - } + s->dsp.filter_row[p](src, dst, srcf, w, mid, size, thra, thrb, weights); dst += out->linesize[p]; src += in->linesize[p]; @@ -202,83 +391,6 @@ return 0; } -static int filter_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) -{ - ATADenoiseContext *s = ctx->priv; - ThreadData *td = arg; - AVFrame *in = td->in; - AVFrame *out = td->out; - const int size = s->size; - const int mid = s->mid; - int p, x, y, i, j; - - for (p = 0; p < s->nb_planes; p++) { - const int h = s->planeheight[p]; - const int w = s->planewidth[p]; - const int slice_start = (h * jobnr) / nb_jobs; - const int slice_end = (h * (jobnr+1)) / nb_jobs; - const uint16_t *src = (uint16_t *)(in->data[p] + slice_start * in->linesize[p]); - uint16_t *dst = (uint16_t *)(out->data[p] + slice_start * out->linesize[p]); - const int thra = s->thra[p]; - const int thrb = s->thrb[p]; - const uint8_t **data = (const uint8_t **)s->data[p]; - const int *linesize = (const int *)s->linesize[p]; - const uint16_t *srcf[SIZE]; - - if (!((1 << p) & s->planes)) { - av_image_copy_plane((uint8_t *)dst, out->linesize[p], (uint8_t *)src, in->linesize[p], - w * 2, slice_end - slice_start); - continue; - } - - for (i = 0; i < s->size; i++) - srcf[i] = (const uint16_t *)(data[i] + slice_start * linesize[i]); - - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < w; x++) { - const int srcx = src[x]; - unsigned lsumdiff = 0, rsumdiff = 0; - unsigned ldiff, rdiff; - unsigned sum = srcx; - int l = 0, r = 0; - int srcjx, srcix; - - for (j = mid - 1, i = mid + 1; j >= 0 && i < size; j--, i++) { - srcjx = srcf[j][x]; - - ldiff = FFABS(srcx - srcjx); - lsumdiff += ldiff; - if (ldiff > thra || - lsumdiff > thrb) - break; - l++; - sum += srcjx; - - srcix = srcf[i][x]; - - rdiff = FFABS(srcx - srcix); - rsumdiff += rdiff; - if (rdiff > thra || - rsumdiff > thrb) - break; - r++; - sum += srcix; - } - - dst[x] = sum / (r + l + 1); - } - - dst += out->linesize[p] / 2; - src += in->linesize[p] / 2; - - for (i = 0; i < size; i++) - srcf[i] += linesize[i] / 2; - } - } - - return 0; -} - static int config_input(AVFilterLink *inlink) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); @@ -294,10 +406,18 @@ s->planewidth[0] = s->planewidth[3] = inlink->w; depth = desc->comp[0].depth; - if (depth == 8) - s->filter_slice = filter_slice8; - else - s->filter_slice = filter_slice16; + s->filter_slice = filter_slice; + + for (int p = 0; p < s->nb_planes; p++) { + if (depth == 8 && s->sigma[p] == INT16_MAX) + s->dsp.filter_row[p] = s->algorithm == PARALLEL ? filter_row8 : filter_row8_serial; + else if (s->sigma[p] == INT16_MAX) + s->dsp.filter_row[p] = s->algorithm == PARALLEL ? filter_row16 : filter_row16_serial; + else if (depth == 8 && s->sigma[p] < INT16_MAX) + s->dsp.filter_row[p] = s->algorithm == PARALLEL ? fweight_row8 : fweight_row8_serial; + else if (s->sigma[p] < INT16_MAX) + s->dsp.filter_row[p] = s->algorithm == PARALLEL ? fweight_row16 : fweight_row16_serial; + } s->thra[0] = s->fthra[0] * (1 << depth) - 1; s->thra[1] = s->fthra[1] * (1 << depth) - 1; @@ -306,6 +426,19 @@ s->thrb[1] = s->fthrb[1] * (1 << depth) - 1; s->thrb[2] = s->fthrb[2] * (1 << depth) - 1; + for (int p = 0; p < s->nb_planes; p++) { + float sigma = s->radius * s->sigma[p]; + + s->weights[p][s->radius] = 1.f; + for (int n = 1; n <= s->radius; n++) { + s->weights[p][s->radius + n] = + s->weights[p][s->radius - n] = expf(-0.5 * (n + 1) * (n + 1) / (sigma * sigma)); + } + } + + if (ARCH_X86) + ff_atadenoise_init_x86(&s->dsp, depth, s->algorithm, s->sigma); + return 0; } @@ -405,6 +538,21 @@ ff_bufqueue_discard_all(&s->q); } +static int process_command(AVFilterContext *ctx, + const char *cmd, + const char *arg, + char *res, + int res_len, + int flags) +{ + int ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags); + + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + static const AVFilterPad inputs[] = { { .name = "default", @@ -435,4 +583,5 @@ .inputs = inputs, .outputs = outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_avgblur.c ffmpeg-4.4/libavfilter/vf_avgblur.c --- ffmpeg-4.2.2/libavfilter/vf_avgblur.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_avgblur.c 2020-07-11 10:39:30.000000000 +0000 @@ -46,7 +46,7 @@ } AverageBlurContext; #define OFFSET(x) offsetof(AverageBlurContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption avgblur_options[] = { { "sizeX", "set horizontal size", OFFSET(radius), AV_OPT_TYPE_INT, {.i64=1}, 1, 1024, FLAGS }, @@ -138,7 +138,6 @@ float acc = 0; \ int count = 0; \ \ - ptr = buffer + x; \ src = s->buffer + x; \ \ for (i = 0; i < radius; i++) { \ @@ -149,7 +148,7 @@ \ src = s->buffer + x; \ ptr = buffer + x; \ - for (i = 0; i <= radius; i++) { \ + for (i = 0; i + radius < height && i <= radius; i++) { \ acc += src[(i + radius) * width]; \ count++; \ ptr[i * linesize] = acc / count; \ @@ -238,6 +237,7 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, @@ -323,4 +323,5 @@ .inputs = avgblur_inputs, .outputs = avgblur_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_avgblur_vulkan.c ffmpeg-4.4/libavfilter/vf_avgblur_vulkan.c --- ffmpeg-4.2.2/libavfilter/vf_avgblur_vulkan.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_avgblur_vulkan.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,412 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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.h" +#include "internal.h" + +#define CGS 32 + +typedef struct AvgBlurVulkanContext { + VulkanFilterContext vkctx; + + int initialized; + FFVkExecContext *exec; + VulkanPipeline *pl_hor; + VulkanPipeline *pl_ver; + + /* Shader updators, must be in the main filter struct */ + VkDescriptorImageInfo input_images[3]; + VkDescriptorImageInfo tmp_images[3]; + VkDescriptorImageInfo output_images[3]; + + int size_x; + int size_y; + int planes; +} AvgBlurVulkanContext; + +static const char blur_kernel[] = { + C(0, shared vec4 cache[DIR(gl_WorkGroupSize) + FILTER_RADIUS*2 + 1]; ) + C(0, ) + C(0, void distort(const ivec2 pos, const int idx) ) + C(0, { ) + C(1, const uint cp = DIR(gl_LocalInvocationID) + FILTER_RADIUS; ) + C(0, ) + C(1, cache[cp] = texture(input_img[idx], pos); ) + C(0, ) + C(1, const ivec2 loc_l = pos - INC(FILTER_RADIUS); ) + C(1, cache[cp - FILTER_RADIUS] = texture(input_img[idx], loc_l); ) + C(0, ) + C(1, const ivec2 loc_h = pos + INC(DIR(gl_WorkGroupSize)); ) + C(1, cache[cp + DIR(gl_WorkGroupSize)] = texture(input_img[idx], loc_h); ) + C(0, ) + C(1, barrier(); ) + C(0, ) + C(1, vec4 sum = vec4(0); ) + C(1, for (int p = -FILTER_RADIUS; p <= FILTER_RADIUS; p++) ) + C(2, sum += cache[cp + p]; ) + C(0, ) + C(1, sum /= vec4(FILTER_RADIUS*2 + 1); ) + C(1, imageStore(output_img[idx], pos, sum); ) + C(0, } ) +}; + +static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) +{ + int err; + SPIRVShader *shd; + AvgBlurVulkanContext *s = ctx->priv; + 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] = { + { + .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", + .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, + }, + }; + + 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; + + { /* 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); + if (!s->pl_hor) + return AVERROR(ENOMEM); + + shd = ff_vk_init_shader(ctx, s->pl_hor, "avgblur_compute_hor", + VK_SHADER_STAGE_COMPUTE_BIT); + + ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ CGS, 1, 1 }); + + RET(ff_vk_add_descriptor_set(ctx, s->pl_hor, shd, desc_i, 2, 0)); + + GLSLF(0, #define FILTER_RADIUS (%i) ,s->size_x - 1); + GLSLC(0, #define INC(x) (ivec2(x, 0)) ); + GLSLC(0, #define DIR(var) (var.x) ); + GLSLD( blur_kernel ); + 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_img[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + if (s->planes & (1 << i)) { + GLSLF(2, distort(pos, %i); ,i); + } else { + GLSLF(2, vec4 res = texture(input_img[%i], pos); ,i); + GLSLF(2, imageStore(output_img[%i], pos, res); ,i); + } + GLSLC(1, } ); + } + GLSLC(0, } ); + + RET(ff_vk_compile_shader(ctx, shd, "main")); + + RET(ff_vk_init_pipeline_layout(ctx, s->pl_hor)); + RET(ff_vk_init_compute_pipeline(ctx, 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); + if (!s->pl_ver) + return AVERROR(ENOMEM); + + shd = ff_vk_init_shader(ctx, s->pl_ver, "avgblur_compute_ver", + VK_SHADER_STAGE_COMPUTE_BIT); + + ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ 1, CGS, 1 }); + + RET(ff_vk_add_descriptor_set(ctx, s->pl_ver, shd, desc_i, 2, 0)); + + GLSLF(0, #define FILTER_RADIUS (%i) ,s->size_y - 1); + GLSLC(0, #define INC(x) (ivec2(0, x)) ); + GLSLC(0, #define DIR(var) (var.y) ); + GLSLD( blur_kernel ); + 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_img[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + if (s->planes & (1 << i)) { + GLSLF(2, distort(pos, %i); ,i); + } else { + GLSLF(2, vec4 res = texture(input_img[%i], pos); ,i); + GLSLF(2, imageStore(output_img[%i], pos, res); ,i); + } + GLSLC(1, } ); + } + GLSLC(0, } ); + + RET(ff_vk_compile_shader(ctx, shd, "main")); + + RET(ff_vk_init_pipeline_layout(ctx, s->pl_ver)); + RET(ff_vk_init_compute_pipeline(ctx, s->pl_ver)); + } + + /* Execution context */ + RET(ff_vk_create_exec_ctx(ctx, &s->exec)); + + s->initialized = 1; + + return 0; + +fail: + return err; +} + +static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f, AVFrame *in_f) +{ + int err; + VkCommandBuffer cmd_buf; + AvgBlurVulkanContext *s = avctx->priv; + AVVkFrame *in = (AVVkFrame *)in_f->data[0]; + AVVkFrame *tmp = (AVVkFrame *)tmp_f->data[0]; + AVVkFrame *out = (AVVkFrame *)out_f->data[0]; + 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); + + 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], + 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], + 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], + 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(avctx, s->pl_hor, 0); + ff_vk_update_descriptor_set(avctx, s->pl_ver, 0); + + for (int i = 0; i < planes; i++) { + VkImageMemoryBarrier bar[] = { + { + .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, + }, + }; + + 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); + + in->layout[i] = bar[0].newLayout; + in->access[i] = bar[0].dstAccessMask; + + tmp->layout[i] = bar[1].newLayout; + tmp->access[i] = bar[1].dstAccessMask; + + out->layout[i] = bar[2].newLayout; + out->access[i] = bar[2].dstAccessMask; + } + + ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_hor); + + vkCmdDispatch(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); + + vkCmdDispatch(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); + + err = ff_vk_submit_exec_queue(avctx, s->exec); + if (err) + return err; + + return err; + +fail: + ff_vk_discard_exec_deps(avctx, s->exec); + return err; +} + +static int avgblur_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + int err; + AVFrame *tmp = NULL, *out = NULL; + AVFilterContext *ctx = link->dst; + AvgBlurVulkanContext *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; + } + + tmp = 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, tmp, in)); + + err = av_frame_copy_props(out, in); + if (err < 0) + goto fail; + + av_frame_free(&in); + av_frame_free(&tmp); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&tmp); + av_frame_free(&out); + return err; +} + +static void avgblur_vulkan_uninit(AVFilterContext *avctx) +{ + AvgBlurVulkanContext *s = avctx->priv; + + ff_vk_filter_uninit(avctx); + + s->initialized = 0; +} + +#define OFFSET(x) offsetof(AvgBlurVulkanContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption avgblur_vulkan_options[] = { + { "sizeX", "Set horizontal radius", OFFSET(size_x), AV_OPT_TYPE_INT, {.i64 = 3}, 1, 32, .flags = FLAGS }, + { "planes", "Set planes to filter (bitmask)", OFFSET(planes), AV_OPT_TYPE_INT, {.i64 = 0xF}, 0, 0xF, .flags = FLAGS }, + { "sizeY", "Set vertical radius", OFFSET(size_y), AV_OPT_TYPE_INT, {.i64 = 3}, 1, 32, .flags = FLAGS }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(avgblur_vulkan); + +static const AVFilterPad avgblur_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &avgblur_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + }, + { NULL } +}; + +static const AVFilterPad avgblur_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_avgblur_vulkan = { + .name = "avgblur_vulkan", + .description = NULL_IF_CONFIG_SMALL("Apply avgblur mask to input video"), + .priv_size = sizeof(AvgBlurVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &avgblur_vulkan_uninit, + .query_formats = &ff_vk_filter_query_formats, + .inputs = avgblur_vulkan_inputs, + .outputs = avgblur_vulkan_outputs, + .priv_class = &avgblur_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_bbox.c ffmpeg-4.4/libavfilter/vf_bbox.c --- ffmpeg-4.2.2/libavfilter/vf_bbox.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_bbox.c 2021-04-08 21:28:39.000000000 +0000 @@ -33,13 +33,14 @@ typedef struct BBoxContext { const AVClass *class; int min_val; + int depth; } BBoxContext; #define OFFSET(x) offsetof(BBoxContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption bbox_options[] = { - { "min_val", "set minimum luminance value for bounding box", OFFSET(min_val), AV_OPT_TYPE_INT, { .i64 = 16 }, 0, 254, FLAGS }, + { "min_val", "set minimum luminance value for bounding box", OFFSET(min_val), AV_OPT_TYPE_INT, { .i64 = 16 }, 0, UINT16_MAX, FLAGS }, { NULL } }; @@ -48,11 +49,26 @@ static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_YUV444P, - AV_PIX_FMT_YUV440P, - AV_PIX_FMT_YUV422P, - AV_PIX_FMT_YUV411P, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, + AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, + AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_NONE, }; @@ -75,7 +91,7 @@ has_bbox = ff_calculate_bounding_box(&box, frame->data[0], frame->linesize[0], - inlink->w, inlink->h, bbox->min_val); + inlink->w, inlink->h, bbox->min_val, bbox->depth); w = box.x2 - box.x1 + 1; h = box.y2 - box.y1 + 1; @@ -105,6 +121,20 @@ return ff_filter_frame(inlink->dst->outputs[0], frame); } +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + BBoxContext *s = ctx->priv; + const AVPixFmtDescriptor *desc; + + desc = av_pix_fmt_desc_get(outlink->format); + if (!desc) + return AVERROR_BUG; + s->depth = desc->comp[0].depth; + + return 0; +} + static const AVFilterPad bbox_inputs[] = { { .name = "default", @@ -118,6 +148,7 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, }, { NULL } }; @@ -131,4 +162,5 @@ .inputs = bbox_inputs, .outputs = bbox_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_bilateral.c ffmpeg-4.4/libavfilter/vf_bilateral.c --- ffmpeg-4.2.2/libavfilter/vf_bilateral.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_bilateral.c 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2017 Ming Yang + * Copyright (c) 2019 Paul B Mahol + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct BilateralContext { + const AVClass *class; + + float sigmaS; + float sigmaR; + int planes; + + int nb_planes; + int depth; + int planewidth[4]; + int planeheight[4]; + + 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; +} BilateralContext; + +#define OFFSET(x) offsetof(BilateralContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption bilateral_options[] = { + { "sigmaS", "set spatial sigma", OFFSET(sigmaS), AV_OPT_TYPE_FLOAT, {.dbl=0.1}, 0.0, 512, FLAGS }, + { "sigmaR", "set range sigma", OFFSET(sigmaR), AV_OPT_TYPE_FLOAT, {.dbl=0.1}, 0.0, 1, FLAGS }, + { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=1}, 0, 0xF, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(bilateral); + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE + }; + + return ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); +} + +static int config_params(AVFilterContext *ctx) +{ + BilateralContext *s = ctx->priv; + float inv_sigma_range; + + inv_sigma_range = 1.0f / (s->sigmaR * ((1 << s->depth) - 1)); + s->alpha = expf(-sqrtf(2.f) / s->sigmaS); + + //compute a lookup table + for (int i = 0; i < (1 << s->depth); i++) + s->range_table[i] = s->alpha * expf(-i * inv_sigma_range); + + return 0; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + BilateralContext *s = ctx->priv; + 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); + 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->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)); + + 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); + + 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]; \ + } \ + \ + for (int y = h1 - 1; y >= 0; y--) { \ + float *ycf_, *ypf_, *factor_; \ + float *ycy_, *ypy_, *out_; \ + \ + tpy = &src[(y + 1) * src_linesize]; \ + tcy = &src[y * src_linesize]; \ + xcy = &img_temp[y * width]; \ + ycy_ = ycy; \ + ypy_ = ypy; \ + out_ = &img_out_f[y * width]; \ + \ + xcf = &in_factor[y * width]; \ + ycf_ = ycf; \ + ypf_ = ypf; \ + factor_ = &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]; \ + float ycc, fcc = inv_alpha_*(*xcf++) + alpha_*(*ypf_++); \ + \ + *ycf_++ = fcc; \ + *factor_ = 0.5f * (*factor_ + fcc); \ + \ + ycc = inv_alpha_*(*xcy++) + alpha_*(*ypy_++); \ + *ycy_++ = ycc; \ + *out_ = 0.5f * (*out_ + ycc) / (*factor_); \ + out_++; \ + factor_++; \ + } \ + \ + 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) + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + BilateralContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + 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 (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_free(&in); + return ff_filter_frame(outlink, out); +} + +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); +} + +static int process_command(AVFilterContext *ctx, + const char *cmd, + const char *arg, + char *res, + int res_len, + int flags) +{ + int ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags); + + if (ret < 0) + return ret; + + return config_params(ctx); +} + +static const AVFilterPad bilateral_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad bilateral_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_bilateral = { + .name = "bilateral", + .description = NULL_IF_CONFIG_SMALL("Apply Bilateral filter."), + .priv_size = sizeof(BilateralContext), + .priv_class = &bilateral_class, + .uninit = uninit, + .query_formats = query_formats, + .inputs = bilateral_inputs, + .outputs = bilateral_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .process_command = process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_bitplanenoise.c ffmpeg-4.4/libavfilter/vf_bitplanenoise.c --- ffmpeg-4.2.2/libavfilter/vf_bitplanenoise.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_bitplanenoise.c 2020-07-11 10:39:30.000000000 +0000 @@ -122,7 +122,7 @@ if (s->depth <= 8) { for (plane = 0; plane < s->nb_planes; plane++) { - const int linesize = in->linesize[plane]; + const int linesize = s->planeheight[plane] > 1 ? in->linesize[plane] : 0; const int dlinesize = out->linesize[plane]; uint8_t *val = in->data[plane]; uint8_t *dst = s->filter ? out->data[plane]: NULL; @@ -151,7 +151,7 @@ } } else { for (plane = 0; plane < s->nb_planes; plane++) { - const int linesize = in->linesize[plane] / 2; + const int linesize = s->planeheight[plane] > 1 ? in->linesize[plane] / 2 : 0; const int dlinesize = out->linesize[plane] / 2; uint16_t *val = (uint16_t *)in->data[plane]; uint16_t *dst = s->filter ? (uint16_t *)out->data[plane] : NULL; diff -Nru ffmpeg-4.2.2/libavfilter/vf_blackdetect.c ffmpeg-4.4/libavfilter/vf_blackdetect.c --- ffmpeg-4.2.2/libavfilter/vf_blackdetect.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_blackdetect.c 2021-04-08 21:28:39.000000000 +0000 @@ -26,6 +26,7 @@ #include #include "libavutil/opt.h" +#include "libavutil/pixdesc.h" #include "libavutil/timestamp.h" #include "avfilter.h" #include "internal.h" @@ -44,6 +45,10 @@ unsigned int pixel_black_th_i; unsigned int nb_black_pixels; ///< number of black pixels counted so far + AVRational time_base; + int depth; + int nb_threads; + unsigned int *counter; } BlackDetectContext; #define OFFSET(x) offsetof(BlackDetectContext, x) @@ -77,6 +82,19 @@ AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NV12, AV_PIX_FMT_NV21, YUVJ_FORMATS, + AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, + AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_NONE }; @@ -89,98 +107,139 @@ static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; - BlackDetectContext *blackdetect = ctx->priv; - - blackdetect->black_min_duration = - blackdetect->black_min_duration_time / av_q2d(inlink->time_base); + BlackDetectContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + const int depth = desc->comp[0].depth; + const int max = (1 << depth) - 1; + const int factor = (1 << (depth - 8)); + + s->depth = depth; + s->nb_threads = ff_filter_get_nb_threads(ctx); + s->time_base = inlink->time_base; + s->black_min_duration = s->black_min_duration_time / av_q2d(s->time_base); + s->counter = av_calloc(s->nb_threads, sizeof(*s->counter)); + if (!s->counter) + return AVERROR(ENOMEM); - blackdetect->pixel_black_th_i = ff_fmt_is_in(inlink->format, yuvj_formats) ? + s->pixel_black_th_i = ff_fmt_is_in(inlink->format, yuvj_formats) ? // luminance_minimum_value + pixel_black_th * luminance_range_size - blackdetect->pixel_black_th * 255 : - 16 + blackdetect->pixel_black_th * (235 - 16); + s->pixel_black_th * max : + 16 * factor + s->pixel_black_th * (235 - 16) * factor; - av_log(blackdetect, AV_LOG_VERBOSE, + av_log(s, AV_LOG_VERBOSE, "black_min_duration:%s pixel_black_th:%f pixel_black_th_i:%d picture_black_ratio_th:%f\n", - av_ts2timestr(blackdetect->black_min_duration, &inlink->time_base), - blackdetect->pixel_black_th, blackdetect->pixel_black_th_i, - blackdetect->picture_black_ratio_th); + av_ts2timestr(s->black_min_duration, &s->time_base), + s->pixel_black_th, s->pixel_black_th_i, + s->picture_black_ratio_th); return 0; } static void check_black_end(AVFilterContext *ctx) { - BlackDetectContext *blackdetect = ctx->priv; - AVFilterLink *inlink = ctx->inputs[0]; + BlackDetectContext *s = ctx->priv; - if ((blackdetect->black_end - blackdetect->black_start) >= blackdetect->black_min_duration) { - av_log(blackdetect, AV_LOG_INFO, + if ((s->black_end - s->black_start) >= s->black_min_duration) { + av_log(s, AV_LOG_INFO, "black_start:%s black_end:%s black_duration:%s\n", - av_ts2timestr(blackdetect->black_start, &inlink->time_base), - av_ts2timestr(blackdetect->black_end, &inlink->time_base), - av_ts2timestr(blackdetect->black_end - blackdetect->black_start, &inlink->time_base)); + av_ts2timestr(s->black_start, &s->time_base), + av_ts2timestr(s->black_end, &s->time_base), + av_ts2timestr(s->black_end - s->black_start, &s->time_base)); } } -static int request_frame(AVFilterLink *outlink) +static int black_counter(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) { - AVFilterContext *ctx = outlink->src; - BlackDetectContext *blackdetect = ctx->priv; - AVFilterLink *inlink = ctx->inputs[0]; - int ret = ff_request_frame(inlink); + BlackDetectContext *s = ctx->priv; + const unsigned int threshold = s->pixel_black_th_i; + unsigned int *counterp = &s->counter[jobnr]; + AVFrame *in = arg; + const int linesize = in->linesize[0]; + const int w = in->width; + const int h = in->height; + const int start = (h * jobnr) / nb_jobs; + const int end = (h * (jobnr+1)) / nb_jobs; + const int size = end - start; + unsigned int counter = 0; + + if (s->depth == 8) { + const uint8_t *p = in->data[0] + start * linesize; + + for (int i = 0; i < size; i++) { + for (int x = 0; x < w; x++) + counter += p[x] <= threshold; + p += linesize; + } + } else { + const uint16_t *p = (const uint16_t *)(in->data[0] + start * linesize); - if (ret == AVERROR_EOF && blackdetect->black_started) { - // FIXME: black_end should be set to last_picref_pts + last_picref_duration - blackdetect->black_end = blackdetect->last_picref_pts; - check_black_end(ctx); + for (int i = 0; i < size; i++) { + for (int x = 0; x < w; x++) + counter += p[x] <= threshold; + p += linesize / 2; + } } - return ret; + + *counterp = counter; + + return 0; } -// TODO: document metadata static int filter_frame(AVFilterLink *inlink, AVFrame *picref) { AVFilterContext *ctx = inlink->dst; - BlackDetectContext *blackdetect = ctx->priv; + BlackDetectContext *s = ctx->priv; double picture_black_ratio = 0; - const uint8_t *p = picref->data[0]; - int x, i; - for (i = 0; i < inlink->h; i++) { - for (x = 0; x < inlink->w; x++) - blackdetect->nb_black_pixels += p[x] <= blackdetect->pixel_black_th_i; - p += picref->linesize[0]; - } + ctx->internal->execute(ctx, black_counter, picref, NULL, + FFMIN(inlink->h, s->nb_threads)); - picture_black_ratio = (double)blackdetect->nb_black_pixels / (inlink->w * inlink->h); + for (int i = 0; i < s->nb_threads; i++) + s->nb_black_pixels += s->counter[i]; + + picture_black_ratio = (double)s->nb_black_pixels / (inlink->w * inlink->h); av_log(ctx, AV_LOG_DEBUG, "frame:%"PRId64" picture_black_ratio:%f pts:%s t:%s type:%c\n", inlink->frame_count_out, picture_black_ratio, - av_ts2str(picref->pts), av_ts2timestr(picref->pts, &inlink->time_base), + av_ts2str(picref->pts), av_ts2timestr(picref->pts, &s->time_base), av_get_picture_type_char(picref->pict_type)); - if (picture_black_ratio >= blackdetect->picture_black_ratio_th) { - if (!blackdetect->black_started) { + if (picture_black_ratio >= s->picture_black_ratio_th) { + if (!s->black_started) { /* black starts here */ - blackdetect->black_started = 1; - blackdetect->black_start = picref->pts; + s->black_started = 1; + s->black_start = picref->pts; av_dict_set(&picref->metadata, "lavfi.black_start", - av_ts2timestr(blackdetect->black_start, &inlink->time_base), 0); + av_ts2timestr(s->black_start, &s->time_base), 0); } - } else if (blackdetect->black_started) { + } else if (s->black_started) { /* black ends here */ - blackdetect->black_started = 0; - blackdetect->black_end = picref->pts; + s->black_started = 0; + s->black_end = picref->pts; check_black_end(ctx); av_dict_set(&picref->metadata, "lavfi.black_end", - av_ts2timestr(blackdetect->black_end, &inlink->time_base), 0); + av_ts2timestr(s->black_end, &s->time_base), 0); } - blackdetect->last_picref_pts = picref->pts; - blackdetect->nb_black_pixels = 0; + s->last_picref_pts = picref->pts; + s->nb_black_pixels = 0; return ff_filter_frame(inlink->dst->outputs[0], picref); } +static av_cold void uninit(AVFilterContext *ctx) +{ + BlackDetectContext *s = ctx->priv; + + av_freep(&s->counter); + + if (s->black_started) { + // FIXME: black_end should be set to last_picref_pts + last_picref_duration + s->black_end = s->last_picref_pts; + check_black_end(ctx); + } +} + static const AVFilterPad blackdetect_inputs[] = { { .name = "default", @@ -195,7 +254,6 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, }, { NULL } }; @@ -207,5 +265,7 @@ .query_formats = query_formats, .inputs = blackdetect_inputs, .outputs = blackdetect_outputs, + .uninit = uninit, .priv_class = &blackdetect_class, + .flags = AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_blend.c ffmpeg-4.4/libavfilter/vf_blend.c --- ffmpeg-4.2.2/libavfilter/vf_blend.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_blend.c 2021-04-08 21:28:40.000000000 +0000 @@ -19,6 +19,7 @@ */ #include "libavutil/imgutils.h" +#include "libavutil/intfloat.h" #include "libavutil/eval.h" #include "libavutil/opt.h" #include "libavutil/pixfmt.h" @@ -59,63 +60,60 @@ FilterParams *param; } ThreadData; -#define COMMON_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"},\ - { "addition", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_ADDITION}, 0, 0, FLAGS, "mode" },\ - { "addition128","", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_GRAINMERGE}, 0, 0, FLAGS, "mode" },\ - { "grainmerge", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_GRAINMERGE}, 0, 0, FLAGS, "mode" },\ - { "and", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_AND}, 0, 0, FLAGS, "mode" },\ - { "average", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_AVERAGE}, 0, 0, FLAGS, "mode" },\ - { "burn", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_BURN}, 0, 0, FLAGS, "mode" },\ - { "darken", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DARKEN}, 0, 0, FLAGS, "mode" },\ - { "difference", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DIFFERENCE}, 0, 0, FLAGS, "mode" },\ - { "difference128", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_GRAINEXTRACT}, 0, 0, FLAGS, "mode" },\ - { "grainextract", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_GRAINEXTRACT}, 0, 0, FLAGS, "mode" },\ - { "divide", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DIVIDE}, 0, 0, FLAGS, "mode" },\ - { "dodge", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DODGE}, 0, 0, FLAGS, "mode" },\ - { "exclusion", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_EXCLUSION}, 0, 0, FLAGS, "mode" },\ - { "extremity", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_EXTREMITY}, 0, 0, FLAGS, "mode" },\ - { "freeze", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_FREEZE}, 0, 0, FLAGS, "mode" },\ - { "glow", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_GLOW}, 0, 0, FLAGS, "mode" },\ - { "hardlight", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_HARDLIGHT}, 0, 0, FLAGS, "mode" },\ - { "hardmix", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_HARDMIX}, 0, 0, FLAGS, "mode" },\ - { "heat", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_HEAT}, 0, 0, FLAGS, "mode" },\ - { "lighten", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_LIGHTEN}, 0, 0, FLAGS, "mode" },\ - { "linearlight","", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_LINEARLIGHT},0, 0, FLAGS, "mode" },\ - { "multiply", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_MULTIPLY}, 0, 0, FLAGS, "mode" },\ - { "multiply128","", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_MULTIPLY128},0, 0, FLAGS, "mode" },\ - { "negation", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_NEGATION}, 0, 0, FLAGS, "mode" },\ - { "normal", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_NORMAL}, 0, 0, FLAGS, "mode" },\ - { "or", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_OR}, 0, 0, FLAGS, "mode" },\ - { "overlay", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_OVERLAY}, 0, 0, FLAGS, "mode" },\ - { "phoenix", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_PHOENIX}, 0, 0, FLAGS, "mode" },\ - { "pinlight", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_PINLIGHT}, 0, 0, FLAGS, "mode" },\ - { "reflect", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_REFLECT}, 0, 0, FLAGS, "mode" },\ - { "screen", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_SCREEN}, 0, 0, FLAGS, "mode" },\ - { "softlight", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_SOFTLIGHT}, 0, 0, FLAGS, "mode" },\ - { "subtract", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_SUBTRACT}, 0, 0, FLAGS, "mode" },\ - { "vividlight", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_VIVIDLIGHT}, 0, 0, FLAGS, "mode" },\ - { "xor", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_XOR}, 0, 0, FLAGS, "mode" },\ - { "c0_expr", "set color component #0 expression", OFFSET(params[0].expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },\ - { "c1_expr", "set color component #1 expression", OFFSET(params[1].expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },\ - { "c2_expr", "set color component #2 expression", OFFSET(params[2].expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },\ - { "c3_expr", "set color component #3 expression", OFFSET(params[3].expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },\ - { "all_expr", "set expression for all color components", OFFSET(all_expr), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },\ - { "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} - #define OFFSET(x) offsetof(BlendContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption blend_options[] = { - COMMON_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" }, + { "addition", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_ADDITION}, 0, 0, FLAGS, "mode" }, + { "addition128","", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_GRAINMERGE}, 0, 0, FLAGS, "mode" }, + { "grainmerge", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_GRAINMERGE}, 0, 0, FLAGS, "mode" }, + { "and", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_AND}, 0, 0, FLAGS, "mode" }, + { "average", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_AVERAGE}, 0, 0, FLAGS, "mode" }, + { "burn", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_BURN}, 0, 0, FLAGS, "mode" }, + { "darken", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DARKEN}, 0, 0, FLAGS, "mode" }, + { "difference", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DIFFERENCE}, 0, 0, FLAGS, "mode" }, + { "difference128", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_GRAINEXTRACT}, 0, 0, FLAGS, "mode" }, + { "grainextract", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_GRAINEXTRACT}, 0, 0, FLAGS, "mode" }, + { "divide", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DIVIDE}, 0, 0, FLAGS, "mode" }, + { "dodge", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DODGE}, 0, 0, FLAGS, "mode" }, + { "exclusion", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_EXCLUSION}, 0, 0, FLAGS, "mode" }, + { "extremity", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_EXTREMITY}, 0, 0, FLAGS, "mode" }, + { "freeze", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_FREEZE}, 0, 0, FLAGS, "mode" }, + { "glow", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_GLOW}, 0, 0, FLAGS, "mode" }, + { "hardlight", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_HARDLIGHT}, 0, 0, FLAGS, "mode" }, + { "hardmix", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_HARDMIX}, 0, 0, FLAGS, "mode" }, + { "heat", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_HEAT}, 0, 0, FLAGS, "mode" }, + { "lighten", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_LIGHTEN}, 0, 0, FLAGS, "mode" }, + { "linearlight","", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_LINEARLIGHT},0, 0, FLAGS, "mode" }, + { "multiply", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_MULTIPLY}, 0, 0, FLAGS, "mode" }, + { "multiply128","", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_MULTIPLY128},0, 0, FLAGS, "mode" }, + { "negation", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_NEGATION}, 0, 0, FLAGS, "mode" }, + { "normal", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_NORMAL}, 0, 0, FLAGS, "mode" }, + { "or", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_OR}, 0, 0, FLAGS, "mode" }, + { "overlay", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_OVERLAY}, 0, 0, FLAGS, "mode" }, + { "phoenix", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_PHOENIX}, 0, 0, FLAGS, "mode" }, + { "pinlight", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_PINLIGHT}, 0, 0, FLAGS, "mode" }, + { "reflect", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_REFLECT}, 0, 0, FLAGS, "mode" }, + { "screen", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_SCREEN}, 0, 0, FLAGS, "mode" }, + { "softlight", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_SOFTLIGHT}, 0, 0, FLAGS, "mode" }, + { "subtract", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_SUBTRACT}, 0, 0, FLAGS, "mode" }, + { "vividlight", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_VIVIDLIGHT}, 0, 0, FLAGS, "mode" }, + { "xor", "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_XOR}, 0, 0, FLAGS, "mode" }, + { "c0_expr", "set color component #0 expression", OFFSET(params[0].expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "c1_expr", "set color component #1 expression", OFFSET(params[1].expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "c2_expr", "set color component #2 expression", OFFSET(params[2].expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "c3_expr", "set color component #3 expression", OFFSET(params[3].expr_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "all_expr", "set expression for all color components", OFFSET(all_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "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 } }; @@ -138,6 +136,9 @@ COPY(top, 16) COPY(bottom, 16) +COPY(top, 32) +COPY(bottom, 32) + #undef COPY static void blend_normal_8bit(const uint8_t *top, ptrdiff_t top_linesize, @@ -184,6 +185,31 @@ } } +static void blend_normal_32bit(const uint8_t *_top, ptrdiff_t top_linesize, + const uint8_t *_bottom, ptrdiff_t bottom_linesize, + uint8_t *_dst, ptrdiff_t dst_linesize, + ptrdiff_t width, ptrdiff_t height, + FilterParams *param, double *values, int starty) +{ + const float *top = (float*)_top; + const float *bottom = (float*)_bottom; + float *dst = (float*)_dst; + const double opacity = param->opacity; + int i, j; + dst_linesize /= 4; + top_linesize /= 4; + bottom_linesize /= 4; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + dst[j] = top[j] * opacity + bottom[j] * (1. - opacity); + } + dst += dst_linesize; + top += top_linesize; + bottom += bottom_linesize; + } +} + #define DEFINE_BLEND8(name, expr) \ static void blend_## name##_8bit(const uint8_t *top, ptrdiff_t top_linesize, \ const uint8_t *bottom, ptrdiff_t bottom_linesize, \ @@ -230,6 +256,32 @@ } \ } +#define DEFINE_BLEND32(name, expr, depth) \ +static void blend_## name##_##depth##bit(const uint8_t *_top, ptrdiff_t top_linesize,\ + const uint8_t *_bottom, ptrdiff_t bottom_linesize, \ + uint8_t *_dst, ptrdiff_t dst_linesize, \ + ptrdiff_t width, ptrdiff_t height, \ + FilterParams *param, double *values, int starty) \ +{ \ + const float *top = (const float*)_top; \ + const float *bottom = (const float*)_bottom; \ + float *dst = (float*)_dst; \ + double opacity = param->opacity; \ + int i, j; \ + dst_linesize /= 4; \ + top_linesize /= 4; \ + bottom_linesize /= 4; \ + \ + for (i = 0; i < height; i++) { \ + for (j = 0; j < width; j++) { \ + dst[j] = top[j] + ((expr) - top[j]) * opacity; \ + } \ + dst += dst_linesize; \ + top += top_linesize; \ + bottom += bottom_linesize; \ + } \ +} + #define A top[j] #define B bottom[j] @@ -443,6 +495,49 @@ DEFINE_BLEND16(vividlight, (A < 256) ? BURN(2 * A, B) : DODGE(2 * (A - 256), B), 9) DEFINE_BLEND16(linearlight,(int)av_clip_uintp2((B < 256) ? B + 2 * A - 511 : B + 2 * (A - 256), 9), 9) +#undef MULTIPLY +#undef SCREEN +#undef BURN +#undef DODGE + +#define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / 1.0)) +#define SCREEN(x, a, b) (1.0 - (x) * ((1.0 - (a)) * (1.0 - (b)) / 1.0)) +#define BURN(a, b) (((a) <= 0.0) ? (a) : FFMAX(0.0, 1.0 - (1.0 - (b)) / (a))) +#define DODGE(a, b) (((a) >= 1.0) ? (a) : FFMIN(1.0, ((b) / (1.0 - (a))))) + +DEFINE_BLEND32(addition, A + B, 32) +DEFINE_BLEND32(grainmerge, A + B - 0.5, 32) +DEFINE_BLEND32(average, (A + B) / 2, 32) +DEFINE_BLEND32(subtract, A - B, 32) +DEFINE_BLEND32(multiply, A * B, 32) +DEFINE_BLEND32(multiply128, (A - 0.5) * B / 0.125 + 0.5, 32) +DEFINE_BLEND32(negation, 1.0 - FFABS(1.0 - A - B), 32) +DEFINE_BLEND32(extremity, FFABS(1.0 - A - B), 32) +DEFINE_BLEND32(difference, FFABS(A - B), 32) +DEFINE_BLEND32(grainextract, 0.5 + A - B, 32) +DEFINE_BLEND32(screen, SCREEN(1, A, B), 32) +DEFINE_BLEND32(overlay, (A < 0.5) ? MULTIPLY(2, A, B) : SCREEN(2, A, B), 32) +DEFINE_BLEND32(hardlight, (B < 0.5) ? MULTIPLY(2, B, A) : SCREEN(2, B, A), 32) +DEFINE_BLEND32(hardmix, (A < (1.0 - B)) ? 0: 1.0, 32) +DEFINE_BLEND32(heat, (A == 0) ? 0 : 1.0 - FFMIN(((1.0 - B) * (1.0 - B)) / A, 1.0), 32) +DEFINE_BLEND32(freeze, (B == 0) ? 0 : 1.0 - FFMIN(((1.0 - A) * (1.0 - A)) / B, 1.0), 32) +DEFINE_BLEND32(darken, FFMIN(A, B), 32) +DEFINE_BLEND32(lighten, FFMAX(A, B), 32) +DEFINE_BLEND32(divide, B == 0 ? 1.0 : 1.0 * A / B, 32) +DEFINE_BLEND32(dodge, DODGE(A, B), 32) +DEFINE_BLEND32(burn, BURN(A, B), 32) +DEFINE_BLEND32(softlight, (A > 0.5) ? B + (1.0 - B) * (A - 0.5) / 0.5 * (0.5 - fabs(B - 0.5) / 1.0): B - B * ((0.5 - A) / 0.5) * (0.5 - fabs(B - 0.5)/1.0), 32) +DEFINE_BLEND32(exclusion, A + B - 2 * A * B / 1.0, 32) +DEFINE_BLEND32(pinlight, (B < 0.5) ? FFMIN(A, 2 * B) : FFMAX(A, 2 * (B - 0.5)), 32) +DEFINE_BLEND32(phoenix, FFMIN(A, B) - FFMAX(A, B) + 1.0, 32) +DEFINE_BLEND32(reflect, (B == 1.0) ? B : FFMIN(1.0, (A * A / (1.0 - B))), 32) +DEFINE_BLEND32(glow, (A == 1.0) ? A : FFMIN(1.0, (B * B / (1.0 - A))), 32) +DEFINE_BLEND32(and, av_int2float(av_float2int(A) & av_float2int(B)), 32) +DEFINE_BLEND32(or, av_int2float(av_float2int(A) | av_float2int(B)), 32) +DEFINE_BLEND32(xor, av_int2float(av_float2int(A) ^ av_float2int(B)), 32) +DEFINE_BLEND32(vividlight, (A < 0.5) ? BURN(2 * A, B) : DODGE(2 * (A - 0.5), B), 32) +DEFINE_BLEND32(linearlight,(B < 0.5) ? B + 2 * A - 1.0 : B + 2 * (A - 0.5), 32) + #define DEFINE_BLEND_EXPR(type, name, div) \ static void blend_expr_## name(const uint8_t *_top, ptrdiff_t top_linesize, \ const uint8_t *_bottom, ptrdiff_t bottom_linesize, \ @@ -475,6 +570,7 @@ DEFINE_BLEND_EXPR(uint8_t, 8bit, 1) DEFINE_BLEND_EXPR(uint16_t, 16bit, 2) +DEFINE_BLEND_EXPR(float, 32bit, 4) static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { @@ -575,10 +671,12 @@ AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GRAY10, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GRAY12, AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_GRAYF32, AV_PIX_FMT_NONE }; @@ -600,50 +698,51 @@ av_expr_free(s->params[i].e); } -#define DEFINE_INIT_BLEND_FUNC(depth, nbits) \ -static av_cold void init_blend_func_##depth##_##nbits##bit(FilterParams *param) \ -{ \ - switch (param->mode) { \ - case BLEND_ADDITION: param->blend = blend_addition_##depth##bit; break; \ - case BLEND_GRAINMERGE: param->blend = blend_grainmerge_##depth##bit; break; \ - case BLEND_AND: param->blend = blend_and_##depth##bit; break; \ - case BLEND_AVERAGE: param->blend = blend_average_##depth##bit; break; \ - case BLEND_BURN: param->blend = blend_burn_##depth##bit; break; \ - case BLEND_DARKEN: param->blend = blend_darken_##depth##bit; break; \ - case BLEND_DIFFERENCE: param->blend = blend_difference_##depth##bit; break; \ - case BLEND_GRAINEXTRACT: param->blend = blend_grainextract_##depth##bit; break; \ - case BLEND_DIVIDE: param->blend = blend_divide_##depth##bit; break; \ - case BLEND_DODGE: param->blend = blend_dodge_##depth##bit; break; \ - case BLEND_EXCLUSION: param->blend = blend_exclusion_##depth##bit; break; \ - case BLEND_EXTREMITY: param->blend = blend_extremity_##depth##bit; break; \ - case BLEND_FREEZE: param->blend = blend_freeze_##depth##bit; break; \ - case BLEND_GLOW: param->blend = blend_glow_##depth##bit; break; \ - case BLEND_HARDLIGHT: param->blend = blend_hardlight_##depth##bit; break; \ - case BLEND_HARDMIX: param->blend = blend_hardmix_##depth##bit; break; \ - case BLEND_HEAT: param->blend = blend_heat_##depth##bit; break; \ - case BLEND_LIGHTEN: param->blend = blend_lighten_##depth##bit; break; \ - case BLEND_LINEARLIGHT:param->blend = blend_linearlight_##depth##bit;break; \ - case BLEND_MULTIPLY: param->blend = blend_multiply_##depth##bit; break; \ - case BLEND_MULTIPLY128:param->blend = blend_multiply128_##depth##bit;break; \ - case BLEND_NEGATION: param->blend = blend_negation_##depth##bit; break; \ - case BLEND_NORMAL: param->blend = blend_normal_##nbits##bit; break; \ - case BLEND_OR: param->blend = blend_or_##depth##bit; break; \ - case BLEND_OVERLAY: param->blend = blend_overlay_##depth##bit; break; \ - case BLEND_PHOENIX: param->blend = blend_phoenix_##depth##bit; break; \ - case BLEND_PINLIGHT: param->blend = blend_pinlight_##depth##bit; break; \ - case BLEND_REFLECT: param->blend = blend_reflect_##depth##bit; break; \ - case BLEND_SCREEN: param->blend = blend_screen_##depth##bit; break; \ - case BLEND_SOFTLIGHT: param->blend = blend_softlight_##depth##bit; break; \ - case BLEND_SUBTRACT: param->blend = blend_subtract_##depth##bit; break; \ - case BLEND_VIVIDLIGHT: param->blend = blend_vividlight_##depth##bit; break; \ - case BLEND_XOR: param->blend = blend_xor_##depth##bit; break; \ - } \ -} -DEFINE_INIT_BLEND_FUNC(8, 8); -DEFINE_INIT_BLEND_FUNC(9, 16); -DEFINE_INIT_BLEND_FUNC(10, 16); -DEFINE_INIT_BLEND_FUNC(12, 16); -DEFINE_INIT_BLEND_FUNC(16, 16); +#define DEFINE_INIT_BLEND_FUNC(depth, nbits) \ +static av_cold void init_blend_func_##depth##_##nbits##bit(FilterParams *param) \ +{ \ + switch (param->mode) { \ + case BLEND_ADDITION: param->blend = blend_addition_##depth##bit; break; \ + case BLEND_GRAINMERGE: param->blend = blend_grainmerge_##depth##bit; break; \ + case BLEND_AND: param->blend = blend_and_##depth##bit; break; \ + case BLEND_AVERAGE: param->blend = blend_average_##depth##bit; break; \ + case BLEND_BURN: param->blend = blend_burn_##depth##bit; break; \ + case BLEND_DARKEN: param->blend = blend_darken_##depth##bit; break; \ + case BLEND_DIFFERENCE: param->blend = blend_difference_##depth##bit; break; \ + case BLEND_GRAINEXTRACT: param->blend = blend_grainextract_##depth##bit; break; \ + case BLEND_DIVIDE: param->blend = blend_divide_##depth##bit; break; \ + case BLEND_DODGE: param->blend = blend_dodge_##depth##bit; break; \ + case BLEND_EXCLUSION: param->blend = blend_exclusion_##depth##bit; break; \ + case BLEND_EXTREMITY: param->blend = blend_extremity_##depth##bit; break; \ + case BLEND_FREEZE: param->blend = blend_freeze_##depth##bit; break; \ + case BLEND_GLOW: param->blend = blend_glow_##depth##bit; break; \ + case BLEND_HARDLIGHT: param->blend = blend_hardlight_##depth##bit; break; \ + case BLEND_HARDMIX: param->blend = blend_hardmix_##depth##bit; break; \ + case BLEND_HEAT: param->blend = blend_heat_##depth##bit; break; \ + case BLEND_LIGHTEN: param->blend = blend_lighten_##depth##bit; break; \ + case BLEND_LINEARLIGHT: param->blend = blend_linearlight_##depth##bit; break; \ + case BLEND_MULTIPLY: param->blend = blend_multiply_##depth##bit; break; \ + case BLEND_MULTIPLY128: param->blend = blend_multiply128_##depth##bit; break; \ + case BLEND_NEGATION: param->blend = blend_negation_##depth##bit; break; \ + case BLEND_NORMAL: param->blend = blend_normal_##nbits##bit; break; \ + case BLEND_OR: param->blend = blend_or_##depth##bit; break; \ + case BLEND_OVERLAY: param->blend = blend_overlay_##depth##bit; break; \ + case BLEND_PHOENIX: param->blend = blend_phoenix_##depth##bit; break; \ + case BLEND_PINLIGHT: param->blend = blend_pinlight_##depth##bit; break; \ + case BLEND_REFLECT: param->blend = blend_reflect_##depth##bit; break; \ + case BLEND_SCREEN: param->blend = blend_screen_##depth##bit; break; \ + case BLEND_SOFTLIGHT: param->blend = blend_softlight_##depth##bit; break; \ + case BLEND_SUBTRACT: param->blend = blend_subtract_##depth##bit; break; \ + case BLEND_VIVIDLIGHT: param->blend = blend_vividlight_##depth##bit; break; \ + case BLEND_XOR: param->blend = blend_xor_##depth##bit; break; \ + } \ +} +DEFINE_INIT_BLEND_FUNC(8, 8) +DEFINE_INIT_BLEND_FUNC(9, 16) +DEFINE_INIT_BLEND_FUNC(10, 16) +DEFINE_INIT_BLEND_FUNC(12, 16) +DEFINE_INIT_BLEND_FUNC(16, 16) +DEFINE_INIT_BLEND_FUNC(32, 32) void ff_blend_init(FilterParams *param, int depth) { @@ -663,28 +762,63 @@ case 16: init_blend_func_16_16bit(param); break; + case 32: + init_blend_func_32_32bit(param); + break; } if (param->opacity == 0 && param->mode != BLEND_NORMAL) { - param->blend = depth > 8 ? blend_copytop_16 : blend_copytop_8; + param->blend = depth > 8 ? depth > 16 ? blend_copytop_32 : blend_copytop_16 : blend_copytop_8; } else if (param->mode == BLEND_NORMAL) { if (param->opacity == 1) - param->blend = depth > 8 ? blend_copytop_16 : blend_copytop_8; + param->blend = depth > 8 ? depth > 16 ? blend_copytop_32 : blend_copytop_16 : blend_copytop_8; else if (param->opacity == 0) - param->blend = depth > 8 ? blend_copybottom_16 : blend_copybottom_8; + param->blend = depth > 8 ? depth > 16 ? blend_copybottom_32 : blend_copybottom_16 : blend_copybottom_8; } if (ARCH_X86) ff_blend_init_x86(param, depth); } +static int config_params(AVFilterContext *ctx) +{ + BlendContext *s = ctx->priv; + int ret; + + for (int plane = 0; plane < FF_ARRAY_ELEMS(s->params); plane++) { + FilterParams *param = &s->params[plane]; + + if (s->all_mode >= 0) + param->mode = s->all_mode; + if (s->all_opacity < 1) + param->opacity = s->all_opacity; + + ff_blend_init(param, s->depth); + + if (s->all_expr && !param->expr_str) { + param->expr_str = av_strdup(s->all_expr); + if (!param->expr_str) + return AVERROR(ENOMEM); + } + if (param->expr_str) { + ret = av_expr_parse(¶m->e, param->expr_str, var_names, + NULL, NULL, NULL, NULL, 0, ctx); + if (ret < 0) + return ret; + param->blend = s->depth > 8 ? s->depth > 16 ? blend_expr_32bit : blend_expr_16bit : blend_expr_8bit; + } + } + + return 0; +} + static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; AVFilterLink *toplink = ctx->inputs[TOP]; BlendContext *s = ctx->priv; const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(toplink->format); - int ret, plane; + int ret; if (!s->tblend) { AVFilterLink *bottomlink = ctx->inputs[BOTTOM]; @@ -719,29 +853,9 @@ if ((ret = ff_framesync_init_dualinput(&s->fs, ctx)) < 0) return ret; - for (plane = 0; plane < FF_ARRAY_ELEMS(s->params); plane++) { - FilterParams *param = &s->params[plane]; - - if (s->all_mode >= 0) - param->mode = s->all_mode; - if (s->all_opacity < 1) - param->opacity = s->all_opacity; - - ff_blend_init(param, s->depth); - - if (s->all_expr && !param->expr_str) { - param->expr_str = av_strdup(s->all_expr); - if (!param->expr_str) - return AVERROR(ENOMEM); - } - if (param->expr_str) { - ret = av_expr_parse(¶m->e, param->expr_str, var_names, - NULL, NULL, NULL, NULL, 0, ctx); - if (ret < 0) - return ret; - param->blend = s->depth > 8 ? blend_expr_16bit : blend_expr_8bit; - } - } + ret = config_params(ctx); + if (ret < 0) + return ret; if (s->tblend) return 0; @@ -752,6 +866,18 @@ return ret; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_params(ctx); +} + #if CONFIG_BLEND_FILTER static int activate(AVFilterContext *ctx) @@ -793,6 +919,7 @@ .outputs = blend_outputs, .priv_class = &blend_class, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; #endif @@ -820,11 +947,7 @@ return 0; } -static const AVOption tblend_options[] = { - COMMON_OPTIONS, - { NULL } -}; - +#define tblend_options blend_options AVFILTER_DEFINE_CLASS(tblend); static const AVFilterPad tblend_inputs[] = { @@ -856,6 +979,7 @@ .inputs = tblend_inputs, .outputs = tblend_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; #endif diff -Nru ffmpeg-4.2.2/libavfilter/vf_bm3d.c ffmpeg-4.4/libavfilter/vf_bm3d.c --- ffmpeg-4.2.2/libavfilter/vf_bm3d.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_bm3d.c 2021-04-08 21:28:40.000000000 +0000 @@ -153,7 +153,7 @@ { "final", "final estimate", 0, AV_OPT_TYPE_CONST, {.i64=FINAL}, 0, 0, FLAGS, "mode" }, { "ref", "have reference stream", - OFFSET(ref), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS }, + OFFSET(ref), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGS }, { NULL } @@ -164,9 +164,8 @@ static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_GRAY8, - AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, - AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, + AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, @@ -182,6 +181,11 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; @@ -439,7 +443,7 @@ } } - threshold[0] = s->hard_threshold * s->sigma; + threshold[0] = s->hard_threshold * s->sigma * M_SQRT2 * block_size * block_size * (1 << (s->depth - 8)) / 255.f; threshold[1] = threshold[0] * sqrtf(2.f); threshold[2] = threshold[0] * 2.f; threshold[3] = threshold[0] * sqrtf(8.f); @@ -660,7 +664,7 @@ sum_den += den; } - dstp[j] = av_clip_uint8(sum_num / sum_den); + dstp[j] = av_clip_uint8(lrintf(sum_num / sum_den)); } } } @@ -688,7 +692,7 @@ sum_den += den; } - dstp[j] = av_clip_uintp2_c(sum_num / sum_den, depth); + dstp[j] = av_clip_uintp2_c(lrintf(sum_num / sum_den), depth); } } } @@ -706,8 +710,8 @@ const int plane = td->plane; const int width = s->planewidth[plane]; const int height = s->planeheight[plane]; - const int block_pos_bottom = height - s->block_size; - const int block_pos_right = width - s->block_size; + const int block_pos_bottom = FFMAX(0, height - s->block_size); + const int block_pos_right = FFMAX(0, width - s->block_size); const int slice_start = (((height + block_step - 1) / block_step) * jobnr / nb_jobs) * block_step; const int slice_end = (jobnr == nb_jobs - 1) ? block_pos_bottom + block_step : (((height + block_step - 1) / block_step) * (jobnr + 1) / nb_jobs) * block_step; @@ -748,7 +752,7 @@ av_frame_copy_props(*out, in); for (p = 0; p < s->nb_planes; p++) { - const int nb_jobs = FFMIN(s->nb_threads, s->planeheight[p] / s->block_step); + const int nb_jobs = FFMAX(1, FFMIN(s->nb_threads, s->planeheight[p] / s->block_size)); ThreadData td; if (!((1 << p) & s->planes) || ctx->is_disabled) { @@ -796,8 +800,8 @@ for (i = 0; i < s->nb_threads; i++) { SliceContext *sc = &s->slices[i]; - sc->num = av_calloc(s->planewidth[0] * s->planeheight[0], sizeof(FFTSample)); - sc->den = av_calloc(s->planewidth[0] * s->planeheight[0], sizeof(FFTSample)); + sc->num = av_calloc(FFALIGN(s->planewidth[0], s->block_size) * FFALIGN(s->planeheight[0], s->block_size), sizeof(FFTSample)); + sc->den = av_calloc(FFALIGN(s->planewidth[0], s->block_size) * FFALIGN(s->planeheight[0], s->block_size), sizeof(FFTSample)); if (!sc->num || !sc->den) return AVERROR(ENOMEM); @@ -857,6 +861,8 @@ int ret, status; int64_t pts; + FF_FILTER_FORWARD_STATUS_BACK(ctx->outputs[0], ctx->inputs[0]); + if ((ret = ff_inlink_consume_frame(ctx->inputs[0], &frame)) > 0) { ret = filter_frame(ctx, &out, frame, frame); av_frame_free(&frame); @@ -936,27 +942,19 @@ } pad.type = AVMEDIA_TYPE_VIDEO; - pad.name = av_strdup("source"); + pad.name = "source"; pad.config_props = config_input; - if (!pad.name) - return AVERROR(ENOMEM); - if ((ret = ff_insert_inpad(ctx, 0, &pad)) < 0) { - av_freep(&pad.name); + if ((ret = ff_insert_inpad(ctx, 0, &pad)) < 0) return ret; - } if (s->ref) { pad.type = AVMEDIA_TYPE_VIDEO; - pad.name = av_strdup("reference"); + pad.name = "reference"; pad.config_props = NULL; - if (!pad.name) - return AVERROR(ENOMEM); - if ((ret = ff_insert_inpad(ctx, 1, &pad)) < 0) { - av_freep(&pad.name); + if ((ret = ff_insert_inpad(ctx, 1, &pad)) < 0) return ret; - } } return 0; @@ -1021,9 +1019,6 @@ BM3DContext *s = ctx->priv; int i; - for (i = 0; i < ctx->nb_inputs; i++) - av_freep(&ctx->input_pads[i].name); - if (s->ref) ff_framesync_uninit(&s->fs); diff -Nru ffmpeg-4.2.2/libavfilter/vf_bwdif.c ffmpeg-4.4/libavfilter/vf_bwdif.c --- ffmpeg-4.2.2/libavfilter/vf_bwdif.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_bwdif.c 2020-07-11 10:39:30.000000000 +0000 @@ -343,8 +343,8 @@ if(yadif->mode&1) link->frame_rate = av_mul_q(link->src->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"); + if (link->w < 3 || link->h < 4) { + av_log(ctx, AV_LOG_ERROR, "Video of less than 3 columns or 4 lines is not supported\n"); return AVERROR(EINVAL); } diff -Nru ffmpeg-4.2.2/libavfilter/vf_cas.c ffmpeg-4.4/libavfilter/vf_cas.c --- ffmpeg-4.2.2/libavfilter/vf_cas.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_cas.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,299 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct CASContext { + const AVClass *class; + + float strength; + int planes; + int nb_planes; + + int depth; + int planeheight[4]; + int planewidth[4]; + + AVFrame *in; + + int (*do_slice)(AVFilterContext *s, void *arg, + int jobnr, int nb_jobs); +} CASContext; + +static inline float lerpf(float v0, float v1, float f) +{ + return v0 + (v1 - v0) * f; +} + +static int cas_slice8(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) +{ + CASContext *s = avctx->priv; + const float strength = -lerpf(16.f, 4.01f, s->strength); + AVFrame *out = arg; + AVFrame *in = s->in; + + for (int p = 0; p < s->nb_planes; p++) { + const int slice_start = (s->planeheight[p] * jobnr) / nb_jobs; + const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs; + const int linesize = out->linesize[p]; + const int in_linesize = in->linesize[p]; + const int w = s->planewidth[p]; + const int w1 = w - 1; + const int h = s->planeheight[p]; + const int h1 = h - 1; + uint8_t *dst = out->data[p] + slice_start * linesize; + const uint8_t *src = in->data[p]; + + if (!((1 << p) & s->planes)) { + av_image_copy_plane(dst, linesize, src + slice_start * linesize, in_linesize, + w, slice_end - slice_start); + continue; + } + + for (int y = slice_start; y < slice_end; y++) { + const int y0 = FFMAX(y - 1, 0); + const int y1 = FFMIN(y + 1, h1); + for (int x = 0; x < w; x++) { + const int x0 = FFMAX(x - 1, 0); + const int x1 = FFMIN(x + 1, w1); + int a = src[y0 * in_linesize + x0]; + int b = src[y0 * in_linesize + x]; + int c = src[y0 * in_linesize + x1]; + int d = src[y * in_linesize + x0]; + int e = src[y * in_linesize + x]; + int f = src[y * in_linesize + x1]; + int g = src[y1 * in_linesize + x0]; + int h = src[y1 * in_linesize + x]; + int i = src[y1 * in_linesize + x1]; + int mn, mn2, mx, mx2; + float amp, weight; + + mn = FFMIN3(FFMIN3( d, e, f), b, h); + mn2 = FFMIN3(FFMIN3(mn, a, c), g, i); + + mn = mn + mn2; + + mx = FFMAX3(FFMAX3( d, e, f), b, h); + mx2 = FFMAX3(FFMAX3(mx, a, c), g, i); + + mx = mx + mx2; + + amp = sqrtf(av_clipf(FFMIN(mn, 511 - mx) / (float)mx, 0.f, 1.f)); + + weight = amp / strength; + + dst[x] = av_clip_uint8(((b + d + f + h) * weight + e) / (1.f + 4.f * weight)); + } + dst += linesize; + } + } + + return 0; +} + +static int cas_slice16(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) +{ + CASContext *s = avctx->priv; + const float strength = -lerpf(16.f, 4.01f, s->strength); + const int max = 2 * (1 << s->depth) - 1; + AVFrame *out = arg; + AVFrame *in = s->in; + + for (int p = 0; p < s->nb_planes; p++) { + const int slice_start = (s->planeheight[p] * jobnr) / nb_jobs; + const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs; + const int linesize = out->linesize[p] / 2; + const int in_linesize = in->linesize[p] / 2; + const int w = s->planewidth[p]; + const int w1 = w - 1; + const int h = s->planeheight[p]; + const int h1 = h - 1; + uint16_t *dst = (uint16_t *)out->data[p] + slice_start * linesize; + const uint16_t *src = (const uint16_t *)in->data[p]; + + if (!((1 << p) & s->planes)) { + av_image_copy_plane((uint8_t *)dst, linesize, (uint8_t *)(src + slice_start * linesize), + in_linesize, w * 2, slice_end - slice_start); + continue; + } + + for (int y = slice_start; y < slice_end; y++) { + const int y0 = FFMAX(y - 1, 0); + const int y1 = FFMIN(y + 1, h1); + for (int x = 0; x < w; x++) { + const int x0 = FFMAX(x - 1, 0); + const int x1 = FFMIN(x + 1, w1); + int a = src[y0 * in_linesize + x0]; + int b = src[y0 * in_linesize + x]; + int c = src[y0 * in_linesize + x1]; + int d = src[y * in_linesize + x0]; + int e = src[y * in_linesize + x]; + int f = src[y * in_linesize + x1]; + int g = src[y1 * in_linesize + x0]; + int h = src[y1 * in_linesize + x]; + int i = src[y1 * in_linesize + x1]; + int mn, mn2, mx, mx2; + float amp, weight; + + mn = FFMIN3(FFMIN3( d, e, f), b, h); + mn2 = FFMIN3(FFMIN3(mn, a, c), g, i); + + mn = mn + mn2; + + mx = FFMAX3(FFMAX3( d, e, f), b, h); + mx2 = FFMAX3(FFMAX3(mx, a, c), g, i); + + mx = mx + mx2; + + amp = sqrtf(av_clipf(FFMIN(mn, max - mx) / (float)mx, 0.f, 1.f)); + + weight = amp / strength; + + dst[x] = av_clip_uintp2_c(((b + d + f + h) * weight + e) / (1.f + 4.f * weight), s->depth); + } + dst += linesize; + } + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + CASContext *s = ctx->priv; + 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); + + s->in = in; + ctx->internal->execute(ctx, s->do_slice, out, NULL, + FFMIN(in->height, ff_filter_get_nb_threads(ctx))); + av_frame_free(&in); + s->in = NULL; + + return ff_filter_frame(ctx->outputs[0], out); +} + +static av_cold int query_formats(AVFilterContext *avctx) +{ + static const enum AVPixelFormat pixel_fmts[] = { + AV_PIX_FMT_GRAY8, + AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, + AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *formats = NULL; + + formats = ff_make_format_list(pixel_fmts); + if (!formats) + return AVERROR(ENOMEM); + + return ff_set_common_formats(avctx, formats); +} + +static av_cold int config_input(AVFilterLink *inlink) +{ + AVFilterContext *avctx = inlink->dst; + CASContext *s = avctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + + s->depth = desc->comp[0].depth; + s->nb_planes = desc->nb_components; + s->do_slice = s->depth <= 8 ? cas_slice8 : cas_slice16; + + return 0; +} + +static const AVFilterPad cas_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad cas_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(CASContext, x) +#define VF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption cas_options[] = { + { "strength", "set the sharpening strength", OFFSET(strength), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, VF }, + { "planes", "set what planes to filter", OFFSET(planes), AV_OPT_TYPE_FLAGS, {.i64=7}, 0, 15, VF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(cas); + +AVFilter ff_vf_cas = { + .name = "cas", + .description = NULL_IF_CONFIG_SMALL("Contrast Adaptive Sharpen."), + .priv_size = sizeof(CASContext), + .priv_class = &cas_class, + .query_formats = query_formats, + .inputs = cas_inputs, + .outputs = cas_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_chromaber_vulkan.c ffmpeg-4.4/libavfilter/vf_chromaber_vulkan.c --- ffmpeg-4.2.2/libavfilter/vf_chromaber_vulkan.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_chromaber_vulkan.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,347 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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.h" +#include "internal.h" + +#define CGROUPS (int [3]){ 32, 32, 1 } + +typedef struct ChromaticAberrationVulkanContext { + VulkanFilterContext vkctx; + + int initialized; + FFVkExecContext *exec; + VulkanPipeline *pl; + + /* Shader updators, must be in the main filter struct */ + VkDescriptorImageInfo input_images[3]; + VkDescriptorImageInfo output_images[3]; + + /* Push constants / options */ + struct { + float dist[2]; + } opts; +} ChromaticAberrationVulkanContext; + +static const char distort_chroma_kernel[] = { + C(0, void distort_rgb(ivec2 size, ivec2 pos) ) + C(0, { ) + C(1, const vec2 p = ((vec2(pos)/vec2(size)) - 0.5f)*2.0f; ) + C(1, const vec2 o = p * (dist - 1.0f); ) + C(0, ) + C(1, vec4 res; ) + C(1, res.r = texture(input_img[0], ((p - o)/2.0f) + 0.5f).r; ) + C(1, res.g = texture(input_img[0], ((p )/2.0f) + 0.5f).g; ) + C(1, res.b = texture(input_img[0], ((p + o)/2.0f) + 0.5f).b; ) + C(1, res.a = texture(input_img[0], ((p )/2.0f) + 0.5f).a; ) + C(1, imageStore(output_img[0], pos, res); ) + C(0, } ) + C(0, ) + C(0, void distort_chroma(int idx, ivec2 size, ivec2 pos) ) + C(0, { ) + C(1, vec2 p = ((vec2(pos)/vec2(size)) - 0.5f)*2.0f; ) + C(1, float d = sqrt(p.x*p.x + p.y*p.y); ) + C(1, p *= d / (d* dist); ) + C(1, vec4 res = texture(input_img[idx], (p/2.0f) + 0.5f); ) + C(1, imageStore(output_img[idx], pos, res); ) + C(0, } ) +}; + +static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) +{ + int err; + ChromaticAberrationVulkanContext *s = ctx->priv; + + /* Create a sampler */ + VkSampler *sampler = ff_vk_init_sampler(ctx, 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); + if (!s->pl) + return AVERROR(ENOMEM); + + /* Normalize options */ + s->opts.dist[0] = (s->opts.dist[0] / 100.0f) + 1.0f; + 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] = { + { + .name = "input_img", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->input_images, + .samplers = DUP_SAMPLER_ARRAY4(*sampler), + }, + { + .name = "output_img", + .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, + }, + }; + + SPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "chromaber_compute", + VK_SHADER_STAGE_COMPUTE_BIT); + if (!shd) + return AVERROR(ENOMEM); + + ff_vk_set_compute_shader_sizes(ctx, 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), + VK_SHADER_STAGE_COMPUTE_BIT); + + RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */ + + GLSLD( distort_chroma_kernel ); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + if (planes == 1) { + GLSLC(1, distort_rgb(imageSize(output_img[0]), pos); ); + } else { + GLSLC(1, ivec2 size = imageSize(output_img[0]); ); + GLSLC(1, vec2 npos = vec2(pos)/vec2(size); ); + GLSLC(1, vec4 res = texture(input_img[0], npos); ); + GLSLC(1, imageStore(output_img[0], pos, res); ); + for (int i = 1; i < planes; i++) { + GLSLC(0, ); + GLSLF(1, size = imageSize(output_img[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + GLSLF(2, distort_chroma(%i, size, pos); ,i); + GLSLC(1, } else { ); + GLSLC(2, npos = vec2(pos)/vec2(size); ); + GLSLF(2, res = texture(input_img[%i], npos); ,i); + GLSLF(2, imageStore(output_img[%i], pos, res); ,i); + GLSLC(1, } ); + } + } + GLSLC(0, } ); + + RET(ff_vk_compile_shader(ctx, shd, "main")); + } + + RET(ff_vk_init_pipeline_layout(ctx, s->pl)); + RET(ff_vk_init_compute_pipeline(ctx, s->pl)); + + /* Execution context */ + RET(ff_vk_create_exec_ctx(ctx, &s->exec)); + + s->initialized = 1; + + return 0; + +fail: + return err; +} + +static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) +{ + int err = 0; + VkCommandBuffer cmd_buf; + ChromaticAberrationVulkanContext *s = avctx->priv; + 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); + + /* 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); + + 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], + 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], + 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); + + for (int i = 0; i < planes; i++) { + VkImageMemoryBarrier bar[2] = { + { + .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, + }, + }; + + 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); + + in->layout[i] = bar[0].newLayout; + in->access[i] = bar[0].dstAccessMask; + + out->layout[i] = bar[1].newLayout; + out->access[i] = bar[1].dstAccessMask; + } + + ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl); + + ff_vk_update_push_exec(avctx, 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); + + 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); + + err = ff_vk_submit_exec_queue(avctx, s->exec); + if (err) + return err; + + return err; + +fail: + ff_vk_discard_exec_deps(avctx, s->exec); + return err; +} + +static int chromaber_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + int err; + AVFilterContext *ctx = link->dst; + ChromaticAberrationVulkanContext *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; + } + + if (!s->initialized) + RET(init_filter(ctx, in)); + + RET(process_frames(ctx, out, in)); + + err = av_frame_copy_props(out, in); + if (err < 0) + goto fail; + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return err; +} + +static void chromaber_vulkan_uninit(AVFilterContext *avctx) +{ + ChromaticAberrationVulkanContext *s = avctx->priv; + + ff_vk_filter_uninit(avctx); + + s->initialized = 0; +} + +#define OFFSET(x) offsetof(ChromaticAberrationVulkanContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption chromaber_vulkan_options[] = { + { "dist_x", "Set horizontal distortion amount", OFFSET(opts.dist[0]), AV_OPT_TYPE_FLOAT, {.dbl = 0.0f}, -10.0f, 10.0f, .flags = FLAGS }, + { "dist_y", "Set vertical distortion amount", OFFSET(opts.dist[1]), AV_OPT_TYPE_FLOAT, {.dbl = 0.0f}, -10.0f, 10.0f, .flags = FLAGS }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(chromaber_vulkan); + +static const AVFilterPad chromaber_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &chromaber_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + }, + { NULL } +}; + +static const AVFilterPad chromaber_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_chromaber_vulkan = { + .name = "chromaber_vulkan", + .description = NULL_IF_CONFIG_SMALL("Offset chroma of input video (chromatic aberration)"), + .priv_size = sizeof(ChromaticAberrationVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &chromaber_vulkan_uninit, + .query_formats = &ff_vk_filter_query_formats, + .inputs = chromaber_vulkan_inputs, + .outputs = chromaber_vulkan_outputs, + .priv_class = &chromaber_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_chromakey.c ffmpeg-4.4/libavfilter/vf_chromakey.c --- ffmpeg-4.2.2/libavfilter/vf_chromakey.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_chromakey.c 2020-07-11 10:39:30.000000000 +0000 @@ -20,6 +20,7 @@ #include "libavutil/opt.h" #include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" #include "avfilter.h" #include "formats.h" #include "internal.h" @@ -29,12 +30,15 @@ const AVClass *class; uint8_t chromakey_rgba[4]; - uint8_t chromakey_uv[2]; + uint16_t chromakey_uv[2]; float similarity; float blend; int is_yuv; + int depth; + int mid; + int max; int hsub_log2; int vsub_log2; @@ -52,7 +56,7 @@ du = (int)u[i] - ctx->chromakey_uv[0]; dv = (int)v[i] - ctx->chromakey_uv[1]; - diff += sqrt((du * du + dv * dv) / (255.0 * 255.0)); + diff += sqrt((du * du + dv * dv) / (255.0 * 255.0 * 2)); } diff /= 9.0; @@ -64,6 +68,28 @@ } } +static uint16_t do_chromakey_pixel16(ChromakeyContext *ctx, uint16_t u[9], uint16_t v[9]) +{ + double max = ctx->max; + double diff = 0.0; + int du, dv, i; + + for (i = 0; i < 9; ++i) { + du = (int)u[i] - ctx->chromakey_uv[0]; + dv = (int)v[i] - ctx->chromakey_uv[1]; + + diff += sqrt((du * du + dv * dv) / (max * max * 2)); + } + + diff /= 9.0; + + if (ctx->blend > 0.0001) { + return av_clipd((diff - ctx->similarity) / ctx->blend, 0.0, 1.0) * max; + } else { + return (diff > ctx->similarity) ? max : 0; + } +} + static av_always_inline void get_pixel_uv(AVFrame *frame, int hsub_log2, int vsub_log2, int x, int y, uint8_t *u, uint8_t *v) { if (x < 0 || x >= frame->width || y < 0 || y >= frame->height) @@ -76,6 +102,18 @@ *v = frame->data[2][frame->linesize[2] * y + x]; } +static av_always_inline void get_pixel16_uv(AVFrame *frame, int hsub_log2, int vsub_log2, int x, int y, uint16_t *u, uint16_t *v) +{ + if (x < 0 || x >= frame->width || y < 0 || y >= frame->height) + return; + + x >>= hsub_log2; + y >>= vsub_log2; + + *u = AV_RN16(&frame->data[1][frame->linesize[1] * y + 2 * x]); + *v = AV_RN16(&frame->data[2][frame->linesize[2] * y + 2 * x]); +} + static int do_chromakey_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) { AVFrame *frame = arg; @@ -106,6 +144,40 @@ return 0; } +static int do_chromakey16_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) +{ + AVFrame *frame = arg; + + const int slice_start = (frame->height * jobnr) / nb_jobs; + const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs; + + ChromakeyContext *ctx = avctx->priv; + + int x, y, xo, yo; + uint16_t u[9], v[9]; + + for (int i = 0; i < 9; i++) { + u[i] = ctx->chromakey_uv[0]; + v[i] = ctx->chromakey_uv[1]; + } + + for (y = slice_start; y < slice_end; ++y) { + for (x = 0; x < frame->width; ++x) { + uint16_t *dst = (uint16_t *)(frame->data[3] + frame->linesize[3] * y); + + for (yo = 0; yo < 3; ++yo) { + for (xo = 0; xo < 3; ++xo) { + get_pixel16_uv(frame, ctx->hsub_log2, ctx->vsub_log2, x + xo - 1, y + yo - 1, &u[yo * 3 + xo], &v[yo * 3 + xo]); + } + } + + dst[x] = do_chromakey_pixel16(ctx, u, v); + } + } + + return 0; +} + static int do_chromahold_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) { ChromakeyContext *ctx = avctx->priv; @@ -143,6 +215,45 @@ return 0; } +static int do_chromahold16_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) +{ + ChromakeyContext *ctx = avctx->priv; + AVFrame *frame = arg; + const int slice_start = ((frame->height >> ctx->vsub_log2) * jobnr) / nb_jobs; + const int slice_end = ((frame->height >> ctx->vsub_log2) * (jobnr + 1)) / nb_jobs; + const int mid = ctx->mid; + double max = ctx->max; + + int x, y, alpha; + + for (y = slice_start; y < slice_end; ++y) { + for (x = 0; x < frame->width >> ctx->hsub_log2; ++x) { + int u = AV_RN16(&frame->data[1][frame->linesize[1] * y + 2 * x]); + int v = AV_RN16(&frame->data[2][frame->linesize[2] * y + 2 * x]); + double diff; + int du, dv; + + du = u - ctx->chromakey_uv[0]; + dv = v - ctx->chromakey_uv[1]; + + diff = sqrt((du * du + dv * dv) / (max * max)); + + alpha = diff > ctx->similarity; + if (ctx->blend > 0.0001) { + double f = 1. - av_clipd((diff - ctx->similarity) / ctx->blend, 0.0, 1.0); + + AV_WN16(&frame->data[1][frame->linesize[1] * y + 2 * x], mid + (u - mid) * f); + AV_WN16(&frame->data[2][frame->linesize[2] * y + 2 * x], mid + (v - mid) * f); + } else if (alpha) { + AV_WN16(&frame->data[1][frame->linesize[1] * y + 2 * x], mid); + AV_WN16(&frame->data[2][frame->linesize[2] * y + 2 * x], mid); + } + } + } + + return 0; +} + static int filter_frame(AVFilterLink *link, AVFrame *frame) { AVFilterContext *avctx = link->dst; @@ -159,22 +270,31 @@ #define RGB_TO_U(rgb) (((- FIXNUM(0.16874) * rgb[0] - FIXNUM(0.33126) * rgb[1] + FIXNUM(0.50000) * rgb[2] + (1 << 9) - 1) >> 10) + 128) #define RGB_TO_V(rgb) ((( FIXNUM(0.50000) * rgb[0] - FIXNUM(0.41869) * rgb[1] - FIXNUM(0.08131) * rgb[2] + (1 << 9) - 1) >> 10) + 128) -static av_cold int initialize_chromakey(AVFilterContext *avctx) +static av_cold int config_output(AVFilterLink *outlink) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); + AVFilterContext *avctx = outlink->src; ChromakeyContext *ctx = avctx->priv; + int factor; + + ctx->depth = desc->comp[0].depth; + ctx->mid = 1 << (ctx->depth - 1); + ctx->max = (1 << ctx->depth) - 1; + + factor = 1 << (ctx->depth - 8); if (ctx->is_yuv) { - ctx->chromakey_uv[0] = ctx->chromakey_rgba[1]; - ctx->chromakey_uv[1] = ctx->chromakey_rgba[2]; + ctx->chromakey_uv[0] = ctx->chromakey_rgba[1] * factor; + ctx->chromakey_uv[1] = ctx->chromakey_rgba[2] * factor; } else { - ctx->chromakey_uv[0] = RGB_TO_U(ctx->chromakey_rgba); - ctx->chromakey_uv[1] = RGB_TO_V(ctx->chromakey_rgba); + ctx->chromakey_uv[0] = RGB_TO_U(ctx->chromakey_rgba) * factor; + ctx->chromakey_uv[1] = RGB_TO_V(ctx->chromakey_rgba) * factor; } if (!strcmp(avctx->filter->name, "chromakey")) { - ctx->do_slice = do_chromakey_slice; + ctx->do_slice = ctx->depth <= 8 ? do_chromakey_slice : do_chromakey16_slice; } else { - ctx->do_slice = do_chromahold_slice; + ctx->do_slice = ctx->depth <= 8 ? do_chromahold_slice: do_chromahold16_slice; } return 0; @@ -186,6 +306,10 @@ AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_NONE }; @@ -196,6 +320,15 @@ AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_NONE }; @@ -220,6 +353,18 @@ return 0; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_output(ctx->outputs[0]); +} + static const AVFilterPad chromakey_inputs[] = { { .name = "default", @@ -235,15 +380,16 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, }, { NULL } }; #define OFFSET(x) offsetof(ChromakeyContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption chromakey_options[] = { - { "color", "set the chromakey key color", OFFSET(chromakey_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "color", "set the chromakey key color", OFFSET(chromakey_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, 0, 0, FLAGS }, { "similarity", "set the chromakey similarity value", OFFSET(similarity), AV_OPT_TYPE_FLOAT, { .dbl = 0.01 }, 0.01, 1.0, FLAGS }, { "blend", "set the chromakey key blend value", OFFSET(blend), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, 0.0, 1.0, FLAGS }, { "yuv", "color parameter is in yuv instead of rgb", OFFSET(is_yuv), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, @@ -257,15 +403,15 @@ .description = NULL_IF_CONFIG_SMALL("Turns a certain color into transparency. Operates on YUV colors."), .priv_size = sizeof(ChromakeyContext), .priv_class = &chromakey_class, - .init = initialize_chromakey, .query_formats = query_formats, .inputs = chromakey_inputs, .outputs = chromakey_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; static const AVOption chromahold_options[] = { - { "color", "set the chromahold key color", OFFSET(chromakey_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "color", "set the chromahold key color", OFFSET(chromakey_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, 0, 0, FLAGS }, { "similarity", "set the chromahold similarity value", OFFSET(similarity), AV_OPT_TYPE_FLOAT, { .dbl = 0.01 }, 0.01, 1.0, FLAGS }, { "blend", "set the chromahold blend value", OFFSET(blend), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, 0.0, 1.0, FLAGS }, { "yuv", "color parameter is in yuv instead of rgb", OFFSET(is_yuv), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, @@ -287,6 +433,7 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, }, { NULL } }; @@ -298,9 +445,9 @@ .description = NULL_IF_CONFIG_SMALL("Turns a certain color range into gray."), .priv_size = sizeof(ChromakeyContext), .priv_class = &chromahold_class, - .init = initialize_chromakey, .query_formats = query_formats, .inputs = chromahold_inputs, .outputs = chromahold_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_chromanr.c ffmpeg-4.4/libavfilter/vf_chromanr.c --- ffmpeg-4.2.2/libavfilter/vf_chromanr.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_chromanr.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct ChromaNRContext { + const AVClass *class; + + float threshold; + float threshold_y; + float threshold_u; + float threshold_v; + int thres; + int thres_y; + int thres_u; + int thres_v; + int sizew; + int sizeh; + int stepw; + int steph; + int depth; + int chroma_w; + int chroma_h; + int nb_planes; + int linesize[4]; + int planeheight[4]; + int planewidth[4]; + + AVFrame *out; + int (*filter_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); +} ChromaNRContext; + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +#define FILTER_FUNC(name, type) \ +static int filter_slice##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ +{ \ + ChromaNRContext *s = ctx->priv; \ + AVFrame *in = arg; \ + AVFrame *out = s->out; \ + const int in_ylinesize = in->linesize[0]; \ + const int in_ulinesize = in->linesize[1]; \ + const int in_vlinesize = in->linesize[2]; \ + const int out_ulinesize = out->linesize[1]; \ + const int out_vlinesize = out->linesize[2]; \ + const int chroma_w = s->chroma_w; \ + const int chroma_h = s->chroma_h; \ + const int stepw = s->stepw; \ + const int steph = s->steph; \ + const int sizew = s->sizew; \ + const int sizeh = s->sizeh; \ + const int thres = s->thres; \ + const int thres_y = s->thres_y; \ + const int thres_u = s->thres_u; \ + const int thres_v = s->thres_v; \ + const int h = s->planeheight[1]; \ + const int w = s->planewidth[1]; \ + const int slice_start = (h * jobnr) / nb_jobs; \ + const int slice_end = (h * (jobnr+1)) / nb_jobs; \ + type *out_uptr = (type *)(out->data[1] + slice_start * out_ulinesize); \ + type *out_vptr = (type *)(out->data[2] + slice_start * out_vlinesize); \ + \ + { \ + const int h = s->planeheight[0]; \ + const int slice_start = (h * jobnr) / nb_jobs; \ + const int slice_end = (h * (jobnr+1)) / nb_jobs; \ + \ + av_image_copy_plane(out->data[0] + slice_start * out->linesize[0], \ + out->linesize[0], \ + in->data[0] + slice_start * in->linesize[0], \ + in->linesize[0], \ + s->linesize[0], slice_end - slice_start); \ + \ + if (s->nb_planes == 4) { \ + av_image_copy_plane(out->data[3] + slice_start * out->linesize[3], \ + out->linesize[3], \ + in->data[3] + slice_start * in->linesize[3], \ + in->linesize[3], \ + s->linesize[3], slice_end - slice_start); \ + } \ + } \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const type *in_yptr = (const type *)(in->data[0] + y * chroma_h * in_ylinesize); \ + const type *in_uptr = (const type *)(in->data[1] + y * in_ulinesize); \ + const type *in_vptr = (const type *)(in->data[2] + y * in_vlinesize); \ + \ + for (int x = 0; x < w; x++) { \ + const int cy = in_yptr[x * chroma_w]; \ + const int cu = in_uptr[x]; \ + const int cv = in_vptr[x]; \ + int su = cu; \ + int sv = cv; \ + int cn = 1; \ + \ + for (int yy = FFMAX(0, y - sizeh); yy < FFMIN(y + sizeh, h); 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) { \ + const int Y = in_yptr[xx * chroma_w]; \ + const int U = in_uptr[xx]; \ + const int V = in_vptr[xx]; \ + \ + if (FFABS(cu - U) + FFABS(cv - V) + FFABS(cy - Y) < thres && \ + FFABS(cu - U) < thres_u && FFABS(cv - V) < thres_v && \ + FFABS(cy - Y) < thres_y && \ + xx != x && yy != y) { \ + su += U; \ + sv += V; \ + cn++; \ + } \ + } \ + } \ + \ + out_uptr[x] = su / cn; \ + out_vptr[x] = sv / cn; \ + } \ + \ + out_uptr += out_ulinesize / sizeof(type); \ + out_vptr += out_vlinesize / sizeof(type); \ + } \ + \ + return 0; \ +} + +FILTER_FUNC(8, uint8_t) +FILTER_FUNC(16, uint16_t) + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + ChromaNRContext *s = ctx->priv; + AVFrame *out; + + s->thres = s->threshold * (1 << (s->depth - 8)); + s->thres_y = s->threshold_y * (1 << (s->depth - 8)); + s->thres_u = s->threshold_u * (1 << (s->depth - 8)); + s->thres_v = s->threshold_v * (1 << (s->depth - 8)); + + 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); + s->out = out; + ctx->internal->execute(ctx, s->filter_slice, in, NULL, + FFMIN3(s->planeheight[1], + s->planeheight[2], + ff_filter_get_nb_threads(ctx))); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ChromaNRContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int ret; + + s->nb_planes = desc->nb_components; + s->depth = desc->comp[0].depth; + s->filter_slice = s->depth <= 8 ? filter_slice8 : filter_slice16; + s->chroma_w = 1 << desc->log2_chroma_w; + s->chroma_h = 1 << desc->log2_chroma_h; + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + + if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + return ret; + + return 0; +} + +#define OFFSET(x) offsetof(ChromaNRContext, x) +#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, 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=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 }, + { NULL } +}; + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(chromanr); + +AVFilter ff_vf_chromanr = { + .name = "chromanr", + .description = NULL_IF_CONFIG_SMALL("Reduce chrominance noise."), + .priv_size = sizeof(ChromaNRContext), + .priv_class = &chromanr_class, + .query_formats = query_formats, + .outputs = outputs, + .inputs = inputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_chromashift.c ffmpeg-4.4/libavfilter/vf_chromashift.c --- ffmpeg-4.2.2/libavfilter/vf_chromashift.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_chromashift.c 2020-07-11 10:39:30.000000000 +0000 @@ -28,7 +28,6 @@ #include "avfilter.h" #include "formats.h" #include "internal.h" -#include "framesync.h" #include "video.h" typedef struct ChromaShiftContext { @@ -63,6 +62,7 @@ AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, @@ -400,17 +400,29 @@ return av_image_fill_linesizes(s->linesize, inlink->format, inlink->w); } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + #define OFFSET(x) offsetof(ChromaShiftContext, x) -#define VF AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +#define VFR AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption chromashift_options[] = { - { "cbh", "shift chroma-blue horizontally", OFFSET(cbh), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VF }, - { "cbv", "shift chroma-blue vertically", OFFSET(cbv), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VF }, - { "crh", "shift chroma-red horizontally", OFFSET(crh), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VF }, - { "crv", "shift chroma-red vertically", OFFSET(crv), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VF }, - { "edge", "set edge operation", OFFSET(edge), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = VF, "edge" }, - { "smear", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags = VF, "edge" }, - { "wrap", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags = VF, "edge" }, + { "cbh", "shift chroma-blue horizontally", OFFSET(cbh), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VFR }, + { "cbv", "shift chroma-blue vertically", OFFSET(cbv), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VFR }, + { "crh", "shift chroma-red horizontally", OFFSET(crh), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VFR }, + { "crv", "shift chroma-red vertically", OFFSET(crv), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VFR }, + { "edge", "set edge operation", OFFSET(edge), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = VFR, "edge" }, + { "smear", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags = VFR, "edge" }, + { "wrap", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags = VFR, "edge" }, { NULL }, }; @@ -443,20 +455,21 @@ .outputs = outputs, .inputs = inputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; static const AVOption rgbashift_options[] = { - { "rh", "shift red horizontally", OFFSET(rh), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VF }, - { "rv", "shift red vertically", OFFSET(rv), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VF }, - { "gh", "shift green horizontally", OFFSET(gh), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VF }, - { "gv", "shift green vertically", OFFSET(gv), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VF }, - { "bh", "shift blue horizontally", OFFSET(bh), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VF }, - { "bv", "shift blue vertically", OFFSET(bv), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VF }, - { "ah", "shift alpha horizontally", OFFSET(ah), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VF }, - { "av", "shift alpha vertically", OFFSET(av), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VF }, - { "edge", "set edge operation", OFFSET(edge), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = VF, "edge" }, - { "smear", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags = VF, "edge" }, - { "wrap", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags = VF, "edge" }, + { "rh", "shift red horizontally", OFFSET(rh), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VFR }, + { "rv", "shift red vertically", OFFSET(rv), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VFR }, + { "gh", "shift green horizontally", OFFSET(gh), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VFR }, + { "gv", "shift green vertically", OFFSET(gv), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VFR }, + { "bh", "shift blue horizontally", OFFSET(bh), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VFR }, + { "bv", "shift blue vertically", OFFSET(bv), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VFR }, + { "ah", "shift alpha horizontally", OFFSET(ah), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VFR }, + { "av", "shift alpha vertically", OFFSET(av), AV_OPT_TYPE_INT, {.i64=0}, -255, 255, .flags = VFR }, + { "edge", "set edge operation", OFFSET(edge), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = VFR, "edge" }, + { "smear", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags = VFR, "edge" }, + { "wrap", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags = VFR, "edge" }, { NULL }, }; @@ -471,4 +484,5 @@ .outputs = outputs, .inputs = inputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_ciescope.c ffmpeg-4.4/libavfilter/vf_ciescope.c --- ffmpeg-4.2.2/libavfilter/vf_ciescope.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_ciescope.c 2021-04-08 21:28:40.000000000 +0000 @@ -46,6 +46,7 @@ CIE1931system, Rec709system, Rec2020system, + DCIP3, NB_CS }; @@ -87,6 +88,7 @@ { "rec709", "ITU.BT-709 Y'CbCr", 0, AV_OPT_TYPE_CONST, {.i64=Rec709system}, 0, 0, FLAGS, "system" }, { "uhdtv", "ITU-R.BT-2020", 0, AV_OPT_TYPE_CONST, {.i64=Rec2020system}, 0, 0, FLAGS, "system" }, { "rec2020", "ITU-R.BT-2020", 0, AV_OPT_TYPE_CONST, {.i64=Rec2020system}, 0, 0, FLAGS, "system" }, + { "dcip3", "DCI-P3", 0, AV_OPT_TYPE_CONST, {.i64=DCIP3}, 0, 0, FLAGS, "system" }, { "cie", "set cie system", OFFSET(cie), AV_OPT_TYPE_INT, {.i64=XYY}, 0, NB_CIE-1, FLAGS, "cie" }, { "xyy", "CIE 1931 xyY", 0, AV_OPT_TYPE_CONST, {.i64=XYY}, 0, 0, FLAGS, "cie" }, { "ucs", "CIE 1960 UCS", 0, AV_OPT_TYPE_CONST, {.i64=UCS}, 0, 0, FLAGS, "cie" }, @@ -105,6 +107,7 @@ { "rec709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<inputs[0]->out_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), &ctx->inputs[0]->outcfg.formats)) < 0) return ret; - if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->incfg.formats)) < 0) return ret; return 0; @@ -694,6 +697,10 @@ 0.708, 0.292, 0.170, 0.797, 0.131, 0.046, D65, GAMMA_REC709 }, + [DCIP3] = { + 0.680, 0.320, 0.265, 0.690, 0.150, 0.060, + 0.314, 0.351, GAMMA_REC709 + }, }; /* @@ -1183,15 +1190,11 @@ if (cie == LUV) { double wup, wvp; xy_to_upvp(cs->xWhite, cs->yWhite, &wup, &wvp); - wx = wup; - wy = wvp; wx = (w - 1) * wup; wy = (h - 1) - ((int) ((h - 1) * wvp)); } else if (cie == UCS) { double wu, wv; xy_to_uv(cs->xWhite, cs->yWhite, &wu, &wv); - wx = wu; - wy = wv; wx = (w - 1) * wu; wy = (h - 1) - ((int) ((h - 1) * wv)); } else if (cie == XYY) { diff -Nru ffmpeg-4.2.2/libavfilter/vf_codecview.c ffmpeg-4.4/libavfilter/vf_codecview.c --- ffmpeg-4.2.2/libavfilter/vf_codecview.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_codecview.c 2021-04-08 21:28:40.000000000 +0000 @@ -33,6 +33,7 @@ #include "libavutil/motion_vector.h" #include "libavutil/opt.h" #include "avfilter.h" +#include "qp_table.h" #include "internal.h" #define MV_P_FOR (1<<0) @@ -140,7 +141,7 @@ } buf += sx + sy * stride; ex -= sx; - f = ((ey - sy) << 16) / ex; + f = ((ey - sy) * (1 << 16)) / ex; for (x = 0; x <= ex; x++) { y = (x * f) >> 16; fr = (x * f) & 0xFFFF; @@ -155,7 +156,7 @@ buf += sx + sy * stride; ey -= sy; if (ey) - f = ((ex - sx) << 16) / ey; + f = ((ex - sx) * (1 << 16)) / ey; else f = 0; for(y= 0; y <= ey; y++){ @@ -198,8 +199,8 @@ int length = sqrt((rx * rx + ry * ry) << 8); // FIXME subpixel accuracy - rx = ROUNDED_DIV(rx * 3 << 4, length); - ry = ROUNDED_DIV(ry * 3 << 4, length); + rx = ROUNDED_DIV(rx * (3 << 4), length); + ry = ROUNDED_DIV(ry * (3 << 4), length); if (tail) { rx = -rx; @@ -219,8 +220,14 @@ AVFilterLink *outlink = ctx->outputs[0]; if (s->qp) { - int qstride, qp_type; - int8_t *qp_table = av_frame_get_qp_table(frame, &qstride, &qp_type); + int qstride, qp_type, ret; + int8_t *qp_table; + + ret = ff_qp_table_extract(frame, &qp_table, &qstride, NULL, &qp_type); + if (ret < 0) { + av_frame_free(&frame); + return ret; + } if (qp_table) { int x, y; @@ -240,6 +247,7 @@ pv += lzv; } } + av_freep(&qp_table); } if (s->mv || s->mv_type) { diff -Nru ffmpeg-4.2.2/libavfilter/vf_colorbalance.c ffmpeg-4.4/libavfilter/vf_colorbalance.c --- ffmpeg-4.2.2/libavfilter/vf_colorbalance.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_colorbalance.c 2021-04-08 21:28:40.000000000 +0000 @@ -36,9 +36,9 @@ } ThreadData; typedef struct Range { - double shadows; - double midtones; - double highlights; + float shadows; + float midtones; + float highlights; } Range; typedef struct ColorBalanceContext { @@ -46,27 +46,29 @@ Range cyan_red; Range magenta_green; Range yellow_blue; - - uint16_t lut[3][65536]; + int preserve_lightness; uint8_t rgba_map[4]; + int depth; + int max; int step; - int (*apply_lut)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + int (*color_balance)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } ColorBalanceContext; #define OFFSET(x) offsetof(ColorBalanceContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption colorbalance_options[] = { - { "rs", "set red shadows", OFFSET(cyan_red.shadows), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS }, - { "gs", "set green shadows", OFFSET(magenta_green.shadows), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS }, - { "bs", "set blue shadows", OFFSET(yellow_blue.shadows), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS }, - { "rm", "set red midtones", OFFSET(cyan_red.midtones), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS }, - { "gm", "set green midtones", OFFSET(magenta_green.midtones), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS }, - { "bm", "set blue midtones", OFFSET(yellow_blue.midtones), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS }, - { "rh", "set red highlights", OFFSET(cyan_red.highlights), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS }, - { "gh", "set green highlights", OFFSET(magenta_green.highlights), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS }, - { "bh", "set blue highlights", OFFSET(yellow_blue.highlights), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS }, + { "rs", "set red shadows", OFFSET(cyan_red.shadows), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS }, + { "gs", "set green shadows", OFFSET(magenta_green.shadows), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS }, + { "bs", "set blue shadows", OFFSET(yellow_blue.shadows), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS }, + { "rm", "set red midtones", OFFSET(cyan_red.midtones), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS }, + { "gm", "set green midtones", OFFSET(magenta_green.midtones), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS }, + { "bm", "set blue midtones", OFFSET(yellow_blue.midtones), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS }, + { "rh", "set red highlights", OFFSET(cyan_red.highlights), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS }, + { "gh", "set green highlights", OFFSET(magenta_green.highlights), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS }, + { "bh", "set blue highlights", OFFSET(yellow_blue.highlights), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS }, + { "pl", "preserve lightness", OFFSET(preserve_lightness), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { NULL } }; @@ -96,7 +98,64 @@ return ff_set_common_formats(ctx, fmts_list); } -static int apply_lut8_p(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +static float get_component(float v, float l, + float s, float m, float h) +{ + const float a = 4.f, b = 0.333f, scale = 0.7f; + + s *= av_clipf((b - l) * a + 0.5f, 0, 1) * scale; + m *= av_clipf((l - b) * a + 0.5f, 0, 1) * av_clipf((1.0 - l - b) * a + 0.5f, 0, 1) * scale; + h *= av_clipf((l + b - 1) * a + 0.5f, 0, 1) * scale; + + v += s; + v += m; + v += h; + + return av_clipf(v, 0, 1); +} + +static float hfun(float n, float h, float s, float l) +{ + float a = s * FFMIN(l, 1. - l); + float k = fmodf(n + h / 30.f, 12.f); + + return av_clipf(l - a * FFMAX(FFMIN3(k - 3.f, 9.f - k, 1), -1.f), 0, 1); +} + +static void preservel(float *r, float *g, float *b, float l) +{ + float max = FFMAX3(*r, *g, *b); + float min = FFMIN3(*r, *g, *b); + float h, s; + + l *= 0.5; + + if (*r == *g && *g == *b) { + h = 0.; + } else if (max == *r) { + h = 60. * (0. + (*g - *b) / (max - min)); + } else if (max == *g) { + h = 60. * (2. + (*b - *r) / (max - min)); + } else if (max == *b) { + h = 60. * (4. + (*r - *g) / (max - min)); + } else { + h = 0.; + } + if (h < 0.) + h += 360.; + + if (max == 0. || min == 1.) { + s = 0.; + } else { + s = (max - min) / (1. - FFABS(2. * l - 1)); + } + + *r = hfun(0, h, s, l); + *g = hfun(8, h, s, l); + *b = hfun(4, h, s, l); +} + +static int color_balance8_p(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ColorBalanceContext *s = ctx->priv; ThreadData *td = arg; @@ -112,13 +171,26 @@ uint8_t *dstb = out->data[1] + slice_start * out->linesize[1]; uint8_t *dstr = out->data[2] + slice_start * out->linesize[2]; uint8_t *dsta = out->data[3] + slice_start * out->linesize[3]; + const float max = s->max; int i, j; for (i = slice_start; i < slice_end; i++) { for (j = 0; j < out->width; j++) { - dstg[j] = s->lut[G][srcg[j]]; - dstb[j] = s->lut[B][srcb[j]]; - dstr[j] = s->lut[R][srcr[j]]; + float r = srcr[j] / max; + float g = srcg[j] / max; + float b = srcb[j] / max; + const float l = FFMAX3(r, g, b) + FFMIN3(r, g, b); + + r = get_component(r, l, s->cyan_red.shadows, s->cyan_red.midtones, s->cyan_red.highlights); + g = get_component(g, l, s->magenta_green.shadows, s->magenta_green.midtones, s->magenta_green.highlights); + b = get_component(b, l, s->yellow_blue.shadows, s->yellow_blue.midtones, s->yellow_blue.highlights); + + if (s->preserve_lightness) + preservel(&r, &g, &b, l); + + dstr[j] = av_clip_uint8(lrintf(r * max)); + dstg[j] = av_clip_uint8(lrintf(g * max)); + dstb[j] = av_clip_uint8(lrintf(b * max)); if (in != out && out->linesize[3]) dsta[j] = srca[j]; } @@ -136,7 +208,7 @@ return 0; } -static int apply_lut16_p(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +static int color_balance16_p(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ColorBalanceContext *s = ctx->priv; ThreadData *td = arg; @@ -152,13 +224,27 @@ uint16_t *dstb = (uint16_t *)out->data[1] + slice_start * out->linesize[1] / 2; uint16_t *dstr = (uint16_t *)out->data[2] + slice_start * out->linesize[2] / 2; uint16_t *dsta = (uint16_t *)out->data[3] + slice_start * out->linesize[3] / 2; + const int depth = s->depth; + const float max = s->max; int i, j; for (i = slice_start; i < slice_end; i++) { for (j = 0; j < out->width; j++) { - dstg[j] = s->lut[G][srcg[j]]; - dstb[j] = s->lut[B][srcb[j]]; - dstr[j] = s->lut[R][srcr[j]]; + float r = srcr[j] / max; + float g = srcg[j] / max; + float b = srcb[j] / max; + const float l = (FFMAX3(r, g, b) + FFMIN3(r, g, b)); + + r = get_component(r, l, s->cyan_red.shadows, s->cyan_red.midtones, s->cyan_red.highlights); + g = get_component(g, l, s->magenta_green.shadows, s->magenta_green.midtones, s->magenta_green.highlights); + b = get_component(b, l, s->yellow_blue.shadows, s->yellow_blue.midtones, s->yellow_blue.highlights); + + if (s->preserve_lightness) + preservel(&r, &g, &b, l); + + dstr[j] = av_clip_uintp2_c(lrintf(r * max), depth); + dstg[j] = av_clip_uintp2_c(lrintf(g * max), depth); + dstb[j] = av_clip_uintp2_c(lrintf(b * max), depth); if (in != out && out->linesize[3]) dsta[j] = srca[j]; } @@ -176,7 +262,7 @@ return 0; } -static int apply_lut8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +static int color_balance8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ColorBalanceContext *s = ctx->priv; ThreadData *td = arg; @@ -190,6 +276,7 @@ const uint8_t goffset = s->rgba_map[G]; const uint8_t boffset = s->rgba_map[B]; const uint8_t aoffset = s->rgba_map[A]; + const float max = s->max; const int step = s->step; uint8_t *dstrow; int i, j; @@ -200,9 +287,21 @@ uint8_t *dst = dstrow; for (j = 0; j < outlink->w * step; j += step) { - dst[j + roffset] = s->lut[R][src[j + roffset]]; - dst[j + goffset] = s->lut[G][src[j + goffset]]; - dst[j + boffset] = s->lut[B][src[j + boffset]]; + float r = src[j + roffset] / max; + float g = src[j + goffset] / max; + float b = src[j + boffset] / max; + const float l = (FFMAX3(r, g, b) + FFMIN3(r, g, b)); + + r = get_component(r, l, s->cyan_red.shadows, s->cyan_red.midtones, s->cyan_red.highlights); + g = get_component(g, l, s->magenta_green.shadows, s->magenta_green.midtones, s->magenta_green.highlights); + b = get_component(b, l, s->yellow_blue.shadows, s->yellow_blue.midtones, s->yellow_blue.highlights); + + if (s->preserve_lightness) + preservel(&r, &g, &b, l); + + dst[j + roffset] = av_clip_uint8(lrintf(r * max)); + dst[j + goffset] = av_clip_uint8(lrintf(g * max)); + dst[j + boffset] = av_clip_uint8(lrintf(b * max)); if (in != out && step == 4) dst[j + aoffset] = src[j + aoffset]; } @@ -214,7 +313,7 @@ return 0; } -static int apply_lut16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +static int color_balance16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { ColorBalanceContext *s = ctx->priv; ThreadData *td = arg; @@ -229,6 +328,8 @@ const uint8_t boffset = s->rgba_map[B]; const uint8_t aoffset = s->rgba_map[A]; const int step = s->step / 2; + const int depth = s->depth; + const float max = s->max; uint16_t *dstrow; int i, j; @@ -238,9 +339,21 @@ uint16_t *dst = dstrow; for (j = 0; j < outlink->w * step; j += step) { - dst[j + roffset] = s->lut[R][src[j + roffset]]; - dst[j + goffset] = s->lut[G][src[j + goffset]]; - dst[j + boffset] = s->lut[B][src[j + boffset]]; + float r = src[j + roffset] / max; + float g = src[j + goffset] / max; + float b = src[j + boffset] / max; + const float l = (FFMAX3(r, g, b) + FFMIN3(r, g, b)); + + r = get_component(r, l, s->cyan_red.shadows, s->cyan_red.midtones, s->cyan_red.highlights); + g = get_component(g, l, s->magenta_green.shadows, s->magenta_green.midtones, s->magenta_green.highlights); + b = get_component(b, l, s->yellow_blue.shadows, s->yellow_blue.midtones, s->yellow_blue.highlights); + + if (s->preserve_lightness) + preservel(&r, &g, &b, l); + + dst[j + roffset] = av_clip_uintp2_c(lrintf(r * max), depth); + dst[j + goffset] = av_clip_uintp2_c(lrintf(g * max), depth); + dst[j + boffset] = av_clip_uintp2_c(lrintf(b * max), depth); if (in != out && step == 4) dst[j + aoffset] = src[j + aoffset]; } @@ -258,64 +371,22 @@ ColorBalanceContext *s = ctx->priv; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); const int depth = desc->comp[0].depth; - const int max = 1 << depth; + const int max = (1 << depth) - 1; const int planar = av_pix_fmt_count_planes(outlink->format) > 1; - double *shadows, *midtones, *highlights, *buffer; - int i, r, g, b; - if (max == 256 && planar) { - s->apply_lut = apply_lut8_p; + s->depth = depth; + s->max = max; + + if (max == 255 && planar) { + s->color_balance = color_balance8_p; } else if (planar) { - s->apply_lut = apply_lut16_p; - } else if (max == 256) { - s->apply_lut = apply_lut8; + s->color_balance = color_balance16_p; + } else if (max == 255) { + s->color_balance = color_balance8; } else { - s->apply_lut = apply_lut16; - } - - buffer = av_malloc(max * 3 * sizeof(*buffer)); - if (!buffer) - return AVERROR(ENOMEM); - - shadows = buffer + max * 0; - midtones = buffer + max * 1; - highlights = buffer + max * 2; - - for (i = 0; i < max; i++) { - const double L = 0.333 * (max - 1); - const double M = 0.7 * (max - 1); - const double H = 1 * (max - 1); - double low = av_clipd((i - L) / (-max * 0.25) + 0.5, 0, 1) * M; - double mid = av_clipd((i - L) / ( max * 0.25) + 0.5, 0, 1) * - av_clipd((i + L - H) / (-max * 0.25) + 0.5, 0, 1) * M; - - shadows[i] = low; - midtones[i] = mid; - highlights[max - i - 1] = low; + s->color_balance = color_balance16; } - for (i = 0; i < max; i++) { - r = g = b = i; - - r = av_clip_uintp2_c(r + s->cyan_red.shadows * shadows[r], depth); - r = av_clip_uintp2_c(r + s->cyan_red.midtones * midtones[r], depth); - r = av_clip_uintp2_c(r + s->cyan_red.highlights * highlights[r], depth); - - g = av_clip_uintp2_c(g + s->magenta_green.shadows * shadows[g], depth); - g = av_clip_uintp2_c(g + s->magenta_green.midtones * midtones[g], depth); - g = av_clip_uintp2_c(g + s->magenta_green.highlights * highlights[g], depth); - - b = av_clip_uintp2_c(b + s->yellow_blue.shadows * shadows[b], depth); - b = av_clip_uintp2_c(b + s->yellow_blue.midtones * midtones[b], depth); - b = av_clip_uintp2_c(b + s->yellow_blue.highlights * highlights[b], depth); - - s->lut[R][i] = r; - s->lut[G][i] = g; - s->lut[B][i] = b; - } - - av_free(buffer); - ff_fill_rgba_map(s->rgba_map, outlink->format); s->step = av_get_padded_bits_per_pixel(desc) >> 3; @@ -343,7 +414,7 @@ td.in = in; td.out = out; - ctx->internal->execute(ctx, s->apply_lut, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); + ctx->internal->execute(ctx, s->color_balance, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); if (in != out) av_frame_free(&in); @@ -377,4 +448,5 @@ .inputs = colorbalance_inputs, .outputs = colorbalance_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_colorchannelmixer.c ffmpeg-4.4/libavfilter/vf_colorchannelmixer.c --- ffmpeg-4.2.2/libavfilter/vf_colorchannelmixer.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_colorchannelmixer.c 2021-04-08 21:28:40.000000000 +0000 @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avfilter.h" @@ -41,6 +43,8 @@ double gr, gg, gb, ga; double br, bg, bb, ba; double ar, ag, ab, aa; + double sr, sg, sb; + double preserve_lightness; int *lut[4][4]; @@ -48,11 +52,12 @@ uint8_t rgba_map[4]; - int (*filter_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + int (*filter_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } ColorChannelMixerContext; #define OFFSET(x) offsetof(ColorChannelMixerContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + static const AVOption colorchannelmixer_options[] = { { "rr", "set the red gain for the red channel", OFFSET(rr), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS }, { "rg", "set the green gain for the red channel", OFFSET(rg), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS }, @@ -70,6 +75,7 @@ { "ag", "set the green gain for the alpha channel", OFFSET(ag), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS }, { "ab", "set the blue gain for the alpha channel", OFFSET(ab), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -2, 2, FLAGS }, { "aa", "set the alpha gain for the alpha channel", OFFSET(aa), AV_OPT_TYPE_DOUBLE, {.dbl=1}, -2, 2, FLAGS }, + { "pl", "preserve lightness", OFFSET(preserve_lightness), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 1, FLAGS }, { NULL } }; @@ -100,13 +106,29 @@ return ff_set_common_formats(ctx, fmts_list); } +static float lerpf(float v0, float v1, float f) +{ + return v0 + (v1 - v0) * f; +} + +static void preservel(float *r, float *g, float *b, float lin, float lout) +{ + *r *= lout / lin; + *g *= lout / lin; + *b *= lout / lin; +} + static av_always_inline int filter_slice_rgba_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, - int have_alpha) + int have_alpha, int pl) { ColorChannelMixerContext *s = ctx->priv; ThreadData *td = arg; AVFrame *in = td->in; AVFrame *out = td->out; + const float l = s->preserve_lightness; + const float sr = s->sr; + const float sg = s->sg; + const float sb = s->sb; const int slice_start = (out->height * jobnr) / nb_jobs; const int slice_end = (out->height * (jobnr+1)) / nb_jobs; const uint8_t *srcg = in->data[0] + slice_start * in->linesize[0]; @@ -124,20 +146,43 @@ const uint8_t rin = srcr[j]; const uint8_t gin = srcg[j]; const uint8_t bin = srcb[j]; - const uint8_t ain = srca[j]; + const uint8_t ain = have_alpha ? srca[j] : 0; + int rout, gout, bout; + float lin; + + if (pl) + lin = FFMAX3(rin, gin, bin) + FFMIN3(rin, gin, bin); + + rout = s->lut[R][R][rin] + + s->lut[R][G][gin] + + s->lut[R][B][bin] + + (have_alpha == 1 ? s->lut[R][A][ain] : 0); + gout = s->lut[G][R][rin] + + s->lut[G][G][gin] + + s->lut[G][B][bin] + + (have_alpha == 1 ? s->lut[G][A][ain] : 0); + bout = s->lut[B][R][rin] + + s->lut[B][G][gin] + + s->lut[B][B][bin] + + (have_alpha == 1 ? s->lut[B][A][ain] : 0); + + if (pl) { + float frout = rout / sr; + float fgout = gout / sg; + float fbout = bout / sb; + float lout = FFMAX3(frout, fgout, fbout) + FFMIN3(frout, fgout, fbout); + + preservel(&frout, &fgout, &fbout, lin, lout); + + rout = lrintf(lerpf(rout, frout, l)); + gout = lrintf(lerpf(gout, fgout, l)); + bout = lrintf(lerpf(bout, fbout, l)); + } + + dstr[j] = av_clip_uint8(rout); + dstg[j] = av_clip_uint8(gout); + dstb[j] = av_clip_uint8(bout); - dstr[j] = av_clip_uint8(s->lut[R][R][rin] + - s->lut[R][G][gin] + - s->lut[R][B][bin] + - (have_alpha == 1 ? s->lut[R][A][ain] : 0)); - dstg[j] = av_clip_uint8(s->lut[G][R][rin] + - s->lut[G][G][gin] + - s->lut[G][B][bin] + - (have_alpha == 1 ? s->lut[G][A][ain] : 0)); - dstb[j] = av_clip_uint8(s->lut[B][R][rin] + - s->lut[B][G][gin] + - s->lut[B][B][bin] + - (have_alpha == 1 ? s->lut[B][A][ain] : 0)); if (have_alpha == 1) { dsta[j] = av_clip_uint8(s->lut[A][R][rin] + s->lut[A][G][gin] + @@ -160,12 +205,16 @@ } static av_always_inline int filter_slice_rgba16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, - int have_alpha, int depth) + int have_alpha, int depth, int pl) { ColorChannelMixerContext *s = ctx->priv; ThreadData *td = arg; AVFrame *in = td->in; AVFrame *out = td->out; + const float l = s->preserve_lightness; + const float sr = s->sr; + const float sg = s->sg; + const float sb = s->sb; const int slice_start = (out->height * jobnr) / nb_jobs; const int slice_end = (out->height * (jobnr+1)) / nb_jobs; const uint16_t *srcg = (const uint16_t *)(in->data[0] + slice_start * in->linesize[0]); @@ -183,20 +232,43 @@ const uint16_t rin = srcr[j]; const uint16_t gin = srcg[j]; const uint16_t bin = srcb[j]; - const uint16_t ain = srca[j]; + const uint16_t ain = have_alpha ? srca[j] : 0; + int rout, gout, bout; + float lin; + + if (pl) + lin = FFMAX3(rin, gin, bin) + FFMIN3(rin, gin, bin); + + rout = s->lut[R][R][rin] + + s->lut[R][G][gin] + + s->lut[R][B][bin] + + (have_alpha == 1 ? s->lut[R][A][ain] : 0); + gout = s->lut[G][R][rin] + + s->lut[G][G][gin] + + s->lut[G][B][bin] + + (have_alpha == 1 ? s->lut[G][A][ain] : 0); + bout = s->lut[B][R][rin] + + s->lut[B][G][gin] + + s->lut[B][B][bin] + + (have_alpha == 1 ? s->lut[B][A][ain] : 0); + + if (pl) { + float frout = rout / sr; + float fgout = gout / sg; + float fbout = bout / sb; + float lout = FFMAX3(frout, fgout, fbout) + FFMIN3(frout, fgout, fbout); + + preservel(&frout, &fgout, &fbout, lin, lout); + + rout = lrintf(lerpf(rout, frout, l)); + gout = lrintf(lerpf(gout, fgout, l)); + bout = lrintf(lerpf(bout, fbout, l)); + } + + dstr[j] = av_clip_uintp2(rout, depth); + dstg[j] = av_clip_uintp2(gout, depth); + dstb[j] = av_clip_uintp2(bout, depth); - dstr[j] = av_clip_uintp2(s->lut[R][R][rin] + - s->lut[R][G][gin] + - s->lut[R][B][bin] + - (have_alpha == 1 ? s->lut[R][A][ain] : 0), depth); - dstg[j] = av_clip_uintp2(s->lut[G][R][rin] + - s->lut[G][G][gin] + - s->lut[G][B][bin] + - (have_alpha == 1 ? s->lut[G][A][ain] : 0), depth); - dstb[j] = av_clip_uintp2(s->lut[B][R][rin] + - s->lut[B][G][gin] + - s->lut[B][B][bin] + - (have_alpha == 1 ? s->lut[B][A][ain] : 0), depth); if (have_alpha == 1) { dsta[j] = av_clip_uintp2(s->lut[A][R][rin] + s->lut[A][G][gin] + @@ -220,61 +292,115 @@ static int filter_slice_gbrp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 0); + return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 0, 0); } static int filter_slice_gbrap(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 1); + return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 1, 0); +} + +static int filter_slice_gbrp_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 0, 1); +} + +static int filter_slice_gbrap_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 1, 1); } static int filter_slice_gbrp9(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 9); + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 9, 0); } static int filter_slice_gbrp10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 10); + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 10, 0); } static int filter_slice_gbrap10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 10); + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 10, 0); } static int filter_slice_gbrp12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 12); + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 12, 0); } static int filter_slice_gbrap12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 12); + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 12, 0); } static int filter_slice_gbrp14(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 14); + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 14, 0); } static int filter_slice_gbrp16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 16); + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 16, 0); } static int filter_slice_gbrap16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 16); + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 16, 0); +} + +static int filter_slice_gbrp9_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 9, 1); +} + +static int filter_slice_gbrp10_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 10, 1); +} + +static int filter_slice_gbrap10_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 10, 1); +} + +static int filter_slice_gbrp12_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 12, 1); +} + +static int filter_slice_gbrap12_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 12, 1); +} + +static int filter_slice_gbrp14_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 14, 1); +} + +static int filter_slice_gbrp16_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 16, 1); +} + +static int filter_slice_gbrap16_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 16, 1); } static av_always_inline int filter_slice_rgba_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, - int have_alpha, int step) + int have_alpha, int step, int pl) { ColorChannelMixerContext *s = ctx->priv; ThreadData *td = arg; AVFrame *in = td->in; AVFrame *out = td->out; + const float l = s->preserve_lightness; + const float sr = s->sr; + const float sg = s->sg; + const float sb = s->sb; const int slice_start = (out->height * jobnr) / nb_jobs; const int slice_end = (out->height * (jobnr+1)) / nb_jobs; const uint8_t roffset = s->rgba_map[R]; @@ -294,19 +420,42 @@ const uint8_t gin = src[j + goffset]; const uint8_t bin = src[j + boffset]; const uint8_t ain = src[j + aoffset]; + int rout, gout, bout; + float lin; + + if (pl) + lin = FFMAX3(rin, gin, bin) + FFMIN3(rin, gin, bin); + + rout = s->lut[R][R][rin] + + s->lut[R][G][gin] + + s->lut[R][B][bin] + + (have_alpha == 1 ? s->lut[R][A][ain] : 0); + gout = s->lut[G][R][rin] + + s->lut[G][G][gin] + + s->lut[G][B][bin] + + (have_alpha == 1 ? s->lut[G][A][ain] : 0); + bout = s->lut[B][R][rin] + + s->lut[B][G][gin] + + s->lut[B][B][bin] + + (have_alpha == 1 ? s->lut[B][A][ain] : 0); + + if (pl) { + float frout = rout / sr; + float fgout = gout / sg; + float fbout = bout / sb; + float lout = FFMAX3(frout, fgout, fbout) + FFMIN3(frout, fgout, fbout); + + preservel(&frout, &fgout, &fbout, lin, lout); + + rout = lrintf(lerpf(rout, frout, l)); + gout = lrintf(lerpf(gout, fgout, l)); + bout = lrintf(lerpf(bout, fbout, l)); + } + + dst[j + roffset] = av_clip_uint8(rout); + dst[j + goffset] = av_clip_uint8(gout); + dst[j + boffset] = av_clip_uint8(bout); - dst[j + roffset] = av_clip_uint8(s->lut[R][R][rin] + - s->lut[R][G][gin] + - s->lut[R][B][bin] + - (have_alpha == 1 ? s->lut[R][A][ain] : 0)); - dst[j + goffset] = av_clip_uint8(s->lut[G][R][rin] + - s->lut[G][G][gin] + - s->lut[G][B][bin] + - (have_alpha == 1 ? s->lut[G][A][ain] : 0)); - dst[j + boffset] = av_clip_uint8(s->lut[B][R][rin] + - s->lut[B][G][gin] + - s->lut[B][B][bin] + - (have_alpha == 1 ? s->lut[B][A][ain] : 0)); if (have_alpha == 1) { dst[j + aoffset] = av_clip_uint8(s->lut[A][R][rin] + s->lut[A][G][gin] + @@ -324,12 +473,16 @@ } static av_always_inline int filter_slice_rgba16_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, - int have_alpha, int step) + int have_alpha, int step, int pl) { ColorChannelMixerContext *s = ctx->priv; ThreadData *td = arg; AVFrame *in = td->in; AVFrame *out = td->out; + const float l = s->preserve_lightness; + const float sr = s->sr; + const float sg = s->sg; + const float sb = s->sb; const int slice_start = (out->height * jobnr) / nb_jobs; const int slice_end = (out->height * (jobnr+1)) / nb_jobs; const uint8_t roffset = s->rgba_map[R]; @@ -349,19 +502,42 @@ const uint16_t gin = src[j + goffset]; const uint16_t bin = src[j + boffset]; const uint16_t ain = src[j + aoffset]; + int rout, gout, bout; + float lin; + + if (pl) + lin = FFMAX3(rin, gin, bin) + FFMIN3(rin, gin, bin); + + rout = s->lut[R][R][rin] + + s->lut[R][G][gin] + + s->lut[R][B][bin] + + (have_alpha == 1 ? s->lut[R][A][ain] : 0); + gout = s->lut[G][R][rin] + + s->lut[G][G][gin] + + s->lut[G][B][bin] + + (have_alpha == 1 ? s->lut[G][A][ain] : 0); + bout = s->lut[B][R][rin] + + s->lut[B][G][gin] + + s->lut[B][B][bin] + + (have_alpha == 1 ? s->lut[B][A][ain] : 0); + + if (pl) { + float frout = rout / sr; + float fgout = gout / sg; + float fbout = bout / sb; + float lout = FFMAX3(frout, fgout, fbout) + FFMIN3(frout, fgout, fbout); + + preservel(&frout, &fgout, &fbout, lin, lout); + + rout = lrintf(lerpf(rout, frout, l)); + gout = lrintf(lerpf(gout, fgout, l)); + bout = lrintf(lerpf(bout, fbout, l)); + } + + dst[j + roffset] = av_clip_uint16(rout); + dst[j + goffset] = av_clip_uint16(gout); + dst[j + boffset] = av_clip_uint16(bout); - dst[j + roffset] = av_clip_uint16(s->lut[R][R][rin] + - s->lut[R][G][gin] + - s->lut[R][B][bin] + - (have_alpha == 1 ? s->lut[R][A][ain] : 0)); - dst[j + goffset] = av_clip_uint16(s->lut[G][R][rin] + - s->lut[G][G][gin] + - s->lut[G][B][bin] + - (have_alpha == 1 ? s->lut[G][A][ain] : 0)); - dst[j + boffset] = av_clip_uint16(s->lut[B][R][rin] + - s->lut[B][G][gin] + - s->lut[B][B][bin] + - (have_alpha == 1 ? s->lut[B][A][ain] : 0)); if (have_alpha == 1) { dst[j + aoffset] = av_clip_uint16(s->lut[A][R][rin] + s->lut[A][G][gin] + @@ -379,27 +555,52 @@ static int filter_slice_rgba64(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 1, 4); + return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 0); } static int filter_slice_rgb48(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 0, 3); + return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 0); +} + +static int filter_slice_rgba64_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 1); +} + +static int filter_slice_rgb48_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 1); } static int filter_slice_rgba(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 1, 4); + return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 0); } static int filter_slice_rgb24(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 0, 3); + return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 0); } static int filter_slice_rgb0(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, -1, 4); + return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, -1, 4, 0); +} + +static int filter_slice_rgba_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 1); +} + +static int filter_slice_rgb24_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 1); +} + +static int filter_slice_rgb0_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, -1, 4, 1); } static int config_output(AVFilterLink *outlink) @@ -408,18 +609,33 @@ ColorChannelMixerContext *s = ctx->priv; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); const int depth = desc->comp[0].depth; - int i, j, size, *buffer; + int i, j, size, *buffer = s->buffer; ff_fill_rgba_map(s->rgba_map, outlink->format); size = 1 << depth; - s->buffer = buffer = av_malloc(16 * size * sizeof(*s->buffer)); - if (!s->buffer) - return AVERROR(ENOMEM); + if (!s->buffer) { + s->buffer = buffer = av_malloc(16 * size * sizeof(*s->buffer)); + if (!s->buffer) + return AVERROR(ENOMEM); - for (i = 0; i < 4; i++) - for (j = 0; j < 4; j++, buffer += size) - s->lut[i][j] = buffer; + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++, buffer += size) + s->lut[i][j] = buffer; + } + + s->sr = s->rr + s->rg + s->rb + s->ra; + s->sg = s->gr + s->gg + s->gb + s->ga; + s->sb = s->br + s->bg + s->bb + s->ba; + + if (fabs(s->sr) <= DBL_EPSILON) + s->sr = 1.; + + if (fabs(s->sg) <= DBL_EPSILON) + s->sg = 1.; + + if (fabs(s->sb) <= DBL_EPSILON) + s->sb = 1.; for (i = 0; i < size; i++) { s->lut[R][R][i] = lrint(i * s->rr); @@ -446,57 +662,72 @@ switch (outlink->format) { case AV_PIX_FMT_BGR24: case AV_PIX_FMT_RGB24: - s->filter_slice = filter_slice_rgb24; + s->filter_slice[0] = filter_slice_rgb24; + s->filter_slice[1] = filter_slice_rgb24_pl; break; case AV_PIX_FMT_0BGR: case AV_PIX_FMT_0RGB: case AV_PIX_FMT_BGR0: case AV_PIX_FMT_RGB0: - s->filter_slice = filter_slice_rgb0; + s->filter_slice[0] = filter_slice_rgb0; + s->filter_slice[1] = filter_slice_rgb0_pl; break; case AV_PIX_FMT_ABGR: case AV_PIX_FMT_ARGB: case AV_PIX_FMT_BGRA: case AV_PIX_FMT_RGBA: - s->filter_slice = filter_slice_rgba; + s->filter_slice[0] = filter_slice_rgba; + s->filter_slice[1] = filter_slice_rgba_pl; break; case AV_PIX_FMT_BGR48: case AV_PIX_FMT_RGB48: - s->filter_slice = filter_slice_rgb48; + s->filter_slice[0] = filter_slice_rgb48; + s->filter_slice[1] = filter_slice_rgb48_pl; break; case AV_PIX_FMT_BGRA64: case AV_PIX_FMT_RGBA64: - s->filter_slice = filter_slice_rgba64; + s->filter_slice[0] = filter_slice_rgba64; + s->filter_slice[1] = filter_slice_rgba64_pl; break; case AV_PIX_FMT_GBRP: - s->filter_slice = filter_slice_gbrp; + s->filter_slice[0] = filter_slice_gbrp; + s->filter_slice[1] = filter_slice_gbrp_pl; break; case AV_PIX_FMT_GBRAP: - s->filter_slice = filter_slice_gbrap; + s->filter_slice[0] = filter_slice_gbrap; + s->filter_slice[1] = filter_slice_gbrap_pl; break; case AV_PIX_FMT_GBRP9: - s->filter_slice = filter_slice_gbrp9; + s->filter_slice[0] = filter_slice_gbrp9; + s->filter_slice[1] = filter_slice_gbrp9_pl; break; case AV_PIX_FMT_GBRP10: - s->filter_slice = filter_slice_gbrp10; + s->filter_slice[0] = filter_slice_gbrp10; + s->filter_slice[1] = filter_slice_gbrp10_pl; break; case AV_PIX_FMT_GBRAP10: - s->filter_slice = filter_slice_gbrap10; + s->filter_slice[0] = filter_slice_gbrap10; + s->filter_slice[1] = filter_slice_gbrap10_pl; break; case AV_PIX_FMT_GBRP12: - s->filter_slice = filter_slice_gbrp12; + s->filter_slice[0] = filter_slice_gbrp12; + s->filter_slice[1] = filter_slice_gbrp12_pl; break; case AV_PIX_FMT_GBRAP12: - s->filter_slice = filter_slice_gbrap12; + s->filter_slice[0] = filter_slice_gbrap12; + s->filter_slice[1] = filter_slice_gbrap12_pl; break; case AV_PIX_FMT_GBRP14: - s->filter_slice = filter_slice_gbrp14; + s->filter_slice[0] = filter_slice_gbrp14; + s->filter_slice[1] = filter_slice_gbrp14_pl; break; case AV_PIX_FMT_GBRP16: - s->filter_slice = filter_slice_gbrp16; + s->filter_slice[0] = filter_slice_gbrp16; + s->filter_slice[1] = filter_slice_gbrp16_pl; break; case AV_PIX_FMT_GBRAP16: - s->filter_slice = filter_slice_gbrap16; + s->filter_slice[0] = filter_slice_gbrap16; + s->filter_slice[1] = filter_slice_gbrap16_pl; break; } @@ -508,6 +739,7 @@ AVFilterContext *ctx = inlink->dst; ColorChannelMixerContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + const int pl = s->preserve_lightness > 0.; ThreadData td; AVFrame *out; @@ -524,13 +756,24 @@ td.in = in; td.out = out; - ctx->internal->execute(ctx, s->filter_slice, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); + ctx->internal->execute(ctx, s->filter_slice[pl], &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); if (in != out) 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) +{ + int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + + if (ret < 0) + return ret; + + return config_output(ctx->outputs[0]); +} + static av_cold void uninit(AVFilterContext *ctx) { ColorChannelMixerContext *s = ctx->priv; @@ -566,4 +809,5 @@ .inputs = colorchannelmixer_inputs, .outputs = colorchannelmixer_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_colorconstancy.c ffmpeg-4.4/libavfilter/vf_colorconstancy.c --- ffmpeg-4.2.2/libavfilter/vf_colorconstancy.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_colorconstancy.c 2020-07-11 10:39:30.000000000 +0000 @@ -121,7 +121,6 @@ for (; i >= 0; --i) { av_freep(&s->gauss[i]); } - av_log(ctx, AV_LOG_ERROR, "Out of memory while allocating gauss buffers.\n"); return AVERROR(ENOMEM); } } @@ -223,7 +222,6 @@ td->data[b][p] = av_mallocz_array(s->planeheight[p] * s->planewidth[p], sizeof(*td->data[b][p])); if (!td->data[b][p]) { cleanup_derivative_buffers(td, b + 1, p); - av_log(ctx, AV_LOG_ERROR, "Out of memory while allocating derivatives buffers.\n"); return AVERROR(ENOMEM); } } @@ -280,7 +278,7 @@ dst[INDX2D(r, c, width)] = 0; for (g = 0; g < filtersize; ++g) { dst[INDX2D(r, c, width)] += GAUSS(src, r, c + GINDX(filtersize, g), - in_linesize, height, width, gauss[GINDX(filtersize, g)]); + in_linesize, height, width, gauss[g]); } } } @@ -295,7 +293,7 @@ dst[INDX2D(r, c, width)] = 0; for (g = 0; g < filtersize; ++g) { dst[INDX2D(r, c, width)] += GAUSS(src, r + GINDX(filtersize, g), c, - width, height, width, gauss[GINDX(filtersize, g)]); + width, height, width, gauss[g]); } } } @@ -682,24 +680,30 @@ AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; int ret; + int direct = 0; ret = illumination_estimation(ctx, in); if (ret) { + av_frame_free(&in); return ret; } if (av_frame_is_writable(in)) { + direct = 1; out = in; } else { out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { - av_log(ctx, AV_LOG_ERROR, "Out of memory while allocating output video buffer.\n"); + av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); } chromatic_adaptation(ctx, in, out); + if (!direct) + av_frame_free(&in); + return ff_filter_frame(outlink, out); } diff -Nru ffmpeg-4.2.2/libavfilter/vf_colorcontrast.c ffmpeg-4.4/libavfilter/vf_colorcontrast.c --- ffmpeg-4.2.2/libavfilter/vf_colorcontrast.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_colorcontrast.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,408 @@ +/* + * 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 "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 + +typedef struct ColorContrastContext { + const AVClass *class; + + float rc, gm, by; + float rcw, gmw, byw; + float preserve; + + int step; + int depth; + uint8_t rgba_map[4]; + + int (*do_slice)(AVFilterContext *s, void *arg, + int jobnr, int nb_jobs); +} ColorContrastContext; + +static inline float lerpf(float v0, float v1, float f) +{ + return v0 + (v1 - v0) * f; +} + +#define PROCESS(max) \ + br = (b + r) * 0.5f; \ + gb = (g + b) * 0.5f; \ + rg = (r + g) * 0.5f; \ + \ + gd = g - br; \ + bd = b - rg; \ + rd = r - gb; \ + \ + g0 = g + gd * gm; \ + b0 = b - gd * gm; \ + r0 = r - gd * gm; \ + \ + g1 = g - bd * by; \ + b1 = b + bd * by; \ + r1 = r - bd * by; \ + \ + g2 = g - rd * rc; \ + b2 = b - rd * rc; \ + r2 = r + rd * rc; \ + \ + ng = av_clipf((g0 * gmw + g1 * byw + g2 * rcw) * scale, 0.f, max); \ + nb = av_clipf((b0 * gmw + b1 * byw + b2 * rcw) * scale, 0.f, max); \ + nr = av_clipf((r0 * gmw + r1 * byw + r2 * rcw) * scale, 0.f, max); \ + \ + li = FFMAX3(r, g, b) + FFMIN3(r, g, b); \ + lo = FFMAX3(nr, ng, nb) + FFMIN3(nr, ng, nb) + FLT_EPSILON; \ + lf = li / lo; \ + \ + r = nr * lf; \ + g = ng * lf; \ + b = nb * lf; \ + \ + nr = lerpf(nr, r, preserve); \ + ng = lerpf(ng, g, preserve); \ + nb = lerpf(nb, b, preserve); + +static int colorcontrast_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorContrastContext *s = ctx->priv; + AVFrame *frame = arg; + const int width = frame->width; + const int height = frame->height; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int glinesize = frame->linesize[0]; + const int blinesize = frame->linesize[1]; + const int rlinesize = frame->linesize[2]; + uint8_t *gptr = frame->data[0] + slice_start * glinesize; + uint8_t *bptr = frame->data[1] + slice_start * blinesize; + uint8_t *rptr = frame->data[2] + slice_start * rlinesize; + const float preserve = s->preserve; + const float gm = s->gm * 0.5f; + const float by = s->by * 0.5f; + const float rc = s->rc * 0.5f; + const float gmw = s->gmw; + const float byw = s->byw; + const float rcw = s->rcw; + const float sum = gmw + byw + rcw; + const float scale = 1.f / sum; + + for (int y = slice_start; y < slice_end && sum > FLT_EPSILON; y++) { + for (int x = 0; x < width; x++) { + float g = gptr[x]; + float b = bptr[x]; + float r = rptr[x]; + float g0, g1, g2; + float b0, b1, b2; + float r0, r1, r2; + float gd, bd, rd; + float gb, br, rg; + float nr, ng, nb; + float li, lo, lf; + + PROCESS(255.f); + + gptr[x] = av_clip_uint8(ng); + bptr[x] = av_clip_uint8(nb); + rptr[x] = av_clip_uint8(nr); + } + + gptr += glinesize; + bptr += blinesize; + rptr += rlinesize; + } + + return 0; +} + +static int colorcontrast_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorContrastContext *s = ctx->priv; + AVFrame *frame = arg; + const int depth = s->depth; + const float max = (1 << depth) - 1; + const int width = frame->width; + const int height = frame->height; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int glinesize = frame->linesize[0] / 2; + const int blinesize = frame->linesize[1] / 2; + const int rlinesize = frame->linesize[2] / 2; + uint16_t *gptr = (uint16_t *)frame->data[0] + slice_start * glinesize; + uint16_t *bptr = (uint16_t *)frame->data[1] + slice_start * blinesize; + uint16_t *rptr = (uint16_t *)frame->data[2] + slice_start * rlinesize; + const float preserve = s->preserve; + const float gm = s->gm * 0.5f; + const float by = s->by * 0.5f; + const float rc = s->rc * 0.5f; + const float gmw = s->gmw; + const float byw = s->byw; + const float rcw = s->rcw; + const float sum = gmw + byw + rcw; + const float scale = 1.f / sum; + + for (int y = slice_start; y < slice_end && sum > FLT_EPSILON; y++) { + for (int x = 0; x < width; x++) { + float g = gptr[x]; + float b = bptr[x]; + float r = rptr[x]; + float g0, g1, g2; + float b0, b1, b2; + float r0, r1, r2; + float gd, bd, rd; + float gb, br, rg; + float nr, ng, nb; + float li, lo, lf; + + PROCESS(max); + + gptr[x] = av_clip_uintp2_c(ng, depth); + bptr[x] = av_clip_uintp2_c(nb, depth); + rptr[x] = av_clip_uintp2_c(nr, depth); + } + + gptr += glinesize; + bptr += blinesize; + rptr += rlinesize; + } + + return 0; +} + +static int colorcontrast_slice8p(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorContrastContext *s = ctx->priv; + AVFrame *frame = arg; + const int step = s->step; + const int width = frame->width; + const int height = frame->height; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int linesize = frame->linesize[0]; + const uint8_t roffset = s->rgba_map[R]; + const uint8_t goffset = s->rgba_map[G]; + const uint8_t boffset = s->rgba_map[B]; + uint8_t *ptr = frame->data[0] + slice_start * linesize; + const float preserve = s->preserve; + const float gm = s->gm * 0.5f; + const float by = s->by * 0.5f; + const float rc = s->rc * 0.5f; + const float gmw = s->gmw; + const float byw = s->byw; + const float rcw = s->rcw; + const float sum = gmw + byw + rcw; + const float scale = 1.f / sum; + + for (int y = slice_start; y < slice_end && sum > FLT_EPSILON; y++) { + for (int x = 0; x < width; x++) { + float g = ptr[x * step + goffset]; + float b = ptr[x * step + boffset]; + float r = ptr[x * step + roffset]; + float g0, g1, g2; + float b0, b1, b2; + float r0, r1, r2; + float gd, bd, rd; + float gb, br, rg; + float nr, ng, nb; + float li, lo, lf; + + PROCESS(255.f); + + ptr[x * step + goffset] = av_clip_uint8(ng); + ptr[x * step + boffset] = av_clip_uint8(nb); + ptr[x * step + roffset] = av_clip_uint8(nr); + } + + ptr += linesize; + } + + return 0; +} + +static int colorcontrast_slice16p(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorContrastContext *s = ctx->priv; + AVFrame *frame = arg; + const int step = s->step; + const int depth = s->depth; + const float max = (1 << depth) - 1; + const int width = frame->width; + const int height = frame->height; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int linesize = frame->linesize[0] / 2; + const uint8_t roffset = s->rgba_map[R]; + const uint8_t goffset = s->rgba_map[G]; + const uint8_t boffset = s->rgba_map[B]; + uint16_t *ptr = (uint16_t *)frame->data[0] + slice_start * linesize; + const float preserve = s->preserve; + const float gm = s->gm * 0.5f; + const float by = s->by * 0.5f; + const float rc = s->rc * 0.5f; + const float gmw = s->gmw; + const float byw = s->byw; + const float rcw = s->rcw; + const float sum = gmw + byw + rcw; + const float scale = 1.f / sum; + + for (int y = slice_start; y < slice_end && sum > FLT_EPSILON; y++) { + for (int x = 0; x < width; x++) { + float g = ptr[x * step + goffset]; + float b = ptr[x * step + boffset]; + float r = ptr[x * step + roffset]; + float g0, g1, g2; + float b0, b1, b2; + float r0, r1, r2; + float gd, bd, rd; + float gb, br, rg; + float nr, ng, nb; + float li, lo, lf; + + PROCESS(max); + + ptr[x * step + goffset] = av_clip_uintp2_c(ng, depth); + ptr[x * step + boffset] = av_clip_uintp2_c(nb, depth); + ptr[x * step + roffset] = av_clip_uintp2_c(nr, depth); + } + + ptr += linesize; + } + + return 0; +} + +static int filter_frame(AVFilterLink *link, AVFrame *frame) +{ + AVFilterContext *ctx = link->dst; + ColorContrastContext *s = ctx->priv; + int res; + + if (res = ctx->internal->execute(ctx, s->do_slice, frame, NULL, + FFMIN(frame->height, ff_filter_get_nb_threads(ctx)))) + return res; + + return ff_filter_frame(ctx->outputs[0], frame); +} + +static av_cold int query_formats(AVFilterContext *ctx) +{ + 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_ARGB, AV_PIX_FMT_ABGR, + AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR, + AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, + AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, + AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48, + AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *formats = NULL; + + formats = ff_make_format_list(pixel_fmts); + if (!formats) + return AVERROR(ENOMEM); + + return ff_set_common_formats(ctx, formats); +} + +static av_cold int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ColorContrastContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR; + + s->step = desc->nb_components; + if (inlink->format == AV_PIX_FMT_RGB0 || + inlink->format == AV_PIX_FMT_0RGB || + inlink->format == AV_PIX_FMT_BGR0 || + inlink->format == AV_PIX_FMT_0BGR) + s->step = 4; + + s->depth = desc->comp[0].depth; + s->do_slice = s->depth <= 8 ? colorcontrast_slice8 : colorcontrast_slice16; + if (!planar) + s->do_slice = s->depth <= 8 ? colorcontrast_slice8p : colorcontrast_slice16p; + + ff_fill_rgba_map(s->rgba_map, inlink->format); + + return 0; +} + +static const AVFilterPad colorcontrast_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .needs_writable = 1, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad colorcontrast_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(ColorContrastContext, x) +#define VF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption colorcontrast_options[] = { + { "rc", "set the red-cyan contrast", OFFSET(rc), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF }, + { "gm", "set the green-magenta contrast", OFFSET(gm), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF }, + { "by", "set the blue-yellow contrast", OFFSET(by), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF }, + { "rcw", "set the red-cyan weight", OFFSET(rcw), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, VF }, + { "gmw", "set the green-magenta weight", OFFSET(gmw), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, VF }, + { "byw", "set the blue-yellow weight", OFFSET(byw), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, VF }, + { "pl", "set the amount of preserving lightness", OFFSET(preserve), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, VF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(colorcontrast); + +AVFilter ff_vf_colorcontrast = { + .name = "colorcontrast", + .description = NULL_IF_CONFIG_SMALL("Adjust color contrast between RGB components."), + .priv_size = sizeof(ColorContrastContext), + .priv_class = &colorcontrast_class, + .query_formats = query_formats, + .inputs = colorcontrast_inputs, + .outputs = colorcontrast_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_colorcorrect.c ffmpeg-4.4/libavfilter/vf_colorcorrect.c --- ffmpeg-4.2.2/libavfilter/vf_colorcorrect.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_colorcorrect.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,217 @@ +/* + * 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 "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct ColorCorrectContext { + const AVClass *class; + + float rl, bl; + float rh, bh; + float saturation; + + int depth; + + int (*do_slice)(AVFilterContext *s, void *arg, + int jobnr, int nb_jobs); +} ColorCorrectContext; + +#define PROCESS() \ + float y = yptr[x] * imax; \ + float u = uptr[x] * imax - .5f; \ + float v = vptr[x] * imax - .5f; \ + float ny, nu, nv; \ + \ + ny = y; \ + nu = saturation * (u + y * bd + bl); \ + nv = saturation * (v + y * rd + rl); + +static int colorcorrect_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorCorrectContext *s = ctx->priv; + AVFrame *frame = arg; + const int depth = s->depth; + const float max = (1 << depth) - 1; + const float imax = 1.f / max; + const int width = frame->width; + const int height = frame->height; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int ylinesize = frame->linesize[0]; + const int ulinesize = frame->linesize[1]; + const int vlinesize = frame->linesize[2]; + uint8_t *yptr = frame->data[0] + slice_start * ylinesize; + uint8_t *uptr = frame->data[1] + slice_start * ulinesize; + uint8_t *vptr = frame->data[2] + slice_start * vlinesize; + const float saturation = s->saturation; + const float bl = s->bl; + const float rl = s->rl; + const float bd = s->bh - bl; + const float rd = s->rh - rl; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) { + PROCESS() + + yptr[x] = av_clip_uint8( ny * max); + uptr[x] = av_clip_uint8((nu + 0.5f) * max); + vptr[x] = av_clip_uint8((nv + 0.5f) * max); + } + + yptr += ylinesize; + uptr += ulinesize; + vptr += vlinesize; + } + + return 0; +} + +static int colorcorrect_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorCorrectContext *s = ctx->priv; + AVFrame *frame = arg; + const int depth = s->depth; + const float max = (1 << depth) - 1; + const float imax = 1.f / max; + const int width = frame->width; + const int height = frame->height; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int ylinesize = frame->linesize[0] / 2; + const int ulinesize = frame->linesize[1] / 2; + const int vlinesize = frame->linesize[2] / 2; + uint16_t *yptr = (uint16_t *)frame->data[0] + slice_start * ylinesize; + uint16_t *uptr = (uint16_t *)frame->data[1] + slice_start * ulinesize; + uint16_t *vptr = (uint16_t *)frame->data[2] + slice_start * vlinesize; + const float saturation = s->saturation; + const float bl = s->bl; + const float rl = s->rl; + const float bd = s->bh - bl; + const float rd = s->rh - rl; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) { + PROCESS() + + yptr[x] = av_clip_uintp2_c( ny * max, depth); + uptr[x] = av_clip_uintp2_c((nu + 0.5f) * max, depth); + vptr[x] = av_clip_uintp2_c((nv + 0.5f) * max, depth); + } + + yptr += ylinesize; + uptr += ulinesize; + vptr += vlinesize; + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + ColorCorrectContext *s = ctx->priv; + + ctx->internal->execute(ctx, s->do_slice, frame, NULL, + FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); + + return ff_filter_frame(ctx->outputs[0], frame); +} + +static av_cold int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pixel_fmts[] = { + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *formats = NULL; + + formats = ff_make_format_list(pixel_fmts); + if (!formats) + return AVERROR(ENOMEM); + + return ff_set_common_formats(ctx, formats); +} + +static av_cold int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ColorCorrectContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + + s->depth = desc->comp[0].depth; + s->do_slice = s->depth <= 8 ? colorcorrect_slice8 : colorcorrect_slice16; + + return 0; +} + +static const AVFilterPad colorcorrect_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .needs_writable = 1, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad colorcorrect_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(ColorCorrectContext, x) +#define VF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption colorcorrect_options[] = { + { "rl", "set the red shadow spot", OFFSET(rl), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF }, + { "bl", "set the blue shadow spot", OFFSET(bl), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF }, + { "rh", "set the red highlight spot", OFFSET(rh), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF }, + { "bh", "set the blue highlight spot", OFFSET(bh), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF }, + { "saturation", "set the amount of saturation", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl=1}, -3, 3, VF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(colorcorrect); + +AVFilter ff_vf_colorcorrect = { + .name = "colorcorrect", + .description = NULL_IF_CONFIG_SMALL("Adjust color white balance selectively for blacks and whites."), + .priv_size = sizeof(ColorCorrectContext), + .priv_class = &colorcorrect_class, + .query_formats = query_formats, + .inputs = colorcorrect_inputs, + .outputs = colorcorrect_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_colorize.c ffmpeg-4.4/libavfilter/vf_colorize.c --- ffmpeg-4.2.2/libavfilter/vf_colorize.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_colorize.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,306 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct ColorizeContext { + const AVClass *class; + + float hue; + float saturation; + float lightness; + float mix; + + int depth; + int c[3]; + int planewidth[4]; + int planeheight[4]; + + int (*do_plane_slice[2])(AVFilterContext *s, void *arg, + int jobnr, int nb_jobs); +} ColorizeContext; + +static inline float lerpf(float v0, float v1, float f) +{ + return v0 + (v1 - v0) * f; +} + +static int colorizey_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorizeContext *s = ctx->priv; + AVFrame *frame = arg; + const int width = s->planewidth[0]; + const int height = s->planeheight[0]; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int ylinesize = frame->linesize[0]; + uint8_t *yptr = frame->data[0] + slice_start * ylinesize; + const int yv = s->c[0]; + const float mix = s->mix; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) + yptr[x] = lerpf(yv, yptr[x], mix); + + yptr += ylinesize; + } + + return 0; +} + +static int colorizey_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorizeContext *s = ctx->priv; + AVFrame *frame = arg; + const int width = s->planewidth[0]; + const int height = s->planeheight[0]; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int ylinesize = frame->linesize[0] / 2; + uint16_t *yptr = (uint16_t *)frame->data[0] + slice_start * ylinesize; + const int yv = s->c[0]; + const float mix = s->mix; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) + yptr[x] = lerpf(yv, yptr[x], mix); + + yptr += ylinesize; + } + + return 0; +} + +static int colorize_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorizeContext *s = ctx->priv; + AVFrame *frame = arg; + const int width = s->planewidth[1]; + const int height = s->planeheight[1]; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int ulinesize = frame->linesize[1]; + const int vlinesize = frame->linesize[2]; + uint8_t *uptr = frame->data[1] + slice_start * ulinesize; + uint8_t *vptr = frame->data[2] + slice_start * vlinesize; + const int u = s->c[1]; + const int v = s->c[2]; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) { + uptr[x] = u; + vptr[x] = v; + } + + uptr += ulinesize; + vptr += vlinesize; + } + + return 0; +} + +static int colorize_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorizeContext *s = ctx->priv; + AVFrame *frame = arg; + const int width = s->planewidth[1]; + const int height = s->planeheight[1]; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int ulinesize = frame->linesize[1] / 2; + const int vlinesize = frame->linesize[2] / 2; + uint16_t *uptr = (uint16_t *)frame->data[1] + slice_start * ulinesize; + uint16_t *vptr = (uint16_t *)frame->data[2] + slice_start * vlinesize; + const int u = s->c[1]; + const int v = s->c[2]; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) { + uptr[x] = u; + vptr[x] = v; + } + + uptr += ulinesize; + vptr += vlinesize; + } + + return 0; +} + +static int do_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorizeContext *s = ctx->priv; + + s->do_plane_slice[0](ctx, arg, jobnr, nb_jobs); + s->do_plane_slice[1](ctx, arg, jobnr, nb_jobs); + + return 0; +} + +static float hue2rgb(float p, float q, float t) +{ + if (t < 0.f) t += 1.f; + if (t > 1.f) t -= 1.f; + if (t < 1.f/6.f) return p + (q - p) * 6.f * t; + if (t < 1.f/2.f) return q; + if (t < 2.f/3.f) return p + (q - p) * (2.f/3.f - t) * 6.f; + + return p; +} + +static void hsl2rgb(float h, float s, float l, float *r, float *g, float *b) +{ + h /= 360.f; + + if (s == 0.f) { + *r = *g = *b = l; + } else { + const float q = l < 0.5f ? l * (1.f + s) : l + s - l * s; + const float p = 2.f * l - q; + + *r = hue2rgb(p, q, h + 1.f / 3.f); + *g = hue2rgb(p, q, h); + *b = hue2rgb(p, q, h - 1.f / 3.f); + } +} + +static void rgb2yuv(float r, float g, float b, int *y, int *u, int *v, int depth) +{ + *y = ((0.21260*219.0/255.0) * r + (0.71520*219.0/255.0) * g + + (0.07220*219.0/255.0) * b) * ((1 << depth) - 1); + *u = (-(0.11457*224.0/255.0) * r - (0.38543*224.0/255.0) * g + + (0.50000*224.0/255.0) * b + 0.5) * ((1 << depth) - 1); + *v = ((0.50000*224.0/255.0) * r - (0.45415*224.0/255.0) * g - + (0.04585*224.0/255.0) * b + 0.5) * ((1 << depth) - 1); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + ColorizeContext *s = ctx->priv; + float c[3]; + + hsl2rgb(s->hue, s->saturation, s->lightness, &c[0], &c[1], &c[2]); + rgb2yuv(c[0], c[1], c[2], &s->c[0], &s->c[1], &s->c[2], s->depth); + + ctx->internal->execute(ctx, do_slice, frame, NULL, + FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx))); + + return ff_filter_frame(ctx->outputs[0], frame); +} + +static av_cold int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pixel_fmts[] = { + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *formats = NULL; + + formats = ff_make_format_list(pixel_fmts); + if (!formats) + return AVERROR(ENOMEM); + + return ff_set_common_formats(ctx, formats); +} + +static av_cold int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ColorizeContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int depth; + + s->depth = depth = desc->comp[0].depth; + + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + 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_plane_slice[0] = depth <= 8 ? colorizey_slice8 : colorizey_slice16; + s->do_plane_slice[1] = depth <= 8 ? colorize_slice8 : colorize_slice16; + + return 0; +} + +static const AVFilterPad colorize_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .needs_writable = 1, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad colorize_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(ColorizeContext, x) +#define VF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption colorize_options[] = { + { "hue", "set the hue", OFFSET(hue), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 360, VF }, + { "saturation", "set the saturation", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl=0.5},0, 1, VF }, + { "lightness", "set the lightness", OFFSET(lightness), AV_OPT_TYPE_FLOAT, {.dbl=0.5},0, 1, VF }, + { "mix", "set the mix of source lightness", OFFSET(mix), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, VF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(colorize); + +AVFilter ff_vf_colorize = { + .name = "colorize", + .description = NULL_IF_CONFIG_SMALL("Overlay a solid color on the video stream."), + .priv_size = sizeof(ColorizeContext), + .priv_class = &colorize_class, + .query_formats = query_formats, + .inputs = colorize_inputs, + .outputs = colorize_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_colorkey.c ffmpeg-4.4/libavfilter/vf_colorkey.c --- ffmpeg-4.2.2/libavfilter/vf_colorkey.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_colorkey.c 2020-07-11 10:39:30.000000000 +0000 @@ -45,7 +45,7 @@ int dg = (int)g - ctx->colorkey_rgba[1]; int db = (int)b - ctx->colorkey_rgba[2]; - double diff = sqrt((dr * dr + dg * dg + db * db) / (255.0 * 255.0)); + double diff = sqrt((dr * dr + dg * dg + db * db) / (255.0 * 255.0 * 3.0)); if (ctx->blend > 0.0001) { return av_clipd((diff - ctx->similarity) / ctx->blend, 0.0, 1.0) * 255.0; @@ -199,12 +199,12 @@ }; #define OFFSET(x) offsetof(ColorkeyContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM #if CONFIG_COLORKEY_FILTER static const AVOption colorkey_options[] = { - { "color", "set the colorkey key color", OFFSET(colorkey_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "color", "set the colorkey key color", OFFSET(colorkey_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, 0, 0, FLAGS }, { "similarity", "set the colorkey similarity value", OFFSET(similarity), AV_OPT_TYPE_FLOAT, { .dbl = 0.01 }, 0.01, 1.0, FLAGS }, { "blend", "set the colorkey key blend value", OFFSET(blend), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, 0.0, 1.0, FLAGS }, { NULL } @@ -222,13 +222,14 @@ .inputs = colorkey_inputs, .outputs = colorkey_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; #endif /* CONFIG_COLORKEY_FILTER */ #if CONFIG_COLORHOLD_FILTER static const AVOption colorhold_options[] = { - { "color", "set the colorhold key color", OFFSET(colorkey_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "color", "set the colorhold key color", OFFSET(colorkey_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, 0, 0, FLAGS }, { "similarity", "set the colorhold similarity value", OFFSET(similarity), AV_OPT_TYPE_FLOAT, { .dbl = 0.01 }, 0.01, 1.0, FLAGS }, { "blend", "set the colorhold blend value", OFFSET(blend), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, 0.0, 1.0, FLAGS }, { NULL } @@ -246,6 +247,7 @@ .inputs = colorkey_inputs, .outputs = colorkey_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; #endif /* CONFIG_COLORHOLD_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/vf_colorkey_opencl.c ffmpeg-4.4/libavfilter/vf_colorkey_opencl.c --- ffmpeg-4.2.2/libavfilter/vf_colorkey_opencl.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_colorkey_opencl.c 2020-07-11 10:39:30.000000000 +0000 @@ -222,7 +222,7 @@ #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption colorkey_opencl_options[] = { - { "color", "set the colorkey key color", OFFSET(colorkey_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "color", "set the colorkey key color", OFFSET(colorkey_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, 0, 0, FLAGS }, { "similarity", "set the colorkey similarity value", OFFSET(similarity), AV_OPT_TYPE_FLOAT, { .dbl = 0.01 }, 0.01, 1.0, FLAGS }, { "blend", "set the colorkey key blend value", OFFSET(blend), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, 0.0, 1.0, FLAGS }, { NULL } diff -Nru ffmpeg-4.2.2/libavfilter/vf_colorlevels.c ffmpeg-4.4/libavfilter/vf_colorlevels.c --- ffmpeg-4.2.2/libavfilter/vf_colorlevels.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_colorlevels.c 2021-04-08 21:28:40.000000000 +0000 @@ -40,15 +40,18 @@ typedef struct ColorLevelsContext { const AVClass *class; Range range[4]; + int nb_comp; int bpp; int step; uint8_t rgba_map[4]; int linesize; + + int (*colorlevels_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } ColorLevelsContext; #define OFFSET(x) offsetof(ColorLevelsContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption colorlevels_options[] = { { "rimin", "set input red black point", OFFSET(range[R].in_min), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS }, { "gimin", "set input green black point", OFFSET(range[G].in_min), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS }, @@ -90,91 +93,101 @@ return ff_set_common_formats(ctx, fmts_list); } -static int config_input(AVFilterLink *inlink) -{ - AVFilterContext *ctx = inlink->dst; - ColorLevelsContext *s = ctx->priv; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - - s->nb_comp = desc->nb_components; - s->bpp = desc->comp[0].depth >> 3; - s->step = (av_get_padded_bits_per_pixel(desc) >> 3) / s->bpp; - s->linesize = inlink->w * s->step; - ff_fill_rgba_map(s->rgba_map, inlink->format); - - return 0; -} - -struct thread_data { +typedef struct ThreadData { const uint8_t *srcrow; uint8_t *dstrow; int dst_linesize; int src_linesize; - double coeff; - uint8_t offset; + float coeff[4]; int h; - int imin; - int omin; -}; - -#define LOAD_COMMON\ - ColorLevelsContext *s = ctx->priv;\ - const struct thread_data *td = arg;\ -\ - int process_h = td->h;\ - const int slice_start = (process_h * jobnr ) / nb_jobs;\ - const int slice_end = (process_h * (jobnr+1)) / nb_jobs;\ - int x, y;\ - const uint8_t *srcrow = td->srcrow;\ - uint8_t *dstrow = td->dstrow;\ - const int step = s->step;\ - const uint8_t offset = td->offset;\ -\ - int imin = td->imin;\ - int omin = td->omin;\ - double coeff = td->coeff;\ + int imin[4]; + int omin[4]; +} ThreadData; + +#define LOAD_COMMON \ + ColorLevelsContext *s = ctx->priv; \ + const ThreadData *td = arg; \ + const int process_h = td->h; \ + const int slice_start = (process_h * jobnr ) / nb_jobs; \ + const int slice_end = (process_h * (jobnr+1)) / nb_jobs; \ + const uint8_t *srcrow = td->srcrow; \ + uint8_t *dstrow = td->dstrow; \ + const int step = s->step; -static int colorlevel_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +static int colorlevels_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { LOAD_COMMON - for (y = slice_start; y < slice_end; y++) { - const uint8_t *src = srcrow + y * td->src_linesize; - uint8_t *dst = dstrow + y * td->dst_linesize; + for (int comp = 0; comp < s->nb_comp; comp++) { + const uint8_t offset = s->rgba_map[comp]; + const int imin = td->imin[comp]; + const int omin = td->omin[comp]; + const float coeff = td->coeff[comp]; + + for (int y = slice_start; y < slice_end; y++) { + const uint8_t *src = srcrow + y * td->src_linesize; + uint8_t *dst = dstrow + y * td->dst_linesize; - for (x = 0; x < s->linesize; x += step) - dst[x + offset] = av_clip_uint8((src[x + offset] - imin) * coeff + omin); + for (int x = 0; x < s->linesize; x += step) + dst[x + offset] = av_clip_uint8((src[x + offset] - imin) * coeff + omin); + } } return 0; } -static int colorlevel_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +static int colorlevels_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { LOAD_COMMON - for (y = slice_start; y < slice_end; y++) { - const uint16_t *src = (const uint16_t *)(srcrow + y * td->src_linesize); - uint16_t *dst = (uint16_t *)(dstrow + y * td->dst_linesize); + for (int comp = 0; comp < s->nb_comp; comp++) { + const uint8_t offset = s->rgba_map[comp]; + const int imin = td->imin[comp]; + const int omin = td->omin[comp]; + const float coeff = td->coeff[comp]; + + for (int y = slice_start; y < slice_end; y++) { + const uint16_t *src = (const uint16_t *)(srcrow + y * td->src_linesize); + uint16_t *dst = (uint16_t *)(dstrow + y * td->dst_linesize); - for (x = 0; x < s->linesize; x += step) - dst[x + offset] = av_clip_uint16((src[x + offset] - imin) * coeff + omin); + for (int x = 0; x < s->linesize; x += step) + dst[x + offset] = av_clip_uint16((src[x + offset] - imin) * coeff + omin); + } } return 0; } +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ColorLevelsContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + + s->nb_comp = desc->nb_components; + s->bpp = desc->comp[0].depth >> 3; + s->step = av_get_padded_bits_per_pixel(desc) >> (3 + (s->bpp == 2)); + s->linesize = inlink->w * s->step; + ff_fill_rgba_map(s->rgba_map, inlink->format); + + s->colorlevels_slice = colorlevels_slice_8; + if (s->bpp == 2) + s->colorlevels_slice = colorlevels_slice_16; + + return 0; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; ColorLevelsContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; const int step = s->step; + ThreadData td; AVFrame *out; - int x, y, i; if (av_frame_is_writable(in)) { out = in; @@ -187,26 +200,30 @@ av_frame_copy_props(out, in); } + td.h = inlink->h; + td.dst_linesize = out->linesize[0]; + td.src_linesize = in->linesize[0]; + td.srcrow = in->data[0]; + td.dstrow = out->data[0]; + switch (s->bpp) { case 1: - for (i = 0; i < s->nb_comp; i++) { + for (int i = 0; i < s->nb_comp; i++) { Range *r = &s->range[i]; const uint8_t offset = s->rgba_map[i]; const uint8_t *srcrow = in->data[0]; - uint8_t *dstrow = out->data[0]; int imin = lrint(r->in_min * UINT8_MAX); int imax = lrint(r->in_max * UINT8_MAX); int omin = lrint(r->out_min * UINT8_MAX); int omax = lrint(r->out_max * UINT8_MAX); - double coeff; - struct thread_data td; + float coeff; if (imin < 0) { imin = UINT8_MAX; - for (y = 0; y < inlink->h; y++) { + for (int y = 0; y < inlink->h; y++) { const uint8_t *src = srcrow; - for (x = 0; x < s->linesize; x += step) + for (int x = 0; x < s->linesize; x += step) imin = FFMIN(imin, src[x + offset]); srcrow += in->linesize[0]; } @@ -214,51 +231,39 @@ if (imax < 0) { srcrow = in->data[0]; imax = 0; - for (y = 0; y < inlink->h; y++) { + for (int y = 0; y < inlink->h; y++) { const uint8_t *src = srcrow; - for (x = 0; x < s->linesize; x += step) + for (int x = 0; x < s->linesize; x += step) imax = FFMAX(imax, src[x + offset]); srcrow += in->linesize[0]; } } - srcrow = in->data[0]; coeff = (omax - omin) / (double)(imax - imin); - td.srcrow = srcrow; - td.dstrow = dstrow; - td.dst_linesize = out->linesize[0]; - td.src_linesize = in->linesize[0]; - td.coeff = coeff; - td.offset = offset; - td.h = inlink->h; - td.imin = imin; - td.omin = omin; - - ctx->internal->execute(ctx, colorlevel_slice_8, &td, NULL, - FFMIN(inlink->h, ff_filter_get_nb_threads(ctx))); + td.coeff[i] = coeff; + td.imin[i] = imin; + td.omin[i] = omin; } break; case 2: - for (i = 0; i < s->nb_comp; i++) { + for (int i = 0; i < s->nb_comp; i++) { Range *r = &s->range[i]; const uint8_t offset = s->rgba_map[i]; const uint8_t *srcrow = in->data[0]; - uint8_t *dstrow = out->data[0]; int imin = lrint(r->in_min * UINT16_MAX); int imax = lrint(r->in_max * UINT16_MAX); int omin = lrint(r->out_min * UINT16_MAX); int omax = lrint(r->out_max * UINT16_MAX); - double coeff; - struct thread_data td; + float coeff; if (imin < 0) { imin = UINT16_MAX; - for (y = 0; y < inlink->h; y++) { + for (int y = 0; y < inlink->h; y++) { const uint16_t *src = (const uint16_t *)srcrow; - for (x = 0; x < s->linesize; x += step) + for (int x = 0; x < s->linesize; x += step) imin = FFMIN(imin, src[x + offset]); srcrow += in->linesize[0]; } @@ -266,33 +271,27 @@ if (imax < 0) { srcrow = in->data[0]; imax = 0; - for (y = 0; y < inlink->h; y++) { + for (int y = 0; y < inlink->h; y++) { const uint16_t *src = (const uint16_t *)srcrow; - for (x = 0; x < s->linesize; x += step) + for (int x = 0; x < s->linesize; x += step) imax = FFMAX(imax, src[x + offset]); srcrow += in->linesize[0]; } } - srcrow = in->data[0]; coeff = (omax - omin) / (double)(imax - imin); - td.srcrow = srcrow; - td.dstrow = dstrow; - td.dst_linesize = out->linesize[0]; - td.src_linesize = in->linesize[0]; - td.coeff = coeff; - td.offset = offset; - td.h = inlink->h; - td.imin = imin; - td.omin = omin; - - ctx->internal->execute(ctx, colorlevel_slice_16, &td, NULL, - FFMIN(inlink->h, ff_filter_get_nb_threads(ctx))); + td.coeff[i] = coeff; + td.imin[i] = imin; + td.omin[i] = omin; } + break; } + ctx->internal->execute(ctx, s->colorlevels_slice, &td, NULL, + FFMIN(inlink->h, ff_filter_get_nb_threads(ctx))); + if (in != out) av_frame_free(&in); return ff_filter_frame(outlink, out); @@ -325,4 +324,5 @@ .inputs = colorlevels_inputs, .outputs = colorlevels_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_colorspace.c ffmpeg-4.4/libavfilter/vf_colorspace.c --- ffmpeg-4.2.2/libavfilter/vf_colorspace.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_colorspace.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ */ #include "libavutil/avassert.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" @@ -179,6 +180,7 @@ [AVCOL_TRC_GAMMA28] = { 1.0, 0.0, 1.0 / 2.8, 0.0 }, [AVCOL_TRC_SMPTE170M] = { 1.099, 0.018, 0.45, 4.5 }, [AVCOL_TRC_SMPTE240M] = { 1.1115, 0.0228, 0.45, 4.0 }, + [AVCOL_TRC_LINEAR] = { 1.0, 0.0, 1.0, 0.0 }, [AVCOL_TRC_IEC61966_2_1] = { 1.055, 0.0031308, 1.0 / 2.4, 12.92 }, [AVCOL_TRC_IEC61966_2_4] = { 1.099, 0.018, 0.45, 4.5 }, [AVCOL_TRC_BT2020_10] = { 1.099, 0.018, 0.45, 4.5 }, @@ -331,15 +333,15 @@ } } -struct ThreadData { +typedef struct ThreadData { AVFrame *in, *out; ptrdiff_t in_linesize[3], out_linesize[3]; int in_ss_h, out_ss_h; -}; +} ThreadData; static int convert(AVFilterContext *ctx, void *data, int job_nr, int n_jobs) { - struct ThreadData *td = data; + const ThreadData *td = data; ColorSpaceContext *s = ctx->priv; uint8_t *in_data[3], *out_data[3]; int16_t *rgb[3]; @@ -732,7 +734,7 @@ return 0; } -static int init(AVFilterContext *ctx) +static av_cold int init(AVFilterContext *ctx) { ColorSpaceContext *s = ctx->priv; @@ -771,7 +773,7 @@ int res; ptrdiff_t rgb_stride = FFALIGN(in->width * sizeof(int16_t), 32); unsigned rgb_sz = rgb_stride * in->height; - struct ThreadData td; + ThreadData td; if (!out) { av_frame_free(&in); @@ -780,6 +782,7 @@ res = av_frame_copy_props(out, in); if (res < 0) { av_frame_free(&in); + av_frame_free(&out); return res; } @@ -839,13 +842,18 @@ !s->dither_scratch_base[1][0] || !s->dither_scratch_base[1][1] || !s->dither_scratch_base[2][0] || !s->dither_scratch_base[2][1]) { uninit(ctx); + av_frame_free(&in); + av_frame_free(&out); return AVERROR(ENOMEM); } s->rgb_sz = rgb_sz; } res = create_filtergraph(ctx, in, out); - if (res < 0) + if (res < 0) { + av_frame_free(&in); + av_frame_free(&out); return res; + } s->rgb_stride = rgb_stride / sizeof(int16_t); td.in = in; td.out = out; @@ -859,8 +867,11 @@ td.out_ss_h = av_pix_fmt_desc_get(out->format)->log2_chroma_h; if (s->yuv2yuv_passthrough) { res = av_frame_copy(out, in); - if (res < 0) + if (res < 0) { + av_frame_free(&in); + av_frame_free(&out); return res; + } } else { ctx->internal->execute(ctx, convert, &td, NULL, FFMIN((in->height + 1) >> 1, ff_filter_get_nb_threads(ctx))); @@ -887,7 +898,7 @@ return AVERROR(ENOMEM); if (s->user_format == AV_PIX_FMT_NONE) return ff_set_common_formats(ctx, formats); - res = ff_formats_ref(formats, &ctx->inputs[0]->out_formats); + res = ff_formats_ref(formats, &ctx->inputs[0]->outcfg.formats); if (res < 0) return res; formats = NULL; @@ -895,7 +906,7 @@ if (res < 0) return res; - return ff_formats_ref(formats, &ctx->outputs[0]->in_formats); + return ff_formats_ref(formats, &ctx->outputs[0]->incfg.formats); } static int config_props(AVFilterLink *outlink) @@ -969,6 +980,7 @@ ENUM("smpte432", AVCOL_PRI_SMPTE432, "prm"), ENUM("bt2020", AVCOL_PRI_BT2020, "prm"), ENUM("jedec-p22", AVCOL_PRI_JEDEC_P22, "prm"), + ENUM("ebu3213", AVCOL_PRI_EBU3213, "prm"), { "trc", "Output transfer characteristics", OFFSET(user_trc), AV_OPT_TYPE_INT, { .i64 = AVCOL_TRC_UNSPECIFIED }, @@ -980,6 +992,7 @@ ENUM("gamma28", AVCOL_TRC_GAMMA28, "trc"), ENUM("smpte170m", AVCOL_TRC_SMPTE170M, "trc"), ENUM("smpte240m", AVCOL_TRC_SMPTE240M, "trc"), + ENUM("linear", AVCOL_TRC_LINEAR, "trc"), ENUM("srgb", AVCOL_TRC_IEC61966_2_1, "trc"), ENUM("iec61966-2-1", AVCOL_TRC_IEC61966_2_1, "trc"), ENUM("xvycc", AVCOL_TRC_IEC61966_2_4, "trc"), diff -Nru ffmpeg-4.2.2/libavfilter/vf_colortemperature.c ffmpeg-4.4/libavfilter/vf_colortemperature.c --- ffmpeg-4.2.2/libavfilter/vf_colortemperature.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_colortemperature.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,370 @@ +/* + * 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 "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 + +typedef struct ColorTemperatureContext { + const AVClass *class; + + float temperature; + float mix; + float preserve; + + float color[3]; + + int step; + int depth; + uint8_t rgba_map[4]; + + int (*do_slice)(AVFilterContext *s, void *arg, + int jobnr, int nb_jobs); +} ColorTemperatureContext; + +static float saturate(float input) +{ + return av_clipf(input, 0.f, 1.f); +} + +static void kelvin2rgb(float k, float *rgb) +{ + float kelvin = k / 100.0f; + + if (kelvin <= 66.0f) { + rgb[0] = 1.0f; + rgb[1] = saturate(0.39008157876901960784f * logf(kelvin) - 0.63184144378862745098f); + } else { + const float t = fmaxf(kelvin - 60.0f, 0.0f); + rgb[0] = saturate(1.29293618606274509804f * powf(t, -0.1332047592f)); + rgb[1] = saturate(1.12989086089529411765f * powf(t, -0.0755148492f)); + } + + if (kelvin >= 66.0f) + rgb[2] = 1.0f; + else if (kelvin <= 19.0f) + rgb[2] = 0.0f; + else + rgb[2] = saturate(0.54320678911019607843f * logf(kelvin - 10.0f) - 1.19625408914f); +} + +static float lerpf(float v0, float v1, float f) +{ + return v0 + (v1 - v0) * f; +} + +#define PROCESS() \ + nr = r * color[0]; \ + ng = g * color[1]; \ + nb = b * color[2]; \ + \ + nr = lerpf(r, nr, mix); \ + ng = lerpf(g, ng, mix); \ + nb = lerpf(b, nb, mix); \ + \ + l0 = (FFMAX3(r, g, b) + FFMIN3(r, g, b)) + FLT_EPSILON; \ + l1 = (FFMAX3(nr, ng, nb) + FFMIN3(nr, ng, nb)) + FLT_EPSILON; \ + l = l0 / l1; \ + \ + r = nr * l; \ + g = ng * l; \ + b = nb * l; \ + \ + nr = lerpf(nr, r, preserve); \ + ng = lerpf(ng, g, preserve); \ + nb = lerpf(nb, b, preserve); + +static int temperature_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorTemperatureContext *s = ctx->priv; + AVFrame *frame = arg; + const int width = frame->width; + const int height = frame->height; + const float mix = s->mix; + const float preserve = s->preserve; + const float *color = s->color; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int glinesize = frame->linesize[0]; + const int blinesize = frame->linesize[1]; + const int rlinesize = frame->linesize[2]; + uint8_t *gptr = frame->data[0] + slice_start * glinesize; + uint8_t *bptr = frame->data[1] + slice_start * blinesize; + uint8_t *rptr = frame->data[2] + slice_start * rlinesize; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) { + float g = gptr[x]; + float b = bptr[x]; + float r = rptr[x]; + float nr, ng, nb; + float l0, l1, l; + + PROCESS() + + gptr[x] = av_clip_uint8(ng); + bptr[x] = av_clip_uint8(nb); + rptr[x] = av_clip_uint8(nr); + } + + gptr += glinesize; + bptr += blinesize; + rptr += rlinesize; + } + + return 0; +} + +static int temperature_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorTemperatureContext *s = ctx->priv; + AVFrame *frame = arg; + const int depth = s->depth; + const int width = frame->width; + const int height = frame->height; + const float preserve = s->preserve; + const float mix = s->mix; + const float *color = s->color; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int glinesize = frame->linesize[0] / sizeof(uint16_t); + const int blinesize = frame->linesize[1] / sizeof(uint16_t); + const int rlinesize = frame->linesize[2] / sizeof(uint16_t); + uint16_t *gptr = (uint16_t *)frame->data[0] + slice_start * glinesize; + uint16_t *bptr = (uint16_t *)frame->data[1] + slice_start * blinesize; + uint16_t *rptr = (uint16_t *)frame->data[2] + slice_start * rlinesize; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) { + float g = gptr[x]; + float b = bptr[x]; + float r = rptr[x]; + float nr, ng, nb; + float l0, l1, l; + + PROCESS() + + gptr[x] = av_clip_uintp2_c(ng, depth); + bptr[x] = av_clip_uintp2_c(nb, depth); + rptr[x] = av_clip_uintp2_c(nr, depth); + } + + gptr += glinesize; + bptr += blinesize; + rptr += rlinesize; + } + + return 0; +} + +static int temperature_slice8p(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorTemperatureContext *s = ctx->priv; + AVFrame *frame = arg; + const int step = s->step; + const int width = frame->width; + const int height = frame->height; + const float mix = s->mix; + const float preserve = s->preserve; + const float *color = s->color; + const uint8_t roffset = s->rgba_map[R]; + const uint8_t goffset = s->rgba_map[G]; + const uint8_t boffset = s->rgba_map[B]; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int linesize = frame->linesize[0]; + uint8_t *ptr = frame->data[0] + slice_start * linesize; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) { + float g = ptr[x * step + goffset]; + float b = ptr[x * step + boffset]; + float r = ptr[x * step + roffset]; + float nr, ng, nb; + float l0, l1, l; + + PROCESS() + + ptr[x * step + goffset] = av_clip_uint8(ng); + ptr[x * step + boffset] = av_clip_uint8(nb); + ptr[x * step + roffset] = av_clip_uint8(nr); + } + + ptr += linesize; + } + + return 0; +} + +static int temperature_slice16p(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorTemperatureContext *s = ctx->priv; + AVFrame *frame = arg; + const int step = s->step; + const int depth = s->depth; + const int width = frame->width; + const int height = frame->height; + const float preserve = s->preserve; + const float mix = s->mix; + const float *color = s->color; + const uint8_t roffset = s->rgba_map[R]; + const uint8_t goffset = s->rgba_map[G]; + const uint8_t boffset = s->rgba_map[B]; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int linesize = frame->linesize[0] / sizeof(uint16_t); + uint16_t *ptr = (uint16_t *)frame->data[0] + slice_start * linesize; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) { + float g = ptr[x * step + goffset]; + float b = ptr[x * step + boffset]; + float r = ptr[x * step + roffset]; + float nr, ng, nb; + float l0, l1, l; + + PROCESS() + + ptr[x * step + goffset] = av_clip_uintp2_c(ng, depth); + ptr[x * step + boffset] = av_clip_uintp2_c(nb, depth); + ptr[x * step + roffset] = av_clip_uintp2_c(nr, depth); + } + + ptr += linesize; + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + ColorTemperatureContext *s = ctx->priv; + + kelvin2rgb(s->temperature, s->color); + + ctx->internal->execute(ctx, s->do_slice, frame, NULL, + FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); + + return ff_filter_frame(ctx->outputs[0], frame); +} + +static av_cold int query_formats(AVFilterContext *ctx) +{ + 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_ARGB, AV_PIX_FMT_ABGR, + AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR, + AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, + AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, + AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48, + AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *formats = NULL; + + formats = ff_make_format_list(pixel_fmts); + if (!formats) + return AVERROR(ENOMEM); + + return ff_set_common_formats(ctx, formats); +} + +static av_cold int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ColorTemperatureContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR; + + s->step = desc->nb_components; + if (inlink->format == AV_PIX_FMT_RGB0 || + inlink->format == AV_PIX_FMT_0RGB || + inlink->format == AV_PIX_FMT_BGR0 || + inlink->format == AV_PIX_FMT_0BGR) + s->step = 4; + + s->depth = desc->comp[0].depth; + s->do_slice = s->depth <= 8 ? temperature_slice8 : temperature_slice16; + if (!planar) + s->do_slice = s->depth <= 8 ? temperature_slice8p : temperature_slice16p; + + ff_fill_rgba_map(s->rgba_map, inlink->format); + + return 0; +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = config_input, + .needs_writable = 1, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(ColorTemperatureContext, x) +#define VF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption colortemperature_options[] = { + { "temperature", "set the temperature in Kelvin", OFFSET(temperature), AV_OPT_TYPE_FLOAT, {.dbl=6500}, 1000, 40000, VF }, + { "mix", "set the mix with filtered output", OFFSET(mix), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, VF }, + { "pl", "set the amount of preserving lightness", OFFSET(preserve), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, VF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(colortemperature); + +AVFilter ff_vf_colortemperature = { + .name = "colortemperature", + .description = NULL_IF_CONFIG_SMALL("Adjust color temperature of video."), + .priv_size = sizeof(ColorTemperatureContext), + .priv_class = &colortemperature_class, + .query_formats = query_formats, + .inputs = inputs, + .outputs = outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_convolution.c ffmpeg-4.4/libavfilter/vf_convolution.c --- ffmpeg-4.2.2/libavfilter/vf_convolution.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_convolution.c 2021-04-08 21:28:40.000000000 +0000 @@ -25,50 +25,13 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avfilter.h" +#include "convolution.h" #include "formats.h" #include "internal.h" #include "video.h" -enum MatrixMode { - MATRIX_SQUARE, - MATRIX_ROW, - MATRIX_COLUMN, - MATRIX_NBMODES, -}; - -typedef struct ConvolutionContext { - const AVClass *class; - - char *matrix_str[4]; - float rdiv[4]; - float bias[4]; - int mode[4]; - float scale; - float delta; - int planes; - - int size[4]; - int depth; - int max; - int bpc; - int nb_planes; - int nb_threads; - int planewidth[4]; - int planeheight[4]; - int matrix[4][49]; - int matrix_length[4]; - int copy[4]; - - void (*setup[4])(int radius, const uint8_t *c[], const uint8_t *src, int stride, - int x, int width, int y, int height, int bpc); - void (*filter[4])(uint8_t *dst, int width, - float rdiv, float bias, const int *const matrix, - const uint8_t *c[], int peak, int radius, - int dstride, int stride); -} ConvolutionContext; - #define OFFSET(x) offsetof(ConvolutionContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption convolution_options[] = { { "0m", "set matrix for 1st plane", OFFSET(matrix_str[0]), AV_OPT_TYPE_STRING, {.str="0 0 0 0 1 0 0 0 0"}, 0, 0, FLAGS }, @@ -128,6 +91,7 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, @@ -146,16 +110,16 @@ static void filter16_prewitt(uint8_t *dstp, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { uint16_t *dst = (uint16_t *)dstp; int x; for (x = 0; x < width; x++) { - int suma = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[1][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * -1 + - AV_RN16A(&c[6][2 * x]) * 1 + AV_RN16A(&c[7][2 * x]) * 1 + AV_RN16A(&c[8][2 * x]) * 1; - int sumb = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -1 + - AV_RN16A(&c[5][2 * x]) * 1 + AV_RN16A(&c[6][2 * x]) * -1 + AV_RN16A(&c[8][2 * x]) * 1; + float suma = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[1][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * -1 + + AV_RN16A(&c[6][2 * x]) * 1 + AV_RN16A(&c[7][2 * x]) * 1 + AV_RN16A(&c[8][2 * x]) * 1; + float sumb = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -1 + + AV_RN16A(&c[5][2 * x]) * 1 + AV_RN16A(&c[6][2 * x]) * -1 + AV_RN16A(&c[8][2 * x]) * 1; dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak); } @@ -164,14 +128,14 @@ static void filter16_roberts(uint8_t *dstp, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { uint16_t *dst = (uint16_t *)dstp; int x; for (x = 0; x < width; x++) { - int suma = AV_RN16A(&c[0][2 * x]) * 1 + AV_RN16A(&c[1][2 * x]) * -1; - int sumb = AV_RN16A(&c[4][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -1; + float suma = AV_RN16A(&c[0][2 * x]) * 1 + AV_RN16A(&c[1][2 * x]) * -1; + float sumb = AV_RN16A(&c[4][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -1; dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak); } @@ -180,25 +144,74 @@ static void filter16_sobel(uint8_t *dstp, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { uint16_t *dst = (uint16_t *)dstp; int x; for (x = 0; x < width; x++) { - int suma = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[1][2 * x]) * -2 + AV_RN16A(&c[2][2 * x]) * -1 + - AV_RN16A(&c[6][2 * x]) * 1 + AV_RN16A(&c[7][2 * x]) * 2 + AV_RN16A(&c[8][2 * x]) * 1; - int sumb = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -2 + - AV_RN16A(&c[5][2 * x]) * 2 + AV_RN16A(&c[6][2 * x]) * -1 + AV_RN16A(&c[8][2 * x]) * 1; + float suma = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[1][2 * x]) * -2 + AV_RN16A(&c[2][2 * x]) * -1 + + AV_RN16A(&c[6][2 * x]) * 1 + AV_RN16A(&c[7][2 * x]) * 2 + AV_RN16A(&c[8][2 * x]) * 1; + float sumb = AV_RN16A(&c[0][2 * x]) * -1 + AV_RN16A(&c[2][2 * x]) * 1 + AV_RN16A(&c[3][2 * x]) * -2 + + AV_RN16A(&c[5][2 * x]) * 2 + AV_RN16A(&c[6][2 * x]) * -1 + AV_RN16A(&c[8][2 * x]) * 1; dst[x] = av_clip(sqrtf(suma*suma + sumb*sumb) * scale + delta, 0, peak); } } +static void filter16_kirsch(uint8_t *dstp, int width, + float scale, float delta, const int *const matrix, + const uint8_t *c[], int peak, int radius, + int dstride, int stride, int size) +{ + uint16_t *dst = (uint16_t *)dstp; + const uint16_t *c0 = (const uint16_t *)c[0], *c1 = (const uint16_t *)c[1], *c2 = (const uint16_t *)c[2]; + const uint16_t *c3 = (const uint16_t *)c[3], *c5 = (const uint16_t *)c[5]; + const uint16_t *c6 = (const uint16_t *)c[6], *c7 = (const uint16_t *)c[7], *c8 = (const uint16_t *)c[8]; + int x; + + for (x = 0; x < width; x++) { + int sum0 = c0[x] * 5 + c1[x] * 5 + c2[x] * 5 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * -3 + c7[x] * -3 + c8[x] * -3; + int sum1 = c0[x] * -3 + c1[x] * 5 + c2[x] * 5 + + c3[x] * 5 + c5[x] * -3 + + c6[x] * -3 + c7[x] * -3 + c8[x] * -3; + int sum2 = c0[x] * -3 + c1[x] * -3 + c2[x] * 5 + + c3[x] * 5 + c5[x] * 5 + + c6[x] * -3 + c7[x] * -3 + c8[x] * -3; + int sum3 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 + + c3[x] * 5 + c5[x] * 5 + + c6[x] * 5 + c7[x] * -3 + c8[x] * -3; + int sum4 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 + + c3[x] * -3 + c5[x] * 5 + + c6[x] * 5 + c7[x] * 5 + c8[x] * -3; + int sum5 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * 5 + c7[x] * 5 + c8[x] * 5; + int sum6 = c0[x] * 5 + c1[x] * -3 + c2[x] * -3 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * -3 + c7[x] * 5 + c8[x] * 5; + int sum7 = c0[x] * 5 + c1[x] * 5 + c2[x] * -3 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * -3 + c7[x] * -3 + c8[x] * 5; + + sum0 = FFMAX(sum0, sum1); + sum2 = FFMAX(sum2, sum3); + sum4 = FFMAX(sum4, sum5); + sum6 = FFMAX(sum6, sum7); + sum0 = FFMAX(sum0, sum2); + sum4 = FFMAX(sum4, sum6); + sum0 = FFMAX(sum0, sum4); + + dst[x] = av_clip(FFABS(sum0) * scale + delta, 0, peak); + } +} + static void filter_prewitt(uint8_t *dst, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2]; const uint8_t *c3 = c[3], *c5 = c[5]; @@ -206,10 +219,10 @@ int x; for (x = 0; x < width; x++) { - int suma = c0[x] * -1 + c1[x] * -1 + c2[x] * -1 + - c6[x] * 1 + c7[x] * 1 + c8[x] * 1; - int sumb = c0[x] * -1 + c2[x] * 1 + c3[x] * -1 + - c5[x] * 1 + c6[x] * -1 + c8[x] * 1; + float suma = c0[x] * -1 + c1[x] * -1 + c2[x] * -1 + + c6[x] * 1 + c7[x] * 1 + c8[x] * 1; + float sumb = c0[x] * -1 + c2[x] * 1 + c3[x] * -1 + + c5[x] * 1 + c6[x] * -1 + c8[x] * 1; dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta); } @@ -218,13 +231,13 @@ static void filter_roberts(uint8_t *dst, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { int x; for (x = 0; x < width; x++) { - int suma = c[0][x] * 1 + c[1][x] * -1; - int sumb = c[4][x] * 1 + c[3][x] * -1; + float suma = c[0][x] * 1 + c[1][x] * -1; + float sumb = c[4][x] * 1 + c[3][x] * -1; dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta); } @@ -233,7 +246,7 @@ static void filter_sobel(uint8_t *dst, int width, float scale, float delta, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2]; const uint8_t *c3 = c[3], *c5 = c[5]; @@ -241,19 +254,67 @@ int x; for (x = 0; x < width; x++) { - int suma = c0[x] * -1 + c1[x] * -2 + c2[x] * -1 + - c6[x] * 1 + c7[x] * 2 + c8[x] * 1; - int sumb = c0[x] * -1 + c2[x] * 1 + c3[x] * -2 + - c5[x] * 2 + c6[x] * -1 + c8[x] * 1; + float suma = c0[x] * -1 + c1[x] * -2 + c2[x] * -1 + + c6[x] * 1 + c7[x] * 2 + c8[x] * 1; + float sumb = c0[x] * -1 + c2[x] * 1 + c3[x] * -2 + + c5[x] * 2 + c6[x] * -1 + c8[x] * 1; dst[x] = av_clip_uint8(sqrtf(suma*suma + sumb*sumb) * scale + delta); } } +static void filter_kirsch(uint8_t *dst, int width, + float scale, float delta, const int *const matrix, + const uint8_t *c[], int peak, int radius, + int dstride, int stride, int size) +{ + const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2]; + const uint8_t *c3 = c[3], *c5 = c[5]; + const uint8_t *c6 = c[6], *c7 = c[7], *c8 = c[8]; + int x; + + for (x = 0; x < width; x++) { + int sum0 = c0[x] * 5 + c1[x] * 5 + c2[x] * 5 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * -3 + c7[x] * -3 + c8[x] * -3; + int sum1 = c0[x] * -3 + c1[x] * 5 + c2[x] * 5 + + c3[x] * 5 + c5[x] * -3 + + c6[x] * -3 + c7[x] * -3 + c8[x] * -3; + int sum2 = c0[x] * -3 + c1[x] * -3 + c2[x] * 5 + + c3[x] * 5 + c5[x] * 5 + + c6[x] * -3 + c7[x] * -3 + c8[x] * -3; + int sum3 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 + + c3[x] * 5 + c5[x] * 5 + + c6[x] * 5 + c7[x] * -3 + c8[x] * -3; + int sum4 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 + + c3[x] * -3 + c5[x] * 5 + + c6[x] * 5 + c7[x] * 5 + c8[x] * -3; + int sum5 = c0[x] * -3 + c1[x] * -3 + c2[x] * -3 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * 5 + c7[x] * 5 + c8[x] * 5; + int sum6 = c0[x] * 5 + c1[x] * -3 + c2[x] * -3 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * -3 + c7[x] * 5 + c8[x] * 5; + int sum7 = c0[x] * 5 + c1[x] * 5 + c2[x] * -3 + + c3[x] * -3 + c5[x] * -3 + + c6[x] * -3 + c7[x] * -3 + c8[x] * 5; + + sum0 = FFMAX(sum0, sum1); + sum2 = FFMAX(sum2, sum3); + sum4 = FFMAX(sum4, sum5); + sum6 = FFMAX(sum6, sum7); + sum0 = FFMAX(sum0, sum2); + sum4 = FFMAX(sum4, sum6); + sum0 = FFMAX(sum0, sum4); + + dst[x] = av_clip_uint8(FFABS(sum0) * scale + delta); + } +} + static void filter16_3x3(uint8_t *dstp, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { uint16_t *dst = (uint16_t *)dstp; int x; @@ -276,7 +337,7 @@ static void filter16_5x5(uint8_t *dstp, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { uint16_t *dst = (uint16_t *)dstp; int x; @@ -295,7 +356,7 @@ static void filter16_7x7(uint8_t *dstp, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { uint16_t *dst = (uint16_t *)dstp; int x; @@ -314,7 +375,7 @@ static void filter16_row(uint8_t *dstp, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { uint16_t *dst = (uint16_t *)dstp; int x; @@ -333,19 +394,24 @@ static void filter16_column(uint8_t *dstp, int height, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { + DECLARE_ALIGNED(64, int, sum)[16]; uint16_t *dst = (uint16_t *)dstp; - int y; + const int width = FFMIN(16, size); - for (y = 0; y < height; y++) { - int i, sum = 0; + for (int y = 0; y < height; y++) { - for (i = 0; i < 2 * radius + 1; i++) - sum += AV_RN16A(&c[i][0 + y * stride]) * matrix[i]; + memset(sum, 0, sizeof(sum)); + for (int i = 0; i < 2 * radius + 1; i++) { + for (int off16 = 0; off16 < width; off16++) + sum[off16] += AV_RN16A(&c[i][0 + y * stride + off16 * 2]) * matrix[i]; + } - sum = (int)(sum * rdiv + bias + 0.5f); - dst[0] = av_clip(sum, 0, peak); + for (int off16 = 0; off16 < width; off16++) { + sum[off16] = (int)(sum[off16] * rdiv + bias + 0.5f); + dst[off16] = av_clip(sum[off16], 0, peak); + } dst += dstride / 2; } } @@ -353,7 +419,7 @@ static void filter_7x7(uint8_t *dst, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { int x; @@ -371,7 +437,7 @@ static void filter_5x5(uint8_t *dst, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { int x; @@ -389,7 +455,7 @@ static void filter_3x3(uint8_t *dst, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2]; const uint8_t *c3 = c[3], *c4 = c[4], *c5 = c[5]; @@ -408,7 +474,7 @@ static void filter_row(uint8_t *dst, int width, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { int x; @@ -426,18 +492,22 @@ static void filter_column(uint8_t *dst, int height, float rdiv, float bias, const int *const matrix, const uint8_t *c[], int peak, int radius, - int dstride, int stride) + int dstride, int stride, int size) { - int y; + DECLARE_ALIGNED(64, int, sum)[16]; - for (y = 0; y < height; y++) { - int i, sum = 0; + for (int y = 0; y < height; y++) { + memset(sum, 0, sizeof(sum)); - for (i = 0; i < 2 * radius + 1; i++) - sum += c[i][0 + y * stride] * matrix[i]; + for (int i = 0; i < 2 * radius + 1; i++) { + for (int off16 = 0; off16 < 16; off16++) + sum[off16] += c[i][0 + y * stride + off16] * matrix[i]; + } - sum = (int)(sum * rdiv + bias + 0.5f); - dst[0] = av_clip_uint8(sum); + for (int off16 = 0; off16 < 16; off16++) { + sum[off16] = (int)(sum[off16] * rdiv + bias + 0.5f); + dst[off16] = av_clip_uint8(sum[off16]); + } dst += dstride; } } @@ -544,6 +614,7 @@ const int dst_pos = slice_start * (mode == MATRIX_COLUMN ? bpc : dstride); uint8_t *dst = out->data[plane] + dst_pos; const int *matrix = s->matrix[plane]; + const int step = mode == MATRIX_COLUMN ? 16 : 1; const uint8_t *c[49]; int y, x; @@ -556,32 +627,31 @@ width * bpc, slice_end - slice_start); continue; } - - for (y = slice_start; y < slice_end; y++) { + for (y = slice_start; y < slice_end; y += step) { const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : radius * bpc; - const int yoff = mode == MATRIX_COLUMN ? radius * stride : 0; + const int yoff = mode == MATRIX_COLUMN ? radius * dstride : 0; for (x = 0; x < radius; x++) { const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc; - const int yoff = mode == MATRIX_COLUMN ? x * stride : 0; + const int yoff = mode == MATRIX_COLUMN ? x * dstride : 0; s->setup[plane](radius, c, src, stride, x, width, y, height, bpc); s->filter[plane](dst + yoff + xoff, 1, rdiv, bias, matrix, c, s->max, radius, - dstride, stride); + dstride, stride, slice_end - step); } s->setup[plane](radius, c, src, stride, radius, width, y, height, bpc); s->filter[plane](dst + yoff + xoff, sizew - 2 * radius, rdiv, bias, matrix, c, s->max, radius, - dstride, stride); + dstride, stride, slice_end - step); for (x = sizew - radius; x < sizew; x++) { const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc; - const int yoff = mode == MATRIX_COLUMN ? x * stride : 0; + const int yoff = mode == MATRIX_COLUMN ? x * dstride : 0; s->setup[plane](radius, c, src, stride, x, width, y, height, bpc); s->filter[plane](dst + yoff + xoff, 1, rdiv, bias, matrix, c, s->max, radius, - dstride, stride); + dstride, stride, slice_end - step); } if (mode != MATRIX_COLUMN) dst += dstride; @@ -625,6 +695,9 @@ 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++) @@ -637,6 +710,10 @@ 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; } return 0; @@ -677,20 +754,25 @@ float sum = 0; p = s->matrix_str[i]; - while (s->matrix_length[i] < 49) { - if (!(arg = av_strtok(p, " ", &saveptr))) - break; - - p = NULL; - sscanf(arg, "%d", &matrix[s->matrix_length[i]]); - sum += matrix[s->matrix_length[i]]; - s->matrix_length[i]++; - } + if (p) { + s->matrix_length[i] = 0; - if (!(s->matrix_length[i] & 1)) { - av_log(ctx, AV_LOG_ERROR, "number of matrix elements must be odd\n"); - return AVERROR(EINVAL); + while (s->matrix_length[i] < 49) { + if (!(arg = av_strtok(p, " |", &saveptr))) + break; + + p = NULL; + sscanf(arg, "%d", &matrix[s->matrix_length[i]]); + sum += matrix[s->matrix_length[i]]; + s->matrix_length[i]++; + } + + if (!(s->matrix_length[i] & 1)) { + av_log(ctx, AV_LOG_ERROR, "number of matrix elements must be odd\n"); + return AVERROR(EINVAL); + } } + if (s->mode[i] == MATRIX_ROW) { s->filter[i] = filter_row; s->setup[i] = setup_row; @@ -701,24 +783,31 @@ s->size[i] = s->matrix_length[i]; } else if (s->matrix_length[i] == 9) { s->size[i] = 3; - if (!memcmp(matrix, same3x3, sizeof(same3x3))) + + if (!memcmp(matrix, same3x3, sizeof(same3x3))) { s->copy[i] = 1; - else + } else { s->filter[i] = filter_3x3; + s->copy[i] = 0; + } s->setup[i] = setup_3x3; } else if (s->matrix_length[i] == 25) { s->size[i] = 5; - if (!memcmp(matrix, same5x5, sizeof(same5x5))) + if (!memcmp(matrix, same5x5, sizeof(same5x5))) { s->copy[i] = 1; - else + } else { s->filter[i] = filter_5x5; + s->copy[i] = 0; + } s->setup[i] = setup_5x5; } else if (s->matrix_length[i] == 49) { s->size[i] = 7; - if (!memcmp(matrix, same7x7, sizeof(same7x7))) + if (!memcmp(matrix, same7x7, sizeof(same7x7))) { s->copy[i] = 1; - else + } else { s->filter[i] = filter_7x7; + s->copy[i] = 0; + } s->setup[i] = setup_7x7; } else { return AVERROR(EINVAL); @@ -765,11 +854,34 @@ s->rdiv[i] = s->scale; s->bias[i] = s->delta; } + } 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->size[i] = 3; + s->setup[i] = setup_3x3; + s->rdiv[i] = s->scale; + s->bias[i] = s->delta; + } } return 0; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return init(ctx); +} + static const AVFilterPad convolution_inputs[] = { { .name = "default", @@ -800,19 +912,23 @@ .inputs = convolution_inputs, .outputs = convolution_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; #endif /* CONFIG_CONVOLUTION_FILTER */ -#if CONFIG_PREWITT_FILTER +#if CONFIG_PREWITT_FILTER || CONFIG_ROBERTS_FILTER || CONFIG_SOBEL_FILTER -static const AVOption prewitt_options[] = { +static const AVOption prewitt_roberts_sobel_options[] = { { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15}, 0, 15, FLAGS}, { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 65535, FLAGS}, { "delta", "set delta", OFFSET(delta), AV_OPT_TYPE_FLOAT, {.dbl=0}, -65535, 65535, FLAGS}, { NULL } }; +#if CONFIG_PREWITT_FILTER + +#define prewitt_options prewitt_roberts_sobel_options AVFILTER_DEFINE_CLASS(prewitt); AVFilter ff_vf_prewitt = { @@ -825,19 +941,14 @@ .inputs = convolution_inputs, .outputs = convolution_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; #endif /* CONFIG_PREWITT_FILTER */ #if CONFIG_SOBEL_FILTER -static const AVOption sobel_options[] = { - { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15}, 0, 15, FLAGS}, - { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 65535, FLAGS}, - { "delta", "set delta", OFFSET(delta), AV_OPT_TYPE_FLOAT, {.dbl=0}, -65535, 65535, FLAGS}, - { NULL } -}; - +#define sobel_options prewitt_roberts_sobel_options AVFILTER_DEFINE_CLASS(sobel); AVFilter ff_vf_sobel = { @@ -850,19 +961,14 @@ .inputs = convolution_inputs, .outputs = convolution_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; #endif /* CONFIG_SOBEL_FILTER */ #if CONFIG_ROBERTS_FILTER -static const AVOption roberts_options[] = { - { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15}, 0, 15, FLAGS}, - { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 65535, FLAGS}, - { "delta", "set delta", OFFSET(delta), AV_OPT_TYPE_FLOAT, {.dbl=0}, -65535, 65535, FLAGS}, - { NULL } -}; - +#define roberts_options prewitt_roberts_sobel_options AVFILTER_DEFINE_CLASS(roberts); AVFilter ff_vf_roberts = { @@ -875,6 +981,29 @@ .inputs = convolution_inputs, .outputs = convolution_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; #endif /* CONFIG_ROBERTS_FILTER */ + +#if CONFIG_KIRSCH_FILTER + +#define kirsch_options prewitt_roberts_sobel_options +AVFILTER_DEFINE_CLASS(kirsch); + +AVFilter ff_vf_kirsch = { + .name = "kirsch", + .description = NULL_IF_CONFIG_SMALL("Apply kirsch operator."), + .priv_size = sizeof(ConvolutionContext), + .priv_class = &kirsch_class, + .init = init, + .query_formats = query_formats, + .inputs = convolution_inputs, + .outputs = convolution_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, +}; + +#endif /* CONFIG_KIRSCH_FILTER */ + +#endif /* CONFIG_PREWITT_FILTER || CONFIG_ROBERTS_FILTER || CONFIG_SOBEL_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/vf_convolve.c ffmpeg-4.4/libavfilter/vf_convolve.c --- ffmpeg-4.2.2/libavfilter/vf_convolve.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_convolve.c 2020-07-11 10:39:30.000000000 +0000 @@ -590,7 +590,9 @@ for (j = 0; j < MAX_THREADS; j++) { av_fft_end(s->fft[i][j]); + s->fft[i][j] = NULL; av_fft_end(s->ifft[i][j]); + s->ifft[i][j] = NULL; } } diff -Nru ffmpeg-4.2.2/libavfilter/vf_copy.c ffmpeg-4.4/libavfilter/vf_copy.c --- ffmpeg-4.2.2/libavfilter/vf_copy.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_copy.c 2021-04-08 21:28:40.000000000 +0000 @@ -30,17 +30,12 @@ static int query_formats(AVFilterContext *ctx) { AVFilterFormats *formats = NULL; - int fmt; - - for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); - int ret; - if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) - continue; - if ((ret = ff_add_format(&formats, fmt)) < 0) - return ret; - } + int ret; + ret = ff_formats_pixdesc_filter(&formats, 0, + AV_PIX_FMT_FLAG_HWACCEL); + if (ret < 0) + return ret; return ff_set_common_formats(ctx, formats); } @@ -48,15 +43,25 @@ { AVFilterLink *outlink = inlink->dst->outputs[0]; AVFrame *out = ff_get_video_buffer(outlink, in->width, in->height); + int ret; if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); + ret = AVERROR(ENOMEM); + goto fail; } - av_frame_copy_props(out, in); - av_frame_copy(out, in); + + ret = av_frame_copy_props(out, in); + if (ret < 0) + goto fail; + ret = av_frame_copy(out, in); + if (ret < 0) + goto fail; av_frame_free(&in); return ff_filter_frame(outlink, out); +fail: + av_frame_free(&in); + av_frame_free(&out); + return ret; } static const AVFilterPad avfilter_vf_copy_inputs[] = { diff -Nru ffmpeg-4.2.2/libavfilter/vf_coreimage.m ffmpeg-4.4/libavfilter/vf_coreimage.m --- ffmpeg-4.2.2/libavfilter/vf_coreimage.m 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_coreimage.m 2021-04-08 21:28:40.000000000 +0000 @@ -149,8 +149,8 @@ return AVERROR(ENOMEM); } - if ((ret = ff_formats_ref(inout_formats, &fctx->inputs[0]->out_formats)) < 0 || - (ret = ff_formats_ref(inout_formats, &fctx->outputs[0]->in_formats)) < 0) { + if ((ret = ff_formats_ref(inout_formats, &fctx->inputs[0]->outcfg.formats)) < 0 || + (ret = ff_formats_ref(inout_formats, &fctx->outputs[0]->incfg.formats)) < 0) { return ret; } @@ -171,7 +171,7 @@ return AVERROR(ENOMEM); } - if ((ret = ff_formats_ref(inout_formats, &fctx->outputs[0]->in_formats)) < 0) { + if ((ret = ff_formats_ref(inout_formats, &fctx->outputs[0]->incfg.formats)) < 0) { return ret; } @@ -486,6 +486,7 @@ av_log(ctx, AV_LOG_DEBUG, "Filter_string: %s\n", ctx->filter_string); ret = av_dict_parse_string(&filter_dict, ctx->filter_string, "@", "#", AV_DICT_MULTIKEY); // parse filter_name:all_filter_options if (ret) { + av_dict_free(&filter_dict); av_log(ctx, AV_LOG_ERROR, "Parsing of filters failed.\n"); return AVERROR(EIO); } @@ -507,6 +508,7 @@ if (strncmp(f->value, "default", 7)) { // not default ret = av_dict_parse_string(&filter_options, f->value, "=", "@", 0); // parse option_name:option_value if (ret) { + av_dict_free(&filter_options); av_log(ctx, AV_LOG_ERROR, "Parsing of filter options for \"%s\" failed.\n", f->key); return AVERROR(EIO); } diff -Nru ffmpeg-4.2.2/libavfilter/vf_crop.c ffmpeg-4.4/libavfilter/vf_crop.c --- ffmpeg-4.2.2/libavfilter/vf_crop.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_crop.c 2020-07-11 10:39:30.000000000 +0000 @@ -94,24 +94,11 @@ static int query_formats(AVFilterContext *ctx) { AVFilterFormats *formats = NULL; - int fmt, ret; - - for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); - if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) - continue; - if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { - // Not usable if there is any subsampling but the format is - // not planar (e.g. YUYV422). - if ((desc->log2_chroma_w || desc->log2_chroma_h) && - !(desc->flags & AV_PIX_FMT_FLAG_PLANAR)) - continue; - } - ret = ff_add_format(&formats, fmt); - if (ret < 0) - return ret; - } + int ret; + ret = ff_formats_pixdesc_filter(&formats, 0, AV_PIX_FMT_FLAG_BITSTREAM | FF_PIX_FMT_FLAG_SW_FLAT_SUB); + if (ret < 0) + return ret; return ff_set_common_formats(ctx, formats); } @@ -174,10 +161,9 @@ s->vsub = pix_desc->log2_chroma_h; } - if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr), - var_names, s->var_values, - NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) - goto fail_expr; + av_expr_parse_and_eval(&res, (expr = s->w_expr), + var_names, s->var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx); s->var_values[VAR_OUT_W] = s->var_values[VAR_OW] = res; if ((ret = av_expr_parse_and_eval(&res, (expr = s->h_expr), var_names, s->var_values, @@ -244,7 +230,7 @@ return 0; fail_expr: - av_log(NULL, AV_LOG_ERROR, "Error when evaluating the expression '%s'\n", expr); + av_log(ctx, AV_LOG_ERROR, "Error when evaluating the expression '%s'\n", expr); return ret; } @@ -371,14 +357,15 @@ #define OFFSET(x) offsetof(CropContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption crop_options[] = { - { "out_w", "set the width crop area expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "w", "set the width crop area expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "out_h", "set the height crop area expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "h", "set the height crop area expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "x", "set the x crop area expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "(in_w-out_w)/2"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "y", "set the y crop area expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "(in_h-out_h)/2"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "out_w", "set the width crop area expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, 0, 0, TFLAGS }, + { "w", "set the width crop area expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, 0, 0, TFLAGS }, + { "out_h", "set the height crop area expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, 0, 0, TFLAGS }, + { "h", "set the height crop area expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, 0, 0, TFLAGS }, + { "x", "set the x crop area expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "(in_w-out_w)/2"}, 0, 0, TFLAGS }, + { "y", "set the y crop area expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "(in_h-out_h)/2"}, 0, 0, TFLAGS }, { "keep_aspect", "keep aspect ratio", OFFSET(keep_aspect), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { "exact", "do exact cropping", OFFSET(exact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { NULL } diff -Nru ffmpeg-4.2.2/libavfilter/vf_cropdetect.c ffmpeg-4.4/libavfilter/vf_cropdetect.c --- ffmpeg-4.2.2/libavfilter/vf_cropdetect.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_cropdetect.c 2021-04-08 21:28:40.000000000 +0000 @@ -37,6 +37,7 @@ int x1, y1, x2, y2; float limit; int round; + int skip; int reset_count; int frame_nb; int max_pixsteps[4]; @@ -127,10 +128,10 @@ { CropDetectContext *s = ctx->priv; - s->frame_nb = -2; + s->frame_nb = -1 * s->skip; - av_log(ctx, AV_LOG_VERBOSE, "limit:%f round:%d reset_count:%d\n", - s->limit, s->round, s->reset_count); + av_log(ctx, AV_LOG_VERBOSE, "limit:%f round:%d skip:%d reset_count:%d\n", + s->limit, s->round, s->skip, s->reset_count); return 0; } @@ -167,7 +168,7 @@ int outliers, last_y; int limit = lrint(s->limit); - // ignore first 2 frames - they may be empty + // ignore first s->skip frames if (++s->frame_nb > 0) { metadata = &frame->metadata; @@ -247,6 +248,7 @@ { "limit", "Threshold below which the pixel is considered black", OFFSET(limit), AV_OPT_TYPE_FLOAT, { .dbl = 24.0/255 }, 0, 65535, FLAGS }, { "round", "Value by which the width/height should be divisible", OFFSET(round), AV_OPT_TYPE_INT, { .i64 = 16 }, 0, INT_MAX, FLAGS }, { "reset", "Recalculate the crop area after this many frames", OFFSET(reset_count), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { "skip", "Number of initial frames to skip", OFFSET(skip), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, INT_MAX, FLAGS }, { "reset_count", "Recalculate the crop area after this many frames",OFFSET(reset_count),AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, INT_MAX, FLAGS }, { "max_outliers", "Threshold count of outliers", OFFSET(max_outliers),AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, { NULL } diff -Nru ffmpeg-4.2.2/libavfilter/vf_curves.c ffmpeg-4.4/libavfilter/vf_curves.c --- ffmpeg-4.2.2/libavfilter/vf_curves.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_curves.c 2021-04-08 21:28:40.000000000 +0000 @@ -69,8 +69,10 @@ uint8_t rgba_map[4]; int step; char *plot_filename; + int saved_plot; int is_16bit; int depth; + int parsed_psfile; int (*filter_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } CurvesContext; @@ -80,20 +82,20 @@ } ThreadData; #define OFFSET(x) offsetof(CurvesContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption curves_options[] = { { "preset", "select a color curves preset", OFFSET(preset), AV_OPT_TYPE_INT, {.i64=PRESET_NONE}, PRESET_NONE, NB_PRESETS-1, FLAGS, "preset_name" }, - { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_NONE}, INT_MIN, INT_MAX, FLAGS, "preset_name" }, - { "color_negative", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_COLOR_NEGATIVE}, INT_MIN, INT_MAX, FLAGS, "preset_name" }, - { "cross_process", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_CROSS_PROCESS}, INT_MIN, INT_MAX, FLAGS, "preset_name" }, - { "darker", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_DARKER}, INT_MIN, INT_MAX, FLAGS, "preset_name" }, - { "increase_contrast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_INCREASE_CONTRAST}, INT_MIN, INT_MAX, FLAGS, "preset_name" }, - { "lighter", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_LIGHTER}, INT_MIN, INT_MAX, FLAGS, "preset_name" }, - { "linear_contrast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_LINEAR_CONTRAST}, INT_MIN, INT_MAX, FLAGS, "preset_name" }, - { "medium_contrast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_MEDIUM_CONTRAST}, INT_MIN, INT_MAX, FLAGS, "preset_name" }, - { "negative", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_NEGATIVE}, INT_MIN, INT_MAX, FLAGS, "preset_name" }, - { "strong_contrast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_STRONG_CONTRAST}, INT_MIN, INT_MAX, FLAGS, "preset_name" }, - { "vintage", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_VINTAGE}, INT_MIN, INT_MAX, FLAGS, "preset_name" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_NONE}, 0, 0, FLAGS, "preset_name" }, + { "color_negative", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_COLOR_NEGATIVE}, 0, 0, FLAGS, "preset_name" }, + { "cross_process", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_CROSS_PROCESS}, 0, 0, FLAGS, "preset_name" }, + { "darker", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_DARKER}, 0, 0, FLAGS, "preset_name" }, + { "increase_contrast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_INCREASE_CONTRAST}, 0, 0, FLAGS, "preset_name" }, + { "lighter", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_LIGHTER}, 0, 0, FLAGS, "preset_name" }, + { "linear_contrast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_LINEAR_CONTRAST}, 0, 0, FLAGS, "preset_name" }, + { "medium_contrast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_MEDIUM_CONTRAST}, 0, 0, FLAGS, "preset_name" }, + { "negative", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_NEGATIVE}, 0, 0, FLAGS, "preset_name" }, + { "strong_contrast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_STRONG_CONTRAST}, 0, 0, FLAGS, "preset_name" }, + { "vintage", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_VINTAGE}, 0, 0, FLAGS, "preset_name" }, { "master","set master points coordinates",OFFSET(comp_points_str[NB_COMP]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS }, { "m", "set master points coordinates",OFFSET(comp_points_str[NB_COMP]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS }, { "red", "set red points coordinates", OFFSET(comp_points_str[0]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS }, @@ -486,10 +488,11 @@ } } - if (curves->psfile) { + if (curves->psfile && !curves->parsed_psfile) { ret = parse_psfile(ctx, curves->psfile); if (ret < 0) return ret; + curves->parsed_psfile = 1; } if (curves->preset != PRESET_NONE) { @@ -504,6 +507,7 @@ SET_COMP_IF_NOT_SET(1, g); SET_COMP_IF_NOT_SET(2, b); SET_COMP_IF_NOT_SET(3, master); + curves->preset = PRESET_NONE; } return 0; @@ -664,7 +668,8 @@ curves->filter_slice = desc->flags & AV_PIX_FMT_FLAG_PLANAR ? filter_slice_planar : filter_slice_packed; for (i = 0; i < NB_COMP + 1; i++) { - curves->graph[i] = av_mallocz_array(curves->lut_size, sizeof(*curves->graph[0])); + if (!curves->graph[i]) + curves->graph[i] = av_mallocz_array(curves->lut_size, sizeof(*curves->graph[0])); if (!curves->graph[i]) return AVERROR(ENOMEM); ret = parse_points_str(ctx, comp_points + i, curves->comp_points_str[i], curves->lut_size); @@ -699,8 +704,10 @@ } } - if (curves->plot_filename) + if (curves->plot_filename && !curves->saved_plot) { dump_curves(curves->plot_filename, curves->graph, comp_points, curves->lut_size); + curves->saved_plot = 1; + } for (i = 0; i < NB_COMP + 1; i++) { struct keypoint *point = comp_points[i]; @@ -743,6 +750,42 @@ 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) +{ + CurvesContext *curves = ctx->priv; + int ret; + + if (!strcmp(cmd, "plot")) { + curves->saved_plot = 0; + } else if (!strcmp(cmd, "all") || !strcmp(cmd, "preset") || !strcmp(cmd, "psfile")) { + if (!strcmp(cmd, "psfile")) + curves->parsed_psfile = 0; + av_freep(&curves->comp_points_str_all); + av_freep(&curves->comp_points_str[0]); + av_freep(&curves->comp_points_str[1]); + av_freep(&curves->comp_points_str[2]); + av_freep(&curves->comp_points_str[NB_COMP]); + } else if (!strcmp(cmd, "red") || !strcmp(cmd, "r")) { + av_freep(&curves->comp_points_str[0]); + } else if (!strcmp(cmd, "green") || !strcmp(cmd, "g")) { + av_freep(&curves->comp_points_str[1]); + } else if (!strcmp(cmd, "blue") || !strcmp(cmd, "b")) { + av_freep(&curves->comp_points_str[2]); + } else if (!strcmp(cmd, "master") || !strcmp(cmd, "m")) { + av_freep(&curves->comp_points_str[NB_COMP]); + } + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + ret = curves_init(ctx); + if (ret < 0) + return ret; + return config_input(ctx->inputs[0]); +} + static av_cold void curves_uninit(AVFilterContext *ctx) { int i; @@ -781,4 +824,5 @@ .outputs = curves_outputs, .priv_class = &curves_class, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_datascope.c ffmpeg-4.4/libavfilter/vf_datascope.c --- ffmpeg-4.2.2/libavfilter/vf_datascope.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_datascope.c 2021-04-08 21:28:40.000000000 +0000 @@ -35,7 +35,9 @@ int ow, oh; int x, y; int mode; + int dformat; int axis; + int components; float opacity; int nb_planes; @@ -54,18 +56,23 @@ #define OFFSET(x) offsetof(DatascopeContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGSR AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption datascope_options[] = { { "size", "set output size", OFFSET(ow), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, FLAGS }, { "s", "set output size", OFFSET(ow), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, FLAGS }, - { "x", "set x offset", OFFSET(x), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, - { "y", "set y offset", OFFSET(y), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, - { "mode", "set scope mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "mode" }, - { "mono", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, - { "color", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" }, - { "color2", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "mode" }, - { "axis", "draw column/row numbers", OFFSET(axis), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, - { "opacity", "set background opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, + { "x", "set x offset", OFFSET(x), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGSR }, + { "y", "set y offset", OFFSET(y), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGSR }, + { "mode", "set scope mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGSR, "mode" }, + { "mono", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGSR, "mode" }, + { "color", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGSR, "mode" }, + { "color2", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGSR, "mode" }, + { "axis", "draw column/row numbers", OFFSET(axis), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGSR }, + { "opacity", "set background opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGSR }, + { "format", "set display number format", OFFSET(dformat), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGSR, "format" }, + { "hex", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGSR, "format" }, + { "dec", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGSR, "format" }, + { "components", "set components to display", OFFSET(components), AV_OPT_TYPE_INT, {.i64=15}, 1, 15, FLAGSR }, { NULL } }; @@ -164,7 +171,7 @@ typedef struct ThreadData { AVFrame *in, *out; - int xoff, yoff; + int xoff, yoff, PP; } ThreadData; static int filter_color2(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) @@ -175,13 +182,15 @@ ThreadData *td = arg; AVFrame *in = td->in; AVFrame *out = td->out; + const int PP = td->PP; const int xoff = td->xoff; const int yoff = td->yoff; const int P = FFMAX(s->nb_planes, s->nb_comps); const int C = s->chars; + const int D = ((s->chars - s->dformat) >> 2) + s->dformat * 2; const int W = (outlink->w - xoff) / (C * 10); - const int H = (outlink->h - yoff) / (P * 12); - const char *format[2] = {"%02X\n", "%04X\n"}; + const int H = (outlink->h - yoff) / (PP * 12); + const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"}; const int slice_start = (W * jobnr) / nb_jobs; const int slice_end = (W * (jobnr+1)) / nb_jobs; int x, y, p; @@ -190,18 +199,21 @@ for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) { FFDrawColor color = { { 0 } }; FFDrawColor reverse = { { 0 } }; - int value[4] = { 0 }; + int value[4] = { 0 }, pp = 0; s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value); s->reverse_color(&s->draw, &color, &reverse); ff_fill_rectangle(&s->draw, &color, out->data, out->linesize, - xoff + x * C * 10, yoff + y * P * 12, C * 10, P * 12); + xoff + x * C * 10, yoff + y * PP * 12, C * 10, PP * 12); for (p = 0; p < P; p++) { char text[256]; - snprintf(text, sizeof(text), format[C>>2], value[p]); - draw_text(&s->draw, out, &reverse, xoff + x * C * 10 + 2, yoff + y * P * 12 + p * 10 + 2, text, 0); + if (!(s->components & (1 << p))) + continue; + snprintf(text, sizeof(text), format[D], value[p]); + draw_text(&s->draw, out, &reverse, xoff + x * C * 10 + 2, yoff + y * PP * 12 + pp * 10 + 2, text, 0); + pp++; } } } @@ -217,13 +229,15 @@ ThreadData *td = arg; AVFrame *in = td->in; AVFrame *out = td->out; + const int PP = td->PP; const int xoff = td->xoff; const int yoff = td->yoff; const int P = FFMAX(s->nb_planes, s->nb_comps); const int C = s->chars; + const int D = ((s->chars - s->dformat) >> 2) + s->dformat * 2; const int W = (outlink->w - xoff) / (C * 10); - const int H = (outlink->h - yoff) / (P * 12); - const char *format[2] = {"%02X\n", "%04X\n"}; + const int H = (outlink->h - yoff) / (PP * 12); + const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"}; const int slice_start = (W * jobnr) / nb_jobs; const int slice_end = (W * (jobnr+1)) / nb_jobs; int x, y, p; @@ -231,15 +245,18 @@ for (y = 0; y < H && (y + s->y < inlink->h); y++) { for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) { FFDrawColor color = { { 0 } }; - int value[4] = { 0 }; + int value[4] = { 0 }, pp = 0; s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value); for (p = 0; p < P; p++) { char text[256]; - snprintf(text, sizeof(text), format[C>>2], value[p]); - draw_text(&s->draw, out, &color, xoff + x * C * 10 + 2, yoff + y * P * 12 + p * 10 + 2, text, 0); + if (!(s->components & (1 << p))) + continue; + snprintf(text, sizeof(text), format[D], value[p]); + draw_text(&s->draw, out, &color, xoff + x * C * 10 + 2, yoff + y * PP * 12 + pp * 10 + 2, text, 0); + pp++; } } } @@ -255,13 +272,15 @@ ThreadData *td = arg; AVFrame *in = td->in; AVFrame *out = td->out; + const int PP = td->PP; const int xoff = td->xoff; const int yoff = td->yoff; const int P = FFMAX(s->nb_planes, s->nb_comps); const int C = s->chars; + const int D = ((s->chars - s->dformat) >> 2) + s->dformat * 2; const int W = (outlink->w - xoff) / (C * 10); - const int H = (outlink->h - yoff) / (P * 12); - const char *format[2] = {"%02X\n", "%04X\n"}; + const int H = (outlink->h - yoff) / (PP * 12); + const char *format[4] = {"%02X\n", "%04X\n", "%03d\n", "%05d\n"}; const int slice_start = (W * jobnr) / nb_jobs; const int slice_end = (W * (jobnr+1)) / nb_jobs; int x, y, p; @@ -269,14 +288,17 @@ for (y = 0; y < H && (y + s->y < inlink->h); y++) { for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) { FFDrawColor color = { { 0 } }; - int value[4] = { 0 }; + int value[4] = { 0 }, pp = 0; s->pick_color(&s->draw, &color, in, x + s->x, y + s->y, value); for (p = 0; p < P; p++) { char text[256]; - snprintf(text, sizeof(text), format[C>>2], value[p]); - draw_text(&s->draw, out, &s->white, xoff + x * C * 10 + 2, yoff + y * P * 12 + p * 10 + 2, text, 0); + if (!(s->components & (1 << p))) + continue; + snprintf(text, sizeof(text), format[D], value[p]); + draw_text(&s->draw, out, &s->white, xoff + x * C * 10 + 2, yoff + y * PP * 12 + pp * 10 + 2, text, 0); + pp++; } } } @@ -289,9 +311,11 @@ AVFilterContext *ctx = inlink->dst; DatascopeContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + const int P = FFMAX(s->nb_planes, s->nb_comps); ThreadData td = { 0 }; int ymaxlen = 0; int xmaxlen = 0; + int PP = 0; AVFrame *out; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -304,10 +328,15 @@ ff_fill_rectangle(&s->draw, &s->black, out->data, out->linesize, 0, 0, outlink->w, outlink->h); + for (int p = 0; p < P; p++) { + if (s->components & (1 << p)) + PP++; + } + PP = FFMAX(PP, 1); + if (s->axis) { - const int P = FFMAX(s->nb_planes, s->nb_comps); const int C = s->chars; - int Y = outlink->h / (P * 12); + int Y = outlink->h / (PP * 12); int X = outlink->w / (C * 10); char text[256] = { 0 }; int x, y; @@ -319,16 +348,16 @@ xmaxlen = strlen(text); xmaxlen *= 10; - Y = (outlink->h - xmaxlen) / (P * 12); + Y = (outlink->h - xmaxlen) / (PP * 12); X = (outlink->w - ymaxlen) / (C * 10); for (y = 0; y < Y; y++) { snprintf(text, sizeof(text), "%d", s->y + y); ff_fill_rectangle(&s->draw, &s->gray, out->data, out->linesize, - 0, xmaxlen + y * P * 12 + (P + 1) * P - 2, ymaxlen, 10); + 0, xmaxlen + y * PP * 12 + (PP + 1) * PP - 2, ymaxlen, 10); - draw_text(&s->draw, out, &s->yellow, 2, xmaxlen + y * P * 12 + (P + 1) * P, text, 0); + draw_text(&s->draw, out, &s->yellow, 2, xmaxlen + y * PP * 12 + (PP + 1) * PP, text, 0); } for (x = 0; x < X; x++) { @@ -341,7 +370,7 @@ } } - td.in = in; td.out = out, td.yoff = xmaxlen, td.xoff = ymaxlen; + td.in = in; td.out = out, td.yoff = xmaxlen, td.xoff = ymaxlen, td.PP = PP; ctx->internal->execute(ctx, s->filter, &td, NULL, FFMIN(ff_filter_get_nb_threads(ctx), FFMAX(outlink->w / 20, 1))); av_frame_free(&in); @@ -359,7 +388,7 @@ ff_draw_color(&s->draw, &s->black, (uint8_t[]){ 0, 0, 0, alpha} ); ff_draw_color(&s->draw, &s->yellow, (uint8_t[]){ 255, 255, 0, 255} ); ff_draw_color(&s->draw, &s->gray, (uint8_t[]){ 77, 77, 77, 255} ); - s->chars = (s->draw.desc->comp[0].depth + 7) / 8 * 2; + s->chars = (s->draw.desc->comp[0].depth + 7) / 8 * 2 + s->dformat; s->nb_comps = s->draw.desc->nb_components; switch (s->mode) { @@ -390,6 +419,18 @@ return 0; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + static const AVFilterPad inputs[] = { { .name = "default", @@ -418,6 +459,7 @@ .inputs = inputs, .outputs = outputs, .flags = AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; typedef struct PixscopeContext { @@ -444,19 +486,21 @@ FFDrawColor red; FFDrawColor *colors[4]; + uint16_t values[4][80][80]; + void (*pick_color)(FFDrawContext *draw, FFDrawColor *color, AVFrame *in, int x, int y, int *value); } PixscopeContext; #define POFFSET(x) offsetof(PixscopeContext, x) static const AVOption pixscope_options[] = { - { "x", "set scope x offset", POFFSET(xpos), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS }, - { "y", "set scope y offset", POFFSET(ypos), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS }, - { "w", "set scope width", POFFSET(w), AV_OPT_TYPE_INT, {.i64=7}, 1, 80, FLAGS }, - { "h", "set scope height", POFFSET(h), AV_OPT_TYPE_INT, {.i64=7}, 1, 80, FLAGS }, - { "o", "set window opacity", POFFSET(o), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS }, - { "wx", "set window x offset", POFFSET(wx), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 1, FLAGS }, - { "wy", "set window y offset", POFFSET(wy), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 1, FLAGS }, + { "x", "set scope x offset", POFFSET(xpos), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR }, + { "y", "set scope y offset", POFFSET(ypos), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR }, + { "w", "set scope width", POFFSET(w), AV_OPT_TYPE_INT, {.i64=7}, 1, 80, FLAGSR }, + { "h", "set scope height", POFFSET(h), AV_OPT_TYPE_INT, {.i64=7}, 1, 80, FLAGSR }, + { "o", "set window opacity", POFFSET(o), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR }, + { "wx", "set window x offset", POFFSET(wx), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 1, FLAGSR }, + { "wy", "set window y offset", POFFSET(wy), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 1, FLAGSR }, { NULL } }; @@ -518,6 +562,8 @@ return 0; } +#define SQR(x) ((x)*(x)) + static int pixscope_filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; @@ -526,7 +572,7 @@ AVFrame *out = ff_get_video_buffer(outlink, in->width, in->height); int max[4] = { 0 }, min[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX }; float average[4] = { 0 }; - double rms[4] = { 0 }; + double std[4] = { 0 }, rms[4] = { 0 }; const char rgba[4] = { 'R', 'G', 'B', 'A' }; const char yuva[4] = { 'Y', 'U', 'V', 'A' }; int x, y, X, Y, i, w, h; @@ -583,6 +629,7 @@ ff_fill_rectangle(&s->draw, &color, out->data, out->linesize, x * w + (s->ww - 4 - (s->w * w)) / 2 + X, y * h + 2 + Y, w, h); for (i = 0; i < 4; i++) { + s->values[i][x][y] = value[i]; rms[i] += (double)value[i] * (double)value[i]; average[i] += value[i]; min[i] = FFMIN(min[i], value[i]); @@ -629,19 +676,51 @@ average[i] /= s->w * s->h; } + for (y = 0; y < s->h; y++) { + for (x = 0; x < s->w; x++) { + for (i = 0; i < 4; i++) + std[i] += SQR(s->values[i][x][y] - average[i]); + } + } + + for (i = 0; i < 4; i++) { + std[i] /= s->w * s->h; + std[i] = sqrt(std[i]); + } + snprintf(text, sizeof(text), "CH AVG MIN MAX RMS\n"); - draw_text(&s->draw, out, &s->white, X + 28, Y + s->ww + 20, text, 0); + draw_text(&s->draw, out, &s->white, X + 28, Y + s->ww + 5, text, 0); for (i = 0; i < s->nb_comps; i++) { int c = s->rgba_map[i]; snprintf(text, sizeof(text), "%c %07.1f %05d %05d %07.1f\n", s->is_rgb ? rgba[i] : yuva[i], average[c], min[c], max[c], rms[c]); - draw_text(&s->draw, out, s->colors[i], X + 28, Y + s->ww + 20 * (i + 2), text, 0); + draw_text(&s->draw, out, s->colors[i], X + 28, Y + s->ww + 15 * (i + 1), text, 0); + } + snprintf(text, sizeof(text), "CH STD\n"); + draw_text(&s->draw, out, &s->white, X + 28, Y + s->ww + 15 * (0 + 5), text, 0); + for (i = 0; i < s->nb_comps; i++) { + int c = s->rgba_map[i]; + + snprintf(text, sizeof(text), "%c %07.2f\n", s->is_rgb ? rgba[i] : yuva[i], std[c]); + draw_text(&s->draw, out, s->colors[i], X + 28, Y + s->ww + 15 * (i + 6), text, 0); } av_frame_free(&in); return ff_filter_frame(outlink, out); } +static int pixscope_process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return pixscope_config_input(ctx->inputs[0]); +} + static const AVFilterPad pixscope_inputs[] = { { .name = "default", @@ -669,6 +748,7 @@ .inputs = pixscope_inputs, .outputs = pixscope_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .process_command = pixscope_process_command, }; typedef struct PixelValues { @@ -720,19 +800,19 @@ #define OOFFSET(x) offsetof(OscilloscopeContext, x) static const AVOption oscilloscope_options[] = { - { "x", "set scope x position", OOFFSET(xpos), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS }, - { "y", "set scope y position", OOFFSET(ypos), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS }, - { "s", "set scope size", OOFFSET(size), AV_OPT_TYPE_FLOAT, {.dbl=0.8}, 0, 1, FLAGS }, - { "t", "set scope tilt", OOFFSET(tilt), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS }, - { "o", "set trace opacity", OOFFSET(o), AV_OPT_TYPE_FLOAT, {.dbl=0.8}, 0, 1, FLAGS }, - { "tx", "set trace x position", OOFFSET(tx), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS }, - { "ty", "set trace y position", OOFFSET(ty), AV_OPT_TYPE_FLOAT, {.dbl=0.9}, 0, 1, FLAGS }, - { "tw", "set trace width", OOFFSET(twidth), AV_OPT_TYPE_FLOAT, {.dbl=0.8},.1, 1, FLAGS }, - { "th", "set trace height", OOFFSET(theight), AV_OPT_TYPE_FLOAT, {.dbl=0.3},.1, 1, FLAGS }, - { "c", "set components to trace", OOFFSET(components), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGS }, - { "g", "draw trace grid", OOFFSET(grid), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, - { "st", "draw statistics", OOFFSET(statistics), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, - { "sc", "draw scope", OOFFSET(scope), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, + { "x", "set scope x position", OOFFSET(xpos), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR }, + { "y", "set scope y position", OOFFSET(ypos), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR }, + { "s", "set scope size", OOFFSET(size), AV_OPT_TYPE_FLOAT, {.dbl=0.8}, 0, 1, FLAGSR }, + { "t", "set scope tilt", OOFFSET(tilt), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR }, + { "o", "set trace opacity", OOFFSET(o), AV_OPT_TYPE_FLOAT, {.dbl=0.8}, 0, 1, FLAGSR }, + { "tx", "set trace x position", OOFFSET(tx), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGSR }, + { "ty", "set trace y position", OOFFSET(ty), AV_OPT_TYPE_FLOAT, {.dbl=0.9}, 0, 1, FLAGSR }, + { "tw", "set trace width", OOFFSET(twidth), AV_OPT_TYPE_FLOAT, {.dbl=0.8},.1, 1, FLAGSR }, + { "th", "set trace height", OOFFSET(theight), AV_OPT_TYPE_FLOAT, {.dbl=0.3},.1, 1, FLAGSR }, + { "c", "set components to trace", OOFFSET(components), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGSR }, + { "g", "draw trace grid", OOFFSET(grid), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGSR }, + { "st", "draw statistics", OOFFSET(statistics), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGSR }, + { "sc", "draw scope", OOFFSET(scope), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGSR }, { NULL } }; @@ -758,7 +838,7 @@ for (p = 0; p < draw->nb_planes; p++) { if (draw->desc->comp[p].depth == 8) { if (draw->nb_planes == 1) { - for (i = 0; i < 4; i++) { + for (i = 0; i < draw->desc->nb_components; i++) { out->data[0][y0 * out->linesize[0] + x0 * draw->pixelstep[0] + i] = color->comp[0].u8[i]; } } else { @@ -766,8 +846,8 @@ } } else { if (draw->nb_planes == 1) { - for (i = 0; i < 4; i++) { - AV_WN16(out->data[0] + y0 * out->linesize[0] + 2 * (x0 * draw->pixelstep[0] + i), color->comp[0].u16[i]); + for (i = 0; i < draw->desc->nb_components; i++) { + AV_WN16(out->data[0] + y0 * out->linesize[0] + (x0 * draw->pixelstep[0] + i), color->comp[0].u16[i]); } } else { AV_WN16(out->data[p] + out->linesize[p] * (y0 >> draw->vsub[p]) + (x0 >> draw->hsub[p]) * 2, color->comp[p].u16[0]); @@ -830,15 +910,36 @@ } } -static int oscilloscope_config_input(AVFilterLink *inlink) +static void update_oscilloscope(AVFilterContext *ctx) { - OscilloscopeContext *s = inlink->dst->priv; + OscilloscopeContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; int cx, cy, size; double tilt; + ff_draw_color(&s->draw, &s->dark, (uint8_t[]){ 0, 0, 0, s->o * 255} ); + s->height = s->theight * inlink->h; + s->width = s->twidth * inlink->w; + size = hypot(inlink->w, inlink->h); + size *= s->size; + tilt = (s->tilt - 0.5) * M_PI; + cx = s->xpos * (inlink->w - 1); + cy = s->ypos * (inlink->h - 1); + s->x1 = cx - size / 2.0 * cos(tilt); + s->x2 = cx + size / 2.0 * cos(tilt); + s->y1 = cy - size / 2.0 * sin(tilt); + s->y2 = cy + size / 2.0 * sin(tilt); + s->ox = (inlink->w - s->width) * s->tx; + s->oy = (inlink->h - s->height) * s->ty; +} + +static int oscilloscope_config_input(AVFilterLink *inlink) +{ + OscilloscopeContext *s = inlink->dst->priv; + int size; + s->nb_planes = av_pix_fmt_count_planes(inlink->format); ff_draw_init(&s->draw, inlink->format, 0); - ff_draw_color(&s->draw, &s->dark, (uint8_t[]){ 0, 0, 0, s->o * 255} ); ff_draw_color(&s->draw, &s->black, (uint8_t[]){ 0, 0, 0, 255} ); ff_draw_color(&s->draw, &s->white, (uint8_t[]){ 255, 255, 255, 255} ); ff_draw_color(&s->draw, &s->green, (uint8_t[]){ 0, 255, 0, 255} ); @@ -876,24 +977,13 @@ } s->max = (1 << s->draw.desc->comp[0].depth); - cx = s->xpos * (inlink->w - 1); - cy = s->ypos * (inlink->h - 1); - s->height = s->theight * inlink->h; - s->width = s->twidth * inlink->w; size = hypot(inlink->w, inlink->h); s->values = av_calloc(size, sizeof(*s->values)); if (!s->values) return AVERROR(ENOMEM); - size *= s->size; - tilt = (s->tilt - 0.5) * M_PI; - s->x1 = cx - size / 2.0 * cos(tilt); - s->x2 = cx + size / 2.0 * cos(tilt); - s->y1 = cy - size / 2.0 * sin(tilt); - s->y2 = cy + size / 2.0 * sin(tilt); - s->ox = (inlink->w - s->width) * s->tx; - s->oy = (inlink->h - s->height) * s->ty; + update_oscilloscope(inlink->dst); return 0; } @@ -922,7 +1012,7 @@ if (s->draw.nb_planes == 1) { int i; - for (i = 0; i < s->draw.pixelstep[0]; i++) + for (i = 0; i < s->nb_comps; i++) out->data[0][out->linesize[0] * y0 + x0 * s->draw.pixelstep[0] + i] = 255 * ((s->nb_values + state) & 1); } else { out->data[0][out->linesize[0] * y0 + x0] = 255 * ((s->nb_values + state) & 1); @@ -931,8 +1021,8 @@ if (s->draw.nb_planes == 1) { int i; - for (i = 0; i < s->draw.pixelstep[0]; i++) - AV_WN16(out->data[0] + out->linesize[0] * y0 + 2 * x0 * (s->draw.pixelstep[0] + i), (s->max - 1) * ((s->nb_values + state) & 1)); + for (i = 0; i < s->nb_comps; i++) + AV_WN16(out->data[0] + out->linesize[0] * y0 + x0 * s->draw.pixelstep[0] + i, (s->max - 1) * ((s->nb_values + state) & 1)); } else { AV_WN16(out->data[0] + out->linesize[0] * y0 + 2 * x0, (s->max - 1) * ((s->nb_values + state) & 1)); } @@ -973,7 +1063,7 @@ frame->width, frame->height, s->ox, s->oy, s->width, s->height + 20 * s->statistics); - if (s->grid) { + if (s->grid && outlink->h >= 10) { ff_fill_rectangle(&s->draw, &s->gray, frame->data, frame->linesize, s->ox, s->oy, s->width - 1, 1); @@ -1022,6 +1112,20 @@ return ff_filter_frame(outlink, frame); } +static int oscilloscope_process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + update_oscilloscope(ctx); + + return 0; +} + static const AVFilterPad oscilloscope_inputs[] = { { .name = "default", @@ -1051,4 +1155,5 @@ .inputs = oscilloscope_inputs, .outputs = oscilloscope_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .process_command = oscilloscope_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_dblur.c ffmpeg-4.4/libavfilter/vf_dblur.c --- ffmpeg-4.2.2/libavfilter/vf_dblur.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_dblur.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct DBlurContext { + const AVClass *class; + + float angle; + float radius; + int planes; + + float b0, b1, q, c, R3; + + int depth; + int planewidth[4]; + int planeheight[4]; + float *buffer; + int nb_planes; +} DBlurContext; + +#define OFFSET(x) offsetof(DBlurContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption dblur_options[] = { + { "angle", "set angle", OFFSET(angle), AV_OPT_TYPE_FLOAT, {.dbl=45}, 0.0, 360, FLAGS }, + { "radius", "set radius", OFFSET(radius), AV_OPT_TYPE_FLOAT, {.dbl=5}, 1, 8192, FLAGS }, + { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(dblur); + +#define f(n, m) (dst[(n) * width + (m)]) + +static int filter_horizontally(AVFilterContext *ctx, int width, int height) +{ + DBlurContext *s = ctx->priv; + const float b0 = s->b0; + const float b1 = s->b1; + const float q = s->q; + const float c = s->c; + float *dst = s->buffer; + float g; + + if (s->R3 > 0) { + for (int y = 1; y < height - 1; y++) { + g = q * f(0, 0) + c * f(0, 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); + } + } + + for (int y = height - 2; y >= 0; y--) { + 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); + } + } + } else { + for (int y = 1; y < height - 1; y++) { + g = q * f(0, width - 1) + c * f(0, 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); + } + } + + for (int y = height - 2; y >= 0; y--) { + 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); + } + } + } + + return 0; +} + +static void diriir2d(AVFilterContext *ctx, int plane) +{ + DBlurContext *s = ctx->priv; + const int width = s->planewidth[plane]; + const int height = s->planeheight[plane]; + + filter_horizontally(ctx, width, height); +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE + }; + + return ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); +} + +static int config_input(AVFilterLink *inlink) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + DBlurContext *s = inlink->dst->priv; + + s->depth = desc->comp[0].depth; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + 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->buffer = av_malloc_array(FFALIGN(inlink->w, 16), FFALIGN(inlink->h, 16) * sizeof(*s->buffer)); + if (!s->buffer) + return AVERROR(ENOMEM); + + return 0; +} + +static void set_params(DBlurContext *s, float angle, float r) +{ + float mu, nu, R1, R2, w1, w2; + float a0, a1, a2, a3; + + angle = angle * M_PI / 180.f; + + mu = cosf(angle); + nu = sinf(angle); + R1 = (mu * r) * (mu * r); + R2 = (nu * r) * (nu * r); + s->R3 = mu * nu * r * r; + w1 = sqrtf(0.25f + R1); + w2 = sqrtf(0.25f + R2); + a0 = (w1 + 0.5f) * (w2 + 0.5f) - fabsf(s->R3); + a1 = 0.5f + w2 - a0; + a2 = 0.5f + w1 - a0; + a3 = a0 - w1 - w2; + s->b0 = 1.f / a0; + s->b1 = -a2 / a0; + s->q = -a1 / a0; + s->c = -a3 / a0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + DBlurContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + int plane; + + set_params(s, s->angle, s->radius); + + 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); + } + + for (plane = 0; plane < s->nb_planes; plane++) { + const int height = s->planeheight[plane]; + const int width = s->planewidth[plane]; + float *bptr = s->buffer; + const uint8_t *src = in->data[plane]; + const uint16_t *src16 = (const uint16_t *)in->data[plane]; + uint8_t *dst = out->data[plane]; + uint16_t *dst16 = (uint16_t *)out->data[plane]; + int y, x; + + if (!(s->planes & (1 << plane))) { + if (out != in) + av_image_copy_plane(out->data[plane], out->linesize[plane], + in->data[plane], in->linesize[plane], + width * ((s->depth + 7) / 8), height); + continue; + } + + if (s->depth == 8) { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + bptr[x] = src[x]; + } + bptr += width; + src += in->linesize[plane]; + } + } else { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + bptr[x] = src16[x]; + } + bptr += width; + src16 += in->linesize[plane] / 2; + } + } + + diriir2d(ctx, plane); + + bptr = s->buffer; + if (s->depth == 8) { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + dst[x] = bptr[x]; + } + bptr += width; + dst += out->linesize[plane]; + } + } else { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + dst16[x] = bptr[x]; + } + bptr += width; + dst16 += out->linesize[plane] / 2; + } + } + } + + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + DBlurContext *s = ctx->priv; + + av_freep(&s->buffer); +} + +static const AVFilterPad dblur_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad dblur_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_dblur = { + .name = "dblur", + .description = NULL_IF_CONFIG_SMALL("Apply Directional Blur filter."), + .priv_size = sizeof(DBlurContext), + .priv_class = &dblur_class, + .uninit = uninit, + .query_formats = query_formats, + .inputs = dblur_inputs, + .outputs = dblur_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_dctdnoiz.c ffmpeg-4.4/libavfilter/vf_dctdnoiz.c --- ffmpeg-4.2.2/libavfilter/vf_dctdnoiz.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_dctdnoiz.c 2021-04-08 21:28:40.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/avassert.h" #include "libavutil/eval.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "internal.h" diff -Nru ffmpeg-4.2.2/libavfilter/vf_deband.c ffmpeg-4.4/libavfilter/vf_deband.c --- ffmpeg-4.2.2/libavfilter/vf_deband.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_deband.c 2021-04-08 21:28:40.000000000 +0000 @@ -49,7 +49,7 @@ } DebandContext; #define OFFSET(x) offsetof(DebandContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption deband_options[] = { { "1thr", "set 1st plane threshold", OFFSET(threshold[0]), AV_OPT_TYPE_FLOAT, {.dbl=0.02}, 0.00003, 0.5, FLAGS }, @@ -74,7 +74,8 @@ DebandContext *s = ctx->priv; static const enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16, + 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_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, @@ -116,7 +117,7 @@ static float frand(int x, int y) { - const float r = sinf(x * 12.9898 + y * 78.233) * 43758.545; + const float r = sinf(x * 12.9898f + y * 78.233f) * 43758.545f; return r - floorf(r); } @@ -388,8 +389,10 @@ s->thr[2] = ((1 << desc->comp[2].depth) - 1) * s->threshold[2]; s->thr[3] = ((1 << desc->comp[3].depth) - 1) * s->threshold[3]; - s->x_pos = av_malloc(s->planewidth[0] * s->planeheight[0] * sizeof(*s->x_pos)); - s->y_pos = av_malloc(s->planewidth[0] * s->planeheight[0] * sizeof(*s->y_pos)); + if (!s->x_pos) + s->x_pos = av_malloc(s->planewidth[0] * s->planeheight[0] * sizeof(*s->x_pos)); + if (!s->y_pos) + s->y_pos = av_malloc(s->planewidth[0] * s->planeheight[0] * sizeof(*s->y_pos)); if (!s->x_pos || !s->y_pos) return AVERROR(ENOMEM); @@ -431,6 +434,17 @@ 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) +{ + int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + static av_cold void uninit(AVFilterContext *ctx) { DebandContext *s = ctx->priv; @@ -467,4 +481,5 @@ .inputs = avfilter_vf_deband_inputs, .outputs = avfilter_vf_deband_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_deblock.c ffmpeg-4.4/libavfilter/vf_deblock.c --- ffmpeg-4.2.2/libavfilter/vf_deblock.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_deblock.c 2021-04-08 21:28:40.000000000 +0000 @@ -76,6 +76,7 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, @@ -284,14 +285,14 @@ if (s->depth <= 8 && s->filter == WEAK) { s->deblockh = deblockh8_weak; s->deblockv = deblockv8_weak; - } else if (s->depth >= 8 && s->filter == WEAK) { + } else if (s->depth > 8 && s->filter == WEAK) { s->deblockh = deblockh16_weak; s->deblockv = deblockv16_weak; } if (s->depth <= 8 && s->filter == STRONG) { s->deblockh = deblockh8_strong; s->deblockv = deblockv8_strong; - } else if (s->depth >= 8 && s->filter == STRONG) { + } else if (s->depth > 8 && s->filter == STRONG) { s->deblockh = deblockh16_strong; s->deblockv = deblockv16_strong; } @@ -366,8 +367,20 @@ 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) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_output(ctx->outputs[0]); +} + #define OFFSET(x) offsetof(DeblockContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption deblock_options[] = { { "filter", "set type of filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=STRONG},0, 1, FLAGS, "filter" }, @@ -411,4 +424,5 @@ .inputs = inputs, .outputs = outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_decimate.c ffmpeg-4.4/libavfilter/vf_decimate.c --- ffmpeg-4.2.2/libavfilter/vf_decimate.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_decimate.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/timestamp.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" #define INPUT_MAIN 0 @@ -43,6 +44,7 @@ AVFrame **clean_src; ///< frame queue for the clean source int got_frame[2]; ///< frame request flag for each input stream AVRational ts_unit; ///< timestamp units for the output frames + int64_t last_pts; ///< last output timestamp int64_t start_pts; ///< base for output timestamps uint32_t eof; ///< bitmask for end of stream int hsub, vsub; ///< chroma subsampling values @@ -165,11 +167,11 @@ dm->got_frame[INPUT_MAIN] = dm->got_frame[INPUT_CLEANSRC] = 0; if (dm->ppsrc) - in = dm->clean_src[dm->fid]; + in = dm->queue[dm->fid].frame; if (in) { /* update frame metrics */ - prv = dm->fid ? (dm->ppsrc ? dm->clean_src[dm->fid - 1] : dm->queue[dm->fid - 1].frame) : dm->last; + prv = dm->fid ? dm->queue[dm->fid - 1].frame : dm->last; if (!prv) { dm->queue[dm->fid].maxbdiff = INT64_MAX; dm->queue[dm->fid].totdiff = INT64_MAX; @@ -217,14 +219,19 @@ av_frame_free(&dm->queue[i].frame); } else { AVFrame *frame = dm->queue[i].frame; + dm->queue[i].frame = NULL; if (frame->pts != AV_NOPTS_VALUE && dm->start_pts == AV_NOPTS_VALUE) dm->start_pts = frame->pts; if (dm->ppsrc) { av_frame_free(&frame); frame = dm->clean_src[i]; + if (!frame) + continue; + dm->clean_src[i] = NULL; } frame->pts = av_rescale_q(outlink->frame_count_in, dm->ts_unit, (AVRational){1,1}) + (dm->start_pts == AV_NOPTS_VALUE ? 0 : dm->start_pts); + dm->last_pts = frame->pts; ret = ff_filter_frame(outlink, frame); if (ret < 0) break; @@ -234,36 +241,63 @@ return ret; } -static int config_input(AVFilterLink *inlink) +static int activate(AVFilterContext *ctx) { - int max_value; - AVFilterContext *ctx = inlink->dst; DecimateContext *dm = ctx->priv; - const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format); - const int w = inlink->w; - const int h = inlink->h; - - dm->hsub = pix_desc->log2_chroma_w; - dm->vsub = pix_desc->log2_chroma_h; - dm->depth = pix_desc->comp[0].depth; - max_value = (1 << dm->depth) - 1; - dm->scthresh = (int64_t)(((int64_t)max_value * w * h * dm->scthresh_flt) / 100); - dm->dupthresh = (int64_t)(((int64_t)max_value * dm->blockx * dm->blocky * dm->dupthresh_flt) / 100); - dm->nxblocks = (w + dm->blockx/2 - 1) / (dm->blockx/2); - dm->nyblocks = (h + dm->blocky/2 - 1) / (dm->blocky/2); - dm->bdiffsize = dm->nxblocks * dm->nyblocks; - dm->bdiffs = av_malloc_array(dm->bdiffsize, sizeof(*dm->bdiffs)); - dm->queue = av_calloc(dm->cycle, sizeof(*dm->queue)); - - if (!dm->bdiffs || !dm->queue) - return AVERROR(ENOMEM); - - if (dm->ppsrc) { - dm->clean_src = av_calloc(dm->cycle, sizeof(*dm->clean_src)); - if (!dm->clean_src) - return AVERROR(ENOMEM); + AVFrame *frame = NULL; + int ret = 0, status; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); + + if ((dm->got_frame[INPUT_MAIN] == 0) && !(dm->eof & (1 << INPUT_MAIN)) && + (ret = ff_inlink_consume_frame(ctx->inputs[INPUT_MAIN], &frame)) > 0) { + ret = filter_frame(ctx->inputs[INPUT_MAIN], frame); + if (ret < 0) + return ret; + } + if (ret < 0) + return ret; + if (dm->ppsrc && + (dm->got_frame[INPUT_CLEANSRC] == 0) && !(dm->eof & (1 << INPUT_CLEANSRC)) && + (ret = ff_inlink_consume_frame(ctx->inputs[INPUT_CLEANSRC], &frame)) > 0) { + ret = filter_frame(ctx->inputs[INPUT_CLEANSRC], frame); + if (ret < 0) + return ret; + } + if (ret < 0) { + return ret; + } else if (dm->eof == ((1 << INPUT_MAIN) | (dm->ppsrc << INPUT_CLEANSRC))) { + ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, dm->last_pts); + return 0; + } else if (!(dm->eof & (1 << INPUT_MAIN)) && ff_inlink_acknowledge_status(ctx->inputs[INPUT_MAIN], &status, &pts)) { + if (status == AVERROR_EOF) { // flushing + dm->eof |= 1 << INPUT_MAIN; + if (dm->ppsrc) + filter_frame(ctx->inputs[INPUT_CLEANSRC], NULL); + filter_frame(ctx->inputs[INPUT_MAIN], NULL); + ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, dm->last_pts); + return 0; + } + } else if (dm->ppsrc && !(dm->eof & (1 << INPUT_CLEANSRC)) && ff_inlink_acknowledge_status(ctx->inputs[INPUT_CLEANSRC], &status, &pts)) { + if (status == AVERROR_EOF) { // flushing + dm->eof |= 1 << INPUT_CLEANSRC; + filter_frame(ctx->inputs[INPUT_MAIN], NULL); + filter_frame(ctx->inputs[INPUT_CLEANSRC], NULL); + ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, dm->last_pts); + return 0; + } } + if (ff_inlink_queued_frames(ctx->inputs[INPUT_MAIN]) > 0 && + (dm->ppsrc && ff_inlink_queued_frames(ctx->inputs[INPUT_CLEANSRC]) > 0)) { + ff_filter_set_ready(ctx, 100); + } else if (ff_outlink_frame_wanted(ctx->outputs[0])) { + if (dm->got_frame[INPUT_MAIN] == 0) + ff_inlink_request_frame(ctx->inputs[INPUT_MAIN]); + if (dm->ppsrc && (dm->got_frame[INPUT_CLEANSRC] == 0)) + ff_inlink_request_frame(ctx->inputs[INPUT_CLEANSRC]); + } return 0; } @@ -271,29 +305,19 @@ { DecimateContext *dm = ctx->priv; AVFilterPad pad = { - .name = av_strdup("main"), + .name = "main", .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = filter_frame, - .config_props = config_input, }; int ret; - if (!pad.name) - return AVERROR(ENOMEM); - if ((ret = ff_insert_inpad(ctx, INPUT_MAIN, &pad)) < 0) { - av_freep(&pad.name); + if ((ret = ff_insert_inpad(ctx, INPUT_MAIN, &pad)) < 0) return ret; - } if (dm->ppsrc) { - pad.name = av_strdup("clean_src"); + pad.name = "clean_src"; pad.config_props = NULL; - if (!pad.name) - return AVERROR(ENOMEM); - if ((ret = ff_insert_inpad(ctx, INPUT_CLEANSRC, &pad)) < 0) { - av_freep(&pad.name); + if ((ret = ff_insert_inpad(ctx, INPUT_CLEANSRC, &pad)) < 0) return ret; - } } if ((dm->blockx & (dm->blockx - 1)) || @@ -314,42 +338,16 @@ av_frame_free(&dm->last); av_freep(&dm->bdiffs); + if (dm->queue) { + for (i = 0; i < dm->cycle; i++) + av_frame_free(&dm->queue[i].frame); + } av_freep(&dm->queue); - av_freep(&dm->clean_src); - for (i = 0; i < ctx->nb_inputs; i++) - av_freep(&ctx->input_pads[i].name); -} - -static int request_inlink(AVFilterContext *ctx, int lid) -{ - int ret = 0; - DecimateContext *dm = ctx->priv; - - if (!dm->got_frame[lid]) { - AVFilterLink *inlink = ctx->inputs[lid]; - ret = ff_request_frame(inlink); - if (ret == AVERROR_EOF) { // flushing - dm->eof |= 1 << lid; - ret = filter_frame(inlink, NULL); - } + if (dm->clean_src) { + for (i = 0; i < dm->cycle; i++) + av_frame_free(&dm->clean_src[i]); } - return ret; -} - -static int request_frame(AVFilterLink *outlink) -{ - int ret; - AVFilterContext *ctx = outlink->src; - DecimateContext *dm = ctx->priv; - const uint32_t eof_mask = 1<ppsrc<eof & eof_mask) == eof_mask) // flush done? - return AVERROR_EOF; - if ((ret = request_inlink(ctx, INPUT_MAIN)) < 0) - return ret; - if (dm->ppsrc && (ret = request_inlink(ctx, INPUT_CLEANSRC)) < 0) - return ret; - return 0; + av_freep(&dm->clean_src); } static int query_formats(AVFilterContext *ctx) @@ -359,8 +357,12 @@ #define PF_ALPHA(suf) AV_PIX_FMT_YUVA420##suf, AV_PIX_FMT_YUVA422##suf, AV_PIX_FMT_YUVA444##suf #define PF(suf) PF_NOALPHA(suf), PF_ALPHA(suf) PF(P), PF(P9), PF(P10), PF_NOALPHA(P12), PF_NOALPHA(P14), PF(P16), + AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, - AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, + 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 }; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); @@ -373,9 +375,33 @@ { AVFilterContext *ctx = outlink->src; DecimateContext *dm = ctx->priv; - const AVFilterLink *inlink = - ctx->inputs[dm->ppsrc ? INPUT_CLEANSRC : INPUT_MAIN]; + const AVFilterLink *inlink = ctx->inputs[INPUT_MAIN]; AVRational fps = inlink->frame_rate; + int max_value; + const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format); + const int w = inlink->w; + const int h = inlink->h; + + dm->hsub = pix_desc->log2_chroma_w; + dm->vsub = pix_desc->log2_chroma_h; + dm->depth = pix_desc->comp[0].depth; + max_value = (1 << dm->depth) - 1; + dm->scthresh = (int64_t)(((int64_t)max_value * w * h * dm->scthresh_flt) / 100); + dm->dupthresh = (int64_t)(((int64_t)max_value * dm->blockx * dm->blocky * dm->dupthresh_flt) / 100); + dm->nxblocks = (w + dm->blockx/2 - 1) / (dm->blockx/2); + dm->nyblocks = (h + dm->blocky/2 - 1) / (dm->blocky/2); + dm->bdiffsize = dm->nxblocks * dm->nyblocks; + dm->bdiffs = av_malloc_array(dm->bdiffsize, sizeof(*dm->bdiffs)); + dm->queue = av_calloc(dm->cycle, sizeof(*dm->queue)); + + if (!dm->bdiffs || !dm->queue) + return AVERROR(ENOMEM); + + if (dm->ppsrc) { + dm->clean_src = av_calloc(dm->cycle, sizeof(*dm->clean_src)); + if (!dm->clean_src) + return AVERROR(ENOMEM); + } if (!fps.num || !fps.den) { av_log(ctx, AV_LOG_ERROR, "The input needs a constant frame rate; " @@ -388,8 +414,13 @@ outlink->time_base = inlink->time_base; outlink->frame_rate = fps; outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; - outlink->w = inlink->w; - outlink->h = inlink->h; + if (dm->ppsrc) { + outlink->w = ctx->inputs[INPUT_CLEANSRC]->w; + outlink->h = ctx->inputs[INPUT_CLEANSRC]->h; + } else { + outlink->w = inlink->w; + outlink->h = inlink->h; + } dm->ts_unit = av_inv_q(av_mul_q(fps, outlink->time_base)); return 0; } @@ -398,7 +429,6 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, .config_props = config_output, }, { NULL } @@ -408,6 +438,7 @@ .name = "decimate", .description = NULL_IF_CONFIG_SMALL("Decimate frames (post field matching filter)."), .init = decimate_init, + .activate = activate, .uninit = decimate_uninit, .priv_size = sizeof(DecimateContext), .query_formats = query_formats, diff -Nru ffmpeg-4.2.2/libavfilter/vf_dedot.c ffmpeg-4.4/libavfilter/vf_dedot.c --- ffmpeg-4.2.2/libavfilter/vf_dedot.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_dedot.c 2020-07-11 10:39:30.000000000 +0000 @@ -71,6 +71,7 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_NONE }; @@ -283,7 +284,7 @@ s->frames[i] = av_frame_clone(frame); } av_frame_free(&frame); - } else { + } else if (s->frames[3]) { s->eof_frames--; s->frames[4] = av_frame_clone(s->frames[3]); } @@ -312,7 +313,8 @@ FFMIN(s->planeheight[2], ff_filter_get_nb_threads(ctx))); } - } + } else + av_frame_free(&out); } else if (!out) { ret = AVERROR(ENOMEM); } @@ -343,7 +345,11 @@ if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { if (status == AVERROR_EOF) { s->eof = 1; - s->eof_frames = 2; + s->eof_frames = !!s->frames[0] + !!s->frames[1]; + if (s->eof_frames <= 0) { + ff_outlink_set_status(outlink, AVERROR_EOF, pts); + return 0; + } ff_filter_set_ready(ctx, 10); return 0; } diff -Nru ffmpeg-4.2.2/libavfilter/vf_deflicker.c ffmpeg-4.4/libavfilter/vf_deflicker.c --- ffmpeg-4.2.2/libavfilter/vf_deflicker.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_deflicker.c 2020-07-11 10:39:30.000000000 +0000 @@ -109,6 +109,10 @@ AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_NONE }; AVFilterFormats *formats = ff_make_format_list(pixel_fmts); @@ -420,7 +424,10 @@ ret = ff_request_frame(ctx->inputs[0]); if (ret == AVERROR_EOF && s->available > 0) { - AVFrame *buf = av_frame_clone(ff_bufqueue_peek(&s->q, s->size - 1)); + AVFrame *buf = ff_bufqueue_peek(&s->q, s->available - 1); + if (!buf) + return AVERROR(ENOMEM); + buf = av_frame_clone(buf); if (!buf) return AVERROR(ENOMEM); diff -Nru ffmpeg-4.2.2/libavfilter/vf_deinterlace_qsv.c ffmpeg-4.4/libavfilter/vf_deinterlace_qsv.c --- ffmpeg-4.2.2/libavfilter/vf_deinterlace_qsv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_deinterlace_qsv.c 2021-04-08 21:28:40.000000000 +0000 @@ -202,16 +202,20 @@ } } - if (err != MFX_ERR_NONE) { - av_log(ctx, AV_LOG_ERROR, "Error getting the session handle\n"); + if (err < 0) + return ff_qsvvpp_print_error(ctx, err, "Error getting the session handle"); + else if (err > 0) { + ff_qsvvpp_print_warning(ctx, err, "Warning in getting the session handle"); return AVERROR_UNKNOWN; } /* create a "slave" session with those same properties, to be used for * actual deinterlacing */ err = MFXInit(impl, &ver, &s->session); - if (err != MFX_ERR_NONE) { - av_log(ctx, AV_LOG_ERROR, "Error initializing a session for deinterlacing\n"); + if (err < 0) + return ff_qsvvpp_print_error(ctx, err, "Error initializing a session for deinterlacing"); + else if (err > 0) { + ff_qsvvpp_print_warning(ctx, err, "Warning in session initialization"); return AVERROR_UNKNOWN; } @@ -309,9 +313,17 @@ par.vpp.Out.FrameRateExtD = ctx->outputs[0]->time_base.den; } + /* Print input memory mode */ + ff_qsvvpp_print_iopattern(ctx, par.IOPattern & 0x0F, "VPP"); + /* Print output memory mode */ + ff_qsvvpp_print_iopattern(ctx, par.IOPattern & 0xF0, "VPP"); err = MFXVideoVPP_Init(s->session, &par); - if (err != MFX_ERR_NONE) { - av_log(ctx, AV_LOG_ERROR, "Error opening the VPP for deinterlacing: %d\n", err); + if (err < 0) + return ff_qsvvpp_print_error(ctx, err, + "Error opening the VPP for deinterlacing"); + else if (err > 0) { + ff_qsvvpp_print_warning(ctx, err, + "Warning in VPP initialization"); return AVERROR_UNKNOWN; } @@ -482,8 +494,13 @@ return QSVDEINT_MORE_INPUT; } - if ((err < 0 && err != MFX_ERR_MORE_SURFACE) || !sync) { - av_log(ctx, AV_LOG_ERROR, "Error during deinterlacing: %d\n", err); + if (err < 0 && err != MFX_ERR_MORE_SURFACE) { + ret = ff_qsvvpp_print_error(ctx, err, "Error during deinterlacing"); + goto fail; + } + + if (!sync) { + av_log(ctx, AV_LOG_ERROR, "No sync during deinterlacing\n"); ret = AVERROR_UNKNOWN; goto fail; } @@ -494,8 +511,7 @@ err = MFXVideoCORE_SyncOperation(s->session, sync, 1000); } while (err == MFX_WRN_IN_EXECUTION); if (err < 0) { - av_log(ctx, AV_LOG_ERROR, "Error synchronizing the operation: %d\n", err); - ret = AVERROR_UNKNOWN; + ret = ff_qsvvpp_print_error(ctx, err, "Error synchronizing the operation"); goto fail; } diff -Nru ffmpeg-4.2.2/libavfilter/vf_deinterlace_vaapi.c ffmpeg-4.4/libavfilter/vf_deinterlace_vaapi.c --- ffmpeg-4.2.2/libavfilter/vf_deinterlace_vaapi.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_deinterlace_vaapi.c 2020-07-11 10:39:30.000000000 +0000 @@ -239,7 +239,7 @@ err = av_frame_copy_props(output_frame, input_frame); if (err < 0) - return err; + goto fail; err = ff_vaapi_vpp_init_params(avctx, ¶ms, input_frame, output_frame); diff -Nru ffmpeg-4.2.2/libavfilter/vf_delogo.c ffmpeg-4.4/libavfilter/vf_delogo.c --- ffmpeg-4.2.2/libavfilter/vf_delogo.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_delogo.c 2021-04-08 21:28:40.000000000 +0000 @@ -31,10 +31,51 @@ #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/eval.h" #include "avfilter.h" #include "formats.h" #include "internal.h" #include "video.h" +static const char * const var_names[] = { + "x", + "y", + "w", + "h", + "n", ///< number of frame + "t", ///< timestamp expressed in seconds + NULL +}; + +enum var_name { + VAR_X, + VAR_Y, + VAR_W, + VAR_H, + VAR_N, + VAR_T, + VAR_VARS_NB +}; + +static int set_expr(AVExpr **pexpr, const char *expr, const char *option, void *log_ctx) +{ + int ret; + AVExpr *old = NULL; + + if (*pexpr) + old = *pexpr; + ret = av_expr_parse(pexpr, expr, var_names, NULL, NULL, NULL, NULL, 0, log_ctx); + if (ret < 0) { + av_log(log_ctx, AV_LOG_ERROR, + "Error when parsing the expression '%s' for %s\n", + expr, option); + *pexpr = old; + return ret; + } + + av_expr_free(old); + return 0; +} + /** * Apply a simple delogo algorithm to the image in src and put the @@ -126,7 +167,7 @@ botleft[x-logo_x1-1] + botleft[x-logo_x1+1]) * weightb; weight = (weightl + weightr + weightt + weightb) * 3U; - interp = ROUNDED_DIV(interp, weight); + interp = (interp + (weight >> 1)) / weight; if (y >= logo_y+band && y < logo_y+logo_h-band && x >= logo_x+band && x < logo_x+logo_w-band) { @@ -156,26 +197,34 @@ typedef struct DelogoContext { const AVClass *class; int x, y, w, h, band, show; + char *x_expr, *y_expr, *w_expr, *h_expr; + AVExpr *x_pexpr, *y_pexpr, *w_pexpr, *h_pexpr; + double var_values[VAR_VARS_NB]; } DelogoContext; #define OFFSET(x) offsetof(DelogoContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption delogo_options[]= { - { "x", "set logo x position", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, - { "y", "set logo y position", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, - { "w", "set logo width", OFFSET(w), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, - { "h", "set logo height", OFFSET(h), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, -#if LIBAVFILTER_VERSION_MAJOR < 7 - /* Actual default value for band/t is 1, set in init */ - { "band", "set delogo area band size", OFFSET(band), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, - { "t", "set delogo area band size", OFFSET(band), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, -#endif - { "show", "show delogo area", OFFSET(show), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, FLAGS }, + { "x", "set logo x position", OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str = "-1" }, 0, 0, FLAGS }, + { "y", "set logo y position", OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str = "-1" }, 0, 0, FLAGS }, + { "w", "set logo width", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str = "-1" }, 0, 0, FLAGS }, + { "h", "set logo height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "-1" }, 0, 0, FLAGS }, + { "show", "show delogo area", OFFSET(show), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, { NULL } }; AVFILTER_DEFINE_CLASS(delogo); +static av_cold void uninit(AVFilterContext *ctx) +{ + DelogoContext *s = ctx->priv; + + av_expr_free(s->x_pexpr); s->x_pexpr = NULL; + av_expr_free(s->y_pexpr); s->y_pexpr = NULL; + av_expr_free(s->w_pexpr); s->w_pexpr = NULL; + av_expr_free(s->h_pexpr); s->h_pexpr = NULL; +} + static int query_formats(AVFilterContext *ctx) { @@ -194,6 +243,18 @@ static av_cold int init(AVFilterContext *ctx) { DelogoContext *s = ctx->priv; + int ret = 0; + + if ((ret = set_expr(&s->x_pexpr, s->x_expr, "x", ctx)) < 0 || + (ret = set_expr(&s->y_pexpr, s->y_expr, "y", ctx)) < 0 || + (ret = set_expr(&s->w_pexpr, s->w_expr, "w", ctx)) < 0 || + (ret = set_expr(&s->h_pexpr, s->h_expr, "h", ctx)) < 0 ) + return ret; + + s->x = av_expr_eval(s->x_pexpr, s->var_values, s); + s->y = av_expr_eval(s->y_pexpr, s->var_values, s); + s->w = av_expr_eval(s->w_pexpr, s->var_values, s); + s->h = av_expr_eval(s->h_pexpr, s->var_values, s); #define CHECK_UNSET_OPT(opt) \ if (s->opt == -1) { \ @@ -205,16 +266,8 @@ CHECK_UNSET_OPT(w); CHECK_UNSET_OPT(h); -#if LIBAVFILTER_VERSION_MAJOR < 7 - if (s->band == 0) { /* Unset, use default */ - av_log(ctx, AV_LOG_WARNING, "Note: default band value was changed from 4 to 1.\n"); - s->band = 1; - } else if (s->band != 1) { - av_log(ctx, AV_LOG_WARNING, "Option band is deprecated.\n"); - } -#else s->band = 1; -#endif + av_log(ctx, AV_LOG_VERBOSE, "x:%d y:%d, w:%d h:%d band:%d show:%d\n", s->x, s->y, s->w, s->h, s->band, s->show); @@ -251,6 +304,40 @@ int direct = 0; int plane; AVRational sar; + int ret; + + s->var_values[VAR_N] = inlink->frame_count_out; + s->var_values[VAR_T] = TS2T(in->pts, inlink->time_base); + s->x = av_expr_eval(s->x_pexpr, s->var_values, s); + s->y = av_expr_eval(s->y_pexpr, s->var_values, s); + s->w = av_expr_eval(s->w_pexpr, s->var_values, s); + s->h = av_expr_eval(s->h_pexpr, s->var_values, s); + + if (s->x + (s->band - 1) <= 0 || s->x + s->w - (s->band*2 - 2) > inlink->w || + s->y + (s->band - 1) <= 0 || s->y + s->h - (s->band*2 - 2) > inlink->h) { + av_log(s, AV_LOG_WARNING, "Logo area is outside of the frame," + " auto set the area inside of the frame\n"); + } + + if (s->x + (s->band - 1) <= 0) + s->x = 1 + s->band; + if (s->y + (s->band - 1) <= 0) + s->y = 1 + s->band; + if (s->x + s->w - (s->band*2 - 2) > inlink->w) + s->w = inlink->w - s->x - (s->band*2 - 2); + if (s->y + s->h - (s->band*2 - 2) > inlink->h) + s->h = inlink->h - s->y - (s->band*2 - 2); + + ret = config_input(inlink); + if (ret < 0) { + av_frame_free(&in); + return ret; + } + + s->w += s->band*2; + s->h += s->band*2; + s->x -= s->band; + s->y -= s->band; if (av_frame_is_writable(in)) { direct = 1; @@ -317,6 +404,7 @@ .priv_size = sizeof(DelogoContext), .priv_class = &delogo_class, .init = init, + .uninit = uninit, .query_formats = query_formats, .inputs = avfilter_vf_delogo_inputs, .outputs = avfilter_vf_delogo_outputs, diff -Nru ffmpeg-4.2.2/libavfilter/vf_derain.c ffmpeg-4.4/libavfilter/vf_derain.c --- ffmpeg-4.2.2/libavfilter/vf_derain.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_derain.c 2021-04-08 21:28:40.000000000 +0000 @@ -27,31 +27,30 @@ #include "libavformat/avio.h" #include "libavutil/opt.h" #include "avfilter.h" -#include "dnn_interface.h" +#include "dnn_filter_common.h" #include "formats.h" #include "internal.h" typedef struct DRContext { const AVClass *class; - - char *model_filename; - DNNBackendType backend_type; - DNNModule *dnn_module; - DNNModel *model; - DNNInputData input; - DNNData output; + DnnContext dnnctx; + int filter_type; } DRContext; -#define CLIP(x, min, max) (x < min ? min : (x > max ? max : x)) #define OFFSET(x) offsetof(DRContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM static const AVOption derain_options[] = { - { "dnn_backend", "DNN backend", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "backend" }, - { "native", "native backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "backend" }, + { "filter_type", "filter type(derain/dehaze)", OFFSET(filter_type), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "type" }, + { "derain", "derain filter flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "type" }, + { "dehaze", "dehaze filter flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "type" }, + { "dnn_backend", "DNN backend", OFFSET(dnnctx.backend_type), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "backend" }, + { "native", "native backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "backend" }, #if (CONFIG_LIBTENSORFLOW == 1) - { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" }, + { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" }, #endif - { "model", "path to model file", OFFSET(model_filename), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, + { "model", "path to model file", OFFSET(dnnctx.model_filename), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, + { "input", "input name of the model", OFFSET(dnnctx.model_inputname), AV_OPT_TYPE_STRING, { .str = "x" }, 0, 0, FLAGS }, + { "output", "output name of the model", OFFSET(dnnctx.model_outputname), AV_OPT_TYPE_STRING, { .str = "y" }, 0, 0, FLAGS }, { NULL } }; @@ -70,73 +69,29 @@ return ff_set_common_formats(ctx, formats); } -static int config_inputs(AVFilterLink *inlink) -{ - AVFilterContext *ctx = inlink->dst; - DRContext *dr_context = ctx->priv; - const char *model_output_name = "y"; - DNNReturnType result; - - dr_context->input.width = inlink->w; - dr_context->input.height = inlink->h; - dr_context->input.channels = 3; - - result = (dr_context->model->set_input_output)(dr_context->model->model, &dr_context->input, "x", &model_output_name, 1); - if (result != DNN_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "could not set input and output for the model\n"); - return AVERROR(EIO); - } - - return 0; -} - static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; DRContext *dr_context = ctx->priv; DNNReturnType dnn_result; - int pad_size; + AVFrame *out; - AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_log(ctx, AV_LOG_ERROR, "could not allocate memory for output frame\n"); av_frame_free(&in); return AVERROR(ENOMEM); } - av_frame_copy_props(out, in); - for (int i = 0; i < in->height; i++){ - for(int j = 0; j < in->width * 3; j++){ - int k = i * in->linesize[0] + j; - int t = i * in->width * 3 + j; - ((float *)dr_context->input.data)[t] = in->data[0][k] / 255.0; - } - } - - dnn_result = (dr_context->dnn_module->execute_model)(dr_context->model, &dr_context->output, 1); + dnn_result = ff_dnn_execute_model(&dr_context->dnnctx, in, out); if (dnn_result != DNN_SUCCESS){ av_log(ctx, AV_LOG_ERROR, "failed to execute model\n"); + av_frame_free(&in); return AVERROR(EIO); } - out->height = dr_context->output.height; - out->width = dr_context->output.width; - outlink->h = dr_context->output.height; - outlink->w = dr_context->output.width; - pad_size = (in->height - out->height) >> 1; - - for (int i = 0; i < out->height; i++){ - for(int j = 0; j < out->width * 3; j++){ - int k = i * out->linesize[0] + j; - int t = i * out->width * 3 + j; - - int t_in = (i + pad_size) * in->width * 3 + j + pad_size * 3; - out->data[0][k] = CLIP((int)((((float *)dr_context->input.data)[t_in] - dr_context->output.data[t]) * 255), 0, 255); - } - } - av_frame_free(&in); return ff_filter_frame(outlink, out); @@ -145,46 +100,19 @@ static av_cold int init(AVFilterContext *ctx) { DRContext *dr_context = ctx->priv; - - dr_context->input.dt = DNN_FLOAT; - dr_context->dnn_module = ff_get_dnn_module(dr_context->backend_type); - if (!dr_context->dnn_module) { - av_log(ctx, AV_LOG_ERROR, "could not create DNN module for requested backend\n"); - return AVERROR(ENOMEM); - } - if (!dr_context->model_filename) { - av_log(ctx, AV_LOG_ERROR, "model file for network is not specified\n"); - return AVERROR(EINVAL); - } - if (!dr_context->dnn_module->load_model) { - av_log(ctx, AV_LOG_ERROR, "load_model for network is not specified\n"); - return AVERROR(EINVAL); - } - - dr_context->model = (dr_context->dnn_module->load_model)(dr_context->model_filename); - if (!dr_context->model) { - av_log(ctx, AV_LOG_ERROR, "could not load DNN model\n"); - return AVERROR(EINVAL); - } - - return 0; + return ff_dnn_init(&dr_context->dnnctx, DFT_PROCESS_FRAME, ctx); } static av_cold void uninit(AVFilterContext *ctx) { DRContext *dr_context = ctx->priv; - - if (dr_context->dnn_module) { - (dr_context->dnn_module->free_model)(&dr_context->model); - av_freep(&dr_context->dnn_module); - } + ff_dnn_uninit(&dr_context->dnnctx); } static const AVFilterPad derain_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .config_props = config_inputs, .filter_frame = filter_frame, }, { NULL } diff -Nru ffmpeg-4.2.2/libavfilter/vf_deshake.c ffmpeg-4.4/libavfilter/vf_deshake.c --- ffmpeg-4.2.2/libavfilter/vf_deshake.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_deshake.c 2020-07-11 10:39:30.000000000 +0000 @@ -354,7 +354,7 @@ if (deshake->filename) deshake->fp = fopen(deshake->filename, "w"); if (deshake->fp) - fwrite("Ori x, Avg x, Fin x, Ori y, Avg y, Fin y, Ori angle, Avg angle, Fin angle, Ori zoom, Avg zoom, Fin zoom\n", sizeof(char), 104, deshake->fp); + fwrite("Ori x, Avg x, Fin x, Ori y, Avg y, Fin y, Ori angle, Avg angle, Fin angle, Ori zoom, Avg zoom, Fin zoom\n", 1, 104, deshake->fp); // Quadword align left edge of box for MMX code, adjust width if necessary // to keep right margin @@ -421,6 +421,7 @@ const int chroma_width = AV_CEIL_RSHIFT(link->w, desc->log2_chroma_w); const int chroma_height = AV_CEIL_RSHIFT(link->h, desc->log2_chroma_h); int aligned; + float transform_zoom; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { @@ -484,7 +485,7 @@ // Write statistics to file if (deshake->fp) { snprintf(tmp, 256, "%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n", orig.vec.x, deshake->avg.vec.x, t.vec.x, orig.vec.y, deshake->avg.vec.y, t.vec.y, orig.angle, deshake->avg.angle, t.angle, orig.zoom, deshake->avg.zoom, t.zoom); - fwrite(tmp, sizeof(char), strlen(tmp), deshake->fp); + fwrite(tmp, 1, strlen(tmp), deshake->fp); } // Turn relative current frame motion into absolute by adding it to the @@ -505,10 +506,12 @@ deshake->last.angle = t.angle; deshake->last.zoom = t.zoom; + transform_zoom = 1.0 + t.zoom / 100.0; + // Generate a luma transformation matrix - avfilter_get_matrix(t.vec.x, t.vec.y, t.angle, 1.0 + t.zoom / 100.0, matrix_y); + ff_get_matrix(t.vec.x, t.vec.y, t.angle, transform_zoom, transform_zoom, matrix_y); // Generate a chroma transformation matrix - avfilter_get_matrix(t.vec.x / (link->w / chroma_width), t.vec.y / (link->h / chroma_height), t.angle, 1.0 + t.zoom / 100.0, matrix_uv); + ff_get_matrix(t.vec.x / (link->w / chroma_width), t.vec.y / (link->h / chroma_height), t.angle, transform_zoom, transform_zoom, matrix_uv); // Transform the luma and chroma planes ret = deshake->transform(link->dst, link->w, link->h, chroma_width, chroma_height, matrix_y, matrix_uv, INTERPOLATE_BILINEAR, deshake->edge, in, out); diff -Nru ffmpeg-4.2.2/libavfilter/vf_deshake_opencl.c ffmpeg-4.4/libavfilter/vf_deshake_opencl.c --- ffmpeg-4.2.2/libavfilter/vf_deshake_opencl.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_deshake_opencl.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,2202 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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) 2000-2008, Intel Corporation, all rights reserved. + * Copyright (C) 2009, Willow Garage Inc., all rights reserved. + * Copyright (C) 2013, OpenCV Foundation, all rights reserved. + * Third party copyrights are property of their respective owners. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistribution's of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistribution's 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. + * + * * The name of the copyright holders may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * This software is provided by the copyright holders and contributors "as is" and + * any express or implied warranties, including, but not limited to, the implied + * warranties of merchantability and fitness for a particular purpose are disclaimed. + * In no event shall the Intel Corporation or contributors be liable for any direct, + * indirect, incidental, special, exemplary, or consequential damages + * (including, but not limited to, procurement of substitute goods or services; + * loss of use, data, or profits; or business interruption) however caused + * and on any theory of liability, whether in contract, strict liability, + * or tort (including negligence or otherwise) arising in any way out of + * the use of this software, even if advised of the possibility of such damage. + */ + +#include +#include +#include "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "libavutil/mem.h" +#include "libavutil/fifo.h" +#include "libavutil/common.h" +#include "libavutil/avassert.h" +#include "libavutil/pixfmt.h" +#include "avfilter.h" +#include "framequeue.h" +#include "filters.h" +#include "transform.h" +#include "formats.h" +#include "internal.h" +#include "opencl.h" +#include "opencl_source.h" +#include "video.h" + +/* +This filter matches feature points between frames (dealing with outliers) and then +uses the matches to estimate an affine transform between frames. This transform is +decomposed into various values (translation, scale, rotation) and the values are +summed relative to the start of the video to obtain on absolute camera position +for each frame. This "camera path" is then smoothed via a gaussian filter, resulting +in a new path that is turned back into an affine transform and applied to each +frame to render it. + +High-level overview: + +All of the work to extract motion data from frames occurs in queue_frame. Motion data +is buffered in a smoothing window, so queue_frame simply computes the absolute camera +positions and places them in ringbuffers. + +filter_frame is responsible for looking at the absolute camera positions currently +in the ringbuffers, applying the gaussian filter, and then transforming the frames. +*/ + +// Number of bits for BRIEF descriptors +#define BREIFN 512 +// Size of the patch from which a BRIEF descriptor is extracted +// This is the size used in OpenCV +#define BRIEF_PATCH_SIZE 31 +#define BRIEF_PATCH_SIZE_HALF (BRIEF_PATCH_SIZE / 2) + +#define MATCHES_CONTIG_SIZE 2000 + +#define ROUNDED_UP_DIV(a, b) ((a + (b - 1)) / b) + +typedef struct PointPair { + // Previous frame + cl_float2 p1; + // Current frame + cl_float2 p2; +} PointPair; + +typedef struct MotionVector { + PointPair p; + // Used to mark vectors as potential outliers + cl_int should_consider; +} MotionVector; + +// Denotes the indices for the different types of motion in the ringbuffers array +enum RingbufferIndices { + RingbufX, + RingbufY, + RingbufRot, + RingbufScaleX, + RingbufScaleY, + + // Should always be last + RingbufCount +}; + +// Struct that holds data for drawing point match debug data +typedef struct DebugMatches { + MotionVector *matches; + // The points used to calculate the affine transform for a frame + MotionVector model_matches[3]; + + int num_matches; + // For cases where we couldn't calculate a model + int num_model_matches; +} DebugMatches; + +// Groups together the ringbuffers that store absolute distortion / position values +// for each frame +typedef struct AbsoluteFrameMotion { + // Array with the various ringbuffers, indexed via the RingbufferIndices enum + AVFifoBuffer *ringbuffers[RingbufCount]; + + // Offset to get to the current frame being processed + // (not in bytes) + int curr_frame_offset; + // Keeps track of where the start and end of contiguous motion data is (to + // deal with cases where no motion data is found between two frames) + int data_start_offset; + int data_end_offset; + + AVFifoBuffer *debug_matches; +} AbsoluteFrameMotion; + +// Takes care of freeing the arrays within the DebugMatches inside of the +// debug_matches ringbuffer and then freeing the buffer itself. +static void free_debug_matches(AbsoluteFrameMotion *afm) { + DebugMatches dm; + + if (!afm->debug_matches) { + return; + } + + while (av_fifo_size(afm->debug_matches) > 0) { + av_fifo_generic_read( + afm->debug_matches, + &dm, + sizeof(DebugMatches), + NULL + ); + + av_freep(&dm.matches); + } + + av_fifo_freep(&afm->debug_matches); +} + +// Stores the translation, scale, rotation, and skew deltas between two frames +typedef struct FrameDelta { + cl_float2 translation; + float rotation; + cl_float2 scale; + cl_float2 skew; +} FrameDelta; + +typedef struct SimilarityMatrix { + // The 2x3 similarity matrix + double matrix[6]; +} SimilarityMatrix; + +typedef struct CropInfo { + // The top left corner of the bounding box for the crop + cl_float2 top_left; + // The bottom right corner of the bounding box for the crop + cl_float2 bottom_right; +} CropInfo; + +// Returned from function that determines start and end values for iteration +// around the current frame in a ringbuffer +typedef struct IterIndices { + int start; + int end; +} IterIndices; + +typedef struct DeshakeOpenCLContext { + OpenCLFilterContext ocf; + // Whether or not the above `OpenCLFilterContext` has been initialized + int initialized; + + // These variables are used in the activate callback + int64_t duration; + int eof; + + // State for random number generation + AVLFG alfg; + + // FIFO frame queue used to buffer future frames for processing + FFFrameQueue fq; + // Ringbuffers for frame positions + AbsoluteFrameMotion abs_motion; + + // The number of frames' motion to consider before and after the frame we are + // smoothing + int smooth_window; + // The number of the frame we are currently processing + int curr_frame; + + // Stores a 1d array of normalised gaussian kernel values for convolution + float *gauss_kernel; + + // Buffer for error values used in RANSAC code + float *ransac_err; + + // Information regarding how to crop the smoothed luminance (or RGB) planes + CropInfo crop_y; + // Information regarding how to crop the smoothed chroma planes + CropInfo crop_uv; + + // Whether or not we are processing YUV input (as oppposed to RGB) + int is_yuv; + // The underlying format of the hardware surfaces + int sw_format; + + // Buffer to copy `matches` into for the CPU to work with + MotionVector *matches_host; + MotionVector *matches_contig_host; + + MotionVector *inliers; + + cl_command_queue command_queue; + cl_kernel kernel_grayscale; + cl_kernel kernel_harris_response; + cl_kernel kernel_refine_features; + cl_kernel kernel_brief_descriptors; + cl_kernel kernel_match_descriptors; + cl_kernel kernel_transform; + cl_kernel kernel_crop_upscale; + + // Stores a frame converted to grayscale + cl_mem grayscale; + // Stores the harris response for a frame (measure of "cornerness" for each pixel) + cl_mem harris_buf; + + // Detected features after non-maximum suppression and sub-pixel refinement + cl_mem refined_features; + // Saved from the previous frame + cl_mem prev_refined_features; + + // BRIEF sampling pattern that is randomly initialized + cl_mem brief_pattern; + // Feature point descriptors for the current frame + cl_mem descriptors; + // Feature point descriptors for the previous frame + cl_mem prev_descriptors; + // Vectors between points in current and previous frame + cl_mem matches; + cl_mem matches_contig; + // Holds the matrix to transform luminance (or RGB) with + cl_mem transform_y; + // Holds the matrix to transform chroma with + cl_mem transform_uv; + + // Configurable options + + int tripod_mode; + int debug_on; + int should_crop; + + // Whether or not feature points should be refined at a sub-pixel level + cl_int refine_features; + // If the user sets a value other than the default, 0, this percentage is + // translated into a sigma value ranging from 0.5 to 40.0 + float smooth_percent; + // This number is multiplied by the video frame rate to determine the size + // of the smooth window + float smooth_window_multiplier; + + // Debug stuff + + cl_kernel kernel_draw_debug_info; + cl_mem debug_matches; + cl_mem debug_model_matches; + + // These store the total time spent executing the different kernels in nanoseconds + unsigned long long grayscale_time; + unsigned long long harris_response_time; + unsigned long long refine_features_time; + unsigned long long brief_descriptors_time; + unsigned long long match_descriptors_time; + unsigned long long transform_time; + unsigned long long crop_upscale_time; + + // Time spent copying matched features from the device to the host + unsigned long long read_buf_time; +} DeshakeOpenCLContext; + +// Returns a random uniformly-distributed number in [low, high] +static int rand_in(int low, int high, AVLFG *alfg) { + return (av_lfg_get(alfg) % (high - low)) + low; +} + +// Returns the average execution time for an event given the total time and the +// number of frames processed. +static double averaged_event_time_ms(unsigned long long total_time, int num_frames) { + return (double)total_time / (double)num_frames / 1000000.0; +} + +// The following code is loosely ported from OpenCV + +// Estimates affine transform from 3 point pairs +// model is a 2x3 matrix: +// a b c +// d e f +static void run_estimate_kernel(const MotionVector *point_pairs, double *model) +{ + // src points + double x1 = point_pairs[0].p.p1.s[0]; + double y1 = point_pairs[0].p.p1.s[1]; + double x2 = point_pairs[1].p.p1.s[0]; + double y2 = point_pairs[1].p.p1.s[1]; + double x3 = point_pairs[2].p.p1.s[0]; + double y3 = point_pairs[2].p.p1.s[1]; + + // dest points + double X1 = point_pairs[0].p.p2.s[0]; + double Y1 = point_pairs[0].p.p2.s[1]; + double X2 = point_pairs[1].p.p2.s[0]; + double Y2 = point_pairs[1].p.p2.s[1]; + double X3 = point_pairs[2].p.p2.s[0]; + double Y3 = point_pairs[2].p.p2.s[1]; + + double d = 1.0 / ( x1*(y2-y3) + x2*(y3-y1) + x3*(y1-y2) ); + + model[0] = d * ( X1*(y2-y3) + X2*(y3-y1) + X3*(y1-y2) ); + model[1] = d * ( X1*(x3-x2) + X2*(x1-x3) + X3*(x2-x1) ); + model[2] = d * ( X1*(x2*y3 - x3*y2) + X2*(x3*y1 - x1*y3) + X3*(x1*y2 - x2*y1) ); + + model[3] = d * ( Y1*(y2-y3) + Y2*(y3-y1) + Y3*(y1-y2) ); + model[4] = d * ( Y1*(x3-x2) + Y2*(x1-x3) + Y3*(x2-x1) ); + model[5] = d * ( Y1*(x2*y3 - x3*y2) + Y2*(x3*y1 - x1*y3) + Y3*(x1*y2 - x2*y1) ); +} + +// Checks that the 3 points in the given array are not collinear +static int points_not_collinear(const cl_float2 **points) +{ + int j, k, i = 2; + + for (j = 0; j < i; j++) { + double dx1 = points[j]->s[0] - points[i]->s[0]; + double dy1 = points[j]->s[1] - points[i]->s[1]; + + for (k = 0; k < j; k++) { + double dx2 = points[k]->s[0] - points[i]->s[0]; + double dy2 = points[k]->s[1] - points[i]->s[1]; + + // Assuming a 3840 x 2160 video with a point at (0, 0) and one at + // (3839, 2159), this prevents a third point from being within roughly + // 0.5 of a pixel of the line connecting the two on both axes + if (fabs(dx2*dy1 - dy2*dx1) <= 1.0) { + return 0; + } + } + } + + return 1; +} + +// Checks a subset of 3 point pairs to make sure that the points are not collinear +// and not too close to each other +static int check_subset(const MotionVector *pairs_subset) +{ + const cl_float2 *prev_points[] = { + &pairs_subset[0].p.p1, + &pairs_subset[1].p.p1, + &pairs_subset[2].p.p1 + }; + + const cl_float2 *curr_points[] = { + &pairs_subset[0].p.p2, + &pairs_subset[1].p.p2, + &pairs_subset[2].p.p2 + }; + + return points_not_collinear(prev_points) && points_not_collinear(curr_points); +} + +// Selects a random subset of 3 points from point_pairs and places them in pairs_subset +static int get_subset( + AVLFG *alfg, + const MotionVector *point_pairs, + const int num_point_pairs, + MotionVector *pairs_subset, + int max_attempts +) { + int idx[3]; + int i = 0, j, iters = 0; + + for (; iters < max_attempts; iters++) { + for (i = 0; i < 3 && iters < max_attempts;) { + int idx_i = 0; + + for (;;) { + idx_i = idx[i] = rand_in(0, num_point_pairs, alfg); + + for (j = 0; j < i; j++) { + if (idx_i == idx[j]) { + break; + } + } + + if (j == i) { + break; + } + } + + pairs_subset[i] = point_pairs[idx[i]]; + i++; + } + + if (i == 3 && !check_subset(pairs_subset)) { + continue; + } + break; + } + + return i == 3 && iters < max_attempts; +} + +// Computes the error for each of the given points based on the given model. +static void compute_error( + const MotionVector *point_pairs, + const int num_point_pairs, + const double *model, + float *err +) { + double F0 = model[0], F1 = model[1], F2 = model[2]; + double F3 = model[3], F4 = model[4], F5 = model[5]; + + for (int i = 0; i < num_point_pairs; i++) { + const cl_float2 *f = &point_pairs[i].p.p1; + const cl_float2 *t = &point_pairs[i].p.p2; + + double a = F0*f->s[0] + F1*f->s[1] + F2 - t->s[0]; + double b = F3*f->s[0] + F4*f->s[1] + F5 - t->s[1]; + + err[i] = a*a + b*b; + } +} + +// Determines which of the given point matches are inliers for the given model +// based on the specified threshold. +// +// err must be an array of num_point_pairs length +static int find_inliers( + MotionVector *point_pairs, + const int num_point_pairs, + const double *model, + float *err, + double thresh +) { + float t = (float)(thresh * thresh); + int i, n = num_point_pairs, num_inliers = 0; + + compute_error(point_pairs, num_point_pairs, model, err); + + for (i = 0; i < n; i++) { + if (err[i] <= t) { + // This is an inlier + point_pairs[i].should_consider = 1; + num_inliers += 1; + } else { + point_pairs[i].should_consider = 0; + } + } + + return num_inliers; +} + +// Determines the number of iterations required to achieve the desired confidence level. +// +// The equation used to determine the number of iterations to do is: +// 1 - confidence = (1 - inlier_probability^num_points)^num_iters +// +// Solving for num_iters: +// +// num_iters = log(1 - confidence) / log(1 - inlier_probability^num_points) +// +// A more in-depth explanation can be found at https://en.wikipedia.org/wiki/Random_sample_consensus +// under the 'Parameters' heading +static int ransac_update_num_iters(double confidence, double num_outliers, int max_iters) +{ + double num, denom; + + confidence = av_clipd(confidence, 0.0, 1.0); + num_outliers = av_clipd(num_outliers, 0.0, 1.0); + + // avoid inf's & nan's + num = FFMAX(1.0 - confidence, DBL_MIN); + denom = 1.0 - pow(1.0 - num_outliers, 3); + if (denom < DBL_MIN) { + return 0; + } + + num = log(num); + denom = log(denom); + + return denom >= 0 || -num >= max_iters * (-denom) ? max_iters : (int)round(num / denom); +} + +// Estimates an affine transform between the given pairs of points using RANdom +// SAmple Consensus +static int estimate_affine_2d( + DeshakeOpenCLContext *deshake_ctx, + MotionVector *point_pairs, + DebugMatches *debug_matches, + const int num_point_pairs, + double *model_out, + const double threshold, + const int max_iters, + const double confidence +) { + int result = 0; + double best_model[6], model[6]; + MotionVector pairs_subset[3], best_pairs[3]; + + int iter, niters = FFMAX(max_iters, 1); + int good_count, max_good_count = 0; + + // We need at least 3 points to build a model from + if (num_point_pairs < 3) { + return 0; + } else if (num_point_pairs == 3) { + // There are only 3 points, so RANSAC doesn't apply here + run_estimate_kernel(point_pairs, model_out); + + for (int i = 0; i < 3; ++i) { + point_pairs[i].should_consider = 1; + } + + return 1; + } + + for (iter = 0; iter < niters; ++iter) { + int found = get_subset(&deshake_ctx->alfg, point_pairs, num_point_pairs, pairs_subset, 10000); + + if (!found) { + if (iter == 0) { + return 0; + } + + break; + } + + run_estimate_kernel(pairs_subset, model); + good_count = find_inliers(point_pairs, num_point_pairs, model, deshake_ctx->ransac_err, threshold); + + if (good_count > FFMAX(max_good_count, 2)) { + for (int mi = 0; mi < 6; ++mi) { + best_model[mi] = model[mi]; + } + + for (int pi = 0; pi < 3; pi++) { + best_pairs[pi] = pairs_subset[pi]; + } + + max_good_count = good_count; + niters = ransac_update_num_iters( + confidence, + (double)(num_point_pairs - good_count) / num_point_pairs, + niters + ); + } + } + + if (max_good_count > 0) { + for (int mi = 0; mi < 6; ++mi) { + model_out[mi] = best_model[mi]; + } + + for (int pi = 0; pi < 3; ++pi) { + debug_matches->model_matches[pi] = best_pairs[pi]; + } + debug_matches->num_model_matches = 3; + + // Find the inliers again for the best model for debugging + find_inliers(point_pairs, num_point_pairs, best_model, deshake_ctx->ransac_err, threshold); + result = 1; + } + + return result; +} + +// "Wiggles" the first point in best_pairs around a tiny bit in order to decrease the +// total error +static void optimize_model( + DeshakeOpenCLContext *deshake_ctx, + MotionVector *best_pairs, + MotionVector *inliers, + const int num_inliers, + float best_err, + double *model_out +) { + float move_x_val = 0.01; + float move_y_val = 0.01; + int move_x = 1; + float old_move_x_val = 0; + double model[6]; + int last_changed = 0; + + for (int iters = 0; iters < 200; iters++) { + float total_err = 0; + + if (move_x) { + best_pairs[0].p.p2.s[0] += move_x_val; + } else { + best_pairs[0].p.p2.s[0] += move_y_val; + } + + run_estimate_kernel(best_pairs, model); + compute_error(inliers, num_inliers, model, deshake_ctx->ransac_err); + + for (int j = 0; j < num_inliers; j++) { + total_err += deshake_ctx->ransac_err[j]; + } + + if (total_err < best_err) { + for (int mi = 0; mi < 6; ++mi) { + model_out[mi] = model[mi]; + } + + best_err = total_err; + last_changed = iters; + } else { + // Undo the change + if (move_x) { + best_pairs[0].p.p2.s[0] -= move_x_val; + } else { + best_pairs[0].p.p2.s[0] -= move_y_val; + } + + if (iters - last_changed > 4) { + // We've already improved the model as much as we can + break; + } + + old_move_x_val = move_x_val; + + if (move_x) { + move_x_val *= -1; + } else { + move_y_val *= -1; + } + + if (old_move_x_val < 0) { + move_x = 0; + } else { + move_x = 1; + } + } + } +} + +// Uses a process similar to that of RANSAC to find a transform that minimizes +// the total error for a set of point matches determined to be inliers +// +// (Pick random subsets, compute model, find total error, iterate until error +// is minimized.) +static int minimize_error( + DeshakeOpenCLContext *deshake_ctx, + MotionVector *inliers, + DebugMatches *debug_matches, + const int num_inliers, + double *model_out, + const int max_iters +) { + int result = 0; + float best_err = FLT_MAX; + double best_model[6], model[6]; + MotionVector pairs_subset[3], best_pairs[3]; + + for (int i = 0; i < max_iters; i++) { + float total_err = 0; + int found = get_subset(&deshake_ctx->alfg, inliers, num_inliers, pairs_subset, 10000); + + if (!found) { + if (i == 0) { + return 0; + } + + break; + } + + run_estimate_kernel(pairs_subset, model); + compute_error(inliers, num_inliers, model, deshake_ctx->ransac_err); + + for (int j = 0; j < num_inliers; j++) { + total_err += deshake_ctx->ransac_err[j]; + } + + if (total_err < best_err) { + for (int mi = 0; mi < 6; ++mi) { + best_model[mi] = model[mi]; + } + + for (int pi = 0; pi < 3; pi++) { + best_pairs[pi] = pairs_subset[pi]; + } + + best_err = total_err; + } + } + + for (int mi = 0; mi < 6; ++mi) { + model_out[mi] = best_model[mi]; + } + + for (int pi = 0; pi < 3; ++pi) { + debug_matches->model_matches[pi] = best_pairs[pi]; + } + debug_matches->num_model_matches = 3; + result = 1; + + optimize_model(deshake_ctx, best_pairs, inliers, num_inliers, best_err, model_out); + return result; +} + +// End code from OpenCV + +// Decomposes a similarity matrix into translation, rotation, scale, and skew +// +// See http://frederic-wang.fr/decomposition-of-2d-transform-matrices.html +static FrameDelta decompose_transform(double *model) +{ + FrameDelta ret; + + double a = model[0]; + double c = model[1]; + double e = model[2]; + double b = model[3]; + double d = model[4]; + double f = model[5]; + double delta = a * d - b * c; + + memset(&ret, 0, sizeof(ret)); + + ret.translation.s[0] = e; + ret.translation.s[1] = f; + + // This is the QR method + if (a != 0 || b != 0) { + double r = hypot(a, b); + + ret.rotation = FFSIGN(b) * acos(a / r); + ret.scale.s[0] = r; + ret.scale.s[1] = delta / r; + ret.skew.s[0] = atan((a * c + b * d) / (r * r)); + ret.skew.s[1] = 0; + } else if (c != 0 || d != 0) { + double s = sqrt(c * c + d * d); + + ret.rotation = M_PI / 2 - FFSIGN(d) * acos(-c / s); + ret.scale.s[0] = delta / s; + ret.scale.s[1] = s; + ret.skew.s[0] = 0; + ret.skew.s[1] = atan((a * c + b * d) / (s * s)); + } // otherwise there is only translation + + return ret; +} + +// Move valid vectors from the 2d buffer into a 1d buffer where they are contiguous +static int make_vectors_contig( + DeshakeOpenCLContext *deshake_ctx, + int size_y, + int size_x +) { + int num_vectors = 0; + + for (int i = 0; i < size_y; ++i) { + for (int j = 0; j < size_x; ++j) { + MotionVector v = deshake_ctx->matches_host[j + i * size_x]; + + if (v.should_consider) { + deshake_ctx->matches_contig_host[num_vectors] = v; + ++num_vectors; + } + + // Make sure we do not exceed the amount of space we allocated for these vectors + if (num_vectors == MATCHES_CONTIG_SIZE - 1) { + return num_vectors; + } + } + } + return num_vectors; +} + +// Returns the gaussian kernel value for the given x coordinate and sigma value +static float gaussian_for(int x, float sigma) { + return 1.0f / expf(((float)x * (float)x) / (2.0f * sigma * sigma)); +} + +// Makes a normalized gaussian kernel of the given length for the given sigma +// and places it in gauss_kernel +static void make_gauss_kernel(float *gauss_kernel, float length, float sigma) +{ + float gauss_sum = 0; + int window_half = length / 2; + + for (int i = 0; i < length; ++i) { + float val = gaussian_for(i - window_half, sigma); + + gauss_sum += val; + gauss_kernel[i] = val; + } + + // Normalize the gaussian values + for (int i = 0; i < length; ++i) { + gauss_kernel[i] /= gauss_sum; + } +} + +// Returns indices to start and end iteration at in order to iterate over a window +// of length size centered at the current frame in a ringbuffer +// +// Always returns numbers that result in a window of length size, even if that +// means specifying negative indices or indices past the end of the values in the +// ringbuffers. Make sure you clip indices appropriately within your loop. +static IterIndices start_end_for(DeshakeOpenCLContext *deshake_ctx, int length) { + IterIndices indices; + + indices.start = deshake_ctx->abs_motion.curr_frame_offset - (length / 2); + indices.end = deshake_ctx->abs_motion.curr_frame_offset + (length / 2) + (length % 2); + + return indices; +} + +// Sets val to the value in the given ringbuffer at the given offset, taking care of +// clipping the offset into the appropriate range +static void ringbuf_float_at( + DeshakeOpenCLContext *deshake_ctx, + AVFifoBuffer *values, + float *val, + int offset +) { + int clip_start, clip_end, offset_clipped; + if (deshake_ctx->abs_motion.data_end_offset != -1) { + clip_end = deshake_ctx->abs_motion.data_end_offset; + } else { + // This expression represents the last valid index in the buffer, + // which we use repeatedly at the end of the video. + clip_end = deshake_ctx->smooth_window - (av_fifo_space(values) / sizeof(float)) - 1; + } + + if (deshake_ctx->abs_motion.data_start_offset != -1) { + clip_start = deshake_ctx->abs_motion.data_start_offset; + } else { + // Negative indices will occur at the start of the video, and we want + // them to be clipped to 0 in order to repeatedly use the position of + // the first frame. + clip_start = 0; + } + + offset_clipped = av_clip( + offset, + clip_start, + clip_end + ); + + av_fifo_generic_peek_at( + values, + val, + offset_clipped * sizeof(float), + sizeof(float), + NULL + ); +} + +// Returns smoothed current frame value of the given buffer of floats based on the +// given Gaussian kernel and its length (also the window length, centered around the +// current frame) and the "maximum value" of the motion. +// +// This "maximum value" should be the width / height of the image in the case of +// translation and an empirically chosen constant for rotation / scale. +// +// The sigma chosen to generate the final gaussian kernel with used to smooth the +// camera path is either hardcoded (set by user, deshake_ctx->smooth_percent) or +// adaptively chosen. +static float smooth( + DeshakeOpenCLContext *deshake_ctx, + float *gauss_kernel, + int length, + float max_val, + AVFifoBuffer *values +) { + float new_large_s = 0, new_small_s = 0, new_best = 0, old, diff_between, + percent_of_max, inverted_percent; + IterIndices indices = start_end_for(deshake_ctx, length); + float large_sigma = 40.0f; + float small_sigma = 2.0f; + float best_sigma; + + if (deshake_ctx->smooth_percent) { + best_sigma = (large_sigma - 0.5f) * deshake_ctx->smooth_percent + 0.5f; + } else { + // Strategy to adaptively smooth trajectory: + // + // 1. Smooth path with large and small sigma values + // 2. Take the absolute value of the difference between them + // 3. Get a percentage by putting the difference over the "max value" + // 4, Invert the percentage + // 5. Calculate a new sigma value weighted towards the larger sigma value + // 6. Determine final smoothed trajectory value using that sigma + + make_gauss_kernel(gauss_kernel, length, large_sigma); + for (int i = indices.start, j = 0; i < indices.end; ++i, ++j) { + ringbuf_float_at(deshake_ctx, values, &old, i); + new_large_s += old * gauss_kernel[j]; + } + + make_gauss_kernel(gauss_kernel, length, small_sigma); + for (int i = indices.start, j = 0; i < indices.end; ++i, ++j) { + ringbuf_float_at(deshake_ctx, values, &old, i); + new_small_s += old * gauss_kernel[j]; + } + + diff_between = fabsf(new_large_s - new_small_s); + percent_of_max = diff_between / max_val; + inverted_percent = 1 - percent_of_max; + best_sigma = large_sigma * powf(inverted_percent, 40); + } + + make_gauss_kernel(gauss_kernel, length, best_sigma); + for (int i = indices.start, j = 0; i < indices.end; ++i, ++j) { + ringbuf_float_at(deshake_ctx, values, &old, i); + new_best += old * gauss_kernel[j]; + } + + return new_best; +} + +// Returns the position of the given point after the transform is applied +static cl_float2 transformed_point(float x, float y, float *transform) { + cl_float2 ret; + + ret.s[0] = x * transform[0] + y * transform[1] + transform[2]; + ret.s[1] = x * transform[3] + y * transform[4] + transform[5]; + + return ret; +} + +// Creates an affine transform that scales from the center of a frame +static void transform_center_scale( + float x_shift, + float y_shift, + float angle, + float scale_x, + float scale_y, + float center_w, + float center_h, + float *matrix +) { + cl_float2 center_s; + float center_s_w, center_s_h; + + ff_get_matrix( + 0, + 0, + 0, + scale_x, + scale_y, + matrix + ); + + center_s = transformed_point(center_w, center_h, matrix); + center_s_w = center_w - center_s.s[0]; + center_s_h = center_h - center_s.s[1]; + + ff_get_matrix( + x_shift + center_s_w, + y_shift + center_s_h, + angle, + scale_x, + scale_y, + matrix + ); +} + +// Determines the crop necessary to eliminate black borders from a smoothed frame +// and updates target crop accordingly +static void update_needed_crop( + CropInfo* crop, + float *transform, + float frame_width, + float frame_height +) { + float new_width, new_height, adjusted_width, adjusted_height, adjusted_x, adjusted_y; + + cl_float2 top_left = transformed_point(0, 0, transform); + cl_float2 top_right = transformed_point(frame_width, 0, transform); + cl_float2 bottom_left = transformed_point(0, frame_height, transform); + cl_float2 bottom_right = transformed_point(frame_width, frame_height, transform); + float ar_h = frame_height / frame_width; + float ar_w = frame_width / frame_height; + + if (crop->bottom_right.s[0] == 0) { + // The crop hasn't been set to the original size of the plane + crop->bottom_right.s[0] = frame_width; + crop->bottom_right.s[1] = frame_height; + } + + crop->top_left.s[0] = FFMAX3( + crop->top_left.s[0], + top_left.s[0], + bottom_left.s[0] + ); + + crop->top_left.s[1] = FFMAX3( + crop->top_left.s[1], + top_left.s[1], + top_right.s[1] + ); + + crop->bottom_right.s[0] = FFMIN3( + crop->bottom_right.s[0], + bottom_right.s[0], + top_right.s[0] + ); + + crop->bottom_right.s[1] = FFMIN3( + crop->bottom_right.s[1], + bottom_right.s[1], + bottom_left.s[1] + ); + + // Make sure our potentially new bounding box has the same aspect ratio + new_height = crop->bottom_right.s[1] - crop->top_left.s[1]; + new_width = crop->bottom_right.s[0] - crop->top_left.s[0]; + + adjusted_width = new_height * ar_w; + adjusted_x = crop->bottom_right.s[0] - adjusted_width; + + if (adjusted_x >= crop->top_left.s[0]) { + crop->top_left.s[0] = adjusted_x; + } else { + adjusted_height = new_width * ar_h; + adjusted_y = crop->bottom_right.s[1] - adjusted_height; + crop->top_left.s[1] = adjusted_y; + } +} + +static av_cold void deshake_opencl_uninit(AVFilterContext *avctx) +{ + DeshakeOpenCLContext *ctx = avctx->priv; + cl_int cle; + + for (int i = 0; i < RingbufCount; i++) + av_fifo_freep(&ctx->abs_motion.ringbuffers[i]); + + if (ctx->debug_on) + free_debug_matches(&ctx->abs_motion); + + if (ctx->gauss_kernel) + av_freep(&ctx->gauss_kernel); + + if (ctx->ransac_err) + av_freep(&ctx->ransac_err); + + if (ctx->matches_host) + av_freep(&ctx->matches_host); + + if (ctx->matches_contig_host) + av_freep(&ctx->matches_contig_host); + + if (ctx->inliers) + av_freep(&ctx->inliers); + + ff_framequeue_free(&ctx->fq); + + CL_RELEASE_KERNEL(ctx->kernel_grayscale); + CL_RELEASE_KERNEL(ctx->kernel_harris_response); + CL_RELEASE_KERNEL(ctx->kernel_refine_features); + CL_RELEASE_KERNEL(ctx->kernel_brief_descriptors); + CL_RELEASE_KERNEL(ctx->kernel_match_descriptors); + CL_RELEASE_KERNEL(ctx->kernel_crop_upscale); + if (ctx->debug_on) + CL_RELEASE_KERNEL(ctx->kernel_draw_debug_info); + + CL_RELEASE_QUEUE(ctx->command_queue); + + if (!ctx->is_yuv) + CL_RELEASE_MEMORY(ctx->grayscale); + CL_RELEASE_MEMORY(ctx->harris_buf); + CL_RELEASE_MEMORY(ctx->refined_features); + CL_RELEASE_MEMORY(ctx->prev_refined_features); + CL_RELEASE_MEMORY(ctx->brief_pattern); + CL_RELEASE_MEMORY(ctx->descriptors); + CL_RELEASE_MEMORY(ctx->prev_descriptors); + CL_RELEASE_MEMORY(ctx->matches); + CL_RELEASE_MEMORY(ctx->matches_contig); + CL_RELEASE_MEMORY(ctx->transform_y); + CL_RELEASE_MEMORY(ctx->transform_uv); + if (ctx->debug_on) { + CL_RELEASE_MEMORY(ctx->debug_matches); + CL_RELEASE_MEMORY(ctx->debug_model_matches); + } + + ff_opencl_filter_uninit(avctx); +} + +static int deshake_opencl_init(AVFilterContext *avctx) +{ + DeshakeOpenCLContext *ctx = avctx->priv; + AVFilterLink *outlink = avctx->outputs[0]; + AVFilterLink *inlink = avctx->inputs[0]; + // Pointer to the host-side pattern buffer to be initialized and then copied + // to the GPU + PointPair *pattern_host = NULL; + cl_int cle; + int err; + cl_ulong8 zeroed_ulong8; + FFFrameQueueGlobal fqg; + cl_image_format grayscale_format; + cl_image_desc grayscale_desc; + cl_command_queue_properties queue_props; + + const enum AVPixelFormat disallowed_formats[14] = { + AV_PIX_FMT_GBRP, + AV_PIX_FMT_GBRP9BE, + AV_PIX_FMT_GBRP9LE, + AV_PIX_FMT_GBRP10BE, + AV_PIX_FMT_GBRP10LE, + AV_PIX_FMT_GBRP16BE, + AV_PIX_FMT_GBRP16LE, + AV_PIX_FMT_GBRAP, + AV_PIX_FMT_GBRAP16BE, + AV_PIX_FMT_GBRAP16LE, + AV_PIX_FMT_GBRAP12BE, + AV_PIX_FMT_GBRAP12LE, + AV_PIX_FMT_GBRAP10BE, + AV_PIX_FMT_GBRAP10LE + }; + + // Number of elements for an array + const int image_grid_32 = ROUNDED_UP_DIV(outlink->h, 32) * ROUNDED_UP_DIV(outlink->w, 32); + + const int descriptor_buf_size = image_grid_32 * (BREIFN / 8); + const int features_buf_size = image_grid_32 * sizeof(cl_float2); + + const AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hw_frames_ctx->sw_format); + + av_assert0(hw_frames_ctx); + av_assert0(desc); + + ff_framequeue_global_init(&fqg); + ff_framequeue_init(&ctx->fq, &fqg); + ctx->eof = 0; + ctx->smooth_window = (int)(av_q2d(avctx->inputs[0]->frame_rate) * ctx->smooth_window_multiplier); + ctx->curr_frame = 0; + + memset(&zeroed_ulong8, 0, sizeof(cl_ulong8)); + + ctx->gauss_kernel = av_malloc_array(ctx->smooth_window, sizeof(float)); + if (!ctx->gauss_kernel) { + err = AVERROR(ENOMEM); + goto fail; + } + + ctx->ransac_err = av_malloc_array(MATCHES_CONTIG_SIZE, sizeof(float)); + if (!ctx->ransac_err) { + err = AVERROR(ENOMEM); + goto fail; + } + + for (int i = 0; i < RingbufCount; i++) { + ctx->abs_motion.ringbuffers[i] = av_fifo_alloc_array( + ctx->smooth_window, + sizeof(float) + ); + + if (!ctx->abs_motion.ringbuffers[i]) { + err = AVERROR(ENOMEM); + goto fail; + } + } + + if (ctx->debug_on) { + ctx->abs_motion.debug_matches = av_fifo_alloc_array( + ctx->smooth_window / 2, + sizeof(DebugMatches) + ); + + if (!ctx->abs_motion.debug_matches) { + err = AVERROR(ENOMEM); + goto fail; + } + } + + ctx->abs_motion.curr_frame_offset = 0; + ctx->abs_motion.data_start_offset = -1; + ctx->abs_motion.data_end_offset = -1; + + pattern_host = av_malloc_array(BREIFN, sizeof(PointPair)); + if (!pattern_host) { + err = AVERROR(ENOMEM); + goto fail; + } + + ctx->matches_host = av_malloc_array(image_grid_32, sizeof(MotionVector)); + if (!ctx->matches_host) { + err = AVERROR(ENOMEM); + goto fail; + } + + ctx->matches_contig_host = av_malloc_array(MATCHES_CONTIG_SIZE, sizeof(MotionVector)); + if (!ctx->matches_contig_host) { + err = AVERROR(ENOMEM); + goto fail; + } + + ctx->inliers = av_malloc_array(MATCHES_CONTIG_SIZE, sizeof(MotionVector)); + if (!ctx->inliers) { + err = AVERROR(ENOMEM); + goto fail; + } + + // Initializing the patch pattern for building BREIF descriptors with + av_lfg_init(&ctx->alfg, 234342424); + for (int i = 0; i < BREIFN; ++i) { + PointPair pair; + + for (int j = 0; j < 2; ++j) { + pair.p1.s[j] = rand_in(-BRIEF_PATCH_SIZE_HALF, BRIEF_PATCH_SIZE_HALF + 1, &ctx->alfg); + pair.p2.s[j] = rand_in(-BRIEF_PATCH_SIZE_HALF, BRIEF_PATCH_SIZE_HALF + 1, &ctx->alfg); + } + + pattern_host[i] = pair; + } + + for (int i = 0; i < 14; i++) { + if (ctx->sw_format == disallowed_formats[i]) { + av_log(avctx, AV_LOG_ERROR, "unsupported format in deshake_opencl.\n"); + err = AVERROR(ENOSYS); + goto fail; + } + } + + if (desc->flags & AV_PIX_FMT_FLAG_RGB) { + ctx->is_yuv = 0; + } else { + ctx->is_yuv = 1; + } + ctx->sw_format = hw_frames_ctx->sw_format; + + err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_deshake, 1); + if (err < 0) + goto fail; + + if (ctx->debug_on) { + queue_props = CL_QUEUE_PROFILING_ENABLE; + } else { + queue_props = 0; + } + ctx->command_queue = clCreateCommandQueue( + ctx->ocf.hwctx->context, + ctx->ocf.hwctx->device_id, + queue_props, + &cle + ); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create OpenCL command queue %d.\n", cle); + + CL_CREATE_KERNEL(ctx, grayscale); + CL_CREATE_KERNEL(ctx, harris_response); + CL_CREATE_KERNEL(ctx, refine_features); + CL_CREATE_KERNEL(ctx, brief_descriptors); + CL_CREATE_KERNEL(ctx, match_descriptors); + CL_CREATE_KERNEL(ctx, transform); + CL_CREATE_KERNEL(ctx, crop_upscale); + if (ctx->debug_on) + CL_CREATE_KERNEL(ctx, draw_debug_info); + + if (!ctx->is_yuv) { + grayscale_format.image_channel_order = CL_R; + grayscale_format.image_channel_data_type = CL_FLOAT; + + grayscale_desc = (cl_image_desc) { + .image_type = CL_MEM_OBJECT_IMAGE2D, + .image_width = outlink->w, + .image_height = outlink->h, + .image_depth = 0, + .image_array_size = 0, + .image_row_pitch = 0, + .image_slice_pitch = 0, + .num_mip_levels = 0, + .num_samples = 0, + .buffer = NULL, + }; + + ctx->grayscale = clCreateImage( + ctx->ocf.hwctx->context, + 0, + &grayscale_format, + &grayscale_desc, + NULL, + &cle + ); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create grayscale image: %d.\n", cle); + } + + CL_CREATE_BUFFER(ctx, harris_buf, outlink->h * outlink->w * sizeof(float)); + CL_CREATE_BUFFER(ctx, refined_features, features_buf_size); + CL_CREATE_BUFFER(ctx, prev_refined_features, features_buf_size); + CL_CREATE_BUFFER_FLAGS( + ctx, + brief_pattern, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + BREIFN * sizeof(PointPair), + pattern_host + ); + CL_CREATE_BUFFER(ctx, descriptors, descriptor_buf_size); + CL_CREATE_BUFFER(ctx, prev_descriptors, descriptor_buf_size); + CL_CREATE_BUFFER(ctx, matches, image_grid_32 * sizeof(MotionVector)); + CL_CREATE_BUFFER(ctx, matches_contig, MATCHES_CONTIG_SIZE * sizeof(MotionVector)); + CL_CREATE_BUFFER(ctx, transform_y, 9 * sizeof(float)); + CL_CREATE_BUFFER(ctx, transform_uv, 9 * sizeof(float)); + if (ctx->debug_on) { + CL_CREATE_BUFFER(ctx, debug_matches, MATCHES_CONTIG_SIZE * sizeof(MotionVector)); + CL_CREATE_BUFFER(ctx, debug_model_matches, 3 * sizeof(MotionVector)); + } + + ctx->initialized = 1; + av_freep(&pattern_host); + + return 0; + +fail: + av_freep(&pattern_host); + return err; +} + +// Logs debug information about the transform data +static void transform_debug(AVFilterContext *avctx, float *new_vals, float *old_vals, int curr_frame) { + av_log(avctx, AV_LOG_VERBOSE, + "Frame %d:\n" + "\tframe moved from: %f x, %f y\n" + "\t to: %f x, %f y\n" + "\t rotated from: %f degrees\n" + "\t to: %f degrees\n" + "\t scaled from: %f x, %f y\n" + "\t to: %f x, %f y\n" + "\n" + "\tframe moved by: %f x, %f y\n" + "\t rotated by: %f degrees\n" + "\t scaled by: %f x, %f y\n", + curr_frame, + old_vals[RingbufX], old_vals[RingbufY], + new_vals[RingbufX], new_vals[RingbufY], + old_vals[RingbufRot] * (180.0 / M_PI), + new_vals[RingbufRot] * (180.0 / M_PI), + old_vals[RingbufScaleX], old_vals[RingbufScaleY], + new_vals[RingbufScaleX], new_vals[RingbufScaleY], + old_vals[RingbufX] - new_vals[RingbufX], old_vals[RingbufY] - new_vals[RingbufY], + old_vals[RingbufRot] * (180.0 / M_PI) - new_vals[RingbufRot] * (180.0 / M_PI), + new_vals[RingbufScaleX] / old_vals[RingbufScaleX], new_vals[RingbufScaleY] / old_vals[RingbufScaleY] + ); +} + +// Uses the buffered motion information to determine a transform that smooths the +// given frame and applies it +static int filter_frame(AVFilterLink *link, AVFrame *input_frame) +{ + AVFilterContext *avctx = link->dst; + AVFilterLink *outlink = avctx->outputs[0]; + DeshakeOpenCLContext *deshake_ctx = avctx->priv; + AVFrame *cropped_frame = NULL, *transformed_frame = NULL; + int err; + cl_int cle; + float new_vals[RingbufCount]; + float old_vals[RingbufCount]; + // Luma (in the case of YUV) transform, or just the transform in the case of RGB + float transform_y[9]; + // Chroma transform + float transform_uv[9]; + // Luma crop transform (or RGB) + float transform_crop_y[9]; + // Chroma crop transform + float transform_crop_uv[9]; + float transform_debug_rgb[9]; + size_t global_work[2]; + int64_t duration; + cl_mem src, transformed, dst; + cl_mem transforms[3]; + CropInfo crops[3]; + cl_event transform_event, crop_upscale_event; + DebugMatches debug_matches; + cl_int num_model_matches; + + const float center_w = (float)input_frame->width / 2; + const float center_h = (float)input_frame->height / 2; + + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(deshake_ctx->sw_format); + const int chroma_width = AV_CEIL_RSHIFT(input_frame->width, desc->log2_chroma_w); + const int chroma_height = AV_CEIL_RSHIFT(input_frame->height, desc->log2_chroma_h); + + const float center_w_chroma = (float)chroma_width / 2; + const float center_h_chroma = (float)chroma_height / 2; + + const float luma_w_over_chroma_w = ((float)input_frame->width / (float)chroma_width); + const float luma_h_over_chroma_h = ((float)input_frame->height / (float)chroma_height); + + if (deshake_ctx->debug_on) { + av_fifo_generic_read( + deshake_ctx->abs_motion.debug_matches, + &debug_matches, + sizeof(DebugMatches), + NULL + ); + } + + if (input_frame->pkt_duration) { + duration = input_frame->pkt_duration; + } else { + duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); + } + deshake_ctx->duration = input_frame->pts + duration; + + // Get the absolute transform data for this frame + for (int i = 0; i < RingbufCount; i++) { + av_fifo_generic_peek_at( + deshake_ctx->abs_motion.ringbuffers[i], + &old_vals[i], + deshake_ctx->abs_motion.curr_frame_offset * sizeof(float), + sizeof(float), + NULL + ); + } + + if (deshake_ctx->tripod_mode) { + // If tripod mode is turned on we simply undo all motion relative to the + // first frame + + new_vals[RingbufX] = 0.0f; + new_vals[RingbufY] = 0.0f; + new_vals[RingbufRot] = 0.0f; + new_vals[RingbufScaleX] = 1.0f; + new_vals[RingbufScaleY] = 1.0f; + } else { + // Tripod mode is off and we need to smooth a moving camera + + new_vals[RingbufX] = smooth( + deshake_ctx, + deshake_ctx->gauss_kernel, + deshake_ctx->smooth_window, + input_frame->width, + deshake_ctx->abs_motion.ringbuffers[RingbufX] + ); + new_vals[RingbufY] = smooth( + deshake_ctx, + deshake_ctx->gauss_kernel, + deshake_ctx->smooth_window, + input_frame->height, + deshake_ctx->abs_motion.ringbuffers[RingbufY] + ); + new_vals[RingbufRot] = smooth( + deshake_ctx, + deshake_ctx->gauss_kernel, + deshake_ctx->smooth_window, + M_PI / 4, + deshake_ctx->abs_motion.ringbuffers[RingbufRot] + ); + new_vals[RingbufScaleX] = smooth( + deshake_ctx, + deshake_ctx->gauss_kernel, + deshake_ctx->smooth_window, + 2.0f, + deshake_ctx->abs_motion.ringbuffers[RingbufScaleX] + ); + new_vals[RingbufScaleY] = smooth( + deshake_ctx, + deshake_ctx->gauss_kernel, + deshake_ctx->smooth_window, + 2.0f, + deshake_ctx->abs_motion.ringbuffers[RingbufScaleY] + ); + } + + transform_center_scale( + old_vals[RingbufX] - new_vals[RingbufX], + old_vals[RingbufY] - new_vals[RingbufY], + old_vals[RingbufRot] - new_vals[RingbufRot], + new_vals[RingbufScaleX] / old_vals[RingbufScaleX], + new_vals[RingbufScaleY] / old_vals[RingbufScaleY], + center_w, + center_h, + transform_y + ); + + transform_center_scale( + (old_vals[RingbufX] - new_vals[RingbufX]) / luma_w_over_chroma_w, + (old_vals[RingbufY] - new_vals[RingbufY]) / luma_h_over_chroma_h, + old_vals[RingbufRot] - new_vals[RingbufRot], + new_vals[RingbufScaleX] / old_vals[RingbufScaleX], + new_vals[RingbufScaleY] / old_vals[RingbufScaleY], + center_w_chroma, + center_h_chroma, + transform_uv + ); + + CL_BLOCKING_WRITE_BUFFER(deshake_ctx->command_queue, deshake_ctx->transform_y, 9 * sizeof(float), transform_y, NULL); + CL_BLOCKING_WRITE_BUFFER(deshake_ctx->command_queue, deshake_ctx->transform_uv, 9 * sizeof(float), transform_uv, NULL); + + if (deshake_ctx->debug_on) + transform_debug(avctx, new_vals, old_vals, deshake_ctx->curr_frame); + + cropped_frame = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!cropped_frame) { + err = AVERROR(ENOMEM); + goto fail; + } + + transformed_frame = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!transformed_frame) { + err = AVERROR(ENOMEM); + goto fail; + } + + transforms[0] = deshake_ctx->transform_y; + transforms[1] = transforms[2] = deshake_ctx->transform_uv; + + for (int p = 0; p < FF_ARRAY_ELEMS(transformed_frame->data); p++) { + // Transform all of the planes appropriately + src = (cl_mem)input_frame->data[p]; + transformed = (cl_mem)transformed_frame->data[p]; + + if (!transformed) + break; + + err = ff_opencl_filter_work_size_from_image(avctx, global_work, input_frame, p, 0); + if (err < 0) + goto fail; + + CL_RUN_KERNEL_WITH_ARGS( + deshake_ctx->command_queue, + deshake_ctx->kernel_transform, + global_work, + NULL, + &transform_event, + { sizeof(cl_mem), &src }, + { sizeof(cl_mem), &transformed }, + { sizeof(cl_mem), &transforms[p] }, + ); + } + + if (deshake_ctx->debug_on && !deshake_ctx->is_yuv && debug_matches.num_matches > 0) { + CL_BLOCKING_WRITE_BUFFER( + deshake_ctx->command_queue, + deshake_ctx->debug_matches, + debug_matches.num_matches * sizeof(MotionVector), + debug_matches.matches, + NULL + ); + + CL_BLOCKING_WRITE_BUFFER( + deshake_ctx->command_queue, + deshake_ctx->debug_model_matches, + debug_matches.num_model_matches * sizeof(MotionVector), + debug_matches.model_matches, + NULL + ); + + num_model_matches = debug_matches.num_model_matches; + + // Invert the transform + transform_center_scale( + new_vals[RingbufX] - old_vals[RingbufX], + new_vals[RingbufY] - old_vals[RingbufY], + new_vals[RingbufRot] - old_vals[RingbufRot], + old_vals[RingbufScaleX] / new_vals[RingbufScaleX], + old_vals[RingbufScaleY] / new_vals[RingbufScaleY], + center_w, + center_h, + transform_debug_rgb + ); + + CL_BLOCKING_WRITE_BUFFER(deshake_ctx->command_queue, deshake_ctx->transform_y, 9 * sizeof(float), transform_debug_rgb, NULL); + + transformed = (cl_mem)transformed_frame->data[0]; + CL_RUN_KERNEL_WITH_ARGS( + deshake_ctx->command_queue, + deshake_ctx->kernel_draw_debug_info, + (size_t[]){ debug_matches.num_matches }, + NULL, + NULL, + { sizeof(cl_mem), &transformed }, + { sizeof(cl_mem), &deshake_ctx->debug_matches }, + { sizeof(cl_mem), &deshake_ctx->debug_model_matches }, + { sizeof(cl_int), &num_model_matches }, + { sizeof(cl_mem), &deshake_ctx->transform_y } + ); + } + + if (deshake_ctx->should_crop) { + // Generate transforms for cropping + transform_center_scale( + (old_vals[RingbufX] - new_vals[RingbufX]) / 5, + (old_vals[RingbufY] - new_vals[RingbufY]) / 5, + (old_vals[RingbufRot] - new_vals[RingbufRot]) / 5, + new_vals[RingbufScaleX] / old_vals[RingbufScaleX], + new_vals[RingbufScaleY] / old_vals[RingbufScaleY], + center_w, + center_h, + transform_crop_y + ); + update_needed_crop(&deshake_ctx->crop_y, transform_crop_y, input_frame->width, input_frame->height); + + transform_center_scale( + (old_vals[RingbufX] - new_vals[RingbufX]) / (5 * luma_w_over_chroma_w), + (old_vals[RingbufY] - new_vals[RingbufY]) / (5 * luma_h_over_chroma_h), + (old_vals[RingbufRot] - new_vals[RingbufRot]) / 5, + new_vals[RingbufScaleX] / old_vals[RingbufScaleX], + new_vals[RingbufScaleY] / old_vals[RingbufScaleY], + center_w_chroma, + center_h_chroma, + transform_crop_uv + ); + update_needed_crop(&deshake_ctx->crop_uv, transform_crop_uv, chroma_width, chroma_height); + + crops[0] = deshake_ctx->crop_y; + crops[1] = crops[2] = deshake_ctx->crop_uv; + + for (int p = 0; p < FF_ARRAY_ELEMS(cropped_frame->data); p++) { + // Crop all of the planes appropriately + dst = (cl_mem)cropped_frame->data[p]; + transformed = (cl_mem)transformed_frame->data[p]; + + if (!dst) + break; + + err = ff_opencl_filter_work_size_from_image(avctx, global_work, input_frame, p, 0); + if (err < 0) + goto fail; + + CL_RUN_KERNEL_WITH_ARGS( + deshake_ctx->command_queue, + deshake_ctx->kernel_crop_upscale, + global_work, + NULL, + &crop_upscale_event, + { sizeof(cl_mem), &transformed }, + { sizeof(cl_mem), &dst }, + { sizeof(cl_float2), &crops[p].top_left }, + { sizeof(cl_float2), &crops[p].bottom_right }, + ); + } + } + + if (deshake_ctx->curr_frame < deshake_ctx->smooth_window / 2) { + // This means we are somewhere at the start of the video. We need to + // increment the current frame offset until it reaches the center of + // the ringbuffers (as the current frame will be located there for + // the rest of the video). + // + // The end of the video is taken care of by draining motion data + // one-by-one out of the buffer, causing the (at that point fixed) + // offset to move towards later frames' data. + ++deshake_ctx->abs_motion.curr_frame_offset; + } + + if (deshake_ctx->abs_motion.data_end_offset != -1) { + // Keep the end offset in sync with the frame it's supposed to be + // positioned at + --deshake_ctx->abs_motion.data_end_offset; + + if (deshake_ctx->abs_motion.data_end_offset == deshake_ctx->abs_motion.curr_frame_offset - 1) { + // The end offset would be the start of the new video sequence; flip to + // start offset + deshake_ctx->abs_motion.data_end_offset = -1; + deshake_ctx->abs_motion.data_start_offset = deshake_ctx->abs_motion.curr_frame_offset; + } + } else if (deshake_ctx->abs_motion.data_start_offset != -1) { + // Keep the start offset in sync with the frame it's supposed to be + // positioned at + --deshake_ctx->abs_motion.data_start_offset; + } + + if (deshake_ctx->debug_on) { + deshake_ctx->transform_time += ff_opencl_get_event_time(transform_event); + if (deshake_ctx->should_crop) { + deshake_ctx->crop_upscale_time += ff_opencl_get_event_time(crop_upscale_event); + } + } + + ++deshake_ctx->curr_frame; + + if (deshake_ctx->debug_on) + av_freep(&debug_matches.matches); + + if (deshake_ctx->should_crop) { + err = av_frame_copy_props(cropped_frame, input_frame); + if (err < 0) + goto fail; + + av_frame_free(&transformed_frame); + av_frame_free(&input_frame); + return ff_filter_frame(outlink, cropped_frame); + + } else { + err = av_frame_copy_props(transformed_frame, input_frame); + if (err < 0) + goto fail; + + av_frame_free(&cropped_frame); + av_frame_free(&input_frame); + return ff_filter_frame(outlink, transformed_frame); + } + +fail: + clFinish(deshake_ctx->command_queue); + + if (deshake_ctx->debug_on) + if (debug_matches.matches) + av_freep(&debug_matches.matches); + + av_frame_free(&input_frame); + av_frame_free(&transformed_frame); + av_frame_free(&cropped_frame); + return err; +} + +// Add the given frame to the frame queue to eventually be processed. +// +// Also determines the motion from the previous frame and updates the stored +// motion information accordingly. +static int queue_frame(AVFilterLink *link, AVFrame *input_frame) +{ + AVFilterContext *avctx = link->dst; + DeshakeOpenCLContext *deshake_ctx = avctx->priv; + int err; + int num_vectors; + int num_inliers = 0; + cl_int cle; + FrameDelta relative; + SimilarityMatrix model; + size_t global_work[2]; + size_t harris_global_work[2]; + size_t grid_32_global_work[2]; + int grid_32_h, grid_32_w; + size_t local_work[2]; + cl_mem src, temp; + float prev_vals[5]; + float new_vals[5]; + cl_event grayscale_event, harris_response_event, refine_features_event, + brief_event, match_descriptors_event, read_buf_event; + DebugMatches debug_matches; + + num_vectors = 0; + + local_work[0] = 8; + local_work[1] = 8; + + err = ff_opencl_filter_work_size_from_image(avctx, global_work, input_frame, 0, 0); + if (err < 0) + goto fail; + + err = ff_opencl_filter_work_size_from_image(avctx, harris_global_work, input_frame, 0, 8); + if (err < 0) + goto fail; + + err = ff_opencl_filter_work_size_from_image(avctx, grid_32_global_work, input_frame, 0, 32); + if (err < 0) + goto fail; + + // We want a single work-item for each 32x32 block of pixels in the input frame + grid_32_global_work[0] /= 32; + grid_32_global_work[1] /= 32; + + grid_32_h = ROUNDED_UP_DIV(input_frame->height, 32); + grid_32_w = ROUNDED_UP_DIV(input_frame->width, 32); + + if (deshake_ctx->is_yuv) { + deshake_ctx->grayscale = (cl_mem)input_frame->data[0]; + } else { + src = (cl_mem)input_frame->data[0]; + + CL_RUN_KERNEL_WITH_ARGS( + deshake_ctx->command_queue, + deshake_ctx->kernel_grayscale, + global_work, + NULL, + &grayscale_event, + { sizeof(cl_mem), &src }, + { sizeof(cl_mem), &deshake_ctx->grayscale } + ); + } + + CL_RUN_KERNEL_WITH_ARGS( + deshake_ctx->command_queue, + deshake_ctx->kernel_harris_response, + harris_global_work, + local_work, + &harris_response_event, + { sizeof(cl_mem), &deshake_ctx->grayscale }, + { sizeof(cl_mem), &deshake_ctx->harris_buf } + ); + + CL_RUN_KERNEL_WITH_ARGS( + deshake_ctx->command_queue, + deshake_ctx->kernel_refine_features, + grid_32_global_work, + NULL, + &refine_features_event, + { sizeof(cl_mem), &deshake_ctx->grayscale }, + { sizeof(cl_mem), &deshake_ctx->harris_buf }, + { sizeof(cl_mem), &deshake_ctx->refined_features }, + { sizeof(cl_int), &deshake_ctx->refine_features } + ); + + CL_RUN_KERNEL_WITH_ARGS( + deshake_ctx->command_queue, + deshake_ctx->kernel_brief_descriptors, + grid_32_global_work, + NULL, + &brief_event, + { sizeof(cl_mem), &deshake_ctx->grayscale }, + { sizeof(cl_mem), &deshake_ctx->refined_features }, + { sizeof(cl_mem), &deshake_ctx->descriptors }, + { sizeof(cl_mem), &deshake_ctx->brief_pattern} + ); + + if (av_fifo_size(deshake_ctx->abs_motion.ringbuffers[RingbufX]) == 0) { + // This is the first frame we've been given to queue, meaning there is + // no previous frame to match descriptors to + + goto no_motion_data; + } + + CL_RUN_KERNEL_WITH_ARGS( + deshake_ctx->command_queue, + deshake_ctx->kernel_match_descriptors, + grid_32_global_work, + NULL, + &match_descriptors_event, + { sizeof(cl_mem), &deshake_ctx->prev_refined_features }, + { sizeof(cl_mem), &deshake_ctx->refined_features }, + { sizeof(cl_mem), &deshake_ctx->descriptors }, + { sizeof(cl_mem), &deshake_ctx->prev_descriptors }, + { sizeof(cl_mem), &deshake_ctx->matches } + ); + + cle = clEnqueueReadBuffer( + deshake_ctx->command_queue, + deshake_ctx->matches, + CL_TRUE, + 0, + grid_32_h * grid_32_w * sizeof(MotionVector), + deshake_ctx->matches_host, + 0, + NULL, + &read_buf_event + ); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to read matches to host: %d.\n", cle); + + num_vectors = make_vectors_contig(deshake_ctx, grid_32_h, grid_32_w); + + if (num_vectors < 10) { + // Not enough matches to get reliable motion data for this frame + // + // From this point on all data is relative to this frame rather than the + // original frame. We have to make sure that we don't mix values that were + // relative to the original frame with the new values relative to this + // frame when doing the gaussian smoothing. We keep track of where the old + // values end using this data_end_offset field in order to accomplish + // that goal. + // + // If no motion data is present for multiple frames in a short window of + // time, we leave the end where it was to avoid mixing 0s in with the + // old data (and just treat them all as part of the new values) + if (deshake_ctx->abs_motion.data_end_offset == -1) { + deshake_ctx->abs_motion.data_end_offset = + av_fifo_size(deshake_ctx->abs_motion.ringbuffers[RingbufX]) / sizeof(float) - 1; + } + + goto no_motion_data; + } + + if (!estimate_affine_2d( + deshake_ctx, + deshake_ctx->matches_contig_host, + &debug_matches, + num_vectors, + model.matrix, + 10.0, + 3000, + 0.999999999999 + )) { + goto no_motion_data; + } + + for (int i = 0; i < num_vectors; i++) { + if (deshake_ctx->matches_contig_host[i].should_consider) { + deshake_ctx->inliers[num_inliers] = deshake_ctx->matches_contig_host[i]; + num_inliers++; + } + } + + if (!minimize_error( + deshake_ctx, + deshake_ctx->inliers, + &debug_matches, + num_inliers, + model.matrix, + 400 + )) { + goto no_motion_data; + } + + + relative = decompose_transform(model.matrix); + + // Get the absolute transform data for the previous frame + for (int i = 0; i < RingbufCount; i++) { + av_fifo_generic_peek_at( + deshake_ctx->abs_motion.ringbuffers[i], + &prev_vals[i], + av_fifo_size(deshake_ctx->abs_motion.ringbuffers[i]) - sizeof(float), + sizeof(float), + NULL + ); + } + + new_vals[RingbufX] = prev_vals[RingbufX] + relative.translation.s[0]; + new_vals[RingbufY] = prev_vals[RingbufY] + relative.translation.s[1]; + new_vals[RingbufRot] = prev_vals[RingbufRot] + relative.rotation; + new_vals[RingbufScaleX] = prev_vals[RingbufScaleX] / relative.scale.s[0]; + new_vals[RingbufScaleY] = prev_vals[RingbufScaleY] / relative.scale.s[1]; + + if (deshake_ctx->debug_on) { + if (!deshake_ctx->is_yuv) { + deshake_ctx->grayscale_time += ff_opencl_get_event_time(grayscale_event); + } + deshake_ctx->harris_response_time += ff_opencl_get_event_time(harris_response_event); + deshake_ctx->refine_features_time += ff_opencl_get_event_time(refine_features_event); + deshake_ctx->brief_descriptors_time += ff_opencl_get_event_time(brief_event); + deshake_ctx->match_descriptors_time += ff_opencl_get_event_time(match_descriptors_event); + deshake_ctx->read_buf_time += ff_opencl_get_event_time(read_buf_event); + } + + goto end; + +no_motion_data: + new_vals[RingbufX] = 0.0f; + new_vals[RingbufY] = 0.0f; + new_vals[RingbufRot] = 0.0f; + new_vals[RingbufScaleX] = 1.0f; + new_vals[RingbufScaleY] = 1.0f; + + for (int i = 0; i < num_vectors; i++) { + deshake_ctx->matches_contig_host[i].should_consider = 0; + } + debug_matches.num_model_matches = 0; + + if (deshake_ctx->debug_on) { + av_log(avctx, AV_LOG_VERBOSE, + "\n[ALERT] No motion data found in queue_frame, motion reset to 0\n\n" + ); + } + + goto end; + +end: + // Swap the descriptor buffers (we don't need the previous frame's descriptors + // again so we will use that space for the next frame's descriptors) + temp = deshake_ctx->prev_descriptors; + deshake_ctx->prev_descriptors = deshake_ctx->descriptors; + deshake_ctx->descriptors = temp; + + // Same for the refined features + temp = deshake_ctx->prev_refined_features; + deshake_ctx->prev_refined_features = deshake_ctx->refined_features; + deshake_ctx->refined_features = temp; + + if (deshake_ctx->debug_on) { + if (num_vectors == 0) { + debug_matches.matches = NULL; + } else { + debug_matches.matches = av_malloc_array(num_vectors, sizeof(MotionVector)); + + if (!debug_matches.matches) { + err = AVERROR(ENOMEM); + goto fail; + } + } + + for (int i = 0; i < num_vectors; i++) { + debug_matches.matches[i] = deshake_ctx->matches_contig_host[i]; + } + debug_matches.num_matches = num_vectors; + + av_fifo_generic_write( + deshake_ctx->abs_motion.debug_matches, + &debug_matches, + sizeof(DebugMatches), + NULL + ); + } + + for (int i = 0; i < RingbufCount; i++) { + av_fifo_generic_write( + deshake_ctx->abs_motion.ringbuffers[i], + &new_vals[i], + sizeof(float), + NULL + ); + } + + return ff_framequeue_add(&deshake_ctx->fq, input_frame); + +fail: + clFinish(deshake_ctx->command_queue); + av_frame_free(&input_frame); + return err; +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + DeshakeOpenCLContext *deshake_ctx = ctx->priv; + AVFrame *frame = NULL; + int ret, status; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + if (!deshake_ctx->eof) { + ret = ff_inlink_consume_frame(inlink, &frame); + if (ret < 0) + return ret; + if (ret > 0) { + if (!frame->hw_frames_ctx) + return AVERROR(EINVAL); + + if (!deshake_ctx->initialized) { + ret = deshake_opencl_init(ctx); + if (ret < 0) + return ret; + } + + // If there is no more space in the ringbuffers, remove the oldest + // values to make room for the new ones + if (av_fifo_space(deshake_ctx->abs_motion.ringbuffers[RingbufX]) == 0) { + for (int i = 0; i < RingbufCount; i++) { + av_fifo_drain(deshake_ctx->abs_motion.ringbuffers[i], sizeof(float)); + } + } + ret = queue_frame(inlink, frame); + if (ret < 0) + return ret; + if (ret >= 0) { + // See if we have enough buffered frames to process one + // + // "enough" is half the smooth window of queued frames into the future + if (ff_framequeue_queued_frames(&deshake_ctx->fq) >= deshake_ctx->smooth_window / 2) { + return filter_frame(inlink, ff_framequeue_take(&deshake_ctx->fq)); + } + } + } + } + + if (!deshake_ctx->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) { + deshake_ctx->eof = 1; + } + } + + if (deshake_ctx->eof) { + // Finish processing the rest of the frames in the queue. + while(ff_framequeue_queued_frames(&deshake_ctx->fq) != 0) { + for (int i = 0; i < RingbufCount; i++) { + av_fifo_drain(deshake_ctx->abs_motion.ringbuffers[i], sizeof(float)); + } + + ret = filter_frame(inlink, ff_framequeue_take(&deshake_ctx->fq)); + if (ret < 0) { + return ret; + } + } + + if (deshake_ctx->debug_on) { + av_log(ctx, AV_LOG_VERBOSE, + "Average kernel execution times:\n" + "\t grayscale: %0.3f ms\n" + "\t harris_response: %0.3f ms\n" + "\t refine_features: %0.3f ms\n" + "\tbrief_descriptors: %0.3f ms\n" + "\tmatch_descriptors: %0.3f ms\n" + "\t transform: %0.3f ms\n" + "\t crop_upscale: %0.3f ms\n" + "Average buffer read times:\n" + "\t features buf: %0.3f ms\n", + averaged_event_time_ms(deshake_ctx->grayscale_time, deshake_ctx->curr_frame), + averaged_event_time_ms(deshake_ctx->harris_response_time, deshake_ctx->curr_frame), + averaged_event_time_ms(deshake_ctx->refine_features_time, deshake_ctx->curr_frame), + averaged_event_time_ms(deshake_ctx->brief_descriptors_time, deshake_ctx->curr_frame), + averaged_event_time_ms(deshake_ctx->match_descriptors_time, deshake_ctx->curr_frame), + averaged_event_time_ms(deshake_ctx->transform_time, deshake_ctx->curr_frame), + averaged_event_time_ms(deshake_ctx->crop_upscale_time, deshake_ctx->curr_frame), + averaged_event_time_ms(deshake_ctx->read_buf_time, deshake_ctx->curr_frame) + ); + } + + ff_outlink_set_status(outlink, AVERROR_EOF, deshake_ctx->duration); + return 0; + } + + if (!deshake_ctx->eof) { + FF_FILTER_FORWARD_WANTED(outlink, inlink); + } + + return FFERROR_NOT_READY; +} + +static const AVFilterPad deshake_opencl_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_opencl_filter_config_input, + }, + { NULL } +}; + +static const AVFilterPad deshake_opencl_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_opencl_filter_config_output, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(DeshakeOpenCLContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption deshake_opencl_options[] = { + { + "tripod", "simulates a tripod by preventing any camera movement whatsoever " + "from the original frame", + OFFSET(tripod_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS + }, + { + "debug", "turn on additional debugging information", + OFFSET(debug_on), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS + }, + { + "adaptive_crop", "attempt to subtly crop borders to reduce mirrored content", + OFFSET(should_crop), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS + }, + { + "refine_features", "refine feature point locations at a sub-pixel level", + OFFSET(refine_features), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS + }, + { + "smooth_strength", "smoothing strength (0 attempts to adaptively determine optimal strength)", + OFFSET(smooth_percent), AV_OPT_TYPE_FLOAT, {.dbl = 0.0f}, 0.0f, 1.0f, FLAGS + }, + { + "smooth_window_multiplier", "multiplier for number of frames to buffer for motion data", + OFFSET(smooth_window_multiplier), AV_OPT_TYPE_FLOAT, {.dbl = 2.0}, 0.1, 10.0, FLAGS + }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(deshake_opencl); + +AVFilter ff_vf_deshake_opencl = { + .name = "deshake_opencl", + .description = NULL_IF_CONFIG_SMALL("Feature-point based video stabilization filter"), + .priv_size = sizeof(DeshakeOpenCLContext), + .priv_class = &deshake_opencl_class, + .init = &ff_opencl_filter_init, + .uninit = &deshake_opencl_uninit, + .query_formats = &ff_opencl_filter_query_formats, + .activate = activate, + .inputs = deshake_opencl_inputs, + .outputs = deshake_opencl_outputs, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_despill.c ffmpeg-4.4/libavfilter/vf_despill.c --- ffmpeg-4.2.2/libavfilter/vf_despill.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_despill.c 2021-04-08 21:28:40.000000000 +0000 @@ -153,7 +153,7 @@ }; #define OFFSET(x) offsetof(DespillContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption despill_options[] = { { "type", "set the screen type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "type" }, @@ -179,5 +179,6 @@ .query_formats = query_formats, .inputs = despill_inputs, .outputs = despill_outputs, + .process_command = ff_filter_process_command, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_detelecine.c ffmpeg-4.4/libavfilter/vf_detelecine.c --- ffmpeg-4.2.2/libavfilter/vf_detelecine.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_detelecine.c 2021-04-08 21:28:40.000000000 +0000 @@ -124,19 +124,16 @@ static int query_formats(AVFilterContext *ctx) { - AVFilterFormats *pix_fmts = NULL; - int fmt, ret; + AVFilterFormats *formats = NULL; + int ret; - for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); - if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL || - desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) && - (ret = ff_add_format(&pix_fmts, fmt)) < 0) - return ret; - } - - return ff_set_common_formats(ctx, pix_fmts); + ret = ff_formats_pixdesc_filter(&formats, 0, + AV_PIX_FMT_FLAG_BITSTREAM | + AV_PIX_FMT_FLAG_PAL | + AV_PIX_FMT_FLAG_HWACCEL); + if (ret < 0) + return ret; + return ff_set_common_formats(ctx, formats); } static int config_input(AVFilterLink *inlink) diff -Nru ffmpeg-4.2.2/libavfilter/vf_dnn_processing.c ffmpeg-4.4/libavfilter/vf_dnn_processing.c --- ffmpeg-4.2.2/libavfilter/vf_dnn_processing.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_dnn_processing.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2019 Guo Yejun + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * implementing a generic image processing filter using deep learning networks. + */ + +#include "libavformat/avio.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "filters.h" +#include "dnn_filter_common.h" +#include "formats.h" +#include "internal.h" +#include "libswscale/swscale.h" +#include "libavutil/time.h" + +typedef struct DnnProcessingContext { + const AVClass *class; + DnnContext dnnctx; + struct SwsContext *sws_uv_scale; + int sws_uv_height; +} DnnProcessingContext; + +#define OFFSET(x) offsetof(DnnProcessingContext, dnnctx.x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM +static const AVOption dnn_processing_options[] = { + { "dnn_backend", "DNN backend", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS, "backend" }, + { "native", "native backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "backend" }, +#if (CONFIG_LIBTENSORFLOW == 1) + { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" }, +#endif +#if (CONFIG_LIBOPENVINO == 1) + { "openvino", "openvino backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, FLAGS, "backend" }, +#endif + DNN_COMMON_OPTIONS + { NULL } +}; + +AVFILTER_DEFINE_CLASS(dnn_processing); + +static av_cold int init(AVFilterContext *context) +{ + DnnProcessingContext *ctx = context->priv; + return ff_dnn_init(&ctx->dnnctx, DFT_PROCESS_FRAME, context); +} + +static int query_formats(AVFilterContext *context) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAYF32, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_NV12, + AV_PIX_FMT_NONE + }; + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + return ff_set_common_formats(context, fmts_list); +} + +#define LOG_FORMAT_CHANNEL_MISMATCH() \ + av_log(ctx, AV_LOG_ERROR, \ + "the frame's format %s does not match " \ + "the model input channel %d\n", \ + av_get_pix_fmt_name(fmt), \ + model_input->channels); + +static int check_modelinput_inlink(const DNNData *model_input, const AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + enum AVPixelFormat fmt = inlink->format; + + // the design is to add explicit scale filter before this filter + if (model_input->height != -1 && model_input->height != inlink->h) { + av_log(ctx, AV_LOG_ERROR, "the model requires frame height %d but got %d\n", + model_input->height, inlink->h); + return AVERROR(EIO); + } + if (model_input->width != -1 && model_input->width != inlink->w) { + av_log(ctx, AV_LOG_ERROR, "the model requires frame width %d but got %d\n", + model_input->width, inlink->w); + return AVERROR(EIO); + } + if (model_input->dt != DNN_FLOAT) { + avpriv_report_missing_feature(ctx, "data type rather than DNN_FLOAT"); + return AVERROR(EIO); + } + + switch (fmt) { + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_BGR24: + if (model_input->channels != 3) { + LOG_FORMAT_CHANNEL_MISMATCH(); + return AVERROR(EIO); + } + return 0; + case AV_PIX_FMT_GRAYF32: + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUV410P: + case AV_PIX_FMT_YUV411P: + case AV_PIX_FMT_NV12: + if (model_input->channels != 1) { + LOG_FORMAT_CHANNEL_MISMATCH(); + return AVERROR(EIO); + } + return 0; + default: + avpriv_report_missing_feature(ctx, "%s", av_get_pix_fmt_name(fmt)); + return AVERROR(EIO); + } + + return 0; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *context = inlink->dst; + DnnProcessingContext *ctx = context->priv; + DNNReturnType result; + DNNData model_input; + int check; + + result = ff_dnn_get_input(&ctx->dnnctx, &model_input); + if (result != DNN_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "could not get input from the model\n"); + return AVERROR(EIO); + } + + check = check_modelinput_inlink(&model_input, inlink); + if (check != 0) { + return check; + } + + return 0; +} + +static av_always_inline int isPlanarYUV(enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + av_assert0(desc); + return !(desc->flags & AV_PIX_FMT_FLAG_RGB) && desc->nb_components == 3; +} + +static int prepare_uv_scale(AVFilterLink *outlink) +{ + AVFilterContext *context = outlink->src; + DnnProcessingContext *ctx = context->priv; + AVFilterLink *inlink = context->inputs[0]; + enum AVPixelFormat fmt = inlink->format; + + if (isPlanarYUV(fmt)) { + if (inlink->w != outlink->w || inlink->h != outlink->h) { + if (fmt == AV_PIX_FMT_NV12) { + ctx->sws_uv_scale = sws_getContext(inlink->w >> 1, inlink->h >> 1, AV_PIX_FMT_YA8, + outlink->w >> 1, outlink->h >> 1, AV_PIX_FMT_YA8, + SWS_BICUBIC, NULL, NULL, NULL); + ctx->sws_uv_height = inlink->h >> 1; + } else { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); + int sws_src_h = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + int sws_src_w = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + int sws_dst_h = AV_CEIL_RSHIFT(outlink->h, desc->log2_chroma_h); + int sws_dst_w = AV_CEIL_RSHIFT(outlink->w, desc->log2_chroma_w); + ctx->sws_uv_scale = sws_getContext(sws_src_w, sws_src_h, AV_PIX_FMT_GRAY8, + sws_dst_w, sws_dst_h, AV_PIX_FMT_GRAY8, + SWS_BICUBIC, NULL, NULL, NULL); + ctx->sws_uv_height = sws_src_h; + } + } + } + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *context = outlink->src; + DnnProcessingContext *ctx = context->priv; + DNNReturnType result; + AVFilterLink *inlink = context->inputs[0]; + + // have a try run in case that the dnn model resize the frame + result = ff_dnn_get_output(&ctx->dnnctx, inlink->w, inlink->h, &outlink->w, &outlink->h); + if (result != DNN_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "could not get output from the model\n"); + return AVERROR(EIO); + } + + prepare_uv_scale(outlink); + + return 0; +} + +static int copy_uv_planes(DnnProcessingContext *ctx, AVFrame *out, const AVFrame *in) +{ + const AVPixFmtDescriptor *desc; + int uv_height; + + if (!ctx->sws_uv_scale) { + av_assert0(in->height == out->height && in->width == out->width); + desc = av_pix_fmt_desc_get(in->format); + uv_height = AV_CEIL_RSHIFT(in->height, desc->log2_chroma_h); + for (int i = 1; i < 3; ++i) { + int bytewidth = av_image_get_linesize(in->format, in->width, i); + av_image_copy_plane(out->data[i], out->linesize[i], + in->data[i], in->linesize[i], + bytewidth, uv_height); + } + } else if (in->format == AV_PIX_FMT_NV12) { + sws_scale(ctx->sws_uv_scale, (const uint8_t **)(in->data + 1), in->linesize + 1, + 0, ctx->sws_uv_height, out->data + 1, out->linesize + 1); + } else { + sws_scale(ctx->sws_uv_scale, (const uint8_t **)(in->data + 1), in->linesize + 1, + 0, ctx->sws_uv_height, out->data + 1, out->linesize + 1); + sws_scale(ctx->sws_uv_scale, (const uint8_t **)(in->data + 2), in->linesize + 2, + 0, ctx->sws_uv_height, out->data + 2, out->linesize + 2); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *context = inlink->dst; + AVFilterLink *outlink = context->outputs[0]; + DnnProcessingContext *ctx = context->priv; + DNNReturnType dnn_result; + 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); + + dnn_result = ff_dnn_execute_model(&ctx->dnnctx, in, out); + if (dnn_result != DNN_SUCCESS){ + av_log(ctx, AV_LOG_ERROR, "failed to execute model\n"); + av_frame_free(&in); + av_frame_free(&out); + return AVERROR(EIO); + } + + if (isPlanarYUV(in->format)) + copy_uv_planes(ctx, out, in); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static int activate_sync(AVFilterContext *filter_ctx) +{ + AVFilterLink *inlink = filter_ctx->inputs[0]; + AVFilterLink *outlink = filter_ctx->outputs[0]; + AVFrame *in = NULL; + int64_t pts; + int ret, status; + int got_frame = 0; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + do { + // drain all input frames + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; + if (ret > 0) { + ret = filter_frame(inlink, in); + if (ret < 0) + return ret; + got_frame = 1; + } + } while (ret > 0); + + // if frame got, schedule to next filter + if (got_frame) + return 0; + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) { + ff_outlink_set_status(outlink, status, pts); + return ret; + } + } + + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; +} + +static int flush_frame(AVFilterLink *outlink, int64_t pts, int64_t *out_pts) +{ + DnnProcessingContext *ctx = outlink->src->priv; + int ret; + DNNAsyncStatusType async_state; + + ret = ff_dnn_flush(&ctx->dnnctx); + if (ret != DNN_SUCCESS) { + return -1; + } + + do { + AVFrame *in_frame = NULL; + AVFrame *out_frame = NULL; + async_state = ff_dnn_get_async_result(&ctx->dnnctx, &in_frame, &out_frame); + if (out_frame) { + if (isPlanarYUV(in_frame->format)) + copy_uv_planes(ctx, out_frame, in_frame); + av_frame_free(&in_frame); + ret = ff_filter_frame(outlink, out_frame); + if (ret < 0) + return ret; + if (out_pts) + *out_pts = out_frame->pts + pts; + } + av_usleep(5000); + } while (async_state >= DAST_NOT_READY); + + return 0; +} + +static int activate_async(AVFilterContext *filter_ctx) +{ + AVFilterLink *inlink = filter_ctx->inputs[0]; + AVFilterLink *outlink = filter_ctx->outputs[0]; + DnnProcessingContext *ctx = filter_ctx->priv; + AVFrame *in = NULL, *out = NULL; + int64_t pts; + int ret, status; + int got_frame = 0; + int async_state; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + do { + // drain all input frames + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; + if (ret > 0) { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + if (ff_dnn_execute_model_async(&ctx->dnnctx, in, out) != DNN_SUCCESS) { + return AVERROR(EIO); + } + } + } while (ret > 0); + + // drain all processed frames + do { + AVFrame *in_frame = NULL; + AVFrame *out_frame = NULL; + async_state = ff_dnn_get_async_result(&ctx->dnnctx, &in_frame, &out_frame); + if (out_frame) { + if (isPlanarYUV(in_frame->format)) + copy_uv_planes(ctx, out_frame, in_frame); + av_frame_free(&in_frame); + ret = ff_filter_frame(outlink, out_frame); + if (ret < 0) + return ret; + got_frame = 1; + } + } while (async_state == DAST_SUCCESS); + + // if frame got, schedule to next filter + if (got_frame) + return 0; + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) { + int64_t out_pts = pts; + ret = flush_frame(outlink, pts, &out_pts); + ff_outlink_set_status(outlink, status, out_pts); + return ret; + } + } + + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return 0; +} + +static int activate(AVFilterContext *filter_ctx) +{ + DnnProcessingContext *ctx = filter_ctx->priv; + + if (ctx->dnnctx.async) + return activate_async(filter_ctx); + else + return activate_sync(filter_ctx); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + DnnProcessingContext *context = ctx->priv; + + sws_freeContext(context->sws_uv_scale); + ff_dnn_uninit(&context->dnnctx); +} + +static const AVFilterPad dnn_processing_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad dnn_processing_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vf_dnn_processing = { + .name = "dnn_processing", + .description = NULL_IF_CONFIG_SMALL("Apply DNN processing filter to the input."), + .priv_size = sizeof(DnnProcessingContext), + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .inputs = dnn_processing_inputs, + .outputs = dnn_processing_outputs, + .priv_class = &dnn_processing_class, + .activate = activate, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_drawbox.c ffmpeg-4.4/libavfilter/vf_drawbox.c --- ffmpeg-4.2.2/libavfilter/vf_drawbox.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_drawbox.c 2021-04-08 21:28:40.000000000 +0000 @@ -208,6 +208,12 @@ return ret; } +static av_pure av_always_inline int pixel_belongs_to_box(DrawBoxContext *s, int x, int y) +{ + return (y - s->y < s->thickness) || (s->y + s->h - 1 - y < s->thickness) || + (x - s->x < s->thickness) || (s->x + s->w - 1 - x < s->thickness); +} + static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { DrawBoxContext *s = inlink->dst->priv; @@ -225,13 +231,11 @@ if (s->invert_color) { for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++) - if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) || - (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness)) + if (pixel_belongs_to_box(s, x, y)) row[0][x] = 0xff - row[0][x]; } else { for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++) { - if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) || - (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness)) { + if (pixel_belongs_to_box(s, x, y)) { row[0][x ] = s->yuv_color[Y]; row[1][x >> s->hsub] = s->yuv_color[U]; row[2][x >> s->hsub] = s->yuv_color[V]; @@ -250,15 +254,13 @@ if (s->invert_color) { for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++) - if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) || - (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness)) + if (pixel_belongs_to_box(s, x, y)) row[0][x] = 0xff - row[0][x]; } else { for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++) { double alpha = (double)s->yuv_color[A] / 255; - if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) || - (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness)) { + if (pixel_belongs_to_box(s, x, y)) { row[0][x ] = (1 - alpha) * row[0][x ] + alpha * s->yuv_color[Y]; row[1][x >> s->hsub] = (1 - alpha) * row[1][x >> s->hsub] + alpha * s->yuv_color[U]; row[2][x >> s->hsub] = (1 - alpha) * row[2][x >> s->hsub] + alpha * s->yuv_color[V]; @@ -271,23 +273,56 @@ return ff_filter_frame(inlink->dst->outputs[0], frame); } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags) +{ + AVFilterLink *inlink = ctx->inputs[0]; + DrawBoxContext *s = ctx->priv; + int old_x = s->x; + int old_y = s->y; + int old_w = s->w; + int old_h = s->h; + int old_t = s->thickness; + int old_r = s->replace; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + ret = init(ctx); + if (ret < 0) + goto end; + ret = config_input(inlink); +end: + if (ret < 0) { + s->x = old_x; + s->y = old_y; + s->w = old_w; + s->h = old_h; + s->thickness = old_t; + s->replace = old_r; + } + + return ret; +} + #define OFFSET(x) offsetof(DrawBoxContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM #if CONFIG_DRAWBOX_FILTER static const AVOption drawbox_options[] = { - { "x", "set horizontal position of the left box edge", OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "y", "set vertical position of the top box edge", OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "width", "set width of the box", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "w", "set width of the box", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "height", "set height of the box", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "h", "set height of the box", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "color", "set color of the box", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "c", "set color of the box", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "thickness", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "t", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "replace", "replace color & alpha", OFFSET(replace), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, FLAGS }, + { "x", "set horizontal position of the left box edge", OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS }, + { "y", "set vertical position of the top box edge", OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS }, + { "width", "set width of the box", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS }, + { "w", "set width of the box", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS }, + { "height", "set height of the box", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS }, + { "h", "set height of the box", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS }, + { "color", "set color of the box", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, 0, 0, FLAGS }, + { "c", "set color of the box", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, 0, 0, FLAGS }, + { "thickness", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, 0, 0, FLAGS }, + { "t", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, 0, 0, FLAGS }, + { "replace", "replace color & alpha", OFFSET(replace), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, FLAGS }, { NULL } }; @@ -321,6 +356,7 @@ .query_formats = query_formats, .inputs = drawbox_inputs, .outputs = drawbox_outputs, + .process_command = process_command, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; #endif /* CONFIG_DRAWBOX_FILTER */ @@ -410,16 +446,16 @@ } static const AVOption drawgrid_options[] = { - { "x", "set horizontal offset", OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "y", "set vertical offset", OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "width", "set width of grid cell", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "w", "set width of grid cell", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "height", "set height of grid cell", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "h", "set height of grid cell", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "color", "set color of the grid", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "c", "set color of the grid", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "thickness", "set grid line thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, {.str="1"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "t", "set grid line thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, {.str="1"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "x", "set horizontal offset", OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS }, + { "y", "set vertical offset", OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS }, + { "width", "set width of grid cell", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS }, + { "w", "set width of grid cell", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS }, + { "height", "set height of grid cell", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS }, + { "h", "set height of grid cell", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS }, + { "color", "set color of the grid", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, 0, 0, FLAGS }, + { "c", "set color of the grid", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, 0, 0, FLAGS }, + { "thickness", "set grid line thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, {.str="1"}, 0, 0, FLAGS }, + { "t", "set grid line thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, {.str="1"}, 0, 0, FLAGS }, { "replace", "replace color & alpha", OFFSET(replace), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, FLAGS }, { NULL } }; @@ -455,6 +491,7 @@ .inputs = drawgrid_inputs, .outputs = drawgrid_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .process_command = process_command, }; #endif /* CONFIG_DRAWGRID_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/vf_drawtext.c ffmpeg-4.4/libavfilter/vf_drawtext.c --- ffmpeg-4.2.2/libavfilter/vf_drawtext.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_drawtext.c 2021-04-08 21:28:40.000000000 +0000 @@ -209,20 +209,20 @@ #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption drawtext_options[]= { - {"fontfile", "set font file", OFFSET(fontfile), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS}, - {"text", "set text", OFFSET(text), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS}, - {"textfile", "set text file", OFFSET(textfile), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS}, - {"fontcolor", "set foreground color", OFFSET(fontcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS}, - {"fontcolor_expr", "set foreground color expression", OFFSET(fontcolor_expr), AV_OPT_TYPE_STRING, {.str=""}, CHAR_MIN, CHAR_MAX, FLAGS}, - {"boxcolor", "set box color", OFFSET(boxcolor.rgba), AV_OPT_TYPE_COLOR, {.str="white"}, CHAR_MIN, CHAR_MAX, FLAGS}, - {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS}, - {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS}, + {"fontfile", "set font file", OFFSET(fontfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, + {"text", "set text", OFFSET(text), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, + {"textfile", "set text file", OFFSET(textfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, + {"fontcolor", "set foreground color", OFFSET(fontcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, + {"fontcolor_expr", "set foreground color expression", OFFSET(fontcolor_expr), AV_OPT_TYPE_STRING, {.str=""}, 0, 0, FLAGS}, + {"boxcolor", "set box color", OFFSET(boxcolor.rgba), AV_OPT_TYPE_COLOR, {.str="white"}, 0, 0, FLAGS}, + {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, + {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS}, {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 , FLAGS}, {"boxborderw", "set box border width", OFFSET(boxborderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS}, {"line_spacing", "set line spacing in pixels", OFFSET(line_spacing), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX,FLAGS}, - {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX , FLAGS}, - {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX, FLAGS}, - {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX, FLAGS}, + {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0 , FLAGS}, + {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, + {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS}, {"shadowx", "set shadow x offset", OFFSET(shadowx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS}, {"shadowy", "set shadow y offset", OFFSET(shadowy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS}, {"borderw", "set border width", OFFSET(borderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS}, @@ -237,7 +237,7 @@ {"normal", "set normal expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NORMAL}, 0, 0, FLAGS, "expansion"}, {"strftime", "set strftime expansion (deprecated)", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_STRFTIME}, 0, 0, FLAGS, "expansion"}, - {"timecode", "set initial timecode", OFFSET(tc_opt_string), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS}, + {"timecode", "set initial timecode", OFFSET(tc_opt_string), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS}, {"tc24hmax", "set 24 hours max (timecode only)", OFFSET(tc24hmax), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, {"timecode_rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, {"r", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, @@ -568,6 +568,11 @@ return err; } +static inline int is_newline(uint32_t c) +{ + return c == '\n' || c == '\r' || c == '\f' || c == '\v'; +} + static int load_textfile(AVFilterContext *ctx) { DrawTextContext *s = ctx->priv; @@ -583,6 +588,8 @@ return err; } + if (textbuf_size > 0 && is_newline(textbuf[textbuf_size - 1])) + textbuf_size--; if (textbuf_size > SIZE_MAX - 1 || !(tmp = av_realloc(s->text, textbuf_size + 1))) { av_file_unmap(textbuf, textbuf_size); return AVERROR(ENOMEM); @@ -595,11 +602,6 @@ return 0; } -static inline int is_newline(uint32_t c) -{ - return c == '\n' || c == '\r' || c == '\f' || c == '\v'; -} - #if CONFIG_LIBFRIBIDI static int shape_text(AVFilterContext *ctx) { @@ -829,6 +831,7 @@ { AVFilterContext *ctx = inlink->dst; DrawTextContext *s = ctx->priv; + char *expr; int ret; ff_draw_init(&s->dc, inlink->format, FF_DRAW_PROCESS_ALPHA); @@ -854,14 +857,15 @@ av_expr_free(s->a_pexpr); s->x_pexpr = s->y_pexpr = s->a_pexpr = NULL; - if ((ret = av_expr_parse(&s->x_pexpr, s->x_expr, var_names, + if ((ret = av_expr_parse(&s->x_pexpr, expr = s->x_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 || - (ret = av_expr_parse(&s->y_pexpr, s->y_expr, var_names, + (ret = av_expr_parse(&s->y_pexpr, expr = s->y_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 || - (ret = av_expr_parse(&s->a_pexpr, s->a_expr, var_names, - NULL, NULL, fun2_names, fun2, 0, ctx)) < 0) - + (ret = av_expr_parse(&s->a_pexpr, expr = s->a_expr, var_names, + NULL, NULL, fun2_names, fun2, 0, ctx)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to parse expression: %s \n", expr); return AVERROR(EINVAL); + } return 0; } @@ -1083,10 +1087,12 @@ feclearexcept(FE_ALL_EXCEPT); intval = res; +#if defined(FE_INVALID) && defined(FE_OVERFLOW) && defined(FE_UNDERFLOW) if ((ret = fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW))) { av_log(ctx, AV_LOG_ERROR, "Conversion of floating-point result to int failed. Control register: 0x%08x. Conversion result: %d\n", ret, intval); return AVERROR(EINVAL); } +#endif if (argc == 3) av_strlcatf(fmt_str, sizeof(fmt_str), "0%u", positions); @@ -1223,7 +1229,8 @@ for (i = 0, p = text; *p; i++) { FT_Bitmap bitmap; Glyph dummy = { 0 }; - GET_UTF8(code, *p++, continue;); + GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_invalid;); +continue_on_invalid: /* skip new line chars, just go to new line */ if (code == '\n' || code == '\r' || code == '\t') @@ -1361,7 +1368,8 @@ /* load and cache glyphs */ for (i = 0, p = text; *p; i++) { - GET_UTF8(code, *p++, continue;); + GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_invalid;); +continue_on_invalid: /* get glyph */ dummy.code = code; @@ -1384,7 +1392,8 @@ /* compute and save position for each glyph */ glyph = NULL; for (i = 0, p = text; *p; i++) { - GET_UTF8(code, *p++, continue;); + GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_invalid2;); +continue_on_invalid2: /* skip the \n in the sequence \r\n */ if (prev_code == '\r' && code == '\n') diff -Nru ffmpeg-4.2.2/libavfilter/vf_edgedetect.c ffmpeg-4.4/libavfilter/vf_edgedetect.c --- ffmpeg-4.2.2/libavfilter/vf_edgedetect.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_edgedetect.c 2021-04-08 21:28:40.000000000 +0000 @@ -150,10 +150,13 @@ int i, j; memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; - memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; + if (h > 1) { + memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; + } for (j = 2; j < h - 2; j++) { dst[0] = src[0]; - dst[1] = src[1]; + if (w > 1) + dst[1] = src[1]; for (i = 2; i < w - 2; i++) { /* Gaussian mask of size 5x5 with sigma = 1.4 */ dst[i] = ((src[-2*src_linesize + i-2] + src[2*src_linesize + i-2]) * 2 @@ -174,14 +177,19 @@ + src[i+1] * 12 + src[i+2] * 5) / 159; } - dst[i ] = src[i ]; - dst[i + 1] = src[i + 1]; + if (w > 2) + dst[i ] = src[i ]; + if (w > 3) + dst[i + 1] = src[i + 1]; dst += dst_linesize; src += src_linesize; } - memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; - memcpy(dst, src, w); + if (h > 2) { + memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; + } + if (h > 3) + memcpy(dst, src, w); } enum { @@ -208,7 +216,7 @@ if (gx < 0) gx = -gx, gy = -gy; - gy <<= 16; + gy *= (1 << 16); tanpi8gx = 27146 * gx; tan3pi8gx = 158218 * gx; if (gy > -tan3pi8gx && gy < -tanpi8gx) return DIRECTION_45UP; @@ -286,7 +294,7 @@ continue; } - if ((!i || i == w - 1 || !j || j == h - 1) && + if (!(!i || i == w - 1 || !j || j == h - 1) && src[i] > low && (src[-src_linesize + i-1] > high || src[-src_linesize + i ] > high || diff -Nru ffmpeg-4.2.2/libavfilter/vf_elbg.c ffmpeg-4.4/libavfilter/vf_elbg.c --- ffmpeg-4.2.2/libavfilter/vf_elbg.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_elbg.c 2021-04-08 21:28:40.000000000 +0000 @@ -36,7 +36,7 @@ typedef struct ELBGContext { const AVClass *class; AVLFG lfg; - unsigned int lfg_seed; + int64_t lfg_seed; int max_steps_nb; int *codeword; int codeword_length; @@ -56,8 +56,8 @@ { "l", "set codebook length", OFFSET(codebook_length), AV_OPT_TYPE_INT, { .i64 = 256 }, 1, INT_MAX, FLAGS }, { "nb_steps", "set max number of steps used to compute the mapping", OFFSET(max_steps_nb), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX, FLAGS }, { "n", "set max number of steps used to compute the mapping", OFFSET(max_steps_nb), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX, FLAGS }, - { "seed", "set the random seed", OFFSET(lfg_seed), AV_OPT_TYPE_INT, {.i64 = -1}, -1, UINT32_MAX, FLAGS }, - { "s", "set the random seed", OFFSET(lfg_seed), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT32_MAX, FLAGS }, + { "seed", "set the random seed", OFFSET(lfg_seed), AV_OPT_TYPE_INT64, {.i64 = -1}, -1, UINT32_MAX, FLAGS }, + { "s", "set the random seed", OFFSET(lfg_seed), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, UINT32_MAX, FLAGS }, { "pal8", "set the pal8 output", OFFSET(pal8), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, { NULL } }; @@ -100,8 +100,8 @@ AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE }; - if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), &ctx->inputs[0]->out_formats)) < 0 || - (ret = ff_formats_ref(ff_make_format_list(pal8_fmt), &ctx->outputs[0]->in_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), &ctx->inputs[0]->outcfg.formats)) < 0 || + (ret = ff_formats_ref(ff_make_format_list(pal8_fmt), &ctx->outputs[0]->incfg.formats)) < 0) return ret; } return 0; @@ -178,8 +178,10 @@ AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); uint32_t *pal; - if (!out) + if (!out) { + av_frame_free(&frame); return AVERROR(ENOMEM); + } out->pts = frame->pts; av_frame_free(&frame); pal = (uint32_t *)out->data[1]; diff -Nru ffmpeg-4.2.2/libavfilter/vf_epx.c ffmpeg-4.4/libavfilter/vf_epx.c --- ffmpeg-4.2.2/libavfilter/vf_epx.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_epx.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,287 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/avassert.h" +#include "libavutil/pixdesc.h" +#include "internal.h" + +typedef struct EPXContext { + const AVClass *class; + + int n; + + int (*epx_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); +} EPXContext; + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +#define OFFSET(x) offsetof(EPXContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +static const AVOption epx_options[] = { + { "n", "set scale factor", OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 3}, 2, 3, .flags = FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(epx); + +static int epx2_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ThreadData *td = arg; + const AVFrame *in = td->in; + AVFrame *out = td->out; + const int slice_start = (in->height * jobnr ) / nb_jobs; + const int slice_end = (in->height * (jobnr+1)) / nb_jobs; + + for (int p = 0; p < 1; p++) { + const int width = in->width; + const int height = in->height; + const int src_linesize = in->linesize[p] / 4; + const int dst_linesize = out->linesize[p] / 4; + const uint32_t *src = (const uint32_t *)in->data[p]; + uint32_t *dst = (uint32_t *)out->data[p]; + const uint32_t *src_line[3]; + + src_line[0] = src + src_linesize * FFMAX(slice_start - 1, 0); + src_line[1] = src + src_linesize * slice_start; + src_line[2] = src + src_linesize * FFMIN(slice_start + 1, height-1); + + for (int y = slice_start; y < slice_end; y++) { + uint32_t *dst_line[2]; + + dst_line[0] = dst + dst_linesize*2*y; + dst_line[1] = dst + dst_linesize*(2*y+1); + + for (int x = 0; x < width; x++) { + uint32_t E0, E1, E2, E3; + uint32_t B, D, E, F, H; + + B = src_line[0][x]; + D = src_line[1][FFMAX(x-1, 0)]; + E = src_line[1][x]; + F = src_line[1][FFMIN(x+1, width - 1)]; + H = src_line[2][x]; + + if (B != H && D != F) { + E0 = D == B ? D : E; + E1 = B == F ? F : E; + E2 = D == H ? D : E; + E3 = H == F ? F : E; + } else { + E0 = E; + E1 = E; + E2 = E; + E3 = E; + } + + dst_line[0][x*2] = E0; + dst_line[0][x*2+1] = E1; + dst_line[1][x*2] = E2; + dst_line[1][x*2+1] = E3; + } + + src_line[0] = src_line[1]; + src_line[1] = src_line[2]; + src_line[2] = src_line[1]; + + if (y < height - 1) + src_line[2] += src_linesize; + } + } + + return 0; +} + +static int epx3_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ThreadData *td = arg; + const AVFrame *in = td->in; + AVFrame *out = td->out; + const int slice_start = (in->height * jobnr ) / nb_jobs; + const int slice_end = (in->height * (jobnr+1)) / nb_jobs; + + for (int p = 0; p < 1; p++) { + const int width = in->width; + const int height = in->height; + const int src_linesize = in->linesize[p] / 4; + const int dst_linesize = out->linesize[p] / 4; + const uint32_t *src = (const uint32_t *)in->data[p]; + uint32_t *dst = (uint32_t *)out->data[p]; + const uint32_t *src_line[3]; + + src_line[0] = src + src_linesize * FFMAX(slice_start - 1, 0); + src_line[1] = src + src_linesize * slice_start; + src_line[2] = src + src_linesize * FFMIN(slice_start + 1, height-1); + + for (int y = slice_start; y < slice_end; y++) { + uint32_t *dst_line[3]; + + dst_line[0] = dst + dst_linesize*3*y; + dst_line[1] = dst + dst_linesize*(3*y+1); + dst_line[2] = dst + dst_linesize*(3*y+2); + + for (int x = 0; x < width; x++) { + uint32_t E0, E1, E2, E3, E4, E5, E6, E7, E8; + uint32_t A, B, C, D, E, F, G, H, I; + + A = src_line[0][FFMAX(x-1, 0)]; + B = src_line[0][x]; + C = src_line[0][FFMIN(x+1, width - 1)]; + D = src_line[1][FFMAX(x-1, 0)]; + E = src_line[1][x]; + F = src_line[1][FFMIN(x+1, width - 1)]; + G = src_line[2][FFMAX(x-1, 0)]; + H = src_line[2][x]; + I = src_line[2][FFMIN(x+1, width - 1)]; + + if (B != H && D != F) { + E0 = D == B ? D : E; + E1 = (D == B && E != C) || (B == F && E != A) ? B : E; + E2 = B == F ? F : E; + E3 = (D == B && E != G) || (D == H && E != A) ? D : E; + E4 = E; + E5 = (B == F && E != I) || (H == F && E != C) ? F : E; + E6 = D == H ? D : E; + E7 = (D == H && E != I) || (H == F && E != G) ? H : E; + E8 = H == F ? F : E; + } else { + E0 = E; + E1 = E; + E2 = E; + E3 = E; + E4 = E; + E5 = E; + E6 = E; + E7 = E; + E8 = E; + } + + dst_line[0][x*3] = E0; + dst_line[0][x*3+1] = E1; + dst_line[0][x*3+2] = E2; + dst_line[1][x*3] = E3; + dst_line[1][x*3+1] = E4; + dst_line[1][x*3+2] = E5; + dst_line[2][x*3] = E6; + dst_line[2][x*3+1] = E7; + dst_line[2][x*3+2] = E8; + } + + src_line[0] = src_line[1]; + src_line[1] = src_line[2]; + src_line[2] = src_line[1]; + + if (y < height - 1) + src_line[2] += src_linesize; + } + } + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + EPXContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + const AVPixFmtDescriptor *desc; + + desc = av_pix_fmt_desc_get(outlink->format); + if (!desc) + return AVERROR_BUG; + + outlink->w = inlink->w * s->n; + outlink->h = inlink->h * s->n; + + switch (s->n) { + case 2: + s->epx_slice = epx2_slice; + break; + case 3: + s->epx_slice = epx3_slice; + break; + } + + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, + AV_PIX_FMT_NONE, + }; + + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + EPXContext *s = ctx->priv; + ThreadData td; + + AVFrame *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; + ctx->internal->execute(ctx, s->epx_slice, &td, NULL, FFMIN(inlink->h, ff_filter_get_nb_threads(ctx))); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vf_epx = { + .name = "epx", + .description = NULL_IF_CONFIG_SMALL("Scale the input using EPX algorithm."), + .inputs = inputs, + .outputs = outputs, + .query_formats = query_formats, + .priv_size = sizeof(EPXContext), + .priv_class = &epx_class, + .flags = AVFILTER_FLAG_SLICE_THREADS, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_eq.c ffmpeg-4.4/libavfilter/vf_eq.c --- ffmpeg-4.2.2/libavfilter/vf_eq.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_eq.c 2021-04-08 21:28:40.000000000 +0000 @@ -174,12 +174,18 @@ return 0; } +void ff_eq_init(EQContext *eq) +{ + eq->process = process_c; + if (ARCH_X86) + ff_eq_init_x86(eq); +} + static int initialize(AVFilterContext *ctx) { EQContext *eq = ctx->priv; int ret; - - eq->process = process_c; + ff_eq_init(eq); if ((ret = set_expr(&eq->contrast_pexpr, eq->contrast_expr, "contrast", ctx)) < 0 || (ret = set_expr(&eq->brightness_pexpr, eq->brightness_expr, "brightness", ctx)) < 0 || @@ -191,9 +197,6 @@ (ret = set_expr(&eq->gamma_weight_pexpr, eq->gamma_weight_expr, "gamma_weight", ctx)) < 0 ) return ret; - if (ARCH_X86) - ff_eq_init_x86(eq); - if (eq->eval_mode == EVAL_MODE_INIT) { set_gamma(eq); set_contrast(eq); @@ -204,7 +207,7 @@ return 0; } -static void uninit(AVFilterContext *ctx) +static av_cold void uninit(AVFilterContext *ctx) { EQContext *eq = ctx->priv; @@ -246,8 +249,6 @@ return ff_set_common_formats(ctx, fmts_list); } -#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts) * av_q2d(tb)) - static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; @@ -350,24 +351,24 @@ #define OFFSET(x) offsetof(EQContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM - +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption eq_options[] = { { "contrast", "set the contrast adjustment, negative values give a negative image", - OFFSET(contrast_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, CHAR_MIN, CHAR_MAX, FLAGS }, + OFFSET(contrast_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, 0, 0, TFLAGS }, { "brightness", "set the brightness adjustment", - OFFSET(brightness_expr), AV_OPT_TYPE_STRING, {.str = "0.0"}, CHAR_MIN, CHAR_MAX, FLAGS }, + OFFSET(brightness_expr), AV_OPT_TYPE_STRING, {.str = "0.0"}, 0, 0, TFLAGS }, { "saturation", "set the saturation adjustment", - OFFSET(saturation_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, CHAR_MIN, CHAR_MAX, FLAGS }, + OFFSET(saturation_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, 0, 0, TFLAGS }, { "gamma", "set the initial gamma value", - OFFSET(gamma_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, CHAR_MIN, CHAR_MAX, FLAGS }, + OFFSET(gamma_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, 0, 0, TFLAGS }, { "gamma_r", "gamma value for red", - OFFSET(gamma_r_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, CHAR_MIN, CHAR_MAX, FLAGS }, + OFFSET(gamma_r_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, 0, 0, TFLAGS }, { "gamma_g", "gamma value for green", - OFFSET(gamma_g_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, CHAR_MIN, CHAR_MAX, FLAGS }, + OFFSET(gamma_g_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, 0, 0, TFLAGS }, { "gamma_b", "gamma value for blue", - OFFSET(gamma_b_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, CHAR_MIN, CHAR_MAX, FLAGS }, + OFFSET(gamma_b_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, 0, 0, TFLAGS }, { "gamma_weight", "set the gamma weight which reduces the effect of gamma on bright areas", - OFFSET(gamma_weight_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, CHAR_MIN, CHAR_MAX, FLAGS }, + OFFSET(gamma_weight_expr), AV_OPT_TYPE_STRING, {.str = "1.0"}, 0, 0, TFLAGS }, { "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}, .flags = FLAGS, .unit = "eval" }, { "frame", "eval expressions per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" }, @@ -387,5 +388,5 @@ .query_formats = query_formats, .init = initialize, .uninit = uninit, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_eq.h ffmpeg-4.4/libavfilter/vf_eq.h --- ffmpeg-4.2.2/libavfilter/vf_eq.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_eq.h 2020-07-11 10:39:30.000000000 +0000 @@ -100,6 +100,7 @@ enum EvalMode { EVAL_MODE_INIT, EVAL_MODE_FRAME, EVAL_MODE_NB } eval_mode; } EQContext; +void ff_eq_init(EQContext *eq); void ff_eq_init_x86(EQContext *eq); #endif /* AVFILTER_EQ_H */ diff -Nru ffmpeg-4.2.2/libavfilter/vf_estdif.c ffmpeg-4.4/libavfilter/vf_estdif.c --- ffmpeg-4.2.2/libavfilter/vf_estdif.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_estdif.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,591 @@ +/* + * 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 "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct ESTDIFContext { + const AVClass *class; + + int mode; ///< 0 is frame, 1 is field + int parity; ///< frame field parity + int deint; ///< which frames to deinterlace + int rslope; ///< best edge slope search radius + int redge; ///< best edge match search radius + int interp; ///< type of interpolation + int linesize[4]; ///< bytes of pixel data per line for each plane + int planewidth[4]; ///< width of each plane + int planeheight[4]; ///< height of each plane + int field; ///< which field are we on, 0 or 1 + int eof; + int depth; + int half; + int nb_planes; + int nb_threads; + int64_t pts; + AVFrame *prev; + + void (*interpolate)(struct ESTDIFContext *s, uint8_t *dst, + 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 depth, int *K); + + unsigned (*mid_8[3])(const uint8_t *const prev, + const uint8_t *const next, + const uint8_t *const prev2, + const uint8_t *const next2, + const uint8_t *const prev3, + const uint8_t *const next3, + int end, int x, int k, int depth); + + unsigned (*mid_16[3])(const uint16_t *const prev, + const uint16_t *const next, + const uint16_t *const prev2, + const uint16_t *const next2, + const uint16_t *const prev3, + const uint16_t *const next3, + int end, int x, int k, int depth); +} ESTDIFContext; + +#define MAX_R 15 +#define S (MAX_R * 2 + 1) + +#define OFFSET(x) offsetof(ESTDIFContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM +#define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, 0, 0, FLAGS, unit } + +static const AVOption estdif_options[] = { + { "mode", "specify the mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "mode" }, + CONST("frame", "send one frame for each frame", 0, "mode"), + CONST("field", "send one frame for each field", 1, "mode"), + { "parity", "specify the assumed picture field parity", OFFSET(parity), AV_OPT_TYPE_INT, {.i64=-1}, -1, 1, FLAGS, "parity" }, + CONST("tff", "assume top field first", 0, "parity"), + CONST("bff", "assume bottom field first", 1, "parity"), + CONST("auto", "auto detect parity", -1, "parity"), + { "deint", "specify which frames to deinterlace", OFFSET(deint), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "deint" }, + CONST("all", "deinterlace all frames", 0, "deint"), + 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, }, + { "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"), + CONST("6p", "six-point interpolation", 2, "interp"), + { NULL } +}; + +AVFILTER_DEFINE_CLASS(estdif); + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, + 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_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; + + outlink->time_base.num = inlink->time_base.num; + outlink->time_base.den = inlink->time_base.den * 2; + outlink->frame_rate.num = inlink->frame_rate.num * 2; + outlink->frame_rate.den = inlink->frame_rate.den; + + return 0; +} + +typedef struct ThreadData { + AVFrame *out, *in; +} ThreadData; + +#define MIDL(type, ss) \ +static unsigned midl_##ss(const type *const prev, \ + const type *const next, \ + int end, int x, int k) \ +{ \ + return (prev[av_clip(x + k, 0, end)] + \ + next[av_clip(x - k, 0, end)] + 1) >> 1; \ +} + +MIDL(uint8_t, 8) +MIDL(uint16_t, 16) + +#define MID2(type, ss) \ +static unsigned mid2_##ss(const type *const prev, \ + const type *const next, \ + const type *const prev2, \ + const type *const next2, \ + const type *const prev3, \ + const type *const next3, \ + int end, int x, int k, int depth) \ +{ \ + return (prev[av_clip(x + k, 0, end)] + \ + next[av_clip(x - k, 0, end)] + 1) >> 1; \ +} + +MID2(uint8_t, 8) +MID2(uint16_t, 16) + +#define MID4(type, ss) \ +static unsigned mid4_##ss(const type *const prev, \ + const type *const next, \ + const type *const prev2, \ + const type *const next2, \ + const type *const prev3, \ + const type *const next3, \ + int end, int x, int k, int depth) \ +{ \ + return av_clip_uintp2_c(( \ + 9 * (prev[av_clip(x + k, 0, end)] + \ + next[av_clip(x - k, 0, end)]) - \ + 1 * (prev2[av_clip(x + k*3, 0, end)] + \ + next2[av_clip(x - k*3, 0, end)]) + 8) >> 4, \ + depth); \ +} + +MID4(uint8_t, 8) +MID4(uint16_t, 16) + +#define MID6(type, ss) \ +static unsigned mid6_##ss(const type *const prev, \ + const type *const next, \ + const type *const prev2, \ + const type *const next2, \ + const type *const prev3, \ + const type *const next3, \ + int end, int x, int k, int depth) \ +{ \ + return av_clip_uintp2_c(( \ + 20 * (prev[av_clip(x + k, 0, end)] + \ + next[av_clip(x - k, 0, end)]) - \ + 5 * (prev2[av_clip(x + k*3, 0, end)] + \ + next2[av_clip(x - k*3, 0, end)]) + \ + 1 * (prev3[av_clip(x + k*5, 0, end)] + \ + next3[av_clip(x - k*5, 0, end)]) + 16) >> 5, \ + depth); \ +} + +MID6(uint8_t, 8) +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) \ +{ \ + return FFABS(prev[av_clip(x + k + j, 0, end)] - \ + next[av_clip(x - k + j, 0, end)]); \ +} + +DIFF(uint8_t, 8) +DIFF(uint16_t, 16) + +#define COST(type, ss) \ +static unsigned cost_##ss(const type *const prev, \ + const type *const next, \ + int end, int x, int k) \ +{ \ + const int m = midl_##ss(prev, next, end, x, k); \ + const int p = prev[x]; \ + const int n = next[x]; \ + \ + return FFABS(p - m) + FFABS(n - m); \ +} + +COST(uint8_t, 8) +COST(uint16_t, 16) + +#define INTERPOLATE(type, atype, max, ss) \ +static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ + const uint8_t *const pprev_line, \ + const uint8_t *const nnext_line, \ + const uint8_t *const pprev2_line, \ + const uint8_t *const nnext2_line, \ + 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 *K) \ +{ \ + type *dst = (type *)ddst; \ + const type *const prev_line = (const type *const)pprev_line; \ + const type *const prev2_line = (const type *const)pprev2_line; \ + const type *const prev3_line = (const type *const)pprev3_line; \ + const type *const next_line = (const type *const)nnext_line; \ + 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 end = width - 1; \ + const atype f = redge + 2; \ + atype sd[S], sD[S], di = 0; \ + atype dmin = max; \ + 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); \ + } \ + \ + sD[i + rslope] = sum; \ + sD[i + rslope] += f * cost_##ss(prev_line, next_line, end, x, i); \ + sD[i + rslope] += h * abs(i); \ + \ + dmin = FFMIN(sD[i + rslope], dmin); \ + } \ + \ + for (int i = -rslope; i <= rslope; i++) { \ + 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); \ + } \ + \ + 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); \ + \ + dmin = FFMIN(sd[i + rslope], dmin); \ + } \ + \ + for (int i = -rslope; i <= rslope && abs(k) > rslope; i++) { \ + if (dmin == sD[i + rslope]) { \ + di = 1; \ + k = i; \ + break; \ + } \ + } \ + \ + for (int i = -rslope; i <= rslope && !di; i++) { \ + if (dmin == sd[i + rslope]) { \ + k += i; \ + break; \ + } \ + } \ + \ + dst[x] = s->mid_##ss[interp](prev_line, next_line, \ + prev2_line, next2_line, \ + prev3_line, next3_line, \ + end, x, k, depth); \ + \ + *K = k; \ +} + +INTERPOLATE(uint8_t, unsigned, UINT_MAX, 8) +INTERPOLATE(uint16_t, uint64_t, UINT64_MAX, 16) + +static int deinterlace_slice(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + ESTDIFContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *out = td->out; + 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 : + s->parity ^ 1)); + + for (int plane = 0; plane < s->nb_planes; plane++) { + const uint8_t *src_data = in->data[plane]; + uint8_t *dst_data = out->data[plane]; + const int linesize = s->linesize[plane]; + const int width = s->planewidth[plane]; + const int height = s->planeheight[plane]; + const int src_linesize = in->linesize[plane]; + const int dst_linesize = out->linesize[plane]; + const int start = (height * jobnr) / nb_jobs; + const int end = (height * (jobnr+1)) / nb_jobs; + const uint8_t *prev_line, *prev2_line, *next_line, *next2_line, *in_line; + const uint8_t *prev3_line, *next3_line; + uint8_t *out_line; + int y_out; + + y_out = start + (tff ^ (start & 1)); + + in_line = src_data + (y_out * src_linesize); + out_line = dst_data + (y_out * dst_linesize); + + while (y_out < end) { + memcpy(out_line, in_line, linesize); + y_out += 2; + in_line += src_linesize * 2; + out_line += dst_linesize * 2; + } + + y_out = start + ((!tff) ^ (start & 1)); + out_line = dst_data + (y_out * dst_linesize); + + for (int y = y_out; y < end; y += 2) { + int y_prev3_in = y - 5; + int y_next3_in = y + 5; + int y_prev2_in = y - 3; + int y_next2_in = y + 3; + int y_prev_in = y - 1; + int y_next_in = y + 1; + int k; + + while (y_prev3_in < 0) + y_prev3_in += 2; + + while (y_next3_in >= height) + y_next3_in -= 2; + + while (y_prev2_in < 0) + y_prev2_in += 2; + + while (y_next2_in >= height) + y_next2_in -= 2; + + while (y_prev_in < 0) + y_prev_in += 2; + + while (y_next_in >= height) + y_next_in -= 2; + + prev3_line = src_data + (y_prev3_in * src_linesize); + next3_line = src_data + (y_next3_in * src_linesize); + + prev2_line = src_data + (y_prev2_in * src_linesize); + next2_line = src_data + (y_next2_in * src_linesize); + + prev_line = src_data + (y_prev_in * src_linesize); + next_line = src_data + (y_next_in * src_linesize); + + k = 0; + + for (int x = 0; x < width; x++) { + s->interpolate(s, out_line, + prev_line, next_line, + prev2_line, next2_line, + prev3_line, next3_line, + x, width, rslope, redge, half, depth, &k); + } + + out_line += 2 * dst_linesize; + } + } + + return 0; +} + +static int filter(AVFilterContext *ctx, int is_second, AVFrame *in) +{ + ESTDIFContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + ThreadData td; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) + return AVERROR(ENOMEM); + av_frame_copy_props(out, in); + out->interlaced_frame = 0; + out->pts = s->pts; + + td.out = out; td.in = in; + ctx->internal->execute(ctx, deinterlace_slice, &td, NULL, + FFMIN(s->planeheight[1] / 2, s->nb_threads)); + + if (s->mode) + s->field = !s->field; + + return ff_filter_frame(outlink, out); +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ESTDIFContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int ret; + + if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + return ret; + + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + + if (inlink->h < 3) { + av_log(ctx, AV_LOG_ERROR, "Video of less than 3 lines is not supported\n"); + return AVERROR(EINVAL); + } + + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + s->nb_threads = ff_filter_get_nb_threads(ctx); + s->depth = desc->comp[0].depth; + s->interpolate = s->depth <= 8 ? interpolate_8 : interpolate_16; + s->mid_8[0] = mid2_8; + s->mid_8[1] = mid4_8; + s->mid_8[2] = mid6_8; + s->mid_16[0] = mid2_16; + s->mid_16[1] = mid4_16; + s->mid_16[2] = mid6_16; + s->half = 1 << (s->depth - 1); + + return 0; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + ESTDIFContext *s = ctx->priv; + int ret; + + if (!s->prev) { + s->prev = in; + return 0; + } + + if ((s->deint && !in->interlaced_frame) || ctx->is_disabled) { + s->prev->pts *= 2; + ret = ff_filter_frame(ctx->outputs[0], s->prev); + s->prev = in; + return ret; + } + + s->pts = s->prev->pts * 2; + ret = filter(ctx, 0, s->prev); + if (ret < 0 || s->mode == 0) { + av_frame_free(&s->prev); + s->prev = in; + return ret; + } + + s->pts = s->prev->pts + in->pts; + ret = filter(ctx, 1, s->prev); + av_frame_free(&s->prev); + s->prev = in; + return ret; +} + +static int request_frame(AVFilterLink *link) +{ + AVFilterContext *ctx = link->src; + ESTDIFContext *s = ctx->priv; + int ret; + + if (s->eof) + return AVERROR_EOF; + + ret = ff_request_frame(ctx->inputs[0]); + + if (ret == AVERROR_EOF && s->prev) { + AVFrame *next = av_frame_clone(s->prev); + + if (!next) + return AVERROR(ENOMEM); + + next->pts = s->prev->pts + av_rescale_q(1, av_inv_q(ctx->outputs[0]->frame_rate), + ctx->outputs[0]->time_base); + s->eof = 1; + ret = filter_frame(ctx->inputs[0], next); + } else if (ret < 0) { + return ret; + } + + return ret; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + ESTDIFContext *s = ctx->priv; + + av_frame_free(&s->prev); +} + +static const AVFilterPad estdif_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad estdif_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + .request_frame = request_frame, + }, + { NULL } +}; + +AVFilter ff_vf_estdif = { + .name = "estdif", + .description = NULL_IF_CONFIG_SMALL("Apply Edge Slope Tracing deinterlace."), + .priv_size = sizeof(ESTDIFContext), + .priv_class = &estdif_class, + .uninit = uninit, + .query_formats = query_formats, + .inputs = estdif_inputs, + .outputs = estdif_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_exposure.c ffmpeg-4.4/libavfilter/vf_exposure.c --- ffmpeg-4.2.2/libavfilter/vf_exposure.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_exposure.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,144 @@ +/* + * 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 "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct ExposureContext { + const AVClass *class; + + float exposure; + float black; + + float scale; + int (*do_slice)(AVFilterContext *s, void *arg, + int jobnr, int nb_jobs); +} ExposureContext; + +static int exposure_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ExposureContext *s = ctx->priv; + AVFrame *frame = arg; + const int width = frame->width; + const int height = frame->height; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const float black = s->black; + const float scale = s->scale; + + for (int p = 0; p < 3; p++) { + const int linesize = frame->linesize[p] / 4; + float *ptr = (float *)frame->data[p] + slice_start * linesize; + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) + ptr[x] = (ptr[x] - black) * scale; + + ptr += linesize; + } + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + ExposureContext *s = ctx->priv; + + s->scale = 1.f / (exp2f(-s->exposure) - s->black); + ctx->internal->execute(ctx, s->do_slice, frame, NULL, + FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); + + return ff_filter_frame(ctx->outputs[0], frame); +} + +static av_cold int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pixel_fmts[] = { + AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *formats = NULL; + + formats = ff_make_format_list(pixel_fmts); + if (!formats) + return AVERROR(ENOMEM); + + return ff_set_common_formats(ctx, formats); +} + +static av_cold int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ExposureContext *s = ctx->priv; + + s->do_slice = exposure_slice; + + return 0; +} + +static const AVFilterPad exposure_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .needs_writable = 1, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad exposure_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(ExposureContext, x) +#define VF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption exposure_options[] = { + { "exposure", "set the exposure correction", OFFSET(exposure), AV_OPT_TYPE_FLOAT, {.dbl=0}, -3, 3, VF }, + { "black", "set the black level correction", OFFSET(black), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(exposure); + +AVFilter ff_vf_exposure = { + .name = "exposure", + .description = NULL_IF_CONFIG_SMALL("Adjust exposure of the video stream."), + .priv_size = sizeof(ExposureContext), + .priv_class = &exposure_class, + .query_formats = query_formats, + .inputs = exposure_inputs, + .outputs = exposure_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_extractplanes.c ffmpeg-4.4/libavfilter/vf_extractplanes.c --- ffmpeg-4.2.2/libavfilter/vf_extractplanes.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_extractplanes.c 2021-04-08 21:28:40.000000000 +0000 @@ -115,16 +115,22 @@ AV_PIX_FMT_YUV422P14##suf, \ AV_PIX_FMT_YUV444P14##suf +#define FLOAT_FORMATS(suf) \ + AV_PIX_FMT_GRAYF32##suf, \ + AV_PIX_FMT_GBRPF32##suf, AV_PIX_FMT_GBRAPF32##suf \ + static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat in_pixfmts_le[] = { EIGHTBIT_FORMATS, HIGHDEPTH_FORMATS(LE), + FLOAT_FORMATS(LE), AV_PIX_FMT_NONE, }; static const enum AVPixelFormat in_pixfmts_be[] = { EIGHTBIT_FORMATS, HIGHDEPTH_FORMATS(BE), + FLOAT_FORMATS(BE), AV_PIX_FMT_NONE, }; static const enum AVPixelFormat out8_pixfmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }; @@ -138,17 +144,19 @@ static const enum AVPixelFormat out14be_pixfmts[] = { AV_PIX_FMT_GRAY14BE, AV_PIX_FMT_NONE }; static const enum AVPixelFormat out16le_pixfmts[] = { AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_NONE }; static const enum AVPixelFormat out16be_pixfmts[] = { AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_NONE }; + static const enum AVPixelFormat out32le_pixfmts[] = { AV_PIX_FMT_GRAYF32LE, AV_PIX_FMT_NONE }; + static const enum AVPixelFormat out32be_pixfmts[] = { AV_PIX_FMT_GRAYF32BE, AV_PIX_FMT_NONE }; const enum AVPixelFormat *out_pixfmts, *in_pixfmts; const AVPixFmtDescriptor *desc; AVFilterFormats *avff; int i, ret, depth = 0, be = 0; - if (!ctx->inputs[0]->in_formats || - !ctx->inputs[0]->in_formats->nb_formats) { + if (!ctx->inputs[0]->incfg.formats || + !ctx->inputs[0]->incfg.formats->nb_formats) { return AVERROR(EAGAIN); } - avff = ctx->inputs[0]->in_formats; + avff = ctx->inputs[0]->incfg.formats; desc = av_pix_fmt_desc_get(avff->formats[0]); depth = desc->comp[0].depth; be = desc->flags & AV_PIX_FMT_FLAG_BE; @@ -157,8 +165,8 @@ } else { in_pixfmts = in_pixfmts_le; } - if (!ctx->inputs[0]->out_formats) - if ((ret = ff_formats_ref(ff_make_format_list(in_pixfmts), &ctx->inputs[0]->out_formats)) < 0) + if (!ctx->inputs[0]->outcfg.formats) + if ((ret = ff_formats_ref(ff_make_format_list(in_pixfmts), &ctx->inputs[0]->outcfg.formats)) < 0) return ret; for (i = 1; i < avff->nb_formats; i++) { @@ -187,13 +195,17 @@ out_pixfmts = out14le_pixfmts; else if (be && depth == 14) out_pixfmts = out14be_pixfmts; - else if (be) + else if (be && depth == 16) out_pixfmts = out16be_pixfmts; - else + else if (!be && depth == 16) out_pixfmts = out16le_pixfmts; + else if (be && depth == 32) + out_pixfmts = out32be_pixfmts; + else + out_pixfmts = out32le_pixfmts; for (i = 0; i < ctx->nb_outputs; i++) - if ((ret = ff_formats_ref(ff_make_format_list(out_pixfmts), &ctx->outputs[i]->in_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(out_pixfmts), &ctx->outputs[i]->incfg.formats)) < 0) return ret; return 0; } diff -Nru ffmpeg-4.2.2/libavfilter/vf_fade.c ffmpeg-4.4/libavfilter/vf_fade.c --- ffmpeg-4.2.2/libavfilter/vf_fade.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_fade.c 2021-04-08 21:28:40.000000000 +0000 @@ -54,15 +54,21 @@ int type; int factor, fade_per_frame; int start_frame, nb_frames; - int hsub, vsub, bpp; + int hsub, vsub, bpp, depth; unsigned int black_level, black_level_scaled; + uint8_t is_rgb; uint8_t is_packed_rgb; uint8_t rgba_map[4]; int alpha; + int is_planar; uint64_t start_time, duration; + uint64_t start_time_pts, duration_pts; enum {VF_FADE_WAITING=0, VF_FADE_FADING, VF_FADE_DONE} fade_state; uint8_t color_rgba[4]; ///< fade color int black_fade; ///< if color_rgba is black + int (*filter_slice_luma)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + int (*filter_slice_chroma)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + int (*filter_slice_alpha)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } FadeContext; static av_cold int init(AVFilterContext *ctx) @@ -107,23 +113,40 @@ AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_NONE }; static const enum AVPixelFormat pix_fmts_rgb[] = { AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, + AV_PIX_FMT_GBRP, AV_PIX_FMT_NONE }; static const enum AVPixelFormat pix_fmts_alpha[] = { AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE }; static const enum AVPixelFormat pix_fmts_rgba[] = { AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE }; AVFilterFormats *fmts_list; @@ -148,32 +171,18 @@ 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_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_NONE }; -static int config_props(AVFilterLink *inlink) -{ - FadeContext *s = inlink->dst->priv; - const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(inlink->format); - - s->hsub = pixdesc->log2_chroma_w; - s->vsub = pixdesc->log2_chroma_h; - - s->bpp = pixdesc->flags & AV_PIX_FMT_FLAG_PLANAR ? - 1 : - av_get_bits_per_pixel(pixdesc) >> 3; - s->alpha &= !!(pixdesc->flags & AV_PIX_FMT_FLAG_ALPHA); - s->is_packed_rgb = ff_fill_rgba_map(s->rgba_map, inlink->format) >= 0; - - /* use CCIR601/709 black level for studio-level pixel non-alpha components */ - s->black_level = - ff_fmt_is_in(inlink->format, studio_level_pix_fmts) && !s->alpha ? 16 : 0; - /* 32768 = 1 << 15, it is an integer representation - * of 0.5 and is for rounding. */ - s->black_level_scaled = (s->black_level << 16) + 32768; - return 0; -} - static av_always_inline void filter_rgb(FadeContext *s, const AVFrame *frame, int slice_start, int slice_end, int do_alpha, int step) @@ -199,6 +208,29 @@ } } +static av_always_inline void filter_rgb_planar(FadeContext *s, const AVFrame *frame, + int slice_start, int slice_end, + int do_alpha) +{ + int i, j; + const uint8_t *c = s->color_rgba; + + for (i = slice_start; i < slice_end; i++) { + uint8_t *pg = frame->data[0] + i * frame->linesize[0]; + uint8_t *pb = frame->data[1] + i * frame->linesize[1]; + uint8_t *pr = frame->data[2] + i * frame->linesize[2]; + uint8_t *pa = frame->data[3] + i * frame->linesize[3]; + for (j = 0; j < frame->width; j++) { +#define INTERPP(c_name, c_idx) av_clip_uint8(((c[c_idx]<<16) + ((int)c_name - (int)c[c_idx]) * s->factor + (1<<15)) >> 16) + pr[j] = INTERPP(pr[j], 0); + pg[j] = INTERPP(pg[j], 1); + pb[j] = INTERPP(pb[j], 2); + if (do_alpha) + pa[j] = INTERPP(pa[j], 3); + } + } +} + static int filter_slice_rgb(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { @@ -207,7 +239,11 @@ int slice_start = (frame->height * jobnr ) / nb_jobs; int slice_end = (frame->height * (jobnr+1)) / nb_jobs; - if (s->alpha) filter_rgb(s, frame, slice_start, slice_end, 1, 4); + if (s->is_planar && s->alpha) + filter_rgb_planar(s, frame, slice_start, slice_end, 1); + else if (s->is_planar) + filter_rgb_planar(s, frame, slice_start, slice_end, 0); + else if (s->alpha) filter_rgb(s, frame, slice_start, slice_end, 1, 4); else if (s->bpp == 3) filter_rgb(s, frame, slice_start, slice_end, 0, 3); else if (s->bpp == 4) filter_rgb(s, frame, slice_start, slice_end, 0, 4); else av_assert0(0); @@ -224,14 +260,41 @@ int slice_end = (frame->height * (jobnr+1)) / nb_jobs; int i, j; - for (i = slice_start; i < slice_end; i++) { - uint8_t *p = frame->data[0] + i * frame->linesize[0]; - for (j = 0; j < frame->width * s->bpp; j++) { - /* s->factor is using 16 lower-order bits for decimal - * places. 32768 = 1 << 15, it is an integer representation - * of 0.5 and is for rounding. */ - *p = ((*p - s->black_level) * s->factor + s->black_level_scaled) >> 16; - p++; + for (int k = 0; k < 1 + 2 * (s->is_planar && s->is_rgb); k++) { + for (i = slice_start; i < slice_end; i++) { + uint8_t *p = frame->data[k] + i * frame->linesize[k]; + for (j = 0; j < frame->width * s->bpp; j++) { + /* s->factor is using 16 lower-order bits for decimal + * places. 32768 = 1 << 15, it is an integer representation + * of 0.5 and is for rounding. */ + *p = ((*p - s->black_level) * s->factor + s->black_level_scaled) >> 16; + p++; + } + } + } + + return 0; +} + +static int filter_slice_luma16(AVFilterContext *ctx, void *arg, int jobnr, + int nb_jobs) +{ + FadeContext *s = ctx->priv; + AVFrame *frame = arg; + int slice_start = (frame->height * jobnr ) / nb_jobs; + int slice_end = (frame->height * (jobnr+1)) / nb_jobs; + int i, j; + + for (int k = 0; k < 1 + 2 * (s->is_planar && s->is_rgb); k++) { + for (i = slice_start; i < slice_end; i++) { + uint16_t *p = (uint16_t *)(frame->data[k] + i * frame->linesize[k]); + for (j = 0; j < frame->width * s->bpp; j++) { + /* s->factor is using 16 lower-order bits for decimal + * places. 32768 = 1 << 15, it is an integer representation + * of 0.5 and is for rounding. */ + *p = ((*p - s->black_level) * s->factor + s->black_level_scaled) >> 16; + p++; + } } } @@ -265,6 +328,32 @@ return 0; } +static int filter_slice_chroma16(AVFilterContext *ctx, void *arg, int jobnr, + int nb_jobs) +{ + FadeContext *s = ctx->priv; + AVFrame *frame = arg; + int i, j, plane; + const int width = AV_CEIL_RSHIFT(frame->width, s->hsub); + const int height= AV_CEIL_RSHIFT(frame->height, s->vsub); + const int mid = 1 << (s->depth - 1); + const int add = ((mid << 1) + 1) << 15; + int slice_start = (height * jobnr ) / nb_jobs; + int slice_end = FFMIN(((height * (jobnr+1)) / nb_jobs), frame->height); + + for (plane = 1; plane < 3; plane++) { + for (i = slice_start; i < slice_end; i++) { + uint16_t *p = (uint16_t *)(frame->data[plane] + i * frame->linesize[plane]); + for (j = 0; j < width; j++) { + *p = ((*p - mid) * s->factor + add) >> 16; + p++; + } + } + } + + return 0; +} + static int filter_slice_alpha(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { @@ -290,33 +379,95 @@ return 0; } +static int filter_slice_alpha16(AVFilterContext *ctx, void *arg, int jobnr, + int nb_jobs) +{ + FadeContext *s = ctx->priv; + AVFrame *frame = arg; + int plane = s->is_packed_rgb ? 0 : A; + int slice_start = (frame->height * jobnr ) / nb_jobs; + int slice_end = (frame->height * (jobnr+1)) / nb_jobs; + int i, j; + + for (i = slice_start; i < slice_end; i++) { + uint16_t *p = (uint16_t *)(frame->data[plane] + i * frame->linesize[plane]) + s->is_packed_rgb*s->rgba_map[A]; + int step = s->is_packed_rgb ? 4 : 1; + for (j = 0; j < frame->width; j++) { + /* s->factor is using 16 lower-order bits for decimal + * places. 32768 = 1 << 15, it is an integer representation + * of 0.5 and is for rounding. */ + *p = ((*p - s->black_level) * s->factor + s->black_level_scaled) >> 16; + p += step; + } + } + + return 0; +} + +static int config_input(AVFilterLink *inlink) +{ + FadeContext *s = inlink->dst->priv; + const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(inlink->format); + + s->hsub = pixdesc->log2_chroma_w; + s->vsub = pixdesc->log2_chroma_h; + + ff_fill_rgba_map(s->rgba_map, inlink->format); + + s->depth = pixdesc->comp[0].depth; + s->bpp = pixdesc->flags & AV_PIX_FMT_FLAG_PLANAR ? + 1 : + av_get_bits_per_pixel(pixdesc) >> 3; + s->alpha &= !!(pixdesc->flags & AV_PIX_FMT_FLAG_ALPHA); + s->is_planar = pixdesc->flags & AV_PIX_FMT_FLAG_PLANAR; + s->is_rgb = pixdesc->flags & AV_PIX_FMT_FLAG_RGB; + s->is_packed_rgb = !s->is_planar && s->is_rgb; + + if (s->duration) + s->duration_pts = av_rescale_q(s->duration, AV_TIME_BASE_Q, inlink->time_base); + if (s->start_time) + s->start_time_pts = av_rescale_q(s->start_time, AV_TIME_BASE_Q, inlink->time_base); + + /* use CCIR601/709 black level for studio-level pixel non-alpha components */ + s->black_level = + ff_fmt_is_in(inlink->format, studio_level_pix_fmts) && !s->alpha ? 16 * (1 << (s->depth - 8)): 0; + /* 32768 = 1 << 15, it is an integer representation + * of 0.5 and is for rounding. */ + s->black_level_scaled = (s->black_level << 16) + 32768; + + s->filter_slice_luma = s->depth <= 8 ? filter_slice_luma : filter_slice_luma16; + s->filter_slice_chroma = s->depth <= 8 ? filter_slice_chroma : filter_slice_chroma16; + s->filter_slice_alpha = s->depth <= 8 ? filter_slice_alpha : filter_slice_alpha16; + + return 0; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; FadeContext *s = ctx->priv; - double frame_timestamp = frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base); // Calculate Fade assuming this is a Fade In if (s->fade_state == VF_FADE_WAITING) { s->factor=0; - if (frame_timestamp >= s->start_time/(double)AV_TIME_BASE + if (frame->pts >= s->start_time_pts && inlink->frame_count_out >= s->start_frame) { // Time to start fading s->fade_state = VF_FADE_FADING; // Save start time in case we are starting based on frames and fading based on time - if (s->start_time == 0 && s->start_frame != 0) { - s->start_time = frame_timestamp*(double)AV_TIME_BASE; + if (s->start_time_pts == 0 && s->start_frame != 0) { + s->start_time_pts = frame->pts; } // Save start frame in case we are starting based on time and fading based on frames - if (s->start_time != 0 && s->start_frame == 0) { + if (s->start_time_pts != 0 && s->start_frame == 0) { s->start_frame = inlink->frame_count_out; } } } if (s->fade_state == VF_FADE_FADING) { - if (s->duration == 0) { + if (s->duration_pts == 0) { // Fading based on frame count s->factor = (inlink->frame_count_out - s->start_frame) * s->fade_per_frame; if (inlink->frame_count_out > s->start_frame + s->nb_frames) { @@ -325,10 +476,8 @@ } else { // Fading based on duration - s->factor = (frame_timestamp - s->start_time/(double)AV_TIME_BASE) - * (float) UINT16_MAX / (s->duration/(double)AV_TIME_BASE); - if (frame_timestamp > s->start_time/(double)AV_TIME_BASE - + s->duration/(double)AV_TIME_BASE) { + s->factor = (frame->pts - s->start_time_pts) * UINT16_MAX / s->duration_pts; + if (frame->pts > s->start_time_pts + s->duration_pts) { s->fade_state = VF_FADE_DONE; } } @@ -346,19 +495,19 @@ if (s->factor < UINT16_MAX) { if (s->alpha) { - ctx->internal->execute(ctx, filter_slice_alpha, frame, NULL, + ctx->internal->execute(ctx, s->filter_slice_alpha, frame, NULL, FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); - } else if (s->is_packed_rgb && !s->black_fade) { + } else if (s->is_rgb && !s->black_fade) { ctx->internal->execute(ctx, filter_slice_rgb, frame, NULL, FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); } else { /* luma, or rgb plane in case of black */ - ctx->internal->execute(ctx, filter_slice_luma, frame, NULL, + ctx->internal->execute(ctx, s->filter_slice_luma, frame, NULL, FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); - if (frame->data[1] && frame->data[2]) { + if (frame->data[1] && frame->data[2] && !s->is_rgb) { /* chroma planes */ - ctx->internal->execute(ctx, filter_slice_chroma, frame, NULL, + ctx->internal->execute(ctx, s->filter_slice_chroma, frame, NULL, FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); } } @@ -372,18 +521,18 @@ #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption fade_options[] = { - { "type", "'in' or 'out' for fade-in/fade-out", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = FADE_IN }, FADE_IN, FADE_OUT, FLAGS, "type" }, - { "t", "'in' or 'out' for fade-in/fade-out", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = FADE_IN }, FADE_IN, FADE_OUT, FLAGS, "type" }, - { "in", "fade-in", 0, AV_OPT_TYPE_CONST, { .i64 = FADE_IN }, .unit = "type" }, - { "out", "fade-out", 0, AV_OPT_TYPE_CONST, { .i64 = FADE_OUT }, .unit = "type" }, + { "type", "set the fade direction", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = FADE_IN }, FADE_IN, FADE_OUT, FLAGS, "type" }, + { "t", "set the fade direction", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = FADE_IN }, FADE_IN, FADE_OUT, FLAGS, "type" }, + { "in", "fade-in", 0, AV_OPT_TYPE_CONST, { .i64 = FADE_IN }, .flags = FLAGS, .unit = "type" }, + { "out", "fade-out", 0, AV_OPT_TYPE_CONST, { .i64 = FADE_OUT }, .flags = FLAGS, .unit = "type" }, { "start_frame", "Number of the first frame to which to apply the effect.", OFFSET(start_frame), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, { "s", "Number of the first frame to which to apply the effect.", OFFSET(start_frame), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, { "nb_frames", "Number of frames to which the effect should be applied.", - OFFSET(nb_frames), AV_OPT_TYPE_INT, { .i64 = 25 }, 0, INT_MAX, FLAGS }, + OFFSET(nb_frames), AV_OPT_TYPE_INT, { .i64 = 25 }, 1, INT_MAX, FLAGS }, { "n", "Number of frames to which the effect should be applied.", - OFFSET(nb_frames), AV_OPT_TYPE_INT, { .i64 = 25 }, 0, INT_MAX, FLAGS }, + OFFSET(nb_frames), AV_OPT_TYPE_INT, { .i64 = 25 }, 1, INT_MAX, FLAGS }, { "alpha", "fade alpha if it is available on the input", OFFSET(alpha), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, FLAGS }, { "start_time", "Number of seconds of the beginning of the effect.", OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, @@ -393,8 +542,8 @@ OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, { "d", "Duration of the effect in seconds.", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, - { "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "c", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS }, + { "c", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS }, { NULL } }; @@ -404,7 +553,7 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .config_props = config_props, + .config_props = config_input, .filter_frame = filter_frame, .needs_writable = 1, }, @@ -428,5 +577,6 @@ .query_formats = query_formats, .inputs = avfilter_vf_fade_inputs, .outputs = avfilter_vf_fade_outputs, - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_fftdnoiz.c ffmpeg-4.4/libavfilter/vf_fftdnoiz.c --- ffmpeg-4.2.2/libavfilter/vf_fftdnoiz.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_fftdnoiz.c 2020-07-11 10:39:30.000000000 +0000 @@ -129,6 +129,11 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); @@ -156,7 +161,7 @@ int j; for (j = 0; j < rw; j++) - dst[j] = av_clip_uint8(src[j].re * scale); + dst[j] = av_clip_uint8(src[j].re * scale + 0.5f); } static void import_row16(FFTComplex *dst, uint8_t *srcp, int rw) @@ -176,7 +181,7 @@ int j; for (j = 0; j < rw; j++) - dst[j] = av_clip_uintp2_c(src[j].re * scale, depth); + dst[j] = av_clip_uintp2_c(src[j].re * scale + 0.5f, depth); } static int config_input(AVFilterLink *inlink) diff -Nru ffmpeg-4.2.2/libavfilter/vf_fftfilt.c ffmpeg-4.4/libavfilter/vf_fftfilt.c --- ffmpeg-4.2.2/libavfilter/vf_fftfilt.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_fftfilt.c 2020-07-11 10:39:30.000000000 +0000 @@ -81,9 +81,9 @@ { "dc_Y", "adjust gain in Y plane", OFFSET(dc[Y]), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1000, FLAGS }, { "dc_U", "adjust gain in U plane", OFFSET(dc[U]), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1000, FLAGS }, { "dc_V", "adjust gain in V plane", OFFSET(dc[V]), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1000, FLAGS }, - { "weight_Y", "set luminance expression in Y plane", OFFSET(weight_str[Y]), AV_OPT_TYPE_STRING, {.str = "1"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "weight_U", "set chrominance expression in U plane", OFFSET(weight_str[U]), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "weight_V", "set chrominance expression in V plane", OFFSET(weight_str[V]), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "weight_Y", "set luminance expression in Y plane", OFFSET(weight_str[Y]), AV_OPT_TYPE_STRING, {.str = "1"}, 0, 0, FLAGS }, + { "weight_U", "set chrominance expression in U plane", OFFSET(weight_str[U]), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, + { "weight_V", "set chrominance expression in V plane", OFFSET(weight_str[V]), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, 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}, .flags = FLAGS, .unit = "eval" }, { "frame", "eval expressions per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" }, diff -Nru ffmpeg-4.2.2/libavfilter/vf_fieldhint.c ffmpeg-4.4/libavfilter/vf_fieldhint.c --- ffmpeg-4.2.2/libavfilter/vf_fieldhint.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_fieldhint.c 2021-04-08 21:28:40.000000000 +0000 @@ -65,7 +65,7 @@ av_log(ctx, AV_LOG_ERROR, "Hint file must be set.\n"); return AVERROR(EINVAL); } - s->hint = fopen(s->hint_file_str, "r"); + s->hint = av_fopen_utf8(s->hint_file_str, "r"); if (!s->hint) { ret = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "%s: %s\n", s->hint_file_str, av_err2str(ret)); @@ -77,19 +77,16 @@ static int query_formats(AVFilterContext *ctx) { - AVFilterFormats *pix_fmts = NULL; - int fmt, ret; - - for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); - if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL || - desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) && - (ret = ff_add_format(&pix_fmts, fmt)) < 0) - return ret; - } + AVFilterFormats *formats = NULL; + int ret; - return ff_set_common_formats(ctx, pix_fmts); + ret = ff_formats_pixdesc_filter(&formats, 0, + AV_PIX_FMT_FLAG_HWACCEL | + AV_PIX_FMT_FLAG_BITSTREAM | + AV_PIX_FMT_FLAG_PAL); + if (ret < 0) + return ret; + return ff_set_common_formats(ctx, formats); } static int config_input(AVFilterLink *inlink) @@ -117,7 +114,8 @@ AVFrame *out, *top, *bottom; char buf[1024] = { 0 }; int64_t tf, bf; - char hint = '='; + int tfactor = 0, bfactor = 1; + char hint = '=', field = '='; int p; av_frame_free(&s->frame[0]); @@ -137,6 +135,8 @@ s->line++; if (buf[0] == '#' || buf[0] == ';') { continue; + } else if (sscanf(buf, "%"PRId64",%"PRId64" %c %c", &tf, &bf, &hint, &field) == 4) { + ; } else if (sscanf(buf, "%"PRId64",%"PRId64" %c", &tf, &bf, &hint) == 3) { ; } else if (sscanf(buf, "%"PRId64",%"PRId64"", &tf, &bf) == 2) { @@ -185,6 +185,23 @@ av_assert0(0); } + switch (field) { + case 'b': + tfactor = 1; + top = bottom; + break; + case 't': + bfactor = 0; + bottom = top; + break; + case '=': + break; + default: + av_log(ctx, AV_LOG_ERROR, "Invalid field: %c.\n", field); + av_frame_free(&out); + return AVERROR(EINVAL); + } + switch (hint) { case '+': out->interlaced_frame = 1; @@ -194,6 +211,14 @@ break; case '=': break; + case 'b': + tfactor = 1; + top = bottom; + break; + case 't': + bfactor = 0; + bottom = top; + break; default: av_log(ctx, AV_LOG_ERROR, "Invalid hint: %c.\n", hint); av_frame_free(&out); @@ -203,13 +228,13 @@ for (p = 0; p < s->nb_planes; p++) { av_image_copy_plane(out->data[p], out->linesize[p] * 2, - top->data[p], + top->data[p] + tfactor * top->linesize[p], top->linesize[p] * 2, s->planewidth[p], (s->planeheight[p] + 1) / 2); av_image_copy_plane(out->data[p] + out->linesize[p], out->linesize[p] * 2, - bottom->data[p] + bottom->linesize[p], + bottom->data[p] + bfactor * bottom->linesize[p], bottom->linesize[p] * 2, s->planewidth[p], (s->planeheight[p] + 1) / 2); diff -Nru ffmpeg-4.2.2/libavfilter/vf_fieldmatch.c ffmpeg-4.4/libavfilter/vf_fieldmatch.c --- ffmpeg-4.2.2/libavfilter/vf_fieldmatch.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_fieldmatch.c 2021-04-08 21:28:40.000000000 +0000 @@ -679,7 +679,7 @@ AVFilterLink *outlink = ctx->outputs[0]; FieldMatchContext *fm = ctx->priv; int combs[] = { -1, -1, -1, -1, -1 }; - int order, field, i, match, sc = 0; + int order, field, i, match, sc = 0, ret = 0; const int *fxo; AVFrame *gen_frames[] = { NULL, NULL, NULL, NULL, NULL }; AVFrame *dst; @@ -725,16 +725,20 @@ if (i > mN && fm->combdbg == COMBDBG_PCN) break; gen_frames[i] = create_weave_frame(ctx, i, field, fm->prv, fm->src, fm->nxt); - if (!gen_frames[i]) - return AVERROR(ENOMEM); + if (!gen_frames[i]) { + ret = AVERROR(ENOMEM); + goto fail; + } combs[i] = calc_combed_score(fm, gen_frames[i]); } av_log(ctx, AV_LOG_INFO, "COMBS: %3d %3d %3d %3d %3d\n", combs[0], combs[1], combs[2], combs[3], combs[4]); } else { gen_frames[mC] = av_frame_clone(fm->src); - if (!gen_frames[mC]) - return AVERROR(ENOMEM); + if (!gen_frames[mC]) { + ret = AVERROR(ENOMEM); + goto fail; + } } /* p/c selection and optional 3-way p/c/n matches */ @@ -801,10 +805,10 @@ gen_frames[match] = NULL; } } - if (!dst) - return AVERROR(ENOMEM); - for (i = 0; i < FF_ARRAY_ELEMS(gen_frames); i++) - av_frame_free(&gen_frames[i]); + if (!dst) { + ret = AVERROR(ENOMEM); + goto fail; + } /* mark the frame we are unable to match properly as interlaced so a proper * de-interlacer can take the relay */ @@ -819,7 +823,13 @@ " match=%d combed=%s\n", sc, combs[0], combs[1], combs[2], combs[3], combs[4], fm->combpel, match, dst->interlaced_frame ? "YES" : "NO"); - return ff_filter_frame(outlink, dst); +fail: + for (i = 0; i < FF_ARRAY_ELEMS(gen_frames); i++) + av_frame_free(&gen_frames[i]); + + if (ret >= 0) + return ff_filter_frame(outlink, dst); + return ret; } static int activate(AVFilterContext *ctx) @@ -829,6 +839,8 @@ int ret = 0, status; int64_t pts; + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); + if ((fm->got_frame[INPUT_MAIN] == 0) && (ret = ff_inlink_consume_frame(ctx->inputs[INPUT_MAIN], &frame)) > 0) { ret = filter_frame(ctx->inputs[INPUT_MAIN], frame); @@ -905,14 +917,14 @@ return ff_set_common_formats(ctx, fmts_list); } - if ((ret = ff_formats_ref(fmts_list, &ctx->inputs[INPUT_MAIN]->out_formats)) < 0) + if ((ret = ff_formats_ref(fmts_list, &ctx->inputs[INPUT_MAIN]->outcfg.formats)) < 0) return ret; fmts_list = ff_make_format_list(unproc_pix_fmts); if (!fmts_list) return AVERROR(ENOMEM); - if ((ret = ff_formats_ref(fmts_list, &ctx->outputs[0]->in_formats)) < 0) + if ((ret = ff_formats_ref(fmts_list, &ctx->outputs[0]->incfg.formats)) < 0) return ret; - if ((ret = ff_formats_ref(fmts_list, &ctx->inputs[INPUT_CLEANSRC]->out_formats)) < 0) + if ((ret = ff_formats_ref(fmts_list, &ctx->inputs[INPUT_CLEANSRC]->outcfg.formats)) < 0) return ret; return 0; } @@ -938,9 +950,9 @@ fm->tpitchy = FFALIGN(w, 16); fm->tpitchuv = FFALIGN(w >> 1, 16); - fm->tbuffer = av_malloc(h/2 * fm->tpitchy); - fm->c_array = av_malloc((((w + fm->blockx/2)/fm->blockx)+1) * - (((h + fm->blocky/2)/fm->blocky)+1) * + fm->tbuffer = av_calloc((h/2 + 4) * fm->tpitchy, sizeof(*fm->tbuffer)); + fm->c_array = av_malloc_array((((w + fm->blockx/2)/fm->blockx)+1) * + (((h + fm->blocky/2)/fm->blocky)+1), 4 * sizeof(*fm->c_array)); if (!fm->tbuffer || !fm->c_array) return AVERROR(ENOMEM); @@ -952,28 +964,20 @@ { const FieldMatchContext *fm = ctx->priv; AVFilterPad pad = { - .name = av_strdup("main"), + .name = "main", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_input, }; int ret; - if (!pad.name) - return AVERROR(ENOMEM); - if ((ret = ff_insert_inpad(ctx, INPUT_MAIN, &pad)) < 0) { - av_freep(&pad.name); + if ((ret = ff_insert_inpad(ctx, INPUT_MAIN, &pad)) < 0) return ret; - } if (fm->ppsrc) { - pad.name = av_strdup("clean_src"); + pad.name = "clean_src"; pad.config_props = NULL; - if (!pad.name) - return AVERROR(ENOMEM); - if ((ret = ff_insert_inpad(ctx, INPUT_CLEANSRC, &pad)) < 0) { - av_freep(&pad.name); + if ((ret = ff_insert_inpad(ctx, INPUT_CLEANSRC, &pad)) < 0) return ret; - } } if ((fm->blockx & (fm->blockx - 1)) || @@ -992,7 +996,6 @@ static av_cold void fieldmatch_uninit(AVFilterContext *ctx) { - int i; FieldMatchContext *fm = ctx->priv; if (fm->prv != fm->src) @@ -1009,8 +1012,6 @@ av_freep(&fm->cmask_data[0]); av_freep(&fm->tbuffer); av_freep(&fm->c_array); - for (i = 0; i < ctx->nb_inputs; i++) - av_freep(&ctx->input_pads[i].name); } static int config_output(AVFilterLink *outlink) diff -Nru ffmpeg-4.2.2/libavfilter/vf_fieldorder.c ffmpeg-4.4/libavfilter/vf_fieldorder.c --- ffmpeg-4.2.2/libavfilter/vf_fieldorder.c 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_fieldorder.c 2021-04-08 21:28:40.000000000 +0000 @@ -58,8 +58,8 @@ (ret = ff_add_format(&formats, pix_fmt)) < 0) return ret; } - if ((ret = ff_formats_ref(formats, &ctx->inputs[0]->out_formats)) < 0 || - (ret = ff_formats_ref(formats, &ctx->outputs[0]->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &ctx->inputs[0]->outcfg.formats)) < 0 || + (ret = ff_formats_ref(formats, &ctx->outputs[0]->incfg.formats)) < 0) return ret; } @@ -108,8 +108,8 @@ s->dst_tff ? "up" : "down"); h = frame->height; for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) { - dst_line_step = out->linesize[plane]; - src_line_step = frame->linesize[plane]; + dst_line_step = out->linesize[plane] * (h > 2); + src_line_step = frame->linesize[plane] * (h > 2); line_size = s->line_size[plane]; dst = out->data[plane]; src = frame->data[plane]; diff -Nru ffmpeg-4.2.2/libavfilter/vf_fillborders.c ffmpeg-4.4/libavfilter/vf_fillborders.c --- ffmpeg-4.2.2/libavfilter/vf_fillborders.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_fillborders.c 2021-04-08 21:28:40.000000000 +0000 @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/colorspace.h" #include "libavutil/common.h" #include "libavutil/opt.h" @@ -31,7 +32,7 @@ enum { Y, U, V, A }; enum { R, G, B }; -enum FillMode { FM_SMEAR, FM_MIRROR, FM_FIXED, FM_NB_MODES }; +enum FillMode { FM_SMEAR, FM_MIRROR, FM_FIXED, FM_REFLECT, FM_WRAP, FM_FADE, FM_NB_MODES }; typedef struct Borders { int left, right, top, bottom; @@ -69,6 +70,7 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, @@ -268,6 +270,231 @@ } } +static void reflect_borders8(FillBordersContext *s, AVFrame *frame) +{ + int p, y, x; + + for (p = 0; p < s->nb_planes; p++) { + uint8_t *ptr = frame->data[p]; + int linesize = frame->linesize[p]; + + for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) { + for (x = 0; x < s->borders[p].left; x++) { + ptr[y * linesize + x] = ptr[y * linesize + s->borders[p].left * 2 - x]; + } + + for (x = 0; x < s->borders[p].right; x++) { + ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] = + ptr[y * linesize + s->planewidth[p] - s->borders[p].right - 2 - x]; + } + } + + for (y = 0; y < s->borders[p].top; y++) { + memcpy(ptr + y * linesize, + ptr + (s->borders[p].top * 2 - y) * linesize, + s->planewidth[p]); + } + + for (y = 0; y < s->borders[p].bottom; y++) { + memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize, + ptr + (s->planeheight[p] - s->borders[p].bottom - 2 - y) * linesize, + s->planewidth[p]); + } + } +} + +static void reflect_borders16(FillBordersContext *s, AVFrame *frame) +{ + int p, y, x; + + for (p = 0; p < s->nb_planes; p++) { + uint16_t *ptr = (uint16_t *)frame->data[p]; + int linesize = frame->linesize[p] / 2; + + for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) { + for (x = 0; x < s->borders[p].left; x++) { + ptr[y * linesize + x] = ptr[y * linesize + s->borders[p].left * 2 - x]; + } + + for (x = 0; x < s->borders[p].right; x++) { + ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] = + ptr[y * linesize + s->planewidth[p] - s->borders[p].right - 2 - x]; + } + } + + for (y = 0; y < s->borders[p].top; y++) { + memcpy(ptr + y * linesize, + ptr + (s->borders[p].top * 2 - y) * linesize, + s->planewidth[p] * 2); + } + + for (y = 0; y < s->borders[p].bottom; y++) { + memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize, + ptr + (s->planeheight[p] - s->borders[p].bottom - 2 - y) * linesize, + s->planewidth[p] * 2); + } + } +} + +static void wrap_borders8(FillBordersContext *s, AVFrame *frame) +{ + int p, y, x; + + for (p = 0; p < s->nb_planes; p++) { + uint8_t *ptr = frame->data[p]; + int linesize = frame->linesize[p]; + + for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) { + for (x = 0; x < s->borders[p].left; x++) { + ptr[y * linesize + x] = ptr[y * linesize + s->planewidth[p] - s->borders[p].right - s->borders[p].left + x]; + } + + for (x = 0; x < s->borders[p].right; x++) { + ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] = + ptr[y * linesize + s->borders[p].left + x]; + } + } + + for (y = 0; y < s->borders[p].top; y++) { + memcpy(ptr + y * linesize, + ptr + (s->planeheight[p] - s->borders[p].bottom - s->borders[p].top + y) * linesize, + s->planewidth[p]); + } + + for (y = 0; y < s->borders[p].bottom; y++) { + memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize, + ptr + (s->borders[p].top + y) * linesize, + s->planewidth[p]); + } + } +} + +static void wrap_borders16(FillBordersContext *s, AVFrame *frame) +{ + int p, y, x; + + for (p = 0; p < s->nb_planes; p++) { + uint16_t *ptr = (uint16_t *)frame->data[p]; + int linesize = frame->linesize[p] / 2; + + for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) { + for (x = 0; x < s->borders[p].left; x++) { + ptr[y * linesize + x] = ptr[y * linesize + s->planewidth[p] - s->borders[p].right - s->borders[p].left + x]; + } + + for (x = 0; x < s->borders[p].right; x++) { + ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] = + ptr[y * linesize + s->borders[p].left + x]; + } + } + + for (y = 0; y < s->borders[p].top; y++) { + memcpy(ptr + y * linesize, + ptr + (s->planeheight[p] - s->borders[p].bottom - s->borders[p].top + y) * linesize, + s->planewidth[p] * 2); + } + + for (y = 0; y < s->borders[p].bottom; y++) { + memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize, + ptr + (s->borders[p].top + y) * linesize, + s->planewidth[p] * 2); + } + } +} + +static int lerp8(int fill, int src, int pos, int size) +{ + return av_clip_uint8(((fill * 256 * pos / size) + (src * 256 * (size - pos) / size)) >> 8); +} + +static int lerp16(int fill, int src, int pos, int size, int depth) +{ + return av_clip_uintp2_c(((fill * (1LL << depth) * pos / size) + (src * (1LL << depth) * (size - pos) / size)) >> depth, depth); +} + +static void fade_borders8(FillBordersContext *s, AVFrame *frame) +{ + int p, y, x; + + for (p = 0; p < s->nb_planes; p++) { + uint8_t *ptr = frame->data[p]; + const uint8_t fill = s->fill[p]; + const int linesize = frame->linesize[p]; + const int start_left = s->borders[p].left; + const int start_right = s->planewidth[p] - s->borders[p].right; + const int start_top = s->borders[p].top; + const int start_bottom = s->planeheight[p] - s->borders[p].bottom; + + for (y = 0; y < start_top; y++) { + for (x = 0; x < s->planewidth[p]; x++) { + int src = ptr[y * linesize + x]; + ptr[y * linesize + x] = lerp8(fill, src, start_top - y, start_top); + } + } + + for (y = start_bottom; y < s->planeheight[p]; y++) { + for (x = 0; x < s->planewidth[p]; x++) { + int src = ptr[y * linesize + x]; + ptr[y * linesize + x] = lerp8(fill, src, y - start_bottom, s->borders[p].bottom); + } + } + + for (y = 0; y < s->planeheight[p]; y++) { + for (x = 0; x < start_left; x++) { + int src = ptr[y * linesize + x]; + ptr[y * linesize + x] = lerp8(fill, src, start_left - x, start_left); + } + + for (x = 0; x < s->borders[p].right; x++) { + int src = ptr[y * linesize + start_right + x]; + ptr[y * linesize + start_right + x] = lerp8(fill, src, x, s->borders[p].right); + } + } + } +} + +static void fade_borders16(FillBordersContext *s, AVFrame *frame) +{ + const int depth = s->depth; + int p, y, x; + + for (p = 0; p < s->nb_planes; p++) { + uint16_t *ptr = (uint16_t *)frame->data[p]; + const uint16_t fill = s->fill[p] << (depth - 8); + const int linesize = frame->linesize[p] / 2; + const int start_left = s->borders[p].left; + const int start_right = s->planewidth[p] - s->borders[p].right; + const int start_top = s->borders[p].top; + const int start_bottom = s->planeheight[p] - s->borders[p].bottom; + + for (y = 0; y < start_top; y++) { + for (x = 0; x < s->planewidth[p]; x++) { + int src = ptr[y * linesize + x]; + ptr[y * linesize + x] = lerp16(fill, src, start_top - y, start_top, depth); + } + } + + for (y = start_bottom; y < s->planeheight[p]; y++) { + for (x = 0; x < s->planewidth[p]; x++) { + int src = ptr[y * linesize + x]; + ptr[y * linesize + x] = lerp16(fill, src, y - start_bottom, s->borders[p].bottom, depth); + } + } + + for (y = 0; y < s->planeheight[p]; y++) { + for (x = 0; x < start_left; x++) { + int src = ptr[y * linesize + x]; + ptr[y * linesize + x] = lerp16(fill, src, start_left - x, start_left, depth); + } + + for (x = 0; x < s->borders[p].right; x++) { + int src = ptr[y * linesize + start_right + x]; + ptr[y * linesize + start_right + x] = lerp16(fill, src, x, s->borders[p].right, depth); + } + } + } +} + static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { FillBordersContext *s = inlink->dst->priv; @@ -291,6 +518,20 @@ s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); s->planewidth[0] = s->planewidth[3] = inlink->w; + if (inlink->w < s->left + s->right || + inlink->w <= s->left || + inlink->w <= s->right || + inlink->h < s->top + s->bottom || + inlink->h <= s->top || + inlink->h <= s->bottom || + inlink->w < s->left * 2 || + inlink->w < s->right * 2 || + inlink->h < s->top * 2 || + inlink->h < s->bottom * 2) { + av_log(ctx, AV_LOG_ERROR, "Borders are bigger than input frame size.\n"); + return AVERROR(EINVAL); + } + s->borders[0].left = s->borders[3].left = s->left; s->borders[0].right = s->borders[3].right = s->right; s->borders[0].top = s->borders[3].top = s->top; @@ -306,24 +547,14 @@ s->borders[2].top = s->top >> desc->log2_chroma_h; s->borders[2].bottom = s->bottom >> desc->log2_chroma_h; - if (inlink->w < s->left + s->right || - inlink->w <= s->left || - inlink->w <= s->right || - inlink->h < s->top + s->bottom || - inlink->h <= s->top || - inlink->h <= s->bottom || - inlink->w < s->left * 2 || - inlink->w < s->right * 2 || - inlink->h < s->top * 2 || - inlink->h < s->bottom * 2) { - av_log(ctx, AV_LOG_ERROR, "Borders are bigger than input frame size.\n"); - return AVERROR(EINVAL); - } - switch (s->mode) { case FM_SMEAR: s->fillborders = s->depth <= 8 ? smear_borders8 : smear_borders16; break; case FM_MIRROR: s->fillborders = s->depth <= 8 ? mirror_borders8 : mirror_borders16; break; case FM_FIXED: s->fillborders = s->depth <= 8 ? fixed_borders8 : fixed_borders16; break; + case FM_REFLECT:s->fillborders = s->depth <= 8 ? reflect_borders8: reflect_borders16;break; + case FM_WRAP: s->fillborders = s->depth <= 8 ? wrap_borders8 : wrap_borders16; break; + case FM_FADE: s->fillborders = s->depth <= 8 ? fade_borders8 : fade_borders16; break; + default: av_assert0(0); } s->yuv_color[Y] = RGB_TO_Y_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B]); @@ -345,8 +576,20 @@ return 0; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + #define OFFSET(x) offsetof(FillBordersContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption fillborders_options[] = { { "left", "set the left fill border", OFFSET(left), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, @@ -357,7 +600,10 @@ { "smear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_SMEAR}, 0, 0, FLAGS, "mode" }, { "mirror", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_MIRROR}, 0, 0, FLAGS, "mode" }, { "fixed", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_FIXED}, 0, 0, FLAGS, "mode" }, - { "color", "set the color for the fixed mode", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str = "black"}, .flags = FLAGS }, + { "reflect",NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_REFLECT},0, 0, FLAGS, "mode" }, + { "wrap", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_WRAP}, 0, 0, FLAGS, "mode" }, + { "fade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_FADE}, 0, 0, FLAGS, "mode" }, + { "color", "set the color for the fixed/fade mode", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str = "black"}, .flags = FLAGS }, { NULL } }; @@ -391,4 +637,5 @@ .inputs = fillborders_inputs, .outputs = fillborders_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_find_rect.c ffmpeg-4.4/libavfilter/vf_find_rect.c --- ffmpeg-4.2.2/libavfilter/vf_find_rect.c 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_find_rect.c 2020-07-11 10:39:30.000000000 +0000 @@ -22,7 +22,6 @@ * @todo switch to dualinput */ -#include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "internal.h" @@ -81,7 +80,7 @@ frame->width = (in->width + 1) / 2; frame->height = (in->height+ 1) / 2; - if (av_frame_get_buffer(frame, 32) < 0) { + if (av_frame_get_buffer(frame, 0) < 0) { av_frame_free(&frame); return NULL; } @@ -159,7 +158,7 @@ if (pass + 1 <= maxpass) { int sub_x, sub_y; - search(foc, pass+1, maxpass, xmin>>1, (xmax+1)>>1, ymin>>1, (ymax+1)>>1, &sub_x, &sub_y, 1.0); + search(foc, pass+1, maxpass, xmin>>1, (xmax+1)>>1, ymin>>1, (ymax+1)>>1, &sub_x, &sub_y, 2.0); xmin = FFMAX(xmin, 2*sub_x - 4); xmax = FFMIN(xmax, 2*sub_x + 4); ymin = FFMAX(ymin, 2*sub_y - 4); @@ -169,7 +168,6 @@ for (y = ymin; y <= ymax; y++) { for (x = xmin; x <= xmax; x++) { float score = compare(foc->haystack_frame[pass], foc->needle_frame[pass], x, y); - av_assert0(score != 0); if (score < best_score) { best_score = score; *best_x = x; @@ -198,7 +196,7 @@ FFMIN(foc->xmax, foc->last_x + 8), FFMAX(foc->ymin, foc->last_y - 8), FFMIN(foc->ymax, foc->last_y + 8), - &best_x, &best_y, 1.0); + &best_x, &best_y, 2.0); best_score = search(foc, 0, foc->mipmaps - 1, foc->xmin, foc->xmax, foc->ymin, foc->ymax, &best_x, &best_y, best_score); diff -Nru ffmpeg-4.2.2/libavfilter/vf_floodfill.c ffmpeg-4.4/libavfilter/vf_floodfill.c --- ffmpeg-4.2.2/libavfilter/vf_floodfill.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_floodfill.c 2020-07-11 10:39:30.000000000 +0000 @@ -34,9 +34,11 @@ const AVClass *class; int x, y; - int s0, s1, s2, s3; - int d0, d1, d2, d3; + int s[4]; + int S[4]; + int d[4]; + int nb_planes; int back, front; Points *points; @@ -238,12 +240,12 @@ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); AVFilterContext *ctx = inlink->dst; FloodfillContext *s = ctx->priv; - int nb_planes = av_pix_fmt_count_planes(inlink->format); int depth; + s->nb_planes = av_pix_fmt_count_planes(inlink->format); depth = desc->comp[0].depth; if (depth == 8) { - switch (nb_planes) { + switch (s->nb_planes) { case 1: s->set_pixel = set_pixel1; s->is_same = is_same1; s->pick_pixel = pick_pixel1; break; @@ -255,7 +257,7 @@ s->pick_pixel = pick_pixel4; break; } } else { - switch (nb_planes) { + switch (s->nb_planes) { case 1: s->set_pixel = set_pixel1_16; s->is_same = is_same1_16; s->pick_pixel = pick_pixel1_16; break; @@ -280,30 +282,42 @@ { AVFilterContext *ctx = link->dst; FloodfillContext *s = ctx->priv; - const unsigned d0 = s->d0; - const unsigned d1 = s->d1; - const unsigned d2 = s->d2; - const unsigned d3 = s->d3; - int s0 = s->s0; - int s1 = s->s1; - int s2 = s->s2; - int s3 = s->s3; + const unsigned d0 = s->d[0]; + const unsigned d1 = s->d[1]; + const unsigned d2 = s->d[2]; + const unsigned d3 = s->d[3]; + int s0 = s->s[0]; + int s1 = s->s[1]; + int s2 = s->s[2]; + int s3 = s->s[3]; const int w = frame->width; const int h = frame->height; - int ret; - - if (ret = av_frame_make_writable(frame)) - return ret; + int i, ret; if (is_inside(s->x, s->y, w, h)) { s->pick_pixel(frame, s->x, s->y, &s0, &s1, &s2, &s3); + s->S[0] = s0; + s->S[1] = s1; + s->S[2] = s2; + s->S[3] = s3; + for (i = 0; i < s->nb_planes; i++) { + if (s->S[i] != s->d[i]) + break; + } + + if (i == s->nb_planes) + goto end; + if (s->is_same(frame, s->x, s->y, s0, s1, s2, s3)) { s->points[s->front].x = s->x; s->points[s->front].y = s->y; s->front++; } + if (ret = av_frame_make_writable(frame)) + return ret; + while (s->front > s->back) { int x, y; @@ -337,34 +351,20 @@ } } +end: return ff_filter_frame(ctx->outputs[0], frame); } static av_cold int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pixel_fmts[] = { - AV_PIX_FMT_GRAY8, - AV_PIX_FMT_YUV444P, - AV_PIX_FMT_YUVA444P, - AV_PIX_FMT_GBRP, - AV_PIX_FMT_GBRP9, - AV_PIX_FMT_GBRP10, - AV_PIX_FMT_GBRAP10, - AV_PIX_FMT_GBRP12, - AV_PIX_FMT_GBRAP12, - AV_PIX_FMT_GBRP14, - AV_PIX_FMT_GBRP16, - AV_PIX_FMT_GBRAP16, - AV_PIX_FMT_GBRAP, - AV_PIX_FMT_YUV444P9, - AV_PIX_FMT_YUVA444P9, - AV_PIX_FMT_YUV444P10, - AV_PIX_FMT_YUVA444P10, - AV_PIX_FMT_YUV444P12, - AV_PIX_FMT_YUV444P14, - AV_PIX_FMT_GRAY16, - AV_PIX_FMT_YUV444P16, - AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP16, AV_PIX_FMT_GBRAP, + AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_NONE }; AVFilterFormats *formats; @@ -405,16 +405,16 @@ #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption floodfill_options[] = { - { "x", "set pixel x coordinate", OFFSET(x), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, - { "y", "set pixel y coordinate", OFFSET(y), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, - { "s0", "set source #0 component value", OFFSET(s0), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS }, - { "s1", "set source #1 component value", OFFSET(s1), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS }, - { "s2", "set source #2 component value", OFFSET(s2), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS }, - { "s3", "set source #3 component value", OFFSET(s3), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS }, - { "d0", "set destination #0 component value", OFFSET(d0), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, - { "d1", "set destination #1 component value", OFFSET(d1), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, - { "d2", "set destination #2 component value", OFFSET(d2), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, - { "d3", "set destination #3 component value", OFFSET(d3), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, + { "x", "set pixel x coordinate", OFFSET(x), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, + { "y", "set pixel y coordinate", OFFSET(y), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, + { "s0", "set source #0 component value", OFFSET(s[0]), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS }, + { "s1", "set source #1 component value", OFFSET(s[1]), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS }, + { "s2", "set source #2 component value", OFFSET(s[2]), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS }, + { "s3", "set source #3 component value", OFFSET(s[3]), AV_OPT_TYPE_INT, {.i64=0},-1, UINT16_MAX, FLAGS }, + { "d0", "set destination #0 component value", OFFSET(d[0]), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, + { "d1", "set destination #1 component value", OFFSET(d[1]), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, + { "d2", "set destination #2 component value", OFFSET(d[2]), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, + { "d3", "set destination #3 component value", OFFSET(d[3]), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, { NULL } }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_fps.c ffmpeg-4.4/libavfilter/vf_fps.c --- ffmpeg-4.2.2/libavfilter/vf_fps.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_fps.c 2020-07-11 10:39:30.000000000 +0000 @@ -256,7 +256,7 @@ av_log(ctx, AV_LOG_DEBUG, "Writing frame with pts %"PRId64" to pts %"PRId64"\n", s->frames[0]->pts, frame->pts); s->cur_frame_out++; - + *again = 1; return ff_filter_frame(outlink, frame); } } diff -Nru ffmpeg-4.2.2/libavfilter/vf_framepack.c ffmpeg-4.4/libavfilter/vf_framepack.c --- ffmpeg-4.2.2/libavfilter/vf_framepack.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_framepack.c 2021-04-08 21:28:40.000000000 +0000 @@ -33,6 +33,7 @@ #include "libavutil/stereo3d.h" #include "avfilter.h" +#include "filters.h" #include "formats.h" #include "internal.h" #include "video.h" @@ -43,19 +44,38 @@ typedef struct FramepackContext { const AVClass *class; + int depth; const AVPixFmtDescriptor *pix_desc; ///< agreed pixel format enum AVStereo3DType format; ///< frame pack type output AVFrame *input_views[2]; ///< input frames - - int64_t double_pts; ///< new pts for frameseq mode } FramepackContext; static const enum AVPixelFormat formats_supported[] = { - AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, - AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVJ420P, - AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, + AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, + AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; @@ -114,14 +134,13 @@ s->pix_desc = av_pix_fmt_desc_get(outlink->format); if (!s->pix_desc) return AVERROR_BUG; + s->depth = s->pix_desc->comp[0].depth; // modify output properties as needed switch (s->format) { case AV_STEREO3D_FRAMESEQUENCE: time_base.den *= 2; frame_rate.num *= 2; - - s->double_pts = AV_NOPTS_VALUE; break; case AV_STEREO3D_COLUMNS: case AV_STEREO3D_SIDEBYSIDE: @@ -152,7 +171,7 @@ FramepackContext *s = ctx->priv; int i, plane; - if (interleaved) { + if (interleaved && s->depth <= 8) { const uint8_t *leftp = s->input_views[LEFT]->data[0]; const uint8_t *rightp = s->input_views[RIGHT]->data[0]; uint8_t *dstp = out->data[0]; @@ -187,17 +206,53 @@ } } } + } else if (interleaved && s->depth > 8) { + const uint16_t *leftp = (const uint16_t *)s->input_views[LEFT]->data[0]; + const uint16_t *rightp = (const uint16_t *)s->input_views[RIGHT]->data[0]; + uint16_t *dstp = (uint16_t *)out->data[0]; + int length = out->width / 2; + int lines = out->height; + + for (plane = 0; plane < s->pix_desc->nb_components; plane++) { + if (plane == 1 || plane == 2) { + length = AV_CEIL_RSHIFT(out->width / 2, s->pix_desc->log2_chroma_w); + lines = AV_CEIL_RSHIFT(out->height, s->pix_desc->log2_chroma_h); + } + for (i = 0; i < lines; i++) { + int j; + leftp = (const uint16_t *)s->input_views[LEFT]->data[plane] + + s->input_views[LEFT]->linesize[plane] * i / 2; + rightp = (const uint16_t *)s->input_views[RIGHT]->data[plane] + + s->input_views[RIGHT]->linesize[plane] * i / 2; + dstp = (uint16_t *)out->data[plane] + out->linesize[plane] * i / 2; + for (j = 0; j < length; j++) { + // interpolate chroma as necessary + if ((s->pix_desc->log2_chroma_w || + s->pix_desc->log2_chroma_h) && + (plane == 1 || plane == 2)) { + *dstp++ = (*leftp + *rightp) / 2; + *dstp++ = (*leftp + *rightp) / 2; + } else { + *dstp++ = *leftp; + *dstp++ = *rightp; + } + leftp += 1; + rightp += 1; + } + } + } } else { for (i = 0; i < 2; i++) { + const int psize = 1 + (s->depth > 8); const uint8_t *src[4]; uint8_t *dst[4]; - int sub_w = s->input_views[i]->width >> s->pix_desc->log2_chroma_w; + int sub_w = psize * s->input_views[i]->width >> s->pix_desc->log2_chroma_w; src[0] = s->input_views[i]->data[0]; src[1] = s->input_views[i]->data[1]; src[2] = s->input_views[i]->data[2]; - dst[0] = out->data[0] + i * s->input_views[i]->width; + dst[0] = out->data[0] + i * s->input_views[i]->width * psize; dst[1] = out->data[1] + i * sub_w; dst[2] = out->data[2] + i * sub_w; @@ -269,39 +324,6 @@ } } -static int try_push_frame(AVFilterContext *ctx); - -static int filter_frame_left(AVFilterLink *inlink, AVFrame *frame) -{ - FramepackContext *s = inlink->dst->priv; - s->input_views[LEFT] = frame; - return try_push_frame(inlink->dst); -} - -static int filter_frame_right(AVFilterLink *inlink, AVFrame *frame) -{ - FramepackContext *s = inlink->dst->priv; - s->input_views[RIGHT] = frame; - return try_push_frame(inlink->dst); -} - -static int request_frame(AVFilterLink *outlink) -{ - AVFilterContext *ctx = outlink->src; - FramepackContext *s = ctx->priv; - int ret, i; - - /* get a frame on the either input, stop as soon as a video ends */ - for (i = 0; i < 2; i++) { - if (!s->input_views[i]) { - ret = ff_request_frame(ctx->inputs[i]); - if (ret < 0) - return ret; - } - } - return 0; -} - static int try_push_frame(AVFilterContext *ctx) { FramepackContext *s = ctx->priv; @@ -312,12 +334,12 @@ if (!(s->input_views[0] && s->input_views[1])) return 0; if (s->format == AV_STEREO3D_FRAMESEQUENCE) { - if (s->double_pts == AV_NOPTS_VALUE) - s->double_pts = s->input_views[LEFT]->pts; + int64_t pts = s->input_views[0]->pts; for (i = 0; i < 2; i++) { // set correct timestamps - s->input_views[i]->pts = s->double_pts++; + if (pts != AV_NOPTS_VALUE) + s->input_views[i]->pts = i == 0 ? pts * 2 : pts * 2 + av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base); // set stereo3d side data stereo = av_stereo3d_create_side_data(s->input_views[i]); @@ -363,21 +385,64 @@ } } +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *outlink = ctx->outputs[0]; + FramepackContext *s = ctx->priv; + int ret; + + FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); + + if (!s->input_views[0]) { + ret = ff_inlink_consume_frame(ctx->inputs[0], &s->input_views[0]); + if (ret < 0) + return ret; + } + + if (!s->input_views[1]) { + ret = ff_inlink_consume_frame(ctx->inputs[1], &s->input_views[1]); + if (ret < 0) + return ret; + } + + if (s->input_views[0] && s->input_views[1]) + return try_push_frame(ctx); + + FF_FILTER_FORWARD_STATUS(ctx->inputs[0], outlink); + FF_FILTER_FORWARD_STATUS(ctx->inputs[1], outlink); + + if (ff_outlink_frame_wanted(ctx->outputs[0]) && + !ff_outlink_get_status(ctx->inputs[0]) && + !s->input_views[0]) { + ff_inlink_request_frame(ctx->inputs[0]); + return 0; + } + + if (ff_outlink_frame_wanted(ctx->outputs[0]) && + !ff_outlink_get_status(ctx->inputs[1]) && + !s->input_views[1]) { + ff_inlink_request_frame(ctx->inputs[1]); + return 0; + } + + return FFERROR_NOT_READY; +} + #define OFFSET(x) offsetof(FramepackContext, x) -#define V AV_OPT_FLAG_VIDEO_PARAM +#define VF AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM static const AVOption framepack_options[] = { { "format", "Frame pack output format", OFFSET(format), AV_OPT_TYPE_INT, - { .i64 = AV_STEREO3D_SIDEBYSIDE }, 0, INT_MAX, .flags = V, .unit = "format" }, + { .i64 = AV_STEREO3D_SIDEBYSIDE }, 0, INT_MAX, .flags = VF, .unit = "format" }, { "sbs", "Views are packed next to each other", 0, AV_OPT_TYPE_CONST, - { .i64 = AV_STEREO3D_SIDEBYSIDE }, INT_MIN, INT_MAX, .flags = V, .unit = "format" }, + { .i64 = AV_STEREO3D_SIDEBYSIDE }, INT_MIN, INT_MAX, .flags = VF, .unit = "format" }, { "tab", "Views are packed on top of each other", 0, AV_OPT_TYPE_CONST, - { .i64 = AV_STEREO3D_TOPBOTTOM }, INT_MIN, INT_MAX, .flags = V, .unit = "format" }, + { .i64 = AV_STEREO3D_TOPBOTTOM }, INT_MIN, INT_MAX, .flags = VF, .unit = "format" }, { "frameseq", "Views are one after the other", 0, AV_OPT_TYPE_CONST, - { .i64 = AV_STEREO3D_FRAMESEQUENCE }, INT_MIN, INT_MAX, .flags = V, .unit = "format" }, + { .i64 = AV_STEREO3D_FRAMESEQUENCE }, INT_MIN, INT_MAX, .flags = VF, .unit = "format" }, { "lines", "Views are interleaved by lines", 0, AV_OPT_TYPE_CONST, - { .i64 = AV_STEREO3D_LINES }, INT_MIN, INT_MAX, .flags = V, .unit = "format" }, + { .i64 = AV_STEREO3D_LINES }, INT_MIN, INT_MAX, .flags = VF, .unit = "format" }, { "columns", "Views are interleaved by columns", 0, AV_OPT_TYPE_CONST, - { .i64 = AV_STEREO3D_COLUMNS }, INT_MIN, INT_MAX, .flags = V, .unit = "format" }, + { .i64 = AV_STEREO3D_COLUMNS }, INT_MIN, INT_MAX, .flags = VF, .unit = "format" }, { NULL }, }; @@ -387,14 +452,10 @@ { .name = "left", .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = filter_frame_left, - .needs_fifo = 1, }, { .name = "right", .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = filter_frame_right, - .needs_fifo = 1, }, { NULL } }; @@ -404,7 +465,6 @@ .name = "packed", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_output, - .request_frame = request_frame, }, { NULL } }; @@ -417,5 +477,6 @@ .query_formats = query_formats, .inputs = framepack_inputs, .outputs = framepack_outputs, + .activate = activate, .uninit = framepack_uninit, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_framerate.c ffmpeg-4.4/libavfilter/vf_framerate.c --- ffmpeg-4.2.2/libavfilter/vf_framerate.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_framerate.c 2021-02-20 20:27:47.000000000 +0000 @@ -51,7 +51,7 @@ {"interp_start", "point to start linear interpolation", OFFSET(interp_start), AV_OPT_TYPE_INT, {.i64=15}, 0, 255, V|F }, {"interp_end", "point to end linear interpolation", OFFSET(interp_end), AV_OPT_TYPE_INT, {.i64=240}, 0, 255, V|F }, - {"scene", "scene change level", OFFSET(scene_score), AV_OPT_TYPE_DOUBLE, {.dbl=8.2}, 0, INT_MAX, V|F }, + {"scene", "scene change level", OFFSET(scene_score), AV_OPT_TYPE_DOUBLE, {.dbl=8.2}, 0, 100., V|F }, {"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, INT_MAX, V|F, "flags" }, {"scene_change_detect", "enable scene change detection", 0, AV_OPT_TYPE_CONST, {.i64=FRAMERATE_FLAG_SCD}, INT_MIN, INT_MAX, V|F, "flags" }, @@ -95,29 +95,22 @@ { FrameRateContext *s = ctx->priv; ThreadData *td = arg; + AVFrame *work = s->work; + AVFrame *src1 = td->copy_src1; + AVFrame *src2 = td->copy_src2; uint16_t src1_factor = td->src1_factor; uint16_t src2_factor = td->src2_factor; int plane; - for (plane = 0; plane < 4 && td->copy_src1->data[plane] && td->copy_src2->data[plane]; plane++) { - int cpy_line_width = s->line_size[plane]; - uint8_t *cpy_src1_data = td->copy_src1->data[plane]; - int cpy_src1_line_size = td->copy_src1->linesize[plane]; - uint8_t *cpy_src2_data = td->copy_src2->data[plane]; - int cpy_src2_line_size = td->copy_src2->linesize[plane]; - int cpy_src_h = (plane > 0 && plane < 3) ? (td->copy_src1->height >> s->vsub) : (td->copy_src1->height); - uint8_t *cpy_dst_data = s->work->data[plane]; - int cpy_dst_line_size = s->work->linesize[plane]; - const int start = (cpy_src_h * job ) / nb_jobs; - const int end = (cpy_src_h * (job+1)) / nb_jobs; - cpy_src1_data += start * cpy_src1_line_size; - cpy_src2_data += start * cpy_src2_line_size; - cpy_dst_data += start * cpy_dst_line_size; - - s->blend(cpy_src1_data, cpy_src1_line_size, - cpy_src2_data, cpy_src2_line_size, - cpy_dst_data, cpy_dst_line_size, - cpy_line_width, end - start, + for (plane = 0; plane < 4 && src1->data[plane] && src2->data[plane]; plane++) { + const int start = (s->height[plane] * job ) / nb_jobs; + const int end = (s->height[plane] * (job+1)) / nb_jobs; + uint8_t *src1_data = src1->data[plane] + start * src1->linesize[plane]; + uint8_t *src2_data = src2->data[plane] + start * src2->linesize[plane]; + uint8_t *dst_data = work->data[plane] + start * work->linesize[plane]; + + s->blend(src1_data, src1->linesize[plane], src2_data, src2->linesize[plane], + dst_data, work->linesize[plane], s->line_size[plane], end - start, src1_factor, src2_factor, s->blend_factor_max >> 1); } @@ -177,7 +170,9 @@ return 0; if (!s->f0) { - s->work = av_frame_clone(s->f1); + av_assert1(s->flush); + s->work = s->f1; + s->f1 = NULL; } else { if (work_pts >= s->pts1 + s->delta && s->flush) return 0; @@ -242,44 +237,38 @@ return ff_set_common_formats(ctx, fmts_list); } -static void blend_frames_c(BLEND_FUNC_PARAMS) -{ - int line, pixel; - for (line = 0; line < height; line++) { - for (pixel = 0; pixel < width; pixel++) - dst[pixel] = ((src1[pixel] * factor1) + (src2[pixel] * factor2) + half) >> BLEND_FACTOR_DEPTH8; - src1 += src1_linesize; - src2 += src2_linesize; - dst += dst_linesize; - } -} - -static void blend_frames16_c(BLEND_FUNC_PARAMS) -{ - int line, pixel; - uint16_t *dstw = (uint16_t *)dst; - uint16_t *src1w = (uint16_t *)src1; - uint16_t *src2w = (uint16_t *)src2; - width /= 2; - src1_linesize /= 2; - src2_linesize /= 2; - dst_linesize /= 2; - for (line = 0; line < height; line++) { - for (pixel = 0; pixel < width; pixel++) - dstw[pixel] = ((src1w[pixel] * factor1) + (src2w[pixel] * factor2) + half) >> BLEND_FACTOR_DEPTH16; - src1w += src1_linesize; - src2w += src2_linesize; - dstw += dst_linesize; - } +#define BLEND_FRAME_FUNC(nbits) \ +static void blend_frames##nbits##_c(BLEND_FUNC_PARAMS) \ +{ \ + int line, pixel; \ + uint##nbits##_t *dstw = (uint##nbits##_t *)dst; \ + uint##nbits##_t *src1w = (uint##nbits##_t *)src1; \ + uint##nbits##_t *src2w = (uint##nbits##_t *)src2; \ + int bytes = nbits / 8; \ + width /= bytes; \ + src1_linesize /= bytes; \ + src2_linesize /= bytes; \ + dst_linesize /= bytes; \ + for (line = 0; line < height; line++) { \ + for (pixel = 0; pixel < width; pixel++) \ + dstw[pixel] = ((src1w[pixel] * factor1) + \ + (src2w[pixel] * factor2) + half) \ + >> BLEND_FACTOR_DEPTH(nbits); \ + src1w += src1_linesize; \ + src2w += src2_linesize; \ + dstw += dst_linesize; \ + } \ } +BLEND_FRAME_FUNC(8) +BLEND_FRAME_FUNC(16) void ff_framerate_init(FrameRateContext *s) { if (s->bitdepth == 8) { - s->blend_factor_max = 1 << BLEND_FACTOR_DEPTH8; - s->blend = blend_frames_c; + s->blend_factor_max = 1 << BLEND_FACTOR_DEPTH(8); + s->blend = blend_frames8_c; } else { - s->blend_factor_max = 1 << BLEND_FACTOR_DEPTH16; + s->blend_factor_max = 1 << BLEND_FACTOR_DEPTH(16); s->blend = blend_frames16_c; } if (ARCH_X86) @@ -293,13 +282,13 @@ const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format); int plane; + s->vsub = pix_desc->log2_chroma_h; for (plane = 0; plane < 4; plane++) { - s->line_size[plane] = av_image_get_linesize(inlink->format, inlink->w, - plane); + s->line_size[plane] = av_image_get_linesize(inlink->format, inlink->w, plane); + s->height[plane] = inlink->h >> ((plane == 1 || plane == 2) ? s->vsub : 0); } s->bitdepth = pix_desc->comp[0].depth; - s->vsub = pix_desc->log2_chroma_h; s->sad = ff_scene_sad_get_fn(s->bitdepth == 8 ? 8 : 16); if (!s->sad) diff -Nru ffmpeg-4.2.2/libavfilter/vf_freezeframes.c ffmpeg-4.4/libavfilter/vf_freezeframes.c --- ffmpeg-4.2.2/libavfilter/vf_freezeframes.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_freezeframes.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2019 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/opt.h" + +#include "avfilter.h" +#include "filters.h" +#include "internal.h" +#include "video.h" + +typedef struct FreezeFramesContext { + const AVClass *class; + int64_t first, last, replace; + + AVFrame *replace_frame; +} FreezeFramesContext; + +#define OFFSET(x) offsetof(FreezeFramesContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) + +static const AVOption freezeframes_options[] = { + { "first", "set first frame to freeze", OFFSET(first), AV_OPT_TYPE_INT64, {.i64=0}, 0, INT64_MAX, FLAGS }, + { "last", "set last frame to freeze", OFFSET(last), AV_OPT_TYPE_INT64, {.i64=0}, 0, INT64_MAX, FLAGS }, + { "replace", "set frame to replace", OFFSET(replace), AV_OPT_TYPE_INT64, {.i64=0}, 0, INT64_MAX, FLAGS }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(freezeframes); + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVFilterLink *sourcelink = ctx->inputs[0]; + AVFilterLink *replacelink = ctx->inputs[1]; + + if (sourcelink->w != replacelink->w || sourcelink->h != replacelink->h) { + av_log(ctx, AV_LOG_ERROR, + "Input frame sizes do not match (%dx%d vs %dx%d).\n", + sourcelink->w, sourcelink->h, + replacelink->w, replacelink->h); + return AVERROR(EINVAL); + } + + outlink->w = sourcelink->w; + outlink->h = sourcelink->h; + outlink->time_base = sourcelink->time_base; + outlink->sample_aspect_ratio = sourcelink->sample_aspect_ratio; + outlink->frame_rate = sourcelink->frame_rate; + + return 0; +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *outlink = ctx->outputs[0]; + FreezeFramesContext *s = ctx->priv; + AVFrame *frame = NULL; + int drop = ctx->inputs[0]->frame_count_out >= s->first && + ctx->inputs[0]->frame_count_out <= s->last; + int replace = ctx->inputs[1]->frame_count_out == s->replace; + int ret; + + FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); + + if (drop && s->replace_frame) { + ret = ff_inlink_consume_frame(ctx->inputs[0], &frame); + if (ret < 0) + return ret; + + if (frame) { + int64_t dropped_pts = frame->pts; + + av_frame_free(&frame); + frame = av_frame_clone(s->replace_frame); + if (!frame) + return AVERROR(ENOMEM); + frame->pts = dropped_pts; + return ff_filter_frame(outlink, frame); + } + } else if (!drop) { + ret = ff_inlink_consume_frame(ctx->inputs[0], &frame); + if (ret < 0) + return ret; + + if (frame) + return ff_filter_frame(outlink, frame); + } + + ret = ff_inlink_consume_frame(ctx->inputs[1], &frame); + if (ret < 0) + return ret; + if (replace && frame) { + s->replace_frame = frame; + } else if (frame) { + av_frame_free(&frame); + } + + FF_FILTER_FORWARD_STATUS(ctx->inputs[0], outlink); + FF_FILTER_FORWARD_STATUS(ctx->inputs[1], outlink); + + if (!drop || (drop && s->replace_frame)) + FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[0]); + if (!s->replace_frame) + FF_FILTER_FORWARD_WANTED(outlink, ctx->inputs[1]); + + return FFERROR_NOT_READY; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + FreezeFramesContext *s = ctx->priv; + + av_frame_free(&s->replace_frame); +} + +static const AVFilterPad freezeframes_inputs[] = { + { + .name = "source", + .type = AVMEDIA_TYPE_VIDEO, + }, + { + .name = "replace", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL }, +}; + +static const AVFilterPad freezeframes_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL }, +}; + +AVFilter ff_vf_freezeframes = { + .name = "freezeframes", + .description = NULL_IF_CONFIG_SMALL("Freeze video frames."), + .priv_size = sizeof(FreezeFramesContext), + .priv_class = &freezeframes_class, + .inputs = freezeframes_inputs, + .outputs = freezeframes_outputs, + .activate = activate, + .uninit = uninit, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_frei0r.c ffmpeg-4.4/libavfilter/vf_frei0r.c --- ffmpeg-4.2.2/libavfilter/vf_frei0r.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_frei0r.c 2021-04-08 21:28:40.000000000 +0000 @@ -338,7 +338,7 @@ return ret; } else { /* F0R_COLOR_MODEL_PACKED32 */ static const enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_BGRA, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_ARGB, AV_PIX_FMT_NONE + AV_PIX_FMT_BGRA, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_NONE }; formats = ff_make_format_list(pix_fmts); } @@ -371,11 +371,25 @@ 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) +{ + Frei0rContext *s = ctx->priv; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return set_params(ctx, s->params); +} + #define OFFSET(x) offsetof(Frei0rContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +#define TFLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption frei0r_options[] = { { "filter_name", NULL, OFFSET(dl_name), AV_OPT_TYPE_STRING, .flags = FLAGS }, - { "filter_params", NULL, OFFSET(params), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { "filter_params", NULL, OFFSET(params), AV_OPT_TYPE_STRING, .flags = TFLAGS }, { NULL } }; @@ -409,6 +423,8 @@ .priv_class = &frei0r_class, .inputs = avfilter_vf_frei0r_inputs, .outputs = avfilter_vf_frei0r_outputs, + .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; static av_cold int source_init(AVFilterContext *ctx) diff -Nru ffmpeg-4.2.2/libavfilter/vf_fspp.c ffmpeg-4.4/libavfilter/vf_fspp.c --- ffmpeg-4.2.2/libavfilter/vf_fspp.c 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_fspp.c 2021-04-08 21:28:40.000000000 +0000 @@ -37,9 +37,11 @@ #include "libavutil/avassert.h" #include "libavutil/imgutils.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "internal.h" +#include "qp_table.h" #include "vf_fspp.h" #define OFFSET(x) offsetof(FSPPContext, x) @@ -525,13 +527,6 @@ if (!fspp->temp || !fspp->src) return AVERROR(ENOMEM); - if (!fspp->use_bframe_qp && !fspp->qp) { - fspp->non_b_qp_alloc_size = AV_CEIL_RSHIFT(inlink->w, 4) * AV_CEIL_RSHIFT(inlink->h, 4); - fspp->non_b_qp_table = av_calloc(fspp->non_b_qp_alloc_size, sizeof(*fspp->non_b_qp_table)); - if (!fspp->non_b_qp_table) - return AVERROR(ENOMEM); - } - fspp->store_slice = store_slice_c; fspp->store_slice2 = store_slice2_c; fspp->mul_thrmat = mul_thrmat_c; @@ -553,8 +548,9 @@ AVFrame *out = in; int qp_stride = 0; - uint8_t *qp_table = NULL; + int8_t *qp_table = NULL; int i, bias; + int ret = 0; int custom_threshold_m[64]; bias = (1 << 4) + fspp->strength; @@ -581,38 +577,25 @@ * the quantizers from the B-frames (B-frames often have a higher QP), we * need to save the qp table from the last non B-frame; this is what the * following code block does */ - if (!fspp->qp) { - qp_table = av_frame_get_qp_table(in, &qp_stride, &fspp->qscale_type); - - if (qp_table && !fspp->use_bframe_qp && in->pict_type != AV_PICTURE_TYPE_B) { - int w, h; - - /* if the qp stride is not set, it means the QP are only defined on - * a line basis */ - if (!qp_stride) { - w = AV_CEIL_RSHIFT(inlink->w, 4); - h = 1; - } else { - w = qp_stride; - h = AV_CEIL_RSHIFT(inlink->h, 4); - } - if (w * h > fspp->non_b_qp_alloc_size) { - int ret = av_reallocp_array(&fspp->non_b_qp_table, w, h); - if (ret < 0) { - fspp->non_b_qp_alloc_size = 0; - return ret; - } - fspp->non_b_qp_alloc_size = w * h; - } + if (!fspp->qp && (fspp->use_bframe_qp || in->pict_type != AV_PICTURE_TYPE_B)) { + ret = ff_qp_table_extract(in, &qp_table, &qp_stride, NULL, &fspp->qscale_type); + if (ret < 0) { + av_frame_free(&in); + return ret; + } - av_assert0(w * h <= fspp->non_b_qp_alloc_size); - memcpy(fspp->non_b_qp_table, qp_table, w * h); + if (!fspp->use_bframe_qp && in->pict_type != AV_PICTURE_TYPE_B) { + av_freep(&fspp->non_b_qp_table); + fspp->non_b_qp_table = qp_table; + fspp->non_b_qp_stride = qp_stride; } } if (fspp->log2_count && !ctx->is_disabled) { - if (!fspp->use_bframe_qp && fspp->non_b_qp_table) + if (!fspp->use_bframe_qp && fspp->non_b_qp_table) { qp_table = fspp->non_b_qp_table; + qp_stride = fspp->non_b_qp_stride; + } if (qp_table || fspp->qp) { const int cw = AV_CEIL_RSHIFT(inlink->w, fspp->hsub); @@ -627,7 +610,8 @@ out = ff_get_video_buffer(outlink, aligned_w, aligned_h); if (!out) { av_frame_free(&in); - return AVERROR(ENOMEM); + ret = AVERROR(ENOMEM); + goto finish; } av_frame_copy_props(out, in); out->width = in->width; @@ -651,7 +635,11 @@ inlink->w, inlink->h); av_frame_free(&in); } - return ff_filter_frame(outlink, out); + ret = ff_filter_frame(outlink, out); +finish: + if (qp_table != fspp->non_b_qp_table) + av_freep(&qp_table); + return ret; } static av_cold void uninit(AVFilterContext *ctx) diff -Nru ffmpeg-4.2.2/libavfilter/vf_fspp.h ffmpeg-4.4/libavfilter/vf_fspp.h --- ffmpeg-4.2.2/libavfilter/vf_fspp.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_fspp.h 2021-04-08 21:28:40.000000000 +0000 @@ -65,8 +65,8 @@ int prev_q; uint8_t *src; int16_t *temp; - uint8_t *non_b_qp_table; - int non_b_qp_alloc_size; + int8_t *non_b_qp_table; + int non_b_qp_stride; int use_bframe_qp; void (*store_slice)(uint8_t *dst, int16_t *src, diff -Nru ffmpeg-4.2.2/libavfilter/vf_gblur.c ffmpeg-4.4/libavfilter/vf_gblur.c --- ffmpeg-4.2.2/libavfilter/vf_gblur.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_gblur.c 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include + #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -35,7 +37,7 @@ #include "video.h" #define OFFSET(x) offsetof(GBlurContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption gblur_options[] = { { "sigma", "set sigma", OFFSET(sigma), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0.0, 1024, FLAGS }, @@ -52,6 +54,15 @@ int width; } ThreadData; +static void postscale_c(float *buffer, int length, + float postscale, float min, float max) +{ + for (int i = 0; i < length; i++) { + buffer[i] *= postscale; + buffer[i] = av_clipf(buffer[i], min, max); + } +} + static void horiz_slice_c(float *buffer, int width, int height, int steps, float nu, float bscale) { @@ -152,22 +163,22 @@ return 0; } - static int filter_postscale(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { GBlurContext *s = ctx->priv; ThreadData *td = arg; + const float max = s->flt ? FLT_MAX : (1 << s->depth) - 1; + const float min = s->flt ? -FLT_MAX : 0.f; const int height = td->height; const int width = td->width; - const int64_t numpixels = width * (int64_t)height; - const unsigned slice_start = (numpixels * jobnr ) / nb_jobs; - const unsigned slice_end = (numpixels * (jobnr+1)) / nb_jobs; + const int awidth = FFALIGN(width, 64); + const int slice_start = (height * jobnr ) / nb_jobs; + const int slice_end = (height * (jobnr+1)) / nb_jobs; const float postscale = s->postscale * s->postscaleV; - float *buffer = s->buffer; - unsigned i; + const int slice_size = slice_end - slice_start; - for (i = slice_start; i < slice_end; i++) - buffer[i] *= postscale; + s->postscale_slice(s->buffer + slice_start * awidth, + slice_size * awidth, postscale, min, max); return 0; } @@ -205,11 +216,14 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, + AV_PIX_FMT_GRAYF32, AV_PIX_FMT_NONE }; @@ -219,7 +233,8 @@ void ff_gblur_init(GBlurContext *s) { s->horiz_slice = horiz_slice_c; - if (ARCH_X86_64) + s->postscale_slice = postscale_c; + if (ARCH_X86) ff_gblur_init_x86(s); } @@ -229,6 +244,7 @@ GBlurContext *s = inlink->dst->priv; s->depth = desc->comp[0].depth; + s->flt = !!(desc->flags & AV_PIX_FMT_FLAG_FLOAT); s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); s->planewidth[0] = s->planewidth[3] = inlink->w; s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); @@ -236,7 +252,7 @@ s->nb_planes = av_pix_fmt_count_planes(inlink->format); - s->buffer = av_malloc_array(inlink->w, inlink->h * sizeof(*s->buffer)); + s->buffer = av_malloc_array(FFALIGN(inlink->w, 64), FFALIGN(inlink->h, 64) * sizeof(*s->buffer)); if (!s->buffer) return AVERROR(ENOMEM); @@ -299,7 +315,11 @@ continue; } - if (s->depth == 8) { + if (s->flt) { + av_image_copy_plane((uint8_t *)bptr, width * sizeof(float), + in->data[plane], in->linesize[plane], + width * sizeof(float), height); + } else if (s->depth == 8) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { bptr[x] = src[x]; @@ -320,7 +340,11 @@ gaussianiir2d(ctx, plane); bptr = s->buffer; - if (s->depth == 8) { + if (s->flt) { + av_image_copy_plane(out->data[plane], out->linesize[plane], + (uint8_t *)bptr, width * sizeof(float), + width * sizeof(float), height); + } else if (s->depth == 8) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { dst[x] = bptr[x]; @@ -379,4 +403,5 @@ .inputs = gblur_inputs, .outputs = gblur_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_geq.c ffmpeg-4.4/libavfilter/vf_geq.c --- ffmpeg-4.2.2/libavfilter/vf_geq.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_geq.c 2021-04-08 21:28:40.000000000 +0000 @@ -4,19 +4,19 @@ * * 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 free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that 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. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser 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. + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** @@ -33,12 +33,21 @@ #include "libavutil/pixdesc.h" #include "internal.h" +#define MAX_NB_THREADS 32 +#define NB_PLANES 4 + +enum InterpolationMethods { + INTERP_NEAREST, + INTERP_BILINEAR, + NB_INTERP +}; + static const char *const var_names[] = { "X", "Y", "W", "H", "N", "SW", "SH", "T", NULL }; enum { VAR_X, VAR_Y, VAR_W, VAR_H, VAR_N, VAR_SW, VAR_SH, VAR_T, VAR_VARS_NB }; typedef struct GEQContext { const AVClass *class; - AVExpr *e[4]; ///< expressions for each plane + AVExpr *e[NB_PLANES][MAX_NB_THREADS]; ///< expressions for each plane and thread char *expr_str[4+3]; ///< expression strings for each plane AVFrame *picref; ///< current input buffer uint8_t *dst; ///< reference pointer to the 8bits output @@ -46,8 +55,12 @@ double values[VAR_VARS_NB]; ///< expression values int hsub, vsub; ///< chroma subsampling int planes; ///< number of planes + int interpolation; int is_rgb; int bps; + + double *pixel_sums[NB_PLANES]; + int needs_sum[NB_PLANES]; } GEQContext; enum { Y = 0, U, V, A, G, B, R }; @@ -56,20 +69,26 @@ #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption geq_options[] = { - { "lum_expr", "set luminance expression", OFFSET(expr_str[Y]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "lum", "set luminance expression", OFFSET(expr_str[Y]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "cb_expr", "set chroma blue expression", OFFSET(expr_str[U]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "cb", "set chroma blue expression", OFFSET(expr_str[U]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "cr_expr", "set chroma red expression", OFFSET(expr_str[V]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "cr", "set chroma red expression", OFFSET(expr_str[V]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "alpha_expr", "set alpha expression", OFFSET(expr_str[A]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "a", "set alpha expression", OFFSET(expr_str[A]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "red_expr", "set red expression", OFFSET(expr_str[R]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "r", "set red expression", OFFSET(expr_str[R]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "green_expr", "set green expression", OFFSET(expr_str[G]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "g", "set green expression", OFFSET(expr_str[G]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "blue_expr", "set blue expression", OFFSET(expr_str[B]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "b", "set blue expression", OFFSET(expr_str[B]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "lum_expr", "set luminance expression", OFFSET(expr_str[Y]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "lum", "set luminance expression", OFFSET(expr_str[Y]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "cb_expr", "set chroma blue expression", OFFSET(expr_str[U]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "cb", "set chroma blue expression", OFFSET(expr_str[U]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "cr_expr", "set chroma red expression", OFFSET(expr_str[V]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "cr", "set chroma red expression", OFFSET(expr_str[V]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "alpha_expr", "set alpha expression", OFFSET(expr_str[A]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "a", "set alpha expression", OFFSET(expr_str[A]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "red_expr", "set red expression", OFFSET(expr_str[R]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "r", "set red expression", OFFSET(expr_str[R]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "green_expr", "set green expression", OFFSET(expr_str[G]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "g", "set green expression", OFFSET(expr_str[G]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "blue_expr", "set blue expression", OFFSET(expr_str[B]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "b", "set blue expression", OFFSET(expr_str[B]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "interpolation","set interpolation method", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERP_BILINEAR}, 0, NB_INTERP-1, FLAGS, "interp" }, + { "i", "set interpolation method", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERP_BILINEAR}, 0, NB_INTERP-1, FLAGS, "interp" }, + { "nearest", "nearest interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERP_NEAREST}, 0, 0, FLAGS, "interp" }, + { "n", "nearest interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERP_NEAREST}, 0, 0, FLAGS, "interp" }, + { "bilinear", "bilinear interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERP_BILINEAR}, 0, 0, FLAGS, "interp" }, + { "b", "bilinear interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERP_BILINEAR}, 0, 0, FLAGS, "interp" }, {NULL}, }; @@ -88,22 +107,106 @@ if (!src) return 0; - xi = x = av_clipd(x, 0, w - 2); - yi = y = av_clipd(y, 0, h - 2); + if (geq->interpolation == INTERP_BILINEAR) { + xi = x = av_clipd(x, 0, w - 2); + yi = y = av_clipd(y, 0, h - 2); + + x -= xi; + y -= yi; + + if (geq->bps > 8) { + const uint16_t *src16 = (const uint16_t*)src; + linesize /= 2; + + return (1-y)*((1-x)*src16[xi + yi * linesize] + x*src16[xi + 1 + yi * linesize]) + + y *((1-x)*src16[xi + (yi+1) * linesize] + x*src16[xi + 1 + (yi+1) * linesize]); + } else { + return (1-y)*((1-x)*src[xi + yi * linesize] + x*src[xi + 1 + yi * linesize]) + + y *((1-x)*src[xi + (yi+1) * linesize] + x*src[xi + 1 + (yi+1) * linesize]); + } + } else { + xi = av_clipd(x, 0, w - 1); + yi = av_clipd(y, 0, h - 1); - x -= xi; - y -= yi; + if (geq->bps > 8) { + const uint16_t *src16 = (const uint16_t*)src; + linesize /= 2; + + return src16[xi + yi * linesize]; + } else { + return src[xi + yi * linesize]; + } + } +} + +static int calculate_sums(GEQContext *geq, int plane, int w, int h) +{ + int xi, yi; + AVFrame *picref = geq->picref; + const uint8_t *src = picref->data[plane]; + int linesize = picref->linesize[plane]; - if (geq->bps > 8) { - const uint16_t *src16 = (const uint16_t*)src; + if (!geq->pixel_sums[plane]) + geq->pixel_sums[plane] = av_malloc_array(w, h * sizeof (*geq->pixel_sums[plane])); + if (!geq->pixel_sums[plane]) + return AVERROR(ENOMEM); + if (geq->bps > 8) linesize /= 2; + for (yi = 0; yi < h; yi ++) { + if (geq->bps > 8) { + const uint16_t *src16 = (const uint16_t*)src; + double linesum = 0; + + for (xi = 0; xi < w; xi ++) { + linesum += src16[xi + yi * linesize]; + geq->pixel_sums[plane][xi + yi * w] = linesum; + } + } else { + double linesum = 0; - return (1-y)*((1-x)*src16[xi + yi * linesize] + x*src16[xi + 1 + yi * linesize]) - + y *((1-x)*src16[xi + (yi+1) * linesize] + x*src16[xi + 1 + (yi+1) * linesize]); - } else { - return (1-y)*((1-x)*src[xi + yi * linesize] + x*src[xi + 1 + yi * linesize]) - + y *((1-x)*src[xi + (yi+1) * linesize] + x*src[xi + 1 + (yi+1) * linesize]); + for (xi = 0; xi < w; xi ++) { + linesum += src[xi + yi * linesize]; + geq->pixel_sums[plane][xi + yi * w] = linesum; + } + } + if (yi) + for (xi = 0; xi < w; xi ++) { + geq->pixel_sums[plane][xi + yi * w] += geq->pixel_sums[plane][xi + yi * w - w]; + } } + return 0; +} + +static inline double getpix_integrate_internal(GEQContext *geq, int x, int y, int plane, int w, int h) +{ + if (x > w - 1) { + double boundary = getpix_integrate_internal(geq, w - 1, y, plane, w, h); + return 2*boundary - getpix_integrate_internal(geq, 2*(w - 1) - x, y, plane, w, h); + } else if (y > h - 1) { + double boundary = getpix_integrate_internal(geq, x, h - 1, plane, w, h); + return 2*boundary - getpix_integrate_internal(geq, x, 2*(h - 1) - y, plane, w, h); + } else if (x < 0) { + if (x == -1) return 0; + return - getpix_integrate_internal(geq, -x-2, y, plane, w, h); + } else if (y < 0) { + if (y == -1) return 0; + return - getpix_integrate_internal(geq, x, -y-2, plane, w, h); + } + + return geq->pixel_sums[plane][x + y * w]; +} + +static inline double getpix_integrate(void *priv, double x, double y, int plane) { + GEQContext *geq = priv; + AVFrame *picref = geq->picref; + const uint8_t *src = picref->data[plane]; + const int w = (plane == 1 || plane == 2) ? AV_CEIL_RSHIFT(picref->width, geq->hsub) : picref->width; + const int h = (plane == 1 || plane == 2) ? AV_CEIL_RSHIFT(picref->height, geq->vsub) : picref->height; + + if (!src) + return 0; + + return getpix_integrate_internal(geq, lrint(av_clipd(x, -w, 2*w)), lrint(av_clipd(y, -h, 2*h)), plane, w, h); } //TODO: cubic interpolate @@ -113,6 +216,11 @@ static double cr(void *priv, double x, double y) { return getpix(priv, x, y, 2); } static double alpha(void *priv, double x, double y) { return getpix(priv, x, y, 3); } +static double lumsum(void *priv, double x, double y) { return getpix_integrate(priv, x, y, 0); } +static double cbsum(void *priv, double x, double y) { return getpix_integrate(priv, x, y, 1); } +static double crsub(void *priv, double x, double y) { return getpix_integrate(priv, x, y, 2); } +static double alphasum(void *priv, double x, double y) { return getpix_integrate(priv, x, y, 3); } + static av_cold int geq_init(AVFilterContext *ctx) { GEQContext *geq = ctx->priv; @@ -161,17 +269,35 @@ goto end; } - for (plane = 0; plane < 4; plane++) { - static double (*p[])(void *, double, double) = { lum, cb, cr, alpha }; - static const char *const func2_yuv_names[] = { "lum", "cb", "cr", "alpha", "p", NULL }; - static const char *const func2_rgb_names[] = { "g", "b", "r", "alpha", "p", NULL }; + for (plane = 0; plane < NB_PLANES; plane++) { + static double (*const p[])(void *, double, double) = { + lum , cb , cr , alpha , + lumsum, cbsum, crsub, alphasum, + }; + static const char *const func2_yuv_names[] = { + "lum" , "cb" , "cr" , "alpha" , "p", + "lumsum", "cbsum", "crsum", "alphasum", "psum", + NULL }; + static const char *const func2_rgb_names[] = { + "g" , "b" , "r" , "alpha" , "p", + "gsum", "bsum", "rsum", "alphasum", "psum", + NULL }; const char *const *func2_names = geq->is_rgb ? func2_rgb_names : func2_yuv_names; - double (*func2[])(void *, double, double) = { lum, cb, cr, alpha, p[plane], NULL }; + double (*const func2[])(void *, double, double) = { + lum , cb , cr , alpha , p[plane], + lumsum, cbsum, crsub, alphasum, p[plane + 4], + NULL }; + int counter[10] = {0}; + + for (int i = 0; i < MAX_NB_THREADS; i++) { + ret = av_expr_parse(&geq->e[plane][i], geq->expr_str[plane < 3 && geq->is_rgb ? plane+4 : plane], var_names, + NULL, NULL, func2_names, func2, 0, ctx); + if (ret < 0) + goto end; + } - ret = av_expr_parse(&geq->e[plane], geq->expr_str[plane < 3 && geq->is_rgb ? plane+4 : plane], var_names, - NULL, NULL, func2_names, func2, 0, ctx); - if (ret < 0) - break; + av_expr_count_func(geq->e[plane][0], counter, FF_ARRAY_ELEMS(counter), 2); + geq->needs_sum[plane] = counter[5] + counter[6] + counter[7] + counter[8] + counter[9]; } end: @@ -252,8 +378,6 @@ const int slice_start = (height * jobnr) / nb_jobs; const int slice_end = (height * (jobnr+1)) / nb_jobs; int x, y; - uint8_t *ptr; - uint16_t *ptr16; double values[VAR_VARS_NB]; values[VAR_W] = geq->values[VAR_W]; @@ -264,25 +388,25 @@ values[VAR_T] = geq->values[VAR_T]; if (geq->bps == 8) { + uint8_t *ptr = geq->dst + linesize * slice_start; for (y = slice_start; y < slice_end; y++) { - ptr = geq->dst + linesize * y; values[VAR_Y] = y; for (x = 0; x < width; x++) { values[VAR_X] = x; - ptr[x] = av_expr_eval(geq->e[plane], values, geq); + ptr[x] = av_expr_eval(geq->e[plane][jobnr], values, geq); } ptr += linesize; } - } - else { + } else { + uint16_t *ptr16 = geq->dst16 + (linesize/2) * slice_start; for (y = slice_start; y < slice_end; y++) { - ptr16 = geq->dst16 + (linesize/2) * y; values[VAR_Y] = y; for (x = 0; x < width; x++) { values[VAR_X] = x; - ptr16[x] = av_expr_eval(geq->e[plane], values, geq); + ptr16[x] = av_expr_eval(geq->e[plane][jobnr], values, geq); } + ptr16 += linesize/2; } } @@ -293,7 +417,7 @@ { int plane; AVFilterContext *ctx = inlink->dst; - const int nb_threads = ff_filter_get_nb_threads(ctx); + const int nb_threads = FFMIN(MAX_NB_THREADS, ff_filter_get_nb_threads(ctx)); GEQContext *geq = ctx->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; AVFrame *out; @@ -328,6 +452,9 @@ td.plane = plane; td.linesize = linesize; + if (geq->needs_sum[plane]) + calculate_sums(geq, plane, width, height); + ctx->internal->execute(ctx, slice_geq_filter, &td, NULL, FFMIN(height, nb_threads)); } @@ -340,8 +467,11 @@ int i; GEQContext *geq = ctx->priv; - for (i = 0; i < FF_ARRAY_ELEMS(geq->e); i++) - av_expr_free(geq->e[i]); + for (i = 0; i < NB_PLANES; i++) + for (int j = 0; j < MAX_NB_THREADS; j++) + av_expr_free(geq->e[i][j]); + for (i = 0; i < NB_PLANES; i++) + av_freep(&geq->pixel_sums); } static const AVFilterPad geq_inputs[] = { diff -Nru ffmpeg-4.2.2/libavfilter/vf_gradfun.c ffmpeg-4.4/libavfilter/vf_gradfun.c --- ffmpeg-4.2.2/libavfilter/vf_gradfun.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_gradfun.c 2021-04-08 21:28:40.000000000 +0000 @@ -35,6 +35,7 @@ #include "libavutil/imgutils.h" #include "libavutil/common.h" #include "libavutil/cpu.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avfilter.h" diff -Nru ffmpeg-4.2.2/libavfilter/vf_hflip.c ffmpeg-4.4/libavfilter/vf_hflip.c --- ffmpeg-4.2.2/libavfilter/vf_hflip.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_hflip.c 2021-04-08 21:28:40.000000000 +0000 @@ -138,6 +138,7 @@ s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, hsub); s->planeheight[0] = s->planeheight[3] = inlink->h; s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, vsub); + s->bayer_plus1 = !!(pix_desc->flags & AV_PIX_FMT_FLAG_BAYER) + 1; nb_planes = av_pix_fmt_count_planes(inlink->format); @@ -149,6 +150,7 @@ int i; for (i = 0; i < nb_planes; i++) { + step[i] *= s->bayer_plus1; switch (step[i]) { case 1: s->flip_line[i] = hflip_byte_c; break; case 2: s->flip_line[i] = hflip_short_c; break; @@ -180,7 +182,7 @@ int i, plane, step; for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) { - const int width = s->planewidth[plane]; + const int width = s->planewidth[plane] / s->bayer_plus1; const int height = s->planeheight[plane]; const int start = (height * job ) / nb_jobs; const int end = (height * (job+1)) / nb_jobs; diff -Nru ffmpeg-4.2.2/libavfilter/vf_histogram.c ffmpeg-4.4/libavfilter/vf_histogram.c --- ffmpeg-4.2.2/libavfilter/vf_histogram.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_histogram.c 2021-04-08 21:28:40.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 Paul B Mahol + * Copyright (c) 2012-2019 Paul B Mahol * * This file is part of FFmpeg. * @@ -19,6 +19,7 @@ */ #include "libavutil/avassert.h" +#include "libavutil/colorspace.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" @@ -31,13 +32,20 @@ typedef struct HistogramContext { const AVClass *class; ///< AVClass context for log and options purpose + int thistogram; + int envelope; + int slide; unsigned histogram[256*256]; int histogram_size; + int width; + int x_pos; int mult; int ncomp; int dncomp; uint8_t bg_color[4]; uint8_t fg_color[4]; + uint8_t envelope_rgba[4]; + uint8_t envelope_color[4]; int level_height; int scale_height; int display_mode; @@ -48,25 +56,30 @@ float bgopacity; int planewidth[4]; int planeheight[4]; + int start[4]; + AVFrame *out; } HistogramContext; #define OFFSET(x) offsetof(HistogramContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define COMMON_OPTIONS \ + { "display_mode", "set display mode", OFFSET(display_mode), AV_OPT_TYPE_INT, {.i64=2}, 0, 2, FLAGS, "display_mode"}, \ + { "d", "set display mode", OFFSET(display_mode), AV_OPT_TYPE_INT, {.i64=2}, 0, 2, FLAGS, "display_mode"}, \ + { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "display_mode" }, \ + { "parade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "display_mode" }, \ + { "stack", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "display_mode" }, \ + { "levels_mode", "set levels mode", OFFSET(levels_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "levels_mode"}, \ + { "m", "set levels mode", OFFSET(levels_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "levels_mode"}, \ + { "linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "levels_mode" }, \ + { "logarithmic", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "levels_mode" }, \ + { "components", "set color components to display", OFFSET(components), AV_OPT_TYPE_INT, {.i64=7}, 1, 15, FLAGS}, \ + { "c", "set color components to display", OFFSET(components), AV_OPT_TYPE_INT, {.i64=7}, 1, 15, FLAGS}, + static const AVOption histogram_options[] = { { "level_height", "set level height", OFFSET(level_height), AV_OPT_TYPE_INT, {.i64=200}, 50, 2048, FLAGS}, { "scale_height", "set scale height", OFFSET(scale_height), AV_OPT_TYPE_INT, {.i64=12}, 0, 40, FLAGS}, - { "display_mode", "set display mode", OFFSET(display_mode), AV_OPT_TYPE_INT, {.i64=2}, 0, 2, FLAGS, "display_mode"}, - { "d", "set display mode", OFFSET(display_mode), AV_OPT_TYPE_INT, {.i64=2}, 0, 2, FLAGS, "display_mode"}, - { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "display_mode" }, - { "parade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "display_mode" }, - { "stack", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "display_mode" }, - { "levels_mode", "set levels mode", OFFSET(levels_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "levels_mode"}, - { "m", "set levels mode", OFFSET(levels_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "levels_mode"}, - { "linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "levels_mode" }, - { "logarithmic", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "levels_mode" }, - { "components", "set color components to display", OFFSET(components), AV_OPT_TYPE_INT, {.i64=7}, 1, 15, FLAGS}, - { "c", "set color components to display", OFFSET(components), AV_OPT_TYPE_INT, {.i64=7}, 1, 15, FLAGS}, + COMMON_OPTIONS { "fgopacity", "set foreground opacity", OFFSET(fgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.7}, 0, 1, FLAGS}, { "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}, @@ -87,6 +100,7 @@ AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, @@ -110,7 +124,7 @@ }; static const enum AVPixelFormat levels_out_yuv12_pix_fmts[] = { - AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_NONE }; @@ -142,15 +156,15 @@ int rgb, i, bits; int ret; - if (!ctx->inputs[0]->in_formats || - !ctx->inputs[0]->in_formats->nb_formats) { + if (!ctx->inputs[0]->incfg.formats || + !ctx->inputs[0]->incfg.formats->nb_formats) { return AVERROR(EAGAIN); } - if (!ctx->inputs[0]->out_formats) - if ((ret = ff_formats_ref(ff_make_format_list(levels_in_pix_fmts), &ctx->inputs[0]->out_formats)) < 0) + if (!ctx->inputs[0]->outcfg.formats) + if ((ret = ff_formats_ref(ff_make_format_list(levels_in_pix_fmts), &ctx->inputs[0]->outcfg.formats)) < 0) return ret; - avff = ctx->inputs[0]->in_formats; + avff = ctx->inputs[0]->incfg.formats; desc = av_pix_fmt_desc_get(avff->formats[0]); rgb = desc->flags & AV_PIX_FMT_FLAG_RGB; bits = desc->comp[0].depth; @@ -179,7 +193,7 @@ out_pix_fmts = levels_out_yuv12_pix_fmts; else return AVERROR(EAGAIN); - if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->incfg.formats)) < 0) return ret; return 0; @@ -192,12 +206,12 @@ static int config_input(AVFilterLink *inlink) { - HistogramContext *h = inlink->dst->priv; + HistogramContext *s = inlink->dst->priv; - h->desc = av_pix_fmt_desc_get(inlink->format); - h->ncomp = h->desc->nb_components; - h->histogram_size = 1 << h->desc->comp[0].depth; - h->mult = h->histogram_size / 256; + s->desc = av_pix_fmt_desc_get(inlink->format); + s->ncomp = s->desc->nb_components; + s->histogram_size = 1 << s->desc->comp[0].depth; + s->mult = s->histogram_size / 256; switch (inlink->format) { case AV_PIX_FMT_GBRAP12: @@ -207,21 +221,29 @@ case AV_PIX_FMT_GBRP9: case AV_PIX_FMT_GBRAP: case AV_PIX_FMT_GBRP: - memcpy(h->bg_color, black_gbrp_color, 4); - memcpy(h->fg_color, white_gbrp_color, 4); + memcpy(s->bg_color, black_gbrp_color, 4); + memcpy(s->fg_color, white_gbrp_color, 4); + s->start[0] = s->start[1] = s->start[2] = s->start[3] = 0; + memcpy(s->envelope_color, s->envelope_rgba, 4); break; default: - memcpy(h->bg_color, black_yuva_color, 4); - memcpy(h->fg_color, white_yuva_color, 4); + memcpy(s->bg_color, black_yuva_color, 4); + memcpy(s->fg_color, white_yuva_color, 4); + s->start[0] = s->start[3] = 0; + s->start[1] = s->start[2] = s->histogram_size / 2; + s->envelope_color[0] = RGB_TO_Y_BT709(s->envelope_rgba[0], s->envelope_rgba[1], s->envelope_rgba[2]); + s->envelope_color[1] = RGB_TO_U_BT709(s->envelope_rgba[0], s->envelope_rgba[1], s->envelope_rgba[2], 0); + s->envelope_color[2] = RGB_TO_V_BT709(s->envelope_rgba[0], s->envelope_rgba[1], s->envelope_rgba[2], 0); + s->envelope_color[3] = s->envelope_rgba[3]; } - h->fg_color[3] = h->fgopacity * 255; - h->bg_color[3] = h->bgopacity * 255; + s->fg_color[3] = s->fgopacity * 255; + s->bg_color[3] = s->bgopacity * 255; - h->planeheight[1] = h->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, h->desc->log2_chroma_h); - h->planeheight[0] = h->planeheight[3] = inlink->h; - h->planewidth[1] = h->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, h->desc->log2_chroma_w); - h->planewidth[0] = h->planewidth[3] = inlink->w; + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, s->desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; return 0; } @@ -229,18 +251,29 @@ static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; - HistogramContext *h = ctx->priv; + HistogramContext *s = ctx->priv; int ncomp = 0, i; - for (i = 0; i < h->ncomp; i++) { - if ((1 << i) & h->components) + if (!strcmp(ctx->filter->name, "thistogram")) + s->thistogram = 1; + + for (i = 0; i < s->ncomp; i++) { + if ((1 << i) & s->components) ncomp++; } - outlink->w = h->histogram_size * FFMAX(ncomp * (h->display_mode == 1), 1); - outlink->h = (h->level_height + h->scale_height) * FFMAX(ncomp * (h->display_mode == 2), 1); - h->odesc = av_pix_fmt_desc_get(outlink->format); - h->dncomp = h->odesc->nb_components; + if (s->thistogram) { + if (!s->width) + s->width = ctx->inputs[0]->w; + outlink->w = s->width * FFMAX(ncomp * (s->display_mode == 1), 1); + outlink->h = s->histogram_size * FFMAX(ncomp * (s->display_mode == 2), 1); + } else { + outlink->w = s->histogram_size * FFMAX(ncomp * (s->display_mode == 1), 1); + outlink->h = (s->level_height + s->scale_height) * FFMAX(ncomp * (s->display_mode == 2), 1); + } + + s->odesc = av_pix_fmt_desc_get(outlink->format); + s->dncomp = s->odesc->nb_components; outlink->sample_aspect_ratio = (AVRational){1,1}; return 0; @@ -248,111 +281,204 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) { - HistogramContext *h = inlink->dst->priv; + HistogramContext *s = inlink->dst->priv; AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *out; + AVFrame *out = s->out; int i, j, k, l, m; - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); - } - - out->pts = in->pts; + if (!s->thistogram || !out) { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + s->out = out; - for (k = 0; k < 4 && out->data[k]; k++) { - const int is_chroma = (k == 1 || k == 2); - const int dst_h = AV_CEIL_RSHIFT(outlink->h, (is_chroma ? h->odesc->log2_chroma_h : 0)); - const int dst_w = AV_CEIL_RSHIFT(outlink->w, (is_chroma ? h->odesc->log2_chroma_w : 0)); - - if (h->histogram_size <= 256) { - for (i = 0; i < dst_h ; i++) - memset(out->data[h->odesc->comp[k].plane] + - i * out->linesize[h->odesc->comp[k].plane], - h->bg_color[k], dst_w); - } else { - const int mult = h->mult; + for (k = 0; k < 4 && out->data[k]; k++) { + const int is_chroma = (k == 1 || k == 2); + const int dst_h = AV_CEIL_RSHIFT(outlink->h, (is_chroma ? s->odesc->log2_chroma_h : 0)); + const int dst_w = AV_CEIL_RSHIFT(outlink->w, (is_chroma ? s->odesc->log2_chroma_w : 0)); + + if (s->histogram_size <= 256) { + for (i = 0; i < dst_h ; i++) + memset(out->data[s->odesc->comp[k].plane] + + i * out->linesize[s->odesc->comp[k].plane], + s->bg_color[k], dst_w); + } else { + const int mult = s->mult; - for (i = 0; i < dst_h ; i++) - for (j = 0; j < dst_w; j++) - AV_WN16(out->data[h->odesc->comp[k].plane] + - i * out->linesize[h->odesc->comp[k].plane] + j * 2, - h->bg_color[k] * mult); + for (i = 0; i < dst_h ; i++) + for (j = 0; j < dst_w; j++) + AV_WN16(out->data[s->odesc->comp[k].plane] + + i * out->linesize[s->odesc->comp[k].plane] + j * 2, + s->bg_color[k] * mult); + } } } - for (m = 0, k = 0; k < h->ncomp; k++) { - const int p = h->desc->comp[k].plane; - const int height = h->planeheight[p]; - const int width = h->planewidth[p]; + for (m = 0, k = 0; k < s->ncomp; k++) { + const int p = s->desc->comp[k].plane; + const int max_value = s->histogram_size - 1 - s->start[p]; + const int height = s->planeheight[p]; + const int width = s->planewidth[p]; double max_hval_log; unsigned max_hval = 0; - int start, startx; + int starty, startx; - if (!((1 << k) & h->components)) + if (!((1 << k) & s->components)) continue; - startx = m * h->histogram_size * (h->display_mode == 1); - start = m++ * (h->level_height + h->scale_height) * (h->display_mode == 2); + if (s->thistogram) { + starty = m * s->histogram_size * (s->display_mode == 2); + startx = m++ * s->width * (s->display_mode == 1); + } else { + startx = m * s->histogram_size * (s->display_mode == 1); + starty = m++ * (s->level_height + s->scale_height) * (s->display_mode == 2); + } - if (h->histogram_size <= 256) { + if (s->histogram_size <= 256) { for (i = 0; i < height; i++) { const uint8_t *src = in->data[p] + i * in->linesize[p]; for (j = 0; j < width; j++) - h->histogram[src[j]]++; + s->histogram[src[j]]++; } } else { for (i = 0; i < height; i++) { const uint16_t *src = (const uint16_t *)(in->data[p] + i * in->linesize[p]); for (j = 0; j < width; j++) - h->histogram[src[j]]++; + s->histogram[src[j]]++; } } - for (i = 0; i < h->histogram_size; i++) - max_hval = FFMAX(max_hval, h->histogram[i]); + for (i = 0; i < s->histogram_size; i++) + max_hval = FFMAX(max_hval, s->histogram[i]); max_hval_log = log2(max_hval + 1); - for (i = 0; i < h->histogram_size; i++) { - int col_height; + if (s->thistogram) { + const int bpp = 1 + (s->histogram_size > 256); + int minh = s->histogram_size - 1, maxh = 0; + + if (s->slide == 2) { + s->x_pos = out->width - 1; + for (j = 0; j < outlink->h; j++) { + memmove(out->data[p] + j * out->linesize[p] , + out->data[p] + j * out->linesize[p] + bpp, + (outlink->w - 1) * bpp); + } + } else if (s->slide == 3) { + s->x_pos = 0; + for (j = 0; j < outlink->h; j++) { + memmove(out->data[p] + j * out->linesize[p] + bpp, + out->data[p] + j * out->linesize[p], + (outlink->w - 1) * bpp); + } + } - if (h->levels_mode) - col_height = lrint(h->level_height * (1. - (log2(h->histogram[i] + 1) / max_hval_log))); - else - col_height = h->level_height - (h->histogram[i] * (int64_t)h->level_height + max_hval - 1) / max_hval; - - if (h->histogram_size <= 256) { - for (j = h->level_height - 1; j >= col_height; j--) { - if (h->display_mode) { - for (l = 0; l < h->dncomp; l++) - out->data[l][(j + start) * out->linesize[l] + startx + i] = h->fg_color[l]; - } else { - out->data[p][(j + start) * out->linesize[p] + startx + i] = 255; + for (int i = 0; i < s->histogram_size; i++) { + int idx = s->histogram_size - i - 1; + int value = s->start[p]; + + if (s->envelope && s->histogram[idx]) { + minh = FFMIN(minh, i); + maxh = FFMAX(maxh, i); + } + + if (s->levels_mode) + value += lrint(max_value * (log2(s->histogram[idx] + 1) / max_hval_log)); + else + value += lrint(max_value * s->histogram[idx] / (float)max_hval); + + if (s->histogram_size <= 256) { + s->out->data[p][(i + starty) * s->out->linesize[p] + startx + s->x_pos] = value; + } else { + AV_WN16(s->out->data[p] + (i + starty) * s->out->linesize[p] + startx * 2 + s->x_pos * 2, value); + } + } + + if (s->envelope) { + if (s->histogram_size <= 256) { + s->out->data[0][(minh + starty) * s->out->linesize[p] + startx + s->x_pos] = s->envelope_color[0]; + s->out->data[0][(maxh + starty) * s->out->linesize[p] + startx + s->x_pos] = s->envelope_color[0]; + if (s->dncomp >= 3) { + s->out->data[1][(minh + starty) * s->out->linesize[p] + startx + s->x_pos] = s->envelope_color[1]; + s->out->data[2][(minh + starty) * s->out->linesize[p] + startx + s->x_pos] = s->envelope_color[2]; + s->out->data[1][(maxh + starty) * s->out->linesize[p] + startx + s->x_pos] = s->envelope_color[1]; + s->out->data[2][(maxh + starty) * s->out->linesize[p] + startx + s->x_pos] = s->envelope_color[2]; + } + } else { + const int mult = s->mult; + + AV_WN16(s->out->data[0] + (minh + starty) * s->out->linesize[p] + startx * 2 + s->x_pos * 2, s->envelope_color[0] * mult); + AV_WN16(s->out->data[0] + (maxh + starty) * s->out->linesize[p] + startx * 2 + s->x_pos * 2, s->envelope_color[0] * mult); + if (s->dncomp >= 3) { + AV_WN16(s->out->data[1] + (minh + starty) * s->out->linesize[p] + startx * 2 + s->x_pos * 2, s->envelope_color[1] * mult); + AV_WN16(s->out->data[2] + (minh + starty) * s->out->linesize[p] + startx * 2 + s->x_pos * 2, s->envelope_color[2] * mult); + AV_WN16(s->out->data[1] + (maxh + starty) * s->out->linesize[p] + startx * 2 + s->x_pos * 2, s->envelope_color[1] * mult); + AV_WN16(s->out->data[2] + (maxh + starty) * s->out->linesize[p] + startx * 2 + s->x_pos * 2, s->envelope_color[2] * mult); } } - for (j = h->level_height + h->scale_height - 1; j >= h->level_height; j--) - out->data[p][(j + start) * out->linesize[p] + startx + i] = i; - } else { - const int mult = h->mult; + } + } else { + for (i = 0; i < s->histogram_size; i++) { + int col_height; - for (j = h->level_height - 1; j >= col_height; j--) { - if (h->display_mode) { - for (l = 0; l < h->dncomp; l++) - AV_WN16(out->data[l] + (j + start) * out->linesize[l] + startx * 2 + i * 2, h->fg_color[l] * mult); - } else { - AV_WN16(out->data[p] + (j + start) * out->linesize[p] + startx * 2 + i * 2, 255 * mult); + if (s->levels_mode) + col_height = lrint(s->level_height * (1. - (log2(s->histogram[i] + 1) / max_hval_log))); + else + col_height = s->level_height - (s->histogram[i] * (int64_t)s->level_height + max_hval - 1) / max_hval; + + if (s->histogram_size <= 256) { + for (j = s->level_height - 1; j >= col_height; j--) { + if (s->display_mode) { + for (l = 0; l < s->dncomp; l++) + out->data[l][(j + starty) * out->linesize[l] + startx + i] = s->fg_color[l]; + } else { + out->data[p][(j + starty) * out->linesize[p] + startx + i] = 255; + } + } + for (j = s->level_height + s->scale_height - 1; j >= s->level_height; j--) + out->data[p][(j + starty) * out->linesize[p] + startx + i] = i; + } else { + const int mult = s->mult; + + for (j = s->level_height - 1; j >= col_height; j--) { + if (s->display_mode) { + for (l = 0; l < s->dncomp; l++) + AV_WN16(out->data[l] + (j + starty) * out->linesize[l] + startx * 2 + i * 2, s->fg_color[l] * mult); + } else { + AV_WN16(out->data[p] + (j + starty) * out->linesize[p] + startx * 2 + i * 2, 255 * mult); + } } + for (j = s->level_height + s->scale_height - 1; j >= s->level_height; j--) + AV_WN16(out->data[p] + (j + starty) * out->linesize[p] + startx * 2 + i * 2, i); } - for (j = h->level_height + h->scale_height - 1; j >= h->level_height; j--) - AV_WN16(out->data[p] + (j + start) * out->linesize[p] + startx * 2 + i * 2, i); } } - memset(h->histogram, 0, h->histogram_size * sizeof(unsigned)); + memset(s->histogram, 0, s->histogram_size * sizeof(unsigned)); } + out->pts = in->pts; av_frame_free(&in); + s->x_pos++; + if (s->x_pos >= s->width) { + s->x_pos = 0; + if (s->thistogram && (s->slide == 4 || s->slide == 0)) { + s->out = NULL; + goto end; + } + } else if (s->thistogram && s->slide == 4) { + return 0; + } + + if (s->thistogram) { + AVFrame *clone = av_frame_clone(out); + + if (!clone) + return AVERROR(ENOMEM); + return ff_filter_frame(outlink, clone); + } +end: return ff_filter_frame(outlink, out); } @@ -375,6 +501,8 @@ { NULL } }; +#if CONFIG_HISTOGRAM_FILTER + AVFilter ff_vf_histogram = { .name = "histogram", .description = NULL_IF_CONFIG_SMALL("Compute and draw a histogram."), @@ -384,3 +512,48 @@ .outputs = outputs, .priv_class = &histogram_class, }; + +#endif /* CONFIG_HISTOGRAM_FILTER */ + +#if CONFIG_THISTOGRAM_FILTER + +static av_cold void uninit(AVFilterContext *ctx) +{ + HistogramContext *s = ctx->priv; + + av_frame_free(&s->out); +} + +static const AVOption thistogram_options[] = { + { "width", "set width", OFFSET(width), AV_OPT_TYPE_INT, {.i64=0}, 0, 8192, FLAGS}, + { "w", "set width", OFFSET(width), AV_OPT_TYPE_INT, {.i64=0}, 0, 8192, FLAGS}, + COMMON_OPTIONS + { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.9}, 0, 1, FLAGS}, + { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.9}, 0, 1, FLAGS}, + { "envelope", "display envelope", OFFSET(envelope), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "e", "display envelope", OFFSET(envelope), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "ecolor", "set envelope color", OFFSET(envelope_rgba), AV_OPT_TYPE_COLOR, {.str="gold"}, 0, 0, FLAGS }, + { "ec", "set envelope color", OFFSET(envelope_rgba), AV_OPT_TYPE_COLOR, {.str="gold"}, 0, 0, FLAGS }, + { "slide", "set slide mode", OFFSET(slide), AV_OPT_TYPE_INT, {.i64=1}, 0, 4, FLAGS, "slide" }, + {"frame", "draw new frames", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "slide"}, + {"replace", "replace old columns with new", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "slide"}, + {"scroll", "scroll from right to left", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "slide"}, + {"rscroll", "scroll from left to right", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "slide"}, + {"picture", "display graph in single frame", OFFSET(slide), AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, FLAGS, "slide"}, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(thistogram); + +AVFilter ff_vf_thistogram = { + .name = "thistogram", + .description = NULL_IF_CONFIG_SMALL("Compute and draw a temporal histogram."), + .priv_size = sizeof(HistogramContext), + .query_formats = query_formats, + .inputs = inputs, + .outputs = outputs, + .uninit = uninit, + .priv_class = &thistogram_class, +}; + +#endif /* CONFIG_THISTOGRAM_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/vf_hqdn3d.c ffmpeg-4.4/libavfilter/vf_hqdn3d.c --- ffmpeg-4.2.2/libavfilter/vf_hqdn3d.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_hqdn3d.c 2020-07-11 10:39:30.000000000 +0000 @@ -160,6 +160,8 @@ case 8: ret = denoise_depth(__VA_ARGS__, 8); break; \ case 9: ret = denoise_depth(__VA_ARGS__, 9); break; \ case 10: ret = denoise_depth(__VA_ARGS__, 10); break; \ + case 12: ret = denoise_depth(__VA_ARGS__, 12); break; \ + case 14: ret = denoise_depth(__VA_ARGS__, 14); break; \ case 16: ret = denoise_depth(__VA_ARGS__, 16); break; \ } \ if (ret < 0) { \ @@ -170,13 +172,10 @@ } \ } while (0) -static int16_t *precalc_coefs(double dist25, int depth) +static void precalc_coefs(double dist25, int depth, int16_t *ct) { int i; double gamma, simil, C; - int16_t *ct = av_malloc((512<coefs[1]); av_freep(&s->coefs[2]); av_freep(&s->coefs[3]); - av_freep(&s->line); + av_freep(&s->line[0]); + av_freep(&s->line[1]); + av_freep(&s->line[2]); av_freep(&s->frame_prev[0]); av_freep(&s->frame_prev[1]); av_freep(&s->frame_prev[2]); @@ -232,25 +232,16 @@ static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_YUV422P, - AV_PIX_FMT_YUV444P, - AV_PIX_FMT_YUV410P, - AV_PIX_FMT_YUV411P, - AV_PIX_FMT_YUV440P, - AV_PIX_FMT_YUVJ420P, - AV_PIX_FMT_YUVJ422P, - AV_PIX_FMT_YUVJ444P, - AV_PIX_FMT_YUVJ440P, - AV_PIX_FMT_YUV420P9, - AV_PIX_FMT_YUV422P9, - AV_PIX_FMT_YUV444P9, - AV_PIX_FMT_YUV420P10, - AV_PIX_FMT_YUV422P10, - AV_PIX_FMT_YUV444P10, - AV_PIX_FMT_YUV420P16, - AV_PIX_FMT_YUV422P16, - AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_NONE }; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); @@ -259,42 +250,79 @@ return ff_set_common_formats(ctx, fmts_list); } +static void calc_coefs(AVFilterContext *ctx) +{ + HQDN3DContext *s = ctx->priv; + + for (int i = 0; i < 4; i++) + precalc_coefs(s->strength[i], s->depth, s->coefs[i]); +} + static int config_input(AVFilterLink *inlink) { + AVFilterContext *ctx = inlink->dst; HQDN3DContext *s = inlink->dst->priv; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - int i; + int i, depth; uninit(inlink->dst); s->hsub = desc->log2_chroma_w; s->vsub = desc->log2_chroma_h; - s->depth = desc->comp[0].depth; + s->depth = depth = desc->comp[0].depth; - s->line = av_malloc_array(inlink->w, sizeof(*s->line)); - if (!s->line) - return AVERROR(ENOMEM); + for (i = 0; i < 3; i++) { + s->line[i] = av_malloc_array(inlink->w, sizeof(*s->line[i])); + if (!s->line[i]) + return AVERROR(ENOMEM); + } for (i = 0; i < 4; i++) { - s->coefs[i] = precalc_coefs(s->strength[i], s->depth); + s->coefs[i] = av_malloc((512<coefs[i]) return AVERROR(ENOMEM); } + calc_coefs(ctx); + if (ARCH_X86) ff_hqdn3d_init_x86(s); return 0; } +typedef struct ThreadData { + AVFrame *in, *out; + int direct; +} ThreadData; + +static int do_denoise(AVFilterContext *ctx, void *data, int job_nr, int n_jobs) +{ + HQDN3DContext *s = ctx->priv; + const ThreadData *td = data; + AVFrame *out = td->out; + AVFrame *in = td->in; + int direct = td->direct; + + denoise(s, in->data[job_nr], out->data[job_nr], + s->line[job_nr], &s->frame_prev[job_nr], + AV_CEIL_RSHIFT(in->width, (!!job_nr * s->hsub)), + AV_CEIL_RSHIFT(in->height, (!!job_nr * s->vsub)), + in->linesize[job_nr], out->linesize[job_nr], + s->coefs[job_nr ? CHROMA_SPATIAL : LUMA_SPATIAL], + s->coefs[job_nr ? CHROMA_TMP : LUMA_TMP]); + + return 0; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; - HQDN3DContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; - int c, direct = av_frame_is_writable(in) && !ctx->is_disabled; + int direct = av_frame_is_writable(in) && !ctx->is_disabled; + ThreadData td; if (direct) { out = in; @@ -308,15 +336,11 @@ av_frame_copy_props(out, in); } - for (c = 0; c < 3; c++) { - denoise(s, in->data[c], out->data[c], - s->line, &s->frame_prev[c], - AV_CEIL_RSHIFT(in->width, (!!c * s->hsub)), - AV_CEIL_RSHIFT(in->height, (!!c * s->vsub)), - in->linesize[c], out->linesize[c], - s->coefs[c ? CHROMA_SPATIAL : LUMA_SPATIAL], - s->coefs[c ? CHROMA_TMP : LUMA_TMP]); - } + td.in = in; + td.out = out; + td.direct = direct; + /* one thread per plane */ + ctx->internal->execute(ctx, do_denoise, &td, NULL, 3); if (ctx->is_disabled) { av_frame_free(&out); @@ -329,8 +353,22 @@ 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) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + calc_coefs(ctx); + + return 0; +} + #define OFFSET(x) offsetof(HQDN3DContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption hqdn3d_options[] = { { "luma_spatial", "spatial luma strength", OFFSET(strength[LUMA_SPATIAL]), AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0, DBL_MAX, FLAGS }, { "chroma_spatial", "spatial chroma strength", OFFSET(strength[CHROMA_SPATIAL]), AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0, DBL_MAX, FLAGS }, @@ -370,5 +408,6 @@ .query_formats = query_formats, .inputs = avfilter_vf_hqdn3d_inputs, .outputs = avfilter_vf_hqdn3d_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_hqdn3d.h ffmpeg-4.4/libavfilter/vf_hqdn3d.h --- ffmpeg-4.2.2/libavfilter/vf_hqdn3d.h 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_hqdn3d.h 2020-07-11 10:39:30.000000000 +0000 @@ -31,7 +31,7 @@ typedef struct HQDN3DContext { const AVClass *class; int16_t *coefs[4]; - uint16_t *line; + uint16_t *line[3]; uint16_t *frame_prev[3]; double strength[4]; int hsub, vsub; diff -Nru ffmpeg-4.2.2/libavfilter/vf_hqx.c ffmpeg-4.4/libavfilter/vf_hqx.c --- ffmpeg-4.2.2/libavfilter/vf_hqx.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_hqx.c 2020-07-09 09:17:46.000000000 +0000 @@ -523,7 +523,7 @@ int startg = FFMAX3(-bg, -rg, 0); int endg = FFMIN3(255-bg, 255-rg, 255); uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000); - c = bg + (rg<<16) + 0x010101 * startg; + c = bg + rg * (1 << 16) + 0x010101 * startg; for (g = startg; g <= endg; g++) { hqx->rgbtoyuv[c] = ((y++) << 16) + (u << 8) + v; c+= 0x010101; diff -Nru ffmpeg-4.2.2/libavfilter/vf_hue.c ffmpeg-4.4/libavfilter/vf_hue.c --- ffmpeg-4.2.2/libavfilter/vf_hue.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_hue.c 2021-04-08 21:28:40.000000000 +0000 @@ -86,7 +86,7 @@ } HueContext; #define OFFSET(x) offsetof(HueContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption hue_options[] = { { "h", "set the hue angle degrees expression", OFFSET(hue_deg_expr), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, @@ -136,7 +136,7 @@ */ for (i = 0; i < 256; i++) { for (j = 0; j < 256; j++) { - /* Normalize the components from range [16;140] to [-112;112] */ + /* Normalize the components from range [16;240] to [-112;112] */ u = i - 128; v = j - 128; /* @@ -363,9 +363,6 @@ } } -#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) -#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts) * av_q2d(tb)) - static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) { HueContext *hue = inlink->dst->priv; diff -Nru ffmpeg-4.2.2/libavfilter/vf_hwdownload.c ffmpeg-4.4/libavfilter/vf_hwdownload.c --- ffmpeg-4.2.2/libavfilter/vf_hwdownload.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_hwdownload.c 2021-04-08 21:28:40.000000000 +0000 @@ -37,26 +37,13 @@ static int hwdownload_query_formats(AVFilterContext *avctx) { - AVFilterFormats *infmts = NULL; - AVFilterFormats *outfmts = NULL; - const AVPixFmtDescriptor *desc; + AVFilterFormats *fmts; int err; - for (desc = av_pix_fmt_desc_next(NULL); desc; - desc = av_pix_fmt_desc_next(desc)) { - if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) - err = ff_add_format(&infmts, av_pix_fmt_desc_get_id(desc)); - else - err = ff_add_format(&outfmts, av_pix_fmt_desc_get_id(desc)); - if (err) { - ff_formats_unref(&infmts); - ff_formats_unref(&outfmts); - return err; - } - } - - if ((err = ff_formats_ref(infmts, &avctx->inputs[0]->out_formats)) < 0 || - (err = ff_formats_ref(outfmts, &avctx->outputs[0]->in_formats)) < 0) + if ((err = ff_formats_pixdesc_filter(&fmts, AV_PIX_FMT_FLAG_HWACCEL, 0)) || + (err = ff_formats_ref(fmts, &avctx->inputs[0]->outcfg.formats)) || + (err = ff_formats_pixdesc_filter(&fmts, 0, AV_PIX_FMT_FLAG_HWACCEL)) || + (err = ff_formats_ref(fmts, &avctx->outputs[0]->incfg.formats))) return err; return 0; diff -Nru ffmpeg-4.2.2/libavfilter/vf_hwmap.c ffmpeg-4.4/libavfilter/vf_hwmap.c --- ffmpeg-4.2.2/libavfilter/vf_hwmap.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_hwmap.c 2021-04-08 21:28:40.000000000 +0000 @@ -42,9 +42,9 @@ int ret; if ((ret = ff_formats_ref(ff_all_formats(AVMEDIA_TYPE_VIDEO), - &avctx->inputs[0]->out_formats)) < 0 || + &avctx->inputs[0]->outcfg.formats)) < 0 || (ret = ff_formats_ref(ff_all_formats(AVMEDIA_TYPE_VIDEO), - &avctx->outputs[0]->in_formats)) < 0) + &avctx->outputs[0]->incfg.formats)) < 0) return ret; return 0; diff -Nru ffmpeg-4.2.2/libavfilter/vf_hwupload.c ffmpeg-4.4/libavfilter/vf_hwupload.c --- ffmpeg-4.2.2/libavfilter/vf_hwupload.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_hwupload.c 2021-04-08 21:28:40.000000000 +0000 @@ -32,10 +32,11 @@ const AVClass *class; AVBufferRef *hwdevice_ref; - AVHWDeviceContext *hwdevice; AVBufferRef *hwframes_ref; AVHWFramesContext *hwframes; + + char *device_type; } HWUploadContext; static int hwupload_query_formats(AVFilterContext *avctx) @@ -46,17 +47,27 @@ AVFilterFormats *input_formats = NULL; int err, i; - if (!avctx->hw_device_ctx) { + if (ctx->hwdevice_ref) { + /* We already have a specified device. */ + } else if (avctx->hw_device_ctx) { + if (ctx->device_type) { + err = av_hwdevice_ctx_create_derived( + &ctx->hwdevice_ref, + av_hwdevice_find_type_by_name(ctx->device_type), + avctx->hw_device_ctx, 0); + if (err < 0) + return err; + } else { + ctx->hwdevice_ref = av_buffer_ref(avctx->hw_device_ctx); + if (!ctx->hwdevice_ref) + return AVERROR(ENOMEM); + } + } else { av_log(ctx, AV_LOG_ERROR, "A hardware device reference is required " "to upload frames to.\n"); return AVERROR(EINVAL); } - ctx->hwdevice_ref = av_buffer_ref(avctx->hw_device_ctx); - if (!ctx->hwdevice_ref) - return AVERROR(ENOMEM); - ctx->hwdevice = (AVHWDeviceContext*)ctx->hwdevice_ref->data; - constraints = av_hwdevice_get_hwframe_constraints(ctx->hwdevice_ref, NULL); if (!constraints) { err = AVERROR(EINVAL); @@ -79,9 +90,9 @@ } } - if ((err = ff_formats_ref(input_formats, &avctx->inputs[0]->out_formats)) < 0 || + if ((err = ff_formats_ref(input_formats, &avctx->inputs[0]->outcfg.formats)) < 0 || (err = ff_formats_ref(ff_make_format_list(output_pix_fmts), - &avctx->outputs[0]->in_formats)) < 0) + &avctx->outputs[0]->incfg.formats)) < 0) goto fail; av_hwframe_constraints_free(&constraints); @@ -127,7 +138,13 @@ av_get_pix_fmt_name(inlink->format)); ctx->hwframes->format = outlink->format; - ctx->hwframes->sw_format = inlink->format; + if (inlink->hw_frames_ctx) { + AVHWFramesContext *in_hwframe_ctx = + (AVHWFramesContext*)inlink->hw_frames_ctx->data; + ctx->hwframes->sw_format = in_hwframe_ctx->sw_format; + } else { + ctx->hwframes->sw_format = inlink->format; + } ctx->hwframes->width = inlink->w; ctx->hwframes->height = inlink->h; @@ -200,13 +217,21 @@ av_buffer_unref(&ctx->hwdevice_ref); } -static const AVClass hwupload_class = { - .class_name = "hwupload", - .item_name = av_default_item_name, - .option = NULL, - .version = LIBAVUTIL_VERSION_INT, +#define OFFSET(x) offsetof(HWUploadContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption hwupload_options[] = { + { + "derive_device", "Derive a new device of this type", + OFFSET(device_type), AV_OPT_TYPE_STRING, + { .str = NULL }, 0, 0, FLAGS + }, + { + NULL + } }; +AVFILTER_DEFINE_CLASS(hwupload); + static const AVFilterPad hwupload_inputs[] = { { .name = "default", diff -Nru ffmpeg-4.2.2/libavfilter/vf_hwupload_cuda.c ffmpeg-4.4/libavfilter/vf_hwupload_cuda.c --- ffmpeg-4.2.2/libavfilter/vf_hwupload_cuda.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_hwupload_cuda.c 2021-04-08 21:28:40.000000000 +0000 @@ -57,9 +57,12 @@ int ret; static const enum AVPixelFormat input_pix_fmts[] = { - AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_P010, AV_PIX_FMT_P016, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_0RGB32, AV_PIX_FMT_0BGR32, +#if CONFIG_VULKAN + AV_PIX_FMT_VULKAN, +#endif AV_PIX_FMT_NONE, }; static const enum AVPixelFormat output_pix_fmts[] = { @@ -68,13 +71,13 @@ AVFilterFormats *in_fmts = ff_make_format_list(input_pix_fmts); AVFilterFormats *out_fmts; - ret = ff_formats_ref(in_fmts, &ctx->inputs[0]->out_formats); + ret = ff_formats_ref(in_fmts, &ctx->inputs[0]->outcfg.formats); if (ret < 0) return ret; out_fmts = ff_make_format_list(output_pix_fmts); - ret = ff_formats_ref(out_fmts, &ctx->outputs[0]->in_formats); + ret = ff_formats_ref(out_fmts, &ctx->outputs[0]->incfg.formats); if (ret < 0) return ret; @@ -97,7 +100,12 @@ hwframe_ctx = (AVHWFramesContext*)s->hwframe->data; hwframe_ctx->format = AV_PIX_FMT_CUDA; - hwframe_ctx->sw_format = inlink->format; + if (inlink->hw_frames_ctx) { + AVHWFramesContext *in_hwframe_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data; + hwframe_ctx->sw_format = in_hwframe_ctx->sw_format; + } else { + hwframe_ctx->sw_format = inlink->format; + } hwframe_ctx->width = inlink->w; hwframe_ctx->height = inlink->h; diff -Nru ffmpeg-4.2.2/libavfilter/vf_identity.c ffmpeg-4.4/libavfilter/vf_identity.c --- ffmpeg-4.2.2/libavfilter/vf_identity.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_identity.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,453 @@ +/* + * 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 + */ + +/** + * @file + * Caculate the Identity between two input videos. + */ + +#include "libavutil/avstring.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "drawutils.h" +#include "formats.h" +#include "framesync.h" +#include "internal.h" +#include "video.h" +#include "scene_sad.h" + +typedef struct IdentityContext { + const AVClass *class; + FFFrameSync fs; + double score, min_score, max_score, score_comp[4]; + uint64_t nb_frames; + int is_rgb; + int is_msad; + uint8_t rgba_map[4]; + int max[4]; + char comps[4]; + int nb_components; + int nb_threads; + int planewidth[4]; + int planeheight[4]; + uint64_t **scores; + unsigned (*filter_line)(const uint8_t *buf, const uint8_t *ref, int w); + int (*filter_slice)(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs); + ff_scene_sad_fn sad; +} IdentityContext; + +#define OFFSET(x) offsetof(IdentityContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static unsigned identity_line_8bit(const uint8_t *main_line, const uint8_t *ref_line, int outw) +{ + unsigned score = 0; + + for (int j = 0; j < outw; j++) + score += main_line[j] == ref_line[j]; + + return score; +} + +static unsigned identity_line_16bit(const uint8_t *mmain_line, const uint8_t *rref_line, int outw) +{ + const uint16_t *main_line = (const uint16_t *)mmain_line; + const uint16_t *ref_line = (const uint16_t *)rref_line; + unsigned score = 0; + + for (int j = 0; j < outw; j++) + score += main_line[j] == ref_line[j]; + + return score; +} + +typedef struct ThreadData { + const uint8_t *main_data[4]; + const uint8_t *ref_data[4]; + int main_linesize[4]; + int ref_linesize[4]; + int planewidth[4]; + int planeheight[4]; + uint64_t **score; + int nb_components; +} ThreadData; + +static +int compute_images_msad(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + IdentityContext *s = ctx->priv; + ThreadData *td = arg; + uint64_t *score = td->score[jobnr]; + + for (int c = 0; c < td->nb_components; c++) { + const int outw = td->planewidth[c]; + const int outh = td->planeheight[c]; + const int slice_start = (outh * jobnr) / nb_jobs; + const int slice_end = (outh * (jobnr+1)) / nb_jobs; + const int ref_linesize = td->ref_linesize[c]; + const int main_linesize = td->main_linesize[c]; + const uint8_t *main_line = td->main_data[c] + main_linesize * slice_start; + const uint8_t *ref_line = td->ref_data[c] + ref_linesize * slice_start; + uint64_t m = 0; + + s->sad(main_line, main_linesize, ref_line, ref_linesize, + outw, slice_end - slice_start, &m); + + score[c] = m; + } + + return 0; +} + +static +int compute_images_identity(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + IdentityContext *s = ctx->priv; + ThreadData *td = arg; + uint64_t *score = td->score[jobnr]; + + for (int c = 0; c < td->nb_components; c++) { + const int outw = td->planewidth[c]; + const int outh = td->planeheight[c]; + const int slice_start = (outh * jobnr) / nb_jobs; + const int slice_end = (outh * (jobnr+1)) / nb_jobs; + const int ref_linesize = td->ref_linesize[c]; + const int main_linesize = td->main_linesize[c]; + const uint8_t *main_line = td->main_data[c] + main_linesize * slice_start; + const uint8_t *ref_line = td->ref_data[c] + ref_linesize * slice_start; + uint64_t m = 0; + + for (int i = slice_start; i < slice_end; i++) { + m += s->filter_line(main_line, ref_line, outw); + ref_line += ref_linesize; + main_line += main_linesize; + } + score[c] = m; + } + + return 0; +} + +static void set_meta(AVFilterContext *ctx, + AVDictionary **metadata, const char *key, char comp, float d) +{ + char value[128]; + snprintf(value, sizeof(value), "%f", d); + if (comp) { + char key2[128]; + snprintf(key2, sizeof(key2), "lavfi.%s.%s%s%c", + ctx->filter->name, ctx->filter->name, key, comp); + av_dict_set(metadata, key2, value, 0); + } else { + char key2[128]; + snprintf(key2, sizeof(key2), "lavfi.%s.%s%s", + ctx->filter->name, ctx->filter->name, key); + av_dict_set(metadata, key2, value, 0); + } +} + +static int do_identity(FFFrameSync *fs) +{ + AVFilterContext *ctx = fs->parent; + IdentityContext *s = ctx->priv; + AVFrame *master, *ref; + double comp_score[4], score = 0.; + uint64_t comp_sum[4] = { 0 }; + AVDictionary **metadata; + ThreadData td; + int ret; + + ret = ff_framesync_dualinput_get(fs, &master, &ref); + if (ret < 0) + return ret; + if (ctx->is_disabled || !ref) + return ff_filter_frame(ctx->outputs[0], master); + metadata = &master->metadata; + + td.nb_components = s->nb_components; + td.score = s->scores; + for (int c = 0; c < s->nb_components; c++) { + td.main_data[c] = master->data[c]; + td.ref_data[c] = ref->data[c]; + td.main_linesize[c] = master->linesize[c]; + td.ref_linesize[c] = ref->linesize[c]; + td.planewidth[c] = s->planewidth[c]; + td.planeheight[c] = s->planeheight[c]; + } + + ctx->internal->execute(ctx, s->filter_slice, &td, NULL, FFMIN(s->planeheight[1], s->nb_threads)); + + for (int j = 0; j < s->nb_threads; j++) { + for (int c = 0; c < s->nb_components; c++) + comp_sum[c] += s->scores[j][c]; + } + + for (int c = 0; c < s->nb_components; c++) + comp_score[c] = comp_sum[c] / ((double)s->planewidth[c] * s->planeheight[c]); + + for (int c = 0; c < s->nb_components && s->is_msad; c++) + comp_score[c] /= (double)s->max[c]; + + for (int c = 0; c < s->nb_components; c++) + score += comp_score[c]; + score /= s->nb_components; + + s->min_score = FFMIN(s->min_score, score); + s->max_score = FFMAX(s->max_score, score); + + s->score += score; + + for (int j = 0; j < s->nb_components; j++) + s->score_comp[j] += comp_score[j]; + s->nb_frames++; + + for (int j = 0; j < s->nb_components; j++) { + int c = s->is_rgb ? s->rgba_map[j] : j; + set_meta(ctx, metadata, ".", s->comps[j], comp_score[c]); + } + set_meta(ctx, metadata, "_avg", 0, score); + + return ff_filter_frame(ctx->outputs[0], master); +} + +static av_cold int init(AVFilterContext *ctx) +{ + IdentityContext *s = ctx->priv; + + s->fs.on_event = do_identity; + + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, +#define PF_NOALPHA(suf) AV_PIX_FMT_YUV420##suf, AV_PIX_FMT_YUV422##suf, AV_PIX_FMT_YUV444##suf +#define PF_ALPHA(suf) AV_PIX_FMT_YUVA420##suf, AV_PIX_FMT_YUVA422##suf, AV_PIX_FMT_YUVA444##suf +#define PF(suf) PF_NOALPHA(suf), PF_ALPHA(suf) + PF(P), PF(P9), PF(P10), PF_NOALPHA(P12), PF_NOALPHA(P14), PF(P16), + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +static int config_input_ref(AVFilterLink *inlink) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + AVFilterContext *ctx = inlink->dst; + IdentityContext *s = ctx->priv; + + s->nb_threads = ff_filter_get_nb_threads(ctx); + s->nb_components = desc->nb_components; + if (ctx->inputs[0]->w != ctx->inputs[1]->w || + ctx->inputs[0]->h != ctx->inputs[1]->h) { + av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n"); + return AVERROR(EINVAL); + } + if (ctx->inputs[0]->format != ctx->inputs[1]->format) { + av_log(ctx, AV_LOG_ERROR, "Inputs must be of same pixel format.\n"); + return AVERROR(EINVAL); + } + + s->is_rgb = ff_fill_rgba_map(s->rgba_map, inlink->format) >= 0; + s->comps[0] = s->is_rgb ? 'R' : 'Y' ; + s->comps[1] = s->is_rgb ? 'G' : 'U' ; + s->comps[2] = s->is_rgb ? 'B' : 'V' ; + s->comps[3] = 'A'; + + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + + s->scores = av_calloc(s->nb_threads, sizeof(*s->scores)); + if (!s->scores) + return AVERROR(ENOMEM); + + for (int t = 0; t < s->nb_threads && s->scores; t++) { + s->scores[t] = av_calloc(s->nb_components, sizeof(*s->scores[0])); + if (!s->scores[t]) + return AVERROR(ENOMEM); + } + + s->min_score = +INFINITY; + s->max_score = -INFINITY; + + s->max[0] = (1 << desc->comp[0].depth) - 1; + s->max[1] = (1 << desc->comp[1].depth) - 1; + s->max[2] = (1 << desc->comp[2].depth) - 1; + s->max[3] = (1 << desc->comp[3].depth) - 1; + + s->is_msad = !strcmp(ctx->filter->name, "msad"); + s->filter_slice = !s->is_msad ? compute_images_identity : compute_images_msad; + s->filter_line = desc->comp[0].depth > 8 ? identity_line_16bit : identity_line_8bit; + + s->sad = ff_scene_sad_get_fn(desc->comp[0].depth <= 8 ? 8 : 16); + if (!s->sad) + return AVERROR(EINVAL); + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + IdentityContext *s = ctx->priv; + AVFilterLink *mainlink = ctx->inputs[0]; + int ret; + + ret = ff_framesync_init_dualinput(&s->fs, ctx); + if (ret < 0) + return ret; + outlink->w = mainlink->w; + outlink->h = mainlink->h; + outlink->time_base = mainlink->time_base; + outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio; + outlink->frame_rate = mainlink->frame_rate; + if ((ret = ff_framesync_configure(&s->fs)) < 0) + return ret; + + outlink->time_base = s->fs.time_base; + + if (av_cmp_q(mainlink->time_base, outlink->time_base) || + av_cmp_q(ctx->inputs[1]->time_base, outlink->time_base)) + av_log(ctx, AV_LOG_WARNING, "not matching timebases found between first input: %d/%d and second input %d/%d, results may be incorrect!\n", + mainlink->time_base.num, mainlink->time_base.den, + ctx->inputs[1]->time_base.num, ctx->inputs[1]->time_base.den); + + return 0; +} + +static int activate(AVFilterContext *ctx) +{ + IdentityContext *s = ctx->priv; + return ff_framesync_activate(&s->fs); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + IdentityContext *s = ctx->priv; + + if (s->nb_frames > 0) { + char buf[256]; + + buf[0] = 0; + for (int j = 0; j < s->nb_components; j++) { + int c = s->is_rgb ? s->rgba_map[j] : j; + av_strlcatf(buf, sizeof(buf), " %c:%f", s->comps[j], s->score_comp[c] / s->nb_frames); + } + + av_log(ctx, AV_LOG_INFO, "%s%s average:%f min:%f max:%f\n", + ctx->filter->name, + buf, + s->score / s->nb_frames, + s->min_score, + s->max_score); + } + + ff_framesync_uninit(&s->fs); + for (int t = 0; t < s->nb_threads && s->scores; t++) + av_freep(&s->scores[t]); + av_freep(&s->scores); +} + +static const AVFilterPad identity_inputs[] = { + { + .name = "main", + .type = AVMEDIA_TYPE_VIDEO, + },{ + .name = "reference", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input_ref, + }, + { NULL } +}; + +static const AVFilterPad identity_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +static const AVOption options[] = { + { NULL } +}; + +#if CONFIG_IDENTITY_FILTER + +#define identity_options options +FRAMESYNC_DEFINE_CLASS(identity, IdentityContext, fs); + +AVFilter ff_vf_identity = { + .name = "identity", + .description = NULL_IF_CONFIG_SMALL("Calculate the Identity between two video streams."), + .preinit = identity_framesync_preinit, + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .activate = activate, + .priv_size = sizeof(IdentityContext), + .priv_class = &identity_class, + .inputs = identity_inputs, + .outputs = identity_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, +}; + +#endif /* CONFIG_IDENTITY_FILTER */ + +#if CONFIG_MSAD_FILTER + +#define msad_options options +FRAMESYNC_DEFINE_CLASS(msad, IdentityContext, fs); + +AVFilter ff_vf_msad = { + .name = "msad", + .description = NULL_IF_CONFIG_SMALL("Calculate the MSAD between two video streams."), + .preinit = msad_framesync_preinit, + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .activate = activate, + .priv_size = sizeof(IdentityContext), + .priv_class = &msad_class, + .inputs = identity_inputs, + .outputs = identity_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, +}; + +#endif /* CONFIG_MSAD_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/vf_il.c ffmpeg-4.4/libavfilter/vf_il.c --- ffmpeg-4.2.2/libavfilter/vf_il.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_il.c 2021-04-08 21:28:40.000000000 +0000 @@ -46,7 +46,7 @@ } IlContext; #define OFFSET(x) offsetof(IlContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption il_options[] = { {"luma_mode", "select luma mode", OFFSET(luma_mode), AV_OPT_TYPE_INT, {.i64=MODE_NONE}, MODE_NONE, MODE_DEINTERLEAVE, FLAGS, "luma_mode"}, @@ -84,16 +84,13 @@ static int query_formats(AVFilterContext *ctx) { AVFilterFormats *formats = NULL; - int fmt, ret; - - for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); - if (!(desc->flags & AV_PIX_FMT_FLAG_PAL) && - !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL) && - (ret = ff_add_format(&formats, fmt)) < 0) - return ret; - } + int ret; + ret = ff_formats_pixdesc_filter(&formats, 0, + AV_PIX_FMT_FLAG_PAL | + AV_PIX_FMT_FLAG_HWACCEL); + if (ret < 0) + return ret; return ff_set_common_formats(ctx, formats); } @@ -210,4 +207,5 @@ .outputs = outputs, .priv_class = &il_class, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_lagfun.c ffmpeg-4.4/libavfilter/vf_lagfun.c --- ffmpeg-4.2.2/libavfilter/vf_lagfun.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_lagfun.c 2021-04-08 21:28:40.000000000 +0000 @@ -30,16 +30,16 @@ typedef struct LagfunContext { const AVClass *class; - const AVPixFmtDescriptor *desc; float decay; int planes; int depth; int nb_planes; int linesize[4]; - int height[4]; + int planewidth[4]; + int planeheight[4]; - AVFrame *old; + float *old[4]; int (*lagfun)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } LagfunContext; @@ -74,100 +74,87 @@ } typedef struct ThreadData { - AVFrame *in, *out, *old; + AVFrame *in, *out; } ThreadData; -static int lagfun_frame8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) -{ - LagfunContext *s = ctx->priv; - const float decay = s->decay; - ThreadData *td = arg; - AVFrame *in = td->in; - AVFrame *out = td->out; - AVFrame *old = td->old; - - for (int p = 0; p < s->nb_planes; p++) { - const int slice_start = (s->height[p] * jobnr) / nb_jobs; - const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; - const uint8_t *src = in->data[p] + slice_start * in->linesize[p]; - const uint8_t *osrc = old->data[p] + slice_start * old->linesize[p]; - uint8_t *dst = out->data[p] + slice_start * out->linesize[p]; - - if (!((1 << p) & s->planes)) { - av_image_copy_plane(dst, out->linesize[p], - src, in->linesize[p], - s->linesize[p], slice_end - slice_start); - continue; - } - - for (int y = slice_start; y < slice_end; y++) { - for (int x = 0; x < s->linesize[p]; x++) - dst[x] = FFMAX(src[x], osrc[x] * decay); - - src += in->linesize[p]; - osrc += old->linesize[p]; - dst += out->linesize[p]; - } - } - - return 0; +#define LAGFUN(name, type) \ +static int lagfun_frame##name(AVFilterContext *ctx, void *arg, \ + int jobnr, int nb_jobs) \ +{ \ + LagfunContext *s = ctx->priv; \ + const float decay = s->decay; \ + ThreadData *td = arg; \ + AVFrame *in = td->in; \ + AVFrame *out = td->out; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const int slice_start = (s->planeheight[p] * jobnr) / nb_jobs; \ + const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs; \ + const type *src = (const type *)in->data[p] + \ + slice_start * in->linesize[p] / sizeof(type); \ + float *osrc = s->old[p] + slice_start * s->planewidth[p]; \ + type *dst = (type *)out->data[p] + \ + slice_start * out->linesize[p] / sizeof(type); \ + \ + if (!((1 << p) & s->planes)) { \ + av_image_copy_plane((uint8_t *)dst, out->linesize[p], \ + (const uint8_t *)src, in->linesize[p], \ + s->linesize[p], slice_end - slice_start); \ + continue; \ + } \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < s->planewidth[p]; x++) { \ + float v = FFMAX(src[x], osrc[x] * decay); \ + \ + osrc[x] = v; \ + if (ctx->is_disabled) { \ + dst[x] = src[x]; \ + } else { \ + dst[x] = lrintf(v); \ + } \ + } \ + \ + src += in->linesize[p] / sizeof(type); \ + osrc += s->planewidth[p]; \ + dst += out->linesize[p] / sizeof(type); \ + } \ + } \ + \ + return 0; \ } -static int lagfun_frame16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) -{ - LagfunContext *s = ctx->priv; - const float decay = s->decay; - ThreadData *td = arg; - AVFrame *in = td->in; - AVFrame *out = td->out; - AVFrame *old = td->old; - - for (int p = 0; p < s->nb_planes; p++) { - const int slice_start = (s->height[p] * jobnr) / nb_jobs; - const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; - const uint16_t *src = (const uint16_t *)in->data[p] + slice_start * in->linesize[p] / 2; - const uint16_t *osrc = (const uint16_t *)old->data[p] + slice_start * old->linesize[p] / 2; - uint16_t *dst = (uint16_t *)out->data[p] + slice_start * out->linesize[p] / 2; - - if (!((1 << p) & s->planes)) { - av_image_copy_plane((uint8_t *)dst, out->linesize[p], - (uint8_t *)src, in->linesize[p], - s->linesize[p], slice_end - slice_start); - continue; - } - - for (int y = slice_start; y < slice_end; y++) { - for (int x = 0; x < s->linesize[p]; x++) - dst[x] = FFMAX(src[x], osrc[x] * decay); - - src += in->linesize[p] / 2; - osrc += old->linesize[p] / 2; - dst += out->linesize[p] / 2; - } - } - - return 0; -} +LAGFUN(8, uint8_t) +LAGFUN(16, uint16_t) static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; LagfunContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; + const AVPixFmtDescriptor *desc; int ret; - s->desc = av_pix_fmt_desc_get(outlink->format); - if (!s->desc) + desc = av_pix_fmt_desc_get(outlink->format); + if (!desc) return AVERROR_BUG; s->nb_planes = av_pix_fmt_count_planes(outlink->format); - s->depth = s->desc->comp[0].depth; + s->depth = desc->comp[0].depth; s->lagfun = s->depth <= 8 ? lagfun_frame8 : lagfun_frame16; if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) return ret; - s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h); - s->height[0] = s->height[3] = inlink->h; + 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; + + for (int p = 0; p < s->nb_planes; p++) { + s->old[p] = av_calloc(s->planewidth[p] * s->planeheight[p], sizeof(*s->old[0])); + if (!s->old[p]) + return AVERROR(ENOMEM); + } return 0; } @@ -180,11 +167,6 @@ ThreadData td; AVFrame *out; - if (!s->old) { - s->old = av_frame_clone(in); - return ff_filter_frame(outlink, in); - } - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); @@ -194,12 +176,9 @@ td.out = out; td.in = in; - td.old = s->old; - ctx->internal->execute(ctx, s->lagfun, &td, NULL, FFMIN(s->height[1], ff_filter_get_nb_threads(ctx))); + ctx->internal->execute(ctx, s->lagfun, &td, NULL, FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx))); - av_frame_free(&s->old); av_frame_free(&in); - s->old = av_frame_clone(out); return ff_filter_frame(outlink, out); } @@ -207,11 +186,12 @@ { LagfunContext *s = ctx->priv; - av_frame_free(&s->old); + for (int p = 0; p < s->nb_planes; p++) + av_freep(&s->old[p]); } #define OFFSET(x) offsetof(LagfunContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption lagfun_options[] = { { "decay", "set decay", OFFSET(decay), AV_OPT_TYPE_FLOAT, {.dbl=.95}, 0, 1, FLAGS }, @@ -248,5 +228,6 @@ .uninit = uninit, .outputs = outputs, .inputs = inputs, - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_lenscorrection.c ffmpeg-4.4/libavfilter/vf_lenscorrection.c --- ffmpeg-4.2.2/libavfilter/vf_lenscorrection.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_lenscorrection.c 2021-04-08 21:28:40.000000000 +0000 @@ -26,30 +26,43 @@ #include #include +#include "libavutil/colorspace.h" #include "libavutil/opt.h" #include "libavutil/intreadwrite.h" #include "libavutil/pixdesc.h" #include "avfilter.h" +#include "drawutils.h" #include "internal.h" #include "video.h" typedef struct LenscorrectionCtx { const AVClass *av_class; - unsigned int width; - unsigned int height; - int hsub, vsub; + int planewidth[4]; + int planeheight[4]; + int depth; int nb_planes; double cx, cy, k1, k2; + int interpolation; + uint8_t fill_rgba[4]; + int fill_color[4]; + int32_t *correction[4]; + + int (*filter_slice)(AVFilterContext *ctx, void *arg, int job, int nb_jobs, int plane); } LenscorrectionCtx; -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define OFFSET(x) offsetof(LenscorrectionCtx, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption lenscorrection_options[] = { - { "cx", "set relative center x", offsetof(LenscorrectionCtx, cx), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 1, .flags=FLAGS }, - { "cy", "set relative center y", offsetof(LenscorrectionCtx, cy), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 1, .flags=FLAGS }, - { "k1", "set quadratic distortion factor", offsetof(LenscorrectionCtx, k1), AV_OPT_TYPE_DOUBLE, {.dbl=0.0}, -1, 1, .flags=FLAGS }, - { "k2", "set double quadratic distortion factor", offsetof(LenscorrectionCtx, k2), AV_OPT_TYPE_DOUBLE, {.dbl=0.0}, -1, 1, .flags=FLAGS }, + { "cx", "set relative center x", OFFSET(cx), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 1, .flags=FLAGS }, + { "cy", "set relative center y", OFFSET(cy), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 1, .flags=FLAGS }, + { "k1", "set quadratic distortion factor", OFFSET(k1), AV_OPT_TYPE_DOUBLE, {.dbl=0.0}, -1, 1, .flags=FLAGS }, + { "k2", "set double quadratic distortion factor", OFFSET(k2), AV_OPT_TYPE_DOUBLE, {.dbl=0.0}, -1, 1, .flags=FLAGS }, + { "i", "set interpolation type", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=0}, 0, 64, .flags=FLAGS, "i" }, + { "nearest", "nearest neighbour", 0, AV_OPT_TYPE_CONST, {.i64=0},0, 0, .flags=FLAGS, "i" }, + { "bilinear", "bilinear", 0, AV_OPT_TYPE_CONST, {.i64=1},0, 0, .flags=FLAGS, "i" }, + { "fc", "set the color of the unmapped pixels", OFFSET(fill_rgba), AV_OPT_TYPE_COLOR, {.str="black@0"}, .flags = FLAGS }, { NULL } }; @@ -57,54 +70,137 @@ typedef struct ThreadData { AVFrame *in, *out; - int w, h; - int plane; - int xcenter, ycenter; - int32_t *correction; } ThreadData; -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) -{ - ThreadData *td = (ThreadData*)arg; - AVFrame *in = td->in; - AVFrame *out = td->out; - - const int w = td->w, h = td->h; - const int xcenter = td->xcenter; - const int ycenter = td->ycenter; - const int start = (h * job ) / nb_jobs; - const int end = (h * (job+1)) / nb_jobs; - const int plane = td->plane; - const int inlinesize = in->linesize[plane]; - const int outlinesize = out->linesize[plane]; - const uint8_t *indata = in->data[plane]; - uint8_t *outrow = out->data[plane] + start * outlinesize; - int i; - for (i = start; i < end; i++, outrow += outlinesize) { - const int off_y = i - ycenter; - uint8_t *out = outrow; - int j; - for (j = 0; j < w; j++) { - const int off_x = j - xcenter; - const int64_t radius_mult = td->correction[j + i*w]; - const int x = xcenter + ((radius_mult * off_x + (1<<23))>>24); - const int y = ycenter + ((radius_mult * off_y + (1<<23))>>24); - const char isvalid = x > 0 && x < w - 1 && y > 0 && y < h - 1; - *out++ = isvalid ? indata[y * inlinesize + x] : 0; - } - } - return 0; +#define NEAREST(type, name) \ +static int filter##name##_slice(AVFilterContext *ctx, void *arg, int job, \ + int nb_jobs, int plane) \ +{ \ + LenscorrectionCtx *rect = ctx->priv; \ + ThreadData *td = arg; \ + AVFrame *in = td->in; \ + AVFrame *out = td->out; \ + \ + const int32_t *correction = rect->correction[plane]; \ + const int fill_color = rect->fill_color[plane]; \ + const int w = rect->planewidth[plane], h = rect->planeheight[plane]; \ + const int xcenter = rect->cx * w; \ + const int ycenter = rect->cy * h; \ + const int start = (h * job ) / nb_jobs; \ + const int end = (h * (job+1)) / nb_jobs; \ + const int inlinesize = in->linesize[plane] / sizeof(type); \ + const int outlinesize = out->linesize[plane] / sizeof(type); \ + const type *indata = (const type *)in->data[plane]; \ + type *outrow = (type *)out->data[plane] + start * outlinesize; \ + for (int i = start; i < end; i++, outrow += outlinesize) { \ + const int off_y = i - ycenter; \ + type *out = outrow; \ + for (int j = 0; j < w; j++) { \ + const int off_x = j - xcenter; \ + const int64_t radius_mult = correction[j + i*w]; \ + const int x = xcenter + ((radius_mult * off_x + (1<<23))>>24); \ + const int y = ycenter + ((radius_mult * off_y + (1<<23))>>24); \ + const char isvalid = x >= 0 && x < w && y >= 0 && y < h; \ + *out++ = isvalid ? indata[y * inlinesize + x] : fill_color; \ + } \ + } \ + return 0; \ +} + + +NEAREST(uint8_t, 8) +NEAREST(uint16_t, 16) + +#define BILINEAR(type, name) \ +static int filter##name##_slice_bilinear(AVFilterContext *ctx, void *arg, \ + int job, int nb_jobs, int plane) \ +{ \ + LenscorrectionCtx *rect = ctx->priv; \ + ThreadData *td = arg; \ + AVFrame *in = td->in; \ + AVFrame *out = td->out; \ + \ + const int32_t *correction = rect->correction[plane]; \ + const int fill_color = rect->fill_color[plane]; \ + const int depth = rect->depth; \ + const uint64_t max = (1 << 24) - 1; \ + const uint64_t add = (1 << 23); \ + const int w = rect->planewidth[plane], h = rect->planeheight[plane]; \ + const int xcenter = rect->cx * w; \ + const int ycenter = rect->cy * h; \ + const int start = (h * job ) / nb_jobs; \ + const int end = (h * (job+1)) / nb_jobs; \ + const int inlinesize = in->linesize[plane] / sizeof(type); \ + const int outlinesize = out->linesize[plane] / sizeof(type); \ + const type *indata = (const type *)in->data[plane]; \ + type *outrow = (type *)out->data[plane] + start * outlinesize; \ + \ + for (int i = start; i < end; i++, outrow += outlinesize) { \ + const int off_y = i - ycenter; \ + type *out = outrow; \ + \ + for (int j = 0; j < w; j++) { \ + const int off_x = j - xcenter; \ + const int64_t radius_mult = correction[j + i*w]; \ + const int x = xcenter + ((radius_mult * off_x + (1<<23)) >> 24); \ + const int y = ycenter + ((radius_mult * off_y + (1<<23)) >> 24); \ + const char isvalid = x >= 0 && x <= w - 1 && y >= 0 && y <= h - 1; \ + \ + if (isvalid) { \ + const int nx = FFMIN(x + 1, w - 1); \ + const int ny = FFMIN(y + 1, h - 1); \ + const uint64_t du = off_x >= 0 ? (radius_mult * off_x + add) & max : max - ((radius_mult * -off_x + add) & max); \ + const uint64_t dv = off_y >= 0 ? (radius_mult * off_y + add) & max : max - ((radius_mult * -off_y + add) & max); \ + const uint64_t p0 = indata[ y * inlinesize + x]; \ + const uint64_t p1 = indata[ y * inlinesize + nx]; \ + const uint64_t p2 = indata[ny * inlinesize + x]; \ + const uint64_t p3 = indata[ny * inlinesize + nx]; \ + uint64_t sum = 0; \ + \ + sum += (max - du) * (max - dv) * p0; \ + sum += ( du) * (max - dv) * p1; \ + sum += (max - du) * ( dv) * p2; \ + sum += ( du) * ( dv) * p3; \ + \ + out[j] = av_clip_uintp2_c((sum + (1ULL << 47)) >> 48, depth); \ + } else { \ + out[j] = fill_color; \ + } \ + } \ + } \ + \ + return 0; \ } +BILINEAR(uint8_t, 8) +BILINEAR(uint16_t, 16) + static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_YUV410P, - AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, - AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P, - AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA420P, - AV_PIX_FMT_YUV422P, - AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, + AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, + AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); @@ -123,17 +219,86 @@ } } -static int config_props(AVFilterLink *outlink) +static void calc_correction(AVFilterContext *ctx, int plane) +{ + LenscorrectionCtx *rect = ctx->priv; + int w = rect->planewidth[plane]; + int h = rect->planeheight[plane]; + int xcenter = rect->cx * w; + int ycenter = rect->cy * h; + int k1 = rect->k1 * (1<<24); + int k2 = rect->k2 * (1<<24); + const int64_t r2inv = (4LL<<60) / (w * w + h * h); + + for (int j = 0; j < h; j++) { + const int off_y = j - ycenter; + const int off_y2 = off_y * off_y; + for (int i = 0; i < w; i++) { + const int off_x = i - xcenter; + const int64_t r2 = ((off_x * off_x + off_y2) * r2inv + (1LL<<31)) >> 32; + const int64_t r4 = (r2 * r2 + (1<<27)) >> 28; + const int radius_mult = (r2 * k1 + r4 * k2 + (1LL<<27) + (1LL<<52))>>28; + rect->correction[plane][j * w + i] = radius_mult; + } + } +} + +static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; LenscorrectionCtx *rect = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(inlink->format); - rect->hsub = pixdesc->log2_chroma_w; - rect->vsub = pixdesc->log2_chroma_h; - outlink->w = rect->width = inlink->w; - outlink->h = rect->height = inlink->h; + int is_rgb = !!(pixdesc->flags & AV_PIX_FMT_FLAG_RGB); + uint8_t rgba_map[4]; + int factor; + + ff_fill_rgba_map(rgba_map, inlink->format); + rect->depth = pixdesc->comp[0].depth; + factor = 1 << (rect->depth - 8); + rect->planeheight[1] = rect->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, pixdesc->log2_chroma_h); + rect->planeheight[0] = rect->planeheight[3] = inlink->h; + rect->planewidth[1] = rect->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, pixdesc->log2_chroma_w); + rect->planewidth[0] = rect->planewidth[3] = inlink->w; rect->nb_planes = av_pix_fmt_count_planes(inlink->format); + rect->filter_slice = rect->depth <= 8 ? filter8_slice : filter16_slice; + if (rect->interpolation) + rect->filter_slice = rect->depth <= 8 ? filter8_slice_bilinear : filter16_slice_bilinear; + + if (is_rgb) { + rect->fill_color[rgba_map[0]] = rect->fill_rgba[0] * factor; + rect->fill_color[rgba_map[1]] = rect->fill_rgba[1] * factor; + rect->fill_color[rgba_map[2]] = rect->fill_rgba[2] * factor; + rect->fill_color[rgba_map[3]] = rect->fill_rgba[3] * factor; + } else { + rect->fill_color[0] = RGB_TO_Y_BT709(rect->fill_rgba[0], rect->fill_rgba[1], rect->fill_rgba[2]) * factor; + rect->fill_color[1] = RGB_TO_U_BT709(rect->fill_rgba[0], rect->fill_rgba[1], rect->fill_rgba[2], 0) * factor; + rect->fill_color[2] = RGB_TO_V_BT709(rect->fill_rgba[0], rect->fill_rgba[1], rect->fill_rgba[2], 0) * factor; + rect->fill_color[3] = rect->fill_rgba[3] * factor; + } + + for (int plane = 0; plane < rect->nb_planes; plane++) { + int w = rect->planewidth[plane]; + int h = rect->planeheight[plane]; + + if (!rect->correction[plane]) + rect->correction[plane] = av_malloc_array(w, h * sizeof(**rect->correction)); + if (!rect->correction[plane]) + return AVERROR(ENOMEM); + calc_correction(ctx, plane); + } + + return 0; +} + +static int filter_slice(AVFilterContext *ctx, void *arg, int job, + int nb_jobs) +{ + LenscorrectionCtx *rect = ctx->priv; + + for (int plane = 0; plane < rect->nb_planes; plane++) + rect->filter_slice(ctx, arg, job, nb_jobs, plane); + return 0; } @@ -141,9 +306,9 @@ { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; - LenscorrectionCtx *rect = (LenscorrectionCtx*)ctx->priv; + LenscorrectionCtx *rect = ctx->priv; AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - int plane; + ThreadData td; if (!out) { av_frame_free(&in); @@ -152,54 +317,28 @@ av_frame_copy_props(out, in); - for (plane = 0; plane < rect->nb_planes; ++plane) { - int hsub = plane == 1 || plane == 2 ? rect->hsub : 0; - int vsub = plane == 1 || plane == 2 ? rect->vsub : 0; - int hdiv = 1 << hsub; - int vdiv = 1 << vsub; - int w = rect->width / hdiv; - int h = rect->height / vdiv; - int xcenter = rect->cx * w; - int ycenter = rect->cy * h; - int k1 = rect->k1 * (1<<24); - int k2 = rect->k2 * (1<<24); - ThreadData td = { - .in = in, - .out = out, - .w = w, - .h = h, - .xcenter = xcenter, - .ycenter = ycenter, - .plane = plane}; - - if (!rect->correction[plane]) { - int i,j; - const int64_t r2inv = (4LL<<60) / (w * w + h * h); - - rect->correction[plane] = av_malloc_array(w, h * sizeof(**rect->correction)); - if (!rect->correction[plane]) - return AVERROR(ENOMEM); - for (j = 0; j < h; j++) { - const int off_y = j - ycenter; - const int off_y2 = off_y * off_y; - for (i = 0; i < w; i++) { - const int off_x = i - xcenter; - const int64_t r2 = ((off_x * off_x + off_y2) * r2inv + (1LL<<31)) >> 32; - const int64_t r4 = (r2 * r2 + (1<<27)) >> 28; - const int radius_mult = (r2 * k1 + r4 * k2 + (1LL<<27) + (1LL<<52))>>28; - rect->correction[plane][j * w + i] = radius_mult; - } - } - } - - td.correction = rect->correction[plane]; - ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(h, ff_filter_get_nb_threads(ctx))); - } + td.in = in; td.out = out; + ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(rect->planeheight[1], ff_filter_get_nb_threads(ctx))); av_frame_free(&in); return ff_filter_frame(outlink, out); } +static int process_command(AVFilterContext *ctx, + const char *cmd, + const char *arg, + char *res, + int res_len, + int flags) +{ + int ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags); + + if (ret < 0) + return ret; + + return config_output(ctx->outputs[0]); +} + static const AVFilterPad lenscorrection_inputs[] = { { .name = "default", @@ -213,7 +352,7 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .config_props = config_props, + .config_props = config_output, }, { NULL } }; @@ -227,5 +366,6 @@ .outputs = lenscorrection_outputs, .priv_class = &lenscorrection_class, .uninit = uninit, - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_lensfun.c ffmpeg-4.4/libavfilter/vf_lensfun.c --- ffmpeg-4.2.2/libavfilter/vf_lensfun.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_lensfun.c 2021-04-08 21:28:40.000000000 +0000 @@ -136,26 +136,35 @@ const lfCamera **cameras; const lfLens **lenses; - if (!lensfun->make) { - av_log(ctx, AV_LOG_FATAL, "Option \"make\" not specified\n"); - return AVERROR(EINVAL); - } else if (!lensfun->model) { - av_log(ctx, AV_LOG_FATAL, "Option \"model\" not specified\n"); + db = lf_db_create(); + if (lf_db_load(db) != LF_NO_ERROR) { + lf_db_destroy(db); + av_log(ctx, AV_LOG_FATAL, "Failed to load lensfun database\n"); + return AVERROR_INVALIDDATA; + } + + if (!lensfun->make || !lensfun->model) { + const lfCamera *const *cameras = lf_db_get_cameras(db); + + av_log(ctx, AV_LOG_FATAL, "Option \"make\" or option \"model\" not specified\n"); + av_log(ctx, AV_LOG_INFO, "Available values for \"make\" and \"model\":\n"); + for (int i = 0; cameras && cameras[i]; i++) + av_log(ctx, AV_LOG_INFO, "\t%s\t%s\n", cameras[i]->Maker, cameras[i]->Model); + lf_db_destroy(db); return AVERROR(EINVAL); } else if (!lensfun->lens_model) { + const lfLens *const *lenses = lf_db_get_lenses(db); + av_log(ctx, AV_LOG_FATAL, "Option \"lens_model\" not specified\n"); + av_log(ctx, AV_LOG_INFO, "Available values for \"lens_model\":\n"); + for (int i = 0; lenses && lenses[i]; i++) + av_log(ctx, AV_LOG_INFO, "\t%s\t(make %s)\n", lenses[i]->Model, lenses[i]->Maker); + lf_db_destroy(db); return AVERROR(EINVAL); } - lensfun->lens = lf_lens_new(); - lensfun->camera = lf_camera_new(); - - db = lf_db_new(); - if (lf_db_load(db) != LF_NO_ERROR) { - lf_db_destroy(db); - av_log(ctx, AV_LOG_FATAL, "Failed to load lensfun database\n"); - return AVERROR_INVALIDDATA; - } + lensfun->lens = lf_lens_create(); + lensfun->camera = lf_camera_create(); cameras = lf_db_find_cameras(db, lensfun->make, lensfun->model); if (cameras && *cameras) { @@ -169,7 +178,7 @@ } lf_free(cameras); - lenses = lf_db_find_lenses_hd(db, lensfun->camera, NULL, lensfun->lens_model, 0); + lenses = lf_db_find_lenses(db, lensfun->camera, NULL, lensfun->lens_model, 0); if (lenses && *lenses) { lf_lens_copy(lensfun->lens, *lenses); av_log(ctx, AV_LOG_INFO, "Using lens %s\n", lensfun->lens->Model); @@ -210,30 +219,23 @@ LensfunContext *lensfun = ctx->priv; int index; float a; - int lensfun_mode = 0; if (!lensfun->modifier) { if (lensfun->camera && lensfun->lens) { - lensfun->modifier = lf_modifier_new(lensfun->lens, - lensfun->camera->CropFactor, - inlink->w, - inlink->h); + lensfun->modifier = lf_modifier_create(lensfun->lens, + lensfun->focal_length, + lensfun->camera->CropFactor, + inlink->w, + inlink->h, LF_PF_U8, lensfun->reverse); if (lensfun->mode & VIGNETTING) - lensfun_mode |= LF_MODIFY_VIGNETTING; - if (lensfun->mode & GEOMETRY_DISTORTION) - lensfun_mode |= LF_MODIFY_DISTORTION | LF_MODIFY_GEOMETRY | LF_MODIFY_SCALE; + lf_modifier_enable_vignetting_correction(lensfun->modifier, lensfun->aperture, lensfun->focus_distance); + if (lensfun->mode & GEOMETRY_DISTORTION) { + lf_modifier_enable_distortion_correction(lensfun->modifier); + lf_modifier_enable_projection_transform(lensfun->modifier, lensfun->target_geometry); + lf_modifier_enable_scaling(lensfun->modifier, lensfun->scale); + } if (lensfun->mode & SUBPIXEL_DISTORTION) - lensfun_mode |= LF_MODIFY_TCA; - lf_modifier_initialize(lensfun->modifier, - lensfun->lens, - LF_PF_U8, - lensfun->focal_length, - lensfun->aperture, - lensfun->focus_distance, - lensfun->scale, - lensfun->target_geometry, - lensfun_mode, - lensfun->reverse); + lf_modifier_enable_tca_correction(lensfun->modifier); } else { // lensfun->camera and lensfun->lens should have been initialized return AVERROR_BUG; diff -Nru ffmpeg-4.2.2/libavfilter/vf_libvmaf.c ffmpeg-4.4/libavfilter/vf_libvmaf.c --- ffmpeg-4.2.2/libavfilter/vf_libvmaf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_libvmaf.c 2021-04-08 21:28:40.000000000 +0000 @@ -74,7 +74,7 @@ static const AVOption libvmaf_options[] = { {"model_path", "Set the model to be used for computing vmaf.", OFFSET(model_path), AV_OPT_TYPE_STRING, {.str="/usr/local/share/model/vmaf_v0.6.1.pkl"}, 0, 1, FLAGS}, {"log_path", "Set the file path to be used to store logs.", OFFSET(log_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, - {"log_fmt", "Set the format of the log (xml or json).", OFFSET(log_fmt), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, + {"log_fmt", "Set the format of the log (csv, json or xml).", OFFSET(log_fmt), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, {"enable_transform", "Enables transform for computing vmaf.", OFFSET(enable_transform), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, {"phone_model", "Invokes the phone model that will generate higher VMAF scores.", OFFSET(phone_model), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, {"psnr", "Enables computing psnr along with vmaf.", OFFSET(psnr), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, @@ -110,6 +110,7 @@ const type *main_ptr = (const type *) s->gmain->data[0]; \ \ float *ptr = ref_data; \ + float factor = 1.f / (1 << (bits - 8)); \ \ int h = s->height; \ int w = s->width; \ @@ -118,7 +119,7 @@ \ for (i = 0; i < h; i++) { \ for ( j = 0; j < w; j++) { \ - ptr[j] = (float)ref_ptr[j]; \ + ptr[j] = ref_ptr[j] * factor; \ } \ ref_ptr += ref_stride / sizeof(*ref_ptr); \ ptr += stride / sizeof(*ptr); \ @@ -128,7 +129,7 @@ \ for (i = 0; i < h; i++) { \ for (j = 0; j < w; j++) { \ - ptr[j] = (float)main_ptr[j]; \ + ptr[j] = main_ptr[j] * factor; \ } \ main_ptr += main_stride / sizeof(*main_ptr); \ ptr += stride / sizeof(*ptr); \ @@ -234,6 +235,9 @@ s->gref = av_frame_alloc(); s->gmain = av_frame_alloc(); + if (!s->gref || !s->gmain) + return AVERROR(ENOMEM); + s->error = 0; s->vmaf_thread_created = 0; diff -Nru ffmpeg-4.2.2/libavfilter/vf_limiter.c ffmpeg-4.4/libavfilter/vf_limiter.c --- ffmpeg-4.2.2/libavfilter/vf_limiter.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_limiter.c 2021-04-08 21:28:40.000000000 +0000 @@ -46,7 +46,7 @@ } LimiterContext; #define OFFSET(x) offsetof(LimiterContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption limiter_options[] = { { "min", "set min value", OFFSET(min), AV_OPT_TYPE_INT, {.i64=0}, 0, 65535, .flags = FLAGS }, @@ -81,6 +81,7 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, @@ -132,7 +133,7 @@ } } -static int config_props(AVFilterLink *inlink) +static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; LimiterContext *s = ctx->priv; @@ -229,12 +230,24 @@ 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) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + static const AVFilterPad inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .filter_frame = filter_frame, - .config_props = config_props, + .config_props = config_input, }, { NULL } }; @@ -257,4 +270,5 @@ .inputs = inputs, .outputs = outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_lumakey.c ffmpeg-4.4/libavfilter/vf_lumakey.c --- ffmpeg-4.2.2/libavfilter/vf_lumakey.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_lumakey.c 2020-07-11 10:39:30.000000000 +0000 @@ -28,12 +28,13 @@ typedef struct LumakeyContext { const AVClass *class; - int threshold; - int tolerance; - int softness; + double threshold; + double tolerance; + double softness; int white; int black; + int so; int max; int (*do_lumakey_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); @@ -47,7 +48,7 @@ const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs; uint8_t *alpha = frame->data[3] + slice_start * frame->linesize[3]; const uint8_t *luma = frame->data[0] + slice_start * frame->linesize[0]; - const int so = s->softness; + const int so = s->so; const int w = s->white; const int b = s->black; int x, y; @@ -79,7 +80,7 @@ const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs; uint16_t *alpha = (uint16_t *)(frame->data[3] + slice_start * frame->linesize[3]); const uint16_t *luma = (const uint16_t *)(frame->data[0] + slice_start * frame->linesize[0]); - const int so = s->softness; + const int so = s->so; const int w = s->white; const int b = s->black; const int m = s->max; @@ -113,14 +114,16 @@ depth = desc->comp[0].depth; if (depth == 8) { - s->white = av_clip_uint8(s->threshold + s->tolerance); - s->black = av_clip_uint8(s->threshold - s->tolerance); + s->white = av_clip_uint8((s->threshold + s->tolerance) * 255); + s->black = av_clip_uint8((s->threshold - s->tolerance) * 255); s->do_lumakey_slice = do_lumakey_slice8; + s->so = s->softness * 255; } else { s->max = (1 << depth) - 1; - s->white = av_clip(s->threshold + s->tolerance, 0, s->max); - s->black = av_clip(s->threshold - s->tolerance, 0, s->max); + s->white = av_clip((s->threshold + s->tolerance) * s->max, 0, s->max); + s->black = av_clip((s->threshold - s->tolerance) * s->max, 0, s->max); s->do_lumakey_slice = do_lumakey_slice16; + s->so = s->softness * s->max; } return 0; @@ -147,6 +150,7 @@ AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10, + AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_NONE }; @@ -159,6 +163,18 @@ return ff_set_common_formats(ctx, formats); } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + static const AVFilterPad lumakey_inputs[] = { { .name = "default", @@ -178,12 +194,12 @@ }; #define OFFSET(x) offsetof(LumakeyContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption lumakey_options[] = { - { "threshold", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, - { "tolerance", "set the tolerance value", OFFSET(tolerance), AV_OPT_TYPE_INT, {.i64=1}, 0, UINT16_MAX, FLAGS }, - { "softness", "set the softness value", OFFSET(softness), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, FLAGS }, + { "threshold", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 1, FLAGS }, + { "tolerance", "set the tolerance value", OFFSET(tolerance), AV_OPT_TYPE_DOUBLE, {.dbl=0.01}, 0, 1, FLAGS }, + { "softness", "set the softness value", OFFSET(softness), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 1, FLAGS }, { NULL } }; @@ -198,4 +214,5 @@ .inputs = lumakey_inputs, .outputs = lumakey_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_lut2.c ffmpeg-4.4/libavfilter/vf_lut2.c --- ffmpeg-4.2.2/libavfilter/vf_lut2.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_lut2.c 2021-04-08 21:28:40.000000000 +0000 @@ -79,12 +79,13 @@ #define OFFSET(x) offsetof(LUT2Context, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption options[] = { - { "c0", "set component #0 expression", OFFSET(comp_expr_str[0]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = FLAGS }, - { "c1", "set component #1 expression", OFFSET(comp_expr_str[1]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = FLAGS }, - { "c2", "set component #2 expression", OFFSET(comp_expr_str[2]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = FLAGS }, - { "c3", "set component #3 expression", OFFSET(comp_expr_str[3]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = FLAGS }, + { "c0", "set component #0 expression", OFFSET(comp_expr_str[0]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS }, + { "c1", "set component #1 expression", OFFSET(comp_expr_str[1]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS }, + { "c2", "set component #2 expression", OFFSET(comp_expr_str[2]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS }, + { "c3", "set component #3 expression", OFFSET(comp_expr_str[3]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS }, { "d", "set output depth", OFFSET(odepth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 16, .flags = FLAGS }, { NULL } }; @@ -125,11 +126,12 @@ #define BIT12_FMTS \ AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, \ + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, \ AV_PIX_FMT_GRAY12, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRP12, #define BIT14_FMTS \ AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, \ - AV_PIX_FMT_GRAY12, AV_PIX_FMT_GBRP14, + AV_PIX_FMT_GRAY14, AV_PIX_FMT_GBRP14, #define BIT16_FMTS \ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, \ @@ -176,7 +178,7 @@ if (s->tlut2 || !s->odepth) return ff_set_common_formats(ctx, ff_make_format_list(all_pix_fmts)); - ret = ff_formats_ref(ff_make_format_list(all_pix_fmts), &ctx->inputs[0]->out_formats); + ret = ff_formats_ref(ff_make_format_list(all_pix_fmts), &ctx->inputs[0]->outcfg.formats); if (ret < 0) return ret; @@ -191,7 +193,7 @@ return AVERROR(EINVAL); } - return ff_formats_ref(ff_make_format_list(pix_fmts), &ctx->outputs[0]->in_formats); + return ff_formats_ref(ff_make_format_list(pix_fmts), &ctx->outputs[0]->incfg.formats); } static int config_inputx(AVFilterLink *inlink) @@ -352,7 +354,8 @@ } for (p = 0; p < s->nb_planes; p++) { - s->lut[p] = av_malloc_array(1 << s->depth, sizeof(uint16_t)); + if (!s->lut[p]) + s->lut[p] = av_malloc_array(1 << s->depth, sizeof(uint16_t)); if (!s->lut[p]) return AVERROR(ENOMEM); } @@ -542,6 +545,17 @@ { NULL } }; +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_output(ctx->outputs[0]); +} + #define lut2_options options FRAMESYNC_DEFINE_CLASS(lut2, LUT2Context, fs); @@ -559,6 +573,7 @@ .outputs = outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; #if CONFIG_TLUT2_FILTER @@ -609,10 +624,10 @@ } static const AVOption tlut2_options[] = { - { "c0", "set component #0 expression", OFFSET(comp_expr_str[0]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = FLAGS }, - { "c1", "set component #1 expression", OFFSET(comp_expr_str[1]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = FLAGS }, - { "c2", "set component #2 expression", OFFSET(comp_expr_str[2]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = FLAGS }, - { "c3", "set component #3 expression", OFFSET(comp_expr_str[3]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = FLAGS }, + { "c0", "set component #0 expression", OFFSET(comp_expr_str[0]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS }, + { "c1", "set component #1 expression", OFFSET(comp_expr_str[1]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS }, + { "c2", "set component #2 expression", OFFSET(comp_expr_str[2]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS }, + { "c3", "set component #3 expression", OFFSET(comp_expr_str[3]), AV_OPT_TYPE_STRING, { .str = "x" }, .flags = TFLAGS }, { NULL } }; @@ -649,6 +664,7 @@ .outputs = tlut2_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; #endif diff -Nru ffmpeg-4.2.2/libavfilter/vf_lut3d.c ffmpeg-4.4/libavfilter/vf_lut3d.c --- ffmpeg-4.2.2/libavfilter/vf_lut3d.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_lut3d.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,9 +24,12 @@ * 3D Lookup table filter */ +#include "float.h" + #include "libavutil/opt.h" #include "libavutil/file.h" #include "libavutil/intreadwrite.h" +#include "libavutil/intfloat.h" #include "libavutil/avassert.h" #include "libavutil/pixdesc.h" #include "libavutil/avstring.h" @@ -46,6 +49,8 @@ INTERPOLATE_NEAREST, INTERPOLATE_TRILINEAR, INTERPOLATE_TETRAHEDRAL, + INTERPOLATE_PYRAMID, + INTERPOLATE_PRISM, NB_INTERP_MODE }; @@ -55,7 +60,16 @@ /* 3D LUT don't often go up to level 32, but it is common to have a Hald CLUT * of 512x512 (64x64x64) */ -#define MAX_LEVEL 128 +#define MAX_LEVEL 256 +#define PRELUT_SIZE 65536 + +typedef struct Lut3DPreLut { + int size; + float min[3]; + float max[3]; + float scale[3]; + float* lut[3]; +} Lut3DPreLut; typedef struct LUT3DContext { const AVClass *class; @@ -65,13 +79,16 @@ int step; avfilter_action_func *interp; struct rgbvec scale; - struct rgbvec lut[MAX_LEVEL][MAX_LEVEL][MAX_LEVEL]; + struct rgbvec *lut; int lutsize; + int lutsize2; + Lut3DPreLut prelut; #if CONFIG_HALDCLUT_FILTER uint8_t clut_rgba_map[4]; int clut_step; int clut_bits; int clut_planar; + int clut_float; int clut_width; FFFrameSync fs; #endif @@ -83,13 +100,40 @@ #define OFFSET(x) offsetof(LUT3DContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM #define COMMON_OPTIONS \ - { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, NB_INTERP_MODE-1, FLAGS, "interp_mode" }, \ - { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_NEAREST}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ - { "trilinear", "interpolate values using the 8 points defining a cube", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TRILINEAR}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ - { "tetrahedral", "interpolate values using a tetrahedron", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TETRAHEDRAL}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ + { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, NB_INTERP_MODE-1, TFLAGS, "interp_mode" }, \ + { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_NEAREST}, 0, 0, TFLAGS, "interp_mode" }, \ + { "trilinear", "interpolate values using the 8 points defining a cube", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TRILINEAR}, 0, 0, TFLAGS, "interp_mode" }, \ + { "tetrahedral", "interpolate values using a tetrahedron", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TETRAHEDRAL}, 0, 0, TFLAGS, "interp_mode" }, \ + { "pyramid", "interpolate values using a pyramid", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PYRAMID}, 0, 0, TFLAGS, "interp_mode" }, \ + { "prism", "interpolate values using a prism", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PRISM}, 0, 0, TFLAGS, "interp_mode" }, \ { NULL } +#define EXPONENT_MASK 0x7F800000 +#define MANTISSA_MASK 0x007FFFFF +#define SIGN_MASK 0x80000000 + +static inline float sanitizef(float f) +{ + union av_intfloat32 t; + t.f = f; + + if ((t.i & EXPONENT_MASK) == EXPONENT_MASK) { + if ((t.i & MANTISSA_MASK) != 0) { + // NAN + return 0.0f; + } else if (t.i & SIGN_MASK) { + // -INF + return -FLT_MAX; + } else { + // +INF + return FLT_MAX; + } + } + return f; +} + static inline float lerpf(float v0, float v1, float f) { return v0 + (v1 - v0) * f; @@ -113,7 +157,7 @@ static inline struct rgbvec interp_nearest(const LUT3DContext *lut3d, const struct rgbvec *s) { - return lut3d->lut[NEAR(s->r)][NEAR(s->g)][NEAR(s->b)]; + return lut3d->lut[NEAR(s->r) * lut3d->lutsize2 + NEAR(s->g) * lut3d->lutsize + NEAR(s->b)]; } /** @@ -123,17 +167,19 @@ static inline struct rgbvec interp_trilinear(const LUT3DContext *lut3d, const struct rgbvec *s) { + const int lutsize2 = lut3d->lutsize2; + const int lutsize = lut3d->lutsize; const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)}; const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)}; const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]}; - const struct rgbvec c000 = lut3d->lut[prev[0]][prev[1]][prev[2]]; - const struct rgbvec c001 = lut3d->lut[prev[0]][prev[1]][next[2]]; - const struct rgbvec c010 = lut3d->lut[prev[0]][next[1]][prev[2]]; - const struct rgbvec c011 = lut3d->lut[prev[0]][next[1]][next[2]]; - const struct rgbvec c100 = lut3d->lut[next[0]][prev[1]][prev[2]]; - const struct rgbvec c101 = lut3d->lut[next[0]][prev[1]][next[2]]; - const struct rgbvec c110 = lut3d->lut[next[0]][next[1]][prev[2]]; - const struct rgbvec c111 = lut3d->lut[next[0]][next[1]][next[2]]; + const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]]; + const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]]; + const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]]; + const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]]; const struct rgbvec c00 = lerp(&c000, &c100, d.r); const struct rgbvec c10 = lerp(&c010, &c110, d.r); const struct rgbvec c01 = lerp(&c001, &c101, d.r); @@ -144,6 +190,101 @@ return c; } +static inline struct rgbvec interp_pyramid(const LUT3DContext *lut3d, + const struct rgbvec *s) +{ + const int lutsize2 = lut3d->lutsize2; + const int lutsize = lut3d->lutsize; + const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)}; + const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)}; + const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]}; + const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]]; + struct rgbvec c; + + if (d.g > d.r && d.b > d.r) { + const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]]; + const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]]; + + c.r = c000.r + (c111.r - c011.r) * d.r + (c010.r - c000.r) * d.g + (c001.r - c000.r) * d.b + + (c011.r - c001.r - c010.r + c000.r) * d.g * d.b; + c.g = c000.g + (c111.g - c011.g) * d.r + (c010.g - c000.g) * d.g + (c001.g - c000.g) * d.b + + (c011.g - c001.g - c010.g + c000.g) * d.g * d.b; + c.b = c000.b + (c111.b - c011.b) * d.r + (c010.b - c000.b) * d.g + (c001.b - c000.b) * d.b + + (c011.b - c001.b - c010.b + c000.b) * d.g * d.b; + } else if (d.r > d.g && d.b > d.g) { + const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]]; + const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]]; + + c.r = c000.r + (c100.r - c000.r) * d.r + (c111.r - c101.r) * d.g + (c001.r - c000.r) * d.b + + (c101.r - c001.r - c100.r + c000.r) * d.r * d.b; + c.g = c000.g + (c100.g - c000.g) * d.r + (c111.g - c101.g) * d.g + (c001.g - c000.g) * d.b + + (c101.g - c001.g - c100.g + c000.g) * d.r * d.b; + c.b = c000.b + (c100.b - c000.b) * d.r + (c111.b - c101.b) * d.g + (c001.b - c000.b) * d.b + + (c101.b - c001.b - c100.b + c000.b) * d.r * d.b; + } else { + const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + + c.r = c000.r + (c100.r - c000.r) * d.r + (c010.r - c000.r) * d.g + (c111.r - c110.r) * d.b + + (c110.r - c100.r - c010.r + c000.r) * d.r * d.g; + c.g = c000.g + (c100.g - c000.g) * d.r + (c010.g - c000.g) * d.g + (c111.g - c110.g) * d.b + + (c110.g - c100.g - c010.g + c000.g) * d.r * d.g; + c.b = c000.b + (c100.b - c000.b) * d.r + (c010.b - c000.b) * d.g + (c111.b - c110.b) * d.b + + (c110.b - c100.b - c010.b + c000.b) * d.r * d.g; + } + + return c; +} + +static inline struct rgbvec interp_prism(const LUT3DContext *lut3d, + const struct rgbvec *s) +{ + const int lutsize2 = lut3d->lutsize2; + const int lutsize = lut3d->lutsize; + const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)}; + const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)}; + const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]}; + const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]]; + const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]]; + struct rgbvec c; + + if (d.b > d.r) { + const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]]; + const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]]; + + c.r = c000.r + (c001.r - c000.r) * d.b + (c101.r - c001.r) * d.r + (c010.r - c000.r) * d.g + + (c000.r - c010.r - c001.r + c011.r) * d.b * d.g + + (c001.r - c011.r - c101.r + c111.r) * d.r * d.g; + c.g = c000.g + (c001.g - c000.g) * d.b + (c101.g - c001.g) * d.r + (c010.g - c000.g) * d.g + + (c000.g - c010.g - c001.g + c011.g) * d.b * d.g + + (c001.g - c011.g - c101.g + c111.g) * d.r * d.g; + c.b = c000.b + (c001.b - c000.b) * d.b + (c101.b - c001.b) * d.r + (c010.b - c000.b) * d.g + + (c000.b - c010.b - c001.b + c011.b) * d.b * d.g + + (c001.b - c011.b - c101.b + c111.b) * d.r * d.g; + } else { + const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + + c.r = c000.r + (c101.r - c100.r) * d.b + (c100.r - c000.r) * d.r + (c010.r - c000.r) * d.g + + (c100.r - c110.r - c101.r + c111.r) * d.b * d.g + + (c000.r - c010.r - c100.r + c110.r) * d.r * d.g; + c.g = c000.g + (c101.g - c100.g) * d.b + (c100.g - c000.g) * d.r + (c010.g - c000.g) * d.g + + (c100.g - c110.g - c101.g + c111.g) * d.b * d.g + + (c000.g - c010.g - c100.g + c110.g) * d.r * d.g; + c.b = c000.b + (c101.b - c100.b) * d.b + (c100.b - c000.b) * d.r + (c010.b - c000.b) * d.g + + (c100.b - c110.b - c101.b + c111.b) * d.b * d.g + + (c000.b - c010.b - c100.b + c110.b) * d.r * d.g; + } + + return c; +} + /** * Tetrahedral interpolation. Based on code found in Truelight Software Library paper. * @see http://www.filmlight.ltd.uk/pdf/whitepapers/FL-TL-TN-0057-SoftwareLib.pdf @@ -151,48 +292,50 @@ static inline struct rgbvec interp_tetrahedral(const LUT3DContext *lut3d, const struct rgbvec *s) { + const int lutsize2 = lut3d->lutsize2; + const int lutsize = lut3d->lutsize; const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)}; const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)}; const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]}; - const struct rgbvec c000 = lut3d->lut[prev[0]][prev[1]][prev[2]]; - const struct rgbvec c111 = lut3d->lut[next[0]][next[1]][next[2]]; + const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]]; struct rgbvec c; if (d.r > d.g) { if (d.g > d.b) { - const struct rgbvec c100 = lut3d->lut[next[0]][prev[1]][prev[2]]; - const struct rgbvec c110 = lut3d->lut[next[0]][next[1]][prev[2]]; + const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]]; c.r = (1-d.r) * c000.r + (d.r-d.g) * c100.r + (d.g-d.b) * c110.r + (d.b) * c111.r; c.g = (1-d.r) * c000.g + (d.r-d.g) * c100.g + (d.g-d.b) * c110.g + (d.b) * c111.g; c.b = (1-d.r) * c000.b + (d.r-d.g) * c100.b + (d.g-d.b) * c110.b + (d.b) * c111.b; } else if (d.r > d.b) { - const struct rgbvec c100 = lut3d->lut[next[0]][prev[1]][prev[2]]; - const struct rgbvec c101 = lut3d->lut[next[0]][prev[1]][next[2]]; + const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]]; c.r = (1-d.r) * c000.r + (d.r-d.b) * c100.r + (d.b-d.g) * c101.r + (d.g) * c111.r; c.g = (1-d.r) * c000.g + (d.r-d.b) * c100.g + (d.b-d.g) * c101.g + (d.g) * c111.g; c.b = (1-d.r) * c000.b + (d.r-d.b) * c100.b + (d.b-d.g) * c101.b + (d.g) * c111.b; } else { - const struct rgbvec c001 = lut3d->lut[prev[0]][prev[1]][next[2]]; - const struct rgbvec c101 = lut3d->lut[next[0]][prev[1]][next[2]]; + const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]]; + const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]]; c.r = (1-d.b) * c000.r + (d.b-d.r) * c001.r + (d.r-d.g) * c101.r + (d.g) * c111.r; c.g = (1-d.b) * c000.g + (d.b-d.r) * c001.g + (d.r-d.g) * c101.g + (d.g) * c111.g; c.b = (1-d.b) * c000.b + (d.b-d.r) * c001.b + (d.r-d.g) * c101.b + (d.g) * c111.b; } } else { if (d.b > d.g) { - const struct rgbvec c001 = lut3d->lut[prev[0]][prev[1]][next[2]]; - const struct rgbvec c011 = lut3d->lut[prev[0]][next[1]][next[2]]; + const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]]; + const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]]; c.r = (1-d.b) * c000.r + (d.b-d.g) * c001.r + (d.g-d.r) * c011.r + (d.r) * c111.r; c.g = (1-d.b) * c000.g + (d.b-d.g) * c001.g + (d.g-d.r) * c011.g + (d.r) * c111.g; c.b = (1-d.b) * c000.b + (d.b-d.g) * c001.b + (d.g-d.r) * c011.b + (d.r) * c111.b; } else if (d.b > d.r) { - const struct rgbvec c010 = lut3d->lut[prev[0]][next[1]][prev[2]]; - const struct rgbvec c011 = lut3d->lut[prev[0]][next[1]][next[2]]; + const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]]; c.r = (1-d.g) * c000.r + (d.g-d.b) * c010.r + (d.b-d.r) * c011.r + (d.r) * c111.r; c.g = (1-d.g) * c000.g + (d.g-d.b) * c010.g + (d.b-d.r) * c011.g + (d.r) * c111.g; c.b = (1-d.g) * c000.b + (d.g-d.b) * c010.b + (d.b-d.r) * c011.b + (d.r) * c111.b; } else { - const struct rgbvec c010 = lut3d->lut[prev[0]][next[1]][prev[2]]; - const struct rgbvec c110 = lut3d->lut[next[0]][next[1]][prev[2]]; + const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]]; c.r = (1-d.g) * c000.r + (d.g-d.r) * c010.r + (d.r-d.b) * c110.r + (d.b) * c111.r; c.g = (1-d.g) * c000.g + (d.g-d.r) * c010.g + (d.r-d.b) * c110.g + (d.b) * c111.g; c.b = (1-d.g) * c000.b + (d.g-d.r) * c010.b + (d.r-d.b) * c110.b + (d.b) * c111.b; @@ -201,11 +344,40 @@ return c; } +static inline float prelut_interp_1d_linear(const Lut3DPreLut *prelut, + int idx, const float s) +{ + const int lut_max = prelut->size - 1; + const float scaled = (s - prelut->min[idx]) * prelut->scale[idx]; + const float x = av_clipf(scaled, 0.0f, lut_max); + const int prev = PREV(x); + const int next = FFMIN((int)(x) + 1, lut_max); + const float p = prelut->lut[idx][prev]; + const float n = prelut->lut[idx][next]; + const float d = x - (float)prev; + return lerpf(p, n, d); +} + +static inline struct rgbvec apply_prelut(const Lut3DPreLut *prelut, + const struct rgbvec *s) +{ + struct rgbvec c; + + if (prelut->size <= 0) + return *s; + + c.r = prelut_interp_1d_linear(prelut, 0, s->r); + c.g = prelut_interp_1d_linear(prelut, 1, s->g); + c.b = prelut_interp_1d_linear(prelut, 2, s->b); + return c; +} + #define DEFINE_INTERP_FUNC_PLANAR(name, nbits, depth) \ static int interp_##nbits##_##name##_p##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ { \ int x, y; \ const LUT3DContext *lut3d = ctx->priv; \ + const Lut3DPreLut *prelut = &lut3d->prelut; \ const ThreadData *td = arg; \ const AVFrame *in = td->in; \ const AVFrame *out = td->out; \ @@ -220,9 +392,11 @@ const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \ const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \ const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \ - const float scale_r = (lut3d->scale.r / ((1<lutsize - 1); \ - const float scale_g = (lut3d->scale.g / ((1<lutsize - 1); \ - const float scale_b = (lut3d->scale.b / ((1<lutsize - 1); \ + const float lut_max = lut3d->lutsize - 1; \ + const float scale_f = 1.0f / ((1<scale.r * lut_max; \ + const float scale_g = lut3d->scale.g * lut_max; \ + const float scale_b = lut3d->scale.b * lut_max; \ \ for (y = slice_start; y < slice_end; y++) { \ uint##nbits##_t *dstg = (uint##nbits##_t *)grow; \ @@ -234,9 +408,13 @@ const uint##nbits##_t *srcr = (const uint##nbits##_t *)srcrrow; \ const uint##nbits##_t *srca = (const uint##nbits##_t *)srcarow; \ for (x = 0; x < in->width; x++) { \ - const struct rgbvec scaled_rgb = {srcr[x] * scale_r, \ - srcg[x] * scale_g, \ - srcb[x] * scale_b}; \ + const struct rgbvec rgb = {srcr[x] * scale_f, \ + srcg[x] * scale_f, \ + srcb[x] * scale_f}; \ + const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \ + const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \ + av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \ + av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \ struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \ dstr[x] = av_clip_uintp2(vec.r * (float)((1<priv; \ + const Lut3DPreLut *prelut = &lut3d->prelut; \ + const ThreadData *td = arg; \ + const AVFrame *in = td->in; \ + const AVFrame *out = td->out; \ + const int direct = out == in; \ + const int slice_start = (in->height * jobnr ) / nb_jobs; \ + const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \ + uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \ + uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \ + uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \ + uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \ + const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \ + const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \ + const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \ + const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \ + const float lut_max = lut3d->lutsize - 1; \ + const float scale_r = lut3d->scale.r * lut_max; \ + const float scale_g = lut3d->scale.g * lut_max; \ + const float scale_b = lut3d->scale.b * lut_max; \ + \ + for (y = slice_start; y < slice_end; y++) { \ + float *dstg = (float *)grow; \ + float *dstb = (float *)brow; \ + float *dstr = (float *)rrow; \ + float *dsta = (float *)arow; \ + const float *srcg = (const float *)srcgrow; \ + const float *srcb = (const float *)srcbrow; \ + const float *srcr = (const float *)srcrrow; \ + const float *srca = (const float *)srcarow; \ + for (x = 0; x < in->width; x++) { \ + const struct rgbvec rgb = {sanitizef(srcr[x]), \ + sanitizef(srcg[x]), \ + sanitizef(srcb[x])}; \ + const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \ + const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \ + av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \ + av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \ + struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \ + dstr[x] = vec.r; \ + dstg[x] = vec.g; \ + dstb[x] = vec.b; \ + if (!direct && in->linesize[3]) \ + dsta[x] = srca[x]; \ + } \ + grow += out->linesize[0]; \ + brow += out->linesize[1]; \ + rrow += out->linesize[2]; \ + arow += out->linesize[3]; \ + srcgrow += in->linesize[0]; \ + srcbrow += in->linesize[1]; \ + srcrrow += in->linesize[2]; \ + srcarow += in->linesize[3]; \ + } \ + return 0; \ +} + +DEFINE_INTERP_FUNC_PLANAR_FLOAT(nearest, 32) +DEFINE_INTERP_FUNC_PLANAR_FLOAT(trilinear, 32) +DEFINE_INTERP_FUNC_PLANAR_FLOAT(tetrahedral, 32) +DEFINE_INTERP_FUNC_PLANAR_FLOAT(pyramid, 32) +DEFINE_INTERP_FUNC_PLANAR_FLOAT(prism, 32) #define DEFINE_INTERP_FUNC(name, nbits) \ static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ { \ int x, y; \ const LUT3DContext *lut3d = ctx->priv; \ + const Lut3DPreLut *prelut = &lut3d->prelut; \ const ThreadData *td = arg; \ const AVFrame *in = td->in; \ const AVFrame *out = td->out; \ @@ -298,17 +556,23 @@ const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \ uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \ const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \ - const float scale_r = (lut3d->scale.r / ((1<lutsize - 1); \ - const float scale_g = (lut3d->scale.g / ((1<lutsize - 1); \ - const float scale_b = (lut3d->scale.b / ((1<lutsize - 1); \ + const float lut_max = lut3d->lutsize - 1; \ + const float scale_f = 1.0f / ((1<scale.r * lut_max; \ + const float scale_g = lut3d->scale.g * lut_max; \ + const float scale_b = lut3d->scale.b * lut_max; \ \ for (y = slice_start; y < slice_end; y++) { \ uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \ const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \ for (x = 0; x < in->width * step; x += step) { \ - const struct rgbvec scaled_rgb = {src[x + r] * scale_r, \ - src[x + g] * scale_g, \ - src[x + b] * scale_b}; \ + const struct rgbvec rgb = {src[x + r] * scale_f, \ + src[x + g] * scale_f, \ + src[x + b] * scale_f}; \ + const struct rgbvec prelut_rgb = apply_prelut(prelut, &rgb); \ + const struct rgbvec scaled_rgb = {av_clipf(prelut_rgb.r * scale_r, 0, lut_max), \ + av_clipf(prelut_rgb.g * scale_g, 0, lut_max), \ + av_clipf(prelut_rgb.b * scale_b, 0, lut_max)}; \ struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \ dst[x + r] = av_clip_uint##nbits(vec.r * (float)((1< 0; max--) { + if ((c = fgetc(f)) == EOF) + break; + + if (av_isspace(c)) + break; + + *p++ = c; + } + + *p = 0; + if (p == dst) + return NULL; + return p; +} + #define NEXT_LINE(loop_cond) do { \ if (!fgets(line, sizeof(line), f)) { \ av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n"); \ @@ -346,30 +648,73 @@ } \ } while (loop_cond) +#define NEXT_LINE_OR_GOTO(loop_cond, label) do { \ + if (!fgets(line, sizeof(line), f)) { \ + av_log(ctx, AV_LOG_ERROR, "Unexpected EOF\n"); \ + ret = AVERROR_INVALIDDATA; \ + goto label; \ + } \ +} while (loop_cond) + +static int allocate_3dlut(AVFilterContext *ctx, int lutsize, int prelut) +{ + LUT3DContext *lut3d = ctx->priv; + int i; + if (lutsize < 2 || lutsize > MAX_LEVEL) { + av_log(ctx, AV_LOG_ERROR, "Too large or invalid 3D LUT size\n"); + return AVERROR(EINVAL); + } + + av_freep(&lut3d->lut); + lut3d->lut = av_malloc_array(lutsize * lutsize * lutsize, sizeof(*lut3d->lut)); + if (!lut3d->lut) + return AVERROR(ENOMEM); + + if (prelut) { + lut3d->prelut.size = PRELUT_SIZE; + for (i = 0; i < 3; i++) { + av_freep(&lut3d->prelut.lut[i]); + lut3d->prelut.lut[i] = av_malloc_array(PRELUT_SIZE, sizeof(*lut3d->prelut.lut[0])); + if (!lut3d->prelut.lut[i]) + return AVERROR(ENOMEM); + } + } else { + lut3d->prelut.size = 0; + for (i = 0; i < 3; i++) { + av_freep(&lut3d->prelut.lut[i]); + } + } + lut3d->lutsize = lutsize; + lut3d->lutsize2 = lutsize * lutsize; + return 0; +} + /* Basically r g and b float values on each line, with a facultative 3DLUTSIZE * directive; seems to be generated by Davinci */ static int parse_dat(AVFilterContext *ctx, FILE *f) { LUT3DContext *lut3d = ctx->priv; char line[MAX_LINE_SIZE]; - int i, j, k, size; + int ret, i, j, k, size, size2; lut3d->lutsize = size = 33; + size2 = size * size; NEXT_LINE(skip_line(line)); if (!strncmp(line, "3DLUTSIZE ", 10)) { size = strtol(line + 10, NULL, 0); - if (size < 2 || size > MAX_LEVEL) { - av_log(ctx, AV_LOG_ERROR, "Too large or invalid 3D LUT size\n"); - return AVERROR(EINVAL); - } - lut3d->lutsize = size; + NEXT_LINE(skip_line(line)); } + + ret = allocate_3dlut(ctx, size, 0); + if (ret < 0) + return ret; + for (k = 0; k < size; k++) { for (j = 0; j < size; j++) { for (i = 0; i < size; i++) { - struct rgbvec *vec = &lut3d->lut[k][j][i]; + struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i]; if (k != 0 || j != 0 || i != 0) NEXT_LINE(skip_line(line)); if (av_sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3) @@ -390,18 +735,18 @@ while (fgets(line, sizeof(line), f)) { if (!strncmp(line, "LUT_3D_SIZE", 11)) { - int i, j, k; + int ret, i, j, k; const int size = strtol(line + 12, NULL, 0); + const int size2 = size * size; + + ret = allocate_3dlut(ctx, size, 0); + if (ret < 0) + return ret; - if (size < 2 || size > MAX_LEVEL) { - av_log(ctx, AV_LOG_ERROR, "Too large or invalid 3D LUT size\n"); - return AVERROR(EINVAL); - } - lut3d->lutsize = size; for (k = 0; k < size; k++) { for (j = 0; j < size; j++) { for (i = 0; i < size; i++) { - struct rgbvec *vec = &lut3d->lut[i][j][k]; + struct rgbvec *vec = &lut3d->lut[i * size2 + j * size + k]; do { try_again: @@ -442,17 +787,23 @@ { char line[MAX_LINE_SIZE]; LUT3DContext *lut3d = ctx->priv; - int i, j, k; + int ret, i, j, k; const int size = 17; + const int size2 = 17 * 17; const float scale = 16*16*16; lut3d->lutsize = size; + + ret = allocate_3dlut(ctx, size, 0); + if (ret < 0) + return ret; + NEXT_LINE(skip_line(line)); for (k = 0; k < size; k++) { for (j = 0; j < size; j++) { for (i = 0; i < size; i++) { int r, g, b; - struct rgbvec *vec = &lut3d->lut[k][j][i]; + struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i]; NEXT_LINE(skip_line(line)); if (av_sscanf(line, "%d %d %d", &r, &g, &b) != 3) @@ -471,7 +822,7 @@ { LUT3DContext *lut3d = ctx->priv; float scale; - int i, j, k, size, in = -1, out = -1; + int ret, i, j, k, size, size2, in = -1, out = -1; char line[MAX_LINE_SIZE]; uint8_t rgb_map[3] = {0, 1, 2}; @@ -510,12 +861,18 @@ } for (size = 1; size*size*size < in; size++); lut3d->lutsize = size; + size2 = size * size; + + ret = allocate_3dlut(ctx, size, 0); + if (ret < 0) + return ret; + scale = 1. / (out - 1); for (k = 0; k < size; k++) { for (j = 0; j < size; j++) { for (i = 0; i < size; i++) { - struct rgbvec *vec = &lut3d->lut[k][j][i]; + struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i]; float val[3]; NEXT_LINE(0); @@ -530,6 +887,44 @@ return 0; } +static int nearest_sample_index(float *data, float x, int low, int hi) +{ + int mid; + if (x < data[low]) + return low; + + if (x > data[hi]) + return hi; + + for (;;) { + av_assert0(x >= data[low]); + av_assert0(x <= data[hi]); + av_assert0((hi-low) > 0); + + if (hi - low == 1) + return low; + + mid = (low + hi) / 2; + + if (x < data[mid]) + hi = mid; + else + low = mid; + } + + return 0; +} + +#define NEXT_FLOAT_OR_GOTO(value, label) \ + if (!fget_next_word(line, sizeof(line) ,f)) { \ + ret = AVERROR_INVALIDDATA; \ + goto label; \ + } \ + if (av_sscanf(line, "%f", &value) != 1) { \ + ret = AVERROR_INVALIDDATA; \ + goto label; \ + } + static int parse_cinespace(AVFilterContext *ctx, FILE *f) { LUT3DContext *lut3d = ctx->priv; @@ -538,22 +933,30 @@ float in_max[3] = {1.0, 1.0, 1.0}; float out_min[3] = {0.0, 0.0, 0.0}; float out_max[3] = {1.0, 1.0, 1.0}; - int inside_metadata = 0, size; + int inside_metadata = 0, size, size2; + int prelut = 0; + int ret = 0; + + int prelut_sizes[3] = {0, 0, 0}; + float *in_prelut[3] = {NULL, NULL, NULL}; + float *out_prelut[3] = {NULL, NULL, NULL}; - NEXT_LINE(skip_line(line)); + NEXT_LINE_OR_GOTO(skip_line(line), end); if (strncmp(line, "CSPLUTV100", 10)) { av_log(ctx, AV_LOG_ERROR, "Not cineSpace LUT format\n"); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto end; } - NEXT_LINE(skip_line(line)); + NEXT_LINE_OR_GOTO(skip_line(line), end); if (strncmp(line, "3D", 2)) { av_log(ctx, AV_LOG_ERROR, "Not 3D LUT format\n"); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto end; } while (1) { - NEXT_LINE(skip_line(line)); + NEXT_LINE_OR_GOTO(skip_line(line), end); if (!strncmp(line, "BEGIN METADATA", 14)) { inside_metadata = 1; @@ -569,43 +972,106 @@ for (int i = 0; i < 3; i++) { int npoints = strtol(line, NULL, 0); - if (npoints != 2) { + if (npoints > 2) { + float v,last; + + if (npoints > PRELUT_SIZE) { + av_log(ctx, AV_LOG_ERROR, "Prelut size too large.\n"); + ret = AVERROR_INVALIDDATA; + goto end; + } + + if (in_prelut[i] || out_prelut[i]) { + av_log(ctx, AV_LOG_ERROR, "Invalid file has multiple preluts.\n"); + ret = AVERROR_INVALIDDATA; + goto end; + } + + in_prelut[i] = (float*)av_malloc(npoints * sizeof(float)); + out_prelut[i] = (float*)av_malloc(npoints * sizeof(float)); + if (!in_prelut[i] || !out_prelut[i]) { + ret = AVERROR(ENOMEM); + goto end; + } + + prelut_sizes[i] = npoints; + in_min[i] = FLT_MAX; + in_max[i] = -FLT_MAX; + out_min[i] = FLT_MAX; + out_max[i] = -FLT_MAX; + + for (int j = 0; j < npoints; j++) { + NEXT_FLOAT_OR_GOTO(v, end) + in_min[i] = FFMIN(in_min[i], v); + in_max[i] = FFMAX(in_max[i], v); + in_prelut[i][j] = v; + if (j > 0 && v < last) { + av_log(ctx, AV_LOG_ERROR, "Invalid file, non increasing prelut.\n"); + ret = AVERROR(ENOMEM); + goto end; + } + last = v; + } + + for (int j = 0; j < npoints; j++) { + NEXT_FLOAT_OR_GOTO(v, end) + out_min[i] = FFMIN(out_min[i], v); + out_max[i] = FFMAX(out_max[i], v); + out_prelut[i][j] = v; + } + + } else if (npoints == 2) { + NEXT_LINE_OR_GOTO(skip_line(line), end); + if (av_sscanf(line, "%f %f", &in_min[i], &in_max[i]) != 2) { + ret = AVERROR_INVALIDDATA; + goto end; + } + NEXT_LINE_OR_GOTO(skip_line(line), end); + if (av_sscanf(line, "%f %f", &out_min[i], &out_max[i]) != 2) { + ret = AVERROR_INVALIDDATA; + goto end; + } + + } else { av_log(ctx, AV_LOG_ERROR, "Unsupported number of pre-lut points.\n"); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto end; } - NEXT_LINE(skip_line(line)); - if (av_sscanf(line, "%f %f", &in_min[i], &in_max[i]) != 2) - return AVERROR_INVALIDDATA; - NEXT_LINE(skip_line(line)); - if (av_sscanf(line, "%f %f", &out_min[i], &out_max[i]) != 2) - return AVERROR_INVALIDDATA; - NEXT_LINE(skip_line(line)); + NEXT_LINE_OR_GOTO(skip_line(line), end); } - if (av_sscanf(line, "%d %d %d", &size_r, &size_g, &size_b) != 3) - return AVERROR(EINVAL); + if (av_sscanf(line, "%d %d %d", &size_r, &size_g, &size_b) != 3) { + ret = AVERROR(EINVAL); + goto end; + } if (size_r != size_g || size_r != size_b) { av_log(ctx, AV_LOG_ERROR, "Unsupported size combination: %dx%dx%d.\n", size_r, size_g, size_b); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto end; } size = size_r; - if (size < 2 || size > MAX_LEVEL) { - av_log(ctx, AV_LOG_ERROR, "Too large or invalid 3D LUT size\n"); - return AVERROR(EINVAL); - } + size2 = size * size; - lut3d->lutsize = size; + if (prelut_sizes[0] && prelut_sizes[1] && prelut_sizes[2]) + prelut = 1; + + ret = allocate_3dlut(ctx, size, prelut); + if (ret < 0) + return ret; for (int k = 0; k < size; k++) { for (int j = 0; j < size; j++) { for (int i = 0; i < size; i++) { - struct rgbvec *vec = &lut3d->lut[i][j][k]; - if (k != 0 || j != 0 || i != 0) - NEXT_LINE(skip_line(line)); - if (av_sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3) - return AVERROR_INVALIDDATA; + struct rgbvec *vec = &lut3d->lut[i * size2 + j * size + k]; + + NEXT_LINE_OR_GOTO(skip_line(line), end); + if (av_sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3) { + ret = AVERROR_INVALIDDATA; + goto end; + } + vec->r *= out_max[0] - out_min[0]; vec->g *= out_max[1] - out_min[1]; vec->b *= out_max[2] - out_min[2]; @@ -617,29 +1083,68 @@ } } - lut3d->scale.r = av_clipf(1. / (in_max[0] - in_min[0]), 0.f, 1.f); - lut3d->scale.g = av_clipf(1. / (in_max[1] - in_min[1]), 0.f, 1.f); - lut3d->scale.b = av_clipf(1. / (in_max[2] - in_min[2]), 0.f, 1.f); + if (prelut) { + for (int c = 0; c < 3; c++) { - return 0; + lut3d->prelut.min[c] = in_min[c]; + lut3d->prelut.max[c] = in_max[c]; + lut3d->prelut.scale[c] = (1.0f / (float)(in_max[c] - in_min[c])) * (lut3d->prelut.size - 1); + + for (int i = 0; i < lut3d->prelut.size; ++i) { + float mix = (float) i / (float)(lut3d->prelut.size - 1); + float x = lerpf(in_min[c], in_max[c], mix), a, b; + + int idx = nearest_sample_index(in_prelut[c], x, 0, prelut_sizes[c]-1); + av_assert0(idx + 1 < prelut_sizes[c]); + + a = out_prelut[c][idx + 0]; + b = out_prelut[c][idx + 1]; + mix = x - in_prelut[c][idx]; + + lut3d->prelut.lut[c][i] = sanitizef(lerpf(a, b, mix)); + } + } + lut3d->scale.r = 1.00f; + lut3d->scale.g = 1.00f; + lut3d->scale.b = 1.00f; + + } else { + lut3d->scale.r = av_clipf(1. / (in_max[0] - in_min[0]), 0.f, 1.f); + lut3d->scale.g = av_clipf(1. / (in_max[1] - in_min[1]), 0.f, 1.f); + lut3d->scale.b = av_clipf(1. / (in_max[2] - in_min[2]), 0.f, 1.f); + } + +end: + for (int c = 0; c < 3; c++) { + av_freep(&in_prelut[c]); + av_freep(&out_prelut[c]); + } + return ret; } -static void set_identity_matrix(LUT3DContext *lut3d, int size) +static int set_identity_matrix(AVFilterContext *ctx, int size) { - int i, j, k; + LUT3DContext *lut3d = ctx->priv; + int ret, i, j, k; + const int size2 = size * size; const float c = 1. / (size - 1); - lut3d->lutsize = size; + ret = allocate_3dlut(ctx, size, 0); + if (ret < 0) + return ret; + for (k = 0; k < size; k++) { for (j = 0; j < size; j++) { for (i = 0; i < size; i++) { - struct rgbvec *vec = &lut3d->lut[k][j][i]; + struct rgbvec *vec = &lut3d->lut[k * size2 + j * size + i]; vec->r = k * c; vec->g = j * c; vec->b = i * c; } } } + + return 0; } static int query_formats(AVFilterContext *ctx) @@ -657,7 +1162,8 @@ AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRP14, - AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_NONE }; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); @@ -668,39 +1174,19 @@ static int config_input(AVFilterLink *inlink) { - int depth, is16bit = 0, planar = 0; + int depth, is16bit, isfloat, planar; LUT3DContext *lut3d = inlink->dst->priv; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); depth = desc->comp[0].depth; - - switch (inlink->format) { - case AV_PIX_FMT_RGB48: - case AV_PIX_FMT_BGR48: - case AV_PIX_FMT_RGBA64: - case AV_PIX_FMT_BGRA64: - is16bit = 1; - break; - case AV_PIX_FMT_GBRP9: - case AV_PIX_FMT_GBRP10: - case AV_PIX_FMT_GBRP12: - case AV_PIX_FMT_GBRP14: - case AV_PIX_FMT_GBRP16: - case AV_PIX_FMT_GBRAP10: - case AV_PIX_FMT_GBRAP12: - case AV_PIX_FMT_GBRAP16: - is16bit = 1; - case AV_PIX_FMT_GBRP: - case AV_PIX_FMT_GBRAP: - planar = 1; - break; - } - + is16bit = desc->comp[0].depth > 8; + planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR; + isfloat = desc->flags & AV_PIX_FMT_FLAG_FLOAT; ff_fill_rgba_map(lut3d->rgba_map, inlink->format); lut3d->step = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit); #define SET_FUNC(name) do { \ - if (planar) { \ + if (planar && !isfloat) { \ switch (depth) { \ case 8: lut3d->interp = interp_8_##name##_p8; break; \ case 9: lut3d->interp = interp_16_##name##_p9; break; \ @@ -709,6 +1195,7 @@ case 14: lut3d->interp = interp_16_##name##_p14; break; \ case 16: lut3d->interp = interp_16_##name##_p16; break; \ } \ + } else if (isfloat) { lut3d->interp = interp_##name##_pf32; \ } else if (is16bit) { lut3d->interp = interp_16_##name; \ } else { lut3d->interp = interp_8_##name; } \ } while (0) @@ -717,6 +1204,8 @@ case INTERPOLATE_NEAREST: SET_FUNC(nearest); break; case INTERPOLATE_TRILINEAR: SET_FUNC(trilinear); break; case INTERPOLATE_TETRAHEDRAL: SET_FUNC(tetrahedral); break; + case INTERPOLATE_PYRAMID: SET_FUNC(pyramid); break; + case INTERPOLATE_PRISM: SET_FUNC(prism); break; default: av_assert0(0); } @@ -762,6 +1251,18 @@ 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) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + #if CONFIG_LUT3D_FILTER static const AVOption lut3d_options[] = { { "file", "set 3D LUT file name", OFFSET(file), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS }, @@ -780,11 +1281,10 @@ lut3d->scale.r = lut3d->scale.g = lut3d->scale.b = 1.f; if (!lut3d->file) { - set_identity_matrix(lut3d, 32); - return 0; + return set_identity_matrix(ctx, 32); } - f = fopen(lut3d->file, "r"); + f = av_fopen_utf8(lut3d->file, "r"); if (!f) { ret = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "%s: %s\n", lut3d->file, av_err2str(ret)); @@ -824,6 +1324,17 @@ return ret; } +static av_cold void lut3d_uninit(AVFilterContext *ctx) +{ + LUT3DContext *lut3d = ctx->priv; + int i; + av_freep(&lut3d->lut); + + for (i = 0; i < 3; i++) { + av_freep(&lut3d->prelut.lut[i]); + } +} + static const AVFilterPad lut3d_inputs[] = { { .name = "default", @@ -847,11 +1358,13 @@ .description = NULL_IF_CONFIG_SMALL("Adjust colors using a 3D LUT."), .priv_size = sizeof(LUT3DContext), .init = lut3d_init, + .uninit = lut3d_uninit, .query_formats = query_formats, .inputs = lut3d_inputs, .outputs = lut3d_outputs, .priv_class = &lut3d_class, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; #endif @@ -865,6 +1378,7 @@ const int step = lut3d->clut_step; const uint8_t *rgba_map = lut3d->clut_rgba_map; const int level = lut3d->lutsize; + const int level2 = lut3d->lutsize2; #define LOAD_CLUT(nbits) do { \ int i, j, k, x = 0, y = 0; \ @@ -874,7 +1388,7 @@ for (i = 0; i < level; i++) { \ const uint##nbits##_t *src = (const uint##nbits##_t *) \ (data + y*linesize + x*step); \ - struct rgbvec *vec = &lut3d->lut[i][j][k]; \ + struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \ vec->r = src[rgba_map[0]] / (float)((1<<(nbits)) - 1); \ vec->g = src[rgba_map[1]] / (float)((1<<(nbits)) - 1); \ vec->b = src[rgba_map[2]] / (float)((1<<(nbits)) - 1); \ @@ -903,6 +1417,7 @@ const int rlinesize = frame->linesize[2]; const int w = lut3d->clut_width; const int level = lut3d->lutsize; + const int level2 = lut3d->lutsize2; #define LOAD_CLUT_PLANAR(nbits, depth) do { \ int i, j, k, x = 0, y = 0; \ @@ -916,7 +1431,7 @@ (datab + y*blinesize); \ const uint##nbits##_t *rsrc = (const uint##nbits##_t *) \ (datar + y*rlinesize); \ - struct rgbvec *vec = &lut3d->lut[i][j][k]; \ + struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; \ vec->r = gsrc[x] / (float)((1<<(depth)) - 1); \ vec->g = bsrc[x] / (float)((1<<(depth)) - 1); \ vec->b = rsrc[x] / (float)((1<<(depth)) - 1); \ @@ -939,6 +1454,39 @@ } } +static void update_clut_float(LUT3DContext *lut3d, const AVFrame *frame) +{ + const uint8_t *datag = frame->data[0]; + const uint8_t *datab = frame->data[1]; + const uint8_t *datar = frame->data[2]; + const int glinesize = frame->linesize[0]; + const int blinesize = frame->linesize[1]; + const int rlinesize = frame->linesize[2]; + const int w = lut3d->clut_width; + const int level = lut3d->lutsize; + const int level2 = lut3d->lutsize2; + + int i, j, k, x = 0, y = 0; + + for (k = 0; k < level; k++) { + for (j = 0; j < level; j++) { + for (i = 0; i < level; i++) { + const float *gsrc = (const float *)(datag + y*glinesize); + const float *bsrc = (const float *)(datab + y*blinesize); + const float *rsrc = (const float *)(datar + y*rlinesize); + struct rgbvec *vec = &lut3d->lut[i * level2 + j * level + k]; + vec->r = rsrc[x]; + vec->g = gsrc[x]; + vec->b = bsrc[x]; + if (++x == w) { + x = 0; + y++; + } + } + } + } +} + static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -973,6 +1521,7 @@ lut3d->clut_bits = desc->comp[0].depth; lut3d->clut_planar = av_pix_fmt_count_planes(inlink->format) > 1; + lut3d->clut_float = desc->flags & AV_PIX_FMT_FLAG_FLOAT; lut3d->clut_step = av_get_padded_bits_per_pixel(desc) >> 3; ff_fill_rgba_map(lut3d->clut_rgba_map, inlink->format); @@ -1001,9 +1550,8 @@ max_clut_level, max_clut_size, max_clut_size); return AVERROR(EINVAL); } - lut3d->lutsize = level; - return 0; + return allocate_3dlut(ctx, level, 0); } static int update_apply_clut(FFFrameSync *fs) @@ -1019,7 +1567,9 @@ return ret; if (!second) return ff_filter_frame(ctx->outputs[0], master); - if (lut3d->clut_planar) + if (lut3d->clut_float) + update_clut_float(ctx->priv, second); + else if (lut3d->clut_planar) update_clut_planar(ctx->priv, second); else update_clut_packed(ctx->priv, second); @@ -1039,6 +1589,7 @@ { LUT3DContext *lut3d = ctx->priv; ff_framesync_uninit(&lut3d->fs); + av_freep(&lut3d->lut); } static const AVOption haldclut_options[] = { @@ -1082,6 +1633,7 @@ .outputs = haldclut_outputs, .priv_class = &haldclut_class, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; #endif @@ -1261,13 +1813,13 @@ } static const AVOption lut1d_options[] = { - { "file", "set 1D LUT file name", OFFSET(file), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS }, - { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_1D_LINEAR}, 0, NB_INTERP_1D_MODE-1, FLAGS, "interp_mode" }, - { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_NEAREST}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, - { "linear", "use values from the linear interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_LINEAR}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, - { "cosine", "use values from the cosine interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_COSINE}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, - { "cubic", "use values from the cubic interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_CUBIC}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, - { "spline", "use values from the spline interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_SPLINE}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, + { "file", "set 1D LUT file name", OFFSET(file), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = TFLAGS }, + { "interp", "select interpolation mode", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERPOLATE_1D_LINEAR}, 0, NB_INTERP_1D_MODE-1, TFLAGS, "interp_mode" }, + { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_NEAREST}, 0, 0, TFLAGS, "interp_mode" }, + { "linear", "use values from the linear interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_LINEAR}, 0, 0, TFLAGS, "interp_mode" }, + { "cosine", "use values from the cosine interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_COSINE}, 0, 0, TFLAGS, "interp_mode" }, + { "cubic", "use values from the cubic interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_CUBIC}, 0, 0, TFLAGS, "interp_mode" }, + { "spline", "use values from the spline interpolation", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_1D_SPLINE}, 0, 0, TFLAGS, "interp_mode" }, { NULL } }; @@ -1446,6 +1998,72 @@ DEFINE_INTERP_FUNC_PLANAR_1D(cubic, 16, 16) DEFINE_INTERP_FUNC_PLANAR_1D(spline, 16, 16) +#define DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(name, depth) \ +static int interp_1d_##name##_pf##depth(AVFilterContext *ctx, \ + void *arg, int jobnr, \ + int nb_jobs) \ +{ \ + int x, y; \ + const LUT1DContext *lut1d = ctx->priv; \ + const ThreadData *td = arg; \ + const AVFrame *in = td->in; \ + const AVFrame *out = td->out; \ + const int direct = out == in; \ + const int slice_start = (in->height * jobnr ) / nb_jobs; \ + const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \ + uint8_t *grow = out->data[0] + slice_start * out->linesize[0]; \ + uint8_t *brow = out->data[1] + slice_start * out->linesize[1]; \ + uint8_t *rrow = out->data[2] + slice_start * out->linesize[2]; \ + uint8_t *arow = out->data[3] + slice_start * out->linesize[3]; \ + const uint8_t *srcgrow = in->data[0] + slice_start * in->linesize[0]; \ + const uint8_t *srcbrow = in->data[1] + slice_start * in->linesize[1]; \ + const uint8_t *srcrrow = in->data[2] + slice_start * in->linesize[2]; \ + const uint8_t *srcarow = in->data[3] + slice_start * in->linesize[3]; \ + const float lutsize = lut1d->lutsize - 1; \ + const float scale_r = lut1d->scale.r * lutsize; \ + const float scale_g = lut1d->scale.g * lutsize; \ + const float scale_b = lut1d->scale.b * lutsize; \ + \ + for (y = slice_start; y < slice_end; y++) { \ + float *dstg = (float *)grow; \ + float *dstb = (float *)brow; \ + float *dstr = (float *)rrow; \ + float *dsta = (float *)arow; \ + const float *srcg = (const float *)srcgrow; \ + const float *srcb = (const float *)srcbrow; \ + const float *srcr = (const float *)srcrrow; \ + const float *srca = (const float *)srcarow; \ + for (x = 0; x < in->width; x++) { \ + float r = av_clipf(sanitizef(srcr[x]) * scale_r, 0.0f, lutsize); \ + float g = av_clipf(sanitizef(srcg[x]) * scale_g, 0.0f, lutsize); \ + float b = av_clipf(sanitizef(srcb[x]) * scale_b, 0.0f, lutsize); \ + r = interp_1d_##name(lut1d, 0, r); \ + g = interp_1d_##name(lut1d, 1, g); \ + b = interp_1d_##name(lut1d, 2, b); \ + dstr[x] = r; \ + dstg[x] = g; \ + dstb[x] = b; \ + if (!direct && in->linesize[3]) \ + dsta[x] = srca[x]; \ + } \ + grow += out->linesize[0]; \ + brow += out->linesize[1]; \ + rrow += out->linesize[2]; \ + arow += out->linesize[3]; \ + srcgrow += in->linesize[0]; \ + srcbrow += in->linesize[1]; \ + srcrrow += in->linesize[2]; \ + srcarow += in->linesize[3]; \ + } \ + return 0; \ +} + +DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(nearest, 32) +DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(linear, 32) +DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cosine, 32) +DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(cubic, 32) +DEFINE_INTERP_FUNC_PLANAR_1D_FLOAT(spline, 32) + #define DEFINE_INTERP_FUNC_1D(name, nbits) \ static int interp_1d_##nbits##_##name(AVFilterContext *ctx, void *arg, \ int jobnr, int nb_jobs) \ @@ -1506,39 +2124,19 @@ static int config_input_1d(AVFilterLink *inlink) { - int depth, is16bit = 0, planar = 0; + int depth, is16bit, isfloat, planar; LUT1DContext *lut1d = inlink->dst->priv; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); depth = desc->comp[0].depth; - - switch (inlink->format) { - case AV_PIX_FMT_RGB48: - case AV_PIX_FMT_BGR48: - case AV_PIX_FMT_RGBA64: - case AV_PIX_FMT_BGRA64: - is16bit = 1; - break; - case AV_PIX_FMT_GBRP9: - case AV_PIX_FMT_GBRP10: - case AV_PIX_FMT_GBRP12: - case AV_PIX_FMT_GBRP14: - case AV_PIX_FMT_GBRP16: - case AV_PIX_FMT_GBRAP10: - case AV_PIX_FMT_GBRAP12: - case AV_PIX_FMT_GBRAP16: - is16bit = 1; - case AV_PIX_FMT_GBRP: - case AV_PIX_FMT_GBRAP: - planar = 1; - break; - } - + is16bit = desc->comp[0].depth > 8; + planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR; + isfloat = desc->flags & AV_PIX_FMT_FLAG_FLOAT; ff_fill_rgba_map(lut1d->rgba_map, inlink->format); lut1d->step = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit); #define SET_FUNC_1D(name) do { \ - if (planar) { \ + if (planar && !isfloat) { \ switch (depth) { \ case 8: lut1d->interp = interp_1d_8_##name##_p8; break; \ case 9: lut1d->interp = interp_1d_16_##name##_p9; break; \ @@ -1547,6 +2145,7 @@ case 14: lut1d->interp = interp_1d_16_##name##_p14; break; \ case 16: lut1d->interp = interp_1d_16_##name##_p16; break; \ } \ + } else if (isfloat) { lut1d->interp = interp_1d_##name##_pf32; \ } else if (is16bit) { lut1d->interp = interp_1d_16_##name; \ } else { lut1d->interp = interp_1d_8_##name; } \ } while (0) @@ -1578,7 +2177,7 @@ return 0; } - f = fopen(lut1d->file, "r"); + f = av_fopen_utf8(lut1d->file, "r"); if (!f) { ret = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "%s: %s\n", lut1d->file, av_err2str(ret)); @@ -1650,6 +2249,24 @@ return ff_filter_frame(outlink, out); } +static int lut1d_process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + LUT1DContext *lut1d = ctx->priv; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + ret = lut1d_init(ctx); + if (ret < 0) { + set_identity_matrix_1d(lut1d, 32); + return ret; + } + return config_input_1d(ctx->inputs[0]); +} + static const AVFilterPad lut1d_inputs[] = { { .name = "default", @@ -1678,5 +2295,6 @@ .outputs = lut1d_outputs, .priv_class = &lut1d_class, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = lut1d_process_command, }; #endif diff -Nru ffmpeg-4.2.2/libavfilter/vf_lut.c ffmpeg-4.4/libavfilter/vf_lut.c --- ffmpeg-4.2.2/libavfilter/vf_lut.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_lut.c 2021-04-08 21:28:40.000000000 +0000 @@ -81,7 +81,7 @@ #define A 3 #define OFFSET(x) offsetof(LutContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption options[] = { { "c0", "set component #0 expression", OFFSET(comp_expr_str[0]), AV_OPT_TYPE_STRING, { .str = "clipval" }, .flags = FLAGS }, @@ -566,6 +566,17 @@ 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) +{ + int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + + if (ret < 0) + return ret; + + return config_props(ctx->inputs[0]); +} + static const AVFilterPad inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, @@ -592,7 +603,9 @@ .query_formats = query_formats, \ .inputs = inputs, \ .outputs = outputs, \ - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, \ + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | \ + AVFILTER_FLAG_SLICE_THREADS, \ + .process_command = process_command, \ } #if CONFIG_LUT_FILTER @@ -654,17 +667,12 @@ static av_cold int negate_init(AVFilterContext *ctx) { LutContext *s = ctx->priv; - int i; - - av_log(ctx, AV_LOG_DEBUG, "negate_alpha:%d\n", s->negate_alpha); - for (i = 0; i < 4; i++) { + 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]) { - uninit(ctx); + if (!s->comp_expr_str[i]) return AVERROR(ENOMEM); - } } return 0; diff -Nru ffmpeg-4.2.2/libavfilter/vf_maskedclamp.c ffmpeg-4.4/libavfilter/vf_maskedclamp.c --- ffmpeg-4.2.2/libavfilter/vf_maskedclamp.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_maskedclamp.c 2021-04-08 21:28:40.000000000 +0000 @@ -26,9 +26,10 @@ #include "internal.h" #include "video.h" #include "framesync.h" +#include "maskedclamp.h" #define OFFSET(x) offsetof(MaskedClampContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM typedef struct ThreadData { AVFrame *b, *o, *m, *d; @@ -47,7 +48,7 @@ int depth; FFFrameSync fs; - int (*maskedclamp)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + MaskedClampDSPContext dsp; } MaskedClampContext; static const AVOption maskedclamp_options[] = { @@ -74,6 +75,7 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, @@ -85,45 +87,7 @@ return ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); } -static int process_frame(FFFrameSync *fs) -{ - AVFilterContext *ctx = fs->parent; - MaskedClampContext *s = fs->opaque; - AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *out, *base, *dark, *bright; - int ret; - - if ((ret = ff_framesync_get_frame(&s->fs, 0, &base, 0)) < 0 || - (ret = ff_framesync_get_frame(&s->fs, 1, &dark, 0)) < 0 || - (ret = ff_framesync_get_frame(&s->fs, 2, &bright, 0)) < 0) - return ret; - - if (ctx->is_disabled) { - out = av_frame_clone(base); - if (!out) - return AVERROR(ENOMEM); - } else { - ThreadData td; - - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) - return AVERROR(ENOMEM); - av_frame_copy_props(out, base); - - td.b = base; - td.o = dark; - td.m = bright; - td.d = out; - - ctx->internal->execute(ctx, s->maskedclamp, &td, NULL, FFMIN(s->height[0], - ff_filter_get_nb_threads(ctx))); - } - out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); - - return ff_filter_frame(outlink, out); -} - -static int maskedclamp8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +static int maskedclamp_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { MaskedClampContext *s = ctx->priv; ThreadData *td = arg; @@ -144,7 +108,7 @@ uint8_t *dst = td->d->data[p] + slice_start * dlinesize; const int undershoot = s->undershoot; const int overshoot = s->overshoot; - int x, y; + int y; if (!((1 << p) & s->planes)) { av_image_copy_plane(dst, dlinesize, bsrc, blinesize, @@ -153,14 +117,7 @@ } for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < w; x++) { - if (bsrc[x] < darksrc[x] - undershoot) - dst[x] = darksrc[x] - undershoot; - else if (bsrc[x] > brightsrc[x] + overshoot) - dst[x] = brightsrc[x] + overshoot; - else - dst[x] = bsrc[x]; - } + s->dsp.maskedclamp(bsrc, dst, darksrc, brightsrc, w, undershoot, overshoot); dst += dlinesize; bsrc += blinesize; @@ -172,55 +129,63 @@ return 0; } -static int maskedclamp16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +static int process_frame(FFFrameSync *fs) { - MaskedClampContext *s = ctx->priv; - ThreadData *td = arg; - int p; + AVFilterContext *ctx = fs->parent; + MaskedClampContext *s = fs->opaque; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out, *base, *dark, *bright; + int ret; - for (p = 0; p < s->nb_planes; p++) { - const ptrdiff_t blinesize = td->b->linesize[p] / 2; - const ptrdiff_t brightlinesize = td->m->linesize[p] / 2; - const ptrdiff_t darklinesize = td->o->linesize[p] / 2; - const ptrdiff_t dlinesize = td->d->linesize[p] / 2; - const int w = s->width[p]; - const int h = s->height[p]; - const int slice_start = (h * jobnr) / nb_jobs; - const int slice_end = (h * (jobnr+1)) / nb_jobs; - const uint16_t *bsrc = (const uint16_t *)td->b->data[p] + slice_start * blinesize; - const uint16_t *darksrc = (const uint16_t *)td->o->data[p] + slice_start * darklinesize; - const uint16_t *brightsrc = (const uint16_t *)td->m->data[p] + slice_start * brightlinesize; - uint16_t *dst = (uint16_t *)td->d->data[p] + slice_start * dlinesize; - const int undershoot = s->undershoot; - const int overshoot = s->overshoot; - int x, y; + if ((ret = ff_framesync_get_frame(&s->fs, 0, &base, 0)) < 0 || + (ret = ff_framesync_get_frame(&s->fs, 1, &dark, 0)) < 0 || + (ret = ff_framesync_get_frame(&s->fs, 2, &bright, 0)) < 0) + return ret; - if (!((1 << p) & s->planes)) { - av_image_copy_plane((uint8_t *)dst, dlinesize, (const uint8_t *)bsrc, blinesize, - s->linesize[p], slice_end - slice_start); - continue; - } + if (ctx->is_disabled) { + out = av_frame_clone(base); + if (!out) + return AVERROR(ENOMEM); + } else { + ThreadData td; - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < w; x++) { - if (bsrc[x] < darksrc[x] - undershoot) - dst[x] = darksrc[x] - undershoot; - else if (bsrc[x] > brightsrc[x] + overshoot) - dst[x] = brightsrc[x] + overshoot; - else - dst[x] = bsrc[x]; - } + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) + return AVERROR(ENOMEM); + av_frame_copy_props(out, base); - dst += dlinesize; - bsrc += blinesize; - darksrc += darklinesize; - brightsrc += brightlinesize; - } + td.b = base; + td.o = dark; + td.m = bright; + td.d = out; + + ctx->internal->execute(ctx, maskedclamp_slice, &td, NULL, FFMIN(s->height[0], + ff_filter_get_nb_threads(ctx))); } + out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); - return 0; + return ff_filter_frame(outlink, out); +} + +#define MASKEDCLAMP(type, name) \ +static void maskedclamp##name(const uint8_t *bbsrc, uint8_t *ddst, \ + const uint8_t *ddarksrc, const uint8_t *bbrightsrc, \ + int w, int undershoot, int overshoot) \ +{ \ + const type *bsrc = (const type *)bbsrc; \ + const type *darksrc = (const type *)ddarksrc; \ + const type *brightsrc = (const type *)bbrightsrc; \ + type *dst = (type *)ddst; \ + \ + for (int x = 0; x < w; x++) { \ + dst[x] = FFMAX(bsrc[x], darksrc[x] - undershoot); \ + dst[x] = FFMIN(dst[x], brightsrc[x] + overshoot); \ + } \ } +MASKEDCLAMP(uint8_t, 8) +MASKEDCLAMP(uint16_t, 16) + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -241,11 +206,16 @@ s->width[0] = s->width[3] = inlink->w; s->depth = desc->comp[0].depth; + s->undershoot = FFMIN(s->undershoot, (1 << s->depth) - 1); + s->overshoot = FFMIN(s->overshoot, (1 << s->depth) - 1); - if (desc->comp[0].depth == 8) - s->maskedclamp = maskedclamp8; + if (s->depth <= 8) + s->dsp.maskedclamp = maskedclamp8; else - s->maskedclamp = maskedclamp16; + s->dsp.maskedclamp = maskedclamp16; + + if (ARCH_X86) + ff_maskedclamp_init_x86(&s->dsp, s->depth); return 0; } @@ -357,4 +327,5 @@ .outputs = maskedclamp_outputs, .priv_class = &maskedclamp_class, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_maskedmerge.c ffmpeg-4.4/libavfilter/vf_maskedmerge.c --- ffmpeg-4.2.2/libavfilter/vf_maskedmerge.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_maskedmerge.c 2021-04-08 21:28:40.000000000 +0000 @@ -28,7 +28,7 @@ #include "maskedmerge.h" #define OFFSET(x) offsetof(MaskedMergeContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption maskedmerge_options[] = { { "planes", "set planes", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, FLAGS }, @@ -46,12 +46,13 @@ AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, - AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, @@ -327,4 +328,5 @@ .outputs = maskedmerge_outputs, .priv_class = &maskedmerge_class, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_maskedminmax.c ffmpeg-4.4/libavfilter/vf_maskedminmax.c --- ffmpeg-4.2.2/libavfilter/vf_maskedminmax.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_maskedminmax.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2019 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" +#include "framesync.h" + +#define OFFSET(x) offsetof(MaskedMinMaxContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +typedef struct ThreadData { + AVFrame *src, *f1, *f2, *dst; +} ThreadData; + +typedef struct MaskedMinMaxContext { + const AVClass *class; + + int planes; + int maskedmin; + + int linesize[4]; + int planewidth[4], planeheight[4]; + int nb_planes; + int depth; + FFFrameSync fs; + + void (*maskedminmax)(const uint8_t *src, uint8_t *dst, const uint8_t *f1, const uint8_t *f2, int w); +} MaskedMinMaxContext; + +static const AVOption maskedminmax_options[] = { + { "planes", "set planes", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, FLAGS }, + { NULL } +}; + +static av_cold int init(AVFilterContext *ctx) +{ + MaskedMinMaxContext *s = ctx->priv; + + s->maskedmin = !strcmp(ctx->filter->name, "maskedmin"); + + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE + }; + + return ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); +} + +static void maskedmin8(const uint8_t *src, uint8_t *dst, const uint8_t *f1, const uint8_t *f2, int w) +{ + for (int x = 0; x < w; x++) + dst[x] = FFABS(src[x] - f2[x]) < FFABS(src[x] - f1[x]) ? f2[x] : f1[x]; +} + +static void maskedmax8(const uint8_t *src, uint8_t *dst, const uint8_t *f1, const uint8_t *f2, int w) +{ + for (int x = 0; x < w; x++) + dst[x] = FFABS(src[x] - f2[x]) > FFABS(src[x] - f1[x]) ? f2[x] : f1[x]; +} + +static void maskedmin16(const uint8_t *ssrc, uint8_t *ddst, const uint8_t *ff1, const uint8_t *ff2, int w) +{ + const uint16_t *src = (const uint16_t *)ssrc; + const uint16_t *f1 = (const uint16_t *)ff1; + const uint16_t *f2 = (const uint16_t *)ff2; + uint16_t *dst = (uint16_t *)ddst; + + for (int x = 0; x < w; x++) + dst[x] = FFABS(src[x] - f2[x]) < FFABS(src[x] - f1[x]) ? f2[x] : f1[x]; +} + +static void maskedmax16(const uint8_t *ssrc, uint8_t *ddst, const uint8_t *ff1, const uint8_t *ff2, int w) +{ + const uint16_t *src = (const uint16_t *)ssrc; + const uint16_t *f1 = (const uint16_t *)ff1; + const uint16_t *f2 = (const uint16_t *)ff2; + uint16_t *dst = (uint16_t *)ddst; + + for (int x = 0; x < w; x++) + dst[x] = FFABS(src[x] - f2[x]) > FFABS(src[x] - f1[x]) ? f2[x] : f1[x]; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + MaskedMinMaxContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int vsub, hsub, ret; + + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + + if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + return ret; + + hsub = desc->log2_chroma_w; + vsub = desc->log2_chroma_h; + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, vsub); + s->planeheight[0] = s->planeheight[3] = inlink->h; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, hsub); + s->planewidth[0] = s->planewidth[3] = inlink->w; + + s->depth = desc->comp[0].depth; + + if (desc->comp[0].depth == 8) + s->maskedminmax = s->maskedmin ? maskedmin8 : maskedmax8; + else + s->maskedminmax = s->maskedmin ? maskedmin16 : maskedmax16; + + return 0; +} + +static int maskedminmax_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + MaskedMinMaxContext *s = ctx->priv; + ThreadData *td = arg; + + for (int p = 0; p < s->nb_planes; p++) { + const ptrdiff_t src_linesize = td->src->linesize[p]; + const ptrdiff_t f1_linesize = td->f1->linesize[p]; + const ptrdiff_t f2_linesize = td->f2->linesize[p]; + const ptrdiff_t dst_linesize = td->dst->linesize[p]; + const int w = s->planewidth[p]; + const int h = s->planeheight[p]; + const int slice_start = (h * jobnr) / nb_jobs; + const int slice_end = (h * (jobnr+1)) / nb_jobs; + const uint8_t *src = td->src->data[p] + slice_start * src_linesize; + const uint8_t *f1 = td->f1->data[p] + slice_start * f1_linesize; + const uint8_t *f2 = td->f2->data[p] + slice_start * f2_linesize; + uint8_t *dst = td->dst->data[p] + slice_start * dst_linesize; + + if (!((1 << p) & s->planes)) { + av_image_copy_plane(dst, dst_linesize, src, src_linesize, + s->linesize[p], slice_end - slice_start); + continue; + } + + for (int y = slice_start; y < slice_end; y++) { + s->maskedminmax(src, dst, f1, f2, w); + + dst += dst_linesize; + src += src_linesize; + f1 += f1_linesize; + f2 += f2_linesize; + } + } + + return 0; +} + +static int process_frame(FFFrameSync *fs) +{ + AVFilterContext *ctx = fs->parent; + MaskedMinMaxContext *s = fs->opaque; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out, *src, *f1, *f2; + int ret; + + if ((ret = ff_framesync_get_frame(&s->fs, 0, &src, 0)) < 0 || + (ret = ff_framesync_get_frame(&s->fs, 1, &f1, 0)) < 0 || + (ret = ff_framesync_get_frame(&s->fs, 2, &f2, 0)) < 0) + return ret; + + if (ctx->is_disabled) { + out = av_frame_clone(src); + if (!out) + return AVERROR(ENOMEM); + } else { + ThreadData td; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) + return AVERROR(ENOMEM); + av_frame_copy_props(out, src); + + td.src = src; + td.f1 = f1; + td.f2 = f2; + td.dst = out; + + ctx->internal->execute(ctx, maskedminmax_slice, &td, NULL, FFMIN(s->planeheight[0], + ff_filter_get_nb_threads(ctx))); + } + out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); + + return ff_filter_frame(outlink, out); +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + MaskedMinMaxContext *s = ctx->priv; + AVFilterLink *source = ctx->inputs[0]; + AVFilterLink *f1 = ctx->inputs[1]; + AVFilterLink *f2 = ctx->inputs[2]; + FFFrameSyncIn *in; + int ret; + + if (source->format != f1->format || + source->format != f2->format) { + av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n"); + return AVERROR(EINVAL); + } + if (source->w != f1->w || source->h != f1->h || + source->w != f2->w || source->h != f2->h) { + av_log(ctx, AV_LOG_ERROR, "First input link %s parameters " + "(size %dx%d) do not match the corresponding " + "second input link %s parameters (%dx%d) " + "and/or third input link %s parameters (size %dx%d)\n", + ctx->input_pads[0].name, source->w, source->h, + ctx->input_pads[1].name, f1->w, f1->h, + ctx->input_pads[2].name, f2->w, f2->h); + return AVERROR(EINVAL); + } + + outlink->w = source->w; + outlink->h = source->h; + outlink->sample_aspect_ratio = source->sample_aspect_ratio; + outlink->frame_rate = source->frame_rate; + + if ((ret = ff_framesync_init(&s->fs, ctx, 3)) < 0) + return ret; + + in = s->fs.in; + in[0].time_base = source->time_base; + in[1].time_base = f1->time_base; + in[2].time_base = f2->time_base; + in[0].sync = 1; + in[0].before = EXT_STOP; + in[0].after = EXT_INFINITY; + in[1].sync = 1; + in[1].before = EXT_STOP; + in[1].after = EXT_INFINITY; + in[2].sync = 1; + in[2].before = EXT_STOP; + in[2].after = EXT_INFINITY; + s->fs.opaque = s; + s->fs.on_event = process_frame; + + ret = ff_framesync_configure(&s->fs); + outlink->time_base = s->fs.time_base; + + return ret; +} + +static int activate(AVFilterContext *ctx) +{ + MaskedMinMaxContext *s = ctx->priv; + return ff_framesync_activate(&s->fs); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + MaskedMinMaxContext *s = ctx->priv; + + ff_framesync_uninit(&s->fs); +} + +static const AVFilterPad maskedminmax_inputs[] = { + { + .name = "source", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + }, + { + .name = "filter1", + .type = AVMEDIA_TYPE_VIDEO, + }, + { + .name = "filter2", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +static const AVFilterPad maskedminmax_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +#define maskedmin_options maskedminmax_options +AVFILTER_DEFINE_CLASS(maskedmin); + +AVFilter ff_vf_maskedmin = { + .name = "maskedmin", + .description = NULL_IF_CONFIG_SMALL("Apply filtering with minimum difference of two streams."), + .priv_class = &maskedmin_class, + .priv_size = sizeof(MaskedMinMaxContext), + .init = init, + .uninit = uninit, + .activate = activate, + .query_formats = query_formats, + .inputs = maskedminmax_inputs, + .outputs = maskedminmax_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; + +#define maskedmax_options maskedminmax_options +AVFILTER_DEFINE_CLASS(maskedmax); + +AVFilter ff_vf_maskedmax = { + .name = "maskedmax", + .description = NULL_IF_CONFIG_SMALL("Apply filtering with maximum difference of two streams."), + .priv_class = &maskedmax_class, + .priv_size = sizeof(MaskedMinMaxContext), + .init = init, + .uninit = uninit, + .activate = activate, + .query_formats = query_formats, + .inputs = maskedminmax_inputs, + .outputs = maskedminmax_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_maskedthreshold.c ffmpeg-4.4/libavfilter/vf_maskedthreshold.c --- ffmpeg-4.2.2/libavfilter/vf_maskedthreshold.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_maskedthreshold.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" +#include "framesync.h" + +typedef struct MaskedThresholdContext { + const AVClass *class; + + int threshold; + int planes; + + int linesize[4]; + int planewidth[4], planeheight[4]; + int nb_planes; + int depth; + FFFrameSync fs; + + void (*maskedthreshold)(const uint8_t *src, const uint8_t *ref, uint8_t *dst, int threshold, int w); +} MaskedThresholdContext; + +#define OFFSET(x) offsetof(MaskedThresholdContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +typedef struct ThreadData { + AVFrame *src, *ref, *dst; +} ThreadData; + +static const AVOption maskedthreshold_options[] = { + { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_INT, {.i64=1}, 0, UINT16_MAX, FLAGS }, + { "planes", "set planes", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, FLAGS }, + { NULL } +}; + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE + }; + + return ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); +} + +static void threshold8(const uint8_t *src, const uint8_t *ref, uint8_t *dst, int threshold, int w) +{ + for (int x = 0; x < w; x++) + dst[x] = FFABS(src[x] - ref[x]) <= threshold ? src[x] : ref[x]; +} + +static void threshold16(const uint8_t *ssrc, const uint8_t *rref, uint8_t *ddst, int threshold, int w) +{ + const uint16_t *src = (const uint16_t *)ssrc; + const uint16_t *ref = (const uint16_t *)rref; + uint16_t *dst = (uint16_t *)ddst; + + for (int x = 0; x < w; x++) + dst[x] = FFABS(src[x] - ref[x]) <= threshold ? src[x] : ref[x]; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + MaskedThresholdContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int vsub, hsub, ret; + + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + + if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + return ret; + + hsub = desc->log2_chroma_w; + vsub = desc->log2_chroma_h; + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, vsub); + s->planeheight[0] = s->planeheight[3] = inlink->h; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, hsub); + s->planewidth[0] = s->planewidth[3] = inlink->w; + + s->depth = desc->comp[0].depth; + + if (desc->comp[0].depth == 8) + s->maskedthreshold = threshold8; + else + s->maskedthreshold = threshold16; + + return 0; +} + +static int threshold_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + MaskedThresholdContext *s = ctx->priv; + const int threshold = s->threshold; + ThreadData *td = arg; + + for (int p = 0; p < s->nb_planes; p++) { + const ptrdiff_t src_linesize = td->src->linesize[p]; + const ptrdiff_t ref_linesize = td->ref->linesize[p]; + const ptrdiff_t dst_linesize = td->dst->linesize[p]; + const int w = s->planewidth[p]; + const int h = s->planeheight[p]; + const int slice_start = (h * jobnr) / nb_jobs; + const int slice_end = (h * (jobnr+1)) / nb_jobs; + const uint8_t *src = td->src->data[p] + slice_start * src_linesize; + const uint8_t *ref = td->ref->data[p] + slice_start * ref_linesize; + uint8_t *dst = td->dst->data[p] + slice_start * dst_linesize; + + if (!((1 << p) & s->planes)) { + av_image_copy_plane(dst, dst_linesize, ref, ref_linesize, + s->linesize[p], slice_end - slice_start); + continue; + } + + for (int y = slice_start; y < slice_end; y++) { + s->maskedthreshold(src, ref, dst, threshold, w); + + dst += dst_linesize; + src += src_linesize; + ref += ref_linesize; + } + } + + return 0; +} + +static int process_frame(FFFrameSync *fs) +{ + AVFilterContext *ctx = fs->parent; + MaskedThresholdContext *s = fs->opaque; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out, *src, *ref; + int ret; + + if ((ret = ff_framesync_get_frame(&s->fs, 0, &src, 0)) < 0 || + (ret = ff_framesync_get_frame(&s->fs, 1, &ref, 0)) < 0) + return ret; + + if (ctx->is_disabled) { + out = av_frame_clone(src); + if (!out) + return AVERROR(ENOMEM); + } else { + ThreadData td; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) + return AVERROR(ENOMEM); + av_frame_copy_props(out, src); + + td.src = src; + td.ref = ref; + td.dst = out; + + ctx->internal->execute(ctx, threshold_slice, &td, NULL, FFMIN(s->planeheight[2], + ff_filter_get_nb_threads(ctx))); + } + out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); + + return ff_filter_frame(outlink, out); +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + MaskedThresholdContext *s = ctx->priv; + AVFilterLink *source = ctx->inputs[0]; + AVFilterLink *ref = ctx->inputs[1]; + FFFrameSyncIn *in; + int ret; + + if (source->format != ref->format) { + av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n"); + return AVERROR(EINVAL); + } + if (source->w != ref->w || source->h != ref->h) { + av_log(ctx, AV_LOG_ERROR, "First input link %s parameters " + "(size %dx%d) do not match the corresponding " + "second input link %s parameters (%dx%d)\n", + ctx->input_pads[0].name, source->w, source->h, + ctx->input_pads[1].name, ref->w, ref->h); + return AVERROR(EINVAL); + } + + outlink->w = source->w; + outlink->h = source->h; + outlink->sample_aspect_ratio = source->sample_aspect_ratio; + outlink->frame_rate = source->frame_rate; + + if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0) + return ret; + + in = s->fs.in; + in[0].time_base = source->time_base; + in[1].time_base = ref->time_base; + in[0].sync = 1; + in[0].before = EXT_STOP; + in[0].after = EXT_INFINITY; + in[1].sync = 1; + in[1].before = EXT_STOP; + in[1].after = EXT_INFINITY; + s->fs.opaque = s; + s->fs.on_event = process_frame; + + ret = ff_framesync_configure(&s->fs); + outlink->time_base = s->fs.time_base; + + return ret; +} + +static int activate(AVFilterContext *ctx) +{ + MaskedThresholdContext *s = ctx->priv; + return ff_framesync_activate(&s->fs); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + MaskedThresholdContext *s = ctx->priv; + + ff_framesync_uninit(&s->fs); +} + +static const AVFilterPad maskedthreshold_inputs[] = { + { + .name = "source", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + }, + { + .name = "reference", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +static const AVFilterPad maskedthreshold_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(maskedthreshold); + +AVFilter ff_vf_maskedthreshold = { + .name = "maskedthreshold", + .description = NULL_IF_CONFIG_SMALL("Pick pixels comparing absolute difference of two streams with threshold."), + .priv_class = &maskedthreshold_class, + .priv_size = sizeof(MaskedThresholdContext), + .uninit = uninit, + .activate = activate, + .query_formats = query_formats, + .inputs = maskedthreshold_inputs, + .outputs = maskedthreshold_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_maskfun.c ffmpeg-4.4/libavfilter/vf_maskfun.c --- ffmpeg-4.2.2/libavfilter/vf_maskfun.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_maskfun.c 2021-04-08 21:28:40.000000000 +0000 @@ -47,14 +47,14 @@ } MaskFunContext; #define OFFSET(x) offsetof(MaskFunContext, x) -#define VF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define VFT AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption maskfun_options[] = { - { "low", "set low threshold", OFFSET(low), AV_OPT_TYPE_INT, {.i64=10}, 0, UINT16_MAX, VF }, - { "high", "set high threshold", OFFSET(high), AV_OPT_TYPE_INT, {.i64=10}, 0, UINT16_MAX, VF }, - { "planes", "set planes", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, VF }, - { "fill", "set fill value", OFFSET(fill), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, VF }, - { "sum", "set sum value", OFFSET(sum), AV_OPT_TYPE_INT, {.i64=10}, 0, UINT16_MAX, VF }, + { "low", "set low threshold", OFFSET(low), AV_OPT_TYPE_INT, {.i64=10}, 0, UINT16_MAX, VFT }, + { "high", "set high threshold", OFFSET(high), AV_OPT_TYPE_INT, {.i64=10}, 0, UINT16_MAX, VFT }, + { "planes", "set planes", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, VFT }, + { "fill", "set fill value", OFFSET(fill), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, VFT }, + { "sum", "set sum value", OFFSET(sum), AV_OPT_TYPE_INT, {.i64=10}, 0, UINT16_MAX, VFT }, { NULL } }; @@ -182,6 +182,45 @@ MASKFUN(8, uint8_t, 1) MASKFUN(16, uint16_t, 2) +static void fill_frame(AVFilterContext *ctx) +{ + MaskFunContext *s = ctx->priv; + + s->fill = FFMIN(s->fill, s->max); + if (s->depth == 8) { + for (int p = 0; p < s->nb_planes; p++) { + uint8_t *dst = s->empty->data[p]; + + for (int y = 0; y < s->height[p]; y++) { + memset(dst, s->fill, s->width[p]); + dst += s->empty->linesize[p]; + } + } + } else { + for (int p = 0; p < s->nb_planes; p++) { + uint16_t *dst = (uint16_t *)s->empty->data[p]; + + for (int y = 0; y < s->height[p]; y++) { + for (int x = 0; x < s->width[p]; x++) + dst[x] = s->fill; + dst += s->empty->linesize[p] / 2; + } + } + } +} + +static void set_max_sum(AVFilterContext *ctx) +{ + MaskFunContext *s = ctx->priv; + + s->max_sum = 0; + for (int p = 0; p < s->nb_planes; p++) { + if (!((1 << p) & s->planes)) + continue; + s->max_sum += (uint64_t)s->sum * s->width[p] * s->height[p]; + } +} + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -203,7 +242,6 @@ s->depth = desc->comp[0].depth; s->max = (1 << s->depth) - 1; - s->fill = FFMIN(s->fill, s->max); if (s->depth == 8) { s->maskfun = maskfun8; @@ -217,37 +255,41 @@ if (!s->empty) return AVERROR(ENOMEM); - if (s->depth == 8) { - for (int p = 0; p < s->nb_planes; p++) { - uint8_t *dst = s->empty->data[p]; + fill_frame(ctx); - for (int y = 0; y < s->height[p]; y++) { - memset(dst, s->fill, s->width[p]); - dst += s->empty->linesize[p]; - } - } - } else { - for (int p = 0; p < s->nb_planes; p++) { - uint16_t *dst = (uint16_t *)s->empty->data[p]; + set_max_sum(ctx); - for (int y = 0; y < s->height[p]; y++) { - for (int x = 0; x < s->width[p]; x++) - dst[x] = s->fill; - dst += s->empty->linesize[p] / 2; - } - } - } + return 0; +} - s->max_sum = 0; - for (int p = 0; p < s->nb_planes; p++) { - if (!((1 << p) & s->planes)) - continue; - s->max_sum += (uint64_t)s->sum * s->width[p] * s->height[p]; - } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + MaskFunContext *s = ctx->priv; + int fill = s->fill; + int sum = s->sum; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + if (sum != s->sum) + set_max_sum(ctx); + + if (fill != s->fill) + fill_frame(ctx); return 0; } +static av_cold void uninit(AVFilterContext *ctx) +{ + MaskFunContext *s = ctx->priv; + + av_frame_free(&s->empty); +} + static const AVFilterPad maskfun_inputs[] = { { .name = "default", @@ -272,8 +314,10 @@ .description = NULL_IF_CONFIG_SMALL("Create Mask."), .priv_size = sizeof(MaskFunContext), .query_formats = query_formats, + .uninit = uninit, .inputs = maskfun_inputs, .outputs = maskfun_outputs, .priv_class = &maskfun_class, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_mcdeint.c ffmpeg-4.4/libavfilter/vf_mcdeint.c --- ffmpeg-4.2.2/libavfilter/vf_mcdeint.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_mcdeint.c 2021-04-08 21:28:40.000000000 +0000 @@ -74,6 +74,7 @@ int mode; ///< MCDeintMode int parity; ///< MCDeintParity int qp; + AVPacket *pkt; AVCodecContext *enc_ctx; } MCDeintContext; @@ -102,7 +103,7 @@ { AVFilterContext *ctx = inlink->dst; MCDeintContext *mcdeint = ctx->priv; - AVCodec *enc; + const AVCodec *enc; AVCodecContext *enc_ctx; AVDictionary *opts = NULL; int ret; @@ -112,6 +113,9 @@ return AVERROR(EINVAL); } + mcdeint->pkt = av_packet_alloc(); + if (!mcdeint->pkt) + return AVERROR(ENOMEM); mcdeint->enc_ctx = avcodec_alloc_context3(enc); if (!mcdeint->enc_ctx) return AVERROR(ENOMEM); @@ -154,6 +158,7 @@ { MCDeintContext *mcdeint = ctx->priv; + av_packet_free(&mcdeint->pkt); avcodec_free_context(&mcdeint->enc_ctx); } @@ -173,7 +178,7 @@ MCDeintContext *mcdeint = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; AVFrame *outpic, *frame_dec; - AVPacket pkt = {0}; + AVPacket *pkt = mcdeint->pkt; int x, y, i, ret, got_frame = 0; outpic = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -184,9 +189,7 @@ av_frame_copy_props(outpic, inpic); inpic->quality = mcdeint->qp * FF_QP2LAMBDA; - av_init_packet(&pkt); - - ret = avcodec_encode_video2(mcdeint->enc_ctx, &pkt, inpic, &got_frame); + ret = avcodec_encode_video2(mcdeint->enc_ctx, pkt, inpic, &got_frame); if (ret < 0) goto end; @@ -274,7 +277,7 @@ mcdeint->parity ^= 1; end: - av_packet_unref(&pkt); + av_packet_unref(pkt); av_frame_free(&inpic); if (ret < 0) { av_frame_free(&outpic); diff -Nru ffmpeg-4.2.2/libavfilter/vf_median.c ffmpeg-4.4/libavfilter/vf_median.c --- ffmpeg-4.2.2/libavfilter/vf_median.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_median.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2019 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 + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + */ + +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "median.h" +#include "video.h" + +#define DEPTH 8 +#include "median_template.c" + +#undef DEPTH +#define DEPTH 9 +#include "median_template.c" + +#undef DEPTH +#define DEPTH 10 +#include "median_template.c" + +#undef DEPTH +#define DEPTH 12 +#include "median_template.c" + +#undef DEPTH +#define DEPTH 14 +#include "median_template.c" + +#undef DEPTH +#define DEPTH 16 +#include "median_template.c" + +#define OFFSET(x) offsetof(MedianContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption median_options[] = { + { "radius", "set median radius", OFFSET(radius), AV_OPT_TYPE_INT, {.i64=1}, 1, 127, FLAGS }, + { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, FLAGS }, + { "radiusV", "set median vertical radius", OFFSET(radiusV), AV_OPT_TYPE_INT, {.i64=0},0, 127, FLAGS }, + { "percentile", "set median percentile", OFFSET(percentile), AV_OPT_TYPE_FLOAT, {.dbl=.5}, 0., 1., FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(median); + +static void hadd(htype *dst, const htype *src, int bins) +{ + for (int i = 0; i < bins; i++) + dst[i] += src[i]; +} + +static void hsub(htype *dst, const htype *src, int bins) +{ + for (int i = 0; i < bins; i++) + dst[i] -= src[i]; +} + +static void hmuladd(htype *dst, const htype *src, int f, int bins) +{ + for (int i = 0; i < bins; i++) + dst[i] += f * src[i]; +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, AV_PIX_FMT_GBRP9, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE + }; + + return ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); +} + +static void check_params(MedianContext *s, AVFilterLink *inlink) +{ + for (int i = 0; i < s->nb_planes; i++) { + if (!(s->planes & (1 << i))) + continue; + + if (s->planewidth[i] < s->radius * 2 + 1) { + av_log(inlink->dst, AV_LOG_WARNING, "The %d plane width %d must be not less than %d, clipping radius.\n", i, s->planewidth[i], s->radius * 2 + 1); + s->radius = (s->planewidth[i] - 1) / 2; + } + + if (s->planeheight[i] < s->radiusV * 2 + 1) { + av_log(inlink->dst, AV_LOG_WARNING, "The %d plane height %d must be not less than %d, clipping radiusV.\n", i, s->planeheight[i], s->radiusV * 2 + 1); + s->radiusV = (s->planeheight[i] - 1) / 2; + } + } + + s->t = (2 * s->radius * s->radiusV + s->radiusV + s->radius) * 2.f * s->percentile; +} + +static int config_input(AVFilterLink *inlink) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + MedianContext *s = inlink->dst->priv; + + s->depth = desc->comp[0].depth; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + + s->radiusV = !s->radiusV ? s->radius : s->radiusV; + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + + check_params(s, inlink); + + s->nb_threads = FFMAX(1, FFMIN(s->planeheight[1] / (s->radiusV + 1), ff_filter_get_nb_threads(inlink->dst))); + s->bins = 1 << ((s->depth + 1) / 2); + s->fine_size = s->bins * s->bins * inlink->w; + s->coarse_size = s->bins * inlink->w; + s->coarse = av_calloc(s->nb_threads, sizeof(*s->coarse)); + s->fine = av_calloc(s->nb_threads, sizeof(*s->fine)); + if (!s->coarse || !s->fine) + return AVERROR(ENOMEM); + for (int i = 0; i < s->nb_threads; i++) { + s->coarse[i] = av_malloc_array(s->coarse_size, sizeof(**s->coarse)); + s->fine[i] = av_malloc_array(s->fine_size, sizeof(**s->fine)); + if (!s->coarse[i] || !s->fine[i]) + return AVERROR(ENOMEM); + } + + s->hadd = hadd; + s->hsub = hsub; + s->hmuladd = hmuladd; + + switch (s->depth) { + case 8: s->filter_plane = filter_plane_8; break; + case 9: s->filter_plane = filter_plane_9; break; + case 10: s->filter_plane = filter_plane_10; break; + case 12: s->filter_plane = filter_plane_12; break; + case 14: s->filter_plane = filter_plane_14; break; + case 16: s->filter_plane = filter_plane_16; break; + } + + return 0; +} + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + MedianContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + + for (int plane = 0; plane < s->nb_planes; plane++) { + const int h = s->planeheight[plane]; + const int w = s->planewidth[plane]; + const int slice_h_start = (h * jobnr) / nb_jobs; + const int slice_h_end = (h * (jobnr+1)) / nb_jobs; + + if (!(s->planes & (1 << plane))) { + av_image_copy_plane(out->data[plane] + slice_h_start * out->linesize[plane], + out->linesize[plane], + in->data[plane] + slice_h_start * in->linesize[plane], + in->linesize[plane], + w * ((s->depth + 7) / 8), + slice_h_end - slice_h_start); + continue; + } + + s->filter_plane(ctx, in->data[plane], + in->linesize[plane], + out->data[plane] + slice_h_start * out->linesize[plane], + out->linesize[plane], w, h, + slice_h_start, slice_h_end, jobnr); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + MedianContext *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); + + td.in = in; td.out = out; + ctx->internal->execute(ctx, filter_slice, &td, NULL, s->nb_threads); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + MedianContext *s = ctx->priv; + + for (int i = 0; i < s->nb_threads && s->coarse && s->fine; i++) { + av_freep(&s->coarse[i]); + av_freep(&s->fine[i]); + } + + av_freep(&s->coarse); + av_freep(&s->fine); +} + +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + MedianContext *s = ctx->priv; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + if (!s->radiusV) + s->radiusV = s->radius; + check_params(s, ctx->inputs[0]); + + return 0; +} + +static const AVFilterPad median_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad median_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_median = { + .name = "median", + .description = NULL_IF_CONFIG_SMALL("Apply Median filter."), + .priv_size = sizeof(MedianContext), + .priv_class = &median_class, + .uninit = uninit, + .query_formats = query_formats, + .inputs = median_inputs, + .outputs = median_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_mergeplanes.c ffmpeg-4.4/libavfilter/vf_mergeplanes.c --- ffmpeg-4.2.2/libavfilter/vf_mergeplanes.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_mergeplanes.c 2021-04-08 21:28:40.000000000 +0000 @@ -122,12 +122,12 @@ } for (i = 0; i < s->nb_inputs; i++) - if ((ret = ff_formats_ref(formats, &ctx->inputs[i]->out_formats)) < 0) + if ((ret = ff_formats_ref(formats, &ctx->inputs[i]->outcfg.formats)) < 0) return ret; formats = NULL; if ((ret = ff_add_format(&formats, s->out_fmt)) < 0 || - (ret = ff_formats_ref(formats, &ctx->outputs[0]->in_formats)) < 0) + (ret = ff_formats_ref(formats, &ctx->outputs[0]->incfg.formats)) < 0) return ret; return 0; diff -Nru ffmpeg-4.2.2/libavfilter/vf_midequalizer.c ffmpeg-4.4/libavfilter/vf_midequalizer.c --- ffmpeg-4.2.2/libavfilter/vf_midequalizer.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_midequalizer.c 2020-07-11 10:39:30.000000000 +0000 @@ -74,7 +74,12 @@ AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GRAY16, AV_PIX_FMT_NONE }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_minterpolate.c ffmpeg-4.4/libavfilter/vf_minterpolate.c --- ffmpeg-4.2.2/libavfilter/vf_minterpolate.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_minterpolate.c 2021-04-08 21:28:40.000000000 +0000 @@ -185,6 +185,7 @@ int64_t out_pts; int b_width, b_height, b_count; int log2_mb_size; + int bitdepth; int scd_method; int scene_changed; @@ -229,7 +230,7 @@ { "scd", "scene change detection method", OFFSET(scd_method), AV_OPT_TYPE_INT, {.i64 = SCD_METHOD_FDIFF}, SCD_METHOD_NONE, SCD_METHOD_FDIFF, FLAGS, "scene" }, CONST("none", "disable detection", SCD_METHOD_NONE, "scene"), CONST("fdiff", "frame difference", SCD_METHOD_FDIFF, "scene"), - { "scd_threshold", "scene change threshold", OFFSET(scd_threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 5.0}, 0, 100.0, FLAGS }, + { "scd_threshold", "scene change threshold", OFFSET(scd_threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 10.}, 0, 100.0, FLAGS }, { NULL } }; @@ -339,10 +340,11 @@ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); const int height = inlink->h; const int width = inlink->w; - int i, ret = 0; + int i; mi_ctx->log2_chroma_h = desc->log2_chroma_h; mi_ctx->log2_chroma_w = desc->log2_chroma_w; + mi_ctx->bitdepth = desc->comp[0].depth; mi_ctx->nb_planes = av_pix_fmt_count_planes(inlink->format); @@ -361,13 +363,25 @@ } if (mi_ctx->mi_mode == MI_MODE_MCI) { + if (mi_ctx->b_width < 2 || mi_ctx->b_height < 2) { + av_log(inlink->dst, AV_LOG_ERROR, "Height or width < %d\n", + 2 * mi_ctx->mb_size); + return AVERROR(EINVAL); + } + ff_me_init_context(me_ctx, mi_ctx->mb_size, mi_ctx->search_param, + width, height, 0, (mi_ctx->b_width - 1) << mi_ctx->log2_mb_size, + 0, (mi_ctx->b_height - 1) << mi_ctx->log2_mb_size); + + if (mi_ctx->me_mode == ME_MODE_BIDIR) + me_ctx->get_cost = &get_sad_ob; + else if (mi_ctx->me_mode == ME_MODE_BILAT) + me_ctx->get_cost = &get_sbad_ob; + mi_ctx->pixel_mvs = av_mallocz_array(width * height, sizeof(PixelMVS)); mi_ctx->pixel_weights = av_mallocz_array(width * height, sizeof(PixelWeights)); mi_ctx->pixel_refs = av_mallocz_array(width * height, sizeof(PixelRefs)); - if (!mi_ctx->pixel_mvs || !mi_ctx->pixel_weights || !mi_ctx->pixel_refs) { - ret = AVERROR(ENOMEM); - goto fail; - } + if (!mi_ctx->pixel_mvs || !mi_ctx->pixel_weights || !mi_ctx->pixel_refs) + return AVERROR(ENOMEM); if (mi_ctx->me_mode == ME_MODE_BILAT) if (!(mi_ctx->int_blocks = av_mallocz_array(mi_ctx->b_count, sizeof(Block)))) @@ -383,26 +397,12 @@ } if (mi_ctx->scd_method == SCD_METHOD_FDIFF) { - mi_ctx->sad = ff_scene_sad_get_fn(8); + mi_ctx->sad = ff_scene_sad_get_fn(mi_ctx->bitdepth == 8 ? 8 : 16); if (!mi_ctx->sad) return AVERROR(EINVAL); } - ff_me_init_context(me_ctx, mi_ctx->mb_size, mi_ctx->search_param, width, height, 0, (mi_ctx->b_width - 1) << mi_ctx->log2_mb_size, 0, (mi_ctx->b_height - 1) << mi_ctx->log2_mb_size); - - if (mi_ctx->me_mode == ME_MODE_BIDIR) - me_ctx->get_cost = &get_sad_ob; - else if (mi_ctx->me_mode == ME_MODE_BILAT) - me_ctx->get_cost = &get_sbad_ob; - return 0; -fail: - for (i = 0; i < NB_FRAMES; i++) - av_freep(&mi_ctx->frames[i].blocks); - av_freep(&mi_ctx->pixel_mvs); - av_freep(&mi_ctx->pixel_weights); - av_freep(&mi_ctx->pixel_refs); - return ret; } static int config_output(AVFilterLink *outlink) @@ -823,9 +823,10 @@ return 0; } -static int detect_scene_change(MIContext *mi_ctx) +static int detect_scene_change(AVFilterContext *ctx) { - AVMotionEstContext *me_ctx = &mi_ctx->me_ctx; + MIContext *mi_ctx = ctx->priv; + AVFilterLink *input = ctx->inputs[0]; uint8_t *p1 = mi_ctx->frames[1].avf->data[0]; ptrdiff_t linesize1 = mi_ctx->frames[1].avf->linesize[0]; uint8_t *p2 = mi_ctx->frames[2].avf->data[0]; @@ -834,9 +835,9 @@ if (mi_ctx->scd_method == SCD_METHOD_FDIFF) { double ret = 0, mafd, diff; uint64_t sad; - mi_ctx->sad(p1, linesize1, p2, linesize2, me_ctx->width, me_ctx->height, &sad); + mi_ctx->sad(p1, linesize1, p2, linesize2, input->w, input->h, &sad); emms_c(); - mafd = (double) sad / (me_ctx->height * me_ctx->width * 3); + mafd = (double) sad * 100.0 / (input->h * input->w) / (1 << mi_ctx->bitdepth); diff = fabs(mafd - mi_ctx->prev_mafd); ret = av_clipf(FFMIN(mafd, diff), 0, 100.0); mi_ctx->prev_mafd = mafd; @@ -1095,6 +1096,7 @@ } if (mi_ctx->scene_changed) { + av_log(ctx, AV_LOG_DEBUG, "scene changed, input pts %"PRId64"\n", mi_ctx->frames[1].avf->pts); /* duplicate frame */ av_frame_copy(avf_out, alpha > ALPHA_MAX / 2 ? mi_ctx->frames[2].avf : mi_ctx->frames[1].avf); return; @@ -1183,7 +1185,7 @@ if (!mi_ctx->frames[0].avf) return 0; - mi_ctx->scene_changed = detect_scene_change(mi_ctx); + mi_ctx->scene_changed = detect_scene_change(ctx); for (;;) { AVFrame *avf_out; diff -Nru ffmpeg-4.2.2/libavfilter/vf_misc_vaapi.c ffmpeg-4.4/libavfilter/vf_misc_vaapi.c --- ffmpeg-4.2.2/libavfilter/vf_misc_vaapi.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_misc_vaapi.c 2020-07-11 10:39:30.000000000 +0000 @@ -145,7 +145,7 @@ err = av_frame_copy_props(output_frame, input_frame); if (err < 0) - return err; + goto fail; err = ff_vaapi_vpp_init_params(avctx, ¶ms, input_frame, output_frame); diff -Nru ffmpeg-4.2.2/libavfilter/vf_mix.c ffmpeg-4.4/libavfilter/vf_mix.c --- ffmpeg-4.2.2/libavfilter/vf_mix.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_mix.c 2021-04-08 21:28:40.000000000 +0000 @@ -55,26 +55,56 @@ static int query_formats(AVFilterContext *ctx) { - AVFilterFormats *pix_fmts = NULL; - int fmt, ret; + AVFilterFormats *formats = NULL; + int ret; - for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); - if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_HWACCEL || - desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) && - (ret = ff_add_format(&pix_fmts, fmt)) < 0) - return ret; + ret = ff_formats_pixdesc_filter(&formats, 0, + AV_PIX_FMT_FLAG_BITSTREAM | + AV_PIX_FMT_FLAG_PAL | + AV_PIX_FMT_FLAG_HWACCEL); + if (ret < 0) + return ret; + return ff_set_common_formats(ctx, formats); +} + +static int parse_weights(AVFilterContext *ctx) +{ + MixContext *s = ctx->priv; + char *p, *arg, *saveptr = NULL; + int i, last = 0; + + s->wfactor = 0.f; + p = s->weights_str; + for (i = 0; i < s->nb_inputs; i++) { + if (!(arg = av_strtok(p, " |", &saveptr))) + break; + + p = NULL; + if (av_sscanf(arg, "%f", &s->weights[i]) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid syntax for weights[%d].\n", i); + return AVERROR(EINVAL); + } + s->wfactor += s->weights[i]; + last = i; } - return ff_set_common_formats(ctx, pix_fmts); + for (; i < s->nb_inputs; i++) { + s->weights[i] = s->weights[last]; + s->wfactor += s->weights[i]; + } + if (s->scale == 0) { + s->wfactor = 1 / s->wfactor; + } else { + s->wfactor = s->scale; + } + + return 0; } static av_cold int init(AVFilterContext *ctx) { MixContext *s = ctx->priv; - char *p, *arg, *saveptr = NULL; - int i, ret, last = 0; + int ret; s->tmix = !strcmp(ctx->filter->name, "tmix"); @@ -87,7 +117,7 @@ return AVERROR(ENOMEM); if (!s->tmix) { - for (i = 0; i < s->nb_inputs; i++) { + for (int i = 0; i < s->nb_inputs; i++) { AVFilterPad pad = { 0 }; pad.type = AVMEDIA_TYPE_VIDEO; @@ -102,27 +132,7 @@ } } - p = s->weights_str; - for (i = 0; i < s->nb_inputs; i++) { - if (!(arg = av_strtok(p, " ", &saveptr))) - break; - - p = NULL; - av_sscanf(arg, "%f", &s->weights[i]); - s->wfactor += s->weights[i]; - last = i; - } - for (; i < s->nb_inputs; i++) { - s->weights[i] = s->weights[last]; - s->wfactor += s->weights[i]; - } - if (s->scale == 0) { - s->wfactor = 1 / s->wfactor; - } else { - s->wfactor = s->scale; - } - - return 0; + return parse_weights(ctx); } typedef struct ThreadData { @@ -201,6 +211,14 @@ return ret; } + if (ctx->is_disabled) { + out = av_frame_clone(s->frames[0]); + if (!out) + return AVERROR(ENOMEM); + out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); + return ff_filter_frame(outlink, out); + } + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); @@ -289,12 +307,24 @@ for (i = 0; i < ctx->nb_inputs; i++) av_freep(&ctx->input_pads[i].name); } else { - for (i = 0; i < s->nb_frames; i++) + for (i = 0; i < s->nb_frames && s->frames; i++) av_frame_free(&s->frames[i]); } av_freep(&s->frames); } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return parse_weights(ctx); +} + static int activate(AVFilterContext *ctx) { MixContext *s = ctx->priv; @@ -303,11 +333,12 @@ #define OFFSET(x) offsetof(MixContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +#define TFLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption mix_options[] = { - { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags = FLAGS }, - { "weights", "set weight for each input", OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, .flags = FLAGS }, - { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, INT16_MAX, .flags = FLAGS }, + { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT16_MAX, .flags = FLAGS }, + { "weights", "set weight for each input", OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, .flags = TFLAGS }, + { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, INT16_MAX, .flags = TFLAGS }, { "duration", "how to determine end of stream", OFFSET(duration), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, .flags = FLAGS, "duration" }, { "longest", "Duration of longest input", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "duration" }, { "shortest", "Duration of shortest input", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "duration" }, @@ -337,7 +368,9 @@ .init = init, .uninit = uninit, .activate = activate, - .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = process_command, }; #endif /* CONFIG_MIX_FILTER */ @@ -386,8 +419,8 @@ static const AVOption tmix_options[] = { { "frames", "set number of successive frames to mix", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=3}, 1, 128, .flags = FLAGS }, - { "weights", "set weight for each frame", OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1 1"}, 0, 0, .flags = FLAGS }, - { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, INT16_MAX, .flags = FLAGS }, + { "weights", "set weight for each frame", OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1 1"}, 0, 0, .flags = TFLAGS }, + { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, INT16_MAX, .flags = TFLAGS }, { NULL }, }; @@ -413,6 +446,7 @@ .init = init, .uninit = uninit, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; #endif /* CONFIG_TMIX_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/vf_monochrome.c ffmpeg-4.4/libavfilter/vf_monochrome.c --- ffmpeg-4.2.2/libavfilter/vf_monochrome.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_monochrome.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,314 @@ +/* + * 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 "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct MonochromeContext { + const AVClass *class; + + float b, r; + float size; + float high; + + int depth; + int subw, subh; + + int (*do_slice)(AVFilterContext *s, void *arg, + int jobnr, int nb_jobs); + int (*clear_uv)(AVFilterContext *s, void *arg, + int jobnr, int nb_jobs); +} MonochromeContext; + +static float envelope(const float x) +{ + const float beta = 0.6f; + + if (x < beta) { + const float tmp = fabsf(x / beta - 1.f); + + return 1.f - tmp * tmp; + } else { + const float tmp = (1.f - x) / (1.f - beta); + + return tmp * tmp * (3.f - 2.f * tmp); + } +} + +static float filter(float b, float r, float u, float v, float size) +{ + return expf(-av_clipf(((b - u) * (b - u) + + (r - v) * (r - v)) * + size, 0.f, 1.f)); +} + +#define PROCESS() \ + const int cx = x >> subw; \ + float y = yptr[x] * imax; \ + float u = uptr[cx] * imax - .5f; \ + float v = vptr[cx] * imax - .5f; \ + float tt, t, ny; \ + \ + ny = filter(b, r, u, v, size); \ + tt = envelope(y); \ + t = tt + (1.f - tt) * ihigh; \ + ny = (1.f - t) * y + t * ny * y; + +static int monochrome_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + MonochromeContext *s = ctx->priv; + AVFrame *frame = arg; + const int depth = s->depth; + const int subw = s->subw; + const int subh = s->subh; + const float max = (1 << depth) - 1; + const float imax = 1.f / max; + const int width = frame->width; + const int height = frame->height; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int ylinesize = frame->linesize[0]; + const int ulinesize = frame->linesize[1]; + const int vlinesize = frame->linesize[2]; + uint8_t *yptr = frame->data[0] + slice_start * ylinesize; + const float ihigh = 1.f - s->high; + const float size = 1.f / s->size; + const float b = s->b * .5f; + const float r = s->r * .5f; + + for (int y = slice_start; y < slice_end; y++) { + const int cy = y >> subh; + uint8_t *uptr = frame->data[1] + cy * ulinesize; + uint8_t *vptr = frame->data[2] + cy * vlinesize; + + for (int x = 0; x < width; x++) { + PROCESS() + + yptr[x] = av_clip_uint8(ny * max); + } + + yptr += ylinesize; + } + + return 0; +} + +static int monochrome_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + MonochromeContext *s = ctx->priv; + AVFrame *frame = arg; + const int depth = s->depth; + const int subw = s->subw; + const int subh = s->subh; + const float max = (1 << depth) - 1; + const float imax = 1.f / max; + const int width = frame->width; + const int height = frame->height; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int ylinesize = frame->linesize[0] / 2; + const int ulinesize = frame->linesize[1] / 2; + const int vlinesize = frame->linesize[2] / 2; + uint16_t *yptr = (uint16_t *)frame->data[0] + slice_start * ylinesize; + const float ihigh = 1.f - s->high; + const float size = 1.f / s->size; + const float b = s->b * .5f; + const float r = s->r * .5f; + + for (int y = slice_start; y < slice_end; y++) { + const int cy = y >> subh; + uint16_t *uptr = (uint16_t *)frame->data[1] + cy * ulinesize; + uint16_t *vptr = (uint16_t *)frame->data[2] + cy * vlinesize; + + for (int x = 0; x < width; x++) { + PROCESS() + + yptr[x] = av_clip_uintp2_c(ny * max, depth); + } + + yptr += ylinesize; + } + + return 0; +} + +static int clear_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + MonochromeContext *s = ctx->priv; + AVFrame *frame = arg; + const int depth = s->depth; + const int half = 1 << (depth - 1); + const int subw = s->subw; + const int subh = s->subh; + const int width = AV_CEIL_RSHIFT(frame->width, subw); + const int height = AV_CEIL_RSHIFT(frame->height, subh); + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int ulinesize = frame->linesize[1]; + const int vlinesize = frame->linesize[2]; + + for (int y = slice_start; y < slice_end; y++) { + uint8_t *uptr = frame->data[1] + y * ulinesize; + uint8_t *vptr = frame->data[2] + y * vlinesize; + + memset(uptr, half, width); + memset(vptr, half, width); + } + + return 0; +} + +static int clear_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + MonochromeContext *s = ctx->priv; + AVFrame *frame = arg; + const int depth = s->depth; + const int half = 1 << (depth - 1); + const int subw = s->subw; + const int subh = s->subh; + const int width = AV_CEIL_RSHIFT(frame->width, subw); + const int height = AV_CEIL_RSHIFT(frame->height, subh); + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int ulinesize = frame->linesize[1] / 2; + const int vlinesize = frame->linesize[2] / 2; + + for (int y = slice_start; y < slice_end; y++) { + uint16_t *uptr = (uint16_t *)frame->data[1] + y * ulinesize; + uint16_t *vptr = (uint16_t *)frame->data[2] + y * vlinesize; + + for (int x = 0; x < width; x++) { + uptr[x] = half; + vptr[x] = half; + } + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + MonochromeContext *s = ctx->priv; + + ctx->internal->execute(ctx, s->do_slice, frame, NULL, + FFMIN(frame->height, ff_filter_get_nb_threads(ctx))); + ctx->internal->execute(ctx, s->clear_uv, frame, NULL, + FFMIN(frame->height >> s->subh, ff_filter_get_nb_threads(ctx))); + + return ff_filter_frame(ctx->outputs[0], frame); +} + +static av_cold int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pixel_fmts[] = { + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *formats = NULL; + + formats = ff_make_format_list(pixel_fmts); + if (!formats) + return AVERROR(ENOMEM); + + return ff_set_common_formats(ctx, formats); +} + +static av_cold int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + MonochromeContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + + s->depth = desc->comp[0].depth; + s->do_slice = s->depth <= 8 ? monochrome_slice8 : monochrome_slice16; + s->clear_uv = s->depth <= 8 ? clear_slice8 : clear_slice16; + s->subw = desc->log2_chroma_w; + s->subh = desc->log2_chroma_h; + + return 0; +} + +static const AVFilterPad monochrome_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .needs_writable = 1, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad monochrome_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(MonochromeContext, x) +#define VF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption monochrome_options[] = { + { "cb", "set the chroma blue spot", OFFSET(b), AV_OPT_TYPE_FLOAT, {.dbl=0},-1, 1, VF }, + { "cr", "set the chroma red spot", OFFSET(r), AV_OPT_TYPE_FLOAT, {.dbl=0},-1, 1, VF }, + { "size", "set the color filter size", OFFSET(size), AV_OPT_TYPE_FLOAT, {.dbl=1},.1,10, VF }, + { "high", "set the highlights strength", OFFSET(high), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, VF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(monochrome); + +AVFilter ff_vf_monochrome = { + .name = "monochrome", + .description = NULL_IF_CONFIG_SMALL("Convert video to gray using custom color filter."), + .priv_size = sizeof(MonochromeContext), + .priv_class = &monochrome_class, + .query_formats = query_formats, + .inputs = monochrome_inputs, + .outputs = monochrome_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_neighbor.c ffmpeg-4.4/libavfilter/vf_neighbor.c --- ffmpeg-4.2.2/libavfilter/vf_neighbor.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_neighbor.c 2021-04-08 21:28:40.000000000 +0000 @@ -64,6 +64,7 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, @@ -296,9 +297,11 @@ src + (width - 2) * bpc, src + (width - 2) * bpc, src + (width - 2) * bpc + ph * stride, src + (width - 1) * bpc + ph * stride, src + (width - 2) * bpc + ph * stride}; - s->filter(dst, src, 1, threshold, coordinateslb, s->coordinates, s->max); - s->filter(dst + 1 * bpc, src + 1 * bpc, width - 2, threshold, coordinates, s->coordinates, s->max); - s->filter(dst + (width - 1) * bpc, src + (width - 1) * bpc, 1, threshold, coordinatesrb, s->coordinates, s->max); + s->filter(dst, src, 1, threshold, coordinateslb, s->coordinates, s->max); + if (width > 1) { + s->filter(dst + 1 * bpc, src + 1 * bpc, width - 2, threshold, coordinates, s->coordinates, s->max); + s->filter(dst + (width - 1) * bpc, src + (width - 1) * bpc, 1, threshold, coordinatesrb, s->coordinates, s->max); + } src += stride; dst += dstride; @@ -350,7 +353,7 @@ }; #define OFFSET(x) offsetof(NContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM #define DEFINE_NEIGHBOR_FILTER(name_, description_) \ AVFILTER_DEFINE_CLASS(name_); \ @@ -365,62 +368,47 @@ .outputs = neighbor_outputs, \ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC| \ AVFILTER_FLAG_SLICE_THREADS, \ + .process_command = ff_filter_process_command, \ } -#if CONFIG_EROSION_FILTER - -static const AVOption erosion_options[] = { +/* The following options are shared between all filters here; + * the de/inflate filters only use the threshold* options. */ +#define DEINFLATE_OPTIONS_OFFSET (CONFIG_EROSION_FILTER || CONFIG_DILATION_FILTER) +static const AVOption options[] = { +#if CONFIG_EROSION_FILTER || CONFIG_DILATION_FILTER + { "coordinates", "set coordinates", OFFSET(coordinates), AV_OPT_TYPE_INT, {.i64=255}, 0, 255, FLAGS }, +#endif { "threshold0", "set threshold for 1st plane", OFFSET(threshold[0]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, { "threshold1", "set threshold for 2nd plane", OFFSET(threshold[1]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, { "threshold2", "set threshold for 3rd plane", OFFSET(threshold[2]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, { "threshold3", "set threshold for 4th plane", OFFSET(threshold[3]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { "coordinates", "set coordinates", OFFSET(coordinates), AV_OPT_TYPE_INT, {.i64=255}, 0, 255, FLAGS }, { NULL } }; +#if CONFIG_EROSION_FILTER + +#define erosion_options options DEFINE_NEIGHBOR_FILTER(erosion, "Apply erosion effect."); #endif /* CONFIG_EROSION_FILTER */ #if CONFIG_DILATION_FILTER -static const AVOption dilation_options[] = { - { "threshold0", "set threshold for 1st plane", OFFSET(threshold[0]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { "threshold1", "set threshold for 2nd plane", OFFSET(threshold[1]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { "threshold2", "set threshold for 3rd plane", OFFSET(threshold[2]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { "threshold3", "set threshold for 4th plane", OFFSET(threshold[3]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { "coordinates", "set coordinates", OFFSET(coordinates), AV_OPT_TYPE_INT, {.i64=255}, 0, 255, FLAGS }, - { NULL } -}; - +#define dilation_options options DEFINE_NEIGHBOR_FILTER(dilation, "Apply dilation effect."); #endif /* CONFIG_DILATION_FILTER */ #if CONFIG_DEFLATE_FILTER -static const AVOption deflate_options[] = { - { "threshold0", "set threshold for 1st plane", OFFSET(threshold[0]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { "threshold1", "set threshold for 2nd plane", OFFSET(threshold[1]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { "threshold2", "set threshold for 3rd plane", OFFSET(threshold[2]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { "threshold3", "set threshold for 4th plane", OFFSET(threshold[3]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { NULL } -}; - +#define deflate_options &options[DEINFLATE_OPTIONS_OFFSET] DEFINE_NEIGHBOR_FILTER(deflate, "Apply deflate effect."); #endif /* CONFIG_DEFLATE_FILTER */ #if CONFIG_INFLATE_FILTER -static const AVOption inflate_options[] = { - { "threshold0", "set threshold for 1st plane", OFFSET(threshold[0]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { "threshold1", "set threshold for 2nd plane", OFFSET(threshold[1]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { "threshold2", "set threshold for 3rd plane", OFFSET(threshold[2]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { "threshold3", "set threshold for 4th plane", OFFSET(threshold[3]), AV_OPT_TYPE_INT, {.i64=65535}, 0, 65535, FLAGS }, - { NULL } -}; - +#define inflate_options &options[DEINFLATE_OPTIONS_OFFSET] DEFINE_NEIGHBOR_FILTER(inflate, "Apply inflate effect."); #endif /* CONFIG_INFLATE_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/vf_nlmeans.c ffmpeg-4.4/libavfilter/vf_nlmeans.c --- ffmpeg-4.2.2/libavfilter/vf_nlmeans.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_nlmeans.c 2020-07-11 10:39:30.000000000 +0000 @@ -419,7 +419,7 @@ // 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); + dst[x] = av_clip_uint8(wa[x].sum / wa[x].total_weight + 0.5f); } dst += dst_linesize; src += src_linesize; diff -Nru ffmpeg-4.2.2/libavfilter/vf_nnedi.c ffmpeg-4.4/libavfilter/vf_nnedi.c --- ffmpeg-4.2.2/libavfilter/vf_nnedi.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_nnedi.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,9 +21,11 @@ #include +#include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/float_dsp.h" #include "libavutil/imgutils.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avfilter.h" @@ -31,44 +33,59 @@ #include "internal.h" #include "video.h" -typedef struct FrameData { - uint8_t *paddedp[3]; - int padded_stride[3]; - int padded_width[3]; - int padded_height[3]; - - uint8_t *dstp[3]; - int dst_stride[3]; - - int field[3]; - - int32_t *lcount[3]; - float *input; - float *temp; -} FrameData; +static const size_t NNEDI_WEIGHTS_SIZE = 13574928; +static const uint8_t NNEDI_XDIM[] = { 8, 16, 32, 48, 8, 16, 32 }; +static const uint8_t NNEDI_YDIM[] = { 6, 6, 6, 6, 4, 4, 4 }; +static const uint16_t NNEDI_NNS[] = { 16, 32, 64, 128, 256 }; + +typedef struct PrescreenerCoefficients { + DECLARE_ALIGNED(32, float, kernel_l0)[4][16 * 4]; + DECLARE_ALIGNED(32, float, bias_l0)[4]; + + DECLARE_ALIGNED(32, float, kernel_l1)[4][4]; + DECLARE_ALIGNED(32, float, bias_l1)[4]; + + DECLARE_ALIGNED(32, float, kernel_l2)[4][8]; + DECLARE_ALIGNED(32, float, bias_l2)[4]; +} PrescreenerCoefficients; + +typedef struct PredictorCoefficients { + int xdim, ydim, nns, nsize; + float *data; + float *softmax_q1; + float *elliott_q1; + float *softmax_bias_q1; + float *elliott_bias_q1; + float *softmax_q2; + float *elliott_q2; + float *softmax_bias_q2; + float *elliott_bias_q2; +} PredictorCoefficients; typedef struct NNEDIContext { const AVClass *class; char *weights_file; - AVFrame *src; - AVFrame *second; - AVFrame *dst; + AVFrame *prev; int eof; - int64_t cur_pts; + int64_t pts; AVFloatDSPContext *fdsp; + int depth; int nb_planes; + int nb_threads; int linesize[4]; + int planewidth[4]; int planeheight[4]; + int field_n; + + PrescreenerCoefficients prescreener[4]; + PredictorCoefficients coeffs[2][5][7]; - float *weights0; - float *weights1[2]; - int asize; - int nns; - int xdia; - int ydia; + float half; + float in_scale; + float out_scale; // Parameters int deint; @@ -79,104 +96,85 @@ int qual; int etype; int pscrn; - int fapprox; - - int max_value; - - void (*copy_pad)(const AVFrame *, FrameData *, struct NNEDIContext *, int); - void (*evalfunc_0)(struct NNEDIContext *, FrameData *); - void (*evalfunc_1)(struct NNEDIContext *, FrameData *); - - // Functions used in evalfunc_0 - void (*readpixels)(const uint8_t *, const int, float *); - void (*compute_network0)(struct NNEDIContext *s, const float *, const float *, uint8_t *); - int32_t (*process_line0)(const uint8_t *, int, uint8_t *, const uint8_t *, const int, const int, const int); - - // Functions used in evalfunc_1 - void (*extract)(const uint8_t *, const int, const int, const int, float *, float *); - void (*dot_prod)(struct NNEDIContext *, const float *, const float *, float *, const int, const int, const float *); - void (*expfunc)(float *, const int); - void (*wae5)(const float *, const int, float *); - FrameData frame_data; + int input_size; + uint8_t **prescreen_buf; + float **input_buf; + float **output_buf; + + void (*read)(const uint8_t *src, float *dst, + int src_stride, int dst_stride, + int width, int height, float scale); + void (*write)(const float *src, uint8_t *dst, + int src_stride, int dst_stride, + int width, int height, int depth, float scale); + void (*prescreen[2])(AVFilterContext *ctx, + const void *src, ptrdiff_t src_stride, + uint8_t *prescreen, int N, + const PrescreenerCoefficients *const coeffs); } NNEDIContext; #define OFFSET(x) offsetof(NNEDIContext, x) +#define RFLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption nnedi_options[] = { {"weights", "set weights file", OFFSET(weights_file), AV_OPT_TYPE_STRING, {.str="nnedi3_weights.bin"}, 0, 0, FLAGS }, - {"deint", "set which frames to deinterlace", OFFSET(deint), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "deint" }, - {"all", "deinterlace all frames", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "deint" }, - {"interlaced", "only deinterlace frames marked as interlaced", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "deint" }, - {"field", "set mode of operation", OFFSET(field), AV_OPT_TYPE_INT, {.i64=-1}, -2, 3, FLAGS, "field" }, - {"af", "use frame flags, both fields", 0, AV_OPT_TYPE_CONST, {.i64=-2}, 0, 0, FLAGS, "field" }, - {"a", "use frame flags, single field", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "field" }, - {"t", "use top field only", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "field" }, - {"b", "use bottom field only", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "field" }, - {"tf", "use both fields, top first", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "field" }, - {"bf", "use both fields, bottom first", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "field" }, - {"planes", "set which planes to process", OFFSET(process_plane), AV_OPT_TYPE_INT, {.i64=7}, 0, 7, FLAGS }, - {"nsize", "set size of local neighborhood around each pixel, used by the predictor neural network", OFFSET(nsize), AV_OPT_TYPE_INT, {.i64=6}, 0, 6, FLAGS, "nsize" }, - {"s8x6", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "nsize" }, - {"s16x6", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "nsize" }, - {"s32x6", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "nsize" }, - {"s48x6", NULL, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "nsize" }, - {"s8x4", NULL, 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, FLAGS, "nsize" }, - {"s16x4", NULL, 0, AV_OPT_TYPE_CONST, {.i64=5}, 0, 0, FLAGS, "nsize" }, - {"s32x4", NULL, 0, AV_OPT_TYPE_CONST, {.i64=6}, 0, 0, FLAGS, "nsize" }, - {"nns", "set number of neurons in predictor neural network", OFFSET(nnsparam), AV_OPT_TYPE_INT, {.i64=1}, 0, 4, FLAGS, "nns" }, - {"n16", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "nns" }, - {"n32", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "nns" }, - {"n64", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "nns" }, - {"n128", NULL, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "nns" }, - {"n256", NULL, 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, FLAGS, "nns" }, - {"qual", "set quality", OFFSET(qual), AV_OPT_TYPE_INT, {.i64=1}, 1, 2, FLAGS, "qual" }, - {"fast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "qual" }, - {"slow", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "qual" }, - {"etype", "set which set of weights to use in the predictor", OFFSET(etype), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "etype" }, - {"a", "weights trained to minimize absolute error", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "etype" }, - {"s", "weights trained to minimize squared error", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "etype" }, - {"pscrn", "set prescreening", OFFSET(pscrn), AV_OPT_TYPE_INT, {.i64=2}, 0, 2, FLAGS, "pscrn" }, - {"none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "pscrn" }, - {"original", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "pscrn" }, - {"new", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "pscrn" }, - {"fapprox", NULL, OFFSET(fapprox), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS }, + {"deint", "set which frames to deinterlace", OFFSET(deint), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, RFLAGS, "deint" }, + {"all", "deinterlace all frames", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, RFLAGS, "deint" }, + {"interlaced", "only deinterlace frames marked as interlaced", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, RFLAGS, "deint" }, + {"field", "set mode of operation", OFFSET(field), AV_OPT_TYPE_INT, {.i64=-1}, -2, 3, RFLAGS, "field" }, + {"af", "use frame flags, both fields", 0, AV_OPT_TYPE_CONST, {.i64=-2}, 0, 0, RFLAGS, "field" }, + {"a", "use frame flags, single field", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, RFLAGS, "field" }, + {"t", "use top field only", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, RFLAGS, "field" }, + {"b", "use bottom field only", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, RFLAGS, "field" }, + {"tf", "use both fields, top first", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, RFLAGS, "field" }, + {"bf", "use both fields, bottom first", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, RFLAGS, "field" }, + {"planes", "set which planes to process", OFFSET(process_plane), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, RFLAGS }, + {"nsize", "set size of local neighborhood around each pixel, used by the predictor neural network", OFFSET(nsize), AV_OPT_TYPE_INT, {.i64=6}, 0, 6, RFLAGS, "nsize" }, + {"s8x6", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, RFLAGS, "nsize" }, + {"s16x6", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, RFLAGS, "nsize" }, + {"s32x6", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, RFLAGS, "nsize" }, + {"s48x6", NULL, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, RFLAGS, "nsize" }, + {"s8x4", NULL, 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, RFLAGS, "nsize" }, + {"s16x4", NULL, 0, AV_OPT_TYPE_CONST, {.i64=5}, 0, 0, RFLAGS, "nsize" }, + {"s32x4", NULL, 0, AV_OPT_TYPE_CONST, {.i64=6}, 0, 0, RFLAGS, "nsize" }, + {"nns", "set number of neurons in predictor neural network", OFFSET(nnsparam), AV_OPT_TYPE_INT, {.i64=1}, 0, 4, RFLAGS, "nns" }, + {"n16", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, RFLAGS, "nns" }, + {"n32", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, RFLAGS, "nns" }, + {"n64", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, RFLAGS, "nns" }, + {"n128", NULL, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, RFLAGS, "nns" }, + {"n256", NULL, 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, RFLAGS, "nns" }, + {"qual", "set quality", OFFSET(qual), AV_OPT_TYPE_INT, {.i64=1}, 1, 2, RFLAGS, "qual" }, + {"fast", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, RFLAGS, "qual" }, + {"slow", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, RFLAGS, "qual" }, + {"etype", "set which set of weights to use in the predictor", OFFSET(etype), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, RFLAGS, "etype" }, + {"a", "weights trained to minimize absolute error", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, RFLAGS, "etype" }, + {"abs","weights trained to minimize absolute error", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, RFLAGS, "etype" }, + {"s", "weights trained to minimize squared error", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, RFLAGS, "etype" }, + {"mse","weights trained to minimize squared error", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, RFLAGS, "etype" }, + {"pscrn", "set prescreening", OFFSET(pscrn), AV_OPT_TYPE_INT, {.i64=2}, 0, 4, RFLAGS, "pscrn" }, + {"none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, RFLAGS, "pscrn" }, + {"original", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, RFLAGS, "pscrn" }, + {"new", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, RFLAGS, "pscrn" }, + {"new2", NULL, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, RFLAGS, "pscrn" }, + {"new3", NULL, 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, RFLAGS, "pscrn" }, { NULL } }; AVFILTER_DEFINE_CLASS(nnedi); -static int config_input(AVFilterLink *inlink) -{ - AVFilterContext *ctx = inlink->dst; - NNEDIContext *s = ctx->priv; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - int ret; - - s->nb_planes = av_pix_fmt_count_planes(inlink->format); - if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) - return ret; - - s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); - s->planeheight[0] = s->planeheight[3] = inlink->h; - - return 0; -} - static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; - NNEDIContext *s = ctx->priv; outlink->time_base.num = ctx->inputs[0]->time_base.num; outlink->time_base.den = ctx->inputs[0]->time_base.den * 2; outlink->w = ctx->inputs[0]->w; outlink->h = ctx->inputs[0]->h; - if (s->field > 1 || s->field == -2) - outlink->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate, - (AVRational){2, 1}); + outlink->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate, + (AVRational){2, 1}); return 0; } @@ -184,14 +182,28 @@ static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_GRAY8, + AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ411P, - AV_PIX_FMT_GBRP, - AV_PIX_FMT_GRAY8, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; @@ -201,728 +213,758 @@ return ff_set_common_formats(ctx, fmts_list); } -static void copy_pad(const AVFrame *src, FrameData *frame_data, NNEDIContext *s, int fn) +static float dot_dsp(const NNEDIContext *const s, const float *kernel, const float *input, + int n, float scale, float bias) { - const int off = 1 - fn; - int plane, y, x; - - for (plane = 0; plane < s->nb_planes; plane++) { - const uint8_t *srcp = (const uint8_t *)src->data[plane]; - uint8_t *dstp = (uint8_t *)frame_data->paddedp[plane]; + float sum, y; - const int src_stride = src->linesize[plane]; - const int dst_stride = frame_data->padded_stride[plane]; + sum = s->fdsp->scalarproduct_float(kernel, input, n); - const int src_height = s->planeheight[plane]; - const int dst_height = frame_data->padded_height[plane]; + y = sum * scale + bias + 1e-20f; - const int src_width = s->linesize[plane]; - const int dst_width = frame_data->padded_width[plane]; + return y; +} - int c = 4; +static float elliott(float x) +{ + return x / (1.0f + fabsf(x)); +} - if (!(s->process_plane & (1 << plane))) - continue; +static void transform_elliott(float *input, int size) +{ + for (int i = 0; i < size; i++) + input[i] = elliott(input[i]); +} - // Copy. - for (y = off; y < src_height; y += 2) - memcpy(dstp + 32 + (6 + y) * dst_stride, - srcp + y * src_stride, - src_width * sizeof(uint8_t)); - - // And pad. - dstp += (6 + off) * dst_stride; - for (y = 6 + off; y < dst_height - 6; y += 2) { - int c = 2; +static void process_old(AVFilterContext *ctx, + const void *src, ptrdiff_t src_stride, + uint8_t *prescreen, int N, + const PrescreenerCoefficients *const m_data) +{ + NNEDIContext *s = ctx->priv; + const float *src_p = src; - for (x = 0; x < 32; x++) - dstp[x] = dstp[64 - x]; + // Adjust source pointer to point to top-left of filter window. + const float *window = src_p - 2 * src_stride - 5; - for (x = dst_width - 32; x < dst_width; x++, c += 2) - dstp[x] = dstp[x - c]; + for (int j = 0; j < N; j++) { + LOCAL_ALIGNED_32(float, input, [48]); + float state[12]; - dstp += dst_stride * 2; - } + for (int i = 0; i < 4; i++) + memcpy(input + i * 12, window + i * src_stride + j, 12 * sizeof(float)); - dstp = (uint8_t *)frame_data->paddedp[plane]; - for (y = off; y < 6; y += 2) - memcpy(dstp + y * dst_stride, - dstp + (12 + 2 * off - y) * dst_stride, - dst_width * sizeof(uint8_t)); + // Layer 0. + for (int n = 0; n < 4; n++) + state[n] = dot_dsp(s, m_data->kernel_l0[n], input, 48, 1.0f, m_data->bias_l0[n]); + transform_elliott(state + 1, 3); - for (y = dst_height - 6 + off; y < dst_height; y += 2, c += 4) - memcpy(dstp + y * dst_stride, - dstp + (y - c) * dst_stride, - dst_width * sizeof(uint8_t)); - } -} + // Layer 1. + for (int n = 0; n < 4; n++) + state[n + 4] = dot_dsp(s, m_data->kernel_l1[n], state, 4, 1.0f, m_data->bias_l1[n]); + transform_elliott(state + 4, 3); -static void elliott(float *data, const int n) -{ - int i; + // Layer 2. + for (int n = 0; n < 4; n++) + state[n + 8] = dot_dsp(s, m_data->kernel_l2[n], state, 8, 1.0f, m_data->bias_l2[n]); - for (i = 0; i < n; i++) - data[i] = data[i] / (1.0f + FFABS(data[i])); + prescreen[j] = FFMAX(state[10], state[11]) <= FFMAX(state[8], state[9]) ? 255 : 0; + } } -static void dot_prod(NNEDIContext *s, const float *data, const float *weights, float *vals, const int n, const int len, const float *scale) +static void process_new(AVFilterContext *ctx, + const void *src, ptrdiff_t src_stride, + uint8_t *prescreen, int N, + const PrescreenerCoefficients *const m_data) { - int i; + NNEDIContext *s = ctx->priv; + const float *src_p = src; - for (i = 0; i < n; i++) { - float sum; + // Adjust source pointer to point to top-left of filter window. + const float *window = src_p - 2 * src_stride - 6; - sum = s->fdsp->scalarproduct_float(data, &weights[i * len], len); + for (int j = 0; j < N; j += 4) { + LOCAL_ALIGNED_32(float, input, [64]); + float state[8]; - vals[i] = sum * scale[0] + weights[n * len + i]; - } -} + for (int i = 0; i < 4; i++) + memcpy(input + i * 16, window + i * src_stride + j, 16 * sizeof(float)); -static void dot_prods(NNEDIContext *s, const float *dataf, const float *weightsf, float *vals, const int n, const int len, const float *scale) -{ - const int16_t *data = (int16_t *)dataf; - const int16_t *weights = (int16_t *)weightsf; - const float *wf = (float *)&weights[n * len]; - int i, j; + for (int n = 0; n < 4; n++) + state[n] = dot_dsp(s, m_data->kernel_l0[n], input, 64, 1.0f, m_data->bias_l0[n]); + transform_elliott(state, 4); - for (i = 0; i < n; i++) { - int sum = 0, off = ((i >> 2) << 3) + (i & 3); - for (j = 0; j < len; j++) - sum += data[j] * weights[i * len + j]; + for (int n = 0; n < 4; n++) + state[n + 4] = dot_dsp(s, m_data->kernel_l1[n], state, 4, 1.0f, m_data->bias_l1[n]); - vals[i] = sum * wf[off] * scale[0] + wf[off + 4]; + for (int n = 0; n < 4; n++) + prescreen[j + n] = state[n + 4] > 0.f; } } -static void compute_network0(NNEDIContext *s, const float *input, const float *weights, uint8_t *d) +static int filter_offset(int nn, const PredictorCoefficients *const model) { - float t, temp[12], scale = 1.0f; - - dot_prod(s, input, weights, temp, 4, 48, &scale); - t = temp[0]; - elliott(temp, 4); - temp[0] = t; - dot_prod(s, temp, weights + 4 * 49, temp + 4, 4, 4, &scale); - elliott(temp + 4, 4); - dot_prod(s, temp, weights + 4 * 49 + 4 * 5, temp + 8, 4, 8, &scale); - if (FFMAX(temp[10], temp[11]) <= FFMAX(temp[8], temp[9])) - d[0] = 1; - else - d[0] = 0; + return nn * model->nsize; } -static void compute_network0_i16(NNEDIContext *s, const float *inputf, const float *weightsf, uint8_t *d) +static const float *softmax_q1_filter(int nn, + const PredictorCoefficients *const model) { - const float *wf = weightsf + 2 * 48; - float t, temp[12], scale = 1.0f; - - dot_prods(s, inputf, weightsf, temp, 4, 48, &scale); - t = temp[0]; - elliott(temp, 4); - temp[0] = t; - dot_prod(s, temp, wf + 8, temp + 4, 4, 4, &scale); - elliott(temp + 4, 4); - dot_prod(s, temp, wf + 8 + 4 * 5, temp + 8, 4, 8, &scale); - if (FFMAX(temp[10], temp[11]) <= FFMAX(temp[8], temp[9])) - d[0] = 1; - else - d[0] = 0; + return model->softmax_q1 + filter_offset(nn, model); } -static void pixel2float48(const uint8_t *t8, const int pitch, float *p) +static const float *elliott_q1_filter(int nn, + const PredictorCoefficients *const model) { - const uint8_t *t = (const uint8_t *)t8; - int y, x; - - for (y = 0; y < 4; y++) - for (x = 0; x < 12; x++) - p[y * 12 + x] = t[y * pitch * 2 + x]; + return model->elliott_q1 + filter_offset(nn, model); } -static void byte2word48(const uint8_t *t, const int pitch, float *pf) +static const float *softmax_q2_filter(int nn, + const PredictorCoefficients *const model) { - int16_t *p = (int16_t *)pf; - int y, x; - - for (y = 0; y < 4; y++) - for (x = 0; x < 12; x++) - p[y * 12 + x] = t[y * pitch * 2 + x]; + return model->softmax_q2 + filter_offset(nn, model); } -static int32_t process_line0(const uint8_t *tempu, int width, uint8_t *dstp8, const uint8_t *src3p8, const int src_pitch, const int max_value, const int chroma) +static const float *elliott_q2_filter(int nn, + const PredictorCoefficients *const model) { - uint8_t *dstp = (uint8_t *)dstp8; - const uint8_t *src3p = (const uint8_t *)src3p8; - int minimum = 0; - int maximum = max_value - 1; // Technically the -1 is only needed for 8 and 16 bit input. - int count = 0, x; - for (x = 0; x < width; x++) { - if (tempu[x]) { - int tmp = 19 * (src3p[x + src_pitch * 2] + src3p[x + src_pitch * 4]) - 3 * (src3p[x] + src3p[x + src_pitch * 6]); - tmp /= 32; - dstp[x] = FFMAX(FFMIN(tmp, maximum), minimum); - } else { - dstp[x] = 255; - count++; - } - } - return count; + return model->elliott_q2 + filter_offset(nn, model); } -// new prescreener functions -static void byte2word64(const uint8_t *t, const int pitch, float *p) +static void gather_input(const float *src, ptrdiff_t src_stride, + float *buf, float mstd[4], + const PredictorCoefficients *const model) { - int16_t *ps = (int16_t *)p; - int y, x; + const float scale = 1.f / model->nsize; + float sum = 0.f; + float sum_sq = 0.f; + float tmp; - for (y = 0; y < 4; y++) - for (x = 0; x < 16; x++) - ps[y * 16 + x] = t[y * pitch * 2 + x]; -} + for (int i = 0; i < model->ydim; i++) { + memcpy(buf, src, model->xdim * sizeof(float)); -static void compute_network0new(NNEDIContext *s, const float *datai, const float *weights, uint8_t *d) -{ - int16_t *data = (int16_t *)datai; - int16_t *ws = (int16_t *)weights; - float *wf = (float *)&ws[4 * 64]; - float vals[8]; - int mask, i, j; + for (int j = 0; j < model->xdim; j++) { + const float val = src[j]; - for (i = 0; i < 4; i++) { - int sum = 0; - float t; + sum += val; + sum_sq += val * val; + } - for (j = 0; j < 64; j++) - sum += data[j] * ws[(i << 3) + ((j >> 3) << 5) + (j & 7)]; - t = sum * wf[i] + wf[4 + i]; - vals[i] = t / (1.0f + FFABS(t)); + src += src_stride; + buf += model->xdim; } - for (i = 0; i < 4; i++) { - float sum = 0.0f; + mstd[0] = sum * scale; + mstd[3] = 0.f; - for (j = 0; j < 4; j++) - sum += vals[j] * wf[8 + i + (j << 2)]; - vals[4 + i] = sum + wf[8 + 16 + i]; + tmp = sum_sq * scale - mstd[0] * mstd[0]; + if (tmp < FLT_EPSILON) { + mstd[1] = 0.0f; + mstd[2] = 0.0f; + } else { + mstd[1] = sqrtf(tmp); + mstd[2] = 1.0f / mstd[1]; } +} - mask = 0; - for (i = 0; i < 4; i++) { - if (vals[4 + i] > 0.0f) - mask |= (0x1 << (i << 3)); - } +static float softmax_exp(float x) +{ + return expf(av_clipf(x, -80.f, 80.f)); +} - ((int *)d)[0] = mask; +static void transform_softmax_exp(float *input, int size) +{ + for (int i = 0; i < size; i++) + input[i] = softmax_exp(input[i]); } -static void evalfunc_0(NNEDIContext *s, FrameData *frame_data) +static void wae5(const float *softmax, const float *el, + int n, float mstd[4]) { - float *input = frame_data->input; - const float *weights0 = s->weights0; - float *temp = frame_data->temp; - uint8_t *tempu = (uint8_t *)temp; - int plane, x, y; + float vsum = 0.0f, wsum = 0.0f; - // And now the actual work. - for (plane = 0; plane < s->nb_planes; plane++) { - const uint8_t *srcp = (const uint8_t *)frame_data->paddedp[plane]; - const int src_stride = frame_data->padded_stride[plane] / sizeof(uint8_t); + for (int i = 0; i < n; i++) { + vsum += softmax[i] * elliott(el[i]); + wsum += softmax[i]; + } - const int width = frame_data->padded_width[plane]; - const int height = frame_data->padded_height[plane]; + if (wsum > 1e-10f) + mstd[3] += (5.0f * vsum) / wsum * mstd[1] + mstd[0]; + else + mstd[3] += mstd[0]; +} - uint8_t *dstp = (uint8_t *)frame_data->dstp[plane]; - const int dst_stride = frame_data->dst_stride[plane] / sizeof(uint8_t); - const uint8_t *src3p; - int ystart, ystop; - int32_t *lcount; +static void predictor(AVFilterContext *ctx, + const void *src, ptrdiff_t src_stride, void *dst, + const uint8_t *prescreen, int N, + const PredictorCoefficients *const model, int use_q2) +{ + const NNEDIContext *const s = ctx->priv; + const float *src_p = src; + float *dst_p = dst; + + // Adjust source pointer to point to top-left of filter window. + const float *window = src_p - (model->ydim / 2) * src_stride - (model->xdim / 2 - 1); + const int filter_size = model->nsize; + const int nns = model->nns; + + for (int i = 0; i < N; i++) { + LOCAL_ALIGNED_32(float, input, [48 * 6]); + float activation[256 * 2]; + float mstd[4]; + float scale; - if (!(s->process_plane & (1 << plane))) + if (prescreen[i]) continue; - for (y = 1 - frame_data->field[plane]; y < height - 12; y += 2) { - memcpy(dstp + y * dst_stride, - srcp + 32 + (6 + y) * src_stride, - (width - 64) * sizeof(uint8_t)); + gather_input(window + i, src_stride, input, mstd, model); + scale = mstd[2]; - } + for (int nn = 0; nn < nns; nn++) + activation[nn] = dot_dsp(s, softmax_q1_filter(nn, model), input, filter_size, scale, model->softmax_bias_q1[nn]); - ystart = 6 + frame_data->field[plane]; - ystop = height - 6; - srcp += ystart * src_stride; - dstp += (ystart - 6) * dst_stride - 32; - src3p = srcp - src_stride * 3; - lcount = frame_data->lcount[plane] - 6; - - if (s->pscrn == 1) { // original - for (y = ystart; y < ystop; y += 2) { - for (x = 32; x < width - 32; x++) { - s->readpixels((const uint8_t *)(src3p + x - 5), src_stride, input); - s->compute_network0(s, input, weights0, tempu+x); - } - lcount[y] += s->process_line0(tempu + 32, width - 64, (uint8_t *)(dstp + 32), (const uint8_t *)(src3p + 32), src_stride, s->max_value, plane); - src3p += src_stride * 2; - dstp += dst_stride * 2; - } - } else if (s->pscrn > 1) { // new - for (y = ystart; y < ystop; y += 2) { - for (x = 32; x < width - 32; x += 4) { - s->readpixels((const uint8_t *)(src3p + x - 6), src_stride, input); - s->compute_network0(s, input, weights0, tempu + x); - } - lcount[y] += s->process_line0(tempu + 32, width - 64, (uint8_t *)(dstp + 32), (const uint8_t *)(src3p + 32), src_stride, s->max_value, plane); - src3p += src_stride * 2; - dstp += dst_stride * 2; - } - } else { // no prescreening - for (y = ystart; y < ystop; y += 2) { - memset(dstp + 32, 255, (width - 64) * sizeof(uint8_t)); - lcount[y] += width - 64; - dstp += dst_stride * 2; - } + for (int nn = 0; nn < nns; nn++) + activation[nns + nn] = dot_dsp(s, elliott_q1_filter(nn, model), input, filter_size, scale, model->elliott_bias_q1[nn]); + + transform_softmax_exp(activation, nns); + wae5(activation, activation + nns, nns, mstd); + + if (use_q2) { + for (int nn = 0; nn < nns; nn++) + activation[nn] = dot_dsp(s, softmax_q2_filter(nn, model), input, filter_size, scale, model->softmax_bias_q2[nn]); + + for (int nn = 0; nn < nns; nn++) + activation[nns + nn] = dot_dsp(s, elliott_q2_filter(nn, model), input, filter_size, scale, model->elliott_bias_q2[nn]); + + transform_softmax_exp(activation, nns); + wae5(activation, activation + nns, nns, mstd); } + + dst_p[i] = mstd[3] * (use_q2 ? 0.5f : 1.f); } } -static void extract_m8(const uint8_t *srcp8, const int stride, const int xdia, const int ydia, float *mstd, float *input) +static void read_bytes(const uint8_t *src, float *dst, + int src_stride, int dst_stride, + int width, int height, float scale) { - // uint8_t or uint16_t or float - const uint8_t *srcp = (const uint8_t *)srcp8; - float scale; - double tmp; - - // int32_t or int64_t or double - int64_t sum = 0, sumsq = 0; - int y, x; - - for (y = 0; y < ydia; y++) { - const uint8_t *srcpT = srcp + y * stride * 2; - - for (x = 0; x < xdia; x++) { - sum += srcpT[x]; - sumsq += (uint32_t)srcpT[x] * (uint32_t)srcpT[x]; - input[x] = srcpT[x]; - } - input += xdia; - } - scale = 1.0f / (xdia * ydia); - mstd[0] = sum * scale; - tmp = (double)sumsq * scale - (double)mstd[0] * mstd[0]; - mstd[3] = 0.0f; - if (tmp <= FLT_EPSILON) - mstd[1] = mstd[2] = 0.0f; - else { - mstd[1] = sqrt(tmp); - mstd[2] = 1.0f / mstd[1]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < 32; x++) + dst[-x - 1] = src[x]; + + for (int x = 0; x < width; x++) + dst[x] = src[x]; + + for (int x = 0; x < 32; x++) + dst[width + x] = src[width - x - 1]; + + dst += dst_stride; + src += src_stride; } } -static void extract_m8_i16(const uint8_t *srcp, const int stride, const int xdia, const int ydia, float *mstd, float *inputf) +static void read_words(const uint8_t *srcp, float *dst, + int src_stride, int dst_stride, + int width, int height, float scale) { - int16_t *input = (int16_t *)inputf; - float scale; - int sum = 0, sumsq = 0; - int y, x; - - for (y = 0; y < ydia; y++) { - const uint8_t *srcpT = srcp + y * stride * 2; - for (x = 0; x < xdia; x++) { - sum += srcpT[x]; - sumsq += srcpT[x] * srcpT[x]; - input[x] = srcpT[x]; - } - input += xdia; - } - scale = 1.0f / (float)(xdia * ydia); - mstd[0] = sum * scale; - mstd[1] = sumsq * scale - mstd[0] * mstd[0]; - mstd[3] = 0.0f; - if (mstd[1] <= FLT_EPSILON) - mstd[1] = mstd[2] = 0.0f; - else { - mstd[1] = sqrt(mstd[1]); - mstd[2] = 1.0f / mstd[1]; - } -} + const uint16_t *src = (const uint16_t *)srcp; + src_stride /= 2; -static const float exp_lo = -80.0f; -static const float exp_hi = +80.0f; + for (int y = 0; y < height; y++) { + for (int x = 0; x < 32; x++) + dst[-x - 1] = src[x] * scale; -static void e2_m16(float *s, const int n) -{ - int i; + for (int x = 0; x < width; x++) + dst[x] = src[x] * scale; - for (i = 0; i < n; i++) - s[i] = exp(av_clipf(s[i], exp_lo, exp_hi)); -} + for (int x = 0; x < 32; x++) + dst[width + x] = src[width - x - 1] * scale; -const float min_weight_sum = 1e-10f; + dst += dst_stride; + src += src_stride; + } +} -static void weighted_avg_elliott_mul5_m16(const float *w, const int n, float *mstd) +static void write_bytes(const float *src, uint8_t *dst, + int src_stride, int dst_stride, + int width, int height, int depth, + float scale) { - float vsum = 0.0f, wsum = 0.0f; - int i; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) + dst[x] = av_clip_uint8(src[x]); - for (i = 0; i < n; i++) { - vsum += w[i] * (w[n + i] / (1.0f + FFABS(w[n + i]))); - wsum += w[i]; + dst += dst_stride; + src += src_stride; } - if (wsum > min_weight_sum) - mstd[3] += ((5.0f * vsum) / wsum) * mstd[1] + mstd[0]; - else - mstd[3] += mstd[0]; } - -static void evalfunc_1(NNEDIContext *s, FrameData *frame_data) +static void write_words(const float *src, uint8_t *dstp, + int src_stride, int dst_stride, + int width, int height, int depth, + float scale) { - float *input = frame_data->input; - float *temp = frame_data->temp; - float **weights1 = s->weights1; - const int qual = s->qual; - const int asize = s->asize; - const int nns = s->nns; - const int xdia = s->xdia; - const int xdiad2m1 = (xdia / 2) - 1; - const int ydia = s->ydia; - const float scale = 1.0f / (float)qual; - int plane, y, x, i; - - for (plane = 0; plane < s->nb_planes; plane++) { - const uint8_t *srcp = (const uint8_t *)frame_data->paddedp[plane]; - const int src_stride = frame_data->padded_stride[plane] / sizeof(uint8_t); - - const int width = frame_data->padded_width[plane]; - const int height = frame_data->padded_height[plane]; - - uint8_t *dstp = (uint8_t *)frame_data->dstp[plane]; - const int dst_stride = frame_data->dst_stride[plane] / sizeof(uint8_t); - - const int ystart = frame_data->field[plane]; - const int ystop = height - 12; - const uint8_t *srcpp; + uint16_t *dst = (uint16_t *)dstp; - if (!(s->process_plane & (1 << plane))) - continue; + dst_stride /= 2; - srcp += (ystart + 6) * src_stride; - dstp += ystart * dst_stride - 32; - srcpp = srcp - (ydia - 1) * src_stride - xdiad2m1; - - for (y = ystart; y < ystop; y += 2) { - for (x = 32; x < width - 32; x++) { - float mstd[4]; - - if (dstp[x] != 255) - continue; - - s->extract((const uint8_t *)(srcpp + x), src_stride, xdia, ydia, mstd, input); - for (i = 0; i < qual; i++) { - s->dot_prod(s, input, weights1[i], temp, nns * 2, asize, mstd + 2); - s->expfunc(temp, nns); - s->wae5(temp, nns, mstd); - } + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) + dst[x] = av_clip_uintp2_c(src[x] * scale, depth); - dstp[x] = FFMIN(FFMAX((int)(mstd[3] * scale + 0.5f), 0), s->max_value); - } - srcpp += src_stride * 2; - dstp += dst_stride * 2; - } + dst += dst_stride; + src += src_stride; } } -#define NUM_NSIZE 7 -#define NUM_NNS 5 - -static int roundds(const double f) +static void interpolation(const void *src, ptrdiff_t src_stride, + void *dst, const uint8_t *prescreen, int n) { - if (f - floor(f) >= 0.5) - return FFMIN((int)ceil(f), 32767); - return FFMAX((int)floor(f), -32768); -} + const float *src_p = src; + float *dst_p = dst; + const float *window = src_p - 2 * src_stride; -static void select_functions(NNEDIContext *s) -{ - s->copy_pad = copy_pad; - s->evalfunc_0 = evalfunc_0; - s->evalfunc_1 = evalfunc_1; + for (int i = 0; i < n; i++) { + float accum = 0.0f; - // evalfunc_0 - s->process_line0 = process_line0; + if (!prescreen[i]) + continue; - if (s->pscrn < 2) { // original prescreener - if (s->fapprox & 1) { // int16 dot products - s->readpixels = byte2word48; - s->compute_network0 = compute_network0_i16; - } else { - s->readpixels = pixel2float48; - s->compute_network0 = compute_network0; - } - } else { // new prescreener - // only int16 dot products - s->readpixels = byte2word64; - s->compute_network0 = compute_network0new; + accum += (-3.0f / 32.0f) * window[0 * src_stride + i]; + accum += (19.0f / 32.0f) * window[1 * src_stride + i]; + accum += (19.0f / 32.0f) * window[2 * src_stride + i]; + accum += (-3.0f / 32.0f) * window[3 * src_stride + i]; + + dst_p[i] = accum; } +} - // evalfunc_1 - s->wae5 = weighted_avg_elliott_mul5_m16; +static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + const NNEDIContext *const s = ctx->priv; + AVFrame *out = arg; + AVFrame *in = s->prev; + const float in_scale = s->in_scale; + const float out_scale = s->out_scale; + const int depth = s->depth; + const int interlaced = in->interlaced_frame; + const int tff = s->field_n == (s->field < 0 ? interlaced ? in->top_field_first : 1 : + (s->field & 1) ^ 1); + + + for (int p = 0; p < s->nb_planes; p++) { + const int height = s->planeheight[p]; + const int width = s->planewidth[p]; + const int slice_start = 2 * ((height / 2 * jobnr) / nb_jobs); + const int slice_end = 2 * ((height / 2 * (jobnr+1)) / nb_jobs); + const uint8_t *src_data = in->data[p]; + uint8_t *dst_data = out->data[p]; + uint8_t *dst = out->data[p] + slice_start * out->linesize[p]; + const int src_linesize = in->linesize[p]; + const int dst_linesize = out->linesize[p]; + uint8_t *prescreen_buf = s->prescreen_buf[jobnr]; + float *srcbuf = s->input_buf[jobnr]; + const int srcbuf_stride = width + 64; + float *dstbuf = s->output_buf[jobnr]; + const int dstbuf_stride = width; + const int slice_height = (slice_end - slice_start) / 2; + const int last_slice = slice_end == height; + const uint8_t *in_line; + uint8_t *out_line; + int y_out; + + if (!(s->process_plane & (1 << p))) { + av_image_copy_plane(dst, out->linesize[p], + in->data[p] + slice_start * in->linesize[p], + in->linesize[p], + s->linesize[p], slice_end - slice_start); + continue; + } - if (s->fapprox & 2) { // use int16 dot products - s->extract = extract_m8_i16; - s->dot_prod = dot_prods; - } else { // use float dot products - s->extract = extract_m8; - s->dot_prod = dot_prod; - } + y_out = slice_start + (tff ^ (slice_start & 1)); + in_line = src_data + (y_out * src_linesize); + out_line = dst_data + (y_out * dst_linesize); + + while (y_out < slice_end) { + memcpy(out_line, in_line, s->linesize[p]); + y_out += 2; + in_line += src_linesize * 2; + out_line += dst_linesize * 2; + } + + y_out = slice_start + ((!tff) ^ (slice_start & 1)); + + s->read(src_data + FFMAX(y_out - 5, tff) * src_linesize, + srcbuf + 32, + src_linesize * 2, srcbuf_stride, + width, 1, in_scale); + srcbuf += srcbuf_stride; + + s->read(src_data + FFMAX(y_out - 3, tff) * src_linesize, + srcbuf + 32, + src_linesize * 2, srcbuf_stride, + width, 1, in_scale); + srcbuf += srcbuf_stride; + + s->read(src_data + FFMAX(y_out - 1, tff) * src_linesize, + srcbuf + 32, + src_linesize * 2, srcbuf_stride, + width, 1, in_scale); + srcbuf += srcbuf_stride; + + in_line = src_data + FFMIN(y_out + 1, height - 1 - !tff) * src_linesize; + out_line = dst_data + (y_out * dst_linesize); + + s->read(in_line, srcbuf + 32, src_linesize * 2, srcbuf_stride, + width, slice_height - last_slice, in_scale); + + y_out += (slice_height - last_slice) * 2; + + s->read(src_data + FFMIN(y_out + 1, height - 1 - !tff) * src_linesize, + srcbuf + 32 + srcbuf_stride * (slice_height - last_slice), + src_linesize * 2, srcbuf_stride, + width, 1, in_scale); + + s->read(src_data + FFMIN(y_out + 3, height - 1 - !tff) * src_linesize, + srcbuf + 32 + srcbuf_stride * (slice_height + 1 - last_slice), + src_linesize * 2, srcbuf_stride, + width, 1, in_scale); + + s->read(src_data + FFMIN(y_out + 5, height - 1 - !tff) * src_linesize, + srcbuf + 32 + srcbuf_stride * (slice_height + 2 - last_slice), + src_linesize * 2, srcbuf_stride, + width, 1, in_scale); + + for (int y = 0; y < slice_end - slice_start; y += 2) { + if (s->pscrn > 0) + s->prescreen[s->pscrn > 1](ctx, srcbuf + (y / 2) * srcbuf_stride + 32, + srcbuf_stride, prescreen_buf, width, + &s->prescreener[s->pscrn - 1]); + + predictor(ctx, + srcbuf + (y / 2) * srcbuf_stride + 32, + srcbuf_stride, + dstbuf + (y / 2) * dstbuf_stride, + prescreen_buf, width, + &s->coeffs[s->etype][s->nnsparam][s->nsize], s->qual == 2); + + if (s->pscrn > 0) + interpolation(srcbuf + (y / 2) * srcbuf_stride + 32, + srcbuf_stride, + dstbuf + (y / 2) * dstbuf_stride, + prescreen_buf, width); + } - s->expfunc = e2_m16; -} + s->write(dstbuf, out_line, dstbuf_stride, dst_linesize * 2, + width, slice_height, depth, out_scale); + } -static int modnpf(const int m, const int n) -{ - if ((m % n) == 0) - return m; - return m + n - (m % n); + return 0; } static int get_frame(AVFilterContext *ctx, int is_second) { NNEDIContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *src = s->src; - FrameData *frame_data; - int effective_field = s->field; - size_t temp_size; - int field_n; - int plane; - - if (effective_field > 1) - effective_field -= 2; - else if (effective_field < 0) - effective_field += 2; - - if (s->field < 0 && src->interlaced_frame && src->top_field_first == 0) - effective_field = 0; - else if (s->field < 0 && src->interlaced_frame && src->top_field_first == 1) - effective_field = 1; - else - effective_field = !effective_field; - - if (s->field > 1 || s->field == -2) { - if (is_second) { - field_n = (effective_field == 0); - } else { - field_n = (effective_field == 1); - } - } else { - field_n = effective_field; - } + AVFrame *dst; - s->dst = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!s->dst) + dst = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!dst) return AVERROR(ENOMEM); - av_frame_copy_props(s->dst, src); - s->dst->interlaced_frame = 0; + av_frame_copy_props(dst, s->prev); + dst->interlaced_frame = 0; + dst->pts = s->pts; - frame_data = &s->frame_data; + ctx->internal->execute(ctx, filter_slice, dst, NULL, FFMIN(s->planeheight[1] / 2, s->nb_threads)); - for (plane = 0; plane < s->nb_planes; plane++) { - int dst_height = s->planeheight[plane]; - int dst_width = s->linesize[plane]; - - const int min_alignment = 16; - const int min_pad = 10; - - if (!(s->process_plane & (1 << plane))) { - av_image_copy_plane(s->dst->data[plane], s->dst->linesize[plane], - src->data[plane], src->linesize[plane], - s->linesize[plane], - s->planeheight[plane]); - continue; - } + if (s->field == -2 || s->field > 1) + s->field_n = !s->field_n; - frame_data->padded_width[plane] = dst_width + 64; - frame_data->padded_height[plane] = dst_height + 12; - frame_data->padded_stride[plane] = modnpf(frame_data->padded_width[plane] + min_pad, min_alignment); // TODO: maybe min_pad is in pixels too? - if (!frame_data->paddedp[plane]) { - frame_data->paddedp[plane] = av_malloc_array(frame_data->padded_stride[plane], frame_data->padded_height[plane]); - if (!frame_data->paddedp[plane]) - return AVERROR(ENOMEM); - } + return ff_filter_frame(outlink, dst); +} - frame_data->dstp[plane] = s->dst->data[plane]; - frame_data->dst_stride[plane] = s->dst->linesize[plane]; +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + NNEDIContext *s = ctx->priv; + int ret; - if (!frame_data->lcount[plane]) { - frame_data->lcount[plane] = av_calloc(dst_height, sizeof(int32_t) * 16); - if (!frame_data->lcount[plane]) - return AVERROR(ENOMEM); - } else { - memset(frame_data->lcount[plane], 0, dst_height * sizeof(int32_t) * 16); - } + if (!s->prev) { + s->prev = in; + return 0; + } - frame_data->field[plane] = field_n; + if ((s->deint && !in->interlaced_frame) || ctx->is_disabled) { + s->prev->pts *= 2; + ret = ff_filter_frame(ctx->outputs[0], s->prev); + s->prev = in; + return ret; } - if (!frame_data->input) { - frame_data->input = av_malloc(512 * sizeof(float)); - if (!frame_data->input) - return AVERROR(ENOMEM); + s->pts = s->prev->pts * 2; + ret = get_frame(ctx, 0); + if (ret < 0 || (s->field > -2 && s->field < 2)) { + av_frame_free(&s->prev); + s->prev = in; + return ret; } - // evalfunc_0 requires at least padded_width[0] bytes. - // evalfunc_1 requires at least 512 floats. - if (!frame_data->temp) { - temp_size = FFMAX(frame_data->padded_width[0], 512 * sizeof(float)); - frame_data->temp = av_malloc(temp_size); - if (!frame_data->temp) + + s->pts = s->prev->pts + in->pts; + ret = get_frame(ctx, 1); + av_frame_free(&s->prev); + s->prev = in; + return ret; +} + +static int request_frame(AVFilterLink *link) +{ + AVFilterContext *ctx = link->src; + NNEDIContext *s = ctx->priv; + int ret; + + if (s->eof) + return AVERROR_EOF; + + ret = ff_request_frame(ctx->inputs[0]); + + if (ret == AVERROR_EOF && s->prev) { + AVFrame *next = av_frame_clone(s->prev); + + if (!next) return AVERROR(ENOMEM); + + next->pts = s->prev->pts + av_rescale_q(1, av_inv_q(ctx->outputs[0]->frame_rate), + ctx->outputs[0]->time_base); + s->eof = 1; + + ret = filter_frame(ctx->inputs[0], next); + } else if (ret < 0) { + return ret; } - // Copy src to a padded "frame" in frame_data and mirror the edges. - s->copy_pad(src, frame_data, s, field_n); + return ret; +} - // Handles prescreening and the cubic interpolation. - s->evalfunc_0(s, frame_data); +static void copy_weights(float *dst, int n, const float **data) +{ + memcpy(dst, *data, n * sizeof(float)); + *data += n; +} - // The rest. - s->evalfunc_1(s, frame_data); +static float *allocate(float **ptr, int size) +{ + float *ret = *ptr; + + *ptr += size; + + return ret; +} + +static int allocate_model(PredictorCoefficients *coeffs, int xdim, int ydim, int nns) +{ + int filter_size = nns * xdim * ydim; + int bias_size = nns; + float *data; + + data = av_calloc(filter_size + bias_size, 4 * sizeof(float)); + if (!data) + return AVERROR(ENOMEM); + + coeffs->data = data; + coeffs->xdim = xdim; + coeffs->ydim = ydim; + coeffs->nsize = xdim * ydim; + coeffs->nns = nns; + + coeffs->softmax_q1 = allocate(&data, filter_size); + coeffs->elliott_q1 = allocate(&data, filter_size); + coeffs->softmax_bias_q1 = allocate(&data, bias_size); + coeffs->elliott_bias_q1 = allocate(&data, bias_size); + + coeffs->softmax_q2 = allocate(&data, filter_size); + coeffs->elliott_q2 = allocate(&data, filter_size); + coeffs->softmax_bias_q2 = allocate(&data, bias_size); + coeffs->elliott_bias_q2 = allocate(&data, bias_size); return 0; } -static int filter_frame(AVFilterLink *inlink, AVFrame *src) +static int read_weights(AVFilterContext *ctx, const float *bdata) { - AVFilterContext *ctx = inlink->dst; - AVFilterLink *outlink = ctx->outputs[0]; NNEDIContext *s = ctx->priv; int ret; - if ((s->field > 1 || - s->field == -2) && !s->second) { - goto second; - } else if (s->field > 1 || - s->field == -2) { - AVFrame *dst; - - s->src = s->second; - ret = get_frame(ctx, 1); - if (ret < 0) { - av_frame_free(&s->dst); - av_frame_free(&s->src); - av_frame_free(&s->second); - return ret; - } - dst = s->dst; + copy_weights(&s->prescreener[0].kernel_l0[0][0], 4 * 48, &bdata); + copy_weights(s->prescreener[0].bias_l0, 4, &bdata); - if (src->pts != AV_NOPTS_VALUE && - dst->pts != AV_NOPTS_VALUE) - dst->pts += src->pts; - else - dst->pts = AV_NOPTS_VALUE; - - ret = ff_filter_frame(outlink, dst); - if (ret < 0) - return ret; - if (s->eof) - return 0; - s->cur_pts = s->second->pts; - av_frame_free(&s->second); -second: - if ((s->deint && src->interlaced_frame && - !ctx->is_disabled) || - (!s->deint && !ctx->is_disabled)) { - s->second = src; + copy_weights(&s->prescreener[0].kernel_l1[0][0], 4 * 4, &bdata); + copy_weights(s->prescreener[0].bias_l1, 4, &bdata); + + copy_weights(&s->prescreener[0].kernel_l2[0][0], 4 * 8, &bdata); + copy_weights(s->prescreener[0].bias_l2, 4, &bdata); + + for (int i = 0; i < 3; i++) { + PrescreenerCoefficients *data = &s->prescreener[i + 1]; + float kernel_l0_shuffled[4 * 64]; + float kernel_l1_shuffled[4 * 4]; + + copy_weights(kernel_l0_shuffled, 4 * 64, &bdata); + copy_weights(data->bias_l0, 4, &bdata); + + copy_weights(kernel_l1_shuffled, 4 * 4, &bdata); + copy_weights(data->bias_l1, 4, &bdata); + + for (int n = 0; n < 4; n++) { + for (int k = 0; k < 64; k++) + data->kernel_l0[n][k] = kernel_l0_shuffled[(k / 8) * 32 + n * 8 + k % 8]; + for (int k = 0; k < 4; k++) + data->kernel_l1[n][k] = kernel_l1_shuffled[k * 4 + n]; } } - if ((s->deint && !src->interlaced_frame) || ctx->is_disabled) { - AVFrame *dst = av_frame_clone(src); - if (!dst) { - av_frame_free(&src); - av_frame_free(&s->second); - return AVERROR(ENOMEM); - } + for (int m = 0; m < 2; m++) { + // Grouping by neuron count. + for (int i = 0; i < 5; i++) { + const int nns = NNEDI_NNS[i]; + + // Grouping by window size. + for (int j = 0; j < 7; j++) { + PredictorCoefficients *model = &s->coeffs[m][i][j]; + const int xdim = NNEDI_XDIM[j]; + const int ydim = NNEDI_YDIM[j]; + const int filter_size = xdim * ydim; + + ret = allocate_model(model, xdim, ydim, nns); + if (ret < 0) + return ret; - if (s->field > 1 || s->field == -2) { - av_frame_free(&s->second); - if ((s->deint && src->interlaced_frame) || - (!s->deint)) - s->second = src; - } else { - av_frame_free(&src); + // Quality 1 model. NNS[i] * (XDIM[j] * YDIM[j]) * 2 coefficients. + copy_weights(model->softmax_q1, nns * filter_size, &bdata); + copy_weights(model->elliott_q1, nns * filter_size, &bdata); + + // Quality 1 model bias. NNS[i] * 2 coefficients. + copy_weights(model->softmax_bias_q1, nns, &bdata); + copy_weights(model->elliott_bias_q1, nns, &bdata); + + // Quality 2 model. NNS[i] * (XDIM[j] * YDIM[j]) * 2 coefficients. + copy_weights(model->softmax_q2, nns * filter_size, &bdata); + copy_weights(model->elliott_q2, nns * filter_size, &bdata); + + // Quality 2 model bias. NNS[i] * 2 coefficients. + copy_weights(model->softmax_bias_q2, nns, &bdata); + copy_weights(model->elliott_bias_q2, nns, &bdata); + } } - if (dst->pts != AV_NOPTS_VALUE) - dst->pts *= 2; - return ff_filter_frame(outlink, dst); } - s->src = src; - ret = get_frame(ctx, 0); - if (ret < 0) { - av_frame_free(&s->dst); - av_frame_free(&s->src); - av_frame_free(&s->second); - return ret; - } + return 0; +} + +static float mean(const float *input, int size) +{ + float sum = 0.f; + + for (int i = 0; i < size; i++) + sum += input[i]; + + return sum / size; +} + +static void transform(float *input, int size, float mean, float half) +{ + for (int i = 0; i < size; i++) + input[i] = (input[i] - mean) / half; +} + +static void subtract_mean_old(PrescreenerCoefficients *coeffs, float half) +{ + for (int n = 0; n < 4; n++) { + float m = mean(coeffs->kernel_l0[n], 48); - if (src->pts != AV_NOPTS_VALUE) - s->dst->pts = src->pts * 2; - if (s->field <= 1 && s->field > -2) { - av_frame_free(&src); - s->src = NULL; + transform(coeffs->kernel_l0[n], 48, m, half); } +} - return ff_filter_frame(outlink, s->dst); +static void subtract_mean_new(PrescreenerCoefficients *coeffs, float half) +{ + for (int n = 0; n < 4; n++) { + float m = mean(coeffs->kernel_l0[n], 64); + + transform(coeffs->kernel_l0[n], 64, m, half); + } } -static int request_frame(AVFilterLink *link) +static void subtract_mean_predictor(PredictorCoefficients *model) { - AVFilterContext *ctx = link->src; - NNEDIContext *s = ctx->priv; - int ret; + const int filter_size = model->nsize; + const int nns = model->nns; + const float scale = 1.f / nns; - if (s->eof) - return AVERROR_EOF; + double softmax_means[256]; // Average of individual softmax filters. + double elliott_means[256]; // Average of individual elliott filters. + double mean_filter[48 * 6] = { 0 }; // Pointwise average of all softmax filters. + double mean_bias; - ret = ff_request_frame(ctx->inputs[0]); + // Quality 1. + for (int nn = 0; nn < nns; nn++) { + softmax_means[nn] = mean(model->softmax_q1 + nn * filter_size, filter_size); + elliott_means[nn] = mean(model->elliott_q1 + nn * filter_size, filter_size); - if (ret == AVERROR_EOF && s->second) { - AVFrame *next = av_frame_clone(s->second); + for (int k = 0; k < filter_size; k++) + mean_filter[k] += model->softmax_q1[nn * filter_size + k] - softmax_means[nn]; + } - if (!next) - return AVERROR(ENOMEM); + for (int k = 0; k < filter_size; k++) + mean_filter[k] *= scale; - next->pts = s->second->pts * 2 - s->cur_pts; - s->eof = 1; + mean_bias = mean(model->softmax_bias_q1, nns); - filter_frame(ctx->inputs[0], next); - } else if (ret < 0) { - return ret; + for (int nn = 0; nn < nns; nn++) { + for (int k = 0; k < filter_size; k++) { + model->softmax_q1[nn * filter_size + k] -= softmax_means[nn] + mean_filter[k]; + model->elliott_q1[nn * filter_size + k] -= elliott_means[nn]; + } + model->softmax_bias_q1[nn] -= mean_bias; } - return 0; + // Quality 2. + memset(mean_filter, 0, sizeof(mean_filter)); + + for (int nn = 0; nn < nns; nn++) { + softmax_means[nn] = mean(model->softmax_q2 + nn * filter_size, filter_size); + elliott_means[nn] = mean(model->elliott_q2 + nn * filter_size, filter_size); + + for (int k = 0; k < filter_size; k++) { + mean_filter[k] += model->softmax_q2[nn * filter_size + k] - softmax_means[nn]; + } + } + + for (int k = 0; k < filter_size; k++) + mean_filter[k] *= scale; + + mean_bias = mean(model->softmax_bias_q2, nns); + + for (int nn = 0; nn < nns; nn++) { + for (int k = 0; k < filter_size; k++) { + model->softmax_q2[nn * filter_size + k] -= softmax_means[nn] + mean_filter[k]; + model->elliott_q2[nn * filter_size + k] -= elliott_means[nn]; + } + + model->softmax_bias_q2[nn] -= mean_bias; + } } static av_cold int init(AVFilterContext *ctx) { NNEDIContext *s = ctx->priv; FILE *weights_file = NULL; - int64_t expected_size = 13574928; int64_t weights_size; float *bdata; size_t bytes_read; - const int xdia_table[NUM_NSIZE] = { 8, 16, 32, 48, 8, 16, 32 }; - const int ydia_table[NUM_NSIZE] = { 6, 6, 6, 6, 4, 4, 4 }; - const int nns_table[NUM_NNS] = { 16, 32, 64, 128, 256 }; - const int dims0 = 49 * 4 + 5 * 4 + 9 * 4; - const int dims0new = 4 * 65 + 4 * 5; - const int dims1 = nns_table[s->nnsparam] * 2 * (xdia_table[s->nsize] * ydia_table[s->nsize] + 1); - int dims1tsize = 0; - int dims1offset = 0; - int ret = 0, i, j, k; + int ret = 0; - weights_file = fopen(s->weights_file, "rb"); + weights_file = av_fopen_utf8(s->weights_file, "rb"); if (!weights_file) { av_log(ctx, AV_LOG_ERROR, "No weights file provided, aborting!\n"); return AVERROR(EINVAL); @@ -940,7 +982,7 @@ fclose(weights_file); av_log(ctx, AV_LOG_ERROR, "Couldn't get size of weights file.\n"); return AVERROR(EINVAL); - } else if (weights_size != expected_size) { + } else if (weights_size != NNEDI_WEIGHTS_SIZE) { fclose(weights_file); av_log(ctx, AV_LOG_ERROR, "Unexpected weights file size.\n"); return AVERROR(EINVAL); @@ -952,15 +994,14 @@ return AVERROR(EINVAL); } - bdata = (float *)av_malloc(expected_size); + bdata = av_malloc(NNEDI_WEIGHTS_SIZE); if (!bdata) { fclose(weights_file); return AVERROR(ENOMEM); } - bytes_read = fread(bdata, 1, expected_size, weights_file); - - if (bytes_read != (size_t)expected_size) { + bytes_read = fread(bdata, 1, NNEDI_WEIGHTS_SIZE, weights_file); + if (bytes_read != NNEDI_WEIGHTS_SIZE) { fclose(weights_file); ret = AVERROR_INVALIDDATA; av_log(ctx, AV_LOG_ERROR, "Couldn't read weights file.\n"); @@ -969,212 +1010,132 @@ fclose(weights_file); - for (j = 0; j < NUM_NNS; j++) { - for (i = 0; i < NUM_NSIZE; i++) { - if (i == s->nsize && j == s->nnsparam) - dims1offset = dims1tsize; - dims1tsize += nns_table[j] * 2 * (xdia_table[i] * ydia_table[i] + 1) * 2; - } - } - - s->weights0 = av_malloc_array(FFMAX(dims0, dims0new), sizeof(float)); - if (!s->weights0) { + s->fdsp = avpriv_float_dsp_alloc(0); + if (!s->fdsp) { ret = AVERROR(ENOMEM); goto fail; } - for (i = 0; i < 2; i++) { - s->weights1[i] = av_malloc_array(dims1, sizeof(float)); - if (!s->weights1[i]) { - ret = AVERROR(ENOMEM); - goto fail; - } - } + ret = read_weights(ctx, bdata); + if (ret < 0) + goto fail; - // Adjust prescreener weights - if (s->pscrn >= 2) {// using new prescreener - const float *bdw; - int16_t *ws; - float *wf; - double mean[4] = { 0.0, 0.0, 0.0, 0.0 }; - int *offt = av_calloc(4 * 64, sizeof(int)); - - if (!offt) { - ret = AVERROR(ENOMEM); - goto fail; - } +fail: + av_free(bdata); + return ret; +} - for (j = 0; j < 4; j++) - for (k = 0; k < 64; k++) - offt[j * 64 + k] = ((k >> 3) << 5) + ((j & 3) << 3) + (k & 7); - - bdw = bdata + dims0 + dims0new * (s->pscrn - 2); - ws = (int16_t *)s->weights0; - wf = (float *)&ws[4 * 64]; - // Calculate mean weight of each first layer neuron - for (j = 0; j < 4; j++) { - double cmean = 0.0; - for (k = 0; k < 64; k++) - cmean += bdw[offt[j * 64 + k]]; - mean[j] = cmean / 64.0; - } - // Factor mean removal and 1.0/127.5 scaling - // into first layer weights. scale to int16 range - for (j = 0; j < 4; j++) { - double scale, mval = 0.0; - - for (k = 0; k < 64; k++) - mval = FFMAX(mval, FFABS((bdw[offt[j * 64 + k]] - mean[j]) / 127.5)); - scale = 32767.0 / mval; - for (k = 0; k < 64; k++) - ws[offt[j * 64 + k]] = roundds(((bdw[offt[j * 64 + k]] - mean[j]) / 127.5) * scale); - wf[j] = (float)(mval / 32767.0); - } - memcpy(wf + 4, bdw + 4 * 64, (dims0new - 4 * 64) * sizeof(float)); - av_free(offt); - } else { // using old prescreener - double mean[4] = { 0.0, 0.0, 0.0, 0.0 }; - // Calculate mean weight of each first layer neuron - for (j = 0; j < 4; j++) { - double cmean = 0.0; - for (k = 0; k < 48; k++) - cmean += bdata[j * 48 + k]; - mean[j] = cmean / 48.0; - } - if (s->fapprox & 1) {// use int16 dot products in first layer - int16_t *ws = (int16_t *)s->weights0; - float *wf = (float *)&ws[4 * 48]; - // Factor mean removal and 1.0/127.5 scaling - // into first layer weights. scale to int16 range - for (j = 0; j < 4; j++) { - double scale, mval = 0.0; - for (k = 0; k < 48; k++) - mval = FFMAX(mval, FFABS((bdata[j * 48 + k] - mean[j]) / 127.5)); - scale = 32767.0 / mval; - for (k = 0; k < 48; k++) - ws[j * 48 + k] = roundds(((bdata[j * 48 + k] - mean[j]) / 127.5) * scale); - wf[j] = (float)(mval / 32767.0); - } - memcpy(wf + 4, bdata + 4 * 48, (dims0 - 4 * 48) * sizeof(float)); - } else {// use float dot products in first layer - double half = (1 << 8) - 1; - - half /= 2; - - // Factor mean removal and 1.0/half scaling - // into first layer weights. - for (j = 0; j < 4; j++) - for (k = 0; k < 48; k++) - s->weights0[j * 48 + k] = (float)((bdata[j * 48 + k] - mean[j]) / half); - memcpy(s->weights0 + 4 * 48, bdata + 4 * 48, (dims0 - 4 * 48) * sizeof(float)); - } - } +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + NNEDIContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int ret; - // Adjust prediction weights - for (i = 0; i < 2; i++) { - const float *bdataT = bdata + dims0 + dims0new * 3 + dims1tsize * s->etype + dims1offset + i * dims1; - const int nnst = nns_table[s->nnsparam]; - const int asize = xdia_table[s->nsize] * ydia_table[s->nsize]; - const int boff = nnst * 2 * asize; - double *mean = (double *)av_calloc(asize + 1 + nnst * 2, sizeof(double)); - - if (!mean) { - ret = AVERROR(ENOMEM); - goto fail; - } + s->depth = desc->comp[0].depth; + s->nb_threads = ff_filter_get_nb_threads(ctx); + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + return ret; - // Calculate mean weight of each neuron (ignore bias) - for (j = 0; j < nnst * 2; j++) { - double cmean = 0.0; - for (k = 0; k < asize; k++) - cmean += bdataT[j * asize + k]; - mean[asize + 1 + j] = cmean / (double)asize; - } - // Calculate mean softmax neuron - for (j = 0; j < nnst; j++) { - for (k = 0; k < asize; k++) - mean[k] += bdataT[j * asize + k] - mean[asize + 1 + j]; - mean[asize] += bdataT[boff + j]; - } - for (j = 0; j < asize + 1; j++) - mean[j] /= (double)(nnst); + 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; - if (s->fapprox & 2) { // use int16 dot products - int16_t *ws = (int16_t *)s->weights1[i]; - float *wf = (float *)&ws[nnst * 2 * asize]; - // Factor mean removal into weights, remove global offset from - // softmax neurons, and scale weights to int16 range. - for (j = 0; j < nnst; j++) { // softmax neurons - double scale, mval = 0.0; - for (k = 0; k < asize; k++) - mval = FFMAX(mval, FFABS(bdataT[j * asize + k] - mean[asize + 1 + j] - mean[k])); - scale = 32767.0 / mval; - for (k = 0; k < asize; k++) - ws[j * asize + k] = roundds((bdataT[j * asize + k] - mean[asize + 1 + j] - mean[k]) * scale); - wf[(j >> 2) * 8 + (j & 3)] = (float)(mval / 32767.0); - wf[(j >> 2) * 8 + (j & 3) + 4] = (float)(bdataT[boff + j] - mean[asize]); - } - for (j = nnst; j < nnst * 2; j++) { // elliott neurons - double scale, mval = 0.0; - for (k = 0; k < asize; k++) - mval = FFMAX(mval, FFABS(bdataT[j * asize + k] - mean[asize + 1 + j])); - scale = 32767.0 / mval; - for (k = 0; k < asize; k++) - ws[j * asize + k] = roundds((bdataT[j * asize + k] - mean[asize + 1 + j]) * scale); - wf[(j >> 2) * 8 + (j & 3)] = (float)(mval / 32767.0); - wf[(j >> 2) * 8 + (j & 3) + 4] = bdataT[boff + j]; - } - } else { // use float dot products - // Factor mean removal into weights, and remove global - // offset from softmax neurons. - for (j = 0; j < nnst * 2; j++) { - for (k = 0; k < asize; k++) { - const double q = j < nnst ? mean[k] : 0.0; - s->weights1[i][j * asize + k] = (float)(bdataT[j * asize + k] - mean[asize + 1 + j] - q); - } - s->weights1[i][boff + j] = (float)(bdataT[boff + j] - (j < nnst ? mean[asize] : 0.0)); - } + s->half = ((1 << 8) - 1) / 2.f; + s->out_scale = 1 << (s->depth - 8); + s->in_scale = 1.f / s->out_scale; + + switch (s->depth) { + case 8: + s->read = read_bytes; + s->write = write_bytes; + break; + default: + s->read = read_words; + s->write = write_words; + break; + } + + subtract_mean_old(&s->prescreener[0], s->half); + subtract_mean_new(&s->prescreener[1], s->half); + subtract_mean_new(&s->prescreener[2], s->half); + subtract_mean_new(&s->prescreener[3], s->half); + + s->prescreen[0] = process_old; + s->prescreen[1] = process_new; + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 5; j++) { + for (int k = 0; k < 7; k++) + subtract_mean_predictor(&s->coeffs[i][j][k]); } - av_free(mean); } - s->nns = nns_table[s->nnsparam]; - s->xdia = xdia_table[s->nsize]; - s->ydia = ydia_table[s->nsize]; - s->asize = xdia_table[s->nsize] * ydia_table[s->nsize]; + s->input_size = (s->planewidth[0] + 64) * (s->planeheight[0] + 6); + s->input_buf = av_calloc(s->nb_threads, sizeof(*s->input_buf)); + if (!s->input_buf) + return AVERROR(ENOMEM); - s->max_value = 65535 >> 8; + for (int i = 0; i < s->nb_threads; i++) { + s->input_buf[i] = av_calloc(s->input_size, sizeof(**s->input_buf)); + if (!s->input_buf[i]) + return AVERROR(ENOMEM); + } - select_functions(s); + s->output_buf = av_calloc(s->nb_threads, sizeof(*s->output_buf)); + if (!s->output_buf) + return AVERROR(ENOMEM); - s->fdsp = avpriv_float_dsp_alloc(0); - if (!s->fdsp) - ret = AVERROR(ENOMEM); + for (int i = 0; i < s->nb_threads; i++) { + s->output_buf[i] = av_calloc(s->input_size, sizeof(**s->output_buf)); + if (!s->output_buf[i]) + return AVERROR(ENOMEM); + } -fail: - av_free(bdata); - return ret; + s->prescreen_buf = av_calloc(s->nb_threads, sizeof(*s->prescreen_buf)); + if (!s->prescreen_buf) + return AVERROR(ENOMEM); + + for (int i = 0; i < s->nb_threads; i++) { + s->prescreen_buf[i] = av_calloc(s->planewidth[0], sizeof(**s->prescreen_buf)); + if (!s->prescreen_buf[i]) + return AVERROR(ENOMEM); + } + + return 0; } static av_cold void uninit(AVFilterContext *ctx) { NNEDIContext *s = ctx->priv; - int i; - av_freep(&s->weights0); + for (int i = 0; i < s->nb_threads && s->prescreen_buf; i++) + av_freep(&s->prescreen_buf[i]); - for (i = 0; i < 2; i++) - av_freep(&s->weights1[i]); + av_freep(&s->prescreen_buf); - for (i = 0; i < s->nb_planes; i++) { - av_freep(&s->frame_data.paddedp[i]); - av_freep(&s->frame_data.lcount[i]); - } + for (int i = 0; i < s->nb_threads && s->input_buf; i++) + av_freep(&s->input_buf[i]); + + av_freep(&s->input_buf); - av_freep(&s->frame_data.input); - av_freep(&s->frame_data.temp); + for (int i = 0; i < s->nb_threads && s->output_buf; i++) + av_freep(&s->output_buf[i]); + + av_freep(&s->output_buf); av_freep(&s->fdsp); - av_frame_free(&s->second); + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 5; j++) { + for (int k = 0; k < 7; k++) { + av_freep(&s->coeffs[i][j][k].data); + } + } + } + + av_frame_free(&s->prev); } static const AVFilterPad inputs[] = { @@ -1207,5 +1168,6 @@ .query_formats = query_formats, .inputs = inputs, .outputs = outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_normalize.c ffmpeg-4.4/libavfilter/vf_normalize.c --- ffmpeg-4.2.2/libavfilter/vf_normalize.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_normalize.c 2021-04-08 21:28:40.000000000 +0000 @@ -73,6 +73,7 @@ */ #include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avfilter.h" @@ -81,6 +82,17 @@ #include "internal.h" #include "video.h" +typedef struct NormalizeHistory { + uint16_t *history; // History entries. + uint64_t history_sum; // Sum of history entries. +} NormalizeHistory; + +typedef struct NormalizeLocal { + uint16_t in; // Original input byte value for this frame. + float smoothed; // Smoothed input value [0,255]. + float out; // Output value [0,255] +} NormalizeLocal; + typedef struct NormalizeContext { const AVClass *class; @@ -92,67 +104,202 @@ float strength; uint8_t co[4]; // Offsets to R,G,B,A bytes respectively in each pixel + int depth; + int sblackpt[4]; + int swhitept[4]; int num_components; // Number of components in the pixel format int step; int history_len; // Number of frames to average; based on smoothing factor int frame_num; // Increments on each frame, starting from 0. // Per-extremum, per-channel history, for temporal smoothing. - struct { - uint8_t *history; // History entries. - uint32_t history_sum; // Sum of history entries. - } min[3], max[3]; // Min and max for each channel in {R,G,B}. - uint8_t *history_mem; // Single allocation for above history entries + NormalizeHistory min[3], max[3]; // Min and max for each channel in {R,G,B}. + uint16_t *history_mem; // Single allocation for above history entries + + uint16_t lut[3][65536]; // Lookup table + void (*find_min_max)(struct NormalizeContext *s, AVFrame *in, NormalizeLocal min[3], NormalizeLocal max[3]); + void (*process)(struct NormalizeContext *s, AVFrame *in, AVFrame *out); } NormalizeContext; #define OFFSET(x) offsetof(NormalizeContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGSR AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption normalize_options[] = { - { "blackpt", "output color to which darkest input color is mapped", OFFSET(blackpt), AV_OPT_TYPE_COLOR, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "whitept", "output color to which brightest input color is mapped", OFFSET(whitept), AV_OPT_TYPE_COLOR, { .str = "white" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "blackpt", "output color to which darkest input color is mapped", OFFSET(blackpt), AV_OPT_TYPE_COLOR, { .str = "black" }, 0, 0, FLAGSR }, + { "whitept", "output color to which brightest input color is mapped", OFFSET(whitept), AV_OPT_TYPE_COLOR, { .str = "white" }, 0, 0, FLAGSR }, { "smoothing", "amount of temporal smoothing of the input range, to reduce flicker", OFFSET(smoothing), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX/8, FLAGS }, - { "independence", "proportion of independent to linked channel normalization", OFFSET(independence), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 1.0, FLAGS }, - { "strength", "strength of filter, from no effect to full normalization", OFFSET(strength), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 1.0, FLAGS }, + { "independence", "proportion of independent to linked channel normalization", OFFSET(independence), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 1.0, FLAGSR }, + { "strength", "strength of filter, from no effect to full normalization", OFFSET(strength), AV_OPT_TYPE_FLOAT, {.dbl=1.0}, 0.0, 1.0, FLAGSR }, { NULL } }; AVFILTER_DEFINE_CLASS(normalize); +static void find_min_max(NormalizeContext *s, AVFrame *in, NormalizeLocal min[3], NormalizeLocal max[3]) +{ + for (int c = 0; c < 3; c++) + min[c].in = max[c].in = in->data[0][s->co[c]]; + for (int y = 0; y < in->height; y++) { + uint8_t *inp = in->data[0] + y * in->linesize[0]; + for (int x = 0; x < in->width; x++) { + for (int c = 0; c < 3; c++) { + min[c].in = FFMIN(min[c].in, inp[s->co[c]]); + max[c].in = FFMAX(max[c].in, inp[s->co[c]]); + } + inp += s->step; + } + } +} + +static void process(NormalizeContext *s, AVFrame *in, AVFrame *out) +{ + for (int y = 0; y < in->height; y++) { + uint8_t *inp = in->data[0] + y * in->linesize[0]; + uint8_t *outp = out->data[0] + y * out->linesize[0]; + for (int x = 0; x < in->width; x++) { + for (int c = 0; c < 3; c++) + outp[s->co[c]] = s->lut[c][inp[s->co[c]]]; + if (s->num_components == 4) + // Copy alpha as-is. + outp[s->co[3]] = inp[s->co[3]]; + inp += s->step; + outp += s->step; + } + } +} + +static void find_min_max_planar(NormalizeContext *s, AVFrame *in, NormalizeLocal min[3], NormalizeLocal max[3]) +{ + min[0].in = max[0].in = in->data[2][0]; + min[1].in = max[1].in = in->data[0][0]; + min[2].in = max[2].in = in->data[1][0]; + for (int y = 0; y < in->height; y++) { + uint8_t *inrp = in->data[2] + y * in->linesize[2]; + uint8_t *ingp = in->data[0] + y * in->linesize[0]; + uint8_t *inbp = in->data[1] + y * in->linesize[1]; + for (int x = 0; x < in->width; x++) { + min[0].in = FFMIN(min[0].in, inrp[x]); + max[0].in = FFMAX(max[0].in, inrp[x]); + min[1].in = FFMIN(min[1].in, ingp[x]); + max[1].in = FFMAX(max[1].in, ingp[x]); + min[2].in = FFMIN(min[2].in, inbp[x]); + max[2].in = FFMAX(max[2].in, inbp[x]); + } + } +} + +static void process_planar(NormalizeContext *s, AVFrame *in, AVFrame *out) +{ + for (int y = 0; y < in->height; y++) { + uint8_t *inrp = in->data[2] + y * in->linesize[2]; + uint8_t *ingp = in->data[0] + y * in->linesize[0]; + uint8_t *inbp = in->data[1] + y * in->linesize[1]; + uint8_t *inap = in->data[3] + y * in->linesize[3]; + uint8_t *outrp = out->data[2] + y * out->linesize[2]; + uint8_t *outgp = out->data[0] + y * out->linesize[0]; + uint8_t *outbp = out->data[1] + y * out->linesize[1]; + uint8_t *outap = out->data[3] + y * out->linesize[3]; + for (int x = 0; x < in->width; x++) { + outrp[x] = s->lut[0][inrp[x]]; + outgp[x] = s->lut[1][ingp[x]]; + outbp[x] = s->lut[2][inbp[x]]; + if (s->num_components == 4) + outap[x] = inap[x]; + } + } +} + +static void find_min_max_16(NormalizeContext *s, AVFrame *in, NormalizeLocal min[3], NormalizeLocal max[3]) +{ + for (int c = 0; c < 3; c++) + min[c].in = max[c].in = AV_RN16(in->data[0] + 2 * s->co[c]); + for (int y = 0; y < in->height; y++) { + uint16_t *inp = (uint16_t *)(in->data[0] + y * in->linesize[0]); + for (int x = 0; x < in->width; x++) { + for (int c = 0; c < 3; c++) { + min[c].in = FFMIN(min[c].in, inp[s->co[c]]); + max[c].in = FFMAX(max[c].in, inp[s->co[c]]); + } + inp += s->step; + } + } +} + +static void process_16(NormalizeContext *s, AVFrame *in, AVFrame *out) +{ + for (int y = 0; y < in->height; y++) { + uint16_t *inp = (uint16_t *)(in->data[0] + y * in->linesize[0]); + uint16_t *outp = (uint16_t *)(out->data[0] + y * out->linesize[0]); + for (int x = 0; x < in->width; x++) { + for (int c = 0; c < 3; c++) + outp[s->co[c]] = s->lut[c][inp[s->co[c]]]; + if (s->num_components == 4) + // Copy alpha as-is. + outp[s->co[3]] = inp[s->co[3]]; + inp += s->step; + outp += s->step; + } + } +} + +static void find_min_max_planar_16(NormalizeContext *s, AVFrame *in, NormalizeLocal min[3], NormalizeLocal max[3]) +{ + min[0].in = max[0].in = AV_RN16(in->data[2]); + min[1].in = max[1].in = AV_RN16(in->data[0]); + min[2].in = max[2].in = AV_RN16(in->data[1]); + for (int y = 0; y < in->height; y++) { + uint16_t *inrp = (uint16_t *)(in->data[2] + y * in->linesize[2]); + uint16_t *ingp = (uint16_t *)(in->data[0] + y * in->linesize[0]); + uint16_t *inbp = (uint16_t *)(in->data[1] + y * in->linesize[1]); + for (int x = 0; x < in->width; x++) { + min[0].in = FFMIN(min[0].in, inrp[x]); + max[0].in = FFMAX(max[0].in, inrp[x]); + min[1].in = FFMIN(min[1].in, ingp[x]); + max[1].in = FFMAX(max[1].in, ingp[x]); + min[2].in = FFMIN(min[2].in, inbp[x]); + max[2].in = FFMAX(max[2].in, inbp[x]); + } + } +} + +static void process_planar_16(NormalizeContext *s, AVFrame *in, AVFrame *out) +{ + for (int y = 0; y < in->height; y++) { + uint16_t *inrp = (uint16_t *)(in->data[2] + y * in->linesize[2]); + uint16_t *ingp = (uint16_t *)(in->data[0] + y * in->linesize[0]); + uint16_t *inbp = (uint16_t *)(in->data[1] + y * in->linesize[1]); + uint16_t *inap = (uint16_t *)(in->data[3] + y * in->linesize[3]); + uint16_t *outrp = (uint16_t *)(out->data[2] + y * out->linesize[2]); + uint16_t *outgp = (uint16_t *)(out->data[0] + y * out->linesize[0]); + uint16_t *outbp = (uint16_t *)(out->data[1] + y * out->linesize[1]); + uint16_t *outap = (uint16_t *)(out->data[3] + y * out->linesize[3]); + for (int x = 0; x < in->width; x++) { + outrp[x] = s->lut[0][inrp[x]]; + outgp[x] = s->lut[1][ingp[x]]; + outbp[x] = s->lut[2][inbp[x]]; + if (s->num_components == 4) + outap[x] = inap[x]; + } + } +} + // This function is the main guts of the filter. Normalizes the input frame // into the output frame. The frames are known to have the same dimensions // and pixel format. static void normalize(NormalizeContext *s, AVFrame *in, AVFrame *out) { // Per-extremum, per-channel local variables. - struct { - uint8_t in; // Original input byte value for this frame. - float smoothed; // Smoothed input value [0,255]. - float out; // Output value [0,255]. - } min[3], max[3]; // Min and max for each channel in {R,G,B}. + NormalizeLocal min[3], max[3]; // Min and max for each channel in {R,G,B}. float rgb_min_smoothed; // Min input range for linked normalization float rgb_max_smoothed; // Max input range for linked normalization - uint8_t lut[3][256]; // Lookup table - int x, y, c; + int c; // First, scan the input frame to find, for each channel, the minimum // (min.in) and maximum (max.in) values present in the channel. - for (c = 0; c < 3; c++) - min[c].in = max[c].in = in->data[0][s->co[c]]; - for (y = 0; y < in->height; y++) { - uint8_t *inp = in->data[0] + y * in->linesize[0]; - uint8_t *outp = out->data[0] + y * out->linesize[0]; - for (x = 0; x < in->width; x++) { - for (c = 0; c < 3; c++) { - min[c].in = FFMIN(min[c].in, inp[s->co[c]]); - max[c].in = FFMAX(max[c].in, inp[s->co[c]]); - } - inp += s->step; - outp += s->step; - } - } + s->find_min_max(s, in, min, max); // Next, for each channel, push min.in and max.in into their respective // histories, to determine the min.smoothed and max.smoothed for this frame. @@ -200,9 +347,9 @@ // Calculate the output range [min.out,max.out] as a ratio of the full- // strength output range [blackpt,whitept] and the original input range // [min.in,max.in], based on the user-specified filter strength. - min[c].out = (s->blackpt[c] * s->strength) + min[c].out = (s->sblackpt[c] * s->strength) + (min[c].in * (1.0f - s->strength)); - max[c].out = (s->whitept[c] * s->strength) + max[c].out = (s->swhitept[c] * s->strength) + (max[c].in * (1.0f - s->strength)); // Now, build a lookup table which linearly maps the adjusted input range @@ -213,7 +360,7 @@ if (min[c].smoothed == max[c].smoothed) { // There is no dynamic range to expand. No mapping for this channel. for (in_val = min[c].in; in_val <= max[c].in; in_val++) - lut[c][in_val] = min[c].out; + s->lut[c][in_val] = min[c].out; } else { // We must set lookup values for all values in the original input // range [min.in,max.in]. Since the original input range may be @@ -222,27 +369,14 @@ float scale = (max[c].out - min[c].out) / (max[c].smoothed - min[c].smoothed); for (in_val = min[c].in; in_val <= max[c].in; in_val++) { int out_val = (in_val - min[c].smoothed) * scale + min[c].out + 0.5f; - out_val = FFMAX(out_val, 0); - out_val = FFMIN(out_val, 255); - lut[c][in_val] = out_val; + out_val = av_clip_uintp2_c(out_val, s->depth); + s->lut[c][in_val] = out_val; } } } // Finally, process the pixels of the input frame using the lookup tables. - for (y = 0; y < in->height; y++) { - uint8_t *inp = in->data[0] + y * in->linesize[0]; - uint8_t *outp = out->data[0] + y * out->linesize[0]; - for (x = 0; x < in->width; x++) { - for (c = 0; c < 3; c++) - outp[s->co[c]] = lut[c][inp[s->co[c]]]; - if (s->num_components == 4) - // Copy alpha as-is. - outp[s->co[3]] = inp[s->co[3]]; - inp += s->step; - outp += s->step; - } - } + s->process(s, in, out); s->frame_num++; } @@ -267,6 +401,11 @@ AV_PIX_FMT_RGB0, AV_PIX_FMT_0BGR, AV_PIX_FMT_BGR0, + AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48, + AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; // According to filter_design.txt, using ff_set_common_formats() this way @@ -286,11 +425,13 @@ NormalizeContext *s = inlink->dst->priv; // Store offsets to R,G,B,A bytes respectively in each pixel const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - int c; + int c, planar, scale; ff_fill_rgba_map(s->co, inlink->format); + s->depth = desc->comp[0].depth; + scale = 1 << (s->depth - 8); s->num_components = desc->nb_components; - s->step = av_get_padded_bits_per_pixel(desc) >> 3; + s->step = av_get_padded_bits_per_pixel(desc) >> (3 + (s->depth > 8)); // Convert smoothing value to history_len (a count of frames to average, // must be at least 1). Currently this is a direct assignment, but the // smoothing value was originally envisaged as a number of seconds. In @@ -300,14 +441,27 @@ // Allocate the history buffers -- there are 6 -- one for each extrema. // s->smoothing is limited to INT_MAX/8, so that (s->history_len * 6) // can't overflow on 32bit causing a too-small allocation. - s->history_mem = av_malloc(s->history_len * 6); + s->history_mem = av_malloc(s->history_len * 6 * sizeof(*s->history_mem)); if (s->history_mem == NULL) return AVERROR(ENOMEM); for (c = 0; c < 3; c++) { s->min[c].history = s->history_mem + (c*2) * s->history_len; s->max[c].history = s->history_mem + (c*2+1) * s->history_len; + s->sblackpt[c] = scale * s->blackpt[c] + (s->blackpt[c] & (1 << (s->depth - 8))); + s->swhitept[c] = scale * s->whitept[c] + (s->whitept[c] & (1 << (s->depth - 8))); } + + planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR; + + if (s->depth <= 8) { + s->find_min_max = planar ? find_min_max_planar : find_min_max; + s->process = planar? process_planar : process; + } else { + s->find_min_max = planar ? find_min_max_planar_16 : find_min_max_16; + s->process = planar? process_planar_16 : process_16; + } + return 0; } @@ -386,4 +540,5 @@ .inputs = inputs, .outputs = outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_ocr.c ffmpeg-4.4/libavfilter/vf_ocr.c --- ffmpeg-4.2.2/libavfilter/vf_ocr.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_ocr.c 2021-04-08 21:28:40.000000000 +0000 @@ -43,7 +43,7 @@ static const AVOption ocr_options[] = { { "datapath", "set datapath", OFFSET(datapath), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, { "language", "set language", OFFSET(language), AV_OPT_TYPE_STRING, {.str="eng"}, 0, 0, FLAGS }, - { "whitelist", "set character whitelist", OFFSET(whitelist), AV_OPT_TYPE_STRING, {.str="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:;,-+_!?\"'[]{}()<>|/\\=*&%$#@!~"}, 0, 0, FLAGS }, + { "whitelist", "set character whitelist", OFFSET(whitelist), AV_OPT_TYPE_STRING, {.str="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:;,-+_!?\"'[]{}()<>|/\\=*&%$#@!~ "}, 0, 0, FLAGS }, { "blacklist", "set character blacklist", OFFSET(blacklist), AV_OPT_TYPE_STRING, {.str=""}, 0, 0, FLAGS }, { NULL } }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_overlay.c ffmpeg-4.4/libavfilter/vf_overlay.c --- ffmpeg-4.2.2/libavfilter/vf_overlay.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_overlay.c 2021-04-08 21:28:40.000000000 +0000 @@ -154,6 +154,7 @@ static const enum AVPixelFormat alpha_pix_fmts[] = { AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE }; @@ -172,6 +173,14 @@ AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE }; + static const enum AVPixelFormat main_pix_fmts_yuv420p10[] = { + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUVA420P10, + AV_PIX_FMT_NONE + }; + static const enum AVPixelFormat overlay_pix_fmts_yuv420p10[] = { + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_NONE + }; + static const enum AVPixelFormat main_pix_fmts_yuv422[] = { AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_NONE }; @@ -179,6 +188,13 @@ AV_PIX_FMT_YUVA422P, AV_PIX_FMT_NONE }; + static const enum AVPixelFormat main_pix_fmts_yuv422p10[] = { + AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_NONE + }; + static const enum AVPixelFormat overlay_pix_fmts_yuv422p10[] = { + AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_NONE + }; + static const enum AVPixelFormat main_pix_fmts_yuv444[] = { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE }; @@ -205,76 +221,52 @@ AV_PIX_FMT_NONE }; - AVFilterFormats *main_formats = NULL; - AVFilterFormats *overlay_formats = NULL; + const enum AVPixelFormat *main_formats, *overlay_formats; + AVFilterFormats *formats; int ret; switch (s->format) { case OVERLAY_FORMAT_YUV420: - if (!(main_formats = ff_make_format_list(main_pix_fmts_yuv420)) || - !(overlay_formats = ff_make_format_list(overlay_pix_fmts_yuv420))) { - ret = AVERROR(ENOMEM); - goto fail; - } + main_formats = main_pix_fmts_yuv420; + overlay_formats = overlay_pix_fmts_yuv420; + break; + case OVERLAY_FORMAT_YUV420P10: + main_formats = main_pix_fmts_yuv420p10; + overlay_formats = overlay_pix_fmts_yuv420p10; break; case OVERLAY_FORMAT_YUV422: - if (!(main_formats = ff_make_format_list(main_pix_fmts_yuv422)) || - !(overlay_formats = ff_make_format_list(overlay_pix_fmts_yuv422))) { - ret = AVERROR(ENOMEM); - goto fail; - } + main_formats = main_pix_fmts_yuv422; + overlay_formats = overlay_pix_fmts_yuv422; + break; + case OVERLAY_FORMAT_YUV422P10: + main_formats = main_pix_fmts_yuv422p10; + overlay_formats = overlay_pix_fmts_yuv422p10; break; case OVERLAY_FORMAT_YUV444: - if (!(main_formats = ff_make_format_list(main_pix_fmts_yuv444)) || - !(overlay_formats = ff_make_format_list(overlay_pix_fmts_yuv444))) { - ret = AVERROR(ENOMEM); - goto fail; - } + main_formats = main_pix_fmts_yuv444; + overlay_formats = overlay_pix_fmts_yuv444; break; case OVERLAY_FORMAT_RGB: - if (!(main_formats = ff_make_format_list(main_pix_fmts_rgb)) || - !(overlay_formats = ff_make_format_list(overlay_pix_fmts_rgb))) { - ret = AVERROR(ENOMEM); - goto fail; - } + main_formats = main_pix_fmts_rgb; + overlay_formats = overlay_pix_fmts_rgb; break; case OVERLAY_FORMAT_GBRP: - if (!(main_formats = ff_make_format_list(main_pix_fmts_gbrp)) || - !(overlay_formats = ff_make_format_list(overlay_pix_fmts_gbrp))) { - ret = AVERROR(ENOMEM); - goto fail; - } + main_formats = main_pix_fmts_gbrp; + overlay_formats = overlay_pix_fmts_gbrp; break; case OVERLAY_FORMAT_AUTO: - if (!(main_formats = ff_make_format_list(alpha_pix_fmts))) { - ret = AVERROR(ENOMEM); - goto fail; - } - break; + return ff_set_common_formats(ctx, ff_make_format_list(alpha_pix_fmts)); default: av_assert0(0); } - if (s->format == OVERLAY_FORMAT_AUTO) { - ret = ff_set_common_formats(ctx, main_formats); - if (ret < 0) - goto fail; - } else { - if ((ret = ff_formats_ref(main_formats , &ctx->inputs[MAIN]->out_formats )) < 0 || - (ret = ff_formats_ref(overlay_formats, &ctx->inputs[OVERLAY]->out_formats)) < 0 || - (ret = ff_formats_ref(main_formats , &ctx->outputs[MAIN]->in_formats )) < 0) - goto fail; - } + formats = ff_make_format_list(main_formats); + if ((ret = ff_formats_ref(formats, &ctx->inputs[MAIN]->outcfg.formats)) < 0 || + (ret = ff_formats_ref(formats, &ctx->outputs[MAIN]->incfg.formats)) < 0) + return ret; - return 0; -fail: - if (main_formats) - av_freep(&main_formats->formats); - av_freep(&main_formats); - if (overlay_formats) - av_freep(&overlay_formats->formats); - av_freep(&overlay_formats); - return ret; + return ff_formats_ref(ff_make_format_list(overlay_formats), + &ctx->inputs[OVERLAY]->outcfg.formats); } static int config_input_overlay(AVFilterLink *inlink) @@ -441,190 +433,216 @@ } } -static av_always_inline void blend_plane(AVFilterContext *ctx, - AVFrame *dst, const AVFrame *src, - int src_w, int src_h, - int dst_w, int dst_h, - int i, int hsub, int vsub, - int x, int y, - int main_has_alpha, - int dst_plane, - int dst_offset, - int dst_step, - int straight, - int yuv, - int jobnr, - int nb_jobs) -{ - OverlayContext *octx = ctx->priv; - int src_wp = AV_CEIL_RSHIFT(src_w, hsub); - int src_hp = AV_CEIL_RSHIFT(src_h, vsub); - int dst_wp = AV_CEIL_RSHIFT(dst_w, hsub); - int dst_hp = AV_CEIL_RSHIFT(dst_h, vsub); - int yp = y>>vsub; - int xp = x>>hsub; - uint8_t *s, *sp, *d, *dp, *dap, *a, *da, *ap; - int jmax, j, k, kmax; - int slice_start, slice_end; - - j = FFMAX(-yp, 0); - jmax = FFMIN3(-yp + dst_hp, FFMIN(src_hp, dst_hp), yp + src_hp); - - slice_start = j + (jmax * jobnr) / nb_jobs; - slice_end = j + (jmax * (jobnr+1)) / nb_jobs; - - sp = src->data[i] + (slice_start) * src->linesize[i]; - dp = dst->data[dst_plane] - + (yp + slice_start) * dst->linesize[dst_plane] - + dst_offset; - ap = src->data[3] + (slice_start << vsub) * src->linesize[3]; - dap = dst->data[3] + ((yp + slice_start) << vsub) * dst->linesize[3]; - - for (j = slice_start; j < slice_end; j++) { - k = FFMAX(-xp, 0); - d = dp + (xp+k) * dst_step; - s = sp + k; - a = ap + (k<blend_row[i]) { - int c = octx->blend_row[i](d, da, s, a, kmax - k, src->linesize[3]); - - s += c; - d += dst_step * c; - da += (1 << hsub) * c; - a += (1 << hsub) * c; - k += c; - } - for (; k < kmax; k++) { - int alpha_v, alpha_h, alpha; - - // average alpha for color components, improve quality - if (hsub && vsub && j+1 < src_hp && k+1 < src_wp) { - alpha = (a[0] + a[src->linesize[3]] + - a[1] + a[src->linesize[3]+1]) >> 2; - } else if (hsub || vsub) { - alpha_h = hsub && k+1 < src_wp ? - (a[0] + a[1]) >> 1 : a[0]; - alpha_v = vsub && j+1 < src_hp ? - (a[0] + a[src->linesize[3]]) >> 1 : a[0]; - alpha = (alpha_v + alpha_h) >> 1; - } else - alpha = a[0]; - // if the main channel has an alpha channel, alpha has to be calculated - // to create an un-premultiplied (straight) alpha value - if (main_has_alpha && alpha != 0 && alpha != 255) { - // average alpha for color components, improve quality - uint8_t alpha_d; - if (hsub && vsub && j+1 < src_hp && k+1 < src_wp) { - alpha_d = (da[0] + da[dst->linesize[3]] + - da[1] + da[dst->linesize[3]+1]) >> 2; - } else if (hsub || vsub) { - alpha_h = hsub && k+1 < src_wp ? - (da[0] + da[1]) >> 1 : da[0]; - alpha_v = vsub && j+1 < src_hp ? - (da[0] + da[dst->linesize[3]]) >> 1 : da[0]; - alpha_d = (alpha_v + alpha_h) >> 1; - } else - alpha_d = da[0]; - alpha = UNPREMULTIPLY_ALPHA(alpha, alpha_d); - } - if (straight) { - *d = FAST_DIV255(*d * (255 - alpha) + *s * alpha); - } else { - if (i && yuv) - *d = av_clip(FAST_DIV255((*d - 128) * (255 - alpha)) + *s - 128, -128, 128) + 128; - else - *d = FFMIN(FAST_DIV255(*d * (255 - alpha)) + *s, 255); - } - s++; - d += dst_step; - da += 1 << hsub; - a += 1 << hsub; - } - dp += dst->linesize[dst_plane]; - sp += src->linesize[i]; - ap += (1 << vsub) * src->linesize[3]; - dap += (1 << vsub) * dst->linesize[3]; - } -} - -static inline void alpha_composite(const AVFrame *src, const AVFrame *dst, - int src_w, int src_h, - int dst_w, int dst_h, - int x, int y, - int jobnr, int nb_jobs) -{ - uint8_t alpha; ///< the amount of overlay to blend on to main - uint8_t *s, *sa, *d, *da; - int i, imax, j, jmax; - int slice_start, slice_end; - - imax = FFMIN(-y + dst_h, src_h); - slice_start = (imax * jobnr) / nb_jobs; - slice_end = ((imax * (jobnr+1)) / nb_jobs); - - i = FFMAX(-y, 0); - sa = src->data[3] + (i + slice_start) * src->linesize[3]; - da = dst->data[3] + (y + i + slice_start) * dst->linesize[3]; - - for (i = i + slice_start; i < slice_end; i++) { - j = FFMAX(-x, 0); - s = sa + j; - d = da + x+j; - - for (jmax = FFMIN(-x + dst_w, src_w); j < jmax; j++) { - alpha = *s; - if (alpha != 0 && alpha != 255) { - uint8_t alpha_d = *d; - alpha = UNPREMULTIPLY_ALPHA(alpha, alpha_d); - } - switch (alpha) { - case 0: - break; - case 255: - *d = *s; - break; - default: - // apply alpha compositing: main_alpha += (1-main_alpha) * overlay_alpha - *d += FAST_DIV255((255 - *d) * *s); - } - d += 1; - s += 1; - } - da += dst->linesize[3]; - sa += src->linesize[3]; - } -} - -static av_always_inline void blend_slice_yuv(AVFilterContext *ctx, - AVFrame *dst, const AVFrame *src, - int hsub, int vsub, - int main_has_alpha, - int x, int y, - int is_straight, - int jobnr, int nb_jobs) -{ - OverlayContext *s = ctx->priv; - const int src_w = src->width; - const int src_h = src->height; - const int dst_w = dst->width; - const int dst_h = dst->height; - - blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0, 0, x, y, main_has_alpha, - s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, s->main_desc->comp[0].step, is_straight, 1, - jobnr, nb_jobs); - blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, x, y, main_has_alpha, - s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, s->main_desc->comp[1].step, is_straight, 1, - jobnr, nb_jobs); - blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, x, y, main_has_alpha, - s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, s->main_desc->comp[2].step, is_straight, 1, - jobnr, nb_jobs); - - if (main_has_alpha) - alpha_composite(src, dst, src_w, src_h, dst_w, dst_h, x, y, jobnr, nb_jobs); +#define DEFINE_BLEND_PLANE(depth, nbits) \ +static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext *ctx, \ + AVFrame *dst, const AVFrame *src, \ + int src_w, int src_h, \ + int dst_w, int dst_h, \ + int i, int hsub, int vsub, \ + int x, int y, \ + int main_has_alpha, \ + int dst_plane, \ + int dst_offset, \ + int dst_step, \ + int straight, \ + int yuv, \ + int jobnr, \ + int nb_jobs) \ +{ \ + OverlayContext *octx = ctx->priv; \ + int src_wp = AV_CEIL_RSHIFT(src_w, hsub); \ + int src_hp = AV_CEIL_RSHIFT(src_h, vsub); \ + int dst_wp = AV_CEIL_RSHIFT(dst_w, hsub); \ + int dst_hp = AV_CEIL_RSHIFT(dst_h, vsub); \ + int yp = y>>vsub; \ + int xp = x>>hsub; \ + uint##depth##_t *s, *sp, *d, *dp, *dap, *a, *da, *ap; \ + int jmax, j, k, kmax; \ + int slice_start, slice_end; \ + const uint##depth##_t max = (1 << nbits) - 1; \ + const uint##depth##_t mid = (1 << (nbits -1)) ; \ + int bytes = depth / 8; \ + \ + dst_step /= bytes; \ + j = FFMAX(-yp, 0); \ + jmax = FFMIN3(-yp + dst_hp, FFMIN(src_hp, dst_hp), yp + src_hp); \ + \ + slice_start = j + (jmax * jobnr) / nb_jobs; \ + slice_end = j + (jmax * (jobnr+1)) / nb_jobs; \ + \ + sp = (uint##depth##_t *)(src->data[i] + (slice_start) * src->linesize[i]); \ + dp = (uint##depth##_t *)(dst->data[dst_plane] \ + + (yp + slice_start) * dst->linesize[dst_plane] \ + + dst_offset); \ + ap = (uint##depth##_t *)(src->data[3] + (slice_start << vsub) * src->linesize[3]); \ + dap = (uint##depth##_t *)(dst->data[3] + ((yp + slice_start) << vsub) * dst->linesize[3]); \ + \ + for (j = slice_start; j < slice_end; j++) { \ + k = FFMAX(-xp, 0); \ + d = dp + (xp+k) * dst_step; \ + s = sp + k; \ + a = ap + (k<blend_row[i]) { \ + int c = octx->blend_row[i]((uint8_t*)d, (uint8_t*)da, (uint8_t*)s, \ + (uint8_t*)a, kmax - k, src->linesize[3]); \ + \ + s += c; \ + d += dst_step * c; \ + da += (1 << hsub) * c; \ + a += (1 << hsub) * c; \ + k += c; \ + } \ + for (; k < kmax; k++) { \ + int alpha_v, alpha_h, alpha; \ + \ + /* average alpha for color components, improve quality */ \ + if (hsub && vsub && j+1 < src_hp && k+1 < src_wp) { \ + alpha = (a[0] + a[src->linesize[3]] + \ + a[1] + a[src->linesize[3]+1]) >> 2; \ + } else if (hsub || vsub) { \ + alpha_h = hsub && k+1 < src_wp ? \ + (a[0] + a[1]) >> 1 : a[0]; \ + alpha_v = vsub && j+1 < src_hp ? \ + (a[0] + a[src->linesize[3]]) >> 1 : a[0]; \ + alpha = (alpha_v + alpha_h) >> 1; \ + } else \ + alpha = a[0]; \ + /* if the main channel has an alpha channel, alpha has to be calculated */ \ + /* to create an un-premultiplied (straight) alpha value */ \ + if (main_has_alpha && alpha != 0 && alpha != max) { \ + /* average alpha for color components, improve quality */ \ + uint8_t alpha_d; \ + if (hsub && vsub && j+1 < src_hp && k+1 < src_wp) { \ + alpha_d = (da[0] + da[dst->linesize[3]] + \ + da[1] + da[dst->linesize[3]+1]) >> 2; \ + } else if (hsub || vsub) { \ + alpha_h = hsub && k+1 < src_wp ? \ + (da[0] + da[1]) >> 1 : da[0]; \ + alpha_v = vsub && j+1 < src_hp ? \ + (da[0] + da[dst->linesize[3]]) >> 1 : da[0]; \ + alpha_d = (alpha_v + alpha_h) >> 1; \ + } else \ + alpha_d = da[0]; \ + alpha = UNPREMULTIPLY_ALPHA(alpha, alpha_d); \ + } \ + if (straight) { \ + if (nbits > 8) \ + *d = (*d * (max - alpha) + *s * alpha) / max; \ + else \ + *d = FAST_DIV255(*d * (255 - alpha) + *s * alpha); \ + } else { \ + if (nbits > 8) { \ + if (i && yuv) \ + *d = av_clip((*d * (max - alpha) + *s * alpha) / max + *s - mid, -mid, mid) + mid; \ + else \ + *d = FFMIN((*d * (max - alpha) + *s * alpha) / max + *s, max); \ + } else { \ + if (i && yuv) \ + *d = av_clip(FAST_DIV255((*d - mid) * (max - alpha)) + *s - mid, -mid, mid) + mid; \ + else \ + *d = FFMIN(FAST_DIV255(*d * (max - alpha)) + *s, max); \ + } \ + } \ + s++; \ + d += dst_step; \ + da += 1 << hsub; \ + a += 1 << hsub; \ + } \ + dp += dst->linesize[dst_plane] / bytes; \ + sp += src->linesize[i] / bytes; \ + ap += (1 << vsub) * src->linesize[3] / bytes; \ + dap += (1 << vsub) * dst->linesize[3] / bytes; \ + } \ +} +DEFINE_BLEND_PLANE(8, 8) +DEFINE_BLEND_PLANE(16, 10) + +#define DEFINE_ALPHA_COMPOSITE(depth, nbits) \ +static inline void alpha_composite_##depth##_##nbits##bits(const AVFrame *src, const AVFrame *dst, \ + int src_w, int src_h, \ + int dst_w, int dst_h, \ + int x, int y, \ + int jobnr, int nb_jobs) \ +{ \ + uint##depth##_t alpha; /* the amount of overlay to blend on to main */ \ + uint##depth##_t *s, *sa, *d, *da; \ + int i, imax, j, jmax; \ + int slice_start, slice_end; \ + const uint##depth##_t max = (1 << nbits) - 1; \ + int bytes = depth / 8; \ + \ + imax = FFMIN(-y + dst_h, src_h); \ + slice_start = (imax * jobnr) / nb_jobs; \ + slice_end = ((imax * (jobnr+1)) / nb_jobs); \ + \ + i = FFMAX(-y, 0); \ + sa = (uint##depth##_t *)(src->data[3] + (i + slice_start) * src->linesize[3]); \ + da = (uint##depth##_t *)(dst->data[3] + (y + i + slice_start) * dst->linesize[3]); \ + \ + for (i = i + slice_start; i < slice_end; i++) { \ + j = FFMAX(-x, 0); \ + s = sa + j; \ + d = da + x+j; \ + \ + for (jmax = FFMIN(-x + dst_w, src_w); j < jmax; j++) { \ + alpha = *s; \ + if (alpha != 0 && alpha != max) { \ + uint8_t alpha_d = *d; \ + alpha = UNPREMULTIPLY_ALPHA(alpha, alpha_d); \ + } \ + if (alpha == max) \ + *d = *s; \ + else if (alpha > 0) { \ + /* apply alpha compositing: main_alpha += (1-main_alpha) * overlay_alpha */ \ + if (nbits > 8) \ + *d += (max - *d) * *s / max; \ + else \ + *d += FAST_DIV255((max - *d) * *s); \ + } \ + d += 1; \ + s += 1; \ + } \ + da += dst->linesize[3] / bytes; \ + sa += src->linesize[3] / bytes; \ + } \ +} +DEFINE_ALPHA_COMPOSITE(8, 8) +DEFINE_ALPHA_COMPOSITE(16, 10) + +#define DEFINE_BLEND_SLICE_YUV(depth, nbits) \ +static av_always_inline void blend_slice_yuv_##depth##_##nbits##bits(AVFilterContext *ctx, \ + AVFrame *dst, const AVFrame *src, \ + int hsub, int vsub, \ + int main_has_alpha, \ + int x, int y, \ + int is_straight, \ + int jobnr, int nb_jobs) \ +{ \ + OverlayContext *s = ctx->priv; \ + const int src_w = src->width; \ + const int src_h = src->height; \ + const int dst_w = dst->width; \ + const int dst_h = dst->height; \ + \ + blend_plane_##depth##_##nbits##bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0, 0, \ + x, y, main_has_alpha, s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, \ + s->main_desc->comp[0].step, is_straight, 1, jobnr, nb_jobs); \ + blend_plane_##depth##_##nbits##bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, \ + x, y, main_has_alpha, s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, \ + s->main_desc->comp[1].step, is_straight, 1, jobnr, nb_jobs); \ + blend_plane_##depth##_##nbits##bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, \ + x, y, main_has_alpha, s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, \ + s->main_desc->comp[2].step, is_straight, 1, jobnr, nb_jobs); \ + \ + if (main_has_alpha) \ + alpha_composite_##depth##_##nbits##bits(src, dst, src_w, src_h, dst_w, dst_h, x, y, \ + jobnr, nb_jobs); \ } +DEFINE_BLEND_SLICE_YUV(8, 8) +DEFINE_BLEND_SLICE_YUV(16, 10) static av_always_inline void blend_slice_planar_rgb(AVFilterContext *ctx, AVFrame *dst, const AVFrame *src, @@ -641,25 +659,25 @@ const int dst_w = dst->width; const int dst_h = dst->height; - blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0, 0, x, y, main_has_alpha, + blend_plane_8_8bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0, 0, x, y, main_has_alpha, s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, s->main_desc->comp[1].step, is_straight, 0, jobnr, nb_jobs); - blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, x, y, main_has_alpha, + blend_plane_8_8bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, x, y, main_has_alpha, s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, s->main_desc->comp[2].step, is_straight, 0, jobnr, nb_jobs); - blend_plane(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, x, y, main_has_alpha, + blend_plane_8_8bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, x, y, main_has_alpha, s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, s->main_desc->comp[0].step, is_straight, 0, jobnr, nb_jobs); if (main_has_alpha) - alpha_composite(src, dst, src_w, src_h, dst_w, dst_h, x, y, jobnr, nb_jobs); + alpha_composite_8_8bits(src, dst, src_w, src_h, dst_w, dst_h, x, y, jobnr, nb_jobs); } static int blend_slice_yuv420(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { OverlayContext *s = ctx->priv; ThreadData *td = arg; - blend_slice_yuv(ctx, td->dst, td->src, 1, 1, 0, s->x, s->y, 1, jobnr, nb_jobs); + blend_slice_yuv_8_8bits(ctx, td->dst, td->src, 1, 1, 0, s->x, s->y, 1, jobnr, nb_jobs); return 0; } @@ -667,7 +685,39 @@ { OverlayContext *s = ctx->priv; ThreadData *td = arg; - blend_slice_yuv(ctx, td->dst, td->src, 1, 1, 1, s->x, s->y, 1, jobnr, nb_jobs); + blend_slice_yuv_8_8bits(ctx, td->dst, td->src, 1, 1, 1, s->x, s->y, 1, jobnr, nb_jobs); + return 0; +} + +static int blend_slice_yuv420p10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + OverlayContext *s = ctx->priv; + ThreadData *td = arg; + blend_slice_yuv_16_10bits(ctx, td->dst, td->src, 1, 1, 0, s->x, s->y, 1, jobnr, nb_jobs); + return 0; +} + +static int blend_slice_yuva420p10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + OverlayContext *s = ctx->priv; + ThreadData *td = arg; + blend_slice_yuv_16_10bits(ctx, td->dst, td->src, 1, 1, 1, s->x, s->y, 1, jobnr, nb_jobs); + return 0; +} + +static int blend_slice_yuv422p10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + OverlayContext *s = ctx->priv; + ThreadData *td = arg; + blend_slice_yuv_16_10bits(ctx, td->dst, td->src, 1, 0, 0, s->x, s->y, 1, jobnr, nb_jobs); + return 0; +} + +static int blend_slice_yuva422p10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + OverlayContext *s = ctx->priv; + ThreadData *td = arg; + blend_slice_yuv_16_10bits(ctx, td->dst, td->src, 1, 0, 1, s->x, s->y, 1, jobnr, nb_jobs); return 0; } @@ -675,7 +725,7 @@ { OverlayContext *s = ctx->priv; ThreadData *td = arg; - blend_slice_yuv(ctx, td->dst, td->src, 1, 0, 0, s->x, s->y, 1, jobnr, nb_jobs); + blend_slice_yuv_8_8bits(ctx, td->dst, td->src, 1, 0, 0, s->x, s->y, 1, jobnr, nb_jobs); return 0; } @@ -683,7 +733,7 @@ { OverlayContext *s = ctx->priv; ThreadData *td = arg; - blend_slice_yuv(ctx, td->dst, td->src, 1, 0, 1, s->x, s->y, 1, jobnr, nb_jobs); + blend_slice_yuv_8_8bits(ctx, td->dst, td->src, 1, 0, 1, s->x, s->y, 1, jobnr, nb_jobs); return 0; } @@ -691,7 +741,7 @@ { OverlayContext *s = ctx->priv; ThreadData *td = arg; - blend_slice_yuv(ctx, td->dst, td->src, 0, 0, 0, s->x, s->y, 1, jobnr, nb_jobs); + blend_slice_yuv_8_8bits(ctx, td->dst, td->src, 0, 0, 0, s->x, s->y, 1, jobnr, nb_jobs); return 0; } @@ -699,7 +749,7 @@ { OverlayContext *s = ctx->priv; ThreadData *td = arg; - blend_slice_yuv(ctx, td->dst, td->src, 0, 0, 1, s->x, s->y, 1, jobnr, nb_jobs); + blend_slice_yuv_8_8bits(ctx, td->dst, td->src, 0, 0, 1, s->x, s->y, 1, jobnr, nb_jobs); return 0; } @@ -723,7 +773,7 @@ { OverlayContext *s = ctx->priv; ThreadData *td = arg; - blend_slice_yuv(ctx, td->dst, td->src, 1, 1, 0, s->x, s->y, 0, jobnr, nb_jobs); + blend_slice_yuv_8_8bits(ctx, td->dst, td->src, 1, 1, 0, s->x, s->y, 0, jobnr, nb_jobs); return 0; } @@ -731,7 +781,7 @@ { OverlayContext *s = ctx->priv; ThreadData *td = arg; - blend_slice_yuv(ctx, td->dst, td->src, 1, 1, 1, s->x, s->y, 0, jobnr, nb_jobs); + blend_slice_yuv_8_8bits(ctx, td->dst, td->src, 1, 1, 1, s->x, s->y, 0, jobnr, nb_jobs); return 0; } @@ -739,7 +789,7 @@ { OverlayContext *s = ctx->priv; ThreadData *td = arg; - blend_slice_yuv(ctx, td->dst, td->src, 1, 0, 0, s->x, s->y, 0, jobnr, nb_jobs); + blend_slice_yuv_8_8bits(ctx, td->dst, td->src, 1, 0, 0, s->x, s->y, 0, jobnr, nb_jobs); return 0; } @@ -747,7 +797,7 @@ { OverlayContext *s = ctx->priv; ThreadData *td = arg; - blend_slice_yuv(ctx, td->dst, td->src, 1, 0, 1, s->x, s->y, 0, jobnr, nb_jobs); + blend_slice_yuv_8_8bits(ctx, td->dst, td->src, 1, 0, 1, s->x, s->y, 0, jobnr, nb_jobs); return 0; } @@ -755,7 +805,7 @@ { OverlayContext *s = ctx->priv; ThreadData *td = arg; - blend_slice_yuv(ctx, td->dst, td->src, 0, 0, 0, s->x, s->y, 0, jobnr, nb_jobs); + blend_slice_yuv_8_8bits(ctx, td->dst, td->src, 0, 0, 0, s->x, s->y, 0, jobnr, nb_jobs); return 0; } @@ -763,7 +813,7 @@ { OverlayContext *s = ctx->priv; ThreadData *td = arg; - blend_slice_yuv(ctx, td->dst, td->src, 0, 0, 1, s->x, s->y, 0, jobnr, nb_jobs); + blend_slice_yuv_8_8bits(ctx, td->dst, td->src, 0, 0, 1, s->x, s->y, 0, jobnr, nb_jobs); return 0; } @@ -834,9 +884,15 @@ case OVERLAY_FORMAT_YUV420: s->blend_slice = s->main_has_alpha ? blend_slice_yuva420 : blend_slice_yuv420; break; + case OVERLAY_FORMAT_YUV420P10: + s->blend_slice = s->main_has_alpha ? blend_slice_yuva420p10 : blend_slice_yuv420p10; + break; case OVERLAY_FORMAT_YUV422: s->blend_slice = s->main_has_alpha ? blend_slice_yuva422 : blend_slice_yuv422; break; + case OVERLAY_FORMAT_YUV422P10: + s->blend_slice = s->main_has_alpha ? blend_slice_yuva422p10 : blend_slice_yuv422p10; + break; case OVERLAY_FORMAT_YUV444: s->blend_slice = s->main_has_alpha ? blend_slice_yuva444 : blend_slice_yuv444; break; @@ -851,9 +907,15 @@ case AV_PIX_FMT_YUVA420P: s->blend_slice = blend_slice_yuva420; break; + case AV_PIX_FMT_YUVA420P10: + s->blend_slice = blend_slice_yuva420p10; + break; case AV_PIX_FMT_YUVA422P: s->blend_slice = blend_slice_yuva422; break; + case AV_PIX_FMT_YUVA422P10: + s->blend_slice = blend_slice_yuva422p10; + break; case AV_PIX_FMT_YUVA444P: s->blend_slice = blend_slice_yuva444; break; @@ -991,8 +1053,8 @@ #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption overlay_options[] = { - { "x", "set the x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "y", "set the y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "x", "set the x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "0"}, 0, 0, FLAGS }, + { "y", "set the y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "0"}, 0, 0, FLAGS }, { "eof_action", "Action to take when encountering EOF from secondary input ", OFFSET(fs.opt_eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT }, EOF_ACTION_REPEAT, EOF_ACTION_PASS, .flags = FLAGS, "eof_action" }, @@ -1005,7 +1067,9 @@ { "shortest", "force termination when the shortest input terminates", OFFSET(fs.opt_shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, { "format", "set output format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=OVERLAY_FORMAT_YUV420}, 0, OVERLAY_FORMAT_NB-1, FLAGS, "format" }, { "yuv420", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV420}, .flags = FLAGS, .unit = "format" }, + { "yuv420p10", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV420P10}, .flags = FLAGS, .unit = "format" }, { "yuv422", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV422}, .flags = FLAGS, .unit = "format" }, + { "yuv422p10", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV422P10}, .flags = FLAGS, .unit = "format" }, { "yuv444", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_YUV444}, .flags = FLAGS, .unit = "format" }, { "rgb", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_RGB}, .flags = FLAGS, .unit = "format" }, { "gbrp", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_GBRP}, .flags = FLAGS, .unit = "format" }, diff -Nru ffmpeg-4.2.2/libavfilter/vf_overlay_cuda.c ffmpeg-4.4/libavfilter/vf_overlay_cuda.c --- ffmpeg-4.2.2/libavfilter/vf_overlay_cuda.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_overlay_cuda.c 2021-04-08 21:28:27.000000000 +0000 @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2020 Yaroslav Pogrebnyak + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * Overlay one video on top of another using cuda hardware acceleration + */ + +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_cuda_internal.h" +#include "libavutil/cuda_check.h" + +#include "avfilter.h" +#include "framesync.h" +#include "internal.h" + +#define CHECK_CU(x) FF_CUDA_CHECK_DL(ctx, ctx->hwctx->internal->cuda_dl, x) +#define DIV_UP(a, b) ( ((a) + (b) - 1) / (b) ) + +#define BLOCK_X 32 +#define BLOCK_Y 16 + +static const enum AVPixelFormat supported_main_formats[] = { + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE, +}; + +static const enum AVPixelFormat supported_overlay_formats[] = { + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVA420P, + AV_PIX_FMT_NONE, +}; + +/** + * OverlayCUDAContext + */ +typedef struct OverlayCUDAContext { + const AVClass *class; + + enum AVPixelFormat in_format_overlay; + enum AVPixelFormat in_format_main; + + AVCUDADeviceContext *hwctx; + + CUcontext cu_ctx; + CUmodule cu_module; + CUfunction cu_func; + CUstream cu_stream; + + FFFrameSync fs; + + int x_position; + int y_position; + +} OverlayCUDAContext; + +/** + * Helper to find out if provided format is supported by filter + */ +static int format_is_supported(const enum AVPixelFormat formats[], enum AVPixelFormat fmt) +{ + for (int i = 0; formats[i] != AV_PIX_FMT_NONE; i++) + if (formats[i] == fmt) + return 1; + return 0; +} + +/** + * Helper checks if we can process main and overlay pixel formats + */ +static int formats_match(const enum AVPixelFormat format_main, const enum AVPixelFormat format_overlay) { + switch(format_main) { + case AV_PIX_FMT_NV12: + return format_overlay == AV_PIX_FMT_NV12; + case AV_PIX_FMT_YUV420P: + return format_overlay == AV_PIX_FMT_YUV420P || + format_overlay == AV_PIX_FMT_YUVA420P; + default: + return 0; + } +} + +/** + * Call overlay kernell for a plane + */ +static int overlay_cuda_call_kernel( + OverlayCUDAContext *ctx, + int x_position, int y_position, + uint8_t* main_data, int main_linesize, + int main_width, int main_height, + uint8_t* overlay_data, int overlay_linesize, + int overlay_width, int overlay_height, + uint8_t* alpha_data, int alpha_linesize, + int alpha_adj_x, int alpha_adj_y) { + + CudaFunctions *cu = ctx->hwctx->internal->cuda_dl; + + void* kernel_args[] = { + &x_position, &y_position, + &main_data, &main_linesize, + &overlay_data, &overlay_linesize, + &overlay_width, &overlay_height, + &alpha_data, &alpha_linesize, + &alpha_adj_x, &alpha_adj_y, + }; + + return CHECK_CU(cu->cuLaunchKernel( + ctx->cu_func, + DIV_UP(main_width, BLOCK_X), DIV_UP(main_height, BLOCK_Y), 1, + BLOCK_X, BLOCK_Y, 1, + 0, ctx->cu_stream, kernel_args, NULL)); +} + +/** + * Perform blend overlay picture over main picture + */ +static int overlay_cuda_blend(FFFrameSync *fs) +{ + int ret; + + AVFilterContext *avctx = fs->parent; + OverlayCUDAContext *ctx = avctx->priv; + AVFilterLink *outlink = avctx->outputs[0]; + + CudaFunctions *cu = ctx->hwctx->internal->cuda_dl; + CUcontext dummy, cuda_ctx = ctx->hwctx->cuda_ctx; + + AVFrame *input_main, *input_overlay; + + ctx->cu_ctx = cuda_ctx; + + // read main and overlay frames from inputs + ret = ff_framesync_dualinput_get(fs, &input_main, &input_overlay); + if (ret < 0) + return ret; + + if (!input_main) + return AVERROR_BUG; + + if (!input_overlay) + return ff_filter_frame(outlink, input_main); + + ret = av_frame_make_writable(input_main); + if (ret < 0) { + av_frame_free(&input_main); + return ret; + } + + // push cuda context + + ret = CHECK_CU(cu->cuCtxPushCurrent(cuda_ctx)); + if (ret < 0) { + av_frame_free(&input_main); + return ret; + } + + // overlay first plane + + overlay_cuda_call_kernel(ctx, + ctx->x_position, ctx->y_position, + input_main->data[0], input_main->linesize[0], + input_main->width, input_main->height, + input_overlay->data[0], input_overlay->linesize[0], + input_overlay->width, input_overlay->height, + input_overlay->data[3], input_overlay->linesize[3], 1, 1); + + // overlay rest planes depending on pixel format + + switch(ctx->in_format_overlay) { + case AV_PIX_FMT_NV12: + overlay_cuda_call_kernel(ctx, + ctx->x_position, ctx->y_position / 2, + input_main->data[1], input_main->linesize[1], + input_main->width, input_main->height / 2, + input_overlay->data[1], input_overlay->linesize[1], + input_overlay->width, input_overlay->height / 2, + 0, 0, 0, 0); + break; + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUVA420P: + overlay_cuda_call_kernel(ctx, + ctx->x_position / 2 , ctx->y_position / 2, + input_main->data[1], input_main->linesize[1], + input_main->width / 2, input_main->height / 2, + input_overlay->data[1], input_overlay->linesize[1], + input_overlay->width / 2, input_overlay->height / 2, + input_overlay->data[3], input_overlay->linesize[3], 2, 2); + + overlay_cuda_call_kernel(ctx, + ctx->x_position / 2 , ctx->y_position / 2, + input_main->data[2], input_main->linesize[2], + input_main->width / 2, input_main->height / 2, + input_overlay->data[2], input_overlay->linesize[2], + input_overlay->width / 2, input_overlay->height / 2, + input_overlay->data[3], input_overlay->linesize[3], 2, 2); + break; + default: + av_log(ctx, AV_LOG_ERROR, "Passed unsupported overlay pixel format\n"); + av_frame_free(&input_main); + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + return AVERROR_BUG; + } + + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + + return ff_filter_frame(outlink, input_main); +} + +/** + * Initialize overlay_cuda + */ +static av_cold int overlay_cuda_init(AVFilterContext *avctx) +{ + OverlayCUDAContext* ctx = avctx->priv; + ctx->fs.on_event = &overlay_cuda_blend; + + return 0; +} + +/** + * Uninitialize overlay_cuda + */ +static av_cold void overlay_cuda_uninit(AVFilterContext *avctx) +{ + OverlayCUDAContext* ctx = avctx->priv; + + ff_framesync_uninit(&ctx->fs); + + if (ctx->hwctx && ctx->cu_module) { + CUcontext dummy; + CudaFunctions *cu = ctx->hwctx->internal->cuda_dl; + CHECK_CU(cu->cuCtxPushCurrent(ctx->cu_ctx)); + CHECK_CU(cu->cuModuleUnload(ctx->cu_module)); + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + } +} + +/** + * Activate overlay_cuda + */ +static int overlay_cuda_activate(AVFilterContext *avctx) +{ + OverlayCUDAContext *ctx = avctx->priv; + + return ff_framesync_activate(&ctx->fs); +} + +/** + * Query formats + */ +static int overlay_cuda_query_formats(AVFilterContext *avctx) +{ + static const enum AVPixelFormat pixel_formats[] = { + AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE, + }; + + AVFilterFormats *pix_fmts = ff_make_format_list(pixel_formats); + + return ff_set_common_formats(avctx, pix_fmts); +} + +/** + * Configure output + */ +static int overlay_cuda_config_output(AVFilterLink *outlink) +{ + + extern char vf_overlay_cuda_ptx[]; + + int err; + AVFilterContext* avctx = outlink->src; + OverlayCUDAContext* ctx = avctx->priv; + + AVFilterLink *inlink = avctx->inputs[0]; + AVHWFramesContext *frames_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data; + + AVFilterLink *inlink_overlay = avctx->inputs[1]; + AVHWFramesContext *frames_ctx_overlay = (AVHWFramesContext*)inlink_overlay->hw_frames_ctx->data; + + CUcontext dummy, cuda_ctx; + CudaFunctions *cu; + + // check main input formats + + if (!frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "No hw context provided on main input\n"); + return AVERROR(EINVAL); + } + + ctx->in_format_main = frames_ctx->sw_format; + if (!format_is_supported(supported_main_formats, ctx->in_format_main)) { + av_log(ctx, AV_LOG_ERROR, "Unsupported main input format: %s\n", + av_get_pix_fmt_name(ctx->in_format_main)); + return AVERROR(ENOSYS); + } + + // check overlay input formats + + if (!frames_ctx_overlay) { + av_log(ctx, AV_LOG_ERROR, "No hw context provided on overlay input\n"); + return AVERROR(EINVAL); + } + + ctx->in_format_overlay = frames_ctx_overlay->sw_format; + if (!format_is_supported(supported_overlay_formats, ctx->in_format_overlay)) { + av_log(ctx, AV_LOG_ERROR, "Unsupported overlay input format: %s\n", + av_get_pix_fmt_name(ctx->in_format_overlay)); + return AVERROR(ENOSYS); + } + + // check we can overlay pictures with those pixel formats + + if (!formats_match(ctx->in_format_main, ctx->in_format_overlay)) { + av_log(ctx, AV_LOG_ERROR, "Can't overlay %s on %s \n", + av_get_pix_fmt_name(ctx->in_format_overlay), av_get_pix_fmt_name(ctx->in_format_main)); + return AVERROR(EINVAL); + } + + // initialize + + ctx->hwctx = frames_ctx->device_ctx->hwctx; + cuda_ctx = ctx->hwctx->cuda_ctx; + ctx->fs.time_base = inlink->time_base; + + ctx->cu_stream = ctx->hwctx->stream; + + outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); + + // load functions + + cu = ctx->hwctx->internal->cuda_dl; + + err = CHECK_CU(cu->cuCtxPushCurrent(cuda_ctx)); + if (err < 0) { + return err; + } + + err = CHECK_CU(cu->cuModuleLoadData(&ctx->cu_module, vf_overlay_cuda_ptx)); + if (err < 0) { + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + return err; + } + + err = CHECK_CU(cu->cuModuleGetFunction(&ctx->cu_func, ctx->cu_module, "Overlay_Cuda")); + if (err < 0) { + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + return err; + } + + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + + // init dual input + + err = ff_framesync_init_dualinput(&ctx->fs, avctx); + if (err < 0) { + return err; + } + + return ff_framesync_configure(&ctx->fs); +} + + +#define OFFSET(x) offsetof(OverlayCUDAContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) + +static const AVOption overlay_cuda_options[] = { + { "x", "Overlay x position", + OFFSET(x_position), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, .flags = FLAGS }, + { "y", "Overlay y position", + OFFSET(y_position), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, .flags = FLAGS }, + { "eof_action", "Action to take when encountering EOF from secondary input ", + OFFSET(fs.opt_eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT }, + EOF_ACTION_REPEAT, EOF_ACTION_PASS, .flags = FLAGS, "eof_action" }, + { "repeat", "Repeat the previous frame.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_REPEAT }, .flags = FLAGS, "eof_action" }, + { "endall", "End both streams.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_ENDALL }, .flags = FLAGS, "eof_action" }, + { "pass", "Pass through the main input.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_PASS }, .flags = FLAGS, "eof_action" }, + { "shortest", "force termination when the shortest input terminates", OFFSET(fs.opt_shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, + { "repeatlast", "repeat overlay of the last overlay frame", OFFSET(fs.opt_repeatlast), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, + { NULL }, +}; + +FRAMESYNC_DEFINE_CLASS(overlay_cuda, OverlayCUDAContext, fs); + +static const AVFilterPad overlay_cuda_inputs[] = { + { + .name = "main", + .type = AVMEDIA_TYPE_VIDEO, + }, + { + .name = "overlay", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +static const AVFilterPad overlay_cuda_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &overlay_cuda_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_overlay_cuda = { + .name = "overlay_cuda", + .description = NULL_IF_CONFIG_SMALL("Overlay one video on top of another using CUDA"), + .priv_size = sizeof(OverlayCUDAContext), + .priv_class = &overlay_cuda_class, + .init = &overlay_cuda_init, + .uninit = &overlay_cuda_uninit, + .activate = &overlay_cuda_activate, + .query_formats = &overlay_cuda_query_formats, + .inputs = overlay_cuda_inputs, + .outputs = overlay_cuda_outputs, + .preinit = overlay_cuda_framesync_preinit, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_overlay_cuda.cu ffmpeg-4.4/libavfilter/vf_overlay_cuda.cu --- ffmpeg-4.2.2/libavfilter/vf_overlay_cuda.cu 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_overlay_cuda.cu 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020 Yaroslav Pogrebnyak + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +extern "C" { + +__global__ void Overlay_Cuda( + int x_position, int y_position, + unsigned char* main, int main_linesize, + unsigned char* overlay, int overlay_linesize, + int overlay_w, int overlay_h, + unsigned char* overlay_alpha, int alpha_linesize, + int alpha_adj_x, int alpha_adj_y) +{ + int x = blockIdx.x * blockDim.x + threadIdx.x; + int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (x >= overlay_w + x_position || + y >= overlay_h + y_position || + x < x_position || + y < y_position ) { + + return; + } + + int overlay_x = x - x_position; + int overlay_y = y - y_position; + + float alpha = 1.0; + if (alpha_linesize) { + alpha = overlay_alpha[alpha_adj_x * overlay_x + alpha_adj_y * overlay_y * alpha_linesize] / 255.0f; + } + + main[x + y*main_linesize] = alpha * overlay[overlay_x + overlay_y * overlay_linesize] + (1.0f - alpha) * main[x + y*main_linesize]; +} + +} + diff -Nru ffmpeg-4.2.2/libavfilter/vf_overlay.h ffmpeg-4.4/libavfilter/vf_overlay.h --- ffmpeg-4.2.2/libavfilter/vf_overlay.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_overlay.h 2021-04-08 21:28:40.000000000 +0000 @@ -41,7 +41,9 @@ enum OverlayFormat { OVERLAY_FORMAT_YUV420, + OVERLAY_FORMAT_YUV420P10, OVERLAY_FORMAT_YUV422, + OVERLAY_FORMAT_YUV422P10, OVERLAY_FORMAT_YUV444, OVERLAY_FORMAT_RGB, OVERLAY_FORMAT_GBRP, diff -Nru ffmpeg-4.2.2/libavfilter/vf_overlay_qsv.c ffmpeg-4.4/libavfilter/vf_overlay_qsv.c --- ffmpeg-4.2.2/libavfilter/vf_overlay_qsv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_overlay_qsv.c 2021-04-08 21:28:40.000000000 +0000 @@ -381,12 +381,12 @@ }; for (i = 0; i < ctx->nb_inputs; i++) { - ret = ff_formats_ref(ff_make_format_list(main_in_fmts), &ctx->inputs[i]->out_formats); + ret = ff_formats_ref(ff_make_format_list(main_in_fmts), &ctx->inputs[i]->outcfg.formats); if (ret < 0) return ret; } - ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats); + ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->incfg.formats); if (ret < 0) return ret; @@ -398,13 +398,11 @@ .name = "main", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_main_input, - .needs_fifo = 1, }, { .name = "overlay", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_overlay_input, - .needs_fifo = 1, }, { NULL } }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_overlay_vulkan.c ffmpeg-4.4/libavfilter/vf_overlay_vulkan.c --- ffmpeg-4.2.2/libavfilter/vf_overlay_vulkan.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_overlay_vulkan.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,490 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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.h" +#include "internal.h" +#include "framesync.h" + +#define CGROUPS (int [3]){ 32, 32, 1 } + +typedef struct OverlayVulkanContext { + VulkanFilterContext vkctx; + + int initialized; + VulkanPipeline *pl; + FFVkExecContext *exec; + FFFrameSync fs; + FFVkBuffer params_buf; + + /* Shader updators, must be in the main filter struct */ + VkDescriptorImageInfo main_images[3]; + VkDescriptorImageInfo overlay_images[3]; + VkDescriptorImageInfo output_images[3]; + VkDescriptorBufferInfo params_desc; + + int overlay_x; + int overlay_y; + int overlay_w; + int overlay_h; +} OverlayVulkanContext; + +static const char overlay_noalpha[] = { + C(0, void overlay_noalpha(int i, ivec2 pos) ) + C(0, { ) + C(1, if ((o_offset[i].x <= pos.x) && (o_offset[i].y <= pos.y) && + (pos.x < (o_offset[i].x + o_size[i].x)) && + (pos.y < (o_offset[i].y + o_size[i].y))) { ) + C(2, vec4 res = texture(overlay_img[i], pos - o_offset[i]); ) + C(2, imageStore(output_img[i], pos, res); ) + C(1, } else { ) + C(2, vec4 res = texture(main_img[i], pos); ) + C(2, imageStore(output_img[i], pos, res); ) + C(1, } ) + C(0, } ) +}; + +static const char overlay_alpha[] = { + C(0, void overlay_alpha_opaque(int i, ivec2 pos) ) + C(0, { ) + C(1, vec4 res = texture(main_img[i], pos); ) + C(1, if ((o_offset[i].x <= pos.x) && (o_offset[i].y <= pos.y) && + (pos.x < (o_offset[i].x + o_size[i].x)) && + (pos.y < (o_offset[i].y + o_size[i].y))) { ) + C(2, vec4 ovr = texture(overlay_img[i], pos - o_offset[i]); ) + C(2, res = ovr * ovr.a + res * (1.0f - ovr.a); ) + C(2, res.a = 1.0f; ) + C(2, imageStore(output_img[i], pos, res); ) + C(1, } ) + C(1, imageStore(output_img[i], pos, res); ) + C(0, } ) +}; + +static av_cold int init_filter(AVFilterContext *ctx) +{ + int err; + OverlayVulkanContext *s = ctx->priv; + VkSampler *sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_NEAREST); + if (!sampler) + return AVERROR_EXTERNAL; + + s->pl = ff_vk_create_pipeline(ctx); + 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] = { + { + .name = "main_img", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->main_images, + .samplers = DUP_SAMPLER_ARRAY4(*sampler), + }, + { + .name = "overlay_img", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->overlay_images, + .samplers = DUP_SAMPLER_ARRAY4(*sampler), + }, + { + .name = "output_img", + .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, + }, + }; + + VulkanDescriptorSetBinding desc_b = { + .name = "params", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .mem_quali = "readonly", + .mem_layout = "std430", + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = &s->params_desc, + .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); + if (!shd) + return AVERROR(ENOMEM); + + ff_vk_set_compute_shader_sizes(ctx, 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 */ + + GLSLD( overlay_noalpha ); + GLSLD( overlay_alpha ); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + GLSLF(1, int planes = %i; ,planes); + GLSLC(1, for (int i = 0; i < planes; i++) { ); + if (ialpha) + GLSLC(2, overlay_alpha_opaque(i, pos); ); + else + GLSLC(2, overlay_noalpha(i, pos); ); + GLSLC(1, } ); + GLSLC(0, } ); + + RET(ff_vk_compile_shader(ctx, shd, "main")); + } + + RET(ff_vk_init_pipeline_layout(ctx, s->pl)); + RET(ff_vk_init_compute_pipeline(ctx, s->pl)); + + { /* Create and update buffer */ + const AVPixFmtDescriptor *desc; + + /* NOTE: std430 requires the same identical struct layout, padding and + * alignment as C, so we're allowed to do this, as this will map + * exactly to what the shader recieves */ + struct { + int32_t o_offset[2*3]; + int32_t o_size[2*3]; + } *par; + + err = ff_vk_create_buf(ctx, &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); + if (err) + return err; + + desc = av_pix_fmt_desc_get(s->vkctx.output_format); + + par->o_offset[0] = s->overlay_x; + par->o_offset[1] = s->overlay_y; + par->o_offset[2] = par->o_offset[0] >> desc->log2_chroma_w; + par->o_offset[3] = par->o_offset[1] >> desc->log2_chroma_h; + par->o_offset[4] = par->o_offset[0] >> desc->log2_chroma_w; + par->o_offset[5] = par->o_offset[1] >> desc->log2_chroma_h; + + par->o_size[0] = s->overlay_w; + par->o_size[1] = s->overlay_h; + par->o_size[2] = par->o_size[0] >> desc->log2_chroma_w; + par->o_size[3] = par->o_size[1] >> desc->log2_chroma_h; + 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); + 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); + } + + /* Execution context */ + RET(ff_vk_create_exec_ctx(ctx, &s->exec)); + + s->initialized = 1; + + return 0; + +fail: + return err; +} + +static int process_frames(AVFilterContext *avctx, AVFrame *out_f, + AVFrame *main_f, AVFrame *overlay_f) +{ + int err; + VkCommandBuffer cmd_buf; + OverlayVulkanContext *s = avctx->priv; + 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 *overlay_fc = (AVHWFramesContext*)overlay_f->hw_frames_ctx->data; + + /* 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); + + 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], + 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], + 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], + ff_comp_identity_map)); + + s->main_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + s->overlay_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); + + for (int i = 0; i < planes; i++) { + VkImageMemoryBarrier bar[3] = { + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .oldLayout = main->layout[i], + .newLayout = s->main_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = main->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 = overlay->layout[i], + .newLayout = s->overlay_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = overlay->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, + }, + }; + + 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); + + main->layout[i] = bar[0].newLayout; + main->access[i] = bar[0].dstAccessMask; + + overlay->layout[i] = bar[1].newLayout; + overlay->access[i] = bar[1].dstAccessMask; + + out->layout[i] = bar[2].newLayout; + out->access[i] = bar[2].dstAccessMask; + } + + ff_vk_bind_pipeline_exec(avctx, 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); + + 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); + + err = ff_vk_submit_exec_queue(avctx, s->exec); + if (err) + return err; + + return err; + +fail: + ff_vk_discard_exec_deps(avctx, s->exec); + return err; +} + +static int overlay_vulkan_blend(FFFrameSync *fs) +{ + int err; + AVFilterContext *ctx = fs->parent; + OverlayVulkanContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *input_main, *input_overlay, *out; + + err = ff_framesync_get_frame(fs, 0, &input_main, 0); + if (err < 0) + goto fail; + err = ff_framesync_get_frame(fs, 1, &input_overlay, 0); + if (err < 0) + goto fail; + + if (!input_main || !input_overlay) + return 0; + + if (!s->initialized) { + AVHWFramesContext *main_fc = (AVHWFramesContext*)input_main->hw_frames_ctx->data; + AVHWFramesContext *overlay_fc = (AVHWFramesContext*)input_overlay->hw_frames_ctx->data; + if (main_fc->sw_format != overlay_fc->sw_format) { + av_log(ctx, AV_LOG_ERROR, "Mismatching sw formats!\n"); + return AVERROR(EINVAL); + } + + s->overlay_w = input_overlay->width; + s->overlay_h = input_overlay->height; + + RET(init_filter(ctx)); + } + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + err = AVERROR(ENOMEM); + goto fail; + } + + RET(process_frames(ctx, out, input_main, input_overlay)); + + err = av_frame_copy_props(out, input_main); + if (err < 0) + goto fail; + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&out); + return err; +} + +static int overlay_vulkan_config_output(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + OverlayVulkanContext *s = avctx->priv; + + err = ff_vk_filter_config_output(outlink); + if (err < 0) + return err; + + err = ff_framesync_init_dualinput(&s->fs, avctx); + if (err < 0) + return err; + + return ff_framesync_configure(&s->fs); +} + +static int overlay_vulkan_activate(AVFilterContext *avctx) +{ + OverlayVulkanContext *s = avctx->priv; + + return ff_framesync_activate(&s->fs); +} + +static av_cold int overlay_vulkan_init(AVFilterContext *avctx) +{ + OverlayVulkanContext *s = avctx->priv; + + s->fs.on_event = &overlay_vulkan_blend; + + return ff_vk_filter_init(avctx); +} + +static void overlay_vulkan_uninit(AVFilterContext *avctx) +{ + OverlayVulkanContext *s = avctx->priv; + + ff_vk_filter_uninit(avctx); + ff_framesync_uninit(&s->fs); + + ff_vk_free_buf(avctx, &s->params_buf); + + s->initialized = 0; +} + +#define OFFSET(x) offsetof(OverlayVulkanContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption overlay_vulkan_options[] = { + { "x", "Set horizontal offset", OFFSET(overlay_x), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, .flags = FLAGS }, + { "y", "Set vertical offset", OFFSET(overlay_y), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, .flags = FLAGS }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(overlay_vulkan); + +static const AVFilterPad overlay_vulkan_inputs[] = { + { + .name = "main", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_input, + }, + { + .name = "overlay", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_input, + }, + { NULL } +}; + +static const AVFilterPad overlay_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &overlay_vulkan_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_overlay_vulkan = { + .name = "overlay_vulkan", + .description = NULL_IF_CONFIG_SMALL("Overlay a source on top of another"), + .priv_size = sizeof(OverlayVulkanContext), + .init = &overlay_vulkan_init, + .uninit = &overlay_vulkan_uninit, + .query_formats = &ff_vk_filter_query_formats, + .activate = &overlay_vulkan_activate, + .inputs = overlay_vulkan_inputs, + .outputs = overlay_vulkan_outputs, + .priv_class = &overlay_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_owdenoise.c ffmpeg-4.4/libavfilter/vf_owdenoise.c --- ffmpeg-4.2.2/libavfilter/vf_owdenoise.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_owdenoise.c 2021-04-08 21:28:40.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/imgutils.h" #include "libavutil/opt.h" +#include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" #include "avfilter.h" #include "internal.h" diff -Nru ffmpeg-4.2.2/libavfilter/vf_pad.c ffmpeg-4.4/libavfilter/vf_pad.c --- ffmpeg-4.2.2/libavfilter/vf_pad.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_pad.c 2020-07-11 10:39:30.000000000 +0000 @@ -178,14 +178,14 @@ if (s->y < 0 || s->y + inlink->h > s->h) s->y = var_values[VAR_Y] = (s->h - inlink->h) / 2; + s->w = ff_draw_round_to_sub(&s->draw, 0, -1, s->w); + s->h = ff_draw_round_to_sub(&s->draw, 1, -1, s->h); /* sanity check params */ - if (s->w < 0 || s->h < 0) { - av_log(ctx, AV_LOG_ERROR, "Negative values are not acceptable.\n"); + if (s->w < inlink->w || s->h < inlink->h) { + av_log(ctx, AV_LOG_ERROR, "Padded dimensions cannot be smaller than input dimensions.\n"); return AVERROR(EINVAL); } - s->w = ff_draw_round_to_sub(&s->draw, 0, -1, s->w); - s->h = ff_draw_round_to_sub(&s->draw, 1, -1, s->h); s->x = ff_draw_round_to_sub(&s->draw, 0, -1, s->x); s->y = ff_draw_round_to_sub(&s->draw, 1, -1, s->y); s->in_w = ff_draw_round_to_sub(&s->draw, 0, -1, inlink->w); @@ -210,7 +210,7 @@ return 0; eval_fail: - av_log(NULL, AV_LOG_ERROR, + av_log(ctx, AV_LOG_ERROR, "Error when evaluating the expression '%s'\n", expr); return ret; @@ -417,12 +417,12 @@ #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption pad_options[] = { - { "width", "set the pad area width expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "w", "set the pad area width expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "height", "set the pad area height expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "h", "set the pad area height expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "x", "set the x offset expression for the input image position", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "y", "set the y offset expression for the input image position", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "width", "set the pad area width expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, 0, 0, FLAGS }, + { "w", "set the pad area width expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, 0, 0, FLAGS }, + { "height", "set the pad area height expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, 0, 0, FLAGS }, + { "h", "set the pad area height expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, 0, 0, FLAGS }, + { "x", "set the x offset expression for the input image position", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "0"}, 0, 0, FLAGS }, + { "y", "set the y offset expression for the input image position", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "0"}, 0, 0, FLAGS }, { "color", "set the color of the padded area border", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str = "black"}, .flags = 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}, .flags = FLAGS, .unit = "eval" }, diff -Nru ffmpeg-4.2.2/libavfilter/vf_pad_opencl.c ffmpeg-4.4/libavfilter/vf_pad_opencl.c --- ffmpeg-4.2.2/libavfilter/vf_pad_opencl.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_pad_opencl.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,397 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/colorspace.h" +#include "libavutil/eval.h" +#include "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "avfilter.h" +#include "drawutils.h" +#include "formats.h" +#include "internal.h" +#include "opencl.h" +#include "opencl_source.h" +#include "video.h" + +static const char *const var_names[] = { + "in_w", "iw", + "in_h", "ih", + "out_w", "ow", + "out_h", "oh", + "x", + "y", + "a", + "sar", + "dar", + 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_X, + VAR_Y, + VAR_A, + VAR_SAR, + VAR_DAR, + VARS_NB +}; + +typedef struct PadOpenCLContext { + OpenCLFilterContext ocf; + int initialized; + int is_rgb; + int is_packed; + int hsub, vsub; + + char *w_expr; + char *h_expr; + char *x_expr; + char *y_expr; + AVRational aspect; + + cl_command_queue command_queue; + cl_kernel kernel_pad; + + int w, h; + int x, y; + uint8_t pad_rgba[4]; + uint8_t pad_color[4]; + cl_float4 pad_color_float; + cl_int2 pad_pos; +} PadOpenCLContext; + +static int pad_opencl_init(AVFilterContext *avctx, AVFrame *input_frame) +{ + PadOpenCLContext *ctx = avctx->priv; + AVHWFramesContext *input_frames_ctx = (AVHWFramesContext *)input_frame->hw_frames_ctx->data; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(input_frames_ctx->sw_format); + uint8_t rgba_map[4]; + cl_int cle; + int err; + + ff_fill_rgba_map(rgba_map, input_frames_ctx->sw_format); + ctx->is_rgb = !!(desc->flags & AV_PIX_FMT_FLAG_RGB); + ctx->is_packed = !(desc->flags & AV_PIX_FMT_FLAG_PLANAR); + ctx->hsub = desc->log2_chroma_w; + ctx->vsub = desc->log2_chroma_h; + + err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_pad, 1); + if (err < 0) + goto fail; + + ctx->command_queue = clCreateCommandQueue( + ctx->ocf.hwctx->context, + ctx->ocf.hwctx->device_id, + 0, + &cle + ); + + if (ctx->is_rgb) { + ctx->pad_color[rgba_map[0]] = ctx->pad_rgba[0]; + ctx->pad_color[rgba_map[1]] = ctx->pad_rgba[1]; + ctx->pad_color[rgba_map[2]] = ctx->pad_rgba[2]; + ctx->pad_color[rgba_map[3]] = ctx->pad_rgba[3]; + } else { + ctx->pad_color[0] = RGB_TO_Y_BT709(ctx->pad_rgba[0], ctx->pad_rgba[1], ctx->pad_rgba[2]); + ctx->pad_color[1] = RGB_TO_U_BT709(ctx->pad_rgba[0], ctx->pad_rgba[1], ctx->pad_rgba[2], 0); + ctx->pad_color[2] = RGB_TO_V_BT709(ctx->pad_rgba[0], ctx->pad_rgba[1], ctx->pad_rgba[2], 0); + ctx->pad_color[3] = ctx->pad_rgba[3]; + } + + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create OpenCL command queue %d.\n", cle); + + ctx->kernel_pad = clCreateKernel(ctx->ocf.program, "pad", &cle); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create pad kernel: %d.\n", cle); + + for (int i = 0; i < 4; ++i) { + ctx->pad_color_float.s[i] = (float)ctx->pad_color[i] / 255.0; + } + + ctx->pad_pos.s[0] = ctx->x; + ctx->pad_pos.s[1] = ctx->y; + + ctx->initialized = 1; + return 0; + +fail: + if (ctx->command_queue) + clReleaseCommandQueue(ctx->command_queue); + if (ctx->kernel_pad) + clReleaseKernel(ctx->kernel_pad); + return err; +} + +static int filter_frame(AVFilterLink *link, AVFrame *input_frame) +{ + AVFilterContext *avctx = link->dst; + AVFilterLink *outlink = avctx->outputs[0]; + PadOpenCLContext *pad_ctx = avctx->priv; + AVFrame *output_frame = NULL; + int err; + cl_int cle; + size_t global_work[2]; + cl_mem src, dst; + + if (!input_frame->hw_frames_ctx) + return AVERROR(EINVAL); + + if (!pad_ctx->initialized) { + err = pad_opencl_init(avctx, input_frame); + if (err < 0) + goto fail; + } + + output_frame = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!output_frame) { + err = AVERROR(ENOMEM); + goto fail; + } + + for (int p = 0; p < FF_ARRAY_ELEMS(output_frame->data); p++) { + cl_float4 pad_color_float; + cl_int2 pad_pos; + + if (pad_ctx->is_packed) { + pad_color_float = pad_ctx->pad_color_float; + } else { + pad_color_float.s[0] = pad_ctx->pad_color_float.s[p]; + pad_color_float.s[1] = pad_ctx->pad_color_float.s[2]; + } + + if (p > 0 && p < 3) { + pad_pos.s[0] = pad_ctx->pad_pos.s[0] >> pad_ctx->hsub; + pad_pos.s[1] = pad_ctx->pad_pos.s[1] >> pad_ctx->vsub; + } else { + pad_pos.s[0] = pad_ctx->pad_pos.s[0]; + pad_pos.s[1] = pad_ctx->pad_pos.s[1]; + } + + src = (cl_mem)input_frame->data[p]; + dst = (cl_mem)output_frame->data[p]; + + if (!dst) + break; + + CL_SET_KERNEL_ARG(pad_ctx->kernel_pad, 0, cl_mem, &src); + CL_SET_KERNEL_ARG(pad_ctx->kernel_pad, 1, cl_mem, &dst); + CL_SET_KERNEL_ARG(pad_ctx->kernel_pad, 2, cl_float4, &pad_color_float); + CL_SET_KERNEL_ARG(pad_ctx->kernel_pad, 3, cl_int2, &pad_pos); + + err = ff_opencl_filter_work_size_from_image(avctx, global_work, output_frame, p, 16); + if (err < 0) + goto fail; + + cle = clEnqueueNDRangeKernel(pad_ctx->command_queue, pad_ctx->kernel_pad, 2, NULL, + global_work, NULL, 0, NULL, NULL); + + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to enqueue pad kernel: %d.\n", cle); + } + + // Run queued kernel + cle = clFinish(pad_ctx->command_queue); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to finish command queue: %d.\n", cle); + + err = av_frame_copy_props(output_frame, input_frame); + if (err < 0) + goto fail; + + av_frame_free(&input_frame); + + return ff_filter_frame(outlink, output_frame); + +fail: + clFinish(pad_ctx->command_queue); + av_frame_free(&input_frame); + av_frame_free(&output_frame); + return err; +} + +static av_cold void pad_opencl_uninit(AVFilterContext *avctx) +{ + PadOpenCLContext *ctx = avctx->priv; + cl_int cle; + + if (ctx->kernel_pad) { + cle = clReleaseKernel(ctx->kernel_pad); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "kernel: %d.\n", cle); + } + + if (ctx->command_queue) { + cle = clReleaseCommandQueue(ctx->command_queue); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "command queue: %d.\n", cle); + } + + ff_opencl_filter_uninit(avctx); +} + +static int pad_opencl_config_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + AVFilterLink *inlink = avctx->inputs[0]; + PadOpenCLContext *ctx = avctx->priv; + AVRational adjusted_aspect = ctx->aspect; + double var_values[VARS_NB], res; + int err, ret; + char *expr; + + var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w; + var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h; + var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN; + var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN; + var_values[VAR_A] = (double) inlink->w / inlink->h; + var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? + (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; + var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; + + av_expr_parse_and_eval(&res, (expr = ctx->w_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx); + ctx->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res; + if ((ret = av_expr_parse_and_eval(&res, (expr = ctx->h_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) + return ret; + ctx->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res; + if (!ctx->h) + var_values[VAR_OUT_H] = var_values[VAR_OH] = ctx->h = inlink->h; + + /* evaluate the width again, as it may depend on the evaluated output height */ + if ((ret = av_expr_parse_and_eval(&res, (expr = ctx->w_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) + return ret; + ctx->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res; + if (!ctx->w) + var_values[VAR_OUT_W] = var_values[VAR_OW] = ctx->w = inlink->w; + + if (adjusted_aspect.num && adjusted_aspect.den) { + adjusted_aspect = av_div_q(adjusted_aspect, inlink->sample_aspect_ratio); + if (ctx->h < av_rescale(ctx->w, adjusted_aspect.den, adjusted_aspect.num)) { + ctx->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = av_rescale(ctx->w, adjusted_aspect.den, adjusted_aspect.num); + } else { + ctx->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = av_rescale(ctx->h, adjusted_aspect.num, adjusted_aspect.den); + } + } + + /* evaluate x and y */ + av_expr_parse_and_eval(&res, (expr = ctx->x_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx); + ctx->x = var_values[VAR_X] = res; + if ((ret = av_expr_parse_and_eval(&res, (expr = ctx->y_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) + return ret; + ctx->y = var_values[VAR_Y] = res; + /* evaluate x again, as it may depend on the evaluated y value */ + if ((ret = av_expr_parse_and_eval(&res, (expr = ctx->x_expr), + var_names, var_values, + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) + return ret; + ctx->x = var_values[VAR_X] = res; + + if (ctx->x < 0 || ctx->x + inlink->w > ctx->w) + ctx->x = var_values[VAR_X] = (ctx->w - inlink->w) / 2; + if (ctx->y < 0 || ctx->y + inlink->h > ctx->h) + ctx->y = var_values[VAR_Y] = (ctx->h - inlink->h) / 2; + + /* sanity check params */ + if (ctx->w < inlink->w || ctx->h < inlink->h) { + av_log(ctx, AV_LOG_ERROR, "Padded dimensions cannot be smaller than input dimensions.\n"); + return AVERROR(EINVAL); + } + + if (ctx->w > avctx->inputs[0]->w) { + ctx->ocf.output_width = ctx->w; + } else { + ctx->ocf.output_width = avctx->inputs[0]->w; + } + + if (ctx->h > avctx->inputs[0]->h) { + ctx->ocf.output_height = ctx->h; + } else { + ctx->ocf.output_height = avctx->inputs[0]->h; + } + + if (ctx->x + avctx->inputs[0]->w > ctx->ocf.output_width || + ctx->y + avctx->inputs[0]->h > ctx->ocf.output_height) { + return AVERROR(EINVAL); + } + + err = ff_opencl_filter_config_output(outlink); + if (err < 0) + return err; + + return 0; +} + +static const AVFilterPad pad_opencl_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = &ff_opencl_filter_config_input, + }, + { NULL } +}; + +static const AVFilterPad pad_opencl_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &pad_opencl_config_output, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(PadOpenCLContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption pad_opencl_options[] = { + { "width", "set the pad area width", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, 0, 0, FLAGS }, + { "w", "set the pad area width", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, 0, 0, FLAGS }, + { "height", "set the pad area height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, 0, 0, FLAGS }, + { "h", "set the pad area height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, 0, 0, FLAGS }, + { "x", "set the x offset for the input image position", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "0"}, 0, INT16_MAX, FLAGS }, + { "y", "set the y offset for the input image position", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "0"}, 0, INT16_MAX, FLAGS }, + { "color", "set the color of the padded area border", OFFSET(pad_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, 0, 0, FLAGS }, + { "aspect", "pad to fit an aspect instead of a resolution", OFFSET(aspect), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, INT16_MAX, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(pad_opencl); + +AVFilter ff_vf_pad_opencl = { + .name = "pad_opencl", + .description = NULL_IF_CONFIG_SMALL("Pad the input video."), + .priv_size = sizeof(PadOpenCLContext), + .priv_class = &pad_opencl_class, + .init = &ff_opencl_filter_init, + .uninit = &pad_opencl_uninit, + .query_formats = &ff_opencl_filter_query_formats, + .inputs = pad_opencl_inputs, + .outputs = pad_opencl_outputs, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_palettegen.c ffmpeg-4.4/libavfilter/vf_palettegen.c --- ffmpeg-4.2.2/libavfilter/vf_palettegen.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_palettegen.c 2021-04-08 21:28:40.000000000 +0000 @@ -83,7 +83,7 @@ static const AVOption palettegen_options[] = { { "max_colors", "set the maximum number of colors to use in the palette", OFFSET(max_colors), AV_OPT_TYPE_INT, {.i64=256}, 4, 256, FLAGS }, { "reserve_transparent", "reserve a palette entry for transparency", OFFSET(reserve_transparent), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, - { "transparency_color", "set a background color for transparency", OFFSET(transparency_color), AV_OPT_TYPE_COLOR, {.str="lime"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "transparency_color", "set a background color for transparency", OFFSET(transparency_color), AV_OPT_TYPE_COLOR, {.str="lime"}, 0, 0, FLAGS }, { "stats_mode", "set statistics mode", OFFSET(stats_mode), AV_OPT_TYPE_INT, {.i64=STATS_MODE_ALL_FRAMES}, 0, NB_STATS_MODE-1, FLAGS, "mode" }, { "full", "compute full frame histograms", 0, AV_OPT_TYPE_CONST, {.i64=STATS_MODE_ALL_FRAMES}, INT_MIN, INT_MAX, FLAGS, "mode" }, { "diff", "compute histograms only for the part that differs from previous frame", 0, AV_OPT_TYPE_CONST, {.i64=STATS_MODE_DIFF_FRAMES}, INT_MIN, INT_MAX, FLAGS, "mode" }, @@ -99,9 +99,9 @@ static const enum AVPixelFormat out_fmts[] = {AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE}; int ret; - if ((ret = ff_formats_ref(ff_make_format_list(in_fmts) , &ctx->inputs[0]->out_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(in_fmts) , &ctx->inputs[0]->outcfg.formats)) < 0) return ret; - if ((ret = ff_formats_ref(ff_make_format_list(out_fmts), &ctx->outputs[0]->in_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(out_fmts), &ctx->outputs[0]->incfg.formats)) < 0) return ret; return 0; } diff -Nru ffmpeg-4.2.2/libavfilter/vf_paletteuse.c ffmpeg-4.4/libavfilter/vf_paletteuse.c --- ffmpeg-4.2.2/libavfilter/vf_paletteuse.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_paletteuse.c 2021-04-08 21:28:40.000000000 +0000 @@ -122,7 +122,7 @@ { "alpha_threshold", "set the alpha threshold for transparency", OFFSET(trans_thresh), AV_OPT_TYPE_INT, {.i64=128}, 0, 255, FLAGS }, /* following are the debug options, not part of the official API */ - { "debug_kdtree", "save Graphviz graph of the kdtree in specified file", OFFSET(dot_filename), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "debug_kdtree", "save Graphviz graph of the kdtree in specified file", OFFSET(dot_filename), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, { "color_search", "set reverse colormap color search method", OFFSET(color_search_method), AV_OPT_TYPE_INT, {.i64=COLOR_SEARCH_NNS_ITERATIVE}, 0, NB_COLOR_SEARCHES-1, FLAGS, "search" }, { "nns_iterative", "iterative search", 0, AV_OPT_TYPE_CONST, {.i64=COLOR_SEARCH_NNS_ITERATIVE}, INT_MIN, INT_MAX, FLAGS, "search" }, { "nns_recursive", "recursive search", 0, AV_OPT_TYPE_CONST, {.i64=COLOR_SEARCH_NNS_RECURSIVE}, INT_MIN, INT_MAX, FLAGS, "search" }, @@ -142,25 +142,20 @@ static const enum AVPixelFormat inpal_fmts[] = {AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE}; static const enum AVPixelFormat out_fmts[] = {AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE}; int ret; - AVFilterFormats *in = ff_make_format_list(in_fmts); - AVFilterFormats *inpal = ff_make_format_list(inpal_fmts); - AVFilterFormats *out = ff_make_format_list(out_fmts); - if (!in || !inpal || !out) { - av_freep(&in); - av_freep(&inpal); - av_freep(&out); - return AVERROR(ENOMEM); - } - if ((ret = ff_formats_ref(in , &ctx->inputs[0]->out_formats)) < 0 || - (ret = ff_formats_ref(inpal, &ctx->inputs[1]->out_formats)) < 0 || - (ret = ff_formats_ref(out , &ctx->outputs[0]->in_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(in_fmts), + &ctx->inputs[0]->outcfg.formats)) < 0 || + (ret = ff_formats_ref(ff_make_format_list(inpal_fmts), + &ctx->inputs[1]->outcfg.formats)) < 0 || + (ret = ff_formats_ref(ff_make_format_list(out_fmts), + &ctx->outputs[0]->incfg.formats)) < 0) return ret; return 0; } -static av_always_inline int dither_color(uint32_t px, int er, int eg, int eb, int scale, int shift) +static av_always_inline uint32_t dither_color(uint32_t px, int er, int eg, + int eb, int scale, int shift) { - return av_clip_uint8( px >> 24 ) << 24 + return px >> 24 << 24 | av_clip_uint8((px >> 16 & 0xff) + ((er * scale) / (1<> 8 & 0xff) + ((eg * scale) / (1<w, outlink->h); if (!out) { - av_frame_free(&in); *outf = NULL; return AVERROR(ENOMEM); } @@ -913,13 +907,12 @@ s->last_out, out, &x, &y, &w, &h); av_frame_unref(s->last_in); av_frame_unref(s->last_out); - if (av_frame_ref(s->last_in, in) < 0 || - av_frame_ref(s->last_out, out) < 0 || - av_frame_make_writable(s->last_in) < 0) { - av_frame_free(&in); + if ((ret = av_frame_ref(s->last_in, in)) < 0 || + (ret = av_frame_ref(s->last_out, out)) < 0 || + (ret = av_frame_make_writable(s->last_in)) < 0) { av_frame_free(&out); *outf = NULL; - return AVERROR(ENOMEM); + return ret; } ff_dlog(ctx, "%dx%d rect: (%d;%d) -> (%d,%d) [area:%dx%d]\n", @@ -934,7 +927,6 @@ memcpy(out->data[1], s->palette, AVPALETTE_SIZE); if (s->calc_mean_err) debug_mean_error(s, in, out, inlink->frame_count_out); - av_frame_free(&in); *outf = out; return 0; } @@ -1023,20 +1015,17 @@ if (ret < 0) return ret; if (!master || !second) { - ret = AVERROR_BUG; - goto error; + av_frame_free(&master); + return AVERROR_BUG; } if (!s->palette_loaded) { load_palette(s, second); } ret = apply_palette(inlink, master, &out); + av_frame_free(&master); if (ret < 0) - goto error; + return ret; return ff_filter_frame(ctx->outputs[0], out); - -error: - av_frame_free(&master); - return ret; } #define DEFINE_SET_FRAME(color_search, name, value) \ diff -Nru ffmpeg-4.2.2/libavfilter/vf_phase.c ffmpeg-4.4/libavfilter/vf_phase.c --- ffmpeg-4.2.2/libavfilter/vf_phase.c 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_phase.c 2021-04-08 21:28:40.000000000 +0000 @@ -39,6 +39,29 @@ AUTO_ANALYZE }; +#define DEPTH 8 +#include "phase_template.c" + +#undef DEPTH +#define DEPTH 9 +#include "phase_template.c" + +#undef DEPTH +#define DEPTH 10 +#include "phase_template.c" + +#undef DEPTH +#define DEPTH 12 +#include "phase_template.c" + +#undef DEPTH +#define DEPTH 14 +#include "phase_template.c" + +#undef DEPTH +#define DEPTH 16 +#include "phase_template.c" + typedef struct PhaseContext { const AVClass *class; int mode; ///format); int ret; + switch (desc->comp[0].depth) { + case 8: s->analyze_plane = analyze_plane_8; break; + case 9: s->analyze_plane = analyze_plane_9; break; + case 10: s->analyze_plane = analyze_plane_10; break; + case 12: s->analyze_plane = analyze_plane_12; break; + case 14: s->analyze_plane = analyze_plane_14; break; + case 16: s->analyze_plane = analyze_plane_16; break; + default: av_assert0(0); + }; + if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) return ret; @@ -100,149 +158,6 @@ return 0; } -/* - * This macro interpolates the value of both fields at a point halfway - * between lines and takes the squared difference. In field resolution - * the point is a quarter pixel below a line in one field and a quarter - * pixel above a line in other. - * - * (The result is actually multiplied by 25) - */ -#define DIFF(a, as, b, bs) ((t) = ((*(a) - (b)[bs]) << 2) + (a)[(as) << 1] - (b)[-(bs)], (t) * (t)) - -/* - * Find which field combination has the smallest average squared difference - * between the fields. - */ -static enum PhaseMode analyze_plane(void *ctx, enum PhaseMode mode, AVFrame *old, AVFrame *new) -{ - double bdiff, tdiff, pdiff; - - if (mode == AUTO) { - mode = new->interlaced_frame ? new->top_field_first ? - TOP_FIRST : BOTTOM_FIRST : PROGRESSIVE; - } else if (mode == AUTO_ANALYZE) { - mode = new->interlaced_frame ? new->top_field_first ? - TOP_FIRST_ANALYZE : BOTTOM_FIRST_ANALYZE : FULL_ANALYZE; - } - - if (mode <= BOTTOM_FIRST) { - bdiff = pdiff = tdiff = 65536.0; - } else { - const int ns = new->linesize[0]; - const int os = old->linesize[0]; - const uint8_t *nptr = new->data[0]; - const uint8_t *optr = old->data[0]; - const int h = new->height; - const int w = new->width; - int bdif, tdif, pdif; - double scale; - - int top = 0, t; - const uint8_t *rend, *end = nptr + (h - 2) * ns; - - bdiff = pdiff = tdiff = 0.0; - - nptr += ns; - optr += os; - while (nptr < end) { - pdif = tdif = bdif = 0; - - switch (mode) { - case TOP_FIRST_ANALYZE: - if (top) { - for (rend = nptr + w; nptr < rend; nptr++, optr++) { - pdif += DIFF(nptr, ns, nptr, ns); - tdif += DIFF(nptr, ns, optr, os); - } - } else { - for (rend = nptr + w; nptr < rend; nptr++, optr++) { - pdif += DIFF(nptr, ns, nptr, ns); - tdif += DIFF(optr, os, nptr, ns); - } - } - break; - case BOTTOM_FIRST_ANALYZE: - if (top) { - for (rend = nptr + w; nptr < rend; nptr++, optr++) { - pdif += DIFF(nptr, ns, nptr, ns); - bdif += DIFF(optr, os, nptr, ns); - } - } else { - for (rend = nptr + w; nptr < rend; nptr++, optr++) { - pdif += DIFF(nptr, ns, nptr, ns); - bdif += DIFF(nptr, ns, optr, os); - } - } - break; - case ANALYZE: - if (top) { - for (rend = nptr + w; nptr < rend; nptr++, optr++) { - tdif += DIFF(nptr, ns, optr, os); - bdif += DIFF(optr, os, nptr, ns); - } - } else { - for (rend = nptr + w; nptr < rend; nptr++, optr++) { - bdif += DIFF(nptr, ns, optr, os); - tdif += DIFF(optr, os, nptr, ns); - } - } - break; - case FULL_ANALYZE: - if (top) { - for (rend = nptr + w; nptr < rend; nptr++, optr++) { - pdif += DIFF(nptr, ns, nptr, ns); - tdif += DIFF(nptr, ns, optr, os); - bdif += DIFF(optr, os, nptr, ns); - } - } else { - for (rend = nptr + w; nptr < rend; nptr++, optr++) { - pdif += DIFF(nptr, ns, nptr, ns); - bdif += DIFF(nptr, ns, optr, os); - tdif += DIFF(optr, os, nptr, ns); - } - } - break; - default: - av_assert0(0); - } - - pdiff += (double)pdif; - tdiff += (double)tdif; - bdiff += (double)bdif; - nptr += ns - w; - optr += os - w; - top ^= 1; - } - - scale = 1.0 / (w * (h - 3)) / 25.0; - pdiff *= scale; - tdiff *= scale; - bdiff *= scale; - - if (mode == TOP_FIRST_ANALYZE) { - bdiff = 65536.0; - } else if (mode == BOTTOM_FIRST_ANALYZE) { - tdiff = 65536.0; - } else if (mode == ANALYZE) { - pdiff = 65536.0; - } - - if (bdiff < pdiff && bdiff < tdiff) { - mode = BOTTOM_FIRST; - } else if (tdiff < pdiff && tdiff < bdiff) { - mode = TOP_FIRST; - } else { - mode = PROGRESSIVE; - } - } - - av_log(ctx, AV_LOG_DEBUG, "mode=%c tdiff=%f bdiff=%f pdiff=%f\n", - mode == BOTTOM_FIRST ? 'b' : mode == TOP_FIRST ? 't' : 'p', - tdiff, bdiff, pdiff); - return mode; -} - static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; @@ -272,7 +187,7 @@ s->frame = in; mode = PROGRESSIVE; } else { - mode = analyze_plane(ctx, s->mode, s->frame, in); + mode = s->analyze_plane(ctx, s->mode, s->frame, in); } for (plane = 0; plane < s->nb_planes; plane++) { @@ -330,4 +245,5 @@ .inputs = phase_inputs, .outputs = phase_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_photosensitivity.c ffmpeg-4.4/libavfilter/vf_photosensitivity.c --- ffmpeg-4.2.2/libavfilter/vf_photosensitivity.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_photosensitivity.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2019 Vladimir Panteleev + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" + +#include "formats.h" +#include "internal.h" +#include "video.h" + +#define MAX_FRAMES 240 +#define GRID_SIZE 8 +#define NUM_CHANNELS 3 + +typedef struct PhotosensitivityFrame { + uint8_t grid[GRID_SIZE][GRID_SIZE][4]; +} PhotosensitivityFrame; + +typedef struct PhotosensitivityContext { + const AVClass *class; + + int nb_frames; + int skip; + float threshold_multiplier; + int bypass; + + int badness_threshold; + + /* Circular buffer */ + int history[MAX_FRAMES]; + int history_pos; + + PhotosensitivityFrame last_frame_e; + AVFrame *last_frame_av; +} PhotosensitivityContext; + +#define OFFSET(x) offsetof(PhotosensitivityContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption photosensitivity_options[] = { + { "frames", "set how many frames to use", OFFSET(nb_frames), AV_OPT_TYPE_INT, {.i64=30}, 2, MAX_FRAMES, FLAGS }, + { "f", "set how many frames to use", OFFSET(nb_frames), AV_OPT_TYPE_INT, {.i64=30}, 2, MAX_FRAMES, FLAGS }, + { "threshold", "set detection threshold factor (lower is stricter)", OFFSET(threshold_multiplier), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0.1, FLT_MAX, FLAGS }, + { "t", "set detection threshold factor (lower is stricter)", OFFSET(threshold_multiplier), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0.1, FLT_MAX, FLAGS }, + { "skip", "set pixels to skip when sampling frames", OFFSET(skip), AV_OPT_TYPE_INT, {.i64=1}, 1, 1024, FLAGS }, + { "bypass", "leave frames unchanged", OFFSET(bypass), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(photosensitivity); + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pixel_fmts[] = { + AV_PIX_FMT_RGB24, + AV_PIX_FMT_BGR24, + AV_PIX_FMT_NONE + }; + AVFilterFormats *formats = ff_make_format_list(pixel_fmts); + if (!formats) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, formats); +} + +typedef struct ThreadData_convert_frame +{ + AVFrame *in; + PhotosensitivityFrame *out; + int skip; +} ThreadData_convert_frame; + +#define NUM_CELLS (GRID_SIZE * GRID_SIZE) + +static int convert_frame_partial(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + int cell, gx, gy, x0, x1, y0, y1, x, y, c, area; + int sum[NUM_CHANNELS]; + const uint8_t *p; + + ThreadData_convert_frame *td = arg; + + const int slice_start = (NUM_CELLS * jobnr) / nb_jobs; + const int slice_end = (NUM_CELLS * (jobnr+1)) / nb_jobs; + + int width = td->in->width, height = td->in->height, linesize = td->in->linesize[0], skip = td->skip; + const uint8_t *data = td->in->data[0]; + + for (cell = slice_start; cell < slice_end; cell++) { + gx = cell % GRID_SIZE; + gy = cell / GRID_SIZE; + + x0 = width * gx / GRID_SIZE; + x1 = width * (gx+1) / GRID_SIZE; + y0 = height * gy / GRID_SIZE; + y1 = height * (gy+1) / GRID_SIZE; + + for (c = 0; c < NUM_CHANNELS; c++) { + sum[c] = 0; + } + for (y = y0; y < y1; y += skip) { + p = data + y * linesize + x0 * NUM_CHANNELS; + for (x = x0; x < x1; x += skip) { + //av_log(NULL, AV_LOG_VERBOSE, "%d %d %d : (%d,%d) (%d,%d) -> %d,%d | *%d\n", c, gx, gy, x0, y0, x1, y1, x, y, (int)row); + sum[0] += p[0]; + sum[1] += p[1]; + sum[2] += p[2]; + p += NUM_CHANNELS * skip; + // TODO: variable size + } + } + + area = ((x1 - x0 + skip - 1) / skip) * ((y1 - y0 + skip - 1) / skip); + for (c = 0; c < NUM_CHANNELS; c++) { + if (area) + sum[c] /= area; + td->out->grid[gy][gx][c] = sum[c]; + } + } + return 0; +} + +static void convert_frame(AVFilterContext *ctx, AVFrame *in, PhotosensitivityFrame *out, int skip) +{ + ThreadData_convert_frame td; + td.in = in; + td.out = out; + td.skip = skip; + ctx->internal->execute(ctx, convert_frame_partial, &td, NULL, FFMIN(NUM_CELLS, ff_filter_get_nb_threads(ctx))); +} + +typedef struct ThreadData_blend_frame +{ + AVFrame *target; + AVFrame *source; + uint16_t s_mul; +} ThreadData_blend_frame; + +static int blend_frame_partial(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + int x, y; + uint8_t *t, *s; + + ThreadData_blend_frame *td = arg; + const uint16_t s_mul = td->s_mul; + const uint16_t t_mul = 0x100 - s_mul; + const int slice_start = (td->target->height * jobnr) / nb_jobs; + const int slice_end = (td->target->height * (jobnr+1)) / nb_jobs; + const int linesize = td->target->linesize[0]; + + for (y = slice_start; y < slice_end; y++) { + t = td->target->data[0] + y * td->target->linesize[0]; + s = td->source->data[0] + y * td->source->linesize[0]; + for (x = 0; x < linesize; x++) { + *t = (*t * t_mul + *s * s_mul) >> 8; + t++; s++; + } + } + return 0; +} + +static void blend_frame(AVFilterContext *ctx, AVFrame *target, AVFrame *source, float factor) +{ + ThreadData_blend_frame td; + td.target = target; + td.source = source; + td.s_mul = (uint16_t)(factor * 0x100); + ctx->internal->execute(ctx, blend_frame_partial, &td, NULL, FFMIN(ctx->outputs[0]->h, ff_filter_get_nb_threads(ctx))); +} + +static int get_badness(PhotosensitivityFrame *a, PhotosensitivityFrame *b) +{ + int badness, x, y, c; + badness = 0; + for (c = 0; c < NUM_CHANNELS; c++) { + for (y = 0; y < GRID_SIZE; y++) { + for (x = 0; x < GRID_SIZE; x++) { + badness += abs((int)a->grid[y][x][c] - (int)b->grid[y][x][c]); + //av_log(NULL, AV_LOG_VERBOSE, "%d - %d -> %d \n", a->grid[y][x], b->grid[y][x], badness); + //av_log(NULL, AV_LOG_VERBOSE, "%d -> %d \n", abs((int)a->grid[y][x] - (int)b->grid[y][x]), badness); + } + } + } + return badness; +} + +static int config_input(AVFilterLink *inlink) +{ + /* const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); */ + AVFilterContext *ctx = inlink->dst; + PhotosensitivityContext *s = ctx->priv; + + s->badness_threshold = (int)(GRID_SIZE * GRID_SIZE * 4 * 256 * s->nb_frames * s->threshold_multiplier / 128); + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + int this_badness, current_badness, fixed_badness, new_badness, i, res; + PhotosensitivityFrame ef; + AVFrame *src, *out; + int free_in = 0; + float factor; + AVDictionary **metadata; + + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + PhotosensitivityContext *s = ctx->priv; + + /* weighted moving average */ + current_badness = 0; + for (i = 1; i < s->nb_frames; i++) + current_badness += i * s->history[(s->history_pos + i) % s->nb_frames]; + current_badness /= s->nb_frames; + + convert_frame(ctx, in, &ef, s->skip); + this_badness = get_badness(&ef, &s->last_frame_e); + new_badness = current_badness + this_badness; + av_log(s, AV_LOG_VERBOSE, "badness: %6d -> %6d / %6d (%3d%% - %s)\n", + current_badness, new_badness, s->badness_threshold, + 100 * new_badness / s->badness_threshold, new_badness < s->badness_threshold ? "OK" : "EXCEEDED"); + + fixed_badness = new_badness; + if (new_badness < s->badness_threshold || !s->last_frame_av || s->bypass) { + factor = 1; /* for metadata */ + av_frame_free(&s->last_frame_av); + s->last_frame_av = src = in; + s->last_frame_e = ef; + s->history[s->history_pos] = this_badness; + } else { + factor = (float)(s->badness_threshold - current_badness) / (new_badness - current_badness); + if (factor <= 0) { + /* just duplicate the frame */ + s->history[s->history_pos] = 0; /* frame was duplicated, thus, delta is zero */ + } else { + res = av_frame_make_writable(s->last_frame_av); + if (res) { + av_frame_free(&in); + return res; + } + blend_frame(ctx, s->last_frame_av, in, factor); + + convert_frame(ctx, s->last_frame_av, &ef, s->skip); + this_badness = get_badness(&ef, &s->last_frame_e); + fixed_badness = current_badness + this_badness; + av_log(s, AV_LOG_VERBOSE, " fixed: %6d -> %6d / %6d (%3d%%) factor=%5.3f\n", + current_badness, fixed_badness, s->badness_threshold, + 100 * new_badness / s->badness_threshold, factor); + s->last_frame_e = ef; + s->history[s->history_pos] = this_badness; + } + src = s->last_frame_av; + free_in = 1; + } + s->history_pos = (s->history_pos + 1) % s->nb_frames; + + out = ff_get_video_buffer(outlink, in->width, in->height); + if (!out) { + if (free_in == 1) + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + metadata = &out->metadata; + if (metadata) { + char value[128]; + + snprintf(value, sizeof(value), "%f", (float)new_badness / s->badness_threshold); + av_dict_set(metadata, "lavfi.photosensitivity.badness", value, 0); + + snprintf(value, sizeof(value), "%f", (float)fixed_badness / s->badness_threshold); + av_dict_set(metadata, "lavfi.photosensitivity.fixed-badness", value, 0); + + snprintf(value, sizeof(value), "%f", (float)this_badness / s->badness_threshold); + av_dict_set(metadata, "lavfi.photosensitivity.frame-badness", value, 0); + + snprintf(value, sizeof(value), "%f", factor); + av_dict_set(metadata, "lavfi.photosensitivity.factor", value, 0); + } + av_frame_copy(out, src); + if (free_in == 1) + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + PhotosensitivityContext *s = ctx->priv; + + av_frame_free(&s->last_frame_av); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_photosensitivity = { + .name = "photosensitivity", + .description = NULL_IF_CONFIG_SMALL("Filter out photosensitive epilepsy seizure-inducing flashes."), + .priv_size = sizeof(PhotosensitivityContext), + .priv_class = &photosensitivity_class, + .uninit = uninit, + .query_formats = query_formats, + .inputs = inputs, + .outputs = outputs, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_pp7.c ffmpeg-4.4/libavfilter/vf_pp7.c --- ffmpeg-4.2.2/libavfilter/vf_pp7.c 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_pp7.c 2021-04-08 21:28:40.000000000 +0000 @@ -29,9 +29,11 @@ #include "libavutil/avassert.h" #include "libavutil/imgutils.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "internal.h" +#include "qp_table.h" #include "vf_pp7.h" enum mode { @@ -322,10 +324,15 @@ AVFrame *out = in; int qp_stride = 0; - uint8_t *qp_table = NULL; + int8_t *qp_table = NULL; - if (!pp7->qp) - qp_table = av_frame_get_qp_table(in, &qp_stride, &pp7->qscale_type); + if (!pp7->qp) { + int ret = ff_qp_table_extract(in, &qp_table, &qp_stride, NULL, &pp7->qscale_type); + if (ret < 0) { + av_frame_free(&in); + return ret; + } + } if (!ctx->is_disabled) { const int cw = AV_CEIL_RSHIFT(inlink->w, pp7->hsub); @@ -340,6 +347,7 @@ out = ff_get_video_buffer(outlink, aligned_w, aligned_h); if (!out) { av_frame_free(&in); + av_freep(&qp_table); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); @@ -366,6 +374,7 @@ inlink->w, inlink->h); av_frame_free(&in); } + av_freep(&qp_table); return ff_filter_frame(outlink, out); } diff -Nru ffmpeg-4.2.2/libavfilter/vf_pp.c ffmpeg-4.4/libavfilter/vf_pp.c --- ffmpeg-4.2.2/libavfilter/vf_pp.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_pp.c 2021-04-08 21:28:40.000000000 +0000 @@ -26,7 +26,9 @@ #include "libavutil/avassert.h" #include "libavutil/opt.h" + #include "internal.h" +#include "qp_table.h" #include "libpostproc/postprocess.h" @@ -126,8 +128,9 @@ const int aligned_w = FFALIGN(outlink->w, 8); const int aligned_h = FFALIGN(outlink->h, 8); AVFrame *outbuf; - int qstride, qp_type; - int8_t *qp_table ; + int qstride = 0; + int8_t *qp_table = NULL; + int ret; outbuf = ff_get_video_buffer(outlink, aligned_w, aligned_h); if (!outbuf) { @@ -137,7 +140,13 @@ av_frame_copy_props(outbuf, inbuf); outbuf->width = inbuf->width; outbuf->height = inbuf->height; - qp_table = av_frame_get_qp_table(inbuf, &qstride, &qp_type); + + ret = ff_qp_table_extract(inbuf, &qp_table, &qstride, NULL, NULL); + if (ret < 0) { + av_frame_free(&inbuf); + av_frame_free(&outbuf); + return ret; + } pp_postprocess((const uint8_t **)inbuf->data, inbuf->linesize, outbuf->data, outbuf->linesize, @@ -146,9 +155,10 @@ qstride, pp->modes[pp->mode_id], pp->pp_ctx, - outbuf->pict_type | (qp_type ? PP_PICT_TYPE_QP2 : 0)); + outbuf->pict_type | (qp_table ? PP_PICT_TYPE_QP2 : 0)); av_frame_free(&inbuf); + av_freep(&qp_table); return ff_filter_frame(outlink, outbuf); } diff -Nru ffmpeg-4.2.2/libavfilter/vf_premultiply.c ffmpeg-4.4/libavfilter/vf_premultiply.c --- ffmpeg-4.2.2/libavfilter/vf_premultiply.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_premultiply.c 2021-04-08 21:28:40.000000000 +0000 @@ -73,16 +73,16 @@ AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, - AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRPF32, 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 const enum AVPixelFormat alpha_pix_fmts[] = { AV_PIX_FMT_YUVA444P, - AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRAP, - AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_NONE }; @@ -186,7 +186,7 @@ for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { - dst[x] = ((((msrc[x] - half) * (((asrc[x] >> 1) & 1) + asrc[x]))) >> shift) + half; + dst[x] = ((((msrc[x] - half) * (int64_t)(((asrc[x] >> 1) & 1) + asrc[x]))) >> shift) + half; } dst += dlinesize / 2; @@ -209,7 +209,7 @@ for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { - dst[x] = ((((msrc[x] - offset) * (((asrc[x] >> 1) & 1) + asrc[x])) + half) >> shift) + offset; + dst[x] = ((((msrc[x] - offset) * (int64_t)(((asrc[x] >> 1) & 1) + asrc[x])) + half) >> shift) + offset; } dst += dlinesize / 2; @@ -218,6 +218,54 @@ } } +static void premultiplyf32(const uint8_t *mmsrc, const uint8_t *aasrc, + uint8_t *ddst, + ptrdiff_t mlinesize, ptrdiff_t alinesize, + ptrdiff_t dlinesize, + int w, int h, + int half, int shift, int offset) +{ + const float *msrc = (const float *)mmsrc; + const float *asrc = (const float *)aasrc; + float *dst = (float *)ddst; + int x, y; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + dst[x] = msrc[x] * asrc[x]; + } + + dst += dlinesize / 4; + msrc += mlinesize / 4; + asrc += alinesize / 4; + } +} + +static void premultiplyf32offset(const uint8_t *mmsrc, const uint8_t *aasrc, + uint8_t *ddst, + ptrdiff_t mlinesize, ptrdiff_t alinesize, + ptrdiff_t dlinesize, + int w, int h, + int half, int shift, int offset) +{ + const float *msrc = (const float *)mmsrc; + const float *asrc = (const float *)aasrc; + float *dst = (float *)ddst; + int x, y; + + float offsetf = offset / 65535.0f; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + dst[x] = ((msrc[x] - offsetf) * asrc[x]) + offsetf; + } + + dst += dlinesize / 4; + msrc += mlinesize / 4; + asrc += alinesize / 4; + } +} + static void unpremultiply8(const uint8_t *msrc, const uint8_t *asrc, uint8_t *dst, ptrdiff_t mlinesize, ptrdiff_t alinesize, @@ -365,6 +413,62 @@ } } +static void unpremultiplyf32(const uint8_t *mmsrc, const uint8_t *aasrc, + uint8_t *ddst, + ptrdiff_t mlinesize, ptrdiff_t alinesize, + ptrdiff_t dlinesize, + int w, int h, + int half, int max, int offset) +{ + const float *msrc = (const float *)mmsrc; + const float *asrc = (const float *)aasrc; + + float *dst = (float *)ddst; + int x, y; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + if (asrc[x] > 0.0f) + dst[x] = msrc[x] / asrc[x]; + else + dst[x] = msrc[x]; + } + + dst += dlinesize / 4; + msrc += mlinesize / 4; + asrc += alinesize / 4; + } +} + +static void unpremultiplyf32offset(const uint8_t *mmsrc, const uint8_t *aasrc, + uint8_t *ddst, + ptrdiff_t mlinesize, ptrdiff_t alinesize, + ptrdiff_t dlinesize, + int w, int h, + int half, int max, int offset) +{ + const float *msrc = (const float *)mmsrc; + const float *asrc = (const float *)aasrc; + + float *dst = (float *)ddst; + int x, y; + + float offsetf = offset / 65535.0f; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + if (asrc[x] > 0.0f) + dst[x] = (msrc[x] - offsetf) / asrc[x] + offsetf; + else + dst[x] = msrc[x]; + } + + dst += dlinesize / 4; + msrc += mlinesize / 4; + asrc += alinesize / 4; + } +} + static int premultiply_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { PreMultiplyContext *s = ctx->priv; @@ -442,6 +546,7 @@ case AV_PIX_FMT_YUV444P10: case AV_PIX_FMT_YUVA444P10: case AV_PIX_FMT_YUV444P12: + case AV_PIX_FMT_YUVA444P12: case AV_PIX_FMT_YUV444P14: case AV_PIX_FMT_YUV444P16: case AV_PIX_FMT_YUVA444P16: @@ -458,6 +563,10 @@ case AV_PIX_FMT_GBRAP16: s->premultiply[0] = s->premultiply[1] = s->premultiply[2] = limited ? unpremultiply16offset : unpremultiply16; break; + case AV_PIX_FMT_GBRPF32: + case AV_PIX_FMT_GBRAPF32: + s->premultiply[0] = s->premultiply[1] = s->premultiply[2] = limited ? unpremultiplyf32offset : unpremultiplyf32; + break; case AV_PIX_FMT_GRAY8: s->premultiply[0] = limited ? unpremultiply8offset : unpremultiply8; break; @@ -489,6 +598,7 @@ case AV_PIX_FMT_YUV444P10: case AV_PIX_FMT_YUVA444P10: case AV_PIX_FMT_YUV444P12: + case AV_PIX_FMT_YUVA444P12: case AV_PIX_FMT_YUV444P14: case AV_PIX_FMT_YUV444P16: case AV_PIX_FMT_YUVA444P16: @@ -505,6 +615,10 @@ case AV_PIX_FMT_GBRAP16: s->premultiply[0] = s->premultiply[1] = s->premultiply[2] = limited ? premultiply16offset : premultiply16; break; + case AV_PIX_FMT_GBRPF32: + case AV_PIX_FMT_GBRAPF32: + s->premultiply[0] = s->premultiply[1] = s->premultiply[2] = limited ? premultiplyf32offset: premultiplyf32; + break; case AV_PIX_FMT_GRAY8: s->premultiply[0] = limited ? premultiply8offset : premultiply8; break; @@ -567,7 +681,7 @@ s->width[1] = s->width[2] = AV_CEIL_RSHIFT(inlink->w, hsub); s->width[0] = s->width[3] = inlink->w; - s->depth = desc->comp[0].depth; + s->depth = desc->flags & AV_PIX_FMT_FLAG_FLOAT ? 16 : desc->comp[0].depth; s->max = (1 << s->depth) - 1; s->half = (1 << s->depth) / 2; s->offset = 16 << (s->depth - 8); @@ -639,6 +753,8 @@ int ret, status; int64_t pts; + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); + if ((ret = ff_inlink_consume_frame(ctx->inputs[0], &frame)) > 0) { ret = filter_frame(ctx, &out, frame, frame); av_frame_free(&frame); @@ -671,27 +787,19 @@ s->inverse = 1; pad.type = AVMEDIA_TYPE_VIDEO; - pad.name = av_strdup("main"); + pad.name = "main"; pad.config_props = config_input; - if (!pad.name) - return AVERROR(ENOMEM); - if ((ret = ff_insert_inpad(ctx, 0, &pad)) < 0) { - av_freep(&pad.name); + if ((ret = ff_insert_inpad(ctx, 0, &pad)) < 0) return ret; - } if (!s->inplace) { pad.type = AVMEDIA_TYPE_VIDEO; - pad.name = av_strdup("alpha"); + pad.name = "alpha"; pad.config_props = NULL; - if (!pad.name) - return AVERROR(ENOMEM); - if ((ret = ff_insert_inpad(ctx, 1, &pad)) < 0) { - av_freep(&pad.name); + if ((ret = ff_insert_inpad(ctx, 1, &pad)) < 0) return ret; - } } return 0; diff -Nru ffmpeg-4.2.2/libavfilter/vf_procamp_vaapi.c ffmpeg-4.4/libavfilter/vf_procamp_vaapi.c --- ffmpeg-4.2.2/libavfilter/vf_procamp_vaapi.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_procamp_vaapi.c 2020-07-11 10:39:30.000000000 +0000 @@ -150,7 +150,7 @@ err = av_frame_copy_props(output_frame, input_frame); if (err < 0) - return err; + goto fail; err = ff_vaapi_vpp_init_params(avctx, ¶ms, input_frame, output_frame); diff -Nru ffmpeg-4.2.2/libavfilter/vf_pseudocolor.c ffmpeg-4.4/libavfilter/vf_pseudocolor.c --- ffmpeg-4.2.2/libavfilter/vf_pseudocolor.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_pseudocolor.c 2021-04-08 21:28:40.000000000 +0000 @@ -59,8 +59,112 @@ VAR_VARS_NB }; +enum Curves { + MAGMA, + INFERNO, + PLASMA, + VIRIDIS, + TURBO, + CIVIDIS, + NB_CURVES, +}; + +enum Presets { + PRESET_MAGMA, + PRESET_INFERNO, + PRESET_PLASMA, + PRESET_VIRIDIS, + PRESET_TURBO, + PRESET_CIVIDIS, + PRESET_RANGE1, + PRESET_RANGE2, + PRESET_SHADOWS, + PRESET_HIGHLIGHTS, + NB_PRESETS, +}; + +typedef struct Curve { + double coef[3][8]; +} Curve; + +typedef struct Fill { + float fill[4]; +} Fill; + +typedef struct Range { + int start, end; +} Range; + +typedef struct Preset { + int nb_segments; + const Range *ranges; + const Curve *curves; + const Fill *fills; +} Preset; + +static const Range full_range = {0, 256}; +static const Range spec1_range[] = {{0, 16}, {16, 236}, {236, 256}}; +static const Range spec2_range[] = {{0, 16}, {16, 22}, {22, 226}, {226, 236}, {236, 256}}; +static const Range shadows_range[] = {{0, 32}, {32, 256}}; +static const Range highlights_range[] = {{0, 214}, {214, 224}, {224, 256}}; + +static const Fill spec1_fills[] = {{{0.5f, 0.f, .5f, 1.f}}, {{-1.f, -1.f, -1.f, 1.f}}, {{1.f, 0.f, 0.f, 1.f}}}; +static const Fill spec2_fills[] = {{{0.5f, 0.f, .5f, 1.f}}, {{0.f, 1.f, 1.f, 1.f}}, {{-1.f, -1.f, -1.f, 1.f}}, {{1.f, 1.f, 0.f, 1.f}}, {{1.f, 0.f, 0.f, 1.f}}}; +static const Fill shadows_fills[] = {{{0.8f, 0.4f, .8f, 1.f}}, {{-1.f, -1.f, -1.f, 1.f}}}; +static const Fill highlights_fills[] = {{{-1.f, -1.f, -1.f, 1.f}}, {{1.f, 0.3f, 0.6f, 1.f}}, {{1.f, 0.2f, .5f, 1.f}}}; + +static const Curve curves[] = +{ + [MAGMA] = {{ + {-7.5631093e-16, 7.4289183e-13, -2.8525484e-10, 5.4446085e-08, -5.5596238e-06, 3.0569325e-04, -2.3137421e-03, 1.2152095e-02 }, + { 1.3217636e-15, -1.2214648e-12, 4.4319712e-10, -8.0197993e-08, 7.6598370e-06, -3.6523704e-04, 8.4836670e-03, -2.5536888e-02 }, + {-1.1446568e-15, 1.0013446e-12, -3.5651575e-10, 6.6775016e-08, -6.7120346e-06, 2.7346619e-04, 4.7969657e-03, 1.1971441e-02 }, + }}, + [INFERNO] = {{ + {-3.9848859e-18, 9.4821649e-14, -6.7371977e-11, 1.8469937e-08, -2.5359307e-06, 1.7959053e-04, 3.9782564e-04, 2.8845935e-04 }, + { 6.8408539e-16, -6.5499979e-13, 2.4562526e-10, -4.5989298e-08, 4.5723324e-06, -2.2111913e-04, 5.2023164e-03, -1.1226064e-02 }, + {-2.9921470e-15, 2.5864165e-12, -8.7403799e-10, 1.4713388e-07, -1.2701505e-05, 4.5159935e-04, 3.1087989e-03, 1.9122831e-02 }, + }}, + [PLASMA] = {{ + { 3.6196089e-16, -3.3623041e-13, 1.2324010e-10, -2.2769060e-08, 2.2297792e-06, -1.2567829e-04, 9.9791629e-03, 5.7247918e-02 }, + { 5.0262888e-16, -5.3193896e-13, 2.2451715e-10, -4.7529623e-08, 5.1374873e-06, -2.3260136e-04, 3.1502825e-03, 1.5362491e-02 }, + {-1.7782261e-16, 2.2487839e-13, -1.0610236e-10, 2.4112644e-08, -2.6331623e-06, 8.9499751e-05, 2.1386328e-03, 5.3824268e-01 }, + }}, + [VIRIDIS] = {{ + { 9.4850045e-16, -8.6629383e-13, 3.0310944e-10, -5.1340396e-08, 4.6024275e-06, -2.2744239e-04, 4.5559993e-03, 2.5662350e-01 }, + { 9.6461041e-17, -6.9209477e-14, 1.7625397e-11, -2.0229773e-09, 1.4900110e-07, -1.9315187e-05, 5.8967339e-03, 3.9544827e-03 }, + { 5.1785449e-16, -3.6663004e-13, 1.0249990e-10, -1.5431998e-08, 1.5007941e-06, -1.2001502e-04, 7.6951526e-03, 3.2292815e-01 }, + }}, + [TURBO] = {{ + {-4.3683890e-15, 3.7020347e-12, -1.1712592e-09, 1.6401790e-07, -8.6842919e-06, -1.8542465e-06, 8.4485325e-03, 1.6267077e-01 }, + {-4.0011069e-16, 2.7861423e-13, -6.3388921e-11, 5.8872238e-09, -5.4466522e-07, 1.8037114e-05, 1.0599869e-02, 7.6914696e-02 }, + {-2.8242609e-15, 2.9234108e-12, -1.1726546e-09, 2.2552115e-07, -2.0059387e-05, 5.0595552e-04, 1.7714932e-02, 2.7271836e-01 }, + }}, + [CIVIDIS] = {{ + {-9.5484131e-16, 9.6988184e-13, -4.0058766e-10, 8.5743924e-08, -9.9644797e-06, 5.9197908e-04, -1.0361579e-02, 3.3164429e-02 }, + { 1.2731941e-17, -9.4238449e-15, 2.2808841e-12, -1.1548296e-10, -2.3888913e-08, 3.8986680e-06, 2.5879330e-03, 1.2769733e-01 }, + { 4.6004608e-16, -5.0686849e-13, 2.2753449e-10, -5.3074099e-08, 6.7196096e-06, -4.4120020e-04, 1.3435551e-02, 2.8293355e-01 }, + }}, +}; + +static const Preset presets[] = +{ + [PRESET_MAGMA] = { 1, &full_range, &curves[MAGMA], NULL }, + [PRESET_INFERNO] = { 1, &full_range, &curves[INFERNO], NULL }, + [PRESET_PLASMA] = { 1, &full_range, &curves[PLASMA], NULL }, + [PRESET_VIRIDIS] = { 1, &full_range, &curves[VIRIDIS], NULL }, + [PRESET_TURBO] = { 1, &full_range, &curves[TURBO], NULL }, + [PRESET_CIVIDIS] = { 1, &full_range, &curves[CIVIDIS], NULL }, + [PRESET_RANGE1] = { 3, spec1_range, NULL, spec1_fills }, + [PRESET_RANGE2] = { 5, spec2_range, NULL, spec2_fills }, + [PRESET_SHADOWS] = { 2, shadows_range, NULL, shadows_fills }, + [PRESET_HIGHLIGHTS] = { 3, highlights_range, NULL, highlights_fills }, +}; + typedef struct PseudoColorContext { const AVClass *class; + int preset; + float opacity; int max; int index; int nb_planes; @@ -78,18 +182,34 @@ ptrdiff_t ilinesize, ptrdiff_t slinesize, ptrdiff_t dlinesize, - float *lut); + float *lut, + float opacity); } PseudoColorContext; #define OFFSET(x) offsetof(PseudoColorContext, x) -#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption pseudocolor_options[] = { { "c0", "set component #0 expression", OFFSET(comp_expr_str[0]), AV_OPT_TYPE_STRING, {.str="val"}, .flags = FLAGS }, { "c1", "set component #1 expression", OFFSET(comp_expr_str[1]), AV_OPT_TYPE_STRING, {.str="val"}, .flags = FLAGS }, { "c2", "set component #2 expression", OFFSET(comp_expr_str[2]), AV_OPT_TYPE_STRING, {.str="val"}, .flags = FLAGS }, { "c3", "set component #3 expression", OFFSET(comp_expr_str[3]), AV_OPT_TYPE_STRING, {.str="val"}, .flags = FLAGS }, + { "index", "set component as base", OFFSET(index), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, .flags = FLAGS }, { "i", "set component as base", OFFSET(index), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, .flags = FLAGS }, + { "preset", "set preset", OFFSET(preset), AV_OPT_TYPE_INT, {.i64=-1},-1, NB_PRESETS-1, .flags = FLAGS, "preset" }, + { "p", "set preset", OFFSET(preset), AV_OPT_TYPE_INT, {.i64=-1},-1, NB_PRESETS-1, .flags = FLAGS, "preset" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=-1}, .flags = FLAGS, "preset" }, + { "magma", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_MAGMA}, .flags = FLAGS, "preset" }, + { "inferno", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_INFERNO}, .flags = FLAGS, "preset" }, + { "plasma", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_PLASMA}, .flags = FLAGS, "preset" }, + { "viridis", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_VIRIDIS}, .flags = FLAGS, "preset" }, + { "turbo", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_TURBO}, .flags = FLAGS, "preset" }, + { "cividis", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_CIVIDIS}, .flags = FLAGS, "preset" }, + { "range1", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_RANGE1}, .flags = FLAGS, "preset" }, + { "range2", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_RANGE2}, .flags = FLAGS, "preset" }, + { "shadows", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_SHADOWS}, .flags = FLAGS, "preset" }, + { "highlights", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_HIGHLIGHTS},.flags=FLAGS, "preset" }, + { "opacity", "set pseudocolor opacity",OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, .flags = FLAGS }, { NULL } }; @@ -130,6 +250,18 @@ return ff_set_common_formats(ctx, fmts_list); } +static inline float lerpf(float v0, float v1, float f) +{ + return v0 + (v1 - v0) * f; +} + +#define PCLIP(v, max, dst, src, x) \ + if (v >= 0 && v <= max) { \ + dst[x] = lerpf(src[x], v, opacity);\ + } else { \ + dst[x] = src[x]; \ + } + static void pseudocolor_filter(int max, int width, int height, const uint8_t *index, const uint8_t *src, @@ -137,7 +269,8 @@ ptrdiff_t ilinesize, ptrdiff_t slinesize, ptrdiff_t dlinesize, - float *lut) + float *lut, + float opacity) { int x, y; @@ -145,11 +278,7 @@ for (x = 0; x < width; x++) { int v = lut[index[x]]; - if (v >= 0 && v <= max) { - dst[x] = v; - } else { - dst[x] = src[x]; - } + PCLIP(v, max, dst, src, x); } index += ilinesize; src += slinesize; @@ -164,7 +293,8 @@ ptrdiff_t ilinesize, ptrdiff_t slinesize, ptrdiff_t dlinesize, - float *lut) + float *lut, + float opacity) { int x, y; @@ -172,11 +302,7 @@ for (x = 0; x < width; x++) { int v = lut[index[(y << 1) * ilinesize + (x << 1)]]; - if (v >= 0 && v <= max) { - dst[x] = v; - } else { - dst[x] = src[x]; - } + PCLIP(v, max, dst, src, x); } src += slinesize; dst += dlinesize; @@ -190,7 +316,8 @@ ptrdiff_t ilinesize, ptrdiff_t slinesize, ptrdiff_t dlinesize, - float *lut) + float *lut, + float opacity) { int x, y; @@ -198,11 +325,7 @@ for (x = 0; x < width; x++) { int v = lut[index[(y >> 1) * ilinesize + (x >> 1)]]; - if (v >= 0 && v <= max) { - dst[x] = v; - } else { - dst[x] = src[x]; - } + PCLIP(v, max, dst, src, x); } src += slinesize; dst += dlinesize; @@ -216,7 +339,8 @@ ptrdiff_t ilinesize, ptrdiff_t slinesize, ptrdiff_t dlinesize, - float *lut) + float *lut, + float opacity) { int x, y; @@ -224,11 +348,7 @@ for (x = 0; x < width; x++) { int v = lut[index[x << 1]]; - if (v >= 0 && v <= max) { - dst[x] = v; - } else { - dst[x] = src[x]; - } + PCLIP(v, max, dst, src, x); } index += ilinesize; src += slinesize; @@ -243,7 +363,8 @@ ptrdiff_t ilinesize, ptrdiff_t slinesize, ptrdiff_t dlinesize, - float *lut) + float *lut, + float opacity) { int x, y; @@ -251,11 +372,7 @@ for (x = 0; x < width; x++) { int v = lut[index[x >> 1]]; - if (v >= 0 && v <= max) { - dst[x] = v; - } else { - dst[x] = src[x]; - } + PCLIP(v, max, dst, src, x); } index += ilinesize; src += slinesize; @@ -270,7 +387,8 @@ ptrdiff_t ilinesize, ptrdiff_t slinesize, ptrdiff_t dlinesize, - float *lut) + float *lut, + float opacity) { const uint16_t *index = (const uint16_t *)iindex; const uint16_t *src = (const uint16_t *)ssrc; @@ -281,11 +399,7 @@ for (x = 0; x < width; x++) { int v = lut[index[x]]; - if (v >= 0 && v <= max) { - dst[x] = v; - } else { - dst[x] = src[x]; - } + PCLIP(v, max, dst, src, x); } index += ilinesize / 2; src += slinesize / 2; @@ -300,7 +414,8 @@ ptrdiff_t ilinesize, ptrdiff_t slinesize, ptrdiff_t dlinesize, - float *lut) + float *lut, + float opacity) { const uint16_t *index = (const uint16_t *)iindex; const uint16_t *src = (const uint16_t *)ssrc; @@ -311,11 +426,7 @@ for (x = 0; x < width; x++) { int v = lut[index[x << 1]]; - if (v >= 0 && v <= max) { - dst[x] = v; - } else { - dst[x] = src[x]; - } + PCLIP(v, max, dst, src, x); } index += ilinesize / 2; src += slinesize / 2; @@ -330,7 +441,8 @@ ptrdiff_t ilinesize, ptrdiff_t slinesize, ptrdiff_t dlinesize, - float *lut) + float *lut, + float opacity) { const uint16_t *index = (const uint16_t *)iindex; const uint16_t *src = (const uint16_t *)ssrc; @@ -341,11 +453,7 @@ for (x = 0; x < width; x++) { int v = lut[index[x >> 1]]; - if (v >= 0 && v <= max) { - dst[x] = v; - } else { - dst[x] = src[x]; - } + PCLIP(v, max, dst, src, x); } index += ilinesize / 2; src += slinesize / 2; @@ -360,7 +468,8 @@ ptrdiff_t ilinesize, ptrdiff_t slinesize, ptrdiff_t dlinesize, - float *lut) + float *lut, + float opacity) { const uint16_t *index = (const uint16_t *)iindex; const uint16_t *src = (const uint16_t *)ssrc; @@ -375,11 +484,7 @@ for (x = 0; x < width; x++) { int v = lut[index[(y << 1) * ilinesize + (x << 1)]]; - if (v >= 0 && v <= max) { - dst[x] = v; - } else { - dst[x] = src[x]; - } + PCLIP(v, max, dst, src, x); } src += slinesize; dst += dlinesize; @@ -393,7 +498,8 @@ ptrdiff_t ilinesize, ptrdiff_t slinesize, ptrdiff_t dlinesize, - float *lut) + float *lut, + float opacity) { const uint16_t *index = (const uint16_t *)iindex; const uint16_t *src = (const uint16_t *)ssrc; @@ -408,25 +514,46 @@ for (x = 0; x < width; x++) { int v = lut[index[(y >> 1) * ilinesize + (x >> 1)]]; - if (v >= 0 && v <= max) { - dst[x] = v; - } else { - dst[x] = src[x]; - } + PCLIP(v, max, dst, src, x); } src += slinesize; dst += dlinesize; } } +#define RGB_TO_Y_BT709(r, g, b) \ +((0.21260*219.0/255.0) * (r) + (0.71520*219.0/255.0) * (g) + \ + (0.07220*219.0/255.0) * (b)) + +#define RGB_TO_U_BT709(r1, g1, b1, max) \ +(-(0.11457*224.0/255.0) * r1 - (0.38543*224.0/255.0) * g1 + \ + (0.50000*224.0/255.0) * b1 + max * 0.5) + +#define RGB_TO_V_BT709(r1, g1, b1, max) \ +((0.50000*224.0/255.0) * r1 - (0.45415*224.0/255.0) * g1 - \ + (0.04585*224.0/255.0) * b1 + max * 0.5) + +static double poly_eval(const double *const poly, double x) +{ + double res = 0.; + + for (int i = 0; i < 8; i++) { + res += pow(x, i) * poly[7-i]; + } + + return av_clipd(res, 0., 1.); +} + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; PseudoColorContext *s = ctx->priv; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - int depth, ret, hsub, vsub, color; + int depth, ret, hsub, vsub, color, factor, rgb; + rgb = desc->flags & AV_PIX_FMT_FLAG_RGB; depth = desc->comp[0].depth; + factor = 1 << (depth - 8); s->max = (1 << depth) - 1; s->nb_planes = av_pix_fmt_count_planes(inlink->format); @@ -457,7 +584,7 @@ s->var_values[VAR_VMAX] = 240 * (1 << (depth - 8)); s->var_values[VAR_AMAX] = s->max; - for (color = 0; color < s->nb_planes; color++) { + for (color = 0; color < s->nb_planes && s->preset < 0; color++) { double res; int val; @@ -488,6 +615,77 @@ } } + if (s->preset >= 0) { + int nb_segments = presets[s->preset].nb_segments; + + for (int seg = 0; seg < nb_segments; seg++) { + int start = presets[s->preset].ranges[seg].start; + int end = presets[s->preset].ranges[seg].end; + + for (int i = start; i < end; i++) { + if (!presets[s->preset].curves) { + const Fill fill = presets[s->preset].fills[seg]; + + for (int j = 0; j < factor; j++) { + double r, g, b, a; + + g = fill.fill[1]; + b = fill.fill[2]; + r = fill.fill[0]; + a = fill.fill[3]; + + if (g >= 0.f && b >= 0.f && r >= 0.f) { + g *= s->max; + b *= s->max; + r *= s->max; + + if (!rgb) { + double y = RGB_TO_Y_BT709(r, g, b); + double u = RGB_TO_U_BT709(r, g, b, s->max); + double v = RGB_TO_V_BT709(r, g, b, s->max); + + r = v; + g = y; + b = u; + } + } + + s->lut[0][i*factor+j] = g; + s->lut[1][i*factor+j] = b; + s->lut[2][i*factor+j] = r; + s->lut[3][i*factor+j] = a * s->max; + } + } else { + const Curve curve = presets[s->preset].curves[seg]; + + for (int j = 0; j < factor; j++) { + const double lf = j / (double)factor; + double r, g, b; + + g = poly_eval(curve.coef[1], i + lf) * s->max; + b = poly_eval(curve.coef[2], i + lf) * s->max; + r = poly_eval(curve.coef[0], i + lf) * s->max; + + if (!rgb) { + double y = RGB_TO_Y_BT709(r, g, b); + double u = RGB_TO_U_BT709(r, g, b, s->max); + double v = RGB_TO_V_BT709(r, g, b, s->max); + + r = v; + g = y; + b = u; + } + + s->lut[0][i*factor+j] = g; + s->lut[1][i*factor+j] = b; + s->lut[2][i*factor+j] = r; + s->lut[3][i*factor+j] = 1.f * s->max; + } + } + } + } + } + switch (inlink->format) { case AV_PIX_FMT_YUV444P: case AV_PIX_FMT_YUVA444P: @@ -596,13 +794,43 @@ return 0; } +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + PseudoColorContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + + for (int plane = 0; plane < s->nb_planes; plane++) { + const int slice_start = (s->height[plane] * jobnr) / nb_jobs; + const int slice_end = (s->height[plane] * (jobnr+1)) / nb_jobs; + const int islice_start = (s->height[s->index] * jobnr) / nb_jobs; + ptrdiff_t ilinesize = in->linesize[s->index]; + ptrdiff_t slinesize = in->linesize[plane]; + ptrdiff_t dlinesize = out->linesize[plane]; + const uint8_t *index = in->data[s->index] + islice_start * ilinesize; + const uint8_t *src = in->data[plane] + slice_start * slinesize; + uint8_t *dst = out->data[plane] + slice_start * dlinesize; + + s->filter[plane](s->max, s->width[plane], slice_end - slice_start, + index, src, dst, ilinesize, slinesize, + dlinesize, s->lut[plane], s->opacity); + } + + return 0; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; PseudoColorContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + ThreadData td; AVFrame *out; - int plane; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { @@ -611,23 +839,24 @@ } av_frame_copy_props(out, in); - for (plane = 0; plane < s->nb_planes; plane++) { - const uint8_t *index = in->data[s->index]; - const uint8_t *src = in->data[plane]; - uint8_t *dst = out->data[plane]; - ptrdiff_t ilinesize = in->linesize[s->index]; - ptrdiff_t slinesize = in->linesize[plane]; - ptrdiff_t dlinesize = out->linesize[plane]; - - s->filter[plane](s->max, s->width[plane], s->height[plane], - index, src, dst, ilinesize, slinesize, - dlinesize, s->lut[plane]); - } + td.out = out, td.in = in; + ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(s->height[1], ff_filter_get_nb_threads(ctx))); 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) +{ + int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + + if (ret < 0) + return ret; + + return config_input(ctx->inputs[0]); +} + static const AVFilterPad inputs[] = { { .name = "default", @@ -668,5 +897,6 @@ .query_formats = query_formats, .inputs = inputs, .outputs = outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_psnr.c ffmpeg-4.4/libavfilter/vf_psnr.c --- ffmpeg-4.2.2/libavfilter/vf_psnr.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_psnr.c 2021-04-08 21:28:40.000000000 +0000 @@ -51,9 +51,11 @@ uint8_t rgba_map[4]; char comps[4]; int nb_components; + int nb_threads; int planewidth[4]; int planeheight[4]; double planeweight[4]; + uint64_t **score; PSNRDSPContext dsp; } PSNRContext; @@ -104,35 +106,50 @@ return m2; } -static inline -void compute_images_mse(PSNRContext *s, - const uint8_t *main_data[4], const int main_linesizes[4], - const uint8_t *ref_data[4], const int ref_linesizes[4], - int w, int h, double mse[4]) -{ - int i, c; - - for (c = 0; c < s->nb_components; c++) { - const int outw = s->planewidth[c]; - const int outh = s->planeheight[c]; - const uint8_t *main_line = main_data[c]; - const uint8_t *ref_line = ref_data[c]; - const int ref_linesize = ref_linesizes[c]; - const int main_linesize = main_linesizes[c]; +typedef struct ThreadData { + const uint8_t *main_data[4]; + const uint8_t *ref_data[4]; + int main_linesize[4]; + int ref_linesize[4]; + int planewidth[4]; + int planeheight[4]; + uint64_t **score; + int nb_components; + PSNRDSPContext *dsp; +} ThreadData; + +static +int compute_images_mse(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + ThreadData *td = arg; + uint64_t *score = td->score[jobnr]; + + for (int c = 0; c < td->nb_components; c++) { + const int outw = td->planewidth[c]; + const int outh = td->planeheight[c]; + const int slice_start = (outh * jobnr) / nb_jobs; + const int slice_end = (outh * (jobnr+1)) / nb_jobs; + const int ref_linesize = td->ref_linesize[c]; + const int main_linesize = td->main_linesize[c]; + const uint8_t *main_line = td->main_data[c] + main_linesize * slice_start; + const uint8_t *ref_line = td->ref_data[c] + ref_linesize * slice_start; uint64_t m = 0; - for (i = 0; i < outh; i++) { - m += s->dsp.sse_line(main_line, ref_line, outw); + for (int i = slice_start; i < slice_end; i++) { + m += td->dsp->sse_line(main_line, ref_line, outw); ref_line += ref_linesize; main_line += main_linesize; } - mse[c] = m / (double)(outw * outh); + score[c] = m; } + + return 0; } static void set_meta(AVDictionary **metadata, const char *key, char comp, float d) { char value[128]; - snprintf(value, sizeof(value), "%0.2f", d); + snprintf(value, sizeof(value), "%f", d); if (comp) { char key2[128]; snprintf(key2, sizeof(key2), "%s%c", key, comp); @@ -147,34 +164,55 @@ AVFilterContext *ctx = fs->parent; PSNRContext *s = ctx->priv; AVFrame *master, *ref; - double comp_mse[4], mse = 0; - int ret, j, c; + double comp_mse[4], mse = 0.; + uint64_t comp_sum[4] = { 0 }; AVDictionary **metadata; + ThreadData td; + int ret; ret = ff_framesync_dualinput_get(fs, &master, &ref); if (ret < 0) return ret; - if (!ref) + if (ctx->is_disabled || !ref) return ff_filter_frame(ctx->outputs[0], master); metadata = &master->metadata; - compute_images_mse(s, (const uint8_t **)master->data, master->linesize, - (const uint8_t **)ref->data, ref->linesize, - master->width, master->height, comp_mse); + td.nb_components = s->nb_components; + td.dsp = &s->dsp; + td.score = s->score; + for (int c = 0; c < s->nb_components; c++) { + td.main_data[c] = master->data[c]; + td.ref_data[c] = ref->data[c]; + td.main_linesize[c] = master->linesize[c]; + td.ref_linesize[c] = ref->linesize[c]; + td.planewidth[c] = s->planewidth[c]; + td.planeheight[c] = s->planeheight[c]; + } - for (j = 0; j < s->nb_components; j++) - mse += comp_mse[j] * s->planeweight[j]; + ctx->internal->execute(ctx, compute_images_mse, &td, NULL, FFMIN(s->planeheight[1], s->nb_threads)); + + for (int j = 0; j < s->nb_threads; j++) { + for (int c = 0; c < s->nb_components; c++) + comp_sum[c] += s->score[j][c]; + } + + for (int c = 0; c < s->nb_components; c++) + comp_mse[c] = comp_sum[c] / ((double)s->planewidth[c] * s->planeheight[c]); + + for (int c = 0; c < s->nb_components; c++) + mse += comp_mse[c] * s->planeweight[c]; s->min_mse = FFMIN(s->min_mse, mse); s->max_mse = FFMAX(s->max_mse, mse); s->mse += mse; - for (j = 0; j < s->nb_components; j++) + + for (int j = 0; j < s->nb_components; j++) s->mse_comp[j] += comp_mse[j]; s->nb_frames++; - for (j = 0; j < s->nb_components; j++) { - c = s->is_rgb ? s->rgba_map[j] : j; + for (int j = 0; j < s->nb_components; j++) { + int c = s->is_rgb ? s->rgba_map[j] : j; set_meta(metadata, "lavfi.psnr.mse.", s->comps[j], comp_mse[c]); set_meta(metadata, "lavfi.psnr.psnr.", s->comps[j], get_psnr(comp_mse[c], 1, s->max[c])); } @@ -185,16 +223,16 @@ if (s->stats_version == 2 && !s->stats_header_written) { fprintf(s->stats_file, "psnr_log_version:2 fields:n"); fprintf(s->stats_file, ",mse_avg"); - for (j = 0; j < s->nb_components; j++) { + for (int j = 0; j < s->nb_components; j++) { fprintf(s->stats_file, ",mse_%c", s->comps[j]); } fprintf(s->stats_file, ",psnr_avg"); - for (j = 0; j < s->nb_components; j++) { + for (int j = 0; j < s->nb_components; j++) { fprintf(s->stats_file, ",psnr_%c", s->comps[j]); } if (s->stats_add_max) { fprintf(s->stats_file, ",max_avg"); - for (j = 0; j < s->nb_components; j++) { + for (int j = 0; j < s->nb_components; j++) { fprintf(s->stats_file, ",max_%c", s->comps[j]); } } @@ -202,20 +240,20 @@ s->stats_header_written = 1; } fprintf(s->stats_file, "n:%"PRId64" mse_avg:%0.2f ", s->nb_frames, mse); - for (j = 0; j < s->nb_components; j++) { - c = s->is_rgb ? s->rgba_map[j] : j; + for (int j = 0; j < s->nb_components; j++) { + int c = s->is_rgb ? s->rgba_map[j] : j; fprintf(s->stats_file, "mse_%c:%0.2f ", s->comps[j], comp_mse[c]); } fprintf(s->stats_file, "psnr_avg:%0.2f ", get_psnr(mse, 1, s->average_max)); - for (j = 0; j < s->nb_components; j++) { - c = s->is_rgb ? s->rgba_map[j] : j; + for (int j = 0; j < s->nb_components; j++) { + int c = s->is_rgb ? s->rgba_map[j] : j; fprintf(s->stats_file, "psnr_%c:%0.2f ", s->comps[j], get_psnr(comp_mse[c], 1, s->max[c])); } if (s->stats_version == 2 && s->stats_add_max) { fprintf(s->stats_file, "max_avg:%d ", s->average_max); - for (j = 0; j < s->nb_components; j++) { - c = s->is_rgb ? s->rgba_map[j] : j; + for (int j = 0; j < s->nb_components; j++) { + int c = s->is_rgb ? s->rgba_map[j] : j; fprintf(s->stats_file, "max_%c:%d ", s->comps[j], s->max[c]); } } @@ -289,6 +327,7 @@ unsigned sum; int j; + s->nb_threads = ff_filter_get_nb_threads(ctx); s->nb_components = desc->nb_components; if (ctx->inputs[0]->w != ctx->inputs[1]->w || ctx->inputs[0]->h != ctx->inputs[1]->h) { @@ -329,6 +368,16 @@ if (ARCH_X86) ff_psnr_init_x86(&s->dsp, desc->comp[0].depth); + s->score = av_calloc(s->nb_threads, sizeof(*s->score)); + if (!s->score) + return AVERROR(ENOMEM); + + for (int t = 0; t < s->nb_threads && s->score; t++) { + s->score[t] = av_calloc(s->nb_components, sizeof(*s->score[0])); + if (!s->score[t]) + return AVERROR(ENOMEM); + } + return 0; } @@ -350,6 +399,14 @@ if ((ret = ff_framesync_configure(&s->fs)) < 0) return ret; + outlink->time_base = s->fs.time_base; + + if (av_cmp_q(mainlink->time_base, outlink->time_base) || + av_cmp_q(ctx->inputs[1]->time_base, outlink->time_base)) + av_log(ctx, AV_LOG_WARNING, "not matching timebases found between first input: %d/%d and second input %d/%d, results may be incorrect!\n", + mainlink->time_base.num, mainlink->time_base.den, + ctx->inputs[1]->time_base.num, ctx->inputs[1]->time_base.den); + return 0; } @@ -381,6 +438,9 @@ } ff_framesync_uninit(&s->fs); + for (int t = 0; t < s->nb_threads && s->score; t++) + av_freep(&s->score[t]); + av_freep(&s->score); if (s->stats_file && s->stats_file != stdout) fclose(s->stats_file); @@ -419,4 +479,5 @@ .priv_class = &psnr_class, .inputs = psnr_inputs, .outputs = psnr_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_qp.c ffmpeg-4.4/libavfilter/vf_qp.c --- ffmpeg-4.2.2/libavfilter/vf_qp.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_qp.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,6 +23,8 @@ #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" +#include "libavutil/video_enc_params.h" + #include "avfilter.h" #include "formats.h" #include "internal.h" @@ -36,6 +38,8 @@ int evaluate_per_mb; } QPContext; +static const char *const var_names[] = { "known", "qp", "x", "y", "w", "h", NULL }; + #define OFFSET(x) offsetof(QPContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM @@ -53,7 +57,6 @@ int i; int ret; AVExpr *e = NULL; - static const char *var_names[] = { "known", "qp", "x", "y", "w", "h", NULL }; if (!s->qp_expr_str) return 0; @@ -89,39 +92,59 @@ AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; QPContext *s = ctx->priv; - AVBufferRef *out_qp_table_buf; AVFrame *out = NULL; - const int8_t *in_qp_table; - int type, stride, ret; + int ret; + + AVFrameSideData *sd_in; + AVVideoEncParams *par_in = NULL; + int8_t in_qp_global = 0; + + AVVideoEncParams *par_out; if (!s->qp_expr_str || ctx->is_disabled) return ff_filter_frame(outlink, in); - out_qp_table_buf = av_buffer_alloc(s->h * s->qstride); - if (!out_qp_table_buf) { - ret = AVERROR(ENOMEM); - goto fail; + sd_in = av_frame_get_side_data(in, AV_FRAME_DATA_VIDEO_ENC_PARAMS); + if (sd_in && sd_in->size >= sizeof(AVVideoEncParams)) { + par_in = (AVVideoEncParams*)sd_in->data; + + // we accept the input QP table only if it is of the MPEG2 type + // and contains either no blocks at all or 16x16 macroblocks + if (par_in->type == AV_VIDEO_ENC_PARAMS_MPEG2 && + (par_in->nb_blocks == s->h * s->qstride || !par_in->nb_blocks)) { + in_qp_global = par_in->qp; + if (!par_in->nb_blocks) + par_in = NULL; + } else + par_in = NULL; } out = av_frame_clone(in); if (!out) { - av_buffer_unref(&out_qp_table_buf); ret = AVERROR(ENOMEM); goto fail; } - in_qp_table = av_frame_get_qp_table(in, &stride, &type); - av_frame_set_qp_table(out, out_qp_table_buf, s->qstride, type); + par_out = av_video_enc_params_create_side_data(out, AV_VIDEO_ENC_PARAMS_MPEG2, + (s->evaluate_per_mb || sd_in) ? + s->h * s->qstride : 0); + if (!par_out) { + ret = AVERROR(ENOMEM); + goto fail; + } +#define BLOCK_QP_DELTA(block_idx) \ + (par_in ? av_video_enc_params_block(par_in, block_idx)->delta_qp : 0) if (s->evaluate_per_mb) { int y, x; for (y = 0; y < s->h; y++) for (x = 0; x < s->qstride; x++) { - int qp = in_qp_table ? in_qp_table[x + stride * y] : NAN; - double var_values[] = { !!in_qp_table, qp, x, y, s->qstride, s->h, 0}; - static const char *var_names[] = { "known", "qp", "x", "y", "w", "h", NULL }; + unsigned int block_idx = y * s->qstride + x; + AVVideoBlockParams *b = av_video_enc_params_block(par_out, block_idx); + int qp = sd_in ? in_qp_global + BLOCK_QP_DELTA(block_idx) : NAN; + double var_values[] = { !!sd_in, qp, x, y, s->qstride, s->h, 0}; double temp_val; ret = av_expr_parse_and_eval(&temp_val, s->qp_expr_str, @@ -129,21 +152,19 @@ NULL, NULL, NULL, NULL, 0, 0, ctx); if (ret < 0) goto fail; - out_qp_table_buf->data[x + s->qstride * y] = lrintf(temp_val); + b->delta_qp = lrintf(temp_val); } - } else if (in_qp_table) { + } else if (sd_in) { int y, x; for (y = 0; y < s->h; y++) - for (x = 0; x < s->qstride; x++) - out_qp_table_buf->data[x + s->qstride * y] = s->lut[129 + - ((int8_t)in_qp_table[x + stride * y])]; + for (x = 0; x < s->qstride; x++) { + unsigned int block_idx = y * s->qstride + x; + AVVideoBlockParams *b = av_video_enc_params_block(par_out, block_idx); + b->delta_qp = s->lut[129 + (int8_t)(in_qp_global + BLOCK_QP_DELTA(block_idx))]; + } } else { - int y, x, qp = s->lut[0]; - - for (y = 0; y < s->h; y++) - for (x = 0; x < s->qstride; x++) - out_qp_table_buf->data[x + s->qstride * y] = qp; + par_out->qp = s->lut[0]; } ret = ff_filter_frame(outlink, out); diff -Nru ffmpeg-4.2.2/libavfilter/vf_random.c ffmpeg-4.4/libavfilter/vf_random.c --- ffmpeg-4.2.2/libavfilter/vf_random.c 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_random.c 2020-07-11 10:39:30.000000000 +0000 @@ -97,8 +97,13 @@ ret = ff_request_frame(ctx->inputs[0]); +next: if (ret == AVERROR_EOF && !ctx->is_disabled && s->nb_frames > 0) { AVFrame *out = s->frames[s->nb_frames - 1]; + if (!out) { + s->nb_frames--; + goto next; + } out->pts = s->pts[s->flush_idx++]; ret = ff_filter_frame(outlink, out); s->frames[s->nb_frames - 1] = NULL; @@ -108,6 +113,14 @@ return ret; } +static av_cold void uninit(AVFilterContext *ctx) +{ + RandomContext *s = ctx->priv; + + for (int i = 0; i < s->nb_frames; i++) + av_frame_free(&s->frames[i]); +} + static const AVFilterPad random_inputs[] = { { .name = "default", @@ -132,6 +145,7 @@ .priv_size = sizeof(RandomContext), .priv_class = &random_class, .init = init, + .uninit = uninit, .inputs = random_inputs, .outputs = random_outputs, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_readeia608.c ffmpeg-4.4/libavfilter/vf_readeia608.c --- ffmpeg-4.2.2/libavfilter/vf_readeia608.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_readeia608.c 2021-04-08 21:28:40.000000000 +0000 @@ -36,41 +36,65 @@ #include "internal.h" #include "video.h" -#define FALL 0 -#define RISE 1 +#define LAG 25 +#define CLOCK_BITSIZE_MIN 0.2f +#define CLOCK_BITSIZE_MAX 1.5f +#define SYNC_BITSIZE_MIN 12.f +#define SYNC_BITSIZE_MAX 15.f + +typedef struct LineItem { + int input; + int output; + + float unfiltered; + float filtered; + float average; + float deviation; +} LineItem; + +typedef struct CodeItem { + uint8_t bit; + int size; +} CodeItem; + +typedef struct ScanItem { + int nb_line; + int found; + int white; + int black; + uint64_t *histogram; + uint8_t byte[2]; + + CodeItem *code; + LineItem *line; +} ScanItem; typedef struct ReadEIA608Context { const AVClass *class; + int start, end; - int min_range; - int max_peak_diff; - int max_period_diff; - int max_start_diff; - int nb_found; - int white; - int black; - float mpd, mhd, msd, mac, spw, bhd, wth, bth; + float spw; int chp; int lp; - uint8_t *temp; + + int depth; + int max; + int nb_allocated; + ScanItem *scan; + + void (*read_line[2])(AVFrame *in, int nb_line, + LineItem *line, int lp, int w); } ReadEIA608Context; #define OFFSET(x) offsetof(ReadEIA608Context, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption readeia608_options[] = { - { "scan_min", "set from which line to scan for codes", OFFSET(start), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, - { "scan_max", "set to which line to scan for codes", OFFSET(end), AV_OPT_TYPE_INT, {.i64=29}, 0, INT_MAX, FLAGS }, - { "mac", "set minimal acceptable amplitude change for sync codes detection", OFFSET(mac), AV_OPT_TYPE_FLOAT, {.dbl=.2}, 0.001, 1, FLAGS }, - { "spw", "set ratio of width reserved for sync code detection", OFFSET(spw), AV_OPT_TYPE_FLOAT, {.dbl=.27}, 0.1, 0.7, FLAGS }, - { "mhd", "set max peaks height difference for sync code detection", OFFSET(mhd), AV_OPT_TYPE_FLOAT, {.dbl=.1}, 0, 0.5, FLAGS }, - { "mpd", "set max peaks period difference for sync code detection", OFFSET(mpd), AV_OPT_TYPE_FLOAT, {.dbl=.1}, 0, 0.5, FLAGS }, - { "msd", "set first two max start code bits differences", OFFSET(msd), AV_OPT_TYPE_FLOAT, {.dbl=.02}, 0, 0.5, FLAGS }, - { "bhd", "set min ratio of bits height compared to 3rd start code bit", OFFSET(bhd), AV_OPT_TYPE_FLOAT, {.dbl=.75}, 0.01, 1, FLAGS }, - { "th_w", "set white color threshold", OFFSET(wth), AV_OPT_TYPE_FLOAT, {.dbl=.35}, 0.1, 1, FLAGS }, - { "th_b", "set black color threshold", OFFSET(bth), AV_OPT_TYPE_FLOAT, {.dbl=.15}, 0, 0.5, FLAGS }, - { "chp", "check and apply parity bit", OFFSET(chp), AV_OPT_TYPE_BOOL, {.i64= 0}, 0, 1, FLAGS }, - { "lp", "lowpass line prior to processing", OFFSET(lp), AV_OPT_TYPE_BOOL, {.i64= 0}, 0, 1, FLAGS }, + { "scan_min", "set from which line to scan for codes", OFFSET(start), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, + { "scan_max", "set to which line to scan for codes", OFFSET(end), AV_OPT_TYPE_INT, {.i64=29}, 0, INT_MAX, FLAGS }, + { "spw", "set ratio of width reserved for sync code detection", OFFSET(spw), AV_OPT_TYPE_FLOAT, {.dbl=.27}, 0.1, 0.7, FLAGS }, + { "chp", "check and apply parity bit", OFFSET(chp), AV_OPT_TYPE_BOOL, {.i64= 0}, 0, 1, FLAGS }, + { "lp", "lowpass line prior to processing", OFFSET(lp), AV_OPT_TYPE_BOOL, {.i64= 1}, 0, 1, FLAGS }, { NULL } }; @@ -79,13 +103,26 @@ static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pixel_fmts[] = { - AV_PIX_FMT_GRAY8, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, + AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, + AV_PIX_FMT_GRAY16, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_NONE }; AVFilterFormats *formats = ff_make_format_list(pixel_fmts); @@ -94,167 +131,340 @@ return ff_set_common_formats(ctx, formats); } -static int config_input(AVFilterLink *inlink) +static int config_filter(AVFilterContext *ctx, int start, int end) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - AVFilterContext *ctx = inlink->dst; ReadEIA608Context *s = ctx->priv; - int depth = desc->comp[0].depth; + AVFilterLink *inlink = ctx->inputs[0]; + int size = inlink->w + LAG; - if (s->end >= inlink->h) { + if (end >= inlink->h) { av_log(ctx, AV_LOG_WARNING, "Last line to scan too large, clipping.\n"); - s->end = inlink->h - 1; + end = inlink->h - 1; } - if (s->start > s->end) { + if (start > end) { av_log(ctx, AV_LOG_ERROR, "Invalid range.\n"); return AVERROR(EINVAL); } - s->min_range = s->mac * ((1 << depth) - 1); - s->max_peak_diff = s->mhd * ((1 << depth) - 1); - s->max_period_diff = s->mpd * ((1 << depth) - 1); - s->max_start_diff = s->msd * ((1 << depth) - 1); - s->white = s->wth * ((1 << depth) - 1); - s->black = s->bth * ((1 << depth) - 1); - s->temp = av_calloc(inlink->w, sizeof(*s->temp)); - if (!s->temp) - return AVERROR(ENOMEM); + if (s->nb_allocated < end - start + 1) { + const int diff = end - start + 1 - s->nb_allocated; + + s->scan = av_realloc_f(s->scan, end - start + 1, sizeof(*s->scan)); + if (!s->scan) + return AVERROR(ENOMEM); + memset(&s->scan[s->nb_allocated], 0, diff * sizeof(*s->scan)); + s->nb_allocated = end - start + 1; + } + + for (int i = 0; i < s->nb_allocated; i++) { + ScanItem *scan = &s->scan[i]; + + if (!scan->histogram) + scan->histogram = av_calloc(s->max + 1, sizeof(*scan->histogram)); + if (!scan->line) + scan->line = av_calloc(size, sizeof(*scan->line)); + if (!scan->code) + scan->code = av_calloc(size, sizeof(*scan->code)); + if (!scan->line || !scan->code || !scan->histogram) + return AVERROR(ENOMEM); + } + + s->start = start; + s->end = end; return 0; } -static void extract_line(AVFilterContext *ctx, AVFilterLink *inlink, AVFrame *in, int line) +static void build_histogram(ReadEIA608Context *s, ScanItem *scan, const LineItem *line, int len) { - ReadEIA608Context *s = ctx->priv; - int max = 0, min = INT_MAX; - int i, ch, range = 0; - const uint8_t *src; - uint16_t clock[8][2] = { { 0 } }; - const int sync_width = s->spw * in->width; - int last = 0, peaks = 0, max_peak_diff = 0, dir = RISE; - const int width_per_bit = (in->width - sync_width) / 19; - uint8_t byte[2] = { 0 }; - int s1, s2, s3, parity; - - src = &in->data[0][line * in->linesize[0]]; - - if (s->lp) { - uint8_t *dst = s->temp; - int w = inlink->w - 1; - - for (i = 0; i < inlink->w; i++) { - int a = FFMAX(i - 3, 0); - int b = FFMAX(i - 2, 0); - int c = FFMAX(i - 1, 0); - int d = FFMIN(i + 3, w); - int e = FFMIN(i + 2, w); - int f = FFMIN(i + 1, w); + memset(scan->histogram, 0, (s->max + 1) * sizeof(*scan->histogram)); + + for (int i = LAG; i < len + LAG; i++) + scan->histogram[line[i].input]++; +} - dst[i] = (src[a] + src[b] + src[c] + src[i] + src[d] + src[e] + src[f] + 6) / 7; +static void find_black_and_white(ReadEIA608Context *s, ScanItem *scan) +{ + const int max = s->max; + int start = 0, end = 0, middle; + int black = 0, white = 0; + int cnt; + + for (int i = 0; i <= max; i++) { + if (scan->histogram[i]) { + start = i; + break; } + } - src = s->temp; + for (int i = max; i >= 0; i--) { + if (scan->histogram[i]) { + end = i; + break; + } } - for (i = 0; i < sync_width; i++) { - max = FFMAX(max, src[i]); - min = FFMIN(min, src[i]); + middle = start + (end - start) / 2; + + cnt = 0; + for (int i = start; i <= middle; i++) { + if (scan->histogram[i] > cnt) { + cnt = scan->histogram[i]; + black = i; + } } - range = max - min; - if (range < s->min_range) - return; + cnt = 0; + for (int i = end; i >= middle; i--) { + if (scan->histogram[i] > cnt) { + cnt = scan->histogram[i]; + white = i; + } + } - for (i = 0; i < sync_width; i++) { - int Y = src[i]; + scan->black = black; + scan->white = white; +} - if (dir == RISE) { - if (Y < last) { - dir = FALL; - if (last >= s->white) { - clock[peaks][0] = last; - clock[peaks][1] = i; - peaks++; - if (peaks > 7) - break; - } - } - } else if (dir == FALL) { - if (Y > last && last <= s->black) { - dir = RISE; +static float meanf(const LineItem *line, int len) +{ + float sum = 0.0, mean = 0.0; + + for (int i = 0; i < len; i++) + sum += line[i].filtered; + + mean = sum / len; + + return mean; +} + +static float stddevf(const LineItem *line, int len) +{ + float m = meanf(line, len); + float standard_deviation = 0.f; + + for (int i = 0; i < len; i++) + standard_deviation += (line[i].filtered - m) * (line[i].filtered - m); + + return sqrtf(standard_deviation / (len - 1)); +} + +static void thresholding(ReadEIA608Context *s, ScanItem *scan, LineItem *line, + int lag, float threshold, float influence, int len) +{ + for (int i = lag; i < len + lag; i++) { + line[i].unfiltered = line[i].input / 255.f; + line[i].filtered = line[i].unfiltered; + } + + for (int i = 0; i < lag; i++) { + line[i].unfiltered = meanf(line, len * s->spw); + line[i].filtered = line[i].unfiltered; + } + + line[lag - 1].average = meanf(line, lag); + line[lag - 1].deviation = stddevf(line, lag); + + for (int i = lag; i < len + lag; i++) { + if (fabsf(line[i].unfiltered - line[i-1].average) > threshold * line[i-1].deviation) { + if (line[i].unfiltered > line[i-1].average) { + line[i].output = 255; + } else { + line[i].output = 0; } + + line[i].filtered = influence * line[i].unfiltered + (1.f - influence) * line[i-1].filtered; + } else { + int distance_from_black, distance_from_white; + + distance_from_black = FFABS(line[i].input - scan->black); + distance_from_white = FFABS(line[i].input - scan->white); + + line[i].output = distance_from_black <= distance_from_white ? 0 : 255; } - last = Y; + + line[i].average = meanf(line + i - lag, lag); + line[i].deviation = stddevf(line + i - lag, lag); } +} - if (peaks != 7) { - av_log(ctx, AV_LOG_DEBUG, "peaks: %d != 7\n", peaks); - return; +static int periods(const LineItem *line, CodeItem *code, int len) +{ + int hold = line[LAG].output, cnt = 0; + int last = LAG; + + memset(code, 0, len * sizeof(*code)); + + for (int i = LAG + 1; i < len + LAG; i++) { + if (line[i].output != hold) { + code[cnt].size = i - last; + code[cnt].bit = hold; + hold = line[i].output; + last = i; + cnt++; + } } - for (i = 1; i < 7; i++) - max_peak_diff = FFMAX(max_peak_diff, FFABS(clock[i][0] - clock[i-1][0])); + code[cnt].size = LAG + len - last; + code[cnt].bit = hold; - if (max_peak_diff > s->max_peak_diff) { - av_log(ctx, AV_LOG_DEBUG, "mhd: %d > %d\n", max_peak_diff, s->max_peak_diff); + return cnt + 1; +} + +static void dump_code(AVFilterContext *ctx, ScanItem *scan, int len, int item) +{ + av_log(ctx, AV_LOG_DEBUG, "%d:", item); + for (int i = 0; i < len; i++) { + av_log(ctx, AV_LOG_DEBUG, " %03d", scan->code[i].size); + } + av_log(ctx, AV_LOG_DEBUG, "\n"); +} + +#define READ_LINE(type, name) \ +static void read_##name(AVFrame *in, int nb_line, LineItem *line, int lp, int w) \ +{ \ + const type *src = (const type *)(&in->data[0][nb_line * in->linesize[0]]);\ + \ + if (lp) { \ + for (int i = 0; i < w; i++) { \ + int a = FFMAX(i - 3, 0); \ + int b = FFMAX(i - 2, 0); \ + int c = FFMAX(i - 1, 0); \ + int d = FFMIN(i + 3, w-1); \ + int e = FFMIN(i + 2, w-1); \ + int f = FFMIN(i + 1, w-1); \ + \ + line[LAG + i].input = (src[a] + src[b] + src[c] + src[i] + \ + src[d] + src[e] + src[f] + 6) / 7; \ + } \ + } else { \ + for (int i = 0; i < w; i++) { \ + line[LAG + i].input = src[i]; \ + } \ + } \ +} + +READ_LINE(uint8_t, byte) +READ_LINE(uint16_t, word) + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ReadEIA608Context *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + + if (!desc) + return AVERROR_BUG; + s->depth = desc->comp[0].depth; + s->max = (1 << desc->comp[0].depth) - 1; + s->read_line[0] = read_byte; + s->read_line[1] = read_word; + + return config_filter(ctx, s->start, s->end); +} + +static void extract_line(AVFilterContext *ctx, AVFrame *in, ScanItem *scan, int w, int nb_line) +{ + ReadEIA608Context *s = ctx->priv; + LineItem *line = scan->line; + int i, j, ch, len; + uint8_t codes[19] = { 0 }; + float bit_size = 0.f; + int parity; + + memset(line, 0, (w + LAG) * sizeof(*line)); + scan->byte[0] = scan->byte[1] = 0; + scan->found = 0; + + s->read_line[s->depth > 8](in, nb_line, line, s->lp, w); + + build_histogram(s, scan, line, w); + find_black_and_white(s, scan); + if (scan->white - scan->black < 5) + return; + + thresholding(s, scan, line, LAG, 1, 0, w); + len = periods(line, scan->code, w); + dump_code(ctx, scan, len, nb_line); + if (len < 15 || + scan->code[14].bit != 0 || + w / (float)scan->code[14].size < SYNC_BITSIZE_MIN || + w / (float)scan->code[14].size > SYNC_BITSIZE_MAX) { return; } - max = 0; min = INT_MAX; - for (i = 1; i < 7; i++) { - max = FFMAX(max, FFABS(clock[i][1] - clock[i-1][1])); - min = FFMIN(min, FFABS(clock[i][1] - clock[i-1][1])); + for (i = 14; i < len; i++) { + bit_size += scan->code[i].size; } - range = max - min; - if (range > s->max_period_diff) { - av_log(ctx, AV_LOG_DEBUG, "mpd: %d > %d\n", range, s->max_period_diff); + bit_size /= 19.f; + for (i = 1; i < 14; i++) { + if (scan->code[i].size / bit_size > CLOCK_BITSIZE_MAX || + scan->code[i].size / bit_size < CLOCK_BITSIZE_MIN) { + return; + } + } + + if (scan->code[15].size / bit_size < 0.45f) { return; } - s1 = src[sync_width + width_per_bit * 0 + width_per_bit / 2]; - s2 = src[sync_width + width_per_bit * 1 + width_per_bit / 2]; - s3 = src[sync_width + width_per_bit * 2 + width_per_bit / 2]; + for (j = 0, i = 14; i < len; i++) { + int run, bit; - if (FFABS(s1 - s2) > s->max_start_diff || s1 > s->black || s2 > s->black || s3 < s->white) { - av_log(ctx, AV_LOG_DEBUG, "msd: %d > %d\n", FFABS(s1 - s2), s->max_start_diff); - return; + run = lrintf(scan->code[i].size / bit_size); + bit = scan->code[i].bit; + + for (int k = 0; j < 19 && k < run; k++) { + codes[j++] = bit; + } + + if (j >= 19) + break; } for (ch = 0; ch < 2; ch++) { for (parity = 0, i = 0; i < 8; i++) { - int b = src[sync_width + width_per_bit * (i + 3 + 8 * ch) + width_per_bit / 2]; + int b = codes[3 + ch * 8 + i]; - if (b - s1 > (s3 - s1) * s->bhd) { - b = 1; + if (b == 255) { parity++; + b = 1; } else { b = 0; } - byte[ch] |= b << i; + scan->byte[ch] |= b << i; } if (s->chp) { if (!(parity & 1)) { - byte[ch] = 0; + scan->byte[ch] = 0x7F; } } } - { - uint8_t key[128], value[128]; + scan->nb_line = nb_line; + scan->found = 1; +} - snprintf(key, sizeof(key), "lavfi.readeia608.%d.cc", s->nb_found); - snprintf(value, sizeof(value), "0x%02X%02X", byte[0], byte[1]); - av_dict_set(&in->metadata, key, value, 0); +static int extract_lines(AVFilterContext *ctx, void *arg, + int job, int nb_jobs) +{ + ReadEIA608Context *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + const int h = s->end - s->start + 1; + const int start = (h * job) / nb_jobs; + const int end = (h * (job+1)) / nb_jobs; + AVFrame *in = arg; - snprintf(key, sizeof(key), "lavfi.readeia608.%d.line", s->nb_found); - snprintf(value, sizeof(value), "%d", line); - av_dict_set(&in->metadata, key, value, 0); + for (int i = start; i < end; i++) { + ScanItem *scan = &s->scan[i]; + + extract_line(ctx, in, scan, inlink->w, i); } - s->nb_found++; + return 0; } static int filter_frame(AVFilterLink *inlink, AVFrame *in) @@ -262,11 +472,33 @@ AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; ReadEIA608Context *s = ctx->priv; - int i; + int nb_found; - s->nb_found = 0; - for (i = s->start; i <= s->end; i++) - extract_line(ctx, inlink, in, i); + ctx->internal->execute(ctx, extract_lines, in, NULL, FFMIN(FFMAX(s->end - s->start + 1, 1), + ff_filter_get_nb_threads(ctx))); + + nb_found = 0; + for (int i = 0; i < s->end - s->start + 1; i++) { + ScanItem *scan = &s->scan[i]; + uint8_t key[128], value[128]; + + if (!scan->found) + continue; + + //snprintf(key, sizeof(key), "lavfi.readeia608.%d.bits", nb_found); + //snprintf(value, sizeof(value), "0b%d%d%d%d%d%d%d%d 0b%d%d%d%d%d%d%d%d", codes[3]==255,codes[4]==255,codes[5]==255,codes[6]==255,codes[7]==255,codes[8]==255,codes[9]==255,codes[10]==255,codes[11]==255,codes[12]==255,codes[13]==255,codes[14]==255,codes[15]==255,codes[16]==255,codes[17]==255,codes[18]==255); + //av_dict_set(&in->metadata, key, value, 0); + + snprintf(key, sizeof(key), "lavfi.readeia608.%d.cc", nb_found); + snprintf(value, sizeof(value), "0x%02X%02X", scan->byte[0], scan->byte[1]); + av_dict_set(&in->metadata, key, value, 0); + + snprintf(key, sizeof(key), "lavfi.readeia608.%d.line", nb_found); + snprintf(value, sizeof(value), "%d", scan->nb_line); + av_dict_set(&in->metadata, key, value, 0); + + nb_found++; + } return ff_filter_frame(outlink, in); } @@ -275,7 +507,35 @@ { ReadEIA608Context *s = ctx->priv; - av_freep(&s->temp); + for (int i = 0; i < s->nb_allocated; i++) { + ScanItem *scan = &s->scan[i]; + + av_freep(&scan->histogram); + av_freep(&scan->code); + av_freep(&scan->line); + } + + s->nb_allocated = 0; + av_freep(&s->scan); +} + +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + ReadEIA608Context *s = ctx->priv; + int ret, start = s->start, end = s->end; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + ret = config_filter(ctx, s->start, s->end); + if (ret < 0) { + s->start = start; + s->end = end; + } + + return 0; } static const AVFilterPad readeia608_inputs[] = { @@ -305,5 +565,6 @@ .inputs = readeia608_inputs, .outputs = readeia608_outputs, .uninit = uninit, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_remap.c ffmpeg-4.4/libavfilter/vf_remap.c --- ffmpeg-4.2.2/libavfilter/vf_remap.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_remap.c 2021-04-08 21:28:40.000000000 +0000 @@ -36,10 +36,12 @@ * Target_frame[y][x] = Source_frame[ ymap[y][x] ][ [xmap[y][x] ]; */ +#include "libavutil/colorspace.h" #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" #include "avfilter.h" +#include "drawutils.h" #include "formats.h" #include "framesync.h" #include "internal.h" @@ -52,6 +54,8 @@ int nb_planes; int nb_components; int step; + uint8_t fill_rgba[4]; + int fill_color[4]; FFFrameSync fs; @@ -65,6 +69,7 @@ { "format", "set output format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "format" }, { "color", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, .flags = FLAGS, .unit = "format" }, { "gray", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, .flags = FLAGS, .unit = "format" }, + { "fill", "set the color of the unmapped pixels", OFFSET(fill_rgba), AV_OPT_TYPE_COLOR, {.str="black"}, .flags = FLAGS }, { NULL } }; @@ -89,7 +94,7 @@ AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16, - AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, @@ -110,25 +115,15 @@ AVFilterFormats *pix_formats = NULL, *map_formats = NULL; int ret; - if (!(pix_formats = ff_make_format_list(s->format ? gray_pix_fmts : pix_fmts)) || - !(map_formats = ff_make_format_list(map_fmts))) { - ret = AVERROR(ENOMEM); - goto fail; - } - if ((ret = ff_formats_ref(pix_formats, &ctx->inputs[0]->out_formats)) < 0 || - (ret = ff_formats_ref(map_formats, &ctx->inputs[1]->out_formats)) < 0 || - (ret = ff_formats_ref(map_formats, &ctx->inputs[2]->out_formats)) < 0 || - (ret = ff_formats_ref(pix_formats, &ctx->outputs[0]->in_formats)) < 0) - goto fail; - return 0; -fail: - if (pix_formats) - av_freep(&pix_formats->formats); - av_freep(&pix_formats); - if (map_formats) - av_freep(&map_formats->formats); - av_freep(&map_formats); - return ret; + pix_formats = ff_make_format_list(s->format ? gray_pix_fmts : pix_fmts); + if ((ret = ff_formats_ref(pix_formats, &ctx->inputs[0]->outcfg.formats)) < 0 || + (ret = ff_formats_ref(pix_formats, &ctx->outputs[0]->incfg.formats)) < 0) + return ret; + + map_formats = ff_make_format_list(map_fmts); + if ((ret = ff_formats_ref(map_formats, &ctx->inputs[1]->outcfg.formats)) < 0) + return ret; + return ff_formats_ref(map_formats, &ctx->inputs[2]->outcfg.formats); } /** @@ -140,7 +135,8 @@ static int remap_planar##bits##_##name##_slice(AVFilterContext *ctx, void *arg, \ int jobnr, int nb_jobs) \ { \ - const ThreadData *td = (ThreadData*)arg; \ + RemapContext *s = ctx->priv; \ + const ThreadData *td = arg; \ const AVFrame *in = td->in; \ const AVFrame *xin = td->xin; \ const AVFrame *yin = td->yin; \ @@ -158,13 +154,14 @@ const int slinesize = in->linesize[plane] / div; \ const uint16_t *xmap = (const uint16_t *)xin->data[0] + slice_start * xlinesize; \ const uint16_t *ymap = (const uint16_t *)yin->data[0] + slice_start * ylinesize; \ + const int color = s->fill_color[plane]; \ \ for (y = slice_start; y < slice_end; y++) { \ for (x = 0; x < out->width; x++) { \ if (ymap[x] < in->height && xmap[x] < in->width) { \ dst[x] = src[ymap[x] * slinesize + xmap[x]]; \ } else { \ - dst[x] = 0; \ + dst[x] = color; \ } \ } \ dst += dlinesize; \ @@ -189,7 +186,8 @@ static int remap_packed##bits##_##name##_slice(AVFilterContext *ctx, void *arg, \ int jobnr, int nb_jobs) \ { \ - const ThreadData *td = (ThreadData*)arg; \ + RemapContext *s = ctx->priv; \ + const ThreadData *td = arg; \ const AVFrame *in = td->in; \ const AVFrame *xin = td->xin; \ const AVFrame *yin = td->yin; \ @@ -213,7 +211,7 @@ if (ymap[x] < in->height && xmap[x] < in->width) { \ dst[x * step + c] = src[ymap[x] * slinesize + xmap[x] * step + c]; \ } else { \ - dst[x * step + c] = 0; \ + dst[x * step + c] = s->fill_color[c]; \ } \ } \ } \ @@ -233,11 +231,28 @@ AVFilterContext *ctx = inlink->dst; RemapContext *s = ctx->priv; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int depth = desc->comp[0].depth; + int is_rgb = !!(desc->flags & AV_PIX_FMT_FLAG_RGB); + int factor = 1 << (depth - 8); + uint8_t rgba_map[4]; + ff_fill_rgba_map(rgba_map, inlink->format); s->nb_planes = av_pix_fmt_count_planes(inlink->format); s->nb_components = desc->nb_components; - if (desc->comp[0].depth == 8) { + if (is_rgb) { + s->fill_color[rgba_map[0]] = s->fill_rgba[0] * factor; + s->fill_color[rgba_map[1]] = s->fill_rgba[1] * factor; + s->fill_color[rgba_map[2]] = s->fill_rgba[2] * factor; + s->fill_color[rgba_map[3]] = s->fill_rgba[3] * factor; + } else { + s->fill_color[0] = RGB_TO_Y_BT709(s->fill_rgba[0], s->fill_rgba[1], s->fill_rgba[2]) * factor; + s->fill_color[1] = RGB_TO_U_BT709(s->fill_rgba[0], s->fill_rgba[1], s->fill_rgba[2], 0) * factor; + s->fill_color[2] = RGB_TO_V_BT709(s->fill_rgba[0], s->fill_rgba[1], s->fill_rgba[2], 0) * factor; + s->fill_color[3] = s->fill_rgba[3] * factor; + } + + if (depth == 8) { if (s->nb_planes > 1 || s->nb_components == 1) { s->remap_slice = remap_planar8_nearest_slice; } else { diff -Nru ffmpeg-4.2.2/libavfilter/vf_removelogo.c ffmpeg-4.4/libavfilter/vf_removelogo.c --- ffmpeg-4.2.2/libavfilter/vf_removelogo.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_removelogo.c 2021-04-08 21:28:40.000000000 +0000 @@ -342,8 +342,8 @@ /* Calculate our bounding rectangles, which determine in what * region the logo resides for faster processing. */ - ff_calculate_bounding_box(&s->full_mask_bbox, s->full_mask_data, w, w, h, 0); - ff_calculate_bounding_box(&s->half_mask_bbox, s->half_mask_data, w/2, w/2, h/2, 0); + ff_calculate_bounding_box(&s->full_mask_bbox, s->full_mask_data, w, w, h, 0, 8); + ff_calculate_bounding_box(&s->half_mask_bbox, s->half_mask_data, w/2, w/2, h/2, 0, 8); #define SHOW_LOGO_INFO(mask_type) \ av_log(ctx, AV_LOG_VERBOSE, #mask_type " x1:%d x2:%d y1:%d y2:%d max_mask_size:%d\n", \ diff -Nru ffmpeg-4.2.2/libavfilter/vf_rotate.c ffmpeg-4.4/libavfilter/vf_rotate.c --- ffmpeg-4.2.2/libavfilter/vf_rotate.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_rotate.c 2021-04-08 21:28:40.000000000 +0000 @@ -94,16 +94,17 @@ #define OFFSET(x) offsetof(RotContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption rotate_options[] = { - { "angle", "set angle (in radians)", OFFSET(angle_expr_str), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX, .flags=FLAGS }, - { "a", "set angle (in radians)", OFFSET(angle_expr_str), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX, .flags=FLAGS }, - { "out_w", "set output width expression", OFFSET(outw_expr_str), AV_OPT_TYPE_STRING, {.str="iw"}, CHAR_MIN, CHAR_MAX, .flags=FLAGS }, - { "ow", "set output width expression", OFFSET(outw_expr_str), AV_OPT_TYPE_STRING, {.str="iw"}, CHAR_MIN, CHAR_MAX, .flags=FLAGS }, - { "out_h", "set output height expression", OFFSET(outh_expr_str), AV_OPT_TYPE_STRING, {.str="ih"}, CHAR_MIN, CHAR_MAX, .flags=FLAGS }, - { "oh", "set output height expression", OFFSET(outh_expr_str), AV_OPT_TYPE_STRING, {.str="ih"}, CHAR_MIN, CHAR_MAX, .flags=FLAGS }, - { "fillcolor", "set background fill color", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str="black"}, CHAR_MIN, CHAR_MAX, .flags=FLAGS }, - { "c", "set background fill color", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str="black"}, CHAR_MIN, CHAR_MAX, .flags=FLAGS }, + { "angle", "set angle (in radians)", OFFSET(angle_expr_str), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, .flags=TFLAGS }, + { "a", "set angle (in radians)", OFFSET(angle_expr_str), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, .flags=TFLAGS }, + { "out_w", "set output width expression", OFFSET(outw_expr_str), AV_OPT_TYPE_STRING, {.str="iw"}, 0, 0, .flags=FLAGS }, + { "ow", "set output width expression", OFFSET(outw_expr_str), AV_OPT_TYPE_STRING, {.str="iw"}, 0, 0, .flags=FLAGS }, + { "out_h", "set output height expression", OFFSET(outh_expr_str), AV_OPT_TYPE_STRING, {.str="ih"}, 0, 0, .flags=FLAGS }, + { "oh", "set output height expression", OFFSET(outh_expr_str), AV_OPT_TYPE_STRING, {.str="ih"}, 0, 0, .flags=FLAGS }, + { "fillcolor", "set background fill color", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str="black"}, 0, 0, .flags=FLAGS }, + { "c", "set background fill color", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str="black"}, 0, 0, .flags=FLAGS }, { "bilinear", "use bilinear interpolation", OFFSET(use_bilinear), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, .flags=FLAGS }, { NULL } }; @@ -414,8 +415,6 @@ } } -#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb)) - static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) { ThreadData *td = arg; diff -Nru ffmpeg-4.2.2/libavfilter/vf_scale.c ffmpeg-4.4/libavfilter/vf_scale.c --- ffmpeg-4.2.2/libavfilter/vf_scale.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_scale.c 2021-04-08 21:28:40.000000000 +0000 @@ -29,9 +29,10 @@ #include "avfilter.h" #include "formats.h" #include "internal.h" -#include "scale.h" +#include "scale_eval.h" #include "video.h" #include "libavutil/avstring.h" +#include "libavutil/eval.h" #include "libavutil/internal.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" @@ -41,6 +42,62 @@ #include "libavutil/avassert.h" #include "libswscale/swscale.h" +static const char *const var_names[] = { + "in_w", "iw", + "in_h", "ih", + "out_w", "ow", + "out_h", "oh", + "a", + "sar", + "dar", + "hsub", + "vsub", + "ohsub", + "ovsub", + "n", + "t", + "pos", + "main_w", + "main_h", + "main_a", + "main_sar", + "main_dar", "mdar", + "main_hsub", + "main_vsub", + "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_HSUB, + VAR_VSUB, + VAR_OHSUB, + VAR_OVSUB, + 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_HSUB, + VAR_S2R_MAIN_VSUB, + VAR_S2R_MAIN_N, + VAR_S2R_MAIN_T, + VAR_S2R_MAIN_POS, + VARS_NB +}; + enum EvalMode { EVAL_MODE_INIT, EVAL_MODE_FRAME, @@ -72,6 +129,10 @@ char *w_expr; ///< width expression string char *h_expr; ///< height expression string + AVExpr *w_pexpr; + AVExpr *h_pexpr; + double var_values[VARS_NB]; + char *flags_str; char *in_color_matrix; @@ -86,6 +147,7 @@ int in_v_chr_pos; int force_original_aspect_ratio; + int force_divisible_by; int nb_slices; @@ -95,6 +157,119 @@ AVFilter ff_vf_scale2ref; +static int config_props(AVFilterLink *outlink); + +static int check_exprs(AVFilterContext *ctx) +{ + ScaleContext *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 && + (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_HSUB] || vars_h[VAR_S2R_MAIN_HSUB] || + vars_w[VAR_S2R_MAIN_VSUB] || vars_h[VAR_S2R_MAIN_VSUB] || + 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 variables are not valid in scale 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 scale_parse_expr(AVFilterContext *ctx, char *str_expr, AVExpr **pexpr_ptr, const char *var, const char *args) +{ + ScaleContext *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 init_dict(AVFilterContext *ctx, AVDictionary **opts) { ScaleContext *scale = ctx->priv; @@ -126,6 +301,14 @@ if (!scale->h_expr) av_opt_set(scale, "h", "ih", 0); + ret = scale_parse_expr(ctx, NULL, &scale->w_pexpr, "width", scale->w_expr); + if (ret < 0) + return ret; + + ret = scale_parse_expr(ctx, NULL, &scale->h_pexpr, "height", scale->h_expr); + if (ret < 0) + return ret; + av_log(ctx, AV_LOG_VERBOSE, "w:%s h:%s flags:'%s' interl:%d\n", scale->w_expr, scale->h_expr, (char *)av_x_if_null(scale->flags_str, ""), scale->interlaced); @@ -148,6 +331,9 @@ static av_cold void uninit(AVFilterContext *ctx) { ScaleContext *scale = ctx->priv; + av_expr_free(scale->w_pexpr); + av_expr_free(scale->h_pexpr); + scale->w_pexpr = scale->h_pexpr = NULL; sws_freeContext(scale->sws); sws_freeContext(scale->isws[0]); sws_freeContext(scale->isws[1]); @@ -172,7 +358,7 @@ return ret; } } - if ((ret = ff_formats_ref(formats, &ctx->inputs[0]->out_formats)) < 0) + if ((ret = ff_formats_ref(formats, &ctx->inputs[0]->outcfg.formats)) < 0) return ret; } if (ctx->outputs[0]) { @@ -186,7 +372,7 @@ return ret; } } - if ((ret = ff_formats_ref(formats, &ctx->outputs[0]->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &ctx->outputs[0]->incfg.formats)) < 0) return ret; } @@ -217,6 +403,81 @@ return sws_getCoefficients(colorspace); } +static int scale_eval_dimensions(AVFilterContext *ctx) +{ + ScaleContext *scale = ctx->priv; + const char scale2ref = ctx->filter == &ff_vf_scale2ref; + const AVFilterLink *inlink = scale2ref ? ctx->inputs[1] : ctx->inputs[0]; + const AVFilterLink *outlink = ctx->outputs[0]; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format); + char *expr; + int eval_w, eval_h; + int ret; + double res; + const AVPixFmtDescriptor *main_desc; + const AVFilterLink *main_link; + + if (scale2ref) { + main_link = ctx->inputs[0]; + main_desc = av_pix_fmt_desc_get(main_link->format); + } + + 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]; + scale->var_values[VAR_HSUB] = 1 << desc->log2_chroma_w; + scale->var_values[VAR_VSUB] = 1 << desc->log2_chroma_h; + scale->var_values[VAR_OHSUB] = 1 << out_desc->log2_chroma_w; + scale->var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h; + + if (scale2ref) { + 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]; + scale->var_values[VAR_S2R_MAIN_HSUB] = 1 << main_desc->log2_chroma_w; + scale->var_values[VAR_S2R_MAIN_VSUB] = 1 << main_desc->log2_chroma_h; + } + + 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 int config_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -227,37 +488,23 @@ enum AVPixelFormat outfmt = outlink->format; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); ScaleContext *scale = ctx->priv; - int w, h; int ret; - if ((ret = ff_scale_eval_dimensions(ctx, - scale->w_expr, scale->h_expr, - inlink, outlink, - &w, &h)) < 0) + if ((ret = scale_eval_dimensions(ctx)) < 0) goto fail; - /* Note that force_original_aspect_ratio may overwrite the previous set - * dimensions so that it is not divisible by the set factors anymore. */ - if (scale->force_original_aspect_ratio) { - int tmp_w = av_rescale(h, inlink->w, inlink->h); - int tmp_h = av_rescale(w, inlink->h, inlink->w); - - if (scale->force_original_aspect_ratio == 1) { - w = FFMIN(tmp_w, w); - h = FFMIN(tmp_h, h); - } else { - w = FFMAX(tmp_w, w); - h = FFMAX(tmp_h, h); - } - } - - if (w > INT_MAX || h > INT_MAX || - (h * inlink->w) > INT_MAX || - (w * inlink->h) > INT_MAX) + ff_scale_adjust_dimensions(inlink, &scale->w, &scale->h, + scale->force_original_aspect_ratio, + scale->force_divisible_by); + + if (scale->w > INT_MAX || + scale->h > INT_MAX || + (scale->h * inlink->w) > INT_MAX || + (scale->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 = scale->w; + outlink->h = scale->h; /* TODO: make algorithm configurable */ @@ -384,45 +631,81 @@ int in_stride[4],out_stride[4]; int i; - for(i=0; i<4; i++){ + for (i=0; i<4; i++) { int vsub= ((i+1)&2) ? scale->vsub : 0; in_stride[i] = cur_pic->linesize[i] * mul; out_stride[i] = out_buf->linesize[i] * mul; - in[i] = cur_pic->data[i] + ((y>>vsub)+field) * cur_pic->linesize[i]; - out[i] = out_buf->data[i] + field * out_buf->linesize[i]; + in[i] = FF_PTR_ADD(cur_pic->data[i], ((y>>vsub)+field) * cur_pic->linesize[i]); + out[i] = FF_PTR_ADD(out_buf->data[i], field * out_buf->linesize[i]); } - if(scale->input_is_pal) + if (scale->input_is_pal) in[1] = cur_pic->data[1]; - if(scale->output_is_pal) + if (scale->output_is_pal) out[1] = out_buf->data[1]; return sws_scale(sws, in, in_stride, y/mul, h, out,out_stride); } -static int filter_frame(AVFilterLink *link, AVFrame *in) +static int scale_frame(AVFilterLink *link, AVFrame *in, AVFrame **frame_out) { - ScaleContext *scale = link->dst->priv; - AVFilterLink *outlink = link->dst->outputs[0]; + AVFilterContext *ctx = link->dst; + ScaleContext *scale = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); char buf[32]; int in_range; + int frame_changed; + *frame_out = NULL; if (in->colorspace == AVCOL_SPC_YCGCO) av_log(link->dst, AV_LOG_WARNING, "Detected unsupported YCgCo colorspace.\n"); - if( 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) { + 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 (scale->eval_mode == EVAL_MODE_FRAME || frame_changed) { int ret; + unsigned vars_w[VARS_NB] = { 0 }, vars_h[VARS_NB] = { 0 }; + + av_expr_count_vars(scale->w_pexpr, vars_w, VARS_NB); + av_expr_count_vars(scale->h_pexpr, vars_h, VARS_NB); + + if (scale->eval_mode == EVAL_MODE_FRAME && + !frame_changed && + ctx->filter != &ff_vf_scale2ref && + !(vars_w[VAR_N] || vars_w[VAR_T] || vars_w[VAR_POS]) && + !(vars_h[VAR_N] || vars_h[VAR_T] || vars_h[VAR_POS]) && + scale->w && scale->h) + goto scale; if (scale->eval_mode == EVAL_MODE_INIT) { snprintf(buf, sizeof(buf)-1, "%d", outlink->w); av_opt_set(scale, "w", buf, 0); snprintf(buf, sizeof(buf)-1, "%d", outlink->h); av_opt_set(scale, "h", buf, 0); + + ret = scale_parse_expr(ctx, NULL, &scale->w_pexpr, "width", scale->w_expr); + if (ret < 0) + return ret; + + ret = scale_parse_expr(ctx, NULL, &scale->h_pexpr, "height", scale->h_expr); + if (ret < 0) + return ret; + } + + if (ctx->filter == &ff_vf_scale2ref) { + scale->var_values[VAR_S2R_MAIN_N] = link->frame_count_out; + scale->var_values[VAR_S2R_MAIN_T] = TS2T(in->pts, link->time_base); + scale->var_values[VAR_S2R_MAIN_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; + } else { + 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; } link->dst->inputs[0]->format = in->format; @@ -432,13 +715,15 @@ link->dst->inputs[0]->sample_aspect_ratio.den = in->sample_aspect_ratio.den; link->dst->inputs[0]->sample_aspect_ratio.num = in->sample_aspect_ratio.num; - if ((ret = config_props(outlink)) < 0) return ret; } - if (!scale->sws) - return ff_filter_frame(outlink, in); +scale: + if (!scale->sws) { + *frame_out = in; + return 0; + } scale->hsub = desc->log2_chroma_w; scale->vsub = desc->log2_chroma_h; @@ -448,12 +733,13 @@ av_frame_free(&in); return AVERROR(ENOMEM); } + *frame_out = out; av_frame_copy_props(out, in); out->width = outlink->w; out->height = outlink->h; - if(scale->output_is_pal) + if (scale->output_is_pal) avpriv_set_systematic_pal2((uint32_t*)out->data[1], outlink->format == AV_PIX_FMT_PAL8 ? AV_PIX_FMT_BGR8 : outlink->format); in_range = in->color_range; @@ -504,10 +790,10 @@ (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, INT_MAX); - if(scale->interlaced>0 || (scale->interlaced<0 && in->interlaced_frame)){ + if (scale->interlaced>0 || (scale->interlaced<0 && in->interlaced_frame)) { scale_slice(link, out, in, scale->isws[0], 0, (link->h+1)/2, 2, 0); scale_slice(link, out, in, scale->isws[1], 0, link->h /2, 2, 1); - }else if (scale->nb_slices) { + } else if (scale->nb_slices) { int i, slice_h, slice_start, slice_end = 0; const int nb_slices = FFMIN(scale->nb_slices, link->h); for (i = 0; i < nb_slices; i++) { @@ -516,17 +802,55 @@ slice_h = slice_end - slice_start; scale_slice(link, out, in, scale->sws, slice_start, slice_h, 1, 0); } - }else{ + } else { scale_slice(link, out, in, scale->sws, 0, link->h, 1, 0); } av_frame_free(&in); - return ff_filter_frame(outlink, out); + return 0; +} + +static int filter_frame(AVFilterLink *link, AVFrame *in) +{ + AVFilterContext *ctx = link->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + int ret; + + ret = scale_frame(link, in, &out); + if (out) + return ff_filter_frame(outlink, out); + + return ret; } static int filter_frame_ref(AVFilterLink *link, AVFrame *in) { + ScaleContext *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); } @@ -535,39 +859,50 @@ char *res, int res_len, int flags) { ScaleContext *scale = ctx->priv; - int ret; - - if ( !strcmp(cmd, "width") || !strcmp(cmd, "w") - || !strcmp(cmd, "height") || !strcmp(cmd, "h")) { + char *str_expr; + AVExpr **pexpr_ptr; + int ret, w, h; + + w = !strcmp(cmd, "width") || !strcmp(cmd, "w"); + h = !strcmp(cmd, "height") || !strcmp(cmd, "h"); + + if (w || h) { + str_expr = w ? scale->w_expr : scale->h_expr; + pexpr_ptr = w ? &scale->w_pexpr : &scale->h_pexpr; - int old_w = scale->w; - int old_h = scale->h; - AVFilterLink *outlink = ctx->outputs[0]; - - av_opt_set(scale, cmd, args, 0); - if ((ret = config_props(outlink)) < 0) { - scale->w = old_w; - scale->h = old_h; - } + ret = scale_parse_expr(ctx, str_expr, pexpr_ptr, cmd, args); } else ret = AVERROR(ENOSYS); + if (ret < 0) + av_log(ctx, AV_LOG_ERROR, "Failed to process command. Continuing with existing parameters.\n"); + return ret; } +#if FF_API_CHILD_CLASS_NEXT static const AVClass *child_class_next(const AVClass *prev) { return prev ? NULL : sws_get_class(); } +#endif + +static const AVClass *child_class_iterate(void **iter) +{ + const AVClass *c = *iter ? NULL : sws_get_class(); + *iter = (void*)(uintptr_t)c; + return c; +} #define OFFSET(x) offsetof(ScaleContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define TFLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption scale_options[] = { - { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = FLAGS }, - { "width", "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 }, - { "height","Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, + { "width", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, + { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, + { "height","Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, { "flags", "Flags to pass to libswscale", OFFSET(flags_str), AV_OPT_TYPE_STRING, { .str = "bilinear" }, .flags = FLAGS }, { "interl", "set interlacing", OFFSET(interlaced), AV_OPT_TYPE_BOOL, {.i64 = 0 }, -1, 1, FLAGS }, { "size", "set video size", OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, FLAGS }, @@ -600,6 +935,7 @@ { "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 }, { "param0", "Scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, FLAGS }, { "param1", "Scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, FLAGS }, { "nb_slices", "set the number of slices (debug purpose only)", OFFSET(nb_slices), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, @@ -615,7 +951,10 @@ .option = scale_options, .version = LIBAVUTIL_VERSION_INT, .category = AV_CLASS_CATEGORY_FILTER, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = child_class_next, +#endif + .child_class_iterate = child_class_iterate, }; static const AVFilterPad avfilter_vf_scale_inputs[] = { @@ -655,7 +994,10 @@ .option = scale_options, .version = LIBAVUTIL_VERSION_INT, .category = AV_CLASS_CATEGORY_FILTER, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = child_class_next, +#endif + .child_class_iterate = child_class_iterate, }; static const AVFilterPad avfilter_vf_scale2ref_inputs[] = { diff -Nru ffmpeg-4.2.2/libavfilter/vf_scale_cuda_bicubic.cu ffmpeg-4.4/libavfilter/vf_scale_cuda_bicubic.cu --- ffmpeg-4.2.2/libavfilter/vf_scale_cuda_bicubic.cu 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_scale_cuda_bicubic.cu 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,224 @@ +/* + * This file is part of FFmpeg. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "cuda/vector_helpers.cuh" +#include "vf_scale_cuda.h" + +typedef float4 (*coeffs_function_t)(float, float); + +__device__ inline float4 lanczos_coeffs(float x, float param) +{ + const float pi = 3.141592654f; + + float4 res = make_float4( + pi * (x + 1), + pi * x, + pi * (x - 1), + pi * (x - 2)); + + res.x = res.x == 0.0f ? 1.0f : + __sinf(res.x) * __sinf(res.x / 2.0f) / (res.x * res.x / 2.0f); + res.y = res.y == 0.0f ? 1.0f : + __sinf(res.y) * __sinf(res.y / 2.0f) / (res.y * res.y / 2.0f); + res.z = res.z == 0.0f ? 1.0f : + __sinf(res.z) * __sinf(res.z / 2.0f) / (res.z * res.z / 2.0f); + res.w = res.w == 0.0f ? 1.0f : + __sinf(res.w) * __sinf(res.w / 2.0f) / (res.w * res.w / 2.0f); + + return res / (res.x + res.y + res.z + res.w); +} + +__device__ inline float4 bicubic_coeffs(float x, float param) +{ + const float A = param == SCALE_CUDA_PARAM_DEFAULT ? 0.0f : -param; + + float4 res; + res.x = ((A * (x + 1) - 5 * A) * (x + 1) + 8 * A) * (x + 1) - 4 * A; + res.y = ((A + 2) * x - (A + 3)) * x * x + 1; + res.z = ((A + 2) * (1 - x) - (A + 3)) * (1 - x) * (1 - x) + 1; + res.w = 1.0f - res.x - res.y - res.z; + + return res; +} + +__device__ inline void derived_fast_coeffs(float4 coeffs, float x, float *h0, float *h1, float *s) +{ + float g0 = coeffs.x + coeffs.y; + float g1 = coeffs.z + coeffs.w; + + *h0 = coeffs.y / g0 - 0.5f; + *h1 = coeffs.w / g1 + 1.5f; + *s = g0 / (g0 + g1); +} + +template +__device__ inline V apply_coeffs(float4 coeffs, V c0, V c1, V c2, V c3) +{ + V res = c0 * coeffs.x; + res += c1 * coeffs.y; + res += c2 * coeffs.z; + res += c3 * coeffs.w; + + return res; +} + +template +__device__ inline void Subsample_Bicubic(coeffs_function_t coeffs_function, + cudaTextureObject_t src_tex, + T *dst, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int bit_depth, float param) +{ + int xo = blockIdx.x * blockDim.x + threadIdx.x; + int yo = blockIdx.y * blockDim.y + threadIdx.y; + + if (yo < dst_height && xo < dst_width) + { + float hscale = (float)src_width / (float)dst_width; + float vscale = (float)src_height / (float)dst_height; + float xi = (xo + 0.5f) * hscale - 0.5f; + float yi = (yo + 0.5f) * vscale - 0.5f; + float px = floor(xi); + float py = floor(yi); + float fx = xi - px; + float fy = yi - py; + + float factor = bit_depth > 8 ? 0xFFFF : 0xFF; + + float4 coeffsX = coeffs_function(fx, param); + float4 coeffsY = coeffs_function(fy, param); + +#define PIX(x, y) tex2D(src_tex, (x), (y)) + + dst[yo * dst_pitch + xo] = from_floatN( + apply_coeffs(coeffsY, + apply_coeffs(coeffsX, PIX(px - 1, py - 1), PIX(px, py - 1), PIX(px + 1, py - 1), PIX(px + 2, py - 1)), + apply_coeffs(coeffsX, PIX(px - 1, py ), PIX(px, py ), PIX(px + 1, py ), PIX(px + 2, py )), + apply_coeffs(coeffsX, PIX(px - 1, py + 1), PIX(px, py + 1), PIX(px + 1, py + 1), PIX(px + 2, py + 1)), + apply_coeffs(coeffsX, PIX(px - 1, py + 2), PIX(px, py + 2), PIX(px + 1, py + 2), PIX(px + 2, py + 2)) + ) * factor + ); + +#undef PIX + } +} + +/* This does not yield correct results. Most likely because of low internal precision in tex2D linear interpolation */ +template +__device__ inline void Subsample_FastBicubic(coeffs_function_t coeffs_function, + cudaTextureObject_t src_tex, + T *dst, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int bit_depth, float param) +{ + int xo = blockIdx.x * blockDim.x + threadIdx.x; + int yo = blockIdx.y * blockDim.y + threadIdx.y; + + if (yo < dst_height && xo < dst_width) + { + float hscale = (float)src_width / (float)dst_width; + float vscale = (float)src_height / (float)dst_height; + float xi = (xo + 0.5f) * hscale - 0.5f; + float yi = (yo + 0.5f) * vscale - 0.5f; + float px = floor(xi); + float py = floor(yi); + float fx = xi - px; + float fy = yi - py; + + float factor = bit_depth > 8 ? 0xFFFF : 0xFF; + + float4 coeffsX = coeffs_function(fx, param); + float4 coeffsY = coeffs_function(fy, param); + + float h0x, h1x, sx; + float h0y, h1y, sy; + derived_fast_coeffs(coeffsX, fx, &h0x, &h1x, &sx); + derived_fast_coeffs(coeffsY, fy, &h0y, &h1y, &sy); + +#define PIX(x, y) tex2D(src_tex, (x), (y)) + + floatT pix[4] = { + PIX(px + h0x, py + h0y), + PIX(px + h1x, py + h0y), + PIX(px + h0x, py + h1y), + PIX(px + h1x, py + h1y) + }; + +#undef PIX + + dst[yo * dst_pitch + xo] = from_floatN( + lerp_scalar( + lerp_scalar(pix[3], pix[2], sx), + lerp_scalar(pix[1], pix[0], sx), + sy) * factor + ); + } +} + +extern "C" { + +#define BICUBIC_KERNEL(T) \ + __global__ void Subsample_Bicubic_ ## T(cudaTextureObject_t src_tex, \ + T *dst, \ + int dst_width, int dst_height, int dst_pitch, \ + int src_width, int src_height, \ + int bit_depth, float param) \ + { \ + Subsample_Bicubic(&bicubic_coeffs, src_tex, dst, \ + dst_width, dst_height, dst_pitch, \ + src_width, src_height, \ + bit_depth, param); \ + } + +BICUBIC_KERNEL(uchar) +BICUBIC_KERNEL(uchar2) +BICUBIC_KERNEL(uchar4) + +BICUBIC_KERNEL(ushort) +BICUBIC_KERNEL(ushort2) +BICUBIC_KERNEL(ushort4) + + +#define LANCZOS_KERNEL(T) \ + __global__ void Subsample_Lanczos_ ## T(cudaTextureObject_t src_tex, \ + T *dst, \ + int dst_width, int dst_height, int dst_pitch, \ + int src_width, int src_height, \ + int bit_depth, float param) \ + { \ + Subsample_Bicubic(&lanczos_coeffs, src_tex, dst, \ + dst_width, dst_height, dst_pitch, \ + src_width, src_height, \ + bit_depth, param); \ + } + +LANCZOS_KERNEL(uchar) +LANCZOS_KERNEL(uchar2) +LANCZOS_KERNEL(uchar4) + +LANCZOS_KERNEL(ushort) +LANCZOS_KERNEL(ushort2) +LANCZOS_KERNEL(ushort4) + +} diff -Nru ffmpeg-4.2.2/libavfilter/vf_scale_cuda.c ffmpeg-4.4/libavfilter/vf_scale_cuda.c --- ffmpeg-4.2.2/libavfilter/vf_scale_cuda.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_scale_cuda.c 2021-04-08 21:28:40.000000000 +0000 @@ -20,6 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include #include #include @@ -35,9 +36,11 @@ #include "avfilter.h" #include "formats.h" #include "internal.h" -#include "scale.h" +#include "scale_eval.h" #include "video.h" +#include "vf_scale_cuda.h" + static const enum AVPixelFormat supported_formats[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NV12, @@ -45,16 +48,27 @@ AV_PIX_FMT_P010, AV_PIX_FMT_P016, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_0RGB32, + AV_PIX_FMT_0BGR32, }; #define DIV_UP(a, b) ( ((a) + (b) - 1) / (b) ) -#define ALIGN_UP(a, b) (((a) + (b) - 1) & ~((b) - 1)) -#define NUM_BUFFERS 2 #define BLOCKX 32 #define BLOCKY 16 #define CHECK_CU(x) FF_CUDA_CHECK_DL(ctx, s->hwctx->internal->cuda_dl, x) +enum { + INTERP_ALGO_DEFAULT, + + INTERP_ALGO_NEAREST, + INTERP_ALGO_BILINEAR, + INTERP_ALGO_BICUBIC, + INTERP_ALGO_LANCZOS, + + INTERP_ALGO_COUNT +}; + typedef struct CUDAScaleContext { const AVClass *class; @@ -63,11 +77,6 @@ enum AVPixelFormat in_fmt; enum AVPixelFormat out_fmt; - struct { - int width; - int height; - } planes_in[3], planes_out[3]; - AVBufferRef *frames_ctx; AVFrame *frame; @@ -82,6 +91,9 @@ char *w_expr; ///< width expression string char *h_expr; ///< height expression string + int force_original_aspect_ratio; + int force_divisible_by; + CUcontext cu_ctx; CUmodule cu_module; CUfunction cu_func_uchar; @@ -95,6 +107,12 @@ CUdeviceptr srcBuffer; CUdeviceptr dstBuffer; int tex_alignment; + + int interp_algo; + int interp_use_linear; + int interp_as_integer; + + float param; } CUDAScaleContext; static av_cold int cudascale_init(AVFilterContext *ctx) @@ -117,6 +135,16 @@ { CUDAScaleContext *s = ctx->priv; + if (s->hwctx && s->cu_module) { + CudaFunctions *cu = s->hwctx->internal->cuda_dl; + CUcontext dummy; + + CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx)); + CHECK_CU(cu->cuModuleUnload(s->cu_module)); + s->cu_module = NULL; + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + } + av_frame_free(&s->frame); av_buffer_unref(&s->frames_ctx); av_frame_free(&s->tmp_frame); @@ -128,30 +156,17 @@ AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE, }; AVFilterFormats *pix_fmts = ff_make_format_list(pixel_formats); + if (!pix_fmts) + return AVERROR(ENOMEM); return ff_set_common_formats(ctx, pix_fmts); } -static av_cold int init_stage(CUDAScaleContext *s, AVBufferRef *device_ctx) +static av_cold int init_hwframe_ctx(CUDAScaleContext *s, AVBufferRef *device_ctx, int width, int height) { AVBufferRef *out_ref = NULL; AVHWFramesContext *out_ctx; - int in_sw, in_sh, out_sw, out_sh; - int ret, i; - - av_pix_fmt_get_chroma_sub_sample(s->in_fmt, &in_sw, &in_sh); - av_pix_fmt_get_chroma_sub_sample(s->out_fmt, &out_sw, &out_sh); - if (!s->planes_out[0].width) { - s->planes_out[0].width = s->planes_in[0].width; - s->planes_out[0].height = s->planes_in[0].height; - } - - for (i = 1; i < FF_ARRAY_ELEMS(s->planes_in); i++) { - s->planes_in[i].width = s->planes_in[0].width >> in_sw; - s->planes_in[i].height = s->planes_in[0].height >> in_sh; - s->planes_out[i].width = s->planes_out[0].width >> out_sw; - s->planes_out[i].height = s->planes_out[0].height >> out_sh; - } + int ret; out_ref = av_hwframe_ctx_alloc(device_ctx); if (!out_ref) @@ -160,8 +175,8 @@ out_ctx->format = AV_PIX_FMT_CUDA; out_ctx->sw_format = s->out_fmt; - out_ctx->width = FFALIGN(s->planes_out[0].width, 32); - out_ctx->height = FFALIGN(s->planes_out[0].height, 32); + out_ctx->width = FFALIGN(width, 32); + out_ctx->height = FFALIGN(height, 32); ret = av_hwframe_ctx_init(out_ref); if (ret < 0) @@ -172,8 +187,8 @@ if (ret < 0) goto fail; - s->frame->width = s->planes_out[0].width; - s->frame->height = s->planes_out[0].height; + s->frame->width = width; + s->frame->height = height; av_buffer_unref(&s->frames_ctx); s->frames_ctx = out_ref; @@ -225,20 +240,20 @@ return AVERROR(ENOSYS); } - if (in_width == out_width && in_height == out_height) - s->passthrough = 1; - s->in_fmt = in_format; s->out_fmt = out_format; - s->planes_in[0].width = in_width; - s->planes_in[0].height = in_height; - s->planes_out[0].width = out_width; - s->planes_out[0].height = out_height; + if (s->passthrough && in_width == out_width && in_height == out_height && in_format == out_format) { + s->frames_ctx = av_buffer_ref(ctx->inputs[0]->hw_frames_ctx); + if (!s->frames_ctx) + return AVERROR(ENOMEM); + } else { + s->passthrough = 0; - ret = init_stage(s, in_frames_ctx->device_ref); - if (ret < 0) - return ret; + ret = init_hwframe_ctx(s, in_frames_ctx->device_ref, out_width, out_height); + if (ret < 0) + return ret; + } ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->frames_ctx); if (!ctx->outputs[0]->hw_frames_ctx) @@ -256,10 +271,46 @@ AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx; CudaFunctions *cu = device_hwctx->internal->cuda_dl; + char buf[64]; int w, h; int ret; + char *scaler_ptx; + const char *function_infix = ""; + extern char vf_scale_cuda_ptx[]; + extern char vf_scale_cuda_bicubic_ptx[]; + + switch(s->interp_algo) { + case INTERP_ALGO_NEAREST: + scaler_ptx = vf_scale_cuda_ptx; + function_infix = "_Nearest"; + s->interp_use_linear = 0; + s->interp_as_integer = 1; + break; + case INTERP_ALGO_BILINEAR: + scaler_ptx = vf_scale_cuda_ptx; + function_infix = "_Bilinear"; + s->interp_use_linear = 1; + s->interp_as_integer = 1; + break; + case INTERP_ALGO_DEFAULT: + case INTERP_ALGO_BICUBIC: + scaler_ptx = vf_scale_cuda_bicubic_ptx; + function_infix = "_Bicubic"; + s->interp_use_linear = 0; + s->interp_as_integer = 0; + break; + case INTERP_ALGO_LANCZOS: + scaler_ptx = vf_scale_cuda_bicubic_ptx; + function_infix = "_Lanczos"; + s->interp_use_linear = 0; + s->interp_as_integer = 0; + break; + default: + av_log(ctx, AV_LOG_ERROR, "Unknown interpolation algorithm\n"); + return AVERROR_BUG; + } s->hwctx = device_hwctx; s->cu_stream = s->hwctx->stream; @@ -268,31 +319,37 @@ if (ret < 0) goto fail; - ret = CHECK_CU(cu->cuModuleLoadData(&s->cu_module, vf_scale_cuda_ptx)); + ret = CHECK_CU(cu->cuModuleLoadData(&s->cu_module, scaler_ptx)); if (ret < 0) goto fail; - CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_uchar, s->cu_module, "Subsample_Bilinear_uchar")); + snprintf(buf, sizeof(buf), "Subsample%s_uchar", function_infix); + CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_uchar, s->cu_module, buf)); if (ret < 0) goto fail; - CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_uchar2, s->cu_module, "Subsample_Bilinear_uchar2")); + snprintf(buf, sizeof(buf), "Subsample%s_uchar2", function_infix); + CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_uchar2, s->cu_module, buf)); if (ret < 0) goto fail; - CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_uchar4, s->cu_module, "Subsample_Bilinear_uchar4")); + snprintf(buf, sizeof(buf), "Subsample%s_uchar4", function_infix); + CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_uchar4, s->cu_module, buf)); if (ret < 0) goto fail; - CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_ushort, s->cu_module, "Subsample_Bilinear_ushort")); + snprintf(buf, sizeof(buf), "Subsample%s_ushort", function_infix); + CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_ushort, s->cu_module, buf)); if (ret < 0) goto fail; - CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_ushort2, s->cu_module, "Subsample_Bilinear_ushort2")); + snprintf(buf, sizeof(buf), "Subsample%s_ushort2", function_infix); + CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_ushort2, s->cu_module, buf)); if (ret < 0) goto fail; - CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_ushort4, s->cu_module, "Subsample_Bilinear_ushort4")); + snprintf(buf, sizeof(buf), "Subsample%s_ushort4", function_infix); + CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_ushort4, s->cu_module, buf)); if (ret < 0) goto fail; @@ -305,6 +362,9 @@ &w, &h)) < 0) goto fail; + ff_scale_adjust_dimensions(inlink, &w, &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) av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n"); @@ -316,8 +376,8 @@ if (ret < 0) return ret; - av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d -> w:%d h:%d\n", - inlink->w, inlink->h, outlink->w, outlink->h); + av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d -> w:%d h:%d%s\n", + inlink->w, inlink->h, outlink->w, outlink->h, s->passthrough ? " (passthrough)" : ""); if (inlink->sample_aspect_ratio.num) { outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h*inlink->w, @@ -336,18 +396,21 @@ static int call_resize_kernel(AVFilterContext *ctx, CUfunction func, int channels, uint8_t *src_dptr, int src_width, int src_height, int src_pitch, uint8_t *dst_dptr, int dst_width, int dst_height, int dst_pitch, - int pixel_size) + int pixel_size, int bit_depth) { CUDAScaleContext *s = ctx->priv; CudaFunctions *cu = s->hwctx->internal->cuda_dl; CUdeviceptr dst_devptr = (CUdeviceptr)dst_dptr; CUtexObject tex = 0; - void *args_uchar[] = { &tex, &dst_devptr, &dst_width, &dst_height, &dst_pitch, &src_width, &src_height }; + void *args_uchar[] = { &tex, &dst_devptr, &dst_width, &dst_height, &dst_pitch, + &src_width, &src_height, &bit_depth, &s->param }; int ret; CUDA_TEXTURE_DESC tex_desc = { - .filterMode = CU_TR_FILTER_MODE_LINEAR, - .flags = CU_TRSF_READ_AS_INTEGER, + .filterMode = s->interp_use_linear ? + CU_TR_FILTER_MODE_LINEAR : + CU_TR_FILTER_MODE_POINT, + .flags = s->interp_as_integer ? CU_TRSF_READ_AS_INTEGER : 0, }; CUDA_RESOURCE_DESC res_desc = { @@ -358,10 +421,14 @@ .res.pitch2D.numChannels = channels, .res.pitch2D.width = src_width, .res.pitch2D.height = src_height, - .res.pitch2D.pitchInBytes = src_pitch * pixel_size, + .res.pitch2D.pitchInBytes = src_pitch, .res.pitch2D.devPtr = (CUdeviceptr)src_dptr, }; + // Handling of channels is done via vector-types in cuda, so their size is implicitly part of the pitch + // Same for pixel_size, which is represented via datatypes on the cuda side of things. + dst_pitch /= channels * pixel_size; + ret = CHECK_CU(cu->cuTexObjectCreate(&tex, &res_desc, &tex_desc, NULL)); if (ret < 0) goto exit; @@ -388,73 +455,80 @@ call_resize_kernel(ctx, s->cu_func_uchar, 1, in->data[0], in->width, in->height, in->linesize[0], out->data[0], out->width, out->height, out->linesize[0], - 1); + 1, 8); call_resize_kernel(ctx, s->cu_func_uchar, 1, - in->data[1], in->width/2, in->height/2, in->linesize[0]/2, - out->data[1], out->width/2, out->height/2, out->linesize[0]/2, - 1); + in->data[1], in->width / 2, in->height / 2, in->linesize[1], + out->data[1], out->width / 2, out->height / 2, out->linesize[1], + 1, 8); call_resize_kernel(ctx, s->cu_func_uchar, 1, - in->data[2], in->width/2, in->height/2, in->linesize[0]/2, - out->data[2], out->width/2, out->height/2, out->linesize[0]/2, - 1); + in->data[2], in->width / 2, in->height / 2, in->linesize[2], + out->data[2], out->width / 2, out->height / 2, out->linesize[2], + 1, 8); break; case AV_PIX_FMT_YUV444P: call_resize_kernel(ctx, s->cu_func_uchar, 1, in->data[0], in->width, in->height, in->linesize[0], out->data[0], out->width, out->height, out->linesize[0], - 1); + 1, 8); call_resize_kernel(ctx, s->cu_func_uchar, 1, - in->data[1], in->width, in->height, in->linesize[0], - out->data[1], out->width, out->height, out->linesize[0], - 1); + in->data[1], in->width, in->height, in->linesize[1], + out->data[1], out->width, out->height, out->linesize[1], + 1, 8); call_resize_kernel(ctx, s->cu_func_uchar, 1, - in->data[2], in->width, in->height, in->linesize[0], - out->data[2], out->width, out->height, out->linesize[0], - 1); + in->data[2], in->width, in->height, in->linesize[2], + out->data[2], out->width, out->height, out->linesize[2], + 1, 8); break; case AV_PIX_FMT_YUV444P16: call_resize_kernel(ctx, s->cu_func_ushort, 1, - in->data[0], in->width, in->height, in->linesize[0] / 2, - out->data[0], out->width, out->height, out->linesize[0] / 2, - 2); + in->data[0], in->width, in->height, in->linesize[0], + out->data[0], out->width, out->height, out->linesize[0], + 2, 16); call_resize_kernel(ctx, s->cu_func_ushort, 1, - in->data[1], in->width, in->height, in->linesize[1] / 2, - out->data[1], out->width, out->height, out->linesize[1] / 2, - 2); + in->data[1], in->width, in->height, in->linesize[1], + out->data[1], out->width, out->height, out->linesize[1], + 2, 16); call_resize_kernel(ctx, s->cu_func_ushort, 1, - in->data[2], in->width, in->height, in->linesize[2] / 2, - out->data[2], out->width, out->height, out->linesize[2] / 2, - 2); + in->data[2], in->width, in->height, in->linesize[2], + out->data[2], out->width, out->height, out->linesize[2], + 2, 16); break; case AV_PIX_FMT_NV12: call_resize_kernel(ctx, s->cu_func_uchar, 1, in->data[0], in->width, in->height, in->linesize[0], out->data[0], out->width, out->height, out->linesize[0], - 1); + 1, 8); call_resize_kernel(ctx, s->cu_func_uchar2, 2, - in->data[1], in->width/2, in->height/2, in->linesize[1], - out->data[1], out->width/2, out->height/2, out->linesize[1]/2, - 1); + in->data[1], in->width / 2, in->height / 2, in->linesize[1], + out->data[1], out->width / 2, out->height / 2, out->linesize[1], + 1, 8); break; case AV_PIX_FMT_P010LE: call_resize_kernel(ctx, s->cu_func_ushort, 1, - in->data[0], in->width, in->height, in->linesize[0]/2, - out->data[0], out->width, out->height, out->linesize[0]/2, - 2); + in->data[0], in->width, in->height, in->linesize[0], + out->data[0], out->width, out->height, out->linesize[0], + 2, 10); call_resize_kernel(ctx, s->cu_func_ushort2, 2, - in->data[1], in->width / 2, in->height / 2, in->linesize[1]/2, - out->data[1], out->width / 2, out->height / 2, out->linesize[1] / 4, - 2); + in->data[1], in->width / 2, in->height / 2, in->linesize[1], + out->data[1], out->width / 2, out->height / 2, out->linesize[1], + 2, 10); break; case AV_PIX_FMT_P016LE: call_resize_kernel(ctx, s->cu_func_ushort, 1, - in->data[0], in->width, in->height, in->linesize[0] / 2, - out->data[0], out->width, out->height, out->linesize[0] / 2, - 2); + in->data[0], in->width, in->height, in->linesize[0], + out->data[0], out->width, out->height, out->linesize[0], + 2, 16); call_resize_kernel(ctx, s->cu_func_ushort2, 2, - in->data[1], in->width / 2, in->height / 2, in->linesize[1] / 2, - out->data[1], out->width / 2, out->height / 2, out->linesize[1] / 4, - 2); + in->data[1], in->width / 2, in->height / 2, in->linesize[1], + out->data[1], out->width / 2, out->height / 2, out->linesize[1], + 2, 16); + break; + case AV_PIX_FMT_0RGB32: + case AV_PIX_FMT_0BGR32: + call_resize_kernel(ctx, s->cu_func_uchar4, 4, + in->data[0], in->width, in->height, in->linesize[0], + out->data[0], out->width, out->height, out->linesize[0], + 1, 8); break; default: return AVERROR_BUG; @@ -466,6 +540,7 @@ static int cudascale_scale(AVFilterContext *ctx, AVFrame *out, AVFrame *in) { CUDAScaleContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; AVFrame *src = in; int ret; @@ -481,8 +556,8 @@ av_frame_move_ref(out, s->frame); av_frame_move_ref(s->frame, s->tmp_frame); - s->frame->width = s->planes_out[0].width; - s->frame->height = s->planes_out[0].height; + s->frame->width = outlink->w; + s->frame->height = outlink->h; ret = av_frame_copy_props(out, in); if (ret < 0) @@ -502,6 +577,9 @@ CUcontext dummy; int ret = 0; + if (s->passthrough) + return ff_filter_frame(outlink, in); + out = av_frame_alloc(); if (!out) { ret = AVERROR(ENOMEM); @@ -531,11 +609,32 @@ return ret; } +static AVFrame *cudascale_get_video_buffer(AVFilterLink *inlink, int w, int h) +{ + CUDAScaleContext *s = inlink->dst->priv; + + return s->passthrough ? + ff_null_get_video_buffer (inlink, w, h) : + ff_default_get_video_buffer(inlink, w, h); +} + #define OFFSET(x) offsetof(CUDAScaleContext, 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, { .str = "iw" }, .flags = FLAGS }, + { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS }, + { "interp_algo", "Interpolation algorithm used for resizing", OFFSET(interp_algo), AV_OPT_TYPE_INT, { .i64 = INTERP_ALGO_DEFAULT }, 0, INTERP_ALGO_COUNT - 1, FLAGS, "interp_algo" }, + { "nearest", "nearest neighbour", 0, AV_OPT_TYPE_CONST, { .i64 = INTERP_ALGO_NEAREST }, 0, 0, FLAGS, "interp_algo" }, + { "bilinear", "bilinear", 0, AV_OPT_TYPE_CONST, { .i64 = INTERP_ALGO_BILINEAR }, 0, 0, FLAGS, "interp_algo" }, + { "bicubic", "bicubic", 0, AV_OPT_TYPE_CONST, { .i64 = INTERP_ALGO_BICUBIC }, 0, 0, FLAGS, "interp_algo" }, + { "lanczos", "lanczos", 0, AV_OPT_TYPE_CONST, { .i64 = INTERP_ALGO_LANCZOS }, 0, 0, FLAGS, "interp_algo" }, + { "passthrough", "Do not process frames at all if parameters match", OFFSET(passthrough), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS }, + { "param", "Algorithm-Specific parameter", OFFSET(param), AV_OPT_TYPE_FLOAT, { .dbl = SCALE_CUDA_PARAM_DEFAULT }, -FLT_MAX, FLT_MAX, FLAGS }, + { "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 }, { NULL }, }; @@ -551,6 +650,7 @@ .name = "default", .type = AVMEDIA_TYPE_VIDEO, .filter_frame = cudascale_filter_frame, + .get_video_buffer = cudascale_get_video_buffer, }, { NULL } }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_scale_cuda.cu ffmpeg-4.4/libavfilter/vf_scale_cuda.cu --- ffmpeg-4.2.2/libavfilter/vf_scale_cuda.cu 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_scale_cuda.cu 2021-04-08 21:28:40.000000000 +0000 @@ -20,40 +20,14 @@ * DEALINGS IN THE SOFTWARE. */ -extern "C" { - -__global__ void Subsample_Bilinear_uchar(cudaTextureObject_t uchar_tex, - unsigned char *dst, - int dst_width, int dst_height, int dst_pitch, - int src_width, int src_height) -{ - int xo = blockIdx.x * blockDim.x + threadIdx.x; - int yo = blockIdx.y * blockDim.y + threadIdx.y; - - if (yo < dst_height && xo < dst_width) - { - float hscale = (float)src_width / (float)dst_width; - float vscale = (float)src_height / (float)dst_height; - float xi = (xo + 0.5f) * hscale; - float yi = (yo + 0.5f) * vscale; - // 3-tap filter weights are {wh,1.0,wh} and {wv,1.0,wv} - float wh = min(max(0.5f * (hscale - 1.0f), 0.0f), 1.0f); - float wv = min(max(0.5f * (vscale - 1.0f), 0.0f), 1.0f); - // Convert weights to two bilinear weights -> {wh,1.0,wh} -> {wh,0.5,0} + {0,0.5,wh} - float dx = wh / (0.5f + wh); - float dy = wv / (0.5f + wv); - int y0 = tex2D(uchar_tex, xi-dx, yi-dy); - int y1 = tex2D(uchar_tex, xi+dx, yi-dy); - int y2 = tex2D(uchar_tex, xi-dx, yi+dy); - int y3 = tex2D(uchar_tex, xi+dx, yi+dy); - dst[yo*dst_pitch+xo] = (unsigned char)((y0+y1+y2+y3+2) >> 2); - } -} +#include "cuda/vector_helpers.cuh" -__global__ void Subsample_Bilinear_uchar2(cudaTextureObject_t uchar2_tex, - uchar2 *dst, - int dst_width, int dst_height, int dst_pitch2, - int src_width, int src_height) +template +__device__ inline void Subsample_Nearest(cudaTextureObject_t tex, + T *dst, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int bit_depth) { int xo = blockIdx.x * blockDim.x + threadIdx.x; int yo = blockIdx.y * blockDim.y + threadIdx.y; @@ -64,61 +38,17 @@ float vscale = (float)src_height / (float)dst_height; float xi = (xo + 0.5f) * hscale; float yi = (yo + 0.5f) * vscale; - // 3-tap filter weights are {wh,1.0,wh} and {wv,1.0,wv} - float wh = min(max(0.5f * (hscale - 1.0f), 0.0f), 1.0f); - float wv = min(max(0.5f * (vscale - 1.0f), 0.0f), 1.0f); - // Convert weights to two bilinear weights -> {wh,1.0,wh} -> {wh,0.5,0} + {0,0.5,wh} - float dx = wh / (0.5f + wh); - float dy = wv / (0.5f + wv); - uchar2 c0 = tex2D(uchar2_tex, xi-dx, yi-dy); - uchar2 c1 = tex2D(uchar2_tex, xi+dx, yi-dy); - uchar2 c2 = tex2D(uchar2_tex, xi-dx, yi+dy); - uchar2 c3 = tex2D(uchar2_tex, xi+dx, yi+dy); - int2 uv; - uv.x = ((int)c0.x+(int)c1.x+(int)c2.x+(int)c3.x+2) >> 2; - uv.y = ((int)c0.y+(int)c1.y+(int)c2.y+(int)c3.y+2) >> 2; - dst[yo*dst_pitch2+xo] = make_uchar2((unsigned char)uv.x, (unsigned char)uv.y); - } -} - -__global__ void Subsample_Bilinear_uchar4(cudaTextureObject_t uchar4_tex, - uchar4 *dst, - int dst_width, int dst_height, int dst_pitch, - int src_width, int src_height) -{ - int xo = blockIdx.x * blockDim.x + threadIdx.x; - int yo = blockIdx.y * blockDim.y + threadIdx.y; - if (yo < dst_height && xo < dst_width) - { - float hscale = (float)src_width / (float)dst_width; - float vscale = (float)src_height / (float)dst_height; - float xi = (xo + 0.5f) * hscale; - float yi = (yo + 0.5f) * vscale; - // 3-tap filter weights are {wh,1.0,wh} and {wv,1.0,wv} - float wh = min(max(0.5f * (hscale - 1.0f), 0.0f), 1.0f); - float wv = min(max(0.5f * (vscale - 1.0f), 0.0f), 1.0f); - // Convert weights to two bilinear weights -> {wh,1.0,wh} -> {wh,0.5,0} + {0,0.5,wh} - float dx = wh / (0.5f + wh); - float dy = wv / (0.5f + wv); - uchar4 c0 = tex2D(uchar4_tex, xi-dx, yi-dy); - uchar4 c1 = tex2D(uchar4_tex, xi+dx, yi-dy); - uchar4 c2 = tex2D(uchar4_tex, xi-dx, yi+dy); - uchar4 c3 = tex2D(uchar4_tex, xi+dx, yi+dy); - int4 res; - res.x = ((int)c0.x+(int)c1.x+(int)c2.x+(int)c3.x+2) >> 2; - res.y = ((int)c0.y+(int)c1.y+(int)c2.y+(int)c3.y+2) >> 2; - res.z = ((int)c0.z+(int)c1.z+(int)c2.z+(int)c3.z+2) >> 2; - res.w = ((int)c0.w+(int)c1.w+(int)c2.w+(int)c3.w+2) >> 2; - dst[yo*dst_pitch+xo] = make_uchar4( - (unsigned char)res.x, (unsigned char)res.y, (unsigned char)res.z, (unsigned char)res.w); + dst[yo*dst_pitch+xo] = tex2D(tex, xi, yi); } } -__global__ void Subsample_Bilinear_ushort(cudaTextureObject_t ushort_tex, - unsigned short *dst, - int dst_width, int dst_height, int dst_pitch, - int src_width, int src_height) +template +__device__ inline void Subsample_Bilinear(cudaTextureObject_t tex, + T *dst, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int bit_depth) { int xo = blockIdx.x * blockDim.x + threadIdx.x; int yo = blockIdx.y * blockDim.y + threadIdx.y; @@ -135,77 +65,59 @@ // Convert weights to two bilinear weights -> {wh,1.0,wh} -> {wh,0.5,0} + {0,0.5,wh} float dx = wh / (0.5f + wh); float dy = wv / (0.5f + wv); - int y0 = tex2D(ushort_tex, xi-dx, yi-dy); - int y1 = tex2D(ushort_tex, xi+dx, yi-dy); - int y2 = tex2D(ushort_tex, xi-dx, yi+dy); - int y3 = tex2D(ushort_tex, xi+dx, yi+dy); - dst[yo*dst_pitch+xo] = (unsigned short)((y0+y1+y2+y3+2) >> 2); - } -} - -__global__ void Subsample_Bilinear_ushort2(cudaTextureObject_t ushort2_tex, - ushort2 *dst, - int dst_width, int dst_height, int dst_pitch2, - int src_width, int src_height) -{ - int xo = blockIdx.x * blockDim.x + threadIdx.x; - int yo = blockIdx.y * blockDim.y + threadIdx.y; - if (yo < dst_height && xo < dst_width) - { - float hscale = (float)src_width / (float)dst_width; - float vscale = (float)src_height / (float)dst_height; - float xi = (xo + 0.5f) * hscale; - float yi = (yo + 0.5f) * vscale; - // 3-tap filter weights are {wh,1.0,wh} and {wv,1.0,wv} - float wh = min(max(0.5f * (hscale - 1.0f), 0.0f), 1.0f); - float wv = min(max(0.5f * (vscale - 1.0f), 0.0f), 1.0f); - // Convert weights to two bilinear weights -> {wh,1.0,wh} -> {wh,0.5,0} + {0,0.5,wh} - float dx = wh / (0.5f + wh); - float dy = wv / (0.5f + wv); - ushort2 c0 = tex2D(ushort2_tex, xi-dx, yi-dy); - ushort2 c1 = tex2D(ushort2_tex, xi+dx, yi-dy); - ushort2 c2 = tex2D(ushort2_tex, xi-dx, yi+dy); - ushort2 c3 = tex2D(ushort2_tex, xi+dx, yi+dy); - int2 uv; - uv.x = ((int)c0.x+(int)c1.x+(int)c2.x+(int)c3.x+2) >> 2; - uv.y = ((int)c0.y+(int)c1.y+(int)c2.y+(int)c3.y+2) >> 2; - dst[yo*dst_pitch2+xo] = make_ushort2((unsigned short)uv.x, (unsigned short)uv.y); + intT r = { 0 }; + vec_set_scalar(r, 2); + r += tex2D(tex, xi - dx, yi - dy); + r += tex2D(tex, xi + dx, yi - dy); + r += tex2D(tex, xi - dx, yi + dy); + r += tex2D(tex, xi + dx, yi + dy); + vec_set(dst[yo*dst_pitch+xo], r >> 2); } } -__global__ void Subsample_Bilinear_ushort4(cudaTextureObject_t ushort4_tex, - ushort4 *dst, - int dst_width, int dst_height, int dst_pitch, - int src_width, int src_height) -{ - int xo = blockIdx.x * blockDim.x + threadIdx.x; - int yo = blockIdx.y * blockDim.y + threadIdx.y; +extern "C" { - if (yo < dst_height && xo < dst_width) - { - float hscale = (float)src_width / (float)dst_width; - float vscale = (float)src_height / (float)dst_height; - float xi = (xo + 0.5f) * hscale; - float yi = (yo + 0.5f) * vscale; - // 3-tap filter weights are {wh,1.0,wh} and {wv,1.0,wv} - float wh = min(max(0.5f * (hscale - 1.0f), 0.0f), 1.0f); - float wv = min(max(0.5f * (vscale - 1.0f), 0.0f), 1.0f); - // Convert weights to two bilinear weights -> {wh,1.0,wh} -> {wh,0.5,0} + {0,0.5,wh} - float dx = wh / (0.5f + wh); - float dy = wv / (0.5f + wv); - ushort4 c0 = tex2D(ushort4_tex, xi-dx, yi-dy); - ushort4 c1 = tex2D(ushort4_tex, xi+dx, yi-dy); - ushort4 c2 = tex2D(ushort4_tex, xi-dx, yi+dy); - ushort4 c3 = tex2D(ushort4_tex, xi+dx, yi+dy); - int4 res; - res.x = ((int)c0.x+(int)c1.x+(int)c2.x+(int)c3.x+2) >> 2; - res.y = ((int)c0.y+(int)c1.y+(int)c2.y+(int)c3.y+2) >> 2; - res.z = ((int)c0.z+(int)c1.z+(int)c2.z+(int)c3.z+2) >> 2; - res.w = ((int)c0.w+(int)c1.w+(int)c2.w+(int)c3.w+2) >> 2; - dst[yo*dst_pitch+xo] = make_ushort4( - (unsigned short)res.x, (unsigned short)res.y, (unsigned short)res.z, (unsigned short)res.w); - } -} +#define NEAREST_KERNEL(T) \ + __global__ void Subsample_Nearest_ ## T(cudaTextureObject_t src_tex, \ + T *dst, \ + int dst_width, int dst_height, int dst_pitch, \ + int src_width, int src_height, \ + int bit_depth) \ + { \ + Subsample_Nearest(src_tex, dst, \ + dst_width, dst_height, dst_pitch, \ + src_width, src_height, \ + bit_depth); \ + } + +NEAREST_KERNEL(uchar) +NEAREST_KERNEL(uchar2) +NEAREST_KERNEL(uchar4) + +NEAREST_KERNEL(ushort) +NEAREST_KERNEL(ushort2) +NEAREST_KERNEL(ushort4) + +#define BILINEAR_KERNEL(T) \ + __global__ void Subsample_Bilinear_ ## T(cudaTextureObject_t src_tex, \ + T *dst, \ + int dst_width, int dst_height, int dst_pitch, \ + int src_width, int src_height, \ + int bit_depth) \ + { \ + Subsample_Bilinear(src_tex, dst, \ + dst_width, dst_height, dst_pitch, \ + src_width, src_height, \ + bit_depth); \ + } + +BILINEAR_KERNEL(uchar) +BILINEAR_KERNEL(uchar2) +BILINEAR_KERNEL(uchar4) + +BILINEAR_KERNEL(ushort) +BILINEAR_KERNEL(ushort2) +BILINEAR_KERNEL(ushort4) } diff -Nru ffmpeg-4.2.2/libavfilter/vf_scale_cuda.h ffmpeg-4.4/libavfilter/vf_scale_cuda.h --- ffmpeg-4.2.2/libavfilter/vf_scale_cuda.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_scale_cuda.h 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,28 @@ +/* + * This file is part of FFmpeg. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef AVFILTER_SCALE_CUDA_H +#define AVFILTER_SCALE_CUDA_H + +#define SCALE_CUDA_PARAM_DEFAULT 999999.0f + +#endif diff -Nru ffmpeg-4.2.2/libavfilter/vf_scale_npp.c ffmpeg-4.4/libavfilter/vf_scale_npp.c --- ffmpeg-4.2.2/libavfilter/vf_scale_npp.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_scale_npp.c 2020-07-11 10:39:30.000000000 +0000 @@ -37,7 +37,7 @@ #include "avfilter.h" #include "formats.h" #include "internal.h" -#include "scale.h" +#include "scale_eval.h" #include "video.h" #define CHECK_CU(x) FF_CUDA_CHECK_DL(ctx, device_hwctx->internal->cuda_dl, x) @@ -98,6 +98,9 @@ char *h_expr; ///< height expression string char *format_str; + int force_original_aspect_ratio; + int force_divisible_by; + int interp_algo; } NPPScaleContext; @@ -347,6 +350,9 @@ &w, &h)) < 0) goto fail; + ff_scale_adjust_dimensions(inlink, &w, &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) av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n"); @@ -552,6 +558,11 @@ { "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" }, + { "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 }, { NULL }, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_scale_qsv.c ffmpeg-4.4/libavfilter/vf_scale_qsv.c --- ffmpeg-4.2.2/libavfilter/vf_scale_qsv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_scale_qsv.c 2021-04-08 21:28:40.000000000 +0000 @@ -201,8 +201,8 @@ out_frames_hwctx = out_frames_ctx->hwctx; out_frames_ctx->format = AV_PIX_FMT_QSV; - out_frames_ctx->width = FFALIGN(out_width, 32); - out_frames_ctx->height = FFALIGN(out_height, 32); + out_frames_ctx->width = FFALIGN(out_width, 16); + out_frames_ctx->height = FFALIGN(out_height, 16); out_frames_ctx->sw_format = out_format; out_frames_ctx->initial_pool_size = 4; @@ -313,8 +313,10 @@ } } - if (err != MFX_ERR_NONE) { - av_log(ctx, AV_LOG_ERROR, "Error getting the session handle\n"); + if (err < 0) + return ff_qsvvpp_print_error(ctx, err, "Error getting the session handle"); + else if (err > 0) { + ff_qsvvpp_print_warning(ctx, err, "Warning in getting the session handle"); return AVERROR_UNKNOWN; } @@ -410,7 +412,7 @@ s->scale_conf.Header.BufferSz = sizeof(mfxExtVPPScaling); s->scale_conf.ScalingMode = s->mode; s->ext_buffers[s->num_ext_buf++] = (mfxExtBuffer*)&s->scale_conf; - av_log(ctx, AV_LOG_VERBOSE, "Scaling mode: %"PRIu16"\n", s->mode); + av_log(ctx, AV_LOG_VERBOSE, "Scaling mode: %d\n", s->mode); #endif par.ExtParam = s->ext_buffers; @@ -430,9 +432,17 @@ par.vpp.Out.FrameRateExtN = 25; par.vpp.Out.FrameRateExtD = 1; + /* Print input memory mode */ + ff_qsvvpp_print_iopattern(ctx, par.IOPattern & 0x0F, "VPP"); + /* Print output memory mode */ + ff_qsvvpp_print_iopattern(ctx, par.IOPattern & 0xF0, "VPP"); err = MFXVideoVPP_Init(s->session, &par); - if (err != MFX_ERR_NONE) { - av_log(ctx, AV_LOG_ERROR, "Error opening the VPP for scaling\n"); + if (err < 0) + return ff_qsvvpp_print_error(ctx, err, + "Error opening the VPP for scaling"); + else if (err > 0) { + ff_qsvvpp_print_warning(ctx, err, + "Warning in VPP initialization"); return AVERROR_UNKNOWN; } @@ -541,7 +551,7 @@ return 0; fail: - av_log(NULL, AV_LOG_ERROR, + av_log(ctx, AV_LOG_ERROR, "Error when evaluating the expression '%s'\n", expr); return ret; } @@ -573,8 +583,13 @@ av_usleep(1); } while (err == MFX_WRN_DEVICE_BUSY); - if (err < 0 || !sync) { - av_log(ctx, AV_LOG_ERROR, "Error during scaling\n"); + if (err < 0) { + ret = ff_qsvvpp_print_error(ctx, err, "Error during scaling"); + goto fail; + } + + if (!sync) { + av_log(ctx, AV_LOG_ERROR, "No sync during scaling\n"); ret = AVERROR_UNKNOWN; goto fail; } @@ -583,8 +598,7 @@ err = MFXVideoCORE_SyncOperation(s->session, sync, 1000); } while (err == MFX_WRN_IN_EXECUTION); if (err < 0) { - av_log(ctx, AV_LOG_ERROR, "Error synchronizing the operation: %d\n", err); - ret = AVERROR_UNKNOWN; + ret = ff_qsvvpp_print_error(ctx, err, "Error synchronizing the operation"); goto fail; } @@ -629,7 +643,7 @@ }; static const AVClass qsvscale_class = { - .class_name = "qsvscale", + .class_name = "scale_qsv", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, diff -Nru ffmpeg-4.2.2/libavfilter/vf_scale_vaapi.c ffmpeg-4.4/libavfilter/vf_scale_vaapi.c --- ffmpeg-4.2.2/libavfilter/vf_scale_vaapi.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_scale_vaapi.c 2020-07-11 10:39:30.000000000 +0000 @@ -26,7 +26,7 @@ #include "avfilter.h" #include "formats.h" #include "internal.h" -#include "scale.h" +#include "scale_eval.h" #include "video.h" #include "vaapi_vpp.h" @@ -40,6 +40,9 @@ char *w_expr; // width expression string char *h_expr; // height expression string + int force_original_aspect_ratio; + int force_divisible_by; + char *colour_primaries_string; char *colour_transfer_string; char *colour_matrix_string; @@ -81,6 +84,9 @@ &vpp_ctx->output_width, &vpp_ctx->output_height)) < 0) return err; + ff_scale_adjust_dimensions(inlink, &vpp_ctx->output_width, &vpp_ctx->output_height, + ctx->force_original_aspect_ratio, ctx->force_divisible_by); + err = ff_vaapi_vpp_config_output(outlink); if (err < 0) return err; @@ -119,7 +125,7 @@ err = av_frame_copy_props(output_frame, input_frame); if (err < 0) - return err; + goto fail; if (ctx->colour_primaries != AVCOL_PRI_UNSPECIFIED) output_frame->color_primaries = ctx->colour_primaries; @@ -247,6 +253,11 @@ { "out_chroma_location", "Output chroma sample location", OFFSET(chroma_location_string), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, + { "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 }, { NULL }, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_scale_vulkan.c ffmpeg-4.4/libavfilter/vf_scale_vulkan.c --- ffmpeg-4.2.2/libavfilter/vf_scale_vulkan.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_scale_vulkan.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,538 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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.h" +#include "scale_eval.h" +#include "internal.h" +#include "colorspace.h" + +#define CGROUPS (int [3]){ 32, 32, 1 } + +enum ScalerFunc { + F_BILINEAR = 0, + F_NEAREST, + + F_NB, +}; + +typedef struct ScaleVulkanContext { + VulkanFilterContext vkctx; + + int initialized; + FFVkExecContext *exec; + VulkanPipeline *pl; + FFVkBuffer params_buf; + + /* Shader updators, must be in the main filter struct */ + VkDescriptorImageInfo input_images[3]; + VkDescriptorImageInfo output_images[3]; + VkDescriptorBufferInfo params_desc; + + enum ScalerFunc scaler; + char *out_format_string; + enum AVColorRange out_range; + char *w_expr; + char *h_expr; +} ScaleVulkanContext; + +static const char scale_bilinear[] = { + C(0, vec4 scale_bilinear(int idx, ivec2 pos, vec2 crop_range, vec2 crop_off)) + C(0, { ) + C(1, vec2 npos = (vec2(pos) + 0.5f) / imageSize(output_img[idx]); ) + C(1, npos *= crop_range; /* Reduce the range */ ) + C(1, npos += crop_off; /* Offset the start */ ) + C(1, return texture(input_img[idx], npos); ) + C(0, } ) +}; + +static const char rgb2yuv[] = { + C(0, vec4 rgb2yuv(vec4 src, int fullrange) ) + C(0, { ) + C(1, src *= yuv_matrix; ) + C(1, if (fullrange == 1) { ) + C(2, src += vec4(0.0, 0.5, 0.5, 0.0); ) + C(1, } else { ) + C(2, src *= vec4(219.0 / 255.0, 224.0 / 255.0, 224.0 / 255.0, 1.0); ) + C(2, src += vec4(16.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0, 0.0); ) + C(1, } ) + C(1, return src; ) + C(0, } ) +}; + +static const char write_nv12[] = { + C(0, void write_nv12(vec4 src, ivec2 pos) ) + C(0, { ) + C(1, imageStore(output_img[0], pos, vec4(src.r, 0.0, 0.0, 0.0)); ) + C(1, pos /= ivec2(2); ) + C(1, imageStore(output_img[1], pos, vec4(src.g, src.b, 0.0, 0.0)); ) + C(0, } ) +}; + +static const char write_420[] = { + C(0, void write_420(vec4 src, ivec2 pos) ) + C(0, { ) + C(1, imageStore(output_img[0], pos, vec4(src.r, 0.0, 0.0, 0.0)); ) + C(1, pos /= ivec2(2); ) + C(1, imageStore(output_img[1], pos, vec4(src.g, 0.0, 0.0, 0.0)); ) + C(1, imageStore(output_img[2], pos, vec4(src.b, 0.0, 0.0, 0.0)); ) + C(0, } ) +}; + +static const char write_444[] = { + C(0, void write_444(vec4 src, ivec2 pos) ) + C(0, { ) + C(1, imageStore(output_img[0], pos, vec4(src.r, 0.0, 0.0, 0.0)); ) + C(1, imageStore(output_img[1], pos, vec4(src.g, 0.0, 0.0, 0.0)); ) + C(1, imageStore(output_img[2], pos, vec4(src.b, 0.0, 0.0, 0.0)); ) + C(0, } ) +}; + +static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) +{ + int err; + VkSampler *sampler; + VkFilter sampler_mode; + ScaleVulkanContext *s = ctx->priv; + + 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); + + 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; + + switch (s->scaler) { + case F_NEAREST: + sampler_mode = VK_FILTER_NEAREST; + break; + case F_BILINEAR: + sampler_mode = VK_FILTER_LINEAR; + break; + }; + + /* Create a sampler */ + sampler = ff_vk_init_sampler(ctx, 0, sampler_mode); + if (!sampler) + return AVERROR_EXTERNAL; + + s->pl = ff_vk_create_pipeline(ctx); + if (!s->pl) + return AVERROR(ENOMEM); + + { /* Create the shader */ + VulkanDescriptorSetBinding 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), + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->input_images, + .samplers = DUP_SAMPLER_ARRAY4(*sampler), + }, + { + .name = "output_img", + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format), + .mem_quali = "writeonly", + .dimensions = 2, + .elems = av_pix_fmt_count_planes(s->vkctx.output_format), + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->output_images, + }, + }; + + VulkanDescriptorSetBinding desc_b = { + .name = "params", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .mem_quali = "readonly", + .mem_layout = "std430", + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = &s->params_desc, + .buf_content = "mat4 yuv_matrix;", + }; + + SPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "scale_compute", + VK_SHADER_STAGE_COMPUTE_BIT); + if (!shd) + return AVERROR(ENOMEM); + + ff_vk_set_compute_shader_sizes(ctx, 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 */ + + GLSLD( scale_bilinear ); + + if (s->vkctx.output_format != s->vkctx.input_format) { + GLSLD( rgb2yuv ); + } + + switch (s->vkctx.output_format) { + case AV_PIX_FMT_NV12: GLSLD(write_nv12); break; + case AV_PIX_FMT_YUV420P: GLSLD( write_420); break; + case AV_PIX_FMT_YUV444P: GLSLD( write_444); break; + default: break; + } + + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + GLSLF(1, vec2 in_d = vec2(%i, %i); ,in->width, in->height); + GLSLF(1, vec2 c_r = vec2(%i, %i) / in_d; ,crop_w, crop_h); + GLSLF(1, vec2 c_o = vec2(%i, %i) / in_d; ,crop_x,crop_y); + GLSLC(0, ); + + if (s->vkctx.output_format == s->vkctx.input_format) { + for (int i = 0; i < desc_i[1].elems; i++) { + GLSLF(1, size = imageSize(output_img[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + switch (s->scaler) { + case F_NEAREST: + case F_BILINEAR: + GLSLF(2, vec4 res = scale_bilinear(%i, pos, c_r, c_o); ,i); + GLSLF(2, imageStore(output_img[%i], pos, res); ,i); + break; + }; + GLSLC(1, } ); + } + } else { + GLSLC(1, vec4 res = scale_bilinear(0, pos, c_r, c_o); ); + GLSLF(1, res = rgb2yuv(res, %i); ,s->out_range == AVCOL_RANGE_JPEG); + switch (s->vkctx.output_format) { + case AV_PIX_FMT_NV12: GLSLC(1, write_nv12(res, pos); ); break; + case AV_PIX_FMT_YUV420P: GLSLC(1, write_420(res, pos); ); break; + case AV_PIX_FMT_YUV444P: GLSLC(1, write_444(res, pos); ); break; + default: return AVERROR(EINVAL); + } + } + + GLSLC(0, } ); + + RET(ff_vk_compile_shader(ctx, shd, "main")); + } + + RET(ff_vk_init_pipeline_layout(ctx, s->pl)); + RET(ff_vk_init_compute_pipeline(ctx, s->pl)); + + if (s->vkctx.output_format != s->vkctx.input_format) { + const struct LumaCoefficients *lcoeffs; + double tmp_mat[3][3]; + + struct { + float yuv_matrix[4][4]; + } *par; + + lcoeffs = ff_get_luma_coefficients(in->colorspace); + if (!lcoeffs) { + av_log(ctx, AV_LOG_ERROR, "Unsupported colorspace\n"); + return AVERROR(EINVAL); + } + + err = ff_vk_create_buf(ctx, &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); + if (err) + return err; + + ff_fill_rgb2yuv_table(lcoeffs, tmp_mat); + + memset(par, 0, sizeof(*par)); + + for (int y = 0; y < 3; y++) + for (int x = 0; x < 3; x++) + par->yuv_matrix[x][y] = tmp_mat[x][y]; + + par->yuv_matrix[3][3] = 1.0; + + err = ff_vk_unmap_buffers(ctx, &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); + } + + /* Execution context */ + RET(ff_vk_create_exec_ctx(ctx, &s->exec)); + + s->initialized = 1; + + return 0; + +fail: + return err; +} + +static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) +{ + int err = 0; + VkCommandBuffer cmd_buf; + ScaleVulkanContext *s = avctx->priv; + 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; + + /* 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); + + 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], + 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); + + for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.input_format); i++) { + VkImageMemoryBarrier bar = { + .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, + }; + + memcpy(&barriers[barrier_count++], &bar, sizeof(VkImageMemoryBarrier)); + + in->layout[i] = bar.newLayout; + in->access[i] = bar.dstAccessMask; + } + + for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.output_format); i++) { + VkImageMemoryBarrier bar = { + .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, + }; + + memcpy(&barriers[barrier_count++], &bar, sizeof(VkImageMemoryBarrier)); + + out->layout[i] = bar.newLayout; + 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); + + ff_vk_bind_pipeline_exec(avctx, 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); + + 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); + + err = ff_vk_submit_exec_queue(avctx, s->exec); + if (err) + return err; + + return err; + +fail: + ff_vk_discard_exec_deps(avctx, s->exec); + return err; +} + +static int scale_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + int err; + AVFilterContext *ctx = link->dst; + ScaleVulkanContext *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; + } + + if (!s->initialized) + RET(init_filter(ctx, in)); + + RET(process_frames(ctx, out, in)); + + err = av_frame_copy_props(out, in); + if (err < 0) + goto fail; + + if (s->out_range != AVCOL_RANGE_UNSPECIFIED) + out->color_range = s->out_range; + if (s->vkctx.output_format != s->vkctx.input_format) + out->chroma_location = AVCHROMA_LOC_TOPLEFT; + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return err; +} + +static int scale_vulkan_config_output(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + ScaleVulkanContext *s = avctx->priv; + 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); + if (err < 0) + return err; + + 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 { + s->vkctx.output_format = s->vkctx.input_format; + } + + if (s->vkctx.output_format != s->vkctx.input_format) { + if (!ff_vk_mt_is_np_rgb(s->vkctx.input_format)) { + av_log(avctx, AV_LOG_ERROR, "Unsupported input format for conversion\n"); + return AVERROR(EINVAL); + } + if (s->vkctx.output_format != AV_PIX_FMT_NV12 && + s->vkctx.output_format != AV_PIX_FMT_YUV420P && + s->vkctx.output_format != AV_PIX_FMT_YUV444P) { + av_log(avctx, AV_LOG_ERROR, "Unsupported output format\n"); + return AVERROR(EINVAL); + } + } else if (s->out_range != AVCOL_RANGE_UNSPECIFIED) { + av_log(avctx, AV_LOG_ERROR, "Cannot change range without converting format\n"); + return AVERROR(EINVAL); + } + + err = ff_vk_filter_config_output(outlink); + if (err < 0) + return err; + + return 0; +} + +static void scale_vulkan_uninit(AVFilterContext *avctx) +{ + ScaleVulkanContext *s = avctx->priv; + + ff_vk_filter_uninit(avctx); + ff_vk_free_buf(avctx, &s->params_buf); + + s->initialized = 0; +} + +#define OFFSET(x) offsetof(ScaleVulkanContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption scale_vulkan_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 }, + { "scaler", "Scaler function", OFFSET(scaler), AV_OPT_TYPE_INT, {.i64 = F_BILINEAR}, 0, F_NB, .flags = FLAGS, "scaler" }, + { "bilinear", "Bilinear interpolation (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = F_BILINEAR}, 0, 0, .flags = FLAGS, "scaler" }, + { "nearest", "Nearest (useful for pixel art)", 0, AV_OPT_TYPE_CONST, {.i64 = F_NEAREST}, 0, 0, .flags = FLAGS, "scaler" }, + { "format", "Output video format (software format of hardware frames)", OFFSET(out_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { "out_range", "Output colour range (from 0 to 2) (default 0)", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED}, AVCOL_RANGE_UNSPECIFIED, AVCOL_RANGE_JPEG, .flags = FLAGS, "range" }, + { "full", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" }, + { "limited", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" }, + { "jpeg", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" }, + { "mpeg", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" }, + { "tv", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" }, + { "pc", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(scale_vulkan); + +static const AVFilterPad scale_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &scale_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + }, + { NULL } +}; + +static const AVFilterPad scale_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &scale_vulkan_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_scale_vulkan = { + .name = "scale_vulkan", + .description = NULL_IF_CONFIG_SMALL("Scale Vulkan frames"), + .priv_size = sizeof(ScaleVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &scale_vulkan_uninit, + .query_formats = &ff_vk_filter_query_formats, + .inputs = scale_vulkan_inputs, + .outputs = scale_vulkan_outputs, + .priv_class = &scale_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_scdet.c ffmpeg-4.4/libavfilter/vf_scdet.c --- ffmpeg-4.2.2/libavfilter/vf_scdet.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_scdet.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,224 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * video scene change detection filter + */ + +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/timestamp.h" + +#include "avfilter.h" +#include "filters.h" +#include "scene_sad.h" + +typedef struct SCDetContext { + const AVClass *class; + + ptrdiff_t width[4]; + ptrdiff_t height[4]; + int nb_planes; + int bitdepth; + ff_scene_sad_fn sad; + double prev_mafd; + double scene_score; + AVFrame *prev_picref; + double threshold; + int sc_pass; +} SCDetContext; + +#define OFFSET(x) offsetof(SCDetContext, x) +#define V AV_OPT_FLAG_VIDEO_PARAM +#define F AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption scdet_options[] = { + { "threshold", "set scene change detect threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 10.}, 0, 100., V|F }, + { "t", "set scene change detect threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 10.}, 0, 100., V|F }, + { "sc_pass", "Set the flag to pass scene change frames", OFFSET(sc_pass), AV_OPT_TYPE_BOOL, {.dbl = 0 }, 0, 1, V|F }, + { "s", "Set the flag to pass scene change frames", OFFSET(sc_pass), AV_OPT_TYPE_BOOL, {.dbl = 0 }, 0, 1, V|F }, + {NULL} +}; + +AVFILTER_DEFINE_CLASS(scdet); + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, AV_PIX_FMT_RGBA, + AV_PIX_FMT_ABGR, AV_PIX_FMT_BGRA, AV_PIX_FMT_GRAY8, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P12, + AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + SCDetContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) && + (desc->flags & AV_PIX_FMT_FLAG_PLANAR) && + desc->nb_components >= 3; + + s->bitdepth = desc->comp[0].depth; + s->nb_planes = is_yuv ? 1 : av_pix_fmt_count_planes(inlink->format); + + for (int plane = 0; plane < 4; plane++) { + ptrdiff_t line_size = av_image_get_linesize(inlink->format, inlink->w, plane); + s->width[plane] = line_size >> (s->bitdepth > 8); + s->height[plane] = inlink->h >> ((plane == 1 || plane == 2) ? desc->log2_chroma_h : 0); + } + + s->sad = ff_scene_sad_get_fn(s->bitdepth == 8 ? 8 : 16); + if (!s->sad) + return AVERROR(EINVAL); + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + SCDetContext *s = ctx->priv; + + av_frame_free(&s->prev_picref); +} + +static double get_scene_score(AVFilterContext *ctx, AVFrame *frame) +{ + double ret = 0; + SCDetContext *s = ctx->priv; + AVFrame *prev_picref = s->prev_picref; + + if (prev_picref && frame->height == prev_picref->height + && frame->width == prev_picref->width) { + uint64_t sad = 0; + double mafd, diff; + uint64_t count = 0; + + for (int plane = 0; plane < s->nb_planes; plane++) { + uint64_t plane_sad; + s->sad(prev_picref->data[plane], prev_picref->linesize[plane], + frame->data[plane], frame->linesize[plane], + s->width[plane], s->height[plane], &plane_sad); + sad += plane_sad; + count += s->width[plane] * s->height[plane]; + } + + emms_c(); + mafd = (double)sad * 100. / count / (1ULL << s->bitdepth); + diff = fabs(mafd - s->prev_mafd); + ret = av_clipf(FFMIN(mafd, diff), 0, 100.); + s->prev_mafd = mafd; + av_frame_free(&prev_picref); + } + s->prev_picref = av_frame_clone(frame); + return ret; +} + +static int set_meta(SCDetContext *s, AVFrame *frame, const char *key, const char *value) +{ + return av_dict_set(&frame->metadata, key, value, 0); +} + +static int activate(AVFilterContext *ctx) +{ + int ret; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + SCDetContext *s = ctx->priv; + AVFrame *frame; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + ret = ff_inlink_consume_frame(inlink, &frame); + if (ret < 0) + return ret; + + if (frame) { + char buf[64]; + s->scene_score = get_scene_score(ctx, frame); + snprintf(buf, sizeof(buf), "%0.3f", s->prev_mafd); + set_meta(s, frame, "lavfi.scd.mafd", buf); + snprintf(buf, sizeof(buf), "%0.3f", s->scene_score); + set_meta(s, frame, "lavfi.scd.score", buf); + + if (s->scene_score > s->threshold) { + av_log(s, AV_LOG_INFO, "lavfi.scd.score: %.3f, lavfi.scd.time: %s\n", + s->scene_score, av_ts2timestr(frame->pts, &inlink->time_base)); + set_meta(s, frame, "lavfi.scd.time", + av_ts2timestr(frame->pts, &inlink->time_base)); + } + if (s->sc_pass) { + if (s->scene_score > s->threshold) + return ff_filter_frame(outlink, frame); + else { + av_frame_free(&frame); + } + } else + return ff_filter_frame(outlink, frame); + } + + FF_FILTER_FORWARD_STATUS(inlink, outlink); + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; +} + +static const AVFilterPad scdet_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad scdet_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_scdet = { + .name = "scdet", + .description = NULL_IF_CONFIG_SMALL("Detect video scene change"), + .priv_size = sizeof(SCDetContext), + .priv_class = &scdet_class, + .uninit = uninit, + .query_formats = query_formats, + .inputs = scdet_inputs, + .outputs = scdet_outputs, + .activate = activate, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_scroll.c ffmpeg-4.4/libavfilter/vf_scroll.c --- ffmpeg-4.2.2/libavfilter/vf_scroll.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_scroll.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2019 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/common.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" + +typedef struct ScrollContext { + const AVClass *class; + + float h_speed, v_speed; + float h_pos, v_pos; + float h_ipos, v_ipos; + + int pos_h[4], pos_v[4]; + + const AVPixFmtDescriptor *desc; + int nb_planes; + int bytes; + + int planewidth[4]; + int planeheight[4]; +} ScrollContext; + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int scroll_slice(AVFilterContext *ctx, void *arg, int jobnr, + int nb_jobs) +{ + ScrollContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + + for (int p = 0; p < s->nb_planes; p++) { + const uint8_t *src = in->data[p]; + const int h = s->planeheight[p]; + const int w = s->planewidth[p] * s->bytes; + const int slice_start = (h * jobnr) / nb_jobs; + const int slice_end = (h * (jobnr+1)) / nb_jobs; + uint8_t *dst = out->data[p] + slice_start * out->linesize[p]; + + for (int y = slice_start; y < slice_end; y++) { + int yy = (y + s->pos_v[p]) % h; + const uint8_t *ssrc = src + yy * in->linesize[p]; + + if (s->pos_h[p] < w) + memcpy(dst, ssrc + s->pos_h[p], w - s->pos_h[p]); + if (s->pos_h[p] > 0) + memcpy(dst + w - s->pos_h[p], ssrc, s->pos_h[p]); + + dst += out->linesize[p]; + } + } + + return 0; +} + +static void scroll(AVFilterContext *ctx, AVFrame *in, AVFrame *out) +{ + ScrollContext *s = ctx->priv; + ThreadData td; + int h_pos, v_pos; + + s->h_pos = fmodf(s->h_pos, in->width); + s->v_pos = fmodf(s->v_pos, in->height); + + h_pos = s->h_pos; + v_pos = s->v_pos; + + if (h_pos < 0) + h_pos += in->width; + if (v_pos < 0) + v_pos += in->height; + + s->pos_v[1] = s->pos_v[2] = AV_CEIL_RSHIFT(v_pos, s->desc->log2_chroma_h); + s->pos_v[0] = s->pos_v[3] = v_pos; + s->pos_h[1] = s->pos_h[2] = AV_CEIL_RSHIFT(h_pos, s->desc->log2_chroma_w) * s->bytes; + s->pos_h[0] = s->pos_h[3] = h_pos * s->bytes; + + td.in = in; td.out = out; + ctx->internal->execute(ctx, scroll_slice, &td, NULL, + FFMIN(out->height, ff_filter_get_nb_threads(ctx))); + + s->h_pos += s->h_speed * in->width; + s->v_pos += s->v_speed * in->height; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + 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); + + scroll(ctx, in, out); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + ScrollContext *s = ctx->priv; + + s->desc = av_pix_fmt_desc_get(inlink->format); + s->nb_planes = s->desc->nb_components; + s->bytes = (s->desc->comp[0].depth + 7) >> 3; + + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, s->desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + + s->h_pos = (1.f - s->h_ipos) * inlink->w; + s->v_pos = (1.f - s->v_ipos) * inlink->h; + + return 0; +} + +#define OFFSET(x) offsetof(ScrollContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define VFT AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption scroll_options[] = { + { "horizontal", "set the horizontal scrolling speed", OFFSET(h_speed), AV_OPT_TYPE_FLOAT, {.dbl=0.}, -1., 1., VFT }, + { "h", "set the horizontal scrolling speed", OFFSET(h_speed), AV_OPT_TYPE_FLOAT, {.dbl=0.}, -1., 1., VFT }, + { "vertical", "set the vertical scrolling speed", OFFSET(v_speed), AV_OPT_TYPE_FLOAT, {.dbl=0.}, -1., 1., VFT }, + { "v", "set the vertical scrolling speed", OFFSET(v_speed), AV_OPT_TYPE_FLOAT, {.dbl=0.}, -1., 1., VFT }, + { "hpos", "set initial horizontal position", OFFSET(h_ipos), AV_OPT_TYPE_FLOAT, {.dbl=0.}, 0, 1., FLAGS }, + { "vpos", "set initial vertical position", OFFSET(v_ipos), AV_OPT_TYPE_FLOAT, {.dbl=0.}, 0, 1., FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(scroll); + +static const AVFilterPad scroll_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad scroll_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_scroll = { + .name = "scroll", + .description = NULL_IF_CONFIG_SMALL("Scroll input video."), + .priv_size = sizeof(ScrollContext), + .priv_class = &scroll_class, + .query_formats = query_formats, + .inputs = scroll_inputs, + .outputs = scroll_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_selectivecolor.c ffmpeg-4.4/libavfilter/vf_selectivecolor.c --- ffmpeg-4.2.2/libavfilter/vf_selectivecolor.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_selectivecolor.c 2021-04-08 21:28:40.000000000 +0000 @@ -61,7 +61,7 @@ NB_CORRECTION_METHODS, }; -static const char *color_names[NB_RANGES] = { +static const char *const color_names[NB_RANGES] = { "red", "yellow", "green", "cyan", "blue", "magenta", "white", "neutral", "black" }; @@ -93,7 +93,7 @@ #define OFFSET(x) offsetof(SelectiveColorContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM #define RANGE_OPTION(color_name, range) \ - { color_name"s", "adjust "color_name" regions", OFFSET(opt_cmyk_adjust[range]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS } + { color_name"s", "adjust "color_name" regions", OFFSET(opt_cmyk_adjust[range]), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS } static const AVOption selectivecolor_options[] = { { "correction_method", "select correction method", OFFSET(correction_method), AV_OPT_TYPE_INT, {.i64 = CORRECTION_METHOD_ABSOLUTE}, 0, NB_CORRECTION_METHODS-1, FLAGS, "correction_method" }, diff -Nru ffmpeg-4.2.2/libavfilter/vf_setparams.c ffmpeg-4.4/libavfilter/vf_setparams.c --- ffmpeg-4.2.2/libavfilter/vf_setparams.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_setparams.c 2020-07-11 10:39:30.000000000 +0000 @@ -75,6 +75,7 @@ {"smpte431", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE431}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, {"smpte432", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE432}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, {"jedec-p22", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_JEDEC_P22}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, + {"ebu3213", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_EBU3213}, INT_MIN, INT_MAX, FLAGS, "color_primaries"}, {"color_trc", "select color transfer", OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_TRC_NB-1, FLAGS, "color_trc"}, {"auto", "keep the same color transfer", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, FLAGS, "color_trc"}, diff -Nru ffmpeg-4.2.2/libavfilter/vf_shear.c ffmpeg-4.4/libavfilter/vf_shear.c --- ffmpeg-4.2.2/libavfilter/vf_shear.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_shear.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,330 @@ +/* + * 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 "libavutil/avstring.h" +#include "libavutil/opt.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/parseutils.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "drawutils.h" +#include "internal.h" +#include "video.h" + +#include + +typedef struct ShearContext { + const AVClass *class; + + float shx, shy; + int interp; + + uint8_t fillcolor[4]; ///< color expressed either in YUVA or RGBA colorspace for the padding area + char *fillcolor_str; + int fillcolor_enable; + int nb_planes; + int depth; + FFDrawContext draw; + FFDrawColor color; + + int hsub, vsub; + int planewidth[4]; + int planeheight[4]; + + int (*filter_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); +} ShearContext; + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +#define OFFSET(x) offsetof(ShearContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption shear_options[] = { + { "shx", "set x shear factor", OFFSET(shx), AV_OPT_TYPE_FLOAT, {.dbl=0.}, -2, 2, .flags=FLAGS }, + { "shy", "set y shear factor", OFFSET(shy), AV_OPT_TYPE_FLOAT, {.dbl=0.}, -2, 2, .flags=FLAGS }, + { "fillcolor", "set background fill color", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str="black"}, 0, 0, .flags=FLAGS }, + { "c", "set background fill color", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str="black"}, 0, 0, .flags=FLAGS }, + { "interp", "set interpolation", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, .flags=FLAGS, "interp" }, + { "nearest", "nearest neighbour", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags=FLAGS, "interp" }, + { "bilinear", "bilinear", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags=FLAGS, "interp" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(shear); + +static av_cold int init(AVFilterContext *ctx) +{ + ShearContext *s = ctx->priv; + + if (!strcmp(s->fillcolor_str, "none")) + s->fillcolor_enable = 0; + else if (av_parse_color(s->fillcolor, s->fillcolor_str, -1, ctx) >= 0) + s->fillcolor_enable = 1; + else + return AVERROR(EINVAL); + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, + AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, + AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +#define NN(type, name) \ +static int filter_slice_nn##name(AVFilterContext *ctx, void *arg, int jobnr, \ + int nb_jobs) \ +{ \ + ThreadData *td = arg; \ + AVFrame *in = td->in; \ + AVFrame *out = td->out; \ + ShearContext *s = ctx->priv; \ + const float shx = s->shx; \ + const float shy = s->shy; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const int hsub = (p == 1 || p == 2) ? s->hsub: 1; \ + const int vsub = (p == 1 || p == 2) ? s->vsub: 1; \ + const int width = s->planewidth[p]; \ + const int height = s->planeheight[p]; \ + const int wx = vsub * shx * height * 0.5f / hsub; \ + const int wy = hsub * shy * width * 0.5f / vsub; \ + const int slice_start = (height * jobnr) / nb_jobs; \ + const int slice_end = (height * (jobnr+1)) / nb_jobs; \ + const int src_linesize = in->linesize[p] / sizeof(type); \ + const int dst_linesize = out->linesize[p] / sizeof(type); \ + const type *src = (const type *)in->data[p]; \ + type *dst = (type *)out->data[p] + slice_start * dst_linesize; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + int sx = x + vsub * shx * y / hsub - wx; \ + int sy = y + hsub * shy * x / vsub - wy; \ + \ + if (sx >= 0 && sx < width - 1 && \ + sy >= 0 && sy < height - 1) { \ + dst[x] = src[sy * src_linesize + sx]; \ + } \ + } \ + \ + dst += dst_linesize; \ + } \ + } \ + \ + return 0; \ +} + +NN(uint8_t, 8) +NN(uint16_t, 16) + +#define BL(type, name) \ +static int filter_slice_bl##name(AVFilterContext *ctx, void *arg, int jobnr, \ + int nb_jobs) \ +{ \ + ThreadData *td = arg; \ + AVFrame *in = td->in; \ + AVFrame *out = td->out; \ + ShearContext *s = ctx->priv; \ + const int depth = s->depth; \ + const float shx = s->shx; \ + const float shy = s->shy; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const int hsub = (p == 1 || p == 2) ? s->hsub: 1; \ + const int vsub = (p == 1 || p == 2) ? s->vsub: 1; \ + const int width = s->planewidth[p]; \ + const int height = s->planeheight[p]; \ + const float wx = vsub * shx * height * 0.5f / hsub; \ + const float wy = hsub * shy * width * 0.5f / vsub; \ + const int slice_start = (height * jobnr) / nb_jobs; \ + const int slice_end = (height * (jobnr+1)) / nb_jobs; \ + const int src_linesize = in->linesize[p] / sizeof(type); \ + const int dst_linesize = out->linesize[p] / sizeof(type); \ + const type *src = (const type *)in->data[p]; \ + type *dst = (type *)out->data[p] + slice_start * dst_linesize; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float sx = x + vsub * shx * y / hsub - wx; \ + const float sy = y + hsub * shy * x / vsub - wy; \ + \ + if (sx >= 0 && sx < width - 1 && \ + sy >= 0 && sy < height - 1) { \ + float sum = 0.f; \ + int ax = floorf(sx); \ + int ay = floorf(sy); \ + float du = sx - ax; \ + float dv = sy - ay; \ + int bx = FFMIN(ax + 1, width - 1); \ + int by = FFMIN(ay + 1, height - 1); \ + \ + sum += (1.f - du) * (1.f - dv) * src[ay * src_linesize + ax];\ + sum += ( du) * (1.f - dv) * src[ay * src_linesize + bx];\ + sum += (1.f - du) * ( dv) * src[by * src_linesize + ax];\ + sum += ( du) * ( dv) * src[by * src_linesize + bx];\ + dst[x] = av_clip_uintp2_c(lrintf(sum), depth); \ + } \ + } \ + \ + dst += dst_linesize; \ + } \ + } \ + \ + return 0; \ +} + +BL(uint8_t, 8) +BL(uint16_t, 16) + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + ShearContext *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); + + /* fill background */ + if (s->fillcolor_enable) + ff_fill_rectangle(&s->draw, &s->color, out->data, out->linesize, + 0, 0, outlink->w, outlink->h); + + td.in = in, td.out = out; + ctx->internal->execute(ctx, s->filter_slice[s->interp], &td, NULL, FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx))); + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + ShearContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); + + s->nb_planes = av_pix_fmt_count_planes(outlink->format); + s->depth = desc->comp[0].depth; + s->hsub = 1 << desc->log2_chroma_w; + s->vsub = 1 << desc->log2_chroma_h; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(ctx->inputs[0]->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = ctx->inputs[0]->w; + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(ctx->inputs[0]->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = ctx->inputs[0]->h; + + ff_draw_init(&s->draw, outlink->format, 0); + ff_draw_color(&s->draw, &s->color, s->fillcolor); + + s->filter_slice[0] = s->depth <= 8 ? filter_slice_nn8 : filter_slice_nn16; + s->filter_slice[1] = s->depth <= 8 ? filter_slice_bl8 : filter_slice_bl16; + + return 0; +} + +static int process_command(AVFilterContext *ctx, + const char *cmd, + const char *arg, + char *res, + int res_len, + int flags) +{ + ShearContext *s = ctx->priv; + int ret; + + ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags); + if (ret < 0) + return ret; + + ret = init(ctx); + if (ret < 0) + return ret; + ff_draw_color(&s->draw, &s->color, s->fillcolor); + + return 0; +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vf_shear = { + .name = "shear", + .description = NULL_IF_CONFIG_SMALL("Shear transform the input image."), + .priv_size = sizeof(ShearContext), + .init = init, + .query_formats = query_formats, + .inputs = inputs, + .outputs = outputs, + .priv_class = &shear_class, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_showinfo.c ffmpeg-4.4/libavfilter/vf_showinfo.c --- ffmpeg-4.2.2/libavfilter/vf_showinfo.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_showinfo.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,16 +24,20 @@ #include +#include "libavutil/bswap.h" #include "libavutil/adler32.h" #include "libavutil/display.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" +#include "libavutil/hdr_dynamic_metadata.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/spherical.h" #include "libavutil/stereo3d.h" #include "libavutil/timestamp.h" #include "libavutil/timecode.h" +#include "libavutil/mastering_display_metadata.h" +#include "libavutil/video_enc_params.h" #include "avfilter.h" #include "internal.h" @@ -54,14 +58,14 @@ AVFILTER_DEFINE_CLASS(showinfo); -static void dump_spherical(AVFilterContext *ctx, AVFrame *frame, AVFrameSideData *sd) +static void dump_spherical(AVFilterContext *ctx, AVFrame *frame, const AVFrameSideData *sd) { - AVSphericalMapping *spherical = (AVSphericalMapping *)sd->data; + const AVSphericalMapping *spherical = (const AVSphericalMapping *)sd->data; double yaw, pitch, roll; av_log(ctx, AV_LOG_INFO, "spherical information: "); if (sd->size < sizeof(*spherical)) { - av_log(ctx, AV_LOG_INFO, "invalid data"); + av_log(ctx, AV_LOG_ERROR, "invalid data\n"); return; } @@ -72,7 +76,7 @@ else if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) av_log(ctx, AV_LOG_INFO, "tiled equirectangular "); else { - av_log(ctx, AV_LOG_WARNING, "unknown"); + av_log(ctx, AV_LOG_WARNING, "unknown\n"); return; } @@ -93,17 +97,17 @@ } } -static void dump_stereo3d(AVFilterContext *ctx, AVFrameSideData *sd) +static void dump_stereo3d(AVFilterContext *ctx, const AVFrameSideData *sd) { - AVStereo3D *stereo; + const AVStereo3D *stereo; av_log(ctx, AV_LOG_INFO, "stereoscopic information: "); if (sd->size < sizeof(*stereo)) { - av_log(ctx, AV_LOG_INFO, "invalid data"); + av_log(ctx, AV_LOG_ERROR, "invalid data\n"); return; } - stereo = (AVStereo3D *)sd->data; + stereo = (const AVStereo3D *)sd->data; av_log(ctx, AV_LOG_INFO, "type - %s", av_stereo3d_type_name(stereo->type)); @@ -111,7 +115,23 @@ av_log(ctx, AV_LOG_INFO, " (inverted)"); } -static void dump_roi(AVFilterContext *ctx, AVFrameSideData *sd) +static void dump_s12m_timecode(AVFilterContext *ctx, AVRational frame_rate, const AVFrameSideData *sd) +{ + const uint32_t *tc = (const uint32_t *)sd->data; + + if ((sd->size != sizeof(uint32_t) * 4) || (tc[0] > 3)) { + av_log(ctx, AV_LOG_ERROR, "invalid data\n"); + return; + } + + for (int j = 1; j <= tc[0]; j++) { + char tcbuf[AV_TIMECODE_STR_SIZE]; + av_timecode_make_smpte_tc_string2(tcbuf, frame_rate, tc[j], 0, 0); + av_log(ctx, AV_LOG_INFO, "timecode - %s%s", tcbuf, j != tc[0] ? ", " : ""); + } +} + +static void dump_roi(AVFilterContext *ctx, const AVFrameSideData *sd) { int nb_rois; const AVRegionOfInterest *roi; @@ -133,6 +153,187 @@ } } +static void dump_mastering_display(AVFilterContext *ctx, const AVFrameSideData *sd) +{ + const AVMasteringDisplayMetadata *mastering_display; + + av_log(ctx, AV_LOG_INFO, "mastering display: "); + if (sd->size < sizeof(*mastering_display)) { + av_log(ctx, AV_LOG_ERROR, "invalid data\n"); + return; + } + + mastering_display = (const AVMasteringDisplayMetadata *)sd->data; + + av_log(ctx, AV_LOG_INFO, "has_primaries:%d has_luminance:%d " + "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f) " + "min_luminance=%f, max_luminance=%f", + mastering_display->has_primaries, mastering_display->has_luminance, + av_q2d(mastering_display->display_primaries[0][0]), + av_q2d(mastering_display->display_primaries[0][1]), + av_q2d(mastering_display->display_primaries[1][0]), + av_q2d(mastering_display->display_primaries[1][1]), + av_q2d(mastering_display->display_primaries[2][0]), + av_q2d(mastering_display->display_primaries[2][1]), + av_q2d(mastering_display->white_point[0]), av_q2d(mastering_display->white_point[1]), + av_q2d(mastering_display->min_luminance), av_q2d(mastering_display->max_luminance)); +} + +static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) +{ + AVDynamicHDRPlus *hdr_plus; + + av_log(ctx, AV_LOG_INFO, "HDR10+ metadata: "); + if (sd->size < sizeof(*hdr_plus)) { + av_log(ctx, AV_LOG_ERROR, "invalid data\n"); + return; + } + + hdr_plus = (AVDynamicHDRPlus *)sd->data; + av_log(ctx, AV_LOG_INFO, "application version: %d, ", hdr_plus->application_version); + 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, "window_upper_left_corner: (%5.4f,%5.4f),", + av_q2d(params->window_upper_left_corner_x), + av_q2d(params->window_upper_left_corner_y)); + av_log(ctx, AV_LOG_INFO, "window_lower_right_corner: (%5.4f,%5.4f), ", + av_q2d(params->window_lower_right_corner_x), + av_q2d(params->window_lower_right_corner_y)); + 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)); + av_log(ctx, AV_LOG_INFO, "center_of_ellipse_x: (%d,%d), ", + params->center_of_ellipse_x, + params->center_of_ellipse_y); + av_log(ctx, AV_LOG_INFO, "rotation_angle: %d, ", + params->rotation_angle); + av_log(ctx, AV_LOG_INFO, "semimajor_axis_internal_ellipse: %d, ", + params->semimajor_axis_internal_ellipse); + av_log(ctx, AV_LOG_INFO, "semimajor_axis_external_ellipse: %d, ", + 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}, ", + params->overlap_process_option); + } + av_log(ctx, AV_LOG_INFO, "targeted_system_display_maximum_luminance: %9.4f, ", + av_q2d(hdr_plus->targeted_system_display_maximum_luminance)); + if (hdr_plus->targeted_system_display_actual_peak_luminance_flag) { + av_log(ctx, AV_LOG_INFO, "targeted_system_display_actual_peak_luminance: {"); + 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_q2d(hdr_plus->targeted_system_display_actual_peak_luminance[i][j])); + } + av_log(ctx, AV_LOG_INFO, ")"); + } + av_log(ctx, AV_LOG_INFO, "}, "); + } + + for (int w = 0; w < hdr_plus->num_windows; w++) { + 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, "} 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++) { + av_log(ctx, AV_LOG_INFO, "(%d,%5.4f)", + params->distribution_maxrgb[i].percentage, + av_q2d(params->distribution_maxrgb[i].percentile)); + } + 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, "bezier_curve_anchors: {"); + for (int i = 0; i < params->num_bezier_curve_anchors; i++) { + av_log(ctx, AV_LOG_INFO, "%5.4f,", + av_q2d(params->bezier_curve_anchors[i])); + } + av_log(ctx, AV_LOG_INFO, "} "); + } + if (params->color_saturation_mapping_flag) { + av_log(ctx, AV_LOG_INFO, "color_saturation_weight: %5.4f", + av_q2d(params->color_saturation_weight)); + } + 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: {"); + 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_q2d(hdr_plus->mastering_display_actual_peak_luminance[i][j])); + } + av_log(ctx, AV_LOG_INFO, ")"); + } + av_log(ctx, AV_LOG_INFO, "} "); + } +} + +static void dump_content_light_metadata(AVFilterContext *ctx, AVFrameSideData *sd) +{ + const AVContentLightMetadata *metadata = (const AVContentLightMetadata *)sd->data; + + av_log(ctx, AV_LOG_INFO, "Content Light Level information: " + "MaxCLL=%d, MaxFALL=%d", + metadata->MaxCLL, metadata->MaxFALL); +} + +static void dump_video_enc_params(AVFilterContext *ctx, const AVFrameSideData *sd) +{ + const AVVideoEncParams *par = (const AVVideoEncParams *)sd->data; + int plane, acdc; + + av_log(ctx, AV_LOG_INFO, "video encoding parameters: type %d; ", par->type); + if (par->qp) + av_log(ctx, AV_LOG_INFO, "qp=%d; ", par->qp); + for (plane = 0; plane < FF_ARRAY_ELEMS(par->delta_qp); plane++) + for (acdc = 0; acdc < FF_ARRAY_ELEMS(par->delta_qp[plane]); acdc++) { + int delta_qp = par->delta_qp[plane][acdc]; + if (delta_qp) + av_log(ctx, AV_LOG_INFO, "delta_qp[%d][%d]=%d; ", + plane, acdc, delta_qp); + } + if (par->nb_blocks) + av_log(ctx, AV_LOG_INFO, "%u blocks; ", par->nb_blocks); +} + +static void dump_sei_unregistered_metadata(AVFilterContext *ctx, const AVFrameSideData *sd) +{ + const int uuid_size = 16; + const uint8_t *user_data = sd->data; + int i; + + if (sd->size < uuid_size) { + av_log(ctx, AV_LOG_ERROR, "invalid data(%d < UUID(%d-bytes))\n", sd->size, uuid_size); + return; + } + + av_log(ctx, AV_LOG_INFO, "User Data Unregistered:\n"); + av_log(ctx, AV_LOG_INFO, "UUID="); + for (i = 0; i < uuid_size; i++) { + av_log(ctx, AV_LOG_INFO, "%02x", user_data[i]); + if (i == 3 || i == 5 || i == 7 || i == 9) + av_log(ctx, AV_LOG_INFO, "-"); + } + av_log(ctx, AV_LOG_INFO, "\n"); + + av_log(ctx, AV_LOG_INFO, "User Data="); + for (; i < sd->size; i++) { + av_log(ctx, AV_LOG_INFO, "%02x", user_data[i]); + } + av_log(ctx, AV_LOG_INFO, "\n"); +} + static void dump_color_property(AVFilterContext *ctx, AVFrame *frame) { const char *color_range_str = av_color_range_name(frame->color_range); @@ -166,7 +367,7 @@ av_log(ctx, AV_LOG_INFO, "\n"); } -static void update_sample_stats(const uint8_t *src, int len, int64_t *sum, int64_t *sum2) +static void update_sample_stats_8(const uint8_t *src, int len, int64_t *sum, int64_t *sum2) { int i; @@ -176,6 +377,30 @@ } } +static void update_sample_stats_16(int be, const uint8_t *src, int len, int64_t *sum, int64_t *sum2) +{ + const uint16_t *src1 = (const uint16_t *)src; + int i; + + for (i = 0; i < len / 2; i++) { + if ((HAVE_BIGENDIAN && !be) || (!HAVE_BIGENDIAN && be)) { + *sum += av_bswap16(src1[i]); + *sum2 += (uint32_t)av_bswap16(src1[i]) * (uint32_t)av_bswap16(src1[i]); + } else { + *sum += src1[i]; + *sum2 += (uint32_t)src1[i] * (uint32_t)src1[i]; + } + } +} + +static void update_sample_stats(int depth, int be, const uint8_t *src, int len, int64_t *sum, int64_t *sum2) +{ + if (depth <= 8) + update_sample_stats_8(src, len, sum, sum2); + else + update_sample_stats_16(be, src, len, sum, sum2); +} + static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; @@ -184,12 +409,15 @@ uint32_t plane_checksum[4] = {0}, checksum = 0; int64_t sum[4] = {0}, sum2[4] = {0}; int32_t pixelcount[4] = {0}; + int bitdepth = desc->comp[0].depth; + int be = desc->flags & AV_PIX_FMT_FLAG_BE; int i, plane, vsub = desc->log2_chroma_h; for (plane = 0; plane < 4 && s->calculate_checksums && frame->data[plane] && frame->linesize[plane]; plane++) { uint8_t *data = frame->data[plane]; int h = plane == 1 || plane == 2 ? AV_CEIL_RSHIFT(inlink->h, vsub) : inlink->h; int linesize = av_image_get_linesize(frame->format, frame->width, plane); + int width = linesize >> (bitdepth > 8); if (linesize < 0) return linesize; @@ -198,8 +426,8 @@ plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize); checksum = av_adler32_update(checksum, data, linesize); - update_sample_stats(data, linesize, sum+plane, sum2+plane); - pixelcount[plane] += linesize; + update_sample_stats(bitdepth, be, data, linesize, sum+plane, sum2+plane); + pixelcount[plane] += width; data += frame->linesize[plane]; } } @@ -253,12 +481,7 @@ dump_stereo3d(ctx, sd); break; case AV_FRAME_DATA_S12M_TIMECODE: { - uint32_t *tc = (uint32_t*)sd->data; - for (int j = 1; j <= tc[0]; j++) { - char tcbuf[AV_TIMECODE_STR_SIZE]; - av_timecode_make_smpte_tc_string(tcbuf, tc[j], 0); - av_log(ctx, AV_LOG_INFO, "timecode - %s%s", tcbuf, j != tc[0] ? ", " : ""); - } + dump_s12m_timecode(ctx, inlink->frame_rate, sd); break; } case AV_FRAME_DATA_DISPLAYMATRIX: @@ -271,8 +494,29 @@ case AV_FRAME_DATA_REGIONS_OF_INTEREST: dump_roi(ctx, sd); break; + case AV_FRAME_DATA_MASTERING_DISPLAY_METADATA: + dump_mastering_display(ctx, sd); + break; + case AV_FRAME_DATA_DYNAMIC_HDR_PLUS: + dump_dynamic_hdr_plus(ctx, sd); + break; + case AV_FRAME_DATA_CONTENT_LIGHT_LEVEL: + dump_content_light_metadata(ctx, sd); + break; + case AV_FRAME_DATA_GOP_TIMECODE: { + char tcbuf[AV_TIMECODE_STR_SIZE]; + av_timecode_make_mpeg_tc_string(tcbuf, *(int64_t *)(sd->data)); + av_log(ctx, AV_LOG_INFO, "GOP timecode - %s", tcbuf); + break; + } + case AV_FRAME_DATA_VIDEO_ENC_PARAMS: + dump_video_enc_params(ctx, sd); + break; + case AV_FRAME_DATA_SEI_UNREGISTERED: + dump_sei_unregistered_metadata(ctx, sd); + break; default: - av_log(ctx, AV_LOG_WARNING, "unknown side data type %d (%d bytes)", + av_log(ctx, AV_LOG_WARNING, "unknown side data type %d (%d bytes)\n", sd->type, sd->size); break; } diff -Nru ffmpeg-4.2.2/libavfilter/vf_showpalette.c ffmpeg-4.4/libavfilter/vf_showpalette.c --- ffmpeg-4.2.2/libavfilter/vf_showpalette.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_showpalette.c 2021-04-08 21:28:40.000000000 +0000 @@ -46,26 +46,13 @@ { static const enum AVPixelFormat in_fmts[] = {AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE}; static const enum AVPixelFormat out_fmts[] = {AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE}; - int ret; - AVFilterFormats *in = ff_make_format_list(in_fmts); - AVFilterFormats *out = ff_make_format_list(out_fmts); - if (!in || !out) { - ret = AVERROR(ENOMEM); - goto fail; - } + int ret = ff_formats_ref(ff_make_format_list(in_fmts), + &ctx->inputs[0]->outcfg.formats); + if (ret < 0) + return ret; - if ((ret = ff_formats_ref(in , &ctx->inputs[0]->out_formats)) < 0 || - (ret = ff_formats_ref(out, &ctx->outputs[0]->in_formats)) < 0) - goto fail; - return 0; -fail: - if (in) - av_freep(&in->formats); - av_freep(&in); - if (out) - av_freep(&out->formats); - av_freep(&out); - return ret; + return ff_formats_ref(ff_make_format_list(out_fmts), + &ctx->outputs[0]->incfg.formats); } static int config_output(AVFilterLink *outlink) @@ -76,7 +63,7 @@ return 0; } -static int disp_palette(AVFrame *out, const AVFrame *in, int size) +static void disp_palette(AVFrame *out, const AVFrame *in, int size) { int x, y, i, j; uint32_t *dst = (uint32_t *)out->data[0]; @@ -88,15 +75,13 @@ for (j = 0; j < size; j++) for (i = 0; i < size; i++) dst[(y*dst_linesize + x) * size + j*dst_linesize + i] = pal[y*16 + x]; - return 0; } static int filter_frame(AVFilterLink *inlink, AVFrame *in) { - int ret; AVFrame *out; AVFilterContext *ctx = inlink->dst; - const ShowPaletteContext *s= ctx->priv; + const ShowPaletteContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -105,9 +90,9 @@ return AVERROR(ENOMEM); } av_frame_copy_props(out, in); - ret = disp_palette(out, in, s->size); + disp_palette(out, in, s->size); av_frame_free(&in); - return ret < 0 ? ret : ff_filter_frame(outlink, out); + return ff_filter_frame(outlink, out); } static const AVFilterPad showpalette_inputs[] = { @@ -136,5 +121,4 @@ .inputs = showpalette_inputs, .outputs = showpalette_outputs, .priv_class = &showpalette_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_shuffleframes.c ffmpeg-4.4/libavfilter/vf_shuffleframes.c --- ffmpeg-4.2.2/libavfilter/vf_shuffleframes.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_shuffleframes.c 2020-07-11 10:39:30.000000000 +0000 @@ -69,7 +69,7 @@ } if (s->map[n] < -1 || s->map[n] >= nb_items) { - av_log(ctx, AV_LOG_ERROR, "Index out of range.\n"); + av_log(ctx, AV_LOG_ERROR, "Index %d out of range: [-1, %d].\n", s->map[n], nb_items - 1); av_free(mapping); return AVERROR(EINVAL); } diff -Nru ffmpeg-4.2.2/libavfilter/vf_shufflepixels.c ffmpeg-4.4/libavfilter/vf_shufflepixels.c --- ffmpeg-4.2.2/libavfilter/vf_shufflepixels.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_shufflepixels.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/imgutils.h" +#include "libavutil/lfg.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/random_seed.h" + +#include "avfilter.h" +#include "internal.h" +#include "video.h" + +typedef struct ShufflePixelsContext { + const AVClass *class; + + int block_w, block_h; + int mode; + int direction; + int64_t seed; + + int depth; + int nb_planes; + int linesize[4]; + int planewidth[4]; + int planeheight[4]; + + int nb_blocks; + + uint8_t *used; + int32_t *map; + + AVLFG c; + + int (*shuffle_pixels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); +} ShufflePixelsContext; + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP16, AV_PIX_FMT_GBRAP, + AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_NONE + }; + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +static void make_horizontal_map(AVFilterContext *ctx) +{ + ShufflePixelsContext *s = ctx->priv; + const int nb_blocks = s->nb_blocks; + AVLFG *c = &s->c; + uint8_t *used = s->used; + int32_t *map = s->map; + + for (int x = 0; x < s->planewidth[0];) { + int rand = av_lfg_get(c) % nb_blocks; + + if (used[rand] == 0) { + int width; + + if (s->direction) { + width = FFMIN(s->block_w, s->planewidth[0] - x); + map[rand * s->block_w] = x; + } else { + width = FFMIN(s->block_w, s->planewidth[0] - rand * s->block_w); + map[x] = rand * s->block_w; + } + used[rand] = 1; + + if (s->direction) { + for (int i = 1; i < width; i++) { + map[rand * s->block_w + i] = map[rand * s->block_w] + i; + } + } else { + for (int i = 1; i < width; i++) { + map[x + i] = map[x] + i; + } + } + + x += width; + } + } +} + +static void make_vertical_map(AVFilterContext *ctx) +{ + ShufflePixelsContext *s = ctx->priv; + const int nb_blocks = s->nb_blocks; + AVLFG *c = &s->c; + uint8_t *used = s->used; + int32_t *map = s->map; + + for (int y = 0; y < s->planeheight[0];) { + int rand = av_lfg_get(c) % nb_blocks; + + if (used[rand] == 0) { + int height; + + if (s->direction) { + height = FFMIN(s->block_h, s->planeheight[0] - y); + map[rand * s->block_h] = y; + } else { + height = FFMIN(s->block_h, s->planeheight[0] - rand * s->block_h); + map[y] = rand * s->block_h; + } + used[rand] = 1; + + if (s->direction) { + for (int i = 1; i < height; i++) { + map[rand * s->block_h + i] = map[rand * s->block_h] + i; + } + } else { + for (int i = 1; i < height; i++) { + map[y + i] = map[y] + i; + } + } + + y += height; + } + } +} + +static void make_block_map(AVFilterContext *ctx) +{ + ShufflePixelsContext *s = ctx->priv; + const int nb_blocks = s->nb_blocks; + int nb_blocks_w = s->planewidth[0] / s->block_w; + AVLFG *c = &s->c; + uint8_t *used = s->used; + int32_t *map = s->map; + + for (int i = 0; i < nb_blocks;) { + int rand = av_lfg_get(c) % nb_blocks; + + if (used[rand] == 0) { + int yin = i / nb_blocks_w; + int xin = i % nb_blocks_w; + int in = yin * s->block_h * s->planewidth[0] + xin * s->block_w; + int yout = rand / nb_blocks_w; + int xout = rand % nb_blocks_w; + int out = yout * s->block_h * s->planewidth[0] + xout * s->block_w; + + if (s->direction) { + map[out] = in; + } else { + map[in] = out; + } + used[rand] = 1; + + if (s->direction) { + for (int y = 0; y < s->block_h; y++) { + for (int x = 0; x < s->block_w; x++) { + map[out + y * s->planewidth[0] + x] = map[out] + x + y * s->planewidth[0]; + } + } + } else { + for (int y = 0; y < s->block_h; y++) { + for (int x = 0; x < s->block_w; x++) { + map[in + y * s->planewidth[0] + x] = map[in] + x + y * s->planewidth[0]; + } + } + } + + i++; + } + } +} + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + + +#define SHUFFLE_HORIZONTAL(name, type) \ +static int shuffle_horizontal## name(AVFilterContext *ctx, void *arg, \ + int jobnr, int nb_jobs) \ +{ \ + ShufflePixelsContext *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 slice_start = (s->planeheight[p] * jobnr) / nb_jobs; \ + const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs; \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + const type *src = (const type *)(in->data[p] + \ + slice_start * in->linesize[p]); \ + const int32_t *map = s->map; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < s->planewidth[p]; x++) { \ + dst[x] = src[map[x]]; \ + } \ + \ + dst += out->linesize[p] / sizeof(type); \ + src += in->linesize[p] / sizeof(type); \ + } \ + } \ + \ + return 0; \ +} + +SHUFFLE_HORIZONTAL(8, uint8_t) +SHUFFLE_HORIZONTAL(16, uint16_t) + +#define SHUFFLE_VERTICAL(name, type) \ +static int shuffle_vertical## name(AVFilterContext *ctx, void *arg, \ + int jobnr, int nb_jobs) \ +{ \ + ShufflePixelsContext *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 slice_start = (s->planeheight[p] * jobnr) / nb_jobs; \ + const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs; \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + const int32_t *map = s->map; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const type *src = (const type *)(in->data[p] + \ + map[y] * in->linesize[p]); \ + \ + memcpy(dst, src, s->linesize[p]); \ + dst += out->linesize[p] / sizeof(type); \ + } \ + } \ + \ + return 0; \ +} + +SHUFFLE_VERTICAL(8, uint8_t) +SHUFFLE_VERTICAL(16, uint16_t) + +#define SHUFFLE_BLOCK(name, type) \ +static int shuffle_block## name(AVFilterContext *ctx, void *arg, \ + int jobnr, int nb_jobs) \ +{ \ + ShufflePixelsContext *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 slice_start = (s->planeheight[p] * jobnr) / nb_jobs; \ + const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs; \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + const type *src = (const type *)in->data[p]; \ + const int32_t *map = s->map + slice_start * s->planewidth[p]; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < s->planewidth[p]; x++) { \ + int ymap = map[x] / s->planewidth[p]; \ + int xmap = map[x] % s->planewidth[p]; \ + \ + dst[x] = src[xmap + ymap * in->linesize[p] / sizeof(type)]; \ + } \ + \ + dst += out->linesize[p] / sizeof(type); \ + map += s->planewidth[p]; \ + } \ + } \ + \ + return 0; \ +} + +SHUFFLE_BLOCK(8, uint8_t) +SHUFFLE_BLOCK(16, uint16_t) + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + ShufflePixelsContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + const AVPixFmtDescriptor *desc; + int ret; + + if (s->seed == -1) + s->seed = av_get_random_seed(); + av_lfg_init(&s->c, s->seed); + + desc = av_pix_fmt_desc_get(outlink->format); + if (!desc) + return AVERROR_BUG; + s->nb_planes = av_pix_fmt_count_planes(outlink->format); + s->depth = desc->comp[0].depth; + + if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + return ret; + + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + + s->map = av_calloc(inlink->w * inlink->h, sizeof(*s->map)); + if (!s->map) + return AVERROR(ENOMEM); + + switch (s->mode) { + case 0: + s->shuffle_pixels = s->depth <= 8 ? shuffle_horizontal8 : shuffle_horizontal16; + s->nb_blocks = (s->planewidth[0] + s->block_w - 1) / s->block_w; + break; + case 1: + s->shuffle_pixels = s->depth <= 8 ? shuffle_vertical8 : shuffle_vertical16; + s->nb_blocks = (s->planeheight[0] + s->block_h - 1) / s->block_h; + break; + case 2: + s->shuffle_pixels = s->depth <= 8 ? shuffle_block8 : shuffle_block16; + s->nb_blocks = (s->planeheight[0] / s->block_h) * + (s->planewidth[0] / s->block_w); + break; + default: + av_assert0(0); + } + + s->used = av_calloc(s->nb_blocks, sizeof(*s->used)); + if (!s->used) + return AVERROR(ENOMEM); + + switch (s->mode) { + case 0: + make_horizontal_map(ctx); + break; + case 1: + make_vertical_map(ctx); + break; + case 2: + make_block_map(ctx); + break; + default: + av_assert0(0); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + ShufflePixelsContext *s = ctx->priv; + AVFrame *out = ff_get_video_buffer(ctx->outputs[0], in->width, in->height); + ThreadData td; + int ret; + + ret = av_frame_copy_props(out, in); + if (ret < 0) { + av_frame_free(&out); + goto fail; + } + + td.out = out; + td.in = in; + ctx->internal->execute(ctx, s->shuffle_pixels, &td, NULL, FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx))); + + av_frame_free(&in); + return ff_filter_frame(ctx->outputs[0], out); +fail: + av_frame_free(&in); + return ret; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + ShufflePixelsContext *s = ctx->priv; + + av_freep(&s->map); + av_freep(&s->used); +} + +#define OFFSET(x) offsetof(ShufflePixelsContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption shufflepixels_options[] = { + { "direction", "set shuffle direction", OFFSET(direction), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "dir" }, + { "d", "set shuffle direction", OFFSET(direction), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "dir" }, + { "forward", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "dir" }, + { "inverse", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "dir" }, + { "mode", "set shuffle mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "mode" }, + { "m", "set shuffle mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "mode" }, + { "horizontal", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, + { "vertical", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" }, + { "block", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "mode" }, + { "width", "set block width", OFFSET(block_w), AV_OPT_TYPE_INT, {.i64=10}, 1, 8000, FLAGS }, + { "w", "set block width", OFFSET(block_w), AV_OPT_TYPE_INT, {.i64=10}, 1, 8000, FLAGS }, + { "height", "set block height", OFFSET(block_h), AV_OPT_TYPE_INT, {.i64=10}, 1, 8000, FLAGS }, + { "h", "set block height", OFFSET(block_h), AV_OPT_TYPE_INT, {.i64=10}, 1, 8000, FLAGS }, + { "seed", "set random seed", OFFSET(seed), AV_OPT_TYPE_INT64, {.i64=-1}, -1, UINT_MAX, FLAGS }, + { "s", "set random seed", OFFSET(seed), AV_OPT_TYPE_INT64, {.i64=-1}, -1, UINT_MAX, FLAGS }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(shufflepixels); + +static const AVFilterPad shufflepixels_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + }, + { NULL }, +}; + +static const AVFilterPad shufflepixels_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL }, +}; + +AVFilter ff_vf_shufflepixels = { + .name = "shufflepixels", + .description = NULL_IF_CONFIG_SMALL("Shuffle video pixels."), + .priv_size = sizeof(ShufflePixelsContext), + .priv_class = &shufflepixels_class, + .query_formats = query_formats, + .uninit = uninit, + .inputs = shufflepixels_inputs, + .outputs = shufflepixels_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_shuffleplanes.c ffmpeg-4.4/libavfilter/vf_shuffleplanes.c --- ffmpeg-4.2.2/libavfilter/vf_shuffleplanes.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_shuffleplanes.c 2021-04-08 21:28:40.000000000 +0000 @@ -40,41 +40,49 @@ int copy; } ShufflePlanesContext; +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + ShufflePlanesContext *s = ctx->priv; + int fmt, ret, i; + + for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); + int planes = av_pix_fmt_count_planes(fmt); + + if (!(desc->flags & AV_PIX_FMT_FLAG_PAL) && + !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { + for (i = 0; i < 4; i++) { + if (s->map[i] >= planes) + break; + + if ((desc->log2_chroma_h || desc->log2_chroma_w) && + (i == 1 || i == 2) != (s->map[i] == 1 || s->map[i] == 2)) + break; + } + + if (i != 4) + continue; + if ((ret = ff_add_format(&formats, fmt)) < 0) { + return ret; + } + } + } + + return ff_set_common_formats(ctx, formats); +} + static av_cold int shuffleplanes_config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; ShufflePlanesContext *s = ctx->priv; - const AVPixFmtDescriptor *desc; int used[4] = { 0 }; int i; s->copy = 0; s->planes = av_pix_fmt_count_planes(inlink->format); - desc = av_pix_fmt_desc_get(inlink->format); for (i = 0; i < s->planes; i++) { - if (s->map[i] >= s->planes) { - av_log(ctx, AV_LOG_ERROR, - "Non-existing input plane #%d mapped to output plane #%d.\n", - s->map[i], i); - return AVERROR(EINVAL); - } - - if ((desc->log2_chroma_h || desc->log2_chroma_w) && - (i == 1 || i == 2) != (s->map[i] == 1 || s->map[i] == 2)) { - av_log(ctx, AV_LOG_ERROR, - "Cannot map between a subsampled chroma plane and a luma " - "or alpha plane.\n"); - return AVERROR(EINVAL); - } - - if ((desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & FF_PSEUDOPAL) && - (i == 1) != (s->map[i] == 1)) { - av_log(ctx, AV_LOG_ERROR, - "Cannot map between a palette plane and a data plane.\n"); - return AVERROR(EINVAL); - } if (used[s->map[i]]) s->copy = 1; used[s->map[i]]++; @@ -127,10 +135,10 @@ #define OFFSET(x) offsetof(ShufflePlanesContext, x) #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) static const AVOption shuffleplanes_options[] = { - { "map0", "Index of the input plane to be used as the first output plane ", OFFSET(map[0]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 4, FLAGS }, - { "map1", "Index of the input plane to be used as the second output plane ", OFFSET(map[1]), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 4, FLAGS }, - { "map2", "Index of the input plane to be used as the third output plane ", OFFSET(map[2]), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 4, FLAGS }, - { "map3", "Index of the input plane to be used as the fourth output plane ", OFFSET(map[3]), AV_OPT_TYPE_INT, { .i64 = 3 }, 0, 4, FLAGS }, + { "map0", "Index of the input plane to be used as the first output plane ", OFFSET(map[0]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 3, FLAGS }, + { "map1", "Index of the input plane to be used as the second output plane ", OFFSET(map[1]), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 3, FLAGS }, + { "map2", "Index of the input plane to be used as the third output plane ", OFFSET(map[2]), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 3, FLAGS }, + { "map3", "Index of the input plane to be used as the fourth output plane ", OFFSET(map[3]), AV_OPT_TYPE_INT, { .i64 = 3 }, 0, 3, FLAGS }, { NULL }, }; @@ -142,7 +150,6 @@ .type = AVMEDIA_TYPE_VIDEO, .config_props = shuffleplanes_config_input, .filter_frame = shuffleplanes_filter_frame, - .get_video_buffer = ff_null_get_video_buffer, }, { NULL }, }; @@ -160,6 +167,7 @@ .description = NULL_IF_CONFIG_SMALL("Shuffle video planes."), .priv_size = sizeof(ShufflePlanesContext), .priv_class = &shuffleplanes_class, + .query_formats = query_formats, .inputs = shuffleplanes_inputs, .outputs = shuffleplanes_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, diff -Nru ffmpeg-4.2.2/libavfilter/vf_signalstats.c ffmpeg-4.4/libavfilter/vf_signalstats.c --- ffmpeg-4.2.2/libavfilter/vf_signalstats.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_signalstats.c 2020-07-11 10:39:30.000000000 +0000 @@ -50,6 +50,7 @@ int nb_jobs; int *jobs_rets; + int maxsize; // history stats array size int *histy, *histu, *histv, *histsat; AVFrame *frame_sat; @@ -149,7 +150,7 @@ frame->width = w; frame->height = h; - if (av_frame_get_buffer(frame, 32) < 0) { + if (av_frame_get_buffer(frame, 0) < 0) { av_frame_free(&frame); return NULL; } @@ -157,7 +158,7 @@ return frame; } -static int config_props(AVFilterLink *outlink) +static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; SignalstatsContext *s = ctx->priv; @@ -166,15 +167,14 @@ s->hsub = desc->log2_chroma_w; s->vsub = desc->log2_chroma_h; s->depth = desc->comp[0].depth; - if (s->depth > 8) { - s->histy = av_malloc_array(1 << s->depth, sizeof(*s->histy)); - s->histu = av_malloc_array(1 << s->depth, sizeof(*s->histu)); - s->histv = av_malloc_array(1 << s->depth, sizeof(*s->histv)); - s->histsat = av_malloc_array(1 << s->depth, sizeof(*s->histsat)); + s->maxsize = 1 << s->depth; + s->histy = av_malloc_array(s->maxsize, sizeof(*s->histy)); + s->histu = av_malloc_array(s->maxsize, sizeof(*s->histu)); + s->histv = av_malloc_array(s->maxsize, sizeof(*s->histv)); + s->histsat = av_malloc_array(s->maxsize, sizeof(*s->histsat)); - if (!s->histy || !s->histu || !s->histv || !s->histsat) - return AVERROR(ENOMEM); - } + if (!s->histy || !s->histu || !s->histv || !s->histsat) + return AVERROR(ENOMEM); outlink->w = inlink->w; outlink->h = inlink->h; @@ -462,8 +462,6 @@ {NULL} }; -#define DEPTH 256 - static int compute_sat_hue_metrics8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { int i, j; @@ -491,7 +489,7 @@ const int yuvu = p_u[i]; const int yuvv = p_v[i]; p_sat[i] = hypot(yuvu - 128, yuvv - 128); // int or round? - ((int16_t*)p_hue)[i] = floor((180 / M_PI) * atan2f(yuvu-128, yuvv-128) + 180); + ((int16_t*)p_hue)[i] = fmod(floor((180 / M_PI) * atan2f(yuvu-128, yuvv-128) + 180), 360.); } p_u += lsz_u; p_v += lsz_v; @@ -530,7 +528,7 @@ const int yuvu = p_u[i]; const int yuvv = p_v[i]; p_sat[i] = hypot(yuvu - mid, yuvv - mid); // int or round? - ((int16_t*)p_hue)[i] = floor((180 / M_PI) * atan2f(yuvu-mid, yuvv-mid) + 180); + ((int16_t*)p_hue)[i] = fmod(floor((180 / M_PI) * atan2f(yuvu-mid, yuvv-mid) + 180), 360.); } p_u += lsz_u; p_v += lsz_v; @@ -557,11 +555,11 @@ pw = 0, cpw = 0; // prev int fil; char metabuf[128]; - unsigned int histy[DEPTH] = {0}, - histu[DEPTH] = {0}, - histv[DEPTH] = {0}, + unsigned int *histy = s->histy, + *histu = s->histu, + *histv = s->histv, histhue[360] = {0}, - histsat[DEPTH] = {0}; // limited to 8 bit data. + *histsat = s->histsat; int miny = -1, minu = -1, minv = -1; int maxy = -1, maxu = -1, maxv = -1; int lowy = -1, lowu = -1, lowv = -1; @@ -605,6 +603,7 @@ NULL, FFMIN(s->chromah, ff_filter_get_nb_threads(ctx))); // Calculate luma histogram and difference with previous frame or field. + memset(s->histy, 0, s->maxsize * sizeof(*s->histy)); for (j = 0; j < link->h; j++) { for (i = 0; i < link->w; i++) { const int yuv = in->data[0][w + i]; @@ -618,6 +617,9 @@ } // Calculate chroma histogram and difference with previous frame or field. + memset(s->histu, 0, s->maxsize * sizeof(*s->histu)); + memset(s->histv, 0, s->maxsize * sizeof(*s->histv)); + memset(s->histsat, 0, s->maxsize * sizeof(*s->histsat)); for (j = 0; j < s->chromah; j++) { for (i = 0; i < s->chromaw; i++) { const int yuvu = in->data[1][cw+i]; @@ -662,7 +664,7 @@ chighp = lrint(s->cfs * 90 / 100.); accy = accu = accv = accsat = 0; - for (fil = 0; fil < DEPTH; fil++) { + for (fil = 0; fil < s->maxsize; fil++) { if (miny < 0 && histy[fil]) miny = fil; if (minu < 0 && histu[fil]) minu = fil; if (minv < 0 && histv[fil]) minv = fil; @@ -823,7 +825,7 @@ NULL, FFMIN(s->chromah, ff_filter_get_nb_threads(ctx))); // Calculate luma histogram and difference with previous frame or field. - memset(s->histy, 0, (1 << s->depth) * sizeof(*s->histy)); + memset(s->histy, 0, s->maxsize * sizeof(*s->histy)); for (j = 0; j < link->h; j++) { for (i = 0; i < link->w; i++) { const int yuv = AV_RN16(in->data[0] + w + i * 2); @@ -837,9 +839,9 @@ } // Calculate chroma histogram and difference with previous frame or field. - memset(s->histu, 0, (1 << s->depth) * sizeof(*s->histu)); - memset(s->histv, 0, (1 << s->depth) * sizeof(*s->histv)); - memset(s->histsat, 0, (1 << s->depth) * sizeof(*s->histsat)); + memset(s->histu, 0, s->maxsize * sizeof(*s->histu)); + memset(s->histv, 0, s->maxsize * sizeof(*s->histv)); + memset(s->histsat, 0, s->maxsize * sizeof(*s->histsat)); for (j = 0; j < s->chromah; j++) { for (i = 0; i < s->chromaw; i++) { const int yuvu = AV_RN16(in->data[1] + cw + i * 2); @@ -884,7 +886,7 @@ chighp = lrint(s->cfs * 90 / 100.); accy = accu = accv = accsat = 0; - for (fil = 0; fil < 1 << s->depth; fil++) { + for (fil = 0; fil < s->maxsize; fil++) { if (miny < 0 && histy[fil]) miny = fil; if (minu < 0 && histu[fil]) minu = fil; if (minv < 0 && histv[fil]) minv = fil; @@ -1004,7 +1006,7 @@ static const AVFilterPad signalstats_outputs[] = { { .name = "default", - .config_props = config_props, + .config_props = config_output, .type = AVMEDIA_TYPE_VIDEO, }, { NULL } diff -Nru ffmpeg-4.2.2/libavfilter/vf_signature.c ffmpeg-4.4/libavfilter/vf_signature.c --- ffmpeg-4.2.2/libavfilter/vf_signature.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_signature.c 2021-04-08 21:28:40.000000000 +0000 @@ -132,8 +132,9 @@ return sum; } -static int cmp(const uint64_t *a, const uint64_t *b) +static int cmp(const void *x, const void *y) { + const uint64_t *a = x, *b = y; return *a < *b ? -1 : ( *a > *b ? 1 : 0 ); } @@ -291,7 +292,7 @@ } /* get threshold */ - qsort(sortsignature, elemcat->elem_count, sizeof(uint64_t), (void*) cmp); + qsort(sortsignature, elemcat->elem_count, sizeof(uint64_t), cmp); th = sortsignature[(int) (elemcat->elem_count*0.333)]; /* ternarize */ @@ -317,7 +318,7 @@ } /* confidence */ - qsort(conflist, DIFFELEM_SIZE, sizeof(uint64_t), (void*) cmp); + qsort(conflist, DIFFELEM_SIZE, sizeof(uint64_t), cmp); fs->confidence = FFMIN(conflist[DIFFELEM_SIZE/2], 255); /* coarsesignature */ @@ -559,7 +560,6 @@ } } - avpriv_align_put_bits(&buf); flush_put_bits(&buf); fwrite(buffer, 1, put_bits_count(&buf)/8, f); fclose(f); @@ -664,6 +664,10 @@ if (!pad.name) return AVERROR(ENOMEM); + if ((ret = ff_insert_inpad(ctx, i, &pad)) < 0) { + av_freep(&pad.name); + return ret; + } sc = &(sic->streamcontexts[i]); @@ -680,11 +684,6 @@ sc->coarseend = sc->coarsesiglist; sc->coarsecount = 0; sc->midcoarse = 0; - - if ((ret = ff_insert_inpad(ctx, i, &pad)) < 0) { - av_freep(&pad.name); - return ret; - } } /* check filename */ @@ -731,6 +730,8 @@ } av_freep(&sic->streamcontexts); } + for (unsigned i = 0; i < ctx->nb_inputs; i++) + av_freep(&ctx->input_pads[i].name); } static int config_output(AVFilterLink *outlink) diff -Nru ffmpeg-4.2.2/libavfilter/vf_spp.c ffmpeg-4.4/libavfilter/vf_spp.c --- ffmpeg-4.2.2/libavfilter/vf_spp.c 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_spp.c 2021-04-08 21:28:40.000000000 +0000 @@ -33,9 +33,11 @@ #include "libavutil/avassert.h" #include "libavutil/imgutils.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "internal.h" +#include "qp_table.h" #include "vf_spp.h" enum mode { @@ -44,10 +46,19 @@ NB_MODES }; +#if FF_API_CHILD_CLASS_NEXT static const AVClass *child_class_next(const AVClass *prev) { return prev ? NULL : avcodec_dct_get_class(); } +#endif + +static const AVClass *child_class_iterate(void **iter) +{ + const AVClass *c = *iter ? NULL : avcodec_dct_get_class(); + *iter = (void*)(uintptr_t)c; + return c; +} static void *child_next(void *obj, void *prev) { @@ -57,8 +68,9 @@ #define OFFSET(x) offsetof(SPPContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption spp_options[] = { - { "quality", "set quality", OFFSET(log2_count), AV_OPT_TYPE_INT, {.i64 = 3}, 0, MAX_LEVEL, FLAGS }, + { "quality", "set quality", OFFSET(log2_count), AV_OPT_TYPE_INT, {.i64 = 3}, 0, MAX_LEVEL, TFLAGS }, { "qp", "force a constant quantizer parameter", OFFSET(qp), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 63, FLAGS }, { "mode", "set thresholding mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_HARD}, 0, NB_MODES - 1, FLAGS, "mode" }, { "hard", "hard thresholding", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_HARD}, INT_MIN, INT_MAX, FLAGS, "mode" }, @@ -73,7 +85,10 @@ .option = spp_options, .version = LIBAVUTIL_VERSION_INT, .category = AV_CLASS_CATEGORY_FILTER, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = child_class_next, +#endif + .child_class_iterate = child_class_iterate, .child_next = child_next, }; @@ -222,10 +237,14 @@ int y; for (y = 0; y < 8; y++) { - *(uint32_t *)&dst[0 + y*linesize] += *(uint32_t *)&block[0 + y*8]; - *(uint32_t *)&dst[2 + y*linesize] += *(uint32_t *)&block[2 + y*8]; - *(uint32_t *)&dst[4 + y*linesize] += *(uint32_t *)&block[4 + y*8]; - *(uint32_t *)&dst[6 + y*linesize] += *(uint32_t *)&block[6 + y*8]; + dst[0 + y*linesize] += block[0 + y*8]; + dst[1 + y*linesize] += block[1 + y*8]; + dst[2 + y*linesize] += block[2 + y*8]; + dst[3 + y*linesize] += block[3 + y*8]; + dst[4 + y*linesize] += block[4 + y*8]; + dst[5 + y*linesize] += block[5 + y*8]; + dst[6 + y*linesize] += block[6 + y*8]; + dst[7 + y*linesize] += block[7 + y*8]; } } @@ -278,7 +297,7 @@ const int x1 = x + offset[i + count - 1][0]; const int y1 = y + offset[i + count - 1][1]; const int index = x1 + y1*linesize; - p->dct->get_pixels(block, p->src + sample_bytes*index, sample_bytes*linesize); + p->dct->get_pixels_unaligned(block, p->src + sample_bytes*index, sample_bytes*linesize); p->dct->fdct(block); p->requantize(block2, block, qp, p->dct->idct_permutation); p->dct->idct(block2); @@ -357,47 +376,34 @@ AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out = in; int qp_stride = 0; - const int8_t *qp_table = NULL; + int8_t *qp_table = NULL; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); const int depth = desc->comp[0].depth; + int ret = 0; /* if we are not in a constant user quantizer mode and we don't want to use * the quantizers from the B-frames (B-frames often have a higher QP), we * need to save the qp table from the last non B-frame; this is what the * following code block does */ - if (!s->qp) { - qp_table = av_frame_get_qp_table(in, &qp_stride, &s->qscale_type); - - if (qp_table && !s->use_bframe_qp && in->pict_type != AV_PICTURE_TYPE_B) { - int w, h; - - /* if the qp stride is not set, it means the QP are only defined on - * a line basis */ - if (!qp_stride) { - w = AV_CEIL_RSHIFT(inlink->w, 4); - h = 1; - } else { - w = qp_stride; - h = AV_CEIL_RSHIFT(inlink->h, 4); - } - - if (w * h > s->non_b_qp_alloc_size) { - int ret = av_reallocp_array(&s->non_b_qp_table, w, h); - if (ret < 0) { - s->non_b_qp_alloc_size = 0; - return ret; - } - s->non_b_qp_alloc_size = w * h; - } + if (!s->qp && (s->use_bframe_qp || in->pict_type != AV_PICTURE_TYPE_B)) { + ret = ff_qp_table_extract(in, &qp_table, &qp_stride, NULL, &s->qscale_type); + if (ret < 0) { + av_frame_free(&in); + return ret; + } - av_assert0(w * h <= s->non_b_qp_alloc_size); - memcpy(s->non_b_qp_table, qp_table, w * h); + if (!s->use_bframe_qp && in->pict_type != AV_PICTURE_TYPE_B) { + av_freep(&s->non_b_qp_table); + s->non_b_qp_table = qp_table; + s->non_b_qp_stride = qp_stride; } } if (s->log2_count && !ctx->is_disabled) { - if (!s->use_bframe_qp && s->non_b_qp_table) - qp_table = s->non_b_qp_table; + if (!s->use_bframe_qp && s->non_b_qp_table) { + qp_table = s->non_b_qp_table; + qp_stride = s->non_b_qp_stride; + } if (qp_table || s->qp) { const int cw = AV_CEIL_RSHIFT(inlink->w, s->hsub); @@ -412,7 +418,8 @@ out = ff_get_video_buffer(outlink, aligned_w, aligned_h); if (!out) { av_frame_free(&in); - return AVERROR(ENOMEM); + ret = AVERROR(ENOMEM); + goto finish; } av_frame_copy_props(out, in); out->width = in->width; @@ -436,7 +443,11 @@ inlink->w, inlink->h); av_frame_free(&in); } - return ff_filter_frame(outlink, out); + ret = ff_filter_frame(outlink, out); +finish: + if (qp_table != s->non_b_qp_table) + av_freep(&qp_table); + return ret; } static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, @@ -444,7 +455,7 @@ { SPPContext *s = ctx->priv; - if (!strcmp(cmd, "level")) { + if (!strcmp(cmd, "level") || !strcmp(cmd, "quality")) { if (!strcmp(args, "max")) s->log2_count = MAX_LEVEL; else @@ -459,9 +470,8 @@ SPPContext *s = ctx->priv; int ret; - s->avctx = avcodec_alloc_context3(NULL); s->dct = avcodec_dct_alloc(); - if (!s->avctx || !s->dct) + if (!s->dct) return AVERROR(ENOMEM); if (opts) { @@ -488,10 +498,6 @@ av_freep(&s->temp); av_freep(&s->src); - if (s->avctx) { - avcodec_close(s->avctx); - av_freep(&s->avctx); - } av_freep(&s->dct); av_freep(&s->non_b_qp_table); } diff -Nru ffmpeg-4.2.2/libavfilter/vf_spp.h ffmpeg-4.4/libavfilter/vf_spp.h --- ffmpeg-4.2.2/libavfilter/vf_spp.h 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_spp.h 2021-04-08 21:28:40.000000000 +0000 @@ -22,7 +22,6 @@ #ifndef AVFILTER_SPP_H #define AVFILTER_SPP_H -#include "libavcodec/avcodec.h" #include "libavcodec/avdct.h" #include "avfilter.h" @@ -38,10 +37,9 @@ int temp_linesize; uint8_t *src; uint16_t *temp; - AVCodecContext *avctx; AVDCT *dct; int8_t *non_b_qp_table; - int non_b_qp_alloc_size; + int non_b_qp_stride; int use_bframe_qp; int hsub, vsub; diff -Nru ffmpeg-4.2.2/libavfilter/vf_sr.c ffmpeg-4.4/libavfilter/vf_sr.c --- ffmpeg-4.2.2/libavfilter/vf_sr.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_sr.c 2021-04-08 21:28:40.000000000 +0000 @@ -32,32 +32,29 @@ #include "libavutil/pixdesc.h" #include "libavformat/avio.h" #include "libswscale/swscale.h" -#include "dnn_interface.h" +#include "dnn_filter_common.h" typedef struct SRContext { const AVClass *class; - - char *model_filename; - DNNBackendType backend_type; - DNNModule *dnn_module; - DNNModel *model; - DNNInputData input; - DNNData output; + DnnContext dnnctx; int scale_factor; - struct SwsContext *sws_contexts[3]; - int sws_slice_h, sws_input_linesize, sws_output_linesize; + struct SwsContext *sws_uv_scale; + int sws_uv_height; + struct SwsContext *sws_pre_scale; } SRContext; #define OFFSET(x) offsetof(SRContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM static const AVOption sr_options[] = { - { "dnn_backend", "DNN backend used for model execution", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "backend" }, + { "dnn_backend", "DNN backend used for model execution", OFFSET(dnnctx.backend_type), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "backend" }, { "native", "native backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "backend" }, #if (CONFIG_LIBTENSORFLOW == 1) { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" }, #endif { "scale_factor", "scale factor for SRCNN model", OFFSET(scale_factor), AV_OPT_TYPE_INT, { .i64 = 2 }, 2, 4, FLAGS }, - { "model", "path to model file specifying network architecture and its parameters", OFFSET(model_filename), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "model", "path to model file specifying network architecture and its parameters", OFFSET(dnnctx.model_filename), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "input", "input name of the model", OFFSET(dnnctx.model_inputname), AV_OPT_TYPE_STRING, { .str = "x" }, 0, 0, FLAGS }, + { "output", "output name of the model", OFFSET(dnnctx.model_outputname), AV_OPT_TYPE_STRING, { .str = "y" }, 0, 0, FLAGS }, { NULL } }; @@ -66,33 +63,7 @@ static av_cold int init(AVFilterContext *context) { SRContext *sr_context = context->priv; - - sr_context->dnn_module = ff_get_dnn_module(sr_context->backend_type); - if (!sr_context->dnn_module){ - av_log(context, AV_LOG_ERROR, "could not create DNN module for requested backend\n"); - return AVERROR(ENOMEM); - } - - if (!sr_context->model_filename){ - av_log(context, AV_LOG_ERROR, "model file for network was not specified\n"); - return AVERROR(EIO); - } - if (!sr_context->dnn_module->load_model) { - av_log(context, AV_LOG_ERROR, "load_model for network was not specified\n"); - return AVERROR(EIO); - } - sr_context->model = (sr_context->dnn_module->load_model)(sr_context->model_filename); - if (!sr_context->model){ - av_log(context, AV_LOG_ERROR, "could not load DNN model\n"); - return AVERROR(EIO); - } - - sr_context->input.dt = DNN_FLOAT; - sr_context->sws_contexts[0] = NULL; - sr_context->sws_contexts[1] = NULL; - sr_context->sws_contexts[2] = NULL; - - return 0; + return ff_dnn_init(&sr_context->dnnctx, DFT_PROCESS_FRAME, context); } static int query_formats(AVFilterContext *context) @@ -111,114 +82,43 @@ return ff_set_common_formats(context, formats_list); } -static int config_props(AVFilterLink *inlink) +static int config_output(AVFilterLink *outlink) { - AVFilterContext *context = inlink->dst; - SRContext *sr_context = context->priv; - AVFilterLink *outlink = context->outputs[0]; + AVFilterContext *context = outlink->src; + SRContext *ctx = context->priv; DNNReturnType result; - int sws_src_h, sws_src_w, sws_dst_h, sws_dst_w; - const char *model_output_name = "y"; - - sr_context->input.width = inlink->w * sr_context->scale_factor; - sr_context->input.height = inlink->h * sr_context->scale_factor; - sr_context->input.channels = 1; - - result = (sr_context->model->set_input_output)(sr_context->model->model, &sr_context->input, "x", &model_output_name, 1); - if (result != DNN_SUCCESS){ - av_log(context, AV_LOG_ERROR, "could not set input and output for the model\n"); - return AVERROR(EIO); - } + AVFilterLink *inlink = context->inputs[0]; + int out_width, out_height; - result = (sr_context->dnn_module->execute_model)(sr_context->model, &sr_context->output, 1); - if (result != DNN_SUCCESS){ - av_log(context, AV_LOG_ERROR, "failed to execute loaded model\n"); + // have a try run in case that the dnn model resize the frame + result = ff_dnn_get_output(&ctx->dnnctx, inlink->w, inlink->h, &out_width, &out_height); + if (result != DNN_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "could not get output from the model\n"); return AVERROR(EIO); } - if (sr_context->input.height != sr_context->output.height || sr_context->input.width != sr_context->output.width){ - sr_context->input.width = inlink->w; - sr_context->input.height = inlink->h; - result = (sr_context->model->set_input_output)(sr_context->model->model, &sr_context->input, "x", &model_output_name, 1); - if (result != DNN_SUCCESS){ - av_log(context, AV_LOG_ERROR, "could not set input and output for the model\n"); - return AVERROR(EIO); - } - result = (sr_context->dnn_module->execute_model)(sr_context->model, &sr_context->output, 1); - if (result != DNN_SUCCESS){ - av_log(context, AV_LOG_ERROR, "failed to execute loaded model\n"); - return AVERROR(EIO); - } - sr_context->scale_factor = 0; - } - outlink->h = sr_context->output.height; - outlink->w = sr_context->output.width; - sr_context->sws_contexts[1] = sws_getContext(sr_context->input.width, sr_context->input.height, AV_PIX_FMT_GRAY8, - sr_context->input.width, sr_context->input.height, AV_PIX_FMT_GRAYF32, - 0, NULL, NULL, NULL); - sr_context->sws_input_linesize = sr_context->input.width << 2; - sr_context->sws_contexts[2] = sws_getContext(sr_context->output.width, sr_context->output.height, AV_PIX_FMT_GRAYF32, - sr_context->output.width, sr_context->output.height, AV_PIX_FMT_GRAY8, - 0, NULL, NULL, NULL); - sr_context->sws_output_linesize = sr_context->output.width << 2; - if (!sr_context->sws_contexts[1] || !sr_context->sws_contexts[2]){ - av_log(context, AV_LOG_ERROR, "could not create SwsContext for conversions\n"); - return AVERROR(ENOMEM); - } - if (sr_context->scale_factor){ - sr_context->sws_contexts[0] = sws_getContext(inlink->w, inlink->h, inlink->format, - outlink->w, outlink->h, outlink->format, - SWS_BICUBIC, NULL, NULL, NULL); - if (!sr_context->sws_contexts[0]){ - av_log(context, AV_LOG_ERROR, "could not create SwsContext for scaling\n"); - return AVERROR(ENOMEM); - } - sr_context->sws_slice_h = inlink->h; - } else { + if (inlink->w != out_width || inlink->h != out_height) { + //espcn + outlink->w = out_width; + outlink->h = out_height; if (inlink->format != AV_PIX_FMT_GRAY8){ - sws_src_h = sr_context->input.height; - sws_src_w = sr_context->input.width; - sws_dst_h = sr_context->output.height; - sws_dst_w = sr_context->output.width; - - switch (inlink->format){ - case AV_PIX_FMT_YUV420P: - sws_src_h = AV_CEIL_RSHIFT(sws_src_h, 1); - sws_src_w = AV_CEIL_RSHIFT(sws_src_w, 1); - sws_dst_h = AV_CEIL_RSHIFT(sws_dst_h, 1); - sws_dst_w = AV_CEIL_RSHIFT(sws_dst_w, 1); - break; - case AV_PIX_FMT_YUV422P: - sws_src_w = AV_CEIL_RSHIFT(sws_src_w, 1); - sws_dst_w = AV_CEIL_RSHIFT(sws_dst_w, 1); - break; - case AV_PIX_FMT_YUV444P: - break; - case AV_PIX_FMT_YUV410P: - sws_src_h = AV_CEIL_RSHIFT(sws_src_h, 2); - sws_src_w = AV_CEIL_RSHIFT(sws_src_w, 2); - sws_dst_h = AV_CEIL_RSHIFT(sws_dst_h, 2); - sws_dst_w = AV_CEIL_RSHIFT(sws_dst_w, 2); - break; - case AV_PIX_FMT_YUV411P: - sws_src_w = AV_CEIL_RSHIFT(sws_src_w, 2); - sws_dst_w = AV_CEIL_RSHIFT(sws_dst_w, 2); - break; - default: - av_log(context, AV_LOG_ERROR, - "could not create SwsContext for scaling for given input pixel format: %s\n", - av_get_pix_fmt_name(inlink->format)); - return AVERROR(EIO); - } - sr_context->sws_contexts[0] = sws_getContext(sws_src_w, sws_src_h, AV_PIX_FMT_GRAY8, - sws_dst_w, sws_dst_h, AV_PIX_FMT_GRAY8, - SWS_BICUBIC, NULL, NULL, NULL); - if (!sr_context->sws_contexts[0]){ - av_log(context, AV_LOG_ERROR, "could not create SwsContext for scaling\n"); - return AVERROR(ENOMEM); - } - sr_context->sws_slice_h = sws_src_h; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int sws_src_h = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + int sws_src_w = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + int sws_dst_h = AV_CEIL_RSHIFT(outlink->h, desc->log2_chroma_h); + int sws_dst_w = AV_CEIL_RSHIFT(outlink->w, desc->log2_chroma_w); + ctx->sws_uv_scale = sws_getContext(sws_src_w, sws_src_h, AV_PIX_FMT_GRAY8, + sws_dst_w, sws_dst_h, AV_PIX_FMT_GRAY8, + SWS_BICUBIC, NULL, NULL, NULL); + ctx->sws_uv_height = sws_src_h; } + } else { + //srcnn + outlink->w = out_width * ctx->scale_factor; + outlink->h = out_height * ctx->scale_factor; + ctx->sws_pre_scale = sws_getContext(inlink->w, inlink->h, inlink->format, + outlink->w, outlink->h, outlink->format, + SWS_BICUBIC, NULL, NULL, NULL); } return 0; @@ -227,7 +127,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *context = inlink->dst; - SRContext *sr_context = context->priv; + SRContext *ctx = context->priv; AVFilterLink *outlink = context->outputs[0]; AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); DNNReturnType dnn_result; @@ -238,62 +138,47 @@ return AVERROR(ENOMEM); } av_frame_copy_props(out, in); - out->height = sr_context->output.height; - out->width = sr_context->output.width; - if (sr_context->scale_factor){ - sws_scale(sr_context->sws_contexts[0], (const uint8_t **)in->data, in->linesize, - 0, sr_context->sws_slice_h, out->data, out->linesize); - - sws_scale(sr_context->sws_contexts[1], (const uint8_t **)out->data, out->linesize, - 0, out->height, (uint8_t * const*)(&sr_context->input.data), - (const int [4]){sr_context->sws_input_linesize, 0, 0, 0}); - } else { - if (sr_context->sws_contexts[0]){ - sws_scale(sr_context->sws_contexts[0], (const uint8_t **)(in->data + 1), in->linesize + 1, - 0, sr_context->sws_slice_h, out->data + 1, out->linesize + 1); - sws_scale(sr_context->sws_contexts[0], (const uint8_t **)(in->data + 2), in->linesize + 2, - 0, sr_context->sws_slice_h, out->data + 2, out->linesize + 2); - } - sws_scale(sr_context->sws_contexts[1], (const uint8_t **)in->data, in->linesize, - 0, in->height, (uint8_t * const*)(&sr_context->input.data), - (const int [4]){sr_context->sws_input_linesize, 0, 0, 0}); + if (ctx->sws_pre_scale) { + sws_scale(ctx->sws_pre_scale, + (const uint8_t **)in->data, in->linesize, 0, in->height, + out->data, out->linesize); + dnn_result = ff_dnn_execute_model(&ctx->dnnctx, out, out); + } else { + dnn_result = ff_dnn_execute_model(&ctx->dnnctx, in, out); } - av_frame_free(&in); - dnn_result = (sr_context->dnn_module->execute_model)(sr_context->model, &sr_context->output, 1); if (dnn_result != DNN_SUCCESS){ - av_log(context, AV_LOG_ERROR, "failed to execute loaded model\n"); + av_log(ctx, AV_LOG_ERROR, "failed to execute loaded model\n"); + av_frame_free(&in); + av_frame_free(&out); return AVERROR(EIO); } - sws_scale(sr_context->sws_contexts[2], (const uint8_t *[4]){(const uint8_t *)sr_context->output.data, 0, 0, 0}, - (const int[4]){sr_context->sws_output_linesize, 0, 0, 0}, - 0, out->height, (uint8_t * const*)out->data, out->linesize); + if (ctx->sws_uv_scale) { + sws_scale(ctx->sws_uv_scale, (const uint8_t **)(in->data + 1), in->linesize + 1, + 0, ctx->sws_uv_height, out->data + 1, out->linesize + 1); + sws_scale(ctx->sws_uv_scale, (const uint8_t **)(in->data + 2), in->linesize + 2, + 0, ctx->sws_uv_height, out->data + 2, out->linesize + 2); + } + av_frame_free(&in); return ff_filter_frame(outlink, out); } static av_cold void uninit(AVFilterContext *context) { - int i; SRContext *sr_context = context->priv; - if (sr_context->dnn_module){ - (sr_context->dnn_module->free_model)(&sr_context->model); - av_freep(&sr_context->dnn_module); - } - - for (i = 0; i < 3; ++i){ - sws_freeContext(sr_context->sws_contexts[i]); - } + ff_dnn_uninit(&sr_context->dnnctx); + sws_freeContext(sr_context->sws_uv_scale); + sws_freeContext(sr_context->sws_pre_scale); } static const AVFilterPad sr_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .config_props = config_props, .filter_frame = filter_frame, }, { NULL } @@ -302,6 +187,7 @@ static const AVFilterPad sr_outputs[] = { { .name = "default", + .config_props = config_output, .type = AVMEDIA_TYPE_VIDEO, }, { NULL } @@ -317,5 +203,4 @@ .inputs = sr_inputs, .outputs = sr_outputs, .priv_class = &sr_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_ssim.c ffmpeg-4.4/libavfilter/vf_ssim.c --- ffmpeg-4.2.2/libavfilter/vf_ssim.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_ssim.c 2021-04-08 21:28:40.000000000 +0000 @@ -51,21 +51,20 @@ FILE *stats_file; char *stats_file_str; int nb_components; + int nb_threads; int max; uint64_t nb_frames; double ssim[4], ssim_total; char comps[4]; - float coefs[4]; + double coefs[4]; uint8_t rgba_map[4]; int planewidth[4]; int planeheight[4]; - int *temp; + int **temp; int is_rgb; - float (*ssim_plane)(SSIMDSPContext *dsp, - uint8_t *main, int main_stride, - uint8_t *ref, int ref_stride, - int width, int height, void *temp, - int max); + double **score; + int (*ssim_plane)(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs); SSIMDSPContext dsp; } SSIMContext; @@ -83,7 +82,7 @@ static void set_meta(AVDictionary **metadata, const char *key, char comp, float d) { char value[128]; - snprintf(value, sizeof(value), "%0.2f", d); + snprintf(value, sizeof(value), "%f", d); if (comp) { char key2[128]; snprintf(key2, sizeof(key2), "%s%c", key, comp); @@ -206,9 +205,9 @@ return ssim; } -static float ssim_endn_8bit(const int (*sum0)[4], const int (*sum1)[4], int width) +static double ssim_endn_8bit(const int (*sum0)[4], const int (*sum1)[4], int width) { - float ssim = 0.0; + double ssim = 0.0; int i; for (i = 0; i < width; i++) @@ -221,65 +220,109 @@ #define SUM_LEN(w) (((w) >> 2) + 3) -static float ssim_plane_16bit(SSIMDSPContext *dsp, - uint8_t *main, int main_stride, - uint8_t *ref, int ref_stride, - int width, int height, void *temp, - int max) -{ - int z = 0, y; - float ssim = 0.0; - int64_t (*sum0)[4] = temp; - int64_t (*sum1)[4] = sum0 + SUM_LEN(width); +typedef struct ThreadData { + const uint8_t *main_data[4]; + const uint8_t *ref_data[4]; + int main_linesize[4]; + int ref_linesize[4]; + int planewidth[4]; + int planeheight[4]; + double **score; + int **temp; + int nb_components; + int max; + SSIMDSPContext *dsp; +} ThreadData; - width >>= 2; - height >>= 2; +static int ssim_plane_16bit(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + ThreadData *td = arg; + double *score = td->score[jobnr]; + void *temp = td->temp[jobnr]; + const int max = td->max; + + for (int c = 0; c < td->nb_components; c++) { + const uint8_t *main_data = td->main_data[c]; + const uint8_t *ref_data = td->ref_data[c]; + const int main_stride = td->main_linesize[c]; + const int ref_stride = td->ref_linesize[c]; + int width = td->planewidth[c]; + int height = td->planeheight[c]; + const int slice_start = ((height >> 2) * jobnr) / nb_jobs; + const int slice_end = ((height >> 2) * (jobnr+1)) / nb_jobs; + const int ystart = FFMAX(1, slice_start); + int z = ystart - 1; + double ssim = 0.0; + int64_t (*sum0)[4] = temp; + int64_t (*sum1)[4] = sum0 + SUM_LEN(width); + + width >>= 2; + height >>= 2; + + for (int y = ystart; y < slice_end; y++) { + for (; z <= y; z++) { + FFSWAP(void*, sum0, sum1); + ssim_4x4xn_16bit(&main_data[4 * z * main_stride], main_stride, + &ref_data[4 * z * ref_stride], ref_stride, + sum0, width); + } - for (y = 1; y < height; y++) { - for (; z <= y; z++) { - FFSWAP(void*, sum0, sum1); - ssim_4x4xn_16bit(&main[4 * z * main_stride], main_stride, - &ref[4 * z * ref_stride], ref_stride, - sum0, width); + ssim += ssim_endn_16bit((const int64_t (*)[4])sum0, (const int64_t (*)[4])sum1, width - 1, max); } - ssim += ssim_endn_16bit((const int64_t (*)[4])sum0, (const int64_t (*)[4])sum1, width - 1, max); + score[c] = ssim; } - return ssim / ((height - 1) * (width - 1)); + return 0; } -static float ssim_plane(SSIMDSPContext *dsp, - uint8_t *main, int main_stride, - uint8_t *ref, int ref_stride, - int width, int height, void *temp, - int max) +static int ssim_plane(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) { - int z = 0, y; - float ssim = 0.0; - int (*sum0)[4] = temp; - int (*sum1)[4] = sum0 + SUM_LEN(width); - - width >>= 2; - height >>= 2; + ThreadData *td = arg; + double *score = td->score[jobnr]; + void *temp = td->temp[jobnr]; + SSIMDSPContext *dsp = td->dsp; + + for (int c = 0; c < td->nb_components; c++) { + const uint8_t *main_data = td->main_data[c]; + const uint8_t *ref_data = td->ref_data[c]; + const int main_stride = td->main_linesize[c]; + const int ref_stride = td->ref_linesize[c]; + int width = td->planewidth[c]; + int height = td->planeheight[c]; + const int slice_start = ((height >> 2) * jobnr) / nb_jobs; + const int slice_end = ((height >> 2) * (jobnr+1)) / nb_jobs; + const int ystart = FFMAX(1, slice_start); + int z = ystart - 1; + double ssim = 0.0; + int (*sum0)[4] = temp; + int (*sum1)[4] = sum0 + SUM_LEN(width); + + width >>= 2; + height >>= 2; + + for (int y = ystart; y < slice_end; y++) { + for (; z <= y; z++) { + FFSWAP(void*, sum0, sum1); + dsp->ssim_4x4_line(&main_data[4 * z * main_stride], main_stride, + &ref_data[4 * z * ref_stride], ref_stride, + sum0, width); + } - for (y = 1; y < height; y++) { - for (; z <= y; z++) { - FFSWAP(void*, sum0, sum1); - dsp->ssim_4x4_line(&main[4 * z * main_stride], main_stride, - &ref[4 * z * ref_stride], ref_stride, - sum0, width); + ssim += dsp->ssim_end_line((const int (*)[4])sum0, (const int (*)[4])sum1, width - 1); } - ssim += dsp->ssim_end_line((const int (*)[4])sum0, (const int (*)[4])sum1, width - 1); + score[c] = ssim; } - return ssim / ((height - 1) * (width - 1)); + return 0; } static double ssim_db(double ssim, double weight) { - return 10 * log10(weight / (weight - ssim)); + return (fabs(weight - ssim) > 1e-9) ? 10.0 * log10(weight / (weight - ssim)) : INFINITY; } static int do_ssim(FFFrameSync *fs) @@ -288,26 +331,47 @@ SSIMContext *s = ctx->priv; AVFrame *master, *ref; AVDictionary **metadata; - float c[4], ssimv = 0.0; + double c[4] = {0}, ssimv = 0.0; + ThreadData td; int ret, i; ret = ff_framesync_dualinput_get(fs, &master, &ref); if (ret < 0) return ret; - if (!ref) + if (ctx->is_disabled || !ref) return ff_filter_frame(ctx->outputs[0], master); metadata = &master->metadata; s->nb_frames++; + td.nb_components = s->nb_components; + td.dsp = &s->dsp; + td.score = s->score; + td.temp = s->temp; + td.max = s->max; + + for (int n = 0; n < s->nb_components; n++) { + td.main_data[n] = master->data[n]; + td.ref_data[n] = ref->data[n]; + td.main_linesize[n] = master->linesize[n]; + td.ref_linesize[n] = ref->linesize[n]; + td.planewidth[n] = s->planewidth[n]; + td.planeheight[n] = s->planeheight[n]; + } + + ctx->internal->execute(ctx, s->ssim_plane, &td, NULL, FFMIN((s->planeheight[1] + 3) >> 2, s->nb_threads)); + + for (i = 0; i < s->nb_components; i++) { + for (int j = 0; j < s->nb_threads; j++) + c[i] += s->score[j][i]; + c[i] = c[i] / (((s->planewidth[i] >> 2) - 1) * ((s->planeheight[i] >> 2) - 1)); + } + for (i = 0; i < s->nb_components; i++) { - c[i] = s->ssim_plane(&s->dsp, master->data[i], master->linesize[i], - ref->data[i], ref->linesize[i], - s->planewidth[i], s->planeheight[i], s->temp, - s->max); ssimv += s->coefs[i] * c[i]; s->ssim[i] += c[i]; } + for (i = 0; i < s->nb_components; i++) { int cidx = s->is_rgb ? s->rgba_map[i] : i; set_meta(metadata, "lavfi.ssim.", s->comps[i], c[cidx]); @@ -383,6 +447,7 @@ SSIMContext *s = ctx->priv; int sum = 0, i; + s->nb_threads = ff_filter_get_nb_threads(ctx); s->nb_components = desc->nb_components; if (ctx->inputs[0]->w != ctx->inputs[1]->w || @@ -410,9 +475,15 @@ for (i = 0; i < s->nb_components; i++) s->coefs[i] = (double) s->planeheight[i] * s->planewidth[i] / sum; - s->temp = av_mallocz_array(2 * SUM_LEN(inlink->w), (desc->comp[0].depth > 8) ? sizeof(int64_t[4]) : sizeof(int[4])); + s->temp = av_calloc(s->nb_threads, sizeof(*s->temp)); if (!s->temp) return AVERROR(ENOMEM); + + for (int t = 0; t < s->nb_threads; t++) { + s->temp[t] = av_mallocz_array(2 * SUM_LEN(inlink->w), (desc->comp[0].depth > 8) ? sizeof(int64_t[4]) : sizeof(int[4])); + if (!s->temp[t]) + return AVERROR(ENOMEM); + } s->max = (1 << desc->comp[0].depth) - 1; s->ssim_plane = desc->comp[0].depth > 8 ? ssim_plane_16bit : ssim_plane; @@ -421,6 +492,16 @@ if (ARCH_X86) ff_ssim_init_x86(&s->dsp); + s->score = av_calloc(s->nb_threads, sizeof(*s->score)); + if (!s->score) + return AVERROR(ENOMEM); + + for (int t = 0; t < s->nb_threads && s->score; t++) { + s->score[t] = av_calloc(s->nb_components, sizeof(*s->score[0])); + if (!s->score[t]) + return AVERROR(ENOMEM); + } + return 0; } @@ -443,6 +524,14 @@ if ((ret = ff_framesync_configure(&s->fs)) < 0) return ret; + outlink->time_base = s->fs.time_base; + + if (av_cmp_q(mainlink->time_base, outlink->time_base) || + av_cmp_q(ctx->inputs[1]->time_base, outlink->time_base)) + av_log(ctx, AV_LOG_WARNING, "not matching timebases found between first input: %d/%d and second input %d/%d, results may be incorrect!\n", + mainlink->time_base.num, mainlink->time_base.den, + ctx->inputs[1]->time_base.num, ctx->inputs[1]->time_base.den); + return 0; } @@ -474,6 +563,12 @@ if (s->stats_file && s->stats_file != stdout) fclose(s->stats_file); + for (int t = 0; t < s->nb_threads && s->score; t++) + av_freep(&s->score[t]); + av_freep(&s->score); + + for (int t = 0; t < s->nb_threads && s->temp; t++) + av_freep(&s->temp[t]); av_freep(&s->temp); } @@ -510,4 +605,5 @@ .priv_class = &ssim_class, .inputs = ssim_inputs, .outputs = ssim_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_stack.c ffmpeg-4.4/libavfilter/vf_stack.c --- ffmpeg-4.2.2/libavfilter/vf_stack.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_stack.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,9 +21,11 @@ #include "libavutil/avstring.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" +#include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" #include "avfilter.h" +#include "drawutils.h" #include "formats.h" #include "internal.h" #include "framesync.h" @@ -44,6 +46,12 @@ int is_vertical; int is_horizontal; int nb_planes; + uint8_t fillcolor[4]; + char *fillcolor_str; + int fillcolor_enable; + + FFDrawContext draw; + FFDrawColor color; StackItem *items; AVFrame **frames; @@ -52,19 +60,21 @@ static int query_formats(AVFilterContext *ctx) { - AVFilterFormats *pix_fmts = NULL; - int fmt, ret; + AVFilterFormats *formats = NULL; + StackContext *s = ctx->priv; + int ret; - for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); - if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_HWACCEL || - desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) && - (ret = ff_add_format(&pix_fmts, fmt)) < 0) - return ret; + if (s->fillcolor_enable) { + return ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0)); } - return ff_set_common_formats(ctx, pix_fmts); + ret = ff_formats_pixdesc_filter(&formats, 0, + AV_PIX_FMT_FLAG_HWACCEL | + AV_PIX_FMT_FLAG_BITSTREAM | + AV_PIX_FMT_FLAG_PAL); + if (ret < 0) + return ret; + return ff_set_common_formats(ctx, formats); } static av_cold int init(AVFilterContext *ctx) @@ -82,7 +92,17 @@ if (!s->frames) return AVERROR(ENOMEM); + s->items = av_calloc(s->nb_inputs, sizeof(*s->items)); + if (!s->items) + return AVERROR(ENOMEM); + if (!strcmp(ctx->filter->name, "xstack")) { + if (strcmp(s->fillcolor_str, "none") && + av_parse_color(s->fillcolor, s->fillcolor_str, -1, ctx) >= 0) { + s->fillcolor_enable = 1; + } else { + s->fillcolor_enable = 0; + } if (!s->layout) { if (s->nb_inputs == 2) { s->layout = av_strdup("0_0|w0_0"); @@ -93,10 +113,6 @@ return AVERROR(EINVAL); } } - - s->items = av_calloc(s->nb_inputs, sizeof(*s->items)); - if (!s->items) - return AVERROR(ENOMEM); } for (i = 0; i < s->nb_inputs; i++) { @@ -116,6 +132,29 @@ return 0; } +static int process_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) +{ + StackContext *s = ctx->priv; + AVFrame *out = arg; + AVFrame **in = s->frames; + const int start = (s->nb_inputs * job ) / nb_jobs; + const int end = (s->nb_inputs * (job+1)) / nb_jobs; + + for (int i = start; i < end; i++) { + StackItem *item = &s->items[i]; + + for (int p = 0; p < s->nb_planes; p++) { + av_image_copy_plane(out->data[p] + out->linesize[p] * item->y[p] + item->x[p], + out->linesize[p], + in[i]->data[p], + in[i]->linesize[p], + item->linesize[p], item->height[p]); + } + } + + return 0; +} + static int process_frame(FFFrameSync *fs) { AVFilterContext *ctx = fs->parent; @@ -123,7 +162,7 @@ StackContext *s = fs->opaque; AVFrame **in = s->frames; AVFrame *out; - int i, p, ret, offset[4] = { 0 }; + int i, ret; for (i = 0; i < s->nb_inputs; i++) { if ((ret = ff_framesync_get_frame(&s->fs, i, &in[i], 0)) < 0) @@ -136,47 +175,11 @@ out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); out->sample_aspect_ratio = outlink->sample_aspect_ratio; - for (i = 0; i < s->nb_inputs; i++) { - AVFilterLink *inlink = ctx->inputs[i]; - int linesize[4]; - int height[4]; + if (s->fillcolor_enable) + ff_fill_rectangle(&s->draw, &s->color, out->data, out->linesize, + 0, 0, outlink->w, outlink->h); - if (s->is_horizontal || s->is_vertical) { - if ((ret = av_image_fill_linesizes(linesize, inlink->format, inlink->w)) < 0) { - av_frame_free(&out); - return ret; - } - - height[1] = height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h); - height[0] = height[3] = inlink->h; - } - - for (p = 0; p < s->nb_planes; p++) { - if (s->is_vertical) { - av_image_copy_plane(out->data[p] + offset[p] * out->linesize[p], - out->linesize[p], - in[i]->data[p], - in[i]->linesize[p], - linesize[p], height[p]); - offset[p] += height[p]; - } else if (s->is_horizontal) { - av_image_copy_plane(out->data[p] + offset[p], - out->linesize[p], - in[i]->data[p], - in[i]->linesize[p], - linesize[p], height[p]); - offset[p] += linesize[p]; - } else { - StackItem *item = &s->items[i]; - - av_image_copy_plane(out->data[p] + out->linesize[p] * item->y[p] + item->x[p], - out->linesize[p], - in[i]->data[p], - in[i]->linesize[p], - item->linesize[p], item->height[p]); - } - } - } + ctx->internal->execute(ctx, process_slice, out, NULL, FFMIN(s->nb_inputs, ff_filter_get_nb_threads(ctx))); return ff_filter_frame(outlink, out); } @@ -197,20 +200,53 @@ return AVERROR_BUG; if (s->is_vertical) { - for (i = 1; i < s->nb_inputs; i++) { + for (i = 0; i < s->nb_inputs; i++) { + AVFilterLink *inlink = ctx->inputs[i]; + StackItem *item = &s->items[i]; + if (ctx->inputs[i]->w != width) { av_log(ctx, AV_LOG_ERROR, "Input %d width %d does not match input %d width %d.\n", i, ctx->inputs[i]->w, 0, width); return AVERROR(EINVAL); } - height += ctx->inputs[i]->h; + + if ((ret = av_image_fill_linesizes(item->linesize, inlink->format, inlink->w)) < 0) { + return ret; + } + + item->height[1] = item->height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h); + item->height[0] = item->height[3] = inlink->h; + + if (i) { + item->y[1] = item->y[2] = AV_CEIL_RSHIFT(height, s->desc->log2_chroma_h); + item->y[0] = item->y[3] = height; + + height += ctx->inputs[i]->h; + } } } else if (s->is_horizontal) { - for (i = 1; i < s->nb_inputs; i++) { + for (i = 0; i < s->nb_inputs; i++) { + AVFilterLink *inlink = ctx->inputs[i]; + StackItem *item = &s->items[i]; + if (ctx->inputs[i]->h != height) { av_log(ctx, AV_LOG_ERROR, "Input %d height %d does not match input %d height %d.\n", i, ctx->inputs[i]->h, 0, height); return AVERROR(EINVAL); } - width += ctx->inputs[i]->w; + + if ((ret = av_image_fill_linesizes(item->linesize, inlink->format, inlink->w)) < 0) { + return ret; + } + + item->height[1] = item->height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h); + item->height[0] = item->height[3] = inlink->h; + + if (i) { + if ((ret = av_image_fill_linesizes(item->x, inlink->format, width)) < 0) { + return ret; + } + + width += ctx->inputs[i]->w; + } } } else { char *arg, *p = s->layout, *saveptr = NULL; @@ -218,6 +254,11 @@ char *arg3, *p3, *saveptr3 = NULL; int inw, inh, size; + if (s->fillcolor_enable) { + ff_draw_init(&s->draw, ctx->inputs[0]->format, 0); + ff_draw_color(&s->draw, &s->color, s->fillcolor); + } + for (i = 0; i < s->nb_inputs; i++) { AVFilterLink *inlink = ctx->inputs[i]; StackItem *item = &s->items[i]; @@ -294,6 +335,17 @@ outlink->frame_rate = frame_rate; outlink->sample_aspect_ratio = sar; + for (i = 1; i < s->nb_inputs; i++) { + AVFilterLink *inlink = ctx->inputs[i]; + if (outlink->frame_rate.num != inlink->frame_rate.num || + outlink->frame_rate.den != inlink->frame_rate.den) { + av_log(ctx, AV_LOG_VERBOSE, + "Video inputs have different frame rates, output will be VFR\n"); + outlink->frame_rate = av_make_q(1, 0); + break; + } + } + if ((ret = ff_framesync_init(&s->fs, ctx, s->nb_inputs)) < 0) return ret; @@ -367,7 +419,7 @@ .init = init, .uninit = uninit, .activate = activate, - .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | AVFILTER_FLAG_SLICE_THREADS, }; #endif /* CONFIG_HSTACK_FILTER */ @@ -387,7 +439,7 @@ .init = init, .uninit = uninit, .activate = activate, - .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | AVFILTER_FLAG_SLICE_THREADS, }; #endif /* CONFIG_VSTACK_FILTER */ @@ -398,6 +450,7 @@ { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags = FLAGS }, { "layout", "set custom layout", OFFSET(layout), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, .flags = FLAGS }, { "shortest", "force termination when the shortest input terminates", OFFSET(shortest), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS }, + { "fill", "set the color for unused pixels", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = FLAGS }, { NULL }, }; @@ -413,7 +466,7 @@ .init = init, .uninit = uninit, .activate = activate, - .flags = AVFILTER_FLAG_DYNAMIC_INPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | AVFILTER_FLAG_SLICE_THREADS, }; #endif /* CONFIG_XSTACK_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/vf_stereo3d.c ffmpeg-4.4/libavfilter/vf_stereo3d.c --- ffmpeg-4.2.2/libavfilter/vf_stereo3d.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_stereo3d.c 2020-07-11 10:39:30.000000000 +0000 @@ -100,9 +100,9 @@ { 0, 0, 0, 0, 65536, 0}, { 0, 0, 0, 0, 0, 65536}}, [ANAGLYPH_RC_DUBOIS] = - {{29891, 32800, 11559, -2849, -5763, -102}, - {-2627, -2479, -1033, 24804, 48080, -1209}, - { -997, -1350, -358, -4729, -7403, 80373}}, + {{29884, 32768, 11534, -2818, -5767, -131}, + {-2621, -2490, -1049, 24773, 48103, -1180}, + { -983, -1376, -328, -4719, -7406, 80347}}, [ANAGLYPH_GM_GRAY] = {{ 0, 0, 0, 19595, 38470, 7471}, {19595, 38470, 7471, 0, 0, 0}, @@ -132,9 +132,9 @@ { 0, 0, 0, 0, 65536, 0}, { 0, 0, 65536, 0, 0, 0}}, [ANAGLYPH_YB_DUBOIS] = - {{65535,-12650,18451, -987, -7590, -1049}, - {-1604, 56032, 4196, 370, 3826, -1049}, - {-2345,-10676, 1358, 5801, 11416, 56217}}, + {{69599,-13435,19595, -1048, -8061, -1114}, + {-1704, 59507, 4456, 393, 4063, -1114}, + {-2490,-11338, 1442, 6160, 12124, 59703}}, }; typedef struct Stereo3DContext { @@ -160,9 +160,13 @@ static const AVOption stereo3d_options[] = { { "in", "set input format", OFFSET(in.format), AV_OPT_TYPE_INT, {.i64=SIDE_BY_SIDE_LR}, INTERLEAVE_ROWS_LR, STEREO_CODE_COUNT-1, FLAGS, "in"}, { "ab2l", "above below half height left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR}, 0, 0, FLAGS, "in" }, + { "tb2l", "above below half height left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR}, 0, 0, FLAGS, "in" }, { "ab2r", "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL}, 0, 0, FLAGS, "in" }, + { "tb2r", "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL}, 0, 0, FLAGS, "in" }, { "abl", "above below left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR}, 0, 0, FLAGS, "in" }, + { "tbl", "above below left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR}, 0, 0, FLAGS, "in" }, { "abr", "above below right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL}, 0, 0, FLAGS, "in" }, + { "tbr", "above below right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL}, 0, 0, FLAGS, "in" }, { "al", "alternating frames left first", 0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_LR}, 0, 0, FLAGS, "in" }, { "ar", "alternating frames right first", 0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_RL}, 0, 0, FLAGS, "in" }, { "sbs2l", "side by side half width left first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_LR}, 0, 0, FLAGS, "in" }, @@ -175,9 +179,13 @@ { "icr", "interleave columns right first", 0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_COLS_RL}, 0, 0, FLAGS, "in" }, { "out", "set output format", OFFSET(out.format), AV_OPT_TYPE_INT, {.i64=ANAGLYPH_RC_DUBOIS}, 0, STEREO_CODE_COUNT-1, FLAGS, "out"}, { "ab2l", "above below half height left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR}, 0, 0, FLAGS, "out" }, + { "tb2l", "above below half height left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR}, 0, 0, FLAGS, "out" }, { "ab2r", "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL}, 0, 0, FLAGS, "out" }, + { "tb2r", "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL}, 0, 0, FLAGS, "out" }, { "abl", "above below left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR}, 0, 0, FLAGS, "out" }, + { "tbl", "above below left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR}, 0, 0, FLAGS, "out" }, { "abr", "above below right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL}, 0, 0, FLAGS, "out" }, + { "tbr", "above below right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL}, 0, 0, FLAGS, "out" }, { "agmc", "anaglyph green magenta color", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_COLOR}, 0, 0, FLAGS, "out" }, { "agmd", "anaglyph green magenta dubois", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_DUBOIS}, 0, 0, FLAGS, "out" }, { "agmg", "anaglyph green magenta gray", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_GRAY}, 0, 0, FLAGS, "out" }, @@ -551,8 +559,6 @@ break; case CHECKERBOARD_LR: case CHECKERBOARD_RL: - s->out.width = s->width * 2; - break; case INTERLEAVE_COLS_LR: case INTERLEAVE_COLS_RL: s->out.width = s->width * 2; @@ -666,7 +672,7 @@ AVFilterContext *ctx = inlink->dst; Stereo3DContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *out, *oleft, *oright, *ileft, *iright; + AVFrame *out = NULL, *oleft, *oright, *ileft, *iright; int out_off_left[4], out_off_right[4]; int i, ret; @@ -1076,6 +1082,7 @@ av_frame_free(&s->prev); av_frame_free(&inpicref); } + av_assert0(out); out->sample_aspect_ratio = s->aspect; return ff_filter_frame(outlink, out); } diff -Nru ffmpeg-4.2.2/libavfilter/vf_subtitles.c ffmpeg-4.4/libavfilter/vf_subtitles.c --- ffmpeg-4.2.2/libavfilter/vf_subtitles.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_subtitles.c 2021-04-08 21:28:40.000000000 +0000 @@ -66,10 +66,10 @@ #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM #define COMMON_OPTIONS \ - {"filename", "set the filename of file to read", OFFSET(filename), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, \ - {"f", "set the filename of file to read", OFFSET(filename), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, \ - {"original_size", "set the size of the original video (used to scale fonts)", OFFSET(original_w), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, \ - {"fontsdir", "set the directory containing the fonts to read", OFFSET(fontsdir), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, \ + {"filename", "set the filename of file to read", OFFSET(filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, \ + {"f", "set the filename of file to read", OFFSET(filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, \ + {"original_size", "set the size of the original video (used to scale fonts)", OFFSET(original_w), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, FLAGS }, \ + {"fontsdir", "set the directory containing the fonts to read", OFFSET(fontsdir), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, \ {"alpha", "enable processing of alpha channel", OFFSET(alpha), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, FLAGS }, \ /* libass supports a log level ranging from 0 to 7 */ @@ -263,10 +263,10 @@ static const AVOption subtitles_options[] = { COMMON_OPTIONS - {"charenc", "set input character encoding", OFFSET(charenc), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, FLAGS}, + {"charenc", "set input character encoding", OFFSET(charenc), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS}, {"stream_index", "set stream index", OFFSET(stream_index), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS}, {"si", "set stream index", OFFSET(stream_index), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS}, - {"force_style", "force subtitle style", OFFSET(force_style), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, FLAGS}, + {"force_style", "force subtitle style", OFFSET(force_style), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS}, {NULL}, }; @@ -302,7 +302,7 @@ AVDictionary *codec_opts = NULL; AVFormatContext *fmt = NULL; AVCodecContext *dec_ctx = NULL; - AVCodec *dec = NULL; + const AVCodec *dec; const AVCodecDescriptor *dec_desc; AVStream *st; AVPacket pkt; @@ -384,22 +384,25 @@ if (!dec) { av_log(ctx, AV_LOG_ERROR, "Failed to find subtitle codec %s\n", avcodec_get_name(st->codecpar->codec_id)); - return AVERROR(EINVAL); + ret = AVERROR_DECODER_NOT_FOUND; + goto end; } dec_desc = avcodec_descriptor_get(st->codecpar->codec_id); if (dec_desc && !(dec_desc->props & AV_CODEC_PROP_TEXT_SUB)) { av_log(ctx, AV_LOG_ERROR, "Only text based subtitles are currently supported\n"); - return AVERROR_PATCHWELCOME; + ret = AVERROR_PATCHWELCOME; + goto end; } if (ass->charenc) av_dict_set(&codec_opts, "sub_charenc", ass->charenc, 0); - if (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57,26,100)) - av_dict_set(&codec_opts, "sub_text_format", "ass", 0); + av_dict_set(&codec_opts, "sub_text_format", "ass", 0); dec_ctx = avcodec_alloc_context3(dec); - if (!dec_ctx) - return AVERROR(ENOMEM); + if (!dec_ctx) { + ret = AVERROR(ENOMEM); + goto end; + } ret = avcodec_parameters_to_context(dec_ctx, st->codecpar); if (ret < 0) @@ -445,9 +448,6 @@ ass_process_codec_private(ass->track, dec_ctx->subtitle_header, dec_ctx->subtitle_header_size); - av_init_packet(&pkt); - pkt.data = NULL; - pkt.size = 0; while (av_read_frame(fmt, &pkt) >= 0) { int i, got_subtitle; AVSubtitle sub = {0}; @@ -464,11 +464,8 @@ char *ass_line = sub.rects[i]->ass; if (!ass_line) break; - if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,25,100)) - ass_process_data(ass->track, ass_line, strlen(ass_line)); - else - ass_process_chunk(ass->track, ass_line, strlen(ass_line), - start_time, duration); + ass_process_chunk(ass->track, ass_line, strlen(ass_line), + start_time, duration); } } } @@ -478,7 +475,6 @@ end: av_dict_free(&codec_opts); - avcodec_close(dec_ctx); avcodec_free_context(&dec_ctx); avformat_close_input(&fmt); return ret; diff -Nru ffmpeg-4.2.2/libavfilter/vf_super2xsai.c ffmpeg-4.4/libavfilter/vf_super2xsai.c --- ffmpeg-4.2.2/libavfilter/vf_super2xsai.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_super2xsai.c 2021-04-08 21:28:40.000000000 +0000 @@ -46,6 +46,10 @@ int is_be; } Super2xSaIContext; +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + #define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D)) #define INTERPOLATE(A, B) (((A & hi_pixel_mask) >> 1) + ((B & hi_pixel_mask) >> 1) + (A & B & lo_pixel_mask)) @@ -53,32 +57,40 @@ #define Q_INTERPOLATE(A, B, C, D) ((A & q_hi_pixel_mask) >> 2) + ((B & q_hi_pixel_mask) >> 2) + ((C & q_hi_pixel_mask) >> 2) + ((D & q_hi_pixel_mask) >> 2) \ + ((((A & q_lo_pixel_mask) + (B & q_lo_pixel_mask) + (C & q_lo_pixel_mask) + (D & q_lo_pixel_mask)) >> 2) & q_lo_pixel_mask) -static void super2xsai(AVFilterContext *ctx, - uint8_t *src, int src_linesize, - uint8_t *dst, int dst_linesize, - int width, int height) +static int super2xsai(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { Super2xSaIContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + const uint8_t *src = in->data[0]; + uint8_t *dst = out->data[0]; + const int src_linesize = in->linesize[0]; + const int dst_linesize = out->linesize[0]; + const int width = in->width; + const int height = in->height; unsigned int x, y; uint32_t color[4][4]; - unsigned char *src_line[4]; + const uint8_t *src_line[4]; const int bpp = s->bpp; const uint32_t hi_pixel_mask = s->hi_pixel_mask; const uint32_t lo_pixel_mask = s->lo_pixel_mask; const uint32_t q_hi_pixel_mask = s->q_hi_pixel_mask; const uint32_t q_lo_pixel_mask = s->q_lo_pixel_mask; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr+1)) / nb_jobs; /* Point to the first 4 lines, first line is duplicated */ - src_line[0] = src; - src_line[1] = src; - src_line[2] = src + src_linesize*FFMIN(1, height-1); - src_line[3] = src + src_linesize*FFMIN(2, height-1); + src_line[0] = src + src_linesize*FFMAX(slice_start - 1, 0); + src_line[1] = src + src_linesize*slice_start; + src_line[2] = src + src_linesize*FFMIN(slice_start + 1, height-1); + src_line[3] = src + src_linesize*FFMIN(slice_start + 2, height-1); #define READ_COLOR4(dst, src_line, off) dst = *((const uint32_t *)src_line + off) #define READ_COLOR3(dst, src_line, off) dst = AV_RL24 (src_line + 3*off) #define READ_COLOR2(dst, src_line, off) dst = s->is_be ? AV_RB16(src_line + 2 * off) : AV_RL16(src_line + 2 * off) - for (y = 0; y < height; y++) { + for (y = slice_start; y < slice_end; y++) { uint8_t *dst_line[2]; dst_line[0] = dst + dst_linesize*2*y; @@ -229,6 +241,8 @@ if (y < height - 3) src_line[3] += src_linesize; } // y loop + + return 0; } static int query_formats(AVFilterContext *ctx) @@ -305,24 +319,25 @@ return 0; } -static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) +static int filter_frame(AVFilterLink *inlink, AVFrame *in) { - AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFrame *outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!outpicref) { - av_frame_free(&inpicref); + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + ThreadData td; + AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); return AVERROR(ENOMEM); } - av_frame_copy_props(outpicref, inpicref); - outpicref->width = outlink->w; - outpicref->height = outlink->h; - - super2xsai(inlink->dst, inpicref->data[0], inpicref->linesize[0], - outpicref->data[0], outpicref->linesize[0], - inlink->w, inlink->h); + av_frame_copy_props(out, in); + out->width = outlink->w; + out->height = outlink->h; + + td.in = in, td.out = out; + ctx->internal->execute(ctx, super2xsai, &td, NULL, FFMIN(in->height, ff_filter_get_nb_threads(ctx))); - av_frame_free(&inpicref); - return ff_filter_frame(outlink, outpicref); + av_frame_free(&in); + return ff_filter_frame(outlink, out); } static const AVFilterPad super2xsai_inputs[] = { @@ -351,4 +366,5 @@ .query_formats = query_formats, .inputs = super2xsai_inputs, .outputs = super2xsai_outputs, + .flags = AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_swaprect.c ffmpeg-4.4/libavfilter/vf_swaprect.c --- ffmpeg-4.2.2/libavfilter/vf_swaprect.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_swaprect.c 2021-04-08 21:28:40.000000000 +0000 @@ -43,7 +43,7 @@ } SwapRectContext; #define OFFSET(x) offsetof(SwapRectContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption swaprect_options[] = { { "w", "set rect width", OFFSET(w), AV_OPT_TYPE_STRING, {.str="w/2"}, 0, 0, .flags = FLAGS }, { "h", "set rect height", OFFSET(h), AV_OPT_TYPE_STRING, {.str="h/2"}, 0, 0, .flags = FLAGS }, @@ -99,7 +99,7 @@ var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; var_values[VAR_N] = inlink->frame_count_out; var_values[VAR_T] = in->pts == AV_NOPTS_VALUE ? NAN : in->pts * av_q2d(inlink->time_base); - var_values[VAR_POS] = in->pkt_pos ? NAN : in->pkt_pos; + var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; ret = av_expr_parse_and_eval(&dw, s->w, var_names, &var_values[0], @@ -253,4 +253,5 @@ .inputs = inputs, .outputs = outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_telecine.c ffmpeg-4.4/libavfilter/vf_telecine.c --- ffmpeg-4.2.2/libavfilter/vf_telecine.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_telecine.c 2021-04-08 21:28:40.000000000 +0000 @@ -101,19 +101,16 @@ static int query_formats(AVFilterContext *ctx) { - AVFilterFormats *pix_fmts = NULL; - int fmt, ret; + AVFilterFormats *formats = NULL; + int ret; - for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); - if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL || - desc->flags & AV_PIX_FMT_FLAG_PAL || - desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) && - (ret = ff_add_format(&pix_fmts, fmt)) < 0) - return ret; - } - - return ff_set_common_formats(ctx, pix_fmts); + ret = ff_formats_pixdesc_filter(&formats, 0, + AV_PIX_FMT_FLAG_BITSTREAM | + AV_PIX_FMT_FLAG_PAL | + AV_PIX_FMT_FLAG_HWACCEL); + if (ret < 0) + return ret; + return ff_set_common_formats(ctx, formats); } static int config_input(AVFilterLink *inlink) @@ -207,6 +204,8 @@ s->stride[i], (s->planeheight[i] - !s->first_field + 1) / 2); } + s->frame[nout]->interlaced_frame = 1; + s->frame[nout]->top_field_first = !s->first_field; nout++; len--; s->occupied = 0; @@ -220,6 +219,8 @@ inpicref->data[i], inpicref->linesize[i], s->stride[i], s->planeheight[i]); + s->frame[nout]->interlaced_frame = inpicref->interlaced_frame; + s->frame[nout]->top_field_first = inpicref->top_field_first; nout++; len -= 2; } @@ -236,6 +237,8 @@ for (i = 0; i < nout; i++) { AVFrame *frame = av_frame_clone(s->frame[i]); + int interlaced = frame ? frame->interlaced_frame : 0; + int tff = frame ? frame->top_field_first : 0; if (!frame) { av_frame_free(&inpicref); @@ -243,6 +246,8 @@ } av_frame_copy_props(frame, inpicref); + frame->interlaced_frame = interlaced; + frame->top_field_first = tff; frame->pts = ((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time) + av_rescale(outlink->frame_count_in, s->ts_unit.num, s->ts_unit.den); diff -Nru ffmpeg-4.2.2/libavfilter/vf_threshold.c ffmpeg-4.4/libavfilter/vf_threshold.c --- ffmpeg-4.2.2/libavfilter/vf_threshold.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_threshold.c 2021-04-08 21:28:40.000000000 +0000 @@ -52,10 +52,12 @@ AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, - AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, diff -Nru ffmpeg-4.2.2/libavfilter/vf_thumbnail.c ffmpeg-4.4/libavfilter/vf_thumbnail.c --- ffmpeg-4.2.2/libavfilter/vf_thumbnail.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_thumbnail.c 2021-04-08 21:28:40.000000000 +0000 @@ -28,6 +28,7 @@ */ #include "libavutil/opt.h" +#include "libavutil/pixdesc.h" #include "avfilter.h" #include "internal.h" @@ -44,6 +45,9 @@ int n_frames; ///< number of frames for analysis struct thumb_frame *frames; ///< the n_frames frames AVRational tb; ///< copy of the input timebase to ease access + + int planewidth[4]; + int planeheight[4]; } ThumbContext; #define OFFSET(x) offsetof(ThumbContext, x) @@ -140,14 +144,55 @@ // keep a reference of each frame s->frames[s->n].buf = frame; - // update current frame RGB histogram - for (j = 0; j < inlink->h; j++) { - for (i = 0; i < inlink->w; i++) { - hist[0*256 + p[i*3 ]]++; - hist[1*256 + p[i*3 + 1]]++; - hist[2*256 + p[i*3 + 2]]++; + // update current frame histogram + switch (inlink->format) { + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_BGR24: + for (j = 0; j < inlink->h; j++) { + for (i = 0; i < inlink->w; i++) { + hist[0*256 + p[i*3 ]]++; + hist[1*256 + p[i*3 + 1]]++; + hist[2*256 + p[i*3 + 2]]++; + } + p += frame->linesize[0]; + } + break; + case AV_PIX_FMT_RGB0: + case AV_PIX_FMT_BGR0: + case AV_PIX_FMT_RGBA: + case AV_PIX_FMT_BGRA: + for (j = 0; j < inlink->h; j++) { + for (i = 0; i < inlink->w; i++) { + hist[0*256 + p[i*4 ]]++; + hist[1*256 + p[i*4 + 1]]++; + hist[2*256 + p[i*4 + 2]]++; + } + p += frame->linesize[0]; + } + break; + case AV_PIX_FMT_0RGB: + case AV_PIX_FMT_0BGR: + case AV_PIX_FMT_ARGB: + case AV_PIX_FMT_ABGR: + for (j = 0; j < inlink->h; j++) { + for (i = 0; i < inlink->w; i++) { + hist[0*256 + p[i*4 + 1]]++; + hist[1*256 + p[i*4 + 2]]++; + hist[2*256 + p[i*4 + 3]]++; + } + p += frame->linesize[0]; } - p += frame->linesize[0]; + break; + default: + for (int plane = 0; plane < 3; plane++) { + const uint8_t *p = frame->data[plane]; + for (j = 0; j < s->planeheight[plane]; j++) { + for (i = 0; i < s->planewidth[plane]; i++) + hist[256*plane + p[i]]++; + p += frame->linesize[plane]; + } + } + break; } // no selection until the buffer of N frames is filled up @@ -162,7 +207,7 @@ { int i; ThumbContext *s = ctx->priv; - for (i = 0; i < s->n_frames && s->frames[i].buf; i++) + for (i = 0; i < s->n_frames && s->frames && s->frames[i].buf; i++) av_frame_free(&s->frames[i].buf); av_freep(&s->frames); } @@ -188,8 +233,14 @@ { AVFilterContext *ctx = inlink->dst; ThumbContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); s->tb = inlink->time_base; + 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; + return 0; } @@ -197,6 +248,18 @@ { static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, + AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0, + AV_PIX_FMT_ABGR, AV_PIX_FMT_ARGB, + AV_PIX_FMT_0BGR, AV_PIX_FMT_0RGB, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE }; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); @@ -234,4 +297,5 @@ .inputs = thumbnail_inputs, .outputs = thumbnail_outputs, .priv_class = &thumbnail_class, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_tile.c ffmpeg-4.4/libavfilter/vf_tile.c --- ffmpeg-4.2.2/libavfilter/vf_tile.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_tile.c 2021-04-08 21:28:40.000000000 +0000 @@ -63,7 +63,7 @@ { "color", "set the color of the unused area", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str = "black"}, .flags = FLAGS }, { "overlap", "set how many frames to overlap for each render", OFFSET(overlap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS }, - { "init_padding", " set how many frames to initially pad", OFFSET(init_padding), + { "init_padding", "set how many frames to initially pad", OFFSET(init_padding), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS }, { NULL } }; @@ -262,6 +262,7 @@ { TileContext *tile = ctx->priv; + av_frame_free(&tile->out_ref); av_frame_free(&tile->prev_out_ref); } diff -Nru ffmpeg-4.2.2/libavfilter/vf_tinterlace.c ffmpeg-4.4/libavfilter/vf_tinterlace.c --- ffmpeg-4.2.2/libavfilter/vf_tinterlace.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_tinterlace.c 2021-04-08 21:28:40.000000000 +0000 @@ -53,6 +53,7 @@ {"complex_filter", "enable complex vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_CVLPF},INT_MIN, INT_MAX, FLAGS, "flags" }, {"cvlpf", "enable complex vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_CVLPF},INT_MIN, INT_MAX, FLAGS, "flags" }, {"exact_tb", "force a timebase which can represent timestamps exactly", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_EXACT_TB}, INT_MIN, INT_MAX, FLAGS, "flags" }, + {"bypass_il", "bypass already interlaced frames", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_BYPASS_IL}, INT_MIN, INT_MAX, FLAGS, "flags" }, {NULL} }; @@ -63,10 +64,10 @@ { "scan", "scanning mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_TFF}, 0, 1, FLAGS, "mode"}, { "tff", "top field first", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_TFF}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"}, { "bff", "bottom field first", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_BFF}, INT_MIN, INT_MAX, FLAGS, .unit = "mode"}, - { "lowpass", "set vertical low-pass filter", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = TINTERLACE_FLAG_VLPF}, 0, 2, FLAGS, "flags" }, - { "off", "disable vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, INT_MIN, INT_MAX, FLAGS, "flags" }, - { "linear", "linear vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_VLPF}, INT_MIN, INT_MAX, FLAGS, "flags" }, - { "complex", "complex vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = TINTERLACE_FLAG_CVLPF},INT_MIN, INT_MAX, FLAGS, "flags" }, + { "lowpass", "set vertical low-pass filter", OFFSET(lowpass), AV_OPT_TYPE_INT, {.i64 = VLPF_LIN}, 0, 2, FLAGS, "lowpass" }, + { "off", "disable vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = VLPF_OFF}, INT_MIN, INT_MAX, FLAGS, "lowpass" }, + { "linear", "linear vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = VLPF_LIN}, INT_MIN, INT_MAX, FLAGS, "lowpass" }, + { "complex", "complex vertical low-pass filter", 0, AV_OPT_TYPE_CONST, {.i64 = VLPF_CMP}, INT_MIN, INT_MAX, FLAGS, "lowpass" }, { NULL } }; @@ -395,12 +396,12 @@ copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, - FIELD_UPPER_AND_LOWER, 1, tinterlace->mode == MODE_MERGEX2 ? inlink->frame_count_out & 1 ? FIELD_LOWER : FIELD_UPPER : FIELD_UPPER, tinterlace->flags); + FIELD_UPPER_AND_LOWER, 1, tinterlace->mode == MODE_MERGEX2 ? (1 + inlink->frame_count_out) & 1 ? FIELD_LOWER : FIELD_UPPER : FIELD_UPPER, tinterlace->flags); /* write even frame lines into the lower field of the new frame */ copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)next->data, next->linesize, inlink->format, inlink->w, inlink->h, - FIELD_UPPER_AND_LOWER, 1, tinterlace->mode == MODE_MERGEX2 ? inlink->frame_count_out & 1 ? FIELD_UPPER : FIELD_LOWER : FIELD_LOWER, tinterlace->flags); + FIELD_UPPER_AND_LOWER, 1, tinterlace->mode == MODE_MERGEX2 ? (1 + inlink->frame_count_out) & 1 ? FIELD_UPPER : FIELD_LOWER : FIELD_LOWER, tinterlace->flags); if (tinterlace->mode != MODE_MERGEX2) av_frame_free(&tinterlace->next); break; @@ -422,7 +423,7 @@ out->height = outlink->h; out->sample_aspect_ratio = av_mul_q(cur->sample_aspect_ratio, av_make_q(2, 1)); - field = (1 + tinterlace->frame) & 1 ? FIELD_UPPER : FIELD_LOWER; + field = (1 + outlink->frame_count_in) & 1 ? FIELD_UPPER : FIELD_LOWER; /* copy upper and lower fields */ copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, @@ -439,6 +440,16 @@ * halving the frame rate and preserving image height */ case MODE_INTERLEAVE_TOP: /* top field first */ case MODE_INTERLEAVE_BOTTOM: /* bottom field first */ + if ((tinterlace->flags & TINTERLACE_FLAG_BYPASS_IL) && cur->interlaced_frame) { + av_log(ctx, AV_LOG_WARNING, + "video is already interlaced, adjusting framerate only\n"); + out = av_frame_clone(cur); + if (!out) + return AVERROR(ENOMEM); + out->pts /= 2; // adjust pts to new framerate + ret = ff_filter_frame(outlink, out); + return ret; + } tff = tinterlace->mode == MODE_INTERLEAVE_TOP; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) @@ -506,7 +517,6 @@ out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base); ret = ff_filter_frame(outlink, out); - tinterlace->frame++; return ret; } @@ -518,6 +528,12 @@ if (tinterlace->mode <= MODE_BFF) tinterlace->mode += MODE_INTERLEAVE_TOP; + tinterlace->flags |= TINTERLACE_FLAG_BYPASS_IL; + if (tinterlace->lowpass == VLPF_LIN) + tinterlace->flags |= TINTERLACE_FLAG_VLPF; + if (tinterlace->lowpass == VLPF_CMP) + tinterlace->flags |= TINTERLACE_FLAG_CVLPF; + return 0; } diff -Nru ffmpeg-4.2.2/libavfilter/vf_tmidequalizer.c ffmpeg-4.4/libavfilter/vf_tmidequalizer.c --- ffmpeg-4.2.2/libavfilter/vf_tmidequalizer.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_tmidequalizer.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +typedef struct TMidEqualizerContext { + const AVClass *class; + + int planes; + int radius; + float sigma; + + int plane_width[4], plane_height[4]; + int nb_frames; + int depth; + int f_frames; + int l_frames; + int del_frame; + int cur_frame; + int nb_planes; + int histogram_size; + float kernel[127]; + float *histogram[4][256]; + float *change[4]; + + AVFrame **frames; + + void (*compute_histogram)(const uint8_t *ssrc, ptrdiff_t linesize, + int w, int h, float *histogram, size_t hsize); + void (*apply_contrast_change)(const uint8_t *src, ptrdiff_t src_linesize, + uint8_t *dst, ptrdiff_t dst_linesize, + int w, int h, float *change, float *orig); +} TMidEqualizerContext; + +#define OFFSET(x) offsetof(TMidEqualizerContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption tmidequalizer_options[] = { + { "radius", "set radius", OFFSET(radius), AV_OPT_TYPE_INT, {.i64=5}, 1, 127, FLAGS }, + { "sigma", "set sigma", OFFSET(sigma), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS }, + { "planes", "set planes", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=0xF}, 0, 0xF, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(tmidequalizer); + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE + }; + + return ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); +} + +static void compute_contrast_function(const float *const histograms[256], + const float *const kernel, + int nb_frames, int radius, int hsize, + float *f, int idx) +{ + const float *const h1 = histograms[idx]; + int p2[256] = { 0 }; + + for (int p1 = 0; p1 < hsize; p1++) { + float weight = 1.f; + float sum = p1 * weight; + + for (int j = 0; j < radius; j++) { + const int nidx = ((idx - radius + j) % nb_frames); + const float *const h2 = histograms[nidx < 0 ? nidx + nb_frames: nidx]; + int k = j; + + for (; p2[k] < hsize && h2[p2[k]] < h1[p1]; p2[k]++); + if (p2[k] == hsize) + p2[k]--; + + weight += kernel[j]; + sum += kernel[j] * p2[k]; + } + + for (int j = radius + 1; j < nb_frames; j++) { + const int nidx = (idx - radius + j) % nb_frames; + const float *const h2 = histograms[nidx < 0 ? nidx + nb_frames: nidx]; + int k = j; + + for (; p2[k] < hsize && h2[p2[k]] < h1[p1]; p2[k]++); + if (p2[k] == hsize) + p2[k]--; + + weight += kernel[j - radius - 1]; + sum += kernel[j - radius - 1] * p2[k]; + } + + f[p1] = sum / weight; + } +} + +static void apply_contrast_change8(const uint8_t *src, ptrdiff_t src_linesize, + uint8_t *dst, ptrdiff_t dst_linesize, + int w, int h, float *change, float *orig) +{ + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) + dst[x] = lrintf(change[src[x]]); + + dst += dst_linesize; + src += src_linesize; + } +} + +static void apply_contrast_change16(const uint8_t *ssrc, ptrdiff_t src_linesize, + uint8_t *ddst, ptrdiff_t dst_linesize, + int w, int h, float *change, float *orig) +{ + const uint16_t *src = (const uint16_t *)ssrc; + uint16_t *dst = (uint16_t *)ddst; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) + dst[x] = lrintf(change[src[x]]); + + dst += dst_linesize / 2; + src += src_linesize / 2; + } +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + TMidEqualizerContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + int eof = 0; + + if (!in) { + int idx = s->f_frames < s->nb_frames ? s->radius : s->del_frame ? s->del_frame - 1 : s->nb_frames - 1; + + if (s->f_frames < s->nb_frames) { + s->l_frames = s->nb_frames - s->f_frames; + } else { + s->l_frames++; + } + in = av_frame_clone(s->frames[idx]); + if (!in) + return AVERROR(ENOMEM); + eof = 1; + } + + if (s->f_frames < s->nb_frames) { + s->frames[s->f_frames] = in; + + for (int p = 0; p < s->nb_planes; p++) { + s->compute_histogram(in->data[p], in->linesize[p], + s->plane_width[p], s->plane_height[p], + s->histogram[p][s->f_frames], + s->histogram_size); + } + + s->f_frames++; + + while (s->f_frames <= s->radius) { + s->frames[s->f_frames] = av_frame_clone(in); + if (!s->frames[s->f_frames]) + return AVERROR(ENOMEM); + for (int p = 0; p < s->nb_planes; p++) { + memcpy(s->histogram[p][s->f_frames], + s->histogram[p][s->f_frames - 1], + s->histogram_size * sizeof(float)); + } + s->f_frames++; + } + + if (!eof && s->f_frames < s->nb_frames) { + return 0; + } else { + while (s->f_frames < s->nb_frames) { + s->frames[s->f_frames] = av_frame_clone(in); + if (!s->frames[s->f_frames]) + return AVERROR(ENOMEM); + for (int p = 0; p < s->nb_planes; p++) { + memcpy(s->histogram[p][s->f_frames], + s->histogram[p][s->f_frames - 1], + s->histogram_size * sizeof(float)); + } + s->f_frames++; + } + } + s->cur_frame = s->radius; + s->del_frame = 0; + } else { + av_frame_free(&s->frames[s->del_frame]); + s->frames[s->del_frame] = in; + + for (int p = 0; p < s->nb_planes; p++) { + s->compute_histogram(in->data[p], in->linesize[p], + s->plane_width[p], s->plane_height[p], + s->histogram[p][s->del_frame], + s->histogram_size); + } + + s->del_frame++; + if (s->del_frame >= s->nb_frames) + s->del_frame = 0; + } + + if (ctx->is_disabled) { + const int idx = s->cur_frame; + + out = av_frame_clone(s->frames[idx]); + if (!out) + return AVERROR(ENOMEM); + } else { + const int idx = s->cur_frame; + + in = s->frames[idx]; + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) + return AVERROR(ENOMEM); + av_frame_copy_props(out, in); + + for (int p = 0; p < s->nb_planes; p++) { + if (!((1 << p) & s->planes)) { + av_image_copy_plane(out->data[p], out->linesize[p], in->data[p], in->linesize[p], + s->plane_width[p] * (1 + (s->depth > 8)), s->plane_height[p]); + continue; + } + + compute_contrast_function((const float *const *)s->histogram[p], s->kernel, + s->nb_frames, s->radius, s->histogram_size, s->change[p], idx); + + s->apply_contrast_change(in->data[p], in->linesize[p], + out->data[p], out->linesize[p], + s->plane_width[p], s->plane_height[p], + s->change[p], s->histogram[p][idx]); + } + } + + s->cur_frame++; + if (s->cur_frame >= s->nb_frames) + s->cur_frame = 0; + + return ff_filter_frame(outlink, out); +} + +static void compute_histogram8(const uint8_t *src, ptrdiff_t linesize, + int w, int h, float *histogram, size_t hsize) +{ + memset(histogram, 0, hsize * sizeof(*histogram)); + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) + histogram[src[x]] += 1; + src += linesize; + } + + for (int x = 0; x < hsize; x++) + histogram[x] /= hsize; + + for (int x = 1; x < hsize; x++) + histogram[x] += histogram[x-1]; +} + +static void compute_histogram16(const uint8_t *ssrc, ptrdiff_t linesize, + int w, int h, float *histogram, size_t hsize) +{ + const uint16_t *src = (const uint16_t *)ssrc; + + memset(histogram, 0, hsize * sizeof(*histogram)); + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) + histogram[src[x]] += 1; + src += linesize / 2; + } + + for (int x = 0; x < hsize; x++) + histogram[x] /= hsize; + + for (int x = 1; x < hsize; x++) + histogram[x] += histogram[x-1]; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + TMidEqualizerContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + float sigma = s->radius * s->sigma; + int vsub, hsub; + + s->depth = desc->comp[0].depth; + s->nb_frames = s->radius * 2 + 1; + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + + hsub = desc->log2_chroma_w; + vsub = desc->log2_chroma_h; + + s->plane_height[0] = s->plane_height[3] = inlink->h; + s->plane_width[0] = s->plane_width[3] = inlink->w; + s->plane_height[1] = s->plane_height[2] = AV_CEIL_RSHIFT(inlink->h, vsub); + s->plane_width[1] = s->plane_width[2] = AV_CEIL_RSHIFT(inlink->w, hsub); + + s->histogram_size = 1 << s->depth; + + for (int n = 0; n < s->radius; n++) + s->kernel[n] = expf(-0.5 * (n + 1) * (n + 1) / (sigma * sigma)); + + for (int p = 0; p < s->nb_planes; p++) { + for (int n = 0; n < s->nb_frames; n++) { + s->histogram[p][n] = av_calloc(s->histogram_size, sizeof(float)); + if (!s->histogram[p][n]) + return AVERROR(ENOMEM); + } + + s->change[p] = av_calloc(s->histogram_size, sizeof(float)); + if (!s->change[p]) + return AVERROR(ENOMEM); + } + + if (!s->frames) + s->frames = av_calloc(s->nb_frames, sizeof(*s->frames)); + if (!s->frames) + return AVERROR(ENOMEM); + + s->compute_histogram = s->depth <= 8 ? compute_histogram8 : compute_histogram16; + s->apply_contrast_change = s->depth <= 8 ? apply_contrast_change8 : apply_contrast_change16; + + return 0; +} + +static int request_frame(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + TMidEqualizerContext *s = ctx->priv; + int ret; + + ret = ff_request_frame(ctx->inputs[0]); + if (ret == AVERROR_EOF && s->l_frames < s->radius) { + ret = filter_frame(ctx->inputs[0], NULL); + } + + return ret; +} + +static void free_histograms(AVFilterContext *ctx, int x, int nb_frames) +{ + TMidEqualizerContext *s = ctx->priv; + + for (int n = 0; n < nb_frames; n++) + av_freep(&s->histogram[x][n]); + av_freep(&s->change[x]); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + TMidEqualizerContext *s = ctx->priv; + + free_histograms(ctx, 0, s->nb_frames); + free_histograms(ctx, 1, s->nb_frames); + free_histograms(ctx, 2, s->nb_frames); + free_histograms(ctx, 3, s->nb_frames); + + for (int i = 0; i < s->nb_frames && s->frames; i++) + av_frame_free(&s->frames[i]); + av_freep(&s->frames); +} + +static const AVFilterPad tmidequalizer_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad tmidequalizer_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .request_frame = request_frame, + }, + { NULL } +}; + +AVFilter ff_vf_tmidequalizer = { + .name = "tmidequalizer", + .description = NULL_IF_CONFIG_SMALL("Apply Temporal Midway Equalization."), + .priv_size = sizeof(TMidEqualizerContext), + .uninit = uninit, + .query_formats = query_formats, + .inputs = tmidequalizer_inputs, + .outputs = tmidequalizer_outputs, + .priv_class = &tmidequalizer_class, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_tonemap_opencl.c ffmpeg-4.4/libavfilter/vf_tonemap_opencl.c --- ffmpeg-4.2.2/libavfilter/vf_tonemap_opencl.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_tonemap_opencl.c 2021-04-08 21:28:40.000000000 +0000 @@ -71,12 +71,12 @@ cl_mem util_mem; } TonemapOpenCLContext; -static const char *linearize_funcs[AVCOL_TRC_NB] = { +static const char *const linearize_funcs[AVCOL_TRC_NB] = { [AVCOL_TRC_SMPTE2084] = "eotf_st2084", [AVCOL_TRC_ARIB_STD_B67] = "inverse_oetf_hlg", }; -static const char *delinearize_funcs[AVCOL_TRC_NB] = { +static const char *const delinearize_funcs[AVCOL_TRC_NB] = { [AVCOL_TRC_BT709] = "inverse_eotf_bt1886", [AVCOL_TRC_BT2020_10] = "inverse_eotf_bt1886", }; @@ -91,7 +91,7 @@ [AVCOL_PRI_BT2020] = { 0.3127, 0.3290 }, }; -static const char *tonemap_func[TONEMAP_MAX] = { +static const char *const tonemap_func[TONEMAP_MAX] = { [TONEMAP_NONE] = "direct", [TONEMAP_LINEAR] = "linear", [TONEMAP_GAMMA] = "gamma", @@ -542,7 +542,7 @@ AVFilter ff_vf_tonemap_opencl = { .name = "tonemap_opencl", - .description = NULL_IF_CONFIG_SMALL("perform HDR to SDR conversion with tonemapping"), + .description = NULL_IF_CONFIG_SMALL("Perform HDR to SDR conversion with tonemapping."), .priv_size = sizeof(TonemapOpenCLContext), .priv_class = &tonemap_opencl_class, .init = &ff_opencl_filter_init, diff -Nru ffmpeg-4.2.2/libavfilter/vf_tonemap_vaapi.c ffmpeg-4.4/libavfilter/vf_tonemap_vaapi.c --- ffmpeg-4.2.2/libavfilter/vf_tonemap_vaapi.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_tonemap_vaapi.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,419 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include + +#include "libavutil/avassert.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/mastering_display_metadata.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "vaapi_vpp.h" + +typedef struct HDRVAAPIContext { + VAAPIVPPContext vpp_ctx; // must be the first field + + char *output_format_string; + + char *color_primaries_string; + char *color_transfer_string; + char *color_matrix_string; + + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_transfer; + enum AVColorSpace color_matrix; + + VAHdrMetaDataHDR10 in_metadata; + + AVFrameSideData *src_display; + AVFrameSideData *src_light; +} HDRVAAPIContext; + +static int tonemap_vaapi_save_metadata(AVFilterContext *avctx, AVFrame *input_frame) +{ + HDRVAAPIContext *ctx = avctx->priv; + AVMasteringDisplayMetadata *hdr_meta; + AVContentLightMetadata *light_meta; + + if (input_frame->color_trc != AVCOL_TRC_SMPTE2084) { + av_log(avctx, AV_LOG_WARNING, "Only support HDR10 as input for vaapi tone-mapping\n"); + } + + ctx->src_display = av_frame_get_side_data(input_frame, + AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); + if (ctx->src_display) { + hdr_meta = (AVMasteringDisplayMetadata *)ctx->src_display->data; + if (!hdr_meta) { + av_log(avctx, AV_LOG_ERROR, "No mastering display data\n"); + return AVERROR(EINVAL); + } + + if (hdr_meta->has_luminance) { + const int luma_den = 10000; + ctx->in_metadata.max_display_mastering_luminance = + lrint(luma_den * av_q2d(hdr_meta->max_luminance)); + ctx->in_metadata.min_display_mastering_luminance = + FFMIN(lrint(luma_den * av_q2d(hdr_meta->min_luminance)), + ctx->in_metadata.max_display_mastering_luminance); + + av_log(avctx, AV_LOG_DEBUG, + "Mastering Display Metadata(in luminance):\n"); + av_log(avctx, AV_LOG_DEBUG, + "min_luminance=%u, max_luminance=%u\n", + ctx->in_metadata.min_display_mastering_luminance, + ctx->in_metadata.max_display_mastering_luminance); + } + + if (hdr_meta->has_primaries) { + int i; + const int mapping[3] = {1, 2, 0}; //green, blue, red + const int chroma_den = 50000; + + for (i = 0; i < 3; i++) { + const int j = mapping[i]; + ctx->in_metadata.display_primaries_x[i] = + FFMIN(lrint(chroma_den * + av_q2d(hdr_meta->display_primaries[j][0])), + chroma_den); + ctx->in_metadata.display_primaries_y[i] = + FFMIN(lrint(chroma_den * + av_q2d(hdr_meta->display_primaries[j][1])), + chroma_den); + } + + ctx->in_metadata.white_point_x = + FFMIN(lrint(chroma_den * av_q2d(hdr_meta->white_point[0])), + chroma_den); + ctx->in_metadata.white_point_y = + FFMIN(lrint(chroma_den * av_q2d(hdr_meta->white_point[1])), + chroma_den); + + av_log(avctx, AV_LOG_DEBUG, + "Mastering Display Metadata(in primaries):\n"); + av_log(avctx, AV_LOG_DEBUG, + "G(%u,%u) B(%u,%u) R(%u,%u) WP(%u,%u)\n", + ctx->in_metadata.display_primaries_x[0], + ctx->in_metadata.display_primaries_y[0], + ctx->in_metadata.display_primaries_x[1], + ctx->in_metadata.display_primaries_y[1], + ctx->in_metadata.display_primaries_x[2], + ctx->in_metadata.display_primaries_y[2], + ctx->in_metadata.white_point_x, + ctx->in_metadata.white_point_y); + } + } else { + av_log(avctx, AV_LOG_ERROR, "No mastering display data from input\n"); + return AVERROR(EINVAL); + } + + ctx->src_light = av_frame_get_side_data(input_frame, + AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); + if (ctx->src_light) { + light_meta = (AVContentLightMetadata *)ctx->src_light->data; + if (!light_meta) { + av_log(avctx, AV_LOG_ERROR, "No light metadata\n"); + return AVERROR(EINVAL); + } + + ctx->in_metadata.max_content_light_level = light_meta->MaxCLL; + ctx->in_metadata.max_pic_average_light_level = light_meta->MaxFALL; + + av_log(avctx, AV_LOG_DEBUG, + "Mastering Content Light Level (in):\n"); + av_log(avctx, AV_LOG_DEBUG, + "MaxCLL(%u) MaxFALL(%u)\n", + ctx->in_metadata.max_content_light_level, + ctx->in_metadata.max_pic_average_light_level); + } else { + av_log(avctx, AV_LOG_DEBUG, "No content light level from input\n"); + } + return 0; +} + +static int tonemap_vaapi_set_filter_params(AVFilterContext *avctx, AVFrame *input_frame) +{ + VAAPIVPPContext *vpp_ctx = avctx->priv; + HDRVAAPIContext *ctx = avctx->priv; + VAStatus vas; + VAProcFilterParameterBufferHDRToneMapping *hdrtm_param; + + vas = vaMapBuffer(vpp_ctx->hwctx->display, vpp_ctx->filter_buffers[0], + (void**)&hdrtm_param); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to map " + "buffer (%d): %d (%s).\n", + vpp_ctx->filter_buffers[0], vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + + memcpy(hdrtm_param->data.metadata, &ctx->in_metadata, sizeof(VAHdrMetaDataHDR10)); + + vas = vaUnmapBuffer(vpp_ctx->hwctx->display, vpp_ctx->filter_buffers[0]); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to unmap output buffers: " + "%d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + + return 0; +} + +static int tonemap_vaapi_build_filter_params(AVFilterContext *avctx) +{ + VAAPIVPPContext *vpp_ctx = avctx->priv; + HDRVAAPIContext *ctx = avctx->priv; + VAStatus vas; + VAProcFilterParameterBufferHDRToneMapping hdrtm_param; + VAProcFilterCapHighDynamicRange hdr_cap[VAProcHighDynamicRangeMetadataTypeCount]; + int num_query_caps; + int i; + + memset(&hdrtm_param, 0, sizeof(hdrtm_param)); + memset(&ctx->in_metadata, 0, sizeof(ctx->in_metadata)); + + num_query_caps = VAProcHighDynamicRangeMetadataTypeCount; + vas = vaQueryVideoProcFilterCaps(vpp_ctx->hwctx->display, + vpp_ctx->va_context, + VAProcFilterHighDynamicRangeToneMapping, + &hdr_cap, &num_query_caps); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query HDR caps " + "context: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + + for (i = 0; i < num_query_caps; i++) { + if (hdr_cap[i].metadata_type != VAProcHighDynamicRangeMetadataNone) + break; + } + + if (i >= num_query_caps) { + av_log(avctx, AV_LOG_ERROR, "VAAPI driver doesn't support HDR\n"); + return AVERROR(EINVAL); + } + + for (i = 0; i < num_query_caps; i++) { + if (VA_TONE_MAPPING_HDR_TO_SDR & hdr_cap[i].caps_flag) + break; + } + + if (i >= num_query_caps) { + av_log(avctx, AV_LOG_ERROR, + "VAAPI driver doesn't support HDR to SDR\n"); + return AVERROR(EINVAL); + } + + hdrtm_param.type = VAProcFilterHighDynamicRangeToneMapping; + hdrtm_param.data.metadata_type = VAProcHighDynamicRangeMetadataHDR10; + hdrtm_param.data.metadata = &ctx->in_metadata; + hdrtm_param.data.metadata_size = sizeof(VAHdrMetaDataHDR10); + + return ff_vaapi_vpp_make_param_buffers(avctx, + VAProcFilterParameterBufferType, + &hdrtm_param, sizeof(hdrtm_param), 1); +} + +static int tonemap_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) +{ + AVFilterContext *avctx = inlink->dst; + AVFilterLink *outlink = avctx->outputs[0]; + VAAPIVPPContext *vpp_ctx = avctx->priv; + HDRVAAPIContext *ctx = avctx->priv; + AVFrame *output_frame = NULL; + VASurfaceID input_surface, output_surface; + + VAProcPipelineParameterBuffer params; + int err; + + av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(input_frame->format), + input_frame->width, input_frame->height, input_frame->pts); + + if (vpp_ctx->va_context == VA_INVALID_ID){ + av_frame_free(&input_frame); + return AVERROR(EINVAL); + } + + err = tonemap_vaapi_save_metadata(avctx, input_frame); + if (err < 0) + goto fail; + + err = tonemap_vaapi_set_filter_params(avctx, input_frame); + if (err < 0) + goto fail; + + input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3]; + av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for tonemap vpp input.\n", + input_surface); + + output_frame = ff_get_video_buffer(outlink, vpp_ctx->output_width, + vpp_ctx->output_height); + if (!output_frame) { + err = AVERROR(ENOMEM); + goto fail; + } + + output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3]; + av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for tonemap vpp output.\n", + output_surface); + memset(¶ms, 0, sizeof(params)); + + err = av_frame_copy_props(output_frame, input_frame); + if (err < 0) + goto fail; + + if (ctx->color_primaries != AVCOL_PRI_UNSPECIFIED) + output_frame->color_primaries = ctx->color_primaries; + + if (ctx->color_transfer != AVCOL_TRC_UNSPECIFIED) + output_frame->color_trc = ctx->color_transfer; + else + output_frame->color_trc = AVCOL_TRC_BT709; + + if (ctx->color_matrix != AVCOL_SPC_UNSPECIFIED) + output_frame->colorspace = ctx->color_matrix; + + err = ff_vaapi_vpp_init_params(avctx, ¶ms, + input_frame, output_frame); + if (err < 0) + goto fail; + + err = ff_vaapi_vpp_render_picture(avctx, ¶ms, output_frame); + if (err < 0) + goto fail; + + av_frame_free(&input_frame); + + av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(output_frame->format), + output_frame->width, output_frame->height, output_frame->pts); + + return ff_filter_frame(outlink, output_frame); + +fail: + av_frame_free(&input_frame); + av_frame_free(&output_frame); + return err; +} + +static av_cold int tonemap_vaapi_init(AVFilterContext *avctx) +{ + VAAPIVPPContext *vpp_ctx = avctx->priv; + HDRVAAPIContext *ctx = avctx->priv; + + ff_vaapi_vpp_ctx_init(avctx); + vpp_ctx->build_filter_params = tonemap_vaapi_build_filter_params; + vpp_ctx->pipeline_uninit = ff_vaapi_vpp_pipeline_uninit; + + if (ctx->output_format_string) { + vpp_ctx->output_format = av_get_pix_fmt(ctx->output_format_string); + switch (vpp_ctx->output_format) { + case AV_PIX_FMT_NV12: + case AV_PIX_FMT_P010: + break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid output format.\n"); + return AVERROR(EINVAL); + } + } else { + vpp_ctx->output_format = AV_PIX_FMT_NV12; + av_log(avctx, AV_LOG_WARNING, "Output format not set, use default format NV12\n"); + } + +#define STRING_OPTION(var_name, func_name, default_value) do { \ + if (ctx->var_name ## _string) { \ + int var = av_ ## func_name ## _from_name(ctx->var_name ## _string); \ + if (var < 0) { \ + av_log(avctx, AV_LOG_ERROR, "Invalid %s.\n", #var_name); \ + return AVERROR(EINVAL); \ + } \ + ctx->var_name = var; \ + } else { \ + ctx->var_name = default_value; \ + } \ + } while (0) + + STRING_OPTION(color_primaries, color_primaries, AVCOL_PRI_UNSPECIFIED); + STRING_OPTION(color_transfer, color_transfer, AVCOL_TRC_UNSPECIFIED); + STRING_OPTION(color_matrix, color_space, AVCOL_SPC_UNSPECIFIED); + + return 0; +} + +#define OFFSET(x) offsetof(HDRVAAPIContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) +static const AVOption tonemap_vaapi_options[] = { + { "format", "Output pixel format set", OFFSET(output_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS, "format" }, + { "matrix", "Output color matrix coefficient set", + OFFSET(color_matrix_string), AV_OPT_TYPE_STRING, + { .str = NULL }, .flags = FLAGS, "matrix" }, + { "m", "Output color matrix coefficient set", + OFFSET(color_matrix_string), AV_OPT_TYPE_STRING, + { .str = NULL }, .flags = FLAGS, "matrix" }, + { "primaries", "Output color primaries set", + OFFSET(color_primaries_string), AV_OPT_TYPE_STRING, + { .str = NULL }, .flags = FLAGS, "primaries" }, + { "p", "Output color primaries set", + OFFSET(color_primaries_string), AV_OPT_TYPE_STRING, + { .str = NULL }, .flags = FLAGS, "primaries" }, + { "transfer", "Output color transfer characteristics set", + OFFSET(color_transfer_string), AV_OPT_TYPE_STRING, + { .str = NULL }, .flags = FLAGS, "transfer" }, + { "t", "Output color transfer characteristics set", + OFFSET(color_transfer_string), AV_OPT_TYPE_STRING, + { .str = NULL }, .flags = FLAGS, "transfer" }, + { NULL } +}; + + +AVFILTER_DEFINE_CLASS(tonemap_vaapi); + +static const AVFilterPad tonemap_vaapi_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &tonemap_vaapi_filter_frame, + .config_props = &ff_vaapi_vpp_config_input, + }, + { NULL } +}; + +static const AVFilterPad tonemap_vaapi_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vaapi_vpp_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_tonemap_vaapi = { + .name = "tonemap_vaapi", + .description = NULL_IF_CONFIG_SMALL("VAAPI VPP for tone-mapping"), + .priv_size = sizeof(HDRVAAPIContext), + .init = &tonemap_vaapi_init, + .uninit = &ff_vaapi_vpp_ctx_uninit, + .query_formats = &ff_vaapi_vpp_query_formats, + .inputs = tonemap_vaapi_inputs, + .outputs = tonemap_vaapi_outputs, + .priv_class = &tonemap_vaapi_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_tpad.c ffmpeg-4.4/libavfilter/vf_tpad.c --- ffmpeg-4.2.2/libavfilter/vf_tpad.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_tpad.c 2020-07-11 10:39:30.000000000 +0000 @@ -181,7 +181,7 @@ return 0; } -static void uninit(AVFilterContext *ctx) +static av_cold void uninit(AVFilterContext *ctx) { TPadContext *s = ctx->priv; diff -Nru ffmpeg-4.2.2/libavfilter/vf_transpose.c ffmpeg-4.4/libavfilter/vf_transpose.c --- ffmpeg-4.2.2/libavfilter/vf_transpose.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_transpose.c 2020-07-11 10:39:30.000000000 +0000 @@ -40,14 +40,6 @@ #include "video.h" #include "transpose.h" -typedef struct TransVtable { - void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize, - uint8_t *dst, ptrdiff_t dst_linesize); - void (*transpose_block)(uint8_t *src, ptrdiff_t src_linesize, - uint8_t *dst, ptrdiff_t dst_linesize, - int w, int h); -} TransVtable; - typedef struct TransContext { const AVClass *class; int hsub, vsub; @@ -243,6 +235,14 @@ } } + if (ARCH_X86) { + for (int i = 0; i < 4; i++) { + TransVtable *v = &s->vtables[i]; + + ff_transpose_init_x86(v, s->pixsteps[i]); + } + } + av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d dir:%d -> w:%d h:%d rotation:%s vflip:%d\n", inlink->w, inlink->h, s->dir, outlink->w, outlink->h, diff -Nru ffmpeg-4.2.2/libavfilter/vf_transpose_vaapi.c ffmpeg-4.4/libavfilter/vf_transpose_vaapi.c --- ffmpeg-4.2.2/libavfilter/vf_transpose_vaapi.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_transpose_vaapi.c 2020-07-11 10:39:30.000000000 +0000 @@ -145,7 +145,7 @@ err = av_frame_copy_props(output_frame, input_frame); if (err < 0) - return err; + goto fail; err = ff_vaapi_vpp_init_params(avctx, ¶ms, input_frame, output_frame); diff -Nru ffmpeg-4.2.2/libavfilter/vf_unsharp.c ffmpeg-4.4/libavfilter/vf_unsharp.c --- ffmpeg-4.2.2/libavfilter/vf_unsharp.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_unsharp.c 2021-04-08 21:28:40.000000000 +0000 @@ -57,81 +57,90 @@ int height; } ThreadData; -static int unsharp_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) -{ - ThreadData *td = arg; - UnsharpFilterParam *fp = td->fp; - uint32_t **sc = fp->sc; - uint32_t *sr = fp->sr; - const uint8_t *src2 = NULL; //silence a warning - const int amount = fp->amount; - const int steps_x = fp->steps_x; - const int steps_y = fp->steps_y; - const int scalebits = fp->scalebits; - const int32_t halfscale = fp->halfscale; - - uint8_t *dst = td->dst; - const uint8_t *src = td->src; - const int dst_stride = td->dst_stride; - const int src_stride = td->src_stride; - const int width = td->width; - const int height = td->height; - const int sc_offset = jobnr * 2 * steps_y; - const int sr_offset = jobnr * (MAX_MATRIX_SIZE - 1); - const int slice_start = (height * jobnr) / nb_jobs; - const int slice_end = (height * (jobnr+1)) / nb_jobs; - - int32_t res; - int x, y, z; - uint32_t tmp1, tmp2; - - if (!amount) { - av_image_copy_plane(dst + slice_start * dst_stride, dst_stride, - src + slice_start * src_stride, src_stride, - width, slice_end - slice_start); - return 0; - } - - for (y = 0; y < 2 * steps_y; y++) - memset(sc[sc_offset + y], 0, sizeof(sc[y][0]) * (width + 2 * steps_x)); - - // if this is not the first tile, we start from (slice_start - steps_y), - // so we can get smooth result at slice boundary - if (slice_start > steps_y) { - src += (slice_start - steps_y) * src_stride; - dst += (slice_start - steps_y) * dst_stride; - } - - for (y = -steps_y + slice_start; y < steps_y + slice_end; y++) { - if (y < height) - src2 = src; - - memset(sr + sr_offset, 0, sizeof(sr[0]) * (2 * steps_x - 1)); - for (x = -steps_x; x < width + steps_x; x++) { - tmp1 = x <= 0 ? src2[0] : x >= width ? src2[width-1] : src2[x]; - for (z = 0; z < steps_x * 2; z += 2) { - tmp2 = sr[sr_offset + z + 0] + tmp1; sr[sr_offset + z + 0] = tmp1; - tmp1 = sr[sr_offset + z + 1] + tmp2; sr[sr_offset + z + 1] = tmp2; - } - for (z = 0; z < steps_y * 2; z += 2) { - tmp2 = sc[sc_offset + z + 0][x + steps_x] + tmp1; sc[sc_offset + z + 0][x + steps_x] = tmp1; - tmp1 = sc[sc_offset + z + 1][x + steps_x] + tmp2; sc[sc_offset + z + 1][x + steps_x] = tmp2; - } - if (x >= steps_x && y >= (steps_y + slice_start)) { - const uint8_t *srx = src - steps_y * src_stride + x - steps_x; - uint8_t *dsx = dst - steps_y * dst_stride + x - steps_x; - - res = (int32_t)*srx + ((((int32_t) * srx - (int32_t)((tmp1 + halfscale) >> scalebits)) * amount) >> 16); - *dsx = av_clip_uint8(res); - } - } - if (y >= 0) { - dst += dst_stride; - src += src_stride; - } - } - return 0; +#define DEF_UNSHARP_SLICE_FUNC(name, nbits) \ +static int name##_##nbits(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ +{ \ + ThreadData *td = arg; \ + UnsharpFilterParam *fp = td->fp; \ + UnsharpContext *s = ctx->priv; \ + uint32_t **sc = fp->sc; \ + uint32_t *sr = fp->sr; \ + const uint##nbits##_t *src2 = NULL; \ + const int amount = fp->amount; \ + const int steps_x = fp->steps_x; \ + const int steps_y = fp->steps_y; \ + const int scalebits = fp->scalebits; \ + const int32_t halfscale = fp->halfscale; \ + \ + uint##nbits##_t *dst = (uint##nbits##_t*)td->dst; \ + const uint##nbits##_t *src = (const uint##nbits##_t *)td->src; \ + int dst_stride = td->dst_stride; \ + int src_stride = td->src_stride; \ + const int width = td->width; \ + const int height = td->height; \ + const int sc_offset = jobnr * 2 * steps_y; \ + const int sr_offset = jobnr * (MAX_MATRIX_SIZE - 1); \ + const int slice_start = (height * jobnr) / nb_jobs; \ + const int slice_end = (height * (jobnr+1)) / nb_jobs; \ + \ + int32_t res; \ + int x, y, z; \ + uint32_t tmp1, tmp2; \ + \ + if (!amount) { \ + av_image_copy_plane(td->dst + slice_start * dst_stride, dst_stride, \ + td->src + slice_start * src_stride, src_stride, \ + width * s->bps, slice_end - slice_start); \ + return 0; \ + } \ + \ + for (y = 0; y < 2 * steps_y; y++) \ + memset(sc[sc_offset + y], 0, sizeof(sc[y][0]) * (width + 2 * steps_x)); \ + \ + dst_stride = dst_stride / s->bps; \ + src_stride = src_stride / s->bps; \ + /* if this is not the first tile, we start from (slice_start - steps_y) */ \ + /* so we can get smooth result at slice boundary */ \ + if (slice_start > steps_y) { \ + src += (slice_start - steps_y) * src_stride; \ + dst += (slice_start - steps_y) * dst_stride; \ + } \ + \ + for (y = -steps_y + slice_start; y < steps_y + slice_end; y++) { \ + if (y < height) \ + src2 = src; \ + \ + memset(sr + sr_offset, 0, sizeof(sr[0]) * (2 * steps_x - 1)); \ + for (x = -steps_x; x < width + steps_x; x++) { \ + tmp1 = x <= 0 ? src2[0] : x >= width ? src2[width-1] : src2[x]; \ + for (z = 0; z < steps_x * 2; z += 2) { \ + tmp2 = sr[sr_offset + z + 0] + tmp1; sr[sr_offset + z + 0] = tmp1; \ + tmp1 = sr[sr_offset + z + 1] + tmp2; sr[sr_offset + z + 1] = tmp2; \ + } \ + for (z = 0; z < steps_y * 2; z += 2) { \ + tmp2 = sc[sc_offset + z + 0][x + steps_x] + tmp1; \ + sc[sc_offset + z + 0][x + steps_x] = tmp1; \ + tmp1 = sc[sc_offset + z + 1][x + steps_x] + tmp2; \ + sc[sc_offset + z + 1][x + steps_x] = tmp2; \ + } \ + if (x >= steps_x && y >= (steps_y + slice_start)) { \ + const uint##nbits##_t *srx = src - steps_y * src_stride + x - steps_x; \ + uint##nbits##_t *dsx = dst - steps_y * dst_stride + x - steps_x; \ + \ + res = (int32_t)*srx + ((((int32_t) * srx - \ + (int32_t)((tmp1 + halfscale) >> scalebits)) * amount) >> (8+nbits)); \ + *dsx = av_clip_uint##nbits(res); \ + } \ + } \ + if (y >= 0) { \ + dst += dst_stride; \ + src += src_stride; \ + } \ + } \ + return 0; \ } +DEF_UNSHARP_SLICE_FUNC(unsharp_slice, 16) +DEF_UNSHARP_SLICE_FUNC(unsharp_slice, 8) static int apply_unsharp_c(AVFilterContext *ctx, AVFrame *in, AVFrame *out) { @@ -155,7 +164,7 @@ td.height = plane_h[i]; td.dst_stride = out->linesize[i]; td.src_stride = in->linesize[i]; - ctx->internal->execute(ctx, unsharp_slice, &td, NULL, FFMIN(plane_h[i], s->nb_threads)); + ctx->internal->execute(ctx, s->unsharp_slice, &td, NULL, FFMIN(plane_h[i], s->nb_threads)); } return 0; } @@ -192,6 +201,10 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_NONE }; @@ -218,7 +231,7 @@ effect, effect_type, fp->msize_x, fp->msize_y, fp->amount / 65535.0); fp->sr = av_malloc_array((MAX_MATRIX_SIZE - 1) * s->nb_threads, sizeof(uint32_t)); - fp->sc = av_malloc_array(2 * fp->steps_y * s->nb_threads, sizeof(uint32_t **)); + fp->sc = av_mallocz_array(2 * fp->steps_y * s->nb_threads, sizeof(uint32_t *)); if (!fp->sr || !fp->sc) return AVERROR(ENOMEM); @@ -230,24 +243,27 @@ return 0; } -static int config_props(AVFilterLink *link) +static int config_input(AVFilterLink *inlink) { - UnsharpContext *s = link->dst->priv; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); + UnsharpContext *s = inlink->dst->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); int ret; s->hsub = desc->log2_chroma_w; s->vsub = desc->log2_chroma_h; + s->bitdepth = desc->comp[0].depth; + s->bps = s->bitdepth > 8 ? 2 : 1; + s->unsharp_slice = s->bitdepth > 8 ? unsharp_slice_16 : unsharp_slice_8; // ensure (height / nb_threads) > 4 * steps_y, // so that we don't have too much overlap between two threads - s->nb_threads = FFMIN(ff_filter_get_nb_threads(link->dst), - link->h / (4 * s->luma.steps_y)); + s->nb_threads = FFMIN(ff_filter_get_nb_threads(inlink->dst), + inlink->h / (4 * s->luma.steps_y)); - ret = init_filter_param(link->dst, &s->luma, "luma", link->w); + ret = init_filter_param(inlink->dst, &s->luma, "luma", inlink->w); if (ret < 0) return ret; - ret = init_filter_param(link->dst, &s->chroma, "chroma", AV_CEIL_RSHIFT(link->w, s->hsub)); + ret = init_filter_param(inlink->dst, &s->chroma, "chroma", AV_CEIL_RSHIFT(inlink->w, s->hsub)); if (ret < 0) return ret; @@ -258,9 +274,11 @@ { int z; - for (z = 0; z < 2 * fp->steps_y * nb_threads; z++) - av_freep(&fp->sc[z]); - av_freep(&fp->sc); + if (fp->sc) { + for (z = 0; z < 2 * fp->steps_y * nb_threads; z++) + av_freep(&fp->sc[z]); + av_freep(&fp->sc); + } av_freep(&fp->sr); } @@ -325,7 +343,7 @@ .name = "default", .type = AVMEDIA_TYPE_VIDEO, .filter_frame = filter_frame, - .config_props = config_props, + .config_props = config_input, }, { NULL } }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_untile.c ffmpeg-4.4/libavfilter/vf_untile.c --- ffmpeg-4.2.2/libavfilter/vf_untile.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_untile.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2020 Nicolas George + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "formats.h" +#include "filters.h" + +typedef struct UntileContext { + const AVClass *class; + unsigned w, h; + unsigned current; + unsigned nb_frames; + AVFrame *frame; + const AVPixFmtDescriptor *desc; + int64_t dpts, pts; + int max_step[4]; +} UntileContext; + +#define OFFSET(x) offsetof(UntileContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption untile_options[] = { + { "layout", "set grid size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, + {.str = "6x5"}, 0, 0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(untile); + +static av_cold int init(AVFilterContext *ctx) +{ + UntileContext *s = ctx->priv; + + if (s->w > UINT_MAX / s->h) { + av_log(ctx, AV_LOG_ERROR, "Tile size %ux%u is insane.\n", + s->w, s->h); + return AVERROR(EINVAL); + } + s->nb_frames = s->w * s->h; + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + int ret; + + ret = ff_formats_pixdesc_filter(&formats, 0, + AV_PIX_FMT_FLAG_HWACCEL | + AV_PIX_FMT_FLAG_BITSTREAM | + FF_PIX_FMT_FLAG_SW_FLAT_SUB); + if (ret < 0) + return ret; + return ff_set_common_formats(ctx, formats); +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + UntileContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + AVRational dt; + + s->desc = av_pix_fmt_desc_get(outlink->format); + if (inlink->w % (s->w << s->desc->log2_chroma_w) || + inlink->h % (s->h << s->desc->log2_chroma_h)) { + av_log(ctx, AV_LOG_ERROR, + "Input resolution %ux%u not multiple of layout %ux%u.\n", + inlink->w, inlink->h, s->w, s->h); + return AVERROR(EINVAL); + } + outlink->w = inlink->w / s->w; + outlink->h = inlink->h / s->h; + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; + outlink->frame_rate = av_mul_q(inlink->frame_rate, av_make_q(s->nb_frames, 1)); + if (outlink->frame_rate.num) + dt = av_inv_q(outlink->frame_rate); + else + dt = av_mul_q(inlink->time_base, av_make_q(1, s->nb_frames)); + outlink->time_base = av_gcd_q(inlink->time_base, dt, AV_TIME_BASE / 2, AV_TIME_BASE_Q); + s->dpts = av_rescale_q(1, dt, outlink->time_base); + av_log(ctx, AV_LOG_VERBOSE, "frame interval: %"PRId64"*%d/%d\n", + s->dpts, dt.num, dt.den); + av_image_fill_max_pixsteps(s->max_step, NULL, s->desc); + return 0; +} + +static int activate(AVFilterContext *ctx) +{ + UntileContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + int i, x, y, ret; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + if (!s->frame) { + ret = ff_inlink_consume_frame(inlink, &s->frame); + if (ret < 0) + return ret; + if (ret) + s->pts = av_rescale_q(s->frame->pts, inlink->time_base, outlink->time_base); + } + if (s->frame) { + if (s->current == s->nb_frames - 1) { + out = s->frame; + s->frame = NULL; + } else { + out = av_frame_clone(s->frame); + if (!out) + return AVERROR(ENOMEM); + } + x = outlink->w * (s->current % s->w); + y = outlink->h * (s->current / s->w); + out->width = outlink->w; + out->height = outlink->h; + out->data[0] += y * out->linesize[0]; + out->data[0] += x * s->max_step[0]; + if (!(s->desc->flags & AV_PIX_FMT_FLAG_PAL || s->desc->flags & FF_PSEUDOPAL)) { + for (i = 1; i < 3; i ++) { + if (out->data[i]) { + out->data[i] += (y >> s->desc->log2_chroma_w) * out->linesize[i]; + out->data[i] += (x >> s->desc->log2_chroma_h) * s->max_step[i]; + } + } + } + if (out->data[3]) { + out->data[3] += y * out->linesize[3]; + out->data[3] += x * s->max_step[3]; + } + out->pts = s->pts; + s->pts += s->dpts; + if (++s->current == s->nb_frames) + s->current = 0; + return ff_filter_frame(outlink, out); + } + FF_FILTER_FORWARD_STATUS(inlink, outlink); + FF_FILTER_FORWARD_WANTED(outlink, inlink); + return FFERROR_NOT_READY; + +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + UntileContext *s = ctx->priv; + + av_frame_free(&s->frame); +} + +static const AVFilterPad untile_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +static const AVFilterPad untile_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vf_untile = { + .name = "untile", + .description = NULL_IF_CONFIG_SMALL("Untile a frame into a sequence of frames."), + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .activate = activate, + .priv_size = sizeof(UntileContext), + .inputs = untile_inputs, + .outputs = untile_outputs, + .priv_class = &untile_class, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_uspp.c ffmpeg-4.4/libavfilter/vf_uspp.c --- ffmpeg-4.2.2/libavfilter/vf_uspp.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_uspp.c 2021-04-08 21:28:40.000000000 +0000 @@ -29,9 +29,11 @@ #include "libavutil/avassert.h" #include "libavutil/imgutils.h" +#include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "internal.h" +#include "qp_table.h" #include "avfilter.h" #define MAX_LEVEL 8 /* quality levels */ @@ -49,10 +51,11 @@ int outbuf_size; uint8_t *outbuf; AVCodecContext *avctx_enc[BLOCK*BLOCK]; + AVPacket *pkt; AVFrame *frame; AVFrame *frame_dec; - uint8_t *non_b_qp_table; - int non_b_qp_alloc_size; + int8_t *non_b_qp_table; + int non_b_qp_stride; int use_bframe_qp; } USPPContext; @@ -238,23 +241,24 @@ const int y1c = y1 >> p->vsub; const int BLOCKc = BLOCK >> p->hsub; int offset; - AVPacket pkt = {0}; + AVPacket *pkt = p->pkt; int got_pkt_ptr; - av_init_packet(&pkt); - pkt.data = p->outbuf; - pkt.size = p->outbuf_size; + av_packet_unref(pkt); + pkt->data = p->outbuf; + pkt->size = p->outbuf_size; p->frame->data[0] = p->src[0] + x1 + y1 * p->frame->linesize[0]; p->frame->data[1] = p->src[1] + x1c + y1c * p->frame->linesize[1]; p->frame->data[2] = p->src[2] + x1c + y1c * p->frame->linesize[2]; p->frame->format = p->avctx_enc[i]->pix_fmt; - ret = avcodec_encode_video2(p->avctx_enc[i], &pkt, p->frame, &got_pkt_ptr); + ret = avcodec_encode_video2(p->avctx_enc[i], pkt, p->frame, &got_pkt_ptr); if (ret < 0) { av_log(p->avctx_enc[i], AV_LOG_ERROR, "Encoding failed\n"); continue; } + av_packet_unref(pkt); p->frame_dec = p->avctx_enc[i]->coded_frame; @@ -316,7 +320,7 @@ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); int i; - AVCodec *enc = avcodec_find_encoder(AV_CODEC_ID_SNOW); + const AVCodec *enc = avcodec_find_encoder(AV_CODEC_ID_SNOW); if (!enc) { av_log(ctx, AV_LOG_ERROR, "SNOW encoder not found.\n"); return AVERROR(EINVAL); @@ -362,15 +366,17 @@ avctx_enc->global_quality = 123; av_dict_set(&opts, "no_bitstream", "1", 0); ret = avcodec_open2(avctx_enc, enc, &opts); + av_dict_free(&opts); if (ret < 0) return ret; - av_dict_free(&opts); av_assert0(avctx_enc->codec); } uspp->outbuf_size = (width + BLOCK) * (height + BLOCK) * 10; if (!(uspp->frame = av_frame_alloc())) return AVERROR(ENOMEM); + if (!(uspp->pkt = av_packet_alloc())) + return AVERROR(ENOMEM); if (!(uspp->outbuf = av_malloc(uspp->outbuf_size))) return AVERROR(ENOMEM); @@ -385,45 +391,32 @@ AVFrame *out = in; int qp_stride = 0; - uint8_t *qp_table = NULL; + int8_t *qp_table = NULL; + int ret = 0; /* if we are not in a constant user quantizer mode and we don't want to use * the quantizers from the B-frames (B-frames often have a higher QP), we * need to save the qp table from the last non B-frame; this is what the * following code block does */ - if (!uspp->qp) { - qp_table = av_frame_get_qp_table(in, &qp_stride, &uspp->qscale_type); - - if (qp_table && !uspp->use_bframe_qp && in->pict_type != AV_PICTURE_TYPE_B) { - int w, h; - - /* if the qp stride is not set, it means the QP are only defined on - * a line basis */ - if (!qp_stride) { - w = AV_CEIL_RSHIFT(inlink->w, 4); - h = 1; - } else { - w = qp_stride; - h = AV_CEIL_RSHIFT(inlink->h, 4); - } - - if (w * h > uspp->non_b_qp_alloc_size) { - int ret = av_reallocp_array(&uspp->non_b_qp_table, w, h); - if (ret < 0) { - uspp->non_b_qp_alloc_size = 0; - return ret; - } - uspp->non_b_qp_alloc_size = w * h; - } + if (!uspp->qp && (uspp->use_bframe_qp || in->pict_type != AV_PICTURE_TYPE_B)) { + ret = ff_qp_table_extract(in, &qp_table, &qp_stride, NULL, &uspp->qscale_type); + if (ret < 0) { + av_frame_free(&in); + return ret; + } - av_assert0(w * h <= uspp->non_b_qp_alloc_size); - memcpy(uspp->non_b_qp_table, qp_table, w * h); + if (!uspp->use_bframe_qp && in->pict_type != AV_PICTURE_TYPE_B) { + av_freep(&uspp->non_b_qp_table); + uspp->non_b_qp_table = qp_table; + uspp->non_b_qp_stride = qp_stride; } } if (uspp->log2_count && !ctx->is_disabled) { - if (!uspp->use_bframe_qp && uspp->non_b_qp_table) + if (!uspp->use_bframe_qp && uspp->non_b_qp_table) { qp_table = uspp->non_b_qp_table; + qp_stride = uspp->non_b_qp_stride; + } if (qp_table || uspp->qp) { @@ -436,6 +429,8 @@ out = ff_get_video_buffer(outlink, aligned_w, aligned_h); if (!out) { av_frame_free(&in); + if (qp_table != uspp->non_b_qp_table) + av_free(qp_table); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); @@ -455,7 +450,10 @@ inlink->w, inlink->h); av_frame_free(&in); } - return ff_filter_frame(outlink, out); + ret = ff_filter_frame(outlink, out); + if (qp_table != uspp->non_b_qp_table) + av_freep(&qp_table); + return ret; } static av_cold void uninit(AVFilterContext *ctx) @@ -468,13 +466,12 @@ av_freep(&uspp->src[i]); } - for (i = 0; i < (1 << uspp->log2_count); i++) { - avcodec_close(uspp->avctx_enc[i]); - av_freep(&uspp->avctx_enc[i]); - } + for (i = 0; i < (1 << uspp->log2_count); i++) + avcodec_free_context(&uspp->avctx_enc[i]); av_freep(&uspp->non_b_qp_table); av_freep(&uspp->outbuf); + av_packet_free(&uspp->pkt); av_frame_free(&uspp->frame); } diff -Nru ffmpeg-4.2.2/libavfilter/vf_v360.c ffmpeg-4.4/libavfilter/vf_v360.c --- ffmpeg-4.2.2/libavfilter/vf_v360.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_v360.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,4780 @@ +/* + * Copyright (c) 2019 Eugene Lyapustin + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * 360 video conversion filter. + * Principle of operation: + * + * (for each pixel in output frame) + * 1) Calculate OpenGL-like coordinates (x, y, z) for pixel position (i, j) + * 2) Apply 360 operations (rotation, mirror) to (x, y, z) + * 3) Calculate pixel position (u, v) in input frame + * 4) Calculate interpolation window and weight for each pixel + * + * (for each frame) + * 5) Remap input frame to output frame using precalculated data + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" +#include "v360.h" + +typedef struct ThreadData { + AVFrame *in; + AVFrame *out; +} ThreadData; + +#define OFFSET(x) offsetof(V360Context, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption v360_options[] = { + { "input", "set input projection", OFFSET(in), AV_OPT_TYPE_INT, {.i64=EQUIRECTANGULAR}, 0, NB_PROJECTIONS-1, FLAGS, "in" }, + { "e", "equirectangular", 0, AV_OPT_TYPE_CONST, {.i64=EQUIRECTANGULAR}, 0, 0, FLAGS, "in" }, + { "equirect", "equirectangular", 0, AV_OPT_TYPE_CONST, {.i64=EQUIRECTANGULAR}, 0, 0, FLAGS, "in" }, + { "c3x2", "cubemap 3x2", 0, AV_OPT_TYPE_CONST, {.i64=CUBEMAP_3_2}, 0, 0, FLAGS, "in" }, + { "c6x1", "cubemap 6x1", 0, AV_OPT_TYPE_CONST, {.i64=CUBEMAP_6_1}, 0, 0, FLAGS, "in" }, + { "eac", "equi-angular cubemap", 0, AV_OPT_TYPE_CONST, {.i64=EQUIANGULAR}, 0, 0, FLAGS, "in" }, + { "dfisheye", "dual fisheye", 0, AV_OPT_TYPE_CONST, {.i64=DUAL_FISHEYE}, 0, 0, FLAGS, "in" }, + { "flat", "regular video", 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "in" }, + {"rectilinear", "regular video", 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "in" }, + { "gnomonic", "regular video", 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "in" }, + { "barrel", "barrel facebook's 360 format", 0, AV_OPT_TYPE_CONST, {.i64=BARREL}, 0, 0, FLAGS, "in" }, + { "fb", "barrel facebook's 360 format", 0, AV_OPT_TYPE_CONST, {.i64=BARREL}, 0, 0, FLAGS, "in" }, + { "c1x6", "cubemap 1x6", 0, AV_OPT_TYPE_CONST, {.i64=CUBEMAP_1_6}, 0, 0, FLAGS, "in" }, + { "sg", "stereographic", 0, AV_OPT_TYPE_CONST, {.i64=STEREOGRAPHIC}, 0, 0, FLAGS, "in" }, + { "mercator", "mercator", 0, AV_OPT_TYPE_CONST, {.i64=MERCATOR}, 0, 0, FLAGS, "in" }, + { "ball", "ball", 0, AV_OPT_TYPE_CONST, {.i64=BALL}, 0, 0, FLAGS, "in" }, + { "hammer", "hammer", 0, AV_OPT_TYPE_CONST, {.i64=HAMMER}, 0, 0, FLAGS, "in" }, + {"sinusoidal", "sinusoidal", 0, AV_OPT_TYPE_CONST, {.i64=SINUSOIDAL}, 0, 0, FLAGS, "in" }, + { "fisheye", "fisheye", 0, AV_OPT_TYPE_CONST, {.i64=FISHEYE}, 0, 0, FLAGS, "in" }, + { "pannini", "pannini", 0, AV_OPT_TYPE_CONST, {.i64=PANNINI}, 0, 0, FLAGS, "in" }, + {"cylindrical", "cylindrical", 0, AV_OPT_TYPE_CONST, {.i64=CYLINDRICAL}, 0, 0, FLAGS, "in" }, + {"tetrahedron", "tetrahedron", 0, AV_OPT_TYPE_CONST, {.i64=TETRAHEDRON}, 0, 0, FLAGS, "in" }, + {"barrelsplit", "barrel split facebook's 360 format", 0, AV_OPT_TYPE_CONST, {.i64=BARREL_SPLIT}, 0, 0, FLAGS, "in" }, + { "tsp", "truncated square pyramid", 0, AV_OPT_TYPE_CONST, {.i64=TSPYRAMID}, 0, 0, FLAGS, "in" }, + { "hequirect", "half equirectangular", 0, AV_OPT_TYPE_CONST, {.i64=HEQUIRECTANGULAR},0, 0, FLAGS, "in" }, + { "he", "half equirectangular", 0, AV_OPT_TYPE_CONST, {.i64=HEQUIRECTANGULAR},0, 0, FLAGS, "in" }, + { "equisolid", "equisolid", 0, AV_OPT_TYPE_CONST, {.i64=EQUISOLID}, 0, 0, FLAGS, "in" }, + { "og", "orthographic", 0, AV_OPT_TYPE_CONST, {.i64=ORTHOGRAPHIC}, 0, 0, FLAGS, "in" }, + {"octahedron", "octahedron", 0, AV_OPT_TYPE_CONST, {.i64=OCTAHEDRON}, 0, 0, FLAGS, "in" }, + { "output", "set output projection", OFFSET(out), AV_OPT_TYPE_INT, {.i64=CUBEMAP_3_2}, 0, NB_PROJECTIONS-1, FLAGS, "out" }, + { "e", "equirectangular", 0, AV_OPT_TYPE_CONST, {.i64=EQUIRECTANGULAR}, 0, 0, FLAGS, "out" }, + { "equirect", "equirectangular", 0, AV_OPT_TYPE_CONST, {.i64=EQUIRECTANGULAR}, 0, 0, FLAGS, "out" }, + { "c3x2", "cubemap 3x2", 0, AV_OPT_TYPE_CONST, {.i64=CUBEMAP_3_2}, 0, 0, FLAGS, "out" }, + { "c6x1", "cubemap 6x1", 0, AV_OPT_TYPE_CONST, {.i64=CUBEMAP_6_1}, 0, 0, FLAGS, "out" }, + { "eac", "equi-angular cubemap", 0, AV_OPT_TYPE_CONST, {.i64=EQUIANGULAR}, 0, 0, FLAGS, "out" }, + { "dfisheye", "dual fisheye", 0, AV_OPT_TYPE_CONST, {.i64=DUAL_FISHEYE}, 0, 0, FLAGS, "out" }, + { "flat", "regular video", 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "out" }, + {"rectilinear", "regular video", 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "out" }, + { "gnomonic", "regular video", 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "out" }, + { "barrel", "barrel facebook's 360 format", 0, AV_OPT_TYPE_CONST, {.i64=BARREL}, 0, 0, FLAGS, "out" }, + { "fb", "barrel facebook's 360 format", 0, AV_OPT_TYPE_CONST, {.i64=BARREL}, 0, 0, FLAGS, "out" }, + { "c1x6", "cubemap 1x6", 0, AV_OPT_TYPE_CONST, {.i64=CUBEMAP_1_6}, 0, 0, FLAGS, "out" }, + { "sg", "stereographic", 0, AV_OPT_TYPE_CONST, {.i64=STEREOGRAPHIC}, 0, 0, FLAGS, "out" }, + { "mercator", "mercator", 0, AV_OPT_TYPE_CONST, {.i64=MERCATOR}, 0, 0, FLAGS, "out" }, + { "ball", "ball", 0, AV_OPT_TYPE_CONST, {.i64=BALL}, 0, 0, FLAGS, "out" }, + { "hammer", "hammer", 0, AV_OPT_TYPE_CONST, {.i64=HAMMER}, 0, 0, FLAGS, "out" }, + {"sinusoidal", "sinusoidal", 0, AV_OPT_TYPE_CONST, {.i64=SINUSOIDAL}, 0, 0, FLAGS, "out" }, + { "fisheye", "fisheye", 0, AV_OPT_TYPE_CONST, {.i64=FISHEYE}, 0, 0, FLAGS, "out" }, + { "pannini", "pannini", 0, AV_OPT_TYPE_CONST, {.i64=PANNINI}, 0, 0, FLAGS, "out" }, + {"cylindrical", "cylindrical", 0, AV_OPT_TYPE_CONST, {.i64=CYLINDRICAL}, 0, 0, FLAGS, "out" }, + {"perspective", "perspective", 0, AV_OPT_TYPE_CONST, {.i64=PERSPECTIVE}, 0, 0, FLAGS, "out" }, + {"tetrahedron", "tetrahedron", 0, AV_OPT_TYPE_CONST, {.i64=TETRAHEDRON}, 0, 0, FLAGS, "out" }, + {"barrelsplit", "barrel split facebook's 360 format", 0, AV_OPT_TYPE_CONST, {.i64=BARREL_SPLIT}, 0, 0, FLAGS, "out" }, + { "tsp", "truncated square pyramid", 0, AV_OPT_TYPE_CONST, {.i64=TSPYRAMID}, 0, 0, FLAGS, "out" }, + { "hequirect", "half equirectangular", 0, AV_OPT_TYPE_CONST, {.i64=HEQUIRECTANGULAR},0, 0, FLAGS, "out" }, + { "he", "half equirectangular", 0, AV_OPT_TYPE_CONST, {.i64=HEQUIRECTANGULAR},0, 0, FLAGS, "out" }, + { "equisolid", "equisolid", 0, AV_OPT_TYPE_CONST, {.i64=EQUISOLID}, 0, 0, FLAGS, "out" }, + { "og", "orthographic", 0, AV_OPT_TYPE_CONST, {.i64=ORTHOGRAPHIC}, 0, 0, FLAGS, "out" }, + {"octahedron", "octahedron", 0, AV_OPT_TYPE_CONST, {.i64=OCTAHEDRON}, 0, 0, FLAGS, "out" }, + { "interp", "set interpolation method", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=BILINEAR}, 0, NB_INTERP_METHODS-1, FLAGS, "interp" }, + { "near", "nearest neighbour", 0, AV_OPT_TYPE_CONST, {.i64=NEAREST}, 0, 0, FLAGS, "interp" }, + { "nearest", "nearest neighbour", 0, AV_OPT_TYPE_CONST, {.i64=NEAREST}, 0, 0, FLAGS, "interp" }, + { "line", "bilinear interpolation", 0, AV_OPT_TYPE_CONST, {.i64=BILINEAR}, 0, 0, FLAGS, "interp" }, + { "linear", "bilinear interpolation", 0, AV_OPT_TYPE_CONST, {.i64=BILINEAR}, 0, 0, FLAGS, "interp" }, + { "lagrange9", "lagrange9 interpolation", 0, AV_OPT_TYPE_CONST, {.i64=LAGRANGE9}, 0, 0, FLAGS, "interp" }, + { "cube", "bicubic interpolation", 0, AV_OPT_TYPE_CONST, {.i64=BICUBIC}, 0, 0, FLAGS, "interp" }, + { "cubic", "bicubic interpolation", 0, AV_OPT_TYPE_CONST, {.i64=BICUBIC}, 0, 0, FLAGS, "interp" }, + { "lanc", "lanczos interpolation", 0, AV_OPT_TYPE_CONST, {.i64=LANCZOS}, 0, 0, FLAGS, "interp" }, + { "lanczos", "lanczos interpolation", 0, AV_OPT_TYPE_CONST, {.i64=LANCZOS}, 0, 0, FLAGS, "interp" }, + { "sp16", "spline16 interpolation", 0, AV_OPT_TYPE_CONST, {.i64=SPLINE16}, 0, 0, FLAGS, "interp" }, + { "spline16", "spline16 interpolation", 0, AV_OPT_TYPE_CONST, {.i64=SPLINE16}, 0, 0, FLAGS, "interp" }, + { "gauss", "gaussian interpolation", 0, AV_OPT_TYPE_CONST, {.i64=GAUSSIAN}, 0, 0, FLAGS, "interp" }, + { "gaussian", "gaussian interpolation", 0, AV_OPT_TYPE_CONST, {.i64=GAUSSIAN}, 0, 0, FLAGS, "interp" }, + { "mitchell", "mitchell interpolation", 0, AV_OPT_TYPE_CONST, {.i64=MITCHELL}, 0, 0, FLAGS, "interp" }, + { "w", "output width", OFFSET(width), AV_OPT_TYPE_INT, {.i64=0}, 0, INT16_MAX, FLAGS, "w"}, + { "h", "output height", OFFSET(height), AV_OPT_TYPE_INT, {.i64=0}, 0, INT16_MAX, FLAGS, "h"}, + { "in_stereo", "input stereo format", OFFSET(in_stereo), AV_OPT_TYPE_INT, {.i64=STEREO_2D}, 0, NB_STEREO_FMTS-1, FLAGS, "stereo" }, + {"out_stereo", "output stereo format", OFFSET(out_stereo), AV_OPT_TYPE_INT, {.i64=STEREO_2D}, 0, NB_STEREO_FMTS-1, FLAGS, "stereo" }, + { "2d", "2d mono", 0, AV_OPT_TYPE_CONST, {.i64=STEREO_2D}, 0, 0, FLAGS, "stereo" }, + { "sbs", "side by side", 0, AV_OPT_TYPE_CONST, {.i64=STEREO_SBS}, 0, 0, FLAGS, "stereo" }, + { "tb", "top bottom", 0, AV_OPT_TYPE_CONST, {.i64=STEREO_TB}, 0, 0, FLAGS, "stereo" }, + { "in_forder", "input cubemap face order", OFFSET(in_forder), AV_OPT_TYPE_STRING, {.str="rludfb"}, 0, NB_DIRECTIONS-1, FLAGS, "in_forder"}, + {"out_forder", "output cubemap face order", OFFSET(out_forder), AV_OPT_TYPE_STRING, {.str="rludfb"}, 0, NB_DIRECTIONS-1, FLAGS, "out_forder"}, + { "in_frot", "input cubemap face rotation", OFFSET(in_frot), AV_OPT_TYPE_STRING, {.str="000000"}, 0, NB_DIRECTIONS-1, FLAGS, "in_frot"}, + { "out_frot", "output cubemap face rotation",OFFSET(out_frot), AV_OPT_TYPE_STRING, {.str="000000"}, 0, NB_DIRECTIONS-1, FLAGS, "out_frot"}, + { "in_pad", "percent input cubemap pads", OFFSET(in_pad), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 0.1,TFLAGS, "in_pad"}, + { "out_pad", "percent output cubemap pads", OFFSET(out_pad), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 0.1,TFLAGS, "out_pad"}, + { "fin_pad", "fixed input cubemap pads", OFFSET(fin_pad), AV_OPT_TYPE_INT, {.i64=0}, 0, 100,TFLAGS, "fin_pad"}, + { "fout_pad", "fixed output cubemap pads", OFFSET(fout_pad), AV_OPT_TYPE_INT, {.i64=0}, 0, 100,TFLAGS, "fout_pad"}, + { "yaw", "yaw rotation", OFFSET(yaw), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f,TFLAGS, "yaw"}, + { "pitch", "pitch rotation", OFFSET(pitch), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f,TFLAGS, "pitch"}, + { "roll", "roll rotation", OFFSET(roll), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f,TFLAGS, "roll"}, + { "rorder", "rotation order", OFFSET(rorder), AV_OPT_TYPE_STRING, {.str="ypr"}, 0, 0,TFLAGS, "rorder"}, + { "h_fov", "output horizontal field of view",OFFSET(h_fov), AV_OPT_TYPE_FLOAT, {.dbl=90.f}, 0.00001f, 360.f,TFLAGS, "h_fov"}, + { "v_fov", "output vertical field of view", OFFSET(v_fov), AV_OPT_TYPE_FLOAT, {.dbl=45.f}, 0.00001f, 360.f,TFLAGS, "v_fov"}, + { "d_fov", "output diagonal field of view", OFFSET(d_fov), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 360.f,TFLAGS, "d_fov"}, + { "h_flip", "flip out video horizontally", OFFSET(h_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1,TFLAGS, "h_flip"}, + { "v_flip", "flip out video vertically", OFFSET(v_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1,TFLAGS, "v_flip"}, + { "d_flip", "flip out video indepth", OFFSET(d_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1,TFLAGS, "d_flip"}, + { "ih_flip", "flip in video horizontally", OFFSET(ih_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1,TFLAGS, "ih_flip"}, + { "iv_flip", "flip in video vertically", OFFSET(iv_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1,TFLAGS, "iv_flip"}, + { "in_trans", "transpose video input", OFFSET(in_transpose), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "in_transpose"}, + { "out_trans", "transpose video output", OFFSET(out_transpose), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "out_transpose"}, + { "ih_fov", "input horizontal field of view",OFFSET(ih_fov), AV_OPT_TYPE_FLOAT, {.dbl=90.f}, 0.00001f, 360.f,TFLAGS, "ih_fov"}, + { "iv_fov", "input vertical field of view", OFFSET(iv_fov), AV_OPT_TYPE_FLOAT, {.dbl=45.f}, 0.00001f, 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"}, + {"alpha_mask", "build mask in alpha plane", OFFSET(alpha), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "alpha"}, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(v360); + +static int query_formats(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + static const enum AVPixelFormat pix_fmts[] = { + // YUVA444 + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA444P16, + + // YUVA422 + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA422P9, + AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, + AV_PIX_FMT_YUVA422P16, + + // YUVA420 + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA420P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + + // YUVJ + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, + + // YUV444 + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16, + + // YUV440 + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV440P12, + + // YUV422 + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P9, + AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P12, + AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV422P16, + + // YUV420 + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV420P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV420P16, + + // YUV411 + AV_PIX_FMT_YUV411P, + + // YUV410 + AV_PIX_FMT_YUV410P, + + // GBR + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, + AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, + AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + + // GBRA + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, + AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + + // GRAY + 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 const enum AVPixelFormat alpha_pix_fmts[] = { + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA422P9, + AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, + AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA420P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, + AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *fmts_list = ff_make_format_list(s->alpha ? alpha_pix_fmts : pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +#define DEFINE_REMAP1_LINE(bits, div) \ +static void remap1_##bits##bit_line_c(uint8_t *dst, int width, const uint8_t *const src, \ + ptrdiff_t in_linesize, \ + const int16_t *const u, const int16_t *const v, \ + const int16_t *const ker) \ +{ \ + const uint##bits##_t *const s = (const uint##bits##_t *const)src; \ + uint##bits##_t *d = (uint##bits##_t *)dst; \ + \ + in_linesize /= div; \ + \ + for (int x = 0; x < width; x++) \ + d[x] = s[v[x] * in_linesize + u[x]]; \ +} + +DEFINE_REMAP1_LINE( 8, 1) +DEFINE_REMAP1_LINE(16, 2) + +/** + * Generate remapping function with a given window size and pixel depth. + * + * @param ws size of interpolation window + * @param bits number of bits per pixel + */ +#define DEFINE_REMAP(ws, bits) \ +static int remap##ws##_##bits##bit_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ +{ \ + ThreadData *td = arg; \ + const V360Context *s = ctx->priv; \ + const SliceXYRemap *r = &s->slice_remap[jobnr]; \ + const AVFrame *in = td->in; \ + AVFrame *out = td->out; \ + \ + for (int stereo = 0; stereo < 1 + s->out_stereo > STEREO_2D; stereo++) { \ + for (int plane = 0; plane < s->nb_planes; plane++) { \ + const unsigned map = s->map[plane]; \ + const int in_linesize = in->linesize[plane]; \ + const int out_linesize = out->linesize[plane]; \ + const int uv_linesize = s->uv_linesize[plane]; \ + const int in_offset_w = stereo ? s->in_offset_w[plane] : 0; \ + const int in_offset_h = stereo ? s->in_offset_h[plane] : 0; \ + const int out_offset_w = stereo ? s->out_offset_w[plane] : 0; \ + const int out_offset_h = stereo ? s->out_offset_h[plane] : 0; \ + const uint8_t *const src = in->data[plane] + \ + in_offset_h * in_linesize + in_offset_w * (bits >> 3); \ + uint8_t *dst = out->data[plane] + out_offset_h * out_linesize + out_offset_w * (bits >> 3); \ + const uint8_t *mask = plane == 3 ? r->mask : NULL; \ + const int width = s->pr_width[plane]; \ + const int height = s->pr_height[plane]; \ + \ + const int slice_start = (height * jobnr ) / nb_jobs; \ + const int slice_end = (height * (jobnr + 1)) / nb_jobs; \ + \ + for (int y = slice_start; y < slice_end && !mask; y++) { \ + const int16_t *const u = r->u[map] + (y - slice_start) * uv_linesize * ws * ws; \ + const int16_t *const v = r->v[map] + (y - slice_start) * uv_linesize * ws * ws; \ + const int16_t *const ker = r->ker[map] + (y - slice_start) * uv_linesize * ws * ws; \ + \ + s->remap_line(dst + y * out_linesize, width, src, in_linesize, u, v, ker); \ + } \ + \ + for (int y = slice_start; y < slice_end && mask; y++) { \ + memcpy(dst + y * out_linesize, mask + \ + (y - slice_start) * width * (bits >> 3), width * (bits >> 3)); \ + } \ + } \ + } \ + \ + return 0; \ +} + +DEFINE_REMAP(1, 8) +DEFINE_REMAP(2, 8) +DEFINE_REMAP(3, 8) +DEFINE_REMAP(4, 8) +DEFINE_REMAP(1, 16) +DEFINE_REMAP(2, 16) +DEFINE_REMAP(3, 16) +DEFINE_REMAP(4, 16) + +#define DEFINE_REMAP_LINE(ws, bits, div) \ +static void remap##ws##_##bits##bit_line_c(uint8_t *dst, int width, const uint8_t *const src, \ + ptrdiff_t in_linesize, \ + const int16_t *const u, const int16_t *const v, \ + const int16_t *const ker) \ +{ \ + const uint##bits##_t *const s = (const uint##bits##_t *const)src; \ + uint##bits##_t *d = (uint##bits##_t *)dst; \ + \ + in_linesize /= div; \ + \ + for (int x = 0; x < width; x++) { \ + const int16_t *const uu = u + x * ws * ws; \ + const int16_t *const vv = v + x * ws * ws; \ + const int16_t *const kker = ker + x * ws * ws; \ + int tmp = 0; \ + \ + for (int i = 0; i < ws; i++) { \ + const int iws = i * ws; \ + for (int j = 0; j < ws; j++) { \ + tmp += kker[iws + j] * s[vv[iws + j] * in_linesize + uu[iws + j]]; \ + } \ + } \ + \ + d[x] = av_clip_uint##bits(tmp >> 14); \ + } \ +} + +DEFINE_REMAP_LINE(2, 8, 1) +DEFINE_REMAP_LINE(3, 8, 1) +DEFINE_REMAP_LINE(4, 8, 1) +DEFINE_REMAP_LINE(2, 16, 2) +DEFINE_REMAP_LINE(3, 16, 2) +DEFINE_REMAP_LINE(4, 16, 2) + +void ff_v360_init(V360Context *s, int depth) +{ + switch (s->interp) { + case NEAREST: + s->remap_line = depth <= 8 ? remap1_8bit_line_c : remap1_16bit_line_c; + break; + case BILINEAR: + s->remap_line = depth <= 8 ? remap2_8bit_line_c : remap2_16bit_line_c; + break; + case LAGRANGE9: + s->remap_line = depth <= 8 ? remap3_8bit_line_c : remap3_16bit_line_c; + break; + case BICUBIC: + case LANCZOS: + case SPLINE16: + case GAUSSIAN: + case MITCHELL: + s->remap_line = depth <= 8 ? remap4_8bit_line_c : remap4_16bit_line_c; + break; + } + + if (ARCH_X86) + ff_v360_init_x86(s, depth); +} + +/** + * Save nearest pixel coordinates for remapping. + * + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + * @param rmap calculated 4x4 window + * @param u u remap data + * @param v v remap data + * @param ker ker remap data + */ +static void nearest_kernel(float du, float dv, const XYRemap *rmap, + int16_t *u, int16_t *v, int16_t *ker) +{ + const int i = lrintf(dv) + 1; + const int j = lrintf(du) + 1; + + u[0] = rmap->u[i][j]; + v[0] = rmap->v[i][j]; +} + +/** + * Calculate kernel for bilinear interpolation. + * + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + * @param rmap calculated 4x4 window + * @param u u remap data + * @param v v remap data + * @param ker ker remap data + */ +static void bilinear_kernel(float du, float dv, const XYRemap *rmap, + int16_t *u, int16_t *v, int16_t *ker) +{ + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + u[i * 2 + j] = rmap->u[i + 1][j + 1]; + v[i * 2 + j] = rmap->v[i + 1][j + 1]; + } + } + + ker[0] = lrintf((1.f - du) * (1.f - dv) * 16385.f); + ker[1] = lrintf( du * (1.f - dv) * 16385.f); + ker[2] = lrintf((1.f - du) * dv * 16385.f); + ker[3] = lrintf( du * dv * 16385.f); +} + +/** + * Calculate 1-dimensional lagrange coefficients. + * + * @param t relative coordinate + * @param coeffs coefficients + */ +static inline void calculate_lagrange_coeffs(float t, float *coeffs) +{ + coeffs[0] = (t - 1.f) * (t - 2.f) * 0.5f; + coeffs[1] = -t * (t - 2.f); + coeffs[2] = t * (t - 1.f) * 0.5f; +} + +/** + * Calculate kernel for lagrange interpolation. + * + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + * @param rmap calculated 4x4 window + * @param u u remap data + * @param v v remap data + * @param ker ker remap data + */ +static void lagrange_kernel(float du, float dv, const XYRemap *rmap, + int16_t *u, int16_t *v, int16_t *ker) +{ + float du_coeffs[3]; + float dv_coeffs[3]; + + calculate_lagrange_coeffs(du, du_coeffs); + calculate_lagrange_coeffs(dv, dv_coeffs); + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + u[i * 3 + j] = rmap->u[i + 1][j + 1]; + v[i * 3 + j] = rmap->v[i + 1][j + 1]; + ker[i * 3 + j] = lrintf(du_coeffs[j] * dv_coeffs[i] * 16385.f); + } + } +} + +/** + * Calculate 1-dimensional cubic coefficients. + * + * @param t relative coordinate + * @param coeffs coefficients + */ +static inline void calculate_bicubic_coeffs(float t, float *coeffs) +{ + const float tt = t * t; + const float ttt = t * t * t; + + coeffs[0] = - t / 3.f + tt / 2.f - ttt / 6.f; + coeffs[1] = 1.f - t / 2.f - tt + ttt / 2.f; + coeffs[2] = t + tt / 2.f - ttt / 2.f; + coeffs[3] = - t / 6.f + ttt / 6.f; +} + +/** + * Calculate kernel for bicubic interpolation. + * + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + * @param rmap calculated 4x4 window + * @param u u remap data + * @param v v remap data + * @param ker ker remap data + */ +static void bicubic_kernel(float du, float dv, const XYRemap *rmap, + int16_t *u, int16_t *v, int16_t *ker) +{ + float du_coeffs[4]; + float dv_coeffs[4]; + + calculate_bicubic_coeffs(du, du_coeffs); + calculate_bicubic_coeffs(dv, dv_coeffs); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + u[i * 4 + j] = rmap->u[i][j]; + v[i * 4 + j] = rmap->v[i][j]; + ker[i * 4 + j] = lrintf(du_coeffs[j] * dv_coeffs[i] * 16385.f); + } + } +} + +/** + * Calculate 1-dimensional lanczos coefficients. + * + * @param t relative coordinate + * @param coeffs coefficients + */ +static inline void calculate_lanczos_coeffs(float t, float *coeffs) +{ + float sum = 0.f; + + for (int i = 0; i < 4; i++) { + const float x = M_PI * (t - i + 1); + if (x == 0.f) { + coeffs[i] = 1.f; + } else { + coeffs[i] = sinf(x) * sinf(x / 2.f) / (x * x / 2.f); + } + sum += coeffs[i]; + } + + for (int i = 0; i < 4; i++) { + coeffs[i] /= sum; + } +} + +/** + * Calculate kernel for lanczos interpolation. + * + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + * @param rmap calculated 4x4 window + * @param u u remap data + * @param v v remap data + * @param ker ker remap data + */ +static void lanczos_kernel(float du, float dv, const XYRemap *rmap, + int16_t *u, int16_t *v, int16_t *ker) +{ + float du_coeffs[4]; + float dv_coeffs[4]; + + calculate_lanczos_coeffs(du, du_coeffs); + calculate_lanczos_coeffs(dv, dv_coeffs); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + u[i * 4 + j] = rmap->u[i][j]; + v[i * 4 + j] = rmap->v[i][j]; + ker[i * 4 + j] = lrintf(du_coeffs[j] * dv_coeffs[i] * 16385.f); + } + } +} + +/** + * Calculate 1-dimensional spline16 coefficients. + * + * @param t relative coordinate + * @param coeffs coefficients + */ +static void calculate_spline16_coeffs(float t, float *coeffs) +{ + coeffs[0] = ((-1.f / 3.f * t + 0.8f) * t - 7.f / 15.f) * t; + coeffs[1] = ((t - 9.f / 5.f) * t - 0.2f) * t + 1.f; + coeffs[2] = ((6.f / 5.f - t) * t + 0.8f) * t; + coeffs[3] = ((1.f / 3.f * t - 0.2f) * t - 2.f / 15.f) * t; +} + +/** + * Calculate kernel for spline16 interpolation. + * + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + * @param rmap calculated 4x4 window + * @param u u remap data + * @param v v remap data + * @param ker ker remap data + */ +static void spline16_kernel(float du, float dv, const XYRemap *rmap, + int16_t *u, int16_t *v, int16_t *ker) +{ + float du_coeffs[4]; + float dv_coeffs[4]; + + calculate_spline16_coeffs(du, du_coeffs); + calculate_spline16_coeffs(dv, dv_coeffs); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + u[i * 4 + j] = rmap->u[i][j]; + v[i * 4 + j] = rmap->v[i][j]; + ker[i * 4 + j] = lrintf(du_coeffs[j] * dv_coeffs[i] * 16385.f); + } + } +} + +/** + * Calculate 1-dimensional gaussian coefficients. + * + * @param t relative coordinate + * @param coeffs coefficients + */ +static void calculate_gaussian_coeffs(float t, float *coeffs) +{ + float sum = 0.f; + + for (int i = 0; i < 4; i++) { + const float x = t - (i - 1); + if (x == 0.f) { + coeffs[i] = 1.f; + } else { + coeffs[i] = expf(-2.f * x * x) * expf(-x * x / 2.f); + } + sum += coeffs[i]; + } + + for (int i = 0; i < 4; i++) { + coeffs[i] /= sum; + } +} + +/** + * Calculate kernel for gaussian interpolation. + * + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + * @param rmap calculated 4x4 window + * @param u u remap data + * @param v v remap data + * @param ker ker remap data + */ +static void gaussian_kernel(float du, float dv, const XYRemap *rmap, + int16_t *u, int16_t *v, int16_t *ker) +{ + float du_coeffs[4]; + float dv_coeffs[4]; + + calculate_gaussian_coeffs(du, du_coeffs); + calculate_gaussian_coeffs(dv, dv_coeffs); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + u[i * 4 + j] = rmap->u[i][j]; + v[i * 4 + j] = rmap->v[i][j]; + ker[i * 4 + j] = lrintf(du_coeffs[j] * dv_coeffs[i] * 16385.f); + } + } +} + +/** + * Calculate 1-dimensional cubic_bc_spline coefficients. + * + * @param t relative coordinate + * @param coeffs coefficients + */ +static void calculate_cubic_bc_coeffs(float t, float *coeffs, + float b, float c) +{ + float sum = 0.f; + float p0 = (6.f - 2.f * b) / 6.f, + p2 = (-18.f + 12.f * b + 6.f * c) / 6.f, + p3 = (12.f - 9.f * b - 6.f * c) / 6.f, + q0 = (8.f * b + 24.f * c) / 6.f, + q1 = (-12.f * b - 48.f * c) / 6.f, + q2 = (6.f * b + 30.f * c) / 6.f, + q3 = (-b - 6.f * c) / 6.f; + + for (int i = 0; i < 4; i++) { + const float x = fabsf(t - i + 1.f); + if (x < 1.f) { + coeffs[i] = (p0 + x * x * (p2 + x * p3)) * + (p0 + x * x * (p2 + x * p3 / 2.f) / 4.f); + } else if (x < 2.f) { + coeffs[i] = (q0 + x * (q1 + x * (q2 + x * q3))) * + (q0 + x * (q1 + x * (q2 + x / 2.f * q3) / 2.f) / 2.f); + } else { + coeffs[i] = 0.f; + } + sum += coeffs[i]; + } + + for (int i = 0; i < 4; i++) { + coeffs[i] /= sum; + } +} + +/** + * Calculate kernel for mitchell interpolation. + * + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + * @param rmap calculated 4x4 window + * @param u u remap data + * @param v v remap data + * @param ker ker remap data + */ +static void mitchell_kernel(float du, float dv, const XYRemap *rmap, + int16_t *u, int16_t *v, int16_t *ker) +{ + float du_coeffs[4]; + float dv_coeffs[4]; + + calculate_cubic_bc_coeffs(du, du_coeffs, 1.f / 3.f, 1.f / 3.f); + calculate_cubic_bc_coeffs(dv, dv_coeffs, 1.f / 3.f, 1.f / 3.f); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + u[i * 4 + j] = rmap->u[i][j]; + v[i * 4 + j] = rmap->v[i][j]; + ker[i * 4 + j] = lrintf(du_coeffs[j] * dv_coeffs[i] * 16385.f); + } + } +} + +/** + * Modulo operation with only positive remainders. + * + * @param a dividend + * @param b divisor + * + * @return positive remainder of (a / b) + */ +static inline int mod(int a, int b) +{ + const int res = a % b; + if (res < 0) { + return res + b; + } else { + return res; + } +} + +/** + * Reflect y operation. + * + * @param y input vertical position + * @param h input height + */ +static inline int reflecty(int y, int h) +{ + if (y < 0) { + y = -y; + } else if (y >= h) { + y = 2 * h - 1 - y; + } + + return av_clip(y, 0, h - 1); +} + +/** + * Reflect x operation for equirect. + * + * @param x input horizontal position + * @param y input vertical position + * @param w input width + * @param h input height + */ +static inline int ereflectx(int x, int y, int w, int h) +{ + if (y < 0 || y >= h) + x += w / 2; + + return mod(x, w); +} + +/** + * Reflect x operation. + * + * @param x input horizontal position + * @param y input vertical position + * @param w input width + * @param h input height + */ +static inline int reflectx(int x, int y, int w, int h) +{ + if (y < 0 || y >= h) + return w - 1 - x; + + return mod(x, w); +} + +/** + * Convert char to corresponding direction. + * Used for cubemap options. + */ +static int get_direction(char c) +{ + switch (c) { + case 'r': + return RIGHT; + case 'l': + return LEFT; + case 'u': + return UP; + case 'd': + return DOWN; + case 'f': + return FRONT; + case 'b': + return BACK; + default: + return -1; + } +} + +/** + * Convert char to corresponding rotation angle. + * Used for cubemap options. + */ +static int get_rotation(char c) +{ + switch (c) { + case '0': + return ROT_0; + case '1': + return ROT_90; + case '2': + return ROT_180; + case '3': + return ROT_270; + default: + return -1; + } +} + +/** + * Convert char to corresponding rotation order. + */ +static int get_rorder(char c) +{ + switch (c) { + case 'Y': + case 'y': + return YAW; + case 'P': + case 'p': + return PITCH; + case 'R': + case 'r': + return ROLL; + default: + return -1; + } +} + +/** + * Prepare data for processing cubemap input format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_cube_in(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + for (int face = 0; face < NB_FACES; face++) { + const char c = s->in_forder[face]; + int direction; + + if (c == '\0') { + av_log(ctx, AV_LOG_ERROR, + "Incomplete in_forder option. Direction for all 6 faces should be specified.\n"); + return AVERROR(EINVAL); + } + + direction = get_direction(c); + if (direction == -1) { + av_log(ctx, AV_LOG_ERROR, + "Incorrect direction symbol '%c' in in_forder option.\n", c); + return AVERROR(EINVAL); + } + + s->in_cubemap_face_order[direction] = face; + } + + for (int face = 0; face < NB_FACES; face++) { + const char c = s->in_frot[face]; + int rotation; + + if (c == '\0') { + av_log(ctx, AV_LOG_ERROR, + "Incomplete in_frot option. Rotation for all 6 faces should be specified.\n"); + return AVERROR(EINVAL); + } + + rotation = get_rotation(c); + if (rotation == -1) { + av_log(ctx, AV_LOG_ERROR, + "Incorrect rotation symbol '%c' in in_frot option.\n", c); + return AVERROR(EINVAL); + } + + s->in_cubemap_face_rotation[face] = rotation; + } + + return 0; +} + +/** + * Prepare data for processing cubemap output format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_cube_out(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + for (int face = 0; face < NB_FACES; face++) { + const char c = s->out_forder[face]; + int direction; + + if (c == '\0') { + av_log(ctx, AV_LOG_ERROR, + "Incomplete out_forder option. Direction for all 6 faces should be specified.\n"); + return AVERROR(EINVAL); + } + + direction = get_direction(c); + if (direction == -1) { + av_log(ctx, AV_LOG_ERROR, + "Incorrect direction symbol '%c' in out_forder option.\n", c); + return AVERROR(EINVAL); + } + + s->out_cubemap_direction_order[face] = direction; + } + + for (int face = 0; face < NB_FACES; face++) { + const char c = s->out_frot[face]; + int rotation; + + if (c == '\0') { + av_log(ctx, AV_LOG_ERROR, + "Incomplete out_frot option. Rotation for all 6 faces should be specified.\n"); + return AVERROR(EINVAL); + } + + rotation = get_rotation(c); + if (rotation == -1) { + av_log(ctx, AV_LOG_ERROR, + "Incorrect rotation symbol '%c' in out_frot option.\n", c); + return AVERROR(EINVAL); + } + + s->out_cubemap_face_rotation[face] = rotation; + } + + return 0; +} + +static inline void rotate_cube_face(float *uf, float *vf, int rotation) +{ + float tmp; + + switch (rotation) { + case ROT_0: + break; + case ROT_90: + tmp = *uf; + *uf = -*vf; + *vf = tmp; + break; + case ROT_180: + *uf = -*uf; + *vf = -*vf; + break; + case ROT_270: + tmp = -*uf; + *uf = *vf; + *vf = tmp; + break; + default: + av_assert0(0); + } +} + +static inline void rotate_cube_face_inverse(float *uf, float *vf, int rotation) +{ + float tmp; + + switch (rotation) { + case ROT_0: + break; + case ROT_90: + tmp = -*uf; + *uf = *vf; + *vf = tmp; + break; + case ROT_180: + *uf = -*uf; + *vf = -*vf; + break; + case ROT_270: + tmp = *uf; + *uf = -*vf; + *vf = tmp; + break; + default: + av_assert0(0); + } +} + +/** + * Normalize vector. + * + * @param vec vector + */ +static void normalize_vector(float *vec) +{ + const float norm = sqrtf(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]); + + vec[0] /= norm; + vec[1] /= norm; + vec[2] /= norm; +} + +/** + * Calculate 3D coordinates on sphere for corresponding cubemap position. + * Common operation for every cubemap. + * + * @param s filter private context + * @param uf horizontal cubemap coordinate [0, 1) + * @param vf vertical cubemap coordinate [0, 1) + * @param face face of cubemap + * @param vec coordinates on sphere + * @param scalew scale for uf + * @param scaleh scale for vf + */ +static void cube_to_xyz(const V360Context *s, + float uf, float vf, int face, + float *vec, float scalew, float scaleh) +{ + const int direction = s->out_cubemap_direction_order[face]; + float l_x, l_y, l_z; + + uf /= scalew; + vf /= scaleh; + + rotate_cube_face_inverse(&uf, &vf, s->out_cubemap_face_rotation[face]); + + switch (direction) { + case RIGHT: + l_x = 1.f; + l_y = vf; + l_z = -uf; + break; + case LEFT: + l_x = -1.f; + l_y = vf; + l_z = uf; + break; + case UP: + l_x = uf; + l_y = -1.f; + l_z = vf; + break; + case DOWN: + l_x = uf; + l_y = 1.f; + l_z = -vf; + break; + case FRONT: + l_x = uf; + l_y = vf; + l_z = 1.f; + break; + case BACK: + l_x = -uf; + l_y = vf; + l_z = -1.f; + break; + default: + av_assert0(0); + } + + vec[0] = l_x; + vec[1] = l_y; + vec[2] = l_z; + + normalize_vector(vec); +} + +/** + * Calculate cubemap position for corresponding 3D coordinates on sphere. + * Common operation for every cubemap. + * + * @param s filter private context + * @param vec coordinated on sphere + * @param uf horizontal cubemap coordinate [0, 1) + * @param vf vertical cubemap coordinate [0, 1) + * @param direction direction of view + */ +static void xyz_to_cube(const V360Context *s, + const float *vec, + float *uf, float *vf, int *direction) +{ + const float phi = atan2f(vec[0], vec[2]); + const float theta = asinf(vec[1]); + float phi_norm, theta_threshold; + int face; + + if (phi >= -M_PI_4 && phi < M_PI_4) { + *direction = FRONT; + phi_norm = phi; + } else if (phi >= -(M_PI_2 + M_PI_4) && phi < -M_PI_4) { + *direction = LEFT; + phi_norm = phi + M_PI_2; + } else if (phi >= M_PI_4 && phi < M_PI_2 + M_PI_4) { + *direction = RIGHT; + phi_norm = phi - M_PI_2; + } else { + *direction = BACK; + phi_norm = phi + ((phi > 0.f) ? -M_PI : M_PI); + } + + theta_threshold = atanf(cosf(phi_norm)); + if (theta > theta_threshold) { + *direction = DOWN; + } else if (theta < -theta_threshold) { + *direction = UP; + } + + switch (*direction) { + case RIGHT: + *uf = -vec[2] / vec[0]; + *vf = vec[1] / vec[0]; + break; + case LEFT: + *uf = -vec[2] / vec[0]; + *vf = -vec[1] / vec[0]; + break; + case UP: + *uf = -vec[0] / vec[1]; + *vf = -vec[2] / vec[1]; + break; + case DOWN: + *uf = vec[0] / vec[1]; + *vf = -vec[2] / vec[1]; + break; + case FRONT: + *uf = vec[0] / vec[2]; + *vf = vec[1] / vec[2]; + break; + case BACK: + *uf = vec[0] / vec[2]; + *vf = -vec[1] / vec[2]; + break; + default: + av_assert0(0); + } + + face = s->in_cubemap_face_order[*direction]; + rotate_cube_face(uf, vf, s->in_cubemap_face_rotation[face]); +} + +/** + * Find position on another cube face in case of overflow/underflow. + * Used for calculation of interpolation window. + * + * @param s filter private context + * @param uf horizontal cubemap coordinate + * @param vf vertical cubemap coordinate + * @param direction direction of view + * @param new_uf new horizontal cubemap coordinate + * @param new_vf new vertical cubemap coordinate + * @param face face position on cubemap + */ +static void process_cube_coordinates(const V360Context *s, + float uf, float vf, int direction, + float *new_uf, float *new_vf, int *face) +{ + /* + * Cubemap orientation + * + * width + * <-------> + * +-------+ + * | | U + * | up | h -------> + * +-------+-------+-------+-------+ ^ e | + * | | | | | | i V | + * | left | front | right | back | | g | + * +-------+-------+-------+-------+ v h v + * | | t + * | down | + * +-------+ + */ + + *face = s->in_cubemap_face_order[direction]; + rotate_cube_face_inverse(&uf, &vf, s->in_cubemap_face_rotation[*face]); + + if ((uf < -1.f || uf >= 1.f) && (vf < -1.f || vf >= 1.f)) { + // There are no pixels to use in this case + *new_uf = uf; + *new_vf = vf; + } else if (uf < -1.f) { + uf += 2.f; + switch (direction) { + case RIGHT: + direction = FRONT; + *new_uf = uf; + *new_vf = vf; + break; + case LEFT: + direction = BACK; + *new_uf = uf; + *new_vf = vf; + break; + case UP: + direction = LEFT; + *new_uf = vf; + *new_vf = -uf; + break; + case DOWN: + direction = LEFT; + *new_uf = -vf; + *new_vf = uf; + break; + case FRONT: + direction = LEFT; + *new_uf = uf; + *new_vf = vf; + break; + case BACK: + direction = RIGHT; + *new_uf = uf; + *new_vf = vf; + break; + default: + av_assert0(0); + } + } else if (uf >= 1.f) { + uf -= 2.f; + switch (direction) { + case RIGHT: + direction = BACK; + *new_uf = uf; + *new_vf = vf; + break; + case LEFT: + direction = FRONT; + *new_uf = uf; + *new_vf = vf; + break; + case UP: + direction = RIGHT; + *new_uf = -vf; + *new_vf = uf; + break; + case DOWN: + direction = RIGHT; + *new_uf = vf; + *new_vf = -uf; + break; + case FRONT: + direction = RIGHT; + *new_uf = uf; + *new_vf = vf; + break; + case BACK: + direction = LEFT; + *new_uf = uf; + *new_vf = vf; + break; + default: + av_assert0(0); + } + } else if (vf < -1.f) { + vf += 2.f; + switch (direction) { + case RIGHT: + direction = UP; + *new_uf = vf; + *new_vf = -uf; + break; + case LEFT: + direction = UP; + *new_uf = -vf; + *new_vf = uf; + break; + case UP: + direction = BACK; + *new_uf = -uf; + *new_vf = -vf; + break; + case DOWN: + direction = FRONT; + *new_uf = uf; + *new_vf = vf; + break; + case FRONT: + direction = UP; + *new_uf = uf; + *new_vf = vf; + break; + case BACK: + direction = UP; + *new_uf = -uf; + *new_vf = -vf; + break; + default: + av_assert0(0); + } + } else if (vf >= 1.f) { + vf -= 2.f; + switch (direction) { + case RIGHT: + direction = DOWN; + *new_uf = -vf; + *new_vf = uf; + break; + case LEFT: + direction = DOWN; + *new_uf = vf; + *new_vf = -uf; + break; + case UP: + direction = FRONT; + *new_uf = uf; + *new_vf = vf; + break; + case DOWN: + direction = BACK; + *new_uf = -uf; + *new_vf = -vf; + break; + case FRONT: + direction = DOWN; + *new_uf = uf; + *new_vf = vf; + break; + case BACK: + direction = DOWN; + *new_uf = -uf; + *new_vf = -vf; + break; + default: + av_assert0(0); + } + } else { + // Inside cube face + *new_uf = uf; + *new_vf = vf; + } + + *face = s->in_cubemap_face_order[direction]; + rotate_cube_face(new_uf, new_vf, s->in_cubemap_face_rotation[*face]); +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in cubemap3x2 format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int cube3x2_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float scalew = s->fout_pad > 0 ? 1.f - s->fout_pad / (width / 3.f) : 1.f - s->out_pad; + const float scaleh = s->fout_pad > 0 ? 1.f - s->fout_pad / (height / 2.f) : 1.f - s->out_pad; + + const float ew = width / 3.f; + const float eh = height / 2.f; + + const int u_face = floorf(i / ew); + const int v_face = floorf(j / eh); + const int face = u_face + 3 * v_face; + + const int u_shift = ceilf(ew * u_face); + const int v_shift = ceilf(eh * v_face); + const int ewi = ceilf(ew * (u_face + 1)) - u_shift; + const int ehi = ceilf(eh * (v_face + 1)) - v_shift; + + const float uf = 2.f * (i - u_shift + 0.5f) / ewi - 1.f; + const float vf = 2.f * (j - v_shift + 0.5f) / ehi - 1.f; + + cube_to_xyz(s, uf, vf, face, vec, scalew, scaleh); + + return 1; +} + +/** + * Calculate frame position in cubemap3x2 format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_cube3x2(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float scalew = s->fin_pad > 0 ? 1.f - s->fin_pad / (width / 3.f) : 1.f - s->in_pad; + const float scaleh = s->fin_pad > 0 ? 1.f - s->fin_pad / (height / 2.f) : 1.f - s->in_pad; + const float ew = width / 3.f; + const float eh = height / 2.f; + float uf, vf; + int ui, vi; + int ewi, ehi; + int direction, face; + int u_face, v_face; + + xyz_to_cube(s, vec, &uf, &vf, &direction); + + uf *= scalew; + vf *= scaleh; + + face = s->in_cubemap_face_order[direction]; + u_face = face % 3; + v_face = face / 3; + ewi = ceilf(ew * (u_face + 1)) - ceilf(ew * u_face); + ehi = ceilf(eh * (v_face + 1)) - ceilf(eh * v_face); + + uf = 0.5f * ewi * (uf + 1.f) - 0.5f; + vf = 0.5f * ehi * (vf + 1.f) - 0.5f; + + ui = floorf(uf); + vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + int new_ui = ui + j - 1; + int new_vi = vi + i - 1; + int u_shift, v_shift; + int new_ewi, new_ehi; + + if (new_ui >= 0 && new_ui < ewi && new_vi >= 0 && new_vi < ehi) { + face = s->in_cubemap_face_order[direction]; + + u_face = face % 3; + v_face = face / 3; + u_shift = ceilf(ew * u_face); + v_shift = ceilf(eh * v_face); + } else { + uf = 2.f * new_ui / ewi - 1.f; + vf = 2.f * new_vi / ehi - 1.f; + + uf /= scalew; + vf /= scaleh; + + process_cube_coordinates(s, uf, vf, direction, &uf, &vf, &face); + + uf *= scalew; + vf *= scaleh; + + u_face = face % 3; + v_face = face / 3; + u_shift = ceilf(ew * u_face); + v_shift = ceilf(eh * v_face); + new_ewi = ceilf(ew * (u_face + 1)) - u_shift; + new_ehi = ceilf(eh * (v_face + 1)) - v_shift; + + new_ui = av_clip(lrintf(0.5f * new_ewi * (uf + 1.f)), 0, new_ewi - 1); + new_vi = av_clip(lrintf(0.5f * new_ehi * (vf + 1.f)), 0, new_ehi - 1); + } + + us[i][j] = u_shift + new_ui; + vs[i][j] = v_shift + new_vi; + } + } + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in cubemap1x6 format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int cube1x6_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float scalew = s->fout_pad > 0 ? 1.f - (float)(s->fout_pad) / width : 1.f - s->out_pad; + const float scaleh = s->fout_pad > 0 ? 1.f - s->fout_pad / (height / 6.f) : 1.f - s->out_pad; + + const float ew = width; + const float eh = height / 6.f; + + const int face = floorf(j / eh); + + const int v_shift = ceilf(eh * face); + const int ehi = ceilf(eh * (face + 1)) - v_shift; + + const float uf = 2.f * (i + 0.5f) / ew - 1.f; + const float vf = 2.f * (j - v_shift + 0.5f) / ehi - 1.f; + + cube_to_xyz(s, uf, vf, face, vec, scalew, scaleh); + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in cubemap6x1 format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int cube6x1_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float scalew = s->fout_pad > 0 ? 1.f - s->fout_pad / (width / 6.f) : 1.f - s->out_pad; + const float scaleh = s->fout_pad > 0 ? 1.f - (float)(s->fout_pad) / height : 1.f - s->out_pad; + + const float ew = width / 6.f; + const float eh = height; + + const int face = floorf(i / ew); + + const int u_shift = ceilf(ew * face); + const int ewi = ceilf(ew * (face + 1)) - u_shift; + + const float uf = 2.f * (i - u_shift + 0.5f) / ewi - 1.f; + const float vf = 2.f * (j + 0.5f) / eh - 1.f; + + cube_to_xyz(s, uf, vf, face, vec, scalew, scaleh); + + return 1; +} + +/** + * Calculate frame position in cubemap1x6 format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_cube1x6(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float scalew = s->fin_pad > 0 ? 1.f - (float)(s->fin_pad) / width : 1.f - s->in_pad; + const float scaleh = s->fin_pad > 0 ? 1.f - s->fin_pad / (height / 6.f) : 1.f - s->in_pad; + const float eh = height / 6.f; + const int ewi = width; + float uf, vf; + int ui, vi; + int ehi; + int direction, face; + + xyz_to_cube(s, vec, &uf, &vf, &direction); + + uf *= scalew; + vf *= scaleh; + + face = s->in_cubemap_face_order[direction]; + ehi = ceilf(eh * (face + 1)) - ceilf(eh * face); + + uf = 0.5f * ewi * (uf + 1.f) - 0.5f; + vf = 0.5f * ehi * (vf + 1.f) - 0.5f; + + ui = floorf(uf); + vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + int new_ui = ui + j - 1; + int new_vi = vi + i - 1; + int v_shift; + int new_ehi; + + if (new_ui >= 0 && new_ui < ewi && new_vi >= 0 && new_vi < ehi) { + face = s->in_cubemap_face_order[direction]; + + v_shift = ceilf(eh * face); + } else { + uf = 2.f * new_ui / ewi - 1.f; + vf = 2.f * new_vi / ehi - 1.f; + + uf /= scalew; + vf /= scaleh; + + process_cube_coordinates(s, uf, vf, direction, &uf, &vf, &face); + + uf *= scalew; + vf *= scaleh; + + v_shift = ceilf(eh * face); + new_ehi = ceilf(eh * (face + 1)) - v_shift; + + new_ui = av_clip(lrintf(0.5f * ewi * (uf + 1.f)), 0, ewi - 1); + new_vi = av_clip(lrintf(0.5f * new_ehi * (vf + 1.f)), 0, new_ehi - 1); + } + + us[i][j] = new_ui; + vs[i][j] = v_shift + new_vi; + } + } + + return 1; +} + +/** + * Calculate frame position in cubemap6x1 format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_cube6x1(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float scalew = s->fin_pad > 0 ? 1.f - s->fin_pad / (width / 6.f) : 1.f - s->in_pad; + const float scaleh = s->fin_pad > 0 ? 1.f - (float)(s->fin_pad) / height : 1.f - s->in_pad; + const float ew = width / 6.f; + const int ehi = height; + float uf, vf; + int ui, vi; + int ewi; + int direction, face; + + xyz_to_cube(s, vec, &uf, &vf, &direction); + + uf *= scalew; + vf *= scaleh; + + face = s->in_cubemap_face_order[direction]; + ewi = ceilf(ew * (face + 1)) - ceilf(ew * face); + + uf = 0.5f * ewi * (uf + 1.f) - 0.5f; + vf = 0.5f * ehi * (vf + 1.f) - 0.5f; + + ui = floorf(uf); + vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + int new_ui = ui + j - 1; + int new_vi = vi + i - 1; + int u_shift; + int new_ewi; + + if (new_ui >= 0 && new_ui < ewi && new_vi >= 0 && new_vi < ehi) { + face = s->in_cubemap_face_order[direction]; + + u_shift = ceilf(ew * face); + } else { + uf = 2.f * new_ui / ewi - 1.f; + vf = 2.f * new_vi / ehi - 1.f; + + uf /= scalew; + vf /= scaleh; + + process_cube_coordinates(s, uf, vf, direction, &uf, &vf, &face); + + uf *= scalew; + vf *= scaleh; + + u_shift = ceilf(ew * face); + new_ewi = ceilf(ew * (face + 1)) - u_shift; + + new_ui = av_clip(lrintf(0.5f * new_ewi * (uf + 1.f)), 0, new_ewi - 1); + new_vi = av_clip(lrintf(0.5f * ehi * (vf + 1.f)), 0, ehi - 1); + } + + us[i][j] = u_shift + new_ui; + vs[i][j] = new_vi; + } + } + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in equirectangular format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int equirect_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float phi = ((2.f * i + 0.5f) / width - 1.f) * M_PI; + const float theta = ((2.f * j + 0.5f) / height - 1.f) * M_PI_2; + + const float sin_phi = sinf(phi); + const float cos_phi = cosf(phi); + const float sin_theta = sinf(theta); + const float cos_theta = cosf(theta); + + vec[0] = cos_theta * sin_phi; + vec[1] = sin_theta; + vec[2] = cos_theta * cos_phi; + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in half equirectangular format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int hequirect_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float phi = ((2.f * i + 0.5f) / width - 1.f) * M_PI_2; + const float theta = ((2.f * j + 0.5f) / height - 1.f) * M_PI_2; + + const float sin_phi = sinf(phi); + const float cos_phi = cosf(phi); + const float sin_theta = sinf(theta); + const float cos_theta = cosf(theta); + + vec[0] = cos_theta * sin_phi; + vec[1] = sin_theta; + vec[2] = cos_theta * cos_phi; + + return 1; +} + +/** + * Prepare data for processing stereographic output format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_stereographic_out(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->flat_range[0] = tanf(FFMIN(s->h_fov, 359.f) * M_PI / 720.f); + s->flat_range[1] = tanf(FFMIN(s->v_fov, 359.f) * M_PI / 720.f); + + return 0; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in stereographic format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int stereographic_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float x = ((2.f * i + 1.f) / width - 1.f) * s->flat_range[0]; + const float y = ((2.f * j + 1.f) / height - 1.f) * s->flat_range[1]; + const float r = hypotf(x, y); + const float theta = atanf(r) * 2.f; + const float sin_theta = sinf(theta); + + vec[0] = x / r * sin_theta; + vec[1] = y / r * sin_theta; + vec[2] = cosf(theta); + + normalize_vector(vec); + + return 1; +} + +/** + * Prepare data for processing stereographic input format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_stereographic_in(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->iflat_range[0] = tanf(FFMIN(s->ih_fov, 359.f) * M_PI / 720.f); + s->iflat_range[1] = tanf(FFMIN(s->iv_fov, 359.f) * M_PI / 720.f); + + return 0; +} + +/** + * Calculate frame position in stereographic format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_stereographic(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float theta = acosf(vec[2]); + const float r = tanf(theta * 0.5f); + const float c = r / hypotf(vec[0], vec[1]); + const float x = vec[0] * c / s->iflat_range[0]; + const float y = vec[1] * c / s->iflat_range[1]; + + const float uf = (x + 1.f) * width / 2.f; + const float vf = (y + 1.f) * height / 2.f; + + const int ui = floorf(uf); + const int vi = floorf(vf); + + const int visible = isfinite(x) && isfinite(y) && vi >= 0 && vi < height && ui >= 0 && ui < width; + + *du = visible ? uf - ui : 0.f; + *dv = visible ? vf - vi : 0.f; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = visible ? av_clip(ui + j - 1, 0, width - 1) : 0; + vs[i][j] = visible ? av_clip(vi + i - 1, 0, height - 1) : 0; + } + } + + return visible; +} + +/** + * Prepare data for processing equisolid output format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_equisolid_out(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->flat_range[0] = sinf(s->h_fov * M_PI / 720.f); + s->flat_range[1] = sinf(s->v_fov * M_PI / 720.f); + + return 0; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in equisolid format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int equisolid_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float x = ((2.f * i + 1.f) / width - 1.f) * s->flat_range[0]; + const float y = ((2.f * j + 1.f) / height - 1.f) * s->flat_range[1]; + const float r = hypotf(x, y); + const float theta = asinf(r) * 2.f; + const float sin_theta = sinf(theta); + + vec[0] = x / r * sin_theta; + vec[1] = y / r * sin_theta; + vec[2] = cosf(theta); + + normalize_vector(vec); + + return 1; +} + +/** + * Prepare data for processing equisolid input format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_equisolid_in(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->iflat_range[0] = sinf(FFMIN(s->ih_fov, 359.f) * M_PI / 720.f); + s->iflat_range[1] = sinf(FFMIN(s->iv_fov, 359.f) * M_PI / 720.f); + + return 0; +} + +/** + * Calculate frame position in equisolid format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_equisolid(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float theta = acosf(vec[2]); + const float r = sinf(theta * 0.5f); + const float c = r / hypotf(vec[0], vec[1]); + const float x = vec[0] * c / s->iflat_range[0]; + const float y = vec[1] * c / s->iflat_range[1]; + + const float uf = (x + 1.f) * width / 2.f; + const float vf = (y + 1.f) * height / 2.f; + + const int ui = floorf(uf); + const int vi = floorf(vf); + + const int visible = isfinite(x) && isfinite(y) && vi >= 0 && vi < height && ui >= 0 && ui < width; + + *du = visible ? uf - ui : 0.f; + *dv = visible ? vf - vi : 0.f; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = visible ? av_clip(ui + j - 1, 0, width - 1) : 0; + vs[i][j] = visible ? av_clip(vi + i - 1, 0, height - 1) : 0; + } + } + + return visible; +} + +/** + * Prepare data for processing orthographic output format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_orthographic_out(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->flat_range[0] = sinf(FFMIN(s->h_fov, 180.f) * M_PI / 360.f); + s->flat_range[1] = sinf(FFMIN(s->v_fov, 180.f) * M_PI / 360.f); + + return 0; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in orthographic format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int orthographic_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float x = ((2.f * i + 1.f) / width - 1.f) * s->flat_range[0]; + const float y = ((2.f * j + 1.f) / height - 1.f) * s->flat_range[1]; + const float r = hypotf(x, y); + const float theta = asinf(r); + + vec[0] = x; + vec[1] = y; + vec[2] = cosf(theta); + + normalize_vector(vec); + + return 1; +} + +/** + * Prepare data for processing orthographic input format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_orthographic_in(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->iflat_range[0] = sinf(FFMIN(s->ih_fov, 180.f) * M_PI / 360.f); + s->iflat_range[1] = sinf(FFMIN(s->iv_fov, 180.f) * M_PI / 360.f); + + return 0; +} + +/** + * Calculate frame position in orthographic format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_orthographic(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float theta = acosf(vec[2]); + const float r = sinf(theta); + const float c = r / hypotf(vec[0], vec[1]); + const float x = vec[0] * c / s->iflat_range[0]; + const float y = vec[1] * c / s->iflat_range[1]; + + const float uf = (x + 1.f) * width / 2.f; + const float vf = (y + 1.f) * height / 2.f; + + const int ui = floorf(uf); + const int vi = floorf(vf); + + const int visible = vec[2] >= 0.f && isfinite(x) && isfinite(y) && vi >= 0 && vi < height && ui >= 0 && ui < width; + + *du = visible ? uf - ui : 0.f; + *dv = visible ? vf - vi : 0.f; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = visible ? av_clip(ui + j - 1, 0, width - 1) : 0; + vs[i][j] = visible ? av_clip(vi + i - 1, 0, height - 1) : 0; + } + } + + return visible; +} + +/** + * Calculate frame position in equirectangular format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_equirect(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float phi = atan2f(vec[0], vec[2]); + const float theta = asinf(vec[1]); + + const float uf = (phi / M_PI + 1.f) * width / 2.f; + const float vf = (theta / M_PI_2 + 1.f) * height / 2.f; + + const int ui = floorf(uf); + const int vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = ereflectx(ui + j - 1, vi + i - 1, width, height); + vs[i][j] = reflecty(vi + i - 1, height); + } + } + + return 1; +} + +/** + * Calculate frame position in half equirectangular format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_hequirect(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float phi = atan2f(vec[0], vec[2]); + const float theta = asinf(vec[1]); + + const float uf = (phi / M_PI_2 + 1.f) * width / 2.f; + const float vf = (theta / M_PI_2 + 1.f) * height / 2.f; + + const int ui = floorf(uf); + const int vi = floorf(vf); + + const int visible = phi >= -M_PI_2 && phi <= M_PI_2; + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = av_clip(ui + j - 1, 0, width - 1); + vs[i][j] = av_clip(vi + i - 1, 0, height - 1); + } + } + + return visible; +} + +/** + * Prepare data for processing flat input format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_flat_in(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->iflat_range[0] = tanf(0.5f * s->ih_fov * M_PI / 180.f); + s->iflat_range[1] = tanf(0.5f * s->iv_fov * M_PI / 180.f); + + return 0; +} + +/** + * Calculate frame position in flat format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_flat(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float theta = acosf(vec[2]); + const float r = tanf(theta); + const float rr = fabsf(r) < 1e+6f ? r : hypotf(width, height); + const float zf = vec[2]; + const float h = hypotf(vec[0], vec[1]); + const float c = h <= 1e-6f ? 1.f : rr / h; + float uf = vec[0] * c / s->iflat_range[0]; + float vf = vec[1] * c / s->iflat_range[1]; + int visible, ui, vi; + + uf = zf >= 0.f ? (uf + 1.f) * width / 2.f : 0.f; + vf = zf >= 0.f ? (vf + 1.f) * height / 2.f : 0.f; + + ui = floorf(uf); + vi = floorf(vf); + + visible = vi >= 0 && vi < height && ui >= 0 && ui < width && zf >= 0.f; + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = visible ? av_clip(ui + j - 1, 0, width - 1) : 0; + vs[i][j] = visible ? av_clip(vi + i - 1, 0, height - 1) : 0; + } + } + + return visible; +} + +/** + * Calculate frame position in mercator format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_mercator(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float phi = atan2f(vec[0], vec[2]); + const float theta = vec[1]; + + const float uf = (phi / M_PI + 1.f) * width / 2.f; + const float vf = (av_clipf(logf((1.f + theta) / (1.f - theta)) / (2.f * M_PI), -1.f, 1.f) + 1.f) * height / 2.f; + + const int ui = floorf(uf); + const int vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = av_clip(ui + j - 1, 0, width - 1); + vs[i][j] = av_clip(vi + i - 1, 0, height - 1); + } + } + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in mercator format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int mercator_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float phi = ((2.f * i + 1.f) / width - 1.f) * M_PI + M_PI_2; + const float y = ((2.f * j + 1.f) / height - 1.f) * M_PI; + const float div = expf(2.f * y) + 1.f; + + const float sin_phi = sinf(phi); + const float cos_phi = cosf(phi); + const float sin_theta = 2.f * expf(y) / div; + const float cos_theta = (expf(2.f * y) - 1.f) / div; + + vec[0] = -sin_theta * cos_phi; + vec[1] = cos_theta; + vec[2] = sin_theta * sin_phi; + + return 1; +} + +/** + * Calculate frame position in ball format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_ball(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float l = hypotf(vec[0], vec[1]); + const float r = sqrtf(1.f - vec[2]) / M_SQRT2; + + const float uf = (1.f + r * vec[0] / (l > 0.f ? l : 1.f)) * width * 0.5f; + const float vf = (1.f + r * vec[1] / (l > 0.f ? l : 1.f)) * height * 0.5f; + + const int ui = floorf(uf); + const int vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = av_clip(ui + j - 1, 0, width - 1); + vs[i][j] = av_clip(vi + i - 1, 0, height - 1); + } + } + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in ball format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int ball_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float x = (2.f * i + 1.f) / width - 1.f; + const float y = (2.f * j + 1.f) / height - 1.f; + const float l = hypotf(x, y); + + if (l <= 1.f) { + const float z = 2.f * l * sqrtf(1.f - l * l); + + vec[0] = z * x / (l > 0.f ? l : 1.f); + vec[1] = z * y / (l > 0.f ? l : 1.f); + vec[2] = 1.f - 2.f * l * l; + } else { + vec[0] = 0.f; + vec[1] = 1.f; + vec[2] = 0.f; + return 0; + } + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in hammer format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int hammer_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float x = ((2.f * i + 1.f) / width - 1.f); + const float y = ((2.f * j + 1.f) / height - 1.f); + + const float xx = x * x; + const float yy = y * y; + + const float z = sqrtf(1.f - xx * 0.5f - yy * 0.5f); + + const float a = M_SQRT2 * x * z; + const float b = 2.f * z * z - 1.f; + + const float aa = a * a; + const float bb = b * b; + + const float w = sqrtf(1.f - 2.f * yy * z * z); + + vec[0] = w * 2.f * a * b / (aa + bb); + vec[1] = M_SQRT2 * y * z; + vec[2] = w * (bb - aa) / (aa + bb); + + normalize_vector(vec); + + return 1; +} + +/** + * Calculate frame position in hammer format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_hammer(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float theta = atan2f(vec[0], vec[2]); + + const float z = sqrtf(1.f + sqrtf(1.f - vec[1] * vec[1]) * cosf(theta * 0.5f)); + const float x = sqrtf(1.f - vec[1] * vec[1]) * sinf(theta * 0.5f) / z; + const float y = vec[1] / z; + + const float uf = (x + 1.f) * width / 2.f; + const float vf = (y + 1.f) * height / 2.f; + + const int ui = floorf(uf); + const int vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = av_clip(ui + j - 1, 0, width - 1); + vs[i][j] = av_clip(vi + i - 1, 0, height - 1); + } + } + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in sinusoidal format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int sinusoidal_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float theta = ((2.f * j + 1.f) / height - 1.f) * M_PI_2; + const float phi = ((2.f * i + 1.f) / width - 1.f) * M_PI / cosf(theta); + + const float sin_phi = sinf(phi); + const float cos_phi = cosf(phi); + const float sin_theta = sinf(theta); + const float cos_theta = cosf(theta); + + vec[0] = cos_theta * sin_phi; + vec[1] = sin_theta; + vec[2] = cos_theta * cos_phi; + + normalize_vector(vec); + + return 1; +} + +/** + * Calculate frame position in sinusoidal format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_sinusoidal(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float theta = asinf(vec[1]); + const float phi = atan2f(vec[0], vec[2]) * cosf(theta); + + const float uf = (phi / M_PI + 1.f) * width / 2.f; + const float vf = (theta / M_PI_2 + 1.f) * height / 2.f; + + const int ui = floorf(uf); + const int vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = av_clip(ui + j - 1, 0, width - 1); + vs[i][j] = av_clip(vi + i - 1, 0, height - 1); + } + } + + return 1; +} + +/** + * Prepare data for processing equi-angular cubemap input format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_eac_in(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->in_cubemap_face_order[RIGHT] = TOP_RIGHT; + s->in_cubemap_face_order[LEFT] = TOP_LEFT; + s->in_cubemap_face_order[UP] = BOTTOM_RIGHT; + s->in_cubemap_face_order[DOWN] = BOTTOM_LEFT; + s->in_cubemap_face_order[FRONT] = TOP_MIDDLE; + s->in_cubemap_face_order[BACK] = BOTTOM_MIDDLE; + + s->in_cubemap_face_rotation[TOP_LEFT] = ROT_0; + s->in_cubemap_face_rotation[TOP_MIDDLE] = ROT_0; + s->in_cubemap_face_rotation[TOP_RIGHT] = ROT_0; + s->in_cubemap_face_rotation[BOTTOM_LEFT] = ROT_270; + s->in_cubemap_face_rotation[BOTTOM_MIDDLE] = ROT_90; + s->in_cubemap_face_rotation[BOTTOM_RIGHT] = ROT_270; + + return 0; +} + +/** + * Prepare data for processing equi-angular cubemap output format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_eac_out(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->out_cubemap_direction_order[TOP_LEFT] = LEFT; + s->out_cubemap_direction_order[TOP_MIDDLE] = FRONT; + s->out_cubemap_direction_order[TOP_RIGHT] = RIGHT; + s->out_cubemap_direction_order[BOTTOM_LEFT] = DOWN; + s->out_cubemap_direction_order[BOTTOM_MIDDLE] = BACK; + s->out_cubemap_direction_order[BOTTOM_RIGHT] = UP; + + s->out_cubemap_face_rotation[TOP_LEFT] = ROT_0; + s->out_cubemap_face_rotation[TOP_MIDDLE] = ROT_0; + s->out_cubemap_face_rotation[TOP_RIGHT] = ROT_0; + s->out_cubemap_face_rotation[BOTTOM_LEFT] = ROT_270; + s->out_cubemap_face_rotation[BOTTOM_MIDDLE] = ROT_90; + s->out_cubemap_face_rotation[BOTTOM_RIGHT] = ROT_270; + + return 0; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in equi-angular cubemap format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int eac_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float pixel_pad = 2; + const float u_pad = pixel_pad / width; + const float v_pad = pixel_pad / height; + + int u_face, v_face, face; + + float l_x, l_y, l_z; + + float uf = (i + 0.5f) / width; + float vf = (j + 0.5f) / height; + + // EAC has 2-pixel padding on faces except between faces on the same row + // Padding pixels seems not to be stretched with tangent as regular pixels + // Formulas below approximate original padding as close as I could get experimentally + + // Horizontal padding + uf = 3.f * (uf - u_pad) / (1.f - 2.f * u_pad); + if (uf < 0.f) { + u_face = 0; + uf -= 0.5f; + } else if (uf >= 3.f) { + u_face = 2; + uf -= 2.5f; + } else { + u_face = floorf(uf); + uf = fmodf(uf, 1.f) - 0.5f; + } + + // Vertical padding + v_face = floorf(vf * 2.f); + vf = (vf - v_pad - 0.5f * v_face) / (0.5f - 2.f * v_pad) - 0.5f; + + if (uf >= -0.5f && uf < 0.5f) { + uf = tanf(M_PI_2 * uf); + } else { + uf = 2.f * uf; + } + if (vf >= -0.5f && vf < 0.5f) { + vf = tanf(M_PI_2 * vf); + } else { + vf = 2.f * vf; + } + + face = u_face + 3 * v_face; + + switch (face) { + case TOP_LEFT: + l_x = -1.f; + l_y = vf; + l_z = uf; + break; + case TOP_MIDDLE: + l_x = uf; + l_y = vf; + l_z = 1.f; + break; + case TOP_RIGHT: + l_x = 1.f; + l_y = vf; + l_z = -uf; + break; + case BOTTOM_LEFT: + l_x = -vf; + l_y = 1.f; + l_z = -uf; + break; + case BOTTOM_MIDDLE: + l_x = -vf; + l_y = -uf; + l_z = -1.f; + break; + case BOTTOM_RIGHT: + l_x = -vf; + l_y = -1.f; + l_z = uf; + break; + default: + av_assert0(0); + } + + vec[0] = l_x; + vec[1] = l_y; + vec[2] = l_z; + + normalize_vector(vec); + + return 1; +} + +/** + * Calculate frame position in equi-angular cubemap format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_eac(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float pixel_pad = 2; + const float u_pad = pixel_pad / width; + const float v_pad = pixel_pad / height; + + float uf, vf; + int ui, vi; + int direction, face; + int u_face, v_face; + + xyz_to_cube(s, vec, &uf, &vf, &direction); + + face = s->in_cubemap_face_order[direction]; + u_face = face % 3; + v_face = face / 3; + + uf = M_2_PI * atanf(uf) + 0.5f; + vf = M_2_PI * atanf(vf) + 0.5f; + + // These formulas are inversed from eac_to_xyz ones + uf = (uf + u_face) * (1.f - 2.f * u_pad) / 3.f + u_pad; + vf = vf * (0.5f - 2.f * v_pad) + v_pad + 0.5f * v_face; + + uf *= width; + vf *= height; + + uf -= 0.5f; + vf -= 0.5f; + + ui = floorf(uf); + vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = av_clip(ui + j - 1, 0, width - 1); + vs[i][j] = av_clip(vi + i - 1, 0, height - 1); + } + } + + return 1; +} + +/** + * Prepare data for processing flat output format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_flat_out(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->flat_range[0] = tanf(0.5f * s->h_fov * M_PI / 180.f); + s->flat_range[1] = tanf(0.5f * s->v_fov * M_PI / 180.f); + + return 0; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in flat format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int flat_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float l_x = s->flat_range[0] * ((2.f * i + 0.5f) / width - 1.f); + const float l_y = s->flat_range[1] * ((2.f * j + 0.5f) / height - 1.f); + + vec[0] = l_x; + vec[1] = l_y; + vec[2] = 1.f; + + normalize_vector(vec); + + return 1; +} + +/** + * Prepare data for processing fisheye output format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_fisheye_out(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->flat_range[0] = s->h_fov / 180.f; + s->flat_range[1] = s->v_fov / 180.f; + + return 0; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in fisheye format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int fisheye_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float uf = s->flat_range[0] * ((2.f * i) / width - 1.f); + const float vf = s->flat_range[1] * ((2.f * j + 1.f) / height - 1.f); + + const float phi = atan2f(vf, uf); + const float theta = M_PI_2 * (1.f - hypotf(uf, vf)); + + const float sin_phi = sinf(phi); + const float cos_phi = cosf(phi); + const float sin_theta = sinf(theta); + const float cos_theta = cosf(theta); + + vec[0] = cos_theta * cos_phi; + vec[1] = cos_theta * sin_phi; + vec[2] = sin_theta; + + normalize_vector(vec); + + return 1; +} + +/** + * Prepare data for processing fisheye input format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_fisheye_in(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->iflat_range[0] = s->ih_fov / 180.f; + s->iflat_range[1] = s->iv_fov / 180.f; + + return 0; +} + +/** + * Calculate frame position in fisheye format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_fisheye(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float h = hypotf(vec[0], vec[1]); + const float lh = h > 0.f ? h : 1.f; + const float phi = atan2f(h, vec[2]) / M_PI; + + float uf = vec[0] / lh * phi / s->iflat_range[0]; + float vf = vec[1] / lh * phi / s->iflat_range[1]; + + const int visible = hypotf(uf, vf) <= 0.5f; + int ui, vi; + + uf = (uf + 0.5f) * width; + vf = (vf + 0.5f) * height; + + ui = floorf(uf); + vi = floorf(vf); + + *du = visible ? uf - ui : 0.f; + *dv = visible ? vf - vi : 0.f; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = visible ? av_clip(ui + j - 1, 0, width - 1) : 0; + vs[i][j] = visible ? av_clip(vi + i - 1, 0, height - 1) : 0; + } + } + + return visible; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in pannini format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int pannini_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float uf = ((2.f * i + 1.f) / width - 1.f); + const float vf = ((2.f * j + 1.f) / height - 1.f); + + const float d = s->h_fov; + const float k = uf * uf / ((d + 1.f) * (d + 1.f)); + const float dscr = k * k * d * d - (k + 1.f) * (k * d * d - 1.f); + const float clon = (-k * d + sqrtf(dscr)) / (k + 1.f); + const float S = (d + 1.f) / (d + clon); + const float lon = atan2f(uf, S * clon); + const float lat = atan2f(vf, S); + + vec[0] = sinf(lon) * cosf(lat); + vec[1] = sinf(lat); + vec[2] = cosf(lon) * cosf(lat); + + normalize_vector(vec); + + return 1; +} + +/** + * Calculate frame position in pannini format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_pannini(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float phi = atan2f(vec[0], vec[2]); + const float theta = asinf(vec[1]); + + const float d = s->ih_fov; + const float S = (d + 1.f) / (d + cosf(phi)); + + const float x = S * sinf(phi); + const float y = S * tanf(theta); + + const float uf = (x + 1.f) * width / 2.f; + const float vf = (y + 1.f) * height / 2.f; + + const int ui = floorf(uf); + const int vi = floorf(vf); + + const int visible = vi >= 0 && vi < height && ui >= 0 && ui < width && vec[2] >= 0.f; + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = visible ? av_clip(ui + j - 1, 0, width - 1) : 0; + vs[i][j] = visible ? av_clip(vi + i - 1, 0, height - 1) : 0; + } + } + + return visible; +} + +/** + * Prepare data for processing cylindrical output format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_cylindrical_out(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->flat_range[0] = M_PI * s->h_fov / 360.f; + s->flat_range[1] = tanf(0.5f * s->v_fov * M_PI / 180.f); + + return 0; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in cylindrical format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int cylindrical_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float uf = s->flat_range[0] * ((2.f * i + 1.f) / width - 1.f); + const float vf = s->flat_range[1] * ((2.f * j + 1.f) / height - 1.f); + + const float phi = uf; + const float theta = atanf(vf); + + const float sin_phi = sinf(phi); + const float cos_phi = cosf(phi); + const float sin_theta = sinf(theta); + const float cos_theta = cosf(theta); + + vec[0] = cos_theta * sin_phi; + vec[1] = sin_theta; + vec[2] = cos_theta * cos_phi; + + normalize_vector(vec); + + return 1; +} + +/** + * Prepare data for processing cylindrical input format. + * + * @param ctx filter context + * + * @return error code + */ +static int prepare_cylindrical_in(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->iflat_range[0] = M_PI * s->ih_fov / 360.f; + s->iflat_range[1] = tanf(0.5f * s->iv_fov * M_PI / 180.f); + + return 0; +} + +/** + * Calculate frame position in cylindrical format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_cylindrical(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float phi = atan2f(vec[0], vec[2]) / s->iflat_range[0]; + const float theta = asinf(vec[1]); + + const float uf = (phi + 1.f) * (width - 1) / 2.f; + const float vf = (tanf(theta) / s->iflat_range[1] + 1.f) * height / 2.f; + + const int ui = floorf(uf); + const int vi = floorf(vf); + + const int visible = vi >= 0 && vi < height && ui >= 0 && ui < width && + theta <= M_PI * s->iv_fov / 180.f && + theta >= -M_PI * s->iv_fov / 180.f; + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = visible ? av_clip(ui + j - 1, 0, width - 1) : 0; + vs[i][j] = visible ? av_clip(vi + i - 1, 0, height - 1) : 0; + } + } + + return visible; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in perspective format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int perspective_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float uf = ((2.f * i + 1.f) / width - 1.f); + const float vf = ((2.f * j + 1.f) / height - 1.f); + const float rh = hypotf(uf, vf); + const float sinzz = 1.f - rh * rh; + const float h = 1.f + s->v_fov; + const float sinz = (h - sqrtf(sinzz)) / (h / rh + rh / h); + const float sinz2 = sinz * sinz; + + if (sinz2 <= 1.f) { + const float cosz = sqrtf(1.f - sinz2); + + const float theta = asinf(cosz); + const float phi = atan2f(uf, vf); + + const float sin_phi = sinf(phi); + const float cos_phi = cosf(phi); + const float sin_theta = sinf(theta); + const float cos_theta = cosf(theta); + + vec[0] = cos_theta * sin_phi; + vec[1] = cos_theta * cos_phi; + vec[2] = sin_theta; + } else { + vec[0] = 0.f; + vec[1] = 1.f; + vec[2] = 0.f; + return 0; + } + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in tetrahedron format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int tetrahedron_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float uf = (float)i / width; + const float vf = (float)j / height; + + vec[0] = uf < 0.5f ? uf * 4.f - 1.f : 3.f - uf * 4.f; + 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; +} + +/** + * Calculate frame position in tetrahedron format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_tetrahedron(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float d0 = vec[0] * 1.f + vec[1] * 1.f + vec[2] *-1.f; + const float d1 = vec[0] *-1.f + vec[1] *-1.f + vec[2] *-1.f; + const float d2 = vec[0] * 1.f + vec[1] *-1.f + vec[2] * 1.f; + const float d3 = vec[0] *-1.f + vec[1] * 1.f + vec[2] * 1.f; + const float d = FFMAX(d0, FFMAX3(d1, d2, d3)); + + float uf, vf, x, y, z; + int ui, vi; + + x = vec[0] / d; + y = vec[1] / d; + z = -vec[2] / d; + + vf = 0.5f - y * 0.5f; + + if ((x + y >= 0.f && y + z >= 0.f && -z - x <= 0.f) || + (x + y <= 0.f && -y + z >= 0.f && z - x >= 0.f)) { + uf = 0.25f * x + 0.25f; + } else { + uf = 0.75f - 0.25f * x; + } + + uf *= width; + vf *= height; + + ui = floorf(uf); + vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = reflectx(ui + j - 1, vi + i - 1, width, height); + vs[i][j] = reflecty(vi + i - 1, height); + } + } + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in dual fisheye format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int dfisheye_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float ew = width / 2.f; + const float eh = height; + + const int ei = i >= ew ? i - ew : i; + const float m = i >= ew ? 1.f : -1.f; + + const float uf = s->flat_range[0] * ((2.f * ei) / ew - 1.f); + const float vf = s->flat_range[1] * ((2.f * j + 1.f) / eh - 1.f); + + const float h = hypotf(uf, vf); + const float lh = h > 0.f ? h : 1.f; + const float theta = m * M_PI_2 * (1.f - h); + + const float sin_theta = sinf(theta); + const float cos_theta = cosf(theta); + + vec[0] = cos_theta * m * uf / lh; + vec[1] = cos_theta * vf / lh; + vec[2] = sin_theta; + + normalize_vector(vec); + + return 1; +} + +/** + * Calculate frame position in dual fisheye format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_dfisheye(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float ew = width / 2.f; + const float eh = height; + + const float h = hypotf(vec[0], vec[1]); + const float lh = h > 0.f ? h : 1.f; + const float theta = acosf(fabsf(vec[2])) / M_PI; + + float uf = (theta * (vec[0] / lh) / s->iflat_range[0] + 0.5f) * ew; + float vf = (theta * (vec[1] / lh) / s->iflat_range[1] + 0.5f) * eh; + + int ui, vi; + int u_shift; + + if (vec[2] >= 0.f) { + u_shift = ceilf(ew); + } else { + u_shift = 0; + uf = ew - uf; + } + + ui = floorf(uf); + vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = av_clip(u_shift + ui + j - 1, 0, width - 1); + vs[i][j] = av_clip( vi + i - 1, 0, height - 1); + } + } + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in barrel facebook's format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int barrel_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float scale = 0.99f; + float l_x, l_y, l_z; + + if (i < 4 * width / 5) { + const float theta_range = M_PI_4; + + const int ew = 4 * width / 5; + const int eh = height; + + const float phi = ((2.f * i) / ew - 1.f) * M_PI / scale; + const float theta = ((2.f * j) / eh - 1.f) * theta_range / scale; + + const float sin_phi = sinf(phi); + const float cos_phi = cosf(phi); + const float sin_theta = sinf(theta); + const float cos_theta = cosf(theta); + + l_x = cos_theta * sin_phi; + l_y = sin_theta; + l_z = cos_theta * cos_phi; + } else { + const int ew = width / 5; + const int eh = height / 2; + + float uf, vf; + + if (j < eh) { // UP + uf = 2.f * (i - 4 * ew) / ew - 1.f; + vf = 2.f * (j ) / eh - 1.f; + + uf /= scale; + vf /= scale; + + l_x = uf; + l_y = -1.f; + l_z = vf; + } else { // DOWN + uf = 2.f * (i - 4 * ew) / ew - 1.f; + vf = 2.f * (j - eh) / eh - 1.f; + + uf /= scale; + vf /= scale; + + l_x = uf; + l_y = 1.f; + l_z = -vf; + } + } + + vec[0] = l_x; + vec[1] = l_y; + vec[2] = l_z; + + normalize_vector(vec); + + return 1; +} + +/** + * Calculate frame position in barrel facebook's format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_barrel(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float scale = 0.99f; + + const float phi = atan2f(vec[0], vec[2]); + const float theta = asinf(vec[1]); + const float theta_range = M_PI_4; + + int ew, eh; + int u_shift, v_shift; + float uf, vf; + int ui, vi; + + if (theta > -theta_range && theta < theta_range) { + ew = 4 * width / 5; + eh = height; + + u_shift = 0; + v_shift = 0; + + uf = (phi / M_PI * scale + 1.f) * ew / 2.f; + vf = (theta / theta_range * scale + 1.f) * eh / 2.f; + } else { + ew = width / 5; + eh = height / 2; + + u_shift = 4 * ew; + + if (theta < 0.f) { // UP + uf = -vec[0] / vec[1]; + vf = -vec[2] / vec[1]; + v_shift = 0; + } else { // DOWN + uf = vec[0] / vec[1]; + vf = -vec[2] / vec[1]; + v_shift = eh; + } + + uf = 0.5f * ew * (uf * scale + 1.f); + vf = 0.5f * eh * (vf * scale + 1.f); + } + + ui = floorf(uf); + vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = u_shift + av_clip(ui + j - 1, 0, ew - 1); + vs[i][j] = v_shift + av_clip(vi + i - 1, 0, eh - 1); + } + } + + return 1; +} + +/** + * Calculate frame position in barrel split facebook's format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_barrelsplit(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + const float phi = atan2f(vec[0], vec[2]); + const float theta = asinf(vec[1]); + + const float theta_range = M_PI_4; + + int ew, eh; + int u_shift, v_shift; + float uf, vf; + int ui, vi; + + if (theta >= -theta_range && theta <= theta_range) { + const float scalew = s->fin_pad > 0 ? 1.f - s->fin_pad / (width * 2.f / 3.f) : 1.f - s->in_pad; + const float scaleh = s->fin_pad > 0 ? 1.f - s->fin_pad / (height / 2.f) : 1.f - s->in_pad; + + ew = width / 3 * 2; + eh = height / 2; + + u_shift = 0; + v_shift = phi >= M_PI_2 || phi < -M_PI_2 ? eh : 0; + + uf = fmodf(phi, M_PI_2) / M_PI_2; + vf = theta / M_PI_4; + + if (v_shift) + uf = uf >= 0.f ? fmodf(uf - 1.f, 1.f) : fmodf(uf + 1.f, 1.f); + + uf = (uf * scalew + 1.f) * width / 3.f; + vf = (vf * scaleh + 1.f) * height / 4.f; + } else { + const float scalew = s->fin_pad > 0 ? 1.f - s->fin_pad / (width / 3.f) : 1.f - s->in_pad; + const float scaleh = s->fin_pad > 0 ? 1.f - s->fin_pad / (height / 4.f) : 1.f - s->in_pad; + int v_offset = 0; + + ew = width / 3; + eh = height / 4; + + u_shift = 2 * ew; + + if (theta <= 0.f && theta >= -M_PI_2 && + phi <= M_PI_2 && phi >= -M_PI_2) { + uf = -vec[0] / vec[1]; + vf = -vec[2] / vec[1]; + v_shift = 0; + v_offset = -eh; + } else if (theta >= 0.f && theta <= M_PI_2 && + phi <= M_PI_2 && phi >= -M_PI_2) { + uf = vec[0] / vec[1]; + vf = -vec[2] / vec[1]; + v_shift = height * 0.25f; + } else if (theta <= 0.f && theta >= -M_PI_2) { + uf = vec[0] / vec[1]; + vf = vec[2] / vec[1]; + v_shift = height * 0.5f; + v_offset = -eh; + } else { + uf = -vec[0] / vec[1]; + vf = vec[2] / vec[1]; + v_shift = height * 0.75f; + } + + uf = 0.5f * width / 3.f * (uf * scalew + 1.f); + vf = height * 0.25f * (vf * scaleh + 1.f) + v_offset; + } + + ui = floorf(uf); + vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = u_shift + av_clip(ui + j - 1, 0, ew - 1); + vs[i][j] = v_shift + av_clip(vi + i - 1, 0, eh - 1); + } + } + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in barrel split facebook's format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int barrelsplit_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float x = (i + 0.5f) / width; + const float y = (j + 0.5f) / height; + float l_x, l_y, l_z; + + if (x < 2.f / 3.f) { + const float scalew = s->fout_pad > 0 ? 1.f - s->fout_pad / (width * 2.f / 3.f) : 1.f - s->out_pad; + const float scaleh = s->fout_pad > 0 ? 1.f - s->fout_pad / (height / 2.f) : 1.f - s->out_pad; + + const float back = floorf(y * 2.f); + + const float phi = ((3.f / 2.f * x - 0.5f) / scalew - back) * M_PI; + const float theta = (y - 0.25f - 0.5f * back) / scaleh * M_PI; + + const float sin_phi = sinf(phi); + const float cos_phi = cosf(phi); + const float sin_theta = sinf(theta); + const float cos_theta = cosf(theta); + + l_x = cos_theta * sin_phi; + l_y = sin_theta; + l_z = cos_theta * cos_phi; + } else { + const float scalew = s->fout_pad > 0 ? 1.f - s->fout_pad / (width / 3.f) : 1.f - s->out_pad; + const float scaleh = s->fout_pad > 0 ? 1.f - s->fout_pad / (height / 4.f) : 1.f - s->out_pad; + + const int face = floorf(y * 4.f); + float uf, vf; + + uf = x * 3.f - 2.f; + + switch (face) { + case 0: + vf = y * 2.f; + uf = 1.f - uf; + vf = 0.5f - vf; + + l_x = (0.5f - uf) / scalew; + l_y = -0.5f; + l_z = (0.5f - vf) / scaleh; + break; + case 1: + vf = y * 2.f; + uf = 1.f - uf; + vf = 1.f - (vf - 0.5f); + + l_x = (0.5f - uf) / scalew; + l_y = 0.5f; + l_z = (-0.5f + vf) / scaleh; + break; + case 2: + vf = y * 2.f - 0.5f; + vf = 1.f - (1.f - vf); + + l_x = (0.5f - uf) / scalew; + l_y = -0.5f; + l_z = (0.5f - vf) / scaleh; + break; + case 3: + vf = y * 2.f - 1.5f; + + l_x = (0.5f - uf) / scalew; + l_y = 0.5f; + l_z = (-0.5f + vf) / scaleh; + break; + } + } + + vec[0] = l_x; + vec[1] = l_y; + vec[2] = l_z; + + normalize_vector(vec); + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in tspyramid format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int tspyramid_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float x = (i + 0.5f) / width; + const float y = (j + 0.5f) / height; + + if (x < 0.5f) { + vec[0] = x * 4.f - 1.f; + vec[1] = (y * 2.f - 1.f); + vec[2] = 1.f; + } else if (x >= 0.6875f && x < 0.8125f && + y >= 0.375f && y < 0.625f) { + vec[0] = -(x - 0.6875f) * 16.f + 1.f; + vec[1] = (y - 0.375f) * 8.f - 1.f; + vec[2] = -1.f; + } else if (0.5f <= x && x < 0.6875f && + ((0.f <= y && y < 0.375f && y >= 2.f * (x - 0.5f)) || + (0.375f <= y && y < 0.625f) || + (0.625f <= y && y < 1.f && y <= 2.f * (1.f - x)))) { + vec[0] = 1.f; + vec[1] = 2.f * (y - 2.f * x + 1.f) / (3.f - 4.f * x) - 1.f; + vec[2] = -2.f * (x - 0.5f) / 0.1875f + 1.f; + } else if (0.8125f <= x && x < 1.f && + ((0.f <= y && y < 0.375f && x >= (1.f - y / 2.f)) || + (0.375f <= y && y < 0.625f) || + (0.625f <= y && y < 1.f && y <= (2.f * x - 1.f)))) { + vec[0] = -1.f; + vec[1] = 2.f * (y + 2.f * x - 2.f) / (4.f * x - 3.f) - 1.f; + vec[2] = 2.f * (x - 0.8125f) / 0.1875f - 1.f; + } else if (0.f <= y && y < 0.375f && + ((0.5f <= x && x < 0.8125f && y < 2.f * (x - 0.5f)) || + (0.6875f <= x && x < 0.8125f) || + (0.8125f <= x && x < 1.f && x < (1.f - y / 2.f)))) { + vec[0] = 2.f * (1.f - x - 0.5f * y) / (0.5f - y) - 1.f; + vec[1] = -1.f; + vec[2] = 2.f * (0.375f - y) / 0.375f - 1.f; + } else { + vec[0] = 2.f * (0.5f - x + 0.5f * y) / (y - 0.5f) - 1.f; + vec[1] = 1.f; + vec[2] = -2.f * (1.f - y) / 0.375f + 1.f; + } + + normalize_vector(vec); + + return 1; +} + +/** + * Calculate frame position in tspyramid format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_tspyramid(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + float uf, vf; + int ui, vi; + int face; + + xyz_to_cube(s, vec, &uf, &vf, &face); + + uf = (uf + 1.f) * 0.5f; + vf = (vf + 1.f) * 0.5f; + + switch (face) { + case UP: + uf = 0.1875f * vf - 0.375f * uf * vf - 0.125f * uf + 0.8125f; + vf = 0.375f - 0.375f * vf; + break; + case FRONT: + uf = 0.5f * uf; + break; + case DOWN: + uf = 1.f - 0.1875f * vf - 0.5f * uf + 0.375f * uf * vf; + vf = 1.f - 0.375f * vf; + break; + case LEFT: + vf = 0.25f * vf + 0.75f * uf * vf - 0.375f * uf + 0.375f; + uf = 0.1875f * uf + 0.8125f; + break; + case RIGHT: + vf = 0.375f * uf - 0.75f * uf * vf + vf; + uf = 0.1875f * uf + 0.5f; + break; + case BACK: + uf = 0.125f * uf + 0.6875f; + vf = 0.25f * vf + 0.375f; + break; + } + + uf *= width; + vf *= height; + + ui = floorf(uf); + vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = reflectx(ui + j - 1, vi + i - 1, width, height); + vs[i][j] = reflecty(vi + i - 1, height); + } + } + + return 1; +} + +/** + * Calculate 3D coordinates on sphere for corresponding frame position in octahedron format. + * + * @param s filter private context + * @param i horizontal position on frame [0, width) + * @param j vertical position on frame [0, height) + * @param width frame width + * @param height frame height + * @param vec coordinates on sphere + */ +static int octahedron_to_xyz(const V360Context *s, + int i, int j, int width, int height, + float *vec) +{ + const float x = ((i + 0.5f) / width) * 2.f - 1.f; + const float y = ((j + 0.5f) / height) * 2.f - 1.f; + const float ax = fabsf(x); + const float ay = fabsf(y); + + vec[2] = 1.f - (ax + ay); + if (ax + ay > 1.f) { + vec[0] = (1.f - ay) * FFSIGN(x); + vec[1] = (1.f - ax) * FFSIGN(y); + } else { + vec[0] = x; + vec[1] = y; + } + + normalize_vector(vec); + + return 1; +} + +/** + * Calculate frame position in octahedron format for corresponding 3D coordinates on sphere. + * + * @param s filter private context + * @param vec coordinates on sphere + * @param width frame width + * @param height frame height + * @param us horizontal coordinates for interpolation window + * @param vs vertical coordinates for interpolation window + * @param du horizontal relative coordinate + * @param dv vertical relative coordinate + */ +static int xyz_to_octahedron(const V360Context *s, + const float *vec, int width, int height, + int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) +{ + float uf, vf, zf; + int ui, vi; + float div = fabsf(vec[0]) + fabsf(vec[1]) + fabsf(vec[2]); + + uf = vec[0] / div; + vf = vec[1] / div; + zf = vec[2]; + + if (zf < 0.f) { + zf = vf; + vf = (1.f - fabsf(uf)) * FFSIGN(zf); + uf = (1.f - fabsf(zf)) * FFSIGN(uf); + } + + uf = uf * 0.5f + 0.5f; + vf = vf * 0.5f + 0.5f; + + uf *= width; + vf *= height; + + ui = floorf(uf); + vi = floorf(vf); + + *du = uf - ui; + *dv = vf - vi; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + us[i][j] = av_clip(ui + j - 1, 0, width - 1); + vs[i][j] = av_clip(vi + i - 1, 0, height - 1); + } + } + + return 1; +} + +static void multiply_quaternion(float c[4], const float a[4], const float b[4]) +{ + c[0] = a[0] * b[0] - a[1] * b[1] - a[2] * b[2] - a[3] * b[3]; + c[1] = a[1] * b[0] + a[0] * b[1] + a[2] * b[3] - a[3] * b[2]; + c[2] = a[2] * b[0] + a[0] * b[2] + a[3] * b[1] - a[1] * b[3]; + c[3] = a[3] * b[0] + a[0] * b[3] + a[1] * b[2] - a[2] * b[1]; +} + +static void conjugate_quaternion(float d[4], const float q[4]) +{ + d[0] = q[0]; + d[1] = -q[1]; + d[2] = -q[2]; + d[3] = -q[3]; +} + +/** + * Calculate rotation quaternion for yaw/pitch/roll angles. + */ +static inline void calculate_rotation(float yaw, float pitch, float roll, + float rot_quaternion[2][4], + const int rotation_order[3]) +{ + const float yaw_rad = yaw * M_PI / 180.f; + const float pitch_rad = pitch * M_PI / 180.f; + const float roll_rad = roll * M_PI / 180.f; + + const float sin_yaw = sinf(yaw_rad * 0.5f); + const float cos_yaw = cosf(yaw_rad * 0.5f); + const float sin_pitch = sinf(pitch_rad * 0.5f); + const float cos_pitch = cosf(pitch_rad * 0.5f); + const float sin_roll = sinf(roll_rad * 0.5f); + const float cos_roll = cosf(roll_rad * 0.5f); + + float m[3][4]; + float tmp[2][4]; + + m[0][0] = cos_yaw; m[0][1] = 0.f; m[0][2] = sin_yaw; m[0][3] = 0.f; + m[1][0] = cos_pitch; m[1][1] = sin_pitch; m[1][2] = 0.f; m[1][3] = 0.f; + m[2][0] = cos_roll; m[2][1] = 0.f; m[2][2] = 0.f; m[2][3] = sin_roll; + + multiply_quaternion(tmp[0], rot_quaternion[0], m[rotation_order[0]]); + multiply_quaternion(tmp[1], tmp[0], m[rotation_order[1]]); + multiply_quaternion(rot_quaternion[0], tmp[1], m[rotation_order[2]]); + + conjugate_quaternion(rot_quaternion[1], rot_quaternion[0]); +} + +/** + * Rotate vector with given rotation quaternion. + * + * @param rot_quaternion rotation quaternion + * @param vec vector + */ +static inline void rotate(const float rot_quaternion[2][4], + float *vec) +{ + float qv[4], temp[4], rqv[4]; + + qv[0] = 0.f; + qv[1] = vec[0]; + qv[2] = vec[1]; + qv[3] = vec[2]; + + multiply_quaternion(temp, rot_quaternion[0], qv); + multiply_quaternion(rqv, temp, rot_quaternion[1]); + + vec[0] = rqv[1]; + vec[1] = rqv[2]; + vec[2] = rqv[3]; +} + +static inline void set_mirror_modifier(int h_flip, int v_flip, int d_flip, + float *modifier) +{ + modifier[0] = h_flip ? -1.f : 1.f; + modifier[1] = v_flip ? -1.f : 1.f; + modifier[2] = d_flip ? -1.f : 1.f; +} + +static inline void mirror(const float *modifier, float *vec) +{ + vec[0] *= modifier[0]; + vec[1] *= modifier[1]; + vec[2] *= modifier[2]; +} + +static inline void input_flip(int16_t u[4][4], int16_t v[4][4], int w, int h, int hflip, int vflip) +{ + if (hflip) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) + u[i][j] = w - 1 - u[i][j]; + } + } + + if (vflip) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) + v[i][j] = h - 1 - v[i][j]; + } + } +} + +static int allocate_plane(V360Context *s, int sizeof_uv, int sizeof_ker, int sizeof_mask, int p) +{ + const int pr_height = s->pr_height[p]; + + for (int n = 0; n < s->nb_threads; n++) { + SliceXYRemap *r = &s->slice_remap[n]; + const int slice_start = (pr_height * n ) / s->nb_threads; + const int slice_end = (pr_height * (n + 1)) / s->nb_threads; + const int height = slice_end - slice_start; + + if (!r->u[p]) + r->u[p] = av_calloc(s->uv_linesize[p] * height, sizeof_uv); + if (!r->v[p]) + r->v[p] = av_calloc(s->uv_linesize[p] * height, sizeof_uv); + if (!r->u[p] || !r->v[p]) + return AVERROR(ENOMEM); + if (sizeof_ker) { + if (!r->ker[p]) + r->ker[p] = av_calloc(s->uv_linesize[p] * height, sizeof_ker); + if (!r->ker[p]) + return AVERROR(ENOMEM); + } + + if (sizeof_mask && !p) { + if (!r->mask) + r->mask = av_calloc(s->pr_width[p] * height, sizeof_mask); + if (!r->mask) + return AVERROR(ENOMEM); + } + } + + return 0; +} + +static void fov_from_dfov(int format, float d_fov, float w, float h, float *h_fov, float *v_fov) +{ + switch (format) { + case ORTHOGRAPHIC: + { + const float d = 0.5f * hypotf(w, h); + const float l = sinf(d_fov * M_PI / 360.f) / d; + + *h_fov = asinf(w * 0.5 * l) * 360.f / M_PI; + *v_fov = asinf(h * 0.5 * l) * 360.f / M_PI; + + if (d_fov > 180.f) { + *h_fov = 180.f - *h_fov; + *v_fov = 180.f - *v_fov; + } + } + break; + case EQUISOLID: + { + const float d = 0.5f * hypotf(w, h); + const float l = d / (sinf(d_fov * M_PI / 720.f)); + + *h_fov = 2.f * asinf(w * 0.5f / l) * 360.f / M_PI; + *v_fov = 2.f * asinf(h * 0.5f / l) * 360.f / M_PI; + } + break; + case STEREOGRAPHIC: + { + const float d = 0.5f * hypotf(w, h); + const float l = d / (tanf(d_fov * M_PI / 720.f)); + + *h_fov = 2.f * atan2f(w * 0.5f, l) * 360.f / M_PI; + *v_fov = 2.f * atan2f(h * 0.5f, l) * 360.f / M_PI; + } + break; + case DUAL_FISHEYE: + { + const float d = 0.5f * hypotf(w * 0.5f, h); + + *h_fov = d / w * 2.f * d_fov; + *v_fov = d / h * d_fov; + } + break; + case FISHEYE: + { + const float d = 0.5f * hypotf(w, h); + + *h_fov = d / w * d_fov; + *v_fov = d / h * d_fov; + } + break; + case FLAT: + default: + { + const float da = tanf(0.5f * FFMIN(d_fov, 359.f) * M_PI / 180.f); + const float d = hypotf(w, h); + + *h_fov = atan2f(da * w, d) * 360.f / M_PI; + *v_fov = atan2f(da * h, d) * 360.f / M_PI; + + if (*h_fov < 0.f) + *h_fov += 360.f; + if (*v_fov < 0.f) + *v_fov += 360.f; + } + break; + } +} + +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[0] = outw[3] = w; + outh[1] = outh[2] = FF_CEIL_RSHIFT(h, desc->log2_chroma_h); + outh[0] = outh[3] = h; +} + +// Calculate remap data +static av_always_inline int v360_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + V360Context *s = ctx->priv; + SliceXYRemap *r = &s->slice_remap[jobnr]; + + for (int p = 0; p < s->nb_allocated; p++) { + const int max_value = s->max_value; + const int width = s->pr_width[p]; + const int uv_linesize = s->uv_linesize[p]; + const int height = s->pr_height[p]; + const int in_width = s->inplanewidth[p]; + const int in_height = s->inplaneheight[p]; + const int slice_start = (height * jobnr ) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int elements = s->elements; + float du, dv; + float vec[3]; + XYRemap rmap; + + for (int j = slice_start; j < slice_end; j++) { + for (int i = 0; i < width; i++) { + int16_t *u = r->u[p] + ((j - slice_start) * uv_linesize + i) * elements; + int16_t *v = r->v[p] + ((j - slice_start) * uv_linesize + i) * elements; + int16_t *ker = r->ker[p] + ((j - slice_start) * uv_linesize + i) * elements; + uint8_t *mask8 = p ? NULL : r->mask + ((j - slice_start) * s->pr_width[0] + i); + uint16_t *mask16 = p ? NULL : (uint16_t *)r->mask + ((j - slice_start) * s->pr_width[0] + i); + int in_mask, out_mask; + + if (s->out_transpose) + out_mask = s->out_transform(s, j, i, height, width, vec); + else + out_mask = s->out_transform(s, i, j, width, height, 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])); + normalize_vector(vec); + mirror(s->output_mirror_modifier, vec); + if (s->in_transpose) + in_mask = s->in_transform(s, vec, in_height, in_width, rmap.v, rmap.u, &du, &dv); + else + in_mask = s->in_transform(s, vec, in_width, in_height, rmap.u, rmap.v, &du, &dv); + input_flip(rmap.u, rmap.v, in_width, in_height, s->ih_flip, s->iv_flip); + av_assert1(!isnan(du) && !isnan(dv)); + s->calculate_kernel(du, dv, &rmap, u, v, ker); + + if (!p && r->mask) { + if (s->mask_size == 1) { + mask8[0] = 255 * (out_mask & in_mask); + } else { + mask16[0] = max_value * (out_mask & in_mask); + } + } + } + } + } + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; + V360Context *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + const int depth = desc->comp[0].depth; + const int sizeof_mask = s->mask_size = (depth + 7) >> 3; + int sizeof_uv; + int sizeof_ker; + int err; + int h, w; + int in_offset_h, in_offset_w; + int out_offset_h, out_offset_w; + float hf, wf; + int (*prepare_out)(AVFilterContext *ctx); + int have_alpha; + + s->max_value = (1 << depth) - 1; + + switch (s->interp) { + case NEAREST: + s->calculate_kernel = nearest_kernel; + s->remap_slice = depth <= 8 ? remap1_8bit_slice : remap1_16bit_slice; + s->elements = 1; + sizeof_uv = sizeof(int16_t) * s->elements; + sizeof_ker = 0; + break; + case BILINEAR: + s->calculate_kernel = bilinear_kernel; + s->remap_slice = depth <= 8 ? remap2_8bit_slice : remap2_16bit_slice; + s->elements = 2 * 2; + sizeof_uv = sizeof(int16_t) * s->elements; + sizeof_ker = sizeof(int16_t) * s->elements; + break; + case LAGRANGE9: + s->calculate_kernel = lagrange_kernel; + s->remap_slice = depth <= 8 ? remap3_8bit_slice : remap3_16bit_slice; + s->elements = 3 * 3; + sizeof_uv = sizeof(int16_t) * s->elements; + sizeof_ker = sizeof(int16_t) * s->elements; + break; + case BICUBIC: + s->calculate_kernel = bicubic_kernel; + s->remap_slice = depth <= 8 ? remap4_8bit_slice : remap4_16bit_slice; + s->elements = 4 * 4; + sizeof_uv = sizeof(int16_t) * s->elements; + sizeof_ker = sizeof(int16_t) * s->elements; + break; + case LANCZOS: + s->calculate_kernel = lanczos_kernel; + s->remap_slice = depth <= 8 ? remap4_8bit_slice : remap4_16bit_slice; + s->elements = 4 * 4; + sizeof_uv = sizeof(int16_t) * s->elements; + sizeof_ker = sizeof(int16_t) * s->elements; + break; + case SPLINE16: + s->calculate_kernel = spline16_kernel; + s->remap_slice = depth <= 8 ? remap4_8bit_slice : remap4_16bit_slice; + s->elements = 4 * 4; + sizeof_uv = sizeof(int16_t) * s->elements; + sizeof_ker = sizeof(int16_t) * s->elements; + break; + case GAUSSIAN: + s->calculate_kernel = gaussian_kernel; + s->remap_slice = depth <= 8 ? remap4_8bit_slice : remap4_16bit_slice; + s->elements = 4 * 4; + sizeof_uv = sizeof(int16_t) * s->elements; + sizeof_ker = sizeof(int16_t) * s->elements; + break; + case MITCHELL: + s->calculate_kernel = mitchell_kernel; + s->remap_slice = depth <= 8 ? remap4_8bit_slice : remap4_16bit_slice; + s->elements = 4 * 4; + sizeof_uv = sizeof(int16_t) * s->elements; + sizeof_ker = sizeof(int16_t) * s->elements; + break; + default: + av_assert0(0); + } + + ff_v360_init(s, depth); + + for (int order = 0; order < NB_RORDERS; order++) { + const char c = s->rorder[order]; + int rorder; + + if (c == '\0') { + av_log(ctx, AV_LOG_WARNING, + "Incomplete rorder option. Direction for all 3 rotation orders should be specified. Switching to default rorder.\n"); + s->rotation_order[0] = YAW; + s->rotation_order[1] = PITCH; + s->rotation_order[2] = ROLL; + break; + } + + rorder = get_rorder(c); + if (rorder == -1) { + av_log(ctx, AV_LOG_WARNING, + "Incorrect rotation order symbol '%c' in rorder option. Switching to default rorder.\n", c); + s->rotation_order[0] = YAW; + s->rotation_order[1] = PITCH; + s->rotation_order[2] = ROLL; + break; + } + + s->rotation_order[order] = rorder; + } + + switch (s->in_stereo) { + case STEREO_2D: + w = inlink->w; + h = inlink->h; + in_offset_w = in_offset_h = 0; + break; + case STEREO_SBS: + w = inlink->w / 2; + h = inlink->h; + in_offset_w = w; + in_offset_h = 0; + break; + case STEREO_TB: + w = inlink->w; + h = inlink->h / 2; + in_offset_w = 0; + in_offset_h = h; + break; + default: + av_assert0(0); + } + + set_dimensions(s->inplanewidth, s->inplaneheight, w, h, desc); + set_dimensions(s->in_offset_w, s->in_offset_h, in_offset_w, in_offset_h, desc); + + s->in_width = s->inplanewidth[0]; + s->in_height = s->inplaneheight[0]; + + if (s->id_fov > 0.f) + fov_from_dfov(s->in, s->id_fov, w, h, &s->ih_fov, &s->iv_fov); + + if (s->in_transpose) + FFSWAP(int, s->in_width, s->in_height); + + switch (s->in) { + case EQUIRECTANGULAR: + s->in_transform = xyz_to_equirect; + err = 0; + wf = w; + hf = h; + break; + case CUBEMAP_3_2: + s->in_transform = xyz_to_cube3x2; + err = prepare_cube_in(ctx); + wf = w / 3.f * 4.f; + hf = h; + break; + case CUBEMAP_1_6: + s->in_transform = xyz_to_cube1x6; + err = prepare_cube_in(ctx); + wf = w * 4.f; + hf = h / 3.f; + break; + case CUBEMAP_6_1: + s->in_transform = xyz_to_cube6x1; + err = prepare_cube_in(ctx); + wf = w / 3.f * 2.f; + hf = h * 2.f; + break; + case EQUIANGULAR: + s->in_transform = xyz_to_eac; + err = prepare_eac_in(ctx); + wf = w; + hf = h / 9.f * 8.f; + break; + case FLAT: + s->in_transform = xyz_to_flat; + err = prepare_flat_in(ctx); + wf = w; + hf = h; + break; + case PERSPECTIVE: + av_log(ctx, AV_LOG_ERROR, "Supplied format is not accepted as input.\n"); + return AVERROR(EINVAL); + case DUAL_FISHEYE: + s->in_transform = xyz_to_dfisheye; + err = prepare_fisheye_in(ctx); + wf = w; + hf = h; + break; + case BARREL: + s->in_transform = xyz_to_barrel; + err = 0; + wf = w / 5.f * 4.f; + hf = h; + break; + case STEREOGRAPHIC: + s->in_transform = xyz_to_stereographic; + err = prepare_stereographic_in(ctx); + wf = w; + hf = h / 2.f; + break; + case MERCATOR: + s->in_transform = xyz_to_mercator; + err = 0; + wf = w; + hf = h / 2.f; + break; + case BALL: + s->in_transform = xyz_to_ball; + err = 0; + wf = w; + hf = h / 2.f; + break; + case HAMMER: + s->in_transform = xyz_to_hammer; + err = 0; + wf = w; + hf = h; + break; + case SINUSOIDAL: + s->in_transform = xyz_to_sinusoidal; + err = 0; + wf = w; + hf = h; + break; + case FISHEYE: + s->in_transform = xyz_to_fisheye; + err = prepare_fisheye_in(ctx); + wf = w * 2; + hf = h; + break; + case PANNINI: + s->in_transform = xyz_to_pannini; + err = 0; + wf = w; + hf = h; + break; + case CYLINDRICAL: + s->in_transform = xyz_to_cylindrical; + err = prepare_cylindrical_in(ctx); + wf = w; + hf = h * 2.f; + break; + case TETRAHEDRON: + s->in_transform = xyz_to_tetrahedron; + err = 0; + wf = w; + hf = h; + break; + case BARREL_SPLIT: + s->in_transform = xyz_to_barrelsplit; + err = 0; + wf = w * 4.f / 3.f; + hf = h; + break; + case TSPYRAMID: + s->in_transform = xyz_to_tspyramid; + err = 0; + wf = w; + hf = h; + break; + case HEQUIRECTANGULAR: + s->in_transform = xyz_to_hequirect; + err = 0; + wf = w * 2.f; + hf = h; + break; + case EQUISOLID: + s->in_transform = xyz_to_equisolid; + err = prepare_equisolid_in(ctx); + wf = w; + hf = h / 2.f; + break; + case ORTHOGRAPHIC: + s->in_transform = xyz_to_orthographic; + err = prepare_orthographic_in(ctx); + wf = w; + hf = h / 2.f; + break; + case OCTAHEDRON: + s->in_transform = xyz_to_octahedron; + err = 0; + wf = w; + hf = h / 2.f; + break; + default: + av_log(ctx, AV_LOG_ERROR, "Specified input format is not handled.\n"); + return AVERROR_BUG; + } + + if (err != 0) { + return err; + } + + switch (s->out) { + case EQUIRECTANGULAR: + s->out_transform = equirect_to_xyz; + prepare_out = NULL; + w = lrintf(wf); + h = lrintf(hf); + break; + case CUBEMAP_3_2: + s->out_transform = cube3x2_to_xyz; + prepare_out = prepare_cube_out; + w = lrintf(wf / 4.f * 3.f); + h = lrintf(hf); + break; + case CUBEMAP_1_6: + s->out_transform = cube1x6_to_xyz; + prepare_out = prepare_cube_out; + w = lrintf(wf / 4.f); + h = lrintf(hf * 3.f); + break; + case CUBEMAP_6_1: + s->out_transform = cube6x1_to_xyz; + prepare_out = prepare_cube_out; + w = lrintf(wf / 2.f * 3.f); + h = lrintf(hf / 2.f); + break; + case EQUIANGULAR: + s->out_transform = eac_to_xyz; + prepare_out = prepare_eac_out; + w = lrintf(wf); + h = lrintf(hf / 8.f * 9.f); + break; + case FLAT: + s->out_transform = flat_to_xyz; + prepare_out = prepare_flat_out; + w = lrintf(wf); + h = lrintf(hf); + break; + case DUAL_FISHEYE: + s->out_transform = dfisheye_to_xyz; + prepare_out = prepare_fisheye_out; + w = lrintf(wf); + h = lrintf(hf); + break; + case BARREL: + s->out_transform = barrel_to_xyz; + prepare_out = NULL; + w = lrintf(wf / 4.f * 5.f); + h = lrintf(hf); + break; + case STEREOGRAPHIC: + s->out_transform = stereographic_to_xyz; + prepare_out = prepare_stereographic_out; + w = lrintf(wf); + h = lrintf(hf * 2.f); + break; + case MERCATOR: + s->out_transform = mercator_to_xyz; + prepare_out = NULL; + w = lrintf(wf); + h = lrintf(hf * 2.f); + break; + case BALL: + s->out_transform = ball_to_xyz; + prepare_out = NULL; + w = lrintf(wf); + h = lrintf(hf * 2.f); + break; + case HAMMER: + s->out_transform = hammer_to_xyz; + prepare_out = NULL; + w = lrintf(wf); + h = lrintf(hf); + break; + case SINUSOIDAL: + s->out_transform = sinusoidal_to_xyz; + prepare_out = NULL; + w = lrintf(wf); + h = lrintf(hf); + break; + case FISHEYE: + s->out_transform = fisheye_to_xyz; + prepare_out = prepare_fisheye_out; + w = lrintf(wf * 0.5f); + h = lrintf(hf); + break; + case PANNINI: + s->out_transform = pannini_to_xyz; + prepare_out = NULL; + w = lrintf(wf); + h = lrintf(hf); + break; + case CYLINDRICAL: + s->out_transform = cylindrical_to_xyz; + prepare_out = prepare_cylindrical_out; + w = lrintf(wf); + h = lrintf(hf * 0.5f); + break; + case PERSPECTIVE: + s->out_transform = perspective_to_xyz; + prepare_out = NULL; + w = lrintf(wf / 2.f); + h = lrintf(hf); + break; + case TETRAHEDRON: + s->out_transform = tetrahedron_to_xyz; + prepare_out = NULL; + w = lrintf(wf); + h = lrintf(hf); + break; + case BARREL_SPLIT: + s->out_transform = barrelsplit_to_xyz; + prepare_out = NULL; + w = lrintf(wf / 4.f * 3.f); + h = lrintf(hf); + break; + case TSPYRAMID: + s->out_transform = tspyramid_to_xyz; + prepare_out = NULL; + w = lrintf(wf); + h = lrintf(hf); + break; + case HEQUIRECTANGULAR: + s->out_transform = hequirect_to_xyz; + prepare_out = NULL; + w = lrintf(wf / 2.f); + h = lrintf(hf); + break; + case EQUISOLID: + s->out_transform = equisolid_to_xyz; + prepare_out = prepare_equisolid_out; + w = lrintf(wf); + h = lrintf(hf * 2.f); + break; + case ORTHOGRAPHIC: + s->out_transform = orthographic_to_xyz; + prepare_out = prepare_orthographic_out; + w = lrintf(wf); + h = lrintf(hf * 2.f); + break; + case OCTAHEDRON: + s->out_transform = octahedron_to_xyz; + prepare_out = NULL; + w = lrintf(wf); + h = lrintf(hf * 2.f); + break; + default: + av_log(ctx, AV_LOG_ERROR, "Specified output format is not handled.\n"); + return AVERROR_BUG; + } + + // Override resolution with user values if specified + if (s->width > 0 && s->height <= 0 && s->h_fov > 0.f && s->v_fov > 0.f && + s->out == FLAT && s->d_fov == 0.f) { + w = s->width; + h = w / tanf(s->h_fov * M_PI / 360.f) * tanf(s->v_fov * M_PI / 360.f); + } else if (s->width <= 0 && s->height > 0 && s->h_fov > 0.f && s->v_fov > 0.f && + s->out == FLAT && s->d_fov == 0.f) { + h = s->height; + w = h / tanf(s->v_fov * M_PI / 360.f) * tanf(s->h_fov * M_PI / 360.f); + } else if (s->width > 0 && s->height > 0) { + w = s->width; + h = s->height; + } else if (s->width > 0 || s->height > 0) { + av_log(ctx, AV_LOG_ERROR, "Both width and height values should be specified.\n"); + return AVERROR(EINVAL); + } else { + if (s->out_transpose) + FFSWAP(int, w, h); + + if (s->in_transpose) + FFSWAP(int, w, h); + } + + s->width = w; + s->height = h; + + if (s->d_fov > 0.f) + fov_from_dfov(s->out, s->d_fov, w, h, &s->h_fov, &s->v_fov); + + if (prepare_out) { + err = prepare_out(ctx); + if (err != 0) + return err; + } + + set_dimensions(s->pr_width, s->pr_height, w, h, desc); + + switch (s->out_stereo) { + case STEREO_2D: + out_offset_w = out_offset_h = 0; + break; + case STEREO_SBS: + out_offset_w = w; + out_offset_h = 0; + w *= 2; + break; + case STEREO_TB: + out_offset_w = 0; + out_offset_h = h; + h *= 2; + break; + default: + av_assert0(0); + } + + set_dimensions(s->out_offset_w, s->out_offset_h, out_offset_w, out_offset_h, desc); + set_dimensions(s->planewidth, s->planeheight, w, h, desc); + + for (int i = 0; i < 4; i++) + s->uv_linesize[i] = FFALIGN(s->pr_width[i], 8); + + outlink->h = h; + outlink->w = w; + + s->nb_threads = FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)); + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + have_alpha = !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA); + + if (desc->log2_chroma_h == desc->log2_chroma_w && desc->log2_chroma_h == 0) { + s->nb_allocated = 1; + s->map[0] = s->map[1] = s->map[2] = s->map[3] = 0; + } else { + s->nb_allocated = 2; + s->map[0] = s->map[3] = 0; + s->map[1] = s->map[2] = 1; + } + + if (!s->slice_remap) + s->slice_remap = av_calloc(s->nb_threads, sizeof(*s->slice_remap)); + if (!s->slice_remap) + return AVERROR(ENOMEM); + + for (int i = 0; i < s->nb_allocated; i++) { + err = allocate_plane(s, sizeof_uv, sizeof_ker, sizeof_mask * have_alpha * s->alpha, i); + if (err < 0) + return err; + } + + calculate_rotation(s->yaw, s->pitch, s->roll, + s->rot_quaternion, s->rotation_order); + + set_mirror_modifier(s->h_flip, s->v_flip, s->d_flip, s->output_mirror_modifier); + + ctx->internal->execute(ctx, v360_slice, NULL, NULL, s->nb_threads); + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + V360Context *s = ctx->priv; + 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; + + ctx->internal->execute(ctx, s->remap_slice, &td, NULL, 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) +{ + V360Context *s = ctx->priv; + int ret; + + s->yaw = s->pitch = s->roll = 0.f; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_output(ctx->outputs[0]); +} + +static av_cold int init(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->rot_quaternion[0][0] = 1.f; + s->rot_quaternion[0][1] = s->rot_quaternion[0][2] = s->rot_quaternion[0][3] = 0.f; + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + for (int n = 0; n < s->nb_threads && s->slice_remap; n++) { + SliceXYRemap *r = &s->slice_remap[n]; + + for (int p = 0; p < s->nb_allocated; p++) { + av_freep(&r->u[p]); + av_freep(&r->v[p]); + av_freep(&r->ker[p]); + } + + av_freep(&r->mask); + } + + av_freep(&s->slice_remap); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vf_v360 = { + .name = "v360", + .description = NULL_IF_CONFIG_SMALL("Convert 360 projection of video."), + .priv_size = sizeof(V360Context), + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .inputs = inputs, + .outputs = outputs, + .priv_class = &v360_class, + .flags = AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_vaguedenoiser.c ffmpeg-4.4/libavfilter/vf_vaguedenoiser.c --- ffmpeg-4.2.2/libavfilter/vf_vaguedenoiser.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_vaguedenoiser.c 2021-04-08 21:28:40.000000000 +0000 @@ -38,6 +38,7 @@ float threshold; float percent; int method; + int type; int nsteps; int planes; @@ -60,7 +61,7 @@ void (*thresholding)(float *block, const int width, const int height, const int stride, const float threshold, - const float percent, const int nsteps); + const float percent); } VagueDenoiserContext; #define OFFSET(x) offsetof(VagueDenoiserContext, x) @@ -70,10 +71,13 @@ { "method", "set filtering method", OFFSET(method), AV_OPT_TYPE_INT, {.i64=2 }, 0, 2, FLAGS, "method" }, { "hard", "hard thresholding", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "method" }, { "soft", "soft thresholding", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "method" }, - { "garrote", "garotte thresholding", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "method" }, + { "garrote", "garrote thresholding", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "method" }, { "nsteps", "set number of steps", OFFSET(nsteps), AV_OPT_TYPE_INT, {.i64=6 }, 1, 32, FLAGS }, { "percent", "set percent of full denoising", OFFSET(percent),AV_OPT_TYPE_FLOAT, {.dbl=85}, 0,100, FLAGS }, { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15 }, 0, 15, FLAGS }, + { "type", "set threshold type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0 }, 0, 1, FLAGS, "type" }, + { "universal", "universal (VisuShrink)", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "type" }, + { "bayes", "bayes (BayesShrink)", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "type" }, { NULL } }; @@ -104,8 +108,8 @@ static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_GRAY8, - AV_PIX_FMT_GRAY16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, + AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, @@ -121,6 +125,11 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); @@ -328,7 +337,7 @@ static void hard_thresholding(float *block, const int width, const int height, const int stride, const float threshold, - const float percent, const int unused) + const float percent) { const float frac = 1.f - percent * 0.01f; int y, x; @@ -343,22 +352,14 @@ } static void soft_thresholding(float *block, const int width, const int height, const int stride, - const float threshold, const float percent, const int nsteps) + const float threshold, const float percent) { const float frac = 1.f - percent * 0.01f; const float shift = threshold * 0.01f * percent; - int w = width; - int h = height; - int y, x, l; - - for (l = 0; l < nsteps; l++) { - w = (w + 1) >> 1; - h = (h + 1) >> 1; - } + int y, x; for (y = 0; y < height; y++) { - const int x0 = (y < h) ? w : 0; - for (x = x0; x < width; x++) { + for (x = 0; x < width; x++) { const float temp = FFABS(block[x]); if (temp <= threshold) block[x] *= frac; @@ -371,7 +372,7 @@ static void qian_thresholding(float *block, const int width, const int height, const int stride, const float threshold, - const float percent, const int unused) + const float percent) { const float percent01 = percent * 0.01f; const float tr2 = threshold * threshold * percent01; @@ -392,6 +393,23 @@ } } +static float bayes_threshold(float *block, const int width, const int height, + const int stride, const float threshold) +{ + float mean = 0.f; + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + mean += block[x] * block[x]; + } + block += stride; + } + + mean /= width * height; + + return threshold * threshold / (FFMAX(sqrtf(mean - threshold), FLT_EPSILON)); +} + static void filter(VagueDenoiserContext *s, AVFrame *in, AVFrame *out) { int p, y, x, i, j; @@ -455,7 +473,28 @@ v_low_size0 = (v_low_size0 + 1) >> 1; } - s->thresholding(s->block, width, height, width, s->threshold, s->percent, s->nsteps); + if (s->type == 0) { + s->thresholding(s->block, width, height, width, s->threshold, s->percent); + } else { + for (int n = 0; n < s->nsteps; n++) { + float threshold; + float *block; + + if (n == s->nsteps - 1) { + threshold = bayes_threshold(s->block, s->hlowsize[p][n], s->vlowsize[p][n], width, s->threshold); + s->thresholding(s->block, s->hlowsize[p][n], s->vlowsize[p][n], width, threshold, s->percent); + } + block = s->block + s->hlowsize[p][n]; + threshold = bayes_threshold(block, s->hhighsize[p][n], s->vlowsize[p][n], width, s->threshold); + s->thresholding(block, s->hhighsize[p][n], s->vlowsize[p][n], width, threshold, s->percent); + block = s->block + s->vlowsize[p][n] * width; + threshold = bayes_threshold(block, s->hlowsize[p][n], s->vhighsize[p][n], width, s->threshold); + s->thresholding(block, s->hlowsize[p][n], s->vhighsize[p][n], width, threshold, s->percent); + block = s->block + s->hlowsize[p][n] + s->vlowsize[p][n] * width; + threshold = bayes_threshold(block, s->hhighsize[p][n], s->vhighsize[p][n], width, s->threshold); + s->thresholding(block, s->hhighsize[p][n], s->vhighsize[p][n], width, threshold, s->percent); + } + } while (nsteps_invert--) { const int idx = s->vlowsize[p][nsteps_invert] + s->vhighsize[p][nsteps_invert]; diff -Nru ffmpeg-4.2.2/libavfilter/vf_vectorscope.c ffmpeg-4.4/libavfilter/vf_vectorscope.c --- ffmpeg-4.2.2/libavfilter/vf_vectorscope.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_vectorscope.c 2021-04-08 21:28:40.000000000 +0000 @@ -29,8 +29,16 @@ #include "internal.h" #include "video.h" +enum GraticuleType { + GRAT_NONE, + GRAT_GREEN, + GRAT_COLOR, + GRAT_INVERT, + NB_GRATICULES +}; + enum VectorscopeMode { - GRAY, + TINT, COLOR, COLOR2, COLOR3, @@ -45,6 +53,7 @@ int intensity; float fintensity; uint16_t bg_color[4]; + float ftint[2]; int planewidth[4]; int planeheight[4]; int hsub, vsub; @@ -59,6 +68,7 @@ float bgopacity; float lthreshold; float hthreshold; + int tint[2]; int tmin; int tmax; int flags; @@ -79,7 +89,8 @@ static const AVOption vectorscope_options[] = { { "mode", "set vectorscope mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, MODE_NB-1, FLAGS, "mode"}, { "m", "set vectorscope mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, MODE_NB-1, FLAGS, "mode"}, - { "gray", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAY}, 0, 0, FLAGS, "mode" }, + { "gray", 0, 0, AV_OPT_TYPE_CONST, {.i64=TINT}, 0, 0, FLAGS, "mode" }, + { "tint", 0, 0, AV_OPT_TYPE_CONST, {.i64=TINT}, 0, 0, FLAGS, "mode" }, { "color", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR}, 0, 0, FLAGS, "mode" }, { "color2", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR2}, 0, 0, FLAGS, "mode" }, { "color3", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR3}, 0, 0, FLAGS, "mode" }, @@ -95,11 +106,12 @@ { "instant", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "envelope" }, { "peak", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "envelope" }, { "peak+instant", 0, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "envelope" }, - { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule"}, - { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule"}, - { "none", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "graticule" }, - { "green", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "graticule" }, - { "color", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "graticule" }, + { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=GRAT_NONE}, 0, NB_GRATICULES-1, FLAGS, "graticule"}, + { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=GRAT_NONE}, 0, NB_GRATICULES-1, FLAGS, "graticule"}, + { "none", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_NONE}, 0, 0, FLAGS, "graticule" }, + { "green", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_GREEN}, 0, 0, FLAGS, "graticule" }, + { "color", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_COLOR}, 0, 0, FLAGS, "graticule" }, + { "invert", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_INVERT},0, 0, FLAGS, "graticule" }, { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS}, { "o", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS}, { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=4}, 0, 7, FLAGS, "flags"}, @@ -118,6 +130,10 @@ { "auto", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "colorspace" }, { "601", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "colorspace" }, { "709", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "colorspace" }, + { "tint0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, + { "t0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, + { "tint1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, + { "t1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, { NULL } }; @@ -139,7 +155,7 @@ }; static const enum AVPixelFormat out_yuv12_pix_fmts[] = { - AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_NONE }; @@ -167,7 +183,7 @@ AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, - AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, @@ -188,6 +204,7 @@ AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_NONE }; @@ -199,23 +216,23 @@ AVFilterFormats *avff; int depth, rgb, i, ret; - if (!ctx->inputs[0]->in_formats || - !ctx->inputs[0]->in_formats->nb_formats) { + if (!ctx->inputs[0]->incfg.formats || + !ctx->inputs[0]->incfg.formats->nb_formats) { return AVERROR(EAGAIN); } - if (!ctx->inputs[0]->out_formats) { + if (!ctx->inputs[0]->outcfg.formats) { const enum AVPixelFormat *in_pix_fmts; if ((s->x == 1 && s->y == 2) || (s->x == 2 && s->y == 1)) in_pix_fmts = in2_pix_fmts; else in_pix_fmts = in1_pix_fmts; - if ((ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), &ctx->inputs[0]->out_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), &ctx->inputs[0]->outcfg.formats)) < 0) return ret; } - avff = ctx->inputs[0]->in_formats; + avff = ctx->inputs[0]->incfg.formats; desc = av_pix_fmt_desc_get(avff->formats[0]); rgb = desc->flags & AV_PIX_FMT_FLAG_RGB; depth = desc->comp[0].depth; @@ -244,7 +261,7 @@ out_pix_fmts = out_yuv12_pix_fmts; else return AVERROR(EAGAIN); - if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->incfg.formats)) < 0) return ret; return 0; @@ -417,6 +434,8 @@ uint16_t *dpx = dst[px]; uint16_t *dpy = dst[py]; uint16_t *dpd = dst[pd]; + uint16_t *dp1 = dst[1]; + uint16_t *dp2 = dst[2]; const int max = s->size - 1; const int mid = s->size / 2; const int tmin = s->tmin; @@ -433,42 +452,21 @@ switch (s->mode) { case COLOR: case COLOR5: - case GRAY: - if (s->is_yuv) { - for (i = 0; i < h; i++) { - const int iwx = i * slinesizex; - const int iwy = i * slinesizey; - const int iwd = i * slinesized; - for (j = 0; j < w; j++) { - const int x = FFMIN(spx[iwx + j], max); - const int y = FFMIN(spy[iwy + j], max); - const int z = spd[iwd + j]; - const int pos = y * dlinesize + x; - - if (z < tmin || z > tmax) - continue; - - dpd[pos] = FFMIN(dpd[pos] + intensity, max); - } - } - } else { - for (i = 0; i < h; i++) { - const int iwx = i * slinesizex; - const int iwy = i * slinesizey; - const int iwd = i * slinesized; - for (j = 0; j < w; j++) { - const int x = FFMIN(spx[iwx + j], max); - const int y = FFMIN(spy[iwy + j], max); - const int z = spd[iwd + j]; - const int pos = y * dlinesize + x; + case TINT: + for (i = 0; i < h; i++) { + const int iwx = i * slinesizex; + const int iwy = i * slinesizey; + const int iwd = i * slinesized; + for (j = 0; j < w; j++) { + const int x = FFMIN(spx[iwx + j], max); + const int y = FFMIN(spy[iwy + j], max); + const int z = spd[iwd + j]; + const int pos = y * dlinesize + x; - if (z < tmin || z > tmax) - continue; + if (z < tmin || z > tmax) + continue; - dst[0][pos] = FFMIN(dst[0][pos] + intensity, max); - dst[1][pos] = FFMIN(dst[1][pos] + intensity, max); - dst[2][pos] = FFMIN(dst[2][pos] + intensity, max); - } + dpd[pos] = FFMIN(dpd[pos] + intensity, max); } } break; @@ -572,7 +570,28 @@ } } - if (s->mode == COLOR) { + if (s->mode == TINT && s->is_yuv && + (s->tint[0] != mid || s->tint[1] != mid)) { + for (i = 0; i < out->height; i++) { + for (j = 0; j < out->width; j++) { + const int pos = i * dlinesize + j; + if (dpd[pos]) { + dp1[pos] = s->tint[0]; + dp2[pos] = s->tint[1]; + } + } + } + } else if (s->mode == TINT && !s->is_yuv) { + for (i = 0; i < out->height; i++) { + for (j = 0; j < out->width; j++) { + const int pos = i * dlinesize + j; + if (dpd[pos]) { + dpx[pos] = av_clip(dpd[pos] + dpd[pos] * s->ftint[0], 0, max); + dpy[pos] = av_clip(dpd[pos] + dpd[pos] * s->ftint[1], 0, max); + } + } + } + } else if (s->mode == COLOR) { for (i = 0; i < out->height; i++) { for (j = 0; j < out->width; j++) { if (!dpd[i * dlinesize + j]) { @@ -615,6 +634,8 @@ uint8_t *dpx = dst[px]; uint8_t *dpy = dst[py]; uint8_t *dpd = dst[pd]; + uint8_t *dp1 = dst[1]; + uint8_t *dp2 = dst[2]; const int tmin = s->tmin; const int tmax = s->tmax; int i, j, k; @@ -627,42 +648,21 @@ switch (s->mode) { case COLOR5: case COLOR: - case GRAY: - if (s->is_yuv) { - for (i = 0; i < h; i++) { - const int iwx = i * slinesizex; - const int iwy = i * slinesizey; - const int iwd = i * slinesized; - for (j = 0; j < w; j++) { - const int x = spx[iwx + j]; - const int y = spy[iwy + j]; - const int z = spd[iwd + j]; - const int pos = y * dlinesize + x; - - if (z < tmin || z > tmax) - continue; - - dpd[pos] = FFMIN(dpd[pos] + intensity, 255); - } - } - } else { - for (i = 0; i < h; i++) { - const int iwx = i * slinesizex; - const int iwy = i * slinesizey; - const int iwd = i * slinesized; - for (j = 0; j < w; j++) { - const int x = spx[iwx + j]; - const int y = spy[iwy + j]; - const int z = spd[iwd + j]; - const int pos = y * dlinesize + x; + case TINT: + for (i = 0; i < h; i++) { + const int iwx = i * slinesizex; + const int iwy = i * slinesizey; + const int iwd = i * slinesized; + for (j = 0; j < w; j++) { + const int x = spx[iwx + j]; + const int y = spy[iwy + j]; + const int z = spd[iwd + j]; + const int pos = y * dlinesize + x; - if (z < tmin || z > tmax) - continue; + if (z < tmin || z > tmax) + continue; - dst[0][pos] = FFMIN(dst[0][pos] + intensity, 255); - dst[1][pos] = FFMIN(dst[1][pos] + intensity, 255); - dst[2][pos] = FFMIN(dst[2][pos] + intensity, 255); - } + dpd[pos] = FFMIN(dpd[pos] + intensity, 255); } } break; @@ -766,7 +766,28 @@ } } - if (s->mode == COLOR) { + if (s->mode == TINT && s->is_yuv && + (s->tint[0] != 128 || s->tint[1] != 128)) { + for (i = 0; i < out->height; i++) { + for (j = 0; j < out->width; j++) { + const int pos = i * dlinesize + j; + if (dpd[pos]) { + dp1[pos] = s->tint[0]; + dp2[pos] = s->tint[1]; + } + } + } + } else if (s->mode == TINT && !s->is_yuv) { + for (i = 0; i < out->height; i++) { + for (j = 0; j < out->width; j++) { + const int pos = i * dlinesize + j; + if (dpd[pos]) { + dpx[pos] = av_clip_uint8(dpd[pos] + dpd[pos] * s->ftint[0]); + dpy[pos] = av_clip_uint8(dpd[pos] + dpd[pos] * s->ftint[1]); + } + } + } + } else if (s->mode == COLOR) { for (i = 0; i < out->height; i++) { for (j = 0; j < out->width; j++) { if (!dpd[i * out->linesize[pd] + j]) { @@ -870,6 +891,28 @@ dst[-l + 2] = dst[-l + 2] * f + V; } +static void draw_idots(uint8_t *dst, int L, float o) +{ + const float f = 1. - o; + int l = L * 2; + + dst[ l - 3] = dst[ l - 3] * f + (255 - dst[ l - 3]) * o; + dst[ l + 3] = dst[ l + 3] * f + (255 - dst[ l + 3]) * o; + dst[-l - 3] = dst[-l - 3] * f + (255 - dst[-l - 3]) * o; + dst[-l + 3] = dst[-l + 3] * f + (255 - dst[-l + 3]) * o; + + l += L; + + dst[ l - 3] = dst[ l - 3] * f + (255 - dst[ l - 3]) * o; + dst[ l + 3] = dst[ l + 3] * f + (255 - dst[ l + 3]) * o; + dst[ l - 2] = dst[ l - 2] * f + (255 - dst[ l - 2]) * o; + dst[ l + 2] = dst[ l + 2] * f + (255 - dst[ l + 2]) * o; + dst[-l - 3] = dst[-l - 3] * f + (255 - dst[-l - 3]) * o; + dst[-l + 3] = dst[-l + 3] * f + (255 - dst[-l + 3]) * o; + dst[-l - 2] = dst[-l - 2] * f + (255 - dst[-l - 2]) * o; + dst[-l + 2] = dst[-l + 2] * f + (255 - dst[-l + 2]) * o; +} + static void draw_dots16(uint16_t *dst, int L, int v, float o) { const float f = 1. - o; @@ -893,10 +936,83 @@ dst[-l + 2] = dst[-l + 2] * f + V; } +static void draw_idots16(uint16_t *dst, int L, int v, float o) +{ + const float f = 1. - o; + int l = L * 2; + + dst[ l - 3] = dst[ l - 3] * f + (v - dst[ l - 3]) * o; + dst[ l + 3] = dst[ l + 3] * f + (v - dst[ l + 3]) * o; + dst[-l - 3] = dst[-l - 3] * f + (v - dst[-l - 3]) * o; + dst[-l + 3] = dst[-l + 3] * f + (v - dst[-l + 3]) * o; + + l += L; + + dst[ l - 3] = dst[ l - 3] * f + (v - dst[ l - 3]) * o; + dst[ l + 3] = dst[ l + 3] * f + (v - dst[ l + 3]) * o; + dst[ l - 2] = dst[ l - 2] * f + (v - dst[ l - 2]) * o; + dst[ l + 2] = dst[ l + 2] * f + (v - dst[ l + 2]) * o; + dst[-l - 3] = dst[-l - 3] * f + (v - dst[-l - 3]) * o; + dst[-l + 3] = dst[-l + 3] * f + (v - dst[-l + 3]) * o; + dst[-l - 2] = dst[-l - 2] * f + (v - dst[-l - 2]) * o; + dst[-l + 2] = dst[-l + 2] * f + (v - dst[-l + 2]) * o; +} + static void none_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P) { } +static void draw_ihtext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4]) +{ + const uint8_t *font; + int font_height; + int i, plane; + + font = avpriv_cga_font, font_height = 8; + + for (plane = 0; plane < 4 && out->data[plane]; plane++) { + for (i = 0; txt[i]; i++) { + int char_y, mask; + + uint8_t *p = out->data[plane] + y * out->linesize[plane] + (x + i * 8); + for (char_y = font_height - 1; char_y >= 0; char_y--) { + for (mask = 0x80; mask; mask >>= 1) { + if (font[txt[i] * font_height + char_y] & mask) + p[0] = p[0] * o2 + (255 - p[0]) * o1; + p++; + } + p += out->linesize[plane] - 8; + } + } + } +} + +static void draw_ihtext16(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint16_t color[4]) +{ + const uint8_t *font; + int font_height; + int i, plane; + + font = avpriv_cga_font, font_height = 8; + + for (plane = 0; plane < 4 && out->data[plane]; plane++) { + for (i = 0; txt[i]; i++) { + int char_y, mask; + int v = color[plane]; + + uint16_t *p = (uint16_t *)(out->data[plane] + y * out->linesize[plane]) + (x + i * 8); + for (char_y = font_height - 1; char_y >= 0; char_y--) { + for (mask = 0x80; mask; mask >>= 1) { + if (font[txt[i] * font_height + char_y] & mask) + p[0] = p[0] * o2 + (v - p[0]) * o1; + p++; + } + p += out->linesize[plane] / 2 - 8; + } + } + } +} + static void draw_htext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4]) { const uint8_t *font; @@ -1201,6 +1317,123 @@ } } +static void invert_graticule16(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P) +{ + const int max = s->size - 1; + const float o = s->opacity; + int i; + + for (i = 0; i < 12; i++) { + int x = positions[P][i][X]; + int y = positions[P][i][Y]; + + draw_idots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, max, o); + draw_idots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, max, o); + draw_idots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, max, o); + if (out->data[3]) + draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o); + } + + if (s->flags & 1) { + int x = positions[P][12][X]; + int y = positions[P][12][Y]; + + draw_idots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, max, o); + draw_idots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, max, o); + draw_idots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, max, o); + if (out->data[3]) + draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o); + } + + if (s->flags & 2) { + int x = positions[P][13][X]; + int y = positions[P][13][Y]; + + draw_idots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, max, o); + draw_idots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, max, o); + draw_idots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, max, o); + if (out->data[3]) + draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o); + } + + for (i = 0; i < 6 && s->flags & 4; i++) { + uint16_t color[4] = { max, max, max, max }; + int x = positions[P][i][X]; + int y = positions[P][i][Y]; + + if (x > max / 2) + x += 8; + else + x -= 14; + if (y > max / 2) + y += 8; + else + y -= 14; + + x = av_clip(x, 0, out->width - 9); + y = av_clip(y, 0, out->height - 9); + draw_ihtext16(out, x, y, o, 1. - o, positions_name[i], color); + } +} + +static void invert_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P) +{ + const float o = s->opacity; + int i; + + for (i = 0; i < 12; i++) { + int x = positions[P][i][X]; + int y = positions[P][i][Y]; + + draw_idots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], o); + draw_idots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], o); + draw_idots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], o); + if (out->data[3]) + draw_idots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], o); + } + + if (s->flags & 1) { + int x = positions[P][12][X]; + int y = positions[P][12][Y]; + + draw_idots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], o); + draw_idots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], o); + draw_idots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], o); + if (out->data[3]) + draw_idots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], o); + } + + if (s->flags & 2) { + int x = positions[P][13][X]; + int y = positions[P][13][Y]; + + draw_idots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], o); + draw_idots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], o); + draw_idots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], o); + if (out->data[3]) + draw_idots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], o); + } + + for (i = 0; i < 6 && s->flags & 4; i++) { + uint8_t color[4] = { 255, 255, 255, 255 }; + int x = positions[P][i][X]; + int y = positions[P][i][Y]; + + if (x > 128) + x += 8; + else + x -= 14; + if (y > 128) + y += 8; + else + y -= 14; + + x = av_clip(x, 0, out->width - 9); + y = av_clip(y, 0, out->height - 9); + draw_ihtext(out, x, y, o, 1. - o, positions_name[i], color); + } +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; @@ -1262,9 +1495,9 @@ return AVERROR(EINVAL); } - if (s->mode == GRAY && s->is_yuv) + if (s->mode == TINT && s->is_yuv) { s->pd = 0; - else { + } else { if ((s->x == 1 && s->y == 2) || (s->x == 2 && s->y == 1)) s->pd = 0; else if ((s->x == 0 && s->y == 2) || (s->x == 2 && s->y == 0)) @@ -1281,19 +1514,26 @@ s->graticulef = none_graticule; if (s->is_yuv && s->size == 256) { - if (s->graticule == 1) + if (s->graticule == GRAT_GREEN) s->graticulef = green_graticule; - else if (s->graticule == 2) + else if (s->graticule == GRAT_COLOR) s->graticulef = color_graticule; + else if (s->graticule == GRAT_INVERT) + s->graticulef = invert_graticule; } else if (s->is_yuv) { - if (s->graticule == 1) + if (s->graticule == GRAT_GREEN) s->graticulef = green_graticule16; - else if (s->graticule == 2) + else if (s->graticule == GRAT_COLOR) s->graticulef = color_graticule16; + else if (s->graticule == GRAT_INVERT) + s->graticulef = invert_graticule16; } s->bg_color[3] = s->bgopacity * (s->size - 1); + s->tint[0] = .5f * (s->ftint[0] + 1.f) * (s->size - 1); + s->tint[1] = .5f * (s->ftint[1] + 1.f) * (s->size - 1); + switch (inlink->format) { case AV_PIX_FMT_GBRP12: case AV_PIX_FMT_GBRP10: @@ -1306,8 +1546,8 @@ break; default: s->bg_color[0] = 0; - s->bg_color[1] = s->size / 2 - 1; - s->bg_color[2] = s->size / 2 - 1; + s->bg_color[1] = s->size / 2; + s->bg_color[2] = s->size / 2; } s->hsub = desc->log2_chroma_w; diff -Nru ffmpeg-4.2.2/libavfilter/vf_vflip.c ffmpeg-4.4/libavfilter/vf_vflip.c --- ffmpeg-4.2.2/libavfilter/vf_vflip.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_vflip.c 2021-04-08 21:28:40.000000000 +0000 @@ -33,6 +33,7 @@ typedef struct FlipContext { const AVClass *class; int vsub; ///< vertical chroma subsampling + int bayer; } FlipContext; static const AVOption vflip_options[] = { @@ -47,6 +48,7 @@ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); flip->vsub = desc->log2_chroma_h; + flip->bayer = !!(desc->flags & AV_PIX_FMT_FLAG_BAYER); return 0; } @@ -74,11 +76,43 @@ return frame; } +static int flip_bayer(AVFilterLink *link, AVFrame *in) +{ + AVFilterContext *ctx = link->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + uint8_t *inrow = in->data[0], *outrow; + int i, width = outlink->w << (av_pix_fmt_desc_get(link->format)->comp[0].step > 1); + if (outlink->h & 1) { + av_log(ctx, AV_LOG_ERROR, "Bayer vertical flip needs even height\n"); + return AVERROR_INVALIDDATA; + } + + 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); + outrow = out->data[0] + out->linesize[0] * (outlink->h - 2); + for (i = 0; i < outlink->h >> 1; i++) { + memcpy(outrow, inrow, width); + memcpy(outrow + out->linesize[0], inrow + in->linesize[0], width); + inrow += 2 * in->linesize[0]; + outrow -= 2 * out->linesize[0]; + } + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + static int filter_frame(AVFilterLink *link, AVFrame *frame) { FlipContext *flip = link->dst->priv; int i; + if (flip->bayer) + return flip_bayer(link, frame); + for (i = 0; i < 4; i ++) { int vsub = i == 1 || i == 2 ? flip->vsub : 0; int height = AV_CEIL_RSHIFT(link->h, vsub); diff -Nru ffmpeg-4.2.2/libavfilter/vf_vfrdet.c ffmpeg-4.4/libavfilter/vf_vfrdet.c --- ffmpeg-4.2.2/libavfilter/vf_vfrdet.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_vfrdet.c 2020-07-11 10:39:30.000000000 +0000 @@ -29,6 +29,7 @@ int64_t delta; int64_t min_delta; int64_t max_delta; + int64_t avg_delta; uint64_t vfr; uint64_t cfr; @@ -44,6 +45,8 @@ if (s->delta == AV_NOPTS_VALUE) { s->delta = delta; + s->min_delta = delta; + s->max_delta = delta; } if (s->delta != delta) { @@ -51,6 +54,7 @@ s->delta = delta; s->min_delta = FFMIN(delta, s->min_delta); s->max_delta = FFMAX(delta, s->max_delta); + s->avg_delta += delta; } else { s->cfr++; } @@ -79,7 +83,7 @@ av_log(ctx, AV_LOG_INFO, "VFR:%f (%"PRIu64"/%"PRIu64")", s->vfr / (float)(s->vfr + s->cfr), s->vfr, s->cfr); if (s->vfr) - av_log(ctx, AV_LOG_INFO, " min: %"PRId64" max: %"PRId64")", s->min_delta, s->max_delta); + av_log(ctx, AV_LOG_INFO, " min: %"PRId64" max: %"PRId64" avg: %"PRId64, s->min_delta, s->max_delta, s->avg_delta / s->vfr); av_log(ctx, AV_LOG_INFO, "\n"); } diff -Nru ffmpeg-4.2.2/libavfilter/vf_vibrance.c ffmpeg-4.4/libavfilter/vf_vibrance.c --- ffmpeg-4.2.2/libavfilter/vf_vibrance.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_vibrance.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,10 +21,15 @@ #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 + typedef struct VibranceContext { const AVClass *class; @@ -33,7 +38,9 @@ float lcoeffs[3]; int alternate; + int step; int depth; + uint8_t rgba_map[4]; int (*do_slice)(AVFilterContext *s, void *arg, int jobnr, int nb_jobs); @@ -160,6 +167,118 @@ return 0; } +static int vibrance_slice8p(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) +{ + VibranceContext *s = avctx->priv; + AVFrame *frame = arg; + const int step = s->step; + const int width = frame->width; + const int height = frame->height; + const float scale = 1.f / 255.f; + const float gc = s->lcoeffs[0]; + const float bc = s->lcoeffs[1]; + const float rc = s->lcoeffs[2]; + const uint8_t roffset = s->rgba_map[R]; + const uint8_t goffset = s->rgba_map[G]; + const uint8_t boffset = s->rgba_map[B]; + const float intensity = s->intensity; + const float alternate = s->alternate ? 1.f : -1.f; + const float gintensity = intensity * s->balance[0]; + const float bintensity = intensity * s->balance[1]; + const float rintensity = intensity * s->balance[2]; + const float sgintensity = alternate * FFSIGN(gintensity); + const float sbintensity = alternate * FFSIGN(bintensity); + const float srintensity = alternate * FFSIGN(rintensity); + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int linesize = frame->linesize[0]; + uint8_t *ptr = frame->data[0] + slice_start * linesize; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) { + float g = ptr[x * step + goffset] * scale; + float b = ptr[x * step + boffset] * scale; + float r = ptr[x * step + roffset] * scale; + float max_color = FFMAX3(r, g, b); + float min_color = FFMIN3(r, g, b); + float color_saturation = max_color - min_color; + float luma = g * gc + r * rc + b * bc; + const float cg = 1.f + gintensity * (1.f - sgintensity * color_saturation); + const float cb = 1.f + bintensity * (1.f - sbintensity * color_saturation); + const float cr = 1.f + rintensity * (1.f - srintensity * color_saturation); + + g = lerpf(luma, g, cg); + b = lerpf(luma, b, cb); + r = lerpf(luma, r, cr); + + ptr[x * step + goffset] = av_clip_uint8(g * 255.f); + ptr[x * step + boffset] = av_clip_uint8(b * 255.f); + ptr[x * step + roffset] = av_clip_uint8(r * 255.f); + } + + ptr += linesize; + } + + return 0; +} + +static int vibrance_slice16p(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) +{ + VibranceContext *s = avctx->priv; + AVFrame *frame = arg; + const int step = s->step; + const int depth = s->depth; + const float max = (1 << depth) - 1; + const float scale = 1.f / max; + const float gc = s->lcoeffs[0]; + const float bc = s->lcoeffs[1]; + const float rc = s->lcoeffs[2]; + const uint8_t roffset = s->rgba_map[R]; + const uint8_t goffset = s->rgba_map[G]; + const uint8_t boffset = s->rgba_map[B]; + const int width = frame->width; + const int height = frame->height; + const float intensity = s->intensity; + const float alternate = s->alternate ? 1.f : -1.f; + const float gintensity = intensity * s->balance[0]; + const float bintensity = intensity * s->balance[1]; + const float rintensity = intensity * s->balance[2]; + const float sgintensity = alternate * FFSIGN(gintensity); + const float sbintensity = alternate * FFSIGN(bintensity); + const float srintensity = alternate * FFSIGN(rintensity); + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int linesize = frame->linesize[0] / 2; + uint16_t *ptr = (uint16_t *)frame->data[0] + slice_start * linesize; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) { + float g = ptr[x * step + goffset] * scale; + float b = ptr[x * step + boffset] * scale; + float r = ptr[x * step + roffset] * scale; + float max_color = FFMAX3(r, g, b); + float min_color = FFMIN3(r, g, b); + float color_saturation = max_color - min_color; + float luma = g * gc + r * rc + b * bc; + const float cg = 1.f + gintensity * (1.f - sgintensity * color_saturation); + const float cb = 1.f + bintensity * (1.f - sbintensity * color_saturation); + const float cr = 1.f + rintensity * (1.f - srintensity * color_saturation); + + g = lerpf(luma, g, cg); + b = lerpf(luma, b, cb); + r = lerpf(luma, r, cr); + + ptr[x * step + goffset] = av_clip_uintp2_c(g * max, depth); + ptr[x * step + boffset] = av_clip_uintp2_c(b * max, depth); + ptr[x * step + roffset] = av_clip_uintp2_c(r * max, depth); + } + + ptr += linesize; + } + + return 0; +} + static int filter_frame(AVFilterLink *link, AVFrame *frame) { AVFilterContext *avctx = link->dst; @@ -176,10 +295,17 @@ static av_cold int query_formats(AVFilterContext *avctx) { 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_ARGB, AV_PIX_FMT_ABGR, + AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR, + AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48, + AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64, AV_PIX_FMT_NONE }; @@ -197,9 +323,21 @@ AVFilterContext *avctx = inlink->dst; VibranceContext *s = avctx->priv; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR; + + s->step = desc->nb_components; + if (inlink->format == AV_PIX_FMT_RGB0 || + inlink->format == AV_PIX_FMT_0RGB || + inlink->format == AV_PIX_FMT_BGR0 || + inlink->format == AV_PIX_FMT_0BGR) + s->step = 4; s->depth = desc->comp[0].depth; s->do_slice = s->depth <= 8 ? vibrance_slice8 : vibrance_slice16; + if (!planar) + s->do_slice = s->depth <= 8 ? vibrance_slice8p : vibrance_slice16p; + + ff_fill_rgba_map(s->rgba_map, inlink->format); return 0; } @@ -224,7 +362,7 @@ }; #define OFFSET(x) offsetof(VibranceContext, x) -#define VF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define VF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption vibrance_options[] = { { "intensity", "set the intensity value", OFFSET(intensity), AV_OPT_TYPE_FLOAT, {.dbl=0}, -2, 2, VF }, @@ -249,4 +387,5 @@ .inputs = vibrance_inputs, .outputs = vibrance_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_vif.c ffmpeg-4.4/libavfilter/vf_vif.c --- ffmpeg-4.2.2/libavfilter/vf_vif.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_vif.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,657 @@ +/* + * Copyright (c) 2017 Ronald S. Bultje + * Copyright (c) 2017 Ashish Pratap Singh + * 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 + */ + +/** + * @file + * Calculate VIF between two input videos. + */ + +#include + +#include "libavutil/avstring.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "framesync.h" +#include "drawutils.h" +#include "formats.h" +#include "internal.h" +#include "vif.h" +#include "video.h" + +typedef struct VIFContext { + const AVClass *class; + FFFrameSync fs; + const AVPixFmtDescriptor *desc; + int width; + int height; + int nb_threads; + float factor; + float *data_buf[13]; + float **temp; + float *ref_data; + float *main_data; + double vif_sum[4]; + double vif_min[4]; + double vif_max[4]; + uint64_t nb_frames; +} VIFContext; + +#define OFFSET(x) offsetof(VIFContext, x) + +static const AVOption vif_options[] = { + { NULL } +}; + +AVFILTER_DEFINE_CLASS(vif); + +static const uint8_t vif_filter1d_width1[4] = { 17, 9, 5, 3 }; + +static const float vif_filter1d_table[4][17] = +{ + { + 0.00745626912, 0.0142655009, 0.0250313189, 0.0402820669, 0.0594526194, + 0.0804751068, 0.0999041125, 0.113746084, 0.118773937, 0.113746084, + 0.0999041125, 0.0804751068, 0.0594526194, 0.0402820669, 0.0250313189, + 0.0142655009, 0.00745626912 + }, + { + 0.0189780835, 0.0558981746, 0.120920904, 0.192116052, 0.224173605, + 0.192116052, 0.120920904, 0.0558981746, 0.0189780835 + }, + { + 0.054488685, 0.244201347, 0.402619958, 0.244201347, 0.054488685 + }, + { + 0.166378498, 0.667243004, 0.166378498 + } +}; + +typedef struct ThreadData { + const float *filter; + const float *src; + float *dst; + int w, h; + int src_stride; + int dst_stride; + int filter_width; + float **temp; +} ThreadData; + +static void vif_dec2(const float *src, float *dst, int w, int h, + int src_stride, int dst_stride) +{ + const int dst_px_stride = dst_stride / 2; + + for (int i = 0; i < h / 2; i++) { + for (int j = 0; j < w / 2; j++) + dst[i * dst_px_stride + j] = src[(i * 2) * src_stride + (j * 2)]; + } +} + +static void vif_statistic(const float *mu1_sq, const float *mu2_sq, + const float *mu1_mu2, const float *xx_filt, + const float *yy_filt, const float *xy_filt, + float *num, float *den, int w, int h) +{ + static const float sigma_nsq = 2; + float mu1_sq_val, mu2_sq_val, mu1_mu2_val, xx_filt_val, yy_filt_val, xy_filt_val; + float sigma1_sq, sigma2_sq, sigma12, g, sv_sq, eps = 1.0e-10f; + float gain_limit = 100.f; + float num_val, den_val; + float accum_num = 0.0f; + float accum_den = 0.0f; + + for (int i = 0; i < h; i++) { + float accum_inner_num = 0.f; + float accum_inner_den = 0.f; + + for (int j = 0; j < w; j++) { + mu1_sq_val = mu1_sq[i * w + j]; + mu2_sq_val = mu2_sq[i * w + j]; + mu1_mu2_val = mu1_mu2[i * w + j]; + xx_filt_val = xx_filt[i * w + j]; + yy_filt_val = yy_filt[i * w + j]; + xy_filt_val = xy_filt[i * w + j]; + + sigma1_sq = xx_filt_val - mu1_sq_val; + sigma2_sq = yy_filt_val - mu2_sq_val; + sigma12 = xy_filt_val - mu1_mu2_val; + + sigma1_sq = FFMAX(sigma1_sq, 0.0f); + sigma2_sq = FFMAX(sigma2_sq, 0.0f); + sigma12 = FFMAX(sigma12, 0.0f); + + g = sigma12 / (sigma1_sq + eps); + sv_sq = sigma2_sq - g * sigma12; + + if (sigma1_sq < eps) { + g = 0.0f; + sv_sq = sigma2_sq; + sigma1_sq = 0.0f; + } + + if (sigma2_sq < eps) { + g = 0.0f; + sv_sq = 0.0f; + } + + if (g < 0.0f) { + sv_sq = sigma2_sq; + g = 0.0f; + } + sv_sq = FFMAX(sv_sq, eps); + + g = FFMIN(g, gain_limit); + + num_val = log2f(1.0f + g * g * sigma1_sq / (sv_sq + sigma_nsq)); + den_val = log2f(1.0f + sigma1_sq / sigma_nsq); + + if (isnan(den_val)) + num_val = den_val = 1.f; + + accum_inner_num += num_val; + accum_inner_den += den_val; + } + + accum_num += accum_inner_num; + accum_den += accum_inner_den; + } + + num[0] = accum_num; + den[0] = accum_den; +} + +static void vif_xx_yy_xy(const float *x, const float *y, float *xx, float *yy, + float *xy, int w, int h) +{ + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + float xval = x[j]; + float yval = y[j]; + float xxval = xval * xval; + float yyval = yval * yval; + float xyval = xval * yval; + + xx[j] = xxval; + yy[j] = yyval; + xy[j] = xyval; + } + + xx += w; + yy += w; + xy += w; + x += w; + y += w; + } +} + +static int vif_filter1d(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ThreadData *td = arg; + const float *filter = td->filter; + const float *src = td->src; + float *dst = td->dst; + int w = td->w; + int h = td->h; + int src_stride = td->src_stride; + int dst_stride = td->dst_stride; + int filt_w = td->filter_width; + float *temp = td->temp[jobnr]; + const int slice_start = (h * jobnr) / nb_jobs; + const int slice_end = (h * (jobnr+1)) / nb_jobs; + + for (int i = slice_start; i < slice_end; i++) { + /** Vertical pass. */ + for (int j = 0; j < w; j++) { + float sum = 0.f; + + if (i >= filt_w / 2 && i < h - filt_w / 2 - 1) { + for (int filt_i = 0; filt_i < filt_w; filt_i++) { + const float filt_coeff = filter[filt_i]; + float img_coeff; + int ii = i - filt_w / 2 + filt_i; + + img_coeff = src[ii * src_stride + j]; + sum += filt_coeff * img_coeff; + } + } else { + for (int filt_i = 0; filt_i < filt_w; filt_i++) { + const float filt_coeff = filter[filt_i]; + int ii = i - filt_w / 2 + filt_i; + float img_coeff; + + ii = ii < 0 ? -ii : (ii >= h ? 2 * h - ii - 1 : ii); + + img_coeff = src[ii * src_stride + j]; + sum += filt_coeff * img_coeff; + } + } + + temp[j] = sum; + } + + /** Horizontal pass. */ + for (int j = 0; j < w; j++) { + float sum = 0.f; + + if (j >= filt_w / 2 && j < w - filt_w / 2 - 1) { + for (int filt_j = 0; filt_j < filt_w; filt_j++) { + const float filt_coeff = filter[filt_j]; + int jj = j - filt_w / 2 + filt_j; + float img_coeff; + + img_coeff = temp[jj]; + sum += filt_coeff * img_coeff; + } + } else { + for (int filt_j = 0; filt_j < filt_w; filt_j++) { + const float filt_coeff = filter[filt_j]; + int jj = j - filt_w / 2 + filt_j; + float img_coeff; + + jj = jj < 0 ? -jj : (jj >= w ? 2 * w - jj - 1 : jj); + + img_coeff = temp[jj]; + sum += filt_coeff * img_coeff; + } + } + + dst[i * dst_stride + j] = sum; + } + } + + return 0; +} + +int ff_compute_vif2(AVFilterContext *ctx, + const float *ref, const float *main, int w, int h, + int ref_stride, int main_stride, float *score, + float *data_buf[14], float **temp, + int gnb_threads) +{ + ThreadData td; + float *ref_scale = data_buf[0]; + float *main_scale = data_buf[1]; + float *ref_sq = data_buf[2]; + float *main_sq = data_buf[3]; + float *ref_main = data_buf[4]; + float *mu1 = data_buf[5]; + float *mu2 = data_buf[6]; + float *mu1_sq = data_buf[7]; + float *mu2_sq = data_buf[8]; + float *mu1_mu2 = data_buf[9]; + float *ref_sq_filt = data_buf[10]; + float *main_sq_filt = data_buf[11]; + float *ref_main_filt = data_buf[12]; + + float *curr_ref_scale = (float *)ref; + float *curr_main_scale = (float *)main; + int curr_ref_stride = ref_stride; + int curr_main_stride = main_stride; + + float num = 0.f; + float den = 0.f; + + for (int scale = 0; scale < 4; scale++) { + const float *filter = vif_filter1d_table[scale]; + int filter_width = vif_filter1d_width1[scale]; + const int nb_threads = FFMIN(h, gnb_threads); + int buf_valid_w = w; + int buf_valid_h = h; + + td.filter = filter; + td.filter_width = filter_width; + + if (scale > 0) { + td.src = curr_ref_scale; + td.dst = mu1; + td.w = w; + td.h = h; + td.src_stride = curr_ref_stride; + td.dst_stride = w; + td.temp = temp; + ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads); + + td.src = curr_main_scale; + td.dst = mu2; + td.src_stride = curr_main_stride; + ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads); + + vif_dec2(mu1, ref_scale, buf_valid_w, buf_valid_h, w, w); + vif_dec2(mu2, main_scale, buf_valid_w, buf_valid_h, w, w); + + w = buf_valid_w / 2; + h = buf_valid_h / 2; + + buf_valid_w = w; + buf_valid_h = h; + + curr_ref_scale = ref_scale; + curr_main_scale = main_scale; + + curr_ref_stride = w; + curr_main_stride = w; + } + + td.src = curr_ref_scale; + td.dst = mu1; + td.w = w; + td.h = h; + td.src_stride = curr_ref_stride; + td.dst_stride = w; + td.temp = temp; + ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads); + + td.src = curr_main_scale; + td.dst = mu2; + td.src_stride = curr_main_stride; + ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads); + + vif_xx_yy_xy(mu1, mu2, mu1_sq, mu2_sq, mu1_mu2, w, h); + + vif_xx_yy_xy(curr_ref_scale, curr_main_scale, ref_sq, main_sq, ref_main, w, h); + + td.src = ref_sq; + td.dst = ref_sq_filt; + td.src_stride = w; + ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads); + + td.src = main_sq; + td.dst = main_sq_filt; + td.src_stride = w; + ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads); + + td.src = ref_main; + td.dst = ref_main_filt; + ctx->internal->execute(ctx, vif_filter1d, &td, NULL, nb_threads); + + vif_statistic(mu1_sq, mu2_sq, mu1_mu2, ref_sq_filt, main_sq_filt, + ref_main_filt, &num, &den, w, h); + + score[scale] = den <= FLT_EPSILON ? 1.f : num / den; + } + + return 0; +} + +#define offset_fn(type, bits) \ +static void offset_##bits##bit(VIFContext *s, \ + const AVFrame *ref, \ + AVFrame *main, int stride)\ +{ \ + int w = s->width; \ + int h = s->height; \ + \ + int ref_stride = ref->linesize[0]; \ + int main_stride = main->linesize[0]; \ + \ + const type *ref_ptr = (const type *) ref->data[0]; \ + const type *main_ptr = (const type *) main->data[0]; \ + \ + const float factor = s->factor; \ + \ + float *ref_ptr_data = s->ref_data; \ + float *main_ptr_data = s->main_data; \ + \ + for (int i = 0; i < h; i++) { \ + for (int j = 0; j < w; j++) { \ + ref_ptr_data[j] = ref_ptr[j] * factor - 128.f; \ + main_ptr_data[j] = main_ptr[j] * factor - 128.f; \ + } \ + ref_ptr += ref_stride / sizeof(type); \ + ref_ptr_data += w; \ + main_ptr += main_stride / sizeof(type); \ + main_ptr_data += w; \ + } \ +} + +offset_fn(uint8_t, 8) +offset_fn(uint16_t, 16) + +static void set_meta(AVDictionary **metadata, const char *key, float d) +{ + char value[257]; + snprintf(value, sizeof(value), "%f", d); + av_dict_set(metadata, key, value, 0); +} + +static AVFrame *do_vif(AVFilterContext *ctx, AVFrame *main, const AVFrame *ref) +{ + VIFContext *s = ctx->priv; + AVDictionary **metadata = &main->metadata; + float score[4]; + + s->factor = 1.f / (1 << (s->desc->comp[0].depth - 8)); + if (s->desc->comp[0].depth <= 8) { + offset_8bit(s, ref, main, s->width); + } else { + offset_16bit(s, ref, main, s->width); + } + + ff_compute_vif2(ctx, + s->ref_data, s->main_data, s->width, + s->height, s->width, s->width, + score, s->data_buf, s->temp, + s->nb_threads); + + set_meta(metadata, "lavfi.vif.scale.0", score[0]); + set_meta(metadata, "lavfi.vif.scale.1", score[1]); + set_meta(metadata, "lavfi.vif.scale.2", score[2]); + set_meta(metadata, "lavfi.vif.scale.3", score[3]); + + for (int i = 0; i < 4; i++) { + s->vif_min[i] = FFMIN(s->vif_min[i], score[i]); + s->vif_max[i] = FFMAX(s->vif_max[i], score[i]); + s->vif_sum[i] += score[i]; + } + + s->nb_frames++; + + return main; +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, + AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, +#define PF(suf) AV_PIX_FMT_YUV420##suf, AV_PIX_FMT_YUV422##suf, AV_PIX_FMT_YUV444##suf + PF(P9), PF(P10), PF(P12), PF(P14), PF(P16), + AV_PIX_FMT_NONE + }; + + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +static int config_input_ref(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + VIFContext *s = ctx->priv; + + if (ctx->inputs[0]->w != ctx->inputs[1]->w || + ctx->inputs[0]->h != ctx->inputs[1]->h) { + av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n"); + return AVERROR(EINVAL); + } + if (ctx->inputs[0]->format != ctx->inputs[1]->format) { + av_log(ctx, AV_LOG_ERROR, "Inputs must be of same pixel format.\n"); + return AVERROR(EINVAL); + } + + s->desc = av_pix_fmt_desc_get(inlink->format); + s->width = ctx->inputs[0]->w; + s->height = ctx->inputs[0]->h; + s->nb_threads = ff_filter_get_nb_threads(ctx); + + for (int i = 0; i < 4; i++) { + s->vif_min[i] = DBL_MAX; + s->vif_max[i] = -DBL_MAX; + } + + for (int i = 0; i < 13; i++) { + if (!(s->data_buf[i] = av_calloc(s->width, s->height * sizeof(float)))) + return AVERROR(ENOMEM); + } + + if (!(s->ref_data = av_calloc(s->width, s->height * sizeof(float)))) + return AVERROR(ENOMEM); + + if (!(s->main_data = av_calloc(s->width, s->height * sizeof(float)))) + return AVERROR(ENOMEM); + + if (!(s->temp = av_calloc(s->nb_threads, sizeof(s->temp[0])))) + return AVERROR(ENOMEM); + + for (int i = 0; i < s->nb_threads; i++) { + if (!(s->temp[i] = av_calloc(s->width, sizeof(float)))) + return AVERROR(ENOMEM); + } + + return 0; +} + +static int process_frame(FFFrameSync *fs) +{ + AVFilterContext *ctx = fs->parent; + VIFContext *s = fs->opaque; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out_frame, *main_frame = NULL, *ref_frame = NULL; + int ret; + + ret = ff_framesync_dualinput_get(fs, &main_frame, &ref_frame); + if (ret < 0) + return ret; + + if (ctx->is_disabled || !ref_frame) { + out_frame = main_frame; + } else { + out_frame = do_vif(ctx, main_frame, ref_frame); + } + + out_frame->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); + + return ff_filter_frame(outlink, out_frame); +} + + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + VIFContext *s = ctx->priv; + AVFilterLink *mainlink = ctx->inputs[0]; + FFFrameSyncIn *in; + int ret; + + outlink->w = mainlink->w; + outlink->h = mainlink->h; + outlink->time_base = mainlink->time_base; + outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio; + outlink->frame_rate = mainlink->frame_rate; + if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0) + return ret; + + in = s->fs.in; + in[0].time_base = mainlink->time_base; + in[1].time_base = ctx->inputs[1]->time_base; + in[0].sync = 2; + in[0].before = EXT_STOP; + in[0].after = EXT_STOP; + in[1].sync = 1; + in[1].before = EXT_STOP; + in[1].after = EXT_STOP; + s->fs.opaque = s; + s->fs.on_event = process_frame; + + return ff_framesync_configure(&s->fs); +} + +static int activate(AVFilterContext *ctx) +{ + VIFContext *s = ctx->priv; + return ff_framesync_activate(&s->fs); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + VIFContext *s = ctx->priv; + + if (s->nb_frames > 0) { + for (int i = 0; i < 4; i++) + av_log(ctx, AV_LOG_INFO, "VIF scale=%d average:%f min:%f: max:%f\n", + i, s->vif_sum[i] / s->nb_frames, s->vif_min[i], s->vif_max[i]); + } + + for (int i = 0; i < 13; i++) + av_freep(&s->data_buf[i]); + + av_freep(&s->ref_data); + av_freep(&s->main_data); + + for (int i = 0; i < s->nb_threads && s->temp; i++) + av_freep(&s->temp[i]); + + av_freep(&s->temp); + + ff_framesync_uninit(&s->fs); +} + +static const AVFilterPad vif_inputs[] = { + { + .name = "main", + .type = AVMEDIA_TYPE_VIDEO, + },{ + .name = "reference", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input_ref, + }, + { NULL } +}; + +static const AVFilterPad vif_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vf_vif = { + .name = "vif", + .description = NULL_IF_CONFIG_SMALL("Calculate the VIF between two video streams."), + .uninit = uninit, + .query_formats = query_formats, + .priv_size = sizeof(VIFContext), + .priv_class = &vif_class, + .activate = activate, + .inputs = vif_inputs, + .outputs = vif_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_vignette.c ffmpeg-4.4/libavfilter/vf_vignette.c --- ffmpeg-4.2.2/libavfilter/vf_vignette.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_vignette.c 2021-04-08 21:28:40.000000000 +0000 @@ -155,9 +155,6 @@ } } -#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) -#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts) * av_q2d(tb)) - static void update_context(VignetteContext *s, AVFilterLink *inlink, AVFrame *frame) { int x, y; diff -Nru ffmpeg-4.2.2/libavfilter/vf_vmafmotion.c ffmpeg-4.4/libavfilter/vf_vmafmotion.c --- ffmpeg-4.2.2/libavfilter/vf_vmafmotion.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_vmafmotion.c 2020-07-11 10:39:30.000000000 +0000 @@ -176,8 +176,8 @@ } \ } -conv_y_fn(uint8_t, 8); -conv_y_fn(uint16_t, 10); +conv_y_fn(uint8_t, 8) +conv_y_fn(uint16_t, 10) static void vmafmotiondsp_init(VMAFMotionDSPContext *dsp, int bpp) { dsp->convolution_x = convolution_x; diff -Nru ffmpeg-4.2.2/libavfilter/vf_vpp_qsv.c ffmpeg-4.4/libavfilter/vf_vpp_qsv.c --- ffmpeg-4.2.2/libavfilter/vf_vpp_qsv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_vpp_qsv.c 2021-04-08 21:28:40.000000000 +0000 @@ -36,12 +36,15 @@ #include "libavformat/avformat.h" #include "qsvvpp.h" +#include "transpose.h" #define OFFSET(x) offsetof(VPPContext, x) #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) /* number of video enhancement filters */ -#define ENH_FILTERS_COUNT (5) +#define ENH_FILTERS_COUNT (7) +#define QSV_HAVE_ROTATION QSV_VERSION_ATLEAST(1, 17) +#define QSV_HAVE_MIRRORING QSV_VERSION_ATLEAST(1, 19) typedef struct VPPContext{ const AVClass *class; @@ -54,6 +57,8 @@ mfxExtVPPDenoise denoise_conf; mfxExtVPPDetail detail_conf; mfxExtVPPProcAmp procamp_conf; + mfxExtVPPRotation rotation_conf; + mfxExtVPPMirroring mirroring_conf; int out_width; int out_height; @@ -74,6 +79,10 @@ int crop_x; int crop_y; + int transpose; + int rotate; /* rotate angle : [0, 90, 180, 270] */ + int hflip; /* flip mode : 0 = off, 1 = HORIZONTAL flip */ + /* param for the procamp */ int procamp; /* enable procamp */ float hue; @@ -100,10 +109,19 @@ { "contrast", "ProcAmp contrast", OFFSET(contrast), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 }, 0.0, 10.0, .flags = FLAGS}, { "brightness", "ProcAmp brightness", OFFSET(brightness), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, -100.0, 100.0, .flags = FLAGS}, - { "cw", "set the width crop area expression", OFFSET(cw), AV_OPT_TYPE_STRING, { .str = "iw" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "ch", "set the height crop area expression", OFFSET(ch), AV_OPT_TYPE_STRING, { .str = "ih" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "cx", "set the x crop area expression", OFFSET(cx), AV_OPT_TYPE_STRING, { .str = "(in_w-out_w)/2" }, CHAR_MIN, CHAR_MAX, FLAGS }, - { "cy", "set the y crop area expression", OFFSET(cy), AV_OPT_TYPE_STRING, { .str = "(in_h-out_h)/2" }, CHAR_MIN, CHAR_MAX, FLAGS }, + { "transpose", "set transpose direction", OFFSET(transpose), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 6, FLAGS, "transpose"}, + { "cclock_hflip", "rotate counter-clockwise with horizontal flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "transpose" }, + { "clock", "rotate clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK }, .flags=FLAGS, .unit = "transpose" }, + { "cclock", "rotate counter-clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK }, .flags=FLAGS, .unit = "transpose" }, + { "clock_hflip", "rotate clockwise with horizontal flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP }, .flags=FLAGS, .unit = "transpose" }, + { "reversal", "rotate by half-turn", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_REVERSAL }, .flags=FLAGS, .unit = "transpose" }, + { "hflip", "flip horizontally", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_HFLIP }, .flags=FLAGS, .unit = "transpose" }, + { "vflip", "flip vertically", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_VFLIP }, .flags=FLAGS, .unit = "transpose" }, + + { "cw", "set the width crop area expression", OFFSET(cw), AV_OPT_TYPE_STRING, { .str = "iw" }, 0, 0, FLAGS }, + { "ch", "set the height crop area expression", OFFSET(ch), AV_OPT_TYPE_STRING, { .str = "ih" }, 0, 0, FLAGS }, + { "cx", "set the x crop area expression", OFFSET(cx), AV_OPT_TYPE_STRING, { .str = "(in_w-out_w)/2" }, 0, 0, FLAGS }, + { "cy", "set the y crop area expression", OFFSET(cy), AV_OPT_TYPE_STRING, { .str = "(in_h-out_h)/2" }, 0, 0, FLAGS }, { "w", "Output video width", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, { "width", "Output video width", OFFSET(ow), AV_OPT_TYPE_STRING, { .str="cw" }, 0, 255, .flags = FLAGS }, @@ -294,7 +312,9 @@ } else in_format = inlink->format; - param.out_sw_format = (vpp->out_format == AV_PIX_FMT_NONE) ? in_format : vpp->out_format; + if (vpp->out_format == AV_PIX_FMT_NONE) + vpp->out_format = in_format; + param.out_sw_format = vpp->out_format; if (vpp->use_crop) { crop.in_idx = 0; @@ -356,8 +376,87 @@ param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->procamp_conf; } + if (vpp->transpose >= 0) { +#ifdef QSV_HAVE_ROTATION + switch (vpp->transpose) { + case TRANSPOSE_CCLOCK_FLIP: + vpp->rotate = MFX_ANGLE_270; + vpp->hflip = MFX_MIRRORING_HORIZONTAL; + break; + case TRANSPOSE_CLOCK: + vpp->rotate = MFX_ANGLE_90; + vpp->hflip = MFX_MIRRORING_DISABLED; + break; + case TRANSPOSE_CCLOCK: + vpp->rotate = MFX_ANGLE_270; + vpp->hflip = MFX_MIRRORING_DISABLED; + break; + case TRANSPOSE_CLOCK_FLIP: + vpp->rotate = MFX_ANGLE_90; + vpp->hflip = MFX_MIRRORING_HORIZONTAL; + break; + case TRANSPOSE_REVERSAL: + vpp->rotate = MFX_ANGLE_180; + vpp->hflip = MFX_MIRRORING_DISABLED; + break; + case TRANSPOSE_HFLIP: + vpp->rotate = MFX_ANGLE_0; + vpp->hflip = MFX_MIRRORING_HORIZONTAL; + break; + case TRANSPOSE_VFLIP: + vpp->rotate = MFX_ANGLE_180; + vpp->hflip = MFX_MIRRORING_HORIZONTAL; + break; + default: + av_log(ctx, AV_LOG_ERROR, "Failed to set transpose mode to %d.\n", vpp->transpose); + return AVERROR(EINVAL); + } +#else + av_log(ctx, AV_LOG_WARNING, "The QSV VPP transpose option is " + "not supported with this MSDK version.\n"); + vpp->transpose = 0; +#endif + } + + if (vpp->rotate) { +#ifdef QSV_HAVE_ROTATION + memset(&vpp->rotation_conf, 0, sizeof(mfxExtVPPRotation)); + vpp->rotation_conf.Header.BufferId = MFX_EXTBUFF_VPP_ROTATION; + vpp->rotation_conf.Header.BufferSz = sizeof(mfxExtVPPRotation); + vpp->rotation_conf.Angle = vpp->rotate; + + if (MFX_ANGLE_90 == vpp->rotate || MFX_ANGLE_270 == vpp->rotate) { + FFSWAP(int, vpp->out_width, vpp->out_height); + FFSWAP(int, outlink->w, outlink->h); + av_log(ctx, AV_LOG_DEBUG, "Swap width and height for clock/cclock rotation.\n"); + } + + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->rotation_conf; +#else + av_log(ctx, AV_LOG_WARNING, "The QSV VPP rotate option is " + "not supported with this MSDK version.\n"); + vpp->rotate = 0; +#endif + } + + if (vpp->hflip) { +#ifdef QSV_HAVE_MIRRORING + memset(&vpp->mirroring_conf, 0, sizeof(mfxExtVPPMirroring)); + vpp->mirroring_conf.Header.BufferId = MFX_EXTBUFF_VPP_MIRRORING; + vpp->mirroring_conf.Header.BufferSz = sizeof(mfxExtVPPMirroring); + vpp->mirroring_conf.Type = vpp->hflip; + + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->mirroring_conf; +#else + av_log(ctx, AV_LOG_WARNING, "The QSV VPP hflip option is " + "not supported with this MSDK version.\n"); + vpp->hflip = 0; +#endif + } + if (vpp->use_frc || vpp->use_crop || vpp->deinterlace || vpp->denoise || - vpp->detail || vpp->procamp || inlink->w != outlink->w || inlink->h != outlink->h) + vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip || + inlink->w != outlink->w || inlink->h != outlink->h || in_format != vpp->out_format) return ff_qsvvpp_create(ctx, &vpp->qsv, ¶m); else { av_log(ctx, AV_LOG_VERBOSE, "qsv vpp pass through mode.\n"); @@ -390,7 +489,6 @@ static int query_formats(AVFilterContext *ctx) { int ret; - AVFilterFormats *in_fmts, *out_fmts; static const enum AVPixelFormat in_pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NV12, @@ -406,16 +504,12 @@ AV_PIX_FMT_NONE }; - in_fmts = ff_make_format_list(in_pix_fmts); - out_fmts = ff_make_format_list(out_pix_fmts); - ret = ff_formats_ref(in_fmts, &ctx->inputs[0]->out_formats); - if (ret < 0) - return ret; - ret = ff_formats_ref(out_fmts, &ctx->outputs[0]->in_formats); + ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), + &ctx->inputs[0]->outcfg.formats); if (ret < 0) return ret; - - return 0; + return ff_formats_ref(ff_make_format_list(out_pix_fmts), + &ctx->outputs[0]->incfg.formats); } static av_cold void vpp_uninit(AVFilterContext *ctx) diff -Nru ffmpeg-4.2.2/libavfilter/vf_w3fdif.c ffmpeg-4.4/libavfilter/vf_w3fdif.c --- ffmpeg-4.2.2/libavfilter/vf_w3fdif.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_w3fdif.c 2021-04-08 21:28:40.000000000 +0000 @@ -34,6 +34,8 @@ typedef struct W3FDIFContext { const AVClass *class; int filter; ///< 0 is simple, 1 is more complex + int mode; ///< 0 is frame, 1 is field + int parity; ///< frame field parity int deint; ///< which frames to deinterlace int linesize[4]; ///< bytes of pixel data per line for each plane int planeheight[4]; ///< height of each plane @@ -49,13 +51,20 @@ } W3FDIFContext; #define OFFSET(x) offsetof(W3FDIFContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM #define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, 0, 0, FLAGS, unit } static const AVOption w3fdif_options[] = { { "filter", "specify the filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "filter" }, CONST("simple", NULL, 0, "filter"), CONST("complex", NULL, 1, "filter"), + { "mode", "specify the interlacing mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "mode"}, + CONST("frame", "send one frame for each frame", 0, "mode"), + CONST("field", "send one frame for each field", 1, "mode"), + { "parity", "specify the assumed picture field parity", OFFSET(parity), AV_OPT_TYPE_INT, {.i64=-1}, -1, 1, FLAGS, "parity" }, + CONST("tff", "assume top field first", 0, "parity"), + CONST("bff", "assume bottom field first", 1, "parity"), + CONST("auto", "auto detect parity", -1, "parity"), { "deint", "specify which frames to deinterlace", OFFSET(deint), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "deint" }, CONST("all", "deinterlace all frames", 0, "deint"), CONST("interlaced", "only deinterlace frames marked as interlaced", 1, "deint"), @@ -76,11 +85,19 @@ AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, 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_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, - AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; @@ -274,6 +291,11 @@ s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); s->planeheight[0] = s->planeheight[3] = inlink->h; + if (inlink->h < 3) { + av_log(ctx, AV_LOG_ERROR, "Video of less than 3 lines is not supported\n"); + return AVERROR(EINVAL); + } + s->nb_planes = av_pix_fmt_count_planes(inlink->format); s->nb_threads = ff_filter_get_nb_threads(ctx); s->work_line = av_calloc(s->nb_threads, sizeof(*s->work_line)); @@ -337,17 +359,16 @@ typedef struct ThreadData { AVFrame *out, *cur, *adj; - int plane; } ThreadData; -static int deinterlace_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +static int deinterlace_plane_slice(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs, int plane) { W3FDIFContext *s = ctx->priv; ThreadData *td = arg; AVFrame *out = td->out; AVFrame *cur = td->cur; AVFrame *adj = td->adj; - const int plane = td->plane; const int filter = s->filter; uint8_t *in_line, *in_lines_cur[5], *in_lines_adj[5]; uint8_t *out_line, *out_pixel; @@ -363,10 +384,13 @@ const int start = (height * jobnr) / nb_jobs; const int end = (height * (jobnr+1)) / nb_jobs; const int max = s->max; + const int interlaced = cur->interlaced_frame; + const int tff = s->field == (s->parity == -1 ? interlaced ? cur->top_field_first : 1 : + s->parity ^ 1); int j, y_in, y_out; /* copy unchanged the lines of the field */ - y_out = start + ((s->field == cur->top_field_first) ^ (start & 1)); + y_out = start + (tff ^ (start & 1)); in_line = cur_data + (y_out * cur_line_stride); out_line = dst_data + (y_out * dst_line_stride); @@ -379,7 +403,7 @@ } /* interpolate other lines of the field */ - y_out = start + ((s->field != cur->top_field_first) ^ (start & 1)); + y_out = start + ((!tff) ^ (start & 1)); out_line = dst_data + (y_out * dst_line_stride); @@ -445,13 +469,23 @@ return 0; } +static int deinterlace_slice(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + W3FDIFContext *s = ctx->priv; + + for (int p = 0; p < s->nb_planes; p++) + deinterlace_plane_slice(ctx, arg, jobnr, nb_jobs, p); + + return 0; +} + static int filter(AVFilterContext *ctx, int is_second) { W3FDIFContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out, *adj; ThreadData td; - int plane; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) @@ -475,12 +509,10 @@ adj = s->field ? s->next : s->prev; td.out = out; td.cur = s->cur; td.adj = adj; - for (plane = 0; plane < s->nb_planes; plane++) { - td.plane = plane; - ctx->internal->execute(ctx, deinterlace_slice, &td, NULL, FFMIN(s->planeheight[plane], s->nb_threads)); - } + ctx->internal->execute(ctx, deinterlace_slice, &td, NULL, FFMIN(s->planeheight[1], s->nb_threads)); - s->field = !s->field; + if (s->mode) + s->field = !s->field; return ff_filter_frame(outlink, out); } @@ -517,7 +549,7 @@ return 0; ret = filter(ctx, 0); - if (ret < 0) + if (ret < 0 || s->mode == 0) return ret; return filter(ctx, 1); @@ -593,4 +625,5 @@ .inputs = w3fdif_inputs, .outputs = w3fdif_outputs, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_waveform.c ffmpeg-4.4/libavfilter/vf_waveform.c --- ffmpeg-4.2.2/libavfilter/vf_waveform.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_waveform.c 2021-04-08 21:28:40.000000000 +0000 @@ -45,6 +45,7 @@ COLOR, ACOLOR, XFLAT, + YFLAT, NB_FILTERS }; @@ -62,6 +63,14 @@ NB_SCALES }; +enum GraticuleType { + GRAT_NONE, + GRAT_GREEN, + GRAT_ORANGE, + GRAT_INVERT, + NB_GRATICULES +}; + typedef struct GraticuleLine { const char *name; uint16_t pos; @@ -103,10 +112,17 @@ GraticuleLines *glines; int nb_glines; int rgb; + float ftint[2]; + int tint[2]; int (*waveform_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); void (*graticulef)(struct WaveformContext *s, AVFrame *out); + void (*blend_line)(uint8_t *dst, int size, int linesize, float o1, float o2, + int v, int step); + void (*draw_text)(AVFrame *out, int x, int y, int mult, + float o1, float o2, const char *txt, + const uint8_t color[4]); const AVPixFmtDescriptor *desc; const AVPixFmtDescriptor *odesc; } WaveformContext; @@ -145,11 +161,13 @@ { "color", NULL, 0, AV_OPT_TYPE_CONST, {.i64=COLOR}, 0, 0, FLAGS, "filter" }, { "acolor", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ACOLOR}, 0, 0, FLAGS, "filter" }, { "xflat", NULL, 0, AV_OPT_TYPE_CONST, {.i64=XFLAT}, 0, 0, FLAGS, "filter" }, - { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule" }, - { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule" }, - { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "graticule" }, - { "green", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "graticule" }, - { "orange", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "graticule" }, + { "yflat", NULL, 0, AV_OPT_TYPE_CONST, {.i64=YFLAT}, 0, 0, FLAGS, "filter" }, + { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_GRATICULES-1, FLAGS, "graticule" }, + { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_GRATICULES-1, FLAGS, "graticule" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_NONE}, 0, 0, FLAGS, "graticule" }, + { "green", NULL, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_GREEN}, 0, 0, FLAGS, "graticule" }, + { "orange", NULL, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_ORANGE}, 0, 0, FLAGS, "graticule" }, + { "invert", NULL, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_INVERT}, 0, 0, FLAGS, "graticule" }, { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, { "o", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, FLAGS, "flags" }, @@ -163,6 +181,10 @@ { "ire", NULL, 0, AV_OPT_TYPE_CONST, {.i64=IRE}, 0, 0, FLAGS, "scale" }, { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, + { "tint0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, + { "t0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, + { "tint1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, + { "t1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, { NULL } }; @@ -183,6 +205,7 @@ AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_NONE }; @@ -200,6 +223,7 @@ AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_NONE }; @@ -215,6 +239,7 @@ AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_NONE }; @@ -254,7 +279,7 @@ }; static const enum AVPixelFormat out_yuv12_lowpass_pix_fmts[] = { - AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_NONE }; @@ -278,24 +303,17 @@ AV_PIX_FMT_NONE }; -static const enum AVPixelFormat flat_pix_fmts[] = { - AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, - AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, - AV_PIX_FMT_YUV444P12, - AV_PIX_FMT_NONE -}; - static int query_formats(AVFilterContext *ctx) { WaveformContext *s = ctx->priv; const enum AVPixelFormat *out_pix_fmts; const enum AVPixelFormat *in_pix_fmts; - const AVPixFmtDescriptor *desc; - AVFilterFormats *avff; - int depth, rgb, i, ret, ncomp; + const AVPixFmtDescriptor *desc, *desc2; + AVFilterFormats *avff, *avff2; + int depth, depth2, rgb, i, ret, ncomp, ncomp2; - if (!ctx->inputs[0]->in_formats || - !ctx->inputs[0]->in_formats->nb_formats) { + if (!ctx->inputs[0]->incfg.formats || + !ctx->inputs[0]->incfg.formats->nb_formats) { return AVERROR(EAGAIN); } @@ -303,6 +321,7 @@ case LOWPASS: in_pix_fmts = in_lowpass_pix_fmts; break; case CHROMA: case XFLAT: + case YFLAT: case AFLAT: case FLAT: in_pix_fmts = in_flat_pix_fmts; break; case ACOLOR: @@ -310,16 +329,22 @@ default: return AVERROR_BUG; } - if (!ctx->inputs[0]->out_formats) { - if ((ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), &ctx->inputs[0]->out_formats)) < 0) + if (!ctx->inputs[0]->outcfg.formats) { + if ((ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), &ctx->inputs[0]->outcfg.formats)) < 0) return ret; } - avff = ctx->inputs[0]->in_formats; + avff = ctx->inputs[0]->incfg.formats; + avff2 = ctx->inputs[0]->outcfg.formats; desc = av_pix_fmt_desc_get(avff->formats[0]); + desc2 = av_pix_fmt_desc_get(avff2->formats[0]); ncomp = desc->nb_components; + ncomp2 = desc2->nb_components; rgb = desc->flags & AV_PIX_FMT_FLAG_RGB; depth = desc->comp[0].depth; + depth2 = desc2->comp[0].depth; + if (ncomp != ncomp2 || depth != depth2) + return AVERROR(EAGAIN); for (i = 1; i < avff->nb_formats; i++) { desc = av_pix_fmt_desc_get(avff->formats[i]); if (rgb != (desc->flags & AV_PIX_FMT_FLAG_RGB) || @@ -353,7 +378,7 @@ out_pix_fmts = out_yuv12_lowpass_pix_fmts; else return AVERROR(EAGAIN); - if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats)) < 0) + if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->incfg.formats)) < 0) return ret; return 0; @@ -655,10 +680,11 @@ int jobnr, int nb_jobs) { const int plane = s->desc->comp[component].plane; + const int dplane = (s->rgb || s->display == OVERLAY) ? plane : 0; const int shift_w = s->shift_w[component]; const int shift_h = s->shift_h[component]; const int src_linesize = in->linesize[plane] / 2; - const int dst_linesize = out->linesize[plane] / 2; + const int dst_linesize = out->linesize[dplane] / 2; const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1); const int limit = s->max - 1; const int max = limit - intensity; @@ -670,7 +696,7 @@ const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w; const int step = column ? 1 << shift_w : 1 << shift_h; const uint16_t *src_data = (const uint16_t *)in->data[plane] + sliceh_start * src_linesize; - uint16_t *dst_data = (uint16_t *)out->data[plane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x; + uint16_t *dst_data = (uint16_t *)out->data[dplane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x; uint16_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1); uint16_t * const dst_line = (mirror ? dst_bottom_line : dst_data); const uint16_t *p; @@ -707,6 +733,56 @@ src_data += src_linesize; dst_data += dst_linesize * step; } + + if (s->display != OVERLAY && column && !s->rgb) { + const int mult = s->max / 256; + const int bg = s->bg_color[0] * mult; + const int t0 = s->tint[0]; + const int t1 = s->tint[1]; + uint16_t *dst0, *dst1; + const uint16_t *src; + int x; + + src = (const uint16_t *)(out->data[0]) + offset_y * dst_linesize + offset_x; + dst0 = (uint16_t *)(out->data[1]) + offset_y * dst_linesize + offset_x; + dst1 = (uint16_t *)(out->data[2]) + offset_y * dst_linesize + offset_x; + for (y = 0; y < s->max; y++) { + for (x = slicew_start * step; x < slicew_end * step; x++) { + if (src[x] != bg) { + dst0[x] = t0; + dst1[x] = t1; + } + } + + src += dst_linesize; + dst0 += dst_linesize; + dst1 += dst_linesize; + } + } else if (s->display != OVERLAY && !s->rgb) { + const int mult = s->max / 256; + const int bg = s->bg_color[0] * mult; + const int t0 = s->tint[0]; + const int t1 = s->tint[1]; + uint16_t *dst0, *dst1; + const uint16_t *src; + int x; + + src = (const uint16_t *)out->data[0] + (offset_y + sliceh_start * step) * dst_linesize + offset_x; + dst0 = (uint16_t *)(out->data[1]) + (offset_y + sliceh_start * step) * dst_linesize + offset_x; + dst1 = (uint16_t *)(out->data[2]) + (offset_y + sliceh_start * step) * dst_linesize + offset_x; + for (y = sliceh_start * step; y < sliceh_end * step; y++) { + for (x = 0; x < s->max; x++) { + if (src[x] != bg) { + dst0[x] = t0; + dst1[x] = t1; + } + } + + src += dst_linesize; + dst0 += dst_linesize; + dst1 += dst_linesize; + } + } } #define LOWPASS16_FUNC(name, column, mirror) \ @@ -742,10 +818,11 @@ int jobnr, int nb_jobs) { const int plane = s->desc->comp[component].plane; + const int dplane = (s->rgb || s->display == OVERLAY) ? plane : 0; const int shift_w = s->shift_w[component]; const int shift_h = s->shift_h[component]; const int src_linesize = in->linesize[plane]; - const int dst_linesize = out->linesize[plane]; + const int dst_linesize = out->linesize[dplane]; const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1); const int max = 255 - intensity; const int src_h = AV_CEIL_RSHIFT(in->height, shift_h); @@ -756,7 +833,7 @@ const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w; const int step = column ? 1 << shift_w : 1 << shift_h; const uint8_t *src_data = in->data[plane] + sliceh_start * src_linesize; - uint8_t *dst_data = out->data[plane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x; + uint8_t *dst_data = out->data[dplane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x; uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1); uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data); const uint8_t *p; @@ -771,48 +848,76 @@ for (p = src_data + slicew_start; p < src_data_end; p++) { uint8_t *target; + int i = 0; + if (column) { - target = dst + dst_signed_linesize * *p; - dst += step; - update(target, max, intensity); + do { + target = dst++ + dst_signed_linesize * *p; + update(target, max, intensity); + } while (++i < step); } else { uint8_t *row = dst_data; - if (mirror) - target = row - *p - 1; - else - target = row + *p; - update(target, max, intensity); - row += dst_linesize; + do { + if (mirror) + target = row - *p - 1; + else + target = row + *p; + update(target, max, intensity); + row += dst_linesize; + } while (++i < step); } } src_data += src_linesize; dst_data += dst_linesize * step; } - if (column && step > 1) { + if (s->display != OVERLAY && column && !s->rgb) { + const int bg = s->bg_color[0]; const int dst_h = 256; - uint8_t *dst; - int x, z; - - dst = out->data[plane] + offset_y * dst_linesize + offset_x; + const int t0 = s->tint[0]; + const int t1 = s->tint[1]; + uint8_t *dst0, *dst1; + const uint8_t *src; + int x; + + src = out->data[0] + offset_y * dst_linesize + offset_x; + dst0 = out->data[1] + offset_y * dst_linesize + offset_x; + dst1 = out->data[2] + offset_y * dst_linesize + offset_x; for (y = 0; y < dst_h; y++) { - for (x = slicew_start * step; x < slicew_end * step; x+=step) { - for (z = 1; z < step; z++) { - dst[x + z] = dst[x]; + for (x = slicew_start * step; x < slicew_end * step; x++) { + if (src[x] != bg) { + dst0[x] = t0; + dst1[x] = t1; } } - dst += dst_linesize; + + src += dst_linesize; + dst0 += dst_linesize; + dst1 += dst_linesize; } - } else if (step > 1) { + } else if (s->display != OVERLAY && !s->rgb) { + const int bg = s->bg_color[0]; const int dst_w = 256; - uint8_t *dst; - int z; + const int t0 = s->tint[0]; + const int t1 = s->tint[1]; + uint8_t *dst0, *dst1; + const uint8_t *src; + int x; + + src = out->data[0] + (offset_y + sliceh_start * step) * dst_linesize + offset_x; + dst0 = out->data[1] + (offset_y + sliceh_start * step) * dst_linesize + offset_x; + dst1 = out->data[2] + (offset_y + sliceh_start * step) * dst_linesize + offset_x; + for (y = sliceh_start * step; y < sliceh_end * step; y++) { + for (x = 0; x < dst_w; x++) { + if (src[x] != bg) { + dst0[x] = t0; + dst1[x] = t1; + } + } - dst = out->data[plane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x; - for (y = sliceh_start * step; y < sliceh_end * step; y+=step) { - for (z = 1; z < step; z++) - memcpy(dst + dst_linesize * z, dst, dst_w); - dst += dst_linesize * step; + src += dst_linesize; + dst0 += dst_linesize; + dst1 += dst_linesize; } } } @@ -1118,7 +1223,7 @@ FLAT_FUNC(row_mirror, 0, 1) FLAT_FUNC(row, 0, 0) -#define AFLAT16(name, update_cr, column, mirror) \ +#define AFLAT16(name, update_cb, update_cr, column, mirror) \ static int name(AVFilterContext *ctx, \ void *arg, int jobnr, \ int nb_jobs) \ @@ -1184,7 +1289,7 @@ update16(target, max, intensity, limit); \ \ target = d1 + x + d1_signed_linesize * (c0 + c1); \ - update16(target, max, intensity, limit); \ + update_cb(target, max, intensity, limit); \ \ target = d2 + x + d2_signed_linesize * (c0 + c2); \ update_cr(target, max, intensity, limit); \ @@ -1225,14 +1330,14 @@ target = d0_data - c0; \ update16(target, max, intensity, limit); \ target = d1_data - (c0 + c1); \ - update16(target, max, intensity, limit); \ + update_cb(target, max, intensity, limit); \ target = d2_data - (c0 + c2); \ update_cr(target, max, intensity, limit); \ } else { \ target = d0_data + c0; \ update16(target, max, intensity, limit); \ target = d1_data + (c0 + c1); \ - update16(target, max, intensity, limit); \ + update_cb(target, max, intensity, limit); \ target = d2_data + (c0 + c2); \ update_cr(target, max, intensity, limit); \ } \ @@ -1252,7 +1357,7 @@ return 0; \ } -#define AFLAT(name, update_cr, column, mirror) \ +#define AFLAT(name, update_cb, update_cr, column, mirror) \ static int name(AVFilterContext *ctx, \ void *arg, int jobnr, \ int nb_jobs) \ @@ -1316,7 +1421,7 @@ update(target, max, intensity); \ \ target = d1 + x + d1_signed_linesize * (c0 + c1); \ - update(target, max, intensity); \ + update_cb(target, max, intensity); \ \ target = d2 + x + d2_signed_linesize * (c0 + c2); \ update_cr(target, max, intensity); \ @@ -1325,8 +1430,8 @@ c0_data += c0_linesize; \ if (!c1_shift_h || (y & c1_shift_h)) \ c1_data += c1_linesize; \ - if (!c1_shift_h || (y & c1_shift_h)) \ - c2_data += c1_linesize; \ + if (!c2_shift_h || (y & c2_shift_h)) \ + c2_data += c2_linesize; \ d0_data += d0_linesize; \ d1_data += d1_linesize; \ d2_data += d2_linesize; \ @@ -1357,14 +1462,14 @@ target = d0_data - c0; \ update(target, max, intensity); \ target = d1_data - (c0 + c1); \ - update(target, max, intensity); \ + update_cb(target, max, intensity); \ target = d2_data - (c0 + c2); \ update_cr(target, max, intensity); \ } else { \ target = d0_data + c0; \ update(target, max, intensity); \ target = d1_data + (c0 + c1); \ - update(target, max, intensity); \ + update_cb(target, max, intensity); \ target = d2_data + (c0 + c2); \ update_cr(target, max, intensity); \ } \ @@ -1384,23 +1489,31 @@ return 0; \ } -AFLAT16(aflat16_row, update16, 0, 0) -AFLAT16(aflat16_row_mirror, update16, 0, 1) -AFLAT16(aflat16_column, update16, 1, 0) -AFLAT16(aflat16_column_mirror, update16, 1, 1) -AFLAT16(xflat16_row, update16_cr, 0, 0) -AFLAT16(xflat16_row_mirror, update16_cr, 0, 1) -AFLAT16(xflat16_column, update16_cr, 1, 0) -AFLAT16(xflat16_column_mirror, update16_cr, 1, 1) - -AFLAT(aflat_row, update, 0, 0) -AFLAT(aflat_row_mirror, update, 0, 1) -AFLAT(aflat_column, update, 1, 0) -AFLAT(aflat_column_mirror, update, 1, 1) -AFLAT(xflat_row, update_cr, 0, 0) -AFLAT(xflat_row_mirror, update_cr, 0, 1) -AFLAT(xflat_column, update_cr, 1, 0) -AFLAT(xflat_column_mirror, update_cr, 1, 1) +AFLAT16(aflat16_row, update16, update16, 0, 0) +AFLAT16(aflat16_row_mirror, update16, update16, 0, 1) +AFLAT16(aflat16_column, update16, update16, 1, 0) +AFLAT16(aflat16_column_mirror, update16, update16, 1, 1) +AFLAT16(xflat16_row, update16, update16_cr, 0, 0) +AFLAT16(xflat16_row_mirror, update16, update16_cr, 0, 1) +AFLAT16(xflat16_column, update16, update16_cr, 1, 0) +AFLAT16(xflat16_column_mirror, update16, update16_cr, 1, 1) +AFLAT16(yflat16_row, update16_cr, update16_cr, 0, 0) +AFLAT16(yflat16_row_mirror, update16_cr, update16_cr, 0, 1) +AFLAT16(yflat16_column, update16_cr, update16_cr, 1, 0) +AFLAT16(yflat16_column_mirror, update16_cr, update16_cr, 1, 1) + +AFLAT(aflat_row, update, update, 0, 0) +AFLAT(aflat_row_mirror, update, update, 0, 1) +AFLAT(aflat_column, update, update, 1, 0) +AFLAT(aflat_column_mirror, update, update, 1, 1) +AFLAT(xflat_row, update, update_cr, 0, 0) +AFLAT(xflat_row_mirror, update, update_cr, 0, 1) +AFLAT(xflat_column, update, update_cr, 1, 0) +AFLAT(xflat_column_mirror, update, update_cr, 1, 1) +AFLAT(yflat_row, update_cr, update_cr, 0, 0) +AFLAT(yflat_row_mirror, update_cr, update_cr, 0, 1) +AFLAT(yflat_column, update_cr, update_cr, 1, 0) +AFLAT(yflat_column_mirror, update_cr, update_cr, 1, 1) static av_always_inline void chroma16(WaveformContext *s, AVFrame *in, AVFrame *out, @@ -2470,8 +2583,9 @@ } } -static void blend_vline16(uint16_t *dst, int height, int linesize, float o1, float o2, int v, int step) +static void blend_vline16(uint8_t *ddst, int height, int linesize, float o1, float o2, int v, int step) { + uint16_t *dst = (uint16_t *)ddst; int y; for (y = 0; y < height; y += step) { @@ -2481,7 +2595,7 @@ } } -static void blend_hline(uint8_t *dst, int width, float o1, float o2, int v, int step) +static void blend_hline(uint8_t *dst, int width, int unused, float o1, float o2, int v, int step) { int x; @@ -2490,8 +2604,9 @@ } } -static void blend_hline16(uint16_t *dst, int width, float o1, float o2, int v, int step) +static void blend_hline16(uint8_t *ddst, int width, int unused, float o1, float o2, int v, int step) { + uint16_t *dst = (uint16_t *)ddst; int x; for (x = 0; x < width; x += step) { @@ -2499,7 +2614,7 @@ } } -static void draw_htext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4]) +static void draw_htext(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4]) { const uint8_t *font; int font_height; @@ -2551,7 +2666,7 @@ } } -static void draw_vtext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4]) +static void draw_vtext(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4]) { const uint8_t *font; int font_height; @@ -2601,6 +2716,150 @@ } } +static void iblend_vline(uint8_t *dst, int height, int linesize, float o1, float o2, int v, int step) +{ + int y; + + for (y = 0; y < height; y += step) { + dst[0] = (v - dst[0]) * o1 + dst[0] * o2; + + dst += linesize * step; + } +} + +static void iblend_vline16(uint8_t *ddst, int height, int linesize, float o1, float o2, int v, int step) +{ + uint16_t *dst = (uint16_t *)ddst; + int y; + + for (y = 0; y < height; y += step) { + dst[0] = (v - dst[0]) * o1 + dst[0] * o2; + + dst += (linesize / 2) * step; + } +} + +static void iblend_hline(uint8_t *dst, int width, int unused, float o1, float o2, int v, int step) +{ + int x; + + for (x = 0; x < width; x += step) { + dst[x] = (v - dst[x]) * o1 + dst[x] * o2; + } +} + +static void iblend_hline16(uint8_t *ddst, int width, int unused, float o1, float o2, int v, int step) +{ + uint16_t *dst = (uint16_t *)ddst; + int x; + + for (x = 0; x < width; x += step) { + dst[x] = (v - dst[x]) * o1 + dst[x] * o2; + } +} + +static void idraw_htext(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4]) +{ + const uint8_t *font; + int font_height; + int i, plane; + + font = avpriv_cga_font, font_height = 8; + + for (plane = 0; plane < 4 && out->data[plane]; plane++) { + for (i = 0; txt[i]; i++) { + int char_y, mask; + int v = color[plane]; + + uint8_t *p = out->data[plane] + y * out->linesize[plane] + (x + i * 8); + for (char_y = 0; char_y < font_height; char_y++) { + for (mask = 0x80; mask; mask >>= 1) { + if (font[txt[i] * font_height + char_y] & mask) + p[0] = p[0] * o2 + (v - p[0]) * o1; + p++; + } + p += out->linesize[plane] - 8; + } + } + } +} + +static void idraw_htext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4]) +{ + const uint8_t *font; + int font_height; + int i, plane; + + font = avpriv_cga_font, font_height = 8; + + for (plane = 0; plane < 4 && out->data[plane]; plane++) { + for (i = 0; txt[i]; i++) { + int char_y, mask; + int v = color[plane] * mult; + + uint16_t *p = (uint16_t *)(out->data[plane] + y * out->linesize[plane]) + (x + i * 8); + for (char_y = 0; char_y < font_height; char_y++) { + for (mask = 0x80; mask; mask >>= 1) { + if (font[txt[i] * font_height + char_y] & mask) + p[0] = p[0] * o2 + (v - p[0]) * o1; + p++; + } + p += out->linesize[plane] / 2 - 8; + } + } + } +} + +static void idraw_vtext(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4]) +{ + const uint8_t *font; + int font_height; + int i, plane; + + font = avpriv_cga_font, font_height = 8; + + for (plane = 0; plane < 4 && out->data[plane]; plane++) { + for (i = 0; txt[i]; i++) { + int char_y, mask; + int v = color[plane]; + + for (char_y = font_height - 1; char_y >= 0; char_y--) { + uint8_t *p = out->data[plane] + (y + i * 10) * out->linesize[plane] + x; + for (mask = 0x80; mask; mask >>= 1) { + if (font[txt[i] * font_height + font_height - 1 - char_y] & mask) + p[char_y] = p[char_y] * o2 + (v - p[char_y]) * o1; + p += out->linesize[plane]; + } + } + } + } +} + +static void idraw_vtext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4]) +{ + const uint8_t *font; + int font_height; + int i, plane; + + font = avpriv_cga_font, font_height = 8; + + for (plane = 0; plane < 4 && out->data[plane]; plane++) { + for (i = 0; txt[i]; i++) { + int char_y, mask; + int v = color[plane] * mult; + + for (char_y = 0; char_y < font_height; char_y++) { + uint16_t *p = (uint16_t *)(out->data[plane] + (y + i * 10) * out->linesize[plane]) + x; + for (mask = 0x80; mask; mask >>= 1) { + if (font[txt[i] * font_height + font_height - 1 - char_y] & mask) + p[char_y] = p[char_y] * o2 + (v - p[char_y]) * o1; + p += out->linesize[plane] / 2; + } + } + } + } +} + static void graticule_none(WaveformContext *s, AVFrame *out) { } @@ -2626,7 +2885,7 @@ int x = offset_x + (s->mirror ? s->size - 1 - pos : pos); uint8_t *dst = out->data[p] + offset_y * out->linesize[p] + x; - blend_vline(dst, height, out->linesize[p], o1, o2, v, step); + s->blend_line(dst, height, out->linesize[p], o1, o2, v, step); } } @@ -2638,7 +2897,7 @@ if (x < 0) x = 4; - draw_vtext(out, x, offset_y + 2, o1, o2, name, s->grat_yuva_color); + s->draw_text(out, x, offset_y + 2, 1, o1, o2, name, s->grat_yuva_color); } offset_x += s->size * (s->display == STACK); @@ -2666,9 +2925,9 @@ for (l = 0; l < s->nb_glines ; l++) { const uint16_t pos = s->glines[l].line[C].pos; int x = offset_x + (s->mirror ? s->size - 1 - pos : pos); - uint16_t *dst = (uint16_t *)(out->data[p] + offset_y * out->linesize[p]) + x; + uint8_t *dst = (uint8_t *)(out->data[p] + offset_y * out->linesize[p]) + x * 2; - blend_vline16(dst, height, out->linesize[p], o1, o2, v, step); + s->blend_line(dst, height, out->linesize[p], o1, o2, v, step); } } @@ -2680,7 +2939,7 @@ if (x < 0) x = 4; - draw_vtext16(out, x, offset_y + 2, mult, o1, o2, name, s->grat_yuva_color); + s->draw_text(out, x, offset_y + 2, mult, o1, o2, name, s->grat_yuva_color); } offset_x += s->size * (s->display == STACK); @@ -2709,7 +2968,7 @@ int y = offset_y + (s->mirror ? s->size - 1 - pos : pos); uint8_t *dst = out->data[p] + y * out->linesize[p] + offset_x; - blend_hline(dst, width, o1, o2, v, step); + s->blend_line(dst, width, 1, o1, o2, v, step); } } @@ -2721,7 +2980,7 @@ if (y < 0) y = 4; - draw_htext(out, 2 + offset_x, y, o1, o2, name, s->grat_yuva_color); + s->draw_text(out, 2 + offset_x, y, 1, o1, o2, name, s->grat_yuva_color); } offset_y += s->size * (s->display == STACK); @@ -2749,9 +3008,9 @@ for (l = 0; l < s->nb_glines ; l++) { const uint16_t pos = s->glines[l].line[C].pos; int y = offset_y + (s->mirror ? s->size - 1 - pos : pos); - uint16_t *dst = (uint16_t *)(out->data[p] + y * out->linesize[p]) + offset_x; + uint8_t *dst = (uint8_t *)(out->data[p] + y * out->linesize[p]) + offset_x * 2; - blend_hline16(dst, width, o1, o2, v, step); + s->blend_line(dst, width, 1, o1, o2, v, step); } } @@ -2763,7 +3022,7 @@ if (y < 0) y = 4; - draw_htext16(out, 2 + offset_x, y, mult, o1, o2, name, s->grat_yuva_color); + s->draw_text(out, 2 + offset_x, y, mult, o1, o2, name, s->grat_yuva_color); } offset_y += s->size * (s->display == STACK); @@ -2791,6 +3050,7 @@ switch (s->filter) { case XFLAT: + case YFLAT: case AFLAT: s->size = 256 * 2; break; case FLAT: s->size = 256 * 3; break; default: s->size = 256; break; @@ -2854,12 +3114,35 @@ case 0x1016: s->waveform_slice = xflat16_row_mirror; break; case 0x0116: s->waveform_slice = xflat16_column; break; case 0x0016: s->waveform_slice = xflat16_row; break; + case 0x1107: s->waveform_slice = yflat_column_mirror; break; + case 0x1007: s->waveform_slice = yflat_row_mirror; break; + case 0x0107: s->waveform_slice = yflat_column; break; + case 0x0007: s->waveform_slice = yflat_row; break; + case 0x1117: s->waveform_slice = yflat16_column_mirror; break; + case 0x1017: s->waveform_slice = yflat16_row_mirror; break; + case 0x0117: s->waveform_slice = yflat16_column; break; + case 0x0017: s->waveform_slice = yflat16_row; break; } s->grat_yuva_color[0] = 255; - s->grat_yuva_color[2] = s->graticule == 2 ? 255 : 0; + s->grat_yuva_color[1] = s->graticule == GRAT_INVERT ? 255 : 0; + s->grat_yuva_color[2] = s->graticule == GRAT_ORANGE || s->graticule == GRAT_INVERT ? 255 : 0; s->grat_yuva_color[3] = 255; + if (s->mode == 0 && s->graticule != GRAT_INVERT) { + s->blend_line = s->bits <= 8 ? blend_vline : blend_vline16; + s->draw_text = s->bits <= 8 ? draw_vtext : draw_vtext16; + } else if (s->graticule != GRAT_INVERT) { + s->blend_line = s->bits <= 8 ? blend_hline : blend_hline16; + s->draw_text = s->bits <= 8 ? draw_htext : draw_htext16; + } else if (s->mode == 0 && s->graticule == GRAT_INVERT) { + s->blend_line = s->bits <= 8 ? iblend_vline : iblend_vline16; + s->draw_text = s->bits <= 8 ? idraw_vtext : idraw_vtext16; + } else if (s->graticule == GRAT_INVERT) { + s->blend_line = s->bits <= 8 ? iblend_hline : iblend_hline16; + s->draw_text = s->bits <= 8 ? idraw_htext : idraw_htext16; + } + switch (s->filter) { case LOWPASS: case COLOR: @@ -2867,10 +3150,11 @@ case CHROMA: case AFLAT: case XFLAT: + case YFLAT: case FLAT: - if (s->graticule && s->mode == 1) + if (s->graticule > GRAT_NONE && s->mode == 1) s->graticulef = s->bits > 8 ? graticule16_column : graticule_column; - else if (s->graticule && s->mode == 0) + else if (s->graticule > GRAT_NONE && s->mode == 0) s->graticulef = s->bits > 8 ? graticule16_row : graticule_row; break; } @@ -2935,6 +3219,7 @@ } break; case XFLAT: + case YFLAT: case AFLAT: switch (s->scale) { case DIGITAL: @@ -2995,6 +3280,9 @@ s->size = s->size << (s->bits - 8); + s->tint[0] = .5f * (s->ftint[0] + 1.f) * (s->size - 1); + s->tint[1] = .5f * (s->ftint[1] + 1.f) * (s->size - 1); + switch (inlink->format) { case AV_PIX_FMT_GBRAP: case AV_PIX_FMT_GBRP: @@ -3131,10 +3419,15 @@ td.offset_x = offset_x; ctx->internal->execute(ctx, s->waveform_slice, &td, NULL, ff_filter_get_nb_threads(ctx)); switch (s->filter) { + case LOWPASS: + if (s->bits <= 8) + envelope(s, out, plane, s->rgb || s->display == OVERLAY ? plane : 0, s->mode ? offset_x : offset_y); + else + envelope16(s, out, plane, s->rgb || s->display == OVERLAY ? plane : 0, s->mode ? offset_x : offset_y); + break; case ACOLOR: case CHROMA: case COLOR: - case LOWPASS: if (s->bits <= 8) envelope(s, out, plane, plane, s->mode ? offset_x : offset_y); else @@ -3151,6 +3444,7 @@ break; case AFLAT: case XFLAT: + case YFLAT: if (s->bits <= 8) { envelope(s, out, plane, (plane + 0) % s->ncomp, s->mode ? offset_x : offset_y); envelope(s, out, plane, (plane + 1) % s->ncomp, s->mode ? offset_x : offset_y); diff -Nru ffmpeg-4.2.2/libavfilter/vf_weave.c ffmpeg-4.4/libavfilter/vf_weave.c --- ffmpeg-4.2.2/libavfilter/vf_weave.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_weave.c 2021-04-08 21:28:40.000000000 +0000 @@ -49,6 +49,19 @@ AVFILTER_DEFINE_CLASS(weave); +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + int ret; + + ret = ff_formats_pixdesc_filter(&formats, 0, + AV_PIX_FMT_FLAG_PAL | + AV_PIX_FMT_FLAG_HWACCEL); + if (ret < 0) + return ret; + return ff_set_common_formats(ctx, formats); +} + static int config_props_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -77,15 +90,51 @@ return 0; } +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int weave_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AVFilterLink *inlink = ctx->inputs[0]; + WeaveContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + + const int weave = (s->double_weave && !(inlink->frame_count_out & 1)); + const int field1 = weave ? s->first_field : (!s->first_field); + const int field2 = weave ? (!s->first_field) : s->first_field; + + for (int i = 0; i < s->nb_planes; i++) { + const int height = s->planeheight[i]; + const int start = (height * jobnr) / nb_jobs; + const int end = (height * (jobnr+1)) / nb_jobs; + + av_image_copy_plane(out->data[i] + out->linesize[i] * field1 + + out->linesize[i] * start * 2, + out->linesize[i] * 2, + in->data[i] + start * in->linesize[i], + in->linesize[i], + s->linesize[i], end - start); + av_image_copy_plane(out->data[i] + out->linesize[i] * field2 + + out->linesize[i] * start * 2, + out->linesize[i] * 2, + s->prev->data[i] + start * s->prev->linesize[i], + s->prev->linesize[i], + s->linesize[i], end - start); + } + + return 0; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; WeaveContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + ThreadData td; AVFrame *out; - int i; - int weave; - int field1, field2; if (!s->prev) { s->prev = in; @@ -100,19 +149,9 @@ } av_frame_copy_props(out, in); - weave = (s->double_weave && !(inlink->frame_count_out & 1)); - field1 = weave ? s->first_field : (!s->first_field); - field2 = weave ? (!s->first_field) : s->first_field; - for (i = 0; i < s->nb_planes; i++) { - av_image_copy_plane(out->data[i] + out->linesize[i] * field1, - out->linesize[i] * 2, - in->data[i], in->linesize[i], - s->linesize[i], s->planeheight[i]); - av_image_copy_plane(out->data[i] + out->linesize[i] * field2, - out->linesize[i] * 2, - s->prev->data[i], s->prev->linesize[i], - s->linesize[i], s->planeheight[i]); - } + td.out = out, td.in = in; + ctx->internal->execute(ctx, weave_slice, &td, NULL, FFMIN(s->planeheight[1], + ff_filter_get_nb_threads(ctx))); out->pts = s->double_weave ? s->prev->pts : in->pts / 2; out->interlaced_frame = 1; @@ -156,9 +195,11 @@ .description = NULL_IF_CONFIG_SMALL("Weave input video fields into frames."), .priv_size = sizeof(WeaveContext), .priv_class = &weave_class, + .query_formats = query_formats, .uninit = uninit, .inputs = weave_inputs, .outputs = weave_outputs, + .flags = AVFILTER_FLAG_SLICE_THREADS, }; static av_cold int init(AVFilterContext *ctx) @@ -179,8 +220,10 @@ .description = NULL_IF_CONFIG_SMALL("Weave input video fields into double number of frames."), .priv_size = sizeof(WeaveContext), .priv_class = &doubleweave_class, + .query_formats = query_formats, .init = init, .uninit = uninit, .inputs = weave_inputs, .outputs = weave_outputs, + .flags = AVFILTER_FLAG_SLICE_THREADS, }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_xbr.c ffmpeg-4.4/libavfilter/vf_xbr.c --- ffmpeg-4.2.2/libavfilter/vf_xbr.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_xbr.c 2020-07-11 10:39:30.000000000 +0000 @@ -380,7 +380,7 @@ return ff_filter_frame(outlink, out); } -static int init(AVFilterContext *ctx) +static av_cold int init(AVFilterContext *ctx) { XBRContext *s = ctx->priv; static const xbrfunc_t xbrfuncs[] = {xbr2x, xbr3x, xbr4x}; @@ -395,7 +395,7 @@ int startg = FFMAX3(-bg, -rg, 0); int endg = FFMIN3(255-bg, 255-rg, 255); uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000); - c = bg + (rg<<16) + 0x010101 * startg; + c = bg + rg * (1 << 16) + 0x010101 * startg; for (g = startg; g <= endg; g++) { s->rgbtoyuv[c] = ((y++) << 16) + (u << 8) + v; c+= 0x010101; diff -Nru ffmpeg-4.2.2/libavfilter/vf_xfade.c ffmpeg-4.4/libavfilter/vf_xfade.c --- ffmpeg-4.2.2/libavfilter/vf_xfade.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_xfade.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,1970 @@ +/* + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/imgutils.h" +#include "libavutil/eval.h" +#include "libavutil/opt.h" +#include "libavutil/pixfmt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "filters.h" +#include "video.h" + +enum XFadeTransitions { + CUSTOM = -1, + FADE, + WIPELEFT, + WIPERIGHT, + WIPEUP, + WIPEDOWN, + SLIDELEFT, + SLIDERIGHT, + SLIDEUP, + SLIDEDOWN, + CIRCLECROP, + RECTCROP, + DISTANCE, + FADEBLACK, + FADEWHITE, + RADIAL, + SMOOTHLEFT, + SMOOTHRIGHT, + SMOOTHUP, + SMOOTHDOWN, + CIRCLEOPEN, + CIRCLECLOSE, + VERTOPEN, + VERTCLOSE, + HORZOPEN, + HORZCLOSE, + DISSOLVE, + PIXELIZE, + DIAGTL, + DIAGTR, + DIAGBL, + DIAGBR, + HLSLICE, + HRSLICE, + VUSLICE, + VDSLICE, + HBLUR, + FADEGRAYS, + WIPETL, + WIPETR, + WIPEBL, + WIPEBR, + SQUEEZEH, + SQUEEZEV, + NB_TRANSITIONS, +}; + +typedef struct XFadeContext { + const AVClass *class; + + int transition; + int64_t duration; + int64_t offset; + char *custom_str; + + int nb_planes; + int depth; + int is_rgb; + + int64_t duration_pts; + int64_t offset_pts; + int64_t first_pts; + int64_t last_pts; + int64_t pts; + int xfade_is_over; + int need_second; + int eof[2]; + AVFrame *xf[2]; + int max_value; + uint16_t black[4]; + uint16_t white[4]; + + void (*transitionf)(AVFilterContext *ctx, const AVFrame *a, const AVFrame *b, AVFrame *out, float progress, + int slice_start, int slice_end, int jobnr); + + AVExpr *e; +} XFadeContext; + +static const char *const var_names[] = { "X", "Y", "W", "H", "A", "B", "PLANE", "P", NULL }; +enum { VAR_X, VAR_Y, VAR_W, VAR_H, VAR_A, VAR_B, VAR_PLANE, VAR_PROGRESS, VAR_VARS_NB }; + +typedef struct ThreadData { + const AVFrame *xf[2]; + AVFrame *out; + float progress; +} ThreadData; + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUV444P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GRAY8, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_GBRP9, + AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GRAY10, + AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GRAY12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_GBRP14, + AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + XFadeContext *s = ctx->priv; + + av_expr_free(s->e); +} + +#define OFFSET(x) offsetof(XFadeContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) + +static const AVOption xfade_options[] = { + { "transition", "set cross fade transition", OFFSET(transition), AV_OPT_TYPE_INT, {.i64=FADE}, -1, NB_TRANSITIONS-1, FLAGS, "transition" }, + { "custom", "custom transition", 0, AV_OPT_TYPE_CONST, {.i64=CUSTOM}, 0, 0, FLAGS, "transition" }, + { "fade", "fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADE}, 0, 0, FLAGS, "transition" }, + { "wipeleft", "wipe left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPELEFT}, 0, 0, FLAGS, "transition" }, + { "wiperight", "wipe right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPERIGHT}, 0, 0, FLAGS, "transition" }, + { "wipeup", "wipe up transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEUP}, 0, 0, FLAGS, "transition" }, + { "wipedown", "wipe down transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEDOWN}, 0, 0, FLAGS, "transition" }, + { "slideleft", "slide left transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDELEFT}, 0, 0, FLAGS, "transition" }, + { "slideright", "slide right transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDERIGHT}, 0, 0, FLAGS, "transition" }, + { "slideup", "slide up transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEUP}, 0, 0, FLAGS, "transition" }, + { "slidedown", "slide down transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEDOWN}, 0, 0, FLAGS, "transition" }, + { "circlecrop", "circle crop transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLECROP}, 0, 0, FLAGS, "transition" }, + { "rectcrop", "rect crop transition", 0, AV_OPT_TYPE_CONST, {.i64=RECTCROP}, 0, 0, FLAGS, "transition" }, + { "distance", "distance transition", 0, AV_OPT_TYPE_CONST, {.i64=DISTANCE}, 0, 0, FLAGS, "transition" }, + { "fadeblack", "fadeblack transition", 0, AV_OPT_TYPE_CONST, {.i64=FADEBLACK}, 0, 0, FLAGS, "transition" }, + { "fadewhite", "fadewhite transition", 0, AV_OPT_TYPE_CONST, {.i64=FADEWHITE}, 0, 0, FLAGS, "transition" }, + { "radial", "radial transition", 0, AV_OPT_TYPE_CONST, {.i64=RADIAL}, 0, 0, FLAGS, "transition" }, + { "smoothleft", "smoothleft transition", 0, AV_OPT_TYPE_CONST, {.i64=SMOOTHLEFT}, 0, 0, FLAGS, "transition" }, + { "smoothright","smoothright transition", 0, AV_OPT_TYPE_CONST, {.i64=SMOOTHRIGHT},0, 0, FLAGS, "transition" }, + { "smoothup", "smoothup transition", 0, AV_OPT_TYPE_CONST, {.i64=SMOOTHUP}, 0, 0, FLAGS, "transition" }, + { "smoothdown", "smoothdown transition", 0, AV_OPT_TYPE_CONST, {.i64=SMOOTHDOWN}, 0, 0, FLAGS, "transition" }, + { "circleopen", "circleopen transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLEOPEN}, 0, 0, FLAGS, "transition" }, + { "circleclose","circleclose transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLECLOSE},0, 0, FLAGS, "transition" }, + { "vertopen", "vert open transition", 0, AV_OPT_TYPE_CONST, {.i64=VERTOPEN}, 0, 0, FLAGS, "transition" }, + { "vertclose", "vert close transition", 0, AV_OPT_TYPE_CONST, {.i64=VERTCLOSE}, 0, 0, FLAGS, "transition" }, + { "horzopen", "horz open transition", 0, AV_OPT_TYPE_CONST, {.i64=HORZOPEN}, 0, 0, FLAGS, "transition" }, + { "horzclose", "horz close transition", 0, AV_OPT_TYPE_CONST, {.i64=HORZCLOSE}, 0, 0, FLAGS, "transition" }, + { "dissolve", "dissolve transition", 0, AV_OPT_TYPE_CONST, {.i64=DISSOLVE}, 0, 0, FLAGS, "transition" }, + { "pixelize", "pixelize transition", 0, AV_OPT_TYPE_CONST, {.i64=PIXELIZE}, 0, 0, FLAGS, "transition" }, + { "diagtl", "diag tl transition", 0, AV_OPT_TYPE_CONST, {.i64=DIAGTL}, 0, 0, FLAGS, "transition" }, + { "diagtr", "diag tr transition", 0, AV_OPT_TYPE_CONST, {.i64=DIAGTR}, 0, 0, FLAGS, "transition" }, + { "diagbl", "diag bl transition", 0, AV_OPT_TYPE_CONST, {.i64=DIAGBL}, 0, 0, FLAGS, "transition" }, + { "diagbr", "diag br transition", 0, AV_OPT_TYPE_CONST, {.i64=DIAGBR}, 0, 0, FLAGS, "transition" }, + { "hlslice", "hl slice transition", 0, AV_OPT_TYPE_CONST, {.i64=HLSLICE}, 0, 0, FLAGS, "transition" }, + { "hrslice", "hr slice transition", 0, AV_OPT_TYPE_CONST, {.i64=HRSLICE}, 0, 0, FLAGS, "transition" }, + { "vuslice", "vu slice transition", 0, AV_OPT_TYPE_CONST, {.i64=VUSLICE}, 0, 0, FLAGS, "transition" }, + { "vdslice", "vd slice transition", 0, AV_OPT_TYPE_CONST, {.i64=VDSLICE}, 0, 0, FLAGS, "transition" }, + { "hblur", "hblur transition", 0, AV_OPT_TYPE_CONST, {.i64=HBLUR}, 0, 0, FLAGS, "transition" }, + { "fadegrays", "fadegrays transition", 0, AV_OPT_TYPE_CONST, {.i64=FADEGRAYS}, 0, 0, FLAGS, "transition" }, + { "wipetl", "wipe tl transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPETL}, 0, 0, FLAGS, "transition" }, + { "wipetr", "wipe tr transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPETR}, 0, 0, FLAGS, "transition" }, + { "wipebl", "wipe bl transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEBL}, 0, 0, FLAGS, "transition" }, + { "wipebr", "wipe br transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEBR}, 0, 0, FLAGS, "transition" }, + { "squeezeh", "squeeze h transition", 0, AV_OPT_TYPE_CONST, {.i64=SQUEEZEH}, 0, 0, FLAGS, "transition" }, + { "squeezev", "squeeze v transition", 0, AV_OPT_TYPE_CONST, {.i64=SQUEEZEV}, 0, 0, FLAGS, "transition" }, + { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=1000000}, 0, 60000000, FLAGS }, + { "offset", "set cross fade start relative to first input stream", OFFSET(offset), AV_OPT_TYPE_DURATION, {.i64=0}, INT64_MIN, INT64_MAX, FLAGS }, + { "expr", "set expression for custom transition", OFFSET(custom_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(xfade); + +#define CUSTOM_TRANSITION(name, type, div) \ +static void custom##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + \ + double values[VAR_VARS_NB]; \ + values[VAR_W] = out->width; \ + values[VAR_H] = out->height; \ + values[VAR_PROGRESS] = progress; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + values[VAR_PLANE] = p; \ + \ + for (int y = 0; y < height; y++) { \ + values[VAR_Y] = slice_start + y; \ + for (int x = 0; x < out->width; x++) { \ + values[VAR_X] = x; \ + values[VAR_A] = xf0[x]; \ + values[VAR_B] = xf1[x]; \ + dst[x] = av_expr_eval(s->e, values, s); \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +CUSTOM_TRANSITION(8, uint8_t, 1) +CUSTOM_TRANSITION(16, uint16_t, 2) + +static inline float mix(float a, float b, float mix) +{ + return a * mix + b * (1.f - mix); +} + +static inline float fract(float a) +{ + return a - floorf(a); +} + +static inline float smoothstep(float edge0, float edge1, float x) +{ + float t; + + t = av_clipf((x - edge0) / (edge1 - edge0), 0.f, 1.f); + + return t * t * (3.f - 2.f * t); +} + +#define FADE_TRANSITION(name, type, div) \ +static void fade##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = mix(xf0[x], xf1[x], progress); \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +FADE_TRANSITION(8, uint8_t, 1) +FADE_TRANSITION(16, uint16_t, 2) + +#define WIPELEFT_TRANSITION(name, type, div) \ +static void wipeleft##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const int z = out->width * progress; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = x > z ? xf1[x] : xf0[x]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +WIPELEFT_TRANSITION(8, uint8_t, 1) +WIPELEFT_TRANSITION(16, uint16_t, 2) + +#define WIPERIGHT_TRANSITION(name, type, div) \ +static void wiperight##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const int z = out->width * (1.f - progress); \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = x > z ? xf0[x] : xf1[x]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +WIPERIGHT_TRANSITION(8, uint8_t, 1) +WIPERIGHT_TRANSITION(16, uint16_t, 2) + +#define WIPEUP_TRANSITION(name, type, div) \ +static void wipeup##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const int z = out->height * progress; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = slice_start + y > z ? xf1[x] : xf0[x]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +WIPEUP_TRANSITION(8, uint8_t, 1) +WIPEUP_TRANSITION(16, uint16_t, 2) + +#define WIPEDOWN_TRANSITION(name, type, div) \ +static void wipedown##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const int z = out->height * (1.f - progress); \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = slice_start + y > z ? xf0[x] : xf1[x]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +WIPEDOWN_TRANSITION(8, uint8_t, 1) +WIPEDOWN_TRANSITION(16, uint16_t, 2) + +#define SLIDELEFT_TRANSITION(name, type, div) \ +static void slideleft##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const int width = out->width; \ + const int z = -progress * width; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < width; x++) { \ + const int zx = z + x; \ + const int zz = zx % width + width * (zx < 0); \ + dst[x] = (zx > 0) && (zx < width) ? xf1[zz] : xf0[zz]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +SLIDELEFT_TRANSITION(8, uint8_t, 1) +SLIDELEFT_TRANSITION(16, uint16_t, 2) + +#define SLIDERIGHT_TRANSITION(name, type, div) \ +static void slideright##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const int width = out->width; \ + const int z = progress * width; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + const int zx = z + x; \ + const int zz = zx % width + width * (zx < 0); \ + dst[x] = (zx > 0) && (zx < width) ? xf1[zz] : xf0[zz]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +SLIDERIGHT_TRANSITION(8, uint8_t, 1) +SLIDERIGHT_TRANSITION(16, uint16_t, 2) + +#define SLIDEUP_TRANSITION(name, type, div) \ +static void slideup##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = out->height; \ + const int z = -progress * height; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const int zy = z + y; \ + const int zz = zy % height + height * (zy < 0); \ + const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \ + \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = (zy > 0) && (zy < height) ? xf1[x] : xf0[x]; \ + } \ + \ + dst += out->linesize[p] / div; \ + } \ + } \ +} + +SLIDEUP_TRANSITION(8, uint8_t, 1) +SLIDEUP_TRANSITION(16, uint16_t, 2) + +#define SLIDEDOWN_TRANSITION(name, type, div) \ +static void slidedown##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = out->height; \ + const int z = progress * height; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const int zy = z + y; \ + const int zz = zy % height + height * (zy < 0); \ + const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \ + \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = (zy > 0) && (zy < height) ? xf1[x] : xf0[x]; \ + } \ + \ + dst += out->linesize[p] / div; \ + } \ + } \ +} + +SLIDEDOWN_TRANSITION(8, uint8_t, 1) +SLIDEDOWN_TRANSITION(16, uint16_t, 2) + +#define CIRCLECROP_TRANSITION(name, type, div) \ +static void circlecrop##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const int height = out->height; \ + float z = powf(2.f * fabsf(progress - 0.5f), 3.f) * hypotf(width/2, height/2); \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const int bg = s->black[p]; \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + \ + for (int x = 0; x < width; x++) { \ + float dist = hypotf(x - width / 2, y - height / 2); \ + int val = progress < 0.5f ? xf1[x] : xf0[x]; \ + dst[x] = (z < dist) ? bg : val; \ + } \ + \ + dst += out->linesize[p] / div; \ + } \ + } \ +} + +CIRCLECROP_TRANSITION(8, uint8_t, 1) +CIRCLECROP_TRANSITION(16, uint16_t, 2) + +#define RECTCROP_TRANSITION(name, type, div) \ +static void rectcrop##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const int height = out->height; \ + int zh = fabsf(progress - 0.5f) * height; \ + int zw = fabsf(progress - 0.5f) * width; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const int bg = s->black[p]; \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + \ + for (int x = 0; x < width; x++) { \ + int dist = FFABS(x - width / 2) < zw && \ + FFABS(y - height / 2) < zh; \ + int val = progress < 0.5f ? xf1[x] : xf0[x]; \ + dst[x] = !dist ? bg : val; \ + } \ + \ + dst += out->linesize[p] / div; \ + } \ + } \ +} + +RECTCROP_TRANSITION(8, uint8_t, 1) +RECTCROP_TRANSITION(16, uint16_t, 2) + +#define DISTANCE_TRANSITION(name, type, div) \ +static void distance##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float max = s->max_value; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + float dist = 0.f; \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + \ + dist += (xf0[x] / max - xf1[x] / max) * \ + (xf0[x] / max - xf1[x] / max); \ + } \ + \ + dist = sqrtf(dist) <= progress; \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + dst[x] = mix(mix(xf0[x], xf1[x], dist), xf1[x], progress); \ + } \ + } \ + } \ +} + +DISTANCE_TRANSITION(8, uint8_t, 1) +DISTANCE_TRANSITION(16, uint16_t, 2) + +#define FADEBLACK_TRANSITION(name, type, div) \ +static void fadeblack##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const float phase = 0.2f; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + const int bg = s->black[p]; \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \ + mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \ + progress); \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +FADEBLACK_TRANSITION(8, uint8_t, 1) +FADEBLACK_TRANSITION(16, uint16_t, 2) + +#define FADEWHITE_TRANSITION(name, type, div) \ +static void fadewhite##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const float phase = 0.2f; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + const int bg = s->white[p]; \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = mix(mix(xf0[x], bg, smoothstep(1.f-phase, 1.f, progress)), \ + mix(bg, xf1[x], smoothstep(phase, 1.f, progress)), \ + progress); \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +FADEWHITE_TRANSITION(8, uint8_t, 1) +FADEWHITE_TRANSITION(16, uint16_t, 2) + +#define RADIAL_TRANSITION(name, type, div) \ +static void radial##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const int height = out->height; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = atan2f(x - width / 2, y - height / 2) - \ + (progress - 0.5f) * (M_PI * 2.5f); \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +RADIAL_TRANSITION(8, uint8_t, 1) +RADIAL_TRANSITION(16, uint16_t, 2) + +#define SMOOTHLEFT_TRANSITION(name, type, div) \ +static void smoothleft##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float w = width; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = 1.f + x / w - progress * 2.f; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +SMOOTHLEFT_TRANSITION(8, uint8_t, 1) +SMOOTHLEFT_TRANSITION(16, uint16_t, 2) + +#define SMOOTHRIGHT_TRANSITION(name, type, div) \ +static void smoothright##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float w = width; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = 1.f + (w - 1 - x) / w - progress * 2.f; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +SMOOTHRIGHT_TRANSITION(8, uint8_t, 1) +SMOOTHRIGHT_TRANSITION(16, uint16_t, 2) + +#define SMOOTHUP_TRANSITION(name, type, div) \ +static void smoothup##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float h = out->height; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const float smooth = 1.f + y / h - progress * 2.f; \ + for (int x = 0; x < width; x++) { \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +SMOOTHUP_TRANSITION(8, uint8_t, 1) +SMOOTHUP_TRANSITION(16, uint16_t, 2) + +#define SMOOTHDOWN_TRANSITION(name, type, div) \ +static void smoothdown##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float h = out->height; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const float smooth = 1.f + (h - 1 - y) / h - progress * 2.f; \ + for (int x = 0; x < width; x++) { \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +SMOOTHDOWN_TRANSITION(8, uint8_t, 1) +SMOOTHDOWN_TRANSITION(16, uint16_t, 2) + +#define CIRCLEOPEN_TRANSITION(name, type, div) \ +static void circleopen##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const int height = out->height; \ + const float z = hypotf(width / 2, height / 2); \ + const float p = (progress - 0.5f) * 3.f; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf0[x], xf1[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +CIRCLEOPEN_TRANSITION(8, uint8_t, 1) +CIRCLEOPEN_TRANSITION(16, uint16_t, 2) + +#define CIRCLECLOSE_TRANSITION(name, type, div) \ +static void circleclose##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const int height = out->height; \ + const float z = hypotf(width / 2, height / 2); \ + const float p = (1.f - progress - 0.5f) * 3.f; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = hypotf(x - width / 2, y - height / 2) / z + p; \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +CIRCLECLOSE_TRANSITION(8, uint8_t, 1) +CIRCLECLOSE_TRANSITION(16, uint16_t, 2) + +#define VERTOPEN_TRANSITION(name, type, div) \ +static void vertopen##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float w2 = out->width / 2; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = 2.f - fabsf((x - w2) / w2) - progress * 2.f; \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +VERTOPEN_TRANSITION(8, uint8_t, 1) +VERTOPEN_TRANSITION(16, uint16_t, 2) + +#define VERTCLOSE_TRANSITION(name, type, div) \ +static void vertclose##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float w2 = out->width / 2; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = 1.f + fabsf((x - w2) / w2) - progress * 2.f; \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +VERTCLOSE_TRANSITION(8, uint8_t, 1) +VERTCLOSE_TRANSITION(16, uint16_t, 2) + +#define HORZOPEN_TRANSITION(name, type, div) \ +static void horzopen##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float h2 = out->height / 2; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const float smooth = 2.f - fabsf((y - h2) / h2) - progress * 2.f; \ + for (int x = 0; x < width; x++) { \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +HORZOPEN_TRANSITION(8, uint8_t, 1) +HORZOPEN_TRANSITION(16, uint16_t, 2) + +#define HORZCLOSE_TRANSITION(name, type, div) \ +static void horzclose##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float h2 = out->height / 2; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const float smooth = 1.f + fabsf((y - h2) / h2) - progress * 2.f; \ + for (int x = 0; x < width; x++) { \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +HORZCLOSE_TRANSITION(8, uint8_t, 1) +HORZCLOSE_TRANSITION(16, uint16_t, 2) + +static float frand(int x, int y) +{ + const float r = sinf(x * 12.9898f + y * 78.233f) * 43758.545f; + + return r - floorf(r); +} + +#define DISSOLVE_TRANSITION(name, type, div) \ +static void dissolve##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = frand(x, y) * 2.f + progress * 2.f - 1.5f; \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = smooth >= 0.5f ? xf0[x] : xf1[x]; \ + } \ + } \ + } \ +} + +DISSOLVE_TRANSITION(8, uint8_t, 1) +DISSOLVE_TRANSITION(16, uint16_t, 2) + +#define PIXELIZE_TRANSITION(name, type, div) \ +static void pixelize##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int w = out->width; \ + const int h = out->height; \ + const float d = fminf(progress, 1.f - progress); \ + const float dist = ceilf(d * 50.f) / 50.f; \ + const float sqx = 2.f * dist * FFMIN(w, h) / 20.f; \ + const float sqy = 2.f * dist * FFMIN(w, h) / 20.f; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < w; x++) { \ + int sx = dist > 0.f ? FFMIN((floorf(x / sqx) + .5f) * sqx, w - 1) : x; \ + int sy = dist > 0.f ? FFMIN((floorf(y / sqy) + .5f) * sqy, h - 1) : y; \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + sy * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + sy * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf0[sx], xf1[sx], progress); \ + } \ + } \ + } \ +} + +PIXELIZE_TRANSITION(8, uint8_t, 1) +PIXELIZE_TRANSITION(16, uint16_t, 2) + +#define DIAGTL_TRANSITION(name, type, div) \ +static void diagtl##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float w = width; \ + const float h = out->height; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = 1.f + x / w * y / h - progress * 2.f; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +DIAGTL_TRANSITION(8, uint8_t, 1) +DIAGTL_TRANSITION(16, uint16_t, 2) + +#define DIAGTR_TRANSITION(name, type, div) \ +static void diagtr##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float w = width; \ + const float h = out->height; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = 1.f + (w - 1 - x) / w * y / h - progress * 2.f; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +DIAGTR_TRANSITION(8, uint8_t, 1) +DIAGTR_TRANSITION(16, uint16_t, 2) + +#define DIAGBL_TRANSITION(name, type, div) \ +static void diagbl##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float w = width; \ + const float h = out->height; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = 1.f + x / w * (h - 1 - y) / h - progress * 2.f; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +DIAGBL_TRANSITION(8, uint8_t, 1) +DIAGBL_TRANSITION(16, uint16_t, 2) + +#define DIAGBR_TRANSITION(name, type, div) \ +static void diagbr##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float w = width; \ + const float h = out->height; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = 1.f + (w - 1 - x) / w * (h - 1 - y) / h - \ + progress * 2.f; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], smoothstep(0.f, 1.f, smooth)); \ + } \ + } \ + } \ +} + +DIAGBR_TRANSITION(8, uint8_t, 1) +DIAGBR_TRANSITION(16, uint16_t, 2) + +#define HLSLICE_TRANSITION(name, type, div) \ +static void hlslice##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float w = width; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float smooth = smoothstep(-0.5f, 0.f, x / w - progress * 1.5f); \ + const float ss = smooth <= fract(10.f * x / w) ? 0.f : 1.f; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], ss); \ + } \ + } \ + } \ +} + +HLSLICE_TRANSITION(8, uint8_t, 1) +HLSLICE_TRANSITION(16, uint16_t, 2) + +#define HRSLICE_TRANSITION(name, type, div) \ +static void hrslice##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float w = width; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + const float xx = (w - 1 - x) / w; \ + const float smooth = smoothstep(-0.5f, 0.f, xx - progress * 1.5f); \ + const float ss = smooth <= fract(10.f * xx) ? 0.f : 1.f; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], ss); \ + } \ + } \ + } \ +} + +HRSLICE_TRANSITION(8, uint8_t, 1) +HRSLICE_TRANSITION(16, uint16_t, 2) + +#define VUSLICE_TRANSITION(name, type, div) \ +static void vuslice##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float h = out->height; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const float smooth = smoothstep(-0.5f, 0.f, y / h - progress * 1.5f); \ + const float ss = smooth <= fract(10.f * y / h) ? 0.f : 1.f; \ + \ + for (int x = 0; x < width; x++) { \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], ss); \ + } \ + } \ + } \ +} + +VUSLICE_TRANSITION(8, uint8_t, 1) +VUSLICE_TRANSITION(16, uint16_t, 2) + +#define VDSLICE_TRANSITION(name, type, div) \ +static void vdslice##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float h = out->height; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + const float yy = (h - 1 - y) / h; \ + const float smooth = smoothstep(-0.5f, 0.f, yy - progress * 1.5f); \ + const float ss = smooth <= fract(10.f * yy) ? 0.f : 1.f; \ + \ + for (int x = 0; x < width; x++) { \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(xf1[x], xf0[x], ss); \ + } \ + } \ + } \ +} + +VDSLICE_TRANSITION(8, uint8_t, 1) +VDSLICE_TRANSITION(16, uint16_t, 2) + +#define HBLUR_TRANSITION(name, type, div) \ +static void hblur##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const float prog = progress <= 0.5f ? progress * 2.f : (1.f - progress) * 2.f; \ + const int size = 1 + (width / 2) * prog; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + float sum0 = 0.f; \ + float sum1 = 0.f; \ + float cnt = size; \ + \ + for (int x = 0; x < size; x++) { \ + sum0 += xf0[x]; \ + sum1 += xf1[x]; \ + } \ + \ + for (int x = 0; x < width; x++) { \ + dst[x] = mix(sum0 / cnt, sum1 / cnt, progress); \ + \ + if (x + size < width) { \ + sum0 += xf0[x + size] - xf0[x]; \ + sum1 += xf1[x + size] - xf1[x]; \ + } else { \ + sum0 -= xf0[x]; \ + sum1 -= xf1[x]; \ + cnt--; \ + } \ + } \ + } \ + } \ +} + +HBLUR_TRANSITION(8, uint8_t, 1) +HBLUR_TRANSITION(16, uint16_t, 2) + +#define FADEGRAYS_TRANSITION(name, type, div) \ +static void fadegrays##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int width = out->width; \ + const int is_rgb = s->is_rgb; \ + const int mid = (s->max_value + 1) / 2; \ + const float phase = 0.2f; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + int bg[2][4]; \ + if (is_rgb) { \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + \ + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + \ + y * b->linesize[p]); \ + if (p == 3) { \ + bg[0][3] = xf0[x]; \ + bg[1][3] = xf1[x]; \ + } else { \ + bg[0][0] += xf0[x]; \ + bg[1][0] += xf1[x]; \ + } \ + } \ + bg[0][0] = bg[0][0] / 3; \ + bg[1][0] = bg[1][0] / 3; \ + bg[0][1] = bg[0][2] = bg[0][0]; \ + bg[1][1] = bg[1][2] = bg[1][0]; \ + } else { \ + const type *yf0 = (const type *)(a->data[0] + \ + y * a->linesize[0]); \ + const type *yf1 = (const type *)(b->data[0] + \ + y * a->linesize[0]); \ + bg[0][0] = yf0[x]; \ + bg[1][0] = yf1[x]; \ + if (s->nb_planes == 4) { \ + const type *af0 = (const type *)(a->data[3] + \ + y * a->linesize[3]); \ + const type *af1 = (const type *)(b->data[3] + \ + y * a->linesize[3]); \ + bg[0][3] = af0[x]; \ + bg[1][3] = af1[x]; \ + } \ + bg[0][1] = bg[1][1] = mid; \ + bg[0][2] = bg[1][2] = mid; \ + } \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + y * out->linesize[p]); \ + \ + dst[x] = mix(mix(xf0[x], bg[0][p], \ + smoothstep(1.f-phase, 1.f, progress)), \ + mix(bg[1][p], xf1[x], smoothstep(phase, 1.f, progress)), \ + progress); \ + } \ + } \ + } \ +} + +FADEGRAYS_TRANSITION(8, uint8_t, 1) +FADEGRAYS_TRANSITION(16, uint16_t, 2) + +#define WIPETL_TRANSITION(name, type, div) \ +static void wipetl##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const int zw = out->width * progress; \ + const int zh = out->height * progress; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = slice_start + y <= zh && \ + x <= zw ? xf0[x] : xf1[x]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +WIPETL_TRANSITION(8, uint8_t, 1) +WIPETL_TRANSITION(16, uint16_t, 2) + +#define WIPETR_TRANSITION(name, type, div) \ +static void wipetr##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const int zw = out->width * (1.f - progress); \ + const int zh = out->height * progress; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = slice_start + y <= zh && \ + x > zw ? xf0[x] : xf1[x]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +WIPETR_TRANSITION(8, uint8_t, 1) +WIPETR_TRANSITION(16, uint16_t, 2) + +#define WIPEBL_TRANSITION(name, type, div) \ +static void wipebl##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const int zw = out->width * progress; \ + const int zh = out->height * (1.f - progress); \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = slice_start + y > zh && \ + x <= zw ? xf0[x] : xf1[x]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +WIPEBL_TRANSITION(8, uint8_t, 1) +WIPEBL_TRANSITION(16, uint16_t, 2) + +#define WIPEBR_TRANSITION(name, type, div) \ +static void wipebr##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const int zh = out->height * (1.f - progress); \ + const int zw = out->width * (1.f - progress); \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = slice_start + y > zh && \ + x > zw ? xf0[x] : xf1[x]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +WIPEBR_TRANSITION(8, uint8_t, 1) +WIPEBR_TRANSITION(16, uint16_t, 2) + +#define SQUEEZEH_TRANSITION(name, type, div) \ +static void squeezeh##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const float h = out->height; \ + const int height = slice_end - slice_start; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + const float z = .5f + ((slice_start + y) / h - .5f) / progress; \ + \ + if (z < 0.f || z > 1.f) { \ + for (int x = 0; x < out->width; x++) \ + dst[x] = xf1[x]; \ + } else { \ + const int yy = lrintf(z * (h - 1.f)); \ + const type *xf0 = (const type *)(a->data[p] + yy * a->linesize[p]); \ + \ + for (int x = 0; x < out->width; x++) \ + dst[x] = xf0[x]; \ + } \ + \ + dst += out->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +SQUEEZEH_TRANSITION(8, uint8_t, 1) +SQUEEZEH_TRANSITION(16, uint16_t, 2) + +#define SQUEEZEV_TRANSITION(name, type, div) \ +static void squeezev##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const float w = out->width; \ + const int height = slice_end - slice_start; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + const float z = .5f + (x / w - .5f) / progress; \ + \ + if (z < 0.f || z > 1.f) { \ + dst[x] = xf1[x]; \ + } else { \ + const int xx = lrintf(z * (w - 1.f)); \ + \ + dst[x] = xf0[xx]; \ + } \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +SQUEEZEV_TRANSITION(8, uint8_t, 1) +SQUEEZEV_TRANSITION(16, uint16_t, 2) + +static inline double getpix(void *priv, double x, double y, int plane, int nb) +{ + XFadeContext *s = priv; + AVFrame *in = s->xf[nb]; + const uint8_t *src = in->data[FFMIN(plane, s->nb_planes - 1)]; + int linesize = in->linesize[FFMIN(plane, s->nb_planes - 1)]; + const int w = in->width; + const int h = in->height; + + int xi, yi; + + xi = av_clipd(x, 0, w - 1); + yi = av_clipd(y, 0, h - 1); + + if (s->depth > 8) { + const uint16_t *src16 = (const uint16_t*)src; + + linesize /= 2; + return src16[xi + yi * linesize]; + } else { + return src[xi + yi * linesize]; + } +} + +static double a0(void *priv, double x, double y) { return getpix(priv, x, y, 0, 0); } +static double a1(void *priv, double x, double y) { return getpix(priv, x, y, 1, 0); } +static double a2(void *priv, double x, double y) { return getpix(priv, x, y, 2, 0); } +static double a3(void *priv, double x, double y) { return getpix(priv, x, y, 3, 0); } + +static double b0(void *priv, double x, double y) { return getpix(priv, x, y, 0, 1); } +static double b1(void *priv, double x, double y) { return getpix(priv, x, y, 1, 1); } +static double b2(void *priv, double x, double y) { return getpix(priv, x, y, 2, 1); } +static double b3(void *priv, double x, double y) { return getpix(priv, x, y, 3, 1); } + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink0 = ctx->inputs[0]; + AVFilterLink *inlink1 = ctx->inputs[1]; + XFadeContext *s = ctx->priv; + const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink0->format); + + if (inlink0->format != inlink1->format) { + av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n"); + return AVERROR(EINVAL); + } + if (inlink0->w != inlink1->w || inlink0->h != inlink1->h) { + av_log(ctx, AV_LOG_ERROR, "First input link %s parameters " + "(size %dx%d) do not match the corresponding " + "second input link %s parameters (size %dx%d)\n", + ctx->input_pads[0].name, inlink0->w, inlink0->h, + ctx->input_pads[1].name, inlink1->w, inlink1->h); + return AVERROR(EINVAL); + } + + if (inlink0->time_base.num != inlink1->time_base.num || + inlink0->time_base.den != inlink1->time_base.den) { + av_log(ctx, AV_LOG_ERROR, "First input link %s timebase " + "(%d/%d) do not match the corresponding " + "second input link %s timebase (%d/%d)\n", + ctx->input_pads[0].name, inlink0->time_base.num, inlink0->time_base.den, + ctx->input_pads[1].name, inlink1->time_base.num, inlink1->time_base.den); + return AVERROR(EINVAL); + } + + if (!inlink0->frame_rate.num || !inlink0->frame_rate.den) { + av_log(ctx, AV_LOG_ERROR, "The inputs needs to be a constant frame rate; " + "current rate of %d/%d is invalid\n", inlink0->frame_rate.num, inlink0->frame_rate.den); + return AVERROR(EINVAL); + } + + if (inlink0->frame_rate.num != inlink1->frame_rate.num || + inlink0->frame_rate.den != inlink1->frame_rate.den) { + av_log(ctx, AV_LOG_ERROR, "First input link %s frame rate " + "(%d/%d) do not match the corresponding " + "second input link %s frame rate (%d/%d)\n", + ctx->input_pads[0].name, inlink0->frame_rate.num, inlink0->frame_rate.den, + ctx->input_pads[1].name, inlink1->frame_rate.num, inlink1->frame_rate.den); + return AVERROR(EINVAL); + } + + outlink->w = inlink0->w; + outlink->h = inlink0->h; + outlink->time_base = inlink0->time_base; + outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; + outlink->frame_rate = inlink0->frame_rate; + + s->depth = pix_desc->comp[0].depth; + s->is_rgb = !!(pix_desc->flags & AV_PIX_FMT_FLAG_RGB); + s->nb_planes = av_pix_fmt_count_planes(inlink0->format); + s->max_value = (1 << s->depth) - 1; + s->black[0] = 0; + s->black[1] = s->black[2] = s->is_rgb ? 0 : s->max_value / 2; + s->black[3] = s->max_value; + s->white[0] = s->white[3] = s->max_value; + s->white[1] = s->white[2] = s->is_rgb ? s->max_value : s->max_value / 2; + + s->first_pts = s->last_pts = s->pts = AV_NOPTS_VALUE; + + if (s->duration) + s->duration_pts = av_rescale_q(s->duration, AV_TIME_BASE_Q, outlink->time_base); + if (s->offset) + s->offset_pts = av_rescale_q(s->offset, AV_TIME_BASE_Q, outlink->time_base); + + switch (s->transition) { + case CUSTOM: s->transitionf = s->depth <= 8 ? custom8_transition : custom16_transition; break; + case FADE: s->transitionf = s->depth <= 8 ? fade8_transition : fade16_transition; break; + case WIPELEFT: s->transitionf = s->depth <= 8 ? wipeleft8_transition : wipeleft16_transition; break; + case WIPERIGHT: s->transitionf = s->depth <= 8 ? wiperight8_transition : wiperight16_transition; break; + case WIPEUP: s->transitionf = s->depth <= 8 ? wipeup8_transition : wipeup16_transition; break; + case WIPEDOWN: s->transitionf = s->depth <= 8 ? wipedown8_transition : wipedown16_transition; break; + case SLIDELEFT: s->transitionf = s->depth <= 8 ? slideleft8_transition : slideleft16_transition; break; + case SLIDERIGHT: s->transitionf = s->depth <= 8 ? slideright8_transition : slideright16_transition; break; + case SLIDEUP: s->transitionf = s->depth <= 8 ? slideup8_transition : slideup16_transition; break; + case SLIDEDOWN: s->transitionf = s->depth <= 8 ? slidedown8_transition : slidedown16_transition; break; + case CIRCLECROP: s->transitionf = s->depth <= 8 ? circlecrop8_transition : circlecrop16_transition; break; + case RECTCROP: s->transitionf = s->depth <= 8 ? rectcrop8_transition : rectcrop16_transition; break; + case DISTANCE: s->transitionf = s->depth <= 8 ? distance8_transition : distance16_transition; break; + case FADEBLACK: s->transitionf = s->depth <= 8 ? fadeblack8_transition : fadeblack16_transition; break; + case FADEWHITE: s->transitionf = s->depth <= 8 ? fadewhite8_transition : fadewhite16_transition; break; + case RADIAL: s->transitionf = s->depth <= 8 ? radial8_transition : radial16_transition; break; + case SMOOTHLEFT: s->transitionf = s->depth <= 8 ? smoothleft8_transition : smoothleft16_transition; break; + case SMOOTHRIGHT:s->transitionf = s->depth <= 8 ? smoothright8_transition: smoothright16_transition;break; + case SMOOTHUP: s->transitionf = s->depth <= 8 ? smoothup8_transition : smoothup16_transition; break; + case SMOOTHDOWN: s->transitionf = s->depth <= 8 ? smoothdown8_transition : smoothdown16_transition; break; + case CIRCLEOPEN: s->transitionf = s->depth <= 8 ? circleopen8_transition : circleopen16_transition; break; + case CIRCLECLOSE:s->transitionf = s->depth <= 8 ? circleclose8_transition: circleclose16_transition;break; + case VERTOPEN: s->transitionf = s->depth <= 8 ? vertopen8_transition : vertopen16_transition; break; + case VERTCLOSE: s->transitionf = s->depth <= 8 ? vertclose8_transition : vertclose16_transition; break; + case HORZOPEN: s->transitionf = s->depth <= 8 ? horzopen8_transition : horzopen16_transition; break; + case HORZCLOSE: s->transitionf = s->depth <= 8 ? horzclose8_transition : horzclose16_transition; break; + case DISSOLVE: s->transitionf = s->depth <= 8 ? dissolve8_transition : dissolve16_transition; break; + case PIXELIZE: s->transitionf = s->depth <= 8 ? pixelize8_transition : pixelize16_transition; break; + case DIAGTL: s->transitionf = s->depth <= 8 ? diagtl8_transition : diagtl16_transition; break; + case DIAGTR: s->transitionf = s->depth <= 8 ? diagtr8_transition : diagtr16_transition; break; + case DIAGBL: s->transitionf = s->depth <= 8 ? diagbl8_transition : diagbl16_transition; break; + case DIAGBR: s->transitionf = s->depth <= 8 ? diagbr8_transition : diagbr16_transition; break; + case HLSLICE: s->transitionf = s->depth <= 8 ? hlslice8_transition : hlslice16_transition; break; + case HRSLICE: s->transitionf = s->depth <= 8 ? hrslice8_transition : hrslice16_transition; break; + case VUSLICE: s->transitionf = s->depth <= 8 ? vuslice8_transition : vuslice16_transition; break; + case VDSLICE: s->transitionf = s->depth <= 8 ? vdslice8_transition : vdslice16_transition; break; + case HBLUR: s->transitionf = s->depth <= 8 ? hblur8_transition : hblur16_transition; break; + case FADEGRAYS: s->transitionf = s->depth <= 8 ? fadegrays8_transition : fadegrays16_transition; break; + case WIPETL: s->transitionf = s->depth <= 8 ? wipetl8_transition : wipetl16_transition; break; + case WIPETR: s->transitionf = s->depth <= 8 ? wipetr8_transition : wipetr16_transition; break; + case WIPEBL: s->transitionf = s->depth <= 8 ? wipebl8_transition : wipebl16_transition; break; + case WIPEBR: s->transitionf = s->depth <= 8 ? wipebr8_transition : wipebr16_transition; break; + case SQUEEZEH: s->transitionf = s->depth <= 8 ? squeezeh8_transition : squeezeh16_transition; break; + case SQUEEZEV: s->transitionf = s->depth <= 8 ? squeezev8_transition : squeezev16_transition; break; + } + + if (s->transition == CUSTOM) { + static const char *const func2_names[] = { + "a0", "a1", "a2", "a3", + "b0", "b1", "b2", "b3", + NULL + }; + double (*func2[])(void *, double, double) = { + a0, a1, a2, a3, + b0, b1, b2, b3, + NULL }; + int ret; + + if (!s->custom_str) + return AVERROR(EINVAL); + ret = av_expr_parse(&s->e, s->custom_str, var_names, + NULL, NULL, func2_names, func2, 0, ctx); + if (ret < 0) + return ret; + } + + return 0; +} + +static int xfade_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + XFadeContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + ThreadData *td = arg; + int slice_start = (outlink->h * jobnr ) / nb_jobs; + int slice_end = (outlink->h * (jobnr+1)) / nb_jobs; + + s->transitionf(ctx, td->xf[0], td->xf[1], td->out, td->progress, slice_start, slice_end, jobnr); + + return 0; +} + +static int xfade_frame(AVFilterContext *ctx, AVFrame *a, AVFrame *b) +{ + XFadeContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + float progress = av_clipf(1.f - ((float)(s->pts - s->first_pts - s->offset_pts) / s->duration_pts), 0.f, 1.f); + ThreadData td; + AVFrame *out; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) + return AVERROR(ENOMEM); + av_frame_copy_props(out, a); + + td.xf[0] = a, td.xf[1] = b, td.out = out, td.progress = progress; + ctx->internal->execute(ctx, xfade_slice, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); + + out->pts = s->pts; + + return ff_filter_frame(outlink, out); +} + +static int xfade_activate(AVFilterContext *ctx) +{ + XFadeContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *in = NULL; + int ret = 0, status; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx); + + if (s->xfade_is_over) { + if (!s->eof[0]) { + ret = ff_inlink_consume_frame(ctx->inputs[0], &in); + if (ret > 0) + av_frame_free(&in); + } + ret = ff_inlink_consume_frame(ctx->inputs[1], &in); + if (ret < 0) { + return ret; + } else if (ret > 0) { + in->pts = (in->pts - s->last_pts) + s->pts; + return ff_filter_frame(outlink, in); + } else if (ff_inlink_acknowledge_status(ctx->inputs[1], &status, &pts)) { + ff_outlink_set_status(outlink, status, s->pts); + return 0; + } else if (!ret) { + if (ff_outlink_frame_wanted(outlink)) + ff_inlink_request_frame(ctx->inputs[1]); + return 0; + } + } + + if (ff_inlink_queued_frames(ctx->inputs[0]) > 0) { + s->xf[0] = ff_inlink_peek_frame(ctx->inputs[0], 0); + if (s->xf[0]) { + if (s->first_pts == AV_NOPTS_VALUE) { + s->first_pts = s->xf[0]->pts; + } + s->pts = s->xf[0]->pts; + if (s->first_pts + s->offset_pts > s->xf[0]->pts) { + s->xf[0] = NULL; + s->need_second = 0; + ff_inlink_consume_frame(ctx->inputs[0], &in); + return ff_filter_frame(outlink, in); + } + + s->need_second = 1; + } + } + + if (s->xf[0] && ff_inlink_queued_frames(ctx->inputs[1]) > 0) { + ff_inlink_consume_frame(ctx->inputs[0], &s->xf[0]); + ff_inlink_consume_frame(ctx->inputs[1], &s->xf[1]); + + s->last_pts = s->xf[1]->pts; + s->pts = s->xf[0]->pts; + if (s->xf[0]->pts - (s->first_pts + s->offset_pts) > s->duration_pts) + s->xfade_is_over = 1; + ret = xfade_frame(ctx, s->xf[0], s->xf[1]); + av_frame_free(&s->xf[0]); + av_frame_free(&s->xf[1]); + return ret; + } + + if (ff_inlink_queued_frames(ctx->inputs[0]) > 0 && + ff_inlink_queued_frames(ctx->inputs[1]) > 0) { + ff_filter_set_ready(ctx, 100); + return 0; + } + + if (ff_outlink_frame_wanted(outlink)) { + if (!s->eof[0] && ff_outlink_get_status(ctx->inputs[0])) { + s->eof[0] = 1; + s->xfade_is_over = 1; + } + if (!s->eof[1] && ff_outlink_get_status(ctx->inputs[1])) { + s->eof[1] = 1; + } + if (!s->eof[0] && !s->xf[0] && ff_inlink_queued_frames(ctx->inputs[0]) == 0) + ff_inlink_request_frame(ctx->inputs[0]); + if (!s->eof[1] && (s->need_second || s->eof[0]) && ff_inlink_queued_frames(ctx->inputs[1]) == 0) + ff_inlink_request_frame(ctx->inputs[1]); + if (s->eof[0] && s->eof[1] && ( + ff_inlink_queued_frames(ctx->inputs[0]) <= 0 && + ff_inlink_queued_frames(ctx->inputs[1]) <= 0)) { + ff_outlink_set_status(outlink, AVERROR_EOF, AV_NOPTS_VALUE); + } else if (s->xfade_is_over) { + ff_filter_set_ready(ctx, 100); + } + return 0; + } + + return FFERROR_NOT_READY; +} + +static const AVFilterPad xfade_inputs[] = { + { + .name = "main", + .type = AVMEDIA_TYPE_VIDEO, + }, + { + .name = "xfade", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +static const AVFilterPad xfade_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vf_xfade = { + .name = "xfade", + .description = NULL_IF_CONFIG_SMALL("Cross fade one video with another video."), + .priv_size = sizeof(XFadeContext), + .priv_class = &xfade_class, + .query_formats = query_formats, + .activate = xfade_activate, + .uninit = uninit, + .inputs = xfade_inputs, + .outputs = xfade_outputs, + .flags = AVFILTER_FLAG_SLICE_THREADS, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_xfade_opencl.c ffmpeg-4.4/libavfilter/vf_xfade_opencl.c --- ffmpeg-4.2.2/libavfilter/vf_xfade_opencl.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_xfade_opencl.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,439 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "filters.h" +#include "internal.h" +#include "opencl.h" +#include "opencl_source.h" +#include "video.h" + +enum XFadeTransitions { + CUSTOM, + FADE, + WIPELEFT, + WIPERIGHT, + WIPEUP, + WIPEDOWN, + SLIDELEFT, + SLIDERIGHT, + SLIDEUP, + SLIDEDOWN, + NB_TRANSITIONS, +}; + +typedef struct XFadeOpenCLContext { + OpenCLFilterContext ocf; + + int transition; + const char *source_file; + const char *kernel_name; + int64_t duration; + int64_t offset; + + int initialised; + cl_kernel kernel; + cl_command_queue command_queue; + + int nb_planes; + + int64_t duration_pts; + int64_t offset_pts; + int64_t first_pts; + int64_t last_pts; + int64_t pts; + int xfade_is_over; + int need_second; + int eof[2]; + AVFrame *xf[2]; +} XFadeOpenCLContext; + +static int xfade_opencl_load(AVFilterContext *avctx, + enum AVPixelFormat main_format, + enum AVPixelFormat xfade_format) +{ + XFadeOpenCLContext *ctx = avctx->priv; + cl_int cle; + const AVPixFmtDescriptor *main_desc; + int err, main_planes; + const char *kernel_name; + + main_desc = av_pix_fmt_desc_get(main_format); + if (main_format != xfade_format) { + av_log(avctx, AV_LOG_ERROR, "Input formats are not same.\n"); + return AVERROR(EINVAL); + } + + main_planes = 0; + for (int i = 0; i < main_desc->nb_components; i++) + main_planes = FFMAX(main_planes, + main_desc->comp[i].plane + 1); + + ctx->nb_planes = main_planes; + + if (ctx->transition == CUSTOM) { + err = ff_opencl_filter_load_program_from_file(avctx, ctx->source_file); + } else { + err = ff_opencl_filter_load_program(avctx, &ff_opencl_source_xfade, 1); + } + if (err < 0) + return err; + + ctx->command_queue = clCreateCommandQueue(ctx->ocf.hwctx->context, + ctx->ocf.hwctx->device_id, + 0, &cle); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create OpenCL " + "command queue %d.\n", cle); + + switch (ctx->transition) { + case CUSTOM: kernel_name = ctx->kernel_name; break; + case FADE: kernel_name = "fade"; break; + case WIPELEFT: kernel_name = "wipeleft"; break; + case WIPERIGHT: kernel_name = "wiperight"; break; + case WIPEUP: kernel_name = "wipeup"; break; + case WIPEDOWN: kernel_name = "wipedown"; break; + case SLIDELEFT: kernel_name = "slideleft"; break; + case SLIDERIGHT: kernel_name = "slideright"; break; + case SLIDEUP: kernel_name = "slideup"; break; + case SLIDEDOWN: kernel_name = "slidedown"; break; + default: + err = AVERROR_BUG; + goto fail; + } + + ctx->kernel = clCreateKernel(ctx->ocf.program, kernel_name, &cle); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create kernel %d.\n", cle); + + ctx->initialised = 1; + + return 0; + +fail: + if (ctx->command_queue) + clReleaseCommandQueue(ctx->command_queue); + if (ctx->kernel) + clReleaseKernel(ctx->kernel); + return err; +} + +static int xfade_frame(AVFilterContext *avctx, AVFrame *a, AVFrame *b) +{ + AVFilterLink *outlink = avctx->outputs[0]; + XFadeOpenCLContext *ctx = avctx->priv; + AVFrame *output; + cl_int cle; + cl_float progress = av_clipf(1.f - ((cl_float)(ctx->pts - ctx->first_pts - ctx->offset_pts) / ctx->duration_pts), 0.f, 1.f); + size_t global_work[2]; + int kernel_arg = 0; + int err, plane; + + if (!ctx->initialised) { + AVHWFramesContext *main_fc = + (AVHWFramesContext*)a->hw_frames_ctx->data; + AVHWFramesContext *xfade_fc = + (AVHWFramesContext*)b->hw_frames_ctx->data; + + err = xfade_opencl_load(avctx, main_fc->sw_format, + xfade_fc->sw_format); + if (err < 0) + return err; + } + + output = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!output) { + err = AVERROR(ENOMEM); + goto fail; + } + + for (plane = 0; plane < ctx->nb_planes; plane++) { + cl_mem mem; + kernel_arg = 0; + + mem = (cl_mem)output->data[plane]; + CL_SET_KERNEL_ARG(ctx->kernel, kernel_arg, cl_mem, &mem); + kernel_arg++; + + mem = (cl_mem)ctx->xf[0]->data[plane]; + CL_SET_KERNEL_ARG(ctx->kernel, kernel_arg, cl_mem, &mem); + kernel_arg++; + + mem = (cl_mem)ctx->xf[1]->data[plane]; + CL_SET_KERNEL_ARG(ctx->kernel, kernel_arg, cl_mem, &mem); + kernel_arg++; + + CL_SET_KERNEL_ARG(ctx->kernel, kernel_arg, cl_float, &progress); + kernel_arg++; + + err = ff_opencl_filter_work_size_from_image(avctx, global_work, + output, plane, 0); + if (err < 0) + goto fail; + + cle = clEnqueueNDRangeKernel(ctx->command_queue, ctx->kernel, 2, NULL, + global_work, NULL, 0, NULL, NULL); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to enqueue xfade kernel " + "for plane %d: %d.\n", plane, cle); + } + + cle = clFinish(ctx->command_queue); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to finish command queue: %d.\n", cle); + + err = av_frame_copy_props(output, ctx->xf[0]); + if (err < 0) + goto fail; + + output->pts = ctx->pts; + + return ff_filter_frame(outlink, output); + +fail: + av_frame_free(&output); + return err; +} + +static int xfade_opencl_config_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + XFadeOpenCLContext *ctx = avctx->priv; + AVFilterLink *inlink0 = avctx->inputs[0]; + AVFilterLink *inlink1 = avctx->inputs[1]; + int err; + + err = ff_opencl_filter_config_output(outlink); + if (err < 0) + return err; + + if (inlink0->w != inlink1->w || inlink0->h != inlink1->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[0].name, inlink0->w, inlink0->h, + avctx->input_pads[1].name, inlink1->w, inlink1->h); + return AVERROR(EINVAL); + } + + if (inlink0->time_base.num != inlink1->time_base.num || + inlink0->time_base.den != inlink1->time_base.den) { + av_log(avctx, AV_LOG_ERROR, "First input link %s timebase " + "(%d/%d) do not match the corresponding " + "second input link %s timebase (%d/%d)\n", + avctx->input_pads[0].name, inlink0->time_base.num, inlink0->time_base.den, + avctx->input_pads[1].name, inlink1->time_base.num, inlink1->time_base.den); + return AVERROR(EINVAL); + } + + ctx->first_pts = ctx->last_pts = ctx->pts = AV_NOPTS_VALUE; + + outlink->time_base = inlink0->time_base; + outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; + outlink->frame_rate = inlink0->frame_rate; + + if (ctx->duration) + ctx->duration_pts = av_rescale_q(ctx->duration, AV_TIME_BASE_Q, outlink->time_base); + if (ctx->offset) + ctx->offset_pts = av_rescale_q(ctx->offset, AV_TIME_BASE_Q, outlink->time_base); + + return 0; +} + +static int xfade_opencl_activate(AVFilterContext *avctx) +{ + XFadeOpenCLContext *ctx = avctx->priv; + AVFilterLink *outlink = avctx->outputs[0]; + AVFrame *in = NULL; + int ret = 0, status; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, avctx); + + if (ctx->xfade_is_over) { + ret = ff_inlink_consume_frame(avctx->inputs[1], &in); + if (ret < 0) { + return ret; + } else if (ret > 0) { + in->pts = (in->pts - ctx->last_pts) + ctx->pts; + return ff_filter_frame(outlink, in); + } else if (ff_inlink_acknowledge_status(avctx->inputs[1], &status, &pts)) { + ff_outlink_set_status(outlink, status, ctx->pts); + return 0; + } else if (!ret) { + if (ff_outlink_frame_wanted(outlink)) { + ff_inlink_request_frame(avctx->inputs[1]); + return 0; + } + } + } + + if (ff_inlink_queued_frames(avctx->inputs[0]) > 0) { + ctx->xf[0] = ff_inlink_peek_frame(avctx->inputs[0], 0); + if (ctx->xf[0]) { + if (ctx->first_pts == AV_NOPTS_VALUE) { + ctx->first_pts = ctx->xf[0]->pts; + } + ctx->pts = ctx->xf[0]->pts; + if (ctx->first_pts + ctx->offset_pts > ctx->xf[0]->pts) { + ctx->xf[0] = NULL; + ctx->need_second = 0; + ff_inlink_consume_frame(avctx->inputs[0], &in); + return ff_filter_frame(outlink, in); + } + + ctx->need_second = 1; + } + } + + if (ctx->xf[0] && ff_inlink_queued_frames(avctx->inputs[1]) > 0) { + ff_inlink_consume_frame(avctx->inputs[0], &ctx->xf[0]); + ff_inlink_consume_frame(avctx->inputs[1], &ctx->xf[1]); + + ctx->last_pts = ctx->xf[1]->pts; + ctx->pts = ctx->xf[0]->pts; + if (ctx->xf[0]->pts - (ctx->first_pts + ctx->offset_pts) > ctx->duration_pts) + ctx->xfade_is_over = 1; + ret = xfade_frame(avctx, ctx->xf[0], ctx->xf[1]); + av_frame_free(&ctx->xf[0]); + av_frame_free(&ctx->xf[1]); + return ret; + } + + if (ff_inlink_queued_frames(avctx->inputs[0]) > 0 && + ff_inlink_queued_frames(avctx->inputs[1]) > 0) { + ff_filter_set_ready(avctx, 100); + return 0; + } + + if (ff_outlink_frame_wanted(outlink)) { + if (!ctx->eof[0] && ff_outlink_get_status(avctx->inputs[0])) { + ctx->eof[0] = 1; + ctx->xfade_is_over = 1; + } + if (!ctx->eof[1] && ff_outlink_get_status(avctx->inputs[1])) { + ctx->eof[1] = 1; + } + if (!ctx->eof[0] && !ctx->xf[0]) + ff_inlink_request_frame(avctx->inputs[0]); + if (!ctx->eof[1] && (ctx->need_second || ctx->eof[0])) + ff_inlink_request_frame(avctx->inputs[1]); + if (ctx->eof[0] && ctx->eof[1] && ( + ff_inlink_queued_frames(avctx->inputs[0]) <= 0 || + ff_inlink_queued_frames(avctx->inputs[1]) <= 0)) + ff_outlink_set_status(outlink, AVERROR_EOF, AV_NOPTS_VALUE); + return 0; + } + + return FFERROR_NOT_READY; +} + +static av_cold void xfade_opencl_uninit(AVFilterContext *avctx) +{ + XFadeOpenCLContext *ctx = avctx->priv; + cl_int cle; + + if (ctx->kernel) { + cle = clReleaseKernel(ctx->kernel); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "kernel: %d.\n", cle); + } + + if (ctx->command_queue) { + cle = clReleaseCommandQueue(ctx->command_queue); + if (cle != CL_SUCCESS) + av_log(avctx, AV_LOG_ERROR, "Failed to release " + "command queue: %d.\n", cle); + } + + ff_opencl_filter_uninit(avctx); +} + +static AVFrame *get_video_buffer(AVFilterLink *inlink, int w, int h) +{ + XFadeOpenCLContext *s = inlink->dst->priv; + + return s->xfade_is_over || !s->need_second ? + ff_null_get_video_buffer (inlink, w, h) : + ff_default_get_video_buffer(inlink, w, h); +} + +#define OFFSET(x) offsetof(XFadeOpenCLContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) + +static const AVOption xfade_opencl_options[] = { + { "transition", "set cross fade transition", OFFSET(transition), AV_OPT_TYPE_INT, {.i64=1}, 0, NB_TRANSITIONS-1, FLAGS, "transition" }, + { "custom", "custom transition", 0, AV_OPT_TYPE_CONST, {.i64=CUSTOM}, 0, 0, FLAGS, "transition" }, + { "fade", "fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADE}, 0, 0, FLAGS, "transition" }, + { "wipeleft", "wipe left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPELEFT}, 0, 0, FLAGS, "transition" }, + { "wiperight", "wipe right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPERIGHT}, 0, 0, FLAGS, "transition" }, + { "wipeup", "wipe up transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEUP}, 0, 0, FLAGS, "transition" }, + { "wipedown", "wipe down transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEDOWN}, 0, 0, FLAGS, "transition" }, + { "slideleft", "slide left transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDELEFT}, 0, 0, FLAGS, "transition" }, + { "slideright", "slide right transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDERIGHT}, 0, 0, FLAGS, "transition" }, + { "slideup", "slide up transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEUP}, 0, 0, FLAGS, "transition" }, + { "slidedown", "slide down transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEDOWN}, 0, 0, FLAGS, "transition" }, + { "source", "set OpenCL program source file for custom transition", OFFSET(source_file), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = FLAGS }, + { "kernel", "set kernel name in program file for custom transition", OFFSET(kernel_name), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = FLAGS }, + { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=1000000}, 0, 60000000, FLAGS }, + { "offset", "set cross fade start relative to first input stream", OFFSET(offset), AV_OPT_TYPE_DURATION, {.i64=0}, INT64_MIN, INT64_MAX, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(xfade_opencl); + +static const AVFilterPad xfade_opencl_inputs[] = { + { + .name = "main", + .type = AVMEDIA_TYPE_VIDEO, + .get_video_buffer = get_video_buffer, + .config_props = &ff_opencl_filter_config_input, + }, + { + .name = "xfade", + .type = AVMEDIA_TYPE_VIDEO, + .get_video_buffer = get_video_buffer, + .config_props = &ff_opencl_filter_config_input, + }, + { NULL } +}; + +static const AVFilterPad xfade_opencl_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &xfade_opencl_config_output, + }, + { NULL } +}; + +AVFilter ff_vf_xfade_opencl = { + .name = "xfade_opencl", + .description = NULL_IF_CONFIG_SMALL("Cross fade one video with another video."), + .priv_size = sizeof(XFadeOpenCLContext), + .priv_class = &xfade_opencl_class, + .init = &ff_opencl_filter_init, + .uninit = &xfade_opencl_uninit, + .query_formats = &ff_opencl_filter_query_formats, + .activate = &xfade_opencl_activate, + .inputs = xfade_opencl_inputs, + .outputs = xfade_opencl_outputs, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_xmedian.c ffmpeg-4.4/libavfilter/vf_xmedian.c --- ffmpeg-4.2.2/libavfilter/vf_xmedian.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_xmedian.c 2021-04-08 21:28:40.000000000 +0000 @@ -35,9 +35,13 @@ const AVClass *class; const AVPixFmtDescriptor *desc; int nb_inputs; + int nb_frames; int planes; + float percentile; + int tmedian; int radius; + int index; int depth; int max; int nb_planes; @@ -75,6 +79,11 @@ AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_NONE }; AVFilterFormats *formats = ff_make_format_list(pixel_fmts); @@ -88,12 +97,23 @@ XMedianContext *s = ctx->priv; int ret; - s->radius = s->nb_inputs / 2; + s->tmedian = !strcmp(ctx->filter->name, "tmedian"); + + if (!s->tmedian) { + s->radius = s->nb_inputs / 2; + } else { + s->nb_inputs = s->radius * 2 + 1; + } + + if (s->nb_inputs & 1) + s->index = s->radius * 2.f * s->percentile; + else + s->index = av_clip(s->radius * 2.f * s->percentile, 1, s->nb_inputs - 1); s->frames = av_calloc(s->nb_inputs, sizeof(*s->frames)); if (!s->frames) return AVERROR(ENOMEM); - for (int i = 0; i < s->nb_inputs; i++) { + for (int i = 0; i < s->nb_inputs && !s->tmedian; i++) { AVFilterPad pad = { 0 }; pad.type = AVMEDIA_TYPE_VIDEO; @@ -129,6 +149,7 @@ AVFrame *out = td->out; const int nb_inputs = s->nb_inputs; const int radius = s->radius; + const int index = s->index; int values[256]; for (int p = 0; p < s->nb_planes; p++) { @@ -138,8 +159,8 @@ if (!((1 << p) & s->planes)) { av_image_copy_plane((uint8_t *)dst, out->linesize[p], - in[0]->data[p] + slice_start * in[radius]->linesize[p], - in[0]->linesize[p], + in[radius]->data[p] + slice_start * in[radius]->linesize[p], + in[radius]->linesize[p], s->linesize[p], slice_end - slice_start); continue; } @@ -152,10 +173,10 @@ } AV_QSORT(values, nb_inputs, int, comparei); - if (radius & 1) - dst[x] = values[radius]; + if (nb_inputs & 1) + dst[x] = values[index]; else - dst[x] = (values[radius] + values[radius - 1]) >> 1; + dst[x] = (values[index] + values[index - 1]) >> 1; } dst += out->linesize[p] / 2; @@ -173,6 +194,7 @@ AVFrame *out = td->out; const int nb_inputs = s->nb_inputs; const int radius = s->radius; + const int index = s->index; int values[256]; for (int p = 0; p < s->nb_planes; p++) { @@ -182,8 +204,8 @@ if (!((1 << p) & s->planes)) { av_image_copy_plane(dst, out->linesize[p], - in[0]->data[p] + slice_start * in[0]->linesize[p], - in[0]->linesize[p], + in[radius]->data[p] + slice_start * in[radius]->linesize[p], + in[radius]->linesize[p], s->linesize[p], slice_end - slice_start); continue; } @@ -194,10 +216,10 @@ values[i] = in[i]->data[p][y * in[i]->linesize[p] + x]; AV_QSORT(values, nb_inputs, int, comparei); - if (radius & 1) - dst[x] = values[radius]; + if (nb_inputs & 1) + dst[x] = values[index]; else - dst[x] = (values[radius] + values[radius - 1]) >> 1; + dst[x] = (values[index] + values[index - 1]) >> 1; } dst += out->linesize[p]; @@ -222,14 +244,20 @@ return ret; } - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (ctx->is_disabled) { + out = av_frame_clone(in[0]); + } else { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + } if (!out) return AVERROR(ENOMEM); out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); - td.in = in; - td.out = out; - ctx->internal->execute(ctx, s->median_frames, &td, NULL, FFMIN(s->height[1], ff_filter_get_nb_threads(ctx))); + if (!ctx->is_disabled) { + td.in = in; + td.out = out; + ctx->internal->execute(ctx, s->median_frames, &td, NULL, FFMIN(s->height[1], ff_filter_get_nb_threads(ctx))); + } return ff_filter_frame(outlink, out); } @@ -246,7 +274,7 @@ FFFrameSyncIn *in; int i, ret; - for (int i = 1; i < s->nb_inputs; i++) { + for (int i = 1; i < s->nb_inputs && !s->tmedian; i++) { if (ctx->inputs[i]->h != height || ctx->inputs[i]->w != width) { av_log(ctx, AV_LOG_ERROR, "Input %d size (%dx%d) does not match input %d size (%dx%d).\n", i, ctx->inputs[i]->w, ctx->inputs[i]->h, 0, width, height); return AVERROR(EINVAL); @@ -273,6 +301,9 @@ s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h); s->height[0] = s->height[3] = inlink->h; + if (s->tmedian) + return 0; + outlink->w = width; outlink->h = height; outlink->frame_rate = frame_rate; @@ -291,7 +322,7 @@ in[i].time_base = inlink->time_base; in[i].sync = 1; in[i].before = EXT_STOP; - in[i].after = EXT_STOP; + in[i].after = EXT_INFINITY; } ret = ff_framesync_configure(&s->fs); @@ -305,10 +336,12 @@ XMedianContext *s = ctx->priv; ff_framesync_uninit(&s->fs); - av_freep(&s->frames); - for (int i = 0; i < ctx->nb_inputs; i++) + for (int i = 0; i < ctx->nb_inputs && !s->tmedian; i++) av_freep(&ctx->input_pads[i].name); + for (int i = 0; i < s->nb_frames && s->frames && s->tmedian; i++) + av_frame_free(&s->frames[i]); + av_freep(&s->frames); } static int activate(AVFilterContext *ctx) @@ -317,12 +350,32 @@ return ff_framesync_activate(&s->fs); } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + XMedianContext *s = ctx->priv; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + if (s->nb_inputs & 1) + s->index = s->radius * 2.f * s->percentile; + else + s->index = av_clip(s->radius * 2.f * s->percentile, 1, s->nb_inputs - 1); + + return 0; +} + #define OFFSET(x) offsetof(XMedianContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +#define TFLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption xmedian_options[] = { { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=3}, 3, 255, .flags = FLAGS }, - { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15}, 0, 15, .flags = FLAGS }, + { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15}, 0, 15, .flags =TFLAGS }, + { "percentile", "set percentile", OFFSET(percentile),AV_OPT_TYPE_FLOAT,{.dbl=0.5}, 0, 1, .flags =TFLAGS }, { NULL }, }; @@ -335,7 +388,8 @@ { NULL } }; -AVFILTER_DEFINE_CLASS(xmedian); +#if CONFIG_XMEDIAN_FILTER +FRAMESYNC_DEFINE_CLASS(xmedian, XMedianContext, fs); AVFilter ff_vf_xmedian = { .name = "xmedian", @@ -344,8 +398,95 @@ .priv_class = &xmedian_class, .query_formats = query_formats, .outputs = outputs, + .preinit = xmedian_framesync_preinit, .init = init, .uninit = uninit, .activate = activate, - .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = process_command, }; + +#endif /* CONFIG_XMEDIAN_FILTER */ + +#if CONFIG_TMEDIAN_FILTER +static int tmedian_filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + XMedianContext *s = ctx->priv; + ThreadData td; + AVFrame *out; + + if (s->nb_frames < s->nb_inputs) { + s->frames[s->nb_frames] = in; + s->nb_frames++; + if (s->nb_frames < s->nb_inputs) + return 0; + } else { + av_frame_free(&s->frames[0]); + memmove(&s->frames[0], &s->frames[1], sizeof(*s->frames) * (s->nb_inputs - 1)); + s->frames[s->nb_inputs - 1] = in; + } + + if (ctx->is_disabled) { + out = av_frame_clone(s->frames[0]); + if (!out) + return AVERROR(ENOMEM); + return ff_filter_frame(outlink, out); + } + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) + return AVERROR(ENOMEM); + out->pts = s->frames[0]->pts; + + td.out = out; + td.in = s->frames; + ctx->internal->execute(ctx, s->median_frames, &td, NULL, FFMIN(s->height[0], ff_filter_get_nb_threads(ctx))); + + return ff_filter_frame(outlink, out); +} + +static const AVOption tmedian_options[] = { + { "radius", "set median filter radius", OFFSET(radius), AV_OPT_TYPE_INT, {.i64=1}, 1, 127, .flags = FLAGS }, + { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=15}, 0, 15, .flags =TFLAGS }, + { "percentile", "set percentile", OFFSET(percentile), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, .flags =TFLAGS }, + { NULL }, +}; + +static const AVFilterPad tmedian_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = tmedian_filter_frame, + }, + { NULL } +}; + +static const AVFilterPad tmedian_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(tmedian); + +AVFilter ff_vf_tmedian = { + .name = "tmedian", + .description = NULL_IF_CONFIG_SMALL("Pick median pixels from successive frames."), + .priv_size = sizeof(XMedianContext), + .priv_class = &tmedian_class, + .query_formats = query_formats, + .inputs = tmedian_inputs, + .outputs = tmedian_outputs, + .init = init, + .uninit = uninit, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, +}; + +#endif /* CONFIG_TMEDIAN_FILTER */ diff -Nru ffmpeg-4.2.2/libavfilter/vf_yadif.c ffmpeg-4.4/libavfilter/vf_yadif.c --- ffmpeg-4.2.2/libavfilter/vf_yadif.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_yadif.c 2020-07-11 10:39:30.000000000 +0000 @@ -265,42 +265,19 @@ static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_YUV422P, - AV_PIX_FMT_YUV444P, - AV_PIX_FMT_YUV410P, - AV_PIX_FMT_YUV411P, - AV_PIX_FMT_GRAY8, - AV_PIX_FMT_YUVJ420P, - AV_PIX_FMT_YUVJ422P, - AV_PIX_FMT_YUVJ444P, - AV_PIX_FMT_GRAY16, - AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, - AV_PIX_FMT_YUV420P9, - AV_PIX_FMT_YUV422P9, - AV_PIX_FMT_YUV444P9, - AV_PIX_FMT_YUV420P10, - AV_PIX_FMT_YUV422P10, - AV_PIX_FMT_YUV444P10, - AV_PIX_FMT_YUV420P12, - AV_PIX_FMT_YUV422P12, - AV_PIX_FMT_YUV444P12, - AV_PIX_FMT_YUV420P14, - AV_PIX_FMT_YUV422P14, - AV_PIX_FMT_YUV444P14, - AV_PIX_FMT_YUV420P16, - AV_PIX_FMT_YUV422P16, - AV_PIX_FMT_YUV444P16, - AV_PIX_FMT_YUVA420P, - AV_PIX_FMT_YUVA422P, - AV_PIX_FMT_YUVA444P, - AV_PIX_FMT_GBRP, - AV_PIX_FMT_GBRP9, - AV_PIX_FMT_GBRP10, - AV_PIX_FMT_GBRP12, - AV_PIX_FMT_GBRP14, - AV_PIX_FMT_GBRP16, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP, AV_PIX_FMT_NONE }; @@ -311,26 +288,26 @@ return ff_set_common_formats(ctx, fmts_list); } -static int config_props(AVFilterLink *link) +static int config_output(AVFilterLink *outlink) { - AVFilterContext *ctx = link->src; + AVFilterContext *ctx = outlink->src; YADIFContext *s = ctx->priv; - 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; + outlink->time_base.num = ctx->inputs[0]->time_base.num; + outlink->time_base.den = ctx->inputs[0]->time_base.den * 2; + outlink->w = ctx->inputs[0]->w; + outlink->h = ctx->inputs[0]->h; if(s->mode & 1) - link->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate, + outlink->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate, (AVRational){2, 1}); - if (link->w < 3 || link->h < 3) { + if (outlink->w < 3 || outlink->h < 3) { av_log(ctx, AV_LOG_ERROR, "Video of less than 3 columns or lines is not supported\n"); return AVERROR(EINVAL); } - s->csp = av_pix_fmt_desc_get(link->format); + s->csp = av_pix_fmt_desc_get(outlink->format); s->filter = filter; if (s->csp->comp[0].depth > 8) { s->filter_line = filter_line_c_16bit; @@ -369,7 +346,7 @@ .name = "default", .type = AVMEDIA_TYPE_VIDEO, .request_frame = ff_yadif_request_frame, - .config_props = config_props, + .config_props = config_output, }, { NULL } }; diff -Nru ffmpeg-4.2.2/libavfilter/vf_yadif_cuda.c ffmpeg-4.4/libavfilter/vf_yadif_cuda.c --- ffmpeg-4.2.2/libavfilter/vf_yadif_cuda.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_yadif_cuda.c 2021-04-08 21:28:40.000000000 +0000 @@ -216,10 +216,10 @@ int ret; if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), - &ctx->inputs[0]->out_formats)) < 0) + &ctx->inputs[0]->outcfg.formats)) < 0) return ret; if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), - &ctx->outputs[0]->in_formats)) < 0) + &ctx->outputs[0]->incfg.formats)) < 0) return ret; return 0; diff -Nru ffmpeg-4.2.2/libavfilter/vf_yaepblur.c ffmpeg-4.4/libavfilter/vf_yaepblur.c --- ffmpeg-4.2.2/libavfilter/vf_yaepblur.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_yaepblur.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,349 @@ +/* + * Copyright (C) 2019 Leo Zhang + + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * yaep(yet another edge preserving) blur filter + * + * This implementation is based on an algorithm described in + * "J. S. Lee, Digital image enhancement and noise filtering by use of local statistics, IEEE Trans. Pattern + * Anal. Mach. Intell. PAMI-2, 1980." + */ + +#include "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "avfilter.h" +#include "internal.h" + +typedef struct YAEPContext { + const AVClass *class; + + int planes; + int radius; + int sigma; + + int nb_planes; + int planewidth[4]; + int planeheight[4]; + int depth; + + uint64_t *sat; ///< summed area table + uint64_t *square_sat; ///< square summed area table + int sat_linesize; + + int (*pre_calculate_row)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + int (*filter_slice )(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); +} YAEPContext; + +static av_cold void uninit(AVFilterContext *ctx) +{ + YAEPContext *s = ctx->priv; + av_freep(&s->sat); + av_freep(&s->square_sat); +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA444P12, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE + }; + + return ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); +} + +typedef struct ThreadData { + int width; + int height; + int src_linesize; + int dst_linesize; + uint8_t *src; + uint8_t *dst; +} ThreadData; + +#define PRE_CALCULATE_ROW(type, name) \ +static int pre_calculate_row_##name(AVFilterContext *ctx, void *arg, \ + int jobnr, int nb_jobs) \ +{ \ + ThreadData *td = arg; \ + YAEPContext *s = ctx->priv; \ + \ + const int width = td->width; \ + const int height = td->height; \ + const int linesize = td->src_linesize / sizeof(type); \ + const int sat_linesize = s->sat_linesize; \ + \ + const int starty = height * jobnr / nb_jobs; \ + const int endy = height * (jobnr+1) / nb_jobs; \ + \ + uint64_t *sat = s->sat + (starty + 1) * sat_linesize; \ + uint64_t *square_sat = s->square_sat + (starty + 1) * sat_linesize; \ + const type *src = (const type *)td->src + starty * linesize; \ + \ + int x, y; \ + \ + for (y = starty; y < endy; y++) { \ + for (x = 0; x < width; x++) { \ + sat[x+1] = sat[x] + src[x]; \ + square_sat[x+1] = square_sat[x] + (uint64_t)src[x] * src[x]; \ + } \ + sat += sat_linesize; \ + square_sat += sat_linesize; \ + src += linesize; \ + } \ + \ + return 0; \ +} + +PRE_CALCULATE_ROW(uint8_t, byte) +PRE_CALCULATE_ROW(uint16_t, word) + +static int pre_calculate_col(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + ThreadData *td = arg; + YAEPContext *s = ctx->priv; + + const int width = td->width; + const int height = td->height; + const int sat_linesize = s->sat_linesize; + + const int startx = width * jobnr / nb_jobs; + const int endx = width * (jobnr + 1) / nb_jobs; + + uint64_t *sat, *square_sat; + int x, y; + + for (x = startx; x < endx; x++) { + sat = s->sat + x + 1; + square_sat = s->square_sat + x + 1; + for (y = 0; y < height; y++) { + *(sat+sat_linesize) += *sat; + *(square_sat+sat_linesize) += *square_sat; + sat += sat_linesize; + square_sat += sat_linesize; + } + } + + return 0; +} + +#define FILTER_SLICE(type, name) \ +static int filter_slice_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ +{ \ + ThreadData *td = arg; \ + YAEPContext *s = ctx->priv; \ + \ + const int width = td->width; \ + const int height = td->height; \ + const int src_linesize = td->src_linesize / sizeof(type); \ + const int dst_linesize = td->dst_linesize / sizeof(type); \ + const int sat_linesize = s->sat_linesize; \ + const int sigma = s->sigma; \ + const int radius = s->radius; \ + \ + uint64_t *sat = s->sat; \ + uint64_t *square_sat = s->square_sat; \ + const type *src = (const type *)td->src; \ + type *dst = (type *)td->dst; \ + \ + const int starty = height * jobnr / nb_jobs; \ + const int endy = height * (jobnr + 1) / nb_jobs; \ + \ + int x, y; \ + int lower_x, higher_x; \ + int lower_y, higher_y; \ + int dist_y, count; \ + uint64_t sum, square_sum, mean, var; \ + \ + for (y = starty; y < endy; y++) { \ + lower_y = y - radius < 0 ? 0 : y - radius; \ + higher_y = y + radius + 1 > height ? height : y + radius + 1; \ + dist_y = higher_y - lower_y; \ + for (x = 0; x < width; x++) { \ + lower_x = x - radius < 0 ? 0 : x - radius; \ + higher_x = x + radius + 1 > width ? width : x + radius + 1; \ + count = dist_y * (higher_x - lower_x); \ + sum = sat[higher_y * sat_linesize + higher_x] \ + - sat[higher_y * sat_linesize + lower_x] \ + - sat[lower_y * sat_linesize + higher_x] \ + + sat[lower_y * sat_linesize + lower_x]; \ + square_sum = square_sat[higher_y * sat_linesize + higher_x] \ + - square_sat[higher_y * sat_linesize + lower_x] \ + - square_sat[lower_y * sat_linesize + higher_x] \ + + square_sat[lower_y * sat_linesize + lower_x]; \ + mean = sum / count; \ + var = (square_sum - sum * sum / count) / count; \ + dst[y * dst_linesize + x] = (sigma * mean + var * src[y * src_linesize + x]) / (sigma + var); \ + } \ + } \ + return 0; \ +} + +FILTER_SLICE(uint8_t, byte) +FILTER_SLICE(uint16_t, word) + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + YAEPContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + int plane; + const int nb_threads = ff_filter_get_nb_threads(ctx); + ThreadData td; + + 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); + } + + for (plane = 0; plane < s->nb_planes; plane++) { + if (!s->radius || !(s->planes & (1<data[plane], out->linesize[plane], + in->data[plane], in->linesize[plane], + s->planewidth[plane] * ((s->depth + 7) / 8), + s->planeheight[plane]); + } + continue; + } + + td.width = s->planewidth[plane]; + td.height = s->planeheight[plane]; + td.src = in->data[plane]; + td.src_linesize = in->linesize[plane]; + ctx->internal->execute(ctx, s->pre_calculate_row, &td, NULL, FFMIN(td.height, nb_threads)); + ctx->internal->execute(ctx, pre_calculate_col, &td, NULL, FFMIN(td.width, nb_threads)); + + td.dst = out->data[plane]; + td.dst_linesize = out->linesize[plane]; + ctx->internal->execute(ctx, s->filter_slice, &td, NULL, FFMIN(td.height, nb_threads)); + } + + if (out != in) + av_frame_free(&in); + + return ff_filter_frame(outlink, out); +} + +static int config_input(AVFilterLink *inlink) +{ + YAEPContext *s = inlink->dst->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + + s->depth = desc->comp[0].depth; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + 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->radius = FFMIN(s->radius, AV_CEIL_RSHIFT(FFMIN(inlink->w, inlink->h), 1)); + + if (s->depth <= 8) { + s->pre_calculate_row = pre_calculate_row_byte; + s->filter_slice = filter_slice_byte; + } else { + s->pre_calculate_row = pre_calculate_row_word; + s->filter_slice = filter_slice_word; + } + + // padding one row on the top, and padding one col on the left, that is why + 1 below + s->sat_linesize = inlink->w + 1; + s->sat = av_mallocz_array(inlink->h + 1, s->sat_linesize*sizeof(*s->sat)); + if (!s->sat) + return AVERROR(ENOMEM); + + s->square_sat = av_mallocz_array(inlink->h + 1, s->sat_linesize*sizeof(*s->square_sat)); + if (!s->square_sat) + return AVERROR(ENOMEM); + + return 0; +} + +static const AVFilterPad yaep_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad yaep_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +#define OFFSET(x) offsetof(YAEPContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption yaepblur_options[] = { + { "radius", "set window radius", OFFSET(radius), AV_OPT_TYPE_INT, {.i64=3}, 0, INT_MAX, .flags=FLAGS }, + { "r" , "set window radius", OFFSET(radius), AV_OPT_TYPE_INT, {.i64=3}, 0, INT_MAX, .flags=FLAGS }, + { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=1}, 0, 0xF, .flags=FLAGS }, + { "p", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=1}, 0, 0xF, .flags=FLAGS }, + { "sigma", "set blur strength", OFFSET(sigma), AV_OPT_TYPE_INT, {.i64=128}, 1, INT_MAX, .flags=FLAGS }, + { "s", "set blur strength", OFFSET(sigma), AV_OPT_TYPE_INT, {.i64=128}, 1, INT_MAX, .flags=FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(yaepblur); + +AVFilter ff_vf_yaepblur = { + .name = "yaepblur", + .description = NULL_IF_CONFIG_SMALL("Yet another edge preserving blur filter."), + .priv_size = sizeof(YAEPContext), + .priv_class = &yaepblur_class, + .uninit = uninit, + .query_formats = query_formats, + .inputs = yaep_inputs, + .outputs = yaep_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vf_zoompan.c ffmpeg-4.4/libavfilter/vf_zoompan.c --- ffmpeg-4.2.2/libavfilter/vf_zoompan.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_zoompan.c 2021-04-08 21:28:40.000000000 +0000 @@ -38,7 +38,8 @@ "on", "duration", "pduration", - "time", + "in_time", "it", + "out_time", "time", "ot", "frame", "zoom", "pzoom", @@ -61,7 +62,8 @@ VAR_ON, VAR_DURATION, VAR_PDURATION, - VAR_TIME, + VAR_IN_TIME, VAR_IT, + VAR_TIME, VAR_OUT_TIME, VAR_OT, VAR_FRAME, VAR_ZOOM, VAR_PZOOM, @@ -155,6 +157,7 @@ { ZPContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + AVFilterLink *inlink = ctx->inputs[0]; int64_t pts = s->frame_count; int k, x, y, w, h, ret = 0; uint8_t *input[4]; @@ -165,7 +168,10 @@ var_values[VAR_PY] = s->y; var_values[VAR_PZOOM] = s->prev_zoom; var_values[VAR_PDURATION] = s->prev_nb_frames; - var_values[VAR_TIME] = pts * av_q2d(outlink->time_base); + var_values[VAR_IN_TIME] = var_values[VAR_IT] = in->pts == AV_NOPTS_VALUE ? + NAN : in->pts * av_q2d(inlink->time_base); + var_values[VAR_OUT_TIME] = pts * av_q2d(outlink->time_base); + var_values[VAR_TIME] = var_values[VAR_OT] = var_values[VAR_OUT_TIME]; var_values[VAR_FRAME] = i; var_values[VAR_ON] = outlink->frame_count_in; @@ -245,6 +251,8 @@ } return ret; error: + sws_freeContext(s->sws); + s->sws = NULL; av_frame_free(&out); return ret; } @@ -257,6 +265,8 @@ int status, ret = 0; int64_t pts; + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + if (s->in && ff_outlink_frame_wanted(outlink)) { double zoom = -1, dx = -1, dy = -1; @@ -344,6 +354,10 @@ sws_freeContext(s->sws); s->sws = NULL; + av_expr_free(s->x_expr); + av_expr_free(s->y_expr); + av_expr_free(s->zoom_expr); + av_frame_free(&s->in); } static const AVFilterPad inputs[] = { diff -Nru ffmpeg-4.2.2/libavfilter/vf_zscale.c ffmpeg-4.4/libavfilter/vf_zscale.c --- ffmpeg-4.2.2/libavfilter/vf_zscale.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vf_zscale.c 2021-04-08 21:28:40.000000000 +0000 @@ -44,6 +44,8 @@ #include "libavutil/imgutils.h" #include "libavutil/avassert.h" +#define ZIMG_ALIGNMENT 32 + static const char *const var_names[] = { "in_w", "iw", "in_h", "ih", @@ -99,6 +101,8 @@ char *size_str; double nominal_peak_luminance; int approximate_gamma; + double param_a; + double param_b; char *w_expr; ///< width expression string char *h_expr; ///< height expression string @@ -185,10 +189,10 @@ }; int ret; - ret = ff_formats_ref(ff_make_format_list(pixel_fmts), &ctx->inputs[0]->out_formats); + ret = ff_formats_ref(ff_make_format_list(pixel_fmts), &ctx->inputs[0]->outcfg.formats); if (ret < 0) return ret; - return ff_formats_ref(ff_make_format_list(pixel_fmts), &ctx->outputs[0]->in_formats); + return ff_formats_ref(ff_make_format_list(pixel_fmts), &ctx->outputs[0]->incfg.formats); } static int config_props(AVFilterLink *outlink) @@ -299,7 +303,7 @@ } else outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; - av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s sar:%d/%d -> w:%d h:%d fmt:%s sar:%d/%d\n", + av_log(ctx, AV_LOG_TRACE, "w:%d h:%d fmt:%s sar:%d/%d -> w:%d h:%d fmt:%s sar:%d/%d\n", inlink ->w, inlink ->h, av_get_pix_fmt_name( inlink->format), inlink->sample_aspect_ratio.num, inlink->sample_aspect_ratio.den, outlink->w, outlink->h, av_get_pix_fmt_name(outlink->format), @@ -502,6 +506,44 @@ return 0; } +static int realign_frame(const AVPixFmtDescriptor *desc, AVFrame **frame) +{ + AVFrame *aligned = NULL; + int ret = 0, plane; + + /* Realign any unaligned input frame. */ + for (plane = 0; plane < 3; plane++) { + int p = desc->comp[plane].plane; + if ((uintptr_t)(*frame)->data[p] % ZIMG_ALIGNMENT || (*frame)->linesize[p] % ZIMG_ALIGNMENT) { + if (!(aligned = av_frame_alloc())) { + ret = AVERROR(ENOMEM); + goto fail; + } + + aligned->format = (*frame)->format; + aligned->width = (*frame)->width; + aligned->height = (*frame)->height; + + if ((ret = av_frame_get_buffer(aligned, ZIMG_ALIGNMENT)) < 0) + goto fail; + + if ((ret = av_frame_copy(aligned, *frame)) < 0) + goto fail; + + if ((ret = av_frame_copy_props(aligned, *frame)) < 0) + goto fail; + + av_frame_free(frame); + *frame = aligned; + return 0; + } + } + +fail: + av_frame_free(&aligned); + return ret; +} + static int filter_frame(AVFilterLink *link, AVFrame *in) { ZScaleContext *s = link->dst->priv; @@ -512,12 +554,14 @@ zimg_image_buffer dst_buf = { ZIMG_API_VERSION }; char buf[32]; int ret = 0, plane; - AVFrame *out; + AVFrame *out = NULL; - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); + if ((ret = realign_frame(desc, &in)) < 0) + goto fail; + + if (!(out = ff_get_video_buffer(outlink, outlink->w, outlink->h))) { + ret = AVERROR(ENOMEM); + goto fail; } av_frame_copy_props(out, in); @@ -546,11 +590,8 @@ link->dst->inputs[0]->w = in->width; link->dst->inputs[0]->h = in->height; - if ((ret = config_props(outlink)) < 0) { - av_frame_free(&in); - av_frame_free(&out); - return ret; - } + if ((ret = config_props(outlink)) < 0) + goto fail; zimg_image_format_default(&s->src_format, ZIMG_API_VERSION); zimg_image_format_default(&s->dst_format, ZIMG_API_VERSION); @@ -562,6 +603,8 @@ s->params.resample_filter_uv = s->filter; s->params.nominal_peak_luminance = s->nominal_peak_luminance; s->params.allow_approximate_gamma = s->approximate_gamma; + s->params.filter_param_a = s->params.filter_param_a_uv = s->param_a; + s->params.filter_param_b = s->params.filter_param_b_uv = s->param_b; format_init(&s->src_format, in, desc, s->colorspace_in, s->primaries_in, s->trc_in, s->range_in, s->chromal_in); @@ -702,7 +745,7 @@ return ff_filter_frame(outlink, out); } -static void uninit(AVFilterContext *ctx) +static av_cold void uninit(AVFilterContext *ctx) { ZScaleContext *s = ctx->priv; @@ -738,12 +781,13 @@ #define OFFSET(x) offsetof(ZScaleContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define TFLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption zscale_options[] = { - { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = FLAGS }, - { "width", "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 }, - { "height", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, + { "width", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, + { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, + { "height", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = TFLAGS }, { "size", "set video size", OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, { "s", "set video size", OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, { "dither", "set dither type", OFFSET(dither), AV_OPT_TYPE_INT, {.i64 = 0}, 0, ZIMG_DITHER_ERROR_DIFFUSION, FLAGS, "dither" }, @@ -789,6 +833,7 @@ { "smpte431", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_ST431_2}, 0, 0, FLAGS, "primaries" }, { "smpte432", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_ST432_1}, 0, 0, FLAGS, "primaries" }, { "jedec-p22", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_EBU3213_E}, 0, 0, FLAGS, "primaries" }, + { "ebu3213", 0, 0, AV_OPT_TYPE_CONST, {.i64 = ZIMG_PRIMARIES_EBU3213_E}, 0, 0, FLAGS, "primaries" }, { "transfer", "set transfer characteristic", OFFSET(trc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "transfer" }, { "t", "set transfer characteristic", OFFSET(trc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, FLAGS, "transfer" }, { "input", 0, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, FLAGS, "transfer" }, @@ -856,6 +901,9 @@ { "cin", "set input chroma location", OFFSET(chromal_in), AV_OPT_TYPE_INT, {.i64 = -1}, -1, ZIMG_CHROMA_BOTTOM, FLAGS, "chroma" }, { "npl", "set nominal peak luminance", OFFSET(nominal_peak_luminance), AV_OPT_TYPE_DOUBLE, {.dbl = NAN}, 0, DBL_MAX, FLAGS }, { "agamma", "allow approximate gamma", OFFSET(approximate_gamma), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, + { "param_a", "parameter A, which is parameter \"b\" for bicubic, " + "and the number of filter taps for lanczos", OFFSET(param_a), AV_OPT_TYPE_DOUBLE, {.dbl = NAN}, -DBL_MAX, DBL_MAX, FLAGS }, + { "param_b", "parameter B, which is parameter \"c\" for bicubic", OFFSET(param_b), AV_OPT_TYPE_DOUBLE, {.dbl = NAN}, -DBL_MAX, DBL_MAX, FLAGS }, { NULL } }; diff -Nru ffmpeg-4.2.2/libavfilter/vif.h ffmpeg-4.4/libavfilter/vif.h --- ffmpeg-4.2.2/libavfilter/vif.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vif.h 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017 Ronald S. Bultje + * Copyright (c) 2017 Ashish Pratap Singh + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_VIF_H +#define AVFILTER_VIF_H + +#include "avfilter.h" + +int ff_compute_vif2(AVFilterContext *ctx, + const float *ref, const float *main, int w, int h, + int ref_stride, int main_stride, float *score, + float *data_buf[13], float **temp, int nb_threads); + +#endif /* AVFILTER_VIF_H */ diff -Nru ffmpeg-4.2.2/libavfilter/vsink_nullsink.c ffmpeg-4.4/libavfilter/vsink_nullsink.c --- ffmpeg-4.2.2/libavfilter/vsink_nullsink.c 2016-03-29 02:25:27.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vsink_nullsink.c 2020-07-11 10:39:30.000000000 +0000 @@ -38,9 +38,7 @@ AVFilter ff_vsink_nullsink = { .name = "nullsink", .description = NULL_IF_CONFIG_SMALL("Do absolutely nothing with the input video."), - - .priv_size = 0, - - .inputs = avfilter_vsink_nullsink_inputs, - .outputs = NULL, + .priv_size = 0, + .inputs = avfilter_vsink_nullsink_inputs, + .outputs = NULL, }; diff -Nru ffmpeg-4.2.2/libavfilter/vsrc_cellauto.c ffmpeg-4.4/libavfilter/vsrc_cellauto.c --- ffmpeg-4.2.2/libavfilter/vsrc_cellauto.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vsrc_cellauto.c 2020-07-11 10:39:30.000000000 +0000 @@ -50,7 +50,7 @@ uint64_t pts; AVRational frame_rate; double random_fill_ratio; - uint32_t random_seed; + int64_t random_seed; int stitch, scroll, start_full; int64_t generation; ///< the generation number, starting from 0 AVLFG lfg; @@ -72,8 +72,8 @@ { "rule", "set rule", OFFSET(rule), AV_OPT_TYPE_INT, {.i64 = 110}, 0, 255, FLAGS }, { "random_fill_ratio", "set fill ratio for filling initial grid randomly", OFFSET(random_fill_ratio), AV_OPT_TYPE_DOUBLE, {.dbl = 1/M_PHI}, 0, 1, FLAGS }, { "ratio", "set fill ratio for filling initial grid randomly", OFFSET(random_fill_ratio), AV_OPT_TYPE_DOUBLE, {.dbl = 1/M_PHI}, 0, 1, FLAGS }, - { "random_seed", "set the seed for filling the initial grid randomly", OFFSET(random_seed), AV_OPT_TYPE_INT, {.i64 = -1}, -1, UINT32_MAX, FLAGS }, - { "seed", "set the seed for filling the initial grid randomly", OFFSET(random_seed), AV_OPT_TYPE_INT, {.i64 = -1}, -1, UINT32_MAX, FLAGS }, + { "random_seed", "set the seed for filling the initial grid randomly", OFFSET(random_seed), AV_OPT_TYPE_INT64, {.i64 = -1}, -1, UINT32_MAX, FLAGS }, + { "seed", "set the seed for filling the initial grid randomly", OFFSET(random_seed), AV_OPT_TYPE_INT64, {.i64 = -1}, -1, UINT32_MAX, FLAGS }, { "scroll", "scroll pattern downward", OFFSET(scroll), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, { "start_full", "start filling the whole video", OFFSET(start_full), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, { "full", "start filling the whole video", OFFSET(start_full), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, @@ -199,7 +199,7 @@ } av_log(ctx, AV_LOG_VERBOSE, - "s:%dx%d r:%d/%d rule:%d stitch:%d scroll:%d full:%d seed:%"PRIu32"\n", + "s:%dx%d r:%d/%d rule:%d stitch:%d scroll:%d full:%d seed:%"PRId64"\n", s->w, s->h, s->frame_rate.num, s->frame_rate.den, s->rule, s->stitch, s->scroll, s->start_full, s->random_seed); diff -Nru ffmpeg-4.2.2/libavfilter/vsrc_gradients.c ffmpeg-4.4/libavfilter/vsrc_gradients.c --- ffmpeg-4.2.2/libavfilter/vsrc_gradients.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vsrc_gradients.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avfilter.h" +#include "filters.h" +#include "formats.h" +#include "video.h" +#include "internal.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/lfg.h" +#include "libavutil/random_seed.h" +#include +#include + +typedef struct GradientsContext { + const AVClass *class; + int w, h; + int type; + AVRational frame_rate; + int64_t pts; + int64_t duration; ///< duration expressed in microseconds + float speed; + + uint8_t color_rgba[8][4]; + int nb_colors; + int x0, y0, x1, y1; + float fx0, fy0, fx1, fy1; + + int64_t seed; + + AVLFG lfg; + int (*draw_slice)(AVFilterContext *ctx, void *arg, int job, int nb_jobs); +} GradientsContext; + +#define OFFSET(x) offsetof(GradientsContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption gradients_options[] = { + {"size", "set frame size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="640x480"}, 0, 0, FLAGS }, + {"s", "set frame size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="640x480"}, 0, 0, FLAGS }, + {"rate", "set frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS }, + {"r", "set frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS }, + {"c0", "set 1st color", OFFSET(color_rgba[0]), AV_OPT_TYPE_COLOR, {.str = "random"}, 0, 0, FLAGS }, + {"c1", "set 2nd color", OFFSET(color_rgba[1]), AV_OPT_TYPE_COLOR, {.str = "random"}, 0, 0, FLAGS }, + {"c2", "set 3rd color", OFFSET(color_rgba[2]), AV_OPT_TYPE_COLOR, {.str = "random"}, 0, 0, FLAGS }, + {"c3", "set 4th color", OFFSET(color_rgba[3]), AV_OPT_TYPE_COLOR, {.str = "random"}, 0, 0, FLAGS }, + {"c4", "set 5th color", OFFSET(color_rgba[4]), AV_OPT_TYPE_COLOR, {.str = "random"}, 0, 0, FLAGS }, + {"c5", "set 6th color", OFFSET(color_rgba[5]), AV_OPT_TYPE_COLOR, {.str = "random"}, 0, 0, FLAGS }, + {"c6", "set 7th color", OFFSET(color_rgba[6]), AV_OPT_TYPE_COLOR, {.str = "random"}, 0, 0, FLAGS }, + {"c7", "set 8th color", OFFSET(color_rgba[7]), AV_OPT_TYPE_COLOR, {.str = "random"}, 0, 0, FLAGS }, + {"x0", "set gradient line source x0", OFFSET(x0), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, FLAGS }, + {"y0", "set gradient line source y0", OFFSET(y0), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, FLAGS }, + {"x1", "set gradient line destination x1", OFFSET(x1), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, FLAGS }, + {"y1", "set gradient line destination y1", OFFSET(y1), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, FLAGS }, + {"nb_colors", "set the number of colors", OFFSET(nb_colors), AV_OPT_TYPE_INT, {.i64=2}, 2, 8, FLAGS }, + {"n", "set the number of colors", OFFSET(nb_colors), AV_OPT_TYPE_INT, {.i64=2}, 2, 8, FLAGS }, + {"seed", "set the seed", OFFSET(seed), AV_OPT_TYPE_INT64, {.i64=-1}, -1, UINT32_MAX, FLAGS }, + {"duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=-1}, -1, INT64_MAX, FLAGS },\ + {"d", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=-1}, -1, INT64_MAX, FLAGS },\ + {"speed", "set gradients rotation speed", OFFSET(speed), AV_OPT_TYPE_FLOAT,{.dbl=0.01}, 0.00001, 1, FLAGS },\ + {NULL}, +}; + +AVFILTER_DEFINE_CLASS(gradients); + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_RGBA, + AV_PIX_FMT_RGBA64, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +static uint32_t lerp_color(uint8_t c0[4], uint8_t c1[4], float x) +{ + const float y = 1.f - x; + + return (lrintf(c0[0] * y + c1[0] * x)) << 0 | + (lrintf(c0[1] * y + c1[1] * x)) << 8 | + (lrintf(c0[2] * y + c1[2] * x)) << 16 | + (lrintf(c0[3] * y + c1[3] * x)) << 24; +} + +static uint64_t lerp_color16(uint8_t c0[4], uint8_t c1[4], float x) +{ + const float y = 1.f - x; + + return (llrintf((c0[0] * y + c1[0] * x) * 256)) << 0 | + (llrintf((c0[1] * y + c1[1] * x) * 256)) << 16 | + (llrintf((c0[2] * y + c1[2] * x) * 256)) << 32 | + (llrintf((c0[3] * y + c1[3] * x) * 256)) << 48; +} + +static uint32_t lerp_colors(uint8_t arr[3][4], int nb_colors, float step) +{ + float scl; + int i; + + if (nb_colors == 1 || step <= 0.0) { + return arr[0][0] | (arr[0][1] << 8) | (arr[0][2] << 16) | (arr[0][3] << 24); + } else if (step >= 1.0) { + i = nb_colors - 1; + return arr[i][0] | (arr[i][1] << 8) | (arr[i][2] << 16) | (arr[i][3] << 24); + } + + scl = step * (nb_colors - 1); + i = floorf(scl); + + return lerp_color(arr[i], arr[i + 1], scl - i); +} + +static uint64_t lerp_colors16(uint8_t arr[3][4], int nb_colors, float step) +{ + float scl; + int i; + + if (nb_colors == 1 || step <= 0.0) { + return ((uint64_t)arr[0][0] << 8) | ((uint64_t)arr[0][1] << 24) | ((uint64_t)arr[0][2] << 40) | ((uint64_t)arr[0][3] << 56); + } else if (step >= 1.0) { + i = nb_colors - 1; + return ((uint64_t)arr[i][0] << 8) | ((uint64_t)arr[i][1] << 24) | ((uint64_t)arr[i][2] << 40) | ((uint64_t)arr[i][3] << 56); + } + + scl = step * (nb_colors - 1); + i = floorf(scl); + + return lerp_color16(arr[i], arr[i + 1], scl - i); +} + +static float project(float origin_x, float origin_y, + float dest_x, float dest_y, + int point_x, int point_y) +{ + // Rise and run of line. + float od_x = dest_x - origin_x; + float od_y = dest_y - origin_y; + + // Distance-squared of line. + float od_s_q = od_x * od_x + od_y * od_y; + + // Rise and run of projection. + float op_x = point_x - origin_x; + float op_y = point_y - origin_y; + float op_x_od = op_x * od_x + op_y * od_y; + + // Normalize and clamp range. + return av_clipf(op_x_od / od_s_q, 0.f, 1.f); +} + +static int draw_gradients_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) +{ + GradientsContext *s = ctx->priv; + AVFrame *frame = arg; + const int width = frame->width; + const int height = frame->height; + const int start = (height * job ) / nb_jobs; + const int end = (height * (job+1)) / nb_jobs; + const int linesize = frame->linesize[0] / 4; + uint32_t *dst = (uint32_t *)frame->data[0] + start * linesize; + + for (int y = start; y < end; y++) { + for (int x = 0; x < width; x++) { + float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y); + dst[x] = lerp_colors(s->color_rgba, s->nb_colors, factor); + } + + dst += linesize; + } + + return 0; +} + +static int draw_gradients_slice16(AVFilterContext *ctx, void *arg, int job, int nb_jobs) +{ + GradientsContext *s = ctx->priv; + AVFrame *frame = arg; + const int width = frame->width; + const int height = frame->height; + const int start = (height * job ) / nb_jobs; + const int end = (height * (job+1)) / nb_jobs; + const int linesize = frame->linesize[0] / 8; + uint64_t *dst = (uint64_t *)frame->data[0] + start * linesize; + + for (int y = start; y < end; y++) { + for (int x = 0; x < width; x++) { + float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y); + dst[x] = lerp_colors16(s->color_rgba, s->nb_colors, factor); + } + + dst += linesize; + } + + return 0; +}static int config_output(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->src; + GradientsContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + + if (av_image_check_size(s->w, s->h, 0, ctx) < 0) + return AVERROR(EINVAL); + + inlink->w = s->w; + inlink->h = s->h; + inlink->time_base = av_inv_q(s->frame_rate); + inlink->sample_aspect_ratio = (AVRational) {1, 1}; + if (s->seed == -1) + s->seed = av_get_random_seed(); + av_lfg_init(&s->lfg, s->seed); + + s->draw_slice = desc->comp[0].depth == 16 ? draw_gradients_slice16 : draw_gradients_slice; + + if (s->x0 < 0 || s->x0 >= s->w) + s->x0 = av_lfg_get(&s->lfg) % s->w; + if (s->y0 < 0 || s->y0 >= s->h) + s->y0 = av_lfg_get(&s->lfg) % s->h; + if (s->x1 < 0 || s->x1 >= s->w) + s->x1 = av_lfg_get(&s->lfg) % s->w; + if (s->y1 < 0 || s->y1 >= s->h) + s->y1 = av_lfg_get(&s->lfg) % s->h; + + return 0; +} + +static int activate(AVFilterContext *ctx) +{ + GradientsContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + if (s->duration >= 0 && + av_rescale_q(s->pts, outlink->time_base, AV_TIME_BASE_Q) >= s->duration) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + return 0; + } + + if (ff_outlink_frame_wanted(outlink)) { + AVFrame *frame = ff_get_video_buffer(outlink, s->w, s->h); + float angle = fmodf(s->pts * s->speed, 2.f * M_PI); + const float w2 = s->w / 2.f; + const float h2 = s->h / 2.f; + + s->fx0 = (s->x0 - w2) * cosf(angle) - (s->y0 - h2) * sinf(angle) + w2; + s->fy0 = (s->x0 - w2) * sinf(angle) + (s->y0 - h2) * cosf(angle) + h2; + + s->fx1 = (s->x1 - w2) * cosf(angle) - (s->y1 - h2) * sinf(angle) + w2; + s->fy1 = (s->x1 - w2) * sinf(angle) + (s->y1 - h2) * cosf(angle) + h2; + + if (!frame) + return AVERROR(ENOMEM); + + frame->key_frame = 1; + frame->interlaced_frame = 0; + frame->pict_type = AV_PICTURE_TYPE_I; + frame->sample_aspect_ratio = (AVRational) {1, 1}; + frame->pts = s->pts++; + + ctx->internal->execute(ctx, s->draw_slice, frame, NULL, + FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); + + return ff_filter_frame(outlink, frame); + } + + return FFERROR_NOT_READY; +} + +static const AVFilterPad gradients_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vsrc_gradients = { + .name = "gradients", + .description = NULL_IF_CONFIG_SMALL("Draw a gradients."), + .priv_size = sizeof(GradientsContext), + .priv_class = &gradients_class, + .query_formats = query_formats, + .inputs = NULL, + .outputs = gradients_outputs, + .activate = activate, + .flags = AVFILTER_FLAG_SLICE_THREADS, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vsrc_life.c ffmpeg-4.4/libavfilter/vsrc_life.c --- ffmpeg-4.2.2/libavfilter/vsrc_life.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vsrc_life.c 2020-07-11 10:39:30.000000000 +0000 @@ -63,7 +63,7 @@ uint64_t pts; AVRational frame_rate; double random_fill_ratio; - uint32_t random_seed; + int64_t random_seed; int stitch; int mold; uint8_t life_color[4]; @@ -84,16 +84,16 @@ { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, FLAGS }, { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS }, { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS }, - { "rule", "set rule", OFFSET(rule_str), AV_OPT_TYPE_STRING, {.str = "B3/S23"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "rule", "set rule", OFFSET(rule_str), AV_OPT_TYPE_STRING, {.str = "B3/S23"}, 0, 0, FLAGS }, { "random_fill_ratio", "set fill ratio for filling initial grid randomly", OFFSET(random_fill_ratio), AV_OPT_TYPE_DOUBLE, {.dbl=1/M_PHI}, 0, 1, FLAGS }, { "ratio", "set fill ratio for filling initial grid randomly", OFFSET(random_fill_ratio), AV_OPT_TYPE_DOUBLE, {.dbl=1/M_PHI}, 0, 1, FLAGS }, - { "random_seed", "set the seed for filling the initial grid randomly", OFFSET(random_seed), AV_OPT_TYPE_INT, {.i64=-1}, -1, UINT32_MAX, FLAGS }, - { "seed", "set the seed for filling the initial grid randomly", OFFSET(random_seed), AV_OPT_TYPE_INT, {.i64=-1}, -1, UINT32_MAX, FLAGS }, + { "random_seed", "set the seed for filling the initial grid randomly", OFFSET(random_seed), AV_OPT_TYPE_INT64, {.i64=-1}, -1, UINT32_MAX, FLAGS }, + { "seed", "set the seed for filling the initial grid randomly", OFFSET(random_seed), AV_OPT_TYPE_INT64, {.i64=-1}, -1, UINT32_MAX, FLAGS }, { "stitch", "stitch boundaries", OFFSET(stitch), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, { "mold", "set mold speed for dead cells", OFFSET(mold), AV_OPT_TYPE_INT, {.i64=0}, 0, 0xFF, FLAGS }, - { "life_color", "set life color", OFFSET( life_color), AV_OPT_TYPE_COLOR, {.str="white"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "death_color", "set death color", OFFSET(death_color), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "mold_color", "set mold color", OFFSET( mold_color), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "life_color", "set life color", OFFSET( life_color), AV_OPT_TYPE_COLOR, {.str="white"}, 0, 0, FLAGS }, + { "death_color", "set death color", OFFSET(death_color), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS }, + { "mold_color", "set mold color", OFFSET( mold_color), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS }, { NULL } }; @@ -260,7 +260,7 @@ } av_log(ctx, AV_LOG_VERBOSE, - "s:%dx%d r:%d/%d rule:%s stay_rule:%d born_rule:%d stitch:%d seed:%"PRIu32"\n", + "s:%dx%d r:%d/%d rule:%s stay_rule:%d born_rule:%d stitch:%d seed:%"PRId64"\n", life->w, life->h, life->frame_rate.num, life->frame_rate.den, life->rule_str, life->stay_rule, life->born_rule, life->stitch, life->random_seed); diff -Nru ffmpeg-4.2.2/libavfilter/vsrc_mandelbrot.c ffmpeg-4.4/libavfilter/vsrc_mandelbrot.c --- ffmpeg-4.2.2/libavfilter/vsrc_mandelbrot.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vsrc_mandelbrot.c 2020-07-11 10:39:30.000000000 +0000 @@ -87,10 +87,10 @@ #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption mandelbrot_options[] = { - {"size", "set frame size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="640x480"}, CHAR_MIN, CHAR_MAX, FLAGS }, - {"s", "set frame size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="640x480"}, CHAR_MIN, CHAR_MAX, FLAGS }, - {"rate", "set frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, CHAR_MIN, CHAR_MAX, FLAGS }, - {"r", "set frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, CHAR_MIN, CHAR_MAX, FLAGS }, + {"size", "set frame size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="640x480"}, 0, 0, FLAGS }, + {"s", "set frame size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="640x480"}, 0, 0, FLAGS }, + {"rate", "set frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS }, + {"r", "set frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS }, {"maxiter", "set max iterations number", OFFSET(maxiter), AV_OPT_TYPE_INT, {.i64=7189}, 1, INT_MAX, FLAGS }, {"start_x", "set the initial x position", OFFSET(start_x), AV_OPT_TYPE_DOUBLE, {.dbl=-0.743643887037158704752191506114774}, -100, 100, FLAGS }, {"start_y", "set the initial y position", OFFSET(start_y), AV_OPT_TYPE_DOUBLE, {.dbl=-0.131825904205311970493132056385139}, -100, 100, FLAGS }, diff -Nru ffmpeg-4.2.2/libavfilter/vsrc_mptestsrc.c ffmpeg-4.4/libavfilter/vsrc_mptestsrc.c --- ffmpeg-4.2.2/libavfilter/vsrc_mptestsrc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vsrc_mptestsrc.c 2020-07-11 10:39:30.000000000 +0000 @@ -54,6 +54,7 @@ const AVClass *class; AVRational frame_rate; int64_t pts, max_pts, duration; + int64_t max_frames; int hsub, vsub; int test; ///< test_type } MPTestContext; @@ -79,6 +80,10 @@ { "ring1", "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_RING1}, INT_MIN, INT_MAX, FLAGS, "test" }, { "ring2", "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_RING2}, INT_MIN, INT_MAX, FLAGS, "test" }, { "all", "", 0, AV_OPT_TYPE_CONST, {.i64=TEST_ALL}, INT_MIN, INT_MAX, FLAGS, "test" }, + { "max_frames", "Set the maximum number of frames generated for each test", OFFSET(max_frames), + AV_OPT_TYPE_INT64, {.i64 = 30}, 1, INT64_MAX, FLAGS }, + { "m", "Set the maximum number of frames generated for each test", OFFSET(max_frames), + AV_OPT_TYPE_INT64, {.i64 = 30}, 1, INT64_MAX, FLAGS }, { NULL } }; @@ -303,7 +308,8 @@ AVFrame *picref; int w = WIDTH, h = HEIGHT, cw = AV_CEIL_RSHIFT(w, test->hsub), ch = AV_CEIL_RSHIFT(h, test->vsub); - unsigned int frame = outlink->frame_count_in; + uint64_t frame = outlink->frame_count_in / test->max_frames; + uint64_t mod = outlink->frame_count_in % test->max_frames; enum test_type tt = test->test; int i; @@ -322,20 +328,20 @@ memset(picref->data[2] + i*picref->linesize[2], 128, cw); } - if (tt == TEST_ALL && frame%30) /* draw a black frame at the beginning of each test */ - tt = (frame/30)%(TEST_NB-1); + if (tt == TEST_ALL && mod) /* draw a black frame at the beginning of each test */ + tt = frame%(TEST_NB-1); switch (tt) { - case TEST_DC_LUMA: dc_test(picref->data[0], picref->linesize[0], 256, 256, frame%30); break; - case TEST_DC_CHROMA: dc_test(picref->data[1], picref->linesize[1], 256, 256, frame%30); break; - case TEST_FREQ_LUMA: freq_test(picref->data[0], picref->linesize[0], frame%30); break; - case TEST_FREQ_CHROMA: freq_test(picref->data[1], picref->linesize[1], frame%30); break; - case TEST_AMP_LUMA: amp_test(picref->data[0], picref->linesize[0], frame%30); break; - case TEST_AMP_CHROMA: amp_test(picref->data[1], picref->linesize[1], frame%30); break; - case TEST_CBP: cbp_test(picref->data , picref->linesize , frame%30); break; - case TEST_MV: mv_test(picref->data[0], picref->linesize[0], frame%30); break; - case TEST_RING1: ring1_test(picref->data[0], picref->linesize[0], frame%30); break; - case TEST_RING2: ring2_test(picref->data[0], picref->linesize[0], frame%30); break; + case TEST_DC_LUMA: dc_test(picref->data[0], picref->linesize[0], 256, 256, mod); break; + case TEST_DC_CHROMA: dc_test(picref->data[1], picref->linesize[1], 256, 256, mod); break; + case TEST_FREQ_LUMA: freq_test(picref->data[0], picref->linesize[0], mod); break; + case TEST_FREQ_CHROMA: freq_test(picref->data[1], picref->linesize[1], mod); break; + case TEST_AMP_LUMA: amp_test(picref->data[0], picref->linesize[0], mod); break; + case TEST_AMP_CHROMA: amp_test(picref->data[1], picref->linesize[1], mod); break; + case TEST_CBP: cbp_test(picref->data , picref->linesize , mod); break; + case TEST_MV: mv_test(picref->data[0], picref->linesize[0], mod); break; + case TEST_RING1: ring1_test(picref->data[0], picref->linesize[0], mod); break; + case TEST_RING2: ring2_test(picref->data[0], picref->linesize[0], mod); break; } return ff_filter_frame(outlink, picref); diff -Nru ffmpeg-4.2.2/libavfilter/vsrc_sierpinski.c ffmpeg-4.4/libavfilter/vsrc_sierpinski.c --- ffmpeg-4.2.2/libavfilter/vsrc_sierpinski.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vsrc_sierpinski.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2019 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Sierpinski carpet fractal renderer + */ + +#include "avfilter.h" +#include "formats.h" +#include "video.h" +#include "internal.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/lfg.h" +#include "libavutil/random_seed.h" +#include +#include + +typedef struct SierpinskiContext { + const AVClass *class; + int w, h; + int type; + AVRational frame_rate; + uint64_t pts; + + int64_t seed; + int jump; + + int pos_x, pos_y; + int dest_x, dest_y; + + AVLFG lfg; + int (*draw_slice)(AVFilterContext *ctx, void *arg, int job, int nb_jobs); +} SierpinskiContext; + +#define OFFSET(x) offsetof(SierpinskiContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption sierpinski_options[] = { + {"size", "set frame size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="640x480"}, 0, 0, FLAGS }, + {"s", "set frame size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="640x480"}, 0, 0, FLAGS }, + {"rate", "set frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS }, + {"r", "set frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS }, + {"seed", "set the seed", OFFSET(seed), AV_OPT_TYPE_INT64, {.i64=-1}, -1, UINT32_MAX, FLAGS }, + {"jump", "set the jump", OFFSET(jump), AV_OPT_TYPE_INT, {.i64=100}, 1, 10000, FLAGS }, + {"type","set fractal type",OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "type" }, + {"carpet", "sierpinski carpet", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "type" }, + {"triangle", "sierpinski triangle", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "type" }, + {NULL}, +}; + +AVFILTER_DEFINE_CLASS(sierpinski); + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_0BGR32, + AV_PIX_FMT_NONE + }; + + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +static int fill_sierpinski(SierpinskiContext *s, int x, int y) +{ + int pos_x = x + s->pos_x; + int pos_y = y + s->pos_y; + + while (pos_x != 0 && pos_y != 0) { + if (FFABS(pos_x % 3) == 1 && FFABS(pos_y % 3) == 1) + return 1; + + pos_x /= 3; + pos_y /= 3; + } + + return 0; +} + +static int draw_triangle_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) +{ + SierpinskiContext *s = ctx->priv; + AVFrame *frame = arg; + const int width = frame->width; + const int height = frame->height; + const int start = (height * job ) / nb_jobs; + const int end = (height * (job+1)) / nb_jobs; + uint8_t *dst = frame->data[0] + start * frame->linesize[0]; + + for (int y = start; y < end; y++) { + for (int x = 0; x < width; x++) { + if ((s->pos_x + x) & (s->pos_y + y)) { + AV_WL32(&dst[x*4], 0x00000000); + } else { + AV_WL32(&dst[x*4], 0xFFFFFFFF); + } + } + + dst += frame->linesize[0]; + } + + return 0; +} + +static int draw_carpet_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) +{ + SierpinskiContext *s = ctx->priv; + AVFrame *frame = arg; + const int width = frame->width; + const int height = frame->height; + const int start = (height * job ) / nb_jobs; + const int end = (height * (job+1)) / nb_jobs; + uint8_t *dst = frame->data[0] + start * frame->linesize[0]; + + for (int y = start; y < end; y++) { + for (int x = 0; x < width; x++) { + if (fill_sierpinski(s, x, y)) { + AV_WL32(&dst[x*4], 0x00000000); + } else { + AV_WL32(&dst[x*4], 0xFFFFFFFF); + } + } + + dst += frame->linesize[0]; + } + + return 0; +} + +static int config_output(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->src; + SierpinskiContext *s = ctx->priv; + + if (av_image_check_size(s->w, s->h, 0, ctx) < 0) + return AVERROR(EINVAL); + + inlink->w = s->w; + inlink->h = s->h; + inlink->time_base = av_inv_q(s->frame_rate); + inlink->sample_aspect_ratio = (AVRational) {1, 1}; + if (s->seed == -1) + s->seed = av_get_random_seed(); + av_lfg_init(&s->lfg, s->seed); + + s->draw_slice = s->type ? draw_triangle_slice : draw_carpet_slice; + + return 0; +} + +static void draw_sierpinski(AVFilterContext *ctx, AVFrame *frame) +{ + SierpinskiContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + if (s->pos_x == s->dest_x && s->pos_y == s->dest_y) { + unsigned int rnd = av_lfg_get(&s->lfg); + int mod = 2 * s->jump + 1; + + s->dest_x += (int)((rnd & 0xffff) % mod) - s->jump; + s->dest_y += (int)((rnd >> 16) % mod) - s->jump; + } else { + if (s->pos_x < s->dest_x) + s->pos_x++; + else if (s->pos_x > s->dest_x) + s->pos_x--; + + if (s->pos_y < s->dest_y) + s->pos_y++; + else if (s->pos_y > s->dest_y) + s->pos_y--; + } + + ctx->internal->execute(ctx, s->draw_slice, frame, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); +} + +static int sierpinski_request_frame(AVFilterLink *link) +{ + SierpinskiContext *s = link->src->priv; + AVFrame *frame = ff_get_video_buffer(link, s->w, s->h); + + if (!frame) + return AVERROR(ENOMEM); + + frame->sample_aspect_ratio = (AVRational) {1, 1}; + frame->pts = s->pts++; + + draw_sierpinski(link->src, frame); + + return ff_filter_frame(link, frame); +} + +static const AVFilterPad sierpinski_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .request_frame = sierpinski_request_frame, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vsrc_sierpinski = { + .name = "sierpinski", + .description = NULL_IF_CONFIG_SMALL("Render a Sierpinski fractal."), + .priv_size = sizeof(SierpinskiContext), + .priv_class = &sierpinski_class, + .query_formats = query_formats, + .inputs = NULL, + .outputs = sierpinski_outputs, + .flags = AVFILTER_FLAG_SLICE_THREADS, +}; diff -Nru ffmpeg-4.2.2/libavfilter/vsrc_testsrc.c ffmpeg-4.4/libavfilter/vsrc_testsrc.c --- ffmpeg-4.2.2/libavfilter/vsrc_testsrc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vsrc_testsrc.c 2021-04-08 21:28:40.000000000 +0000 @@ -45,6 +45,7 @@ #include "libavutil/xga_font_data.h" #include "avfilter.h" #include "drawutils.h" +#include "filters.h" #include "formats.h" #include "internal.h" #include "video.h" @@ -76,6 +77,8 @@ /* only used by rgbtest */ uint8_t rgba_map[4]; + int complement; + int depth; /* only used by haldclut */ int level; @@ -83,6 +86,7 @@ #define OFFSET(x) offsetof(TestSourceContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define FLAGSR AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM #define SIZE_OPTIONS \ { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "320x240"}, 0, 0, FLAGS },\ @@ -97,6 +101,9 @@ #define COMMON_OPTIONS SIZE_OPTIONS COMMON_OPTIONS_NOSIZE +#define NOSIZE_OPTIONS_OFFSET 2 +/* Filters using COMMON_OPTIONS_NOSIZE also use the following options + * via &options[NOSIZE_OPTIONS_OFFSET]. So don't break it. */ static const AVOption options[] = { COMMON_OPTIONS { NULL } @@ -137,14 +144,19 @@ return 0; } -static int request_frame(AVFilterLink *outlink) +static int activate(AVFilterContext *ctx) { - TestSourceContext *test = outlink->src->priv; + AVFilterLink *outlink = ctx->outputs[0]; + TestSourceContext *test = ctx->priv; AVFrame *frame; + if (!ff_outlink_frame_wanted(outlink)) + return FFERROR_NOT_READY; if (test->duration >= 0 && - av_rescale_q(test->pts, test->time_base, AV_TIME_BASE_Q) >= test->duration) - return AVERROR_EOF; + av_rescale_q(test->pts, test->time_base, AV_TIME_BASE_Q) >= test->duration) { + ff_outlink_set_status(outlink, AVERROR_EOF, test->pts); + return 0; + } if (test->draw_once) { if (test->draw_once_reset) { @@ -181,8 +193,8 @@ #if CONFIG_COLOR_FILTER static const AVOption color_options[] = { - { "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, FLAGS }, - { "c", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, FLAGS }, + { "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGSR }, + { "c", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGSR }, COMMON_OPTIONS { NULL } }; @@ -236,27 +248,19 @@ TestSourceContext *test = ctx->priv; int ret; - if (!strcmp(cmd, "color") || !strcmp(cmd, "c")) { - uint8_t color_rgba[4]; - - ret = av_parse_color(color_rgba, args, -1, ctx); - if (ret < 0) - return ret; - - memcpy(test->color_rgba, color_rgba, sizeof(color_rgba)); - ff_draw_color(&test->draw, &test->color, test->color_rgba); - test->draw_once_reset = 1; - return 0; - } + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; - return AVERROR(ENOSYS); + ff_draw_color(&test->draw, &test->color, test->color_rgba); + test->draw_once_reset = 1; + return 0; } static const AVFilterPad color_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, .config_props = color_config_props, }, { NULL } @@ -269,6 +273,7 @@ .priv_size = sizeof(TestSourceContext), .init = color_init, .uninit = uninit, + .activate = activate, .query_formats = color_query_formats, .inputs = NULL, .outputs = color_outputs, @@ -280,7 +285,7 @@ #if CONFIG_HALDCLUTSRC_FILTER static const AVOption haldclutsrc_options[] = { - { "level", "set level", OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 6}, 2, 8, FLAGS }, + { "level", "set level", OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 6}, 2, 16, FLAGS }, COMMON_OPTIONS_NOSIZE { NULL } }; @@ -390,7 +395,6 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, .config_props = haldclutsrc_config_props, }, { NULL } @@ -404,6 +408,7 @@ .init = haldclutsrc_init, .uninit = uninit, .query_formats = haldclutsrc_query_formats, + .activate = activate, .inputs = NULL, .outputs = haldclutsrc_outputs, }; @@ -428,7 +433,6 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, .config_props = config_props, }, { NULL }, @@ -439,6 +443,7 @@ .description = NULL_IF_CONFIG_SMALL("Null video source, return unprocessed video frames."), .init = nullsrc_init, .uninit = uninit, + .activate = activate, .priv_size = sizeof(TestSourceContext), .priv_class = &nullsrc_class, .inputs = NULL, @@ -664,7 +669,6 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, .config_props = config_props, }, { NULL } @@ -678,6 +682,7 @@ .init = test_init, .uninit = uninit, .query_formats = test_query_formats, + .activate = activate, .inputs = NULL, .outputs = avfilter_vsrc_testsrc_outputs, }; @@ -937,7 +942,6 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, .config_props = test2_config_props, }, { NULL } @@ -951,6 +955,7 @@ .init = test2_init, .uninit = uninit, .query_formats = test2_query_formats, + .activate = activate, .inputs = NULL, .outputs = avfilter_vsrc_testsrc2_outputs, }; @@ -959,7 +964,13 @@ #if CONFIG_RGBTESTSRC_FILTER -#define rgbtestsrc_options options +static const AVOption rgbtestsrc_options[] = { + COMMON_OPTIONS + { "complement", "set complement colors", OFFSET(complement), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "co", "set complement colors", OFFSET(complement), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { NULL } +}; + AVFILTER_DEFINE_CLASS(rgbtestsrc); #define R 0 @@ -967,12 +978,15 @@ #define B 2 #define A 3 -static void rgbtest_put_pixel(uint8_t *dst, int dst_linesize, - int x, int y, int r, int g, int b, enum AVPixelFormat fmt, +static void rgbtest_put_pixel(uint8_t *dstp[4], int dst_linesizep[4], + int x, int y, unsigned r, unsigned g, unsigned b, enum AVPixelFormat fmt, uint8_t rgba_map[4]) { - int32_t v; + uint8_t *dst = dstp[0]; + int dst_linesize = dst_linesizep[0]; + uint32_t v; uint8_t *p; + uint16_t *p16; switch (fmt) { case AV_PIX_FMT_BGR444: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4); break; @@ -991,13 +1005,56 @@ case AV_PIX_FMT_BGRA: case AV_PIX_FMT_ARGB: case AV_PIX_FMT_ABGR: - v = (r << (rgba_map[R]*8)) + (g << (rgba_map[G]*8)) + (b << (rgba_map[B]*8)) + (255 << (rgba_map[A]*8)); + v = (r << (rgba_map[R]*8)) + (g << (rgba_map[G]*8)) + (b << (rgba_map[B]*8)) + (255U << (rgba_map[A]*8)); p = dst + 4*x + y*dst_linesize; AV_WL32(p, v); break; + case AV_PIX_FMT_GBRP: + p = dstp[0] + x + y * dst_linesizep[0]; + p[0] = g; + p = dstp[1] + x + y * dst_linesizep[1]; + p[0] = b; + p = dstp[2] + x + y * dst_linesizep[2]; + p[0] = r; + break; + case AV_PIX_FMT_GBRP9: + case AV_PIX_FMT_GBRP10: + case AV_PIX_FMT_GBRP12: + case AV_PIX_FMT_GBRP14: + case AV_PIX_FMT_GBRP16: + p16 = (uint16_t *)(dstp[0] + x*2 + y * dst_linesizep[0]); + p16[0] = g; + p16 = (uint16_t *)(dstp[1] + x*2 + y * dst_linesizep[1]); + p16[0] = b; + p16 = (uint16_t *)(dstp[2] + x*2 + y * dst_linesizep[2]); + p16[0] = r; + break; } } +static void rgbtest_fill_picture_complement(AVFilterContext *ctx, AVFrame *frame) +{ + TestSourceContext *test = ctx->priv; + int x, y, w = frame->width, h = frame->height; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + int c = (1 << FFMAX(test->depth, 8))*x/w; + int r = 0, g = 0, b = 0; + + if (6*y < h ) r = c; + else if (6*y < 2*h) g = c, b = c; + else if (6*y < 3*h) g = c; + else if (6*y < 4*h) r = c, b = c; + else if (6*y < 5*h) b = c; + else r = c, g = c; + + rgbtest_put_pixel(frame->data, frame->linesize, x, y, r, g, b, + ctx->outputs[0]->format, test->rgba_map); + } + } +} + static void rgbtest_fill_picture(AVFilterContext *ctx, AVFrame *frame) { TestSourceContext *test = ctx->priv; @@ -1005,14 +1062,14 @@ for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { - int c = 256*x/w; + int c = (1 << FFMAX(test->depth, 8))*x/w; int r = 0, g = 0, b = 0; if (3*y < h ) r = c; else if (3*y < 2*h) g = c; else b = c; - rgbtest_put_pixel(frame->data[0], frame->linesize[0], x, y, r, g, b, + rgbtest_put_pixel(frame->data, frame->linesize, x, y, r, g, b, ctx->outputs[0]->format, test->rgba_map); } } @@ -1023,7 +1080,7 @@ TestSourceContext *test = ctx->priv; test->draw_once = 1; - test->fill_picture_fn = rgbtest_fill_picture; + test->fill_picture_fn = test->complement ? rgbtest_fill_picture_complement : rgbtest_fill_picture; return init(ctx); } @@ -1035,6 +1092,8 @@ AV_PIX_FMT_RGB444, AV_PIX_FMT_BGR444, AV_PIX_FMT_RGB565, AV_PIX_FMT_BGR565, AV_PIX_FMT_RGB555, AV_PIX_FMT_BGR555, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_NONE }; @@ -1047,7 +1106,9 @@ static int rgbtest_config_props(AVFilterLink *outlink) { TestSourceContext *test = outlink->src->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); + test->depth = desc->comp[0].depth; ff_fill_rgba_map(test->rgba_map, outlink->format); return config_props(outlink); } @@ -1056,7 +1117,6 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, .config_props = rgbtest_config_props, }, { NULL } @@ -1070,6 +1130,7 @@ .init = rgbtest_init, .uninit = uninit, .query_formats = rgbtest_query_formats, + .activate = activate, .inputs = NULL, .outputs = avfilter_vsrc_rgbtestsrc_outputs, }; @@ -1232,7 +1293,6 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, .config_props = yuvtest_config_props, }, { NULL } @@ -1246,6 +1306,7 @@ .init = yuvtest_init, .uninit = uninit, .query_formats = yuvtest_query_formats, + .activate = activate, .inputs = NULL, .outputs = avfilter_vsrc_yuvtestsrc_outputs, }; @@ -1375,7 +1436,6 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, .config_props = config_props, }, { NULL } @@ -1423,6 +1483,7 @@ .init = pal75bars_init, .uninit = uninit, .query_formats = smptebars_query_formats, + .activate = activate, .inputs = NULL, .outputs = smptebars_outputs, }; @@ -1469,6 +1530,7 @@ .init = pal100bars_init, .uninit = uninit, .query_formats = smptebars_query_formats, + .activate = activate, .inputs = NULL, .outputs = smptebars_outputs, }; @@ -1536,6 +1598,7 @@ .init = smptebars_init, .uninit = uninit, .query_formats = smptebars_query_formats, + .activate = activate, .inputs = NULL, .outputs = smptebars_outputs, }; @@ -1641,6 +1704,7 @@ .init = smptehdbars_init, .uninit = uninit, .query_formats = smptebars_query_formats, + .activate = activate, .inputs = NULL, .outputs = smptebars_outputs, }; @@ -1650,11 +1714,7 @@ #if CONFIG_ALLYUV_FILTER -static const AVOption allyuv_options[] = { - COMMON_OPTIONS_NOSIZE - { NULL } -}; - +#define allyuv_options &options[NOSIZE_OPTIONS_OFFSET] AVFILTER_DEFINE_CLASS(allyuv); static void allyuv_fill_picture(AVFilterContext *ctx, AVFrame *frame) @@ -1709,7 +1769,6 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, .config_props = config_props, }, { NULL } @@ -1723,6 +1782,7 @@ .init = allyuv_init, .uninit = uninit, .query_formats = allyuv_query_formats, + .activate = activate, .inputs = NULL, .outputs = avfilter_vsrc_allyuv_outputs, }; @@ -1731,11 +1791,7 @@ #if CONFIG_ALLRGB_FILTER -static const AVOption allrgb_options[] = { - COMMON_OPTIONS_NOSIZE - { NULL } -}; - +#define allrgb_options &options[NOSIZE_OPTIONS_OFFSET] AVFILTER_DEFINE_CLASS(allrgb); static void allrgb_fill_picture(AVFilterContext *ctx, AVFrame *frame) @@ -1790,7 +1846,6 @@ { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, .config_props = allrgb_config_props, }, { NULL } @@ -1804,6 +1859,7 @@ .init = allrgb_init, .uninit = uninit, .query_formats = allrgb_query_formats, + .activate = activate, .inputs = NULL, .outputs = avfilter_vsrc_allrgb_outputs, }; diff -Nru ffmpeg-4.2.2/libavfilter/vulkan.c ffmpeg-4.4/libavfilter/vulkan.c --- ffmpeg-4.2.2/libavfilter/vulkan.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vulkan.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,1440 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "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); +} + +int ff_vk_filter_query_formats(AVFilterContext *avctx) +{ + static const enum AVPixelFormat pixel_formats[] = { + AV_PIX_FMT_VULKAN, AV_PIX_FMT_NONE, + }; + AVFilterFormats *pix_fmts = ff_make_format_list(pixel_formats); + if (!pix_fmts) + return AVERROR(ENOMEM); + + return ff_set_common_formats(avctx, pix_fmts); +} + +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); +} diff -Nru ffmpeg-4.2.2/libavfilter/vulkan.h ffmpeg-4.4/libavfilter/vulkan.h --- ffmpeg-4.2.2/libavfilter/vulkan.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/vulkan.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,376 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_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_query_formats (AVFilterContext *avctx); +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); + +#endif /* AVFILTER_VULKAN_H */ diff -Nru ffmpeg-4.2.2/libavfilter/window_func.h ffmpeg-4.4/libavfilter/window_func.h --- ffmpeg-4.2.2/libavfilter/window_func.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/window_func.h 2020-07-11 10:39:30.000000000 +0000 @@ -133,7 +133,7 @@ for (c = 1 - 1 / (b*b), n = (N-1) / 2; n >= 0; --n) { for (sum = !n, b = t = j = 1; j <= n && sum != t; b *= (n-j) * (1./j), ++j) t = sum, sum += (b *= c * (N - n - j) * (1./j)); - sum /= (N - 1 - n), sum /= (norm = norm ? norm : sum); + sum /= (N - 1 - n), norm = norm ? norm : sum, sum /= norm; lut[n] = sum; lut[N - 1 - n] = sum; } diff -Nru ffmpeg-4.2.2/libavfilter/x86/Makefile ffmpeg-4.4/libavfilter/x86/Makefile --- ffmpeg-4.2.2/libavfilter/x86/Makefile 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/Makefile 2020-07-11 10:39:30.000000000 +0000 @@ -2,10 +2,12 @@ OBJS-$(CONFIG_AFIR_FILTER) += x86/af_afir_init.o OBJS-$(CONFIG_ANLMDN_FILTER) += x86/af_anlmdn_init.o +OBJS-$(CONFIG_ATADENOISE_FILTER) += x86/vf_atadenoise_init.o OBJS-$(CONFIG_BLEND_FILTER) += x86/vf_blend_init.o OBJS-$(CONFIG_BWDIF_FILTER) += x86/vf_bwdif_init.o OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp_init.o -OBJS-$(CONFIG_EQ_FILTER) += x86/vf_eq.o +OBJS-$(CONFIG_CONVOLUTION_FILTER) += x86/vf_convolution_init.o +OBJS-$(CONFIG_EQ_FILTER) += x86/vf_eq_init.o OBJS-$(CONFIG_FSPP_FILTER) += x86/vf_fspp_init.o OBJS-$(CONFIG_GBLUR_FILTER) += x86/vf_gblur_init.o OBJS-$(CONFIG_GRADFUN_FILTER) += x86/vf_gradfun_init.o @@ -15,6 +17,7 @@ OBJS-$(CONFIG_IDET_FILTER) += x86/vf_idet_init.o OBJS-$(CONFIG_INTERLACE_FILTER) += x86/vf_tinterlace_init.o OBJS-$(CONFIG_LIMITER_FILTER) += x86/vf_limiter_init.o +OBJS-$(CONFIG_MASKEDCLAMP_FILTER) += x86/vf_maskedclamp_init.o OBJS-$(CONFIG_MASKEDMERGE_FILTER) += x86/vf_maskedmerge_init.o OBJS-$(CONFIG_NOISE_FILTER) += x86/vf_noise.o OBJS-$(CONFIG_OVERLAY_FILTER) += x86/vf_overlay_init.o @@ -29,7 +32,9 @@ OBJS-$(CONFIG_TBLEND_FILTER) += x86/vf_blend_init.o OBJS-$(CONFIG_THRESHOLD_FILTER) += x86/vf_threshold_init.o OBJS-$(CONFIG_TINTERLACE_FILTER) += x86/vf_tinterlace_init.o +OBJS-$(CONFIG_TRANSPOSE_FILTER) += x86/vf_transpose_init.o OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume_init.o +OBJS-$(CONFIG_V360_FILTER) += x86/vf_v360_init.o OBJS-$(CONFIG_W3FDIF_FILTER) += x86/vf_w3fdif_init.o OBJS-$(CONFIG_YADIF_FILTER) += x86/vf_yadif_init.o @@ -37,9 +42,12 @@ X86ASM-OBJS-$(CONFIG_AFIR_FILTER) += x86/af_afir.o X86ASM-OBJS-$(CONFIG_ANLMDN_FILTER) += x86/af_anlmdn.o +X86ASM-OBJS-$(CONFIG_ATADENOISE_FILTER) += x86/vf_atadenoise.o X86ASM-OBJS-$(CONFIG_BLEND_FILTER) += x86/vf_blend.o X86ASM-OBJS-$(CONFIG_BWDIF_FILTER) += x86/vf_bwdif.o X86ASM-OBJS-$(CONFIG_COLORSPACE_FILTER) += x86/colorspacedsp.o +X86ASM-OBJS-$(CONFIG_CONVOLUTION_FILTER) += x86/vf_convolution.o +X86ASM-OBJS-$(CONFIG_EQ_FILTER) += x86/vf_eq.o X86ASM-OBJS-$(CONFIG_FRAMERATE_FILTER) += x86/vf_framerate.o X86ASM-OBJS-$(CONFIG_FSPP_FILTER) += x86/vf_fspp.o X86ASM-OBJS-$(CONFIG_GBLUR_FILTER) += x86/vf_gblur.o @@ -49,6 +57,7 @@ X86ASM-OBJS-$(CONFIG_IDET_FILTER) += x86/vf_idet.o X86ASM-OBJS-$(CONFIG_INTERLACE_FILTER) += x86/vf_interlace.o X86ASM-OBJS-$(CONFIG_LIMITER_FILTER) += x86/vf_limiter.o +X86ASM-OBJS-$(CONFIG_MASKEDCLAMP_FILTER) += x86/vf_maskedclamp.o X86ASM-OBJS-$(CONFIG_MASKEDMERGE_FILTER) += x86/vf_maskedmerge.o X86ASM-OBJS-$(CONFIG_OVERLAY_FILTER) += x86/vf_overlay.o X86ASM-OBJS-$(CONFIG_PP7_FILTER) += x86/vf_pp7.o @@ -63,6 +72,8 @@ X86ASM-OBJS-$(CONFIG_TBLEND_FILTER) += x86/vf_blend.o X86ASM-OBJS-$(CONFIG_THRESHOLD_FILTER) += x86/vf_threshold.o X86ASM-OBJS-$(CONFIG_TINTERLACE_FILTER) += x86/vf_interlace.o +X86ASM-OBJS-$(CONFIG_TRANSPOSE_FILTER) += x86/vf_transpose.o X86ASM-OBJS-$(CONFIG_VOLUME_FILTER) += x86/af_volume.o +X86ASM-OBJS-$(CONFIG_V360_FILTER) += x86/vf_v360.o X86ASM-OBJS-$(CONFIG_W3FDIF_FILTER) += x86/vf_w3fdif.o X86ASM-OBJS-$(CONFIG_YADIF_FILTER) += x86/vf_yadif.o x86/yadif-16.o x86/yadif-10.o diff -Nru ffmpeg-4.2.2/libavfilter/x86/scene_sad_init.c ffmpeg-4.4/libavfilter/x86/scene_sad_init.c --- ffmpeg-4.2.2/libavfilter/x86/scene_sad_init.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/scene_sad_init.c 2020-07-11 10:39:30.000000000 +0000 @@ -37,9 +37,9 @@ } #if HAVE_X86ASM -SCENE_SAD_FUNC(scene_sad_sse2, ff_scene_sad_sse2, 16); +SCENE_SAD_FUNC(scene_sad_sse2, ff_scene_sad_sse2, 16) #if HAVE_AVX2_EXTERNAL -SCENE_SAD_FUNC(scene_sad_avx2, ff_scene_sad_avx2, 32); +SCENE_SAD_FUNC(scene_sad_avx2, ff_scene_sad_avx2, 32) #endif #endif diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_atadenoise.asm ffmpeg-4.4/libavfilter/x86/vf_atadenoise.asm --- ffmpeg-4.2.2/libavfilter/x86/vf_atadenoise.asm 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_atadenoise.asm 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,279 @@ +;***************************************************************************** +;* x86-optimized functions for atadenoise filter +;* +;* Copyright (C) 2019 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 +;****************************************************************************** + +%if ARCH_X86_64 + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA +pw_one: times 8 dw 1 +pw_ones: times 8 dw 65535 + +SECTION .text + +;------------------------------------------------------------------------------ +; void ff_filter_row(const uint8_t *src, uint8_t *dst, +; const uint8_t **srcf, +; int w, int mid, int size, +; int thra, int thrb) +;------------------------------------------------------------------------------ + +INIT_XMM sse4 +cglobal atadenoise_filter_row8, 8,10,13, src, dst, srcf, w, mid, size, i, j, srcfx, x + movsxdifnidn wq, wd + movsxdifnidn midq, midd + movsxdifnidn sizeq, sized + add srcq, wq + add dstq, wq + mov xq, wq + dec sizeq + neg xq + movd m4, r6m + SPLATW m4, m4 + movd m5, r7m + SPLATW m5, m5 + pxor m2, m2 + mova m10, [pw_ones] + + .loop: + mov iq, midq + mov jq, midq + pxor m3, m3 + pxor m11, m11 + movu m0, [srcq + xq] + punpcklbw m0, m2 + mova m7, m0 + mova m8, [pw_one] + mova m12, [pw_ones] + + .loop0: + inc iq + dec jq + + mov srcfxq, [srcfq + jq * 8] + add srcfxq, wq + + movu m1, [srcfxq + xq] + punpcklbw m1, m2 + mova m9, m1 + psubw m1, m0 + pabsw m1, m1 + paddw m11, m1 + pcmpgtw m1, m4 + mova m6, m11 + pcmpgtw m6, m5 + por m6, m1 + pxor m6, m10 + pand m12, m6 + pand m9, m12 + paddw m7, m9 + mova m6, m12 + psrlw m6, 15 + paddw m8, m6 + + mov srcfxq, [srcfq + iq * 8] + add srcfxq, wq + + movu m1, [srcfxq + xq] + punpcklbw m1, m2 + mova m9, m1 + psubw m1, m0 + pabsw m1, m1 + paddw m3, m1 + pcmpgtw m1, m4 + mova m6, m3 + pcmpgtw m6, m5 + por m6, m1 + pxor m6, m10 + pand m12, m6 + pand m9, m12 + paddw m7, m9 + mova m6, m12 + psrlw m6, 15 + paddw m8, m6 + + ptest m12, m12 + jz .finish + + cmp iq, sizeq + jl .loop0 + + .finish: + mova m9, m8 + psrlw m9, 1 + paddw m7, m9 + + mova m1, m7 + mova m6, m8 + + punpcklwd m7, m2 + punpcklwd m8, m2 + cvtdq2ps m7, m7 + cvtdq2ps m8, m8 + divps m7, m8 + cvttps2dq m7, m7 + packssdw m7, m7 + packuswb m7, m7 + + movd [dstq + xq], m7 + + punpckhwd m1, m2 + punpckhwd m6, m2 + cvtdq2ps m1, m1 + cvtdq2ps m6, m6 + divps m1, m6 + cvttps2dq m1, m1 + packssdw m1, m1 + packuswb m1, m1 + + movd [dstq + xq + 4], m1 + + add xq, mmsize/2 + jl .loop + RET + +INIT_XMM sse4 +cglobal atadenoise_filter_row8_serial, 8,10,13, src, dst, srcf, w, mid, size, i, j, srcfx, x + movsxdifnidn wq, wd + movsxdifnidn midq, midd + movsxdifnidn sizeq, sized + add srcq, wq + add dstq, wq + mov xq, wq + dec sizeq + neg xq + movd m4, r6m + SPLATW m4, m4 + movd m5, r7m + SPLATW m5, m5 + pxor m2, m2 + mova m10, [pw_ones] + + .loop: + mov iq, midq + mov jq, midq + pxor m3, m3 + pxor m11, m11 + movu m0, [srcq + xq] + punpcklbw m0, m2 + mova m7, m0 + mova m8, [pw_one] + mova m12, [pw_ones] + + .loop0: + dec jq + + mov srcfxq, [srcfq + jq * 8] + add srcfxq, wq + + movu m1, [srcfxq + xq] + punpcklbw m1, m2 + mova m9, m1 + psubw m1, m0 + pabsw m1, m1 + paddw m11, m1 + pcmpgtw m1, m4 + mova m6, m11 + pcmpgtw m6, m5 + por m6, m1 + pxor m6, m10 + pand m12, m6 + pand m9, m12 + paddw m7, m9 + mova m6, m12 + psrlw m6, 15 + paddw m8, m6 + + ptest m12, m12 + jz .end_loop0 + + cmp jq, 0 + jg .loop0 + + .end_loop0: + mova m12, [pw_ones] + + .loop1: + inc iq + + mov srcfxq, [srcfq + iq * 8] + add srcfxq, wq + + movu m1, [srcfxq + xq] + punpcklbw m1, m2 + mova m9, m1 + psubw m1, m0 + pabsw m1, m1 + paddw m3, m1 + pcmpgtw m1, m4 + mova m6, m3 + pcmpgtw m6, m5 + por m6, m1 + pxor m6, m10 + pand m12, m6 + pand m9, m12 + paddw m7, m9 + mova m6, m12 + psrlw m6, 15 + paddw m8, m6 + + ptest m12, m12 + jz .finish + + cmp iq, sizeq + jl .loop1 + + .finish: + mova m9, m8 + psrlw m9, 1 + paddw m7, m9 + + mova m1, m7 + mova m6, m8 + + punpcklwd m7, m2 + punpcklwd m8, m2 + cvtdq2ps m7, m7 + cvtdq2ps m8, m8 + divps m7, m8 + cvttps2dq m7, m7 + packssdw m7, m7 + packuswb m7, m7 + + movd [dstq + xq], m7 + + punpckhwd m1, m2 + punpckhwd m6, m2 + cvtdq2ps m1, m1 + cvtdq2ps m6, m6 + divps m1, m6 + cvttps2dq m1, m1 + packssdw m1, m1 + packuswb m1, m1 + + movd [dstq + xq + 4], m1 + + add xq, mmsize/2 + jl .loop + RET + +%endif diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_atadenoise_init.c ffmpeg-4.4/libavfilter/x86/vf_atadenoise_init.c --- ffmpeg-4.2.2/libavfilter/x86/vf_atadenoise_init.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_atadenoise_init.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/mem.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavfilter/atadenoise.h" + +void ff_atadenoise_filter_row8_sse4(const uint8_t *src, uint8_t *dst, + const uint8_t **srcf, + int w, int mid, int size, + int thra, int thrb, const float *weights); + +void ff_atadenoise_filter_row8_serial_sse4(const uint8_t *src, uint8_t *dst, + const uint8_t **srcf, + int w, int mid, int size, + int thra, int thrb, const float *weights); + +av_cold void ff_atadenoise_init_x86(ATADenoiseDSPContext *dsp, int depth, int algorithm, const float *sigma) +{ + int cpu_flags = av_get_cpu_flags(); + + for (int p = 0; p < 4; p++) { + if (ARCH_X86_64 && EXTERNAL_SSE4(cpu_flags) && depth <= 8 && algorithm == PARALLEL && sigma[p] == INT16_MAX) { + dsp->filter_row[p] = ff_atadenoise_filter_row8_sse4; + } + + if (ARCH_X86_64 && EXTERNAL_SSE4(cpu_flags) && depth <= 8 && algorithm == SERIAL && sigma[p] == INT16_MAX) { + dsp->filter_row[p] = ff_atadenoise_filter_row8_serial_sse4; + } + } +} diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_blend.asm ffmpeg-4.4/libavfilter/x86/vf_blend.asm --- ffmpeg-4.2.2/libavfilter/x86/vf_blend.asm 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_blend.asm 2021-02-20 20:27:47.000000000 +0000 @@ -38,11 +38,11 @@ SECTION .text -%macro BLEND_INIT 2-3 +%macro BLEND_INIT 2-3 0 %if ARCH_X86_64 cglobal blend_%1, 6, 9, %2, top, top_linesize, bottom, bottom_linesize, dst, dst_linesize, width, end, x mov widthd, dword widthm - %if %0 == 3; is 16 bit + %if %3; is 16 bit add widthq, widthq ; doesn't compile on x86_32 %endif %else @@ -66,7 +66,7 @@ REP_RET %endmacro -%macro BLEND_SIMPLE 2-3 +%macro BLEND_SIMPLE 2-3 0 BLEND_INIT %1, 2, %3 .nextrow: mov xq, widthq @@ -82,10 +82,10 @@ %endmacro ; %1 name , %2 src (b or w), %3 inter (w or d), %4 (1 if 16bit, not set if 8 bit) -%macro GRAINEXTRACT 3-4 +%macro GRAINEXTRACT 3-4 0 BLEND_INIT %1, 6, %4 pxor m4, m4 -%if %0 == 4 ; 16 bit +%if %4 ; 16 bit VBROADCASTI128 m5, [pd_32768] %else VBROADCASTI128 m5, [pw_128] @@ -182,7 +182,7 @@ %endmacro ;%1 name, %2 (b or w), %3 (set if 16 bit) -%macro AVERAGE 2-3 +%macro AVERAGE 2-3 0 BLEND_INIT %1, 3, %3 pcmpeqb m2, m2 @@ -203,10 +203,10 @@ %endmacro ; %1 name , %2 src (b or w), %3 inter (w or d), %4 (1 if 16bit, not set if 8 bit) -%macro GRAINMERGE 3-4 +%macro GRAINMERGE 3-4 0 BLEND_INIT %1, 6, %4 pxor m4, m4 -%if %0 == 4 ; 16 bit +%if %4 ; 16 bit VBROADCASTI128 m5, [pd_32768] %else VBROADCASTI128 m5, [pw_128] @@ -288,7 +288,7 @@ BLEND_END %endmacro -%macro PHOENIX 2-3 +%macro PHOENIX 2-3 0 ; %1 name, %2 b or w, %3 (opt) 1 if 16 bit BLEND_INIT %1, 4, %3 VBROADCASTI128 m3, [pb_255] @@ -311,7 +311,7 @@ %endmacro ; %1 name , %2 src (b or w), %3 inter (w or d), %4 (1 if 16bit, not set if 8 bit) -%macro DIFFERENCE 3-4 +%macro DIFFERENCE 3-4 0 BLEND_INIT %1, 5, %4 pxor m2, m2 .nextrow: @@ -326,7 +326,7 @@ punpckl%2%3 m1, m2 psub%3 m0, m1 psub%3 m3, m4 -%if %0 == 4; 16 bit +%if %4; 16 bit pabsd m0, m0 pabsd m3, m3 %else @@ -340,10 +340,10 @@ %endmacro ; %1 name , %2 src (b or w), %3 inter (w or d), %4 (1 if 16bit, not set if 8 bit) -%macro EXTREMITY 3-4 +%macro EXTREMITY 3-4 0 BLEND_INIT %1, 8, %4 pxor m2, m2 -%if %0 == 4; 16 bit +%if %4; 16 bit VBROADCASTI128 m4, [pd_65535] %else VBROADCASTI128 m4, [pw_255] @@ -362,7 +362,7 @@ psub%3 m7, m4, m5 psub%3 m3, m1 psub%3 m7, m6 -%if %0 == 4; 16 bit +%if %4; 16 bit pabsd m3, m3 pabsd m7, m7 %else @@ -375,10 +375,10 @@ BLEND_END %endmacro -%macro NEGATION 3-4 +%macro NEGATION 3-4 0 BLEND_INIT %1, 8, %4 pxor m2, m2 -%if %0 == 4; 16 bit +%if %4; 16 bit VBROADCASTI128 m4, [pd_65535] %else VBROADCASTI128 m4, [pw_255] @@ -397,7 +397,7 @@ psub%3 m7, m4, m5 psub%3 m3, m1 psub%3 m7, m6 -%if %0 == 4; 16 bit +%if %4; 16 bit pabsd m3, m3 pabsd m7, m7 %else diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_convolution.asm ffmpeg-4.4/libavfilter/x86/vf_convolution.asm --- ffmpeg-4.2.2/libavfilter/x86/vf_convolution.asm 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_convolution.asm 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,156 @@ +;***************************************************************************** +;* x86-optimized functions for convolution 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" + +SECTION_RODATA +half: dd 0.5 + +SECTION .text + +; void filter_3x3_sse4(uint8_t *dst, int width, +; float rdiv, float bias, const int *const matrix, +; const uint8_t *c[], int peak, int radius, +; int dstride, int stride) + + +%macro PROCESS_V 1 + movss m2, [matrixq + 4 * %1] + VBROADCASTSS m2, m2 + movss m3, [c%1q + xq] + punpcklbw m3, m6 + punpcklwd m3, m6 + pmulld m2, m3 + paddd m4, m2 +%endmacro + +%macro PROCESS_S 1 + movzx ptrd, byte [c%1q + xq] + imul ptrd, [matrixq + 4 * %1] + add rd, ptrd +%endmacro + +%macro FILTER_3X3 0 +%if UNIX64 +cglobal filter_3x3, 4, 15, 7, dst, width, matrix, ptr, c0, c1, c2, c3, c4, c5, c6, c7, c8, r, x +%else +cglobal filter_3x3, 4, 15, 7, dst, width, rdiv, bias, matrix, ptr, c0, c1, c2, c3, c4, c5, c6, c7, c8, r, x +%endif + +%if WIN64 + SWAP m0, m2 + SWAP m1, m3 + mov r2q, matrixmp + mov r3q, ptrmp + DEFINE_ARGS dst, width, matrix, ptr, c0, c1, c2, c3, c4, c5, c6, c7, c8, r, x +%endif + movsxdifnidn widthq, widthd + VBROADCASTSS m0, m0 + VBROADCASTSS m1, m1 + pxor m6, m6 + movss m5, [half] + VBROADCASTSS m5, m5 + mov c0q, [ptrq + 0*gprsize] + mov c1q, [ptrq + 1*gprsize] + mov c2q, [ptrq + 2*gprsize] + mov c3q, [ptrq + 3*gprsize] + mov c4q, [ptrq + 4*gprsize] + mov c5q, [ptrq + 5*gprsize] + mov c6q, [ptrq + 6*gprsize] + mov c7q, [ptrq + 7*gprsize] + mov c8q, [ptrq + 8*gprsize] + + xor xq, xq + cmp widthq, mmsize/4 + jl .loop2 + + mov rq, widthq + and rq, mmsize/4-1 + sub widthq, rq + +.loop1: + pxor m4, m4 ; sum = 0; + + PROCESS_V 0 + PROCESS_V 1 + PROCESS_V 2 + PROCESS_V 3 + PROCESS_V 4 + PROCESS_V 5 + PROCESS_V 6 + PROCESS_V 7 + PROCESS_V 8 + + cvtdq2ps m4, m4 + mulps m4, m0 ; sum *= rdiv + addps m4, m1 ; sum += bias + addps m4, m5 ; sum += 0.5 + cvttps2dq m4, m4 + packssdw m4, m4 + packuswb m4, m4 + movss [dstq + xq], m4 + + add xq, mmsize/4 + cmp xq, widthq + jl .loop1 + + add widthq, rq + cmp xq, widthq + jge .end + +.loop2: + ; reuse r to hold sum, init with zero + xor rd, rd + + PROCESS_S 0 + PROCESS_S 1 + PROCESS_S 2 + PROCESS_S 3 + PROCESS_S 4 + PROCESS_S 5 + PROCESS_S 6 + PROCESS_S 7 + PROCESS_S 8 + + pxor m4, m4 + cvtsi2ss m4, rd + mulss m4, m0 ; sum *= rdiv + addss m4, m1 ; sum += bias + addss m4, m5 ; sum += 0.5 + ; we don't have simple scalar instructions to convert + ; from 32bit to 8bit with saturation, so here + ; just use packed version SSE instructions for simplicity. + cvttps2dq m4, m4 ; trunc to integer + packssdw m4, m4 + packuswb m4, m4 + movd rd, m4 + mov [dstq + xq], rb + + add xq, 1 + cmp xq, widthq + jl .loop2 +.end: + RET +%endmacro + +%if ARCH_X86_64 +INIT_XMM sse4 +FILTER_3X3 +%endif diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_convolution_init.c ffmpeg-4.4/libavfilter/x86/vf_convolution_init.c --- ffmpeg-4.2.2/libavfilter/x86/vf_convolution_init.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_convolution_init.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,46 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavfilter/convolution.h" + +void ff_filter_3x3_sse4(uint8_t *dst, int width, + float rdiv, float bias, const int *const matrix, + const uint8_t *c[], int peak, int radius, + int dstride, int stride, int size); + +av_cold void ff_convolution_init_x86(ConvolutionContext *s) +{ +#if ARCH_X86_64 + int i; + int cpu_flags = av_get_cpu_flags(); + for (i = 0; i < 4; i++) { + if (s->mode[i] == MATRIX_SQUARE) { + if (s->matrix_length[i] == 9 && s->depth == 8) { + if (EXTERNAL_SSE4(cpu_flags)) + s->filter[i] = ff_filter_3x3_sse4; + } + } + } +#endif +} diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_eq.asm ffmpeg-4.4/libavfilter/x86/vf_eq.asm --- ffmpeg-4.2.2/libavfilter/x86/vf_eq.asm 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_eq.asm 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,90 @@ +;***************************************************************************** +;* x86-optimized functions for eq filter +;* +;* Original MPlayer filters by Richard Felker. +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION .text + +%macro PROCESS_ONE_LINE 1 +cglobal process_one_line, 5, 7, 5, src, dst, contrast, brightness, w + movd m3, contrastd + movd m4, brightnessd + movsx r5d, contrastw + movsx r6d, brightnessw + SPLATW m3, m3, 0 + SPLATW m4, m4, 0 + + DEFINE_ARGS src, dst, tmp, scalar, w + xor tmpd, tmpd + pxor m0, m0 + pxor m1, m1 + mov scalard, wd + and scalard, mmsize-1 + sar wd, %1 + cmp wd, 1 + jl .loop1 + + .loop0: + movu m1, [srcq] + mova m2, m1 + punpcklbw m1, m0 + punpckhbw m2, m0 + psllw m1, 4 + psllw m2, 4 + pmulhw m1, m3 + pmulhw m2, m3 + paddw m1, m4 + paddw m2, m4 + packuswb m1, m2 + movu [dstq], m1 + add srcq, mmsize + add dstq, mmsize + sub wd, 1 + cmp wd, 0 + jne .loop0 + + .loop1: + cmp scalard, 0 + je .end + movzx tmpd, byte [srcq] + imul tmpd, r5d + sar tmpd, 12 + add tmpd, r6d + movd m1, tmpd + packuswb m1, m0 + movd tmpd, m1 + mov [dstq], tmpb + inc srcq + inc dstq + dec scalard + jmp .loop1 + + .end: + RET + +%endmacro + +INIT_MMX mmxext +PROCESS_ONE_LINE 3 + +INIT_XMM sse2 +PROCESS_ONE_LINE 4 diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_eq.c ffmpeg-4.4/libavfilter/x86/vf_eq.c --- ffmpeg-4.2.2/libavfilter/x86/vf_eq.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_eq.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -/* - * - * Original MPlayer filters by Richard Felker. - * - * 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 "libavutil/attributes.h" -#include "libavutil/cpu.h" -#include "libavutil/mem.h" -#include "libavutil/x86/asm.h" -#include "libavfilter/vf_eq.h" - -#if HAVE_MMX_INLINE && HAVE_6REGS -static void process_MMX(EQParameters *param, uint8_t *dst, int dst_stride, - const uint8_t *src, int src_stride, int w, int h) -{ - int i; - int pel; - int dstep = dst_stride - w; - int sstep = src_stride - w; - short brvec[4]; - short contvec[4]; - int contrast = (int) (param->contrast * 256 * 16); - int brightness = ((int) (100.0 * param->brightness + 100.0) * 511) / 200 - 128 - contrast / 32; - - brvec[0] = brvec[1] = brvec[2] = brvec[3] = brightness; - contvec[0] = contvec[1] = contvec[2] = contvec[3] = contrast; - - while (h--) { - __asm__ volatile ( - "movq (%5), %%mm3 \n\t" - "movq (%6), %%mm4 \n\t" - "pxor %%mm0, %%mm0 \n\t" - "movl %4, %%eax \n\t" - ".p2align 4 \n\t" - "1: \n\t" - "movq (%0), %%mm1 \n\t" - "movq (%0), %%mm2 \n\t" - "punpcklbw %%mm0, %%mm1\n\t" - "punpckhbw %%mm0, %%mm2\n\t" - "psllw $4, %%mm1 \n\t" - "psllw $4, %%mm2 \n\t" - "pmulhw %%mm4, %%mm1 \n\t" - "pmulhw %%mm4, %%mm2 \n\t" - "paddw %%mm3, %%mm1 \n\t" - "paddw %%mm3, %%mm2 \n\t" - "packuswb %%mm2, %%mm1 \n\t" - "add $8, %0 \n\t" - "movq %%mm1, (%1) \n\t" - "add $8, %1 \n\t" - "decl %%eax \n\t" - "jnz 1b \n\t" - : "=r" (src), "=r" (dst) - : "0" (src), "1" (dst), "r" (w>>3), "r" (brvec), "r" (contvec) - : "%eax" - ); - - for (i = w&7; i; i--) { - pel = ((*src++ * contrast) >> 12) + brightness; - if (pel & ~255) - pel = (-pel) >> 31; - *dst++ = pel; - } - - src += sstep; - dst += dstep; - } - __asm__ volatile ( "emms \n\t" ::: "memory" ); -} -#endif - -av_cold void ff_eq_init_x86(EQContext *eq) -{ -#if HAVE_MMX_INLINE && HAVE_6REGS - int cpu_flags = av_get_cpu_flags(); - - if (cpu_flags & AV_CPU_FLAG_MMX) { - eq->process = process_MMX; - } -#endif -} diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_eq_init.c ffmpeg-4.4/libavfilter/x86/vf_eq_init.c --- ffmpeg-4.2.2/libavfilter/x86/vf_eq_init.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_eq_init.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,76 @@ +/* + * + * Original MPlayer filters by Richard Felker. + * + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/mem.h" +#include "libavutil/x86/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavfilter/vf_eq.h" + +extern void ff_process_one_line_mmxext(const uint8_t *src, uint8_t *dst, short contrast, + short brightness, int w); +extern void ff_process_one_line_sse2(const uint8_t *src, uint8_t *dst, short contrast, + short brightness, int w); + +#if HAVE_X86ASM +static void process_mmxext(EQParameters *param, uint8_t *dst, int dst_stride, + const uint8_t *src, int src_stride, int w, int h) +{ + short contrast = (short) (param->contrast * 256 * 16); + short brightness = ((short) (100.0 * param->brightness + 100.0) * 511) + / 200 - 128 - contrast / 32; + + while (h--) { + ff_process_one_line_mmxext(src, dst, contrast, brightness, w); + src += src_stride; + dst += dst_stride; + } + emms_c(); +} + +static void process_sse2(EQParameters *param, uint8_t *dst, int dst_stride, + const uint8_t *src, int src_stride, int w, int h) +{ + short contrast = (short) (param->contrast * 256 * 16); + short brightness = ((short) (100.0 * param->brightness + 100.0) * 511) + / 200 - 128 - contrast / 32; + + while (h--) { + ff_process_one_line_sse2(src, dst, contrast, brightness, w); + src += src_stride; + dst += dst_stride; + } +} +#endif + +av_cold void ff_eq_init_x86(EQContext *eq) +{ +#if HAVE_X86ASM + int cpu_flags = av_get_cpu_flags(); + if (EXTERNAL_MMXEXT(cpu_flags)) { + eq->process = process_mmxext; + } + if (EXTERNAL_SSE2(cpu_flags)) { + eq->process = process_sse2; + } +#endif +} diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_gblur.asm ffmpeg-4.4/libavfilter/x86/vf_gblur.asm --- ffmpeg-4.2.2/libavfilter/x86/vf_gblur.asm 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_gblur.asm 2021-04-08 21:28:40.000000000 +0000 @@ -100,7 +100,7 @@ add widthq, remainq cmp xq, widthq - je .end_scalar + jge .end_scalar .loop_scalar: ; ptr[x] += nu * ptr[x-1] @@ -148,7 +148,7 @@ jg .loop_x_back cmp xq, 0 - je .end_scalar_back + jle .end_scalar_back .loop_scalar_back: ; ptr[x-1] += nu * ptr[x] @@ -183,3 +183,49 @@ INIT_XMM avx2 HORIZ_SLICE %endif + +%macro POSTSCALE_SLICE 0 +cglobal postscale_slice, 2, 2, 4, ptr, length, postscale, min, max + shl lengthd, 2 + add ptrq, lengthq + neg lengthq +%if ARCH_X86_32 + VBROADCASTSS m0, postscalem + VBROADCASTSS m1, minm + VBROADCASTSS m2, maxm +%elif WIN64 + SWAP 0, 2 + SWAP 1, 3 + VBROADCASTSS m0, xm0 + VBROADCASTSS m1, xm1 + VBROADCASTSS m2, maxm +%else ; UNIX64 + VBROADCASTSS m0, xm0 + VBROADCASTSS m1, xm1 + VBROADCASTSS m2, xm2 +%endif + + .loop: +%if cpuflag(avx2) + mulps m3, m0, [ptrq + lengthq] +%else + movu m3, [ptrq + lengthq] + mulps m3, m0 +%endif + maxps m3, m1 + minps m3, m2 + movu [ptrq+lengthq], m3 + + add lengthq, mmsize + jl .loop + + RET +%endmacro + +INIT_XMM sse +POSTSCALE_SLICE + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +POSTSCALE_SLICE +%endif diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_gblur_init.c ffmpeg-4.4/libavfilter/x86/vf_gblur_init.c --- ffmpeg-4.2.2/libavfilter/x86/vf_gblur_init.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_gblur_init.c 2021-04-08 21:28:40.000000000 +0000 @@ -27,14 +27,25 @@ void ff_horiz_slice_sse4(float *ptr, int width, int height, int steps, float nu, float bscale); void ff_horiz_slice_avx2(float *ptr, int width, int height, int steps, float nu, float bscale); +void ff_postscale_slice_sse(float *ptr, int length, float postscale, float min, float max); +void ff_postscale_slice_avx2(float *ptr, int length, float postscale, float min, float max); + av_cold void ff_gblur_init_x86(GBlurContext *s) { -#if ARCH_X86_64 int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_SSE4(cpu_flags)) + if (EXTERNAL_SSE(cpu_flags)) { + s->postscale_slice = ff_postscale_slice_sse; + } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + s->postscale_slice = ff_postscale_slice_avx2; + } +#if ARCH_X86_64 + if (EXTERNAL_SSE4(cpu_flags)) { s->horiz_slice = ff_horiz_slice_sse4; - if (EXTERNAL_AVX2(cpu_flags)) + } + if (EXTERNAL_AVX2(cpu_flags)) { s->horiz_slice = ff_horiz_slice_avx2; + } #endif } diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_interlace.asm ffmpeg-4.4/libavfilter/x86/vf_interlace.asm --- ffmpeg-4.2.2/libavfilter/x86/vf_interlace.asm 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_interlace.asm 2020-07-11 10:39:30.000000000 +0000 @@ -49,7 +49,7 @@ pxor m2, m6, [srcq+hq] pavg%1 m0, m2 pxor m0, m6 - mova [dstq+hq], m0 + movu [dstq+hq], m0 add hq, mmsize jge .end @@ -66,8 +66,8 @@ pavg%1 m1, m3 pxor m0, m6 pxor m1, m6 - mova [dstq+hq], m0 - mova [dstq+hq+mmsize], m1 + movu [dstq+hq], m0 + movu [dstq+hq+mmsize], m1 add hq, 2*mmsize jl .loop @@ -140,7 +140,7 @@ pand m0, m6 pandn m6, m1 por m0, m6 - mova [dstq], m0 + movu [dstq], m0 add dstq, mmsize add srcq, mmsize @@ -201,8 +201,8 @@ pandn m7, m3 por m0, m6 por m1, m7 - mova [dstq], m0 - mova [dstq+mmsize], m1 + movu [dstq], m0 + movu [dstq+mmsize], m1 add dstq, 2*mmsize add srcq, 2*mmsize diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_maskedclamp.asm ffmpeg-4.4/libavfilter/x86/vf_maskedclamp.asm --- ffmpeg-4.2.2/libavfilter/x86/vf_maskedclamp.asm 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_maskedclamp.asm 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,95 @@ +;***************************************************************************** +;* x86-optimized functions for maskedclamp filter +;* +;* Copyright (c) 2019 Paul B Mahol +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION .text + +;------------------------------------------------------------------------------ +; void ff_maskedclamp(const uint8_t *src, uint8_t *dst, +; const uint8_t *darksrc, +; const uint8_t *brightsrc, +; int w, int undershoot, int overshoot) +;------------------------------------------------------------------------------ + +INIT_XMM sse2 +cglobal maskedclamp8, 5,5,5, src, dst, dark, bright, w, undershoot, overshoot + movsxdifnidn wq, wd + + add srcq, wq + add darkq, wq + add brightq, wq + add dstq, wq + neg wq + + movd m3, r5m + punpcklbw m3, m3 + SPLATW m3, m3 + + movd m4, r6m + punpcklbw m4, m4 + SPLATW m4, m4 + + .loop: + movu m0, [srcq + wq] + movu m1, [darkq + wq] + movu m2, [brightq + wq] + + psubusb m1, m3 + paddusb m2, m4 + CLIPUB m0, m1, m2 + mova [dstq + wq], m0 + + add wq, mmsize + jl .loop + RET + +INIT_XMM sse4 +cglobal maskedclamp16, 5,5,5, src, dst, dark, bright, w, undershoot, overshoot + shl wd, 1 + + add srcq, wq + add darkq, wq + add brightq, wq + add dstq, wq + neg wq + + movd m3, r5m + SPLATW m3, m3 + + movd m4, r6m + SPLATW m4, m4 + + .loop: + movu m0, [srcq + wq] + movu m1, [darkq + wq] + movu m2, [brightq + wq] + + psubusw m1, m3 + paddusw m2, m4 + pmaxuw m0, m1 + pminuw m0, m2 + mova [dstq + wq], m0 + + add wq, mmsize + jl .loop + RET diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_maskedclamp_init.c ffmpeg-4.4/libavfilter/x86/vf_maskedclamp_init.c --- ffmpeg-4.2.2/libavfilter/x86/vf_maskedclamp_init.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_maskedclamp_init.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/mem.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavfilter/maskedclamp.h" + +void ff_maskedclamp8_sse2(const uint8_t *bsrc, uint8_t *dst, + const uint8_t *darksrc, const uint8_t *brightsrc, + int w, int undershoot, int overshoot); + +void ff_maskedclamp16_sse4(const uint8_t *bsrc, uint8_t *dst, + const uint8_t *darksrc, const uint8_t *brightsrc, + int w, int undershoot, int overshoot); + +av_cold void ff_maskedclamp_init_x86(MaskedClampDSPContext *dsp, int depth) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_SSE2(cpu_flags) && depth <= 8) { + dsp->maskedclamp = ff_maskedclamp8_sse2; + } + + if (EXTERNAL_SSE4(cpu_flags) && depth > 8) { + dsp->maskedclamp = ff_maskedclamp16_sse4; + } +} diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_ssim.asm ffmpeg-4.4/libavfilter/x86/vf_ssim.asm --- ffmpeg-4.2.2/libavfilter/x86/vf_ssim.asm 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_ssim.asm 2020-07-11 10:39:30.000000000 +0000 @@ -169,8 +169,9 @@ %endif INIT_XMM sse4 -cglobal ssim_end_line, 3, 3, 6, sum0, sum1, w +cglobal ssim_end_line, 3, 3, 7, sum0, sum1, w pxor m0, m0 + pxor m6, m6 .loop: mova m1, [sum0q+mmsize*0] mova m2, [sum0q+mmsize*1] @@ -214,34 +215,46 @@ mulps m4, m5 mulps m3, m1 divps m4, m3 ; ssim_endl - addps m0, m4 ; ssim + mova m5, m4 + cvtps2pd m3, m5 + movhlps m5, m5 + cvtps2pd m5, m5 + addpd m0, m3 ; ssim + addpd m6, m5 ; ssim add sum0q, mmsize*4 add sum1q, mmsize*4 sub wd, 4 jg .loop - ; subps the ones we added too much + ; subpd the ones we added too much test wd, wd jz .end add wd, 4 + test wd, 3 + jz .skip3 test wd, 2 jz .skip2 - psrldq m4, 8 -.skip2: test wd, 1 jz .skip1 - psrldq m4, 4 +.skip3: + psrldq m5, 8 + subpd m6, m5 + jmp .end +.skip2: + psrldq m5, 8 + subpd m6, m5 + subpd m0, m3 + jmp .end .skip1: - subps m0, m4 + psrldq m3, 16 + subpd m6, m5 .end: + addpd m0, m6 movhlps m4, m0 - addps m0, m4 - movss m4, m0 - shufps m0, m0, 1 - addss m0, m4 + addpd m0, m4 %if ARCH_X86_32 - movss r0m, m0 - fld r0mp + movsd r0m, m0 + fld qword r0m %endif RET diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_ssim_init.c ffmpeg-4.4/libavfilter/x86/vf_ssim_init.c --- ffmpeg-4.2.2/libavfilter/x86/vf_ssim_init.c 2017-12-31 22:35:48.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_ssim_init.c 2020-07-11 10:39:30.000000000 +0000 @@ -28,7 +28,7 @@ void ff_ssim_4x4_line_xop (const uint8_t *buf, ptrdiff_t buf_stride, const uint8_t *ref, ptrdiff_t ref_stride, int (*sums)[4], int w); -float ff_ssim_end_line_sse4(const int (*sum0)[4], const int (*sum1)[4], int w); +double ff_ssim_end_line_sse4(const int (*sum0)[4], const int (*sum1)[4], int w); void ff_ssim_init_x86(SSIMDSPContext *dsp) { diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_transpose.asm ffmpeg-4.4/libavfilter/x86/vf_transpose.asm --- ffmpeg-4.2.2/libavfilter/x86/vf_transpose.asm 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_transpose.asm 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,87 @@ +;***************************************************************************** +;* x86-optimized functions for transpose filter +;* +;* Copyright (C) 2019 Paul B Mahol +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION .text + +;------------------------------------------------------------------------------ +; void ff_transpose_8x8(uint8_t *src, ptrdiff_t src_linesize, +; uint8_t *dst, ptrdiff_t dst_linesize) +;------------------------------------------------------------------------------ + +INIT_XMM sse2 +cglobal transpose_8x8_8, 4,5,8, src, src_linesize, dst, dst_linesize, linesize3 + lea linesize3q, [src_linesizeq * 3] + movq m0, [srcq + src_linesizeq * 0] + movq m1, [srcq + src_linesizeq * 1] + movq m2, [srcq + src_linesizeq * 2] + movq m3, [srcq + linesize3q] + lea srcq, [srcq + src_linesizeq * 4] + movq m4, [srcq + src_linesizeq * 0] + movq m5, [srcq + src_linesizeq * 1] + movq m6, [srcq + src_linesizeq * 2] + movq m7, [srcq + linesize3q] + + TRANSPOSE_8X8B 0, 1, 2, 3, 4, 5, 6, 7 + + lea linesize3q, [dst_linesizeq * 3] + movq [dstq + dst_linesizeq * 0], m0 + movq [dstq + dst_linesizeq * 1], m1 + movq [dstq + dst_linesizeq * 2], m2 + movq [dstq + linesize3q], m3 + lea dstq, [dstq + dst_linesizeq * 4] + movq [dstq + dst_linesizeq * 0], m4 + movq [dstq + dst_linesizeq * 1], m5 + movq [dstq + dst_linesizeq * 2], m6 + movq [dstq + linesize3q], m7 + RET + +cglobal transpose_8x8_16, 4,5,9, ARCH_X86_32 * 32, src, src_linesize, dst, dst_linesize, linesize3 + lea linesize3q, [src_linesizeq * 3] + movu m0, [srcq + src_linesizeq * 0] + movu m1, [srcq + src_linesizeq * 1] + movu m2, [srcq + src_linesizeq * 2] + movu m3, [srcq + linesize3q] + lea srcq, [srcq + src_linesizeq * 4] + movu m4, [srcq + src_linesizeq * 0] + movu m5, [srcq + src_linesizeq * 1] + movu m6, [srcq + src_linesizeq * 2] + movu m7, [srcq + linesize3q] + +%if ARCH_X86_64 + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, 8 +%else + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, [rsp], [rsp + 16] +%endif + + lea linesize3q, [dst_linesizeq * 3] + movu [dstq + dst_linesizeq * 0], m0 + movu [dstq + dst_linesizeq * 1], m1 + movu [dstq + dst_linesizeq * 2], m2 + movu [dstq + linesize3q], m3 + lea dstq, [dstq + dst_linesizeq * 4] + movu [dstq + dst_linesizeq * 0], m4 + movu [dstq + dst_linesizeq * 1], m5 + movu [dstq + dst_linesizeq * 2], m6 + movu [dstq + linesize3q], m7 + RET diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_transpose_init.c ffmpeg-4.4/libavfilter/x86/vf_transpose_init.c --- ffmpeg-4.2.2/libavfilter/x86/vf_transpose_init.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_transpose_init.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2019 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/mem.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavfilter/transpose.h" + +void ff_transpose_8x8_8_sse2(uint8_t *src, + ptrdiff_t src_linesize, + uint8_t *dst, + ptrdiff_t dst_linesize); + +void ff_transpose_8x8_16_sse2(uint8_t *src, + ptrdiff_t src_linesize, + uint8_t *dst, + ptrdiff_t dst_linesize); + +av_cold void ff_transpose_init_x86(TransVtable *v, int pixstep) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_SSE2(cpu_flags) && pixstep == 1) { + v->transpose_8x8 = ff_transpose_8x8_8_sse2; + } + + if (EXTERNAL_SSE2(cpu_flags) && pixstep == 2) { + v->transpose_8x8 = ff_transpose_8x8_16_sse2; + } +} diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_v360.asm ffmpeg-4.4/libavfilter/x86/vf_v360.asm --- ffmpeg-4.2.2/libavfilter/x86/vf_v360.asm 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_v360.asm 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,256 @@ +;***************************************************************************** +;* x86-optimized functions for v360 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 + +SECTION_RODATA + +pb_mask: db 0,4,8,12,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 +pw_mask: db 0,1,4, 5, 8, 9,12,13,-1,-1,-1,-1,-1,-1,-1,-1 +pd_255: times 4 dd 255 +pd_65535: times 4 dd 65535 + +SECTION .text + +; void ff_remap2_8bit_line_avx2(uint8_t *dst, int width, const uint8_t *src, ptrdiff_t in_linesize, +; const uint16_t *u, const uint16_t *v, const int16_t *ker); + +INIT_YMM avx2 +cglobal remap1_8bit_line, 6, 7, 6, dst, width, src, in_linesize, u, v, x + movsxdifnidn widthq, widthd + xor xq, xq + movd xm0, in_linesized + pcmpeqw m4, m4 + VBROADCASTI128 m3, [pb_mask] + vpbroadcastd m0, xm0 + + .loop: + pmovsxwd m1, [vq + xq * 2] + pmovsxwd m2, [uq + xq * 2] + + pmulld m1, m0 + paddd m1, m2 + mova m2, m4 + vpgatherdd m5, [srcq + m1], m2 + pshufb m1, m5, m3 + vextracti128 xm2, m1, 1 + movd [dstq+xq], xm1 + movd [dstq+xq+4], xm2 + + add xq, mmsize / 4 + cmp xq, widthq + jl .loop + RET + +INIT_YMM avx2 +cglobal remap1_16bit_line, 6, 7, 6, dst, width, src, in_linesize, u, v, x + movsxdifnidn widthq, widthd + xor xq, xq + movd xm0, in_linesized + pcmpeqw m4, m4 + VBROADCASTI128 m3, [pw_mask] + vpbroadcastd m0, xm0 + + .loop: + pmovsxwd m1, [vq + xq * 2] + pmovsxwd m2, [uq + xq * 2] + + pslld m2, 0x1 + pmulld m1, m0 + paddd m1, m2 + mova m2, m4 + vpgatherdd m5, [srcq + m1], m2 + pshufb m1, m5, m3 + vextracti128 xm2, m1, 1 + movq [dstq+xq*2], xm1 + movq [dstq+xq*2+8], xm2 + + add xq, mmsize / 4 + cmp xq, widthq + jl .loop + RET + +INIT_YMM avx2 +cglobal remap2_8bit_line, 7, 8, 8, dst, width, src, in_linesize, u, v, ker, x + movsxdifnidn widthq, widthd + movd xm0, in_linesized +%if ARCH_X86_32 +DEFINE_ARGS dst, width, src, x, u, v, ker +%endif + xor xq, xq + pcmpeqw m7, m7 + vpbroadcastd m0, xm0 + vpbroadcastd m6, [pd_255] + + .loop: + pmovsxwd m1, [kerq + xq * 8] + pmovsxwd m2, [vq + xq * 8] + pmovsxwd m3, [uq + xq * 8] + + pmulld m4, m2, m0 + paddd m4, m3 + mova m3, m7 + vpgatherdd m2, [srcq + m4], m3 + pand m2, m6 + pmulld m2, m1 + phaddd m2, m2 + phaddd m1, m2, m2 + psrld m1, m1, 0xe + vextracti128 xm2, m1, 1 + + pextrb [dstq+xq], xm1, 0 + pextrb [dstq+xq+1], xm2, 0 + + add xq, mmsize / 16 + cmp xq, widthq + jl .loop + RET + +INIT_YMM avx2 +cglobal remap2_16bit_line, 7, 8, 8, dst, width, src, in_linesize, u, v, ker, x + movsxdifnidn widthq, widthd + movd xm0, in_linesized +%if ARCH_X86_32 +DEFINE_ARGS dst, width, src, x, u, v, ker +%endif + xor xq, xq + pcmpeqw m7, m7 + vpbroadcastd m0, xm0 + vpbroadcastd m6, [pd_65535] + + .loop: + pmovsxwd m1, [kerq + xq * 8] + pmovsxwd m2, [vq + xq * 8] + pmovsxwd m3, [uq + xq * 8] + + pslld m3, 0x1 + pmulld m4, m2, m0 + paddd m4, m3 + mova m3, m7 + vpgatherdd m2, [srcq + m4], m3 + pand m2, m6 + pmulld m2, m1 + phaddd m2, m2 + phaddd m1, m2, m2 + psrld m1, m1, 0xe + vextracti128 xm2, m1, 1 + + pextrw [dstq+xq*2], xm1, 0 + pextrw [dstq+xq*2+2], xm2, 0 + + add xq, mmsize / 16 + cmp xq, widthq + jl .loop + RET + +%if ARCH_X86_64 + +INIT_YMM avx2 +cglobal remap3_8bit_line, 7, 11, 8, dst, width, src, in_linesize, u, v, ker, x, y, tmp, z + movsxdifnidn widthq, widthd + xor zq, zq + xor yq, yq + xor xq, xq + movd xm0, in_linesized + pcmpeqw m7, m7 + vpbroadcastd m0, xm0 + vpbroadcastd m6, [pd_255] + + .loop: + pmovsxwd m1, [kerq + yq] + pmovsxwd m2, [vq + yq] + pmovsxwd m3, [uq + yq] + + pmulld m4, m2, m0 + paddd m4, m3 + mova m3, m7 + vpgatherdd m2, [srcq + m4], m3 + pand m2, m6 + pmulld m2, m1 + HADDD m2, m1 + movzx tmpq, word [vq + yq + 16] + imul tmpq, in_linesizeq + movzx zq, word [uq + yq + 16] + add tmpq, zq + movzx zq, byte [srcq + tmpq] + movzx tmpq, word [kerq + yq + 16] + imul zd, tmpd + movd xm1, zd + paddd m2, m1 + psrld m2, m2, 0xe + + packuswb m2, m2 + pextrb [dstq+xq], xm2, 0 + + add xq, 1 + add yq, 18 + cmp xq, widthq + jl .loop + RET + +INIT_YMM avx2 +cglobal remap4_8bit_line, 7, 9, 11, dst, width, src, in_linesize, u, v, ker, x, y + movsxdifnidn widthq, widthd + xor yq, yq + xor xq, xq + movd xm0, in_linesized + pcmpeqw m7, m7 + vpbroadcastd m0, xm0 + vpbroadcastd m6, [pd_255] + + .loop: + pmovsxwd m1, [kerq + yq] + pmovsxwd m5, [kerq + yq + 16] + pmovsxwd m2, [vq + yq] + pmovsxwd m8, [vq + yq + 16] + pmovsxwd m3, [uq + yq] + pmovsxwd m9, [uq + yq + 16] + + pmulld m4, m2, m0 + pmulld m10, m8, m0 + paddd m4, m3 + paddd m10, m9 + mova m3, m7 + vpgatherdd m2, [srcq + m4], m3 + mova m3, m7 + vpgatherdd m4, [srcq + m10], m3 + pand m2, m6 + pand m4, m6 + pmulld m2, m1 + pmulld m4, m5 + + paddd m2, m4 + HADDD m2, m1 + psrld m2, m2, 0xe + packuswb m2, m2 + + pextrb [dstq+xq], xm2, 0 + + add xq, 1 + add yq, 32 + cmp xq, widthq + jl .loop + RET + +%endif +%endif diff -Nru ffmpeg-4.2.2/libavfilter/x86/vf_v360_init.c ffmpeg-4.4/libavfilter/x86/vf_v360_init.c --- ffmpeg-4.2.2/libavfilter/x86/vf_v360_init.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavfilter/x86/vf_v360_init.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavfilter/v360.h" + +void ff_remap1_8bit_line_avx2(uint8_t *dst, int width, const uint8_t *src, ptrdiff_t in_linesize, + const int16_t *const u, const int16_t *const v, const int16_t *const ker); + +void ff_remap2_8bit_line_avx2(uint8_t *dst, int width, const uint8_t *src, ptrdiff_t in_linesize, + const int16_t *const u, const int16_t *const v, const int16_t *const ker); + +void ff_remap3_8bit_line_avx2(uint8_t *dst, int width, const uint8_t *src, ptrdiff_t in_linesize, + const int16_t *const u, const int16_t *const v, const int16_t *const ker); + +void ff_remap4_8bit_line_avx2(uint8_t *dst, int width, const uint8_t *src, ptrdiff_t in_linesize, + const int16_t *const u, const int16_t *const v, const int16_t *const ker); + +void ff_remap1_16bit_line_avx2(uint8_t *dst, int width, const uint8_t *src, ptrdiff_t in_linesize, + const int16_t *const u, const int16_t *const v, const int16_t *const ker); + +void ff_remap2_16bit_line_avx2(uint8_t *dst, int width, const uint8_t *src, ptrdiff_t in_linesize, + const int16_t *const u, const int16_t *const v, const int16_t *const ker); + +av_cold void ff_v360_init_x86(V360Context *s, int depth) +{ + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_AVX2_FAST(cpu_flags) && s->interp == NEAREST && depth <= 8) + s->remap_line = ff_remap1_8bit_line_avx2; + + if (EXTERNAL_AVX2_FAST(cpu_flags) && s->interp == BILINEAR && depth <= 8) + s->remap_line = ff_remap2_8bit_line_avx2; + + if (EXTERNAL_AVX2_FAST(cpu_flags) && s->interp == NEAREST && depth > 8) + s->remap_line = ff_remap1_16bit_line_avx2; + + if (EXTERNAL_AVX2_FAST(cpu_flags) && s->interp == BILINEAR && depth > 8) + s->remap_line = ff_remap2_16bit_line_avx2; + +#if ARCH_X86_64 + if (EXTERNAL_AVX2_FAST(cpu_flags) && s->interp == LAGRANGE9 && depth <= 8) + s->remap_line = ff_remap3_8bit_line_avx2; + + if (EXTERNAL_AVX2_FAST(cpu_flags) && (s->interp == BICUBIC || + s->interp == LANCZOS || + s->interp == SPLINE16 || + s->interp == GAUSSIAN || + s->interp == MITCHELL) && depth <= 8) + s->remap_line = ff_remap4_8bit_line_avx2; +#endif +} diff -Nru ffmpeg-4.2.2/libavformat/3dostr.c ffmpeg-4.4/libavformat/3dostr.c --- ffmpeg-4.2.2/libavformat/3dostr.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/3dostr.c 2021-04-08 21:28:40.000000000 +0000 @@ -19,17 +19,56 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/intreadwrite.h" #include "avformat.h" #include "internal.h" static int threedostr_probe(const AVProbeData *p) { - if (memcmp(p->buf, "CTRL", 4) && - memcmp(p->buf, "SHDR", 4) && - memcmp(p->buf, "SNDS", 4)) - return 0; + for (int i = 0; i < p->buf_size;) { + unsigned chunk = AV_RL32(p->buf + i); + unsigned size = AV_RB32(p->buf + i + 4); + + if (size < 8 || p->buf_size - i < size) + return 0; + i += 8; + size -= 8; + switch (chunk) { + case MKTAG('C','T','R','L'): + break; + case MKTAG('S','N','D','S'): + if (size < 56) + return 0; + i += 8; + if (AV_RL32(p->buf + i) != MKTAG('S','H','D','R')) + return 0; + i += 28; + + if (AV_RB32(p->buf + i) <= 0) + return 0; + i += 4; + if (AV_RB32(p->buf + i) <= 0) + return 0; + i += 4; + if (AV_RL32(p->buf + i) == MKTAG('S','D','X','2')) + return AVPROBE_SCORE_MAX; + else + return 0; + break; + case MKTAG('S','H','D','R'): + if (size > 0x78) { + i += 0x78; + size -= 0x78; + } + break; + default: + break; + } - return AVPROBE_SCORE_MAX / 3 * 2; + i += size; + } + + return 0; } static int threedostr_read_header(AVFormatContext *s) @@ -64,7 +103,7 @@ st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->sample_rate = avio_rb32(s->pb); st->codecpar->channels = avio_rb32(s->pb); - if (st->codecpar->channels <= 0) + if (st->codecpar->channels <= 0 || st->codecpar->sample_rate <= 0) return AVERROR_INVALIDDATA; codec = avio_rl32(s->pb); avio_skip(s->pb, 4); @@ -110,15 +149,12 @@ static int threedostr_read_packet(AVFormatContext *s, AVPacket *pkt) { - unsigned chunk, size, found_ssmp = 0; + unsigned chunk, size; AVStream *st = s->streams[0]; int64_t pos; int ret = 0; - while (!found_ssmp) { - if (avio_feof(s->pb)) - return AVERROR_EOF; - + while (!avio_feof(s->pb)) { pos = avio_tell(s->pb); chunk = avio_rl32(s->pb); size = avio_rb32(s->pb); @@ -143,9 +179,7 @@ pkt->pos = pos; pkt->stream_index = 0; pkt->duration = size / st->codecpar->channels; - size = 0; - found_ssmp = 1; - break; + return ret; default: av_log(s, AV_LOG_DEBUG, "skipping unknown chunk: %X\n", chunk); break; @@ -154,7 +188,7 @@ avio_skip(s->pb, size); } - return ret; + return AVERROR_EOF; } AVInputFormat ff_threedostr_demuxer = { diff -Nru ffmpeg-4.2.2/libavformat/4xm.c ffmpeg-4.4/libavformat/4xm.c --- ffmpeg-4.2.2/libavformat/4xm.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/4xm.c 2021-02-20 20:27:47.000000000 +0000 @@ -59,8 +59,10 @@ #define GET_LIST_HEADER() \ fourcc_tag = avio_rl32(pb); \ size = avio_rl32(pb); \ - if (fourcc_tag != LIST_TAG) \ - return AVERROR_INVALIDDATA; \ + if (fourcc_tag != LIST_TAG) { \ + ret = AVERROR_INVALIDDATA; \ + goto fail; \ + } \ fourcc_tag = avio_rl32(pb); typedef struct AudioTrack { @@ -210,12 +212,13 @@ unsigned int size; int header_size; FourxmDemuxContext *fourxm = s->priv_data; - unsigned char *header; + unsigned char *header = NULL; int i, ret; fourxm->track_count = 0; fourxm->tracks = NULL; fourxm->fps = (AVRational){1,1}; + fourxm->video_stream_index = -1; /* skip the first 3 32-bit numbers */ avio_skip(pb, 12); @@ -241,7 +244,8 @@ size = AV_RL32(&header[i + 4]); if (size > header_size - i - 8 && (fourcc_tag == vtrk_TAG || fourcc_tag == strk_TAG)) { av_log(s, AV_LOG_ERROR, "chunk larger than array %d>%d\n", size, header_size - i - 8); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } if (fourcc_tag == std__TAG) { @@ -295,7 +299,7 @@ unsigned int track_number; int packet_read = 0; unsigned char header[8]; - int audio_frame_count; + int64_t audio_frame_count; while (!packet_read) { if ((ret = avio_read(s->pb, header, 8)) < 0) @@ -321,8 +325,12 @@ case cfr2_TAG: /* allocate 8 more bytes than 'size' to account for fourcc * and size */ - if (size + 8 < size || av_new_packet(pkt, size + 8)) - return AVERROR(EIO); + if (size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE - 8) + return AVERROR_INVALIDDATA; + if (fourxm->video_stream_index < 0) + return AVERROR_INVALIDDATA; + if ((ret = av_new_packet(pkt, size + 8)) < 0) + return ret; pkt->stream_index = fourxm->video_stream_index; pkt->pts = fourxm->video_pts; pkt->pos = avio_tell(s->pb); @@ -346,7 +354,7 @@ fourxm->tracks[track_number].channels > 0) { ret = av_get_packet(s->pb, pkt, size); if (ret < 0) - return AVERROR(EIO); + return ret; pkt->stream_index = fourxm->tracks[track_number].stream_index; pkt->pts = fourxm->tracks[track_number].audio_pts; diff -Nru ffmpeg-4.2.2/libavformat/aacdec.c ffmpeg-4.4/libavformat/aacdec.c --- ffmpeg-4.2.2/libavformat/aacdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/aacdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -141,13 +141,12 @@ ret = av_append_packet(s->pb, pkt, ff_id3v2_tag_len(pkt->data) - pkt->size); if (ret < 0) { - av_packet_unref(pkt); return ret; } ffio_init_context(&ioctx, pkt->data, pkt->size, 0, NULL, NULL, NULL, NULL); ff_id3v2_read_dict(&ioctx, &metadata, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); - if ((ret = ff_id3v2_parse_priv_dict(&metadata, &id3v2_extra_meta)) < 0) + if ((ret = ff_id3v2_parse_priv_dict(&metadata, id3v2_extra_meta)) < 0) goto error; if (metadata) { @@ -174,7 +173,6 @@ return ret; if (ret < ADTS_HEADER_SIZE) { - av_packet_unref(pkt); return AVERROR(EIO); } @@ -185,7 +183,6 @@ av_assert2(append > 0); ret = av_append_packet(s->pb, pkt, append); if (ret != append) { - av_packet_unref(pkt); return AVERROR(EIO); } if (!ff_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) { @@ -201,13 +198,10 @@ fsize = (AV_RB32(pkt->data + 3) >> 13) & 0x1FFF; if (fsize < ADTS_HEADER_SIZE) { - av_packet_unref(pkt); return AVERROR_INVALIDDATA; } ret = av_append_packet(s->pb, pkt, fsize - pkt->size); - if (ret < 0) - av_packet_unref(pkt); return ret; } diff -Nru ffmpeg-4.2.2/libavformat/aadec.c ffmpeg-4.4/libavformat/aadec.c --- ffmpeg-4.2.2/libavformat/aadec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/aadec.c 2021-04-08 21:28:40.000000000 +0000 @@ -72,8 +72,8 @@ static int aa_read_header(AVFormatContext *s) { int i, j, idx, largest_idx = -1; - uint32_t nkey, nval, toc_size, npairs, header_seed = 0, start; - char key[128], val[128], codec_name[64] = {0}; + uint32_t toc_size, npairs, header_seed = 0, start; + char codec_name[64] = {0}; uint8_t output[24], dst[8], src[8]; int64_t largest_size = -1, current_size = -1, chapter_pos; struct toc_entry { @@ -92,7 +92,7 @@ avio_skip(pb, 4); // magic string toc_size = avio_rb32(pb); // TOC size avio_skip(pb, 4); // unidentified integer - if (toc_size > MAX_TOC_ENTRIES) + if (toc_size > MAX_TOC_ENTRIES || toc_size < 2) return AVERROR_INVALIDDATA; for (i = 0; i < toc_size; i++) { // read TOC avio_skip(pb, 4); // TOC entry index @@ -104,8 +104,9 @@ if (npairs > MAX_DICTIONARY_ENTRIES) return AVERROR_INVALIDDATA; for (i = 0; i < npairs; i++) { - memset(val, 0, sizeof(val)); - memset(key, 0, sizeof(key)); + char key[128], val[128]; + uint32_t nkey, nval; + avio_skip(pb, 1); // unidentified integer nkey = avio_rb32(pb); // key string length nval = avio_rb32(pb); // value string length @@ -113,7 +114,7 @@ avio_get_str(pb, nval, val, sizeof(val)); if (!strcmp(key, "codec")) { av_log(s, AV_LOG_DEBUG, "Codec is <%s>\n", val); - strncpy(codec_name, val, sizeof(codec_name) - 1); + av_strlcpy(codec_name, val, sizeof(codec_name)); } else if (!strcmp(key, "HeaderSeed")) { av_log(s, AV_LOG_DEBUG, "HeaderSeed is <%s>\n", val); header_seed = atoi(val); @@ -221,14 +222,18 @@ c->content_end = start + largest_size; while ((chapter_pos = avio_tell(pb)) >= 0 && chapter_pos < c->content_end) { - int chapter_idx = s->nb_chapters; + unsigned chapter_idx = s->nb_chapters; uint32_t chapter_size = avio_rb32(pb); - if (chapter_size == 0) break; + if (chapter_size == 0 || avio_feof(pb)) + break; chapter_pos -= start + CHAPTER_HEADER_SIZE * chapter_idx; avio_skip(pb, 4 + chapter_size); if (!avpriv_new_chapter(s, chapter_idx, st->time_base, - chapter_pos * TIMEPREC, (chapter_pos + chapter_size) * TIMEPREC, NULL)) - return AVERROR(ENOMEM); + chapter_pos * TIMEPREC, + (chapter_pos + chapter_size) * TIMEPREC, NULL)) { + av_freep(&c->tea_ctx); + return AVERROR(ENOMEM); + } } st->duration = (largest_size - CHAPTER_HEADER_SIZE * s->nb_chapters) * TIMEPREC; diff -Nru ffmpeg-4.2.2/libavformat/aaxdec.c ffmpeg-4.4/libavformat/aaxdec.c --- ffmpeg-4.2.2/libavformat/aaxdec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/aaxdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,415 @@ +/* + * AAX demuxer + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "internal.h" + +typedef struct AAXColumn { + uint8_t flag; + uint8_t type; + const char *name; + uint32_t offset; + int size; +} AAXColumn; + +typedef struct AAXSegment { + int64_t start; + int64_t end; +} AAXSegment; + +typedef struct AAXContext { + int64_t table_size; + uint16_t version; + int64_t rows_offset; + int64_t strings_offset; + int64_t data_offset; + int64_t name_offset; + uint16_t columns; + uint16_t row_width; + uint32_t nb_segments; + int64_t schema_offset; + int64_t strings_size; + char *string_table; + + uint32_t current_segment; + + AAXColumn *xcolumns; + AAXSegment *segments; +} AAXContext; + +static int aax_probe(const AVProbeData *p) +{ + if (AV_RB32(p->buf) != MKBETAG('@','U','T','F')) + return 0; + if (AV_RB32(p->buf + 4) == 0) + return 0; + if (AV_RB16(p->buf + 8) > 1) + return 0; + if (AV_RB32(p->buf + 28) < 1) + return 0; + + return AVPROBE_SCORE_MAX; +} + +enum ColumnFlag { + COLUMN_FLAG_NAME = 0x1, + COLUMN_FLAG_DEFAULT = 0x2, + COLUMN_FLAG_ROW = 0x4, + COLUMN_FLAG_UNDEFINED = 0x8 /* shouldn't exist */ +}; + +enum ColumnType { + COLUMN_TYPE_UINT8 = 0x00, + COLUMN_TYPE_SINT8 = 0x01, + COLUMN_TYPE_UINT16 = 0x02, + COLUMN_TYPE_SINT16 = 0x03, + COLUMN_TYPE_UINT32 = 0x04, + COLUMN_TYPE_SINT32 = 0x05, + COLUMN_TYPE_UINT64 = 0x06, + COLUMN_TYPE_SINT64 = 0x07, + COLUMN_TYPE_FLOAT = 0x08, + COLUMN_TYPE_DOUBLE = 0x09, + COLUMN_TYPE_STRING = 0x0a, + COLUMN_TYPE_VLDATA = 0x0b, + COLUMN_TYPE_UINT128 = 0x0c, /* for GUIDs */ + COLUMN_TYPE_UNDEFINED = -1 +}; + +static int64_t get_pts(AVFormatContext *s, int64_t pos, int size) +{ + AAXContext *a = s->priv_data; + int64_t pts = 0; + + for (int seg = 0; seg < a->current_segment; seg++) + pts += (a->segments[seg].end - a->segments[seg].start) / size; + + pts += ((pos - a->segments[a->current_segment].start) / size); + + return pts; +} + +static int aax_read_header(AVFormatContext *s) +{ + AAXContext *a = s->priv_data; + AVIOContext *pb = s->pb; + AVCodecParameters *par; + AVStream *st; + int64_t column_offset = 0; + int ret, extradata_size; + char *codec; + + avio_skip(pb, 4); + a->table_size = avio_rb32(pb) + 8LL; + a->version = avio_rb16(pb); + a->rows_offset = avio_rb16(pb) + 8LL; + a->strings_offset = avio_rb32(pb) + 8LL; + a->data_offset = avio_rb32(pb) + 8LL; + a->name_offset = avio_rb32(pb); + a->columns = avio_rb16(pb); + a->row_width = avio_rb16(pb); + a->nb_segments = avio_rb32(pb); + + if (a->nb_segments < 1) + return AVERROR_INVALIDDATA; + + a->schema_offset = 0x20; + a->strings_size = a->data_offset - a->strings_offset; + + if (a->rows_offset > a->table_size || + a->strings_offset > a->table_size || + a->data_offset > a->table_size) + return AVERROR_INVALIDDATA; + if (a->strings_size <= 0 || a->name_offset >= a->strings_size || + a->strings_size > UINT16_MAX) + return AVERROR_INVALIDDATA; + if (a->columns <= 0) + return AVERROR_INVALIDDATA; + + a->segments = av_calloc(a->nb_segments, sizeof(*a->segments)); + if (!a->segments) + return AVERROR(ENOMEM); + + a->xcolumns = av_calloc(a->columns, sizeof(*a->xcolumns)); + if (!a->xcolumns) { + ret = AVERROR(ENOMEM); + goto fail; + } + + a->string_table = av_calloc(a->strings_size + 1, sizeof(*a->string_table)); + if (!a->string_table) { + ret = AVERROR(ENOMEM); + goto fail; + } + + for (int c = 0; c < a->columns; c++) { + uint8_t info = avio_r8(pb); + uint32_t offset = avio_rb32(pb); + int value_size; + + if (offset >= a->strings_size) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + a->xcolumns[c].flag = info >> 4; + a->xcolumns[c].type = info & 0x0F; + + switch (a->xcolumns[c].type) { + case COLUMN_TYPE_UINT8: + case COLUMN_TYPE_SINT8: + value_size = 0x01; + break; + case COLUMN_TYPE_UINT16: + case COLUMN_TYPE_SINT16: + value_size = 0x02; + break; + case COLUMN_TYPE_UINT32: + case COLUMN_TYPE_SINT32: + case COLUMN_TYPE_FLOAT: + case COLUMN_TYPE_STRING: + value_size = 0x04; + break; + case COLUMN_TYPE_VLDATA: + value_size = 0x08; + break; + case COLUMN_TYPE_UINT128: + value_size = 0x10; + break; + default: + ret = AVERROR_INVALIDDATA; + goto fail; + } + + a->xcolumns[c].size = value_size; + + if (a->xcolumns[c].flag & COLUMN_FLAG_NAME) + a->xcolumns[c].name = a->string_table + offset; + + if (a->xcolumns[c].flag & COLUMN_FLAG_DEFAULT) { + /* data is found relative to columns start */ + a->xcolumns[c].offset = avio_tell(pb) - a->schema_offset; + avio_skip(pb, value_size); + } + + if (a->xcolumns[c].flag & COLUMN_FLAG_ROW) { + /* data is found relative to row start */ + a->xcolumns[c].offset = column_offset; + column_offset += value_size; + } + } + + avio_seek(pb, a->strings_offset, SEEK_SET); + ret = avio_read(pb, a->string_table, a->strings_size); + if (ret != a->strings_size) { + if (ret < 0) + goto fail; + ret = AVERROR(EIO); + goto fail; + } + + for (int c = 0; c < a->columns; c++) { + int64_t data_offset = 0; + int64_t col_offset; + int flag, type; + + if (!a->xcolumns[c].name || strcmp(a->xcolumns[c].name, "data")) + continue; + + type = a->xcolumns[c].type; + flag = a->xcolumns[c].flag; + col_offset = a->xcolumns[c].offset; + + for (uint64_t r = 0; r < a->nb_segments; r++) { + if (flag & COLUMN_FLAG_DEFAULT) { + data_offset = a->schema_offset + col_offset; + } else if (flag & COLUMN_FLAG_ROW) { + data_offset = a->rows_offset + r * a->row_width + col_offset; + } else { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + avio_seek(pb, data_offset, SEEK_SET); + if (type == COLUMN_TYPE_VLDATA) { + int64_t start, size; + + start = avio_rb32(pb); + size = avio_rb32(pb); + a->segments[r].start = start + a->data_offset; + a->segments[r].end = a->segments[r].start + size; + } else { + ret = AVERROR_INVALIDDATA; + goto fail; + } + } + } + + if (!a->segments[0].end) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + st = avformat_new_stream(s, NULL); + if (!st) { + ret = AVERROR(ENOMEM); + goto fail; + } + st->start_time = 0; + par = s->streams[0]->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + + codec = a->string_table + a->name_offset; + if (!strcmp(codec, "AAX")) { + par->codec_id = AV_CODEC_ID_ADPCM_ADX; + avio_seek(pb, a->segments[0].start, SEEK_SET); + if (avio_rb16(pb) != 0x8000) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + extradata_size = avio_rb16(pb) + 4; + if (extradata_size < 12) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + avio_seek(pb, -4, SEEK_CUR); + ret = ff_get_extradata(s, par, pb, extradata_size); + if (ret < 0) { + goto fail; + } + par->channels = AV_RB8 (par->extradata + 7); + par->sample_rate = AV_RB32(par->extradata + 8); + if (!par->channels || !par->sample_rate) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + avpriv_set_pts_info(st, 64, 32, par->sample_rate); + /*} else if (!strcmp(codec, "HCA") ){ + par->codec_id = AV_CODEC_ID_HCA;*/ + } else { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + return 0; +fail: + av_freep(&a->string_table); + av_freep(&a->xcolumns); + av_freep(&a->segments); + + return ret; +} + +static int aax_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AAXContext *a = s->priv_data; + AVCodecParameters *par = s->streams[0]->codecpar; + AVIOContext *pb = s->pb; + const int size = 18 * par->channels; + int ret, extradata_size = 0; + uint8_t *extradata = NULL; + int skip = 0; + + if (avio_feof(pb)) + return AVERROR_EOF; + + pkt->pos = avio_tell(pb); + + for (uint32_t seg = 0; seg < a->nb_segments; seg++) { + int64_t start = a->segments[seg].start; + int64_t end = a->segments[seg].end; + + if (pkt->pos >= start && pkt->pos <= end) { + a->current_segment = seg; + if (par->codec_id == AV_CODEC_ID_ADPCM_ADX) + skip = (end - start) - ((end - start) / size) * size; + break; + } + } + + if (pkt->pos >= a->segments[a->current_segment].end - skip) { + if (a->current_segment + 1 == a->nb_segments) + return AVERROR_EOF; + a->current_segment++; + avio_seek(pb, a->segments[a->current_segment].start, SEEK_SET); + + if (par->codec_id == AV_CODEC_ID_ADPCM_ADX) { + if (avio_rb16(pb) != 0x8000) + return AVERROR_INVALIDDATA; + extradata_size = avio_rb16(pb) + 4; + avio_seek(pb, -4, SEEK_CUR); + if (extradata_size < 12) + return AVERROR_INVALIDDATA; + extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!extradata) + return AVERROR(ENOMEM); + if (avio_read(pb, extradata, extradata_size) != extradata_size) { + av_free(extradata); + return AVERROR(EIO); + } + memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + } + } + + ret = av_get_packet(pb, pkt, size); + if (ret != size) { + av_free(extradata); + return ret < 0 ? ret : AVERROR(EIO); + } + pkt->duration = 1; + pkt->stream_index = 0; + pkt->pts = get_pts(s, pkt->pos, size); + + if (extradata) { + ret = av_packet_add_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, extradata, extradata_size); + if (ret < 0) { + av_free(extradata); + return ret; + } + } + + return ret; +} + +static int aax_read_close(AVFormatContext *s) +{ + AAXContext *a = s->priv_data; + + av_freep(&a->segments); + av_freep(&a->xcolumns); + av_freep(&a->string_table); + + return 0; +} + +AVInputFormat ff_aax_demuxer = { + .name = "aax", + .long_name = NULL_IF_CONFIG_SMALL("CRI AAX"), + .priv_data_size = sizeof(AAXContext), + .read_probe = aax_probe, + .read_header = aax_read_header, + .read_packet = aax_read_packet, + .read_close = aax_read_close, + .extensions = "aax", + .flags = AVFMT_GENERIC_INDEX, +}; diff -Nru ffmpeg-4.2.2/libavformat/acedec.c ffmpeg-4.4/libavformat/acedec.c --- ffmpeg-4.2.2/libavformat/acedec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/acedec.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,114 @@ +/* + * ACE demuxer + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "internal.h" + +static int ace_probe(const AVProbeData *p) +{ + uint32_t asc; + + if (AV_RB32(p->buf) != MKBETAG('A','A','C',' ')) + return 0; + if (p->buf_size < 0x44) + return 0; + asc = AV_RB32(p->buf + 0x40); + if (asc < 0x44 || asc > p->buf_size - 4) + return 0; + if (AV_RB32(p->buf + asc) != MKBETAG('A','S','C',' ')) + return 0; + + return AVPROBE_SCORE_MAX / 2 + 1; +} + +static int ace_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + AVCodecParameters *par; + int ret, codec, rate, nb_channels; + uint32_t asc_pos, size; + AVStream *st; + + avio_skip(pb, 0x40); + asc_pos = avio_rb32(pb); + if (asc_pos < 0x44) + return AVERROR_INVALIDDATA; + avio_skip(pb, asc_pos - 0x44); + if (avio_rb32(pb) != MKBETAG('A','S','C',' ')) + return AVERROR_INVALIDDATA; + avio_skip(pb, 0xec); + codec = avio_rb32(pb); + nb_channels = avio_rb32(pb); + if (nb_channels <= 0 || nb_channels > 8) + return AVERROR_INVALIDDATA; + size = avio_rb32(pb); + if (size == 0) + return AVERROR_INVALIDDATA; + rate = avio_rb32(pb); + if (rate <= 0) + return AVERROR_INVALIDDATA; + avio_skip(pb, 16); + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + st->start_time = 0; + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->channels = nb_channels; + par->sample_rate = rate; + par->block_align = (codec == 4 ? 0x60 : codec == 5 ? 0x98 : 0xC0) * nb_channels; + st->duration = (size / par->block_align) * 1024LL; + par->codec_id = AV_CODEC_ID_ATRAC3; + + ret = ff_alloc_extradata(par, 14); + if (ret < 0) + return ret; + + AV_WL16(st->codecpar->extradata, 1); + AV_WL16(st->codecpar->extradata+2, 2048 * par->channels); + AV_WL16(st->codecpar->extradata+4, 0); + AV_WL16(st->codecpar->extradata+6, codec == 4 ? 1 : 0); + AV_WL16(st->codecpar->extradata+8, codec == 4 ? 1 : 0); + AV_WL16(st->codecpar->extradata+10, 1); + AV_WL16(st->codecpar->extradata+12, 0); + + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + + return 0; +} + +static int ace_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVCodecParameters *par = s->streams[0]->codecpar; + + return av_get_packet(s->pb, pkt, par->block_align); +} + +AVInputFormat ff_ace_demuxer = { + .name = "ace", + .long_name = NULL_IF_CONFIG_SMALL("tri-Ace Audio Container"), + .read_probe = ace_probe, + .read_header = ace_read_header, + .read_packet = ace_read_packet, + .flags = AVFMT_GENERIC_INDEX, +}; diff -Nru ffmpeg-4.2.2/libavformat/adp.c ffmpeg-4.4/libavformat/adp.c --- ffmpeg-4.2.2/libavformat/adp.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/adp.c 2021-04-08 21:28:40.000000000 +0000 @@ -75,14 +75,9 @@ return AVERROR_EOF; ret = av_get_packet(s->pb, pkt, size); + if (ret < 0) + return ret; - if (ret != size) { - if (ret < 0) { - av_packet_unref(pkt); - return ret; - } - av_shrink_packet(pkt, ret); - } pkt->stream_index = 0; return ret; diff -Nru ffmpeg-4.2.2/libavformat/ads.c ffmpeg-4.4/libavformat/ads.c --- ffmpeg-4.2.2/libavformat/ads.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ads.c 2021-02-20 20:27:47.000000000 +0000 @@ -34,8 +34,9 @@ static int ads_read_header(AVFormatContext *s) { - int align, codec, size; + int align, codec; AVStream *st; + int64_t size; st = avformat_new_stream(s, NULL); if (!st) @@ -62,7 +63,7 @@ st->codecpar->block_align = st->codecpar->channels * align; avio_skip(s->pb, 12); size = avio_rl32(s->pb); - if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_PSX) + if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_PSX && size >= 0x40) st->duration = (size - 0x40) / 16 / st->codecpar->channels * 28; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff -Nru ffmpeg-4.2.2/libavformat/adtsenc.c ffmpeg-4.4/libavformat/adtsenc.c --- ffmpeg-4.2.2/libavformat/adtsenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/adtsenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -40,6 +40,7 @@ int pce_size; int apetag; int id3v2tag; + int mpeg_id; uint8_t pce_data[MAX_PCE_SIZE]; } ADTSContext; @@ -53,7 +54,7 @@ int off; init_get_bits(&gb, buf, size * 8); - off = avpriv_mpeg4audio_get_config(&m4ac, buf, size * 8, 1); + off = avpriv_mpeg4audio_get_config2(&m4ac, buf, size, 1, s); if (off < 0) return off; skip_bits_long(&gb, off); @@ -136,7 +137,7 @@ /* adts_fixed_header */ put_bits(&pb, 12, 0xfff); /* syncword */ - put_bits(&pb, 1, 0); /* ID */ + put_bits(&pb, 1, ctx->mpeg_id); /* ID */ put_bits(&pb, 2, 0); /* layer */ put_bits(&pb, 1, 1); /* protection_absent */ put_bits(&pb, 2, ctx->objecttype); /* profile_objecttype */ @@ -169,7 +170,8 @@ return 0; if (!par->extradata_size) { uint8_t *side_data; - int side_data_size = 0, ret; + buffer_size_t side_data_size; + int ret; side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_data_size); @@ -214,6 +216,7 @@ static const AVOption options[] = { { "write_id3v2", "Enable ID3v2 tag writing", OFFSET(id3v2tag), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, ENC}, { "write_apetag", "Enable APE tag writing", OFFSET(apetag), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, ENC}, + { "write_mpeg2", "Use MPE2 ID when writing", OFFSET(mpeg_id), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, ENC, "mpeg_id"}, { NULL }, }; diff -Nru ffmpeg-4.2.2/libavformat/adxdec.c ffmpeg-4.4/libavformat/adxdec.c --- ffmpeg-4.2.2/libavformat/adxdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/adxdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -53,6 +53,9 @@ AVCodecParameters *par = s->streams[0]->codecpar; int ret, size; + if (avio_feof(s->pb)) + return AVERROR_EOF; + if (par->channels <= 0) { av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", par->channels); return AVERROR_INVALIDDATA; @@ -63,18 +66,21 @@ pkt->pos = avio_tell(s->pb); pkt->stream_index = 0; - ret = av_get_packet(s->pb, pkt, size); - if (ret != size) { - av_packet_unref(pkt); - return ret < 0 ? ret : AVERROR(EIO); - } - if (AV_RB16(pkt->data) & 0x8000) { - av_packet_unref(pkt); - return AVERROR_EOF; + ret = av_get_packet(s->pb, pkt, size * 128); + if (ret < 0) + return ret; + if ((ret % size) && ret >= size) { + size = ret - (ret % size); + av_shrink_packet(pkt, size); + pkt->flags &= ~AV_PKT_FLAG_CORRUPT; + } else if (ret < size) { + return AVERROR(EIO); + } else { + size = ret; } - pkt->size = size; - pkt->duration = 1; - pkt->pts = (pkt->pos - c->header_size) / size; + + pkt->duration = size / (BLOCK_SIZE * par->channels); + pkt->pts = (pkt->pos - c->header_size) / (BLOCK_SIZE * par->channels); return 0; } @@ -83,7 +89,7 @@ { ADXDemuxerContext *c = s->priv_data; AVCodecParameters *par; - + int ret; AVStream *st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); @@ -94,8 +100,8 @@ c->header_size = avio_rb16(s->pb) + 4; avio_seek(s->pb, -4, SEEK_CUR); - if (ff_get_extradata(s, par, s->pb, c->header_size) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_get_extradata(s, par, s->pb, c->header_size)) < 0) + return ret; if (par->extradata_size < 12) { av_log(s, AV_LOG_ERROR, "Invalid extradata size.\n"); diff -Nru ffmpeg-4.2.2/libavformat/afc.c ffmpeg-4.4/libavformat/afc.c --- ffmpeg-4.2.2/libavformat/afc.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/afc.c 2020-07-11 10:39:30.000000000 +0000 @@ -31,6 +31,7 @@ { AFCDemuxContext *c = s->priv_data; AVStream *st; + int ret; st = avformat_new_stream(s, NULL); if (!st) @@ -40,8 +41,8 @@ st->codecpar->channels = 2; st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; - if (ff_alloc_extradata(st->codecpar, 1)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 1)) < 0) + return ret; st->codecpar->extradata[0] = 8 * st->codecpar->channels; c->data_end = avio_rb32(s->pb) + 32LL; diff -Nru ffmpeg-4.2.2/libavformat/aiff.c ffmpeg-4.4/libavformat/aiff.c --- ffmpeg-4.2.2/libavformat/aiff.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/aiff.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * AIFF/AIFF-C muxer/demuxer common data + * Copyright (c) 2006 Patrick Guimond + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "libavcodec/codec_id.h" +#include "internal.h" + +const AVCodecTag ff_codec_aiff_tags[] = { + { AV_CODEC_ID_PCM_S16BE, MKTAG('N','O','N','E') }, + { AV_CODEC_ID_PCM_S8, MKTAG('N','O','N','E') }, + { AV_CODEC_ID_PCM_U8, MKTAG('r','a','w',' ') }, + { AV_CODEC_ID_PCM_S24BE, MKTAG('N','O','N','E') }, + { AV_CODEC_ID_PCM_S32BE, MKTAG('N','O','N','E') }, + { AV_CODEC_ID_PCM_F32BE, MKTAG('f','l','3','2') }, + { AV_CODEC_ID_PCM_F64BE, MKTAG('f','l','6','4') }, + { AV_CODEC_ID_PCM_ALAW, MKTAG('a','l','a','w') }, + { AV_CODEC_ID_PCM_MULAW, MKTAG('u','l','a','w') }, + { AV_CODEC_ID_PCM_S24BE, MKTAG('i','n','2','4') }, + { AV_CODEC_ID_PCM_S32BE, MKTAG('i','n','3','2') }, + { AV_CODEC_ID_MACE3, MKTAG('M','A','C','3') }, + { AV_CODEC_ID_MACE6, MKTAG('M','A','C','6') }, + { AV_CODEC_ID_GSM, MKTAG('G','S','M',' ') }, + { AV_CODEC_ID_ADPCM_G722, MKTAG('G','7','2','2') }, + { AV_CODEC_ID_ADPCM_G726LE, MKTAG('G','7','2','6') }, + { AV_CODEC_ID_PCM_S16BE, MKTAG('t','w','o','s') }, + { AV_CODEC_ID_PCM_S16LE, MKTAG('s','o','w','t') }, + { AV_CODEC_ID_ADPCM_IMA_QT, MKTAG('i','m','a','4') }, + { AV_CODEC_ID_QDMC, MKTAG('Q','D','M','C') }, + { AV_CODEC_ID_QDM2, MKTAG('Q','D','M','2') }, + { AV_CODEC_ID_QCELP, MKTAG('Q','c','l','p') }, + { AV_CODEC_ID_SDX2_DPCM, MKTAG('S','D','X','2') }, + { AV_CODEC_ID_ADPCM_IMA_WS, MKTAG('A','D','P','4') }, + { AV_CODEC_ID_NONE, 0 }, +}; + +const AVCodecTag *const ff_aiff_codec_tags_list[] = { ff_codec_aiff_tags, NULL }; diff -Nru ffmpeg-4.2.2/libavformat/aiffdec.c ffmpeg-4.4/libavformat/aiffdec.c --- ffmpeg-4.2.2/libavformat/aiffdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/aiffdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -20,15 +20,14 @@ */ #include "libavutil/intreadwrite.h" -#include "libavutil/mathematics.h" #include "libavutil/dict.h" #include "avformat.h" #include "internal.h" #include "pcm.h" #include "aiff.h" -#include "isom.h" #include "id3v2.h" #include "mov_chan.h" +#include "replaygain.h" #define AIFF 0 #define AIFF_C_VERSION1 0xA2805140 @@ -119,6 +118,8 @@ else sample_rate = (val + (1ULL<<(-exp-1))) >> -exp; par->sample_rate = sample_rate; + if (size < 18) + return AVERROR_INVALIDDATA; size -= 18; /* get codec id for AIFF-C */ @@ -242,7 +243,10 @@ if (size < 0) return size; - filesize -= size + 8; + if (size >= 0x7fffffff - 8) + filesize = 0; + else + filesize -= size + 8; switch (tag) { case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */ @@ -257,8 +261,8 @@ position = avio_tell(pb); ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size); if (id3v2_extra_meta) - if ((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0 || - (ret = ff_id3v2_parse_chapters(s, &id3v2_extra_meta)) < 0) { + if ((ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0 || + (ret = ff_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0) { ff_id3v2_free_extra_meta(&id3v2_extra_meta); return ret; } @@ -282,6 +286,8 @@ get_meta(s, "comment" , size); break; case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */ + if (size < 8) + return AVERROR_INVALIDDATA; aiff->data_end = avio_tell(pb) + size; offset = avio_rb32(pb); /* Offset of sound data */ avio_rb32(pb); /* BlockSize... don't care */ @@ -297,8 +303,8 @@ case MKTAG('w', 'a', 'v', 'e'): if ((uint64_t)size > (1<<30)) return -1; - if (ff_get_extradata(s, st->codecpar, pb, size) < 0) - return AVERROR(ENOMEM); + 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) && size>=12*4 && !st->codecpar->block_align) { st->codecpar->block_align = AV_RB32(st->codecpar->extradata+11*4); @@ -321,8 +327,8 @@ } break; case MKTAG('C','H','A','N'): - if(ff_mov_read_chan(s, pb, st, size) < 0) - return AVERROR_INVALIDDATA; + if ((ret = ff_mov_read_chan(s, pb, st, size)) < 0) + return ret; break; case MKTAG('A','P','C','M'): /* XA ADPCM compressed sound chunk */ st->codecpar->codec_id = AV_CODEC_ID_ADPCM_XA; @@ -348,6 +354,10 @@ } } + ret = ff_replaygain_export(st, s->metadata); + if (ret < 0) + return ret; + 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"); @@ -398,6 +408,8 @@ break; default: size = st->codecpar->block_align ? (MAX_SIZE / st->codecpar->block_align) * st->codecpar->block_align : MAX_SIZE; + if (!size) + return AVERROR_INVALIDDATA; } size = FFMIN(max_size, size); res = av_get_packet(s->pb, pkt, size); @@ -420,5 +432,5 @@ .read_header = aiff_read_header, .read_packet = aiff_read_packet, .read_seek = ff_pcm_read_seek, - .codec_tag = (const AVCodecTag* const []){ ff_codec_aiff_tags, 0 }, + .codec_tag = ff_aiff_codec_tags_list, }; diff -Nru ffmpeg-4.2.2/libavformat/aiffenc.c ffmpeg-4.4/libavformat/aiffenc.c --- ffmpeg-4.2.2/libavformat/aiffenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavformat/aiffenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/intfloat.h" #include "libavutil/opt.h" +#include "libavcodec/packet_internal.h" #include "avformat.h" #include "internal.h" #include "aiff.h" @@ -36,7 +37,7 @@ int64_t frames; int64_t ssnd; int audio_stream_idx; - AVPacketList *pict_list; + PacketList *pict_list, *pict_list_end; int write_id3v2; int id3v2_version; } AIFFOutputContext; @@ -47,12 +48,9 @@ uint64_t pos, end, size; ID3v2EncContext id3v2 = { 0 }; AVIOContext *pb = s->pb; - AVPacketList *pict_list = aiff->pict_list; + PacketList *pict_list = aiff->pict_list; - if (!pb->seekable & AVIO_SEEKABLE_NORMAL) - return 0; - - if (!s->metadata && !aiff->pict_list) + if (!s->metadata && !s->nb_chapters && !aiff->pict_list) return 0; avio_wl32(pb, MKTAG('I', 'D', '3', ' ')); @@ -125,7 +123,7 @@ /* First verify if format is ok */ if (!par->codec_tag) - return -1; + return AVERROR(EINVAL); if (par->codec_tag != MKTAG('N','O','N','E')) aifc = 1; @@ -138,7 +136,7 @@ if (aifc) { // compressed audio if (!par->block_align) { av_log(s, AV_LOG_ERROR, "block align not set\n"); - return -1; + return AVERROR(EINVAL); } /* Version chunk */ ffio_wfourcc(pb, "FVER"); @@ -169,7 +167,7 @@ par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id); if (!par->bits_per_coded_sample) { av_log(s, AV_LOG_ERROR, "could not compute bits per sample\n"); - return -1; + return AVERROR(EINVAL); } if (!par->block_align) par->block_align = (par->bits_per_coded_sample * par->channels) >> 3; @@ -202,9 +200,6 @@ avpriv_set_pts_info(s->streams[aiff->audio_stream_idx], 64, 1, s->streams[aiff->audio_stream_idx]->codecpar->sample_rate); - /* Data is starting here */ - avio_flush(pb); - return 0; } @@ -215,9 +210,6 @@ if (pkt->stream_index == aiff->audio_stream_idx) avio_write(pb, pkt->data, pkt->size); else { - int ret; - AVPacketList *pict_list, *last; - if (s->streams[pkt->stream_index]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) return 0; @@ -229,24 +221,8 @@ if (s->streams[pkt->stream_index]->nb_frames >= 1) return 0; - pict_list = av_mallocz(sizeof(AVPacketList)); - if (!pict_list) - return AVERROR(ENOMEM); - - ret = av_packet_ref(&pict_list->pkt, pkt); - if (ret < 0) { - av_freep(&pict_list); - return ret; - } - - if (!aiff->pict_list) - aiff->pict_list = pict_list; - else { - last = aiff->pict_list; - while (last->next) - last = last->next; - last->next = pict_list; - } + return avpriv_packet_list_put(&aiff->pict_list, &aiff->pict_list_end, + pkt, av_packet_ref, 0); } return 0; @@ -254,10 +230,9 @@ static int aiff_write_trailer(AVFormatContext *s) { - int ret; + int ret = 0; AVIOContext *pb = s->pb; AIFFOutputContext *aiff = s->priv_data; - AVPacketList *pict_list = aiff->pict_list; AVCodecParameters *par = s->streams[aiff->audio_stream_idx]->codecpar; /* Chunks sizes must be even */ @@ -289,18 +264,16 @@ file_size = avio_tell(pb); avio_seek(pb, aiff->form, SEEK_SET); avio_wb32(pb, file_size - aiff->form - 4); - - avio_flush(pb); } - while (pict_list) { - AVPacketList *next = pict_list->next; - av_packet_unref(&pict_list->pkt); - av_freep(&pict_list); - pict_list = next; - } + return ret; +} - return 0; +static void aiff_deinit(AVFormatContext *s) +{ + AIFFOutputContext *aiff = s->priv_data; + + avpriv_packet_list_free(&aiff->pict_list, &aiff->pict_list_end); } #define OFFSET(x) offsetof(AIFFOutputContext, x) @@ -331,6 +304,7 @@ .write_header = aiff_write_header, .write_packet = aiff_write_packet, .write_trailer = aiff_write_trailer, - .codec_tag = (const AVCodecTag* const []){ ff_codec_aiff_tags, 0 }, + .deinit = aiff_deinit, + .codec_tag = ff_aiff_codec_tags_list, .priv_class = &aiff_muxer_class, }; diff -Nru ffmpeg-4.2.2/libavformat/aiff.h ffmpeg-4.4/libavformat/aiff.h --- ffmpeg-4.2.2/libavformat/aiff.h 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/aiff.h 2021-04-08 21:28:40.000000000 +0000 @@ -27,35 +27,9 @@ #ifndef AVFORMAT_AIFF_H #define AVFORMAT_AIFF_H -#include "avformat.h" #include "internal.h" -static const AVCodecTag ff_codec_aiff_tags[] = { - { AV_CODEC_ID_PCM_S16BE, MKTAG('N','O','N','E') }, - { AV_CODEC_ID_PCM_S8, MKTAG('N','O','N','E') }, - { AV_CODEC_ID_PCM_U8, MKTAG('r','a','w',' ') }, - { AV_CODEC_ID_PCM_S24BE, MKTAG('N','O','N','E') }, - { AV_CODEC_ID_PCM_S32BE, MKTAG('N','O','N','E') }, - { AV_CODEC_ID_PCM_F32BE, MKTAG('f','l','3','2') }, - { AV_CODEC_ID_PCM_F64BE, MKTAG('f','l','6','4') }, - { AV_CODEC_ID_PCM_ALAW, MKTAG('a','l','a','w') }, - { AV_CODEC_ID_PCM_MULAW, MKTAG('u','l','a','w') }, - { AV_CODEC_ID_PCM_S24BE, MKTAG('i','n','2','4') }, - { AV_CODEC_ID_PCM_S32BE, MKTAG('i','n','3','2') }, - { AV_CODEC_ID_MACE3, MKTAG('M','A','C','3') }, - { AV_CODEC_ID_MACE6, MKTAG('M','A','C','6') }, - { AV_CODEC_ID_GSM, MKTAG('G','S','M',' ') }, - { AV_CODEC_ID_ADPCM_G722, MKTAG('G','7','2','2') }, - { AV_CODEC_ID_ADPCM_G726LE, MKTAG('G','7','2','6') }, - { AV_CODEC_ID_PCM_S16BE, MKTAG('t','w','o','s') }, - { AV_CODEC_ID_PCM_S16LE, MKTAG('s','o','w','t') }, - { AV_CODEC_ID_ADPCM_IMA_QT, MKTAG('i','m','a','4') }, - { AV_CODEC_ID_QDMC, MKTAG('Q','D','M','C') }, - { AV_CODEC_ID_QDM2, MKTAG('Q','D','M','2') }, - { AV_CODEC_ID_QCELP, MKTAG('Q','c','l','p') }, - { AV_CODEC_ID_SDX2_DPCM, MKTAG('S','D','X','2') }, - { AV_CODEC_ID_ADPCM_IMA_WS, MKTAG('A','D','P','4') }, - { AV_CODEC_ID_NONE, 0 }, -}; +extern const AVCodecTag ff_codec_aiff_tags[]; +extern const AVCodecTag *const ff_aiff_codec_tags_list[]; #endif /* AVFORMAT_AIFF_H */ diff -Nru ffmpeg-4.2.2/libavformat/allformats.c ffmpeg-4.4/libavformat/allformats.c --- ffmpeg-4.2.2/libavformat/allformats.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/allformats.c 2021-04-08 21:28:40.000000000 +0000 @@ -31,8 +31,10 @@ extern AVOutputFormat ff_a64_muxer; extern AVInputFormat ff_aa_demuxer; extern AVInputFormat ff_aac_demuxer; +extern AVInputFormat ff_aax_demuxer; extern AVInputFormat ff_ac3_demuxer; extern AVOutputFormat ff_ac3_muxer; +extern AVInputFormat ff_ace_demuxer; extern AVInputFormat ff_acm_demuxer; extern AVInputFormat ff_act_demuxer; extern AVInputFormat ff_adf_demuxer; @@ -46,13 +48,18 @@ extern AVInputFormat ff_aiff_demuxer; extern AVOutputFormat ff_aiff_muxer; extern AVInputFormat ff_aix_demuxer; +extern AVInputFormat ff_alp_demuxer; +extern AVOutputFormat ff_alp_muxer; extern AVInputFormat ff_amr_demuxer; extern AVOutputFormat ff_amr_muxer; extern AVInputFormat ff_amrnb_demuxer; extern AVInputFormat ff_amrwb_demuxer; +extern AVOutputFormat ff_amv_muxer; extern AVInputFormat ff_anm_demuxer; extern AVInputFormat ff_apc_demuxer; extern AVInputFormat ff_ape_demuxer; +extern AVInputFormat ff_apm_demuxer; +extern AVOutputFormat ff_apm_muxer; extern AVInputFormat ff_apng_demuxer; extern AVOutputFormat ff_apng_muxer; extern AVInputFormat ff_aptx_demuxer; @@ -60,6 +67,9 @@ extern AVInputFormat ff_aptx_hd_demuxer; extern AVOutputFormat ff_aptx_hd_muxer; extern AVInputFormat ff_aqtitle_demuxer; +extern AVInputFormat ff_argo_asf_demuxer; +extern AVOutputFormat ff_argo_asf_muxer; +extern AVInputFormat ff_argo_brp_demuxer; extern AVInputFormat ff_asf_demuxer; extern AVOutputFormat ff_asf_muxer; extern AVInputFormat ff_asf_o_demuxer; @@ -70,6 +80,7 @@ extern AVOutputFormat ff_asf_stream_muxer; extern AVInputFormat ff_au_demuxer; extern AVOutputFormat ff_au_muxer; +extern AVInputFormat ff_av1_demuxer; extern AVInputFormat ff_avi_demuxer; extern AVOutputFormat ff_avi_muxer; extern AVInputFormat ff_avisynth_demuxer; @@ -78,10 +89,12 @@ extern AVInputFormat ff_avs_demuxer; extern AVInputFormat ff_avs2_demuxer; extern AVOutputFormat ff_avs2_muxer; +extern AVInputFormat ff_avs3_demuxer; extern AVInputFormat ff_bethsoftvid_demuxer; extern AVInputFormat ff_bfi_demuxer; extern AVInputFormat ff_bintext_demuxer; extern AVInputFormat ff_bink_demuxer; +extern AVInputFormat ff_binka_demuxer; extern AVInputFormat ff_bit_demuxer; extern AVOutputFormat ff_bit_muxer; extern AVInputFormat ff_bmv_demuxer; @@ -109,6 +122,7 @@ extern AVInputFormat ff_daud_demuxer; extern AVOutputFormat ff_daud_muxer; extern AVInputFormat ff_dcstr_demuxer; +extern AVInputFormat ff_derf_demuxer; extern AVInputFormat ff_dfa_demuxer; extern AVInputFormat ff_dhav_demuxer; extern AVInputFormat ff_dirac_demuxer; @@ -152,6 +166,7 @@ extern AVOutputFormat ff_framemd5_muxer; extern AVInputFormat ff_frm_demuxer; extern AVInputFormat ff_fsb_demuxer; +extern AVInputFormat ff_fwse_demuxer; extern AVInputFormat ff_g722_demuxer; extern AVOutputFormat ff_g722_muxer; extern AVInputFormat ff_g723_1_demuxer; @@ -176,6 +191,7 @@ extern AVInputFormat ff_h264_demuxer; extern AVOutputFormat ff_h264_muxer; extern AVOutputFormat ff_hash_muxer; +extern AVInputFormat ff_hca_demuxer; extern AVInputFormat ff_hcom_demuxer; extern AVOutputFormat ff_hds_muxer; extern AVInputFormat ff_hevc_demuxer; @@ -200,6 +216,7 @@ extern AVInputFormat ff_ingenient_demuxer; extern AVInputFormat ff_ipmovie_demuxer; extern AVOutputFormat ff_ipod_muxer; +extern AVInputFormat ff_ipu_demuxer; extern AVInputFormat ff_ircam_demuxer; extern AVOutputFormat ff_ircam_muxer; extern AVOutputFormat ff_ismv_muxer; @@ -212,15 +229,20 @@ extern AVOutputFormat ff_jacosub_muxer; extern AVInputFormat ff_jv_demuxer; extern AVInputFormat ff_kux_demuxer; +extern AVInputFormat ff_kvag_demuxer; +extern AVOutputFormat ff_kvag_muxer; extern AVOutputFormat ff_latm_muxer; extern AVInputFormat ff_lmlm4_demuxer; extern AVInputFormat ff_loas_demuxer; +extern AVInputFormat ff_luodat_demuxer; extern AVInputFormat ff_lrc_demuxer; extern AVOutputFormat ff_lrc_muxer; extern AVInputFormat ff_lvf_demuxer; extern AVInputFormat ff_lxf_demuxer; extern AVInputFormat ff_m4v_demuxer; extern AVOutputFormat ff_m4v_muxer; +extern AVInputFormat ff_mca_demuxer; +extern AVInputFormat ff_mcc_demuxer; extern AVOutputFormat ff_md5_muxer; extern AVInputFormat ff_matroska_demuxer; extern AVOutputFormat ff_matroska_muxer; @@ -237,6 +259,8 @@ extern AVInputFormat ff_mm_demuxer; extern AVInputFormat ff_mmf_demuxer; extern AVOutputFormat ff_mmf_muxer; +extern AVInputFormat ff_mods_demuxer; +extern AVInputFormat ff_moflex_demuxer; extern AVInputFormat ff_mov_demuxer; extern AVOutputFormat ff_mov_muxer; extern AVOutputFormat ff_mp2_muxer; @@ -263,6 +287,7 @@ extern AVInputFormat ff_mpsub_demuxer; extern AVInputFormat ff_msf_demuxer; extern AVInputFormat ff_msnwc_tcp_demuxer; +extern AVInputFormat ff_msp_demuxer; extern AVInputFormat ff_mtaf_demuxer; extern AVInputFormat ff_mtv_demuxer; extern AVInputFormat ff_musx_demuxer; @@ -281,6 +306,7 @@ extern AVInputFormat ff_nut_demuxer; extern AVOutputFormat ff_nut_muxer; extern AVInputFormat ff_nuv_demuxer; +extern AVInputFormat ff_obu_demuxer; extern AVOutputFormat ff_oga_muxer; extern AVInputFormat ff_ogg_demuxer; extern AVOutputFormat ff_ogg_muxer; @@ -333,6 +359,7 @@ extern AVOutputFormat ff_pcm_u8_muxer; extern AVInputFormat ff_pjs_demuxer; extern AVInputFormat ff_pmp_demuxer; +extern AVInputFormat ff_pp_bnk_demuxer; extern AVOutputFormat ff_psp_muxer; extern AVInputFormat ff_pva_demuxer; extern AVInputFormat ff_pvf_demuxer; @@ -374,8 +401,10 @@ extern AVOutputFormat ff_segment_muxer; extern AVOutputFormat ff_stream_segment_muxer; extern AVInputFormat ff_ser_demuxer; +extern AVInputFormat ff_sga_demuxer; extern AVInputFormat ff_shorten_demuxer; extern AVInputFormat ff_siff_demuxer; +extern AVInputFormat ff_simbiosis_imx_demuxer; extern AVOutputFormat ff_singlejpeg_muxer; extern AVInputFormat ff_sln_demuxer; extern AVInputFormat ff_smacker_demuxer; @@ -393,11 +422,13 @@ extern AVOutputFormat ff_srt_muxer; extern AVInputFormat ff_str_demuxer; extern AVInputFormat ff_stl_demuxer; +extern AVOutputFormat ff_streamhash_muxer; extern AVInputFormat ff_subviewer1_demuxer; extern AVInputFormat ff_subviewer_demuxer; extern AVInputFormat ff_sup_demuxer; extern AVOutputFormat ff_sup_muxer; extern AVInputFormat ff_svag_demuxer; +extern AVInputFormat ff_svs_demuxer; extern AVInputFormat ff_swf_demuxer; extern AVOutputFormat ff_swf_muxer; extern AVInputFormat ff_tak_demuxer; @@ -414,6 +445,7 @@ extern AVOutputFormat ff_truehd_muxer; extern AVInputFormat ff_tta_demuxer; extern AVOutputFormat ff_tta_muxer; +extern AVOutputFormat ff_ttml_muxer; extern AVInputFormat ff_txd_demuxer; extern AVInputFormat ff_tty_demuxer; extern AVInputFormat ff_ty_demuxer; @@ -464,6 +496,7 @@ extern AVOutputFormat ff_yuv4mpegpipe_muxer; /* image demuxers */ extern AVInputFormat ff_image_bmp_pipe_demuxer; +extern AVInputFormat ff_image_cri_pipe_demuxer; extern AVInputFormat ff_image_dds_pipe_demuxer; extern AVInputFormat ff_image_dpx_pipe_demuxer; extern AVInputFormat ff_image_exr_pipe_demuxer; @@ -476,6 +509,8 @@ extern AVInputFormat ff_image_pcx_pipe_demuxer; extern AVInputFormat ff_image_pgmyuv_pipe_demuxer; extern AVInputFormat ff_image_pgm_pipe_demuxer; +extern AVInputFormat ff_image_pgx_pipe_demuxer; +extern AVInputFormat ff_image_photocd_pipe_demuxer; extern AVInputFormat ff_image_pictor_pipe_demuxer; extern AVInputFormat ff_image_png_pipe_demuxer; extern AVInputFormat ff_image_ppm_pipe_demuxer; @@ -486,6 +521,7 @@ extern AVInputFormat ff_image_sunrast_pipe_demuxer; extern AVInputFormat ff_image_tiff_pipe_demuxer; extern AVInputFormat ff_image_webp_pipe_demuxer; +extern AVInputFormat ff_image_xbm_pipe_demuxer; extern AVInputFormat ff_image_xpm_pipe_demuxer; extern AVInputFormat ff_image_xwd_pipe_demuxer; @@ -510,7 +546,7 @@ if (i < size) { f = muxer_list[i]; - } else if (indev_list) { + } else if (outdev_list) { f = outdev_list[i - size]; } @@ -527,7 +563,7 @@ if (i < size) { f = demuxer_list[i]; - } else if (outdev_list) { + } else if (indev_list) { f = indev_list[i - size]; } diff -Nru ffmpeg-4.2.2/libavformat/alp.c ffmpeg-4.4/libavformat/alp.c --- ffmpeg-4.2.2/libavformat/alp.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/alp.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,306 @@ +/* + * LEGO Racers ALP (.tun & .pcm) (de)muxer + * + * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.com) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "avformat.h" +#include "internal.h" +#include "rawenc.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/internal.h" +#include "libavutil/opt.h" + +#define ALP_TAG MKTAG('A', 'L', 'P', ' ') +#define ALP_MAX_READ_SIZE 4096 + +typedef struct ALPHeader { + uint32_t magic; /*< Magic Number, {'A', 'L', 'P', ' '} */ + uint32_t header_size; /*< Header size (after this). */ + char adpcm[6]; /*< "ADPCM" */ + uint8_t unk1; /*< Unknown */ + uint8_t num_channels; /*< Channel Count. */ + uint32_t sample_rate; /*< Sample rate, only if header_size >= 12. */ +} ALPHeader; + +typedef enum ALPType { + ALP_TYPE_AUTO = 0, /*< Autodetect based on file extension. */ + ALP_TYPE_TUN = 1, /*< Force a .TUN file. */ + ALP_TYPE_PCM = 2, /*< Force a .PCM file. */ +} ALPType; + +typedef struct ALPMuxContext { + const AVClass *class; + ALPType type; +} ALPMuxContext; + +#if CONFIG_ALP_DEMUXER +static int alp_probe(const AVProbeData *p) +{ + uint32_t i; + + if (AV_RL32(p->buf) != ALP_TAG) + return 0; + + /* Only allowed header sizes are 8 and 12. */ + i = AV_RL32(p->buf + 4); + if (i != 8 && i != 12) + return 0; + + if (strncmp("ADPCM", p->buf + 8, 6) != 0) + return 0; + + return AVPROBE_SCORE_MAX - 1; +} + +static int alp_read_header(AVFormatContext *s) +{ + int ret; + AVStream *st; + ALPHeader *hdr = s->priv_data; + AVCodecParameters *par; + + if ((hdr->magic = avio_rl32(s->pb)) != ALP_TAG) + return AVERROR_INVALIDDATA; + + hdr->header_size = avio_rl32(s->pb); + + if (hdr->header_size != 8 && hdr->header_size != 12) { + return AVERROR_INVALIDDATA; + } + + if ((ret = avio_read(s->pb, hdr->adpcm, sizeof(hdr->adpcm))) < 0) + return ret; + else if (ret != sizeof(hdr->adpcm)) + return AVERROR(EIO); + + if (strncmp("ADPCM", hdr->adpcm, sizeof(hdr->adpcm)) != 0) + return AVERROR_INVALIDDATA; + + hdr->unk1 = avio_r8(s->pb); + hdr->num_channels = avio_r8(s->pb); + + if (hdr->header_size == 8) { + /* .TUN music file */ + hdr->sample_rate = 22050; + + } else { + /* .PCM sound file */ + hdr->sample_rate = avio_rl32(s->pb); + } + + if (hdr->sample_rate > 44100) { + avpriv_request_sample(s, "Sample Rate > 44100"); + return AVERROR_PATCHWELCOME; + } + + if (!(st = avformat_new_stream(s, NULL))) + return AVERROR(ENOMEM); + + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = AV_CODEC_ID_ADPCM_IMA_ALP; + par->format = AV_SAMPLE_FMT_S16; + par->sample_rate = hdr->sample_rate; + par->channels = hdr->num_channels; + + if (hdr->num_channels == 1) + par->channel_layout = AV_CH_LAYOUT_MONO; + else if (hdr->num_channels == 2) + par->channel_layout = AV_CH_LAYOUT_STEREO; + else + return AVERROR_INVALIDDATA; + + par->bits_per_coded_sample = 4; + par->bits_per_raw_sample = 16; + par->block_align = 1; + par->bit_rate = par->channels * + par->sample_rate * + par->bits_per_coded_sample; + + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + return 0; +} + +static int alp_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + int ret; + AVCodecParameters *par = s->streams[0]->codecpar; + + if ((ret = av_get_packet(s->pb, pkt, ALP_MAX_READ_SIZE)) < 0) + return ret; + + pkt->flags &= ~AV_PKT_FLAG_CORRUPT; + pkt->stream_index = 0; + pkt->duration = ret * 2 / par->channels; + + return 0; +} + +static int alp_seek(AVFormatContext *s, int stream_index, + int64_t pts, int flags) +{ + const ALPHeader *hdr = s->priv_data; + + if (pts != 0) + return AVERROR(EINVAL); + + return avio_seek(s->pb, hdr->header_size + 8, SEEK_SET); +} + +AVInputFormat ff_alp_demuxer = { + .name = "alp", + .long_name = NULL_IF_CONFIG_SMALL("LEGO Racers ALP"), + .priv_data_size = sizeof(ALPHeader), + .read_probe = alp_probe, + .read_header = alp_read_header, + .read_packet = alp_read_packet, + .read_seek = alp_seek, +}; +#endif + +#if CONFIG_ALP_MUXER + +static int alp_write_init(AVFormatContext *s) +{ + ALPMuxContext *alp = s->priv_data; + AVCodecParameters *par; + + if (alp->type == ALP_TYPE_AUTO) { + if (av_match_ext(s->url, "pcm")) + alp->type = ALP_TYPE_PCM; + else + alp->type = ALP_TYPE_TUN; + } + + if (s->nb_streams != 1) { + av_log(s, AV_LOG_ERROR, "Too many streams\n"); + return AVERROR(EINVAL); + } + + par = s->streams[0]->codecpar; + + if (par->codec_id != AV_CODEC_ID_ADPCM_IMA_ALP) { + av_log(s, AV_LOG_ERROR, "%s codec not supported\n", + avcodec_get_name(par->codec_id)); + return AVERROR(EINVAL); + } + + if (par->channels > 2) { + av_log(s, AV_LOG_ERROR, "A maximum of 2 channels are supported\n"); + return AVERROR(EINVAL); + } + + if (par->sample_rate > 44100) { + av_log(s, AV_LOG_ERROR, "Sample rate too large\n"); + return AVERROR(EINVAL); + } + + if (alp->type == ALP_TYPE_TUN && par->sample_rate != 22050) { + av_log(s, AV_LOG_ERROR, "Sample rate must be 22050 for TUN files\n"); + return AVERROR(EINVAL); + } + return 0; +} + +static int alp_write_header(AVFormatContext *s) +{ + ALPMuxContext *alp = s->priv_data; + AVCodecParameters *par = s->streams[0]->codecpar; + + avio_wl32(s->pb, ALP_TAG); + avio_wl32(s->pb, alp->type == ALP_TYPE_PCM ? 12 : 8); + avio_write(s->pb, "ADPCM", 6); + avio_w8(s->pb, 0); + avio_w8(s->pb, par->channels); + if (alp->type == ALP_TYPE_PCM) + avio_wl32(s->pb, par->sample_rate); + + return 0; +} + +enum { AE = AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }; + +static const AVOption alp_options[] = { + { + .name = "type", + .help = "set file type", + .offset = offsetof(ALPMuxContext, type), + .type = AV_OPT_TYPE_INT, + .default_val = {.i64 = ALP_TYPE_AUTO}, + .min = ALP_TYPE_AUTO, + .max = ALP_TYPE_PCM, + .flags = AE, + .unit = "type", + }, + { + .name = "auto", + .help = "autodetect based on file extension", + .offset = 0, + .type = AV_OPT_TYPE_CONST, + .default_val = {.i64 = ALP_TYPE_AUTO}, + .min = 0, + .max = 0, + .flags = AE, + .unit = "type" + }, + { + .name = "tun", + .help = "force .tun, used for music", + .offset = 0, + .type = AV_OPT_TYPE_CONST, + .default_val = {.i64 = ALP_TYPE_TUN}, + .min = 0, + .max = 0, + .flags = AE, + .unit = "type" + }, + { + .name = "pcm", + .help = "force .pcm, used for sfx", + .offset = 0, + .type = AV_OPT_TYPE_CONST, + .default_val = {.i64 = ALP_TYPE_PCM}, + .min = 0, + .max = 0, + .flags = AE, + .unit = "type" + }, + { NULL } +}; + +static const AVClass alp_muxer_class = { + .class_name = "alp", + .item_name = av_default_item_name, + .option = alp_options, + .version = LIBAVUTIL_VERSION_INT +}; + +AVOutputFormat ff_alp_muxer = { + .name = "alp", + .long_name = NULL_IF_CONFIG_SMALL("LEGO Racers ALP"), + .extensions = "tun,pcm", + .audio_codec = AV_CODEC_ID_ADPCM_IMA_ALP, + .video_codec = AV_CODEC_ID_NONE, + .init = alp_write_init, + .write_header = alp_write_header, + .write_packet = ff_raw_write_packet, + .priv_class = &alp_muxer_class, + .priv_data_size = sizeof(ALPMuxContext) +}; +#endif diff -Nru ffmpeg-4.2.2/libavformat/amr.c ffmpeg-4.4/libavformat/amr.c --- ffmpeg-4.2.2/libavformat/amr.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/amr.c 2020-07-11 10:39:30.000000000 +0000 @@ -29,6 +29,7 @@ #include "libavutil/channel_layout.h" #include "avformat.h" #include "internal.h" +#include "rawenc.h" typedef struct { uint64_t cumulated_size; @@ -60,13 +61,6 @@ } else { return -1; } - avio_flush(pb); - return 0; -} - -static int amr_write_packet(AVFormatContext *s, AVPacket *pkt) -{ - avio_write(s->pb, pkt->data, pkt->size); return 0; } #endif /* CONFIG_AMR_MUXER */ @@ -90,13 +84,15 @@ AVStream *st; uint8_t header[9]; - avio_read(pb, header, 6); + if (avio_read(pb, header, 6) != 6) + return AVERROR_INVALIDDATA; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); if (memcmp(header, AMR_header, 6)) { - avio_read(pb, header + 6, 3); + if (avio_read(pb, header + 6, 3) != 3) + return AVERROR_INVALIDDATA; if (memcmp(header, AMRWB_header, 9)) { return -1; } @@ -154,7 +150,6 @@ read = avio_read(s->pb, pkt->data + 1, size - 1); if (read != size - 1) { - av_packet_unref(pkt); if (read < 0) return read; return AVERROR(EIO); @@ -296,7 +291,7 @@ .audio_codec = AV_CODEC_ID_AMR_NB, .video_codec = AV_CODEC_ID_NONE, .write_header = amr_write_header, - .write_packet = amr_write_packet, + .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; #endif diff -Nru ffmpeg-4.2.2/libavformat/amvenc.c ffmpeg-4.4/libavformat/amvenc.c --- ffmpeg-4.2.2/libavformat/amvenc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/amvenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,422 @@ +/* + * AMV muxer + * + * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.com) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "riff.h" +#include "internal.h" +#include "avio_internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/avassert.h" + +/* + * Things to note: + * - AMV is a hard-coded (and broken) subset of AVI. It's not worth sullying the + * existing AVI muxer with its filth. + * - No separate demuxer as the existing AVI demuxer can handle these. + * - The sizes of certain tags are deliberately set to 0 as some players break + * when they're set correctly. Ditto with some header fields. + * - There is no index. + * - Players are **very** sensitive to the frame order and sizes. + * - Frames must be strictly interleaved as V-A, any V-V or A-A will + * cause crashes. + * - Variable video frame sizes seem to be handled fine. + * - Variable audio frame sizes cause crashes. + * - If audio is shorter than video, it's padded with silence. + * - If video is shorter than audio, the most recent frame is repeated. + */ + +#define AMV_STREAM_COUNT 2 +#define AMV_STREAM_VIDEO 0 +#define AMV_STREAM_AUDIO 1 +#define AMV_VIDEO_STRH_SIZE 56 +#define AMV_VIDEO_STRF_SIZE 36 +#define AMV_AUDIO_STRH_SIZE 48 +#define AMV_AUDIO_STRF_SIZE 20 /* sizeof(WAVEFORMATEX) + 2 */ + +typedef struct AMVContext +{ + int64_t riff_start; + int64_t movi_list; + int64_t offset_duration; + int last_stream; + + int32_t us_per_frame; /* Microseconds per frame. */ + + int32_t aframe_size; /* Expected audio frame size. */ + int32_t ablock_align; /* Expected audio block align. */ + AVPacket *apad; /* Dummy audio packet for padding. */ + AVPacket *vpad; /* Most recent video frame, for padding. */ + + /* + * Cumulative PTS values for each stream, used for the final + * duration calculcation. + */ + int64_t lastpts[AMV_STREAM_COUNT]; +} AMVContext; + +/* ff_{start,end}_tag(), but sets the size to 0. */ +static int64_t amv_start_tag(AVIOContext *pb, const char *tag) +{ + ffio_wfourcc(pb, tag); + avio_wl32(pb, 0); + return avio_tell(pb); +} + +static void amv_end_tag(AVIOContext *pb, int64_t start) +{ + int64_t pos; + av_assert0((start&1) == 0); + + pos = avio_tell(pb); + if (pos & 1) + avio_w8(pb, 0); +} + +static av_cold int amv_init(AVFormatContext *s) +{ + AMVContext *amv = s->priv_data; + AVStream *vst, *ast; + int ret; + + amv->last_stream = -1; + + if (s->nb_streams != AMV_STREAM_COUNT) { + av_log(s, AV_LOG_ERROR, "AMV files only support 2 streams\n"); + return AVERROR(EINVAL); + } + + vst = s->streams[AMV_STREAM_VIDEO]; + ast = s->streams[AMV_STREAM_AUDIO]; + + if (vst->codecpar->codec_id != AV_CODEC_ID_AMV) { + av_log(s, AV_LOG_ERROR, "First AMV stream must be %s\n", + avcodec_get_name(AV_CODEC_ID_AMV)); + return AVERROR(EINVAL); + } + + if (ast->codecpar->codec_id != AV_CODEC_ID_ADPCM_IMA_AMV) { + av_log(s, AV_LOG_ERROR, "Second AMV stream must be %s\n", + avcodec_get_name(AV_CODEC_ID_ADPCM_IMA_AMV)); + return AVERROR(EINVAL); + } + + /* These files are broken-enough as they are. They shouldn't be streamed. */ + if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) { + av_log(s, AV_LOG_ERROR, "Stream not seekable, unable to write output file\n"); + return AVERROR(EINVAL); + } + + amv->us_per_frame = av_rescale(AV_TIME_BASE, vst->time_base.num, vst->time_base.den); + amv->aframe_size = av_rescale(ast->codecpar->sample_rate, amv->us_per_frame, AV_TIME_BASE); + amv->ablock_align = 8 + (FFALIGN(amv->aframe_size, 2) / 2); + + av_log(s, AV_LOG_TRACE, "us_per_frame = %d\n", amv->us_per_frame); + av_log(s, AV_LOG_TRACE, "aframe_size = %d\n", amv->aframe_size); + av_log(s, AV_LOG_TRACE, "ablock_align = %d\n", amv->ablock_align); + + /* + * Bail if the framerate's too high. Prevents the audio frame size from + * getting too small. 63fps is the closest value to 60fps that divides + * cleanly, so cap it there. + */ + if (amv->us_per_frame < 15873) { + av_log(s, AV_LOG_ERROR, "Refusing to mux >63fps video\n"); + return AVERROR(EINVAL); + } + + /* + * frame_size will be set if coming from the encoder. + * Make sure the its been configured correctly. The audio frame duration + * needs to match that of the video. + */ + if (ast->codecpar->frame_size) { + AVCodecParameters *par = ast->codecpar; + int bad = 0; + + if (par->frame_size != amv->aframe_size) { + av_log(s, AV_LOG_ERROR, "Invalid audio frame size. Got %d, wanted %d\n", + par->frame_size, amv->aframe_size); + bad = 1; + } + + if (par->block_align != amv->ablock_align) { + av_log(s, AV_LOG_ERROR, "Invalid audio block align. Got %d, wanted %d\n", + par->block_align, amv->ablock_align); + bad = 1; + } + + if (bad) { + av_log(s, AV_LOG_ERROR, "Try -block_size %d\n", amv->aframe_size); + return AVERROR(EINVAL); + } + + if (ast->codecpar->sample_rate % amv->aframe_size) { + av_log(s, AV_LOG_ERROR, "Audio sample rate not a multiple of the frame size.\n" + "Please change video frame rate. Suggested rates: 10,14,15,18,21,25,30\n"); + return AVERROR(EINVAL); + } + } else { + /* If remuxing from the same source, then this will match the video. */ + int32_t aus = av_rescale(AV_TIME_BASE, ast->time_base.num, ast->time_base.den); + if (aus != amv->us_per_frame) { + av_log(s, AV_LOG_ERROR, "Cannot remux streams with a different time base\n"); + return AVERROR(EINVAL); + } + } + + /* Allocate and fill dummy packet so we can pad the audio. */ + amv->apad = av_packet_alloc(); + if (!amv->apad) + return AVERROR(ENOMEM); + if ((ret = av_new_packet(amv->apad, amv->ablock_align)) < 0) { + av_packet_free(&amv->apad); + return ret; + } + + amv->apad->stream_index = AMV_STREAM_AUDIO; + memset(amv->apad->data, 0, amv->ablock_align); + AV_WL32(amv->apad->data + 4, amv->aframe_size); + + amv->vpad = av_packet_alloc(); + if (!amv->vpad) { + av_packet_free(&amv->apad); + return AVERROR(ENOMEM); + } + amv->vpad->stream_index = AMV_STREAM_VIDEO; + amv->vpad->duration = 1; + return 0; +} + +static void amv_deinit(AVFormatContext *s) +{ + AMVContext *amv = s->priv_data; + + av_packet_free(&amv->apad); + av_packet_free(&amv->vpad); +} + +static void amv_write_vlist(AVFormatContext *s, AVCodecParameters *par) +{ + int64_t tag_list, tag_str; + + av_assert0(par->codec_id == AV_CODEC_ID_AMV); + + tag_list = amv_start_tag(s->pb, "LIST"); + ffio_wfourcc(s->pb, "strl"); + tag_str = ff_start_tag(s->pb, "strh"); + ffio_fill(s->pb, 0, AMV_VIDEO_STRH_SIZE); + ff_end_tag(s->pb, tag_str); + + tag_str = ff_start_tag(s->pb, "strf"); + ffio_fill(s->pb, 0, AMV_VIDEO_STRF_SIZE); + ff_end_tag(s->pb, tag_str); + + amv_end_tag(s->pb, tag_list); +} + +static void amv_write_alist(AVFormatContext *s, AVCodecParameters *par) +{ + uint8_t buf[AMV_AUDIO_STRF_SIZE]; + AVIOContext *pb = s->pb; + int64_t tag_list, tag_str; + + av_assert0(par->codec_id == AV_CODEC_ID_ADPCM_IMA_AMV); + + tag_list = amv_start_tag(pb, "LIST"); + ffio_wfourcc(pb, "strl"); + tag_str = ff_start_tag(pb, "strh"); + ffio_fill(s->pb, 0, AMV_AUDIO_STRH_SIZE); + ff_end_tag(pb, tag_str); + + /* Bodge an (incorrect) WAVEFORMATEX (+2 pad bytes) */ + tag_str = ff_start_tag(pb, "strf"); + AV_WL16(buf + 0, 1); + AV_WL16(buf + 2, par->channels); + AV_WL32(buf + 4, par->sample_rate); + AV_WL32(buf + 8, par->sample_rate * par->channels * 2); + AV_WL16(buf + 12, 2); + AV_WL16(buf + 14, 16); + AV_WL16(buf + 16, 0); + AV_WL16(buf + 18, 0); + avio_write(pb, buf, AMV_AUDIO_STRF_SIZE); + ff_end_tag(pb, tag_str); + + amv_end_tag(pb, tag_list); +} + +static int amv_write_header(AVFormatContext *s) +{ + AMVContext *amv = s->priv_data; + AVIOContext *pb = s->pb; + AVStream *vst = s->streams[AMV_STREAM_VIDEO]; + AVStream *ast = s->streams[AMV_STREAM_AUDIO]; + uint8_t amvh[56] = {0}; + int64_t list1; + + amv->riff_start = amv_start_tag(pb, "RIFF"); + ffio_wfourcc(pb, "AMV "); + list1 = amv_start_tag(pb, "LIST"); + ffio_wfourcc(pb, "hdrl"); + + ffio_wfourcc(pb, "amvh"); + avio_wl32(pb, 56); + + AV_WL32(amvh + 0, amv->us_per_frame); + AV_WL32(amvh + 32, vst->codecpar->width); + AV_WL32(amvh + 36, vst->codecpar->height); + AV_WL32(amvh + 40, vst->time_base.den); + AV_WL32(amvh + 44, vst->time_base.num); + AV_WL32(amvh + 48, 0); + AV_WL32(amvh + 52, 0); /* duration, filled in later. */ + + avio_write(pb, amvh, sizeof(amvh)); + amv->offset_duration = avio_tell(pb) - 4; + + amv_write_vlist(s, vst->codecpar); + amv_write_alist(s, ast->codecpar); + amv_end_tag(pb, list1); + + amv->movi_list = amv_start_tag(pb, "LIST"); + ffio_wfourcc(pb, "movi"); + return 0; +} + +static int amv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) +{ + AMVContext *amv = s->priv_data; + + if (pkt->stream_index == AMV_STREAM_VIDEO) + ffio_wfourcc(s->pb, "00dc"); + else if (pkt->stream_index == AMV_STREAM_AUDIO) + ffio_wfourcc(s->pb, "01wb"); + else + av_assert0(0); + + if (pkt->stream_index == AMV_STREAM_AUDIO && pkt->size != amv->ablock_align) { + /* Can happen when remuxing files produced by another encoder. */ + av_log(s, AV_LOG_WARNING, "Invalid audio packet size (%d != %d)\n", + pkt->size, amv->ablock_align); + } + + avio_wl32(s->pb, pkt->size); + avio_write(s->pb, pkt->data, pkt->size); + + amv->lastpts[pkt->stream_index] += pkt->duration; + amv->last_stream = pkt->stream_index; + return 0; +} + +static int amv_pad(AVFormatContext *s, AVPacket *pkt) +{ + AMVContext *amv = s->priv_data; + int stream_index = pkt->stream_index; + + if (stream_index != amv->last_stream) + return 0; + + stream_index = (stream_index + 1) % s->nb_streams; + if (stream_index == AMV_STREAM_VIDEO) + return amv_write_packet_internal(s, amv->vpad); + else if (stream_index == AMV_STREAM_AUDIO) + return amv_write_packet_internal(s, amv->apad); + else + av_assert0(0); + + return AVERROR(EINVAL); +} + +static int amv_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + AMVContext *amv = s->priv_data; + int ret; + + /* Add a dummy frame if we've received two of the same index. */ + if ((ret = amv_pad(s, pkt)) < 0) + return ret; + + if ((ret = amv_write_packet_internal(s, pkt)) < 0) + return ret; + + if (pkt->stream_index == AMV_STREAM_VIDEO) { + /* Save the last packet for padding. */ + av_packet_unref(amv->vpad); + if ((ret = av_packet_ref(amv->vpad, pkt)) < 0) + return ret; + } + + return 0; +} + +static int amv_write_trailer(AVFormatContext *s) +{ + AMVContext *amv = s->priv_data; + AVStream *vst = s->streams[AMV_STREAM_VIDEO]; + AVStream *ast = s->streams[AMV_STREAM_AUDIO]; + int64_t maxpts, ret; + int hh, mm, ss; + + /* Pad-out one last audio frame if needed. */ + if (amv->last_stream == AMV_STREAM_VIDEO) { + if ((ret = amv_write_packet_internal(s, amv->apad)) < 0) + return ret; + } + + amv_end_tag(s->pb, amv->movi_list); + amv_end_tag(s->pb, amv->riff_start); + + ffio_wfourcc(s->pb, "AMV_"); + ffio_wfourcc(s->pb, "END_"); + + if ((ret = avio_seek(s->pb, amv->offset_duration, SEEK_SET)) < 0) + return ret; + + /* Go back and write the duration. */ + maxpts = FFMAX( + av_rescale_q(amv->lastpts[AMV_STREAM_VIDEO], vst->time_base, AV_TIME_BASE_Q), + av_rescale_q(amv->lastpts[AMV_STREAM_AUDIO], ast->time_base, AV_TIME_BASE_Q) + ); + + ss = maxpts / AV_TIME_BASE; + mm = ss / 60; + hh = mm / 60; + ss %= 60; + mm %= 60; + + avio_w8(s->pb, ss); + avio_w8(s->pb, mm); + avio_wl16(s->pb, hh); + return 0; +} + +AVOutputFormat ff_amv_muxer = { + .name = "amv", + .long_name = NULL_IF_CONFIG_SMALL("AMV"), + .mime_type = "video/amv", + .extensions = "amv", + .priv_data_size = sizeof(AMVContext), + .audio_codec = AV_CODEC_ID_ADPCM_IMA_AMV, + .video_codec = AV_CODEC_ID_AMV, + .init = amv_init, + .deinit = amv_deinit, + .write_header = amv_write_header, + .write_packet = amv_write_packet, + .write_trailer = amv_write_trailer, +}; diff -Nru ffmpeg-4.2.2/libavformat/apc.c ffmpeg-4.4/libavformat/apc.c --- ffmpeg-4.2.2/libavformat/apc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/apc.c 2020-07-11 10:39:30.000000000 +0000 @@ -37,6 +37,7 @@ { AVIOContext *pb = s->pb; AVStream *st; + int ret; avio_rl32(pb); /* CRYO */ avio_rl32(pb); /* _APC */ @@ -53,8 +54,8 @@ st->codecpar->sample_rate = avio_rl32(pb); /* initial predictor values for adpcm decoder */ - if (ff_get_extradata(s, st->codecpar, pb, 2 * 4) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_get_extradata(s, st->codecpar, pb, 2 * 4)) < 0) + return ret; if (avio_rl32(pb)) { st->codecpar->channels = 2; @@ -78,7 +79,6 @@ { if (av_get_packet(s->pb, pkt, MAX_READ_SIZE) <= 0) return AVERROR(EIO); - pkt->flags &= ~AV_PKT_FLAG_CORRUPT; pkt->stream_index = 0; return 0; } diff -Nru ffmpeg-4.2.2/libavformat/ape.c ffmpeg-4.4/libavformat/ape.c --- ffmpeg-4.2.2/libavformat/ape.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ape.c 2021-04-08 21:28:40.000000000 +0000 @@ -77,12 +77,10 @@ uint16_t bps; uint16_t channels; uint32_t samplerate; - - /* Seektable */ - uint32_t *seektable; - uint8_t *bittable; } APEContext; +static int ape_read_close(AVFormatContext * s); + static int ape_probe(const AVProbeData * p) { int version = AV_RL16(p->buf+4); @@ -128,20 +126,6 @@ av_log(s, AV_LOG_DEBUG, "\nSeektable\n\n"); if ((ape_ctx->seektablelength / sizeof(uint32_t)) != ape_ctx->totalframes) { av_log(s, AV_LOG_DEBUG, "No seektable\n"); - } else { - for (i = 0; i < ape_ctx->seektablelength / sizeof(uint32_t); i++) { - if (i < ape_ctx->totalframes - 1) { - av_log(s, AV_LOG_DEBUG, "%8d %"PRIu32" (%"PRIu32" bytes)", - i, ape_ctx->seektable[i], - ape_ctx->seektable[i + 1] - ape_ctx->seektable[i]); - if (ape_ctx->bittable) - av_log(s, AV_LOG_DEBUG, " + %2d bits\n", - ape_ctx->bittable[i]); - av_log(s, AV_LOG_DEBUG, "\n"); - } else { - av_log(s, AV_LOG_DEBUG, "%8d %"PRIu32"\n", i, ape_ctx->seektable[i]); - } - } } av_log(s, AV_LOG_DEBUG, "\nFrames\n\n"); @@ -163,7 +147,7 @@ APEContext *ape = s->priv_data; AVStream *st; uint32_t tag; - int i; + int i, ret; int total_blocks, final_size = 0; int64_t pts, file_size; @@ -251,7 +235,7 @@ avio_skip(pb, ape->wavheaderlength); } - if(!ape->totalframes){ + if(!ape->totalframes || pb->eof_reached){ av_log(s, AV_LOG_ERROR, "No frames in the file!\n"); return AVERROR(EINVAL); } @@ -260,10 +244,10 @@ ape->totalframes); return AVERROR_INVALIDDATA; } - if (ape->seektablelength / sizeof(*ape->seektable) < ape->totalframes) { + if (ape->seektablelength / sizeof(uint32_t) < ape->totalframes) { av_log(s, AV_LOG_ERROR, "Number of seek entries is less than number of frames: %"SIZE_SPECIFIER" vs. %"PRIu32"\n", - ape->seektablelength / sizeof(*ape->seektable), ape->totalframes); + ape->seektablelength / sizeof(uint32_t), ape->totalframes); return AVERROR_INVALIDDATA; } ape->frames = av_malloc_array(ape->totalframes, sizeof(APEFrame)); @@ -279,32 +263,26 @@ if (ape->totalframes > 1) ape->totalsamples += ape->blocksperframe * (ape->totalframes - 1); - if (ape->seektablelength > 0) { - ape->seektable = av_mallocz(ape->seektablelength); - if (!ape->seektable) - return AVERROR(ENOMEM); - for (i = 0; i < ape->seektablelength / sizeof(uint32_t) && !pb->eof_reached; i++) - ape->seektable[i] = avio_rl32(pb); - if (ape->fileversion < 3810) { - ape->bittable = av_mallocz(ape->totalframes); - if (!ape->bittable) - return AVERROR(ENOMEM); - for (i = 0; i < ape->totalframes && !pb->eof_reached; i++) - ape->bittable[i] = avio_r8(pb); - } - if (pb->eof_reached) - av_log(s, AV_LOG_WARNING, "File truncated\n"); - } - ape->frames[0].pos = ape->firstframe; ape->frames[0].nblocks = ape->blocksperframe; ape->frames[0].skip = 0; + avio_rl32(pb); // seektable[0] for (i = 1; i < ape->totalframes; i++) { - ape->frames[i].pos = ape->seektable[i] + ape->junklength; + uint32_t seektable_entry = avio_rl32(pb); + ape->frames[i].pos = seektable_entry + ape->junklength; ape->frames[i].nblocks = ape->blocksperframe; ape->frames[i - 1].size = ape->frames[i].pos - ape->frames[i - 1].pos; ape->frames[i].skip = (ape->frames[i].pos - ape->frames[0].pos) & 3; + + if (pb->eof_reached) { + av_log(s, AV_LOG_ERROR, "seektable truncated\n"); + ret = AVERROR_INVALIDDATA; + goto fail; + } + ff_dlog(s, "seektable: %8d %"PRIu32"\n", i, seektable_entry); } + avio_skip(pb, ape->seektablelength / sizeof(uint32_t) - ape->totalframes); + ape->frames[ape->totalframes - 1].nblocks = ape->finalframeblocks; /* calculate final packet size from total file size, if available */ file_size = avio_size(pb); @@ -326,10 +304,18 @@ } if (ape->fileversion < 3810) { for (i = 0; i < ape->totalframes; i++) { - if (i < ape->totalframes - 1 && ape->bittable[i + 1]) - ape->frames[i].size += 4; + int bits = avio_r8(pb); + if (i && bits) + ape->frames[i - 1].size += 4; + ape->frames[i].skip <<= 3; - ape->frames[i].skip += ape->bittable[i]; + ape->frames[i].skip += bits; + ff_dlog(s, "bittable: %2d\n", bits); + if (pb->eof_reached) { + av_log(s, AV_LOG_ERROR, "bittable truncated\n"); + ret = AVERROR_INVALIDDATA; + goto fail; + } } } @@ -341,8 +327,10 @@ /* now we are ready: build format streams */ st = avformat_new_stream(s, NULL); - if (!st) - return AVERROR(ENOMEM); + if (!st) { + ret = AVERROR(ENOMEM); + goto fail; + } total_blocks = (ape->totalframes == 0) ? 0 : ((ape->totalframes - 1) * ape->blocksperframe) + ape->finalframeblocks; @@ -358,8 +346,8 @@ st->duration = total_blocks; avpriv_set_pts_info(st, 64, 1, ape->samplerate); - if (ff_alloc_extradata(st->codecpar, APE_EXTRADATA_SIZE)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, APE_EXTRADATA_SIZE)) < 0) + goto fail; AV_WL16(st->codecpar->extradata + 0, ape->fileversion); AV_WL16(st->codecpar->extradata + 2, ape->compressiontype); AV_WL16(st->codecpar->extradata + 4, ape->formatflags); @@ -378,6 +366,10 @@ } return 0; +fail: + ape_read_close(s); + + return ret; } static int ape_read_packet(AVFormatContext * s, AVPacket * pkt) @@ -386,14 +378,16 @@ int nblocks; APEContext *ape = s->priv_data; uint32_t extra_size = 8; + int64_t ret64; if (avio_feof(s->pb)) return AVERROR_EOF; if (ape->currentframe >= ape->totalframes) return AVERROR_EOF; - if (avio_seek(s->pb, ape->frames[ape->currentframe].pos, SEEK_SET) < 0) - return AVERROR(EIO); + ret64 = avio_seek(s->pb, ape->frames[ape->currentframe].pos, SEEK_SET); + if (ret64 < 0) + return ret64; /* Calculate how many blocks there are in this frame */ if (ape->currentframe == (ape->totalframes - 1)) @@ -409,14 +403,14 @@ return AVERROR(EIO); } - if (av_new_packet(pkt, ape->frames[ape->currentframe].size + extra_size) < 0) - return AVERROR(ENOMEM); + ret = av_new_packet(pkt, ape->frames[ape->currentframe].size + extra_size); + if (ret < 0) + return ret; AV_WL32(pkt->data , nblocks); AV_WL32(pkt->data + 4, ape->frames[ape->currentframe].skip); ret = avio_read(s->pb, pkt->data + extra_size, ape->frames[ape->currentframe].size); if (ret < 0) { - av_packet_unref(pkt); return ret; } @@ -437,8 +431,6 @@ APEContext *ape = s->priv_data; av_freep(&ape->frames); - av_freep(&ape->seektable); - av_freep(&ape->bittable); return 0; } @@ -447,12 +439,13 @@ AVStream *st = s->streams[stream_index]; APEContext *ape = s->priv_data; int index = av_index_search_timestamp(st, timestamp, flags); + int64_t ret; if (index < 0) return -1; - if (avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET) < 0) - return -1; + if ((ret = avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET)) < 0) + return ret; ape->currentframe = index; return 0; } diff -Nru ffmpeg-4.2.2/libavformat/apetag.c ffmpeg-4.4/libavformat/apetag.c --- ffmpeg-4.2.2/libavformat/apetag.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/apetag.c 2020-07-11 10:39:30.000000000 +0000 @@ -96,8 +96,8 @@ st->attached_pic.stream_index = st->index; st->attached_pic.flags |= AV_PKT_FLAG_KEY; } else { - if (ff_get_extradata(s, st->codecpar, s->pb, size) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0) + return ret; st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT; } } else { @@ -186,11 +186,11 @@ { AVDictionaryEntry *e = NULL; int size, ret, count = 0; - AVIOContext *dyn_bc = NULL; - uint8_t *dyn_buf = NULL; + AVIOContext *dyn_bc; + uint8_t *dyn_buf; if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0) - goto end; + return ret; ff_standardize_creation_time(s); while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) { @@ -211,7 +211,7 @@ if (!count) goto end; - size = avio_close_dyn_buf(dyn_bc, &dyn_buf); + size = avio_get_dyn_buf(dyn_bc, &dyn_buf); if (size <= 0) goto end; size += APE_TAG_FOOTER_BYTES; @@ -239,9 +239,7 @@ ffio_fill(s->pb, 0, 8); // reserved end: - if (dyn_bc && !dyn_buf) - avio_close_dyn_buf(dyn_bc, &dyn_buf); - av_freep(&dyn_buf); + ffio_free_dyn_buf(&dyn_bc); return ret; } diff -Nru ffmpeg-4.2.2/libavformat/apm.c ffmpeg-4.4/libavformat/apm.c --- ffmpeg-4.2.2/libavformat/apm.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/apm.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,317 @@ +/* + * Rayman 2 APM (De)muxer + * + * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.com) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "avformat.h" +#include "internal.h" +#include "rawenc.h" +#include "libavutil/avassert.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" + +#define APM_FILE_HEADER_SIZE 20 +#define APM_FILE_EXTRADATA_SIZE 80 +#define APM_EXTRADATA_SIZE 28 + +#define APM_MAX_READ_SIZE 4096 + +#define APM_TAG_CODEC 0x2000 +#define APM_TAG_VS12 MKTAG('v', 's', '1', '2') +#define APM_TAG_DATA MKTAG('D', 'A', 'T', 'A') + +typedef struct APMState { + int32_t has_saved; + int32_t predictor_r; + int32_t step_index_r; + int32_t saved_r; + int32_t predictor_l; + int32_t step_index_l; + int32_t saved_l; +} APMState; + +typedef struct APMExtraData { + uint32_t magic; + uint32_t file_size; + uint32_t data_size; + uint32_t unk1; + uint32_t unk2; + APMState state; + uint32_t unk3[7]; + uint32_t data; +} APMExtraData; + +#if CONFIG_APM_DEMUXER +static void apm_parse_extradata(APMExtraData *ext, const uint8_t *buf) +{ + ext->magic = AV_RL32(buf + 0); + ext->file_size = AV_RL32(buf + 4); + ext->data_size = AV_RL32(buf + 8); + ext->unk1 = AV_RL32(buf + 12); + ext->unk2 = AV_RL32(buf + 16); + + ext->state.has_saved = AV_RL32(buf + 20); + ext->state.predictor_r = AV_RL32(buf + 24); + ext->state.step_index_r = AV_RL32(buf + 28); + ext->state.saved_r = AV_RL32(buf + 32); + ext->state.predictor_l = AV_RL32(buf + 36); + ext->state.step_index_l = AV_RL32(buf + 40); + ext->state.saved_l = AV_RL32(buf + 44); + + for (int i = 0; i < FF_ARRAY_ELEMS(ext->unk3); i++) + ext->unk3[i] = AV_RL32(buf + 48 + (i * 4)); + + ext->data = AV_RL32(buf + 76); +} + +static int apm_probe(const AVProbeData *p) +{ + if (AV_RL16(p->buf) != APM_TAG_CODEC) + return 0; + + if (p->buf_size < 100) + return 0; + + if (AV_RL32(p->buf + 20) != APM_TAG_VS12) + return 0; + + if (AV_RL32(p->buf + 96) != APM_TAG_DATA) + return 0; + + return AVPROBE_SCORE_MAX - 1; +} + +static int apm_read_header(AVFormatContext *s) +{ + int64_t ret; + AVStream *st; + APMExtraData extradata; + AVCodecParameters *par; + uint8_t buf[APM_FILE_EXTRADATA_SIZE]; + + if (!(st = avformat_new_stream(s, NULL))) + return AVERROR(ENOMEM); + + /* + * This is 98% a WAVEFORMATEX, but there's something screwy with the extradata + * that ff_get_wav_header() can't (and shouldn't) handle properly. + */ + if (avio_rl16(s->pb) != APM_TAG_CODEC) + return AVERROR_INVALIDDATA; + + par = st->codecpar; + par->channels = avio_rl16(s->pb); + par->sample_rate = avio_rl32(s->pb); + + /* Skip the bitrate, it's usually wrong anyway. */ + if ((ret = avio_skip(s->pb, 4)) < 0) + return ret; + + par->block_align = avio_rl16(s->pb); + par->bits_per_coded_sample = avio_rl16(s->pb); + + if (avio_rl32(s->pb) != APM_FILE_EXTRADATA_SIZE) + return AVERROR_INVALIDDATA; + + /* 8 = bits per sample * max channels */ + if (par->sample_rate > (INT_MAX / 8)) + return AVERROR_INVALIDDATA; + + if (par->bits_per_coded_sample != 4) + return AVERROR_INVALIDDATA; + + if (par->channels == 2) + par->channel_layout = AV_CH_LAYOUT_STEREO; + else if (par->channels == 1) + par->channel_layout = AV_CH_LAYOUT_MONO; + else + return AVERROR_INVALIDDATA; + + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = AV_CODEC_ID_ADPCM_IMA_APM; + par->format = AV_SAMPLE_FMT_S16; + par->bits_per_raw_sample = 16; + par->bit_rate = par->channels * + par->sample_rate * + par->bits_per_coded_sample; + + if ((ret = avio_read(s->pb, buf, APM_FILE_EXTRADATA_SIZE)) < 0) + return ret; + else if (ret != APM_FILE_EXTRADATA_SIZE) + return AVERROR(EIO); + + apm_parse_extradata(&extradata, buf); + + if (extradata.magic != APM_TAG_VS12 || extradata.data != APM_TAG_DATA) + return AVERROR_INVALIDDATA; + + if (extradata.state.has_saved) { + avpriv_request_sample(s, "Saved Samples"); + return AVERROR_PATCHWELCOME; + } + + if ((ret = ff_alloc_extradata(par, APM_EXTRADATA_SIZE)) < 0) + return ret; + + /* Use the entire state as extradata. */ + memcpy(par->extradata, buf + 20, APM_EXTRADATA_SIZE); + + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + st->start_time = 0; + st->duration = extradata.data_size * + (8 / par->bits_per_coded_sample) / + par->channels; + return 0; +} + +static int apm_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + int ret; + AVCodecParameters *par = s->streams[0]->codecpar; + + /* + * For future reference: if files with the `has_saved` field set ever + * surface, `saved_l`, and `saved_r` will each contain 8 "saved" samples + * that should be sent to the decoder before the actual data. + */ + + if ((ret = av_get_packet(s->pb, pkt, APM_MAX_READ_SIZE)) < 0) + return ret; + + pkt->flags &= ~AV_PKT_FLAG_CORRUPT; + pkt->stream_index = 0; + pkt->duration = ret * (8 / par->bits_per_coded_sample) / par->channels; + + return 0; +} + +AVInputFormat ff_apm_demuxer = { + .name = "apm", + .long_name = NULL_IF_CONFIG_SMALL("Ubisoft Rayman 2 APM"), + .read_probe = apm_probe, + .read_header = apm_read_header, + .read_packet = apm_read_packet +}; +#endif + +#if CONFIG_APM_MUXER +static int apm_write_init(AVFormatContext *s) +{ + AVCodecParameters *par; + + if (s->nb_streams != 1) { + av_log(s, AV_LOG_ERROR, "APM files have exactly one stream\n"); + return AVERROR(EINVAL); + } + + par = s->streams[0]->codecpar; + + if (par->codec_id != AV_CODEC_ID_ADPCM_IMA_APM) { + av_log(s, AV_LOG_ERROR, "%s codec not supported\n", + avcodec_get_name(par->codec_id)); + return AVERROR(EINVAL); + } + + if (par->channels > 2) { + av_log(s, AV_LOG_ERROR, "APM files only support up to 2 channels\n"); + return AVERROR(EINVAL); + } + + if (par->sample_rate > (INT_MAX / 8)) { + av_log(s, AV_LOG_ERROR, "Sample rate too large\n"); + return AVERROR(EINVAL); + } + + if (par->extradata_size != APM_EXTRADATA_SIZE) { + av_log(s, AV_LOG_ERROR, "Invalid/missing extradata\n"); + return AVERROR(EINVAL); + } + + if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) { + av_log(s, AV_LOG_ERROR, "Stream not seekable, unable to write output file\n"); + return AVERROR(EINVAL); + } + + return 0; +} + +static int apm_write_header(AVFormatContext *s) +{ + uint8_t buf[APM_FILE_EXTRADATA_SIZE] = { 0 }; + AVCodecParameters *par = s->streams[0]->codecpar; + + /* + * Bodge a WAVEFORMATEX manually, ff_put_wav_header() can't + * be used because of the extra 2 bytes. + */ + avio_wl16(s->pb, APM_TAG_CODEC); + avio_wl16(s->pb, par->channels); + avio_wl32(s->pb, par->sample_rate); + /* This is the wrong calculation, but it's what the orginal files have. */ + avio_wl32(s->pb, par->sample_rate * par->channels * 2); + avio_wl16(s->pb, par->block_align); + avio_wl16(s->pb, par->bits_per_coded_sample); + avio_wl32(s->pb, APM_FILE_EXTRADATA_SIZE); + + /* + * Build the extradata. Assume the codec's given us correct data. + * File and data sizes are fixed later. + */ + AV_WL32(buf + 0, APM_TAG_VS12); /* magic */ + AV_WL32(buf + 12, 0xFFFFFFFF); /* unk1 */ + memcpy( buf + 20, par->extradata, APM_EXTRADATA_SIZE); + AV_WL32(buf + 76, APM_TAG_DATA); /* data */ + + avio_write(s->pb, buf, APM_FILE_EXTRADATA_SIZE); + return 0; +} + +static int apm_write_trailer(AVFormatContext *s) +{ + int64_t file_size, data_size; + + file_size = avio_tell(s->pb); + data_size = file_size - (APM_FILE_HEADER_SIZE + APM_FILE_EXTRADATA_SIZE); + + if (file_size >= UINT32_MAX) { + av_log(s, AV_LOG_ERROR, + "Filesize %"PRId64" invalid for APM, output file will be broken\n", + file_size); + return AVERROR(ERANGE); + } + + avio_seek(s->pb, 24, SEEK_SET); + avio_wl32(s->pb, (uint32_t)file_size); + avio_wl32(s->pb, (uint32_t)data_size); + + return 0; +} + +AVOutputFormat ff_apm_muxer = { + .name = "apm", + .long_name = NULL_IF_CONFIG_SMALL("Ubisoft Rayman 2 APM"), + .extensions = "apm", + .audio_codec = AV_CODEC_ID_ADPCM_IMA_APM, + .video_codec = AV_CODEC_ID_NONE, + .init = apm_write_init, + .write_header = apm_write_header, + .write_packet = ff_raw_write_packet, + .write_trailer = apm_write_trailer +}; +#endif diff -Nru ffmpeg-4.2.2/libavformat/apngdec.c ffmpeg-4.4/libavformat/apngdec.c --- ffmpeg-4.2.2/libavformat/apngdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/apngdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -127,17 +127,18 @@ int new_size, ret; uint8_t *new_extradata; - if (previous_size > INT_MAX - len) + if (len > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE - previous_size) return AVERROR_INVALIDDATA; new_size = previous_size + len; new_extradata = av_realloc(par->extradata, new_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!new_extradata) return AVERROR(ENOMEM); + memset(new_extradata + new_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); par->extradata = new_extradata; par->extradata_size = new_size; - if ((ret = avio_read(pb, par->extradata + previous_size, len)) < 0) + if ((ret = ffio_read_size(pb, par->extradata + previous_size, len)) < 0) return ret; return previous_size; @@ -150,17 +151,17 @@ uint32_t len, tag; AVStream *st; int acTL_found = 0; - int64_t ret = AVERROR_INVALIDDATA; + int64_t ret; /* verify PNGSIG */ if (avio_rb64(pb) != PNGSIG) - return ret; + return AVERROR_INVALIDDATA; /* parse IHDR (must be first chunk) */ len = avio_rb32(pb); tag = avio_rl32(pb); if (len != 13 || tag != MKTAG('I', 'H', 'D', 'R')) - return ret; + return AVERROR_INVALIDDATA; st = avformat_new_stream(s, NULL); if (!st) @@ -177,27 +178,24 @@ return ret; /* extradata will contain every chunk up to the first fcTL (excluded) */ - st->codecpar->extradata = av_malloc(len + 12 + AV_INPUT_BUFFER_PADDING_SIZE); - if (!st->codecpar->extradata) - return AVERROR(ENOMEM); - st->codecpar->extradata_size = len + 12; + ret = ff_alloc_extradata(st->codecpar, len + 12); + if (ret < 0) + return ret; AV_WB32(st->codecpar->extradata, len); AV_WL32(st->codecpar->extradata+4, tag); AV_WB32(st->codecpar->extradata+8, st->codecpar->width); AV_WB32(st->codecpar->extradata+12, st->codecpar->height); - if ((ret = avio_read(pb, st->codecpar->extradata+16, 9)) < 0) - goto fail; + if ((ret = ffio_read_size(pb, st->codecpar->extradata + 16, 9)) < 0) + return ret; - while (!avio_feof(pb)) { + while (1) { if (acTL_found && ctx->num_play != 1) { int64_t size = avio_size(pb); int64_t offset = avio_tell(pb); if (size < 0) { - ret = size; - goto fail; + return size; } else if (offset < 0) { - ret = offset; - goto fail; + return offset; } else if ((ret = ffio_ensure_seekback(pb, size - offset)) < 0) { av_log(s, AV_LOG_WARNING, "Could not ensure seekback, will not loop\n"); ctx->num_play = 1; @@ -205,20 +203,18 @@ } if ((ctx->num_play == 1 || !acTL_found) && ((ret = ffio_ensure_seekback(pb, 4 /* len */ + 4 /* tag */)) < 0)) - goto fail; + return ret; len = avio_rb32(pb); - if (len > 0x7fffffff) { - ret = AVERROR_INVALIDDATA; - goto fail; - } + if (len > INT_MAX - 12) + return AVERROR_INVALIDDATA; tag = avio_rl32(pb); switch (tag) { case MKTAG('a', 'c', 'T', 'L'): if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 || (ret = append_extradata(st->codecpar, pb, len + 12)) < 0) - goto fail; + return ret; acTL_found = 1; ctx->num_frames = AV_RB32(st->codecpar->extradata + ret + 8); ctx->num_play = AV_RB32(st->codecpar->extradata + ret + 12); @@ -226,26 +222,18 @@ ctx->num_frames, ctx->num_play); break; case MKTAG('f', 'c', 'T', 'L'): - if (!acTL_found) { - ret = AVERROR_INVALIDDATA; - goto fail; + if (!acTL_found || len != 26) { + return AVERROR_INVALIDDATA; } if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0) - goto fail; + return ret; return 0; default: if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 || (ret = append_extradata(st->codecpar, pb, len + 12)) < 0) - goto fail; + return ret; } } - -fail: - if (st->codecpar->extradata_size) { - av_freep(&st->codecpar->extradata); - st->codecpar->extradata_size = 0; - } - return ret; } static int decode_fctl_chunk(AVFormatContext *s, APNGDemuxContext *ctx, AVPacket *pkt) diff -Nru ffmpeg-4.2.2/libavformat/apngenc.c ffmpeg-4.4/libavformat/apngenc.c --- ffmpeg-4.2.2/libavformat/apngenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavformat/apngenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -119,7 +119,7 @@ AVIOContext *io_context = format_context->pb; AVStream *codec_stream = format_context->streams[0]; uint8_t *side_data = NULL; - int side_data_size = 0; + buffer_size_t side_data_size; av_assert0(apng->prev_packet); @@ -251,7 +251,6 @@ if (apng->prev_packet) { ret = flush_packet(format_context, NULL); - av_freep(&apng->prev_packet); if (ret < 0) return ret; } @@ -266,12 +265,18 @@ apng_write_chunk(io_context, MKBETAG('a', 'c', 'T', 'L'), buf, 8); } - av_freep(&apng->extra_data); - apng->extra_data = 0; - return 0; } +static void apng_deinit(AVFormatContext *s) +{ + APNGMuxContext *apng = s->priv_data; + + av_packet_free(&apng->prev_packet); + av_freep(&apng->extra_data); + apng->extra_data_size = 0; +} + #define OFFSET(x) offsetof(APNGMuxContext, x) #define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { @@ -300,6 +305,7 @@ .write_header = apng_write_header, .write_packet = apng_write_packet, .write_trailer = apng_write_trailer, + .deinit = apng_deinit, .priv_class = &apng_muxer_class, .flags = AVFMT_VARIABLE_FPS, }; diff -Nru ffmpeg-4.2.2/libavformat/aqtitledec.c ffmpeg-4.4/libavformat/aqtitledec.c --- ffmpeg-4.2.2/libavformat/aqtitledec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/aqtitledec.c 2020-07-09 09:17:49.000000000 +0000 @@ -81,11 +81,11 @@ if (!new_event) { sub = ff_subtitles_queue_insert(&aqt->q, "\n", 1, 1); if (!sub) - return AVERROR(ENOMEM); + goto fail; } sub = ff_subtitles_queue_insert(&aqt->q, line, strlen(line), !new_event); if (!sub) - return AVERROR(ENOMEM); + goto fail; if (new_event) { sub->pts = frame; sub->duration = -1; @@ -97,6 +97,9 @@ ff_subtitles_queue_finalize(s, &aqt->q); return 0; +fail: + ff_subtitles_queue_clean(&aqt->q); + return AVERROR(ENOMEM); } static int aqt_read_packet(AVFormatContext *s, AVPacket *pkt) diff -Nru ffmpeg-4.2.2/libavformat/argo_asf.c ffmpeg-4.4/libavformat/argo_asf.c --- ffmpeg-4.2.2/libavformat/argo_asf.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/argo_asf.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,487 @@ +/* + * Argonaut Games ASF (de)muxer + * + * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.com) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "avformat.h" +#include "internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/avassert.h" +#include "libavutil/opt.h" +#include "argo_asf.h" + +/* Maximum number of blocks to read at once. */ +#define ASF_NB_BLOCKS 32 + +typedef struct ArgoASFDemuxContext { + ArgoASFFileHeader fhdr; + ArgoASFChunkHeader ckhdr; + uint32_t blocks_read; +} ArgoASFDemuxContext; + +typedef struct ArgoASFMuxContext { + const AVClass *class; + int version_major; + int version_minor; + const char *name; + int64_t nb_blocks; +} ArgoASFMuxContext; + +void ff_argo_asf_parse_file_header(ArgoASFFileHeader *hdr, const uint8_t *buf) +{ + hdr->magic = AV_RL32(buf + 0); + hdr->version_major = AV_RL16(buf + 4); + hdr->version_minor = AV_RL16(buf + 6); + hdr->num_chunks = AV_RL32(buf + 8); + hdr->chunk_offset = AV_RL32(buf + 12); + for (int i = 0; i < FF_ARRAY_ELEMS(hdr->name); i++) + hdr->name[i] = AV_RL8(buf + 16 + i); +} + +int ff_argo_asf_validate_file_header(AVFormatContext *s, const ArgoASFFileHeader *hdr) +{ + if (hdr->magic != ASF_TAG || hdr->num_chunks == 0) + return AVERROR_INVALIDDATA; + + if (hdr->chunk_offset < ASF_FILE_HEADER_SIZE) + return AVERROR_INVALIDDATA; + + return 0; +} + +void ff_argo_asf_parse_chunk_header(ArgoASFChunkHeader *hdr, const uint8_t *buf) +{ + hdr->num_blocks = AV_RL32(buf + 0); + hdr->num_samples = AV_RL32(buf + 4); + hdr->unk1 = AV_RL32(buf + 8); + hdr->sample_rate = AV_RL16(buf + 12); + hdr->unk2 = AV_RL16(buf + 14); + hdr->flags = AV_RL32(buf + 16); +} + +int ff_argo_asf_fill_stream(AVFormatContext *s, AVStream *st, const ArgoASFFileHeader *fhdr, + const ArgoASFChunkHeader *ckhdr) +{ + if (ckhdr->num_samples != ASF_SAMPLE_COUNT) { + av_log(s, AV_LOG_ERROR, "Invalid sample count. Got %u, expected %d\n", + ckhdr->num_samples, ASF_SAMPLE_COUNT); + return AVERROR_INVALIDDATA; + } + + if ((ckhdr->flags & ASF_CF_ALWAYS1) != ASF_CF_ALWAYS1 || (ckhdr->flags & ASF_CF_ALWAYS0) != 0) { + avpriv_request_sample(s, "Nonstandard flags (0x%08X)", ckhdr->flags); + return AVERROR_PATCHWELCOME; + } + + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_ARGO; + st->codecpar->format = AV_SAMPLE_FMT_S16P; + + if (ckhdr->flags & ASF_CF_STEREO) { + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->channels = 2; + } else { + st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->channels = 1; + } + + /* v1.1 files (FX Fighter) are all marked as 44100, but are actually 22050. */ + if (fhdr->version_major == 1 && fhdr->version_minor == 1) + st->codecpar->sample_rate = 22050; + else + st->codecpar->sample_rate = ckhdr->sample_rate; + + st->codecpar->bits_per_coded_sample = 4; + + if (ckhdr->flags & ASF_CF_BITS_PER_SAMPLE) + st->codecpar->bits_per_raw_sample = 16; + else + st->codecpar->bits_per_raw_sample = 8; + + if (st->codecpar->bits_per_raw_sample != 16) { + /* The header allows for these, but I've never seen any files with them. */ + avpriv_request_sample(s, "Non 16-bit samples"); + return AVERROR_PATCHWELCOME; + } + + /* + * (nchannel control bytes) + ((bytes_per_channel) * nchannel) + * For mono, this is 17. For stereo, this is 34. + */ + st->codecpar->block_align = st->codecpar->channels + + (ckhdr->num_samples / 2) * + st->codecpar->channels; + + st->codecpar->bit_rate = st->codecpar->channels * + st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample; + + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); + st->start_time = 0; + + if (fhdr->num_chunks == 1) { + st->duration = ckhdr->num_blocks * ckhdr->num_samples; + st->nb_frames = ckhdr->num_blocks; + } + + return 0; +} + +#if CONFIG_ARGO_ASF_DEMUXER +/* + * Known versions: + * 1.1: https://samples.ffmpeg.org/game-formats/brender/part2.zip + * FX Fighter + * 1.2: Croc! Legend of the Gobbos + * 2.1: Croc 2 + * The Emperor's New Groove + * Disney's Aladdin in Nasira's Revenge + */ +static int argo_asf_is_known_version(const ArgoASFFileHeader *hdr) +{ + return (hdr->version_major == 1 && hdr->version_minor == 1) || + (hdr->version_major == 1 && hdr->version_minor == 2) || + (hdr->version_major == 2 && hdr->version_minor == 1); +} + +static int argo_asf_probe(const AVProbeData *p) +{ + ArgoASFFileHeader hdr; + + av_assert0(AVPROBE_PADDING_SIZE >= ASF_FILE_HEADER_SIZE); + + ff_argo_asf_parse_file_header(&hdr, p->buf); + + if (hdr.magic != ASF_TAG) + return 0; + + if (!argo_asf_is_known_version(&hdr)) + return AVPROBE_SCORE_EXTENSION / 2; + + return AVPROBE_SCORE_EXTENSION + 1; +} + +static int argo_asf_read_header(AVFormatContext *s) +{ + int64_t ret; + AVIOContext *pb = s->pb; + AVStream *st; + ArgoASFDemuxContext *asf = s->priv_data; + uint8_t buf[ASF_MIN_BUFFER_SIZE]; + + if (!(st = avformat_new_stream(s, NULL))) + return AVERROR(ENOMEM); + + if ((ret = avio_read(pb, buf, ASF_FILE_HEADER_SIZE)) < 0) + return ret; + else if (ret != ASF_FILE_HEADER_SIZE) + return AVERROR(EIO); + + ff_argo_asf_parse_file_header(&asf->fhdr, buf); + + if ((ret = ff_argo_asf_validate_file_header(s, &asf->fhdr)) < 0) + return ret; + + /* This should only be 1 in ASF files. >1 is fine if in BRP. */ + if (asf->fhdr.num_chunks != 1) + return AVERROR_INVALIDDATA; + + if ((ret = avio_skip(pb, asf->fhdr.chunk_offset - ASF_FILE_HEADER_SIZE)) < 0) + return ret; + + if ((ret = avio_read(pb, buf, ASF_CHUNK_HEADER_SIZE)) < 0) + return ret; + else if (ret != ASF_CHUNK_HEADER_SIZE) + return AVERROR(EIO); + + ff_argo_asf_parse_chunk_header(&asf->ckhdr, buf); + + return ff_argo_asf_fill_stream(s, st, &asf->fhdr, &asf->ckhdr); +} + +static int argo_asf_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + ArgoASFDemuxContext *asf = s->priv_data; + + AVStream *st = s->streams[0]; + AVIOContext *pb = s->pb; + int ret; + + if (asf->blocks_read >= asf->ckhdr.num_blocks) + return AVERROR_EOF; + + ret = av_get_packet(pb, pkt, st->codecpar->block_align * + FFMIN(ASF_NB_BLOCKS, asf->ckhdr.num_blocks - asf->blocks_read)); + if (ret < 0) + return ret; + + /* Something real screwy is going on. */ + if (ret % st->codecpar->block_align != 0) + return AVERROR_INVALIDDATA; + + + pkt->stream_index = st->index; + pkt->duration = asf->ckhdr.num_samples * (ret / st->codecpar->block_align); + pkt->pts = asf->blocks_read * asf->ckhdr.num_samples; + asf->blocks_read += (ret / st->codecpar->block_align); + + pkt->flags &= ~AV_PKT_FLAG_CORRUPT; + return 0; +} + +static int argo_asf_seek(AVFormatContext *s, int stream_index, + int64_t pts, int flags) +{ + ArgoASFDemuxContext *asf = s->priv_data; + AVStream *st = s->streams[stream_index]; + int64_t offset; + uint32_t block = pts / asf->ckhdr.num_samples; + + if (block >= asf->ckhdr.num_blocks) + return -1; + + offset = asf->fhdr.chunk_offset + ASF_CHUNK_HEADER_SIZE + + (block * st->codecpar->block_align); + + if ((offset = avio_seek(s->pb, offset, SEEK_SET)) < 0) + return offset; + + asf->blocks_read = block; + return 0; +} + +/* + * Not actually sure what ASF stands for. + * - Argonaut Sound File? + * - Audio Stream File? + */ +AVInputFormat ff_argo_asf_demuxer = { + .name = "argo_asf", + .long_name = NULL_IF_CONFIG_SMALL("Argonaut Games ASF"), + .priv_data_size = sizeof(ArgoASFDemuxContext), + .read_probe = argo_asf_probe, + .read_header = argo_asf_read_header, + .read_packet = argo_asf_read_packet, + .read_seek = argo_asf_seek, +}; +#endif + +#if CONFIG_ARGO_ASF_MUXER +static int argo_asf_write_init(AVFormatContext *s) +{ + ArgoASFMuxContext *ctx = s->priv_data; + const AVCodecParameters *par; + + if (s->nb_streams != 1) { + av_log(s, AV_LOG_ERROR, "ASF files have exactly one stream\n"); + return AVERROR(EINVAL); + } + + par = s->streams[0]->codecpar; + + if (par->codec_id != AV_CODEC_ID_ADPCM_ARGO) { + av_log(s, AV_LOG_ERROR, "%s codec not supported\n", + avcodec_get_name(par->codec_id)); + return AVERROR(EINVAL); + } + + if (ctx->version_major == 1 && ctx->version_minor == 1 && par->sample_rate != 22050) { + av_log(s, AV_LOG_ERROR, "ASF v1.1 files only support a sample rate of 22050\n"); + return AVERROR(EINVAL); + } + + if (par->channels > 2) { + av_log(s, AV_LOG_ERROR, "ASF files only support up to 2 channels\n"); + return AVERROR(EINVAL); + } + + if (par->block_align != 17 * par->channels) + return AVERROR(EINVAL); + + if (par->sample_rate > UINT16_MAX) { + av_log(s, AV_LOG_ERROR, "Sample rate too large\n"); + return AVERROR(EINVAL); + } + + if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) { + av_log(s, AV_LOG_ERROR, "Stream not seekable, unable to write output file\n"); + return AVERROR(EINVAL); + } + + return 0; +} + +static void argo_asf_write_file_header(const ArgoASFFileHeader *fhdr, AVIOContext *pb) +{ + avio_wl32( pb, fhdr->magic); + avio_wl16( pb, fhdr->version_major); + avio_wl16( pb, fhdr->version_minor); + avio_wl32( pb, fhdr->num_chunks); + avio_wl32( pb, fhdr->chunk_offset); + avio_write(pb, fhdr->name, sizeof(fhdr->name)); +} + +static void argo_asf_write_chunk_header(const ArgoASFChunkHeader *ckhdr, AVIOContext *pb) +{ + avio_wl32(pb, ckhdr->num_blocks); + avio_wl32(pb, ckhdr->num_samples); + avio_wl32(pb, ckhdr->unk1); + avio_wl16(pb, ckhdr->sample_rate); + avio_wl16(pb, ckhdr->unk2); + avio_wl32(pb, ckhdr->flags); +} + +static int argo_asf_write_header(AVFormatContext *s) +{ + const AVCodecParameters *par = s->streams[0]->codecpar; + ArgoASFMuxContext *ctx = s->priv_data; + ArgoASFChunkHeader chdr; + ArgoASFFileHeader fhdr = { + .magic = ASF_TAG, + .version_major = (uint16_t)ctx->version_major, + .version_minor = (uint16_t)ctx->version_minor, + .num_chunks = 1, + .chunk_offset = ASF_FILE_HEADER_SIZE + }; + + /* + * If the user specified a name, use it as is. Otherwise take the + * basename and lop off the extension (if any). + */ + if (ctx->name) { + strncpy(fhdr.name, ctx->name, sizeof(fhdr.name)); + } else { + const char *start = av_basename(s->url); + const char *end = strrchr(start, '.'); + size_t len; + + if (end) + len = end - start; + else + len = strlen(start); + + memcpy(fhdr.name, start, FFMIN(len, sizeof(fhdr.name))); + } + + chdr.num_blocks = 0; + chdr.num_samples = ASF_SAMPLE_COUNT; + chdr.unk1 = 0; + + if (ctx->version_major == 1 && ctx->version_minor == 1) + chdr.sample_rate = 44100; + else + chdr.sample_rate = par->sample_rate; + + chdr.unk2 = ~0; + chdr.flags = ASF_CF_BITS_PER_SAMPLE | ASF_CF_ALWAYS1; + + if (par->channels == 2) + chdr.flags |= ASF_CF_STEREO; + + argo_asf_write_file_header(&fhdr, s->pb); + argo_asf_write_chunk_header(&chdr, s->pb); + return 0; +} + +static int argo_asf_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + ArgoASFMuxContext *ctx = s->priv_data; + AVCodecParameters *par = s->streams[0]->codecpar; + int nb_blocks = pkt->size / par->block_align; + + if (pkt->size % par->block_align != 0) + return AVERROR_INVALIDDATA; + + if (ctx->nb_blocks + nb_blocks > UINT32_MAX) + return AVERROR_INVALIDDATA; + + avio_write(s->pb, pkt->data, pkt->size); + + ctx->nb_blocks += nb_blocks; + return 0; +} + +static int argo_asf_write_trailer(AVFormatContext *s) +{ + ArgoASFMuxContext *ctx = s->priv_data; + int64_t ret; + + if ((ret = avio_seek(s->pb, ASF_FILE_HEADER_SIZE, SEEK_SET) < 0)) + return ret; + + avio_wl32(s->pb, (uint32_t)ctx->nb_blocks); + return 0; +} + +static const AVOption argo_asf_options[] = { + { + .name = "version_major", + .help = "override file major version", + .offset = offsetof(ArgoASFMuxContext, version_major), + .type = AV_OPT_TYPE_INT, + .default_val = {.i64 = 2}, + .min = 0, + .max = UINT16_MAX, + .flags = AV_OPT_FLAG_ENCODING_PARAM + }, + { + .name = "version_minor", + .help = "override file minor version", + .offset = offsetof(ArgoASFMuxContext, version_minor), + .type = AV_OPT_TYPE_INT, + .default_val = {.i64 = 1}, + .min = 0, + .max = UINT16_MAX, + .flags = AV_OPT_FLAG_ENCODING_PARAM + }, + { + .name = "name", + .help = "embedded file name (max 8 characters)", + .offset = offsetof(ArgoASFMuxContext, name), + .type = AV_OPT_TYPE_STRING, + .default_val = {.str = NULL}, + .flags = AV_OPT_FLAG_ENCODING_PARAM + }, + { NULL } +}; + +static const AVClass argo_asf_muxer_class = { + .class_name = "argo_asf_muxer", + .item_name = av_default_item_name, + .option = argo_asf_options, + .version = LIBAVUTIL_VERSION_INT +}; + +AVOutputFormat ff_argo_asf_muxer = { + .name = "argo_asf", + .long_name = NULL_IF_CONFIG_SMALL("Argonaut Games ASF"), + /* + * NB: Can't do this as it conflicts with the actual ASF format. + * .extensions = "asf", + */ + .audio_codec = AV_CODEC_ID_ADPCM_ARGO, + .video_codec = AV_CODEC_ID_NONE, + .init = argo_asf_write_init, + .write_header = argo_asf_write_header, + .write_packet = argo_asf_write_packet, + .write_trailer = argo_asf_write_trailer, + .priv_class = &argo_asf_muxer_class, + .priv_data_size = sizeof(ArgoASFMuxContext) +}; +#endif diff -Nru ffmpeg-4.2.2/libavformat/argo_asf.h ffmpeg-4.4/libavformat/argo_asf.h --- ffmpeg-4.2.2/libavformat/argo_asf.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/argo_asf.h 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * Argonaut Games ASF (de)muxer + * + * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.com) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_ARGO_ASF_H +#define AVFORMAT_ARGO_ASF_H + +#include +#include "libavutil/common.h" + +#include "avformat.h" + +#define ASF_TAG MKTAG('A', 'S', 'F', '\0') +#define ASF_FILE_HEADER_SIZE 24 +#define ASF_CHUNK_HEADER_SIZE 20 +#define ASF_SAMPLE_COUNT 32 +#define ASF_MIN_BUFFER_SIZE FFMAX(ASF_FILE_HEADER_SIZE, ASF_CHUNK_HEADER_SIZE) + +typedef struct ArgoASFFileHeader { + uint32_t magic; /*< Magic Number, {'A', 'S', 'F', '\0'} */ + uint16_t version_major; /*< File Major Version. */ + uint16_t version_minor; /*< File Minor Version. */ + uint32_t num_chunks; /*< No. chunks in the file. */ + uint32_t chunk_offset; /*< Offset to the first chunk from the start of the file. */ + int8_t name[8]; /*< Name. */ +} ArgoASFFileHeader; + +typedef struct ArgoASFChunkHeader { + uint32_t num_blocks; /*< No. blocks in the chunk. */ + uint32_t num_samples; /*< No. samples per channel in a block. Always 32. */ + uint32_t unk1; /*< Unknown */ + uint16_t sample_rate; /*< Sample rate. */ + uint16_t unk2; /*< Unknown. */ + uint32_t flags; /*< Stream flags. */ +} ArgoASFChunkHeader; + +enum { + ASF_CF_BITS_PER_SAMPLE = (1 << 0), /*< 16-bit if set, 8 otherwise. */ + ASF_CF_STEREO = (1 << 1), /*< Stereo if set, mono otherwise. */ + ASF_CF_ALWAYS1_1 = (1 << 2), /*< Unknown, always seems to be set. */ + ASF_CF_ALWAYS1_2 = (1 << 3), /*< Unknown, always seems to be set. */ + + ASF_CF_ALWAYS1 = ASF_CF_ALWAYS1_1 | ASF_CF_ALWAYS1_2, + ASF_CF_ALWAYS0 = ~(ASF_CF_BITS_PER_SAMPLE | ASF_CF_STEREO | ASF_CF_ALWAYS1) +}; + +void ff_argo_asf_parse_file_header(ArgoASFFileHeader *hdr, const uint8_t *buf); +int ff_argo_asf_validate_file_header(AVFormatContext *s, const ArgoASFFileHeader *hdr); +void ff_argo_asf_parse_chunk_header(ArgoASFChunkHeader *hdr, const uint8_t *buf); +int ff_argo_asf_fill_stream(AVFormatContext *s, AVStream *st, const ArgoASFFileHeader *fhdr, + const ArgoASFChunkHeader *ckhdr); + +#endif /* AVFORMAT_ARGO_ASF_H */ diff -Nru ffmpeg-4.2.2/libavformat/argo_brp.c ffmpeg-4.4/libavformat/argo_brp.c --- ffmpeg-4.2.2/libavformat/argo_brp.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/argo_brp.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,423 @@ +/* + * Argonaut Games BRP Demuxer + * + * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.com) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/avassert.h" +#include "libavutil/internal.h" +#include "argo_asf.h" + +#define BRP_TAG MKTAG('B', 'R', 'P', 'P') +#define BRP_FILE_HEADER_SIZE 12 +#define BRP_BLOCK_HEADER_SIZE 12 +#define BRP_STREAM_HEADER_SIZE 20 +#define BRP_MAX_STREAMS 32 /* Soft cap, but even this is overkill. */ +#define BRP_BASF_LOOKAHEAD 10 /* How many blocks to search for the first BASF one. */ +#define BVID_HEADER_SIZE 16 +#define MASK_HEADER_SIZE 12 +#define BRP_MIN_BUFFER_SIZE FFMAX3(FFMAX3(BRP_FILE_HEADER_SIZE, \ + BRP_BLOCK_HEADER_SIZE, \ + BRP_STREAM_HEADER_SIZE), \ + BVID_HEADER_SIZE, \ + MASK_HEADER_SIZE) + +#define BRP_CODEC_ID_BVID MKTAG('B', 'V', 'I', 'D') +#define BRP_CODEC_ID_BASF MKTAG('B', 'A', 'S', 'F') +#define BRP_CODEC_ID_MASK MKTAG('M', 'A', 'S', 'K') + +typedef struct ArgoBRPFileHeader { + uint32_t magic; + uint32_t num_streams; + uint32_t byte_rate; +} ArgoBRPFileHeader; + +typedef struct ArgoBRPBlockHeader { + int32_t stream_id; + uint32_t start_ms; + uint32_t size; +} ArgoBRPBlockHeader; + +typedef struct ArgoBVIDHeader { + uint32_t num_frames; + uint32_t width; + uint32_t height; + uint32_t depth; +} ArgoBVIDHeader; + +typedef struct ArgoMASKHeader { + uint32_t num_frames; + uint32_t width; + uint32_t height; +} ArgoMASKHeader; + +typedef struct ArgoBRPStreamHeader { + uint32_t codec_id; + uint32_t id; + uint32_t duration_ms; + uint32_t byte_rate; + uint32_t extradata_size; + union + { + /* If codec_id == BRP_CODEC_ID_BVID */ + ArgoBVIDHeader bvid; + /* If codec_id == BRP_CODEC_ID_BASF */ + ArgoASFFileHeader basf; + /* If codec_id == BRP_CODEC_ID_MASK */ + ArgoMASKHeader mask; + } extradata; +} ArgoBRPStreamHeader; + +typedef struct ArgoBRPDemuxContext { + ArgoBRPFileHeader fhdr; + ArgoBRPStreamHeader streams[BRP_MAX_STREAMS]; + + struct { + int index; + ArgoASFChunkHeader ckhdr; + } basf; +} ArgoBRPDemuxContext; + +static int argo_brp_probe(const AVProbeData *p) +{ + if (AV_RL32(p->buf) != BRP_TAG) + return 0; + + return AVPROBE_SCORE_EXTENSION + 1; +} + +static int read_extradata(AVFormatContext *s, const ArgoBRPStreamHeader *hdr, + void *buf, size_t bufsz) +{ + const char *name; + uint32_t size; + int64_t ret; + + if (hdr->codec_id == BRP_CODEC_ID_BVID) { + name = "BVID"; + size = BVID_HEADER_SIZE; + } else if (hdr->codec_id == BRP_CODEC_ID_BASF) { + name = "BASF"; + size = ASF_FILE_HEADER_SIZE; + } else if (hdr->codec_id == BRP_CODEC_ID_MASK) { + name = "MASK"; + size = MASK_HEADER_SIZE; + } else { + avpriv_request_sample(s, "BRP codec id 0x%x", hdr->codec_id); + + if ((ret = avio_skip(s->pb, hdr->extradata_size)) < 0) + return ret; + + return 1; + } + + if (hdr->extradata_size != size) { + av_log(s, AV_LOG_ERROR, "Invalid %s extradata size %u, expected %u\n", + name, hdr->extradata_size, size); + return AVERROR_INVALIDDATA; + } + + av_assert0(bufsz >= size); + + if ((ret = avio_read(s->pb, buf, size)) < 0) + return ret; + + if (ret != size) + return AVERROR(EIO); + + return 0; +} + +static int argo_brp_read_header(AVFormatContext *s) +{ + int64_t ret; + AVIOContext *pb = s->pb; + ArgoBRPDemuxContext *brp = s->priv_data; + uint8_t buf[FFMAX(BRP_MIN_BUFFER_SIZE, ASF_MIN_BUFFER_SIZE)]; + + if ((ret = avio_read(pb, buf, BRP_FILE_HEADER_SIZE)) < 0) + return ret; + else if (ret != BRP_FILE_HEADER_SIZE) + return AVERROR(EIO); + + brp->fhdr.magic = AV_RL32(buf + 0); + brp->fhdr.num_streams = AV_RL32(buf + 4); + brp->fhdr.byte_rate = AV_RL32(buf + 8); + + if (brp->fhdr.magic != BRP_TAG) + return AVERROR_INVALIDDATA; + + if (brp->fhdr.num_streams > BRP_MAX_STREAMS) { + avpriv_request_sample(s, ">%d streams", BRP_MAX_STREAMS); + return AVERROR_PATCHWELCOME; + } + + /* Build the stream info. */ + brp->basf.index = -1; + for (uint32_t i = 0; i < brp->fhdr.num_streams; i++) { + ArgoBRPStreamHeader *hdr = brp->streams + i; + AVStream *st; + + if (!(st = avformat_new_stream(s, NULL))) + return AVERROR(ENOMEM); + + if ((ret = avio_read(pb, buf, BRP_STREAM_HEADER_SIZE)) < 0) + return ret; + else if (ret != BRP_STREAM_HEADER_SIZE) + return AVERROR(EIO); + + hdr->codec_id = AV_RL32(buf + 0); + hdr->id = AV_RL32(buf + 4); + hdr->duration_ms = AV_RL32(buf + 8); + hdr->byte_rate = AV_RL32(buf + 12); + hdr->extradata_size = AV_RL32(buf + 16); + + /* This should always be the case. */ + if (hdr->id != i) + return AVERROR_INVALIDDATA; + + /* Timestamps are in milliseconds. */ + avpriv_set_pts_info(st, 64, 1, 1000); + st->duration = hdr->duration_ms; + st->codecpar->bit_rate = hdr->byte_rate * 8; + + if ((ret = read_extradata(s, hdr, buf, sizeof(buf))) < 0) { + return ret; + } else if (ret > 0) { + st->codecpar->codec_type = AVMEDIA_TYPE_UNKNOWN; + continue; + } + + if (hdr->codec_id == BRP_CODEC_ID_BVID) { + ArgoBVIDHeader *bvid = &hdr->extradata.bvid; + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_ARGO; + + bvid->num_frames = AV_RL32(buf + 0); + bvid->width = AV_RL32(buf + 4); + bvid->height = AV_RL32(buf + 8); + bvid->depth = AV_RL32(buf + 12); + + if (bvid->num_frames == 0) + return AVERROR_INVALIDDATA; + + /* These are from 1990's games, sanity check this. */ + if (bvid->width >= 65536 || bvid->height >= 65536 || + bvid->depth > 24 || bvid->depth % 8 != 0) { + return AVERROR_INVALIDDATA; + } + + st->codecpar->width = bvid->width; + st->codecpar->height = bvid->height; + st->nb_frames = bvid->num_frames; + st->codecpar->bits_per_raw_sample = bvid->depth; + } else if (hdr->codec_id == BRP_CODEC_ID_BASF) { + /* + * It would make the demuxer significantly more complicated + * to support multiple BASF streams. I've never seen a file + * with more than one. + */ + if (brp->basf.index >= 0) { + avpriv_request_sample(s, "Multiple BASF streams"); + return AVERROR_PATCHWELCOME; + } + + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_ARGO; + brp->basf.index = i; + ff_argo_asf_parse_file_header(&hdr->extradata.basf, buf); + + if ((ret = ff_argo_asf_validate_file_header(s, &hdr->extradata.basf)) < 0) + return ret; + + st->nb_frames = hdr->extradata.basf.num_chunks; + } else if (hdr->codec_id == BRP_CODEC_ID_MASK) { + ArgoMASKHeader *mask = &hdr->extradata.mask; + + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; + + mask->num_frames = AV_RL32(buf + 0); + mask->width = AV_RL32(buf + 4); + mask->height = AV_RL32(buf + 8); + + st->nb_frames = mask->num_frames; + } else { + av_assert0(0); /* Caught above, should never happen. */ + } + } + + /* Try to find the first BASF chunk. */ + if (brp->basf.index >= 0) { + AVStream *st = s->streams[brp->basf.index]; + ArgoBRPStreamHeader *hdr = brp->streams + brp->basf.index; + ArgoBRPBlockHeader blk; + int64_t offset; + int i; + + av_assert0(st->codecpar->codec_id == AV_CODEC_ID_ADPCM_ARGO); + av_assert0(brp->streams[brp->basf.index].extradata_size == ASF_FILE_HEADER_SIZE); + + if ((ret = avio_tell(s->pb)) < 0) + return ret; + + offset = ret; + + av_log(s, AV_LOG_TRACE, "Searching %d blocks for BASF...", BRP_BASF_LOOKAHEAD); + + for (i = 0; i < BRP_BASF_LOOKAHEAD; i++) { + if ((ret = avio_read(pb, buf, BRP_BLOCK_HEADER_SIZE)) < 0) + return ret; + else if (ret != BRP_BLOCK_HEADER_SIZE) + return AVERROR(EIO); + + blk.stream_id = AV_RL32(buf + 0); + blk.start_ms = AV_RL32(buf + 4); + blk.size = AV_RL32(buf + 8); + + if (blk.stream_id == brp->basf.index || blk.stream_id == -1) + break; + + if ((ret = avio_skip(pb, blk.size)) < 0) + return ret; + } + + if (i == BRP_BASF_LOOKAHEAD || blk.stream_id == -1) { + /* Don't error here, as there may still be a valid video stream. */ + av_log(s, AV_LOG_TRACE, "not found\n"); + goto done; + } + + av_log(s, AV_LOG_TRACE, "found at index %d\n", i); + + if (blk.size < ASF_CHUNK_HEADER_SIZE) + return AVERROR_INVALIDDATA; + + if ((ret = avio_read(pb, buf, ASF_CHUNK_HEADER_SIZE)) < 0) + return ret; + else if (ret != ASF_CHUNK_HEADER_SIZE) + return AVERROR(EIO); + + ff_argo_asf_parse_chunk_header(&brp->basf.ckhdr, buf); + + /* + * Special Case Hack. It seems that in files where the BASF block isn't first, + * v1.1 streams are allowed to be non-22050... + * Bump the version to 1.2 so ff_argo_asf_fill_stream() doesn't "correct" it. + * + * Found in Alien Odyssey games files in: + * ./GRAPHICS/COMMBUNK/{{COMADD1,COMM2_{1,2,3E},COMM3_{2,3,4,5,6}},FADE{1,2}}.BRP + * + * Either this format really inconsistent, or FX Fighter and Croc just ignored the + * sample rate field... + */ + if (i != 0 && hdr->extradata.basf.version_major == 1 && hdr->extradata.basf.version_minor == 1) + hdr->extradata.basf.version_minor = 2; + + if ((ret = ff_argo_asf_fill_stream(s, st, &hdr->extradata.basf, &brp->basf.ckhdr)) < 0) + return ret; + + /* Convert ms to samples. */ + st->start_time = av_rescale_rnd(blk.start_ms, st->codecpar->sample_rate, 1000, AV_ROUND_UP); + st->duration = av_rescale_rnd(hdr->duration_ms, st->codecpar->sample_rate, 1000, AV_ROUND_UP); + +done: + if ((ret = avio_seek(s->pb, offset, SEEK_SET)) < 0) + return ret; + } + return 0; +} + +static int argo_brp_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + ArgoBRPDemuxContext *brp = s->priv_data; + ArgoBRPBlockHeader blk; + const ArgoBRPStreamHeader *shdr; + AVStream *st; + uint8_t buf[BRP_MIN_BUFFER_SIZE]; + ArgoASFChunkHeader ckhdr; + int ret; + + if ((ret = avio_read(s->pb, buf, BRP_BLOCK_HEADER_SIZE)) < 0) + return ret; + else if (ret != BRP_BLOCK_HEADER_SIZE) + return AVERROR(EIO); + + blk.stream_id = AV_RL32(buf + 0); + blk.start_ms = AV_RL32(buf + 4); + blk.size = AV_RL32(buf + 8); + + if (blk.stream_id == -1) + return AVERROR_EOF; + + if (blk.stream_id < -1 || blk.stream_id >= s->nb_streams) + return AVERROR_INVALIDDATA; + + st = s->streams[blk.stream_id]; + shdr = brp->streams + blk.stream_id; + + if (blk.stream_id == brp->basf.index) { + if (blk.size < ASF_CHUNK_HEADER_SIZE) + return AVERROR_INVALIDDATA; + + if ((ret = avio_read(s->pb, buf, ASF_CHUNK_HEADER_SIZE)) < 0) + return ret; + + ff_argo_asf_parse_chunk_header(&ckhdr, buf); + + /* Ensure the chunk attributes are the same. */ + if (ckhdr.sample_rate != brp->basf.ckhdr.sample_rate || + ckhdr.flags != brp->basf.ckhdr.flags || + ckhdr.unk1 != brp->basf.ckhdr.unk1 || + ckhdr.unk2 != brp->basf.ckhdr.unk2) + return AVERROR_INVALIDDATA; + + blk.size -= ASF_CHUNK_HEADER_SIZE; + } + + if ((ret = av_get_packet(s->pb, pkt, blk.size)) < 0) + return ret; + else if (ret != blk.size) + return AVERROR_INVALIDDATA; + + if (blk.stream_id == brp->basf.index) { + pkt->duration = ckhdr.num_samples * ckhdr.num_blocks; + pkt->pts = av_rescale_rnd(blk.start_ms, ckhdr.sample_rate, 1000, AV_ROUND_UP); + } else if (shdr->codec_id == BRP_CODEC_ID_BVID) { + pkt->duration = av_rescale_rnd(1, st->duration, shdr->extradata.bvid.num_frames, AV_ROUND_UP); + pkt->pts = blk.start_ms; + } else { + pkt->pts = blk.start_ms; + } + + pkt->stream_index = blk.stream_id; + return 0; +} + +AVInputFormat ff_argo_brp_demuxer = { + .name = "argo_brp", + .long_name = NULL_IF_CONFIG_SMALL("Argonaut Games BRP"), + .priv_data_size = sizeof(ArgoBRPDemuxContext), + .read_probe = argo_brp_probe, + .read_header = argo_brp_read_header, + .read_packet = argo_brp_read_packet, +}; diff -Nru ffmpeg-4.2.2/libavformat/asf.c ffmpeg-4.4/libavformat/asf.c --- ffmpeg-4.2.2/libavformat/asf.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/asf.c 2021-04-08 21:28:40.000000000 +0000 @@ -40,12 +40,6 @@ 0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B }; -const ff_asf_guid ff_asf_audio_conceal_none = { - // 0x40, 0xa4, 0xf1, 0x49, 0x4ece, 0x11d0, 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 - // New value lifted from avifile - 0x00, 0x57, 0xfb, 0x20, 0x55, 0x5B, 0xCF, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b -}; - const ff_asf_guid ff_asf_audio_conceal_spread = { 0x50, 0xCD, 0xC3, 0xBF, 0x8F, 0x61, 0xCF, 0x11, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20 }; diff -Nru ffmpeg-4.2.2/libavformat/asfdec_f.c ffmpeg-4.4/libavformat/asfdec_f.c --- ffmpeg-4.2.2/libavformat/asfdec_f.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/asfdec_f.c 2021-04-08 21:28:40.000000000 +0000 @@ -143,6 +143,12 @@ 0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2 }; +static const ff_asf_guid asf_audio_conceal_none = { + // 0x40, 0xa4, 0xf1, 0x49, 0x4ece, 0x11d0, 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 + // New value lifted from avifile + 0x00, 0x57, 0xfb, 0x20, 0x55, 0x5B, 0xCF, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b +}; + #define PRINT_IF_GUID(g, cmp) \ if (!ff_guidcmp(g, &cmp)) \ av_log(NULL, AV_LOG_TRACE, "(GUID: %s) ", # cmp) @@ -154,7 +160,7 @@ else PRINT_IF_GUID(g, ff_asf_file_header); else PRINT_IF_GUID(g, ff_asf_stream_header); else PRINT_IF_GUID(g, ff_asf_audio_stream); - else PRINT_IF_GUID(g, ff_asf_audio_conceal_none); + else PRINT_IF_GUID(g, asf_audio_conceal_none); else PRINT_IF_GUID(g, ff_asf_video_stream); else PRINT_IF_GUID(g, ff_asf_video_conceal_none); else PRINT_IF_GUID(g, ff_asf_command_stream); @@ -308,8 +314,8 @@ ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, len); if (id3v2_extra_meta) { - ff_id3v2_parse_apic(s, &id3v2_extra_meta); - ff_id3v2_parse_chapters(s, &id3v2_extra_meta); + ff_id3v2_parse_apic(s, id3v2_extra_meta); + ff_id3v2_parse_chapters(s, id3v2_extra_meta); } ff_id3v2_free_extra_meta(&id3v2_extra_meta); } @@ -321,8 +327,7 @@ int64_t off = avio_tell(s->pb); #define LEN 22 - if ((unsigned)len >= (UINT_MAX - LEN) / 2) - return; + av_assert0((unsigned)len < (INT_MAX - LEN) / 2); if (!asf->export_xmp && !strncmp(key, "xmp", 3)) goto finish; @@ -425,7 +430,7 @@ if (!(asf->hdr.flags & 0x01)) { // if we aren't streaming... int64_t fsize = avio_size(pb); if (fsize <= 0 || (int64_t)asf->hdr.file_size <= 0 || - 20*FFABS(fsize - (int64_t)asf->hdr.file_size) < FFMIN(fsize, asf->hdr.file_size)) + FFABS(fsize - (int64_t)asf->hdr.file_size) < FFMIN(fsize, asf->hdr.file_size)/20) st->duration = asf->hdr.play_time / (10000000 / 1000) - start_time; } @@ -480,7 +485,7 @@ if (is_dvr_ms_audio) { // codec_id and codec_tag are unreliable in dvr_ms // files. Set them later by probing stream. - st->request_probe = 1; + st->internal->request_probe = 1; st->codecpar->codec_tag = 0; } if (st->codecpar->codec_id == AV_CODEC_ID_AAC) @@ -517,6 +522,8 @@ tag1 = avio_rl32(pb); avio_skip(pb, 20); if (sizeX > 40) { + if (size < sizeX - 40) + return AVERROR_INVALIDDATA; st->codecpar->extradata_size = ffio_limit(pb, sizeX - 40); st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); @@ -608,6 +615,8 @@ ff_get_guid(pb, &g); size = avio_rl16(pb); ext_len = avio_rl32(pb); + if (ext_len < 0) + return AVERROR_INVALIDDATA; avio_skip(pb, ext_len); if (stream_num < 128 && i < FF_ARRAY_ELEMS(asf->streams[stream_num].payload)) { ASFPayload *p = &asf->streams[stream_num].payload[i]; @@ -712,6 +721,9 @@ value_type = avio_rl16(pb); /* value_type */ value_len = avio_rl32(pb); + if (value_len < 0 || value_len > UINT16_MAX) + return AVERROR_INVALIDDATA; + name_len_utf8 = 2*name_len_utf16 + 1; name = av_malloc(name_len_utf8); if (!name) @@ -767,6 +779,8 @@ avio_rl32(pb); // send time avio_rl32(pb); // flags name_len = avio_rl32(pb); // name length + if ((unsigned)name_len > INT_MAX / 2) + return AVERROR_INVALIDDATA; if ((ret = avio_get_str16le(pb, name_len * 2, name, sizeof(name))) < name_len) avio_skip(pb, name_len - ret); @@ -857,11 +871,20 @@ return ret; av_hex_dump_log(s, AV_LOG_DEBUG, pkt.data, pkt.size); av_packet_unref(&pkt); + len= avio_rl32(pb); + if (len > UINT16_MAX) + return AVERROR_INVALIDDATA; get_tag(s, "ASF_Protection_Type", -1, len, 32); + len= avio_rl32(pb); + if (len > UINT16_MAX) + return AVERROR_INVALIDDATA; get_tag(s, "ASF_Key_ID", -1, len, 32); + len= avio_rl32(pb); + if (len > UINT16_MAX) + return AVERROR_INVALIDDATA; get_tag(s, "ASF_License_URL", -1, len, 32); } else if (!ff_guidcmp(&g, &ff_asf_ext_content_encryption)) { av_log(s, AV_LOG_WARNING, diff -Nru ffmpeg-4.2.2/libavformat/asfdec_o.c ffmpeg-4.4/libavformat/asfdec_o.c --- ffmpeg-4.2.2/libavformat/asfdec_o.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/asfdec_o.c 2021-04-08 21:28:40.000000000 +0000 @@ -63,7 +63,7 @@ } GUIDParseTable; typedef struct ASFPacket { - AVPacket avpkt; + AVPacket *avpkt; int64_t dts; uint32_t frame_num; // ASF payloads with the same number are parts of the same frame int flags; @@ -245,6 +245,9 @@ avio_skip(pb, 4); // flags len = avio_rl32(pb); + if (avio_feof(pb)) + return AVERROR_INVALIDDATA; + if ((ret = avio_get_str16le(pb, len, name, sizeof(name))) < len) avio_skip(pb, len - ret); @@ -357,7 +360,6 @@ * but in reality this is only loosely similar */ static int asf_read_picture(AVFormatContext *s, int len) { - ASFContext *asf = s->priv_data; AVPacket pkt = { 0 }; const CodecMime *mime = ff_id3v2_mime_tags; enum AVCodecID id = AV_CODEC_ID_NONE; @@ -365,7 +367,6 @@ uint8_t *desc = NULL; AVStream *st = NULL; int ret, type, picsize, desc_len; - ASFStream *asf_st; /* type + picsize + mime + desc */ if (len < 1 + 4 + 2 + 2) { @@ -422,22 +423,14 @@ ret = AVERROR(ENOMEM); goto fail; } - asf->asf_st[asf->nb_streams] = av_mallocz(sizeof(*asf_st)); - asf_st = asf->asf_st[asf->nb_streams]; - if (!asf_st) { - ret = AVERROR(ENOMEM); - goto fail; - } st->disposition |= AV_DISPOSITION_ATTACHED_PIC; - st->codecpar->codec_type = asf_st->type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; st->codecpar->codec_id = id; st->attached_pic = pkt; - st->attached_pic.stream_index = asf_st->index = st->index; + st->attached_pic.stream_index = st->index; st->attached_pic.flags |= AV_PKT_FLAG_KEY; - asf->nb_streams++; - if (*desc) { if (av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL) < 0) av_log(s, AV_LOG_WARNING, "av_dict_set failed.\n"); @@ -461,8 +454,8 @@ ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, len); if (id3v2_extra_meta) { - ff_id3v2_parse_apic(s, &id3v2_extra_meta); - ff_id3v2_parse_chapters(s, &id3v2_extra_meta); + ff_id3v2_parse_apic(s, id3v2_extra_meta); + ff_id3v2_parse_chapters(s, id3v2_extra_meta); } ff_id3v2_free_extra_meta(&id3v2_extra_meta); } @@ -606,7 +599,8 @@ } else { if (st_num < ASF_MAX_STREAMS) { if ((ret = process_metadata(s, name, name_len, val_len, type, - &asf->asf_sd[st_num].asf_met)) < 0) { + st_num ? &asf->asf_sd[st_num].asf_met + : &s->metadata)) < 0) { av_freep(&name); break; } @@ -787,8 +781,10 @@ asf_st->index = st->index; asf_st->indexed = 0; st->id = flags & ASF_STREAM_NUM; - av_init_packet(&asf_st->pkt.avpkt); asf_st->pkt.data_size = 0; + asf_st->pkt.avpkt = av_packet_alloc(); + if (!asf_st->pkt.avpkt) + return AVERROR(ENOMEM); avio_skip(pb, 4); // skip reserved field switch (type) { @@ -860,6 +856,8 @@ st_num = avio_rl16(pb); st_num &= ASF_STREAM_NUM; lang_idx = avio_rl16(pb); // Stream Language ID Index + if (lang_idx >= ASF_MAX_STREAMS) + return AVERROR_INVALIDDATA; for (i = 0; i < asf->nb_streams; i++) { if (st_num == asf->asf_st[i]->stream_index) { st = s->streams[asf->asf_st[i]->index]; @@ -1144,9 +1142,7 @@ asf_pkt->duration = 0; asf_pkt->flags = 0; asf_pkt->dts = 0; - asf_pkt->duration = 0; - av_packet_unref(&asf_pkt->avpkt); - av_init_packet(&asf_pkt->avpkt); + av_packet_unref(asf_pkt->avpkt); } static int asf_read_replicated_data(AVFormatContext *s, ASFPacket *asf_pkt) @@ -1159,13 +1155,13 @@ data_size = avio_rl32(pb); // read media object size if (data_size <= 0) return AVERROR_INVALIDDATA; - if ((ret = av_new_packet(&asf_pkt->avpkt, data_size)) < 0) + if ((ret = av_new_packet(asf_pkt->avpkt, data_size)) < 0) return ret; asf_pkt->data_size = asf_pkt->size_left = data_size; } else avio_skip(pb, 4); // reading of media object size is already done asf_pkt->dts = avio_rl32(pb); // read presentation time - if (asf->rep_data_len && (asf->rep_data_len >= 8)) + if (asf->rep_data_len >= 8) avio_skip(pb, asf->rep_data_len - 8); // skip replicated data return 0; @@ -1200,7 +1196,7 @@ pay_len, asf->packet_size, avio_tell(pb)); return AVERROR_INVALIDDATA; } - p = asf_pkt->avpkt.data + asf_pkt->data_size - asf_pkt->size_left; + p = asf_pkt->avpkt->data + asf_pkt->data_size - asf_pkt->size_left; if (pay_len > asf_pkt->size_left) { av_log(s, AV_LOG_ERROR, "Error: invalid buffer size, pay_len %d, data size left %d.\n", @@ -1235,7 +1231,7 @@ data_size = avio_rl32(pb); // read media object size if (data_size <= 0) return AVERROR_EOF; - if ((ret = av_new_packet(&asf_pkt->avpkt, data_size)) < 0) + if ((ret = av_new_packet(asf_pkt->avpkt, data_size)) < 0) return ret; asf_pkt->data_size = asf_pkt->size_left = data_size; } else @@ -1256,7 +1252,7 @@ avio_tell(pb)); return AVERROR_INVALIDDATA; } - p = asf_pkt->avpkt.data + asf_pkt->data_size - asf_pkt->size_left; + p = asf_pkt->avpkt->data + asf_pkt->data_size - asf_pkt->size_left; if (size > asf_pkt->size_left || asf_pkt->size_left <= 0) return AVERROR_INVALIDDATA; if (asf_pkt->size_left > size) @@ -1393,16 +1389,18 @@ { ASFContext *asf = s->priv_data; ASFStream *asf_st = asf->asf_st[st_num]; - unsigned char *p = asf_pkt->avpkt.data; + unsigned char *p = asf_pkt->avpkt->data; uint16_t pkt_len = asf->asf_st[st_num]->virtual_pkt_len; uint16_t chunk_len = asf->asf_st[st_num]->virtual_chunk_len; int nchunks = pkt_len / chunk_len; - AVPacket pkt; + uint8_t *data; int pos = 0, j, l, ret; - if ((ret = av_new_packet(&pkt, asf_pkt->data_size)) < 0) - return ret; + data = av_malloc(asf_pkt->data_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!data) + return AVERROR(ENOMEM); + memset(data + asf_pkt->data_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); while (asf_pkt->data_size >= asf_st->span * pkt_len + pos) { if (pos >= asf_pkt->data_size) { @@ -1415,20 +1413,22 @@ for (j = 0; j < asf_st->span; j++) { if ((pos + chunk_len) >= asf_pkt->data_size) break; - memcpy(pkt.data + pos, + memcpy(data + pos, p + (j * nchunks + l) * chunk_len, chunk_len); pos += chunk_len; } } p += asf_st->span * pkt_len; - if (p > asf_pkt->avpkt.data + asf_pkt->data_size) + if (p > asf_pkt->avpkt->data + asf_pkt->data_size) break; } - av_packet_unref(&asf_pkt->avpkt); - asf_pkt->avpkt = pkt; + av_packet_unref(asf_pkt->avpkt); + ret = av_packet_from_data(asf_pkt->avpkt, data, asf_pkt->data_size); + if (ret < 0) + av_free(data); - return 0; + return ret; } static int asf_read_packet(AVFormatContext *s, AVPacket *pkt) @@ -1498,7 +1498,7 @@ asf->asf_st[i]->type == AVMEDIA_TYPE_AUDIO) if ((ret = asf_deinterleave(s, asf_pkt, i)) < 0) return ret; - av_packet_move_ref(pkt, &asf_pkt->avpkt); + av_packet_move_ref(pkt, asf_pkt->avpkt); pkt->stream_index = asf->asf_st[i]->index; pkt->flags = asf_pkt->flags; pkt->dts = asf_pkt->dts - asf->preroll; @@ -1523,7 +1523,7 @@ for (i = 0; i < ASF_MAX_STREAMS; i++) { av_dict_free(&asf->asf_sd[i].asf_met); if (i < asf->nb_streams) { - av_packet_unref(&asf->asf_st[i]->pkt.avpkt); + av_packet_free(&asf->asf_st[i]->pkt.avpkt); av_freep(&asf->asf_st[i]); } } @@ -1553,14 +1553,7 @@ asf->sub_dts = 0; for (i = 0; i < asf->nb_streams; i++) { ASFPacket *pkt = &asf->asf_st[i]->pkt; - pkt->size_left = 0; - pkt->data_size = 0; - pkt->duration = 0; - pkt->flags = 0; - pkt->dts = 0; - pkt->duration = 0; - av_packet_unref(&pkt->avpkt); - av_init_packet(&pkt->avpkt); + reset_packet(pkt); } } @@ -1580,9 +1573,12 @@ { ASFContext *asf = s->priv_data; int64_t pkt_pos = *pos, pkt_offset, dts = AV_NOPTS_VALUE, data_end; - AVPacket pkt; + AVPacket *pkt = av_packet_alloc(); int n; + if (!pkt) + return AVERROR(ENOMEM); + data_end = asf->data_offset + asf->data_size; n = (pkt_pos - asf->first_packet_offset + asf->packet_size - 1) / @@ -1598,9 +1594,9 @@ int i, ret, st_found; - av_init_packet(&pkt); pkt_offset = avio_tell(s->pb); - if ((ret = asf_read_packet(s, &pkt)) < 0) { + if ((ret = asf_read_packet(s, pkt)) < 0) { + av_packet_free(&pkt); dts = AV_NOPTS_VALUE; return ret; } @@ -1612,11 +1608,11 @@ ASFStream *st = asf->asf_st[i]; st_found = 0; - if (pkt.flags & AV_PKT_FLAG_KEY) { - dts = pkt.dts; + if (pkt->flags & AV_PKT_FLAG_KEY) { + dts = pkt->dts; if (dts) { - av_add_index_entry(s->streams[pkt.stream_index], pkt_pos, - dts, pkt.size, 0, AVINDEX_KEYFRAME); + av_add_index_entry(s->streams[pkt->stream_index], pkt_pos, + dts, pkt->size, 0, AVINDEX_KEYFRAME); if (stream_index == st->index) { st_found = 1; break; @@ -1626,11 +1622,11 @@ } if (st_found) break; - av_packet_unref(&pkt); + av_packet_unref(pkt); } *pos = pkt_pos; - av_packet_unref(&pkt); + av_packet_free(&pkt); return dts; } @@ -1679,6 +1675,9 @@ ff_asf_guid guid; int ret; + if (offset > INT64_MAX - size) + return AVERROR_INVALIDDATA; + while (avio_tell(pb) <= offset + size) { if (avio_tell(pb) == asf->offset) break; diff -Nru ffmpeg-4.2.2/libavformat/asfenc.c ffmpeg-4.4/libavformat/asfenc.c --- ffmpeg-4.2.2/libavformat/asfenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavformat/asfenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -22,7 +22,6 @@ #include "libavutil/avassert.h" #include "libavutil/dict.h" #include "libavutil/mathematics.h" -#include "libavutil/parseutils.h" #include "libavutil/opt.h" #include "avformat.h" #include "avlanguage.h" @@ -259,6 +258,10 @@ { AV_CODEC_ID_NONE, 0 }, }; +static const AVCodecTag *const asf_codec_tags[] = { + codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, NULL +}; + #define PREROLL_TIME 3100 static void put_str16(AVIOContext *s, const char *tag) @@ -358,12 +361,12 @@ int64_t pres_time = av_rescale_q(c->start, c->time_base, scale); uint64_t offset; int32_t send_time = get_send_time(asf, pres_time, &offset); - int len = 0; + int len = 0, ret; uint8_t *buf; AVIOContext *dyn_buf; if (t) { - if (avio_open_dyn_buf(&dyn_buf) < 0) - return AVERROR(ENOMEM); + if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0) + return ret; avio_put_str16le(dyn_buf, t->value); len = avio_close_dyn_buf(dyn_buf, &buf); } @@ -580,12 +583,12 @@ /* title and other info */ if (has_title) { - int len; + int len, ret; uint8_t *buf; AVIOContext *dyn_buf; - if (avio_open_dyn_buf(&dyn_buf) < 0) - return AVERROR(ENOMEM); + if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0) + return ret; hpos = put_header(pb, &ff_asf_comment_header); @@ -683,7 +686,7 @@ avio_wl16(pb, 40 + par->extradata_size); /* size */ /* BITMAPINFOHEADER header */ - ff_put_bmp_header(pb, par, 1, 0); + ff_put_bmp_header(pb, par, 1, 0, 0); } end_header(pb, hpos); } @@ -715,10 +718,10 @@ if (desc) { AVIOContext *dyn_buf; uint8_t *buf; - int len; + int len, ret; - if (avio_open_dyn_buf(&dyn_buf) < 0) - return AVERROR(ENOMEM); + if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0) + return ret; avio_put_str16le(dyn_buf, desc); len = avio_close_dyn_buf(dyn_buf, &buf); @@ -802,8 +805,6 @@ return -1; } - avio_flush(s->pb); - asf->packet_nb_payloads = 0; asf->packet_timestamp_start = -1; asf->packet_timestamp_end = -1; @@ -895,7 +896,8 @@ avio_write(s->pb, asf->packet_buf, s->packet_size - packet_hdr_size); - avio_flush(s->pb); + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); + asf->nb_packets++; asf->packet_nb_payloads = 0; asf->packet_timestamp_start = -1; @@ -1133,7 +1135,6 @@ return ret; asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->next_start_sec); } - avio_flush(s->pb); if (asf->is_streamed || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) { put_chunk(s, 0x4524, 0, 0); /* end of stream */ @@ -1173,9 +1174,7 @@ .write_packet = asf_write_packet, .write_trailer = asf_write_trailer, .flags = AVFMT_GLOBALHEADER, - .codec_tag = (const AVCodecTag * const []) { - codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0 - }, + .codec_tag = asf_codec_tags, .priv_class = &asf_muxer_class, }; #endif /* CONFIG_ASF_MUXER */ @@ -1200,9 +1199,7 @@ .write_packet = asf_write_packet, .write_trailer = asf_write_trailer, .flags = AVFMT_GLOBALHEADER, - .codec_tag = (const AVCodecTag * const []) { - codec_asf_bmp_tags, ff_codec_bmp_tags, ff_codec_wav_tags, 0 - }, + .codec_tag = asf_codec_tags, .priv_class = &asf_stream_muxer_class, }; #endif /* CONFIG_ASF_STREAM_MUXER */ diff -Nru ffmpeg-4.2.2/libavformat/asf.h ffmpeg-4.4/libavformat/asf.h --- ffmpeg-4.2.2/libavformat/asf.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/asf.h 2021-04-08 21:28:40.000000000 +0000 @@ -74,7 +74,6 @@ extern const ff_asf_guid ff_asf_stream_header; extern const ff_asf_guid ff_asf_ext_stream_header; extern const ff_asf_guid ff_asf_audio_stream; -extern const ff_asf_guid ff_asf_audio_conceal_none; extern const ff_asf_guid ff_asf_audio_conceal_spread; extern const ff_asf_guid ff_asf_video_stream; extern const ff_asf_guid ff_asf_jfif_media; diff -Nru ffmpeg-4.2.2/libavformat/assdec.c ffmpeg-4.4/libavformat/assdec.c --- ffmpeg-4.2.2/libavformat/assdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/assdec.c 2020-07-09 09:17:49.000000000 +0000 @@ -160,6 +160,8 @@ ff_subtitles_queue_finalize(s, &ass->q); end: + if (res < 0) + ass_read_close(s); av_bprint_finalize(&header, NULL); av_bprint_finalize(&line, NULL); av_bprint_finalize(&rline, NULL); diff -Nru ffmpeg-4.2.2/libavformat/assenc.c ffmpeg-4.4/libavformat/assenc.c --- ffmpeg-4.2.2/libavformat/assenc.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/assenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -77,7 +77,6 @@ avio_printf(s->pb, "[Events]\r\nFormat: %s, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\n", ass->ssa_mode ? "Marked" : "Layer"); } - avio_flush(s->pb); return 0; } @@ -95,7 +94,7 @@ ass->expected_readorder, dialogue->readorder); ass->expected_readorder = dialogue->readorder; } - avio_printf(s->pb, "Dialogue: %s\r\n", dialogue->line); + avio_print(s->pb, "Dialogue: ", dialogue->line, "\r\n"); if (dialogue == ass->last_added_dialogue) ass->last_added_dialogue = next; av_freep(&dialogue->line); diff -Nru ffmpeg-4.2.2/libavformat/ast.c ffmpeg-4.4/libavformat/ast.c --- ffmpeg-4.2.2/libavformat/ast.c 2016-03-29 02:25:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/ast.c 2021-04-08 21:28:40.000000000 +0000 @@ -19,7 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avformat.h" +#include +#include "libavcodec/codec_id.h" #include "internal.h" const AVCodecTag ff_codec_ast_tags[] = { @@ -27,3 +28,5 @@ { AV_CODEC_ID_PCM_S16BE_PLANAR, 1 }, { AV_CODEC_ID_NONE, 0 }, }; + +const AVCodecTag *const ff_ast_codec_tags_list[] = { ff_codec_ast_tags, NULL }; diff -Nru ffmpeg-4.2.2/libavformat/astdec.c ffmpeg-4.4/libavformat/astdec.c --- ffmpeg-4.2.2/libavformat/astdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/astdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -118,5 +118,5 @@ .read_packet = ast_read_packet, .extensions = "ast", .flags = AVFMT_GENERIC_INDEX, - .codec_tag = (const AVCodecTag* const []){ff_codec_ast_tags, 0}, + .codec_tag = ff_ast_codec_tags_list, }; diff -Nru ffmpeg-4.2.2/libavformat/astenc.c ffmpeg-4.4/libavformat/astenc.c --- ffmpeg-4.2.2/libavformat/astenc.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavformat/astenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -101,8 +101,6 @@ avio_wb64(pb, 0); avio_wb32(pb, 0); - avio_flush(pb); - return 0; } @@ -180,7 +178,6 @@ } avio_seek(pb, file_size, SEEK_SET); - avio_flush(pb); } return 0; } @@ -210,5 +207,5 @@ .write_packet = ast_write_packet, .write_trailer = ast_write_trailer, .priv_class = &ast_muxer_class, - .codec_tag = (const AVCodecTag* const []){ff_codec_ast_tags, 0}, + .codec_tag = ff_ast_codec_tags_list, }; diff -Nru ffmpeg-4.2.2/libavformat/ast.h ffmpeg-4.4/libavformat/ast.h --- ffmpeg-4.2.2/libavformat/ast.h 2016-03-29 02:25:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/ast.h 2021-04-08 21:28:40.000000000 +0000 @@ -26,5 +26,6 @@ #include "internal.h" extern const AVCodecTag ff_codec_ast_tags[]; +extern const AVCodecTag *const ff_ast_codec_tags_list[]; #endif /* AVFORMAT_AST_H */ diff -Nru ffmpeg-4.2.2/libavformat/async.c ffmpeg-4.4/libavformat/async.c --- ffmpeg-4.2.2/libavformat/async.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/async.c 2021-04-08 21:28:40.000000000 +0000 @@ -262,24 +262,28 @@ ret = pthread_mutex_init(&c->mutex, NULL); if (ret != 0) { + ret = AVERROR(ret); av_log(h, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", av_err2str(ret)); goto mutex_fail; } ret = pthread_cond_init(&c->cond_wakeup_main, NULL); if (ret != 0) { + ret = AVERROR(ret); av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", av_err2str(ret)); goto cond_wakeup_main_fail; } ret = pthread_cond_init(&c->cond_wakeup_background, NULL); if (ret != 0) { + ret = AVERROR(ret); av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", av_err2str(ret)); goto cond_wakeup_background_fail; } ret = pthread_create(&c->async_buffer_thread, NULL, async_buffer_task, h); if (ret) { + ret = AVERROR(ret); av_log(h, AV_LOG_ERROR, "pthread_create failed : %s\n", av_err2str(ret)); goto thread_fail; } @@ -293,7 +297,7 @@ cond_wakeup_main_fail: pthread_mutex_destroy(&c->mutex); mutex_fail: - ffurl_close(c->inner); + ffurl_closep(&c->inner); url_fail: ring_destroy(&c->ring); fifo_fail: @@ -317,7 +321,7 @@ pthread_cond_destroy(&c->cond_wakeup_background); pthread_cond_destroy(&c->cond_wakeup_main); pthread_mutex_destroy(&c->mutex); - ffurl_close(c->inner); + ffurl_closep(&c->inner); ring_destroy(&c->ring); return 0; @@ -608,7 +612,8 @@ /* * test normal read */ - ret = ffurl_open(&h, "async:async-test:", AVIO_FLAG_READ, NULL, NULL); + ret = ffurl_open_whitelist(&h, "async:async-test:", AVIO_FLAG_READ, + NULL, NULL, NULL, NULL, NULL); printf("open: %d\n", ret); size = ffurl_size(h); @@ -684,7 +689,8 @@ */ ffurl_close(h); av_dict_set_int(&opts, "async-test-read-error", -10000, 0); - ret = ffurl_open(&h, "async:async-test:", AVIO_FLAG_READ, NULL, &opts); + ret = ffurl_open_whitelist(&h, "async:async-test:", AVIO_FLAG_READ, + NULL, &opts, NULL, NULL, NULL); printf("open: %d\n", ret); ret = ffurl_read(h, buf, 1); diff -Nru ffmpeg-4.2.2/libavformat/au.c ffmpeg-4.4/libavformat/au.c --- ffmpeg-4.2.2/libavformat/au.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/au.c 2021-04-08 21:28:40.000000000 +0000 @@ -35,8 +35,6 @@ /* if we don't know the size in advance */ #define AU_UNKNOWN_SIZE ((uint32_t)(~0)) -/* the specification requires an annotation field of at least eight bytes */ -#define AU_DEFAULT_HEADER_SIZE (24+8) static const AVCodecTag codec_au_tags[] = { { AV_CODEC_ID_PCM_MULAW, 1 }, @@ -55,6 +53,8 @@ { AV_CODEC_ID_NONE, 0 }, }; +static const AVCodecTag *const au_codec_tags[] = { codec_au_tags, NULL }; + #if CONFIG_AU_DEMUXER static int au_probe(const AVProbeData *p) @@ -68,31 +68,38 @@ static int au_read_annotation(AVFormatContext *s, int size) { - static const char * keys[] = { + static const char keys[][7] = { "title", "artist", "album", "track", "genre", - NULL }; + }; AVIOContext *pb = s->pb; enum { PARSE_KEY, PARSE_VALUE, PARSE_FINISHED } state = PARSE_KEY; char c; AVBPrint bprint; char * key = NULL; char * value = NULL; - int i; + int ret, i; av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED); while (size-- > 0) { + if (avio_feof(pb)) { + av_bprint_finalize(&bprint, NULL); + av_freep(&key); + return AVERROR_EOF; + } c = avio_r8(pb); switch(state) { case PARSE_KEY: if (c == '\0') { state = PARSE_FINISHED; } else if (c == '=') { - av_bprint_finalize(&bprint, &key); + ret = av_bprint_finalize(&bprint, &key); + if (ret < 0) + return ret; av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED); state = PARSE_VALUE; } else { @@ -105,11 +112,11 @@ av_log(s, AV_LOG_ERROR, "Memory error while parsing AU metadata.\n"); } else { av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED); - for (i = 0; keys[i] != NULL && key != NULL; i++) { + for (i = 0; i < FF_ARRAY_ELEMS(keys); i++) { if (av_strcasecmp(keys[i], key) == 0) { av_dict_set(&(s->metadata), keys[i], value, AV_DICT_DONT_STRDUP_VAL); - av_freep(&key); value = NULL; + break; } } } @@ -143,6 +150,7 @@ int bps, ba = 0; enum AVCodecID codec; AVStream *st; + int ret; tag = avio_rl32(pb); if (tag != MKTAG('.', 's', 'n', 'd')) @@ -161,7 +169,9 @@ if (size > 24) { /* parse annotation field to get metadata */ - au_read_annotation(s, size - 24); + ret = au_read_annotation(s, size - 24); + if (ret < 0) + return ret; } codec = ff_codec_get_id(codec_au_tags, id); @@ -223,7 +233,7 @@ .read_header = au_read_header, .read_packet = ff_pcm_read_packet, .read_seek = ff_pcm_read_seek, - .codec_tag = (const AVCodecTag* const []) { codec_au_tags, 0 }, + .codec_tag = au_codec_tags, }; #endif /* CONFIG_AU_DEMUXER */ @@ -236,36 +246,31 @@ #include "rawenc.h" -static int au_get_annotations(AVFormatContext *s, char **buffer) +static int au_get_annotations(AVFormatContext *s, AVBPrint *annotations) { - static const char * keys[] = { + static const char keys[][7] = { "Title", "Artist", "Album", "Track", "Genre", - NULL }; - int i; + }; int cnt = 0; AVDictionary *m = s->metadata; AVDictionaryEntry *t = NULL; - AVBPrint bprint; - - av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED); - for (i = 0; keys[i] != NULL; i++) { + for (int i = 0; i < FF_ARRAY_ELEMS(keys); i++) { t = av_dict_get(m, keys[i], NULL, 0); if (t != NULL) { if (cnt++) - av_bprint_chars(&bprint, '\n', 1); - av_bprint_append_data(&bprint, keys[i], strlen(keys[i])); - av_bprint_chars(&bprint, '=', 1); - av_bprint_append_data(&bprint, t->value, strlen(t->value)); + av_bprint_chars(annotations, '\n', 1); + av_bprintf(annotations, "%s=%s", keys[i], t->value); } } - /* pad with 0's */ - av_bprint_append_data(&bprint, "\0\0\0\0\0\0\0\0", 8); - return av_bprint_finalize(&bprint, buffer); + /* The specification requires the annotation field to be zero-terminated + * and its length to be a multiple of eight, so pad with 0's */ + av_bprint_chars(annotations, '\0', 8); + return av_bprint_is_complete(annotations) ? 0 : AVERROR(ENOMEM); } static int au_write_header(AVFormatContext *s) @@ -274,9 +279,7 @@ AUContext *au = s->priv_data; AVIOContext *pb = s->pb; AVCodecParameters *par = s->streams[0]->codecpar; - char *annotations = NULL; - - au->header_size = AU_DEFAULT_HEADER_SIZE; + AVBPrint annotations; if (s->nb_streams != 1) { av_log(s, AV_LOG_ERROR, "only one stream is supported\n"); @@ -289,31 +292,24 @@ return AVERROR(EINVAL); } - if (av_dict_count(s->metadata) > 0) { - ret = au_get_annotations(s, &annotations); - if (ret < 0) - return ret; - if (annotations != NULL) { - au->header_size = (24 + strlen(annotations) + 8) & ~7; - if (au->header_size < AU_DEFAULT_HEADER_SIZE) - au->header_size = AU_DEFAULT_HEADER_SIZE; - } - } + av_bprint_init(&annotations, 0, INT_MAX - 24); + ret = au_get_annotations(s, &annotations); + if (ret < 0) + goto fail; + au->header_size = 24 + annotations.len & ~7; + ffio_wfourcc(pb, ".snd"); /* magic number */ avio_wb32(pb, au->header_size); /* header size */ avio_wb32(pb, AU_UNKNOWN_SIZE); /* data size */ avio_wb32(pb, par->codec_tag); /* codec ID */ avio_wb32(pb, par->sample_rate); avio_wb32(pb, par->channels); - if (annotations != NULL) { - avio_write(pb, annotations, au->header_size - 24); - av_freep(&annotations); - } else { - avio_wb64(pb, 0); /* annotation field */ - } - avio_flush(pb); + avio_write(pb, annotations.str, annotations.len & ~7); - return 0; +fail: + av_bprint_finalize(&annotations, NULL); + + return ret; } static int au_write_trailer(AVFormatContext *s) @@ -327,7 +323,6 @@ avio_seek(pb, 8, SEEK_SET); avio_wb32(pb, (uint32_t)(file_size - au->header_size)); avio_seek(pb, file_size, SEEK_SET); - avio_flush(pb); } return 0; @@ -344,7 +339,7 @@ .write_header = au_write_header, .write_packet = ff_raw_write_packet, .write_trailer = au_write_trailer, - .codec_tag = (const AVCodecTag* const []) { codec_au_tags, 0 }, + .codec_tag = au_codec_tags, .flags = AVFMT_NOTIMESTAMPS, }; diff -Nru ffmpeg-4.2.2/libavformat/audiointerleave.c ffmpeg-4.4/libavformat/audiointerleave.c --- ffmpeg-4.2.2/libavformat/audiointerleave.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/audiointerleave.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,150 +0,0 @@ -/* - * Audio Interleaving functions - * - * Copyright (c) 2009 Baptiste Coudurier - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/fifo.h" -#include "libavutil/mathematics.h" -#include "avformat.h" -#include "audiointerleave.h" -#include "internal.h" - -void ff_audio_interleave_close(AVFormatContext *s) -{ - int i; - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - AudioInterleaveContext *aic = st->priv_data; - - if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) - av_fifo_freep(&aic->fifo); - } -} - -int ff_audio_interleave_init(AVFormatContext *s, - const int *samples_per_frame, - AVRational time_base) -{ - int i; - - if (!samples_per_frame) - return AVERROR(EINVAL); - - if (!time_base.num) { - av_log(s, AV_LOG_ERROR, "timebase not set for audio interleave\n"); - return AVERROR(EINVAL); - } - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - AudioInterleaveContext *aic = st->priv_data; - - if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - aic->sample_size = (st->codecpar->channels * - av_get_bits_per_sample(st->codecpar->codec_id)) / 8; - if (!aic->sample_size) { - av_log(s, AV_LOG_ERROR, "could not compute sample size\n"); - return AVERROR(EINVAL); - } - aic->samples_per_frame = samples_per_frame; - aic->samples = aic->samples_per_frame; - aic->time_base = time_base; - - aic->fifo_size = 100* *aic->samples; - if (!(aic->fifo= av_fifo_alloc_array(100, *aic->samples))) - return AVERROR(ENOMEM); - } - } - - return 0; -} - -static int interleave_new_audio_packet(AVFormatContext *s, AVPacket *pkt, - int stream_index, int flush) -{ - AVStream *st = s->streams[stream_index]; - AudioInterleaveContext *aic = st->priv_data; - int ret; - int frame_size = *aic->samples * aic->sample_size; - int size = FFMIN(av_fifo_size(aic->fifo), frame_size); - if (!size || (!flush && size == av_fifo_size(aic->fifo))) - return 0; - - ret = av_new_packet(pkt, frame_size); - if (ret < 0) - return ret; - av_fifo_generic_read(aic->fifo, pkt->data, size, NULL); - - if (size < pkt->size) - memset(pkt->data + size, 0, pkt->size - size); - - pkt->dts = pkt->pts = aic->dts; - pkt->duration = av_rescale_q(*aic->samples, st->time_base, aic->time_base); - pkt->stream_index = stream_index; - aic->dts += pkt->duration; - - aic->samples++; - if (!*aic->samples) - aic->samples = aic->samples_per_frame; - - return pkt->size; -} - -int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush, - int (*get_packet)(AVFormatContext *, AVPacket *, AVPacket *, int), - int (*compare_ts)(AVFormatContext *, AVPacket *, AVPacket *)) -{ - int i, ret; - - if (pkt) { - AVStream *st = s->streams[pkt->stream_index]; - AudioInterleaveContext *aic = st->priv_data; - if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - unsigned new_size = av_fifo_size(aic->fifo) + pkt->size; - if (new_size > aic->fifo_size) { - if (av_fifo_realloc2(aic->fifo, new_size) < 0) - return AVERROR(ENOMEM); - aic->fifo_size = new_size; - } - av_fifo_generic_write(aic->fifo, pkt->data, pkt->size, NULL); - } else { - // rewrite pts and dts to be decoded time line position - pkt->pts = pkt->dts = aic->dts; - aic->dts += pkt->duration; - if ((ret = ff_interleave_add_packet(s, pkt, compare_ts)) < 0) - return ret; - } - pkt = NULL; - } - - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - AVPacket new_pkt = { 0 }; - while ((ret = interleave_new_audio_packet(s, &new_pkt, i, flush)) > 0) { - if ((ret = ff_interleave_add_packet(s, &new_pkt, compare_ts)) < 0) - return ret; - } - if (ret < 0) - return ret; - } - } - - return get_packet(s, out, NULL, flush); -} diff -Nru ffmpeg-4.2.2/libavformat/audiointerleave.h ffmpeg-4.4/libavformat/audiointerleave.h --- ffmpeg-4.2.2/libavformat/audiointerleave.h 2016-03-29 02:25:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/audiointerleave.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -/* - * audio interleaving prototypes and declarations - * - * Copyright (c) 2009 Baptiste Coudurier - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef AVFORMAT_AUDIOINTERLEAVE_H -#define AVFORMAT_AUDIOINTERLEAVE_H - -#include "libavutil/fifo.h" -#include "avformat.h" - -typedef struct AudioInterleaveContext { - AVFifoBuffer *fifo; - unsigned fifo_size; ///< size of currently allocated FIFO - uint64_t dts; ///< current dts - int sample_size; ///< size of one sample all channels included - const int *samples_per_frame; ///< must be 0-terminated - const int *samples; ///< current samples per frame, pointer to samples_per_frame - AVRational time_base; ///< time base of output audio packets -} AudioInterleaveContext; - -int ff_audio_interleave_init(AVFormatContext *s, const int *samples_per_frame, AVRational time_base); -void ff_audio_interleave_close(AVFormatContext *s); - -/** - * Rechunk audio PCM packets per AudioInterleaveContext->samples_per_frame - * and interleave them correctly. - * The first element of AVStream->priv_data must be AudioInterleaveContext - * when using this function. - * - * @param get_packet function will output a packet when streams are correctly interleaved. - * @param compare_ts function will compare AVPackets and decide interleaving order. - */ -int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush, - int (*get_packet)(AVFormatContext *, AVPacket *, AVPacket *, int), - int (*compare_ts)(AVFormatContext *, AVPacket *, AVPacket *)); - -#endif /* AVFORMAT_AUDIOINTERLEAVE_H */ diff -Nru ffmpeg-4.2.2/libavformat/av1.c ffmpeg-4.4/libavformat/av1.c --- ffmpeg-4.2.2/libavformat/av1.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/av1.c 2021-04-08 21:28:40.000000000 +0000 @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/mem.h" #include "libavcodec/av1.h" #include "libavcodec/av1_parse.h" @@ -28,13 +29,20 @@ #include "avio.h" #include "avio_internal.h" -int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size) +static int av1_filter_obus(AVIOContext *pb, const uint8_t *buf, + int size, int *offset) { - const uint8_t *end = buf + size; + const uint8_t *start = buf, *end = buf + size; int64_t obu_size; - int start_pos, type, temporal_id, spatial_id; + int off, start_pos, type, temporal_id, spatial_id; + enum { + START_NOT_FOUND, + START_FOUND, + END_FOUND, + OFFSET_IMPOSSIBLE, + } state = START_NOT_FOUND; - size = 0; + off = size = 0; while (buf < end) { int len = parse_obu_header(buf, end - buf, &obu_size, &start_pos, &type, &temporal_id, &spatial_id); @@ -46,37 +54,70 @@ case AV1_OBU_REDUNDANT_FRAME_HEADER: case AV1_OBU_TILE_LIST: case AV1_OBU_PADDING: + if (state == START_FOUND) + state = END_FOUND; break; default: - avio_write(pb, buf, len); + if (state == START_NOT_FOUND) { + off = buf - start; + state = START_FOUND; + } else if (state == END_FOUND) { + state = OFFSET_IMPOSSIBLE; + } + if (pb) + avio_write(pb, buf, len); size += len; break; } buf += len; } + if (offset) + *offset = state != OFFSET_IMPOSSIBLE ? off : -1; + return size; } -int ff_av1_filter_obus_buf(const uint8_t *buf, uint8_t **out, int *size) +int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size) { - AVIOContext *pb; - int ret; + return av1_filter_obus(pb, buf, size, NULL); +} - ret = avio_open_dyn_buf(&pb); - if (ret < 0) - return ret; +int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out, + int *size, int *offset) +{ + AVIOContext pb; + uint8_t *buf; + int len, off, ret; - ret = ff_av1_filter_obus(pb, buf, *size); + len = ret = av1_filter_obus(NULL, in, *size, &off); if (ret < 0) { - ffio_free_dyn_buf(&pb); return ret; } + if (off >= 0) { + *out = (uint8_t *)in; + *size = len; + *offset = off; - av_freep(out); - *size = avio_close_dyn_buf(pb, out); + return 0; + } - return ret; + buf = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE); + if (!buf) + return AVERROR(ENOMEM); + + ffio_init_context(&pb, buf, len, 1, NULL, NULL, NULL, NULL); + + ret = av1_filter_obus(&pb, in, *size, NULL); + av_assert1(ret == len); + + memset(buf + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); + + *out = buf; + *size = len; + *offset = 0; + + return 0; } static inline void uvlc(GetBitContext *gb) @@ -257,7 +298,7 @@ if (!reduced_still_picture_header) { int enable_order_hint, seq_force_screen_content_tools; - skip_bits(&gb, 4); // enable_intraintra_compound (1), enable_masked_compound (1) + skip_bits(&gb, 4); // enable_interintra_compound (1), enable_masked_compound (1) // enable_warped_motion (1), enable_dual_filter (1) enable_order_hint = get_bits1(&gb); @@ -322,11 +363,11 @@ int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size) { - AVIOContext *seq_pb = NULL, *meta_pb = NULL; + AVIOContext *meta_pb; AV1SequenceParameters seq_params; PutBitContext pbc; - uint8_t header[4]; - uint8_t *seq = NULL, *meta = NULL; + uint8_t header[4], *meta; + const uint8_t *seq; int64_t obu_size; int start_pos, type, temporal_id, spatial_id; int ret, nb_seq = 0, seq_size, meta_size; @@ -334,12 +375,23 @@ if (size <= 0) return AVERROR_INVALIDDATA; - ret = avio_open_dyn_buf(&seq_pb); - if (ret < 0) - return ret; + if (buf[0] & 0x80) { + // first bit is nonzero, the passed data does not consist purely of + // OBUs. Expect that the data is already in AV1CodecConfigurationRecord + // format. + int config_record_version = buf[0] & 0x7f; + if (config_record_version != 1 || size < 4) { + return AVERROR_INVALIDDATA; + } + + avio_write(pb, buf, size); + + return 0; + } + ret = avio_open_dyn_buf(&meta_pb); if (ret < 0) - goto fail; + return ret; while (size > 0) { int len = parse_obu_header(buf, size, &obu_size, &start_pos, @@ -360,7 +412,8 @@ if (ret < 0) goto fail; - avio_write(seq_pb, buf, len); + seq = buf; + seq_size = len; break; case AV1_OBU_METADATA: if (!obu_size) { @@ -376,8 +429,7 @@ buf += len; } - seq_size = avio_close_dyn_buf(seq_pb, &seq); - if (!seq_size) { + if (!nb_seq) { ret = AVERROR_INVALIDDATA; goto fail; } @@ -401,17 +453,12 @@ avio_write(pb, header, sizeof(header)); avio_write(pb, seq, seq_size); - meta_size = avio_close_dyn_buf(meta_pb, &meta); + meta_size = avio_get_dyn_buf(meta_pb, &meta); if (meta_size) avio_write(pb, meta, meta_size); fail: - if (!seq) - avio_close_dyn_buf(seq_pb, &seq); - if (!meta) - avio_close_dyn_buf(meta_pb, &meta); - av_free(seq); - av_free(meta); + ffio_free_dyn_buf(&meta_pb); return ret; } diff -Nru ffmpeg-4.2.2/libavformat/av1dec.c ffmpeg-4.4/libavformat/av1dec.c --- ffmpeg-4.2.2/libavformat/av1dec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/av1dec.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,483 @@ +/* + * AV1 Annex B demuxer + * Copyright (c) 2019 James Almer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/common.h" +#include "libavutil/fifo.h" +#include "libavutil/opt.h" +#include "libavcodec/av1_parse.h" +#include "avformat.h" +#include "avio_internal.h" +#include "internal.h" + +//return < 0 if we need more data +static int get_score(int type, int *seq) +{ + switch (type) { + case AV1_OBU_SEQUENCE_HEADER: + *seq = 1; + return -1; + case AV1_OBU_FRAME: + case AV1_OBU_FRAME_HEADER: + return *seq ? AVPROBE_SCORE_EXTENSION + 1 : 0; + case AV1_OBU_METADATA: + case AV1_OBU_PADDING: + return -1; + default: + break; + } + return 0; +} + +static int read_header(AVFormatContext *s, const AVRational *framerate, AVBSFContext **bsf, void *logctx) +{ + const AVBitStreamFilter *filter = av_bsf_get_by_name("av1_frame_merge"); + AVStream *st; + int ret; + + if (!filter) { + av_log(logctx, AV_LOG_ERROR, "av1_frame_merge bitstream filter " + "not found. This is a bug, please report it.\n"); + return AVERROR_BUG; + } + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_AV1; + st->need_parsing = AVSTREAM_PARSE_HEADERS; + + st->internal->avctx->framerate = *framerate; + // taken from rawvideo demuxers + avpriv_set_pts_info(st, 64, 1, 1200000); + + ret = av_bsf_alloc(filter, bsf); + if (ret < 0) + return ret; + + ret = avcodec_parameters_copy((*bsf)->par_in, st->codecpar); + if (ret < 0) { + av_bsf_free(bsf); + return ret; + } + + ret = av_bsf_init(*bsf); + if (ret < 0) + av_bsf_free(bsf); + + return ret; + +} + +#define DEC AV_OPT_FLAG_DECODING_PARAM + +#if CONFIG_AV1_DEMUXER +typedef struct AnnexBContext { + const AVClass *class; + AVBSFContext *bsf; + uint32_t temporal_unit_size; + uint32_t frame_unit_size; + AVRational framerate; +} AnnexBContext; + +static int leb(AVIOContext *pb, uint32_t *len) { + int more, i = 0; + uint8_t byte; + *len = 0; + do { + unsigned bits; + byte = avio_r8(pb); + more = byte & 0x80; + bits = byte & 0x7f; + if (i <= 3 || (i == 4 && bits < (1 << 4))) + *len |= bits << (i * 7); + else if (bits) + return AVERROR_INVALIDDATA; + if (++i == 8 && more) + return AVERROR_INVALIDDATA; + if (pb->eof_reached || pb->error) + return pb->error ? pb->error : AVERROR(EIO); + } while (more); + return i; +} + +static int read_obu(const uint8_t *buf, int size, int64_t *obu_size, int *type) +{ + int start_pos, temporal_id, spatial_id; + int len; + + len = parse_obu_header(buf, size, obu_size, &start_pos, + type, &temporal_id, &spatial_id); + if (len < 0) + return len; + + return 0; +} + +static int annexb_probe(const AVProbeData *p) +{ + AVIOContext pb; + int64_t obu_size; + uint32_t temporal_unit_size, frame_unit_size, obu_unit_size; + int seq = 0; + int ret, type, cnt = 0; + + ffio_init_context(&pb, p->buf, p->buf_size, 0, + NULL, NULL, NULL, NULL); + + ret = leb(&pb, &temporal_unit_size); + if (ret < 0) + return 0; + cnt += ret; + ret = leb(&pb, &frame_unit_size); + if (ret < 0 || ((int64_t)frame_unit_size + ret) > temporal_unit_size) + return 0; + cnt += ret; + ret = leb(&pb, &obu_unit_size); + if (ret < 0 || ((int64_t)obu_unit_size + ret) >= frame_unit_size) + return 0; + cnt += ret; + + frame_unit_size -= obu_unit_size + ret; + + avio_skip(&pb, obu_unit_size); + if (pb.eof_reached || pb.error) + return 0; + + // Check that the first OBU is a Temporal Delimiter. + ret = read_obu(p->buf + cnt, FFMIN(p->buf_size - cnt, obu_unit_size), &obu_size, &type); + if (ret < 0 || type != AV1_OBU_TEMPORAL_DELIMITER || obu_size > 0) + return 0; + cnt += obu_unit_size; + + do { + ret = leb(&pb, &obu_unit_size); + if (ret < 0 || ((int64_t)obu_unit_size + ret) > frame_unit_size) + return 0; + cnt += ret; + + avio_skip(&pb, obu_unit_size); + if (pb.eof_reached || pb.error) + return 0; + + ret = read_obu(p->buf + cnt, FFMIN(p->buf_size - cnt, obu_unit_size), &obu_size, &type); + if (ret < 0) + return 0; + cnt += obu_unit_size; + + ret = get_score(type, &seq); + if (ret >= 0) + return ret; + + frame_unit_size -= obu_unit_size + ret; + } while (frame_unit_size); + + return 0; +} + +static int annexb_read_header(AVFormatContext *s) +{ + AnnexBContext *c = s->priv_data; + return read_header(s, &c->framerate, &c->bsf, c); +} + +static int annexb_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AnnexBContext *c = s->priv_data; + uint32_t obu_unit_size; + int ret, len; + +retry: + if (avio_feof(s->pb)) { + if (c->temporal_unit_size || c->frame_unit_size) + return AVERROR(EIO); + goto end; + } + + if (!c->temporal_unit_size) { + len = leb(s->pb, &c->temporal_unit_size); + if (len < 0) return AVERROR_INVALIDDATA; + } + + if (!c->frame_unit_size) { + len = leb(s->pb, &c->frame_unit_size); + if (len < 0 || ((int64_t)c->frame_unit_size + len) > c->temporal_unit_size) + return AVERROR_INVALIDDATA; + c->temporal_unit_size -= len; + } + + len = leb(s->pb, &obu_unit_size); + if (len < 0 || ((int64_t)obu_unit_size + len) > c->frame_unit_size) + return AVERROR_INVALIDDATA; + + ret = av_get_packet(s->pb, pkt, obu_unit_size); + if (ret < 0) + return ret; + if (ret != obu_unit_size) + return AVERROR(EIO); + + c->temporal_unit_size -= obu_unit_size + len; + c->frame_unit_size -= obu_unit_size + len; + +end: + ret = av_bsf_send_packet(c->bsf, pkt); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Failed to send packet to " + "av1_frame_merge filter\n"); + return ret; + } + + ret = av_bsf_receive_packet(c->bsf, pkt); + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + av_log(s, AV_LOG_ERROR, "av1_frame_merge filter failed to " + "send output packet\n"); + + if (ret == AVERROR(EAGAIN)) + goto retry; + + return ret; +} + +static int annexb_read_close(AVFormatContext *s) +{ + AnnexBContext *c = s->priv_data; + + av_bsf_free(&c->bsf); + return 0; +} + +#define OFFSET(x) offsetof(AnnexBContext, x) +static const AVOption annexb_options[] = { + { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC}, + { NULL }, +}; +#undef OFFSET + +static const AVClass annexb_demuxer_class = { + .class_name = "AV1 Annex B demuxer", + .item_name = av_default_item_name, + .option = annexb_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_av1_demuxer = { + .name = "av1", + .long_name = NULL_IF_CONFIG_SMALL("AV1 Annex B"), + .priv_data_size = sizeof(AnnexBContext), + .read_probe = annexb_probe, + .read_header = annexb_read_header, + .read_packet = annexb_read_packet, + .read_close = annexb_read_close, + .extensions = "obu", + .flags = AVFMT_GENERIC_INDEX, + .priv_class = &annexb_demuxer_class, +}; +#endif + +#if CONFIG_OBU_DEMUXER +typedef struct ObuContext { + const AVClass *class; + AVBSFContext *bsf; + AVRational framerate; + AVFifoBuffer *fifo; +} ObuContext; + +//For low overhead obu, we can't foresee the obu size before we parsed the header. +//So, we can't use parse_obu_header here, since it will check size <= buf_size +//see c27c7b49dc for more details +static int read_obu_with_size(const uint8_t *buf, int buf_size, int64_t *obu_size, int *type) +{ + GetBitContext gb; + int ret, extension_flag, start_pos; + int64_t size; + + ret = init_get_bits8(&gb, buf, FFMIN(buf_size, MAX_OBU_HEADER_SIZE)); + if (ret < 0) + return ret; + + if (get_bits1(&gb) != 0) // obu_forbidden_bit + return AVERROR_INVALIDDATA; + + *type = get_bits(&gb, 4); + extension_flag = get_bits1(&gb); + if (!get_bits1(&gb)) // has_size_flag + return AVERROR_INVALIDDATA; + skip_bits1(&gb); // obu_reserved_1bit + + if (extension_flag) { + get_bits(&gb, 3); // temporal_id + get_bits(&gb, 2); // spatial_id + skip_bits(&gb, 3); // extension_header_reserved_3bits + } + + *obu_size = leb128(&gb); + if (*obu_size > INT_MAX) + return AVERROR_INVALIDDATA; + + if (get_bits_left(&gb) < 0) + return AVERROR_INVALIDDATA; + + start_pos = get_bits_count(&gb) / 8; + + size = *obu_size + start_pos; + if (size > INT_MAX) + return AVERROR_INVALIDDATA; + return size; +} + +static int obu_probe(const AVProbeData *p) +{ + int64_t obu_size; + int seq = 0; + int ret, type, cnt; + + // Check that the first OBU is a Temporal Delimiter. + cnt = read_obu_with_size(p->buf, p->buf_size, &obu_size, &type); + if (cnt < 0 || type != AV1_OBU_TEMPORAL_DELIMITER || obu_size != 0) + return 0; + + while (1) { + ret = read_obu_with_size(p->buf + cnt, p->buf_size - cnt, &obu_size, &type); + if (ret < 0 || obu_size <= 0) + return 0; + cnt += FFMIN(ret, p->buf_size - cnt); + + ret = get_score(type, &seq); + if (ret >= 0) + return ret; + } + return 0; +} + +static int obu_read_header(AVFormatContext *s) +{ + ObuContext *c = s->priv_data; + c->fifo = av_fifo_alloc(MAX_OBU_HEADER_SIZE); + if (!c->fifo) + return AVERROR(ENOMEM); + return read_header(s, &c->framerate, &c->bsf, c); +} + +static int obu_get_packet(AVFormatContext *s, AVPacket *pkt) +{ + ObuContext *c = s->priv_data; + uint8_t header[MAX_OBU_HEADER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; + int64_t obu_size; + int size = av_fifo_space(c->fifo); + int ret, len, type; + + av_fifo_generic_write(c->fifo, s->pb, size, + (int (*)(void*, void*, int))avio_read); + size = av_fifo_size(c->fifo); + if (!size) + return 0; + + av_fifo_generic_peek(c->fifo, header, size, NULL); + + len = read_obu_with_size(header, size, &obu_size, &type); + if (len < 0) { + av_log(c, AV_LOG_ERROR, "Failed to read obu\n"); + return len; + } + + ret = av_new_packet(pkt, len); + if (ret < 0) { + av_log(c, AV_LOG_ERROR, "Failed to allocate packet for obu\n"); + return ret; + } + size = FFMIN(size, len); + av_fifo_generic_read(c->fifo, pkt->data, size, NULL); + len -= size; + if (len > 0) { + ret = avio_read(s->pb, pkt->data + size, len); + if (ret != len) { + av_log(c, AV_LOG_ERROR, "Failed to read %d frome file\n", len); + return ret < 0 ? ret : AVERROR_INVALIDDATA; + } + } + return 0; +} + +static int obu_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + ObuContext *c = s->priv_data; + int ret; + + while (1) { + ret = obu_get_packet(s, pkt); + if (ret < 0) + return ret; + ret = av_bsf_send_packet(c->bsf, pkt); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Failed to send packet to " + "av1_frame_merge filter\n"); + return ret; + } + ret = av_bsf_receive_packet(c->bsf, pkt); + if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) + av_log(s, AV_LOG_ERROR, "av1_frame_merge filter failed to " + "send output packet\n"); + if (ret != AVERROR(EAGAIN)) + break; + } + + return ret; +} + +static int obu_read_close(AVFormatContext *s) +{ + ObuContext *c = s->priv_data; + + av_fifo_freep(&c->fifo); + av_bsf_free(&c->bsf); + return 0; +} + +#define OFFSET(x) offsetof(ObuContext, x) +static const AVOption obu_options[] = { + { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC}, + { NULL }, +}; +#undef OFFSET + +static const AVClass obu_demuxer_class = { + .class_name = "AV1 low overhead OBU demuxer", + .item_name = av_default_item_name, + .option = obu_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_obu_demuxer = { + .name = "obu", + .long_name = NULL_IF_CONFIG_SMALL("AV1 low overhead OBU"), + .priv_data_size = sizeof(ObuContext), + .read_probe = obu_probe, + .read_header = obu_read_header, + .read_packet = obu_read_packet, + .read_close = obu_read_close, + .extensions = "obu", + .flags = AVFMT_GENERIC_INDEX, + .priv_class = &obu_demuxer_class, +}; +#endif diff -Nru ffmpeg-4.2.2/libavformat/av1.h ffmpeg-4.4/libavformat/av1.h --- ffmpeg-4.2.2/libavformat/av1.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/av1.h 2020-07-11 10:39:30.000000000 +0000 @@ -56,20 +56,24 @@ int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size); /** - * Filter out AV1 OBUs not meant to be present in ISOBMFF sample data and write - * the resulting bitstream to a newly allocated data buffer. + * Filter out AV1 OBUs not meant to be present in ISOBMFF sample data and return + * the result in a data buffer, avoiding allocations and copies if possible. * - * @param pb pointer to the AVIOContext where the filtered bitstream shall be - * written - * @param buf input data buffer - * @param out pointer to pointer that will hold the allocated data buffer + * @param in input data buffer + * @param out pointer to pointer for the returned buffer. In case of success, + * it is independently allocated if and only if `*out` differs from in. * @param size size of the input data buffer. The size of the resulting output - data buffer will be written here - * - * @return the amount of bytes written in case of success, a negative AVERROR - * code in case of failure. On failure, out and size are unchanged + * data buffer will be written here + * @param offset offset of the returned data inside `*out`: It runs from + * `*out + offset` (inclusive) to `*out + offset + size` + * (exclusive); is zero if `*out` is independently allocated. + * + * @return 0 in case of success, a negative AVERROR code in case of failure. + * On failure, *out and *size are unchanged + * @note *out will be treated as unintialized on input and will not be freed. */ -int ff_av1_filter_obus_buf(const uint8_t *buf, uint8_t **out, int *size); +int ff_av1_filter_obus_buf(const uint8_t *in, uint8_t **out, + int *size, int *offset); /** * Parses a Sequence Header from the the provided buffer. @@ -87,7 +91,7 @@ * Writes AV1 extradata (Sequence Header and Metadata OBUs) to the provided * AVIOContext. * - * @param pb pointer to the AVIOContext where the hvcC shall be written + * @param pb pointer to the AVIOContext where the av1C box shall be written * @param buf input data buffer * @param size size in bytes of the input data buffer * diff -Nru ffmpeg-4.2.2/libavformat/avc.c ffmpeg-4.4/libavformat/avc.c --- ffmpeg-4.2.2/libavformat/avc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/avc.c 2021-04-08 21:28:40.000000000 +0000 @@ -25,8 +25,9 @@ #include "avformat.h" #include "avio.h" #include "avc.h" +#include "avio_internal.h" -static const uint8_t *ff_avc_find_startcode_internal(const uint8_t *p, const uint8_t *end) +static const uint8_t *avc_find_startcode_internal(const uint8_t *p, const uint8_t *end) { const uint8_t *a = p + 4 - ((intptr_t)p & 3); @@ -64,7 +65,7 @@ } const uint8_t *ff_avc_find_startcode(const uint8_t *p, const uint8_t *end){ - const uint8_t *out= ff_avc_find_startcode_internal(p, end); + const uint8_t *out = avc_find_startcode_internal(p, end); if(p 4) { @@ -160,12 +163,21 @@ } avio_wb16(pps_pb, size); avio_write(pps_pb, buf, size); + } else if (nal_type == 13) { /* SPS_EXT */ + nb_sps_ext++; + if (size > UINT16_MAX || nb_sps_ext >= 256) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + avio_wb16(sps_ext_pb, size); + avio_write(sps_ext_pb, buf, size); } buf += size; } - sps_size = avio_close_dyn_buf(sps_pb, &sps); - pps_size = avio_close_dyn_buf(pps_pb, &pps); + sps_size = avio_get_dyn_buf(sps_pb, &sps); + pps_size = avio_get_dyn_buf(pps_pb, &pps); + sps_ext_size = avio_get_dyn_buf(sps_ext_pb, &sps_ext); if (sps_size < 6 || !pps_size) { ret = AVERROR_INVALIDDATA; @@ -183,13 +195,24 @@ avio_w8(pb, nb_pps); /* number of pps */ avio_write(pb, pps, pps_size); + if (sps[3] != 66 && sps[3] != 77 && sps[3] != 88) { + H264SPS seq; + ret = ff_avc_decode_sps(&seq, sps + 3, sps_size - 3); + if (ret < 0) + goto fail; + + avio_w8(pb, 0xfc | seq.chroma_format_idc); /* 6 bits reserved (111111) + chroma_format_idc */ + avio_w8(pb, 0xf8 | (seq.bit_depth_luma - 8)); /* 5 bits reserved (11111) + bit_depth_luma_minus8 */ + avio_w8(pb, 0xf8 | (seq.bit_depth_chroma - 8)); /* 5 bits reserved (11111) + bit_depth_chroma_minus8 */ + avio_w8(pb, nb_sps_ext); /* number of sps ext */ + if (nb_sps_ext) + avio_write(pb, sps_ext, sps_ext_size); + } + fail: - if (!sps) - avio_close_dyn_buf(sps_pb, &sps); - if (!pps) - avio_close_dyn_buf(pps_pb, &pps); - av_free(sps); - av_free(pps); + ffio_free_dyn_buf(&sps_pb); + ffio_free_dyn_buf(&pps_pb); + ffio_free_dyn_buf(&sps_ext_pb); av_free(start); return ret; @@ -308,27 +331,24 @@ return ((v >> 1) ^ sign) - sign; } -H264SequenceParameterSet *ff_avc_decode_sps(const uint8_t *buf, int buf_size) +int ff_avc_decode_sps(H264SPS *sps, const uint8_t *buf, int buf_size) { int i, j, ret, rbsp_size, aspect_ratio_idc, pic_order_cnt_type; int num_ref_frames_in_pic_order_cnt_cycle; int delta_scale, lastScale = 8, nextScale = 8; int sizeOfScalingList; - H264SequenceParameterSet *sps = NULL; GetBitContext gb; uint8_t *rbsp_buf; rbsp_buf = ff_nal_unit_extract_rbsp(buf, buf_size, &rbsp_size, 0); if (!rbsp_buf) - return NULL; + return AVERROR(ENOMEM); ret = init_get_bits8(&gb, rbsp_buf, rbsp_size); if (ret < 0) goto end; - sps = av_mallocz(sizeof(*sps)); - if (!sps) - goto end; + memset(sps, 0, sizeof(*sps)); sps->profile_idc = get_bits(&gb, 8); sps->constraint_set_flags |= get_bits1(&gb) << 0; // constraint_set0_flag @@ -351,7 +371,7 @@ skip_bits1(&gb); // separate_colour_plane_flag } sps->bit_depth_luma = get_ue_golomb(&gb) + 8; - get_ue_golomb(&gb); // bit_depth_chroma_minus8 + sps->bit_depth_chroma = get_ue_golomb(&gb) + 8; skip_bits1(&gb); // qpprime_y_zero_transform_bypass_flag if (get_bits1(&gb)) { // seq_scaling_matrix_present_flag for (i = 0; i < ((sps->chroma_format_idc != 3) ? 8 : 12); i++) { @@ -372,6 +392,7 @@ } else { sps->chroma_format_idc = 1; sps->bit_depth_luma = 8; + sps->bit_depth_chroma = 8; } get_ue_golomb(&gb); // log2_max_frame_num_minus4 @@ -423,7 +444,8 @@ sps->sar.den = 1; } + ret = 0; end: av_free(rbsp_buf); - return sps; + return ret; } diff -Nru ffmpeg-4.2.2/libavformat/avc.h ffmpeg-4.4/libavformat/avc.h --- ffmpeg-4.2.2/libavformat/avc.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/avc.h 2020-07-11 10:39:32.000000000 +0000 @@ -43,10 +43,11 @@ uint8_t constraint_set_flags; uint8_t chroma_format_idc; uint8_t bit_depth_luma; + uint8_t bit_depth_chroma; uint8_t frame_mbs_only_flag; AVRational sar; -} H264SequenceParameterSet; +} H264SPS; -H264SequenceParameterSet *ff_avc_decode_sps(const uint8_t *src, int src_len); +int ff_avc_decode_sps(H264SPS *sps, const uint8_t *buf, int buf_size); #endif /* AVFORMAT_AVC_H */ diff -Nru ffmpeg-4.2.2/libavformat/avformat.h ffmpeg-4.4/libavformat/avformat.h --- ffmpeg-4.2.2/libavformat/avformat.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/avformat.h 2021-04-08 21:28:40.000000000 +0000 @@ -170,14 +170,9 @@ * information will be in AVStream.time_base units, i.e. it has to be * multiplied by the timebase to convert them to seconds. * - * If AVPacket.buf is set on the returned packet, then the packet is - * allocated dynamically and the user may keep it indefinitely. - * Otherwise, if AVPacket.buf is NULL, the packet data is backed by a - * static storage somewhere inside the demuxer and the packet is only valid - * until the next av_read_frame() call or closing the file. If the caller - * requires a longer lifetime, av_packet_make_refcounted() will ensure that - * the data is reference counted, copying the data if necessary. - * In both cases, the packet must be freed with av_packet_unref() when it is no + * A packet returned by av_read_frame() is always reference-counted, + * i.e. AVPacket.buf is set and the user may keep it indefinitely. + * The packet must be freed with av_packet_unref() when it is no * longer needed. * * @section lavf_decoding_seek Seeking @@ -361,7 +356,7 @@ * sorting will have '-sort' appended. E.g. artist="The Beatles", * artist-sort="Beatles, The". * - Some protocols and demuxers support metadata updates. After a successful - * call to av_read_packet(), AVFormatContext.event_flags or AVStream.event_flags + * call to av_read_frame(), AVFormatContext.event_flags or AVStream.event_flags * will be updated to indicate if metadata changed. In order to detect metadata * changes on a stream, you need to loop through all streams in the AVFormatContext * and check their individual event_flags. @@ -539,7 +534,9 @@ #else #define ff_const59 const #endif +#if FF_API_NEXT ff_const59 struct AVOutputFormat *next; +#endif /** * size of private data so that it can be allocated in the wrapper */ @@ -556,7 +553,8 @@ int (*write_packet)(struct AVFormatContext *, AVPacket *pkt); int (*write_trailer)(struct AVFormatContext *); /** - * Currently only used to set pixel format if not YUV420P. + * A format-specific function for interleavement. + * If unset, packets will be interleaved by dts. */ int (*interleave_packet)(struct AVFormatContext *, AVPacket *out, AVPacket *in, int flush); @@ -592,6 +590,7 @@ * @see avdevice_list_devices() for more details. */ int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list); +#if LIBAVFORMAT_VERSION_MAJOR < 59 /** * Initialize device capabilities submodule. * @see avdevice_capabilities_create() for more details. @@ -602,6 +601,7 @@ * @see avdevice_capabilities_free() for more details. */ int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps); +#endif enum AVCodecID data_codec; /**< default data codec */ /** * Initialize format. May allocate data here, and set any AVFormatContext or @@ -683,7 +683,9 @@ * New public fields should be added right above. ***************************************************************** */ +#if FF_API_NEXT ff_const59 struct AVInputFormat *next; +#endif /** * Raw demuxers store their codec ID here. @@ -715,8 +717,7 @@ * AVFMTCTX_NOHEADER is used and only in the calling thread (not in a * background thread). * @return 0 on success, < 0 on error. - * When returning an error, pkt must not have been allocated - * or must be freed before returning + * Upon returning an error, pkt must be unreferenced by the caller. */ int (*read_packet)(struct AVFormatContext *, AVPacket *pkt); @@ -770,6 +771,7 @@ */ int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list); +#if LIBAVFORMAT_VERSION_MAJOR < 59 /** * Initialize device capabilities submodule. * @see avdevice_capabilities_create() for more details. @@ -781,6 +783,7 @@ * @see avdevice_capabilities_free() for more details. */ int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps); +#endif } AVInputFormat; /** * @} @@ -978,12 +981,30 @@ int nb_side_data; /** - * Flags for the user to detect events happening on the stream. Flags must - * be cleared by the user once the event has been handled. - * A combination of AVSTREAM_EVENT_FLAG_*. + * Flags indicating events happening on the stream, a combination of + * AVSTREAM_EVENT_FLAG_*. + * + * - demuxing: may be set by the demuxer in avformat_open_input(), + * avformat_find_stream_info() and av_read_frame(). Flags must be cleared + * by the user once the event has been handled. + * - muxing: may be set by the user after avformat_write_header(). to + * indicate a user-triggered event. The muxer will clear the flags for + * events it has handled in av_[interleaved]_write_frame(). */ int event_flags; -#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata. +/** + * - demuxing: the demuxer read new metadata from the file and updated + * AVStream.metadata accordingly + * - muxing: the user updated AVStream.metadata and wishes the muxer to write + * it into the file + */ +#define AVSTREAM_EVENT_FLAG_METADATA_UPDATED 0x0001 +/** + * - demuxing: new packets for this stream were read from the file. This + * event is informational only and does not guarantee that new packets + * for this stream will necessarily be returned from av_read_frame(). + */ +#define AVSTREAM_EVENT_FLAG_NEW_PACKETS (1 << 1) /** * Real base framerate of the stream. @@ -1028,38 +1049,10 @@ ***************************************************************** */ -#define MAX_STD_TIMEBASES (30*12+30+3+6) - /** - * Stream information used internally by avformat_find_stream_info() - */ - struct { - int64_t last_dts; - int64_t duration_gcd; - int duration_count; - int64_t rfps_duration_sum; - double (*duration_error)[2][MAX_STD_TIMEBASES]; - int64_t codec_info_duration; - int64_t codec_info_duration_fields; - int frame_delay_evidence; - - /** - * 0 -> decoder has not been searched for yet. - * >0 -> decoder found - * <0 -> decoder with codec_id == -found_decoder has not been found - */ - int found_decoder; - - int64_t last_duration; - - /** - * Those are used for average framerate estimation. - */ - int64_t fps_first_dts; - int fps_first_dts_idx; - int64_t fps_last_dts; - int fps_last_dts_idx; - - } *info; +#if LIBAVFORMAT_VERSION_MAJOR < 59 + // kept for ABI compatibility only, do not access in any way + void *unused; +#endif int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */ @@ -1090,14 +1083,12 @@ enum AVStreamParseType need_parsing; struct AVCodecParserContext *parser; - /** - * last packet in packet_buffer for this stream when muxing. - */ - struct AVPacketList *last_in_packet_buffer; - AVProbeData probe_data; -#define MAX_REORDER_DELAY 16 - int64_t pts_buffer[MAX_REORDER_DELAY+1]; - +#if LIBAVFORMAT_VERSION_MAJOR < 59 + // kept for ABI compatibility only, do not access in any way + void *unused7; + AVProbeData unused6; + int64_t unused5[16+1]; +#endif AVIndexEntry *index_entries; /**< Only used if the format does not support seeking natively. */ int nb_index_entries; @@ -1110,117 +1101,12 @@ */ int stream_identifier; - /** - * Details of the MPEG-TS program which created this stream. - */ - int program_num; - int pmt_version; - int pmt_stream_idx; - - int64_t interleaver_chunk_size; - int64_t interleaver_chunk_duration; - - /** - * stream probing state - * -1 -> probing finished - * 0 -> no probing requested - * rest -> perform probing with request_probe being the minimum score to accept. - * NOT PART OF PUBLIC API - */ - int request_probe; - /** - * Indicates that everything up to the next keyframe - * should be discarded. - */ - int skip_to_keyframe; - - /** - * Number of samples to skip at the start of the frame decoded from the next packet. - */ - int skip_samples; - - /** - * If not 0, the number of samples that should be skipped from the start of - * the stream (the samples are removed from packets with pts==0, which also - * assumes negative timestamps do not happen). - * Intended for use with formats such as mp3 with ad-hoc gapless audio - * support. - */ - int64_t start_skip_samples; - - /** - * If not 0, the first audio sample that should be discarded from the stream. - * This is broken by design (needs global sample count), but can't be - * avoided for broken by design formats such as mp3 with ad-hoc gapless - * audio support. - */ - int64_t first_discard_sample; - - /** - * The sample after last sample that is intended to be discarded after - * first_discard_sample. Works on frame boundaries only. Used to prevent - * early EOF if the gapless info is broken (considered concatenated mp3s). - */ - int64_t last_discard_sample; - - /** - * Number of internally decoded frames, used internally in libavformat, do not access - * its lifetime differs from info which is why it is not in that structure. - */ - int nb_decoded_frames; - - /** - * Timestamp offset added to timestamps before muxing - * NOT PART OF PUBLIC API - */ - int64_t mux_ts_offset; - - /** - * Internal data to check for wrapping of the time stamp - */ - int64_t pts_wrap_reference; - - /** - * Options for behavior, when a wrap is detected. - * - * Defined by AV_PTS_WRAP_ values. - * - * If correction is enabled, there are two possibilities: - * If the first time stamp is near the wrap point, the wrap offset - * will be subtracted, which will create negative time stamps. - * Otherwise the offset will be added. - */ - int pts_wrap_behavior; - - /** - * Internal data to prevent doing update_initial_durations() twice - */ - int update_initial_durations_done; - - /** - * Internal data to generate dts from pts - */ - int64_t pts_reorder_error[MAX_REORDER_DELAY+1]; - uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1]; - - /** - * Internal data to analyze DTS and detect faulty mpeg streams - */ - int64_t last_dts_for_order_check; - uint8_t dts_ordered; - uint8_t dts_misordered; - - /** - * Internal data to inject global side data - */ - int inject_global_side_data; - - /** - * display aspect ratio (0 if unknown) - * - encoding: unused - * - decoding: Set by libavformat to calculate sample_aspect_ratio internally - */ - AVRational display_aspect_ratio; +#if LIBAVFORMAT_VERSION_MAJOR < 59 + // kept for ABI compatibility only, do not access in any way + int unused8; + int unused9; + int unused10; +#endif /** * An opaque field for libavformat internal usage. @@ -1299,7 +1185,11 @@ change dynamically at runtime. */ typedef struct AVChapter { +#if FF_API_CHAPTER_ID_INT int id; ///< unique ID to identify the chapter +#else + int64_t id; ///< unique ID to identify the chapter +#endif AVRational time_base; ///< time base in which the start/end timestamps are specified int64_t start, end; ///< chapter start/end time in time_base units AVDictionary *metadata; @@ -1494,7 +1384,9 @@ #define AVFMT_FLAG_MP4A_LATM 0x8000 ///< Deprecated, does nothing. #endif #define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down) -#define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (this could be made default once all code is converted) +#if FF_API_LAVF_PRIV_OPT +#define AVFMT_FLAG_PRIV_OPT 0x20000 ///< Enable use of private options by delaying codec open (deprecated, will do nothing once av_demuxer_open() is removed) +#endif #if FF_API_LAVF_KEEPSIDE_FLAG #define AVFMT_FLAG_KEEP_SIDE_DATA 0x40000 ///< Deprecated, does nothing. #endif @@ -1652,12 +1544,24 @@ int strict_std_compliance; /** - * Flags for the user to detect events happening on the file. Flags must - * be cleared by the user once the event has been handled. - * A combination of AVFMT_EVENT_FLAG_*. + * Flags indicating events happening on the file, a combination of + * AVFMT_EVENT_FLAG_*. + * + * - demuxing: may be set by the demuxer in avformat_open_input(), + * avformat_find_stream_info() and av_read_frame(). Flags must be cleared + * by the user once the event has been handled. + * - muxing: may be set by the user after avformat_write_header() to + * indicate a user-triggered event. The muxer will clear the flags for + * events it has handled in av_[interleaved]_write_frame(). */ int event_flags; -#define AVFMT_EVENT_FLAG_METADATA_UPDATED 0x0001 ///< The call resulted in updated metadata. +/** + * - demuxing: the demuxer read new metadata from the file and updated + * AVFormatContext.metadata accordingly + * - muxing: the user updated AVFormatContext.metadata and wishes the muxer to + * write it into the file + */ +#define AVFMT_EVENT_FLAG_METADATA_UPDATED 0x0001 /** * Maximum number of packets to read while waiting for the first timestamp. @@ -1951,6 +1855,13 @@ * - decoding: set by user */ int skip_estimate_duration_from_pts; + + /** + * Maximum number of packets that can be probed + * - encoding: unused + * - decoding: set by user + */ + int max_probe_packets; } AVFormatContext; #if FF_API_FORMAT_GET_SET @@ -2007,12 +1918,6 @@ */ enum AVDurationEstimationMethod av_fmt_ctx_get_duration_estimation_method(const AVFormatContext* ctx); -typedef struct AVPacketList { - AVPacket pkt; - struct AVPacketList *next; -} AVPacketList; - - /** * @defgroup lavf_core Core functions * @ingroup libavf @@ -2183,17 +2088,26 @@ * @return pointer to fresh allocated data or NULL otherwise */ uint8_t *av_stream_new_side_data(AVStream *stream, +#if FF_API_BUFFER_SIZE_T enum AVPacketSideDataType type, int size); +#else + enum AVPacketSideDataType type, size_t size); +#endif /** * Get side information from stream. * * @param stream stream * @param type desired side information type - * @param size pointer for side information size to store (optional) + * @param size If supplied, *size will be set to the size of the side data + * or to zero if the desired side data is not present. * @return pointer to data if present or NULL otherwise */ uint8_t *av_stream_get_side_data(const AVStream *stream, +#if FF_API_BUFFER_SIZE_T enum AVPacketSideDataType type, int *size); +#else + enum AVPacketSideDataType type, size_t *size); +#endif AVProgram *av_new_program(AVFormatContext *s, int id); @@ -2311,8 +2225,13 @@ */ int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options); +#if FF_API_DEMUXER_OPEN +/** + * @deprecated Use an AVDictionary to pass options to a demuxer. + */ attribute_deprecated int av_demuxer_open(AVFormatContext *ic); +#endif /** * Read packets of a media file to get stream information. This @@ -2390,13 +2309,12 @@ * omit invalid data between valid frames so as to give the decoder the maximum * information possible for decoding. * - * If pkt->buf is NULL, then the packet is valid until the next - * av_read_frame() or until avformat_close_input(). Otherwise the packet - * is valid indefinitely. In both cases the packet must be freed with - * av_packet_unref when it is no longer needed. For video, the packet contains - * exactly one frame. For audio, it contains an integer number of frames if each - * frame has a known fixed size (e.g. PCM or ADPCM data). If the audio frames - * have a variable size (e.g. MPEG audio), then it contains one frame. + * On success, the returned packet is reference-counted (pkt->buf is set) and + * valid indefinitely. The packet must be freed with av_packet_unref() when + * it is no longer needed. For video, the packet contains exactly one frame. + * For audio, it contains an integer number of frames if each frame has + * a known fixed size (e.g. PCM or ADPCM data). If the audio frames have + * a variable size (e.g. MPEG audio), then it contains one frame. * * pkt->pts, pkt->dts and pkt->duration are always set to correct * values in AVStream.time_base units (and guessed if the format cannot @@ -2404,7 +2322,11 @@ * has B-frames, so it is better to rely on pkt->dts if you do not * decompress the payload. * - * @return 0 if OK, < 0 on error or end of file + * @return 0 if OK, < 0 on error or end of file. On error, pkt will be blank + * (as if it came from av_packet_alloc()). + * + * @note pkt will be initialized, so it may be uninitialized, but it must not + * contain data that needs to be freed. */ int av_read_frame(AVFormatContext *s, AVPacket *pkt); @@ -2449,8 +2371,6 @@ * @return >=0 on success, error code otherwise * * @note This is part of the new seek API which is still under construction. - * Thus do not use this yet. It may change at any time, do not expect - * ABI compatibility yet! */ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags); @@ -2637,9 +2557,9 @@ * Write an uncoded frame to an output media file. * * The frame must be correctly interleaved according to the container - * specification; if not, then av_interleaved_write_frame() must be used. + * specification; if not, av_interleaved_write_uncoded_frame() must be used. * - * See av_interleaved_write_frame() for details. + * See av_interleaved_write_uncoded_frame() for details. */ int av_write_uncoded_frame(AVFormatContext *s, int stream_index, AVFrame *frame); diff -Nru ffmpeg-4.2.2/libavformat/avidec.c ffmpeg-4.4/libavformat/avidec.c --- ffmpeg-4.2.2/libavformat/avidec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/avidec.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,7 +23,6 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" -#include "libavutil/bswap.h" #include "libavutil/opt.h" #include "libavutil/dict.h" #include "libavutil/internal.h" @@ -60,8 +59,8 @@ * the MS dshow demuxer */ AVFormatContext *sub_ctx; - AVPacket sub_pkt; - uint8_t *sub_buffer; + AVPacket *sub_pkt; + AVBufferRef *sub_buffer; int64_t seek_pos; } AVIStream; @@ -111,14 +110,24 @@ static const AVMetadataConv avi_metadata_conv[] = { { "strn", "title" }, + { "isbj", "subject" }, + { "inam", "title" }, + { "iart", "artist" }, + { "icop", "copyright" }, + { "icmt", "comment" }, + { "ignr", "genre" }, + { "iprd", "product" }, + { "isft", "software" }, + { 0 }, }; +static int avi_read_close(AVFormatContext *s); static int avi_load_index(AVFormatContext *s); static int guess_ni_flag(AVFormatContext *s); -#define print_tag(str, tag, size) \ - av_log(NULL, AV_LOG_TRACE, "pos:%"PRIX64" %s: tag=%s size=0x%x\n", \ +#define print_tag(s, str, tag, size) \ + av_log(s, AV_LOG_TRACE, "pos:%"PRIX64" %s: tag=%s size=0x%x\n", \ avio_tell(pb), str, av_fourcc2str(tag), size) \ static inline int get_duration(AVIStream *ast, int len) @@ -126,7 +135,7 @@ if (ast->sample_size) return len; else if (ast->dshow_block_align) - return (len + ast->dshow_block_align - 1) / ast->dshow_block_align; + return (len + (int64_t)ast->dshow_block_align - 1) / ast->dshow_block_align; else return 1; } @@ -306,8 +315,10 @@ value = av_malloc(size + 1); if (!value) return AVERROR(ENOMEM); - if (avio_read(pb, value, size) != size) + if (avio_read(pb, value, size) != size) { + av_freep(&value); return AVERROR_INVALIDDATA; + } value[size] = 0; AV_WL32(key, tag); @@ -438,7 +449,7 @@ maxpos = FFMAX(maxpos, st->index_entries[j-1].pos); lensum += len; } - if (maxpos < avi->io_fsize*9/10) // index does not cover the whole file + if (maxpos < av_rescale(avi->io_fsize, 9, 10)) // index does not cover the whole file return 0; if (lensum*9/10 > maxpos || lensum < maxpos*9/10) // frame sum and filesize mismatch return 0; @@ -463,6 +474,7 @@ return 1; } +#define RETURN_ERROR(code) do { ret = (code); goto fail; } while (0) static int avi_read_header(AVFormatContext *s) { AVIContext *avi = s->priv_data; @@ -498,11 +510,11 @@ frame_period = 0; for (;;) { if (avio_feof(pb)) - goto fail; + RETURN_ERROR(AVERROR_INVALIDDATA); tag = avio_rl32(pb); size = avio_rl32(pb); - print_tag("tag", tag, size); + print_tag(s, "tag", tag, size); switch (tag) { case MKTAG('L', 'I', 'S', 'T'): @@ -510,7 +522,7 @@ /* Ignored, except at start of video packets. */ tag1 = avio_rl32(pb); - print_tag("list", tag1, 0); + print_tag(s, "list", tag1, 0); if (tag1 == MKTAG('m', 'o', 'v', 'i')) { avi->movi_list = avio_tell(pb) - 4; @@ -518,7 +530,7 @@ avi->movi_end = avi->movi_list + size + (size & 1); else avi->movi_end = avi->fsize; - av_log(NULL, AV_LOG_TRACE, "movi end=%"PRIx64"\n", avi->movi_end); + av_log(s, AV_LOG_TRACE, "movi end=%"PRIx64"\n", avi->movi_end); goto end_of_header; } else if (tag1 == MKTAG('I', 'N', 'F', 'O')) ff_read_riff_info(s, size - 4); @@ -570,19 +582,19 @@ stream_index++; st = avformat_new_stream(s, NULL); if (!st) - goto fail; + RETURN_ERROR(AVERROR(ENOMEM)); st->id = stream_index; ast = av_mallocz(sizeof(AVIStream)); if (!ast) - goto fail; + RETURN_ERROR(AVERROR(ENOMEM)); st->priv_data = ast; } if (amv_file_format) tag1 = stream_index ? MKTAG('a', 'u', 'd', 's') : MKTAG('v', 'i', 'd', 's'); - print_tag("strh", tag1, -1); + print_tag(s, "strh", tag1, -1); if (tag1 == MKTAG('i', 'a', 'v', 's') || tag1 == MKTAG('i', 'v', 'a', 's')) { @@ -591,35 +603,26 @@ /* After some consideration -- I don't think we * have to support anything but DV in type1 AVIs. */ if (s->nb_streams != 1) - goto fail; + RETURN_ERROR(AVERROR_INVALIDDATA); if (handler != MKTAG('d', 'v', 's', 'd') && handler != MKTAG('d', 'v', 'h', 'd') && handler != MKTAG('d', 'v', 's', 'l')) - goto fail; + return AVERROR_INVALIDDATA; + + if (!CONFIG_DV_DEMUXER) + return AVERROR_DEMUXER_NOT_FOUND; ast = s->streams[0]->priv_data; - av_freep(&s->streams[0]->codecpar->extradata); - av_freep(&s->streams[0]->codecpar); -#if FF_API_LAVF_AVCTX -FF_DISABLE_DEPRECATION_WARNINGS - av_freep(&s->streams[0]->codec); -FF_ENABLE_DEPRECATION_WARNINGS -#endif - if (s->streams[0]->info) - av_freep(&s->streams[0]->info->duration_error); - av_freep(&s->streams[0]->info); - if (s->streams[0]->internal) - av_freep(&s->streams[0]->internal->avctx); - av_freep(&s->streams[0]->internal); - av_freep(&s->streams[0]); - s->nb_streams = 0; - if (CONFIG_DV_DEMUXER) { - avi->dv_demux = avpriv_dv_init_demux(s); - if (!avi->dv_demux) - goto fail; - } else - goto fail; + st->priv_data = NULL; + ff_free_stream(s, st); + + avi->dv_demux = avpriv_dv_init_demux(s); + if (!avi->dv_demux) { + av_free(ast); + return AVERROR(ENOMEM); + } + s->streams[0]->priv_data = ast; avio_skip(pb, 3 * 4); ast->scale = avio_rl32(pb); @@ -705,7 +708,7 @@ "Invalid sample_size %d at stream %d\n", ast->sample_size, stream_index); - goto fail; + RETURN_ERROR(AVERROR_INVALIDDATA); } av_log(s, AV_LOG_WARNING, "Invalid sample_size %d at stream %d " @@ -769,10 +772,11 @@ st->codecpar->extradata_size = size - 10 * 4; if (st->codecpar->extradata) { av_log(s, AV_LOG_WARNING, "New extradata in strf chunk, freeing previous one.\n"); - av_freep(&st->codecpar->extradata); } - if (ff_get_extradata(s, st->codecpar, pb, st->codecpar->extradata_size) < 0) - return AVERROR(ENOMEM); + ret = ff_get_extradata(s, st->codecpar, pb, + st->codecpar->extradata_size); + if (ret < 0) + return ret; } // FIXME: check if the encoder really did this correctly @@ -800,7 +804,7 @@ ast->has_pal = 1; } - print_tag("video", tag1, 0); + print_tag(s, "video", tag1, 0); st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; st->codecpar->codec_tag = tag1; @@ -830,6 +834,15 @@ st->need_parsing = AVSTREAM_PARSE_FULL; if (st->codecpar->codec_id == AV_CODEC_ID_RV40) st->need_parsing = AVSTREAM_PARSE_NONE; + if (st->codecpar->codec_id == AV_CODEC_ID_HEVC && + st->codecpar->codec_tag == MKTAG('H', '2', '6', '5')) + st->need_parsing = AVSTREAM_PARSE_FULL; + + if (st->codecpar->codec_id == AV_CODEC_ID_AVRN && + st->codecpar->codec_tag == MKTAG('A', 'V', 'R', 'n') && + (st->codecpar->extradata_size < 31 || + memcmp(&st->codecpar->extradata[28], "1:1", 3))) + st->codecpar->codec_id = AV_CODEC_ID_MJPEG; if (st->codecpar->codec_tag == 0 && st->codecpar->height > 0 && st->codecpar->extradata_size < 1U << 30) { @@ -903,7 +916,7 @@ break; case AVMEDIA_TYPE_SUBTITLE: st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; - st->request_probe= 1; + st->internal->request_probe= 1; avio_skip(pb, size); break; default: @@ -929,10 +942,9 @@ if (size<(1<<30)) { if (st->codecpar->extradata) { av_log(s, AV_LOG_WARNING, "New extradata in strd chunk, freeing previous one.\n"); - av_freep(&st->codecpar->extradata); } - if (ff_get_extradata(s, st->codecpar, pb, size) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_get_extradata(s, st->codecpar, pb, size)) < 0) + goto fail; } if (st->codecpar->extradata_size & 1) //FIXME check if the encoder really did this correctly @@ -950,7 +962,7 @@ avi->use_odml && read_odml_index(s, 0) < 0 && (s->error_recognition & AV_EF_EXPLODE)) - goto fail; + RETURN_ERROR(AVERROR_INVALIDDATA); avio_seek(pb, pos + size, SEEK_SET); break; case MKTAG('v', 'p', 'r', 'p'): @@ -982,10 +994,18 @@ avio_skip(pb, size); break; case MKTAG('s', 't', 'r', 'n'): + case MKTAG('i', 's', 'b', 'j'): + case MKTAG('i', 'n', 'a', 'm'): + case MKTAG('i', 'a', 'r', 't'): + case MKTAG('i', 'c', 'o', 'p'): + case MKTAG('i', 'c', 'm', 't'): + case MKTAG('i', 'g', 'n', 'r'): + case MKTAG('i', 'p', 'o', 'd'): + case MKTAG('i', 's', 'o', 'f'): if (s->nb_streams) { ret = avi_read_tag(s, s->streams[s->nb_streams - 1], tag, size); if (ret < 0) - return ret; + goto fail; break; } default: @@ -996,7 +1016,7 @@ "I will ignore it and try to continue anyway.\n", av_fourcc2str(tag), size); if (s->error_recognition & AV_EF_EXPLODE) - goto fail; + RETURN_ERROR(AVERROR_INVALIDDATA); avi->movi_list = avio_tell(pb) - 4; avi->movi_end = avi->fsize; goto end_of_header; @@ -1013,9 +1033,7 @@ end_of_header: /* check stream number */ if (stream_index != s->nb_streams - 1) { - -fail: - return AVERROR_INVALIDDATA; + RETURN_ERROR(AVERROR_INVALIDDATA); } if (!avi->index_loaded && (pb->seekable & AVIO_SEEKABLE_NORMAL)) @@ -1024,7 +1042,7 @@ avi->index_loaded |= 1; if ((ret = guess_ni_flag(s)) < 0) - return ret; + goto fail; avi->non_interleaved |= ret | (s->flags & AVFMT_FLAG_SORT_DTS); @@ -1061,6 +1079,9 @@ ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv); return 0; +fail: + avi_read_close(s); + return ret; } static int read_gab2_sub(AVFormatContext *s, AVStream *st, AVPacket *pkt) @@ -1074,11 +1095,15 @@ ff_const59 AVInputFormat *sub_demuxer; AVRational time_base; int size; + AVProbeData pd; + unsigned int desc_len; AVIOContext *pb = avio_alloc_context(pkt->data + 7, pkt->size - 7, 0, NULL, NULL, NULL, NULL); - AVProbeData pd; - unsigned int desc_len = avio_rl32(pb); + if (!pb) + goto error; + + desc_len = avio_rl32(pb); if (desc_len > pb->buf_end - pb->buf_ptr) goto error; @@ -1105,6 +1130,9 @@ if (strcmp(sub_demuxer->name, "srt") && strcmp(sub_demuxer->name, "ass")) goto error; + if (!(ast->sub_pkt = av_packet_alloc())) + goto error; + if (!(ast->sub_ctx = avformat_alloc_context())) goto error; @@ -1116,16 +1144,18 @@ if (!avformat_open_input(&ast->sub_ctx, "", sub_demuxer, NULL)) { if (ast->sub_ctx->nb_streams != 1) goto error; - ff_read_packet(ast->sub_ctx, &ast->sub_pkt); + ff_read_packet(ast->sub_ctx, ast->sub_pkt); avcodec_parameters_copy(st->codecpar, ast->sub_ctx->streams[0]->codecpar); time_base = ast->sub_ctx->streams[0]->time_base; avpriv_set_pts_info(st, 64, time_base.num, time_base.den); } - ast->sub_buffer = pkt->data; - memset(pkt, 0, sizeof(*pkt)); + ast->sub_buffer = pkt->buf; + pkt->buf = NULL; + av_packet_unref(pkt); return 1; error: + av_packet_free(&ast->sub_pkt); av_freep(&ast->sub_ctx); avio_context_free(&pb); } @@ -1146,8 +1176,8 @@ for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; ast = st->priv_data; - if (st->discard < AVDISCARD_ALL && ast && ast->sub_pkt.data) { - ts = av_rescale_q(ast->sub_pkt.dts, st->time_base, AV_TIME_BASE_Q); + if (st->discard < AVDISCARD_ALL && ast && ast->sub_pkt && ast->sub_pkt->data) { + ts = av_rescale_q(ast->sub_pkt->dts, st->time_base, AV_TIME_BASE_Q); if (ts <= next_ts && ts < ts_min) { ts_min = ts; sub_st = st; @@ -1157,11 +1187,11 @@ if (sub_st) { ast = sub_st->priv_data; - *pkt = ast->sub_pkt; + av_packet_move_ref(pkt, ast->sub_pkt); pkt->stream_index = sub_st->index; - if (ff_read_packet(ast->sub_ctx, &ast->sub_pkt) < 0) - ast->sub_pkt.data = NULL; + if (ff_read_packet(ast->sub_ctx, ast->sub_pkt) < 0) + ast->sub_pkt->data = NULL; } return sub_st; } @@ -1258,7 +1288,7 @@ AVStream *st1 = s->streams[1]; AVIStream *ast1 = st1->priv_data; // workaround for broken small-file-bug402.avi - if ( d[2] == 'w' && d[3] == 'b' + if (ast1 && d[2] == 'w' && d[3] == 'b' && n == 0 && st ->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st1->codecpar->codec_type == AVMEDIA_TYPE_AUDIO @@ -1426,6 +1456,7 @@ if (avi->stream_index >= 0) { AVStream *st = s->streams[avi->stream_index]; AVIStream *ast = st->priv_data; + int dv_demux = CONFIG_DV_DEMUXER && avi->dv_demux; int size, err; if (get_subtitle_pkt(s, st, pkt)) @@ -1448,7 +1479,7 @@ return err; size = err; - if (ast->has_pal && pkt->size < (unsigned)INT_MAX / 2) { + if (ast->has_pal && pkt->size < (unsigned)INT_MAX / 2 && !dv_demux) { uint8_t *pal; pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, @@ -1462,7 +1493,7 @@ } } - if (CONFIG_DV_DEMUXER && avi->dv_demux) { + if (CONFIG_DV_DEMUXER && dv_demux) { AVBufferRef *avbuf = pkt->buf; size = avpriv_dv_produce_packet(avi->dv_demux, pkt, pkt->data, pkt->size, pkt->pos); @@ -1531,11 +1562,12 @@ if (!avi->non_interleaved && st->nb_index_entries>1 && avi->index_loaded>1) { int64_t dts= av_rescale_q(pkt->dts, st->time_base, AV_TIME_BASE_Q); - if (avi->dts_max - dts > 2*AV_TIME_BASE) { + if (avi->dts_max < dts) { + avi->dts_max = dts; + } else if (avi->dts_max - (uint64_t)dts > 2*AV_TIME_BASE) { avi->non_interleaved= 1; av_log(s, AV_LOG_INFO, "Switching to NI mode, due to poor interleaving\n"); - }else if (avi->dts_max < dts) - avi->dts_max = dts; + } } return 0; @@ -1670,18 +1702,19 @@ AVIStream *ast = st->priv_data; if (idx[i] && min_dts != INT64_MAX / 2) { - int64_t dts; + int64_t dts, delta_dts; dts = av_rescale_q(st->index_entries[idx[i] - 1].timestamp / FFMAX(ast->sample_size, 1), st->time_base, AV_TIME_BASE_Q); + delta_dts = av_sat_sub64(dts, min_dts); max_dts = FFMAX(max_dts, dts); max_buffer = FFMAX(max_buffer, - av_rescale(dts - min_dts, + av_rescale(delta_dts, st->codecpar->bit_rate, AV_TIME_BASE)); } } - if (max_dts - min_dts > 2 * AV_TIME_BASE || + if (av_sat_sub64(max_dts, min_dts) > 2 * AV_TIME_BASE || max_buffer > 1024 * 1024 * 8 * 8) { av_free(idx); return 1; @@ -1777,10 +1810,10 @@ { AVIStream *ast2 = st2->priv_data; int64_t ts2 = av_rescale_q(timestamp, st->time_base, st2->time_base); - av_packet_unref(&ast2->sub_pkt); + av_packet_unref(ast2->sub_pkt); if (avformat_seek_file(ast2->sub_ctx, 0, INT64_MIN, ts2, ts2, 0) >= 0 || avformat_seek_file(ast2->sub_ctx, 0, ts2, ts2, INT64_MAX, 0) >= 0) - ff_read_packet(ast2->sub_ctx, &ast2->sub_pkt); + ff_read_packet(ast2->sub_ctx, ast2->sub_pkt); } static int avi_read_seek(AVFormatContext *s, int stream_index, @@ -1913,8 +1946,8 @@ av_freep(&ast->sub_ctx->pb); avformat_close_input(&ast->sub_ctx); } - av_freep(&ast->sub_buffer); - av_packet_unref(&ast->sub_pkt); + av_buffer_unref(&ast->sub_buffer); + av_packet_free(&ast->sub_pkt); } } diff -Nru ffmpeg-4.2.2/libavformat/avienc.c ffmpeg-4.4/libavformat/avienc.c --- ffmpeg-4.2.2/libavformat/avienc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/avienc.c 2021-04-08 21:28:40.000000000 +0000 @@ -31,7 +31,6 @@ #include "libavutil/avstring.h" #include "libavutil/avutil.h" #include "libavutil/internal.h" -#include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "libavutil/avassert.h" #include "libavutil/timestamp.h" @@ -67,12 +66,14 @@ typedef struct AVIContext { const AVClass *class; + AVPacket *empty_packet; int64_t riff_start, movi_list, odml_list; int64_t frames_hdr_all; int riff_id; int reserve_index_space; int master_index_max_size; int write_channel_mask; + int flipped_raw_rgb; } AVIContext; typedef struct AVIStream { @@ -269,11 +270,15 @@ int padding; if (s->nb_streams > AVI_MAX_STREAM_COUNT) { - av_log(s, AV_LOG_ERROR, "AVI does not support >%d streams\n", - AVI_MAX_STREAM_COUNT); + av_log(s, AV_LOG_ERROR, "AVI does not support " + ">"AV_STRINGIFY(AVI_MAX_STREAM_COUNT)" streams\n"); return AVERROR(EINVAL); } + avi->empty_packet = av_packet_alloc(); + if (!avi->empty_packet) + return AVERROR(ENOMEM); + for (n = 0; n < s->nb_streams; n++) { s->streams[n]->priv_data = av_mallocz(sizeof(AVIStream)); if (!s->streams[n]->priv_data) @@ -450,7 +455,7 @@ && par->bits_per_coded_sample == 15) par->bits_per_coded_sample = 16; avist->pal_offset = avio_tell(pb) + 40; - ff_put_bmp_header(pb, par, 0, 0); + ff_put_bmp_header(pb, par, 0, 0, avi->flipped_raw_rgb); pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, par->bits_per_coded_sample); if ( !par->codec_tag @@ -459,6 +464,14 @@ && par->format != AV_PIX_FMT_NONE) av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to avi, output file will be unreadable\n", av_get_pix_fmt_name(par->format)); + + if (par->format == AV_PIX_FMT_PAL8) { + if (par->bits_per_coded_sample < 0 || par->bits_per_coded_sample > 8) { + av_log(s, AV_LOG_ERROR, "PAL8 with %d bps is not allowed\n", par->bits_per_coded_sample); + return AVERROR(EINVAL); + } + } + break; case AVMEDIA_TYPE_AUDIO: flags = (avi->write_channel_mask == 0) ? FF_PUT_WAV_HEADER_SKIP_CHANNELMASK : 0; @@ -581,8 +594,6 @@ avi->movi_list = ff_start_tag(pb, "LIST"); ffio_wfourcc(pb, "movi"); - avio_flush(pb); - return 0; } @@ -594,7 +605,6 @@ int64_t pos; int au_byterate, au_ssize, au_scale; - avio_flush(pb); pos = avio_tell(pb); /* Updating one entry in the AVI OpenDML master index */ @@ -734,24 +744,21 @@ static int write_skip_frames(AVFormatContext *s, int stream_index, int64_t dts) { + AVIContext *avi = s->priv_data; AVIStream *avist = s->streams[stream_index]->priv_data; AVCodecParameters *par = s->streams[stream_index]->codecpar; ff_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(dts), avist->packet_count, stream_index); while (par->block_align == 0 && dts != AV_NOPTS_VALUE && dts > avist->packet_count && par->codec_id != AV_CODEC_ID_XSUB && avist->packet_count) { - AVPacket empty_packet; if (dts - avist->packet_count > 60000) { av_log(s, AV_LOG_ERROR, "Too large number of skipped frames %"PRId64" > 60000\n", dts - avist->packet_count); return AVERROR(EINVAL); } - av_init_packet(&empty_packet); - empty_packet.size = 0; - empty_packet.data = NULL; - empty_packet.stream_index = stream_index; - avi_write_packet_internal(s, &empty_packet); + avi->empty_packet->stream_index = stream_index; + avi_write_packet_internal(s, avi->empty_packet); ff_dlog(s, "dup dts:%s packet_count:%d\n", av_ts2str(dts), avist->packet_count); } @@ -909,7 +916,7 @@ AVIContext *avi = s->priv_data; AVIOContext *pb = s->pb; int res = 0; - int i, j, n, nb_frames; + int i, n, nb_frames; int64_t file_size; for (i = 0; i < s->nb_streams; i++) { @@ -962,10 +969,6 @@ for (i = 0; i < s->nb_streams; i++) { AVIStream *avist = s->streams[i]->priv_data; - for (j = 0; j < avist->indexes.ents_allocated / AVI_INDEX_CLUSTER_SIZE; j++) - av_freep(&avist->indexes.cluster[j]); - av_freep(&avist->indexes.cluster); - avist->indexes.ents_allocated = avist->indexes.entry = 0; if (pb->seekable & AVIO_SEEKABLE_NORMAL) { avio_seek(pb, avist->frames_hdr_strm + 4, SEEK_SET); avio_wl32(pb, avist->max_size); @@ -975,11 +978,29 @@ return res; } +static void avi_deinit(AVFormatContext *s) +{ + AVIContext *avi = s->priv_data; + + av_packet_free(&avi->empty_packet); + + for (int i = 0; i < s->nb_streams; i++) { + AVIStream *avist = s->streams[i]->priv_data; + if (!avist) + continue; + for (int j = 0; j < avist->indexes.ents_allocated / AVI_INDEX_CLUSTER_SIZE; j++) + av_freep(&avist->indexes.cluster[j]); + av_freep(&avist->indexes.cluster); + avist->indexes.ents_allocated = avist->indexes.entry = 0; + } +} + #define OFFSET(x) offsetof(AVIContext, x) #define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "reserve_index_space", "reserve space (in bytes) at the beginning of the file for each stream index", OFFSET(reserve_index_space), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, ENC }, { "write_channel_mask", "write channel mask into wave format header", OFFSET(write_channel_mask), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, ENC }, + { "flipped_raw_rgb", "Raw RGB bitmaps are stored bottom-up", OFFSET(flipped_raw_rgb), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC }, { NULL }, }; @@ -999,11 +1020,10 @@ .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_AC3, .video_codec = AV_CODEC_ID_MPEG4, .init = avi_init, + .deinit = avi_deinit, .write_header = avi_write_header, .write_packet = avi_write_packet, .write_trailer = avi_write_trailer, - .codec_tag = (const AVCodecTag * const []) { - ff_codec_bmp_tags, ff_codec_wav_tags, 0 - }, + .codec_tag = ff_riff_codec_tags_list, .priv_class = &avi_muxer_class, }; diff -Nru ffmpeg-4.2.2/libavformat/aviobuf.c ffmpeg-4.4/libavformat/aviobuf.c --- ffmpeg-4.2.2/libavformat/aviobuf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/aviobuf.c 2021-04-08 21:28:40.000000000 +0000 @@ -40,29 +40,33 @@ * data instead of calling the protocol seek function, for seekable * protocols. */ -#define SHORT_SEEK_THRESHOLD 4096 - -typedef struct AVIOInternal { - URLContext *h; -} AVIOInternal; +#define SHORT_SEEK_THRESHOLD 32768 static void *ff_avio_child_next(void *obj, void *prev) { AVIOContext *s = obj; - AVIOInternal *internal = s->opaque; - return prev ? NULL : internal->h; + return prev ? NULL : s->opaque; } +#if FF_API_CHILD_CLASS_NEXT static const AVClass *ff_avio_child_class_next(const AVClass *prev) { return prev ? NULL : &ffurl_context_class; } +#endif + +static const AVClass *child_class_iterate(void **iter) +{ + const AVClass *c = *iter ? NULL : &ffurl_context_class; + *iter = (void*)(uintptr_t)c; + return c; +} #define OFFSET(x) offsetof(AVIOContext,x) #define E AV_OPT_FLAG_ENCODING_PARAM #define D AV_OPT_FLAG_DECODING_PARAM static const AVOption ff_avio_options[] = { - {"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D }, + {"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, { NULL }, }; @@ -72,7 +76,10 @@ .version = LIBAVUTIL_VERSION_INT, .option = ff_avio_options, .child_next = ff_avio_child_next, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = ff_avio_child_class_next, +#endif + .child_class_iterate = child_class_iterate, }; static void fill_buffer(AVIOContext *s); @@ -255,6 +262,9 @@ if(!s) return AVERROR(EINVAL); + if ((whence & AVSEEK_SIZE)) + return s->seek ? s->seek(s->opaque, offset, AVSEEK_SIZE) : AVERROR(ENOSYS); + buffer_size = s->buf_end - s->buffer; // pos is the absolute position that the beginning of s->buffer corresponds to in the file pos = s->pos - (s->write_flag ? 0 : buffer_size); @@ -273,13 +283,9 @@ if (offset < 0) return AVERROR(EINVAL); - if (s->short_seek_get) { - short_seek = s->short_seek_get(s->opaque); - /* fallback to default short seek */ - if (short_seek <= 0) - short_seek = s->short_seek_threshold; - } else - short_seek = s->short_seek_threshold; + short_seek = s->short_seek_threshold; + if (s->short_seek_get) + short_seek = FFMAX(s->short_seek_get(s->opaque), short_seek); offset1 = offset - pos; // "offset1" is the relative offset from the beginning of s->buffer s->buf_ptr_max = FFMAX(s->buf_ptr_max, s->buf_ptr); @@ -434,26 +440,6 @@ #undef PUT_STR16 -int ff_get_v_length(uint64_t val) -{ - int i = 1; - - while (val >>= 7) - i++; - - return i; -} - -void ff_put_v(AVIOContext *bc, uint64_t val) -{ - int i = ff_get_v_length(val); - - while (--i > 0) - avio_w8(bc, 128 | (uint8_t)(val >> (7*i))); - - avio_w8(bc, val & 127); -} - void avio_wl64(AVIOContext *s, uint64_t val) { avio_wl32(s, (uint32_t)(val & 0xffffffff)); @@ -550,7 +536,7 @@ { int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE; - uint8_t *dst = s->buf_end - s->buffer + max_buffer_size < s->buffer_size ? + uint8_t *dst = s->buf_end - s->buffer + max_buffer_size <= s->buffer_size ? s->buf_end : s->buffer; int len = s->buffer_size - (dst - s->buffer); @@ -696,9 +682,11 @@ int ffio_read_size(AVIOContext *s, unsigned char *buf, int size) { int ret = avio_read(s, buf, size); - if (ret != size) - return AVERROR_INVALIDDATA; - return ret; + if (ret == size) + return ret; + if (ret < 0 && ret != AVERROR_EOF) + return ret; + return AVERROR_INVALIDDATA; } int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data) @@ -718,7 +706,7 @@ int len; if (size < 0) - return -1; + return AVERROR(EINVAL); if (s->read_packet && s->write_flag) { len = read_packet_wrapper(s, buf, size); @@ -729,13 +717,6 @@ len = s->buf_end - s->buf_ptr; if (len == 0) { - /* Reset the buf_end pointer to the start of the buffer, to make sure - * the fill_buffer call tries to read as much data as fits into the - * full buffer, instead of just what space is left after buf_end. - * This avoids returning partial packets at the end of the buffer, - * for packet based inputs. - */ - s->buf_end = s->buf_ptr = s->buffer; fill_buffer(s); len = s->buf_end - s->buf_ptr; } @@ -937,49 +918,8 @@ return val; } -static int io_read_packet(void *opaque, uint8_t *buf, int buf_size) -{ - AVIOInternal *internal = opaque; - return ffurl_read(internal->h, buf, buf_size); -} - -static int io_write_packet(void *opaque, uint8_t *buf, int buf_size) -{ - AVIOInternal *internal = opaque; - return ffurl_write(internal->h, buf, buf_size); -} - -static int64_t io_seek(void *opaque, int64_t offset, int whence) -{ - AVIOInternal *internal = opaque; - return ffurl_seek(internal->h, offset, whence); -} - -static int io_short_seek(void *opaque) -{ - AVIOInternal *internal = opaque; - return ffurl_get_short_seek(internal->h); -} - -static int io_read_pause(void *opaque, int pause) -{ - AVIOInternal *internal = opaque; - if (!internal->h->prot->url_read_pause) - return AVERROR(ENOSYS); - return internal->h->prot->url_read_pause(internal->h, pause); -} - -static int64_t io_read_seek(void *opaque, int stream_index, int64_t timestamp, int flags) -{ - AVIOInternal *internal = opaque; - if (!internal->h->prot->url_read_seek) - return AVERROR(ENOSYS); - return internal->h->prot->url_read_seek(internal->h, stream_index, timestamp, flags); -} - int ffio_fdopen(AVIOContext **s, URLContext *h) { - AVIOInternal *internal = NULL; uint8_t *buffer = NULL; int buffer_size, max_packet_size; @@ -989,18 +929,19 @@ } else { buffer_size = IO_BUFFER_SIZE; } + if (!(h->flags & AVIO_FLAG_WRITE) && h->is_streamed) { + if (buffer_size > INT_MAX/2) + return AVERROR(EINVAL); + buffer_size *= 2; + } buffer = av_malloc(buffer_size); if (!buffer) return AVERROR(ENOMEM); - internal = av_mallocz(sizeof(*internal)); - if (!internal) - goto fail; - - internal->h = h; - - *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, - internal, io_read_packet, io_write_packet, io_seek); + *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, 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; @@ -1020,76 +961,119 @@ (*s)->max_packet_size = max_packet_size; (*s)->min_packet_size = h->min_packet_size; if(h->prot) { - (*s)->read_pause = io_read_pause; - (*s)->read_seek = io_read_seek; + (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause; + (*s)->read_seek = + (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek; if (h->prot->url_read_seek) (*s)->seekable |= AVIO_SEEKABLE_TIME; } - (*s)->short_seek_get = io_short_seek; + (*s)->short_seek_get = (int (*)(void *))ffurl_get_short_seek; (*s)->av_class = &ff_avio_class; return 0; fail: - av_freep(&internal); av_freep(&buffer); return AVERROR(ENOMEM); } URLContext* ffio_geturlcontext(AVIOContext *s) { - AVIOInternal *internal; if (!s) return NULL; - internal = s->opaque; - if (internal && s->read_packet == io_read_packet) - return internal->h; + if (s->opaque && s->read_packet == (int (*)(void *, uint8_t *, int))ffurl_read) + return s->opaque; else return NULL; } +static void update_checksum(AVIOContext *s) +{ + if (s->update_checksum && s->buf_ptr > s->checksum_ptr) { + s->checksum = s->update_checksum(s->checksum, s->checksum_ptr, + s->buf_ptr - s->checksum_ptr); + } +} + int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size) { uint8_t *buffer; int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE; - int filled = s->buf_end - s->buffer; - ptrdiff_t checksum_ptr_offset = s->checksum_ptr ? s->checksum_ptr - s->buffer : -1; + ptrdiff_t filled = s->buf_end - s->buf_ptr; - buf_size += s->buf_ptr - s->buffer + max_buffer_size; + if (buf_size <= s->buf_end - s->buf_ptr) + return 0; + + buf_size += max_buffer_size - 1; - if (buf_size < filled || s->seekable || !s->read_packet) + if (buf_size + s->buf_ptr - s->buffer <= s->buffer_size || s->seekable || !s->read_packet) return 0; av_assert0(!s->write_flag); + if (buf_size <= s->buffer_size) { + update_checksum(s); + memmove(s->buffer, s->buf_ptr, filled); + } else { + buffer = av_malloc(buf_size); + if (!buffer) + return AVERROR(ENOMEM); + update_checksum(s); + memcpy(buffer, s->buf_ptr, filled); + av_free(s->buffer); + s->buffer = buffer; + s->buffer_size = buf_size; + } + s->buf_ptr = s->buffer; + s->buf_end = s->buffer + filled; + s->checksum_ptr = s->buffer; + return 0; +} + +int ffio_set_buf_size(AVIOContext *s, int buf_size) +{ + uint8_t *buffer; buffer = av_malloc(buf_size); if (!buffer) return AVERROR(ENOMEM); - memcpy(buffer, s->buffer, filled); av_free(s->buffer); - s->buf_ptr = buffer + (s->buf_ptr - s->buffer); - s->buf_end = buffer + (s->buf_end - s->buffer); s->buffer = buffer; + s->orig_buffer_size = s->buffer_size = buf_size; - if (checksum_ptr_offset >= 0) - s->checksum_ptr = s->buffer + checksum_ptr_offset; + s->buf_ptr = s->buf_ptr_max = buffer; + url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ); return 0; } -int ffio_set_buf_size(AVIOContext *s, int buf_size) +int ffio_realloc_buf(AVIOContext *s, int buf_size) { uint8_t *buffer; + int data_size; + + if (!s->buffer_size) + return ffio_set_buf_size(s, buf_size); + + if (buf_size <= s->buffer_size) + return 0; + buffer = av_malloc(buf_size); if (!buffer) return AVERROR(ENOMEM); + data_size = s->write_flag ? (s->buf_ptr - s->buffer) : (s->buf_end - s->buf_ptr); + if (data_size > 0) + memcpy(buffer, s->write_flag ? s->buffer : s->buf_ptr, data_size); av_free(s->buffer); s->buffer = buffer; - s->orig_buffer_size = + s->orig_buffer_size = buf_size; s->buffer_size = buf_size; - s->buf_ptr = s->buf_ptr_max = buffer; - url_resetbuf(s, s->write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ); + s->buf_ptr = s->write_flag ? (s->buffer + data_size) : s->buffer; + if (s->write_flag) + s->buf_ptr_max = s->buffer + data_size; + + s->buf_end = s->write_flag ? (s->buffer + s->buffer_size) : (s->buf_ptr + data_size); + return 0; } @@ -1163,6 +1147,8 @@ URLContext *h; int err; + *s = NULL; + err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist, blacklist, NULL); if (err < 0) return err; @@ -1182,17 +1168,15 @@ int avio_close(AVIOContext *s) { - AVIOInternal *internal; URLContext *h; if (!s) return 0; avio_flush(s); - internal = s->opaque; - h = internal->h; + h = s->opaque; + s->opaque = NULL; - av_freep(&s->opaque); av_freep(&s->buffer); if (s->write_flag) av_log(s, AV_LOG_VERBOSE, "Statistics: %d seeks, %d writeouts\n", s->seek_count, s->writeout_count); @@ -1215,14 +1199,26 @@ int avio_printf(AVIOContext *s, const char *fmt, ...) { va_list ap; - char buf[4096]; /* update doc entry in avio.h if changed */ - int ret; + AVBPrint bp; + av_bprint_init(&bp, 0, INT_MAX); va_start(ap, fmt); - ret = vsnprintf(buf, sizeof(buf), fmt, ap); + av_vbprintf(&bp, fmt, ap); va_end(ap); - avio_write(s, buf, strlen(buf)); - return ret; + if (!av_bprint_is_complete(&bp)) { + av_bprint_finalize(&bp, NULL); + s->error = AVERROR(ENOMEM); + return AVERROR(ENOMEM); + } + avio_write(s, bp.str, bp.len); + av_bprint_finalize(&bp, NULL); + return bp.len; +} + +void avio_print_string_array(AVIOContext *s, const char *strings[]) +{ + for(; *strings; strings++) + avio_write(s, (const unsigned char *)*strings, strlen(*strings)); } int avio_pause(AVIOContext *s, int pause) @@ -1272,8 +1268,7 @@ int avio_accept(AVIOContext *s, AVIOContext **c) { int ret; - AVIOInternal *internal = s->opaque; - URLContext *sc = internal->h; + URLContext *sc = s->opaque; URLContext *cc = NULL; ret = ffurl_accept(sc, &cc); if (ret < 0) @@ -1283,8 +1278,7 @@ int avio_handshake(AVIOContext *c) { - AVIOInternal *internal = c->opaque; - URLContext *cc = internal->h; + URLContext *cc = c->opaque; return ffurl_handshake(cc); } @@ -1300,22 +1294,21 @@ static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size) { DynBuffer *d = opaque; - unsigned new_size, new_allocated_size; + unsigned new_size; /* reallocate buffer if needed */ - new_size = d->pos + buf_size; - new_allocated_size = d->allocated_size; - if (new_size < d->pos || new_size > INT_MAX/2) - return -1; - while (new_size > new_allocated_size) { - if (!new_allocated_size) - new_allocated_size = new_size; - else + new_size = (unsigned)d->pos + buf_size; + if (new_size < d->pos || new_size > INT_MAX) + return AVERROR(ERANGE); + if (new_size > d->allocated_size) { + unsigned new_allocated_size = d->allocated_size ? d->allocated_size + : new_size; + int err; + while (new_size > new_allocated_size) new_allocated_size += new_allocated_size / 2 + 1; - } - if (new_allocated_size > d->allocated_size) { - int err; + new_allocated_size = FFMIN(new_allocated_size, INT_MAX); + if ((err = av_reallocp(&d->buffer, new_allocated_size)) < 0) { d->allocated_size = 0; d->size = 0; @@ -1353,8 +1346,10 @@ offset += d->pos; else if (whence == SEEK_END) offset += d->size; - if (offset < 0 || offset > 0x7fffffffLL) - return -1; + if (offset < 0) + return AVERROR(EINVAL); + if (offset > INT_MAX) + return AVERROR(ERANGE); d->pos = offset; return 0; } @@ -1365,7 +1360,7 @@ unsigned io_buffer_size = max_packet_size ? max_packet_size : 1024; if (sizeof(DynBuffer) + io_buffer_size < io_buffer_size) - return -1; + return AVERROR(ERANGE); d = av_mallocz(sizeof(DynBuffer) + io_buffer_size); if (!d) return AVERROR(ENOMEM); @@ -1389,7 +1384,7 @@ int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size) { if (max_packet_size <= 0) - return -1; + return AVERROR(EINVAL); return url_open_dyn_buf_internal(s, max_packet_size); } @@ -1401,15 +1396,31 @@ *pbuffer = NULL; return 0; } + d = s->opaque; + + if (!s->error && !d->size) { + *pbuffer = d->io_buffer; + return FFMAX(s->buf_ptr, s->buf_ptr_max) - s->buffer; + } avio_flush(s); - d = s->opaque; *pbuffer = d->buffer; return d->size; } +void ffio_reset_dyn_buf(AVIOContext *s) +{ + DynBuffer *d = s->opaque; + int max_packet_size = s->max_packet_size; + + ffio_init_context(s, d->io_buffer, d->io_buffer_size, 1, d, NULL, + s->write_packet, s->seek); + s->max_packet_size = max_packet_size; + d->pos = d->size = 0; +} + int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer) { DynBuffer *d; @@ -1442,12 +1453,15 @@ void ffio_free_dyn_buf(AVIOContext **s) { - uint8_t *tmp; + DynBuffer *d; + if (!*s) return; - avio_close_dyn_buf(*s, &tmp); - av_free(tmp); - *s = NULL; + + d = (*s)->opaque; + av_free(d->buffer); + av_free(d); + avio_context_free(s); } static int null_buf_write(void *opaque, uint8_t *buf, int buf_size) diff -Nru ffmpeg-4.2.2/libavformat/avio.c ffmpeg-4.4/libavformat/avio.c --- ffmpeg-4.2.2/libavformat/avio.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/avio.c 2021-04-08 21:28:40.000000000 +0000 @@ -26,6 +26,7 @@ #include "libavutil/avassert.h" #include "os_support.h" #include "avformat.h" +#include "internal.h" #if CONFIG_NETWORK #include "network.h" #endif @@ -54,8 +55,8 @@ #define E AV_OPT_FLAG_ENCODING_PARAM #define D AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { - {"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D }, - {"protocol_blacklist", "List of protocols that are not allowed to be used", OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D }, + {"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, + {"protocol_blacklist", "List of protocols that are not allowed to be used", OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, {"rw_timeout", "Timeout for IO operations (in microseconds)", offsetof(URLContext, rw_timeout), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_DECODING_PARAM }, { NULL } }; @@ -66,7 +67,10 @@ .option = options, .version = LIBAVUTIL_VERSION_INT, .child_next = urlcontext_child_next, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = ff_urlcontext_child_class_next, +#endif + .child_class_iterate = ff_urlcontext_child_class_iterate, }; /*@}*/ @@ -110,11 +114,10 @@ goto fail; } if (up->priv_data_class) { - int proto_len= strlen(up->name); - char *start = strchr(uc->filename, ','); + char *start; *(const AVClass **)uc->priv_data = up->priv_data_class; av_opt_set_defaults(uc->priv_data); - if(!strncmp(up->name, uc->filename, proto_len) && uc->filename + proto_len == start){ + if (av_strstart(uc->filename, up->name, (const char**)&start) && *start == ',') { int ret= 0; char *p= start; char sep= *++p; @@ -283,6 +286,9 @@ } } av_freep(&protocols); + if (av_strstart(filename, "https:", NULL) || av_strstart(filename, "tls:", NULL)) + av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile FFmpeg with " + "openssl, gnutls or securetransport enabled.\n"); return NULL; } @@ -297,10 +303,6 @@ return url_alloc_for_protocol(puc, p, filename, flags, int_cb); *puc = NULL; - if (av_strstart(filename, "https:", NULL) || av_strstart(filename, "tls:", NULL)) - av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile FFmpeg with " - "openssl, gnutls " - "or securetransport enabled.\n"); return AVERROR_PROTOCOL_NOT_FOUND; } @@ -347,18 +349,10 @@ if (!ret) return 0; fail: - ffurl_close(*puc); - *puc = NULL; + ffurl_closep(puc); return ret; } -int ffurl_open(URLContext **puc, const char *filename, int flags, - const AVIOInterruptCB *int_cb, AVDictionary **options) -{ - return ffurl_open_whitelist(puc, filename, flags, - int_cb, options, NULL, NULL, NULL); -} - static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf, int size, int size_min, int (*transfer_func)(URLContext *h, @@ -667,3 +661,11 @@ return cb->callback(cb->opaque); return 0; } + +int ff_rename(const char *url_src, const char *url_dst, void *logctx) +{ + int ret = avpriv_io_move(url_src, url_dst); + if (ret < 0) + av_log(logctx, AV_LOG_ERROR, "failed to rename file %s to %s: %s\n", url_src, url_dst, av_err2str(ret)); + return ret; +} diff -Nru ffmpeg-4.2.2/libavformat/avio.h ffmpeg-4.4/libavformat/avio.h --- ffmpeg-4.2.2/libavformat/avio.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/avio.h 2020-07-11 10:39:30.000000000 +0000 @@ -571,10 +571,30 @@ */ int avio_feof(AVIOContext *s); -/** @warning Writes up to 4 KiB per call */ +/** + * Writes a formatted string to the context. + * @return number of bytes written, < 0 on error. + */ int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3); /** + * Write a NULL terminated array of strings to the context. + * Usually you don't need to use this function directly but its macro wrapper, + * avio_print. + */ +void avio_print_string_array(AVIOContext *s, const char *strings[]); + +/** + * Write strings (const char *) to the context. + * This is a convenience macro around avio_print_string_array and it + * automatically creates the string array from the variable argument list. + * For simple string concatenations this function is more performant than using + * avio_printf since it does not need a temporary buffer. + */ +#define avio_print(s, ...) \ + avio_print_string_array(s, (const char*[]){__VA_ARGS__, NULL}) + +/** * Force flushing of buffered data. * * For write streams, force the buffered data to be immediately written to the output, @@ -788,6 +808,13 @@ const char *avio_enum_protocols(void **opaque, int output); /** + * Get AVClass by names of available protocols. + * + * @return A AVClass of input protocol name or NULL + */ +const AVClass *avio_protocol_get_class(const char *name); + +/** * Pause and resume playing - only meaningful if using a network streaming * protocol (e.g. MMS). * diff -Nru ffmpeg-4.2.2/libavformat/avio_internal.h ffmpeg-4.4/libavformat/avio_internal.h --- ffmpeg-4.2.2/libavformat/avio_internal.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/avio_internal.h 2021-04-08 21:28:40.000000000 +0000 @@ -87,11 +87,22 @@ int ffio_set_buf_size(AVIOContext *s, int buf_size); /** + * Reallocate a given buffer for AVIOContext. + * + * @param s the AVIOContext to realloc. + * @param buf_size required new buffer size. + * @return 0 on success, a negative AVERROR on failure. + */ +int ffio_realloc_buf(AVIOContext *s, int buf_size); + +/** * Ensures that the requested seekback buffer size will be available * * Will ensure that when reading sequentially up to buf_size, seeking * within the current pos and pos+buf_size is possible. - * Once the stream position moves outside this window this guarantee is lost. + * Once the stream position moves outside this window or another + * ffio_ensure_seekback call requests a buffer outside this window this + * guarantee is lost. */ int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size); @@ -163,6 +174,13 @@ int ffio_close_null_buf(AVIOContext *s); /** + * Reset a dynamic buffer. + * + * Resets everything, but keeps the allocated buffer for later use. + */ +void ffio_reset_dyn_buf(AVIOContext *s); + +/** * Free a dynamic buffer. * * @param s a pointer to an IO context opened by avio_open_dyn_buf() diff -Nru ffmpeg-4.2.2/libavformat/avisynth.c ffmpeg-4.4/libavformat/avisynth.c --- ffmpeg-4.2.2/libavformat/avisynth.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/avisynth.c 2021-04-08 21:28:40.000000000 +0000 @@ -1,5 +1,5 @@ /* - * AviSynth/AvxSynth support + * AviSynth(+) support * Copyright (c) 2012 AvxSynth Team * * This file is part of FFmpeg @@ -31,20 +31,26 @@ /* Enable function pointer definitions for runtime loading. */ #define AVSC_NO_DECLSPEC -/* Platform-specific directives for AviSynth vs AvxSynth. */ +/* Platform-specific directives. */ #ifdef _WIN32 #include "compat/w32dlfcn.h" #undef EXTERN_C - #include "compat/avisynth/avisynth_c.h" #define AVISYNTH_LIB "avisynth" - #define USING_AVISYNTH #else #include - #include "compat/avisynth/avxsynth_c.h" - #define AVISYNTH_NAME "libavxsynth" + #define AVISYNTH_NAME "libavisynth" #define AVISYNTH_LIB AVISYNTH_NAME SLIBSUF #endif +/* Endianness guards for audio */ +#if HAVE_BIGENDIAN + #define PCM(format) (AV_CODEC_ID_PCM_ ## format ## BE) +#else + #define PCM(format) (AV_CODEC_ID_PCM_ ## format ## LE) +#endif + +#include + typedef struct AviSynthLibrary { void *library; #define AVSC_DECLARE_FUNC(name) name ## _func name @@ -58,11 +64,11 @@ AVSC_DECLARE_FUNC(avs_get_version); AVSC_DECLARE_FUNC(avs_get_video_info); AVSC_DECLARE_FUNC(avs_invoke); + AVSC_DECLARE_FUNC(avs_is_color_space); AVSC_DECLARE_FUNC(avs_release_clip); AVSC_DECLARE_FUNC(avs_release_value); AVSC_DECLARE_FUNC(avs_release_video_frame); AVSC_DECLARE_FUNC(avs_take_clip); -#ifdef USING_AVISYNTH AVSC_DECLARE_FUNC(avs_bits_per_pixel); AVSC_DECLARE_FUNC(avs_get_height_p); AVSC_DECLARE_FUNC(avs_get_pitch_p); @@ -70,7 +76,6 @@ AVSC_DECLARE_FUNC(avs_get_row_size_p); AVSC_DECLARE_FUNC(avs_is_planar_rgb); AVSC_DECLARE_FUNC(avs_is_planar_rgba); -#endif #undef AVSC_DECLARE_FUNC } AviSynthLibrary; @@ -97,14 +102,12 @@ static const int avs_planes_grey[1] = { AVS_PLANAR_Y }; static const int avs_planes_yuv[3] = { AVS_PLANAR_Y, AVS_PLANAR_U, AVS_PLANAR_V }; -#ifdef USING_AVISYNTH static const int avs_planes_rgb[3] = { AVS_PLANAR_G, AVS_PLANAR_B, AVS_PLANAR_R }; static const int avs_planes_yuva[4] = { AVS_PLANAR_Y, AVS_PLANAR_U, AVS_PLANAR_V, AVS_PLANAR_A }; static const int avs_planes_rgba[4] = { AVS_PLANAR_G, AVS_PLANAR_B, AVS_PLANAR_R, AVS_PLANAR_A }; -#endif /* A conflict between C++ global objects, atexit, and dynamic loading requires * us to register our own atexit handler to prevent double freeing. */ @@ -138,11 +141,11 @@ LOAD_AVS_FUNC(avs_get_version, 0); LOAD_AVS_FUNC(avs_get_video_info, 0); LOAD_AVS_FUNC(avs_invoke, 0); + LOAD_AVS_FUNC(avs_is_color_space, 1); LOAD_AVS_FUNC(avs_release_clip, 0); LOAD_AVS_FUNC(avs_release_value, 0); LOAD_AVS_FUNC(avs_release_video_frame, 0); LOAD_AVS_FUNC(avs_take_clip, 0); -#ifdef USING_AVISYNTH LOAD_AVS_FUNC(avs_bits_per_pixel, 1); LOAD_AVS_FUNC(avs_get_height_p, 1); LOAD_AVS_FUNC(avs_get_pitch_p, 1); @@ -150,7 +153,6 @@ LOAD_AVS_FUNC(avs_get_row_size_p, 1); LOAD_AVS_FUNC(avs_is_planar_rgb, 1); LOAD_AVS_FUNC(avs_is_planar_rgba, 1); -#endif #undef LOAD_AVS_FUNC atexit(avisynth_atexit_handler); @@ -248,8 +250,24 @@ st->nb_frames = avs->vi->num_frames; avpriv_set_pts_info(st, 32, avs->vi->fps_denominator, avs->vi->fps_numerator); + av_log(s, AV_LOG_TRACE, "avs_is_field_based: %d\n", avs_is_field_based(avs->vi)); + av_log(s, AV_LOG_TRACE, "avs_is_parity_known: %d\n", avs_is_parity_known(avs->vi)); + + /* The following typically only works when assumetff (-bff) and + * assumefieldbased is used in-script. Additional + * logic using GetParity() could deliver more accurate results + * but also decodes a frame which we want to avoid. */ + st->codecpar->field_order = AV_FIELD_UNKNOWN; + if (avs_is_field_based(avs->vi)) { + if (avs_is_tff(avs->vi)) { + st->codecpar->field_order = AV_FIELD_TT; + } + else if (avs_is_bff(avs->vi)) { + st->codecpar->field_order = AV_FIELD_BB; + } + } + switch (avs->vi->pixel_type) { -#ifdef USING_AVISYNTH /* 10~16-bit YUV pix_fmts (AviSynth+) */ case AVS_CS_YUV444P10: st->codecpar->format = AV_PIX_FMT_YUV444P10; @@ -434,8 +452,7 @@ case AVS_CS_BGR64: st->codecpar->format = AV_PIX_FMT_BGRA64; break; -#endif - /* AviSynth 2.5 and AvxSynth pix_fmts */ + /* AviSynth 2.5 pix_fmts */ case AVS_CS_BGR24: st->codecpar->format = AV_PIX_FMT_BGR24; break; @@ -461,7 +478,6 @@ } switch (planar) { -#ifdef USING_AVISYNTH case 5: // Planar RGB + Alpha avs->n_planes = 4; avs->planes = avs_planes_rgba; @@ -474,7 +490,6 @@ avs->n_planes = 3; avs->planes = avs_planes_rgb; break; -#endif case 2: // Y8 avs->n_planes = 1; avs->planes = avs_planes_grey; @@ -505,16 +520,16 @@ st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; break; case AVS_SAMPLE_INT16: - st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; + st->codecpar->codec_id = PCM(S16); break; case AVS_SAMPLE_INT24: - st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE; + st->codecpar->codec_id = PCM(S24); break; case AVS_SAMPLE_INT32: - st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE; + st->codecpar->codec_id = PCM(S32); break; case AVS_SAMPLE_FLOAT: - st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE; + st->codecpar->codec_id = PCM(F32); break; default: av_log(s, AV_LOG_ERROR, @@ -556,7 +571,7 @@ AviSynthContext *avs = s->priv_data; AVS_Value arg, val; int ret; -#ifdef USING_AVISYNTH +#ifdef _WIN32 char filename_ansi[MAX_PATH * 4]; wchar_t filename_wc[MAX_PATH * 4]; #endif @@ -564,14 +579,14 @@ if (ret = avisynth_context_create(s)) return ret; -#ifdef USING_AVISYNTH +#ifdef _WIN32 /* Convert UTF-8 to ANSI code page */ - MultiByteToWideChar(CP_UTF8, 0, s->filename, -1, filename_wc, MAX_PATH * 4); + MultiByteToWideChar(CP_UTF8, 0, s->url, -1, filename_wc, MAX_PATH * 4); WideCharToMultiByte(CP_THREAD_ACP, 0, filename_wc, -1, filename_ansi, MAX_PATH * 4, NULL, NULL); arg = avs_new_value_string(filename_ansi); #else - arg = avs_new_value_string(s->filename); + arg = avs_new_value_string(s->url); #endif val = avs_library.avs_invoke(avs->env, "Import", arg, 0); if (avs_is_error(val)) { @@ -588,11 +603,9 @@ avs->clip = avs_library.avs_take_clip(val, avs->env); avs->vi = avs_library.avs_get_video_info(avs->clip); -#ifdef USING_AVISYNTH /* On Windows, FFmpeg supports AviSynth interface version 6 or higher. * This includes AviSynth 2.6 RC1 or higher, and AviSynth+ r1718 or higher, - * and excludes 2.5 and the 2.6 alphas. Since AvxSynth identifies itself - * as interface version 3 like 2.5.8, this needs to be special-cased. */ + * and excludes 2.5 and the 2.6 alphas. */ if (avs_library.avs_get_version(avs->clip) < 6) { av_log(s, AV_LOG_ERROR, @@ -600,7 +613,6 @@ ret = AVERROR_UNKNOWN; goto fail; } -#endif /* Release the AVS_Value as it will go out of scope. */ avs_library.avs_release_value(val); @@ -640,9 +652,8 @@ AVS_VideoFrame *frame; unsigned char *dst_p; const unsigned char *src_p; - int n, i, plane, rowsize, planeheight, pitch, bits; + int n, i, plane, rowsize, planeheight, pitch, bits, ret; const char *error; - int avsplus av_unused; if (avs->curr_frame >= avs->vi->num_frames) return AVERROR_EOF; @@ -652,22 +663,7 @@ if (discard) return 0; -#ifdef USING_AVISYNTH - /* Detect whether we're using AviSynth 2.6 or AviSynth+ by - * looking for whether avs_is_planar_rgb exists. */ - if (GetProcAddress(avs_library.library, "avs_is_planar_rgb") == NULL) - avsplus = 0; - else - avsplus = 1; - - /* avs_bits_per_pixel changed to AVSC_API with AviSynth 2.6, which - * requires going through avs_library, while AvxSynth has it under - * the older AVSC_INLINE type, so special-case this. */ - bits = avs_library.avs_bits_per_pixel(avs->vi); -#else - bits = avs_bits_per_pixel(avs->vi); -#endif /* Without the cast to int64_t, calculation overflows at about 9k x 9k * resolution. */ @@ -676,8 +672,8 @@ if (!pkt->size) return AVERROR_UNKNOWN; - if (av_new_packet(pkt, pkt->size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, pkt->size)) < 0) + return ret; pkt->pts = n; pkt->dts = n; @@ -696,34 +692,19 @@ dst_p = pkt->data; for (i = 0; i < avs->n_planes; i++) { plane = avs->planes[i]; -#ifdef USING_AVISYNTH src_p = avs_library.avs_get_read_ptr_p(frame, plane); pitch = avs_library.avs_get_pitch_p(frame, plane); rowsize = avs_library.avs_get_row_size_p(frame, plane); planeheight = avs_library.avs_get_height_p(frame, plane); -#else - src_p = avs_get_read_ptr_p(frame, plane); - pitch = avs_get_pitch_p(frame, plane); - - rowsize = avs_get_row_size_p(frame, plane); - planeheight = avs_get_height_p(frame, plane); -#endif /* Flip RGB video. */ - if (avs_is_rgb24(avs->vi) || avs_is_rgb(avs->vi)) { - src_p = src_p + (planeheight - 1) * pitch; - pitch = -pitch; - } - -#ifdef USING_AVISYNTH - /* Flip Planar RGB video */ - if (avsplus && (avs_library.avs_is_planar_rgb(avs->vi) || - avs_library.avs_is_planar_rgba(avs->vi))) { + if (avs_library.avs_is_color_space(avs->vi, AVS_CS_BGR) || + avs_library.avs_is_color_space(avs->vi, AVS_CS_BGR48) || + avs_library.avs_is_color_space(avs->vi, AVS_CS_BGR64)) { src_p = src_p + (planeheight - 1) * pitch; pitch = -pitch; } -#endif avs_library.avs_bit_blt(avs->env, dst_p, rowsize, src_p, pitch, rowsize, planeheight); @@ -739,7 +720,7 @@ { AviSynthContext *avs = s->priv_data; AVRational fps, samplerate; - int samples; + int samples, ret; int64_t n; const char *error; @@ -782,8 +763,8 @@ if (!pkt->size) return AVERROR_UNKNOWN; - if (av_new_packet(pkt, pkt->size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, pkt->size)) < 0) + return ret; pkt->pts = n; pkt->dts = n; diff -Nru ffmpeg-4.2.2/libavformat/avlanguage.c ffmpeg-4.4/libavformat/avlanguage.c --- ffmpeg-4.2.2/libavformat/avlanguage.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/avlanguage.c 2021-04-08 21:28:40.000000000 +0000 @@ -763,10 +763,3 @@ return NULL; } - -#if LIBAVFORMAT_VERSION_MAJOR < 58 -const char *av_convert_lang_to(const char *lang, enum AVLangCodespace target_codespace) -{ - return ff_convert_lang_to(lang, target_codespace); -} -#endif diff -Nru ffmpeg-4.2.2/libavformat/avlanguage.h ffmpeg-4.4/libavformat/avlanguage.h --- ffmpeg-4.2.2/libavformat/avlanguage.h 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/avlanguage.h 2021-04-08 21:28:40.000000000 +0000 @@ -21,9 +21,6 @@ #ifndef AVFORMAT_AVLANGUAGE_H #define AVFORMAT_AVLANGUAGE_H -#include "libavutil/attributes.h" -#include "libavformat/version.h" - /** * Known language codespaces */ @@ -38,9 +35,5 @@ * @return NULL if the provided lang is null or invalid. */ const char *ff_convert_lang_to(const char *lang, enum AVLangCodespace target_codespace); -#if LIBAVFORMAT_VERSION_MAJOR < 58 -attribute_deprecated -const char *av_convert_lang_to(const char *lang, enum AVLangCodespace target_codespace); -#endif #endif /* AVFORMAT_AVLANGUAGE_H */ diff -Nru ffmpeg-4.2.2/libavformat/avs2dec.c ffmpeg-4.4/libavformat/avs2dec.c --- ffmpeg-4.2.2/libavformat/avs2dec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/avs2dec.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * AVS2 video stream probe. + * + * Copyright (C) 2018 Huiwen Ren, + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "rawdec.h" +#include "libavcodec/internal.h" +#include "libavutil/intreadwrite.h" + +#define AVS2_ISSQH(x) ((x) == 0xB0) +#define AVS2_ISEND(x) ((x) == 0xB1) +#define AVS2_ISPIC(x) ((x) == 0xB3 || (x) == 0xB6) +#define AVS2_ISUNIT(x) (AVS2_ISSQH(x) || AVS2_ISEND(x) || (x) == 0xB2 || AVS2_ISPIC(x) || (x) == 0xB5 || (x) == 0xB7) +#define AVS2_ISPROFILE(x) ((x) == 0x20 || (x) == 0x22 || (x) == 0x30 || (x) == 0x32) + +static int avs2_probe(const AVProbeData *p) +{ + uint32_t code = -1, hds = 0, pic = 0, seq = 0; + uint8_t state = 0; + const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size, *sqb = 0; + if (AV_RB32(p->buf) != 0x1B0){ + return 0; + } + + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &code); + state = code & 0xFF; + if ((code & 0xffffff00) == 0x100) { + if (AVS2_ISUNIT(state)) { + if (sqb && !hds) { + hds = ptr - sqb; + } + if (AVS2_ISSQH(state)) { + if (!AVS2_ISPROFILE(*ptr)) + return 0; + sqb = ptr; + seq++; + } else if (AVS2_ISPIC(state)) { + pic++; + } else if (AVS2_ISEND(state)) { + break; + } + } + } + } + if (seq && hds >= 21 && pic){ + return AVPROBE_SCORE_EXTENSION + 2; // more than cavs + } + + return 0; +} + +FF_DEF_RAWVIDEO_DEMUXER(avs2, "raw AVS2-P2/IEEE1857.4", avs2_probe, "avs,avs2", AV_CODEC_ID_AVS2) diff -Nru ffmpeg-4.2.2/libavformat/avs3dec.c ffmpeg-4.4/libavformat/avs3dec.c --- ffmpeg-4.2.2/libavformat/avs3dec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/avs3dec.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,68 @@ +/* + * RAW AVS3-P2/IEEE1857.10 video demuxer + * Copyright (c) 2020 Zhenyu Wang + * Bingjie Han + * Huiwen Ren + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/avs3.h" +#include "libavcodec/internal.h" +#include "avformat.h" +#include "rawdec.h" + +static int avs3video_probe(const AVProbeData *p) +{ + const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size; + uint32_t code = -1; + uint8_t state = 0; + int pic = 0, seq = 0, slice_pos = 0; + int ret = 0; + + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &code); + state = code & 0xFF; + if ((code & 0xFFFFFF00) == 0x100) { + if (state < AVS3_SEQ_START_CODE) { + if (code < slice_pos) + return 0; + slice_pos = code; + } else { + slice_pos = 0; + } + if (state == AVS3_SEQ_START_CODE) { + seq++; + if (*ptr != AVS3_PROFILE_BASELINE_MAIN && *ptr != AVS3_PROFILE_BASELINE_MAIN10) + return 0; + } else if (AVS3_ISPIC(state)) { + pic++; + } else if ((state == AVS3_UNDEF_START_CODE) || + (state > AVS3_VIDEO_EDIT_CODE)) { + return 0; + } + } + } + + if (seq && pic && av_match_ext(p->filename, "avs3")) { + ret = AVPROBE_SCORE_MAX; + } + + return ret; +} + +FF_DEF_RAWVIDEO_DEMUXER(avs3, "raw AVS3-P2/IEEE1857.10", avs3video_probe, "avs3", AV_CODEC_ID_AVS3) diff -Nru ffmpeg-4.2.2/libavformat/avs.c ffmpeg-4.4/libavformat/avs.c --- ffmpeg-4.2.2/libavformat/avs.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/avs.c 2021-02-20 20:27:47.000000000 +0000 @@ -114,7 +114,6 @@ pkt->data[palette_size + 3] = (size >> 8) & 0xFF; ret = avio_read(s->pb, pkt->data + palette_size + 4, size - 4) + 4; if (ret < size) { - av_packet_unref(pkt); return AVERROR(EIO); } @@ -129,7 +128,8 @@ static int avs_read_audio_packet(AVFormatContext * s, AVPacket * pkt) { AvsFormat *avs = s->priv_data; - int ret, size; + int ret; + int64_t size; size = avio_tell(s->pb); ret = ff_voc_get_packet(s, pkt, avs->st_audio, avs->remaining_audio_size); @@ -224,11 +224,6 @@ } } -static int avs_read_close(AVFormatContext * s) -{ - return 0; -} - AVInputFormat ff_avs_demuxer = { .name = "avs", .long_name = NULL_IF_CONFIG_SMALL("Argonaut Games Creature Shock"), @@ -236,5 +231,4 @@ .read_probe = avs_probe, .read_header = avs_read_header, .read_packet = avs_read_packet, - .read_close = avs_read_close, }; diff -Nru ffmpeg-4.2.2/libavformat/bethsoftvid.c ffmpeg-4.4/libavformat/bethsoftvid.c --- ffmpeg-4.2.2/libavformat/bethsoftvid.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/bethsoftvid.c 2021-02-20 20:27:47.000000000 +0000 @@ -28,6 +28,7 @@ */ #include "libavutil/channel_layout.h" +#include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "avformat.h" #include "internal.h" @@ -49,7 +50,8 @@ int bethsoft_global_delay; int video_index; /**< video stream index */ int audio_index; /**< audio stream index */ - uint8_t *palette; + int has_palette; + uint8_t palette[BVID_PALETTE_SIZE]; int is_finished; @@ -71,6 +73,7 @@ { BVID_DemuxContext *vid = s->priv_data; AVIOContext *pb = s->pb; + int ret; /* load main header. Contents: * bytes: 'V' 'I' 'D' @@ -83,6 +86,10 @@ vid->bethsoft_global_delay = avio_rl16(pb); avio_rl16(pb); + ret = av_image_check_size(vid->width, vid->height, 0, s); + if (ret < 0) + return ret; + // wait until the first packet to create each stream vid->video_index = -1; vid->audio_index = -1; @@ -146,9 +153,13 @@ } do{ - vidbuf_start = av_fast_realloc(vidbuf_start, &vidbuf_capacity, vidbuf_nbytes + BUFFER_PADDING_SIZE); - if(!vidbuf_start) - return AVERROR(ENOMEM); + uint8_t *tmp = av_fast_realloc(vidbuf_start, &vidbuf_capacity, + vidbuf_nbytes + BUFFER_PADDING_SIZE); + if (!tmp) { + ret = AVERROR(ENOMEM); + goto fail; + } + vidbuf_start = tmp; code = avio_r8(pb); vidbuf_start[vidbuf_nbytes++] = code; @@ -188,7 +199,7 @@ pkt->flags |= AV_PKT_FLAG_KEY; /* if there is a new palette available, add it to packet side data */ - if (vid->palette) { + if (vid->has_palette) { uint8_t *pdata = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, BVID_PALETTE_SIZE); if (!pdata) { @@ -197,8 +208,7 @@ goto fail; } memcpy(pdata, vid->palette, BVID_PALETTE_SIZE); - - av_freep(&vid->palette); + vid->has_palette = 0; } vid->nframes--; // used to check if all the frames were read @@ -222,17 +232,14 @@ block_type = avio_r8(pb); switch(block_type){ case PALETTE_BLOCK: - if (vid->palette) { + if (vid->has_palette) { av_log(s, AV_LOG_WARNING, "discarding unused palette\n"); - av_freep(&vid->palette); + vid->has_palette = 0; } - vid->palette = av_malloc(BVID_PALETTE_SIZE); - if (!vid->palette) - return AVERROR(ENOMEM); if (avio_read(pb, vid->palette, BVID_PALETTE_SIZE) != BVID_PALETTE_SIZE) { - av_freep(&vid->palette); return AVERROR(EIO); } + vid->has_palette = 1; return vid_read_packet(s, pkt); case FIRST_AUDIO_BLOCK: @@ -284,13 +291,6 @@ } } -static int vid_read_close(AVFormatContext *s) -{ - BVID_DemuxContext *vid = s->priv_data; - av_freep(&vid->palette); - return 0; -} - AVInputFormat ff_bethsoftvid_demuxer = { .name = "bethsoftvid", .long_name = NULL_IF_CONFIG_SMALL("Bethesda Softworks VID"), @@ -298,5 +298,4 @@ .read_probe = vid_probe, .read_header = vid_read_header, .read_packet = vid_read_packet, - .read_close = vid_read_close, }; diff -Nru ffmpeg-4.2.2/libavformat/bfi.c ffmpeg-4.4/libavformat/bfi.c --- ffmpeg-4.2.2/libavformat/bfi.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/bfi.c 2021-02-20 20:27:47.000000000 +0000 @@ -69,6 +69,9 @@ /* Set the total number of frames. */ avio_skip(pb, 8); chunk_header = avio_rl32(pb); + if (chunk_header < 3) + return AVERROR_INVALIDDATA; + bfi->nframes = avio_rl32(pb); avio_rl32(pb); avio_rl32(pb); diff -Nru ffmpeg-4.2.2/libavformat/binka.c ffmpeg-4.4/libavformat/binka.c --- ffmpeg-4.2.2/libavformat/binka.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/binka.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,100 @@ +/* + * 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 "libavutil/intreadwrite.h" +#include "avformat.h" +#include "internal.h" + +static int binka_probe(const AVProbeData *p) +{ + if (AV_RB32(p->buf) == MKBETAG('1', 'F', 'C', 'B') && + (p->buf[4] == 1 || p->buf[4] == 2)) + return AVPROBE_SCORE_MAX; + return 0; +} + +static int binka_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + AVStream *st; + int entries, offset; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + avio_skip(pb, 5); + + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_BINKAUDIO_DCT; + st->codecpar->channels = avio_r8(pb); + st->codecpar->sample_rate = avio_rl16(pb); + st->duration = avio_rl32(pb); + + avio_skip(pb, 8); + entries = avio_rl16(pb); + + offset = entries * 2 + 2; + avio_skip(pb, offset); + + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); + + return 0; +} + +static int binka_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVIOContext *pb = s->pb; + AVStream *st = s->streams[0]; + int64_t pos; + int pkt_size; + int ret; + + if (avio_feof(pb)) + return AVERROR_EOF; + + pos = avio_tell(pb); + avio_skip(pb, 2); + pkt_size = avio_rl16(pb) + 4; + if (pkt_size <= 4) + return AVERROR(EIO); + ret = av_new_packet(pkt, pkt_size); + if (ret < 0) + return ret; + + avio_read(pb, pkt->data + 4, pkt_size - 4); + AV_WL32(pkt->data, pkt_size); + + pkt->pos = pos; + pkt->stream_index = 0; + pkt->duration = av_get_audio_frame_duration2(st->codecpar, 0); + + return 0; +} + +AVInputFormat ff_binka_demuxer = { + .name = "binka", + .long_name = NULL_IF_CONFIG_SMALL("Bink Audio"), + .read_probe = binka_probe, + .read_header = binka_read_header, + .read_packet = binka_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "binka", +}; diff -Nru ffmpeg-4.2.2/libavformat/bink.c ffmpeg-4.4/libavformat/bink.c --- ffmpeg-4.2.2/libavformat/bink.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/bink.c 2020-07-11 10:39:30.000000000 +0000 @@ -56,6 +56,7 @@ int64_t audio_pts[BINK_MAX_AUDIO_TRACKS]; uint32_t remain_packet_size; + int flags; int smush_size; } BinkDemuxContext; @@ -90,6 +91,7 @@ unsigned int i; uint32_t pos, next_pos; uint16_t flags; + int next_keyframe = 1; int keyframe; int ret; uint32_t signature; @@ -150,8 +152,8 @@ vst->codecpar->codec_id = AV_CODEC_ID_NONE; } - if (ff_get_extradata(s, vst->codecpar, pb, 4) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_get_extradata(s, vst->codecpar, pb, 4)) < 0) + return ret; bink->num_audio_tracks = avio_rl32(pb); @@ -190,8 +192,8 @@ ast->codecpar->channels = 1; ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; } - if (ff_alloc_extradata(ast->codecpar, 4)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(ast->codecpar, 4)) < 0) + return ret; AV_WL32(ast->codecpar->extradata, vst->codecpar->codec_tag); } @@ -203,12 +205,13 @@ next_pos = avio_rl32(pb); for (i = 0; i < vst->duration; i++) { pos = next_pos; + keyframe = next_keyframe; if (i == vst->duration - 1) { next_pos = bink->file_size; - keyframe = 0; + next_keyframe = 0; } else { next_pos = avio_rl32(pb); - keyframe = pos & 1; + next_keyframe = next_pos & 1; } pos &= ~1; next_pos &= ~1; @@ -254,6 +257,7 @@ } bink->remain_packet_size = st->index_entries[index_entry].size; + bink->flags = st->index_entries[index_entry].flags; bink->current_track = 0; } @@ -290,7 +294,8 @@ return ret; pkt->stream_index = 0; pkt->pts = bink->video_pts++; - pkt->flags |= AV_PKT_FLAG_KEY; + if (bink->flags & AVINDEX_KEYFRAME) + pkt->flags |= AV_PKT_FLAG_KEY; /* -1 instructs the next call to read_packet() to read the next frame */ bink->current_track = -1; @@ -302,13 +307,15 @@ { BinkDemuxContext *bink = s->priv_data; AVStream *vst = s->streams[0]; + int64_t ret; if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) return -1; /* seek to the first frame */ - if (avio_seek(s->pb, vst->index_entries[0].pos + bink->smush_size, SEEK_SET) < 0) - return -1; + ret = avio_seek(s->pb, vst->index_entries[0].pos + bink->smush_size, SEEK_SET); + if (ret < 0) + return ret; bink->video_pts = 0; memset(bink->audio_pts, 0, sizeof(bink->audio_pts)); diff -Nru ffmpeg-4.2.2/libavformat/bintext.c ffmpeg-4.4/libavformat/bintext.c --- ffmpeg-4.2.2/libavformat/bintext.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/bintext.c 2021-02-20 20:27:47.000000000 +0000 @@ -149,7 +149,7 @@ return AVPROBE_SCORE_EXTENSION + 1; predict_width(&par, p->buf_size, got_width); - if (par.width <= 0) + if (par.width < 8) return 0; calculate_height(&par, p->buf_size); if (par.height <= 0) @@ -177,14 +177,14 @@ { BinDemuxContext *bin = s->priv_data; AVIOContext *pb = s->pb; - + int ret; AVStream *st = init_stream(s); if (!st) return AVERROR(ENOMEM); st->codecpar->codec_id = AV_CODEC_ID_BINTEXT; - if (ff_alloc_extradata(st->codecpar, 2)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 2)) < 0) + return ret; st->codecpar->extradata[0] = 16; st->codecpar->extradata[1] = 0; @@ -195,6 +195,8 @@ next_tag_read(s, &bin->fsize); if (!bin->width) { predict_width(st->codecpar, bin->fsize, got_width); + if (st->codecpar->width < 8) + return AVERROR_INVALIDDATA; calculate_height(st->codecpar, bin->fsize); } avio_seek(pb, 0, SEEK_SET); @@ -220,7 +222,7 @@ BinDemuxContext *bin = s->priv_data; AVIOContext *pb = s->pb; char fontheight, flags; - + int ret; AVStream *st = init_stream(s); if (!st) return AVERROR(ENOMEM); @@ -239,8 +241,9 @@ st->codecpar->extradata_size += fontheight * (flags & 0x10 ? 512 : 256); st->codecpar->codec_id = flags & 4 ? AV_CODEC_ID_XBIN : AV_CODEC_ID_BINTEXT; - if (ff_alloc_extradata(st->codecpar, st->codecpar->extradata_size)) - return AVERROR(ENOMEM); + ret = ff_alloc_extradata(st->codecpar, st->codecpar->extradata_size); + if (ret < 0) + return ret; st->codecpar->extradata[0] = fontheight; st->codecpar->extradata[1] = flags; if (avio_read(pb, st->codecpar->extradata + 2, st->codecpar->extradata_size - 2) < 0) @@ -262,6 +265,7 @@ BinDemuxContext *bin = s->priv_data; AVIOContext *pb = s->pb; AVStream *st; + int ret; if (avio_r8(pb) != 1) return AVERROR_INVALIDDATA; @@ -271,8 +275,8 @@ return AVERROR(ENOMEM); st->codecpar->codec_id = AV_CODEC_ID_BINTEXT; - if (ff_alloc_extradata(st->codecpar, 2 + 48 + 4096)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 2 + 48 + 4096)) < 0) + return ret; st->codecpar->extradata[0] = 16; st->codecpar->extradata[1] = BINTEXT_PALETTE|BINTEXT_FONT; @@ -289,6 +293,8 @@ bin->fsize = avio_size(pb) - 1 - 192 - 4096; st->codecpar->width = 80<<3; ff_sauce_read(s, &bin->fsize, &got_width, 0); + if (st->codecpar->width < 8) + return AVERROR_INVALIDDATA; if (!bin->width) calculate_height(st->codecpar, bin->fsize); avio_seek(pb, 1 + 192 + 4096, SEEK_SET); @@ -316,7 +322,7 @@ BinDemuxContext *bin = s->priv_data; AVIOContext *pb = s->pb; AVStream *st; - int got_width = 0; + int got_width = 0, ret; if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) return AVERROR(EIO); @@ -326,8 +332,8 @@ return AVERROR(ENOMEM); st->codecpar->codec_id = AV_CODEC_ID_IDF; - if (ff_alloc_extradata(st->codecpar, 2 + 48 + 4096)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 2 + 48 + 4096)) < 0) + return ret; st->codecpar->extradata[0] = 16; st->codecpar->extradata[1] = BINTEXT_PALETTE|BINTEXT_FONT; @@ -340,6 +346,8 @@ bin->fsize = avio_size(pb) - 12 - 4096 - 48; ff_sauce_read(s, &bin->fsize, &got_width, 0); + if (st->codecpar->width < 8) + return AVERROR_INVALIDDATA; if (!bin->width) calculate_height(st->codecpar, bin->fsize); avio_seek(pb, 12, SEEK_SET); diff -Nru ffmpeg-4.2.2/libavformat/bit.c ffmpeg-4.4/libavformat/bit.c --- ffmpeg-4.2.2/libavformat/bit.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/bit.c 2020-07-11 10:39:30.000000000 +0000 @@ -94,8 +94,8 @@ if(ret != 8 * packet_size * sizeof(uint16_t)) return AVERROR(EIO); - if (av_new_packet(pkt, packet_size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, packet_size)) < 0) + return ret; init_put_bits(&pbo, pkt->data, packet_size); for(j=0; j < packet_size; j++) diff -Nru ffmpeg-4.2.2/libavformat/bmv.c ffmpeg-4.4/libavformat/bmv.c --- ffmpeg-4.2.2/libavformat/bmv.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/bmv.c 2020-07-11 10:39:30.000000000 +0000 @@ -96,8 +96,8 @@ audio_size, c->size); return AVERROR_INVALIDDATA; } - if (av_new_packet(pkt, audio_size) < 0) - return AVERROR(ENOMEM); + if ((err = av_new_packet(pkt, audio_size)) < 0) + return err; memcpy(pkt->data, c->packet + 1, pkt->size); pkt->stream_index = 1; pkt->pts = c->audio_pos; @@ -108,8 +108,8 @@ } else break; } - if (av_new_packet(pkt, c->size + 1) < 0) - return AVERROR(ENOMEM); + if ((err = av_new_packet(pkt, c->size + 1)) < 0) + return err; pkt->stream_index = 0; c->get_next = 1; memcpy(pkt->data, c->packet, pkt->size); diff -Nru ffmpeg-4.2.2/libavformat/boadec.c ffmpeg-4.4/libavformat/boadec.c --- ffmpeg-4.2.2/libavformat/boadec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/boadec.c 2021-02-20 20:27:47.000000000 +0000 @@ -54,12 +54,12 @@ avio_rl32(s->pb); st->codecpar->sample_rate = avio_rl32(s->pb); st->codecpar->channels = avio_rl32(s->pb); - if (st->codecpar->channels > FF_SANE_NB_CHANNELS) + if (st->codecpar->channels > FF_SANE_NB_CHANNELS || st->codecpar->channels <= 0) return AVERROR(ENOSYS); s->internal->data_offset = avio_rl32(s->pb); avio_r8(s->pb); st->codecpar->block_align = avio_rl32(s->pb); - if (st->codecpar->block_align > INT_MAX / FF_SANE_NB_CHANNELS) + if (st->codecpar->block_align > INT_MAX / FF_SANE_NB_CHANNELS || st->codecpar->block_align <= 0) return AVERROR_INVALIDDATA; st->codecpar->block_align *= st->codecpar->channels; diff -Nru ffmpeg-4.2.2/libavformat/brstm.c ffmpeg-4.4/libavformat/brstm.c --- ffmpeg-4.2.2/libavformat/brstm.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/brstm.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,11 @@ #include "avformat.h" #include "internal.h" +typedef struct BRSTMCoeffOffset { + uint8_t channel; + uint32_t offset; +} BRSTMCoeffOffset; + typedef struct BRSTMDemuxContext { uint32_t block_size; uint32_t block_count; @@ -33,8 +38,9 @@ uint32_t last_block_size; uint32_t last_block_samples; uint32_t data_start; - uint8_t *table; + uint8_t table[256 * 32]; uint8_t *adpc; + BRSTMCoeffOffset offsets[256]; int little_endian; } BRSTMDemuxContext; @@ -61,12 +67,18 @@ { BRSTMDemuxContext *b = s->priv_data; - av_freep(&b->table); av_freep(&b->adpc); return 0; } +static int sort_offsets(const void *a, const void *b) +{ + const BRSTMCoeffOffset *s1 = a; + const BRSTMCoeffOffset *s2 = b; + return FFDIFFSIGN(s1->offset, s2->offset); +} + static av_always_inline unsigned int read16(AVFormatContext *s) { BRSTMDemuxContext *b = s->priv_data; @@ -259,17 +271,30 @@ if (toffset > size) return AVERROR_INVALIDDATA; + if (!bfstm) { + avio_skip(s->pb, pos + toffset - avio_tell(s->pb) - 8LL * (st->codecpar->channels + 1)); + for (ch = 0; ch < st->codecpar->channels; ch++) { + avio_skip(s->pb, 4); + b->offsets[ch].channel = ch; + b->offsets[ch].offset = read32(s); + } + + qsort(b->offsets, st->codecpar->channels, sizeof(*b->offsets), sort_offsets); + } + avio_skip(s->pb, pos + toffset - avio_tell(s->pb)); - b->table = av_mallocz(32 * st->codecpar->channels); - if (!b->table) - return AVERROR(ENOMEM); for (ch = 0; ch < st->codecpar->channels; ch++) { + if (!bfstm) + avio_skip(s->pb, pos + 16LL + b->offsets[ch].offset - avio_tell(s->pb)); + if (avio_read(s->pb, b->table + ch * 32, 32) != 32) { ret = AVERROR_INVALIDDATA; goto fail; } - avio_skip(s->pb, bfstm ? 14 : 24); + + if (bfstm) + avio_skip(s->pb, 14); } } @@ -393,18 +418,13 @@ av_log(s, AV_LOG_ERROR, "adpcm_thp requires ADPC chunk, but none was found.\n"); return AVERROR_INVALIDDATA; } - if (!b->table) { - b->table = av_mallocz(32 * par->channels); - if (!b->table) - return AVERROR(ENOMEM); - } if (size > (INT_MAX - 32 - 4) || (32 + 4 + size) > (INT_MAX / par->channels) || (32 + 4 + size) * par->channels > INT_MAX - 8) return AVERROR_INVALIDDATA; - if (av_new_packet(pkt, 8 + (32 + 4 + size) * par->channels) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, 8 + (32 + 4 + size) * par->channels)) < 0) + return ret; dst = pkt->data; if (par->codec_id == AV_CODEC_ID_ADPCM_THP_LE) { bytestream_put_le32(&dst, size * par->channels); @@ -422,8 +442,7 @@ dst += size; avio_skip(s->pb, skip); if (ret != size) { - av_packet_unref(pkt); - break; + return AVERROR(EIO); } } pkt->duration = samples; @@ -447,7 +466,11 @@ BRSTMDemuxContext *b = s->priv_data; int64_t ret = 0; + if (timestamp < 0) + timestamp = 0; timestamp /= b->samples_per_block; + if (timestamp >= b->block_count) + timestamp = b->block_count - 1; ret = avio_seek(s->pb, b->data_start + timestamp * b->block_size * st->codecpar->channels, SEEK_SET); if (ret < 0) diff -Nru ffmpeg-4.2.2/libavformat/c93.c ffmpeg-4.4/libavformat/c93.c --- ffmpeg-4.2.2/libavformat/c93.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/c93.c 2020-07-11 10:39:30.000000000 +0000 @@ -158,22 +158,19 @@ ret = avio_read(pb, pkt->data + 1, datasize); if (ret < datasize) { - ret = AVERROR(EIO); - goto fail; + return AVERROR(EIO); } datasize = avio_rl16(pb); /* palette size */ if (datasize) { if (datasize != 768) { av_log(s, AV_LOG_ERROR, "invalid palette size %u\n", datasize); - ret = AVERROR_INVALIDDATA; - goto fail; + return AVERROR_INVALIDDATA; } pkt->data[0] |= C93_HAS_PALETTE; ret = avio_read(pb, pkt->data + pkt->size, datasize); if (ret < datasize) { - ret = AVERROR(EIO); - goto fail; + return AVERROR(EIO); } pkt->size += 768; } @@ -186,10 +183,6 @@ pkt->data[0] |= C93_FIRST_FRAME; } return 0; - - fail: - av_packet_unref(pkt); - return ret; } AVInputFormat ff_c93_demuxer = { diff -Nru ffmpeg-4.2.2/libavformat/cache.c ffmpeg-4.4/libavformat/cache.c --- ffmpeg-4.2.2/libavformat/cache.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/cache.c 2020-07-11 10:39:30.000000000 +0000 @@ -310,7 +310,7 @@ av_log(h, AV_LOG_ERROR, "Could not delete %s.\n", c->filename); av_freep(&c->filename); } - ffurl_close(c->inner); + ffurl_closep(&c->inner); av_tree_enumerate(c->root, NULL, NULL, enu_free); av_tree_destroy(c->root); @@ -326,7 +326,7 @@ }; static const AVClass cache_context_class = { - .class_name = "Cache", + .class_name = "cache", .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, diff -Nru ffmpeg-4.2.2/libavformat/caf.c ffmpeg-4.4/libavformat/caf.c --- ffmpeg-4.2.2/libavformat/caf.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavformat/caf.c 2021-04-08 21:28:40.000000000 +0000 @@ -78,3 +78,4 @@ { AV_CODEC_ID_NONE, 0 }, }; +const AVCodecTag *const ff_caf_codec_tags_list[] = { ff_codec_caf_tags, NULL }; diff -Nru ffmpeg-4.2.2/libavformat/cafdec.c ffmpeg-4.4/libavformat/cafdec.c --- ffmpeg-4.2.2/libavformat/cafdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/cafdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -70,7 +70,7 @@ /* parse format description */ st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->sample_rate = av_int2double(avio_rb64(pb)); + st->codecpar->sample_rate = av_clipd(av_int2double(avio_rb64(pb)), 0, INT_MAX); st->codecpar->codec_tag = avio_rl32(pb); flags = avio_rb32(pb); caf->bytes_per_packet = avio_rb32(pb); @@ -79,6 +79,9 @@ st->codecpar->channels = avio_rb32(pb); st->codecpar->bits_per_coded_sample = avio_rb32(pb); + if (caf->bytes_per_packet < 0 || caf->frames_per_packet < 0) + return AVERROR_INVALIDDATA; + /* calculate bit rate for constant size packets */ if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) { st->codecpar->bit_rate = (uint64_t)st->codecpar->sample_rate * (uint64_t)caf->bytes_per_packet * 8 @@ -100,6 +103,7 @@ { AVIOContext *pb = s->pb; AVStream *st = s->streams[0]; + int ret; if (size < 0 || size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) return -1; @@ -134,9 +138,8 @@ return AVERROR_INVALIDDATA; } - av_freep(&st->codecpar->extradata); - if (ff_alloc_extradata(st->codecpar, ALAC_HEADER)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, ALAC_HEADER)) < 0) + return ret; /* For the old style cookie, we skip 12 bytes, then read 36 bytes. * The new style cookie only contains the last 24 bytes of what was @@ -174,10 +177,8 @@ return AVERROR_PATCHWELCOME; } avio_skip(pb, size); - } else { - av_freep(&st->codecpar->extradata); - if (ff_get_extradata(s, st->codecpar, pb, size) < 0) - return AVERROR(ENOMEM); + } else if ((ret = ff_get_extradata(s, st->codecpar, pb, size)) < 0) { + return ret; } return 0; @@ -191,6 +192,7 @@ CafContext *caf = s->priv_data; int64_t pos = 0, ccount, num_packets; int i; + int ret; ccount = avio_tell(pb); @@ -202,11 +204,20 @@ st->nb_frames += avio_rb32(pb); /* priming frames */ st->nb_frames += avio_rb32(pb); /* remainder frames */ - st->duration = 0; - for (i = 0; i < num_packets; i++) { - av_add_index_entry(s->streams[0], pos, st->duration, 0, 0, AVINDEX_KEYFRAME); - pos += caf->bytes_per_packet ? caf->bytes_per_packet : ff_mp4_read_descr_len(pb); - st->duration += caf->frames_per_packet ? caf->frames_per_packet : ff_mp4_read_descr_len(pb); + if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) { + st->duration = caf->frames_per_packet * num_packets; + pos = caf-> bytes_per_packet * num_packets; + } else { + st->duration = 0; + for (i = 0; i < num_packets; i++) { + if (avio_feof(pb)) + return AVERROR_INVALIDDATA; + ret = av_add_index_entry(s->streams[0], pos, st->duration, 0, 0, AVINDEX_KEYFRAME); + if (ret < 0) + return ret; + pos += caf->bytes_per_packet ? caf->bytes_per_packet : ff_mp4_read_descr_len(pb); + st->duration += caf->frames_per_packet ? caf->frames_per_packet : ff_mp4_read_descr_len(pb); + } } if (avio_tell(pb) - ccount > size) { @@ -454,5 +465,5 @@ .read_header = read_header, .read_packet = read_packet, .read_seek = read_seek, - .codec_tag = (const AVCodecTag* const []){ ff_codec_caf_tags, 0 }, + .codec_tag = ff_caf_codec_tags_list, }; diff -Nru ffmpeg-4.2.2/libavformat/cafenc.c ffmpeg-4.4/libavformat/cafenc.c --- ffmpeg-4.2.2/libavformat/cafenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/cafenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -203,7 +203,6 @@ avio_wb64(pb, -1); //< mChunkSize avio_wb32(pb, 0); //< mEditCount - avio_flush(pb); return 0; } @@ -259,7 +258,6 @@ avio_write(pb, caf->pkt_sizes, caf->size_entries_used); caf->size_buffer_size = 0; } - avio_flush(pb); } av_freep(&caf->pkt_sizes); return 0; @@ -276,5 +274,5 @@ .write_header = caf_write_header, .write_packet = caf_write_packet, .write_trailer = caf_write_trailer, - .codec_tag = (const AVCodecTag* const []){ff_codec_caf_tags, 0}, + .codec_tag = ff_caf_codec_tags_list, }; diff -Nru ffmpeg-4.2.2/libavformat/caf.h ffmpeg-4.4/libavformat/caf.h --- ffmpeg-4.2.2/libavformat/caf.h 2016-03-29 02:25:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/caf.h 2021-04-08 21:28:40.000000000 +0000 @@ -30,5 +30,6 @@ #include "internal.h" extern const AVCodecTag ff_codec_caf_tags[]; +extern const AVCodecTag *const ff_caf_codec_tags_list[]; #endif /* AVFORMAT_CAF_H */ diff -Nru ffmpeg-4.2.2/libavformat/cdg.c ffmpeg-4.4/libavformat/cdg.c --- ffmpeg-4.2.2/libavformat/cdg.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/cdg.c 2021-04-08 21:28:40.000000000 +0000 @@ -26,10 +26,6 @@ #define CDG_COMMAND 0x09 #define CDG_MASK 0x3F -typedef struct CDGContext { - int got_first_packet; -} CDGContext; - static int read_header(AVFormatContext *s) { AVStream *vst; @@ -49,33 +45,23 @@ if (ret < 0) { av_log(s, AV_LOG_WARNING, "Cannot calculate duration as file size cannot be determined\n"); } else - vst->duration = (ret * vst->time_base.den) / (CDG_PACKET_SIZE * 300); + vst->duration = (ret * (int64_t)vst->time_base.den) / (CDG_PACKET_SIZE * 300); return 0; } static int read_packet(AVFormatContext *s, AVPacket *pkt) { - CDGContext *priv = s->priv_data; int ret; - while (1) { - ret = av_get_packet(s->pb, pkt, CDG_PACKET_SIZE); - if (ret < 1 || (pkt->data[0] & CDG_MASK) == CDG_COMMAND) - break; - av_packet_unref(pkt); - } - - if (!priv->got_first_packet) { - pkt->flags |= AV_PKT_FLAG_KEY; - priv->got_first_packet = 1; - } - + ret = av_get_packet(s->pb, pkt, CDG_PACKET_SIZE); pkt->stream_index = 0; pkt->dts= pkt->pts= pkt->pos / CDG_PACKET_SIZE; - if(ret>5 && (pkt->data[0]&0x3F) == 9 && (pkt->data[1]&0x3F)==1 && !(pkt->data[2+2+1] & 0x0F)){ + if (!pkt->pos || (ret > 5 && + (pkt->data[0] & CDG_MASK) == CDG_COMMAND && + (pkt->data[1] & CDG_MASK) == 1 && !(pkt->data[2+2+1] & 0x0F))) { pkt->flags = AV_PKT_FLAG_KEY; } return ret; @@ -84,7 +70,6 @@ AVInputFormat ff_cdg_demuxer = { .name = "cdg", .long_name = NULL_IF_CONFIG_SMALL("CD Graphics"), - .priv_data_size = sizeof(CDGContext), .read_header = read_header, .read_packet = read_packet, .flags = AVFMT_GENERIC_INDEX, diff -Nru ffmpeg-4.2.2/libavformat/cdxl.c ffmpeg-4.4/libavformat/cdxl.c --- ffmpeg-4.2.2/libavformat/cdxl.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/cdxl.c 2021-04-08 21:28:40.000000000 +0000 @@ -30,53 +30,70 @@ typedef struct CDXLDemuxContext { AVClass *class; - int sample_rate; - char *framerate; - AVRational fps; int read_chunk; + AVRational frate; + int srate; + AVRational frame_rate; + int sample_rate; uint8_t header[CDXL_HEADER_SIZE]; int video_stream_index; int audio_stream_index; int64_t filesize; + int64_t pos; } CDXLDemuxContext; static int cdxl_read_probe(const AVProbeData *p) { int score = AVPROBE_SCORE_EXTENSION + 10; + const uint8_t *buf = p->buf; if (p->buf_size < CDXL_HEADER_SIZE) return 0; - /* reserved bytes should always be set to 0 */ - if (AV_RN64(&p->buf[24]) || AV_RN16(&p->buf[10])) + /* check type */ + if (buf[0] > 1) return 0; - /* check type */ - if (p->buf[0] != 1) + /* reserved bytes should always be set to 0 */ + if (AV_RL24(&buf[29])) return 0; /* check palette size */ - if (AV_RB16(&p->buf[20]) > 512) + if (!AV_RN16(&buf[20])) + return 0; + if (buf[0] == 1 && AV_RB16(&buf[20]) > 512) + return 0; + if (buf[0] == 0 && AV_RB16(&buf[20]) > 768) + return 0; + + if (!AV_RN16(&buf[22]) && AV_RN16(&buf[24])) + return 0; + + if (buf[0] == 0 && (!buf[26] || !AV_RB16(&buf[24]))) return 0; /* check number of planes */ - if (p->buf[18] || !p->buf[19]) + if (buf[19] != 6 && buf[19] != 8 && buf[19] != 24) + return 0; + + if (buf[18]) return 0; /* check widh and height */ - if (!AV_RN16(&p->buf[14]) || !AV_RN16(&p->buf[16])) + if (AV_RB16(&buf[14]) > 640 || AV_RB16(&buf[16]) > 480 || + AV_RB16(&buf[14]) == 0 || AV_RB16(&buf[16]) == 0) return 0; /* chunk size */ - if (AV_RB32(&p->buf[2]) < AV_RB16(&p->buf[22]) + AV_RB16(&p->buf[20]) + CDXL_HEADER_SIZE) + if (AV_RB32(&buf[2]) <= AV_RB16(&buf[20]) + AV_RB16(&buf[22]) * (1 + !!(buf[1] & 0x10)) + CDXL_HEADER_SIZE) return 0; /* previous chunk size */ - if (AV_RN32(&p->buf[6])) + if (AV_RN32(&buf[6])) score /= 2; /* current frame number, usually starts from 1 */ - if (AV_RB16(&p->buf[12]) != 1) + if (AV_RB32(&buf[10]) != 1) score /= 2; return score; @@ -85,13 +102,6 @@ static int cdxl_read_header(AVFormatContext *s) { CDXLDemuxContext *cdxl = s->priv_data; - int ret; - - if (cdxl->framerate && (ret = av_parse_video_rate(&cdxl->fps, cdxl->framerate)) < 0) { - av_log(s, AV_LOG_ERROR, - "Could not parse framerate: %s.\n", cdxl->framerate); - return ret; - } cdxl->read_chunk = 0; cdxl->video_stream_index = -1; @@ -110,27 +120,34 @@ AVIOContext *pb = s->pb; uint32_t current_size, video_size, image_size; uint16_t audio_size, palette_size, width, height; - int64_t pos; - int format, frames, ret; + int channels, type, format, ret; if (avio_feof(pb)) return AVERROR_EOF; - pos = avio_tell(pb); - if (!cdxl->read_chunk && - avio_read(pb, cdxl->header, CDXL_HEADER_SIZE) != CDXL_HEADER_SIZE) - return AVERROR_EOF; - if (cdxl->header[0] != 1) { - av_log(s, AV_LOG_ERROR, "non-standard cdxl file\n"); + if (!cdxl->read_chunk) { + cdxl->pos = avio_tell(pb); + if (avio_read(pb, cdxl->header, CDXL_HEADER_SIZE) != CDXL_HEADER_SIZE) + return AVERROR_EOF; + } + if (cdxl->header[0] > 1) { + av_log(s, AV_LOG_ERROR, "unsupported cdxl file\n"); return AVERROR_INVALIDDATA; } + type = cdxl->header[0]; + channels = 1 + !!(cdxl->header[1] & 0x10); format = cdxl->header[1] & 0xE0; current_size = AV_RB32(&cdxl->header[2]); width = AV_RB16(&cdxl->header[14]); height = AV_RB16(&cdxl->header[16]); palette_size = AV_RB16(&cdxl->header[20]); - audio_size = AV_RB16(&cdxl->header[22]); + audio_size = AV_RB16(&cdxl->header[22]) * channels; + cdxl->srate = AV_RB16(&cdxl->header[24]); + if (!cdxl->srate && audio_size) + cdxl->srate = cdxl->sample_rate; + cdxl->frate.num = cdxl->header[26]; + cdxl->frate.den = 1; if (cdxl->header[19] == 0 || FFALIGN(width, 16) * (uint64_t)height * cdxl->header[19] > INT_MAX) return AVERROR_INVALIDDATA; @@ -140,11 +157,18 @@ image_size = FFALIGN(width, 16) * height * cdxl->header[19] / 8; video_size = palette_size + image_size; - if (palette_size > 512) + if ((type == 1 && palette_size > 512) || + (type == 0 && palette_size > 768)) return AVERROR_INVALIDDATA; if (current_size < (uint64_t)audio_size + video_size + CDXL_HEADER_SIZE) return AVERROR_INVALIDDATA; + if (!cdxl->frate.num && audio_size && cdxl->srate > 0) { + cdxl->frate = (AVRational){ cdxl->srate, audio_size }; + } else if (!cdxl->frate.num) { + cdxl->frate = cdxl->frame_rate; + } + if (cdxl->read_chunk && audio_size) { if (cdxl->audio_stream_index == -1) { AVStream *st = avformat_new_stream(s, NULL); @@ -153,26 +177,23 @@ st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_tag = 0; - st->codecpar->codec_id = AV_CODEC_ID_PCM_S8; - if (cdxl->header[1] & 0x10) { - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; - } else { - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; - } - st->codecpar->sample_rate = cdxl->sample_rate; + st->codecpar->codec_id = AV_CODEC_ID_PCM_S8_PLANAR; + st->codecpar->channels = channels; + st->codecpar->channel_layout = channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; + st->codecpar->sample_rate= cdxl->srate; st->start_time = 0; cdxl->audio_stream_index = st->index; - avpriv_set_pts_info(st, 64, 1, cdxl->sample_rate); + avpriv_set_pts_info(st, 64, 1, cdxl->srate); + if (current_size && cdxl->filesize > 0 && audio_size > 0) + st->duration = (cdxl->filesize / current_size) * audio_size / channels; } ret = av_get_packet(pb, pkt, audio_size); if (ret < 0) return ret; pkt->stream_index = cdxl->audio_stream_index; - pkt->pos = pos; - pkt->duration = audio_size; + pkt->pos = cdxl->pos; + pkt->duration = audio_size / channels; cdxl->read_chunk = 0; } else { if (cdxl->video_stream_index == -1) { @@ -186,35 +207,25 @@ st->codecpar->width = width; st->codecpar->height = height; - if (audio_size + video_size && cdxl->filesize > 0) { - frames = cdxl->filesize / (audio_size + video_size); - - if(cdxl->framerate) - st->duration = frames; - else - st->duration = frames * (int64_t)audio_size; - } + if (current_size && cdxl->filesize > 0) + st->nb_frames = cdxl->filesize / current_size; st->start_time = 0; cdxl->video_stream_index = st->index; - if (cdxl->framerate) - avpriv_set_pts_info(st, 64, cdxl->fps.den, cdxl->fps.num); - else - avpriv_set_pts_info(st, 64, 1, cdxl->sample_rate); + avpriv_set_pts_info(st, 64, cdxl->frate.den, cdxl->frate.num); } - if (av_new_packet(pkt, video_size + CDXL_HEADER_SIZE) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, video_size + CDXL_HEADER_SIZE)) < 0) + return ret; memcpy(pkt->data, cdxl->header, CDXL_HEADER_SIZE); ret = avio_read(pb, pkt->data + CDXL_HEADER_SIZE, video_size); if (ret < 0) { - av_packet_unref(pkt); return ret; } av_shrink_packet(pkt, CDXL_HEADER_SIZE + ret); pkt->stream_index = cdxl->video_stream_index; pkt->flags |= AV_PKT_FLAG_KEY; - pkt->pos = pos; - pkt->duration = cdxl->framerate ? 1 : audio_size ? audio_size : 220; + pkt->pos = cdxl->pos; + pkt->duration = 1; cdxl->read_chunk = audio_size; } @@ -223,10 +234,20 @@ return ret; } +static int read_seek(AVFormatContext *s, int stream_index, + int64_t timestamp, int flags) +{ + CDXLDemuxContext *cdxl = s->priv_data; + + cdxl->read_chunk = 0; + + return -1; +} + #define OFFSET(x) offsetof(CDXLDemuxContext, x) static const AVOption cdxl_options[] = { - { "sample_rate", "", OFFSET(sample_rate), AV_OPT_TYPE_INT, { .i64 = 11025 }, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, + { "sample_rate", "", OFFSET(sample_rate), AV_OPT_TYPE_INT, { .i64=11025 }, 8000, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, + { "frame_rate", "", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, { .str="15" }, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, { NULL }, }; @@ -241,10 +262,11 @@ .name = "cdxl", .long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"), .priv_data_size = sizeof(CDXLDemuxContext), + .priv_class = &cdxl_demuxer_class, .read_probe = cdxl_read_probe, .read_header = cdxl_read_header, .read_packet = cdxl_read_packet, + .read_seek = read_seek, .extensions = "cdxl,xl", .flags = AVFMT_GENERIC_INDEX, - .priv_class = &cdxl_demuxer_class, }; diff -Nru ffmpeg-4.2.2/libavformat/chromaprint.c ffmpeg-4.4/libavformat/chromaprint.c --- ffmpeg-4.2.2/libavformat/chromaprint.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/chromaprint.c 2021-04-08 21:28:40.000000000 +0000 @@ -1,6 +1,6 @@ /* * Chromaprint fingerprinting muxer - * Copyright (c) 2015 Rodger Combs + * Copyright (c) 2015 rcombs * * This file is part of FFmpeg. * @@ -73,7 +73,7 @@ if (cpr->silence_threshold != -1) { #if CPR_VERSION_INT >= AV_VERSION_INT(0, 7, 0) if (!chromaprint_set_option(cpr->ctx, "silence_threshold", cpr->silence_threshold)) { - av_log(s, AV_LOG_ERROR, "Failed to set silence threshold.\n"); + av_log(s, AV_LOG_ERROR, "Failed to set silence threshold. Setting silence_threshold requires -algorithm 3 option.\n"); goto fail; } #else @@ -114,14 +114,15 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) { ChromaprintMuxContext *cpr = s->priv_data; - return chromaprint_feed(cpr->ctx, pkt->data, pkt->size / 2) ? 0 : AVERROR(EINVAL); + return chromaprint_feed(cpr->ctx, (const int16_t *)pkt->data, pkt->size / 2) ? 0 : AVERROR(EINVAL); } static int write_trailer(AVFormatContext *s) { ChromaprintMuxContext *cpr = s->priv_data; AVIOContext *pb = s->pb; - void *fp = NULL, *enc_fp = NULL; + void *fp = NULL; + char *enc_fp = NULL; int size, enc_size, ret = AVERROR(EINVAL); if (!chromaprint_finish(cpr->ctx)) { @@ -129,14 +130,14 @@ goto fail; } - if (!chromaprint_get_raw_fingerprint(cpr->ctx, &fp, &size)) { + if (!chromaprint_get_raw_fingerprint(cpr->ctx, (uint32_t **)&fp, &size)) { av_log(s, AV_LOG_ERROR, "Failed to retrieve fingerprint\n"); goto fail; } switch (cpr->fp_format) { case FINGERPRINT_RAW: - avio_write(pb, fp, size); + avio_write(pb, fp, size * 4); //fp points to array of uint32_t break; case FINGERPRINT_COMPRESSED: case FINGERPRINT_BASE64: @@ -164,7 +165,7 @@ static const AVOption options[] = { { "silence_threshold", "threshold for detecting silence", OFFSET(silence_threshold), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 32767, FLAGS }, { "algorithm", "version of the fingerprint algorithm", OFFSET(algorithm), AV_OPT_TYPE_INT, { .i64 = CHROMAPRINT_ALGORITHM_DEFAULT }, CHROMAPRINT_ALGORITHM_TEST1, INT_MAX, FLAGS }, - { "fp_format", "fingerprint format to write", OFFSET(fp_format), AV_OPT_TYPE_INT, { .i64 = FINGERPRINT_BASE64 }, FINGERPRINT_RAW, FINGERPRINT_BASE64, FLAGS }, + { "fp_format", "fingerprint format to write", OFFSET(fp_format), AV_OPT_TYPE_INT, { .i64 = FINGERPRINT_BASE64 }, FINGERPRINT_RAW, FINGERPRINT_BASE64, FLAGS, "fp_format" }, { "raw", "binary raw fingerprint", 0, AV_OPT_TYPE_CONST, {.i64 = FINGERPRINT_RAW }, INT_MIN, INT_MAX, FLAGS, "fp_format"}, { "compressed", "binary compressed fingerprint", 0, AV_OPT_TYPE_CONST, {.i64 = FINGERPRINT_COMPRESSED }, INT_MIN, INT_MAX, FLAGS, "fp_format"}, { "base64", "Base64 compressed fingerprint", 0, AV_OPT_TYPE_CONST, {.i64 = FINGERPRINT_BASE64 }, INT_MIN, INT_MAX, FLAGS, "fp_format"}, diff -Nru ffmpeg-4.2.2/libavformat/cinedec.c ffmpeg-4.4/libavformat/cinedec.c --- ffmpeg-4.2.2/libavformat/cinedec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/cinedec.c 2021-04-08 21:28:40.000000000 +0000 @@ -168,6 +168,10 @@ avio_skip(pb, 616); // Binning .. bFlipH if (!avio_rl32(pb) ^ vflip) { st->codecpar->extradata = av_strdup("BottomUp"); + if (!st->codecpar->extradata) { + st->codecpar->extradata_size = 0; + return AVERROR(ENOMEM); + } st->codecpar->extradata_size = 9; } @@ -284,7 +288,7 @@ AVIOContext *pb = avctx->pb; int n, size, ret; - if (cine->pts >= st->duration) + if (cine->pts >= st->nb_index_entries) return AVERROR_EOF; avio_seek(pb, st->index_entries[cine->pts].pos, SEEK_SET); diff -Nru ffmpeg-4.2.2/libavformat/codec2.c ffmpeg-4.4/libavformat/codec2.c --- ffmpeg-4.2.2/libavformat/codec2.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/codec2.c 2021-04-08 21:28:40.000000000 +0000 @@ -29,8 +29,8 @@ #include "rawenc.h" #include "pcm.h" -#define AVPRIV_CODEC2_HEADER_SIZE 7 -#define AVPRIV_CODEC2_MAGIC 0xC0DEC2 +#define CODEC2_HEADER_SIZE 7 +#define CODEC2_MAGIC 0xC0DEC2 //the lowest version we should ever run across is 0.8 //we may run across later versions as the format evolves @@ -46,7 +46,7 @@ static int codec2_probe(const AVProbeData *p) { //must start wih C0 DE C2 - if (AV_RB24(p->buf) != AVPRIV_CODEC2_MAGIC) { + if (AV_RB24(p->buf) != CODEC2_MAGIC) { return 0; } @@ -61,9 +61,69 @@ return AVPROBE_SCORE_EXTENSION + 1; } +//Mimics codec2_samples_per_frame() +static int codec2_mode_frame_size(AVFormatContext *s, int mode) +{ + int frame_size_table[CODEC2_MODE_MAX+1] = { + 160, // 3200 + 160, // 2400 + 320, // 1600 + 320, // 1400 + 320, // 1300 + 320, // 1200 + 320, // 700 + 320, // 700B + 320, // 700C + }; + + if (mode < 0 || mode > CODEC2_MODE_MAX) { + av_log(s, AV_LOG_ERROR, "unknown codec2 mode %i, can't find frame_size\n", mode); + return 0; + } else { + return frame_size_table[mode]; + } +} + +//Mimics (codec2_bits_per_frame()+7)/8 +static int codec2_mode_block_align(AVFormatContext *s, int mode) +{ + int block_align_table[CODEC2_MODE_MAX+1] = { + 8, // 3200 + 6, // 2400 + 8, // 1600 + 7, // 1400 + 7, // 1300 + 6, // 1200 + 4, // 700 + 4, // 700B + 4, // 700C + }; + + if (mode < 0 || mode > CODEC2_MODE_MAX) { + av_log(s, AV_LOG_ERROR, "unknown codec2 mode %i, can't find block_align\n", mode); + return 0; + } else { + return block_align_table[mode]; + } +} + +//Computes bitrate from mode, with frames rounded up to the nearest octet. +//So 700 bit/s (28 bits/frame) becomes 800 bits/s (32 bits/frame). +static int codec2_mode_bit_rate(AVFormatContext *s, int mode) +{ + int frame_size = codec2_mode_frame_size(s, mode); + int block_align = codec2_mode_block_align(s, mode); + + if (frame_size <= 0 || block_align <= 0) { + return 0; + } + + return 8 * 8000 * block_align / frame_size; +} + static int codec2_read_header_common(AVFormatContext *s, AVStream *st) { - int mode = avpriv_codec2_mode_from_extradata(st->codecpar->extradata); + int mode = codec2_mode_from_extradata(st->codecpar->extradata); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_CODEC2; @@ -71,9 +131,9 @@ st->codecpar->channels = 1; st->codecpar->format = AV_SAMPLE_FMT_S16; st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; - st->codecpar->bit_rate = avpriv_codec2_mode_bit_rate(s, mode); - st->codecpar->frame_size = avpriv_codec2_mode_frame_size(s, mode); - st->codecpar->block_align = avpriv_codec2_mode_block_align(s, mode); + st->codecpar->bit_rate = codec2_mode_bit_rate(s, mode); + st->codecpar->frame_size = codec2_mode_frame_size(s, mode); + st->codecpar->block_align = codec2_mode_block_align(s, mode); if (st->codecpar->bit_rate <= 0 || st->codecpar->frame_size <= 0 || @@ -95,28 +155,28 @@ return AVERROR(ENOMEM); } - if (avio_rb24(s->pb) != AVPRIV_CODEC2_MAGIC) { + if (avio_rb24(s->pb) != CODEC2_MAGIC) { av_log(s, AV_LOG_ERROR, "not a .c2 file\n"); return AVERROR_INVALIDDATA; } - ret = ff_alloc_extradata(st->codecpar, AVPRIV_CODEC2_EXTRADATA_SIZE); + ret = ff_alloc_extradata(st->codecpar, CODEC2_EXTRADATA_SIZE); if (ret) { return ret; } - ret = ffio_read_size(s->pb, st->codecpar->extradata, AVPRIV_CODEC2_EXTRADATA_SIZE); + ret = ffio_read_size(s->pb, st->codecpar->extradata, CODEC2_EXTRADATA_SIZE); if (ret < 0) { return ret; } - version = avpriv_codec2_version_from_extradata(st->codecpar->extradata); + version = AV_RB16(st->codecpar->extradata); if ((version >> 8) != EXPECTED_CODEC2_MAJOR_VERSION) { avpriv_report_missing_feature(s, "Major version %i", version >> 8); return AVERROR_PATCHWELCOME; } - s->internal->data_offset = AVPRIV_CODEC2_HEADER_SIZE; + s->internal->data_offset = CODEC2_HEADER_SIZE; return codec2_read_header_common(s, st); } @@ -160,14 +220,14 @@ st = s->streams[0]; - if (st->codecpar->extradata_size != AVPRIV_CODEC2_EXTRADATA_SIZE) { + if (st->codecpar->extradata_size != CODEC2_EXTRADATA_SIZE) { av_log(s, AV_LOG_ERROR, ".c2 files require exactly %i bytes of extradata (got %i)\n", - AVPRIV_CODEC2_EXTRADATA_SIZE, st->codecpar->extradata_size); + CODEC2_EXTRADATA_SIZE, st->codecpar->extradata_size); return AVERROR(EINVAL); } - avio_wb24(s->pb, AVPRIV_CODEC2_MAGIC); - avio_write(s->pb, st->codecpar->extradata, AVPRIV_CODEC2_EXTRADATA_SIZE); + avio_wb24(s->pb, CODEC2_MAGIC); + avio_write(s->pb, st->codecpar->extradata, CODEC2_EXTRADATA_SIZE); return 0; } @@ -189,13 +249,13 @@ return AVERROR(ENOMEM); } - ret = ff_alloc_extradata(st->codecpar, AVPRIV_CODEC2_EXTRADATA_SIZE); + ret = ff_alloc_extradata(st->codecpar, CODEC2_EXTRADATA_SIZE); if (ret) { return ret; } s->internal->data_offset = 0; - avpriv_codec2_make_extradata(st->codecpar->extradata, c2->mode); + codec2_make_extradata(st->codecpar->extradata, c2->mode); return codec2_read_header_common(s, st); } @@ -211,7 +271,7 @@ }; static const AVOption codec2raw_options[] = { - AVPRIV_CODEC2_AVOPTIONS("codec2 mode [mandatory]", Codec2Context, -1, -1, AV_OPT_FLAG_DECODING_PARAM), + CODEC2_AVOPTIONS("codec2 mode [mandatory]", Codec2Context, -1, -1, AV_OPT_FLAG_DECODING_PARAM), FRAMES_PER_PACKET, { NULL }, }; diff -Nru ffmpeg-4.2.2/libavformat/concat.c ffmpeg-4.4/libavformat/concat.c --- ffmpeg-4.2.2/libavformat/concat.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/concat.c 2021-04-08 21:28:40.000000000 +0000 @@ -38,6 +38,7 @@ struct concat_nodes *nodes; ///< list of nodes to concat size_t length; ///< number of cat'ed nodes size_t current; ///< index of currently read node + uint64_t total_size; }; static av_cold int concat_close(URLContext *h) @@ -48,7 +49,7 @@ struct concat_nodes *nodes = data->nodes; for (i = 0; i != data->length; i++) - err |= ffurl_close(nodes[i].uc); + err |= ffurl_closep(&nodes[i].uc); av_freep(&data->nodes); @@ -59,7 +60,7 @@ { char *node_uri = NULL; int err = 0; - int64_t size; + int64_t size, total_size = 0; size_t len, i; URLContext *uc; struct concat_data *data = h->priv_data; @@ -72,15 +73,11 @@ for (i = 0, len = 1; uri[i]; i++) { if (uri[i] == *AV_CAT_SEPARATOR) { - /* integer overflow */ - if (++len == UINT_MAX / sizeof(*nodes)) { - av_freep(&h->priv_data); - return AVERROR(ENAMETOOLONG); - } + len++; } } - if (!(nodes = av_realloc(NULL, sizeof(*nodes) * len))) + if (!(nodes = av_realloc_array(NULL, len, sizeof(*nodes)))) return AVERROR(ENOMEM); else data->nodes = nodes; @@ -112,6 +109,7 @@ /* assembling */ nodes[i].uc = uc; nodes[i].size = size; + total_size += size; } av_free(node_uri); data->length = i; @@ -123,6 +121,7 @@ err = AVERROR(ENOMEM); } else data->nodes = nodes; + data->total_size = total_size; return err; } @@ -158,6 +157,8 @@ struct concat_nodes *nodes = data->nodes; size_t i; + if ((whence & AVSEEK_SIZE)) + return data->total_size; switch (whence) { case SEEK_END: for (i = data->length - 1; i && pos < -nodes[i].size; i--) diff -Nru ffmpeg-4.2.2/libavformat/concatdec.c ffmpeg-4.4/libavformat/concatdec.c --- ffmpeg-4.2.2/libavformat/concatdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/concatdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -113,7 +113,8 @@ ConcatFile *file; char *url = NULL; const char *proto; - size_t url_len, proto_len; + const char *ptr; + size_t url_len; int ret; if (cat->safe > 0 && !safe_filename(filename)) { @@ -122,9 +123,8 @@ } proto = avio_find_protocol_name(filename); - proto_len = proto ? strlen(proto) : 0; - if (proto && !memcmp(filename, proto, proto_len) && - (filename[proto_len] == ':' || filename[proto_len] == ',')) { + if (proto && av_strstart(filename, proto, &ptr) && + (*ptr == ':' || *ptr == ',')) { url = filename; filename = NULL; } else { @@ -171,10 +171,6 @@ if (st->codecpar->codec_id || !source_st->codecpar->codec_id) { if (st->codecpar->extradata_size < source_st->codecpar->extradata_size) { - if (st->codecpar->extradata) { - av_freep(&st->codecpar->extradata); - st->codecpar->extradata_size = 0; - } ret = ff_alloc_extradata(st->codecpar, source_st->codecpar->extradata_size); if (ret < 0) @@ -546,7 +542,6 @@ if (ret < 0) { av_log(avf, AV_LOG_ERROR, "h264_mp4toannexb filter " "failed to send input packet\n"); - av_packet_unref(pkt); return ret; } @@ -596,7 +591,6 @@ if (ret < 0) return ret; if ((ret = match_streams(avf)) < 0) { - av_packet_unref(pkt); return ret; } if (packet_after_outpoint(cat, pkt)) { @@ -612,7 +606,7 @@ } break; } - if ((ret = filter_packet(avf, cs, pkt))) + if ((ret = filter_packet(avf, cs, pkt)) < 0) return ret; st = cat->avf->streams[pkt->stream_index]; @@ -632,17 +626,16 @@ av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base)); if (cat->cur_file->metadata) { - uint8_t* metadata; - int metadata_len; + buffer_size_t metadata_len; char* packed_metadata = av_packet_pack_dictionary(cat->cur_file->metadata, &metadata_len); if (!packed_metadata) return AVERROR(ENOMEM); - if (!(metadata = av_packet_new_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, metadata_len))) { + ret = av_packet_add_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, + packed_metadata, metadata_len); + if (ret < 0) { av_freep(&packed_metadata); - return AVERROR(ENOMEM); + return ret; } - memcpy(metadata, packed_metadata, metadata_len); - av_freep(&packed_metadata); } if (cat->cur_file->duration == AV_NOPTS_VALUE && st->cur_dts != AV_NOPTS_VALUE) { @@ -653,7 +646,7 @@ } pkt->stream_index = cs->out_stream_index; - return ret; + return 0; } static void rescale_interval(AVRational tb_in, AVRational tb_out, diff -Nru ffmpeg-4.2.2/libavformat/crypto.c ffmpeg-4.4/libavformat/crypto.c --- ffmpeg-4.2.2/libavformat/crypto.c 2019-07-08 17:45:25.000000000 +0000 +++ ffmpeg-4.4/libavformat/crypto.c 2021-04-08 21:28:40.000000000 +0000 @@ -252,21 +252,17 @@ case SEEK_CUR: pos = pos + c->position; break; - case SEEK_END: { - int64_t newpos = ffurl_seek( c->hd, pos, AVSEEK_SIZE ); + case SEEK_END: + newpos = ffurl_seek( c->hd, pos, AVSEEK_SIZE ); if (newpos < 0) { av_log(h, AV_LOG_ERROR, "Crypto: seek_end - can't get file size (pos=%lld)\r\n", (long long int)pos); return newpos; } pos = newpos - pos; - } - break; - case AVSEEK_SIZE: { - int64_t newpos = ffurl_seek( c->hd, pos, AVSEEK_SIZE ); - return newpos; - } break; + case AVSEEK_SIZE: + return ffurl_seek( c->hd, pos, AVSEEK_SIZE ); default: av_log(h, AV_LOG_ERROR, "Crypto: no support for seek where 'whence' is %d\r\n", whence); @@ -385,8 +381,7 @@ ret = ffurl_write(c->hd, out_buf, BLOCKSIZE); } - if (c->hd) - ffurl_close(c->hd); + ffurl_closep(&c->hd); av_freep(&c->aes_decrypt); av_freep(&c->aes_encrypt); av_freep(&c->write_buf); diff -Nru ffmpeg-4.2.2/libavformat/cutils.c ffmpeg-4.4/libavformat/cutils.c --- ffmpeg-4.2.2/libavformat/cutils.c 2017-12-31 22:35:49.000000000 +0000 +++ ffmpeg-4.4/libavformat/cutils.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* - * various simple utilities for libavformat - * Copyright (c) 2000, 2001, 2002 Fabrice Bellard - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/time_internal.h" -#include "avformat.h" -#include "internal.h" - -#define ISLEAP(y) (((y) % 4 == 0) && (((y) % 100) != 0 || ((y) % 400) == 0)) -#define LEAPS_COUNT(y) ((y)/4 - (y)/100 + (y)/400) - -/* This is our own gmtime_r. It differs from its POSIX counterpart in a - couple of places, though. */ -struct tm *ff_brktimegm(time_t secs, struct tm *tm) -{ - tm = gmtime_r(&secs, tm); - - tm->tm_year += 1900; /* unlike gmtime_r we store complete year here */ - tm->tm_mon += 1; /* unlike gmtime_r tm_mon is from 1 to 12 */ - - return tm; -} diff -Nru ffmpeg-4.2.2/libavformat/dashdec.c ffmpeg-4.4/libavformat/dashdec.c --- ffmpeg-4.2.2/libavformat/dashdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/dashdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -29,6 +29,8 @@ #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; @@ -78,13 +80,10 @@ AVIOContext *input; AVFormatContext *parent; AVFormatContext *ctx; - AVPacket pkt; - int rep_idx; - int rep_count; int stream_index; - enum AVMediaType type; - char id[20]; + char *id; + char *lang; int bandwidth; AVRational framerate; AVStream *assoc_stream; /* demuxer stream associated with this representation */ @@ -122,19 +121,6 @@ typedef struct DASHContext { const AVClass *class; char *base_url; - char *adaptionset_contenttype_val; - char *adaptionset_par_val; - char *adaptionset_lang_val; - char *adaptionset_minbw_val; - char *adaptionset_maxbw_val; - char *adaptionset_minwidth_val; - char *adaptionset_maxwidth_val; - char *adaptionset_minheight_val; - char *adaptionset_maxheight_val; - char *adaptionset_minframerate_val; - char *adaptionset_maxframerate_val; - char *adaptionset_segmentalignment_val; - char *adaptionset_bitstreamswitching_val; int n_videos; struct representation **videos; @@ -157,6 +143,9 @@ uint64_t period_duration; uint64_t period_start; + /* AdaptationSet Attribute */ + char *adaptionset_lang; + int is_live; AVIOInterruptCB *interrupt_callback; char *allowed_extensions; @@ -166,13 +155,14 @@ /* Flags for init section*/ int is_init_section_common_video; int is_init_section_common_audio; + int is_init_section_common_subtitle; } DASHContext; static int ishttp(char *url) { const char *proto_name = avio_find_protocol_name(url); - return av_strstart(proto_name, "http", NULL); + return proto_name && av_strstart(proto_name, "http", NULL); } static int aligned(int val) @@ -238,21 +228,21 @@ return 0; /* parser error */ } switch (type) { - case 'D': - days = (uint32_t)value; - break; - case 'H': - hours = (uint32_t)value; - break; - case 'M': - mins = (uint32_t)value; - break; - case 'S': - secs = (uint32_t)value; - break; - default: - // handle invalid type - break; + case 'D': + days = (uint32_t)value; + break; + case 'H': + hours = (uint32_t)value; + break; + case 'M': + mins = (uint32_t)value; + break; + case 'S': + secs = (uint32_t)value; + break; + default: + // handle invalid type + break; } ptr += size; } @@ -363,14 +353,15 @@ free_fragment(&pls->init_section); av_freep(&pls->init_sec_buf); av_freep(&pls->pb.buffer); - if (pls->input) - ff_format_io_close(pls->parent, &pls->input); + ff_format_io_close(pls->parent, &pls->input); if (pls->ctx) { pls->ctx->pb = NULL; avformat_close_input(&pls->ctx); } av_freep(&pls->url_template); + av_freep(&pls->lang); + av_freep(&pls->id); av_freep(&pls); } @@ -408,16 +399,13 @@ } static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, - AVDictionary *opts, AVDictionary *opts2, int *is_http) + AVDictionary **opts, AVDictionary *opts2, int *is_http) { DASHContext *c = s->priv_data; AVDictionary *tmp = NULL; const char *proto_name = NULL; int ret; - av_dict_copy(&tmp, opts, 0); - av_dict_copy(&tmp, opts2, 0); - if (av_strstart(url, "crypto", NULL)) { if (url[6] == '+' || url[6] == ':') proto_name = avio_find_protocol_name(url + 7); @@ -451,6 +439,8 @@ return AVERROR_INVALIDDATA; av_freep(pb); + av_dict_copy(&tmp, *opts, 0); + av_dict_copy(&tmp, opts2, 0); ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); if (ret >= 0) { // update cookies on http response with setcookies. @@ -460,7 +450,7 @@ av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, (uint8_t**)&new_cookies); if (new_cookies) { - av_dict_set(&opts, "cookies", new_cookies, AV_DICT_DONT_STRDUP_VAL); + av_dict_set(opts, "cookies", new_cookies, AV_DICT_DONT_STRDUP_VAL); } } @@ -484,11 +474,9 @@ char *text; char *url = NULL; char *tmp_str = av_mallocz(max_url_size); - char *tmp_str_2 = av_mallocz(max_url_size); - if (!tmp_str || !tmp_str_2) { + if (!tmp_str) return NULL; - } for (i = 0; i < n_baseurl_nodes; ++i) { if (baseurl_nodes[i] && @@ -497,9 +485,7 @@ text = xmlNodeGetContent(baseurl_nodes[i]->children); if (text) { memset(tmp_str, 0, max_url_size); - memset(tmp_str_2, 0, max_url_size); - ff_make_absolute_url(tmp_str_2, max_url_size, tmp_str, text); - av_strlcpy(tmp_str, tmp_str_2, max_url_size); + ff_make_absolute_url(tmp_str, max_url_size, "", text); xmlFree(text); } } @@ -509,7 +495,7 @@ ff_make_absolute_url(tmp_str, max_url_size, tmp_str, val); if (rep_id_val) { - url = av_strireplace(tmp_str, "$RepresentationID$", (const char*)rep_id_val); + url = av_strireplace(tmp_str, "$RepresentationID$", rep_id_val); if (!url) { goto end; } @@ -518,14 +504,13 @@ if (rep_bandwidth_val && tmp_str[0] != '\0') { // free any previously assigned url before reassigning av_free(url); - url = av_strireplace(tmp_str, "$Bandwidth$", (const char*)rep_bandwidth_val); + url = av_strireplace(tmp_str, "$Bandwidth$", rep_bandwidth_val); if (!url) { goto end; } } end: av_free(tmp_str); - av_free(tmp_str_2); return url; } @@ -574,11 +559,11 @@ attr = i ? "mimeType" : "contentType"; val = xmlGetProp(node, attr); if (val) { - if (av_stristr((const char *)val, "video")) { + if (av_stristr(val, "video")) { type = AVMEDIA_TYPE_VIDEO; - } else if (av_stristr((const char *)val, "audio")) { + } else if (av_stristr(val, "audio")) { type = AVMEDIA_TYPE_AUDIO; - } else if (av_stristr((const char *)val, "text")) { + } else if (av_stristr(val, "text")) { type = AVMEDIA_TYPE_SUBTITLE; } xmlFree(val); @@ -600,7 +585,7 @@ char *str_end_offset; char *str_offset = av_strtok(range, "-", &str_end_offset); seg->url_offset = strtoll(str_offset, NULL, 10); - seg->size = strtoll(str_end_offset, NULL, 10) - seg->url_offset; + seg->size = strtoll(str_end_offset, NULL, 10) - seg->url_offset + 1; } return seg; @@ -617,15 +602,17 @@ char *media_val = NULL; char *range_val = NULL; int max_url_size = c ? c->max_url_size: MAX_URL_SIZE; + int err; - if (!av_strcasecmp(fragmenturl_node->name, (const char *)"Initialization")) { + if (!av_strcasecmp(fragmenturl_node->name, "Initialization")) { initialization_val = xmlGetProp(fragmenturl_node, "sourceURL"); range_val = xmlGetProp(fragmenturl_node, "range"); if (initialization_val || range_val) { + free_fragment(&rep->init_section); rep->init_section = get_Fragment(range_val); + xmlFree(range_val); if (!rep->init_section) { xmlFree(initialization_val); - xmlFree(range_val); return AVERROR(ENOMEM); } rep->init_section->url = get_content_url(baseurl_nodes, 4, @@ -633,24 +620,20 @@ rep_id_val, rep_bandwidth_val, initialization_val); - + xmlFree(initialization_val); if (!rep->init_section->url) { - av_free(rep->init_section); - xmlFree(initialization_val); - xmlFree(range_val); + av_freep(&rep->init_section); return AVERROR(ENOMEM); } - xmlFree(initialization_val); - xmlFree(range_val); } - } else if (!av_strcasecmp(fragmenturl_node->name, (const char *)"SegmentURL")) { + } else if (!av_strcasecmp(fragmenturl_node->name, "SegmentURL")) { media_val = xmlGetProp(fragmenturl_node, "media"); range_val = xmlGetProp(fragmenturl_node, "mediaRange"); if (media_val || range_val) { struct fragment *seg = get_Fragment(range_val); + xmlFree(range_val); if (!seg) { xmlFree(media_val); - xmlFree(range_val); return AVERROR(ENOMEM); } seg->url = get_content_url(baseurl_nodes, 4, @@ -658,15 +641,16 @@ rep_id_val, rep_bandwidth_val, media_val); + xmlFree(media_val); if (!seg->url) { av_free(seg); - xmlFree(media_val); - xmlFree(range_val); return AVERROR(ENOMEM); } - dynarray_add(&rep->fragments, &rep->n_fragments, seg); - xmlFree(media_val); - xmlFree(range_val); + err = av_dynarray_add_nofree(&rep->fragments, &rep->n_fragments, seg); + if (err < 0) { + free_fragment(&seg); + return err; + } } } @@ -678,8 +662,9 @@ { xmlAttrPtr attr = NULL; char *val = NULL; + int err; - if (!av_strcasecmp(fragment_timeline_node->name, (const char *)"S")) { + if (!av_strcasecmp(fragment_timeline_node->name, "S")) { struct timeline *tml = av_mallocz(sizeof(struct timeline)); if (!tml) { return AVERROR(ENOMEM); @@ -693,17 +678,21 @@ continue; } - if (!av_strcasecmp(attr->name, (const char *)"t")) { + if (!av_strcasecmp(attr->name, "t")) { tml->starttime = (int64_t)strtoll(val, NULL, 10); - } else if (!av_strcasecmp(attr->name, (const char *)"r")) { + } else if (!av_strcasecmp(attr->name, "r")) { tml->repeat =(int64_t) strtoll(val, NULL, 10); - } else if (!av_strcasecmp(attr->name, (const char *)"d")) { + } else if (!av_strcasecmp(attr->name, "d")) { tml->duration = (int64_t)strtoll(val, NULL, 10); } attr = attr->next; xmlFree(val); } - dynarray_add(&rep->timelines, &rep->n_timelines, tml); + err = av_dynarray_add_nofree(&rep->timelines, &rep->n_timelines, tml); + if (err < 0) { + av_free(tml); + return err; + } } return 0; @@ -784,7 +773,7 @@ size = strlen(root_url); isRootHttp = ishttp(root_url); - if (root_url[size - 1] != token) { + if (size > 0 && root_url[size - 1] != token) { av_strlcat(root_url, "/", size + 2); size += 2; } @@ -794,12 +783,22 @@ continue; } text = xmlNodeGetContent(baseurl_nodes[i]); - if (text) { + if (text && !av_strstart(text, "/", NULL)) { memset(tmp_str, 0, strlen(tmp_str)); if (!ishttp(text) && isRootHttp) { av_strlcpy(tmp_str, root_url, size + 1); } start = (text[0] == token); + if (start && av_stristr(tmp_str, text)) { + char *p = tmp_str; + if (!av_strncasecmp(tmp_str, "http://", 7)) { + p += 7; + } else if (!av_strncasecmp(tmp_str, "https://", 8)) { + p += 8; + } + p = strchr(p, '/'); + memset(p + 1, 0, strlen(p)); + } av_strlcat(tmp_str, text + start, tmp_max_url_size); xmlNodeSetContent(baseurl_nodes[i], tmp_str); updated = 1; @@ -832,9 +831,6 @@ xmlNodePtr adaptionset_supplementalproperty_node) { int32_t ret = 0; - int32_t subtitle_rep_idx = 0; - int32_t audio_rep_idx = 0; - int32_t video_rep_idx = 0; DASHContext *c = s->priv_data; struct representation *rep = NULL; struct fragment *seg = NULL; @@ -844,18 +840,10 @@ xmlNodePtr segmentlists_tab[3]; xmlNodePtr fragment_timeline_node = NULL; xmlNodePtr fragment_templates_tab[5]; - char *duration_val = NULL; - char *presentation_timeoffset_val = NULL; - char *startnumber_val = NULL; - char *timescale_val = NULL; - char *initialization_val = NULL; - char *media_val = NULL; char *val = NULL; xmlNodePtr baseurl_nodes[4]; xmlNodePtr representation_node = node; - char *rep_id_val = xmlGetProp(representation_node, "id"); - char *rep_bandwidth_val = xmlGetProp(representation_node, "bandwidth"); - char *rep_framerate_val = xmlGetProp(representation_node, "frameRate"); + char *rep_bandwidth_val; enum AVMediaType type = AVMEDIA_TYPE_UNKNOWN; // try get information from representation @@ -867,236 +855,253 @@ // try get information from adaption set if (type == AVMEDIA_TYPE_UNKNOWN) type = get_content_type(adaptionset_node); - if (type == AVMEDIA_TYPE_UNKNOWN) { + if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO && + type != AVMEDIA_TYPE_SUBTITLE) { av_log(s, AV_LOG_VERBOSE, "Parsing '%s' - skipp not supported representation type\n", url); - } else if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_SUBTITLE) { - // convert selected representation to our internal struct - rep = av_mallocz(sizeof(struct representation)); - if (!rep) { - ret = AVERROR(ENOMEM); - goto end; - } - representation_segmenttemplate_node = find_child_node_by_name(representation_node, "SegmentTemplate"); - representation_baseurl_node = find_child_node_by_name(representation_node, "BaseURL"); - representation_segmentlist_node = find_child_node_by_name(representation_node, "SegmentList"); - - baseurl_nodes[0] = mpd_baseurl_node; - baseurl_nodes[1] = period_baseurl_node; - baseurl_nodes[2] = adaptionset_baseurl_node; - baseurl_nodes[3] = representation_baseurl_node; - - ret = resolve_content_path(s, url, &c->max_url_size, baseurl_nodes, 4); - c->max_url_size = aligned(c->max_url_size - + (rep_id_val ? strlen(rep_id_val) : 0) - + (rep_bandwidth_val ? strlen(rep_bandwidth_val) : 0)); - if (ret == AVERROR(ENOMEM) || ret == 0) { - goto end; + return 0; + } + + // convert selected representation to our internal struct + rep = av_mallocz(sizeof(struct representation)); + if (!rep) + return AVERROR(ENOMEM); + if (c->adaptionset_lang) { + rep->lang = av_strdup(c->adaptionset_lang); + if (!rep->lang) { + av_log(s, AV_LOG_ERROR, "alloc language memory failure\n"); + av_freep(&rep); + return AVERROR(ENOMEM); } - if (representation_segmenttemplate_node || fragment_template_node || period_segmenttemplate_node) { - fragment_timeline_node = NULL; - fragment_templates_tab[0] = representation_segmenttemplate_node; - fragment_templates_tab[1] = adaptionset_segmentlist_node; - fragment_templates_tab[2] = fragment_template_node; - fragment_templates_tab[3] = period_segmenttemplate_node; - fragment_templates_tab[4] = period_segmentlist_node; - - presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "presentationTimeOffset"); - duration_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "duration"); - startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "startNumber"); - timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "timescale"); - initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "initialization"); - media_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "media"); - - if (initialization_val) { - rep->init_section = av_mallocz(sizeof(struct fragment)); - if (!rep->init_section) { - av_free(rep); - ret = AVERROR(ENOMEM); - goto end; - } - c->max_url_size = aligned(c->max_url_size + strlen(initialization_val)); - rep->init_section->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, initialization_val); - if (!rep->init_section->url) { - av_free(rep->init_section); - av_free(rep); - ret = AVERROR(ENOMEM); - goto end; - } - rep->init_section->size = -1; - xmlFree(initialization_val); - } + } + rep->parent = s; + representation_segmenttemplate_node = find_child_node_by_name(representation_node, "SegmentTemplate"); + representation_baseurl_node = find_child_node_by_name(representation_node, "BaseURL"); + representation_segmentlist_node = find_child_node_by_name(representation_node, "SegmentList"); + rep_bandwidth_val = xmlGetProp(representation_node, "bandwidth"); + val = xmlGetProp(representation_node, "id"); + if (val) { + rep->id = av_strdup(val); + xmlFree(val); + if (!rep->id) + goto enomem; + } - if (media_val) { - c->max_url_size = aligned(c->max_url_size + strlen(media_val)); - rep->url_template = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, media_val); - xmlFree(media_val); + baseurl_nodes[0] = mpd_baseurl_node; + baseurl_nodes[1] = period_baseurl_node; + baseurl_nodes[2] = adaptionset_baseurl_node; + baseurl_nodes[3] = representation_baseurl_node; + + ret = resolve_content_path(s, url, &c->max_url_size, baseurl_nodes, 4); + c->max_url_size = aligned(c->max_url_size + + (rep->id ? strlen(rep->id) : 0) + + (rep_bandwidth_val ? strlen(rep_bandwidth_val) : 0)); + if (ret == AVERROR(ENOMEM) || ret == 0) + goto free; + if (representation_segmenttemplate_node || fragment_template_node || period_segmenttemplate_node) { + fragment_timeline_node = NULL; + fragment_templates_tab[0] = representation_segmenttemplate_node; + fragment_templates_tab[1] = adaptionset_segmentlist_node; + fragment_templates_tab[2] = fragment_template_node; + fragment_templates_tab[3] = period_segmenttemplate_node; + fragment_templates_tab[4] = period_segmentlist_node; + + val = get_val_from_nodes_tab(fragment_templates_tab, 4, "initialization"); + if (val) { + rep->init_section = av_mallocz(sizeof(struct fragment)); + if (!rep->init_section) { + xmlFree(val); + goto enomem; } - - if (presentation_timeoffset_val) { - rep->presentation_timeoffset = (int64_t) strtoll(presentation_timeoffset_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->presentation_timeoffset = [%"PRId64"]\n", rep->presentation_timeoffset); - xmlFree(presentation_timeoffset_val); - } - if (duration_val) { - rep->fragment_duration = (int64_t) strtoll(duration_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->fragment_duration = [%"PRId64"]\n", rep->fragment_duration); - xmlFree(duration_val); - } - if (timescale_val) { - rep->fragment_timescale = (int64_t) strtoll(timescale_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->fragment_timescale = [%"PRId64"]\n", rep->fragment_timescale); - xmlFree(timescale_val); - } - if (startnumber_val) { - rep->first_seq_no = (int64_t) strtoll(startnumber_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->first_seq_no = [%"PRId64"]\n", rep->first_seq_no); - xmlFree(startnumber_val); - } - if (adaptionset_supplementalproperty_node) { - if (!av_strcasecmp(xmlGetProp(adaptionset_supplementalproperty_node,"schemeIdUri"), "http://dashif.org/guidelines/last-segment-number")) { - val = xmlGetProp(adaptionset_supplementalproperty_node,"value"); - if (!val) { - av_log(s, AV_LOG_ERROR, "Missing value attribute in adaptionset_supplementalproperty_node\n"); - } else { - rep->last_seq_no =(int64_t) strtoll(val, NULL, 10) - 1; - xmlFree(val); - } + c->max_url_size = aligned(c->max_url_size + strlen(val)); + rep->init_section->url = get_content_url(baseurl_nodes, 4, + c->max_url_size, rep->id, + rep_bandwidth_val, val); + xmlFree(val); + if (!rep->init_section->url) + goto enomem; + rep->init_section->size = -1; + } + val = get_val_from_nodes_tab(fragment_templates_tab, 4, "media"); + if (val) { + c->max_url_size = aligned(c->max_url_size + strlen(val)); + rep->url_template = get_content_url(baseurl_nodes, 4, + c->max_url_size, rep->id, + rep_bandwidth_val, val); + xmlFree(val); + } + val = get_val_from_nodes_tab(fragment_templates_tab, 4, "presentationTimeOffset"); + if (val) { + rep->presentation_timeoffset = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->presentation_timeoffset = [%"PRId64"]\n", rep->presentation_timeoffset); + xmlFree(val); + } + val = get_val_from_nodes_tab(fragment_templates_tab, 4, "duration"); + if (val) { + rep->fragment_duration = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->fragment_duration = [%"PRId64"]\n", rep->fragment_duration); + xmlFree(val); + } + val = get_val_from_nodes_tab(fragment_templates_tab, 4, "timescale"); + if (val) { + rep->fragment_timescale = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->fragment_timescale = [%"PRId64"]\n", rep->fragment_timescale); + xmlFree(val); + } + val = get_val_from_nodes_tab(fragment_templates_tab, 4, "startNumber"); + if (val) { + rep->start_number = rep->first_seq_no = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->first_seq_no = [%"PRId64"]\n", rep->first_seq_no); + xmlFree(val); + } + if (adaptionset_supplementalproperty_node) { + if (!av_strcasecmp(xmlGetProp(adaptionset_supplementalproperty_node,"schemeIdUri"), "http://dashif.org/guidelines/last-segment-number")) { + val = xmlGetProp(adaptionset_supplementalproperty_node,"value"); + if (!val) { + av_log(s, AV_LOG_ERROR, "Missing value attribute in adaptionset_supplementalproperty_node\n"); + } else { + rep->last_seq_no =(int64_t) strtoll(val, NULL, 10) - 1; + xmlFree(val); } } + } - fragment_timeline_node = find_child_node_by_name(representation_segmenttemplate_node, "SegmentTimeline"); + fragment_timeline_node = find_child_node_by_name(representation_segmenttemplate_node, "SegmentTimeline"); - if (!fragment_timeline_node) - fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline"); - if (!fragment_timeline_node) - fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline"); - if (!fragment_timeline_node) - fragment_timeline_node = find_child_node_by_name(period_segmentlist_node, "SegmentTimeline"); - if (fragment_timeline_node) { - fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); - while (fragment_timeline_node) { - ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node); - if (ret < 0) { - return ret; - } - fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node); - } - } - } else if (representation_baseurl_node && !representation_segmentlist_node) { - seg = av_mallocz(sizeof(struct fragment)); - if (!seg) { - ret = AVERROR(ENOMEM); - goto end; - } - seg->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, NULL); - if (!seg->url) { - av_free(seg); - ret = AVERROR(ENOMEM); - goto end; - } - seg->size = -1; - dynarray_add(&rep->fragments, &rep->n_fragments, seg); - } else if (representation_segmentlist_node) { - // TODO: https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html - // http://www-itec.uni-klu.ac.at/dash/ddash/mpdGenerator.php?fragmentlength=15&type=full - xmlNodePtr fragmenturl_node = NULL; - segmentlists_tab[0] = representation_segmentlist_node; - segmentlists_tab[1] = adaptionset_segmentlist_node; - segmentlists_tab[2] = period_segmentlist_node; - - duration_val = get_val_from_nodes_tab(segmentlists_tab, 3, "duration"); - timescale_val = get_val_from_nodes_tab(segmentlists_tab, 3, "timescale"); - if (duration_val) { - rep->fragment_duration = (int64_t) strtoll(duration_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->fragment_duration = [%"PRId64"]\n", rep->fragment_duration); - xmlFree(duration_val); - } - if (timescale_val) { - rep->fragment_timescale = (int64_t) strtoll(timescale_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->fragment_timescale = [%"PRId64"]\n", rep->fragment_timescale); - xmlFree(timescale_val); - } - fragmenturl_node = xmlFirstElementChild(representation_segmentlist_node); - while (fragmenturl_node) { - ret = parse_manifest_segmenturlnode(s, rep, fragmenturl_node, - baseurl_nodes, - rep_id_val, - rep_bandwidth_val); - if (ret < 0) { - return ret; - } - fragmenturl_node = xmlNextElementSibling(fragmenturl_node); + if (!fragment_timeline_node) + fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline"); + if (!fragment_timeline_node) + fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline"); + if (!fragment_timeline_node) + fragment_timeline_node = find_child_node_by_name(period_segmentlist_node, "SegmentTimeline"); + if (fragment_timeline_node) { + fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); + while (fragment_timeline_node) { + ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node); + if (ret < 0) + goto free; + fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node); } + } + } else if (representation_baseurl_node && !representation_segmentlist_node) { + seg = av_mallocz(sizeof(struct fragment)); + if (!seg) + goto enomem; + ret = av_dynarray_add_nofree(&rep->fragments, &rep->n_fragments, seg); + if (ret < 0) { + av_free(seg); + goto free; + } + seg->url = get_content_url(baseurl_nodes, 4, c->max_url_size, + rep->id, rep_bandwidth_val, NULL); + if (!seg->url) + goto enomem; + seg->size = -1; + } else if (representation_segmentlist_node) { + // TODO: https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html + // http://www-itec.uni-klu.ac.at/dash/ddash/mpdGenerator.php?fragmentlength=15&type=full + xmlNodePtr fragmenturl_node = NULL; + segmentlists_tab[0] = representation_segmentlist_node; + segmentlists_tab[1] = adaptionset_segmentlist_node; + segmentlists_tab[2] = period_segmentlist_node; + + val = get_val_from_nodes_tab(segmentlists_tab, 3, "duration"); + if (val) { + rep->fragment_duration = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->fragment_duration = [%"PRId64"]\n", rep->fragment_duration); + xmlFree(val); + } + val = get_val_from_nodes_tab(segmentlists_tab, 3, "timescale"); + if (val) { + rep->fragment_timescale = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->fragment_timescale = [%"PRId64"]\n", rep->fragment_timescale); + xmlFree(val); + } + val = get_val_from_nodes_tab(segmentlists_tab, 3, "startNumber"); + if (val) { + rep->start_number = rep->first_seq_no = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->first_seq_no = [%"PRId64"]\n", rep->first_seq_no); + xmlFree(val); + } - fragment_timeline_node = find_child_node_by_name(representation_segmenttemplate_node, "SegmentTimeline"); - - if (!fragment_timeline_node) - fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline"); - if (!fragment_timeline_node) - fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline"); - if (!fragment_timeline_node) - fragment_timeline_node = find_child_node_by_name(period_segmentlist_node, "SegmentTimeline"); - if (fragment_timeline_node) { - fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); - while (fragment_timeline_node) { - ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node); - if (ret < 0) { - return ret; - } - fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node); - } - } - } else { - free_representation(rep); - rep = NULL; - av_log(s, AV_LOG_ERROR, "Unknown format of Representation node id[%s] \n", (const char *)rep_id_val); + fragmenturl_node = xmlFirstElementChild(representation_segmentlist_node); + while (fragmenturl_node) { + ret = parse_manifest_segmenturlnode(s, rep, fragmenturl_node, + baseurl_nodes, rep->id, + rep_bandwidth_val); + if (ret < 0) + goto free; + fragmenturl_node = xmlNextElementSibling(fragmenturl_node); } - if (rep) { - if (rep->fragment_duration > 0 && !rep->fragment_timescale) - rep->fragment_timescale = 1; - rep->bandwidth = rep_bandwidth_val ? atoi(rep_bandwidth_val) : 0; - strncpy(rep->id, rep_id_val ? rep_id_val : "", sizeof(rep->id)); - rep->framerate = av_make_q(0, 0); - if (type == AVMEDIA_TYPE_VIDEO && rep_framerate_val) { - ret = av_parse_video_rate(&rep->framerate, rep_framerate_val); + fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline"); + if (!fragment_timeline_node) + fragment_timeline_node = find_child_node_by_name(period_segmentlist_node, "SegmentTimeline"); + if (fragment_timeline_node) { + fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); + while (fragment_timeline_node) { + ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node); if (ret < 0) - av_log(s, AV_LOG_VERBOSE, "Ignoring invalid frame rate '%s'\n", rep_framerate_val); + goto free; + fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node); } + } + } else { + av_log(s, AV_LOG_ERROR, "Unknown format of Representation node id '%s' \n", + rep->id ? rep->id : ""); + goto free; + } - switch (type) { - case AVMEDIA_TYPE_VIDEO: - rep->rep_idx = video_rep_idx; - dynarray_add(&c->videos, &c->n_videos, rep); - break; - case AVMEDIA_TYPE_AUDIO: - rep->rep_idx = audio_rep_idx; - dynarray_add(&c->audios, &c->n_audios, rep); - break; - case AVMEDIA_TYPE_SUBTITLE: - rep->rep_idx = subtitle_rep_idx; - dynarray_add(&c->subtitles, &c->n_subtitles, rep); - break; - default: - av_log(s, AV_LOG_WARNING, "Unsupported the stream type %d\n", type); - break; - } + if (rep->fragment_duration > 0 && !rep->fragment_timescale) + rep->fragment_timescale = 1; + rep->bandwidth = rep_bandwidth_val ? atoi(rep_bandwidth_val) : 0; + rep->framerate = av_make_q(0, 0); + if (type == AVMEDIA_TYPE_VIDEO) { + char *rep_framerate_val = xmlGetProp(representation_node, "frameRate"); + if (rep_framerate_val) { + ret = av_parse_video_rate(&rep->framerate, rep_framerate_val); + if (ret < 0) + av_log(s, AV_LOG_VERBOSE, "Ignoring invalid frame rate '%s'\n", rep_framerate_val); + xmlFree(rep_framerate_val); } } - video_rep_idx += type == AVMEDIA_TYPE_VIDEO; - audio_rep_idx += type == AVMEDIA_TYPE_AUDIO; - subtitle_rep_idx += type == AVMEDIA_TYPE_SUBTITLE; + switch (type) { + case AVMEDIA_TYPE_VIDEO: + ret = av_dynarray_add_nofree(&c->videos, &c->n_videos, rep); + break; + case AVMEDIA_TYPE_AUDIO: + ret = av_dynarray_add_nofree(&c->audios, &c->n_audios, rep); + break; + case AVMEDIA_TYPE_SUBTITLE: + ret = av_dynarray_add_nofree(&c->subtitles, &c->n_subtitles, rep); + break; + } + if (ret < 0) + goto free; end: - if (rep_id_val) - xmlFree(rep_id_val); if (rep_bandwidth_val) xmlFree(rep_bandwidth_val); - if (rep_framerate_val) - xmlFree(rep_framerate_val); return ret; +enomem: + ret = AVERROR(ENOMEM); +free: + free_representation(rep); + goto end; +} + +static int parse_manifest_adaptationset_attr(AVFormatContext *s, xmlNodePtr adaptionset_node) +{ + DASHContext *c = s->priv_data; + + if (!adaptionset_node) { + av_log(s, AV_LOG_WARNING, "Cannot get AdaptionSet\n"); + return AVERROR(EINVAL); + } + c->adaptionset_lang = xmlGetProp(adaptionset_node, "lang"); + + return 0; } static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, @@ -1114,33 +1119,24 @@ xmlNodePtr adaptionset_segmentlist_node = NULL; xmlNodePtr adaptionset_supplementalproperty_node = NULL; xmlNodePtr node = NULL; - c->adaptionset_contenttype_val = xmlGetProp(adaptionset_node, "contentType"); - c->adaptionset_par_val = xmlGetProp(adaptionset_node, "par"); - c->adaptionset_lang_val = xmlGetProp(adaptionset_node, "lang"); - c->adaptionset_minbw_val = xmlGetProp(adaptionset_node, "minBandwidth"); - c->adaptionset_maxbw_val = xmlGetProp(adaptionset_node, "maxBandwidth"); - c->adaptionset_minwidth_val = xmlGetProp(adaptionset_node, "minWidth"); - c->adaptionset_maxwidth_val = xmlGetProp(adaptionset_node, "maxWidth"); - c->adaptionset_minheight_val = xmlGetProp(adaptionset_node, "minHeight"); - c->adaptionset_maxheight_val = xmlGetProp(adaptionset_node, "maxHeight"); - c->adaptionset_minframerate_val = xmlGetProp(adaptionset_node, "minFrameRate"); - c->adaptionset_maxframerate_val = xmlGetProp(adaptionset_node, "maxFrameRate"); - c->adaptionset_segmentalignment_val = xmlGetProp(adaptionset_node, "segmentAlignment"); - c->adaptionset_bitstreamswitching_val = xmlGetProp(adaptionset_node, "bitstreamSwitching"); + + ret = parse_manifest_adaptationset_attr(s, adaptionset_node); + if (ret < 0) + return ret; node = xmlFirstElementChild(adaptionset_node); while (node) { - if (!av_strcasecmp(node->name, (const char *)"SegmentTemplate")) { + if (!av_strcasecmp(node->name, "SegmentTemplate")) { fragment_template_node = node; - } else if (!av_strcasecmp(node->name, (const char *)"ContentComponent")) { + } else if (!av_strcasecmp(node->name, "ContentComponent")) { content_component_node = node; - } else if (!av_strcasecmp(node->name, (const char *)"BaseURL")) { + } else if (!av_strcasecmp(node->name, "BaseURL")) { adaptionset_baseurl_node = node; - } else if (!av_strcasecmp(node->name, (const char *)"SegmentList")) { + } else if (!av_strcasecmp(node->name, "SegmentList")) { adaptionset_segmentlist_node = node; - } else if (!av_strcasecmp(node->name, (const char *)"SupplementalProperty")) { + } else if (!av_strcasecmp(node->name, "SupplementalProperty")) { adaptionset_supplementalproperty_node = node; - } else if (!av_strcasecmp(node->name, (const char *)"Representation")) { + } else if (!av_strcasecmp(node->name, "Representation")) { ret = parse_manifest_representation(s, url, node, adaptionset_node, mpd_baseurl_node, @@ -1152,13 +1148,16 @@ adaptionset_baseurl_node, adaptionset_segmentlist_node, adaptionset_supplementalproperty_node); - if (ret < 0) { - return ret; - } + if (ret < 0) + goto err; } node = xmlNextElementSibling(node); } - return 0; + +err: + xmlFree(c->adaptionset_lang); + c->adaptionset_lang = NULL; + return ret; } static int parse_programinformation(AVFormatContext *s, xmlNodePtr node) @@ -1185,6 +1184,7 @@ } node = xmlNextElementSibling(node); xmlFree(val); + val = NULL; } return 0; } @@ -1194,9 +1194,8 @@ DASHContext *c = s->priv_data; int ret = 0; int close_in = 0; - uint8_t *new_url = NULL; int64_t filesize = 0; - char *buffer = NULL; + AVBPrint buf; AVDictionary *opts = NULL; xmlDoc *doc = NULL; xmlNodePtr root_element = NULL; @@ -1223,31 +1222,29 @@ return ret; } - if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, &new_url) >= 0) { - c->base_url = av_strdup(new_url); - } else { + 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); - if (filesize <= 0) { - filesize = 8 * 1024; - } + filesize = filesize > 0 ? filesize : DEFAULT_MANIFEST_SIZE; - buffer = av_mallocz(filesize); - if (!buffer) { - av_free(c->base_url); - return AVERROR(ENOMEM); + if (filesize > MAX_BPRINT_READ_SIZE) { + av_log(s, AV_LOG_ERROR, "Manifest too large: %"PRId64"\n", filesize); + return AVERROR_INVALIDDATA; } - filesize = avio_read(in, buffer, filesize); - if (filesize <= 0) { - av_log(s, AV_LOG_ERROR, "Unable to read to offset '%s'\n", url); - ret = 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) { + 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(buffer, filesize, c->base_url, NULL, 0); + doc = xmlReadMemory(buf.str, filesize, c->base_url, NULL, 0); root_element = xmlDocGetRootElement(doc); node = root_element; @@ -1258,7 +1255,7 @@ } if (node->type != XML_ELEMENT_NODE || - av_strcasecmp(node->name, (const char *)"MPD")) { + av_strcasecmp(node->name, "MPD")) { ret = AVERROR_INVALIDDATA; av_log(s, AV_LOG_ERROR, "Unable to parse '%s' - wrong root node name[%s] type[%d]\n", url, node->name, (int)node->type); goto cleanup; @@ -1270,7 +1267,7 @@ ret = AVERROR_INVALIDDATA; goto cleanup; } - if (!av_strcasecmp(val, (const char *)"dynamic")) + if (!av_strcasecmp(val, "dynamic")) c->is_live = 1; xmlFree(val); @@ -1278,29 +1275,29 @@ while (attr) { val = xmlGetProp(node, attr->name); - if (!av_strcasecmp(attr->name, (const char *)"availabilityStartTime")) { - c->availability_start_time = get_utc_date_time_insec(s, (const char *)val); + if (!av_strcasecmp(attr->name, "availabilityStartTime")) { + c->availability_start_time = get_utc_date_time_insec(s, val); av_log(s, AV_LOG_TRACE, "c->availability_start_time = [%"PRId64"]\n", c->availability_start_time); - } else if (!av_strcasecmp(attr->name, (const char *)"availabilityEndTime")) { - c->availability_end_time = get_utc_date_time_insec(s, (const char *)val); + } else if (!av_strcasecmp(attr->name, "availabilityEndTime")) { + c->availability_end_time = get_utc_date_time_insec(s, val); av_log(s, AV_LOG_TRACE, "c->availability_end_time = [%"PRId64"]\n", c->availability_end_time); - } else if (!av_strcasecmp(attr->name, (const char *)"publishTime")) { - c->publish_time = get_utc_date_time_insec(s, (const char *)val); + } else if (!av_strcasecmp(attr->name, "publishTime")) { + c->publish_time = get_utc_date_time_insec(s, val); av_log(s, AV_LOG_TRACE, "c->publish_time = [%"PRId64"]\n", c->publish_time); - } else if (!av_strcasecmp(attr->name, (const char *)"minimumUpdatePeriod")) { - c->minimum_update_period = get_duration_insec(s, (const char *)val); + } else if (!av_strcasecmp(attr->name, "minimumUpdatePeriod")) { + c->minimum_update_period = get_duration_insec(s, val); av_log(s, AV_LOG_TRACE, "c->minimum_update_period = [%"PRId64"]\n", c->minimum_update_period); - } else if (!av_strcasecmp(attr->name, (const char *)"timeShiftBufferDepth")) { - c->time_shift_buffer_depth = get_duration_insec(s, (const char *)val); + } else if (!av_strcasecmp(attr->name, "timeShiftBufferDepth")) { + c->time_shift_buffer_depth = get_duration_insec(s, val); av_log(s, AV_LOG_TRACE, "c->time_shift_buffer_depth = [%"PRId64"]\n", c->time_shift_buffer_depth); - } else if (!av_strcasecmp(attr->name, (const char *)"minBufferTime")) { - c->min_buffer_time = get_duration_insec(s, (const char *)val); + } else if (!av_strcasecmp(attr->name, "minBufferTime")) { + c->min_buffer_time = get_duration_insec(s, val); av_log(s, AV_LOG_TRACE, "c->min_buffer_time = [%"PRId64"]\n", c->min_buffer_time); - } else if (!av_strcasecmp(attr->name, (const char *)"suggestedPresentationDelay")) { - c->suggested_presentation_delay = get_duration_insec(s, (const char *)val); + } else if (!av_strcasecmp(attr->name, "suggestedPresentationDelay")) { + c->suggested_presentation_delay = get_duration_insec(s, val); av_log(s, AV_LOG_TRACE, "c->suggested_presentation_delay = [%"PRId64"]\n", c->suggested_presentation_delay); - } else if (!av_strcasecmp(attr->name, (const char *)"mediaPresentationDuration")) { - c->media_presentation_duration = get_duration_insec(s, (const char *)val); + } else if (!av_strcasecmp(attr->name, "mediaPresentationDuration")) { + c->media_presentation_duration = get_duration_insec(s, val); av_log(s, AV_LOG_TRACE, "c->media_presentation_duration = [%"PRId64"]\n", c->media_presentation_duration); } attr = attr->next; @@ -1317,16 +1314,16 @@ // at now we can handle only one period, with the longest duration node = xmlFirstElementChild(node); while (node) { - if (!av_strcasecmp(node->name, (const char *)"Period")) { + if (!av_strcasecmp(node->name, "Period")) { period_duration_sec = 0; period_start_sec = 0; attr = node->properties; while (attr) { val = xmlGetProp(node, attr->name); - if (!av_strcasecmp(attr->name, (const char *)"duration")) { - period_duration_sec = get_duration_insec(s, (const char *)val); - } else if (!av_strcasecmp(attr->name, (const char *)"start")) { - period_start_sec = get_duration_insec(s, (const char *)val); + if (!av_strcasecmp(attr->name, "duration")) { + period_duration_sec = get_duration_insec(s, val); + } else if (!av_strcasecmp(attr->name, "start")) { + period_start_sec = get_duration_insec(s, val); } attr = attr->next; xmlFree(val); @@ -1351,13 +1348,13 @@ adaptionset_node = xmlFirstElementChild(period_node); while (adaptionset_node) { - if (!av_strcasecmp(adaptionset_node->name, (const char *)"BaseURL")) { + if (!av_strcasecmp(adaptionset_node->name, "BaseURL")) { period_baseurl_node = adaptionset_node; - } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"SegmentTemplate")) { + } else if (!av_strcasecmp(adaptionset_node->name, "SegmentTemplate")) { period_segmenttemplate_node = adaptionset_node; - } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"SegmentList")) { + } else if (!av_strcasecmp(adaptionset_node->name, "SegmentList")) { period_segmentlist_node = adaptionset_node; - } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"AdaptationSet")) { + } else if (!av_strcasecmp(adaptionset_node->name, "AdaptationSet")) { parse_manifest_adaptationset(s, url, adaptionset_node, mpd_baseurl_node, period_baseurl_node, period_segmenttemplate_node, period_segmentlist_node); } adaptionset_node = xmlNextElementSibling(adaptionset_node); @@ -1369,8 +1366,7 @@ xmlFreeNode(mpd_baseurl_node); } - av_free(new_url); - av_free(buffer); + av_bprint_finalize(&buf, NULL); if (close_in) { avio_close(in); } @@ -1623,10 +1619,10 @@ refresh_manifest(pls->parent); } if (pls->cur_seq_no <= min_seq_no) { - av_log(pls->parent, AV_LOG_VERBOSE, "old fragment: cur[%"PRId64"] min[%"PRId64"] max[%"PRId64"], playlist %d\n", (int64_t)pls->cur_seq_no, min_seq_no, max_seq_no, (int)pls->rep_idx); + av_log(pls->parent, AV_LOG_VERBOSE, "old fragment: cur[%"PRId64"] min[%"PRId64"] max[%"PRId64"]\n", (int64_t)pls->cur_seq_no, min_seq_no, max_seq_no); pls->cur_seq_no = calc_cur_seg_no(pls->parent, pls); } else if (pls->cur_seq_no > max_seq_no) { - av_log(pls->parent, AV_LOG_VERBOSE, "new fragment: min[%"PRId64"] max[%"PRId64"], playlist %d\n", min_seq_no, max_seq_no, (int)pls->rep_idx); + av_log(pls->parent, AV_LOG_VERBOSE, "new fragment: min[%"PRId64"] max[%"PRId64"]\n", min_seq_no, max_seq_no); } seg = av_mallocz(sizeof(struct fragment)); if (!seg) { @@ -1639,8 +1635,15 @@ } } if (seg) { - char *tmpfilename= av_mallocz(c->max_url_size); + char *tmpfilename; + if (!pls->url_template) { + av_log(pls->parent, AV_LOG_ERROR, "Cannot get fragment, missing template URL\n"); + av_free(seg); + return NULL; + } + tmpfilename = av_mallocz(c->max_url_size); if (!tmpfilename) { + av_free(seg); return NULL; } ff_dash_fill_tmpl_params(tmpfilename, c->max_url_size, pls->url_template, 0, pls->cur_seq_no, 0, get_segment_start_time_based_on_timeline(pls, pls->cur_seq_no)); @@ -1651,6 +1654,7 @@ if (!seg->url) { av_log(pls->parent, AV_LOG_ERROR, "Cannot resolve template url '%s'\n", pls->url_template); av_free(tmpfilename); + av_free(seg); return NULL; } } @@ -1697,9 +1701,9 @@ } ff_make_absolute_url(url, c->max_url_size, c->base_url, seg->url); - av_log(pls->parent, AV_LOG_VERBOSE, "DASH request for url '%s', offset %"PRId64", playlist %d\n", - url, seg->url_offset, pls->rep_idx); - ret = open_url(pls->parent, &pls->input, url, c->avio_opts, opts, NULL); + av_log(pls->parent, AV_LOG_VERBOSE, "DASH request for url '%s', offset %"PRId64"\n", + url, seg->url_offset); + ret = open_url(pls->parent, &pls->input, url, &c->avio_opts, opts, NULL); cleanup: av_free(url); @@ -1723,8 +1727,7 @@ ret = open_input(c, pls, pls->init_section); if (ret < 0) { av_log(pls->parent, AV_LOG_WARNING, - "Failed to open an initialization section in playlist %d\n", - pls->rep_idx); + "Failed to open an initialization section\n"); return ret; } @@ -1792,7 +1795,7 @@ ret = AVERROR_EXIT; goto end; } - av_log(v->parent, AV_LOG_WARNING, "Failed to open fragment of playlist %d\n", v->rep_idx); + av_log(v->parent, AV_LOG_WARNING, "Failed to open fragment of playlist\n"); v->cur_seq_no++; goto restart; } @@ -1833,7 +1836,7 @@ { DASHContext *c = s->priv_data; const char *opts[] = { - "headers", "user_agent", "cookies", "http_proxy", "referer", "rw_timeout", NULL }; + "headers", "user_agent", "cookies", "http_proxy", "referer", "rw_timeout", "icy", NULL }; const char **opt = opts; uint8_t *buf = NULL; int ret = 0; @@ -1842,10 +1845,8 @@ if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) { if (buf[0] != '\0') { ret = av_dict_set(&c->avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL); - if (ret < 0) { - av_freep(&buf); + if (ret < 0) return ret; - } } else { av_freep(&buf); } @@ -1873,7 +1874,6 @@ memset(&pls->pb, 0x00, sizeof(AVIOContext)); pls->ctx->pb = NULL; avformat_close_input(&pls->ctx); - pls->ctx = NULL; } static int reopen_demux_for_component(AVFormatContext *s, struct representation *pls) @@ -1905,22 +1905,20 @@ pls->ctx = NULL; goto fail; } - if (c->is_live) { - ffio_init_context(&pls->pb, avio_ctx_buffer , INITIAL_BUFFER_SIZE, 0, pls, read_data, NULL, NULL); - } else { - ffio_init_context(&pls->pb, avio_ctx_buffer , INITIAL_BUFFER_SIZE, 0, pls, read_data, NULL, seek_data); - } + ffio_init_context(&pls->pb, avio_ctx_buffer, INITIAL_BUFFER_SIZE, 0, + pls, read_data, NULL, c->is_live ? NULL : seek_data); pls->pb.seekable = 0; if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0) goto fail; pls->ctx->flags = AVFMT_FLAG_CUSTOM_IO; - pls->ctx->probesize = 1024 * 4; - pls->ctx->max_analyze_duration = 4 * AV_TIME_BASE; + pls->ctx->probesize = s->probesize > 0 ? s->probesize : 1024 * 4; + pls->ctx->max_analyze_duration = s->max_analyze_duration > 0 ? s->max_analyze_duration : 4 * AV_TIME_BASE; + pls->ctx->interrupt_callback = s->interrupt_callback; ret = av_probe_input_buffer(&pls->pb, &in_fmt, "", NULL, 0, 0); if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Error when loading first fragment, playlist %d\n", (int)pls->rep_idx); + av_log(s, AV_LOG_ERROR, "Error when loading first fragment of playlist\n"); avformat_free_context(pls->ctx); pls->ctx = NULL; goto fail; @@ -1976,6 +1974,20 @@ st->id = i; avcodec_parameters_copy(st->codecpar, ist->codecpar); avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den); + + // copy disposition + st->disposition = ist->disposition; + + // copy side data + for (int i = 0; i < ist->nb_side_data; i++) { + const AVPacketSideData *sd_src = &ist->side_data[i]; + uint8_t *dst_data; + + dst_data = av_stream_new_side_data(st, sd_src->type, sd_src->size); + if (!dst_data) + return AVERROR(ENOMEM); + memcpy(dst_data, sd_src->data, sd_src->size); + } } return 0; @@ -1998,7 +2010,12 @@ url_offset = first_init_section->url_offset; size = pls[0]->init_section->size; for (i=0;iinit_section->url,url) || pls[i]->init_section->url_offset != url_offset || pls[i]->init_section->size != size) { + if (!pls[i]->init_section) + continue; + + if (av_strcasecmp(pls[i]->init_section->url, url) || + pls[i]->init_section->url_offset != url_offset || + pls[i]->init_section->size != size) { return 0; } } @@ -2020,11 +2037,21 @@ return 0; } +static int dash_close(AVFormatContext *s); + +static void move_metadata(AVStream *st, const char *key, char **value) +{ + if (*value) { + av_dict_set(&st->metadata, key, *value, AV_DICT_DONT_STRDUP_VAL); + *value = NULL; + } +} static int dash_read_header(AVFormatContext *s) { DASHContext *c = s->priv_data; struct representation *rep; + AVProgram *program; int ret = 0; int stream_index = 0; int i; @@ -2083,11 +2110,11 @@ } if (c->n_subtitles) - c->is_init_section_common_audio = is_common_init_section_exist(c->subtitles, c->n_subtitles); + c->is_init_section_common_subtitle = is_common_init_section_exist(c->subtitles, c->n_subtitles); for (i = 0; i < c->n_subtitles; i++) { rep = c->subtitles[i]; - if (i > 0 && c->is_init_section_common_audio) { + if (i > 0 && c->is_init_section_common_subtitle) { ret = copy_init_section(rep, c->subtitles[0]); if (ret < 0) goto fail; @@ -2106,42 +2133,40 @@ } /* Create a program */ - if (!ret) { - AVProgram *program; - program = av_new_program(s, 0); - if (!program) { - goto fail; - } + program = av_new_program(s, 0); + if (!program) { + ret = AVERROR(ENOMEM); + goto fail; + } - for (i = 0; i < c->n_videos; i++) { - rep = c->videos[i]; - av_program_add_stream_index(s, 0, rep->stream_index); - rep->assoc_stream = s->streams[rep->stream_index]; - if (rep->bandwidth > 0) - av_dict_set_int(&rep->assoc_stream->metadata, "variant_bitrate", rep->bandwidth, 0); - if (rep->id[0]) - av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0); - } - for (i = 0; i < c->n_audios; i++) { - rep = c->audios[i]; - av_program_add_stream_index(s, 0, rep->stream_index); - rep->assoc_stream = s->streams[rep->stream_index]; - if (rep->bandwidth > 0) - av_dict_set_int(&rep->assoc_stream->metadata, "variant_bitrate", rep->bandwidth, 0); - if (rep->id[0]) - av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0); - } - for (i = 0; i < c->n_subtitles; i++) { - rep = c->subtitles[i]; - av_program_add_stream_index(s, 0, rep->stream_index); - rep->assoc_stream = s->streams[rep->stream_index]; - if (rep->id[0]) - av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0); - } + for (i = 0; i < c->n_videos; i++) { + rep = c->videos[i]; + av_program_add_stream_index(s, 0, rep->stream_index); + rep->assoc_stream = s->streams[rep->stream_index]; + if (rep->bandwidth > 0) + av_dict_set_int(&rep->assoc_stream->metadata, "variant_bitrate", rep->bandwidth, 0); + move_metadata(rep->assoc_stream, "id", &rep->id); + } + for (i = 0; i < c->n_audios; i++) { + rep = c->audios[i]; + av_program_add_stream_index(s, 0, rep->stream_index); + rep->assoc_stream = s->streams[rep->stream_index]; + if (rep->bandwidth > 0) + av_dict_set_int(&rep->assoc_stream->metadata, "variant_bitrate", rep->bandwidth, 0); + move_metadata(rep->assoc_stream, "id", &rep->id); + move_metadata(rep->assoc_stream, "language", &rep->lang); + } + for (i = 0; i < c->n_subtitles; i++) { + rep = c->subtitles[i]; + av_program_add_stream_index(s, 0, rep->stream_index); + rep->assoc_stream = s->streams[rep->stream_index]; + move_metadata(rep->assoc_stream, "id", &rep->id); + move_metadata(rep->assoc_stream, "language", &rep->lang); } return 0; fail: + dash_close(s); return ret; } @@ -2164,8 +2189,7 @@ av_log(s, AV_LOG_INFO, "Now receiving stream_index %d\n", pls->stream_index); } else if (!needed && pls->ctx) { close_demux_for_component(pls); - if (pls->input) - ff_format_io_close(pls->parent, &pls->input); + ff_format_io_close(pls->parent, &pls->input); av_log(s, AV_LOG_INFO, "No longer receiving stream_index %d\n", pls->stream_index); } } @@ -2226,8 +2250,7 @@ if (cur->is_restart_needed) { cur->cur_seg_offset = 0; cur->init_sec_buf_read_offset = 0; - if (cur->input) - ff_format_io_close(cur->parent, &cur->input); + ff_format_io_close(cur->parent, &cur->input); ret = reopen_demux_for_component(s, cur); cur->is_restart_needed = 0; } @@ -2240,6 +2263,7 @@ DASHContext *c = s->priv_data; free_audio_list(c); free_video_list(c); + free_subtitle_list(c); av_dict_free(&c->avio_opts); av_freep(&c->base_url); return 0; @@ -2252,8 +2276,8 @@ int j = 0; int64_t duration = 0; - av_log(pls->parent, AV_LOG_VERBOSE, "DASH seek pos[%"PRId64"ms], playlist %d%s\n", - seek_pos_msec, pls->rep_idx, dry_run ? " (dry)" : ""); + av_log(pls->parent, AV_LOG_VERBOSE, "DASH seek pos[%"PRId64"ms] %s\n", + seek_pos_msec, dry_run ? " (dry)" : ""); // single fragment mode if (pls->n_fragments == 1) { @@ -2265,15 +2289,14 @@ return av_seek_frame(pls->ctx, -1, seek_pos_msec * 1000, flags); } - if (pls->input) - ff_format_io_close(pls->parent, &pls->input); + ff_format_io_close(pls->parent, &pls->input); // find the nearest fragment if (pls->n_timelines > 0 && pls->fragment_timescale > 0) { int64_t num = pls->first_seq_no; av_log(pls->parent, AV_LOG_VERBOSE, "dash_seek with SegmentTimeline start n_timelines[%d] " - "last_seq_no[%"PRId64"], playlist %d.\n", - (int)pls->n_timelines, (int64_t)pls->last_seq_no, (int)pls->rep_idx); + "last_seq_no[%"PRId64"].\n", + (int)pls->n_timelines, (int64_t)pls->last_seq_no); for (i = 0; i < pls->n_timelines; i++) { if (pls->timelines[i]->starttime > 0) { duration = pls->timelines[i]->starttime; @@ -2294,8 +2317,8 @@ set_seq_num: pls->cur_seq_no = num > pls->last_seq_no ? pls->last_seq_no : num; - av_log(pls->parent, AV_LOG_VERBOSE, "dash_seek with SegmentTimeline end cur_seq_no[%"PRId64"], playlist %d.\n", - (int64_t)pls->cur_seq_no, (int)pls->rep_idx); + av_log(pls->parent, AV_LOG_VERBOSE, "dash_seek with SegmentTimeline end cur_seq_no[%"PRId64"].\n", + (int64_t)pls->cur_seq_no); } else if (pls->fragment_duration > 0) { pls->cur_seq_no = pls->first_seq_no + ((seek_pos_msec * pls->fragment_timescale) / pls->fragment_duration) / 1000; } else { @@ -2346,7 +2369,8 @@ if (av_stristr(p->buf, "dash:profile:isoff-on-demand:2011") || av_stristr(p->buf, "dash:profile:isoff-live:2011") || av_stristr(p->buf, "dash:profile:isoff-live:2012") || - av_stristr(p->buf, "dash:profile:isoff-main:2011")) { + av_stristr(p->buf, "dash:profile:isoff-main:2011") || + av_stristr(p->buf, "3GPP:PSS:profile:DASH1")) { return AVPROBE_SCORE_MAX; } if (av_stristr(p->buf, "dash:profile")) { @@ -2361,7 +2385,7 @@ static const AVOption dash_options[] = { {"allowed_extensions", "List of file extensions that dash is allowed to access", OFFSET(allowed_extensions), AV_OPT_TYPE_STRING, - {.str = "aac,m4a,m4s,m4v,mov,mp4,webm"}, + {.str = "aac,m4a,m4s,m4v,mov,mp4,webm,ts"}, INT_MIN, INT_MAX, FLAGS}, {NULL} }; diff -Nru ffmpeg-4.2.2/libavformat/dashenc.c ffmpeg-4.4/libavformat/dashenc.c --- ffmpeg-4.2.2/libavformat/dashenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/dashenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -31,6 +31,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" +#include "libavutil/parseutils.h" #include "libavutil/rational.h" #include "libavutil/time.h" #include "libavutil/time_internal.h" @@ -57,6 +58,17 @@ SEGMENT_TYPE_NB } SegmentType; +enum { + FRAG_TYPE_NONE = 0, + FRAG_TYPE_EVERY_FRAME, + FRAG_TYPE_DURATION, + FRAG_TYPE_PFRAMES, + FRAG_TYPE_NB +}; + +#define MPD_PROFILE_DASH 1 +#define MPD_PROFILE_DVB 2 + typedef struct Segment { char file[1024]; int64_t start_pos; @@ -68,26 +80,42 @@ } Segment; typedef struct AdaptationSet { - char id[10]; + int id; + char *descriptor; + int64_t seg_duration; + int64_t frag_duration; + int frag_type; enum AVMediaType media_type; AVDictionary *metadata; AVRational min_frame_rate, max_frame_rate; int ambiguous_frame_rate; + int64_t max_frag_duration; + int max_width, max_height; + int nb_streams; + AVRational par; + int trick_idx; } AdaptationSet; typedef struct OutputStream { AVFormatContext *ctx; int ctx_inited, as_idx; AVIOContext *out; + AVCodecParserContext *parser; + AVCodecContext *parser_avctx; int packets_written; char initfile[1024]; int64_t init_start_pos, pos; int init_range_length; int nb_segments, segments_size, segment_index; + int64_t seg_duration; + int64_t frag_duration; + int64_t last_duration; Segment **segments; int64_t first_pts, start_pts, max_pts; int64_t last_dts, last_pts; + int last_flags; int bit_rate; + int first_segment_bit_rate; SegmentType segment_type; /* segment type selected for this particular stream */ const char *format_name; const char *extension_name; @@ -101,8 +129,15 @@ char full_path[1024]; char temp_path[1024]; double availability_time_offset; + AVProducerReferenceTime producer_reference_time; + char producer_reference_time_str[100]; int total_pkt_size; + int64_t total_pkt_duration; int muxer_overhead; + int frag_type; + int64_t gop_size; + AVRational sar; + int coding_dependency; } OutputStream; typedef struct DASHContext { @@ -116,6 +151,7 @@ int min_seg_duration; #endif int64_t seg_duration; + int64_t frag_duration; int remove_at_exit; int use_template; int use_timeline; @@ -126,6 +162,7 @@ int64_t total_duration; char availability_start_time[100]; time_t start_time_s; + int64_t presentation_time_offset; char dirname[1024]; const char *single_file_name; /* file names as specified in options */ const char *init_seg_name; @@ -133,7 +170,9 @@ const char *utc_timing_url; const char *method; const char *user_agent; + AVDictionary *http_opts; int hls_playlist; + const char *hls_master_name; int http_persistent; int master_playlist_created; AVIOContext *mpd_out; @@ -141,14 +180,25 @@ int streaming; int64_t timeout; int index_correction; - char *format_options_str; + AVDictionary *format_options; int global_sidx; SegmentType segment_type_option; /* segment type as specified in options */ int ignore_io_errors; int lhls; + int ldash; int master_publish_rate; int nr_of_streams_to_flush; int nr_of_streams_flushed; + int frag_type; + int write_prft; + int64_t max_gop_size; + int64_t max_segment_duration; + int profile; + int64_t target_latency; + int target_latency_refid; + AVRational min_playback_rate; + AVRational max_playback_rate; + int64_t update_period; } DASHContext; static struct codec_string { @@ -437,6 +487,7 @@ { if (c->method) av_dict_set(options, "method", c->method, 0); + av_dict_copy(options, c->http_opts, 0); if (c->user_agent) av_dict_set(options, "user_agent", c->user_agent, 0); if (c->http_persistent) @@ -539,9 +590,7 @@ dashenc_io_close(s, &c->m3u8_out, temp_filename_hls); if (use_rename) - if (avpriv_io_move(temp_filename_hls, filename_hls) < 0) { - av_log(os->ctx, AV_LOG_WARNING, "renaming file %s to %s failed\n\n", temp_filename_hls, filename_hls); - } + ff_rename(temp_filename_hls, filename_hls, os->ctx); } static int flush_init_segment(AVFormatContext *s, OutputStream *os) @@ -568,8 +617,10 @@ int i, j; if (c->as) { - for (i = 0; i < c->nb_as; i++) + for (i = 0; i < c->nb_as; i++) { av_dict_free(&c->as[i].metadata); + av_freep(&c->as[i].descriptor); + } av_freep(&c->as); c->nb_as = 0; } @@ -585,8 +636,9 @@ avio_close(os->ctx->pb); } ff_format_io_close(s, &os->out); - if (os->ctx) - avformat_free_context(os->ctx); + avformat_free_context(os->ctx); + avcodec_free_context(&os->parser_avctx); + av_parser_close(os->parser); for (j = 0; j < os->nb_segments; j++) av_free(os->segments[j]); av_free(os->segments); @@ -611,12 +663,18 @@ int timescale = c->use_timeline ? os->ctx->streams[0]->time_base.den : AV_TIME_BASE; avio_printf(out, "\t\t\t\tuse_timeline) { - avio_printf(out, "duration=\"%"PRId64"\" ", c->seg_duration); + avio_printf(out, "duration=\"%"PRId64"\" ", os->seg_duration); if (c->streaming && os->availability_time_offset) avio_printf(out, "availabilityTimeOffset=\"%.3f\" ", os->availability_time_offset); } - avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\">\n", os->init_seg_name, os->media_seg_name, c->use_timeline ? start_number : 1); + if (c->streaming && os->availability_time_offset && !final) + avio_printf(out, "availabilityTimeComplete=\"false\" "); + + avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\"", os->init_seg_name, os->media_seg_name, c->use_timeline ? start_number : 1); + if (c->presentation_time_offset) + avio_printf(out, " presentationTimeOffset=\"%"PRId64"\"", c->presentation_time_offset); + avio_printf(out, ">\n"); if (c->use_timeline) { int64_t cur_time = 0; avio_printf(out, "\t\t\t\t\t\n"); @@ -644,7 +702,7 @@ avio_printf(out, "\t\t\t\t\n"); } else if (c->single_file) { avio_printf(out, "\t\t\t\t%s\n", os->initfile); - avio_printf(out, "\t\t\t\t\n", AV_TIME_BASE, c->last_duration, start_number); + avio_printf(out, "\t\t\t\t\n", AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number); avio_printf(out, "\t\t\t\t\t\n", os->init_start_pos, os->init_start_pos + os->init_range_length - 1); for (i = start_index; i < os->nb_segments; i++) { Segment *seg = os->segments[i]; @@ -655,7 +713,7 @@ } avio_printf(out, "\t\t\t\t\n"); } else { - avio_printf(out, "\t\t\t\t\n", AV_TIME_BASE, c->last_duration, start_number); + avio_printf(out, "\t\t\t\t\n", AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number); avio_printf(out, "\t\t\t\t\t\n", os->initfile); for (i = start_index; i < os->nb_segments; i++) { Segment *seg = os->segments[i]; @@ -725,10 +783,9 @@ avio_printf(out, "%d.%dS", seconds, fractions / (AV_TIME_BASE / 10)); } -static void format_date_now(char *buf, int size) +static void format_date(char *buf, int size, int64_t time_us) { struct tm *ptm, tmbuf; - int64_t time_us = av_gettime(); int64_t time_ms = time_us / 1000; const time_t time_s = time_ms / 1000; int millisec = time_ms - (time_s * 1000); @@ -752,20 +809,32 @@ AVDictionaryEntry *lang, *role; int i; - avio_printf(out, "\t\tid, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den); + else if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && !av_cmp_q(as->min_frame_rate, as->max_frame_rate)) + avio_printf(out, " frameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den); + if (as->media_type == AVMEDIA_TYPE_VIDEO) { + avio_printf(out, " maxWidth=\"%d\" maxHeight=\"%d\"", as->max_width, as->max_height); + avio_printf(out, " par=\"%d:%d\"", as->par.num, as->par.den); + } lang = av_dict_get(as->metadata, "language", NULL, 0); if (lang) avio_printf(out, " lang=\"%s\"", lang->value); avio_printf(out, ">\n"); + if (!final && c->ldash && as->max_frag_duration && !(c->profile & MPD_PROFILE_DVB)) + avio_printf(out, "\t\t\t\n", as->max_frag_duration); + if (as->trick_idx >= 0) + avio_printf(out, "\t\t\t\n", as->id, as->trick_idx); role = av_dict_get(as->metadata, "role", NULL, 0); if (role) avio_printf(out, "\t\t\t\n", role->value); - + if (as->descriptor) + avio_printf(out, "\t\t\t%s\n", as->descriptor); for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; OutputStream *os = &c->streams[i]; char bandwidth_str[64] = {'\0'}; @@ -773,15 +842,30 @@ continue; if (os->bit_rate > 0) - snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"", - os->bit_rate); + snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"", os->bit_rate); + else if (final) { + int average_bit_rate = os->pos * 8 * AV_TIME_BASE / c->total_duration; + snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"", average_bit_rate); + } else if (os->first_segment_bit_rate > 0) + snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"", os->first_segment_bit_rate); if (as->media_type == AVMEDIA_TYPE_VIDEO) { - AVStream *st = s->streams[i]; avio_printf(out, "\t\t\tformat_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height); - if (st->avg_frame_rate.num) + if (st->codecpar->field_order == AV_FIELD_UNKNOWN) + avio_printf(out, " scanType=\"unknown\""); + else if (st->codecpar->field_order != AV_FIELD_PROGRESSIVE) + avio_printf(out, " scanType=\"interlaced\""); + avio_printf(out, " sar=\"%d:%d\"", os->sar.num, os->sar.den); + if (st->avg_frame_rate.num && av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0) avio_printf(out, " frameRate=\"%d/%d\"", st->avg_frame_rate.num, st->avg_frame_rate.den); + if (as->trick_idx >= 0) { + AdaptationSet *tas = &c->as[as->trick_idx]; + if (!as->ambiguous_frame_rate && !tas->ambiguous_frame_rate) + avio_printf(out, " maxPlayoutRate=\"%d\"", FFMAX((int)av_q2d(av_div_q(tas->min_frame_rate, as->min_frame_rate)), 1)); + } + if (!os->coding_dependency) + avio_printf(out, " codingDependency=\"false\""); avio_printf(out, ">\n"); } else { avio_printf(out, "\t\t\t\n", @@ -789,6 +873,15 @@ avio_printf(out, "\t\t\t\t\n", s->streams[i]->codecpar->channels); } + if (!final && c->write_prft && os->producer_reference_time_str[0]) { + avio_printf(out, "\t\t\t\t\n", + i, os->producer_reference_time.flags ? "captured" : "encoder", os->producer_reference_time_str, c->presentation_time_offset); + avio_printf(out, "\t\t\t\t\t\n", c->utc_timing_url); + avio_printf(out, "\t\t\t\t\n"); + } + if (!final && c->ldash && os->gop_size && os->frag_type != FRAG_TYPE_NONE && !(c->profile & MPD_PROFILE_DVB) && + (os->frag_type != FRAG_TYPE_DURATION || os->frag_duration != os->seg_duration)) + avio_printf(out, "\t\t\t\t\n", os->gop_size); output_segment_list(os, out, s, i, final); avio_printf(out, "\t\t\t\n"); } @@ -800,8 +893,13 @@ static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMediaType type) { DASHContext *c = s->priv_data; + void *mem; - void *mem = av_realloc(c->as, sizeof(*c->as) * (c->nb_as + 1)); + if (c->profile & MPD_PROFILE_DVB && (c->nb_as + 1) > 16) { + av_log(s, AV_LOG_ERROR, "DVB-DASH profile allows a max of 16 Adaptation Sets\n"); + return AVERROR(EINVAL); + } + mem = av_realloc(c->as, sizeof(*c->as) * (c->nb_as + 1)); if (!mem) return AVERROR(ENOMEM); c->as = mem; @@ -810,6 +908,8 @@ *as = &c->as[c->nb_as - 1]; memset(*as, 0, sizeof(**as)); (*as)->media_type = type; + (*as)->frag_type = -1; + (*as)->trick_idx = -1; return 0; } @@ -827,7 +927,12 @@ av_log(s, AV_LOG_ERROR, "Stream %d is already assigned to an AdaptationSet\n", i); return AVERROR(EINVAL); } + if (c->profile & MPD_PROFILE_DVB && (as->nb_streams + 1) > 16) { + av_log(s, AV_LOG_ERROR, "DVB-DASH profile allows a max of 16 Representations per Adaptation Set\n"); + return AVERROR(EINVAL); + } os->as_idx = as_idx; + ++as->nb_streams; return 0; } @@ -836,7 +941,7 @@ { DASHContext *c = s->priv_data; const char *p = c->adaptation_sets; - enum { new_set, parse_id, parsing_streams } state; + enum { new_set, parse_default, parsing_streams, parse_seg_duration, parse_frag_duration } state; AdaptationSet *as; int i, n, ret; @@ -845,32 +950,121 @@ for (i = 0; i < s->nb_streams; i++) { if ((ret = add_adaptation_set(s, &as, s->streams[i]->codecpar->codec_type)) < 0) return ret; - snprintf(as->id, sizeof(as->id), "%d", i); + as->id = i; c->streams[i].as_idx = c->nb_as; + ++as->nb_streams; } goto end; } // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on + // option id=0,descriptor=descriptor_str,streams=0,1,2 and so on + // option id=0,seg_duration=2.5,frag_duration=0.5,streams=0,1,2 + // id=1,trick_id=0,seg_duration=10,frag_type=none,streams=3 and so on + // descriptor is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015 + // descriptor_str should be a self-closing xml tag. + // seg_duration and frag_duration have the same syntax as the global options of + // the same name, and the former have precedence over them if set. state = new_set; while (*p) { if (*p == ' ') { p++; continue; } else if (state == new_set && av_strstart(p, "id=", &p)) { + char id_str[10], *end_str; + + n = strcspn(p, ","); + snprintf(id_str, sizeof(id_str), "%.*s", n, p); + + i = strtol(id_str, &end_str, 10); + if (id_str == end_str || i < 0 || i > c->nb_as) { + av_log(s, AV_LOG_ERROR, "\"%s\" is not a valid value for an AdaptationSet id\n", id_str); + return AVERROR(EINVAL); + } if ((ret = add_adaptation_set(s, &as, AVMEDIA_TYPE_UNKNOWN)) < 0) return ret; + as->id = i; + + p += n; + if (*p) + p++; + state = parse_default; + } else if (state != new_set && av_strstart(p, "seg_duration=", &p)) { + state = parse_seg_duration; + } else if (state != new_set && av_strstart(p, "frag_duration=", &p)) { + state = parse_frag_duration; + } else if (state == parse_seg_duration || state == parse_frag_duration) { + char str[32]; + int64_t usecs = 0; n = strcspn(p, ","); - snprintf(as->id, sizeof(as->id), "%.*s", n, p); + snprintf(str, sizeof(str), "%.*s", n, p); + p += n; + if (*p) + p++; + ret = av_parse_time(&usecs, str, 1); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Unable to parse option value \"%s\" as duration\n", str); + return ret; + } + + if (state == parse_seg_duration) + as->seg_duration = usecs; + else + as->frag_duration = usecs; + state = parse_default; + } else if (state != new_set && av_strstart(p, "frag_type=", &p)) { + char type_str[16]; + + n = strcspn(p, ","); + snprintf(type_str, sizeof(type_str), "%.*s", n, p); p += n; if (*p) p++; - state = parse_id; - } else if (state == parse_id && av_strstart(p, "streams=", &p)) { + + if (!strcmp(type_str, "duration")) + as->frag_type = FRAG_TYPE_DURATION; + else if (!strcmp(type_str, "pframes")) + as->frag_type = FRAG_TYPE_PFRAMES; + else if (!strcmp(type_str, "every_frame")) + as->frag_type = FRAG_TYPE_EVERY_FRAME; + else if (!strcmp(type_str, "none")) + as->frag_type = FRAG_TYPE_NONE; + else { + av_log(s, AV_LOG_ERROR, "Unable to parse option value \"%s\" as fragment type\n", type_str); + return ret; + } + state = parse_default; + } else if (state != new_set && av_strstart(p, "descriptor=", &p)) { + n = strcspn(p, ">") + 1; //followed by one comma, so plus 1 + if (n < strlen(p)) { + as->descriptor = av_strndup(p, n); + } else { + av_log(s, AV_LOG_ERROR, "Parse error, descriptor string should be a self-closing xml tag\n"); + return AVERROR(EINVAL); + } + p += n; + if (*p) + p++; + state = parse_default; + } else if ((state != new_set) && av_strstart(p, "trick_id=", &p)) { + char trick_id_str[10], *end_str; + + n = strcspn(p, ","); + snprintf(trick_id_str, sizeof(trick_id_str), "%.*s", n, p); + p += n; + + as->trick_idx = strtol(trick_id_str, &end_str, 10); + if (trick_id_str == end_str || as->trick_idx < 0) + return AVERROR(EINVAL); + + if (*p) + p++; + state = parse_default; + } else if ((state != new_set) && av_strstart(p, "streams=", &p)) { //descriptor and durations are optional state = parsing_streams; } else if (state == parsing_streams) { AdaptationSet *as = &c->as[c->nb_as - 1]; @@ -928,6 +1122,22 @@ return AVERROR(EINVAL); } } + + // check references for trick mode AdaptationSet + for (i = 0; i < c->nb_as; i++) { + as = &c->as[i]; + if (as->trick_idx < 0) + continue; + for (n = 0; n < c->nb_as; n++) { + if (c->as[n].id == as->trick_idx) + break; + } + if (n >= c->nb_as) { + av_log(s, AV_LOG_ERROR, "reference AdaptationSet id \"%d\" not found for trick mode AdaptationSet id \"%d\"\n", as->trick_idx, as->id); + return AVERROR(EINVAL); + } + } + return 0; } @@ -959,8 +1169,13 @@ "\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n" "\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n" "\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n" - "\tprofiles=\"urn:mpeg:dash:profile:isoff-live:2011\"\n" - "\ttype=\"%s\"\n", final ? "static" : "dynamic"); + "\tprofiles=\""); + if (c->profile & MPD_PROFILE_DASH) + avio_printf(out, "%s%s", "urn:mpeg:dash:profile:isoff-live:2011", c->profile & MPD_PROFILE_DVB ? "," : "\"\n"); + if (c->profile & MPD_PROFILE_DVB) + avio_printf(out, "%s", "urn:dvb:dash:profile:dvb-dash:2014\"\n"); + avio_printf(out, "\ttype=\"%s\"\n", + final ? "static" : "dynamic"); if (final) { avio_printf(out, "\tmediaPresentationDuration=\""); write_time(out, c->total_duration); @@ -970,11 +1185,14 @@ char now_str[100]; if (c->use_template && !c->use_timeline) update_period = 500; + if (c->update_period) + update_period = c->update_period; avio_printf(out, "\tminimumUpdatePeriod=\"PT%"PRId64"S\"\n", update_period); - avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE); + if (!c->ldash) + avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE); if (c->availability_start_time[0]) avio_printf(out, "\tavailabilityStartTime=\"%s\"\n", c->availability_start_time); - format_date_now(now_str, sizeof(now_str)); + format_date(now_str, sizeof(now_str), av_gettime()); if (now_str[0]) avio_printf(out, "\tpublishTime=\"%s\"\n", now_str); if (c->window_size && c->use_template) { @@ -983,8 +1201,11 @@ avio_printf(out, "\"\n"); } } + avio_printf(out, "\tmaxSegmentDuration=\""); + write_time(out, c->max_segment_duration); + avio_printf(out, "\"\n"); avio_printf(out, "\tminBufferTime=\""); - write_time(out, c->last_duration * 2); + write_time(out, c->ldash && c->max_gop_size ? c->max_gop_size : c->last_duration * 2); avio_printf(out, "\">\n"); avio_printf(out, "\t\n"); if (title) { @@ -994,6 +1215,19 @@ } avio_printf(out, "\t\n"); + avio_printf(out, "\t\n"); + if (!final && c->target_latency && c->target_latency_refid >= 0) { + avio_printf(out, "\t\ttarget_latency / 1000); + if (s->nb_streams > 1) + avio_printf(out, " referenceId=\"%d\"", c->target_latency_refid); + avio_printf(out, "/>\n"); + } + if (av_cmp_q(c->min_playback_rate, (AVRational) {1, 1}) || + av_cmp_q(c->max_playback_rate, (AVRational) {1, 1})) + avio_printf(out, "\t\t\n", + av_q2d(c->min_playback_rate), av_q2d(c->max_playback_rate)); + avio_printf(out, "\t\n"); + if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) { OutputStream *os = &c->streams[0]; int start_index = FFMAX(os->nb_segments - c->window_size, 0); @@ -1019,7 +1253,7 @@ dashenc_io_close(s, &c->mpd_out, temp_filename); if (use_rename) { - if ((ret = avpriv_io_move(temp_filename, s->url)) < 0) + if ((ret = ff_rename(temp_filename, s->url, s)) < 0) return ret; } @@ -1036,9 +1270,9 @@ return 0; if (*c->dirname) - snprintf(filename_hls, sizeof(filename_hls), "%smaster.m3u8", c->dirname); + snprintf(filename_hls, sizeof(filename_hls), "%s%s", c->dirname, c->hls_master_name); else - snprintf(filename_hls, sizeof(filename_hls), "master.m3u8"); + snprintf(filename_hls, sizeof(filename_hls), "%s", c->hls_master_name); snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", filename_hls); @@ -1079,7 +1313,13 @@ OutputStream *os = &c->streams[i]; char *agroup = NULL; char *codec_str_ptr = NULL; - int stream_bitrate = st->codecpar->bit_rate + os->muxer_overhead; + int stream_bitrate = os->muxer_overhead; + if (os->bit_rate > 0) + stream_bitrate += os->bit_rate; + else if (final) + stream_bitrate += os->pos * 8 * AV_TIME_BASE / c->total_duration; + else if (os->first_segment_bit_rate > 0) + stream_bitrate += os->first_segment_bit_rate; if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) continue; if (os->segment_type != SEGMENT_TYPE_MP4) @@ -1097,11 +1337,11 @@ get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i); ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate, playlist_file, agroup, - codec_str_ptr, NULL); + codec_str_ptr, NULL, NULL); } dashenc_io_close(s, &c->m3u8_out, temp_filename); if (use_rename) - if ((ret = avpriv_io_move(temp_filename, filename_hls)) < 0) + if ((ret = ff_rename(temp_filename, filename_hls, s)) < 0) return ret; c->master_playlist_created = 1; } @@ -1130,6 +1370,10 @@ if (c->single_file) c->use_template = 0; + if (!c->profile) { + av_log(s, AV_LOG_ERROR, "At least one profile must be enabled.\n"); + return AVERROR(EINVAL); + } #if FF_API_DASH_MIN_SEG_DURATION if (c->min_seg_duration != 5000000) { av_log(s, AV_LOG_WARNING, "The min_seg_duration option is deprecated and will be removed. Please use the -seg_duration\n"); @@ -1152,6 +1396,16 @@ c->lhls = 0; } + 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; + } + + if (c->target_latency && !c->streaming) { + av_log(s, AV_LOG_WARNING, "Target latency option will be ignored as streaming is not enabled\n"); + c->target_latency = 0; + } + if (c->global_sidx && !c->single_file) { av_log(s, AV_LOG_WARNING, "Global SIDX option will be ignored as single_file is not enabled\n"); c->global_sidx = 0; @@ -1161,6 +1415,40 @@ av_log(s, AV_LOG_WARNING, "Global SIDX option will be ignored as streaming is enabled\n"); c->global_sidx = 0; } + if (c->frag_type == FRAG_TYPE_NONE && c->streaming) { + av_log(s, AV_LOG_VERBOSE, "Changing frag_type from none to every_frame as streaming is enabled\n"); + c->frag_type = FRAG_TYPE_EVERY_FRAME; + } + + if (c->write_prft < 0) { + c->write_prft = c->ldash; + if (c->ldash) + av_log(s, AV_LOG_VERBOSE, "Enabling Producer Reference Time element for Low Latency mode\n"); + } + + if (c->write_prft && !c->utc_timing_url) { + av_log(s, AV_LOG_WARNING, "Producer Reference Time element option will be ignored as utc_timing_url is not set\n"); + c->write_prft = 0; + } + + if (c->write_prft && !c->streaming) { + av_log(s, AV_LOG_WARNING, "Producer Reference Time element option will be ignored as streaming is not enabled\n"); + c->write_prft = 0; + } + + if (c->ldash && !c->write_prft) { + av_log(s, AV_LOG_WARNING, "Low Latency mode enabled without Producer Reference Time element option! Resulting manifest may not be complaint\n"); + } + + if (c->target_latency && !c->write_prft) { + av_log(s, AV_LOG_WARNING, "Target latency option will be ignored as Producer Reference Time element will not be written\n"); + c->target_latency = 0; + } + + if (av_cmp_q(c->max_playback_rate, c->min_playback_rate) < 0) { + av_log(s, AV_LOG_WARNING, "Minimum playback rate value is higer than the Maximum. Both will be ignored\n"); + c->min_playback_rate = c->max_playback_rate = (AVRational) {1, 1}; + } av_strlcpy(c->dirname, s->url, sizeof(c->dirname)); ptr = strrchr(c->dirname, '/'); @@ -1207,10 +1495,6 @@ dict_copy_entry(&as->metadata, s->streams[i]->metadata, "language"); dict_copy_entry(&as->metadata, s->streams[i]->metadata, "role"); - ctx = avformat_alloc_context(); - if (!ctx) - return AVERROR(ENOMEM); - if (c->init_seg_name) { os->init_seg_name = av_strireplace(c->init_seg_name, "$ext$", os->extension_name); if (!os->init_seg_name) @@ -1243,10 +1527,13 @@ } } + os->ctx = ctx = avformat_alloc_context(); + if (!ctx) + return AVERROR(ENOMEM); + ctx->oformat = av_guess_format(os->format_name, NULL, NULL); if (!ctx->oformat) return AVERROR_MUXER_NOT_FOUND; - os->ctx = ctx; ctx->interrupt_callback = s->interrupt_callback; ctx->opaque = s->opaque; ctx->io_close = s->io_close; @@ -1262,6 +1549,18 @@ ctx->avoid_negative_ts = s->avoid_negative_ts; ctx->flags = s->flags; + os->parser = av_parser_init(st->codecpar->codec_id); + if (os->parser) { + os->parser_avctx = avcodec_alloc_context3(NULL); + if (!os->parser_avctx) + return AVERROR(ENOMEM); + ret = avcodec_parameters_to_context(os->parser_avctx, st->codecpar); + if (ret < 0) + return ret; + // We only want to parse frame headers + os->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + } + if (c->single_file) { if (os->single_file_name) ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate, 0); @@ -1285,24 +1584,60 @@ return ret; os->init_start_pos = 0; - if (c->format_options_str) { - ret = av_dict_parse_string(&opts, c->format_options_str, "=", ":", 0); - if (ret < 0) - return ret; + av_dict_copy(&opts, c->format_options, 0); + if (!as->seg_duration) + as->seg_duration = c->seg_duration; + if (!as->frag_duration) + as->frag_duration = c->frag_duration; + if (as->frag_type < 0) + as->frag_type = c->frag_type; + os->seg_duration = as->seg_duration; + os->frag_duration = as->frag_duration; + os->frag_type = as->frag_type; + + c->max_segment_duration = FFMAX(c->max_segment_duration, as->seg_duration); + + if (c->profile & MPD_PROFILE_DVB && (os->seg_duration > 15000000 || os->seg_duration < 960000)) { + av_log(s, AV_LOG_ERROR, "Segment duration %"PRId64" is outside the allowed range for DVB-DASH profile\n", os->seg_duration); + return AVERROR(EINVAL); } + if (os->frag_type == FRAG_TYPE_DURATION && !os->frag_duration) { + av_log(s, AV_LOG_WARNING, "frag_type set to duration for stream %d but no frag_duration set\n", i); + os->frag_type = c->streaming ? FRAG_TYPE_EVERY_FRAME : FRAG_TYPE_NONE; + } + if (os->frag_type == FRAG_TYPE_DURATION && os->frag_duration > os->seg_duration) { + av_log(s, AV_LOG_ERROR, "Fragment duration %"PRId64" is longer than Segment duration %"PRId64"\n", os->frag_duration, os->seg_duration); + return AVERROR(EINVAL); + } + if (os->frag_type == FRAG_TYPE_PFRAMES && (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO || !os->parser)) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !os->parser) + av_log(s, AV_LOG_WARNING, "frag_type set to P-Frame reordering, but no parser found for stream %d\n", i); + os->frag_type = c->streaming ? FRAG_TYPE_EVERY_FRAME : FRAG_TYPE_NONE; + } + if (os->frag_type != FRAG_TYPE_PFRAMES && as->trick_idx < 0) + // Set this now if a parser isn't used + os->coding_dependency = 1; + if (os->segment_type == SEGMENT_TYPE_MP4) { if (c->streaming) - // frag_every_frame : Allows lower latency streaming // skip_sidx : Reduce bitrate overhead // skip_trailer : Avoids growing memory usage with time - av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov+skip_sidx+skip_trailer", 0); + av_dict_set(&opts, "movflags", "+dash+delay_moov+skip_sidx+skip_trailer", AV_DICT_APPEND); else { if (c->global_sidx) - av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+global_sidx+skip_trailer", 0); + av_dict_set(&opts, "movflags", "+dash+delay_moov+global_sidx+skip_trailer", AV_DICT_APPEND); else - av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+skip_trailer", 0); + av_dict_set(&opts, "movflags", "+dash+delay_moov+skip_trailer", AV_DICT_APPEND); } + if (os->frag_type == FRAG_TYPE_EVERY_FRAME) + av_dict_set(&opts, "movflags", "+frag_every_frame", AV_DICT_APPEND); + else + av_dict_set(&opts, "movflags", "+frag_custom", AV_DICT_APPEND); + if (os->frag_type == FRAG_TYPE_DURATION) + av_dict_set_int(&opts, "frag_duration", os->frag_duration, 0); + if (c->write_prft) + av_dict_set(&opts, "write_prft", "wallclock", 0); } else { av_dict_set_int(&opts, "cluster_time_limit", c->seg_duration / 1000, 0); av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit @@ -1326,6 +1661,7 @@ s->avoid_negative_ts = ctx->avoid_negative_ts; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { AVRational avg_frame_rate = s->streams[i]->avg_frame_rate; + AVRational par; if (avg_frame_rate.num > 0) { if (av_cmp_q(avg_frame_rate, as->min_frame_rate) < 0) as->min_frame_rate = avg_frame_rate; @@ -1334,6 +1670,27 @@ } else { as->ambiguous_frame_rate = 1; } + + if (st->codecpar->width > as->max_width) + as->max_width = st->codecpar->width; + if (st->codecpar->height > as->max_height) + as->max_height = st->codecpar->height; + + if (st->sample_aspect_ratio.num) + os->sar = st->sample_aspect_ratio; + else + os->sar = (AVRational){1,1}; + av_reduce(&par.num, &par.den, + st->codecpar->width * (int64_t)os->sar.num, + st->codecpar->height * (int64_t)os->sar.den, + 1024 * 1024); + + if (as->par.num && av_cmp_q(par, as->par)) { + av_log(s, AV_LOG_ERROR, "Conflicting stream aspect ratios values in Adaptation Set %d. Please ensure all adaptation sets have the same aspect ratio\n", os->as_idx); + return AVERROR(EINVAL); + } + as->par = par; + c->has_video = 1; } @@ -1352,8 +1709,11 @@ av_log(s, AV_LOG_WARNING, "no video stream and no seg duration set\n"); return AVERROR(EINVAL); } + if (!c->has_video && c->frag_type == FRAG_TYPE_PFRAMES) + av_log(s, AV_LOG_WARNING, "no video stream and P-frame fragmentation set\n"); c->nr_of_streams_flushed = 0; + c->target_latency_refid = -1; return 0; } @@ -1386,7 +1746,7 @@ Segment *seg; if (os->nb_segments >= os->segments_size) { os->segments_size = (os->segments_size + 1) * 2; - if ((err = av_reallocp(&os->segments, sizeof(*os->segments) * + if ((err = av_reallocp_array(&os->segments, sizeof(*os->segments), os->segments_size)) < 0) { os->segments_size = 0; os->nb_segments = 0; @@ -1455,7 +1815,8 @@ { AVCodecParameters *par = os->ctx->streams[0]->codecpar; uint8_t *extradata; - int ret, extradata_size; + buffer_size_t extradata_size; + int ret; if (par->extradata_size) return 0; @@ -1505,28 +1866,20 @@ static int dashenc_delete_segment_file(AVFormatContext *s, const char* file) { DASHContext *c = s->priv_data; - size_t dirname_len, file_len; - char filename[1024]; + AVBPrint buf; - dirname_len = strlen(c->dirname); - if (dirname_len >= sizeof(filename)) { - av_log(s, AV_LOG_WARNING, "Cannot delete segments as the directory path is too long: %"PRIu64" characters: %s\n", - (uint64_t)dirname_len, c->dirname); - return AVERROR(ENAMETOOLONG); - } - - memcpy(filename, c->dirname, dirname_len); + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); - file_len = strlen(file); - if ((dirname_len + file_len) >= sizeof(filename)) { - av_log(s, AV_LOG_WARNING, "Cannot delete segments as the path is too long: %"PRIu64" characters: %s%s\n", - (uint64_t)(dirname_len + file_len), c->dirname, file); - return AVERROR(ENAMETOOLONG); + av_bprintf(&buf, "%s%s", c->dirname, file); + if (!av_bprint_is_complete(&buf)) { + av_bprint_finalize(&buf, NULL); + av_log(s, AV_LOG_WARNING, "Out of memory for filename\n"); + return AVERROR(ENOMEM); } - memcpy(filename + dirname_len, file, file_len + 1); // include the terminating zero - dashenc_delete_file(s, filename); + dashenc_delete_file(s, buf.str); + av_bprint_finalize(&buf, NULL); return 0; } @@ -1563,7 +1916,7 @@ c->streams[stream].first_pts, s->streams[stream]->time_base, AV_TIME_BASE_Q); - next_exp_index = (pts_diff / c->seg_duration) + 1; + next_exp_index = (pts_diff / c->streams[stream].seg_duration) + 1; } } @@ -1571,6 +1924,7 @@ OutputStream *os = &c->streams[i]; AVStream *st = s->streams[i]; int range_length, index_length = 0; + int64_t duration; if (!os->packets_written) continue; @@ -1579,6 +1933,9 @@ // Flush all audio streams as well, in sync with video keyframes, // but not the other video streams. if (stream >= 0 && i != stream) { + if (s->streams[stream]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && + s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) + continue; if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) continue; // Make sure we don't flush audio streams multiple times, when @@ -1587,12 +1944,8 @@ continue; } - if (!c->single_file) { - if (os->segment_type == SEGMENT_TYPE_MP4 && !os->written_len) - write_styp(os->ctx->pb); - } else { + if (c->single_file) snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile); - } ret = flush_dynbuf(c, os, &range_length); if (ret < 0) @@ -1605,26 +1958,23 @@ dashenc_io_close(s, &os->out, os->temp_path); if (use_rename) { - ret = avpriv_io_move(os->temp_path, os->full_path); + ret = ff_rename(os->temp_path, os->full_path, os->ctx); if (ret < 0) break; } } - if (!os->muxer_overhead) + duration = av_rescale_q(os->max_pts - os->start_pts, st->time_base, AV_TIME_BASE_Q); + os->last_duration = FFMAX(os->last_duration, duration); + + if (!os->muxer_overhead && os->max_pts > os->start_pts) os->muxer_overhead = ((int64_t) (range_length - os->total_pkt_size) * - 8 * AV_TIME_BASE) / - av_rescale_q(os->max_pts - os->start_pts, - st->time_base, AV_TIME_BASE_Q); + 8 * AV_TIME_BASE) / duration; os->total_pkt_size = 0; + os->total_pkt_duration = 0; - if (!os->bit_rate) { - // calculate average bitrate of first segment - int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / av_rescale_q(os->max_pts - os->start_pts, - st->time_base, - AV_TIME_BASE_Q); - if (bitrate >= 0) - os->bit_rate = bitrate; + if (!os->bit_rate && !os->first_segment_bit_rate) { + os->first_segment_bit_rate = (int64_t) range_length * 8 * AV_TIME_BASE / duration; } add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length, next_exp_index); av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, os->full_path); @@ -1677,11 +2027,38 @@ return ret; } +static int dash_parse_prft(DASHContext *c, AVPacket *pkt) +{ + OutputStream *os = &c->streams[pkt->stream_index]; + AVProducerReferenceTime *prft; + buffer_size_t side_data_size; + + prft = (AVProducerReferenceTime *)av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &side_data_size); + if (!prft || side_data_size != sizeof(AVProducerReferenceTime) || (prft->flags && prft->flags != 24)) { + // No encoder generated or user provided capture time AVProducerReferenceTime side data. Instead + // of letting the mov muxer generate one, do it here so we can also use it for the manifest. + prft = (AVProducerReferenceTime *)av_packet_new_side_data(pkt, AV_PKT_DATA_PRFT, + sizeof(AVProducerReferenceTime)); + if (!prft) + return AVERROR(ENOMEM); + prft->wallclock = av_gettime(); + prft->flags = 24; + } + if (os->first_pts == AV_NOPTS_VALUE) { + os->producer_reference_time = *prft; + if (c->target_latency_refid < 0) + c->target_latency_refid = pkt->stream_index; + } + + return 0; +} + static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) { DASHContext *c = s->priv_data; AVStream *st = s->streams[pkt->stream_index]; OutputStream *os = &c->streams[pkt->stream_index]; + AdaptationSet *as = &c->as[os->as_idx - 1]; int64_t seg_end_duration, elapsed_duration; int ret; @@ -1707,54 +2084,94 @@ pkt->dts = 0; } - if (os->first_pts == AV_NOPTS_VALUE) + if (c->write_prft) { + ret = dash_parse_prft(c, pkt); + if (ret < 0) + return ret; + } + + if (os->first_pts == AV_NOPTS_VALUE) { os->first_pts = pkt->pts; + } os->last_pts = pkt->pts; if (!c->availability_start_time[0]) { int64_t start_time_us = av_gettime(); c->start_time_s = start_time_us / 1000000; - format_date_now(c->availability_start_time, - sizeof(c->availability_start_time)); + format_date(c->availability_start_time, + sizeof(c->availability_start_time), start_time_us); } - if (!os->availability_time_offset && pkt->duration) { - int64_t frame_duration = av_rescale_q(pkt->duration, st->time_base, - AV_TIME_BASE_Q); - os->availability_time_offset = ((double) c->seg_duration - + if (!os->packets_written) + os->availability_time_offset = 0; + + if (!os->availability_time_offset && + ((os->frag_type == FRAG_TYPE_DURATION && os->seg_duration != os->frag_duration) || + (os->frag_type == FRAG_TYPE_EVERY_FRAME && pkt->duration))) { + AdaptationSet *as = &c->as[os->as_idx - 1]; + int64_t frame_duration = 0; + + switch (os->frag_type) { + case FRAG_TYPE_DURATION: + frame_duration = os->frag_duration; + break; + case FRAG_TYPE_EVERY_FRAME: + frame_duration = av_rescale_q(pkt->duration, st->time_base, AV_TIME_BASE_Q); + break; + } + + os->availability_time_offset = ((double) os->seg_duration - frame_duration) / AV_TIME_BASE; + as->max_frag_duration = FFMAX(frame_duration, as->max_frag_duration); } if (c->use_template && !c->use_timeline) { elapsed_duration = pkt->pts - os->first_pts; - seg_end_duration = (int64_t) os->segment_index * c->seg_duration; + seg_end_duration = (int64_t) os->segment_index * os->seg_duration; } else { elapsed_duration = pkt->pts - os->start_pts; - seg_end_duration = c->seg_duration; + seg_end_duration = os->seg_duration; } - if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && - pkt->flags & AV_PKT_FLAG_KEY && os->packets_written && - av_compare_ts(elapsed_duration, st->time_base, - seg_end_duration, AV_TIME_BASE_Q) >= 0) { - int64_t prev_duration = c->last_duration; + if (os->parser && + (os->frag_type == FRAG_TYPE_PFRAMES || + as->trick_idx >= 0)) { + // Parse the packets only in scenarios where it's needed + uint8_t *data; + int size; + av_parser_parse2(os->parser, os->parser_avctx, + &data, &size, pkt->data, pkt->size, + pkt->pts, pkt->dts, pkt->pos); - c->last_duration = av_rescale_q(pkt->pts - os->start_pts, - st->time_base, - AV_TIME_BASE_Q); - c->total_duration = av_rescale_q(pkt->pts - os->first_pts, - st->time_base, - AV_TIME_BASE_Q); + os->coding_dependency |= os->parser->pict_type != AV_PICTURE_TYPE_I; + } - if ((!c->use_timeline || !c->use_template) && prev_duration) { - if (c->last_duration < prev_duration*9/10 || - c->last_duration > prev_duration*11/10) { - av_log(s, AV_LOG_WARNING, - "Segment durations differ too much, enable use_timeline " - "and use_template, or keep a stricter keyframe interval\n"); + if (pkt->flags & AV_PKT_FLAG_KEY && os->packets_written && + av_compare_ts(elapsed_duration, st->time_base, + seg_end_duration, AV_TIME_BASE_Q) >= 0) { + if (!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + c->last_duration = av_rescale_q(pkt->pts - os->start_pts, + st->time_base, + AV_TIME_BASE_Q); + c->total_duration = av_rescale_q(pkt->pts - os->first_pts, + st->time_base, + AV_TIME_BASE_Q); + + if ((!c->use_timeline || !c->use_template) && os->last_duration) { + if (c->last_duration < os->last_duration*9/10 || + c->last_duration > os->last_duration*11/10) { + av_log(s, AV_LOG_WARNING, + "Segment durations differ too much, enable use_timeline " + "and use_template, or keep a stricter keyframe interval\n"); + } } } + if (c->write_prft && os->producer_reference_time.wallclock && !os->producer_reference_time_str[0]) + format_date(os->producer_reference_time_str, + sizeof(os->producer_reference_time_str), + os->producer_reference_time.wallclock); + if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0) return ret; } @@ -1772,11 +2189,42 @@ os->max_pts = pkt->pts + pkt->duration; else os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration); - os->packets_written++; - os->total_pkt_size += pkt->size; + + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + os->frag_type == FRAG_TYPE_PFRAMES && + os->packets_written) { + av_assert0(os->parser); + if ((os->parser->pict_type == AV_PICTURE_TYPE_P && + st->codecpar->video_delay && + !(os->last_flags & AV_PKT_FLAG_KEY)) || + pkt->flags & AV_PKT_FLAG_KEY) { + ret = av_write_frame(os->ctx, NULL); + if (ret < 0) + return ret; + + if (!os->availability_time_offset) { + int64_t frag_duration = av_rescale_q(os->total_pkt_duration, st->time_base, + AV_TIME_BASE_Q); + os->availability_time_offset = ((double) os->seg_duration - + frag_duration) / AV_TIME_BASE; + as->max_frag_duration = FFMAX(frag_duration, as->max_frag_duration); + } + } + } + + if (pkt->flags & AV_PKT_FLAG_KEY && (os->packets_written || os->nb_segments) && !os->gop_size && as->trick_idx < 0) { + os->gop_size = os->last_duration + av_rescale_q(os->total_pkt_duration, st->time_base, AV_TIME_BASE_Q); + c->max_gop_size = FFMAX(c->max_gop_size, os->gop_size); + } + if ((ret = ff_write_chained(os->ctx, 0, pkt, s, 0)) < 0) return ret; + os->packets_written++; + os->total_pkt_size += pkt->size; + os->total_pkt_duration += pkt->duration; + os->last_flags = pkt->flags; + if (!os->init_range_length) flush_init_segment(s, os); @@ -1785,6 +2233,8 @@ AVDictionary *opts = NULL; const char *proto = avio_find_protocol_name(s->url); int use_rename = proto && !strcmp(proto, "file"); + if (os->segment_type == SEGMENT_TYPE_MP4) + write_styp(os->ctx->pb); os->filename[0] = os->full_path[0] = os->temp_path[0] = '\0'; ff_dash_fill_tmpl_params(os->filename, sizeof(os->filename), os->media_seg_name, pkt->stream_index, @@ -1809,8 +2259,6 @@ if (c->streaming && os->segment_type == SEGMENT_TYPE_MP4) { int len = 0; uint8_t *buf = NULL; - if (!os->written_len) - write_styp(os->ctx->pb); avio_flush(os->ctx->pb); len = avio_get_dyn_buf (os->ctx->pb, &buf); if (os->out) { @@ -1857,7 +2305,7 @@ if (c->hls_playlist && c->master_playlist_created) { char filename[1024]; - snprintf(filename, sizeof(filename), "%smaster.m3u8", c->dirname); + snprintf(filename, sizeof(filename), "%s%s", c->dirname, c->hls_master_name); dashenc_delete_file(s, filename); } } @@ -1878,10 +2326,8 @@ if (ret == 1) { AVStream *st = s->streams[avpkt->stream_index]; AVStream *ost = oc->streams[0]; - st->internal->bsfcs = ost->internal->bsfcs; - st->internal->nb_bsfcs = ost->internal->nb_bsfcs; - ost->internal->bsfcs = NULL; - ost->internal->nb_bsfcs = 0; + st->internal->bsfc = ost->internal->bsfc; + ost->internal->bsfc = NULL; } return ret; } @@ -1898,6 +2344,12 @@ { "min_seg_duration", "minimum segment duration (in microseconds) (will be deprecated)", OFFSET(min_seg_duration), AV_OPT_TYPE_INT, { .i64 = 5000000 }, 0, INT_MAX, E }, #endif { "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration), AV_OPT_TYPE_DURATION, { .i64 = 5000000 }, 0, INT_MAX, E }, + { "frag_duration", "fragment duration (in seconds, fractional value can be set)", OFFSET(frag_duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, E }, + { "frag_type", "set type of interval for fragments", OFFSET(frag_type), AV_OPT_TYPE_INT, {.i64 = FRAG_TYPE_NONE }, 0, FRAG_TYPE_NB - 1, E, "frag_type"}, + { "none", "one fragment per segment", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_NONE }, 0, UINT_MAX, E, "frag_type"}, + { "every_frame", "fragment at every frame", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_EVERY_FRAME }, 0, UINT_MAX, E, "frag_type"}, + { "duration", "fragment at specific time intervals", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_DURATION }, 0, UINT_MAX, E, "frag_type"}, + { "pframes", "fragment at keyframes and following P-Frame reordering (Video only, experimental)", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_PFRAMES }, 0, UINT_MAX, E, "frag_type"}, { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E }, { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E }, @@ -1910,10 +2362,11 @@ { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, + { "hls_master_name", "HLS master playlist name", OFFSET(hls_master_name), AV_OPT_TYPE_STRING, {.str = "master.m3u8"}, 0, 0, E }, { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E }, { "index_correction", "Enable/Disable segment index correction logic", OFFSET(index_correction), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, - { "format_options","set list of options for the container format (mp4/webm) used for dash", OFFSET(format_options_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, + { "format_options","set list of options for the container format (mp4/webm) used for dash", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E}, { "global_sidx", "Write global SIDX atom. Applicable only for single file, mp4 output, non-streaming mode", OFFSET(global_sidx), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "dash_segment_type", "set dash segment files type", OFFSET(segment_type_option), AV_OPT_TYPE_INT, {.i64 = SEGMENT_TYPE_AUTO }, 0, SEGMENT_TYPE_NB - 1, E, "segment_type"}, { "auto", "select segment file format based on codec", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO }, 0, UINT_MAX, E, "segment_type"}, @@ -1921,7 +2374,17 @@ { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_WEBM }, 0, UINT_MAX, E, "segment_type"}, { "ignore_io_errors", "Ignore IO errors during open and write. Useful for long-duration runs with network output", OFFSET(ignore_io_errors), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "lhls", "Enable Low-latency HLS(Experimental). Adds #EXT-X-PREFETCH tag with current segment's URI", OFFSET(lhls), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, + { "ldash", "Enable Low-latency dash. Constrains the value of a few elements", OFFSET(ldash), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "master_m3u8_publish_rate", "Publish master playlist every after this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E}, + { "write_prft", "Write producer reference time element", OFFSET(write_prft), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, E}, + { "mpd_profile", "Set profiles. Elements and values used in the manifest may be constrained by them", OFFSET(profile), AV_OPT_TYPE_FLAGS, {.i64 = MPD_PROFILE_DASH }, 0, UINT_MAX, E, "mpd_profile"}, + { "dash", "MPEG-DASH ISO Base media file format live profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DASH }, 0, UINT_MAX, E, "mpd_profile"}, + { "dvb_dash", "DVB-DASH profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DVB }, 0, UINT_MAX, E, "mpd_profile"}, + { "http_opts", "HTTP protocol options", OFFSET(http_opts), AV_OPT_TYPE_DICT, { .str = NULL }, 0, 0, E }, + { "target_latency", "Set desired target latency for Low-latency dash", OFFSET(target_latency), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, E }, + { "min_playback_rate", "Set desired minimum playback rate", OFFSET(min_playback_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 1.0 }, 0.5, 1.5, E }, + { "max_playback_rate", "Set desired maximum playback rate", OFFSET(max_playback_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 1.0 }, 0.5, 1.5, E }, + { "update_period", "Set the mpd update interval", OFFSET(update_period), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E}, { NULL }, }; diff -Nru ffmpeg-4.2.2/libavformat/daudenc.c ffmpeg-4.4/libavformat/daudenc.c --- ffmpeg-4.2.2/libavformat/daudenc.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/daudenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,11 +21,11 @@ #include "avformat.h" -static int daud_write_header(struct AVFormatContext *s) +static int daud_init(struct AVFormatContext *s) { AVCodecParameters *par = s->streams[0]->codecpar; if (par->channels!=6 || par->sample_rate!=96000) - return -1; + return AVERROR(EINVAL); return 0; } @@ -34,7 +34,7 @@ if (pkt->size > 65535) { av_log(s, AV_LOG_ERROR, "Packet size too large for s302m. (%d > 65535)\n", pkt->size); - return -1; + return AVERROR_INVALIDDATA; } avio_wb16(s->pb, pkt->size); avio_wb16(s->pb, 0x8010); // unknown @@ -48,7 +48,7 @@ .extensions = "302", .audio_codec = AV_CODEC_ID_PCM_S24DAUD, .video_codec = AV_CODEC_ID_NONE, - .write_header = daud_write_header, + .init = daud_init, .write_packet = daud_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; diff -Nru ffmpeg-4.2.2/libavformat/davs2.c ffmpeg-4.4/libavformat/davs2.c --- ffmpeg-4.2.2/libavformat/davs2.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/davs2.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -/* - * AVS2 video stream probe. - * - * Copyright (C) 2018 Huiwen Ren, - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "avformat.h" -#include "rawdec.h" -#include "libavcodec/internal.h" -#include "libavutil/intreadwrite.h" - -#define ISSQH(x) ((x) == 0xB0 ) -#define ISEND(x) ((x) == 0xB1 ) -#define ISPIC(x) ((x) == 0xB3 || (x) == 0xB6) -#define ISUNIT(x) ( ISSQH(x) || ISEND(x) || (x) == 0xB2 || ISPIC(x) || (x) == 0xB5 || (x) == 0xB7 ) -#define ISAVS2(x) ((x) == 0x20 || (x) == 0x22 || (x) == 0x30 || (x) == 0x32 ) - -static int avs2_probe(const AVProbeData *p) -{ - uint32_t code= -1, hds=0, pic=0, seq=0; - uint8_t state=0; - const uint8_t *ptr = p->buf, *end = p->buf + p->buf_size, *sqb=0; - if (AV_RB32(p->buf) != 0x1B0){ - return 0; - } - - while (ptr < end) { - ptr = avpriv_find_start_code(ptr, end, &code); - state = code & 0xFF; - if ((code & 0xffffff00) == 0x100) { - if (ISUNIT(state)) { - if (sqb && !hds) { - hds = ptr - sqb; - } - if (ISSQH(state)) { - if (!ISAVS2(*ptr)) - return 0; - sqb = ptr; - seq++; - } else if (ISPIC(state)) { - pic++; - } else if (ISEND(state)) { - break; - } - } - } - } - if (seq && hds >= 21 && pic){ - return AVPROBE_SCORE_EXTENSION + 2; // more than cavs - } - - return 0; -} - -FF_DEF_RAWVIDEO_DEMUXER(avs2, "raw AVS2-P2/IEEE1857.4", avs2_probe, "avs,avs2", AV_CODEC_ID_AVS2) diff -Nru ffmpeg-4.2.2/libavformat/dcstr.c ffmpeg-4.4/libavformat/dcstr.c --- ffmpeg-4.2.2/libavformat/dcstr.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/dcstr.c 2021-04-08 21:28:40.000000000 +0000 @@ -43,6 +43,8 @@ st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->channels = avio_rl32(s->pb); st->codecpar->sample_rate = avio_rl32(s->pb); + if (st->codecpar->sample_rate <= 0) + return AVERROR_INVALIDDATA; codec = avio_rl32(s->pb); align = avio_rl32(s->pb); avio_skip(s->pb, 4); diff -Nru ffmpeg-4.2.2/libavformat/derf.c ffmpeg-4.4/libavformat/derf.c --- ffmpeg-4.2.2/libavformat/derf.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/derf.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * DERF demuxer + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "internal.h" +#include "pcm.h" + +static int derf_probe(const AVProbeData *p) +{ + if (AV_RL32(p->buf) != MKTAG('D','E','R','F')) + return 0; + if (AV_RL32(p->buf+4) != 1 && AV_RL32(p->buf+4) != 2) + return 0; + + return AVPROBE_SCORE_MAX / 3 * 2; +} + +static int derf_read_header(AVFormatContext *s) +{ + unsigned data_size; + AVIOContext *pb = s->pb; + AVCodecParameters *par; + AVStream *st; + + avio_skip(pb, 4); + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = AV_CODEC_ID_DERF_DPCM; + par->format = AV_SAMPLE_FMT_S16; + par->channels = avio_rl32(pb); + if (par->channels != 1 && par->channels != 2) + return AVERROR_INVALIDDATA; + if (par->channels == 1) + par->channel_layout = AV_CH_LAYOUT_MONO; + else if (par->channels == 2) + par->channel_layout = AV_CH_LAYOUT_STEREO; + data_size = avio_rl32(pb); + st->duration = data_size / par->channels; + par->sample_rate = 22050; + par->block_align = 1; + + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + + return 0; +} + +AVInputFormat ff_derf_demuxer = { + .name = "derf", + .long_name = NULL_IF_CONFIG_SMALL("Xilam DERF"), + .read_probe = derf_probe, + .read_header = derf_read_header, + .read_packet = ff_pcm_read_packet, + .read_seek = ff_pcm_read_seek, + .extensions = "adp", +}; diff -Nru ffmpeg-4.2.2/libavformat/dfa.c ffmpeg-4.4/libavformat/dfa.c --- ffmpeg-4.2.2/libavformat/dfa.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/dfa.c 2020-07-11 10:39:30.000000000 +0000 @@ -40,7 +40,7 @@ { AVIOContext *pb = s->pb; AVStream *st; - int frames; + int frames, ret; int version; uint32_t mspf; @@ -69,8 +69,8 @@ avio_skip(pb, 128 - 16); // padding st->duration = frames; - if (ff_alloc_extradata(st->codecpar, 2)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 2)) < 0) + return ret; AV_WL16(st->codecpar->extradata, version); if (version == 0x100) st->sample_aspect_ratio = (AVRational){2, 1}; @@ -93,7 +93,6 @@ if (!first) { ret = av_append_packet(pb, pkt, 12); if (ret < 0) { - av_packet_unref(pkt); return ret; } } else @@ -101,7 +100,6 @@ frame_size = AV_RL32(pkt->data + pkt->size - 8); if (frame_size > INT_MAX - 4) { av_log(s, AV_LOG_ERROR, "Too large chunk size: %"PRIu32"\n", frame_size); - av_packet_unref(pkt); return AVERROR(EIO); } if (AV_RL32(pkt->data + pkt->size - 12) == MKTAG('E', 'O', 'F', 'R')) { @@ -115,7 +113,6 @@ } ret = av_append_packet(pb, pkt, frame_size); if (ret < 0) { - av_packet_unref(pkt); return ret; } } diff -Nru ffmpeg-4.2.2/libavformat/dhav.c ffmpeg-4.4/libavformat/dhav.c --- ffmpeg-4.2.2/libavformat/dhav.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/dhav.c 2021-04-08 21:28:40.000000000 +0000 @@ -39,6 +39,8 @@ int audio_channels; int audio_codec; int sample_rate; + int64_t last_good_pos; + int64_t duration; int video_stream_index; int audio_stream_index; @@ -46,6 +48,7 @@ typedef struct DHAVStream { int64_t last_timestamp; + int64_t last_time; int64_t pts; } DHAVStream; @@ -65,61 +68,6 @@ return 0; } -static int dhav_read_header(AVFormatContext *s) -{ - DHAVContext *dhav = s->priv_data; - uint8_t signature[5]; - - ffio_ensure_seekback(s->pb, 5); - avio_read(s->pb, signature, sizeof(signature)); - if (!memcmp(signature, "DAHUA", 5)) - avio_skip(s->pb, 0x400 - 5); - else - avio_seek(s->pb, -5, SEEK_CUR); - - s->ctx_flags |= AVFMTCTX_NOHEADER; - dhav->video_stream_index = -1; - dhav->audio_stream_index = -1; - - return 0; -} - -static int64_t get_pts(AVFormatContext *s, DHAVStream *st) -{ - DHAVContext *dhav = s->priv_data; - /* - int year, month, day, hour, min, sec; - struct tm timeinfo; - - sec = dhav->date & 0x3F; - min = (dhav->date >> 6) & 0x3F; - hour = (dhav->date >> 12) & 0x1F; - day = (dhav->date >> 17) & 0x1F; - month = (dhav->date >> 22) & 0x0F; - year = ((dhav->date >> 26) & 0x3F) + 2000; - - timeinfo.tm_year = year - 1900; - timeinfo.tm_mon = month - 1; - timeinfo.tm_mday = day; - timeinfo.tm_hour = hour; - timeinfo.tm_min = min; - timeinfo.tm_sec = sec;*/ - - if (st->last_timestamp == AV_NOPTS_VALUE) { - st->last_timestamp = dhav->timestamp; - } - - if (st->last_timestamp <= dhav->timestamp) { - st->pts += dhav->timestamp - st->last_timestamp; - } else { - st->pts += 65535 + dhav->timestamp - st->last_timestamp; - } - - st->last_timestamp = dhav->timestamp; - - return st->pts; -} - static const uint32_t sample_rates[] = { 8000, 4000, 8000, 11025, 16000, 20000, 22050, 32000, 44100, 48000, @@ -129,26 +77,26 @@ static int parse_ext(AVFormatContext *s, int length) { DHAVContext *dhav = s->priv_data; - int index; + int index, ret = 0; while (length > 0) { int type = avio_r8(s->pb); switch (type) { case 0x80: - avio_skip(s->pb, 1); + ret = avio_skip(s->pb, 1); dhav->width = 8 * avio_r8(s->pb); dhav->height = 8 * avio_r8(s->pb); length -= 4; break; case 0x81: - avio_skip(s->pb, 1); + ret = avio_skip(s->pb, 1); dhav->video_codec = avio_r8(s->pb); dhav->frame_rate = avio_r8(s->pb); length -= 4; break; case 0x82: - avio_skip(s->pb, 3); + ret = avio_skip(s->pb, 3); dhav->width = avio_rl16(s->pb); dhav->height = avio_rl16(s->pb); length -= 8; @@ -165,11 +113,11 @@ length -= 4; break; case 0x88: - avio_skip(s->pb, 7); + ret = avio_skip(s->pb, 7); length -= 8; break; case 0x8c: - avio_skip(s->pb, 1); + ret = avio_skip(s->pb, 1); dhav->audio_channels = avio_r8(s->pb); dhav->audio_codec = avio_r8(s->pb); index = avio_r8(s->pb); @@ -178,7 +126,7 @@ } else { dhav->sample_rate = 8000; } - avio_skip(s->pb, 3); + ret = avio_skip(s->pb, 3); length -= 8; break; case 0x91: @@ -188,7 +136,7 @@ case 0x9a: case 0x9b: // sample aspect ratio case 0xb3: - avio_skip(s->pb, 7); + ret = avio_skip(s->pb, 7); length -= 8; break; case 0x84: @@ -199,14 +147,17 @@ case 0xa0: case 0xb2: case 0xb4: - avio_skip(s->pb, 3); + ret = avio_skip(s->pb, 3); length -= 4; break; default: av_log(s, AV_LOG_INFO, "Unknown type: %X, skipping rest of header.\n", type); - avio_skip(s->pb, length - 1); + ret = avio_skip(s->pb, length - 1); length = 0; } + + if (ret < 0) + return ret; } return 0; @@ -215,33 +166,35 @@ static int read_chunk(AVFormatContext *s) { DHAVContext *dhav = s->priv_data; - unsigned frame_length, ext_length; + int frame_length, ext_length; int64_t start, end; int ret; - start = avio_tell(s->pb); - if (avio_feof(s->pb)) return AVERROR_EOF; - if (avio_rl32(s->pb) != MKTAG('D','H','A','V')) - return AVERROR_INVALIDDATA; + while (avio_r8(s->pb) != 'D' || avio_r8(s->pb) != 'H' || avio_r8(s->pb) != 'A' || avio_r8(s->pb) != 'V') { + if (avio_feof(s->pb)) + return AVERROR_EOF; + } + start = avio_tell(s->pb) - 4; + dhav->last_good_pos = start; dhav->type = avio_r8(s->pb); dhav->subtype = avio_r8(s->pb); dhav->channel = avio_r8(s->pb); dhav->frame_subnumber = avio_r8(s->pb); dhav->frame_number = avio_rl32(s->pb); frame_length = avio_rl32(s->pb); + dhav->date = avio_rl32(s->pb); if (frame_length < 24) return AVERROR_INVALIDDATA; if (dhav->type == 0xf1) { - avio_skip(s->pb, frame_length - 16); - return 0; + ret = avio_skip(s->pb, frame_length - 20); + return ret < 0 ? ret : 0; } - dhav->date = avio_rl32(s->pb); dhav->timestamp = avio_rl16(s->pb); ext_length = avio_r8(s->pb); avio_skip(s->pb, 1); // checksum @@ -255,14 +208,129 @@ return frame_length - 8 - (end - start); } -static int dhav_read_packet(AVFormatContext *s, AVPacket *pkt) +static void get_timeinfo(unsigned date, struct tm *timeinfo) +{ + int year, month, day, hour, min, sec; + + sec = date & 0x3F; + min = (date >> 6) & 0x3F; + hour = (date >> 12) & 0x1F; + day = (date >> 17) & 0x1F; + month = (date >> 22) & 0x0F; + year = ((date >> 26) & 0x3F) + 2000; + + timeinfo->tm_year = year - 1900; + timeinfo->tm_mon = month - 1; + timeinfo->tm_mday = day; + timeinfo->tm_hour = hour; + timeinfo->tm_min = min; + timeinfo->tm_sec = sec; +} + +static int64_t get_duration(AVFormatContext *s) { DHAVContext *dhav = s->priv_data; - int64_t start; - int ret; + int64_t start_pos = avio_tell(s->pb); + int64_t start = 0, end = 0; + struct tm timeinfo; - start = avio_tell(s->pb); + if (!s->pb->seekable) + return 0; + avio_seek(s->pb, avio_size(s->pb) - 8, SEEK_SET); + if (avio_rl32(s->pb) == MKTAG('d','h','a','v')) { + int seek_back = avio_rl32(s->pb); + + avio_seek(s->pb, -seek_back, SEEK_CUR); + read_chunk(s); + get_timeinfo(dhav->date, &timeinfo); + end = av_timegm(&timeinfo) * 1000LL; + } else { + avio_seek(s->pb, start_pos, SEEK_SET); + return 0; + } + + avio_seek(s->pb, start_pos, SEEK_SET); + + read_chunk(s); + get_timeinfo(dhav->date, &timeinfo); + start = av_timegm(&timeinfo) * 1000LL; + + avio_seek(s->pb, start_pos, SEEK_SET); + + return end - start; +} + +static int dhav_read_header(AVFormatContext *s) +{ + DHAVContext *dhav = s->priv_data; + uint8_t signature[5]; + + ffio_ensure_seekback(s->pb, 5); + avio_read(s->pb, signature, sizeof(signature)); + if (!memcmp(signature, "DAHUA", 5)) { + avio_skip(s->pb, 0x400 - 5); + dhav->last_good_pos = avio_tell(s->pb); + } else { + if (!memcmp(signature, "DHAV", 4)) { + avio_seek(s->pb, -5, SEEK_CUR); + dhav->last_good_pos = avio_tell(s->pb); + } else if (s->pb->seekable) { + avio_seek(s->pb, avio_size(s->pb) - 8, SEEK_SET); + while (avio_rl32(s->pb) == MKTAG('d','h','a','v')) { + int seek_back; + + seek_back = avio_rl32(s->pb) + 8; + if (seek_back < 9) + break; + dhav->last_good_pos = avio_tell(s->pb); + avio_seek(s->pb, -seek_back, SEEK_CUR); + } + avio_seek(s->pb, dhav->last_good_pos, SEEK_SET); + } + } + + dhav->duration = get_duration(s); + dhav->last_good_pos = avio_tell(s->pb); + s->ctx_flags |= AVFMTCTX_NOHEADER; + dhav->video_stream_index = -1; + dhav->audio_stream_index = -1; + + return 0; +} + +static int64_t get_pts(AVFormatContext *s, int stream_index) +{ + DHAVStream *dst = s->streams[stream_index]->priv_data; + DHAVContext *dhav = s->priv_data; + struct tm timeinfo; + time_t t; + + get_timeinfo(dhav->date, &timeinfo); + + t = av_timegm(&timeinfo); + if (dst->last_time == t) { + int64_t diff = dhav->timestamp - dst->last_timestamp; + + if (diff < 0) + diff += 65535; + dst->pts += diff; + } else { + dst->pts = t * 1000LL; + } + + dst->last_time = t; + dst->last_timestamp = dhav->timestamp; + + return dst->pts; +} + +static int dhav_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + DHAVContext *dhav = s->priv_data; + int size, ret, stream_index; + +retry: while ((ret = read_chunk(s)) == 0) ; @@ -284,8 +352,9 @@ case 0x4: case 0x8: st->codecpar->codec_id = AV_CODEC_ID_H264; break; case 0xc: st->codecpar->codec_id = AV_CODEC_ID_HEVC; break; - default: avpriv_request_sample(s, "Unknown video codec %X\n", dhav->video_codec); + default: avpriv_request_sample(s, "Unknown video codec %X", dhav->video_codec); } + st->duration = dhav->duration; st->codecpar->width = dhav->width; st->codecpar->height = dhav->height; st->avg_frame_rate.num = dhav->frame_rate; @@ -293,7 +362,7 @@ st->priv_data = dst = av_mallocz(sizeof(DHAVStream)); if (!st->priv_data) return AVERROR(ENOMEM); - dst->last_timestamp = AV_NOPTS_VALUE; + dst->last_time = AV_NOPTS_VALUE; dhav->video_stream_index = st->index; avpriv_set_pts_info(st, 64, 1, 1000); @@ -316,32 +385,41 @@ case 0x1f: st->codecpar->codec_id = AV_CODEC_ID_MP2; break; case 0x21: st->codecpar->codec_id = AV_CODEC_ID_MP3; break; case 0x0d: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_MS; break; - default: avpriv_request_sample(s, "Unknown audio codec %X\n", dhav->audio_codec); + default: avpriv_request_sample(s, "Unknown audio codec %X", dhav->audio_codec); } + st->duration = dhav->duration; st->codecpar->channels = dhav->audio_channels; st->codecpar->sample_rate = dhav->sample_rate; st->priv_data = dst = av_mallocz(sizeof(DHAVStream)); if (!st->priv_data) return AVERROR(ENOMEM); - dst->last_timestamp = AV_NOPTS_VALUE; + dst->last_time = AV_NOPTS_VALUE; dhav->audio_stream_index = st->index; avpriv_set_pts_info(st, 64, 1, 1000); } - ret = av_get_packet(s->pb, pkt, ret); + stream_index = dhav->type == 0xf0 ? dhav->audio_stream_index : dhav->video_stream_index; + if (stream_index < 0) { + avio_skip(s->pb, ret); + if (avio_rl32(s->pb) == MKTAG('d','h','a','v')) + avio_skip(s->pb, 4); + goto retry; + } + + size = ret; + ret = av_get_packet(s->pb, pkt, size); if (ret < 0) return ret; - pkt->stream_index = dhav->type == 0xf0 ? dhav->audio_stream_index : dhav->video_stream_index; + pkt->stream_index = stream_index; if (dhav->type != 0xfc) pkt->flags |= AV_PKT_FLAG_KEY; - if (pkt->stream_index >= 0) - pkt->pts = get_pts(s, s->streams[pkt->stream_index]->priv_data); pkt->duration = 1; - pkt->pos = start; - if (avio_rl32(s->pb) != MKTAG('d','h','a','v')) - return AVERROR_INVALIDDATA; - avio_skip(s->pb, 4); + if (pkt->stream_index >= 0) + pkt->pts = get_pts(s, pkt->stream_index); + pkt->pos = dhav->last_good_pos; + if (avio_rl32(s->pb) == MKTAG('d','h','a','v')) + avio_skip(s->pb, 4); return ret; } @@ -349,6 +427,7 @@ static int dhav_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { + DHAVContext *dhav = s->priv_data; AVStream *st = s->streams[stream_index]; int index = av_index_search_timestamp(st, timestamp, flags); int64_t pts; @@ -365,8 +444,9 @@ DHAVStream *dst = st->priv_data; dst->pts = pts; - dst->last_timestamp = AV_NOPTS_VALUE; + dst->last_time = AV_NOPTS_VALUE; } + dhav->last_good_pos = avio_tell(s->pb); return 0; } @@ -380,5 +460,5 @@ .read_packet = dhav_read_packet, .read_seek = dhav_read_seek, .extensions = "dav", - .flags = AVFMT_GENERIC_INDEX | AVFMT_NO_BYTE_SEEK, + .flags = AVFMT_GENERIC_INDEX | AVFMT_NO_BYTE_SEEK | AVFMT_TS_DISCONT | AVFMT_TS_NONSTRICT, }; diff -Nru ffmpeg-4.2.2/libavformat/dsfdec.c ffmpeg-4.4/libavformat/dsfdec.c --- ffmpeg-4.2.2/libavformat/dsfdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/dsfdec.c 2021-02-20 20:27:47.000000000 +0000 @@ -56,8 +56,8 @@ ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, 0); if (id3v2_extra_meta) { - ff_id3v2_parse_apic(s, &id3v2_extra_meta); - ff_id3v2_parse_chapters(s, &id3v2_extra_meta); + ff_id3v2_parse_apic(s, id3v2_extra_meta); + ff_id3v2_parse_chapters(s, id3v2_extra_meta); } ff_id3v2_free_extra_meta(&id3v2_extra_meta); } @@ -124,12 +124,13 @@ dsf->audio_size = avio_rl64(pb) / 8 * st->codecpar->channels; st->codecpar->block_align = avio_rl32(pb); - if (st->codecpar->block_align > INT_MAX / st->codecpar->channels) { - avpriv_request_sample(s, "block_align overflow"); + if (st->codecpar->block_align > INT_MAX / st->codecpar->channels || st->codecpar->block_align <= 0) { + avpriv_request_sample(s, "block_align invalid"); return AVERROR_INVALIDDATA; } st->codecpar->block_align *= st->codecpar->channels; st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * 8LL; + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); avio_skip(pb, 4); /* data chunk */ @@ -150,11 +151,11 @@ AVIOContext *pb = s->pb; AVStream *st = s->streams[0]; int64_t pos = avio_tell(pb); + int ret; if (pos >= dsf->data_end) return AVERROR_EOF; - pkt->stream_index = 0; if (dsf->data_size > dsf->audio_size) { int last_packet = pos == (dsf->data_end - st->codecpar->block_align); @@ -168,8 +169,8 @@ if (packet_size <= 0 || skip_size <= 0) return AVERROR_INVALIDDATA; - if (av_new_packet(pkt, packet_size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, packet_size)) < 0) + return ret; dst = pkt->data; for (ch = 0; ch < st->codecpar->channels; ch++) { ret = avio_read(pb, dst, packet_size / st->codecpar->channels); @@ -180,10 +181,22 @@ avio_skip(pb, skip_size / st->codecpar->channels); } + pkt->pos = pos; + pkt->stream_index = 0; + pkt->pts = (pos - s->internal->data_offset) / st->codecpar->channels; + pkt->duration = packet_size / st->codecpar->channels; return 0; } } - return av_get_packet(pb, pkt, FFMIN(dsf->data_end - pos, st->codecpar->block_align)); + ret = av_get_packet(pb, pkt, FFMIN(dsf->data_end - pos, st->codecpar->block_align)); + if (ret < 0) + return ret; + + pkt->stream_index = 0; + pkt->pts = (pos - s->internal->data_offset) / st->codecpar->channels; + pkt->duration = st->codecpar->block_align / st->codecpar->channels; + + return 0; } AVInputFormat ff_dsf_demuxer = { diff -Nru ffmpeg-4.2.2/libavformat/dsicin.c ffmpeg-4.4/libavformat/dsicin.c --- ffmpeg-4.2.2/libavformat/dsicin.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/dsicin.c 2020-07-11 10:39:30.000000000 +0000 @@ -200,7 +200,6 @@ ret = avio_read(pb, &pkt->data[4], pkt_size); if (ret < 0) { - av_packet_unref(pkt); return ret; } if (ret < pkt_size) diff -Nru ffmpeg-4.2.2/libavformat/dss.c ffmpeg-4.4/libavformat/dss.c --- ffmpeg-4.2.2/libavformat/dss.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/dss.c 2021-04-08 21:28:40.000000000 +0000 @@ -19,8 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/attributes.h" -#include "libavutil/bswap.h" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" @@ -52,7 +50,7 @@ int counter; int swap; int dss_sp_swap_byte; - int8_t *dss_sp_buf; + int8_t dss_sp_buf[DSS_FRAME_SIZE + 1]; int packet_size; int dss_header_size; @@ -105,15 +103,11 @@ ret = avio_read(s->pb, value, size); if (ret < size) { - ret = ret < 0 ? ret : AVERROR_EOF; - goto exit; + av_free(value); + return ret < 0 ? ret : AVERROR_EOF; } - ret = av_dict_set(&s->metadata, key, value, 0); - -exit: - av_free(value); - return ret; + return av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); } static int dss_read_header(AVFormatContext *s) @@ -174,10 +168,6 @@ ctx->counter = 0; ctx->swap = 0; - ctx->dss_sp_buf = av_malloc(DSS_FRAME_SIZE + 1); - if (!ctx->dss_sp_buf) - return AVERROR(ENOMEM); - return 0; } @@ -229,7 +219,6 @@ } else read_size = DSS_FRAME_SIZE; - ctx->counter -= read_size; ctx->packet_size = DSS_FRAME_SIZE - 1; ret = av_new_packet(pkt, DSS_FRAME_SIZE); @@ -241,17 +230,16 @@ pkt->stream_index = 0; s->bit_rate = 8LL * ctx->packet_size * st->codecpar->sample_rate * 512 / (506 * pkt->duration); - if (ctx->counter < 0) { - int size2 = ctx->counter + read_size; - - ret = avio_read(s->pb, ctx->dss_sp_buf + offset + buff_offset, - size2 - offset); - if (ret < size2 - offset) + if (ctx->counter < read_size) { + ret = avio_read(s->pb, ctx->dss_sp_buf + buff_offset, + ctx->counter); + if (ret < ctx->counter) goto error_eof; + offset = ctx->counter; dss_skip_audio_header(s, pkt); - offset = size2; } + ctx->counter -= read_size; ret = avio_read(s->pb, ctx->dss_sp_buf + offset + buff_offset, read_size - offset); @@ -261,14 +249,12 @@ dss_sp_byte_swap(ctx, pkt->data, ctx->dss_sp_buf); if (ctx->dss_sp_swap_byte < 0) { - ret = AVERROR(EAGAIN); - goto error_eof; + return AVERROR(EAGAIN); } return pkt->size; error_eof: - av_packet_unref(pkt); return ret < 0 ? ret : AVERROR_EOF; } @@ -290,7 +276,7 @@ size = frame_size[byte & 3]; ctx->packet_size = size; - ctx->counter -= size; + ctx->counter--; ret = av_new_packet(pkt, size); if (ret < 0) @@ -300,29 +286,26 @@ pkt->data[0] = byte; offset = 1; pkt->duration = 240; - s->bit_rate = 8LL * size * st->codecpar->sample_rate * 512 / (506 * pkt->duration); + s->bit_rate = 8LL * size-- * st->codecpar->sample_rate * 512 / (506 * pkt->duration); pkt->stream_index = 0; - if (ctx->counter < 0) { - int size2 = ctx->counter + size; - + if (ctx->counter < size) { ret = avio_read(s->pb, pkt->data + offset, - size2 - offset); - if (ret < size2 - offset) { - av_packet_unref(pkt); + ctx->counter); + if (ret < ctx->counter) return ret < 0 ? ret : AVERROR_EOF; - } + offset += ctx->counter; + size -= ctx->counter; + ctx->counter = 0; dss_skip_audio_header(s, pkt); - offset = size2; } + ctx->counter -= size; - ret = avio_read(s->pb, pkt->data + offset, size - offset); - if (ret < size - offset) { - av_packet_unref(pkt); + ret = avio_read(s->pb, pkt->data + offset, size); + if (ret < size) return ret < 0 ? ret : AVERROR_EOF; - } return pkt->size; } @@ -337,15 +320,6 @@ return dss_723_1_read_packet(s, pkt); } -static int dss_read_close(AVFormatContext *s) -{ - DSSDemuxContext *ctx = s->priv_data; - - av_freep(&ctx->dss_sp_buf); - - return 0; -} - static int dss_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { @@ -392,7 +366,6 @@ .read_probe = dss_probe, .read_header = dss_read_header, .read_packet = dss_read_packet, - .read_close = dss_read_close, .read_seek = dss_read_seek, .extensions = "dss" }; diff -Nru ffmpeg-4.2.2/libavformat/dtsdec.c ffmpeg-4.4/libavformat/dtsdec.c --- ffmpeg-4.2.2/libavformat/dtsdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/dtsdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -37,6 +37,7 @@ int exss_markers = 0, exss_nextpos = 0; int sum, max, pos, ret, i; int64_t diff = 0; + int diffcount = 1; uint8_t hdr[DCA_CORE_FRAME_HEADER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE] = { 0 }; for (pos = FFMIN(4096, p->buf_size); pos < p->buf_size - 2; pos += 2) { @@ -47,8 +48,12 @@ bufp = buf = p->buf + pos; state = (state << 16) | bytestream_get_be16(&bufp); - if (pos >= 4) - diff += FFABS(((int16_t)AV_RL16(buf)) - (int16_t)AV_RL16(buf-4)); + if (pos >= 4) { + if (AV_RL16(buf) || AV_RL16(buf-4)) { + diff += FFABS(((int16_t)AV_RL16(buf)) - (int16_t)AV_RL16(buf-4)); + diffcount ++; + } + } /* extension substream (EXSS) */ if (state == DCA_SYNCWORD_SUBSTREAM) { @@ -121,7 +126,7 @@ if (markers[max] > 3 && p->buf_size / markers[max] < 32*1024 && markers[max] * 4 > sum * 3 && - diff / p->buf_size > 200) + diff / diffcount > 600) return AVPROBE_SCORE_EXTENSION + 1; return 0; diff -Nru ffmpeg-4.2.2/libavformat/dump.c ffmpeg-4.4/libavformat/dump.c --- ffmpeg-4.2.2/libavformat/dump.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/dump.c 2021-04-08 21:28:40.000000000 +0000 @@ -27,12 +27,14 @@ #include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "libavutil/mastering_display_metadata.h" +#include "libavutil/dovi_meta.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "libavutil/avstring.h" #include "libavutil/replaygain.h" #include "libavutil/spherical.h" #include "libavutil/stereo3d.h" +#include "libavutil/timecode.h" #include "avformat.h" @@ -130,10 +132,10 @@ av_log(NULL, AV_LOG_INFO, "%1.0fk %s", d / 1000, postfix); } -static void dump_metadata(void *ctx, AVDictionary *m, const char *indent) +static void dump_metadata(void *ctx, const AVDictionary *m, const char *indent) { if (m && !(av_dict_count(m) == 1 && av_dict_get(m, "language", NULL, 0))) { - AVDictionaryEntry *tag = NULL; + const AVDictionaryEntry *tag = NULL; av_log(ctx, AV_LOG_INFO, "%sMetadata:\n", indent); while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) @@ -157,7 +159,7 @@ } /* param change side data*/ -static void dump_paramchange(void *ctx, AVPacketSideData *sd) +static void dump_paramchange(void *ctx, const AVPacketSideData *sd) { int size = sd->size; const uint8_t *data = sd->data; @@ -210,7 +212,7 @@ return; fail: - av_log(ctx, AV_LOG_INFO, "unknown param"); + av_log(ctx, AV_LOG_ERROR, "unknown param\n"); } /* replaygain side data*/ @@ -234,15 +236,15 @@ av_log(ctx, AV_LOG_INFO, ", "); } -static void dump_replaygain(void *ctx, AVPacketSideData *sd) +static void dump_replaygain(void *ctx, const AVPacketSideData *sd) { - AVReplayGain *rg; + const AVReplayGain *rg; if (sd->size < sizeof(*rg)) { - av_log(ctx, AV_LOG_INFO, "invalid data"); + av_log(ctx, AV_LOG_ERROR, "invalid data\n"); return; } - rg = (AVReplayGain*)sd->data; + rg = (const AVReplayGain *)sd->data; print_gain(ctx, "track gain", rg->track_gain); print_peak(ctx, "track peak", rg->track_peak); @@ -250,16 +252,16 @@ print_peak(ctx, "album peak", rg->album_peak); } -static void dump_stereo3d(void *ctx, AVPacketSideData *sd) +static void dump_stereo3d(void *ctx, const AVPacketSideData *sd) { - AVStereo3D *stereo; + const AVStereo3D *stereo; if (sd->size < sizeof(*stereo)) { - av_log(ctx, AV_LOG_INFO, "invalid data"); + av_log(ctx, AV_LOG_ERROR, "invalid data\n"); return; } - stereo = (AVStereo3D *)sd->data; + stereo = (const AVStereo3D *)sd->data; av_log(ctx, AV_LOG_INFO, "%s", av_stereo3d_type_name(stereo->type)); @@ -267,12 +269,12 @@ av_log(ctx, AV_LOG_INFO, " (inverted)"); } -static void dump_audioservicetype(void *ctx, AVPacketSideData *sd) +static void dump_audioservicetype(void *ctx, const AVPacketSideData *sd) { - enum AVAudioServiceType *ast = (enum AVAudioServiceType *)sd->data; + const enum AVAudioServiceType *ast = (const enum AVAudioServiceType *)sd->data; if (sd->size < sizeof(*ast)) { - av_log(ctx, AV_LOG_INFO, "invalid data"); + av_log(ctx, AV_LOG_ERROR, "invalid data\n"); return; } @@ -310,24 +312,33 @@ } } -static void dump_cpb(void *ctx, AVPacketSideData *sd) +static void dump_cpb(void *ctx, const AVPacketSideData *sd) { - AVCPBProperties *cpb = (AVCPBProperties *)sd->data; + const AVCPBProperties *cpb = (const AVCPBProperties *)sd->data; if (sd->size < sizeof(*cpb)) { - av_log(ctx, AV_LOG_INFO, "invalid data"); + av_log(ctx, AV_LOG_ERROR, "invalid data\n"); return; } av_log(ctx, AV_LOG_INFO, - "bitrate max/min/avg: %d/%d/%d buffer size: %d vbv_delay: %"PRId64, +#if FF_API_UNSANITIZED_BITRATES + "bitrate max/min/avg: %d/%d/%d buffer size: %d ", +#else + "bitrate max/min/avg: %"PRId64"/%"PRId64"/%"PRId64" buffer size: %d ", +#endif cpb->max_bitrate, cpb->min_bitrate, cpb->avg_bitrate, - cpb->buffer_size, - cpb->vbv_delay); + cpb->buffer_size); + if (cpb->vbv_delay == UINT64_MAX) + av_log(ctx, AV_LOG_INFO, "vbv_delay: N/A"); + else + av_log(ctx, AV_LOG_INFO, "vbv_delay: %"PRIu64"", cpb->vbv_delay); } -static void dump_mastering_display_metadata(void *ctx, AVPacketSideData* sd) { - AVMasteringDisplayMetadata* metadata = (AVMasteringDisplayMetadata*)sd->data; +static void dump_mastering_display_metadata(void *ctx, const AVPacketSideData *sd) +{ + const AVMasteringDisplayMetadata *metadata = + (const AVMasteringDisplayMetadata *)sd->data; av_log(ctx, AV_LOG_INFO, "Mastering Display Metadata, " "has_primaries:%d has_luminance:%d " "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f) " @@ -343,21 +354,23 @@ av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance)); } -static void dump_content_light_metadata(void *ctx, AVPacketSideData* sd) +static void dump_content_light_metadata(void *ctx, const AVPacketSideData *sd) { - AVContentLightMetadata* metadata = (AVContentLightMetadata*)sd->data; + const AVContentLightMetadata *metadata = + (const AVContentLightMetadata *)sd->data; av_log(ctx, AV_LOG_INFO, "Content Light Level Metadata, " "MaxCLL=%d, MaxFALL=%d", metadata->MaxCLL, metadata->MaxFALL); } -static void dump_spherical(void *ctx, AVCodecParameters *par, AVPacketSideData *sd) +static void dump_spherical(void *ctx, const AVCodecParameters *par, + const AVPacketSideData *sd) { - AVSphericalMapping *spherical = (AVSphericalMapping *)sd->data; + const AVSphericalMapping *spherical = (const AVSphericalMapping *)sd->data; double yaw, pitch, roll; if (sd->size < sizeof(*spherical)) { - av_log(ctx, AV_LOG_INFO, "invalid data"); + av_log(ctx, AV_LOG_ERROR, "invalid data\n"); return; } @@ -380,7 +393,38 @@ } } -static void dump_sidedata(void *ctx, AVStream *st, const char *indent) +static void dump_dovi_conf(void *ctx, const AVPacketSideData *sd) +{ + const AVDOVIDecoderConfigurationRecord *dovi = + (const AVDOVIDecoderConfigurationRecord *)sd->data; + + av_log(ctx, AV_LOG_INFO, "version: %d.%d, profile: %d, level: %d, " + "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d", + 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); +} + +static void dump_s12m_timecode(void *ctx, const AVStream *st, const AVPacketSideData *sd) +{ + const uint32_t *tc = (const uint32_t *)sd->data; + + if ((sd->size != sizeof(uint32_t) * 4) || (tc[0] > 3)) { + av_log(ctx, AV_LOG_ERROR, "invalid data\n"); + return; + } + + for (int j = 1; j <= tc[0]; j++) { + char tcbuf[AV_TIMECODE_STR_SIZE]; + av_timecode_make_smpte_tc_string2(tcbuf, st->avg_frame_rate, tc[j], 0, 0); + av_log(ctx, AV_LOG_INFO, "timecode - %s%s", tcbuf, j != tc[0] ? ", " : ""); + } +} + +static void dump_sidedata(void *ctx, const AVStream *st, const char *indent) { int i; @@ -388,10 +432,10 @@ av_log(ctx, AV_LOG_INFO, "%sSide data:\n", indent); for (i = 0; i < st->nb_side_data; i++) { - AVPacketSideData sd = st->side_data[i]; + const AVPacketSideData *sd = &st->side_data[i]; av_log(ctx, AV_LOG_INFO, "%s ", indent); - switch (sd.type) { + switch (sd->type) { case AV_PKT_DATA_PALETTE: av_log(ctx, AV_LOG_INFO, "palette"); break; @@ -400,48 +444,59 @@ break; case AV_PKT_DATA_PARAM_CHANGE: av_log(ctx, AV_LOG_INFO, "paramchange: "); - dump_paramchange(ctx, &sd); + dump_paramchange(ctx, sd); break; case AV_PKT_DATA_H263_MB_INFO: av_log(ctx, AV_LOG_INFO, "H.263 macroblock info"); break; case AV_PKT_DATA_REPLAYGAIN: av_log(ctx, AV_LOG_INFO, "replaygain: "); - dump_replaygain(ctx, &sd); + dump_replaygain(ctx, sd); break; case AV_PKT_DATA_DISPLAYMATRIX: av_log(ctx, AV_LOG_INFO, "displaymatrix: rotation of %.2f degrees", - av_display_rotation_get((int32_t *)sd.data)); + av_display_rotation_get((const int32_t *)sd->data)); break; case AV_PKT_DATA_STEREO3D: av_log(ctx, AV_LOG_INFO, "stereo3d: "); - dump_stereo3d(ctx, &sd); + dump_stereo3d(ctx, sd); break; case AV_PKT_DATA_AUDIO_SERVICE_TYPE: av_log(ctx, AV_LOG_INFO, "audio service type: "); - dump_audioservicetype(ctx, &sd); + dump_audioservicetype(ctx, sd); break; case AV_PKT_DATA_QUALITY_STATS: av_log(ctx, AV_LOG_INFO, "quality factor: %"PRId32", pict_type: %c", - AV_RL32(sd.data), av_get_picture_type_char(sd.data[4])); + AV_RL32(sd->data), av_get_picture_type_char(sd->data[4])); break; case AV_PKT_DATA_CPB_PROPERTIES: av_log(ctx, AV_LOG_INFO, "cpb: "); - dump_cpb(ctx, &sd); + dump_cpb(ctx, sd); break; case AV_PKT_DATA_MASTERING_DISPLAY_METADATA: - dump_mastering_display_metadata(ctx, &sd); + dump_mastering_display_metadata(ctx, sd); break; case AV_PKT_DATA_SPHERICAL: av_log(ctx, AV_LOG_INFO, "spherical: "); - dump_spherical(ctx, st->codecpar, &sd); + dump_spherical(ctx, st->codecpar, sd); break; case AV_PKT_DATA_CONTENT_LIGHT_LEVEL: - dump_content_light_metadata(ctx, &sd); + dump_content_light_metadata(ctx, sd); + break; + case AV_PKT_DATA_ICC_PROFILE: + av_log(ctx, AV_LOG_INFO, "ICC Profile"); + break; + case AV_PKT_DATA_DOVI_CONF: + av_log(ctx, AV_LOG_INFO, "DOVI configuration record: "); + dump_dovi_conf(ctx, sd); + break; + case AV_PKT_DATA_S12M_TIMECODE: + av_log(ctx, AV_LOG_INFO, "SMPTE ST 12-1:2014: "); + dump_s12m_timecode(ctx, st, sd); break; default: av_log(ctx, AV_LOG_INFO, - "unknown side data type %d (%d bytes)", sd.type, sd.size); + "unknown side data type %d (%d bytes)", sd->type, sd->size); break; } @@ -450,14 +505,14 @@ } /* "user interface" functions */ -static void dump_stream_format(AVFormatContext *ic, int i, +static void dump_stream_format(const AVFormatContext *ic, int i, int index, int is_output) { char buf[256]; int flags = (is_output ? ic->oformat->flags : ic->iformat->flags); - AVStream *st = ic->streams[i]; - AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); - char *separator = ic->dump_separator; + const AVStream *st = ic->streams[i]; + const AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); + const char *separator = ic->dump_separator; AVCodecContext *avctx; int ret; @@ -471,6 +526,8 @@ return; } +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS // Fields which are missing from AVCodecParameters need to be taken from the AVCodecContext avctx->properties = st->codec->properties; avctx->codec = st->codec->codec; @@ -478,13 +535,15 @@ avctx->qmax = st->codec->qmax; avctx->coded_width = st->codec->coded_width; avctx->coded_height = st->codec->coded_height; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (separator) av_opt_set(avctx, "dump_separator", separator, 0); avcodec_string(buf, sizeof(buf), avctx, is_output); avcodec_free_context(&avctx); - av_log(NULL, AV_LOG_INFO, " Stream #%d:%d", index, i); + av_log(NULL, AV_LOG_INFO, " Stream #%d:%d", index, i); /* the pid is an important information, so we display it */ /* XXX: add a generic system */ @@ -512,7 +571,13 @@ int fps = st->avg_frame_rate.den && st->avg_frame_rate.num; int tbr = st->r_frame_rate.den && st->r_frame_rate.num; int tbn = st->time_base.den && st->time_base.num; +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS int tbc = st->codec->time_base.den && st->codec->time_base.num; +FF_ENABLE_DEPRECATION_WARNINGS +#else + int tbc = 0; +#endif if (fps || tbr || tbn || tbc) av_log(NULL, AV_LOG_INFO, "%s", separator); @@ -523,8 +588,12 @@ print_fps(av_q2d(st->r_frame_rate), tbn || tbc ? "tbr, " : "tbr"); if (tbn) print_fps(1 / av_q2d(st->time_base), tbc ? "tbn, " : "tbn"); +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS if (tbc) print_fps(1 / av_q2d(st->codec->time_base), "tbc"); +FF_ENABLE_DEPRECATION_WARNINGS +#endif } if (st->disposition & AV_DISPOSITION_DEFAULT) @@ -586,7 +655,7 @@ if (!is_output) { av_log(NULL, AV_LOG_INFO, " Duration: "); if (ic->duration != AV_NOPTS_VALUE) { - int hours, mins, secs, us; + int64_t hours, mins, secs, us; int64_t duration = ic->duration + (ic->duration <= INT64_MAX - 5000 ? 5000 : 0); secs = duration / AV_TIME_BASE; us = duration % AV_TIME_BASE; @@ -594,7 +663,7 @@ secs %= 60; hours = mins / 60; mins %= 60; - av_log(NULL, AV_LOG_INFO, "%02d:%02d:%02d.%02d", hours, mins, secs, + av_log(NULL, AV_LOG_INFO, "%02"PRId64":%02"PRId64":%02"PRId64".%02"PRId64"", hours, mins, secs, (100 * us) / AV_TIME_BASE); } else { av_log(NULL, AV_LOG_INFO, "N/A"); @@ -617,31 +686,34 @@ av_log(NULL, AV_LOG_INFO, "\n"); } + if (ic->nb_chapters) + av_log(NULL, AV_LOG_INFO, " Chapters:\n"); for (i = 0; i < ic->nb_chapters; i++) { - AVChapter *ch = ic->chapters[i]; + const AVChapter *ch = ic->chapters[i]; av_log(NULL, AV_LOG_INFO, " Chapter #%d:%d: ", index, i); av_log(NULL, AV_LOG_INFO, "start %f, ", ch->start * av_q2d(ch->time_base)); av_log(NULL, AV_LOG_INFO, "end %f\n", ch->end * av_q2d(ch->time_base)); - dump_metadata(NULL, ch->metadata, " "); + dump_metadata(NULL, ch->metadata, " "); } if (ic->nb_programs) { int j, k, total = 0; for (j = 0; j < ic->nb_programs; j++) { - AVDictionaryEntry *name = av_dict_get(ic->programs[j]->metadata, - "name", NULL, 0); - av_log(NULL, AV_LOG_INFO, " Program %d %s\n", ic->programs[j]->id, + const AVProgram *program = ic->programs[j]; + const AVDictionaryEntry *name = av_dict_get(program->metadata, + "name", NULL, 0); + av_log(NULL, AV_LOG_INFO, " Program %d %s\n", program->id, name ? name->value : ""); - dump_metadata(NULL, ic->programs[j]->metadata, " "); - for (k = 0; k < ic->programs[j]->nb_stream_indexes; k++) { - dump_stream_format(ic, ic->programs[j]->stream_index[k], + dump_metadata(NULL, program->metadata, " "); + for (k = 0; k < program->nb_stream_indexes; k++) { + dump_stream_format(ic, program->stream_index[k], index, is_output); - printed[ic->programs[j]->stream_index[k]] = 1; + printed[program->stream_index[k]] = 1; } - total += ic->programs[j]->nb_stream_indexes; + total += program->nb_stream_indexes; } if (total < ic->nb_streams) av_log(NULL, AV_LOG_INFO, " No Program\n"); diff -Nru ffmpeg-4.2.2/libavformat/dv.c ffmpeg-4.4/libavformat/dv.c --- ffmpeg-4.2.2/libavformat/dv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/dv.c 2021-04-08 21:28:40.000000000 +0000 @@ -49,7 +49,6 @@ uint8_t audio_buf[4][8192]; int ach; int frames; - uint64_t abytes; }; static inline uint16_t dv_audio_12to16(uint16_t sample) @@ -258,7 +257,7 @@ c->ast[i] = avformat_new_stream(c->fctx, NULL); if (!c->ast[i]) break; - avpriv_set_pts_info(c->ast[i], 64, 1, 30000); + avpriv_set_pts_info(c->ast[i], 64, c->sys->time_base.num, c->sys->time_base.den); c->ast[i]->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; c->ast[i]->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; @@ -315,12 +314,27 @@ tc_pack = dv_extract_pack(frame, dv_timecode); if (!tc_pack) return 0; - av_timecode_make_smpte_tc_string(tc, AV_RB32(tc_pack + 1), prevent_df); + av_timecode_make_smpte_tc_string2(tc, av_inv_q(c->sys->time_base), AV_RB32(tc_pack + 1), prevent_df, 1); return 1; } /* The following 3 functions constitute our interface to the world */ +static int dv_init_demux(AVFormatContext *s, DVDemuxContext *c) +{ + c->vst = avformat_new_stream(s, NULL); + if (!c->vst) + return AVERROR(ENOMEM); + + c->fctx = s; + c->vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + c->vst->codecpar->codec_id = AV_CODEC_ID_DVVIDEO; + c->vst->codecpar->bit_rate = 25000000; + c->vst->start_time = 0; + + return 0; +} + DVDemuxContext *avpriv_dv_init_demux(AVFormatContext *s) { DVDemuxContext *c; @@ -329,18 +343,11 @@ if (!c) return NULL; - c->vst = avformat_new_stream(s, NULL); - if (!c->vst) { + if (dv_init_demux(s, c)) { av_free(c); return NULL; } - c->fctx = s; - c->vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - c->vst->codecpar->codec_id = AV_CODEC_ID_DVVIDEO; - c->vst->codecpar->bit_rate = 25000000; - c->vst->start_time = 0; - return c; } @@ -379,8 +386,7 @@ for (i = 0; i < c->ach; i++) { c->audio_pkt[i].pos = pos; c->audio_pkt[i].size = size; - c->audio_pkt[i].pts = c->abytes * 30000 * 8 / - c->ast[i]->codecpar->bit_rate; + c->audio_pkt[i].pts = (c->sys->height == 720) ? (c->frames & ~1) : c->frames; ppcm[i] = c->audio_buf[i]; } if (c->ach) @@ -393,10 +399,7 @@ c->audio_pkt[2].size = c->audio_pkt[3].size = 0; } else { c->audio_pkt[0].size = c->audio_pkt[1].size = 0; - c->abytes += size; } - } else { - c->abytes += size; } /* Now it's time to return video packet */ @@ -436,13 +439,6 @@ void ff_dv_offset_reset(DVDemuxContext *c, int64_t frame_offset) { c->frames = frame_offset; - if (c->ach) { - if (c->sys) { - c->abytes = av_rescale_q(c->frames, c->sys->time_base, - (AVRational) { 8, c->ast[0]->codecpar->bit_rate }); - } else - av_log(c->fctx, AV_LOG_ERROR, "cannot adjust audio bytes\n"); - } c->audio_pkt[0].size = c->audio_pkt[1].size = 0; c->audio_pkt[2].size = c->audio_pkt[3].size = 0; } @@ -452,7 +448,7 @@ ************************************************************/ typedef struct RawDVContext { - DVDemuxContext *dv_demux; + DVDemuxContext dv_demux; uint8_t buf[DV_MAX_FRAME_SIZE]; } RawDVContext; @@ -462,31 +458,26 @@ int64_t pos = avio_tell(s->pb); // Read 3 DIF blocks: Header block and 2 Subcode blocks. - int partial_frame_size = 3 * 80; - uint8_t *partial_frame = av_mallocz(sizeof(*partial_frame) * - partial_frame_size); - +#define PARTIAL_FRAME_SIZE (3 * 80) + uint8_t partial_frame[PARTIAL_FRAME_SIZE]; RawDVContext *c = s->priv_data; - if (!partial_frame) - return AVERROR(ENOMEM); - ret = avio_read(s->pb, partial_frame, partial_frame_size); + ret = avio_read(s->pb, partial_frame, PARTIAL_FRAME_SIZE); if (ret < 0) goto finish; - if (ret < partial_frame_size) { + if (ret < PARTIAL_FRAME_SIZE) { ret = -1; goto finish; } - ret = dv_extract_timecode(c->dv_demux, partial_frame, timecode); + ret = dv_extract_timecode(&c->dv_demux, partial_frame, timecode); if (ret) av_dict_set(&s->metadata, "timecode", timecode, 0); else av_log(s, AV_LOG_ERROR, "Detected timecode is invalid\n"); finish: - av_free(partial_frame); avio_seek(s->pb, pos, SEEK_SET); return ret; } @@ -495,16 +486,16 @@ { unsigned state, marker_pos = 0; RawDVContext *c = s->priv_data; + int ret; - c->dv_demux = avpriv_dv_init_demux(s); - if (!c->dv_demux) - return -1; + if ((ret = dv_init_demux(s, &c->dv_demux)) < 0) + return ret; state = avio_rb32(s->pb); while ((state & 0xffffff7f) != 0x1f07003f) { if (avio_feof(s->pb)) { av_log(s, AV_LOG_ERROR, "Cannot find DV header.\n"); - return -1; + return AVERROR_INVALIDDATA; } if (state == 0x003f0700 || state == 0xff3f0700) marker_pos = avio_tell(s->pb); @@ -518,21 +509,22 @@ AV_WB32(c->buf, state); if (avio_read(s->pb, c->buf + 4, DV_PROFILE_BYTES - 4) != DV_PROFILE_BYTES - 4 || - avio_seek(s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0) + avio_seek(s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0) { return AVERROR(EIO); + } - c->dv_demux->sys = av_dv_frame_profile(c->dv_demux->sys, + c->dv_demux.sys = av_dv_frame_profile(c->dv_demux.sys, c->buf, DV_PROFILE_BYTES); - if (!c->dv_demux->sys) { + if (!c->dv_demux.sys) { av_log(s, AV_LOG_ERROR, "Can't determine profile of DV input stream.\n"); - return -1; + return AVERROR_INVALIDDATA; } - s->bit_rate = av_rescale_q(c->dv_demux->sys->frame_size, + s->bit_rate = av_rescale_q(c->dv_demux.sys->frame_size, (AVRational) { 8, 1 }, - c->dv_demux->sys->time_base); + c->dv_demux.sys->time_base); if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) dv_read_timecode(s); @@ -545,14 +537,14 @@ int size; RawDVContext *c = s->priv_data; - size = avpriv_dv_get_packet(c->dv_demux, pkt); + size = avpriv_dv_get_packet(&c->dv_demux, pkt); if (size < 0) { int ret; int64_t pos = avio_tell(s->pb); - if (!c->dv_demux->sys) + if (!c->dv_demux.sys) return AVERROR(EIO); - size = c->dv_demux->sys->frame_size; + size = c->dv_demux.sys->frame_size; ret = avio_read(s->pb, c->buf, size); if (ret < 0) { return ret; @@ -560,7 +552,7 @@ return AVERROR(EIO); } - size = avpriv_dv_produce_packet(c->dv_demux, pkt, c->buf, size, pos); + size = avpriv_dv_produce_packet(&c->dv_demux, pkt, c->buf, size, pos); } return size; @@ -570,7 +562,7 @@ int64_t timestamp, int flags) { RawDVContext *r = s->priv_data; - DVDemuxContext *c = r->dv_demux; + DVDemuxContext *c = &r->dv_demux; int64_t offset = dv_frame_offset(s, c, timestamp, flags); if (avio_seek(s->pb, offset, SEEK_SET) < 0) @@ -580,13 +572,6 @@ return 0; } -static int dv_read_close(AVFormatContext *s) -{ - RawDVContext *c = s->priv_data; - av_freep(&c->dv_demux); - return 0; -} - static int dv_probe(const AVProbeData *p) { unsigned marker_pos = 0; @@ -636,7 +621,6 @@ .read_probe = dv_probe, .read_header = dv_read_header, .read_packet = dv_read_packet, - .read_close = dv_read_close, .read_seek = dv_read_seek, .extensions = "dv,dif", }; diff -Nru ffmpeg-4.2.2/libavformat/dvenc.c ffmpeg-4.4/libavformat/dvenc.c --- ffmpeg-4.2.2/libavformat/dvenc.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/dvenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -28,8 +28,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include -#include +#include "libavutil/time_internal.h" #include "avformat.h" #include "internal.h" #include "libavcodec/dv_profile.h" @@ -48,8 +48,8 @@ AVClass *av_class; const AVDVProfile* sys; /* current DV profile, e.g.: 525/60, 625/50 */ int n_ast; /* number of stereo audio streams (up to 2) */ - AVStream *ast[2]; /* stereo audio streams */ - AVFifoBuffer *audio_data[2]; /* FIFO for storing excessive amounts of PCM */ + AVStream *ast[4]; /* stereo audio streams */ + AVFifoBuffer *audio_data[4]; /* FIFO for storing excessive amounts of PCM */ int frames; /* current frame number */ int64_t start_time; /* recording start time */ int has_audio; /* frame under construction has audio */ @@ -73,6 +73,14 @@ { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff }, }; +static void brktimegm(time_t secs, struct tm *tm) +{ + tm = gmtime_r(&secs, tm); + + tm->tm_year += 1900; /* unlike gmtime_r we store complete year here */ + tm->tm_mon += 1; /* unlike gmtime_r tm_mon is from 1 to 12 */ +} + static int dv_audio_frame_size(const AVDVProfile* sys, int frame, int sample_rate) { if ((sys->time_base.den == 25 || sys->time_base.den == 50) && sys->time_base.num == 1) { @@ -87,14 +95,12 @@ sizeof(sys->audio_samples_dist[0]))]; } -static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* buf, ...) +static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* buf, int channel, int seq) { struct tm tc; time_t ct; uint32_t timecode; - va_list ap; int audio_type = 0; - int channel; buf[0] = (uint8_t)pack_id; switch (pack_id) { @@ -104,8 +110,6 @@ AV_WB32(buf + 1, timecode); break; case dv_audio_source: /* AAUX source pack */ - va_start(ap, buf); - channel = va_arg(ap, int); if (c->ast[channel]->codecpar->sample_rate == 44100) { audio_type = 1; } else if (c->ast[channel]->codecpar->sample_rate == 32000) @@ -118,17 +122,16 @@ buf[2] = (0 << 7) | /* multi-stereo */ (0 << 5) | /* #of audio channels per block: 0 -- 1 channel */ (0 << 4) | /* pair bit: 0 -- one pair of channels */ - !!va_arg(ap, int); /* audio mode */ + (seq >= c->sys->difseg_size/2); /* audio mode (1st or 2nd channel) */ buf[3] = (1 << 7) | /* res */ (1 << 6) | /* multi-language flag */ (c->sys->dsf << 5) | /* system: 60fields/50fields */ - (c->sys->n_difchan & 2); /* definition: 0 -- 25Mbps, 2 -- 50Mbps */ + (DV_PROFILE_IS_HD(c->sys) ? 0x3 : c->sys->video_stype ? 2 : 0); /* stype */ buf[4] = (1 << 7) | /* emphasis: 1 -- off */ (0 << 6) | /* emphasis time constant: 0 -- reserved */ (audio_type << 3) | /* frequency: 0 -- 48kHz, 1 -- 44,1kHz, 2 -- 32kHz */ 0; /* quantization: 0 -- 16-bit linear, 1 -- 12-bit nonlinear */ - va_end(ap); break; case dv_audio_control: buf[1] = (0 << 6) | /* copy protection: 0 -- unrestricted */ @@ -149,7 +152,7 @@ case dv_video_recdate: /* VAUX recording date */ ct = c->start_time + av_rescale_rnd(c->frames, c->sys->time_base.num, c->sys->time_base.den, AV_ROUND_DOWN); - ff_brktimegm(ct, &tc); + brktimegm(ct, &tc); buf[1] = 0xff; /* ds, tm, tens of time zone, units of time zone */ /* 0xff is very likely to be "unknown" */ buf[2] = (3 << 6) | /* reserved -- always 1 */ @@ -165,7 +168,7 @@ case dv_video_rectime: /* VAUX recording time */ ct = c->start_time + av_rescale_rnd(c->frames, c->sys->time_base.num, c->sys->time_base.den, AV_ROUND_DOWN); - ff_brktimegm(ct, &tc); + brktimegm(ct, &tc); buf[1] = (3 << 6) | /* reserved -- always 1 */ 0x3f; /* tens of frame, units of frame: 0x3f - "unknown" ? */ buf[2] = (1 << 7) | /* reserved -- always 1 */ @@ -192,7 +195,7 @@ for (i = 0; i < c->sys->difseg_size; i++) { frame_ptr += 6 * 80; /* skip DIF segment header */ for (j = 0; j < 9; j++) { - dv_write_pack(dv_aaux_packs_dist[i][j], c, &frame_ptr[3], channel, i >= c->sys->difseg_size/2); + dv_write_pack(dv_aaux_packs_dist[i][j], c, &frame_ptr[3], channel, i); for (d = 8; d < 80; d+=2) { of = c->sys->audio_shuffle[i][j] + (d - 8)/2 * c->sys->audio_stride; if (of*2 >= size) @@ -210,27 +213,28 @@ { int j, k; uint8_t* buf; + int seq = 0; - for (buf = frame; buf < frame + c->sys->frame_size; buf += 150 * 80) { + for (buf = frame; buf < frame + c->sys->frame_size; buf += 150 * 80, seq++) { /* DV subcode: 2nd and 3d DIFs */ for (j = 80; j < 80 * 3; j += 80) { for (k = 6; k < 6 * 8; k += 8) - dv_write_pack(dv_timecode, c, &buf[j+k]); + dv_write_pack(dv_timecode, c, &buf[j+k], 0, seq); if (((long)(buf-frame)/(c->sys->frame_size/(c->sys->difseg_size*c->sys->n_difchan))%c->sys->difseg_size) > 5) { /* FIXME: is this really needed ? */ - dv_write_pack(dv_video_recdate, c, &buf[j+14]); - dv_write_pack(dv_video_rectime, c, &buf[j+22]); - dv_write_pack(dv_video_recdate, c, &buf[j+38]); - dv_write_pack(dv_video_rectime, c, &buf[j+46]); + dv_write_pack(dv_video_recdate, c, &buf[j+14], 0, seq); + dv_write_pack(dv_video_rectime, c, &buf[j+22], 0, seq); + dv_write_pack(dv_video_recdate, c, &buf[j+38], 0, seq); + dv_write_pack(dv_video_rectime, c, &buf[j+46], 0, seq); } } /* DV VAUX: 4th, 5th and 6th 3DIFs */ for (j = 80*3 + 3; j < 80*6; j += 80) { - dv_write_pack(dv_video_recdate, c, &buf[j+5*2]); - dv_write_pack(dv_video_rectime, c, &buf[j+5*3]); - dv_write_pack(dv_video_recdate, c, &buf[j+5*11]); - dv_write_pack(dv_video_rectime, c, &buf[j+5*12]); + dv_write_pack(dv_video_recdate, c, &buf[j+5* 2], 0, seq); + dv_write_pack(dv_video_rectime, c, &buf[j+5* 3], 0, seq); + dv_write_pack(dv_video_recdate, c, &buf[j+5*11], 0, seq); + dv_write_pack(dv_video_rectime, c, &buf[j+5*12], 0, seq); } } } @@ -307,42 +311,39 @@ int i; /* we support at most 1 video and 2 audio streams */ - if (s->nb_streams > 3) + if (s->nb_streams > 5) return NULL; - c->n_ast = 0; - c->ast[0] = c->ast[1] = NULL; - /* We have to sort out where audio and where video stream is */ for (i=0; inb_streams; i++) { - switch (s->streams[i]->codecpar->codec_type) { + AVStream *st = s->streams[i]; + switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: if (vst) return NULL; - vst = s->streams[i]; + if (st->codecpar->codec_id != AV_CODEC_ID_DVVIDEO) + goto bail_out; + vst = st; break; case AVMEDIA_TYPE_AUDIO: if (c->n_ast > 1) return NULL; - c->ast[c->n_ast++] = s->streams[i]; + /* Some checks -- DV format is very picky about its incoming streams */ + if(st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE || + st->codecpar->channels != 2) + goto bail_out; + if (st->codecpar->sample_rate != 48000 && + st->codecpar->sample_rate != 44100 && + st->codecpar->sample_rate != 32000 ) + goto bail_out; + c->ast[c->n_ast++] = st; break; default: goto bail_out; } } - /* Some checks -- DV format is very picky about its incoming streams */ - if (!vst || vst->codecpar->codec_id != AV_CODEC_ID_DVVIDEO) + if (!vst) goto bail_out; - for (i=0; in_ast; i++) { - if (c->ast[i]) { - if(c->ast[i]->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE || - c->ast[i]->codecpar->channels != 2) - goto bail_out; - if (c->ast[i]->codecpar->sample_rate != 48000 && - c->ast[i]->codecpar->sample_rate != 44100 && - c->ast[i]->codecpar->sample_rate != 32000 ) - goto bail_out; - } - } + c->sys = av_dv_codec_profile2(vst->codecpar->width, vst->codecpar->height, vst->codecpar->format, vst->time_base); if (!c->sys) @@ -355,8 +356,9 @@ goto bail_out; } - if ((c->n_ast > 1) && (c->sys->n_difchan < 2)) { - /* only 1 stereo pair is allowed in 25Mbps mode */ + if (((c->n_ast > 1) && (c->sys->n_difchan < 2)) || + ((c->n_ast > 2) && (c->sys->n_difchan < 4))) { + /* only 2 stereo pairs allowed in 50Mbps mode */ goto bail_out; } @@ -368,10 +370,6 @@ for (i=0; i < c->n_ast; i++) { if (c->ast[i] && !(c->audio_data[i]=av_fifo_alloc_array(100, MAX_AUDIO_FRAME_SIZE))) { - while (i > 0) { - i--; - av_fifo_freep(&c->audio_data[i]); - } goto bail_out; } } @@ -382,13 +380,6 @@ return NULL; } -static void dv_delete_mux(DVMuxContext *c) -{ - int i; - for (i=0; i < c->n_ast; i++) - av_fifo_freep(&c->audio_data[i]); -} - static int dv_write_header(AVFormatContext *s) { AVRational rate; @@ -424,9 +415,10 @@ fsize = dv_assemble_frame(s, s->priv_data, s->streams[pkt->stream_index], pkt->data, pkt->size, &frame); - if (fsize > 0) { - avio_write(s->pb, frame, fsize); + if (fsize < 0) { + return fsize; } + avio_write(s->pb, frame, fsize); return 0; } @@ -436,10 +428,12 @@ * Currently we simply drop the last frame. I don't know whether this * is the best strategy of all */ -static int dv_write_trailer(struct AVFormatContext *s) +static void dv_deinit(AVFormatContext *s) { - dv_delete_mux(s->priv_data); - return 0; + DVMuxContext *c = s->priv_data; + + for (int i = 0; i < c->n_ast; i++) + av_fifo_freep(&c->audio_data[i]); } AVOutputFormat ff_dv_muxer = { @@ -451,5 +445,5 @@ .video_codec = AV_CODEC_ID_DVVIDEO, .write_header = dv_write_header, .write_packet = dv_write_packet, - .write_trailer = dv_write_trailer, + .deinit = dv_deinit, }; diff -Nru ffmpeg-4.2.2/libavformat/dxa.c ffmpeg-4.4/libavformat/dxa.c --- ffmpeg-4.2.2/libavformat/dxa.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/dxa.c 2021-02-20 20:27:47.000000000 +0000 @@ -143,7 +143,7 @@ c->readvid = !c->has_sound; c->vidpos = avio_tell(pb); s->start_time = 0; - s->duration = (int64_t)c->frames * AV_TIME_BASE * num / den; + s->duration = av_rescale(c->frames, AV_TIME_BASE * (int64_t)num, den); av_log(s, AV_LOG_DEBUG, "%d frame(s)\n",c->frames); return 0; @@ -179,8 +179,8 @@ tag = AV_RL32(buf); switch (tag) { case MKTAG('N', 'U', 'L', 'L'): - if(av_new_packet(pkt, 4 + pal_size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, 4 + pal_size)) < 0) + return ret; pkt->stream_index = 0; if(pal_size) memcpy(pkt->data, pal, pal_size); memcpy(pkt->data + pal_size, buf, 4); @@ -204,12 +204,12 @@ size); return AVERROR_INVALIDDATA; } - if(av_new_packet(pkt, size + DXA_EXTRA_SIZE + pal_size) < 0) - return AVERROR(ENOMEM); + ret = av_new_packet(pkt, size + DXA_EXTRA_SIZE + pal_size); + if (ret < 0) + return ret; memcpy(pkt->data + pal_size, buf, DXA_EXTRA_SIZE); ret = avio_read(s->pb, pkt->data + DXA_EXTRA_SIZE + pal_size, size); if(ret != size){ - av_packet_unref(pkt); return AVERROR(EIO); } if(pal_size) memcpy(pkt->data, pal, pal_size); diff -Nru ffmpeg-4.2.2/libavformat/electronicarts.c ffmpeg-4.4/libavformat/electronicarts.c --- ffmpeg-4.2.2/libavformat/electronicarts.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/electronicarts.c 2021-04-08 21:28:40.000000000 +0000 @@ -530,20 +530,17 @@ if (ea->num_channels <= 0 || ea->num_channels > 2) { av_log(s, AV_LOG_WARNING, "Unsupported number of channels: %d\n", ea->num_channels); - ea->audio_codec = 0; - return 1; + goto no_audio; } if (ea->sample_rate <= 0) { av_log(s, AV_LOG_ERROR, "Unsupported sample rate: %d\n", ea->sample_rate); - ea->audio_codec = 0; - return 1; + goto no_audio; } if (ea->bytes <= 0 || ea->bytes > 2) { av_log(s, AV_LOG_ERROR, "Invalid number of bytes per sample: %d\n", ea->bytes); - ea->audio_codec = AV_CODEC_ID_NONE; - return 1; + goto no_audio; } /* initialize the audio decoder stream */ @@ -564,9 +561,14 @@ st->codecpar->bits_per_coded_sample; ea->audio_stream_index = st->index; st->start_time = 0; + return 0; } +no_audio: + ea->audio_codec = AV_CODEC_ID_NONE; - return 1; + if (!ea->video.codec) + return AVERROR_INVALIDDATA; + return 0; } static int ea_read_packet(AVFormatContext *s, AVPacket *pkt) @@ -580,6 +582,8 @@ int av_uninit(num_samples); while ((!packet_read && !hit_end) || partial_packet) { + if (avio_feof(pb)) + return AVERROR_EOF; chunk_type = avio_rl32(pb); chunk_size = ea->big_endian ? avio_rb32(pb) : avio_rl32(pb); if (chunk_size < 8) @@ -603,10 +607,14 @@ break; } else if (ea->audio_codec == AV_CODEC_ID_PCM_S16LE_PLANAR || ea->audio_codec == AV_CODEC_ID_MP3) { + if (chunk_size < 12) + return AVERROR_INVALIDDATA; num_samples = avio_rl32(pb); avio_skip(pb, 8); chunk_size -= 12; } else if (ea->audio_codec == AV_CODEC_ID_ADPCM_PSX) { + if (chunk_size < 8) + return AVERROR_INVALIDDATA; avio_skip(pb, 8); chunk_size -= 8; } @@ -633,7 +641,6 @@ case AV_CODEC_ID_ADPCM_EA_R3: if (pkt->size < 4) { av_log(s, AV_LOG_ERROR, "Packet is too short\n"); - av_packet_unref(pkt); return AVERROR_INVALIDDATA; } if (ea->audio_codec == AV_CODEC_ID_ADPCM_EA_R3) @@ -690,6 +697,8 @@ case fVGT_TAG: case MADm_TAG: case MADe_TAG: + if (chunk_size > INT_MAX - 8) + return AVERROR_INVALIDDATA; avio_seek(pb, -8, SEEK_CUR); // include chunk preamble chunk_size += 8; goto get_video_packet; @@ -719,6 +728,7 @@ ret = av_get_packet(pb, pkt, chunk_size); if (ret < 0) { packet_read = 1; + partial_packet = 0; break; } partial_packet = chunk_type == MVIh_TAG; @@ -736,8 +746,6 @@ } } - if (ret < 0 && partial_packet) - av_packet_unref(pkt); if (ret >= 0 && hit_end && !packet_read) return AVERROR(EAGAIN); diff -Nru ffmpeg-4.2.2/libavformat/ffmetadec.c ffmpeg-4.4/libavformat/ffmetadec.c --- ffmpeg-4.2.2/libavformat/ffmetadec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ffmetadec.c 2021-04-08 21:28:40.000000000 +0000 @@ -101,19 +101,22 @@ uint8_t line[256]; int64_t start, end; AVRational tb = {1, 1e9}; + int ret; get_line(s->pb, line, sizeof(line)); if (sscanf(line, "TIMEBASE=%d/%d", &tb.num, &tb.den)) get_line(s->pb, line, sizeof(line)); - if (!sscanf(line, "START=%"SCNd64, &start)) { + ret = sscanf(line, "START=%"SCNd64, &start); + if (ret <= 0) { av_log(s, AV_LOG_ERROR, "Expected chapter start timestamp, found %s.\n", line); start = (s->nb_chapters && s->chapters[s->nb_chapters - 1]->end != AV_NOPTS_VALUE) ? s->chapters[s->nb_chapters - 1]->end : 0; } else get_line(s->pb, line, sizeof(line)); - if (!sscanf(line, "END=%"SCNd64, &end)) { + ret = sscanf(line, "END=%"SCNd64, &end); + if (ret <= 0) { av_log(s, AV_LOG_ERROR, "Expected chapter end timestamp, found %s.\n", line); end = AV_NOPTS_VALUE; } @@ -182,7 +185,7 @@ AVStream *st = avformat_new_stream(s, NULL); if (!st) - return AVERROR(ENOMEM); + goto nomem; st->codecpar->codec_type = AVMEDIA_TYPE_DATA; st->codecpar->codec_id = AV_CODEC_ID_FFMETADATA; @@ -192,7 +195,7 @@ AVChapter *ch = read_chapter(s); if (!ch) - return AVERROR(ENOMEM); + goto nomem; m = &ch->metadata; } else @@ -208,6 +211,10 @@ AV_TIME_BASE_Q); return 0; +nomem: + av_bprint_finalize(&bp, NULL); + + return AVERROR(ENOMEM); } static int read_packet(AVFormatContext *s, AVPacket *pkt) diff -Nru ffmpeg-4.2.2/libavformat/ffmetaenc.c ffmpeg-4.4/libavformat/ffmetaenc.c --- ffmpeg-4.2.2/libavformat/ffmetaenc.c 2016-03-29 02:25:28.000000000 +0000 +++ ffmpeg-4.4/libavformat/ffmetaenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -54,7 +54,6 @@ avio_write(s->pb, ID_STRING, sizeof(ID_STRING) - 1); avio_w8(s->pb, '1'); // version avio_w8(s->pb, '\n'); - avio_flush(s->pb); return 0; } diff -Nru ffmpeg-4.2.2/libavformat/fifo.c ffmpeg-4.4/libavformat/fifo.c --- ffmpeg-4.2.2/libavformat/fifo.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/fifo.c 2021-04-08 21:28:40.000000000 +0000 @@ -19,6 +19,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/avassert.h" #include "libavutil/opt.h" #include "libavutil/time.h" @@ -36,7 +38,6 @@ AVFormatContext *avf; char *format; - char *format_options_str; AVDictionary *format_options; int queue_size; @@ -78,6 +79,9 @@ /* Value > 0 signals queue overflow */ volatile uint8_t overflow_flag; + atomic_int_least64_t queue_duration; + int64_t last_sent_dts; + int64_t timeshift; } FifoContext; typedef struct FifoThreadContext { @@ -99,9 +103,12 @@ * so finalization by calling write_trailer and ff_io_close must be done * before exiting / reinitialization of underlying muxer */ uint8_t header_written; + + int64_t last_received_dts; } FifoThreadContext; typedef enum FifoMessageType { + FIFO_NOOP, FIFO_WRITE_HEADER, FIFO_WRITE_PACKET, FIFO_FLUSH_OUTPUT @@ -160,6 +167,15 @@ return av_write_frame(avf2, NULL); } +static int64_t next_duration(AVFormatContext *avf, AVPacket *pkt, int64_t *last_dts) +{ + AVStream *st = avf->streams[pkt->stream_index]; + int64_t dts = av_rescale_q(pkt->dts, st->time_base, AV_TIME_BASE_Q); + int64_t duration = (*last_dts == AV_NOPTS_VALUE ? 0 : dts - *last_dts); + *last_dts = dts; + return duration; +} + static int fifo_thread_write_packet(FifoThreadContext *ctx, AVPacket *pkt) { AVFormatContext *avf = ctx->avf; @@ -168,6 +184,9 @@ AVRational src_tb, dst_tb; int ret, s_idx; + 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); + if (ctx->drop_until_keyframe) { if (pkt->flags & AV_PKT_FLAG_KEY) { ctx->drop_until_keyframe = 0; @@ -210,6 +229,9 @@ { int ret = AVERROR(EINVAL); + if (msg->type == FIFO_NOOP) + return 0; + if (!ctx->header_written) { ret = fifo_thread_write_header(ctx); if (ret < 0) @@ -391,12 +413,13 @@ AVFormatContext *avf = data; FifoContext *fifo = avf->priv_data; AVThreadMessageQueue *queue = fifo->queue; - FifoMessage msg = {FIFO_WRITE_HEADER, {0}}; + FifoMessage msg = {fifo->timeshift ? FIFO_NOOP : FIFO_WRITE_HEADER, {0}}; int ret; FifoThreadContext fifo_thread_ctx; memset(&fifo_thread_ctx, 0, sizeof(FifoThreadContext)); fifo_thread_ctx.avf = avf; + fifo_thread_ctx.last_received_dts = AV_NOPTS_VALUE; while (1) { uint8_t just_flushed = 0; @@ -430,6 +453,10 @@ if (just_flushed) av_log(avf, AV_LOG_INFO, "FIFO queue flushed\n"); + if (fifo->timeshift) + while (atomic_load_explicit(&fifo->queue_duration, memory_order_relaxed) < fifo->timeshift) + av_usleep(10000); + ret = av_thread_message_queue_recv(queue, &msg, 0); if (ret < 0) { av_thread_message_queue_set_err_send(queue, ret); @@ -489,16 +516,8 @@ " only when drop_pkts_on_overflow is also turned on\n"); return AVERROR(EINVAL); } - - if (fifo->format_options_str) { - ret = av_dict_parse_string(&fifo->format_options, fifo->format_options_str, - "=", ":", 0); - if (ret < 0) { - av_log(avf, AV_LOG_ERROR, "Could not parse format options list '%s'\n", - fifo->format_options_str); - return ret; - } - } + atomic_init(&fifo->queue_duration, 0); + fifo->last_sent_dts = AV_NOPTS_VALUE; oformat = av_guess_format(fifo->format, avf->url, NULL); if (!oformat) { @@ -547,7 +566,6 @@ int ret; if (pkt) { - av_init_packet(&msg.pkt); ret = av_packet_ref(&msg.pkt,pkt); if (ret < 0) return ret; @@ -575,6 +593,9 @@ goto fail; } + if (fifo->timeshift && pkt->dts != AV_NOPTS_VALUE) + atomic_fetch_add_explicit(&fifo->queue_duration, next_duration(avf, pkt, &fifo->last_sent_dts), memory_order_relaxed); + return ret; fail: if (pkt) @@ -588,6 +609,27 @@ int ret; av_thread_message_queue_set_err_recv(fifo->queue, AVERROR_EOF); + if (fifo->timeshift) { + int64_t now = av_gettime_relative(); + int64_t elapsed = 0; + FifoMessage msg = {FIFO_NOOP}; + do { + int64_t delay = av_gettime_relative() - now; + if (delay < 0) { // Discontinuity? + delay = 10000; + now = av_gettime_relative(); + } else { + now += delay; + } + atomic_fetch_add_explicit(&fifo->queue_duration, delay, memory_order_relaxed); + elapsed += delay; + if (elapsed > fifo->timeshift) + break; + av_usleep(10000); + ret = av_thread_message_queue_send(fifo->queue, &msg, AV_THREAD_MESSAGE_NONBLOCK); + } while (ret >= 0 || ret == AVERROR(EAGAIN)); + atomic_store(&fifo->queue_duration, INT64_MAX); + } ret = pthread_join(fifo->writer_thread, NULL); if (ret < 0) { @@ -604,7 +646,6 @@ { FifoContext *fifo = avf->priv_data; - av_dict_free(&fifo->format_options); avformat_free_context(fifo->avf); av_thread_message_queue_free(&fifo->queue); if (fifo->overflow_flag_lock_initialized) @@ -619,8 +660,8 @@ {"queue_size", "Size of fifo queue", OFFSET(queue_size), AV_OPT_TYPE_INT, {.i64 = FIFO_DEFAULT_QUEUE_SIZE}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, - {"format_opts", "Options to be passed to underlying muxer", OFFSET(format_options_str), - AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM}, + {"format_opts", "Options to be passed to underlying muxer", OFFSET(format_options), + AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM}, {"drop_pkts_on_overflow", "Drop packets on fifo queue overflow not to block encoder", OFFSET(drop_pkts_on_overflow), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, @@ -643,6 +684,9 @@ {"recover_any_error", "Attempt recovery regardless of type of the error", OFFSET(recover_any_error), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, + {"timeshift", "Delay fifo output", OFFSET(timeshift), + AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM}, + {NULL}, }; diff -Nru ffmpeg-4.2.2/libavformat/file.c ffmpeg-4.4/libavformat/file.c --- ffmpeg-4.2.2/libavformat/file.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/file.c 2020-07-11 10:39:30.000000000 +0000 @@ -369,7 +369,7 @@ .url_open_dir = file_open_dir, .url_read_dir = file_read_dir, .url_close_dir = file_close_dir, - .default_whitelist = "file,crypto" + .default_whitelist = "file,crypto,data" }; #endif /* CONFIG_FILE_PROTOCOL */ @@ -408,7 +408,7 @@ .url_check = file_check, .priv_data_size = sizeof(FileContext), .priv_data_class = &pipe_class, - .default_whitelist = "crypto" + .default_whitelist = "crypto,data" }; #endif /* CONFIG_PIPE_PROTOCOL */ diff -Nru ffmpeg-4.2.2/libavformat/filmstripenc.c ffmpeg-4.4/libavformat/filmstripenc.c --- ffmpeg-4.2.2/libavformat/filmstripenc.c 2018-11-01 18:34:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/filmstripenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -26,13 +26,10 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "rawenc.h" #define RAND_TAG MKBETAG('R','a','n','d') -typedef struct FilmstripMuxContext { - int nb_frames; -} FilmstripMuxContext; - static int write_header(AVFormatContext *s) { if (s->streams[0]->codecpar->format != AV_PIX_FMT_RGBA) { @@ -42,23 +39,14 @@ return 0; } -static int write_packet(AVFormatContext *s, AVPacket *pkt) -{ - FilmstripMuxContext *film = s->priv_data; - avio_write(s->pb, pkt->data, pkt->size); - film->nb_frames++; - return 0; -} - static int write_trailer(AVFormatContext *s) { - FilmstripMuxContext *film = s->priv_data; AVIOContext *pb = s->pb; AVStream *st = s->streams[0]; int i; avio_wb32(pb, RAND_TAG); - avio_wb32(pb, film->nb_frames); + avio_wb32(pb, st->nb_frames); avio_wb16(pb, 0); // packing method avio_wb16(pb, 0); // reserved avio_wb16(pb, st->codecpar->width); @@ -76,10 +64,9 @@ .name = "filmstrip", .long_name = NULL_IF_CONFIG_SMALL("Adobe Filmstrip"), .extensions = "flm", - .priv_data_size = sizeof(FilmstripMuxContext), .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_RAWVIDEO, .write_header = write_header, - .write_packet = write_packet, + .write_packet = ff_raw_write_packet, .write_trailer = write_trailer, }; diff -Nru ffmpeg-4.2.2/libavformat/fitsdec.c ffmpeg-4.4/libavformat/fitsdec.c --- ffmpeg-4.2.2/libavformat/fitsdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/fitsdec.c 2021-02-20 20:27:47.000000000 +0000 @@ -24,6 +24,7 @@ * FITS demuxer. */ +#include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" #include "internal.h" #include "libavutil/opt.h" @@ -125,14 +126,14 @@ size += header->pcount; t = (abs(header->bitpix) >> 3) * ((int64_t) header->gcount); - if(size && t > UINT64_MAX / size) + if(size && t > INT64_MAX / size) return AVERROR_INVALIDDATA; size *= t; if (!size) { image = 0; } else { - if(FITS_BLOCK_SIZE - 1 > UINT64_MAX - size) + if(FITS_BLOCK_SIZE - 1 > INT64_MAX - size) return AVERROR_INVALIDDATA; size = ((size + FITS_BLOCK_SIZE - 1) / FITS_BLOCK_SIZE) * FITS_BLOCK_SIZE; } @@ -157,11 +158,11 @@ av_bprint_init(&avbuf, FITS_BLOCK_SIZE, AV_BPRINT_SIZE_UNLIMITED); while ((ret = is_image(s, fits, &header, &avbuf, &size)) == 0) { + av_bprint_finalize(&avbuf, NULL); pos = avio_skip(s->pb, size); if (pos < 0) return pos; - av_bprint_finalize(&avbuf, NULL); av_bprint_init(&avbuf, FITS_BLOCK_SIZE, AV_BPRINT_SIZE_UNLIMITED); avpriv_fits_header_init(&header, STATE_XTENSION); } @@ -173,6 +174,11 @@ goto fail; } + av_assert0(avbuf.len <= INT64_MAX && size <= INT64_MAX); + if (avbuf.len + size > INT_MAX - 80) { + ret = AVERROR_INVALIDDATA; + goto fail; + } // Header is sent with the first line removed... ret = av_new_packet(pkt, avbuf.len - 80 + size); if (ret < 0) @@ -183,7 +189,6 @@ ret = av_bprint_finalize(&avbuf, &buf); if (ret < 0) { - av_packet_unref(pkt); return ret; } @@ -192,7 +197,6 @@ av_freep(&buf); ret = avio_read(s->pb, pkt->data + pkt->size, size); if (ret < 0) { - av_packet_unref(pkt); return ret; } diff -Nru ffmpeg-4.2.2/libavformat/fitsenc.c ffmpeg-4.4/libavformat/fitsenc.c --- ffmpeg-4.2.2/libavformat/fitsenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/fitsenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -45,7 +45,8 @@ * @param lines_written to keep track of lines written so far * @return 0 */ -static int write_keyword_value(AVFormatContext *s, const char *keyword, int value, int *lines_written) +static int write_keyword_value(AVFormatContext *s, const char *fmt, + const char *keyword, void *value, int *lines_written) { int len, ret; uint8_t header[80]; @@ -57,7 +58,12 @@ header[8] = '='; header[9] = ' '; - ret = snprintf(header + 10, 70, "%d", value); + if (!strcmp(fmt, "%d")) { + ret = snprintf(header + 10, 70, fmt, *(int *)value); + } else { + ret = snprintf(header + 10, 70, fmt, *(float *)value); + } + memset(&header[ret + 10], ' ', sizeof(header) - (ret + 10)); avio_write(s->pb, header, sizeof(header)); @@ -72,16 +78,22 @@ FITSContext *fitsctx = s->priv_data; uint8_t buffer[80]; int bitpix, naxis, naxis3 = 1, bzero = 0, rgb = 0, lines_written = 0, lines_left; + int pcount = 0, gcount = 1; + float datamax, datamin; switch (encctx->format) { case AV_PIX_FMT_GRAY8: bitpix = 8; naxis = 2; + datamin = 0; + datamax = 255; break; case AV_PIX_FMT_GRAY16BE: bitpix = 16; naxis = 2; bzero = 32768; + datamin = 0; + datamax = 65535; break; case AV_PIX_FMT_GBRP: case AV_PIX_FMT_GBRAP: @@ -93,6 +105,8 @@ } else { naxis3 = 4; } + datamin = 0; + datamax = 255; break; case AV_PIX_FMT_GBRP16BE: case AV_PIX_FMT_GBRAP16BE: @@ -105,6 +119,8 @@ naxis3 = 4; } bzero = 32768; + datamin = 0; + datamax = 65535; break; default: return AVERROR(EINVAL); @@ -122,28 +138,31 @@ } lines_written++; - write_keyword_value(s, "BITPIX", bitpix, &lines_written); // no of bits per pixel - write_keyword_value(s, "NAXIS", naxis, &lines_written); // no of dimensions of image - write_keyword_value(s, "NAXIS1", encctx->width, &lines_written); // first dimension i.e. width - write_keyword_value(s, "NAXIS2", encctx->height, &lines_written); // second dimension i.e. height + write_keyword_value(s, "%d", "BITPIX", &bitpix, &lines_written); // no of bits per pixel + write_keyword_value(s, "%d", "NAXIS", &naxis, &lines_written); // no of dimensions of image + write_keyword_value(s, "%d", "NAXIS1", &encctx->width, &lines_written); // first dimension i.e. width + write_keyword_value(s, "%d", "NAXIS2", &encctx->height, &lines_written); // second dimension i.e. height if (rgb) - write_keyword_value(s, "NAXIS3", naxis3, &lines_written); // third dimension to store RGBA planes + write_keyword_value(s, "%d", "NAXIS3", &naxis3, &lines_written); // third dimension to store RGBA planes if (!fitsctx->first_image) { - write_keyword_value(s, "PCOUNT", 0, &lines_written); - write_keyword_value(s, "GCOUNT", 1, &lines_written); + write_keyword_value(s, "%d", "PCOUNT", &pcount, &lines_written); + write_keyword_value(s, "%d", "GCOUNT", &gcount, &lines_written); } else { fitsctx->first_image = 0; } + write_keyword_value(s, "%g", "DATAMIN", &datamin, &lines_written); + write_keyword_value(s, "%g", "DATAMAX", &datamax, &lines_written); + /* * Since FITS does not support unsigned 16 bit integers, * BZERO = 32768 is used to store unsigned 16 bit integers as * signed integers so that it can be read properly. */ if (bitpix == 16) - write_keyword_value(s, "BZERO", bzero, &lines_written); + write_keyword_value(s, "%d", "BZERO", &bzero, &lines_written); if (rgb) { memcpy(buffer, "CTYPE3 = 'RGB '", 20); diff -Nru ffmpeg-4.2.2/libavformat/flacdec.c ffmpeg-4.4/libavformat/flacdec.c --- ffmpeg-4.2.2/libavformat/flacdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/flacdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -146,7 +146,7 @@ } av_freep(&buffer); } else if (metadata_type == FLAC_METADATA_TYPE_PICTURE) { - ret = ff_flac_parse_picture(s, buffer, metadata_size); + ret = ff_flac_parse_picture(s, buffer, metadata_size, 1); av_freep(&buffer); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Error parsing attached picture.\n"); @@ -259,7 +259,7 @@ static av_unused int64_t flac_read_timestamp(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit) { - AVPacket pkt, out_pkt; + AVPacket *pkt = s->internal->parse_pkt; AVStream *st = s->streams[stream_index]; AVCodecParserContext *parser; int ret; @@ -268,7 +268,6 @@ if (avio_seek(s->pb, *ppos, SEEK_SET) < 0) return AV_NOPTS_VALUE; - av_init_packet(&pkt); parser = av_parser_init(st->codecpar->codec_id); if (!parser){ return AV_NOPTS_VALUE; @@ -276,23 +275,24 @@ parser->flags |= PARSER_FLAG_USE_CODEC_TS; for (;;){ - ret = ff_raw_read_partial_packet(s, &pkt); + uint8_t *data; + int size; + + ret = ff_raw_read_partial_packet(s, pkt); if (ret < 0){ if (ret == AVERROR(EAGAIN)) continue; else { - av_packet_unref(&pkt); - av_assert1(!pkt.size); + av_packet_unref(pkt); + av_assert1(!pkt->size); } } - av_init_packet(&out_pkt); av_parser_parse2(parser, st->internal->avctx, - &out_pkt.data, &out_pkt.size, pkt.data, pkt.size, - pkt.pts, pkt.dts, *ppos); + &data, &size, pkt->data, pkt->size, + pkt->pts, pkt->dts, *ppos); - av_packet_unref(&pkt); - if (out_pkt.size){ - int size = out_pkt.size; + av_packet_unref(pkt); + if (size) { if (parser->pts != AV_NOPTS_VALUE){ // seeking may not have started from beginning of a frame // calculate frame start position from next frame backwards diff -Nru ffmpeg-4.2.2/libavformat/flacenc.c ffmpeg-4.4/libavformat/flacenc.c --- ffmpeg-4.2.2/libavformat/flacenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/flacenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,13 +23,13 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavcodec/flac.h" +#include "libavcodec/packet_internal.h" #include "avformat.h" #include "avio_internal.h" #include "flacenc.h" #include "id3v2.h" #include "internal.h" #include "vorbiscomment.h" -#include "libavcodec/bytestream.h" typedef struct FlacMuxerContext { @@ -39,10 +39,11 @@ int audio_stream_idx; int waiting_pics; /* audio packets are queued here until we get all the attached pictures */ - AVPacketList *queue, *queue_end; + PacketList *queue, *queue_end; /* updated streaminfo sent by the encoder at the end */ - uint8_t *streaminfo; + uint8_t streaminfo[FLAC_STREAMINFO_SIZE]; + int updated_streaminfo; unsigned attached_types; } FlacMuxerContext; @@ -61,25 +62,16 @@ { const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT; int64_t len; - uint8_t *p, *p0; ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL); len = ff_vorbiscomment_length(*m, vendor, NULL, 0); if (len >= ((1<<24) - 4)) return AVERROR(EINVAL); - p0 = av_malloc(len+4); - if (!p0) - return AVERROR(ENOMEM); - p = p0; - - bytestream_put_byte(&p, last_block ? 0x84 : 0x04); - bytestream_put_be24(&p, len); - ff_vorbiscomment_write(&p, m, vendor, NULL, 0); - - avio_write(pb, p0, len+4); - av_freep(&p0); - p = NULL; + + avio_w8(pb, last_block ? 0x84 : 0x04); + avio_wb24(pb, len); + ff_vorbiscomment_write(pb, *m, vendor, NULL, 0); return 0; } @@ -93,7 +85,7 @@ AVDictionaryEntry *e; const char *mimetype = NULL, *desc = ""; const AVStream *st = s->streams[pkt->stream_index]; - int i, mimelen, desclen, type = 0; + int i, mimelen, desclen, type = 0, blocklen; if (!pkt->data) return 0; @@ -140,8 +132,14 @@ desc = e->value; desclen = strlen(desc); + blocklen = 4 + 4 + mimelen + 4 + desclen + 4 + 4 + 4 + 4 + 4 + pkt->size; + if (blocklen >= 1<<24) { + av_log(s, AV_LOG_ERROR, "Picture block too big %d >= %d\n", blocklen, 1<<24); + return AVERROR(EINVAL); + } + avio_w8(pb, 0x06); - avio_wb24(pb, 4 + 4 + mimelen + 4 + desclen + 4 + 4 + 4 + 4 + 4 + pkt->size); + avio_wb24(pb, blocklen); avio_wb32(pb, type); @@ -282,18 +280,14 @@ { FlacMuxerContext *c = s->priv_data; uint8_t *streaminfo; - int streaminfo_size; + buffer_size_t streaminfo_size; /* check for updated streaminfo */ streaminfo = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &streaminfo_size); if (streaminfo && streaminfo_size == FLAC_STREAMINFO_SIZE) { - av_freep(&c->streaminfo); - - c->streaminfo = av_malloc(FLAC_STREAMINFO_SIZE); - if (!c->streaminfo) - return AVERROR(ENOMEM); memcpy(c->streaminfo, streaminfo, FLAC_STREAMINFO_SIZE); + c->updated_streaminfo = 1; } if (pkt->size) @@ -312,7 +306,7 @@ write = 0; while (c->queue) { - ff_packet_list_get(&c->queue, &c->queue_end, &pkt); + avpriv_packet_list_get(&c->queue, &c->queue_end, &pkt); if (write && (ret = flac_write_audio_packet(s, &pkt)) < 0) write = 0; av_packet_unref(&pkt); @@ -325,8 +319,6 @@ AVIOContext *pb = s->pb; int64_t file_size; FlacMuxerContext *c = s->priv_data; - uint8_t *streaminfo = c->streaminfo ? c->streaminfo : - s->streams[c->audio_stream_idx]->codecpar->extradata; if (c->waiting_pics) { av_log(s, AV_LOG_WARNING, "No packets were sent for some of the " @@ -334,25 +326,31 @@ flac_queue_flush(s); } - if (!c->write_header || !streaminfo) + if (!c->write_header || !c->updated_streaminfo) return 0; if (pb->seekable & AVIO_SEEKABLE_NORMAL) { /* rewrite the STREAMINFO header block data */ file_size = avio_tell(pb); avio_seek(pb, 8, SEEK_SET); - avio_write(pb, streaminfo, FLAC_STREAMINFO_SIZE); + avio_write(pb, c->streaminfo, FLAC_STREAMINFO_SIZE); avio_seek(pb, file_size, SEEK_SET); - avio_flush(pb); } else { av_log(s, AV_LOG_WARNING, "unable to rewrite FLAC header.\n"); } - av_freep(&c->streaminfo); - return 0; } +static void flac_deinit(struct AVFormatContext *s) +{ + FlacMuxerContext *c = s->priv_data; + + avpriv_packet_list_free(&c->queue, &c->queue_end); + for (unsigned i = 0; i < s->nb_streams; i++) + av_packet_free((AVPacket **)&s->streams[i]->priv_data); +} + static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt) { FlacMuxerContext *c = s->priv_data; @@ -361,7 +359,7 @@ if (pkt->stream_index == c->audio_stream_idx) { if (c->waiting_pics) { /* buffer audio packets until we get all the pictures */ - ret = ff_packet_list_put(&c->queue, &c->queue_end, pkt, FF_PACKETLIST_FLAG_REF_PACKET); + ret = avpriv_packet_list_put(&c->queue, &c->queue_end, pkt, av_packet_ref, 0); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Out of memory in packet queue; skipping attached pictures\n"); c->waiting_pics = 0; @@ -425,6 +423,7 @@ .write_header = flac_write_header, .write_packet = flac_write_packet, .write_trailer = flac_write_trailer, + .deinit = flac_deinit, .flags = AVFMT_NOTIMESTAMPS, .priv_class = &flac_muxer_class, }; diff -Nru ffmpeg-4.2.2/libavformat/flacenc.h ffmpeg-4.4/libavformat/flacenc.h --- ffmpeg-4.2.2/libavformat/flacenc.h 2016-03-29 02:25:28.000000000 +0000 +++ ffmpeg-4.4/libavformat/flacenc.h 2020-07-11 10:39:30.000000000 +0000 @@ -26,7 +26,7 @@ #include "libavcodec/bytestream.h" #include "avformat.h" -int ff_flac_write_header(AVIOContext *pb, uint8_t *extradata, +int ff_flac_write_header(AVIOContext *pb, const uint8_t *extradata, int extradata_size, int last_block); int ff_flac_is_native_layout(uint64_t channel_layout); diff -Nru ffmpeg-4.2.2/libavformat/flacenc_header.c ffmpeg-4.4/libavformat/flacenc_header.c --- ffmpeg-4.2.2/libavformat/flacenc_header.c 2016-03-29 02:25:28.000000000 +0000 +++ ffmpeg-4.4/libavformat/flacenc_header.c 2020-07-11 10:39:30.000000000 +0000 @@ -26,7 +26,7 @@ #include "avformat.h" #include "flacenc.h" -int ff_flac_write_header(AVIOContext *pb, uint8_t *extradata, +int ff_flac_write_header(AVIOContext *pb, const uint8_t *extradata, int extradata_size, int last_block) { uint8_t header[8] = { diff -Nru ffmpeg-4.2.2/libavformat/flac_picture.c ffmpeg-4.4/libavformat/flac_picture.c --- ffmpeg-4.2.2/libavformat/flac_picture.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/flac_picture.c 2021-04-08 21:28:40.000000000 +0000 @@ -19,51 +19,63 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" +#include "libavcodec/bytestream.h" #include "libavcodec/png.h" #include "avformat.h" #include "flac_picture.h" #include "id3v2.h" #include "internal.h" -int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) +#define MAX_TRUNC_PICTURE_SIZE (500 * 1024 * 1024) + +int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size, int truncate_workaround) { const CodecMime *mime = ff_id3v2_mime_tags; enum AVCodecID id = AV_CODEC_ID_NONE; AVBufferRef *data = NULL; uint8_t mimetype[64], *desc = NULL; - AVIOContext *pb = NULL; + GetByteContext g; AVStream *st; int width, height, ret = 0; - int len; unsigned int type; + uint32_t len, left, trunclen = 0; + + if (buf_size < 34) { + av_log(s, AV_LOG_ERROR, "Attached picture metadata block too short\n"); + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + return 0; + } - pb = avio_alloc_context(buf, buf_size, 0, NULL, NULL, NULL, NULL); - if (!pb) - return AVERROR(ENOMEM); + bytestream2_init(&g, buf, buf_size); /* read the picture type */ - type = avio_rb32(pb); + type = bytestream2_get_be32u(&g); if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types)) { av_log(s, AV_LOG_ERROR, "Invalid picture type: %d.\n", type); if (s->error_recognition & AV_EF_EXPLODE) { - RETURN_ERROR(AVERROR_INVALIDDATA); + return AVERROR_INVALIDDATA; } type = 0; } /* picture mimetype */ - len = avio_rb32(pb); - if (len <= 0 || len >= 64 || - avio_read(pb, mimetype, FFMIN(len, sizeof(mimetype) - 1)) != len) { + len = bytestream2_get_be32u(&g); + if (len <= 0 || len >= sizeof(mimetype)) { av_log(s, AV_LOG_ERROR, "Could not read mimetype from an attached " "picture.\n"); if (s->error_recognition & AV_EF_EXPLODE) - ret = AVERROR_INVALIDDATA; - goto fail; + return AVERROR_INVALIDDATA; + return 0; + } + if (len + 24 > bytestream2_get_bytes_left(&g)) { + av_log(s, AV_LOG_ERROR, "Attached picture metadata block too short\n"); + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + return 0; } - av_assert0(len < sizeof(mimetype)); + bytestream2_get_bufferu(&g, mimetype, len); mimetype[len] = 0; while (mime->id != AV_CODEC_ID_NONE) { @@ -77,49 +89,73 @@ av_log(s, AV_LOG_ERROR, "Unknown attached picture mimetype: %s.\n", mimetype); if (s->error_recognition & AV_EF_EXPLODE) - ret = AVERROR_INVALIDDATA; - goto fail; + return AVERROR_INVALIDDATA; + return 0; } /* picture description */ - len = avio_rb32(pb); + len = bytestream2_get_be32u(&g); + if (len > bytestream2_get_bytes_left(&g) - 20) { + av_log(s, AV_LOG_ERROR, "Attached picture metadata block too short\n"); + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + return 0; + } if (len > 0) { if (!(desc = av_malloc(len + 1))) { - RETURN_ERROR(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); } - if (avio_read(pb, desc, len) != len) { - av_log(s, AV_LOG_ERROR, "Error reading attached picture description.\n"); - if (s->error_recognition & AV_EF_EXPLODE) - ret = AVERROR(EIO); - goto fail; - } + bytestream2_get_bufferu(&g, desc, len); desc[len] = 0; } /* picture metadata */ - width = avio_rb32(pb); - height = avio_rb32(pb); - avio_skip(pb, 8); + width = bytestream2_get_be32u(&g); + height = bytestream2_get_be32u(&g); + bytestream2_skipu(&g, 8); /* picture data */ - len = avio_rb32(pb); - if (len <= 0) { - av_log(s, AV_LOG_ERROR, "Invalid attached picture size: %d.\n", len); - if (s->error_recognition & AV_EF_EXPLODE) - ret = AVERROR_INVALIDDATA; - goto fail; + len = bytestream2_get_be32u(&g); + + left = bytestream2_get_bytes_left(&g); + if (len <= 0 || len > left) { + if (len > MAX_TRUNC_PICTURE_SIZE || len >= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { + av_log(s, AV_LOG_ERROR, "Attached picture metadata block too big %u\n", len); + if (s->error_recognition & AV_EF_EXPLODE) + ret = AVERROR_INVALIDDATA; + goto fail; + } + + // Workaround bug for flac muxers that writs truncated metadata picture block size if + // the picture size do not fit in 24 bits. lavf flacenc used to have the issue and based + // on existing broken files other unknown flac muxers seems to truncate also. + if (truncate_workaround && + s->strict_std_compliance <= FF_COMPLIANCE_NORMAL && + len > left && (len & 0xffffff) == left) { + av_log(s, AV_LOG_INFO, "Correcting truncated metadata picture size from %u to %u\n", left, len); + trunclen = len - left; + } else { + av_log(s, AV_LOG_ERROR, "Attached picture metadata block too short\n"); + if (s->error_recognition & AV_EF_EXPLODE) + ret = AVERROR_INVALIDDATA; + goto fail; + } } if (!(data = av_buffer_alloc(len + AV_INPUT_BUFFER_PADDING_SIZE))) { RETURN_ERROR(AVERROR(ENOMEM)); } - memset(data->data + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); - if (avio_read(pb, data->data, len) != len) { - av_log(s, AV_LOG_ERROR, "Error reading attached picture data.\n"); - if (s->error_recognition & AV_EF_EXPLODE) - ret = AVERROR(EIO); - goto fail; + + if (trunclen == 0) { + bytestream2_get_bufferu(&g, data->data, len); + } else { + // If truncation was detected copy all data from block and read missing bytes + // not included in the block size + bytestream2_get_bufferu(&g, data->data, left); + if (avio_read(s->pb, data->data + len - trunclen, trunclen) < trunclen) + RETURN_ERROR(AVERROR_INVALIDDATA); } + memset(data->data + len, 0, AV_INPUT_BUFFER_PADDING_SIZE); if (AV_RB64(data->data) == PNGSIG) id = AV_CODEC_ID_PNG; @@ -129,7 +165,7 @@ RETURN_ERROR(AVERROR(ENOMEM)); } - av_init_packet(&st->attached_pic); + av_packet_unref(&st->attached_pic); st->attached_pic.buf = data; st->attached_pic.data = data->data; st->attached_pic.size = len; @@ -145,14 +181,11 @@ if (desc) av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL); - avio_context_free(&pb); - return 0; fail: av_buffer_unref(&data); av_freep(&desc); - avio_context_free(&pb); return ret; } diff -Nru ffmpeg-4.2.2/libavformat/flac_picture.h ffmpeg-4.4/libavformat/flac_picture.h --- ffmpeg-4.2.2/libavformat/flac_picture.h 2016-03-29 02:25:28.000000000 +0000 +++ ffmpeg-4.4/libavformat/flac_picture.h 2020-07-11 10:39:30.000000000 +0000 @@ -26,6 +26,6 @@ #define RETURN_ERROR(code) do { ret = (code); goto fail; } while (0) -int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size); +int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size, int truncate_workaround); #endif /* AVFORMAT_FLAC_PICTURE_H */ diff -Nru ffmpeg-4.2.2/libavformat/flic.c ffmpeg-4.4/libavformat/flic.c --- ffmpeg-4.2.2/libavformat/flic.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/flic.c 2021-04-08 21:28:40.000000000 +0000 @@ -89,7 +89,7 @@ AVIOContext *pb = s->pb; unsigned char header[FLIC_HEADER_SIZE]; AVStream *st, *ast; - int speed; + int speed, ret; int magic_number; unsigned char preamble[FLIC_PREAMBLE_SIZE]; @@ -125,8 +125,8 @@ } /* send over the whole 128-byte FLIC header */ - if (ff_alloc_extradata(st->codecpar, FLIC_HEADER_SIZE)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, FLIC_HEADER_SIZE)) < 0) + return ret; memcpy(st->codecpar->extradata, header, FLIC_HEADER_SIZE); /* peek at the preamble to detect TFTD videos - they seem to always start with an audio chunk */ @@ -175,9 +175,8 @@ avio_seek(pb, 12, SEEK_SET); /* send over abbreviated FLIC header chunk */ - av_freep(&st->codecpar->extradata); - if (ff_alloc_extradata(st->codecpar, 12)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 12)) < 0) + return ret; memcpy(st->codecpar->extradata, header, 12); } else if (magic_number == FLIC_FILE_MAGIC_1) { @@ -203,6 +202,7 @@ int magic; int ret = 0; unsigned char preamble[FLIC_PREAMBLE_SIZE]; + int64_t pos = avio_tell(pb); while (!packet_read && !avio_feof(pb)) { @@ -216,37 +216,38 @@ magic = AV_RL16(&preamble[4]); if (((magic == FLIC_CHUNK_MAGIC_1) || (magic == FLIC_CHUNK_MAGIC_2)) && size > FLIC_PREAMBLE_SIZE) { - if (av_new_packet(pkt, size)) { - ret = AVERROR(EIO); - break; - } + if ((ret = av_new_packet(pkt, size)) < 0) + return ret; + pkt->stream_index = flic->video_stream_index; - pkt->pts = flic->frame_number++; - pkt->pos = avio_tell(pb); + pkt->pos = pos; memcpy(pkt->data, preamble, FLIC_PREAMBLE_SIZE); ret = avio_read(pb, pkt->data + FLIC_PREAMBLE_SIZE, size - FLIC_PREAMBLE_SIZE); if (ret != size - FLIC_PREAMBLE_SIZE) { - av_packet_unref(pkt); ret = AVERROR(EIO); } + pkt->flags = flic->frame_number == 0 ? AV_PKT_FLAG_KEY : 0; + pkt->pts = flic->frame_number; + if (flic->frame_number == 0) + av_add_index_entry(s->streams[flic->video_stream_index], pkt->pos, pkt->pts, pkt->size, 0, AVINDEX_KEYFRAME); packet_read = 1; + flic->frame_number++; } else if (magic == FLIC_TFTD_CHUNK_AUDIO) { - if (av_new_packet(pkt, size)) { - ret = AVERROR(EIO); - break; - } + if ((ret = av_new_packet(pkt, size)) < 0) + return ret; /* skip useless 10B sub-header (yes, it's not accounted for in the chunk header) */ avio_skip(pb, 10); pkt->stream_index = flic->audio_stream_index; - pkt->pos = avio_tell(pb); + pkt->pos = pos; + pkt->flags = AV_PKT_FLAG_KEY; ret = avio_read(pb, pkt->data, size); if (ret != size) { - av_packet_unref(pkt); ret = AVERROR(EIO); + break; } packet_read = 1; @@ -259,6 +260,31 @@ return avio_feof(pb) ? AVERROR_EOF : ret; } +static int flic_read_seek(AVFormatContext *s, int stream_index, + int64_t pts, int flags) +{ + FlicDemuxContext *flic = s->priv_data; + AVStream *st = s->streams[stream_index]; + int64_t pos, ts; + int index; + + if (!st->index_entries || stream_index != flic->video_stream_index) + return -1; + + index = av_index_search_timestamp(st, pts, flags); + + if (index < 0) + index = av_index_search_timestamp(st, pts, flags ^ AVSEEK_FLAG_BACKWARD); + if (index < 0) + return -1; + + pos = st->index_entries[index].pos; + ts = st->index_entries[index].timestamp; + flic->frame_number = ts; + avio_seek(s->pb, pos, SEEK_SET); + return 0; +} + AVInputFormat ff_flic_demuxer = { .name = "flic", .long_name = NULL_IF_CONFIG_SMALL("FLI/FLC/FLX animation"), @@ -266,4 +292,5 @@ .read_probe = flic_probe, .read_header = flic_read_header, .read_packet = flic_read_packet, + .read_seek = flic_read_seek, }; diff -Nru ffmpeg-4.2.2/libavformat/flvdec.c ffmpeg-4.4/libavformat/flvdec.c --- ffmpeg-4.2.2/libavformat/flvdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/flvdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -32,7 +32,6 @@ #include "libavutil/mathematics.h" #include "libavutil/time_internal.h" #include "libavcodec/bytestream.h" -#include "libavcodec/mpeg4audio.h" #include "avformat.h" #include "internal.h" #include "avio_internal.h" @@ -42,6 +41,8 @@ #define RESYNC_BUFFER_SIZE (1<<20) +#define MAX_DEPTH 16 ///< arbitrary limit to prevent unbounded recursion + typedef struct FLVContext { const AVClass *class; ///< Class for private options. int trust_metadata; ///< configure streams according onMetaData @@ -383,13 +384,18 @@ static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize) { + int ret; int length = avio_rb16(ioc); if (length >= buffsize) { avio_skip(ioc, length); return -1; } - avio_read(ioc, buffer, length); + ret = avio_read(ioc, buffer, length); + if (ret < 0) + return ret; + if (ret < length) + return AVERROR_INVALIDDATA; buffer[length] = '\0'; @@ -447,9 +453,13 @@ } for (i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) { + double d; if (avio_r8(ioc) != AMF_DATA_TYPE_NUMBER) goto invalid; - current_array[0][i] = av_int2double(avio_rb64(ioc)); + d = av_int2double(avio_rb64(ioc)); + if (isnan(d) || d < INT64_MIN || d > INT64_MAX) + goto invalid; + current_array[0][i] = d; } if (times && filepositions) { // All done, exiting at a position allowing amf_parse_object @@ -494,8 +504,13 @@ double num_val; amf_date date; + if (depth > MAX_DEPTH) + return AVERROR_PATCHWELCOME; + num_val = 0; ioc = s->pb; + if (avio_feof(ioc)) + return AVERROR_EOF; amf_type = avio_r8(ioc); switch (amf_type) { @@ -515,8 +530,7 @@ if (key && (ioc->seekable & AVIO_SEEKABLE_NORMAL) && !strcmp(KEYFRAMES_TAG, key) && depth == 1) - if (parse_keyframes_index(s, ioc, - max_pos) < 0) + if (parse_keyframes_index(s, ioc, max_pos) < 0) av_log(s, AV_LOG_ERROR, "Keyframe index parsing failed\n"); else add_keyframes_index(s); @@ -717,7 +731,7 @@ if (!strcmp(buffer, "onCaptionInfo")) return TYPE_ONCAPTIONINFO; - if (strcmp(buffer, "onMetaData") && strcmp(buffer, "onCuePoint")) { + if (strcmp(buffer, "onMetaData") && strcmp(buffer, "onCuePoint") && strcmp(buffer, "|RtmpSampleAccess")) { av_log(s, AV_LOG_DEBUG, "Unknown type %s\n", buffer); return TYPE_UNKNOWN; } @@ -733,8 +747,7 @@ astream = stream; if (flv->last_keyframe_stream_index == -1) flv->last_keyframe_stream_index = i; - } - else if (stream->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) + } else if (stream->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) dstream = stream; } @@ -796,12 +809,12 @@ static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size) { + int ret; if (!size) return 0; - av_freep(&st->codecpar->extradata); - if (ff_get_extradata(s, st->codecpar, s->pb, size) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0) + return ret; st->internal->need_context_update = 1; return 0; } @@ -838,10 +851,16 @@ } } -static int amf_skip_tag(AVIOContext *pb, AMFDataType type) +static int amf_skip_tag(AVIOContext *pb, AMFDataType type, int depth) { int nb = -1, ret, parse_name = 1; + if (depth > MAX_DEPTH) + return AVERROR_PATCHWELCOME; + + if (avio_feof(pb)) + return AVERROR_EOF; + switch (type) { case AMF_DATA_TYPE_NUMBER: avio_skip(pb, 8); @@ -856,6 +875,8 @@ parse_name = 0; case AMF_DATA_TYPE_MIXEDARRAY: nb = avio_rb32(pb); + if (nb < 0) + return AVERROR_INVALIDDATA; case AMF_DATA_TYPE_OBJECT: while(!pb->eof_reached && (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY)) { if (parse_name) { @@ -866,7 +887,7 @@ } avio_skip(pb, size); } - if ((ret = amf_skip_tag(pb, avio_r8(pb))) < 0) + if ((ret = amf_skip_tag(pb, avio_r8(pb), depth + 1)) < 0) return ret; } break; @@ -910,7 +931,7 @@ else break; } else { - if ((ret = amf_skip_tag(pb, type)) < 0) + if ((ret = amf_skip_tag(pb, type, 0)) < 0) goto skip; } } @@ -1059,8 +1080,7 @@ if (type == 0 && dts == 0 || type < 0) { if (type < 0 && flv->validate_count && flv->validate_index[0].pos > next && - flv->validate_index[0].pos - 4 < next - ) { + flv->validate_index[0].pos - 4 < next) { av_log(s, AV_LOG_WARNING, "Adjusting next position due to index mismatch\n"); next = flv->validate_index[0].pos - 4; } @@ -1121,7 +1141,6 @@ st = create_stream(s, stream_types[stream_type]); if (!st) return AVERROR(ENOMEM); - } av_log(s, AV_LOG_TRACE, "%d %X %d \n", stream_type, flags, st->discard); @@ -1134,10 +1153,9 @@ stream_type == FLV_STREAM_TYPE_AUDIO)) av_add_index_entry(st, pos, dts, size, 0, AVINDEX_KEYFRAME); - if ( (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || (stream_type == FLV_STREAM_TYPE_AUDIO))) - ||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && (stream_type == FLV_STREAM_TYPE_VIDEO))) - || st->discard >= AVDISCARD_ALL - ) { + if ((st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || stream_type == FLV_STREAM_TYPE_AUDIO)) || + (st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && stream_type == FLV_STREAM_TYPE_VIDEO)) || + st->discard >= AVDISCARD_ALL) { avio_seek(s->pb, next, SEEK_SET); ret = FFERROR_REDO; goto leave; @@ -1162,7 +1180,7 @@ avio_seek(s->pb, fsize - 3 - size, SEEK_SET); if (size == avio_rb24(s->pb) + 11) { uint32_t ts = avio_rb24(s->pb); - ts |= avio_r8(s->pb) << 24; + ts |= (unsigned)avio_r8(s->pb) << 24; if (ts) s->duration = ts * (int64_t)AV_TIME_BASE / 1000; else if (fsize >= 8 && fsize - 8 >= size) { @@ -1235,7 +1253,7 @@ if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4) { // sign extension int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000; - pts = dts + cts; + pts = av_sat_add64(dts, cts); if (cts < 0) { // dts might be wrong if (!flv->wrong_dts) av_log(s, AV_LOG_WARNING, @@ -1265,22 +1283,6 @@ if (st->codecpar->codec_id == AV_CODEC_ID_AAC && t && !strcmp(t->value, "Omnia A/XE")) st->codecpar->extradata_size = 2; - if (st->codecpar->codec_id == AV_CODEC_ID_AAC && 0) { - MPEG4AudioConfig cfg; - - if (avpriv_mpeg4audio_get_config(&cfg, st->codecpar->extradata, - st->codecpar->extradata_size * 8, 1) >= 0) { - st->codecpar->channels = cfg.channels; - st->codecpar->channel_layout = 0; - if (cfg.ext_sample_rate) - st->codecpar->sample_rate = cfg.ext_sample_rate; - else - st->codecpar->sample_rate = cfg.sample_rate; - av_log(s, AV_LOG_TRACE, "mp4a config channels %d sample rate %d\n", - st->codecpar->channels, st->codecpar->sample_rate); - } - } - ret = FFERROR_REDO; goto leave; } @@ -1300,12 +1302,11 @@ pkt->stream_index = st->index; pkt->pos = pos; if (flv->new_extradata[stream_type]) { - uint8_t *side = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, - flv->new_extradata_size[stream_type]); - if (side) { - memcpy(side, flv->new_extradata[stream_type], - flv->new_extradata_size[stream_type]); - av_freep(&flv->new_extradata[stream_type]); + int ret = av_packet_add_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, + flv->new_extradata[stream_type], + flv->new_extradata_size[stream_type]); + if (ret >= 0) { + flv->new_extradata[stream_type] = NULL; flv->new_extradata_size[stream_type] = 0; } } @@ -1317,10 +1318,10 @@ ff_add_param_change(pkt, channels, 0, sample_rate, 0, 0); } - if ( stream_type == FLV_STREAM_TYPE_AUDIO || - ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY) || - stream_type == FLV_STREAM_TYPE_SUBTITLE || - stream_type == FLV_STREAM_TYPE_DATA) + if (stream_type == FLV_STREAM_TYPE_AUDIO || + (flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || + stream_type == FLV_STREAM_TYPE_SUBTITLE || + stream_type == FLV_STREAM_TYPE_DATA) pkt->flags |= AV_PKT_FLAG_KEY; leave: diff -Nru ffmpeg-4.2.2/libavformat/flvenc.c ffmpeg-4.4/libavformat/flvenc.c --- ffmpeg-4.2.2/libavformat/flvenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/flvenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -580,7 +580,7 @@ int n = 0; int64_t metadata_size = 0; FLVContext *flv = s->priv_data; - int64_t pos, pos_end = avio_tell(s->pb); + 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]; @@ -608,7 +608,6 @@ avio_seek(s->pb, flv->metadata_totalsize_pos, SEEK_SET); avio_wb32(s->pb, flv->metadata_totalsize + 11 + metadata_size); - avio_seek(s->pb, pos_end, SEEK_SET); /* 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 @@ -621,9 +620,7 @@ 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); + /* 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 */ @@ -887,7 +884,7 @@ unsigned ts; int size = pkt->size; uint8_t *data = NULL; - int flags = -1, flags_size, ret; + int flags = -1, flags_size, ret = 0; int64_t cur_offset = avio_tell(pb); if (par->codec_type == AVMEDIA_TYPE_AUDIO && !pkt->size) { @@ -905,17 +902,13 @@ if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) { - int side_size = 0; + buffer_size_t side_size; uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { - av_free(par->extradata); - par->extradata = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!par->extradata) { - par->extradata_size = 0; - return AVERROR(ENOMEM); - } + ret = ff_alloc_extradata(par, side_size); + if (ret < 0) + return ret; memcpy(par->extradata, side, side_size); - par->extradata_size = side_size; flv_write_codec_header(s, par, pkt->dts); } } @@ -928,6 +921,12 @@ "Packets are not in the proper order with respect to DTS\n"); return AVERROR(EINVAL); } + if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) { + if (pkt->pts == AV_NOPTS_VALUE) { + av_log(s, AV_LOG_ERROR, "Packet is missing PTS\n"); + return AVERROR(EINVAL); + } + } ts = pkt->dts; @@ -970,10 +969,10 @@ } else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { if (!s->streams[pkt->stream_index]->nb_frames) { - av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: " - "use the audio bitstream filter 'aac_adtstoasc' to fix it " - "('-bsf:a aac_adtstoasc' option with ffmpeg)\n"); - return AVERROR_INVALIDDATA; + av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: " + "use the audio bitstream filter 'aac_adtstoasc' to fix it " + "('-bsf:a aac_adtstoasc' option with ffmpeg)\n"); + return AVERROR_INVALIDDATA; } av_log(s, AV_LOG_WARNING, "aac bitstream error\n"); } @@ -990,7 +989,8 @@ if (size + flags_size >= 1<<24) { av_log(s, AV_LOG_ERROR, "Too large packet with size %u >= %u\n", size + flags_size, 1<<24); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } avio_wb24(pb, size + flags_size); @@ -1055,15 +1055,17 @@ case AVMEDIA_TYPE_VIDEO: flv->videosize += (avio_tell(pb) - cur_offset); flv->lasttimestamp = flv->acurframeindex / flv->framerate; + flv->acurframeindex++; if (pkt->flags & AV_PKT_FLAG_KEY) { - double ts = flv->acurframeindex / flv->framerate; + double ts = flv->lasttimestamp; int64_t pos = cur_offset; - flv->lastkeyframetimestamp = flv->acurframeindex / flv->framerate; + flv->lastkeyframetimestamp = ts; flv->lastkeyframelocation = pos; - flv_append_keyframe_info(s, flv, ts, pos); + ret = flv_append_keyframe_info(s, flv, ts, pos); + if (ret < 0) + goto fail; } - flv->acurframeindex++; break; case AVMEDIA_TYPE_AUDIO: @@ -1075,10 +1077,10 @@ break; } } - +fail: av_free(data); - return pb->error; + return ret; } static int flv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) diff -Nru ffmpeg-4.2.2/libavformat/framecrcenc.c ffmpeg-4.4/libavformat/framecrcenc.c --- ffmpeg-4.2.2/libavformat/framecrcenc.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/framecrcenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,8 +21,11 @@ #include +#include "config.h" #include "libavutil/adler32.h" #include "libavutil/avstring.h" +#include "libavutil/intreadwrite.h" +#include "libavcodec/avcodec.h" #include "avformat.h" #include "internal.h" @@ -42,6 +45,17 @@ return ff_framehash_write_header(s); } +static av_unused void inline bswap(char *buf, int offset, int size) +{ + if (size == 8) { + uint64_t val = AV_RN64(buf + offset); + AV_WN64(buf + offset, av_bswap64(val)); + } else if (size == 4) { + uint32_t val = AV_RN32(buf + offset); + AV_WN32(buf + offset, av_bswap32(val)); + } +} + static int framecrc_write_packet(struct AVFormatContext *s, AVPacket *pkt) { uint32_t crc = av_adler32_update(0, pkt->data, pkt->size); @@ -52,21 +66,58 @@ if (pkt->flags != AV_PKT_FLAG_KEY) av_strlcatf(buf, sizeof(buf), ", F=0x%0X", pkt->flags); if (pkt->side_data_elems) { - int i, j; + int i; av_strlcatf(buf, sizeof(buf), ", S=%d", pkt->side_data_elems); for (i=0; iside_data_elems; i++) { + const AVPacketSideData *const sd = &pkt->side_data[i]; + const uint8_t *data = sd->data; uint32_t side_data_crc = 0; - if (HAVE_BIGENDIAN && AV_PKT_DATA_PALETTE == pkt->side_data[i].type) { - for (j=0; jside_data[i].size; j++) { - side_data_crc = av_adler32_update(side_data_crc, - pkt->side_data[i].data + (j^3), - 1); + + switch (sd->type) { +#if HAVE_BIGENDIAN + uint8_t bswap_buf[FFMAX(sizeof(AVCPBProperties), + sizeof(AVProducerReferenceTime))]; + case AV_PKT_DATA_PALETTE: + case AV_PKT_DATA_REPLAYGAIN: + case AV_PKT_DATA_DISPLAYMATRIX: + case AV_PKT_DATA_STEREO3D: + case AV_PKT_DATA_AUDIO_SERVICE_TYPE: + case AV_PKT_DATA_FALLBACK_TRACK: + case AV_PKT_DATA_MASTERING_DISPLAY_METADATA: + case AV_PKT_DATA_SPHERICAL: + case AV_PKT_DATA_CONTENT_LIGHT_LEVEL: + case AV_PKT_DATA_S12M_TIMECODE: + for (int j = 0; j < sd->size / 4; j++) { + uint8_t buf[4]; + AV_WL32(buf, AV_RB32(sd->data + 4 * j)); + side_data_crc = av_adler32_update(side_data_crc, buf, 4); + } + break; + case AV_PKT_DATA_CPB_PROPERTIES: +#define BSWAP(struct, field) bswap(bswap_buf, offsetof(struct, field), sizeof(((struct){0}).field)) + if (sd->size == sizeof(AVCPBProperties)) { + memcpy(bswap_buf, sd->data, sizeof(AVCPBProperties)); + data = bswap_buf; + BSWAP(AVCPBProperties, max_bitrate); + BSWAP(AVCPBProperties, min_bitrate); + BSWAP(AVCPBProperties, avg_bitrate); + BSWAP(AVCPBProperties, buffer_size); + BSWAP(AVCPBProperties, vbv_delay); + } + goto pod; + case AV_PKT_DATA_PRFT: + if (sd->size == sizeof(AVProducerReferenceTime)) { + memcpy(bswap_buf, sd->data, sizeof(AVProducerReferenceTime)); + data = bswap_buf; + BSWAP(AVProducerReferenceTime, wallclock); + BSWAP(AVProducerReferenceTime, flags); } - } else { - side_data_crc = av_adler32_update(0, - pkt->side_data[i].data, - pkt->side_data[i].size); + goto pod; + pod: +#endif + default: + side_data_crc = av_adler32_update(0, data, sd->size); } av_strlcatf(buf, sizeof(buf), ", %8d, 0x%08"PRIx32, pkt->side_data[i].size, side_data_crc); } diff -Nru ffmpeg-4.2.2/libavformat/framehash.c ffmpeg-4.4/libavformat/framehash.c --- ffmpeg-4.2.2/libavformat/framehash.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/framehash.c 2020-07-11 10:39:30.000000000 +0000 @@ -45,7 +45,6 @@ avio_printf(s->pb, "#sar %d: %d/%d\n", i, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); break; } - avio_flush(s->pb); } return 0; } diff -Nru ffmpeg-4.2.2/libavformat/frmdec.c ffmpeg-4.4/libavformat/frmdec.c --- ffmpeg-4.2.2/libavformat/frmdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/frmdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -29,13 +29,12 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" -static const PixelFormatTag frm_pix_fmt_tags[] = { - { AV_PIX_FMT_RGB555, 1 }, - { AV_PIX_FMT_RGB0, 2 }, - { AV_PIX_FMT_RGB24, 3 }, - { AV_PIX_FMT_BGR0, 4 }, - { AV_PIX_FMT_BGRA, 5 }, - { AV_PIX_FMT_NONE, 0 }, +static const enum AVPixelFormat frm_pix_fmt_tags[] = { + AV_PIX_FMT_RGB555, + AV_PIX_FMT_RGB0, + AV_PIX_FMT_RGB24, + AV_PIX_FMT_BGR0, + AV_PIX_FMT_BGRA, }; typedef struct { @@ -55,6 +54,8 @@ { AVIOContext *pb = avctx->pb; AVStream *st = avformat_new_stream(avctx, 0); + unsigned idx; + if (!st) return AVERROR(ENOMEM); @@ -62,9 +63,10 @@ st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; avio_skip(pb, 3); - st->codecpar->format = avpriv_find_pix_fmt(frm_pix_fmt_tags, avio_r8(pb)); - if (!st->codecpar->format) + idx = avio_r8(pb) - 1; + if (idx >= FF_ARRAY_ELEMS(frm_pix_fmt_tags)) return AVERROR_INVALIDDATA; + st->codecpar->format = frm_pix_fmt_tags[idx]; st->codecpar->codec_tag = 0; st->codecpar->width = avio_rl16(pb); diff -Nru ffmpeg-4.2.2/libavformat/fsb.c ffmpeg-4.4/libavformat/fsb.c --- ffmpeg-4.2.2/libavformat/fsb.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/fsb.c 2020-07-11 10:39:30.000000000 +0000 @@ -41,6 +41,7 @@ int64_t offset; AVCodecParameters *par; AVStream *st = avformat_new_stream(s, NULL); + int ret; avio_skip(pb, 3); // "FSB" version = avio_r8(pb) - '0'; @@ -86,9 +87,9 @@ par->block_align = 8 * par->channels; if (par->channels > INT_MAX / 32) return AVERROR_INVALIDDATA; - ff_alloc_extradata(par, 32 * par->channels); - if (!par->extradata) - return AVERROR(ENOMEM); + ret = ff_alloc_extradata(par, 32 * par->channels); + if (ret < 0) + return ret; avio_seek(pb, 0x68, SEEK_SET); for (c = 0; c < par->channels; c++) { avio_read(pb, par->extradata + 32 * c, 32); @@ -130,18 +131,18 @@ switch (par->codec_id) { case AV_CODEC_ID_XMA2: - ff_alloc_extradata(par, 34); - if (!par->extradata) - return AVERROR(ENOMEM); + ret = ff_alloc_extradata(par, 34); + if (ret < 0) + return ret; memset(par->extradata, 0, 34); par->block_align = 2048; break; case AV_CODEC_ID_ADPCM_THP: if (par->channels > INT_MAX / 32) return AVERROR_INVALIDDATA; - ff_alloc_extradata(par, 32 * par->channels); - if (!par->extradata) - return AVERROR(ENOMEM); + ret = ff_alloc_extradata(par, 32 * par->channels); + if (ret < 0) + return ret; avio_seek(pb, 0x80, SEEK_SET); for (c = 0; c < par->channels; c++) { avio_read(pb, par->extradata + 32 * c, 32); diff -Nru ffmpeg-4.2.2/libavformat/ftp.c ffmpeg-4.4/libavformat/ftp.c --- ffmpeg-4.2.2/libavformat/ftp.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ftp.c 2020-07-11 10:39:30.000000000 +0000 @@ -18,12 +18,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/avstring.h" #include "libavutil/internal.h" #include "libavutil/parseutils.h" #include "avformat.h" #include "internal.h" #include "url.h" +#include "urldecode.h" #include "libavutil/opt.h" #include "libavutil/bprint.h" @@ -36,7 +39,8 @@ DOWNLOADING, UPLOADING, LISTING_DIR, - DISCONNECTED + DISCONNECTED, + ENDOFFILE, } FTPState; typedef enum { @@ -69,6 +73,8 @@ size_t dir_buffer_size; size_t dir_buffer_offset; int utf8; + const char *option_user; /**< User to be used if none given in the URL */ + const char *option_password; /**< Password to be used if none given in the URL */ } FTPContext; #define OFFSET(x) offsetof(FTPContext, x) @@ -78,6 +84,8 @@ {"timeout", "set timeout of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E }, {"ftp-write-seekable", "control seekability of connection during encoding", OFFSET(write_seekable), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E }, {"ftp-anonymous-password", "password for anonymous login. E-mail address should be used.", OFFSET(anonymous_password), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E }, + {"ftp-user", "user for FTP login. Overridden by whatever is in the URL.", OFFSET(option_user), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E }, + {"ftp-password", "password for FTP login. Overridden by whatever is in the URL.", OFFSET(option_password), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E }, {NULL} }; @@ -224,7 +232,6 @@ static void ftp_close_data_connection(FTPContext *s) { ffurl_closep(&s->conn_data); - s->position = 0; s->state = DISCONNECTED; } @@ -241,10 +248,14 @@ static const int user_codes[] = {331, 230, 0}; static const int pass_codes[] = {230, 0}; + if (strpbrk(s->user, "\r\n")) + return AVERROR(EINVAL); snprintf(buf, sizeof(buf), "USER %s\r\n", s->user); 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 = ftp_send_command(s, buf, pass_codes, NULL); } else @@ -322,15 +333,15 @@ *end = '\0'; /* skip ip */ if (!av_strtok(start, ",", &end)) goto fail; - if (!av_strtok(end, ",", &end)) goto fail; - if (!av_strtok(end, ",", &end)) goto fail; - if (!av_strtok(end, ",", &end)) goto fail; + if (!av_strtok(NULL, ",", &end)) goto fail; + if (!av_strtok(NULL, ",", &end)) goto fail; + if (!av_strtok(NULL, ",", &end)) goto fail; /* parse port number */ - start = av_strtok(end, ",", &end); + start = av_strtok(NULL, ",", &end); if (!start) goto fail; s->server_data_port = atoi(start) * 256; - start = av_strtok(end, ",", &end); + start = av_strtok(NULL, ",", &end); if (!start) goto fail; s->server_data_port += atoi(start); ff_dlog(s, "Server data port: %d\n", s->server_data_port); @@ -652,9 +663,9 @@ static int ftp_connect(URLContext *h, const char *url) { - char proto[10], path[MAX_URL_SIZE], credencials[MAX_URL_SIZE], hostname[MAX_URL_SIZE]; + char proto[10], path[MAX_URL_SIZE], credentials[MAX_URL_SIZE], hostname[MAX_URL_SIZE]; const char *tok_user = NULL, *tok_pass = NULL; - char *end = NULL, *newpath = NULL; + char *newpath = NULL; int err; FTPContext *s = h->priv_data; @@ -665,20 +676,34 @@ s->features = NULL; av_url_split(proto, sizeof(proto), - credencials, sizeof(credencials), + credentials, sizeof(credentials), hostname, sizeof(hostname), &s->server_control_port, path, sizeof(path), url); - tok_user = av_strtok(credencials, ":", &end); - tok_pass = av_strtok(end, ":", &end); - if (!tok_user) { - tok_user = "anonymous"; - tok_pass = av_x_if_null(s->anonymous_password, "nopassword"); + if (!*credentials) { + if (!s->option_user) { + tok_user = "anonymous"; + tok_pass = av_x_if_null(s->anonymous_password, "nopassword"); + } else { + tok_user = s->option_user; + tok_pass = s->option_password; + } + s->user = av_strdup(tok_user); + s->password = av_strdup(tok_pass); + } else { + char *pass = strchr(credentials, ':'); + if (pass) { + *pass++ = '\0'; + tok_pass = pass; + s->password = ff_urldecode(pass, 0); + } else { + tok_pass = s->option_password; + s->password = av_strdup(tok_pass); + } + s->user = ff_urldecode(credentials, 0); } - s->user = av_strdup(tok_user); - s->password = av_strdup(tok_pass); s->hostname = av_strdup(hostname); if (!s->hostname || !s->user || (tok_pass && !s->password)) { return AVERROR(ENOMEM); @@ -715,8 +740,7 @@ if (ftp_restart(s, 0) < 0) { h->is_streamed = 1; } else { - if (ftp_file_size(s) < 0 && flags & AVIO_FLAG_READ) - h->is_streamed = 1; + ftp_file_size(s); if (s->write_seekable != 1 && flags & AVIO_FLAG_WRITE) h->is_streamed = 1; } @@ -733,7 +757,7 @@ { FTPContext *s = h->priv_data; int err; - int64_t new_pos, fake_pos; + int64_t new_pos; ff_dlog(h, "ftp protocol seek %"PRId64" %d\n", pos, whence); @@ -763,11 +787,10 @@ return AVERROR(EINVAL); } - fake_pos = s->filesize != -1 ? FFMIN(new_pos, s->filesize) : new_pos; - if (fake_pos != s->position) { + if (new_pos != s->position) { if ((err = ftp_abort(h)) < 0) return err; - s->position = fake_pos; + s->position = new_pos; } return new_pos; } @@ -779,16 +802,13 @@ ff_dlog(h, "ftp protocol read %d bytes\n", size); retry: + if (s->state == ENDOFFILE) + return AVERROR_EOF; if (s->state == DISCONNECTED) { - /* optimization */ - if (s->position >= s->filesize) - return AVERROR_EOF; if ((err = ftp_connect_data_connection(h)) < 0) return err; } if (s->state == READY) { - if (s->position >= s->filesize) - return AVERROR_EOF; if ((err = ftp_retrieve(s)) < 0) return err; } @@ -796,27 +816,28 @@ read = ffurl_read(s->conn_data, buf, size); if (read >= 0) { s->position += read; - if (s->position >= s->filesize) { - /* server will terminate, but keep current position to avoid madness */ - /* save position to restart from it */ - int64_t pos = s->position; - if (ftp_abort(h) < 0) { - s->position = pos; - return AVERROR(EIO); - } - s->position = pos; - } + s->filesize = FFMAX(s->filesize, s->position); } - if (read <= 0 && s->position < s->filesize && !h->is_streamed) { + if (read == AVERROR_EOF) { + static const int retr_codes[] = {226, 250, 425, 426, 451, 0}; + char *response = NULL; + err = ftp_status(s, &response, retr_codes); + if (err == 226) { + ftp_close_data_connection(s); + av_freep(&response); + s->state = ENDOFFILE; + return AVERROR_EOF; + } + /* 250 is not allowed, any other status means some kind of error */ + av_log(h, AV_LOG_ERROR, "FTP transfer failed: %s\n", response ? response : (err < 0 ? av_err2str(err) : "?")); + av_freep(&response); + read = AVERROR(EIO); + } + if (read <= 0 && !h->is_streamed) { /* Server closed connection. Probably due to inactivity */ - int64_t pos = s->position; av_log(h, AV_LOG_INFO, "Reconnect to FTP server.\n"); if ((err = ftp_abort(h)) < 0) return err; - if ((err = ftp_seek(h, pos, SEEK_SET)) < 0) { - av_log(h, AV_LOG_ERROR, "Position cannot be restored.\n"); - return err; - } if (!retry_done) { retry_done = 1; goto retry; @@ -942,8 +963,10 @@ static int ftp_parse_entry_mlsd(char *mlsd, AVIODirEntry *next) { char *fact, *value; + char *saveptr = NULL, *p = mlsd; ff_dlog(NULL, "%s\n", mlsd); - while(fact = av_strtok(mlsd, ";", &mlsd)) { + while(fact = av_strtok(p, ";", &saveptr)) { + p = NULL; if (fact[0] == ' ') { next->name = av_strdup(&fact[1]); continue; diff -Nru ffmpeg-4.2.2/libavformat/fwse.c ffmpeg-4.4/libavformat/fwse.c --- ffmpeg-4.2.2/libavformat/fwse.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/fwse.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,88 @@ +/* + * FWSE demuxer + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "internal.h" +#include "pcm.h" + +static int fwse_probe(const AVProbeData *p) +{ + if (AV_RL32(p->buf) != MKTAG('F','W','S','E')) + return 0; + if (AV_RL32(p->buf+4) != 2 && AV_RL32(p->buf+4) != 3) + return 0; + if (AV_RL32(p->buf+16) != 1 && AV_RL32(p->buf+16) != 2) + return 0; + + return AVPROBE_SCORE_MAX / 4 * 3; +} + +static int fwse_read_header(AVFormatContext *s) +{ + unsigned start_offset, version; + AVIOContext *pb = s->pb; + AVCodecParameters *par; + AVStream *st; + + avio_skip(pb, 4); + version = avio_rl32(pb); + if (version != 2 && version != 3) + return AVERROR_INVALIDDATA; + avio_skip(pb, 4); + start_offset = avio_rl32(pb); + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = AV_CODEC_ID_ADPCM_IMA_MTF; + par->format = AV_SAMPLE_FMT_S16; + par->channels = avio_rl32(pb); + if (par->channels != 1 && par->channels != 2) + return AVERROR_INVALIDDATA; + if (par->channels == 1) + par->channel_layout = AV_CH_LAYOUT_MONO; + else if (par->channels == 2) + par->channel_layout = AV_CH_LAYOUT_STEREO; + st->duration = avio_rl32(pb); + par->sample_rate = avio_rl32(pb); + if (par->sample_rate <= 0 || par->sample_rate > INT_MAX) + return AVERROR_INVALIDDATA; + + par->block_align = 1; + avio_skip(pb, start_offset - avio_tell(pb)); + + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + + return 0; +} + +AVInputFormat ff_fwse_demuxer = { + .name = "fwse", + .long_name = NULL_IF_CONFIG_SMALL("Capcom's MT Framework sound"), + .read_probe = fwse_probe, + .read_header = fwse_read_header, + .read_packet = ff_pcm_read_packet, + .extensions = "fwse", +}; diff -Nru ffmpeg-4.2.2/libavformat/g723_1.c ffmpeg-4.4/libavformat/g723_1.c --- ffmpeg-4.2.2/libavformat/g723_1.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/g723_1.c 2020-07-11 10:39:30.000000000 +0000 @@ -69,7 +69,6 @@ ret = avio_read(s->pb, pkt->data + 1, size - 1); if (ret < size - 1) { - av_packet_unref(pkt); return ret < 0 ? ret : AVERROR_EOF; } diff -Nru ffmpeg-4.2.2/libavformat/g729dec.c ffmpeg-4.4/libavformat/g729dec.c --- ffmpeg-4.2.2/libavformat/g729dec.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/g729dec.c 2020-07-11 10:39:30.000000000 +0000 @@ -61,8 +61,7 @@ return AVERROR(EINVAL); } - avpriv_set_pts_info(st, st->codecpar->block_align << 3, 1, - st->codecpar->sample_rate); + avpriv_set_pts_info(st, 64, 80, st->codecpar->sample_rate); return 0; } @@ -76,6 +75,7 @@ pkt->stream_index = 0; pkt->dts = pkt->pts = pkt->pos / st->codecpar->block_align; + pkt->duration = 1; return 0; } diff -Nru ffmpeg-4.2.2/libavformat/gdv.c ffmpeg-4.4/libavformat/gdv.c --- ffmpeg-4.2.2/libavformat/gdv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/gdv.c 2020-07-11 10:39:30.000000000 +0000 @@ -182,7 +182,6 @@ pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); if (!pal) { - av_packet_unref(pkt); return AVERROR(ENOMEM); } memcpy(pal, gdv->pal, AVPALETTE_SIZE); diff -Nru ffmpeg-4.2.2/libavformat/genh.c ffmpeg-4.4/libavformat/genh.c --- ffmpeg-4.2.2/libavformat/genh.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/genh.c 2021-02-20 20:27:47.000000000 +0000 @@ -87,7 +87,9 @@ case 5: st->codecpar->codec_id = st->codecpar->block_align > 0 ? AV_CODEC_ID_PCM_S8_PLANAR : AV_CODEC_ID_PCM_S8; break; - case 6: st->codecpar->codec_id = AV_CODEC_ID_SDX2_DPCM; break; + case 6: if (st->codecpar->block_align > INT_MAX/1024) + return AVERROR_INVALIDDATA; + st->codecpar->codec_id = AV_CODEC_ID_SDX2_DPCM; break; case 7: ret = ff_alloc_extradata(st->codecpar, 2); if (ret < 0) return ret; @@ -144,6 +146,9 @@ } } + if (st->codecpar->block_align <= 0) + return AVERROR_INVALIDDATA; + avio_skip(s->pb, start_offset - avio_tell(s->pb)); avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff -Nru ffmpeg-4.2.2/libavformat/gifdec.c ffmpeg-4.4/libavformat/gifdec.c --- ffmpeg-4.2.2/libavformat/gifdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/gifdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -144,7 +144,7 @@ AVBPrint bp; int block_size; - av_bprint_init(&bp, 0, -1); + av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); while ((block_size = avio_r8(pb)) != 0) { avio_read_to_bprint(pb, &bp, block_size); } diff -Nru ffmpeg-4.2.2/libavformat/gopher.c ffmpeg-4.4/libavformat/gopher.c --- ffmpeg-4.2.2/libavformat/gopher.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/gopher.c 2021-04-08 21:28:40.000000000 +0000 @@ -2,6 +2,7 @@ * Gopher protocol * * Copyright (c) 2009 Toshimitsu Kimura + * Copyright (c) 2021 parazyd * * based on libavformat/http.c, Copyright (c) 2000, 2001 Fabrice Bellard * @@ -22,6 +23,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + #include "libavutil/avstring.h" #include "avformat.h" #include "internal.h" @@ -68,29 +71,30 @@ static int gopher_close(URLContext *h) { GopherContext *s = h->priv_data; - if (s->hd) { - ffurl_close(s->hd); - s->hd = NULL; - } + ffurl_closep(&s->hd); return 0; } static int gopher_open(URLContext *h, const char *uri, int flags) { GopherContext *s = h->priv_data; - char hostname[1024], auth[1024], path[1024], buf[1024]; + char proto[10], hostname[1024], auth[1024], path[1024], buf[1024]; int port, err; + const char *lower_proto = "tcp"; h->is_streamed = 1; /* needed in any case to build the host string */ - av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port, - path, sizeof(path), uri); + av_url_split(proto, sizeof(proto), auth, sizeof(auth), + hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (port < 0) port = 70; - ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL); + if (!strcmp(proto, "gophers")) + lower_proto = "tls"; + + ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL); s->hd = NULL; err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE, @@ -113,13 +117,28 @@ return len; } - +#if CONFIG_GOPHER_PROTOCOL const URLProtocol ff_gopher_protocol = { - .name = "gopher", - .url_open = gopher_open, - .url_read = gopher_read, - .url_write = gopher_write, - .url_close = gopher_close, - .priv_data_size = sizeof(GopherContext), - .flags = URL_PROTOCOL_FLAG_NETWORK, + .name = "gopher", + .url_open = gopher_open, + .url_read = gopher_read, + .url_write = gopher_write, + .url_close = gopher_close, + .priv_data_size = sizeof(GopherContext), + .flags = URL_PROTOCOL_FLAG_NETWORK, + .default_whitelist = "gopher,tcp" +}; +#endif /* CONFIG_GOPHER_PROTOCOL */ + +#if CONFIG_GOPHERS_PROTOCOL +const URLProtocol ff_gophers_protocol = { + .name = "gophers", + .url_open = gopher_open, + .url_read = gopher_read, + .url_write = gopher_write, + .url_close = gopher_close, + .priv_data_size = sizeof(GopherContext), + .flags = URL_PROTOCOL_FLAG_NETWORK, + .default_whitelist = "gopher,gophers,tcp,tls" }; +#endif /* CONFIG_GOPHERS_PROTOCOL */ diff -Nru ffmpeg-4.2.2/libavformat/gsmdec.c ffmpeg-4.4/libavformat/gsmdec.c --- ffmpeg-4.2.2/libavformat/gsmdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/gsmdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -62,7 +62,6 @@ ret = av_get_packet(s->pb, pkt, size); if (ret < GSM_BLOCK_SIZE) { - av_packet_unref(pkt); return ret < 0 ? ret : AVERROR(EIO); } pkt->duration = 1; diff -Nru ffmpeg-4.2.2/libavformat/gxf.c ffmpeg-4.4/libavformat/gxf.c --- ffmpeg-4.2.2/libavformat/gxf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/gxf.c 2021-02-20 20:27:47.000000000 +0000 @@ -285,9 +285,12 @@ static void gxf_read_index(AVFormatContext *s, int pkt_len) { AVIOContext *pb = s->pb; AVStream *st; - uint32_t fields_per_map = avio_rl32(pb); - uint32_t map_cnt = avio_rl32(pb); + uint32_t fields_per_map, map_cnt; int i; + if (pkt_len < 8) + return; + fields_per_map = avio_rl32(pb); + map_cnt = avio_rl32(pb); pkt_len -= 8; if ((s->flags & AVFMT_FLAG_IGNIDX) || !s->streams) { avio_skip(pb, pkt_len); diff -Nru ffmpeg-4.2.2/libavformat/gxfenc.c ffmpeg-4.4/libavformat/gxfenc.c --- ffmpeg-4.2.2/libavformat/gxfenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/gxfenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -27,8 +27,8 @@ #include "avformat.h" #include "internal.h" #include "gxf.h" -#include "audiointerleave.h" +#define GXF_SAMPLES_PER_FRAME 32768 #define GXF_AUDIO_PACKET_SIZE 65536 #define GXF_TIMECODE(c, d, h, m, s, f) \ @@ -44,7 +44,7 @@ } GXFTimecode; typedef struct GXFStreamContext { - AudioInterleaveContext aic; + int64_t pkt_cnt; uint32_t track_type; uint32_t sample_size; uint32_t sample_rate; @@ -663,8 +663,6 @@ return updatePacketSize(pb, pos); } -static const int GXF_samples_per_frame[] = { 32768, 0 }; - static void gxf_init_timecode_track(GXFStreamContext *sc, GXFStreamContext *vsc) { if (!vsc) @@ -736,6 +734,9 @@ av_log(s, AV_LOG_ERROR, "only mono tracks are allowed\n"); return -1; } + ret = ff_stream_add_bitstream_filter(st, "pcm_rechunk", "n="AV_STRINGIFY(GXF_SAMPLES_PER_FRAME)); + if (ret < 0) + return ret; sc->track_type = 2; sc->sample_rate = st->codecpar->sample_rate; avpriv_set_pts_info(st, 64, 1, sc->sample_rate); @@ -818,9 +819,6 @@ sc->order = s->nb_streams - st->index; } - if (ff_audio_interleave_init(s, GXF_samples_per_frame, (AVRational){ 1, 48000 }) < 0) - return -1; - if (tcr && vsc) gxf_init_timecode(s, &gxf->tc, tcr->value, vsc->fields); @@ -834,7 +832,6 @@ gxf->packet_count = 3; - avio_flush(pb); return 0; } @@ -854,8 +851,6 @@ int i; int ret; - ff_audio_interleave_close(s); - gxf_write_eos_packet(pb); end = avio_tell(pb); avio_seek(pb, 0, SEEK_SET); @@ -864,21 +859,24 @@ return ret; gxf_write_flt_packet(s); gxf_write_umf_packet(s); - avio_flush(pb); /* update duration in all map packets */ for (i = 1; i < gxf->map_offsets_nb; i++) { avio_seek(pb, gxf->map_offsets[i], SEEK_SET); if ((ret = gxf_write_map_packet(s, 1)) < 0) return ret; - avio_flush(pb); } avio_seek(pb, end, SEEK_SET); + return 0; +} + +static void gxf_deinit(AVFormatContext *s) +{ + GXFContext *gxf = s->priv_data; + av_freep(&gxf->flt_entries); av_freep(&gxf->map_offsets); - - return 0; } static int gxf_parse_mpeg_frame(GXFStreamContext *sc, const uint8_t *buf, int size) @@ -987,10 +985,11 @@ return 0; } -static int gxf_compare_field_nb(AVFormatContext *s, AVPacket *next, AVPacket *cur) +static int gxf_compare_field_nb(AVFormatContext *s, const AVPacket *next, + const AVPacket *cur) { GXFContext *gxf = s->priv_data; - AVPacket *pkt[2] = { cur, next }; + const AVPacket *pkt[2] = { cur, next }; int i, field_nb[2]; GXFStreamContext *sc[2]; @@ -1011,10 +1010,19 @@ static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) { - if (pkt && s->streams[pkt->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) - pkt->duration = 2; // enforce 2 fields - return ff_audio_rechunk_interleave(s, out, pkt, flush, - ff_interleave_packet_per_dts, gxf_compare_field_nb); + int ret; + if (pkt) { + AVStream *st = s->streams[pkt->stream_index]; + GXFStreamContext *sc = st->priv_data; + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) + pkt->pts = pkt->dts = sc->pkt_cnt * 2; // enforce 2 fields + else + pkt->pts = pkt->dts = sc->pkt_cnt * GXF_SAMPLES_PER_FRAME; + sc->pkt_cnt++; + if ((ret = ff_interleave_add_packet(s, pkt, gxf_compare_field_nb)) < 0) + return ret; + } + return ff_interleave_packet_per_dts(s, out, NULL, flush); } AVOutputFormat ff_gxf_muxer = { @@ -1027,5 +1035,6 @@ .write_header = gxf_write_header, .write_packet = gxf_write_packet, .write_trailer = gxf_write_trailer, + .deinit = gxf_deinit, .interleave_packet = gxf_interleave_packet, }; diff -Nru ffmpeg-4.2.2/libavformat/hashenc.c ffmpeg-4.4/libavformat/hashenc.c --- ffmpeg-4.2.2/libavformat/hashenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/hashenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -29,68 +29,145 @@ struct HashContext { const AVClass *avclass; - struct AVHashContext *hash; + struct AVHashContext **hashes; char *hash_name; + int per_stream; int format_version; }; #define OFFSET(x) offsetof(struct HashContext, x) #define ENC AV_OPT_FLAG_ENCODING_PARAM -#if CONFIG_HASH_MUXER || CONFIG_FRAMEHASH_MUXER -static const AVOption hash_options[] = { - { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = "sha256"}, 0, 0, ENC }, - { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC }, +#define HASH_OPT(defaulttype) \ + { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = defaulttype}, 0, 0, ENC } +#define FORMAT_VERSION_OPT \ + { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC } + +#if CONFIG_HASH_MUXER || CONFIG_STREAMHASH_MUXER +static const AVOption hash_streamhash_options[] = { + HASH_OPT("sha256"), { NULL }, }; #endif -#if CONFIG_MD5_MUXER || CONFIG_FRAMEMD5_MUXER +#if CONFIG_FRAMEHASH_MUXER +static const AVOption framehash_options[] = { + HASH_OPT("sha256"), + FORMAT_VERSION_OPT, + { NULL }, +}; +#endif + +#if CONFIG_MD5_MUXER static const AVOption md5_options[] = { - { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = "md5"}, 0, 0, ENC }, - { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC }, + HASH_OPT("md5"), + { NULL }, +}; +#endif + +#if CONFIG_FRAMEMD5_MUXER +static const AVOption framemd5_options[] = { + HASH_OPT("md5"), + FORMAT_VERSION_OPT, { NULL }, }; #endif #if CONFIG_HASH_MUXER || CONFIG_MD5_MUXER -static int hash_write_header(struct AVFormatContext *s) +static int hash_init(struct AVFormatContext *s) { + int res; struct HashContext *c = s->priv_data; - int res = av_hash_alloc(&c->hash, c->hash_name); + c->per_stream = 0; + c->hashes = av_mallocz_array(1, sizeof(*c->hashes)); + if (!c->hashes) + return AVERROR(ENOMEM); + res = av_hash_alloc(&c->hashes[0], c->hash_name); if (res < 0) return res; - av_hash_init(c->hash); + av_hash_init(c->hashes[0]); + return 0; +} +#endif + +#if CONFIG_STREAMHASH_MUXER +static int streamhash_init(struct AVFormatContext *s) +{ + int res, i; + struct HashContext *c = s->priv_data; + c->per_stream = 1; + c->hashes = av_mallocz_array(s->nb_streams, sizeof(*c->hashes)); + if (!c->hashes) + return AVERROR(ENOMEM); + for (i = 0; i < s->nb_streams; i++) { + res = av_hash_alloc(&c->hashes[i], c->hash_name); + if (res < 0) { + return res; + } + av_hash_init(c->hashes[i]); + } return 0; } +#endif + +#if CONFIG_HASH_MUXER || CONFIG_MD5_MUXER || CONFIG_STREAMHASH_MUXER +static char get_media_type_char(enum AVMediaType type) +{ + switch (type) { + case AVMEDIA_TYPE_VIDEO: return 'v'; + case AVMEDIA_TYPE_AUDIO: return 'a'; + case AVMEDIA_TYPE_DATA: return 'd'; + case AVMEDIA_TYPE_SUBTITLE: return 's'; + case AVMEDIA_TYPE_ATTACHMENT: return 't'; + default: return '?'; + } +} static int hash_write_packet(struct AVFormatContext *s, AVPacket *pkt) { struct HashContext *c = s->priv_data; - av_hash_update(c->hash, pkt->data, pkt->size); + av_hash_update(c->hashes[c->per_stream ? pkt->stream_index : 0], pkt->data, pkt->size); return 0; } static int hash_write_trailer(struct AVFormatContext *s) { struct HashContext *c = s->priv_data; - char buf[AV_HASH_MAX_SIZE*2+128]; - snprintf(buf, sizeof(buf) - 200, "%s=", av_hash_get_name(c->hash)); - - av_hash_final_hex(c->hash, buf + strlen(buf), sizeof(buf) - strlen(buf)); - av_strlcatf(buf, sizeof(buf), "\n"); - avio_write(s->pb, buf, strlen(buf)); - avio_flush(s->pb); + int num_hashes = c->per_stream ? s->nb_streams : 1; + for (int i = 0; i < num_hashes; i++) { + char buf[AV_HASH_MAX_SIZE*2+128]; + if (c->per_stream) { + AVStream *st = s->streams[i]; + snprintf(buf, sizeof(buf) - 200, "%d,%c,%s=", i, get_media_type_char(st->codecpar->codec_type), + av_hash_get_name(c->hashes[i])); + } else { + snprintf(buf, sizeof(buf) - 200, "%s=", av_hash_get_name(c->hashes[i])); + } + av_hash_final_hex(c->hashes[i], buf + strlen(buf), sizeof(buf) - strlen(buf)); + av_strlcatf(buf, sizeof(buf), "\n"); + avio_write(s->pb, buf, strlen(buf)); + } - av_hash_freep(&c->hash); return 0; } #endif +static void hash_free(struct AVFormatContext *s) +{ + struct HashContext *c = s->priv_data; + if (c->hashes) { + int num_hashes = c->per_stream ? s->nb_streams : 1; + for (int i = 0; i < num_hashes; i++) { + av_hash_freep(&c->hashes[i]); + } + } + av_freep(&c->hashes); +} + #if CONFIG_HASH_MUXER static const AVClass hashenc_class = { .class_name = "hash muxer", .item_name = av_default_item_name, - .option = hash_options, + .option = hash_streamhash_options, .version = LIBAVUTIL_VERSION_INT, }; @@ -100,9 +177,10 @@ .priv_data_size = sizeof(struct HashContext), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_RAWVIDEO, - .write_header = hash_write_header, + .init = hash_init, .write_packet = hash_write_packet, .write_trailer = hash_write_trailer, + .deinit = hash_free, .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_TS_NEGATIVE, .priv_class = &hashenc_class, @@ -123,15 +201,40 @@ .priv_data_size = sizeof(struct HashContext), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_RAWVIDEO, - .write_header = hash_write_header, + .init = hash_init, .write_packet = hash_write_packet, .write_trailer = hash_write_trailer, + .deinit = hash_free, .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_TS_NEGATIVE, .priv_class = &md5enc_class, }; #endif +#if CONFIG_STREAMHASH_MUXER +static const AVClass streamhashenc_class = { + .class_name = "stream hash muxer", + .item_name = av_default_item_name, + .option = hash_streamhash_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVOutputFormat ff_streamhash_muxer = { + .name = "streamhash", + .long_name = NULL_IF_CONFIG_SMALL("Per-stream hash testing"), + .priv_data_size = sizeof(struct HashContext), + .audio_codec = AV_CODEC_ID_PCM_S16LE, + .video_codec = AV_CODEC_ID_RAWVIDEO, + .init = streamhash_init, + .write_packet = hash_write_packet, + .write_trailer = hash_write_trailer, + .deinit = hash_free, + .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | + AVFMT_TS_NEGATIVE, + .priv_class = &streamhashenc_class, +}; +#endif + #if CONFIG_FRAMEHASH_MUXER || CONFIG_FRAMEMD5_MUXER static void framehash_print_extradata(struct AVFormatContext *s) { @@ -145,24 +248,35 @@ char buf[AV_HASH_MAX_SIZE*2+1]; avio_printf(s->pb, "#extradata %d, %31d, ", i, par->extradata_size); - av_hash_init(c->hash); - av_hash_update(c->hash, par->extradata, par->extradata_size); - av_hash_final_hex(c->hash, buf, sizeof(buf)); + av_hash_init(c->hashes[0]); + av_hash_update(c->hashes[0], par->extradata, par->extradata_size); + av_hash_final_hex(c->hashes[0], buf, sizeof(buf)); avio_write(s->pb, buf, strlen(buf)); avio_printf(s->pb, "\n"); } } } -static int framehash_write_header(struct AVFormatContext *s) +static int framehash_init(struct AVFormatContext *s) { + int res; struct HashContext *c = s->priv_data; - int res = av_hash_alloc(&c->hash, c->hash_name); + c->per_stream = 0; + c->hashes = av_mallocz_array(1, sizeof(*c->hashes)); + if (!c->hashes) + return AVERROR(ENOMEM); + res = av_hash_alloc(&c->hashes[0], c->hash_name); if (res < 0) return res; + return 0; +} + +static int framehash_write_header(struct AVFormatContext *s) +{ + struct HashContext *c = s->priv_data; avio_printf(s->pb, "#format: frame checksums\n"); avio_printf(s->pb, "#version: %d\n", c->format_version); - avio_printf(s->pb, "#hash: %s\n", av_hash_get_name(c->hash)); + avio_printf(s->pb, "#hash: %s\n", av_hash_get_name(c->hashes[0])); framehash_print_extradata(s); ff_framehash_write_header(s); avio_printf(s->pb, "#stream#, dts, pts, duration, size, hash\n"); @@ -174,43 +288,35 @@ struct HashContext *c = s->priv_data; char buf[AV_HASH_MAX_SIZE*2+128]; int len; - av_hash_init(c->hash); - av_hash_update(c->hash, pkt->data, pkt->size); + av_hash_init(c->hashes[0]); + av_hash_update(c->hashes[0], pkt->data, pkt->size); snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), "%d, %10"PRId64", %10"PRId64", %8"PRId64", %8d, ", pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size); len = strlen(buf); - av_hash_final_hex(c->hash, buf + len, sizeof(buf) - len); + av_hash_final_hex(c->hashes[0], buf + len, sizeof(buf) - len); avio_write(s->pb, buf, strlen(buf)); if (c->format_version > 1 && pkt->side_data_elems) { int i, j; avio_printf(s->pb, ", S=%d", pkt->side_data_elems); for (i = 0; i < pkt->side_data_elems; i++) { - av_hash_init(c->hash); + av_hash_init(c->hashes[0]); if (HAVE_BIGENDIAN && pkt->side_data[i].type == AV_PKT_DATA_PALETTE) { for (j = 0; j < pkt->side_data[i].size; j += sizeof(uint32_t)) { uint32_t data = AV_RL32(pkt->side_data[i].data + j); - av_hash_update(c->hash, (uint8_t *)&data, sizeof(uint32_t)); + av_hash_update(c->hashes[0], (uint8_t *)&data, sizeof(uint32_t)); } } else - av_hash_update(c->hash, pkt->side_data[i].data, pkt->side_data[i].size); + av_hash_update(c->hashes[0], pkt->side_data[i].data, pkt->side_data[i].size); snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), ", %8d, ", pkt->side_data[i].size); len = strlen(buf); - av_hash_final_hex(c->hash, buf + len, sizeof(buf) - len); + av_hash_final_hex(c->hashes[0], buf + len, sizeof(buf) - len); avio_write(s->pb, buf, strlen(buf)); } } avio_printf(s->pb, "\n"); - avio_flush(s->pb); - return 0; -} - -static int framehash_write_trailer(struct AVFormatContext *s) -{ - struct HashContext *c = s->priv_data; - av_hash_freep(&c->hash); return 0; } #endif @@ -219,7 +325,7 @@ static const AVClass framehash_class = { .class_name = "frame hash muxer", .item_name = av_default_item_name, - .option = hash_options, + .option = framehash_options, .version = LIBAVUTIL_VERSION_INT, }; @@ -229,9 +335,10 @@ .priv_data_size = sizeof(struct HashContext), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_RAWVIDEO, + .init = framehash_init, .write_header = framehash_write_header, .write_packet = framehash_write_packet, - .write_trailer = framehash_write_trailer, + .deinit = hash_free, .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_TS_NEGATIVE, .priv_class = &framehash_class, @@ -242,7 +349,7 @@ static const AVClass framemd5_class = { .class_name = "frame MD5 muxer", .item_name = av_default_item_name, - .option = md5_options, + .option = framemd5_options, .version = LIBAVUTIL_VERSION_INT, }; @@ -252,9 +359,10 @@ .priv_data_size = sizeof(struct HashContext), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_RAWVIDEO, + .init = framehash_init, .write_header = framehash_write_header, .write_packet = framehash_write_packet, - .write_trailer = framehash_write_trailer, + .deinit = hash_free, .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | AVFMT_TS_NEGATIVE, .priv_class = &framemd5_class, diff -Nru ffmpeg-4.2.2/libavformat/hca.c ffmpeg-4.4/libavformat/hca.c --- ffmpeg-4.2.2/libavformat/hca.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/hca.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,124 @@ +/* + * HCA demuxer + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "libavcodec/bytestream.h" + +#include "avformat.h" +#include "internal.h" + +static int hca_probe(const AVProbeData *p) +{ + if (AV_RL32(p->buf) != MKTAG('H', 'C', 'A', 0)) + return 0; + + if (AV_RL32(p->buf + 8) != MKTAG('f', 'm', 't', 0)) + return 0; + + return AVPROBE_SCORE_MAX / 3; +} + +static int hca_read_header(AVFormatContext *s) +{ + AVCodecParameters *par; + GetByteContext gb; + AVIOContext *pb = s->pb; + AVStream *st; + uint32_t chunk; + uint16_t version; + uint32_t block_count; + uint16_t block_size; + int ret; + + avio_skip(pb, 4); + version = avio_rb16(pb); + + s->internal->data_offset = avio_rb16(pb); + if (s->internal->data_offset <= 8) + return AVERROR_INVALIDDATA; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + par = st->codecpar; + ret = ff_alloc_extradata(par, s->internal->data_offset); + if (ret < 0) + return ret; + + ret = avio_read(pb, par->extradata + 8, par->extradata_size - 8); + if (ret < par->extradata_size - 8) + return AVERROR(EIO); + AV_WL32(par->extradata, MKTAG('H', 'C', 'A', 0)); + AV_WB16(par->extradata + 4, version); + AV_WB16(par->extradata + 6, s->internal->data_offset); + + bytestream2_init(&gb, par->extradata + 8, par->extradata_size - 8); + + if (bytestream2_get_le32(&gb) != MKTAG('f', 'm', 't', 0)) + return AVERROR_INVALIDDATA; + + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = AV_CODEC_ID_HCA; + par->codec_tag = 0; + par->channels = bytestream2_get_byte(&gb); + par->sample_rate = bytestream2_get_be24(&gb); + block_count = bytestream2_get_be32(&gb); + bytestream2_skip(&gb, 4); + chunk = bytestream2_get_le32(&gb); + if (chunk == MKTAG('c', 'o', 'm', 'p')) { + block_size = bytestream2_get_be16(&gb); + } else if (chunk == MKTAG('d', 'e', 'c', 0)) { + block_size = bytestream2_get_be16(&gb); + } else { + return AVERROR_INVALIDDATA; + } + + if (block_size < 8) + return AVERROR_INVALIDDATA; + par->block_align = block_size; + st->duration = 1024 * block_count; + + avio_seek(pb, s->internal->data_offset, SEEK_SET); + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + + return 0; +} + +static int hca_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVCodecParameters *par = s->streams[0]->codecpar; + int ret; + + ret = av_get_packet(s->pb, pkt, par->block_align); + pkt->duration = 1024; + return ret; +} + +AVInputFormat ff_hca_demuxer = { + .name = "hca", + .long_name = NULL_IF_CONFIG_SMALL("CRI HCA"), + .read_probe = hca_probe, + .read_header = hca_read_header, + .read_packet = hca_read_packet, + .extensions = "hca", + .flags = AVFMT_GENERIC_INDEX, +}; diff -Nru ffmpeg-4.2.2/libavformat/hcom.c ffmpeg-4.4/libavformat/hcom.c --- ffmpeg-4.2.2/libavformat/hcom.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/hcom.c 2020-07-11 10:39:30.000000000 +0000 @@ -38,7 +38,7 @@ static int hcom_read_header(AVFormatContext *s) { AVStream *st; - unsigned data_size, rsrc_size, huffcount; + av_unused unsigned data_size, rsrc_size, huffcount; unsigned compresstype, divisor; unsigned dict_entries; int ret; diff -Nru ffmpeg-4.2.2/libavformat/hdsenc.c ffmpeg-4.4/libavformat/hdsenc.c --- ffmpeg-4.2.2/libavformat/hdsenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/hdsenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -146,8 +146,7 @@ av_write_trailer(os->ctx); if (os->ctx) avio_context_free(&os->ctx->pb); - if (os->ctx) - avformat_free_context(os->ctx); + avformat_free_context(os->ctx); av_freep(&os->metadata); for (j = 0; j < os->nb_extra_packets; j++) av_freep(&os->extra_packets[j]); @@ -318,21 +317,18 @@ ff_const59 AVOutputFormat *oformat; if (mkdir(s->url, 0777) == -1 && errno != EEXIST) { - ret = AVERROR(errno); av_log(s, AV_LOG_ERROR , "Failed to create directory %s\n", s->url); - goto fail; + return AVERROR(errno); } oformat = av_guess_format("flv", NULL, NULL); if (!oformat) { - ret = AVERROR_MUXER_NOT_FOUND; - goto fail; + return AVERROR_MUXER_NOT_FOUND; } c->streams = av_mallocz_array(s->nb_streams, sizeof(*c->streams)); if (!c->streams) { - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } for (i = 0; i < s->nb_streams; i++) { @@ -342,8 +338,7 @@ if (!st->codecpar->bit_rate) { av_log(s, AV_LOG_ERROR, "No bit rate set for stream %d\n", i); - ret = AVERROR(EINVAL); - goto fail; + return AVERROR(EINVAL); } if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (os->has_video) { @@ -359,8 +354,7 @@ os->has_audio = 1; } else { av_log(s, AV_LOG_ERROR, "Unsupported stream type in stream %d\n", i); - ret = AVERROR(EINVAL); - goto fail; + return AVERROR(EINVAL); } os->bitrate += s->streams[i]->codecpar->bit_rate; @@ -368,8 +362,7 @@ os->first_stream = i; ctx = avformat_alloc_context(); if (!ctx) { - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } os->ctx = ctx; ctx->oformat = oformat; @@ -380,8 +373,7 @@ AVIO_FLAG_WRITE, os, NULL, hds_write, NULL); if (!ctx->pb) { - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } } else { ctx = os->ctx; @@ -389,8 +381,7 @@ s->streams[i]->id = c->nb_streams; if (!(st = avformat_new_stream(ctx, NULL))) { - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar); st->codecpar->codec_tag = 0; @@ -404,7 +395,7 @@ OutputStream *os = &c->streams[i]; int j; if ((ret = avformat_write_header(os->ctx, NULL)) < 0) { - goto fail; + return ret; } os->ctx_inited = 1; avio_flush(os->ctx->pb); @@ -415,7 +406,7 @@ "%s/stream%d_temp", s->url, i); ret = init_file(s, os, 0); if (ret < 0) - goto fail; + return ret; if (!os->has_video && c->min_frag_duration <= 0) { av_log(s, AV_LOG_WARNING, @@ -426,9 +417,6 @@ } ret = write_manifest(s, 0); -fail: - if (ret) - hds_free(s); return ret; } @@ -558,7 +546,6 @@ rmdir(s->url); } - hds_free(s); return 0; } @@ -589,5 +576,6 @@ .write_header = hds_write_header, .write_packet = hds_write_packet, .write_trailer = hds_write_trailer, + .deinit = hds_free, .priv_class = &hds_class, }; diff -Nru ffmpeg-4.2.2/libavformat/hevc.c ffmpeg-4.4/libavformat/hevc.c --- ffmpeg-4.2.2/libavformat/hevc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/hevc.c 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,7 @@ #include "libavutil/intreadwrite.h" #include "avc.h" #include "avio.h" +#include "avio_internal.h" #include "hevc.h" #define MAX_SPATIAL_SEGMENTATION 4096 // max. value of u(12) field @@ -1054,37 +1055,40 @@ return ret; ret = ff_hevc_annexb2mp4(pb, buf_in, *size, filter_ps, ps_count); + if (ret < 0) { + ffio_free_dyn_buf(&pb); + return ret; + } + *size = avio_close_dyn_buf(pb, buf_out); - return ret; + return 0; } int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, int size, int ps_array_completeness) { - int ret = 0; - uint8_t *buf, *end, *start = NULL; HEVCDecoderConfigurationRecord hvcc; - - hvcc_init(&hvcc); + uint8_t *buf, *end, *start; + int ret; if (size < 6) { /* We can't write a valid hvcC from the provided data */ - ret = AVERROR_INVALIDDATA; - goto end; + return AVERROR_INVALIDDATA; } else if (*data == 1) { /* Data is already hvcC-formatted */ avio_write(pb, data, size); - goto end; + return 0; } else if (!(AV_RB24(data) == 1 || AV_RB32(data) == 1)) { /* Not a valid Annex B start code prefix */ - ret = AVERROR_INVALIDDATA; - goto end; + return AVERROR_INVALIDDATA; } ret = ff_avc_parse_nal_units_buf(data, &start, &size); if (ret < 0) - goto end; + return ret; + + hvcc_init(&hvcc); buf = start; end = start + size; diff -Nru ffmpeg-4.2.2/libavformat/hevc.h ffmpeg-4.4/libavformat/hevc.h --- ffmpeg-4.2.2/libavformat/hevc.h 2016-03-29 02:25:28.000000000 +0000 +++ ffmpeg-4.4/libavformat/hevc.h 2020-07-11 10:39:30.000000000 +0000 @@ -60,19 +60,20 @@ * If filter_ps is non-zero, any HEVC parameter sets found in the input will be * discarded, and *ps_count will be set to the number of discarded PS NAL units. * - * On output, *size holds the size (in bytes) of the output data buffer. + * On success, *size holds the size (in bytes) of the output data buffer. * * @param buf_in address of the buffer holding the input data * @param size address of the variable holding the size (in bytes) of the input - * buffer (on input) and of the output buffer (on output) - * @param buf_out address of the variable holding the address of the output - * buffer + * buffer (on input) and of the output buffer (on success) + * @param buf_out on success, address of the variable holding the address of + * the output buffer * @param filter_ps whether to write parameter set NAL units to the output (0) * or to discard them (non-zero) * @param ps_count address of the variable where the number of discarded * parameter set NAL units shall be written, may be NULL - * @return the amount (in bytes) of data written in case of success, a negative - * value corresponding to an AVERROR code in case of failure + * @return 0 in case of success, a negative value corresponding to an AVERROR + * code in case of failure + * @note *buf_out will be treated as uninitialized on input and won't be freed. */ int ff_hevc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out, int *size, int filter_ps, int *ps_count); diff -Nru ffmpeg-4.2.2/libavformat/hls.c ffmpeg-4.4/libavformat/hls.c --- ffmpeg-4.2.2/libavformat/hls.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/hls.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,7 +23,7 @@ /** * @file * Apple HTTP Live Streaming demuxer - * http://tools.ietf.org/html/draft-pantos-http-live-streaming + * https://www.rfc-editor.org/rfc/rfc8216.txt */ #include "libavformat/http.h" @@ -101,7 +101,7 @@ AVFormatContext *parent; int index; AVFormatContext *ctx; - AVPacket pkt; + AVPacket *pkt; int has_noheader_flag; /* main demuxer streams associated with this playlist @@ -112,11 +112,14 @@ int finished; enum PlaylistType type; int64_t target_duration; - int start_seq_no; + int64_t start_seq_no; int n_segments; struct segment **segments; int needed; - int cur_seq_no; + int broken; + int64_t cur_seq_no; + int64_t last_seq_no; + int m3u8_hold_counters; int64_t cur_seg_offset; int64_t last_load_time; @@ -196,7 +199,8 @@ int n_renditions; struct rendition **renditions; - int cur_seq_no; + int64_t cur_seq_no; + int m3u8_hold_counters; int live_start_index; int first_packet; int64_t first_timestamp; @@ -207,6 +211,7 @@ int max_reload; int http_persistent; int http_multiple; + int http_seekable; AVIOContext *playlist_pb; } HLSContext; @@ -251,13 +256,11 @@ av_dict_free(&pls->id3_initial); ff_id3v2_free_extra_meta(&pls->id3_deferred_extra); av_freep(&pls->init_sec_buf); - av_packet_unref(&pls->pkt); + av_packet_free(&pls->pkt); av_freep(&pls->pb.buffer); - if (pls->input) - ff_format_io_close(c->ctx, &pls->input); + ff_format_io_close(c->ctx, &pls->input); pls->input_read_done = 0; - if (pls->input_next) - ff_format_io_close(c->ctx, &pls->input_next); + ff_format_io_close(c->ctx, &pls->input_next); pls->input_next_requested = 0; if (pls->ctx) { pls->ctx->pb = NULL; @@ -290,24 +293,23 @@ c->n_renditions = 0; } -/* - * Used to reset a statically allocated AVPacket to a clean state, - * containing no data. - */ -static void reset_packet(AVPacket *pkt) -{ - av_init_packet(pkt); - pkt->data = NULL; -} - static struct playlist *new_playlist(HLSContext *c, const char *url, const char *base) { struct playlist *pls = av_mallocz(sizeof(struct playlist)); if (!pls) return NULL; - reset_packet(&pls->pkt); + pls->pkt = av_packet_alloc(); + if (!pls->pkt) { + av_free(pls); + return NULL; + } ff_make_absolute_url(pls->url, sizeof(pls->url), base, url); + if (!pls->url[0]) { + av_packet_free(&pls->pkt); + av_free(pls); + return NULL; + } pls->seek_timestamp = AV_NOPTS_VALUE; pls->is_id3_timestamped = -1; @@ -400,8 +402,7 @@ const char *url_base) { struct segment *sec; - char *ptr; - char tmp_str[MAX_URL_SIZE]; + char tmp_str[MAX_URL_SIZE], *ptr = tmp_str; if (!info->uri[0]) return NULL; @@ -410,8 +411,16 @@ if (!sec) return NULL; - ff_make_absolute_url(tmp_str, sizeof(tmp_str), url_base, info->uri); - sec->url = av_strdup(tmp_str); + if (!av_strncasecmp(info->uri, "data:", 5)) { + ptr = info->uri; + } else { + ff_make_absolute_url(tmp_str, sizeof(tmp_str), url_base, info->uri); + if (!tmp_str[0]) { + av_free(sec); + return NULL; + } + } + sec->url = av_strdup(ptr); if (!sec->url) { av_free(sec); return NULL; @@ -477,20 +486,20 @@ return NULL; if (type == AVMEDIA_TYPE_UNKNOWN) { - av_log(c, AV_LOG_WARNING, "Can't support the type: %s\n", info->type); + av_log(c->ctx, AV_LOG_WARNING, "Can't support the type: %s\n", info->type); return NULL; } /* URI is mandatory for subtitles as per spec */ if (type == AVMEDIA_TYPE_SUBTITLE && !info->uri[0]) { - av_log(c, AV_LOG_ERROR, "The URI tag is REQUIRED for subtitle.\n"); + av_log(c->ctx, AV_LOG_ERROR, "The URI tag is REQUIRED for subtitle.\n"); return NULL; } /* TODO: handle subtitles (each segment has to parsed separately) */ if (c->ctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) if (type == AVMEDIA_TYPE_SUBTITLE) { - av_log(c, AV_LOG_WARNING, "Can't support the subtitle(uri: %s)\n", info->uri); + av_log(c->ctx, AV_LOG_WARNING, "Can't support the subtitle(uri: %s)\n", info->uri); return NULL; } @@ -595,7 +604,7 @@ } static int open_url_keepalive(AVFormatContext *s, AVIOContext **pb, - const char *url) + const char *url, AVDictionary **options) { #if !CONFIG_HTTP_PROTOCOL return AVERROR_PROTOCOL_NOT_FOUND; @@ -604,7 +613,7 @@ URLContext *uc = ffio_geturlcontext(*pb); av_assert0(uc); (*pb)->eof_reached = 0; - ret = ff_http_do_new_request(uc, url); + ret = ff_http_do_new_request2(uc, url, options); if (ret < 0) { ff_format_io_close(s, pb); } @@ -613,7 +622,7 @@ } static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, - AVDictionary *opts, AVDictionary *opts2, int *is_http_out) + AVDictionary **opts, AVDictionary *opts2, int *is_http_out) { HLSContext *c = s->priv_data; AVDictionary *tmp = NULL; @@ -621,12 +630,12 @@ int ret; int is_http = 0; - av_dict_copy(&tmp, opts, 0); - av_dict_copy(&tmp, opts2, 0); - if (av_strstart(url, "crypto", NULL)) { if (url[6] == '+' || url[6] == ':') proto_name = avio_find_protocol_name(url + 7); + } else if (av_strstart(url, "data", NULL)) { + if (url[4] == '+' || url[4] == ':') + proto_name = avio_find_protocol_name(url + 5); } if (!proto_name) @@ -646,6 +655,8 @@ } } else if (av_strstart(proto_name, "http", NULL)) { is_http = 1; + } else if (av_strstart(proto_name, "data", NULL)) { + ; } else return AVERROR_INVALIDDATA; @@ -653,18 +664,26 @@ ; else if (av_strstart(url, "crypto", NULL) && !strncmp(proto_name, url + 7, strlen(proto_name)) && url[7 + strlen(proto_name)] == ':') ; + else if (av_strstart(url, "data", NULL) && !strncmp(proto_name, url + 5, strlen(proto_name)) && url[5 + strlen(proto_name)] == ':') + ; else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) return AVERROR_INVALIDDATA; + av_dict_copy(&tmp, *opts, 0); + av_dict_copy(&tmp, opts2, 0); + if (is_http && c->http_persistent && *pb) { - ret = open_url_keepalive(c->ctx, pb, url); + ret = open_url_keepalive(c->ctx, pb, url, &tmp); if (ret == AVERROR_EXIT) { + av_dict_free(&tmp); return ret; } else if (ret < 0) { if (ret != AVERROR_EOF) av_log(s, AV_LOG_WARNING, - "keepalive request failed for '%s' when opening url, retrying with new connection: %s\n", + "keepalive request failed for '%s' with error: '%s' when opening url, retrying with new connection\n", url, av_err2str(ret)); + av_dict_copy(&tmp, *opts, 0); + av_dict_copy(&tmp, opts2, 0); ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); } } else { @@ -678,7 +697,7 @@ av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, (uint8_t**)&new_cookies); if (new_cookies) - av_dict_set(&opts, "cookies", new_cookies, AV_DICT_DONT_STRDUP_VAL); + av_dict_set(opts, "cookies", new_cookies, AV_DICT_DONT_STRDUP_VAL); } av_dict_free(&tmp); @@ -710,17 +729,17 @@ int is_http = av_strstart(url, "http", NULL); struct segment **prev_segments = NULL; int prev_n_segments = 0; - int prev_start_seq_no = -1; + int64_t prev_start_seq_no = -1; if (is_http && !in && c->http_persistent && c->playlist_pb) { in = c->playlist_pb; - ret = open_url_keepalive(c->ctx, &c->playlist_pb, url); + ret = open_url_keepalive(c->ctx, &c->playlist_pb, url, NULL); if (ret == AVERROR_EXIT) { return ret; } else if (ret < 0) { if (ret != AVERROR_EOF) av_log(c->ctx, AV_LOG_WARNING, - "keepalive request failed for '%s' when parsing playlist, retrying with new connection: %s\n", + "keepalive request failed for '%s' with error: '%s' when parsing playlist\n", url, av_err2str(ret)); in = NULL; } @@ -796,10 +815,17 @@ goto fail; pls->target_duration = strtoll(ptr, NULL, 10) * AV_TIME_BASE; } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { + uint64_t seq_no; ret = ensure_playlist(c, &pls, url); if (ret < 0) goto fail; - pls->start_seq_no = atoi(ptr); + seq_no = strtoull(ptr, NULL, 10); + if (seq_no > INT64_MAX) { + av_log(c->ctx, AV_LOG_DEBUG, "MEDIA-SEQUENCE higher than " + "INT64_MAX, mask out the highest bit\n"); + seq_no &= INT64_MAX; + } + pls->start_seq_no = seq_no; } else if (av_strstart(line, "#EXT-X-PLAYLIST-TYPE:", &ptr)) { ret = ensure_playlist(c, &pls, url); if (ret < 0) @@ -820,13 +846,18 @@ if (has_iv) { memcpy(cur_init_section->iv, iv, sizeof(iv)); } else { - int seq = pls->start_seq_no + pls->n_segments; + int64_t seq = pls->start_seq_no + pls->n_segments; memset(cur_init_section->iv, 0, sizeof(cur_init_section->iv)); - AV_WB32(cur_init_section->iv + 12, seq); + AV_WB64(cur_init_section->iv + 8, seq); } if (key_type != KEY_NONE) { ff_make_absolute_url(tmp_str, sizeof(tmp_str), url, key); + if (!tmp_str[0]) { + av_free(cur_init_section); + ret = AVERROR_INVALIDDATA; + goto fail; + } cur_init_section->key = av_strdup(tmp_str); if (!cur_init_section->key) { av_free(cur_init_section); @@ -861,30 +892,29 @@ } if (is_segment) { struct segment *seg; - if (!pls) { - if (!new_variant(c, 0, url, NULL)) { - ret = AVERROR(ENOMEM); - goto fail; - } - pls = c->playlists[c->n_playlists - 1]; - } + ret = ensure_playlist(c, &pls, url); + if (ret < 0) + goto fail; seg = av_malloc(sizeof(struct segment)); if (!seg) { ret = AVERROR(ENOMEM); goto fail; } - seg->duration = duration; - seg->key_type = key_type; if (has_iv) { memcpy(seg->iv, iv, sizeof(iv)); } else { - int seq = pls->start_seq_no + pls->n_segments; + int64_t seq = pls->start_seq_no + pls->n_segments; memset(seg->iv, 0, sizeof(seg->iv)); - AV_WB32(seg->iv + 12, seq); + AV_WB64(seg->iv + 8, seq); } if (key_type != KEY_NONE) { ff_make_absolute_url(tmp_str, sizeof(tmp_str), url, key); + if (!tmp_str[0]) { + ret = AVERROR_INVALIDDATA; + av_free(seg); + goto fail; + } seg->key = av_strdup(tmp_str); if (!seg->key) { av_free(seg); @@ -896,6 +926,13 @@ } ff_make_absolute_url(tmp_str, sizeof(tmp_str), url, line); + if (!tmp_str[0]) { + ret = AVERROR_INVALIDDATA; + if (seg->key) + av_free(seg->key); + av_free(seg); + goto fail; + } seg->url = av_strdup(tmp_str); if (!seg->url) { av_free(seg->key); @@ -904,6 +941,13 @@ goto fail; } + if (duration < 0.001 * AV_TIME_BASE) { + av_log(c->ctx, AV_LOG_WARNING, "Cannot get correct #EXTINF value of segment %s," + " set to default value to 1ms.\n", seg->url); + duration = 0.001 * AV_TIME_BASE; + } + seg->duration = duration; + seg->key_type = key_type; dynarray_add(&pls->segments, &pls->n_segments, seg); is_segment = 0; @@ -924,16 +968,17 @@ if (prev_segments) { if (pls->start_seq_no > prev_start_seq_no && c->first_timestamp != AV_NOPTS_VALUE) { int64_t prev_timestamp = c->first_timestamp; - int i, diff = pls->start_seq_no - prev_start_seq_no; + int i; + int64_t diff = pls->start_seq_no - prev_start_seq_no; for (i = 0; i < prev_n_segments && i < diff; i++) { c->first_timestamp += prev_segments[i]->duration; } - av_log(c->ctx, AV_LOG_DEBUG, "Media sequence change (%d -> %d)" + av_log(c->ctx, AV_LOG_DEBUG, "Media sequence change (%"PRId64" -> %"PRId64")" " reflected in first_timestamp: %"PRId64" -> %"PRId64"\n", prev_start_seq_no, pls->start_seq_no, prev_timestamp, c->first_timestamp); } else if (pls->start_seq_no < prev_start_seq_no) { - av_log(c->ctx, AV_LOG_WARNING, "Media sequence changed unexpectedly: %d -> %d\n", + av_log(c->ctx, AV_LOG_WARNING, "Media sequence changed unexpectedly: %"PRId64" -> %"PRId64"\n", prev_start_seq_no, pls->start_seq_no); } free_segment_dynarray(prev_segments, prev_n_segments); @@ -961,7 +1006,7 @@ static struct segment *next_segment(struct playlist *pls) { - int n = pls->cur_seq_no - pls->start_seq_no + 1; + int64_t n = pls->cur_seq_no - pls->start_seq_no + 1; if (n >= pls->n_segments) return NULL; return pls->segments[n]; @@ -994,7 +1039,7 @@ ff_id3v2_read_dict(pb, metadata, ID3v2_DEFAULT_MAGIC, extra_meta); for (meta = *extra_meta; meta; meta = meta->next) { if (!strcmp(meta->tag, "PRIV")) { - ID3v2ExtraMetaPRIV *priv = meta->data; + ID3v2ExtraMetaPRIV *priv = &meta->data.priv; if (priv->datasize == 8 && !strcmp(priv->owner, id3_priv_owner_ts)) { /* 33-bit MPEG timestamp */ int64_t ts = AV_RB64(priv->data); @@ -1005,7 +1050,7 @@ av_log(s, AV_LOG_ERROR, "Invalid HLS ID3 audio timestamp %"PRId64"\n", ts); } } else if (!strcmp(meta->tag, "APIC") && apic) - *apic = meta->data; + *apic = &meta->data.apic; } } @@ -1060,18 +1105,18 @@ /* get picture attachment and set text metadata */ if (pls->ctx->nb_streams) - ff_id3v2_parse_apic(pls->ctx, &extra_meta); + ff_id3v2_parse_apic(pls->ctx, extra_meta); else /* demuxer not yet opened, defer picture attachment */ pls->id3_deferred_extra = extra_meta; - ff_id3v2_parse_priv_dict(&metadata, &extra_meta); + ff_id3v2_parse_priv_dict(&metadata, extra_meta); av_dict_copy(&pls->ctx->metadata, metadata, 0); pls->id3_initial = metadata; } else { if (!pls->id3_changed && id3_has_changed_values(pls, metadata, apic)) { - avpriv_report_missing_feature(pls->ctx, "Changing ID3 metadata in HLS audio elementary stream"); + avpriv_report_missing_feature(pls->parent, "Changing ID3 metadata in HLS audio elementary stream"); pls->id3_changed = 1; } av_dict_free(&metadata); @@ -1122,7 +1167,7 @@ int remaining = taglen - tag_got_bytes; if (taglen > maxsize) { - av_log(pls->ctx, AV_LOG_ERROR, "Too large HLS ID3 tag (%d > %"PRId64" bytes)\n", + av_log(pls->parent, AV_LOG_ERROR, "Too large HLS ID3 tag (%d > %"PRId64" bytes)\n", taglen, maxsize); break; } @@ -1143,14 +1188,14 @@ /* strip the intercepted bytes */ *len -= tag_got_bytes; memmove(buf, buf + tag_got_bytes, *len); - av_log(pls->ctx, AV_LOG_DEBUG, "Stripped %d HLS ID3 bytes\n", tag_got_bytes); + av_log(pls->parent, AV_LOG_DEBUG, "Stripped %d HLS ID3 bytes\n", tag_got_bytes); if (remaining > 0) { /* read the rest of the tag in */ if (read_from_url(pls, seg, pls->id3_buf + id3_buf_pos, remaining) != remaining) break; id3_buf_pos += remaining; - av_log(pls->ctx, AV_LOG_DEBUG, "Stripped additional %d HLS ID3 bytes\n", remaining); + av_log(pls->parent, AV_LOG_DEBUG, "Stripped additional %d HLS ID3 bytes\n", remaining); } } else { @@ -1201,12 +1246,12 @@ seg->url, seg->url_offset, pls->index); if (seg->key_type == KEY_NONE) { - ret = open_url(pls->parent, in, seg->url, c->avio_opts, opts, &is_http); + ret = open_url(pls->parent, in, seg->url, &c->avio_opts, opts, &is_http); } else if (seg->key_type == KEY_AES_128) { char iv[33], key[33], url[MAX_URL_SIZE]; if (strcmp(seg->key, pls->key_url)) { AVIOContext *pb = NULL; - if (open_url(pls->parent, &pb, seg->key, c->avio_opts, opts, NULL) == 0) { + if (open_url(pls->parent, &pb, seg->key, &c->avio_opts, opts, NULL) == 0) { ret = avio_read(pb, pls->key, sizeof(pls->key)); if (ret != sizeof(pls->key)) { av_log(pls->parent, AV_LOG_ERROR, "Unable to read key file %s\n", @@ -1230,7 +1275,7 @@ av_dict_set(&opts, "key", key, 0); av_dict_set(&opts, "iv", iv, 0); - ret = open_url(pls->parent, in, url, c->avio_opts, opts, &is_http); + ret = open_url(pls->parent, in, url, &c->avio_opts, opts, &is_http); if (ret < 0) { goto cleanup; } @@ -1253,7 +1298,7 @@ * as would be expected. Wrong offset received from the server will not be * noticed without the call, though. */ - if (ret == 0 && !is_http && seg->key_type == KEY_NONE && seg->url_offset) { + if (ret == 0 && !is_http && seg->url_offset) { int64_t seekret = avio_seek(*in, seg->url_offset, SEEK_SET); if (seekret < 0) { av_log(pls->parent, AV_LOG_ERROR, "Unable to seek to offset %"PRId64" of HLS segment '%s'\n", seg->url_offset, seg->url); @@ -1427,10 +1472,21 @@ } if (v->cur_seq_no < v->start_seq_no) { av_log(v->parent, AV_LOG_WARNING, - "skipping %d segments ahead, expired from playlists\n", + "skipping %"PRId64" segments ahead, expired from playlists\n", v->start_seq_no - v->cur_seq_no); v->cur_seq_no = v->start_seq_no; } + if (v->cur_seq_no > v->last_seq_no) { + v->last_seq_no = v->cur_seq_no; + v->m3u8_hold_counters = 0; + } else if (v->last_seq_no == v->cur_seq_no) { + v->m3u8_hold_counters++; + if (v->m3u8_hold_counters >= c->m3u8_hold_counters) { + return AVERROR_EOF; + } + } else { + av_log(v->parent, AV_LOG_WARNING, "maybe the m3u8 list sequence have been wraped.\n"); + } if (v->cur_seq_no >= v->start_seq_no + v->n_segments) { if (v->finished) return AVERROR_EOF; @@ -1453,6 +1509,7 @@ if (c->http_multiple == 1 && v->input_next_requested) { FFSWAP(AVIOContext *, v->input, v->input_next); + v->cur_seg_offset = 0; v->input_next_requested = 0; ret = 0; } else { @@ -1461,7 +1518,7 @@ if (ret < 0) { if (ff_check_interrupt(c->interrupt_callback)) return AVERROR_EXIT; - av_log(v->parent, AV_LOG_WARNING, "Failed to open segment %d of playlist %d\n", + av_log(v->parent, AV_LOG_WARNING, "Failed to open segment %"PRId64" of playlist %d\n", v->cur_seq_no, v->index); v->cur_seq_no += 1; @@ -1486,7 +1543,7 @@ if (ret < 0) { if (ff_check_interrupt(c->interrupt_callback)) return AVERROR_EXIT; - av_log(v->parent, AV_LOG_WARNING, "Failed to open segment %d of playlist %d\n", + av_log(v->parent, AV_LOG_WARNING, "Failed to open segment %"PRId64" of playlist %d\n", v->cur_seq_no + 1, v->index); } else { @@ -1583,7 +1640,7 @@ /* if timestamp was in valid range: returns 1 and sets seq_no * if not: returns 0 and sets seq_no to closest segment */ static int find_timestamp_in_playlist(HLSContext *c, struct playlist *pls, - int64_t timestamp, int *seq_no) + int64_t timestamp, int64_t *seq_no) { int i; int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? @@ -1608,9 +1665,9 @@ return 0; } -static int select_cur_seq_no(HLSContext *c, struct playlist *pls) +static int64_t select_cur_seq_no(HLSContext *c, struct playlist *pls) { - int seq_no; + int64_t seq_no; if (!pls->finished && !c->first_packet && av_gettime_relative() - pls->last_load_time >= default_reload_interval(pls)) @@ -1651,7 +1708,7 @@ { HLSContext *c = s->priv_data; static const char * const opts[] = { - "headers", "http_proxy", "user_agent", "cookies", "referer", "rw_timeout", NULL }; + "headers", "http_proxy", "user_agent", "cookies", "referer", "rw_timeout", "icy", NULL }; const char * const * opt = opts; uint8_t *buf; int ret = 0; @@ -1718,6 +1775,20 @@ else avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den); + // copy disposition + st->disposition = ist->disposition; + + // copy side data + for (int i = 0; i < ist->nb_side_data; i++) { + const AVPacketSideData *sd_src = &ist->side_data[i]; + uint8_t *dst_data; + + dst_data = av_stream_new_side_data(st, sd_src->type, sd_src->size); + if (!dst_data) + return AVERROR(ENOMEM); + memcpy(dst_data, sd_src->data, sd_src->size); + } + st->internal->need_context_update = 1; return 0; @@ -1788,7 +1859,7 @@ { HLSContext *c = s->priv_data; int ret = 0, i; - int highest_cur_seq_no = 0; + int64_t highest_cur_seq_no = 0; c->ctx = s; c->interrupt_callback = &s->interrupt_callback; @@ -1800,8 +1871,10 @@ if ((ret = save_avio_options(s)) < 0) goto fail; - /* Some HLS servers don't like being sent the range header */ - av_dict_set(&c->avio_opts, "seekable", "0", 0); + /* XXX: Some HLS servers don't like being sent the range header, + in this case, need to setting http_seekable = 0 to disable + the range header */ + av_dict_set_int(&c->avio_opts, "seekable", c->http_seekable, 0); if ((ret = parse_playlist(c, s->url, NULL, s->pb)) < 0) goto fail; @@ -1816,15 +1889,22 @@ if (c->n_playlists > 1 || c->playlists[0]->n_segments == 0) { for (i = 0; i < c->n_playlists; i++) { struct playlist *pls = c->playlists[i]; - if ((ret = parse_playlist(c, pls->url, pls, NULL)) < 0) + pls->m3u8_hold_counters = 0; + if ((ret = parse_playlist(c, pls->url, pls, NULL)) < 0) { + av_log(s, AV_LOG_WARNING, "parse_playlist error %s [%s]\n", av_err2str(ret), pls->url); + pls->broken = 1; + if (c->n_playlists > 1) + continue; goto fail; + } } } - if (c->variants[0]->playlists[0]->n_segments == 0) { - av_log(s, AV_LOG_WARNING, "Empty segment\n"); - ret = AVERROR_EOF; - goto fail; + for (i = 0; i < c->n_variants; i++) { + if (c->variants[i]->playlists[0]->n_segments == 0) { + av_log(s, AV_LOG_WARNING, "Empty segment [%s]\n", c->variants[i]->playlists[0]->url); + c->variants[i]->playlists[0]->broken = 1; + } } /* If this isn't a live stream, calculate the total duration of the @@ -1873,6 +1953,7 @@ /* Open the demuxer for each playlist */ for (i = 0; i < c->n_playlists; i++) { struct playlist *pls = c->playlists[i]; + char *url; ff_const59 AVInputFormat *in_fmt = NULL; if (!(pls->ctx = avformat_alloc_context())) { @@ -1908,19 +1989,23 @@ } ffio_init_context(&pls->pb, pls->read_buffer, INITIAL_BUFFER_SIZE, 0, pls, read_data, NULL, NULL); - pls->pb.seekable = 0; - ret = av_probe_input_buffer(&pls->pb, &in_fmt, pls->segments[0]->url, - NULL, 0, 0); + pls->ctx->probesize = s->probesize > 0 ? s->probesize : 1024 * 4; + pls->ctx->max_analyze_duration = s->max_analyze_duration > 0 ? s->max_analyze_duration : 4 * AV_TIME_BASE; + pls->ctx->interrupt_callback = s->interrupt_callback; + url = av_strdup(pls->segments[0]->url); + ret = av_probe_input_buffer(&pls->pb, &in_fmt, url, NULL, 0, 0); if (ret < 0) { /* Free the ctx - it isn't initialized properly at this point, * so avformat_close_input shouldn't be called. If * avformat_open_input fails below, it frees and zeros the * context, so it doesn't need any special treatment like this. */ - av_log(s, AV_LOG_ERROR, "Error when loading first segment '%s'\n", pls->segments[0]->url); + av_log(s, AV_LOG_ERROR, "Error when loading first segment '%s'\n", url); avformat_free_context(pls->ctx); pls->ctx = NULL; + av_free(url); goto fail; } + av_free(url); pls->ctx->pb = &pls->pb; pls->ctx->io_open = nested_io_open; pls->ctx->flags |= s->flags & ~AVFMT_FLAG_CUSTOM_IO; @@ -1933,11 +2018,10 @@ goto fail; if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) { - ff_id3v2_parse_apic(pls->ctx, &pls->id3_deferred_extra); + ff_id3v2_parse_apic(pls->ctx, pls->id3_deferred_extra); avformat_queue_attached_pictures(pls->ctx); - ff_id3v2_parse_priv(pls->ctx, &pls->id3_deferred_extra); + ff_id3v2_parse_priv(pls->ctx, pls->id3_deferred_extra); ff_id3v2_free_extra_meta(&pls->id3_deferred_extra); - pls->id3_deferred_extra = NULL; } if (pls->is_id3_timestamped == -1) @@ -1994,6 +2078,9 @@ cur_needed = playlist_needed(c->playlists[i]); + if (pls->broken) { + continue; + } if (cur_needed && !pls->needed) { pls->needed = 1; changed = 1; @@ -2005,13 +2092,11 @@ pls->seek_flags = AVSEEK_FLAG_ANY; pls->seek_stream_index = -1; } - av_log(s, AV_LOG_INFO, "Now receiving playlist %d, segment %d\n", i, pls->cur_seq_no); + av_log(s, AV_LOG_INFO, "Now receiving playlist %d, segment %"PRId64"\n", i, pls->cur_seq_no); } else if (first && !cur_needed && pls->needed) { - if (pls->input) - ff_format_io_close(pls->parent, &pls->input); + ff_format_io_close(pls->parent, &pls->input); pls->input_read_done = 0; - if (pls->input_next) - ff_format_io_close(pls->parent, &pls->input_next); + ff_format_io_close(pls->parent, &pls->input_next); pls->input_next_requested = 0; pls->needed = 0; changed = 1; @@ -2024,26 +2109,26 @@ static void fill_timing_for_id3_timestamped_stream(struct playlist *pls) { if (pls->id3_offset >= 0) { - pls->pkt.dts = pls->id3_mpegts_timestamp + + pls->pkt->dts = pls->id3_mpegts_timestamp + av_rescale_q(pls->id3_offset, - pls->ctx->streams[pls->pkt.stream_index]->time_base, + pls->ctx->streams[pls->pkt->stream_index]->time_base, MPEG_TIME_BASE_Q); - if (pls->pkt.duration) - pls->id3_offset += pls->pkt.duration; + if (pls->pkt->duration) + pls->id3_offset += pls->pkt->duration; else pls->id3_offset = -1; } else { /* there have been packets with unknown duration * since the last id3 tag, should not normally happen */ - pls->pkt.dts = AV_NOPTS_VALUE; + pls->pkt->dts = AV_NOPTS_VALUE; } - if (pls->pkt.duration) - pls->pkt.duration = av_rescale_q(pls->pkt.duration, - pls->ctx->streams[pls->pkt.stream_index]->time_base, + if (pls->pkt->duration) + pls->pkt->duration = av_rescale_q(pls->pkt->duration, + pls->ctx->streams[pls->pkt->stream_index]->time_base, MPEG_TIME_BASE_Q); - pls->pkt.pts = AV_NOPTS_VALUE; + pls->pkt->pts = AV_NOPTS_VALUE; } static AVRational get_timebase(struct playlist *pls) @@ -2051,7 +2136,7 @@ if (pls->is_id3_timestamped) return MPEG_TIME_BASE_Q; - return pls->ctx->streams[pls->pkt.stream_index]->time_base; + return pls->ctx->streams[pls->pkt->stream_index]->time_base; } static int compare_ts_with_wrapdetect(int64_t ts_a, struct playlist *pls_a, @@ -2075,26 +2160,25 @@ struct playlist *pls = c->playlists[i]; /* Make sure we've got one buffered packet from each open playlist * stream */ - if (pls->needed && !pls->pkt.data) { + if (pls->needed && !pls->pkt->data) { while (1) { int64_t ts_diff; AVRational tb; - ret = av_read_frame(pls->ctx, &pls->pkt); + ret = av_read_frame(pls->ctx, pls->pkt); if (ret < 0) { if (!avio_feof(&pls->pb) && ret != AVERROR_EOF) return ret; - reset_packet(&pls->pkt); break; } else { /* stream_index check prevents matching picture attachments etc. */ - if (pls->is_id3_timestamped && pls->pkt.stream_index == 0) { + if (pls->is_id3_timestamped && pls->pkt->stream_index == 0) { /* audio elementary streams are id3 timestamped */ fill_timing_for_id3_timestamped_stream(pls); } if (c->first_timestamp == AV_NOPTS_VALUE && - pls->pkt.dts != AV_NOPTS_VALUE) - c->first_timestamp = av_rescale_q(pls->pkt.dts, + pls->pkt->dts != AV_NOPTS_VALUE) + c->first_timestamp = av_rescale_q(pls->pkt->dts, get_timebase(pls), AV_TIME_BASE_Q); } @@ -2102,36 +2186,35 @@ break; if (pls->seek_stream_index < 0 || - pls->seek_stream_index == pls->pkt.stream_index) { + pls->seek_stream_index == pls->pkt->stream_index) { - if (pls->pkt.dts == AV_NOPTS_VALUE) { + if (pls->pkt->dts == AV_NOPTS_VALUE) { pls->seek_timestamp = AV_NOPTS_VALUE; break; } tb = get_timebase(pls); - ts_diff = av_rescale_rnd(pls->pkt.dts, AV_TIME_BASE, + ts_diff = av_rescale_rnd(pls->pkt->dts, AV_TIME_BASE, tb.den, AV_ROUND_DOWN) - pls->seek_timestamp; if (ts_diff >= 0 && (pls->seek_flags & AVSEEK_FLAG_ANY || - pls->pkt.flags & AV_PKT_FLAG_KEY)) { + pls->pkt->flags & AV_PKT_FLAG_KEY)) { pls->seek_timestamp = AV_NOPTS_VALUE; break; } } - av_packet_unref(&pls->pkt); - reset_packet(&pls->pkt); + av_packet_unref(pls->pkt); } } /* Check if this stream has the packet with the lowest dts */ - if (pls->pkt.data) { + if (pls->pkt->data) { struct playlist *minpls = minplaylist < 0 ? NULL : c->playlists[minplaylist]; if (minplaylist < 0) { minplaylist = i; } else { - int64_t dts = pls->pkt.dts; - int64_t mindts = minpls->pkt.dts; + int64_t dts = pls->pkt->dts; + int64_t mindts = minpls->pkt->dts; if (dts == AV_NOPTS_VALUE || (mindts != AV_NOPTS_VALUE && compare_ts_with_wrapdetect(dts, pls, mindts, minpls) < 0)) @@ -2148,8 +2231,7 @@ ret = update_streams_from_subdemuxer(s, pls); if (ret < 0) { - av_packet_unref(&pls->pkt); - reset_packet(&pls->pkt); + av_packet_unref(pls->pkt); return ret; } @@ -2170,20 +2252,18 @@ update_noheader_flag(s); } - if (pls->pkt.stream_index >= pls->n_main_streams) { + if (pls->pkt->stream_index >= pls->n_main_streams) { av_log(s, AV_LOG_ERROR, "stream index inconsistency: index %d, %d main streams, %d subdemuxer streams\n", - pls->pkt.stream_index, pls->n_main_streams, pls->ctx->nb_streams); - av_packet_unref(&pls->pkt); - reset_packet(&pls->pkt); + pls->pkt->stream_index, pls->n_main_streams, pls->ctx->nb_streams); + av_packet_unref(pls->pkt); return AVERROR_BUG; } - ist = pls->ctx->streams[pls->pkt.stream_index]; - st = pls->main_streams[pls->pkt.stream_index]; + ist = pls->ctx->streams[pls->pkt->stream_index]; + st = pls->main_streams[pls->pkt->stream_index]; - *pkt = pls->pkt; + av_packet_move_ref(pkt, pls->pkt); pkt->stream_index = st->index; - reset_packet(&c->playlists[minplaylist]->pkt); if (pkt->dts != AV_NOPTS_VALUE) c->cur_timestamp = av_rescale_q(pkt->dts, @@ -2195,7 +2275,6 @@ if (ist->codecpar->codec_id != st->codecpar->codec_id) { ret = set_stream_info_from_input_stream(st, pls, ist); if (ret < 0) { - av_packet_unref(pkt); return ret; } } @@ -2210,10 +2289,10 @@ { HLSContext *c = s->priv_data; struct playlist *seek_pls = NULL; - int i, seq_no; - int j; + int i, j; int stream_subdemuxer_index; int64_t first_timestamp, seek_timestamp, duration; + int64_t seq_no; if ((flags & AVSEEK_FLAG_BYTE) || (c->ctx->ctx_flags & AVFMTCTX_UNSEEKABLE)) return AVERROR(ENOSYS); @@ -2255,14 +2334,11 @@ for (i = 0; i < c->n_playlists; i++) { /* Reset reading */ struct playlist *pls = c->playlists[i]; - if (pls->input) - ff_format_io_close(pls->parent, &pls->input); + ff_format_io_close(pls->parent, &pls->input); pls->input_read_done = 0; - if (pls->input_next) - ff_format_io_close(pls->parent, &pls->input_next); + ff_format_io_close(pls->parent, &pls->input_next); pls->input_next_requested = 0; - av_packet_unref(&pls->pkt); - reset_packet(&pls->pkt); + av_packet_unref(pls->pkt); pls->pb.eof_reached = 0; /* Clear any buffered data */ pls->pb.buf_end = pls->pb.buf_ptr = pls->pb.buffer; @@ -2311,14 +2387,18 @@ OFFSET(live_start_index), AV_OPT_TYPE_INT, {.i64 = -3}, INT_MIN, INT_MAX, FLAGS}, {"allowed_extensions", "List of file extensions that hls is allowed to access", OFFSET(allowed_extensions), AV_OPT_TYPE_STRING, - {.str = "3gp,aac,avi,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,wav"}, + {.str = "3gp,aac,avi,ac3,eac3,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,wav"}, INT_MIN, INT_MAX, FLAGS}, {"max_reload", "Maximum number of times a insufficient list is attempted to be reloaded", OFFSET(max_reload), AV_OPT_TYPE_INT, {.i64 = 1000}, 0, INT_MAX, FLAGS}, + {"m3u8_hold_counters", "The maximum number of times to load m3u8 when it refreshes without new segments", + OFFSET(m3u8_hold_counters), AV_OPT_TYPE_INT, {.i64 = 1000}, 0, INT_MAX, FLAGS}, {"http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, {"http_multiple", "Use multiple HTTP connections for fetching segments", OFFSET(http_multiple), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, FLAGS}, + {"http_seekable", "Use HTTP partial requests, 0 = disable, 1 = enable, -1 = auto", + OFFSET(http_seekable), AV_OPT_TYPE_BOOL, { .i64 = -1}, -1, 1, FLAGS}, {NULL} }; @@ -2334,7 +2414,7 @@ .long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"), .priv_class = &hls_class, .priv_data_size = sizeof(HLSContext), - .flags = AVFMT_NOGENSEARCH, + .flags = AVFMT_NOGENSEARCH | AVFMT_TS_DISCONT, .read_probe = hls_probe, .read_header = hls_read_header, .read_packet = hls_read_packet, diff -Nru ffmpeg-4.2.2/libavformat/hlsenc.c ffmpeg-4.4/libavformat/hlsenc.c --- ffmpeg-4.2.2/libavformat/hlsenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/hlsenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -41,10 +41,12 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" #include "libavutil/log.h" +#include "libavutil/time.h" #include "libavutil/time_internal.h" #include "avformat.h" #include "avio_internal.h" +#include "avc.h" #if CONFIG_HTTP_PROTOCOL #include "http.h" #endif @@ -53,9 +55,11 @@ #include "os_support.h" typedef enum { - HLS_START_SEQUENCE_AS_START_NUMBER = 0, - HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH = 1, - HLS_START_SEQUENCE_AS_FORMATTED_DATETIME = 2, // YYYYMMDDhhmmss + HLS_START_SEQUENCE_AS_START_NUMBER = 0, + HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH = 1, + HLS_START_SEQUENCE_AS_FORMATTED_DATETIME = 2, // YYYYMMDDhhmmss + HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH = 3, + HLS_START_SEQUENCE_LAST, // unused } StartSequenceSourceType; typedef enum { @@ -66,6 +70,7 @@ #define KEYSIZE 16 #define LINE_BUFFER_SIZE MAX_URL_SIZE #define HLS_MICROSECOND_UNIT 1000000 +#define BUFSIZE (16 * 1024) #define POSTFIX_PATTERN "_%d" typedef struct HLSSegment { @@ -83,6 +88,7 @@ char iv_string[KEYSIZE*2 + 1]; struct HLSSegment *next; + double discont_program_date_time; } HLSSegment; typedef enum HLSFlags { @@ -116,8 +122,11 @@ ff_const59 AVOutputFormat *oformat; ff_const59 AVOutputFormat *vtt_oformat; AVIOContext *out; + AVIOContext *out_single_file; int packets_written; int init_range_length; + uint8_t *temp_buffer; + uint8_t *init_buffer; AVFormatContext *avf; AVFormatContext *vtt_avf; @@ -125,6 +134,7 @@ int has_video; int has_subtitle; int new_start; + int start_pts_from_audio; double dpp; // duration per packet int64_t start_pts; int64_t end_pts; @@ -143,6 +153,7 @@ HLSSegment *last_segment; HLSSegment *old_segments; + char *basename_tmp; char *basename; char *vtt_basename; char *vtt_m3u8_name; @@ -154,23 +165,30 @@ char *fmp4_init_filename; char *base_output_dirname; + int encrypt_started; + + char key_file[LINE_BUFFER_SIZE + 1]; + char key_uri[LINE_BUFFER_SIZE + 1]; + char key_string[KEYSIZE*2 + 1]; + char iv_string[KEYSIZE*2 + 1]; + AVStream **streams; char codec_attr[128]; CodecAttributeStatus attr_status; unsigned int nb_streams; int m3u8_created; /* status of media play-list creation */ int is_default; /* default status of audio group */ - char *language; /* audio lauguage name */ - char *agroup; /* audio group name */ - char *ccgroup; /* closed caption group name */ - char *baseurl; - char *varname; // variant name + const char *language; /* audio lauguage name */ + const char *agroup; /* audio group name */ + const char *sgroup; /* subtitle group name */ + const char *ccgroup; /* closed caption group name */ + const char *varname; /* variant name */ } VariantStream; typedef struct ClosedCaptionsStream { - char *ccgroup; /* closed caption group name */ - char *instreamid; /* closed captions INSTREAM-ID */ - char *language; /* closed captions langauge */ + const char *ccgroup; /* closed caption group name */ + const char *instreamid; /* closed captions INSTREAM-ID */ + const char *language; /* closed captions langauge */ } ClosedCaptionsStream; typedef struct HLSContext { @@ -178,8 +196,8 @@ int64_t start_sequence; uint32_t start_sequence_source_type; // enum StartSequenceSourceType - float time; // Set by a private option. - float init_time; // Set by a private option. + int64_t time; // Set by a private option. + int64_t init_time; // Set by a private option. int max_nb_segments; // Set by a private option. int hls_delete_threshold; // Set by a private option. #if FF_API_HLS_WRAP @@ -190,6 +208,7 @@ char *segment_filename; char *fmp4_init_filename; int segment_type; + int resend_init_file; ///< resend init file into disk after refresh m3u8 int use_localtime; ///< flag to expand filename with localtime int use_localtime_mkdir;///< flag to mkdir dirname in timebased filename @@ -198,7 +217,6 @@ int64_t max_seg_size; // every segment file max size char *baseurl; - char *format_options_str; char *vtt_format_options_str; char *subtitle_filename; AVDictionary *format_options; @@ -242,8 +260,32 @@ int has_video_m3u8; /* has video stream m3u8 list */ } HLSContext; +static int strftime_expand(const char *fmt, char **dest) +{ + int r = 1; + time_t now0; + struct tm *tm, tmpbuf; + char *buf; + + buf = av_mallocz(MAX_URL_SIZE); + if (!buf) + return AVERROR(ENOMEM); + + time(&now0); + tm = localtime_r(&now0, &tmpbuf); + r = strftime(buf, MAX_URL_SIZE, fmt, tm); + if (!r) { + av_free(buf); + return AVERROR(EINVAL); + } + *dest = buf; + + return r; +} + static int hlsenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, - AVDictionary **options) { + AVDictionary **options) +{ HLSContext *hls = s->priv_data; int http_base_proto = filename ? ff_is_http_proto(filename) : 0; int err = AVERROR_MUXER_NOT_FOUND; @@ -262,11 +304,13 @@ return err; } -static void hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) { +static int hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) +{ HLSContext *hls = s->priv_data; int http_base_proto = filename ? ff_is_http_proto(filename) : 0; + int ret = 0; if (!*pb) - return; + return ret; if (!http_base_proto || !hls->http_persistent || hls->key_info_file || hls->encrypt) { ff_format_io_close(s, pb); #if CONFIG_HTTP_PROTOCOL @@ -275,8 +319,10 @@ av_assert0(http_url_context); avio_flush(*pb); ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE); + ret = ff_http_get_shutdown_status(http_url_context); #endif } + return ret; } static void set_http_options(AVFormatContext *s, AVDictionary **options, HLSContext *c) @@ -286,7 +332,6 @@ if (c->method) { av_dict_set(options, "method", c->method, 0); } else if (http_base_proto) { - av_log(c, AV_LOG_WARNING, "No HTTP method set, hls muxer defaulting to method PUT.\n"); av_dict_set(options, "method", "PUT", 0); } if (c->user_agent) @@ -299,7 +344,8 @@ av_dict_set(options, "headers", c->headers, 0); } -static void write_codec_attr(AVStream *st, VariantStream *vs) { +static void write_codec_attr(AVStream *st, VariantStream *vs) +{ int codec_strlen = strlen(vs->codec_attr); char attr[32]; @@ -316,6 +362,51 @@ } else { goto fail; } + } else if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) { + uint8_t *data = st->codecpar->extradata; + int profile = FF_PROFILE_UNKNOWN; + int level = FF_LEVEL_UNKNOWN; + + if (st->codecpar->profile != FF_PROFILE_UNKNOWN) + profile = st->codecpar->profile; + if (st->codecpar->level != FF_LEVEL_UNKNOWN) + level = st->codecpar->level; + + /* check the boundary of data which from current position is small than extradata_size */ + while (data && (data - st->codecpar->extradata + 19) < st->codecpar->extradata_size) { + /* get HEVC SPS NAL and seek to profile_tier_level */ + if (!(data[0] | data[1] | data[2]) && data[3] == 1 && ((data[4] & 0x7E) == 0x42)) { + uint8_t *rbsp_buf; + int remain_size = 0; + int rbsp_size = 0; + /* skip start code + nalu header */ + data += 6; + /* process by reference General NAL unit syntax */ + remain_size = st->codecpar->extradata_size - (data - st->codecpar->extradata); + rbsp_buf = ff_nal_unit_extract_rbsp(data, remain_size, &rbsp_size, 0); + if (!rbsp_buf) + return; + if (rbsp_size < 13) { + av_freep(&rbsp_buf); + break; + } + /* skip sps_video_parameter_set_id u(4), + * sps_max_sub_layers_minus1 u(3), + * and sps_temporal_id_nesting_flag u(1) */ + profile = rbsp_buf[1] & 0x1f; + /* skip 8 + 8 + 32 + 4 + 43 + 1 bit */ + level = rbsp_buf[12]; + av_freep(&rbsp_buf); + break; + } + data++; + } + if (st->codecpar->codec_tag == MKTAG('h','v','c','1') && + profile != FF_PROFILE_UNKNOWN && + level != FF_LEVEL_UNKNOWN) { + snprintf(attr, sizeof(attr), "%s.%d.4.L%d.B01", av_fourcc2str(st->codecpar->codec_tag), profile, level); + } else + goto fail; } else if (st->codecpar->codec_id == AV_CODEC_ID_MP2) { snprintf(attr, sizeof(attr), "mp4a.40.33"); } else if (st->codecpar->codec_id == AV_CODEC_ID_MP3) { @@ -347,11 +438,11 @@ static int replace_str_data_in_filename(char **s, const char *filename, char placeholder, const char *datastring) { const char *p; - char *new_filename; char c; int addchar_count; int found_count = 0; AVBPrint buf; + int ret; av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); @@ -377,22 +468,21 @@ } if (!av_bprint_is_complete(&buf)) { av_bprint_finalize(&buf, NULL); - return -1; + return AVERROR(ENOMEM); } - if (av_bprint_finalize(&buf, &new_filename) < 0 || !new_filename) - return -1; - *s = new_filename; + if ((ret = av_bprint_finalize(&buf, s)) < 0) + return ret; return found_count; } static int replace_int_data_in_filename(char **s, const char *filename, char placeholder, int64_t number) { const char *p; - char *new_filename; char c; int nd, addchar_count; int found_count = 0; AVBPrint buf; + int ret; av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); @@ -426,11 +516,10 @@ } if (!av_bprint_is_complete(&buf)) { av_bprint_finalize(&buf, NULL); - return -1; + return AVERROR(ENOMEM); } - if (av_bprint_finalize(&buf, &new_filename) < 0 || !new_filename) - return -1; - *s = new_filename; + if ((ret = av_bprint_finalize(&buf, s)) < 0) + return ret; return found_count; } @@ -447,7 +536,6 @@ static int flush_dynbuf(VariantStream *vs, int *range_length) { AVFormatContext *ctx = vs->avf; - uint8_t *buffer; if (!ctx->pb) { return AVERROR(EINVAL); @@ -455,32 +543,67 @@ // flush av_write_frame(ctx, NULL); - avio_flush(ctx->pb); // write out to file - *range_length = avio_close_dyn_buf(ctx->pb, &buffer); + *range_length = avio_close_dyn_buf(ctx->pb, &vs->temp_buffer); ctx->pb = NULL; - avio_write(vs->out, buffer, *range_length); - av_free(buffer); + avio_write(vs->out, vs->temp_buffer, *range_length); + avio_flush(vs->out); // re-open buffer return avio_open_dyn_buf(&ctx->pb); } +static void reflush_dynbuf(VariantStream *vs, int *range_length) +{ + // re-open buffer + avio_write(vs->out, vs->temp_buffer, *range_length); +} + +#if HAVE_DOS_PATHS +#define SEPARATOR '\\' +#else +#define SEPARATOR '/' +#endif + +static int hls_delete_file(HLSContext *hls, AVFormatContext *avf, + const char *path, const char *proto) +{ + if (hls->method || (proto && !av_strcasecmp(proto, "http"))) { + AVDictionary *opt = NULL; + AVIOContext *out = NULL; + int ret; + av_dict_set(&opt, "method", "DELETE", 0); + ret = avf->io_open(avf, &out, path, AVIO_FLAG_WRITE, &opt); + av_dict_free(&opt); + if (ret < 0) + return hls->ignore_io_errors ? 1 : ret; + ff_format_io_close(avf, &out); + } else if (unlink(path) < 0) { + av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n", + path, strerror(errno)); + } + return 0; +} + static int hls_delete_old_segments(AVFormatContext *s, HLSContext *hls, - VariantStream *vs) { + VariantStream *vs) +{ HLSSegment *segment, *previous_segment = NULL; float playlist_duration = 0.0f; - int ret = 0, path_size, sub_path_size; + int ret = 0; int segment_cnt = 0; - char *dirname = NULL, *p, *sub_path; - char *path = NULL; - char *vtt_dirname = NULL; - AVDictionary *options = NULL; - AVIOContext *out = NULL; + AVBPrint path; + const char *dirname = NULL; + char *dirname_r = NULL; + char *dirname_repl = NULL; + const char *vtt_dirname = NULL; + char *vtt_dirname_r = NULL; const char *proto = NULL; + av_bprint_init(&path, 0, AV_BPRINT_SIZE_UNLIMITED); + segment = vs->segments; while (segment) { playlist_duration += segment->duration; @@ -505,114 +628,71 @@ } if (segment && !hls->use_localtime_mkdir) { - if (hls->segment_filename) { - dirname = av_strdup(hls->segment_filename); - } else { - dirname = av_strdup(vs->avf->url); - } - if (!dirname) { - ret = AVERROR(ENOMEM); - goto fail; - } - p = (char *)av_basename(dirname); - *p = '\0'; - + dirname_r = hls->segment_filename ? av_strdup(hls->segment_filename): av_strdup(vs->avf->url); + dirname = av_dirname(dirname_r); } /* if %v is present in the file's directory * all segment belongs to the same variant, so do it only once before the loop*/ if (dirname && av_stristr(dirname, "%v")) { - char * r_dirname = dirname; if (!vs->varname) { - if (replace_int_data_in_filename(&r_dirname, dirname, 'v', segment->var_stream_idx) < 1) { + if (replace_int_data_in_filename(&dirname_repl, dirname, 'v', segment->var_stream_idx) < 1) { ret = AVERROR(EINVAL); goto fail; } } else { - if (replace_str_data_in_filename(&r_dirname, dirname, 'v', vs->varname) < 1) { + if (replace_str_data_in_filename(&dirname_repl, dirname, 'v', vs->varname) < 1) { ret = AVERROR(EINVAL); goto fail; } } - av_free(dirname); - dirname = r_dirname; + dirname = dirname_repl; } while (segment) { av_log(hls, AV_LOG_DEBUG, "deleting old segment %s\n", - segment->filename); - path_size = (hls->use_localtime_mkdir ? 0 : strlen(dirname)) + strlen(segment->filename) + 1; - path = av_malloc(path_size); - if (!path) { + segment->filename); + if (!hls->use_localtime_mkdir) // segment->filename contains basename only + av_bprintf(&path, "%s%c", dirname, SEPARATOR); + av_bprintf(&path, "%s", segment->filename); + + if (!av_bprint_is_complete(&path)) { ret = AVERROR(ENOMEM); goto fail; } - if (hls->use_localtime_mkdir) - av_strlcpy(path, segment->filename, path_size); - else { // segment->filename contains basename only - av_strlcpy(path, dirname, path_size); - av_strlcat(path, segment->filename, path_size); - } - proto = avio_find_protocol_name(s->url); - if (hls->method || (proto && !av_strcasecmp(proto, "http"))) { - av_dict_set(&options, "method", "DELETE", 0); - if ((ret = vs->avf->io_open(vs->avf, &out, path, AVIO_FLAG_WRITE, &options)) < 0) { - if (hls->ignore_io_errors) - ret = 0; - goto fail; - } - ff_format_io_close(vs->avf, &out); - } else if (unlink(path) < 0) { - av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n", - path, strerror(errno)); - } + if (ret = hls_delete_file(hls, vs->avf, path.str, proto)) + goto fail; if ((segment->sub_filename[0] != '\0')) { - vtt_dirname = av_strdup(vs->vtt_avf->url); - if (!vtt_dirname) { - ret = AVERROR(ENOMEM); - goto fail; - } - p = (char *)av_basename(vtt_dirname); - *p = '\0'; - sub_path_size = strlen(segment->sub_filename) + 1 + strlen(vtt_dirname); - sub_path = av_malloc(sub_path_size); - if (!sub_path) { + vtt_dirname_r = av_strdup(vs->vtt_avf->url); + vtt_dirname = av_dirname(vtt_dirname_r); + + av_bprint_clear(&path); + av_bprintf(&path, "%s%c%s", vtt_dirname, SEPARATOR, + segment->sub_filename); + av_freep(&vtt_dirname_r); + + if (!av_bprint_is_complete(&path)) { ret = AVERROR(ENOMEM); goto fail; } - av_strlcpy(sub_path, vtt_dirname, sub_path_size); - av_strlcat(sub_path, segment->sub_filename, sub_path_size); - - if (hls->method || (proto && !av_strcasecmp(proto, "http"))) { - av_dict_set(&options, "method", "DELETE", 0); - if ((ret = vs->vtt_avf->io_open(vs->vtt_avf, &out, sub_path, AVIO_FLAG_WRITE, &options)) < 0) { - if (hls->ignore_io_errors) - ret = 0; - av_free(sub_path); - goto fail; - } - ff_format_io_close(vs->vtt_avf, &out); - } else if (unlink(sub_path) < 0) { - av_log(hls, AV_LOG_ERROR, "failed to delete old segment %s: %s\n", - sub_path, strerror(errno)); - } - av_free(sub_path); + if (ret = hls_delete_file(hls, vs->vtt_avf, path.str, proto)) + goto fail; } - av_freep(&path); + av_bprint_clear(&path); previous_segment = segment; segment = previous_segment->next; - av_free(previous_segment); + av_freep(&previous_segment); } fail: - av_free(path); - av_free(dirname); - av_free(vtt_dirname); + av_bprint_finalize(&path, NULL); + av_freep(&dirname_r); + av_freep(&dirname_repl); return ret; } @@ -638,13 +718,14 @@ int len; AVIOContext *pb; uint8_t key[KEYSIZE]; + char * key_basename_source = (hls->master_m3u8_url) ? hls->master_m3u8_url : s->url; - len = strlen(s->url) + 4 + 1; + len = strlen(key_basename_source) + 4 + 1; hls->key_basename = av_mallocz(len); if (!hls->key_basename) return AVERROR(ENOMEM); - av_strlcpy(hls->key_basename, s->url, len); + av_strlcpy(hls->key_basename, key_basename_source, len); av_strlcat(hls->key_basename, ".key", len); if (hls->key_url) { @@ -680,6 +761,7 @@ } if (!*hls->key_string) { + AVDictionary *options = NULL; if (!hls->key) { if ((ret = randomize(key, sizeof(key))) < 0) { av_log(s, AV_LOG_ERROR, "Cannot generate a strong random key\n"); @@ -690,7 +772,10 @@ } ff_data_to_hex(hls->key_string, key, sizeof(key), 0); - if ((ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_WRITE, NULL)) < 0) + set_http_options(s, &options, hls); + ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_WRITE, &options); + av_dict_free(&options); + if (ret < 0) return ret; avio_seek(pb, 0, SEEK_CUR); avio_write(pb, key, KEYSIZE); @@ -700,54 +785,61 @@ } -static int hls_encryption_start(AVFormatContext *s) +static int hls_encryption_start(AVFormatContext *s, VariantStream *vs) { HLSContext *hls = s->priv_data; int ret; AVIOContext *pb; uint8_t key[KEYSIZE]; + AVDictionary *options = NULL; - if ((ret = s->io_open(s, &pb, hls->key_info_file, AVIO_FLAG_READ, NULL)) < 0) { + set_http_options(s, &options, hls); + ret = s->io_open(s, &pb, hls->key_info_file, AVIO_FLAG_READ, &options); + av_dict_free(&options); + if (ret < 0) { av_log(hls, AV_LOG_ERROR, - "error opening key info file %s\n", hls->key_info_file); + "error opening key info file %s\n", hls->key_info_file); return ret; } - ff_get_line(pb, hls->key_uri, sizeof(hls->key_uri)); - hls->key_uri[strcspn(hls->key_uri, "\r\n")] = '\0'; + ff_get_line(pb, vs->key_uri, sizeof(vs->key_uri)); + vs->key_uri[strcspn(vs->key_uri, "\r\n")] = '\0'; - ff_get_line(pb, hls->key_file, sizeof(hls->key_file)); - hls->key_file[strcspn(hls->key_file, "\r\n")] = '\0'; + ff_get_line(pb, vs->key_file, sizeof(vs->key_file)); + vs->key_file[strcspn(vs->key_file, "\r\n")] = '\0'; - ff_get_line(pb, hls->iv_string, sizeof(hls->iv_string)); - hls->iv_string[strcspn(hls->iv_string, "\r\n")] = '\0'; + ff_get_line(pb, vs->iv_string, sizeof(vs->iv_string)); + vs->iv_string[strcspn(vs->iv_string, "\r\n")] = '\0'; ff_format_io_close(s, &pb); - if (!*hls->key_uri) { + if (!*vs->key_uri) { av_log(hls, AV_LOG_ERROR, "no key URI specified in key info file\n"); return AVERROR(EINVAL); } - if (!*hls->key_file) { + if (!*vs->key_file) { av_log(hls, AV_LOG_ERROR, "no key file specified in key info file\n"); return AVERROR(EINVAL); } - if ((ret = s->io_open(s, &pb, hls->key_file, AVIO_FLAG_READ, NULL)) < 0) { - av_log(hls, AV_LOG_ERROR, "error opening key file %s\n", hls->key_file); + set_http_options(s, &options, hls); + ret = s->io_open(s, &pb, vs->key_file, AVIO_FLAG_READ, &options); + av_dict_free(&options); + if (ret < 0) { + av_log(hls, AV_LOG_ERROR, "error opening key file %s\n", vs->key_file); return ret; } ret = avio_read(pb, key, sizeof(key)); ff_format_io_close(s, &pb); if (ret != sizeof(key)) { - av_log(hls, AV_LOG_ERROR, "error reading key file %s\n", hls->key_file); + av_log(hls, AV_LOG_ERROR, "error reading key file %s\n", vs->key_file); if (ret >= 0 || ret == AVERROR_EOF) ret = AVERROR(EINVAL); return ret; } - ff_data_to_hex(hls->key_string, key, sizeof(key), 0); + ff_data_to_hex(vs->key_string, key, sizeof(key), 0); return 0; } @@ -759,6 +851,7 @@ AVFormatContext *oc; AVFormatContext *vtt_oc = NULL; int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); + int remaining_options; int i, ret; ret = avformat_alloc_output_context2(&vs->avf, vs->oformat, NULL, NULL); @@ -770,20 +863,19 @@ if (!oc->url) return AVERROR(ENOMEM); - oc->oformat = vs->oformat; - oc->interrupt_callback = s->interrupt_callback; - oc->max_delay = s->max_delay; - oc->opaque = s->opaque; - oc->io_open = s->io_open; - oc->io_close = s->io_close; + oc->interrupt_callback = s->interrupt_callback; + oc->max_delay = s->max_delay; + oc->opaque = s->opaque; + oc->io_open = s->io_open; + oc->io_close = s->io_close; + oc->strict_std_compliance = s->strict_std_compliance; av_dict_copy(&oc->metadata, s->metadata, 0); - if(vs->vtt_oformat) { + if (vs->vtt_oformat) { ret = avformat_alloc_output_context2(&vs->vtt_avf, vs->vtt_oformat, NULL, NULL); if (ret < 0) return ret; vtt_oc = vs->vtt_avf; - vtt_oc->oformat = vs->vtt_oformat; av_dict_copy(&vtt_oc->metadata, s->metadata, 0); } @@ -811,11 +903,10 @@ av_dict_copy(&st->metadata, vs->streams[i]->metadata, 0); } - vs->packets_written = 1; vs->start_pos = 0; vs->new_start = 1; - if (hls->segment_type == SEGMENT_TYPE_FMP4) { + if (hls->segment_type == SEGMENT_TYPE_FMP4 && hls->max_seg_size > 0) { if (hls->http_persistent > 0) { //TODO: Support fragment fmp4 for http persistent in HLS muxer. av_log(s, AV_LOG_WARNING, "http persistent mode is currently unsupported for fragment mp4 in the HLS muxer.\n"); @@ -824,47 +915,46 @@ av_log(s, AV_LOG_WARNING, "Multi-file byterange mode is currently unsupported in the HLS muxer.\n"); return AVERROR_PATCHWELCOME; } + } - vs->packets_written = 0; - vs->init_range_length = 0; - set_http_options(s, &options, hls); - if ((ret = avio_open_dyn_buf(&oc->pb)) < 0) - return ret; + if ((ret = avio_open_dyn_buf(&oc->pb)) < 0) + return ret; + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + set_http_options(s, &options, hls); if (byterange_mode) { ret = hlsenc_io_open(s, &vs->out, vs->basename, &options); } else { ret = hlsenc_io_open(s, &vs->out, vs->base_output_dirname, &options); } av_dict_free(&options); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", vs->fmp4_init_filename); - return ret; - } - - if (hls->format_options_str) { - ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", - hls->format_options_str); - return ret; - } - } + } + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", vs->fmp4_init_filename); + return ret; + } - av_dict_copy(&options, hls->format_options, 0); + av_dict_copy(&options, hls->format_options, 0); + if (hls->segment_type == SEGMENT_TYPE_FMP4) { av_dict_set(&options, "fflags", "-autobsf", 0); av_dict_set(&options, "movflags", "+frag_custom+dash+delay_moov", AV_DICT_APPEND); - ret = avformat_init_output(oc, &options); - if (ret < 0) - return ret; - if (av_dict_count(options)) { - av_log(s, AV_LOG_ERROR, "Some of the provided format options in '%s' are not recognized\n", hls->format_options_str); - av_dict_free(&options); - return AVERROR(EINVAL); - } - avio_flush(oc->pb); - av_dict_free(&options); + } else { + /* We only require one PAT/PMT per segment. */ + char period[21]; + snprintf(period, sizeof(period), "%d", (INT_MAX / 2) - 1); + av_dict_set(&options, "sdt_period", period, AV_DICT_DONT_OVERWRITE); + av_dict_set(&options, "pat_period", period, AV_DICT_DONT_OVERWRITE); + } + ret = avformat_init_output(oc, &options); + remaining_options = av_dict_count(options); + av_dict_free(&options); + if (ret < 0) + return ret; + if (remaining_options) { + av_log(s, AV_LOG_ERROR, "Some of the provided format options are not recognized\n"); + return AVERROR(EINVAL); } + avio_flush(oc->pb); return 0; } @@ -886,7 +976,6 @@ strlen(vs->current_segment_final_filename_fmt)) { char * new_url = av_strdup(vs->current_segment_final_filename_fmt); if (!new_url) { - av_free(en); return AVERROR(ENOMEM); } ff_format_set_url(vs->avf, new_url); @@ -895,10 +984,9 @@ if (replace_int_data_in_filename(&filename, vs->avf->url, 's', pos + size) < 1) { av_log(hls, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " - "you can try to remove second_level_segment_size flag\n", + "you can try to remove second_level_segment_size flag\n", vs->avf->url); - av_free(filename); - av_free(en); + av_freep(&filename); return AVERROR(EINVAL); } ff_format_set_url(vs->avf, filename); @@ -906,13 +994,12 @@ if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) { char *filename = NULL; if (replace_int_data_in_filename(&filename, vs->avf->url, - 't', (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) { + 't', (int64_t)round(duration * HLS_MICROSECOND_UNIT)) < 1) { av_log(hls, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " - "you can try to remove second_level_segment_time flag\n", + "you can try to remove second_level_segment_time flag\n", vs->avf->url); - av_free(filename); - av_free(en); + av_freep(&filename); return AVERROR(EINVAL); } ff_format_set_url(vs->avf, filename); @@ -926,14 +1013,14 @@ int ret = 0; if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) { - av_log(hls, AV_LOG_ERROR, - "second_level_segment_duration hls_flag requires strftime to be true\n"); - ret = AVERROR(EINVAL); + av_log(hls, AV_LOG_ERROR, + "second_level_segment_duration hls_flag requires strftime to be true\n"); + ret = AVERROR(EINVAL); } if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) { - av_log(hls, AV_LOG_ERROR, - "second_level_segment_size hls_flag requires strfime to be true\n"); - ret = AVERROR(EINVAL); + av_log(hls, AV_LOG_ERROR, + "second_level_segment_size hls_flag requires strfime to be true\n"); + ret = AVERROR(EINVAL); } if (hls->flags & HLS_SECOND_LEVEL_SEGMENT_INDEX) { av_log(hls, AV_LOG_ERROR, @@ -951,14 +1038,14 @@ int ret = 0; if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_DURATION) && !segment_renaming_ok) { - av_log(hls, AV_LOG_ERROR, - "second_level_segment_duration hls_flag works only with file protocol segment names\n"); - ret = AVERROR(EINVAL); + av_log(hls, AV_LOG_ERROR, + "second_level_segment_duration hls_flag works only with file protocol segment names\n"); + ret = AVERROR(EINVAL); } if ((hls->flags & HLS_SECOND_LEVEL_SEGMENT_SIZE) && !segment_renaming_ok) { - av_log(hls, AV_LOG_ERROR, - "second_level_segment_size hls_flag works only with file protocol segment names\n"); - ret = AVERROR(EINVAL); + av_log(hls, AV_LOG_ERROR, + "second_level_segment_size hls_flag works only with file protocol segment names\n"); + ret = AVERROR(EINVAL); } return ret; @@ -984,7 +1071,7 @@ av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_index flag\n", oc->url); - av_free(filename); + av_freep(&filename); return AVERROR(EINVAL); } ff_format_set_url(oc, filename); @@ -998,7 +1085,7 @@ av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_size flag\n", oc->url); - av_free(filename); + av_freep(&filename); return AVERROR(EINVAL); } ff_format_set_url(oc, filename); @@ -1009,7 +1096,7 @@ av_log(c, AV_LOG_ERROR, "Invalid second level segment filename template '%s', " "you can try to remove second_level_segment_time flag\n", oc->url); - av_free(filename); + av_freep(&filename); return AVERROR(EINVAL); } ff_format_set_url(oc, filename); @@ -1034,6 +1121,7 @@ en->var_stream_idx = vs->var_stream_idx; ret = sls_flags_filename_process(s, hls, vs, en, duration, pos, size); if (ret < 0) { + av_freep(&en); return ret; } @@ -1048,7 +1136,7 @@ } av_strlcpy(en->filename, filename, sizeof(en->filename)); - if(vs->has_subtitle) + if (vs->has_subtitle) av_strlcpy(en->sub_filename, av_basename(vs->vtt_avf->url), sizeof(en->sub_filename)); else en->sub_filename[0] = '\0'; @@ -1060,6 +1148,7 @@ en->keyframe_size = vs->video_keyframe_size; en->next = NULL; en->discont = 0; + en->discont_program_date_time = 0; if (vs->discontinuity) { en->discont = 1; @@ -1067,8 +1156,8 @@ } if (hls->key_info_file || hls->encrypt) { - av_strlcpy(en->key_uri, hls->key_uri, sizeof(en->key_uri)); - av_strlcpy(en->iv_string, hls->iv_string, sizeof(en->iv_string)); + av_strlcpy(en->key_uri, vs->key_uri, sizeof(en->key_uri)); + av_strlcpy(en->iv_string, vs->iv_string, sizeof(en->iv_string)); } if (!vs->segments) @@ -1084,7 +1173,8 @@ if (hls->max_nb_segments && vs->nb_entries >= hls->max_nb_segments) { en = vs->segments; - vs->initial_prog_date_time += en->duration; + if (!en->next->discont_program_date_time && !en->discont_program_date_time) + vs->initial_prog_date_time += en->duration; vs->segments = en->next; if (en && hls->flags & HLS_DELETE_SEGMENTS && #if FF_API_HLS_WRAP @@ -1097,7 +1187,7 @@ if ((ret = hls_delete_old_segments(s, hls, vs)) < 0) return ret; } else - av_free(en); + av_freep(&en); } else vs->nb_entries++; @@ -1118,6 +1208,7 @@ char line[MAX_URL_SIZE]; const char *ptr; const char *end; + double discont_program_date_time = 0; if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ, &s->interrupt_callback, NULL, @@ -1156,9 +1247,9 @@ ptr += strlen("URI=\""); end = av_stristr(ptr, ","); if (end) { - av_strlcpy(hls->key_uri, ptr, end - ptr); + av_strlcpy(vs->key_uri, ptr, end - ptr); } else { - av_strlcpy(hls->key_uri, ptr, sizeof(hls->key_uri)); + av_strlcpy(vs->key_uri, ptr, sizeof(vs->key_uri)); } } @@ -1167,12 +1258,30 @@ ptr += strlen("IV=0x"); end = av_stristr(ptr, ","); if (end) { - av_strlcpy(hls->iv_string, ptr, end - ptr); + av_strlcpy(vs->iv_string, ptr, end - ptr); } else { - av_strlcpy(hls->iv_string, ptr, sizeof(hls->iv_string)); + av_strlcpy(vs->iv_string, ptr, sizeof(vs->iv_string)); } } + } else if (av_strstart(line, "#EXT-X-PROGRAM-DATE-TIME:", &ptr)) { + struct tm program_date_time; + int y,M,d,h,m,s; + double ms; + if (sscanf(ptr, "%d-%d-%dT%d:%d:%d.%lf", &y, &M, &d, &h, &m, &s, &ms) != 7) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + program_date_time.tm_year = y - 1900; + program_date_time.tm_mon = M - 1; + program_date_time.tm_mday = d; + program_date_time.tm_hour = h; + program_date_time.tm_min = m; + program_date_time.tm_sec = s; + program_date_time.tm_isdst = -1; + + discont_program_date_time = mktime(&program_date_time); + discont_program_date_time += (double)(ms / 1000); } else if (av_strstart(line, "#", NULL)) { continue; } else if (line[0]) { @@ -1187,6 +1296,8 @@ new_start_pos = avio_tell(vs->avf->pb); vs->size = new_start_pos - vs->start_pos; ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); + vs->last_segment->discont_program_date_time = discont_program_date_time; + discont_program_date_time += vs->duration; if (ret < 0) goto fail; vs->start_pos = new_start_pos; @@ -1203,10 +1314,10 @@ { HLSSegment *en; - while(p) { + while (p) { en = p; p = p->next; - av_free(en); + av_freep(&en); } } @@ -1225,25 +1336,28 @@ return ret; } -static int get_relative_url(const char *master_url, const char *media_url, - char *rel_url, int rel_url_buf_size) +static const char* get_relative_url(const char *master_url, const char *media_url) { - char *p = NULL; - int base_len = -1; - p = strrchr(master_url, '/') ? strrchr(master_url, '/') :\ - strrchr(master_url, '\\'); + const char *p = strrchr(master_url, '/'); + size_t base_len = 0; + + if (!p) p = strrchr(master_url, '\\'); + if (p) { - base_len = FFABS(p - master_url); + base_len = p - master_url; if (av_strncasecmp(master_url, media_url, base_len)) { av_log(NULL, AV_LOG_WARNING, "Unable to find relative url\n"); - return AVERROR(EINVAL); + return NULL; } + } else { + return media_url; } - av_strlcpy(rel_url, &(media_url[base_len + 1]), rel_url_buf_size); - return 0; + + return media_url + base_len + 1; } -static int64_t get_stream_bit_rate(AVStream *stream) { +static int64_t get_stream_bit_rate(AVStream *stream) +{ AVCPBProperties *props = (AVCPBProperties*)av_stream_get_side_data( stream, AV_PKT_DATA_CPB_PROPERTIES, @@ -1266,8 +1380,11 @@ AVStream *vid_st, *aud_st; AVDictionary *options = NULL; unsigned int i, j; - int m3u8_name_size, ret, bandwidth; - char *m3u8_rel_name = NULL, *ccgroup; + int ret, bandwidth; + const char *m3u8_rel_name = NULL; + const char *vtt_m3u8_rel_name = NULL; + const char *ccgroup; + const char *sgroup = NULL; ClosedCaptionsStream *ccs; const char *proto = avio_find_protocol_name(hls->master_m3u8_url); int is_file_proto = proto && !strcmp(proto, "file"); @@ -1292,7 +1409,7 @@ ret = hlsenc_io_open(s, &hls->m3u8_out, temp_filename, &options); av_dict_free(&options); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Failed to open master play list file '%s'\n", + av_log(s, AV_LOG_ERROR, "Failed to open master play list file '%s'\n", temp_filename); goto fail; } @@ -1316,40 +1433,22 @@ if (vs->has_video || vs->has_subtitle || !vs->agroup) continue; - m3u8_name_size = strlen(vs->m3u8_name) + 1; - m3u8_rel_name = av_malloc(m3u8_name_size); + m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name); if (!m3u8_rel_name) { - ret = AVERROR(ENOMEM); - goto fail; - } - av_strlcpy(m3u8_rel_name, vs->m3u8_name, m3u8_name_size); - ret = get_relative_url(hls->master_m3u8_url, vs->m3u8_name, - m3u8_rel_name, m3u8_name_size); - if (ret < 0) { av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n"); goto fail; } ff_hls_write_audio_rendition(hls->m3u8_out, vs->agroup, m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 1); - - av_freep(&m3u8_rel_name); } /* For variant streams with video add #EXT-X-STREAM-INF tag with attributes*/ for (i = 0; i < hls->nb_varstreams; i++) { vs = &(hls->var_streams[i]); - m3u8_name_size = strlen(vs->m3u8_name) + 1; - m3u8_rel_name = av_malloc(m3u8_name_size); + m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->m3u8_name); if (!m3u8_rel_name) { - ret = AVERROR(ENOMEM); - goto fail; - } - av_strlcpy(m3u8_rel_name, vs->m3u8_name, m3u8_name_size); - ret = get_relative_url(hls->master_m3u8_url, vs->m3u8_name, - m3u8_rel_name, m3u8_name_size); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Unable to find relative URL\n"); + av_log(s, AV_LOG_ERROR, "Unable to find relative URL\n"); goto fail; } @@ -1363,7 +1462,7 @@ } if (!vid_st && !aud_st) { - av_log(NULL, AV_LOG_WARNING, "Media stream not found\n"); + av_log(s, AV_LOG_WARNING, "Media stream not found\n"); continue; } @@ -1404,26 +1503,34 @@ } } if (j == hls->nb_ccstreams) - av_log(NULL, AV_LOG_WARNING, "mapping ccgroup %s not found\n", + av_log(s, AV_LOG_WARNING, "mapping ccgroup %s not found\n", vs->ccgroup); } + if (vid_st && vs->sgroup) { + sgroup = vs->sgroup; + vtt_m3u8_rel_name = get_relative_url(hls->master_m3u8_url, vs->vtt_m3u8_name); + if (!vtt_m3u8_rel_name) { + av_log(s, AV_LOG_WARNING, "Unable to find relative subtitle URL\n"); + break; + } + + ff_hls_write_subtitle_rendition(hls->m3u8_out, sgroup, vtt_m3u8_rel_name, vs->language, i, hls->has_default_key ? vs->is_default : 1); + } + if (!hls->has_default_key || !hls->has_video_m3u8) { ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name, - aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup); + aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup); } else { if (vid_st) { ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name, - aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup); + aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup); } } - - av_freep(&m3u8_rel_name); } fail: - if(ret >=0) + if (ret >=0) hls->master_m3u8_created = 1; - av_freep(&m3u8_rel_name); hlsenc_io_close(s, &hls->m3u8_out, temp_filename); if (use_temp_file) ff_rename(temp_filename, hls->master_m3u8_url, s); @@ -1435,7 +1542,6 @@ { HLSContext *hls = s->priv_data; HLSSegment *en; - AVFormatContext *oc = vs->avf; int target_duration = 0; int ret = 0; char temp_filename[MAX_URL_SIZE]; @@ -1458,6 +1564,10 @@ sequence = 0; } + if (hls->flags & HLS_I_FRAMES_ONLY) { + hls->version = 4; + } + if (hls->flags & HLS_INDEPENDENT_SEGMENTS) { hls->version = 6; } @@ -1471,7 +1581,7 @@ set_http_options(s, &options, hls); snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : "%s", vs->m3u8_name); - if ((ret = hlsenc_io_open(s, (byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? &hls->m3u8_out : &oc->pb, temp_filename, &options)) < 0) { + if ((ret = hlsenc_io_open(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename, &options)) < 0) { if (hls->ignore_io_errors) ret = 0; goto fail; @@ -1483,43 +1593,47 @@ } vs->discontinuity_set = 0; - ff_hls_write_playlist_header((byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, hls->version, hls->allowcache, + ff_hls_write_playlist_header(byterange_mode ? hls->m3u8_out : vs->out, hls->version, hls->allowcache, target_duration, sequence, hls->pl_type, hls->flags & HLS_I_FRAMES_ONLY); - if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && vs->discontinuity_set==0 ){ - avio_printf((byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, "#EXT-X-DISCONTINUITY\n"); + if ((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && vs->discontinuity_set==0) { + avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-DISCONTINUITY\n"); vs->discontinuity_set = 1; } if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) { - avio_printf((byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, "#EXT-X-INDEPENDENT-SEGMENTS\n"); + avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-INDEPENDENT-SEGMENTS\n"); } for (en = vs->segments; en; en = en->next) { if ((hls->encrypt || hls->key_info_file) && (!key_uri || strcmp(en->key_uri, key_uri) || av_strcasecmp(en->iv_string, iv_string))) { - avio_printf((byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri); + avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri); if (*en->iv_string) - avio_printf((byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, ",IV=0x%s", en->iv_string); - avio_printf((byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, "\n"); + avio_printf(byterange_mode ? hls->m3u8_out : vs->out, ",IV=0x%s", en->iv_string); + avio_printf(byterange_mode ? hls->m3u8_out : vs->out, "\n"); key_uri = en->key_uri; iv_string = en->iv_string; } if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) { - ff_hls_write_init_file((byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, (hls->flags & HLS_SINGLE_FILE) ? en->filename : vs->fmp4_init_filename, + ff_hls_write_init_file(byterange_mode ? hls->m3u8_out : vs->out, (hls->flags & HLS_SINGLE_FILE) ? en->filename : vs->fmp4_init_filename, hls->flags & HLS_SINGLE_FILE, vs->init_range_length, 0); } - ret = ff_hls_write_file_entry((byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, en->discont, byterange_mode, + ret = ff_hls_write_file_entry(byterange_mode ? hls->m3u8_out : vs->out, en->discont, byterange_mode, en->duration, hls->flags & HLS_ROUND_DURATIONS, - en->size, en->pos, vs->baseurl, - en->filename, prog_date_time_p, en->keyframe_size, en->keyframe_pos, hls->flags & HLS_I_FRAMES_ONLY); + en->size, en->pos, hls->baseurl, + en->filename, + en->discont_program_date_time ? &en->discont_program_date_time : prog_date_time_p, + en->keyframe_size, en->keyframe_pos, hls->flags & HLS_I_FRAMES_ONLY); + if (en->discont_program_date_time) + en->discont_program_date_time -= en->duration; if (ret < 0) { av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n"); } } if (last && (hls->flags & HLS_OMIT_ENDLIST)==0) - ff_hls_write_end_list((byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb); + ff_hls_write_end_list(byterange_mode ? hls->m3u8_out : vs->out); if (vs->vtt_m3u8_name) { snprintf(temp_vtt_filename, sizeof(temp_vtt_filename), use_temp_file ? "%s.tmp" : "%s", vs->vtt_m3u8_name); @@ -1533,7 +1647,7 @@ for (en = vs->segments; en; en = en->next) { ret = ff_hls_write_file_entry(hls->sub_m3u8_out, 0, byterange_mode, en->duration, 0, en->size, en->pos, - vs->baseurl, en->sub_filename, NULL, 0, 0, 0); + hls->baseurl, en->sub_filename, NULL, 0, 0, 0); if (ret < 0) { av_log(s, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n"); } @@ -1546,7 +1660,10 @@ fail: av_dict_free(&options); - hlsenc_io_close(s, (byterange_mode || hls->segment_type == SEGMENT_TYPE_FMP4) ? &hls->m3u8_out : &oc->pb, temp_filename); + ret = hlsenc_io_close(s, byterange_mode ? &hls->m3u8_out : &vs->out, temp_filename); + if (ret < 0) { + return ret; + } hlsenc_io_close(s, &hls->sub_m3u8_out, vs->vtt_m3u8_name); if (use_temp_file) { ff_rename(temp_filename, vs->m3u8_name, s); @@ -1568,7 +1685,7 @@ AVDictionary *options = NULL; const char *proto = NULL; int use_temp_file = 0; - char *filename, iv_string[KEYSIZE*2 + 1]; + char iv_string[KEYSIZE*2 + 1]; int err = 0; if (c->flags & HLS_SINGLE_FILE) { @@ -1590,26 +1707,22 @@ #else vs->basename, 'd', vs->sequence) < 1) { #endif - av_free(filename); + av_freep(&filename); av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s', you can try to use -strftime 1 with it\n", vs->basename); return AVERROR(EINVAL); } ff_format_set_url(oc, filename); } else { if (c->use_localtime) { - time_t now0; - struct tm *tm, tmpbuf; - int bufsize = strlen(vs->basename) + MAX_URL_SIZE; - char *buf = av_mallocz(bufsize); - if (!buf) - return AVERROR(ENOMEM); - time(&now0); - tm = localtime_r(&now0, &tmpbuf); - ff_format_set_url(oc, buf); - if (!strftime(oc->url, bufsize, vs->basename, tm)) { + int r; + char *expanded = NULL; + + r = strftime_expand(vs->basename, &expanded); + if (r < 0) { av_log(oc, AV_LOG_ERROR, "Could not get segment filename with strftime\n"); - return AVERROR(EINVAL); + return r; } + ff_format_set_url(oc, expanded); err = sls_flag_use_localtime_filename(oc, c, vs); if (err < 0) { @@ -1619,16 +1732,15 @@ if (c->use_localtime_mkdir) { const char *dir; char *fn_copy = av_strdup(oc->url); - if (!fn_copy) { + if (!fn_copy) return AVERROR(ENOMEM); - } dir = av_dirname(fn_copy); if (ff_mkdir_p(dir) == -1 && errno != EEXIST) { av_log(oc, AV_LOG_ERROR, "Could not create directory %s with use_localtime_mkdir\n", dir); - av_free(fn_copy); + av_freep(&fn_copy); return AVERROR(errno); } - av_free(fn_copy); + av_freep(&fn_copy); } } else { char *filename = NULL; @@ -1638,13 +1750,13 @@ #else vs->basename, 'd', vs->sequence) < 1) { #endif - av_free(filename); + av_freep(&filename); av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try to use -strftime 1 with it\n", vs->basename); return AVERROR(EINVAL); } ff_format_set_url(oc, filename); } - if( vs->vtt_basename) { + if (vs->vtt_basename) { char *filename = NULL; if (replace_int_data_in_filename(&filename, #if FF_API_HLS_WRAP @@ -1652,16 +1764,13 @@ #else vs->vtt_basename, 'd', vs->sequence) < 1) { #endif - av_free(filename); + av_freep(&filename); av_log(vtt_oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", vs->vtt_basename); return AVERROR(EINVAL); } ff_format_set_url(vtt_oc, filename); } } - vs->number++; - - set_http_options(s, &options, c); proto = avio_find_protocol_name(oc->url); use_temp_file = proto && !strcmp(proto, "file") && (c->flags & HLS_TEMP_FILE); @@ -1684,40 +1793,62 @@ " ignoring -hls_enc\n"); } - if (!c->encrypt_started || (c->flags & HLS_PERIODIC_REKEY)) { + if (!vs->encrypt_started || (c->flags & HLS_PERIODIC_REKEY)) { if (c->key_info_file) { - if ((err = hls_encryption_start(s)) < 0) + if ((err = hls_encryption_start(s, vs)) < 0) goto fail; } else { - if ((err = do_encrypt(s, vs)) < 0) - goto fail; + if (!c->encrypt_started) { + if ((err = do_encrypt(s, vs)) < 0) + goto fail; + c->encrypt_started = 1; + } + av_strlcpy(vs->key_uri, c->key_uri, sizeof(vs->key_uri)); + av_strlcpy(vs->key_string, c->key_string, sizeof(vs->key_string)); + av_strlcpy(vs->iv_string, c->iv_string, sizeof(vs->iv_string)); } - c->encrypt_started = 1; + vs->encrypt_started = 1; } - if ((err = av_dict_set(&options, "encryption_key", c->key_string, 0)) - < 0) - goto fail; - err = av_strlcpy(iv_string, c->iv_string, sizeof(iv_string)); - if (!err) + err = av_strlcpy(iv_string, vs->iv_string, sizeof(iv_string)); + if (!err) { snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, vs->sequence); - if ((err = av_dict_set(&options, "encryption_iv", iv_string, 0)) < 0) - goto fail; - - filename = av_asprintf("crypto:%s", oc->url); - if (!filename) { - err = AVERROR(ENOMEM); - goto fail; + memset(vs->iv_string, 0, sizeof(vs->iv_string)); + memcpy(vs->iv_string, iv_string, sizeof(iv_string)); } - err = hlsenc_io_open(s, &oc->pb, filename, &options); - av_free(filename); - av_dict_free(&options); - if (err < 0) - return err; - } else if (c->segment_type != SEGMENT_TYPE_FMP4) { - if ((err = hlsenc_io_open(s, &oc->pb, oc->url, &options)) < 0) { - if (c->ignore_io_errors) - err = 0; - goto fail; + } + if (c->segment_type != SEGMENT_TYPE_FMP4) { + if (oc->oformat->priv_class && oc->priv_data) { + av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0); + } + if (c->flags & HLS_SINGLE_FILE) { + if (c->key_info_file || c->encrypt) { + av_dict_set(&options, "encryption_key", vs->key_string, 0); + av_dict_set(&options, "encryption_iv", vs->iv_string, 0); + + /* Write temp file with cryption content */ + av_freep(&vs->basename_tmp); + vs->basename_tmp = av_asprintf("crypto:%s.tmp", oc->url); + + /* append temp file content into single file */ + av_freep(&vs->basename); + vs->basename = av_asprintf("%s", oc->url); + } else { + vs->basename_tmp = vs->basename; + } + set_http_options(s, &options, c); + if (!vs->out_single_file) + if ((err = hlsenc_io_open(s, &vs->out_single_file, vs->basename, &options)) < 0) { + if (c->ignore_io_errors) + err = 0; + goto fail; + } + + if ((err = hlsenc_io_open(s, &vs->out, vs->basename_tmp, &options)) < 0) { + if (c->ignore_io_errors) + err = 0; + goto fail; + } + } } if (vs->vtt_basename) { @@ -1730,19 +1861,6 @@ } av_dict_free(&options); - if (c->segment_type != SEGMENT_TYPE_FMP4) { - /* We only require one PAT/PMT per segment. */ - if (oc->oformat->priv_class && oc->priv_data) { - char period[21]; - - snprintf(period, sizeof(period), "%d", (INT_MAX / 2) - 1); - - av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0); - av_opt_set(oc->priv_data, "sdt_period", period, 0); - av_opt_set(oc->priv_data, "pat_period", period, 0); - } - } - if (vs->vtt_basename) { err = avformat_write_header(vtt_oc,NULL); if (err < 0) @@ -1797,17 +1915,12 @@ char *fn_dup = NULL; int ret = 0; - if (!fn) { - ret = AVERROR(EINVAL); - goto fail; - } + if (!fn) + return AVERROR(EINVAL); fn_dup = av_strdup(fn); - if (!fn_dup) { - ret = AVERROR(ENOMEM); - goto fail; - } - + if (!fn_dup) + return AVERROR(ENOMEM); filename = av_basename(fn); subdir_name = av_dirname(fn_dup); @@ -1837,14 +1950,12 @@ int ret = 0; orig_buf_dup = av_strdup(buf); - if (!orig_buf_dup) { - ret = AVERROR(ENOMEM); - goto fail; - } + if (!orig_buf_dup) + return AVERROR(ENOMEM); if (!av_stristr(buf, "%v")) { *s = orig_buf_dup; - return ret; + return 0; } if (!varname) { @@ -1865,11 +1976,6 @@ /* if %v is present in the file's directory, create sub-directory */ if (av_stristr(dir, "%v") && proto && !strcmp(proto, "file")) { mod_buf_dup = av_strdup(*s); - if (!mod_buf_dup) { - ret = AVERROR(ENOMEM); - goto fail; - } - dir = av_dirname(mod_buf_dup); if (ff_mkdir_p(dir) == -1 && errno != EEXIST) { ret = AVERROR(errno); @@ -1885,7 +1991,7 @@ static int get_nth_codec_stream_index(AVFormatContext *s, enum AVMediaType codec_type, - int stream_id) + int64_t stream_id) { unsigned int stream_index, cnt; if (stream_id < 0 || stream_id > s->nb_streams - 1) @@ -1907,7 +2013,7 @@ VariantStream *vs; int stream_index, i, j; enum AVMediaType codec_type; - int nb_varstreams, nb_streams; + int nb_varstreams = 0, nb_streams; char *p, *q, *saveptr1, *saveptr2, *varstr, *keyval; const char *val; @@ -1924,18 +2030,23 @@ * practical usage) * * agroup: is key to specify audio group. A string can be given as value. + * sgroup: is key to specify subtitle group. A string can be given as value. */ p = av_strdup(hls->var_stream_map); + if (!p) + return AVERROR(ENOMEM); + q = p; - while(av_strtok(q, " \t", &saveptr1)) { + while (av_strtok(q, " \t", &saveptr1)) { q = NULL; - hls->nb_varstreams++; + nb_varstreams++; } av_freep(&p); - hls->var_streams = av_mallocz(sizeof(*hls->var_streams) * hls->nb_varstreams); + hls->var_streams = av_mallocz(sizeof(*hls->var_streams) * nb_varstreams); if (!hls->var_streams) return AVERROR(ENOMEM); + hls->nb_varstreams = nb_varstreams; p = hls->var_stream_map; nb_varstreams = 0; @@ -1951,10 +2062,13 @@ return AVERROR(EINVAL); q = varstr; - while (q < varstr + strlen(varstr)) { + while (1) { if (!av_strncasecmp(q, "a:", 2) || !av_strncasecmp(q, "v:", 2) || !av_strncasecmp(q, "s:", 2)) vs->nb_streams++; + q = strchr(q, ','); + if (!q) + break; q++; } vs->streams = av_mallocz(sizeof(AVStream *) * vs->nb_streams); @@ -1963,11 +2077,11 @@ nb_streams = 0; while (keyval = av_strtok(varstr, ",", &saveptr2)) { + int64_t num; + char *end; varstr = NULL; if (av_strstart(keyval, "language:", &val)) { - vs->language = av_strdup(val); - if (!vs->language) - return AVERROR(ENOMEM); + vs->language = val; continue; } else if (av_strstart(keyval, "default:", &val)) { vs->is_default = (!av_strncasecmp(val, "YES", strlen("YES")) || @@ -1975,19 +2089,16 @@ hls->has_default_key = 1; continue; } else if (av_strstart(keyval, "name:", &val)) { - vs->varname = av_strdup(val); - if (!vs->varname) - return AVERROR(ENOMEM); + vs->varname = val; continue; } else if (av_strstart(keyval, "agroup:", &val)) { - vs->agroup = av_strdup(val); - if (!vs->agroup) - return AVERROR(ENOMEM); + vs->agroup = val; + continue; + } else if (av_strstart(keyval, "sgroup:", &val)) { + vs->sgroup = val; continue; } else if (av_strstart(keyval, "ccgroup:", &val)) { - vs->ccgroup = av_strdup(val); - if (!vs->ccgroup) - return AVERROR(ENOMEM); + vs->ccgroup = val; continue; } else if (av_strstart(keyval, "v:", &val)) { codec_type = AVMEDIA_TYPE_VIDEO; @@ -2001,21 +2112,23 @@ return AVERROR(EINVAL); } - stream_index = -1; - if (av_isdigit(*val)) - stream_index = get_nth_codec_stream_index (s, codec_type, - atoi(val)); + num = strtoll(val, &end, 10); + if (!av_isdigit(*val) || *end != '\0') { + av_log(s, AV_LOG_ERROR, "Invalid stream number: '%s'\n", val); + return AVERROR(EINVAL); + } + stream_index = get_nth_codec_stream_index(s, codec_type, num); if (stream_index >= 0 && nb_streams < vs->nb_streams) { - for(i = 0; nb_streams > 0 && i < nb_streams; i++) { + for (i = 0; nb_streams > 0 && i < nb_streams; i++) { if (vs->streams[i] == s->streams[stream_index]) { av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once inside " "variant definition #%d\n", nb_varstreams - 1); return AVERROR(EINVAL); } } - for(j = 0; nb_varstreams > 1 && j < nb_varstreams - 1; j++) { - for(i = 0; i < hls->var_streams[j].nb_streams; i++) { + for (j = 0; nb_varstreams > 1 && j < nb_varstreams - 1; j++) { + for (i = 0; i < hls->var_streams[j].nb_streams; i++) { if (hls->var_streams[j].streams[i] == s->streams[stream_index]) { av_log(s, AV_LOG_ERROR, "Same elementary stream found more than once " "in two different variant definitions #%d and #%d\n", @@ -2040,23 +2153,27 @@ static int parse_cc_stream_mapstring(AVFormatContext *s) { HLSContext *hls = s->priv_data; - int nb_ccstreams; + int nb_ccstreams = 0; char *p, *q, *ccstr, *keyval; char *saveptr1 = NULL, *saveptr2 = NULL; const char *val; ClosedCaptionsStream *ccs; p = av_strdup(hls->cc_stream_map); + if(!p) + return AVERROR(ENOMEM); + q = p; - while(av_strtok(q, " \t", &saveptr1)) { + while (av_strtok(q, " \t", &saveptr1)) { q = NULL; - hls->nb_ccstreams++; + nb_ccstreams++; } av_freep(&p); - hls->cc_streams = av_mallocz(sizeof(*hls->cc_streams) * hls->nb_ccstreams); + hls->cc_streams = av_mallocz(sizeof(*hls->cc_streams) * nb_ccstreams); if (!hls->cc_streams) return AVERROR(ENOMEM); + hls->nb_ccstreams = nb_ccstreams; p = hls->cc_stream_map; nb_ccstreams = 0; @@ -2072,17 +2189,11 @@ ccstr = NULL; if (av_strstart(keyval, "ccgroup:", &val)) { - ccs->ccgroup = av_strdup(val); - if (!ccs->ccgroup) - return AVERROR(ENOMEM); + ccs->ccgroup = val; } else if (av_strstart(keyval, "instreamid:", &val)) { - ccs->instreamid = av_strdup(val); - if (!ccs->instreamid) - return AVERROR(ENOMEM); + ccs->instreamid = val; } else if (av_strstart(keyval, "language:", &val)) { - ccs->language = av_strdup(val); - if (!ccs->language) - return AVERROR(ENOMEM); + ccs->language = val; } else { av_log(s, AV_LOG_ERROR, "Invalid keyval %s\n", keyval); return AVERROR(EINVAL); @@ -2095,19 +2206,19 @@ } if (av_strstart(ccs->instreamid, "CC", &val)) { - if(atoi(val) < 1 || atoi(val) > 4) { + if (atoi(val) < 1 || atoi(val) > 4) { av_log(s, AV_LOG_ERROR, "Invalid instream ID CC index %d in %s, range 1-4\n", atoi(val), ccs->instreamid); return AVERROR(EINVAL); } } else if (av_strstart(ccs->instreamid, "SERVICE", &val)) { - if(atoi(val) < 1 || atoi(val) > 63) { + if (atoi(val) < 1 || atoi(val) > 63) { av_log(s, AV_LOG_ERROR, "Invalid instream ID SERVICE index %d in %s, range 1-63 \n", atoi(val), ccs->instreamid); return AVERROR(EINVAL); } } else { - av_log(s, AV_LOG_ERROR, "Invalid instream ID %s, supported are CCn or SERIVICEn\n", + av_log(s, AV_LOG_ERROR, "Invalid instream ID %s, supported are CCn or SERVICEn\n", ccs->instreamid); return AVERROR(EINVAL); } @@ -2116,7 +2227,8 @@ return 0; } -static int update_variant_stream_info(AVFormatContext *s) { +static int update_variant_stream_info(AVFormatContext *s) +{ HLSContext *hls = s->priv_data; unsigned int i; int ret = 0; @@ -2131,11 +2243,10 @@ return parse_variant_stream_mapstring(s); } else { //By default, a single variant stream with all the codec streams is created - hls->nb_varstreams = 1; - hls->var_streams = av_mallocz(sizeof(*hls->var_streams) * - hls->nb_varstreams); + hls->var_streams = av_mallocz(sizeof(*hls->var_streams)); if (!hls->var_streams) return AVERROR(ENOMEM); + hls->nb_varstreams = 1; hls->var_streams[0].var_stream_idx = 0; hls->var_streams[0].nb_streams = s->nb_streams; @@ -2145,11 +2256,8 @@ return AVERROR(ENOMEM); //by default, the first available ccgroup is mapped to the variant stream - if (hls->nb_ccstreams) { - hls->var_streams[0].ccgroup = av_strdup(hls->cc_streams[0].ccgroup); - if (!hls->var_streams[0].ccgroup) - return AVERROR(ENOMEM); - } + if (hls->nb_ccstreams) + hls->var_streams[0].ccgroup = hls->cc_streams[0].ccgroup; for (i = 0; i < s->nb_streams; i++) hls->var_streams[0].streams[i] = s->streams[i]; @@ -2157,18 +2265,16 @@ return 0; } -static int update_master_pl_info(AVFormatContext *s) { +static int update_master_pl_info(AVFormatContext *s) +{ HLSContext *hls = s->priv_data; const char *dir; char *fn1= NULL, *fn2 = NULL; int ret = 0; fn1 = av_strdup(s->url); - if (!fn1) { - ret = AVERROR(ENOMEM); - goto fail; - } - + if (!fn1) + return AVERROR(ENOMEM); dir = av_dirname(fn1); /** @@ -2237,6 +2343,10 @@ continue; } avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den); + if (outer_st->codecpar->codec_id == AV_CODEC_ID_HEVC && + outer_st->codecpar->codec_tag != MKTAG('h','v','c','1')) { + av_log(s, AV_LOG_WARNING, "Stream HEVC is not hvc1, you should use tag:v hvc1 to set it.\n"); + } write_codec_attr(outer_st, vs); } @@ -2256,6 +2366,55 @@ return ret; } +static int hls_init_file_resend(AVFormatContext *s, VariantStream *vs) +{ + HLSContext *hls = s->priv_data; + AVDictionary *options = NULL; + int ret = 0; + + set_http_options(s, &options, hls); + ret = hlsenc_io_open(s, &vs->out, vs->base_output_dirname, &options); + av_dict_free(&options); + if (ret < 0) + return ret; + avio_write(vs->out, vs->init_buffer, vs->init_range_length); + hlsenc_io_close(s, &vs->out, hls->fmp4_init_filename); + + return ret; +} + +static int64_t append_single_file(AVFormatContext *s, VariantStream *vs) +{ + int ret = 0; + int64_t read_byte = 0; + int64_t total_size = 0; + char *filename = NULL; + char buf[BUFSIZE]; + AVFormatContext *oc = vs->avf; + + hlsenc_io_close(s, &vs->out, vs->basename_tmp); + filename = av_asprintf("%s.tmp", oc->url); + ret = s->io_open(s, &vs->out, filename, AVIO_FLAG_READ, NULL); + if (ret < 0) { + av_free(filename); + return ret; + } + + 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) { + total_size += read_byte; + ret = total_size; + } + } while (read_byte > 0); + + hlsenc_io_close(s, &vs->out, filename); + av_free(filename); + + return ret; +} static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) { HLSContext *hls = s->priv_data; @@ -2268,16 +2427,14 @@ int range_length = 0; const char *proto = NULL; int use_temp_file = 0; - uint8_t *buffer = NULL; VariantStream *vs = NULL; - AVDictionary *options = NULL; char *old_filename = NULL; for (i = 0; i < hls->nb_varstreams; i++) { vs = &hls->var_streams[i]; for (j = 0; j < vs->nb_streams; j++) { if (vs->streams[j] == st) { - if( st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE ) { + if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { oc = vs->vtt_avf; stream_index = 0; } else { @@ -2301,17 +2458,23 @@ if (vs->sequence - vs->nb_entries > hls->start_sequence && hls->init_time > 0) { /* reset end_pts, hls->recording_time at end of the init hls list */ - int init_list_dur = hls->init_time * vs->nb_entries * AV_TIME_BASE; - int after_init_list_dur = (vs->sequence - hls->start_sequence - vs->nb_entries ) * (hls->time * AV_TIME_BASE); - hls->recording_time = hls->time * AV_TIME_BASE; + int64_t init_list_dur = hls->init_time * vs->nb_entries; + int64_t after_init_list_dur = (vs->sequence - hls->start_sequence - vs->nb_entries) * hls->time; + hls->recording_time = hls->time; end_pts = init_list_dur + after_init_list_dur ; } if (vs->start_pts == AV_NOPTS_VALUE) { vs->start_pts = pkt->pts; + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) + vs->start_pts_from_audio = 1; + } + if (vs->start_pts_from_audio && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && vs->start_pts > pkt->pts) { + vs->start_pts = pkt->pts; + vs->start_pts_from_audio = 0; } - if (vs->has_video) { + if (vs->has_video) { can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ((pkt->flags & AV_PKT_FLAG_KEY) || (hls->flags & HLS_SPLIT_BY_TIME)); is_ref_pkt = (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && (pkt->stream_index == vs->reference_stream_index); @@ -2335,44 +2498,34 @@ vs->duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den; } } - } + can_split = can_split && (pkt->pts - vs->end_pts > 0); if (vs->packets_written && can_split && av_compare_ts(pkt->pts - vs->start_pts, st->time_base, end_pts, AV_TIME_BASE_Q) >= 0) { int64_t new_start_pos; int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); - av_write_frame(vs->avf, NULL); /* Flush any buffered data */ - - new_start_pos = avio_tell(vs->avf->pb); - - if (hls->segment_type != SEGMENT_TYPE_FMP4) { - avio_flush(oc->pb); - vs->size = new_start_pos - vs->start_pos; - } else { - vs->size = new_start_pos; - } - + av_write_frame(oc, NULL); /* Flush any buffered data */ + new_start_pos = avio_tell(oc->pb); + vs->size = new_start_pos - vs->start_pos; + avio_flush(oc->pb); if (hls->segment_type == SEGMENT_TYPE_FMP4) { if (!vs->init_range_length) { - avio_flush(oc->pb); - range_length = avio_close_dyn_buf(oc->pb, &buffer); - avio_write(vs->out, buffer, range_length); - av_free(buffer); + range_length = avio_close_dyn_buf(oc->pb, &vs->init_buffer); + if (range_length <= 0) + return AVERROR(EINVAL); + avio_write(vs->out, vs->init_buffer, range_length); + if (!hls->resend_init_file) + av_freep(&vs->init_buffer); vs->init_range_length = range_length; avio_open_dyn_buf(&oc->pb); vs->packets_written = 0; vs->start_pos = range_length; if (!byterange_mode) { - ff_format_io_close(s, &vs->out); hlsenc_io_close(s, &vs->out, vs->base_output_dirname); } } - } else { - if (!byterange_mode) { - hlsenc_io_close(s, &oc->pb, oc->url); - } } if (!byterange_mode) { if (vs->vtt_avf) { @@ -2380,91 +2533,136 @@ } } - if (oc->url[0]) { - proto = avio_find_protocol_name(oc->url); - use_temp_file = proto && !strcmp(proto, "file") && (hls->flags & HLS_TEMP_FILE); - } - - // look to rename the asset name - if (use_temp_file) { - if (!(hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size <= 0)) - if ((vs->avf->oformat->priv_class && vs->avf->priv_data) && hls->segment_type != SEGMENT_TYPE_FMP4) - av_opt_set(vs->avf->priv_data, "mpegts_flags", "resend_headers", 0); - } + if (hls->flags & HLS_SINGLE_FILE) { + ret = flush_dynbuf(vs, &range_length); + av_freep(&vs->temp_buffer); + if (ret < 0) { + return ret; + } + vs->size = range_length; + if (hls->key_info_file || hls->encrypt) + vs->size = append_single_file(s, vs); + } else { + if (oc->url[0]) { + proto = avio_find_protocol_name(oc->url); + use_temp_file = proto && !strcmp(proto, "file") + && (hls->flags & HLS_TEMP_FILE); + } - if (hls->segment_type == SEGMENT_TYPE_FMP4) { - if (hls->flags & HLS_SINGLE_FILE) { - ret = flush_dynbuf(vs, &range_length); - if (ret < 0) { - return ret; + if ((hls->max_seg_size > 0 && (vs->size + vs->start_pos >= hls->max_seg_size)) || !byterange_mode) { + AVDictionary *options = NULL; + char *filename = NULL; + if (hls->key_info_file || hls->encrypt) { + av_dict_set(&options, "encryption_key", vs->key_string, 0); + av_dict_set(&options, "encryption_iv", vs->iv_string, 0); + filename = av_asprintf("crypto:%s", oc->url); + } else { + filename = av_asprintf("%s", oc->url); } - vs->size = range_length; - } else { + if (!filename) { + av_dict_free(&options); + return AVERROR(ENOMEM); + } + + // look to rename the asset name + if (use_temp_file) + av_dict_set(&options, "mpegts_flags", "resend_headers", 0); + set_http_options(s, &options, hls); - ret = hlsenc_io_open(s, &vs->out, vs->avf->url, &options); + + ret = hlsenc_io_open(s, &vs->out, filename, &options); if (ret < 0) { av_log(s, hls->ignore_io_errors ? AV_LOG_WARNING : AV_LOG_ERROR, - "Failed to open file '%s'\n", vs->avf->url); + "Failed to open file '%s'\n", filename); + av_freep(&filename); + av_dict_free(&options); return hls->ignore_io_errors ? 0 : ret; } - write_styp(vs->out); + if (hls->segment_type == SEGMENT_TYPE_FMP4) { + write_styp(vs->out); + } ret = flush_dynbuf(vs, &range_length); if (ret < 0) { + av_freep(&filename); + av_dict_free(&options); return ret; } - ff_format_io_close(s, &vs->out); + ret = hlsenc_io_close(s, &vs->out, filename); + if (ret < 0) { + av_log(s, AV_LOG_WARNING, "upload segment failed," + " will retry with a new http session.\n"); + ff_format_io_close(s, &vs->out); + ret = hlsenc_io_open(s, &vs->out, filename, &options); + reflush_dynbuf(vs, &range_length); + ret = hlsenc_io_close(s, &vs->out, filename); + } + av_dict_free(&options); + av_freep(&vs->temp_buffer); + av_freep(&filename); } - } - if (use_temp_file && !(hls->flags & HLS_SINGLE_FILE)) { - hls_rename_temp_file(s, oc); + if (use_temp_file) + hls_rename_temp_file(s, oc); } - old_filename = av_strdup(vs->avf->url); + old_filename = av_strdup(oc->url); if (!old_filename) { return AVERROR(ENOMEM); } if (vs->start_pos || hls->segment_type != SEGMENT_TYPE_FMP4) { - ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); + double cur_duration = (double)(pkt->pts - vs->end_pts) * st->time_base.num / st->time_base.den; + ret = hls_append_segment(s, hls, vs, cur_duration, vs->start_pos, vs->size); vs->end_pts = pkt->pts; vs->duration = 0; if (ret < 0) { - av_free(old_filename); + av_freep(&old_filename); return ret; } } - if (hls->segment_type != SEGMENT_TYPE_FMP4) { - vs->start_pos = new_start_pos; - } else { - vs->start_pos += vs->size; - } // if we're building a VOD playlist, skip writing the manifest multiple times, and just wait until the end if (hls->pl_type != PLAYLIST_TYPE_VOD) { if ((ret = hls_window(s, 0, vs)) < 0) { + av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n"); + ff_format_io_close(s, &vs->out); + if ((ret = hls_window(s, 0, vs)) < 0) { + av_freep(&old_filename); + return ret; + } + } + } + + if (hls->resend_init_file && hls->segment_type == SEGMENT_TYPE_FMP4) { + ret = hls_init_file_resend(s, vs); + if (ret < 0) { + av_freep(&old_filename); return ret; } } if (hls->flags & HLS_SINGLE_FILE) { - vs->number++; + vs->start_pos += vs->size; + if (hls->key_info_file || hls->encrypt) + ret = hls_start(s, vs); } else if (hls->max_seg_size > 0) { - if (vs->start_pos >= hls->max_seg_size) { + if (vs->size + vs->start_pos >= hls->max_seg_size) { vs->sequence++; sls_flag_file_rename(hls, vs, old_filename); ret = hls_start(s, vs); vs->start_pos = 0; /* When split segment by byte, the duration is short than hls_time, * so it is not enough one segment duration as hls_time, */ - vs->number--; + } else { + vs->start_pos = new_start_pos; } - vs->number++; } else { + vs->start_pos = new_start_pos; sls_flag_file_rename(hls, vs, old_filename); ret = hls_start(s, vs); } - av_free(old_filename); + vs->number++; + av_freep(&old_filename); if (ret < 0) { return ret; @@ -2474,14 +2672,14 @@ vs->packets_written++; if (oc->pb) { + int64_t keyframe_pre_pos = avio_tell(oc->pb); ret = ff_write_chained(oc, stream_index, pkt, s, 0); - if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && (pkt->flags & AV_PKT_FLAG_KEY)) { - vs->video_keyframe_size = avio_tell(oc->pb) - vs->video_lastpos; - vs->video_keyframe_pos = vs->start_pos; - } else { - vs->video_lastpos = avio_tell(oc->pb); + if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && + (pkt->flags & AV_PKT_FLAG_KEY) && !keyframe_pre_pos) { + av_write_frame(oc, NULL); /* Flush any buffered data */ + vs->video_keyframe_size = avio_tell(oc->pb) - keyframe_pre_pos; } - + vs->video_keyframe_pos = vs->start_pos; if (hls->ignore_io_errors) ret = 0; } @@ -2489,34 +2687,37 @@ return ret; } -static void hls_free_variant_streams(struct HLSContext *hls) +static void hls_deinit(AVFormatContext *s) { + HLSContext *hls = s->priv_data; int i = 0; - AVFormatContext *vtt_oc = NULL; VariantStream *vs = NULL; for (i = 0; i < hls->nb_varstreams; i++) { vs = &hls->var_streams[i]; - vtt_oc = vs->vtt_avf; av_freep(&vs->basename); av_freep(&vs->base_output_dirname); av_freep(&vs->fmp4_init_filename); - if (vtt_oc) { - av_freep(&vs->vtt_basename); - av_freep(&vs->vtt_m3u8_name); - } + av_freep(&vs->vtt_basename); + av_freep(&vs->vtt_m3u8_name); + avformat_free_context(vs->vtt_avf); + avformat_free_context(vs->avf); + if (hls->resend_init_file) + av_freep(&vs->init_buffer); hls_free_segments(vs->segments); hls_free_segments(vs->old_segments); av_freep(&vs->m3u8_name); av_freep(&vs->streams); - av_freep(&vs->agroup); - av_freep(&vs->language); - av_freep(&vs->ccgroup); - av_freep(&vs->baseurl); - av_freep(&vs->varname); } + + ff_format_io_close(s, &hls->m3u8_out); + ff_format_io_close(s, &hls->sub_m3u8_out); + av_freep(&hls->key_basename); + av_freep(&hls->var_streams); + av_freep(&hls->cc_streams); + av_freep(&hls->master_m3u8_url); } static int hls_write_trailer(struct AVFormatContext *s) @@ -2530,29 +2731,41 @@ int i; int ret = 0; VariantStream *vs = NULL; + AVDictionary *options = NULL; + int range_length, byterange_mode; for (i = 0; i < hls->nb_varstreams; i++) { + char *filename = NULL; vs = &hls->var_streams[i]; - oc = vs->avf; vtt_oc = vs->vtt_avf; - old_filename = av_strdup(vs->avf->url); + old_filename = av_strdup(oc->url); use_temp_file = 0; if (!old_filename) { return AVERROR(ENOMEM); } - if ( hls->segment_type == SEGMENT_TYPE_FMP4) { + if (hls->key_info_file || hls->encrypt) { + av_dict_set(&options, "encryption_key", vs->key_string, 0); + av_dict_set(&options, "encryption_iv", vs->iv_string, 0); + filename = av_asprintf("crypto:%s", oc->url); + } else { + filename = av_asprintf("%s", oc->url); + } + if (!filename) { + av_freep(&old_filename); + return AVERROR(ENOMEM); + } + + if (hls->segment_type == SEGMENT_TYPE_FMP4) { int range_length = 0; if (!vs->init_range_length) { uint8_t *buffer = NULL; - int range_length, byterange_mode; - av_write_frame(vs->avf, NULL); /* Flush any buffered data */ - avio_flush(oc->pb); + av_write_frame(oc, NULL); /* Flush any buffered data */ range_length = avio_close_dyn_buf(oc->pb, &buffer); avio_write(vs->out, buffer, range_length); - av_free(buffer); + av_freep(&buffer); vs->init_range_length = range_length; avio_open_dyn_buf(&oc->pb); vs->packets_written = 0; @@ -2563,51 +2776,66 @@ hlsenc_io_close(s, &vs->out, vs->base_output_dirname); } } - if (!(hls->flags & HLS_SINGLE_FILE)) { - ret = hlsenc_io_open(s, &vs->out, vs->avf->url, NULL); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", vs->avf->url); - goto failed; - } - write_styp(vs->out); - } - ret = flush_dynbuf(vs, &range_length); + } + if (!(hls->flags & HLS_SINGLE_FILE)) { + set_http_options(s, &options, hls); + ret = hlsenc_io_open(s, &vs->out, filename, &options); if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url); goto failed; } - vs->size = range_length; - ff_format_io_close(s, &vs->out); + if (hls->segment_type == SEGMENT_TYPE_FMP4) + write_styp(vs->out); } + ret = flush_dynbuf(vs, &range_length); + if (ret < 0) + goto failed; + vs->size = range_length; + ret = hlsenc_io_close(s, &vs->out, filename); + if (ret < 0) { + av_log(s, AV_LOG_WARNING, "upload segment failed, will retry with a new http session.\n"); + ff_format_io_close(s, &vs->out); + ret = hlsenc_io_open(s, &vs->out, filename, &options); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", oc->url); + goto failed; + } + reflush_dynbuf(vs, &range_length); + ret = hlsenc_io_close(s, &vs->out, filename); + if (ret < 0) + av_log(s, AV_LOG_WARNING, "Failed to upload file '%s' at the end.\n", oc->url); + } + if (hls->flags & HLS_SINGLE_FILE) { + if (hls->key_info_file || hls->encrypt) { + vs->size = append_single_file(s, vs); + } + hlsenc_io_close(s, &vs->out_single_file, vs->basename); + } failed: + av_freep(&vs->temp_buffer); + av_dict_free(&options); + av_freep(&filename); av_write_trailer(oc); - if (oc->url[0]) { proto = avio_find_protocol_name(oc->url); use_temp_file = proto && !strcmp(proto, "file") && (hls->flags & HLS_TEMP_FILE); } - if (oc->pb) { - if (hls->segment_type != SEGMENT_TYPE_FMP4) { - vs->size = avio_tell(vs->avf->pb) - vs->start_pos; - hlsenc_io_close(s, &vs->avf->pb, vs->avf->url); - } - - // rename that segment from .tmp to the real one - if (use_temp_file && !(hls->flags & HLS_SINGLE_FILE)) { - hls_rename_temp_file(s, oc); - av_free(old_filename); - old_filename = av_strdup(vs->avf->url); + // rename that segment from .tmp to the real one + if (use_temp_file && !(hls->flags & HLS_SINGLE_FILE)) { + hls_rename_temp_file(s, oc); + av_freep(&old_filename); + old_filename = av_strdup(oc->url); - if (!old_filename) { - return AVERROR(ENOMEM); - } + if (!old_filename) { + return AVERROR(ENOMEM); } - - /* after av_write_trailer, then duration + 1 duration per packet */ - hls_append_segment(s, hls, vs, vs->duration + vs->dpp, vs->start_pos, vs->size); } + /* after av_write_trailer, then duration + 1 duration per packet */ + hls_append_segment(s, hls, vs, vs->duration + vs->dpp, vs->start_pos, vs->size); + sls_flag_file_rename(hls, vs, old_filename); if (vtt_oc) { @@ -2615,30 +2843,18 @@ av_write_trailer(vtt_oc); vs->size = avio_tell(vs->vtt_avf->pb) - vs->start_pos; ff_format_io_close(s, &vtt_oc->pb); - avformat_free_context(vtt_oc); } - hls_window(s, 1, vs); - avformat_free_context(oc); + ret = hls_window(s, 1, vs); + if (ret < 0) { + av_log(s, AV_LOG_WARNING, "upload playlist failed, will retry with a new http session.\n"); + ff_format_io_close(s, &vs->out); + hls_window(s, 1, vs); + } + ffio_free_dyn_buf(&oc->pb); - vs->avf = NULL; av_free(old_filename); } - hls_free_variant_streams(hls); - - for (i = 0; i < hls->nb_ccstreams; i++) { - ClosedCaptionsStream *ccs = &hls->cc_streams[i]; - av_freep(&ccs->ccgroup); - av_freep(&ccs->instreamid); - av_freep(&ccs->language); - } - - ff_format_io_close(s, &hls->m3u8_out); - ff_format_io_close(s, &hls->sub_m3u8_out); - av_freep(&hls->key_basename); - av_freep(&hls->var_streams); - av_freep(&hls->cc_streams); - av_freep(&hls->master_m3u8_url); return 0; } @@ -2649,14 +2865,21 @@ int i = 0; int j = 0; HLSContext *hls = s->priv_data; - const char *pattern = "%d.ts"; + const char *pattern; VariantStream *vs = NULL; - int basename_size = 0; - const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s); - const char *vtt_pattern = "%d.vtt"; + const char *vtt_pattern = hls->flags & HLS_SINGLE_FILE ? ".vtt" : "%d.vtt"; char *p = NULL; - int vtt_basename_size = 0; + int http_base_proto = ff_is_http_proto(s->url); int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1; + double initial_program_date_time = av_gettime() / 1000000.0; + + if (hls->use_localtime) { + pattern = get_default_pattern_localtime_fmt(s); + } else { + pattern = hls->segment_type == SEGMENT_TYPE_FMP4 ? "%d.m4s" : "%d.ts"; + if (hls->flags & HLS_SINGLE_FILE) + pattern += 2; + } hls->has_default_key = 0; hls->has_video_m3u8 = 0; @@ -2664,35 +2887,33 @@ if (ret < 0) { av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n", ret); - goto fail; + return ret; } - //TODO: Updates needed to encryption functionality with periodic re-key when more than one variant streams are present - if (hls->nb_varstreams > 1 && hls->flags & HLS_PERIODIC_REKEY) { - ret = AVERROR(EINVAL); - av_log(s, AV_LOG_ERROR, "Periodic re-key not supported when more than one variant streams are present\n"); - goto fail; + + if (!hls->method && http_base_proto) { + av_log(hls, AV_LOG_WARNING, "No HTTP method set, hls muxer defaulting to method PUT.\n"); } ret = validate_name(hls->nb_varstreams, s->url); if (ret < 0) - goto fail; + return ret; if (hls->segment_filename) { ret = validate_name(hls->nb_varstreams, hls->segment_filename); if (ret < 0) - goto fail; + return ret; } if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { ret = validate_name(hls->nb_varstreams, hls->fmp4_init_filename); if (ret < 0) - goto fail; + return ret; } if (hls->subtitle_filename) { ret = validate_name(hls->nb_varstreams, hls->subtitle_filename); if (ret < 0) - goto fail; + return ret; } if (hls->master_pl_name) { @@ -2700,23 +2921,23 @@ if (ret < 0) { av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n", ret); - goto fail; + return ret; } } - if (hls->segment_type == SEGMENT_TYPE_FMP4) { - pattern = "%d.m4s"; - } if ((hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) || + (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH) || (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME)) { - time_t t = time(NULL); // we will need it in either case - if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) { + time_t t = time(NULL); + if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH) { + hls->start_sequence = av_gettime(); + } else if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) { hls->start_sequence = (int64_t)t; } else if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME) { char b[15]; struct tm *p, tmbuf; if (!(p = localtime_r(&t, &tmbuf))) - return AVERROR(ENOMEM); + return AVERROR(errno); if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p)) return AVERROR(ENOMEM); hls->start_sequence = strtoll(b, NULL, 10); @@ -2724,39 +2945,28 @@ av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence); } - hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE; + hls->recording_time = hls->init_time ? hls->init_time : hls->time; + + if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) { + // Independent segments cannot be guaranteed when splitting by time + hls->flags &= ~HLS_INDEPENDENT_SEGMENTS; + av_log(s, AV_LOG_WARNING, + "'split_by_time' and 'independent_segments' cannot be " + "enabled together. Disabling 'independent_segments' flag\n"); + } + for (i = 0; i < hls->nb_varstreams; i++) { vs = &hls->var_streams[i]; ret = format_name(s->url, &vs->m3u8_name, i, vs->varname); if (ret < 0) - goto fail; + return ret; - vs->sequence = hls->start_sequence; - vs->start_pts = AV_NOPTS_VALUE; - vs->end_pts = AV_NOPTS_VALUE; + vs->sequence = hls->start_sequence; + vs->start_pts = AV_NOPTS_VALUE; + vs->end_pts = AV_NOPTS_VALUE; vs->current_segment_final_filename_fmt[0] = '\0'; - - if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) { - // Independent segments cannot be guaranteed when splitting by time - hls->flags &= ~HLS_INDEPENDENT_SEGMENTS; - av_log(s, AV_LOG_WARNING, - "'split_by_time' and 'independent_segments' cannot be enabled together. " - "Disabling 'independent_segments' flag\n"); - } - - if (hls->flags & HLS_PROGRAM_DATE_TIME) { - time_t now0; - time(&now0); - vs->initial_prog_date_time = now0; - } - if (hls->format_options_str) { - ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", hls->format_options_str); - goto fail; - } - } + vs->initial_prog_date_time = initial_program_date_time; for (j = 0; j < vs->nb_streams; j++) { vs->has_video += vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO; @@ -2775,55 +2985,24 @@ } else { vs->oformat = av_guess_format("mpegts", NULL, NULL); } + if (!vs->oformat) + return AVERROR_MUXER_NOT_FOUND; - if (!vs->oformat) { - ret = AVERROR_MUXER_NOT_FOUND; - goto fail; - } - - if (vs->has_subtitle) { - vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL); - if (!vs->oformat) { - ret = AVERROR_MUXER_NOT_FOUND; - goto fail; - } - } if (hls->segment_filename) { ret = format_name(hls->segment_filename, &vs->basename, i, vs->varname); if (ret < 0) - goto fail; - basename_size = strlen(vs->basename) + 1; + return ret; } else { - if (hls->flags & HLS_SINGLE_FILE) { - if (hls->segment_type == SEGMENT_TYPE_FMP4) { - pattern = ".m4s"; - } else { - pattern = ".ts"; - } - } - - if (hls->use_localtime) { - basename_size = strlen(vs->m3u8_name) + strlen(pattern_localtime_fmt) + 1; - } else { - basename_size = strlen(vs->m3u8_name) + strlen(pattern) + 1; - } - - vs->basename = av_malloc(basename_size); - if (!vs->basename) { - ret = AVERROR(ENOMEM); - goto fail; - } + p = strrchr(vs->m3u8_name, '.'); + if (p) + *p = '\0'; - av_strlcpy(vs->basename, vs->m3u8_name, basename_size); + vs->basename = av_asprintf("%s%s", vs->m3u8_name, pattern); + if (!vs->basename) + return AVERROR(ENOMEM); - p = strrchr(vs->basename, '.'); if (p) - *p = '\0'; - if (hls->use_localtime) { - av_strlcat(vs->basename, pattern_localtime_fmt, basename_size); - } else { - av_strlcat(vs->basename, pattern, basename_size); - } + *p = '.'; } if (hls->segment_type == SEGMENT_TYPE_FMP4) { @@ -2831,106 +3010,86 @@ fmp4_init_filename_len += strlen(POSTFIX_PATTERN); if (hls->flags & HLS_SINGLE_FILE) { vs->fmp4_init_filename = av_strdup(vs->basename); - if (!vs->fmp4_init_filename) { - ret = AVERROR(ENOMEM); - goto fail; - } + if (!vs->fmp4_init_filename) + return AVERROR(ENOMEM); } else { vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len); - if (!vs->fmp4_init_filename ) { - ret = AVERROR(ENOMEM); - goto fail; - } + if (!vs->fmp4_init_filename) + return AVERROR(ENOMEM); av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename, fmp4_init_filename_len); if (hls->nb_varstreams > 1) { if (av_stristr(vs->fmp4_init_filename, "%v")) { av_freep(&vs->fmp4_init_filename); - format_name(hls->fmp4_init_filename, &vs->fmp4_init_filename, i, vs->varname); + ret = format_name(hls->fmp4_init_filename, + &vs->fmp4_init_filename, i, vs->varname); } else { ret = append_postfix(vs->fmp4_init_filename, fmp4_init_filename_len, i); } if (ret < 0) - goto fail; + return ret; } - fmp4_init_filename_len = strlen(vs->m3u8_name) + - strlen(vs->fmp4_init_filename) + 1; + if (hls->use_localtime) { + int r; + char *expanded = NULL; - vs->base_output_dirname = av_malloc(fmp4_init_filename_len); - if (!vs->base_output_dirname) { - ret = AVERROR(ENOMEM); - goto fail; + r = strftime_expand(vs->fmp4_init_filename, &expanded); + if (r < 0) { + av_log(s, AV_LOG_ERROR, "Could not get segment filename with strftime\n"); + return r; + } + av_free(vs->fmp4_init_filename); + vs->fmp4_init_filename = expanded; } - av_strlcpy(vs->base_output_dirname, vs->m3u8_name, - fmp4_init_filename_len); - p = strrchr(vs->base_output_dirname, '/'); + p = strrchr(vs->m3u8_name, '/'); if (p) { - *(p + 1) = '\0'; - av_strlcat(vs->base_output_dirname, vs->fmp4_init_filename, - fmp4_init_filename_len); + char tmp = *(++p); + *p = '\0'; + vs->base_output_dirname = av_asprintf("%s%s", vs->m3u8_name, + vs->fmp4_init_filename); + *p = tmp; } else { - av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename, - fmp4_init_filename_len); + vs->base_output_dirname = av_strdup(vs->fmp4_init_filename); } + if (!vs->base_output_dirname) + return AVERROR(ENOMEM); } } - if (!hls->use_localtime) { - ret = sls_flag_check_duration_size_index(hls); - if (ret < 0) { - goto fail; - } - } else { - ret = sls_flag_check_duration_size(hls, vs); - if (ret < 0) { - goto fail; - } - } - if (vs->has_subtitle) { + ret = hls->use_localtime ? sls_flag_check_duration_size(hls, vs) : sls_flag_check_duration_size_index(hls); + if (ret < 0) + return ret; - if (hls->flags & HLS_SINGLE_FILE) - vtt_pattern = ".vtt"; - vtt_basename_size = strlen(vs->m3u8_name) + strlen(vtt_pattern) + 1; + if (vs->has_subtitle) { + vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL); + if (!vs->vtt_oformat) + return AVERROR_MUXER_NOT_FOUND; - vs->vtt_basename = av_malloc(vtt_basename_size); - if (!vs->vtt_basename) { - ret = AVERROR(ENOMEM); - goto fail; - } - vs->vtt_m3u8_name = av_malloc(vtt_basename_size); - if (!vs->vtt_m3u8_name ) { - ret = AVERROR(ENOMEM); - goto fail; - } - av_strlcpy(vs->vtt_basename, vs->m3u8_name, vtt_basename_size); - p = strrchr(vs->vtt_basename, '.'); + p = strrchr(vs->m3u8_name, '.'); if (p) *p = '\0'; - if ( hls->subtitle_filename ) { - av_freep(&vs->vtt_m3u8_name); + vs->vtt_basename = av_asprintf("%s%s", vs->m3u8_name, vtt_pattern); + if (!vs->vtt_basename) + return AVERROR(ENOMEM); + + if (hls->subtitle_filename) { ret = format_name(hls->subtitle_filename, &vs->vtt_m3u8_name, i, vs->varname); if (ret < 0) - goto fail; + return ret; } else { - strcpy(vs->vtt_m3u8_name, vs->vtt_basename); - av_strlcat(vs->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size); - } - av_strlcat(vs->vtt_basename, vtt_pattern, vtt_basename_size); - } - - if (hls->baseurl) { - vs->baseurl = av_strdup(hls->baseurl); - if (!vs->baseurl) { - ret = AVERROR(ENOMEM); - goto fail; + vs->vtt_m3u8_name = av_asprintf("%s_vtt.m3u8", vs->m3u8_name); + if (!vs->vtt_m3u8_name) + return AVERROR(ENOMEM); } + if (p) + *p = '.'; } if ((ret = hls_mux_init(s, vs)) < 0) - goto fail; + return ret; if (hls->flags & HLS_APPEND_LIST) { parse_playlist(s, vs->m3u8_name, vs); @@ -2939,44 +3098,13 @@ av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time," " hls_init_time value will have no effect\n"); hls->init_time = 0; - hls->recording_time = hls->time * AV_TIME_BASE; + hls->recording_time = hls->time; } } if ((ret = hls_start(s, vs)) < 0) - goto fail; - } - -fail: - if (ret < 0) { - av_freep(&hls->key_basename); - for (i = 0; i < hls->nb_varstreams && hls->var_streams; i++) { - vs = &hls->var_streams[i]; - av_freep(&vs->basename); - av_freep(&vs->vtt_basename); - av_freep(&vs->fmp4_init_filename); - av_freep(&vs->m3u8_name); - av_freep(&vs->vtt_m3u8_name); - av_freep(&vs->streams); - av_freep(&vs->language); - av_freep(&vs->agroup); - av_freep(&vs->ccgroup); - av_freep(&vs->baseurl); - av_freep(&vs->varname); - if (vs->avf) - avformat_free_context(vs->avf); - if (vs->vtt_avf) - avformat_free_context(vs->vtt_avf); - } - for (i = 0; i < hls->nb_ccstreams; i++) { - ClosedCaptionsStream *ccs = &hls->cc_streams[i]; - av_freep(&ccs->ccgroup); - av_freep(&ccs->instreamid); - av_freep(&ccs->language); - } - av_freep(&hls->var_streams); - av_freep(&hls->cc_streams); - av_freep(&hls->master_m3u8_url); + return ret; + vs->number++; } return ret; @@ -2986,11 +3114,11 @@ #define E AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { {"start_number", "set first number in the sequence", OFFSET(start_sequence),AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E}, - {"hls_time", "set segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E}, - {"hls_init_time", "set segment length in seconds at init list", OFFSET(init_time), AV_OPT_TYPE_FLOAT, {.dbl = 0}, 0, FLT_MAX, E}, + {"hls_time", "set segment length", OFFSET(time), AV_OPT_TYPE_DURATION, {.i64 = 2000000}, 0, INT64_MAX, E}, + {"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_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, 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}, {"hls_vtt_options","set hls vtt list of options for the container format used for hls", OFFSET(vtt_format_options_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, #if FF_API_HLS_WRAP {"hls_wrap", "set number after which the index wraps (will be deprecated)", OFFSET(wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E}, @@ -3009,6 +3137,7 @@ {"mpegts", "make segment file to mpegts files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MPEGTS }, 0, UINT_MAX, E, "segment_type"}, {"fmp4", "make segment file to fragment mp4 files in m3u8", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_FMP4 }, 0, UINT_MAX, E, "segment_type"}, {"hls_fmp4_init_filename", "set fragment mp4 file init filename", OFFSET(fmp4_init_filename), AV_OPT_TYPE_STRING, {.str = "init.mp4"}, 0, 0, E}, + {"hls_fmp4_init_resend", "resend fragment mp4 init file after refresh m3u8 every time", OFFSET(resend_init_file), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, {"hls_flags", "set flags affecting HLS playlist and media file generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, "flags"}, {"single_file", "generate a single media file indexed with byte ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX, E, "flags"}, {"temp_file", "write segment and playlist to temporary file and rename when complete", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_TEMP_FILE }, 0, UINT_MAX, E, "flags"}, @@ -3026,7 +3155,7 @@ {"independent_segments", "add EXT-X-INDEPENDENT-SEGMENTS, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_INDEPENDENT_SEGMENTS }, 0, UINT_MAX, E, "flags"}, {"iframes_only", "add EXT-X-I-FRAMES-ONLY, whenever applicable", 0, AV_OPT_TYPE_CONST, { .i64 = HLS_I_FRAMES_ONLY }, 0, UINT_MAX, E, "flags"}, #if FF_API_HLS_USE_LOCALTIME - {"use_localtime", "set filename expansion with strftime at segment creation(will be deprecated )", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, + {"use_localtime", "set filename expansion with strftime at segment creation(will be deprecated)", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, #endif {"strftime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, #if FF_API_HLS_USE_LOCALTIME @@ -3037,9 +3166,10 @@ {"event", "EVENT playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_EVENT }, INT_MIN, INT_MAX, E, "pl_type" }, {"vod", "VOD playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_VOD }, INT_MIN, INT_MAX, E, "pl_type" }, {"method", "set the HTTP method(default: PUT)", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, - {"hls_start_number_source", "set source of first number in sequence", OFFSET(start_sequence_source_type), AV_OPT_TYPE_INT, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, 0, HLS_START_SEQUENCE_AS_FORMATTED_DATETIME, E, "start_sequence_source_type" }, + {"hls_start_number_source", "set source of first number in sequence", OFFSET(start_sequence_source_type), AV_OPT_TYPE_INT, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, 0, HLS_START_SEQUENCE_LAST-1, E, "start_sequence_source_type" }, {"generic", "start_number value (default)", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_START_NUMBER }, INT_MIN, INT_MAX, E, "start_sequence_source_type" }, {"epoch", "seconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, "start_sequence_source_type" }, + {"epoch_us", "microseconds since epoch", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_MICROSECONDS_SINCE_EPOCH }, INT_MIN, INT_MAX, E, "start_sequence_source_type" }, {"datetime", "current datetime as YYYYMMDDhhmmss", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_START_SEQUENCE_AS_FORMATTED_DATETIME }, INT_MIN, INT_MAX, E, "start_sequence_source_type" }, {"http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"var_stream_map", "Variant stream map string", OFFSET(var_stream_map), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, @@ -3074,5 +3204,6 @@ .write_header = hls_write_header, .write_packet = hls_write_packet, .write_trailer = hls_write_trailer, + .deinit = hls_deinit, .priv_class = &hls_class, }; diff -Nru ffmpeg-4.2.2/libavformat/hlsplaylist.c ffmpeg-4.4/libavformat/hlsplaylist.c --- ffmpeg-4.2.2/libavformat/hlsplaylist.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/hlsplaylist.c 2020-07-11 10:39:30.000000000 +0000 @@ -28,15 +28,18 @@ #include "avformat.h" #include "hlsplaylist.h" -void ff_hls_write_playlist_version(AVIOContext *out, int version) { +void ff_hls_write_playlist_version(AVIOContext *out, int version) +{ if (!out) return; avio_printf(out, "#EXTM3U\n"); avio_printf(out, "#EXT-X-VERSION:%d\n", version); } -void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, - char *filename, char *language, int name_id, int is_default) { +void ff_hls_write_audio_rendition(AVIOContext *out, const char *agroup, + const char *filename, const char *language, + int name_id, int is_default) +{ if (!out || !agroup || !filename) return; @@ -48,10 +51,26 @@ avio_printf(out, "URI=\"%s\"\n", filename); } -void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, - int bandwidth, char *filename, char *agroup, - char *codecs, char *ccgroup) { +void ff_hls_write_subtitle_rendition(AVIOContext *out, const char *sgroup, + const char *filename, const char *language, + int name_id, int is_default) +{ + if (!out || !filename) + return; + + avio_printf(out, "#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"%s\"", sgroup); + avio_printf(out, ",NAME=\"subtitle_%d\",DEFAULT=%s,", name_id, is_default ? "YES" : "NO"); + if (language) { + avio_printf(out, "LANGUAGE=\"%s\",", language); + } + avio_printf(out, "URI=\"%s\"\n", filename); +} +void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, + const char *filename, const char *agroup, + const char *codecs, const char *ccgroup, + const char *sgroup) +{ if (!out || !filename) return; @@ -65,18 +84,21 @@ if (st && st->codecpar->width > 0 && st->codecpar->height > 0) avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width, st->codecpar->height); - if (codecs && strlen(codecs) > 0) + if (codecs && codecs[0]) avio_printf(out, ",CODECS=\"%s\"", codecs); - if (agroup && strlen(agroup) > 0) + if (agroup && agroup[0]) avio_printf(out, ",AUDIO=\"group_%s\"", agroup); - if (ccgroup && strlen(ccgroup) > 0) + if (ccgroup && ccgroup[0]) avio_printf(out, ",CLOSED-CAPTIONS=\"%s\"", ccgroup); + if (sgroup && sgroup[0]) + avio_printf(out, ",SUBTITLES=\"%s\"", sgroup); avio_printf(out, "\n%s\n\n", filename); } void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, int target_duration, int64_t sequence, - uint32_t playlist_type, int iframe_mode) { + uint32_t playlist_type, int iframe_mode) +{ if (!out) return; ff_hls_write_playlist_version(out, version); @@ -97,8 +119,9 @@ } } -void ff_hls_write_init_file(AVIOContext *out, char *filename, - int byterange_mode, int64_t size, int64_t pos) { +void ff_hls_write_init_file(AVIOContext *out, const char *filename, + int byterange_mode, int64_t size, int64_t pos) +{ avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", filename); if (byterange_mode) { avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", size, pos); @@ -107,12 +130,14 @@ } int ff_hls_write_file_entry(AVIOContext *out, int insert_discont, - int byterange_mode, - double duration, int round_duration, - int64_t size, int64_t pos, //Used only if HLS_SINGLE_FILE flag is set - char *baseurl, //Ignored if NULL - char *filename, double *prog_date_time, - int64_t video_keyframe_size, int64_t video_keyframe_pos, int iframe_mode) { + int byterange_mode, double duration, + int round_duration, int64_t size, + int64_t pos /* Used only if HLS_SINGLE_FILE flag is set */, + const char *baseurl /* Ignored if NULL */, + const char *filename, double *prog_date_time, + int64_t video_keyframe_size, int64_t video_keyframe_pos, + int iframe_mode) +{ if (!out || !filename) return AVERROR(EINVAL); @@ -161,7 +186,8 @@ return 0; } -void ff_hls_write_end_list (AVIOContext *out) { +void ff_hls_write_end_list(AVIOContext *out) +{ if (!out) return; avio_printf(out, "#EXT-X-ENDLIST\n"); diff -Nru ffmpeg-4.2.2/libavformat/hlsplaylist.h ffmpeg-4.4/libavformat/hlsplaylist.h --- ffmpeg-4.2.2/libavformat/hlsplaylist.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/hlsplaylist.h 2020-07-11 10:39:30.000000000 +0000 @@ -37,23 +37,29 @@ } PlaylistType; void ff_hls_write_playlist_version(AVIOContext *out, int version); -void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, - char *filename, char *language, int name_id, int is_default); -void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, - int bandwidth, char *filename, char *agroup, - char *codecs, char *ccgroup); +void ff_hls_write_audio_rendition(AVIOContext *out, const char *agroup, + const char *filename, const char *language, + int name_id, int is_default); +void ff_hls_write_subtitle_rendition(AVIOContext *out, const char *sgroup, + const char *filename, const char *language, + int name_id, int is_default); +void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, + const char *filename, const char *agroup, + const char *codecs, const char *ccgroup, + const char *sgroup); void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, int target_duration, int64_t sequence, uint32_t playlist_type, int iframe_mode); -void ff_hls_write_init_file(AVIOContext *out, char *filename, +void ff_hls_write_init_file(AVIOContext *out, const char *filename, int byterange_mode, int64_t size, int64_t pos); int ff_hls_write_file_entry(AVIOContext *out, int insert_discont, - int byterange_mode, - double duration, int round_duration, - int64_t size, int64_t pos, //Used only if HLS_SINGLE_FILE flag is set - char *baseurl, //Ignored if NULL - char *filename, double *prog_date_time, - int64_t video_keyframe_size, int64_t video_keyframe_pos, int iframe_mode); + int byterange_mode, double duration, + int round_duration, int64_t size, + int64_t pos /* Used only if HLS_SINGLE_FILE flag is set */, + const char *baseurl /* Ignored if NULL */, + const char *filename, double *prog_date_time, + int64_t video_keyframe_size, int64_t video_keyframe_pos, + int iframe_mode); void ff_hls_write_end_list (AVIOContext *out); #endif /* AVFORMAT_HLSPLAYLIST_H_ */ diff -Nru ffmpeg-4.2.2/libavformat/hlsproto.c ffmpeg-4.4/libavformat/hlsproto.c --- ffmpeg-4.2.2/libavformat/hlsproto.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/hlsproto.c 2021-04-08 21:28:40.000000000 +0000 @@ -22,7 +22,7 @@ /** * @file * Apple HTTP Live Streaming Protocol Handler - * http://tools.ietf.org/html/draft-pantos-http-live-streaming + * https://www.rfc-editor.org/rfc/rfc8216.txt */ #include "libavutil/avstring.h" @@ -178,7 +178,7 @@ free_segment_list(s); free_variant_list(s); - ffurl_close(s->seg_hd); + ffurl_closep(&s->seg_hd); return 0; } @@ -260,8 +260,7 @@ return ret; } if (s->seg_hd) { - ffurl_close(s->seg_hd); - s->seg_hd = NULL; + ffurl_closep(&s->seg_hd); s->cur_seq_no++; } reload_interval = s->n_segments > 0 ? diff -Nru ffmpeg-4.2.2/libavformat/hnm.c ffmpeg-4.4/libavformat/hnm.c --- ffmpeg-4.2.2/libavformat/hnm.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/hnm.c 2020-07-11 10:39:30.000000000 +0000 @@ -37,19 +37,9 @@ #define HNM4_CHUNK_ID_SD 17491 typedef struct Hnm4DemuxContext { - uint8_t version; - uint16_t width; - uint16_t height; - uint32_t filesize; uint32_t frames; - uint32_t taboffset; - uint16_t bits; - uint16_t channels; - uint32_t framesize; uint32_t currentframe; - int64_t pts; uint32_t superchunk_remaining; - AVPacket vpkt; } Hnm4DemuxContext; static int hnm_probe(const AVProbeData *p) @@ -69,54 +59,37 @@ { Hnm4DemuxContext *hnm = s->priv_data; AVIOContext *pb = s->pb; + unsigned width, height; AVStream *vst; - - /* default context members */ - hnm->pts = 0; - av_init_packet(&hnm->vpkt); - hnm->vpkt.data = NULL; - hnm->vpkt.size = 0; - - hnm->superchunk_remaining = 0; + int ret; avio_skip(pb, 8); - hnm->width = avio_rl16(pb); - hnm->height = avio_rl16(pb); - hnm->filesize = avio_rl32(pb); + width = avio_rl16(pb); + height = avio_rl16(pb); + avio_rl32(pb); // filesize hnm->frames = avio_rl32(pb); - hnm->taboffset = avio_rl32(pb); - hnm->bits = avio_rl16(pb); - hnm->channels = avio_rl16(pb); - hnm->framesize = avio_rl32(pb); - avio_skip(pb, 32); + avio_skip(pb, 44); - hnm->currentframe = 0; - - if (hnm->width < 256 || hnm->width > 640 || - hnm->height < 150 || hnm->height > 480) { + if (width < 256 || width > 640 || + height < 150 || height > 480) { av_log(s, AV_LOG_ERROR, - "invalid resolution: %ux%u\n", hnm->width, hnm->height); + "invalid resolution: %ux%u\n", width, height); return AVERROR_INVALIDDATA; } - // TODO: find a better way to detect HNM4A - if (hnm->width == 640) - hnm->version = 0x4a; - else - hnm->version = 0x40; - if (!(vst = avformat_new_stream(s, NULL))) return AVERROR(ENOMEM); vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; vst->codecpar->codec_id = AV_CODEC_ID_HNM4_VIDEO; vst->codecpar->codec_tag = 0; - vst->codecpar->width = hnm->width; - vst->codecpar->height = hnm->height; - vst->codecpar->extradata = av_mallocz(1); + vst->codecpar->width = width; + vst->codecpar->height = height; + if ((ret = ff_alloc_extradata(vst->codecpar, 1)) < 0) + return ret; - vst->codecpar->extradata_size = 1; - memcpy(vst->codecpar->extradata, &hnm->version, 1); + // TODO: find a better way to detect HNM4A + vst->codecpar->extradata[0] = width == 640 ? 0x4a : 0x40; vst->start_time = 0; @@ -185,16 +158,6 @@ return ret; } -static int hnm_read_close(AVFormatContext *s) -{ - Hnm4DemuxContext *hnm = s->priv_data; - - if (hnm->vpkt.size > 0) - av_packet_unref(&hnm->vpkt); - - return 0; -} - AVInputFormat ff_hnm_demuxer = { .name = "hnm", .long_name = NULL_IF_CONFIG_SMALL("Cryo HNM v4"), @@ -202,6 +165,5 @@ .read_probe = hnm_probe, .read_header = hnm_read_header, .read_packet = hnm_read_packet, - .read_close = hnm_read_close, .flags = AVFMT_NO_BYTE_SEEK | AVFMT_NOGENSEARCH | AVFMT_NOBINSEARCH }; diff -Nru ffmpeg-4.2.2/libavformat/httpauth.c ffmpeg-4.4/libavformat/httpauth.c --- ffmpeg-4.2.2/libavformat/httpauth.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/httpauth.c 2020-07-11 10:39:30.000000000 +0000 @@ -255,7 +255,7 @@ if (state->auth_type == HTTP_AUTH_BASIC) { int auth_b64_len, len; - char *ptr, *decoded_auth = ff_urldecode(auth); + char *ptr, *decoded_auth = ff_urldecode(auth, 0); if (!decoded_auth) return NULL; @@ -275,7 +275,7 @@ av_strlcat(ptr, "\r\n", len - (ptr - authstr)); av_free(decoded_auth); } else if (state->auth_type == HTTP_AUTH_DIGEST) { - char *username = ff_urldecode(auth), *password; + char *username = ff_urldecode(auth, 0), *password; if (!username) return NULL; diff -Nru ffmpeg-4.2.2/libavformat/http.c ffmpeg-4.4/libavformat/http.c --- ffmpeg-4.2.2/libavformat/http.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/http.c 2021-04-08 21:28:40.000000000 +0000 @@ -27,6 +27,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/bprint.h" #include "libavutil/opt.h" #include "libavutil/time.h" #include "libavutil/parseutils.h" @@ -45,7 +46,7 @@ /* The IO buffer size is unrelated to the max URL size in itself, but needs * to be large enough to fit the full request headers (including long * path names). */ -#define BUFFER_SIZE MAX_URL_SIZE +#define BUFFER_SIZE (MAX_URL_SIZE + HTTP_HEADERS_SIZE) #define MAX_REDIRECTS 8 #define HTTP_SINGLE 1 #define HTTP_MUTLI 2 @@ -77,9 +78,6 @@ char *http_version; char *user_agent; char *referer; -#if FF_API_HTTP_USER_AGENT - char *user_agent_deprecated; -#endif char *content_type; /* Set if the server correctly handles Connection: close and will close * the connection after feeding us the content. */ @@ -118,8 +116,10 @@ char *method; int reconnect; int reconnect_at_eof; + int reconnect_on_network_error; int reconnect_streamed; int reconnect_delay_max; + char *reconnect_on_http_error; int listen; char *resource; int reply_code; @@ -142,7 +142,7 @@ { "user_agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, { .str = DEFAULT_USER_AGENT }, 0, 0, D }, { "referer", "override referer header", OFFSET(referer), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, #if FF_API_HTTP_USER_AGENT - { "user-agent", "use the \"user_agent\" option instead", OFFSET(user_agent_deprecated), AV_OPT_TYPE_STRING, { .str = DEFAULT_USER_AGENT }, 0, 0, D|AV_OPT_FLAG_DEPRECATED }, + { "user-agent", "use the \"user_agent\" option instead", OFFSET(user_agent), AV_OPT_TYPE_STRING, { .str = DEFAULT_USER_AGENT }, 0, 0, D|AV_OPT_FLAG_DEPRECATED }, #endif { "multiple_requests", "use persistent connections", OFFSET(multiple_requests), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D | E }, { "post_data", "set custom HTTP post data", OFFSET(post_data), AV_OPT_TYPE_BINARY, .flags = D | E }, @@ -163,6 +163,8 @@ { "method", "Override the HTTP method or set the expected HTTP method from a client", OFFSET(method), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E }, { "reconnect", "auto reconnect after disconnect before EOF", OFFSET(reconnect), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D }, { "reconnect_at_eof", "auto reconnect at EOF", OFFSET(reconnect_at_eof), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D }, + { "reconnect_on_network_error", "auto reconnect in case of tcp/tls error during connect", OFFSET(reconnect_on_network_error), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D }, + { "reconnect_on_http_error", "list of http status codes to reconnect on", OFFSET(reconnect_on_http_error), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, { "reconnect_streamed", "auto reconnect streamed / non seekable streams", OFFSET(reconnect_streamed), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D }, { "reconnect_delay_max", "max reconnect delay in seconds after which to give up", OFFSET(reconnect_delay_max), AV_OPT_TYPE_INT, { .i64 = 120 }, 0, UINT_MAX/1000/1000, D }, { "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, D | E }, @@ -190,9 +192,10 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) { const char *path, *proxy_path, *lower_proto = "tcp", *local_path; + char *hashmark; char hostname[1024], hoststr[1024], proto[10]; char auth[1024], proxyauth[1024] = ""; - char path1[MAX_URL_SIZE]; + char path1[MAX_URL_SIZE], sanitized_path[MAX_URL_SIZE]; char buf[1024], urlbuf[MAX_URL_SIZE]; int port, use_proxy, err, location_changed = 0; HTTPContext *s = h->priv_data; @@ -211,14 +214,28 @@ use_proxy = 0; if (port < 0) port = 443; + /* pass http_proxy to underlying protocol */ + if (s->http_proxy) { + err = av_dict_set(options, "http_proxy", s->http_proxy, 0); + if (err < 0) + return err; + } } if (port < 0) port = 80; - if (path1[0] == '\0') + hashmark = strchr(path1, '#'); + if (hashmark) + *hashmark = '\0'; + + if (path1[0] == '\0') { path = "/"; - else + } else if (path1[0] == '?') { + snprintf(sanitized_path, sizeof(sanitized_path), "/%s", path1); + path = sanitized_path; + } else { path = path1; + } local_path = path; if (use_proxy) { /* Reassemble the request URL without auth string - we don't @@ -248,21 +265,73 @@ return location_changed; } +static int http_should_reconnect(HTTPContext *s, int err) +{ + const char *status_group; + char http_code[4]; + + switch (err) { + case AVERROR_HTTP_BAD_REQUEST: + case AVERROR_HTTP_UNAUTHORIZED: + case AVERROR_HTTP_FORBIDDEN: + case AVERROR_HTTP_NOT_FOUND: + case AVERROR_HTTP_OTHER_4XX: + status_group = "4xx"; + break; + + case AVERROR_HTTP_SERVER_ERROR: + status_group = "5xx"; + break; + + default: + return s->reconnect_on_network_error; + } + + if (!s->reconnect_on_http_error) + return 0; + + if (av_match_list(status_group, s->reconnect_on_http_error, ',') > 0) + return 1; + + snprintf(http_code, sizeof(http_code), "%d", s->http_code); + + return av_match_list(http_code, s->reconnect_on_http_error, ',') > 0; +} + /* return non zero if error */ static int http_open_cnx(URLContext *h, AVDictionary **options) { HTTPAuthType cur_auth_type, cur_proxy_auth_type; HTTPContext *s = h->priv_data; int location_changed, attempts = 0, redirects = 0; + int reconnect_delay = 0; + uint64_t off; + redo: av_dict_copy(options, s->chained_options, 0); cur_auth_type = s->auth_state.auth_type; cur_proxy_auth_type = s->auth_state.auth_type; + off = s->off; location_changed = http_open_cnx_internal(h, options); - if (location_changed < 0) - goto fail; + if (location_changed < 0) { + if (!http_should_reconnect(s, location_changed) || + reconnect_delay > s->reconnect_delay_max) + goto fail; + + av_log(h, AV_LOG_WARNING, "Will reconnect at %"PRIu64" in %d second(s).\n", off, reconnect_delay); + location_changed = ff_network_sleep_interruptible(1000U * 1000 * reconnect_delay, &h->interrupt_callback); + if (location_changed != AVERROR(ETIMEDOUT)) + goto fail; + reconnect_delay = 1 + 2 * reconnect_delay; + + /* restore the offset (http_connect resets it) */ + s->off = off; + + ffurl_closep(&s->hd); + goto redo; + } attempts++; if (s->http_code == 401) { @@ -282,7 +351,7 @@ goto fail; } if ((s->http_code == 301 || s->http_code == 302 || - s->http_code == 303 || s->http_code == 307) && + s->http_code == 303 || s->http_code == 307 || s->http_code == 308) && location_changed == 1) { /* url moved, get next */ ffurl_closep(&s->hd); @@ -304,8 +373,27 @@ return location_changed; return ff_http_averror(s->http_code, AVERROR(EIO)); } +int ff_http_get_shutdown_status(URLContext *h) +{ + int ret = 0; + HTTPContext *s = h->priv_data; + + /* flush the receive buffer when it is write only mode */ + char buf[1024]; + int read_ret; + read_ret = ffurl_read(s->hd, buf, sizeof(buf)); + if (read_ret < 0) { + ret = read_ret; + } + + return ret; +} -int ff_http_do_new_request(URLContext *h, const char *uri) +int ff_http_do_new_request(URLContext *h, const char *uri) { + return ff_http_do_new_request2(h, uri, NULL); +} + +int ff_http_do_new_request2(URLContext *h, const char *uri, AVDictionary **opts) { HTTPContext *s = h->priv_data; AVDictionary *options = NULL; @@ -350,6 +438,9 @@ if (!s->location) return AVERROR(ENOMEM); + if ((ret = av_opt_set_dict(s, opts)) < 0) + return ret; + av_log(s, AV_LOG_INFO, "Opening \'%s\' for %s\n", uri, h->flags & AVIO_FLAG_WRITE ? "writing" : "reading"); ret = http_open_cnx(h, &options); av_dict_free(&options); @@ -545,7 +636,7 @@ "No trailing CRLF found in HTTP header. Adding it.\n"); ret = av_reallocp(&s->headers, len + 3); if (ret < 0) - return ret; + goto bail_out; s->headers[len] = '\r'; s->headers[len + 1] = '\n'; s->headers[len + 2] = '\0'; @@ -556,6 +647,7 @@ return http_listen(h, uri, flags, options); } ret = http_open_cnx(h, options); +bail_out: if (ret < 0) av_dict_free(&s->chained_options); return ret; @@ -754,6 +846,7 @@ static int parse_set_cookie(const char *set_cookie, AVDictionary **dict) { char *param, *next_param, *cstr, *back; + char *saveptr = NULL; if (!set_cookie[0]) return 0; @@ -771,8 +864,9 @@ } next_param = cstr; - while ((param = av_strtok(next_param, ";", &next_param))) { + while ((param = av_strtok(next_param, ";", &saveptr))) { char *name, *value; + next_param = NULL; param += strspn(param, WHITESPACES); if ((name = av_strtok(param, "=", &value))) { if (av_dict_set(dict, name, value, 0) < 0) { @@ -1032,6 +1126,7 @@ // Set-Cookie fields will result in multiple values delimited by a newline int ret = 0; char *cookie, *set_cookies, *next; + char *saveptr = NULL; // destroy any cookies in the dictionary. av_dict_free(&s->cookie_dict); @@ -1044,10 +1139,11 @@ return AVERROR(ENOMEM); *cookies = NULL; - while ((cookie = av_strtok(next, "\n", &next)) && !ret) { + while ((cookie = av_strtok(next, "\n", &saveptr)) && !ret) { AVDictionary *cookie_params = NULL; AVDictionaryEntry *cookie_entry, *e; + next = NULL; // store the cookie in a dict in case it is updated in the response if (parse_cookie(s, cookie, &s->cookie_dict)) av_log(s, AV_LOG_WARNING, "Unable to parse '%s'\n", cookie); @@ -1147,19 +1243,50 @@ return err; } +/** + * Escape unsafe characters in path in order to pass them safely to the HTTP + * request. Insipred by the algorithm in GNU wget: + * - escape "%" characters not followed by two hex digits + * - escape all "unsafe" characters except which are also "reserved" + * - pass through everything else + */ +static void bprint_escaped_path(AVBPrint *bp, const char *path) +{ +#define NEEDS_ESCAPE(ch) \ + ((ch) <= ' ' || (ch) >= '\x7f' || \ + (ch) == '"' || (ch) == '%' || (ch) == '<' || (ch) == '>' || (ch) == '\\' || \ + (ch) == '^' || (ch) == '`' || (ch) == '{' || (ch) == '}' || (ch) == '|') + while (*path) { + char buf[1024]; + char *q = buf; + while (*path && q - buf < sizeof(buf) - 4) { + if (path[0] == '%' && av_isxdigit(path[1]) && av_isxdigit(path[2])) { + *q++ = *path++; + *q++ = *path++; + *q++ = *path++; + } else if (NEEDS_ESCAPE(*path)) { + q += snprintf(q, 4, "%%%02X", (uint8_t)*path++); + } else { + *q++ = *path++; + } + } + av_bprint_append_data(bp, buf, q - buf); + } +} + static int http_connect(URLContext *h, const char *path, const char *local_path, const char *hoststr, const char *auth, const char *proxyauth, int *new_location) { HTTPContext *s = h->priv_data; int post, err; - char headers[HTTP_HEADERS_SIZE] = ""; + AVBPrint request; char *authstr = NULL, *proxyauthstr = NULL; uint64_t off = s->off; - int len = 0; const char *method; int send_expect_100 = 0; - int ret; + + av_bprint_init_for_buffer(&request, s->buffer, sizeof(s->buffer)); /* send http header */ post = h->flags & AVIO_FLAG_WRITE; @@ -1197,100 +1324,73 @@ } } -#if FF_API_HTTP_USER_AGENT - if (strcmp(s->user_agent_deprecated, DEFAULT_USER_AGENT)) { - s->user_agent = av_strdup(s->user_agent_deprecated); - } -#endif + av_bprintf(&request, "%s ", method); + bprint_escaped_path(&request, path); + av_bprintf(&request, " HTTP/1.1\r\n"); + + if (post && s->chunked_post) + av_bprintf(&request, "Transfer-Encoding: chunked\r\n"); /* set default headers if needed */ if (!has_header(s->headers, "\r\nUser-Agent: ")) - len += av_strlcatf(headers + len, sizeof(headers) - len, - "User-Agent: %s\r\n", s->user_agent); + av_bprintf(&request, "User-Agent: %s\r\n", s->user_agent); if (s->referer) { /* set default headers if needed */ if (!has_header(s->headers, "\r\nReferer: ")) - len += av_strlcatf(headers + len, sizeof(headers) - len, - "Referer: %s\r\n", s->referer); + av_bprintf(&request, "Referer: %s\r\n", s->referer); } if (!has_header(s->headers, "\r\nAccept: ")) - len += av_strlcpy(headers + len, "Accept: */*\r\n", - sizeof(headers) - len); + av_bprintf(&request, "Accept: */*\r\n"); // Note: we send this on purpose even when s->off is 0 when we're probing, // since it allows us to detect more reliably if a (non-conforming) // server supports seeking by analysing the reply headers. if (!has_header(s->headers, "\r\nRange: ") && !post && (s->off > 0 || s->end_off || s->seekable == -1)) { - len += av_strlcatf(headers + len, sizeof(headers) - len, - "Range: bytes=%"PRIu64"-", s->off); + av_bprintf(&request, "Range: bytes=%"PRIu64"-", s->off); if (s->end_off) - len += av_strlcatf(headers + len, sizeof(headers) - len, - "%"PRId64, s->end_off - 1); - len += av_strlcpy(headers + len, "\r\n", - sizeof(headers) - len); + av_bprintf(&request, "%"PRId64, s->end_off - 1); + av_bprintf(&request, "\r\n"); } if (send_expect_100 && !has_header(s->headers, "\r\nExpect: ")) - len += av_strlcatf(headers + len, sizeof(headers) - len, - "Expect: 100-continue\r\n"); + av_bprintf(&request, "Expect: 100-continue\r\n"); - if (!has_header(s->headers, "\r\nConnection: ")) { - if (s->multiple_requests) - len += av_strlcpy(headers + len, "Connection: keep-alive\r\n", - sizeof(headers) - len); - else - len += av_strlcpy(headers + len, "Connection: close\r\n", - sizeof(headers) - len); - } + if (!has_header(s->headers, "\r\nConnection: ")) + av_bprintf(&request, "Connection: %s\r\n", s->multiple_requests ? "keep-alive" : "close"); if (!has_header(s->headers, "\r\nHost: ")) - len += av_strlcatf(headers + len, sizeof(headers) - len, - "Host: %s\r\n", hoststr); + av_bprintf(&request, "Host: %s\r\n", hoststr); if (!has_header(s->headers, "\r\nContent-Length: ") && s->post_data) - len += av_strlcatf(headers + len, sizeof(headers) - len, - "Content-Length: %d\r\n", s->post_datalen); + av_bprintf(&request, "Content-Length: %d\r\n", s->post_datalen); if (!has_header(s->headers, "\r\nContent-Type: ") && s->content_type) - len += av_strlcatf(headers + len, sizeof(headers) - len, - "Content-Type: %s\r\n", s->content_type); + av_bprintf(&request, "Content-Type: %s\r\n", s->content_type); if (!has_header(s->headers, "\r\nCookie: ") && s->cookies) { char *cookies = NULL; if (!get_cookies(s, &cookies, path, hoststr) && cookies) { - len += av_strlcatf(headers + len, sizeof(headers) - len, - "Cookie: %s\r\n", cookies); + av_bprintf(&request, "Cookie: %s\r\n", cookies); av_free(cookies); } } if (!has_header(s->headers, "\r\nIcy-MetaData: ") && s->icy) - len += av_strlcatf(headers + len, sizeof(headers) - len, - "Icy-MetaData: %d\r\n", 1); + av_bprintf(&request, "Icy-MetaData: 1\r\n"); /* now add in custom headers */ if (s->headers) - av_strlcpy(headers + len, s->headers, sizeof(headers) - len); + av_bprintf(&request, "%s", s->headers); - ret = snprintf(s->buffer, sizeof(s->buffer), - "%s %s HTTP/1.1\r\n" - "%s" - "%s" - "%s" - "%s%s" - "\r\n", - method, - path, - post && s->chunked_post ? "Transfer-Encoding: chunked\r\n" : "", - headers, - authstr ? authstr : "", - proxyauthstr ? "Proxy-" : "", proxyauthstr ? proxyauthstr : ""); + if (authstr) + av_bprintf(&request, "%s", authstr); + if (proxyauthstr) + av_bprintf(&request, "Proxy-%s", proxyauthstr); + av_bprintf(&request, "\r\n"); - av_log(h, AV_LOG_DEBUG, "request: %s\n", s->buffer); + av_log(h, AV_LOG_DEBUG, "request: %s\n", request.str); - if (strlen(headers) + 1 == sizeof(headers) || - ret >= sizeof(s->buffer)) { + if (!av_bprint_is_complete(&request)) { av_log(h, AV_LOG_ERROR, "overlong headers\n"); err = AVERROR(EINVAL); goto done; } - - if ((err = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0) + if ((err = ffurl_write(s->hd, request.str, request.len)) < 0) goto done; if (s->post_data) @@ -1389,7 +1489,8 @@ if ((!s->willclose || s->chunksize == UINT64_MAX) && s->off >= target_end) return AVERROR_EOF; len = ffurl_read(s->hd, buf, size); - if (!len && (!s->willclose || s->chunksize == UINT64_MAX) && s->off < target_end) { + if ((!len || len == AVERROR_EOF) && + (!s->willclose || s->chunksize == UINT64_MAX) && s->off < target_end) { av_log(h, AV_LOG_ERROR, "Stream ends prematurely at %"PRIu64", should be %"PRIu64"\n", s->off, target_end @@ -1769,7 +1870,7 @@ .priv_data_size = sizeof(HTTPContext), .priv_data_class = &http_context_class, .flags = URL_PROTOCOL_FLAG_NETWORK, - .default_whitelist = "http,https,tls,rtp,tcp,udp,crypto,httpproxy" + .default_whitelist = "http,https,tls,rtp,tcp,udp,crypto,httpproxy,data" }; #endif /* CONFIG_HTTP_PROTOCOL */ diff -Nru ffmpeg-4.2.2/libavformat/http.h ffmpeg-4.4/libavformat/http.h --- ffmpeg-4.2.2/libavformat/http.h 2017-12-31 22:35:49.000000000 +0000 +++ ffmpeg-4.4/libavformat/http.h 2020-07-11 10:39:30.000000000 +0000 @@ -38,6 +38,15 @@ void ff_http_init_auth_state(URLContext *dest, const URLContext *src); /** + * Get the HTTP shutdown response status, be used after http_shutdown. + * + * @param h pointer to the resource + * @return a negative value if an error condition occurred, 0 + * otherwise + */ +int ff_http_get_shutdown_status(URLContext *h); + +/** * Send a new HTTP request, reusing the old connection. * * @param h pointer to the resource @@ -47,6 +56,19 @@ */ int ff_http_do_new_request(URLContext *h, const char *uri); +/** + * Send a new HTTP request, reusing the old connection. + * + * @param h pointer to the resource + * @param uri uri used to perform the request + * @param options A dictionary filled with HTTP options. On return + * this parameter will be destroyed and replaced with a dict containing options + * that were not found. May be NULL. + * @return a negative value if an error condition occurred, 0 + * otherwise + */ +int ff_http_do_new_request2(URLContext *h, const char *uri, AVDictionary **options); + int ff_http_averror(int status_code, int default_averror); #endif /* AVFORMAT_HTTP_H */ diff -Nru ffmpeg-4.2.2/libavformat/icecast.c ffmpeg-4.4/libavformat/icecast.c --- ffmpeg-4.2.2/libavformat/icecast.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/icecast.c 2021-04-08 21:28:40.000000000 +0000 @@ -43,6 +43,7 @@ int public; char *url; char *user_agent; + int tls; } IcecastContext; #define DEFAULT_ICE_USER "source" @@ -62,6 +63,7 @@ { "password", "set password", OFFSET(pass), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, { "content_type", "set content-type, MUST be set if not audio/mpeg", OFFSET(content_type), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, { "legacy_icecast", "use legacy SOURCE method, for Icecast < v2.4", OFFSET(legacy_icecast), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, + { "tls", "use a TLS connection", OFFSET(tls), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { NULL } }; @@ -75,8 +77,7 @@ static int icecast_close(URLContext *h) { IcecastContext *s = h->priv_data; - if (s->hd) - ffurl_close(s->hd); + ffurl_closep(&s->hd); return 0; } @@ -89,7 +90,7 @@ // URI part variables char h_url[1024], host[1024], auth[1024], path[1024]; - char *headers = NULL, *user = NULL; + char *headers, *user = NULL; int port, ret; AVBPrint bp; @@ -105,15 +106,16 @@ cat_header(&bp, "Ice-Genre", s->genre); cat_header(&bp, "Ice-Public", s->public ? "1" : "0"); if (!av_bprint_is_complete(&bp)) { - ret = AVERROR(ENOMEM); - goto cleanup; + av_bprint_finalize(&bp, NULL); + return AVERROR(ENOMEM); } - av_bprint_finalize(&bp, &headers); + if ((ret = av_bprint_finalize(&bp, &headers)) < 0) + return ret; // Set options av_dict_set(&opt_dict, "method", s->legacy_icecast ? "SOURCE" : "PUT", 0); av_dict_set(&opt_dict, "auth_type", "basic", 0); - av_dict_set(&opt_dict, "headers", headers, 0); + av_dict_set(&opt_dict, "headers", headers, AV_DICT_DONT_STRDUP_VAL); av_dict_set(&opt_dict, "chunked_post", "0", 0); av_dict_set(&opt_dict, "send_expect_100", s->legacy_icecast ? "-1" : "1", 0); if (NOT_EMPTY(s->content_type)) @@ -162,14 +164,15 @@ } // Build new URI for passing to http protocol - ff_url_join(h_url, sizeof(h_url), "http", auth, host, port, "%s", path); + ff_url_join(h_url, sizeof(h_url), + s->tls ? "https" : "http", + auth, host, port, "%s", path); // Finally open http proto handler ret = ffurl_open_whitelist(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL, &opt_dict, h->protocol_whitelist, h->protocol_blacklist, h); cleanup: av_freep(&user); - av_freep(&headers); av_dict_free(&opt_dict); return ret; diff -Nru ffmpeg-4.2.2/libavformat/icodec.c ffmpeg-4.4/libavformat/icodec.c --- ffmpeg-4.2.2/libavformat/icodec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/icodec.c 2021-02-20 20:27:47.000000000 +0000 @@ -84,6 +84,9 @@ avio_skip(pb, 4); ico->nb_images = avio_rl16(pb); + if (!ico->nb_images) + return AVERROR_INVALIDDATA; + ico->images = av_malloc_array(ico->nb_images, sizeof(IcoImage)); if (!ico->images) return AVERROR(ENOMEM); @@ -93,7 +96,7 @@ int tmp; if (avio_seek(pb, 6 + i * 16, SEEK_SET) < 0) - break; + goto fail; st = avformat_new_stream(s, NULL); if (!st) { @@ -113,13 +116,12 @@ ico->images[i].size = avio_rl32(pb); if (ico->images[i].size <= 0) { av_log(s, AV_LOG_ERROR, "Invalid image size %d\n", ico->images[i].size); - av_freep(&ico->images); - return AVERROR_INVALIDDATA; + goto fail; } ico->images[i].offset = avio_rl32(pb); if (avio_seek(pb, ico->images[i].offset, SEEK_SET) < 0) - break; + goto fail; codec = avio_rl32(pb); switch (codec) { @@ -130,8 +132,7 @@ break; case 40: if (ico->images[i].size < 40) { - av_freep(&ico->images); - return AVERROR_INVALIDDATA; + goto fail; } st->codecpar->codec_id = AV_CODEC_ID_BMP; tmp = avio_rl32(pb); @@ -143,12 +144,14 @@ break; default: avpriv_request_sample(s, "codec %d", codec); - av_freep(&ico->images); - return AVERROR_INVALIDDATA; + goto fail; } } return 0; +fail: + av_freep(&ico->images); + return AVERROR_INVALIDDATA; } static int read_packet(AVFormatContext *s, AVPacket *pkt) @@ -156,12 +159,14 @@ IcoDemuxContext *ico = s->priv_data; IcoImage *image; AVIOContext *pb = s->pb; - AVStream *st = s->streams[0]; + AVStream *st; int ret; if (ico->current_image >= ico->nb_images) return AVERROR_EOF; + st = s->streams[0]; + image = &ico->images[ico->current_image]; if ((ret = avio_seek(pb, image->offset, SEEK_SET)) < 0) @@ -185,7 +190,6 @@ bytestream_put_le32(&buf, 0); if ((ret = avio_read(pb, buf, image->size)) != image->size) { - av_packet_unref(pkt); return ret < 0 ? ret : AVERROR_INVALIDDATA; } diff -Nru ffmpeg-4.2.2/libavformat/icoenc.c ffmpeg-4.4/libavformat/icoenc.c --- ffmpeg-4.2.2/libavformat/icoenc.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/icoenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -106,8 +106,6 @@ if (!ico->images) return AVERROR(ENOMEM); - avio_flush(pb); - return 0; } @@ -183,11 +181,16 @@ avio_wl32(pb, ico->images[i].offset); } - av_freep(&ico->images); - return 0; } +static void ico_deinit(AVFormatContext *s) +{ + IcoMuxContext *ico = s->priv_data; + + av_freep(&ico->images); +} + AVOutputFormat ff_ico_muxer = { .name = "ico", .long_name = NULL_IF_CONFIG_SMALL("Microsoft Windows ICO"), @@ -199,5 +202,6 @@ .write_header = ico_write_header, .write_packet = ico_write_packet, .write_trailer = ico_write_trailer, + .deinit = ico_deinit, .flags = AVFMT_NOTIMESTAMPS, }; diff -Nru ffmpeg-4.2.2/libavformat/id3v1.c ffmpeg-4.4/libavformat/id3v1.c --- ffmpeg-4.2.2/libavformat/id3v1.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/id3v1.c 2020-07-11 10:39:30.000000000 +0000 @@ -92,7 +92,7 @@ [64] = "Native American", [65] = "Cabaret", [66] = "New Wave", - [67] = "Psychadelic", /* sic, the misspelling is used in the specification */ + [67] = "Psychedelic", [68] = "Rave", [69] = "Showtunes", [70] = "Trailer", @@ -110,7 +110,7 @@ [82] = "National Folk", [83] = "Swing", [84] = "Fast Fusion", - [85] = "Bebob", + [85] = "Bebop", [86] = "Latin", [87] = "Revival", [88] = "Celtic", @@ -148,20 +148,20 @@ [120] = "Duet", [121] = "Punk Rock", [122] = "Drum Solo", - [123] = "A capella", + [123] = "A Cappella", [124] = "Euro-House", [125] = "Dance Hall", [126] = "Goa", [127] = "Drum & Bass", [128] = "Club-House", - [129] = "Hardcore", + [129] = "Hardcore Techno", [130] = "Terror", [131] = "Indie", [132] = "BritPop", [133] = "Negerpunk", [134] = "Polsk Punk", [135] = "Beat", - [136] = "Christian Gangsta", + [136] = "Christian Gangsta Rap", [137] = "Heavy Metal", [138] = "Black Metal", [139] = "Crossover", @@ -171,8 +171,52 @@ [143] = "Salsa", [144] = "Thrash Metal", [145] = "Anime", - [146] = "JPop", - [147] = "SynthPop", + [146] = "Jpop", + [147] = "Synthpop", + [148] = "Abstract", + [149] = "Art Rock", + [150] = "Baroque", + [151] = "Bhangra", + [152] = "Big Beat", + [153] = "Breakbeat", + [154] = "Chillout", + [155] = "Downtempo", + [156] = "Dub", + [157] = "EBM", + [158] = "Eclectic", + [159] = "Electro", + [160] = "Electroclash", + [161] = "Emo", + [162] = "Experimental", + [163] = "Garage", + [164] = "Global", + [165] = "IDM", + [166] = "Illbient", + [167] = "Industro-Goth", + [168] = "Jam Band", + [169] = "Krautrock", + [170] = "Leftfield", + [171] = "Lounge", + [172] = "Math Rock", + [173] = "New Romantic", + [174] = "Nu-Breakz", + [175] = "Post-Punk", + [176] = "Post-Rock", + [177] = "Psytrance", + [178] = "Shoegaze", + [179] = "Space Rock", + [180] = "Trop Rock", + [181] = "World Music", + [182] = "Neoclassical", + [183] = "Audiobook", + [184] = "Audio Theatre", + [185] = "Neue Deutsche Welle", + [186] = "Podcast", + [187] = "Indie Rock", + [188] = "G-Funk", + [189] = "Dubstep", + [190] = "Garage Rock", + [191] = "Psybient" }; static void get_string(AVFormatContext *s, const char *key, diff -Nru ffmpeg-4.2.2/libavformat/id3v1.h ffmpeg-4.4/libavformat/id3v1.h --- ffmpeg-4.2.2/libavformat/id3v1.h 2016-03-29 02:25:28.000000000 +0000 +++ ffmpeg-4.4/libavformat/id3v1.h 2020-07-11 10:39:30.000000000 +0000 @@ -26,7 +26,7 @@ #define ID3v1_TAG_SIZE 128 -#define ID3v1_GENRE_MAX 147 +#define ID3v1_GENRE_MAX 191 /** * ID3v1 genres diff -Nru ffmpeg-4.2.2/libavformat/id3v2.c ffmpeg-4.4/libavformat/id3v2.c --- ffmpeg-4.2.2/libavformat/id3v2.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/id3v2.c 2021-04-08 21:28:40.000000000 +0000 @@ -225,7 +225,6 @@ av_freep(&geob->file_name); av_freep(&geob->description); av_freep(&geob->data); - av_free(geob); } /** @@ -361,8 +360,8 @@ { uint8_t lang[4]; uint8_t *descriptor = NULL; // 'Content descriptor' - uint8_t *text = NULL; - char *key = NULL; + uint8_t *text; + char *key; int encoding; int ok = 0; @@ -387,18 +386,19 @@ key = av_asprintf("lyrics-%s%s%s", descriptor[0] ? (char *)descriptor : "", descriptor[0] ? "-" : "", lang); - if (!key) + if (!key) { + av_free(text); goto error; + } - av_dict_set(metadata, key, text, 0); + av_dict_set(metadata, key, text, + AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); ok = 1; error: if (!ok) av_log(s, AV_LOG_ERROR, "Error reading lyrics, skipped\n"); av_free(descriptor); - av_free(text); - av_free(key); } /** @@ -458,20 +458,15 @@ if (taglen < 1) return; - geob_data = av_mallocz(sizeof(ID3v2ExtraMetaGEOB)); - if (!geob_data) { - av_log(s, AV_LOG_ERROR, "Failed to alloc %"SIZE_SPECIFIER" bytes\n", - sizeof(ID3v2ExtraMetaGEOB)); - return; - } - new_extra = av_mallocz(sizeof(ID3v2ExtraMeta)); if (!new_extra) { av_log(s, AV_LOG_ERROR, "Failed to alloc %"SIZE_SPECIFIER" bytes\n", sizeof(ID3v2ExtraMeta)); - goto fail; + return; } + geob_data = &new_extra->data.geob; + /* read encoding type byte */ encoding = avio_r8(pb); taglen--; @@ -510,7 +505,6 @@ /* add data to the list */ new_extra->tag = "GEOB"; - new_extra->data = geob_data; new_extra->next = *extra_meta; *extra_meta = new_extra; @@ -576,7 +570,6 @@ ID3v2ExtraMetaAPIC *apic = obj; av_buffer_unref(&apic->buf); av_freep(&apic->description); - av_freep(&apic); } static void rstrip_spaces(char *buf) @@ -602,16 +595,20 @@ goto fail; new_extra = av_mallocz(sizeof(*new_extra)); - apic = av_mallocz(sizeof(*apic)); - if (!new_extra || !apic) + if (!new_extra) goto fail; + apic = &new_extra->data.apic; + enc = avio_r8(pb); taglen--; /* mimetype */ if (isv34) { - taglen -= avio_get_str(pb, taglen, mimetype, sizeof(mimetype)); + int ret = avio_get_str(pb, taglen, mimetype, sizeof(mimetype)); + if (ret < 0 || ret >= taglen) + goto fail; + taglen -= ret; } else { if (avio_read(pb, mimetype, 3) < 0) goto fail; @@ -657,7 +654,6 @@ memset(apic->buf->data + taglen, 0, AV_INPUT_BUFFER_PADDING_SIZE); new_extra->tag = "APIC"; - new_extra->data = apic; new_extra->next = *extra_meta; *extra_meta = new_extra; @@ -679,7 +675,6 @@ ID3v2ExtraMetaCHAP *chap = obj; av_freep(&chap->element_id); av_dict_free(&chap->meta); - av_freep(&chap); } static void read_chapter(AVFormatContext *s, AVIOContext *pb, int len, const char *ttag, ID3v2ExtraMeta **extra_meta, int isv34) @@ -690,10 +685,10 @@ ID3v2ExtraMetaCHAP *chap = NULL; new_extra = av_mallocz(sizeof(*new_extra)); - chap = av_mallocz(sizeof(*chap)); + if (!new_extra) + return; - if (!new_extra || !chap) - goto fail; + chap = &new_extra->data.chap; if (decode_str(s, pb, 0, &chap->element_id, &len) < 0) goto fail; @@ -726,15 +721,13 @@ ff_metadata_conv(&chap->meta, NULL, ff_id3v2_4_metadata_conv); new_extra->tag = "CHAP"; - new_extra->data = chap; new_extra->next = *extra_meta; *extra_meta = new_extra; return; fail: - if (chap) - free_chapter(chap); + free_chapter(chap); av_freep(&new_extra); } @@ -743,7 +736,6 @@ ID3v2ExtraMetaPRIV *priv = obj; av_freep(&priv->owner); av_freep(&priv->data); - av_freep(&priv); } static void read_priv(AVFormatContext *s, AVIOContext *pb, int taglen, @@ -753,10 +745,10 @@ ID3v2ExtraMetaPRIV *priv; meta = av_mallocz(sizeof(*meta)); - priv = av_mallocz(sizeof(*priv)); + if (!meta) + return; - if (!meta || !priv) - goto fail; + priv = &meta->data.priv; if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &priv->owner, &taglen) < 0) goto fail; @@ -771,15 +763,13 @@ goto fail; meta->tag = "PRIV"; - meta->data = priv; meta->next = *extra_meta; *extra_meta = meta; return; fail: - if (priv) - free_priv(priv); + free_priv(priv); av_freep(&meta); } @@ -1006,6 +996,11 @@ av_log(s, AV_LOG_DEBUG, "Compresssed frame %s tlen=%d dlen=%ld\n", tag, tlen, dlen); + if (tlen <= 0) + goto seek; + if (dlen / 32768 > tlen) + goto seek; + av_fast_malloc(&uncompressed_buffer, &uncompressed_buffer_size, dlen); if (!uncompressed_buffer) { av_log(s, AV_LOG_ERROR, "Failed to alloc %ld bytes\n", dlen); @@ -1131,7 +1126,7 @@ while (current) { if ((extra_func = get_extra_meta_func(current->tag, 1))) - extra_func->free(current->data); + extra_func->free(¤t->data); next = current->next; av_freep(¤t); current = next; @@ -1140,17 +1135,17 @@ *extra_meta = NULL; } -int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta) +int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta *extra_meta) { ID3v2ExtraMeta *cur; - for (cur = *extra_meta; cur; cur = cur->next) { + for (cur = extra_meta; cur; cur = cur->next) { ID3v2ExtraMetaAPIC *apic; AVStream *st; if (strcmp(cur->tag, "APIC")) continue; - apic = cur->data; + apic = &cur->data.apic; if (!(st = avformat_new_stream(s, NULL))) return AVERROR(ENOMEM); @@ -1167,7 +1162,7 @@ av_dict_set(&st->metadata, "comment", apic->type, 0); - av_init_packet(&st->attached_pic); + av_packet_unref(&st->attached_pic); st->attached_pic.buf = apic->buf; st->attached_pic.data = apic->buf->data; st->attached_pic.size = apic->buf->size - AV_INPUT_BUFFER_PADDING_SIZE; @@ -1180,7 +1175,7 @@ return 0; } -int ff_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta **extra_meta) +int ff_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta *extra_meta) { int ret = 0; ID3v2ExtraMeta *cur; @@ -1191,12 +1186,12 @@ // since extra_meta is a linked list where elements are prepended, // we need to reverse the order of chapters - for (cur = *extra_meta; cur; cur = cur->next) { + for (cur = extra_meta; cur; cur = cur->next) { ID3v2ExtraMetaCHAP *chap; if (strcmp(cur->tag, "CHAP")) continue; - chap = cur->data; + chap = &cur->data.chap; if ((ret = av_dynarray_add_nofree(&chapters, &num_chapters, chap)) < 0) goto end; @@ -1231,14 +1226,14 @@ return ret; } -int ff_id3v2_parse_priv_dict(AVDictionary **metadata, ID3v2ExtraMeta **extra_meta) +int ff_id3v2_parse_priv_dict(AVDictionary **metadata, ID3v2ExtraMeta *extra_meta) { ID3v2ExtraMeta *cur; int dict_flags = AV_DICT_DONT_OVERWRITE | AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL; - for (cur = *extra_meta; cur; cur = cur->next) { + for (cur = extra_meta; cur; cur = cur->next) { if (!strcmp(cur->tag, "PRIV")) { - ID3v2ExtraMetaPRIV *priv = cur->data; + ID3v2ExtraMetaPRIV *priv = &cur->data.priv; AVBPrint bprint; char *escaped, *key; int i, ret; @@ -1271,7 +1266,7 @@ return 0; } -int ff_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta **extra_meta) +int ff_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta *extra_meta) { return ff_id3v2_parse_priv_dict(&s->metadata, extra_meta); } diff -Nru ffmpeg-4.2.2/libavformat/id3v2enc.c ffmpeg-4.4/libavformat/id3v2enc.c --- ffmpeg-4.2.2/libavformat/id3v2enc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/id3v2enc.c 2020-07-11 10:39:30.000000000 +0000 @@ -65,11 +65,11 @@ static int id3v2_put_ttag(ID3v2EncContext *id3, AVIOContext *avioc, const char *str1, const char *str2, uint32_t tag, enum ID3v2Encoding enc) { - int len; + int len, ret; uint8_t *pb; AVIOContext *dyn_buf; - if (avio_open_dyn_buf(&dyn_buf) < 0) - return AVERROR(ENOMEM); + if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0) + return ret; /* check if the strings are ASCII-only and use UTF16 only if * they're not */ @@ -81,7 +81,7 @@ id3v2_encode_string(dyn_buf, str1, enc); if (str2) id3v2_encode_string(dyn_buf, str2, enc); - len = avio_close_dyn_buf(dyn_buf, &pb); + len = avio_get_dyn_buf(dyn_buf, &pb); avio_wb32(avioc, tag); /* ID3v2.3 frame size is not sync-safe */ @@ -92,7 +92,7 @@ avio_wb16(avioc, 0); avio_write(avioc, pb, len); - av_freep(&pb); + ffio_free_dyn_buf(&dyn_buf); return len + ID3v2_HEADER_SIZE; } @@ -103,7 +103,7 @@ */ static int id3v2_put_priv(ID3v2EncContext *id3, AVIOContext *avioc, const char *key, const char *data) { - int len; + int len, ret; uint8_t *pb; AVIOContext *dyn_buf; @@ -111,8 +111,8 @@ return 0; } - if (avio_open_dyn_buf(&dyn_buf) < 0) - return AVERROR(ENOMEM); + if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0) + return ret; // owner + null byte. avio_write(dyn_buf, key, strlen(key) + 1); @@ -134,7 +134,7 @@ } } - len = avio_close_dyn_buf(dyn_buf, &pb); + len = avio_get_dyn_buf(dyn_buf, &pb); avio_wb32(avioc, MKBETAG('P', 'R', 'I', 'V')); if (id3->version == 3) @@ -144,7 +144,7 @@ avio_wb16(avioc, 0); avio_write(avioc, pb, len); - av_free(pb); + ffio_free_dyn_buf(&dyn_buf); return len + ID3v2_HEADER_SIZE; } @@ -257,8 +257,8 @@ static int write_ctoc(AVFormatContext *s, ID3v2EncContext *id3, int enc) { - uint8_t *dyn_buf = NULL; - AVIOContext *dyn_bc = NULL; + uint8_t *dyn_buf; + AVIOContext *dyn_bc; char name[123]; int len, ret; @@ -266,27 +266,24 @@ return 0; if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0) - goto fail; + return ret; - id3->len += avio_put_str(dyn_bc, "toc"); + avio_put_str(dyn_bc, "toc"); avio_w8(dyn_bc, 0x03); avio_w8(dyn_bc, s->nb_chapters); for (int i = 0; i < s->nb_chapters; i++) { snprintf(name, 122, "ch%d", i); - id3->len += avio_put_str(dyn_bc, name); + avio_put_str(dyn_bc, name); } - len = avio_close_dyn_buf(dyn_bc, &dyn_buf); - id3->len += 16 + ID3v2_HEADER_SIZE; + len = avio_get_dyn_buf(dyn_bc, &dyn_buf); + id3->len += len + ID3v2_HEADER_SIZE; avio_wb32(s->pb, MKBETAG('C', 'T', 'O', 'C')); avio_wb32(s->pb, len); avio_wb16(s->pb, 0); avio_write(s->pb, dyn_buf, len); -fail: - if (dyn_bc && !dyn_buf) - avio_close_dyn_buf(dyn_bc, &dyn_buf); - av_freep(&dyn_buf); + ffio_free_dyn_buf(&dyn_bc); return ret; } @@ -295,13 +292,13 @@ { const AVRational time_base = {1, 1000}; AVChapter *ch = s->chapters[id]; - uint8_t *dyn_buf = NULL; - AVIOContext *dyn_bc = NULL; + uint8_t *dyn_buf; + AVIOContext *dyn_bc; char name[123]; int len, start, end, ret; if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0) - goto fail; + return ret; start = av_rescale_q(ch->start, ch->time_base, time_base); end = av_rescale_q(ch->end, ch->time_base, time_base); @@ -316,7 +313,7 @@ if ((ret = write_metadata(dyn_bc, &ch->metadata, id3, enc)) < 0) goto fail; - len = avio_close_dyn_buf(dyn_bc, &dyn_buf); + len = avio_get_dyn_buf(dyn_bc, &dyn_buf); id3->len += 16 + ID3v2_HEADER_SIZE; avio_wb32(s->pb, MKBETAG('C', 'H', 'A', 'P')); @@ -325,9 +322,7 @@ avio_write(s->pb, dyn_buf, len); fail: - if (dyn_bc && !dyn_buf) - avio_close_dyn_buf(dyn_bc, &dyn_buf); - av_freep(&dyn_buf); + ffio_free_dyn_buf(&dyn_bc); return ret; } @@ -364,7 +359,7 @@ const char *mimetype = NULL, *desc = ""; int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM : ID3v2_ENCODING_UTF8; - int i, len, type = 0; + int i, len, type = 0, ret; /* get the mimetype*/ while (mime->id != AV_CODEC_ID_NONE) { @@ -398,15 +393,15 @@ enc = ID3v2_ENCODING_ISO8859; /* start writing */ - if (avio_open_dyn_buf(&dyn_buf) < 0) - return AVERROR(ENOMEM); + if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0) + return ret; avio_w8(dyn_buf, enc); avio_put_str(dyn_buf, mimetype); avio_w8(dyn_buf, type); id3v2_encode_string(dyn_buf, desc, enc); avio_write(dyn_buf, pkt->data, pkt->size); - len = avio_close_dyn_buf(dyn_buf, &buf); + len = avio_get_dyn_buf(dyn_buf, &buf); avio_wb32(s->pb, MKBETAG('A', 'P', 'I', 'C')); if (id3->version == 3) @@ -415,7 +410,7 @@ id3v2_put_size(s->pb, len); avio_wb16(s->pb, 0); avio_write(s->pb, buf, len); - av_freep(&buf); + ffio_free_dyn_buf(&dyn_buf); id3->len += len + ID3v2_HEADER_SIZE; diff -Nru ffmpeg-4.2.2/libavformat/id3v2.h ffmpeg-4.4/libavformat/id3v2.h --- ffmpeg-4.2.2/libavformat/id3v2.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/id3v2.h 2020-07-11 10:39:30.000000000 +0000 @@ -54,12 +54,6 @@ int len; ///< size of the tag written so far } ID3v2EncContext; -typedef struct ID3v2ExtraMeta { - const char *tag; - void *data; - struct ID3v2ExtraMeta *next; -} ID3v2ExtraMeta; - typedef struct ID3v2ExtraMetaGEOB { uint32_t datasize; uint8_t *mime_type; @@ -87,6 +81,17 @@ AVDictionary *meta; } ID3v2ExtraMetaCHAP; +typedef struct ID3v2ExtraMeta { + const char *tag; + struct ID3v2ExtraMeta *next; + union { + ID3v2ExtraMetaAPIC apic; + ID3v2ExtraMetaCHAP chap; + ID3v2ExtraMetaGEOB geob; + ID3v2ExtraMetaPRIV priv; + } data; +} ID3v2ExtraMeta; + /** * Detect ID3v2 Header. * @param buf must be ID3v2_HEADER_SIZE byte long @@ -162,25 +167,25 @@ * Create a stream for each APIC (attached picture) extracted from the * ID3v2 header. */ -int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta); +int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta *extra_meta); /** * Create chapters for all CHAP tags found in the ID3v2 header. */ -int ff_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta **extra_meta); +int ff_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta *extra_meta); /** * Parse PRIV tags into a dictionary. The PRIV owner is the metadata key. The * PRIV data is the value, with non-printable characters escaped. */ -int ff_id3v2_parse_priv_dict(AVDictionary **d, ID3v2ExtraMeta **extra_meta); +int ff_id3v2_parse_priv_dict(AVDictionary **d, ID3v2ExtraMeta *extra_meta); /** * Add metadata for all PRIV tags in the ID3v2 header. The PRIV owner is the * metadata key. The PRIV data is the value, with non-printable characters * escaped. */ -int ff_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta **extra_meta); +int ff_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta *extra_meta); extern const AVMetadataConv ff_id3v2_34_metadata_conv[]; extern const AVMetadataConv ff_id3v2_4_metadata_conv[]; diff -Nru ffmpeg-4.2.2/libavformat/idcin.c ffmpeg-4.4/libavformat/idcin.c --- ffmpeg-4.2.2/libavformat/idcin.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/idcin.c 2020-07-11 10:39:30.000000000 +0000 @@ -313,7 +313,6 @@ return ret; else if (ret != chunk_size) { av_log(s, AV_LOG_ERROR, "incomplete packet\n"); - av_packet_unref(pkt); return AVERROR(EIO); } if (command == 1) { @@ -322,7 +321,6 @@ pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); if (!pal) { - av_packet_unref(pkt); return AVERROR(ENOMEM); } memcpy(pal, palette, AVPALETTE_SIZE); diff -Nru ffmpeg-4.2.2/libavformat/idroqdec.c ffmpeg-4.4/libavformat/idroqdec.c --- ffmpeg-4.2.2/libavformat/idroqdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/idroqdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -205,8 +205,9 @@ } /* load up the packet */ - if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE)) - return AVERROR(EIO); + ret = av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE); + if (ret < 0) + return ret; /* copy over preamble */ memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE); @@ -223,8 +224,7 @@ ret = avio_read(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE, chunk_size); if (ret != chunk_size) { - av_packet_unref(pkt); - ret = AVERROR(EIO); + return AVERROR(EIO); } packet_read = 1; diff -Nru ffmpeg-4.2.2/libavformat/idroqenc.c ffmpeg-4.4/libavformat/idroqenc.c --- ffmpeg-4.2.2/libavformat/idroqenc.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/idroqenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -55,7 +55,6 @@ } avio_write(s->pb, header, 8); - avio_flush(s->pb); return 0; } diff -Nru ffmpeg-4.2.2/libavformat/iff.c ffmpeg-4.4/libavformat/iff.c --- ffmpeg-4.2.2/libavformat/iff.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/iff.c 2021-02-20 20:27:47.000000000 +0000 @@ -223,6 +223,9 @@ uint64_t orig_pos = avio_tell(pb); const char * metadata_tag = NULL; + if (size >= INT64_MAX) + return AVERROR_INVALIDDATA; + switch(tag) { case MKTAG('D','I','A','R'): metadata_tag = "artist"; break; case MKTAG('D','I','T','I'): metadata_tag = "title"; break; @@ -256,6 +259,9 @@ uint64_t size = avio_rb64(pb); uint64_t orig_pos = avio_tell(pb); + if (size >= INT64_MAX) + return AVERROR_INVALIDDATA; + switch(tag) { case MKTAG('A','B','S','S'): if (size < 8) @@ -312,8 +318,8 @@ id3v2_extra_meta = NULL; ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size); if (id3v2_extra_meta) { - if ((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0 || - (ret = ff_id3v2_parse_chapters(s, &id3v2_extra_meta)) < 0) { + if ((ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0 || + (ret = ff_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0) { ff_id3v2_free_extra_meta(&id3v2_extra_meta); return ret; } @@ -362,7 +368,7 @@ data_size = iff->is_64bit ? avio_rb64(pb) : avio_rb32(pb); data_pos = avio_tell(pb); - if (data_size < 1) + if (data_size < 1 || data_size >= INT64_MAX) return AVERROR_INVALIDDATA; switch (chunk_id) { @@ -449,6 +455,9 @@ data_size = iff->is_64bit ? avio_rb64(pb) : avio_rb32(pb); orig_pos = avio_tell(pb); + if (data_size >= INT64_MAX) + return AVERROR_INVALIDDATA; + switch(chunk_id) { case ID_VHDR: st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; @@ -525,12 +534,15 @@ data_size); return AVERROR_INVALIDDATA; } - st->codecpar->extradata_size = data_size + IFF_EXTRA_VIDEO_SIZE; - st->codecpar->extradata = av_malloc(data_size + IFF_EXTRA_VIDEO_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); - if (!st->codecpar->extradata) - return AVERROR(ENOMEM); - if (avio_read(pb, st->codecpar->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0) + res = ff_alloc_extradata(st->codecpar, + data_size + IFF_EXTRA_VIDEO_SIZE); + if (res < 0) + return res; + if (avio_read(pb, st->codecpar->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0) { + av_freep(&st->codecpar->extradata); + st->codecpar->extradata_size = 0; return AVERROR(EIO); + } break; case ID_BMHD: @@ -751,7 +763,7 @@ st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id); st->codecpar->bit_rate = (int64_t)st->codecpar->channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample; - if (st->codecpar->codec_tag == ID_DSD && st->codecpar->block_align <= 0) + if ((st->codecpar->codec_tag == ID_DSD || st->codecpar->codec_tag == ID_MAUD) && st->codecpar->block_align <= 0) return AVERROR_INVALIDDATA; break; @@ -768,10 +780,9 @@ iff->transparency = transparency; if (!st->codecpar->extradata) { - st->codecpar->extradata_size = IFF_EXTRA_VIDEO_SIZE; - st->codecpar->extradata = av_malloc(IFF_EXTRA_VIDEO_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); - if (!st->codecpar->extradata) - return AVERROR(ENOMEM); + int ret = ff_alloc_extradata(st->codecpar, IFF_EXTRA_VIDEO_SIZE); + if (ret < 0) + return ret; } av_assert0(st->codecpar->extradata_size >= IFF_EXTRA_VIDEO_SIZE); buf = st->codecpar->extradata; @@ -834,7 +845,7 @@ } else if (st->codecpar->codec_tag == ID_DST) { return read_dst_frame(s, pkt); } else { - if (iff->body_size > INT_MAX) + if (iff->body_size > INT_MAX || !iff->body_size) return AVERROR_INVALIDDATA; ret = av_get_packet(pb, pkt, iff->body_size); } @@ -870,6 +881,8 @@ pkt->flags |= AV_PKT_FLAG_KEY; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->codecpar->codec_tag != ID_ANIM) { + if (iff->body_size > INT_MAX || !iff->body_size) + return AVERROR_INVALIDDATA; ret = av_get_packet(pb, pkt, iff->body_size); pkt->pos = pos; if (pos == iff->body_pos) diff -Nru ffmpeg-4.2.2/libavformat/ifv.c ffmpeg-4.4/libavformat/ifv.c --- ffmpeg-4.2.2/libavformat/ifv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ifv.c 2021-02-20 20:27:47.000000000 +0000 @@ -210,6 +210,7 @@ } if (!ev) { + uint64_t vframes, aframes; if (ifv->is_audio_present && !ea) { /*read new video and audio indexes*/ @@ -217,8 +218,12 @@ ifv->next_audio_index = ifv->total_aframes; avio_skip(s->pb, 0x1c); - ifv->total_vframes += avio_rl32(s->pb); - ifv->total_aframes += avio_rl32(s->pb); + vframes = ifv->total_vframes + (uint64_t)avio_rl32(s->pb); + aframes = ifv->total_aframes + (uint64_t)avio_rl32(s->pb); + if (vframes > INT_MAX || aframes > INT_MAX) + return AVERROR_INVALIDDATA; + ifv->total_vframes = vframes; + ifv->total_aframes = aframes; avio_skip(s->pb, 0xc); if (avio_feof(s->pb)) @@ -240,7 +245,10 @@ ifv->next_video_index = ifv->total_vframes; avio_skip(s->pb, 0x1c); - ifv->total_vframes += avio_rl32(s->pb); + vframes = ifv->total_vframes + (uint64_t)avio_rl32(s->pb); + if (vframes > INT_MAX) + return AVERROR_INVALIDDATA; + ifv->total_vframes = vframes; avio_skip(s->pb, 0x10); if (avio_feof(s->pb)) diff -Nru ffmpeg-4.2.2/libavformat/ilbc.c ffmpeg-4.4/libavformat/ilbc.c --- ffmpeg-4.2.2/libavformat/ilbc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ilbc.c 2020-07-11 10:39:30.000000000 +0000 @@ -21,6 +21,7 @@ #include "avformat.h" #include "internal.h" +#include "rawenc.h" static const char mode20_header[] = "#!iLBC20\n"; static const char mode30_header[] = "#!iLBC30\n"; @@ -49,13 +50,6 @@ av_log(s, AV_LOG_ERROR, "Unsupported mode\n"); return AVERROR(EINVAL); } - avio_flush(pb); - return 0; -} - -static int ilbc_write_packet(AVFormatContext *s, AVPacket *pkt) -{ - avio_write(s->pb, pkt->data, pkt->size); return 0; } @@ -112,7 +106,6 @@ pkt->pos = avio_tell(s->pb); pkt->duration = par->block_align == 38 ? 160 : 240; if ((ret = avio_read(s->pb, pkt->data, par->block_align)) != par->block_align) { - av_packet_unref(pkt); return ret < 0 ? ret : AVERROR(EIO); } @@ -128,6 +121,7 @@ .flags = AVFMT_GENERIC_INDEX, }; +#if CONFIG_ILBC_MUXER AVOutputFormat ff_ilbc_muxer = { .name = "ilbc", .long_name = NULL_IF_CONFIG_SMALL("iLBC storage"), @@ -135,6 +129,7 @@ .extensions = "lbc", .audio_codec = AV_CODEC_ID_ILBC, .write_header = ilbc_write_header, - .write_packet = ilbc_write_packet, + .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; +#endif diff -Nru ffmpeg-4.2.2/libavformat/img2.c ffmpeg-4.4/libavformat/img2.c --- ffmpeg-4.2.2/libavformat/img2.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/img2.c 2021-04-08 21:28:40.000000000 +0000 @@ -40,6 +40,8 @@ { AV_CODEC_ID_PGMYUV, "pgmyuv" }, { AV_CODEC_ID_PBM, "pbm" }, { AV_CODEC_ID_PAM, "pam" }, + { AV_CODEC_ID_PFM, "pfm" }, + { AV_CODEC_ID_CRI, "cri" }, { AV_CODEC_ID_ALIAS_PIX, "pix" }, { AV_CODEC_ID_DDS, "dds" }, { AV_CODEC_ID_MPEG1VIDEO, "mpg1-img" }, @@ -54,6 +56,7 @@ { AV_CODEC_ID_TIFF, "dng" }, { AV_CODEC_ID_SGI, "sgi" }, { AV_CODEC_ID_PTX, "ptx" }, + { AV_CODEC_ID_PHOTOCD, "pcd" }, { AV_CODEC_ID_PCX, "pcx" }, { AV_CODEC_ID_QDRAW, "pic" }, { AV_CODEC_ID_QDRAW, "pct" }, diff -Nru ffmpeg-4.2.2/libavformat/img2dec.c ffmpeg-4.4/libavformat/img2dec.c --- ffmpeg-4.2.2/libavformat/img2dec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/img2dec.c 2021-04-08 21:28:40.000000000 +0000 @@ -220,8 +220,10 @@ avpriv_set_pts_info(st, 64, 1, 1000000000); } else if (s->ts_from_file) avpriv_set_pts_info(st, 64, 1, 1); - else + else { avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num); + st->avg_frame_rate = s->framerate; + } if (s->width && s->height) { st->codecpar->width = s->width; @@ -374,6 +376,32 @@ return 0; } +/** + * Add this frame's source path and basename to packet's sidedata + * as a dictionary, so it can be used by filters like 'drawtext'. + */ +static int add_filename_as_pkt_side_data(char *filename, AVPacket *pkt) { + AVDictionary *d = NULL; + char *packed_metadata = NULL; + buffer_size_t metadata_len; + int ret; + + av_dict_set(&d, "lavf.image2dec.source_path", filename, 0); + av_dict_set(&d, "lavf.image2dec.source_basename", av_basename(filename), 0); + + packed_metadata = av_packet_pack_dictionary(d, &metadata_len); + av_dict_free(&d); + if (!packed_metadata) + return AVERROR(ENOMEM); + ret = av_packet_add_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, + packed_metadata, metadata_len); + if (ret < 0) { + av_freep(&packed_metadata); + return ret; + } + return 0; +} + int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt) { VideoDemuxData *s = s1->priv_data; @@ -486,6 +514,17 @@ if (s->is_pipe) pkt->pos = avio_tell(f[0]); + /* + * export_path_metadata must be explicitly enabled via + * command line options for path metadata to be exported + * as packet side_data. + */ + if (!s->is_pipe && s->export_path_metadata == 1) { + res = add_filename_as_pkt_side_data(filename, pkt); + if (res < 0) + goto fail; + } + pkt->size = 0; for (i = 0; i < 3; i++) { if (f[i]) { @@ -504,7 +543,6 @@ } if (ret[0] <= 0 || ret[1] < 0 || ret[2] < 0) { - av_packet_unref(pkt); if (ret[0] < 0) { res = ret[0]; } else if (ret[1] < 0) { @@ -585,6 +623,7 @@ { "none", "none", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 2, DEC, "ts_type" }, { "sec", "second precision", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 2, DEC, "ts_type" }, { "ns", "nano second precision", 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 2, DEC, "ts_type" }, + { "export_path_metadata", "enable metadata containing input path information", OFFSET(export_path_metadata), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, DEC }, \ COMMON_OPTIONS }; @@ -648,6 +687,17 @@ return AVPROBE_SCORE_EXTENSION / 4; } +static int cri_probe(const AVProbeData *p) +{ + const uint8_t *b = p->buf; + + if ( AV_RL32(b) == 1 + && AV_RL32(b + 4) == 4 + && AV_RN32(b + 8) == AV_RN32("DVCC")) + return AVPROBE_SCORE_MAX - 1; + return 0; +} + static int dds_probe(const AVProbeData *p) { const uint8_t *b = p->buf; @@ -768,7 +818,7 @@ return AVPROBE_SCORE_EXTENSION + 1; if (state == SOS) return AVPROBE_SCORE_EXTENSION / 2; - return AVPROBE_SCORE_EXTENSION / 8; + return AVPROBE_SCORE_EXTENSION / 8 + 1; } static int jpegls_probe(const AVProbeData *p) @@ -944,7 +994,7 @@ static int pbm_probe(const AVProbeData *p) { - return pnm_magic_check(p, 1) || pnm_magic_check(p, 4) ? pnm_probe(p) : 0; + return pnm_magic_check(p, 1) || pnm_magic_check(p, 4) || pnm_magic_check(p, 22) || pnm_magic_check(p, 54) ? pnm_probe(p) : 0; } static inline int pgmx_probe(const AVProbeData *p) @@ -964,6 +1014,14 @@ return ret && av_match_ext(p->filename, "pgmyuv") ? ret : 0; } +static int pgx_probe(const AVProbeData *p) +{ + const uint8_t *b = p->buf; + if (!memcmp(b, "PG ML ", 6)) + return AVPROBE_SCORE_EXTENSION + 1; + return 0; +} + static int ppm_probe(const AVProbeData *p) { return pnm_magic_check(p, 3) || pnm_magic_check(p, 6) ? pnm_probe(p) : 0; @@ -974,6 +1032,16 @@ return pnm_magic_check(p, 7) ? pnm_probe(p) : 0; } +static int xbm_probe(const AVProbeData *p) +{ + if (!memcmp(p->buf, "/* XBM X10 format */", 20)) + return AVPROBE_SCORE_MAX; + + if (!memcmp(p->buf, "#define", 7)) + return AVPROBE_SCORE_MAX - 1; + return 0; +} + static int xpm_probe(const AVProbeData *p) { const uint8_t *b = p->buf; @@ -1026,6 +1094,17 @@ return AVPROBE_SCORE_MAX - 1; } +static int photocd_probe(const AVProbeData *p) +{ + if (!memcmp(p->buf, "PCD_OPA", 7)) + return AVPROBE_SCORE_MAX - 1; + + if (p->buf_size < 0x807 || memcmp(p->buf + 0x800, "PCD_IPI", 7)) + return 0; + + return AVPROBE_SCORE_MAX - 1; +} + #define IMAGEAUTO_DEMUXER(imgname, codecid)\ static const AVClass imgname ## _class = {\ .class_name = AV_STRINGIFY(imgname) " demuxer",\ @@ -1046,6 +1125,7 @@ }; 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) @@ -1058,6 +1138,8 @@ 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) @@ -1068,5 +1150,6 @@ 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) diff -Nru ffmpeg-4.2.2/libavformat/img2enc.c ffmpeg-4.4/libavformat/img2enc.c --- ffmpeg-4.2.2/libavformat/img2enc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/img2enc.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/dict.h" #include "libavutil/log.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -35,7 +36,6 @@ typedef struct VideoMuxData { const AVClass *class; /**< Class for private options. */ int img_number; - int is_pipe; int split_planes; /**< use independent file for each Y, U, V plane */ char path[1024]; char tmp[4][1024]; @@ -45,6 +45,7 @@ int frame_pts; const char *muxer; int use_rename; + AVDictionary *protocol_opts; } VideoMuxData; static int write_header(AVFormatContext *s) @@ -55,12 +56,6 @@ av_strlcpy(img->path, s->url, sizeof(img->path)); - /* find format */ - if (s->oformat->flags & AVFMT_NOFILE) - img->is_pipe = 0; - else - img->is_pipe = 1; - if (st->codecpar->codec_id == AV_CODEC_ID_GIF) { img->muxer = "gif"; } else if (st->codecpar->codec_id == AV_CODEC_ID_FITS) { @@ -78,60 +73,116 @@ return 0; } +static int write_muxed_file(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt) +{ + VideoMuxData *img = s->priv_data; + AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + AVStream *st; + AVPacket pkt2; + AVFormatContext *fmt = NULL; + int ret; + + /* URL is not used directly as we are overriding the IO context later. */ + ret = avformat_alloc_output_context2(&fmt, NULL, img->muxer, s->url); + if (ret < 0) + return ret; + st = avformat_new_stream(fmt, NULL); + if (!st) { + ret = AVERROR(ENOMEM); + goto out; + } + st->id = pkt->stream_index; + + fmt->pb = pb; + + ret = av_packet_ref(&pkt2, pkt); + if (ret < 0) + goto out; + pkt2.stream_index = 0; + + if ((ret = avcodec_parameters_copy(st->codecpar, par)) < 0 || + (ret = avformat_write_header(fmt, NULL)) < 0 || + (ret = av_interleaved_write_frame(fmt, &pkt2)) < 0 || + (ret = av_write_trailer(fmt))) {} + + av_packet_unref(&pkt2); +out: + avformat_free_context(fmt); + return ret; +} + +static int write_packet_pipe(AVFormatContext *s, AVPacket *pkt) +{ + VideoMuxData *img = s->priv_data; + if (img->muxer) { + int ret = write_muxed_file(s, s->pb, pkt); + if (ret < 0) + return ret; + } else { + avio_write(s->pb, pkt->data, pkt->size); + } + img->img_number++; + return 0; +} + static int write_packet(AVFormatContext *s, AVPacket *pkt) { VideoMuxData *img = s->priv_data; - AVIOContext *pb[4]; + AVIOContext *pb[4] = {0}; char filename[1024]; AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); - int i; + int ret, i; int nb_renames = 0; + AVDictionary *options = NULL; - if (!img->is_pipe) { - if (img->update) { - av_strlcpy(filename, img->path, 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)) { - av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); - return AVERROR(EINVAL); - } - } else if (img->frame_pts) { - if (av_get_frame_filename2(filename, sizeof(filename), img->path, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { - av_log(s, AV_LOG_ERROR, "Cannot write filename by pts of the frames."); - return AVERROR(EINVAL); - } - } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, - img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && - 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); + if (img->update) { + av_strlcpy(filename, img->path, 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)) { + av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); return AVERROR(EINVAL); } - for (i = 0; i < 4; i++) { - snprintf(img->tmp[i], sizeof(img->tmp[i]), "%s.tmp", filename); - av_strlcpy(img->target[i], filename, sizeof(img->target[i])); - if (s->io_open(s, &pb[i], img->use_rename ? img->tmp[i] : filename, AVIO_FLAG_WRITE, NULL) < 0) { - av_log(s, AV_LOG_ERROR, "Could not open file : %s\n", img->use_rename ? img->tmp[i] : filename); - return AVERROR(EIO); - } - - if (!img->split_planes || i+1 >= desc->nb_components) - break; - filename[strlen(filename) - 1] = "UVAx"[i]; + } else if (img->frame_pts) { + if (av_get_frame_filename2(filename, sizeof(filename), img->path, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + av_log(s, AV_LOG_ERROR, "Cannot write filename by pts of the frames."); + return AVERROR(EINVAL); } - if (img->use_rename) - nb_renames = i + 1; - } else { - pb[0] = s->pb; + } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, + 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); + return AVERROR(EINVAL); } + for (i = 0; i < 4; i++) { + av_dict_copy(&options, img->protocol_opts, 0); + snprintf(img->tmp[i], sizeof(img->tmp[i]), "%s.tmp", filename); + av_strlcpy(img->target[i], filename, sizeof(img->target[i])); + if (s->io_open(s, &pb[i], img->use_rename ? img->tmp[i] : filename, AVIO_FLAG_WRITE, &options) < 0) { + av_log(s, AV_LOG_ERROR, "Could not open file : %s\n", img->use_rename ? img->tmp[i] : filename); + ret = AVERROR(EIO); + goto fail; + } + if (options) { + av_log(s, AV_LOG_ERROR, "Could not recognize some protocol options\n"); + ret = AVERROR(EINVAL); + goto fail; + } + + if (!img->split_planes || i+1 >= desc->nb_components) + break; + filename[strlen(filename) - 1] = "UVAx"[i]; + } + if (img->use_rename) + nb_renames = i + 1; if (img->split_planes) { int ysize = par->width * par->height; @@ -150,50 +201,29 @@ ff_format_io_close(s, &pb[3]); } } else if (img->muxer) { - int ret; - AVStream *st; - AVPacket pkt2 = {0}; - AVFormatContext *fmt = NULL; - - av_assert0(!img->split_planes); - - ret = avformat_alloc_output_context2(&fmt, NULL, img->muxer, s->url); + ret = write_muxed_file(s, pb[0], pkt); if (ret < 0) - return ret; - st = avformat_new_stream(fmt, NULL); - if (!st) { - avformat_free_context(fmt); - return AVERROR(ENOMEM); - } - st->id = pkt->stream_index; - - fmt->pb = pb[0]; - if ((ret = av_packet_ref(&pkt2, pkt)) < 0 || - (ret = avcodec_parameters_copy(st->codecpar, s->streams[0]->codecpar)) < 0 || - (ret = avformat_write_header(fmt, NULL)) < 0 || - (ret = av_interleaved_write_frame(fmt, &pkt2)) < 0 || - (ret = av_write_trailer(fmt)) < 0) { - av_packet_unref(&pkt2); - avformat_free_context(fmt); - return ret; - } - av_packet_unref(&pkt2); - avformat_free_context(fmt); + goto fail; } else { avio_write(pb[0], pkt->data, pkt->size); } avio_flush(pb[0]); - if (!img->is_pipe) { - ff_format_io_close(s, &pb[0]); - for (i = 0; i < nb_renames; i++) { - int ret = ff_rename(img->tmp[i], img->target[i], s); - if (ret < 0) - return ret; - } + ff_format_io_close(s, &pb[0]); + for (i = 0; i < nb_renames; i++) { + int ret = ff_rename(img->tmp[i], img->target[i], s); + if (ret < 0) + return ret; } img->img_number++; return 0; + +fail: + av_dict_free(&options); + for (i = 0; i < FF_ARRAY_ELEMS(pb); i++) + if (pb[i]) + ff_format_io_close(s, &pb[i]); + return ret; } static int query_codec(enum AVCodecID id, int std_compliance) @@ -215,6 +245,7 @@ { "strftime", "use strftime for filename", OFFSET(use_strftime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC }, { "frame_pts", "use current frame pts for filename", OFFSET(frame_pts), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC }, { "atomic_writing", "write files atomically (using temporary files and renames)", OFFSET(use_rename), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC }, + { "protocol_opts", "specify protocol options for the opened files", OFFSET(protocol_opts), AV_OPT_TYPE_DICT, {0}, 0, 0, ENC }, { NULL }, }; @@ -229,7 +260,7 @@ AVOutputFormat ff_image2_muxer = { .name = "image2", .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"), - .extensions = "bmp,dpx,jls,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png," + .extensions = "bmp,dpx,exr,jls,jpeg,jpg,ljpg,pam,pbm,pcx,pfm,pgm,pgmyuv,png," "ppm,sgi,tga,tif,tiff,jp2,j2c,j2k,xwd,sun,ras,rs,im1,im8,im24," "sunras,xbm,xface,pix,y", .priv_data_size = sizeof(VideoMuxData), @@ -248,7 +279,7 @@ .priv_data_size = sizeof(VideoMuxData), .video_codec = AV_CODEC_ID_MJPEG, .write_header = write_header, - .write_packet = write_packet, + .write_packet = write_packet_pipe, .query_codec = query_codec, .flags = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS }; diff -Nru ffmpeg-4.2.2/libavformat/img2.h ffmpeg-4.4/libavformat/img2.h --- ffmpeg-4.2.2/libavformat/img2.h 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavformat/img2.h 2020-07-11 10:39:30.000000000 +0000 @@ -61,6 +61,7 @@ int start_number_range; int frame_size; int ts_from_file; + int export_path_metadata; /**< enabled when set to 1. */ } VideoDemuxData; typedef struct IdStrMap { diff -Nru ffmpeg-4.2.2/libavformat/imx.c ffmpeg-4.4/libavformat/imx.c --- ffmpeg-4.2.2/libavformat/imx.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/imx.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,168 @@ +/* + * Simbiosis game demuxer + * + * 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 "avformat.h" +#include "internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/avassert.h" +#include "libavutil/internal.h" + +#define IMX_TAG MKTAG('I', 'M', 'A', 'X') + +typedef struct SimbiosisIMXDemuxContext { + uint8_t pal[AVPALETTE_SIZE]; + int pal_changed; + int64_t first_video_packet_pos; +} SimbiosisIMXDemuxContext; + +static int simbiosis_imx_probe(const AVProbeData *p) +{ + if (AV_RL32(p->buf) != IMX_TAG) + return 0; + if (AV_RN32(p->buf+4) == 0) + return 0; + if (AV_RN16(p->buf+8) == 0) + return 0; + if (AV_RL16(p->buf+10) != 0x102) + return 0; + + return AVPROBE_SCORE_EXTENSION + 10; +} + +static int simbiosis_imx_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + AVStream *vst, *ast; + int rate; + + vst = avformat_new_stream(s, NULL); + ast = avformat_new_stream(s, NULL); + if (!vst || !ast) + return AVERROR(ENOMEM); + + avio_skip(pb, 4); + + vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codecpar->codec_tag = 0; + vst->codecpar->format = AV_PIX_FMT_PAL8; + vst->codecpar->codec_id = AV_CODEC_ID_SIMBIOSIS_IMX; + vst->start_time = 0; + vst->duration = + vst->nb_frames = avio_rl32(pb); + rate = avio_rl16(pb); + avio_skip(pb, 12); + + avpriv_set_pts_info(vst, 64, 1, rate); + + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codecpar->codec_tag = 0; + ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; + ast->codecpar->channels = 1; + ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->sample_rate = 22050; + ast->start_time = 0; + + avpriv_set_pts_info(ast, 64, 1, 22050); + + return 0; +} + +static int simbiosis_imx_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVIOContext *pb = s->pb; + SimbiosisIMXDemuxContext *imx = s->priv_data; + uint32_t chunk_size, chunk_type; + int64_t pos = avio_tell(pb); + int ret, idx = -1; + +retry: + if (avio_feof(pb)) + return AVERROR_EOF; + + chunk_size = avio_rl32(pb); + chunk_type = avio_rl32(pb); + + switch (chunk_type) { + case 0xAAFF: + return AVERROR_EOF; + case 0xAA99: + idx = 1; + break; + case 0xAA97: + idx = 0; + if (!imx->first_video_packet_pos) + imx->first_video_packet_pos = pos; + break; + case 0xAA98: + if (chunk_size > 256 * 3) + return AVERROR_INVALIDDATA; + for (int i = 0; i < chunk_size / 3; i++) { + unsigned r = avio_r8(pb) << 18; + unsigned g = avio_r8(pb) << 10; + unsigned b = avio_r8(pb) << 2; + + AV_WL32(imx->pal + i * 4, (0xFFU << 24) | r | g | b); + } + imx->pal_changed = 1; + idx = -1; + break; + default: + return AVERROR_INVALIDDATA; + } + + if (idx == -1) + goto retry; + + ret = av_get_packet(pb, pkt, chunk_size); + if (ret < 0) + return ret; + + if (imx->pal_changed && idx == 0) { + uint8_t *pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, + AVPALETTE_SIZE); + if (!pal) + return AVERROR(ENOMEM); + memcpy(pal, imx->pal, AVPALETTE_SIZE); + imx->pal_changed = 0; + if (pos <= imx->first_video_packet_pos) + pkt->flags |= AV_PKT_FLAG_KEY; + } else if (idx == 1) { + pkt->flags |= AV_PKT_FLAG_KEY; + } + + pkt->pos = pos; + pkt->stream_index = idx; + pkt->duration = idx ? chunk_size : 1; + + return ret; +} + +AVInputFormat ff_simbiosis_imx_demuxer = { + .name = "simbiosis_imx", + .long_name = NULL_IF_CONFIG_SMALL("Simbiosis Interactive IMX"), + .priv_data_size = sizeof(SimbiosisIMXDemuxContext), + .read_probe = simbiosis_imx_probe, + .read_header = simbiosis_imx_read_header, + .read_packet = simbiosis_imx_read_packet, + .extensions = "imx", + .flags = AVFMT_GENERIC_INDEX, +}; diff -Nru ffmpeg-4.2.2/libavformat/internal.h ffmpeg-4.4/libavformat/internal.h --- ffmpeg-4.2.2/libavformat/internal.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/internal.h 2021-04-08 21:28:40.000000000 +0000 @@ -33,8 +33,6 @@ #define PROBE_BUF_MIN 2048 #define PROBE_BUF_MAX (1 << 20) -#define MAX_PROBE_PACKETS 2500 - #ifdef DEBUG # define hex_dump_debug(class, buf, size) av_hex_dump_log(class, AV_LOG_DEBUG, buf, size) #else @@ -75,8 +73,8 @@ * not decoded, for example to get the codec parameters in MPEG * streams. */ - struct AVPacketList *packet_buffer; - struct AVPacketList *packet_buffer_end; + struct PacketList *packet_buffer; + struct PacketList *packet_buffer_end; /* av_seek_frame() support */ int64_t data_offset; /**< offset of the first packet */ @@ -87,13 +85,19 @@ * be identified, as parsing cannot be done without knowing the * codec. */ - struct AVPacketList *raw_packet_buffer; - struct AVPacketList *raw_packet_buffer_end; + struct PacketList *raw_packet_buffer; + struct PacketList *raw_packet_buffer_end; /** * Packets split by the parser get queued here. */ - struct AVPacketList *parse_queue; - struct AVPacketList *parse_queue_end; + AVPacket *parse_pkt; + struct PacketList *parse_queue; + struct PacketList *parse_queue_end; + + /** + * Used to hold temporary packets. + */ + AVPacket *pkt; /** * Remaining size available for raw_packet_buffer, in bytes. */ @@ -144,6 +148,11 @@ * Prefer the codec framerate for avg_frame_rate computation. */ int prefer_codec_framerate; + + /** + * Set if chapter ids are strictly monotonic. + */ + int chapter_ids_monotonic; }; struct AVStreamInternal { @@ -154,12 +163,11 @@ int reorder; /** - * bitstream filters to run on stream + * bitstream filter to run on stream * - encoding: Set by muxer using ff_stream_add_bitstream_filter * - decoding: unused */ - AVBSFContext **bsfcs; - int nb_bsfcs; + AVBSFContext *bsfc; /** * Whether or not check_bitstream should still be run on each packet @@ -191,7 +199,156 @@ */ int need_context_update; + int is_intra_only; + FFFrac *priv_pts; + +#define MAX_STD_TIMEBASES (30*12+30+3+6) + /** + * Stream information used internally by avformat_find_stream_info() + */ + struct { + int64_t last_dts; + int64_t duration_gcd; + int duration_count; + int64_t rfps_duration_sum; + double (*duration_error)[2][MAX_STD_TIMEBASES]; + int64_t codec_info_duration; + int64_t codec_info_duration_fields; + int frame_delay_evidence; + + /** + * 0 -> decoder has not been searched for yet. + * >0 -> decoder found + * <0 -> decoder with codec_id == -found_decoder has not been found + */ + int found_decoder; + + int64_t last_duration; + + /** + * Those are used for average framerate estimation. + */ + int64_t fps_first_dts; + int fps_first_dts_idx; + int64_t fps_last_dts; + int fps_last_dts_idx; + + } *info; + + int64_t interleaver_chunk_size; + int64_t interleaver_chunk_duration; + + /** + * stream probing state + * -1 -> probing finished + * 0 -> no probing requested + * rest -> perform probing with request_probe being the minimum score to accept. + */ + int request_probe; + /** + * Indicates that everything up to the next keyframe + * should be discarded. + */ + int skip_to_keyframe; + + /** + * Number of samples to skip at the start of the frame decoded from the next packet. + */ + int skip_samples; + + /** + * If not 0, the number of samples that should be skipped from the start of + * the stream (the samples are removed from packets with pts==0, which also + * assumes negative timestamps do not happen). + * Intended for use with formats such as mp3 with ad-hoc gapless audio + * support. + */ + int64_t start_skip_samples; + + /** + * If not 0, the first audio sample that should be discarded from the stream. + * This is broken by design (needs global sample count), but can't be + * avoided for broken by design formats such as mp3 with ad-hoc gapless + * audio support. + */ + int64_t first_discard_sample; + + /** + * The sample after last sample that is intended to be discarded after + * first_discard_sample. Works on frame boundaries only. Used to prevent + * early EOF if the gapless info is broken (considered concatenated mp3s). + */ + int64_t last_discard_sample; + + /** + * Number of internally decoded frames, used internally in libavformat, do not access + * its lifetime differs from info which is why it is not in that structure. + */ + int nb_decoded_frames; + + /** + * Timestamp offset added to timestamps before muxing + */ + int64_t mux_ts_offset; + + /** + * Internal data to check for wrapping of the time stamp + */ + int64_t pts_wrap_reference; + + /** + * Options for behavior, when a wrap is detected. + * + * Defined by AV_PTS_WRAP_ values. + * + * If correction is enabled, there are two possibilities: + * If the first time stamp is near the wrap point, the wrap offset + * will be subtracted, which will create negative time stamps. + * Otherwise the offset will be added. + */ + int pts_wrap_behavior; + + /** + * Internal data to prevent doing update_initial_durations() twice + */ + int update_initial_durations_done; + +#define MAX_REORDER_DELAY 16 + + /** + * Internal data to generate dts from pts + */ + int64_t pts_reorder_error[MAX_REORDER_DELAY+1]; + uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1]; + + int64_t pts_buffer[MAX_REORDER_DELAY+1]; + + /** + * Internal data to analyze DTS and detect faulty mpeg streams + */ + int64_t last_dts_for_order_check; + uint8_t dts_ordered; + uint8_t dts_misordered; + + /** + * Internal data to inject global side data + */ + int inject_global_side_data; + + /** + * display aspect ratio (0 if unknown) + * - encoding: unused + * - decoding: Set by libavformat to calculate sample_aspect_ratio internally + */ + AVRational display_aspect_ratio; + + AVProbeData probe_data; + + /** + * last packet in packet_buffer for this stream when muxing. + */ + struct PacketList *last_in_packet_buffer; }; #ifdef __GNUC__ @@ -209,8 +366,6 @@ } while(0) #endif -struct tm *ff_brktimegm(time_t secs, struct tm *tm); - /** * Automatically create sub-directories * @@ -232,12 +387,12 @@ int ff_hex_to_data(uint8_t *data, const char *p); /** - * Add packet to AVFormatContext->packet_buffer list, determining its + * Add packet to an AVFormatContext's packet_buffer list, determining its * interleaved position using compare() function argument. - * @return 0, or < 0 on error + * @return 0 on success, < 0 on error. pkt will always be blank on return. */ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, - int (*compare)(AVFormatContext *, AVPacket *, AVPacket *)); + int (*compare)(AVFormatContext *, const AVPacket *, const AVPacket *)); void ff_read_frame_flush(AVFormatContext *s); @@ -293,16 +448,6 @@ AVFormatContext *src, int interleave); /** - * Get the length in bytes which is needed to store val as v. - */ -int ff_get_v_length(uint64_t val); - -/** - * Put val using a variable number of bytes. - */ -void ff_put_v(AVIOContext *bc, uint64_t val); - -/** * Read a whole line of text from AVIOContext. Stop reading after reaching * either a \\n, a \\0 or EOF. The returned string is always \\0-terminated, * and may be truncated if the buffer is too small. @@ -410,7 +555,11 @@ * * @return AVChapter or NULL on error */ +#if FF_API_CHAPTER_ID_INT AVChapter *avpriv_new_chapter(AVFormatContext *s, int id, AVRational time_base, +#else +AVChapter *avpriv_new_chapter(AVFormatContext *s, int64_t id, AVRational time_base, +#endif int64_t start, int64_t end, const char *title); /** @@ -497,19 +646,16 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt); /** - * Interleave a packet per dts in an output media file. + * Interleave an AVPacket per dts so it can be muxed. * - * Packets with pkt->destruct == av_destruct_packet will be freed inside this - * function, so they cannot be used after it. Note that calling av_packet_unref() - * on them is still safe. - * - * @param s media file handle + * @param s an AVFormatContext for output. pkt resp. out will be added to + * resp. taken from its packet buffer. * @param out the interleaved packet will be output here - * @param pkt the input packet + * @param pkt the input packet; will be blank on return if not NULL * @param flush 1 if no further packets are available as input and all * remaining packets should be output - * @return 1 if a packet was output, 0 if no packet could be output, - * < 0 if an error occurred + * @return 1 if a packet was output, 0 if no packet could be output + * (in which case out may be uninitialized), < 0 if an error occurred */ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush); @@ -526,6 +672,8 @@ enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag); +int ff_is_intra_only(enum AVCodecID id); + /** * Select a PCM codec based on the given parameters. * @@ -582,25 +730,13 @@ int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src); /** - * Wrap errno on rename() error. + * Wrap avpriv_io_move and log if error happens. * - * @param oldpath source path - * @param newpath destination path + * @param url_src source path + * @param url_dst destination path * @return 0 or AVERROR on failure */ -static inline int ff_rename(const char *oldpath, const char *newpath, void *logctx) -{ - int ret = 0; - if (rename(oldpath, newpath) == -1) { - ret = AVERROR(errno); - if (logctx) { - char err[AV_ERROR_MAX_STRING_SIZE] = {0}; - av_make_error_string(err, AV_ERROR_MAX_STRING_SIZE, ret); - av_log(logctx, AV_LOG_ERROR, "failed to rename file %s to %s: %s\n", oldpath, newpath, err); - } - } - return ret; -} +int ff_rename(const char *url_src, const char *url_dst, void *logctx); /** * Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end @@ -734,15 +870,12 @@ /** * Find the next packet in the interleaving queue for the given stream. - * The pkt parameter is filled in with the queued packet, including - * references to the data (which the caller is not allowed to keep or - * modify). * - * @return 0 if a packet was found, a negative value if no packet was found + * @return a pointer to a packet if one was found, NULL otherwise. */ -int ff_interleaved_peek(AVFormatContext *s, int stream, - AVPacket *pkt, int add_offset); +const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream); +int ff_get_muxer_ts_offset(AVFormatContext *s, int stream_index, int64_t *offset); int ff_lock_avformat(void); int ff_unlock_avformat(void); @@ -754,44 +887,6 @@ */ void ff_format_set_url(AVFormatContext *s, char *url); -#define FF_PACKETLIST_FLAG_REF_PACKET (1 << 0) /**< Create a new reference for the packet instead of - transferring the ownership of the existing one to the - list. */ - -/** - * Append an AVPacket to the list. - * - * @param head List head element - * @param tail List tail element - * @param pkt The packet being appended - * @param flags Any combination of FF_PACKETLIST_FLAG_* flags - * @return 0 on success, negative AVERROR value on failure. On failure, - the list is unchanged - */ -int ff_packet_list_put(AVPacketList **head, AVPacketList **tail, - AVPacket *pkt, int flags); - -/** - * Remove the oldest AVPacket in the list and return it. - * - * @note The pkt will be overwritten completely. The caller owns the - * packet and must unref it by itself. - * - * @param head List head element - * @param tail List tail element - * @param pkt Pointer to an initialized AVPacket struct - */ -int ff_packet_list_get(AVPacketList **head, AVPacketList **tail, - AVPacket *pkt); - -/** - * Wipe the list and unref all the packets in it. - * - * @param head List head element - * @param tail List tail element - */ -void ff_packet_list_free(AVPacketList **head, AVPacketList **tail); - void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]); #endif /* AVFORMAT_INTERNAL_H */ diff -Nru ffmpeg-4.2.2/libavformat/ipmovie.c ffmpeg-4.4/libavformat/ipmovie.c --- ffmpeg-4.2.2/libavformat/ipmovie.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ipmovie.c 2021-04-08 21:28:40.000000000 +0000 @@ -661,8 +661,10 @@ ipmovie->palette[i] = 0xFFU << 24; /* process the first chunk which should be CHUNK_INIT_VIDEO */ - if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO) + if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO) { + av_packet_unref(&pkt); return AVERROR_INVALIDDATA; + } /* peek ahead to the next chunk-- if it is an init audio chunk, process * it; if it is the first video chunk, this is a silent file */ @@ -674,8 +676,10 @@ if (chunk_type == CHUNK_VIDEO) ipmovie->audio_type = AV_CODEC_ID_NONE; /* no audio */ - else if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_AUDIO) + else if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_AUDIO) { + av_packet_unref(&pkt); return AVERROR_INVALIDDATA; + } /* initialize the stream decoders */ st = avformat_new_stream(s, NULL); diff -Nru ffmpeg-4.2.2/libavformat/ipudec.c ffmpeg-4.4/libavformat/ipudec.c --- ffmpeg-4.2.2/libavformat/ipudec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/ipudec.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,89 @@ +/* + * IPU video demuxer + * Copyright (c) 2020 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 "avformat.h" +#include "internal.h" +#include "avio_internal.h" +#include "rawdec.h" + +#include "libavutil/intreadwrite.h" +#include "libavcodec/internal.h" + +static int ipu_read_probe(const AVProbeData *p) +{ + if (AV_RB32(p->buf) != MKBETAG('i', 'p', 'u', 'm')) + return 0; + + if (AV_RL32(p->buf + 4) == 0) + return 0; + + if (AV_RL16(p->buf + 8) == 0) + return 0; + + if (AV_RL16(p->buf + 10) == 0) + return 0; + + if (AV_RL32(p->buf + 12) == 0) + return 0; + + return AVPROBE_SCORE_MAX; +} + +static int ipu_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + AVStream *st = avformat_new_stream(s, NULL); + + if (!st) + return AVERROR(ENOMEM); + avio_skip(pb, 8); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_IPU; + st->codecpar->width = avio_rl16(pb); + st->codecpar->height = avio_rl16(pb); + st->start_time = 0; + st->duration = + st->nb_frames = avio_rl32(pb); + st->need_parsing = AVSTREAM_PARSE_FULL_RAW; + avpriv_set_pts_info(st, 64, 1, 25); + + return 0; +} + +static const AVClass ipu_demuxer_class = { + .class_name = "ipu demuxer", + .item_name = av_default_item_name, + .option = ff_raw_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_ipu_demuxer = { + .name = "ipu", + .long_name = NULL_IF_CONFIG_SMALL("raw IPU Video"), + .read_probe = ipu_read_probe, + .read_header = ipu_read_header, + .read_packet = ff_raw_read_partial_packet, + .extensions = "ipu", + .flags = AVFMT_GENERIC_INDEX, + .raw_codec_id = AV_CODEC_ID_IPU, + .priv_data_size = sizeof(FFRawDemuxerContext), + .priv_class = &ipu_demuxer_class, +}; diff -Nru ffmpeg-4.2.2/libavformat/ircamdec.c ffmpeg-4.4/libavformat/ircamdec.c --- ffmpeg-4.2.2/libavformat/ircamdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ircamdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -66,12 +66,12 @@ } if (le == 1) { - sample_rate = av_int2float(avio_rl32(s->pb)); + sample_rate = lrintf(av_int2float(avio_rl32(s->pb))); channels = avio_rl32(s->pb); tag = avio_rl32(s->pb); tags = ff_codec_ircam_le_tags; } else if (le == 0) { - sample_rate = av_int2float(avio_rb32(s->pb)); + sample_rate = lrintf(av_int2float(avio_rb32(s->pb))); channels = avio_rb32(s->pb); tag = avio_rb32(s->pb); tags = ff_codec_ircam_be_tags; diff -Nru ffmpeg-4.2.2/libavformat/isom.c ffmpeg-4.4/libavformat/isom.c --- ffmpeg-4.2.2/libavformat/isom.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/isom.c 2021-04-08 21:28:40.000000000 +0000 @@ -72,307 +72,6 @@ { AV_CODEC_ID_NONE , 0 }, }; -const AVCodecTag ff_codec_movvideo_tags[] = { -/* { AV_CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */ - - { AV_CODEC_ID_RAWVIDEO, MKTAG('r', 'a', 'w', ' ') }, /* uncompressed RGB */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('y', 'u', 'v', '2') }, /* uncompressed YUV422 */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('2', 'v', 'u', 'y') }, /* uncompressed 8-bit 4:2:2 */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('y', 'u', 'v', 's') }, /* same as 2VUY but byte-swapped */ - - { AV_CODEC_ID_RAWVIDEO, MKTAG('L', '5', '5', '5') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('L', '5', '6', '5') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', '5', '6', '5') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('2', '4', 'B', 'G') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 'A') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 'A') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'B', 'G', 'R') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('b', '1', '6', 'g') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('b', '4', '8', 'r') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('b', '6', '4', 'a') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'b', 'g') }, /* BOXX */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'r', 'g') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'y', 'v') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('N', 'O', '1', '6') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('D', 'V', 'O', 'O') }, /* Digital Voodoo SD 8 Bit */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', '4', '2', '0') }, /* Radius DV YUV PAL */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', '4', '1', '1') }, /* Radius DV YUV NTSC */ - - { AV_CODEC_ID_R10K, MKTAG('R', '1', '0', 'k') }, /* uncompressed 10-bit RGB */ - { AV_CODEC_ID_R10K, MKTAG('R', '1', '0', 'g') }, /* uncompressed 10-bit RGB */ - { AV_CODEC_ID_R210, MKTAG('r', '2', '1', '0') }, /* uncompressed 10-bit RGB */ - { AV_CODEC_ID_AVUI, MKTAG('A', 'V', 'U', 'I') }, /* AVID Uncompressed deinterleaved UYVY422 */ - { AV_CODEC_ID_AVRP, MKTAG('A', 'V', 'r', 'p') }, /* Avid 1:1 10-bit RGB Packer */ - { AV_CODEC_ID_AVRP, MKTAG('S', 'U', 'D', 'S') }, /* Avid DS Uncompressed */ - { AV_CODEC_ID_V210, MKTAG('v', '2', '1', '0') }, /* uncompressed 10-bit 4:2:2 */ - { AV_CODEC_ID_V210, MKTAG('b', 'x', 'y', '2') }, /* BOXX 10-bit 4:2:2 */ - { AV_CODEC_ID_V308, MKTAG('v', '3', '0', '8') }, /* uncompressed 8-bit 4:4:4 */ - { AV_CODEC_ID_V408, MKTAG('v', '4', '0', '8') }, /* uncompressed 8-bit 4:4:4:4 */ - { AV_CODEC_ID_V410, MKTAG('v', '4', '1', '0') }, /* uncompressed 10-bit 4:4:4 */ - { AV_CODEC_ID_Y41P, MKTAG('Y', '4', '1', 'P') }, /* uncompressed 12-bit 4:1:1 */ - { AV_CODEC_ID_YUV4, MKTAG('y', 'u', 'v', '4') }, /* libquicktime packed yuv420p */ - { AV_CODEC_ID_TARGA_Y216, MKTAG('Y', '2', '1', '6') }, - - { AV_CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, /* PhotoJPEG */ - { AV_CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') }, /* Motion-JPEG (format A) */ - { AV_CODEC_ID_AVRN , MKTAG('A', 'V', 'D', 'J') }, /* MJPEG with alpha-channel (AVID JFIF meridien compressed) */ -/* { AV_CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, *//* MJPEG with alpha-channel (AVID ABVB/Truevision NuVista) */ - { AV_CODEC_ID_MJPEG, MKTAG('d', 'm', 'b', '1') }, /* Motion JPEG OpenDML */ - { AV_CODEC_ID_MJPEGB, MKTAG('m', 'j', 'p', 'b') }, /* Motion-JPEG (format B) */ - - { AV_CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, /* Sorenson Video v1 */ - { AV_CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, /* Sorenson Video v1 */ - { AV_CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', 'i') }, /* Sorenson Video v1 (from QT specs)*/ - { AV_CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') }, /* Sorenson Video v3 */ - - { AV_CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') }, - { AV_CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, /* OpenDiVX *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */ - { AV_CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') }, - { AV_CODEC_ID_MPEG4, MKTAG('3', 'I', 'V', '2') }, /* experimental: 3IVX files before ivx D4 4.5.1 */ - - { AV_CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H.263 */ - { AV_CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H.263 ?? works */ - - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */ - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */ - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'p', 'p') }, /* DVCPRO PAL produced by FCP */ - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'p') }, /* DVCPRO50 PAL produced by FCP */ - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC produced by FCP */ - { AV_CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, /* AVID DV */ - { AV_CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', '1') }, /* AVID DV100 */ - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'q') }, /* DVCPRO HD 720p50 */ - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'p') }, /* DVCPRO HD 720p60 */ - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '1') }, - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '2') }, - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '4') }, - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '5') }, /* DVCPRO HD 50i produced by FCP */ - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '6') }, /* DVCPRO HD 60i produced by FCP */ - { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '3') }, /* DVCPRO HD 30p produced by FCP */ - - { AV_CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, /* On2 VP3 */ - { AV_CODEC_ID_RPZA, MKTAG('r', 'p', 'z', 'a') }, /* Apple Video (RPZA) */ - { AV_CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, /* Cinepak */ - { AV_CODEC_ID_8BPS, MKTAG('8', 'B', 'P', 'S') }, /* Planar RGB (8BPS) */ - { AV_CODEC_ID_SMC, MKTAG('s', 'm', 'c', ' ') }, /* Apple Graphics (SMC) */ - { AV_CODEC_ID_QTRLE, MKTAG('r', 'l', 'e', ' ') }, /* Apple Animation (RLE) */ - { AV_CODEC_ID_SGIRLE, MKTAG('r', 'l', 'e', '1') }, /* SGI RLE 8-bit */ - { AV_CODEC_ID_MSRLE, MKTAG('W', 'R', 'L', 'E') }, - { AV_CODEC_ID_QDRAW, MKTAG('q', 'd', 'r', 'w') }, /* QuickDraw */ - - { AV_CODEC_ID_RAWVIDEO, MKTAG('W', 'R', 'A', 'W') }, - - { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') }, /* HEVC/H.265 which indicates parameter sets may be in ES */ - { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') }, /* HEVC/H.265 which indicates parameter sets shall not be in ES */ - { AV_CODEC_ID_HEVC, MKTAG('d', 'v', 'h', 'e') }, /* HEVC-based Dolby Vision derived from hev1 */ - /* dvh1 is handled within mov.c */ - - { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, /* AVC-1/H.264 */ - { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '2') }, - { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') }, - { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '4') }, - { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', 'p') }, /* AVC-Intra 50M 720p24/30/60 */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', 'q') }, /* AVC-Intra 50M 720p25/50 */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', '2') }, /* AVC-Intra 50M 1080p25/50 */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', '3') }, /* AVC-Intra 50M 1080p24/30/60 */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', '5') }, /* AVC-Intra 50M 1080i50 */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', '6') }, /* AVC-Intra 50M 1080i60 */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', 'p') }, /* AVC-Intra 100M 720p24/30/60 */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', 'q') }, /* AVC-Intra 100M 720p25/50 */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '2') }, /* AVC-Intra 100M 1080p25/50 */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '3') }, /* AVC-Intra 100M 1080p24/30/60 */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '5') }, /* AVC-Intra 100M 1080i50 */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '6') }, /* AVC-Intra 100M 1080i60 */ - { AV_CODEC_ID_H264, MKTAG('A', 'V', 'i', 'n') }, /* AVC-Intra with implicit SPS/PPS */ - { AV_CODEC_ID_H264, MKTAG('a', 'i', 'v', 'x') }, /* XAVC 10-bit 4:2:2 */ - { AV_CODEC_ID_H264, MKTAG('r', 'v', '6', '4') }, /* X-Com Radvision */ - { AV_CODEC_ID_H264, MKTAG('x', 'a', 'l', 'g') }, /* XAVC-L HD422 produced by FCP */ - { AV_CODEC_ID_H264, MKTAG('a', 'v', 'l', 'g') }, /* Panasonic P2 AVC-LongG */ - { AV_CODEC_ID_H264, MKTAG('d', 'v', 'a', '1') }, /* AVC-based Dolby Vision derived from avc1 */ - { AV_CODEC_ID_H264, MKTAG('d', 'v', 'a', 'v') }, /* AVC-based Dolby Vision derived from avc3 */ - - { AV_CODEC_ID_VP8, MKTAG('v', 'p', '0', '8') }, /* VP8 */ - { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') }, /* VP9 */ - { AV_CODEC_ID_AV1, MKTAG('a', 'v', '0', '1') }, /* AV1 */ - - { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', ' ') }, - { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', '1') }, /* Apple MPEG-1 Camcorder */ - { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */ - { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '1', 'v') }, /* CoreMedia CMVideoCodecType */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', '2', 'v', '1') }, /* Apple MPEG-2 Camcorder */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '1') }, /* MPEG-2 HDV 720p30 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG-2 HDV 1080i60 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '3') }, /* MPEG-2 HDV 1080i50 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '4') }, /* MPEG-2 HDV 720p24 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '5') }, /* MPEG-2 HDV 720p25 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '6') }, /* MPEG-2 HDV 1080p24 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '7') }, /* MPEG-2 HDV 1080p25 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '8') }, /* MPEG-2 HDV 1080p30 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '9') }, /* MPEG-2 HDV 720p60 JVC */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', 'a') }, /* MPEG-2 HDV 720p50 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'n') }, /* MPEG-2 IMX NTSC 525/60 50mb/s produced by FCP */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'p') }, /* MPEG-2 IMX PAL 625/50 50mb/s produced by FCP */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'n') }, /* MPEG-2 IMX NTSC 525/60 40mb/s produced by FCP */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'p') }, /* MPEG-2 IMX PAL 625/50 40mb/s produced by FCP */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG-2 IMX NTSC 525/60 30mb/s produced by FCP */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG-2 IMX PAL 625/50 30mb/s produced by FCP */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '1') }, /* XDCAM HD422 720p30 CBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '4') }, /* XDCAM HD422 720p24 CBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '5') }, /* XDCAM HD422 720p25 CBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '9') }, /* XDCAM HD422 720p60 CBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', 'a') }, /* XDCAM HD422 720p50 CBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', 'b') }, /* XDCAM HD422 1080i60 CBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', 'c') }, /* XDCAM HD422 1080i50 CBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', 'd') }, /* XDCAM HD422 1080p24 CBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', 'e') }, /* XDCAM HD422 1080p25 CBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', 'f') }, /* XDCAM HD422 1080p30 CBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '1') }, /* XDCAM EX 720p30 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '2') }, /* XDCAM HD 1080i60 */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '3') }, /* XDCAM HD 1080i50 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '4') }, /* XDCAM EX 720p24 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '5') }, /* XDCAM EX 720p25 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '6') }, /* XDCAM HD 1080p24 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '7') }, /* XDCAM HD 1080p25 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '8') }, /* XDCAM HD 1080p30 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '9') }, /* XDCAM EX 720p60 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', 'a') }, /* XDCAM EX 720p50 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', 'b') }, /* XDCAM EX 1080i60 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', 'c') }, /* XDCAM EX 1080i50 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', 'd') }, /* XDCAM EX 1080p24 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', 'e') }, /* XDCAM EX 1080p25 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', 'f') }, /* XDCAM EX 1080p30 VBR */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'h', 'd') }, /* XDCAM HD 540p */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'h', '2') }, /* XDCAM HD422 540p */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('A', 'V', 'm', 'p') }, /* AVID IMX PAL */ - { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '2', 'v') }, /* FCP5 */ - - { AV_CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') }, /* JPEG 2000 produced by FCP */ - - { AV_CODEC_ID_TARGA, MKTAG('t', 'g', 'a', ' ') }, /* Truevision Targa */ - { AV_CODEC_ID_TIFF, MKTAG('t', 'i', 'f', 'f') }, /* TIFF embedded in MOV */ - { AV_CODEC_ID_GIF, MKTAG('g', 'i', 'f', ' ') }, /* embedded gif files as frames (usually one "click to play movie" frame) */ - { AV_CODEC_ID_PNG, MKTAG('p', 'n', 'g', ' ') }, - { AV_CODEC_ID_PNG, MKTAG('M', 'N', 'G', ' ') }, - - { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') }, /* SMPTE RP 2025 */ - { AV_CODEC_ID_CAVS, MKTAG('a', 'v', 's', '2') }, - - { AV_CODEC_ID_DIRAC, MKTAG('d', 'r', 'a', 'c') }, - { AV_CODEC_ID_DNXHD, MKTAG('A', 'V', 'd', 'n') }, /* AVID DNxHD */ - { AV_CODEC_ID_DNXHD, MKTAG('A', 'V', 'd', 'h') }, /* AVID DNxHR */ - { AV_CODEC_ID_H263, MKTAG('H', '2', '6', '3') }, - { AV_CODEC_ID_MSMPEG4V3, MKTAG('3', 'I', 'V', 'D') }, /* 3ivx DivX Doctor */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'V', '1', 'x') }, /* AVID 1:1x */ - { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'V', 'u', 'p') }, - { AV_CODEC_ID_SGI, MKTAG('s', 'g', 'i', ' ') }, /* SGI */ - { AV_CODEC_ID_DPX, MKTAG('d', 'p', 'x', ' ') }, /* DPX */ - { AV_CODEC_ID_EXR, MKTAG('e', 'x', 'r', ' ') }, /* OpenEXR */ - - { AV_CODEC_ID_PRORES, MKTAG('a', 'p', 'c', 'h') }, /* Apple ProRes 422 High Quality */ - { AV_CODEC_ID_PRORES, MKTAG('a', 'p', 'c', 'n') }, /* Apple ProRes 422 Standard Definition */ - { AV_CODEC_ID_PRORES, MKTAG('a', 'p', 'c', 's') }, /* Apple ProRes 422 LT */ - { AV_CODEC_ID_PRORES, MKTAG('a', 'p', 'c', 'o') }, /* Apple ProRes 422 Proxy */ - { AV_CODEC_ID_PRORES, MKTAG('a', 'p', '4', 'h') }, /* Apple ProRes 4444 */ - { AV_CODEC_ID_PRORES, MKTAG('a', 'p', '4', 'x') }, /* Apple ProRes 4444 XQ */ - { AV_CODEC_ID_FLIC, MKTAG('f', 'l', 'i', 'c') }, - - { AV_CODEC_ID_AIC, MKTAG('i', 'c', 'o', 'd') }, - - { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', '1') }, - { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', '5') }, - { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', 'Y') }, - { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', 'A') }, - { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', 'M') }, - - { AV_CODEC_ID_DXV, MKTAG('D', 'X', 'D', '3') }, - { AV_CODEC_ID_DXV, MKTAG('D', 'X', 'D', 'I') }, - - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'R', '0') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'R', 'A') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'R', 'G') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'Y', '2') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'Y', '4') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'R', 'G') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'R', 'A') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'G', '0') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '0') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '2') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '4') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', 'A') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '2', 'R', 'A') }, - { AV_CODEC_ID_MAGICYUV, MKTAG('M', '2', 'R', 'G') }, - - { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '0') }, - { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '1') }, - { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '2') }, - { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '3') }, - { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '4') }, - { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '5') }, - { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '6') }, - { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '7') }, - - { AV_CODEC_ID_PIXLET, MKTAG('p', 'x', 'l', 't') }, - - { AV_CODEC_ID_NONE, 0 }, -}; - -const AVCodecTag ff_codec_movaudio_tags[] = { - { AV_CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, - { AV_CODEC_ID_AC3, MKTAG('a', 'c', '-', '3') }, /* ETSI TS 102 366 Annex F */ - { AV_CODEC_ID_AC3, MKTAG('s', 'a', 'c', '3') }, /* Nero Recode */ - { AV_CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') }, - { AV_CODEC_ID_ALAC, MKTAG('a', 'l', 'a', 'c') }, - { AV_CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') }, /* AMR-NB 3gp */ - { AV_CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') }, /* AMR-WB 3gp */ - { AV_CODEC_ID_DTS, MKTAG('d', 't', 's', 'c') }, /* DTS formats prior to DTS-HD */ - { AV_CODEC_ID_DTS, MKTAG('d', 't', 's', 'h') }, /* DTS-HD audio formats */ - { AV_CODEC_ID_DTS, MKTAG('d', 't', 's', 'l') }, /* DTS-HD Lossless formats */ - { AV_CODEC_ID_DTS, MKTAG('d', 't', 's', 'e') }, /* DTS Express */ - { AV_CODEC_ID_DTS, MKTAG('D', 'T', 'S', ' ') }, /* non-standard */ - { AV_CODEC_ID_EAC3, MKTAG('e', 'c', '-', '3') }, /* ETSI TS 102 366 Annex F (only valid in ISOBMFF) */ - { AV_CODEC_ID_DVAUDIO, MKTAG('v', 'd', 'v', 'a') }, - { AV_CODEC_ID_DVAUDIO, MKTAG('d', 'v', 'c', 'a') }, - { AV_CODEC_ID_GSM, MKTAG('a', 'g', 's', 'm') }, - { AV_CODEC_ID_ILBC, MKTAG('i', 'l', 'b', 'c') }, - { AV_CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') }, - { AV_CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, - { AV_CODEC_ID_MP1, MKTAG('.', 'm', 'p', '1') }, - { AV_CODEC_ID_MP2, MKTAG('.', 'm', 'p', '2') }, - { AV_CODEC_ID_MP3, MKTAG('.', 'm', 'p', '3') }, - { AV_CODEC_ID_MP3, MKTAG('m', 'p', '3', ' ') }, /* vlc */ - { AV_CODEC_ID_MP3, 0x6D730055 }, - { AV_CODEC_ID_NELLYMOSER, MKTAG('n', 'm', 'o', 's') }, /* Flash Media Server */ - { AV_CODEC_ID_NELLYMOSER, MKTAG('N', 'E', 'L', 'L') }, /* Perian */ - { AV_CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') }, - { AV_CODEC_ID_PCM_F32BE, MKTAG('f', 'l', '3', '2') }, - { AV_CODEC_ID_PCM_F32LE, MKTAG('f', 'l', '3', '2') }, - { AV_CODEC_ID_PCM_F64BE, MKTAG('f', 'l', '6', '4') }, - { AV_CODEC_ID_PCM_F64LE, MKTAG('f', 'l', '6', '4') }, - { AV_CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') }, - { AV_CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') }, - { 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_S24BE, MKTAG('i', 'n', '2', '4') }, - { AV_CODEC_ID_PCM_S24LE, MKTAG('i', 'n', '2', '4') }, - { 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') }, - { AV_CODEC_ID_PCM_U8, MKTAG('r', 'a', 'w', ' ') }, - { AV_CODEC_ID_PCM_U8, MKTAG('N', 'O', 'N', 'E') }, - { AV_CODEC_ID_QCELP, MKTAG('Q', 'c', 'l', 'p') }, - { AV_CODEC_ID_QCELP, MKTAG('Q', 'c', 'l', 'q') }, - { AV_CODEC_ID_QCELP, MKTAG('s', 'q', 'c', 'p') }, /* ISO Media fourcc */ - { AV_CODEC_ID_QDM2, MKTAG('Q', 'D', 'M', '2') }, - { AV_CODEC_ID_QDMC, MKTAG('Q', 'D', 'M', 'C') }, - { AV_CODEC_ID_SPEEX, MKTAG('s', 'p', 'e', 'x') }, /* Flash Media Server */ - { AV_CODEC_ID_SPEEX, MKTAG('S', 'P', 'X', 'N') }, /* ZygoAudio (quality 10 mode) */ - { AV_CODEC_ID_EVRC, MKTAG('s', 'e', 'v', 'c') }, /* 3GPP2 */ - { AV_CODEC_ID_SMV, MKTAG('s', 's', 'm', 'v') }, /* 3GPP2 */ - { AV_CODEC_ID_FLAC, MKTAG('f', 'L', 'a', 'C') }, /* nonstandard */ - { AV_CODEC_ID_OPUS, MKTAG('O', 'p', 'u', 's') }, /* mp4ra.org */ - { AV_CODEC_ID_NONE, 0 }, -}; - const AVCodecTag ff_codec_movsubtitle_tags[] = { { AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'e', 'x', 't') }, { AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') }, @@ -390,25 +89,145 @@ /* http://developer.apple.com/documentation/mac/Text/Text-368.html */ /* deprecated by putting the code as 3*5 bits ASCII */ static const char mov_mdhd_language_map[][4] = { - /* 0-9 */ - "eng", "fra", "ger", "ita", "dut", "sve", "spa", "dan", "por", "nor", - "heb", "jpn", "ara", "fin", "gre", "ice", "mlt", "tur", "hr "/*scr*/, "chi"/*ace?*/, - "urd", "hin", "tha", "kor", "lit", "pol", "hun", "est", "lav", "", - "fo ", "", "rus", "chi", "", "iri", "alb", "ron", "ces", "slk", - "slv", "yid", "sr ", "mac", "bul", "ukr", "bel", "uzb", "kaz", "aze", - /*?*/ - "aze", "arm", "geo", "mol", "kir", "tgk", "tuk", "mon", "", "pus", - "kur", "kas", "snd", "tib", "nep", "san", "mar", "ben", "asm", "guj", - "pa ", "ori", "mal", "kan", "tam", "tel", "", "bur", "khm", "lao", - /* roman? arabic? */ - "vie", "ind", "tgl", "may", "may", "amh", "tir", "orm", "som", "swa", - /*==rundi?*/ - "", "run", "", "mlg", "epo", "", "", "", "", "", - /* 100 */ - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "wel", "baq", - "cat", "lat", "que", "grn", "aym", "tat", "uig", "dzo", "jav" + "eng", /* 0 English */ + "fra", /* 1 French */ + "ger", /* 2 German */ + "ita", /* 3 Italian */ + "dut", /* 4 Dutch */ + "sve", /* 5 Swedish */ + "spa", /* 6 Spanish */ + "dan", /* 7 Danish */ + "por", /* 8 Portuguese */ + "nor", /* 9 Norwegian */ + "heb", /* 10 Hebrew */ + "jpn", /* 11 Japanese */ + "ara", /* 12 Arabic */ + "fin", /* 13 Finnish */ + "gre", /* 14 Greek */ + "ice", /* 15 Icelandic */ + "mlt", /* 16 Maltese */ + "tur", /* 17 Turkish */ + "hr ", /* 18 Croatian */ + "chi", /* 19 Traditional Chinese */ + "urd", /* 20 Urdu */ + "hin", /* 21 Hindi */ + "tha", /* 22 Thai */ + "kor", /* 23 Korean */ + "lit", /* 24 Lithuanian */ + "pol", /* 25 Polish */ + "hun", /* 26 Hungarian */ + "est", /* 27 Estonian */ + "lav", /* 28 Latvian */ + "", /* 29 Sami */ + "fo ", /* 30 Faroese */ + "", /* 31 Farsi */ + "rus", /* 32 Russian */ + "chi", /* 33 Simplified Chinese */ + "", /* 34 Flemish */ + "iri", /* 35 Irish */ + "alb", /* 36 Albanian */ + "ron", /* 37 Romanian */ + "ces", /* 38 Czech */ + "slk", /* 39 Slovak */ + "slv", /* 40 Slovenian */ + "yid", /* 41 Yiddish */ + "sr ", /* 42 Serbian */ + "mac", /* 43 Macedonian */ + "bul", /* 44 Bulgarian */ + "ukr", /* 45 Ukrainian */ + "bel", /* 46 Belarusian */ + "uzb", /* 47 Uzbek */ + "kaz", /* 48 Kazakh */ + "aze", /* 49 Azerbaijani */ + "aze", /* 50 AzerbaijanAr */ + "arm", /* 51 Armenian */ + "geo", /* 52 Georgian */ + "mol", /* 53 Moldavian */ + "kir", /* 54 Kirghiz */ + "tgk", /* 55 Tajiki */ + "tuk", /* 56 Turkmen */ + "mon", /* 57 Mongolian */ + "", /* 58 MongolianCyr */ + "pus", /* 59 Pashto */ + "kur", /* 60 Kurdish */ + "kas", /* 61 Kashmiri */ + "snd", /* 62 Sindhi */ + "tib", /* 63 Tibetan */ + "nep", /* 64 Nepali */ + "san", /* 65 Sanskrit */ + "mar", /* 66 Marathi */ + "ben", /* 67 Bengali */ + "asm", /* 68 Assamese */ + "guj", /* 69 Gujarati */ + "pa ", /* 70 Punjabi */ + "ori", /* 71 Oriya */ + "mal", /* 72 Malayalam */ + "kan", /* 73 Kannada */ + "tam", /* 74 Tamil */ + "tel", /* 75 Telugu */ + "", /* 76 Sinhala */ + "bur", /* 77 Burmese */ + "khm", /* 78 Khmer */ + "lao", /* 79 Lao */ + "vie", /* 80 Vietnamese */ + "ind", /* 81 Indonesian */ + "tgl", /* 82 Tagalog */ + "may", /* 83 MalayRoman */ + "may", /* 84 MalayArabic */ + "amh", /* 85 Amharic */ + "tir", /* 86 Galla */ + "orm", /* 87 Oromo */ + "som", /* 88 Somali */ + "swa", /* 89 Swahili */ + "", /* 90 Kinyarwanda */ + "run", /* 91 Rundi */ + "", /* 92 Nyanja */ + "mlg", /* 93 Malagasy */ + "epo", /* 94 Esperanto */ + "", /* 95 */ + "", /* 96 */ + "", /* 97 */ + "", /* 98 */ + "", /* 99 */ + "", /* 100 */ + "", /* 101 */ + "", /* 102 */ + "", /* 103 */ + "", /* 104 */ + "", /* 105 */ + "", /* 106 */ + "", /* 107 */ + "", /* 108 */ + "", /* 109 */ + "", /* 110 */ + "", /* 111 */ + "", /* 112 */ + "", /* 113 */ + "", /* 114 */ + "", /* 115 */ + "", /* 116 */ + "", /* 117 */ + "", /* 118 */ + "", /* 119 */ + "", /* 120 */ + "", /* 121 */ + "", /* 122 */ + "", /* 123 */ + "", /* 124 */ + "", /* 125 */ + "", /* 126 */ + "", /* 127 */ + "wel", /* 128 Welsh */ + "baq", /* 129 Basque */ + "cat", /* 130 Catalan */ + "lat", /* 131 Latin */ + "que", /* 132 Quechua */ + "grn", /* 133 Guarani */ + "aym", /* 134 Aymara */ + "tat", /* 135 Tatar */ + "uig", /* 136 Uighur */ + "dzo", /* 137 Dzongkha */ + "jav", /* 138 JavaneseRom */ }; int ff_mov_iso639_to_lang(const char lang[4], int mp4) @@ -546,8 +365,8 @@ return ret; if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { MPEG4AudioConfig cfg = {0}; - ret = avpriv_mpeg4audio_get_config(&cfg, st->codecpar->extradata, - st->codecpar->extradata_size * 8, 1); + ret = avpriv_mpeg4audio_get_config2(&cfg, st->codecpar->extradata, + st->codecpar->extradata_size, 1, fc); if (ret < 0) return ret; st->codecpar->channels = cfg.channels; @@ -599,45 +418,6 @@ { AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY, (137<<16) | 5}, // kCAFChannelLayoutTag_DVD_11 { 0, 0}, }; -#if 0 -int ff_mov_read_chan(AVFormatContext *s, AVStream *st, int64_t size) -{ - AVCodecContext *codec= st->codec; - uint32_t layout_tag; - AVIOContext *pb = s->pb; - const MovChannelLayout *layouts = mov_channel_layout; - - if (size < 12) - return AVERROR_INVALIDDATA; - - layout_tag = avio_rb32(pb); - size -= 4; - if (layout_tag == 0) { // kCAFChannelLayoutTag_UseChannelDescriptions - // Channel descriptions not implemented - av_log_ask_for_sample(s, "Unimplemented container channel layout.\n"); - avio_skip(pb, size); - return 0; - } - if (layout_tag == 0x10000) { // kCAFChannelLayoutTag_UseChannelBitmap - codec->channel_layout = avio_rb32(pb); - size -= 4; - avio_skip(pb, size); - return 0; - } - while (layouts->channel_layout) { - if (layout_tag == layouts->layout_tag) { - codec->channel_layout = layouts->channel_layout; - break; - } - layouts++; - } - if (!codec->channel_layout) - av_log(s, AV_LOG_WARNING, "Unknown container channel layout.\n"); - avio_skip(pb, size); - - return 0; -} -#endif void ff_mov_write_chan(AVIOContext *pb, int64_t channel_layout) { @@ -659,13 +439,3 @@ } avio_wb32(pb, 0); // mNumberChannelDescriptions } - -const struct AVCodecTag *avformat_get_mov_video_tags(void) -{ - return ff_codec_movvideo_tags; -} - -const struct AVCodecTag *avformat_get_mov_audio_tags(void) -{ - return ff_codec_movaudio_tags; -} diff -Nru ffmpeg-4.2.2/libavformat/isom.h ffmpeg-4.4/libavformat/isom.h --- ffmpeg-4.2.2/libavformat/isom.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/isom.h 2021-04-08 21:28:40.000000000 +0000 @@ -129,6 +129,7 @@ int64_t sidx_pts; int64_t first_tfra_pts; int64_t tfdt_dts; + int64_t next_trun_dts; int index_entry; MOVEncryptionIndex *encryption_index; } MOVFragmentStreamInfo; @@ -163,6 +164,8 @@ int64_t *chunk_offsets; unsigned int stts_count; MOVStts *stts_data; + unsigned int sdtp_count; + uint8_t *sdtp_data; unsigned int ctts_count; unsigned int ctts_allocated_size; MOVStts *ctts_data; @@ -283,11 +286,17 @@ int activation_bytes_size; void *audible_fixed_key; int audible_fixed_key_size; + void *audible_key; + int audible_key_size; + void *audible_iv; + int audible_iv_size; struct AVAES *aes_decrypt; uint8_t *decryption_key; int decryption_key_len; int enable_drefs; int32_t movie_display_matrix[3][3]; ///< display matrix from mvhd + int have_read_mfra_size; + uint32_t mfra_size; } MOVContext; int ff_mp4_read_descr_len(AVIOContext *pb); diff -Nru ffmpeg-4.2.2/libavformat/isom_tags.c ffmpeg-4.4/libavformat/isom_tags.c --- ffmpeg-4.2.2/libavformat/isom_tags.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/isom_tags.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,346 @@ +/* + * ISO Media codec tags + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002 Francois Revol + * Copyright (c) 2006 Baptiste Coudurier + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/codec_id.h" +#include "avformat.h" +#include "internal.h" +#include "isom.h" + +const AVCodecTag ff_codec_movvideo_tags[] = { +/* { AV_CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */ + + { AV_CODEC_ID_RAWVIDEO, MKTAG('r', 'a', 'w', ' ') }, /* uncompressed RGB */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('y', 'u', 'v', '2') }, /* uncompressed YUV422 */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('2', 'v', 'u', 'y') }, /* uncompressed 8-bit 4:2:2 */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('y', 'u', 'v', 's') }, /* same as 2VUY but byte-swapped */ + + { AV_CODEC_ID_RAWVIDEO, MKTAG('L', '5', '5', '5') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('L', '5', '6', '5') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', '5', '6', '5') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('2', '4', 'B', 'G') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 'A') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 'A') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'B', 'G', 'R') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('b', '1', '6', 'g') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('b', '4', '8', 'r') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('b', '6', '4', 'a') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'b', 'g') }, /* BOXX */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'r', 'g') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('b', 'x', 'y', 'v') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('N', 'O', '1', '6') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('D', 'V', 'O', 'O') }, /* Digital Voodoo SD 8 Bit */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', '4', '2', '0') }, /* Radius DV YUV PAL */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', '4', '1', '1') }, /* Radius DV YUV NTSC */ + + { AV_CODEC_ID_R10K, MKTAG('R', '1', '0', 'k') }, /* uncompressed 10-bit RGB */ + { AV_CODEC_ID_R10K, MKTAG('R', '1', '0', 'g') }, /* uncompressed 10-bit RGB */ + { AV_CODEC_ID_R210, MKTAG('r', '2', '1', '0') }, /* uncompressed 10-bit RGB */ + { AV_CODEC_ID_AVUI, MKTAG('A', 'V', 'U', 'I') }, /* AVID Uncompressed deinterleaved UYVY422 */ + { AV_CODEC_ID_AVRP, MKTAG('A', 'V', 'r', 'p') }, /* Avid 1:1 10-bit RGB Packer */ + { AV_CODEC_ID_AVRP, MKTAG('S', 'U', 'D', 'S') }, /* Avid DS Uncompressed */ + { AV_CODEC_ID_V210, MKTAG('v', '2', '1', '0') }, /* uncompressed 10-bit 4:2:2 */ + { AV_CODEC_ID_V210, MKTAG('b', 'x', 'y', '2') }, /* BOXX 10-bit 4:2:2 */ + { AV_CODEC_ID_V308, MKTAG('v', '3', '0', '8') }, /* uncompressed 8-bit 4:4:4 */ + { AV_CODEC_ID_V408, MKTAG('v', '4', '0', '8') }, /* uncompressed 8-bit 4:4:4:4 */ + { AV_CODEC_ID_V410, MKTAG('v', '4', '1', '0') }, /* uncompressed 10-bit 4:4:4 */ + { AV_CODEC_ID_Y41P, MKTAG('Y', '4', '1', 'P') }, /* uncompressed 12-bit 4:1:1 */ + { AV_CODEC_ID_YUV4, MKTAG('y', 'u', 'v', '4') }, /* libquicktime packed yuv420p */ + { AV_CODEC_ID_TARGA_Y216, MKTAG('Y', '2', '1', '6') }, + + { AV_CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, /* PhotoJPEG */ + { AV_CODEC_ID_MJPEG, MKTAG('m', 'j', 'p', 'a') }, /* Motion-JPEG (format A) */ + { AV_CODEC_ID_MJPEG, MKTAG('A', 'V', 'D', 'J') }, /* MJPEG with alpha-channel (AVID JFIF meridien compressed) */ + { AV_CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, /* MJPEG with alpha-channel (AVID ABVB/Truevision NuVista) */ + { AV_CODEC_ID_MJPEG, MKTAG('d', 'm', 'b', '1') }, /* Motion JPEG OpenDML */ + { AV_CODEC_ID_MJPEGB, MKTAG('m', 'j', 'p', 'b') }, /* Motion-JPEG (format B) */ + + { AV_CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, /* Sorenson Video v1 */ + { AV_CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, /* Sorenson Video v1 */ + { AV_CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', 'i') }, /* Sorenson Video v1 (from QT specs)*/ + { AV_CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') }, /* Sorenson Video v3 */ + + { AV_CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, /* OpenDiVX *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */ + { AV_CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') }, + { AV_CODEC_ID_MPEG4, MKTAG('3', 'I', 'V', '2') }, /* experimental: 3IVX files before ivx D4 4.5.1 */ + + { AV_CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H.263 */ + { AV_CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H.263 ?? works */ + + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */ + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */ + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'p', 'p') }, /* DVCPRO PAL produced by FCP */ + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'p') }, /* DVCPRO50 PAL produced by FCP */ + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC produced by FCP */ + { AV_CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, /* AVID DV */ + { AV_CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', '1') }, /* AVID DV100 */ + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'q') }, /* DVCPRO HD 720p50 */ + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'p') }, /* DVCPRO HD 720p60 */ + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '1') }, + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '2') }, + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '4') }, + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '5') }, /* DVCPRO HD 50i produced by FCP */ + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '6') }, /* DVCPRO HD 60i produced by FCP */ + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '3') }, /* DVCPRO HD 30p produced by FCP */ + + { AV_CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') }, /* On2 VP3 */ + { AV_CODEC_ID_RPZA, MKTAG('r', 'p', 'z', 'a') }, /* Apple Video (RPZA) */ + { AV_CODEC_ID_CINEPAK, MKTAG('c', 'v', 'i', 'd') }, /* Cinepak */ + { AV_CODEC_ID_8BPS, MKTAG('8', 'B', 'P', 'S') }, /* Planar RGB (8BPS) */ + { AV_CODEC_ID_SMC, MKTAG('s', 'm', 'c', ' ') }, /* Apple Graphics (SMC) */ + { AV_CODEC_ID_QTRLE, MKTAG('r', 'l', 'e', ' ') }, /* Apple Animation (RLE) */ + { AV_CODEC_ID_SGIRLE, MKTAG('r', 'l', 'e', '1') }, /* SGI RLE 8-bit */ + { AV_CODEC_ID_MSRLE, MKTAG('W', 'R', 'L', 'E') }, + { AV_CODEC_ID_QDRAW, MKTAG('q', 'd', 'r', 'w') }, /* QuickDraw */ + { AV_CODEC_ID_CDTOONS, MKTAG('Q', 'k', 'B', 'k') }, /* CDToons */ + + { AV_CODEC_ID_RAWVIDEO, MKTAG('W', 'R', 'A', 'W') }, + + { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') }, /* HEVC/H.265 which indicates parameter sets may be in ES */ + { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') }, /* HEVC/H.265 which indicates parameter sets shall not be in ES */ + { AV_CODEC_ID_HEVC, MKTAG('d', 'v', 'h', 'e') }, /* HEVC-based Dolby Vision derived from hev1 */ + /* dvh1 is handled within mov.c */ + + { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, /* AVC-1/H.264 */ + { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '2') }, + { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') }, + { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '4') }, + { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', 'p') }, /* AVC-Intra 50M 720p24/30/60 */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', 'q') }, /* AVC-Intra 50M 720p25/50 */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', '2') }, /* AVC-Intra 50M 1080p25/50 */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', '3') }, /* AVC-Intra 50M 1080p24/30/60 */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', '5') }, /* AVC-Intra 50M 1080i50 */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', '6') }, /* AVC-Intra 50M 1080i60 */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', 'p') }, /* AVC-Intra 100M 720p24/30/60 */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', 'q') }, /* AVC-Intra 100M 720p25/50 */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '2') }, /* AVC-Intra 100M 1080p25/50 */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '3') }, /* AVC-Intra 100M 1080p24/30/60 */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '5') }, /* AVC-Intra 100M 1080i50 */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '6') }, /* AVC-Intra 100M 1080i60 */ + { AV_CODEC_ID_H264, MKTAG('A', 'V', 'i', 'n') }, /* AVC-Intra with implicit SPS/PPS */ + { AV_CODEC_ID_H264, MKTAG('a', 'i', 'v', 'x') }, /* XAVC 10-bit 4:2:2 */ + { AV_CODEC_ID_H264, MKTAG('r', 'v', '6', '4') }, /* X-Com Radvision */ + { AV_CODEC_ID_H264, MKTAG('x', 'a', 'l', 'g') }, /* XAVC-L HD422 produced by FCP */ + { AV_CODEC_ID_H264, MKTAG('a', 'v', 'l', 'g') }, /* Panasonic P2 AVC-LongG */ + { AV_CODEC_ID_H264, MKTAG('d', 'v', 'a', '1') }, /* AVC-based Dolby Vision derived from avc1 */ + { AV_CODEC_ID_H264, MKTAG('d', 'v', 'a', 'v') }, /* AVC-based Dolby Vision derived from avc3 */ + + { AV_CODEC_ID_VP8, MKTAG('v', 'p', '0', '8') }, /* VP8 */ + { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') }, /* VP9 */ + { AV_CODEC_ID_AV1, MKTAG('a', 'v', '0', '1') }, /* AV1 */ + + { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', ' ') }, + { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', '1') }, /* Apple MPEG-1 Camcorder */ + { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */ + { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '1', 'v') }, /* CoreMedia CMVideoCodecType */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', '2', 'v', '1') }, /* Apple MPEG-2 Camcorder */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '1') }, /* MPEG-2 HDV 720p30 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG-2 HDV 1080i60 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '3') }, /* MPEG-2 HDV 1080i50 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '4') }, /* MPEG-2 HDV 720p24 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '5') }, /* MPEG-2 HDV 720p25 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '6') }, /* MPEG-2 HDV 1080p24 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '7') }, /* MPEG-2 HDV 1080p25 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '8') }, /* MPEG-2 HDV 1080p30 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '9') }, /* MPEG-2 HDV 720p60 JVC */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', 'a') }, /* MPEG-2 HDV 720p50 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'n') }, /* MPEG-2 IMX NTSC 525/60 50mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'p') }, /* MPEG-2 IMX PAL 625/50 50mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'n') }, /* MPEG-2 IMX NTSC 525/60 40mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'p') }, /* MPEG-2 IMX PAL 625/50 40mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG-2 IMX NTSC 525/60 30mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG-2 IMX PAL 625/50 30mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '1') }, /* XDCAM HD422 720p30 CBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '4') }, /* XDCAM HD422 720p24 CBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '5') }, /* XDCAM HD422 720p25 CBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '9') }, /* XDCAM HD422 720p60 CBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', 'a') }, /* XDCAM HD422 720p50 CBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', 'b') }, /* XDCAM HD422 1080i60 CBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', 'c') }, /* XDCAM HD422 1080i50 CBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', 'd') }, /* XDCAM HD422 1080p24 CBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', 'e') }, /* XDCAM HD422 1080p25 CBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', 'f') }, /* XDCAM HD422 1080p30 CBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '1') }, /* XDCAM EX 720p30 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '2') }, /* XDCAM HD 1080i60 */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '3') }, /* XDCAM HD 1080i50 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '4') }, /* XDCAM EX 720p24 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '5') }, /* XDCAM EX 720p25 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '6') }, /* XDCAM HD 1080p24 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '7') }, /* XDCAM HD 1080p25 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '8') }, /* XDCAM HD 1080p30 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', '9') }, /* XDCAM EX 720p60 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', 'a') }, /* XDCAM EX 720p50 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', 'b') }, /* XDCAM EX 1080i60 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', 'c') }, /* XDCAM EX 1080i50 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', 'd') }, /* XDCAM EX 1080p24 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', 'e') }, /* XDCAM EX 1080p25 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'v', 'f') }, /* XDCAM EX 1080p30 VBR */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'h', 'd') }, /* XDCAM HD 540p */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', 'h', '2') }, /* XDCAM HD422 540p */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('A', 'V', 'm', 'p') }, /* AVID IMX PAL */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '2', 'v') }, /* FCP5 */ + + { AV_CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') }, /* JPEG 2000 produced by FCP */ + + { AV_CODEC_ID_TARGA, MKTAG('t', 'g', 'a', ' ') }, /* Truevision Targa */ + { AV_CODEC_ID_TIFF, MKTAG('t', 'i', 'f', 'f') }, /* TIFF embedded in MOV */ + { AV_CODEC_ID_GIF, MKTAG('g', 'i', 'f', ' ') }, /* embedded gif files as frames (usually one "click to play movie" frame) */ + { AV_CODEC_ID_PNG, MKTAG('p', 'n', 'g', ' ') }, + { AV_CODEC_ID_PNG, MKTAG('M', 'N', 'G', ' ') }, + + { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') }, /* SMPTE RP 2025 */ + { AV_CODEC_ID_CAVS, MKTAG('a', 'v', 's', '2') }, + + { AV_CODEC_ID_DIRAC, MKTAG('d', 'r', 'a', 'c') }, + { AV_CODEC_ID_DNXHD, MKTAG('A', 'V', 'd', 'n') }, /* AVID DNxHD */ + { AV_CODEC_ID_DNXHD, MKTAG('A', 'V', 'd', 'h') }, /* AVID DNxHR */ + { AV_CODEC_ID_H263, MKTAG('H', '2', '6', '3') }, + { AV_CODEC_ID_MSMPEG4V3, MKTAG('3', 'I', 'V', 'D') }, /* 3ivx DivX Doctor */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'V', '1', 'x') }, /* AVID 1:1x */ + { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'V', 'u', 'p') }, + { AV_CODEC_ID_SGI, MKTAG('s', 'g', 'i', ' ') }, /* SGI */ + { AV_CODEC_ID_DPX, MKTAG('d', 'p', 'x', ' ') }, /* DPX */ + { AV_CODEC_ID_EXR, MKTAG('e', 'x', 'r', ' ') }, /* OpenEXR */ + + { AV_CODEC_ID_PRORES, MKTAG('a', 'p', 'c', 'h') }, /* Apple ProRes 422 High Quality */ + { AV_CODEC_ID_PRORES, MKTAG('a', 'p', 'c', 'n') }, /* Apple ProRes 422 Standard Definition */ + { AV_CODEC_ID_PRORES, MKTAG('a', 'p', 'c', 's') }, /* Apple ProRes 422 LT */ + { AV_CODEC_ID_PRORES, MKTAG('a', 'p', 'c', 'o') }, /* Apple ProRes 422 Proxy */ + { AV_CODEC_ID_PRORES, MKTAG('a', 'p', '4', 'h') }, /* Apple ProRes 4444 */ + { AV_CODEC_ID_PRORES, MKTAG('a', 'p', '4', 'x') }, /* Apple ProRes 4444 XQ */ + { AV_CODEC_ID_FLIC, MKTAG('f', 'l', 'i', 'c') }, + + { AV_CODEC_ID_AIC, MKTAG('i', 'c', 'o', 'd') }, + + { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', '1') }, + { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', '5') }, + { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', 'Y') }, + { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', 'A') }, + { AV_CODEC_ID_HAP, MKTAG('H', 'a', 'p', 'M') }, + + { AV_CODEC_ID_DXV, MKTAG('D', 'X', 'D', '3') }, + { AV_CODEC_ID_DXV, MKTAG('D', 'X', 'D', 'I') }, + + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'R', '0') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'R', 'A') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'R', 'G') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'Y', '0') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'Y', '2') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'Y', '4') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'R', 'G') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'R', 'A') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'G', '0') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '0') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '2') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '4') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', 'A') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '2', 'R', 'A') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '2', 'R', 'G') }, + + { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '0') }, + { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '1') }, + { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '2') }, + { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '3') }, + { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '4') }, + { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '5') }, + { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '6') }, + { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '7') }, + + { AV_CODEC_ID_PIXLET, MKTAG('p', 'x', 'l', 't') }, + + { AV_CODEC_ID_NOTCHLC, MKTAG('n', 'c', 'l', 'c') }, + + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'G', 'R') }, /* ASC Bayer BGGR */ + + { AV_CODEC_ID_NONE, 0 }, +}; + +const AVCodecTag ff_codec_movaudio_tags[] = { + { AV_CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_AC3, MKTAG('a', 'c', '-', '3') }, /* ETSI TS 102 366 Annex F */ + { AV_CODEC_ID_AC3, MKTAG('s', 'a', 'c', '3') }, /* Nero Recode */ + { AV_CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') }, + { AV_CODEC_ID_ALAC, MKTAG('a', 'l', 'a', 'c') }, + { AV_CODEC_ID_AMR_NB, MKTAG('s', 'a', 'm', 'r') }, /* AMR-NB 3gp */ + { AV_CODEC_ID_AMR_WB, MKTAG('s', 'a', 'w', 'b') }, /* AMR-WB 3gp */ + { AV_CODEC_ID_DTS, MKTAG('d', 't', 's', 'c') }, /* DTS formats prior to DTS-HD */ + { AV_CODEC_ID_DTS, MKTAG('d', 't', 's', 'h') }, /* DTS-HD audio formats */ + { AV_CODEC_ID_DTS, MKTAG('d', 't', 's', 'l') }, /* DTS-HD Lossless formats */ + { AV_CODEC_ID_DTS, MKTAG('d', 't', 's', 'e') }, /* DTS Express */ + { AV_CODEC_ID_DTS, MKTAG('D', 'T', 'S', ' ') }, /* non-standard */ + { AV_CODEC_ID_EAC3, MKTAG('e', 'c', '-', '3') }, /* ETSI TS 102 366 Annex F (only valid in ISOBMFF) */ + { AV_CODEC_ID_DVAUDIO, MKTAG('v', 'd', 'v', 'a') }, + { AV_CODEC_ID_DVAUDIO, MKTAG('d', 'v', 'c', 'a') }, + { AV_CODEC_ID_GSM, MKTAG('a', 'g', 's', 'm') }, + { AV_CODEC_ID_ILBC, MKTAG('i', 'l', 'b', 'c') }, + { AV_CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') }, + { AV_CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, + { AV_CODEC_ID_MP1, MKTAG('.', 'm', 'p', '1') }, + { AV_CODEC_ID_MP2, MKTAG('.', 'm', 'p', '2') }, + { AV_CODEC_ID_MP3, MKTAG('.', 'm', 'p', '3') }, + { AV_CODEC_ID_MP3, MKTAG('m', 'p', '3', ' ') }, /* vlc */ + { AV_CODEC_ID_MP3, 0x6D730055 }, + { AV_CODEC_ID_NELLYMOSER, MKTAG('n', 'm', 'o', 's') }, /* Flash Media Server */ + { AV_CODEC_ID_NELLYMOSER, MKTAG('N', 'E', 'L', 'L') }, /* Perian */ + { AV_CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') }, + { AV_CODEC_ID_PCM_F32BE, MKTAG('f', 'l', '3', '2') }, + { AV_CODEC_ID_PCM_F32LE, MKTAG('f', 'l', '3', '2') }, + { AV_CODEC_ID_PCM_F64BE, MKTAG('f', 'l', '6', '4') }, + { AV_CODEC_ID_PCM_F64LE, MKTAG('f', 'l', '6', '4') }, + { AV_CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') }, + { AV_CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') }, + { 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_S24BE, MKTAG('i', 'n', '2', '4') }, + { AV_CODEC_ID_PCM_S24LE, MKTAG('i', 'n', '2', '4') }, + { 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') }, + { AV_CODEC_ID_PCM_U8, MKTAG('r', 'a', 'w', ' ') }, + { AV_CODEC_ID_PCM_U8, MKTAG('N', 'O', 'N', 'E') }, + { AV_CODEC_ID_QCELP, MKTAG('Q', 'c', 'l', 'p') }, + { AV_CODEC_ID_QCELP, MKTAG('Q', 'c', 'l', 'q') }, + { AV_CODEC_ID_QCELP, MKTAG('s', 'q', 'c', 'p') }, /* ISO Media fourcc */ + { AV_CODEC_ID_QDM2, MKTAG('Q', 'D', 'M', '2') }, + { AV_CODEC_ID_QDMC, MKTAG('Q', 'D', 'M', 'C') }, + { AV_CODEC_ID_SPEEX, MKTAG('s', 'p', 'e', 'x') }, /* Flash Media Server */ + { AV_CODEC_ID_SPEEX, MKTAG('S', 'P', 'X', 'N') }, /* ZygoAudio (quality 10 mode) */ + { AV_CODEC_ID_EVRC, MKTAG('s', 'e', 'v', 'c') }, /* 3GPP2 */ + { AV_CODEC_ID_SMV, MKTAG('s', 's', 'm', 'v') }, /* 3GPP2 */ + { AV_CODEC_ID_FLAC, MKTAG('f', 'L', 'a', 'C') }, /* nonstandard */ + { AV_CODEC_ID_TRUEHD, MKTAG('m', 'l', 'p', 'a') }, /* mp4ra.org */ + { AV_CODEC_ID_OPUS, MKTAG('O', 'p', 'u', 's') }, /* mp4ra.org */ + { AV_CODEC_ID_MPEGH_3D_AUDIO, MKTAG('m', 'h', 'm', '1') }, /* MPEG-H 3D Audio bitstream */ + { AV_CODEC_ID_NONE, 0 }, +}; + +const struct AVCodecTag *avformat_get_mov_video_tags(void) +{ + return ff_codec_movvideo_tags; +} + +const struct AVCodecTag *avformat_get_mov_audio_tags(void) +{ + return ff_codec_movaudio_tags; +} diff -Nru ffmpeg-4.2.2/libavformat/iv8.c ffmpeg-4.4/libavformat/iv8.c --- ffmpeg-4.2.2/libavformat/iv8.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/iv8.c 2020-07-11 10:39:30.000000000 +0000 @@ -92,7 +92,6 @@ ret = av_append_packet(s->pb, pkt, size); if (ret < 0) { av_log(s, AV_LOG_ERROR, "failed to grow packet\n"); - av_packet_unref(pkt); return ret; } } diff -Nru ffmpeg-4.2.2/libavformat/ivfdec.c ffmpeg-4.4/libavformat/ivfdec.c --- ffmpeg-4.2.2/libavformat/ivfdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ivfdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -53,7 +53,8 @@ st->codecpar->height = avio_rl16(s->pb); time_base.den = avio_rl32(s->pb); time_base.num = avio_rl32(s->pb); - st->duration = avio_rl64(s->pb); + st->duration = avio_rl32(s->pb); + avio_skip(s->pb, 4); // unused st->need_parsing = AVSTREAM_PARSE_HEADERS; diff -Nru ffmpeg-4.2.2/libavformat/ivfenc.c ffmpeg-4.4/libavformat/ivfenc.c --- ffmpeg-4.2.2/libavformat/ivfenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ivfenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,13 +23,12 @@ typedef struct IVFEncContext { unsigned frame_cnt; - uint64_t last_pts, sum_delta_pts; + uint64_t last_pts, sum_delta_pts, last_pkt_duration; } IVFEncContext; -static int ivf_write_header(AVFormatContext *s) +static int ivf_init(AVFormatContext *s) { AVCodecParameters *par; - AVIOContext *pb = s->pb; if (s->nb_streams != 1) { av_log(s, AV_LOG_ERROR, "Format supports only exactly one video stream\n"); @@ -43,6 +42,25 @@ av_log(s, AV_LOG_ERROR, "Currently only VP8, VP9 and AV1 are supported!\n"); return AVERROR(EINVAL); } + + if (par->codec_id == AV_CODEC_ID_VP9) { + int ret = ff_stream_add_bitstream_filter(s->streams[0], "vp9_superframe", NULL); + if (ret < 0) + return ret; + } else if (par->codec_id == AV_CODEC_ID_AV1) { + int ret = ff_stream_add_bitstream_filter(s->streams[0], "av1_metadata", "td=insert"); + if (ret < 0) + return ret; + } + + return 0; +} + +static int ivf_write_header(AVFormatContext *s) +{ + AVCodecParameters *par = s->streams[0]->codecpar; + AVIOContext *pb = s->pb; + avio_write(pb, "DKIF", 4); avio_wl16(pb, 0); // version avio_wl16(pb, 32); // header length @@ -53,7 +71,7 @@ avio_wl16(pb, par->height); avio_wl32(pb, s->streams[0]->time_base.den); avio_wl32(pb, s->streams[0]->time_base.num); - avio_wl64(pb, 0xFFFFFFFFFFFFFFFFULL); + avio_wl64(pb, 0xFFFFFFFFFFFFFFFFULL); // length is overwritten at the end of muxing return 0; } @@ -68,6 +86,7 @@ avio_write(pb, pkt->data, pkt->size); if (ctx->frame_cnt) ctx->sum_delta_pts += pkt->pts - ctx->last_pts; + ctx->last_pkt_duration = pkt->duration; ctx->frame_cnt++; ctx->last_pts = pkt->pts; @@ -79,30 +98,22 @@ AVIOContext *pb = s->pb; IVFEncContext *ctx = s->priv_data; - if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && ctx->frame_cnt > 1) { - size_t end = avio_tell(pb); + if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && + (ctx->frame_cnt > 1 || (ctx->frame_cnt == 1 && ctx->last_pkt_duration))) { + int64_t end = avio_tell(pb); avio_seek(pb, 24, SEEK_SET); - avio_wl64(pb, ctx->frame_cnt * ctx->sum_delta_pts / (ctx->frame_cnt - 1)); + // overwrite the "length" field (duration) + avio_wl32(pb, ctx->last_pkt_duration ? + ctx->sum_delta_pts + ctx->last_pkt_duration : + ctx->frame_cnt * ctx->sum_delta_pts / (ctx->frame_cnt - 1)); + avio_wl32(pb, 0); // zero out unused bytes avio_seek(pb, end, SEEK_SET); } return 0; } -static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) -{ - int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; - - if (st->codecpar->codec_id == AV_CODEC_ID_VP9) - ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL); - else if (st->codecpar->codec_id == AV_CODEC_ID_AV1) - ret = ff_stream_add_bitstream_filter(st, "av1_metadata", "td=insert"); - - return ret; -} - static const AVCodecTag codec_ivf_tags[] = { { AV_CODEC_ID_VP8, MKTAG('V', 'P', '8', '0') }, { AV_CODEC_ID_VP9, MKTAG('V', 'P', '9', '0') }, @@ -117,9 +128,9 @@ .extensions = "ivf", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_VP8, + .init = ivf_init, .write_header = ivf_write_header, .write_packet = ivf_write_packet, .write_trailer = ivf_write_trailer, - .check_bitstream = ivf_check_bitstream, .codec_tag = (const AVCodecTag* const []){ codec_ivf_tags, 0 }, }; diff -Nru ffmpeg-4.2.2/libavformat/jacosubdec.c ffmpeg-4.4/libavformat/jacosubdec.c --- ffmpeg-4.2.2/libavformat/jacosubdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/jacosubdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -125,8 +125,8 @@ return NULL; shift_and_ret: - ts_start64 = (ts_start + jacosub->shift) * 100LL / jacosub->timeres; - ts_end64 = (ts_end + jacosub->shift) * 100LL / jacosub->timeres; + ts_start64 = (ts_start + (int64_t)jacosub->shift) * 100LL / jacosub->timeres; + ts_end64 = (ts_end + (int64_t)jacosub->shift) * 100LL / jacosub->timeres; *start = ts_start64; *duration = ts_end64 - ts_start64; return buf + len; @@ -136,6 +136,7 @@ { int sign = 1; int a = 0, b = 0, c = 0, d = 0; + int64_t ret; #define SSEP "%*1[.:]" int n = sscanf(buf, "%d"SSEP"%d"SSEP"%d"SSEP"%d", &a, &b, &c, &d); #undef SSEP @@ -145,13 +146,22 @@ a = FFABS(a); } + ret = 0; switch (n) { - case 4: return sign * ((a*3600 + b*60 + c) * timeres + d); - case 3: return sign * (( a*60 + b) * timeres + c); - case 2: return sign * (( a) * timeres + b); + case 4: + ret = sign * (((int64_t)a*3600 + b*60 + c) * timeres + d); + break; + case 3: + ret = sign * (( (int64_t)a*60 + b) * timeres + c); + break; + case 2: + ret = sign * (( (int64_t)a) * timeres + b); + break; } + if ((int)ret != ret) + ret = 0; - return 0; + return ret; } static int jacosub_read_header(AVFormatContext *s) @@ -188,8 +198,11 @@ AVPacket *sub; sub = ff_subtitles_queue_insert(&jacosub->q, line, len, merge_line); - if (!sub) - return AVERROR(ENOMEM); + if (!sub) { + av_bprint_finalize(&header, NULL); + ret = AVERROR(ENOMEM); + goto fail; + } sub->pos = pos; merge_line = len > 1 && !strcmp(&line[len - 2], "\\\n"); continue; @@ -238,7 +251,7 @@ /* SHIFT and TIMERES affect the whole script so packet timing can only be * done in a second pass */ for (i = 0; i < jacosub->q.nb_subs; i++) { - AVPacket *sub = &jacosub->q.subs[i]; + AVPacket *sub = jacosub->q.subs[i]; read_ts(jacosub, sub->data, &sub->pts, &sub->duration); } ff_subtitles_queue_finalize(s, &jacosub->q); diff -Nru ffmpeg-4.2.2/libavformat/jacosubenc.c ffmpeg-4.4/libavformat/jacosubenc.c --- ffmpeg-4.2.2/libavformat/jacosubenc.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/jacosubenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -25,7 +25,6 @@ if (par->extradata_size) { avio_write(s->pb, par->extradata, par->extradata_size - 1); - avio_flush(s->pb); } return 0; } diff -Nru ffmpeg-4.2.2/libavformat/jvdec.c ffmpeg-4.4/libavformat/jvdec.c --- ffmpeg-4.2.2/libavformat/jvdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/jvdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -113,9 +113,10 @@ return AVERROR(ENOMEM); jv->frames = av_malloc(ast->nb_index_entries * sizeof(JVFrame)); - if (!jv->frames) + if (!jv->frames) { + av_freep(&ast->index_entries); return AVERROR(ENOMEM); - + } offset = 0x68 + ast->nb_index_entries * 16; for (i = 0; i < ast->nb_index_entries; i++) { AVIndexEntry *e = ast->index_entries + i; @@ -137,6 +138,8 @@ - jvf->palette_size < 0) { if (s->error_recognition & AV_EF_EXPLODE) { read_close(s); + av_freep(&jv->frames); + av_freep(&ast->index_entries); return AVERROR_INVALIDDATA; } jvf->audio_size = @@ -165,6 +168,7 @@ JVDemuxContext *jv = s->priv_data; AVIOContext *pb = s->pb; AVStream *ast = s->streams[0]; + int ret; while (!avio_feof(s->pb) && jv->pts < ast->nb_index_entries) { const AVIndexEntry *e = ast->index_entries + jv->pts; @@ -174,8 +178,8 @@ case JV_AUDIO: jv->state++; if (jvf->audio_size) { - if (av_get_packet(s->pb, pkt, jvf->audio_size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_get_packet(s->pb, pkt, jvf->audio_size)) < 0) + return ret; pkt->stream_index = 0; pkt->pts = e->timestamp; pkt->flags |= AV_PKT_FLAG_KEY; @@ -184,10 +188,9 @@ case JV_VIDEO: jv->state++; if (jvf->video_size || jvf->palette_size) { - int ret; int size = jvf->video_size + jvf->palette_size; - if (av_new_packet(pkt, size + JV_PREAMBLE_SIZE)) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, size + JV_PREAMBLE_SIZE)) < 0) + return ret; AV_WL32(pkt->data, jvf->video_size); pkt->data[4] = jvf->video_type; diff -Nru ffmpeg-4.2.2/libavformat/kvag.c ffmpeg-4.4/libavformat/kvag.c --- ffmpeg-4.2.2/libavformat/kvag.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/kvag.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,207 @@ +/* + * Simon & Schuster Interactive VAG (de)muxer + * + * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.com) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "avformat.h" +#include "internal.h" +#include "rawenc.h" +#include "libavutil/intreadwrite.h" + +#define KVAG_TAG MKTAG('K', 'V', 'A', 'G') +#define KVAG_HEADER_SIZE 14 +#define KVAG_MAX_READ_SIZE 4096 + +typedef struct KVAGHeader { + uint32_t magic; + uint32_t data_size; + uint32_t sample_rate; + uint16_t stereo; +} KVAGHeader; + +#if CONFIG_KVAG_DEMUXER +static int kvag_probe(const AVProbeData *p) +{ + if (AV_RL32(p->buf) != KVAG_TAG) + return 0; + + return AVPROBE_SCORE_EXTENSION + 1; +} + +static int kvag_read_header(AVFormatContext *s) +{ + int ret; + AVStream *st; + KVAGHeader hdr; + AVCodecParameters *par; + uint8_t buf[KVAG_HEADER_SIZE]; + + if (!(st = avformat_new_stream(s, NULL))) + return AVERROR(ENOMEM); + + if ((ret = avio_read(s->pb, buf, KVAG_HEADER_SIZE)) < 0) + return ret; + else if (ret != KVAG_HEADER_SIZE) + return AVERROR(EIO); + + hdr.magic = AV_RL32(buf + 0); + hdr.data_size = AV_RL32(buf + 4); + hdr.sample_rate = AV_RL32(buf + 8); + hdr.stereo = AV_RL16(buf + 12); + + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = AV_CODEC_ID_ADPCM_IMA_SSI; + par->format = AV_SAMPLE_FMT_S16; + + if (hdr.stereo) { + par->channel_layout = AV_CH_LAYOUT_STEREO; + par->channels = 2; + } else { + par->channel_layout = AV_CH_LAYOUT_MONO; + par->channels = 1; + } + + par->sample_rate = hdr.sample_rate; + par->bits_per_coded_sample = 4; + par->bits_per_raw_sample = 16; + par->block_align = 1; + par->bit_rate = par->channels * + (uint64_t)par->sample_rate * + par->bits_per_coded_sample; + + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + st->start_time = 0; + st->duration = hdr.data_size * + (8 / par->bits_per_coded_sample) / + par->channels; + + return 0; +} + +static int kvag_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + int ret; + AVCodecParameters *par = s->streams[0]->codecpar; + + if ((ret = av_get_packet(s->pb, pkt, KVAG_MAX_READ_SIZE)) < 0) + return ret; + + pkt->flags &= ~AV_PKT_FLAG_CORRUPT; + pkt->stream_index = 0; + pkt->duration = ret * (8 / par->bits_per_coded_sample) / par->channels; + + return 0; +} + +static int kvag_seek(AVFormatContext *s, int stream_index, + int64_t pts, int flags) +{ + if (pts != 0) + return AVERROR(EINVAL); + + return avio_seek(s->pb, KVAG_HEADER_SIZE, SEEK_SET); +} + +AVInputFormat ff_kvag_demuxer = { + .name = "kvag", + .long_name = NULL_IF_CONFIG_SMALL("Simon & Schuster Interactive VAG"), + .read_probe = kvag_probe, + .read_header = kvag_read_header, + .read_packet = kvag_read_packet, + .read_seek = kvag_seek, +}; +#endif + +#if CONFIG_KVAG_MUXER +static int kvag_write_init(AVFormatContext *s) +{ + AVCodecParameters *par; + + if (s->nb_streams != 1) { + av_log(s, AV_LOG_ERROR, "KVAG files have exactly one stream\n"); + return AVERROR(EINVAL); + } + + par = s->streams[0]->codecpar; + + if (par->codec_id != AV_CODEC_ID_ADPCM_IMA_SSI) { + av_log(s, AV_LOG_ERROR, "%s codec not supported\n", + avcodec_get_name(par->codec_id)); + return AVERROR(EINVAL); + } + + if (par->channels > 2) { + av_log(s, AV_LOG_ERROR, "KVAG files only support up to 2 channels\n"); + return AVERROR(EINVAL); + } + + if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) { + av_log(s, AV_LOG_WARNING, "Stream not seekable, unable to write output file\n"); + return AVERROR(EINVAL); + } + + return 0; +} + +static int kvag_write_header(AVFormatContext *s) +{ + uint8_t buf[KVAG_HEADER_SIZE]; + AVCodecParameters *par = s->streams[0]->codecpar; + + AV_WL32(buf + 0, KVAG_TAG); + AV_WL32(buf + 4, 0); /* Data size, we fix this up later. */ + AV_WL32(buf + 8, par->sample_rate); + AV_WL16(buf + 12, par->channels == 2); + + avio_write(s->pb, buf, sizeof(buf)); + return 0; +} + +static int kvag_write_trailer(AVFormatContext *s) +{ + int64_t file_size, data_size; + + file_size = avio_tell(s->pb); + data_size = file_size - KVAG_HEADER_SIZE; + if (data_size < UINT32_MAX) { + avio_seek(s->pb, 4, SEEK_SET); + avio_wl32(s->pb, (uint32_t)data_size); + avio_seek(s->pb, file_size, SEEK_SET); + } else { + av_log(s, AV_LOG_WARNING, + "Filesize %"PRId64" invalid for KVAG, output file will be broken\n", + file_size); + } + + return 0; +} + +AVOutputFormat ff_kvag_muxer = { + .name = "kvag", + .long_name = NULL_IF_CONFIG_SMALL("Simon & Schuster Interactive VAG"), + .extensions = "vag", + .audio_codec = AV_CODEC_ID_ADPCM_IMA_SSI, + .video_codec = AV_CODEC_ID_NONE, + .init = kvag_write_init, + .write_header = kvag_write_header, + .write_packet = ff_raw_write_packet, + .write_trailer = kvag_write_trailer +}; +#endif diff -Nru ffmpeg-4.2.2/libavformat/latmenc.c ffmpeg-4.4/libavformat/latmenc.c --- ffmpeg-4.2.2/libavformat/latmenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/latmenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -53,27 +53,28 @@ .version = LIBAVUTIL_VERSION_INT, }; -static int latm_decode_extradata(LATMContext *ctx, uint8_t *buf, int size) +static int latm_decode_extradata(AVFormatContext *s, uint8_t *buf, int size) { + LATMContext *ctx = s->priv_data; MPEG4AudioConfig m4ac; if (size > MAX_EXTRADATA_SIZE) { - av_log(ctx, AV_LOG_ERROR, "Extradata is larger than currently supported.\n"); + av_log(s, AV_LOG_ERROR, "Extradata is larger than currently supported.\n"); return AVERROR_INVALIDDATA; } - ctx->off = avpriv_mpeg4audio_get_config(&m4ac, buf, size * 8, 1); + ctx->off = avpriv_mpeg4audio_get_config2(&m4ac, buf, size, 1, s); if (ctx->off < 0) return ctx->off; if (ctx->object_type == AOT_ALS && (ctx->off & 7)) { // as long as avpriv_mpeg4audio_get_config works correctly this is impossible - av_log(ctx, AV_LOG_ERROR, "BUG: ALS offset is not byte-aligned\n"); + av_log(s, AV_LOG_ERROR, "BUG: ALS offset is not byte-aligned\n"); return AVERROR_INVALIDDATA; } /* FIXME: are any formats not allowed in LATM? */ if (m4ac.object_type > AOT_SBR && m4ac.object_type != AOT_ALS) { - av_log(ctx, AV_LOG_ERROR, "Muxing MPEG-4 AOT %d in LATM is not supported\n", m4ac.object_type); + av_log(s, AV_LOG_ERROR, "Muxing MPEG-4 AOT %d in LATM is not supported\n", m4ac.object_type); return AVERROR_INVALIDDATA; } ctx->channel_conf = m4ac.chan_config; @@ -84,23 +85,33 @@ static int latm_write_header(AVFormatContext *s) { - LATMContext *ctx = s->priv_data; AVCodecParameters *par = s->streams[0]->codecpar; if (par->codec_id == AV_CODEC_ID_AAC_LATM) return 0; if (par->codec_id != AV_CODEC_ID_AAC && par->codec_id != AV_CODEC_ID_MP4ALS) { - av_log(ctx, AV_LOG_ERROR, "Only AAC, LATM and ALS are supported\n"); + av_log(s, AV_LOG_ERROR, "Only AAC, LATM and ALS are supported\n"); return AVERROR(EINVAL); } if (par->extradata_size > 0 && - latm_decode_extradata(ctx, par->extradata, par->extradata_size) < 0) + latm_decode_extradata(s, par->extradata, par->extradata_size) < 0) return AVERROR_INVALIDDATA; return 0; } +static void copy_bits(PutBitContext *pb, const uint8_t *src, int length) +{ + int words = length >> 4; + int bits = length & 15; + int i; + for (i = 0; i < words; i++) + put_bits(pb, 16, AV_RB16(src + 2 * i)); + if (bits) + put_bits(pb, bits, AV_RB16(src + 2 * words) >> (16 - bits)); +} + static void latm_write_frame_header(AVFormatContext *s, PutBitContext *bs) { LATMContext *ctx = s->priv_data; @@ -120,12 +131,12 @@ /* AudioSpecificConfig */ if (ctx->object_type == AOT_ALS) { - header_size = par->extradata_size-(ctx->off >> 3); - avpriv_copy_bits(bs, &par->extradata[ctx->off >> 3], header_size); + header_size = (par->extradata_size - (ctx->off >> 3)) * 8; + copy_bits(bs, &par->extradata[ctx->off >> 3], header_size); } else { // + 3 assumes not scalable and dependsOnCoreCoder == 0, // see decode_ga_specific_config in libavcodec/aacdec.c - avpriv_copy_bits(bs, par->extradata, ctx->off + 3); + copy_bits(bs, par->extradata, ctx->off + 3); if (!ctx->channel_conf) { GetBitContext gb; @@ -165,18 +176,20 @@ return ff_raw_write_packet(s, pkt); else { uint8_t *side_data; - int side_data_size = 0, ret; + buffer_size_t side_data_size; + int ret; side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_data_size); if (side_data_size) { - if (latm_decode_extradata(ctx, side_data, side_data_size) < 0) + if (latm_decode_extradata(s, side_data, side_data_size) < 0) return AVERROR_INVALIDDATA; ret = ff_alloc_extradata(par, side_data_size); if (ret < 0) return ret; memcpy(par->extradata, side_data, side_data_size); - } + } else + return AVERROR_INVALIDDATA; } } @@ -206,11 +219,10 @@ // This allows us to remux our FATE AAC samples into latm // files that are still playable with minimal effort. put_bits(&bs, 8, pkt->data[0] & 0xfe); - avpriv_copy_bits(&bs, pkt->data + 1, 8*pkt->size - 8); + copy_bits(&bs, pkt->data + 1, 8*pkt->size - 8); } else - avpriv_copy_bits(&bs, pkt->data, 8*pkt->size); + copy_bits(&bs, pkt->data, 8*pkt->size); - avpriv_align_put_bits(&bs); flush_put_bits(&bs); len = put_bits_count(&bs) >> 3; diff -Nru ffmpeg-4.2.2/libavformat/libamqp.c ffmpeg-4.4/libavformat/libamqp.c --- ffmpeg-4.2.2/libavformat/libamqp.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/libamqp.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,323 @@ +/* + * Advanced Message Queuing Protocol (AMQP) 0-9-1 + * Copyright (c) 2020 Andriy Gelman + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "avformat.h" +#include "libavutil/avstring.h" +#include "libavutil/opt.h" +#include "libavutil/time.h" +#include "network.h" +#include "url.h" +#include "urldecode.h" + +typedef struct AMQPContext { + const AVClass *class; + amqp_connection_state_t conn; + amqp_socket_t *socket; + const char *exchange; + const char *routing_key; + int pkt_size; + int64_t connection_timeout; + int pkt_size_overflow; + int delivery_mode; +} AMQPContext; + +#define STR_LEN 1024 +#define DEFAULT_CHANNEL 1 + +#define OFFSET(x) offsetof(AMQPContext, x) +#define D AV_OPT_FLAG_DECODING_PARAM +#define E AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "pkt_size", "Maximum send/read packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = 131072 }, 4096, INT_MAX, .flags = D | E }, + { "exchange", "Exchange to send/read packets", OFFSET(exchange), AV_OPT_TYPE_STRING, { .str = "amq.direct" }, 0, 0, .flags = D | E }, + { "routing_key", "Key to filter streams", OFFSET(routing_key), AV_OPT_TYPE_STRING, { .str = "amqp" }, 0, 0, .flags = D | E }, + { "connection_timeout", "Initial connection timeout", OFFSET(connection_timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT64_MAX, .flags = D | E}, + { "delivery_mode", "Delivery mode", OFFSET(delivery_mode), AV_OPT_TYPE_INT, { .i64 = AMQP_DELIVERY_PERSISTENT }, 1, 2, .flags = E, "delivery_mode"}, + { "persistent", "Persistent delivery mode", 0, AV_OPT_TYPE_CONST, { .i64 = AMQP_DELIVERY_PERSISTENT }, 0, 0, E, "delivery_mode" }, + { "non-persistent", "Non-persistent delivery mode", 0, AV_OPT_TYPE_CONST, { .i64 = AMQP_DELIVERY_NONPERSISTENT }, 0, 0, E, "delivery_mode" }, + { NULL } +}; + +static int amqp_proto_open(URLContext *h, const char *uri, int flags) +{ + int ret, server_msg; + char hostname[STR_LEN], credentials[STR_LEN], path[STR_LEN]; + int port; + const char *user, *password = NULL, *vhost; + const char *user_decoded, *password_decoded, *vhost_decoded; + char *p; + amqp_rpc_reply_t broker_reply; + struct timeval tval = { 0 }; + + AMQPContext *s = h->priv_data; + + h->is_streamed = 1; + h->max_packet_size = s->pkt_size; + + av_url_split(NULL, 0, credentials, sizeof(credentials), + hostname, sizeof(hostname), &port, path, sizeof(path), uri); + + if (port < 0) + port = 5672; + + if (hostname[0] == '\0' || port <= 0 || port > 65535 ) { + av_log(h, AV_LOG_ERROR, "Invalid hostname/port\n"); + return AVERROR(EINVAL); + } + + p = strchr(credentials, ':'); + if (p) { + *p = '\0'; + password = p + 1; + } + + if (!password || *password == '\0') + password = "guest"; + + password_decoded = ff_urldecode(password, 0); + if (!password_decoded) + return AVERROR(ENOMEM); + + user = credentials; + if (*user == '\0') + user = "guest"; + + user_decoded = ff_urldecode(user, 0); + if (!user_decoded) { + av_freep(&password_decoded); + return AVERROR(ENOMEM); + } + + /* skip query for now */ + p = strchr(path, '?'); + if (p) + *p = '\0'; + + vhost = path; + if (*vhost == '\0') + vhost = "/"; + else + vhost++; /* skip leading '/' */ + + vhost_decoded = ff_urldecode(vhost, 0); + if (!vhost_decoded) { + av_freep(&user_decoded); + av_freep(&password_decoded); + return AVERROR(ENOMEM); + } + + s->conn = amqp_new_connection(); + if (!s->conn) { + av_freep(&vhost_decoded); + av_freep(&user_decoded); + av_freep(&password_decoded); + av_log(h, AV_LOG_ERROR, "Error creating connection\n"); + return AVERROR_EXTERNAL; + } + + s->socket = amqp_tcp_socket_new(s->conn); + if (!s->socket) { + av_log(h, AV_LOG_ERROR, "Error creating socket\n"); + goto destroy_connection; + } + + if (s->connection_timeout < 0) + s->connection_timeout = (h->rw_timeout > 0 ? h->rw_timeout : 5000000); + + tval.tv_sec = s->connection_timeout / 1000000; + tval.tv_usec = s->connection_timeout % 1000000; + ret = amqp_socket_open_noblock(s->socket, hostname, port, &tval); + + if (ret) { + av_log(h, AV_LOG_ERROR, "Error connecting to server: %s\n", + amqp_error_string2(ret)); + goto destroy_connection; + } + + broker_reply = amqp_login(s->conn, vhost_decoded, 0, s->pkt_size, 0, + AMQP_SASL_METHOD_PLAIN, user_decoded, password_decoded); + + if (broker_reply.reply_type != AMQP_RESPONSE_NORMAL) { + av_log(h, AV_LOG_ERROR, "Error login\n"); + server_msg = AMQP_ACCESS_REFUSED; + goto close_connection; + } + + amqp_channel_open(s->conn, DEFAULT_CHANNEL); + broker_reply = amqp_get_rpc_reply(s->conn); + + if (broker_reply.reply_type != AMQP_RESPONSE_NORMAL) { + av_log(h, AV_LOG_ERROR, "Error set channel\n"); + server_msg = AMQP_CHANNEL_ERROR; + goto close_connection; + } + + if (h->flags & AVIO_FLAG_READ) { + amqp_bytes_t queuename; + char queuename_buff[STR_LEN]; + amqp_queue_declare_ok_t *r; + + r = amqp_queue_declare(s->conn, DEFAULT_CHANNEL, amqp_empty_bytes, + 0, 0, 0, 1, amqp_empty_table); + broker_reply = amqp_get_rpc_reply(s->conn); + if (!r || broker_reply.reply_type != AMQP_RESPONSE_NORMAL) { + av_log(h, AV_LOG_ERROR, "Error declare queue\n"); + server_msg = AMQP_RESOURCE_ERROR; + goto close_channel; + } + + /* store queuename */ + queuename.bytes = queuename_buff; + queuename.len = FFMIN(r->queue.len, STR_LEN); + memcpy(queuename.bytes, r->queue.bytes, queuename.len); + + amqp_queue_bind(s->conn, DEFAULT_CHANNEL, queuename, + amqp_cstring_bytes(s->exchange), + amqp_cstring_bytes(s->routing_key), amqp_empty_table); + + broker_reply = amqp_get_rpc_reply(s->conn); + if (broker_reply.reply_type != AMQP_RESPONSE_NORMAL) { + av_log(h, AV_LOG_ERROR, "Queue bind error\n"); + server_msg = AMQP_INTERNAL_ERROR; + goto close_channel; + } + + amqp_basic_consume(s->conn, DEFAULT_CHANNEL, queuename, amqp_empty_bytes, + 0, 1, 0, amqp_empty_table); + + broker_reply = amqp_get_rpc_reply(s->conn); + if (broker_reply.reply_type != AMQP_RESPONSE_NORMAL) { + av_log(h, AV_LOG_ERROR, "Set consume error\n"); + server_msg = AMQP_INTERNAL_ERROR; + goto close_channel; + } + } + + av_freep(&vhost_decoded); + av_freep(&user_decoded); + av_freep(&password_decoded); + return 0; + +close_channel: + amqp_channel_close(s->conn, DEFAULT_CHANNEL, server_msg); +close_connection: + amqp_connection_close(s->conn, server_msg); +destroy_connection: + amqp_destroy_connection(s->conn); + + av_freep(&vhost_decoded); + av_freep(&user_decoded); + av_freep(&password_decoded); + return AVERROR_EXTERNAL; +} + +static int amqp_proto_write(URLContext *h, const unsigned char *buf, int size) +{ + int ret; + AMQPContext *s = h->priv_data; + int fd = amqp_socket_get_sockfd(s->socket); + + amqp_bytes_t message = { size, (void *)buf }; + amqp_basic_properties_t props; + + ret = ff_network_wait_fd_timeout(fd, 1, h->rw_timeout, &h->interrupt_callback); + if (ret) + return ret; + + props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG; + props.content_type = amqp_cstring_bytes("octet/stream"); + props.delivery_mode = s->delivery_mode; + + ret = amqp_basic_publish(s->conn, DEFAULT_CHANNEL, amqp_cstring_bytes(s->exchange), + amqp_cstring_bytes(s->routing_key), 0, 0, + &props, message); + + if (ret) { + av_log(h, AV_LOG_ERROR, "Error publish: %s\n", amqp_error_string2(ret)); + return AVERROR_EXTERNAL; + } + + return size; +} + +static int amqp_proto_read(URLContext *h, unsigned char *buf, int size) +{ + AMQPContext *s = h->priv_data; + int fd = amqp_socket_get_sockfd(s->socket); + int ret; + + amqp_rpc_reply_t broker_reply; + amqp_envelope_t envelope; + + ret = ff_network_wait_fd_timeout(fd, 0, h->rw_timeout, &h->interrupt_callback); + if (ret) + return ret; + + amqp_maybe_release_buffers(s->conn); + broker_reply = amqp_consume_message(s->conn, &envelope, NULL, 0); + + if (broker_reply.reply_type != AMQP_RESPONSE_NORMAL) + return AVERROR_EXTERNAL; + + if (envelope.message.body.len > size) { + s->pkt_size_overflow = FFMAX(s->pkt_size_overflow, envelope.message.body.len); + av_log(h, AV_LOG_WARNING, "Message exceeds space in the buffer. " + "Message will be truncated. Setting -pkt_size %d " + "may resolve this issue.\n", s->pkt_size_overflow); + } + size = FFMIN(size, envelope.message.body.len); + + memcpy(buf, envelope.message.body.bytes, size); + amqp_destroy_envelope(&envelope); + + return size; +} + +static int amqp_proto_close(URLContext *h) +{ + AMQPContext *s = h->priv_data; + amqp_channel_close(s->conn, DEFAULT_CHANNEL, AMQP_REPLY_SUCCESS); + amqp_connection_close(s->conn, AMQP_REPLY_SUCCESS); + amqp_destroy_connection(s->conn); + + return 0; +} + +static const AVClass amqp_context_class = { + .class_name = "amqp", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const URLProtocol ff_libamqp_protocol = { + .name = "amqp", + .url_close = amqp_proto_close, + .url_open = amqp_proto_open, + .url_read = amqp_proto_read, + .url_write = amqp_proto_write, + .priv_data_size = sizeof(AMQPContext), + .priv_data_class = &amqp_context_class, + .flags = URL_PROTOCOL_FLAG_NETWORK, +}; diff -Nru ffmpeg-4.2.2/libavformat/libgme.c ffmpeg-4.4/libavformat/libgme.c --- ffmpeg-4.2.2/libavformat/libgme.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/libgme.c 2021-04-08 21:28:40.000000000 +0000 @@ -31,7 +31,6 @@ typedef struct GMEContext { const AVClass *class; Music_Emu *music_emu; - gme_info_t *info; ///< selected track /* options */ int track_index; @@ -55,12 +54,16 @@ av_dict_set(&s->metadata, name, value, 0); } -static int load_metadata(AVFormatContext *s) +static int load_metadata(AVFormatContext *s, int64_t *duration) { GMEContext *gme = s->priv_data; - gme_info_t *info = gme->info; + gme_info_t *info = NULL; char buf[30]; + if (gme_track_info(gme->music_emu, &info, gme->track_index)) + return AVERROR_STREAM_NOT_FOUND; + + *duration = info->length; add_meta(s, "system", info->system); add_meta(s, "game", info->game); add_meta(s, "song", info->song); @@ -71,20 +74,30 @@ snprintf(buf, sizeof(buf), "%d", (int)gme_track_count(gme->music_emu)); add_meta(s, "tracks", buf); + gme_free_info(info); return 0; } #define AUDIO_PKT_SIZE 512 +static int read_close_gme(AVFormatContext *s) +{ + GMEContext *gme = s->priv_data; + gme_delete(gme->music_emu); + return 0; +} + static int read_header_gme(AVFormatContext *s) { AVStream *st; AVIOContext *pb = s->pb; GMEContext *gme = s->priv_data; int64_t sz = avio_size(pb); + int64_t duration; char *buf; char dummy; + int ret; if (sz < 0) { av_log(s, AV_LOG_WARNING, "Could not determine file size\n"); @@ -103,6 +116,7 @@ av_log(s, AV_LOG_ERROR, "File size is larger than max_size option " "value %"PRIi64", consider increasing the max_size option\n", gme->max_size); + av_freep(&buf); return AVERROR_BUFFER_TOO_SMALL; } @@ -112,20 +126,24 @@ } av_freep(&buf); - if (gme_track_info(gme->music_emu, &gme->info, gme->track_index)) - return AVERROR_STREAM_NOT_FOUND; - - if (gme_start_track(gme->music_emu, gme->track_index)) + ret = load_metadata(s, &duration); + if (ret < 0) { + read_close_gme(s); + return ret; + } + if (gme_start_track(gme->music_emu, gme->track_index)) { + read_close_gme(s); return AVERROR_UNKNOWN; - - load_metadata(s); + } st = avformat_new_stream(s, NULL); - if (!st) + if (!st) { + read_close_gme(s); return AVERROR(ENOMEM); + } avpriv_set_pts_info(st, 64, 1, 1000); if (st->duration > 0) - st->duration = gme->info->length; + st->duration = duration; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE); st->codecpar->channels = 2; @@ -153,14 +171,6 @@ return 0; } -static int read_close_gme(AVFormatContext *s) -{ - GMEContext *gme = s->priv_data; - gme_free_info(gme->info); - gme_delete(gme->music_emu); - return 0; -} - static int read_seek_gme(AVFormatContext *s, int stream_idx, int64_t ts, int flags) { GMEContext *gme = s->priv_data; diff -Nru ffmpeg-4.2.2/libavformat/libmodplug.c ffmpeg-4.4/libavformat/libmodplug.c --- ffmpeg-4.2.2/libavformat/libmodplug.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/libmodplug.c 2021-04-08 21:28:40.000000000 +0000 @@ -99,6 +99,14 @@ {NULL}, }; +static int modplug_read_close(AVFormatContext *s) +{ + ModPlugContext *modplug = s->priv_data; + ModPlug_Unload(modplug->f); + av_freep(&modplug->buf); + return 0; +} + #define SET_OPT_IF_REQUESTED(libopt, opt, flag) do { \ if (modplug->opt) { \ settings.libopt = modplug->opt; \ @@ -168,6 +176,7 @@ ModPlug_Settings settings; ModPlugContext *modplug = s->priv_data; int64_t sz = avio_size(pb); + int ret; if (sz < 0) { av_log(s, AV_LOG_WARNING, "Could not determine file size\n"); @@ -216,12 +225,15 @@ ModPlug_SetSettings(&settings); modplug->f = ModPlug_Load(modplug->buf, sz); - if (!modplug->f) + if (!modplug->f) { + av_freep(&modplug->buf); return AVERROR_INVALIDDATA; - + } st = avformat_new_stream(s, NULL); - if (!st) - return AVERROR(ENOMEM); + if (!st) { + ret = AVERROR(ENOMEM); + goto fail; + } avpriv_set_pts_info(st, 64, 1, 1000); st->duration = ModPlug_GetLength(modplug->f); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; @@ -234,8 +246,10 @@ if (modplug->video_stream) { AVStream *vst = avformat_new_stream(s, NULL); - if (!vst) - return AVERROR(ENOMEM); + if (!vst) { + ret = AVERROR(ENOMEM); + goto fail; + } avpriv_set_pts_info(vst, 64, 1, 1000); vst->duration = st->duration; vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; @@ -246,7 +260,13 @@ modplug->fsize = modplug->linesize * modplug->h; } - return modplug_load_metadata(s); + ret = modplug_load_metadata(s); + if (ret < 0) + goto fail; + return 0; +fail: + modplug_read_close(s); + return ret; } static void write_text(uint8_t *dst, const char *s, int linesize, int x, int y) @@ -269,6 +289,7 @@ static int modplug_read_packet(AVFormatContext *s, AVPacket *pkt) { ModPlugContext *modplug = s->priv_data; + int ret; if (modplug->video_stream) { modplug->video_switch ^= 1; // one video packet for one audio packet @@ -284,8 +305,8 @@ var_values[VAR_PATTERN] = ModPlug_GetCurrentPattern(modplug->f); var_values[VAR_ROW ] = ModPlug_GetCurrentRow (modplug->f); - if (av_new_packet(pkt, modplug->fsize) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, modplug->fsize)) < 0) + return ret; pkt->stream_index = 1; memset(pkt->data, 0, modplug->fsize); @@ -317,28 +338,19 @@ } } - if (av_new_packet(pkt, AUDIO_PKT_SIZE) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, AUDIO_PKT_SIZE)) < 0) + return ret; if (modplug->video_stream) pkt->pts = pkt->dts = modplug->packet_count++ * modplug->ts_per_packet; pkt->size = ModPlug_Read(modplug->f, pkt->data, AUDIO_PKT_SIZE); if (pkt->size <= 0) { - av_packet_unref(pkt); return pkt->size == 0 ? AVERROR_EOF : AVERROR(EIO); } return 0; } -static int modplug_read_close(AVFormatContext *s) -{ - ModPlugContext *modplug = s->priv_data; - ModPlug_Unload(modplug->f); - av_freep(&modplug->buf); - return 0; -} - static int modplug_read_seek(AVFormatContext *s, int stream_idx, int64_t ts, int flags) { ModPlugContext *modplug = s->priv_data; diff -Nru ffmpeg-4.2.2/libavformat/libopenmpt.c ffmpeg-4.4/libavformat/libopenmpt.c --- ffmpeg-4.2.2/libavformat/libopenmpt.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/libopenmpt.c 2021-04-08 21:28:40.000000000 +0000 @@ -218,7 +218,7 @@ return 0; } -static int probe_openmpt_extension(AVProbeData *p) +static int probe_openmpt_extension(const AVProbeData *p) { const char *ext; if (p->filename) { diff -Nru ffmpeg-4.2.2/libavformat/librist.c ffmpeg-4.4/libavformat/librist.c --- ffmpeg-4.2.2/libavformat/librist.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/librist.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,244 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * Reliable Internet Streaming Transport protocol + */ + +#include "libavutil/avassert.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "libavutil/time.h" + +#include "avformat.h" +#include "internal.h" +#include "network.h" +#include "os_support.h" +#include "url.h" + +#include + +// RIST_MAX_PACKET_SIZE - 28 minimum protocol overhead +#define MAX_PAYLOAD_SIZE (10000-28) + +typedef struct RISTContext { + const AVClass *class; + + int profile; + int buffer_size; + int packet_size; + int log_level; + int encryption; + char *secret; + + struct rist_logging_settings logging_settings; + struct rist_peer_config peer_config; + + struct rist_peer *peer; + struct rist_ctx *ctx; +} RISTContext; + +#define D AV_OPT_FLAG_DECODING_PARAM +#define E AV_OPT_FLAG_ENCODING_PARAM +#define OFFSET(x) offsetof(RISTContext, x) +static const AVOption librist_options[] = { + { "rist_profile","set profile", OFFSET(profile), AV_OPT_TYPE_INT, {.i64=RIST_PROFILE_MAIN}, 0, 2, .flags = D|E, "profile" }, + { "simple", NULL, 0, AV_OPT_TYPE_CONST, {.i64=RIST_PROFILE_SIMPLE}, 0, 0, .flags = D|E, "profile" }, + { "main", NULL, 0, AV_OPT_TYPE_CONST, {.i64=RIST_PROFILE_MAIN}, 0, 0, .flags = D|E, "profile" }, + { "advanced", NULL, 0, AV_OPT_TYPE_CONST, {.i64=RIST_PROFILE_ADVANCED}, 0, 0, .flags = D|E, "profile" }, + { "buffer_size", "set buffer_size in ms", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64=0}, 0, 30000, .flags = D|E }, + { "pkt_size", "set packet size", OFFSET(packet_size), AV_OPT_TYPE_INT, {.i64=1316}, 1, MAX_PAYLOAD_SIZE, .flags = D|E }, + { "log_level", "set loglevel", OFFSET(log_level), AV_OPT_TYPE_INT, {.i64=RIST_LOG_INFO}, -1, INT_MAX, .flags = D|E }, + { "secret", "set encryption secret",OFFSET(secret), AV_OPT_TYPE_STRING,{.str=NULL}, 0, 0, .flags = D|E }, + { "encryption","set encryption type",OFFSET(encryption), AV_OPT_TYPE_INT ,{.i64=0}, 0, INT_MAX, .flags = D|E }, + { NULL } +}; + +static int risterr2ret(int err) +{ + switch (err) { + case RIST_ERR_MALLOC: + return AVERROR(ENOMEM); + default: + return AVERROR_EXTERNAL; + } +} + +static int log_cb(void *arg, enum rist_log_level log_level, const char *msg) +{ + int level; + + switch (log_level) { + case RIST_LOG_ERROR: level = AV_LOG_ERROR; break; + case RIST_LOG_WARN: level = AV_LOG_WARNING; break; + case RIST_LOG_NOTICE: level = AV_LOG_INFO; break; + case RIST_LOG_INFO: level = AV_LOG_VERBOSE; break; + case RIST_LOG_DEBUG: level = AV_LOG_DEBUG; break; + case RIST_LOG_DISABLE: level = AV_LOG_QUIET; break; + default: level = AV_LOG_WARNING; + } + + av_log(arg, level, "%s", msg); + + return 0; +} + +static int librist_close(URLContext *h) +{ + RISTContext *s = h->priv_data; + int ret = 0; + + s->peer = NULL; + + if (s->ctx) + ret = rist_destroy(s->ctx); + s->ctx = NULL; + + return risterr2ret(ret); +} + +static int librist_open(URLContext *h, const char *uri, int flags) +{ + RISTContext *s = h->priv_data; + struct rist_logging_settings *logging_settings = &s->logging_settings; + struct rist_peer_config *peer_config = &s->peer_config; + int ret; + + if ((flags & AVIO_FLAG_READ_WRITE) == AVIO_FLAG_READ_WRITE) + return AVERROR(EINVAL); + + ret = rist_logging_set(&logging_settings, s->log_level, log_cb, h, NULL, NULL); + if (ret < 0) + return risterr2ret(ret); + + if (flags & AVIO_FLAG_WRITE) { + h->max_packet_size = s->packet_size; + ret = rist_sender_create(&s->ctx, s->profile, 0, logging_settings); + } + if (ret < 0) + goto err; + + if (flags & AVIO_FLAG_READ) { + h->max_packet_size = MAX_PAYLOAD_SIZE; + ret = rist_receiver_create(&s->ctx, s->profile, logging_settings); + } + if (ret < 0) + goto err; + + ret = rist_peer_config_defaults_set(peer_config); + if (ret < 0) + goto err; + + ret = rist_parse_address(uri, (const struct rist_peer_config **)&peer_config); + if (ret < 0) + goto err; + + if (((s->encryption == 128 || s->encryption == 256) && !s->secret) || + ((peer_config->key_size == 128 || peer_config->key_size == 256) && !peer_config->secret[0])) { + av_log(h, AV_LOG_ERROR, "secret is mandatory if encryption is enabled\n"); + librist_close(h); + return AVERROR(EINVAL); + } + + if (s->secret && peer_config->secret[0] == 0) + av_strlcpy(peer_config->secret, s->secret, RIST_MAX_STRING_SHORT); + + if (s->secret && (s->encryption == 128 || s->encryption == 256)) + peer_config->key_size = s->encryption; + + if (s->buffer_size) { + peer_config->recovery_length_min = s->buffer_size; + peer_config->recovery_length_max = s->buffer_size; + } + + ret = rist_peer_create(s->ctx, &s->peer, &s->peer_config); + if (ret < 0) + goto err; + + ret = rist_start(s->ctx); + if (ret < 0) + goto err; + + return 0; + +err: + librist_close(h); + + return risterr2ret(ret); +} + +static int librist_read(URLContext *h, uint8_t *buf, int size) +{ + RISTContext *s = h->priv_data; + const struct rist_data_block *data_block; + int ret; + + ret = rist_receiver_data_read(s->ctx, &data_block, POLLING_TIME); + if (ret < 0) + return risterr2ret(ret); + + if (ret == 0) + return AVERROR(EAGAIN); + + if (data_block->payload_len > MAX_PAYLOAD_SIZE) { + rist_receiver_data_block_free((struct rist_data_block**)&data_block); + return AVERROR_EXTERNAL; + } + + size = data_block->payload_len; + memcpy(buf, data_block->payload, size); + rist_receiver_data_block_free((struct rist_data_block**)&data_block); + + return size; +} + +static int librist_write(URLContext *h, const uint8_t *buf, int size) +{ + RISTContext *s = h->priv_data; + struct rist_data_block data_block = { 0 }; + int ret; + + data_block.ts_ntp = 0; + data_block.payload = buf; + data_block.payload_len = size; + + ret = rist_sender_data_write(s->ctx, &data_block); + if (ret < 0) + return risterr2ret(ret); + + return ret; +} + +static const AVClass librist_class = { + .class_name = "librist", + .item_name = av_default_item_name, + .option = librist_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const URLProtocol ff_librist_protocol = { + .name = "rist", + .url_open = librist_open, + .url_read = librist_read, + .url_write = librist_write, + .url_close = librist_close, + .priv_data_size = sizeof(RISTContext), + .flags = URL_PROTOCOL_FLAG_NETWORK, + .priv_data_class = &librist_class, +}; diff -Nru ffmpeg-4.2.2/libavformat/libsrt.c ffmpeg-4.4/libavformat/libsrt.c --- ffmpeg-4.2.2/libavformat/libsrt.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/libsrt.c 2021-04-08 21:28:40.000000000 +0000 @@ -62,6 +62,11 @@ int64_t maxbw; int pbkeylen; char *passphrase; +#if SRT_VERSION_VALUE >= 0x010302 + int enforced_encryption; + int kmrefreshrate; + int kmpreannounce; +#endif int mss; int ffs; int ipttl; @@ -84,14 +89,15 @@ char *smoother; int messageapi; SRT_TRANSTYPE transtype; + int linger; } SRTContext; #define D AV_OPT_FLAG_DECODING_PARAM #define E AV_OPT_FLAG_ENCODING_PARAM #define OFFSET(x) offsetof(SRTContext, x) static const AVOption libsrt_options[] = { - { "rw_timeout", "Timeout of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, - { "listen_timeout", "Connection awaiting timeout", OFFSET(listen_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "timeout", "Timeout of socket I/O operations (in microseconds)", OFFSET(rw_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "listen_timeout", "Connection awaiting timeout (in microseconds)" , OFFSET(listen_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, { "send_buffer_size", "Socket send buffer size (in bytes)", OFFSET(send_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "recv_buffer_size", "Socket receive buffer size (in bytes)", OFFSET(recv_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "pkt_size", "Maximum SRT packet size", OFFSET(payload_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, SRT_LIVE_MAX_PAYLOAD_SIZE, .flags = D|E, "payload_size" }, @@ -101,19 +107,24 @@ { "maxbw", "Maximum bandwidth (bytes per second) that the connection can use", OFFSET(maxbw), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, { "pbkeylen", "Crypto key len in bytes {16,24,32} Default: 16 (128-bit)", OFFSET(pbkeylen), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 32, .flags = D|E }, { "passphrase", "Crypto PBKDF2 Passphrase size[0,10..64] 0:disable crypto", OFFSET(passphrase), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, +#if SRT_VERSION_VALUE >= 0x010302 + { "enforced_encryption", "Enforces that both connection parties have the same passphrase set", OFFSET(enforced_encryption), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, .flags = D|E }, + { "kmrefreshrate", "The number of packets to be transmitted after which the encryption key is switched to a new key", OFFSET(kmrefreshrate), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "kmpreannounce", "The interval between when a new encryption key is sent and when switchover occurs", OFFSET(kmpreannounce), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, +#endif { "mss", "The Maximum Segment Size", OFFSET(mss), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1500, .flags = D|E }, { "ffs", "Flight flag size (window size) (in bytes)", OFFSET(ffs), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "ipttl", "IP Time To Live", OFFSET(ipttl), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, .flags = D|E }, { "iptos", "IP Type of Service", OFFSET(iptos), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, .flags = D|E }, { "inputbw", "Estimated input stream rate", OFFSET(inputbw), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, { "oheadbw", "MaxBW ceiling based on % over input stream rate", OFFSET(oheadbw), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 100, .flags = D|E }, - { "latency", "receiver delay to absorb bursts of missed packet retransmissions", OFFSET(latency), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "latency", "receiver delay (in microseconds) to absorb bursts of missed packet retransmissions", OFFSET(latency), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, { "tsbpddelay", "deprecated, same effect as latency option", OFFSET(latency), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, - { "rcvlatency", "receive latency", OFFSET(rcvlatency), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, - { "peerlatency", "peer latency", OFFSET(peerlatency), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, - { "tlpktdrop", "Enable receiver pkt drop", OFFSET(tlpktdrop), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, .flags = D|E }, - { "nakreport", "Enable receiver to send periodic NAK reports", OFFSET(nakreport), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, .flags = D|E }, - { "connect_timeout", "Connect timeout. Caller default: 3000, rendezvous (x 10)", OFFSET(connect_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "rcvlatency", "receive latency (in microseconds)", OFFSET(rcvlatency), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "peerlatency", "peer latency (in microseconds)", OFFSET(peerlatency), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, + { "tlpktdrop", "Enable too-late pkt drop", OFFSET(tlpktdrop), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, .flags = D|E }, + { "nakreport", "Enable receiver to send periodic NAK reports", OFFSET(nakreport), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, .flags = D|E }, + { "connect_timeout", "Connect timeout(in milliseconds). Caller default: 3000, rendezvous (x 10)", OFFSET(connect_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, { "mode", "Connection mode (caller, listener, rendezvous)", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = SRT_MODE_CALLER }, SRT_MODE_CALLER, SRT_MODE_RENDEZVOUS, .flags = D|E, "mode" }, { "caller", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = SRT_MODE_CALLER }, INT_MIN, INT_MAX, .flags = D|E, "mode" }, { "listener", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = SRT_MODE_LISTENER }, INT_MIN, INT_MAX, .flags = D|E, "mode" }, @@ -124,42 +135,57 @@ { "minversion", "The minimum SRT version that is required from the peer", OFFSET(minversion), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "streamid", "A string of up to 512 characters that an Initiator can pass to a Responder", OFFSET(streamid), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, { "smoother", "The type of Smoother used for the transmission for that socket", OFFSET(smoother), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, - { "messageapi", "Enable message API", OFFSET(messageapi), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, .flags = D|E }, + { "messageapi", "Enable message API", OFFSET(messageapi), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, .flags = D|E }, { "transtype", "The transmission type for the socket", OFFSET(transtype), AV_OPT_TYPE_INT, { .i64 = SRTT_INVALID }, SRTT_LIVE, SRTT_INVALID, .flags = D|E, "transtype" }, { "live", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = SRTT_LIVE }, INT_MIN, INT_MAX, .flags = D|E, "transtype" }, { "file", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = SRTT_FILE }, INT_MIN, INT_MAX, .flags = D|E, "transtype" }, + { "linger", "Number of seconds that the socket waits for unsent data when closing", OFFSET(linger), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { NULL } }; static int libsrt_neterrno(URLContext *h) { - int err = srt_getlasterror(NULL); - av_log(h, AV_LOG_ERROR, "%s\n", srt_getlasterror_str()); - if (err == SRT_EASYNCRCV) + int os_errno; + int err = srt_getlasterror(&os_errno); + if (err == SRT_EASYNCRCV || err == SRT_EASYNCSND) return AVERROR(EAGAIN); - return AVERROR_UNKNOWN; + av_log(h, AV_LOG_ERROR, "%s\n", srt_getlasterror_str()); + return os_errno ? AVERROR(os_errno) : AVERROR_UNKNOWN; } static int libsrt_socket_nonblock(int socket, int enable) { - int ret = srt_setsockopt(socket, 0, SRTO_SNDSYN, &enable, sizeof(enable)); + int ret, blocking = enable ? 0 : 1; + /* Setting SRTO_{SND,RCV}SYN options to 1 enable blocking mode, setting them to 0 enable non-blocking mode. */ + ret = srt_setsockopt(socket, 0, SRTO_SNDSYN, &blocking, sizeof(blocking)); if (ret < 0) return ret; - return srt_setsockopt(socket, 0, SRTO_RCVSYN, &enable, sizeof(enable)); + return srt_setsockopt(socket, 0, SRTO_RCVSYN, &blocking, sizeof(blocking)); +} + +static int libsrt_epoll_create(URLContext *h, int fd, int write) +{ + int modes = SRT_EPOLL_ERR | (write ? SRT_EPOLL_OUT : SRT_EPOLL_IN); + int eid = srt_epoll_create(); + if (eid < 0) + return libsrt_neterrno(h); + if (srt_epoll_add_usock(eid, fd, &modes) < 0) { + srt_epoll_release(eid); + return libsrt_neterrno(h); + } + return eid; } -static int libsrt_network_wait_fd(URLContext *h, int eid, int fd, int write) +static int libsrt_network_wait_fd(URLContext *h, int eid, int write) { - int ret, len = 1; - int modes = write ? SRT_EPOLL_OUT : SRT_EPOLL_IN; + int ret, len = 1, errlen = 1; SRTSOCKET ready[1]; + SRTSOCKET error[1]; - if (srt_epoll_add_usock(eid, fd, &modes) < 0) - return libsrt_neterrno(h); if (write) { - ret = srt_epoll_wait(eid, 0, 0, ready, &len, POLLING_TIME, 0, 0, 0, 0); + ret = srt_epoll_wait(eid, error, &errlen, ready, &len, POLLING_TIME, 0, 0, 0, 0); } else { - ret = srt_epoll_wait(eid, ready, &len, 0, 0, POLLING_TIME, 0, 0, 0, 0); + ret = srt_epoll_wait(eid, ready, &len, error, &errlen, POLLING_TIME, 0, 0, 0, 0); } if (ret < 0) { if (srt_getlasterror(NULL) == SRT_ETIMEOUT) @@ -167,16 +193,14 @@ else ret = libsrt_neterrno(h); } else { - ret = 0; + ret = errlen ? AVERROR(EIO) : 0; } - if (srt_epoll_remove_usock(eid, fd) < 0) - return libsrt_neterrno(h); return ret; } /* TODO de-duplicate code from ff_network_wait_fd_timeout() */ -static int libsrt_network_wait_fd_timeout(URLContext *h, int eid, int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb) +static int libsrt_network_wait_fd_timeout(URLContext *h, int eid, int write, int64_t timeout, AVIOInterruptCB *int_cb) { int ret; int64_t wait_start = 0; @@ -184,7 +208,7 @@ while (1) { if (ff_check_interrupt(int_cb)) return AVERROR_EXIT; - ret = libsrt_network_wait_fd(h, eid, fd, write); + ret = libsrt_network_wait_fd(h, eid, write); if (ret != AVERROR(EAGAIN)) return ret; if (timeout > 0) { @@ -196,29 +220,22 @@ } } -static int libsrt_listen(int eid, int fd, const struct sockaddr *addr, socklen_t addrlen, URLContext *h, int timeout) +static int libsrt_listen(int eid, int fd, const struct sockaddr *addr, socklen_t addrlen, URLContext *h, int64_t timeout) { int ret; int reuse = 1; if (srt_setsockopt(fd, SOL_SOCKET, SRTO_REUSEADDR, &reuse, sizeof(reuse))) { av_log(h, AV_LOG_WARNING, "setsockopt(SRTO_REUSEADDR) failed\n"); } - ret = srt_bind(fd, addr, addrlen); - if (ret) + if (srt_bind(fd, addr, addrlen)) return libsrt_neterrno(h); - ret = srt_listen(fd, 1); - if (ret) + if (srt_listen(fd, 1)) return libsrt_neterrno(h); - while ((ret = libsrt_network_wait_fd_timeout(h, eid, fd, 1, timeout, &h->interrupt_callback))) { - switch (ret) { - case AVERROR(ETIMEDOUT): - continue; - default: - return ret; - } - } + ret = libsrt_network_wait_fd_timeout(h, eid, 1, timeout, &h->interrupt_callback); + if (ret < 0) + return ret; ret = srt_accept(fd, NULL, NULL); if (ret < 0) @@ -229,41 +246,22 @@ return ret; } -static int libsrt_listen_connect(int eid, int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h, int will_try_next) +static int libsrt_listen_connect(int eid, int fd, const struct sockaddr *addr, socklen_t addrlen, int64_t timeout, URLContext *h, int will_try_next) { int ret; - if (libsrt_socket_nonblock(fd, 1) < 0) - av_log(h, AV_LOG_DEBUG, "ff_socket_nonblock failed\n"); + if (srt_connect(fd, addr, addrlen) < 0) + return libsrt_neterrno(h); - while ((ret = srt_connect(fd, addr, addrlen))) { - ret = libsrt_neterrno(h); - switch (ret) { - case AVERROR(EINTR): - if (ff_check_interrupt(&h->interrupt_callback)) - return AVERROR_EXIT; - continue; - case AVERROR(EINPROGRESS): - case AVERROR(EAGAIN): - ret = libsrt_network_wait_fd_timeout(h, eid, fd, 1, timeout, &h->interrupt_callback); - if (ret < 0) - return ret; - ret = srt_getlasterror(NULL); - srt_clearlasterror(); - if (ret != 0) { - char buf[128]; - ret = AVERROR(ret); - av_strerror(ret, buf, sizeof(buf)); - if (will_try_next) - av_log(h, AV_LOG_WARNING, - "Connection to %s failed (%s), trying next address\n", - h->filename, buf); - else - av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n", - h->filename, buf); - } - default: - return ret; + ret = libsrt_network_wait_fd_timeout(h, eid, 1, timeout, &h->interrupt_callback); + if (ret < 0) { + if (will_try_next) { + av_log(h, AV_LOG_WARNING, + "Connection to %s failed (%s), trying next address\n", + h->filename, av_err2str(ret)); + } else { + av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n", + h->filename, av_err2str(ret)); } } return ret; @@ -319,14 +317,24 @@ (s->maxbw >= 0 && libsrt_setsockopt(h, fd, SRTO_MAXBW, "SRTO_MAXBW", &s->maxbw, sizeof(s->maxbw)) < 0) || (s->pbkeylen >= 0 && libsrt_setsockopt(h, fd, SRTO_PBKEYLEN, "SRTO_PBKEYLEN", &s->pbkeylen, sizeof(s->pbkeylen)) < 0) || (s->passphrase && libsrt_setsockopt(h, fd, SRTO_PASSPHRASE, "SRTO_PASSPHRASE", s->passphrase, strlen(s->passphrase)) < 0) || - (s->mss >= 0 && libsrt_setsockopt(h, fd, SRTO_MSS, "SRTO_MMS", &s->mss, sizeof(s->mss)) < 0) || +#if SRT_VERSION_VALUE >= 0x010302 +#if SRT_VERSION_VALUE >= 0x010401 + (s->enforced_encryption >= 0 && libsrt_setsockopt(h, fd, SRTO_ENFORCEDENCRYPTION, "SRTO_ENFORCEDENCRYPTION", &s->enforced_encryption, sizeof(s->enforced_encryption)) < 0) || +#else + /* SRTO_STRICTENC == SRTO_ENFORCEDENCRYPTION (53), but for compatibility, we used SRTO_STRICTENC */ + (s->enforced_encryption >= 0 && libsrt_setsockopt(h, fd, SRTO_STRICTENC, "SRTO_STRICTENC", &s->enforced_encryption, sizeof(s->enforced_encryption)) < 0) || +#endif + (s->kmrefreshrate >= 0 && libsrt_setsockopt(h, fd, SRTO_KMREFRESHRATE, "SRTO_KMREFRESHRATE", &s->kmrefreshrate, sizeof(s->kmrefreshrate)) < 0) || + (s->kmpreannounce >= 0 && libsrt_setsockopt(h, fd, SRTO_KMPREANNOUNCE, "SRTO_KMPREANNOUNCE", &s->kmpreannounce, sizeof(s->kmpreannounce)) < 0) || +#endif + (s->mss >= 0 && libsrt_setsockopt(h, fd, SRTO_MSS, "SRTO_MSS", &s->mss, sizeof(s->mss)) < 0) || (s->ffs >= 0 && libsrt_setsockopt(h, fd, SRTO_FC, "SRTO_FC", &s->ffs, sizeof(s->ffs)) < 0) || - (s->ipttl >= 0 && libsrt_setsockopt(h, fd, SRTO_IPTTL, "SRTO_UPTTL", &s->ipttl, sizeof(s->ipttl)) < 0) || + (s->ipttl >= 0 && libsrt_setsockopt(h, fd, SRTO_IPTTL, "SRTO_IPTTL", &s->ipttl, sizeof(s->ipttl)) < 0) || (s->iptos >= 0 && libsrt_setsockopt(h, fd, SRTO_IPTOS, "SRTO_IPTOS", &s->iptos, sizeof(s->iptos)) < 0) || (s->latency >= 0 && libsrt_setsockopt(h, fd, SRTO_LATENCY, "SRTO_LATENCY", &latency, sizeof(latency)) < 0) || (s->rcvlatency >= 0 && libsrt_setsockopt(h, fd, SRTO_RCVLATENCY, "SRTO_RCVLATENCY", &rcvlatency, sizeof(rcvlatency)) < 0) || (s->peerlatency >= 0 && libsrt_setsockopt(h, fd, SRTO_PEERLATENCY, "SRTO_PEERLATENCY", &peerlatency, sizeof(peerlatency)) < 0) || - (s->tlpktdrop >= 0 && libsrt_setsockopt(h, fd, SRTO_TLPKTDROP, "SRTO_TLPKDROP", &s->tlpktdrop, sizeof(s->tlpktdrop)) < 0) || + (s->tlpktdrop >= 0 && libsrt_setsockopt(h, fd, SRTO_TLPKTDROP, "SRTO_TLPKTDROP", &s->tlpktdrop, sizeof(s->tlpktdrop)) < 0) || (s->nakreport >= 0 && libsrt_setsockopt(h, fd, SRTO_NAKREPORT, "SRTO_NAKREPORT", &s->nakreport, sizeof(s->nakreport)) < 0) || (connect_timeout >= 0 && libsrt_setsockopt(h, fd, SRTO_CONNTIMEO, "SRTO_CONNTIMEO", &connect_timeout, sizeof(connect_timeout)) <0 ) || (s->sndbuf >= 0 && libsrt_setsockopt(h, fd, SRTO_SNDBUF, "SRTO_SNDBUF", &s->sndbuf, sizeof(s->sndbuf)) < 0) || @@ -334,12 +342,24 @@ (s->lossmaxttl >= 0 && libsrt_setsockopt(h, fd, SRTO_LOSSMAXTTL, "SRTO_LOSSMAXTTL", &s->lossmaxttl, sizeof(s->lossmaxttl)) < 0) || (s->minversion >= 0 && libsrt_setsockopt(h, fd, SRTO_MINVERSION, "SRTO_MINVERSION", &s->minversion, sizeof(s->minversion)) < 0) || (s->streamid && libsrt_setsockopt(h, fd, SRTO_STREAMID, "SRTO_STREAMID", s->streamid, strlen(s->streamid)) < 0) || +#if SRT_VERSION_VALUE >= 0x010401 + (s->smoother && libsrt_setsockopt(h, fd, SRTO_CONGESTION, "SRTO_CONGESTION", s->smoother, strlen(s->smoother)) < 0) || +#else (s->smoother && libsrt_setsockopt(h, fd, SRTO_SMOOTHER, "SRTO_SMOOTHER", s->smoother, strlen(s->smoother)) < 0) || +#endif (s->messageapi >= 0 && libsrt_setsockopt(h, fd, SRTO_MESSAGEAPI, "SRTO_MESSAGEAPI", &s->messageapi, sizeof(s->messageapi)) < 0) || (s->payload_size >= 0 && libsrt_setsockopt(h, fd, SRTO_PAYLOADSIZE, "SRTO_PAYLOADSIZE", &s->payload_size, sizeof(s->payload_size)) < 0) || ((h->flags & AVIO_FLAG_WRITE) && libsrt_setsockopt(h, fd, SRTO_SENDER, "SRTO_SENDER", &yes, sizeof(yes)) < 0)) { return AVERROR(EIO); } + + if (s->linger >= 0) { + struct linger lin; + lin.l_linger = s->linger; + lin.l_onoff = lin.l_linger > 0 ? 1 : 0; + if (libsrt_setsockopt(h, fd, SRTO_LINGER, "SRTO_LINGER", &lin, sizeof(lin)) < 0) + return AVERROR(EIO); + } return 0; } @@ -347,20 +367,15 @@ static int libsrt_setup(URLContext *h, const char *uri, int flags) { struct addrinfo hints = { 0 }, *ai, *cur_ai; - int port, fd = -1; + int port, fd; SRTContext *s = h->priv_data; const char *p; char buf[256]; int ret; char hostname[1024],proto[1024],path[1024]; char portstr[10]; - int open_timeout = 5000000; - int eid; - - eid = srt_epoll_create(); - if (eid < 0) - return libsrt_neterrno(h); - s->eid = eid; + int64_t open_timeout = 0; + int eid, write_eid; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); @@ -417,20 +432,33 @@ if (s->send_buffer_size > 0) { srt_setsockopt(fd, SOL_SOCKET, SRTO_UDP_SNDBUF, &s->send_buffer_size, sizeof (s->send_buffer_size)); } + if (libsrt_socket_nonblock(fd, 1) < 0) + av_log(h, AV_LOG_DEBUG, "libsrt_socket_nonblock failed\n"); + + ret = write_eid = libsrt_epoll_create(h, fd, 1); + if (ret < 0) + goto fail1; if (s->mode == SRT_MODE_LISTENER) { // multi-client - if ((ret = libsrt_listen(s->eid, fd, cur_ai->ai_addr, cur_ai->ai_addrlen, h, open_timeout / 1000)) < 0) + ret = libsrt_listen(write_eid, fd, cur_ai->ai_addr, cur_ai->ai_addrlen, h, s->listen_timeout); + srt_epoll_release(write_eid); + if (ret < 0) goto fail1; + srt_close(fd); fd = ret; } else { if (s->mode == SRT_MODE_RENDEZVOUS) { - ret = srt_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); - if (ret) + if (srt_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen)) { + ret = libsrt_neterrno(h); + srt_epoll_release(write_eid); goto fail1; + } } - if ((ret = libsrt_listen_connect(s->eid, fd, cur_ai->ai_addr, cur_ai->ai_addrlen, - open_timeout / 1000, h, !!cur_ai->ai_next)) < 0) { + ret = libsrt_listen_connect(write_eid, fd, cur_ai->ai_addr, cur_ai->ai_addrlen, + open_timeout, h, !!cur_ai->ai_next); + srt_epoll_release(write_eid); + if (ret < 0) { if (ret == AVERROR_EXIT) goto fail1; else @@ -451,8 +479,13 @@ h->max_packet_size = packet_size; } + ret = eid = libsrt_epoll_create(h, fd, flags & AVIO_FLAG_WRITE); + if (eid < 0) + goto fail1; + h->is_streamed = 1; s->fd = fd; + s->eid = eid; freeaddrinfo(ai); return 0; @@ -478,6 +511,7 @@ SRTContext *s = h->priv_data; const char * p; char buf[256]; + int ret = 0; if (srt_startup() < 0) { return AVERROR_UNKNOWN; @@ -493,8 +527,20 @@ s->pbkeylen = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "passphrase", p)) { + av_freep(&s->passphrase); s->passphrase = av_strndup(buf, strlen(buf)); } +#if SRT_VERSION_VALUE >= 0x010302 + if (av_find_info_tag(buf, sizeof(buf), "enforced_encryption", p)) { + s->enforced_encryption = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "kmrefreshrate", p)) { + s->kmrefreshrate = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "kmpreannounce", p)) { + s->kmpreannounce = strtol(buf, NULL, 10); + } +#endif if (av_find_info_tag(buf, sizeof(buf), "mss", p)) { s->mss = strtol(buf, NULL, 10); } @@ -546,7 +592,8 @@ } else if (!strcmp(buf, "rendezvous")) { s->mode = SRT_MODE_RENDEZVOUS; } else { - return AVERROR(EIO); + ret = AVERROR(EINVAL); + goto err; } } if (av_find_info_tag(buf, sizeof(buf), "sndbuf", p)) { @@ -564,10 +611,18 @@ if (av_find_info_tag(buf, sizeof(buf), "streamid", p)) { av_freep(&s->streamid); s->streamid = av_strdup(buf); + if (!s->streamid) { + ret = AVERROR(ENOMEM); + goto err; + } } if (av_find_info_tag(buf, sizeof(buf), "smoother", p)) { av_freep(&s->smoother); s->smoother = av_strdup(buf); + if(!s->smoother) { + ret = AVERROR(ENOMEM); + goto err; + } } if (av_find_info_tag(buf, sizeof(buf), "messageapi", p)) { s->messageapi = strtol(buf, NULL, 10); @@ -578,11 +633,24 @@ } else if (!strcmp(buf, "file")) { s->transtype = SRTT_FILE; } else { - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto err; } } + if (av_find_info_tag(buf, sizeof(buf), "linger", p)) { + s->linger = strtol(buf, NULL, 10); + } } - return libsrt_setup(h, uri, flags); + ret = libsrt_setup(h, uri, flags); + if (ret < 0) + goto err; + return 0; + +err: + av_freep(&s->smoother); + av_freep(&s->streamid); + srt_cleanup(); + return ret; } static int libsrt_read(URLContext *h, uint8_t *buf, int size) @@ -591,7 +659,7 @@ int ret; if (!(h->flags & AVIO_FLAG_NONBLOCK)) { - ret = libsrt_network_wait_fd_timeout(h, s->eid, s->fd, 0, h->rw_timeout, &h->interrupt_callback); + ret = libsrt_network_wait_fd_timeout(h, s->eid, 0, h->rw_timeout, &h->interrupt_callback); if (ret) return ret; } @@ -610,7 +678,7 @@ int ret; if (!(h->flags & AVIO_FLAG_NONBLOCK)) { - ret = libsrt_network_wait_fd_timeout(h, s->eid, s->fd, 1, h->rw_timeout, &h->interrupt_callback); + ret = libsrt_network_wait_fd_timeout(h, s->eid, 1, h->rw_timeout, &h->interrupt_callback); if (ret) return ret; } @@ -627,9 +695,8 @@ { SRTContext *s = h->priv_data; - srt_close(s->fd); - srt_epoll_release(s->eid); + srt_close(s->fd); srt_cleanup(); diff -Nru ffmpeg-4.2.2/libavformat/libzmq.c ffmpeg-4.4/libavformat/libzmq.c --- ffmpeg-4.2.2/libavformat/libzmq.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/libzmq.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,204 @@ +/* + * ZeroMQ Protocol + * Copyright (c) 2019 Andriy Gelman + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "url.h" +#include "network.h" +#include "libavutil/avstring.h" +#include "libavutil/opt.h" +#include "libavutil/time.h" + +#define ZMQ_STRERROR zmq_strerror(zmq_errno()) + +typedef struct ZMQContext { + const AVClass *class; + void *context; + void *socket; + int pkt_size; + int pkt_size_overflow; /*keep track of the largest packet during overflow*/ +} ZMQContext; + +#define OFFSET(x) offsetof(ZMQContext, x) +#define D AV_OPT_FLAG_DECODING_PARAM +#define E AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "pkt_size", "Maximum send/read packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = 131072 }, -1, INT_MAX, .flags = D | E }, + { NULL } +}; + +static int zmq_proto_wait(URLContext *h, void *socket, int write) +{ + int ret; + int ev = write ? ZMQ_POLLOUT : ZMQ_POLLIN; + zmq_pollitem_t items = { .socket = socket, .fd = 0, .events = ev, .revents = 0 }; + ret = zmq_poll(&items, 1, POLLING_TIME); + if (ret == -1) { + av_log(h, AV_LOG_ERROR, "Error occured during zmq_poll(): %s\n", ZMQ_STRERROR); + return AVERROR_EXTERNAL; + } + return items.revents & ev ? 0 : AVERROR(EAGAIN); +} + +static int zmq_proto_wait_timeout(URLContext *h, void *socket, int write, int64_t timeout, AVIOInterruptCB *int_cb) +{ + int ret; + int64_t wait_start = 0; + + while (1) { + if (ff_check_interrupt(int_cb)) + return AVERROR_EXIT; + ret = zmq_proto_wait(h, socket, write); + if (ret != AVERROR(EAGAIN)) + return ret; + if (timeout > 0) { + if (!wait_start) + wait_start = av_gettime_relative(); + else if (av_gettime_relative() - wait_start > timeout) + return AVERROR(ETIMEDOUT); + } + } +} + +static int zmq_proto_open(URLContext *h, const char *uri, int flags) +{ + int ret; + ZMQContext *s = h->priv_data; + s->pkt_size_overflow = 0; + h->is_streamed = 1; + + if (s->pkt_size > 0) + h->max_packet_size = s->pkt_size; + + s->context = zmq_ctx_new(); + if (!s->context) { + /*errno not set on failure during zmq_ctx_new()*/ + av_log(h, AV_LOG_ERROR, "Error occured during zmq_ctx_new()\n"); + return AVERROR_EXTERNAL; + } + + av_strstart(uri, "zmq:", &uri); + + /*publish during write*/ + if (h->flags & AVIO_FLAG_WRITE) { + s->socket = zmq_socket(s->context, ZMQ_PUB); + if (!s->socket) { + av_log(h, AV_LOG_ERROR, "Error occured during zmq_socket(): %s\n", ZMQ_STRERROR); + goto fail_term; + } + + ret = zmq_bind(s->socket, uri); + if (ret == -1) { + av_log(h, AV_LOG_ERROR, "Error occured during zmq_bind(): %s\n", ZMQ_STRERROR); + goto fail_close; + } + } + + /*subscribe for read*/ + if (h->flags & AVIO_FLAG_READ) { + s->socket = zmq_socket(s->context, ZMQ_SUB); + if (!s->socket) { + av_log(h, AV_LOG_ERROR, "Error occured during zmq_socket(): %s\n", ZMQ_STRERROR); + goto fail_term; + } + + ret = zmq_setsockopt(s->socket, ZMQ_SUBSCRIBE, "", 0); + if (ret == -1) { + av_log(h, AV_LOG_ERROR, "Error occured during zmq_setsockopt(): %s\n", ZMQ_STRERROR); + goto fail_close; + } + + ret = zmq_connect(s->socket, uri); + if (ret == -1) { + av_log(h, AV_LOG_ERROR, "Error occured during zmq_connect(): %s\n", ZMQ_STRERROR); + goto fail_close; + } + } + return 0; + +fail_close: + zmq_close(s->socket); +fail_term: + zmq_ctx_term(s->context); + return AVERROR_EXTERNAL; +} + +static int zmq_proto_write(URLContext *h, const unsigned char *buf, int size) +{ + int ret; + ZMQContext *s = h->priv_data; + + ret = zmq_proto_wait_timeout(h, s->socket, 1, h->rw_timeout, &h->interrupt_callback); + if (ret) + return ret; + ret = zmq_send(s->socket, buf, size, 0); + if (ret == -1) { + av_log(h, AV_LOG_ERROR, "Error occured during zmq_send(): %s\n", ZMQ_STRERROR); + return AVERROR_EXTERNAL; + } + return ret; /*number of bytes sent*/ +} + +static int zmq_proto_read(URLContext *h, unsigned char *buf, int size) +{ + int ret; + ZMQContext *s = h->priv_data; + + ret = zmq_proto_wait_timeout(h, s->socket, 0, h->rw_timeout, &h->interrupt_callback); + if (ret) + return ret; + ret = zmq_recv(s->socket, buf, size, 0); + if (ret == -1) { + av_log(h, AV_LOG_ERROR, "Error occured during zmq_recv(): %s\n", ZMQ_STRERROR); + return AVERROR_EXTERNAL; + } + if (ret > size) { + s->pkt_size_overflow = FFMAX(s->pkt_size_overflow, ret); + av_log(h, AV_LOG_WARNING, "Message exceeds available space in the buffer. Message will be truncated. Setting -pkt_size %d may resolve the issue.\n", s->pkt_size_overflow); + ret = size; + } + return ret; /*number of bytes read*/ +} + +static int zmq_proto_close(URLContext *h) +{ + ZMQContext *s = h->priv_data; + zmq_close(s->socket); + zmq_ctx_term(s->context); + return 0; +} + +static const AVClass zmq_context_class = { + .class_name = "zmq", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const URLProtocol ff_libzmq_protocol = { + .name = "zmq", + .url_close = zmq_proto_close, + .url_open = zmq_proto_open, + .url_read = zmq_proto_read, + .url_write = zmq_proto_write, + .priv_data_size = sizeof(ZMQContext), + .priv_data_class = &zmq_context_class, + .flags = URL_PROTOCOL_FLAG_NETWORK, +}; diff -Nru ffmpeg-4.2.2/libavformat/lrcdec.c ffmpeg-4.4/libavformat/lrcdec.c --- ffmpeg-4.2.2/libavformat/lrcdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/lrcdec.c 2021-02-20 20:27:47.000000000 +0000 @@ -185,6 +185,8 @@ sscanf(comma_offset + 1, "%"SCNd64, &lrc->ts_offset) != 1) { av_dict_set(&s->metadata, line.str + 1, comma_offset + 1, 0); } + lrc->ts_offset = av_clip64(lrc->ts_offset, INT64_MIN/4, INT64_MAX/4); + *comma_offset = ':'; *right_bracket_offset = ']'; } @@ -198,10 +200,12 @@ while((ts_stroffset_incr = read_ts(line.str + ts_stroffset, &ts_start)) != 0) { + ts_start = av_clip64(ts_start, INT64_MIN/4, INT64_MAX/4); ts_stroffset += ts_stroffset_incr; sub = ff_subtitles_queue_insert(&lrc->q, line.str + ts_strlength, line.len - ts_strlength, 0); if(!sub) { + ff_subtitles_queue_clean(&lrc->q); return AVERROR(ENOMEM); } sub->pos = pos; diff -Nru ffmpeg-4.2.2/libavformat/luodatdec.c ffmpeg-4.4/libavformat/luodatdec.c --- ffmpeg-4.2.2/libavformat/luodatdec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/luodatdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,126 @@ +/* + * CCTV DAT demuxer + * + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "avio_internal.h" +#include "avformat.h" +#include "internal.h" + +static int dat_probe(const AVProbeData *p) +{ + if (p->buf_size < 0x2080) + return 0; + + if (memcmp(p->buf, "luo ", 4)) + return 0; + + if (memcmp(p->buf + 0x1ffc, " oulliu ", 8)) + return 0; + + if (!AV_RL32(p->buf + 0x2004)) + return 0; + + if (memcmp(p->buf + 0x207c, " uil", 4)) + return 0; + + return AVPROBE_SCORE_MAX; +} + +static int dat_read_header(AVFormatContext *s) +{ + s->ctx_flags |= AVFMTCTX_NOHEADER; + + avio_seek(s->pb, 0x2000, SEEK_SET); + + return 0; +} + +static int dat_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVIOContext *pb = s->pb; + int index, ret, key, stream_id, stream_index, width, height, fps, pkt_size; + int64_t pts, pos = avio_tell(pb); + + if (avio_feof(pb)) + return AVERROR_EOF; + + if (avio_rb32(pb) != MKBETAG('l', 'i', 'u', ' ')) + return AVERROR_INVALIDDATA; + stream_id = avio_rl32(pb); + width = avio_rl32(pb); + height = avio_rl32(pb); + fps = avio_rl32(pb); + avio_skip(pb, 16); + key = avio_rl32(pb) == 1; + avio_skip(pb, 4); + index = avio_rl32(pb); + avio_skip(pb, 4); + pts = avio_rl64(pb); + pkt_size = avio_rl32(pb); + avio_skip(pb, 64); + + if (pkt_size == 0) + return AVERROR_EOF; + + for (stream_index = 0; stream_index < s->nb_streams; stream_index++) { + if (s->streams[stream_index]->id == stream_id) + break; + } + + if (stream_index == s->nb_streams) { + AVStream *st = avformat_new_stream(s, NULL); + + if (!st) + return AVERROR(ENOMEM); + + st->id = stream_id; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_H264; + st->codecpar->width = width; + st->codecpar->height = height; + avpriv_set_pts_info(st, 64, 1, fps); + } + + if (index >= s->nb_streams) + av_log(s, AV_LOG_WARNING, "Stream index out of range.\n"); + + ret = av_get_packet(pb, pkt, pkt_size); + if (ret < 0) + return ret; + pkt->pos = pos; + pkt->pts = pts; + pkt->stream_index = stream_index; + if (key) + pkt->flags |= AV_PKT_FLAG_KEY; + + return ret; +} + +AVInputFormat ff_luodat_demuxer = { + .name = "luodat", + .long_name = NULL_IF_CONFIG_SMALL("Video CCTV DAT"), + .read_probe = dat_probe, + .read_header = dat_read_header, + .read_packet = dat_read_packet, + .extensions = "dat", + .flags = AVFMT_GENERIC_INDEX, +}; diff -Nru ffmpeg-4.2.2/libavformat/lvfdec.c ffmpeg-4.4/libavformat/lvfdec.c --- ffmpeg-4.2.2/libavformat/lvfdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/lvfdec.c 2021-02-20 20:27:47.000000000 +0000 @@ -106,6 +106,7 @@ unsigned size, flags, timestamp, id; int64_t pos; int ret, is_video = 0; + int stream_index; pos = avio_tell(s->pb); while (!avio_feof(s->pb)) { @@ -121,12 +122,15 @@ case MKTAG('0', '1', 'w', 'b'): if (size < 8) return AVERROR_INVALIDDATA; + stream_index = is_video ? 0 : 1; + if (stream_index >= s->nb_streams) + return AVERROR_INVALIDDATA; timestamp = avio_rl32(s->pb); flags = avio_rl32(s->pb); ret = av_get_packet(s->pb, pkt, size - 8); if (flags & (1 << 12)) pkt->flags |= AV_PKT_FLAG_KEY; - pkt->stream_index = is_video ? 0 : 1; + pkt->stream_index = stream_index; pkt->pts = timestamp; pkt->pos = pos; return ret; diff -Nru ffmpeg-4.2.2/libavformat/lxfdec.c ffmpeg-4.4/libavformat/lxfdec.c --- ffmpeg-4.2.2/libavformat/lxfdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/lxfdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -195,7 +195,7 @@ return AVERROR_PATCHWELCOME; } - samples = track_size * 8 / st->codecpar->bits_per_coded_sample; + samples = track_size * 8LL / st->codecpar->bits_per_coded_sample; //use audio packet size to determine video standard //for NTSC we have one 8008-sample audio frame per five video frames @@ -210,6 +210,8 @@ avpriv_set_pts_info(s->streams[0], 64, 1, 25); } + if (av_popcount(channels) * (uint64_t)track_size > INT_MAX) + return AVERROR_INVALIDDATA; //TODO: warning if track mask != (1 << channels) - 1? ret = av_popcount(channels) * track_size; @@ -316,7 +318,6 @@ return ret2; if ((ret2 = avio_read(pb, pkt->data, ret)) != ret) { - av_packet_unref(pkt); return ret2 < 0 ? ret2 : AVERROR_EOF; } diff -Nru ffmpeg-4.2.2/libavformat/Makefile ffmpeg-4.4/libavformat/Makefile --- ffmpeg-4.2.2/libavformat/Makefile 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/Makefile 2021-04-08 21:28:40.000000000 +0000 @@ -8,7 +8,6 @@ OBJS = allformats.o \ avio.o \ aviobuf.o \ - cutils.o \ dump.o \ format.o \ id3v1.o \ @@ -17,7 +16,6 @@ mux.o \ options.o \ os_support.o \ - qtpalette.o \ protocols.o \ riff.o \ sdp.o \ @@ -27,7 +25,7 @@ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o # subsystems -OBJS-$(CONFIG_ISO_MEDIA) += isom.o +OBJS-$(CONFIG_ISO_MEDIA) += isom.o isom_tags.o OBJS-$(CONFIG_NETWORK) += network.o OBJS-$(CONFIG_RIFFDEC) += riffdec.o OBJS-$(CONFIG_RIFFENC) += riffenc.o @@ -68,8 +66,10 @@ OBJS-$(CONFIG_A64_MUXER) += a64.o rawenc.o OBJS-$(CONFIG_AA_DEMUXER) += aadec.o OBJS-$(CONFIG_AAC_DEMUXER) += aacdec.o apetag.o img2.o rawdec.o +OBJS-$(CONFIG_AAX_DEMUXER) += aaxdec.o OBJS-$(CONFIG_AC3_DEMUXER) += ac3dec.o rawdec.o OBJS-$(CONFIG_AC3_MUXER) += rawenc.o +OBJS-$(CONFIG_ACE_DEMUXER) += acedec.o OBJS-$(CONFIG_ACM_DEMUXER) += acm.o rawdec.o OBJS-$(CONFIG_ACT_DEMUXER) += act.o OBJS-$(CONFIG_ADF_DEMUXER) += bintext.o sauce.o @@ -81,17 +81,22 @@ OBJS-$(CONFIG_ADX_MUXER) += rawenc.o OBJS-$(CONFIG_AEA_DEMUXER) += aea.o pcm.o OBJS-$(CONFIG_AFC_DEMUXER) += afc.o -OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o pcm.o isom.o \ - mov_chan.o -OBJS-$(CONFIG_AIFF_MUXER) += aiffenc.o id3v2enc.o +OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o aiff.o pcm.o \ + mov_chan.o replaygain.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_AMR_MUXER) += amr.o +OBJS-$(CONFIG_AMR_MUXER) += amr.o rawenc.o OBJS-$(CONFIG_AMRNB_DEMUXER) += amr.o OBJS-$(CONFIG_AMRWB_DEMUXER) += amr.o +OBJS-$(CONFIG_AMV_MUXER) += amvenc.o OBJS-$(CONFIG_ANM_DEMUXER) += anm.o OBJS-$(CONFIG_APC_DEMUXER) += apc.o OBJS-$(CONFIG_APE_DEMUXER) += ape.o apetag.o img2.o +OBJS-$(CONFIG_APM_DEMUXER) += apm.o +OBJS-$(CONFIG_APM_MUXER) += apm.o rawenc.o OBJS-$(CONFIG_APNG_DEMUXER) += apngdec.o OBJS-$(CONFIG_APNG_MUXER) += apngenc.o OBJS-$(CONFIG_APTX_DEMUXER) += aptxdec.o rawdec.o @@ -99,6 +104,9 @@ OBJS-$(CONFIG_APTX_HD_DEMUXER) += aptxdec.o rawdec.o OBJS-$(CONFIG_APTX_HD_MUXER) += rawenc.o OBJS-$(CONFIG_AQTITLE_DEMUXER) += aqtitledec.o subtitles.o +OBJS-$(CONFIG_ARGO_ASF_DEMUXER) += argo_asf.o +OBJS-$(CONFIG_ARGO_ASF_MUXER) += argo_asf.o +OBJS-$(CONFIG_ARGO_BRP_DEMUXER) += argo_brp.o argo_asf.o OBJS-$(CONFIG_ASF_DEMUXER) += asfdec_f.o asf.o asfcrypt.o \ avlanguage.o OBJS-$(CONFIG_ASF_O_DEMUXER) += asfdec_o.o asf.o asfcrypt.o \ @@ -110,16 +118,18 @@ OBJS-$(CONFIG_AST_MUXER) += ast.o astenc.o OBJS-$(CONFIG_AU_DEMUXER) += au.o pcm.o OBJS-$(CONFIG_AU_MUXER) += au.o rawenc.o -OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o +OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o isom_tags.o OBJS-$(CONFIG_AVI_MUXER) += avienc.o mpegtsenc.o avlanguage.o rawutils.o OBJS-$(CONFIG_AVM2_MUXER) += swfenc.o swf.o OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o -OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o vocdec.o voc.o -OBJS-$(CONFIG_AVS2_DEMUXER) += davs2.o rawdec.o +OBJS-$(CONFIG_AVS_DEMUXER) += avs.o voc_packet.o voc.o +OBJS-$(CONFIG_AVS2_DEMUXER) += avs2dec.o rawdec.o OBJS-$(CONFIG_AVS2_MUXER) += rawenc.o +OBJS-$(CONFIG_AVS3_DEMUXER) += avs3dec.o rawdec.o OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o OBJS-$(CONFIG_BINK_DEMUXER) += bink.o +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 @@ -127,7 +137,7 @@ OBJS-$(CONFIG_BOA_DEMUXER) += boadec.o OBJS-$(CONFIG_BFSTM_DEMUXER) += brstm.o OBJS-$(CONFIG_BRSTM_DEMUXER) += brstm.o -OBJS-$(CONFIG_C93_DEMUXER) += c93.o voc_packet.o vocdec.o voc.o +OBJS-$(CONFIG_C93_DEMUXER) += c93.o voc_packet.o voc.o OBJS-$(CONFIG_CAF_DEMUXER) += cafdec.o caf.o mov_chan.o mov_esds.o OBJS-$(CONFIG_CAF_MUXER) += cafenc.o caf.o riff.o OBJS-$(CONFIG_CAVSVIDEO_DEMUXER) += cavsvideodec.o rawdec.o @@ -148,6 +158,7 @@ OBJS-$(CONFIG_DAUD_DEMUXER) += dauddec.o OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o OBJS-$(CONFIG_DCSTR_DEMUXER) += dcstr.o +OBJS-$(CONFIG_DERF_DEMUXER) += derf.o pcm.o OBJS-$(CONFIG_DFA_DEMUXER) += dfa.o OBJS-$(CONFIG_DHAV_DEMUXER) += dhav.o OBJS-$(CONFIG_DIRAC_DEMUXER) += diracdec.o rawdec.o @@ -175,7 +186,7 @@ OBJS-$(CONFIG_FIFO_MUXER) += fifo.o OBJS-$(CONFIG_FIFO_TEST_MUXER) += fifo_test.o OBJS-$(CONFIG_FILMSTRIP_DEMUXER) += filmstripdec.o -OBJS-$(CONFIG_FILMSTRIP_MUXER) += filmstripenc.o +OBJS-$(CONFIG_FILMSTRIP_MUXER) += filmstripenc.o rawenc.o OBJS-$(CONFIG_FITS_DEMUXER) += fitsdec.o OBJS-$(CONFIG_FITS_MUXER) += fitsenc.o OBJS-$(CONFIG_FLAC_DEMUXER) += flacdec.o rawdec.o \ @@ -195,12 +206,13 @@ OBJS-$(CONFIG_FRAMEMD5_MUXER) += hashenc.o framehash.o OBJS-$(CONFIG_FRM_DEMUXER) += frmdec.o OBJS-$(CONFIG_FSB_DEMUXER) += fsb.o +OBJS-$(CONFIG_FWSE_DEMUXER) += fwse.o pcm.o OBJS-$(CONFIG_GIF_MUXER) += gif.o OBJS-$(CONFIG_GIF_DEMUXER) += gifdec.o OBJS-$(CONFIG_GSM_DEMUXER) += gsmdec.o OBJS-$(CONFIG_GSM_MUXER) += rawenc.o OBJS-$(CONFIG_GXF_DEMUXER) += gxf.o -OBJS-$(CONFIG_GXF_MUXER) += gxfenc.o audiointerleave.o +OBJS-$(CONFIG_GXF_MUXER) += gxfenc.o OBJS-$(CONFIG_G722_DEMUXER) += g722.o rawdec.o OBJS-$(CONFIG_G722_MUXER) += rawenc.o OBJS-$(CONFIG_G723_1_DEMUXER) += g723_1.o @@ -219,12 +231,13 @@ OBJS-$(CONFIG_H264_DEMUXER) += h264dec.o rawdec.o OBJS-$(CONFIG_H264_MUXER) += rawenc.o OBJS-$(CONFIG_HASH_MUXER) += hashenc.o -OBJS-$(CONFIG_HCOM_DEMUXER) += hcom.o +OBJS-$(CONFIG_HCA_DEMUXER) += hca.o +OBJS-$(CONFIG_HCOM_DEMUXER) += hcom.o pcm.o OBJS-$(CONFIG_HDS_MUXER) += hdsenc.o OBJS-$(CONFIG_HEVC_DEMUXER) += hevcdec.o rawdec.o OBJS-$(CONFIG_HEVC_MUXER) += rawenc.o OBJS-$(CONFIG_HLS_DEMUXER) += hls.o -OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o hlsplaylist.o +OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o hlsplaylist.o avc.o OBJS-$(CONFIG_HNM_DEMUXER) += hnm.o OBJS-$(CONFIG_ICO_DEMUXER) += icodec.o OBJS-$(CONFIG_ICO_MUXER) += icoenc.o @@ -233,7 +246,7 @@ OBJS-$(CONFIG_IFF_DEMUXER) += iff.o OBJS-$(CONFIG_IFV_DEMUXER) += ifv.o OBJS-$(CONFIG_ILBC_DEMUXER) += ilbc.o -OBJS-$(CONFIG_ILBC_MUXER) += ilbc.o +OBJS-$(CONFIG_ILBC_MUXER) += ilbc.o rawenc.o OBJS-$(CONFIG_IMAGE2_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE2_MUXER) += img2enc.o img2.o OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2dec.o img2.o @@ -253,6 +266,7 @@ 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_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 @@ -263,10 +277,12 @@ OBJS-$(CONFIG_IMAGE_SUNRAST_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_TIFF_PIPE_DEMUXER) += img2dec.o img2.o 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_INGENIENT_DEMUXER) += ingenientdec.o rawdec.o OBJS-$(CONFIG_IPMOVIE_DEMUXER) += ipmovie.o +OBJS-$(CONFIG_IPU_DEMUXER) += ipudec.o OBJS-$(CONFIG_IRCAM_DEMUXER) += ircamdec.o ircam.o pcm.o OBJS-$(CONFIG_IRCAM_MUXER) += ircamenc.o ircam.o rawenc.o OBJS-$(CONFIG_ISS_DEMUXER) += iss.o @@ -278,9 +294,12 @@ OBJS-$(CONFIG_JACOSUB_MUXER) += jacosubenc.o rawenc.o OBJS-$(CONFIG_JV_DEMUXER) += jvdec.o OBJS-$(CONFIG_KUX_DEMUXER) += flvdec.o +OBJS-$(CONFIG_KVAG_DEMUXER) += kvag.o +OBJS-$(CONFIG_KVAG_MUXER) += kvag.o rawenc.o OBJS-$(CONFIG_LATM_MUXER) += latmenc.o rawenc.o OBJS-$(CONFIG_LMLM4_DEMUXER) += lmlm4.o OBJS-$(CONFIG_LOAS_DEMUXER) += loasdec.o rawdec.o +OBJS-$(CONFIG_LUODAT_DEMUXER) += luodatdec.o OBJS-$(CONFIG_LRC_DEMUXER) += lrcdec.o lrc.o subtitles.o OBJS-$(CONFIG_LRC_MUXER) += lrcenc.o lrc.o OBJS-$(CONFIG_LVF_DEMUXER) += lvfdec.o @@ -288,13 +307,15 @@ OBJS-$(CONFIG_M4V_DEMUXER) += m4vdec.o rawdec.o OBJS-$(CONFIG_M4V_MUXER) += rawenc.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \ - rmsipr.o flac_picture.o \ + flac_picture.o isom_tags.o rmsipr.o \ oggparsevorbis.o vorbiscomment.o \ - flac_picture.o replaygain.o + qtpalette.o replaygain.o OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \ - av1.o avc.o hevc.o \ - flacenc_header.o avlanguage.o vorbiscomment.o wv.o \ - webmdashenc.o webm_chunk.o + av1.o avc.o hevc.o isom_tags.o \ + flacenc_header.o avlanguage.o \ + vorbiscomment.o wv.o +OBJS-$(CONFIG_MCA_DEMUXER) += mca.o +OBJS-$(CONFIG_MCC_DEMUXER) += mccdec.o subtitles.o OBJS-$(CONFIG_MD5_MUXER) += hashenc.o OBJS-$(CONFIG_MGSTS_DEMUXER) += mgsts.o OBJS-$(CONFIG_MICRODVD_DEMUXER) += microdvddec.o subtitles.o @@ -308,7 +329,10 @@ OBJS-$(CONFIG_MM_DEMUXER) += mm.o OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o OBJS-$(CONFIG_MMF_MUXER) += mmf.o rawenc.o -OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_esds.o replaygain.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 OBJS-$(CONFIG_MOV_MUXER) += movenc.o av1.o avc.o hevc.o vpcc.o \ movenchint.o mov_chan.o rtp.o \ movenccenc.o rawutils.o @@ -334,25 +358,27 @@ OBJS-$(CONFIG_MSF_DEMUXER) += msf.o OBJS-$(CONFIG_MPSUB_DEMUXER) += mpsubdec.o subtitles.o OBJS-$(CONFIG_MSNWC_TCP_DEMUXER) += msnwc_tcp.o +OBJS-$(CONFIG_MSP_DEMUXER) += mspdec.o OBJS-$(CONFIG_MTAF_DEMUXER) += mtaf.o OBJS-$(CONFIG_MTV_DEMUXER) += mtv.o OBJS-$(CONFIG_MUSX_DEMUXER) += musx.o OBJS-$(CONFIG_MV_DEMUXER) += mvdec.o OBJS-$(CONFIG_MVI_DEMUXER) += mvi.o OBJS-$(CONFIG_MXF_DEMUXER) += mxfdec.o mxf.o -OBJS-$(CONFIG_MXF_MUXER) += mxfenc.o mxf.o audiointerleave.o avc.o +OBJS-$(CONFIG_MXF_MUXER) += mxfenc.o mxf.o avc.o OBJS-$(CONFIG_MXG_DEMUXER) += mxg.o OBJS-$(CONFIG_NC_DEMUXER) += ncdec.o OBJS-$(CONFIG_NISTSPHERE_DEMUXER) += nistspheredec.o pcm.o -OBJS-$(CONFIG_NSP_DEMUXER) += nspdec.o +OBJS-$(CONFIG_NSP_DEMUXER) += nspdec.o pcm.o OBJS-$(CONFIG_NSV_DEMUXER) += nsvdec.o OBJS-$(CONFIG_NULL_MUXER) += nullenc.o -OBJS-$(CONFIG_NUT_DEMUXER) += nutdec.o nut.o isom.o +OBJS-$(CONFIG_NUT_DEMUXER) += nutdec.o nut.o isom_tags.o OBJS-$(CONFIG_NUT_MUXER) += nutenc.o nut.o OBJS-$(CONFIG_NUV_DEMUXER) += nuv.o +OBJS-$(CONFIG_AV1_DEMUXER) += av1dec.o +OBJS-$(CONFIG_OBU_DEMUXER) += av1dec.o OBJS-$(CONFIG_OGG_DEMUXER) += oggdec.o \ oggparsecelt.o \ - oggparsedaala.o \ oggparsedirac.o \ oggparseflac.o \ oggparseogm.o \ @@ -420,6 +446,7 @@ OBJS-$(CONFIG_PCM_VIDC_MUXER) += pcmenc.o rawenc.o OBJS-$(CONFIG_PJS_DEMUXER) += pjsdec.o subtitles.o OBJS-$(CONFIG_PMP_DEMUXER) += pmpdec.o +OBJS-$(CONFIG_PP_BNK_DEMUXER) += pp_bnk.o OBJS-$(CONFIG_PVA_DEMUXER) += pva.o OBJS-$(CONFIG_PVF_DEMUXER) += pvfdec.o pcm.o OBJS-$(CONFIG_QCP_DEMUXER) += qcp.o @@ -436,7 +463,7 @@ OBJS-$(CONFIG_RSD_DEMUXER) += rsd.o OBJS-$(CONFIG_RPL_DEMUXER) += rpl.o OBJS-$(CONFIG_RSO_DEMUXER) += rsodec.o rso.o pcm.o -OBJS-$(CONFIG_RSO_MUXER) += rsoenc.o rso.o +OBJS-$(CONFIG_RSO_MUXER) += rsoenc.o rso.o rawenc.o OBJS-$(CONFIG_RTP_MPEGTS_MUXER) += rtpenc_mpegts.o OBJS-$(CONFIG_RTP_MUXER) += rtp.o \ rtpenc_aac.o \ @@ -470,14 +497,17 @@ OBJS-$(CONFIG_SDP_DEMUXER) += rtsp.o OBJS-$(CONFIG_SDR2_DEMUXER) += sdr2.o OBJS-$(CONFIG_SDS_DEMUXER) += sdsdec.o -OBJS-$(CONFIG_SDX_DEMUXER) += sdxdec.o +OBJS-$(CONFIG_SDX_DEMUXER) += sdxdec.o pcm.o OBJS-$(CONFIG_SEGAFILM_DEMUXER) += segafilm.o OBJS-$(CONFIG_SEGAFILM_MUXER) += segafilmenc.o OBJS-$(CONFIG_SEGMENT_MUXER) += segment.o OBJS-$(CONFIG_SER_DEMUXER) += serdec.o +OBJS-$(CONFIG_SGA_DEMUXER) += sga.o OBJS-$(CONFIG_SHORTEN_DEMUXER) += shortendec.o rawdec.o OBJS-$(CONFIG_SIFF_DEMUXER) += siff.o +OBJS-$(CONFIG_SIMBIOSIS_IMX_DEMUXER) += imx.o OBJS-$(CONFIG_SINGLEJPEG_MUXER) += rawenc.o +OBJS-$(CONFIG_SLN_DEMUXER) += pcmdec.o pcm.o OBJS-$(CONFIG_SMACKER_DEMUXER) += smacker.o OBJS-$(CONFIG_SMJPEG_DEMUXER) += smjpegdec.o smjpeg.o OBJS-$(CONFIG_SMJPEG_MUXER) += smjpegenc.o smjpeg.o @@ -494,12 +524,14 @@ OBJS-$(CONFIG_SRT_MUXER) += srtenc.o OBJS-$(CONFIG_STL_DEMUXER) += stldec.o subtitles.o OBJS-$(CONFIG_STR_DEMUXER) += psxstr.o +OBJS-$(CONFIG_STREAMHASH_MUXER) += hashenc.o OBJS-$(CONFIG_STREAM_SEGMENT_MUXER) += segment.o OBJS-$(CONFIG_SUBVIEWER1_DEMUXER) += subviewer1dec.o subtitles.o OBJS-$(CONFIG_SUBVIEWER_DEMUXER) += subviewerdec.o subtitles.o OBJS-$(CONFIG_SUP_DEMUXER) += supdec.o OBJS-$(CONFIG_SUP_MUXER) += supenc.o OBJS-$(CONFIG_SVAG_DEMUXER) += svag.o +OBJS-$(CONFIG_SVS_DEMUXER) += svs.o OBJS-$(CONFIG_SWF_DEMUXER) += swfdec.o swf.o OBJS-$(CONFIG_SWF_MUXER) += swfenc.o swf.o OBJS-$(CONFIG_TAK_DEMUXER) += takdec.o apetag.o img2.o rawdec.o @@ -514,6 +546,7 @@ OBJS-$(CONFIG_TRUEHD_MUXER) += rawenc.o OBJS-$(CONFIG_TTA_DEMUXER) += tta.o apetag.o img2.o OBJS-$(CONFIG_TTA_MUXER) += ttaenc.o apetag.o img2.o +OBJS-$(CONFIG_TTML_MUXER) += ttmlenc.o OBJS-$(CONFIG_TTY_DEMUXER) += tty.o sauce.o OBJS-$(CONFIG_TY_DEMUXER) += ty.o OBJS-$(CONFIG_TXD_DEMUXER) += txd.o @@ -540,12 +573,11 @@ 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 \ + av1.o avc.o hevc.o isom_tags.o \ flacenc_header.o avlanguage.o \ - wv.o vorbiscomment.o \ - webmdashenc.o webm_chunk.o -OBJS-$(CONFIG_WEBM_DASH_MANIFEST_MUXER) += webmdashenc.o matroska.o -OBJS-$(CONFIG_WEBM_CHUNK_MUXER) += webm_chunk.o matroska.o + wv.o vorbiscomment.o +OBJS-$(CONFIG_WEBM_DASH_MANIFEST_MUXER) += webmdashenc.o +OBJS-$(CONFIG_WEBM_CHUNK_MUXER) += webm_chunk.o OBJS-$(CONFIG_WEBP_MUXER) += webpenc.o OBJS-$(CONFIG_WEBVTT_DEMUXER) += webvttdec.o subtitles.o OBJS-$(CONFIG_WEBVTT_MUXER) += webvttenc.o @@ -587,8 +619,9 @@ OBJS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpcrypt.o rtmpdigest.o rtmpdh.o OBJS-$(CONFIG_FFRTMPHTTP_PROTOCOL) += rtmphttp.o OBJS-$(CONFIG_FILE_PROTOCOL) += file.o -OBJS-$(CONFIG_FTP_PROTOCOL) += ftp.o +OBJS-$(CONFIG_FTP_PROTOCOL) += ftp.o urldecode.o OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o +OBJS-$(CONFIG_GOPHERS_PROTOCOL) += gopher.o OBJS-$(CONFIG_HLS_PROTOCOL) += hlsproto.o OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o urldecode.o OBJS-$(CONFIG_HTTPPROXY_PROTOCOL) += http.o httpauth.o urldecode.o @@ -623,6 +656,8 @@ OBJS-$(CONFIG_UNIX_PROTOCOL) += unix.o # external library protocols +OBJS-$(CONFIG_LIBAMQP_PROTOCOL) += libamqp.o +OBJS-$(CONFIG_LIBRIST_PROTOCOL) += librist.o OBJS-$(CONFIG_LIBRTMP_PROTOCOL) += librtmp.o OBJS-$(CONFIG_LIBRTMPE_PROTOCOL) += librtmp.o OBJS-$(CONFIG_LIBRTMPS_PROTOCOL) += librtmp.o @@ -631,6 +666,7 @@ OBJS-$(CONFIG_LIBSMBCLIENT_PROTOCOL) += libsmbclient.o OBJS-$(CONFIG_LIBSRT_PROTOCOL) += libsrt.o OBJS-$(CONFIG_LIBSSH_PROTOCOL) += libssh.o +OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o # libavdevice dependencies OBJS-$(CONFIG_IEC61883_INDEV) += dv.o @@ -658,3 +694,4 @@ probetest \ seek_print \ sidxindex \ + venc_data_dump diff -Nru ffmpeg-4.2.2/libavformat/matroska.c ffmpeg-4.4/libavformat/matroska.c --- ffmpeg-4.2.2/libavformat/matroska.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/matroska.c 2020-07-11 10:39:30.000000000 +0000 @@ -119,25 +119,6 @@ {"" , AV_CODEC_ID_NONE} }; -const CodecMime ff_mkv_image_mime_tags[] = { - {"image/gif" , AV_CODEC_ID_GIF}, - {"image/jpeg" , AV_CODEC_ID_MJPEG}, - {"image/png" , AV_CODEC_ID_PNG}, - {"image/tiff" , AV_CODEC_ID_TIFF}, - - {"" , AV_CODEC_ID_NONE} -}; - -const CodecMime ff_mkv_mime_tags[] = { - {"text/plain" , AV_CODEC_ID_TEXT}, - {"application/x-truetype-font", AV_CODEC_ID_TTF}, - {"application/x-font" , AV_CODEC_ID_TTF}, - {"application/vnd.ms-opentype", AV_CODEC_ID_OTF}, - {"binary" , AV_CODEC_ID_BIN_DATA}, - - {"" , AV_CODEC_ID_NONE} -}; - const AVMetadataConv ff_mkv_metadata_conv[] = { { "LEAD_PERFORMER", "performer" }, { "PART_NUMBER" , "track" }, diff -Nru ffmpeg-4.2.2/libavformat/matroskadec.c ffmpeg-4.4/libavformat/matroskadec.c --- ffmpeg-4.2.2/libavformat/matroskadec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/matroskadec.c 2021-04-08 21:28:40.000000000 +0000 @@ -48,6 +48,7 @@ #include "libavcodec/bytestream.h" #include "libavcodec/flac.h" #include "libavcodec/mpeg4audio.h" +#include "libavcodec/packet_internal.h" #include "avformat.h" #include "avio_internal.h" @@ -94,9 +95,20 @@ EBML_TYPE_COUNT } EbmlType; +typedef struct CountedElement { + union { + uint64_t u; + int64_t i; + double f; + char *s; + } el; + unsigned count; +} CountedElement; + typedef const struct EbmlSyntax { uint32_t id; - EbmlType type; + uint8_t type; + uint8_t is_counted; size_t list_elem_size; size_t data_offset; union { @@ -156,7 +168,7 @@ double white_x; double white_y; double max_luminance; - double min_luminance; + CountedElement min_luminance; } MatroskaMasteringMeta; typedef struct MatroskaTrackVideoColor { @@ -238,6 +250,11 @@ uint64_t default_duration; uint64_t flag_default; uint64_t flag_forced; + uint64_t flag_comment; + uint64_t flag_hearingimpaired; + uint64_t flag_visualimpaired; + uint64_t flag_textdescriptions; + CountedElement flag_original; uint64_t seek_preroll; MatroskaTrackVideo video; MatroskaTrackAudio audio; @@ -249,6 +266,7 @@ AVStream *stream; int64_t end_timecode; int ms_compat; + int needs_decoding; uint64_t max_block_additional_id; uint32_t palette[AVPALETTE_COUNT]; @@ -258,6 +276,7 @@ typedef struct MatroskaAttachment { uint64_t uid; char *filename; + char *description; char *mime; EbmlBin bin; @@ -316,7 +335,7 @@ typedef struct MatroskaBlock { uint64_t duration; - int64_t reference; + CountedElement reference; uint64_t non_simple; EbmlBin bin; uint64_t additional_id; @@ -362,9 +381,11 @@ /* byte position of the segment inside the stream */ int64_t segment_start; + AVPacket *pkt; + /* the packet queue */ - AVPacketList *queue; - AVPacketList *queue_end; + PacketList *queue; + PacketList *queue_end; int done; @@ -395,120 +416,120 @@ // 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[27], matroska_track_encoding[6], matroska_track_encodings[2], + matroska_track[32], matroska_track_encoding[6], matroska_track_encodings[2], matroska_track_combine_planes[2], matroska_track_operation[2], 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]; static EbmlSyntax ebml_header[] = { - { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, offsetof(Ebml, version), { .u = EBML_VERSION } }, - { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, offsetof(Ebml, max_size), { .u = 8 } }, - { EBML_ID_EBMLMAXIDLENGTH, EBML_UINT, 0, offsetof(Ebml, id_length), { .u = 4 } }, - { EBML_ID_DOCTYPE, EBML_STR, 0, offsetof(Ebml, doctype), { .s = "(none)" } }, - { EBML_ID_DOCTYPEREADVERSION, EBML_UINT, 0, offsetof(Ebml, doctype_version), { .u = 1 } }, + { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, 0, offsetof(Ebml, version), { .u = EBML_VERSION } }, + { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, 0, offsetof(Ebml, max_size), { .u = 8 } }, + { EBML_ID_EBMLMAXIDLENGTH, EBML_UINT, 0, 0, offsetof(Ebml, id_length), { .u = 4 } }, + { EBML_ID_DOCTYPE, EBML_STR, 0, 0, offsetof(Ebml, doctype), { .s = "(none)" } }, + { EBML_ID_DOCTYPEREADVERSION, EBML_UINT, 0, 0, offsetof(Ebml, doctype_version), { .u = 1 } }, { EBML_ID_EBMLVERSION, EBML_NONE }, { EBML_ID_DOCTYPEVERSION, EBML_NONE }, CHILD_OF(ebml_syntax) }; static EbmlSyntax ebml_syntax[] = { - { EBML_ID_HEADER, EBML_NEST, 0, 0, { .n = ebml_header } }, + { EBML_ID_HEADER, EBML_NEST, 0, 0, 0, { .n = ebml_header } }, { MATROSKA_ID_SEGMENT, EBML_STOP }, { 0 } }; static EbmlSyntax matroska_info[] = { - { MATROSKA_ID_TIMECODESCALE, EBML_UINT, 0, offsetof(MatroskaDemuxContext, time_scale), { .u = 1000000 } }, - { MATROSKA_ID_DURATION, EBML_FLOAT, 0, offsetof(MatroskaDemuxContext, duration) }, - { MATROSKA_ID_TITLE, EBML_UTF8, 0, offsetof(MatroskaDemuxContext, title) }, + { MATROSKA_ID_TIMECODESCALE, EBML_UINT, 0, 0, offsetof(MatroskaDemuxContext, time_scale), { .u = 1000000 } }, + { MATROSKA_ID_DURATION, EBML_FLOAT, 0, 0, offsetof(MatroskaDemuxContext, duration) }, + { MATROSKA_ID_TITLE, EBML_UTF8, 0, 0, offsetof(MatroskaDemuxContext, title) }, { MATROSKA_ID_WRITINGAPP, EBML_NONE }, - { MATROSKA_ID_MUXINGAPP, EBML_UTF8, 0, offsetof(MatroskaDemuxContext, muxingapp) }, - { MATROSKA_ID_DATEUTC, EBML_BIN, 0, offsetof(MatroskaDemuxContext, date_utc) }, + { MATROSKA_ID_MUXINGAPP, EBML_UTF8, 0, 0, offsetof(MatroskaDemuxContext, muxingapp) }, + { MATROSKA_ID_DATEUTC, EBML_BIN, 0, 0, offsetof(MatroskaDemuxContext, date_utc) }, { MATROSKA_ID_SEGMENTUID, EBML_NONE }, CHILD_OF(matroska_segment) }; static EbmlSyntax matroska_mastering_meta[] = { - { MATROSKA_ID_VIDEOCOLOR_RX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, r_x), { .f=-1 } }, - { MATROSKA_ID_VIDEOCOLOR_RY, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, r_y), { .f=-1 } }, - { MATROSKA_ID_VIDEOCOLOR_GX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, g_x), { .f=-1 } }, - { MATROSKA_ID_VIDEOCOLOR_GY, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, g_y), { .f=-1 } }, - { MATROSKA_ID_VIDEOCOLOR_BX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, b_x), { .f=-1 } }, - { MATROSKA_ID_VIDEOCOLOR_BY, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, b_y), { .f=-1 } }, - { MATROSKA_ID_VIDEOCOLOR_WHITEX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, white_x), { .f=-1 } }, - { MATROSKA_ID_VIDEOCOLOR_WHITEY, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, white_y), { .f=-1 } }, - { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, min_luminance), { .f=-1 } }, - { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, max_luminance), { .f=-1 } }, + { MATROSKA_ID_VIDEOCOLOR_RX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, r_x) }, + { MATROSKA_ID_VIDEOCOLOR_RY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, r_y) }, + { MATROSKA_ID_VIDEOCOLOR_GX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, g_x) }, + { MATROSKA_ID_VIDEOCOLOR_GY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, g_y) }, + { MATROSKA_ID_VIDEOCOLOR_BX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, b_x) }, + { MATROSKA_ID_VIDEOCOLOR_BY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, b_y) }, + { MATROSKA_ID_VIDEOCOLOR_WHITEX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, white_x) }, + { MATROSKA_ID_VIDEOCOLOR_WHITEY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, white_y) }, + { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN, EBML_FLOAT, 1, 0, offsetof(MatroskaMasteringMeta, min_luminance) }, + { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, max_luminance) }, CHILD_OF(matroska_track_video_color) }; static EbmlSyntax matroska_track_video_color[] = { - { MATROSKA_ID_VIDEOCOLORMATRIXCOEFF, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, matrix_coefficients), { .u = AVCOL_SPC_UNSPECIFIED } }, - { MATROSKA_ID_VIDEOCOLORBITSPERCHANNEL, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, bits_per_channel), { .u=0 } }, - { MATROSKA_ID_VIDEOCOLORCHROMASUBHORZ, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_horz), { .u=0 } }, - { MATROSKA_ID_VIDEOCOLORCHROMASUBVERT, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_vert), { .u=0 } }, - { MATROSKA_ID_VIDEOCOLORCBSUBHORZ, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, cb_sub_horz), { .u=0 } }, - { MATROSKA_ID_VIDEOCOLORCBSUBVERT, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, cb_sub_vert), { .u=0 } }, - { MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_horz), { .u = MATROSKA_COLOUR_CHROMASITINGHORZ_UNDETERMINED } }, - { MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_vert), { .u = MATROSKA_COLOUR_CHROMASITINGVERT_UNDETERMINED } }, - { MATROSKA_ID_VIDEOCOLORRANGE, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, range), { .u = AVCOL_RANGE_UNSPECIFIED } }, - { MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, transfer_characteristics), { .u = AVCOL_TRC_UNSPECIFIED } }, - { MATROSKA_ID_VIDEOCOLORPRIMARIES, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, primaries), { .u = AVCOL_PRI_UNSPECIFIED } }, - { MATROSKA_ID_VIDEOCOLORMAXCLL, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, max_cll), { .u=0 } }, - { MATROSKA_ID_VIDEOCOLORMAXFALL, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, max_fall), { .u=0 } }, - { MATROSKA_ID_VIDEOCOLORMASTERINGMETA, EBML_NEST, 0, offsetof(MatroskaTrackVideoColor, mastering_meta), { .n = matroska_mastering_meta } }, + { MATROSKA_ID_VIDEOCOLORMATRIXCOEFF, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, matrix_coefficients), { .u = AVCOL_SPC_UNSPECIFIED } }, + { MATROSKA_ID_VIDEOCOLORBITSPERCHANNEL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, bits_per_channel), { .u = 0 } }, + { MATROSKA_ID_VIDEOCOLORCHROMASUBHORZ, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_horz) }, + { MATROSKA_ID_VIDEOCOLORCHROMASUBVERT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_vert) }, + { MATROSKA_ID_VIDEOCOLORCBSUBHORZ, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, cb_sub_horz) }, + { MATROSKA_ID_VIDEOCOLORCBSUBVERT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, cb_sub_vert) }, + { MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_horz), { .u = MATROSKA_COLOUR_CHROMASITINGHORZ_UNDETERMINED } }, + { MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_vert), { .u = MATROSKA_COLOUR_CHROMASITINGVERT_UNDETERMINED } }, + { MATROSKA_ID_VIDEOCOLORRANGE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, range), { .u = AVCOL_RANGE_UNSPECIFIED } }, + { MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, transfer_characteristics), { .u = AVCOL_TRC_UNSPECIFIED } }, + { MATROSKA_ID_VIDEOCOLORPRIMARIES, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, primaries), { .u = AVCOL_PRI_UNSPECIFIED } }, + { MATROSKA_ID_VIDEOCOLORMAXCLL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, max_cll) }, + { MATROSKA_ID_VIDEOCOLORMAXFALL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, max_fall) }, + { MATROSKA_ID_VIDEOCOLORMASTERINGMETA, EBML_NEST, 0, 0, offsetof(MatroskaTrackVideoColor, mastering_meta), { .n = matroska_mastering_meta } }, CHILD_OF(matroska_track_video) }; static EbmlSyntax matroska_track_video_projection[] = { - { MATROSKA_ID_VIDEOPROJECTIONTYPE, EBML_UINT, 0, offsetof(MatroskaTrackVideoProjection, type), { .u = MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR } }, - { MATROSKA_ID_VIDEOPROJECTIONPRIVATE, EBML_BIN, 0, offsetof(MatroskaTrackVideoProjection, private) }, - { MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, EBML_FLOAT, 0, offsetof(MatroskaTrackVideoProjection, yaw), { .f=0.0 } }, - { MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, EBML_FLOAT, 0, offsetof(MatroskaTrackVideoProjection, pitch), { .f=0.0 } }, - { MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, EBML_FLOAT, 0, offsetof(MatroskaTrackVideoProjection, roll), { .f=0.0 } }, + { MATROSKA_ID_VIDEOPROJECTIONTYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoProjection, type), { .u = MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR } }, + { MATROSKA_ID_VIDEOPROJECTIONPRIVATE, EBML_BIN, 0, 0, offsetof(MatroskaTrackVideoProjection, private) }, + { MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideoProjection, yaw), { .f = 0.0 } }, + { MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideoProjection, pitch), { .f = 0.0 } }, + { MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideoProjection, roll), { .f = 0.0 } }, CHILD_OF(matroska_track_video) }; static EbmlSyntax matroska_track_video[] = { - { MATROSKA_ID_VIDEOFRAMERATE, EBML_FLOAT, 0, offsetof(MatroskaTrackVideo, frame_rate) }, - { MATROSKA_ID_VIDEODISPLAYWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo, display_width), { .u=-1 } }, - { MATROSKA_ID_VIDEODISPLAYHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo, display_height), { .u=-1 } }, - { MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, offsetof(MatroskaTrackVideo, pixel_width) }, - { MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, offsetof(MatroskaTrackVideo, pixel_height) }, - { MATROSKA_ID_VIDEOCOLORSPACE, EBML_BIN, 0, offsetof(MatroskaTrackVideo, color_space) }, - { MATROSKA_ID_VIDEOALPHAMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo, alpha_mode) }, - { MATROSKA_ID_VIDEOCOLOR, EBML_NEST, sizeof(MatroskaTrackVideoColor), offsetof(MatroskaTrackVideo, color), { .n = matroska_track_video_color } }, - { MATROSKA_ID_VIDEOPROJECTION, EBML_NEST, 0, offsetof(MatroskaTrackVideo, projection), { .n = matroska_track_video_projection } }, + { MATROSKA_ID_VIDEOFRAMERATE, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideo, frame_rate) }, + { MATROSKA_ID_VIDEODISPLAYWIDTH, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, display_width), { .u=-1 } }, + { MATROSKA_ID_VIDEODISPLAYHEIGHT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, display_height), { .u=-1 } }, + { MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, pixel_width) }, + { MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, pixel_height) }, + { MATROSKA_ID_VIDEOCOLORSPACE, EBML_BIN, 0, 0, offsetof(MatroskaTrackVideo, color_space) }, + { MATROSKA_ID_VIDEOALPHAMODE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, alpha_mode), { .u = 0 } }, + { MATROSKA_ID_VIDEOCOLOR, EBML_NEST, 0, sizeof(MatroskaTrackVideoColor), offsetof(MatroskaTrackVideo, color), { .n = matroska_track_video_color } }, + { MATROSKA_ID_VIDEOPROJECTION, EBML_NEST, 0, 0, offsetof(MatroskaTrackVideo, projection), { .n = matroska_track_video_projection } }, { MATROSKA_ID_VIDEOPIXELCROPB, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE }, { MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE }, - { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_UINT, 0, offsetof(MatroskaTrackVideo, display_unit), { .u= MATROSKA_VIDEO_DISPLAYUNIT_PIXELS } }, - { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_UINT, 0, offsetof(MatroskaTrackVideo, interlaced), { .u = MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED } }, - { MATROSKA_ID_VIDEOFIELDORDER, EBML_UINT, 0, offsetof(MatroskaTrackVideo, field_order), { .u = MATROSKA_VIDEO_FIELDORDER_UNDETERMINED } }, - { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo, stereo_mode), { .u = MATROSKA_VIDEO_STEREOMODE_TYPE_NB } }, + { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, display_unit), { .u= MATROSKA_VIDEO_DISPLAYUNIT_PIXELS } }, + { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, interlaced), { .u = MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED } }, + { MATROSKA_ID_VIDEOFIELDORDER, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, field_order), { .u = MATROSKA_VIDEO_FIELDORDER_UNDETERMINED } }, + { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, stereo_mode), { .u = MATROSKA_VIDEO_STEREOMODE_TYPE_NB } }, { MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE }, CHILD_OF(matroska_track) }; static EbmlSyntax matroska_track_audio[] = { - { MATROSKA_ID_AUDIOSAMPLINGFREQ, EBML_FLOAT, 0, offsetof(MatroskaTrackAudio, samplerate), { .f = 8000.0 } }, - { MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, EBML_FLOAT, 0, offsetof(MatroskaTrackAudio, out_samplerate) }, - { MATROSKA_ID_AUDIOBITDEPTH, EBML_UINT, 0, offsetof(MatroskaTrackAudio, bitdepth) }, - { MATROSKA_ID_AUDIOCHANNELS, EBML_UINT, 0, offsetof(MatroskaTrackAudio, channels), { .u = 1 } }, + { MATROSKA_ID_AUDIOSAMPLINGFREQ, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackAudio, samplerate), { .f = 8000.0 } }, + { MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackAudio, out_samplerate) }, + { MATROSKA_ID_AUDIOBITDEPTH, EBML_UINT, 0, 0, offsetof(MatroskaTrackAudio, bitdepth) }, + { MATROSKA_ID_AUDIOCHANNELS, EBML_UINT, 0, 0, offsetof(MatroskaTrackAudio, channels), { .u = 1 } }, CHILD_OF(matroska_track) }; static EbmlSyntax matroska_track_encoding_compression[] = { - { MATROSKA_ID_ENCODINGCOMPALGO, EBML_UINT, 0, offsetof(MatroskaTrackCompression, algo), { .u = 0 } }, - { MATROSKA_ID_ENCODINGCOMPSETTINGS, EBML_BIN, 0, offsetof(MatroskaTrackCompression, settings) }, + { MATROSKA_ID_ENCODINGCOMPALGO, EBML_UINT, 0, 0, offsetof(MatroskaTrackCompression, algo), { .u = MATROSKA_TRACK_ENCODING_COMP_ZLIB } }, + { MATROSKA_ID_ENCODINGCOMPSETTINGS, EBML_BIN, 0, 0, offsetof(MatroskaTrackCompression, settings) }, CHILD_OF(matroska_track_encoding) }; static EbmlSyntax matroska_track_encoding_encryption[] = { - { MATROSKA_ID_ENCODINGENCALGO, EBML_UINT, 0, offsetof(MatroskaTrackEncryption,algo), {.u = 0} }, - { MATROSKA_ID_ENCODINGENCKEYID, EBML_BIN, 0, offsetof(MatroskaTrackEncryption,key_id) }, + { MATROSKA_ID_ENCODINGENCALGO, EBML_UINT, 0, 0, offsetof(MatroskaTrackEncryption,algo), {.u = 0} }, + { MATROSKA_ID_ENCODINGENCKEYID, EBML_BIN, 0, 0, offsetof(MatroskaTrackEncryption,key_id) }, { MATROSKA_ID_ENCODINGENCAESSETTINGS, EBML_NONE }, { MATROSKA_ID_ENCODINGSIGALGO, EBML_NONE }, { MATROSKA_ID_ENCODINGSIGHASHALGO, EBML_NONE }, @@ -517,54 +538,59 @@ CHILD_OF(matroska_track_encoding) }; static EbmlSyntax matroska_track_encoding[] = { - { MATROSKA_ID_ENCODINGSCOPE, EBML_UINT, 0, offsetof(MatroskaTrackEncoding, scope), { .u = 1 } }, - { MATROSKA_ID_ENCODINGTYPE, EBML_UINT, 0, offsetof(MatroskaTrackEncoding, type), { .u = 0 } }, - { MATROSKA_ID_ENCODINGCOMPRESSION, EBML_NEST, 0, offsetof(MatroskaTrackEncoding, compression), { .n = matroska_track_encoding_compression } }, - { MATROSKA_ID_ENCODINGENCRYPTION, EBML_NEST, 0, offsetof(MatroskaTrackEncoding, encryption), { .n = matroska_track_encoding_encryption } }, + { MATROSKA_ID_ENCODINGSCOPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackEncoding, scope), { .u = 1 } }, + { MATROSKA_ID_ENCODINGTYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackEncoding, type), { .u = 0 } }, + { MATROSKA_ID_ENCODINGCOMPRESSION, EBML_NEST, 0, 0, offsetof(MatroskaTrackEncoding, compression), { .n = matroska_track_encoding_compression } }, + { MATROSKA_ID_ENCODINGENCRYPTION, EBML_NEST, 0, 0, offsetof(MatroskaTrackEncoding, encryption), { .n = matroska_track_encoding_encryption } }, { MATROSKA_ID_ENCODINGORDER, EBML_NONE }, CHILD_OF(matroska_track_encodings) }; static EbmlSyntax matroska_track_encodings[] = { - { MATROSKA_ID_TRACKCONTENTENCODING, EBML_NEST, sizeof(MatroskaTrackEncoding), offsetof(MatroskaTrack, encodings), { .n = matroska_track_encoding } }, + { MATROSKA_ID_TRACKCONTENTENCODING, EBML_NEST, 0, sizeof(MatroskaTrackEncoding), offsetof(MatroskaTrack, encodings), { .n = matroska_track_encoding } }, CHILD_OF(matroska_track) }; static EbmlSyntax matroska_track_plane[] = { - { MATROSKA_ID_TRACKPLANEUID, EBML_UINT, 0, offsetof(MatroskaTrackPlane,uid) }, - { MATROSKA_ID_TRACKPLANETYPE, EBML_UINT, 0, offsetof(MatroskaTrackPlane,type) }, + { MATROSKA_ID_TRACKPLANEUID, EBML_UINT, 0, 0, offsetof(MatroskaTrackPlane,uid) }, + { MATROSKA_ID_TRACKPLANETYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackPlane,type) }, CHILD_OF(matroska_track_combine_planes) }; static EbmlSyntax matroska_track_combine_planes[] = { - { MATROSKA_ID_TRACKPLANE, EBML_NEST, sizeof(MatroskaTrackPlane), offsetof(MatroskaTrackOperation,combine_planes), {.n = matroska_track_plane} }, + { MATROSKA_ID_TRACKPLANE, EBML_NEST, 0, sizeof(MatroskaTrackPlane), offsetof(MatroskaTrackOperation,combine_planes), {.n = matroska_track_plane} }, CHILD_OF(matroska_track_operation) }; static EbmlSyntax matroska_track_operation[] = { - { MATROSKA_ID_TRACKCOMBINEPLANES, EBML_NEST, 0, 0, {.n = matroska_track_combine_planes} }, + { MATROSKA_ID_TRACKCOMBINEPLANES, EBML_NEST, 0, 0, 0, {.n = matroska_track_combine_planes} }, CHILD_OF(matroska_track) }; static EbmlSyntax matroska_track[] = { - { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, offsetof(MatroskaTrack, num) }, - { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, offsetof(MatroskaTrack, name) }, - { MATROSKA_ID_TRACKUID, EBML_UINT, 0, offsetof(MatroskaTrack, uid) }, - { MATROSKA_ID_TRACKTYPE, EBML_UINT, 0, offsetof(MatroskaTrack, type) }, - { MATROSKA_ID_CODECID, EBML_STR, 0, offsetof(MatroskaTrack, codec_id) }, - { MATROSKA_ID_CODECPRIVATE, EBML_BIN, 0, offsetof(MatroskaTrack, codec_priv) }, - { MATROSKA_ID_CODECDELAY, EBML_UINT, 0, offsetof(MatroskaTrack, codec_delay) }, - { MATROSKA_ID_TRACKLANGUAGE, EBML_UTF8, 0, offsetof(MatroskaTrack, language), { .s = "eng" } }, - { MATROSKA_ID_TRACKDEFAULTDURATION, EBML_UINT, 0, offsetof(MatroskaTrack, default_duration) }, - { MATROSKA_ID_TRACKTIMECODESCALE, EBML_FLOAT, 0, offsetof(MatroskaTrack, time_scale), { .f = 1.0 } }, - { MATROSKA_ID_TRACKFLAGDEFAULT, EBML_UINT, 0, offsetof(MatroskaTrack, flag_default), { .u = 1 } }, - { MATROSKA_ID_TRACKFLAGFORCED, EBML_UINT, 0, offsetof(MatroskaTrack, flag_forced), { .u = 0 } }, - { MATROSKA_ID_TRACKVIDEO, EBML_NEST, 0, offsetof(MatroskaTrack, video), { .n = matroska_track_video } }, - { MATROSKA_ID_TRACKAUDIO, EBML_NEST, 0, offsetof(MatroskaTrack, audio), { .n = matroska_track_audio } }, - { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, offsetof(MatroskaTrack, operation), { .n = matroska_track_operation } }, - { MATROSKA_ID_TRACKCONTENTENCODINGS, EBML_NEST, 0, 0, { .n = matroska_track_encodings } }, - { MATROSKA_ID_TRACKMAXBLKADDID, EBML_UINT, 0, offsetof(MatroskaTrack, max_block_additional_id) }, - { MATROSKA_ID_SEEKPREROLL, EBML_UINT, 0, offsetof(MatroskaTrack, seek_preroll) }, + { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, 0, offsetof(MatroskaTrack, num) }, + { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, 0, offsetof(MatroskaTrack, name) }, + { MATROSKA_ID_TRACKUID, EBML_UINT, 0, 0, offsetof(MatroskaTrack, uid) }, + { MATROSKA_ID_TRACKTYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrack, type) }, + { MATROSKA_ID_CODECID, EBML_STR, 0, 0, offsetof(MatroskaTrack, codec_id) }, + { MATROSKA_ID_CODECPRIVATE, EBML_BIN, 0, 0, offsetof(MatroskaTrack, codec_priv) }, + { MATROSKA_ID_CODECDELAY, EBML_UINT, 0, 0, offsetof(MatroskaTrack, codec_delay), { .u = 0 } }, + { MATROSKA_ID_TRACKLANGUAGE, EBML_STR, 0, 0, offsetof(MatroskaTrack, language), { .s = "eng" } }, + { MATROSKA_ID_TRACKDEFAULTDURATION, EBML_UINT, 0, 0, offsetof(MatroskaTrack, default_duration) }, + { MATROSKA_ID_TRACKTIMECODESCALE, EBML_FLOAT, 0, 0, offsetof(MatroskaTrack, time_scale), { .f = 1.0 } }, + { MATROSKA_ID_TRACKFLAGCOMMENTARY, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_comment), { .u = 0 } }, + { MATROSKA_ID_TRACKFLAGDEFAULT, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_default), { .u = 1 } }, + { MATROSKA_ID_TRACKFLAGFORCED, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_forced), { .u = 0 } }, + { MATROSKA_ID_TRACKFLAGHEARINGIMPAIRED, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_hearingimpaired), { .u = 0 } }, + { MATROSKA_ID_TRACKFLAGVISUALIMPAIRED, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_visualimpaired), { .u = 0 } }, + { MATROSKA_ID_TRACKFLAGTEXTDESCRIPTIONS, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_textdescriptions), { .u = 0 } }, + { MATROSKA_ID_TRACKFLAGORIGINAL, EBML_UINT, 1, 0, offsetof(MatroskaTrack, flag_original), {.u = 0 } }, + { MATROSKA_ID_TRACKVIDEO, EBML_NEST, 0, 0, offsetof(MatroskaTrack, video), { .n = matroska_track_video } }, + { MATROSKA_ID_TRACKAUDIO, EBML_NEST, 0, 0, offsetof(MatroskaTrack, audio), { .n = matroska_track_audio } }, + { 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_SEEKPREROLL, EBML_UINT, 0, 0, offsetof(MatroskaTrack, seek_preroll), { .u = 0 } }, { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE }, { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE }, { MATROSKA_ID_CODECNAME, EBML_NONE }, @@ -577,36 +603,36 @@ }; static EbmlSyntax matroska_tracks[] = { - { MATROSKA_ID_TRACKENTRY, EBML_NEST, sizeof(MatroskaTrack), offsetof(MatroskaDemuxContext, tracks), { .n = matroska_track } }, + { MATROSKA_ID_TRACKENTRY, EBML_NEST, 0, sizeof(MatroskaTrack), offsetof(MatroskaDemuxContext, tracks), { .n = matroska_track } }, CHILD_OF(matroska_segment) }; static EbmlSyntax matroska_attachment[] = { - { MATROSKA_ID_FILEUID, EBML_UINT, 0, offsetof(MatroskaAttachment, uid) }, - { MATROSKA_ID_FILENAME, EBML_UTF8, 0, offsetof(MatroskaAttachment, filename) }, - { MATROSKA_ID_FILEMIMETYPE, EBML_STR, 0, offsetof(MatroskaAttachment, mime) }, - { MATROSKA_ID_FILEDATA, EBML_BIN, 0, offsetof(MatroskaAttachment, bin) }, - { MATROSKA_ID_FILEDESC, EBML_NONE }, + { MATROSKA_ID_FILEUID, EBML_UINT, 0, 0, offsetof(MatroskaAttachment, uid) }, + { MATROSKA_ID_FILENAME, EBML_UTF8, 0, 0, offsetof(MatroskaAttachment, filename) }, + { MATROSKA_ID_FILEMIMETYPE, EBML_STR, 0, 0, offsetof(MatroskaAttachment, mime) }, + { MATROSKA_ID_FILEDATA, EBML_BIN, 0, 0, offsetof(MatroskaAttachment, bin) }, + { MATROSKA_ID_FILEDESC, EBML_UTF8, 0, 0, offsetof(MatroskaAttachment, description) }, CHILD_OF(matroska_attachments) }; static EbmlSyntax matroska_attachments[] = { - { MATROSKA_ID_ATTACHEDFILE, EBML_NEST, sizeof(MatroskaAttachment), offsetof(MatroskaDemuxContext, attachments), { .n = matroska_attachment } }, + { MATROSKA_ID_ATTACHEDFILE, EBML_NEST, 0, sizeof(MatroskaAttachment), offsetof(MatroskaDemuxContext, attachments), { .n = matroska_attachment } }, CHILD_OF(matroska_segment) }; static EbmlSyntax matroska_chapter_display[] = { - { MATROSKA_ID_CHAPSTRING, EBML_UTF8, 0, offsetof(MatroskaChapter, title) }, + { MATROSKA_ID_CHAPSTRING, EBML_UTF8, 0, 0, offsetof(MatroskaChapter, title) }, { MATROSKA_ID_CHAPLANG, EBML_NONE }, { MATROSKA_ID_CHAPCOUNTRY, EBML_NONE }, CHILD_OF(matroska_chapter_entry) }; static EbmlSyntax matroska_chapter_entry[] = { - { MATROSKA_ID_CHAPTERTIMESTART, EBML_UINT, 0, offsetof(MatroskaChapter, start), { .u = AV_NOPTS_VALUE } }, - { MATROSKA_ID_CHAPTERTIMEEND, EBML_UINT, 0, offsetof(MatroskaChapter, end), { .u = AV_NOPTS_VALUE } }, - { MATROSKA_ID_CHAPTERUID, EBML_UINT, 0, offsetof(MatroskaChapter, uid) }, - { MATROSKA_ID_CHAPTERDISPLAY, EBML_NEST, 0, 0, { .n = matroska_chapter_display } }, + { MATROSKA_ID_CHAPTERTIMESTART, EBML_UINT, 0, 0, offsetof(MatroskaChapter, start), { .u = AV_NOPTS_VALUE } }, + { MATROSKA_ID_CHAPTERTIMEEND, EBML_UINT, 0, 0, offsetof(MatroskaChapter, end), { .u = AV_NOPTS_VALUE } }, + { MATROSKA_ID_CHAPTERUID, EBML_UINT, 0, 0, offsetof(MatroskaChapter, uid) }, + { MATROSKA_ID_CHAPTERDISPLAY, EBML_NEST, 0, 0, 0, { .n = matroska_chapter_display } }, { MATROSKA_ID_CHAPTERFLAGHIDDEN, EBML_NONE }, { MATROSKA_ID_CHAPTERFLAGENABLED, EBML_NONE }, { MATROSKA_ID_CHAPTERPHYSEQUIV, EBML_NONE }, @@ -615,7 +641,7 @@ }; static EbmlSyntax matroska_chapter[] = { - { MATROSKA_ID_CHAPTERATOM, EBML_NEST, sizeof(MatroskaChapter), offsetof(MatroskaDemuxContext, chapters), { .n = matroska_chapter_entry } }, + { MATROSKA_ID_CHAPTERATOM, EBML_NEST, 0, sizeof(MatroskaChapter), offsetof(MatroskaDemuxContext, chapters), { .n = matroska_chapter_entry } }, { MATROSKA_ID_EDITIONUID, EBML_NONE }, { MATROSKA_ID_EDITIONFLAGHIDDEN, EBML_NONE }, { MATROSKA_ID_EDITIONFLAGDEFAULT, EBML_NONE }, @@ -624,13 +650,13 @@ }; static EbmlSyntax matroska_chapters[] = { - { MATROSKA_ID_EDITIONENTRY, EBML_NEST, 0, 0, { .n = matroska_chapter } }, + { MATROSKA_ID_EDITIONENTRY, EBML_NEST, 0, 0, 0, { .n = matroska_chapter } }, CHILD_OF(matroska_segment) }; static EbmlSyntax matroska_index_pos[] = { - { MATROSKA_ID_CUETRACK, EBML_UINT, 0, offsetof(MatroskaIndexPos, track) }, - { MATROSKA_ID_CUECLUSTERPOSITION, EBML_UINT, 0, offsetof(MatroskaIndexPos, pos) }, + { MATROSKA_ID_CUETRACK, EBML_UINT, 0, 0, offsetof(MatroskaIndexPos, track) }, + { MATROSKA_ID_CUECLUSTERPOSITION, EBML_UINT, 0, 0, offsetof(MatroskaIndexPos, pos) }, { MATROSKA_ID_CUERELATIVEPOSITION,EBML_NONE }, { MATROSKA_ID_CUEDURATION, EBML_NONE }, { MATROSKA_ID_CUEBLOCKNUMBER, EBML_NONE }, @@ -638,102 +664,102 @@ }; static EbmlSyntax matroska_index_entry[] = { - { MATROSKA_ID_CUETIME, EBML_UINT, 0, offsetof(MatroskaIndex, time) }, - { MATROSKA_ID_CUETRACKPOSITION, EBML_NEST, sizeof(MatroskaIndexPos), offsetof(MatroskaIndex, pos), { .n = matroska_index_pos } }, + { MATROSKA_ID_CUETIME, EBML_UINT, 0, 0, offsetof(MatroskaIndex, time) }, + { MATROSKA_ID_CUETRACKPOSITION, EBML_NEST, 0, sizeof(MatroskaIndexPos), offsetof(MatroskaIndex, pos), { .n = matroska_index_pos } }, CHILD_OF(matroska_index) }; static EbmlSyntax matroska_index[] = { - { MATROSKA_ID_POINTENTRY, EBML_NEST, sizeof(MatroskaIndex), offsetof(MatroskaDemuxContext, index), { .n = matroska_index_entry } }, + { MATROSKA_ID_POINTENTRY, EBML_NEST, 0, sizeof(MatroskaIndex), offsetof(MatroskaDemuxContext, index), { .n = matroska_index_entry } }, CHILD_OF(matroska_segment) }; static EbmlSyntax matroska_simpletag[] = { - { MATROSKA_ID_TAGNAME, EBML_UTF8, 0, offsetof(MatroskaTag, name) }, - { MATROSKA_ID_TAGSTRING, EBML_UTF8, 0, offsetof(MatroskaTag, string) }, - { MATROSKA_ID_TAGLANG, EBML_STR, 0, offsetof(MatroskaTag, lang), { .s = "und" } }, - { MATROSKA_ID_TAGDEFAULT, EBML_UINT, 0, offsetof(MatroskaTag, def) }, - { MATROSKA_ID_TAGDEFAULT_BUG, EBML_UINT, 0, offsetof(MatroskaTag, def) }, - { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTag, sub), { .n = matroska_simpletag } }, + { MATROSKA_ID_TAGNAME, EBML_UTF8, 0, 0, offsetof(MatroskaTag, name) }, + { MATROSKA_ID_TAGSTRING, EBML_UTF8, 0, 0, offsetof(MatroskaTag, string) }, + { MATROSKA_ID_TAGLANG, EBML_STR, 0, 0, offsetof(MatroskaTag, lang), { .s = "und" } }, + { MATROSKA_ID_TAGDEFAULT, EBML_UINT, 0, 0, offsetof(MatroskaTag, def) }, + { MATROSKA_ID_TAGDEFAULT_BUG, EBML_UINT, 0, 0, offsetof(MatroskaTag, def) }, + { MATROSKA_ID_SIMPLETAG, EBML_NEST, 0, sizeof(MatroskaTag), offsetof(MatroskaTag, sub), { .n = matroska_simpletag } }, CHILD_OF(matroska_tag) }; static EbmlSyntax matroska_tagtargets[] = { - { MATROSKA_ID_TAGTARGETS_TYPE, EBML_STR, 0, offsetof(MatroskaTagTarget, type) }, - { MATROSKA_ID_TAGTARGETS_TYPEVALUE, EBML_UINT, 0, offsetof(MatroskaTagTarget, typevalue), { .u = 50 } }, - { MATROSKA_ID_TAGTARGETS_TRACKUID, EBML_UINT, 0, offsetof(MatroskaTagTarget, trackuid) }, - { MATROSKA_ID_TAGTARGETS_CHAPTERUID, EBML_UINT, 0, offsetof(MatroskaTagTarget, chapteruid) }, - { MATROSKA_ID_TAGTARGETS_ATTACHUID, EBML_UINT, 0, offsetof(MatroskaTagTarget, attachuid) }, + { MATROSKA_ID_TAGTARGETS_TYPE, EBML_STR, 0, 0, offsetof(MatroskaTagTarget, type) }, + { MATROSKA_ID_TAGTARGETS_TYPEVALUE, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, typevalue), { .u = 50 } }, + { MATROSKA_ID_TAGTARGETS_TRACKUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, trackuid), { .u = 0 } }, + { MATROSKA_ID_TAGTARGETS_CHAPTERUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, chapteruid), { .u = 0 } }, + { MATROSKA_ID_TAGTARGETS_ATTACHUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, attachuid), { .u = 0 } }, CHILD_OF(matroska_tag) }; static EbmlSyntax matroska_tag[] = { - { MATROSKA_ID_SIMPLETAG, EBML_NEST, sizeof(MatroskaTag), offsetof(MatroskaTags, tag), { .n = matroska_simpletag } }, - { MATROSKA_ID_TAGTARGETS, EBML_NEST, 0, offsetof(MatroskaTags, target), { .n = matroska_tagtargets } }, + { MATROSKA_ID_SIMPLETAG, EBML_NEST, 0, sizeof(MatroskaTag), offsetof(MatroskaTags, tag), { .n = matroska_simpletag } }, + { MATROSKA_ID_TAGTARGETS, EBML_NEST, 0, 0, offsetof(MatroskaTags, target), { .n = matroska_tagtargets } }, CHILD_OF(matroska_tags) }; static EbmlSyntax matroska_tags[] = { - { MATROSKA_ID_TAG, EBML_NEST, sizeof(MatroskaTags), offsetof(MatroskaDemuxContext, tags), { .n = matroska_tag } }, + { MATROSKA_ID_TAG, EBML_NEST, 0, sizeof(MatroskaTags), offsetof(MatroskaDemuxContext, tags), { .n = matroska_tag } }, CHILD_OF(matroska_segment) }; static EbmlSyntax matroska_seekhead_entry[] = { - { MATROSKA_ID_SEEKID, EBML_UINT, 0, offsetof(MatroskaSeekhead, id) }, - { MATROSKA_ID_SEEKPOSITION, EBML_UINT, 0, offsetof(MatroskaSeekhead, pos), { .u = -1 } }, + { MATROSKA_ID_SEEKID, EBML_UINT, 0, 0, offsetof(MatroskaSeekhead, id) }, + { MATROSKA_ID_SEEKPOSITION, EBML_UINT, 0, 0, offsetof(MatroskaSeekhead, pos), { .u = -1 } }, CHILD_OF(matroska_seekhead) }; static EbmlSyntax matroska_seekhead[] = { - { MATROSKA_ID_SEEKENTRY, EBML_NEST, sizeof(MatroskaSeekhead), offsetof(MatroskaDemuxContext, seekhead), { .n = matroska_seekhead_entry } }, + { MATROSKA_ID_SEEKENTRY, EBML_NEST, 0, sizeof(MatroskaSeekhead), offsetof(MatroskaDemuxContext, seekhead), { .n = matroska_seekhead_entry } }, CHILD_OF(matroska_segment) }; static EbmlSyntax matroska_segment[] = { { MATROSKA_ID_CLUSTER, EBML_STOP }, - { MATROSKA_ID_INFO, EBML_LEVEL1, 0, 0, { .n = matroska_info } }, - { MATROSKA_ID_TRACKS, EBML_LEVEL1, 0, 0, { .n = matroska_tracks } }, - { MATROSKA_ID_ATTACHMENTS, EBML_LEVEL1, 0, 0, { .n = matroska_attachments } }, - { MATROSKA_ID_CHAPTERS, EBML_LEVEL1, 0, 0, { .n = matroska_chapters } }, - { MATROSKA_ID_CUES, EBML_LEVEL1, 0, 0, { .n = matroska_index } }, - { MATROSKA_ID_TAGS, EBML_LEVEL1, 0, 0, { .n = matroska_tags } }, - { MATROSKA_ID_SEEKHEAD, EBML_LEVEL1, 0, 0, { .n = matroska_seekhead } }, + { MATROSKA_ID_INFO, EBML_LEVEL1, 0, 0, 0, { .n = matroska_info } }, + { MATROSKA_ID_TRACKS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_tracks } }, + { MATROSKA_ID_ATTACHMENTS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_attachments } }, + { MATROSKA_ID_CHAPTERS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_chapters } }, + { MATROSKA_ID_CUES, EBML_LEVEL1, 0, 0, 0, { .n = matroska_index } }, + { MATROSKA_ID_TAGS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_tags } }, + { MATROSKA_ID_SEEKHEAD, EBML_LEVEL1, 0, 0, 0, { .n = matroska_seekhead } }, { 0 } /* We don't want to go back to level 0, so don't add the parent. */ }; static EbmlSyntax matroska_segments[] = { - { MATROSKA_ID_SEGMENT, EBML_NEST, 0, 0, { .n = matroska_segment } }, + { MATROSKA_ID_SEGMENT, EBML_NEST, 0, 0, 0, { .n = matroska_segment } }, { 0 } }; static EbmlSyntax matroska_blockmore[] = { - { MATROSKA_ID_BLOCKADDID, EBML_UINT, 0, offsetof(MatroskaBlock,additional_id) }, - { MATROSKA_ID_BLOCKADDITIONAL, EBML_BIN, 0, offsetof(MatroskaBlock,additional) }, + { MATROSKA_ID_BLOCKADDID, EBML_UINT, 0, 0, offsetof(MatroskaBlock,additional_id), { .u = 1 } }, + { MATROSKA_ID_BLOCKADDITIONAL, EBML_BIN, 0, 0, offsetof(MatroskaBlock,additional) }, CHILD_OF(matroska_blockadditions) }; static EbmlSyntax matroska_blockadditions[] = { - { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, 0, {.n = matroska_blockmore} }, + { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, 0, 0, {.n = matroska_blockmore} }, CHILD_OF(matroska_blockgroup) }; static EbmlSyntax matroska_blockgroup[] = { - { MATROSKA_ID_BLOCK, EBML_BIN, 0, offsetof(MatroskaBlock, bin) }, - { MATROSKA_ID_BLOCKADDITIONS, EBML_NEST, 0, 0, { .n = matroska_blockadditions} }, - { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, offsetof(MatroskaBlock, duration) }, - { MATROSKA_ID_DISCARDPADDING, EBML_SINT, 0, offsetof(MatroskaBlock, discard_padding) }, - { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 0, offsetof(MatroskaBlock, reference), { .i = INT64_MIN } }, + { MATROSKA_ID_BLOCK, EBML_BIN, 0, 0, offsetof(MatroskaBlock, bin) }, + { MATROSKA_ID_BLOCKADDITIONS, EBML_NEST, 0, 0, 0, { .n = matroska_blockadditions} }, + { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, 0, offsetof(MatroskaBlock, duration) }, + { MATROSKA_ID_DISCARDPADDING, EBML_SINT, 0, 0, offsetof(MatroskaBlock, discard_padding) }, + { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 1, 0, offsetof(MatroskaBlock, reference) }, { MATROSKA_ID_CODECSTATE, EBML_NONE }, - { 1, EBML_UINT, 0, offsetof(MatroskaBlock, non_simple), { .u = 1 } }, + { 1, EBML_UINT, 0, 0, offsetof(MatroskaBlock, non_simple), { .u = 1 } }, CHILD_OF(matroska_cluster_parsing) }; // The following array contains SimpleBlock and BlockGroup twice // in order to reuse the other values for matroska_cluster_enter. static EbmlSyntax matroska_cluster_parsing[] = { - { MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, offsetof(MatroskaBlock, bin) }, - { MATROSKA_ID_BLOCKGROUP, EBML_NEST, 0, 0, { .n = matroska_blockgroup } }, - { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, offsetof(MatroskaCluster, timecode) }, + { MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, 0, offsetof(MatroskaBlock, bin) }, + { MATROSKA_ID_BLOCKGROUP, EBML_NEST, 0, 0, 0, { .n = matroska_blockgroup } }, + { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, 0, offsetof(MatroskaCluster, timecode) }, { MATROSKA_ID_SIMPLEBLOCK, EBML_STOP }, { MATROSKA_ID_BLOCKGROUP, EBML_STOP }, { MATROSKA_ID_CLUSTERPOSITION, EBML_NONE }, @@ -742,11 +768,30 @@ }; static EbmlSyntax matroska_cluster_enter[] = { - { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, { .n = &matroska_cluster_parsing[2] } }, + { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, 0, { .n = &matroska_cluster_parsing[2] } }, { 0 } }; #undef CHILD_OF +static const CodecMime mkv_image_mime_tags[] = { + {"image/gif" , AV_CODEC_ID_GIF}, + {"image/jpeg" , AV_CODEC_ID_MJPEG}, + {"image/png" , AV_CODEC_ID_PNG}, + {"image/tiff" , AV_CODEC_ID_TIFF}, + + {"" , AV_CODEC_ID_NONE} +}; + +static const CodecMime mkv_mime_tags[] = { + {"text/plain" , AV_CODEC_ID_TEXT}, + {"application/x-truetype-font", AV_CODEC_ID_TTF}, + {"application/x-font" , AV_CODEC_ID_TTF}, + {"application/vnd.ms-opentype", AV_CODEC_ID_OTF}, + {"binary" , AV_CODEC_ID_BIN_DATA}, + + {"" , AV_CODEC_ID_NONE} +}; + static const char *const matroska_doctypes[] = { "matroska", "webm" }; static int matroska_read_close(AVFormatContext *s); @@ -896,12 +941,17 @@ /* * Read the next element as an unsigned int. - * Returns NEEDS_CHECKING. + * Returns NEEDS_CHECKING unless size == 0. */ -static int ebml_read_uint(AVIOContext *pb, int size, uint64_t *num) +static int ebml_read_uint(AVIOContext *pb, int size, + uint64_t default_value, uint64_t *num) { int n = 0; + if (size == 0) { + *num = default_value; + return 0; + } /* big-endian ordering; build up number */ *num = 0; while (n++ < size) @@ -912,14 +962,16 @@ /* * Read the next element as a signed int. - * Returns NEEDS_CHECKING. + * Returns NEEDS_CHECKING unless size == 0. */ -static int ebml_read_sint(AVIOContext *pb, int size, int64_t *num) +static int ebml_read_sint(AVIOContext *pb, int size, + int64_t default_value, int64_t *num) { int n = 1; if (size == 0) { - *num = 0; + *num = default_value; + return 0; } else { *num = sign_extend(avio_r8(pb), 8); @@ -933,17 +985,19 @@ /* * Read the next element as a float. - * Returns NEEDS_CHECKING or < 0 on obvious failure. + * Returns 0 if size == 0, NEEDS_CHECKING or < 0 on obvious failure. */ -static int ebml_read_float(AVIOContext *pb, int size, double *num) +static int ebml_read_float(AVIOContext *pb, int size, + double default_value, double *num) { - if (size == 0) - *num = 0; - else if (size == 4) + if (size == 0) { + *num = default_value; + return 0; + } else if (size == 4) { *num = av_int2float(avio_rb32(pb)); - else if (size == 8) + } else if (size == 8) { *num = av_int2double(avio_rb64(pb)); - else + } else return AVERROR_INVALIDDATA; return NEEDS_CHECKING; @@ -953,20 +1007,27 @@ * Read the next element as an ASCII string. * 0 is success, < 0 or NEEDS_CHECKING is failure. */ -static int ebml_read_ascii(AVIOContext *pb, int size, char **str) +static int ebml_read_ascii(AVIOContext *pb, int size, + const char *default_value, char **str) { char *res; int ret; - /* EBML strings are usually not 0-terminated, so we allocate one - * byte more, read the string and NULL-terminate it ourselves. */ - if (!(res = av_malloc(size + 1))) - return AVERROR(ENOMEM); - if ((ret = avio_read(pb, (uint8_t *) res, size)) != size) { - av_free(res); - return ret < 0 ? ret : NEEDS_CHECKING; + if (size == 0 && default_value) { + res = av_strdup(default_value); + if (!res) + return AVERROR(ENOMEM); + } else { + /* EBML strings are usually not 0-terminated, so we allocate one + * byte more, read the string and NUL-terminate it ourselves. */ + if (!(res = av_malloc(size + 1))) + return AVERROR(ENOMEM); + if ((ret = avio_read(pb, (uint8_t *) res, size)) != size) { + av_free(res); + return ret < 0 ? ret : NEEDS_CHECKING; + } + (res)[size] = '\0'; } - (res)[size] = '\0'; av_free(*str); *str = res; @@ -1024,28 +1085,17 @@ } /* - * Read signed/unsigned "EBML" numbers. + * Read a signed "EBML number" * Return: number of bytes processed, < 0 on error */ -static int matroska_ebmlnum_uint(MatroskaDemuxContext *matroska, - uint8_t *data, uint32_t size, uint64_t *num) -{ - AVIOContext pb; - ffio_init_context(&pb, data, size, 0, NULL, NULL, NULL, NULL); - return ebml_read_num(matroska, &pb, FFMIN(size, 8), num, 1); -} - -/* - * Same as above, but signed. - */ static int matroska_ebmlnum_sint(MatroskaDemuxContext *matroska, - uint8_t *data, uint32_t size, int64_t *num) + AVIOContext *pb, int64_t *num) { uint64_t unum; int res; /* read as unsigned number first */ - if ((res = matroska_ebmlnum_uint(matroska, data, size, &unum)) < 0) + if ((res = ebml_read_num(matroska, pb, 8, &unum, 1)) < 0) return res; /* make signed (weird way) */ @@ -1076,28 +1126,29 @@ int res; if (data) { - for (int i = 0; syntax[i].id; i++) + for (int i = 0; syntax[i].id; i++) { + void *dst = (char *)data + syntax[i].data_offset; switch (syntax[i].type) { case EBML_UINT: - *(uint64_t *) ((char *) data + syntax[i].data_offset) = syntax[i].def.u; + *(uint64_t *)dst = syntax[i].def.u; break; case EBML_SINT: - *(int64_t *) ((char *) data + syntax[i].data_offset) = syntax[i].def.i; + *(int64_t *) dst = syntax[i].def.i; break; case EBML_FLOAT: - *(double *) ((char *) data + syntax[i].data_offset) = syntax[i].def.f; + *(double *) dst = syntax[i].def.f; break; case EBML_STR: case EBML_UTF8: // the default may be NULL if (syntax[i].def.s) { - uint8_t **dst = (uint8_t **) ((uint8_t *) data + syntax[i].data_offset); - *dst = av_strdup(syntax[i].def.s); - if (!*dst) + *(char**)dst = av_strdup(syntax[i].def.s); + if (!*(char**)dst) return AVERROR(ENOMEM); } break; } + } if (!matroska->levels[matroska->num_levels - 1].length) { matroska->num_levels--; @@ -1126,7 +1177,7 @@ * an entry already exists, return the existing entry. */ static MatroskaLevel1Element *matroska_find_level1_elem(MatroskaDemuxContext *matroska, - uint32_t id) + uint32_t id, int64_t pos) { int i; MatroskaLevel1Element *elem; @@ -1138,19 +1189,18 @@ if (id == MATROSKA_ID_CLUSTER) return NULL; - // There can be multiple seekheads. - if (id != MATROSKA_ID_SEEKHEAD) { - for (i = 0; i < matroska->num_level1_elems; i++) { - if (matroska->level1_elems[i].id == id) + // There can be multiple SeekHeads and Tags. + for (i = 0; i < matroska->num_level1_elems; i++) { + if (matroska->level1_elems[i].id == id) { + if (matroska->level1_elems[i].pos == pos || + id != MATROSKA_ID_SEEKHEAD && id != MATROSKA_ID_TAGS) return &matroska->level1_elems[i]; } } // Only a completely broken file would have more elements. - // It also provides a low-effort way to escape from circular seekheads - // (every iteration will add a level1 entry). if (matroska->num_level1_elems >= FF_ARRAY_ELEMS(matroska->level1_elems)) { - av_log(matroska->ctx, AV_LOG_ERROR, "Too many level1 elements or circular seekheads.\n"); + av_log(matroska->ctx, AV_LOG_ERROR, "Too many level1 elements.\n"); return NULL; } @@ -1375,17 +1425,17 @@ switch (syntax->type) { case EBML_UINT: - res = ebml_read_uint(pb, length, data); + res = ebml_read_uint(pb, length, syntax->def.u, data); break; case EBML_SINT: - res = ebml_read_sint(pb, length, data); + res = ebml_read_sint(pb, length, syntax->def.i, data); break; case EBML_FLOAT: - res = ebml_read_float(pb, length, data); + res = ebml_read_float(pb, length, syntax->def.f, data); break; case EBML_STR: case EBML_UTF8: - res = ebml_read_ascii(pb, length, data); + res = ebml_read_ascii(pb, length, syntax->def.s, data); break; case EBML_BIN: res = ebml_read_binary(pb, length, pos_alt, data); @@ -1399,7 +1449,7 @@ if (id == MATROSKA_ID_CUES) matroska->cues_parsing_deferred = 0; if (syntax->type == EBML_LEVEL1 && - (level1_elem = matroska_find_level1_elem(matroska, syntax->id))) { + (level1_elem = matroska_find_level1_elem(matroska, syntax->id, pos))) { if (!level1_elem->pos) { // Zero is not a valid position for a level 1 element. level1_elem->pos = pos; @@ -1458,6 +1508,12 @@ } level_check: + if (syntax->is_counted && data) { + CountedElement *elem = data; + if (elem->count != UINT_MAX) + elem->count++; + } + if (level_check == LEVEL_ENDED && matroska->num_levels) { level = &matroska->levels[matroska->num_levels - 1]; pos = avio_tell(pb); @@ -1556,7 +1612,7 @@ } static MatroskaTrack *matroska_find_track_by_num(MatroskaDemuxContext *matroska, - int num) + uint64_t num) { MatroskaTrack *tracks = matroska->tracks.elem; int i; @@ -1565,7 +1621,7 @@ if (tracks[i].num == num) return &tracks[i]; - av_log(matroska->ctx, AV_LOG_ERROR, "Invalid track number %d\n", num); + av_log(matroska->ctx, AV_LOG_ERROR, "Invalid track number %"PRIu64"\n", num); return NULL; } @@ -1610,6 +1666,7 @@ #if CONFIG_LZO case MATROSKA_TRACK_ENCODING_COMP_LZO: do { + int insize = isize; olen = pkt_size *= 3; newpktdata = av_realloc(pkt_data, pkt_size + AV_LZO_OUTPUT_PADDING + AV_INPUT_BUFFER_PADDING_SIZE); @@ -1618,7 +1675,7 @@ goto failed; } pkt_data = newpktdata; - result = av_lzo1x_decode(pkt_data, &olen, data, &isize); + result = av_lzo1x_decode(pkt_data, &olen, data, &insize); } while (result == AV_LZO_OUTPUT_FULL && pkt_size < 10000000); if (result) { result = AVERROR_INVALIDDATA; @@ -1762,7 +1819,7 @@ } } if (!found) { - av_log(NULL, AV_LOG_WARNING, + av_log(s, AV_LOG_WARNING, "The tags at index %d refer to a " "non-existent attachment %"PRId64".\n", i, tags[i].target.attachuid); @@ -1779,7 +1836,7 @@ } } if (!found) { - av_log(NULL, AV_LOG_WARNING, + av_log(s, AV_LOG_WARNING, "The tags at index %d refer to a non-existent chapter " "%"PRId64".\n", i, tags[i].target.chapteruid); @@ -1796,7 +1853,7 @@ } } if (!found) { - av_log(NULL, AV_LOG_WARNING, + av_log(s, AV_LOG_WARNING, "The tags at index %d refer to a non-existent track " "%"PRId64".\n", i, tags[i].target.trackuid); @@ -1856,8 +1913,12 @@ MatroskaSeekhead *seekheads = seekhead_list->elem; uint32_t id = seekheads[i].id; int64_t pos = seekheads[i].pos + matroska->segment_start; + MatroskaLevel1Element *elem; - MatroskaLevel1Element *elem = matroska_find_level1_elem(matroska, id); + if (id != seekheads[i].id || pos < matroska->segment_start) + continue; + + elem = matroska_find_level1_elem(matroska, id, pos); if (!elem || elem->parsed) continue; @@ -2013,12 +2074,12 @@ static int mkv_field_order(MatroskaDemuxContext *matroska, int64_t field_order) { - int major, minor, micro, bttb = 0; + int minor, micro, bttb = 0; /* workaround a bug in our Matroska muxer, introduced in version 57.36 alongside * this function, and fixed in 57.52 */ - if (matroska->muxingapp && sscanf(matroska->muxingapp, "Lavf%d.%d.%d", &major, &minor, µ) == 3) - bttb = (major == 57 && minor >= 36 && minor <= 51 && micro >= 100); + if (matroska->muxingapp && sscanf(matroska->muxingapp, "Lavf57.%d.%d", &minor, µ) == 2) + bttb = (minor >= 36 && minor <= 51 && micro >= 100); switch (field_order) { case MATROSKA_VIDEO_FIELDORDER_PROGRESSIVE: @@ -2078,7 +2139,10 @@ mastering_meta->g_x > 0 && mastering_meta->g_y > 0 && mastering_meta->b_x > 0 && mastering_meta->b_y > 0 && mastering_meta->white_x > 0 && mastering_meta->white_y > 0; - has_mastering_luminance = mastering_meta->max_luminance > 0; + has_mastering_luminance = mastering_meta->max_luminance > + mastering_meta->min_luminance.el.f && + mastering_meta->min_luminance.el.f >= 0 && + mastering_meta->min_luminance.count; if (color->matrix_coefficients != AVCOL_SPC_RESERVED) st->codecpar->color_space = color->matrix_coefficients; @@ -2116,9 +2180,6 @@ } if (has_mastering_primaries || has_mastering_luminance) { - // Use similar rationals as other standards. - const int chroma_den = 50000; - const int luma_den = 10000; AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata*) av_stream_new_side_data( st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, @@ -2128,71 +2189,59 @@ } memset(metadata, 0, sizeof(AVMasteringDisplayMetadata)); if (has_mastering_primaries) { - metadata->display_primaries[0][0] = av_make_q( - round(mastering_meta->r_x * chroma_den), chroma_den); - metadata->display_primaries[0][1] = av_make_q( - round(mastering_meta->r_y * chroma_den), chroma_den); - metadata->display_primaries[1][0] = av_make_q( - round(mastering_meta->g_x * chroma_den), chroma_den); - metadata->display_primaries[1][1] = av_make_q( - round(mastering_meta->g_y * chroma_den), chroma_den); - metadata->display_primaries[2][0] = av_make_q( - round(mastering_meta->b_x * chroma_den), chroma_den); - metadata->display_primaries[2][1] = av_make_q( - round(mastering_meta->b_y * chroma_den), chroma_den); - metadata->white_point[0] = av_make_q( - round(mastering_meta->white_x * chroma_den), chroma_den); - metadata->white_point[1] = av_make_q( - round(mastering_meta->white_y * chroma_den), chroma_den); + metadata->display_primaries[0][0] = av_d2q(mastering_meta->r_x, INT_MAX); + metadata->display_primaries[0][1] = av_d2q(mastering_meta->r_y, INT_MAX); + metadata->display_primaries[1][0] = av_d2q(mastering_meta->g_x, INT_MAX); + metadata->display_primaries[1][1] = av_d2q(mastering_meta->g_y, INT_MAX); + metadata->display_primaries[2][0] = av_d2q(mastering_meta->b_x, INT_MAX); + metadata->display_primaries[2][1] = av_d2q(mastering_meta->b_y, INT_MAX); + metadata->white_point[0] = av_d2q(mastering_meta->white_x, INT_MAX); + metadata->white_point[1] = av_d2q(mastering_meta->white_y, INT_MAX); metadata->has_primaries = 1; } if (has_mastering_luminance) { - metadata->max_luminance = av_make_q( - round(mastering_meta->max_luminance * luma_den), luma_den); - metadata->min_luminance = av_make_q( - round(mastering_meta->min_luminance * luma_den), luma_den); + metadata->max_luminance = av_d2q(mastering_meta->max_luminance, INT_MAX); + metadata->min_luminance = av_d2q(mastering_meta->min_luminance.el.f, INT_MAX); metadata->has_luminance = 1; } } return 0; } -static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track) { +static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track, + void *logctx) +{ AVSphericalMapping *spherical; + const MatroskaTrackVideoProjection *mkv_projection = &track->video.projection; + const uint8_t *priv_data = mkv_projection->private.data; enum AVSphericalProjection projection; size_t spherical_size; uint32_t l = 0, t = 0, r = 0, b = 0; uint32_t padding = 0; int ret; - GetByteContext gb; - bytestream2_init(&gb, track->video.projection.private.data, - track->video.projection.private.size); - - if (bytestream2_get_byte(&gb) != 0) { - av_log(NULL, AV_LOG_WARNING, "Unknown spherical metadata\n"); + if (mkv_projection->private.size && priv_data[0] != 0) { + av_log(logctx, AV_LOG_WARNING, "Unknown spherical metadata\n"); return 0; } - bytestream2_skip(&gb, 3); // flags - switch (track->video.projection.type) { case MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR: if (track->video.projection.private.size == 20) { - t = bytestream2_get_be32(&gb); - b = bytestream2_get_be32(&gb); - l = bytestream2_get_be32(&gb); - r = bytestream2_get_be32(&gb); + t = AV_RB32(priv_data + 4); + b = AV_RB32(priv_data + 8); + l = AV_RB32(priv_data + 12); + r = AV_RB32(priv_data + 16); if (b >= UINT_MAX - t || r >= UINT_MAX - l) { - av_log(NULL, AV_LOG_ERROR, + av_log(logctx, AV_LOG_ERROR, "Invalid bounding rectangle coordinates " "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", l, t, r, b); return AVERROR_INVALIDDATA; } } else if (track->video.projection.private.size != 0) { - av_log(NULL, AV_LOG_ERROR, "Unknown spherical metadata\n"); + av_log(logctx, AV_LOG_ERROR, "Unknown spherical metadata\n"); return AVERROR_INVALIDDATA; } @@ -2203,19 +2252,19 @@ break; case MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP: if (track->video.projection.private.size < 4) { - av_log(NULL, AV_LOG_ERROR, "Missing projection private properties\n"); + av_log(logctx, AV_LOG_ERROR, "Missing projection private properties\n"); return AVERROR_INVALIDDATA; } else if (track->video.projection.private.size == 12) { - uint32_t layout = bytestream2_get_be32(&gb); + uint32_t layout = AV_RB32(priv_data + 4); if (layout) { - av_log(NULL, AV_LOG_WARNING, + av_log(logctx, AV_LOG_WARNING, "Unknown spherical cubemap layout %"PRIu32"\n", layout); return 0; } projection = AV_SPHERICAL_CUBEMAP; - padding = bytestream2_get_be32(&gb); + padding = AV_RB32(priv_data + 8); } else { - av_log(NULL, AV_LOG_ERROR, "Unknown spherical metadata\n"); + av_log(logctx, AV_LOG_ERROR, "Unknown spherical metadata\n"); return AVERROR_INVALIDDATA; } break; @@ -2223,7 +2272,7 @@ /* No Spherical metadata */ return 0; default: - av_log(NULL, AV_LOG_WARNING, + av_log(logctx, AV_LOG_WARNING, "Unknown spherical metadata type %"PRIu64"\n", track->video.projection.type); return 0; @@ -2318,6 +2367,15 @@ if (!track->codec_id) continue; + if ( track->type == MATROSKA_TRACK_TYPE_AUDIO && track->codec_id[0] != 'A' + || track->type == MATROSKA_TRACK_TYPE_VIDEO && track->codec_id[0] != 'V' + || track->type == MATROSKA_TRACK_TYPE_SUBTITLE && track->codec_id[0] != 'D' && track->codec_id[0] != 'S' + || track->type == MATROSKA_TRACK_TYPE_METADATA && track->codec_id[0] != 'D' && track->codec_id[0] != 'S' + ) { + av_log(matroska->ctx, AV_LOG_INFO, "Inconsistent track type\n"); + continue; + } + if (track->audio.samplerate < 0 || track->audio.samplerate > INT_MAX || isnan(track->audio.samplerate)) { av_log(matroska->ctx, AV_LOG_WARNING, @@ -2409,10 +2467,14 @@ } } } + track->needs_decoding = encodings && !encodings[0].type && + encodings[0].scope & 1 && + (encodings[0].compression.algo != + MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP || + encodings[0].compression.settings.size); for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) { - if (!strncmp(ff_mkv_codec_tags[j].str, track->codec_id, - strlen(ff_mkv_codec_tags[j].str))) { + if (av_strstart(track->codec_id, ff_mkv_codec_tags[j].str, NULL)) { codec_id = ff_mkv_codec_tags[j].id; break; } @@ -2426,8 +2488,8 @@ if (key_id_base64) { /* export encryption key id as base64 metadata tag */ - av_dict_set(&st->metadata, "enc_key_id", key_id_base64, 0); - av_freep(&key_id_base64); + av_dict_set(&st->metadata, "enc_key_id", key_id_base64, + AV_DICT_DONT_STRDUP_VAL); } if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") && @@ -2558,34 +2620,33 @@ memcpy(&extradata[12], track->codec_priv.data, track->codec_priv.size); } else if (codec_id == AV_CODEC_ID_TTA) { - extradata_size = 30; - extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!extradata) - return AVERROR(ENOMEM); - ffio_init_context(&b, extradata, extradata_size, 1, - NULL, NULL, NULL, NULL); - avio_write(&b, "TTA1", 4); - avio_wl16(&b, 1); + uint8_t *ptr; if (track->audio.channels > UINT16_MAX || track->audio.bitdepth > UINT16_MAX) { av_log(matroska->ctx, AV_LOG_WARNING, "Too large audio channel number %"PRIu64 " or bitdepth %"PRIu64". Skipping track.\n", track->audio.channels, track->audio.bitdepth); - av_freep(&extradata); if (matroska->ctx->error_recognition & AV_EF_EXPLODE) return AVERROR_INVALIDDATA; else continue; } - avio_wl16(&b, track->audio.channels); - avio_wl16(&b, track->audio.bitdepth); if (track->audio.out_samplerate < 0 || track->audio.out_samplerate > INT_MAX) return AVERROR_INVALIDDATA; - avio_wl32(&b, track->audio.out_samplerate); - avio_wl32(&b, av_rescale((matroska->duration * matroska->time_scale), - track->audio.out_samplerate, - AV_TIME_BASE * 1000)); + extradata_size = 22; + extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!extradata) + return AVERROR(ENOMEM); + ptr = extradata; + bytestream_put_be32(&ptr, AV_RB32("TTA1")); + bytestream_put_le16(&ptr, 1); + bytestream_put_le16(&ptr, track->audio.channels); + bytestream_put_le16(&ptr, track->audio.bitdepth); + bytestream_put_le32(&ptr, track->audio.out_samplerate); + bytestream_put_le32(&ptr, av_rescale(matroska->duration * matroska->time_scale, + track->audio.out_samplerate, + AV_TIME_BASE * 1000)); } else if (codec_id == AV_CODEC_ID_RV10 || codec_id == AV_CODEC_ID_RV20 || codec_id == AV_CODEC_ID_RV30 || @@ -2611,32 +2672,46 @@ track->audio.sub_packet_h = avio_rb16(&b); track->audio.frame_size = avio_rb16(&b); track->audio.sub_packet_size = avio_rb16(&b); - if (flavor < 0 || - track->audio.coded_framesize <= 0 || + if (track->audio.coded_framesize <= 0 || track->audio.sub_packet_h <= 0 || - track->audio.frame_size <= 0 || - track->audio.sub_packet_size <= 0 && codec_id != AV_CODEC_ID_SIPR) + track->audio.frame_size <= 0) return AVERROR_INVALIDDATA; - track->audio.buf = av_malloc_array(track->audio.sub_packet_h, - track->audio.frame_size); - if (!track->audio.buf) - return AVERROR(ENOMEM); + if (codec_id == AV_CODEC_ID_RA_288) { + if (track->audio.sub_packet_h & 1 || 2 * track->audio.frame_size + != (int64_t)track->audio.sub_packet_h * track->audio.coded_framesize) + return AVERROR_INVALIDDATA; st->codecpar->block_align = track->audio.coded_framesize; track->codec_priv.size = 0; } else { - if (codec_id == AV_CODEC_ID_SIPR && flavor < 4) { + if (codec_id == AV_CODEC_ID_SIPR) { static const int sipr_bit_rate[4] = { 6504, 8496, 5000, 16000 }; + if (flavor > 3) + return AVERROR_INVALIDDATA; track->audio.sub_packet_size = ff_sipr_subpk_size[flavor]; st->codecpar->bit_rate = sipr_bit_rate[flavor]; - } + } else if (track->audio.sub_packet_size <= 0 || + track->audio.frame_size % track->audio.sub_packet_size) + return AVERROR_INVALIDDATA; st->codecpar->block_align = track->audio.sub_packet_size; extradata_offset = 78; } + track->audio.buf = av_malloc_array(track->audio.sub_packet_h, + track->audio.frame_size); + if (!track->audio.buf) + return AVERROR(ENOMEM); } else if (codec_id == AV_CODEC_ID_FLAC && track->codec_priv.size) { ret = matroska_parse_flac(s, track, &extradata_offset); if (ret < 0) return ret; + } else if (codec_id == AV_CODEC_ID_WAVPACK && track->codec_priv.size < 2) { + av_log(matroska->ctx, AV_LOG_INFO, "Assuming WavPack version 4.10 " + "in absence of valid CodecPrivate.\n"); + extradata_size = 2; + extradata = av_mallocz(2 + AV_INPUT_BUFFER_PADDING_SIZE); + if (!extradata) + return AVERROR(ENOMEM); + AV_WL16(extradata, 0x410); } else if (codec_id == AV_CODEC_ID_PRORES && track->codec_priv.size == 4) { fourcc = AV_RL32(track->codec_priv.data); } else if (codec_id == AV_CODEC_ID_VP9 && track->codec_priv.size) { @@ -2654,8 +2729,12 @@ av_log(matroska->ctx, AV_LOG_INFO, "Unknown/unsupported AVCodecID %s.\n", track->codec_id); - if (track->time_scale < 0.01) + if (track->time_scale < 0.01) { + av_log(matroska->ctx, AV_LOG_WARNING, + "Track TimestampScale too small %f, assuming 1.0.\n", + track->time_scale); track->time_scale = 1.0; + } avpriv_set_pts_info(st, 64, matroska->time_scale * track->time_scale, 1000 * 1000 * 1000); /* 64 bit pts in ns */ @@ -2674,6 +2753,15 @@ st->disposition |= AV_DISPOSITION_DEFAULT; if (track->flag_forced) st->disposition |= AV_DISPOSITION_FORCED; + if (track->flag_comment) + st->disposition |= AV_DISPOSITION_COMMENT; + if (track->flag_hearingimpaired) + st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; + if (track->flag_visualimpaired) + st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; + if (track->flag_original.count > 0) + st->disposition |= track->flag_original.el.u ? AV_DISPOSITION_ORIGINAL + : AV_DISPOSITION_DUB; if (!st->codecpar->extradata) { if (extradata) { @@ -2761,7 +2849,7 @@ ret = mkv_parse_video_color(st, track); if (ret < 0) return ret; - ret = mkv_parse_video_projection(st, track); + ret = mkv_parse_video_projection(st, track, matroska->ctx); if (ret < 0) return ret; } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { @@ -2800,6 +2888,9 @@ } } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) { st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; + + if (track->flag_textdescriptions) + st->disposition |= AV_DISPOSITION_DESCRIPTIONS; } } @@ -2854,6 +2945,10 @@ } ebml_free(ebml_syntax, &ebml); + matroska->pkt = av_packet_alloc(); + if (!matroska->pkt) + return AVERROR(ENOMEM); + /* The next thing is a segment. */ pos = avio_tell(matroska->ctx->pb); res = ebml_parse(matroska, matroska_segments, matroska); @@ -2864,6 +2959,8 @@ goto fail; pos = avio_tell(matroska->ctx->pb); res = ebml_parse(matroska, matroska_segment, matroska); + if (res == AVERROR(EIO)) // EOF is translated to EIO, this exists the loop on EOF + goto fail; } /* Set data_offset as it might be needed later by seek_frame_generic. */ if (matroska->current_id == MATROSKA_ID_CLUSTER) @@ -2896,12 +2993,13 @@ break; av_dict_set(&st->metadata, "filename", attachments[j].filename, 0); av_dict_set(&st->metadata, "mimetype", attachments[j].mime, 0); + if (attachments[j].description) + av_dict_set(&st->metadata, "title", attachments[j].description, 0); st->codecpar->codec_id = AV_CODEC_ID_NONE; - for (i = 0; ff_mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { - if (!strncmp(ff_mkv_image_mime_tags[i].str, attachments[j].mime, - strlen(ff_mkv_image_mime_tags[i].str))) { - st->codecpar->codec_id = ff_mkv_image_mime_tags[i].id; + for (i = 0; mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { + if (av_strstart(attachments[j].mime, mkv_image_mime_tags[i].str, NULL)) { + st->codecpar->codec_id = mkv_image_mime_tags[i].id; break; } } @@ -2914,10 +3012,9 @@ st->disposition |= AV_DISPOSITION_ATTACHED_PIC; st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - av_init_packet(pkt); - pkt->buf = av_buffer_ref(attachments[j].bin.buf); - if (!pkt->buf) - return AVERROR(ENOMEM); + av_packet_unref(pkt); + pkt->buf = attachments[j].bin.buf; + attachments[j].bin.buf = NULL; pkt->data = attachments[j].bin.data; pkt->size = attachments[j].bin.size; pkt->stream_index = st->index; @@ -2929,10 +3026,9 @@ memcpy(st->codecpar->extradata, attachments[j].bin.data, attachments[j].bin.size); - for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { - if (!strncmp(ff_mkv_mime_tags[i].str, attachments[j].mime, - strlen(ff_mkv_mime_tags[i].str))) { - st->codecpar->codec_id = ff_mkv_mime_tags[i].id; + for (i = 0; mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { + if (av_strstart(attachments[j].mime, mkv_mime_tags[i].str, NULL)) { + st->codecpar->codec_id = mkv_mime_tags[i].id; break; } } @@ -2949,10 +3045,6 @@ (AVRational) { 1, 1000000000 }, chapters[i].start, chapters[i].end, chapters[i].title); - if (chapters[i].chapter) { - av_dict_set(&chapters[i].chapter->metadata, - "title", chapters[i].title, 0); - } max_start = chapters[i].start; } @@ -2977,7 +3069,7 @@ MatroskaTrack *tracks = matroska->tracks.elem; MatroskaTrack *track; - ff_packet_list_get(&matroska->queue, &matroska->queue_end, pkt); + avpriv_packet_list_get(&matroska->queue, &matroska->queue_end, pkt); track = &tracks[pkt->stream_index]; if (track->has_palette) { uint8_t *pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); @@ -2999,71 +3091,57 @@ */ static void matroska_clear_queue(MatroskaDemuxContext *matroska) { - ff_packet_list_free(&matroska->queue, &matroska->queue_end); + avpriv_packet_list_free(&matroska->queue, &matroska->queue_end); } static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, - int *buf_size, int type, - uint32_t **lace_buf, int *laces) + int size, int type, AVIOContext *pb, + uint32_t lace_size[256], int *laces) { - int res = 0, n, size = *buf_size; + int n; uint8_t *data = *buf; - uint32_t *lace_size; if (!type) { *laces = 1; - *lace_buf = av_malloc(sizeof(**lace_buf)); - if (!*lace_buf) - return AVERROR(ENOMEM); - - *lace_buf[0] = size; + lace_size[0] = size; return 0; } - av_assert0(size > 0); - *laces = *data + 1; - data += 1; - size -= 1; - lace_size = av_malloc_array(*laces, sizeof(*lace_size)); - if (!lace_size) - return AVERROR(ENOMEM); + if (size <= 0) + return AVERROR_INVALIDDATA; + + *laces = *data + 1; + data += 1; + size -= 1; switch (type) { case 0x1: /* Xiph lacing */ { uint8_t temp; uint32_t total = 0; - for (n = 0; res == 0 && n < *laces - 1; n++) { + for (n = 0; n < *laces - 1; n++) { lace_size[n] = 0; - while (1) { - if (size <= total) { - res = AVERROR_INVALIDDATA; - break; - } + do { + if (size <= total) + return AVERROR_INVALIDDATA; temp = *data; total += temp; lace_size[n] += temp; data += 1; size -= 1; - if (temp != 0xff) - break; - } - } - if (size <= total) { - res = AVERROR_INVALIDDATA; - break; + } while (temp == 0xff); } + if (size < total) + return AVERROR_INVALIDDATA; lace_size[n] = size - total; break; } case 0x2: /* fixed-size lacing */ - if (size % (*laces)) { - res = AVERROR_INVALIDDATA; - break; - } + if (size % (*laces)) + return AVERROR_INVALIDDATA; for (n = 0; n < *laces; n++) lace_size[n] = size / *laces; break; @@ -3072,45 +3150,44 @@ { uint64_t num; uint64_t total; - n = matroska_ebmlnum_uint(matroska, data, size, &num); - if (n < 0 || num > INT_MAX) { - av_log(matroska->ctx, AV_LOG_INFO, - "EBML block data error\n"); - res = n<0 ? n : AVERROR_INVALIDDATA; - break; - } - data += n; - size -= n; + int offset; + + avio_skip(pb, 4); + + n = ebml_read_num(matroska, pb, 8, &num, 1); + if (n < 0) + return n; + if (num > INT_MAX) + return AVERROR_INVALIDDATA; + total = lace_size[0] = num; - for (n = 1; res == 0 && n < *laces - 1; n++) { + offset = n; + for (n = 1; n < *laces - 1; n++) { int64_t snum; int r; - r = matroska_ebmlnum_sint(matroska, data, size, &snum); - if (r < 0 || lace_size[n - 1] + snum > (uint64_t)INT_MAX) { - av_log(matroska->ctx, AV_LOG_INFO, - "EBML block data error\n"); - res = r<0 ? r : AVERROR_INVALIDDATA; - break; - } - data += r; - size -= r; + r = matroska_ebmlnum_sint(matroska, pb, &snum); + if (r < 0) + return r; + if (lace_size[n - 1] + snum > (uint64_t)INT_MAX) + return AVERROR_INVALIDDATA; + lace_size[n] = lace_size[n - 1] + snum; total += lace_size[n]; + offset += r; } - if (size <= total) { - res = AVERROR_INVALIDDATA; - break; - } + data += offset; + size -= offset; + if (size < total) + return AVERROR_INVALIDDATA; + lace_size[*laces - 1] = size - total; break; } } - *buf = data; - *lace_buf = lace_size; - *buf_size = size; + *buf = data; - return res; + return 0; } static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, @@ -3118,12 +3195,12 @@ uint8_t *data, int size, uint64_t timecode, int64_t pos) { - int a = st->codecpar->block_align; - int sps = track->audio.sub_packet_size; - int cfs = track->audio.coded_framesize; - int h = track->audio.sub_packet_h; + const int a = st->codecpar->block_align; + const int sps = track->audio.sub_packet_size; + const int cfs = track->audio.coded_framesize; + const int h = track->audio.sub_packet_h; + const int w = track->audio.frame_size; int y = track->audio.sub_packet_cnt; - int w = track->audio.frame_size; int x; if (!track->audio.pkt_cnt) { @@ -3146,7 +3223,7 @@ } memcpy(track->audio.buf + y * w, data, w); } else { - if (size < sps * w / sps || h<=0 || w%sps) { + if (size < w) { av_log(matroska->ctx, AV_LOG_ERROR, "Corrupt generic RM-style audio packet size\n"); return AVERROR_INVALIDDATA; @@ -3167,7 +3244,7 @@ while (track->audio.pkt_cnt) { int ret; - AVPacket pktl, *pkt = &pktl; + AVPacket *pkt = matroska->pkt; ret = av_new_packet(pkt, a); if (ret < 0) { @@ -3180,7 +3257,7 @@ track->audio.buf_timecode = AV_NOPTS_VALUE; pkt->pos = pos; pkt->stream_index = st->index; - ret = ff_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, 0); + ret = avpriv_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, NULL, 0); if (ret < 0) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -3191,19 +3268,21 @@ } /* reconstruct full wavpack blocks from mangled matroska ones */ -static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src, - uint8_t **pdst, int *size) +static int matroska_parse_wavpack(MatroskaTrack *track, + uint8_t **data, int *size) { uint8_t *dst = NULL; + uint8_t *src = *data; int dstlen = 0; int srclen = *size; uint32_t samples; uint16_t ver; int ret, offset = 0; - if (srclen < 12 || track->stream->codecpar->extradata_size < 2) + if (srclen < 12) return AVERROR_INVALIDDATA; + av_assert1(track->stream->codecpar->extradata_size >= 2); ver = AV_RL16(track->stream->codecpar->extradata); samples = AV_RL32(src); @@ -3263,7 +3342,7 @@ memset(dst + dstlen, 0, AV_INPUT_BUFFER_PADDING_SIZE); - *pdst = dst; + *data = dst; *size = dstlen; return 0; @@ -3273,22 +3352,22 @@ return ret; } -static int matroska_parse_prores(MatroskaTrack *track, uint8_t *src, - uint8_t **pdst, int *size) +static int matroska_parse_prores(MatroskaTrack *track, + uint8_t **data, int *size) { uint8_t *dst; int dstlen = *size + 8; - dst = av_malloc(dstlen + AV_INPUT_BUFFER_PADDING_SIZE); - if (!dst) - return AVERROR(ENOMEM); + dst = av_malloc(dstlen + AV_INPUT_BUFFER_PADDING_SIZE); + if (!dst) + return AVERROR(ENOMEM); - AV_WB32(dst, dstlen); - AV_WB32(dst + 4, MKBETAG('i', 'c', 'p', 'f')); - memcpy(dst + 8, src, dstlen - 8); - memset(dst + dstlen, 0, AV_INPUT_BUFFER_PADDING_SIZE); + AV_WB32(dst, dstlen); + AV_WB32(dst + 4, MKBETAG('i', 'c', 'p', 'f')); + memcpy(dst + 8, *data, dstlen - 8); + memset(dst + dstlen, 0, AV_INPUT_BUFFER_PADDING_SIZE); - *pdst = dst; + *data = dst; *size = dstlen; return 0; @@ -3302,7 +3381,7 @@ uint64_t duration, int64_t pos) { - AVPacket pktl, *pkt = &pktl; + AVPacket *pkt = matroska->pkt; uint8_t *id, *settings, *text, *buf; int id_len, settings_len, text_len; uint8_t *p, *q; @@ -3400,7 +3479,7 @@ pkt->duration = duration; pkt->pos = pos; - err = ff_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, 0); + err = avpriv_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, NULL, 0); if (err < 0) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -3417,46 +3496,40 @@ uint8_t *additional, uint64_t additional_id, int additional_size, int64_t discard_padding) { - MatroskaTrackEncoding *encodings = track->encodings.elem; uint8_t *pkt_data = data; - int res; - AVPacket pktl, *pkt = &pktl; - - if (encodings && !encodings->type && encodings->scope & 1) { - res = matroska_decode_buffer(&pkt_data, &pkt_size, track); - if (res < 0) - return res; - } + int res = 0; + AVPacket *pkt = matroska->pkt; if (st->codecpar->codec_id == AV_CODEC_ID_WAVPACK) { - uint8_t *wv_data; - res = matroska_parse_wavpack(track, pkt_data, &wv_data, &pkt_size); + res = matroska_parse_wavpack(track, &pkt_data, &pkt_size); if (res < 0) { av_log(matroska->ctx, AV_LOG_ERROR, "Error parsing a wavpack block.\n"); goto fail; } - if (pkt_data != data) - av_freep(&pkt_data); - pkt_data = wv_data; + if (!buf) + av_freep(&data); + buf = NULL; } if (st->codecpar->codec_id == AV_CODEC_ID_PRORES && AV_RB32(pkt_data + 4) != MKBETAG('i', 'c', 'p', 'f')) { - uint8_t *pr_data; - res = matroska_parse_prores(track, pkt_data, &pr_data, &pkt_size); + res = matroska_parse_prores(track, &pkt_data, &pkt_size); if (res < 0) { av_log(matroska->ctx, AV_LOG_ERROR, "Error parsing a prores block.\n"); goto fail; } - if (pkt_data != data) - av_freep(&pkt_data); - pkt_data = pr_data; + if (!buf) + av_freep(&data); + buf = NULL; } - av_init_packet(pkt); - if (pkt_data != data) + if (!pkt_size && !additional_size) + goto no_output; + + av_packet_unref(pkt); + if (!buf) pkt->buf = av_buffer_create(pkt_data, pkt_size + AV_INPUT_BUFFER_PADDING_SIZE, NULL, NULL, 0); else @@ -3517,7 +3590,7 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif - res = ff_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, 0); + res = avpriv_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, NULL, 0); if (res < 0) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -3525,9 +3598,10 @@ return 0; +no_output: fail: - if (pkt_data != data) - av_freep(&pkt_data); + if (!buf) + av_free(pkt_data); return res; } @@ -3539,31 +3613,37 @@ { uint64_t timecode = AV_NOPTS_VALUE; MatroskaTrack *track; + AVIOContext pb; int res = 0; AVStream *st; int16_t block_time; - uint32_t *lace_size = NULL; + uint32_t lace_size[256]; int n, flags, laces = 0; uint64_t num; - int trust_default_duration = 1; + int trust_default_duration; + + ffio_init_context(&pb, data, size, 0, NULL, NULL, NULL, NULL); - if ((n = matroska_ebmlnum_uint(matroska, data, size, &num)) < 0) { + if ((n = ebml_read_num(matroska, &pb, 8, &num, 1)) < 0) return n; - } data += n; size -= n; track = matroska_find_track_by_num(matroska, num); - if (!track || !track->stream) { - av_log(matroska->ctx, AV_LOG_INFO, - "Invalid stream %"PRIu64"\n", num); + if (!track || size < 3) return AVERROR_INVALIDDATA; - } else if (size <= 3) + + if (!(st = track->stream)) { + av_log(matroska->ctx, AV_LOG_VERBOSE, + "No stream associated to TrackNumber %"PRIu64". " + "Ignoring Block with this TrackNumber.\n", num); return 0; - st = track->stream; + } + if (st->discard >= AVDISCARD_ALL) return res; - av_assert1(block_duration != AV_NOPTS_VALUE); + if (block_duration > INT64_MAX) + block_duration = INT64_MAX; block_time = sign_extend(AV_RB16(data), 16); data += 2; @@ -3574,7 +3654,8 @@ if (cluster_time != (uint64_t) -1 && (block_time >= 0 || cluster_time >= -block_time)) { - timecode = cluster_time + block_time - track->codec_delay_in_track_tb; + uint64_t timecode_cluster_in_track_tb = (double) cluster_time / track->time_scale; + timecode = timecode_cluster_in_track_tb + block_time - track->codec_delay_in_track_tb; if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE && timecode < track->end_timecode) is_keyframe = 0; /* overlapping subtitles are not key frame */ @@ -3594,19 +3675,21 @@ return res; if (is_keyframe) matroska->skip_to_keyframe = 0; - else if (!st->skip_to_keyframe) { + else if (!st->internal->skip_to_keyframe) { av_log(matroska->ctx, AV_LOG_ERROR, "File is broken, keyframes not correctly marked!\n"); matroska->skip_to_keyframe = 0; } } - res = matroska_parse_laces(matroska, &data, &size, (flags & 0x06) >> 1, - &lace_size, &laces); - - if (res) - goto end; + res = matroska_parse_laces(matroska, &data, size, (flags & 0x06) >> 1, + &pb, lace_size, &laces); + if (res < 0) { + av_log(matroska->ctx, AV_LOG_ERROR, "Error parsing frame sizes.\n"); + return res; + } - if (track->audio.samplerate == 8000) { + trust_default_duration = track->default_duration != 0; + if (track->audio.samplerate == 8000 && trust_default_duration) { // If this is needed for more codecs, then add them here if (st->codecpar->codec_id == AV_CODEC_ID_AC3) { if (track->audio.samplerate != st->codecpar->sample_rate || !st->codecpar->frame_size) @@ -3623,49 +3706,53 @@ for (n = 0; n < laces; n++) { int64_t lace_duration = block_duration*(n+1) / laces - block_duration*n / laces; + uint8_t *out_data = data; + int out_size = lace_size[n]; - if (lace_size[n] > size) { - av_log(matroska->ctx, AV_LOG_ERROR, "Invalid packet size\n"); - break; + if (track->needs_decoding) { + res = matroska_decode_buffer(&out_data, &out_size, track); + if (res < 0) + return res; + /* Given that we are here means that out_data is no longer + * owned by buf, so set it to NULL. This depends upon + * zero-length header removal compression being ignored. */ + av_assert1(out_data != data); + buf = NULL; } - if ((st->codecpar->codec_id == AV_CODEC_ID_RA_288 || - st->codecpar->codec_id == AV_CODEC_ID_COOK || - st->codecpar->codec_id == AV_CODEC_ID_SIPR || - st->codecpar->codec_id == AV_CODEC_ID_ATRAC3) && - st->codecpar->block_align && track->audio.sub_packet_size) { - res = matroska_parse_rm_audio(matroska, track, st, data, - lace_size[n], + if (track->audio.buf) { + res = matroska_parse_rm_audio(matroska, track, st, + out_data, out_size, timecode, pos); + if (!buf) + av_free(out_data); if (res) - goto end; - + return res; } else if (st->codecpar->codec_id == AV_CODEC_ID_WEBVTT) { res = matroska_parse_webvtt(matroska, track, st, - data, lace_size[n], + out_data, out_size, timecode, lace_duration, pos); + if (!buf) + av_free(out_data); if (res) - goto end; + return res; } else { - res = matroska_parse_frame(matroska, track, st, buf, data, lace_size[n], - timecode, lace_duration, pos, - !n ? is_keyframe : 0, + res = matroska_parse_frame(matroska, track, st, buf, out_data, + out_size, timecode, lace_duration, + pos, !n ? is_keyframe : 0, additional, additional_id, additional_size, discard_padding); if (res) - goto end; + return res; } if (timecode != AV_NOPTS_VALUE) timecode = lace_duration ? timecode + lace_duration : AV_NOPTS_VALUE; data += lace_size[n]; - size -= lace_size[n]; } -end: - av_free(lace_size); - return res; + return 0; } static int matroska_parse_cluster(MatroskaDemuxContext *matroska) @@ -3694,7 +3781,7 @@ res = ebml_parse(matroska, matroska_cluster_parsing, cluster); if (res >= 0 && block->bin.size > 0) { - int is_keyframe = block->non_simple ? block->reference == INT64_MIN : -1; + int is_keyframe = block->non_simple ? block->reference.count == 0 : -1; uint8_t* additional = block->additional.size > 0 ? block->additional.data : NULL; @@ -3786,10 +3873,10 @@ /* We seek to a level 1 element, so set the appropriate status. */ matroska_reset_status(matroska, 0, st->index_entries[index].pos); if (flags & AVSEEK_FLAG_ANY) { - st->skip_to_keyframe = 0; + st->internal->skip_to_keyframe = 0; matroska->skip_to_timecode = timestamp; } else { - st->skip_to_keyframe = 1; + st->internal->skip_to_keyframe = 1; matroska->skip_to_timecode = st->index_entries[index].timestamp; } matroska->skip_to_keyframe = 1; @@ -3802,7 +3889,7 @@ matroska_reset_status(matroska, 0, -1); matroska->resync_pos = -1; matroska_clear_queue(matroska); - st->skip_to_keyframe = + st->internal->skip_to_keyframe = matroska->skip_to_keyframe = 0; matroska->done = 0; return -1; @@ -3815,6 +3902,7 @@ int n; matroska_clear_queue(matroska); + av_packet_free(&matroska->pkt); for (n = 0; n < matroska->tracks.nb_elem; n++) if (tracks[n].type == MATROSKA_TRACK_TYPE_AUDIO) @@ -4152,8 +4240,8 @@ } end += ret; } - av_dict_set(&s->streams[0]->metadata, CUE_TIMESTAMPS, buf, 0); - av_free(buf); + av_dict_set(&s->streams[0]->metadata, CUE_TIMESTAMPS, + buf, AV_DICT_DONT_STRDUP_VAL); return 0; } @@ -4169,17 +4257,20 @@ av_log(s, AV_LOG_ERROR, "Failed to read file headers\n"); return -1; } - if (!s->nb_streams) { - matroska_read_close(s); - av_log(s, AV_LOG_ERROR, "No streams found\n"); - return AVERROR_INVALIDDATA; + if (!matroska->tracks.nb_elem || !s->nb_streams) { + av_log(s, AV_LOG_ERROR, "No track found\n"); + ret = AVERROR_INVALIDDATA; + goto fail; } if (!matroska->is_live) { buf = av_asprintf("%g", matroska->duration); - if (!buf) return AVERROR(ENOMEM); - av_dict_set(&s->streams[0]->metadata, DURATION, buf, 0); - av_free(buf); + if (!buf) { + ret = AVERROR(ENOMEM); + goto fail; + } + av_dict_set(&s->streams[0]->metadata, DURATION, + buf, AV_DICT_DONT_STRDUP_VAL); // initialization range // 5 is the offset of Cluster ID. @@ -4200,7 +4291,7 @@ ret = webm_dash_manifest_cues(s, init_range); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Error parsing Cues\n"); - return ret; + goto fail; } } @@ -4210,6 +4301,9 @@ matroska->bandwidth, 0); } return 0; +fail: + matroska_read_close(s); + return ret; } static int webm_dash_manifest_read_packet(AVFormatContext *s, AVPacket *pkt) @@ -4234,7 +4328,7 @@ AVInputFormat ff_matroska_demuxer = { .name = "matroska,webm", .long_name = NULL_IF_CONFIG_SMALL("Matroska / WebM"), - .extensions = "mkv,mk3d,mka,mks", + .extensions = "mkv,mk3d,mka,mks,webm", .priv_data_size = sizeof(MatroskaDemuxContext), .read_probe = matroska_probe, .read_header = matroska_read_header, diff -Nru ffmpeg-4.2.2/libavformat/matroskaenc.c ffmpeg-4.4/libavformat/matroskaenc.c --- ffmpeg-4.2.2/libavformat/matroskaenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/matroskaenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -32,7 +32,6 @@ #include "isom.h" #include "matroska.h" #include "riff.h" -#include "subtitles.h" #include "vorbiscomment.h" #include "wv.h" @@ -50,18 +49,34 @@ #include "libavutil/random_seed.h" #include "libavutil/rational.h" #include "libavutil/samplefmt.h" -#include "libavutil/sha.h" #include "libavutil/stereo3d.h" #include "libavcodec/xiph.h" #include "libavcodec/mpeg4audio.h" -#include "libavcodec/internal.h" + +/* Level 1 elements we create a SeekHead entry for: + * Info, Tracks, Chapters, Attachments, Tags (potentially twice) and Cues */ +#define MAX_SEEKHEAD_ENTRIES 7 + +#define IS_SEEKABLE(pb, mkv) (((pb)->seekable & AVIO_SEEKABLE_NORMAL) && \ + !(mkv)->is_live) + +enum { + DEFAULT_MODE_INFER, + DEFAULT_MODE_INFER_NO_SUBS, + DEFAULT_MODE_PASSTHROUGH, +}; typedef struct ebml_master { int64_t pos; ///< absolute offset in the containing AVIOContext where the master's elements start int sizebytes; ///< how many bytes were reserved for the size } ebml_master; +typedef struct ebml_stored_master { + AVIOContext *bc; + int64_t pos; +} ebml_stored_master; + typedef struct mkv_seekhead_entry { uint32_t elementid; uint64_t segmentpos; @@ -69,98 +84,80 @@ typedef struct mkv_seekhead { int64_t filepos; - int64_t segment_offset; ///< the file offset to the beginning of the segment - int reserved_size; ///< -1 if appending to file - int max_entries; - mkv_seekhead_entry *entries; + mkv_seekhead_entry entries[MAX_SEEKHEAD_ENTRIES]; int num_entries; + int reserved_size; } mkv_seekhead; typedef struct mkv_cuepoint { uint64_t pts; int stream_idx; - int tracknum; - int64_t cluster_pos; ///< file offset of the cluster containing the block + int64_t cluster_pos; ///< offset of the cluster containing the block relative to the segment int64_t relative_pos; ///< relative offset from the position of the cluster containing the block int64_t duration; ///< duration of the block according to time base } mkv_cuepoint; typedef struct mkv_cues { - int64_t segment_offset; - mkv_cuepoint *entries; + mkv_cuepoint *entries; int num_entries; } mkv_cues; typedef struct mkv_track { int write_dts; int has_cue; + uint64_t uid; + unsigned track_num; + int track_num_size; int sample_rate; int64_t sample_rate_offset; + int64_t last_timestamp; + int64_t duration; + int64_t duration_offset; int64_t codecpriv_offset; int64_t ts_offset; } mkv_track; -typedef struct mkv_attachment { - int stream_idx; - uint32_t fileuid; -} mkv_attachment; - -typedef struct mkv_attachments { - mkv_attachment *entries; - int num_entries; -} mkv_attachments; - #define MODE_MATROSKAv2 0x01 #define MODE_WEBM 0x02 -/** Maximum number of tracks allowed in a Matroska file (with track numbers in - * range 1 to 126 (inclusive) */ -#define MAX_TRACKS 126 - typedef struct MatroskaMuxContext { - const AVClass *class; - int mode; - AVIOContext *tags_bc; - int64_t tags_pos; - AVIOContext *info_bc; - int64_t info_pos; - AVIOContext *tracks_bc; - int64_t tracks_pos; - ebml_master segment; - int64_t segment_offset; - AVIOContext *cluster_bc; - int64_t cluster_pos; ///< file offset of the current cluster - int64_t cluster_pts; - int64_t duration_offset; - int64_t duration; - mkv_seekhead *seekhead; - mkv_cues *cues; - mkv_track *tracks; - mkv_attachments *attachments; - - AVPacket cur_audio_pkt; - - int have_attachments; - int have_video; - - int reserve_cues_space; - int cluster_size_limit; - int64_t cues_pos; - int64_t cluster_time_limit; - int is_dash; - int dash_track_number; - int is_live; - int write_crc; - - uint32_t chapter_id_offset; - int wrote_chapters; + const AVClass *class; + int mode; + ebml_stored_master info; + ebml_stored_master track; + ebml_stored_master tags; + int64_t segment_offset; + AVIOContext *cluster_bc; + int64_t cluster_pos; ///< file offset of the current Cluster + int64_t cluster_pts; + int64_t duration_offset; + int64_t duration; + mkv_track *tracks; + mkv_seekhead seekhead; + mkv_cues cues; + int64_t cues_pos; + + AVPacket *cur_audio_pkt; + + unsigned nb_attachments; + int have_video; + + int wrote_chapters; + int wrote_tags; + + int reserve_cues_space; + int cluster_size_limit; + int64_t cluster_time_limit; + int write_crc; + int is_live; + + int is_dash; + int dash_track_number; + int allow_raw_vfw; + int flipped_raw_rgb; + int default_mode; - int64_t last_track_timestamp[MAX_TRACKS]; - - int64_t *stream_durations; - int64_t *stream_duration_offsets; - - int allow_raw_vfw; + uint32_t segment_uid[4]; } MatroskaMuxContext; /** 2 bytes * 7 for EBML IDs, 7 1-byte EBML lengths, 6 1-byte uint, @@ -171,19 +168,15 @@ * offset, 4 bytes for target EBML ID */ #define MAX_SEEKENTRY_SIZE 21 -/** per-cuepoint-track - 5 1-byte EBML IDs, 5 1-byte EBML sizes, 3 8-byte uint max - * and one 1-byte uint for the track number (this assumes MAX_TRACKS to be <= 255) */ -#define MAX_CUETRACKPOS_SIZE 35 - -/** per-cuepoint - 1 1-byte EBML ID, 1 1-byte EBML size, 8-byte uint max */ -#define MAX_CUEPOINT_CONTENT_SIZE(num_tracks) 10 + MAX_CUETRACKPOS_SIZE * num_tracks +/** 4 * (1-byte EBML ID, 1-byte EBML size, 8-byte uint max) */ +#define MAX_CUETRACKPOS_SIZE 40 /** Seek preroll value for opus */ #define OPUS_SEEK_PREROLL 80000000 static int ebml_id_size(uint32_t id) { - return (av_log2(id + 1) - 1) / 7 + 1; + return (av_log2(id) + 7U) / 8; } static void put_ebml_id(AVIOContext *pb, uint32_t id) @@ -206,39 +199,67 @@ } /** - * Calculate how many bytes are needed to represent a given number in EBML. + * Returns how many bytes are needed to represent a number + * as EBML variable length integer. */ static int ebml_num_size(uint64_t num) { - int bytes = 1; - while ((num + 1) >> bytes * 7) + int bytes = 0; + do { bytes++; + } while (num >>= 7); return bytes; } /** - * Write a number in EBML variable length format. + * Calculate how many bytes are needed to represent the length field + * of an EBML element whose payload has a given length. + */ +static int ebml_length_size(uint64_t length) +{ + return ebml_num_size(length + 1); +} + +/** + * Write a number as EBML variable length integer on `bytes` bytes. + * `bytes` is taken literally without checking. + */ +static void put_ebml_num(AVIOContext *pb, uint64_t num, int bytes) +{ + num |= 1ULL << bytes * 7; + for (int i = bytes - 1; i >= 0; i--) + avio_w8(pb, (uint8_t)(num >> i * 8)); +} + +/** + * Write a length as EBML variable length integer. * * @param bytes The number of bytes that need to be used to write the number. - * If zero, any number of bytes can be used. + * If zero, the minimal number of bytes will be used. */ -static void put_ebml_num(AVIOContext *pb, uint64_t num, int bytes) +static void put_ebml_length(AVIOContext *pb, uint64_t length, int bytes) { - int i, needed_bytes = ebml_num_size(num); + int needed_bytes = ebml_length_size(length); // sizes larger than this are currently undefined in EBML - av_assert0(num < (1ULL << 56) - 1); + av_assert0(length < (1ULL << 56) - 1); if (bytes == 0) - // don't care how many bytes are used, so use the min bytes = needed_bytes; - // the bytes needed to write the given size would exceed the bytes - // that we need to use, so write unknown size. This shouldn't happen. + // The bytes needed to write the given size must not exceed + // the bytes that we ought to use. av_assert0(bytes >= needed_bytes); + put_ebml_num(pb, length, bytes); +} - num |= 1ULL << bytes * 7; - for (i = bytes - 1; i >= 0; i--) - avio_w8(pb, (uint8_t)(num >> i * 8)); +/** + * Write a (random) UID with fixed size to make the output more deterministic + */ +static void put_ebml_uid(AVIOContext *pb, uint32_t elementid, uint64_t uid) +{ + put_ebml_id(pb, elementid); + put_ebml_length(pb, 8, 0); + avio_wb64(pb, uid); } static void put_ebml_uint(AVIOContext *pb, uint32_t elementid, uint64_t val) @@ -249,7 +270,7 @@ bytes++; put_ebml_id(pb, elementid); - put_ebml_num(pb, bytes, 0); + put_ebml_length(pb, bytes, 0); for (i = bytes - 1; i >= 0; i--) avio_w8(pb, (uint8_t)(val >> i * 8)); } @@ -259,10 +280,11 @@ int i, bytes = 1; uint64_t tmp = 2*(val < 0 ? val^-1 : val); - while (tmp>>=8) bytes++; + while (tmp >>= 8) + bytes++; put_ebml_id(pb, elementid); - put_ebml_num(pb, bytes, 0); + put_ebml_length(pb, bytes, 0); for (i = bytes - 1; i >= 0; i--) avio_w8(pb, (uint8_t)(val >> i * 8)); } @@ -270,7 +292,7 @@ static void put_ebml_float(AVIOContext *pb, uint32_t elementid, double val) { put_ebml_id(pb, elementid); - put_ebml_num(pb, 8, 0); + put_ebml_length(pb, 8, 0); avio_wb64(pb, av_double2int(val)); } @@ -278,7 +300,7 @@ const void *buf, int size) { put_ebml_id(pb, elementid); - put_ebml_num(pb, size, 0); + put_ebml_length(pb, size, 0); avio_write(pb, buf, size); } @@ -294,27 +316,28 @@ * * @param size The number of bytes to reserve, which must be at least 2. */ -static void put_ebml_void(AVIOContext *pb, uint64_t size) +static void put_ebml_void(AVIOContext *pb, int size) { - int64_t currentpos = avio_tell(pb); - av_assert0(size >= 2); put_ebml_id(pb, EBML_ID_VOID); // we need to subtract the length needed to store the size from the // size we need to reserve so 2 cases, we use 8 bytes to store the // size if possible, 1 byte otherwise - if (size < 10) - put_ebml_num(pb, size - 2, 0); - else - put_ebml_num(pb, size - 9, 8); - ffio_fill(pb, 0, currentpos + size - avio_tell(pb)); + if (size < 10) { + size -= 2; + put_ebml_length(pb, size, 0); + } else { + size -= 9; + put_ebml_length(pb, size, 8); + } + ffio_fill(pb, 0, size); } static ebml_master start_ebml_master(AVIOContext *pb, uint32_t elementid, uint64_t expectedsize) { - int bytes = expectedsize ? ebml_num_size(expectedsize) : 8; + int bytes = expectedsize ? ebml_length_size(expectedsize) : 8; put_ebml_id(pb, elementid); put_ebml_size_unknown(pb, bytes); @@ -327,32 +350,51 @@ if (avio_seek(pb, master.pos - master.sizebytes, SEEK_SET) < 0) return; - put_ebml_num(pb, pos - master.pos, master.sizebytes); + put_ebml_length(pb, pos - master.pos, master.sizebytes); avio_seek(pb, pos, SEEK_SET); } -static int start_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, MatroskaMuxContext *mkv, - uint32_t elementid) +static void mkv_add_seekhead_entry(MatroskaMuxContext *mkv, uint32_t elementid, + uint64_t filepos) +{ + mkv_seekhead *seekhead = &mkv->seekhead; + + av_assert1(seekhead->num_entries < MAX_SEEKHEAD_ENTRIES); + + seekhead->entries[seekhead->num_entries].elementid = elementid; + seekhead->entries[seekhead->num_entries++].segmentpos = filepos - mkv->segment_offset; +} + +static int start_ebml_master_crc32(AVIOContext **dyn_cp, MatroskaMuxContext *mkv) { int ret; - if ((ret = avio_open_dyn_buf(dyn_cp)) < 0) + if (!*dyn_cp && (ret = avio_open_dyn_buf(dyn_cp)) < 0) return ret; - put_ebml_id(pb, elementid); if (mkv->write_crc) put_ebml_void(*dyn_cp, 6); /* Reserve space for CRC32 so position/size calculations using avio_tell() take it into account */ return 0; } -static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, MatroskaMuxContext *mkv) +static int end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, + MatroskaMuxContext *mkv, uint32_t id, + int length_size, int keep_buffer, + int add_seekentry) { uint8_t *buf, crc[4]; - int size, skip = 0; + int ret, size, skip = 0; + + size = avio_get_dyn_buf(*dyn_cp, &buf); + if ((ret = (*dyn_cp)->error) < 0) + goto fail; - size = avio_close_dyn_buf(*dyn_cp, &buf); - put_ebml_num(pb, size, 0); + if (add_seekentry) + mkv_add_seekhead_entry(mkv, id, avio_tell(pb)); + + put_ebml_id(pb, id); + put_ebml_length(pb, size, length_size); if (mkv->write_crc) { skip = 6; /* Skip reserved 6-byte long void element from the dynamic buffer. */ AV_WL32(crc, av_crc(av_crc_get_table(AV_CRC_32_IEEE_LE), UINT32_MAX, buf + skip, size - skip) ^ UINT32_MAX); @@ -360,23 +402,40 @@ } avio_write(pb, buf + skip, size - skip); - av_free(buf); - *dyn_cp = NULL; +fail: + if (keep_buffer) { + ffio_reset_dyn_buf(*dyn_cp); + } else { + ffio_free_dyn_buf(dyn_cp); + } + return ret; } /** -* Complete ebml master without destroying the buffer, allowing for later updates -*/ -static void end_ebml_master_crc32_preliminary(AVIOContext *pb, AVIOContext **dyn_cp, MatroskaMuxContext *mkv, - int64_t *pos) -{ - uint8_t *buf; - int size = avio_get_dyn_buf(*dyn_cp, &buf); - - *pos = avio_tell(pb); + * Output EBML master. Keep the buffer if seekable, allowing for later updates. + * Furthermore always add a SeekHead Entry for this element. + */ +static int end_ebml_master_crc32_tentatively(AVIOContext *pb, + ebml_stored_master *elem, + MatroskaMuxContext *mkv, uint32_t id) +{ + if (IS_SEEKABLE(pb, mkv)) { + uint8_t *buf; + int size = avio_get_dyn_buf(elem->bc, &buf); + + if (elem->bc->error < 0) + return elem->bc->error; + + elem->pos = avio_tell(pb); + mkv_add_seekhead_entry(mkv, id, elem->pos); + + put_ebml_id(pb, id); + put_ebml_length(pb, size, 0); + avio_write(pb, buf, size); - put_ebml_num(pb, size, 0); - avio_write(pb, buf, size); + return 0; + } else + return end_ebml_master_crc32(pb, &elem->bc, mkv, id, 0, 0, 1); } static void put_xiph_size(AVIOContext *pb, int size) @@ -388,164 +447,91 @@ /** * Free the members allocated in the mux context. */ -static void mkv_free(MatroskaMuxContext *mkv) { - uint8_t* buf; - if (mkv->cluster_bc) { - avio_close_dyn_buf(mkv->cluster_bc, &buf); - av_free(buf); - } - if (mkv->info_bc) { - avio_close_dyn_buf(mkv->info_bc, &buf); - av_free(buf); - } - if (mkv->tracks_bc) { - avio_close_dyn_buf(mkv->tracks_bc, &buf); - av_free(buf); - } - if (mkv->tags_bc) { - avio_close_dyn_buf(mkv->tags_bc, &buf); - av_free(buf); - } - if (mkv->seekhead) { - av_freep(&mkv->seekhead->entries); - av_freep(&mkv->seekhead); - } - if (mkv->cues) { - av_freep(&mkv->cues->entries); - av_freep(&mkv->cues); - } - if (mkv->attachments) { - av_freep(&mkv->attachments->entries); - av_freep(&mkv->attachments); - } - av_freep(&mkv->tracks); - av_freep(&mkv->stream_durations); - av_freep(&mkv->stream_duration_offsets); -} - -/** - * Initialize a mkv_seekhead element to be ready to index level 1 Matroska - * elements. If a maximum number of elements is specified, enough space - * will be reserved at the current file location to write a seek head of - * that size. - * - * @param segment_offset The absolute offset to the position in the file - * where the segment begins. - * @param numelements The maximum number of elements that will be indexed - * by this seek head, 0 if unlimited. - */ -static mkv_seekhead *mkv_start_seekhead(AVIOContext *pb, int64_t segment_offset, - int numelements) +static void mkv_deinit(AVFormatContext *s) { - mkv_seekhead *new_seekhead = av_mallocz(sizeof(mkv_seekhead)); - if (!new_seekhead) - return NULL; + MatroskaMuxContext *mkv = s->priv_data; - new_seekhead->segment_offset = segment_offset; + av_packet_free(&mkv->cur_audio_pkt); - if (numelements > 0) { - new_seekhead->filepos = avio_tell(pb); - // 21 bytes max for a seek entry, 10 bytes max for the SeekHead ID - // and size, 6 bytes for a CRC32 element, and 3 bytes to guarantee - // that an EBML void element will fit afterwards - new_seekhead->reserved_size = numelements * MAX_SEEKENTRY_SIZE + 19; - new_seekhead->max_entries = numelements; - put_ebml_void(pb, new_seekhead->reserved_size); - } - return new_seekhead; + ffio_free_dyn_buf(&mkv->cluster_bc); + ffio_free_dyn_buf(&mkv->info.bc); + ffio_free_dyn_buf(&mkv->track.bc); + ffio_free_dyn_buf(&mkv->tags.bc); + + av_freep(&mkv->cues.entries); + av_freep(&mkv->tracks); } -static int mkv_add_seekhead_entry(mkv_seekhead *seekhead, uint32_t elementid, uint64_t filepos) +/** + * Initialize the SeekHead element to be ready to index level 1 Matroska + * elements. Enough space to write MAX_SEEKHEAD_ENTRIES SeekHead entries + * will be reserved at the current file location. + */ +static void mkv_start_seekhead(MatroskaMuxContext *mkv, AVIOContext *pb) { - mkv_seekhead_entry *entries = seekhead->entries; - - // don't store more elements than we reserved space for - if (seekhead->max_entries > 0 && seekhead->max_entries <= seekhead->num_entries) - return -1; - - entries = av_realloc_array(entries, seekhead->num_entries + 1, sizeof(mkv_seekhead_entry)); - if (!entries) - return AVERROR(ENOMEM); - seekhead->entries = entries; - - seekhead->entries[seekhead->num_entries].elementid = elementid; - seekhead->entries[seekhead->num_entries++].segmentpos = filepos - seekhead->segment_offset; - - return 0; + mkv->seekhead.filepos = avio_tell(pb); + // 21 bytes max for a Seek entry, 6 bytes max for the SeekHead ID + // and size, 6 bytes for a CRC32 element, and 2 bytes to guarantee + // that an EBML void element will fit afterwards + mkv->seekhead.reserved_size = MAX_SEEKHEAD_ENTRIES * MAX_SEEKENTRY_SIZE + 14; + put_ebml_void(pb, mkv->seekhead.reserved_size); } /** - * Write the seek head to the file and free it. If a maximum number of - * elements was specified to mkv_start_seekhead(), the seek head will - * be written at the location reserved for it. Otherwise, it is written - * at the current location in the file. + * Write the SeekHead to the file at the location reserved for it + * and seek to destpos afterwards. When error_on_seek_failure + * is not set, failure to seek to the position designated for the + * SeekHead is not considered an error and it is presumed that + * destpos is the current position; failure to seek to destpos + * afterwards is always an error. * - * @return The file offset where the seekhead was written, - * -1 if an error occurred. + * @return 0 on success, < 0 on error. */ -static int64_t mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv) +static int mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv, + int error_on_seek_failure, int64_t destpos) { - AVIOContext *dyn_cp; - mkv_seekhead *seekhead = mkv->seekhead; - ebml_master seekentry; - int64_t currentpos; - int i; - - currentpos = avio_tell(pb); + AVIOContext *dyn_cp = NULL; + mkv_seekhead *seekhead = &mkv->seekhead; + int64_t remaining, ret64; + int i, ret; - if (seekhead->reserved_size > 0) { - if (avio_seek(pb, seekhead->filepos, SEEK_SET) < 0) { - currentpos = -1; - goto fail; - } - } + if ((ret64 = avio_seek(pb, seekhead->filepos, SEEK_SET)) < 0) + return error_on_seek_failure ? ret64 : 0; - if (start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_SEEKHEAD) < 0) { - currentpos = -1; - goto fail; - } + ret = start_ebml_master_crc32(&dyn_cp, mkv); + if (ret < 0) + return ret; for (i = 0; i < seekhead->num_entries; i++) { mkv_seekhead_entry *entry = &seekhead->entries[i]; - - seekentry = start_ebml_master(dyn_cp, MATROSKA_ID_SEEKENTRY, MAX_SEEKENTRY_SIZE); + ebml_master seekentry = start_ebml_master(dyn_cp, MATROSKA_ID_SEEKENTRY, + MAX_SEEKENTRY_SIZE); put_ebml_id(dyn_cp, MATROSKA_ID_SEEKID); - put_ebml_num(dyn_cp, ebml_id_size(entry->elementid), 0); + put_ebml_length(dyn_cp, ebml_id_size(entry->elementid), 0); put_ebml_id(dyn_cp, entry->elementid); put_ebml_uint(dyn_cp, MATROSKA_ID_SEEKPOSITION, entry->segmentpos); end_ebml_master(dyn_cp, seekentry); } - end_ebml_master_crc32(pb, &dyn_cp, mkv); - - if (seekhead->reserved_size > 0) { - uint64_t remaining = seekhead->filepos + seekhead->reserved_size - avio_tell(pb); - put_ebml_void(pb, remaining); - avio_seek(pb, currentpos, SEEK_SET); - - currentpos = seekhead->filepos; - } -fail: - av_freep(&mkv->seekhead->entries); - av_freep(&mkv->seekhead); + ret = end_ebml_master_crc32(pb, &dyn_cp, mkv, + MATROSKA_ID_SEEKHEAD, 0, 0, 0); + if (ret < 0) + return ret; - return currentpos; -} + remaining = seekhead->filepos + seekhead->reserved_size - avio_tell(pb); + put_ebml_void(pb, remaining); -static mkv_cues *mkv_start_cues(int64_t segment_offset) -{ - mkv_cues *cues = av_mallocz(sizeof(mkv_cues)); - if (!cues) - return NULL; + if ((ret64 = avio_seek(pb, destpos, SEEK_SET)) < 0) + return ret64; - cues->segment_offset = segment_offset; - return cues; + return 0; } -static int mkv_add_cuepoint(mkv_cues *cues, int stream, int tracknum, int64_t ts, +static int mkv_add_cuepoint(MatroskaMuxContext *mkv, int stream, int64_t ts, int64_t cluster_pos, int64_t relative_pos, int64_t duration) { + mkv_cues *cues = &mkv->cues; mkv_cuepoint *entries = cues->entries; if (ts < 0) @@ -558,89 +544,80 @@ cues->entries[cues->num_entries].pts = ts; cues->entries[cues->num_entries].stream_idx = stream; - cues->entries[cues->num_entries].tracknum = tracknum; - cues->entries[cues->num_entries].cluster_pos = cluster_pos - cues->segment_offset; + 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; return 0; } -static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tracks, int num_tracks) +static int mkv_assemble_cues(AVStream **streams, AVIOContext *dyn_cp, + mkv_cues *cues, mkv_track *tracks, int num_tracks) { - MatroskaMuxContext *mkv = s->priv_data; - AVIOContext *dyn_cp, *pb = s->pb; - int64_t currentpos; - int i, j, ret; + AVIOContext *cuepoint; + int ret; - currentpos = avio_tell(pb); - ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CUES); + ret = avio_open_dyn_buf(&cuepoint); if (ret < 0) return ret; - for (i = 0; i < cues->num_entries; i++) { - ebml_master cuepoint, track_positions; - mkv_cuepoint *entry = &cues->entries[i]; + for (mkv_cuepoint *entry = cues->entries, *end = entry + cues->num_entries; + entry < end;) { uint64_t pts = entry->pts; - int ctp_nb = 0; - - // Calculate the number of entries, so we know the element size - for (j = 0; j < num_tracks; j++) - tracks[j].has_cue = 0; - for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) { - int tracknum = entry[j].stream_idx; - av_assert0(tracknum>=0 && tracknumstreams[tracknum]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) - continue; - tracks[tracknum].has_cue = 1; - ctp_nb ++; - } + uint8_t *buf; + int size; - cuepoint = start_ebml_master(dyn_cp, MATROSKA_ID_POINTENTRY, MAX_CUEPOINT_CONTENT_SIZE(ctp_nb)); - put_ebml_uint(dyn_cp, MATROSKA_ID_CUETIME, pts); + put_ebml_uint(cuepoint, MATROSKA_ID_CUETIME, pts); // put all the entries from different tracks that have the exact same // timestamp into the same CuePoint - for (j = 0; j < num_tracks; j++) + for (int j = 0; j < num_tracks; j++) tracks[j].has_cue = 0; - for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) { - int tracknum = entry[j].stream_idx; - av_assert0(tracknum>=0 && tracknumstreams[tracknum]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) + do { + ebml_master track_positions; + int idx = entry->stream_idx; + + av_assert0(idx >= 0 && idx < num_tracks); + if (tracks[idx].has_cue && streams[idx]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) continue; - tracks[tracknum].has_cue = 1; - track_positions = start_ebml_master(dyn_cp, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE); - put_ebml_uint(dyn_cp, MATROSKA_ID_CUETRACK , entry[j].tracknum ); - put_ebml_uint(dyn_cp, MATROSKA_ID_CUECLUSTERPOSITION , entry[j].cluster_pos); - put_ebml_uint(dyn_cp, MATROSKA_ID_CUERELATIVEPOSITION, entry[j].relative_pos); - if (entry[j].duration != -1) - put_ebml_uint(dyn_cp, MATROSKA_ID_CUEDURATION , entry[j].duration); - end_ebml_master(dyn_cp, track_positions); - } - i += j - 1; - end_ebml_master(dyn_cp, cuepoint); + 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_CUERELATIVEPOSITION, entry->relative_pos); + if (entry->duration != -1) + put_ebml_uint(cuepoint, MATROSKA_ID_CUEDURATION , entry->duration); + end_ebml_master(cuepoint, track_positions); + } while (++entry < end && entry->pts == pts); + size = avio_get_dyn_buf(cuepoint, &buf); + if ((ret = cuepoint->error) < 0) + break; + put_ebml_binary(dyn_cp, MATROSKA_ID_POINTENTRY, buf, size); + ffio_reset_dyn_buf(cuepoint); } - end_ebml_master_crc32(pb, &dyn_cp, mkv); + ffio_free_dyn_buf(&cuepoint); - return currentpos; + return ret; } -static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par) +static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, + const AVCodecParameters *par) { const uint8_t *header_start[3]; int header_len[3]; int first_header_size; - int j; + int err, j; if (par->codec_id == AV_CODEC_ID_VORBIS) first_header_size = 30; else first_header_size = 42; - if (avpriv_split_xiph_headers(par->extradata, par->extradata_size, - first_header_size, header_start, header_len) < 0) { + err = avpriv_split_xiph_headers(par->extradata, par->extradata_size, + first_header_size, header_start, header_len); + if (err < 0) { av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n"); - return -1; + return err; } avio_w8(pb, 2); // number packets - 1 @@ -653,17 +630,17 @@ return 0; } -static int put_wv_codecpriv(AVIOContext *pb, AVCodecParameters *par) +static int put_wv_codecpriv(AVIOContext *pb, const AVCodecParameters *par) { if (par->extradata && par->extradata_size == 2) avio_write(pb, par->extradata, 2); else - avio_wl16(pb, 0x403); // fallback to the version mentioned in matroska specs + avio_wl16(pb, 0x410); // fallback to the most recent version return 0; } -static int put_flac_codecpriv(AVFormatContext *s, - AVIOContext *pb, AVCodecParameters *par) +static int put_flac_codecpriv(AVFormatContext *s, AVIOContext *pb, + const AVCodecParameters *par) { int write_comment = (par->channel_layout && !(par->channel_layout & ~0x3ffffULL) && @@ -678,53 +655,40 @@ const char *vendor = (s->flags & AVFMT_FLAG_BITEXACT) ? "Lavf" : LIBAVFORMAT_IDENT; AVDictionary *dict = NULL; - uint8_t buf[32], *data, *p; + uint8_t buf[32]; int64_t len; snprintf(buf, sizeof(buf), "0x%"PRIx64, par->channel_layout); av_dict_set(&dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0); len = ff_vorbiscomment_length(dict, vendor, NULL, 0); - if (len >= ((1<<24) - 4)) { - av_dict_free(&dict); - return AVERROR(EINVAL); - } - - data = av_malloc(len + 4); - if (!data) { - av_dict_free(&dict); - return AVERROR(ENOMEM); - } - - data[0] = 0x84; - AV_WB24(data + 1, len); + av_assert1(len < (1 << 24) - 4); - p = data + 4; - ff_vorbiscomment_write(&p, &dict, vendor, NULL, 0); + avio_w8(pb, 0x84); + avio_wb24(pb, len); - avio_write(pb, data, len + 4); + ff_vorbiscomment_write(pb, dict, vendor, NULL, 0); - av_freep(&data); av_dict_free(&dict); } return 0; } -static int get_aac_sample_rates(AVFormatContext *s, uint8_t *extradata, int extradata_size, +static int get_aac_sample_rates(AVFormatContext *s, MatroskaMuxContext *mkv, + const uint8_t *extradata, int extradata_size, int *sample_rate, int *output_sample_rate) { MPEG4AudioConfig mp4ac; int ret; - ret = avpriv_mpeg4audio_get_config(&mp4ac, extradata, - extradata_size * 8, 1); + ret = avpriv_mpeg4audio_get_config2(&mp4ac, extradata, extradata_size, 1, s); /* Don't abort if the failure is because of missing extradata. Assume in that * case a bitstream filter will provide the muxer with the extradata in the * first packet. * Abort however if s->pb is not seekable, as we would not be able to seek back * to write the sample rate elements once the extradata shows up, anyway. */ - if (ret < 0 && (extradata_size || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL))) { + if (ret < 0 && (extradata_size || !IS_SEEKABLE(s->pb, mkv))) { av_log(s, AV_LOG_ERROR, "Error parsing AAC extradata, unable to determine samplerate.\n"); return AVERROR(EINVAL); @@ -745,7 +709,7 @@ } static int mkv_write_native_codecprivate(AVFormatContext *s, AVIOContext *pb, - AVCodecParameters *par, + const AVCodecParameters *par, AVIOContext *dyn_cp) { switch (par->codec_id) { @@ -760,9 +724,8 @@ return ff_isom_write_avcc(dyn_cp, par->extradata, par->extradata_size); case AV_CODEC_ID_HEVC: - ff_isom_write_hvcc(dyn_cp, par->extradata, - par->extradata_size, 0); - return 0; + 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, @@ -802,6 +765,7 @@ int native_id, int qt_id) { AVIOContext *dyn_cp; + MatroskaMuxContext *mkv = s->priv_data; uint8_t *codecpriv; int ret, codecpriv_size; @@ -840,7 +804,7 @@ ret = AVERROR(EINVAL); } - ff_put_bmp_header(dyn_cp, par, 0, 0); + ff_put_bmp_header(dyn_cp, par, 0, 0, mkv->flipped_raw_rgb); } } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) { unsigned int tag; @@ -856,24 +820,28 @@ ff_put_wav_header(s, dyn_cp, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX); } - codecpriv_size = avio_close_dyn_buf(dyn_cp, &codecpriv); - if (codecpriv_size) - put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv, - codecpriv_size); - av_free(codecpriv); + if (ret >= 0) { + codecpriv_size = avio_get_dyn_buf(dyn_cp, &codecpriv); + if ((ret = dyn_cp->error) >= 0 && codecpriv_size) + put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv, + codecpriv_size); + } + ffio_free_dyn_buf(&dyn_cp); return ret; } -static int mkv_write_video_color(AVIOContext *pb, AVCodecParameters *par, AVStream *st) { - AVIOContext *dyn_cp; - uint8_t *colorinfo_ptr; - int side_data_size = 0; - int ret, colorinfo_size; - const uint8_t *side_data; +static void mkv_write_video_color(AVIOContext *pb, const AVStream *st, + const AVCodecParameters *par) +{ + /* 18 Elements with two bytes ID, one byte length field, 8 bytes payload + * a master element with two bytes ID and one byte length field + * plus another byte to stay clear of the end. */ + uint8_t colour[(2 + 1 + 8) * 18 + (2 + 1) + 1]; + AVIOContext buf, *dyn_cp = &buf; + int colorinfo_size; + const void *side_data; - ret = avio_open_dyn_buf(&dyn_cp); - if (ret < 0) - return ret; + ffio_init_context(dyn_cp, colour, sizeof(colour), 1, NULL, NULL, NULL, NULL); if (par->color_trc != AVCOL_TRC_UNSPECIFIED && par->color_trc < AVCOL_TRC_NB) { @@ -902,21 +870,19 @@ } side_data = av_stream_get_side_data(st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL, - &side_data_size); - if (side_data_size) { - const AVContentLightMetadata *metadata = - (const AVContentLightMetadata*)side_data; + NULL); + if (side_data) { + const AVContentLightMetadata *metadata = side_data; put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORMAXCLL, metadata->MaxCLL); put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORMAXFALL, metadata->MaxFALL); } side_data = av_stream_get_side_data(st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, - &side_data_size); - if (side_data_size == sizeof(AVMasteringDisplayMetadata)) { + NULL); + if (side_data) { ebml_master meta_element = start_ebml_master( - dyn_cp, MATROSKA_ID_VIDEOCOLORMASTERINGMETA, 0); - const AVMasteringDisplayMetadata *metadata = - (const AVMasteringDisplayMetadata*)side_data; + dyn_cp, MATROSKA_ID_VIDEOCOLORMASTERINGMETA, 10 * (2 + 1 + 8)); + const AVMasteringDisplayMetadata *metadata = side_data; if (metadata->has_primaries) { put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_RX, av_q2d(metadata->display_primaries[0][0])); @@ -944,91 +910,76 @@ end_ebml_master(dyn_cp, meta_element); } - colorinfo_size = avio_close_dyn_buf(dyn_cp, &colorinfo_ptr); - if (colorinfo_size) { - ebml_master colorinfo = start_ebml_master(pb, MATROSKA_ID_VIDEOCOLOR, colorinfo_size); - avio_write(pb, colorinfo_ptr, colorinfo_size); - end_ebml_master(pb, colorinfo); - } - av_free(colorinfo_ptr); - return 0; + colorinfo_size = avio_tell(dyn_cp); + if (colorinfo_size) + put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLOR, colour, colorinfo_size); } -static int mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, - AVStream *st) +static void mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, + const AVStream *st) { - AVIOContext b; - AVIOContext *dyn_cp; - int side_data_size = 0; - int ret, projection_size; - uint8_t *projection_ptr; + ebml_master projection; uint8_t private[20]; const AVSphericalMapping *spherical = (const AVSphericalMapping *)av_stream_get_side_data(st, AV_PKT_DATA_SPHERICAL, - &side_data_size); + NULL); - if (!side_data_size) - return 0; + if (!spherical) + return; - ret = avio_open_dyn_buf(&dyn_cp); - if (ret < 0) - return ret; + if (spherical->projection != AV_SPHERICAL_EQUIRECTANGULAR && + spherical->projection != AV_SPHERICAL_EQUIRECTANGULAR_TILE && + spherical->projection != AV_SPHERICAL_CUBEMAP) { + av_log(s, AV_LOG_WARNING, "Unknown projection type\n"); + return; + } + + // Maximally 4 8-byte elements with id-length 2 + 1 byte length field + // and the private data of the AV_SPHERICAL_EQUIRECTANGULAR_TILE case + projection = start_ebml_master(pb, MATROSKA_ID_VIDEOPROJECTION, + 4 * (2 + 1 + 8) + (2 + 1 + 20)); switch (spherical->projection) { case AV_SPHERICAL_EQUIRECTANGULAR: - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONTYPE, + put_ebml_uint(pb, MATROSKA_ID_VIDEOPROJECTIONTYPE, MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR); break; case AV_SPHERICAL_EQUIRECTANGULAR_TILE: - ffio_init_context(&b, private, 20, 1, NULL, NULL, NULL, NULL); - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONTYPE, + put_ebml_uint(pb, MATROSKA_ID_VIDEOPROJECTIONTYPE, MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR); - avio_wb32(&b, 0); // version + flags - avio_wb32(&b, spherical->bound_top); - avio_wb32(&b, spherical->bound_bottom); - avio_wb32(&b, spherical->bound_left); - avio_wb32(&b, spherical->bound_right); - put_ebml_binary(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONPRIVATE, - private, avio_tell(&b)); + AV_WB32(private, 0); // version + flags + AV_WB32(private + 4, spherical->bound_top); + AV_WB32(private + 8, spherical->bound_bottom); + AV_WB32(private + 12, spherical->bound_left); + AV_WB32(private + 16, spherical->bound_right); + put_ebml_binary(pb, MATROSKA_ID_VIDEOPROJECTIONPRIVATE, + private, 20); break; case AV_SPHERICAL_CUBEMAP: - ffio_init_context(&b, private, 12, 1, NULL, NULL, NULL, NULL); - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONTYPE, + put_ebml_uint(pb, MATROSKA_ID_VIDEOPROJECTIONTYPE, MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP); - avio_wb32(&b, 0); // version + flags - avio_wb32(&b, 0); // layout - avio_wb32(&b, spherical->padding); - put_ebml_binary(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONPRIVATE, - private, avio_tell(&b)); + AV_WB32(private, 0); // version + flags + AV_WB32(private + 4, 0); // layout + AV_WB32(private + 8, spherical->padding); + put_ebml_binary(pb, MATROSKA_ID_VIDEOPROJECTIONPRIVATE, + private, 12); break; default: - av_log(s, AV_LOG_WARNING, "Unknown projection type\n"); - goto end; + av_assert0(0); } if (spherical->yaw) - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, + put_ebml_float(pb, MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, (double) spherical->yaw / (1 << 16)); if (spherical->pitch) - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, + put_ebml_float(pb, MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, (double) spherical->pitch / (1 << 16)); if (spherical->roll) - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, + put_ebml_float(pb, MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, (double) spherical->roll / (1 << 16)); -end: - projection_size = avio_close_dyn_buf(dyn_cp, &projection_ptr); - if (projection_size) { - ebml_master projection = start_ebml_master(pb, - MATROSKA_ID_VIDEOPROJECTION, - projection_size); - avio_write(pb, projection_ptr, projection_size); - end_ebml_master(pb, projection); - } - av_freep(&projection_ptr); - - return 0; + end_ebml_master(pb, projection); } static void mkv_write_field_order(AVIOContext *pb, int mode, @@ -1073,10 +1024,9 @@ static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, AVStream *st, int mode, int *h_width, int *h_height) { - int i; - int ret = 0; - AVDictionaryEntry *tag; + const AVDictionaryEntry *tag; MatroskaVideoStereoModeType format = MATROSKA_VIDEO_STEREOMODE_TYPE_NB; + const AVStereo3D *stereo; *h_width = 1; *h_height = 1; @@ -1085,7 +1035,7 @@ (tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) { int stereo_mode = atoi(tag->value); - for (i=0; ivalue, ff_matroska_video_stereo_mode[i])){ stereo_mode = i; break; @@ -1099,57 +1049,52 @@ } } - // iterate to find the stereo3d side data - for (i = 0; i < st->nb_side_data; i++) { - AVPacketSideData sd = st->side_data[i]; - if (sd.type == AV_PKT_DATA_STEREO3D) { - AVStereo3D *stereo = (AVStereo3D *)sd.data; - - switch (stereo->type) { - case AV_STEREO3D_2D: - format = MATROSKA_VIDEO_STEREOMODE_TYPE_MONO; - break; - case AV_STEREO3D_SIDEBYSIDE: - format = (stereo->flags & AV_STEREO3D_FLAG_INVERT) - ? MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT - : MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT; - *h_width = 2; - break; - case AV_STEREO3D_TOPBOTTOM: - format = MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM; - if (stereo->flags & AV_STEREO3D_FLAG_INVERT) - format--; - *h_height = 2; - break; - case AV_STEREO3D_CHECKERBOARD: - format = MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR; - if (stereo->flags & AV_STEREO3D_FLAG_INVERT) - format--; - break; - case AV_STEREO3D_LINES: - format = MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR; - if (stereo->flags & AV_STEREO3D_FLAG_INVERT) - format--; - *h_height = 2; - break; - case AV_STEREO3D_COLUMNS: - format = MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR; - if (stereo->flags & AV_STEREO3D_FLAG_INVERT) - format--; - *h_width = 2; - break; - case AV_STEREO3D_FRAMESEQUENCE: - format = MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR; - if (stereo->flags & AV_STEREO3D_FLAG_INVERT) - format++; - break; - } + stereo = (const AVStereo3D*)av_stream_get_side_data(st, AV_PKT_DATA_STEREO3D, + NULL); + if (stereo) { + switch (stereo->type) { + case AV_STEREO3D_2D: + format = MATROSKA_VIDEO_STEREOMODE_TYPE_MONO; + break; + case AV_STEREO3D_SIDEBYSIDE: + format = (stereo->flags & AV_STEREO3D_FLAG_INVERT) + ? MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT + : MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT; + *h_width = 2; + break; + case AV_STEREO3D_TOPBOTTOM: + format = MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM; + if (stereo->flags & AV_STEREO3D_FLAG_INVERT) + format--; + *h_height = 2; + break; + case AV_STEREO3D_CHECKERBOARD: + format = MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR; + if (stereo->flags & AV_STEREO3D_FLAG_INVERT) + format--; + break; + case AV_STEREO3D_LINES: + format = MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR; + if (stereo->flags & AV_STEREO3D_FLAG_INVERT) + format--; + *h_height = 2; + break; + case AV_STEREO3D_COLUMNS: + format = MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR; + if (stereo->flags & AV_STEREO3D_FLAG_INVERT) + format--; + *h_width = 2; + break; + case AV_STEREO3D_FRAMESEQUENCE: + format = MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR; + if (stereo->flags & AV_STEREO3D_FLAG_INVERT) + format++; break; } } if (format == MATROSKA_VIDEO_STEREOMODE_TYPE_NB) - return ret; + return 0; // if webm, do not write unsupported modes if ((mode == MODE_WEBM && @@ -1158,75 +1103,56 @@ || format >= MATROSKA_VIDEO_STEREOMODE_TYPE_NB) { av_log(s, AV_LOG_ERROR, "The specified stereo mode is not valid.\n"); - format = MATROSKA_VIDEO_STEREOMODE_TYPE_NB; return AVERROR(EINVAL); } // write StereoMode if format is valid put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, format); - return ret; + return 0; } static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, - int i, AVIOContext *pb, int default_stream_exists) + AVStream *st, mkv_track *track, AVIOContext *pb, + int is_default) { - AVStream *st = s->streams[i]; AVCodecParameters *par = st->codecpar; - ebml_master subinfo, track; + ebml_master subinfo, track_master; int native_id = 0; int qt_id = 0; - int bit_depth = av_get_bits_per_sample(par->codec_id); + int bit_depth; int sample_rate = par->sample_rate; int output_sample_rate = 0; int display_width_div = 1; int display_height_div = 1; int j, ret; - AVDictionaryEntry *tag; + const AVDictionaryEntry *tag; - if (par->codec_type == AVMEDIA_TYPE_ATTACHMENT) { - mkv->have_attachments = 1; + if (par->codec_type == AVMEDIA_TYPE_ATTACHMENT) return 0; - } - - if (par->codec_type == AVMEDIA_TYPE_AUDIO) { - if (!bit_depth && par->codec_id != AV_CODEC_ID_ADPCM_G726) { - if (par->bits_per_raw_sample) - bit_depth = par->bits_per_raw_sample; - else - bit_depth = av_get_bytes_per_sample(par->format) << 3; - } - if (!bit_depth) - bit_depth = par->bits_per_coded_sample; - } if (par->codec_id == AV_CODEC_ID_AAC) { - ret = get_aac_sample_rates(s, par->extradata, par->extradata_size, &sample_rate, - &output_sample_rate); + ret = get_aac_sample_rates(s, mkv, par->extradata, par->extradata_size, + &sample_rate, &output_sample_rate); if (ret < 0) return ret; } - track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0); - put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER, - mkv->is_dash ? mkv->dash_track_number : i + 1); - put_ebml_uint (pb, MATROSKA_ID_TRACKUID, - mkv->is_dash ? mkv->dash_track_number : i + 1); - put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet) + 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); + put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGLACING, 0); // no lacing (yet) if ((tag = av_dict_get(st->metadata, "title", NULL, 0))) put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value); tag = av_dict_get(st->metadata, "language", NULL, 0); - if (mkv->mode != MODE_WEBM || par->codec_id != AV_CODEC_ID_WEBVTT) { - put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag && tag->value ? tag->value:"und"); - } else if (tag && tag->value) { - put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag->value); - } + put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, + tag && tag->value[0] ? tag->value : "und"); // The default value for TRACKFLAGDEFAULT is 1, so add element // if we need to clear it. - if (default_stream_exists && !(st->disposition & AV_DISPOSITION_DEFAULT)) - put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, !!(st->disposition & AV_DISPOSITION_DEFAULT)); + if (!is_default) + put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, 0); if (st->disposition & AV_DISPOSITION_FORCED) put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGFORCED, 1); @@ -1265,6 +1191,18 @@ put_ebml_string(pb, MATROSKA_ID_CODECID, codec_id); } else { + if (st->disposition & AV_DISPOSITION_COMMENT) + put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGCOMMENTARY, 1); + if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED) + put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGHEARINGIMPAIRED, 1); + if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED) + put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGVISUALIMPAIRED, 1); + if (st->disposition & (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB) && + (st->disposition & (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB)) + != (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB)) + put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGORIGINAL, + !!(st->disposition & AV_DISPOSITION_ORIGINAL)); + // look for a codec ID string specific to mkv to use, // if none are found, use AVI codes if (par->codec_id != AV_CODEC_ID_RAWVIDEO || par->codec_tag) { @@ -1286,24 +1224,6 @@ } } - if (par->codec_type == AVMEDIA_TYPE_AUDIO && par->initial_padding && par->codec_id == AV_CODEC_ID_OPUS) { - int64_t codecdelay = av_rescale_q(par->initial_padding, - (AVRational){ 1, 48000 }, - (AVRational){ 1, 1000000000 }); - if (codecdelay < 0) { - av_log(s, AV_LOG_ERROR, "Initial padding is invalid\n"); - return AVERROR(EINVAL); - } -// mkv->tracks[i].ts_offset = av_rescale_q(par->initial_padding, -// (AVRational){ 1, par->sample_rate }, -// st->time_base); - - put_ebml_uint(pb, MATROSKA_ID_CODECDELAY, codecdelay); - } - if (par->codec_id == AV_CODEC_ID_OPUS) { - put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL); - } - switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: mkv->have_video = 1; @@ -1312,6 +1232,9 @@ if( st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0 && av_cmp_q(av_inv_q(st->avg_frame_rate), st->time_base) > 0) put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1000000000LL * st->avg_frame_rate.den / st->avg_frame_rate.num); + else if( st->r_frame_rate.num > 0 && st->r_frame_rate.den > 0 + && 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 && ff_codec_get_tag(ff_codec_movvideo_tags, par->codec_id) && @@ -1326,7 +1249,7 @@ else if (!native_id) { // if there is no mkv-specific codec ID, use VFW mode put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC"); - mkv->tracks[i].write_dts = 1; + track->write_dts = 1; s->internal->avoid_negative_ts_use_pts = 0; } @@ -1384,29 +1307,53 @@ uint32_t color_space = av_le2ne32(par->codec_tag); put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space)); } - ret = mkv_write_video_color(pb, par, st); - if (ret < 0) - return ret; - ret = mkv_write_video_projection(s, pb, st); - if (ret < 0) - return ret; + mkv_write_video_color(pb, st, par); + mkv_write_video_projection(s, pb, st); + end_ebml_master(pb, subinfo); break; case AVMEDIA_TYPE_AUDIO: + if (par->initial_padding && par->codec_id == AV_CODEC_ID_OPUS) { + int64_t codecdelay = av_rescale_q(par->initial_padding, + (AVRational){ 1, 48000 }, + (AVRational){ 1, 1000000000 }); + if (codecdelay < 0) { + av_log(s, AV_LOG_ERROR, "Initial padding is invalid\n"); + return AVERROR(EINVAL); + } +// track->ts_offset = av_rescale_q(par->initial_padding, +// (AVRational){ 1, par->sample_rate }, +// st->time_base); + + put_ebml_uint(pb, MATROSKA_ID_CODECDELAY, codecdelay); + } + if (par->codec_id == AV_CODEC_ID_OPUS) + put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL); + put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO); if (!native_id) // no mkv-specific ID, use ACM mode put_ebml_string(pb, MATROSKA_ID_CODECID, "A_MS/ACM"); - subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 0); + subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 6 + 4 * 9); put_ebml_uint (pb, MATROSKA_ID_AUDIOCHANNELS , par->channels); - mkv->tracks[i].sample_rate_offset = avio_tell(pb); + track->sample_rate_offset = avio_tell(pb); put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate); if (output_sample_rate) put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); + + bit_depth = av_get_bits_per_sample(par->codec_id); + if (!bit_depth && par->codec_id != AV_CODEC_ID_ADPCM_G726) { + if (par->bits_per_raw_sample) + bit_depth = par->bits_per_raw_sample; + else + bit_depth = av_get_bytes_per_sample(par->format) << 3; + } + if (!bit_depth) + bit_depth = par->bits_per_coded_sample; if (bit_depth) put_ebml_uint(pb, MATROSKA_ID_AUDIOBITDEPTH, bit_depth); end_ebml_master(pb, subinfo); @@ -1417,6 +1364,8 @@ 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) + put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGTEXTDESCRIPTIONS, 1); if (mkv->mode != MODE_WEBM || par->codec_id != AV_CODEC_ID_WEBVTT) native_id = MATROSKA_TRACK_TYPE_SUBTITLE; @@ -1429,13 +1378,13 @@ } if (mkv->mode != MODE_WEBM || par->codec_id != AV_CODEC_ID_WEBVTT) { - mkv->tracks[i].codecpriv_offset = avio_tell(pb); + track->codecpriv_offset = avio_tell(pb); ret = mkv_write_codecprivate(s, pb, par, native_id, qt_id); if (ret < 0) return ret; } - end_ebml_master(pb, track); + end_ebml_master(pb, track_master); return 0; } @@ -1444,113 +1393,81 @@ { MatroskaMuxContext *mkv = s->priv_data; AVIOContext *pb = s->pb; - int i, ret, default_stream_exists = 0; + int i, ret, video_default_idx, audio_default_idx, subtitle_default_idx; - ret = mkv_add_seekhead_entry(mkv->seekhead, MATROSKA_ID_TRACKS, avio_tell(pb)); - if (ret < 0) - return ret; + if (mkv->nb_attachments == s->nb_streams) + return 0; - ret = start_ebml_master_crc32(pb, &mkv->tracks_bc, mkv, MATROSKA_ID_TRACKS); + ret = start_ebml_master_crc32(&mkv->track.bc, mkv); if (ret < 0) return ret; - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - default_stream_exists |= st->disposition & AV_DISPOSITION_DEFAULT; + if (mkv->default_mode != DEFAULT_MODE_PASSTHROUGH) { + int video_idx, audio_idx, subtitle_idx; + + video_idx = video_default_idx = + audio_idx = audio_default_idx = + subtitle_idx = subtitle_default_idx = -1; + + for (i = s->nb_streams - 1; i >= 0; i--) { + AVStream *st = s->streams[i]; + + switch (st->codecpar->codec_type) { +#define CASE(type, variable) \ + case AVMEDIA_TYPE_ ## type: \ + variable ## _idx = i; \ + if (st->disposition & AV_DISPOSITION_DEFAULT) \ + variable ## _default_idx = i; \ + break; + CASE(VIDEO, video) + CASE(AUDIO, audio) + CASE(SUBTITLE, subtitle) +#undef CASE + } + } + + video_default_idx = FFMAX(video_default_idx, video_idx); + audio_default_idx = FFMAX(audio_default_idx, audio_idx); + if (mkv->default_mode != DEFAULT_MODE_INFER_NO_SUBS) + subtitle_default_idx = FFMAX(subtitle_default_idx, subtitle_idx); } for (i = 0; i < s->nb_streams; i++) { - ret = mkv_write_track(s, mkv, i, mkv->tracks_bc, default_stream_exists); + AVStream *st = s->streams[i]; + int is_default = mkv->default_mode == DEFAULT_MODE_PASSTHROUGH ? + st->disposition & AV_DISPOSITION_DEFAULT : + i == video_default_idx || i == audio_default_idx || + i == subtitle_default_idx; + ret = mkv_write_track(s, mkv, st, &mkv->tracks[i], + mkv->track.bc, is_default); if (ret < 0) return ret; } - if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) - end_ebml_master_crc32_preliminary(pb, &mkv->tracks_bc, mkv, &mkv->tracks_pos); - else - end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv); - - return 0; + return end_ebml_master_crc32_tentatively(pb, &mkv->track, mkv, + MATROSKA_ID_TRACKS); } -static int mkv_write_chapters(AVFormatContext *s) +static int mkv_write_simpletag(AVIOContext *pb, const AVDictionaryEntry *t) { - MatroskaMuxContext *mkv = s->priv_data; - AVIOContext *dyn_cp, *pb = s->pb; - ebml_master editionentry; - AVRational scale = {1, 1E9}; - int i, ret; - - if (!s->nb_chapters || mkv->wrote_chapters) - return 0; + uint8_t *key = av_strdup(t->key); + uint8_t *p = key; + const uint8_t *lang = NULL; + ebml_master tag; - ret = mkv_add_seekhead_entry(mkv->seekhead, MATROSKA_ID_CHAPTERS, avio_tell(pb)); - if (ret < 0) return ret; + if (!key) + return AVERROR(ENOMEM); - ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CHAPTERS); - if (ret < 0) return ret; + if ((p = strrchr(p, '-')) && + (lang = ff_convert_lang_to(p + 1, AV_LANG_ISO639_2_BIBL))) + *p = 0; - editionentry = start_ebml_master(dyn_cp, MATROSKA_ID_EDITIONENTRY, 0); - if (mkv->mode != MODE_WEBM) { - put_ebml_uint(dyn_cp, MATROSKA_ID_EDITIONFLAGDEFAULT, 1); - put_ebml_uint(dyn_cp, MATROSKA_ID_EDITIONFLAGHIDDEN , 0); - } - for (i = 0; i < s->nb_chapters; i++) { - ebml_master chapteratom, chapterdisplay; - AVChapter *c = s->chapters[i]; - int64_t chapterstart = av_rescale_q(c->start, c->time_base, scale); - int64_t chapterend = av_rescale_q(c->end, c->time_base, scale); - AVDictionaryEntry *t = NULL; - if (chapterstart < 0 || chapterstart > chapterend || chapterend < 0) { - av_log(s, AV_LOG_ERROR, - "Invalid chapter start (%"PRId64") or end (%"PRId64").\n", - chapterstart, chapterend); - return AVERROR_INVALIDDATA; - } - - chapteratom = start_ebml_master(dyn_cp, MATROSKA_ID_CHAPTERATOM, 0); - put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID, c->id + mkv->chapter_id_offset); - put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMESTART, chapterstart); - put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMEEND, chapterend); - if (mkv->mode != MODE_WEBM) { - put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERFLAGHIDDEN , 0); - put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERFLAGENABLED, 1); - } - if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { - chapterdisplay = start_ebml_master(dyn_cp, MATROSKA_ID_CHAPTERDISPLAY, 0); - put_ebml_string(dyn_cp, MATROSKA_ID_CHAPSTRING, t->value); - put_ebml_string(dyn_cp, MATROSKA_ID_CHAPLANG , "und"); - end_ebml_master(dyn_cp, chapterdisplay); - } - end_ebml_master(dyn_cp, chapteratom); - } - end_ebml_master(dyn_cp, editionentry); - end_ebml_master_crc32(pb, &dyn_cp, mkv); - - mkv->wrote_chapters = 1; - return 0; -} - -static int mkv_write_simpletag(AVIOContext *pb, AVDictionaryEntry *t) -{ - uint8_t *key = av_strdup(t->key); - uint8_t *p = key; - const uint8_t *lang = NULL; - ebml_master tag; - - if (!key) - return AVERROR(ENOMEM); - - if ((p = strrchr(p, '-')) && - (lang = ff_convert_lang_to(p + 1, AV_LANG_ISO639_2_BIBL))) - *p = 0; - - p = key; - while (*p) { - if (*p == ' ') - *p = '_'; - else if (*p >= 'a' && *p <= 'z') - *p -= 'a' - 'A'; - p++; + p = key; + while (*p) { + if (*p == ' ') + *p = '_'; + else if (*p >= 'a' && *p <= 'z') + *p -= 'a' - 'A'; + p++; } tag = start_ebml_master(pb, MATROSKA_ID_SIMPLETAG, 0); @@ -1564,27 +1481,23 @@ return 0; } -static int mkv_write_tag_targets(AVFormatContext *s, uint32_t elementid, - unsigned int uid, ebml_master *tag) +static int mkv_write_tag_targets(MatroskaMuxContext *mkv, AVIOContext **pb, + ebml_master *tag, uint32_t elementid, uint64_t uid) { - AVIOContext *pb; - MatroskaMuxContext *mkv = s->priv_data; ebml_master targets; int ret; - if (!mkv->tags_bc) { - ret = mkv_add_seekhead_entry(mkv->seekhead, MATROSKA_ID_TAGS, avio_tell(s->pb)); - if (ret < 0) return ret; - - start_ebml_master_crc32(s->pb, &mkv->tags_bc, mkv, MATROSKA_ID_TAGS); + if (!*pb) { + ret = start_ebml_master_crc32(pb, mkv); + if (ret < 0) + return ret; } - pb = mkv->tags_bc; - *tag = start_ebml_master(pb, MATROSKA_ID_TAG, 0); - targets = start_ebml_master(pb, MATROSKA_ID_TAGTARGETS, 0); + *tag = start_ebml_master(*pb, MATROSKA_ID_TAG, 0); + targets = start_ebml_master(*pb, MATROSKA_ID_TAGTARGETS, 4 + 1 + 8); if (elementid) - put_ebml_uint(pb, elementid, uid); - end_ebml_master(pb, targets); + put_ebml_uid(*pb, elementid, uid); + end_ebml_master(*pb, targets); return 0; } @@ -1602,33 +1515,35 @@ av_strcasecmp(name, "mimetype"))); } -static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, uint32_t elementid, - unsigned int uid) +static int mkv_write_tag(MatroskaMuxContext *mkv, const AVDictionary *m, + AVIOContext **pb, ebml_master *tag, + uint32_t elementid, uint64_t uid) { - MatroskaMuxContext *mkv = s->priv_data; - ebml_master tag; + const AVDictionaryEntry *t = NULL; + ebml_master tag2; int ret; - AVDictionaryEntry *t = NULL; - ret = mkv_write_tag_targets(s, elementid, uid, &tag); + ret = mkv_write_tag_targets(mkv, pb, tag ? tag : &tag2, elementid, uid); if (ret < 0) return ret; while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) { if (mkv_check_tag_name(t->key, elementid)) { - ret = mkv_write_simpletag(mkv->tags_bc, t); + ret = mkv_write_simpletag(*pb, t); if (ret < 0) return ret; } } - end_ebml_master(mkv->tags_bc, tag); + if (!tag) + end_ebml_master(*pb, tag2); + return 0; } -static int mkv_check_tag(AVDictionary *m, uint32_t elementid) +static int mkv_check_tag(const AVDictionary *m, uint32_t elementid) { - AVDictionaryEntry *t = NULL; + const AVDictionaryEntry *t = NULL; while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) if (mkv_check_tag_name(t->key, elementid)) @@ -1640,127 +1555,213 @@ static int mkv_write_tags(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; + ebml_master tag, *tagp = IS_SEEKABLE(s->pb, mkv) ? &tag : NULL; int i, ret; + mkv->wrote_tags = 1; + ff_metadata_conv_ctx(s, ff_mkv_metadata_conv, NULL); if (mkv_check_tag(s->metadata, 0)) { - ret = mkv_write_tag(s, s->metadata, 0, 0); - if (ret < 0) return ret; + ret = mkv_write_tag(mkv, s->metadata, &mkv->tags.bc, NULL, 0, 0); + if (ret < 0) + return ret; } for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; + const AVStream *st = s->streams[i]; + mkv_track *track = &mkv->tracks[i]; if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) continue; - if (!mkv_check_tag(st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID)) + if (!tagp && !mkv_check_tag(st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID)) continue; - ret = mkv_write_tag(s, st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID, i + 1); - if (ret < 0) return ret; - } - - if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) { - for (i = 0; i < s->nb_streams; i++) { - AVIOContext *pb; - AVStream *st = s->streams[i]; - ebml_master tag_target; - ebml_master tag; - - if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) - continue; + ret = mkv_write_tag(mkv, st->metadata, &mkv->tags.bc, tagp, + MATROSKA_ID_TAGTARGETS_TRACKUID, track->uid); + if (ret < 0) + return ret; - mkv_write_tag_targets(s, MATROSKA_ID_TAGTARGETS_TRACKUID, i + 1, &tag_target); - pb = mkv->tags_bc; + if (tagp) { + AVIOContext *pb = mkv->tags.bc; + ebml_master simpletag; - tag = start_ebml_master(pb, MATROSKA_ID_SIMPLETAG, 0); + simpletag = start_ebml_master(pb, MATROSKA_ID_SIMPLETAG, + 2 + 1 + 8 + 23); put_ebml_string(pb, MATROSKA_ID_TAGNAME, "DURATION"); - mkv->stream_duration_offsets[i] = avio_tell(pb); + track->duration_offset = avio_tell(pb); // Reserve space to write duration as a 20-byte string. // 2 (ebml id) + 1 (data size) + 20 (data) put_ebml_void(pb, 23); + end_ebml_master(pb, simpletag); end_ebml_master(pb, tag); - end_ebml_master(pb, tag_target); } } - if (mkv->mode != MODE_WEBM) { - for (i = 0; i < s->nb_chapters; i++) { - AVChapter *ch = s->chapters[i]; + if (mkv->nb_attachments && mkv->mode != MODE_WEBM) { + for (i = 0; i < s->nb_streams; i++) { + const mkv_track *track = &mkv->tracks[i]; + const AVStream *st = s->streams[i]; + + if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT) + continue; - if (!mkv_check_tag(ch->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID)) + if (!mkv_check_tag(st->metadata, MATROSKA_ID_TAGTARGETS_ATTACHUID)) continue; - ret = mkv_write_tag(s, ch->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID, ch->id + mkv->chapter_id_offset); + ret = mkv_write_tag(mkv, st->metadata, &mkv->tags.bc, NULL, + MATROSKA_ID_TAGTARGETS_ATTACHUID, track->uid); if (ret < 0) return ret; } } - if (mkv->have_attachments && mkv->mode != MODE_WEBM) { - for (i = 0; i < mkv->attachments->num_entries; i++) { - mkv_attachment *attachment = &mkv->attachments->entries[i]; - AVStream *st = s->streams[attachment->stream_idx]; + if (mkv->tags.bc) { + return end_ebml_master_crc32_tentatively(s->pb, &mkv->tags, mkv, + MATROSKA_ID_TAGS); + } + return 0; +} - if (!mkv_check_tag(st->metadata, MATROSKA_ID_TAGTARGETS_ATTACHUID)) - continue; +static int mkv_new_chapter_ids_needed(const AVFormatContext *s) +{ + for (unsigned i = 0; i < s->nb_chapters; i++) { + if (!s->chapters[i]->id) + return 1; + for (unsigned j = 0; j < i; j++) + if (s->chapters[j]->id == s->chapters[i]->id) + return 1; + } + return 0; +} + +static int mkv_write_chapters(AVFormatContext *s) +{ + MatroskaMuxContext *mkv = s->priv_data; + AVIOContext *dyn_cp = NULL, *dyn_tags = NULL, **tags, *pb = s->pb; + ebml_master editionentry; + AVRational scale = {1, 1E9}; + int ret, create_new_ids; + + if (!s->nb_chapters || mkv->wrote_chapters) + return 0; + + ret = start_ebml_master_crc32(&dyn_cp, mkv); + if (ret < 0) + return ret; + + editionentry = start_ebml_master(dyn_cp, MATROSKA_ID_EDITIONENTRY, 0); + if (mkv->mode != MODE_WEBM) { + 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. */ + tags = mkv->wrote_tags ? &dyn_tags : &mkv->tags.bc; + } else + tags = NULL; + + create_new_ids = mkv_new_chapter_ids_needed(s); + + for (unsigned i = 0; i < s->nb_chapters; i++) { + ebml_master chapteratom, chapterdisplay; + const AVChapter *c = s->chapters[i]; + int64_t chapterstart = av_rescale_q(c->start, c->time_base, scale); + int64_t chapterend = av_rescale_q(c->end, c->time_base, scale); + const AVDictionaryEntry *t; +#if FF_API_CHAPTER_ID_INT + uint64_t uid = create_new_ids ? i + 1ULL : (uint32_t)c->id; +#else + uint64_t uid = create_new_ids ? i + 1ULL : c->id; +#endif + if (chapterstart < 0 || chapterstart > chapterend || chapterend < 0) { + av_log(s, AV_LOG_ERROR, + "Invalid chapter start (%"PRId64") or end (%"PRId64").\n", + chapterstart, chapterend); + ret = AVERROR_INVALIDDATA; + goto fail; + } - ret = mkv_write_tag(s, st->metadata, MATROSKA_ID_TAGTARGETS_ATTACHUID, attachment->fileuid); + chapteratom = start_ebml_master(dyn_cp, MATROSKA_ID_CHAPTERATOM, 0); + put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID, uid); + put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMESTART, chapterstart); + put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMEEND, chapterend); + if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { + chapterdisplay = start_ebml_master(dyn_cp, MATROSKA_ID_CHAPTERDISPLAY, 0); + put_ebml_string(dyn_cp, MATROSKA_ID_CHAPSTRING, t->value); + put_ebml_string(dyn_cp, MATROSKA_ID_CHAPLANG , "und"); + end_ebml_master(dyn_cp, chapterdisplay); + } + end_ebml_master(dyn_cp, chapteratom); + + if (tags && mkv_check_tag(c->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID)) { + ret = mkv_write_tag(mkv, c->metadata, tags, NULL, + MATROSKA_ID_TAGTARGETS_CHAPTERUID, uid); if (ret < 0) - return ret; + goto fail; } } + end_ebml_master(dyn_cp, editionentry); + mkv->wrote_chapters = 1; - if (mkv->tags_bc) { - if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) - end_ebml_master_crc32_preliminary(s->pb, &mkv->tags_bc, mkv, &mkv->tags_pos); - else - end_ebml_master_crc32(s->pb, &mkv->tags_bc, mkv); - } + ret = end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CHAPTERS, 0, 0, 1); + if (ret < 0) + goto fail; + if (dyn_tags) + return end_ebml_master_crc32(pb, &dyn_tags, mkv, + MATROSKA_ID_TAGS, 0, 0, 1); return 0; + +fail: + if (tags) { + /* tags == &mkv->tags.bc can only happen if mkv->tags.bc was + * initially NULL, so we never free older tags. */ + ffio_free_dyn_buf(tags); + } + ffio_free_dyn_buf(&dyn_cp); + return ret; +} + +static const char *get_mimetype(const AVStream *st) +{ + const AVDictionaryEntry *t; + + if (t = av_dict_get(st->metadata, "mimetype", NULL, 0)) + return t->value; + if (st->codecpar->codec_id != AV_CODEC_ID_NONE) { + const AVCodecDescriptor *desc = avcodec_descriptor_get(st->codecpar->codec_id); + if (desc && desc->mime_types) { + return desc->mime_types[0]; + } else if (st->codecpar->codec_id == AV_CODEC_ID_TEXT) + return "text/plain"; + } + + return NULL; } static int mkv_write_attachments(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; - AVIOContext *dyn_cp, *pb = s->pb; - AVLFG c; + AVIOContext *dyn_cp = NULL, *pb = s->pb; int i, ret; - if (!mkv->have_attachments) + if (!mkv->nb_attachments) return 0; - mkv->attachments = av_mallocz(sizeof(*mkv->attachments)); - if (!mkv->attachments) - return AVERROR(ENOMEM); - - av_lfg_init(&c, av_get_random_seed()); - - ret = mkv_add_seekhead_entry(mkv->seekhead, MATROSKA_ID_ATTACHMENTS, avio_tell(pb)); - if (ret < 0) return ret; - - ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_ATTACHMENTS); - if (ret < 0) return ret; + ret = start_ebml_master_crc32(&dyn_cp, mkv); + if (ret < 0) + return ret; for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; + const AVStream *st = s->streams[i]; + mkv_track *track = &mkv->tracks[i]; ebml_master attached_file; - mkv_attachment *attachment = mkv->attachments->entries; - AVDictionaryEntry *t; - const char *mimetype = NULL; - uint32_t fileuid; + const AVDictionaryEntry *t; + const char *mimetype; if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT) continue; - attachment = av_realloc_array(attachment, mkv->attachments->num_entries + 1, sizeof(mkv_attachment)); - if (!attachment) - return AVERROR(ENOMEM); - mkv->attachments->entries = attachment; - attached_file = start_ebml_master(dyn_cp, MATROSKA_ID_ATTACHEDFILE, 0); if (t = av_dict_get(st->metadata, "title", NULL, 0)) @@ -1770,71 +1771,33 @@ return AVERROR(EINVAL); } put_ebml_string(dyn_cp, MATROSKA_ID_FILENAME, t->value); - if (t = av_dict_get(st->metadata, "mimetype", NULL, 0)) - mimetype = t->value; - else if (st->codecpar->codec_id != AV_CODEC_ID_NONE ) { - int i; - for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) - if (ff_mkv_mime_tags[i].id == st->codecpar->codec_id) { - mimetype = ff_mkv_mime_tags[i].str; - break; - } - for (i = 0; ff_mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++) - if (ff_mkv_image_mime_tags[i].id == st->codecpar->codec_id) { - mimetype = ff_mkv_image_mime_tags[i].str; - break; - } - } - if (!mimetype) { - av_log(s, AV_LOG_ERROR, "Attachment stream %d has no mimetype tag and " - "it cannot be deduced from the codec id.\n", i); - return AVERROR(EINVAL); - } - - if (s->flags & AVFMT_FLAG_BITEXACT) { - struct AVSHA *sha = av_sha_alloc(); - uint8_t digest[20]; - if (!sha) - return AVERROR(ENOMEM); - av_sha_init(sha, 160); - av_sha_update(sha, st->codecpar->extradata, st->codecpar->extradata_size); - av_sha_final(sha, digest); - av_free(sha); - fileuid = AV_RL32(digest); - } else { - fileuid = av_lfg_get(&c); - } - av_log(s, AV_LOG_VERBOSE, "Using %.8"PRIx32" for attachment %d\n", - fileuid, mkv->attachments->num_entries); + mimetype = get_mimetype(st); + av_assert0(mimetype); put_ebml_string(dyn_cp, MATROSKA_ID_FILEMIMETYPE, mimetype); put_ebml_binary(dyn_cp, MATROSKA_ID_FILEDATA, st->codecpar->extradata, st->codecpar->extradata_size); - put_ebml_uint(dyn_cp, MATROSKA_ID_FILEUID, fileuid); + put_ebml_uid(dyn_cp, MATROSKA_ID_FILEUID, track->uid); end_ebml_master(dyn_cp, attached_file); - - mkv->attachments->entries[mkv->attachments->num_entries].stream_idx = i; - mkv->attachments->entries[mkv->attachments->num_entries++].fileuid = fileuid; } - end_ebml_master_crc32(pb, &dyn_cp, mkv); - - return 0; + return end_ebml_master_crc32(pb, &dyn_cp, mkv, + MATROSKA_ID_ATTACHMENTS, 0, 0, 1); } static int64_t get_metadata_duration(AVFormatContext *s) { - int i = 0; + const AVDictionaryEntry *duration = av_dict_get(s->metadata, "DURATION", + NULL, 0); int64_t max = 0; int64_t us; - AVDictionaryEntry *explicitDuration = av_dict_get(s->metadata, "DURATION", NULL, 0); - if (explicitDuration && (av_parse_time(&us, explicitDuration->value, 1) == 0) && us > 0) { + if (duration && (av_parse_time(&us, duration->value, 1) == 0) && us > 0) { av_log(s, AV_LOG_DEBUG, "get_metadata_duration found duration in context metadata: %" PRId64 "\n", us); return us; } - for (i = 0; i < s->nb_streams; i++) { + for (unsigned i = 0; i < s->nb_streams; i++) { int64_t us; - AVDictionaryEntry *duration = av_dict_get(s->streams[i]->metadata, "DURATION", NULL, 0); + duration = av_dict_get(s->streams[i]->metadata, "DURATION", NULL, 0); if (duration && (av_parse_time(&us, duration->value, 1) == 0)) max = FFMAX(max, us); @@ -1849,16 +1812,10 @@ MatroskaMuxContext *mkv = s->priv_data; AVIOContext *pb = s->pb; ebml_master ebml_header; - AVDictionaryEntry *tag; + const AVDictionaryEntry *tag; int ret, i, version = 2; int64_t creation_time; - if (!strcmp(s->oformat->name, "webm")) { - mkv->mode = MODE_WEBM; - mkv->write_crc = 0; - } else - mkv->mode = MODE_MATROSKAv2; - if (mkv->mode != MODE_WEBM || av_dict_get(s->metadata, "stereo_mode", NULL, 0) || av_dict_get(s->metadata, "alpha_mode", NULL, 0)) @@ -1871,11 +1828,6 @@ version = 4; } - mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks)); - if (!mkv->tracks) { - ret = AVERROR(ENOMEM); - goto fail; - } ebml_header = start_ebml_master(pb, EBML_ID_HEADER, MAX_EBML_HEADER_SIZE); put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1); put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1); @@ -1886,25 +1838,18 @@ put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION, 2); end_ebml_master(pb, ebml_header); - mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT, 0); + put_ebml_id(pb, MATROSKA_ID_SEGMENT); + put_ebml_size_unknown(pb, 8); mkv->segment_offset = avio_tell(pb); - // we write a seek head at the beginning to point to all other level - // one elements, which aren't more than 10 elements as we write only one - // of every other currently defined level 1 element - mkv->seekhead = mkv_start_seekhead(pb, mkv->segment_offset, 10); - if (!mkv->seekhead) { - ret = AVERROR(ENOMEM); - goto fail; - } + // We write a SeekHead at the beginning to point to all other level + // one elements (except Clusters). + mkv_start_seekhead(mkv, pb); - ret = mkv_add_seekhead_entry(mkv->seekhead, MATROSKA_ID_INFO, avio_tell(pb)); - if (ret < 0) goto fail; - - ret = start_ebml_master_crc32(pb, &mkv->info_bc, mkv, MATROSKA_ID_INFO); + ret = start_ebml_master_crc32(&mkv->info.bc, mkv); if (ret < 0) return ret; - pb = mkv->info_bc; + pb = mkv->info.bc; put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000); if ((tag = av_dict_get(s->metadata, "title", NULL, 0))) @@ -1916,17 +1861,8 @@ else put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT); - if (mkv->mode != MODE_WEBM) { - uint32_t segment_uid[4]; - AVLFG lfg; - - av_lfg_init(&lfg, av_get_random_seed()); - - for (i = 0; i < 4; i++) - segment_uid[i] = av_lfg_get(&lfg); - - put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, segment_uid, 16); - } + if (mkv->mode != MODE_WEBM) + put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, mkv->segment_uid, 16); } else { const char *ident = "Lavf"; put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , ident); @@ -1955,52 +1891,40 @@ int64_t scaledDuration = av_rescale(metadata_duration, 1000, AV_TIME_BASE); put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration); av_log(s, AV_LOG_DEBUG, "Write early duration from metadata = %" PRIu64 "\n", scaledDuration); - } else { + } else if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { put_ebml_void(pb, 11); // assumes double-precision float to be written } } - if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) - end_ebml_master_crc32_preliminary(s->pb, &mkv->info_bc, mkv, &mkv->info_pos); - else - end_ebml_master_crc32(s->pb, &mkv->info_bc, mkv); + ret = end_ebml_master_crc32_tentatively(s->pb, &mkv->info, + mkv, MATROSKA_ID_INFO); + if (ret < 0) + return ret; pb = s->pb; - // initialize stream_duration fields - mkv->stream_durations = av_mallocz(s->nb_streams * sizeof(int64_t)); - mkv->stream_duration_offsets = av_mallocz(s->nb_streams * sizeof(int64_t)); - if (!mkv->stream_durations || !mkv->stream_duration_offsets) { - ret = AVERROR(ENOMEM); - goto fail; - } - ret = mkv_write_tracks(s); if (ret < 0) - goto fail; - - for (i = 0; i < s->nb_chapters; i++) - mkv->chapter_id_offset = FFMAX(mkv->chapter_id_offset, 1LL - s->chapters[i]->id); + return ret; ret = mkv_write_chapters(s); if (ret < 0) - goto fail; + return ret; if (mkv->mode != MODE_WEBM) { ret = mkv_write_attachments(s); if (ret < 0) - goto fail; + return ret; } + /* Must come after mkv_write_chapters() to write chapter tags + * into the same Tags element as the other tags. */ ret = mkv_write_tags(s); if (ret < 0) - goto fail; - - if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) - mkv_write_seekhead(pb, mkv); + return ret; - mkv->cues = mkv_start_cues(mkv->segment_offset); - if (!mkv->cues) { - ret = AVERROR(ENOMEM); - goto fail; + if (!IS_SEEKABLE(pb, mkv)) { + ret = mkv_write_seekhead(pb, mkv, 0, avio_tell(pb)); + if (ret < 0) + return ret; } if (s->metadata_header_padding > 0) { @@ -2009,22 +1933,21 @@ put_ebml_void(pb, s->metadata_header_padding); } - if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && mkv->reserve_cues_space) { - mkv->cues_pos = avio_tell(pb); - if (mkv->reserve_cues_space == 1) - mkv->reserve_cues_space++; - put_ebml_void(pb, mkv->reserve_cues_space); + if (mkv->reserve_cues_space) { + 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); + } else + mkv->reserve_cues_space = -1; } - av_init_packet(&mkv->cur_audio_pkt); - mkv->cur_audio_pkt.size = 0; mkv->cluster_pos = -1; - avio_flush(pb); - // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or // after 4k and on a keyframe - if (pb->seekable & AVIO_SEEKABLE_NORMAL) { + if (IS_SEEKABLE(pb, mkv)) { if (mkv->cluster_time_limit < 0) mkv->cluster_time_limit = 5000; if (mkv->cluster_size_limit < 0) @@ -2037,15 +1960,12 @@ } return 0; -fail: - mkv_free(mkv); - return ret; } -static int mkv_blockgroup_size(int pkt_size) +static int mkv_blockgroup_size(int pkt_size, int track_num_size) { - int size = pkt_size + 4; - size += ebml_num_size(size); + int size = pkt_size + track_num_size + 3; + size += ebml_length_size(size); size += 2; // EBML ID for block and block duration size += 9; // max size of block duration incl. length field return size; @@ -2104,47 +2024,52 @@ return ret; } -static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, - uint32_t blockid, AVPacket *pkt, int keyframe) +static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, + uint32_t blockid, const AVPacket *pkt, int keyframe) { MatroskaMuxContext *mkv = s->priv_data; AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + mkv_track *track = &mkv->tracks[pkt->stream_index]; uint8_t *data = NULL, *side_data = NULL; - int offset = 0, size = pkt->size, side_data_size = 0; - int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; - uint64_t additional_id = 0; + buffer_size_t side_data_size; + int err = 0, offset = 0, size = pkt->size; + int64_t ts = track->write_dts ? pkt->dts : pkt->pts; + uint64_t additional_id; int64_t discard_padding = 0; - uint8_t track_number = (mkv->is_dash ? mkv->dash_track_number : (pkt->stream_index + 1)); + unsigned track_number = track->track_num; ebml_master block_group, block_additions, block_more; - ts += mkv->tracks[pkt->stream_index].ts_offset; + ts += track->ts_offset; /* The following string is identical to the one in mkv_write_vtt_blocks * so that only one copy needs to exist in binaries. */ av_log(s, AV_LOG_DEBUG, "Writing block of size %d with pts %" PRId64 ", dts %" PRId64 ", " "duration %" PRId64 " at relative offset %" PRId64 " in cluster " - "at offset %" PRId64 ". TrackNumber %d, keyframe %d\n", + "at offset %" PRId64 ". TrackNumber %u, keyframe %d\n", pkt->size, pkt->pts, pkt->dts, pkt->duration, avio_tell(pb), mkv->cluster_pos, track_number, keyframe != 0); + if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0 && - (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) - ff_avc_parse_nal_units_buf(pkt->data, &data, &size); - else if (par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6 && - (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) + (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) { + err = ff_avc_parse_nal_units_buf(pkt->data, &data, &size); + } else if (par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6 && + (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) { /* extradata is Annex B, assume the bitstream is too and convert it */ - ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL); - else if (par->codec_id == AV_CODEC_ID_AV1) - ff_av1_filter_obus_buf(pkt->data, &data, &size); - else if (par->codec_id == AV_CODEC_ID_WAVPACK) { - int ret = mkv_strip_wavpack(pkt->data, &data, &size); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Error stripping a WavPack packet.\n"); - return; - } + 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 data = pkt->data; + if (err < 0) { + av_log(s, AV_LOG_ERROR, "Error when reformatting data of " + "a packet from stream %d.\n", pkt->stream_index); + return err; + } + if (par->codec_id == AV_CODEC_ID_PRORES && size >= 8) { /* Matroska specification requires to remove the first QuickTime atom */ @@ -2155,7 +2080,6 @@ side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, &side_data_size); - if (side_data && side_data_size >= 10) { discard_padding = av_rescale_q(AV_RL32(side_data + 4), (AVRational){1, par->sample_rate}, @@ -2166,67 +2090,71 @@ AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, &side_data_size); if (side_data) { - additional_id = AV_RB64(side_data); - side_data += 8; - side_data_size -= 8; + // Only the Codec-specific BlockMore (id == 1) is currently supported. + if (side_data_size < 8 || (additional_id = AV_RB64(side_data)) != 1) { + side_data_size = 0; + } else { + side_data += 8; + side_data_size -= 8; + } } - if ((side_data_size && additional_id == 1) || discard_padding) { + if (side_data_size || discard_padding) { block_group = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, 0); blockid = MATROSKA_ID_BLOCK; } put_ebml_id(pb, blockid); - put_ebml_num(pb, size + 4, 0); - // this assumes stream_index is less than 126 - avio_w8(pb, 0x80 | track_number); + put_ebml_length(pb, size + track->track_num_size + 3, 0); + put_ebml_num(pb, track_number, track->track_num_size); avio_wb16(pb, ts - mkv->cluster_pts); avio_w8(pb, (blockid == MATROSKA_ID_SIMPLEBLOCK && keyframe) ? (1 << 7) : 0); avio_write(pb, data + offset, size); if (data != pkt->data) av_free(data); - if (blockid == MATROSKA_ID_BLOCK && !keyframe) { - put_ebml_sint(pb, MATROSKA_ID_BLOCKREFERENCE, - mkv->last_track_timestamp[track_number - 1]); - } - mkv->last_track_timestamp[track_number - 1] = ts - mkv->cluster_pts; + if (blockid == MATROSKA_ID_BLOCK && !keyframe) + put_ebml_sint(pb, MATROSKA_ID_BLOCKREFERENCE, track->last_timestamp - ts); + track->last_timestamp = ts; - if (discard_padding) { + if (discard_padding) put_ebml_sint(pb, MATROSKA_ID_DISCARDPADDING, discard_padding); - } - if (side_data_size && additional_id == 1) { + if (side_data_size) { block_additions = start_ebml_master(pb, MATROSKA_ID_BLOCKADDITIONS, 0); block_more = start_ebml_master(pb, MATROSKA_ID_BLOCKMORE, 0); - put_ebml_uint(pb, MATROSKA_ID_BLOCKADDID, 1); - put_ebml_id(pb, MATROSKA_ID_BLOCKADDITIONAL); - put_ebml_num(pb, side_data_size, 0); - avio_write(pb, side_data, side_data_size); + /* Until dbc50f8a our demuxer used a wrong default value + * of BlockAddID, so we write it unconditionally. */ + put_ebml_uint (pb, MATROSKA_ID_BLOCKADDID, additional_id); + put_ebml_binary(pb, MATROSKA_ID_BLOCKADDITIONAL, + side_data, side_data_size); end_ebml_master(pb, block_more); end_ebml_master(pb, block_additions); } - if ((side_data_size && additional_id == 1) || discard_padding) { + if (side_data_size || discard_padding) end_ebml_master(pb, block_group); - } + + return 0; } -static int mkv_write_vtt_blocks(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt) +static int mkv_write_vtt_blocks(AVFormatContext *s, AVIOContext *pb, const AVPacket *pkt) { MatroskaMuxContext *mkv = s->priv_data; + mkv_track *track = &mkv->tracks[pkt->stream_index]; ebml_master blockgroup; - int id_size, settings_size, size; - uint8_t *id, *settings; - int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; + buffer_size_t id_size, settings_size; + int size; + const char *id, *settings; + int64_t ts = track->write_dts ? pkt->dts : pkt->pts; const int flags = 0; - id_size = 0; id = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_IDENTIFIER, &id_size); + id = id ? id : ""; - settings_size = 0; settings = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_SETTINGS, &settings_size); + settings = settings ? settings : ""; size = id_size + 1 + settings_size + 1 + pkt->size; @@ -2235,15 +2163,16 @@ av_log(s, AV_LOG_DEBUG, "Writing block of size %d with pts %" PRId64 ", dts %" PRId64 ", " "duration %" PRId64 " at relative offset %" PRId64 " in cluster " - "at offset %" PRId64 ". TrackNumber %d, keyframe %d\n", + "at offset %" PRId64 ". TrackNumber %u, keyframe %d\n", size, pkt->pts, pkt->dts, pkt->duration, avio_tell(pb), - mkv->cluster_pos, pkt->stream_index + 1, 1); + mkv->cluster_pos, track->track_num, 1); - blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(size)); + blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, + mkv_blockgroup_size(size, track->track_num_size)); put_ebml_id(pb, MATROSKA_ID_BLOCK); - put_ebml_num(pb, size + 4, 0); - avio_w8(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 + put_ebml_length(pb, size + track->track_num_size + 3, 0); + put_ebml_num(pb, track->track_num, track->track_num_size); avio_wb16(pb, ts - mkv->cluster_pts); avio_w8(pb, flags); avio_printf(pb, "%.*s\n%.*s\n%.*s", id_size, id, settings_size, settings, pkt->size, pkt->data); @@ -2254,56 +2183,59 @@ return pkt->duration; } -static void mkv_start_new_cluster(AVFormatContext *s, AVPacket *pkt) +static int mkv_end_cluster(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; + int ret; - end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv); + if (!mkv->have_video) { + for (unsigned i = 0; i < s->nb_streams; i++) + mkv->tracks[i].has_cue = 0; + } mkv->cluster_pos = -1; - av_log(s, AV_LOG_DEBUG, - "Starting new cluster at offset %" PRIu64 " bytes, " - "pts %" PRIu64 ", dts %" PRIu64 "\n", - avio_tell(s->pb), pkt->pts, pkt->dts); - avio_flush(s->pb); + ret = end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv, + MATROSKA_ID_CLUSTER, 0, 1, 0); + if (ret < 0) + return ret; + + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); + return 0; } -static int mkv_check_new_extra_data(AVFormatContext *s, AVPacket *pkt) +static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) { MatroskaMuxContext *mkv = s->priv_data; mkv_track *track = &mkv->tracks[pkt->stream_index]; AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; uint8_t *side_data; - int side_data_size = 0, ret; + buffer_size_t side_data_size; + int ret; side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_data_size); switch (par->codec_id) { case AV_CODEC_ID_AAC: - if (side_data_size && (s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) { + if (side_data_size && mkv->track.bc) { int filler, output_sample_rate = 0; - int64_t curpos; - ret = get_aac_sample_rates(s, side_data, side_data_size, &track->sample_rate, - &output_sample_rate); + ret = get_aac_sample_rates(s, mkv, side_data, side_data_size, + &track->sample_rate, &output_sample_rate); if (ret < 0) return ret; if (!output_sample_rate) output_sample_rate = track->sample_rate; // Space is already reserved, so it's this or a void element. - av_freep(&par->extradata); ret = ff_alloc_extradata(par, side_data_size); if (ret < 0) return ret; memcpy(par->extradata, side_data, side_data_size); - curpos = avio_tell(mkv->tracks_bc); - avio_seek(mkv->tracks_bc, track->codecpriv_offset, SEEK_SET); - mkv_write_codecprivate(s, mkv->tracks_bc, par, 1, 0); - filler = MAX_PCE_SIZE + 2 + 4 - (avio_tell(mkv->tracks_bc) - track->codecpriv_offset); + avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET); + mkv_write_codecprivate(s, mkv->track.bc, par, 1, 0); + filler = MAX_PCE_SIZE + 2 + 4 - (avio_tell(mkv->track.bc) - track->codecpriv_offset); if (filler) - put_ebml_void(mkv->tracks_bc, filler); - avio_seek(mkv->tracks_bc, track->sample_rate_offset, SEEK_SET); - put_ebml_float(mkv->tracks_bc, MATROSKA_ID_AUDIOSAMPLINGFREQ, track->sample_rate); - put_ebml_float(mkv->tracks_bc, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); - avio_seek(mkv->tracks_bc, curpos, SEEK_SET); + put_ebml_void(mkv->track.bc, filler); + avio_seek(mkv->track.bc, track->sample_rate_offset, SEEK_SET); + put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOSAMPLINGFREQ, track->sample_rate); + put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); } else if (!par->extradata_size && !track->sample_rate) { // No extradata (codecpar or packet side data). av_log(s, AV_LOG_ERROR, "Error parsing AAC extradata, unable to determine samplerate.\n"); @@ -2311,54 +2243,40 @@ } break; case AV_CODEC_ID_FLAC: - if (side_data_size && (s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) { - AVCodecParameters *codecpriv_par; - int64_t curpos; + if (side_data_size && mkv->track.bc) { + uint8_t *old_extradata = par->extradata; if (side_data_size != par->extradata_size) { av_log(s, AV_LOG_ERROR, "Invalid FLAC STREAMINFO metadata for output stream %d\n", pkt->stream_index); return AVERROR(EINVAL); } - codecpriv_par = avcodec_parameters_alloc(); - if (!codecpriv_par) - return AVERROR(ENOMEM); - ret = avcodec_parameters_copy(codecpriv_par, par); - if (ret < 0) { - avcodec_parameters_free(&codecpriv_par); - return ret; - } - memcpy(codecpriv_par->extradata, side_data, side_data_size); - curpos = avio_tell(mkv->tracks_bc); - avio_seek(mkv->tracks_bc, track->codecpriv_offset, SEEK_SET); - mkv_write_codecprivate(s, mkv->tracks_bc, codecpriv_par, 1, 0); - avio_seek(mkv->tracks_bc, curpos, SEEK_SET); - avcodec_parameters_free(&codecpriv_par); + par->extradata = side_data; + avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET); + mkv_write_codecprivate(s, mkv->track.bc, par, 1, 0); + par->extradata = old_extradata; } break; // 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: - if (side_data_size && (s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live && - !par->extradata_size) { + if (side_data_size && mkv->track.bc && !par->extradata_size) { AVIOContext *dyn_cp; uint8_t *codecpriv; int codecpriv_size; - int64_t curpos; ret = avio_open_dyn_buf(&dyn_cp); if (ret < 0) return ret; ff_isom_write_av1c(dyn_cp, side_data, side_data_size); - codecpriv_size = avio_close_dyn_buf(dyn_cp, &codecpriv); - if (!codecpriv_size) { - av_free(codecpriv); - return AVERROR_INVALIDDATA; + codecpriv_size = avio_get_dyn_buf(dyn_cp, &codecpriv); + if ((ret = dyn_cp->error) < 0 || + !codecpriv_size && (ret = AVERROR_INVALIDDATA)) { + ffio_free_dyn_buf(&dyn_cp); + return ret; } - curpos = avio_tell(mkv->tracks_bc); - avio_seek(mkv->tracks_bc, track->codecpriv_offset, SEEK_SET); + avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET); // Do not write the OBUs as we don't have space saved for them - put_ebml_binary(mkv->tracks_bc, MATROSKA_ID_CODECPRIVATE, codecpriv, 4); - av_free(codecpriv); - avio_seek(mkv->tracks_bc, curpos, SEEK_SET); + put_ebml_binary(mkv->track.bc, MATROSKA_ID_CODECPRIVATE, codecpriv, 4); + ffio_free_dyn_buf(&dyn_cp); ret = ff_alloc_extradata(par, side_data_size); if (ret < 0) return ret; @@ -2375,56 +2293,69 @@ return 0; } -static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_cue) +static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) { MatroskaMuxContext *mkv = s->priv_data; - AVIOContext *pb = s->pb; + AVIOContext *pb; AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; + mkv_track *track = &mkv->tracks[pkt->stream_index]; int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY); int duration = pkt->duration; int ret; - int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; + int64_t ts = track->write_dts ? pkt->dts : pkt->pts; int64_t relative_packet_pos; - int dash_tracknum = mkv->is_dash ? mkv->dash_track_number : pkt->stream_index + 1; if (ts == AV_NOPTS_VALUE) { av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n"); return AVERROR(EINVAL); } - ts += mkv->tracks[pkt->stream_index].ts_offset; + ts += track->ts_offset; if (mkv->cluster_pos != -1) { int64_t cluster_time = ts - mkv->cluster_pts; if ((int16_t)cluster_time != cluster_time) { + ret = mkv_end_cluster(s); + if (ret < 0) + return ret; av_log(s, AV_LOG_WARNING, "Starting new cluster due to timestamp\n"); - mkv_start_new_cluster(s, pkt); } } if (mkv->cluster_pos == -1) { - mkv->cluster_pos = avio_tell(s->pb); - ret = start_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv, MATROSKA_ID_CLUSTER); + ret = start_ebml_master_crc32(&mkv->cluster_bc, mkv); if (ret < 0) return ret; + mkv->cluster_pos = avio_tell(s->pb); put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts)); mkv->cluster_pts = FFMAX(0, ts); + av_log(s, AV_LOG_DEBUG, + "Starting new cluster with timestamp " + "%" PRId64 " at offset %" PRId64 " bytes\n", + mkv->cluster_pts, mkv->cluster_pos); } pb = mkv->cluster_bc; relative_packet_pos = avio_tell(pb); if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) { - mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); - if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && (par->codec_type == AVMEDIA_TYPE_VIDEO && keyframe || add_cue)) { - ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, mkv->cluster_pos, relative_packet_pos, -1); - if (ret < 0) return ret; + ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); + if (ret < 0) + return ret; + if (keyframe && IS_SEEKABLE(s->pb, mkv) && + (par->codec_type == AVMEDIA_TYPE_VIDEO || !mkv->have_video && !track->has_cue)) { + ret = mkv_add_cuepoint(mkv, pkt->stream_index, ts, + mkv->cluster_pos, relative_packet_pos, -1); + if (ret < 0) + return ret; + track->has_cue = 1; } } else { if (par->codec_id == AV_CODEC_ID_WEBVTT) { duration = mkv_write_vtt_blocks(s, pb, pkt); } else { ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, - mkv_blockgroup_size(pkt->size)); + mkv_blockgroup_size(pkt->size, + track->track_num_size)); #if FF_API_CONVERGENCE_DURATION FF_DISABLE_DEPRECATION_WARNINGS @@ -2440,24 +2371,21 @@ end_ebml_master(pb, blockgroup); } - if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { - ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, + if (IS_SEEKABLE(s->pb, mkv)) { + ret = mkv_add_cuepoint(mkv, pkt->stream_index, ts, mkv->cluster_pos, relative_packet_pos, duration); if (ret < 0) return ret; } } - mkv->duration = FFMAX(mkv->duration, ts + duration); - - if (mkv->stream_durations) - mkv->stream_durations[pkt->stream_index] = - FFMAX(mkv->stream_durations[pkt->stream_index], ts + duration); + mkv->duration = FFMAX(mkv->duration, ts + duration); + track->duration = FFMAX(track->duration, ts + duration); return 0; } -static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) +static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt) { MatroskaMuxContext *mkv = s->priv_data; int codec_type = s->streams[pkt->stream_index]->codecpar->codec_type; @@ -2471,38 +2399,38 @@ if (ret < 0) return ret; - if (mkv->tracks[pkt->stream_index].write_dts) - cluster_time = pkt->dts - mkv->cluster_pts; - else - cluster_time = pkt->pts - mkv->cluster_pts; - cluster_time += mkv->tracks[pkt->stream_index].ts_offset; + if (mkv->cluster_pos != -1) { + if (mkv->tracks[pkt->stream_index].write_dts) + cluster_time = pkt->dts - mkv->cluster_pts; + else + cluster_time = pkt->pts - mkv->cluster_pts; + cluster_time += mkv->tracks[pkt->stream_index].ts_offset; - // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or - // after 4k and on a keyframe - cluster_size = avio_tell(mkv->cluster_bc); + cluster_size = avio_tell(mkv->cluster_bc); - if (mkv->is_dash && codec_type == AVMEDIA_TYPE_VIDEO) { - // WebM DASH specification states that the first block of every cluster - // has to be a key frame. So for DASH video, we only create a cluster - // on seeing key frames. - start_new_cluster = keyframe; - } else if (mkv->is_dash && codec_type == AVMEDIA_TYPE_AUDIO && - (mkv->cluster_pos == -1 || - cluster_time > mkv->cluster_time_limit)) { - // For DASH audio, we create a Cluster based on cluster_time_limit - start_new_cluster = 1; - } else if (!mkv->is_dash && - (cluster_size > mkv->cluster_size_limit || - cluster_time > mkv->cluster_time_limit || - (codec_type == AVMEDIA_TYPE_VIDEO && keyframe && - cluster_size > 4 * 1024))) { - start_new_cluster = 1; - } else { - start_new_cluster = 0; - } + if (mkv->is_dash && codec_type == AVMEDIA_TYPE_VIDEO) { + // WebM DASH specification states that the first block of + // every Cluster has to be a key frame. So for DASH video, + // we only create a Cluster on seeing key frames. + start_new_cluster = keyframe; + } else if (mkv->is_dash && codec_type == AVMEDIA_TYPE_AUDIO && + cluster_time > mkv->cluster_time_limit) { + // For DASH audio, we create a Cluster based on cluster_time_limit. + start_new_cluster = 1; + } else if (!mkv->is_dash && + (cluster_size > mkv->cluster_size_limit || + cluster_time > mkv->cluster_time_limit || + (codec_type == AVMEDIA_TYPE_VIDEO && keyframe && + cluster_size > 4 * 1024))) { + start_new_cluster = 1; + } else + start_new_cluster = 0; - if (mkv->cluster_pos != -1 && start_new_cluster) { - mkv_start_new_cluster(s, pkt); + if (start_new_cluster) { + ret = mkv_end_cluster(s); + if (ret < 0) + return ret; + } } if (!mkv->cluster_pos) @@ -2511,11 +2439,9 @@ keyframe && (mkv->have_video ? codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT); // check if we have an audio packet cached - if (mkv->cur_audio_pkt.size > 0) { - // for DASH audio, a CuePoint has to be added when there is a new cluster. - ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt, - mkv->is_dash ? start_new_cluster : 0); - av_packet_unref(&mkv->cur_audio_pkt); + if (mkv->cur_audio_pkt->size > 0) { + ret = mkv_write_packet_internal(s, mkv->cur_audio_pkt); + av_packet_unref(mkv->cur_audio_pkt); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret); @@ -2527,9 +2453,9 @@ // keyframe's timecode is contained in the same cluster for WebM if (codec_type == AVMEDIA_TYPE_AUDIO) { if (pkt->size > 0) - ret = av_packet_ref(&mkv->cur_audio_pkt, pkt); + ret = av_packet_ref(mkv->cur_audio_pkt, pkt); } else - ret = mkv_write_packet_internal(s, pkt, 0); + ret = mkv_write_packet_internal(s, pkt); return ret; } @@ -2539,12 +2465,12 @@ if (!pkt) { if (mkv->cluster_pos != -1) { - end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv); - mkv->cluster_pos = -1; + int ret = mkv_end_cluster(s); + if (ret < 0) + return ret; av_log(s, AV_LOG_DEBUG, "Flushing cluster at offset %" PRIu64 " bytes\n", avio_tell(s->pb)); - avio_flush(s->pb); } return 1; } @@ -2555,13 +2481,12 @@ { MatroskaMuxContext *mkv = s->priv_data; AVIOContext *pb = s->pb; - int64_t currentpos, cuespos; - int ret; + int64_t endpos, ret64; + int ret, ret2 = 0; // check if we have an audio packet cached - if (mkv->cur_audio_pkt.size > 0) { - ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt, 0); - av_packet_unref(&mkv->cur_audio_pkt); + if (mkv->cur_audio_pkt->size > 0) { + ret = mkv_write_packet_internal(s, mkv->cur_audio_pkt); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Could not write cached audio packet ret:%d\n", ret); @@ -2569,101 +2494,143 @@ } } - if (mkv->cluster_bc) { - end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv); + if (mkv->cluster_pos != -1) { + ret = end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv, + MATROSKA_ID_CLUSTER, 0, 0, 0); + if (ret < 0) + return ret; } ret = mkv_write_chapters(s); if (ret < 0) return ret; + if (!IS_SEEKABLE(pb, mkv)) + return 0; - if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) { - if (mkv->cues->num_entries) { - if (mkv->reserve_cues_space) { - int64_t cues_end; - - currentpos = avio_tell(pb); - avio_seek(pb, mkv->cues_pos, SEEK_SET); - - cuespos = mkv_write_cues(s, mkv->cues, mkv->tracks, s->nb_streams); - cues_end = avio_tell(pb); - if (cues_end > cuespos + mkv->reserve_cues_space) { - av_log(s, AV_LOG_ERROR, - "Insufficient space reserved for cues: %d " - "(needed: %" PRId64 ").\n", - mkv->reserve_cues_space, cues_end - cuespos); - return AVERROR(EINVAL); - } + endpos = avio_tell(pb); - if (cues_end < cuespos + mkv->reserve_cues_space) - put_ebml_void(pb, mkv->reserve_cues_space - - (cues_end - cuespos)); + if (mkv->cues.num_entries && mkv->reserve_cues_space >= 0) { + AVIOContext *cues = NULL; + uint64_t size; + int length_size = 0; - avio_seek(pb, currentpos, SEEK_SET); + 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); + if (ret < 0) { + ffio_free_dyn_buf(&cues); + return ret; + } + + if (mkv->reserve_cues_space) { + size = avio_tell(cues); + length_size = ebml_length_size(size); + size += 4 + length_size; + if (mkv->reserve_cues_space < size) { + av_log(s, AV_LOG_WARNING, + "Insufficient space reserved for Cues: " + "%d < %"PRIu64". No Cues will be output.\n", + mkv->reserve_cues_space, size); + ret2 = AVERROR(EINVAL); + goto after_cues; } else { - cuespos = mkv_write_cues(s, mkv->cues, mkv->tracks, s->nb_streams); + if ((ret64 = avio_seek(pb, mkv->cues_pos, SEEK_SET)) < 0) { + ffio_free_dyn_buf(&cues); + return ret64; + } + if (mkv->reserve_cues_space == size + 1) { + /* There is no way to reserve a single byte because + * the minimal size of an EBML Void element is 2 + * (1 byte ID, 1 byte length field). This problem + * is solved by writing the Cues' length field on + * one byte more than necessary. */ + length_size++; + size++; + } } - - ret = mkv_add_seekhead_entry(mkv->seekhead, MATROSKA_ID_CUES, - cuespos); - if (ret < 0) - return ret; } + ret = end_ebml_master_crc32(pb, &cues, mkv, MATROSKA_ID_CUES, + length_size, 0, 1); + if (ret < 0) + return ret; + if (mkv->reserve_cues_space) { + if (size < mkv->reserve_cues_space) + put_ebml_void(pb, mkv->reserve_cues_space - size); + } else + endpos = avio_tell(pb); + } + +after_cues: + /* Lengths greater than (1ULL << 56) - 1 can't be represented + * via an EBML number, so leave the unknown length field. */ + if (endpos - mkv->segment_offset < (1ULL << 56) - 1) { + if ((ret64 = avio_seek(pb, mkv->segment_offset - 8, SEEK_SET)) < 0) + return ret64; + put_ebml_length(pb, endpos - mkv->segment_offset, 8); + } - mkv_write_seekhead(pb, mkv); + ret = mkv_write_seekhead(pb, mkv, 1, mkv->info.pos); + if (ret < 0) + return ret; + if (mkv->info.bc) { // update the duration av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); - currentpos = avio_tell(pb); - avio_seek(mkv->info_bc, mkv->duration_offset, SEEK_SET); - put_ebml_float(mkv->info_bc, MATROSKA_ID_DURATION, mkv->duration); - avio_seek(pb, mkv->info_pos, SEEK_SET); - end_ebml_master_crc32(pb, &mkv->info_bc, mkv); - - // write tracks master - avio_seek(pb, mkv->tracks_pos, SEEK_SET); - end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv); - - // update stream durations - if (!mkv->is_live && mkv->stream_durations) { - int i; - int64_t curr = avio_tell(mkv->tags_bc); - for (i = 0; i < s->nb_streams; ++i) { - AVStream *st = s->streams[i]; - - if (mkv->stream_duration_offsets[i] > 0) { - double duration_sec = mkv->stream_durations[i] * av_q2d(st->time_base); - char duration_string[20] = ""; - - av_log(s, AV_LOG_DEBUG, "stream %d end duration = %" PRIu64 "\n", i, - mkv->stream_durations[i]); - - avio_seek(mkv->tags_bc, mkv->stream_duration_offsets[i], SEEK_SET); - - snprintf(duration_string, 20, "%02d:%02d:%012.9f", - (int) duration_sec / 3600, ((int) duration_sec / 60) % 60, - fmod(duration_sec, 60)); + avio_seek(mkv->info.bc, mkv->duration_offset, SEEK_SET); + put_ebml_float(mkv->info.bc, MATROSKA_ID_DURATION, mkv->duration); + ret = end_ebml_master_crc32(pb, &mkv->info.bc, mkv, + MATROSKA_ID_INFO, 0, 0, 0); + if (ret < 0) + return ret; + } - put_ebml_binary(mkv->tags_bc, MATROSKA_ID_TAGSTRING, duration_string, 20); - } + if (mkv->track.bc) { + // write Tracks master + avio_seek(pb, mkv->track.pos, SEEK_SET); + ret = end_ebml_master_crc32(pb, &mkv->track.bc, mkv, + MATROSKA_ID_TRACKS, 0, 0, 0); + if (ret < 0) + return ret; + } + + // update stream durations + if (mkv->tags.bc) { + int i; + for (i = 0; i < s->nb_streams; ++i) { + const AVStream *st = s->streams[i]; + const mkv_track *track = &mkv->tracks[i]; + + if (track->duration_offset > 0) { + double duration_sec = track->duration * av_q2d(st->time_base); + char duration_string[20] = ""; + + av_log(s, AV_LOG_DEBUG, "stream %d end duration = %" PRIu64 "\n", i, + track->duration); + + avio_seek(mkv->tags.bc, track->duration_offset, SEEK_SET); + + snprintf(duration_string, 20, "%02d:%02d:%012.9f", + (int) duration_sec / 3600, ((int) duration_sec / 60) % 60, + fmod(duration_sec, 60)); + + put_ebml_binary(mkv->tags.bc, MATROSKA_ID_TAGSTRING, duration_string, 20); } - avio_seek(mkv->tags_bc, curr, SEEK_SET); - } - if (mkv->tags_bc && !mkv->is_live) { - avio_seek(pb, mkv->tags_pos, SEEK_SET); - end_ebml_master_crc32(pb, &mkv->tags_bc, mkv); } - avio_seek(pb, currentpos, SEEK_SET); + avio_seek(pb, mkv->tags.pos, SEEK_SET); + ret = end_ebml_master_crc32(pb, &mkv->tags.bc, mkv, + MATROSKA_ID_TAGS, 0, 0, 0); + if (ret < 0) + return ret; } - if (!mkv->is_live) { - end_ebml_master(pb, mkv->segment); - } + avio_seek(pb, endpos, SEEK_SET); - mkv_free(mkv); - return 0; + return ret2; } static int mkv_query_codec(enum AVCodecID codec_id, int std_compliance) @@ -2693,17 +2660,31 @@ return 0; } +static uint64_t mkv_get_uid(const mkv_track *tracks, int i, AVLFG *c) +{ + while (1) { + uint64_t uid; + int k; + uid = (uint64_t)av_lfg_get(c) << 32; + uid |= av_lfg_get(c); + if (!uid) + continue; + for (k = 0; k < i; k++) { + if (tracks[k].uid == uid) + break; + } + if (k == i) + return uid; + } +} + static int mkv_init(struct AVFormatContext *s) { + MatroskaMuxContext *mkv = s->priv_data; + AVLFG c; + unsigned nb_tracks = 0; int i; - if (s->nb_streams > MAX_TRACKS) { - av_log(s, AV_LOG_ERROR, - "At most %d streams are supported for muxing in Matroska\n", - MAX_TRACKS); - return AVERROR(EINVAL); - } - for (i = 0; i < s->nb_streams; i++) { if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_ATRAC3 || s->streams[i]->codecpar->codec_id == AV_CODEC_ID_COOK || @@ -2723,11 +2704,61 @@ s->internal->avoid_negative_ts_use_pts = 1; } + if (!strcmp(s->oformat->name, "webm")) { + mkv->mode = MODE_WEBM; + mkv->write_crc = 0; + } else + mkv->mode = MODE_MATROSKAv2; + + mkv->cur_audio_pkt = av_packet_alloc(); + if (!mkv->cur_audio_pkt) + return AVERROR(ENOMEM); + mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks)); + if (!mkv->tracks) + return AVERROR(ENOMEM); + + if (!(s->flags & AVFMT_FLAG_BITEXACT)) { + av_lfg_init(&c, av_get_random_seed()); + + // Calculate the SegmentUID now in order not to waste our random seed. + for (i = 0; i < 4; i++) + mkv->segment_uid[i] = av_lfg_get(&c); + } + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + mkv_track *track = &mkv->tracks[i]; + + if (s->flags & AVFMT_FLAG_BITEXACT) { + track->uid = i + 1; + } else { + track->uid = mkv_get_uid(mkv->tracks, i, &c); + } + // ms precision is the de-facto standard timescale for mkv files - avpriv_set_pts_info(s->streams[i], 64, 1, 1000); + avpriv_set_pts_info(st, 64, 1, 1000); + + if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) { + if (mkv->mode == MODE_WEBM) { + av_log(s, AV_LOG_WARNING, "Stream %d will be ignored " + "as WebM doesn't support attachments.\n", i); + } else if (!get_mimetype(st)) { + av_log(s, AV_LOG_ERROR, "Attachment stream %d has no mimetype " + "tag and it cannot be deduced from the codec id.\n", i); + return AVERROR(EINVAL); + } + mkv->nb_attachments++; + continue; + } + + nb_tracks++; + track->track_num = mkv->is_dash ? mkv->dash_track_number : nb_tracks; + track->track_num_size = ebml_num_size(track->track_num); } + if (mkv->is_dash && nb_tracks != 1) + return AVERROR(EINVAL); + return 0; } @@ -2783,10 +2814,15 @@ { "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 }, - { "dash_track_number", "Track number for the DASH stream", OFFSET(dash_track_number), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 127, FLAGS }, + { "dash_track_number", "Track number for the DASH stream", OFFSET(dash_track_number), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX, FLAGS }, { "live", "Write files assuming it is a live stream.", OFFSET(is_live), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, { "allow_raw_vfw", "allow RAW VFW mode", OFFSET(allow_raw_vfw), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, + { "flipped_raw_rgb", "Raw RGB bitmaps in VFW mode are stored bottom-up", OFFSET(flipped_raw_rgb), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, { "write_crc32", "write a CRC32 element inside every Level 1 element", OFFSET(write_crc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS }, + { "default_mode", "Controls how a track's FlagDefault is inferred", OFFSET(default_mode), AV_OPT_TYPE_INT, { .i64 = DEFAULT_MODE_INFER }, DEFAULT_MODE_INFER, DEFAULT_MODE_PASSTHROUGH, FLAGS, "default_mode" }, + { "infer", "For each track type, mark the first track of disposition default as default; if none exists, mark the first track as default.", 0, AV_OPT_TYPE_CONST, { .i64 = DEFAULT_MODE_INFER }, 0, 0, FLAGS, "default_mode" }, + { "infer_no_subs", "For each track type, mark the first track of disposition default as default; for audio and video: if none exists, mark the first track as default.", 0, AV_OPT_TYPE_CONST, { .i64 = DEFAULT_MODE_INFER_NO_SUBS }, 0, 0, FLAGS, "default_mode" }, + { "passthrough", "Use the disposition flag as-is", 0, AV_OPT_TYPE_CONST, { .i64 = DEFAULT_MODE_PASSTHROUGH }, 0, 0, FLAGS, "default_mode" }, { NULL }, }; @@ -2809,6 +2845,7 @@ .video_codec = CONFIG_LIBX264_ENCODER ? AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, .init = mkv_init, + .deinit = mkv_deinit, .write_header = mkv_write_header, .write_packet = mkv_write_flush_packet, .write_trailer = mkv_write_trailer, @@ -2843,6 +2880,7 @@ .video_codec = CONFIG_LIBVPX_VP9_ENCODER? AV_CODEC_ID_VP9 : AV_CODEC_ID_VP8, .subtitle_codec = AV_CODEC_ID_WEBVTT, .init = mkv_init, + .deinit = mkv_deinit, .write_header = mkv_write_header, .write_packet = mkv_write_flush_packet, .write_trailer = mkv_write_trailer, @@ -2871,6 +2909,7 @@ AV_CODEC_ID_VORBIS : AV_CODEC_ID_AC3, .video_codec = AV_CODEC_ID_NONE, .init = mkv_init, + .deinit = mkv_deinit, .write_header = mkv_write_header, .write_packet = mkv_write_flush_packet, .write_trailer = mkv_write_trailer, diff -Nru ffmpeg-4.2.2/libavformat/matroska.h ffmpeg-4.4/libavformat/matroska.h --- ffmpeg-4.2.2/libavformat/matroska.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/matroska.h 2021-04-08 21:28:40.000000000 +0000 @@ -98,6 +98,11 @@ #define MATROSKA_ID_TRACKFLAGENABLED 0xB9 #define MATROSKA_ID_TRACKFLAGDEFAULT 0x88 #define MATROSKA_ID_TRACKFLAGFORCED 0x55AA +#define MATROSKA_ID_TRACKFLAGHEARINGIMPAIRED 0x55AB +#define MATROSKA_ID_TRACKFLAGVISUALIMPAIRED 0x55AC +#define MATROSKA_ID_TRACKFLAGTEXTDESCRIPTIONS 0x55AD +#define MATROSKA_ID_TRACKFLAGORIGINAL 0x55AE +#define MATROSKA_ID_TRACKFLAGCOMMENTARY 0x55AF #define MATROSKA_ID_TRACKFLAGLACING 0x9C #define MATROSKA_ID_TRACKMINCACHE 0x6DE7 #define MATROSKA_ID_TRACKMAXCACHE 0x6DF8 @@ -271,6 +276,7 @@ MATROSKA_TRACK_TYPE_COMPLEX = 0x3, MATROSKA_TRACK_TYPE_LOGO = 0x10, MATROSKA_TRACK_TYPE_SUBTITLE = 0x11, + MATROSKA_TRACK_TYPE_BUTTONS = 0x12, MATROSKA_TRACK_TYPE_CONTROL = 0x20, MATROSKA_TRACK_TYPE_METADATA = 0x21, } MatroskaTrackType; @@ -285,13 +291,13 @@ typedef enum { MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED = 0, MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED = 1, - MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE = 2 + MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE = 2, } MatroskaVideoInterlaceFlag; typedef enum { MATROSKA_VIDEO_FIELDORDER_PROGRESSIVE = 0, - MATROSKA_VIDEO_FIELDORDER_UNDETERMINED = 2, MATROSKA_VIDEO_FIELDORDER_TT = 1, + MATROSKA_VIDEO_FIELDORDER_UNDETERMINED = 2, MATROSKA_VIDEO_FIELDORDER_BB = 6, MATROSKA_VIDEO_FIELDORDER_TB = 9, MATROSKA_VIDEO_FIELDORDER_BT = 14, @@ -361,8 +367,6 @@ extern const CodecTags ff_mkv_codec_tags[]; extern const CodecTags ff_webm_codec_tags[]; -extern const CodecMime ff_mkv_mime_tags[]; -extern const CodecMime ff_mkv_image_mime_tags[]; extern const AVMetadataConv ff_mkv_metadata_conv[]; extern const char * const ff_matroska_video_stereo_mode[MATROSKA_VIDEO_STEREOMODE_TYPE_NB]; extern const char * const ff_matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_PLANE_COUNT]; diff -Nru ffmpeg-4.2.2/libavformat/mca.c ffmpeg-4.4/libavformat/mca.c --- ffmpeg-4.2.2/libavformat/mca.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/mca.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,229 @@ +/* + * MCA demuxer + * Copyright (c) 2020 Zixing Liu + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "avio_internal.h" +#include "internal.h" + +typedef struct MCADemuxContext { + uint32_t block_count; + uint16_t block_size; + uint32_t current_block; + uint32_t data_start; + uint32_t samples_per_block; +} MCADemuxContext; + +static int probe(const AVProbeData *p) +{ + if (AV_RL32(p->buf) == MKTAG('M', 'A', 'D', 'P') && + AV_RL16(p->buf + 4) <= 0x5) + return AVPROBE_SCORE_MAX / 3 * 2; + return 0; +} + +static int read_header(AVFormatContext *s) +{ + AVStream *st; + MCADemuxContext *m = s->priv_data; + AVCodecParameters *par; + int64_t file_size = avio_size(s->pb); + uint16_t version = 0; + uint32_t header_size, data_size, data_offset, loop_start, loop_end, + nb_samples, nb_metadata, coef_offset = 0; + int ch, ret; + int64_t ret_size; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + + // parse file headers + avio_skip(s->pb, 0x4); // skip the file magic + version = avio_rl16(s->pb); + avio_skip(s->pb, 0x2); // padding + par->channels = avio_r8(s->pb); + avio_skip(s->pb, 0x1); // padding + m->block_size = avio_rl16(s->pb); + nb_samples = avio_rl32(s->pb); + par->sample_rate = avio_rl32(s->pb); + loop_start = avio_rl32(s->pb); + loop_end = avio_rl32(s->pb); + header_size = avio_rl32(s->pb); + data_size = avio_rl32(s->pb); + avio_skip(s->pb, 0x4); + nb_metadata = avio_rl16(s->pb); + avio_skip(s->pb, 0x2); // unknown u16 field + + // samples per frame = 14; frame size = 8 (2^3) + m->samples_per_block = (m->block_size * 14) >> 3; + + if (m->samples_per_block < 1) + return AVERROR_INVALIDDATA; + + m->block_count = nb_samples / m->samples_per_block; + st->duration = nb_samples; + + // sanity checks + if (!par->channels || par->sample_rate <= 0 + || loop_start > loop_end || m->block_count < 1) + return AVERROR_INVALIDDATA; + if ((ret = av_dict_set_int(&s->metadata, "loop_start", + av_rescale(loop_start, AV_TIME_BASE, + par->sample_rate), 0)) < 0) + return ret; + if ((ret = av_dict_set_int(&s->metadata, "loop_end", + av_rescale(loop_end, AV_TIME_BASE, + par->sample_rate), 0)) < 0) + return ret; + if ((32 + 4 + m->block_size) > (INT_MAX / par->channels) || + (32 + 4 + m->block_size) * par->channels > INT_MAX - 8) + return AVERROR_INVALIDDATA; + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + + if (version <= 4) { + // version <= 4 needs to use the file size to calculate the offsets + if (file_size < 0) { + return AVERROR(EIO); + } + if (file_size - data_size > UINT32_MAX) + return AVERROR_INVALIDDATA; + m->data_start = file_size - data_size; + if (version <= 3) { + nb_metadata = 0; + // header_size is not available or incorrect in older versions + header_size = m->data_start; + } + } else if (version == 5) { + // read data_start location from the header + if (0x30 * par->channels + 0x4 > header_size) + return AVERROR_INVALIDDATA; + data_offset = header_size - 0x30 * par->channels - 0x4; + if ((ret_size = avio_seek(s->pb, data_offset, SEEK_SET)) < 0) + return ret_size; + m->data_start = avio_rl32(s->pb); + // check if the metadata is reasonable + if (file_size > 0 && (int64_t)m->data_start + data_size > file_size) { + // the header is broken beyond repair + if ((int64_t)header_size + data_size > file_size) { + av_log(s, AV_LOG_ERROR, + "MCA metadata corrupted, unable to determine the data offset.\n"); + return AVERROR_INVALIDDATA; + } + // recover the data_start information from the data size + av_log(s, AV_LOG_WARNING, + "Incorrect header size found in metadata, " + "header size approximated from the data size\n"); + if (file_size - data_offset > UINT32_MAX) + return AVERROR_INVALIDDATA; + m->data_start = file_size - data_size; + } + } else { + avpriv_request_sample(s, "version %d", version); + return AVERROR_PATCHWELCOME; + } + + // coefficient alignment = 0x30; metadata size = 0x14 + if (0x30 * par->channels + nb_metadata * 0x14 > header_size) + return AVERROR_INVALIDDATA; + coef_offset = + header_size - 0x30 * par->channels + nb_metadata * 0x14; + + st->start_time = 0; + par->codec_id = AV_CODEC_ID_ADPCM_THP_LE; + + ret = ff_alloc_extradata(st->codecpar, 32 * par->channels); + if (ret < 0) + return ret; + + if ((ret_size = avio_seek(s->pb, coef_offset, SEEK_SET)) < 0) + return ret_size; + for (ch = 0; ch < par->channels; ch++) { + if ((ret = ffio_read_size(s->pb, par->extradata + ch * 32, 32)) < 0) + return ret; + // 0x30 (alignment) - 0x20 (actual size, 32) = 0x10 (padding) + avio_skip(s->pb, 0x10); + } + + // seek to the beginning of the adpcm data + // there are some files where the adpcm audio data is not immediately after the header + if ((ret_size = avio_seek(s->pb, m->data_start, SEEK_SET)) < 0) + return ret_size; + + return 0; +} + +static int read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVCodecParameters *par = s->streams[0]->codecpar; + MCADemuxContext *m = s->priv_data; + uint16_t size = m->block_size; + uint32_t samples = m->samples_per_block; + int ret = 0; + + if (avio_feof(s->pb)) + return AVERROR_EOF; + m->current_block++; + if (m->current_block > m->block_count) + return AVERROR_EOF; + + if ((ret = av_get_packet(s->pb, pkt, size * par->channels)) < 0) + return ret; + pkt->duration = samples; + pkt->stream_index = 0; + + return 0; +} + +static int read_seek(AVFormatContext *s, int stream_index, + int64_t timestamp, int flags) +{ + AVStream *st = s->streams[stream_index]; + MCADemuxContext *m = s->priv_data; + int64_t ret = 0; + + if (timestamp < 0) + timestamp = 0; + timestamp /= m->samples_per_block; + if (timestamp >= m->block_count) + timestamp = m->block_count - 1; + ret = avio_seek(s->pb, m->data_start + timestamp * m->block_size * + st->codecpar->channels, SEEK_SET); + if (ret < 0) + return ret; + + m->current_block = timestamp; + ff_update_cur_dts(s, st, timestamp * m->samples_per_block); + return 0; +} + +AVInputFormat ff_mca_demuxer = { + .name = "mca", + .long_name = NULL_IF_CONFIG_SMALL("MCA Audio Format"), + .priv_data_size = sizeof(MCADemuxContext), + .read_probe = probe, + .read_header = read_header, + .read_packet = read_packet, + .read_seek = read_seek, + .extensions = "mca", +}; diff -Nru ffmpeg-4.2.2/libavformat/mccdec.c ffmpeg-4.4/libavformat/mccdec.c --- ffmpeg-4.2.2/libavformat/mccdec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/mccdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,238 @@ +/* + * MCC subtitle demuxer + * Copyright (c) 2020 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 "avformat.h" +#include "internal.h" +#include "subtitles.h" +#include "libavutil/avstring.h" +#include "libavutil/bprint.h" +#include "libavutil/intreadwrite.h" + +typedef struct MCCContext { + FFDemuxSubtitlesQueue q; +} MCCContext; + +static int mcc_probe(const AVProbeData *p) +{ + char buf[28]; + FFTextReader tr; + + ff_text_init_buf(&tr, p->buf, p->buf_size); + + while (ff_text_peek_r8(&tr) == '\r' || ff_text_peek_r8(&tr) == '\n') + ff_text_r8(&tr); + + ff_text_read(&tr, buf, sizeof(buf)); + + if (!memcmp(buf, "File Format=MacCaption_MCC V", 28)) + return AVPROBE_SCORE_MAX; + + return 0; +} + +static int convert(uint8_t x) +{ + if (x >= 'a') + x -= 87; + else if (x >= 'A') + x -= 55; + else + x -= '0'; + return x; +} + +typedef struct alias { + uint8_t key; + int len; + const char *value; +} alias; + +static const alias aliases[20] = { + { .key = 16, .len = 3, .value = "\xFA\x0\x0", }, + { .key = 17, .len = 6, .value = "\xFA\x0\x0\xFA\x0\x0", }, + { .key = 18, .len = 9, .value = "\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0", }, + { .key = 19, .len = 12, .value = "\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0", }, + { .key = 20, .len = 15, .value = "\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0", }, + { .key = 21, .len = 18, .value = "\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0", }, + { .key = 22, .len = 21, .value = "\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0", }, + { .key = 23, .len = 24, .value = "\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0", }, + { .key = 24, .len = 27, .value = "\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0\xFA\x0\x0", }, + { .key = 25, .len = 3, .value = "\xFB\x80\x80", }, + { .key = 26, .len = 3, .value = "\xFC\x80\x80", }, + { .key = 27, .len = 3, .value = "\xFD\x80\x80", }, + { .key = 28, .len = 2, .value = "\x96\x69", }, + { .key = 29, .len = 2, .value = "\x61\x01", }, + { .key = 30, .len = 3, .value = "\xFC\x80\x80", }, + { .key = 31, .len = 3, .value = "\xFC\x80\x80", }, + { .key = 32, .len = 4, .value = "\xE1\x00\x00\x00", }, + { .key = 33, .len = 0, .value = NULL, }, + { .key = 34, .len = 0, .value = NULL, }, + { .key = 35, .len = 1, .value = "\x0", }, +}; + +static int mcc_read_header(AVFormatContext *s) +{ + MCCContext *mcc = s->priv_data; + AVStream *st = avformat_new_stream(s, NULL); + AVRational rate; + int64_t ts, pos; + uint8_t out[4096]; + char line[4096]; + FFTextReader tr; + int ret = 0; + + ff_text_init_avio(s, &tr, s->pb); + + if (!st) + return AVERROR(ENOMEM); + st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codecpar->codec_id = AV_CODEC_ID_EIA_608; + avpriv_set_pts_info(st, 64, 1, 30); + + while (!ff_text_eof(&tr)) { + int hh, mm, ss, fs, i = 0, j = 0; + int start = 12, count = 0; + AVPacket *sub; + char *lline; + + ff_subtitles_read_line(&tr, line, sizeof(line)); + if (!strncmp(line, "File Format=MacCaption_MCC V", 28)) + continue; + if (!strncmp(line, "//", 2)) + continue; + if (!strncmp(line, "Time Code Rate=", 15)) { + char *rate_str = line + 15; + char *df = NULL; + int num = -1, den = -1; + + if (rate_str[0]) { + num = strtol(rate_str, &df, 10); + den = 1; + if (df && !av_strncasecmp(df, "DF", 2)) { + num *= 1000; + den = 1001; + } + } + + if (num > 0 && den > 0) { + rate = av_make_q(num, den); + avpriv_set_pts_info(st, 64, rate.den, rate.num); + } + continue; + } + + if (av_sscanf(line, "%d:%d:%d:%d", &hh, &mm, &ss, &fs) != 4) + continue; + + ts = av_sat_add64(av_rescale(hh * 3600LL + mm * 60LL + ss, rate.num, rate.den), fs); + + lline = (char *)&line; + lline += 12; + pos = ff_text_pos(&tr); + + while (lline[i]) { + uint8_t v = convert(lline[i]); + + if (v >= 16 && v <= 35) { + int idx = v - 16; + if (aliases[idx].len) { + if (j >= sizeof(out) - 1 - aliases[idx].len) { + j = 0; + break; + } + memcpy(out + j, aliases[idx].value, aliases[idx].len); + j += aliases[idx].len; + } + } else { + uint8_t vv; + + if (i + 13 >= sizeof(line) - 1) + break; + vv = convert(lline[i + 1]); + if (j >= sizeof(out) - 1) { + j = 0; + break; + } + out[j++] = vv | (v << 4); + i++; + } + + i++; + } + out[j] = 0; + + if (out[7] & 0x80) + start += 4; + count = (out[11] & 0x1f) * 3; + if (j < start + count + 1) + continue; + + if (!count) + continue; + sub = ff_subtitles_queue_insert(&mcc->q, out + start, count, 0); + if (!sub) + goto fail; + + sub->pos = pos; + sub->pts = ts; + sub->duration = 1; + } + + ff_subtitles_queue_finalize(s, &mcc->q); + + return ret; +fail: + ff_subtitles_queue_clean(&mcc->q); + return AVERROR(ENOMEM); +} + +static int mcc_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + MCCContext *mcc = s->priv_data; + return ff_subtitles_queue_read_packet(&mcc->q, pkt); +} + +static int mcc_read_seek(AVFormatContext *s, int stream_index, + int64_t min_ts, int64_t ts, int64_t max_ts, int flags) +{ + MCCContext *mcc = s->priv_data; + return ff_subtitles_queue_seek(&mcc->q, s, stream_index, + min_ts, ts, max_ts, flags); +} + +static int mcc_read_close(AVFormatContext *s) +{ + MCCContext *mcc = s->priv_data; + ff_subtitles_queue_clean(&mcc->q); + return 0; +} + +AVInputFormat ff_mcc_demuxer = { + .name = "mcc", + .long_name = NULL_IF_CONFIG_SMALL("MacCaption"), + .priv_data_size = sizeof(MCCContext), + .read_probe = mcc_probe, + .read_header = mcc_read_header, + .read_packet = mcc_read_packet, + .read_seek2 = mcc_read_seek, + .read_close = mcc_read_close, + .extensions = "mcc", +}; diff -Nru ffmpeg-4.2.2/libavformat/microdvddec.c ffmpeg-4.4/libavformat/microdvddec.c --- ffmpeg-4.2.2/libavformat/microdvddec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/microdvddec.c 2021-04-08 21:28:40.000000000 +0000 @@ -65,12 +65,12 @@ return AV_NOPTS_VALUE; } -static int get_duration(const char *buf) +static int64_t get_duration(const char *buf) { int frame_start, frame_end; if (sscanf(buf, "{%d}{%d}", &frame_start, &frame_end) == 2) - return frame_end - frame_start; + return frame_end - (int64_t)frame_start; return -1; } @@ -81,7 +81,7 @@ AVRational pts_info = (AVRational){ 2997, 125 }; /* default: 23.976 fps */ MicroDVDContext *microdvd = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); - int i = 0; + int i = 0, ret; char line_buf[MAX_LINESIZE]; int has_real_fps = 0; @@ -94,6 +94,7 @@ int64_t pos = avio_tell(s->pb); int len = ff_get_line(s->pb, line_buf, sizeof(line_buf)); char *line = line_buf; + int64_t pts; if (!strncmp(line, bom, 3)) line += 3; @@ -117,10 +118,11 @@ continue; } if (!st->codecpar->extradata && sscanf(line, "{DEFAULT}{}%c", &c) == 1) { - st->codecpar->extradata = av_strdup(line + 11); - if (!st->codecpar->extradata) - return AVERROR(ENOMEM); - st->codecpar->extradata_size = strlen(st->codecpar->extradata) + 1; + int size = strlen(line + 11); + ret = ff_alloc_extradata(st->codecpar, size); + if (ret < 0) + goto fail; + memcpy(st->codecpar->extradata, line + 11, size); continue; } } @@ -136,11 +138,16 @@ SKIP_FRAME_ID; if (!*p) continue; + pts = get_pts(line); + if (pts == AV_NOPTS_VALUE) + continue; sub = ff_subtitles_queue_insert(µdvd->q, p, strlen(p), 0); - if (!sub) - return AVERROR(ENOMEM); + if (!sub) { + ret = AVERROR(ENOMEM); + goto fail; + } sub->pos = pos; - sub->pts = get_pts(line); + sub->pts = pts; sub->duration = get_duration(line); } ff_subtitles_queue_finalize(s, µdvd->q); @@ -155,6 +162,9 @@ st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codecpar->codec_id = AV_CODEC_ID_MICRODVD; return 0; +fail: + ff_subtitles_queue_clean(µdvd->q); + return ret; } static int microdvd_read_packet(AVFormatContext *s, AVPacket *pkt) diff -Nru ffmpeg-4.2.2/libavformat/microdvdenc.c ffmpeg-4.4/libavformat/microdvdenc.c --- ffmpeg-4.2.2/libavformat/microdvdenc.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/microdvdenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -36,7 +36,7 @@ if (par->extradata && par->extradata_size > 0) { avio_write(s->pb, "{DEFAULT}{}", 11); avio_write(s->pb, par->extradata, par->extradata_size); - avio_flush(s->pb); + avio_w8(s->pb, '\n'); } avpriv_set_pts_info(s->streams[0], 64, framerate.num, framerate.den); @@ -51,7 +51,7 @@ else avio_printf(avf->pb, "{%"PRId64"}", pkt->pts + pkt->duration); avio_write(avf->pb, pkt->data, pkt->size); - avio_write(avf->pb, "\n", 1); + avio_w8(avf->pb, '\n'); return 0; } diff -Nru ffmpeg-4.2.2/libavformat/mlvdec.c ffmpeg-4.4/libavformat/mlvdec.c --- ffmpeg-4.2.2/libavformat/mlvdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mlvdec.c 2021-04-08 21:28:27.000000000 +0000 @@ -52,6 +52,8 @@ uint64_t pts; } MlvContext; +static int read_close(AVFormatContext *s); + static int probe(const AVProbeData *p) { if (AV_RL32(p->buf) == MKTAG('M','L','V','I') && @@ -130,23 +132,25 @@ break; size -= 16; if (vst && type == MKTAG('R','A','W','I') && size >= 164) { - vst->codecpar->width = avio_rl16(pb); - vst->codecpar->height = avio_rl16(pb); - ret = av_image_check_size(vst->codecpar->width, vst->codecpar->height, 0, avctx); + unsigned width = avio_rl16(pb); + unsigned height = avio_rl16(pb); + unsigned bits_per_coded_sample; + ret = av_image_check_size(width, height, 0, avctx); if (ret < 0) return ret; if (avio_rl32(pb) != 1) avpriv_request_sample(avctx, "raw api version"); avio_skip(pb, 20); // pointer, width, height, pitch, frame_size - vst->codecpar->bits_per_coded_sample = avio_rl32(pb); - if (vst->codecpar->bits_per_coded_sample < 0 || - vst->codecpar->bits_per_coded_sample > (INT_MAX - 7) / (vst->codecpar->width * vst->codecpar->height)) { + bits_per_coded_sample = avio_rl32(pb); + if (bits_per_coded_sample > (INT_MAX - 7) / (width * height)) { av_log(avctx, AV_LOG_ERROR, - "invalid bits_per_coded_sample %d (size: %dx%d)\n", - vst->codecpar->bits_per_coded_sample, - vst->codecpar->width, vst->codecpar->height); + "invalid bits_per_coded_sample %u (size: %ux%u)\n", + bits_per_coded_sample, width, height); return AVERROR_INVALIDDATA; } + vst->codecpar->width = width; + vst->codecpar->height = height; + vst->codecpar->bits_per_coded_sample = bits_per_coded_sample; avio_skip(pb, 8 + 16 + 24); // black_level, white_level, xywh, active_area, exposure_bias if (avio_rl32(pb) != 0x2010100) /* RGGB */ avpriv_request_sample(avctx, "cfa_pattern"); @@ -376,6 +380,7 @@ if ((vst && !vst->nb_index_entries) || (ast && !ast->nb_index_entries)) { av_log(avctx, AV_LOG_ERROR, "no index entries found\n"); + read_close(avctx); return AVERROR_INVALIDDATA; } @@ -393,10 +398,14 @@ { MlvContext *mlv = avctx->priv_data; AVIOContext *pb; - AVStream *st = avctx->streams[mlv->stream_index]; + AVStream *st; int index, ret; unsigned int size, space; + if (!avctx->nb_streams) + return AVERROR_EOF; + + st = avctx->streams[mlv->stream_index]; if (mlv->pts >= st->duration) return AVERROR_EOF; @@ -407,6 +416,10 @@ } pb = mlv->pb[st->index_entries[index].size]; + if (!pb) { + ret = FFERROR_REDO; + goto next_packet; + } avio_seek(pb, st->index_entries[index].pos, SEEK_SET); avio_skip(pb, 4); // blockType @@ -435,12 +448,14 @@ pkt->stream_index = mlv->stream_index; pkt->pts = mlv->pts; + ret = 0; +next_packet: mlv->stream_index++; if (mlv->stream_index == avctx->nb_streams) { mlv->stream_index = 0; mlv->pts++; } - return 0; + return ret; } static int read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags) @@ -462,8 +477,7 @@ MlvContext *mlv = s->priv_data; int i; for (i = 0; i < 100; i++) - if (mlv->pb[i]) - ff_format_io_close(s, &mlv->pb[i]); + ff_format_io_close(s, &mlv->pb[i]); return 0; } diff -Nru ffmpeg-4.2.2/libavformat/mm.c ffmpeg-4.4/libavformat/mm.c --- ffmpeg-4.2.2/libavformat/mm.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mm.c 2020-07-11 10:39:32.000000000 +0000 @@ -142,6 +142,7 @@ AVIOContext *pb = s->pb; unsigned char preamble[MM_PREAMBLE_SIZE]; unsigned int type, length; + int ret; while(1) { @@ -161,8 +162,8 @@ case MM_TYPE_INTRA_HHV : case MM_TYPE_INTER_HHV : /* output preamble + data */ - if (av_new_packet(pkt, length + MM_PREAMBLE_SIZE)) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, length + MM_PREAMBLE_SIZE)) < 0) + return ret; memcpy(pkt->data, preamble, MM_PREAMBLE_SIZE); if (avio_read(pb, pkt->data + MM_PREAMBLE_SIZE, length) != length) return AVERROR(EIO); @@ -174,8 +175,10 @@ return 0; case MM_TYPE_AUDIO : - if (av_get_packet(s->pb, pkt, length)<0) - return AVERROR(ENOMEM); + if (s->nb_streams < 2) + return AVERROR_INVALIDDATA; + if ((ret = av_get_packet(s->pb, pkt, length)) < 0) + return ret; pkt->stream_index = 1; pkt->pts = mm->audio_pts++; return 0; diff -Nru ffmpeg-4.2.2/libavformat/mmf.c ffmpeg-4.4/libavformat/mmf.c --- ffmpeg-4.2.2/libavformat/mmf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mmf.c 2020-07-11 10:39:30.000000000 +0000 @@ -123,8 +123,6 @@ avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codecpar->sample_rate); - avio_flush(pb); - return 0; } @@ -173,8 +171,6 @@ avio_write(pb, "\x00\x00\x00\x00", 4); avio_seek(pb, pos, SEEK_SET); - - avio_flush(pb); } return 0; } diff -Nru ffmpeg-4.2.2/libavformat/mms.c ffmpeg-4.4/libavformat/mms.c --- ffmpeg-4.2.2/libavformat/mms.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/mms.c 2020-07-11 10:39:30.000000000 +0000 @@ -60,7 +60,7 @@ if (mms->asf_header_size < sizeof(ff_asf_guid) * 2 + 22 || memcmp(p, ff_asf_header, sizeof(ff_asf_guid))) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Corrupt stream (invalid ASF header, size=%d)\n", mms->asf_header_size); return AVERROR_INVALIDDATA; @@ -77,7 +77,7 @@ chunksize = AV_RL64(p + sizeof(ff_asf_guid)); } if (!chunksize || chunksize > end - p) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Corrupt stream (header chunksize %"PRId64" is invalid)\n", chunksize); return AVERROR_INVALIDDATA; @@ -87,7 +87,7 @@ if (end - p > sizeof(ff_asf_guid) * 2 + 68) { mms->asf_packet_len = AV_RL32(p + sizeof(ff_asf_guid) * 2 + 64); if (mms->asf_packet_len <= 0 || mms->asf_packet_len > sizeof(mms->in_buffer)) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Corrupt stream (too large pkt_len %d)\n", mms->asf_packet_len); return AVERROR_INVALIDDATA; @@ -110,7 +110,7 @@ mms->streams[mms->stream_num].id = stream_id; mms->stream_num++; } else { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Corrupt stream (too many A/V streams)\n"); return AVERROR_INVALIDDATA; } @@ -121,7 +121,7 @@ uint64_t skip_bytes = 88; while (stream_count--) { if (end - p < skip_bytes + 4) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Corrupt stream (next stream name length is not in the buffer)\n"); return AVERROR_INVALIDDATA; } @@ -129,14 +129,14 @@ } while (ext_len_count--) { if (end - p < skip_bytes + 22) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Corrupt stream (next extension system info length is not in the buffer)\n"); return AVERROR_INVALIDDATA; } skip_bytes += 22 + AV_RL32(p + skip_bytes + 18); } if (end - p < skip_bytes) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Corrupt stream (the last extension system info length is invalid)\n"); return AVERROR_INVALIDDATA; } @@ -146,7 +146,7 @@ } else if (!memcmp(p, ff_asf_head1_guid, sizeof(ff_asf_guid))) { chunksize = 46; // see references [2] section 3.4. This should be set 46. if (chunksize > end - p) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Corrupt stream (header chunksize %"PRId64" is invalid)\n", chunksize); return AVERROR_INVALIDDATA; diff -Nru ffmpeg-4.2.2/libavformat/mmsh.c ffmpeg-4.4/libavformat/mmsh.c --- ffmpeg-4.2.2/libavformat/mmsh.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/mmsh.c 2020-07-11 10:39:30.000000000 +0000 @@ -65,8 +65,7 @@ { MMSHContext *mmsh = (MMSHContext *)h->priv_data; MMSContext *mms = &mmsh->mms; - if (mms->mms_hd) - ffurl_closep(&mms->mms_hd); + ffurl_closep(&mms->mms_hd); av_freep(&mms->streams); av_freep(&mms->asf_header); return 0; @@ -265,7 +264,7 @@ } // close the socket and then reopen it for sending the second play request. - ffurl_close(mms->mms_hd); + ffurl_closep(&mms->mms_hd); memset(headers, 0, sizeof(headers)); if ((err = ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ, &h->interrupt_callback)) < 0) { diff -Nru ffmpeg-4.2.2/libavformat/mmst.c ffmpeg-4.4/libavformat/mmst.c --- ffmpeg-4.2.2/libavformat/mmst.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/mmst.c 2020-07-11 10:39:30.000000000 +0000 @@ -141,7 +141,7 @@ // write it out. write_result= ffurl_write(mms->mms_hd, mms->out_buffer, exact_length); if(write_result != exact_length) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Failed to write data of length %d: %d (%s)\n", exact_length, write_result, write_result < 0 ? strerror(AVUNERROR(write_result)) : @@ -215,11 +215,11 @@ static void handle_packet_stream_changing_type(MMSTContext *mmst) { MMSContext *mms = &mmst->mms; - av_log(NULL, AV_LOG_TRACE, "Stream changing!\n"); + av_log(mms->mms_hd, AV_LOG_TRACE, "Stream changing!\n"); // 40 is the packet header size, 7 is the prefix size. mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7); - av_log(NULL, AV_LOG_TRACE, "Changed header prefix to 0x%x", mmst->header_packet_id); + av_log(mms->mms_hd, AV_LOG_TRACE, "Changed header prefix to 0x%x", mmst->header_packet_id); } static int send_keepalive_packet(MMSTContext *mmst) @@ -251,12 +251,12 @@ read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer, 8); if (read_result != 8) { if(read_result < 0) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Error reading packet header: %d (%s)\n", read_result, strerror(AVUNERROR(read_result))); packet_type = SC_PKT_CANCEL; } else { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "The server closed the connection\n"); packet_type = SC_PKT_NO_DATA; } @@ -270,7 +270,7 @@ mmst->incoming_flags= mms->in_buffer[3]; read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer+8, 4); if(read_result != 4) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Reading command packet length failed: %d (%s)\n", read_result, read_result < 0 ? strerror(AVUNERROR(read_result)) : @@ -279,11 +279,11 @@ } length_remaining= AV_RL32(mms->in_buffer+8) + 4; - av_log(NULL, AV_LOG_TRACE, "Length remaining is %d\n", length_remaining); + av_log(mms->mms_hd, AV_LOG_TRACE, "Length remaining is %d\n", length_remaining); // read the rest of the packet. if (length_remaining < 0 || length_remaining > sizeof(mms->in_buffer) - 12) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Incoming packet length %d exceeds bufsize %"SIZE_SPECIFIER"\n", length_remaining, sizeof(mms->in_buffer) - 12); return AVERROR_INVALIDDATA; @@ -291,7 +291,7 @@ read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer + 12, length_remaining) ; if (read_result != length_remaining) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Reading pkt data (length=%d) failed: %d (%s)\n", length_remaining, read_result, read_result < 0 ? strerror(AVUNERROR(read_result)) : @@ -300,7 +300,7 @@ } packet_type= AV_RL16(mms->in_buffer+36); if (read_result >= 44 && (hr = AV_RL32(mms->in_buffer + 40))) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Server sent a message with packet type 0x%x and error status code 0x%08x\n", packet_type, hr); return AVERROR(EINVAL); } @@ -319,7 +319,7 @@ if (length_remaining < 0 || length_remaining > sizeof(mms->in_buffer) - 8) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Data length %d is invalid or too large (max=%"SIZE_SPECIFIER")\n", length_remaining, sizeof(mms->in_buffer)); return AVERROR_INVALIDDATA; @@ -328,7 +328,7 @@ mms->read_in_ptr = mms->in_buffer; read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer, length_remaining); if(read_result != length_remaining) { - av_log(NULL, AV_LOG_ERROR, + av_log(mms->mms_hd, AV_LOG_ERROR, "Failed to read packet data of size %d: %d (%s)\n", length_remaining, read_result, read_result < 0 ? strerror(AVUNERROR(read_result)) : @@ -358,7 +358,7 @@ } else if(packet_id_type == mmst->packet_id) { packet_type = SC_PKT_ASF_MEDIA; } else { - av_log(NULL, AV_LOG_TRACE, "packet id type %d is old.", packet_id_type); + av_log(mms->mms_hd, AV_LOG_TRACE, "packet id type %d is old.", packet_id_type); continue; } } @@ -473,7 +473,7 @@ MMSContext *mms = &mmst->mms; if(mms->mms_hd) { send_close_packet(mmst); - ffurl_close(mms->mms_hd); + ffurl_closep(&mms->mms_hd); } /* free all separately allocated pointers in mms */ @@ -555,14 +555,14 @@ if (err) goto fail; if((mmst->incoming_flags != 0X08) && (mmst->incoming_flags != 0X0C)) { - av_log(NULL, AV_LOG_ERROR, + av_log(h, AV_LOG_ERROR, "The server does not support MMST (try MMSH or RTSP)\n"); err = AVERROR(EINVAL); goto fail; } err = ff_mms_asf_header_parser(mms); if (err) { - av_log(NULL, AV_LOG_TRACE, "asf header parsed failed!\n"); + av_log(h, AV_LOG_TRACE, "asf header parsed failed!\n"); goto fail; } mms->header_parsed = 1; @@ -579,11 +579,11 @@ if (err) { goto fail; } - av_log(NULL, AV_LOG_TRACE, "Leaving open (success)\n"); + av_log(h, AV_LOG_TRACE, "Leaving open (success)\n"); return 0; fail: mms_close(h); - av_log(NULL, AV_LOG_TRACE, "Leaving open (failure: %d)\n", err); + av_log(mms->mms_hd, AV_LOG_TRACE, "Leaving open (failure: %d)\n", err); return err; } @@ -608,7 +608,7 @@ int err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_MEDIA); if (err == 0) { if(mms->remaining_in_len>mms->asf_packet_len) { - av_log(NULL, AV_LOG_ERROR, + av_log(h, AV_LOG_ERROR, "Incoming pktlen %d is larger than ASF pktsize %d\n", mms->remaining_in_len, mms->asf_packet_len); result= AVERROR(EIO); @@ -616,12 +616,12 @@ // copy the data to the packet buffer. result = ff_mms_read_data(mms, buf, size); if (result == 0) { - av_log(NULL, AV_LOG_TRACE, "Read ASF media packet size is zero!\n"); + av_log(h, AV_LOG_TRACE, "Read ASF media packet size is zero!\n"); break; } } } else { - av_log(NULL, AV_LOG_TRACE, "read packet error!\n"); + av_log(h, AV_LOG_TRACE, "read packet error!\n"); break; } } diff -Nru ffmpeg-4.2.2/libavformat/mods.c ffmpeg-4.4/libavformat/mods.c --- ffmpeg-4.2.2/libavformat/mods.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/mods.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,102 @@ +/* + * MODS demuxer + * Copyright (c) 2015-2016 Florian Nouwt + * Copyright (c) 2017 Adib Surani + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" + +#include "avformat.h" +#include "internal.h" + +static int mods_probe(const AVProbeData *p) +{ + if (memcmp(p->buf, "MODSN3\x0a\x00", 8)) + return 0; + if (AV_RB32(p->buf + 8) == 0) + return 0; + if (AV_RB32(p->buf + 12) == 0) + return 0; + if (AV_RB32(p->buf + 16) == 0) + return 0; + return AVPROBE_SCORE_MAX; +} + +static int mods_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + AVRational fps; + int64_t pos; + + AVStream *st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + avio_skip(pb, 8); + + st->nb_frames = avio_rl32(pb); + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_MOBICLIP; + st->codecpar->width = avio_rl32(pb); + st->codecpar->height = avio_rl32(pb); + + fps.num = avio_rl32(pb); + fps.den = 0x1000000; + avpriv_set_pts_info(st, 64, fps.den, fps.num); + + avio_skip(pb, 16); + + pos = avio_rl32(pb) + 4; + avio_seek(pb, pos, SEEK_SET); + pos = avio_rl32(pb); + avio_seek(pb, pos, SEEK_SET); + + return 0; +} + +static int mods_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVIOContext *pb = s->pb; + unsigned size; + int64_t pos; + int ret; + + if (avio_feof(pb)) + return AVERROR_EOF; + + pos = avio_tell(pb); + size = avio_rl32(pb) >> 14; + ret = av_get_packet(pb, pkt, size); + pkt->pos = pos; + pkt->stream_index = 0; + pkt->flags |= AV_PKT_FLAG_KEY; + + return ret; +} + +AVInputFormat ff_mods_demuxer = { + .name = "mods", + .long_name = NULL_IF_CONFIG_SMALL("MobiClip MODS"), + .read_probe = mods_probe, + .read_header = mods_read_header, + .read_packet = mods_read_packet, + .extensions = "mods", + .flags = AVFMT_GENERIC_INDEX, +}; diff -Nru ffmpeg-4.2.2/libavformat/moflex.c ffmpeg-4.4/libavformat/moflex.c --- ffmpeg-4.2.2/libavformat/moflex.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/moflex.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,392 @@ +/* + * MOFLEX demuxer + * Copyright (c) 2015-2016 Florian Nouwt + * Copyright (c) 2017 Adib Surani + * Copyright (c) 2020 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 "libavcodec/bytestream.h" + +#include "avformat.h" +#include "internal.h" + +typedef struct BitReader { + unsigned last; + unsigned pos; +} BitReader; + +typedef struct MOFLEXDemuxContext { + unsigned size; + int64_t pos; + int64_t ts; + int flags; + int in_block; + + BitReader br; +} MOFLEXDemuxContext; + +static int pop(BitReader *br, AVIOContext *pb) +{ + if (avio_feof(pb)) + return AVERROR_EOF; + + if ((br->pos & 7) == 0) + br->last = (unsigned)avio_r8(pb) << 24U; + else + br->last <<= 1; + + br->pos++; + return !!(br->last & 0x80000000); +} + +static int pop_int(BitReader *br, AVIOContext *pb, int n) +{ + int value = 0; + + for (int i = 0; i < n; i++) { + int ret = pop(br, pb); + + if (ret < 0) + return ret; + if (ret > INT_MAX - value - value) + return AVERROR_INVALIDDATA; + value = 2 * value + ret; + } + + return value; +} + +static int pop_length(BitReader *br, AVIOContext *pb) +{ + int ret, n = 1; + + while ((ret = pop(br, pb)) == 0) + n++; + + if (ret < 0) + return ret; + return n; +} + +static int read_var_byte(AVFormatContext *s, unsigned *out) +{ + AVIOContext *pb = s->pb; + unsigned value = 0, data; + + data = avio_r8(pb); + if (!(data & 0x80)) { + *out = data; + return 0; + } + + value = (data & 0x7F) << 7; + data = avio_r8(pb); + if (!(data & 0x80)) { + value |= data; + *out = value; + return 0; + } + + value = ((data & 0x7F) | value) << 7; + data = avio_r8(pb); + if (!(data & 0x80)) { + value |= data; + *out = value; + return 0; + } + + value = (((data & 0x7F) | value) << 7) | avio_r8(pb); + *out = value; + + return 0; +} + +static int moflex_probe(const AVProbeData *p) +{ + GetByteContext gb; + int score = 0; + + bytestream2_init(&gb, p->buf, p->buf_size); + + if (bytestream2_get_be16(&gb) != 0x4C32) + return 0; + score += 10; + + bytestream2_skip(&gb, 10); + if (bytestream2_get_be16(&gb) == 0) + return 0; + score += 5; + + while (bytestream2_get_bytes_left(&gb) > 0) { + int type = bytestream2_get_byte(&gb); + int size = bytestream2_get_byte(&gb); + + if (type == 0) { + score += 5 * (size == 0); + break; + } + if ((type == 1 && size == 12) || + (type == 2 && size == 6) || + (type == 3 && size == 13) || + (type == 4 && size == 2)) + score += 20; + bytestream2_skip(&gb, size); + } + + return FFMIN(AVPROBE_SCORE_MAX, score); +} + +static int moflex_read_sync(AVFormatContext *s) +{ + MOFLEXDemuxContext *m = s->priv_data; + AVIOContext *pb = s->pb; + + if (avio_rb16(pb) != 0x4C32) { + if (avio_feof(pb)) + return AVERROR_EOF; + avio_seek(pb, -2, SEEK_CUR); + return 1; + } + + avio_skip(pb, 2); + m->ts = avio_rb64(pb); + m->size = avio_rb16(pb) + 1; + + while (!avio_feof(pb)) { + unsigned type, ssize, codec_id = 0; + unsigned codec_type, width = 0, height = 0, sample_rate = 0, channels = 0; + int stream_index = -1; + int format; + AVRational fps; + + read_var_byte(s, &type); + read_var_byte(s, &ssize); + + switch (type) { + case 0: + if (ssize > 0) + avio_skip(pb, ssize); + return 0; + case 2: + codec_type = AVMEDIA_TYPE_AUDIO; + stream_index = avio_r8(pb); + codec_id = avio_r8(pb); + switch (codec_id) { + case 0: codec_id = AV_CODEC_ID_FASTAUDIO; break; + case 1: codec_id = AV_CODEC_ID_ADPCM_IMA_MOFLEX; break; + case 2: codec_id = AV_CODEC_ID_PCM_S16LE; break; + default: + av_log(s, AV_LOG_ERROR, "Unsupported audio codec: %d\n", codec_id); + return AVERROR_PATCHWELCOME; + } + sample_rate = avio_rb24(pb) + 1; + channels = avio_r8(pb) + 1; + break; + case 1: + case 3: + codec_type = AVMEDIA_TYPE_VIDEO; + stream_index = avio_r8(pb); + codec_id = avio_r8(pb); + switch (codec_id) { + case 0: codec_id = AV_CODEC_ID_MOBICLIP; break; + default: + 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); + width = avio_rb16(pb); + height = avio_rb16(pb); + format = AV_PIX_FMT_YUV420P; + avio_skip(pb, type == 3 ? 3 : 2); + break; + case 4: + codec_type = AVMEDIA_TYPE_DATA; + stream_index = avio_r8(pb); + avio_skip(pb, 1); + break; + } + + if (stream_index == s->nb_streams) { + AVStream *st = avformat_new_stream(s, NULL); + + if (!st) + return AVERROR(ENOMEM); + + st->codecpar->codec_type = codec_type; + st->codecpar->codec_id = codec_id; + st->codecpar->width = width; + st->codecpar->height = height; + st->codecpar->sample_rate= sample_rate; + st->codecpar->channels = channels; + st->codecpar->format = format; + st->priv_data = av_packet_alloc(); + 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); + } + } + + return 0; +} + +static int moflex_read_header(AVFormatContext *s) +{ + int ret; + + ret = moflex_read_sync(s); + if (ret < 0) + return ret; + + s->ctx_flags |= AVFMTCTX_NOHEADER; + avio_seek(s->pb, 0, SEEK_SET); + + return 0; +} + +static int moflex_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + MOFLEXDemuxContext *m = s->priv_data; + AVIOContext *pb = s->pb; + BitReader *br = &m->br; + int ret; + + while (!avio_feof(pb)) { + if (!m->in_block) { + m->pos = avio_tell(pb); + + ret = moflex_read_sync(s); + if (ret < 0) + return ret; + + m->flags = avio_r8(pb); + if (m->flags & 2) + avio_skip(pb, 2); + } + + while ((avio_tell(pb) < m->pos + m->size) && !avio_feof(pb) && avio_r8(pb)) { + int stream_index, bits, pkt_size, endframe; + AVPacket *packet; + + m->in_block = 1; + + avio_seek(pb, -1, SEEK_CUR); + br->pos = br->last = 0; + + bits = pop_length(br, pb); + if (bits < 0) + return bits; + stream_index = pop_int(br, pb, bits); + if (stream_index < 0) + return stream_index; + if (stream_index >= s->nb_streams) + return AVERROR_INVALIDDATA; + + endframe = pop(br, pb); + if (endframe < 0) + return endframe; + if (endframe) { + bits = pop_length(br, pb); + if (bits < 0) + return bits; + pop_int(br, pb, bits); + pop(br, pb); + bits = pop_length(br, pb); + if (bits < 0) + return bits; + pop_int(br, pb, bits * 2 + 26); + } + + pkt_size = pop_int(br, pb, 13) + 1; + if (pkt_size > m->size) + return AVERROR_INVALIDDATA; + packet = s->streams[stream_index]->priv_data; + if (!packet) { + avio_skip(pb, pkt_size); + continue; + } + + ret = av_append_packet(pb, packet, pkt_size); + if (ret < 0) + return ret; + if (endframe && packet->size > 0) { + av_packet_move_ref(pkt, packet); + pkt->pos = m->pos; + pkt->stream_index = stream_index; + if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + pkt->duration = 1; + if (pkt->data[0] & 0x80) + pkt->flags |= AV_PKT_FLAG_KEY; + } else { + pkt->flags |= AV_PKT_FLAG_KEY; + } + return ret; + } + } + + m->in_block = 0; + + if (m->flags % 2 == 0) { + if (m->size <= 0) + return AVERROR_INVALIDDATA; + avio_seek(pb, m->pos + m->size, SEEK_SET); + } + } + + return AVERROR_EOF; +} + +static int moflex_read_seek(AVFormatContext *s, int stream_index, + int64_t pts, int flags) +{ + MOFLEXDemuxContext *m = s->priv_data; + + m->in_block = 0; + + return -1; +} + +static int moflex_read_close(AVFormatContext *s) +{ + for (int i = 0; i < s->nb_streams; i++) { + AVPacket *packet = s->streams[i]->priv_data; + + av_packet_free(&packet); + s->streams[i]->priv_data = 0; + } + + return 0; +} + +AVInputFormat ff_moflex_demuxer = { + .name = "moflex", + .long_name = NULL_IF_CONFIG_SMALL("MobiClip MOFLEX"), + .priv_data_size = sizeof(MOFLEXDemuxContext), + .read_probe = moflex_probe, + .read_header = moflex_read_header, + .read_packet = moflex_read_packet, + .read_seek = moflex_read_seek, + .read_close = moflex_read_close, + .extensions = "moflex", + .flags = AVFMT_GENERIC_INDEX, +}; diff -Nru ffmpeg-4.2.2/libavformat/mov.c ffmpeg-4.4/libavformat/mov.c --- ffmpeg-4.2.2/libavformat/mov.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/mov.c 2021-04-08 21:28:40.000000000 +0000 @@ -46,9 +46,11 @@ #include "libavutil/spherical.h" #include "libavutil/stereo3d.h" #include "libavutil/timecode.h" +#include "libavutil/dovi_meta.h" #include "libavcodec/ac3tab.h" #include "libavcodec/flac.h" #include "libavcodec/mpegaudiodecheader.h" +#include "libavcodec/mlp_parse.h" #include "avformat.h" #include "internal.h" #include "avio_internal.h" @@ -179,7 +181,6 @@ static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len) { - AVPacket pkt; AVStream *st; MOVStreamContext *sc; enum AVCodecID id; @@ -203,12 +204,12 @@ return AVERROR(ENOMEM); st->priv_data = sc; - ret = av_get_packet(pb, &pkt, len); + ret = av_get_packet(pb, &st->attached_pic, len); if (ret < 0) return ret; - if (pkt.size >= 8 && id != AV_CODEC_ID_BMP) { - if (AV_RB64(pkt.data) == 0x89504e470d0a1a0a) { + if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) { + if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) { id = AV_CODEC_ID_PNG; } else { id = AV_CODEC_ID_MJPEG; @@ -217,7 +218,6 @@ st->disposition |= AV_DISPOSITION_ATTACHED_PIC; - st->attached_pic = pkt; st->attached_pic.stream_index = st->index; st->attached_pic.flags |= AV_PKT_FLAG_KEY; @@ -288,6 +288,8 @@ return 0; n_hmmt = avio_rb32(pb); + if (n_hmmt > len / 4) + return AVERROR_INVALIDDATA; for (i = 0; i < n_hmmt && !pb->eof_reached; i++) { int moment_time = avio_rb32(pb); avpriv_new_chapter(c->fc, i, av_make_q(1, 1000), moment_time, AV_NOPTS_VALUE, NULL); @@ -297,7 +299,7 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom) { - char tmp_key[5]; + char tmp_key[AV_FOURCC_MAX_STRING_SIZE] = {0}; char key2[32], language[4] = {0}; char *str = NULL; const char *key = NULL; @@ -402,7 +404,7 @@ if (c->itunes_metadata && atom.size > 8) { int data_size = avio_rb32(pb); int tag = avio_rl32(pb); - if (tag == MKTAG('d','a','t','a') && data_size <= atom.size) { + if (tag == MKTAG('d','a','t','a') && data_size <= atom.size && data_size >= 16) { data_type = avio_rb32(pb); // type avio_rb32(pb); // unknown str_size = data_size - 16; @@ -444,8 +446,7 @@ str_size = atom.size; if (c->export_all && !key) { - snprintf(tmp_key, 5, "%.4s", (char*)&atom.type); - key = tmp_key; + key = av_fourcc_make_string(tmp_key, atom.type); } if (!key) @@ -588,7 +589,12 @@ entries > (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 || entries >= UINT_MAX / sizeof(*sc->drefs)) return AVERROR_INVALIDDATA; - sc->drefs_count = 0; + + for (i = 0; i < sc->drefs_count; i++) { + MOVDref *dref = &sc->drefs[i]; + av_freep(&dref->path); + av_freep(&dref->dir); + } av_free(sc->drefs); sc->drefs_count = 0; sc->drefs = av_mallocz(entries * sizeof(*sc->drefs)); @@ -644,7 +650,7 @@ avio_skip(pb, 16); for (type = 0; type != -1 && avio_tell(pb) < next; ) { - if(avio_feof(pb)) + if (avio_feof(pb)) return AVERROR_EOF; type = avio_rb16(pb); len = avio_rb16(pb); @@ -857,26 +863,20 @@ static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom) { - const uint32_t ddts_size = 20; +#define DDTS_SIZE 20 + uint8_t buf[DDTS_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; AVStream *st = NULL; - uint8_t *buf = NULL; uint32_t frame_duration_code = 0; uint32_t channel_layout_code = 0; GetBitContext gb; + int ret; - buf = av_malloc(ddts_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!buf) { - return AVERROR(ENOMEM); - } - if (avio_read(pb, buf, ddts_size) < ddts_size) { - av_free(buf); - return AVERROR_INVALIDDATA; - } + if ((ret = ffio_read_size(pb, buf, DDTS_SIZE)) < 0) + return ret; - init_get_bits(&gb, buf, 8*ddts_size); + init_get_bits(&gb, buf, 8 * DDTS_SIZE); if (c->fc->nb_streams < 1) { - av_free(buf); return 0; } st = c->fc->streams[c->fc->nb_streams-1]; @@ -884,7 +884,6 @@ st->codecpar->sample_rate = get_bits_long(&gb, 32); if (st->codecpar->sample_rate <= 0) { av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate); - av_free(buf); return AVERROR_INVALIDDATA; } skip_bits_long(&gb, 32); /* max bitrate */ @@ -901,7 +900,7 @@ (frame_duration_code == 3) ? 4096 : 0; if (channel_layout_code > 0xff) { - av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout"); + av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout\n"); } st->codecpar->channel_layout = ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) | @@ -912,7 +911,6 @@ ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0); st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout); - av_free(buf); return 0; } @@ -1004,6 +1002,7 @@ sha = av_sha_alloc(); if (!sha) return AVERROR(ENOMEM); + av_free(c->aes_decrypt); c->aes_decrypt = av_aes_alloc(); if (!c->aes_decrypt) { ret = AVERROR(ENOMEM); @@ -1083,6 +1082,30 @@ return ret; } +static int mov_aaxc_crypto(MOVContext *c) +{ + if (c->audible_key_size != 16) { + av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_key value needs to be 16 bytes!\n"); + return AVERROR(EINVAL); + } + + if (c->audible_iv_size != 16) { + av_log(c->fc, AV_LOG_FATAL, "[aaxc] audible_iv value needs to be 16 bytes!\n"); + return AVERROR(EINVAL); + } + + c->aes_decrypt = av_aes_alloc(); + if (!c->aes_decrypt) { + return AVERROR(ENOMEM); + } + + memcpy(c->file_key, c->audible_key, 16); + memcpy(c->file_iv, c->audible_iv, 16); + c->aax_mode = 1; + + return 0; +} + // Audible AAX (and AAX+) bytestream decryption static int aax_filter(uint8_t *input, int size, MOVContext *c) { @@ -1116,7 +1139,7 @@ av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0); comp_brand_size = atom.size - 8; - if (comp_brand_size < 0) + if (comp_brand_size < 0 || comp_brand_size == INT_MAX) return AVERROR_INVALIDDATA; comp_brands_str = av_malloc(comp_brand_size + 1); /* Add null terminator */ if (!comp_brands_str) @@ -1128,8 +1151,13 @@ return ret; } comp_brands_str[comp_brand_size] = 0; - av_dict_set(&c->fc->metadata, "compatible_brands", comp_brands_str, 0); - av_freep(&comp_brands_str); + av_dict_set(&c->fc->metadata, "compatible_brands", + comp_brands_str, AV_DICT_DONT_STRDUP_VAL); + + // Logic for handling Audible's .aaxc files + if (!strcmp(type, "aaxc")) { + mov_aaxc_crypto(c); + } return 0; } @@ -1251,6 +1279,10 @@ if (track_id >= 0) { frag_stream_info = get_frag_stream_info(frag_index, index, track_id); + if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE) + return frag_stream_info->sidx_pts; + if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE) + return frag_stream_info->first_tfra_pts; return frag_stream_info->sidx_pts; } @@ -1315,7 +1347,7 @@ &c->frag_index.allocated_size, (c->frag_index.nb_items + 1) * sizeof(*c->frag_index.item)); - if(!item) + if (!item) return -1; c->frag_index.item = item; @@ -1326,12 +1358,15 @@ for (i = 0; i < c->fc->nb_streams; i++) { // Avoid building frag index if streams lack track id. - if (c->fc->streams[i]->id < 0) + if (c->fc->streams[i]->id < 0) { + av_free(frag_stream_info); return AVERROR_INVALIDDATA; + } frag_stream_info[i].id = c->fc->streams[i]->id; frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE; frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE; + frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE; frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE; frag_stream_info[i].index_entry = -1; frag_stream_info[i].encryption_index = NULL; @@ -1393,14 +1428,14 @@ return mov_read_default(c, pb, atom); } -static void mov_metadata_creation_time(AVDictionary **metadata, int64_t time) +static void mov_metadata_creation_time(AVDictionary **metadata, int64_t time, void *logctx) { if (time) { - if(time >= 2082844800) + if (time >= 2082844800) time -= 2082844800; /* seconds between 1904-01-01 and Epoch */ if ((int64_t)(time * 1000000ULL) / 1000000 != time) { - av_log(NULL, AV_LOG_DEBUG, "creation_time is not representable\n"); + av_log(logctx, AV_LOG_DEBUG, "creation_time is not representable\n"); return; } @@ -1440,7 +1475,7 @@ creation_time = avio_rb32(pb); avio_rb32(pb); /* modification time */ } - mov_metadata_creation_time(&st->metadata, creation_time); + mov_metadata_creation_time(&st->metadata, creation_time, c->fc); sc->time_scale = avio_rb32(pb); if (sc->time_scale <= 0) { @@ -1471,7 +1506,7 @@ creation_time = avio_rb32(pb); avio_rb32(pb); /* modification time */ } - mov_metadata_creation_time(&c->fc->metadata, creation_time); + mov_metadata_creation_time(&c->fc->metadata, creation_time, c->fc); c->time_scale = avio_rb32(pb); /* time scale */ if (c->time_scale <= 0) { av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale); @@ -1480,9 +1515,9 @@ av_log(c->fc, AV_LOG_TRACE, "time scale = %i\n", c->time_scale); c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */ - // set the AVCodecContext duration because the duration of individual tracks + // set the AVFormatContext duration because the duration of individual tracks // may be inaccurate - if (c->time_scale > 0 && !c->trex_data) + if (!c->trex_data) c->fc->duration = av_rescale(c->duration, AV_TIME_BASE, c->time_scale); avio_rb32(pb); /* preferred scale */ @@ -1543,6 +1578,7 @@ static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; + uint8_t *icc_profile; char color_parameter_type[5] = { 0 }; uint16_t color_primaries, color_trc, color_matrix; int ret; @@ -1555,41 +1591,50 @@ if (ret < 0) return ret; if (strncmp(color_parameter_type, "nclx", 4) && - strncmp(color_parameter_type, "nclc", 4)) { + strncmp(color_parameter_type, "nclc", 4) && + strncmp(color_parameter_type, "prof", 4)) { av_log(c->fc, AV_LOG_WARNING, "unsupported color_parameter_type %s\n", color_parameter_type); return 0; } - color_primaries = avio_rb16(pb); - color_trc = avio_rb16(pb); - color_matrix = avio_rb16(pb); - - av_log(c->fc, AV_LOG_TRACE, - "%s: pri %d trc %d matrix %d", - color_parameter_type, color_primaries, color_trc, color_matrix); - - if (!strncmp(color_parameter_type, "nclx", 4)) { - uint8_t color_range = avio_r8(pb) >> 7; - av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range); - if (color_range) - st->codecpar->color_range = AVCOL_RANGE_JPEG; - else - st->codecpar->color_range = AVCOL_RANGE_MPEG; - } + if (!strncmp(color_parameter_type, "prof", 4)) { + icc_profile = av_stream_new_side_data(st, AV_PKT_DATA_ICC_PROFILE, atom.size - 4); + if (!icc_profile) + return AVERROR(ENOMEM); + ret = ffio_read_size(pb, icc_profile, atom.size - 4); + if (ret < 0) + return ret; + } else { + color_primaries = avio_rb16(pb); + color_trc = avio_rb16(pb); + color_matrix = avio_rb16(pb); - if (!av_color_primaries_name(color_primaries)) - color_primaries = AVCOL_PRI_UNSPECIFIED; - if (!av_color_transfer_name(color_trc)) - color_trc = AVCOL_TRC_UNSPECIFIED; - if (!av_color_space_name(color_matrix)) - color_matrix = AVCOL_SPC_UNSPECIFIED; + av_log(c->fc, AV_LOG_TRACE, + "%s: pri %d trc %d matrix %d", + color_parameter_type, color_primaries, color_trc, color_matrix); - st->codecpar->color_primaries = color_primaries; - st->codecpar->color_trc = color_trc; - st->codecpar->color_space = color_matrix; - av_log(c->fc, AV_LOG_TRACE, "\n"); + if (!strncmp(color_parameter_type, "nclx", 4)) { + uint8_t color_range = avio_r8(pb) >> 7; + av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range); + if (color_range) + st->codecpar->color_range = AVCOL_RANGE_JPEG; + else + st->codecpar->color_range = AVCOL_RANGE_MPEG; + } + if (!av_color_primaries_name(color_primaries)) + color_primaries = AVCOL_PRI_UNSPECIFIED; + if (!av_color_transfer_name(color_trc)) + color_trc = AVCOL_TRC_UNSPECIFIED; + if (!av_color_space_name(color_matrix)) + color_matrix = AVCOL_SPC_UNSPECIFIED; + + st->codecpar->color_primaries = color_primaries; + st->codecpar->color_trc = color_trc; + st->codecpar->color_space = color_matrix; + av_log(c->fc, AV_LOG_TRACE, "\n"); + } return 0; } @@ -1620,7 +1665,7 @@ } } if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) { - av_log(NULL, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order); + av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order); } st->codecpar->field_order = decoded_field_order; @@ -1713,7 +1758,7 @@ static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom) { int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI); - if(ret == 0) + if (!ret) ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_DNXHD); return ret; } @@ -1762,8 +1807,8 @@ return 0; den *= 2; case 1: - c->fc->streams[c->fc->nb_streams-1]->display_aspect_ratio.num = num; - c->fc->streams[c->fc->nb_streams-1]->display_aspect_ratio.den = den; + c->fc->streams[c->fc->nb_streams-1]->internal->display_aspect_ratio.num = num; + c->fc->streams[c->fc->nb_streams-1]->internal->display_aspect_ratio.den = den; default: return 0; } @@ -1797,19 +1842,19 @@ par->color_range = AVCOL_RANGE_JPEG; break; default: - av_log(c, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value); + av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value); break; } - ff_dlog(c, "color_range: %d\n", par->color_range); + ff_dlog(c->fc, "color_range: %d\n", par->color_range); } else { /* For some reason the whole atom was not added to the extradata */ - av_log(c, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n"); + av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n"); } } else { - av_log(c, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n"); + av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n"); } } else { - av_log(c, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size); + av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size); } } @@ -1837,7 +1882,6 @@ st->codecpar->codec_id == AV_CODEC_ID_QDMC || st->codecpar->codec_id == AV_CODEC_ID_SPEEX) { // pass all frma atom to codec, needed at least for QDMC and QDM2 - av_freep(&st->codecpar->extradata); ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size); if (ret < 0) return ret; @@ -1901,10 +1945,9 @@ return mov_read_default(c, pb, atom); } if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) { - av_log(c, AV_LOG_WARNING, "ignoring multiple glbl\n"); + av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n"); return 0; } - av_freep(&st->codecpar->extradata); ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size); if (ret < 0) return ret; @@ -1937,7 +1980,6 @@ return 0; avio_seek(pb, 6, SEEK_CUR); - av_freep(&st->codecpar->extradata); ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7); if (ret < 0) return ret; @@ -1965,7 +2007,6 @@ return AVERROR_INVALIDDATA; avio_skip(pb, 40); - av_freep(&st->codecpar->extradata); ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40); if (ret < 0) return ret; @@ -1979,6 +2020,10 @@ MOVStreamContext *sc; unsigned int i, entries; + if (c->trak_index < 0) { + av_log(c->fc, AV_LOG_WARNING, "STCO outside TRAK\n"); + return 0; + } if (c->fc->nb_streams < 1) return 0; st = c->fc->streams[c->fc->nb_streams-1]; @@ -1992,8 +2037,10 @@ if (!entries) return 0; - if (sc->chunk_offsets) - av_log(c->fc, AV_LOG_WARNING, "Duplicated STCO atom\n"); + if (sc->chunk_offsets) { + av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n"); + return 0; + } av_free(sc->chunk_offsets); sc->chunk_count = 0; sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets)); @@ -2061,6 +2108,7 @@ uint8_t codec_name[32] = { 0 }; int64_t stsd_start; unsigned int len; + uint32_t id = 0; /* The first 16 bytes of the video sample description are already * read in ff_mov_read_stsd_entries() */ @@ -2068,7 +2116,8 @@ avio_rb16(pb); /* version */ avio_rb16(pb); /* revision level */ - avio_rb32(pb); /* vendor */ + id = avio_rl32(pb); /* vendor */ + av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0); avio_rb32(pb); /* temporal quality */ avio_rb32(pb); /* spatial quality */ @@ -2116,10 +2165,12 @@ { int bits_per_sample, flags; uint16_t version = avio_rb16(pb); + uint32_t id = 0; AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE); avio_rb16(pb); /* revision level */ - avio_rb32(pb); /* vendor */ + id = avio_rl32(pb); /* vendor */ + av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0); st->codecpar->channels = avio_rb16(pb); /* channel count */ st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */ @@ -2214,7 +2265,7 @@ } bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id); - if (bits_per_sample) { + if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->channels <= INT_MAX) { st->codecpar->bits_per_coded_sample = bits_per_sample; sc->sample_size = (bits_per_sample >> 3) * st->codecpar->channels; } @@ -2254,7 +2305,7 @@ { char buf[256] = {0}; uint8_t *src = st->codecpar->extradata; - int i; + int i, ret; if (st->codecpar->extradata_size != 64) return 0; @@ -2274,12 +2325,9 @@ if (av_strlcat(buf, "\n", sizeof(buf)) >= sizeof(buf)) return 0; - av_freep(&st->codecpar->extradata); - st->codecpar->extradata_size = 0; - st->codecpar->extradata = av_mallocz(strlen(buf) + AV_INPUT_BUFFER_PADDING_SIZE); - if (!st->codecpar->extradata) - return AVERROR(ENOMEM); - st->codecpar->extradata_size = strlen(buf); + ret = ff_alloc_extradata(st->codecpar, strlen(buf)); + if (ret < 0) + return ret; memcpy(st->codecpar->extradata, buf, st->codecpar->extradata_size); return 0; @@ -2303,43 +2351,27 @@ int val; val = AV_RB32(st->codecpar->extradata + 4); tmcd_ctx->tmcd_flags = val; - st->avg_frame_rate.num = st->codecpar->extradata[16]; /* number of frame */ - st->avg_frame_rate.den = 1; + st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */ + st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */ #if FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS st->codec->time_base = av_inv_q(st->avg_frame_rate); FF_ENABLE_DEPRECATION_WARNINGS #endif - /* adjust for per frame dur in counter mode */ - if (tmcd_ctx->tmcd_flags & 0x0008) { - int timescale = AV_RB32(st->codecpar->extradata + 8); - int framedur = AV_RB32(st->codecpar->extradata + 12); - st->avg_frame_rate.num *= timescale; - st->avg_frame_rate.den *= framedur; -#if FF_API_LAVF_AVCTX -FF_DISABLE_DEPRECATION_WARNINGS - st->codec->time_base.den *= timescale; - st->codec->time_base.num *= framedur; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - } if (size > 30) { uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */ uint32_t format = AV_RB32(st->codecpar->extradata + 22); if (format == AV_RB32("name") && (int64_t)size >= (int64_t)len + 18) { uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */ - if (str_size > 0 && size >= (int)str_size + 26) { + if (str_size > 0 && size >= (int)str_size + 30 && + st->codecpar->extradata[30] /* Don't add empty string */) { char *reel_name = av_malloc(str_size + 1); if (!reel_name) return AVERROR(ENOMEM); memcpy(reel_name, st->codecpar->extradata + 30, str_size); reel_name[str_size] = 0; /* Add null terminator */ - /* don't add reel_name if emtpy string */ - if (*reel_name == 0) { - av_free(reel_name); - } else { - av_dict_set(&st->metadata, "reel_name", reel_name, AV_DICT_DONT_STRDUP_VAL); - } + av_dict_set(&st->metadata, "reel_name", reel_name, + AV_DICT_DONT_STRDUP_VAL); } } } @@ -2424,6 +2456,9 @@ case AV_CODEC_ID_VP9: st->need_parsing = AVSTREAM_PARSE_FULL; break; + case AV_CODEC_ID_AV1: + st->need_parsing = AVSTREAM_PARSE_HEADERS; + break; default: break; } @@ -2536,11 +2571,8 @@ /* Move the current stream extradata to the stream context one. */ sc->extradata_size[pseudo_stream_id] = extra_size; - sc->extradata[pseudo_stream_id] = av_malloc(extra_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!sc->extradata[pseudo_stream_id]) - return AVERROR(ENOMEM); - memcpy(sc->extradata[pseudo_stream_id], st->codecpar->extradata, extra_size); - av_freep(&st->codecpar->extradata); + sc->extradata[pseudo_stream_id] = st->codecpar->extradata; + st->codecpar->extradata = NULL; st->codecpar->extradata_size = 0; } sc->stsd_count++; @@ -2570,7 +2602,7 @@ entries = avio_rb32(pb); /* Each entry contains a size (4 bytes) and format (4 bytes). */ - if (entries <= 0 || entries > atom.size / 8) { + if (entries <= 0 || entries > atom.size / 8 || entries > 1024) { av_log(c->fc, AV_LOG_ERROR, "invalid STSD entries %d\n", entries); return AVERROR_INVALIDDATA; } @@ -2641,8 +2673,10 @@ if (!entries) return 0; - if (sc->stsc_data) - av_log(c->fc, AV_LOG_WARNING, "Duplicated STSC atom\n"); + if (sc->stsc_data) { + av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n"); + return 0; + } av_free(sc->stsc_data); sc->stsc_count = 0; sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data)); @@ -2665,6 +2699,10 @@ sc->stsc_data[i].id < 1) { av_log(c->fc, AV_LOG_WARNING, "STSC entry %d is invalid (first=%d count=%d id=%d)\n", i, sc->stsc_data[i].first, sc->stsc_data[i].count, sc->stsc_data[i].id); if (i+1 >= sc->stsc_count) { + if (sc->stsc_data[i].count == 0 && i > 0) { + sc->stsc_count --; + continue; + } sc->stsc_data[i].first = FFMAX(sc->stsc_data[i].first, first_min); if (i > 0 && sc->stsc_data[i].first <= sc->stsc_data[i-1].first) sc->stsc_data[i].first = FFMIN(sc->stsc_data[i-1].first + 1LL, INT_MAX); @@ -2763,8 +2801,7 @@ av_log(c->fc, AV_LOG_TRACE, "keyframe_count = %u\n", entries); - if (!entries) - { + if (!entries) { sc->keyframe_absent = 1; if (!st->need_parsing && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) st->need_parsing = AVSTREAM_PARSE_HEADERS; @@ -2867,6 +2904,11 @@ for (i = 0; i < entries && !pb->eof_reached; i++) { sc->sample_sizes[i] = get_bits_long(&gb, field_size); + if (sc->sample_sizes[i] < 0) { + av_free(buf); + av_log(c->fc, AV_LOG_ERROR, "Invalid sample size %d\n", sc->sample_sizes[i]); + return AVERROR_INVALIDDATA; + } sc->data_size += sc->sample_sizes[i]; } @@ -2887,8 +2929,8 @@ AVStream *st; MOVStreamContext *sc; unsigned int i, entries, alloc_size = 0; - int64_t duration=0; - int64_t total_sample_count=0; + int64_t duration = 0; + int64_t total_sample_count = 0; if (c->fc->nb_streams < 1) return 0; @@ -2923,7 +2965,7 @@ sc->stts_count = min_entries; sc->stts_data = stts_data; - sample_count=avio_rb32(pb); + sample_count = avio_rb32(pb); sample_duration = avio_rb32(pb); sc->stts_data[i].count= sample_count; @@ -2940,8 +2982,7 @@ if (duration > 0 && duration <= INT64_MAX - sc->duration_for_fps && - total_sample_count <= INT_MAX - sc->nb_frames_for_fps - ) { + total_sample_count <= INT_MAX - sc->nb_frames_for_fps) { sc->duration_for_fps += duration; sc->nb_frames_for_fps += total_sample_count; } @@ -2958,11 +2999,45 @@ return 0; } -static void mov_update_dts_shift(MOVStreamContext *sc, int duration) +static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVStream *st; + MOVStreamContext *sc; + int64_t i, entries; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams - 1]; + sc = st->priv_data; + + avio_r8(pb); /* version */ + avio_rb24(pb); /* flags */ + entries = atom.size - 4; + + av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n", + c->fc->nb_streams - 1, entries); + + if (sc->sdtp_data) + av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n"); + av_freep(&sc->sdtp_data); + sc->sdtp_count = 0; + + sc->sdtp_data = av_malloc(entries); + if (!sc->sdtp_data) + return AVERROR(ENOMEM); + + for (i = 0; i < entries && !pb->eof_reached; i++) + sc->sdtp_data[i] = avio_r8(pb); + sc->sdtp_count = i; + + return 0; +} + +static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx) { if (duration < 0) { if (duration == INT_MIN) { - av_log(NULL, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX); + av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX); duration++; } sc->dts_shift = FFMAX(sc->dts_shift, -duration); @@ -2996,8 +3071,8 @@ return AVERROR(ENOMEM); for (i = 0; i < entries && !pb->eof_reached; i++) { - int count =avio_rb32(pb); - int duration =avio_rb32(pb); + int count = avio_rb32(pb); + int duration = avio_rb32(pb); if (count <= 0) { av_log(c->fc, AV_LOG_TRACE, @@ -3020,7 +3095,7 @@ } if (i+2fc); } sc->ctts_count = ctts_count; @@ -3237,13 +3312,13 @@ FFMAX(min_size_needed, 2 * st->index_entries_allocated_size) : min_size_needed; - if((unsigned)st->nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry)) + if (st->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry)) return -1; entries = av_fast_realloc(st->index_entries, &st->index_entries_allocated_size, requested_size); - if(!entries) + if (!entries) return -1; st->index_entries= entries; @@ -3288,12 +3363,12 @@ 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(MOVStts) - 1) return -1; ctts_buf_new = av_fast_realloc(*ctts_data, allocated_size, requested_size); - if(!ctts_buf_new) + if (!ctts_buf_new) return -1; *ctts_data = ctts_buf_new; @@ -3306,7 +3381,8 @@ } #define MAX_REORDER_DELAY 16 -static void mov_estimate_video_delay(MOVContext *c, AVStream* st) { +static void mov_estimate_video_delay(MOVContext *c, AVStream* st) +{ MOVStreamContext *msc = st->priv_data; int ind; int ctts_ind = 0; @@ -3321,7 +3397,7 @@ if (st->codecpar->video_delay <= 0 && msc->ctts_data && st->codecpar->codec_id == AV_CODEC_ID_H264) { st->codecpar->video_delay = 0; - for(ind = 0; ind < st->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) { + for (ind = 0; ind < st->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) { // Point j to the last elem of the buffer and insert the current pts there. j = buf_start; buf_start = (buf_start + 1); @@ -3509,7 +3585,7 @@ } if (first_non_zero_audio_edit > 0) - st->skip_samples = msc->start_pad = 0; + st->internal->skip_samples = msc->start_pad = 0; } // While reordering frame index according to edit list we must handle properly @@ -3584,7 +3660,7 @@ curr_cts < edit_list_media_time && curr_cts + frame_duration > edit_list_media_time && first_non_zero_audio_edit > 0) { packet_skip_samples = edit_list_media_time - curr_cts; - st->skip_samples += packet_skip_samples; + st->internal->skip_samples += packet_skip_samples; // Shift the index entry timestamp by packet_skip_samples to be correct. edit_list_dts_counter -= packet_skip_samples; @@ -3617,7 +3693,7 @@ // Increment skip_samples for the first non-zero audio edit list if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && first_non_zero_audio_edit > 0 && st->codecpar->codec_id != AV_CODEC_ID_VORBIS) { - st->skip_samples += frame_duration; + st->internal->skip_samples += frame_duration; } } } @@ -3703,7 +3779,7 @@ // Update av stream length, if it ends up shorter than the track's media duration st->duration = FFMIN(st->duration, edit_list_dts_entry_end - start_dts); - msc->start_pad = st->skip_samples; + msc->start_pad = st->internal->skip_samples; // Free the old index and the old CTTS structures av_free(e_old); @@ -4119,10 +4195,10 @@ return AVERROR(ENOENT); } - if(strstr(ref->path + l + 1, "..") || - strstr(ref->path + l + 1, ":") || - (ref->nlvl_from > 1 && same_origin < 0) || - (filename[0] == '/' && src_path == src)) + if (strstr(ref->path + l + 1, "..") || + strstr(ref->path + l + 1, ":") || + (ref->nlvl_from > 1 && same_origin < 0) || + (filename[0] == '/' && src_path == src)) return AVERROR(ENOENT); } @@ -4339,7 +4415,7 @@ static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom) { - int64_t end = avio_tell(pb) + atom.size; + int64_t end = av_sat_add64(avio_tell(pb), atom.size); uint8_t *key = NULL, *val = NULL, *mean = NULL; int i; int ret = 0; @@ -4377,6 +4453,9 @@ } else break; + if (*p) + break; + *p = av_malloc(len + 1); if (!*p) { ret = AVERROR(ENOMEM); @@ -4564,6 +4643,7 @@ MOVFragment *frag = &c->fragment; MOVTrackExt *trex = NULL; int flags, track_id, i; + MOVFragmentStreamInfo * frag_stream_info; avio_r8(pb); /* version */ flags = avio_rb24(pb); @@ -4597,6 +4677,10 @@ avio_rb32(pb) : trex->flags; av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags); + frag_stream_info = get_current_frag_stream_info(&c->frag_index); + if (frag_stream_info) + frag_stream_info->next_trun_dts = AV_NOPTS_VALUE; + return 0; } @@ -4748,13 +4832,19 @@ if (flags & MOV_TRUN_FIRST_SAMPLE_FLAGS) first_sample_flags = avio_rb32(pb); frag_stream_info = get_current_frag_stream_info(&c->frag_index); - if (frag_stream_info) - { - if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE && + if (frag_stream_info) { + if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) { + dts = frag_stream_info->next_trun_dts - sc->time_offset; + } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE && c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) { pts = frag_stream_info->first_tfra_pts; av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64 ", using it for pts\n", pts); + } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE && + c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) { + 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) { // FIXME: sidx earliest_presentation_time is *PTS*, s.b. // pts = frag_stream_info->sidx_pts; @@ -4784,14 +4874,14 @@ entries = UINT_MAX / sizeof(AVIndexEntry) - st->nb_index_entries; av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n"); } - if (entries <= 0) - return -1; + if (entries == 0) + return 0; requested_size = (st->nb_index_entries + entries) * sizeof(AVIndexEntry); new_entries = av_fast_realloc(st->index_entries, &st->index_entries_allocated_size, requested_size); - if(!new_entries) + if (!new_entries) return AVERROR(ENOMEM); st->index_entries= new_entries; @@ -4846,7 +4936,7 @@ if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb); if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb); - mov_update_dts_shift(sc, ctts_duration); + mov_update_dts_shift(sc, ctts_duration, c->fc); if (pts != AV_NOPTS_VALUE) { dts = pts - sc->dts_shift; if (flags & MOV_TRUN_SAMPLE_CTS) { @@ -4905,6 +4995,8 @@ sc->nb_frames_for_fps ++; } } + if (frag_stream_info) + frag_stream_info->next_trun_dts = dts + sc->time_offset; if (i < entries) { // EOF found before reading all entries. Fix the hole this would // leave in index_entries and ctts_data @@ -4960,8 +5052,10 @@ static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom) { - int64_t offset = avio_tell(pb) + atom.size, pts, timestamp; - uint8_t version; + int64_t stream_size = avio_size(pb); + int64_t offset = av_sat_add64(avio_tell(pb), atom.size), pts, timestamp; + uint8_t version, is_complete; + int64_t offadd; unsigned i, j, track_id, item_count; AVStream *st = NULL; AVStream *ref_st = NULL; @@ -4999,11 +5093,15 @@ if (version == 0) { pts = avio_rb32(pb); - offset += avio_rb32(pb); + offadd= avio_rb32(pb); } else { pts = avio_rb64(pb); - offset += avio_rb64(pb); + offadd= avio_rb64(pb); } + if (av_sat_add64(offset, offadd) != offset + (uint64_t)offadd) + return AVERROR_INVALIDDATA; + + offset += (uint64_t)offadd; avio_rb16(pb); // reserved @@ -5019,13 +5117,15 @@ return AVERROR_PATCHWELCOME; } avio_rb32(pb); // sap_flags - timestamp = av_rescale_q(pts, st->time_base, timescale); + timestamp = av_rescale_q(pts, timescale, st->time_base); index = update_frag_index(c, offset); frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id); if (frag_stream_info) frag_stream_info->sidx_pts = timestamp; + if (av_sat_add64(offset, size) != offset + size) + return AVERROR_INVALIDDATA; offset += size; pts += duration; } @@ -5034,7 +5134,24 @@ sc->has_sidx = 1; - if (offset == avio_size(pb)) { + // See if the remaining bytes are just an mfra which we can ignore. + is_complete = offset == stream_size; + if (!is_complete && (pb->seekable & AVIO_SEEKABLE_NORMAL)) { + int64_t ret; + int64_t original_pos = avio_tell(pb); + if (!c->have_read_mfra_size) { + if ((ret = avio_seek(pb, stream_size - 4, SEEK_SET)) < 0) + return ret; + c->mfra_size = avio_rb32(pb); + c->have_read_mfra_size = 1; + if ((ret = avio_seek(pb, original_pos, SEEK_SET)) < 0) + return ret; + } + if (offset + c->mfra_size == stream_size) + is_complete = 1; + } + + if (is_complete) { // Find first entry in fragment index that came from an sidx. // This will pretty much always be the first entry. for (i = 0; i < c->frag_index.nb_items; i++) { @@ -5164,7 +5281,7 @@ } else { edit_count = atom.size / elst_entry_size; if (edit_count * elst_entry_size != atom.size) { - av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.", atom.size, edit_count); + av_log(c->fc, AV_LOG_WARNING, "ELST atom of %"PRId64" bytes, bigger than %d entries.\n", atom.size, edit_count); } } } @@ -5446,6 +5563,10 @@ av_log(c->fc, AV_LOG_ERROR, "Empty stereoscopic video box\n"); return AVERROR_INVALIDDATA; } + + if (sc->stereo3d) + return AVERROR_INVALIDDATA; + avio_skip(pb, 4); /* version + flags */ mode = avio_r8(pb); @@ -5699,12 +5820,9 @@ st = c->fc->streams[c->fc->nb_streams - 1]; sc = st->priv_data; - ret = avio_read(pb, uuid, sizeof(uuid)); - if (ret < 0) { + ret = ffio_read_size(pb, uuid, sizeof(uuid)); + if (ret < 0) return ret; - } else if (ret != sizeof(uuid)) { - return AVERROR_INVALIDDATA; - } if (!memcmp(uuid, uuid_isml_manifest, sizeof(uuid))) { uint8_t *buffer, *ptr; char *endptr; @@ -5720,13 +5838,10 @@ if (!buffer) { return AVERROR(ENOMEM); } - ret = avio_read(pb, buffer, len); + ret = ffio_read_size(pb, buffer, len); if (ret < 0) { av_free(buffer); return ret; - } else if (ret != len) { - av_free(buffer); - return AVERROR_INVALIDDATA; } ptr = buffer; @@ -5757,17 +5872,14 @@ if (!buffer) { return AVERROR(ENOMEM); } - ret = avio_read(pb, buffer, len); + ret = ffio_read_size(pb, buffer, len); if (ret < 0) { av_free(buffer); return ret; - } else if (ret != len) { - av_free(buffer); - return AVERROR_INVALIDDATA; } buffer[len] = '\0'; - av_dict_set(&c->fc->metadata, "xmp", buffer, 0); - av_free(buffer); + av_dict_set(&c->fc->metadata, "xmp", + buffer, AV_DICT_DONT_STRDUP_VAL); } else { // skip all uuid atom, which makes it fast for long uuid-xmp file ret = avio_skip(pb, len); @@ -5907,7 +6019,7 @@ static int mov_read_sample_encryption_info(MOVContext *c, AVIOContext *pb, MOVStreamContext *sc, AVEncryptionInfo **sample, int use_subsamples) { - int i; + int i, ret; unsigned int subsample_count; AVSubsampleEncryptionInfo *subsamples; @@ -5921,11 +6033,11 @@ return AVERROR(ENOMEM); if (sc->cenc.per_sample_iv_size != 0) { - if (avio_read(pb, (*sample)->iv, sc->cenc.per_sample_iv_size) != sc->cenc.per_sample_iv_size) { + if ((ret = ffio_read_size(pb, (*sample)->iv, sc->cenc.per_sample_iv_size)) < 0) { av_log(c->fc, AV_LOG_ERROR, "failed to read the initialization vector\n"); av_encryption_info_free(*sample); *sample = NULL; - return AVERROR_INVALIDDATA; + return ret; } } @@ -6278,7 +6390,8 @@ AVStream *st; uint8_t *side_data, *extra_data, *old_side_data; size_t side_data_size; - int ret = 0, old_side_data_size; + buffer_size_t old_side_data_size; + int ret = 0; unsigned int version, kid_count, extra_data_size, alloc_size = 0; if (c->fc->nb_streams < 1) @@ -6293,16 +6406,17 @@ if (!info) return AVERROR(ENOMEM); - if (avio_read(pb, info->system_id, 16) != 16) { + if ((ret = ffio_read_size(pb, info->system_id, 16)) < 0) { av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n"); - ret = AVERROR_INVALIDDATA; goto finish; } if (version > 0) { kid_count = avio_rb32(pb); - if (kid_count >= INT_MAX / sizeof(*key_ids)) - return AVERROR(ENOMEM); + if (kid_count >= INT_MAX / sizeof(*key_ids)) { + ret = AVERROR(ENOMEM); + goto finish; + } for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) { unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count); @@ -6321,9 +6435,8 @@ } info->num_key_ids = i + 1; - if (avio_read(pb, info->key_ids[i], 16) != 16) { + if ((ret = ffio_read_size(pb, info->key_ids[i], 16)) < 0) { av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n"); - ret = AVERROR_INVALIDDATA; goto finish; } } @@ -6542,15 +6655,13 @@ av_aes_ctr_set_full_iv(sc->cenc.aes_ctr, sample->iv); - if (!sample->subsample_count) - { + if (!sample->subsample_count) { /* decrypt the whole packet */ av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, size); return 0; } - for (i = 0; i < sample->subsample_count; i++) - { + for (i = 0; i < sample->subsample_count; i++) { if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) { av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n"); return AVERROR_INVALIDDATA; @@ -6641,6 +6752,7 @@ static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom) { const int OPUS_SEEK_PREROLL_MS = 80; + int ret; AVStream *st; size_t size; uint16_t pre_skip; @@ -6661,8 +6773,8 @@ /* OpusSpecificBox size plus magic for Ogg OpusHead header. */ size = atom.size + 8; - if (ff_alloc_extradata(st->codecpar, size)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0) + return ret; AV_WL32(st->codecpar->extradata, MKTAG('O','p','u','s')); AV_WL32(st->codecpar->extradata + 4, MKTAG('H','e','a','d')); @@ -6686,6 +6798,95 @@ return 0; } +static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVStream *st; + unsigned format_info; + int channel_assignment, channel_assignment1, channel_assignment2; + int ratebits; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams-1]; + + if (atom.size < 10) + return AVERROR_INVALIDDATA; + + format_info = avio_rb32(pb); + + ratebits = (format_info >> 28) & 0xF; + channel_assignment1 = (format_info >> 15) & 0x1F; + channel_assignment2 = format_info & 0x1FFF; + if (channel_assignment2) + channel_assignment = channel_assignment2; + else + channel_assignment = channel_assignment1; + + st->codecpar->frame_size = 40 << (ratebits & 0x7); + st->codecpar->sample_rate = mlp_samplerate(ratebits); + st->codecpar->channels = truehd_channels(channel_assignment); + st->codecpar->channel_layout = truehd_layout(channel_assignment); + + return 0; +} + +static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVStream *st; + uint32_t buf; + AVDOVIDecoderConfigurationRecord *dovi; + size_t dovi_size; + int ret; + + 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; + + 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); + 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; +} + static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('A','C','L','R'), mov_read_aclr }, { MKTAG('A','P','R','G'), mov_read_avid }, @@ -6734,6 +6935,7 @@ { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */ { MKTAG('s','t','t','s'), mov_read_stts }, { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */ +{ MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */ { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */ { MKTAG('t','f','d','t'), mov_read_tfdt }, { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */ @@ -6774,11 +6976,14 @@ { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */ { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */ { MKTAG('d','O','p','s'), mov_read_dops }, +{ MKTAG('d','m','l','p'), mov_read_dmlp }, { MKTAG('S','m','D','m'), mov_read_smdm }, { MKTAG('C','o','L','L'), mov_read_coll }, { MKTAG('v','p','c','C'), mov_read_vpcc }, { MKTAG('m','d','c','v'), mov_read_mdcv }, { MKTAG('c','l','l','i'), mov_read_clli }, +{ MKTAG('d','v','c','C'), mov_read_dvcc_dvvc }, +{ MKTAG('d','v','v','C'), mov_read_dvcc_dvvc }, { 0, NULL } }; @@ -6803,26 +7008,26 @@ if (atom.size >= 8) { a.size = avio_rb32(pb); a.type = avio_rl32(pb); - if (a.type == MKTAG('f','r','e','e') && + if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) || + a.type == MKTAG('h','o','o','v')) && a.size >= 8 && - c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT && - c->moov_retry) { - uint8_t buf[8]; - uint32_t *type = (uint32_t *)buf + 1; - if (avio_read(pb, buf, 8) != 8) - return AVERROR_INVALIDDATA; + c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) { + uint32_t type; + avio_skip(pb, 4); + type = avio_rl32(pb); + if (avio_feof(pb)) + break; avio_seek(pb, -8, SEEK_CUR); - if (*type == MKTAG('m','v','h','d') || - *type == MKTAG('c','m','o','v')) { - av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free atom.\n"); + if (type == MKTAG('m','v','h','d') || + type == MKTAG('c','m','o','v')) { + av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n"); a.type = MKTAG('m','o','o','v'); } } if (atom.type != MKTAG('r','o','o','t') && - atom.type != MKTAG('m','o','o','v')) - { - if (a.type == MKTAG('t','r','a','k') || a.type == MKTAG('m','d','a','t')) - { + atom.type != MKTAG('m','o','o','v')) { + if (a.type == MKTAG('t','r','a','k') || + a.type == MKTAG('m','d','a','t')) { av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n"); avio_skip(pb, -8); c->atom_depth --; @@ -6860,7 +7065,8 @@ // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html if (!parse && c->found_hdlr_mdta && atom.type == MKTAG('m','e','t','a') && - a.type == MKTAG('k','e','y','s')) { + a.type == MKTAG('k','e','y','s') && + c->meta_keys_count == 0) { parse = mov_read_keys; } @@ -6874,7 +7080,7 @@ c->atom_depth --; return err; } - if (c->found_moov && c->found_mdat && + if (c->found_moov && c->found_mdat && a.size <= INT64_MAX - start_pos && ((!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) || start_pos + a.size == avio_size(pb))) { if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || c->fc->flags & AVFMT_FLAG_IGNIDX || c->frag_index.complete) @@ -6887,8 +7093,8 @@ avio_skip(pb, left); else if (left < 0) { av_log(c->fc, AV_LOG_WARNING, - "overread end of atom '%.4s' by %"PRId64" bytes\n", - (char*)&a.type, -left); + "overread end of atom '%s' by %"PRId64" bytes\n", + av_fourcc2str(a.type), -left); avio_seek(pb, left, SEEK_CUR); } } @@ -6913,9 +7119,22 @@ /* check file header */ offset = 0; for (;;) { + int64_t size; + int minsize = 8; /* ignore invalid offset */ - if ((offset + 8) > (unsigned int)p->buf_size) + if ((offset + 8ULL) > (unsigned int)p->buf_size) break; + size = AV_RB32(p->buf + offset); + if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) { + size = AV_RB64(p->buf+offset + 8); + minsize = 16; + } else if (size == 0) { + size = p->buf_size - offset; + } + if (size < minsize) { + offset += 4; + continue; + } tag = AV_RL32(p->buf + offset + 4); switch(tag) { /* check for obvious tags */ @@ -6925,12 +7144,7 @@ case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */ case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */ case MKTAG('f','t','y','p'): - if (AV_RB32(p->buf+offset) < 8 && - (AV_RB32(p->buf+offset) != 1 || - offset + 12 > (unsigned int)p->buf_size || - AV_RB64(p->buf+offset + 8) == 0)) { - score = FFMAX(score, AVPROBE_SCORE_EXTENSION); - } else if (tag == MKTAG('f','t','y','p') && + if (tag == MKTAG('f','t','y','p') && ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ') || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ') )) { @@ -6938,7 +7152,6 @@ } else { score = AVPROBE_SCORE_MAX; } - offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset; break; /* those are more common words, so rate then a bit less */ case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */ @@ -6947,7 +7160,6 @@ case MKTAG('j','u','n','k'): case MKTAG('p','i','c','t'): score = FFMAX(score, AVPROBE_SCORE_MAX - 5); - offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset; break; case MKTAG(0x82,0x82,0x7f,0x7d): case MKTAG('s','k','i','p'): @@ -6955,31 +7167,32 @@ case MKTAG('p','r','f','l'): /* if we only find those cause probedata is too small at least rate them */ score = FFMAX(score, AVPROBE_SCORE_EXTENSION); - offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset; break; - default: - offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset; } + if (size > INT64_MAX - offset) + break; + offset += size; } - if(score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) { + if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) { /* moov atom in the header - we should make sure that this is not a * MOV-packed MPEG-PS */ offset = moov_offset; - while(offset < (p->buf_size - 16)){ /* Sufficient space */ + while (offset < (p->buf_size - 16)) { /* Sufficient space */ /* We found an actual hdlr atom */ - if(AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') && - AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') && - AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')){ + if (AV_RL32(p->buf + offset ) == MKTAG('h','d','l','r') && + AV_RL32(p->buf + offset + 8) == MKTAG('m','h','l','r') && + AV_RL32(p->buf + offset + 12) == MKTAG('M','P','E','G')) { av_log(NULL, AV_LOG_WARNING, "Found media data tag MPEG indicating this is a MOV-packed MPEG-PS.\n"); /* We found a media handler reference atom describing an * MPEG-PS-in-MOV, return a * low score to force expanding the probe window until * mpegps_probe finds what it needs */ return 5; - }else + } else { /* Keep looking */ - offset+=2; + offset += 2; + } } } @@ -7016,17 +7229,15 @@ st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS; if (st->nb_index_entries) { // Retrieve the first frame, if possible - AVPacket pkt; AVIndexEntry *sample = &st->index_entries[0]; if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) { av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n"); goto finish; } - if (av_get_packet(sc->pb, &pkt, sample->size) < 0) + if (av_get_packet(sc->pb, &st->attached_pic, sample->size) < 0) goto finish; - st->attached_pic = pkt; st->attached_pic.stream_index = st->index; st->attached_pic.flags |= AV_PKT_FLAG_KEY; } @@ -7197,6 +7408,7 @@ av_freep(&sc->sample_sizes); av_freep(&sc->keyframes); av_freep(&sc->stts_data); + av_freep(&sc->sdtp_data); av_freep(&sc->stps_data); av_freep(&sc->elst_data); av_freep(&sc->rap_group); @@ -7219,10 +7431,9 @@ av_freep(&sc->coll); } - if (mov->dv_demux) { - avformat_free_context(mov->dv_fctx); - mov->dv_fctx = NULL; - } + av_freep(&mov->dv_demux); + avformat_free_context(mov->dv_fctx); + mov->dv_fctx = NULL; if (mov->meta_keys) { for (i = 1; i < mov->meta_keys_count; i++) { @@ -7343,22 +7554,22 @@ int64_t stream_size = avio_size(f); int64_t original_pos = avio_tell(f); int64_t seek_ret; - int32_t mfra_size; int ret = -1; if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) { ret = seek_ret; goto fail; } - mfra_size = avio_rb32(f); - if (mfra_size < 0 || mfra_size > stream_size) { + c->mfra_size = avio_rb32(f); + c->have_read_mfra_size = 1; + if (!c->mfra_size || c->mfra_size > stream_size) { av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n"); goto fail; } - if ((seek_ret = avio_seek(f, -mfra_size, SEEK_CUR)) < 0) { + if ((seek_ret = avio_seek(f, -((int64_t) c->mfra_size), SEEK_CUR)) < 0) { ret = seek_ret; goto fail; } - if (avio_rb32(f) != mfra_size) { + if (avio_rb32(f) != c->mfra_size) { av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n"); goto fail; } @@ -7373,6 +7584,7 @@ goto fail; } while (!ret); ret = 0; + c->frag_index.complete = 1; fail: seek_ret = avio_seek(f, original_pos, SEEK_SET); if (seek_ret < 0) { @@ -7411,14 +7623,13 @@ avio_seek(pb, 0, SEEK_SET); if ((err = mov_read_default(mov, pb, atom)) < 0) { av_log(s, AV_LOG_ERROR, "error reading header\n"); - mov_read_close(s); - return err; + goto fail; } } while ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mov->found_moov && !mov->moov_retry++); if (!mov->found_moov) { av_log(s, AV_LOG_ERROR, "moov atom not found\n"); - mov_read_close(s); - return AVERROR_INVALIDDATA; + err = AVERROR_INVALIDDATA; + goto fail; } av_log(mov->fc, AV_LOG_TRACE, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb)); @@ -7458,8 +7669,9 @@ AVStream *st = s->streams[i]; MOVStreamContext *sc = st->priv_data; fix_timescale(mov, sc); - if(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id == AV_CODEC_ID_AAC) { - st->skip_samples = sc->start_pad; + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + st->codecpar->codec_id == AV_CODEC_ID_AAC) { + st->internal->skip_samples = sc->start_pad; } if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0) av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, @@ -7471,13 +7683,12 @@ } if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) { if ((err = mov_rewrite_dvd_sub_extradata(st)) < 0) - return err; + goto fail; } } if (mov->handbrake_version && mov->handbrake_version <= 1000000*0 + 1000*10 + 2 && // 0.10.2 - st->codecpar->codec_id == AV_CODEC_ID_MP3 - ) { + st->codecpar->codec_id == AV_CODEC_ID_MP3) { av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n"); st->need_parsing = AVSTREAM_PARSE_FULL; } @@ -7491,8 +7702,8 @@ 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", sc->data_size, sc->time_scale); - mov_read_close(s); - return AVERROR_INVALIDDATA; + err = AVERROR_INVALIDDATA; + goto fail; } st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / st->duration; } @@ -7507,8 +7718,8 @@ 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", sc->data_size, sc->time_scale); - mov_read_close(s); - return AVERROR_INVALIDDATA; + err = AVERROR_INVALIDDATA; + goto fail; } st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / sc->duration_for_fps; @@ -7531,17 +7742,15 @@ switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_AUDIO: err = ff_replaygain_export(st, s->metadata); - if (err < 0) { - mov_read_close(s); - return err; - } + if (err < 0) + goto fail; break; case AVMEDIA_TYPE_VIDEO: if (sc->display_matrix) { err = av_stream_add_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, (uint8_t*)sc->display_matrix, sizeof(int32_t) * 9); if (err < 0) - return err; + goto fail; sc->display_matrix = NULL; } @@ -7550,7 +7759,7 @@ (uint8_t *)sc->stereo3d, sizeof(*sc->stereo3d)); if (err < 0) - return err; + goto fail; sc->stereo3d = NULL; } @@ -7559,7 +7768,7 @@ (uint8_t *)sc->spherical, sc->spherical_size); if (err < 0) - return err; + goto fail; sc->spherical = NULL; } @@ -7568,7 +7777,7 @@ (uint8_t *)sc->mastering, sizeof(*sc->mastering)); if (err < 0) - return err; + goto fail; sc->mastering = NULL; } @@ -7577,7 +7786,7 @@ (uint8_t *)sc->coll, sc->coll_size); if (err < 0) - return err; + goto fail; sc->coll = NULL; } @@ -7591,6 +7800,9 @@ mov->frag_index.item[i].headers_read = 1; return 0; +fail: + mov_read_close(s); + return err; } static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st) @@ -7607,7 +7819,7 @@ av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts); if (!sample || (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && current_sample->pos < sample->pos) || ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && - ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && + ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && dts != AV_NOPTS_VALUE && ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < sample->pos) || (FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) { sample = current_sample; @@ -7641,7 +7853,8 @@ mov->next_root_atom = 0; if (index < 0 || index >= mov->frag_index.nb_items) index = search_frag_moof_offset(&mov->frag_index, target); - if (index < mov->frag_index.nb_items) { + if (index < mov->frag_index.nb_items && + mov->frag_index.item[index].moof_offset == target) { if (index + 1 < mov->frag_index.nb_items) mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset; if (mov->frag_index.item[index].headers_read) @@ -7684,6 +7897,27 @@ return 0; } +static int get_eia608_packet(AVIOContext *pb, AVPacket *pkt, int size) +{ + int new_size, ret; + + if (size <= 8) + return AVERROR_INVALIDDATA; + new_size = ((size - 8) / 2) * 3; + ret = av_new_packet(pkt, new_size); + if (ret < 0) + return ret; + + avio_skip(pb, 8); + for (int j = 0; j < new_size; j += 3) { + pkt->data[j] = 0xFC; + pkt->data[j+1] = avio_r8(pb); + pkt->data[j+2] = avio_r8(pb); + } + + return 0; +} + static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) { MOVContext *mov = s->priv_data; @@ -7723,18 +7957,34 @@ return AVERROR_INVALIDDATA; } - if( st->discard == AVDISCARD_NONKEY && 0==(sample->flags & AVINDEX_KEYFRAME) ) { + if (st->discard == AVDISCARD_NONKEY && !(sample->flags & AVINDEX_KEYFRAME)) { av_log(mov->fc, AV_LOG_DEBUG, "Nonkey frame from stream %d discarded due to AVDISCARD_NONKEY\n", sc->ffindex); goto retry; } - ret = av_get_packet(sc->pb, pkt, sample->size); + if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608 && sample->size > 8) + ret = get_eia608_packet(sc->pb, pkt, sample->size); + else + ret = av_get_packet(sc->pb, pkt, sample->size); if (ret < 0) { if (should_retry(sc->pb, ret)) { mov_current_sample_dec(sc); } return ret; } +#if CONFIG_DV_DEMUXER + if (mov->dv_demux && sc->dv_audio_container) { + AVBufferRef *buf = pkt->buf; + ret = avpriv_dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size, pkt->pos); + pkt->buf = buf; + av_packet_unref(pkt); + if (ret < 0) + return ret; + ret = avpriv_dv_get_packet(mov->dv_demux, pkt); + if (ret < 0) + return ret; + } +#endif if (sc->has_palette) { uint8_t *pal; @@ -7746,16 +7996,6 @@ sc->has_palette = 0; } } -#if CONFIG_DV_DEMUXER - if (mov->dv_demux && sc->dv_audio_container) { - avpriv_dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size, pkt->pos); - av_freep(&pkt->data); - pkt->size = 0; - ret = avpriv_dv_get_packet(mov->dv_demux, pkt); - if (ret < 0) - return ret; - } -#endif if (st->codecpar->codec_id == AV_CODEC_ID_MP3 && !st->need_parsing && pkt->size > 4) { if (ff_mpa_check_header(AV_RB32(pkt->data)) < 0) st->need_parsing = AVSTREAM_PARSE_FULL; @@ -7786,6 +8026,11 @@ } if (st->discard == AVDISCARD_ALL) goto retry; + if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) { + uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1]; + uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3; + pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0; + } pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0; pkt->pos = sample->pos; @@ -7812,8 +8057,9 @@ aax_filter(pkt->data, pkt->size, mov); ret = cenc_filter(mov, st, sc, pkt, current_index); - if (ret < 0) + if (ret < 0) { return ret; + } return 0; } @@ -7875,22 +8121,38 @@ /* adjust stsd index */ if (sc->chunk_count) { - time_sample = 0; - for (i = 0; i < sc->stsc_count; i++) { - int64_t next = time_sample + mov_get_stsc_samples(sc, i); - if (next > sc->current_sample) { - sc->stsc_index = i; - sc->stsc_sample = sc->current_sample - time_sample; - break; + time_sample = 0; + for (i = 0; i < sc->stsc_count; i++) { + int64_t next = time_sample + mov_get_stsc_samples(sc, i); + if (next > sc->current_sample) { + sc->stsc_index = i; + sc->stsc_sample = sc->current_sample - time_sample; + break; + } + av_assert0(next == (int)next); + time_sample = next; } - av_assert0(next == (int)next); - time_sample = next; - } } return sample; } +static int64_t mov_get_skip_samples(AVStream *st, int sample) +{ + MOVStreamContext *sc = st->priv_data; + int64_t first_ts = st->index_entries[0].timestamp; + int64_t ts = st->index_entries[sample].timestamp; + int64_t off; + + if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) + return 0; + + /* compute skip samples according to stream start_pad, seek ts and first ts */ + off = av_rescale_q(ts - first_ts, st->time_base, + (AVRational){1, st->codecpar->sample_rate}); + return FFMAX(sc->start_pad - off, 0); +} + static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags) { MOVContext *mc = s->priv_data; @@ -7909,18 +8171,19 @@ if (mc->seek_individually) { /* adjust seek timestamp to found sample timestamp */ int64_t seek_timestamp = st->index_entries[sample].timestamp; + st->internal->skip_samples = mov_get_skip_samples(st, sample); for (i = 0; i < s->nb_streams; i++) { int64_t timestamp; - MOVStreamContext *sc = s->streams[i]->priv_data; st = s->streams[i]; - st->skip_samples = (sample_time <= 0) ? sc->start_pad : 0; if (stream_index == i) continue; timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base); - mov_seek_stream(s, st, timestamp, flags); + sample = mov_seek_stream(s, st, timestamp, flags); + if (sample >= 0) + st->internal->skip_samples = mov_get_skip_samples(st, sample); } } else { for (i = 0; i < s->nb_streams; i++) { @@ -7951,7 +8214,7 @@ OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS}, {"seek_streams_individually", - "Seek each stream individually to the to the closest point", + "Seek each stream individually to the closest point", OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS}, {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0}, @@ -7979,6 +8242,10 @@ AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS }, { "activation_bytes", "Secret bytes for Audible AAX files", OFFSET(activation_bytes), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM }, + { "audible_key", "AES-128 Key for Audible AAXC files", OFFSET(audible_key), + AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM }, + { "audible_iv", "AES-128 IV for Audible AAXC files", OFFSET(audible_iv), + AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM }, { "audible_fixed_key", // extracted from libAAX_SDK.so and AAXSDKWin.dll files! "Fixed key used for handling Audible AAX files", OFFSET(audible_fixed_key), AV_OPT_TYPE_BINARY, {.str="77214d4b196a87cd520045fd20a51d67"}, @@ -8002,7 +8269,7 @@ .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"), .priv_class = &mov_class, .priv_data_size = sizeof(MOVContext), - .extensions = "mov,mp4,m4a,3gp,3g2,mj2", + .extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v", .read_probe = mov_probe, .read_header = mov_read_header, .read_packet = mov_read_packet, diff -Nru ffmpeg-4.2.2/libavformat/movenc.c ffmpeg-4.4/libavformat/movenc.c --- ffmpeg-4.2.2/libavformat/movenc.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/movenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -51,6 +51,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/stereo3d.h" #include "libavutil/timecode.h" +#include "libavutil/dovi_meta.h" #include "libavutil/color_utils.h" #include "hevc.h" #include "rtpenc.h" @@ -72,11 +73,13 @@ { "disable_chpl", "Disable Nero chapter atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DISABLE_CHPL}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "default_base_moof", "Set the default-base-is-moof flag in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DEFAULT_BASE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "dash", "Write DASH compatible fragmented MP4", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DASH}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "cmaf", "Write CMAF compatible fragmented MP4", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_CMAF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "frag_discont", "Signal that the next fragment is discontinuous from earlier ones", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_DISCONT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "delay_moov", "Delay writing the initial moov until the first fragment is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DELAY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "global_sidx", "Write a global sidx index at the start of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "skip_sidx", "Skip writing of sidx atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SKIP_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, - { "write_colr", "Write colr atom (Experimental, may be renamed or changed, do not use from scripts)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "write_colr", "Write colr atom even if the color info is unspecified (Experimental, may be renamed or changed, do not use from scripts)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "prefer_icc", "If writing colr atom prioritise usage of ICC profile if it exists in stream packet side data", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_PREFER_ICC}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "use_metadata_tags", "Use mdta atom for metadata.", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_USE_MDTA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "skip_trailer", "Skip writing the mfra/tfra/mfro trailer for fragmented files", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SKIP_TRAILER}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, @@ -362,7 +365,7 @@ } struct eac3_info { - AVPacket pkt; + AVPacket *pkt; uint8_t ec3_done; uint8_t num_blocks; @@ -404,6 +407,9 @@ return AVERROR(ENOMEM); info = track->eac3_priv; + if (!info->pkt && !(info->pkt = av_packet_alloc())) + return AVERROR(ENOMEM); + if (avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size) < 0) { /* drop the packets until we see a good one */ if (!track->entry) { @@ -508,22 +514,20 @@ } if (!info->num_blocks) { - ret = av_packet_ref(&info->pkt, pkt); + ret = av_packet_ref(info->pkt, pkt); if (!ret) info->num_blocks = num_blocks; goto end; } else { - if ((ret = av_grow_packet(&info->pkt, pkt->size)) < 0) + if ((ret = av_grow_packet(info->pkt, pkt->size)) < 0) goto end; - memcpy(info->pkt.data + info->pkt.size - pkt->size, pkt->data, pkt->size); + memcpy(info->pkt->data + info->pkt->size - pkt->size, pkt->data, pkt->size); info->num_blocks += num_blocks; - info->pkt.duration += pkt->duration; - if ((ret = av_copy_packet_side_data(&info->pkt, pkt)) < 0) - goto end; + info->pkt->duration += pkt->duration; if (info->num_blocks != 6) goto end; av_packet_unref(pkt); - av_packet_move_ref(pkt, &info->pkt); + av_packet_move_ref(pkt, info->pkt); info->num_blocks = 0; } ret = pkt->size; @@ -632,12 +636,59 @@ return size * 8 * track->timescale / track->track_duration; } +struct mpeg4_bit_rate_values { + uint32_t buffer_size; ///< Size of the decoding buffer for the elementary stream in bytes. + uint32_t max_bit_rate; ///< Maximum rate in bits/second over any window of one second. + uint32_t avg_bit_rate; ///< Average rate in bits/second over the entire presentation. +}; + +static struct mpeg4_bit_rate_values calculate_mpeg4_bit_rates(MOVTrack *track) +{ + AVCPBProperties *props = track->st ? + (AVCPBProperties*)av_stream_get_side_data(track->st, + AV_PKT_DATA_CPB_PROPERTIES, + NULL) : + NULL; + struct mpeg4_bit_rate_values bit_rates = { 0 }; + + bit_rates.avg_bit_rate = compute_avg_bitrate(track); + if (!bit_rates.avg_bit_rate) { + // if the average bit rate cannot be calculated at this point, such as + // in the case of fragmented MP4, utilize the following values as + // fall-back in priority order: + // + // 1. average bit rate property + // 2. bit rate (usually average over the whole clip) + // 3. maximum bit rate property + + if (props && props->avg_bitrate) { + bit_rates.avg_bit_rate = props->avg_bitrate; + } else if (track->par->bit_rate) { + bit_rates.avg_bit_rate = track->par->bit_rate; + } else if (props && props->max_bitrate) { + bit_rates.avg_bit_rate = props->max_bitrate; + } + } + + // (FIXME should be max rate in any 1 sec window) + bit_rates.max_bit_rate = FFMAX(track->par->bit_rate, + bit_rates.avg_bit_rate); + + // utilize values from properties if we have them available + if (props) { + bit_rates.max_bit_rate = FFMAX(bit_rates.max_bit_rate, + props->max_bitrate); + bit_rates.buffer_size = props->buffer_size / 8; + } + + return bit_rates; +} + static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic { - AVCPBProperties *props; + struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track); int64_t pos = avio_tell(pb); int decoder_specific_info_len = track->vos_len ? 5 + track->vos_len : 0; - unsigned avg_bitrate; avio_wb32(pb, 0); // size ffio_wfourcc(pb, "esds"); @@ -668,14 +719,9 @@ else avio_w8(pb, 0x11); // flags (= Visualstream) - props = (AVCPBProperties*)av_stream_get_side_data(track->st, AV_PKT_DATA_CPB_PROPERTIES, - NULL); - - avio_wb24(pb, props ? props->buffer_size / 8 : 0); // Buffersize DB - - avg_bitrate = compute_avg_bitrate(track); - avio_wb32(pb, props ? FFMAX3(props->max_bitrate, props->avg_bitrate, avg_bitrate) : FFMAX(track->par->bit_rate, avg_bitrate)); // maxbitrate (FIXME should be max rate in any 1 sec window) - avio_wb32(pb, avg_bitrate); + avio_wb24(pb, bit_rates.buffer_size); // Buffersize DB + avio_wb32(pb, bit_rates.max_bit_rate); // maxbitrate + avio_wb32(pb, bit_rates.avg_bit_rate); if (track->vos_len) { // DecoderSpecific info descriptor @@ -771,6 +817,35 @@ return update_size(pb, pos); } +static int mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) +{ + int64_t pos = avio_tell(pb); + int length; + avio_wb32(pb, 0); + ffio_wfourcc(pb, "dmlp"); + + if (track->vos_len < 20) { + av_log(s, AV_LOG_ERROR, + "Cannot write moov atom before TrueHD packets." + " Set the delay_moov flag to fix this.\n"); + return AVERROR(EINVAL); + } + + length = (AV_RB16(track->vos_data) & 0xFFF) * 2; + if (length < 20 || length > track->vos_len) + return AVERROR_INVALIDDATA; + + // Only TrueHD is supported + if (AV_RB32(track->vos_data + 4) != 0xF8726FBA) + return AVERROR_INVALIDDATA; + + avio_wb32(pb, AV_RB32(track->vos_data + 8)); /* format_info */ + avio_wb16(pb, AV_RB16(track->vos_data + 18) << 1); /* peak_data_rate */ + avio_wb32(pb, 0); /* reserved */ + + return update_size(pb, pos); +} + static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { uint32_t layout_tag, bitmap; @@ -1019,6 +1094,25 @@ return first_duration; } +static int mov_write_btrt_tag(AVIOContext *pb, MOVTrack *track) +{ + int64_t pos = avio_tell(pb); + struct mpeg4_bit_rate_values bit_rates = calculate_mpeg4_bit_rates(track); + if (!bit_rates.max_bit_rate && !bit_rates.avg_bit_rate && + !bit_rates.buffer_size) + // no useful data to be written, skip + return 0; + + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "btrt"); + + avio_wb32(pb, bit_rates.buffer_size); + avio_wb32(pb, bit_rates.max_bit_rate); + avio_wb32(pb, bit_rates.avg_bit_rate); + + return update_size(pb, pos); +} + static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { int64_t pos = avio_tell(pb); @@ -1100,10 +1194,14 @@ avio_wb16(pb, 0); /* packet size (= 0) */ if (track->par->codec_id == AV_CODEC_ID_OPUS) avio_wb16(pb, 48000); + else if (track->par->codec_id == AV_CODEC_ID_TRUEHD) + avio_wb32(pb, track->par->sample_rate); else avio_wb16(pb, track->par->sample_rate <= UINT16_MAX ? track->par->sample_rate : 0); - avio_wb16(pb, 0); /* Reserved */ + + if (track->par->codec_id != AV_CODEC_ID_TRUEHD) + avio_wb16(pb, 0); /* Reserved */ } if (version == 1) { /* SoundDescription V1 extended info */ @@ -1145,6 +1243,8 @@ ret = mov_write_dfla_tag(pb, track); else if (track->par->codec_id == AV_CODEC_ID_OPUS) ret = mov_write_dops_tag(s, pb, track); + else if (track->par->codec_id == AV_CODEC_ID_TRUEHD) + ret = mov_write_dmlp_tag(s, pb, track); else if (track->vos_len > 0) ret = mov_write_glbl_tag(pb, track); @@ -1161,6 +1261,10 @@ return ret; } + if (track->mode == MODE_MP4 && + ((ret = mov_write_btrt_tag(pb, track)) < 0)) + return ret; + ret = update_size(pb, pos); return ret; } @@ -1552,6 +1656,10 @@ { unsigned int tag = track->par->codec_tag; + // "rtp " is used to distinguish internally created RTP-hint tracks + // (with rtp_ctx) from other tracks. + if (tag == MKTAG('r','t','p',' ')) + tag = 0; if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL && (track->par->codec_id == AV_CODEC_ID_DVVIDEO || track->par->codec_id == AV_CODEC_ID_RAWVIDEO || @@ -1676,6 +1784,7 @@ static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track) { + int ret = AVERROR_BUG; int64_t pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ avio_wl32(pb, track->tag); // store it byteswapped @@ -1688,6 +1797,10 @@ else if (track->par->extradata_size) avio_write(pb, track->par->extradata, track->par->extradata_size); + if (track->mode == MODE_MP4 && + ((ret = mov_write_btrt_tag(pb, track)) < 0)) + return ret; + return update_size(pb, pos); } @@ -1779,6 +1892,36 @@ return update_size(pb, sv3d_pos); } +static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDecoderConfigurationRecord *dovi) +{ + avio_wb32(pb, 32); /* size = 8 + 24 */ + 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); + + avio_wb32(pb, 0); /* reserved */ + avio_wb32(pb, 0); /* reserved */ + avio_wb32(pb, 0); /* reserved */ + avio_wb32(pb, 0); /* 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); + return 32; /* 8 + 24 */ +} + static int mov_write_clap_tag(AVIOContext *pb, MOVTrack *track) { avio_wb32(pb, 40); @@ -1830,85 +1973,103 @@ return 0; } -static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc) { + int64_t pos = avio_tell(pb); + // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9 // Ref (MP4): ISO/IEC 14496-12:2012 - if (track->par->color_primaries == AVCOL_PRI_UNSPECIFIED && - track->par->color_trc == AVCOL_TRC_UNSPECIFIED && - track->par->color_space == AVCOL_SPC_UNSPECIFIED) { - if ((track->par->width >= 1920 && track->par->height >= 1080) - || (track->par->width == 1280 && track->par->height == 720)) { - av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming bt709\n"); - track->par->color_primaries = AVCOL_PRI_BT709; - } else if (track->par->width == 720 && track->height == 576) { - av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming bt470bg\n"); - track->par->color_primaries = AVCOL_PRI_BT470BG; - } else if (track->par->width == 720 && - (track->height == 486 || track->height == 480)) { - av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming smpte170\n"); - track->par->color_primaries = AVCOL_PRI_SMPTE170M; - } else { - av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, unable to assume anything\n"); + const uint8_t *icc_profile; + buffer_size_t icc_profile_size; + + if (prefer_icc) { + icc_profile = av_stream_get_side_data(track->st, AV_PKT_DATA_ICC_PROFILE, &icc_profile_size); + + if (icc_profile) { + avio_wb32(pb, 12 + icc_profile_size); + ffio_wfourcc(pb, "colr"); + ffio_wfourcc(pb, "prof"); + avio_write(pb, icc_profile, icc_profile_size); + return 12 + icc_profile_size; } - switch (track->par->color_primaries) { - case AVCOL_PRI_BT709: - track->par->color_trc = AVCOL_TRC_BT709; - track->par->color_space = AVCOL_SPC_BT709; - break; - case AVCOL_PRI_SMPTE170M: - case AVCOL_PRI_BT470BG: - track->par->color_trc = AVCOL_TRC_BT709; - track->par->color_space = AVCOL_SPC_SMPTE170M; - break; + else { + av_log(NULL, AV_LOG_INFO, "no ICC profile found, will write nclx/nclc colour info instead\n"); } } /* We should only ever be called by MOV or MP4. */ av_assert0(track->mode == MODE_MOV || track->mode == MODE_MP4); - avio_wb32(pb, 18 + (track->mode == MODE_MP4)); + avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "colr"); if (track->mode == MODE_MP4) ffio_wfourcc(pb, "nclx"); else ffio_wfourcc(pb, "nclc"); - switch (track->par->color_primaries) { - case AVCOL_PRI_BT709: avio_wb16(pb, 1); break; - case AVCOL_PRI_BT470BG: avio_wb16(pb, 5); break; - case AVCOL_PRI_SMPTE170M: - case AVCOL_PRI_SMPTE240M: avio_wb16(pb, 6); break; - case AVCOL_PRI_BT2020: avio_wb16(pb, 9); break; - case AVCOL_PRI_SMPTE431: avio_wb16(pb, 11); break; - case AVCOL_PRI_SMPTE432: avio_wb16(pb, 12); break; - default: avio_wb16(pb, 2); - } - switch (track->par->color_trc) { - case AVCOL_TRC_BT709: avio_wb16(pb, 1); break; - case AVCOL_TRC_SMPTE170M: avio_wb16(pb, 1); break; // remapped - case AVCOL_TRC_SMPTE240M: avio_wb16(pb, 7); break; - case AVCOL_TRC_SMPTEST2084: avio_wb16(pb, 16); break; - case AVCOL_TRC_SMPTE428: avio_wb16(pb, 17); break; - case AVCOL_TRC_ARIB_STD_B67: avio_wb16(pb, 18); break; - default: avio_wb16(pb, 2); - } - switch (track->par->color_space) { - case AVCOL_SPC_BT709: avio_wb16(pb, 1); break; - case AVCOL_SPC_BT470BG: - case AVCOL_SPC_SMPTE170M: avio_wb16(pb, 6); break; - case AVCOL_SPC_SMPTE240M: avio_wb16(pb, 7); break; - case AVCOL_SPC_BT2020_NCL: avio_wb16(pb, 9); break; - default: avio_wb16(pb, 2); - } - + // Do not try to guess the color info if it is AVCOL_PRI_UNSPECIFIED. + // e.g., Dolby Vision for Apple devices should be set to AVCOL_PRI_UNSPECIFIED. See + // https://developer.apple.com/av-foundation/High-Dynamic-Range-Metadata-for-Apple-Devices.pdf + avio_wb16(pb, track->par->color_primaries); + avio_wb16(pb, track->par->color_trc); + avio_wb16(pb, track->par->color_space); if (track->mode == MODE_MP4) { int full_range = track->par->color_range == AVCOL_RANGE_JPEG; avio_w8(pb, full_range << 7); - return 19; - } else { - return 18; } + + return update_size(pb, pos); +} + +static int mov_write_clli_tag(AVIOContext *pb, MOVTrack *track) +{ + const uint8_t *side_data; + const AVContentLightMetadata *content_light_metadata; + + side_data = av_stream_get_side_data(track->st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL, NULL); + if (!side_data) { + return 0; + } + content_light_metadata = (const AVContentLightMetadata*)side_data; + + avio_wb32(pb, 12); // size + ffio_wfourcc(pb, "clli"); + avio_wb16(pb, content_light_metadata->MaxCLL); + avio_wb16(pb, content_light_metadata->MaxFALL); + return 12; +} + +static inline int64_t rescale_mdcv(AVRational q, int b) +{ + return av_rescale(q.num, b, q.den); +} + +static int mov_write_mdcv_tag(AVIOContext *pb, MOVTrack *track) +{ + const int chroma_den = 50000; + const int luma_den = 10000; + const uint8_t *side_data; + const AVMasteringDisplayMetadata *metadata; + + side_data = av_stream_get_side_data(track->st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, NULL); + metadata = (const AVMasteringDisplayMetadata*)side_data; + if (!metadata || !metadata->has_primaries || !metadata->has_luminance) { + return 0; + } + + avio_wb32(pb, 32); // size + ffio_wfourcc(pb, "mdcv"); + avio_wb16(pb, rescale_mdcv(metadata->display_primaries[1][0], chroma_den)); + avio_wb16(pb, rescale_mdcv(metadata->display_primaries[1][1], chroma_den)); + avio_wb16(pb, rescale_mdcv(metadata->display_primaries[2][0], chroma_den)); + avio_wb16(pb, rescale_mdcv(metadata->display_primaries[2][1], chroma_den)); + avio_wb16(pb, rescale_mdcv(metadata->display_primaries[0][0], chroma_den)); + avio_wb16(pb, rescale_mdcv(metadata->display_primaries[0][1], chroma_den)); + avio_wb16(pb, rescale_mdcv(metadata->white_point[0], chroma_den)); + avio_wb16(pb, rescale_mdcv(metadata->white_point[1], chroma_den)); + avio_wb32(pb, rescale_mdcv(metadata->max_luminance, luma_den)); + avio_wb32(pb, rescale_mdcv(metadata->min_luminance, luma_den)); + return 32; } static void find_compressor(char * compressor_name, int len, MOVTrack *track) @@ -1941,6 +2102,7 @@ static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { + int ret = AVERROR_BUG; int64_t pos = avio_tell(pb); char compressor_name[32] = { 0 }; int avid = 0; @@ -2078,21 +2240,35 @@ else av_log(mov->fc, AV_LOG_WARNING, "Not writing 'gama' atom. Format is not MOV.\n"); } - if (mov->flags & FF_MOV_FLAG_WRITE_COLR) { - if (track->mode == MODE_MOV || track->mode == MODE_MP4) - mov_write_colr_tag(pb, track); - else - av_log(mov->fc, AV_LOG_WARNING, "Not writing 'colr' atom. Format is not MOV or MP4.\n"); + if (track->mode == MODE_MOV || track->mode == MODE_MP4) { + int has_color_info = track->par->color_primaries != AVCOL_PRI_UNSPECIFIED && + track->par->color_trc != AVCOL_TRC_UNSPECIFIED && + track->par->color_space != AVCOL_SPC_UNSPECIFIED; + if (has_color_info || mov->flags & FF_MOV_FLAG_WRITE_COLR || + av_stream_get_side_data(track->st, AV_PKT_DATA_ICC_PROFILE, NULL)) { + int prefer_icc = mov->flags & FF_MOV_FLAG_PREFER_ICC || !has_color_info; + mov_write_colr_tag(pb, track, prefer_icc); + } else if (mov->flags & FF_MOV_FLAG_WRITE_COLR) { + av_log(mov->fc, AV_LOG_WARNING, "Not writing 'colr' atom. Format is not MOV or MP4.\n"); + } + } + if (track->mode == MODE_MOV || track->mode == MODE_MP4) { + mov_write_clli_tag(pb, track); + mov_write_mdcv_tag(pb, track); } if (track->mode == MODE_MP4 && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) { AVStereo3D* stereo_3d = (AVStereo3D*) av_stream_get_side_data(track->st, AV_PKT_DATA_STEREO3D, NULL); AVSphericalMapping* spherical_mapping = (AVSphericalMapping*)av_stream_get_side_data(track->st, AV_PKT_DATA_SPHERICAL, NULL); + AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *) + av_stream_get_side_data(track->st, AV_PKT_DATA_DOVI_CONF, NULL); if (stereo_3d) mov_write_st3d_tag(s, pb, stereo_3d); if (spherical_mapping) mov_write_sv3d_tag(mov->fc, pb, spherical_mapping); + if (dovi) + mov_write_dvcc_dvvc_tag(s, pb, dovi); } if (track->par->sample_aspect_ratio.den && track->par->sample_aspect_ratio.num) { @@ -2107,6 +2283,10 @@ ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid); } + if (track->mode == MODE_MP4 && + ((ret = mov_write_btrt_tag(pb, track)) < 0)) + return ret; + /* extra padding for avid stsd */ /* https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-61112 */ if (avid) @@ -2456,6 +2636,8 @@ return ret; mov_write_stts_tag(pb, track); if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO || + track->par->codec_id == AV_CODEC_ID_TRUEHD || + track->par->codec_id == AV_CODEC_ID_MPEGH_3D_AUDIO || track->par->codec_tag == MKTAG('r','t','p',' ')) && track->has_keyframes && track->has_keyframes < track->entry) mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE); @@ -2627,7 +2809,7 @@ } else { hdlr_type = "text"; } - descr = "SubtitleHandler"; + descr = "SubtitleHandler"; } } else if (track->par->codec_tag == MKTAG('r','t','p',' ')) { hdlr_type = "hint"; @@ -2723,10 +2905,57 @@ return update_size(pb, pos); } +static void get_pts_range(MOVMuxContext *mov, MOVTrack *track, + int64_t *start, int64_t *end) +{ + if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) { + // tmcd tracks gets track_duration set in mov_write_moov_tag from + // another track's duration, while the end_pts may be left at zero. + // Calculate the pts duration for that track instead. + get_pts_range(mov, &mov->tracks[track->src_track], start, end); + *start = av_rescale(*start, track->timescale, + mov->tracks[track->src_track].timescale); + *end = av_rescale(*end, track->timescale, + mov->tracks[track->src_track].timescale); + return; + } + if (track->end_pts != AV_NOPTS_VALUE && + track->start_dts != AV_NOPTS_VALUE && + track->start_cts != AV_NOPTS_VALUE) { + *start = track->start_dts + track->start_cts; + *end = track->end_pts; + return; + } + *start = 0; + *end = track->track_duration; +} + +static int64_t calc_samples_pts_duration(MOVMuxContext *mov, MOVTrack *track) +{ + int64_t start, end; + get_pts_range(mov, track, &start, &end); + return end - start; +} + +// Calculate the actual duration of the track, after edits. +// If it starts with a pts < 0, that is removed by the edit list. +// If it starts with a pts > 0, the edit list adds a delay before that. +// Thus, with edit lists enabled, the post-edit output of the file is +// starting with pts=0. +static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track) +{ + int64_t start, end; + get_pts_range(mov, track, &start, &end); + if (mov->use_editlist != 0) + start = 0; + return end - start; +} + static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { - int version = track->track_duration < INT32_MAX ? 0 : 1; + int64_t duration = calc_pts_duration(mov, track); + int version = duration < INT32_MAX ? 0 : 1; if (track->mode == MODE_ISM) version = 1; @@ -2748,7 +2977,7 @@ else if (!track->entry) (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0); else - (version == 1) ? avio_wb64(pb, track->track_duration) : avio_wb32(pb, track->track_duration); /* duration */ + (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration); /* duration */ avio_wb16(pb, track->language); /* language */ avio_wb16(pb, 0); /* reserved (quality) */ @@ -2798,15 +3027,17 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, AVStream *st) { - int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE, - track->timescale, AV_ROUND_UP); + int64_t duration = av_rescale_rnd(calc_pts_duration(mov, track), + MOV_TIMESCALE, track->timescale, + AV_ROUND_UP); int version = duration < INT32_MAX ? 0 : 1; int flags = MOV_TKHD_FLAG_IN_MOVIE; int rotation = 0; int group = 0; uint32_t *display_matrix = NULL; - int display_matrix_size, i; + buffer_size_t display_matrix_size; + int i; if (st) { if (mov->per_stream_grouping) @@ -2945,8 +3176,9 @@ static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { - int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE, - track->timescale, AV_ROUND_UP); + int64_t duration = av_rescale_rnd(calc_samples_pts_duration(mov, track), + MOV_TIMESCALE, track->timescale, + AV_ROUND_UP); int version = duration < INT32_MAX ? 0 : 1; int entry_size, entry_count, size; int64_t delay, start_ct = track->start_cts; @@ -3108,12 +3340,12 @@ if (mov->mode & (MODE_MP4|MODE_MOV)) mov_write_track_metadata(pb_buf, st, "name", "title"); - if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) { + if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) { avio_wb32(pb, size + 8); ffio_wfourcc(pb, "udta"); avio_write(pb, buf, size); } - av_free(buf); + ffio_free_dyn_buf(&pb_buf); return 0; } @@ -3232,7 +3464,8 @@ for (i = 0; i < mov->nb_streams; i++) { if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) { - int64_t max_track_len_temp = av_rescale_rnd(mov->tracks[i].track_duration, + int64_t max_track_len_temp = av_rescale_rnd( + calc_pts_duration(mov, &mov->tracks[i]), MOV_TIMESCALE, mov->tracks[i].timescale, AV_ROUND_UP); @@ -3503,7 +3736,7 @@ for (i = 0; i < s->nb_streams; i++) { MOVTrack *trk = &mov->tracks[i]; - if (!is_cover_image(trk->st) || trk->cover_image.size <= 0) + if (!is_cover_image(trk->st) || trk->cover_image->size <= 0) continue; if (!pos) { @@ -3511,11 +3744,11 @@ avio_wb32(pb, 0); ffio_wfourcc(pb, "covr"); } - avio_wb32(pb, 16 + trk->cover_image.size); + avio_wb32(pb, 16 + trk->cover_image->size); ffio_wfourcc(pb, "data"); avio_wb32(pb, trk->tag); avio_wb32(pb , 0); - avio_write(pb, trk->cover_image.data, trk->cover_image.size); + avio_write(pb, trk->cover_image->data, trk->cover_image->size); } return pos ? update_size(pb, pos) : 0; @@ -3783,12 +4016,12 @@ if (s->nb_chapters && !(mov->flags & FF_MOV_FLAG_DISABLE_CHPL)) mov_write_chpl_tag(pb_buf, s); - if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) { + if ((size = avio_get_dyn_buf(pb_buf, &buf)) > 0) { avio_wb32(pb, size + 8); ffio_wfourcc(pb, "udta"); avio_write(pb, buf, size); } - av_free(buf); + ffio_free_dyn_buf(&pb_buf); return 0; } @@ -3944,7 +4177,8 @@ track->tref_tag = MKTAG('h','i','n','t'); track->tref_id = mov->tracks[track->src_track].track_id; } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) { - int * fallback, size; + buffer_size_t size; + int *fallback; fallback = (int*)av_stream_get_side_data(track->st, AV_PKT_DATA_FALLBACK_TRACK, &size); @@ -4012,8 +4246,6 @@ { int64_t pos = avio_tell(pb); int i; - int64_t manifest_bit_rate = 0; - AVCPBProperties *props = NULL; static const uint8_t uuid[] = { 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd, @@ -4039,6 +4271,8 @@ for (i = 0; i < mov->nb_streams; i++) { MOVTrack *track = &mov->tracks[i]; + struct mpeg4_bit_rate_values bit_rates = + calculate_mpeg4_bit_rates(track); const char *type; int track_id = track->track_id; char track_name_buf[32] = { 0 }; @@ -4054,17 +4288,9 @@ continue; } - props = (AVCPBProperties*)av_stream_get_side_data(track->st, AV_PKT_DATA_CPB_PROPERTIES, NULL); - - if (track->par->bit_rate) { - manifest_bit_rate = track->par->bit_rate; - } else if (props) { - manifest_bit_rate = props->max_bitrate; - } - - avio_printf(pb, "<%s systemBitrate=\"%"PRId64"\">\n", type, - manifest_bit_rate); - param_write_int(pb, "systemBitrate", manifest_bit_rate); + avio_printf(pb, "<%s systemBitrate=\"%"PRIu32"\">\n", type, + bit_rates.avg_bit_rate); + param_write_int(pb, "systemBitrate", bit_rates.avg_bit_rate); param_write_int(pb, "trackID", track_id); param_write_string(pb, "systemLanguage", lang ? lang->value : "und"); @@ -4172,6 +4398,9 @@ flags &= ~MOV_TFHD_BASE_DATA_OFFSET; flags |= MOV_TFHD_DEFAULT_BASE_IS_MOOF; } + /* CMAF requires all values to be explicit in tfhd atoms */ + if (mov->flags & FF_MOV_FLAG_CMAF) + flags |= MOV_TFHD_STSD_ID; /* Don't set a default sample size, the silverlight player refuses * to play files with that set. Don't set a default sample duration, @@ -4179,7 +4408,7 @@ * file format says it MUST NOT be set. */ if (track->mode == MODE_ISM) flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION | - MOV_TFHD_BASE_DATA_OFFSET); + MOV_TFHD_BASE_DATA_OFFSET | MOV_TFHD_STSD_ID); avio_wb32(pb, 0); /* size placeholder */ ffio_wfourcc(pb, "tfhd"); @@ -4189,6 +4418,9 @@ avio_wb32(pb, track->track_id); /* track-id */ if (flags & MOV_TFHD_BASE_DATA_OFFSET) avio_wb64(pb, moof_offset); + if (flags & MOV_TFHD_STSD_ID) { + avio_wb32(pb, 1); + } if (flags & MOV_TFHD_DEFAULT_DURATION) { track->default_duration = get_cluster_duration(track, 0); avio_wb32(pb, track->default_duration); @@ -4475,7 +4707,8 @@ { int64_t pos = avio_tell(pb), offset_pos, end_pos; int64_t presentation_time, duration, offset; - int starts_with_SAP, i, entries; + unsigned starts_with_SAP; + int i, entries; if (track->entry) { entries = 1; @@ -4570,6 +4803,7 @@ { int64_t pos = avio_tell(pb), pts_us, ntp_ts; MOVTrack *first_track; + int flags = 24; /* PRFT should be associated with at most one track. So, choosing only the * first track. */ @@ -4588,7 +4822,13 @@ } if (mov->write_prft == MOV_PRFT_SRC_WALLCLOCK) { - ntp_ts = ff_get_formatted_ntp_time(ff_ntp_time()); + if (first_track->cluster[0].prft.wallclock) { + /* Round the NTP time to whole milliseconds. */ + ntp_ts = ff_get_formatted_ntp_time((first_track->cluster[0].prft.wallclock / 1000) * 1000 + + NTP_OFFSET_US); + flags = first_track->cluster[0].prft.flags; + } else + ntp_ts = ff_get_formatted_ntp_time(ff_ntp_time()); } else if (mov->write_prft == MOV_PRFT_SRC_PTS) { pts_us = av_rescale_q(first_track->cluster[0].pts, first_track->st->time_base, AV_TIME_BASE_Q); @@ -4602,7 +4842,7 @@ avio_wb32(pb, 0); // Size place holder ffio_wfourcc(pb, "prft"); // Type avio_w8(pb, 1); // Version - avio_wb24(pb, 0); // Flags + avio_wb24(pb, flags); // Flags avio_wb32(pb, first_track->track_id); // reference track ID avio_wb64(pb, ntp_ts); // NTP time stamp avio_wb64(pb, first_track->cluster[0].pts); //media time @@ -4667,28 +4907,40 @@ static int mov_write_mfra_tag(AVIOContext *pb, MOVMuxContext *mov) { - int64_t pos = avio_tell(pb); - int i; + AVIOContext *mfra_pb; + int i, ret, sz; + uint8_t *buf; - avio_wb32(pb, 0); /* size placeholder */ - ffio_wfourcc(pb, "mfra"); + ret = avio_open_dyn_buf(&mfra_pb); + if (ret < 0) + return ret; + + avio_wb32(mfra_pb, 0); /* size placeholder */ + ffio_wfourcc(mfra_pb, "mfra"); /* An empty mfra atom is enough to indicate to the publishing point that * the stream has ended. */ if (mov->flags & FF_MOV_FLAG_ISML) - return update_size(pb, pos); + goto done_mfra; for (i = 0; i < mov->nb_streams; i++) { MOVTrack *track = &mov->tracks[i]; if (track->nb_frag_info) - mov_write_tfra_tag(pb, track); + mov_write_tfra_tag(mfra_pb, track); } - avio_wb32(pb, 16); - ffio_wfourcc(pb, "mfro"); - avio_wb32(pb, 0); /* version + flags */ - avio_wb32(pb, avio_tell(pb) + 4 - pos); + avio_wb32(mfra_pb, 16); + ffio_wfourcc(mfra_pb, "mfro"); + avio_wb32(mfra_pb, 0); /* version + flags */ + avio_wb32(mfra_pb, avio_tell(mfra_pb) + 4); - return update_size(pb, pos); +done_mfra: + + sz = update_size(mfra_pb, 0); + ret = avio_get_dyn_buf(mfra_pb, &buf); + avio_write(pb, buf, ret); + ffio_free_dyn_buf(&mfra_pb); + + return sz; } static int mov_write_mdat_tag(AVIOContext *pb, MOVMuxContext *mov) @@ -4702,27 +4954,11 @@ return 0; } -/* TODO: This needs to be more general */ -static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) +static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s, + int has_h264, int has_video, int write_minor) { MOVMuxContext *mov = s->priv_data; - int64_t pos = avio_tell(pb); - int has_h264 = 0, has_video = 0; int minor = 0x200; - int i; - - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - if (is_cover_image(st)) - continue; - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) - has_video = 1; - if (st->codecpar->codec_id == AV_CODEC_ID_H264) - has_h264 = 1; - } - - avio_wb32(pb, 0); /* size */ - ffio_wfourcc(pb, "ftyp"); if (mov->major_brand && strlen(mov->major_brand) >= 4) ffio_wfourcc(pb, mov->major_brand); @@ -4734,6 +4970,9 @@ minor = has_h264 ? 0x20000 : 0x10000; } else if (mov->mode == MODE_PSP) ffio_wfourcc(pb, "MSNV"); + else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_FRAGMENT && + mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) + ffio_wfourcc(pb, "iso6"); // Required when using signed CTS offsets in trun boxes else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) @@ -4749,31 +4988,72 @@ else ffio_wfourcc(pb, "qt "); - avio_wb32(pb, minor); + if (write_minor) + avio_wb32(pb, minor); +} - if (mov->mode == MODE_MOV) - ffio_wfourcc(pb, "qt "); - else if (mov->mode == MODE_ISM) { +static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) +{ + MOVMuxContext *mov = s->priv_data; + int64_t pos = avio_tell(pb); + int has_h264 = 0, has_av1 = 0, has_video = 0; + int i; + + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + if (is_cover_image(st)) + continue; + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) + has_video = 1; + if (st->codecpar->codec_id == AV_CODEC_ID_H264) + has_h264 = 1; + if (st->codecpar->codec_id == AV_CODEC_ID_AV1) + has_av1 = 1; + } + + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "ftyp"); + + // Write major brand + mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 1); + // Write the major brand as the first compatible brand as well + mov_write_ftyp_tag_internal(pb, s, has_h264, has_video, 0); + + // Write compatible brands, ensuring that we don't write the major brand as a + // compatible brand a second time. + if (mov->mode == MODE_ISM) { ffio_wfourcc(pb, "piff"); - } else if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) { - ffio_wfourcc(pb, "isom"); - ffio_wfourcc(pb, "iso2"); - if (has_h264) - ffio_wfourcc(pb, "avc1"); + } else if (mov->mode != MODE_MOV) { + // We add tfdt atoms when fragmenting, signal this with the iso6 compatible + // brand, if not already the major brand. This is compatible with users that + // don't understand tfdt. + if (mov->mode == MODE_MP4) { + if (mov->flags & FF_MOV_FLAG_CMAF) + ffio_wfourcc(pb, "cmfc"); + if (mov->flags & FF_MOV_FLAG_FRAGMENT && !(mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)) + ffio_wfourcc(pb, "iso6"); + if (has_av1) + ffio_wfourcc(pb, "av01"); + } else { + if (mov->flags & FF_MOV_FLAG_FRAGMENT) + ffio_wfourcc(pb, "iso6"); + if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) + ffio_wfourcc(pb, "iso5"); + else if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) + ffio_wfourcc(pb, "iso4"); + } + // Brands prior to iso5 can't be signaled when using default-base-is-moof + if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) { + // write isom for mp4 only if it it's not the major brand already. + if (mov->mode != MODE_MP4 || mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) + ffio_wfourcc(pb, "isom"); + ffio_wfourcc(pb, "iso2"); + if (has_h264) + ffio_wfourcc(pb, "avc1"); + } } - // We add tfdt atoms when fragmenting, signal this with the iso6 compatible - // brand. This is compatible with users that don't understand tfdt. - if (mov->flags & FF_MOV_FLAG_FRAGMENT && mov->mode != MODE_ISM) - ffio_wfourcc(pb, "iso6"); - - if (mov->mode == MODE_3GP) - ffio_wfourcc(pb, has_h264 ? "3gp6":"3gp4"); - else if (mov->mode & MODE_3G2) - ffio_wfourcc(pb, has_h264 ? "3g2b":"3g2a"); - else if (mov->mode == MODE_PSP) - ffio_wfourcc(pb, "MSNV"); - else if (mov->mode == MODE_MP4) + if (mov->mode == MODE_MP4) ffio_wfourcc(pb, "mp41"); if (mov->flags & FF_MOV_FLAG_DASH && mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) @@ -4963,6 +5243,25 @@ } } +static void mov_parse_truehd_frame(AVPacket *pkt, MOVTrack *trk) +{ + int length; + + if (pkt->size < 8) + return; + + length = (AV_RB16(pkt->data) & 0xFFF) * 2; + if (length < 8 || length > pkt->size) + return; + + if (AV_RB32(pkt->data + 4) == 0xF8726FBA) { + trk->cluster[trk->entry].flags |= MOV_SYNC_SAMPLE; + trk->has_keyframes++; + } + + return; +} + static int mov_flush_fragment_interleaving(AVFormatContext *s, MOVTrack *track) { MOVMuxContext *mov = s->priv_data; @@ -4976,12 +5275,11 @@ if ((ret = avio_open_dyn_buf(&mov->mdat_buf)) < 0) return ret; } - buf_size = avio_close_dyn_buf(track->mdat_buf, &buf); - track->mdat_buf = NULL; + buf_size = avio_get_dyn_buf(track->mdat_buf, &buf); offset = avio_tell(mov->mdat_buf); avio_write(mov->mdat_buf, buf, buf_size); - av_free(buf); + ffio_free_dyn_buf(&track->mdat_buf); for (i = track->entries_flushed; i < track->entry; i++) track->cluster[i].pos += offset; @@ -5008,15 +5306,19 @@ for (i = 0; i < s->nb_streams; i++) { MOVTrack *track = &mov->tracks[i]; if (!track->end_reliable) { - AVPacket pkt; - if (!ff_interleaved_peek(s, i, &pkt, 1)) { + const AVPacket *pkt = ff_interleaved_peek(s, i); + if (pkt) { + int64_t offset, dts, pts; + ff_get_muxer_ts_offset(s, i, &offset); + pts = pkt->pts + offset; + dts = pkt->dts + offset; if (track->dts_shift != AV_NOPTS_VALUE) - pkt.dts += track->dts_shift; - track->track_duration = pkt.dts - track->start_dts; - if (pkt.pts != AV_NOPTS_VALUE) - track->end_pts = pkt.pts; + dts += track->dts_shift; + track->track_duration = dts - track->start_dts; + if (pts != AV_NOPTS_VALUE) + track->end_pts = pts; else - track->end_pts = pkt.dts; + track->end_pts = dts; } } } @@ -5073,17 +5375,16 @@ if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) { if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) mov->reserved_header_pos = avio_tell(s->pb); - avio_flush(s->pb); + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); mov->moov_written = 1; return 0; } - buf_size = avio_close_dyn_buf(mov->mdat_buf, &buf); - mov->mdat_buf = NULL; + buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf); avio_wb32(s->pb, buf_size + 8); ffio_wfourcc(s->pb, "mdat"); avio_write(s->pb, buf, buf_size); - av_free(buf); + ffio_free_dyn_buf(&mov->mdat_buf); if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) mov->reserved_header_pos = avio_tell(s->pb); @@ -5098,7 +5399,7 @@ mov->tracks[i].entry = 0; mov->tracks[i].end_reliable = 0; } - avio_flush(s->pb); + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); return 0; } @@ -5163,7 +5464,7 @@ } if (write_moof) { - avio_flush(s->pb); + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size); mov->fragments++; @@ -5195,7 +5496,7 @@ mov->mdat_size = 0; - avio_flush(s->pb); + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); return 0; } @@ -5257,8 +5558,10 @@ AVIOContext *pb = s->pb; MOVTrack *trk = &mov->tracks[pkt->stream_index]; AVCodecParameters *par = trk->par; + AVProducerReferenceTime *prft; unsigned int samples_in_chunk = 0; - int size = pkt->size, ret = 0; + int size = pkt->size, ret = 0, offset = 0; + buffer_size_t prft_size; uint8_t *reformatted_data = NULL; ret = check_pkt(s, pkt); @@ -5330,6 +5633,23 @@ memset(trk->vos_data + trk->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE); } + if ((par->codec_id == AV_CODEC_ID_DNXHD || + par->codec_id == AV_CODEC_ID_H264 || + par->codec_id == AV_CODEC_ID_HEVC || + par->codec_id == AV_CODEC_ID_TRUEHD || + par->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len && + !TAG_IS_AVCI(trk->tag)) { + /* copy frame to create needed atoms */ + trk->vos_len = size; + trk->vos_data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!trk->vos_data) { + ret = AVERROR(ENOMEM); + goto err; + } + memcpy(trk->vos_data, pkt->data, size); + memset(trk->vos_data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + } + if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { if (!s->streams[pkt->stream_index]->nb_frames) { @@ -5344,8 +5664,10 @@ /* from x264 or from bytestream H.264 */ /* NAL reformatting needed */ if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) { - ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data, - &size); + ret = ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data, + &size); + if (ret < 0) + return ret; avio_write(pb, reformatted_data, size); } else { if (trk->cenc.aes_ctr) { @@ -5362,14 +5684,20 @@ (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) { /* extradata is Annex B, assume the bitstream is too and convert it */ if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) { - ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data, &size, 0, NULL); + ret = ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data, + &size, 0, NULL); + if (ret < 0) + return ret; avio_write(pb, reformatted_data, size); } else { size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL); } } else if (par->codec_id == AV_CODEC_ID_AV1) { if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) { - ff_av1_filter_obus_buf(pkt->data, &reformatted_data, &size); + ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data, + &size, &offset); + if (ret < 0) + return ret; avio_write(pb, reformatted_data, size); } else { size = ff_av1_filter_obus(pb, pkt->data, pkt->size); @@ -5383,6 +5711,22 @@ goto end; avio_write(pb, pkt->data, size); #endif + } else if (par->codec_id == AV_CODEC_ID_EIA_608) { + size = 8; + + for (int i = 0; i < pkt->size; i += 3) { + if (pkt->data[i] == 0xFC) { + size += 2; + } + } + avio_wb32(pb, size); + ffio_wfourcc(pb, "cdat"); + for (int i = 0; i < pkt->size; i += 3) { + if (pkt->data[i] == 0xFC) { + avio_w8(pb, pkt->data[i + 1]); + avio_w8(pb, pkt->data[i + 2]); + } + } } else { if (trk->cenc.aes_ctr) { if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 4) { @@ -5400,26 +5744,14 @@ } } - if ((par->codec_id == AV_CODEC_ID_DNXHD || - par->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len) { - /* copy frame to create needed atoms */ - trk->vos_len = size; - trk->vos_data = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!trk->vos_data) { - ret = AVERROR(ENOMEM); - goto err; - } - memcpy(trk->vos_data, pkt->data, size); - memset(trk->vos_data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); - } - if (trk->entry >= trk->cluster_capacity) { - unsigned new_capacity = 2 * (trk->entry + MOV_INDEX_CLUSTER_SIZE); - if (av_reallocp_array(&trk->cluster, new_capacity, - sizeof(*trk->cluster))) { + unsigned new_capacity = trk->entry + MOV_INDEX_CLUSTER_SIZE; + void *cluster = av_realloc_array(trk->cluster, new_capacity, sizeof(*trk->cluster)); + if (!cluster) { ret = AVERROR(ENOMEM); goto err; } + trk->cluster = cluster; trk->cluster_capacity = new_capacity; } @@ -5511,6 +5843,8 @@ if (par->codec_id == AV_CODEC_ID_VC1) { mov_parse_vc1_frame(pkt, trk); + } else if (par->codec_id == AV_CODEC_ID_TRUEHD) { + mov_parse_truehd_frame(pkt, trk); } else if (pkt->flags & AV_PKT_FLAG_KEY) { if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO && trk->entry > 0) { // force sync sample for the first key frame @@ -5527,123 +5861,132 @@ trk->cluster[trk->entry].flags |= MOV_DISPOSABLE_SAMPLE; trk->has_disposable++; } + + prft = (AVProducerReferenceTime *)av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &prft_size); + if (prft && prft_size == sizeof(AVProducerReferenceTime)) + memcpy(&trk->cluster[trk->entry].prft, prft, prft_size); + else + memset(&trk->cluster[trk->entry].prft, 0, sizeof(AVProducerReferenceTime)); + trk->entry++; trk->sample_count += samples_in_chunk; mov->mdat_size += size; if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry, - reformatted_data, size); + reformatted_data ? reformatted_data + offset + : NULL, size); end: err: - av_free(reformatted_data); + if (pkt->data != reformatted_data) + av_free(reformatted_data); return ret; } static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) { - MOVMuxContext *mov = s->priv_data; - MOVTrack *trk = &mov->tracks[pkt->stream_index]; - AVCodecParameters *par = trk->par; - int64_t frag_duration = 0; - int size = pkt->size; + MOVMuxContext *mov = s->priv_data; + MOVTrack *trk = &mov->tracks[pkt->stream_index]; + AVCodecParameters *par = trk->par; + int64_t frag_duration = 0; + int size = pkt->size; - int ret = check_pkt(s, pkt); - if (ret < 0) - return ret; + int ret = check_pkt(s, pkt); + if (ret < 0) + return ret; - if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) { - int i; - for (i = 0; i < s->nb_streams; i++) - mov->tracks[i].frag_discont = 1; - mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT; - } + if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) { + int i; + for (i = 0; i < s->nb_streams; i++) + mov->tracks[i].frag_discont = 1; + mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT; + } - if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) { - if (trk->dts_shift == AV_NOPTS_VALUE) - trk->dts_shift = pkt->pts - pkt->dts; - pkt->dts += trk->dts_shift; - } + if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) { + if (trk->dts_shift == AV_NOPTS_VALUE) + trk->dts_shift = pkt->pts - pkt->dts; + pkt->dts += trk->dts_shift; + } - if (trk->par->codec_id == AV_CODEC_ID_MP4ALS || + if (trk->par->codec_id == AV_CODEC_ID_MP4ALS || trk->par->codec_id == AV_CODEC_ID_AAC || trk->par->codec_id == AV_CODEC_ID_AV1 || trk->par->codec_id == AV_CODEC_ID_FLAC) { - int side_size = 0; - uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); - if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { - void *newextra = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!newextra) - return AVERROR(ENOMEM); - av_free(par->extradata); - par->extradata = newextra; - memcpy(par->extradata, side, side_size); - par->extradata_size = side_size; - if (!pkt->size) // Flush packet - mov->need_rewrite_extradata = 1; - } + buffer_size_t side_size; + uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size); + if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) { + void *newextra = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!newextra) + return AVERROR(ENOMEM); + av_free(par->extradata); + par->extradata = newextra; + memcpy(par->extradata, side, side_size); + par->extradata_size = side_size; + if (!pkt->size) // Flush packet + mov->need_rewrite_extradata = 1; } + } - if (!pkt->size) { - if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) { - trk->start_dts = pkt->dts; - if (pkt->pts != AV_NOPTS_VALUE) - trk->start_cts = pkt->pts - pkt->dts; - else - trk->start_cts = 0; - } - - return 0; /* Discard 0 sized packets */ + if (!pkt->size) { + if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) { + trk->start_dts = pkt->dts; + if (pkt->pts != AV_NOPTS_VALUE) + trk->start_cts = pkt->pts - pkt->dts; + else + trk->start_cts = 0; } - if (trk->entry && pkt->stream_index < s->nb_streams) - frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts, - s->streams[pkt->stream_index]->time_base, - AV_TIME_BASE_Q); - if ((mov->max_fragment_duration && - frag_duration >= mov->max_fragment_duration) || - (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) || - (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME && - par->codec_type == AVMEDIA_TYPE_VIDEO && - trk->entry && pkt->flags & AV_PKT_FLAG_KEY) || - (mov->flags & FF_MOV_FLAG_FRAG_EVERY_FRAME)) { - if (frag_duration >= mov->min_fragment_duration) { - // Set the duration of this track to line up with the next - // sample in this track. This avoids relying on AVPacket - // duration, but only helps for this particular track, not - // for the other ones that are flushed at the same time. - trk->track_duration = pkt->dts - trk->start_dts; - if (pkt->pts != AV_NOPTS_VALUE) - trk->end_pts = pkt->pts; - else - trk->end_pts = pkt->dts; - trk->end_reliable = 1; - mov_auto_flush_fragment(s, 0); - } + return 0; /* Discard 0 sized packets */ + } + + if (trk->entry && pkt->stream_index < s->nb_streams) + frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts, + s->streams[pkt->stream_index]->time_base, + AV_TIME_BASE_Q); + if ((mov->max_fragment_duration && + frag_duration >= mov->max_fragment_duration) || + (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) || + (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME && + par->codec_type == AVMEDIA_TYPE_VIDEO && + trk->entry && pkt->flags & AV_PKT_FLAG_KEY) || + (mov->flags & FF_MOV_FLAG_FRAG_EVERY_FRAME)) { + if (frag_duration >= mov->min_fragment_duration) { + // Set the duration of this track to line up with the next + // sample in this track. This avoids relying on AVPacket + // duration, but only helps for this particular track, not + // for the other ones that are flushed at the same time. + trk->track_duration = pkt->dts - trk->start_dts; + if (pkt->pts != AV_NOPTS_VALUE) + trk->end_pts = pkt->pts; + else + trk->end_pts = pkt->dts; + trk->end_reliable = 1; + mov_auto_flush_fragment(s, 0); } + } - return ff_mov_write_packet(s, pkt); + return ff_mov_write_packet(s, pkt); } static int mov_write_subtitle_end_packet(AVFormatContext *s, int stream_index, int64_t dts) { - AVPacket end; + MOVMuxContext *mov = s->priv_data; + AVPacket *end = mov->pkt; uint8_t data[2] = {0}; int ret; - av_init_packet(&end); - end.size = sizeof(data); - end.data = data; - end.pts = dts; - end.dts = dts; - end.duration = 0; - end.stream_index = stream_index; + end->size = sizeof(data); + end->data = data; + end->pts = dts; + end->dts = dts; + end->duration = 0; + end->stream_index = stream_index; - ret = mov_write_single_packet(s, &end); - av_packet_unref(&end); + ret = mov_write_single_packet(s, end); + av_packet_unref(end); return ret; } @@ -5670,7 +6013,7 @@ return 0; } - if ((ret = av_packet_ref(&trk->cover_image, pkt)) < 0) + if ((ret = av_packet_ref(trk->cover_image, pkt)) < 0) return ret; return 0; @@ -5756,7 +6099,7 @@ MOVMuxContext *mov = s->priv_data; MOVTrack *track = &mov->tracks[tracknum]; - AVPacket pkt = { .stream_index = tracknum, .flags = AV_PKT_FLAG_KEY }; + AVPacket *pkt = mov->pkt; int i, len; track->mode = mov->mode; @@ -5818,13 +6161,16 @@ } #endif + pkt->stream_index = tracknum; + pkt->flags = AV_PKT_FLAG_KEY; + for (i = 0; i < s->nb_chapters; i++) { AVChapter *c = s->chapters[i]; AVDictionaryEntry *t; int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,MOV_TIMESCALE}); - pkt.pts = pkt.dts = av_rescale_q(c->start, c->time_base, (AVRational){1,MOV_TIMESCALE}); - pkt.duration = end - pkt.dts; + pkt->pts = pkt->dts = av_rescale_q(c->start, c->time_base, (AVRational){1,MOV_TIMESCALE}); + pkt->duration = end - pkt->dts; if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { static const char encd[12] = { @@ -5832,18 +6178,22 @@ 'e', 'n', 'c', 'd', 0x00, 0x00, 0x01, 0x00 }; len = strlen(t->value); - pkt.size = len + 2 + 12; - pkt.data = av_malloc(pkt.size); - if (!pkt.data) + pkt->size = len + 2 + 12; + pkt->data = av_malloc(pkt->size); + if (!pkt->data) { + av_packet_unref(pkt); return AVERROR(ENOMEM); - AV_WB16(pkt.data, len); - memcpy(pkt.data + 2, t->value, len); - memcpy(pkt.data + len + 2, encd, sizeof(encd)); - ff_mov_write_packet(s, &pkt); - av_freep(&pkt.data); + } + AV_WB16(pkt->data, len); + memcpy(pkt->data + 2, t->value, len); + memcpy(pkt->data + len + 2, encd, sizeof(encd)); + ff_mov_write_packet(s, pkt); + av_freep(&pkt->data); } } + av_packet_unref(mov->pkt); + return 0; } @@ -5859,12 +6209,13 @@ static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, AVTimecode tc) { - int ret; MOVMuxContext *mov = s->priv_data; MOVTrack *track = &mov->tracks[index]; AVStream *src_st = s->streams[src_index]; - AVPacket pkt = {.stream_index = index, .flags = AV_PKT_FLAG_KEY, .size = 4}; + uint8_t data[4]; + AVPacket *pkt = mov->pkt; AVRational rate = find_fps(s, src_st); + int ret; /* tmcd track based on video stream */ track->mode = mov->mode; @@ -5886,12 +6237,13 @@ track->st->avg_frame_rate = av_inv_q(rate); /* the tmcd track just contains one packet with the frame number */ - pkt.data = av_malloc(pkt.size); - if (!pkt.data) - return AVERROR(ENOMEM); - AV_WB32(pkt.data, tc.start); - ret = ff_mov_write_packet(s, &pkt); - av_free(pkt.data); + pkt->data = data; + pkt->stream_index = index; + pkt->flags = AV_PKT_FLAG_KEY; + pkt->size = 4; + AV_WB32(pkt->data, tc.start); + ret = ff_mov_write_packet(s, pkt); + av_packet_unref(pkt); return ret; } @@ -5953,10 +6305,13 @@ MOVMuxContext *mov = s->priv_data; int i; + av_packet_free(&mov->pkt); + + if (!mov->tracks) + return; + if (mov->chapter_track) { - if (mov->tracks[mov->chapter_track].par) - av_freep(&mov->tracks[mov->chapter_track].par->extradata); - av_freep(&mov->tracks[mov->chapter_track].par); + avcodec_parameters_free(&mov->tracks[mov->chapter_track].par); } for (i = 0; i < mov->nb_streams; i++) { @@ -5966,20 +6321,22 @@ av_freep(&mov->tracks[i].par); av_freep(&mov->tracks[i].cluster); av_freep(&mov->tracks[i].frag_info); - av_packet_unref(&mov->tracks[i].cover_image); + av_packet_free(&mov->tracks[i].cover_image); if (mov->tracks[i].eac3_priv) { struct eac3_info *info = mov->tracks[i].eac3_priv; - av_packet_unref(&info->pkt); + av_packet_free(&info->pkt); av_freep(&mov->tracks[i].eac3_priv); } if (mov->tracks[i].vos_len) av_freep(&mov->tracks[i].vos_data); ff_mov_cenc_free(&mov->tracks[i].cenc); + ffio_free_dyn_buf(&mov->tracks[i].mdat_buf); } av_freep(&mov->tracks); + ffio_free_dyn_buf(&mov->mdat_buf); } static uint32_t rgb_to_yuv(uint32_t rgb) @@ -6051,7 +6408,6 @@ static int mov_init(AVFormatContext *s) { MOVMuxContext *mov = s->priv_data; - AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode", NULL, 0); int i, ret; mov->fc = s; @@ -6059,15 +6415,15 @@ /* Default mode == MP4 */ mov->mode = MODE_MP4; - if (s->oformat) { - if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP; - else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3GP|MODE_3G2; - else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV; - else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP; - else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD; - else if (!strcmp("ismv",s->oformat->name)) mov->mode = MODE_ISM; - else if (!strcmp("f4v", s->oformat->name)) mov->mode = MODE_F4V; - } +#define IS_MODE(muxer, config) (CONFIG_ ## config ## _MUXER && !strcmp(#muxer, s->oformat->name)) + if (IS_MODE(3gp, TGP)) mov->mode = MODE_3GP; + else if (IS_MODE(3g2, TG2)) mov->mode = MODE_3GP|MODE_3G2; + else if (IS_MODE(mov, MOV)) mov->mode = MODE_MOV; + else if (IS_MODE(psp, PSP)) mov->mode = MODE_PSP; + else if (IS_MODE(ipod, IPOD)) mov->mode = MODE_IPOD; + else if (IS_MODE(ismv, ISMV)) mov->mode = MODE_ISM; + else if (IS_MODE(f4v, F4V)) mov->mode = MODE_F4V; +#undef IS_MODE if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) mov->flags |= FF_MOV_FLAG_EMPTY_MOOV; @@ -6088,6 +6444,9 @@ if (mov->flags & FF_MOV_FLAG_DASH) mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_DEFAULT_BASE_MOOF; + if (mov->flags & FF_MOV_FLAG_CMAF) + mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV | + FF_MOV_FLAG_DEFAULT_BASE_MOOF | FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS; if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && s->flags & AVFMT_FLAG_AUTO_BSF) { av_log(s, AV_LOG_VERBOSE, "Empty MOOV enabled; disabling automatic bitstream filtering\n"); @@ -6114,12 +6473,21 @@ s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) mov->use_editlist = 0; } + if (mov->flags & FF_MOV_FLAG_CMAF) { + // CMAF Track requires negative cts offsets without edit lists + mov->use_editlist = 0; + } } if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && !(mov->flags & FF_MOV_FLAG_DELAY_MOOV) && mov->use_editlist) av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov without delay_moov\n"); - if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO) + if (mov->flags & FF_MOV_FLAG_CMAF && mov->use_editlist) { + av_log(s, AV_LOG_WARNING, "Edit list enabled; Assuming writing CMAF Track File\n"); + mov->flags &= ~FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS; + } + if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO && + !(mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS)) s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO; /* Clear the omit_tfhd_offset flag if default_base_moof is set; @@ -6157,6 +6525,9 @@ if ( mov->write_tmcd == -1 && (mov->mode == MODE_MOV || mov->mode == MODE_MP4) || mov->write_tmcd == 1) { + AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode", + NULL, 0); + /* +1 tmcd track for each video stream with a timecode */ for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; @@ -6185,6 +6556,10 @@ 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_mallocz_array((mov->nb_streams + 1), sizeof(*mov->tracks)); @@ -6250,6 +6625,8 @@ } if (mov->video_track_timescale) { track->timescale = mov->video_track_timescale; + if (mov->mode == MODE_ISM && mov->video_track_timescale != 10000000) + av_log(s, AV_LOG_WARNING, "Warning: some tools, like mp4split, assume a timescale of 10000000 for ISMV.\n"); } else { track->timescale = st->time_base.den; while(track->timescale < 10000) @@ -6290,6 +6667,11 @@ av_log(s, AV_LOG_ERROR, "VP8 muxing is currently not supported.\n"); return AVERROR_PATCHWELCOME; } + if (is_cover_image(st)) { + track->cover_image = av_packet_alloc(); + if (!track->cover_image) + return AVERROR(ENOMEM); + } } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { track->timescale = st->codecpar->sample_rate; if (!st->codecpar->frame_size && !av_get_bits_per_sample(st->codecpar->codec_id)) { @@ -6324,12 +6706,14 @@ } } if (track->par->codec_id == AV_CODEC_ID_FLAC || + track->par->codec_id == AV_CODEC_ID_TRUEHD || track->par->codec_id == AV_CODEC_ID_OPUS) { if (track->mode != MODE_MP4) { av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id)); return AVERROR(EINVAL); } - if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + if (track->par->codec_id != AV_CODEC_ID_OPUS && + s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { av_log(s, AV_LOG_ERROR, "%s in MP4 support is experimental, add " "'-strict %d' if you want to use it.\n", @@ -6346,10 +6730,14 @@ } if (!track->height) track->height = st->codecpar->height; - /* The ism specific timescale isn't mandatory, but is assumed by - * some tools, such as mp4split. */ - if (mov->mode == MODE_ISM) - track->timescale = 10000000; + /* The Protected Interoperable File Format (PIFF) standard, used by ISMV recommends but + doesn't mandate a track timescale of 10,000,000. The muxer allows a custom timescale + for video tracks, so if user-set, it isn't overwritten */ + if (mov->mode == MODE_ISM && + (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO || + (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !mov->video_track_timescale))) { + track->timescale = 10000000; + } avpriv_set_pts_info(st, 64, 1, track->timescale); @@ -6369,7 +6757,6 @@ { AVIOContext *pb = s->pb; MOVMuxContext *mov = s->priv_data; - AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata, "timecode", NULL, 0); int i, ret, hint_track = 0, tmcd_track = 0, nb_tracks = s->nb_streams; if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) @@ -6468,6 +6855,8 @@ } if (mov->nb_meta_tmcd) { + const AVDictionaryEntry *t, *global_tcr = av_dict_get(s->metadata, + "timecode", NULL, 0); /* Initialize the tmcd tracks */ for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; @@ -6497,7 +6886,6 @@ !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) { if ((ret = mov_write_moov_tag(pb, mov, s)) < 0) return ret; - avio_flush(pb); mov->moov_written = 1; if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) mov->reserved_header_pos = avio_tell(pb); @@ -6581,7 +6969,7 @@ { int ret = 0, moov_size; MOVMuxContext *mov = s->priv_data; - int64_t pos, pos_end = avio_tell(s->pb); + int64_t pos, pos_end; uint8_t *buf, *read_buf[2]; int read_buf_id = 0; int read_size[2]; @@ -6657,6 +7045,7 @@ AVCodecParameters *par = track->par; track->vos_len = par->extradata_size; + av_freep(&track->vos_data); track->vos_data = av_malloc(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE); if (!track->vos_data) return AVERROR(ENOMEM); @@ -6751,7 +7140,9 @@ } if (!(mov->flags & FF_MOV_FLAG_SKIP_TRAILER)) { avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER); - mov_write_mfra_tag(pb, mov); + res = mov_write_mfra_tag(pb, mov); + if (res < 0) + return res; } } @@ -6773,6 +7164,7 @@ return ret; } +#if CONFIG_TGP_MUXER || CONFIG_TG2_MUXER static const AVCodecTag codec_3gp_tags[] = { { AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, @@ -6783,42 +7175,50 @@ { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, { AV_CODEC_ID_NONE, 0 }, }; +static const AVCodecTag *const codec_3gp_tags_list[] = { codec_3gp_tags, NULL }; +#endif -const AVCodecTag codec_mp4_tags[] = { - { AV_CODEC_ID_MPEG4 , MKTAG('m', 'p', '4', 'v') }, - { AV_CODEC_ID_H264 , MKTAG('a', 'v', 'c', '1') }, - { AV_CODEC_ID_H264 , MKTAG('a', 'v', 'c', '3') }, - { AV_CODEC_ID_HEVC , MKTAG('h', 'e', 'v', '1') }, - { AV_CODEC_ID_HEVC , MKTAG('h', 'v', 'c', '1') }, - { AV_CODEC_ID_MPEG2VIDEO , MKTAG('m', 'p', '4', 'v') }, - { AV_CODEC_ID_MPEG1VIDEO , MKTAG('m', 'p', '4', 'v') }, - { AV_CODEC_ID_MJPEG , MKTAG('m', 'p', '4', 'v') }, - { AV_CODEC_ID_PNG , MKTAG('m', 'p', '4', 'v') }, - { AV_CODEC_ID_JPEG2000 , MKTAG('m', 'p', '4', 'v') }, - { AV_CODEC_ID_VC1 , MKTAG('v', 'c', '-', '1') }, - { AV_CODEC_ID_DIRAC , MKTAG('d', 'r', 'a', 'c') }, - { AV_CODEC_ID_TSCC2 , MKTAG('m', 'p', '4', 'v') }, - { AV_CODEC_ID_VP9 , MKTAG('v', 'p', '0', '9') }, - { AV_CODEC_ID_AV1 , MKTAG('a', 'v', '0', '1') }, - { AV_CODEC_ID_AAC , MKTAG('m', 'p', '4', 'a') }, - { AV_CODEC_ID_MP4ALS , MKTAG('m', 'p', '4', 'a') }, - { AV_CODEC_ID_MP3 , MKTAG('m', 'p', '4', 'a') }, - { AV_CODEC_ID_MP2 , MKTAG('m', 'p', '4', 'a') }, - { AV_CODEC_ID_AC3 , MKTAG('a', 'c', '-', '3') }, - { AV_CODEC_ID_EAC3 , MKTAG('e', 'c', '-', '3') }, - { AV_CODEC_ID_DTS , MKTAG('m', 'p', '4', 'a') }, - { AV_CODEC_ID_FLAC , MKTAG('f', 'L', 'a', 'C') }, - { AV_CODEC_ID_OPUS , MKTAG('O', 'p', 'u', 's') }, - { AV_CODEC_ID_VORBIS , MKTAG('m', 'p', '4', 'a') }, - { AV_CODEC_ID_QCELP , MKTAG('m', 'p', '4', 'a') }, - { AV_CODEC_ID_EVRC , MKTAG('m', 'p', '4', 'a') }, - { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') }, - { AV_CODEC_ID_MOV_TEXT , MKTAG('t', 'x', '3', 'g') }, - { AV_CODEC_ID_BIN_DATA , MKTAG('g', 'p', 'm', 'd') }, - { AV_CODEC_ID_NONE , 0 }, +static const AVCodecTag codec_mp4_tags[] = { + { AV_CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, + { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') }, + { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') }, + { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') }, + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_MJPEG, MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_PNG, MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_JPEG2000, MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_VC1, MKTAG('v', 'c', '-', '1') }, + { AV_CODEC_ID_DIRAC, MKTAG('d', 'r', 'a', 'c') }, + { AV_CODEC_ID_TSCC2, MKTAG('m', 'p', '4', 'v') }, + { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') }, + { AV_CODEC_ID_AV1, MKTAG('a', 'v', '0', '1') }, + { AV_CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_ALAC, MKTAG('a', 'l', 'a', 'c') }, + { AV_CODEC_ID_MP4ALS, MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_MP3, MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_MP2, MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_AC3, MKTAG('a', 'c', '-', '3') }, + { AV_CODEC_ID_EAC3, MKTAG('e', 'c', '-', '3') }, + { AV_CODEC_ID_DTS, MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_TRUEHD, MKTAG('m', 'l', 'p', 'a') }, + { AV_CODEC_ID_FLAC, MKTAG('f', 'L', 'a', 'C') }, + { AV_CODEC_ID_OPUS, MKTAG('O', 'p', 'u', 's') }, + { AV_CODEC_ID_VORBIS, MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_QCELP, MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_EVRC, MKTAG('m', 'p', '4', 'a') }, + { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') }, + { AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') }, + { AV_CODEC_ID_BIN_DATA, MKTAG('g', 'p', 'm', 'd') }, + { AV_CODEC_ID_MPEGH_3D_AUDIO, MKTAG('m', 'h', 'm', '1') }, + { AV_CODEC_ID_NONE, 0 }, }; +#if CONFIG_MP4_MUXER || CONFIG_PSP_MUXER +static const AVCodecTag *const mp4_codec_tags_list[] = { codec_mp4_tags, NULL }; +#endif -const AVCodecTag codec_ism_tags[] = { +static const AVCodecTag codec_ism_tags[] = { { AV_CODEC_ID_WMAPRO , MKTAG('w', 'm', 'a', ' ') }, { AV_CODEC_ID_NONE , 0 }, }; @@ -6881,7 +7281,7 @@ .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ codec_3gp_tags, 0 }, + .codec_tag = codec_3gp_tags_list, .check_bitstream = mov_check_bitstream, .priv_class = &tgp_muxer_class, }; @@ -6903,7 +7303,7 @@ .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ codec_mp4_tags, 0 }, + .codec_tag = mp4_codec_tags_list, .check_bitstream = mov_check_bitstream, .priv_class = &mp4_muxer_class, }; @@ -6924,7 +7324,7 @@ .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ codec_mp4_tags, 0 }, + .codec_tag = mp4_codec_tags_list, .check_bitstream = mov_check_bitstream, .priv_class = &psp_muxer_class, }; @@ -6944,7 +7344,7 @@ .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, - .codec_tag = (const AVCodecTag* const []){ codec_3gp_tags, 0 }, + .codec_tag = codec_3gp_tags_list, .check_bitstream = mov_check_bitstream, .priv_class = &tg2_muxer_class, }; diff -Nru ffmpeg-4.2.2/libavformat/movenccenc.c ffmpeg-4.4/libavformat/movenccenc.c --- ffmpeg-4.2.2/libavformat/movenccenc.c 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavformat/movenccenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -412,4 +412,6 @@ void ff_mov_cenc_free(MOVMuxCencContext* ctx) { av_aes_ctr_free(ctx->aes_ctr); + av_freep(&ctx->auxiliary_info); + av_freep(&ctx->auxiliary_info_sizes); } diff -Nru ffmpeg-4.2.2/libavformat/movenc.h ffmpeg-4.4/libavformat/movenc.h --- ffmpeg-4.2.2/libavformat/movenc.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/movenc.h 2021-04-08 21:28:40.000000000 +0000 @@ -56,6 +56,7 @@ #define MOV_PARTIAL_SYNC_SAMPLE 0x0002 #define MOV_DISPOSABLE_SAMPLE 0x0004 uint32_t flags; + AVProducerReferenceTime prft; } MOVIentry; typedef struct HintSample { @@ -133,7 +134,7 @@ uint32_t default_size; HintSampleQueue sample_queue; - AVPacket cover_image; + AVPacket *cover_image; AVIOContext *mdat_buf; int64_t data_offset; @@ -214,6 +215,8 @@ int per_stream_grouping; AVFormatContext *fc; + AVPacket *pkt; + int use_editlist; float gamma; @@ -258,6 +261,8 @@ #define FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS (1 << 19) #define FF_MOV_FLAG_FRAG_EVERY_FRAME (1 << 20) #define FF_MOV_FLAG_SKIP_SIDX (1 << 21) +#define FF_MOV_FLAG_CMAF (1 << 22) +#define FF_MOV_FLAG_PREFER_ICC (1 << 23) int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt); diff -Nru ffmpeg-4.2.2/libavformat/movenchint.c ffmpeg-4.4/libavformat/movenchint.c --- ffmpeg-4.2.2/libavformat/movenchint.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/movenchint.c 2021-04-08 21:28:40.000000000 +0000 @@ -408,7 +408,7 @@ uint8_t *buf = NULL; int size; AVIOContext *hintbuf = NULL; - AVPacket hint_pkt; + AVPacket *hint_pkt = mov->pkt; int ret = 0, count; if (!rtp_ctx) @@ -437,21 +437,22 @@ /* Open a buffer for writing the hint */ if ((ret = avio_open_dyn_buf(&hintbuf)) < 0) goto done; - av_init_packet(&hint_pkt); - count = write_hint_packets(hintbuf, buf, size, trk, &hint_pkt.dts); + av_packet_unref(hint_pkt); + count = write_hint_packets(hintbuf, buf, size, trk, &hint_pkt->dts); av_freep(&buf); /* Write the hint data into the hint track */ - hint_pkt.size = size = avio_close_dyn_buf(hintbuf, &buf); - hint_pkt.data = buf; - hint_pkt.pts = hint_pkt.dts; - hint_pkt.stream_index = track_index; + hint_pkt->size = size = avio_close_dyn_buf(hintbuf, &buf); + hint_pkt->data = buf; + hint_pkt->pts = hint_pkt->dts; + hint_pkt->stream_index = track_index; if (pkt->flags & AV_PKT_FLAG_KEY) - hint_pkt.flags |= AV_PKT_FLAG_KEY; + hint_pkt->flags |= AV_PKT_FLAG_KEY; if (count > 0) - ff_mov_write_packet(s, &hint_pkt); + ff_mov_write_packet(s, hint_pkt); done: av_free(buf); + av_packet_unref(hint_pkt); sample_queue_retain(&trk->sample_queue); return ret; } diff -Nru ffmpeg-4.2.2/libavformat/mp3dec.c ffmpeg-4.4/libavformat/mp3dec.c --- ffmpeg-4.2.2/libavformat/mp3dec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/mp3dec.c 2021-04-08 21:28:40.000000000 +0000 @@ -42,8 +42,6 @@ #define XING_TOC_COUNT 100 -#define SAME_HEADER_MASK \ - (0xffe00000 | (3 << 17) | (3 << 10) | (3 << 19)) typedef struct { AVClass *class; @@ -73,32 +71,46 @@ int frames, ret; int framesizes, max_framesizes; uint32_t header; - const uint8_t *buf, *buf0, *buf2, *end; + const uint8_t *buf, *buf0, *buf2, *buf3, *end; buf0 = p->buf; end = p->buf + p->buf_size - sizeof(uint32_t); - while(buf0 < end && !*buf0) + while (buf0 < end && !*buf0) buf0++; max_frames = 0; max_framesizes = 0; buf = buf0; - for(; buf < end; buf= buf2+1) { + for (; buf < end; buf = buf2+1) { buf2 = buf; - for(framesizes = frames = 0; buf2 < end; frames++) { + for (framesizes = frames = 0; buf2 < end; frames++) { MPADecodeHeader h; + int header_emu = 0; + int available; header = AV_RB32(buf2); ret = avpriv_mpegaudio_decode_header(&h, header); - if (ret != 0 || end - buf2 < h.frame_size) + if (ret != 0) + break; + + available = FFMIN(h.frame_size, end - buf2); + for (buf3 = buf2 + 4; buf3 < buf2 + available; buf3++) { + uint32_t next_sync = AV_RB32(buf3); + header_emu += (next_sync & MP3_MASK) == (header & MP3_MASK); + } + if (header_emu > 2) break; - buf2 += h.frame_size; framesizes += h.frame_size; + if (available < h.frame_size) { + frames++; + break; + } + buf2 += h.frame_size; } max_frames = FFMAX(max_frames, frames); max_framesizes = FFMAX(max_framesizes, framesizes); - if(buf == buf0) { + if (buf == buf0) { first_frames= frames; if (buf2 == end + sizeof(uint32_t)) whole_used = 1; @@ -107,14 +119,14 @@ // keep this in sync with ac3 probe, both need to avoid // issues with MPEG-files! if (first_frames>=7) return AVPROBE_SCORE_EXTENSION + 1; - else if(max_frames>200 && p->buf_size < 2*max_framesizes)return AVPROBE_SCORE_EXTENSION; - else if(max_frames>=4 && p->buf_size < 2*max_framesizes) return AVPROBE_SCORE_EXTENSION / 2; - else if(ff_id3v2_match(buf0, ID3v2_DEFAULT_MAGIC) && 2*ff_id3v2_tag_len(buf0) >= p->buf_size) + else if (max_frames>200 && p->buf_size < 2*max_framesizes)return AVPROBE_SCORE_EXTENSION; + else if (max_frames>=4 && p->buf_size < 2*max_framesizes) return AVPROBE_SCORE_EXTENSION / 2; + else if (ff_id3v2_match(buf0, ID3v2_DEFAULT_MAGIC) && 2*ff_id3v2_tag_len(buf0) >= p->buf_size) return p->buf_size < PROBE_BUF_MAX ? AVPROBE_SCORE_EXTENSION / 4 : AVPROBE_SCORE_EXTENSION - 2; - else if(first_frames > 1 && whole_used) return 5; - else if(max_frames>=1 && p->buf_size < 10*max_framesizes) return 1; + else if (first_frames > 1 && whole_used) return 5; + else if (max_frames>=1 && p->buf_size < 10*max_framesizes) return 1; else return 0; -//mpegps_mp3_unrecognized_format.mpg has max_frames=3 + //mpegps_mp3_unrecognized_format.mpg has max_frames=3 } static void read_xing_toc(AVFormatContext *s, int64_t filesize, int64_t duration) @@ -235,21 +247,21 @@ avio_r8(s->pb); /* Encoder delays */ - v= avio_rb24(s->pb); - if(AV_RB32(version) == MKBETAG('L', 'A', 'M', 'E') + v = avio_rb24(s->pb); + if (AV_RB32(version) == MKBETAG('L', 'A', 'M', 'E') || AV_RB32(version) == MKBETAG('L', 'a', 'v', 'f') || AV_RB32(version) == MKBETAG('L', 'a', 'v', 'c') ) { mp3->start_pad = v>>12; mp3-> end_pad = v&4095; - st->start_skip_samples = mp3->start_pad + 528 + 1; + st->internal->start_skip_samples = mp3->start_pad + 528 + 1; if (mp3->frames) { - st->first_discard_sample = -mp3->end_pad + 528 + 1 + mp3->frames * (int64_t)spf; - st->last_discard_sample = mp3->frames * (int64_t)spf; + st->internal->first_discard_sample = -mp3->end_pad + 528 + 1 + mp3->frames * (int64_t)spf; + st->internal->last_discard_sample = mp3->frames * (int64_t)spf; } if (!st->start_time) - st->start_time = av_rescale_q(st->start_skip_samples, + st->start_time = av_rescale_q(st->internal->start_skip_samples, (AVRational){1, c->sample_rate}, st->time_base); av_log(s, AV_LOG_DEBUG, "pad %d %d\n", mp3->start_pad, mp3-> end_pad); @@ -319,7 +331,7 @@ return ret; else if (ret == 0) vbrtag_size = c.frame_size; - if(c.layer != 3) + if (c.layer != 3) return -1; spf = c.lsf ? 576 : 1152; /* Samples per frame, layer 3 */ @@ -374,7 +386,7 @@ if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) ff_id3v1_read(s); - if(s->pb->seekable & AVIO_SEEKABLE_NORMAL) + if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) mp3->filesize = avio_size(s->pb); if (mp3_parse_vbr_tags(s, st, off) < 0) @@ -398,7 +410,7 @@ ffio_ensure_seekback(s->pb, i + 1024 + frame_size + 4); ret = check(s->pb, off + i + frame_size, &header2); if (ret >= 0 && - (header & SAME_HEADER_MASK) == (header2 & SAME_HEADER_MASK)) + (header & MP3_MASK) == (header2 & MP3_MASK)) { av_log(s, i > 0 ? AV_LOG_INFO : AV_LOG_VERBOSE, "Skipping %d bytes of junk at %"PRId64".\n", i, off); ret = avio_seek(s->pb, off + i, SEEK_SET); @@ -434,12 +446,12 @@ int ret, size; int64_t pos; - size= MP3_PACKET_SIZE; + size = MP3_PACKET_SIZE; pos = avio_tell(s->pb); - if(mp3->filesize > ID3v1_TAG_SIZE && pos < mp3->filesize) + if (mp3->filesize > ID3v1_TAG_SIZE && pos < mp3->filesize) size= FFMIN(size, mp3->filesize - pos); - ret= av_get_packet(s->pb, pkt, size); + ret = av_get_packet(s->pb, pkt, size); if (ret <= 0) { if(ret<0) return ret; @@ -494,7 +506,7 @@ #define MIN_VALID 3 best_pos = target_pos; best_score = 999; - for(i=0; i 0 ? i - SEEK_WINDOW/4 : -i); int64_t candidate = -1; int score = 999; @@ -502,9 +514,9 @@ if (pos < 0) continue; - for(j=0; jpb, pos, NULL); - if(ret < 0) { + if (ret < 0) { if (ret == CHECK_WRONG_HEADER) { break; } else if (ret == CHECK_SEEK_FAILED) { diff -Nru ffmpeg-4.2.2/libavformat/mp3enc.c ffmpeg-4.4/libavformat/mp3enc.c --- ffmpeg-4.2.2/libavformat/mp3enc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mp3enc.c 2021-04-08 21:28:40.000000000 +0000 @@ -28,6 +28,7 @@ #include "libavcodec/mpegaudio.h" #include "libavcodec/mpegaudiodata.h" #include "libavcodec/mpegaudiodecheader.h" +#include "libavcodec/packet_internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "libavutil/dict.h" @@ -45,6 +46,7 @@ return !!tag; } +// refer to: http://id3.org/ID3v1 static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf) { AVDictionaryEntry *tag; @@ -58,7 +60,17 @@ count += id3v1_set_string(s, "TIT2", buf + 3, 30 + 1); //title count += id3v1_set_string(s, "TPE1", buf + 33, 30 + 1); //author|artist count += id3v1_set_string(s, "TALB", buf + 63, 30 + 1); //album - count += id3v1_set_string(s, "TDRC", buf + 93, 4 + 1); //date + if ((tag = av_dict_get(s->metadata, "TYER", NULL, 0))) { //year + av_strlcpy(buf + 93, tag->value, 4 + 1); + count++; + } else if ((tag = av_dict_get(s->metadata, "TDRC", NULL, 0))) { + av_strlcpy(buf + 93, tag->value, 4 + 1); + count++; + } else if ((tag = av_dict_get(s->metadata, "TDAT", NULL, 0))) { + av_strlcpy(buf + 93, tag->value, 4 + 1); + count++; + } + count += id3v1_set_string(s, "comment", buf + 97, 30 + 1); if ((tag = av_dict_get(s->metadata, "TRCK", NULL, 0))) { //track buf[125] = 0; @@ -120,7 +132,7 @@ int pics_to_write; /* audio packets are queued here until we get all the attached pictures */ - AVPacketList *queue, *queue_end; + PacketList *queue, *queue_end; } MP3Context; static const uint8_t xing_offtbl[2][2] = {{32, 17}, {17, 9}}; @@ -343,7 +355,7 @@ if (mp3->xing_offset) { uint8_t *side_data = NULL; - int side_data_size = 0; + buffer_size_t side_data_size; mp3_xing_add_frame(mp3, pkt); mp3->audio_size += pkt->size; @@ -376,7 +388,7 @@ mp3_write_xing(s); while (mp3->queue) { - ff_packet_list_get(&mp3->queue, &mp3->queue_end, &pkt); + avpriv_packet_list_get(&mp3->queue, &mp3->queue_end, &pkt); if (write && (ret = mp3_write_audio_packet(s, &pkt)) < 0) write = 0; av_packet_unref(&pkt); @@ -390,7 +402,8 @@ AVReplayGain *rg; uint16_t tag_crc; uint8_t *toc; - int i, rg_size; + buffer_size_t rg_size; + int i; int64_t old_pos = avio_tell(s->pb); /* replace "Xing" identification string with "Info" for CBR files. */ @@ -473,8 +486,6 @@ if (mp3->xing_offset) mp3_update_xing(s); - av_freep(&mp3->xing_frame); - return 0; } @@ -513,7 +524,7 @@ if (pkt->stream_index == mp3->audio_stream_idx) { if (mp3->pics_to_write) { /* buffer audio packets until we get all the pictures */ - int ret = ff_packet_list_put(&mp3->queue, &mp3->queue_end, pkt, FF_PACKETLIST_FLAG_REF_PACKET); + int ret = avpriv_packet_list_put(&mp3->queue, &mp3->queue_end, pkt, av_packet_ref, 0); if (ret < 0) { av_log(s, AV_LOG_WARNING, "Not enough memory to buffer audio. Skipping picture streams\n"); @@ -551,10 +562,10 @@ * Write an ID3v2 header at beginning of stream */ -static int mp3_write_header(struct AVFormatContext *s) +static int mp3_init(struct AVFormatContext *s) { MP3Context *mp3 = s->priv_data; - int ret, i; + int i; if (mp3->id3v2_version && mp3->id3v2_version != 3 && @@ -593,6 +604,14 @@ return AVERROR(EINVAL); } + return 0; +} + +static int mp3_write_header(struct AVFormatContext *s) +{ + MP3Context *mp3 = s->priv_data; + int ret; + if (mp3->id3v2_version) { ff_id3v2_start(&mp3->id3, s->pb, mp3->id3v2_version, ID3v2_DEFAULT_MAGIC); ret = ff_id3v2_write_metadata(s, &mp3->id3); @@ -609,6 +628,14 @@ return 0; } +static void mp3_deinit(struct AVFormatContext *s) +{ + MP3Context *mp3 = s->priv_data; + + avpriv_packet_list_free(&mp3->queue, &mp3->queue_end); + av_freep(&mp3->xing_frame); +} + AVOutputFormat ff_mp3_muxer = { .name = "mp3", .long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), @@ -617,9 +644,11 @@ .priv_data_size = sizeof(MP3Context), .audio_codec = AV_CODEC_ID_MP3, .video_codec = AV_CODEC_ID_PNG, + .init = mp3_init, .write_header = mp3_write_header, .write_packet = mp3_write_packet, .write_trailer = mp3_write_trailer, + .deinit = mp3_deinit, .query_codec = query_codec, .flags = AVFMT_NOTIMESTAMPS, .priv_class = &mp3_muxer_class, diff -Nru ffmpeg-4.2.2/libavformat/mpc8.c ffmpeg-4.4/libavformat/mpc8.c --- ffmpeg-4.2.2/libavformat/mpc8.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mpc8.c 2021-04-08 21:28:40.000000000 +0000 @@ -127,7 +127,11 @@ pos = avio_tell(pb); *tag = avio_rl16(pb); *size = ffio_read_varlen(pb); - *size -= avio_tell(pb) - pos; + pos -= avio_tell(pb); + if (av_sat_add64(*size, pos) != (uint64_t)*size + pos) { + *size = -1; + } else + *size += pos; } static void mpc8_parse_seektable(AVFormatContext *s, int64_t off) @@ -168,6 +172,7 @@ size = gb_get_v(&gb); if(size > UINT_MAX/4 || size > c->samples/1152){ av_log(s, AV_LOG_ERROR, "Seek table is too big\n"); + av_free(buf); return; } seekd = get_bits(&gb, 4); @@ -177,12 +182,16 @@ av_add_index_entry(s->streams[0], pos, i, 0, 0, AVINDEX_KEYFRAME); } for(; i < size; i++){ + if (get_bits_left(&gb) < 13) { + av_free(buf); + return; + } t = get_unary(&gb, 1, 33) << 12; t += get_bits(&gb, 12); if(t & 1) t = -(t & ~1); - pos = (t >> 1) + ppos[0]*2 - ppos[1]; - av_add_index_entry(s->streams[0], pos, i << seekd, 0, 0, AVINDEX_KEYFRAME); + pos = (t >> 1) + (uint64_t)ppos[0]*2 - ppos[1]; + av_add_index_entry(s->streams[0], pos, (int64_t)i << seekd, 0, 0, AVINDEX_KEYFRAME); ppos[1] = ppos[0]; ppos[0] = pos; } @@ -211,7 +220,7 @@ MPCContext *c = s->priv_data; AVIOContext *pb = s->pb; AVStream *st; - int tag = 0; + int tag = 0, ret; int64_t size, pos; c->header_pos = avio_tell(pb); @@ -252,12 +261,12 @@ st->codecpar->codec_id = AV_CODEC_ID_MUSEPACK8; st->codecpar->bits_per_coded_sample = 16; - if (ff_get_extradata(s, st->codecpar, pb, 2) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_get_extradata(s, st->codecpar, pb, 2)) < 0) + return ret; st->codecpar->channels = (st->codecpar->extradata[1] >> 4) + 1; st->codecpar->sample_rate = mpc8_rate[st->codecpar->extradata[0] >> 5]; - avpriv_set_pts_info(st, 32, 1152 << (st->codecpar->extradata[1]&3)*2, st->codecpar->sample_rate); + avpriv_set_pts_info(st, 64, 1152 << (st->codecpar->extradata[1]&3)*2, st->codecpar->sample_rate); st->start_time = 0; st->duration = c->samples / (1152 << (st->codecpar->extradata[1]&3)*2); size -= avio_tell(pb) - pos; @@ -276,7 +285,7 @@ static int mpc8_read_packet(AVFormatContext *s, AVPacket *pkt) { MPCContext *c = s->priv_data; - int tag; + int tag, ret; int64_t pos, size; while(!avio_feof(s->pb)){ @@ -287,11 +296,11 @@ return AVERROR_EOF; mpc8_get_chunk_header(s->pb, &tag, &size); - if (size < 0) + if (size < 0 || size > INT_MAX) return -1; if(tag == TAG_AUDIOPACKET){ - if(av_get_packet(s->pb, pkt, size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_get_packet(s->pb, pkt, size)) < 0) + return ret; pkt->stream_index = 0; pkt->duration = 1; return 0; diff -Nru ffmpeg-4.2.2/libavformat/mpc.c ffmpeg-4.4/libavformat/mpc.c --- ffmpeg-4.2.2/libavformat/mpc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mpc.c 2020-07-11 10:39:30.000000000 +0000 @@ -57,6 +57,7 @@ { MPCContext *c = s->priv_data; AVStream *st; + int ret; if(avio_rl24(s->pb) != MKTAG('M', 'P', '+', 0)){ av_log(s, AV_LOG_ERROR, "Not a Musepack file\n"); @@ -72,15 +73,6 @@ av_log(s, AV_LOG_ERROR, "Too many frames, seeking is not possible\n"); return AVERROR_INVALIDDATA; } - if(c->fcount){ - c->frames = av_malloc(c->fcount * sizeof(MPCFrame)); - if(!c->frames){ - av_log(s, AV_LOG_ERROR, "Cannot allocate seektable\n"); - return AVERROR(ENOMEM); - } - }else{ - av_log(s, AV_LOG_WARNING, "Container reports no frames\n"); - } c->curframe = 0; c->lastframe = -1; c->curbits = 8; @@ -88,15 +80,27 @@ st = avformat_new_stream(s, NULL); if (!st) - goto mem_error; + return AVERROR(ENOMEM); + + if (c->fcount) { + c->frames = av_malloc(c->fcount * sizeof(MPCFrame)); + if (!c->frames) { + av_log(s, AV_LOG_ERROR, "Cannot allocate seektable\n"); + return AVERROR(ENOMEM); + } + st->priv_data = c->frames; + } else { + av_log(s, AV_LOG_WARNING, "Container reports no frames\n"); + } + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_MUSEPACK7; st->codecpar->channels = 2; st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; st->codecpar->bits_per_coded_sample = 16; - if (ff_get_extradata(s, st->codecpar, s->pb, 16) < 0) - goto mem_error; + if ((ret = ff_get_extradata(s, st->codecpar, s->pb, 16)) < 0) + return ret; st->codecpar->sample_rate = mpc_rate[st->codecpar->extradata[2] & 3]; avpriv_set_pts_info(st, 32, MPC_FRAMESIZE, st->codecpar->sample_rate); /* scan for seekpoints */ @@ -113,9 +117,6 @@ } return 0; -mem_error: - av_freep(&c->frames); - return AVERROR(ENOMEM); } static int mpc_read_packet(AVFormatContext *s, AVPacket *pkt) @@ -169,7 +170,6 @@ if(c->curbits) avio_seek(s->pb, -4, SEEK_CUR); if(ret < size){ - av_packet_unref(pkt); return ret < 0 ? ret : AVERROR(EIO); } pkt->size = ret + 4; @@ -177,14 +177,6 @@ return 0; } -static int mpc_read_close(AVFormatContext *s) -{ - MPCContext *c = s->priv_data; - - av_freep(&c->frames); - return 0; -} - /** * Seek to the given position * If position is unknown but is within the limits of file @@ -233,7 +225,6 @@ .read_probe = mpc_probe, .read_header = mpc_read_header, .read_packet = mpc_read_packet, - .read_close = mpc_read_close, .read_seek = mpc_read_seek, .extensions = "mpc", }; diff -Nru ffmpeg-4.2.2/libavformat/mpeg.c ffmpeg-4.4/libavformat/mpeg.c --- ffmpeg-4.2.2/libavformat/mpeg.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mpeg.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,14 +24,6 @@ #include "internal.h" #include "mpeg.h" -#if CONFIG_VOBSUB_DEMUXER -# include "subtitles.h" -# include "libavutil/bprint.h" -# include "libavutil/opt.h" -#endif - -#include "libavutil/avassert.h" - /*********************************************/ /* demux code */ @@ -107,7 +99,7 @@ if (sys > invalid && sys * 9 <= pspack * 10) return (audio > 12 || vid > 3 || pspack > 2) ? AVPROBE_SCORE_EXTENSION + 2 - : AVPROBE_SCORE_EXTENSION / 2 + 1; // 1 more than mp3 + : AVPROBE_SCORE_EXTENSION / 2 + (audio + vid + pspack > 1); // 1 more than mp3 if (pspack > invalid && (priv1 + vid + audio) * 10 >= pspack * 9) return pspack > 2 ? AVPROBE_SCORE_EXTENSION + 2 : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg @@ -123,18 +115,12 @@ } typedef struct MpegDemuxContext { - AVClass *class; int32_t header_state; unsigned char psm_es_type[256]; int sofdec; int dvd; int imkh_cctv; int raw_ac3; -#if CONFIG_VOBSUB_DEMUXER - AVFormatContext *sub_ctx; - FFDemuxSubtitlesQueue q[32]; - char *sub_name; -#endif } MpegDemuxContext; static int mpegps_read_header(AVFormatContext *s) @@ -161,9 +147,12 @@ static int64_t get_pts(AVIOContext *pb, int c) { uint8_t buf[5]; + int ret; buf[0] = c < 0 ? avio_r8(pb) : c; - avio_read(pb, buf + 1, 4); + ret = avio_read(pb, buf + 1, 4); + if (ret < 4) + return AV_NOPTS_VALUE; return ff_parse_pes_pts(buf); } @@ -489,7 +478,7 @@ MpegDemuxContext *m = s->priv_data; AVStream *st; int len, startcode, i, es_type, ret; - int lpcm_header_len = -1; //Init to suppress warning + int pcm_dvd = 0; int request_probe= 0; enum AVCodecID codec_id = AV_CODEC_ID_NONE; enum AVMediaType type; @@ -506,13 +495,18 @@ if (!m->raw_ac3) { /* audio: skip header */ - avio_r8(s->pb); - lpcm_header_len = avio_rb16(s->pb); + avio_skip(s->pb, 3); len -= 3; if (startcode >= 0xb0 && startcode <= 0xbf) { /* MLP/TrueHD audio has a 4-byte header */ avio_r8(s->pb); len--; + } else if (startcode >= 0xa0 && startcode <= 0xaf) { + ret = ffio_ensure_seekback(s->pb, 3); + if (ret < 0) + return ret; + pcm_dvd = (avio_rb24(s->pb) & 0xFF) == 0x80; + avio_skip(s->pb, -3); } } } @@ -591,7 +585,7 @@ codec_id = AV_CODEC_ID_DTS; } else if (startcode >= 0xa0 && startcode <= 0xaf) { type = AVMEDIA_TYPE_AUDIO; - if (lpcm_header_len >= 6 && startcode == 0xa1) { + if (!pcm_dvd) { codec_id = AV_CODEC_ID_MLP; } else { codec_id = AV_CODEC_ID_PCM_DVD; @@ -628,7 +622,7 @@ st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; st->codecpar->sample_rate = 8000; } - st->request_probe = request_probe; + st->internal->request_probe = request_probe; st->need_parsing = AVSTREAM_PARSE_FULL; found: @@ -700,9 +694,21 @@ #if CONFIG_VOBSUB_DEMUXER +#include "subtitles.h" +#include "libavutil/avassert.h" +#include "libavutil/bprint.h" +#include "libavutil/opt.h" + #define REF_STRING "# VobSub index file," #define MAX_LINE_SIZE 2048 +typedef struct VobSubDemuxContext { + const AVClass *class; + AVFormatContext *sub_ctx; + FFDemuxSubtitlesQueue q[32]; + char *sub_name; +} VobSubDemuxContext; + static int vobsub_probe(const AVProbeData *p) { if (!strncmp(p->buf, REF_STRING, sizeof(REF_STRING) - 1)) @@ -710,12 +716,23 @@ return 0; } +static int vobsub_read_close(AVFormatContext *s) +{ + VobSubDemuxContext *vobsub = s->priv_data; + int i; + + for (i = 0; i < s->nb_streams; i++) + ff_subtitles_queue_clean(&vobsub->q[i]); + if (vobsub->sub_ctx) + avformat_close_input(&vobsub->sub_ctx); + return 0; +} + static int vobsub_read_header(AVFormatContext *s) { int i, ret = 0, header_parsed = 0, langidx = 0; - MpegDemuxContext *vobsub = s->priv_data; + VobSubDemuxContext *vobsub = s->priv_data; size_t fname_len; - char *header_str; AVBPrint header; int64_t delay = 0; AVStream *st = NULL; @@ -728,8 +745,7 @@ char *ext; vobsub->sub_name = av_strdup(s->url); if (!vobsub->sub_name) { - ret = AVERROR(ENOMEM); - goto end; + return AVERROR(ENOMEM); } fname_len = strlen(vobsub->sub_name); @@ -737,24 +753,23 @@ if (fname_len < 4 || *(ext - 1) != '.') { av_log(s, AV_LOG_ERROR, "The input index filename is too short " "to guess the associated .SUB file\n"); - ret = AVERROR_INVALIDDATA; - goto end; + return AVERROR_INVALIDDATA; } memcpy(ext, !strncmp(ext, "IDX", 3) ? "SUB" : "sub", 3); av_log(s, AV_LOG_VERBOSE, "IDX/SUB: %s -> %s\n", s->url, vobsub->sub_name); } if (!(iformat = av_find_input_format("mpeg"))) { - ret = AVERROR_DEMUXER_NOT_FOUND; - goto end; + return AVERROR_DEMUXER_NOT_FOUND; } vobsub->sub_ctx = avformat_alloc_context(); if (!vobsub->sub_ctx) { - ret = AVERROR(ENOMEM); - goto end; + return AVERROR(ENOMEM); } + av_bprint_init(&header, 0, INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE); + if ((ret = ff_copy_whiteblacklists(vobsub->sub_ctx, s)) < 0) goto end; @@ -764,7 +779,6 @@ goto end; } - av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED); while (!avio_feof(s->pb)) { char line[MAX_LINE_SIZE]; int len = ff_get_line(s->pb, line, sizeof(line)); @@ -885,29 +899,30 @@ } if (!av_bprint_is_complete(&header)) { - av_bprint_finalize(&header, NULL); ret = AVERROR(ENOMEM); goto end; } - av_bprint_finalize(&header, &header_str); for (i = 0; i < s->nb_streams; i++) { - AVStream *sub_st = s->streams[i]; - sub_st->codecpar->extradata = av_strdup(header_str); - sub_st->codecpar->extradata_size = header.len; + AVCodecParameters *par = s->streams[i]->codecpar; + ret = ff_alloc_extradata(par, header.len); + if (ret < 0) { + goto end; + } + memcpy(par->extradata, header.str, header.len); } - av_free(header_str); - end: + if (ret < 0) + vobsub_read_close(s); + av_bprint_finalize(&header, NULL); return ret; } static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt) { - MpegDemuxContext *vobsub = s->priv_data; + VobSubDemuxContext *vobsub = s->priv_data; FFDemuxSubtitlesQueue *q; AVIOContext *pb = vobsub->sub_ctx->pb; int ret, psize, total_read = 0, i; - AVPacket idx_pkt = { 0 }; int64_t min_ts = INT64_MAX; int sid = 0; @@ -915,31 +930,33 @@ FFDemuxSubtitlesQueue *tmpq = &vobsub->q[i]; int64_t ts; av_assert0(tmpq->nb_subs); - ts = tmpq->subs[tmpq->current_sub_idx].pts; + + if (tmpq->current_sub_idx >= tmpq->nb_subs) + continue; + + ts = tmpq->subs[tmpq->current_sub_idx]->pts; if (ts < min_ts) { min_ts = ts; sid = i; } } q = &vobsub->q[sid]; - ret = ff_subtitles_queue_read_packet(q, &idx_pkt); + /* The returned packet will have size zero, + * so that it can be directly used with av_grow_packet. */ + ret = ff_subtitles_queue_read_packet(q, pkt); if (ret < 0) return ret; /* compute maximum packet size using the next packet position. This is * useful when the len in the header is non-sense */ if (q->current_sub_idx < q->nb_subs) { - psize = q->subs[q->current_sub_idx].pos - idx_pkt.pos; + psize = q->subs[q->current_sub_idx]->pos - pkt->pos; } else { int64_t fsize = avio_size(pb); - psize = fsize < 0 ? 0xffff : fsize - idx_pkt.pos; + psize = fsize < 0 ? 0xffff : fsize - pkt->pos; } - avio_seek(pb, idx_pkt.pos, SEEK_SET); - - av_init_packet(pkt); - pkt->size = 0; - pkt->data = NULL; + avio_seek(pb, pkt->pos, SEEK_SET); do { int n, to_read, startcode; @@ -951,7 +968,7 @@ if (ret < 0) { if (pkt->size) // raise packet even if incomplete break; - goto fail; + return ret; } to_read = ret & 0xffff; new_pos = avio_tell(pb); @@ -963,35 +980,25 @@ total_read += pkt_size; /* the current chunk doesn't match the stream index (unlikely) */ - if ((startcode & 0x1f) != s->streams[idx_pkt.stream_index]->id) + if ((startcode & 0x1f) != s->streams[pkt->stream_index]->id) break; ret = av_grow_packet(pkt, to_read); if (ret < 0) - goto fail; + return ret; n = avio_read(pb, pkt->data + (pkt->size - to_read), to_read); if (n < to_read) pkt->size -= to_read - n; } while (total_read < psize); - pkt->pts = pkt->dts = idx_pkt.pts; - pkt->pos = idx_pkt.pos; - pkt->stream_index = idx_pkt.stream_index; - - av_packet_unref(&idx_pkt); return 0; - -fail: - av_packet_unref(pkt); - av_packet_unref(&idx_pkt); - return ret; } static int vobsub_read_seek(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags) { - MpegDemuxContext *vobsub = s->priv_data; + VobSubDemuxContext *vobsub = s->priv_data; /* Rescale requested timestamps based on the first stream (timebase is the * same for all subtitles stream within a .idx/.sub). Rescaling is done just @@ -1021,20 +1028,8 @@ min_ts, ts, max_ts, flags); } -static int vobsub_read_close(AVFormatContext *s) -{ - int i; - MpegDemuxContext *vobsub = s->priv_data; - - for (i = 0; i < s->nb_streams; i++) - ff_subtitles_queue_clean(&vobsub->q[i]); - if (vobsub->sub_ctx) - avformat_close_input(&vobsub->sub_ctx); - return 0; -} - static const AVOption options[] = { - { "sub_name", "URI for .sub file", offsetof(MpegDemuxContext, sub_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, + { "sub_name", "URI for .sub file", offsetof(VobSubDemuxContext, sub_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, { NULL } }; @@ -1048,7 +1043,7 @@ AVInputFormat ff_vobsub_demuxer = { .name = "vobsub", .long_name = NULL_IF_CONFIG_SMALL("VobSub subtitle format"), - .priv_data_size = sizeof(MpegDemuxContext), + .priv_data_size = sizeof(VobSubDemuxContext), .read_probe = vobsub_probe, .read_header = vobsub_read_header, .read_packet = vobsub_read_packet, diff -Nru ffmpeg-4.2.2/libavformat/mpegenc.c ffmpeg-4.4/libavformat/mpegenc.c --- ffmpeg-4.2.2/libavformat/mpegenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mpegenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -48,9 +48,9 @@ uint8_t id; int max_buffer_size; /* in bytes */ int buffer_index; - PacketDesc *predecode_packet; + PacketDesc *predecode_packet; /* start of packet queue */ + PacketDesc *last_packet; /* end of packet queue */ PacketDesc *premux_packet; - PacketDesc **next_packet; int packet_number; uint8_t lpcm_header[3]; int lpcm_align; @@ -315,7 +315,7 @@ if (ctx->packet_size < 20 || ctx->packet_size > (1 << 23) + 10) { av_log(ctx, AV_LOG_ERROR, "Invalid packet size %d\n", ctx->packet_size); - goto fail; + return AVERROR(EINVAL); } s->packet_size = ctx->packet_size; } else @@ -343,7 +343,7 @@ st = ctx->streams[i]; stream = av_mallocz(sizeof(StreamInfo)); if (!stream) - goto fail; + return AVERROR(ENOMEM); st->priv_data = stream; avpriv_set_pts_info(st, 64, 1, 90000); @@ -377,11 +377,11 @@ for (sr = 0; sr < 4; sr++) av_log(ctx, AV_LOG_INFO, " %d", lpcm_freq_tab[sr]); av_log(ctx, AV_LOG_INFO, "\n"); - goto fail; + return AVERROR(EINVAL); } if (st->codecpar->channels > 8) { av_log(ctx, AV_LOG_ERROR, "At most 8 channels allowed for LPCM streams.\n"); - goto fail; + return AVERROR(EINVAL); } stream->lpcm_header[0] = 0x0c; stream->lpcm_header[1] = (st->codecpar->channels - 1) | (j << 4); @@ -416,7 +416,7 @@ st->codecpar->codec_id != AV_CODEC_ID_MP2 && st->codecpar->codec_id != AV_CODEC_ID_MP3) { av_log(ctx, AV_LOG_ERROR, "Unsupported audio codec. Must be one of mp1, mp2, mp3, 16-bit pcm_dvd, pcm_s16be, ac3 or dts.\n"); - goto fail; + return AVERROR(EINVAL); } else { stream->id = mpa_id++; } @@ -460,7 +460,7 @@ } stream->fifo = av_fifo_alloc(16); if (!stream->fifo) - goto fail; + return AVERROR(ENOMEM); } bitrate = 0; audio_bitrate = 0; @@ -560,11 +560,6 @@ s->system_header_size = get_system_header_size(ctx); s->last_scr = AV_NOPTS_VALUE; return 0; - -fail: - for (i = 0; i < ctx->nb_streams; i++) - av_freep(&ctx->streams[i]->priv_data); - return AVERROR(ENOMEM); } static inline void put_timestamp(AVIOContext *pb, int id, int64_t timestamp) @@ -933,7 +928,7 @@ for (i = 0; i < zero_trail_bytes; i++) avio_w8(ctx->pb, 0x00); - avio_flush(ctx->pb); + avio_write_marker(ctx->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); s->packet_number++; @@ -962,7 +957,7 @@ s->vcd_padding_bytes_written += s->packet_size; - avio_flush(ctx->pb); + avio_write_marker(ctx->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); /* increasing the packet number is correct. The SCR of the following packs * is calculated from the packet_number and it has to include the padding @@ -991,6 +986,8 @@ } stream->buffer_index -= pkt_desc->size; stream->predecode_packet = pkt_desc->next; + if (!stream->predecode_packet) + stream->last_packet = NULL; av_freep(&pkt_desc); } } @@ -1154,7 +1151,7 @@ StreamInfo *stream = st->priv_data; int64_t pts, dts; PacketDesc *pkt_desc; - int preload; + int preload, ret; const int is_iframe = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && (pkt->flags & AV_PKT_FLAG_KEY); @@ -1182,14 +1179,6 @@ av_log(ctx, AV_LOG_TRACE, "dts:%f pts:%f flags:%d stream:%d nopts:%d\n", dts / 90000.0, pts / 90000.0, pkt->flags, pkt->stream_index, pts != AV_NOPTS_VALUE); - if (!stream->premux_packet) - stream->next_packet = &stream->premux_packet; - *stream->next_packet = - pkt_desc = av_mallocz(sizeof(PacketDesc)); - if (!pkt_desc) - return AVERROR(ENOMEM); - pkt_desc->pts = pts; - pkt_desc->dts = dts; if (st->codecpar->codec_id == AV_CODEC_ID_PCM_DVD) { if (size < 3) { @@ -1203,19 +1192,29 @@ size -= 3; } + pkt_desc = av_mallocz(sizeof(PacketDesc)); + if (!pkt_desc) + return AVERROR(ENOMEM); + if (!stream->predecode_packet) { + stream->predecode_packet = pkt_desc; + } else + stream->last_packet->next = pkt_desc; + stream->last_packet = pkt_desc; + if (!stream->premux_packet) + stream->premux_packet = pkt_desc; + pkt_desc->pts = pts; + pkt_desc->dts = dts; pkt_desc->unwritten_size = pkt_desc->size = size; - if (!stream->predecode_packet) - stream->predecode_packet = pkt_desc; - stream->next_packet = &pkt_desc->next; - if (av_fifo_realloc2(stream->fifo, av_fifo_size(stream->fifo) + size) < 0) - return -1; + ret = av_fifo_realloc2(stream->fifo, av_fifo_size(stream->fifo) + size); + if (ret < 0) + return ret; if (s->is_dvd) { // min VOBU length 0.4 seconds (mpucoder) if (is_iframe && - (s->packet_number == 0 || + (s->packet_number == 0 || pts != AV_NOPTS_VALUE && (pts - stream->vobu_start_pts >= 36000))) { stream->bytes_to_iframe = av_fifo_size(stream->fifo); stream->align_iframe = 1; @@ -1249,17 +1248,30 @@ * it as it is usually not needed by decoders and because it * complicates MPEG stream concatenation. */ // avio_wb32(ctx->pb, ISO_11172_END_CODE); - // avio_flush(ctx->pb); for (i = 0; i < ctx->nb_streams; i++) { stream = ctx->streams[i]->priv_data; av_assert0(av_fifo_size(stream->fifo) == 0); - av_fifo_freep(&stream->fifo); } return 0; } +static void mpeg_mux_deinit(AVFormatContext *ctx) +{ + for (int i = 0; i < ctx->nb_streams; i++) { + StreamInfo *stream = ctx->streams[i]->priv_data; + if (!stream) + continue; + for (PacketDesc *pkt = stream->predecode_packet; pkt; ) { + PacketDesc *tmp = pkt->next; + av_free(pkt); + pkt = tmp; + } + av_fifo_freep(&stream->fifo); + } +} + #define OFFSET(x) offsetof(MpegMuxContext, x) #define E AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { @@ -1289,6 +1301,7 @@ .write_header = mpeg_mux_init, .write_packet = mpeg_mux_write_packet, .write_trailer = mpeg_mux_end, + .deinit = mpeg_mux_deinit, .priv_class = &mpeg_class, }; #endif @@ -1305,6 +1318,7 @@ .write_header = mpeg_mux_init, .write_packet = mpeg_mux_write_packet, .write_trailer = mpeg_mux_end, + .deinit = mpeg_mux_deinit, .priv_class = &vcd_class, }; #endif @@ -1322,6 +1336,7 @@ .write_header = mpeg_mux_init, .write_packet = mpeg_mux_write_packet, .write_trailer = mpeg_mux_end, + .deinit = mpeg_mux_deinit, .priv_class = &vob_class, }; #endif @@ -1340,6 +1355,7 @@ .write_header = mpeg_mux_init, .write_packet = mpeg_mux_write_packet, .write_trailer = mpeg_mux_end, + .deinit = mpeg_mux_deinit, .priv_class = &svcd_class, }; #endif @@ -1358,6 +1374,7 @@ .write_header = mpeg_mux_init, .write_packet = mpeg_mux_write_packet, .write_trailer = mpeg_mux_end, + .deinit = mpeg_mux_deinit, .priv_class = &dvd_class, }; #endif diff -Nru ffmpeg-4.2.2/libavformat/mpegts.c ffmpeg-4.4/libavformat/mpegts.c --- ffmpeg-4.2.2/libavformat/mpegts.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mpegts.c 2021-04-08 21:28:40.000000000 +0000 @@ -20,6 +20,7 @@ */ #include "libavutil/buffer.h" +#include "libavutil/common.h" #include "libavutil/crc.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" @@ -28,6 +29,7 @@ #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "libavutil/avassert.h" +#include "libavutil/dovi_meta.h" #include "libavcodec/bytestream.h" #include "libavcodec/get_bits.h" #include "libavcodec/opus.h" @@ -105,11 +107,19 @@ } u; }; -#define MAX_PIDS_PER_PROGRAM 64 +struct Stream { + int idx; + int stream_identifier; +}; + +#define MAX_STREAMS_PER_PROGRAM 128 +#define MAX_PIDS_PER_PROGRAM (MAX_STREAMS_PER_PROGRAM + 2) struct Program { unsigned int id; // program id/service id unsigned int nb_pids; unsigned int pids[MAX_PIDS_PER_PROGRAM]; + unsigned int nb_streams; + struct Stream streams[MAX_STREAMS_PER_PROGRAM]; /** have we found pmt for this program */ int pmt_found; @@ -122,10 +132,6 @@ /** raw packet size, including FEC if present */ int raw_packet_size; - int size_stat[3]; - int size_stat_count; -#define SIZE_STAT_THRESHOLD 10 - int64_t pos47_full; /** if true, all pids are analyzed to find streams */ @@ -138,7 +144,7 @@ int fix_teletext_pts; int64_t cur_pcr; /**< used to estimate the exact PCR */ - int pcr_incr; /**< used to estimate the exact PCR */ + int64_t pcr_incr; /**< used to estimate the exact PCR */ /* data needed to handle file based ts */ /** stop parsing loop */ @@ -168,6 +174,9 @@ /** filters for various streams specified by PMT + for the PAT and PMT */ MpegTSFilter *pids[NB_PID_MAX]; int current_pid; + + AVStream *epg_stream; + AVBufferPool* pools[32]; }; #define MPEGTS_OPTIONS \ @@ -285,16 +294,13 @@ prg->nb_stream_indexes = 0; } -static void clear_program(MpegTSContext *ts, unsigned int programid) +static void clear_program(struct Program *p) { - int i; - - clear_avprogram(ts, programid); - for (i = 0; i < ts->nb_prg; i++) - if (ts->prg[i].id == programid) { - ts->prg[i].nb_pids = 0; - ts->prg[i].pmt_found = 0; - } + if (!p) + return; + p->nb_pids = 0; + p->nb_streams = 0; + p->pmt_found = 0; } static void clear_programs(MpegTSContext *ts) @@ -303,24 +309,24 @@ ts->nb_prg = 0; } -static void add_pat_entry(MpegTSContext *ts, unsigned int programid) +static struct Program * add_program(MpegTSContext *ts, unsigned int programid) { - struct Program *p; + struct Program *p = get_program(ts, programid); + if (p) + return p; if (av_reallocp_array(&ts->prg, ts->nb_prg + 1, sizeof(*ts->prg)) < 0) { ts->nb_prg = 0; - return; + return NULL; } p = &ts->prg[ts->nb_prg]; p->id = programid; - p->nb_pids = 0; - p->pmt_found = 0; + clear_program(p); ts->nb_prg++; + return p; } -static void add_pid_to_pmt(MpegTSContext *ts, unsigned int programid, - unsigned int pid) +static void add_pid_to_program(struct Program *p, unsigned int pid) { - struct Program *p = get_program(ts, programid); int i; if (!p) return; @@ -335,15 +341,6 @@ p->pids[p->nb_pids++] = pid; } -static void set_pmt_found(MpegTSContext *ts, unsigned int programid) -{ - struct Program *p = get_program(ts, programid); - if (!p) - return; - - p->pmt_found = 1; -} - static void update_av_program_info(AVFormatContext *s, unsigned int programid, unsigned int pid, int version) { @@ -380,6 +377,9 @@ int used = 0, discarded = 0; struct Program *p; + if (pid == PAT_PID) + return 0; + /* If none of the programs have .discard=AVDISCARD_ALL then there's * no way we have to discard this packet */ for (k = 0; k < ts->stream->nb_programs; k++) @@ -510,20 +510,22 @@ { MpegTSFilter *filter; MpegTSSectionFilter *sec; + uint8_t *section_buf = av_mallocz(MAX_SECTION_SIZE); - if (!(filter = mpegts_open_filter(ts, pid, MPEGTS_SECTION))) + if (!section_buf) return NULL; + + if (!(filter = mpegts_open_filter(ts, pid, MPEGTS_SECTION))) { + av_free(section_buf); + return NULL; + } sec = &filter->u.section_filter; sec->section_cb = section_cb; sec->opaque = opaque; - sec->section_buf = av_mallocz(MAX_SECTION_SIZE); + sec->section_buf = section_buf; sec->check_crc = check_crc; sec->last_ver = -1; - if (!sec->section_buf) { - av_free(filter); - return NULL; - } return filter; } @@ -607,8 +609,9 @@ /*init buffer to store stream for probing */ uint8_t buf[PROBE_PACKET_MAX_BUF] = {0}; int buf_size = 0; + int max_iterations = 16; - while (buf_size < PROBE_PACKET_MAX_BUF) { + while (buf_size < PROBE_PACKET_MAX_BUF && max_iterations--) { ret = avio_read_partial(s->pb, buf + buf_size, PROBE_PACKET_MAX_BUF - buf_size); if (ret < 0) return AVERROR_INVALIDDATA; @@ -803,6 +806,7 @@ { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC }, { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS }, { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, + { 0xd2, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_AVS2 }, { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, { 0 }, }; @@ -879,7 +883,7 @@ st->codecpar->codec_id = types->codec_id; st->internal->need_context_update = 1; } - st->request_probe = 0; + st->internal->request_probe = 0; return; } } @@ -912,7 +916,7 @@ mpegts_find_stream_type(st, pes->stream_type, ISO_types); if (pes->stream_type == 4 || pes->stream_type == 0x0f) - st->request_probe = 50; + st->internal->request_probe = 50; if ((prog_reg_desc == AV_RL32("HDMV") || prog_reg_desc == AV_RL32("HDPR")) && st->codecpar->codec_id == AV_CODEC_ID_NONE) { @@ -949,12 +953,12 @@ st->codecpar->codec_type = old_codec_type; } if ((st->codecpar->codec_id == AV_CODEC_ID_NONE || - (st->request_probe > 0 && st->request_probe < AVPROBE_SCORE_STREAM_RETRY / 5)) && + (st->internal->request_probe > 0 && st->internal->request_probe < AVPROBE_SCORE_STREAM_RETRY / 5)) && st->probe_packets > 0 && stream_type == STREAM_TYPE_PRIVATE_DATA) { st->codecpar->codec_type = AVMEDIA_TYPE_DATA; st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA; - st->request_probe = AVPROBE_SCORE_STREAM_RETRY / 5; + st->internal->request_probe = AVPROBE_SCORE_STREAM_RETRY / 5; } /* queue a context update if properties changed */ @@ -977,7 +981,7 @@ static void new_data_packet(const uint8_t *buffer, int len, AVPacket *pkt) { - av_init_packet(pkt); + av_packet_unref(pkt); pkt->data = (uint8_t *)buffer; pkt->size = len; } @@ -986,7 +990,7 @@ { uint8_t *sd; - av_init_packet(pkt); + av_packet_unref(pkt); pkt->buf = pes->buffer; pkt->data = pes->buffer->data; @@ -1100,6 +1104,18 @@ return (get_bits_count(&gb) + 7) >> 3; } +static AVBufferRef *buffer_pool_get(MpegTSContext *ts, int size) +{ + int index = av_log2(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!ts->pools[index]) { + int pool_size = FFMIN(MAX_PES_PAYLOAD + AV_INPUT_BUFFER_PADDING_SIZE, 2 << index); + ts->pools[index] = av_buffer_pool_init(pool_size, NULL); + if (!ts->pools[index]) + return NULL; + } + return av_buffer_pool_get(ts->pools[index]); +} + /* return non zero if a packet could be constructed */ static int mpegts_push_data(MpegTSFilter *filter, const uint8_t *buf, int buf_size, int is_start, @@ -1174,8 +1190,7 @@ pes->total_size = MAX_PES_PAYLOAD; /* allocate pes buffer */ - pes->buffer = av_buffer_alloc(pes->total_size + - AV_INPUT_BUFFER_PADDING_SIZE); + pes->buffer = buffer_pool_get(ts, pes->total_size); if (!pes->buffer) return AVERROR(ENOMEM); @@ -1184,12 +1199,12 @@ code != 0x1ff && code != 0x1f2 && /* program_stream_directory, DSMCC_stream */ code != 0x1f8) { /* ITU-T Rec. H.222.1 type E stream */ pes->state = MPEGTS_PESHEADER; - if (pes->st->codecpar->codec_id == AV_CODEC_ID_NONE && !pes->st->request_probe) { + if (pes->st->codecpar->codec_id == AV_CODEC_ID_NONE && !pes->st->internal->request_probe) { av_log(pes->stream, AV_LOG_TRACE, "pid=%x stream_type=%x probing\n", pes->pid, pes->stream_type); - pes->st->request_probe = 1; + pes->st->internal->request_probe = 1; } } else { pes->pes_header_size = 6; @@ -1311,8 +1326,8 @@ int64_t pcr = f->last_pcr / 300; pcr_found = 1; if (st) { - pes->st->pts_wrap_reference = st->pts_wrap_reference; - pes->st->pts_wrap_behavior = st->pts_wrap_behavior; + pes->st->internal->pts_wrap_reference = st->internal->pts_wrap_reference; + pes->st->internal->pts_wrap_behavior = st->internal->pts_wrap_behavior; } if (pes->dts == AV_NOPTS_VALUE || pes->dts < pcr) { pes->pts = pes->dts = pcr; @@ -1329,7 +1344,8 @@ } } - if (!pcr_found) { + if (pes->st->codecpar->codec_id == AV_CODEC_ID_DVB_TELETEXT && + !pcr_found) { av_log(pes->stream, AV_LOG_VERBOSE, "Forcing DTS/PTS to be unset for a " "non-trustworthy PES packet for PID %d as " @@ -1348,8 +1364,7 @@ if (ret < 0) return ret; pes->total_size = MAX_PES_PAYLOAD; - pes->buffer = av_buffer_alloc(pes->total_size + - AV_INPUT_BUFFER_PADDING_SIZE); + pes->buffer = buffer_pool_get(ts, pes->total_size); if (!pes->buffer) return AVERROR(ENOMEM); ts->stop_parse = 1; @@ -1785,17 +1800,17 @@ av_log(fc, AV_LOG_TRACE, "tag: 0x%02x len=%d\n", desc_tag, desc_len); - if ((st->codecpar->codec_id == AV_CODEC_ID_NONE || st->request_probe > 0) && + if ((st->codecpar->codec_id == AV_CODEC_ID_NONE || st->internal->request_probe > 0) && stream_type == STREAM_TYPE_PRIVATE_DATA) mpegts_find_stream_type(st, desc_tag, DESC_types); switch (desc_tag) { - case 0x02: /* video stream descriptor */ + case VIDEO_STREAM_DESCRIPTOR: if (get8(pp, desc_end) & 0x1) { st->disposition |= AV_DISPOSITION_STILL_IMAGE; } break; - case 0x1E: /* SL descriptor */ + case SL_DESCRIPTOR: desc_es_id = get16(pp, desc_end); if (desc_es_id < 0) break; @@ -1818,13 +1833,13 @@ mpegts_open_section_filter(ts, pid, m4sl_cb, ts, 1); } break; - case 0x1F: /* FMC descriptor */ + case FMC_DESCRIPTOR: if (get16(pp, desc_end) < 0) break; if (mp4_descr_count > 0 && (st->codecpar->codec_id == AV_CODEC_ID_AAC_LATM || - (st->request_probe == 0 && st->codecpar->codec_id == AV_CODEC_ID_NONE) || - st->request_probe > 0) && + (st->internal->request_probe == 0 && st->codecpar->codec_id == AV_CODEC_ID_NONE) || + st->internal->request_probe > 0) && mp4_descr->dec_config_descr_len && mp4_descr->es_id == pid) { AVIOContext pb; ffio_init_context(&pb, mp4_descr->dec_config_descr, @@ -1833,7 +1848,7 @@ ff_mp4_read_dec_config_descr(fc, st, &pb); if (st->codecpar->codec_id == AV_CODEC_ID_AAC && st->codecpar->extradata_size > 0) { - st->request_probe = st->need_parsing = 0; + st->internal->request_probe = st->need_parsing = 0; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->internal->need_context_update = 1; } @@ -1842,7 +1857,7 @@ case 0x56: /* DVB teletext descriptor */ { uint8_t *extradata = NULL; - int language_count = desc_len / 5; + int language_count = desc_len / 5, ret; if (desc_len > 0 && desc_len % 5 != 0) return AVERROR_INVALIDDATA; @@ -1852,9 +1867,9 @@ av_assert0(language_count <= sizeof(language) / 4); if (st->codecpar->extradata == NULL) { - if (ff_alloc_extradata(st->codecpar, language_count * 2)) { - return AVERROR(ENOMEM); - } + ret = ff_alloc_extradata(st->codecpar, language_count * 2); + if (ret < 0) + return ret; } if (st->codecpar->extradata_size < language_count * 2) @@ -1887,7 +1902,7 @@ * subtitling_type (1 byte), * composition_page_id (2 bytes), * ancillary_page_id (2 bytes) */ - int language_count = desc_len / 8; + int language_count = desc_len / 8, ret; if (desc_len > 0 && desc_len % 8 != 0) return AVERROR_INVALIDDATA; @@ -1903,9 +1918,9 @@ av_assert0(language_count <= sizeof(language) / 4); if (st->codecpar->extradata == NULL) { - if (ff_alloc_extradata(st->codecpar, language_count * 5)) { - return AVERROR(ENOMEM); - } + ret = ff_alloc_extradata(st->codecpar, language_count * 5); + if (ret < 0) + return ret; } if (st->codecpar->extradata_size < language_count * 5) @@ -1944,7 +1959,7 @@ } } break; - case 0x0a: /* ISO 639 language descriptor */ + case ISO_639_LANGUAGE_DESCRIPTOR: for (i = 0; i + 4 <= desc_len; i += 4) { language[i + 0] = get8(pp, desc_end); language[i + 1] = get8(pp, desc_end); @@ -1970,19 +1985,19 @@ av_dict_set(&st->metadata, "language", language, AV_DICT_DONT_OVERWRITE); } break; - case 0x05: /* registration descriptor */ + case REGISTRATION_DESCRIPTOR: st->codecpar->codec_tag = bytestream_get_le32(pp); av_log(fc, AV_LOG_TRACE, "reg_desc=%.4s\n", (char *)&st->codecpar->codec_tag); - if (st->codecpar->codec_id == AV_CODEC_ID_NONE || st->request_probe > 0) { + if (st->codecpar->codec_id == AV_CODEC_ID_NONE || st->internal->request_probe > 0) { mpegts_find_stream_type(st, st->codecpar->codec_tag, REGD_types); if (st->codecpar->codec_tag == MKTAG('B', 'S', 'S', 'D')) - st->request_probe = 50; + st->internal->request_probe = 50; } break; case 0x52: /* stream identifier descriptor */ st->stream_identifier = 1 + get8(pp, desc_end); break; - case 0x26: /* metadata descriptor */ + case METADATA_DESCRIPTOR: if (get16(pp, desc_end) == 0xFFFF) *pp += 4; if (get8(pp, desc_end) == 0xFF) { @@ -2129,7 +2144,54 @@ st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codecpar->codec_id = AV_CODEC_ID_ARIB_CAPTION; st->codecpar->profile = picked_profile; - st->request_probe = 0; + st->internal->request_probe = 0; + } + break; + case 0xb0: /* DOVI video stream descriptor */ + { + uint32_t buf; + AVDOVIDecoderConfigurationRecord *dovi; + size_t dovi_size; + int ret; + if (desc_end - *pp < 4) // (8 + 8 + 7 + 6 + 1 + 1 + 1) / 8 + return AVERROR_INVALIDDATA; + + dovi = av_dovi_alloc(&dovi_size); + if (!dovi) + return AVERROR(ENOMEM); + + dovi->dv_version_major = get8(pp, desc_end); + dovi->dv_version_minor = get8(pp, desc_end); + buf = get16(pp, desc_end); + 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 (desc_end - *pp >= 20) { // 4 + 4 * 4 + buf = get8(pp, desc_end); + 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); + return ret; + } + + 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", + 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); } break; default: @@ -2140,25 +2202,20 @@ } static AVStream *find_matching_stream(MpegTSContext *ts, int pid, unsigned int programid, - int stream_identifier, int pmt_stream_idx) + int stream_identifier, int pmt_stream_idx, struct Program *p) { AVFormatContext *s = ts->stream; int i; AVStream *found = NULL; - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - if (st->program_num != programid) - continue; - if (stream_identifier != -1) { /* match based on "stream identifier descriptor" if present */ - if (st->stream_identifier == stream_identifier+1) { - found = st; - break; - } - } else if (st->pmt_stream_idx == pmt_stream_idx) { /* match based on position within the PMT */ - found = st; - break; + if (stream_identifier) { /* match based on "stream identifier descriptor" if present */ + for (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]; } + } else if (pmt_stream_idx < p->nb_streams) { /* match based on position within the PMT */ + found = s->streams[p->streams[pmt_stream_idx].idx]; } if (found) { @@ -2217,6 +2274,7 @@ { MpegTSContext *ts = filter->u.section_filter.opaque; MpegTSSectionFilter *tssf = &filter->u.section_filter; + struct Program old_program; SectionHeader h1, *h = &h1; PESContext *pes; AVStream *st; @@ -2225,6 +2283,7 @@ int desc_list_len; uint32_t prog_reg_desc = 0; /* registration descriptor */ int stream_identifier = -1; + struct Program *prg; int mp4_descr_count = 0; Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = { { 0 } }; @@ -2248,16 +2307,26 @@ if (!ts->scan_all_pmts && ts->skip_changes) return; - if (ts->skip_unknown_pmt && !get_program(ts, h->id)) + prg = get_program(ts, h->id); + if (prg) + old_program = *prg; + else + clear_program(&old_program); + + if (ts->skip_unknown_pmt && !prg) + return; + if (prg && prg->nb_pids && prg->pids[0] != ts->current_pid) return; if (!ts->skip_clear) - clear_program(ts, h->id); + clear_avprogram(ts, h->id); + clear_program(prg); + add_pid_to_program(prg, ts->current_pid); pcr_pid = get16(&p, p_end); if (pcr_pid < 0) return; pcr_pid &= 0x1fff; - add_pid_to_pmt(ts, h->id, pcr_pid); + add_pid_to_program(prg, pcr_pid); update_av_program_info(ts->stream, h->id, pcr_pid, h->version); av_log(ts->stream, AV_LOG_TRACE, "pcr_pid=0x%x\n", pcr_pid); @@ -2277,13 +2346,13 @@ // something else is broken, exit the program_descriptors_loop break; program_info_length -= len + 2; - if (tag == 0x1d) { // IOD descriptor + if (tag == IOD_DESCRIPTOR) { get8(&p, p_end); // scope get8(&p, p_end); // label len -= 2; mp4_read_iods(ts->stream, p, len, mp4_descr + mp4_descr_count, &mp4_descr_count, MAX_MP4_DESCR_COUNT); - } else if (tag == 0x05 && len >= 4) { // registration descriptor + } else if (tag == REGISTRATION_DESCRIPTOR && len >= 4) { prog_reg_desc = bytestream_get_le32(&p); len -= 4; } @@ -2294,13 +2363,13 @@ goto out; // stop parsing after pmt, we found header - if (!ts->stream->nb_streams) + if (!ts->pkt) ts->stop_parse = 2; - set_pmt_found(ts, h->id); + if (prg) + prg->pmt_found = 1; - - for (i = 0; ; i++) { + for (i = 0; i < MAX_STREAMS_PER_PROGRAM; i++) { st = 0; pes = NULL; stream_type = get8(&p, p_end); @@ -2313,14 +2382,13 @@ if (pid == ts->current_pid) goto out; - if (ts->merge_pmt_versions) - stream_identifier = parse_stream_identifier_desc(p, p_end); + stream_identifier = parse_stream_identifier_desc(p, p_end) + 1; /* now create stream */ if (ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES) { pes = ts->pids[pid]->u.pes_filter.opaque; if (ts->merge_pmt_versions && !pes->st) { - st = find_matching_stream(ts, pid, h->id, stream_identifier, i); + st = find_matching_stream(ts, pid, h->id, stream_identifier, i, &old_program); if (st) { pes->st = st; pes->stream_type = stream_type; @@ -2332,9 +2400,6 @@ if (!pes->st) goto out; pes->st->id = pes->pid; - pes->st->program_num = h->id; - pes->st->pmt_version = h->version; - pes->st->pmt_stream_idx = i; } st = pes->st; } else if (is_pes_stream(stream_type, prog_reg_desc)) { @@ -2342,7 +2407,7 @@ mpegts_close_filter(ts, ts->pids[pid]); // wrongly added sdt filter probably pes = add_pes_stream(ts, pid, pcr_pid); if (ts->merge_pmt_versions && pes && !pes->st) { - st = find_matching_stream(ts, pid, h->id, stream_identifier, i); + st = find_matching_stream(ts, pid, h->id, stream_identifier, i, &old_program); if (st) { pes->st = st; pes->stream_type = stream_type; @@ -2354,9 +2419,6 @@ if (!st) goto out; st->id = pes->pid; - st->program_num = h->id; - st->pmt_version = h->version; - st->pmt_stream_idx = i; } } else { int idx = ff_find_stream_index(ts->stream, pid); @@ -2364,16 +2426,13 @@ st = ts->stream->streams[idx]; } if (ts->merge_pmt_versions && !st) { - st = find_matching_stream(ts, pid, h->id, stream_identifier, i); + st = find_matching_stream(ts, pid, h->id, stream_identifier, i, &old_program); } if (!st) { st = avformat_new_stream(ts->stream, NULL); if (!st) goto out; st->id = pid; - st->program_num = h->id; - st->pmt_version = h->version; - st->pmt_stream_idx = i; st->codecpar->codec_type = AVMEDIA_TYPE_DATA; if (stream_type == 0x86 && prog_reg_desc == AV_RL32("CUEI")) { mpegts_find_stream_type(st, stream_type, SCTE_types); @@ -2388,7 +2447,12 @@ if (pes && !pes->stream_type) mpegts_set_stream_info(st, pes, stream_type, prog_reg_desc); - add_pid_to_pmt(ts, h->id, pid); + add_pid_to_program(prg, pid); + if (prg) { + prg->streams[i].idx = st->index; + prg->streams[i].stream_identifier = stream_identifier; + prg->nb_streams++; + } av_program_add_stream_index(ts->stream, h->id, st->index); @@ -2430,6 +2494,7 @@ SectionHeader h1, *h = &h1; const uint8_t *p, *p_end; int sid, pmt_pid; + int nb_prg = 0; AVProgram *program; av_log(ts->stream, AV_LOG_TRACE, "PAT:\n"); @@ -2448,7 +2513,6 @@ return; ts->stream->ts_id = h->id; - clear_programs(ts); for (;;) { sid = get16(&p, p_end); if (sid < 0) @@ -2467,6 +2531,7 @@ /* NIT info */ } else { MpegTSFilter *fil = ts->pids[pmt_pid]; + struct Program *prg; program = av_new_program(ts->stream, sid); if (program) { program->program_num = sid; @@ -2480,11 +2545,20 @@ if (!ts->pids[pmt_pid]) mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1); - add_pat_entry(ts, sid); - add_pid_to_pmt(ts, sid, 0); // add pat pid to program - add_pid_to_pmt(ts, sid, pmt_pid); + prg = add_program(ts, sid); + if (prg) { + unsigned prg_idx = prg - ts->prg; + if (prg->nb_pids && prg->pids[0] != pmt_pid) + clear_program(prg); + add_pid_to_program(prg, pmt_pid); + if (prg_idx > nb_prg) + FFSWAP(struct Program, ts->prg[nb_prg], ts->prg[prg_idx]); + if (prg_idx >= nb_prg) + nb_prg++; + } } } + ts->nb_prg = nb_prg; if (sid < 0) { int i,j; @@ -2498,6 +2572,60 @@ } } +static void eit_cb(MpegTSFilter *filter, const uint8_t *section, int section_len) +{ + MpegTSContext *ts = filter->u.section_filter.opaque; + const uint8_t *p, *p_end; + SectionHeader h1, *h = &h1; + + /* + * Sometimes we receive EPG packets but SDT table do not have + * eit_pres_following or eit_sched turned on, so we open EPG + * stream directly here. + */ + if (!ts->epg_stream) { + ts->epg_stream = avformat_new_stream(ts->stream, NULL); + if (!ts->epg_stream) + return; + ts->epg_stream->id = EIT_PID; + ts->epg_stream->codecpar->codec_type = AVMEDIA_TYPE_DATA; + ts->epg_stream->codecpar->codec_id = AV_CODEC_ID_EPG; + } + + if (ts->epg_stream->discard == AVDISCARD_ALL) + return; + + p_end = section + section_len - 4; + p = section; + + if (parse_section_header(h, &p, p_end) < 0) + return; + if (h->tid < EIT_TID || h->tid > OEITS_END_TID) + return; + + av_log(ts->stream, AV_LOG_TRACE, "EIT: tid received = %.02x\n", h->tid); + + /** + * Service_id 0xFFFF is reserved, it indicates that the current EIT table + * is scrambled. + */ + if (h->id == 0xFFFF) { + av_log(ts->stream, AV_LOG_TRACE, "Scrambled EIT table received.\n"); + return; + } + + /** + * In case we receive an EPG packet before mpegts context is fully + * initialized. + */ + if (!ts->pkt) + return; + + new_data_packet(section, section_len, ts->pkt); + ts->pkt->stream_index = ts->epg_stream->index; + ts->stop_parse = 1; +} + static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len) { MpegTSContext *ts = filter->u.section_filter.opaque; @@ -2586,13 +2714,12 @@ const uint8_t *packet); /* handle one TS packet */ -static int handle_packet(MpegTSContext *ts, const uint8_t *packet) +static int handle_packet(MpegTSContext *ts, const uint8_t *packet, int64_t pos) { MpegTSFilter *tss; int len, pid, cc, expected_cc, cc_ok, afc, is_start, is_discontinuity, has_adaptation, has_payload; const uint8_t *p, *p_end; - int64_t pos; pid = AV_RB16(packet + 1) & 0x1fff; is_start = packet[1] & 0x40; @@ -2659,7 +2786,6 @@ if (p >= p_end || !has_payload) return 0; - pos = avio_tell(ts->stream->pb); if (pos >= 0) { av_assert0(pos >= TS_PACKET_SIZE); ts->pos47_full = pos - TS_PACKET_SIZE; @@ -2726,63 +2852,39 @@ return 0; } -static void reanalyze(MpegTSContext *ts) { - AVIOContext *pb = ts->stream->pb; - int64_t pos = avio_tell(pb); - if (pos < 0) - return; - pos -= ts->pos47_full; - if (pos == TS_PACKET_SIZE) { - ts->size_stat[0] ++; - } else if (pos == TS_DVHS_PACKET_SIZE) { - ts->size_stat[1] ++; - } else if (pos == TS_FEC_PACKET_SIZE) { - ts->size_stat[2] ++; - } - - ts->size_stat_count ++; - if (ts->size_stat_count > SIZE_STAT_THRESHOLD) { - int newsize = 0; - if (ts->size_stat[0] > SIZE_STAT_THRESHOLD) { - newsize = TS_PACKET_SIZE; - } else if (ts->size_stat[1] > SIZE_STAT_THRESHOLD) { - newsize = TS_DVHS_PACKET_SIZE; - } else if (ts->size_stat[2] > SIZE_STAT_THRESHOLD) { - newsize = TS_FEC_PACKET_SIZE; - } - if (newsize && newsize != ts->raw_packet_size) { - av_log(ts->stream, AV_LOG_WARNING, "changing packet size to %d\n", newsize); - ts->raw_packet_size = newsize; - } - ts->size_stat_count = 0; - memset(ts->size_stat, 0, sizeof(ts->size_stat)); - } -} - -/* XXX: try to find a better synchro over several packets (use - * get_packet_size() ?) */ static int mpegts_resync(AVFormatContext *s, int seekback, const uint8_t *current_packet) { MpegTSContext *ts = s->priv_data; AVIOContext *pb = s->pb; int c, i; uint64_t pos = avio_tell(pb); - - avio_seek(pb, -FFMIN(seekback, pos), SEEK_CUR); + int64_t back = FFMIN(seekback, pos); //Special case for files like 01c56b0dc1.ts if (current_packet[0] == 0x80 && current_packet[12] == 0x47) { - avio_seek(pb, 12, SEEK_CUR); + avio_seek(pb, 12 - back, SEEK_CUR); return 0; } + avio_seek(pb, -back, SEEK_CUR); + for (i = 0; i < ts->resync_size; i++) { c = avio_r8(pb); if (avio_feof(pb)) return AVERROR_EOF; if (c == 0x47) { + int new_packet_size, ret; avio_seek(pb, -1, SEEK_CUR); - reanalyze(s->priv_data); + pos = avio_tell(pb); + ret = ffio_ensure_seekback(pb, PROBE_PACKET_MAX_BUF); + if (ret < 0) + return ret; + new_packet_size = get_packet_size(s); + if (new_packet_size > 0 && new_packet_size != ts->raw_packet_size) { + av_log(ts->stream, AV_LOG_WARNING, "changing packet size to %d\n", new_packet_size); + ts->raw_packet_size = new_packet_size; + } + avio_seek(pb, pos, SEEK_SET); return 0; } } @@ -2870,7 +2972,7 @@ ret = read_packet(s, packet, ts->raw_packet_size, &data); if (ret != 0) break; - ret = handle_packet(ts, data); + ret = handle_packet(ts, data, avio_tell(s->pb)); finished_reading_packet(s, ts->raw_packet_size); if (ret != 0) break; @@ -2962,10 +3064,11 @@ MpegTSContext *ts = s->priv_data; AVIOContext *pb = s->pb; int64_t pos, probesize = s->probesize; + int64_t seekback = FFMAX(s->probesize, (int64_t)ts->resync_size + PROBE_PACKET_MAX_BUF); s->internal->prefer_codec_framerate = 1; - if (ffio_ensure_seekback(pb, probesize) < 0) + if (ffio_ensure_seekback(pb, seekback) < 0) av_log(s, AV_LOG_WARNING, "Failed to allocate buffers for seekback\n"); pos = avio_tell(pb); @@ -2984,8 +3087,8 @@ seek_back(s, pb, pos); mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1); - mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1); + mpegts_open_section_filter(ts, EIT_PID, eit_cb, ts, 1); handle_packets(ts, probesize / ts->raw_packet_size); /* if could not find service, enable auto_guess */ @@ -2999,7 +3102,6 @@ AVStream *st; int pcr_pid, pid, nb_packets, nb_pcrs, ret, pcr_l; int64_t pcrs[2], pcr_h; - int packet_count[2]; uint8_t packet[TS_PACKET_SIZE]; const uint8_t *data; @@ -3025,7 +3127,6 @@ parse_pcr(&pcr_h, &pcr_l, data) == 0) { finished_reading_packet(s, ts->raw_packet_size); pcr_pid = pid; - packet_count[nb_pcrs] = nb_packets; pcrs[nb_pcrs] = pcr_h * 300 + pcr_l; nb_pcrs++; if (nb_pcrs >= 2) { @@ -3035,7 +3136,6 @@ } else { av_log(ts->stream, AV_LOG_WARNING, "invalid pcr pair %"PRId64" >= %"PRId64"\n", pcrs[0], pcrs[1]); pcrs[0] = pcrs[1]; - packet_count[0] = packet_count[1]; nb_pcrs--; } } @@ -3047,12 +3147,12 @@ /* NOTE1: the bitrate is computed without the FEC */ /* NOTE2: it is only the bitrate of the start of the stream */ - ts->pcr_incr = (pcrs[1] - pcrs[0]) / (packet_count[1] - packet_count[0]); - ts->cur_pcr = pcrs[0] - ts->pcr_incr * packet_count[0]; + ts->pcr_incr = pcrs[1] - pcrs[0]; + ts->cur_pcr = pcrs[0] - ts->pcr_incr * (nb_packets - 1); s->bit_rate = TS_PACKET_SIZE * 8 * 27000000LL / ts->pcr_incr; st->codecpar->bit_rate = s->bit_rate; st->start_time = ts->cur_pcr; - av_log(ts->stream, AV_LOG_TRACE, "start=%0.3f pcr=%0.3f incr=%d\n", + av_log(ts->stream, AV_LOG_TRACE, "start=%0.3f pcr=%0.3f incr=%"PRId64"\n", st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr); } @@ -3071,16 +3171,15 @@ uint8_t pcr_buf[12]; const uint8_t *data; - if (av_new_packet(pkt, TS_PACKET_SIZE) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, TS_PACKET_SIZE)) < 0) + return ret; ret = read_packet(s, pkt->data, ts->raw_packet_size, &data); pkt->pos = avio_tell(s->pb); if (ret < 0) { - av_packet_unref(pkt); return ret; } if (data != pkt->data) - memcpy(pkt->data, data, ts->raw_packet_size); + memcpy(pkt->data, data, TS_PACKET_SIZE); finished_reading_packet(s, ts->raw_packet_size); if (ts->mpeg2ts_compute_pcr) { /* compute exact PCR for each packet */ @@ -3146,6 +3245,9 @@ clear_programs(ts); + for (i = 0; i < FF_ARRAY_ELEMS(ts->pools); i++) + av_buffer_pool_uninit(&ts->pools[i]); + for (i = 0; i < NB_PID_MAX; i++) if (ts->pids[i]) mpegts_close_filter(ts, ts->pids[i]); @@ -3196,33 +3298,37 @@ int64_t *ppos, int64_t pos_limit) { MpegTSContext *ts = s->priv_data; + AVPacket *pkt; int64_t pos; int pos47 = ts->pos47_full % ts->raw_packet_size; pos = ((*ppos + ts->raw_packet_size - 1 - pos47) / ts->raw_packet_size) * ts->raw_packet_size + pos47; ff_read_frame_flush(s); if (avio_seek(s->pb, pos, SEEK_SET) < 0) return AV_NOPTS_VALUE; + pkt = av_packet_alloc(); + if (!pkt) + return AV_NOPTS_VALUE; while(pos < pos_limit) { - int ret; - AVPacket pkt; - av_init_packet(&pkt); - ret = av_read_frame(s, &pkt); - if (ret < 0) + int ret = av_read_frame(s, pkt); + if (ret < 0) { + av_packet_free(&pkt); return AV_NOPTS_VALUE; - if (pkt.dts != AV_NOPTS_VALUE && pkt.pos >= 0) { - ff_reduce_index(s, pkt.stream_index); - av_add_index_entry(s->streams[pkt.stream_index], pkt.pos, pkt.dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */); - if (pkt.stream_index == stream_index && pkt.pos >= *ppos) { - int64_t dts = pkt.dts; - *ppos = pkt.pos; - av_packet_unref(&pkt); + } + if (pkt->dts != AV_NOPTS_VALUE && pkt->pos >= 0) { + ff_reduce_index(s, pkt->stream_index); + av_add_index_entry(s->streams[pkt->stream_index], pkt->pos, pkt->dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */); + if (pkt->stream_index == stream_index && pkt->pos >= *ppos) { + int64_t dts = pkt->dts; + *ppos = pkt->pos; + av_packet_free(&pkt); return dts; } } - pos = pkt.pos; - av_packet_unref(&pkt); + pos = pkt->pos; + av_packet_unref(pkt); } + av_packet_free(&pkt); return AV_NOPTS_VALUE; } @@ -3240,8 +3346,10 @@ ts->raw_packet_size = TS_PACKET_SIZE; ts->stream = s; ts->auto_guess = 1; + mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1); mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1); + mpegts_open_section_filter(ts, EIT_PID, eit_cb, ts, 1); return ts; } @@ -3263,7 +3371,7 @@ buf++; len--; } else { - handle_packet(ts, buf); + handle_packet(ts, buf, len1 - len + TS_PACKET_SIZE); buf += TS_PACKET_SIZE; len -= TS_PACKET_SIZE; if (ts->stop_parse == 1) diff -Nru ffmpeg-4.2.2/libavformat/mpegtsenc.c ffmpeg-4.4/libavformat/mpegtsenc.c --- ffmpeg-4.2.2/libavformat/mpegtsenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mpegtsenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -27,6 +27,7 @@ #include "libavutil/mathematics.h" #include "libavutil/opt.h" +#include "libavcodec/ac3_parser_internal.h" #include "libavcodec/internal.h" #include "avformat.h" @@ -57,8 +58,6 @@ uint8_t name[256]; uint8_t provider_name[256]; int pcr_pid; - int pcr_packet_count; - int pcr_packet_period; AVProgram *program; } MpegTSService; @@ -78,16 +77,16 @@ MpegTSSection pat; /* MPEG-2 PAT table */ MpegTSSection sdt; /* MPEG-2 SDT table context */ MpegTSService **services; - int sdt_packet_count; - int sdt_packet_period; - int pat_packet_count; - int pat_packet_period; + AVPacket *pkt; + int64_t sdt_period; /* SDT period in PCR time base */ + int64_t pat_period; /* PAT/PMT period in PCR time base */ int nb_services; - int onid; - int tsid; int64_t first_pcr; + int first_dts_checked; + int64_t next_pcr; int mux_rate; ///< set to 1 when VBR int pes_payload_size; + int64_t total_size; int transport_stream_id; int original_network_id; @@ -97,10 +96,12 @@ int pmt_start_pid; int start_pid; int m2ts_mode; + int m2ts_video_pid; + int m2ts_audio_pid; + int m2ts_pgssub_pid; + int m2ts_textsub_pid; - int reemit_pat_pmt; // backward compatibility - - int pcr_period; + int pcr_period_ms; #define MPEGTS_FLAG_REEMIT_PAT_PMT 0x01 #define MPEGTS_FLAG_AAC_LATM 0x02 #define MPEGTS_FLAG_PAT_PMT_AT_FRAMES 0x04 @@ -109,8 +110,8 @@ int flags; int copyts; int tables_version; - double pat_period; - double sdt_period; + int64_t pat_period_us; + int64_t sdt_period_us; int64_t last_pat_ts; int64_t last_sdt_ts; @@ -220,7 +221,7 @@ /* mpegts writer */ #define DEFAULT_PROVIDER_NAME "FFmpeg" -#define DEFAULT_SERVICE_NAME "Service01" +#define DEFAULT_SERVICE_NAME "Service" /* we retransmit the SI info at this rate */ #define SDT_RETRANS_TIME 500 @@ -228,23 +229,27 @@ #define PCR_RETRANS_TIME 20 typedef struct MpegTSWriteStream { - struct MpegTSService *service; int pid; /* stream associated pid */ int cc; int discontinuity; int payload_size; - int first_pts_check; ///< first pts check needed + int first_timestamp_checked; ///< first pts/dts check needed int prev_payload_key; int64_t payload_pts; int64_t payload_dts; int payload_flags; uint8_t *payload; AVFormatContext *amux; - AVRational user_tb; + int data_st_warning; + + int64_t pcr_period; /* PCR period in PCR time base */ + int64_t last_pcr; /* For Opus */ int opus_queued_samples; int opus_pending_trim_start; + + DVBAC3Descriptor *dvb_ac3_desc; } MpegTSWriteStream; static void mpegts_write_pat(AVFormatContext *s) @@ -260,7 +265,7 @@ put16(&q, service->sid); put16(&q, 0xe000 | service->pmt.pid); } - mpegts_write_section1(&ts->pat, PAT_TID, ts->tsid, ts->tables_version, 0, 0, + mpegts_write_section1(&ts->pat, PAT_TID, ts->transport_stream_id, ts->tables_version, 0, 0, data, q - data); } @@ -273,7 +278,7 @@ static void put_registration_descriptor(uint8_t **q_ptr, uint32_t tag) { uint8_t *q = *q_ptr; - *q++ = 0x05; /* MPEG-2 registration descriptor*/ + *q++ = REGISTRATION_DESCRIPTOR; *q++ = 4; *q++ = tag; *q++ = tag >> 8; @@ -282,6 +287,148 @@ *q_ptr = q; } +static int get_dvb_stream_type(AVFormatContext *s, AVStream *st) +{ + MpegTSWrite *ts = s->priv_data; + MpegTSWriteStream *ts_st = st->priv_data; + int stream_type; + + switch (st->codecpar->codec_id) { + case AV_CODEC_ID_MPEG1VIDEO: + case AV_CODEC_ID_MPEG2VIDEO: + stream_type = STREAM_TYPE_VIDEO_MPEG2; + break; + case AV_CODEC_ID_MPEG4: + stream_type = STREAM_TYPE_VIDEO_MPEG4; + break; + case AV_CODEC_ID_H264: + stream_type = STREAM_TYPE_VIDEO_H264; + break; + case AV_CODEC_ID_HEVC: + stream_type = STREAM_TYPE_VIDEO_HEVC; + break; + case AV_CODEC_ID_CAVS: + stream_type = STREAM_TYPE_VIDEO_CAVS; + break; + case AV_CODEC_ID_DIRAC: + stream_type = STREAM_TYPE_VIDEO_DIRAC; + break; + case AV_CODEC_ID_VC1: + stream_type = STREAM_TYPE_VIDEO_VC1; + break; + case AV_CODEC_ID_MP2: + case AV_CODEC_ID_MP3: + if ( st->codecpar->sample_rate > 0 + && st->codecpar->sample_rate < 32000) { + stream_type = STREAM_TYPE_AUDIO_MPEG2; + } else { + stream_type = STREAM_TYPE_AUDIO_MPEG1; + } + break; + case AV_CODEC_ID_AAC: + stream_type = (ts->flags & MPEGTS_FLAG_AAC_LATM) + ? STREAM_TYPE_AUDIO_AAC_LATM + : STREAM_TYPE_AUDIO_AAC; + break; + case AV_CODEC_ID_AAC_LATM: + stream_type = STREAM_TYPE_AUDIO_AAC_LATM; + break; + case AV_CODEC_ID_AC3: + stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) + ? STREAM_TYPE_PRIVATE_DATA + : STREAM_TYPE_AUDIO_AC3; + break; + case AV_CODEC_ID_EAC3: + stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) + ? STREAM_TYPE_PRIVATE_DATA + : STREAM_TYPE_AUDIO_EAC3; + break; + case AV_CODEC_ID_DTS: + stream_type = STREAM_TYPE_AUDIO_DTS; + break; + case AV_CODEC_ID_TRUEHD: + stream_type = STREAM_TYPE_AUDIO_TRUEHD; + break; + case AV_CODEC_ID_OPUS: + stream_type = STREAM_TYPE_PRIVATE_DATA; + break; + case AV_CODEC_ID_TIMED_ID3: + stream_type = STREAM_TYPE_METADATA; + break; + case AV_CODEC_ID_DVB_SUBTITLE: + case AV_CODEC_ID_DVB_TELETEXT: + stream_type = STREAM_TYPE_PRIVATE_DATA; + break; + case AV_CODEC_ID_SMPTE_KLV: + if (st->codecpar->profile == FF_PROFILE_KLVA_SYNC) { + stream_type = STREAM_TYPE_METADATA; + } else { + stream_type = STREAM_TYPE_PRIVATE_DATA; + } + break; + default: + av_log_once(s, AV_LOG_WARNING, AV_LOG_DEBUG, &ts_st->data_st_warning, + "Stream %d, codec %s, is muxed as a private data stream " + "and may not be recognized upon reading.\n", st->index, + avcodec_get_name(st->codecpar->codec_id)); + stream_type = STREAM_TYPE_PRIVATE_DATA; + break; + } + + return stream_type; +} + +static int get_m2ts_stream_type(AVFormatContext *s, AVStream *st) +{ + int stream_type; + MpegTSWriteStream *ts_st = st->priv_data; + + switch (st->codecpar->codec_id) { + case AV_CODEC_ID_MPEG2VIDEO: + stream_type = STREAM_TYPE_VIDEO_MPEG2; + break; + case AV_CODEC_ID_H264: + stream_type = STREAM_TYPE_VIDEO_H264; + break; + case AV_CODEC_ID_VC1: + stream_type = STREAM_TYPE_VIDEO_VC1; + break; + case AV_CODEC_ID_HEVC: + stream_type = STREAM_TYPE_VIDEO_HEVC; + break; + case AV_CODEC_ID_PCM_BLURAY: + stream_type = 0x80; + break; + case AV_CODEC_ID_AC3: + stream_type = 0x81; + break; + case AV_CODEC_ID_DTS: + stream_type = (st->codecpar->channels > 6) ? 0x85 : 0x82; + break; + case AV_CODEC_ID_TRUEHD: + stream_type = 0x83; + break; + case AV_CODEC_ID_EAC3: + stream_type = 0x84; + break; + case AV_CODEC_ID_HDMV_PGS_SUBTITLE: + stream_type = 0x90; + break; + case AV_CODEC_ID_HDMV_TEXT_SUBTITLE: + stream_type = 0x92; + break; + default: + av_log_once(s, AV_LOG_WARNING, AV_LOG_DEBUG, &ts_st->data_st_warning, + "Stream %d, codec %s, is muxed as a private data stream " + "and may not be recognized upon reading.\n", st->index, + avcodec_get_name(st->codecpar->codec_id)); + stream_type = STREAM_TYPE_PRIVATE_DATA; + break; + } + + return stream_type; +} + static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) { MpegTSWrite *ts = s->priv_data; @@ -295,6 +442,14 @@ q += 2; /* patched after */ /* put program info here */ + if (ts->m2ts_mode) { + put_registration_descriptor(&q, MKTAG('H', 'D', 'M', 'V')); + *q++ = 0x88; // descriptor_tag - hdmv_copy_control_descriptor + *q++ = 0x04; // descriptor_length + put16(&q, 0x0fff); // CA_System_ID + *q++ = 0xfc; // private_data_byte + *q++ = 0xfc; // private_data_byte + } val = 0xf000 | (q - program_info_length_ptr - 2); program_info_length_ptr[0] = val >> 8; @@ -304,6 +459,7 @@ AVStream *st = s->streams[i]; MpegTSWriteStream *ts_st = st->priv_data; AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); + enum AVCodecID codec_id = st->codecpar->codec_id; if (s->nb_programs) { int k, found = 0; @@ -323,72 +479,8 @@ err = 1; break; } - switch (st->codecpar->codec_id) { - case AV_CODEC_ID_MPEG1VIDEO: - case AV_CODEC_ID_MPEG2VIDEO: - stream_type = STREAM_TYPE_VIDEO_MPEG2; - break; - case AV_CODEC_ID_MPEG4: - stream_type = STREAM_TYPE_VIDEO_MPEG4; - break; - case AV_CODEC_ID_H264: - stream_type = STREAM_TYPE_VIDEO_H264; - break; - case AV_CODEC_ID_HEVC: - stream_type = STREAM_TYPE_VIDEO_HEVC; - break; - case AV_CODEC_ID_CAVS: - stream_type = STREAM_TYPE_VIDEO_CAVS; - break; - case AV_CODEC_ID_DIRAC: - stream_type = STREAM_TYPE_VIDEO_DIRAC; - break; - case AV_CODEC_ID_VC1: - stream_type = STREAM_TYPE_VIDEO_VC1; - break; - case AV_CODEC_ID_MP2: - case AV_CODEC_ID_MP3: - if ( st->codecpar->sample_rate > 0 - && st->codecpar->sample_rate < 32000) { - stream_type = STREAM_TYPE_AUDIO_MPEG2; - } else { - stream_type = STREAM_TYPE_AUDIO_MPEG1; - } - break; - case AV_CODEC_ID_AAC: - stream_type = (ts->flags & MPEGTS_FLAG_AAC_LATM) - ? STREAM_TYPE_AUDIO_AAC_LATM - : STREAM_TYPE_AUDIO_AAC; - break; - case AV_CODEC_ID_AAC_LATM: - stream_type = STREAM_TYPE_AUDIO_AAC_LATM; - break; - case AV_CODEC_ID_AC3: - stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) - ? STREAM_TYPE_PRIVATE_DATA - : STREAM_TYPE_AUDIO_AC3; - break; - case AV_CODEC_ID_EAC3: - stream_type = (ts->flags & MPEGTS_FLAG_SYSTEM_B) - ? STREAM_TYPE_PRIVATE_DATA - : STREAM_TYPE_AUDIO_EAC3; - break; - case AV_CODEC_ID_DTS: - stream_type = STREAM_TYPE_AUDIO_DTS; - break; - case AV_CODEC_ID_TRUEHD: - stream_type = STREAM_TYPE_AUDIO_TRUEHD; - break; - case AV_CODEC_ID_OPUS: - stream_type = STREAM_TYPE_PRIVATE_DATA; - break; - case AV_CODEC_ID_TIMED_ID3: - stream_type = STREAM_TYPE_METADATA; - break; - default: - stream_type = STREAM_TYPE_PRIVATE_DATA; - break; - } + + stream_type = ts->m2ts_mode ? get_m2ts_stream_type(s, st) : get_dvb_stream_type(s, st); *q++ = stream_type; put16(&q, 0xe000 | ts_st->pid); @@ -398,19 +490,43 @@ /* write optional descriptors here */ switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_AUDIO: - if (st->codecpar->codec_id==AV_CODEC_ID_AC3 && (ts->flags & MPEGTS_FLAG_SYSTEM_B)) { - *q++=0x6a; // AC3 descriptor see A038 DVB SI - *q++=1; // 1 byte, all flags sets to 0 - *q++=0; // omit all fields... - } - if (st->codecpar->codec_id==AV_CODEC_ID_EAC3 && (ts->flags & MPEGTS_FLAG_SYSTEM_B)) { - *q++=0x7a; // EAC3 descriptor see A038 DVB SI - *q++=1; // 1 byte, all flags sets to 0 - *q++=0; // omit all fields... + if (codec_id == AV_CODEC_ID_AC3) + put_registration_descriptor(&q, MKTAG('A', 'C', '-', '3')); + if (codec_id == AV_CODEC_ID_EAC3) + put_registration_descriptor(&q, MKTAG('E', 'A', 'C', '3')); + if (ts->flags & MPEGTS_FLAG_SYSTEM_B) { + if (codec_id == AV_CODEC_ID_AC3) { + DVBAC3Descriptor *dvb_ac3_desc = ts_st->dvb_ac3_desc; + + *q++=0x6a; // AC3 descriptor see A038 DVB SI + if (dvb_ac3_desc) { + int len = 1 + + !!(dvb_ac3_desc->component_type_flag) + + !!(dvb_ac3_desc->bsid_flag) + + !!(dvb_ac3_desc->mainid_flag) + + !!(dvb_ac3_desc->asvc_flag); + + *q++ = len; + *q++ = dvb_ac3_desc->component_type_flag << 7 | dvb_ac3_desc->bsid_flag << 6 | + dvb_ac3_desc->mainid_flag << 5 | dvb_ac3_desc->asvc_flag << 4; + + if (dvb_ac3_desc->component_type_flag) *q++ = dvb_ac3_desc->component_type; + if (dvb_ac3_desc->bsid_flag) *q++ = dvb_ac3_desc->bsid; + if (dvb_ac3_desc->mainid_flag) *q++ = dvb_ac3_desc->mainid; + if (dvb_ac3_desc->asvc_flag) *q++ = dvb_ac3_desc->asvc; + } else { + *q++=1; // 1 byte, all flags sets to 0 + *q++=0; // omit all fields... + } + } else if (codec_id == AV_CODEC_ID_EAC3) { + *q++=0x7a; // EAC3 descriptor see A038 DVB SI + *q++=1; // 1 byte, all flags sets to 0 + *q++=0; // omit all fields... + } } - if (st->codecpar->codec_id==AV_CODEC_ID_S302M) + if (codec_id == AV_CODEC_ID_S302M) put_registration_descriptor(&q, MKTAG('B', 'S', 'S', 'D')); - if (st->codecpar->codec_id==AV_CODEC_ID_OPUS) { + if (codec_id == AV_CODEC_ID_OPUS) { /* 6 bytes registration descriptor, 4 bytes Opus audio descriptor */ if (q - data > SECTION_LENGTH - 6 - 4) { err = 1; @@ -487,7 +603,7 @@ char *next = lang->value; uint8_t *len_ptr; - *q++ = 0x0a; /* ISO 639 language descriptor */ + *q++ = ISO_639_LANGUAGE_DESCRIPTOR; len_ptr = q++; *len_ptr = 0; @@ -525,7 +641,7 @@ const char default_language[] = "und"; const char *language = lang && strlen(lang->value) >= 3 ? lang->value : default_language; - if (st->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE) { + if (codec_id == AV_CODEC_ID_DVB_SUBTITLE) { uint8_t *len_ptr; int extradata_copied = 0; @@ -567,7 +683,7 @@ } *len_ptr = q - len_ptr - 1; - } else if (st->codecpar->codec_id == AV_CODEC_ID_DVB_TELETEXT) { + } else if (codec_id == AV_CODEC_ID_DVB_TELETEXT) { uint8_t *len_ptr = NULL; int extradata_copied = 0; @@ -611,11 +727,11 @@ } break; case AVMEDIA_TYPE_DATA: - if (st->codecpar->codec_id == AV_CODEC_ID_SMPTE_KLV) { + if (codec_id == AV_CODEC_ID_SMPTE_KLV) { put_registration_descriptor(&q, MKTAG('K', 'L', 'V', 'A')); - } else if (st->codecpar->codec_id == AV_CODEC_ID_TIMED_ID3) { + } else if (codec_id == AV_CODEC_ID_TIMED_ID3) { const char *tag = "ID3 "; - *q++ = 0x26; /* metadata descriptor */ + *q++ = METADATA_DESCRIPTOR; *q++ = 13; put16(&q, 0xffff); /* metadata application format */ putbuf(&q, tag, strlen(tag)); @@ -651,7 +767,7 @@ int i, running_status, free_ca_mode, val; q = data; - put16(&q, ts->onid); + put16(&q, ts->original_network_id); *q++ = 0xff; for (i = 0; i < ts->nb_services; i++) { service = ts->services[i]; @@ -677,7 +793,7 @@ desc_list_len_ptr[0] = val >> 8; desc_list_len_ptr[1] = val; } - mpegts_write_section1(&ts->sdt, SDT_TID, ts->tsid, ts->tables_version, 0, 0, + mpegts_write_section1(&ts->sdt, SDT_TID, ts->transport_stream_id, ts->tables_version, 0, 0, data, q - data); } @@ -717,12 +833,50 @@ return 0; } +static int64_t get_pcr(const MpegTSWrite *ts) +{ + return av_rescale(ts->total_size + 11, 8 * PCR_TIME_BASE, ts->mux_rate) + + ts->first_pcr; +} + +static void write_packet(AVFormatContext *s, const uint8_t *packet) +{ + MpegTSWrite *ts = s->priv_data; + if (ts->m2ts_mode) { + int64_t pcr = get_pcr(s->priv_data); + uint32_t tp_extra_header = pcr % 0x3fffffff; + tp_extra_header = AV_RB32(&tp_extra_header); + avio_write(s->pb, (unsigned char *) &tp_extra_header, + sizeof(tp_extra_header)); + } + avio_write(s->pb, packet, TS_PACKET_SIZE); + ts->total_size += TS_PACKET_SIZE; +} + +static void section_write_packet(MpegTSSection *s, const uint8_t *packet) +{ + AVFormatContext *ctx = s->opaque; + write_packet(ctx, packet); +} + static MpegTSService *mpegts_add_service(AVFormatContext *s, int sid, - const char *provider_name, - const char *name) + const AVDictionary *metadata, + AVProgram *program) { MpegTSWrite *ts = s->priv_data; MpegTSService *service; + AVDictionaryEntry *title, *provider; + char default_service_name[32]; + const char *service_name; + const char *provider_name; + + title = av_dict_get(metadata, "service_name", NULL, 0); + if (!title) + title = av_dict_get(metadata, "title", NULL, 0); + snprintf(default_service_name, sizeof(default_service_name), "%s%02d", DEFAULT_SERVICE_NAME, ts->nb_services + 1); + service_name = title ? title->value : default_service_name; + provider = av_dict_get(metadata, "service_provider", NULL, 0); + provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; service = av_mallocz(sizeof(MpegTSService)); if (!service) @@ -731,103 +885,127 @@ service->sid = sid; service->pcr_pid = 0x1fff; if (encode_str8(service->provider_name, provider_name) < 0 || - encode_str8(service->name, name) < 0) { + encode_str8(service->name, service_name) < 0) { av_log(s, AV_LOG_ERROR, "Too long service or provider name\n"); goto fail; } if (av_dynarray_add_nofree(&ts->services, &ts->nb_services, service) < 0) goto fail; + service->pmt.write_packet = section_write_packet; + service->pmt.opaque = s; + service->pmt.cc = 15; + service->pmt.discontinuity= ts->flags & MPEGTS_FLAG_DISCONT; + service->program = program; + return service; fail: av_free(service); return NULL; } -static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb) -{ - return av_rescale(avio_tell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) + - ts->first_pcr; -} - -static void mpegts_prefix_m2ts_header(AVFormatContext *s) +static void enable_pcr_generation_for_stream(AVFormatContext *s, AVStream *pcr_st) { MpegTSWrite *ts = s->priv_data; - if (ts->m2ts_mode) { - int64_t pcr = get_pcr(s->priv_data, s->pb); - uint32_t tp_extra_header = pcr % 0x3fffffff; - tp_extra_header = AV_RB32(&tp_extra_header); - avio_write(s->pb, (unsigned char *) &tp_extra_header, - sizeof(tp_extra_header)); + MpegTSWriteStream *ts_st = pcr_st->priv_data; + + if (ts->mux_rate > 1 || ts->pcr_period_ms >= 0) { + int pcr_period_ms = ts->pcr_period_ms == -1 ? PCR_RETRANS_TIME : ts->pcr_period_ms; + ts_st->pcr_period = av_rescale(pcr_period_ms, PCR_TIME_BASE, 1000); + } else { + /* By default, for VBR we select the highest multiple of frame duration which is less than 100 ms. */ + int64_t frame_period = 0; + if (pcr_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + int frame_size = av_get_audio_frame_duration2(pcr_st->codecpar, 0); + if (!frame_size) { + av_log(s, AV_LOG_WARNING, "frame size not set\n"); + frame_size = 512; + } + frame_period = av_rescale_rnd(frame_size, PCR_TIME_BASE, pcr_st->codecpar->sample_rate, AV_ROUND_UP); + } else if (pcr_st->avg_frame_rate.num) { + frame_period = av_rescale_rnd(pcr_st->avg_frame_rate.den, PCR_TIME_BASE, pcr_st->avg_frame_rate.num, AV_ROUND_UP); + } + if (frame_period > 0 && frame_period <= PCR_TIME_BASE / 10) + ts_st->pcr_period = frame_period * (PCR_TIME_BASE / 10 / frame_period); + else + ts_st->pcr_period = 1; } + + // output a PCR as soon as possible + ts_st->last_pcr = ts->first_pcr - ts_st->pcr_period; } -static void section_write_packet(MpegTSSection *s, const uint8_t *packet) +static void select_pcr_streams(AVFormatContext *s) { - AVFormatContext *ctx = s->opaque; - mpegts_prefix_m2ts_header(ctx); - avio_write(ctx->pb, packet, TS_PACKET_SIZE); + MpegTSWrite *ts = s->priv_data; + + for (int i = 0; i < ts->nb_services; i++) { + MpegTSService *service = ts->services[i]; + AVStream *pcr_st = NULL; + AVProgram *program = service->program; + int nb_streams = program ? program->nb_stream_indexes : s->nb_streams; + + for (int j = 0; j < nb_streams; j++) { + AVStream *st = s->streams[program ? program->stream_index[j] : j]; + if (!pcr_st || + pcr_st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) + { + pcr_st = st; + } + } + + if (pcr_st) { + MpegTSWriteStream *ts_st = pcr_st->priv_data; + service->pcr_pid = ts_st->pid; + enable_pcr_generation_for_stream(s, pcr_st); + av_log(s, AV_LOG_VERBOSE, "service %i using PCR in pid=%i, pcr_period=%"PRId64"ms\n", + service->sid, service->pcr_pid, av_rescale(ts_st->pcr_period, 1000, PCR_TIME_BASE)); + } + } } static int mpegts_init(AVFormatContext *s) { MpegTSWrite *ts = s->priv_data; - MpegTSWriteStream *ts_st; - MpegTSService *service; - AVStream *st, *pcr_st = NULL; - AVDictionaryEntry *title, *provider; int i, j; - const char *service_name; - const char *provider_name; - int *pids; int ret; + if (ts->m2ts_mode == -1) { + if (av_match_ext(s->url, "m2ts")) { + ts->m2ts_mode = 1; + } else { + ts->m2ts_mode = 0; + } + } + + ts->m2ts_video_pid = M2TS_VIDEO_PID; + ts->m2ts_audio_pid = M2TS_AUDIO_START_PID; + ts->m2ts_pgssub_pid = M2TS_PGSSUB_START_PID; + ts->m2ts_textsub_pid = M2TS_TEXTSUB_PID; + + if (ts->m2ts_mode) { + ts->pmt_start_pid = M2TS_PMT_PID; + if (s->nb_programs > 1) { + av_log(s, AV_LOG_ERROR, "Only one program is allowed in m2ts mode!\n"); + return AVERROR(EINVAL); + } + } + if (s->max_delay < 0) /* Not set by the caller */ s->max_delay = 0; // round up to a whole number of TS packets ts->pes_payload_size = (ts->pes_payload_size + 14 + 183) / 184 * 184 - 14; - ts->tsid = ts->transport_stream_id; - ts->onid = ts->original_network_id; if (!s->nb_programs) { /* allocate a single DVB service */ - title = av_dict_get(s->metadata, "service_name", NULL, 0); - if (!title) - title = av_dict_get(s->metadata, "title", NULL, 0); - service_name = title ? title->value : DEFAULT_SERVICE_NAME; - provider = av_dict_get(s->metadata, "service_provider", NULL, 0); - provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; - service = mpegts_add_service(s, ts->service_id, - provider_name, service_name); - - if (!service) + if (!mpegts_add_service(s, ts->service_id, s->metadata, NULL)) return AVERROR(ENOMEM); - - service->pmt.write_packet = section_write_packet; - service->pmt.opaque = s; - service->pmt.cc = 15; - service->pmt.discontinuity= ts->flags & MPEGTS_FLAG_DISCONT; } else { for (i = 0; i < s->nb_programs; i++) { AVProgram *program = s->programs[i]; - title = av_dict_get(program->metadata, "service_name", NULL, 0); - if (!title) - title = av_dict_get(program->metadata, "title", NULL, 0); - service_name = title ? title->value : DEFAULT_SERVICE_NAME; - provider = av_dict_get(program->metadata, "service_provider", NULL, 0); - provider_name = provider ? provider->value : DEFAULT_PROVIDER_NAME; - service = mpegts_add_service(s, program->id, - provider_name, service_name); - - if (!service) + if (!mpegts_add_service(s, program->id, program->metadata, program)) return AVERROR(ENOMEM); - - service->pmt.write_packet = section_write_packet; - service->pmt.opaque = s; - service->pmt.cc = 15; - service->pmt.discontinuity= ts->flags & MPEGTS_FLAG_DISCONT; - service->program = program; } } @@ -845,217 +1023,161 @@ ts->sdt.write_packet = section_write_packet; ts->sdt.opaque = s; - pids = av_malloc_array(s->nb_streams, sizeof(*pids)); - if (!pids) { - ret = AVERROR(ENOMEM); - goto fail; - } + ts->pkt = av_packet_alloc(); + if (!ts->pkt) + return AVERROR(ENOMEM); /* assign pids to each stream */ for (i = 0; i < s->nb_streams; i++) { - AVProgram *program; - st = s->streams[i]; + AVStream *st = s->streams[i]; + MpegTSWriteStream *ts_st; ts_st = av_mallocz(sizeof(MpegTSWriteStream)); if (!ts_st) { - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } st->priv_data = ts_st; - ts_st->user_tb = st->time_base; avpriv_set_pts_info(st, 33, 1, 90000); ts_st->payload = av_mallocz(ts->pes_payload_size); if (!ts_st->payload) { - ret = AVERROR(ENOMEM); - goto fail; - } - - program = av_find_program_from_stream(s, NULL, i); - if (program) { - for (j = 0; j < ts->nb_services; j++) { - if (ts->services[j]->program == program) { - service = ts->services[j]; - break; - } - } + return AVERROR(ENOMEM); } - ts_st->service = service; /* MPEG pid values < 16 are reserved. Applications which set st->id in * this range are assigned a calculated pid. */ if (st->id < 16) { - ts_st->pid = ts->start_pid + i; - } else if (st->id < 0x1FFF) { - ts_st->pid = st->id; + if (ts->m2ts_mode) { + switch (st->codecpar->codec_type) { + case AVMEDIA_TYPE_VIDEO: + ts_st->pid = ts->m2ts_video_pid++; + break; + case AVMEDIA_TYPE_AUDIO: + ts_st->pid = ts->m2ts_audio_pid++; + break; + case AVMEDIA_TYPE_SUBTITLE: + switch (st->codecpar->codec_id) { + case AV_CODEC_ID_HDMV_PGS_SUBTITLE: + ts_st->pid = ts->m2ts_pgssub_pid++; + break; + case AV_CODEC_ID_HDMV_TEXT_SUBTITLE: + ts_st->pid = ts->m2ts_textsub_pid++; + break; + } + break; + } + if (ts->m2ts_video_pid > M2TS_VIDEO_PID + 1 || + ts->m2ts_audio_pid > M2TS_AUDIO_START_PID + 32 || + ts->m2ts_pgssub_pid > M2TS_PGSSUB_START_PID + 32 || + ts->m2ts_textsub_pid > M2TS_TEXTSUB_PID + 1 || + ts_st->pid < 16) { + av_log(s, AV_LOG_ERROR, "Cannot automatically assign PID for stream %d\n", st->index); + return AVERROR(EINVAL); + } + } else { + ts_st->pid = ts->start_pid + i; + } } else { + ts_st->pid = st->id; + } + if (ts_st->pid >= 0x1FFF) { av_log(s, AV_LOG_ERROR, "Invalid stream id %d, must be less than 8191\n", st->id); - ret = AVERROR(EINVAL); - goto fail; + return AVERROR(EINVAL); } - if (ts_st->pid == service->pmt.pid) { - av_log(s, AV_LOG_ERROR, "Duplicate stream id %d\n", ts_st->pid); - ret = AVERROR(EINVAL); - goto fail; + for (j = 0; j < ts->nb_services; j++) { + if (ts->services[j]->pmt.pid > LAST_OTHER_PID) { + av_log(s, AV_LOG_ERROR, + "Invalid PMT PID %d, must be less than %d\n", ts->services[j]->pmt.pid, LAST_OTHER_PID + 1); + return AVERROR(EINVAL); + } + if (ts_st->pid == ts->services[j]->pmt.pid) { + av_log(s, AV_LOG_ERROR, "PID %d cannot be both elementary and PMT PID\n", ts_st->pid); + return AVERROR(EINVAL); + } } for (j = 0; j < i; j++) { - if (pids[j] == ts_st->pid) { + MpegTSWriteStream *ts_st_prev = s->streams[j]->priv_data; + if (ts_st_prev->pid == ts_st->pid) { av_log(s, AV_LOG_ERROR, "Duplicate stream id %d\n", ts_st->pid); - ret = AVERROR(EINVAL); - goto fail; + return AVERROR(EINVAL); } } - pids[i] = ts_st->pid; ts_st->payload_pts = AV_NOPTS_VALUE; ts_st->payload_dts = AV_NOPTS_VALUE; - ts_st->first_pts_check = 1; ts_st->cc = 15; ts_st->discontinuity = ts->flags & MPEGTS_FLAG_DISCONT; - /* update PCR pid by using the first video stream */ - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && - service->pcr_pid == 0x1fff) { - service->pcr_pid = ts_st->pid; - pcr_st = st; - } if (st->codecpar->codec_id == AV_CODEC_ID_AAC && st->codecpar->extradata_size > 0) { AVStream *ast; ts_st->amux = avformat_alloc_context(); if (!ts_st->amux) { - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } ts_st->amux->oformat = av_guess_format((ts->flags & MPEGTS_FLAG_AAC_LATM) ? "latm" : "adts", NULL, NULL); if (!ts_st->amux->oformat) { - ret = AVERROR(EINVAL); - goto fail; + return AVERROR(EINVAL); } if (!(ast = avformat_new_stream(ts_st->amux, NULL))) { - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } ret = avcodec_parameters_copy(ast->codecpar, st->codecpar); if (ret != 0) - goto fail; + return ret; ast->time_base = st->time_base; ret = avformat_write_header(ts_st->amux, NULL); if (ret < 0) - goto fail; + return ret; } if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) { ts_st->opus_pending_trim_start = st->codecpar->initial_padding * 48000 / st->codecpar->sample_rate; } } - av_freep(&pids); + if (ts->copyts < 1) + ts->first_pcr = av_rescale(s->max_delay, PCR_TIME_BASE, AV_TIME_BASE); - /* if no video stream, use the first stream as PCR */ - if (service->pcr_pid == 0x1fff && s->nb_streams > 0) { - pcr_st = s->streams[0]; - ts_st = pcr_st->priv_data; - service->pcr_pid = ts_st->pid; - } else - ts_st = pcr_st->priv_data; - - if (ts->mux_rate > 1) { - service->pcr_packet_period = (int64_t)ts->mux_rate * ts->pcr_period / - (TS_PACKET_SIZE * 8 * 1000); - ts->sdt_packet_period = (int64_t)ts->mux_rate * SDT_RETRANS_TIME / - (TS_PACKET_SIZE * 8 * 1000); - ts->pat_packet_period = (int64_t)ts->mux_rate * PAT_RETRANS_TIME / - (TS_PACKET_SIZE * 8 * 1000); - - if (ts->copyts < 1) - ts->first_pcr = av_rescale(s->max_delay, PCR_TIME_BASE, AV_TIME_BASE); - } else { - /* Arbitrary values, PAT/PMT will also be written on video key frames */ - ts->sdt_packet_period = 200; - ts->pat_packet_period = 40; - if (pcr_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - int frame_size = av_get_audio_frame_duration2(pcr_st->codecpar, 0); - if (!frame_size) { - av_log(s, AV_LOG_WARNING, "frame size not set\n"); - service->pcr_packet_period = - pcr_st->codecpar->sample_rate / (10 * 512); - } else { - service->pcr_packet_period = - pcr_st->codecpar->sample_rate / (10 * frame_size); - } - } else { - // max delta PCR 0.1s - // TODO: should be avg_frame_rate - service->pcr_packet_period = - ts_st->user_tb.den / (10 * ts_st->user_tb.num); - } - if (!service->pcr_packet_period) - service->pcr_packet_period = 1; - } + select_pcr_streams(s); ts->last_pat_ts = AV_NOPTS_VALUE; ts->last_sdt_ts = AV_NOPTS_VALUE; - // The user specified a period, use only it - if (ts->pat_period < INT_MAX/2) { - ts->pat_packet_period = INT_MAX; - } - if (ts->sdt_period < INT_MAX/2) { - ts->sdt_packet_period = INT_MAX; - } - - // output a PCR as soon as possible - service->pcr_packet_count = service->pcr_packet_period; - ts->pat_packet_count = ts->pat_packet_period - 1; - ts->sdt_packet_count = ts->sdt_packet_period - 1; + ts->pat_period = av_rescale(ts->pat_period_us, PCR_TIME_BASE, AV_TIME_BASE); + ts->sdt_period = av_rescale(ts->sdt_period_us, PCR_TIME_BASE, AV_TIME_BASE); if (ts->mux_rate == 1) av_log(s, AV_LOG_VERBOSE, "muxrate VBR, "); else av_log(s, AV_LOG_VERBOSE, "muxrate %d, ", ts->mux_rate); av_log(s, AV_LOG_VERBOSE, - "pcr every %d pkts, sdt every %d, pat/pmt every %d pkts\n", - service->pcr_packet_period, - ts->sdt_packet_period, ts->pat_packet_period); - - if (ts->m2ts_mode == -1) { - if (av_match_ext(s->url, "m2ts")) { - ts->m2ts_mode = 1; - } else { - ts->m2ts_mode = 0; - } - } + "sdt every %"PRId64" ms, pat/pmt every %"PRId64" ms\n", + av_rescale(ts->sdt_period, 1000, PCR_TIME_BASE), + av_rescale(ts->pat_period, 1000, PCR_TIME_BASE)); return 0; - -fail: - av_freep(&pids); - return ret; } /* send SDT, PAT and PMT tables regularly */ -static void retransmit_si_info(AVFormatContext *s, int force_pat, int64_t dts) +static void retransmit_si_info(AVFormatContext *s, int force_pat, int force_sdt, int64_t pcr) { MpegTSWrite *ts = s->priv_data; int i; - if (++ts->sdt_packet_count == ts->sdt_packet_period || - (dts != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) || - (dts != AV_NOPTS_VALUE && dts - ts->last_sdt_ts >= ts->sdt_period*90000.0) + if ((pcr != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) || + (pcr != AV_NOPTS_VALUE && pcr - ts->last_sdt_ts >= ts->sdt_period) || + force_sdt ) { - ts->sdt_packet_count = 0; - if (dts != AV_NOPTS_VALUE) - ts->last_sdt_ts = FFMAX(dts, ts->last_sdt_ts); + if (pcr != AV_NOPTS_VALUE) + ts->last_sdt_ts = FFMAX(pcr, ts->last_sdt_ts); mpegts_write_sdt(s); } - if (++ts->pat_packet_count == ts->pat_packet_period || - (dts != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) || - (dts != AV_NOPTS_VALUE && dts - ts->last_pat_ts >= ts->pat_period*90000.0) || + if ((pcr != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) || + (pcr != AV_NOPTS_VALUE && pcr - ts->last_pat_ts >= ts->pat_period) || force_pat) { - ts->pat_packet_count = 0; - if (dts != AV_NOPTS_VALUE) - ts->last_pat_ts = FFMAX(dts, ts->last_pat_ts); + if (pcr != AV_NOPTS_VALUE) + ts->last_pat_ts = FFMAX(pcr, ts->last_pat_ts); mpegts_write_pat(s); for (i = 0; i < ts->nb_services; i++) mpegts_write_pmt(s, ts->services[i]); @@ -1088,8 +1210,7 @@ *q++ = 0xff; *q++ = 0x10; memset(q, 0x0FF, TS_PACKET_SIZE - (q - buf)); - mpegts_prefix_m2ts_header(s); - avio_write(s->pb, buf, TS_PACKET_SIZE); + write_packet(s, buf); } /* Write a single transport stream packet with a PCR and no payload */ @@ -1114,12 +1235,11 @@ } /* PCR coded into 6 bytes */ - q += write_pcr_bits(q, get_pcr(ts, s->pb)); + q += write_pcr_bits(q, get_pcr(ts)); /* stuffing bytes */ memset(q, 0xFF, TS_PACKET_SIZE - (q - buf)); - mpegts_prefix_m2ts_header(s); - avio_write(s->pb, buf, TS_PACKET_SIZE); + write_packet(s, buf); } static void write_pts(uint8_t *q, int fourbits, int64_t pts) @@ -1183,46 +1303,82 @@ uint8_t *q; int val, is_start, len, header_len, write_pcr, is_dvb_subtitle, is_dvb_teletext, flags; int afc_len, stuffing_len; - int64_t pcr = -1; /* avoid warning */ int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE); int force_pat = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key; + int force_sdt = 0; av_assert0(ts_st->payload != buf || st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO); if (ts->flags & MPEGTS_FLAG_PAT_PMT_AT_FRAMES && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { force_pat = 1; } + if (ts->flags & MPEGTS_FLAG_REEMIT_PAT_PMT) { + force_pat = 1; + force_sdt = 1; + ts->flags &= ~MPEGTS_FLAG_REEMIT_PAT_PMT; + } + is_start = 1; while (payload_size > 0) { - retransmit_si_info(s, force_pat, dts); + int64_t pcr = AV_NOPTS_VALUE; + if (ts->mux_rate > 1) + pcr = get_pcr(ts); + else if (dts != AV_NOPTS_VALUE) + pcr = (dts - delay) * 300; + + retransmit_si_info(s, force_pat, force_sdt, pcr); force_pat = 0; + force_sdt = 0; write_pcr = 0; - if (ts_st->pid == ts_st->service->pcr_pid) { - if (ts->mux_rate > 1 || is_start) // VBR pcr period is based on frames - ts_st->service->pcr_packet_count++; - if (ts_st->service->pcr_packet_count >= - ts_st->service->pcr_packet_period) { - ts_st->service->pcr_packet_count = 0; + if (ts->mux_rate > 1) { + /* Send PCR packets for all PCR streams if needed */ + pcr = get_pcr(ts); + if (pcr >= ts->next_pcr) { + int64_t next_pcr = INT64_MAX; + for (int i = 0; i < s->nb_streams; i++) { + /* Make the current stream the last, because for that we + * can insert the pcr into the payload later */ + int st2_index = i < st->index ? i : (i + 1 == s->nb_streams ? st->index : i + 1); + AVStream *st2 = s->streams[st2_index]; + MpegTSWriteStream *ts_st2 = st2->priv_data; + if (ts_st2->pcr_period) { + if (pcr - ts_st2->last_pcr >= ts_st2->pcr_period) { + ts_st2->last_pcr = FFMAX(pcr - ts_st2->pcr_period, ts_st2->last_pcr + ts_st2->pcr_period); + if (st2 != st) { + mpegts_insert_pcr_only(s, st2); + pcr = get_pcr(ts); + } else { + write_pcr = 1; + } + } + next_pcr = FFMIN(next_pcr, ts_st2->last_pcr + ts_st2->pcr_period); + } + } + ts->next_pcr = next_pcr; + } + if (dts != AV_NOPTS_VALUE && (dts - pcr / 300) > delay) { + /* pcr insert gets priority over null packet insert */ + if (write_pcr) + mpegts_insert_pcr_only(s, st); + else + mpegts_insert_null_packet(s); + /* recalculate write_pcr and possibly retransmit si_info */ + continue; + } + } else if (ts_st->pcr_period && pcr != AV_NOPTS_VALUE) { + if (pcr - ts_st->last_pcr >= ts_st->pcr_period && is_start) { + ts_st->last_pcr = FFMAX(pcr - ts_st->pcr_period, ts_st->last_pcr + ts_st->pcr_period); write_pcr = 1; } } - if (ts->mux_rate > 1 && dts != AV_NOPTS_VALUE && - (dts - get_pcr(ts, s->pb) / 300) > delay) { - /* pcr insert gets priority over null packet insert */ - if (write_pcr) - mpegts_insert_pcr_only(s, st); - else - mpegts_insert_null_packet(s); - /* recalculate write_pcr and possibly retransmit si_info */ - continue; - } - /* prepare packet header */ q = buf; *q++ = 0x47; val = ts_st->pid >> 8; + if (ts->m2ts_mode && st->codecpar->codec_id == AV_CODEC_ID_AC3) + val |= 0x20; if (is_start) val |= 0x40; *q++ = val; @@ -1236,7 +1392,7 @@ } if (key && is_start && pts != AV_NOPTS_VALUE) { // set Random Access for key frames - if (ts_st->pid == ts_st->service->pcr_pid) + if (ts_st->pcr_period) write_pcr = 1; set_af_flag(buf, 0x40); q = get_ts_payload_start(buf); @@ -1245,10 +1401,6 @@ set_af_flag(buf, 0x10); q = get_ts_payload_start(buf); // add 11, pcr references the last byte of program clock reference base - if (ts->mux_rate > 1) - pcr = get_pcr(ts, s->pb); - else - pcr = (dts - delay) * 300; if (dts != AV_NOPTS_VALUE && dts < pcr / 300) av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n"); extend_af(buf, write_pcr_bits(q, pcr)); @@ -1265,28 +1417,28 @@ is_dvb_teletext = 0; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (st->codecpar->codec_id == AV_CODEC_ID_DIRAC) - *q++ = 0xfd; + *q++ = STREAM_ID_EXTENDED_STREAM_ID; else - *q++ = 0xe0; + *q++ = STREAM_ID_VIDEO_STREAM_0; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && (st->codecpar->codec_id == AV_CODEC_ID_MP2 || st->codecpar->codec_id == AV_CODEC_ID_MP3 || st->codecpar->codec_id == AV_CODEC_ID_AAC)) { - *q++ = 0xc0; + *q++ = STREAM_ID_AUDIO_STREAM_0; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id == AV_CODEC_ID_AC3 && ts->m2ts_mode) { - *q++ = 0xfd; + *q++ = STREAM_ID_EXTENDED_STREAM_ID; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA && st->codecpar->codec_id == AV_CODEC_ID_TIMED_ID3) { - *q++ = 0xbd; + *q++ = STREAM_ID_PRIVATE_STREAM_1; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { - *q++ = stream_id != -1 ? stream_id : 0xfc; + *q++ = stream_id != -1 ? stream_id : STREAM_ID_METADATA_STREAM; - if (stream_id == 0xbd) /* asynchronous KLV */ + if (stream_id == STREAM_ID_PRIVATE_STREAM_1) /* asynchronous KLV */ pts = dts = AV_NOPTS_VALUE; } else { - *q++ = 0xbd; + *q++ = STREAM_ID_PRIVATE_STREAM_1; if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { if (st->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE) { is_dvb_subtitle = 1; @@ -1322,10 +1474,10 @@ if (ts->m2ts_mode && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id == AV_CODEC_ID_AC3) { - /* set PES_extension_flag */ - pes_extension = 1; - flags |= 0x01; - header_len += 3; + /* set PES_extension_flag */ + pes_extension = 1; + flags |= 0x01; + header_len += 3; } if (is_dvb_teletext) { pes_header_stuffing_bytes = 0x24 - header_len; @@ -1368,14 +1520,14 @@ *q++ = 0x00 | 0x60; } /* For Blu-ray AC3 Audio Setting extended flags */ - if (ts->m2ts_mode && - pes_extension && - st->codecpar->codec_id == AV_CODEC_ID_AC3) { - flags = 0x01; /* set PES_extension_flag_2 */ - *q++ = flags; - *q++ = 0x80 | 0x01; /* marker bit + extension length */ - *q++ = 0x00 | 0x71; /* for AC3 Audio (specifically on blue-rays) */ - } + if (ts->m2ts_mode && + pes_extension && + st->codecpar->codec_id == AV_CODEC_ID_AC3) { + flags = 0x01; /* set PES_extension_flag_2 */ + *q++ = flags; + *q++ = 0x80 | 0x01; /* marker bit + extension length */ + *q++ = 0x00 | 0x71; /* for AC3 Audio (specifically on blue-rays) */ + } if (is_dvb_subtitle) { @@ -1429,8 +1581,7 @@ payload += len; payload_size -= len; - mpegts_prefix_m2ts_header(s); - avio_write(s->pb, buf, TS_PACKET_SIZE); + write_packet(s, buf); } ts_st->prev_payload_key = key; } @@ -1528,9 +1679,10 @@ MpegTSWrite *ts = s->priv_data; MpegTSWriteStream *ts_st = st->priv_data; const int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) * 2; + const int64_t max_audio_delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) / 2; int64_t dts = pkt->dts, pts = pkt->pts; int opus_samples = 0; - int side_data_size; + buffer_size_t side_data_size; uint8_t *side_data = NULL; int stream_id = -1; @@ -1540,31 +1692,23 @@ if (side_data) stream_id = side_data[0]; - if (ts->reemit_pat_pmt) { - av_log(s, AV_LOG_WARNING, - "resend_headers option is deprecated, use -mpegts_flags resend_headers\n"); - ts->reemit_pat_pmt = 0; - ts->flags |= MPEGTS_FLAG_REEMIT_PAT_PMT; - } - - if (ts->flags & MPEGTS_FLAG_REEMIT_PAT_PMT) { - ts->pat_packet_count = ts->pat_packet_period - 1; - ts->sdt_packet_count = ts->sdt_packet_period - 1; - ts->flags &= ~MPEGTS_FLAG_REEMIT_PAT_PMT; - } - if (ts->copyts < 1) { + if (!ts->first_dts_checked && dts != AV_NOPTS_VALUE) { + ts->first_pcr += dts * 300; + ts->first_dts_checked = 1; + } + if (pts != AV_NOPTS_VALUE) pts += delay; if (dts != AV_NOPTS_VALUE) dts += delay; } - if (ts_st->first_pts_check && pts == AV_NOPTS_VALUE) { - av_log(s, AV_LOG_ERROR, "first pts value must be set\n"); + if (!ts_st->first_timestamp_checked && (pts == AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE)) { + av_log(s, AV_LOG_ERROR, "first pts and dts value must be set\n"); return AVERROR_INVALIDDATA; } - ts_st->first_pts_check = 0; + ts_st->first_timestamp_checked = 1; if (st->codecpar->codec_id == AV_CODEC_ID_H264) { const uint8_t *p = buf, *buf_end = p + size; @@ -1606,30 +1750,30 @@ } if ((AV_RB16(pkt->data) & 0xfff0) != 0xfff0) { int ret; - AVPacket pkt2; + AVPacket *pkt2 = ts->pkt; if (!ts_st->amux) { av_log(s, AV_LOG_ERROR, "AAC bitstream not in ADTS format " "and extradata missing\n"); } else { - av_init_packet(&pkt2); - pkt2.data = pkt->data; - pkt2.size = pkt->size; - av_assert0(pkt->dts != AV_NOPTS_VALUE); - pkt2.dts = av_rescale_q(pkt->dts, st->time_base, ts_st->amux->streams[0]->time_base); - - ret = avio_open_dyn_buf(&ts_st->amux->pb); - if (ret < 0) - return AVERROR(ENOMEM); - - ret = av_write_frame(ts_st->amux, &pkt2); - if (ret < 0) { - ffio_free_dyn_buf(&ts_st->amux->pb); - return ret; - } - size = avio_close_dyn_buf(ts_st->amux->pb, &data); - ts_st->amux->pb = NULL; - buf = data; + av_packet_unref(pkt2); + pkt2->data = pkt->data; + pkt2->size = pkt->size; + av_assert0(pkt->dts != AV_NOPTS_VALUE); + pkt2->dts = av_rescale_q(pkt->dts, st->time_base, ts_st->amux->streams[0]->time_base); + + ret = avio_open_dyn_buf(&ts_st->amux->pb); + if (ret < 0) + return ret; + + ret = av_write_frame(ts_st->amux, pkt2); + if (ret < 0) { + ffio_free_dyn_buf(&ts_st->amux->pb); + return ret; + } + size = avio_close_dyn_buf(ts_st->amux->pb, &data); + ts_st->amux->pb = NULL; + buf = data; } } } else if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) { @@ -1651,7 +1795,7 @@ } while (p < buf_end && (state & 0x7e) != 2*35 && (state & 0x7e) >= 2*32); - if ((state & 0x7e) < 2*16 && (state & 0x7e) >= 2*24) + if ((state & 0x7e) < 2*16 || (state & 0x7e) >= 2*24) extradd = 0; if ((state & 0x7e) != 2*35) { // AUD NAL data = av_malloc(pkt->size + 7 + extradd); @@ -1675,7 +1819,7 @@ /* Add Opus control header */ if ((AV_RB16(pkt->data) >> 5) != 0x3ff) { uint8_t *side_data; - int side_data_size; + buffer_size_t side_data_size; int i, n; int ctrl_header_size; int trim_start = 0, trim_end = 0; @@ -1737,27 +1881,68 @@ * need to count the samples of that too! */ av_log(s, AV_LOG_WARNING, "Got MPEG-TS formatted Opus data, unhandled"); } - } + } else if (st->codecpar->codec_id == AV_CODEC_ID_AC3 && !ts_st->dvb_ac3_desc) { + AC3HeaderInfo *hdr = NULL; - if (pkt->dts != AV_NOPTS_VALUE) { - int i; - for(i=0; inb_streams; i++) { - AVStream *st2 = s->streams[i]; - MpegTSWriteStream *ts_st2 = st2->priv_data; - if ( ts_st2->payload_size - && (ts_st2->payload_dts == AV_NOPTS_VALUE || dts - ts_st2->payload_dts > delay/2)) { - mpegts_write_pes(s, st2, ts_st2->payload, ts_st2->payload_size, - ts_st2->payload_pts, ts_st2->payload_dts, - ts_st2->payload_flags & AV_PKT_FLAG_KEY, stream_id); - ts_st2->payload_size = 0; + if (avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size) >= 0) { + uint8_t number_of_channels_flag; + uint8_t service_type_flag; + uint8_t full_service_flag = 1; + DVBAC3Descriptor *dvb_ac3_desc; + + dvb_ac3_desc = av_mallocz(sizeof(*dvb_ac3_desc)); + if (!dvb_ac3_desc) { + av_free(hdr); + return AVERROR(ENOMEM); } + + service_type_flag = hdr->bitstream_mode; + switch (hdr->channel_mode) { + case AC3_CHMODE_DUALMONO: + number_of_channels_flag = 1; + break; + case AC3_CHMODE_MONO: + number_of_channels_flag = 0; + break; + case AC3_CHMODE_STEREO: + if (hdr->dolby_surround_mode == AC3_DSURMOD_ON) + number_of_channels_flag = 3; + else + number_of_channels_flag = 2; + break; + case AC3_CHMODE_3F: + case AC3_CHMODE_2F1R: + case AC3_CHMODE_3F1R: + case AC3_CHMODE_2F2R: + case AC3_CHMODE_3F2R: + number_of_channels_flag = 4; + break; + default: /* reserved */ + number_of_channels_flag = 7; + break; + } + + if (service_type_flag == 1 || service_type_flag == 4 || + (service_type_flag == 7 && !number_of_channels_flag)) + full_service_flag = 0; + + dvb_ac3_desc->component_type_flag = 1; + dvb_ac3_desc->component_type = (full_service_flag << 6) | + ((service_type_flag & 0x7) << 3) | + (number_of_channels_flag & 0x7); + dvb_ac3_desc->bsid_flag = 1; + dvb_ac3_desc->bsid = hdr->bitstream_id; + dvb_ac3_desc->mainid_flag = 0; + dvb_ac3_desc->asvc_flag = 0; + + ts_st->dvb_ac3_desc = dvb_ac3_desc; } + av_free(hdr); } if (ts_st->payload_size && (ts_st->payload_size + size > ts->pes_payload_size || (dts != AV_NOPTS_VALUE && ts_st->payload_dts != AV_NOPTS_VALUE && - av_compare_ts(dts - ts_st->payload_dts, st->time_base, - s->max_delay, AV_TIME_BASE_Q) >= 0) || + dts - ts_st->payload_dts >= max_audio_delay) || ts_st->opus_queued_samples + opus_samples >= 5760 /* 120ms */)) { mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_size, ts_st->payload_pts, ts_st->payload_dts, @@ -1793,6 +1978,7 @@ static void mpegts_write_flush(AVFormatContext *s) { + MpegTSWrite *ts = s->priv_data; int i; /* flush current packets */ @@ -1807,6 +1993,12 @@ ts_st->opus_queued_samples = 0; } } + + if (ts->m2ts_mode) { + int packets = (avio_tell(s->pb) / (TS_PACKET_SIZE + 4)) % 32; + while (packets++ < 32) + mpegts_insert_null_packet(s); + } } static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) @@ -1833,10 +2025,13 @@ 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; if (ts_st) { + av_freep(&ts_st->dvb_ac3_desc); av_freep(&ts_st->payload); if (ts_st->amux) { avformat_free_context(ts_st->amux); @@ -1874,98 +2069,62 @@ return ret; } +#define OFFSET(x) offsetof(MpegTSWrite, x) +#define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "mpegts_transport_stream_id", "Set transport_stream_id field.", - offsetof(MpegTSWrite, transport_stream_id), AV_OPT_TYPE_INT, - { .i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, + OFFSET(transport_stream_id), AV_OPT_TYPE_INT, { .i64 = 0x0001 }, 0x0001, 0xffff, ENC }, { "mpegts_original_network_id", "Set original_network_id field.", - offsetof(MpegTSWrite, original_network_id), AV_OPT_TYPE_INT, - { .i64 = DVB_PRIVATE_NETWORK_START }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, + OFFSET(original_network_id), AV_OPT_TYPE_INT, { .i64 = DVB_PRIVATE_NETWORK_START }, 0x0001, 0xffff, ENC }, { "mpegts_service_id", "Set service_id field.", - offsetof(MpegTSWrite, service_id), AV_OPT_TYPE_INT, - { .i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM }, + OFFSET(service_id), AV_OPT_TYPE_INT, { .i64 = 0x0001 }, 0x0001, 0xffff, ENC }, { "mpegts_service_type", "Set service_type field.", - offsetof(MpegTSWrite, service_type), AV_OPT_TYPE_INT, - { .i64 = 0x01 }, 0x01, 0xff, AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + OFFSET(service_type), AV_OPT_TYPE_INT, { .i64 = 0x01 }, 0x01, 0xff, ENC, "mpegts_service_type" }, { "digital_tv", "Digital Television.", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_DIGITAL_TV }, 0x01, 0xff, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_DIGITAL_TV }, 0x01, 0xff, ENC, "mpegts_service_type" }, { "digital_radio", "Digital Radio.", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_DIGITAL_RADIO }, 0x01, 0xff, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_DIGITAL_RADIO }, 0x01, 0xff, ENC, "mpegts_service_type" }, { "teletext", "Teletext.", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_TELETEXT }, 0x01, 0xff, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_TELETEXT }, 0x01, 0xff, ENC, "mpegts_service_type" }, { "advanced_codec_digital_radio", "Advanced Codec Digital Radio.", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_RADIO }, 0x01, 0xff, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_RADIO }, 0x01, 0xff, ENC, "mpegts_service_type" }, { "mpeg2_digital_hdtv", "MPEG2 Digital HDTV.", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_MPEG2_DIGITAL_HDTV }, 0x01, 0xff, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_MPEG2_DIGITAL_HDTV }, 0x01, 0xff, ENC, "mpegts_service_type" }, { "advanced_codec_digital_sdtv", "Advanced Codec Digital SDTV.", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_SDTV }, 0x01, 0xff, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_SDTV }, 0x01, 0xff, ENC, "mpegts_service_type" }, { "advanced_codec_digital_hdtv", "Advanced Codec Digital HDTV.", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_HDTV }, 0x01, 0xff, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_HDTV }, 0x01, 0xff, ENC, "mpegts_service_type" }, { "hevc_digital_hdtv", "HEVC Digital Television Service.", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_HEVC_DIGITAL_HDTV }, 0x01, 0xff, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_HEVC_DIGITAL_HDTV }, 0x01, 0xff, ENC, "mpegts_service_type" }, { "mpegts_pmt_start_pid", "Set the first pid of the PMT.", - offsetof(MpegTSWrite, pmt_start_pid), AV_OPT_TYPE_INT, - { .i64 = 0x1000 }, 0x0010, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM }, + OFFSET(pmt_start_pid), AV_OPT_TYPE_INT, { .i64 = 0x1000 }, FIRST_OTHER_PID, LAST_OTHER_PID, ENC }, { "mpegts_start_pid", "Set the first pid.", - offsetof(MpegTSWrite, start_pid), AV_OPT_TYPE_INT, - { .i64 = 0x0100 }, 0x0010, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM }, - { "mpegts_m2ts_mode", "Enable m2ts mode.", - offsetof(MpegTSWrite, m2ts_mode), AV_OPT_TYPE_BOOL, - { .i64 = -1 }, -1, 1, AV_OPT_FLAG_ENCODING_PARAM }, - { "muxrate", NULL, - offsetof(MpegTSWrite, mux_rate), AV_OPT_TYPE_INT, - { .i64 = 1 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, + OFFSET(start_pid), AV_OPT_TYPE_INT, { .i64 = 0x0100 }, FIRST_OTHER_PID, LAST_OTHER_PID, ENC }, + { "mpegts_m2ts_mode", "Enable m2ts mode.", OFFSET(m2ts_mode), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, ENC }, + { "muxrate", NULL, OFFSET(mux_rate), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, ENC }, { "pes_payload_size", "Minimum PES packet payload in bytes", - offsetof(MpegTSWrite, pes_payload_size), AV_OPT_TYPE_INT, - { .i64 = DEFAULT_PES_PAYLOAD_SIZE }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, - { "mpegts_flags", "MPEG-TS muxing flags", - offsetof(MpegTSWrite, flags), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, 0, INT_MAX, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + OFFSET(pes_payload_size), AV_OPT_TYPE_INT, { .i64 = DEFAULT_PES_PAYLOAD_SIZE }, 0, INT_MAX, ENC }, + { "mpegts_flags", "MPEG-TS muxing flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, 0, INT_MAX, ENC, "mpegts_flags" }, { "resend_headers", "Reemit PAT/PMT before writing the next packet", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_REEMIT_PAT_PMT }, 0, INT_MAX, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_REEMIT_PAT_PMT }, 0, INT_MAX, ENC, "mpegts_flags" }, { "latm", "Use LATM packetization for AAC", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_AAC_LATM }, 0, INT_MAX, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_AAC_LATM }, 0, INT_MAX, ENC, "mpegts_flags" }, { "pat_pmt_at_frames", "Reemit PAT and PMT at each video frame", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_PAT_PMT_AT_FRAMES}, 0, INT_MAX, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_PAT_PMT_AT_FRAMES}, 0, INT_MAX, ENC, "mpegts_flags" }, { "system_b", "Conform to System B (DVB) instead of System A (ATSC)", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_SYSTEM_B }, 0, INT_MAX, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_SYSTEM_B }, 0, INT_MAX, ENC, "mpegts_flags" }, { "initial_discontinuity", "Mark initial packets as discontinuous", - 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_DISCONT }, 0, INT_MAX, - AV_OPT_FLAG_ENCODING_PARAM, "mpegts_flags" }, - // backward compatibility - { "resend_headers", "Reemit PAT/PMT before writing the next packet", - offsetof(MpegTSWrite, reemit_pat_pmt), AV_OPT_TYPE_INT, - { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, - { "mpegts_copyts", "don't offset dts/pts", - offsetof(MpegTSWrite, copyts), AV_OPT_TYPE_BOOL, - { .i64 = -1 }, -1, 1, AV_OPT_FLAG_ENCODING_PARAM }, - { "tables_version", "set PAT, PMT and SDT version", - offsetof(MpegTSWrite, tables_version), AV_OPT_TYPE_INT, - { .i64 = 0 }, 0, 31, AV_OPT_FLAG_ENCODING_PARAM }, + 0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_FLAG_DISCONT }, 0, INT_MAX, ENC, "mpegts_flags" }, + { "mpegts_copyts", "don't offset dts/pts", OFFSET(copyts), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, ENC }, + { "tables_version", "set PAT, PMT and SDT version", OFFSET(tables_version), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 31, ENC }, { "omit_video_pes_length", "Omit the PES packet length for video packets", - offsetof(MpegTSWrite, omit_video_pes_length), AV_OPT_TYPE_BOOL, - { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, + OFFSET(omit_video_pes_length), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, ENC }, { "pcr_period", "PCR retransmission time in milliseconds", - offsetof(MpegTSWrite, pcr_period), AV_OPT_TYPE_INT, - { .i64 = PCR_RETRANS_TIME }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, + OFFSET(pcr_period_ms), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ENC }, { "pat_period", "PAT/PMT retransmission time limit in seconds", - offsetof(MpegTSWrite, pat_period), AV_OPT_TYPE_DOUBLE, - { .dbl = INT_MAX }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, + OFFSET(pat_period_us), AV_OPT_TYPE_DURATION, { .i64 = PAT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC }, { "sdt_period", "SDT retransmission time limit in seconds", - offsetof(MpegTSWrite, sdt_period), AV_OPT_TYPE_DOUBLE, - { .dbl = INT_MAX }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, + OFFSET(sdt_period_us), AV_OPT_TYPE_DURATION, { .i64 = SDT_RETRANS_TIME * 1000LL }, 0, INT64_MAX, ENC }, { NULL }, }; diff -Nru ffmpeg-4.2.2/libavformat/mpegts.h ffmpeg-4.4/libavformat/mpegts.h --- ffmpeg-4.2.2/libavformat/mpegts.h 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/mpegts.h 2021-04-08 21:28:40.000000000 +0000 @@ -30,17 +30,91 @@ #define TS_MAX_PACKET_SIZE 204 #define NB_PID_MAX 8192 +#define USUAL_SECTION_SIZE 1024 /* except EIT which is limited to 4096 */ #define MAX_SECTION_SIZE 4096 /* pids */ -#define PAT_PID 0x0000 -#define SDT_PID 0x0011 +#define PAT_PID 0x0000 /* Program Association Table */ +#define CAT_PID 0x0001 /* Conditional Access Table */ +#define TSDT_PID 0x0002 /* Transport Stream Description Table */ +#define IPMP_PID 0x0003 +/* PID from 0x0004 to 0x000F are reserved */ +#define NIT_PID 0x0010 /* Network Information Table */ +#define SDT_PID 0x0011 /* Service Description Table */ +#define BAT_PID 0x0011 /* Bouquet Association Table */ +#define EIT_PID 0x0012 /* Event Information Table */ +#define RST_PID 0x0013 /* Running Status Table */ +#define TDT_PID 0x0014 /* Time and Date Table */ +#define TOT_PID 0x0014 +#define NET_SYNC_PID 0x0015 +#define RNT_PID 0x0016 /* RAR Notification Table */ +/* PID from 0x0017 to 0x001B are reserved for future use */ +/* PID value 0x001C allocated to link-local inband signalling shall not be + * used on any broadcast signals. It shall only be used between devices in a + * controlled environment. */ +#define LINK_LOCAL_PID 0x001C +#define MEASUREMENT_PID 0x001D +#define DIT_PID 0x001E /* Discontinuity Information Table */ +#define SIT_PID 0x001F /* Selection Information Table */ +/* PID from 0x0020 to 0x1FFA may be assigned as needed to PMT, elementary + * streams and other data tables */ +#define FIRST_OTHER_PID 0x0020 +#define LAST_OTHER_PID 0x1FFA +/* PID 0x1FFB is used by DigiCipher 2/ATSC MGT metadata */ +/* PID from 0x1FFC to 0x1FFE may be assigned as needed to PMT, elementary + * streams and other data tables */ +#define NULL_PID 0x1FFF /* Null packet (used for fixed bandwidth padding) */ + +/* m2ts pids */ +#define M2TS_PMT_PID 0x0100 +#define M2TS_PCR_PID 0x1001 +#define M2TS_VIDEO_PID 0x1011 +#define M2TS_AUDIO_START_PID 0x1100 +#define M2TS_PGSSUB_START_PID 0x1200 +#define M2TS_TEXTSUB_PID 0x1800 +#define M2TS_SECONDARY_AUDIO_START_PID 0x1A00 +#define M2TS_SECONDARY_VIDEO_START_PID 0x1B00 /* table ids */ -#define PAT_TID 0x00 -#define PMT_TID 0x02 -#define M4OD_TID 0x05 -#define SDT_TID 0x42 +#define PAT_TID 0x00 /* Program Association section */ +#define CAT_TID 0x01 /* Conditional Access section */ +#define PMT_TID 0x02 /* Program Map section */ +#define TSDT_TID 0x03 /* Transport Stream Description section */ +/* TID from 0x04 to 0x3F are reserved */ +#define M4OD_TID 0x05 +#define NIT_TID 0x40 /* Network Information section - actual network */ +#define ONIT_TID 0x41 /* Network Information section - other network */ +#define SDT_TID 0x42 /* Service Description section - actual TS */ +/* TID from 0x43 to 0x45 are reserved for future use */ +#define OSDT_TID 0x46 /* Service Descrition section - other TS */ +/* TID from 0x47 to 0x49 are reserved for future use */ +#define BAT_TID 0x4A /* Bouquet Association section */ +#define UNT_TID 0x4B /* Update Notification Table section */ +#define DFI_TID 0x4C /* Downloadable Font Info section */ +/* TID 0x4D is reserved for future use */ +#define EIT_TID 0x4E /* Event Information section - actual TS */ +#define OEIT_TID 0x4F /* Event Information section - other TS */ +#define EITS_START_TID 0x50 /* Event Information section schedule - actual TS */ +#define EITS_END_TID 0x5F /* Event Information section schedule - actual TS */ +#define OEITS_START_TID 0x60 /* Event Information section schedule - other TS */ +#define OEITS_END_TID 0x6F /* Event Information section schedule - other TS */ +#define TDT_TID 0x70 /* Time Date section */ +#define RST_TID 0x71 /* Running Status section */ +#define ST_TID 0x72 /* Stuffing section */ +#define TOT_TID 0x73 /* Time Offset section */ +#define AIT_TID 0x74 /* Application Inforamtion section */ +#define CT_TID 0x75 /* Container section */ +#define RCT_TID 0x76 /* Related Content section */ +#define CIT_TID 0x77 /* Content Identifier section */ +#define MPE_FEC_TID 0x78 /* MPE-FEC section */ +#define RPNT_TID 0x79 /* Resolution Provider Notification section */ +#define MPE_IFEC_TID 0x7A /* MPE-IFEC section */ +#define PROTMT_TID 0x7B /* Protection Message section */ +/* TID from 0x7C to 0x7D are reserved for future use */ +#define DIT_TID 0x7E /* Discontinuity Information section */ +#define SIT_TID 0x7F /* Selection Information section */ +/* TID from 0x80 to 0xFE are user defined */ +/* TID 0xFF is reserved */ #define STREAM_TYPE_VIDEO_MPEG1 0x01 #define STREAM_TYPE_VIDEO_MPEG2 0x02 @@ -63,6 +137,23 @@ #define STREAM_TYPE_AUDIO_TRUEHD 0x83 #define STREAM_TYPE_AUDIO_EAC3 0x87 +/* ISO/IEC 13818-1 Table 2-22 */ +#define STREAM_ID_PRIVATE_STREAM_1 0xbd +#define STREAM_ID_AUDIO_STREAM_0 0xc0 +#define STREAM_ID_VIDEO_STREAM_0 0xe0 +#define STREAM_ID_METADATA_STREAM 0xfc +#define STREAM_ID_EXTENDED_STREAM_ID 0xfd + +/* ISO/IEC 13818-1 Table 2-45 */ +#define VIDEO_STREAM_DESCRIPTOR 0x02 +#define REGISTRATION_DESCRIPTOR 0x05 +#define ISO_639_LANGUAGE_DESCRIPTOR 0x0a +#define IOD_DESCRIPTOR 0x1d +#define SL_DESCRIPTOR 0x1e +#define FMC_DESCRIPTOR 0x1f +#define METADATA_DESCRIPTOR 0x26 +#define METADATA_STD_DESCRIPTOR 0x27 + typedef struct MpegTSContext MpegTSContext; MpegTSContext *avpriv_mpegts_parse_open(AVFormatContext *s); @@ -94,6 +185,22 @@ SLConfigDescr sl; } Mp4Descr; +/* + * ETSI 300 468 descriptor 0x6A(AC-3) + * Refer to: ETSI EN 300 468 V1.11.1 (2010-04) (SI in DVB systems) + */ +typedef struct DVBAC3Descriptor { + uint8_t component_type_flag; + uint8_t bsid_flag; + uint8_t mainid_flag; + uint8_t asvc_flag; + uint8_t reserved_flags; + uint8_t component_type; + uint8_t bsid; + uint8_t mainid; + uint8_t asvc; +} DVBAC3Descriptor; + /** * Parse an MPEG-2 descriptor * @param[in] fc Format context (used for logging only) diff -Nru ffmpeg-4.2.2/libavformat/mpjpeg.c ffmpeg-4.4/libavformat/mpjpeg.c --- ffmpeg-4.2.2/libavformat/mpjpeg.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mpjpeg.c 2020-07-11 10:39:30.000000000 +0000 @@ -34,7 +34,6 @@ { MPJPEGContext *mpj = s->priv_data; avio_printf(s->pb, "--%s\r\n", mpj->boundary_tag); - avio_flush(s->pb); return 0; } @@ -50,11 +49,6 @@ return 0; } -static int mpjpeg_write_trailer(AVFormatContext *s) -{ - return 0; -} - static const AVOption options[] = { { "boundary_tag", "Boundary tag", offsetof(MPJPEGContext, boundary_tag), AV_OPT_TYPE_STRING, {.str = BOUNDARY_TAG}, .flags = AV_OPT_FLAG_ENCODING_PARAM }, { NULL }, @@ -77,7 +71,6 @@ .video_codec = AV_CODEC_ID_MJPEG, .write_header = mpjpeg_write_header, .write_packet = mpjpeg_write_packet, - .write_trailer = mpjpeg_write_trailer, .flags = AVFMT_NOTIMESTAMPS, .priv_class = &mpjpeg_muxer_class, }; diff -Nru ffmpeg-4.2.2/libavformat/mpjpegdec.c ffmpeg-4.4/libavformat/mpjpegdec.c --- ffmpeg-4.2.2/libavformat/mpjpegdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mpjpegdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -113,20 +113,16 @@ static int mpjpeg_read_probe(const AVProbeData *p) { - AVIOContext *pb; + AVIOContext pb; int ret = 0; int size = 0; if (p->buf_size < 2 || p->buf[0] != '-' || p->buf[1] != '-') return 0; - pb = avio_alloc_context(p->buf, p->buf_size, 0, NULL, NULL, NULL, NULL); - if (!pb) - return 0; - - ret = (parse_multipart_header(pb, &size, "--", NULL) >= 0) ? AVPROBE_SCORE_MAX : 0; + ffio_init_context(&pb, p->buf, p->buf_size, 0, NULL, NULL, NULL, NULL); - avio_context_free(&pb); + ret = (parse_multipart_header(&pb, &size, "--", NULL) >= 0) ? AVPROBE_SCORE_MAX : 0; return ret; } @@ -271,7 +267,7 @@ while (av_isspace(*start)) start++; - if (!av_stristart(start, "boundary=", &start)) { + if (av_stristart(start, "boundary=", &start)) { end = strchr(start, ';'); if (end) len = end - start - 1; @@ -306,8 +302,9 @@ boundary = mpjpeg_get_boundary(s->pb); } if (boundary != NULL) { - mpjpeg->boundary = boundary; - mpjpeg->searchstr = av_asprintf( "\r\n%s\r\n", boundary ); + mpjpeg->boundary = av_asprintf("--%s", boundary); + mpjpeg->searchstr = av_asprintf("\r\n--%s\r\n", boundary); + av_freep(&boundary); } else { mpjpeg->boundary = av_strdup("--"); mpjpeg->searchstr = av_strdup("\r\n--"); @@ -331,22 +328,18 @@ ret = av_get_packet(s->pb, pkt, size); } else { /* no size was given -- we read until the next boundary or end-of-file */ - int remaining = 0, len; + int len; const int read_chunk = 2048; - av_init_packet(pkt); - pkt->data = NULL; - pkt->size = 0; - pkt->pos = avio_tell(s->pb); - /* we may need to return as much as all we've read back to the buffer */ - ffio_ensure_seekback(s->pb, read_chunk); + pkt->pos = avio_tell(s->pb); - while ((ret = av_append_packet(s->pb, pkt, read_chunk - remaining)) >= 0) { + while ((ret = ffio_ensure_seekback(s->pb, read_chunk)) >= 0 && /* we may need to return as much as all we've read back to the buffer */ + (ret = av_append_packet(s->pb, pkt, read_chunk)) >= 0) { /* scan the new data */ char *start; - len = ret + remaining; + len = ret; start = pkt->data + pkt->size - len; do { if (!memcmp(start, mpjpeg->searchstr, mpjpeg->searchstr_len)) { @@ -358,14 +351,13 @@ len--; start++; } while (len >= mpjpeg->searchstr_len); - remaining = len; + avio_seek(s->pb, -len, SEEK_CUR); + pkt->size -= len; } /* error or EOF occurred */ if (ret == AVERROR_EOF) { ret = pkt->size > 0 ? pkt->size : AVERROR_EOF; - } else { - av_packet_unref(pkt); } } diff -Nru ffmpeg-4.2.2/libavformat/mpl2dec.c ffmpeg-4.4/libavformat/mpl2dec.c --- ffmpeg-4.2.2/libavformat/mpl2dec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mpl2dec.c 2021-04-08 21:28:40.000000000 +0000 @@ -55,7 +55,7 @@ return AVPROBE_SCORE_MAX; } -static int read_ts(char **line, int64_t *pts_start, int *duration) +static int read_ts(char **line, int64_t *pts_start, int64_t *duration) { char c; int len; @@ -69,7 +69,10 @@ } if (sscanf(*line, "[%"SCNd64"][%"SCNd64"]%c%n", pts_start, &end, &c, &len) >= 3) { - *duration = end - *pts_start; + if (end < *pts_start || end - (uint64_t)*pts_start > INT64_MAX) { + *duration = -1; + } else + *duration = end - *pts_start; *line += len - 1; return 0; } @@ -80,7 +83,6 @@ { MPL2Context *mpl2 = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); - int res = 0; if (!st) return AVERROR(ENOMEM); @@ -97,7 +99,7 @@ const int64_t pos = avio_tell(s->pb); int len = ff_get_line(s->pb, line, sizeof(line)); int64_t pts_start; - int duration; + int64_t duration; if (!len) break; @@ -108,8 +110,10 @@ AVPacket *sub; sub = ff_subtitles_queue_insert(&mpl2->q, p, strlen(p), 0); - if (!sub) + if (!sub) { + ff_subtitles_queue_clean(&mpl2->q); return AVERROR(ENOMEM); + } sub->pos = pos; sub->pts = pts_start; sub->duration = duration; @@ -117,7 +121,7 @@ } ff_subtitles_queue_finalize(s, &mpl2->q); - return res; + return 0; } static int mpl2_read_packet(AVFormatContext *s, AVPacket *pkt) diff -Nru ffmpeg-4.2.2/libavformat/mpsubdec.c ffmpeg-4.4/libavformat/mpsubdec.c --- ffmpeg-4.2.2/libavformat/mpsubdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/mpsubdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -27,6 +27,8 @@ #include "internal.h" #include "subtitles.h" +#define TSBASE 10000000 + typedef struct { FFDemuxSubtitlesQueue q; } MPSubContext; @@ -51,21 +53,55 @@ return 0; } +static int parse_line(const char *line, int64_t *value, int64_t *value2) +{ + int vi, p1, p2; + + for (vi = 0; vi < 2; vi++) { + long long intval, fracval; + int n = av_sscanf(line, "%lld%n.%lld%n", &intval, &p1, &fracval, &p2); + if (n <= 0 || intval < INT64_MIN / TSBASE || intval > INT64_MAX / TSBASE) + return AVERROR_INVALIDDATA; + + intval *= TSBASE; + + if (n == 2) { + if (fracval < 0) + return AVERROR_INVALIDDATA; + for (;p2 - p1 < 7 + 1; p1--) + fracval *= 10; + for (;p2 - p1 > 7 + 1; p1++) + fracval /= 10; + if (intval > 0) intval = av_sat_add64(intval, fracval); + else intval = av_sat_sub64(intval, fracval); + line += p2; + } else + line += p1; + + *value = intval; + + value = value2; + } + + return 0; +} + static int mpsub_read_header(AVFormatContext *s) { MPSubContext *mpsub = s->priv_data; AVStream *st; AVBPrint buf; - AVRational pts_info = (AVRational){ 100, 1 }; // ts based by default + AVRational pts_info = (AVRational){ TSBASE, 1 }; // ts based by default int res = 0; - int multiplier = 100; - double current_pts = 0; + int64_t current_pts = 0; + int i; + int common_factor = 0; av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); while (!avio_feof(s->pb)) { char line[1024]; - double start, duration; + int64_t start, duration; int fps, len = ff_get_line(s->pb, line, sizeof(line)); if (!len) @@ -75,9 +111,8 @@ if (sscanf(line, "FORMAT=%d", &fps) == 1 && fps > 3 && fps < 100) { /* frame based timing */ - pts_info = (AVRational){ fps, 1 }; - multiplier = 1; - } else if (sscanf(line, "%lf %lf", &start, &duration) == 2) { + pts_info = (AVRational){ TSBASE * fps, 1 }; + } else if (parse_line(line, &start, &duration) >= 0) { AVPacket *sub; const int64_t pos = avio_tell(s->pb); @@ -88,17 +123,41 @@ res = AVERROR(ENOMEM); goto end; } - sub->pts = (int64_t)(current_pts + start*multiplier); - sub->duration = (int)(duration * multiplier); - current_pts += (start + duration) * multiplier; + if ( current_pts < 0 && start < INT64_MIN - current_pts + || current_pts > 0 && start > INT64_MAX - current_pts) { + res = AVERROR_INVALIDDATA; + goto end; + } + sub->pts = current_pts + start; + if (duration < 0 || sub->pts > INT64_MAX - duration) { + res = AVERROR_INVALIDDATA; + goto end; + } + sub->duration = duration; + + common_factor = av_gcd(duration, common_factor); + common_factor = av_gcd(sub->pts, common_factor); + + current_pts = sub->pts + duration; sub->pos = pos; } } } + if (common_factor > 1) { + common_factor = av_gcd(pts_info.num, common_factor); + for (i = 0; i < mpsub->q.nb_subs; i++) { + mpsub->q.subs[i]->pts /= common_factor; + mpsub->q.subs[i]->duration /= common_factor; + } + pts_info.num /= common_factor; + } + st = avformat_new_stream(s, NULL); - if (!st) - return AVERROR(ENOMEM); + if (!st) { + res = AVERROR(ENOMEM); + goto end; + } avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num); st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codecpar->codec_id = AV_CODEC_ID_TEXT; diff -Nru ffmpeg-4.2.2/libavformat/mspdec.c ffmpeg-4.4/libavformat/mspdec.c --- ffmpeg-4.2.2/libavformat/mspdec.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/mspdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,117 @@ +/* + * Microsoft Paint (MSP) demuxer + * Copyright (c) 2020 Peter Ross (pross@xvid.org) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * Microsoft Paint (MSP) demuxer + */ + +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "avformat.h" +#include "internal.h" + +typedef struct { + int packet_size; +} MSPContext; + +static int msp_probe(const AVProbeData *p) +{ + unsigned int i, sum; + + if (p->buf_size <= 32 || (memcmp(p->buf, "DanM", 4) && memcmp(p->buf, "LinS", 4))) + return 0; + + sum = 0; + for (i = 0; i < 24; i += 2) + sum ^= AV_RL16(p->buf + i); + + return AV_RL16(p->buf + 24) == sum ? AVPROBE_SCORE_MAX : 0; +} + +static int msp_read_header(AVFormatContext *s) +{ + MSPContext * cntx = s->priv_data; + AVIOContext *pb = s->pb; + AVStream *st; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = avio_rl32(pb) == MKTAG('D', 'a', 'n', 'M') ? AV_CODEC_ID_RAWVIDEO : AV_CODEC_ID_MSP2; + + st->codecpar->width = avio_rl16(pb); + st->codecpar->height = avio_rl16(pb); + st->codecpar->format = AV_PIX_FMT_MONOBLACK; + + st->sample_aspect_ratio.num = avio_rl16(pb); + st->sample_aspect_ratio.den = avio_rl16(pb); + avio_skip(pb, 20); + + if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) { + cntx->packet_size = av_image_get_buffer_size(st->codecpar->format, st->codecpar->width, st->codecpar->height, 1); + } else + cntx->packet_size = 2 * st->codecpar->height; + + if (cntx->packet_size <= 0) + return cntx->packet_size < 0 ? cntx->packet_size : AVERROR_INVALIDDATA; + + return 0; +} + +static int msp_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVStream *st = s->streams[0]; + MSPContext *cntx = s->priv_data; + int ret; + + ret = av_get_packet(s->pb, pkt, cntx->packet_size); + if (ret < 0) + return ret; + + if (st->codecpar->codec_id == AV_CODEC_ID_MSP2) { + unsigned int size, i; + if (pkt->size != 2 * st->codecpar->height) + return AVERROR_INVALIDDATA; + size = 0; + for (i = 0; i < st->codecpar->height; i++) + size += AV_RL16(&pkt->data[i * 2]); + ret = av_append_packet(s->pb, pkt, size); + if (ret < 0) + return ret; + } + + pkt->stream_index = 0; + pkt->flags |= AV_PKT_FLAG_KEY; + return 0; +} + +AVInputFormat ff_msp_demuxer = { + .name = "msp", + .long_name = NULL_IF_CONFIG_SMALL("Microsoft Paint (MSP))"), + .read_probe = msp_probe, + .read_header = msp_read_header, + .read_packet = msp_read_packet, + .flags = AVFMT_NOTIMESTAMPS, + .priv_data_size = sizeof(MSPContext), +}; diff -Nru ffmpeg-4.2.2/libavformat/mtv.c ffmpeg-4.4/libavformat/mtv.c --- ffmpeg-4.2.2/libavformat/mtv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mtv.c 2020-07-11 10:39:30.000000000 +0000 @@ -171,6 +171,8 @@ st->codecpar->width = mtv->img_width; st->codecpar->height = mtv->img_height; st->codecpar->extradata = av_strdup("BottomUp"); + if (!st->codecpar->extradata) + return AVERROR(ENOMEM); st->codecpar->extradata_size = 9; // audio - mp3 diff -Nru ffmpeg-4.2.2/libavformat/musx.c ffmpeg-4.4/libavformat/musx.c --- ffmpeg-4.2.2/libavformat/musx.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/musx.c 2021-04-08 21:28:40.000000000 +0000 @@ -20,12 +20,23 @@ */ #include "libavutil/avassert.h" +#include "libavutil/intreadwrite.h" #include "avformat.h" #include "internal.h" static int musx_probe(const AVProbeData *p) { - if (memcmp(p->buf, "MUSX", 4)) + unsigned version; + + if (AV_RB32(p->buf) != MKBETAG('M','U','S','X')) + return 0; + + version = AV_RL32(p->buf + 8); + if (version != 10 && + version != 6 && + version != 5 && + version != 4 && + version != 201) return 0; return AVPROBE_SCORE_MAX / 5 * 2; diff -Nru ffmpeg-4.2.2/libavformat/mux.c ffmpeg-4.4/libavformat/mux.c --- ffmpeg-4.2.2/libavformat/mux.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mux.c 2021-04-08 21:28:40.000000000 +0000 @@ -20,29 +20,17 @@ */ #include "avformat.h" -#include "avio_internal.h" #include "internal.h" #include "libavcodec/internal.h" -#include "libavcodec/bytestream.h" +#include "libavcodec/packet_internal.h" #include "libavutil/opt.h" #include "libavutil/dict.h" #include "libavutil/pixdesc.h" #include "libavutil/timestamp.h" -#include "metadata.h" -#include "id3v2.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/internal.h" #include "libavutil/mathematics.h" -#include "libavutil/parseutils.h" -#include "libavutil/time.h" -#include "riff.h" -#include "audiointerleave.h" -#include "url.h" -#include -#if CONFIG_NETWORK -#include "network.h" -#endif /** * @file @@ -357,6 +345,8 @@ if (desc && desc->props & AV_CODEC_PROP_REORDER) st->internal->reorder = 1; + st->internal->is_intra_only = ff_is_intra_only(par->codec_id); + if (of->codec_tag) { if ( par->codec_tag && par->codec_id == AV_CODEC_ID_RAWVIDEO @@ -485,6 +475,14 @@ } } +static void deinit_muxer(AVFormatContext *s) +{ + if (s->oformat && s->oformat->deinit && s->internal->initialized) + s->oformat->deinit(s); + s->internal->initialized = + s->internal->streams_initialized = 0; +} + int avformat_init_output(AVFormatContext *s, AVDictionary **options) { int ret = 0; @@ -536,19 +534,12 @@ return streams_already_initialized; fail: - if (s->oformat->deinit) - s->oformat->deinit(s); + deinit_muxer(s); return ret; } #define AV_PKT_FLAG_UNCODED_FRAME 0x2000 -/* Note: using sizeof(AVFrame) from outside lavu is unsafe in general, but - it is only being used internally to this file as a consistency check. - The value is chosen to be very unlikely to appear on its own and to cause - immediate failure if used anywhere as a real size. */ -#define UNCODED_FRAME_PACKET_SIZE (INT_MIN / 3 * 2 + (int)sizeof(AVFrame)) - #if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS @@ -556,7 +547,7 @@ static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket *pkt) { int delay = FFMAX(st->codecpar->video_delay, st->internal->avctx->max_b_frames > 0); - int num, den, i; + int i; int frame_size; if (!s->internal->missing_ts_warning && @@ -574,20 +565,6 @@ av_log(s, AV_LOG_DEBUG, "compute_muxer_pkt_fields: pts:%s dts:%s cur_dts:%s b:%d size:%d st:%d\n", av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts), delay, pkt->size, pkt->stream_index); - if (pkt->duration < 0 && st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) { - av_log(s, AV_LOG_WARNING, "Packet with invalid duration %"PRId64" in stream %d\n", - pkt->duration, pkt->stream_index); - pkt->duration = 0; - } - - /* duration field */ - if (pkt->duration == 0) { - ff_compute_frame_duration(s, &num, &den, st, NULL, pkt); - if (den && num) { - pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den * st->codec->ticks_per_frame, den * (int64_t)st->time_base.num); - } - } - if (pkt->pts == AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && delay == 0) pkt->pts = pkt->dts; @@ -605,13 +582,13 @@ //calculate dts from pts if (pkt->pts != AV_NOPTS_VALUE && pkt->dts == AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY) { - st->pts_buffer[0] = pkt->pts; - for (i = 1; i < delay + 1 && st->pts_buffer[i] == AV_NOPTS_VALUE; i++) - st->pts_buffer[i] = pkt->pts + (i - delay - 1) * pkt->duration; - for (i = 0; ipts_buffer[i] > st->pts_buffer[i + 1]; i++) - FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i + 1]); + st->internal->pts_buffer[0] = pkt->pts; + for (i = 1; i < delay + 1 && st->internal->pts_buffer[i] == AV_NOPTS_VALUE; i++) + st->internal->pts_buffer[i] = pkt->pts + (i - delay - 1) * pkt->duration; + for (i = 0; iinternal->pts_buffer[i] > st->internal->pts_buffer[i + 1]; i++) + FFSWAP(int64_t, st->internal->pts_buffer[i], st->internal->pts_buffer[i + 1]); - pkt->dts = st->pts_buffer[0]; + pkt->dts = st->internal->pts_buffer[0]; } if (st->cur_dts && st->cur_dts != AV_NOPTS_VALUE && @@ -643,7 +620,7 @@ switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_AUDIO: frame_size = (pkt->flags & AV_PKT_FLAG_UNCODED_FRAME) ? - ((AVFrame *)pkt->data)->nb_samples : + (*(AVFrame **)pkt->data)->nb_samples : av_get_audio_frame_duration(st->codec, pkt->size); /* HACK/FIXME, we skip the initial 0 size packets as they are most @@ -662,9 +639,39 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif +static void guess_pkt_duration(AVFormatContext *s, AVStream *st, AVPacket *pkt) +{ + if (pkt->duration < 0 && st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) { + av_log(s, AV_LOG_WARNING, "Packet with invalid duration %"PRId64" in stream %d\n", + pkt->duration, pkt->stream_index); + pkt->duration = 0; + } + + if (pkt->duration) + return; + + switch (st->codecpar->codec_type) { + case AVMEDIA_TYPE_VIDEO: + if (st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0) { + pkt->duration = av_rescale_q(1, av_inv_q(st->avg_frame_rate), + st->time_base); + } else if (st->time_base.num * 1000LL > st->time_base.den) + pkt->duration = 1; + break; + case AVMEDIA_TYPE_AUDIO: { + int frame_size = av_get_audio_frame_duration2(st->codecpar, pkt->size); + if (frame_size && st->codecpar->sample_rate) { + pkt->duration = av_rescale_q(frame_size, + (AVRational){1, st->codecpar->sample_rate}, + st->time_base); + } + break; + } + } +} + /** - * Make timestamps non negative, move side data from payload to internal struct, call muxer, and restore - * sidedata. + * Shift timestamps and call muxer; the original pts/dts are not kept. * * FIXME: this function should NEVER get undefined pts/dts beside when the * AVFMT_NOTIMESTAMPS is set. @@ -674,10 +681,6 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) { int ret; - int64_t pts_backup, dts_backup; - - pts_backup = pkt->pts; - dts_backup = pkt->dts; // If the timestamp offsetting below is adjusted, adjust // ff_interleaved_peek similarly. @@ -693,7 +696,7 @@ if (s->avoid_negative_ts > 0) { AVStream *st = s->streams[pkt->stream_index]; - int64_t offset = st->mux_ts_offset; + int64_t offset = st->internal->mux_ts_offset; int64_t ts = s->internal->avoid_negative_ts_use_pts ? pkt->pts : pkt->dts; if (s->internal->offset == AV_NOPTS_VALUE && ts != AV_NOPTS_VALUE && @@ -703,7 +706,7 @@ } if (s->internal->offset != AV_NOPTS_VALUE && !offset) { - offset = st->mux_ts_offset = + offset = st->internal->mux_ts_offset = av_rescale_q_rnd(s->internal->offset, s->internal->offset_timebase, st->time_base, @@ -739,10 +742,9 @@ } if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) { - AVFrame *frame = (AVFrame *)pkt->data; - av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE); - ret = s->oformat->write_uncoded_frame(s, pkt->stream_index, &frame, 0); - av_frame_free(&frame); + AVFrame **frame = (AVFrame **)pkt->data; + av_assert0(pkt->size == sizeof(*frame)); + ret = s->oformat->write_uncoded_frame(s, pkt->stream_index, frame, 0); } else { ret = s->oformat->write_packet(s, pkt); } @@ -753,19 +755,14 @@ ret = s->pb->error; } - if (ret < 0) { - pkt->pts = pts_backup; - pkt->dts = dts_backup; - } + if (ret >= 0) + s->streams[pkt->stream_index]->nb_frames++; return ret; } static int check_packet(AVFormatContext *s, AVPacket *pkt) { - if (!pkt) - return 0; - if (pkt->stream_index < 0 || pkt->stream_index >= s->nb_streams) { av_log(s, AV_LOG_ERROR, "Invalid packet stream index: %d\n", pkt->stream_index); @@ -780,18 +777,11 @@ return 0; } -static int prepare_input_packet(AVFormatContext *s, AVPacket *pkt) +static int prepare_input_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt) { - int ret; - - ret = check_packet(s, pkt); - if (ret < 0) - return ret; - #if !FF_API_COMPUTE_PKT_FIELDS2 || !FF_API_LAVF_AVCTX /* sanitize the timestamps */ if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { - AVStream *st = s->streams[pkt->stream_index]; /* when there is no reordering (so dts is equal to pts), but * only one of them is set, set the other as well */ @@ -828,144 +818,62 @@ } } #endif + /* update flags */ + if (st->internal->is_intra_only) + pkt->flags |= AV_PKT_FLAG_KEY; return 0; } -static int do_packet_auto_bsf(AVFormatContext *s, AVPacket *pkt) { - AVStream *st = s->streams[pkt->stream_index]; - int i, ret; - - if (!(s->flags & AVFMT_FLAG_AUTO_BSF)) - return 1; - - if (s->oformat->check_bitstream) { - if (!st->internal->bitstream_checked) { - if ((ret = s->oformat->check_bitstream(s, pkt)) < 0) - return ret; - else if (ret == 1) - st->internal->bitstream_checked = 1; - } - } - - for (i = 0; i < st->internal->nb_bsfcs; i++) { - AVBSFContext *ctx = st->internal->bsfcs[i]; - // TODO: when any bitstream filter requires flushing at EOF, we'll need to - // flush each stream's BSF chain on write_trailer. - if ((ret = av_bsf_send_packet(ctx, pkt)) < 0) { - av_log(ctx, AV_LOG_ERROR, - "Failed to send packet to filter %s for stream %d\n", - ctx->filter->name, pkt->stream_index); - return ret; - } - // TODO: when any automatically-added bitstream filter is generating multiple - // output packets for a single input one, we'll need to call this in a loop - // and write each output packet. - if ((ret = av_bsf_receive_packet(ctx, pkt)) < 0) { - if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) - return 0; - av_log(ctx, AV_LOG_ERROR, - "Failed to receive packet from filter %s for stream %d\n", - ctx->filter->name, pkt->stream_index); - if (s->error_recognition & AV_EF_EXPLODE) - return ret; - return 0; - } - } - return 1; -} - -int av_write_frame(AVFormatContext *s, AVPacket *pkt) -{ - int ret; - - ret = prepare_input_packet(s, pkt); - if (ret < 0) - return ret; - - if (!pkt) { - if (s->oformat->flags & AVFMT_ALLOW_FLUSH) { - ret = s->oformat->write_packet(s, NULL); - flush_if_needed(s); - if (ret >= 0 && s->pb && s->pb->error < 0) - ret = s->pb->error; - return ret; - } - return 1; - } - - ret = do_packet_auto_bsf(s, pkt); - if (ret <= 0) - return ret; - -#if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX - ret = compute_muxer_pkt_fields(s, s->streams[pkt->stream_index], pkt); - - if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) - return ret; -#endif - - ret = write_packet(s, pkt); - if (ret >= 0 && s->pb && s->pb->error < 0) - ret = s->pb->error; - - if (ret >= 0) - s->streams[pkt->stream_index]->nb_frames++; - return ret; -} - #define CHUNK_START 0x1000 int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, - int (*compare)(AVFormatContext *, AVPacket *, AVPacket *)) + int (*compare)(AVFormatContext *, const AVPacket *, const AVPacket *)) { int ret; - AVPacketList **next_point, *this_pktl; - AVStream *st = s->streams[pkt->stream_index]; - int chunked = s->max_chunk_size || s->max_chunk_duration; + PacketList **next_point, *this_pktl; + AVStream *st = s->streams[pkt->stream_index]; + int chunked = s->max_chunk_size || s->max_chunk_duration; - this_pktl = av_mallocz(sizeof(AVPacketList)); - if (!this_pktl) + this_pktl = av_malloc(sizeof(PacketList)); + if (!this_pktl) { + av_packet_unref(pkt); return AVERROR(ENOMEM); - if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) { - av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE); - av_assert0(((AVFrame *)pkt->data)->buf); - this_pktl->pkt = *pkt; - pkt->buf = NULL; - pkt->side_data = NULL; - pkt->side_data_elems = 0; - } else { - if ((ret = av_packet_ref(&this_pktl->pkt, pkt)) < 0) { - av_free(this_pktl); - return ret; - } } + if ((ret = av_packet_make_refcounted(pkt)) < 0) { + av_free(this_pktl); + av_packet_unref(pkt); + return ret; + } + + av_packet_move_ref(&this_pktl->pkt, pkt); + pkt = &this_pktl->pkt; - if (s->streams[pkt->stream_index]->last_in_packet_buffer) { - next_point = &(st->last_in_packet_buffer->next); + if (st->internal->last_in_packet_buffer) { + next_point = &(st->internal->last_in_packet_buffer->next); } else { next_point = &s->internal->packet_buffer; } if (chunked) { uint64_t max= av_rescale_q_rnd(s->max_chunk_duration, AV_TIME_BASE_Q, st->time_base, AV_ROUND_UP); - st->interleaver_chunk_size += pkt->size; - st->interleaver_chunk_duration += pkt->duration; - if ( (s->max_chunk_size && st->interleaver_chunk_size > s->max_chunk_size) - || (max && st->interleaver_chunk_duration > max)) { - st->interleaver_chunk_size = 0; - this_pktl->pkt.flags |= CHUNK_START; - if (max && st->interleaver_chunk_duration > max) { + st->internal->interleaver_chunk_size += pkt->size; + st->internal->interleaver_chunk_duration += pkt->duration; + if ( (s->max_chunk_size && st->internal->interleaver_chunk_size > s->max_chunk_size) + || (max && st->internal->interleaver_chunk_duration > max)) { + st->internal->interleaver_chunk_size = 0; + pkt->flags |= CHUNK_START; + if (max && st->internal->interleaver_chunk_duration > max) { int64_t syncoffset = (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)*max/2; int64_t syncto = av_rescale(pkt->dts + syncoffset, 1, max)*max - syncoffset; - st->interleaver_chunk_duration += (pkt->dts - syncto)/8 - max; + st->internal->interleaver_chunk_duration += (pkt->dts - syncto)/8 - max; } else - st->interleaver_chunk_duration = 0; + st->internal->interleaver_chunk_duration = 0; } } if (*next_point) { - if (chunked && !(this_pktl->pkt.flags & CHUNK_START)) + if (chunked && !(pkt->flags & CHUNK_START)) goto next_non_null; if (compare(s, &s->internal->packet_buffer_end->pkt, pkt)) { @@ -986,16 +894,13 @@ this_pktl->next = *next_point; - s->streams[pkt->stream_index]->last_in_packet_buffer = - *next_point = this_pktl; - - av_packet_unref(pkt); + st->internal->last_in_packet_buffer = *next_point = this_pktl; return 0; } -static int interleave_compare_dts(AVFormatContext *s, AVPacket *next, - AVPacket *pkt) +static int interleave_compare_dts(AVFormatContext *s, const AVPacket *next, + const AVPacket *pkt) { AVStream *st = s->streams[pkt->stream_index]; AVStream *st2 = s->streams[next->stream_index]; @@ -1027,7 +932,7 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) { - AVPacketList *pktl; + PacketList *pktl; int stream_count = 0; int noninterleaved_count = 0; int i, ret; @@ -1039,7 +944,7 @@ } for (i = 0; i < s->nb_streams; i++) { - if (s->streams[i]->last_in_packet_buffer) { + if (s->streams[i]->internal->last_in_packet_buffer) { ++stream_count; } else if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT && s->streams[i]->codecpar->codec_id != AV_CODEC_ID_VP8 && @@ -1064,7 +969,7 @@ for (i = 0; i < s->nb_streams; i++) { int64_t last_dts; - const AVPacketList *last = s->streams[i]->last_in_packet_buffer; + const PacketList *last = s->streams[i]->internal->last_in_packet_buffer; if (!last) continue; @@ -1113,8 +1018,8 @@ if (!s->internal->packet_buffer) s->internal->packet_buffer_end = NULL; - if (st->last_in_packet_buffer == pktl) - st->last_in_packet_buffer = NULL; + if (st->internal->last_in_packet_buffer == pktl) + st->internal->last_in_packet_buffer = NULL; av_packet_unref(&pktl->pkt); av_freep(&pktl); @@ -1132,47 +1037,48 @@ if (!s->internal->packet_buffer) s->internal->packet_buffer_end = NULL; - if (st->last_in_packet_buffer == pktl) - st->last_in_packet_buffer = NULL; + if (st->internal->last_in_packet_buffer == pktl) + st->internal->last_in_packet_buffer = NULL; av_freep(&pktl); return 1; } else { - av_init_packet(out); return 0; } } -int ff_interleaved_peek(AVFormatContext *s, int stream, - AVPacket *pkt, int add_offset) +int ff_get_muxer_ts_offset(AVFormatContext *s, int stream_index, int64_t *offset) { - AVPacketList *pktl = s->internal->packet_buffer; + AVStream *st; + + if (stream_index < 0 || stream_index >= s->nb_streams) + return AVERROR(EINVAL); + + st = s->streams[stream_index]; + *offset = st->internal->mux_ts_offset; + + if (s->output_ts_offset) + *offset += av_rescale_q(s->output_ts_offset, AV_TIME_BASE_Q, st->time_base); + + return 0; +} + +const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream) +{ + PacketList *pktl = s->internal->packet_buffer; while (pktl) { if (pktl->pkt.stream_index == stream) { - *pkt = pktl->pkt; - if (add_offset) { - AVStream *st = s->streams[pkt->stream_index]; - int64_t offset = st->mux_ts_offset; - - if (s->output_ts_offset) - offset += av_rescale_q(s->output_ts_offset, AV_TIME_BASE_Q, st->time_base); - - if (pkt->dts != AV_NOPTS_VALUE) - pkt->dts += offset; - if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts += offset; - } - return 0; + return &pktl->pkt; } pktl = pktl->next; } - return AVERROR(ENOENT); + return NULL; } /** * Interleave an AVPacket correctly so it can be muxed. * @param out the interleaved packet will be output here - * @param in the input packet + * @param in the input packet; will always be blank on return if not NULL * @param flush 1 if no further packets are available as input and all * remaining packets should be output * @return 1 if a packet was output, 0 if no packet could be output, @@ -1181,101 +1087,209 @@ static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, int flush) { if (s->oformat->interleave_packet) { - int ret = s->oformat->interleave_packet(s, out, in, flush); - if (in) - av_packet_unref(in); - return ret; + return s->oformat->interleave_packet(s, out, in, flush); } else return ff_interleave_packet_per_dts(s, out, in, flush); } -int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) +static int check_bitstream(AVFormatContext *s, AVStream *st, AVPacket *pkt) { - int ret, flush = 0; + int ret; - ret = prepare_input_packet(s, pkt); - if (ret < 0) - goto fail; + if (!(s->flags & AVFMT_FLAG_AUTO_BSF)) + return 1; - if (pkt) { - AVStream *st = s->streams[pkt->stream_index]; + if (s->oformat->check_bitstream) { + if (!st->internal->bitstream_checked) { + if ((ret = s->oformat->check_bitstream(s, pkt)) < 0) + return ret; + else if (ret == 1) + st->internal->bitstream_checked = 1; + } + } - ret = do_packet_auto_bsf(s, pkt); - if (ret == 0) - return 0; - else if (ret < 0) - goto fail; + return 1; +} + +static int interleaved_write_packet(AVFormatContext *s, AVPacket *pkt, int flush) +{ + for (;; ) { + AVPacket opkt; + int ret = interleave_packet(s, &opkt, pkt, flush); + if (ret <= 0) + return ret; + + pkt = NULL; + + ret = write_packet(s, &opkt); + + av_packet_unref(&opkt); + + if (ret < 0) + return ret; + } +} + +static int write_packet_common(AVFormatContext *s, AVStream *st, AVPacket *pkt, int interleaved) +{ + int ret; + + if (s->debug & FF_FDEBUG_TS) + av_log(s, AV_LOG_DEBUG, "%s size:%d dts:%s pts:%s\n", __FUNCTION__, + pkt->size, av_ts2str(pkt->dts), av_ts2str(pkt->pts)); - if (s->debug & FF_FDEBUG_TS) - av_log(s, AV_LOG_DEBUG, "av_interleaved_write_frame size:%d dts:%s pts:%s\n", - pkt->size, av_ts2str(pkt->dts), av_ts2str(pkt->pts)); + guess_pkt_duration(s, st, pkt); #if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX - if ((ret = compute_muxer_pkt_fields(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) - goto fail; + if ((ret = compute_muxer_pkt_fields(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) + return ret; #endif - if (pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { - ret = AVERROR(EINVAL); - goto fail; - } + if (interleaved) { + if (pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) + return AVERROR(EINVAL); + return interleaved_write_packet(s, pkt, 0); } else { - av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame FLUSH\n"); - flush = 1; + return write_packet(s, pkt); } +} - for (;; ) { - AVPacket opkt; - int ret = interleave_packet(s, &opkt, pkt, flush); - if (pkt) { - memset(pkt, 0, sizeof(*pkt)); - av_init_packet(pkt); - pkt = NULL; - } - if (ret <= 0) //FIXME cleanup needed for ret<0 ? +static int write_packets_from_bsfs(AVFormatContext *s, AVStream *st, AVPacket *pkt, int interleaved) +{ + AVBSFContext *bsfc = st->internal->bsfc; + int ret; + + if ((ret = av_bsf_send_packet(bsfc, pkt)) < 0) { + av_log(s, AV_LOG_ERROR, + "Failed to send packet to filter %s for stream %d\n", + bsfc->filter->name, st->index); + return ret; + } + + do { + ret = av_bsf_receive_packet(bsfc, pkt); + if (ret < 0) { + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) + return 0; + av_log(s, AV_LOG_ERROR, "Error applying bitstream filters to an output " + "packet for stream #%d: %s\n", st->index, av_err2str(ret)); + if (!(s->error_recognition & AV_EF_EXPLODE) && ret != AVERROR(ENOMEM)) + continue; return ret; + } + av_packet_rescale_ts(pkt, bsfc->time_base_out, st->time_base); + ret = write_packet_common(s, st, pkt, interleaved); + if (ret >= 0 && !interleaved) // a successful write_packet_common already unrefed pkt for interleaved + av_packet_unref(pkt); + } while (ret >= 0); - ret = write_packet(s, &opkt); - if (ret >= 0) - s->streams[opkt.stream_index]->nb_frames++; + return ret; +} - av_packet_unref(&opkt); +static int write_packets_common(AVFormatContext *s, AVPacket *pkt, int interleaved) +{ + AVStream *st; + int ret = check_packet(s, pkt); + if (ret < 0) + return ret; + st = s->streams[pkt->stream_index]; + ret = prepare_input_packet(s, st, pkt); + if (ret < 0) + return ret; + + ret = check_bitstream(s, st, pkt); + if (ret < 0) + return ret; + + if (st->internal->bsfc) { + return write_packets_from_bsfs(s, st, pkt, interleaved); + } else { + return write_packet_common(s, st, pkt, interleaved); + } +} + +int av_write_frame(AVFormatContext *s, AVPacket *in) +{ + AVPacket *pkt = s->internal->pkt; + int ret; + + if (!in) { + if (s->oformat->flags & AVFMT_ALLOW_FLUSH) { + ret = s->oformat->write_packet(s, NULL); + flush_if_needed(s); + if (ret >= 0 && s->pb && s->pb->error < 0) + ret = s->pb->error; + return ret; + } + return 1; + } + + if (in->flags & AV_PKT_FLAG_UNCODED_FRAME) { + pkt = in; + } else { + /* We don't own in, so we have to make sure not to modify it. + * The following avoids copying in's data unnecessarily. + * Copying side data is unavoidable as a bitstream filter + * may change it, e.g. free it on errors. */ + av_packet_unref(pkt); + pkt->buf = NULL; + pkt->data = in->data; + pkt->size = in->size; + ret = av_packet_copy_props(pkt, in); if (ret < 0) return ret; - if(s->pb && s->pb->error) - return s->pb->error; + if (in->buf) { + pkt->buf = av_buffer_ref(in->buf); + if (!pkt->buf) { + ret = AVERROR(ENOMEM); + goto fail; + } + } } + + ret = write_packets_common(s, pkt, 0/*non-interleaved*/); + fail: + // Uncoded frames using the noninterleaved codepath are also freed here av_packet_unref(pkt); return ret; } -int av_write_trailer(AVFormatContext *s) +int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) { - int ret, i; + int ret; - for (;; ) { - AVPacket pkt; - ret = interleave_packet(s, &pkt, NULL, 1); + if (pkt) { + ret = write_packets_common(s, pkt, 1/*interleaved*/); if (ret < 0) - goto fail; - if (!ret) - break; - - ret = write_packet(s, &pkt); - if (ret >= 0) - s->streams[pkt.stream_index]->nb_frames++; + av_packet_unref(pkt); + return ret; + } else { + av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame FLUSH\n"); + return interleaved_write_packet(s, NULL, 1/*flush*/); + } +} - av_packet_unref(&pkt); +int av_write_trailer(AVFormatContext *s) +{ + int i, ret1, ret = 0; + AVPacket *pkt = s->internal->pkt; - if (ret < 0) - goto fail; - if(s->pb && s->pb->error) - goto fail; + av_packet_unref(pkt); + for (i = 0; i < s->nb_streams; i++) { + if (s->streams[i]->internal->bsfc) { + ret1 = write_packets_from_bsfs(s, s->streams[i], pkt, 1/*interleaved*/); + if (ret1 < 0) + av_packet_unref(pkt); + if (ret >= 0) + ret = ret1; + } } + ret1 = interleaved_write_packet(s, NULL, 1); + if (ret >= 0) + ret = ret1; -fail: if (s->oformat->write_trailer) { if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER); @@ -1286,11 +1300,7 @@ } } - if (s->oformat->deinit) - s->oformat->deinit(s); - - s->internal->initialized = - s->internal->streams_initialized = 0; + deinit_muxer(s); if (s->pb) avio_flush(s->pb); @@ -1323,18 +1333,10 @@ local_pkt = *pkt; local_pkt.stream_index = dst_stream; - if (pkt->pts != AV_NOPTS_VALUE) - local_pkt.pts = av_rescale_q(pkt->pts, - src->streams[pkt->stream_index]->time_base, - dst->streams[dst_stream]->time_base); - if (pkt->dts != AV_NOPTS_VALUE) - local_pkt.dts = av_rescale_q(pkt->dts, - src->streams[pkt->stream_index]->time_base, - dst->streams[dst_stream]->time_base); - if (pkt->duration) - local_pkt.duration = av_rescale_q(pkt->duration, - src->streams[pkt->stream_index]->time_base, - dst->streams[dst_stream]->time_base); + + av_packet_rescale_ts(&local_pkt, + src->streams[pkt->stream_index]->time_base, + dst->streams[dst_stream]->time_base); if (interleave) ret = av_interleaved_write_frame(dst, &local_pkt); else ret = av_write_frame(dst, &local_pkt); @@ -1344,43 +1346,65 @@ return ret; } -static int av_write_uncoded_frame_internal(AVFormatContext *s, int stream_index, - AVFrame *frame, int interleaved) +static void uncoded_frame_free(void *unused, uint8_t *data) +{ + av_frame_free((AVFrame **)data); + av_free(data); +} + +static int write_uncoded_frame_internal(AVFormatContext *s, int stream_index, + AVFrame *frame, int interleaved) { - AVPacket pkt, *pktp; + AVPacket *pkt = s->internal->pkt; av_assert0(s->oformat); - if (!s->oformat->write_uncoded_frame) + if (!s->oformat->write_uncoded_frame) { + av_frame_free(&frame); return AVERROR(ENOSYS); + } if (!frame) { - pktp = NULL; + pkt = NULL; } else { - pktp = &pkt; - av_init_packet(&pkt); - pkt.data = (void *)frame; - pkt.size = UNCODED_FRAME_PACKET_SIZE; - pkt.pts = - pkt.dts = frame->pts; - pkt.duration = frame->pkt_duration; - pkt.stream_index = stream_index; - pkt.flags |= AV_PKT_FLAG_UNCODED_FRAME; + size_t bufsize = sizeof(frame) + AV_INPUT_BUFFER_PADDING_SIZE; + AVFrame **framep = av_mallocz(bufsize); + + if (!framep) + goto fail; + av_packet_unref(pkt); + pkt->buf = av_buffer_create((void *)framep, bufsize, + uncoded_frame_free, NULL, 0); + if (!pkt->buf) { + av_free(framep); + fail: + av_frame_free(&frame); + return AVERROR(ENOMEM); + } + *framep = frame; + + pkt->data = (void *)framep; + pkt->size = sizeof(frame); + pkt->pts = + pkt->dts = frame->pts; + pkt->duration = frame->pkt_duration; + pkt->stream_index = stream_index; + pkt->flags |= AV_PKT_FLAG_UNCODED_FRAME; } - return interleaved ? av_interleaved_write_frame(s, pktp) : - av_write_frame(s, pktp); + return interleaved ? av_interleaved_write_frame(s, pkt) : + av_write_frame(s, pkt); } int av_write_uncoded_frame(AVFormatContext *s, int stream_index, AVFrame *frame) { - return av_write_uncoded_frame_internal(s, stream_index, frame, 0); + return write_uncoded_frame_internal(s, stream_index, frame, 0); } int av_interleaved_write_uncoded_frame(AVFormatContext *s, int stream_index, AVFrame *frame) { - return av_write_uncoded_frame_internal(s, stream_index, frame, 1); + return write_uncoded_frame_internal(s, stream_index, frame, 1); } int av_write_uncoded_frame_query(AVFormatContext *s, int stream_index) diff -Nru ffmpeg-4.2.2/libavformat/mvdec.c ffmpeg-4.4/libavformat/mvdec.c --- ffmpeg-4.2.2/libavformat/mvdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mvdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -159,7 +159,10 @@ st->codecpar->sample_rate = var_read_int(pb, size); avpriv_set_pts_info(st, 33, 1, st->codecpar->sample_rate); } else if (!strcmp(name, "SAMPLE_WIDTH")) { - st->codecpar->bits_per_coded_sample = var_read_int(pb, size) * 8; + uint64_t bpc = var_read_int(pb, size) * (uint64_t)8; + if (bpc > 16) + return AVERROR_INVALIDDATA; + st->codecpar->bits_per_coded_sample = bpc; } else return AVERROR_INVALIDDATA; @@ -210,8 +213,12 @@ st->codecpar->width = var_read_int(pb, size); } else if (!strcmp(name, "ORIENTATION")) { if (var_read_int(pb, size) == 1101) { - st->codecpar->extradata = av_strdup("BottomUp"); - st->codecpar->extradata_size = 9; + if (!st->codecpar->extradata) { + st->codecpar->extradata = av_strdup("BottomUp"); + if (!st->codecpar->extradata) + return AVERROR(ENOMEM); + st->codecpar->extradata_size = 9; + } } } else if (!strcmp(name, "Q_SPATIAL") || !strcmp(name, "Q_TEMPORAL")) { var_read_metadata(avctx, name, size); @@ -264,9 +271,11 @@ uint32_t pos = avio_rb32(pb); uint32_t size = avio_rb32(pb); avio_skip(pb, 8); + if (avio_feof(pb)) + return ; av_add_index_entry(st, pos, timestamp, size, 0, AVINDEX_KEYFRAME); if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - timestamp += size / (st->codecpar->channels * 2); + timestamp += size / (st->codecpar->channels * 2LL); } else { timestamp++; } @@ -353,7 +362,7 @@ avio_skip(pb, 8); av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME); av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME); - timestamp += asize / (ast->codecpar->channels * 2); + timestamp += asize / (ast->codecpar->channels * 2LL); } } else if (!version && avio_rb16(pb) == 3) { avio_skip(pb, 4); @@ -361,6 +370,12 @@ if ((ret = read_table(avctx, NULL, parse_global_var)) < 0) return ret; + if (mv->nb_audio_tracks < 0 || mv->nb_video_tracks < 0 || + (mv->nb_audio_tracks == 0 && mv->nb_video_tracks == 0)) { + av_log(avctx, AV_LOG_ERROR, "Stream count is invalid.\n"); + return AVERROR_INVALIDDATA; + } + if (mv->nb_audio_tracks > 1) { avpriv_request_sample(avctx, "Multiple audio streams support"); return AVERROR_PATCHWELCOME; diff -Nru ffmpeg-4.2.2/libavformat/mvi.c ffmpeg-4.4/libavformat/mvi.c --- ffmpeg-4.2.2/libavformat/mvi.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/mvi.c 2021-04-08 21:28:40.000000000 +0000 @@ -45,6 +45,7 @@ AVIOContext *pb = s->pb; AVStream *ast, *vst; unsigned int version, frames_count, msecs_per_frame, player_version; + int ret; ast = avformat_new_stream(s, NULL); if (!ast) @@ -54,8 +55,8 @@ if (!vst) return AVERROR(ENOMEM); - if (ff_alloc_extradata(vst->codecpar, 2)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(vst->codecpar, 2)) < 0) + return ret; version = avio_r8(pb); vst->codecpar->extradata[0] = avio_r8(pb); @@ -93,7 +94,7 @@ vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; vst->codecpar->codec_id = AV_CODEC_ID_MOTIONPIXELS; - mvi->get_int = (vst->codecpar->width * vst->codecpar->height < (1 << 16)) ? avio_rl16 : avio_rl24; + mvi->get_int = (vst->codecpar->width * (int64_t)vst->codecpar->height < (1 << 16)) ? avio_rl16 : avio_rl24; mvi->audio_frame_size = ((uint64_t)mvi->audio_data_size << MVI_FRAC_BITS) / frames_count; if (mvi->audio_frame_size <= 1 << MVI_FRAC_BITS - 1) { @@ -119,9 +120,15 @@ mvi->video_frame_size = (mvi->get_int)(pb); if (mvi->audio_size_left == 0) return AVERROR(EIO); + if (mvi->audio_size_counter + 512 > UINT64_MAX - mvi->audio_frame_size || + mvi->audio_size_counter + 512 + mvi->audio_frame_size >= ((uint64_t)INT32_MAX) << MVI_FRAC_BITS) + return AVERROR_INVALIDDATA; + count = (mvi->audio_size_counter + mvi->audio_frame_size + 512) >> MVI_FRAC_BITS; if (count > mvi->audio_size_left) count = mvi->audio_size_left; + if ((int64_t)count << MVI_FRAC_BITS > INT_MAX) + return AVERROR_INVALIDDATA; if ((ret = av_get_packet(pb, pkt, count)) < 0) return ret; pkt->stream_index = MVI_AUDIO_STREAM_INDEX; diff -Nru ffmpeg-4.2.2/libavformat/mxf.c ffmpeg-4.4/libavformat/mxf.c --- ffmpeg-4.2.2/libavformat/mxf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mxf.c 2021-04-08 21:28:40.000000000 +0000 @@ -22,6 +22,8 @@ #include "libavutil/common.h" #include "mxf.h" +const uint8_t ff_mxf_random_index_pack_key[16] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x11,0x01,0x00 }; + /** * SMPTE RP224 http://www.smpte-ra.org/mdd/index.html */ @@ -86,6 +88,55 @@ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, 0 }, }; +const MXFCodecUL ff_mxf_color_primaries_uls[] = { + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x03,0x01,0x00,0x00 }, 14, AVCOL_PRI_SMPTE170M }, /* SMPTE 170M */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x03,0x02,0x00,0x00 }, 14, AVCOL_PRI_BT470BG }, /* ITU-R BT.470 PAL */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x03,0x03,0x00,0x00 }, 14, AVCOL_PRI_BT709 }, /* ITU-R BT.709 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x03,0x04,0x00,0x00 }, 14, AVCOL_PRI_BT2020 }, /* ITU-R BT.2020 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x03,0x05,0x00,0x00 }, 14, AVCOL_PRI_SMPTE428 }, /* SMPTE-DC28 DCDM */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x03,0x06,0x00,0x00 }, 14, AVCOL_PRI_SMPTE432 }, /* P3D65 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x03,0x08,0x00,0x00 }, 14, AVCOL_PRI_SMPTE428 }, /* Cinema Mezzanine */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x03,0x0a,0x00,0x00 }, 14, AVCOL_PRI_SMPTE431 }, /* P3DCI */ + /* alternate mappings for encoding */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x03,0x01,0x00,0x00 }, 14, AVCOL_PRI_SMPTE240M }, /* = AVCOL_PRI_SMPTE170M */ + + { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AVCOL_PRI_UNSPECIFIED }, +}; + +const MXFCodecUL ff_mxf_color_trc_uls[] = { + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x01,0x00,0x00 }, 14, AVCOL_TRC_GAMMA22 }, /* ITU-R BT.470 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x02,0x00,0x00 }, 14, AVCOL_TRC_BT709 }, /* ITU-R BT.709 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x03,0x00,0x00 }, 14, AVCOL_TRC_SMPTE240M }, /* SMPTE 240M */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x04,0x00,0x00 }, 14, AVCOL_TRC_BT709 }, /* SMPTE 274/296M (must appear after ITU-R BT.709) */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x01,0x05,0x00,0x00 }, 14, AVCOL_TRC_BT1361_ECG }, /* ITU-R BT.1361 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x01,0x06,0x00,0x00 }, 14, AVCOL_TRC_LINEAR }, /* Linear */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x08,0x04,0x01,0x01,0x01,0x01,0x07,0x00,0x00 }, 14, AVCOL_TRC_SMPTE428 }, /* SMPTE-DC28 DCDM */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x01,0x08,0x00,0x00 }, 14, AVCOL_TRC_IEC61966_2_4 }, /* IEC 61966-2-4 xvYCC */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0E,0x04,0x01,0x01,0x01,0x01,0x09,0x00,0x00 }, 14, AVCOL_TRC_BT2020_10 }, /* ITU-R BT.2020 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x01,0x0A,0x00,0x00 }, 14, AVCOL_TRC_SMPTE2084 }, /* SMPTE ST 2084 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x01,0x0B,0x00,0x00 }, 14, AVCOL_TRC_ARIB_STD_B67 }, /* Hybrid Log-Gamma OETF */ + /* alternate mappings for encoding */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x01,0x00,0x00 }, 14, AVCOL_TRC_GAMMA28 }, /* = AVCOL_TRC_GAMMA22 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x02,0x00,0x00 }, 14, AVCOL_TRC_SMPTE170M }, /* = AVCOL_TRC_BT709 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0E,0x04,0x01,0x01,0x01,0x01,0x09,0x00,0x00 }, 14, AVCOL_TRC_BT2020_12 }, /* = AVCOL_TRC_BT2020_10 */ + + { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AVCOL_TRC_UNSPECIFIED }, +}; + +/* aka Coding Equations */ +const MXFCodecUL ff_mxf_color_space_uls[] = { + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x02,0x01,0x00,0x00 }, 14, AVCOL_SPC_BT470BG }, /* ITU-R BT.601 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x02,0x02,0x00,0x00 }, 14, AVCOL_SPC_BT709 }, /* ITU-R BT.709 */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x02,0x03,0x00,0x00 }, 14, AVCOL_SPC_SMPTE240M }, /* SMPTE 240M */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x02,0x04,0x00,0x00 }, 14, AVCOL_SPC_YCGCO }, /* YCgCo */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x02,0x05,0x00,0x00 }, 14, AVCOL_SPC_RGB }, /* GBR */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x02,0x06,0x00,0x00 }, 14, AVCOL_SPC_BT2020_NCL }, /* ITU-R BT.2020 Non-Constant Luminance */ + /* alternate mappings for encoding */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x02,0x03,0x00,0x00 }, 14, AVCOL_SPC_SMPTE170M }, /* = AVCOL_SPC_SMPTE240M */ + + { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AVCOL_SPC_UNSPECIFIED }, +}; + static const struct { enum AVPixelFormat pix_fmt; const char data[16]; @@ -131,61 +182,38 @@ return -1; } -static const MXFSamplesPerFrame mxf_spf[] = { - { { 1001, 24000 }, { 2002, 0, 0, 0, 0, 0 } }, // FILM 23.976 - { { 1, 24}, { 2000, 0, 0, 0, 0, 0 } }, // FILM 24 - { { 1001, 30000 }, { 1602, 1601, 1602, 1601, 1602, 0 } }, // NTSC 29.97 - { { 1001, 60000 }, { 801, 801, 800, 801, 801, 0 } }, // NTSC 59.94 - { { 1, 25 }, { 1920, 0, 0, 0, 0, 0 } }, // PAL 25 - { { 1, 50 }, { 960, 0, 0, 0, 0, 0 } }, // PAL 50 - { { 1, 60 }, { 800, 0, 0, 0, 0, 0 } }, -}; - -static const AVRational mxf_time_base[] = { - { 1001, 24000 }, - { 1, 24}, - { 1001, 30000 }, - { 1001, 60000 }, - { 1, 25 }, - { 1, 50 }, - { 1, 60 }, - { 0, 0} -}; - -const MXFSamplesPerFrame *ff_mxf_get_samples_per_frame(AVFormatContext *s, - AVRational time_base) -{ - int idx = av_find_nearest_q_idx(time_base, mxf_time_base); - AVRational diff = av_sub_q(time_base, mxf_time_base[idx]); - - diff.num = FFABS(diff.num); - - if (av_cmp_q(diff, (AVRational){1, 1000}) >= 0) - return NULL; - - if (av_cmp_q(time_base, mxf_time_base[idx])) - av_log(s, AV_LOG_WARNING, - "%d/%d input time base matched %d/%d container time base\n", - time_base.num, time_base.den, - mxf_spf[idx].time_base.num, - mxf_spf[idx].time_base.den); - - return &mxf_spf[idx]; -} - -static const int mxf_content_package_rates[] = { - 3, 2, 7, 13, 4, 10, 12, +/** + * See SMPTE 326M-2000 Section 7.2 Content package rate + * MXFContentPackageRate->rate is bits b5..b0. + */ +static const MXFContentPackageRate mxf_content_package_rates[] = { + { 2, { 1, 24 } }, + { 3, { 1001, 24000 } }, + { 4, { 1, 25 } }, + { 6, { 1, 30 } }, + { 7, { 1001, 30000 } }, + { 8, { 1 , 48 } }, + { 9, { 1001, 48000 } }, + { 10, { 1, 50 } }, + { 12, { 1, 60 } }, + { 13, { 1001, 60000 } }, + { 14, { 1, 72 } }, + { 15, { 1001, 72000 } }, + { 16, { 1, 75 } }, + { 18, { 1, 90 } }, + { 19, { 1001, 90000 } }, + { 20, { 1, 96 } }, + { 21, { 1001, 96000 } }, + { 22, { 1, 100 } }, + { 24, { 1, 120 } }, + { 25, { 1001, 120000} }, + {0} }; int ff_mxf_get_content_package_rate(AVRational time_base) { - int idx = av_find_nearest_q_idx(time_base, mxf_time_base); - AVRational diff = av_sub_q(time_base, mxf_time_base[idx]); - - diff.num = FFABS(diff.num); - - if (av_cmp_q(diff, (AVRational){1, 1000}) >= 0) - return -1; - - return mxf_content_package_rates[idx]; + for (int i = 0; mxf_content_package_rates[i].rate; i++) + if (!av_cmp_q(time_base, mxf_content_package_rates[i].tb)) + return mxf_content_package_rates[i].rate; + return 0; } diff -Nru ffmpeg-4.2.2/libavformat/mxfdec.c ffmpeg-4.4/libavformat/mxfdec.c --- ffmpeg-4.2.2/libavformat/mxfdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/mxfdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -28,6 +28,7 @@ * SMPTE 381M Mapping MPEG Streams into the MXF Generic Container * SMPTE 382M Mapping AES3 and Broadcast Wave Audio into the MXF Generic Container * SMPTE 383M Mapping DV-DIF Data to the MXF Generic Container + * SMPTE 2067-21 Interoperable Master Format — Application #2E * * Principle * Search for Track numbers which will identify essence element KLV packets. @@ -47,6 +48,7 @@ #include "libavutil/aes.h" #include "libavutil/avassert.h" +#include "libavutil/mastering_display_metadata.h" #include "libavutil/mathematics.h" #include "libavcodec/bytestream.h" #include "libavutil/intreadwrite.h" @@ -131,7 +133,7 @@ uint8_t origin; } MXFSequence; -typedef struct MXFTrack { +typedef struct MXFTimecodeComponent { UID uid; enum MXFMetadataSetType type; int drop_frame; @@ -199,6 +201,9 @@ int bits_per_sample; int64_t duration; /* ContainerDuration optional property */ unsigned int component_depth; + unsigned int black_ref_level; + unsigned int white_ref_level; + unsigned int color_range; unsigned int horiz_subsampling; unsigned int vert_subsampling; UID *sub_descriptors_refs; @@ -207,6 +212,12 @@ uint8_t *extradata; int extradata_size; enum AVPixelFormat pix_fmt; + UID color_primaries_ul; + UID color_trc_ul; + UID color_space_ul; + AVMasteringDisplayMetadata *mastering; + AVContentLightMetadata *coll; + size_t coll_size; } MXFDescriptor; typedef struct MXFIndexTableSegment { @@ -312,16 +323,26 @@ static const uint8_t mxf_system_item_key_cp[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x03,0x01,0x04 }; static const uint8_t mxf_system_item_key_gc[] = { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x03,0x01,0x14 }; static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 }; +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 }; static const uint8_t mxf_encrypted_essence_container[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0b,0x01,0x00 }; -static const uint8_t mxf_random_index_pack_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x11,0x01,0x00 }; static const uint8_t mxf_sony_mpeg4_extradata[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0e,0x06,0x06,0x02,0x02,0x01,0x00,0x00 }; static const uint8_t mxf_avid_project_name[] = { 0xa5,0xfb,0x7b,0x25,0xf6,0x15,0x94,0xb9,0x62,0xfc,0x37,0x17,0x49,0x2d,0x42,0xbf }; static const uint8_t mxf_jp2k_rsiz[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }; static const uint8_t mxf_indirect_value_utf16le[] = { 0x4c,0x00,0x02,0x10,0x01,0x00,0x00,0x00,0x00,0x06,0x0e,0x2b,0x34,0x01,0x04,0x01,0x01 }; static const uint8_t mxf_indirect_value_utf16be[] = { 0x42,0x01,0x10,0x02,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x2b,0x34,0x01,0x04,0x01,0x01 }; +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_mastering_display_prefix[13] = { FF_MXF_MasteringDisplay_PREFIX }; +static const uint8_t mxf_mastering_display_uls[4][16] = { + FF_MXF_MasteringDisplayPrimaries, + FF_MXF_MasteringDisplayWhitePointChromaticity, + FF_MXF_MasteringDisplayMaximumLuminance, + FF_MXF_MasteringDisplayMinimumLuminance, +}; #define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y))) @@ -330,9 +351,10 @@ MXFIndexTableSegment *seg; switch ((*ctx)->type) { case Descriptor: - av_freep(&((MXFDescriptor *)*ctx)->extradata); - break; case MultipleDescriptor: + av_freep(&((MXFDescriptor *)*ctx)->extradata); + av_freep(&((MXFDescriptor *)*ctx)->mastering); + av_freep(&((MXFDescriptor *)*ctx)->coll); av_freep(&((MXFDescriptor *)*ctx)->sub_descriptors_refs); break; case Sequence: @@ -362,8 +384,9 @@ default: break; } - if (freectx) - av_freep(ctx); + if (freectx) { + av_freep(ctx); + } } static int64_t klv_decode_ber_length(AVIOContext *pb) @@ -821,15 +844,17 @@ return 0; } -static int mxf_add_metadata_set(MXFContext *mxf, void *metadata_set) +static int mxf_add_metadata_set(MXFContext *mxf, MXFMetadataSet **metadata_set) { MXFMetadataSet **tmp; tmp = av_realloc_array(mxf->metadata_sets, mxf->metadata_sets_count + 1, sizeof(*mxf->metadata_sets)); - if (!tmp) + if (!tmp) { + mxf_free_metadataset(metadata_set, 1); return AVERROR(ENOMEM); + } mxf->metadata_sets = tmp; - mxf->metadata_sets[mxf->metadata_sets_count] = metadata_set; + mxf->metadata_sets[mxf->metadata_sets_count] = *metadata_set; mxf->metadata_sets_count++; return 0; } @@ -847,6 +872,7 @@ static int mxf_read_strong_ref_array(AVIOContext *pb, UID **refs, int *count) { *count = avio_rb32(pb); + av_free(*refs); *refs = av_calloc(*count, sizeof(UID)); if (!*refs) { *count = 0; @@ -866,6 +892,7 @@ return AVERROR(EINVAL); buf_size = size + size / 2 + 1; + av_free(*str); *str = av_malloc(buf_size); if (!*str) return AVERROR(ENOMEM); @@ -899,10 +926,8 @@ case 0x1901: if (mxf->packages_refs) av_log(mxf->fc, AV_LOG_VERBOSE, "Multiple packages_refs\n"); - av_free(mxf->packages_refs); return mxf_read_strong_ref_array(pb, &mxf->packages_refs, &mxf->packages_count); case 0x1902: - av_free(mxf->essence_container_data_refs); return mxf_read_strong_ref_array(pb, &mxf->essence_container_data_refs, &mxf->essence_container_data_count); } return 0; @@ -1069,9 +1094,9 @@ if(segment->nb_index_entries && length < 11) return AVERROR_INVALIDDATA; - if (!(segment->temporal_offset_entries=av_calloc(segment->nb_index_entries, sizeof(*segment->temporal_offset_entries))) || - !(segment->flag_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->flag_entries))) || - !(segment->stream_offset_entries = av_calloc(segment->nb_index_entries, sizeof(*segment->stream_offset_entries)))) { + if (!FF_ALLOC_TYPED_ARRAY(segment->temporal_offset_entries, segment->nb_index_entries) || + !FF_ALLOC_TYPED_ARRAY(segment->flag_entries , segment->nb_index_entries) || + !FF_ALLOC_TYPED_ARRAY(segment->stream_offset_entries , segment->nb_index_entries)) { av_freep(&segment->temporal_offset_entries); av_freep(&segment->flag_entries); return AVERROR(ENOMEM); @@ -1198,15 +1223,33 @@ descriptor->aspect_ratio.num = avio_rb32(pb); descriptor->aspect_ratio.den = avio_rb32(pb); break; + case 0x3210: + avio_read(pb, descriptor->color_trc_ul, 16); + break; case 0x3212: descriptor->field_dominance = avio_r8(pb); break; + case 0x3219: + avio_read(pb, descriptor->color_primaries_ul, 16); + break; + case 0x321A: + avio_read(pb, descriptor->color_space_ul, 16); + break; case 0x3301: descriptor->component_depth = avio_rb32(pb); break; case 0x3302: descriptor->horiz_subsampling = avio_rb32(pb); break; + case 0x3304: + descriptor->black_ref_level = avio_rb32(pb); + break; + case 0x3305: + descriptor->white_ref_level = avio_rb32(pb); + break; + case 0x3306: + descriptor->color_range = avio_rb32(pb); + break; case 0x3308: descriptor->vert_subsampling = avio_rb32(pb); break; @@ -1245,6 +1288,55 @@ rsiz == FF_PROFILE_JPEG2000_DCINEMA_4K) descriptor->pix_fmt = AV_PIX_FMT_XYZ12; } + if (IS_KLV_KEY(uid, mxf_mastering_display_prefix)) { + if (!descriptor->mastering) { + descriptor->mastering = av_mastering_display_metadata_alloc(); + if (!descriptor->mastering) + return AVERROR(ENOMEM); + } + if (IS_KLV_KEY(uid, mxf_mastering_display_uls[0])) { + for (int i = 0; i < 3; i++) { + /* Order: large x, large y, other (i.e. RGB) */ + descriptor->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), FF_MXF_MASTERING_CHROMA_DEN); + descriptor->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), FF_MXF_MASTERING_CHROMA_DEN); + } + /* Check we have seen mxf_mastering_display_white_point_chromaticity */ + if (descriptor->mastering->white_point[0].den != 0) + descriptor->mastering->has_primaries = 1; + } + if (IS_KLV_KEY(uid, mxf_mastering_display_uls[1])) { + descriptor->mastering->white_point[0] = av_make_q(avio_rb16(pb), FF_MXF_MASTERING_CHROMA_DEN); + descriptor->mastering->white_point[1] = av_make_q(avio_rb16(pb), FF_MXF_MASTERING_CHROMA_DEN); + /* Check we have seen mxf_mastering_display_primaries */ + if (descriptor->mastering->display_primaries[0][0].den != 0) + descriptor->mastering->has_primaries = 1; + } + if (IS_KLV_KEY(uid, mxf_mastering_display_uls[2])) { + descriptor->mastering->max_luminance = av_make_q(avio_rb32(pb), FF_MXF_MASTERING_LUMA_DEN); + /* Check we have seen mxf_mastering_display_minimum_luminance */ + if (descriptor->mastering->min_luminance.den != 0) + descriptor->mastering->has_luminance = 1; + } + if (IS_KLV_KEY(uid, mxf_mastering_display_uls[3])) { + descriptor->mastering->min_luminance = av_make_q(avio_rb32(pb), FF_MXF_MASTERING_LUMA_DEN); + /* Check we have seen mxf_mastering_display_maximum_luminance */ + if (descriptor->mastering->max_luminance.den != 0) + descriptor->mastering->has_luminance = 1; + } + } + if (IS_KLV_KEY(uid, mxf_apple_coll_prefix)) { + if (!descriptor->coll) { + descriptor->coll = av_content_light_metadata_alloc(&descriptor->coll_size); + if (!descriptor->coll) + return AVERROR(ENOMEM); + } + if (IS_KLV_KEY(uid, mxf_apple_coll_max_cll)) { + descriptor->coll->MaxCLL = avio_rb16(pb); + } + if (IS_KLV_KEY(uid, mxf_apple_coll_max_fall)) { + descriptor->coll->MaxFALL = avio_rb16(pb); + } + } break; } return 0; @@ -1886,6 +1978,15 @@ return 0; } +static int mxf_version_to_str(uint16_t major, uint16_t minor, uint16_t tertiary, + uint16_t patch, uint16_t release, char **str) +{ + *str = av_asprintf("%d.%d.%d.%d.%d", major, minor, tertiary, patch, release); + if (!*str) + return AVERROR(ENOMEM); + return 0; +} + static int mxf_add_umid_metadata(AVDictionary **pm, const char *key, MXFPackage* package) { char *str; @@ -2017,7 +2118,7 @@ static int mxf_parse_package_comments(MXFContext *mxf, AVDictionary **pm, MXFPackage *package) { MXFTaggedValue *tag; - int size, i; + int i; char *key = NULL; for (i = 0; i < package->comment_count; i++) { @@ -2025,12 +2126,10 @@ if (!tag || !tag->name || !tag->value) continue; - size = strlen(tag->name) + 8 + 1; - key = av_mallocz(size); + key = av_asprintf("comment_%s", tag->name); if (!key) return AVERROR(ENOMEM); - snprintf(key, size, "comment_%s", tag->name); av_dict_set(pm, key, tag->value, AV_DICT_DONT_STRDUP_KEY); } return 0; @@ -2144,6 +2243,30 @@ return 0; } +static enum AVColorRange mxf_get_color_range(MXFContext *mxf, MXFDescriptor *descriptor) +{ + if (descriptor->black_ref_level || descriptor->white_ref_level || descriptor->color_range) { + /* CDCI range metadata */ + if (!descriptor->component_depth) + return AVCOL_RANGE_UNSPECIFIED; + if (descriptor->black_ref_level == 0 && + 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 && + 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)) + return AVCOL_RANGE_MPEG; + avpriv_request_sample(mxf->fc, "Unrecognized CDCI color range (color diff range %d, b %d, w %d, depth %d)", + descriptor->color_range, descriptor->black_ref_level, + descriptor->white_ref_level, descriptor->component_depth); + } + + return AVCOL_RANGE_UNSPECIFIED; +} + static int mxf_parse_structural_metadata(MXFContext *mxf) { MXFPackage *material_package = NULL; @@ -2478,7 +2601,27 @@ av_dict_set_int(&st->metadata, "source_track_origin", source_track->sequence->origin, 0); } if (descriptor->aspect_ratio.num && descriptor->aspect_ratio.den) - st->display_aspect_ratio = descriptor->aspect_ratio; + st->internal->display_aspect_ratio = descriptor->aspect_ratio; + st->codecpar->color_range = mxf_get_color_range(mxf, descriptor); + st->codecpar->color_primaries = mxf_get_codec_ul(ff_mxf_color_primaries_uls, &descriptor->color_primaries_ul)->id; + st->codecpar->color_trc = mxf_get_codec_ul(ff_mxf_color_trc_uls, &descriptor->color_trc_ul)->id; + st->codecpar->color_space = mxf_get_codec_ul(ff_mxf_color_space_uls, &descriptor->color_space_ul)->id; + if (descriptor->mastering) { + ret = av_stream_add_side_data(st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, + (uint8_t *)descriptor->mastering, + sizeof(*descriptor->mastering)); + if (ret < 0) + goto fail_and_free; + descriptor->mastering = NULL; + } + if (descriptor->coll) { + ret = av_stream_add_side_data(st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL, + (uint8_t *)descriptor->coll, + descriptor->coll_size); + if (ret < 0) + goto fail_and_free; + descriptor->coll = NULL; + } } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { container_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul); /* Only overwrite existing codec ID if it is unset or A-law, which is the default according to SMPTE RP 224. */ @@ -2605,6 +2748,17 @@ av_dict_set(&s->metadata, name, str, AV_DICT_DONT_STRDUP_VAL); \ } while (0) +#define SET_VERSION_METADATA(pb, name, major, minor, tertiary, patch, release, str) do { \ + major = avio_rb16(pb); \ + minor = avio_rb16(pb); \ + tertiary = avio_rb16(pb); \ + patch = avio_rb16(pb); \ + release = avio_rb16(pb); \ + if ((ret = mxf_version_to_str(major, minor, tertiary, patch, release, &str)) < 0) \ + return ret; \ + av_dict_set(&s->metadata, name, str, AV_DICT_DONT_STRDUP_VAL); \ +} while (0) + #define SET_UID_METADATA(pb, name, var, str) do { \ avio_read(pb, var, 16); \ if ((ret = mxf_uid_to_str(var, &str)) < 0) \ @@ -2626,6 +2780,7 @@ UID uid = { 0 }; char *str = NULL; uint64_t ts; + uint16_t major, minor, tertiary, patch, release; switch (tag) { case 0x3C01: SET_STR_METADATA(pb, "company_name", str); @@ -2633,6 +2788,9 @@ case 0x3C02: SET_STR_METADATA(pb, "product_name", str); break; + case 0x3C03: + SET_VERSION_METADATA(pb, "product_version_num", major, minor, tertiary, patch, release, str); + break; case 0x3C04: SET_STR_METADATA(pb, "product_version", str); break; @@ -2642,6 +2800,9 @@ case 0x3C06: SET_TS_METADATA(pb, "modification_date", ts, str); break; + case 0x3C07: + SET_VERSION_METADATA(pb, "toolkit_version_num", major, minor, tertiary, patch, release, str); + break; case 0x3C08: SET_STR_METADATA(pb, "application_platform", str); break; @@ -2712,6 +2873,7 @@ static int mxf_metadataset_init(MXFMetadataSet *ctx, enum MXFMetadataSetType type) { + ctx->type = type; switch (type){ case MultipleDescriptor: case Descriptor: @@ -2727,18 +2889,33 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadFunc *read_child, int ctx_size, enum MXFMetadataSetType type) { AVIOContext *pb = mxf->fc->pb; - MXFMetadataSet *ctx = ctx_size ? av_mallocz(ctx_size) : mxf; uint64_t klv_end = avio_tell(pb) + klv->length; + MXFMetadataSet *meta; + void *ctx; - if (!ctx) - return AVERROR(ENOMEM); - mxf_metadataset_init(ctx, type); + if (ctx_size) { + meta = av_mallocz(ctx_size); + if (!meta) + return AVERROR(ENOMEM); + ctx = meta; + mxf_metadataset_init(meta, type); + } else { + meta = NULL; + ctx = mxf; + } while (avio_tell(pb) + 4 < klv_end && !avio_feof(pb)) { int ret; int tag = avio_rb16(pb); int size = avio_rb16(pb); /* KLV specified by 0x53 */ - uint64_t next = avio_tell(pb) + size; + int64_t next = avio_tell(pb); UID uid = {0}; + if (next < 0 || next > INT64_MAX - size) { + if (meta) { + mxf_free_metadataset(&meta, 1); + } + return next < 0 ? next : AVERROR_INVALIDDATA; + } + next += size; av_log(mxf->fc, AV_LOG_TRACE, "local tag %#04x size %d\n", tag, size); if (!size) { /* ignore empty tag, needed for some files with empty UMID tag */ @@ -2756,20 +2933,20 @@ } } } - if (ctx_size && tag == 0x3C0A) { - avio_read(pb, ctx->uid, 16); + if (meta && tag == 0x3C0A) { + avio_read(pb, meta->uid, 16); } else if ((ret = read_child(ctx, pb, tag, size, uid, -1)) < 0) { - if (ctx_size) - mxf_free_metadataset(&ctx, 1); + if (meta) { + mxf_free_metadataset(&meta, 1); + } return ret; } /* Accept the 64k local set limit being exceeded (Avid). Don't accept * it extending past the end of the KLV though (zzuf5.mxf). */ if (avio_tell(pb) > klv_end) { - if (ctx_size) { - ctx->type = type; - mxf_free_metadataset(&ctx, 1); + if (meta) { + mxf_free_metadataset(&meta, 1); } av_log(mxf->fc, AV_LOG_ERROR, @@ -2779,8 +2956,7 @@ } else if (avio_tell(pb) <= next) /* only seek forward, else this can loop for a long time */ avio_seek(pb, next, SEEK_SET); } - if (ctx_size) ctx->type = type; - return ctx_size ? mxf_add_metadata_set(mxf, ctx) : 0; + return meta ? mxf_add_metadata_set(mxf, &meta) : 0; } /** @@ -3083,10 +3259,8 @@ if (!(segment = av_mallocz(sizeof(*segment)))) return AVERROR(ENOMEM); - if ((ret = mxf_add_metadata_set(mxf, segment))) { - mxf_free_metadataset((MXFMetadataSet**)&segment, 1); + if ((ret = mxf_add_metadata_set(mxf, (MXFMetadataSet**)&segment))) return ret; - } /* Make sure we have nonzero unique index_sid, body_sid will be ok, because * using the same SID for index is forbidden in MXF. */ @@ -3138,7 +3312,7 @@ goto end; avio_seek(s->pb, file_size - length, SEEK_SET); if (klv_read_packet(&klv, s->pb) < 0 || - !IS_KLV_KEY(klv.key, mxf_random_index_pack_key)) + !IS_KLV_KEY(klv.key, ff_mxf_random_index_pack_key)) goto end; if (klv.next_klv != file_size || klv.length <= 4 || (klv.length - 4) % 12) { av_log(s, AV_LOG_WARNING, "Invalid RIP KLV length\n"); @@ -3169,6 +3343,7 @@ if (!mxf_read_sync(s->pb, mxf_header_partition_pack_key, 14)) { av_log(s, AV_LOG_ERROR, "could not find header partition pack key\n"); + //goto fail should not be needed as no metadata sets will have been parsed yet return AVERROR_INVALIDDATA; } avio_seek(s->pb, -14, SEEK_CUR); @@ -3199,7 +3374,8 @@ if (!mxf->current_partition) { av_log(mxf->fc, AV_LOG_ERROR, "found essence prior to first PartitionPack\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } if (!mxf->current_partition->first_essence_klv.offset) @@ -3305,20 +3481,17 @@ static int64_t mxf_compute_sample_count(MXFContext *mxf, AVStream *st, int64_t edit_unit) { - int i, total = 0, size = 0; MXFTrack *track = st->priv_data; AVRational time_base = av_inv_q(track->edit_rate); AVRational sample_rate = av_inv_q(st->time_base); - const MXFSamplesPerFrame *spf = NULL; - int64_t sample_count; // For non-audio sample_count equals current edit unit if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) return edit_unit; - if ((sample_rate.num / sample_rate.den) == 48000) - spf = ff_mxf_get_samples_per_frame(mxf->fc, time_base); - if (!spf) { + if ((sample_rate.num / sample_rate.den) == 48000) { + return av_rescale_q(edit_unit, sample_rate, track->edit_rate); + } else { int remainder = (sample_rate.num * time_base.num) % (time_base.den * sample_rate.den); if (remainder) @@ -3329,20 +3502,6 @@ sample_rate.num, sample_rate.den); return av_rescale_q(edit_unit, sample_rate, track->edit_rate); } - - while (spf->samples_per_frame[size]) { - total += spf->samples_per_frame[size]; - size++; - } - - av_assert2(size); - - sample_count = (edit_unit / size) * (uint64_t)total; - for (i = 0; i < edit_unit % size; i++) { - sample_count += spf->samples_per_frame[i]; - } - - return sample_count; } /** @@ -3616,7 +3775,7 @@ AV_RN32(bufp+ 4) == AV_RN32(mxf_header_partition_pack_key+ 4) && AV_RN32(bufp+ 8) == AV_RN32(mxf_header_partition_pack_key+ 8) && AV_RN16(bufp+12) == AV_RN16(mxf_header_partition_pack_key+12)) - return AVPROBE_SCORE_MAX; + return bufp == p->buf ? AVPROBE_SCORE_MAX : AVPROBE_SCORE_MAX - 1; bufp ++; } else bufp += 10; diff -Nru ffmpeg-4.2.2/libavformat/mxfenc.c ffmpeg-4.4/libavformat/mxfenc.c --- ffmpeg-4.2.2/libavformat/mxfenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mxfenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -44,6 +44,7 @@ #include "libavutil/random_seed.h" #include "libavutil/timecode.h" #include "libavutil/avassert.h" +#include "libavutil/mastering_display_metadata.h" #include "libavutil/pixdesc.h" #include "libavutil/time_internal.h" #include "libavcodec/bytestream.h" @@ -52,7 +53,7 @@ #include "libavcodec/h264_ps.h" #include "libavcodec/golomb.h" #include "libavcodec/internal.h" -#include "audiointerleave.h" +#include "libavcodec/packet_internal.h" #include "avformat.h" #include "avio_internal.h" #include "internal.h" @@ -66,23 +67,19 @@ #define EDIT_UNITS_PER_BODY 250 #define KAG_SIZE 512 -typedef struct MXFLocalTagPair { - int local_tag; - UID uid; -} MXFLocalTagPair; - typedef struct MXFIndexEntry { - uint8_t flags; uint64_t offset; unsigned slice_offset; ///< offset of audio slice uint16_t temporal_ref; + uint8_t flags; } MXFIndexEntry; typedef struct MXFStreamContext { - AudioInterleaveContext aic; + int64_t pkt_cnt; ///< pkt counter for muxed packets UID track_essence_element_key; int index; ///< index in mxf_essence_container_uls table const UID *codec_ul; + const UID *container_ul; int order; ///< interleaving order if dts are equal int interlaced; ///< whether picture is interlaced int field_dominance; ///< tff=1, bff=2 @@ -122,29 +119,9 @@ INDEX_MPEG2 = 0, INDEX_AES3, INDEX_WAV, - INDEX_D10_625_50_50_VIDEO, - INDEX_D10_625_50_50_AUDIO, - INDEX_D10_525_60_50_VIDEO, - INDEX_D10_525_60_50_AUDIO, - INDEX_D10_625_50_40_VIDEO, - INDEX_D10_625_50_40_AUDIO, - INDEX_D10_525_60_40_VIDEO, - INDEX_D10_525_60_40_AUDIO, - INDEX_D10_625_50_30_VIDEO, - INDEX_D10_625_50_30_AUDIO, - INDEX_D10_525_60_30_VIDEO, - INDEX_D10_525_60_30_AUDIO, + INDEX_D10_VIDEO, + INDEX_D10_AUDIO, INDEX_DV, - INDEX_DV25_525_60, - INDEX_DV25_625_50, - INDEX_DV25_525_60_IEC, - INDEX_DV25_625_50_IEC, - INDEX_DV50_525_60, - INDEX_DV50_625_50, - INDEX_DV100_1080_60, - INDEX_DV100_1080_50, - INDEX_DV100_720_60, - INDEX_DV100_720_50, INDEX_DNXHD, INDEX_JPEG2000, INDEX_H264, @@ -188,118 +165,21 @@ { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x16,0x01,0x01,0x00 }, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, mxf_write_wav_desc }, - // D-10 625/50 PAL 50mb/s + // D-10 Video { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x05,0x01,0x01,0x00 }, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x01 }, mxf_write_cdci_desc }, + // D-10 Audio { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 }, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, mxf_write_generic_sound_desc }, - // D-10 525/60 NTSC 50mb/s - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x02,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x05,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x02 }, - mxf_write_cdci_desc }, - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x02,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, - mxf_write_generic_sound_desc }, - // D-10 625/50 PAL 40mb/s - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x03,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x05,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x03 }, - mxf_write_cdci_desc }, - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x03,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, - mxf_write_generic_sound_desc }, - // D-10 525/60 NTSC 40mb/s - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x04,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x05,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x04 }, - mxf_write_cdci_desc }, - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x04,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, - mxf_write_generic_sound_desc }, - // D-10 625/50 PAL 30mb/s - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x05,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x05,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x05 }, - mxf_write_cdci_desc }, - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x05,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, - mxf_write_generic_sound_desc }, - // D-10 525/60 NTSC 30mb/s - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x06,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x05,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x06 }, - mxf_write_cdci_desc }, - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x06,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, - mxf_write_generic_sound_desc }, - // DV Unknown + // DV { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x7F,0x01 }, { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 }, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x00,0x00,0x00 }, mxf_write_cdci_desc }, - - // DV25 525/60 - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x40,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x01,0x00 }, - mxf_write_cdci_desc }, - // DV25 625/50 - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x02,0x00 }, - mxf_write_cdci_desc }, - - // IEC DV25 525/60 - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x01,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x01,0x00 }, - mxf_write_cdci_desc }, - // IEC DV25 625/50 - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x02,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x02,0x00 }, - mxf_write_cdci_desc }, - - // DV50 525/60 - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x50,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x03,0x00 }, - mxf_write_cdci_desc }, - // DV50 625/50 - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x51,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x04,0x00 }, - mxf_write_cdci_desc }, - // DV100 1080/60 - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x60,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x05,0x00 }, - mxf_write_cdci_desc }, - // DV100 1080/50 - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x61,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x06,0x00 }, - mxf_write_cdci_desc }, - // DV100 720/60 - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x62,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x07,0x00 }, - mxf_write_cdci_desc }, - // DV100 720/50 - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x63,0x01 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x08,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 }, @@ -331,37 +211,23 @@ NULL }, }; -typedef struct MXFContext { - AVClass *av_class; - int64_t footer_partition_offset; - int essence_container_count; - AVRational time_base; - int header_written; - MXFIndexEntry *index_entries; - unsigned edit_units_count; - uint64_t timestamp; ///< timestamp, as year(16),month(8),day(8),hour(8),minutes(8),msec/4(8) - uint8_t slice_count; ///< index slice count minus 1 (1 if no audio, 0 otherwise) - int last_indexed_edit_unit; - uint64_t *body_partition_offset; - unsigned body_partitions_count; - int last_key_index; ///< index of last key frame - uint64_t duration; - AVTimecode tc; ///< timecode context - AVStream *timecode_track; - int timecode_base; ///< rounded time code base (25 or 30) - int edit_unit_byte_count; ///< fixed edit unit byte count - int content_package_rate; ///< content package rate in system element, see SMPTE 326M - uint64_t body_offset; - uint32_t instance_number; - uint8_t umid[16]; ///< unique material identifier - int channel_count; - int signal_standard; - uint32_t tagged_value_count; - AVRational audio_edit_rate; - int store_user_comments; - int track_instance_count; // used to generate MXFTrack uuids - int cbr_index; ///< use a constant bitrate index -} MXFContext; +static const UID mxf_d10_codec_uls[] = { + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x01 }, // D-10 625/50 PAL 50mb/s + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x02 }, // D-10 525/50 NTSC 50mb/s + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x03 }, // D-10 625/50 PAL 40mb/s + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x04 }, // D-10 525/50 NTSC 40mb/s + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x05 }, // D-10 625/50 PAL 30mb/s + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x06 }, // D-10 525/50 NTSC 30mb/s +}; + +static const UID mxf_d10_container_uls[] = { + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, // D-10 625/50 PAL 50mb/s + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x02,0x01 }, // D-10 525/50 NTSC 50mb/s + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x03,0x01 }, // D-10 625/50 PAL 40mb/s + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x04,0x01 }, // D-10 525/50 NTSC 40mb/s + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x05,0x01 }, // D-10 625/50 PAL 30mb/s + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x06,0x01 }, // D-10 525/50 NTSC 30mb/s +}; static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd }; static const uint8_t umid_ul[] = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13 }; @@ -374,7 +240,6 @@ static const uint8_t footer_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x04,0x04,0x00 }; // ClosedComplete static const uint8_t primer_pack_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x05,0x01,0x00 }; static const uint8_t index_table_segment_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 }; -static const uint8_t random_index_pack_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x11,0x01,0x00 }; static const uint8_t header_open_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }; // OpenIncomplete static const uint8_t header_closed_partition_key[] = { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0D,0x01,0x02,0x01,0x01,0x02,0x04,0x00 }; // ClosedComplete static const uint8_t klv_fill_key[] = { 0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x01,0x02,0x10,0x01,0x00,0x00,0x00 }; @@ -465,6 +330,8 @@ { 0x3217, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x03,0x02,0x07,0x00,0x00,0x00}}, /* Display F2 offset */ { 0x320E, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x00,0x00,0x00}}, /* Aspect Ratio */ { 0x3210, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x02,0x01,0x01,0x01,0x02,0x00}}, /* Transfer characteristic */ + { 0x321A, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x02,0x01,0x01,0x03,0x01,0x00}}, /* Coding Equations (color space) */ + { 0x3219, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x09,0x04,0x01,0x02,0x01,0x01,0x06,0x01,0x00}}, /* Color Primaries */ { 0x3213, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x18,0x01,0x02,0x00,0x00,0x00,0x00}}, /* Image Start Offset */ { 0x3214, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x18,0x01,0x03,0x00,0x00,0x00,0x00}}, /* Image End Offset */ { 0x3201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x06,0x01,0x00,0x00,0x00,0x00}}, /* Picture Essence Coding */ @@ -505,20 +372,56 @@ // Wave Audio Essence Descriptor { 0x3D09, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x03,0x03,0x05,0x00,0x00,0x00}}, /* Average Bytes Per Second */ { 0x3D0A, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x03,0x02,0x01,0x00,0x00,0x00}}, /* Block Align */ -}; - -static const MXFLocalTagPair mxf_avc_subdescriptor_local_tags[] = { + // mxf_user_comments_local_tag + { 0x4406, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x02,0x01,0x02,0x0C,0x00,0x00,0x00}}, /* User Comments */ + { 0x5001, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x02,0x01,0x02,0x09,0x01,0x00,0x00}}, /* Name */ + { 0x5003, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x02,0x01,0x02,0x0A,0x01,0x00,0x00}}, /* Value */ + // mxf_avc_subdescriptor_local_tags { 0x8100, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x04,0x06,0x10,0x00,0x00}}, /* SubDescriptors */ { 0x8200, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0E,0x00,0x00}}, /* AVC Decoding Delay */ { 0x8201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0A,0x00,0x00}}, /* AVC Profile */ { 0x8202, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0D,0x00,0x00}}, /* AVC Level */ + // ff_mxf_mastering_display_local_tags + { 0x8301, FF_MXF_MasteringDisplayPrimaries }, + { 0x8302, FF_MXF_MasteringDisplayWhitePointChromaticity }, + { 0x8303, FF_MXF_MasteringDisplayMaximumLuminance }, + { 0x8304, FF_MXF_MasteringDisplayMinimumLuminance }, }; -static const MXFLocalTagPair mxf_user_comments_local_tag[] = { - { 0x4406, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x02,0x01,0x02,0x0C,0x00,0x00,0x00}}, /* User Comments */ - { 0x5001, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x02,0x01,0x02,0x09,0x01,0x00,0x00}}, /* Name */ - { 0x5003, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x02,0x01,0x02,0x0A,0x01,0x00,0x00}}, /* Value */ -}; +#define MXF_NUM_TAGS FF_ARRAY_ELEMS(mxf_local_tag_batch) + +typedef struct MXFContext { + AVClass *av_class; + int64_t footer_partition_offset; + int essence_container_count; + AVRational time_base; + int header_written; + MXFIndexEntry *index_entries; + unsigned edit_units_count; + uint64_t timestamp; ///< timestamp, as year(16),month(8),day(8),hour(8),minutes(8),msec/4(8) + uint8_t slice_count; ///< index slice count minus 1 (1 if no audio, 0 otherwise) + int last_indexed_edit_unit; + uint64_t *body_partition_offset; + unsigned body_partitions_count; + int last_key_index; ///< index of last key frame + uint64_t duration; + AVTimecode tc; ///< timecode context + AVStream *timecode_track; + int timecode_base; ///< rounded time code base (25 or 30) + int edit_unit_byte_count; ///< fixed edit unit byte count + int content_package_rate; ///< content package rate in system element, see SMPTE 326M + uint64_t body_offset; + uint32_t instance_number; + uint8_t umid[16]; ///< unique material identifier + int channel_count; + int signal_standard; + uint32_t tagged_value_count; + AVRational audio_edit_rate; + int store_user_comments; + 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 +} MXFContext; static void mxf_write_uuid(AVIOContext *pb, enum MXFMetadataSetType type, int value) { @@ -553,15 +456,14 @@ static int klv_encode_ber_length(AVIOContext *pb, uint64_t len) { // Determine the best BER size - int size; - if (len < 128) { + int size = klv_ber_length(len); + if (size == 1) { //short form avio_w8(pb, len); return 1; } - size = (av_log2(len) >> 3) + 1; - + size --; // long form avio_w8(pb, 0x80 + size); while(size) { @@ -595,30 +497,64 @@ return -1; } -static void mxf_write_local_tags(AVIOContext *pb, const MXFLocalTagPair *local_tags, int count) +static const MXFLocalTagPair* mxf_lookup_local_tag(int tag) { - int i; - for (i = 0; i < count; i++) { - avio_wb16(pb, local_tags[i].local_tag); - avio_write(pb, local_tags[i].uid, 16); + for (int i = 0; i < MXF_NUM_TAGS; i++) { + if (mxf_local_tag_batch[i].local_tag == tag) { + return &mxf_local_tag_batch[i]; + } } + + // this assert can only be hit during development + av_assert0(0 && "you forgot to add your new tag to mxf_local_tag_batch"); +} + +static void mxf_mark_tag_unused(MXFContext *mxf, int tag) +{ + const MXFLocalTagPair *pair = mxf_lookup_local_tag(tag); + mxf->unused_tags[pair - mxf_local_tag_batch] = 1; } static void mxf_write_primer_pack(AVFormatContext *s) { MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; - int local_tag_number, i = 0; - int avc_tags_count = 0; - - local_tag_number = FF_ARRAY_ELEMS(mxf_local_tag_batch); - local_tag_number += mxf->store_user_comments * FF_ARRAY_ELEMS(mxf_user_comments_local_tag); + int local_tag_number = MXF_NUM_TAGS, i; + int will_have_avc_tags = 0, will_have_mastering_tags = 0; for (i = 0; i < s->nb_streams; i++) { MXFStreamContext *sc = s->streams[i]->priv_data; if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_H264 && !sc->avc_intra) { - avc_tags_count = FF_ARRAY_ELEMS(mxf_avc_subdescriptor_local_tags); - local_tag_number += avc_tags_count; + will_have_avc_tags = 1; + } + if (av_stream_get_side_data(s->streams[i], AV_PKT_DATA_MASTERING_DISPLAY_METADATA, NULL)) { + will_have_mastering_tags = 1; + } + } + + if (!mxf->store_user_comments) { + mxf_mark_tag_unused(mxf, 0x4406); + mxf_mark_tag_unused(mxf, 0x5001); + mxf_mark_tag_unused(mxf, 0x5003); + } + + if (!will_have_avc_tags) { + mxf_mark_tag_unused(mxf, 0x8100); + mxf_mark_tag_unused(mxf, 0x8200); + mxf_mark_tag_unused(mxf, 0x8201); + mxf_mark_tag_unused(mxf, 0x8202); + } + + if (!will_have_mastering_tags) { + mxf_mark_tag_unused(mxf, 0x8301); + mxf_mark_tag_unused(mxf, 0x8302); + mxf_mark_tag_unused(mxf, 0x8303); + mxf_mark_tag_unused(mxf, 0x8304); + } + + for (i = 0; i < MXF_NUM_TAGS; i++) { + if (mxf->unused_tags[i]) { + local_tag_number--; } } @@ -628,21 +564,23 @@ avio_wb32(pb, local_tag_number); // local_tag num avio_wb32(pb, 18); // item size, always 18 according to the specs - for (i = 0; i < FF_ARRAY_ELEMS(mxf_local_tag_batch); i++) { - avio_wb16(pb, mxf_local_tag_batch[i].local_tag); - avio_write(pb, mxf_local_tag_batch[i].uid, 16); - } - if (mxf->store_user_comments) - for (i = 0; i < FF_ARRAY_ELEMS(mxf_user_comments_local_tag); i++) { - avio_wb16(pb, mxf_user_comments_local_tag[i].local_tag); - avio_write(pb, mxf_user_comments_local_tag[i].uid, 16); + for (i = 0; i < MXF_NUM_TAGS; i++) { + if (mxf->unused_tags[i] == 0) { + avio_wb16(pb, mxf_local_tag_batch[i].local_tag); + avio_write(pb, mxf_local_tag_batch[i].uid, 16); } - if (avc_tags_count > 0) - mxf_write_local_tags(pb, mxf_avc_subdescriptor_local_tags, avc_tags_count); + } } -static void mxf_write_local_tag(AVIOContext *pb, int size, int tag) +static void mxf_write_local_tag(AVFormatContext *s, int size, int tag) { + MXFContext *mxf = s->priv_data; + AVIOContext *pb = s->pb; + const MXFLocalTagPair *pair = mxf_lookup_local_tag(tag); + + // make sure the tag was not declared unnecessary upfront + av_assert0(mxf->unused_tags[pair - mxf_local_tag_batch] == 0); + avio_wb16(pb, tag); avio_wb16(pb, size); } @@ -653,21 +591,10 @@ avio_wb24(pb, value); } -static void mxf_free(AVFormatContext *s) -{ - int i; - - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - av_freep(&st->priv_data); - } -} - -static const MXFCodecUL *mxf_get_data_definition_ul(int type) +static const MXFCodecUL *mxf_get_codec_ul_by_id(const MXFCodecUL *uls, int id) { - const MXFCodecUL *uls = ff_mxf_data_definition_uls; while (uls->uid[0]) { - if (type == uls->id) + if (id == uls->id) break; uls++; } @@ -691,7 +618,7 @@ // check first track of essence container type and only write it once if (sc->track_essence_element_key[15] != 0) continue; - avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16); + avio_write(pb, *sc->container_ul, 16); if (c->essence_container_count == 1) break; } @@ -710,44 +637,44 @@ klv_encode_ber_length(pb, 138 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count)); // write preface set uid - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, Preface, 0); PRINT_KEY(s, "preface uid", pb->buf_ptr - 16); // last modified date - mxf_write_local_tag(pb, 8, 0x3B02); + mxf_write_local_tag(s, 8, 0x3B02); avio_wb64(pb, mxf->timestamp); // write version - mxf_write_local_tag(pb, 2, 0x3B05); + mxf_write_local_tag(s, 2, 0x3B05); avio_wb16(pb, 259); // v1.3 // Object Model Version - mxf_write_local_tag(pb, 4, 0x3B07); + mxf_write_local_tag(s, 4, 0x3B07); avio_wb32(pb, 1); // write identification_refs - mxf_write_local_tag(pb, 16 + 8, 0x3B06); + mxf_write_local_tag(s, 16 + 8, 0x3B06); mxf_write_refs_count(pb, 1); mxf_write_uuid(pb, Identification, 0); // write content_storage_refs - mxf_write_local_tag(pb, 16, 0x3B03); + mxf_write_local_tag(s, 16, 0x3B03); mxf_write_uuid(pb, ContentStorage, 0); // operational pattern - mxf_write_local_tag(pb, 16, 0x3B09); + mxf_write_local_tag(s, 16, 0x3B09); if (s->oformat == &ff_mxf_opatom_muxer) avio_write(pb, opatom_ul, 16); else avio_write(pb, op1a_ul, 16); // write essence_container_refs - mxf_write_local_tag(pb, 8 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count), 0x3B0A); + mxf_write_local_tag(s, 8 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count), 0x3B0A); mxf_write_essence_container_refs(s); // write dm_scheme_refs - mxf_write_local_tag(pb, 8, 0x3B0B); + mxf_write_local_tag(s, 8, 0x3B0B); avio_wb64(pb, 0); } @@ -796,8 +723,9 @@ /* * Write a local tag containing an utf-8 string as utf-16 */ -static void mxf_write_local_tag_utf16(AVIOContext *pb, int tag, const char *value) +static void mxf_write_local_tag_utf16(AVFormatContext *s, int tag, const char *value) { + AVIOContext *pb = s->pb; uint64_t size = mxf_utf16len(value); if (size >= UINT16_MAX/2) { @@ -805,7 +733,7 @@ return; } - mxf_write_local_tag(pb, size*2, tag); + mxf_write_local_tag(s, size*2, tag); avio_put_str16be(pb, value); } @@ -825,50 +753,57 @@ avio_wb16(pb, 0); // release } +#define PLATFORM_IDENT "Lavf " AV_STRINGIFY((OS_NAME)) static void mxf_write_identification(AVFormatContext *s) { MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; - const char *company = "FFmpeg"; - const char *product = s->oformat != &ff_mxf_opatom_muxer ? "OP1a Muxer" : "OPAtom Muxer"; - const char *version; + AVDictionaryEntry *com_entry = av_dict_get(s->metadata, "company_name", NULL, 0); + AVDictionaryEntry *product_entry = av_dict_get(s->metadata, "product_name", NULL, 0); + AVDictionaryEntry *version_entry = av_dict_get(s->metadata, "product_version", NULL, 0); + const char *company = com_entry ? com_entry->value : "FFmpeg"; + const char *product = product_entry ? product_entry->value : s->oformat != &ff_mxf_opatom_muxer ? "OP1a Muxer" : "OPAtom Muxer"; + const char *platform = s->flags & AVFMT_FLAG_BITEXACT ? "Lavf" : PLATFORM_IDENT; + const char *version = version_entry ? version_entry->value : + s->flags & AVFMT_FLAG_BITEXACT ? "0.0.0" : + AV_STRINGIFY(LIBAVFORMAT_VERSION); int length; mxf_write_metadata_key(pb, 0x013000); PRINT_KEY(s, "identification key", pb->buf_ptr - 16); - version = s->flags & AVFMT_FLAG_BITEXACT ? - "0.0.0" : AV_STRINGIFY(LIBAVFORMAT_VERSION); length = 100 +mxf_utf16_local_tag_length(company) + mxf_utf16_local_tag_length(product) + + mxf_utf16_local_tag_length(platform) + mxf_utf16_local_tag_length(version); klv_encode_ber_length(pb, length); // write uid - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, Identification, 0); PRINT_KEY(s, "identification uid", pb->buf_ptr - 16); // write generation uid - mxf_write_local_tag(pb, 16, 0x3C09); + mxf_write_local_tag(s, 16, 0x3C09); mxf_write_uuid(pb, Identification, 1); - mxf_write_local_tag_utf16(pb, 0x3C01, company); // Company Name - mxf_write_local_tag_utf16(pb, 0x3C02, product); // Product Name + mxf_write_local_tag_utf16(s, 0x3C01, company); // Company Name + mxf_write_local_tag_utf16(s, 0x3C02, product); // Product Name - mxf_write_local_tag(pb, 10, 0x3C03); // Product Version + mxf_write_local_tag(s, 10, 0x3C03); // Product Version store_version(s); - mxf_write_local_tag_utf16(pb, 0x3C04, version); // Version String + mxf_write_local_tag_utf16(s, 0x3C04, version); // Version String + mxf_write_local_tag_utf16(s, 0x3C08, platform); // Platform // write product uid - mxf_write_local_tag(pb, 16, 0x3C05); + mxf_write_local_tag(s, 16, 0x3C05); mxf_write_uuid(pb, Identification, 2); // modification date - mxf_write_local_tag(pb, 8, 0x3C06); + mxf_write_local_tag(s, 8, 0x3C06); avio_wb64(pb, mxf->timestamp); - mxf_write_local_tag(pb, 10, 0x3C07); // Toolkit Version + mxf_write_local_tag(s, 10, 0x3C07); // Toolkit Version store_version(s); } @@ -882,19 +817,19 @@ klv_encode_ber_length(pb, 60 + (16 * package_count)); // write uid - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, ContentStorage, 0); PRINT_KEY(s, "content storage uid", pb->buf_ptr - 16); // write package reference - mxf_write_local_tag(pb, 16 * package_count + 8, 0x1901); + mxf_write_local_tag(s, 16 * package_count + 8, 0x1901); mxf_write_refs_count(pb, package_count); for (i = 0; i < package_count; i++) { mxf_write_uuid(pb, packages[i].type, packages[i].instance); } // write essence container data - mxf_write_local_tag(pb, 8 + 16, 0x1902); + mxf_write_local_tag(s, 8 + 16, 0x1902); mxf_write_refs_count(pb, 1); mxf_write_uuid(pb, EssenceContainerData, 0); } @@ -910,23 +845,23 @@ klv_encode_ber_length(pb, 80); // write track uid - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, Track, mxf->track_instance_count); PRINT_KEY(s, "track uid", pb->buf_ptr - 16); // write track id - mxf_write_local_tag(pb, 4, 0x4801); + mxf_write_local_tag(s, 4, 0x4801); avio_wb32(pb, st->index+2); // write track number - mxf_write_local_tag(pb, 4, 0x4804); + mxf_write_local_tag(s, 4, 0x4804); if (package->type == MaterialPackage) avio_wb32(pb, 0); // track number of material package is 0 else avio_write(pb, sc->track_essence_element_key + 12, 4); // write edit rate - mxf_write_local_tag(pb, 8, 0x4B01); + mxf_write_local_tag(s, 8, 0x4B01); if (st == mxf->timecode_track && s->oformat == &ff_mxf_opatom_muxer) { avio_wb32(pb, mxf->tc.rate.num); @@ -937,11 +872,11 @@ } // write origin - mxf_write_local_tag(pb, 8, 0x4B02); + mxf_write_local_tag(s, 8, 0x4B02); avio_wb64(pb, 0); // write sequence refs - mxf_write_local_tag(pb, 16, 0x4803); + mxf_write_local_tag(s, 16, 0x4803); mxf_write_uuid(pb, Sequence, mxf->track_instance_count); } @@ -953,16 +888,16 @@ AVIOContext *pb = s->pb; // find data define uls - mxf_write_local_tag(pb, 16, 0x0201); + mxf_write_local_tag(s, 16, 0x0201); if (st == mxf->timecode_track) avio_write(pb, smpte_12m_timecode_track_data_ul, 16); else { - const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codecpar->codec_type); + const MXFCodecUL *data_def_ul = mxf_get_codec_ul_by_id(ff_mxf_data_definition_uls, st->codecpar->codec_type); avio_write(pb, data_def_ul->uid, 16); } // write duration - mxf_write_local_tag(pb, 8, 0x0202); + mxf_write_local_tag(s, 8, 0x0202); if (st != mxf->timecode_track && s->oformat == &ff_mxf_opatom_muxer && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { avio_wb64(pb, mxf->body_offset / mxf->edit_unit_byte_count); @@ -981,14 +916,14 @@ PRINT_KEY(s, "sequence key", pb->buf_ptr - 16); klv_encode_ber_length(pb, 80); - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, Sequence, mxf->track_instance_count); PRINT_KEY(s, "sequence uid", pb->buf_ptr - 16); mxf_write_common_fields(s, st); // write structural component - mxf_write_local_tag(pb, 16 + 8, 0x1001); + mxf_write_local_tag(s, 16 + 8, 0x1001); mxf_write_refs_count(pb, 1); if (st == mxf->timecode_track) component = TimecodeComponent; @@ -1007,21 +942,21 @@ klv_encode_ber_length(pb, 75); // UID - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, TimecodeComponent, mxf->track_instance_count); mxf_write_common_fields(s, st); // Start Time Code - mxf_write_local_tag(pb, 8, 0x1501); + mxf_write_local_tag(s, 8, 0x1501); avio_wb64(pb, mxf->tc.start); // Rounded Time Code Base - mxf_write_local_tag(pb, 2, 0x1502); + mxf_write_local_tag(s, 2, 0x1502); avio_wb16(pb, mxf->timecode_base); // Drop Frame - mxf_write_local_tag(pb, 1, 0x1503); + mxf_write_local_tag(s, 1, 0x1503); avio_w8(pb, !!(mxf->tc.flags & AV_TIMECODE_FLAG_DROPFRAME)); } @@ -1036,18 +971,18 @@ klv_encode_ber_length(pb, 108); // write uid - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, SourceClip, mxf->track_instance_count); PRINT_KEY(s, "structural component uid", pb->buf_ptr - 16); mxf_write_common_fields(s, st); // write start_position - mxf_write_local_tag(pb, 8, 0x1201); + mxf_write_local_tag(s, 8, 0x1201); avio_wb64(pb, 0); // write source package uid, end of the reference - mxf_write_local_tag(pb, 32, 0x1101); + mxf_write_local_tag(s, 32, 0x1101); if (!package->ref) { for (i = 0; i < 4; i++) avio_wb64(pb, 0); @@ -1055,7 +990,7 @@ mxf_write_umid(s, package->ref->instance); // write source track id - mxf_write_local_tag(pb, 4, 0x1102); + mxf_write_local_tag(s, 4, 0x1102); if (package->type == SourcePackage && !package->ref) avio_wb32(pb, 0); else @@ -1069,7 +1004,7 @@ mxf_write_metadata_key(pb, 0x012e00); PRINT_KEY(s, "tape descriptor key", pb->buf_ptr - 16); klv_encode_ber_length(pb, 20); - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, TapeDescriptor, 0); PRINT_KEY(s, "tape_desc uid", pb->buf_ptr - 16); } @@ -1086,27 +1021,27 @@ PRINT_KEY(s, "multiple descriptor key", pb->buf_ptr - 16); klv_encode_ber_length(pb, 64 + 16LL * s->nb_streams); - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, MultipleDescriptor, 0); PRINT_KEY(s, "multi_desc uid", pb->buf_ptr - 16); // write sample rate - mxf_write_local_tag(pb, 8, 0x3001); + mxf_write_local_tag(s, 8, 0x3001); avio_wb32(pb, mxf->time_base.den); avio_wb32(pb, mxf->time_base.num); // write essence container ul - mxf_write_local_tag(pb, 16, 0x3004); + mxf_write_local_tag(s, 16, 0x3004); if (mxf->essence_container_count > 1) ul = multiple_desc_ul; else { MXFStreamContext *sc = s->streams[0]->priv_data; - ul = mxf_essence_container_uls[sc->index].container_ul; + ul = *sc->container_ul; } avio_write(pb, ul, 16); // write sub descriptor refs - mxf_write_local_tag(pb, s->nb_streams * 16 + 8, 0x3F01); + mxf_write_local_tag(s, s->nb_streams * 16 + 8, 0x3F01); mxf_write_refs_count(pb, s->nb_streams); for (i = 0; i < s->nb_streams; i++) mxf_write_uuid(pb, SubDescriptor, i); @@ -1123,13 +1058,13 @@ klv_encode_ber4_length(pb, 0); pos = avio_tell(pb); - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, SubDescriptor, st->index); - mxf_write_local_tag(pb, 4, 0x3006); + mxf_write_local_tag(s, 4, 0x3006); avio_wb32(pb, st->index+2); - mxf_write_local_tag(pb, 8, 0x3001); + mxf_write_local_tag(s, 8, 0x3001); if (s->oformat == &ff_mxf_d10_muxer) { avio_wb32(pb, mxf->time_base.den); avio_wb32(pb, mxf->time_base.num); @@ -1144,8 +1079,8 @@ } } - mxf_write_local_tag(pb, 16, 0x3004); - avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16); + mxf_write_local_tag(s, 16, 0x3004); + avio_write(pb, *sc->container_ul, 16); return pos; } @@ -1159,85 +1094,81 @@ static const UID mxf_avc_subdescriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6E,0x00 }; -static int get_trc(UID ul, enum AVColorTransferCharacteristic trc) +static inline uint16_t rescale_mastering_chroma(AVRational q) { - switch (trc){ - case AVCOL_TRC_GAMMA28 : - case AVCOL_TRC_GAMMA22 : - memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x01,0x00,0x00}), 16); - return 0; - case AVCOL_TRC_BT709 : - case AVCOL_TRC_SMPTE170M : - memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x02,0x00,0x00}), 16); - return 0; - case AVCOL_TRC_SMPTE240M : - memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x03,0x00,0x00}), 16); - return 0; - case AVCOL_TRC_BT1361_ECG: - memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x01,0x05,0x00,0x00}), 16); - return 0; - case AVCOL_TRC_LINEAR : - memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x01,0x06,0x00,0x00}), 16); - return 0; - case AVCOL_TRC_SMPTE428 : - memcpy(ul, ((UID){0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x08,0x04,0x01,0x01,0x01,0x01,0x07,0x00,0x00}), 16); - return 0; - default: - return -1; - } + return av_clip_uint16(av_rescale(q.num, FF_MXF_MASTERING_CHROMA_DEN, q.den)); +} + +static inline uint32_t rescale_mastering_luma(AVRational q) +{ + return av_rescale(q.num, FF_MXF_MASTERING_LUMA_DEN, q.den); } static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID key) { MXFStreamContext *sc = st->priv_data; AVIOContext *pb = s->pb; - int stored_width = (st->codecpar->width +15)/16*16; + int stored_width = 0; int stored_height = (st->codecpar->height+15)/16*16; int display_height; int f1, f2; - UID transfer_ul = {0}; + const MXFCodecUL *color_primaries_ul; + const MXFCodecUL *color_trc_ul; + const MXFCodecUL *color_space_ul; int64_t pos = mxf_write_generic_desc(s, st, key); + uint8_t *side_data; - get_trc(transfer_ul, st->codecpar->color_trc); + color_primaries_ul = mxf_get_codec_ul_by_id(ff_mxf_color_primaries_uls, st->codecpar->color_primaries); + color_trc_ul = mxf_get_codec_ul_by_id(ff_mxf_color_trc_uls, st->codecpar->color_trc); + color_space_ul = mxf_get_codec_ul_by_id(ff_mxf_color_space_uls, st->codecpar->color_space); + + if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO) { + if (st->codecpar->height == 1080) + stored_width = 1920; + else if (st->codecpar->height == 720) + stored_width = 1280; + } + if (!stored_width) + stored_width = (st->codecpar->width+15)/16*16; - mxf_write_local_tag(pb, 4, 0x3203); + mxf_write_local_tag(s, 4, 0x3203); avio_wb32(pb, stored_width); - mxf_write_local_tag(pb, 4, 0x3202); + mxf_write_local_tag(s, 4, 0x3202); avio_wb32(pb, stored_height>>sc->interlaced); if (s->oformat == &ff_mxf_d10_muxer) { //Stored F2 Offset - mxf_write_local_tag(pb, 4, 0x3216); + mxf_write_local_tag(s, 4, 0x3216); avio_wb32(pb, 0); //Image Start Offset - mxf_write_local_tag(pb, 4, 0x3213); + mxf_write_local_tag(s, 4, 0x3213); avio_wb32(pb, 0); //Image End Offset - mxf_write_local_tag(pb, 4, 0x3214); + mxf_write_local_tag(s, 4, 0x3214); avio_wb32(pb, 0); } //Sampled width - mxf_write_local_tag(pb, 4, 0x3205); - avio_wb32(pb, st->codecpar->width); + mxf_write_local_tag(s, 4, 0x3205); + avio_wb32(pb, stored_width); //Samples height - mxf_write_local_tag(pb, 4, 0x3204); + mxf_write_local_tag(s, 4, 0x3204); avio_wb32(pb, st->codecpar->height>>sc->interlaced); //Sampled X Offset - mxf_write_local_tag(pb, 4, 0x3206); + mxf_write_local_tag(s, 4, 0x3206); avio_wb32(pb, 0); //Sampled Y Offset - mxf_write_local_tag(pb, 4, 0x3207); + mxf_write_local_tag(s, 4, 0x3207); avio_wb32(pb, 0); - mxf_write_local_tag(pb, 4, 0x3209); - avio_wb32(pb, st->codecpar->width); + mxf_write_local_tag(s, 4, 0x3209); + avio_wb32(pb, stored_width); if (st->codecpar->height == 608) // PAL + VBI display_height = 576; @@ -1246,67 +1177,67 @@ else display_height = st->codecpar->height; - mxf_write_local_tag(pb, 4, 0x3208); + mxf_write_local_tag(s, 4, 0x3208); avio_wb32(pb, display_height>>sc->interlaced); // display X offset - mxf_write_local_tag(pb, 4, 0x320A); + mxf_write_local_tag(s, 4, 0x320A); avio_wb32(pb, 0); // display Y offset - mxf_write_local_tag(pb, 4, 0x320B); + mxf_write_local_tag(s, 4, 0x320B); avio_wb32(pb, (st->codecpar->height - display_height)>>sc->interlaced); if (sc->interlaced) { //Display F2 Offset - mxf_write_local_tag(pb, 4, 0x3217); + mxf_write_local_tag(s, 4, 0x3217); avio_wb32(pb, -((st->codecpar->height - display_height)&1)); } // component depth - mxf_write_local_tag(pb, 4, 0x3301); + mxf_write_local_tag(s, 4, 0x3301); avio_wb32(pb, sc->component_depth); // horizontal subsampling - mxf_write_local_tag(pb, 4, 0x3302); + mxf_write_local_tag(s, 4, 0x3302); avio_wb32(pb, sc->h_chroma_sub_sample); // vertical subsampling - mxf_write_local_tag(pb, 4, 0x3308); + mxf_write_local_tag(s, 4, 0x3308); avio_wb32(pb, sc->v_chroma_sub_sample); // color siting - mxf_write_local_tag(pb, 1, 0x3303); + mxf_write_local_tag(s, 1, 0x3303); avio_w8(pb, sc->color_siting); // Padding Bits - mxf_write_local_tag(pb, 2, 0x3307); + mxf_write_local_tag(s, 2, 0x3307); avio_wb16(pb, 0); if (st->codecpar->color_range != AVCOL_RANGE_UNSPECIFIED) { int black = 0, white = (1<component_depth) - 1, - color = (1<component_depth) - 1; + color = (1<component_depth); if (st->codecpar->color_range == AVCOL_RANGE_MPEG) { black = 1 << (sc->component_depth - 4); white = 235 << (sc->component_depth - 8); color = (14 << (sc->component_depth - 4)) + 1; } - mxf_write_local_tag(pb, 4, 0x3304); + mxf_write_local_tag(s, 4, 0x3304); avio_wb32(pb, black); - mxf_write_local_tag(pb, 4, 0x3305); + mxf_write_local_tag(s, 4, 0x3305); avio_wb32(pb, white); - mxf_write_local_tag(pb, 4, 0x3306); + mxf_write_local_tag(s, 4, 0x3306); avio_wb32(pb, color); } if (sc->signal_standard) { - mxf_write_local_tag(pb, 1, 0x3215); + mxf_write_local_tag(s, 1, 0x3215); avio_w8(pb, sc->signal_standard); } // frame layout - mxf_write_local_tag(pb, 1, 0x320C); + mxf_write_local_tag(s, 1, 0x320C); avio_w8(pb, sc->interlaced); // video line map @@ -1326,33 +1257,70 @@ } - mxf_write_local_tag(pb, 16, 0x320D); + mxf_write_local_tag(s, 16, 0x320D); avio_wb32(pb, 2); avio_wb32(pb, 4); avio_wb32(pb, f1); avio_wb32(pb, f2); - mxf_write_local_tag(pb, 8, 0x320E); + mxf_write_local_tag(s, 8, 0x320E); avio_wb32(pb, sc->aspect_ratio.num); avio_wb32(pb, sc->aspect_ratio.den); - //Transfer characteristic - if (transfer_ul[0]) { - mxf_write_local_tag(pb, 16, 0x3210); - avio_write(pb, transfer_ul, 16); + if (color_primaries_ul->uid[0]) { + mxf_write_local_tag(s, 16, 0x3219); + avio_write(pb, color_primaries_ul->uid, 16); + }; + + if (color_trc_ul->uid[0]) { + mxf_write_local_tag(s, 16, 0x3210); + avio_write(pb, color_trc_ul->uid, 16); + }; + + if (color_space_ul->uid[0]) { + mxf_write_local_tag(s, 16, 0x321A); + avio_write(pb, color_space_ul->uid, 16); }; - mxf_write_local_tag(pb, 16, 0x3201); + mxf_write_local_tag(s, 16, 0x3201); avio_write(pb, *sc->codec_ul, 16); + // Mastering Display metadata + side_data = av_stream_get_side_data(st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, NULL); + if (side_data) { + const AVMasteringDisplayMetadata *metadata = (const AVMasteringDisplayMetadata*)side_data; + if (metadata->has_primaries) { + mxf_write_local_tag(s, 12, 0x8301); + avio_wb16(pb, rescale_mastering_chroma(metadata->display_primaries[0][0])); + avio_wb16(pb, rescale_mastering_chroma(metadata->display_primaries[0][1])); + avio_wb16(pb, rescale_mastering_chroma(metadata->display_primaries[1][0])); + avio_wb16(pb, rescale_mastering_chroma(metadata->display_primaries[1][1])); + avio_wb16(pb, rescale_mastering_chroma(metadata->display_primaries[2][0])); + avio_wb16(pb, rescale_mastering_chroma(metadata->display_primaries[2][1])); + mxf_write_local_tag(s, 4, 0x8302); + avio_wb16(pb, rescale_mastering_chroma(metadata->white_point[0])); + avio_wb16(pb, rescale_mastering_chroma(metadata->white_point[1])); + } else { + av_log(NULL, AV_LOG_VERBOSE, "Not writing mastering display primaries. Missing data.\n"); + } + if (metadata->has_luminance) { + mxf_write_local_tag(s, 4, 0x8303); + avio_wb32(pb, rescale_mastering_luma(metadata->max_luminance)); + mxf_write_local_tag(s, 4, 0x8304); + avio_wb32(pb, rescale_mastering_luma(metadata->min_luminance)); + } else { + av_log(NULL, AV_LOG_VERBOSE, "Not writing mastering display luminances. Missing data.\n"); + } + } + if (sc->interlaced && sc->field_dominance) { - mxf_write_local_tag(pb, 1, 0x3212); + mxf_write_local_tag(s, 1, 0x3212); avio_w8(pb, sc->field_dominance); } if (st->codecpar->codec_id == AV_CODEC_ID_H264 && !sc->avc_intra) { // write avc sub descriptor ref - mxf_write_local_tag(pb, 8 + 16, 0x8100); + mxf_write_local_tag(s, 8 + 16, 0x8100); mxf_write_refs_count(pb, 1); mxf_write_uuid(pb, AVCSubDescriptor, 0); } @@ -1378,16 +1346,16 @@ klv_encode_ber4_length(pb, 0); pos = avio_tell(pb); - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, AVCSubDescriptor, 0); - mxf_write_local_tag(pb, 1, 0x8200); + mxf_write_local_tag(s, 1, 0x8200); avio_w8(pb, 0xFF); // AVC Decoding Delay, unknown - mxf_write_local_tag(pb, 1, 0x8201); + mxf_write_local_tag(s, 1, 0x8201); avio_w8(pb, st->codecpar->profile); // AVC Profile - mxf_write_local_tag(pb, 1, 0x8202); + mxf_write_local_tag(s, 1, 0x8202); avio_w8(pb, st->codecpar->level); // AVC Level mxf_update_klv_size(s->pb, pos); @@ -1430,29 +1398,29 @@ if (st->codecpar->codec_id != AV_CODEC_ID_H264) { // bit rate - mxf_write_local_tag(pb, 4, 0x8000); + mxf_write_local_tag(s, 4, 0x8000); avio_wb32(pb, sc->video_bit_rate); // profile and level - mxf_write_local_tag(pb, 1, 0x8007); + mxf_write_local_tag(s, 1, 0x8007); if (!st->codecpar->profile) profile_and_level |= 0x80; // escape bit avio_w8(pb, profile_and_level); // low delay - mxf_write_local_tag(pb, 1, 0x8003); + mxf_write_local_tag(s, 1, 0x8003); avio_w8(pb, sc->low_delay); // closed gop - mxf_write_local_tag(pb, 1, 0x8004); + mxf_write_local_tag(s, 1, 0x8004); avio_w8(pb, sc->seq_closed_gop); // max gop - mxf_write_local_tag(pb, 2, 0x8006); + mxf_write_local_tag(s, 2, 0x8006); avio_wb16(pb, sc->max_gop); // b picture count - mxf_write_local_tag(pb, 2, 0x8008); + mxf_write_local_tag(s, 2, 0x8008); avio_wb16(pb, sc->b_picture_count); } @@ -1467,25 +1435,25 @@ int64_t pos = mxf_write_generic_desc(s, st, key); if (s->oformat == &ff_mxf_opatom_muxer) { - mxf_write_local_tag(pb, 8, 0x3002); + mxf_write_local_tag(s, 8, 0x3002); avio_wb64(pb, mxf->body_offset / mxf->edit_unit_byte_count); } // audio locked - mxf_write_local_tag(pb, 1, 0x3D02); + mxf_write_local_tag(s, 1, 0x3D02); avio_w8(pb, 1); // write audio sampling rate - mxf_write_local_tag(pb, 8, 0x3D03); + mxf_write_local_tag(s, 8, 0x3D03); avio_wb32(pb, st->codecpar->sample_rate); avio_wb32(pb, 1); if (s->oformat == &ff_mxf_d10_muxer) { - mxf_write_local_tag(pb, 1, 0x3D04); + mxf_write_local_tag(s, 1, 0x3D04); avio_w8(pb, 0); } - mxf_write_local_tag(pb, 4, 0x3D07); + mxf_write_local_tag(s, 4, 0x3D07); if (mxf->channel_count == -1) { if (show_warnings && (s->oformat == &ff_mxf_d10_muxer) && (st->codecpar->channels != 4) && (st->codecpar->channels != 8)) av_log(s, AV_LOG_WARNING, "the number of audio channels shall be 4 or 8 : the output will not comply to MXF D-10 specs, use -d10_channelcount to fix this\n"); @@ -1500,7 +1468,7 @@ avio_wb32(pb, st->codecpar->channels); } - mxf_write_local_tag(pb, 4, 0x3D01); + mxf_write_local_tag(s, 4, 0x3D01); avio_wb32(pb, av_get_bits_per_sample(st->codecpar->codec_id)); return pos; @@ -1511,11 +1479,11 @@ AVIOContext *pb = s->pb; int64_t pos = mxf_write_generic_sound_common(s, st, key); - mxf_write_local_tag(pb, 2, 0x3D0A); + mxf_write_local_tag(s, 2, 0x3D0A); avio_wb16(pb, st->codecpar->block_align); // avg bytes per sec - mxf_write_local_tag(pb, 4, 0x3D09); + mxf_write_local_tag(s, 4, 0x3D09); avio_wb32(pb, st->codecpar->block_align*st->codecpar->sample_rate); return pos; @@ -1555,14 +1523,14 @@ klv_encode_ber_length(pb, 24 + name_size + indirect_value_size); // write instance UID - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, TaggedValue, mxf->tagged_value_count); // write name - mxf_write_local_tag_utf16(pb, 0x5001, name); // Name + mxf_write_local_tag_utf16(s, 0x5001, name); // Name // write indirect value - mxf_write_local_tag(pb, indirect_value_size, 0x5003); + mxf_write_local_tag(s, indirect_value_size, 0x5003); avio_write(pb, mxf_indirect_value_utf16le, 17); avio_put_str16le(pb, value); @@ -1609,30 +1577,30 @@ } // write uid - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, package->type, package->instance); av_log(s, AV_LOG_DEBUG, "package type:%d\n", package->type); PRINT_KEY(s, "package uid", pb->buf_ptr - 16); // write package umid - mxf_write_local_tag(pb, 32, 0x4401); + mxf_write_local_tag(s, 32, 0x4401); mxf_write_umid(s, package->instance); PRINT_KEY(s, "package umid second part", pb->buf_ptr - 16); // package name if (name_size) - mxf_write_local_tag_utf16(pb, 0x4402, package->name); + mxf_write_local_tag_utf16(s, 0x4402, package->name); // package creation date - mxf_write_local_tag(pb, 8, 0x4405); + mxf_write_local_tag(s, 8, 0x4405); avio_wb64(pb, mxf->timestamp); // package modified date - mxf_write_local_tag(pb, 8, 0x4404); + mxf_write_local_tag(s, 8, 0x4404); avio_wb64(pb, mxf->timestamp); // write track refs - mxf_write_local_tag(pb, track_count*16 + 8, 0x4403); + mxf_write_local_tag(s, track_count*16 + 8, 0x4403); mxf_write_refs_count(pb, track_count); // these are the uuids of the tracks the will be written in mxf_write_track for (i = 0; i < track_count; i++) @@ -1640,7 +1608,7 @@ // write user comment refs if (mxf->store_user_comments) { - mxf_write_local_tag(pb, user_comment_count*16 + 8, 0x4406); + mxf_write_local_tag(s, user_comment_count*16 + 8, 0x4406); mxf_write_refs_count(pb, user_comment_count); for (i = 0; i < user_comment_count; i++) mxf_write_uuid(pb, TaggedValue, mxf->tagged_value_count - user_comment_count + i); @@ -1648,14 +1616,14 @@ // write multiple descriptor reference if (package->type == SourcePackage && package->instance == 1) { - mxf_write_local_tag(pb, 16, 0x4701); + mxf_write_local_tag(s, 16, 0x4701); if (s->nb_streams > 1) { mxf_write_uuid(pb, MultipleDescriptor, 0); mxf_write_multi_descriptor(s); } else mxf_write_uuid(pb, SubDescriptor, 0); } else if (package->type == SourcePackage && package->instance == 2) { - mxf_write_local_tag(pb, 16, 0x4701); + mxf_write_local_tag(s, 16, 0x4701); mxf_write_uuid(pb, TapeDescriptor, 0); mxf_write_tape_descriptor(s); } @@ -1695,16 +1663,16 @@ mxf_write_metadata_key(pb, 0x012300); klv_encode_ber_length(pb, 72); - mxf_write_local_tag(pb, 16, 0x3C0A); // Instance UID + mxf_write_local_tag(s, 16, 0x3C0A); // Instance UID mxf_write_uuid(pb, EssenceContainerData, 0); - mxf_write_local_tag(pb, 32, 0x2701); // Linked Package UID + mxf_write_local_tag(s, 32, 0x2701); // Linked Package UID mxf_write_umid(s, 1); - mxf_write_local_tag(pb, 4, 0x3F07); // BodySID + mxf_write_local_tag(s, 4, 0x3F07); // BodySID avio_wb32(pb, 1); - mxf_write_local_tag(pb, 4, 0x3F06); // IndexSID + mxf_write_local_tag(s, 4, 0x3F06); // IndexSID avio_wb32(pb, 2); return 0; @@ -1789,43 +1757,43 @@ pos = avio_tell(pb); // instance id - mxf_write_local_tag(pb, 16, 0x3C0A); + mxf_write_local_tag(s, 16, 0x3C0A); mxf_write_uuid(pb, IndexTableSegment, 0); // index edit rate - mxf_write_local_tag(pb, 8, 0x3F0B); + mxf_write_local_tag(s, 8, 0x3F0B); avio_wb32(pb, mxf->time_base.den); avio_wb32(pb, mxf->time_base.num); // index start position - mxf_write_local_tag(pb, 8, 0x3F0C); + mxf_write_local_tag(s, 8, 0x3F0C); avio_wb64(pb, mxf->last_indexed_edit_unit); // index duration - mxf_write_local_tag(pb, 8, 0x3F0D); + mxf_write_local_tag(s, 8, 0x3F0D); if (mxf->edit_unit_byte_count) avio_wb64(pb, 0); // index table covers whole container else avio_wb64(pb, mxf->edit_units_count); // edit unit byte count - mxf_write_local_tag(pb, 4, 0x3F05); + mxf_write_local_tag(s, 4, 0x3F05); avio_wb32(pb, mxf->edit_unit_byte_count); // index sid - mxf_write_local_tag(pb, 4, 0x3F06); + mxf_write_local_tag(s, 4, 0x3F06); avio_wb32(pb, 2); // body sid - mxf_write_local_tag(pb, 4, 0x3F07); + mxf_write_local_tag(s, 4, 0x3F07); avio_wb32(pb, 1); // real slice count - 1 - mxf_write_local_tag(pb, 1, 0x3F08); + mxf_write_local_tag(s, 1, 0x3F08); avio_w8(pb, !mxf->edit_unit_byte_count); // only one slice for CBR // delta entry array - mxf_write_local_tag(pb, 8 + (s->nb_streams+1)*6, 0x3F09); + mxf_write_local_tag(s, 8 + (s->nb_streams+1)*6, 0x3F09); avio_wb32(pb, s->nb_streams+1); // num of entries avio_wb32(pb, 6); // size of one entry // write system item delta entry @@ -1847,7 +1815,7 @@ avio_wb32(pb, KAG_SIZE); // system item size including klv fill } else { // audio or data track if (!audio_frame_size) { - audio_frame_size = sc->aic.samples[0]*sc->aic.sample_size; + audio_frame_size = sc->frame_size; audio_frame_size += klv_fill_size(audio_frame_size); } avio_w8(pb, 1); @@ -1857,7 +1825,7 @@ if (!mxf->edit_unit_byte_count) { MXFStreamContext *sc = s->streams[0]->priv_data; - mxf_write_local_tag(pb, 8 + mxf->edit_units_count*15, 0x3F0A); + mxf_write_local_tag(s, 8 + mxf->edit_units_count*15, 0x3F0A); avio_wb32(pb, mxf->edit_units_count); // num of entries avio_wb32(pb, 15); // size of one entry @@ -2026,7 +1994,7 @@ } if(key) - avio_flush(pb); + avio_write_marker(pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); return 0; } @@ -2052,7 +2020,6 @@ if (mxf->header_written) return 1; - sc->codec_ul = NULL; profile = st->codecpar->profile; for (i = 0; i < FF_ARRAY_ELEMS(mxf_prores_codec_uls); i++) { if (profile == mxf_prores_codec_uls[i].profile) { @@ -2060,7 +2027,7 @@ break; } } - if (!sc->codec_ul) + if (i == FF_ARRAY_ELEMS(mxf_prores_codec_uls)) return 0; sc->frame_size = pkt->size; @@ -2106,7 +2073,6 @@ if (pkt->size < 43) return 0; - sc->codec_ul = NULL; cid = AV_RB32(pkt->data + 0x28); for (i = 0; i < FF_ARRAY_ELEMS(mxf_dnxhd_codec_uls); i++) { if (cid == mxf_dnxhd_codec_uls[i].cid) { @@ -2114,7 +2080,7 @@ break; } } - if (!sc->codec_ul) + if (i == FF_ARRAY_ELEMS(mxf_dnxhd_codec_uls)) return 0; sc->component_depth = 0; @@ -2148,13 +2114,38 @@ return 1; } +static const struct { + const UID container_ul; + const UID codec_ul; +} mxf_dv_uls[] = { + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x01,0x01 }, // IEC DV25 525/60 + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x01,0x00 } }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x02,0x01 }, // IEC DV25 626/50 + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x02,0x00 } }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x40,0x01 }, // DV25 525/60 + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x01,0x00 }, }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, // DV25 625/50 + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x02,0x00 }, }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x50,0x01 }, // DV50 525/60 + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x03,0x00 }, }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x51,0x01 }, // DV50 625/50 + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x04,0x00 }, }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x60,0x01 }, // DV100 1080/60 + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x05,0x00 }, }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x61,0x01 }, // DV100 1080/50 + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x06,0x00 }, }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x62,0x01 }, // DV100 720/60 + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x07,0x00 }, }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x63,0x01 }, // DV100 720/50 + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x08,0x00 }, }, +}; + static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt) { MXFContext *mxf = s->priv_data; MXFStreamContext *sc = st->priv_data; uint8_t *vs_pack, *vsc_pack; - int ul_index, stype, pal; - const AVDVProfile *profile; + int apt, ul_index, stype, pal; if (mxf->header_written) return 1; @@ -2163,8 +2154,7 @@ if (pkt->size < 120000) return -1; - profile = av_dv_frame_profile(NULL, pkt->data, pkt->size); - + apt = pkt->data[4] & 0x7; vs_pack = pkt->data + 80*5 + 48; vsc_pack = pkt->data + 80*5 + 53; stype = vs_pack[3] & 0x1f; @@ -2183,28 +2173,29 @@ switch (stype) { case 0x18: // DV100 720p - ul_index = INDEX_DV100_720_50 + pal; + ul_index = 8+pal; if (sc->interlaced) { av_log(s, AV_LOG_ERROR, "source marked as interlaced but codec profile is progressive\n"); sc->interlaced = 0; } break; case 0x14: // DV100 1080i - ul_index = INDEX_DV100_1080_50 + pal; + ul_index = 6+pal; break; case 0x04: // DV50 - ul_index = INDEX_DV50_525_60 + pal; + ul_index = 4+pal; break; default: // DV25 - if (profile && profile->pix_fmt == AV_PIX_FMT_YUV420P && pal) { - ul_index = INDEX_DV25_525_60_IEC + pal; - break; + if (!apt) { // IEC + ul_index = 0+pal; + } else { + ul_index = 2+pal; } - ul_index = INDEX_DV25_525_60 + pal; } - sc->index = ul_index; - sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul; + sc->container_ul = &mxf_dv_uls[ul_index].container_ul; + sc->codec_ul = &mxf_dv_uls[ul_index].codec_ul; + sc->frame_size = pkt->size; return 1; @@ -2247,14 +2238,15 @@ { MXFContext *mxf = s->priv_data; MXFStreamContext *sc = st->priv_data; - H264SequenceParameterSet *sps = NULL; + H264SPS seq, *const sps = &seq; GetBitContext gb; const uint8_t *buf = pkt->data; const uint8_t *buf_end = pkt->data + pkt->size; const uint8_t *nal_end; + const UID *codec_ul = NULL; uint32_t state = -1; int extra_size = 512; // support AVC Intra files without SPS/PPS header - int i, frame_size, slice_type, intra_only = 0; + int i, frame_size, slice_type, has_sps = 0, intra_only = 0, ret; for (;;) { buf = avpriv_find_start_code(buf, buf_end, &state); @@ -2269,11 +2261,12 @@ break; nal_end = ff_avc_find_startcode(buf, buf_end); - sps = ff_avc_decode_sps(buf, nal_end - buf); - if (!sps) { + ret = ff_avc_decode_sps(sps, buf, nal_end - buf); + if (ret < 0) { av_log(s, AV_LOG_ERROR, "error parsing sps\n"); return 0; } + has_sps = 1; sc->aspect_ratio.num = st->codecpar->width * sps->sar.num; sc->aspect_ratio.den = st->codecpar->height * sps->sar.den; @@ -2319,14 +2312,13 @@ if (mxf->header_written) return 1; - if (!sps) + if (!has_sps) sc->interlaced = st->codecpar->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0; - sc->codec_ul = NULL; frame_size = pkt->size + extra_size; for (i = 0; i < FF_ARRAY_ELEMS(mxf_h264_codec_uls); i++) { if (frame_size == mxf_h264_codec_uls[i].frame_size && sc->interlaced == mxf_h264_codec_uls[i].interlaced) { - sc->codec_ul = &mxf_h264_codec_uls[i].uid; + codec_ul = &mxf_h264_codec_uls[i].uid; sc->component_depth = 10; // AVC Intra is always 10 Bit sc->aspect_ratio = (AVRational){ 16, 9 }; // 16:9 is mandatory for broadcast HD st->codecpar->profile = mxf_h264_codec_uls[i].profile; @@ -2336,23 +2328,22 @@ if (sc->interlaced) sc->field_dominance = 1; // top field first is mandatory for AVC Intra break; - } else if (sps && mxf_h264_codec_uls[i].frame_size == 0 && + } else if (has_sps && mxf_h264_codec_uls[i].frame_size == 0 && mxf_h264_codec_uls[i].profile == sps->profile_idc && (mxf_h264_codec_uls[i].intra_only < 0 || mxf_h264_codec_uls[i].intra_only == intra_only)) { - sc->codec_ul = &mxf_h264_codec_uls[i].uid; + codec_ul = &mxf_h264_codec_uls[i].uid; st->codecpar->profile = sps->profile_idc; st->codecpar->level = sps->level_idc; // continue to check for avc intra } } - av_free(sps); - - if (!sc->codec_ul) { + if (!codec_ul) { av_log(s, AV_LOG_ERROR, "h264 profile not supported\n"); return 0; } + sc->codec_ul = codec_ul; return 1; } @@ -2449,9 +2440,13 @@ } } } - if (s->oformat != &ff_mxf_d10_muxer) - sc->codec_ul = mxf_get_mpeg2_codec_ul(st->codecpar); - return !!sc->codec_ul; + if (s->oformat != &ff_mxf_d10_muxer) { + const UID *codec_ul = mxf_get_mpeg2_codec_ul(st->codecpar); + if (!codec_ul) + return 0; + sc->codec_ul = codec_ul; + } + return 1; } static uint64_t mxf_parse_timestamp(int64_t timestamp64) @@ -2482,17 +2477,28 @@ mxf->instance_number = seed & 0xFFFFFF; } -static int mxf_init_timecode(AVFormatContext *s, AVStream *st, AVRational rate) +static int mxf_init_timecode(AVFormatContext *s, AVStream *st, AVRational tbc) { MXFContext *mxf = s->priv_data; AVDictionaryEntry *tcr = av_dict_get(s->metadata, "timecode", NULL, 0); + + if (!ff_mxf_get_content_package_rate(tbc)) { + if (s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { + av_log(s, AV_LOG_ERROR, "Unsupported frame rate %d/%d. Set -strict option to 'unofficial' or lower in order to allow it!\n", tbc.den, tbc.num); + return AVERROR(EINVAL); + } else { + av_log(s, AV_LOG_WARNING, "Unofficial frame rate %d/%d.\n", tbc.den, tbc.num); + } + } + + mxf->timecode_base = (tbc.den + tbc.num/2) / tbc.num; if (!tcr) tcr = av_dict_get(st->metadata, "timecode", NULL, 0); if (tcr) - return av_timecode_init_from_string(&mxf->tc, rate, tcr->value, s); + return av_timecode_init_from_string(&mxf->tc, av_inv_q(tbc), tcr->value, s); else - return av_timecode_init(&mxf->tc, rate, 0, 0, s); + return av_timecode_init(&mxf->tc, av_inv_q(tbc), 0, 0, s); } static int mxf_write_header(AVFormatContext *s) @@ -2500,7 +2506,6 @@ MXFContext *mxf = s->priv_data; int i, ret; uint8_t present[FF_ARRAY_ELEMS(mxf_essence_container_uls)] = {0}; - const MXFSamplesPerFrame *spf = NULL; int64_t timestamp = 0; if (!s->nb_streams) @@ -2520,6 +2525,7 @@ if (!sc) return AVERROR(ENOMEM); st->priv_data = sc; + sc->index = -1; if (((i == 0) ^ (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) && s->oformat != &ff_mxf_opatom_muxer) { av_log(s, AV_LOG_ERROR, "there must be exactly one video stream and it must be the first one\n"); @@ -2529,7 +2535,7 @@ if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(st->codecpar->format); // TODO: should be avg_frame_rate - AVRational rate, tbc = st->time_base; + AVRational tbc = st->time_base; // Default component depth to 8 sc->component_depth = 8; sc->h_chroma_sub_sample = 2; @@ -2553,18 +2559,10 @@ case AVCHROMA_LOC_CENTER: sc->color_siting = 3; break; } - mxf->timecode_base = (tbc.den + tbc.num/2) / tbc.num; - spf = ff_mxf_get_samples_per_frame(s, tbc); - if (!spf) { - av_log(s, AV_LOG_ERROR, "Unsupported video frame rate %d/%d\n", - tbc.den, tbc.num); - return AVERROR(EINVAL); - } mxf->content_package_rate = ff_mxf_get_content_package_rate(tbc); - mxf->time_base = spf->time_base; - rate = av_inv_q(mxf->time_base); + mxf->time_base = tbc; avpriv_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den); - if((ret = mxf_init_timecode(s, st, rate)) < 0) + if((ret = mxf_init_timecode(s, st, tbc)) < 0) return ret; if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) { @@ -2579,25 +2577,29 @@ mxf->cbr_index = 1; if (s->oformat == &ff_mxf_d10_muxer) { + int ntsc = mxf->time_base.den != 25; + int ul_index; + if (st->codecpar->codec_id != AV_CODEC_ID_MPEG2VIDEO) { av_log(s, AV_LOG_ERROR, "error MXF D-10 only support MPEG-2 Video\n"); return AVERROR(EINVAL); } if ((sc->video_bit_rate == 50000000) && (mxf->time_base.den == 25)) { - sc->index = INDEX_D10_625_50_50_VIDEO; - } else if ((sc->video_bit_rate == 49999840 || sc->video_bit_rate == 50000000) && (mxf->time_base.den != 25)) { - sc->index = INDEX_D10_525_60_50_VIDEO; + ul_index = 0; + } else if ((sc->video_bit_rate == 49999840 || sc->video_bit_rate == 50000000) && ntsc) { + ul_index = 1; } else if (sc->video_bit_rate == 40000000) { - if (mxf->time_base.den == 25) sc->index = INDEX_D10_625_50_40_VIDEO; - else sc->index = INDEX_D10_525_60_40_VIDEO; + ul_index = 2+ntsc; } else if (sc->video_bit_rate == 30000000) { - if (mxf->time_base.den == 25) sc->index = INDEX_D10_625_50_30_VIDEO; - else sc->index = INDEX_D10_525_60_30_VIDEO; + ul_index = 4+ntsc; } else { av_log(s, AV_LOG_ERROR, "error MXF D-10 only support 30/40/50 mbit/s\n"); return -1; } + sc->codec_ul = &mxf_d10_codec_uls[ul_index]; + sc->container_ul = &mxf_d10_container_uls[ul_index]; + sc->index = INDEX_D10_VIDEO; sc->signal_standard = 1; sc->color_siting = 0; sc->frame_size = (int64_t)sc->video_bit_rate * @@ -2606,6 +2608,7 @@ if (mxf->signal_standard >= 0) sc->signal_standard = mxf->signal_standard; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + char bsf_arg[32]; if (st->codecpar->sample_rate != 48000) { av_log(s, AV_LOG_ERROR, "only 48khz is implemented\n"); return -1; @@ -2620,8 +2623,9 @@ st->codecpar->codec_id != AV_CODEC_ID_PCM_S24LE) { av_log(s, AV_LOG_ERROR, "MXF D-10 only support 16 or 24 bits le audio\n"); } - sc->index = ((MXFStreamContext*)s->streams[0]->priv_data)->index + 1; - sc->frame_size = 4 + 8 * spf[0].samples_per_frame[0] * 4; + sc->index = INDEX_D10_AUDIO; + sc->container_ul = ((MXFStreamContext*)s->streams[0]->priv_data)->container_ul; + sc->frame_size = 4 + 8 * av_rescale_rnd(st->codecpar->sample_rate, mxf->time_base.num, mxf->time_base.den, AV_ROUND_UP) * 4; } else if (s->oformat == &ff_mxf_opatom_muxer) { AVRational tbc = av_inv_q(mxf->audio_edit_rate); @@ -2635,24 +2639,22 @@ return AVERROR(EINVAL); } - spf = ff_mxf_get_samples_per_frame(s, tbc); - if (!spf) { - av_log(s, AV_LOG_ERROR, "Unsupported timecode frame rate %d/%d\n", tbc.den, tbc.num); - return AVERROR(EINVAL); - } - mxf->time_base = st->time_base; - if((ret = mxf_init_timecode(s, st, av_inv_q(spf->time_base))) < 0) + if((ret = mxf_init_timecode(s, st, tbc)) < 0) return ret; - mxf->timecode_base = (tbc.den + tbc.num/2) / tbc.num; mxf->edit_unit_byte_count = (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->channels) >> 3; sc->index = INDEX_WAV; } else { mxf->slice_count = 1; - sc->frame_size = (st->codecpar->channels * spf[0].samples_per_frame[0] * - av_get_bits_per_sample(st->codecpar->codec_id)) / 8; - } + sc->frame_size = st->codecpar->channels * + av_rescale_rnd(st->codecpar->sample_rate, mxf->time_base.num, mxf->time_base.den, AV_ROUND_UP) * + av_get_bits_per_sample(st->codecpar->codec_id) / 8; + } + snprintf(bsf_arg, sizeof(bsf_arg), "r=%d/%d", mxf->tc.rate.num, mxf->tc.rate.den); + ret = ff_stream_add_bitstream_filter(st, "pcm_rechunk", bsf_arg); + if (ret < 0) + return ret; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { AVDictionaryEntry *e = av_dict_get(st->metadata, "data_type", NULL, 0); if (e && !strcmp(e->value, "vbi_vanc_smpte_436M")) { @@ -2667,7 +2669,7 @@ } } - if (!sc->index) { + if (sc->index == -1) { sc->index = mxf_get_essence_container_ul_index(st->codecpar->codec_id); if (sc->index == -1) { av_log(s, AV_LOG_ERROR, "track %d: could not find essence container ul, " @@ -2676,7 +2678,10 @@ } } - sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul; + if (!sc->codec_ul) + sc->codec_ul = &mxf_essence_container_uls[sc->index].codec_ul; + if (!sc->container_ul) + sc->container_ul = &mxf_essence_container_uls[sc->index].container_ul; memcpy(sc->track_essence_element_key, mxf_essence_container_uls[sc->index].element_ul, 15); sc->track_essence_element_key[15] = present[sc->index]; @@ -2698,7 +2703,7 @@ MXFStreamContext *sc = s->streams[i]->priv_data; // update element count sc->track_essence_element_key[13] = present[sc->index]; - if (!memcmp(sc->track_essence_element_key, mxf_essence_container_uls[15].element_ul, 13)) // DV + if (!memcmp(sc->track_essence_element_key, mxf_essence_container_uls[INDEX_DV].element_ul, 13)) // DV sc->order = (0x15 << 24) | AV_RB32(sc->track_essence_element_key+13); else sc->order = AV_RB32(sc->track_essence_element_key+12); @@ -2716,12 +2721,6 @@ return AVERROR(ENOMEM); mxf->timecode_track->index = -1; - if (!spf) - spf = ff_mxf_get_samples_per_frame(s, (AVRational){ 1, 25 }); - - if (ff_audio_interleave_init(s, spf->samples_per_frame, mxf->time_base) < 0) - return -1; - return 0; } @@ -2752,12 +2751,12 @@ avio_w8(pb, mxf->content_package_rate); // content package rate avio_w8(pb, 0x00); // content package type avio_wb16(pb, 0x00); // channel handle - avio_wb16(pb, (mxf->tc.start + frame) & 0xFFFF); // continuity count, supposed to overflow + avio_wb16(pb, frame & 0xFFFF); // continuity count, supposed to overflow if (mxf->essence_container_count > 1) avio_write(pb, multiple_desc_ul, 16); else { MXFStreamContext *sc = s->streams[0]->priv_data; - avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16); + avio_write(pb, *sc->container_ul, 16); } avio_w8(pb, 0); avio_wb64(pb, 0); @@ -2855,7 +2854,6 @@ mxf->edit_units_count++; avio_write(pb, pkt->data, pkt->size); mxf->body_offset += pkt->size; - avio_flush(pb); return 0; } @@ -2890,6 +2888,13 @@ MXFIndexEntry ie = {0}; int err; + if (!mxf->header_written && pkt->stream_index != 0 && + s->oformat != &ff_mxf_opatom_muxer) { + av_log(s, AV_LOG_ERROR, "Received non-video packet before " + "header has been written\n"); + return AVERROR_INVALIDDATA; + } + if (!mxf->cbr_index && !mxf->edit_unit_byte_count && !(mxf->edit_units_count % EDIT_UNITS_PER_BODY)) { if ((err = av_reallocp_array(&mxf->index_entries, mxf->edit_units_count + EDIT_UNITS_PER_BODY, sizeof(*mxf->index_entries))) < 0) { @@ -2993,8 +2998,6 @@ mxf->body_offset += 16+4+pkt->size + klv_fill_size(16+4+pkt->size); } - avio_flush(pb); - return 0; } @@ -3005,7 +3008,7 @@ uint64_t pos = avio_tell(pb); int i; - avio_write(pb, random_index_pack_key, 16); + avio_write(pb, ff_mxf_random_index_pack_key, 16); klv_encode_ber_length(pb, 28 + 12LL*mxf->body_partitions_count); if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) @@ -3029,13 +3032,12 @@ { MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; - int i, err = 0; + int i, err; if (!mxf->header_written || (s->oformat == &ff_mxf_opatom_muxer && !mxf->body_partition_offset)) { /* reason could be invalid options/not supported codec/out of memory */ - err = AVERROR_UNKNOWN; - goto end; + return AVERROR_UNKNOWN; } mxf->duration = mxf->last_indexed_edit_unit + mxf->edit_units_count; @@ -3044,10 +3046,10 @@ mxf->footer_partition_offset = avio_tell(pb); if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) { // no need to repeat index if ((err = mxf_write_partition(s, 0, 0, footer_partition_key, 0)) < 0) - goto end; + return err; } else { if ((err = mxf_write_partition(s, 0, 2, footer_partition_key, 0)) < 0) - goto end; + return err; mxf_write_klv_fill(s); mxf_write_index_table_segment(s); } @@ -3060,18 +3062,18 @@ /* rewrite body partition to update lengths */ avio_seek(pb, mxf->body_partition_offset[0], SEEK_SET); if ((err = mxf_write_opatom_body_partition(s)) < 0) - goto end; + return err; } avio_seek(pb, 0, SEEK_SET); if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer) { if ((err = mxf_write_partition(s, 1, 2, header_closed_partition_key, 1)) < 0) - goto end; + return err; mxf_write_klv_fill(s); mxf_write_index_table_segment(s); } else { if ((err = mxf_write_partition(s, 0, 0, header_closed_partition_key, 1)) < 0) - goto end; + return err; } // update footer partition offset for (i = 0; i < mxf->body_partitions_count; i++) { @@ -3080,17 +3082,19 @@ } } -end: - ff_audio_interleave_close(s); + return 0; +} + +static void mxf_deinit(AVFormatContext *s) +{ + MXFContext *mxf = s->priv_data; av_freep(&mxf->index_entries); av_freep(&mxf->body_partition_offset); - av_freep(&mxf->timecode_track->priv_data); - av_freep(&mxf->timecode_track); - - mxf_free(s); - - return err < 0 ? err : 0; + if (mxf->timecode_track) { + av_freep(&mxf->timecode_track->priv_data); + av_freep(&mxf->timecode_track); + } } static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) @@ -3098,26 +3102,26 @@ int i, stream_count = 0; for (i = 0; i < s->nb_streams; i++) - stream_count += !!s->streams[i]->last_in_packet_buffer; + stream_count += !!s->streams[i]->internal->last_in_packet_buffer; if (stream_count && (s->nb_streams == stream_count || flush)) { - AVPacketList *pktl = s->internal->packet_buffer; + PacketList *pktl = s->internal->packet_buffer; if (s->nb_streams != stream_count) { - AVPacketList *last = NULL; + PacketList *last = NULL; // find last packet in edit unit while (pktl) { if (!stream_count || pktl->pkt.stream_index == 0) break; // update last packet in packet buffer - if (s->streams[pktl->pkt.stream_index]->last_in_packet_buffer != pktl) - s->streams[pktl->pkt.stream_index]->last_in_packet_buffer = pktl; + if (s->streams[pktl->pkt.stream_index]->internal->last_in_packet_buffer != pktl) + s->streams[pktl->pkt.stream_index]->internal->last_in_packet_buffer = pktl; last = pktl; pktl = pktl->next; stream_count--; } // purge packet queue while (pktl) { - AVPacketList *next = pktl->next; + PacketList *next = pktl->next; av_packet_unref(&pktl->pkt); av_freep(&pktl); pktl = next; @@ -3135,20 +3139,20 @@ *out = pktl->pkt; av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", (*out).stream_index, (*out).dts); s->internal->packet_buffer = pktl->next; - if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl) - s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL; + if(s->streams[pktl->pkt.stream_index]->internal->last_in_packet_buffer == pktl) + s->streams[pktl->pkt.stream_index]->internal->last_in_packet_buffer= NULL; if(!s->internal->packet_buffer) s->internal->packet_buffer_end= NULL; av_freep(&pktl); return 1; } else { out: - av_init_packet(out); return 0; } } -static int mxf_compare_timestamps(AVFormatContext *s, AVPacket *next, AVPacket *pkt) +static int mxf_compare_timestamps(AVFormatContext *s, const AVPacket *next, + const AVPacket *pkt) { MXFStreamContext *sc = s->streams[pkt ->stream_index]->priv_data; MXFStreamContext *sc2 = s->streams[next->stream_index]->priv_data; @@ -3159,8 +3163,14 @@ static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush) { - return ff_audio_rechunk_interleave(s, out, pkt, flush, - mxf_interleave_get_packet, mxf_compare_timestamps); + int ret; + if (pkt) { + MXFStreamContext *sc = s->streams[pkt->stream_index]->priv_data; + pkt->pts = pkt->dts = sc->pkt_cnt++; + if ((ret = ff_interleave_add_packet(s, pkt, mxf_compare_timestamps)) < 0) + return ret; + } + return mxf_interleave_get_packet(s, out, NULL, flush); } #define MXF_COMMON_OPTIONS \ @@ -3240,6 +3250,7 @@ .write_header = mxf_write_header, .write_packet = mxf_write_packet, .write_trailer = mxf_write_footer, + .deinit = mxf_deinit, .flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, .priv_class = &mxf_muxer_class, @@ -3255,6 +3266,7 @@ .write_header = mxf_write_header, .write_packet = mxf_write_packet, .write_trailer = mxf_write_footer, + .deinit = mxf_deinit, .flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, .priv_class = &mxf_d10_muxer_class, @@ -3271,6 +3283,7 @@ .write_header = mxf_write_header, .write_packet = mxf_write_packet, .write_trailer = mxf_write_footer, + .deinit = mxf_deinit, .flags = AVFMT_NOTIMESTAMPS, .interleave_packet = mxf_interleave, .priv_class = &mxf_opatom_muxer_class, diff -Nru ffmpeg-4.2.2/libavformat/mxf.h ffmpeg-4.4/libavformat/mxf.h --- ffmpeg-4.2.2/libavformat/mxf.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/mxf.h 2021-04-08 21:28:40.000000000 +0000 @@ -59,6 +59,11 @@ SegmentedFrame, }; +typedef struct MXFContentPackageRate { + int rate; + AVRational tb; +} MXFContentPackageRate; + typedef struct KLVPacket { UID key; int64_t offset; @@ -73,6 +78,22 @@ RawVWrap } MXFWrappingIndicatorType; +typedef struct MXFLocalTagPair { + int local_tag; + UID uid; +} MXFLocalTagPair; + +extern const uint8_t ff_mxf_random_index_pack_key[16]; + +#define FF_MXF_MasteringDisplay_PREFIX 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x20,0x04,0x01,0x01 +#define FF_MXF_MasteringDisplayPrimaries { FF_MXF_MasteringDisplay_PREFIX,0x01,0x00,0x00 } +#define FF_MXF_MasteringDisplayWhitePointChromaticity { FF_MXF_MasteringDisplay_PREFIX,0x02,0x00,0x00 } +#define FF_MXF_MasteringDisplayMaximumLuminance { FF_MXF_MasteringDisplay_PREFIX,0x03,0x00,0x00 } +#define FF_MXF_MasteringDisplayMinimumLuminance { FF_MXF_MasteringDisplay_PREFIX,0x04,0x00,0x00 } + +#define FF_MXF_MASTERING_CHROMA_DEN 50000 +#define FF_MXF_MASTERING_LUMA_DEN 10000 + typedef struct MXFCodecUL { UID uid; unsigned matching_len; @@ -82,18 +103,15 @@ MXFWrappingIndicatorType wrapping_indicator_type; } MXFCodecUL; -typedef struct { - struct AVRational time_base; - int samples_per_frame[6]; -} MXFSamplesPerFrame; - extern const MXFCodecUL ff_mxf_data_definition_uls[]; extern const MXFCodecUL ff_mxf_codec_uls[]; extern const MXFCodecUL ff_mxf_pixel_format_uls[]; extern const MXFCodecUL ff_mxf_codec_tag_uls[]; +extern const MXFCodecUL ff_mxf_color_primaries_uls[]; +extern const MXFCodecUL ff_mxf_color_trc_uls[]; +extern const MXFCodecUL ff_mxf_color_space_uls[]; int ff_mxf_decode_pixel_layout(const char pixel_layout[16], enum AVPixelFormat *pix_fmt); -const MXFSamplesPerFrame *ff_mxf_get_samples_per_frame(AVFormatContext *s, AVRational time_base); int ff_mxf_get_content_package_rate(AVRational time_base); diff -Nru ffmpeg-4.2.2/libavformat/ncdec.c ffmpeg-4.4/libavformat/ncdec.c --- ffmpeg-4.2.2/libavformat/ncdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ncdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -83,7 +83,6 @@ ret = av_get_packet(s->pb, pkt, size); if (ret != size) { - if (ret > 0) av_packet_unref(pkt); return AVERROR(EIO); } diff -Nru ffmpeg-4.2.2/libavformat/network.c ffmpeg-4.4/libavformat/network.c --- ffmpeg-4.2.2/libavformat/network.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/network.c 2020-07-11 10:39:30.000000000 +0000 @@ -238,7 +238,7 @@ if (ret < 0) return ff_neterrno(); if (ff_socket_nonblock(ret, 1) < 0) - av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n"); + av_log(h, AV_LOG_DEBUG, "ff_socket_nonblock failed\n"); return ret; } @@ -264,7 +264,7 @@ socklen_t optlen; if (ff_socket_nonblock(fd, 1) < 0) - av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n"); + av_log(h, AV_LOG_DEBUG, "ff_socket_nonblock failed\n"); while ((ret = connect(fd, addr, addrlen))) { ret = ff_neterrno(); diff -Nru ffmpeg-4.2.2/libavformat/network.h ffmpeg-4.4/libavformat/network.h --- ffmpeg-4.2.2/libavformat/network.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/network.h 2020-07-11 10:39:30.000000000 +0000 @@ -50,6 +50,9 @@ #ifndef EINPROGRESS #define EINPROGRESS WSAEINPROGRESS #endif +#ifndef ENOTCONN +#define ENOTCONN WSAENOTCONN +#endif #define getsockopt(a, b, c, d, e) getsockopt(a, b, c, (char*) d, e) #define setsockopt(a, b, c, d, e) setsockopt(a, b, c, (const char*) d, e) diff -Nru ffmpeg-4.2.2/libavformat/nistspheredec.c ffmpeg-4.4/libavformat/nistspheredec.c --- ffmpeg-4.2.2/libavformat/nistspheredec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/nistspheredec.c 2021-02-20 20:27:47.000000000 +0000 @@ -90,6 +90,8 @@ return 0; } else if (!memcmp(buffer, "channel_count", 13)) { sscanf(buffer, "%*s %*s %u", &st->codecpar->channels); + if (st->codecpar->channels <= 0 || st->codecpar->channels > INT16_MAX) + return AVERROR_INVALIDDATA; } else if (!memcmp(buffer, "sample_byte_format", 18)) { sscanf(buffer, "%*s %*s %31s", format); @@ -109,10 +111,14 @@ sscanf(buffer, "%*s %*s %"SCNd64, &st->duration); } else if (!memcmp(buffer, "sample_n_bytes", 14)) { sscanf(buffer, "%*s %*s %d", &bps); + if (bps > INT16_MAX/8U) + return AVERROR_INVALIDDATA; } else if (!memcmp(buffer, "sample_rate", 11)) { sscanf(buffer, "%*s %*s %d", &st->codecpar->sample_rate); } else if (!memcmp(buffer, "sample_sig_bits", 15)) { sscanf(buffer, "%*s %*s %d", &st->codecpar->bits_per_coded_sample); + if (st->codecpar->bits_per_coded_sample <= 0 || st->codecpar->bits_per_coded_sample > INT16_MAX) + return AVERROR_INVALIDDATA; } else { char key[32], value[32]; if (sscanf(buffer, "%31s %*s %31s", key, value) == 2) { diff -Nru ffmpeg-4.2.2/libavformat/nsvdec.c ffmpeg-4.4/libavformat/nsvdec.c --- ffmpeg-4.2.2/libavformat/nsvdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/nsvdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -211,6 +211,7 @@ //static int nsv_load_index(AVFormatContext *s); static int nsv_read_chunk(AVFormatContext *s, int fill_header); +static int nsv_read_close(AVFormatContext *s); /* try to find something we recognize, and set the state accordingly */ static int nsv_resync(AVFormatContext *s) @@ -492,25 +493,32 @@ nsv->ahead[0].data = nsv->ahead[1].data = NULL; for (i = 0; i < NSV_MAX_RESYNC_TRIES; i++) { - if (nsv_resync(s) < 0) - return -1; + err = nsv_resync(s); + if (err < 0) + goto fail; if (nsv->state == NSV_FOUND_NSVF) { err = nsv_parse_NSVf_header(s); if (err < 0) - return err; + goto fail; } /* we need the first NSVs also... */ if (nsv->state == NSV_FOUND_NSVS) { err = nsv_parse_NSVs_header(s); if (err < 0) - return err; + goto fail; break; /* we just want the first one */ } } - if (s->nb_streams < 1) /* no luck so far */ - return -1; + if (s->nb_streams < 1) { /* no luck so far */ + err = AVERROR_INVALIDDATA; + goto fail; + } + /* now read the first chunk, so we can attempt to decode more info */ err = nsv_read_chunk(s, 1); +fail: + if (err < 0) + nsv_read_close(s); av_log(s, AV_LOG_TRACE, "parsed header\n"); return err; @@ -654,10 +662,8 @@ /* now pick one of the plates */ for (i = 0; i < 2; i++) { if (nsv->ahead[i].data) { - /* avoid the cost of new_packet + memcpy(->data) */ - memcpy(pkt, &nsv->ahead[i], sizeof(AVPacket)); - nsv->ahead[i].data = NULL; /* we ate that one */ - return pkt->size; + av_packet_move_ref(pkt, &nsv->ahead[i]); + return 0; } } diff -Nru ffmpeg-4.2.2/libavformat/nut.c ffmpeg-4.4/libavformat/nut.c --- ffmpeg-4.2.2/libavformat/nut.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/nut.c 2021-04-08 21:28:40.000000000 +0000 @@ -27,6 +27,8 @@ const AVCodecTag ff_nut_subtitle_tags[] = { { AV_CODEC_ID_TEXT, MKTAG('U', 'T', 'F', '8') }, + { AV_CODEC_ID_ASS, MKTAG('S', 'S', 'A', 0 ) }, + { AV_CODEC_ID_ASS, MKTAG('A', 'S', 'S', 0 ) }, { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('D', 'V', 'D', 'S') }, { AV_CODEC_ID_DVB_SUBTITLE, MKTAG('D', 'V', 'B', 'S') }, { AV_CODEC_ID_DVB_TELETEXT, MKTAG('D', 'V', 'B', 'T') }, @@ -227,6 +229,8 @@ { AV_CODEC_ID_PCM_S24LE, MKTAG('P', 'S', 'D', 24 ) }, { AV_CODEC_ID_PCM_S32BE, MKTAG(32 , 'D', 'S', 'P') }, { AV_CODEC_ID_PCM_S32LE, MKTAG('P', 'S', 'D', 32 ) }, + { AV_CODEC_ID_PCM_S64BE, MKTAG(64 , 'D', 'S', 'P') }, + { AV_CODEC_ID_PCM_S64LE, MKTAG('P', 'S', 'D', 64 ) }, { AV_CODEC_ID_PCM_S8, MKTAG('P', 'S', 'D', 8 ) }, { AV_CODEC_ID_PCM_U16BE, MKTAG(16 , 'D', 'U', 'P') }, { AV_CODEC_ID_PCM_U16LE, MKTAG('P', 'U', 'D', 16 ) }, diff -Nru ffmpeg-4.2.2/libavformat/nutdec.c ffmpeg-4.4/libavformat/nutdec.c --- ffmpeg-4.2.2/libavformat/nutdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/nutdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -193,13 +193,13 @@ { AVFormatContext *s = nut->avf; AVIOContext *bc = s->pb; - uint64_t tmp, end; + uint64_t tmp, end, length; unsigned int stream_count; int i, j, count, ret; int tmp_stream, tmp_mul, tmp_pts, tmp_size, tmp_res, tmp_head_idx; - end = get_packetheader(nut, bc, 1, MAIN_STARTCODE); - end += avio_tell(bc); + length = get_packetheader(nut, bc, 1, MAIN_STARTCODE); + end = length + avio_tell(bc); nut->version = ffio_read_varlen(bc); if (nut->version < NUT_MIN_VERSION || @@ -219,7 +219,7 @@ nut->max_distance = 65536; } - GET_V(nut->time_base_count, tmp > 0 && tmp < INT_MAX / sizeof(AVRational)); + GET_V(nut->time_base_count, tmp > 0 && tmp < INT_MAX / sizeof(AVRational) && tmp < length/2); nut->time_base = av_malloc_array(nut->time_base_count, sizeof(AVRational)); if (!nut->time_base) return AVERROR(ENOMEM); @@ -260,7 +260,7 @@ if (tmp_fields > 5) count = ffio_read_varlen(bc); else - count = tmp_mul - tmp_size; + count = tmp_mul - (unsigned)tmp_size; if (tmp_fields > 6) get_s(bc); if (tmp_fields > 7) @@ -427,8 +427,10 @@ GET_V(st->codecpar->extradata_size, tmp < (1 << 30)); if (st->codecpar->extradata_size) { - if (ff_get_extradata(s, st->codecpar, bc, st->codecpar->extradata_size) < 0) - return AVERROR(ENOMEM); + ret = ff_get_extradata(s, st->codecpar, bc, + st->codecpar->extradata_size); + if (ret < 0) + return ret; } if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -487,8 +489,8 @@ AVIOContext *bc = s->pb; uint64_t tmp, chapter_start, chapter_len; unsigned int stream_id_plus1, count; - int chapter_id, i, ret = 0; - int64_t value, end; + int i, ret = 0; + int64_t chapter_id, value, end; char name[256], str_value[1024], type_str[256]; const char *type; int *event_flags = NULL; @@ -1275,13 +1277,13 @@ av_assert0(sp); pos2 = sp->back_ptr - 15; } - av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2); + av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2); pos = find_startcode(s->pb, SYNCPOINT_STARTCODE, pos2); avio_seek(s->pb, pos, SEEK_SET); nut->last_syncpoint_pos = pos; - av_log(NULL, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos); + av_log(s, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos); if (pos2 > pos || pos2 + 15 < pos) - av_log(NULL, AV_LOG_ERROR, "no syncpoint at backptr pos\n"); + av_log(s, AV_LOG_ERROR, "no syncpoint at backptr pos\n"); for (i = 0; i < s->nb_streams; i++) nut->stream[i].skip_until_key_frame = 1; diff -Nru ffmpeg-4.2.2/libavformat/nutenc.c ffmpeg-4.4/libavformat/nutenc.c --- ffmpeg-4.2.2/libavformat/nutenc.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/nutenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -277,11 +277,37 @@ nut->frame_code['N'].flags = FLAG_INVALID; } +/** + * Get the length in bytes which is needed to store val as v. + */ +static int get_v_length(uint64_t val) +{ + int i = 1; + + while (val >>= 7) + i++; + + return i; +} + +/** + * Put val using a variable number of bytes. + */ +static void put_v(AVIOContext *bc, uint64_t val) +{ + int i = get_v_length(val); + + while (--i > 0) + avio_w8(bc, 128 | (uint8_t)(val >> (7*i))); + + avio_w8(bc, val & 127); +} + static void put_tt(NUTContext *nut, AVRational *time_base, AVIOContext *bc, uint64_t val) { val *= nut->time_base_count; val += time_base - nut->time_base; - ff_put_v(bc, val); + put_v(bc, val); } /** * Store a string as vb. @@ -290,37 +316,34 @@ { size_t len = strlen(string); - ff_put_v(bc, len); + put_v(bc, len); avio_write(bc, string, len); } static void put_s(AVIOContext *bc, int64_t val) { - ff_put_v(bc, 2 * FFABS(val) - (val > 0)); + put_v(bc, 2 * FFABS(val) - (val > 0)); } -//FIXME remove calculate_checksum static void put_packet(NUTContext *nut, AVIOContext *bc, AVIOContext *dyn_bc, - int calculate_checksum, uint64_t startcode) + uint64_t startcode) { uint8_t *dyn_buf = NULL; - int dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf); - int forw_ptr = dyn_size + 4 * calculate_checksum; + int dyn_size = avio_get_dyn_buf(dyn_bc, &dyn_buf); + int forw_ptr = dyn_size + 4; if (forw_ptr > 4096) ffio_init_checksum(bc, ff_crc04C11DB7_update, 0); avio_wb64(bc, startcode); - ff_put_v(bc, forw_ptr); + put_v(bc, forw_ptr); if (forw_ptr > 4096) avio_wl32(bc, ffio_get_checksum(bc)); - if (calculate_checksum) - ffio_init_checksum(bc, ff_crc04C11DB7_update, 0); + ffio_init_checksum(bc, ff_crc04C11DB7_update, 0); avio_write(bc, dyn_buf, dyn_size); - if (calculate_checksum) - avio_wl32(bc, ffio_get_checksum(bc)); + avio_wl32(bc, ffio_get_checksum(bc)); - av_free(dyn_buf); + ffio_reset_dyn_buf(dyn_bc); } static void write_mainheader(NUTContext *nut, AVIOContext *bc) @@ -329,16 +352,16 @@ tmp_head_idx; int64_t tmp_match; - ff_put_v(bc, nut->version); + put_v(bc, nut->version); if (nut->version > 3) - ff_put_v(bc, nut->minor_version = 1); - ff_put_v(bc, nut->avf->nb_streams); - ff_put_v(bc, nut->max_distance); - ff_put_v(bc, nut->time_base_count); + put_v(bc, nut->minor_version = 1); + put_v(bc, nut->avf->nb_streams); + put_v(bc, nut->max_distance); + put_v(bc, nut->time_base_count); for (i = 0; i < nut->time_base_count; i++) { - ff_put_v(bc, nut->time_base[i].num); - ff_put_v(bc, nut->time_base[i].den); + put_v(bc, nut->time_base[i].num); + put_v(bc, nut->time_base[i].den); } tmp_pts = 0; @@ -382,25 +405,25 @@ if (j != tmp_mul - tmp_size) tmp_fields = 6; - ff_put_v(bc, tmp_flags); - ff_put_v(bc, tmp_fields); + put_v(bc, tmp_flags); + put_v(bc, tmp_fields); if (tmp_fields > 0) put_s(bc, tmp_pts); - if (tmp_fields > 1) ff_put_v(bc, tmp_mul); - if (tmp_fields > 2) ff_put_v(bc, tmp_stream); - if (tmp_fields > 3) ff_put_v(bc, tmp_size); - if (tmp_fields > 4) ff_put_v(bc, 0 /*tmp_res*/); - if (tmp_fields > 5) ff_put_v(bc, j); - if (tmp_fields > 6) ff_put_v(bc, tmp_match); - if (tmp_fields > 7) ff_put_v(bc, tmp_head_idx); + if (tmp_fields > 1) put_v(bc, tmp_mul); + if (tmp_fields > 2) put_v(bc, tmp_stream); + if (tmp_fields > 3) put_v(bc, tmp_size); + if (tmp_fields > 4) put_v(bc, 0 /*tmp_res*/); + if (tmp_fields > 5) put_v(bc, j); + if (tmp_fields > 6) put_v(bc, tmp_match); + if (tmp_fields > 7) put_v(bc, tmp_head_idx); } - ff_put_v(bc, nut->header_count - 1); + put_v(bc, nut->header_count - 1); for (i = 1; i < nut->header_count; i++) { - ff_put_v(bc, nut->header_len[i]); + put_v(bc, nut->header_len[i]); avio_write(bc, nut->header[i], nut->header_len[i]); } // flags had been effectively introduced in version 4 if (nut->version > 3) - ff_put_v(bc, nut->flags); + put_v(bc, nut->flags); } static int write_streamheader(AVFormatContext *avctx, AVIOContext *bc, @@ -409,14 +432,14 @@ NUTContext *nut = avctx->priv_data; AVCodecParameters *par = st->codecpar; - ff_put_v(bc, i); + put_v(bc, i); switch (par->codec_type) { - case AVMEDIA_TYPE_VIDEO: ff_put_v(bc, 0); break; - case AVMEDIA_TYPE_AUDIO: ff_put_v(bc, 1); break; - case AVMEDIA_TYPE_SUBTITLE: ff_put_v(bc, 2); break; - default: ff_put_v(bc, 3); break; + case AVMEDIA_TYPE_VIDEO: put_v(bc, 0); break; + case AVMEDIA_TYPE_AUDIO: put_v(bc, 1); break; + case AVMEDIA_TYPE_SUBTITLE: put_v(bc, 2); break; + default: put_v(bc, 3); break; } - ff_put_v(bc, 4); + put_v(bc, 4); if (par->codec_tag) { avio_wl32(bc, par->codec_tag); @@ -425,34 +448,34 @@ return AVERROR(EINVAL); } - ff_put_v(bc, nut->stream[i].time_base - nut->time_base); - ff_put_v(bc, nut->stream[i].msb_pts_shift); - ff_put_v(bc, nut->stream[i].max_pts_distance); - ff_put_v(bc, par->video_delay); + put_v(bc, nut->stream[i].time_base - nut->time_base); + put_v(bc, nut->stream[i].msb_pts_shift); + put_v(bc, nut->stream[i].max_pts_distance); + put_v(bc, par->video_delay); avio_w8(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */ - ff_put_v(bc, par->extradata_size); + put_v(bc, par->extradata_size); avio_write(bc, par->extradata, par->extradata_size); switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: - ff_put_v(bc, par->sample_rate); - ff_put_v(bc, 1); - ff_put_v(bc, par->channels); + put_v(bc, par->sample_rate); + put_v(bc, 1); + put_v(bc, par->channels); break; case AVMEDIA_TYPE_VIDEO: - ff_put_v(bc, par->width); - ff_put_v(bc, par->height); + put_v(bc, par->width); + put_v(bc, par->height); if (st->sample_aspect_ratio.num <= 0 || st->sample_aspect_ratio.den <= 0) { - ff_put_v(bc, 0); - ff_put_v(bc, 0); + put_v(bc, 0); + put_v(bc, 0); } else { - ff_put_v(bc, st->sample_aspect_ratio.num); - ff_put_v(bc, st->sample_aspect_ratio.den); + put_v(bc, st->sample_aspect_ratio.num); + put_v(bc, st->sample_aspect_ratio.den); } - ff_put_v(bc, 0); /* csp type -- unknown */ + put_v(bc, 0); /* csp type -- unknown */ break; default: break; @@ -483,12 +506,12 @@ while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) count += add_info(dyn_bc, t->key, t->value); - ff_put_v(bc, 0); //stream_if_plus1 - ff_put_v(bc, 0); //chapter_id - ff_put_v(bc, 0); //timestamp_start - ff_put_v(bc, 0); //length + put_v(bc, 0); //stream_if_plus1 + put_v(bc, 0); //chapter_id + put_v(bc, 0); //timestamp_start + put_v(bc, 0); //length - ff_put_v(bc, count); + put_v(bc, count); dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf); avio_write(bc, dyn_buf, dyn_size); @@ -524,12 +547,12 @@ dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf); if (count) { - ff_put_v(bc, stream_id + 1); //stream_id_plus1 - ff_put_v(bc, 0); //chapter_id - ff_put_v(bc, 0); //timestamp_start - ff_put_v(bc, 0); //length + put_v(bc, stream_id + 1); //stream_id_plus1 + put_v(bc, 0); //chapter_id + put_v(bc, 0); //timestamp_start + put_v(bc, 0); //length - ff_put_v(bc, count); + put_v(bc, count); avio_write(bc, dyn_buf, dyn_size); } @@ -550,15 +573,15 @@ if (ret < 0) return ret; - ff_put_v(bc, 0); // stream_id_plus1 + put_v(bc, 0); // stream_id_plus1 put_s(bc, id + 1); // chapter_id put_tt(nut, nut->chapter[id].time_base, bc, ch->start); // chapter_start - ff_put_v(bc, ch->end - ch->start); // chapter_len + put_v(bc, ch->end - ch->start); // chapter_len while ((t = av_dict_get(ch->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) count += add_info(dyn_bc, t->key, t->value); - ff_put_v(bc, count); + put_v(bc, count); dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf); avio_write(bc, dyn_buf, dyn_size); @@ -575,11 +598,11 @@ put_tt(nut, nut->max_pts_tb, bc, nut->max_pts); - ff_put_v(bc, nut->sp_count); + put_v(bc, nut->sp_count); for (i=0; isp_count; i++) { av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pos_cmp, (void**)next_node); - ff_put_v(bc, (next_node[1]->pos >> 4) - (dummy.pos>>4)); + put_v(bc, (next_node[1]->pos >> 4) - (dummy.pos>>4)); dummy.pos = next_node[1]->pos; } @@ -600,12 +623,12 @@ for (; jsp_count && (nus->keyframe_pts[j] != AV_NOPTS_VALUE) == flag; j++) n++; - ff_put_v(bc, 1 + 2*flag + 4*n); + put_v(bc, 1 + 2 * flag + 4 * n); for (k= j - n; k<=j && ksp_count; k++) { if (nus->keyframe_pts[k] == AV_NOPTS_VALUE) continue; av_assert0(nus->keyframe_pts[k] > last_pts); - ff_put_v(bc, nus->keyframe_pts[k] - last_pts); + put_v(bc, nus->keyframe_pts[k] - last_pts); last_pts = nus->keyframe_pts[k]; } } @@ -630,52 +653,44 @@ if (ret < 0) return ret; write_mainheader(nut, dyn_bc); - put_packet(nut, bc, dyn_bc, 1, MAIN_STARTCODE); + put_packet(nut, bc, dyn_bc, MAIN_STARTCODE); for (i = 0; i < nut->avf->nb_streams; i++) { - ret = avio_open_dyn_buf(&dyn_bc); - if (ret < 0) - return ret; ret = write_streamheader(avctx, dyn_bc, nut->avf->streams[i], i); - if (ret < 0) - return ret; - put_packet(nut, bc, dyn_bc, 1, STREAM_STARTCODE); + if (ret < 0) { + goto fail; + } + put_packet(nut, bc, dyn_bc, STREAM_STARTCODE); } - ret = avio_open_dyn_buf(&dyn_bc); - if (ret < 0) - return ret; write_globalinfo(nut, dyn_bc); - put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE); + put_packet(nut, bc, dyn_bc, INFO_STARTCODE); for (i = 0; i < nut->avf->nb_streams; i++) { - ret = avio_open_dyn_buf(&dyn_bc); - if (ret < 0) - return ret; ret = write_streaminfo(nut, dyn_bc, i); - if (ret < 0) - return ret; if (ret > 0) - put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE); - else - ffio_free_dyn_buf(&dyn_bc); + put_packet(nut, bc, dyn_bc, INFO_STARTCODE); + else if (ret < 0) { + goto fail; + } } for (i = 0; i < nut->avf->nb_chapters; i++) { - ret = avio_open_dyn_buf(&dyn_bc); - if (ret < 0) - return ret; ret = write_chapter(nut, dyn_bc, i); if (ret < 0) { - ffio_free_dyn_buf(&dyn_bc); - return ret; + goto fail; } - put_packet(nut, bc, dyn_bc, 1, INFO_STARTCODE); + put_packet(nut, bc, dyn_bc, INFO_STARTCODE); } nut->last_syncpoint_pos = INT_MIN; nut->header_count++; - return 0; + + ret = 0; +fail: + ffio_free_dyn_buf(&dyn_bc); + + return ret; } static int nut_write_header(AVFormatContext *s) @@ -700,12 +715,8 @@ nut->chapter = av_calloc(s->nb_chapters, sizeof(*nut->chapter)); nut->time_base= av_calloc(s->nb_streams + s->nb_chapters, sizeof(*nut->time_base)); - if (!nut->stream || !nut->chapter || !nut->time_base) { - av_freep(&nut->stream); - av_freep(&nut->chapter); - av_freep(&nut->time_base); + if (!nut->stream || !nut->chapter || !nut->time_base) return AVERROR(ENOMEM); - } for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; @@ -765,8 +776,6 @@ if (s->avoid_negative_ts < 0) s->avoid_negative_ts = 1; - avio_flush(bc); - return 0; } @@ -879,7 +888,7 @@ } put_s(dyn_bc, -2); put_str(dyn_bc, "bin"); - ff_put_v(dyn_bc, pkt->side_data[i].size); + put_v(dyn_bc, pkt->side_data[i].size); avio_write(dyn_bc, data, pkt->side_data[i].size); sm_data_count++; break; @@ -894,7 +903,7 @@ put_str(dyn_bc, "ChannelLayout"); put_s(dyn_bc, -2); put_str(dyn_bc, "u64"); - ff_put_v(bc, 8); + put_v(dyn_bc, 8); avio_write(dyn_bc, data, 8); data+=8; sm_data_count++; } @@ -933,7 +942,7 @@ } fail: - ff_put_v(bc, sm_data_count); + put_v(bc, sm_data_count); dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf); avio_write(bc, dyn_buf, dyn_size); av_freep(&dyn_buf); @@ -1019,13 +1028,14 @@ if (ret < 0) goto fail; put_tt(nut, nus->time_base, dyn_bc, pkt->dts); - ff_put_v(dyn_bc, sp_pos != INT64_MAX ? (nut->last_syncpoint_pos - sp_pos) >> 4 : 0); + put_v(dyn_bc, sp_pos != INT64_MAX ? (nut->last_syncpoint_pos - sp_pos) >> 4 : 0); if (nut->flags & NUT_BROADCAST) { put_tt(nut, nus->time_base, dyn_bc, av_rescale_q(av_gettime(), AV_TIME_BASE_Q, *nus->time_base)); } - put_packet(nut, bc, dyn_bc, 1, SYNCPOINT_STARTCODE); + put_packet(nut, bc, dyn_bc, SYNCPOINT_STARTCODE); + ffio_free_dyn_buf(&dyn_bc); if (nut->write_index) { if ((ret = ff_nut_add_sp(nut, nut->last_syncpoint_pos, 0 /*unused*/, pkt->dts)) < 0) @@ -1076,18 +1086,18 @@ continue; if (flags & FLAG_STREAM_ID) - length += ff_get_v_length(pkt->stream_index); + length += get_v_length(pkt->stream_index); if (data_size % fc->size_mul != fc->size_lsb) continue; if (flags & FLAG_SIZE_MSB) - length += ff_get_v_length(data_size / fc->size_mul); + length += get_v_length(data_size / fc->size_mul); if (flags & FLAG_CHECKSUM) length += 4; if (flags & FLAG_CODED_PTS) - length += ff_get_v_length(coded_pts); + length += get_v_length(coded_pts); if ( (flags & FLAG_CODED) && nut->header_len[best_header_idx] > nut->header_len[fc->header_idx] + 1) { @@ -1119,13 +1129,13 @@ ffio_init_checksum(bc, ff_crc04C11DB7_update, 0); avio_w8(bc, frame_code); if (flags & FLAG_CODED) { - ff_put_v(bc, (flags ^ needed_flags) & ~(FLAG_CODED)); + put_v(bc, (flags ^ needed_flags) & ~(FLAG_CODED)); flags = needed_flags; } - if (flags & FLAG_STREAM_ID) ff_put_v(bc, pkt->stream_index); - if (flags & FLAG_CODED_PTS) ff_put_v(bc, coded_pts); - if (flags & FLAG_SIZE_MSB ) ff_put_v(bc, data_size / fc->size_mul); - if (flags & FLAG_HEADER_IDX) ff_put_v(bc, header_idx = best_header_idx); + if (flags & FLAG_STREAM_ID) put_v(bc, pkt->stream_index); + if (flags & FLAG_CODED_PTS) put_v(bc, coded_pts); + if (flags & FLAG_SIZE_MSB ) put_v(bc, data_size / fc->size_mul); + if (flags & FLAG_HEADER_IDX) put_v(bc, header_idx = best_header_idx); if (flags & FLAG_CHECKSUM) avio_wl32(bc, ffio_get_checksum(bc)); else ffio_get_checksum(bc); @@ -1171,11 +1181,15 @@ while (nut->header_count < 3) write_headers(s, bc); + if (!nut->sp_count) + return 0; + ret = avio_open_dyn_buf(&dyn_bc); - if (ret >= 0 && nut->sp_count) { + if (ret >= 0) { av_assert1(nut->write_index); // sp_count should be 0 if no index is going to be written write_index(nut, dyn_bc); - put_packet(nut, bc, dyn_bc, 1, INDEX_STARTCODE); + put_packet(nut, bc, dyn_bc, INDEX_STARTCODE); + ffio_free_dyn_buf(&dyn_bc); } return 0; diff -Nru ffmpeg-4.2.2/libavformat/nuv.c ffmpeg-4.4/libavformat/nuv.c --- ffmpeg-4.2.2/libavformat/nuv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/nuv.c 2021-02-20 20:27:47.000000000 +0000 @@ -74,7 +74,7 @@ if (!vst && !myth) return 1; // no codec data needed while (!avio_feof(pb)) { - int size, subtype; + int size, subtype, ret; frametype = avio_r8(pb); switch (frametype) { @@ -83,12 +83,8 @@ avio_skip(pb, 6); size = PKTSIZE(avio_rl32(pb)); if (vst && subtype == 'R') { - if (vst->codecpar->extradata) { - av_freep(&vst->codecpar->extradata); - vst->codecpar->extradata_size = 0; - } - if (ff_get_extradata(NULL, vst->codecpar, pb, size) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_get_extradata(NULL, vst->codecpar, pb, size)) < 0) + return ret; size = 0; if (!myth) return 0; @@ -121,6 +117,10 @@ ast->codecpar->bits_per_coded_sample = avio_rl32(pb); ast->codecpar->channels = avio_rl32(pb); ast->codecpar->channel_layout = 0; + if (ast->codecpar->channels <= 0) { + av_log(s, AV_LOG_ERROR, "Invalid channels %d\n", ast->codecpar->channels); + return AVERROR_INVALIDDATA; + } id = ff_wav_codec_get_id(ast->codecpar->codec_tag, ast->codecpar->bits_per_coded_sample); @@ -288,7 +288,6 @@ memcpy(pkt->data, hdr, copyhdrsize); ret = avio_read(pb, pkt->data + copyhdrsize, size); if (ret < 0) { - av_packet_unref(pkt); return ret; } if (ret < size) diff -Nru ffmpeg-4.2.2/libavformat/oggdec.c ffmpeg-4.4/libavformat/oggdec.c --- ffmpeg-4.2.2/libavformat/oggdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/oggdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -31,6 +31,7 @@ #include #include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" +#include "avio_internal.h" #include "oggdec.h" #include "avformat.h" #include "internal.h" @@ -41,7 +42,6 @@ static const struct ogg_codec * const ogg_codecs[] = { &ff_skeleton_codec, - &ff_daala_codec, &ff_dirac_codec, &ff_speex_codec, &ff_vorbis_codec, @@ -177,6 +177,7 @@ if (start_pos <= s->internal->data_offset) { os->lastpts = 0; } + os->start_trimming = 0; os->end_trimming = 0; av_freep(&os->new_metadata); os->new_metadata_size = 0; @@ -205,59 +206,43 @@ * situation where a new audio stream spawn (identified with a new serial) and * must replace the previous one (track switch). */ -static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs) +static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic, int page_size, + int probing) { struct ogg *ogg = s->priv_data; struct ogg_stream *os; const struct ogg_codec *codec; int i = 0; - if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { - uint8_t magic[8]; - int64_t pos = avio_tell(s->pb); - avio_skip(s->pb, nsegs); - avio_read(s->pb, magic, sizeof(magic)); - avio_seek(s->pb, pos, SEEK_SET); - codec = ogg_find_codec(magic, sizeof(magic)); - if (!codec) { - av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n"); - return AVERROR_INVALIDDATA; - } - for (i = 0; i < ogg->nstreams; i++) { - if (ogg->streams[i].codec == codec) - break; - } - if (i >= ogg->nstreams) - return ogg_new_stream(s, serial); - } else if (ogg->nstreams != 1) { + if (ogg->nstreams != 1) { avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg"); return AVERROR_PATCHWELCOME; } - os = &ogg->streams[i]; - - os->serial = serial; - return i; - -#if 0 - buf = os->buf; - bufsize = os->bufsize; - codec = os->codec; + /* Check for codecs */ + codec = ogg_find_codec(magic, page_size); + if (!codec && !probing) { + av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n"); + return AVERROR_INVALIDDATA; + } - if (!ogg->state || ogg->state->streams[i].private != os->private) - av_freep(&ogg->streams[i].private); + os = &ogg->streams[0]; + if (os->codec != codec) + return AVERROR(EINVAL); - /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We - * also re-use the ogg_stream allocated buffer */ - memset(os, 0, sizeof(*os)); os->serial = serial; - os->bufsize = bufsize; - os->buf = buf; - os->header = -1; os->codec = codec; + os->serial = serial; + os->lastpts = 0; + os->lastdts = 0; + os->start_trimming = 0; + os->end_trimming = 0; + + /* Chained files have extradata as a new packet */ + if (codec == &ff_opus_codec) + os->header = -1; return i; -#endif } static int ogg_new_stream(AVFormatContext *s, uint32_t serial) @@ -302,27 +287,6 @@ return idx; } -static int ogg_new_buf(struct ogg *ogg, int idx) -{ - struct ogg_stream *os = ogg->streams + idx; - uint8_t *nb = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE); - int size = os->bufpos - os->pstart; - - if (!nb) - return AVERROR(ENOMEM); - - if (os->buf) { - memcpy(nb, os->buf + os->pstart, size); - av_free(os->buf); - } - - os->buf = nb; - os->bufpos = size; - os->pstart = 0; - - return 0; -} - static int data_packets_seen(const struct ogg *ogg) { int i; @@ -333,7 +297,21 @@ return 0; } -static int ogg_read_page(AVFormatContext *s, int *sid) +static int buf_realloc(struct ogg_stream *os, int size) +{ + /* Even if invalid guarantee there's enough memory to read the page */ + if (os->bufsize - os->bufpos < size) { + uint8_t *nb = av_realloc(os->buf, 2*os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE); + if (!nb) + return AVERROR(ENOMEM); + os->buf = nb; + os->bufsize *= 2; + } + + return 0; +} + +static int ogg_read_page(AVFormatContext *s, int *sid, int probing) { AVIOContext *bc = s->pb; struct ogg *ogg = s->priv_data; @@ -342,8 +320,13 @@ int flags, nsegs; uint64_t gp; uint32_t serial; - int size, idx; + uint32_t crc, crc_tmp; + int size = 0, idx; + int64_t version, page_pos; + int64_t start_pos; uint8_t sync[4]; + uint8_t segments[255]; + uint8_t *readout_buf; int sp = 0; ret = avio_read(bc, sync, 4); @@ -377,53 +360,109 @@ return AVERROR_INVALIDDATA; } - if (avio_r8(bc) != 0) { /* version */ - av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n"); - return AVERROR_INVALIDDATA; - } + /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */ + ffio_init_checksum(bc, ff_crc04C11DB7_update, 0x4fa9b05f); - flags = avio_r8(bc); - gp = avio_rl64(bc); - serial = avio_rl32(bc); - avio_skip(bc, 8); /* seq, crc */ - nsegs = avio_r8(bc); + /* To rewind if checksum is bad/check magic on switches - this is the max packet size */ + ffio_ensure_seekback(bc, MAX_PAGE_SIZE); + start_pos = avio_tell(bc); + + version = avio_r8(bc); + flags = avio_r8(bc); + gp = avio_rl64(bc); + serial = avio_rl32(bc); + avio_skip(bc, 4); /* seq */ + + crc_tmp = ffio_get_checksum(bc); + crc = avio_rb32(bc); + crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4); + ffio_init_checksum(bc, ff_crc04C11DB7_update, crc_tmp); + + nsegs = avio_r8(bc); + page_pos = avio_tell(bc) - 27; + + ret = avio_read(bc, segments, nsegs); + if (ret < nsegs) + return ret < 0 ? ret : AVERROR_EOF; + + for (i = 0; i < nsegs; i++) + size += segments[i]; idx = ogg_find_stream(ogg, serial); + if (idx >= 0) { + os = ogg->streams + idx; + + ret = buf_realloc(os, size); + if (ret < 0) + return ret; + + readout_buf = os->buf + os->bufpos; + } else { + readout_buf = av_malloc(size); + } + + ret = avio_read(bc, readout_buf, size); + if (ret < size) { + if (idx < 0) + av_free(readout_buf); + return ret < 0 ? ret : AVERROR_EOF; + } + + if (crc ^ ffio_get_checksum(bc)) { + av_log(s, AV_LOG_ERROR, "CRC mismatch!\n"); + if (idx < 0) + av_free(readout_buf); + avio_seek(bc, start_pos, SEEK_SET); + *sid = -1; + return 0; + } + + /* Since we're almost sure its a valid packet, checking the version after + * the checksum lets the demuxer be more tolerant */ + if (version) { + av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n"); + if (idx < 0) + av_free(readout_buf); + avio_seek(bc, start_pos, SEEK_SET); + *sid = -1; + return 0; + } + + /* CRC is correct so we can be 99% sure there's an actual change here */ if (idx < 0) { if (data_packets_seen(ogg)) - idx = ogg_replace_stream(s, serial, nsegs); + idx = ogg_replace_stream(s, serial, readout_buf, size, probing); else idx = ogg_new_stream(s, serial); if (idx < 0) { av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n"); + av_free(readout_buf); return idx; } - } - os = ogg->streams + idx; - ogg->page_pos = - os->page_pos = avio_tell(bc) - 27; + os = ogg->streams + idx; - if (os->psize > 0) { - ret = ogg_new_buf(ogg, idx); - if (ret < 0) + ret = buf_realloc(os, size); + if (ret < 0) { + av_free(readout_buf); return ret; - } - - ret = avio_read(bc, os->segments, nsegs); - if (ret < nsegs) - return ret < 0 ? ret : AVERROR_EOF; - - os->nsegs = nsegs; - os->segp = 0; + } - size = 0; - for (i = 0; i < nsegs; i++) - size += os->segments[i]; + memcpy(os->buf + os->bufpos, readout_buf, size); + av_free(readout_buf); + } - if (!(flags & OGG_FLAG_BOS)) - os->got_data = 1; + ogg->page_pos = page_pos; + os->page_pos = page_pos; + os->nsegs = nsegs; + os->segp = 0; + os->got_data = !(flags & OGG_FLAG_BOS); + os->bufpos += size; + os->granule = gp; + os->flags = flags; + memcpy(os->segments, segments, nsegs); + memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE); if (flags & OGG_FLAG_CONT || os->incomplete) { if (!os->psize) { @@ -443,26 +482,8 @@ os->sync_pos = os->page_pos; } - if (os->bufsize - os->bufpos < size) { - uint8_t *nb = av_malloc((os->bufsize *= 2) + AV_INPUT_BUFFER_PADDING_SIZE); - if (!nb) - return AVERROR(ENOMEM); - memcpy(nb, os->buf, os->bufpos); - av_free(os->buf); - os->buf = nb; - } - - ret = avio_read(bc, os->buf + os->bufpos, size); - if (ret < size) - return ret < 0 ? ret : AVERROR_EOF; - - os->bufpos += size; - os->granule = gp; - os->flags = flags; - - memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE); - if (sid) - *sid = idx; + /* This function is always called with sid != NULL */ + *sid = idx; return 0; } @@ -491,7 +512,7 @@ idx = ogg->curidx; while (idx < 0) { - ret = ogg_read_page(s, &idx); + ret = ogg_read_page(s, &idx, 0); if (ret < 0) return ret; } @@ -642,8 +663,8 @@ avio_seek(s->pb, end, SEEK_SET); ogg->page_pos = -1; - while (!ogg_read_page(s, &i)) { - if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 && + while (!ogg_read_page(s, &i, 1)) { + if (i >= 0 && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 && ogg->streams[i].codec) { s->streams[i]->duration = ogg_gptopts(s, i, ogg->streams[i].granule, NULL); @@ -846,32 +867,29 @@ pkt->duration = os->pduration; pkt->pos = fpos; - if (os->end_trimming) { + if (os->start_trimming || os->end_trimming) { uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10); if(!side_data) - goto fail; + return AVERROR(ENOMEM); + AV_WL32(side_data + 0, os->start_trimming); AV_WL32(side_data + 4, os->end_trimming); + os->start_trimming = 0; os->end_trimming = 0; } if (os->new_metadata) { - uint8_t *side_data = av_packet_new_side_data(pkt, - AV_PKT_DATA_METADATA_UPDATE, - os->new_metadata_size); - if(!side_data) - goto fail; + ret = av_packet_add_side_data(pkt, AV_PKT_DATA_METADATA_UPDATE, + os->new_metadata, os->new_metadata_size); + if (ret < 0) + return ret; - memcpy(side_data, os->new_metadata, os->new_metadata_size); - av_freep(&os->new_metadata); + os->new_metadata = NULL; os->new_metadata_size = 0; } return psize; -fail: - av_packet_unref(pkt); - return AVERROR(ENOMEM); } static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, diff -Nru ffmpeg-4.2.2/libavformat/oggdec.h ffmpeg-4.4/libavformat/oggdec.h --- ffmpeg-4.2.2/libavformat/oggdec.h 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavformat/oggdec.h 2021-04-08 21:28:40.000000000 +0000 @@ -84,9 +84,10 @@ int got_start; int got_data; ///< 1 if the stream got some data (non-initial packets), 0 otherwise int nb_header; ///< set to the number of parsed headers + int start_trimming; ///< set the number of packets to drop from the start int end_trimming; ///< set the number of packets to drop from the end uint8_t *new_metadata; - unsigned int new_metadata_size; + buffer_size_t new_metadata_size; void *private; }; @@ -114,7 +115,6 @@ #define OGG_NOGRANULE_VALUE (-1ull) extern const struct ogg_codec ff_celt_codec; -extern const struct ogg_codec ff_daala_codec; extern const struct ogg_codec ff_dirac_codec; extern const struct ogg_codec ff_flac_codec; extern const struct ogg_codec ff_ogm_audio_codec; diff -Nru ffmpeg-4.2.2/libavformat/oggenc.c ffmpeg-4.4/libavformat/oggenc.c --- ffmpeg-4.2.2/libavformat/oggenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/oggenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -99,51 +99,32 @@ .version = LIBAVUTIL_VERSION_INT,\ }; -static void ogg_update_checksum(AVFormatContext *s, AVIOContext *pb, int64_t crc_offset) -{ - int64_t pos = avio_tell(pb); - uint32_t checksum = ffio_get_checksum(pb); - avio_seek(pb, crc_offset, SEEK_SET); - avio_wb32(pb, checksum); - avio_seek(pb, pos, SEEK_SET); -} - -static int ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags) +static void ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags) { OGGStreamContext *oggstream = s->streams[page->stream_index]->priv_data; - AVIOContext *pb; - int64_t crc_offset; - int ret, size; - uint8_t *buf; - - ret = avio_open_dyn_buf(&pb); - if (ret < 0) - return ret; - ffio_init_checksum(pb, ff_crc04C11DB7_update, 0); - ffio_wfourcc(pb, "OggS"); - avio_w8(pb, 0); - avio_w8(pb, page->flags | extra_flags); - avio_wl64(pb, page->granule); - avio_wl32(pb, oggstream->serial_num); - avio_wl32(pb, oggstream->page_counter++); - crc_offset = avio_tell(pb); - avio_wl32(pb, 0); // crc - avio_w8(pb, page->segments_count); - avio_write(pb, page->segments, page->segments_count); - avio_write(pb, page->data, page->size); - - ogg_update_checksum(s, pb, crc_offset); - avio_flush(pb); - - size = avio_close_dyn_buf(pb, &buf); - if (size < 0) - return size; - - avio_write(s->pb, buf, size); - avio_flush(s->pb); - av_free(buf); + uint8_t buf[4 + 1 + 1 + 8 + 4 + 4 + 4 + 1 + 255], *ptr = buf, *crc_pos; + const AVCRC *crc_table = av_crc_get_table(AV_CRC_32_IEEE); + uint32_t crc; + + bytestream_put_le32(&ptr, MKTAG('O', 'g', 'g', 'S')); + bytestream_put_byte(&ptr, 0); + bytestream_put_byte(&ptr, page->flags | extra_flags); + bytestream_put_le64(&ptr, page->granule); + bytestream_put_le32(&ptr, oggstream->serial_num); + bytestream_put_le32(&ptr, oggstream->page_counter++); + crc_pos = ptr; + bytestream_put_le32(&ptr, 0); + bytestream_put_byte(&ptr, page->segments_count); + bytestream_put_buffer(&ptr, page->segments, page->segments_count); + + crc = av_crc(crc_table, 0, buf, ptr - buf); + crc = av_crc(crc_table, crc, page->data, page->size); + bytestream_put_be32(&crc_pos, crc); + + avio_write(s->pb, buf, ptr - buf); + avio_write(s->pb, page->data, page->size); + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); oggstream->page_count--; - return 0; } static int ogg_key_granule(OGGStreamContext *oggstream, int64_t granule) @@ -295,8 +276,9 @@ AVChapter **chapters, unsigned int nb_chapters) { const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT; + AVIOContext pb; int64_t size; - uint8_t *p, *p0; + uint8_t *p; ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL); @@ -306,15 +288,14 @@ p = av_mallocz(size); if (!p) return NULL; - p0 = p; - p += offset; - ff_vorbiscomment_write(&p, m, vendor, chapters, nb_chapters); + ffio_init_context(&pb, p + offset, size - offset, 1, NULL, NULL, NULL, NULL); + ff_vorbiscomment_write(&pb, *m, vendor, chapters, nb_chapters); if (framing_bit) - bytestream_put_byte(&p, 1); + avio_w8(&pb, 1); *header_len = size; - return p0; + return p; } static int ogg_build_flac_headers(AVCodecParameters *par, @@ -547,7 +528,6 @@ &st->metadata); if (err) { av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n"); - av_freep(&st->priv_data); return err; } } else if (st->codecpar->codec_id == AV_CODEC_ID_SPEEX) { @@ -556,7 +536,6 @@ &st->metadata); if (err) { av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n"); - av_freep(&st->priv_data); return err; } } else if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) { @@ -565,7 +544,6 @@ &st->metadata, s->chapters, s->nb_chapters); if (err) { av_log(s, AV_LOG_ERROR, "Error writing Opus headers\n"); - av_freep(&st->priv_data); return err; } } else if (st->codecpar->codec_id == AV_CODEC_ID_VP8) { @@ -573,7 +551,6 @@ s->flags & AVFMT_FLAG_BITEXACT); if (err) { av_log(s, AV_LOG_ERROR, "Error writing VP8 headers\n"); - av_freep(&st->priv_data); return err; } } else { @@ -586,7 +563,7 @@ st->codecpar->codec_id == AV_CODEC_ID_VORBIS ? 30 : 42, (const uint8_t**)oggstream->header, oggstream->header_len) < 0) { av_log(s, AV_LOG_ERROR, "Extradata corrupted\n"); - av_freep(&st->priv_data); + oggstream->header[1] = NULL; return AVERROR_INVALIDDATA; } @@ -740,6 +717,8 @@ static void ogg_free(AVFormatContext *s) { + OGGContext *ogg = s->priv_data; + OGGPageList *p = ogg->page_list; int i; for (i = 0; i < s->nb_streams; i++) { @@ -754,8 +733,14 @@ av_freep(&oggstream->header[0]); } av_freep(&oggstream->header[1]); - av_freep(&st->priv_data); } + + while (p) { + OGGPageList *next = p->next; + av_free(p); + p = next; + } + ogg->page_list = NULL; } #if CONFIG_OGG_MUXER diff -Nru ffmpeg-4.2.2/libavformat/oggparsecelt.c ffmpeg-4.4/libavformat/oggparsecelt.c --- ffmpeg-4.2.2/libavformat/oggparsecelt.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/oggparsecelt.c 2020-07-11 10:39:30.000000000 +0000 @@ -37,6 +37,7 @@ AVStream *st = s->streams[idx]; struct oggcelt_private *priv = os->private; uint8_t *p = os->buf + os->pstart; + int ret; if (os->psize == 60 && !memcmp(p, ff_celt_codec.magic, ff_celt_codec.magicsize)) { @@ -48,9 +49,10 @@ priv = av_malloc(sizeof(struct oggcelt_private)); if (!priv) return AVERROR(ENOMEM); - if (ff_alloc_extradata(st->codecpar, 2 * sizeof(uint32_t)) < 0) { + ret = ff_alloc_extradata(st->codecpar, 2 * sizeof(uint32_t)); + if (ret < 0) { av_free(priv); - return AVERROR(ENOMEM); + return ret; } version = AV_RL32(p + 28); /* unused header size field skipped */ diff -Nru ffmpeg-4.2.2/libavformat/oggparsedaala.c ffmpeg-4.4/libavformat/oggparsedaala.c --- ffmpeg-4.2.2/libavformat/oggparsedaala.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/oggparsedaala.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,261 +0,0 @@ -/* - * Ogg Daala parser - * Copyright (C) 2015 Rostislav Pehlivanov - * Copyright (C) 2015 Vittorio Giovara - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include "libavcodec/bytestream.h" -#include "avformat.h" -#include "internal.h" -#include "oggdec.h" - -struct DaalaPixFmtMap { - enum AVPixelFormat ffmpeg_fmt; - int depth; - int planes; - int xdec[4]; - int ydec[4]; -}; - -/* Currently supported formats only */ -static const struct DaalaPixFmtMap list_fmts[] = { - { AV_PIX_FMT_YUV420P, 8, 3, {0, 1, 1, 0}, {0, 1, 1, 0} }, - { AV_PIX_FMT_YUV444P, 8, 3, {0, 0, 0, 0}, {0, 0, 0, 0} } -}; - -typedef struct DaalaInfoHeader { - int init_d; - int fpr; - int gpshift; - int gpmask; - int version_maj; - int version_min; - int version_sub; - int frame_duration; - int keyframe_granule_shift; - struct DaalaPixFmtMap format; -} DaalaInfoHeader; - -static inline int daala_match_pix_fmt(struct DaalaPixFmtMap *fmt) -{ - int i, j; - for (i = 0; i < FF_ARRAY_ELEMS(list_fmts); i++) { - int match = 0; - if (fmt->depth != list_fmts[i].depth) - continue; - if (fmt->planes != list_fmts[i].planes) - continue; - for (j = 0; j < fmt->planes; j++) { - if (fmt->xdec[j] != list_fmts[i].xdec[j]) - continue; - if (fmt->ydec[j] != list_fmts[i].ydec[j]) - continue; - match++; - } - if (match == fmt->planes) - return list_fmts[i].ffmpeg_fmt; - } - return -1; -} - -static int daala_header(AVFormatContext *s, int idx) -{ - int i, err; - uint8_t *cdp; - GetByteContext gb; - AVRational timebase; - struct ogg *ogg = s->priv_data; - struct ogg_stream *os = ogg->streams + idx; - AVStream *st = s->streams[idx]; - int cds = st->codecpar->extradata_size + os->psize + 2; - DaalaInfoHeader *hdr = os->private; - - if (!(os->buf[os->pstart] & 0x80)) - return 0; - - if (!hdr) { - hdr = av_mallocz(sizeof(*hdr)); - if (!hdr) - return AVERROR(ENOMEM); - os->private = hdr; - } - - switch (os->buf[os->pstart]) { - case 0x80: - bytestream2_init(&gb, os->buf + os->pstart, os->psize); - bytestream2_skip(&gb, ff_daala_codec.magicsize); - - hdr->version_maj = bytestream2_get_byte(&gb); - hdr->version_min = bytestream2_get_byte(&gb); - hdr->version_sub = bytestream2_get_byte(&gb); - - st->codecpar->width = bytestream2_get_ne32(&gb); - st->codecpar->height = bytestream2_get_ne32(&gb); - - st->sample_aspect_ratio.num = bytestream2_get_ne32(&gb); - st->sample_aspect_ratio.den = bytestream2_get_ne32(&gb); - - timebase.num = bytestream2_get_ne32(&gb); - timebase.den = bytestream2_get_ne32(&gb); - if (timebase.num < 0 && timebase.den < 0) { - av_log(s, AV_LOG_WARNING, "Invalid timebase, assuming 30 FPS\n"); - timebase.num = 1; - timebase.den = 30; - } - avpriv_set_pts_info(st, 64, timebase.den, timebase.num); - - hdr->frame_duration = bytestream2_get_ne32(&gb); - hdr->gpshift = bytestream2_get_byte(&gb); - if (hdr->gpshift >= 32) { - av_log(s, AV_LOG_ERROR, "Too large gpshift %d (>= 32).\n", - hdr->gpshift); - hdr->gpshift = 0; - return AVERROR_INVALIDDATA; - } - hdr->gpmask = (1U << hdr->gpshift) - 1; - - hdr->format.depth = 8 + 2*(bytestream2_get_byte(&gb)-1); - - hdr->fpr = bytestream2_get_byte(&gb); - - hdr->format.planes = bytestream2_get_byte(&gb); - if (hdr->format.planes > 4) { - av_log(s, AV_LOG_ERROR, - "Invalid number of planes %d in daala pixel format map.\n", - hdr->format.planes); - return AVERROR_INVALIDDATA; - } - for (i = 0; i < hdr->format.planes; i++) { - hdr->format.xdec[i] = bytestream2_get_byte(&gb); - hdr->format.ydec[i] = bytestream2_get_byte(&gb); - } - - if ((st->codecpar->format = daala_match_pix_fmt(&hdr->format)) < 0) - av_log(s, AV_LOG_ERROR, "Unsupported pixel format - %i %i\n", - hdr->format.depth, hdr->format.planes); - - st->codecpar->codec_id = AV_CODEC_ID_DAALA; - st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - st->need_parsing = AVSTREAM_PARSE_HEADERS; - - hdr->init_d = 1; - break; - case 0x81: - if (!hdr->init_d) - return AVERROR_INVALIDDATA; - ff_vorbis_stream_comment(s, st, - os->buf + os->pstart + ff_daala_codec.magicsize, - os->psize - ff_daala_codec.magicsize); - break; - case 0x82: - if (!hdr->init_d) - return AVERROR_INVALIDDATA; - break; - default: - av_log(s, AV_LOG_ERROR, "Unknown header type %X\n", os->buf[os->pstart]); - return AVERROR_INVALIDDATA; - break; - } - - if ((err = av_reallocp(&st->codecpar->extradata, - cds + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) { - st->codecpar->extradata_size = 0; - return err; - } - - memset(st->codecpar->extradata + cds, 0, AV_INPUT_BUFFER_PADDING_SIZE); - cdp = st->codecpar->extradata + st->codecpar->extradata_size; - *cdp++ = os->psize >> 8; - *cdp++ = os->psize & 0xff; - memcpy(cdp, os->buf + os->pstart, os->psize); - st->codecpar->extradata_size = cds; - - return 1; -} - -static uint64_t daala_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, - int64_t *dts) -{ - uint64_t iframe, pframe; - struct ogg *ogg = ctx->priv_data; - struct ogg_stream *os = ogg->streams + idx; - DaalaInfoHeader *hdr = os->private; - - if (!hdr) - return AV_NOPTS_VALUE; - - iframe = gp >> hdr->gpshift; - pframe = gp & hdr->gpmask; - - if (!pframe) - os->pflags |= AV_PKT_FLAG_KEY; - - if (dts) - *dts = iframe + pframe; - - return iframe + pframe; -} - -static int daala_packet(AVFormatContext *s, int idx) -{ - int seg, duration = 1; - struct ogg *ogg = s->priv_data; - struct ogg_stream *os = ogg->streams + idx; - int64_t pts; - - /* - * first packet handling: here we parse the duration of each packet in the - * first page and compare the total duration to the page granule to find the - * encoder delay and set the first timestamp - */ - - if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) { - for (seg = os->segp; seg < os->nsegs; seg++) - if (os->segments[seg] < 255) - duration++; - - pts = daala_gptopts(s, idx, os->granule, NULL); - if (pts != AV_NOPTS_VALUE) - pts -= duration; - os->lastpts = os->lastdts = pts; - if(s->streams[idx]->start_time == AV_NOPTS_VALUE) { - s->streams[idx]->start_time = os->lastpts; - if (s->streams[idx]->duration != AV_NOPTS_VALUE) - s->streams[idx]->duration -= s->streams[idx]->start_time; - } - } - - /* parse packet duration */ - if (os->psize > 0) - os->pduration = 1; - - return 0; -} - -const struct ogg_codec ff_daala_codec = { - .name = "Daala", - .magic = "\200daala", - .magicsize = 6, - .header = daala_header, - .packet = daala_packet, - .gptopts = daala_gptopts, - .granule_is_start = 1, - .nb_header = 3, -}; diff -Nru ffmpeg-4.2.2/libavformat/oggparseflac.c ffmpeg-4.4/libavformat/oggparseflac.c --- ffmpeg-4.2.2/libavformat/oggparseflac.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/oggparseflac.c 2020-07-11 10:39:30.000000000 +0000 @@ -34,7 +34,7 @@ struct ogg_stream *os = ogg->streams + idx; AVStream *st = s->streams[idx]; GetBitContext gb; - int mdt; + int mdt, ret; if (os->buf[os->pstart] == 0xff) return 0; @@ -50,7 +50,7 @@ skip_bits_long(&gb, 4*8); /* "FLAC" */ if(get_bits(&gb, 8) != 1) /* unsupported major version */ return -1; - skip_bits_long(&gb, 8 + 16); /* minor version + header count */ + skip_bits(&gb, 8 + 16); /* minor version + header count */ skip_bits_long(&gb, 4*8); /* "fLaC" */ /* METADATA_BLOCK_HEADER */ @@ -61,8 +61,8 @@ st->codecpar->codec_id = AV_CODEC_ID_FLAC; st->need_parsing = AVSTREAM_PARSE_HEADERS; - if (ff_alloc_extradata(st->codecpar, FLAC_STREAMINFO_SIZE) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, FLAC_STREAMINFO_SIZE)) < 0) + return ret; memcpy(st->codecpar->extradata, streaminfo_start, st->codecpar->extradata_size); samplerate = AV_RB24(st->codecpar->extradata + 10) >> 4; diff -Nru ffmpeg-4.2.2/libavformat/oggparseogm.c ffmpeg-4.4/libavformat/oggparseogm.c --- ffmpeg-4.2.2/libavformat/oggparseogm.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/oggparseogm.c 2020-07-11 10:39:30.000000000 +0000 @@ -43,6 +43,7 @@ uint64_t time_unit; uint64_t spu; uint32_t size; + int ret; bytestream2_init(&p, os->buf + os->pstart, os->psize); if (!(bytestream2_peek_byte(&p) & 1)) @@ -108,9 +109,8 @@ size -= 52; if (bytestream2_get_bytes_left(&p) < size) return AVERROR_INVALIDDATA; - av_freep(&st->codecpar->extradata); - if (ff_alloc_extradata(st->codecpar, size) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0) + return ret; bytestream2_get_buffer(&p, st->codecpar->extradata, st->codecpar->extradata_size); } } diff -Nru ffmpeg-4.2.2/libavformat/oggparseopus.c ffmpeg-4.4/libavformat/oggparseopus.c --- ffmpeg-4.2.2/libavformat/oggparseopus.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/oggparseopus.c 2020-07-11 10:39:30.000000000 +0000 @@ -42,6 +42,7 @@ AVStream *st = avf->streams[idx]; struct oggopus_private *priv = os->private; uint8_t *packet = os->buf + os->pstart; + int ret; if (!priv) { priv = os->private = av_mallocz(sizeof(*priv)); @@ -58,13 +59,13 @@ priv->pre_skip = AV_RL16(packet + 10); st->codecpar->initial_padding = priv->pre_skip; + os->start_trimming = priv->pre_skip; /*orig_sample_rate = AV_RL32(packet + 12);*/ /*gain = AV_RL16(packet + 16);*/ /*channel_map = AV_RL8 (packet + 18);*/ - av_freep(&st->codecpar->extradata); - if (ff_alloc_extradata(st->codecpar, os->psize)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, os->psize)) < 0) + return ret; memcpy(st->codecpar->extradata, packet, os->psize); diff -Nru ffmpeg-4.2.2/libavformat/oggparsespeex.c ffmpeg-4.4/libavformat/oggparsespeex.c --- ffmpeg-4.2.2/libavformat/oggparsespeex.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/oggparsespeex.c 2020-07-11 10:39:30.000000000 +0000 @@ -46,6 +46,7 @@ struct speex_params *spxp = os->private; AVStream *st = s->streams[idx]; uint8_t *p = os->buf + os->pstart; + int ret; if (!spxp) { spxp = av_mallocz(sizeof(*spxp)); @@ -92,8 +93,8 @@ if (frames_per_packet) spxp->packet_size *= frames_per_packet; - if (ff_alloc_extradata(st->codecpar, os->psize) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, os->psize)) < 0) + return ret; memcpy(st->codecpar->extradata, p, st->codecpar->extradata_size); avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff -Nru ffmpeg-4.2.2/libavformat/oggparsetheora.c ffmpeg-4.4/libavformat/oggparsetheora.c --- ffmpeg-4.2.2/libavformat/oggparsetheora.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/oggparsetheora.c 2020-07-11 10:39:30.000000000 +0000 @@ -65,7 +65,7 @@ /* 0x80"theora" */ skip_bits_long(&gb, 7 * 8); - thp->version = get_bits_long(&gb, 24); + thp->version = get_bits(&gb, 24); if (thp->version < 0x030100) { av_log(s, AV_LOG_ERROR, "Too old or unsupported Theora (%x)\n", thp->version); @@ -79,8 +79,8 @@ skip_bits(&gb, 100); if (thp->version >= 0x030200) { - int width = get_bits_long(&gb, 24); - int height = get_bits_long(&gb, 24); + int width = get_bits(&gb, 24); + int height = get_bits(&gb, 24); if (width <= st->codecpar->width && width > st->codecpar->width - 16 && height <= st->codecpar->height && height > st->codecpar->height - 16) { st->codecpar->width = width; @@ -99,8 +99,8 @@ } avpriv_set_pts_info(st, 64, timebase.num, timebase.den); - st->sample_aspect_ratio.num = get_bits_long(&gb, 24); - st->sample_aspect_ratio.den = get_bits_long(&gb, 24); + st->sample_aspect_ratio.num = get_bits(&gb, 24); + st->sample_aspect_ratio.den = get_bits(&gb, 24); if (thp->version >= 0x030200) skip_bits_long(&gb, 38); @@ -191,9 +191,9 @@ pts = theora_gptopts(s, idx, os->granule, NULL); if (pts != AV_NOPTS_VALUE) - pts -= duration; + pts = av_sat_sub64(pts, duration); os->lastpts = os->lastdts = pts; - if(s->streams[idx]->start_time == AV_NOPTS_VALUE) { + if(s->streams[idx]->start_time == AV_NOPTS_VALUE && os->lastpts != AV_NOPTS_VALUE) { s->streams[idx]->start_time = os->lastpts; if (s->streams[idx]->duration > 0) s->streams[idx]->duration -= s->streams[idx]->start_time; diff -Nru ffmpeg-4.2.2/libavformat/oggparsevorbis.c ffmpeg-4.4/libavformat/oggparsevorbis.c --- ffmpeg-4.2.2/libavformat/oggparsevorbis.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/oggparsevorbis.c 2020-07-11 10:39:30.000000000 +0000 @@ -151,7 +151,7 @@ * 'METADATA_BLOCK_PICTURE'. This is the preferred and * recommended way of embedding cover art within VorbisComments." */ - if (!strcmp(tt, "METADATA_BLOCK_PICTURE") && parse_picture) { + if (!av_strcasecmp(tt, "METADATA_BLOCK_PICTURE") && parse_picture) { int ret, len = AV_BASE64_DECODE_SIZE(vl); char *pict = av_malloc(len); @@ -165,7 +165,7 @@ av_freep(&tt); av_freep(&ct); if (ret > 0) - ret = ff_flac_parse_picture(as, pict, ret); + ret = ff_flac_parse_picture(as, pict, ret, 0); av_freep(&pict); if (ret < 0) { av_log(as, AV_LOG_WARNING, "Failed to parse cover art block.\n"); @@ -177,9 +177,8 @@ av_dict_set(m, tt, ";", AV_DICT_APPEND); } av_dict_set(m, tt, ct, - AV_DICT_DONT_STRDUP_KEY | + AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL | AV_DICT_APPEND); - av_freep(&ct); } } } @@ -288,7 +287,7 @@ os->new_metadata = av_packet_pack_dictionary(st->metadata, &os->new_metadata_size); /* Send an empty dictionary to indicate that metadata has been cleared. */ } else { - os->new_metadata = av_malloc(1); + os->new_metadata = av_mallocz(1); os->new_metadata_size = 0; } @@ -386,7 +385,12 @@ } } } else { - int ret = fixup_vorbis_headers(s, priv, &st->codecpar->extradata); + int ret; + + if (priv->vp) + return AVERROR_INVALIDDATA; + + ret = fixup_vorbis_headers(s, priv, &st->codecpar->extradata); if (ret < 0) { st->codecpar->extradata_size = 0; return ret; diff -Nru ffmpeg-4.2.2/libavformat/oma.c ffmpeg-4.4/libavformat/oma.c --- ffmpeg-4.2.2/libavformat/oma.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/oma.c 2021-04-08 21:28:40.000000000 +0000 @@ -18,10 +18,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include "libavcodec/codec_id.h" #include "internal.h" #include "oma.h" -#include "libavcodec/avcodec.h" -#include "libavutil/channel_layout.h" const uint16_t ff_oma_srate_tab[8] = { 320, 441, 480, 882, 960, 0 }; @@ -35,16 +35,4 @@ { 0 }, }; -/** map ATRAC-X channel id to internal channel layout */ -const uint64_t ff_oma_chid_to_native_layout[7] = { - AV_CH_LAYOUT_MONO, - AV_CH_LAYOUT_STEREO, - AV_CH_LAYOUT_SURROUND, - AV_CH_LAYOUT_4POINT0, - AV_CH_LAYOUT_5POINT1_BACK, - AV_CH_LAYOUT_6POINT1_BACK, - AV_CH_LAYOUT_7POINT1 -}; - -/** map ATRAC-X channel id to total number of channels */ -const int ff_oma_chid_to_num_channels[7] = {1, 2, 3, 4, 6, 7, 8}; +const AVCodecTag *const ff_oma_codec_tags_list[] = { ff_oma_codec_tags, NULL }; diff -Nru ffmpeg-4.2.2/libavformat/omadec.c ffmpeg-4.4/libavformat/omadec.c --- ffmpeg-4.2.2/libavformat/omadec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/omadec.c 2021-04-08 21:28:40.000000000 +0000 @@ -59,6 +59,20 @@ 0x1573cd93da7df623, 0x47f98d79620dd535 }; +/** map ATRAC-X channel id to internal channel layout */ +static const uint64_t oma_chid_to_native_layout[7] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT1_BACK, + AV_CH_LAYOUT_6POINT1_BACK, + AV_CH_LAYOUT_7POINT1 +}; + +/** map ATRAC-X channel id to total number of channels */ +static const int oma_chid_to_num_channels[7] = { 1, 2, 3, 4, 6, 7, 8 }; + typedef struct OMAContext { uint64_t content_start; int encrypted; @@ -79,6 +93,13 @@ int (*read_packet)(AVFormatContext *s, AVPacket *pkt); } OMAContext; +static int oma_read_close(AVFormatContext *s) +{ + OMAContext *oc = s->priv_data; + av_freep(&oc->av_des); + return 0; +} + static void hex_log(AVFormatContext *s, int level, const char *name, const uint8_t *value, int len) { @@ -217,14 +238,13 @@ av_log(s, AV_LOG_INFO, "File is encrypted\n"); /* find GEOB metadata */ - while (em) { - if (!strcmp(em->tag, "GEOB") && - (geob = em->data) && - (!strcmp(geob->description, "OMG_LSI") || - !strcmp(geob->description, "OMG_BKLSI"))) { + for (; em; em = em->next) { + if (strcmp(em->tag, "GEOB")) + continue; + geob = &em->data.geob; + if (!strcmp(geob->description, "OMG_LSI") || + !strcmp(geob->description, "OMG_BKLSI")) break; - } - em = em->next; } if (!em) { av_log(s, AV_LOG_ERROR, "No encryption header found\n"); @@ -397,17 +417,20 @@ OMAContext *oc = s->priv_data; ff_id3v2_read(s, ID3v2_EA3_MAGIC, &extra_meta, 0); - if ((ret = ff_id3v2_parse_chapters(s, &extra_meta)) < 0) { + if ((ret = ff_id3v2_parse_chapters(s, extra_meta)) < 0) { ff_id3v2_free_extra_meta(&extra_meta); return ret; } ret = avio_read(s->pb, buf, EA3_HEADER_SIZE); - if (ret < EA3_HEADER_SIZE) + if (ret < EA3_HEADER_SIZE) { + ff_id3v2_free_extra_meta(&extra_meta); return -1; + } if (memcmp(buf, ((const uint8_t[]){'E', 'A', '3'}), 3) || buf[4] != 0 || buf[5] != EA3_HEADER_SIZE) { + ff_id3v2_free_extra_meta(&extra_meta); av_log(s, AV_LOG_ERROR, "Couldn't find the EA3 header !\n"); return AVERROR_INVALIDDATA; } @@ -426,8 +449,10 @@ codec_params = AV_RB24(&buf[33]); st = avformat_new_stream(s, NULL); - if (!st) - return AVERROR(ENOMEM); + if (!st) { + ret = AVERROR(ENOMEM); + goto fail; + } st->start_time = 0; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; @@ -442,7 +467,8 @@ samplerate = ff_oma_srate_tab[(codec_params >> 13) & 7] * 100; if (!samplerate) { av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } if (samplerate != 44100) avpriv_request_sample(s, "Sample rate %d", samplerate); @@ -459,8 +485,8 @@ /* fake the ATRAC3 extradata * (wav format, makes stream copy to wav work) */ - if (ff_alloc_extradata(st->codecpar, 14)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 14)) < 0) + goto fail; edata = st->codecpar->extradata; AV_WL16(&edata[0], 1); // always 1 @@ -477,15 +503,17 @@ if (!channel_id) { av_log(s, AV_LOG_ERROR, "Invalid ATRAC-X channel id: %"PRIu32"\n", channel_id); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } - st->codecpar->channel_layout = ff_oma_chid_to_native_layout[channel_id - 1]; - st->codecpar->channels = ff_oma_chid_to_num_channels[channel_id - 1]; + st->codecpar->channel_layout = oma_chid_to_native_layout[channel_id - 1]; + st->codecpar->channels = oma_chid_to_num_channels[channel_id - 1]; framesize = ((codec_params & 0x3FF) * 8) + 8; samplerate = ff_oma_srate_tab[(codec_params >> 13) & 7] * 100; if (!samplerate) { av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } st->codecpar->sample_rate = samplerate; st->codecpar->bit_rate = samplerate * framesize / (2048 / 8); @@ -525,12 +553,16 @@ break; default: av_log(s, AV_LOG_ERROR, "Unsupported codec %d!\n", buf[32]); - return AVERROR(ENOSYS); + ret = AVERROR(ENOSYS); + goto fail; } st->codecpar->block_align = framesize; return 0; +fail: + oma_read_close(s); + return ret; } static int oma_read_packet(AVFormatContext *s, AVPacket *pkt) @@ -592,13 +624,6 @@ return err; } -static int oma_read_close(AVFormatContext *s) -{ - OMAContext *oc = s->priv_data; - av_free(oc->av_des); - return 0; -} - AVInputFormat ff_oma_demuxer = { .name = "oma", .long_name = NULL_IF_CONFIG_SMALL("Sony OpenMG audio"), @@ -610,5 +635,5 @@ .read_close = oma_read_close, .flags = AVFMT_GENERIC_INDEX, .extensions = "oma,omg,aa3", - .codec_tag = (const AVCodecTag* const []){ff_oma_codec_tags, 0}, + .codec_tag = ff_oma_codec_tags_list, }; diff -Nru ffmpeg-4.2.2/libavformat/omaenc.c ffmpeg-4.4/libavformat/omaenc.c --- ffmpeg-4.2.2/libavformat/omaenc.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/omaenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -102,6 +102,6 @@ .audio_codec = AV_CODEC_ID_ATRAC3, .write_header = oma_write_header, .write_packet = ff_raw_write_packet, - .codec_tag = (const AVCodecTag* const []){ff_oma_codec_tags, 0}, + .codec_tag = ff_oma_codec_tags_list, .flags = AVFMT_NOTIMESTAMPS, }; diff -Nru ffmpeg-4.2.2/libavformat/oma.h ffmpeg-4.4/libavformat/oma.h --- ffmpeg-4.2.2/libavformat/oma.h 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/oma.h 2021-04-08 21:28:40.000000000 +0000 @@ -42,8 +42,6 @@ extern const uint16_t ff_oma_srate_tab[8]; extern const AVCodecTag ff_oma_codec_tags[]; - -extern const uint64_t ff_oma_chid_to_native_layout[7]; -extern const int ff_oma_chid_to_num_channels[7]; +extern const AVCodecTag *const ff_oma_codec_tags_list[]; #endif /* AVFORMAT_OMA_H */ diff -Nru ffmpeg-4.2.2/libavformat/options.c ffmpeg-4.4/libavformat/options.c --- ffmpeg-4.2.2/libavformat/options.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/options.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,6 +21,7 @@ #include "avio_internal.h" #include "internal.h" +#include "libavutil/avassert.h" #include "libavutil/internal.h" #include "libavutil/opt.h" @@ -53,33 +54,96 @@ return NULL; } +#if FF_API_CHILD_CLASS_NEXT static const AVClass *format_child_class_next(const AVClass *prev) { - AVInputFormat *ifmt = NULL; - AVOutputFormat *ofmt = NULL; + const AVInputFormat *ifmt = NULL; + const AVOutputFormat *ofmt = NULL; + void *ifmt_iter = NULL, *ofmt_iter = NULL; if (!prev) return &ff_avio_class; - while ((ifmt = av_iformat_next(ifmt))) + while ((ifmt = av_demuxer_iterate(&ifmt_iter))) if (ifmt->priv_class == prev) break; - if (!ifmt) - while ((ofmt = av_oformat_next(ofmt))) + if (!ifmt) { + ifmt_iter = NULL; + while ((ofmt = av_muxer_iterate(&ofmt_iter))) if (ofmt->priv_class == prev) break; - if (!ofmt) - while (ifmt = av_iformat_next(ifmt)) + } + if (!ofmt) { + ofmt_iter = NULL; + while ((ifmt = av_demuxer_iterate(&ifmt_iter))) if (ifmt->priv_class) return ifmt->priv_class; + } - while (ofmt = av_oformat_next(ofmt)) + while ((ofmt = av_muxer_iterate(&ofmt_iter))) if (ofmt->priv_class) return ofmt->priv_class; return NULL; } +#endif + +enum { + CHILD_CLASS_ITER_AVIO = 0, + CHILD_CLASS_ITER_MUX, + CHILD_CLASS_ITER_DEMUX, + CHILD_CLASS_ITER_DONE, + +}; + +#define ITER_STATE_SHIFT 16 + +static const AVClass *format_child_class_iterate(void **iter) +{ + // we use the low 16 bits of iter as the value to be passed to + // av_(de)muxer_iterate() + void *val = (void*)(((uintptr_t)*iter) & ((1 << ITER_STATE_SHIFT) - 1)); + unsigned int state = ((uintptr_t)*iter) >> ITER_STATE_SHIFT; + const AVClass *ret = NULL; + + if (state == CHILD_CLASS_ITER_AVIO) { + ret = &ff_avio_class; + state++; + goto finish; + } + + if (state == CHILD_CLASS_ITER_MUX) { + const AVOutputFormat *ofmt; + + while ((ofmt = av_muxer_iterate(&val))) { + ret = ofmt->priv_class; + if (ret) + goto finish; + } + + val = NULL; + state++; + } + + if (state == CHILD_CLASS_ITER_DEMUX) { + const AVInputFormat *ifmt; + + while ((ifmt = av_demuxer_iterate(&val))) { + ret = ifmt->priv_class; + if (ret) + goto finish; + } + val = NULL; + state++; + } + +finish: + // make sure none av_(de)muxer_iterate does not set the high bits of val + av_assert0(!((uintptr_t)val >> ITER_STATE_SHIFT)); + *iter = (void*)((uintptr_t)val | (state << ITER_STATE_SHIFT)); + return ret; +} static AVClassCategory get_category(void *ptr) { @@ -94,7 +158,10 @@ .option = avformat_options, .version = LIBAVUTIL_VERSION_INT, .child_next = format_child_next, +#if FF_API_CHILD_CLASS_NEXT .child_class_next = format_child_class_next, +#endif + .child_class_iterate = format_child_class_iterate, .category = AV_CLASS_CATEGORY_MUXER, .get_category = get_category, }; @@ -144,15 +211,26 @@ AVFormatContext *avformat_alloc_context(void) { AVFormatContext *ic; + AVFormatInternal *internal; ic = av_malloc(sizeof(AVFormatContext)); if (!ic) return ic; - avformat_get_context_defaults(ic); - ic->internal = av_mallocz(sizeof(*ic->internal)); - if (!ic->internal) { - avformat_free_context(ic); + internal = av_mallocz(sizeof(*internal)); + if (!internal) { + av_free(ic); return NULL; } + internal->pkt = av_packet_alloc(); + internal->parse_pkt = av_packet_alloc(); + if (!internal->pkt || !internal->parse_pkt) { + av_packet_free(&internal->pkt); + av_packet_free(&internal->parse_pkt); + av_free(internal); + av_free(ic); + return NULL; + } + avformat_get_context_defaults(ic); + ic->internal = internal; ic->internal->offset = AV_NOPTS_VALUE; ic->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; ic->internal->shortest_end = AV_NOPTS_VALUE; diff -Nru ffmpeg-4.2.2/libavformat/options_table.h ffmpeg-4.4/libavformat/options_table.h --- ffmpeg-4.2.2/libavformat/options_table.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/options_table.h 2020-07-11 10:39:30.000000000 +0000 @@ -82,8 +82,8 @@ {"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, D, "err_detect"}, {"ignore_err", "ignore errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_IGNORE_ERR }, INT_MIN, INT_MAX, D, "err_detect"}, {"careful", "consider things that violate the spec, are fast to check and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, D, "err_detect"}, -{"compliant", "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, D, "err_detect"}, -{"aggressive", "consider things that a sane encoder shouldn't do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, D, "err_detect"}, +{"compliant", "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT | AV_EF_CAREFUL }, INT_MIN, INT_MAX, D, "err_detect"}, +{"aggressive", "consider things that a sane encoder shouldn't do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE | AV_EF_COMPLIANT | AV_EF_CAREFUL}, INT_MIN, INT_MAX, D, "err_detect"}, {"use_wallclock_as_timestamps", "use wallclock as timestamps", OFFSET(use_wallclock_as_timestamps), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, D}, {"skip_initial_bytes", "set number of bytes to skip before reading header and frames", OFFSET(skip_initial_bytes), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX-1, D}, {"correct_ts_overflow", "correct single timestamp overflows", OFFSET(correct_ts_overflow), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, D}, @@ -104,13 +104,14 @@ {"disabled", "do not change timestamps", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, {"make_non_negative", "shift timestamps so they are non negative", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, {"make_zero", "shift timestamps so they start at 0", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_MAKE_ZERO }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, -{"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = ", "}, CHAR_MIN, CHAR_MAX, D|E}, -{"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D }, -{"format_whitelist", "List of demuxers that are allowed to be used", OFFSET(format_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D }, -{"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D }, -{"protocol_blacklist", "List of protocols that are not allowed to be used", OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D }, +{"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = ", "}, 0, 0, D|E}, +{"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, +{"format_whitelist", "List of demuxers that are allowed to be used", OFFSET(format_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, +{"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, +{"protocol_blacklist", "List of protocols that are not allowed to be used", OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, {"max_streams", "maximum number of streams", OFFSET(max_streams), AV_OPT_TYPE_INT, { .i64 = 1000 }, 0, INT_MAX, D }, {"skip_estimate_duration_from_pts", "skip duration calculation in estimate_timings_from_pts", OFFSET(skip_estimate_duration_from_pts), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, D}, +{"max_probe_packets", "Maximum number of packets to probe a codec", OFFSET(max_probe_packets), AV_OPT_TYPE_INT, { .i64 = 2500 }, 0, INT_MAX, D }, {NULL}, }; diff -Nru ffmpeg-4.2.2/libavformat/paf.c ffmpeg-4.4/libavformat/paf.c --- ffmpeg-4.2.2/libavformat/paf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/paf.c 2021-04-08 21:28:40.000000000 +0000 @@ -75,14 +75,18 @@ return 0; } -static void read_table(AVFormatContext *s, uint32_t *table, uint32_t count) +static int read_table(AVFormatContext *s, uint32_t *table, uint32_t count) { int i; - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { + if (avio_feof(s->pb)) + return AVERROR_INVALIDDATA; table[i] = avio_rl32(s->pb); + } avio_skip(s->pb, 4 * (FFALIGN(count, 512) - count)); + return 0; } static int read_header(AVFormatContext *s) @@ -132,6 +136,10 @@ p->start_offset = avio_rl32(pb); p->max_video_blks = avio_rl32(pb); p->max_audio_blks = avio_rl32(pb); + + if (avio_feof(pb)) + return AVERROR_INVALIDDATA; + if (p->buffer_size < 175 || p->max_audio_blks < 2 || p->max_video_blks < 1 || @@ -145,11 +153,11 @@ p->frame_blks > INT_MAX / sizeof(uint32_t)) return AVERROR_INVALIDDATA; - p->blocks_count_table = av_mallocz(p->nb_frames * + p->blocks_count_table = av_malloc_array(p->nb_frames, sizeof(*p->blocks_count_table)); - p->frames_offset_table = av_mallocz(p->nb_frames * + p->frames_offset_table = av_malloc_array(p->nb_frames, sizeof(*p->frames_offset_table)); - p->blocks_offset_table = av_mallocz(p->frame_blks * + p->blocks_offset_table = av_malloc_array(p->frame_blks, sizeof(*p->blocks_offset_table)); p->video_size = p->max_video_blks * p->buffer_size; @@ -171,9 +179,15 @@ avio_seek(pb, p->buffer_size, SEEK_SET); - read_table(s, p->blocks_count_table, p->nb_frames); - read_table(s, p->frames_offset_table, p->nb_frames); - read_table(s, p->blocks_offset_table, p->frame_blks); + ret = read_table(s, p->blocks_count_table, p->nb_frames); + if (ret < 0) + goto fail; + ret = read_table(s, p->frames_offset_table, p->nb_frames); + if (ret < 0) + goto fail; + ret = read_table(s, p->blocks_offset_table, p->frame_blks); + if (ret < 0) + goto fail; p->got_audio = 0; p->current_frame = 0; @@ -194,7 +208,7 @@ PAFDemuxContext *p = s->priv_data; AVIOContext *pb = s->pb; uint32_t count, offset; - int size, i; + int size, i, ret; if (p->current_frame >= p->nb_frames) return AVERROR_EOF; @@ -203,8 +217,8 @@ return AVERROR_EOF; if (p->got_audio) { - if (av_new_packet(pkt, p->audio_size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, p->audio_size)) < 0) + return ret; memcpy(pkt->data, p->temp_audio_frame, p->audio_size); pkt->duration = PAF_SOUND_SAMPLES * (p->audio_size / PAF_SOUND_FRAME_SIZE); @@ -244,8 +258,8 @@ size = p->video_size - p->frames_offset_table[p->current_frame]; - if (av_new_packet(pkt, size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, size)) < 0) + return ret; pkt->stream_index = 0; pkt->duration = 1; diff -Nru ffmpeg-4.2.2/libavformat/pcm.c ffmpeg-4.4/libavformat/pcm.c --- ffmpeg-4.2.2/libavformat/pcm.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/pcm.c 2021-02-20 20:27:47.000000000 +0000 @@ -39,7 +39,11 @@ * Clamp to RAW_SAMPLES if larger. */ size = FFMAX(par->sample_rate/25, 1); - size = FFMIN(size, RAW_SAMPLES) * par->block_align; + if (par->block_align <= INT_MAX / RAW_SAMPLES) { + size = FFMIN(size, RAW_SAMPLES) * par->block_align; + } else { + size = par->block_align; + } ret = av_get_packet(s->pb, pkt, size); diff -Nru ffmpeg-4.2.2/libavformat/pcmdec.c ffmpeg-4.4/libavformat/pcmdec.c --- ffmpeg-4.2.2/libavformat/pcmdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/pcmdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avstring.h" #include "avformat.h" #include "internal.h" #include "pcm.h" @@ -35,36 +36,33 @@ static int pcm_read_header(AVFormatContext *s) { PCMAudioDemuxerContext *s1 = s->priv_data; + AVCodecParameters *par; AVStream *st; uint8_t *mime_type = NULL; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); + par = st->codecpar; - - st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->codec_id = s->iformat->raw_codec_id; - st->codecpar->sample_rate = s1->sample_rate; - st->codecpar->channels = s1->channels; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = s->iformat->raw_codec_id; + par->sample_rate = s1->sample_rate; + par->channels = s1->channels; av_opt_get(s->pb, "mime_type", AV_OPT_SEARCH_CHILDREN, &mime_type); if (mime_type && s->iformat->mime_type) { int rate = 0, channels = 0, little_endian = 0; - size_t len = strlen(s->iformat->mime_type); - if (!av_strncasecmp(s->iformat->mime_type, mime_type, len)) { /* audio/L16 */ - uint8_t *options = mime_type + len; - len = strlen(mime_type); - while (options < mime_type + len) { - options = strstr(options, ";"); - if (!options++) - break; + const char *options; + if (av_stristart(mime_type, s->iformat->mime_type, &options)) { /* audio/L16 */ + while (options = strchr(options, ';')) { + options++; if (!rate) sscanf(options, " rate=%d", &rate); if (!channels) sscanf(options, " channels=%d", &channels); if (!little_endian) { - char val[14]; /* sizeof("little-endian") == 14 */ + char val[sizeof("little-endian")]; if (sscanf(options, " endianness=%13s", val) == 1) { little_endian = strcmp(val, "little-endian") == 0; } @@ -77,24 +75,22 @@ av_freep(&mime_type); return AVERROR_INVALIDDATA; } - st->codecpar->sample_rate = rate; + par->sample_rate = rate; if (channels > 0) - st->codecpar->channels = channels; + par->channels = channels; if (little_endian) - st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; + par->codec_id = AV_CODEC_ID_PCM_S16LE; } } av_freep(&mime_type); - st->codecpar->bits_per_coded_sample = - av_get_bits_per_sample(st->codecpar->codec_id); + par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id); - av_assert0(st->codecpar->bits_per_coded_sample > 0); + av_assert0(par->bits_per_coded_sample > 0); - st->codecpar->block_align = - st->codecpar->bits_per_coded_sample * st->codecpar->channels / 8; + par->block_align = par->bits_per_coded_sample * par->channels / 8; - avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); + avpriv_set_pts_info(st, 64, 1, par->sample_rate); return 0; } @@ -104,7 +100,8 @@ { NULL }, }; -#define PCMDEF(name_, long_name_, ext, codec, ...) \ +#define PCMDEF_0(name_, long_name_, ext, codec, ...) +#define PCMDEF_1(name_, long_name_, ext, codec, ...) \ static const AVClass name_ ## _demuxer_class = { \ .class_name = #name_ " demuxer", \ .item_name = av_default_item_name, \ @@ -124,70 +121,40 @@ .priv_class = &name_ ## _demuxer_class, \ __VA_ARGS__ \ }; +#define PCMDEF_2(name, long_name, ext, codec, enabled, ...) \ + PCMDEF_ ## enabled(name, long_name, ext, codec, __VA_ARGS__) +#define PCMDEF_3(name, long_name, ext, codec, config, ...) \ + PCMDEF_2(name, long_name, ext, codec, config, __VA_ARGS__) +#define PCMDEF_EXT(name, long_name, ext, uppercase, ...) \ + PCMDEF_3(name, long_name, ext, AV_CODEC_ID_PCM_ ## uppercase, \ + CONFIG_PCM_ ## uppercase ## _DEMUXER, __VA_ARGS__) +#define PCMDEF(name, long_name, ext, uppercase) \ + PCMDEF_EXT(name, long_name, ext, uppercase, ) + +PCMDEF(f64be, "PCM 64-bit floating-point big-endian", NULL, F64BE) +PCMDEF(f64le, "PCM 64-bit floating-point little-endian", NULL, F64LE) +PCMDEF(f32be, "PCM 32-bit floating-point big-endian", NULL, F32BE) +PCMDEF(f32le, "PCM 32-bit floating-point little-endian", NULL, F32LE) +PCMDEF(s32be, "PCM signed 32-bit big-endian", NULL, S32BE) +PCMDEF(s32le, "PCM signed 32-bit little-endian", NULL, S32LE) +PCMDEF(s24be, "PCM signed 24-bit big-endian", NULL, S24BE) +PCMDEF(s24le, "PCM signed 24-bit little-endian", NULL, S24LE) +PCMDEF_EXT(s16be, "PCM signed 16-bit big-endian", + AV_NE("sw", NULL), S16BE, .mime_type = "audio/L16") +PCMDEF(s16le, "PCM signed 16-bit little-endian", AV_NE(NULL, "sw"), S16LE) +PCMDEF(s8, "PCM signed 8-bit", "sb", S8) +PCMDEF(u32be, "PCM unsigned 32-bit big-endian", NULL, U32BE) +PCMDEF(u32le, "PCM unsigned 32-bit little-endian", NULL, U32LE) +PCMDEF(u24be, "PCM unsigned 24-bit big-endian", NULL, U24BE) +PCMDEF(u24le, "PCM unsigned 24-bit little-endian", NULL, U24LE) +PCMDEF(u16be, "PCM unsigned 16-bit big-endian", AV_NE("uw", NULL), U16BE) +PCMDEF(u16le, "PCM unsigned 16-bit little-endian", AV_NE(NULL, "uw"), U16LE) +PCMDEF(u8, "PCM unsigned 8-bit", "ub", U8) +PCMDEF(alaw, "PCM A-law", "al", ALAW) +PCMDEF(mulaw, "PCM mu-law", "ul", MULAW) +PCMDEF(vidc, "PCM Archimedes VIDC", NULL, VIDC) -PCMDEF(f64be, "PCM 64-bit floating-point big-endian", - NULL, AV_CODEC_ID_PCM_F64BE) - -PCMDEF(f64le, "PCM 64-bit floating-point little-endian", - NULL, AV_CODEC_ID_PCM_F64LE) - -PCMDEF(f32be, "PCM 32-bit floating-point big-endian", - NULL, AV_CODEC_ID_PCM_F32BE) - -PCMDEF(f32le, "PCM 32-bit floating-point little-endian", - NULL, AV_CODEC_ID_PCM_F32LE) - -PCMDEF(s32be, "PCM signed 32-bit big-endian", - NULL, AV_CODEC_ID_PCM_S32BE) - -PCMDEF(s32le, "PCM signed 32-bit little-endian", - NULL, AV_CODEC_ID_PCM_S32LE) - -PCMDEF(s24be, "PCM signed 24-bit big-endian", - NULL, AV_CODEC_ID_PCM_S24BE) - -PCMDEF(s24le, "PCM signed 24-bit little-endian", - NULL, AV_CODEC_ID_PCM_S24LE) - -PCMDEF(s16be, "PCM signed 16-bit big-endian", - AV_NE("sw", NULL), AV_CODEC_ID_PCM_S16BE, .mime_type = "audio/L16") - -PCMDEF(s16le, "PCM signed 16-bit little-endian", - AV_NE(NULL, "sw"), AV_CODEC_ID_PCM_S16LE) - -PCMDEF(s8, "PCM signed 8-bit", - "sb", AV_CODEC_ID_PCM_S8) - -PCMDEF(u32be, "PCM unsigned 32-bit big-endian", - NULL, AV_CODEC_ID_PCM_U32BE) - -PCMDEF(u32le, "PCM unsigned 32-bit little-endian", - NULL, AV_CODEC_ID_PCM_U32LE) - -PCMDEF(u24be, "PCM unsigned 24-bit big-endian", - NULL, AV_CODEC_ID_PCM_U24BE) - -PCMDEF(u24le, "PCM unsigned 24-bit little-endian", - NULL, AV_CODEC_ID_PCM_U24LE) - -PCMDEF(u16be, "PCM unsigned 16-bit big-endian", - AV_NE("uw", NULL), AV_CODEC_ID_PCM_U16BE) - -PCMDEF(u16le, "PCM unsigned 16-bit little-endian", - AV_NE(NULL, "uw"), AV_CODEC_ID_PCM_U16LE) - -PCMDEF(u8, "PCM unsigned 8-bit", - "ub", AV_CODEC_ID_PCM_U8) - -PCMDEF(alaw, "PCM A-law", - "al", AV_CODEC_ID_PCM_ALAW) - -PCMDEF(mulaw, "PCM mu-law", - "ul", AV_CODEC_ID_PCM_MULAW) - -PCMDEF(vidc, "PCM Archimedes VIDC", - NULL, AV_CODEC_ID_PCM_VIDC) - +#if CONFIG_SLN_DEMUXER static const AVOption sln_options[] = { { "sample_rate", "", offsetof(PCMAudioDemuxerContext, sample_rate), AV_OPT_TYPE_INT, {.i64 = 8000}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, { "channels", "", offsetof(PCMAudioDemuxerContext, channels), AV_OPT_TYPE_INT, {.i64 = 1}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, @@ -213,3 +180,4 @@ .raw_codec_id = AV_CODEC_ID_PCM_S16LE, .priv_class = &sln_demuxer_class, }; +#endif diff -Nru ffmpeg-4.2.2/libavformat/pcmenc.c ffmpeg-4.4/libavformat/pcmenc.c --- ffmpeg-4.2.2/libavformat/pcmenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/pcmenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -22,7 +22,8 @@ #include "avformat.h" #include "rawenc.h" -#define PCMDEF(name_, long_name_, ext, codec) \ +#define PCMDEF_0(name_, long_name_, ext, codec) +#define PCMDEF_1(name_, long_name_, ext, codec) \ AVOutputFormat ff_pcm_ ## name_ ## _muxer = { \ .name = #name_, \ .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ @@ -32,66 +33,32 @@ .write_packet = ff_raw_write_packet, \ .flags = AVFMT_NOTIMESTAMPS, \ }; - -PCMDEF(f64be, "PCM 64-bit floating-point big-endian", - NULL, AV_CODEC_ID_PCM_F64BE) - -PCMDEF(f64le, "PCM 64-bit floating-point little-endian", - NULL, AV_CODEC_ID_PCM_F64LE) - -PCMDEF(f32be, "PCM 32-bit floating-point big-endian", - NULL, AV_CODEC_ID_PCM_F32BE) - -PCMDEF(f32le, "PCM 32-bit floating-point little-endian", - NULL, AV_CODEC_ID_PCM_F32LE) - -PCMDEF(s32be, "PCM signed 32-bit big-endian", - NULL, AV_CODEC_ID_PCM_S32BE) - -PCMDEF(s32le, "PCM signed 32-bit little-endian", - NULL, AV_CODEC_ID_PCM_S32LE) - -PCMDEF(s24be, "PCM signed 24-bit big-endian", - NULL, AV_CODEC_ID_PCM_S24BE) - -PCMDEF(s24le, "PCM signed 24-bit little-endian", - NULL, AV_CODEC_ID_PCM_S24LE) - -PCMDEF(s16be, "PCM signed 16-bit big-endian", - AV_NE("sw", NULL), AV_CODEC_ID_PCM_S16BE) - -PCMDEF(s16le, "PCM signed 16-bit little-endian", - AV_NE(NULL, "sw"), AV_CODEC_ID_PCM_S16LE) - -PCMDEF(s8, "PCM signed 8-bit", - "sb", AV_CODEC_ID_PCM_S8) - -PCMDEF(u32be, "PCM unsigned 32-bit big-endian", - NULL, AV_CODEC_ID_PCM_U32BE) - -PCMDEF(u32le, "PCM unsigned 32-bit little-endian", - NULL, AV_CODEC_ID_PCM_U32LE) - -PCMDEF(u24be, "PCM unsigned 24-bit big-endian", - NULL, AV_CODEC_ID_PCM_U24BE) - -PCMDEF(u24le, "PCM unsigned 24-bit little-endian", - NULL, AV_CODEC_ID_PCM_U24LE) - -PCMDEF(u16be, "PCM unsigned 16-bit big-endian", - AV_NE("uw", NULL), AV_CODEC_ID_PCM_U16BE) - -PCMDEF(u16le, "PCM unsigned 16-bit little-endian", - AV_NE(NULL, "uw"), AV_CODEC_ID_PCM_U16LE) - -PCMDEF(u8, "PCM unsigned 8-bit", - "ub", AV_CODEC_ID_PCM_U8) - -PCMDEF(alaw, "PCM A-law", - "al", AV_CODEC_ID_PCM_ALAW) - -PCMDEF(mulaw, "PCM mu-law", - "ul", AV_CODEC_ID_PCM_MULAW) - -PCMDEF(vidc, "PCM Archimedes VIDC", - NULL, AV_CODEC_ID_PCM_VIDC) +#define PCMDEF_2(name, long_name, ext, codec, enabled) \ + PCMDEF_ ## enabled(name, long_name, ext, codec) +#define PCMDEF_3(name, long_name, ext, codec, config) \ + PCMDEF_2(name, long_name, ext, codec, config) +#define PCMDEF(name, long_name, ext, uppercase) \ + PCMDEF_3(name, long_name, ext, AV_CODEC_ID_PCM_ ## uppercase, \ + CONFIG_PCM_ ## uppercase ## _MUXER) + +PCMDEF(f64be, "PCM 64-bit floating-point big-endian", NULL, F64BE) +PCMDEF(f64le, "PCM 64-bit floating-point little-endian", NULL, F64LE) +PCMDEF(f32be, "PCM 32-bit floating-point big-endian", NULL, F32BE) +PCMDEF(f32le, "PCM 32-bit floating-point little-endian", NULL, F32LE) +PCMDEF(s32be, "PCM signed 32-bit big-endian", NULL, S32BE) +PCMDEF(s32le, "PCM signed 32-bit little-endian", NULL, S32LE) +PCMDEF(s24be, "PCM signed 24-bit big-endian", NULL, S24BE) +PCMDEF(s24le, "PCM signed 24-bit little-endian", NULL, S24LE) +PCMDEF(s16be, "PCM signed 16-bit big-endian", AV_NE("sw", NULL), S16BE) +PCMDEF(s16le, "PCM signed 16-bit little-endian", AV_NE(NULL, "sw"), S16LE) +PCMDEF(s8, "PCM signed 8-bit", "sb", S8) +PCMDEF(u32be, "PCM unsigned 32-bit big-endian", NULL, U32BE) +PCMDEF(u32le, "PCM unsigned 32-bit little-endian", NULL, U32LE) +PCMDEF(u24be, "PCM unsigned 24-bit big-endian", NULL, U24BE) +PCMDEF(u24le, "PCM unsigned 24-bit little-endian", NULL, U24LE) +PCMDEF(u16be, "PCM unsigned 16-bit big-endian", AV_NE("uw", NULL), U16BE) +PCMDEF(u16le, "PCM unsigned 16-bit little-endian", AV_NE(NULL, "uw"), U16LE) +PCMDEF(u8, "PCM unsigned 8-bit", "ub", U8) +PCMDEF(alaw, "PCM A-law", "al", ALAW) +PCMDEF(mulaw, "PCM mu-law", "ul", MULAW) +PCMDEF(vidc, "PCM Archimedes VIDC", NULL, VIDC) diff -Nru ffmpeg-4.2.2/libavformat/pjsdec.c ffmpeg-4.4/libavformat/pjsdec.c --- ffmpeg-4.2.2/libavformat/pjsdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/pjsdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -67,7 +67,6 @@ { PJSContext *pjs = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); - int res = 0; if (!st) return AVERROR(ENOMEM); @@ -94,8 +93,10 @@ p[strcspn(p, "\"")] = 0; sub = ff_subtitles_queue_insert(&pjs->q, p, strlen(p), 0); - if (!sub) + if (!sub) { + ff_subtitles_queue_clean(&pjs->q); return AVERROR(ENOMEM); + } sub->pos = pos; sub->pts = pts_start; sub->duration = duration; @@ -103,7 +104,7 @@ } ff_subtitles_queue_finalize(s, &pjs->q); - return res; + return 0; } static int pjs_read_packet(AVFormatContext *s, AVPacket *pkt) diff -Nru ffmpeg-4.2.2/libavformat/pp_bnk.c ffmpeg-4.4/libavformat/pp_bnk.c --- ffmpeg-4.2.2/libavformat/pp_bnk.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/pp_bnk.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,344 @@ +/* + * Pro Pinball Series Soundbank (44c, 22c, 11c, 5c) demuxer. + * + * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.com) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "avformat.h" +#include "internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/avassert.h" +#include "libavutil/internal.h" + +#define PP_BNK_MAX_READ_SIZE 4096 +#define PP_BNK_FILE_HEADER_SIZE 20 +#define PP_BNK_TRACK_SIZE 20 + +typedef struct PPBnkHeader { + uint32_t bank_id; /*< Bank ID, useless for our purposes. */ + uint32_t sample_rate; /*< Sample rate of the contained tracks. */ + uint32_t always1; /*< Unknown, always seems to be 1. */ + uint32_t track_count; /*< Number of tracks in the file. */ + uint32_t flags; /*< Flags. */ +} PPBnkHeader; + +typedef struct PPBnkTrack { + uint32_t id; /*< Track ID. Usually track[i].id == track[i-1].id + 1, but not always */ + uint32_t size; /*< Size of the data in bytes. */ + uint32_t sample_rate; /*< Sample rate. */ + uint32_t always1_1; /*< Unknown, always seems to be 1. */ + uint32_t always1_2; /*< Unknown, always seems to be 1. */ +} PPBnkTrack; + +typedef struct PPBnkCtxTrack { + int64_t data_offset; + uint32_t data_size; + uint32_t bytes_read; +} PPBnkCtxTrack; + +typedef struct PPBnkCtx { + int track_count; + PPBnkCtxTrack *tracks; + uint32_t current_track; + int is_music; +} PPBnkCtx; + +enum { + PP_BNK_FLAG_PERSIST = (1 << 0), /*< This is a large file, keep in memory. */ + PP_BNK_FLAG_MUSIC = (1 << 1), /*< This is music. */ + PP_BNK_FLAG_MASK = (PP_BNK_FLAG_PERSIST | PP_BNK_FLAG_MUSIC) +}; + +static void pp_bnk_parse_header(PPBnkHeader *hdr, const uint8_t *buf) +{ + hdr->bank_id = AV_RL32(buf + 0); + hdr->sample_rate = AV_RL32(buf + 4); + hdr->always1 = AV_RL32(buf + 8); + hdr->track_count = AV_RL32(buf + 12); + hdr->flags = AV_RL32(buf + 16); +} + +static void pp_bnk_parse_track(PPBnkTrack *trk, const uint8_t *buf) +{ + trk->id = AV_RL32(buf + 0); + trk->size = AV_RL32(buf + 4); + trk->sample_rate = AV_RL32(buf + 8); + trk->always1_1 = AV_RL32(buf + 12); + trk->always1_2 = AV_RL32(buf + 16); +} + +static int pp_bnk_probe(const AVProbeData *p) +{ + uint32_t sample_rate = AV_RL32(p->buf + 4); + uint32_t track_count = AV_RL32(p->buf + 12); + uint32_t flags = AV_RL32(p->buf + 16); + + if (track_count == 0 || track_count > INT_MAX) + return 0; + + if ((sample_rate != 5512) && (sample_rate != 11025) && + (sample_rate != 22050) && (sample_rate != 44100)) + return 0; + + /* Check the first track header. */ + if (AV_RL32(p->buf + 28) != sample_rate) + return 0; + + if ((flags & ~PP_BNK_FLAG_MASK) != 0) + return 0; + + return AVPROBE_SCORE_MAX / 4 + 1; +} + +static int pp_bnk_read_header(AVFormatContext *s) +{ + int64_t ret; + AVStream *st; + AVCodecParameters *par; + PPBnkCtx *ctx = s->priv_data; + uint8_t buf[FFMAX(PP_BNK_FILE_HEADER_SIZE, PP_BNK_TRACK_SIZE)]; + PPBnkHeader hdr; + + if ((ret = avio_read(s->pb, buf, PP_BNK_FILE_HEADER_SIZE)) < 0) + return ret; + else if (ret != PP_BNK_FILE_HEADER_SIZE) + return AVERROR(EIO); + + pp_bnk_parse_header(&hdr, buf); + + if (hdr.track_count == 0 || hdr.track_count > INT_MAX) + return AVERROR_INVALIDDATA; + + if (hdr.sample_rate == 0 || hdr.sample_rate > INT_MAX) + return AVERROR_INVALIDDATA; + + if (hdr.always1 != 1) { + avpriv_request_sample(s, "Non-one header value"); + return AVERROR_PATCHWELCOME; + } + + ctx->track_count = hdr.track_count; + + if (!(ctx->tracks = av_malloc_array(hdr.track_count, sizeof(PPBnkCtxTrack)))) + return AVERROR(ENOMEM); + + /* Parse and validate each track. */ + for (int i = 0; i < hdr.track_count; i++) { + PPBnkTrack e; + PPBnkCtxTrack *trk = ctx->tracks + i; + + ret = avio_read(s->pb, buf, PP_BNK_TRACK_SIZE); + if (ret < 0 && ret != AVERROR_EOF) + goto fail; + + /* Short byte-count or EOF, we have a truncated file. */ + if (ret != PP_BNK_TRACK_SIZE) { + av_log(s, AV_LOG_WARNING, "File truncated at %d/%u track(s)\n", + i, hdr.track_count); + ctx->track_count = i; + break; + } + + pp_bnk_parse_track(&e, buf); + + /* The individual sample rates of all tracks must match that of the file header. */ + if (e.sample_rate != hdr.sample_rate) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + if (e.always1_1 != 1 || e.always1_2 != 1) { + avpriv_request_sample(s, "Non-one track header values"); + ret = AVERROR_PATCHWELCOME; + goto fail; + } + + trk->data_offset = avio_tell(s->pb); + trk->data_size = e.size; + trk->bytes_read = 0; + + /* + * Skip over the data to the next stream header. + * Sometimes avio_skip() doesn't detect EOF. If it doesn't, either: + * - the avio_read() above will, or + * - pp_bnk_read_packet() will read a truncated last track. + */ + if ((ret = avio_skip(s->pb, e.size)) == AVERROR_EOF) { + ctx->track_count = i + 1; + av_log(s, AV_LOG_WARNING, + "Track %d has truncated data, assuming track count == %d\n", + i, ctx->track_count); + break; + } else if (ret < 0) { + goto fail; + } + } + + /* File is only a header. */ + if (ctx->track_count == 0) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + ctx->is_music = (hdr.flags & PP_BNK_FLAG_MUSIC) && + (ctx->track_count == 2) && + (ctx->tracks[0].data_size == ctx->tracks[1].data_size); + + /* Build the streams. */ + for (int i = 0; i < (ctx->is_music ? 1 : ctx->track_count); i++) { + if (!(st = avformat_new_stream(s, NULL))) { + ret = AVERROR(ENOMEM); + goto fail; + } + + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = AV_CODEC_ID_ADPCM_IMA_CUNNING; + par->format = AV_SAMPLE_FMT_S16P; + + if (ctx->is_music) { + par->channel_layout = AV_CH_LAYOUT_STEREO; + par->channels = 2; + } else { + par->channel_layout = AV_CH_LAYOUT_MONO; + par->channels = 1; + } + + par->sample_rate = hdr.sample_rate; + par->bits_per_coded_sample = 4; + par->bits_per_raw_sample = 16; + par->block_align = 1; + par->bit_rate = par->sample_rate * par->bits_per_coded_sample * par->channels; + + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + st->start_time = 0; + st->duration = ctx->tracks[i].data_size * 2; + } + + return 0; + +fail: + av_freep(&ctx->tracks); + return ret; +} + +static int pp_bnk_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + PPBnkCtx *ctx = s->priv_data; + + /* + * Read a packet from each track, round-robin style. + * This method is nasty, but needed to avoid "Too many packets buffered" errors. + */ + for (int i = 0; i < ctx->track_count; i++, ctx->current_track++) + { + int64_t ret; + int size; + PPBnkCtxTrack *trk; + + ctx->current_track %= ctx->track_count; + + trk = ctx->tracks + ctx->current_track; + + if (trk->bytes_read == trk->data_size) + continue; + + if ((ret = avio_seek(s->pb, trk->data_offset + trk->bytes_read, SEEK_SET)) < 0) + return ret; + else if (ret != trk->data_offset + trk->bytes_read) + return AVERROR(EIO); + + size = FFMIN(trk->data_size - trk->bytes_read, PP_BNK_MAX_READ_SIZE); + + if (!ctx->is_music) { + ret = av_get_packet(s->pb, pkt, size); + if (ret == AVERROR_EOF) { + /* If we've hit EOF, don't attempt this track again. */ + trk->data_size = trk->bytes_read; + continue; + } + } else { + if (!pkt->data && (ret = av_new_packet(pkt, size * 2)) < 0) + return ret; + ret = avio_read(s->pb, pkt->data + size * ctx->current_track, size); + if (ret >= 0 && ret != size) { + /* Only return stereo packets if both tracks could be read. */ + ret = AVERROR_EOF; + } + } + if (ret < 0) + return ret; + + trk->bytes_read += ret; + pkt->flags &= ~AV_PKT_FLAG_CORRUPT; + pkt->stream_index = ctx->current_track; + pkt->duration = ret * 2; + + if (ctx->is_music) { + if (pkt->stream_index == 0) + continue; + + pkt->stream_index = 0; + } + + ctx->current_track++; + return 0; + } + + /* If we reach here, we're done. */ + return AVERROR_EOF; +} + +static int pp_bnk_read_close(AVFormatContext *s) +{ + PPBnkCtx *ctx = s->priv_data; + + av_freep(&ctx->tracks); + + return 0; +} + +static int pp_bnk_seek(AVFormatContext *s, int stream_index, + int64_t pts, int flags) +{ + PPBnkCtx *ctx = s->priv_data; + + if (pts != 0) + return AVERROR(EINVAL); + + if (ctx->is_music) { + av_assert0(stream_index == 0); + ctx->tracks[0].bytes_read = 0; + ctx->tracks[1].bytes_read = 0; + } else { + ctx->tracks[stream_index].bytes_read = 0; + } + + return 0; +} + +AVInputFormat ff_pp_bnk_demuxer = { + .name = "pp_bnk", + .long_name = NULL_IF_CONFIG_SMALL("Pro Pinball Series Soundbank"), + .priv_data_size = sizeof(PPBnkCtx), + .read_probe = pp_bnk_probe, + .read_header = pp_bnk_read_header, + .read_packet = pp_bnk_read_packet, + .read_close = pp_bnk_read_close, + .read_seek = pp_bnk_seek, +}; diff -Nru ffmpeg-4.2.2/libavformat/prompeg.c ffmpeg-4.4/libavformat/prompeg.c --- ffmpeg-4.2.2/libavformat/prompeg.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/prompeg.c 2020-07-11 10:39:30.000000000 +0000 @@ -291,8 +291,7 @@ } if (s->ttl > 0) { - snprintf(buf, sizeof (buf), "%d", s->ttl); - av_dict_set(&udp_opts, "ttl", buf, 0); + av_dict_set_int(&udp_opts, "ttl", s->ttl, 0); } ff_url_join(buf, sizeof (buf), "udp", NULL, hostname, rtp_port + 2, NULL); @@ -388,7 +387,7 @@ PrompegFec *fec_tmp; uint8_t *bitstring = NULL; int col_idx, col_out_idx, row_idx; - int ret, written = 0; + int ret = 0; if (s->init && ((ret = prompeg_init(h, buf, size)) < 0)) goto end; @@ -404,7 +403,6 @@ if (!s->first || s->packet_idx > 0) { if ((ret = prompeg_write_fec(h, s->fec_row, PROMPEG_FEC_ROW)) < 0) goto end; - written += ret; } memcpy(s->fec_row->bitstring, bitstring, s->bitstring_size); s->fec_row->sn = AV_RB16(buf + 2); @@ -435,7 +433,6 @@ col_out_idx = s->packet_idx / s->d; if ((ret = prompeg_write_fec(h, s->fec_col[col_out_idx], PROMPEG_FEC_COL)) < 0) goto end; - written += ret; } if (++s->packet_idx >= s->packet_idx_max) { @@ -444,7 +441,7 @@ s->first = 0; } - ret = written; + ret = size; end: av_free(bitstring); diff -Nru ffmpeg-4.2.2/libavformat/protocols.c ffmpeg-4.4/libavformat/protocols.c --- ffmpeg-4.2.2/libavformat/protocols.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/protocols.c 2021-04-08 21:28:40.000000000 +0000 @@ -34,6 +34,7 @@ extern const URLProtocol ff_file_protocol; extern const URLProtocol ff_ftp_protocol; extern const URLProtocol ff_gopher_protocol; +extern const URLProtocol ff_gophers_protocol; extern const URLProtocol ff_hls_protocol; extern const URLProtocol ff_http_protocol; extern const URLProtocol ff_httpproxy_protocol; @@ -60,6 +61,8 @@ extern const URLProtocol ff_udp_protocol; extern const URLProtocol ff_udplite_protocol; extern const URLProtocol ff_unix_protocol; +extern const URLProtocol ff_libamqp_protocol; +extern const URLProtocol ff_librist_protocol; extern const URLProtocol ff_librtmp_protocol; extern const URLProtocol ff_librtmpe_protocol; extern const URLProtocol ff_librtmps_protocol; @@ -68,9 +71,11 @@ extern const URLProtocol ff_libsrt_protocol; extern const URLProtocol ff_libssh_protocol; extern const URLProtocol ff_libsmbclient_protocol; +extern const URLProtocol ff_libzmq_protocol; #include "libavformat/protocol_list.c" +#if FF_API_CHILD_CLASS_NEXT const AVClass *ff_urlcontext_child_class_next(const AVClass *prev) { int i; @@ -89,7 +94,22 @@ return url_protocols[i]->priv_data_class; return NULL; } +#endif +const AVClass *ff_urlcontext_child_class_iterate(void **iter) +{ + const AVClass *ret = NULL; + uintptr_t i; + + for (i = (uintptr_t)*iter; url_protocols[i]; i++) { + ret = url_protocols[i]->priv_data_class; + if (ret) + break; + } + + *iter = (void*)(uintptr_t)(url_protocols[i] ? i + 1 : i); + return ret; +} const char *avio_enum_protocols(void **opaque, int output) { @@ -106,6 +126,16 @@ return avio_enum_protocols(opaque, output); } +const AVClass *avio_protocol_get_class(const char *name) +{ + int i = 0; + for (i = 0; url_protocols[i]; i++) { + if (!strcmp(url_protocols[i]->name, name)) + return url_protocols[i]->priv_data_class; + } + return NULL; +} + const URLProtocol **ffurl_get_protocols(const char *whitelist, const char *blacklist) { diff -Nru ffmpeg-4.2.2/libavformat/psxstr.c ffmpeg-4.4/libavformat/psxstr.c --- ffmpeg-4.2.2/libavformat/psxstr.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/psxstr.c 2020-07-11 10:39:30.000000000 +0000 @@ -160,7 +160,7 @@ AVIOContext *pb = s->pb; StrDemuxContext *str = s->priv_data; unsigned char sector[RAW_CD_SECTOR_SIZE]; - int channel; + int channel, ret; AVPacket *pkt; AVStream *st; @@ -213,8 +213,9 @@ if(pkt->data) av_log(s, AV_LOG_ERROR, "mismatching sector_count\n"); av_packet_unref(pkt); - if (av_new_packet(pkt, sector_count*VIDEO_DATA_CHUNK_SIZE)) - return AVERROR(EIO); + ret = av_new_packet(pkt, sector_count * VIDEO_DATA_CHUNK_SIZE); + if (ret < 0) + return ret; memset(pkt->data, 0, sector_count*VIDEO_DATA_CHUNK_SIZE); pkt->pos= avio_tell(pb) - RAW_CD_SECTOR_SIZE; @@ -267,8 +268,8 @@ st->start_time = 0; } pkt = ret_pkt; - if (av_new_packet(pkt, 2304)) - return AVERROR(EIO); + if ((ret = av_new_packet(pkt, 2304)) < 0) + return ret; memcpy(pkt->data,sector+24,2304); pkt->stream_index = diff -Nru ffmpeg-4.2.2/libavformat/qtpalette.c ffmpeg-4.4/libavformat/qtpalette.c --- ffmpeg-4.2.2/libavformat/qtpalette.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/qtpalette.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,10 +24,302 @@ #include #include -#include "avformat.h" -#include "libavutil/intreadwrite.h" +#include "libavcodec/codec_id.h" +#include "avio.h" #include "qtpalette.h" +static const uint8_t qt_default_palette_2[2 * 3] = { + 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00 +}; + +/* From a screenshot of the "Monitors & Sound" control panel in Mac OS 7.5.5 */ +static const uint8_t qt_default_palette_4[4 * 3] = { + 0xFF, 0xFF, 0xFF, + 0xAC, 0xAC, 0xAC, + 0x55, 0x55, 0x55, + 0x00, 0x00, 0x00 +}; + +/* From a screenshot of the "Monitors & Sound" control panel in Mac OS 7.5.5 */ +static const uint8_t qt_default_palette_16[16 * 3] = { + 0xFF, 0xFF, 0xFF, + 0xFC, 0xF3, 0x05, + 0xFF, 0x64, 0x02, + 0xDD, 0x08, 0x06, + 0xF2, 0x08, 0x84, + 0x46, 0x00, 0xA5, + 0x00, 0x00, 0xD4, + 0x02, 0xAB, 0xEA, + 0x1F, 0xB7, 0x14, + 0x00, 0x64, 0x11, + 0x56, 0x2C, 0x05, + 0x90, 0x71, 0x3A, + 0xC0, 0xC0, 0xC0, + 0x80, 0x80, 0x80, + 0x40, 0x40, 0x40, + 0x00, 0x00, 0x00 +}; + +static const uint8_t qt_default_palette_256[256 * 3] = { + /* 0, 0x00 */ 0xFF, 0xFF, 0xFF, + /* 1, 0x01 */ 0xFF, 0xFF, 0xCC, + /* 2, 0x02 */ 0xFF, 0xFF, 0x99, + /* 3, 0x03 */ 0xFF, 0xFF, 0x66, + /* 4, 0x04 */ 0xFF, 0xFF, 0x33, + /* 5, 0x05 */ 0xFF, 0xFF, 0x00, + /* 6, 0x06 */ 0xFF, 0xCC, 0xFF, + /* 7, 0x07 */ 0xFF, 0xCC, 0xCC, + /* 8, 0x08 */ 0xFF, 0xCC, 0x99, + /* 9, 0x09 */ 0xFF, 0xCC, 0x66, + /* 10, 0x0A */ 0xFF, 0xCC, 0x33, + /* 11, 0x0B */ 0xFF, 0xCC, 0x00, + /* 12, 0x0C */ 0xFF, 0x99, 0xFF, + /* 13, 0x0D */ 0xFF, 0x99, 0xCC, + /* 14, 0x0E */ 0xFF, 0x99, 0x99, + /* 15, 0x0F */ 0xFF, 0x99, 0x66, + /* 16, 0x10 */ 0xFF, 0x99, 0x33, + /* 17, 0x11 */ 0xFF, 0x99, 0x00, + /* 18, 0x12 */ 0xFF, 0x66, 0xFF, + /* 19, 0x13 */ 0xFF, 0x66, 0xCC, + /* 20, 0x14 */ 0xFF, 0x66, 0x99, + /* 21, 0x15 */ 0xFF, 0x66, 0x66, + /* 22, 0x16 */ 0xFF, 0x66, 0x33, + /* 23, 0x17 */ 0xFF, 0x66, 0x00, + /* 24, 0x18 */ 0xFF, 0x33, 0xFF, + /* 25, 0x19 */ 0xFF, 0x33, 0xCC, + /* 26, 0x1A */ 0xFF, 0x33, 0x99, + /* 27, 0x1B */ 0xFF, 0x33, 0x66, + /* 28, 0x1C */ 0xFF, 0x33, 0x33, + /* 29, 0x1D */ 0xFF, 0x33, 0x00, + /* 30, 0x1E */ 0xFF, 0x00, 0xFF, + /* 31, 0x1F */ 0xFF, 0x00, 0xCC, + /* 32, 0x20 */ 0xFF, 0x00, 0x99, + /* 33, 0x21 */ 0xFF, 0x00, 0x66, + /* 34, 0x22 */ 0xFF, 0x00, 0x33, + /* 35, 0x23 */ 0xFF, 0x00, 0x00, + /* 36, 0x24 */ 0xCC, 0xFF, 0xFF, + /* 37, 0x25 */ 0xCC, 0xFF, 0xCC, + /* 38, 0x26 */ 0xCC, 0xFF, 0x99, + /* 39, 0x27 */ 0xCC, 0xFF, 0x66, + /* 40, 0x28 */ 0xCC, 0xFF, 0x33, + /* 41, 0x29 */ 0xCC, 0xFF, 0x00, + /* 42, 0x2A */ 0xCC, 0xCC, 0xFF, + /* 43, 0x2B */ 0xCC, 0xCC, 0xCC, + /* 44, 0x2C */ 0xCC, 0xCC, 0x99, + /* 45, 0x2D */ 0xCC, 0xCC, 0x66, + /* 46, 0x2E */ 0xCC, 0xCC, 0x33, + /* 47, 0x2F */ 0xCC, 0xCC, 0x00, + /* 48, 0x30 */ 0xCC, 0x99, 0xFF, + /* 49, 0x31 */ 0xCC, 0x99, 0xCC, + /* 50, 0x32 */ 0xCC, 0x99, 0x99, + /* 51, 0x33 */ 0xCC, 0x99, 0x66, + /* 52, 0x34 */ 0xCC, 0x99, 0x33, + /* 53, 0x35 */ 0xCC, 0x99, 0x00, + /* 54, 0x36 */ 0xCC, 0x66, 0xFF, + /* 55, 0x37 */ 0xCC, 0x66, 0xCC, + /* 56, 0x38 */ 0xCC, 0x66, 0x99, + /* 57, 0x39 */ 0xCC, 0x66, 0x66, + /* 58, 0x3A */ 0xCC, 0x66, 0x33, + /* 59, 0x3B */ 0xCC, 0x66, 0x00, + /* 60, 0x3C */ 0xCC, 0x33, 0xFF, + /* 61, 0x3D */ 0xCC, 0x33, 0xCC, + /* 62, 0x3E */ 0xCC, 0x33, 0x99, + /* 63, 0x3F */ 0xCC, 0x33, 0x66, + /* 64, 0x40 */ 0xCC, 0x33, 0x33, + /* 65, 0x41 */ 0xCC, 0x33, 0x00, + /* 66, 0x42 */ 0xCC, 0x00, 0xFF, + /* 67, 0x43 */ 0xCC, 0x00, 0xCC, + /* 68, 0x44 */ 0xCC, 0x00, 0x99, + /* 69, 0x45 */ 0xCC, 0x00, 0x66, + /* 70, 0x46 */ 0xCC, 0x00, 0x33, + /* 71, 0x47 */ 0xCC, 0x00, 0x00, + /* 72, 0x48 */ 0x99, 0xFF, 0xFF, + /* 73, 0x49 */ 0x99, 0xFF, 0xCC, + /* 74, 0x4A */ 0x99, 0xFF, 0x99, + /* 75, 0x4B */ 0x99, 0xFF, 0x66, + /* 76, 0x4C */ 0x99, 0xFF, 0x33, + /* 77, 0x4D */ 0x99, 0xFF, 0x00, + /* 78, 0x4E */ 0x99, 0xCC, 0xFF, + /* 79, 0x4F */ 0x99, 0xCC, 0xCC, + /* 80, 0x50 */ 0x99, 0xCC, 0x99, + /* 81, 0x51 */ 0x99, 0xCC, 0x66, + /* 82, 0x52 */ 0x99, 0xCC, 0x33, + /* 83, 0x53 */ 0x99, 0xCC, 0x00, + /* 84, 0x54 */ 0x99, 0x99, 0xFF, + /* 85, 0x55 */ 0x99, 0x99, 0xCC, + /* 86, 0x56 */ 0x99, 0x99, 0x99, + /* 87, 0x57 */ 0x99, 0x99, 0x66, + /* 88, 0x58 */ 0x99, 0x99, 0x33, + /* 89, 0x59 */ 0x99, 0x99, 0x00, + /* 90, 0x5A */ 0x99, 0x66, 0xFF, + /* 91, 0x5B */ 0x99, 0x66, 0xCC, + /* 92, 0x5C */ 0x99, 0x66, 0x99, + /* 93, 0x5D */ 0x99, 0x66, 0x66, + /* 94, 0x5E */ 0x99, 0x66, 0x33, + /* 95, 0x5F */ 0x99, 0x66, 0x00, + /* 96, 0x60 */ 0x99, 0x33, 0xFF, + /* 97, 0x61 */ 0x99, 0x33, 0xCC, + /* 98, 0x62 */ 0x99, 0x33, 0x99, + /* 99, 0x63 */ 0x99, 0x33, 0x66, + /* 100, 0x64 */ 0x99, 0x33, 0x33, + /* 101, 0x65 */ 0x99, 0x33, 0x00, + /* 102, 0x66 */ 0x99, 0x00, 0xFF, + /* 103, 0x67 */ 0x99, 0x00, 0xCC, + /* 104, 0x68 */ 0x99, 0x00, 0x99, + /* 105, 0x69 */ 0x99, 0x00, 0x66, + /* 106, 0x6A */ 0x99, 0x00, 0x33, + /* 107, 0x6B */ 0x99, 0x00, 0x00, + /* 108, 0x6C */ 0x66, 0xFF, 0xFF, + /* 109, 0x6D */ 0x66, 0xFF, 0xCC, + /* 110, 0x6E */ 0x66, 0xFF, 0x99, + /* 111, 0x6F */ 0x66, 0xFF, 0x66, + /* 112, 0x70 */ 0x66, 0xFF, 0x33, + /* 113, 0x71 */ 0x66, 0xFF, 0x00, + /* 114, 0x72 */ 0x66, 0xCC, 0xFF, + /* 115, 0x73 */ 0x66, 0xCC, 0xCC, + /* 116, 0x74 */ 0x66, 0xCC, 0x99, + /* 117, 0x75 */ 0x66, 0xCC, 0x66, + /* 118, 0x76 */ 0x66, 0xCC, 0x33, + /* 119, 0x77 */ 0x66, 0xCC, 0x00, + /* 120, 0x78 */ 0x66, 0x99, 0xFF, + /* 121, 0x79 */ 0x66, 0x99, 0xCC, + /* 122, 0x7A */ 0x66, 0x99, 0x99, + /* 123, 0x7B */ 0x66, 0x99, 0x66, + /* 124, 0x7C */ 0x66, 0x99, 0x33, + /* 125, 0x7D */ 0x66, 0x99, 0x00, + /* 126, 0x7E */ 0x66, 0x66, 0xFF, + /* 127, 0x7F */ 0x66, 0x66, 0xCC, + /* 128, 0x80 */ 0x66, 0x66, 0x99, + /* 129, 0x81 */ 0x66, 0x66, 0x66, + /* 130, 0x82 */ 0x66, 0x66, 0x33, + /* 131, 0x83 */ 0x66, 0x66, 0x00, + /* 132, 0x84 */ 0x66, 0x33, 0xFF, + /* 133, 0x85 */ 0x66, 0x33, 0xCC, + /* 134, 0x86 */ 0x66, 0x33, 0x99, + /* 135, 0x87 */ 0x66, 0x33, 0x66, + /* 136, 0x88 */ 0x66, 0x33, 0x33, + /* 137, 0x89 */ 0x66, 0x33, 0x00, + /* 138, 0x8A */ 0x66, 0x00, 0xFF, + /* 139, 0x8B */ 0x66, 0x00, 0xCC, + /* 140, 0x8C */ 0x66, 0x00, 0x99, + /* 141, 0x8D */ 0x66, 0x00, 0x66, + /* 142, 0x8E */ 0x66, 0x00, 0x33, + /* 143, 0x8F */ 0x66, 0x00, 0x00, + /* 144, 0x90 */ 0x33, 0xFF, 0xFF, + /* 145, 0x91 */ 0x33, 0xFF, 0xCC, + /* 146, 0x92 */ 0x33, 0xFF, 0x99, + /* 147, 0x93 */ 0x33, 0xFF, 0x66, + /* 148, 0x94 */ 0x33, 0xFF, 0x33, + /* 149, 0x95 */ 0x33, 0xFF, 0x00, + /* 150, 0x96 */ 0x33, 0xCC, 0xFF, + /* 151, 0x97 */ 0x33, 0xCC, 0xCC, + /* 152, 0x98 */ 0x33, 0xCC, 0x99, + /* 153, 0x99 */ 0x33, 0xCC, 0x66, + /* 154, 0x9A */ 0x33, 0xCC, 0x33, + /* 155, 0x9B */ 0x33, 0xCC, 0x00, + /* 156, 0x9C */ 0x33, 0x99, 0xFF, + /* 157, 0x9D */ 0x33, 0x99, 0xCC, + /* 158, 0x9E */ 0x33, 0x99, 0x99, + /* 159, 0x9F */ 0x33, 0x99, 0x66, + /* 160, 0xA0 */ 0x33, 0x99, 0x33, + /* 161, 0xA1 */ 0x33, 0x99, 0x00, + /* 162, 0xA2 */ 0x33, 0x66, 0xFF, + /* 163, 0xA3 */ 0x33, 0x66, 0xCC, + /* 164, 0xA4 */ 0x33, 0x66, 0x99, + /* 165, 0xA5 */ 0x33, 0x66, 0x66, + /* 166, 0xA6 */ 0x33, 0x66, 0x33, + /* 167, 0xA7 */ 0x33, 0x66, 0x00, + /* 168, 0xA8 */ 0x33, 0x33, 0xFF, + /* 169, 0xA9 */ 0x33, 0x33, 0xCC, + /* 170, 0xAA */ 0x33, 0x33, 0x99, + /* 171, 0xAB */ 0x33, 0x33, 0x66, + /* 172, 0xAC */ 0x33, 0x33, 0x33, + /* 173, 0xAD */ 0x33, 0x33, 0x00, + /* 174, 0xAE */ 0x33, 0x00, 0xFF, + /* 175, 0xAF */ 0x33, 0x00, 0xCC, + /* 176, 0xB0 */ 0x33, 0x00, 0x99, + /* 177, 0xB1 */ 0x33, 0x00, 0x66, + /* 178, 0xB2 */ 0x33, 0x00, 0x33, + /* 179, 0xB3 */ 0x33, 0x00, 0x00, + /* 180, 0xB4 */ 0x00, 0xFF, 0xFF, + /* 181, 0xB5 */ 0x00, 0xFF, 0xCC, + /* 182, 0xB6 */ 0x00, 0xFF, 0x99, + /* 183, 0xB7 */ 0x00, 0xFF, 0x66, + /* 184, 0xB8 */ 0x00, 0xFF, 0x33, + /* 185, 0xB9 */ 0x00, 0xFF, 0x00, + /* 186, 0xBA */ 0x00, 0xCC, 0xFF, + /* 187, 0xBB */ 0x00, 0xCC, 0xCC, + /* 188, 0xBC */ 0x00, 0xCC, 0x99, + /* 189, 0xBD */ 0x00, 0xCC, 0x66, + /* 190, 0xBE */ 0x00, 0xCC, 0x33, + /* 191, 0xBF */ 0x00, 0xCC, 0x00, + /* 192, 0xC0 */ 0x00, 0x99, 0xFF, + /* 193, 0xC1 */ 0x00, 0x99, 0xCC, + /* 194, 0xC2 */ 0x00, 0x99, 0x99, + /* 195, 0xC3 */ 0x00, 0x99, 0x66, + /* 196, 0xC4 */ 0x00, 0x99, 0x33, + /* 197, 0xC5 */ 0x00, 0x99, 0x00, + /* 198, 0xC6 */ 0x00, 0x66, 0xFF, + /* 199, 0xC7 */ 0x00, 0x66, 0xCC, + /* 200, 0xC8 */ 0x00, 0x66, 0x99, + /* 201, 0xC9 */ 0x00, 0x66, 0x66, + /* 202, 0xCA */ 0x00, 0x66, 0x33, + /* 203, 0xCB */ 0x00, 0x66, 0x00, + /* 204, 0xCC */ 0x00, 0x33, 0xFF, + /* 205, 0xCD */ 0x00, 0x33, 0xCC, + /* 206, 0xCE */ 0x00, 0x33, 0x99, + /* 207, 0xCF */ 0x00, 0x33, 0x66, + /* 208, 0xD0 */ 0x00, 0x33, 0x33, + /* 209, 0xD1 */ 0x00, 0x33, 0x00, + /* 210, 0xD2 */ 0x00, 0x00, 0xFF, + /* 211, 0xD3 */ 0x00, 0x00, 0xCC, + /* 212, 0xD4 */ 0x00, 0x00, 0x99, + /* 213, 0xD5 */ 0x00, 0x00, 0x66, + /* 214, 0xD6 */ 0x00, 0x00, 0x33, + /* 215, 0xD7 */ 0xEE, 0x00, 0x00, + /* 216, 0xD8 */ 0xDD, 0x00, 0x00, + /* 217, 0xD9 */ 0xBB, 0x00, 0x00, + /* 218, 0xDA */ 0xAA, 0x00, 0x00, + /* 219, 0xDB */ 0x88, 0x00, 0x00, + /* 220, 0xDC */ 0x77, 0x00, 0x00, + /* 221, 0xDD */ 0x55, 0x00, 0x00, + /* 222, 0xDE */ 0x44, 0x00, 0x00, + /* 223, 0xDF */ 0x22, 0x00, 0x00, + /* 224, 0xE0 */ 0x11, 0x00, 0x00, + /* 225, 0xE1 */ 0x00, 0xEE, 0x00, + /* 226, 0xE2 */ 0x00, 0xDD, 0x00, + /* 227, 0xE3 */ 0x00, 0xBB, 0x00, + /* 228, 0xE4 */ 0x00, 0xAA, 0x00, + /* 229, 0xE5 */ 0x00, 0x88, 0x00, + /* 230, 0xE6 */ 0x00, 0x77, 0x00, + /* 231, 0xE7 */ 0x00, 0x55, 0x00, + /* 232, 0xE8 */ 0x00, 0x44, 0x00, + /* 233, 0xE9 */ 0x00, 0x22, 0x00, + /* 234, 0xEA */ 0x00, 0x11, 0x00, + /* 235, 0xEB */ 0x00, 0x00, 0xEE, + /* 236, 0xEC */ 0x00, 0x00, 0xDD, + /* 237, 0xED */ 0x00, 0x00, 0xBB, + /* 238, 0xEE */ 0x00, 0x00, 0xAA, + /* 239, 0xEF */ 0x00, 0x00, 0x88, + /* 240, 0xF0 */ 0x00, 0x00, 0x77, + /* 241, 0xF1 */ 0x00, 0x00, 0x55, + /* 242, 0xF2 */ 0x00, 0x00, 0x44, + /* 243, 0xF3 */ 0x00, 0x00, 0x22, + /* 244, 0xF4 */ 0x00, 0x00, 0x11, + /* 245, 0xF5 */ 0xEE, 0xEE, 0xEE, + /* 246, 0xF6 */ 0xDD, 0xDD, 0xDD, + /* 247, 0xF7 */ 0xBB, 0xBB, 0xBB, + /* 248, 0xF8 */ 0xAA, 0xAA, 0xAA, + /* 249, 0xF9 */ 0x88, 0x88, 0x88, + /* 250, 0xFA */ 0x77, 0x77, 0x77, + /* 251, 0xFB */ 0x55, 0x55, 0x55, + /* 252, 0xFC */ 0x44, 0x44, 0x44, + /* 253, 0xFD */ 0x22, 0x22, 0x22, + /* 254, 0xFE */ 0x11, 0x11, 0x11, + /* 255, 0xFF */ 0x00, 0x00, 0x00 +}; + int ff_get_qtpalette(int codec_id, AVIOContext *pb, uint32_t *palette) { int tmp, bit_depth, color_table_id, greyscale, i; @@ -73,13 +365,13 @@ const uint8_t *color_table; color_count = 1 << bit_depth; if (bit_depth == 1) - color_table = ff_qt_default_palette_2; + color_table = qt_default_palette_2; else if (bit_depth == 2) - color_table = ff_qt_default_palette_4; + color_table = qt_default_palette_4; else if (bit_depth == 4) - color_table = ff_qt_default_palette_16; + color_table = qt_default_palette_16; else - color_table = ff_qt_default_palette_256; + color_table = qt_default_palette_256; for (i = 0; i < color_count; i++) { r = color_table[i * 3 + 0]; g = color_table[i * 3 + 1]; diff -Nru ffmpeg-4.2.2/libavformat/qtpalette.h ffmpeg-4.4/libavformat/qtpalette.h --- ffmpeg-4.2.2/libavformat/qtpalette.h 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavformat/qtpalette.h 2021-04-08 21:28:40.000000000 +0000 @@ -24,299 +24,7 @@ #define AVFORMAT_QTPALETTE_H #include -#include "avformat.h" - -static const uint8_t ff_qt_default_palette_2[2 * 3] = { - 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00 -}; - -/* From a screenshot of the "Monitors & Sound" control panel in Mac OS 7.5.5 */ -static const uint8_t ff_qt_default_palette_4[4 * 3] = { - 0xFF, 0xFF, 0xFF, - 0xAC, 0xAC, 0xAC, - 0x55, 0x55, 0x55, - 0x00, 0x00, 0x00 -}; - -/* From a screenshot of the "Monitors & Sound" control panel in Mac OS 7.5.5 */ -static const uint8_t ff_qt_default_palette_16[16 * 3] = { - 0xFF, 0xFF, 0xFF, - 0xFC, 0xF3, 0x05, - 0xFF, 0x64, 0x02, - 0xDD, 0x08, 0x06, - 0xF2, 0x08, 0x84, - 0x46, 0x00, 0xA5, - 0x00, 0x00, 0xD4, - 0x02, 0xAB, 0xEA, - 0x1F, 0xB7, 0x14, - 0x00, 0x64, 0x11, - 0x56, 0x2C, 0x05, - 0x90, 0x71, 0x3A, - 0xC0, 0xC0, 0xC0, - 0x80, 0x80, 0x80, - 0x40, 0x40, 0x40, - 0x00, 0x00, 0x00 -}; - -static const uint8_t ff_qt_default_palette_256[256 * 3] = { - /* 0, 0x00 */ 0xFF, 0xFF, 0xFF, - /* 1, 0x01 */ 0xFF, 0xFF, 0xCC, - /* 2, 0x02 */ 0xFF, 0xFF, 0x99, - /* 3, 0x03 */ 0xFF, 0xFF, 0x66, - /* 4, 0x04 */ 0xFF, 0xFF, 0x33, - /* 5, 0x05 */ 0xFF, 0xFF, 0x00, - /* 6, 0x06 */ 0xFF, 0xCC, 0xFF, - /* 7, 0x07 */ 0xFF, 0xCC, 0xCC, - /* 8, 0x08 */ 0xFF, 0xCC, 0x99, - /* 9, 0x09 */ 0xFF, 0xCC, 0x66, - /* 10, 0x0A */ 0xFF, 0xCC, 0x33, - /* 11, 0x0B */ 0xFF, 0xCC, 0x00, - /* 12, 0x0C */ 0xFF, 0x99, 0xFF, - /* 13, 0x0D */ 0xFF, 0x99, 0xCC, - /* 14, 0x0E */ 0xFF, 0x99, 0x99, - /* 15, 0x0F */ 0xFF, 0x99, 0x66, - /* 16, 0x10 */ 0xFF, 0x99, 0x33, - /* 17, 0x11 */ 0xFF, 0x99, 0x00, - /* 18, 0x12 */ 0xFF, 0x66, 0xFF, - /* 19, 0x13 */ 0xFF, 0x66, 0xCC, - /* 20, 0x14 */ 0xFF, 0x66, 0x99, - /* 21, 0x15 */ 0xFF, 0x66, 0x66, - /* 22, 0x16 */ 0xFF, 0x66, 0x33, - /* 23, 0x17 */ 0xFF, 0x66, 0x00, - /* 24, 0x18 */ 0xFF, 0x33, 0xFF, - /* 25, 0x19 */ 0xFF, 0x33, 0xCC, - /* 26, 0x1A */ 0xFF, 0x33, 0x99, - /* 27, 0x1B */ 0xFF, 0x33, 0x66, - /* 28, 0x1C */ 0xFF, 0x33, 0x33, - /* 29, 0x1D */ 0xFF, 0x33, 0x00, - /* 30, 0x1E */ 0xFF, 0x00, 0xFF, - /* 31, 0x1F */ 0xFF, 0x00, 0xCC, - /* 32, 0x20 */ 0xFF, 0x00, 0x99, - /* 33, 0x21 */ 0xFF, 0x00, 0x66, - /* 34, 0x22 */ 0xFF, 0x00, 0x33, - /* 35, 0x23 */ 0xFF, 0x00, 0x00, - /* 36, 0x24 */ 0xCC, 0xFF, 0xFF, - /* 37, 0x25 */ 0xCC, 0xFF, 0xCC, - /* 38, 0x26 */ 0xCC, 0xFF, 0x99, - /* 39, 0x27 */ 0xCC, 0xFF, 0x66, - /* 40, 0x28 */ 0xCC, 0xFF, 0x33, - /* 41, 0x29 */ 0xCC, 0xFF, 0x00, - /* 42, 0x2A */ 0xCC, 0xCC, 0xFF, - /* 43, 0x2B */ 0xCC, 0xCC, 0xCC, - /* 44, 0x2C */ 0xCC, 0xCC, 0x99, - /* 45, 0x2D */ 0xCC, 0xCC, 0x66, - /* 46, 0x2E */ 0xCC, 0xCC, 0x33, - /* 47, 0x2F */ 0xCC, 0xCC, 0x00, - /* 48, 0x30 */ 0xCC, 0x99, 0xFF, - /* 49, 0x31 */ 0xCC, 0x99, 0xCC, - /* 50, 0x32 */ 0xCC, 0x99, 0x99, - /* 51, 0x33 */ 0xCC, 0x99, 0x66, - /* 52, 0x34 */ 0xCC, 0x99, 0x33, - /* 53, 0x35 */ 0xCC, 0x99, 0x00, - /* 54, 0x36 */ 0xCC, 0x66, 0xFF, - /* 55, 0x37 */ 0xCC, 0x66, 0xCC, - /* 56, 0x38 */ 0xCC, 0x66, 0x99, - /* 57, 0x39 */ 0xCC, 0x66, 0x66, - /* 58, 0x3A */ 0xCC, 0x66, 0x33, - /* 59, 0x3B */ 0xCC, 0x66, 0x00, - /* 60, 0x3C */ 0xCC, 0x33, 0xFF, - /* 61, 0x3D */ 0xCC, 0x33, 0xCC, - /* 62, 0x3E */ 0xCC, 0x33, 0x99, - /* 63, 0x3F */ 0xCC, 0x33, 0x66, - /* 64, 0x40 */ 0xCC, 0x33, 0x33, - /* 65, 0x41 */ 0xCC, 0x33, 0x00, - /* 66, 0x42 */ 0xCC, 0x00, 0xFF, - /* 67, 0x43 */ 0xCC, 0x00, 0xCC, - /* 68, 0x44 */ 0xCC, 0x00, 0x99, - /* 69, 0x45 */ 0xCC, 0x00, 0x66, - /* 70, 0x46 */ 0xCC, 0x00, 0x33, - /* 71, 0x47 */ 0xCC, 0x00, 0x00, - /* 72, 0x48 */ 0x99, 0xFF, 0xFF, - /* 73, 0x49 */ 0x99, 0xFF, 0xCC, - /* 74, 0x4A */ 0x99, 0xFF, 0x99, - /* 75, 0x4B */ 0x99, 0xFF, 0x66, - /* 76, 0x4C */ 0x99, 0xFF, 0x33, - /* 77, 0x4D */ 0x99, 0xFF, 0x00, - /* 78, 0x4E */ 0x99, 0xCC, 0xFF, - /* 79, 0x4F */ 0x99, 0xCC, 0xCC, - /* 80, 0x50 */ 0x99, 0xCC, 0x99, - /* 81, 0x51 */ 0x99, 0xCC, 0x66, - /* 82, 0x52 */ 0x99, 0xCC, 0x33, - /* 83, 0x53 */ 0x99, 0xCC, 0x00, - /* 84, 0x54 */ 0x99, 0x99, 0xFF, - /* 85, 0x55 */ 0x99, 0x99, 0xCC, - /* 86, 0x56 */ 0x99, 0x99, 0x99, - /* 87, 0x57 */ 0x99, 0x99, 0x66, - /* 88, 0x58 */ 0x99, 0x99, 0x33, - /* 89, 0x59 */ 0x99, 0x99, 0x00, - /* 90, 0x5A */ 0x99, 0x66, 0xFF, - /* 91, 0x5B */ 0x99, 0x66, 0xCC, - /* 92, 0x5C */ 0x99, 0x66, 0x99, - /* 93, 0x5D */ 0x99, 0x66, 0x66, - /* 94, 0x5E */ 0x99, 0x66, 0x33, - /* 95, 0x5F */ 0x99, 0x66, 0x00, - /* 96, 0x60 */ 0x99, 0x33, 0xFF, - /* 97, 0x61 */ 0x99, 0x33, 0xCC, - /* 98, 0x62 */ 0x99, 0x33, 0x99, - /* 99, 0x63 */ 0x99, 0x33, 0x66, - /* 100, 0x64 */ 0x99, 0x33, 0x33, - /* 101, 0x65 */ 0x99, 0x33, 0x00, - /* 102, 0x66 */ 0x99, 0x00, 0xFF, - /* 103, 0x67 */ 0x99, 0x00, 0xCC, - /* 104, 0x68 */ 0x99, 0x00, 0x99, - /* 105, 0x69 */ 0x99, 0x00, 0x66, - /* 106, 0x6A */ 0x99, 0x00, 0x33, - /* 107, 0x6B */ 0x99, 0x00, 0x00, - /* 108, 0x6C */ 0x66, 0xFF, 0xFF, - /* 109, 0x6D */ 0x66, 0xFF, 0xCC, - /* 110, 0x6E */ 0x66, 0xFF, 0x99, - /* 111, 0x6F */ 0x66, 0xFF, 0x66, - /* 112, 0x70 */ 0x66, 0xFF, 0x33, - /* 113, 0x71 */ 0x66, 0xFF, 0x00, - /* 114, 0x72 */ 0x66, 0xCC, 0xFF, - /* 115, 0x73 */ 0x66, 0xCC, 0xCC, - /* 116, 0x74 */ 0x66, 0xCC, 0x99, - /* 117, 0x75 */ 0x66, 0xCC, 0x66, - /* 118, 0x76 */ 0x66, 0xCC, 0x33, - /* 119, 0x77 */ 0x66, 0xCC, 0x00, - /* 120, 0x78 */ 0x66, 0x99, 0xFF, - /* 121, 0x79 */ 0x66, 0x99, 0xCC, - /* 122, 0x7A */ 0x66, 0x99, 0x99, - /* 123, 0x7B */ 0x66, 0x99, 0x66, - /* 124, 0x7C */ 0x66, 0x99, 0x33, - /* 125, 0x7D */ 0x66, 0x99, 0x00, - /* 126, 0x7E */ 0x66, 0x66, 0xFF, - /* 127, 0x7F */ 0x66, 0x66, 0xCC, - /* 128, 0x80 */ 0x66, 0x66, 0x99, - /* 129, 0x81 */ 0x66, 0x66, 0x66, - /* 130, 0x82 */ 0x66, 0x66, 0x33, - /* 131, 0x83 */ 0x66, 0x66, 0x00, - /* 132, 0x84 */ 0x66, 0x33, 0xFF, - /* 133, 0x85 */ 0x66, 0x33, 0xCC, - /* 134, 0x86 */ 0x66, 0x33, 0x99, - /* 135, 0x87 */ 0x66, 0x33, 0x66, - /* 136, 0x88 */ 0x66, 0x33, 0x33, - /* 137, 0x89 */ 0x66, 0x33, 0x00, - /* 138, 0x8A */ 0x66, 0x00, 0xFF, - /* 139, 0x8B */ 0x66, 0x00, 0xCC, - /* 140, 0x8C */ 0x66, 0x00, 0x99, - /* 141, 0x8D */ 0x66, 0x00, 0x66, - /* 142, 0x8E */ 0x66, 0x00, 0x33, - /* 143, 0x8F */ 0x66, 0x00, 0x00, - /* 144, 0x90 */ 0x33, 0xFF, 0xFF, - /* 145, 0x91 */ 0x33, 0xFF, 0xCC, - /* 146, 0x92 */ 0x33, 0xFF, 0x99, - /* 147, 0x93 */ 0x33, 0xFF, 0x66, - /* 148, 0x94 */ 0x33, 0xFF, 0x33, - /* 149, 0x95 */ 0x33, 0xFF, 0x00, - /* 150, 0x96 */ 0x33, 0xCC, 0xFF, - /* 151, 0x97 */ 0x33, 0xCC, 0xCC, - /* 152, 0x98 */ 0x33, 0xCC, 0x99, - /* 153, 0x99 */ 0x33, 0xCC, 0x66, - /* 154, 0x9A */ 0x33, 0xCC, 0x33, - /* 155, 0x9B */ 0x33, 0xCC, 0x00, - /* 156, 0x9C */ 0x33, 0x99, 0xFF, - /* 157, 0x9D */ 0x33, 0x99, 0xCC, - /* 158, 0x9E */ 0x33, 0x99, 0x99, - /* 159, 0x9F */ 0x33, 0x99, 0x66, - /* 160, 0xA0 */ 0x33, 0x99, 0x33, - /* 161, 0xA1 */ 0x33, 0x99, 0x00, - /* 162, 0xA2 */ 0x33, 0x66, 0xFF, - /* 163, 0xA3 */ 0x33, 0x66, 0xCC, - /* 164, 0xA4 */ 0x33, 0x66, 0x99, - /* 165, 0xA5 */ 0x33, 0x66, 0x66, - /* 166, 0xA6 */ 0x33, 0x66, 0x33, - /* 167, 0xA7 */ 0x33, 0x66, 0x00, - /* 168, 0xA8 */ 0x33, 0x33, 0xFF, - /* 169, 0xA9 */ 0x33, 0x33, 0xCC, - /* 170, 0xAA */ 0x33, 0x33, 0x99, - /* 171, 0xAB */ 0x33, 0x33, 0x66, - /* 172, 0xAC */ 0x33, 0x33, 0x33, - /* 173, 0xAD */ 0x33, 0x33, 0x00, - /* 174, 0xAE */ 0x33, 0x00, 0xFF, - /* 175, 0xAF */ 0x33, 0x00, 0xCC, - /* 176, 0xB0 */ 0x33, 0x00, 0x99, - /* 177, 0xB1 */ 0x33, 0x00, 0x66, - /* 178, 0xB2 */ 0x33, 0x00, 0x33, - /* 179, 0xB3 */ 0x33, 0x00, 0x00, - /* 180, 0xB4 */ 0x00, 0xFF, 0xFF, - /* 181, 0xB5 */ 0x00, 0xFF, 0xCC, - /* 182, 0xB6 */ 0x00, 0xFF, 0x99, - /* 183, 0xB7 */ 0x00, 0xFF, 0x66, - /* 184, 0xB8 */ 0x00, 0xFF, 0x33, - /* 185, 0xB9 */ 0x00, 0xFF, 0x00, - /* 186, 0xBA */ 0x00, 0xCC, 0xFF, - /* 187, 0xBB */ 0x00, 0xCC, 0xCC, - /* 188, 0xBC */ 0x00, 0xCC, 0x99, - /* 189, 0xBD */ 0x00, 0xCC, 0x66, - /* 190, 0xBE */ 0x00, 0xCC, 0x33, - /* 191, 0xBF */ 0x00, 0xCC, 0x00, - /* 192, 0xC0 */ 0x00, 0x99, 0xFF, - /* 193, 0xC1 */ 0x00, 0x99, 0xCC, - /* 194, 0xC2 */ 0x00, 0x99, 0x99, - /* 195, 0xC3 */ 0x00, 0x99, 0x66, - /* 196, 0xC4 */ 0x00, 0x99, 0x33, - /* 197, 0xC5 */ 0x00, 0x99, 0x00, - /* 198, 0xC6 */ 0x00, 0x66, 0xFF, - /* 199, 0xC7 */ 0x00, 0x66, 0xCC, - /* 200, 0xC8 */ 0x00, 0x66, 0x99, - /* 201, 0xC9 */ 0x00, 0x66, 0x66, - /* 202, 0xCA */ 0x00, 0x66, 0x33, - /* 203, 0xCB */ 0x00, 0x66, 0x00, - /* 204, 0xCC */ 0x00, 0x33, 0xFF, - /* 205, 0xCD */ 0x00, 0x33, 0xCC, - /* 206, 0xCE */ 0x00, 0x33, 0x99, - /* 207, 0xCF */ 0x00, 0x33, 0x66, - /* 208, 0xD0 */ 0x00, 0x33, 0x33, - /* 209, 0xD1 */ 0x00, 0x33, 0x00, - /* 210, 0xD2 */ 0x00, 0x00, 0xFF, - /* 211, 0xD3 */ 0x00, 0x00, 0xCC, - /* 212, 0xD4 */ 0x00, 0x00, 0x99, - /* 213, 0xD5 */ 0x00, 0x00, 0x66, - /* 214, 0xD6 */ 0x00, 0x00, 0x33, - /* 215, 0xD7 */ 0xEE, 0x00, 0x00, - /* 216, 0xD8 */ 0xDD, 0x00, 0x00, - /* 217, 0xD9 */ 0xBB, 0x00, 0x00, - /* 218, 0xDA */ 0xAA, 0x00, 0x00, - /* 219, 0xDB */ 0x88, 0x00, 0x00, - /* 220, 0xDC */ 0x77, 0x00, 0x00, - /* 221, 0xDD */ 0x55, 0x00, 0x00, - /* 222, 0xDE */ 0x44, 0x00, 0x00, - /* 223, 0xDF */ 0x22, 0x00, 0x00, - /* 224, 0xE0 */ 0x11, 0x00, 0x00, - /* 225, 0xE1 */ 0x00, 0xEE, 0x00, - /* 226, 0xE2 */ 0x00, 0xDD, 0x00, - /* 227, 0xE3 */ 0x00, 0xBB, 0x00, - /* 228, 0xE4 */ 0x00, 0xAA, 0x00, - /* 229, 0xE5 */ 0x00, 0x88, 0x00, - /* 230, 0xE6 */ 0x00, 0x77, 0x00, - /* 231, 0xE7 */ 0x00, 0x55, 0x00, - /* 232, 0xE8 */ 0x00, 0x44, 0x00, - /* 233, 0xE9 */ 0x00, 0x22, 0x00, - /* 234, 0xEA */ 0x00, 0x11, 0x00, - /* 235, 0xEB */ 0x00, 0x00, 0xEE, - /* 236, 0xEC */ 0x00, 0x00, 0xDD, - /* 237, 0xED */ 0x00, 0x00, 0xBB, - /* 238, 0xEE */ 0x00, 0x00, 0xAA, - /* 239, 0xEF */ 0x00, 0x00, 0x88, - /* 240, 0xF0 */ 0x00, 0x00, 0x77, - /* 241, 0xF1 */ 0x00, 0x00, 0x55, - /* 242, 0xF2 */ 0x00, 0x00, 0x44, - /* 243, 0xF3 */ 0x00, 0x00, 0x22, - /* 244, 0xF4 */ 0x00, 0x00, 0x11, - /* 245, 0xF5 */ 0xEE, 0xEE, 0xEE, - /* 246, 0xF6 */ 0xDD, 0xDD, 0xDD, - /* 247, 0xF7 */ 0xBB, 0xBB, 0xBB, - /* 248, 0xF8 */ 0xAA, 0xAA, 0xAA, - /* 249, 0xF9 */ 0x88, 0x88, 0x88, - /* 250, 0xFA */ 0x77, 0x77, 0x77, - /* 251, 0xFB */ 0x55, 0x55, 0x55, - /* 252, 0xFC */ 0x44, 0x44, 0x44, - /* 253, 0xFD */ 0x22, 0x22, 0x22, - /* 254, 0xFE */ 0x11, 0x11, 0x11, - /* 255, 0xFF */ 0x00, 0x00, 0x00 -}; +#include "avio.h" /** * Retrieve the palette (or "color table" in QuickTime terms), either diff -Nru ffmpeg-4.2.2/libavformat/r3d.c ffmpeg-4.4/libavformat/r3d.c --- ffmpeg-4.2.2/libavformat/r3d.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/r3d.c 2021-04-08 21:28:40.000000000 +0000 @@ -27,7 +27,6 @@ typedef struct R3DContext { unsigned video_offsets_count; - unsigned *video_offsets; unsigned rdvo_offset; int audio_channels; @@ -57,6 +56,7 @@ R3DContext *r3d = s->priv_data; char filename[258]; int tmp; + int ret; int av_unused tmp2; AVRational framerate; @@ -98,7 +98,9 @@ r3d->audio_channels = avio_r8(s->pb); // audio channels av_log(s, AV_LOG_TRACE, "audio channels %d\n", tmp); - avio_read(s->pb, filename, 257); + ret = avio_read(s->pb, filename, 257); + if (ret < 257) + return ret < 0 ? ret : AVERROR_EOF; filename[sizeof(filename)-1] = 0; av_dict_set(&st->metadata, "filename", filename, 0); @@ -118,17 +120,14 @@ int i; r3d->video_offsets_count = (atom->size - 8) / 4; - r3d->video_offsets = av_malloc(atom->size); - if (!r3d->video_offsets) - return AVERROR(ENOMEM); for (i = 0; i < r3d->video_offsets_count; i++) { - r3d->video_offsets[i] = avio_rb32(s->pb); - if (!r3d->video_offsets[i]) { + unsigned video_offset = avio_rb32(s->pb); + if (!video_offset) { r3d->video_offsets_count = i; break; } - av_log(s, AV_LOG_TRACE, "video offset %d: %#x\n", i, r3d->video_offsets[i]); + av_log(s, AV_LOG_TRACE, "video offset %d: %#x\n", i, video_offset); } if (st->avg_frame_rate.num) @@ -326,7 +325,8 @@ pkt->stream_index = 1; pkt->dts = dts; - if (st->codecpar->sample_rate) + + if (st->codecpar->sample_rate && samples > 0) pkt->duration = av_rescale(samples, st->time_base.den, st->codecpar->sample_rate); av_log(s, AV_LOG_TRACE, "pkt dts %"PRId64" duration %"PRId64" samples %d sample rate %d\n", pkt->dts, pkt->duration, samples, st->codecpar->sample_rate); @@ -400,15 +400,6 @@ return 0; } -static int r3d_close(AVFormatContext *s) -{ - R3DContext *r3d = s->priv_data; - - av_freep(&r3d->video_offsets); - - return 0; -} - AVInputFormat ff_r3d_demuxer = { .name = "r3d", .long_name = NULL_IF_CONFIG_SMALL("REDCODE R3D"), @@ -416,6 +407,5 @@ .read_probe = r3d_probe, .read_header = r3d_read_header, .read_packet = r3d_read_packet, - .read_close = r3d_close, .read_seek = r3d_seek, }; diff -Nru ffmpeg-4.2.2/libavformat/rawdec.c ffmpeg-4.4/libavformat/rawdec.c --- ffmpeg-4.2.2/libavformat/rawdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rawdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -39,8 +39,8 @@ size = raw->raw_packet_size; - if (av_new_packet(pkt, size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, size)) < 0) + return ret; pkt->pos= avio_tell(s->pb); pkt->stream_index = 0; @@ -123,6 +123,8 @@ { "raw_packet_size", "", OFFSET(raw_packet_size), AV_OPT_TYPE_INT, {.i64 = RAW_PACKET_SIZE }, 1, INT_MAX, DEC}, { NULL }, }; +#undef OFFSET +#define OFFSET(x) offsetof(FFRawDemuxerContext, x) const AVOption ff_raw_options[] = { { "raw_packet_size", "", OFFSET(raw_packet_size), AV_OPT_TYPE_INT, {.i64 = RAW_PACKET_SIZE }, 1, INT_MAX, DEC}, { NULL }, @@ -206,6 +208,8 @@ return AVPROBE_SCORE_EXTENSION / 2; return AVPROBE_SCORE_EXTENSION / 4; } + if (!nb_invalid && nb_frames) + return AVPROBE_SCORE_EXTENSION / 4; return 0; } diff -Nru ffmpeg-4.2.2/libavformat/rawdec.h ffmpeg-4.4/libavformat/rawdec.h --- ffmpeg-4.2.2/libavformat/rawdec.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rawdec.h 2020-07-09 09:17:49.000000000 +0000 @@ -95,7 +95,7 @@ }; #define FF_DEF_RAWSUB_DEMUXER(shortname, longname, probe, ext, id, flag)\ -FF_RAWVIDEO_DEMUXER_CLASS(shortname)\ +FF_RAWSUB_DEMUXER_CLASS(shortname)\ AVInputFormat ff_ ## shortname ## _demuxer = {\ .name = #shortname,\ .long_name = NULL_IF_CONFIG_SMALL(longname),\ diff -Nru ffmpeg-4.2.2/libavformat/rawenc.c ffmpeg-4.4/libavformat/rawenc.c --- ffmpeg-4.2.2/libavformat/rawenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rawenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -64,7 +64,7 @@ .extensions = "ac3", .audio_codec = AV_CODEC_ID_AC3, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -96,7 +96,7 @@ .extensions = "adx", .audio_codec = AV_CODEC_ID_ADPCM_ADX, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .write_trailer = adx_write_trailer, .flags = AVFMT_NOTIMESTAMPS, @@ -110,7 +110,7 @@ .extensions = "aptx", .audio_codec = AV_CODEC_ID_APTX, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -123,7 +123,7 @@ .extensions = "aptxhd", .audio_codec = AV_CODEC_ID_APTX_HD, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -136,7 +136,7 @@ .extensions = "avs,avs2", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_AVS2, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -149,7 +149,7 @@ .extensions = "cavs", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_CAVS, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -161,7 +161,7 @@ .long_name = NULL_IF_CONFIG_SMALL("raw codec2 muxer"), .audio_codec = AV_CODEC_ID_CODEC2, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -172,7 +172,7 @@ AVOutputFormat ff_data_muxer = { .name = "data", .long_name = NULL_IF_CONFIG_SMALL("raw data"), - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -185,7 +185,7 @@ .extensions = "drc,vc2", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_DIRAC, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -198,7 +198,7 @@ .extensions = "dnxhd,dnxhr", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_DNXHD, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -212,7 +212,7 @@ .extensions = "dts", .audio_codec = AV_CODEC_ID_DTS, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -226,7 +226,7 @@ .extensions = "eac3", .audio_codec = AV_CODEC_ID_EAC3, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -240,7 +240,7 @@ .extensions = "g722", .audio_codec = AV_CODEC_ID_ADPCM_G722, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -254,7 +254,7 @@ .extensions = "tco,rco", .audio_codec = AV_CODEC_ID_G723_1, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -266,7 +266,7 @@ .long_name = NULL_IF_CONFIG_SMALL("raw big-endian G.726 (\"left-justified\")"), .audio_codec = AV_CODEC_ID_ADPCM_G726, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -278,7 +278,7 @@ .long_name = NULL_IF_CONFIG_SMALL("raw little-endian G.726 (\"right-justified\")"), .audio_codec = AV_CODEC_ID_ADPCM_G726LE, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -292,7 +292,7 @@ .extensions = "gsm", .audio_codec = AV_CODEC_ID_GSM, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -306,7 +306,7 @@ .extensions = "h261", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_H261, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -320,7 +320,7 @@ .extensions = "h263", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_H263, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -342,7 +342,7 @@ .extensions = "h264,264", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_H264, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .check_bitstream = h264_check_bitstream, .flags = AVFMT_NOTIMESTAMPS, @@ -365,7 +365,7 @@ .extensions = "hevc,h265,265", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_HEVC, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .check_bitstream = hevc_check_bitstream, .flags = AVFMT_NOTIMESTAMPS, @@ -379,7 +379,7 @@ .extensions = "m4v", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_MPEG4, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -393,7 +393,7 @@ .extensions = "mjpg,mjpeg", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_MJPEG, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -406,9 +406,9 @@ .mime_type = "image/jpeg", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_MJPEG, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, - .write_header = force_one_stream, }; #endif @@ -419,7 +419,7 @@ .extensions = "mlp", .audio_codec = AV_CODEC_ID_MLP, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -446,7 +446,7 @@ .extensions = "mpg,mpeg,m1v", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_MPEG1VIDEO, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -459,7 +459,7 @@ .extensions = "m2v", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_MPEG2VIDEO, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -484,7 +484,7 @@ .mime_type = "audio/x-sbc", .extensions = "sbc,msbc", .audio_codec = AV_CODEC_ID_SBC, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -497,7 +497,7 @@ .extensions = "thd", .audio_codec = AV_CODEC_ID_TRUEHD, .video_codec = AV_CODEC_ID_NONE, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; @@ -510,7 +510,7 @@ .extensions = "vc1", .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_VC1, - .write_header = force_one_stream, + .init = force_one_stream, .write_packet = ff_raw_write_packet, .flags = AVFMT_NOTIMESTAMPS, }; diff -Nru ffmpeg-4.2.2/libavformat/rdt.c ffmpeg-4.4/libavformat/rdt.c --- ffmpeg-4.2.2/libavformat/rdt.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rdt.c 2021-04-08 21:28:40.000000000 +0000 @@ -554,7 +554,7 @@ } #define RDT_HANDLER(n, s, t) \ -RTPDynamicProtocolHandler ff_rdt_ ## n ## _handler = { \ +const RTPDynamicProtocolHandler ff_rdt_ ## n ## _handler = { \ .enc_name = s, \ .codec_type = t, \ .codec_id = AV_CODEC_ID_NONE, \ diff -Nru ffmpeg-4.2.2/libavformat/realtextdec.c ffmpeg-4.4/libavformat/realtextdec.c --- ffmpeg-4.2.2/libavformat/realtextdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/realtextdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -45,16 +45,16 @@ return !av_strncasecmp(buf, "pb, pkt, size); if (ret != size) { - av_packet_unref(pkt); return AVERROR(EIO); } diff -Nru ffmpeg-4.2.2/libavformat/riff.c ffmpeg-4.4/libavformat/riff.c --- ffmpeg-4.2.2/libavformat/riff.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/riff.c 2021-04-08 21:28:40.000000000 +0000 @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" #include "libavutil/error.h" #include "libavcodec/avcodec.h" #include "avformat.h" @@ -403,6 +404,7 @@ { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'H', '0') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'H', '2') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'H', '4') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'Y', '0') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'Y', '2') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'R', 'A') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'R', 'G') }, @@ -453,6 +455,7 @@ { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'R', 'A') }, { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'R', 'G') }, { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'G', '0') }, + { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'Y', '0') }, { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'Y', '2') }, { AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'Y', '4') }, { AV_CODEC_ID_MAGICYUV, MKTAG('M', '2', 'R', 'A') }, @@ -488,11 +491,17 @@ { AV_CODEC_ID_AGM, MKTAG('A', 'G', 'M', '6') }, { AV_CODEC_ID_AGM, MKTAG('A', 'G', 'M', '7') }, { AV_CODEC_ID_LSCR, MKTAG('L', 'S', 'C', 'R') }, + { AV_CODEC_ID_IMM5, MKTAG('I', 'M', 'M', '5') }, + { AV_CODEC_ID_MVDV, MKTAG('M', 'V', 'D', 'V') }, + { AV_CODEC_ID_MVHA, MKTAG('M', 'V', 'H', 'A') }, + { AV_CODEC_ID_MV30, MKTAG('M', 'V', '3', '0') }, + { AV_CODEC_ID_NOTCHLC, MKTAG('n', 'l', 'c', '1') }, { AV_CODEC_ID_NONE, 0 } }; const AVCodecTag ff_codec_bmp_tags_unofficial[] = { { AV_CODEC_ID_HEVC, MKTAG('H', 'E', 'V', 'C') }, + { AV_CODEC_ID_HEVC, MKTAG('H', '2', '6', '5') }, { AV_CODEC_ID_NONE, 0 } }; @@ -513,7 +522,7 @@ { AV_CODEC_ID_ADPCM_IMA_OKI, 0x0010 }, { AV_CODEC_ID_ADPCM_IMA_WAV, 0x0011 }, /* must come after adpcm_ima_wav in this list */ - { AV_CODEC_ID_PCM_ZORK, 0x0011 }, + { AV_CODEC_ID_ADPCM_ZORK, 0x0011 }, { AV_CODEC_ID_ADPCM_IMA_OKI, 0x0017 }, { AV_CODEC_ID_ADPCM_YAMAHA, 0x0020 }, { AV_CODEC_ID_TRUESPEECH, 0x0022 }, @@ -539,6 +548,7 @@ { AV_CODEC_ID_AAC, 0x00ff }, { AV_CODEC_ID_G723_1, 0x0111 }, { AV_CODEC_ID_SIPR, 0x0130 }, + { AV_CODEC_ID_ACELP_KELVIN, 0x0135 }, { AV_CODEC_ID_WMAV1, 0x0160 }, { AV_CODEC_ID_WMAV2, 0x0161 }, { AV_CODEC_ID_WMAPRO, 0x0162 }, @@ -580,6 +590,16 @@ { AV_CODEC_ID_NONE, 0 }, }; +#if CONFIG_AVI_MUXER || CONFIG_WTV_MUXER +const AVCodecTag *const ff_riff_codec_tags_list[] = { + ff_codec_bmp_tags, ff_codec_wav_tags, NULL +}; +#endif + +#if CONFIG_WAV_DEMUXER || CONFIG_WAV_MUXER || CONFIG_W64_DEMUXER || CONFIG_W64_MUXER +const AVCodecTag *const ff_wav_codec_tags_list[] = { ff_codec_wav_tags, NULL }; +#endif + const AVMetadataConv ff_riff_info_conv[] = { { "IART", "artist" }, { "ICMT", "comment" }, diff -Nru ffmpeg-4.2.2/libavformat/riffdec.c ffmpeg-4.4/libavformat/riffdec.c --- ffmpeg-4.2.2/libavformat/riffdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/riffdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -145,7 +145,6 @@ size -= 22; } if (cbSize > 0) { - av_freep(&par->extradata); if (ff_get_extradata(s, par, pb, cbSize) < 0) return AVERROR(ENOMEM); size -= cbSize; @@ -158,7 +157,6 @@ int nb_streams, i; size -= 4; - av_freep(&par->extradata); if (ff_get_extradata(s, par, pb, size) < 0) return AVERROR(ENOMEM); nb_streams = AV_RL16(par->extradata + 4); @@ -204,7 +202,7 @@ id = ff_get_pcm_codec_id(bps, 1, 0, 0); if (id == AV_CODEC_ID_ADPCM_IMA_WAV && bps == 8) - id = AV_CODEC_ID_PCM_ZORK; + id = AV_CODEC_ID_ADPCM_ZORK; return id; } diff -Nru ffmpeg-4.2.2/libavformat/riffenc.c ffmpeg-4.4/libavformat/riffenc.c --- ffmpeg-4.2.2/libavformat/riffenc.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/riffenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -65,6 +65,12 @@ if (!par->codec_tag || par->codec_tag > 0xffff) return -1; + if (par->codec_id == AV_CODEC_ID_ADPCM_SWF && par->block_align == 0) { + av_log(s, AV_LOG_ERROR, "%s can only be written to WAVE with a constant frame size\n", + avcodec_get_name(par->codec_id)); + return AVERROR(EINVAL); + } + /* We use the known constant frame size for the codec if known, otherwise * fall back on using AVCodecContext.frame_size, which is not as reliable * for indicating packet duration. */ @@ -207,11 +213,12 @@ /* BITMAPINFOHEADER header */ void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par, - int for_asf, int ignore_extradata) + int for_asf, int ignore_extradata, int rgb_frame_is_flipped) { - int keep_height = par->extradata_size >= 9 && - !memcmp(par->extradata + par->extradata_size - 9, "BottomUp", 9); - int extradata_size = par->extradata_size - 9*keep_height; + int flipped_extradata = (par->extradata_size >= 9 && + !memcmp(par->extradata + par->extradata_size - 9, "BottomUp", 9)); + int keep_height = flipped_extradata || rgb_frame_is_flipped; + int extradata_size = par->extradata_size - 9*flipped_extradata; enum AVPixelFormat pix_fmt = par->format; int pal_avi; diff -Nru ffmpeg-4.2.2/libavformat/riff.h ffmpeg-4.4/libavformat/riff.h --- ffmpeg-4.2.2/libavformat/riff.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/riff.h 2021-04-08 21:28:40.000000000 +0000 @@ -46,7 +46,7 @@ */ int ff_get_bmp_header(AVIOContext *pb, AVStream *st, uint32_t *size); -void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par, int for_asf, int ignore_extradata); +void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par, int for_asf, int ignore_extradata, int rgb_frame_is_flipped); /** * Tell ff_put_wav_header() to use WAVEFORMATEX even for PCM codecs. @@ -72,6 +72,10 @@ extern const AVCodecTag ff_codec_bmp_tags[]; // exposed through avformat_get_riff_video_tags() extern const AVCodecTag ff_codec_wav_tags[]; +/* The following list contains both ff_codec_bmp_tags and ff_codec_wav_tags. */ +extern const AVCodecTag *const ff_riff_codec_tags_list[]; +/* The following list contains only ff_codec_wav_tags. */ +extern const AVCodecTag *const ff_wav_codec_tags_list[]; extern const AVCodecTag ff_codec_bmp_tags_unofficial[]; diff -Nru ffmpeg-4.2.2/libavformat/rl2.c ffmpeg-4.4/libavformat/rl2.c --- ffmpeg-4.2.2/libavformat/rl2.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rl2.c 2020-07-11 10:39:30.000000000 +0000 @@ -127,8 +127,9 @@ if(signature == RLV3_TAG && back_size > 0) st->codecpar->extradata_size += back_size; - if(ff_get_extradata(s, st->codecpar, pb, st->codecpar->extradata_size) < 0) - return AVERROR(ENOMEM); + ret = ff_get_extradata(s, st->codecpar, pb, st->codecpar->extradata_size); + if (ret < 0) + return ret; /** setup audio stream if present */ if(sound_rate){ @@ -171,18 +172,24 @@ /** read offset and size tables */ for(i=0; i < frame_count;i++) { - if (avio_feof(pb)) - return AVERROR_INVALIDDATA; + if (avio_feof(pb)) { + ret = AVERROR_INVALIDDATA; + goto end; + } chunk_size[i] = avio_rl32(pb); } for(i=0; i < frame_count;i++) { - if (avio_feof(pb)) - return AVERROR_INVALIDDATA; + if (avio_feof(pb)) { + ret = AVERROR_INVALIDDATA; + goto end; + } chunk_offset[i] = avio_rl32(pb); } for(i=0; i < frame_count;i++) { - if (avio_feof(pb)) - return AVERROR_INVALIDDATA; + if (avio_feof(pb)) { + ret = AVERROR_INVALIDDATA; + goto end; + } audio_size[i] = avio_rl32(pb) & 0xFFFF; } @@ -203,7 +210,7 @@ ++video_frame_counter; } - +end: av_free(chunk_size); av_free(audio_size); av_free(chunk_offset); @@ -249,7 +256,6 @@ /** fill the packet */ ret = av_get_packet(pb, pkt, sample->size); if(ret != sample->size){ - av_packet_unref(pkt); return AVERROR(EIO); } diff -Nru ffmpeg-4.2.2/libavformat/rmdec.c ffmpeg-4.4/libavformat/rmdec.c --- ffmpeg-4.2.2/libavformat/rmdec.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/rmdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -87,9 +87,7 @@ av_log(s, AV_LOG_ERROR, "extradata size %u too large\n", size); return -1; } - if (ff_get_extradata(s, par, pb, size) < 0) - return AVERROR(ENOMEM); - return 0; + return ff_get_extradata(s, par, pb, size); } static void rm_read_metadata(AVFormatContext *s, AVIOContext *pb, int wide) @@ -117,6 +115,9 @@ void ff_rm_free_rmstream (RMStream *rms) { + if (!rms) + return; + av_packet_unref(&rms->pkt); } @@ -164,7 +165,11 @@ avio_rb16(pb); /* version2 */ avio_rb32(pb); /* header size */ flavor= avio_rb16(pb); /* add codec info / flavor */ - ast->coded_framesize = coded_framesize = avio_rb32(pb); /* coded frame size */ + coded_framesize = avio_rb32(pb); /* coded frame size */ + if (coded_framesize < 0) + return AVERROR_INVALIDDATA; + ast->coded_framesize = coded_framesize; + avio_rb32(pb); /* ??? */ bytes_per_minute = avio_rb32(pb); if (version == 4) { @@ -218,7 +223,7 @@ if (version == 5) avio_r8(pb); codecdata_length = avio_rb32(pb); - if(codecdata_length + AV_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ + if((unsigned)codecdata_length > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE){ av_log(s, AV_LOG_ERROR, "codecdata_length too large\n"); return -1; } @@ -249,7 +254,7 @@ if (version == 5) avio_r8(pb); codecdata_length = avio_rb32(pb); - if(codecdata_length + AV_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ + if((unsigned)codecdata_length > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE){ av_log(s, AV_LOG_ERROR, "codecdata_length too large\n"); return -1; } @@ -291,7 +296,7 @@ ast->deint_id == DEINT_ID_GENR || ast->deint_id == DEINT_ID_SIPR) { if (st->codecpar->block_align <= 0 || - ast->audio_framesize * sub_packet_h > (unsigned)INT_MAX || + ast->audio_framesize * (uint64_t)sub_packet_h > (unsigned)INT_MAX || ast->audio_framesize * sub_packet_h < st->codecpar->block_align) return AVERROR_INVALIDDATA; if (av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h) < 0) @@ -453,6 +458,8 @@ } for (n = 0; n < n_pkts; n++) { + if (avio_feof(pb)) + return AVERROR_INVALIDDATA; avio_skip(pb, 2); pts = avio_rb32(pb); pos = avio_rb32(pb); @@ -540,7 +547,7 @@ unsigned int data_off = 0, indx_off = 0; char buf[128], mime[128]; int flags = 0; - int ret = -1; + int ret; unsigned size, v; int64_t codec_pos; @@ -556,6 +563,7 @@ avio_skip(pb, tag_size - 8); for(;;) { + ret = AVERROR_INVALIDDATA; if (avio_feof(pb)) goto fail; tag = avio_rl32(pb); @@ -606,8 +614,10 @@ get_str8(pb, mime, sizeof(mime)); /* mimetype */ st->codecpar->codec_type = AVMEDIA_TYPE_DATA; st->priv_data = ff_rm_alloc_rmstream(); - if (!st->priv_data) - return AVERROR(ENOMEM); + if (!st->priv_data) { + ret = AVERROR(ENOMEM); + goto fail; + } size = avio_rb32(pb); codec_pos = avio_tell(pb); @@ -621,8 +631,9 @@ avio_seek(pb, codec_pos + size, SEEK_SET); } else { avio_skip(pb, -4); - if (ff_rm_read_mdpr_codecdata(s, s->pb, st, st->priv_data, - size, mime) < 0) + ret = ff_rm_read_mdpr_codecdata(s, s->pb, st, st->priv_data, + size, mime); + if (ret < 0) goto fail; } @@ -696,21 +707,23 @@ state= (state<<8) + avio_r8(pb); if(state == MKBETAG('I', 'N', 'D', 'X')){ - int n_pkts, expected_len; + int n_pkts; + int64_t expected_len; len = avio_rb32(pb); avio_skip(pb, 2); n_pkts = avio_rb32(pb); - expected_len = 20 + n_pkts * 14; - if (len == 20) + expected_len = 20 + n_pkts * 14LL; + + if (len == 20 && expected_len <= INT_MAX) /* some files don't add index entries to chunk size... */ len = expected_len; else if (len != expected_len) av_log(s, AV_LOG_WARNING, - "Index size %d (%d pkts) is wrong, should be %d.\n", + "Index size %d (%d pkts) is wrong, should be %"PRId64".\n", len, n_pkts, expected_len); - len -= 14; // we already read part of the index header - if(len<0) + if(len < 14) continue; + len -= 14; // we already read part of the index header goto skip; } else if (state == MKBETAG('D','A','T','A')) { av_log(s, AV_LOG_WARNING, @@ -724,8 +737,8 @@ num = avio_rb16(pb); *timestamp = avio_rb32(pb); - mlti_id = (avio_r8(pb)>>1)-1<<16; - mlti_id = FFMAX(mlti_id, 0); + mlti_id = (avio_r8(pb) >> 1) - 1; + mlti_id = FFMAX(mlti_id, 0) << 16; *flags = avio_r8(pb); /* flags */ } for(i=0;inb_streams;i++) { @@ -783,8 +796,8 @@ return -1; } rm->remaining_len -= len; - if(av_new_packet(pkt, len + 9) < 0) - return AVERROR(EIO); + if ((ret = av_new_packet(pkt, len + 9)) < 0) + return ret; pkt->data[0] = 0; AV_WL32(pkt->data + 1, 1); AV_WL32(pkt->data + 5, 0); @@ -806,9 +819,8 @@ vst->slices = ((hdr & 0x3F) << 1) + 1; vst->videobufsize = len2 + 8*vst->slices + 1; av_packet_unref(&vst->pkt); //FIXME this should be output. - if(av_new_packet(&vst->pkt, vst->videobufsize) < 0) - return AVERROR(ENOMEM); - memset(vst->pkt.data, 0, vst->pkt.size); + if ((ret = av_new_packet(&vst->pkt, vst->videobufsize)) < 0) + return ret; vst->videobufpos = 8*vst->slices + 1; vst->cur_slice = 0; vst->curpic_num = pic_num; @@ -836,14 +848,11 @@ if (type == 2 || vst->videobufpos == vst->videobufsize) { vst->pkt.data[0] = vst->cur_slice-1; - *pkt= vst->pkt; - vst->pkt.data= NULL; - vst->pkt.size= 0; - vst->pkt.buf = NULL; + av_packet_move_ref(pkt, &vst->pkt); if(vst->slices != vst->cur_slice) //FIXME find out how to set slices correct from the begin memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices, vst->videobufpos - 1 - 8*vst->slices); - pkt->size = vst->videobufpos + 8*(vst->cur_slice - vst->slices); + av_shrink_packet(pkt, vst->videobufpos + 8*(vst->cur_slice - vst->slices)); pkt->pts = AV_NOPTS_VALUE; pkt->pos = vst->pktpos; vst->slices = 0; @@ -1242,20 +1251,19 @@ } for (n = 0; n < nb_streams; n++) { - st = avformat_new_stream(s, NULL); - if (!st) - return AVERROR(ENOMEM); - st->priv_data = ff_rm_alloc_rmstream(); - if (!st->priv_data) - return AVERROR(ENOMEM); + if (!(st = avformat_new_stream(s, NULL)) || + !(st->priv_data = ff_rm_alloc_rmstream())) { + ret = AVERROR(ENOMEM); + goto fail; + } if (avio_r8(pb) != 1) - return AVERROR_INVALIDDATA; + goto invalid_data; count = avio_rb32(pb); for (i = 0; i < count; i++) { if (avio_feof(pb)) - return AVERROR_INVALIDDATA; + goto invalid_data; type = avio_r8(pb); tlen = avio_rb32(pb); @@ -1267,24 +1275,27 @@ } else if (type == 4 && !strncmp(key, "OpaqueData", tlen)) { ret = ffio_ensure_seekback(pb, 4); if (ret < 0) - return ret; + goto fail; if (avio_rb32(pb) == MKBETAG('M', 'L', 'T', 'I')) { ret = rm_read_multi(s, pb, st, NULL); } else { if (avio_feof(pb)) - return AVERROR_INVALIDDATA; + goto invalid_data; avio_seek(pb, -4, SEEK_CUR); ret = ff_rm_read_mdpr_codecdata(s, pb, st, st->priv_data, len, NULL); } if (ret < 0) - return ret; + goto fail; } else if (type == 4) { int j; av_log(s, AV_LOG_DEBUG, "%s = '0x", key); - for (j = 0; j < len; j++) + for (j = 0; j < len; j++) { + if (avio_feof(pb)) + goto invalid_data; av_log(s, AV_LOG_DEBUG, "%X", avio_r8(pb)); + } av_log(s, AV_LOG_DEBUG, "'\n"); } else if (len == 4 && type == 3 && !strncmp(key, "Duration", tlen)) { st->duration = avio_rb32(pb); @@ -1299,14 +1310,19 @@ } if (avio_r8(pb) != 6) - return AVERROR_INVALIDDATA; + goto invalid_data; avio_skip(pb, 12); - avio_skip(pb, avio_rb64(pb) + pos - avio_tell(s->pb)); + avio_seek(pb, avio_rb64(pb) + pos, SEEK_SET); if (avio_r8(pb) != 8) - return AVERROR_INVALIDDATA; + goto invalid_data; avio_skip(pb, 8); return 0; +invalid_data: + ret = AVERROR_INVALIDDATA; +fail: + rm_read_close(s); + return ret; } static int ivr_read_packet(AVFormatContext *s, AVPacket *pkt) diff -Nru ffmpeg-4.2.2/libavformat/rmenc.c ffmpeg-4.4/libavformat/rmenc.c --- ffmpeg-4.2.2/libavformat/rmenc.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/rmenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -360,7 +360,6 @@ if (rv10_write_header(s, 0, 0)) return AVERROR_INVALIDDATA; - avio_flush(s->pb); return 0; } diff -Nru ffmpeg-4.2.2/libavformat/rpl.c ffmpeg-4.4/libavformat/rpl.c --- ffmpeg-4.2.2/libavformat/rpl.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rpl.c 2021-02-20 20:27:47.000000000 +0000 @@ -253,6 +253,9 @@ error |= read_line(pb, line, sizeof(line)); } + if (s->nb_streams == 0) + return AVERROR_INVALIDDATA; + rpl->frames_per_chunk = read_line_and_int(pb, &error); // video frames per chunk if (vst && rpl->frames_per_chunk > 1 && vst->codecpar->codec_tag != 124) av_log(s, AV_LOG_WARNING, @@ -338,7 +341,6 @@ if (ret < 0) return ret; if (ret != frame_size) { - av_packet_unref(pkt); return AVERROR(EIO); } pkt->duration = 1; @@ -355,7 +357,6 @@ if (ret < 0) return ret; if (ret != index_entry->size) { - av_packet_unref(pkt); return AVERROR(EIO); } diff -Nru ffmpeg-4.2.2/libavformat/rsd.c ffmpeg-4.4/libavformat/rsd.c --- ffmpeg-4.2.2/libavformat/rsd.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rsd.c 2021-02-20 20:27:47.000000000 +0000 @@ -97,20 +97,15 @@ switch (par->codec_id) { case AV_CODEC_ID_XMA2: par->block_align = 2048; - ff_alloc_extradata(par, 34); - if (!par->extradata) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(par, 34)) < 0) + return ret; memset(par->extradata, 0, 34); break; case AV_CODEC_ID_ADPCM_PSX: par->block_align = 16 * par->channels; - if (pb->seekable & AVIO_SEEKABLE_NORMAL) - st->duration = av_get_audio_frame_duration2(par, avio_size(pb) - start); break; case AV_CODEC_ID_ADPCM_IMA_RAD: par->block_align = 20 * par->channels; - if (pb->seekable & AVIO_SEEKABLE_NORMAL) - st->duration = av_get_audio_frame_duration2(par, avio_size(pb) - start); break; case AV_CODEC_ID_ADPCM_IMA_WAV: if (version == 2) @@ -118,8 +113,6 @@ par->bits_per_coded_sample = 4; par->block_align = 36 * par->channels; - if (pb->seekable & AVIO_SEEKABLE_NORMAL) - st->duration = av_get_audio_frame_duration2(par, avio_size(pb) - start); break; case AV_CODEC_ID_ADPCM_THP_LE: /* RSD3GADP is mono, so only alloc enough memory @@ -129,8 +122,6 @@ if ((ret = ff_get_extradata(s, par, s->pb, 32)) < 0) return ret; - if (pb->seekable & AVIO_SEEKABLE_NORMAL) - st->duration = av_get_audio_frame_duration2(par, avio_size(pb) - start); break; case AV_CODEC_ID_ADPCM_THP: par->block_align = 8 * par->channels; @@ -140,21 +131,41 @@ return ret; for (i = 0; i < par->channels; i++) { + if (avio_feof(pb)) + return AVERROR_EOF; avio_read(s->pb, st->codecpar->extradata + 32 * i, 32); avio_skip(s->pb, 8); } - if (pb->seekable & AVIO_SEEKABLE_NORMAL) - st->duration = (avio_size(pb) - start) / (8 * par->channels) * 14; break; case AV_CODEC_ID_PCM_S16LE: case AV_CODEC_ID_PCM_S16BE: if (version != 4) start = avio_rl32(pb); - if (pb->seekable & AVIO_SEEKABLE_NORMAL) - st->duration = (avio_size(pb) - start) / 2 / par->channels; break; } + if (start < 0) + return AVERROR_INVALIDDATA; + + if (pb->seekable & AVIO_SEEKABLE_NORMAL) { + int64_t remaining = avio_size(pb); + + if (remaining >= start && remaining - start <= INT_MAX) + switch (par->codec_id) { + case AV_CODEC_ID_ADPCM_PSX: + case AV_CODEC_ID_ADPCM_IMA_RAD: + case AV_CODEC_ID_ADPCM_IMA_WAV: + case AV_CODEC_ID_ADPCM_THP_LE: + st->duration = av_get_audio_frame_duration2(par, remaining - start); + break; + case AV_CODEC_ID_ADPCM_THP: + st->duration = (remaining - start) / (8 * par->channels) * 14; + break; + case AV_CODEC_ID_PCM_S16LE: + case AV_CODEC_ID_PCM_S16BE: + st->duration = (remaining - start) / 2 / par->channels; + } + } avio_skip(pb, start - avio_tell(pb)); if (par->codec_id == AV_CODEC_ID_XMA2) { diff -Nru ffmpeg-4.2.2/libavformat/rso.c ffmpeg-4.4/libavformat/rso.c --- ffmpeg-4.2.2/libavformat/rso.c 2016-03-29 02:25:29.000000000 +0000 +++ ffmpeg-4.4/libavformat/rso.c 2021-04-08 21:28:40.000000000 +0000 @@ -28,3 +28,5 @@ { AV_CODEC_ID_ADPCM_IMA_WAV, 0x0101 }, { AV_CODEC_ID_NONE, 0 }, }; + +const AVCodecTag *const ff_rso_codec_tags_list[] = { ff_codec_rso_tags, NULL }; diff -Nru ffmpeg-4.2.2/libavformat/rsodec.c ffmpeg-4.4/libavformat/rsodec.c --- ffmpeg-4.2.2/libavformat/rsodec.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/rsodec.c 2021-04-08 21:28:40.000000000 +0000 @@ -79,5 +79,5 @@ .read_header = rso_read_header, .read_packet = ff_pcm_read_packet, .read_seek = ff_pcm_read_seek, - .codec_tag = (const AVCodecTag* const []){ff_codec_rso_tags, 0}, + .codec_tag = ff_rso_codec_tags_list, }; diff -Nru ffmpeg-4.2.2/libavformat/rsoenc.c ffmpeg-4.4/libavformat/rsoenc.c --- ffmpeg-4.2.2/libavformat/rsoenc.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/rsoenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -22,6 +22,7 @@ #include "avformat.h" #include "internal.h" +#include "rawenc.h" #include "riff.h" #include "rso.h" @@ -60,14 +61,6 @@ avio_wb16(pb, par->sample_rate); avio_wb16(pb, 0x0000); /* play mode ? (0x0000 = don't loop) */ - avio_flush(pb); - - return 0; -} - -static int rso_write_packet(AVFormatContext *s, AVPacket *pkt) -{ - avio_write(s->pb, pkt->data, pkt->size); return 0; } @@ -105,8 +98,8 @@ .audio_codec = AV_CODEC_ID_PCM_U8, .video_codec = AV_CODEC_ID_NONE, .write_header = rso_write_header, - .write_packet = rso_write_packet, + .write_packet = ff_raw_write_packet, .write_trailer = rso_write_trailer, - .codec_tag = (const AVCodecTag* const []){ff_codec_rso_tags, 0}, + .codec_tag = ff_rso_codec_tags_list, .flags = AVFMT_NOTIMESTAMPS, }; diff -Nru ffmpeg-4.2.2/libavformat/rso.h ffmpeg-4.4/libavformat/rso.h --- ffmpeg-4.2.2/libavformat/rso.h 2016-03-29 02:25:29.000000000 +0000 +++ ffmpeg-4.4/libavformat/rso.h 2021-04-08 21:28:40.000000000 +0000 @@ -28,5 +28,6 @@ /* The libavcodec codecs we support, and the IDs they have in the file */ extern const AVCodecTag ff_codec_rso_tags[]; +extern const AVCodecTag *const ff_rso_codec_tags_list[]; #endif /* AVFORMAT_RSO_H */ diff -Nru ffmpeg-4.2.2/libavformat/rtmpcrypt.c ffmpeg-4.4/libavformat/rtmpcrypt.c --- ffmpeg-4.2.2/libavformat/rtmpcrypt.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtmpcrypt.c 2020-07-11 10:39:30.000000000 +0000 @@ -240,7 +240,7 @@ RTMPEContext *rt = h->priv_data; ff_dh_free(rt->dh); - ffurl_close(rt->stream); + ffurl_closep(&rt->stream); return 0; } diff -Nru ffmpeg-4.2.2/libavformat/rtmphttp.c ffmpeg-4.4/libavformat/rtmphttp.c --- ffmpeg-4.2.2/libavformat/rtmphttp.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtmphttp.c 2020-07-11 10:39:30.000000000 +0000 @@ -176,7 +176,7 @@ } av_freep(&rt->out_data); - ffurl_close(rt->stream); + ffurl_closep(&rt->stream); return ret; } diff -Nru ffmpeg-4.2.2/libavformat/rtmppkt.c ffmpeg-4.4/libavformat/rtmppkt.c --- ffmpeg-4.2.2/libavformat/rtmppkt.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtmppkt.c 2021-04-08 21:28:40.000000000 +0000 @@ -84,14 +84,6 @@ bytestream_put_be24(dst, AMF_DATA_TYPE_OBJECT_END); } -int ff_amf_read_bool(GetByteContext *bc, int *val) -{ - if (bytestream2_get_byte(bc) != AMF_DATA_TYPE_BOOL) - return AVERROR_INVALIDDATA; - *val = bytestream2_get_byte(bc); - return 0; -} - int ff_amf_read_number(GetByteContext *bc, double *val) { uint64_t read; @@ -569,6 +561,7 @@ return amf_get_field_value2(&gb, name, dst, dst_size); } +#ifdef DEBUG static const char* rtmp_packet_type(int type) { switch (type) { @@ -685,6 +678,7 @@ av_log(ctx, AV_LOG_DEBUG, "\n"); } } +#endif int ff_amf_match_string(const uint8_t *data, int size, const char *str) { diff -Nru ffmpeg-4.2.2/libavformat/rtmppkt.h ffmpeg-4.4/libavformat/rtmppkt.h --- ffmpeg-4.2.2/libavformat/rtmppkt.h 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtmppkt.h 2021-04-08 21:28:40.000000000 +0000 @@ -260,15 +260,6 @@ void ff_amf_write_object_end(uint8_t **dst); /** - * Read AMF boolean value. - * - *@param[in,out] gbc GetByteContext initialized with AMF-formatted data - *@param[out] val 0 or 1 - *@return 0 on success or an AVERROR code on failure -*/ -int ff_amf_read_bool(GetByteContext *gbc, int *val); - -/** * Read AMF number value. * *@param[in,out] gbc GetByteContext initialized with AMF-formatted data diff -Nru ffmpeg-4.2.2/libavformat/rtmpproto.c ffmpeg-4.4/libavformat/rtmpproto.c --- ffmpeg-4.2.2/libavformat/rtmpproto.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtmpproto.c 2021-04-08 21:28:40.000000000 +0000 @@ -48,7 +48,6 @@ #endif #define APP_MAX_LENGTH 1024 -#define PLAYPATH_MAX_LENGTH 512 #define TCURL_MAX_LENGTH 1024 #define FLASHVER_MAX_LENGTH 64 #define RTMP_PKTDATA_DEFAULT_SIZE 4096 @@ -164,7 +163,7 @@ if (rt->nb_tracked_methods + 1 > rt->tracked_methods_size) { rt->tracked_methods_size = (rt->nb_tracked_methods + 1) * 2; - if ((err = av_reallocp(&rt->tracked_methods, rt->tracked_methods_size * + if ((err = av_reallocp_array(&rt->tracked_methods, rt->tracked_methods_size, sizeof(*rt->tracked_methods))) < 0) { rt->nb_tracked_methods = 0; rt->tracked_methods_size = 0; @@ -1112,7 +1111,7 @@ RTMPContext *rt = s->priv_data; uint8_t *in_data = NULL, *out_data = NULL, *swfdata; int64_t in_size; - URLContext *stream; + URLContext *stream = NULL; char swfhash[32]; int swfsize; int ret = 0; @@ -2386,7 +2385,7 @@ next += size + 3 + 4; } if (p != rt->flv_data + rt->flv_size) { - av_log(NULL, AV_LOG_WARNING, "Incomplete flv packets in " + av_log(rt, AV_LOG_WARNING, "Incomplete flv packets in " "RTMP_PT_METADATA packet\n"); rt->flv_size = p - rt->flv_data; } @@ -2512,7 +2511,7 @@ free_tracked_methods(rt); av_freep(&rt->flv_data); - ffurl_close(rt->stream); + ffurl_closep(&rt->stream); return ret; } @@ -2746,7 +2745,10 @@ } if (!rt->playpath) { - rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH); + int max_len = 1; + if (fname) + max_len = strlen(fname) + 5; // add prefix "mp4:" + rt->playpath = av_malloc(max_len); if (!rt->playpath) { ret = AVERROR(ENOMEM); goto fail; @@ -2763,7 +2765,7 @@ fname[len - 4] = '\0'; rt->playpath[0] = 0; } - av_strlcat(rt->playpath, fname, PLAYPATH_MAX_LENGTH); + av_strlcat(rt->playpath, fname, max_len); } else { rt->playpath[0] = '\0'; } @@ -2822,8 +2824,7 @@ if (rt->do_reconnect) { int i; - ffurl_close(rt->stream); - rt->stream = NULL; + ffurl_closep(&rt->stream); rt->do_reconnect = 0; rt->nb_invokes = 0; for (i = 0; i < 2; i++) @@ -2880,6 +2881,9 @@ return 0; fail: + av_freep(&rt->playpath); + av_freep(&rt->tcurl); + av_freep(&rt->flashver); av_dict_free(opts); rtmp_close(s); return ret; @@ -3115,7 +3119,8 @@ { NULL }, }; -#define RTMP_PROTOCOL(flavor) \ +#define RTMP_PROTOCOL_0(flavor) +#define RTMP_PROTOCOL_1(flavor) \ static const AVClass flavor##_class = { \ .class_name = #flavor, \ .item_name = av_default_item_name, \ @@ -3135,11 +3140,16 @@ .flags = URL_PROTOCOL_FLAG_NETWORK, \ .priv_data_class= &flavor##_class, \ }; - - -RTMP_PROTOCOL(rtmp) -RTMP_PROTOCOL(rtmpe) -RTMP_PROTOCOL(rtmps) -RTMP_PROTOCOL(rtmpt) -RTMP_PROTOCOL(rtmpte) -RTMP_PROTOCOL(rtmpts) +#define RTMP_PROTOCOL_2(flavor, enabled) \ + RTMP_PROTOCOL_ ## enabled(flavor) +#define RTMP_PROTOCOL_3(flavor, config) \ + RTMP_PROTOCOL_2(flavor, config) +#define RTMP_PROTOCOL(flavor, uppercase) \ + RTMP_PROTOCOL_3(flavor, CONFIG_ ## uppercase ## _PROTOCOL) + +RTMP_PROTOCOL(rtmp, RTMP) +RTMP_PROTOCOL(rtmpe, RTMPE) +RTMP_PROTOCOL(rtmps, RTMPS) +RTMP_PROTOCOL(rtmpt, RTMPT) +RTMP_PROTOCOL(rtmpte, RTMPTE) +RTMP_PROTOCOL(rtmpts, RTMPTS) diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_ac3.c ffmpeg-4.4/libavformat/rtpdec_ac3.c --- ffmpeg-4.2.2/libavformat/rtpdec_ac3.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_ac3.c 2020-07-11 10:39:30.000000000 +0000 @@ -62,9 +62,9 @@ av_log(ctx, AV_LOG_ERROR, "Invalid AC3 packet data\n"); return AVERROR_INVALIDDATA; } - if (av_new_packet(pkt, len)) { + if ((err = av_new_packet(pkt, len)) < 0) { av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); - return AVERROR(ENOMEM); + return err; } pkt->stream_index = st->index; diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_amr.c ffmpeg-4.4/libavformat/rtpdec_amr.c --- ffmpeg-4.2.2/libavformat/rtpdec_amr.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_amr.c 2020-07-11 10:39:30.000000000 +0000 @@ -51,7 +51,7 @@ { const uint8_t *frame_sizes = NULL; int frames; - int i; + int i, ret; const uint8_t *speech_data; uint8_t *ptr; @@ -93,9 +93,9 @@ speech_data = buf + 1 + frames; /* Everything except the codec mode request byte should be output. */ - if (av_new_packet(pkt, len - 1)) { + if ((ret = av_new_packet(pkt, len - 1)) < 0) { av_log(ctx, AV_LOG_ERROR, "Out of memory\n"); - return AVERROR(ENOMEM); + return ret; } pkt->stream_index = st->index; ptr = pkt->data; diff -Nru ffmpeg-4.2.2/libavformat/rtpdec.c ffmpeg-4.4/libavformat/rtpdec.c --- ffmpeg-4.2.2/libavformat/rtpdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,57 +24,60 @@ #include "libavutil/intreadwrite.h" #include "libavutil/time.h" +#include "libavcodec/bytestream.h" + #include "avformat.h" #include "network.h" #include "srtp.h" #include "url.h" #include "rtpdec.h" #include "rtpdec_formats.h" +#include "internal.h" #define MIN_FEEDBACK_INTERVAL 200000 /* 200 ms in us */ -static RTPDynamicProtocolHandler l24_dynamic_handler = { +static const RTPDynamicProtocolHandler l24_dynamic_handler = { .enc_name = "L24", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_PCM_S24BE, }; -static RTPDynamicProtocolHandler gsm_dynamic_handler = { +static const RTPDynamicProtocolHandler gsm_dynamic_handler = { .enc_name = "GSM", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_GSM, }; -static RTPDynamicProtocolHandler realmedia_mp3_dynamic_handler = { +static const RTPDynamicProtocolHandler realmedia_mp3_dynamic_handler = { .enc_name = "X-MP3-draft-00", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_MP3ADU, }; -static RTPDynamicProtocolHandler speex_dynamic_handler = { +static const RTPDynamicProtocolHandler speex_dynamic_handler = { .enc_name = "speex", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_SPEEX, }; -static RTPDynamicProtocolHandler opus_dynamic_handler = { +static const RTPDynamicProtocolHandler opus_dynamic_handler = { .enc_name = "opus", .codec_type = AVMEDIA_TYPE_AUDIO, .codec_id = AV_CODEC_ID_OPUS, }; -static RTPDynamicProtocolHandler t140_dynamic_handler = { /* RFC 4103 */ +static const RTPDynamicProtocolHandler t140_dynamic_handler = { /* RFC 4103 */ .enc_name = "t140", .codec_type = AVMEDIA_TYPE_SUBTITLE, .codec_id = AV_CODEC_ID_TEXT, }; -extern RTPDynamicProtocolHandler ff_rdt_video_handler; -extern RTPDynamicProtocolHandler ff_rdt_audio_handler; -extern RTPDynamicProtocolHandler ff_rdt_live_video_handler; -extern RTPDynamicProtocolHandler ff_rdt_live_audio_handler; +extern const RTPDynamicProtocolHandler ff_rdt_video_handler; +extern const RTPDynamicProtocolHandler ff_rdt_audio_handler; +extern const RTPDynamicProtocolHandler ff_rdt_live_video_handler; +extern const RTPDynamicProtocolHandler ff_rdt_live_audio_handler; -static const RTPDynamicProtocolHandler *rtp_dynamic_protocol_handler_list[] = { +static const RTPDynamicProtocolHandler *const rtp_dynamic_protocol_handler_list[] = { /* rtp */ &ff_ac3_dynamic_handler, &ff_amr_nb_dynamic_handler, @@ -401,40 +404,26 @@ void ff_rtp_send_punch_packets(URLContext *rtp_handle) { - AVIOContext *pb; - uint8_t *buf; - int len; + uint8_t buf[RTP_MIN_PACKET_LENGTH], *ptr = buf; /* Send a small RTP packet */ - if (avio_open_dyn_buf(&pb) < 0) - return; - avio_w8(pb, (RTP_VERSION << 6)); - avio_w8(pb, 0); /* Payload type */ - avio_wb16(pb, 0); /* Seq */ - avio_wb32(pb, 0); /* Timestamp */ - avio_wb32(pb, 0); /* SSRC */ + bytestream_put_byte(&ptr, (RTP_VERSION << 6)); + bytestream_put_byte(&ptr, 0); /* Payload type */ + bytestream_put_be16(&ptr, 0); /* Seq */ + bytestream_put_be32(&ptr, 0); /* Timestamp */ + bytestream_put_be32(&ptr, 0); /* SSRC */ - avio_flush(pb); - len = avio_close_dyn_buf(pb, &buf); - if ((len > 0) && buf) - ffurl_write(rtp_handle, buf, len); - av_free(buf); + ffurl_write(rtp_handle, buf, ptr - buf); /* Send a minimal RTCP RR */ - if (avio_open_dyn_buf(&pb) < 0) - return; - - avio_w8(pb, (RTP_VERSION << 6)); - avio_w8(pb, RTCP_RR); /* receiver report */ - avio_wb16(pb, 1); /* length in words - 1 */ - avio_wb32(pb, 0); /* our own SSRC */ + ptr = buf; + bytestream_put_byte(&ptr, (RTP_VERSION << 6)); + bytestream_put_byte(&ptr, RTCP_RR); /* receiver report */ + bytestream_put_be16(&ptr, 1); /* length in words - 1 */ + bytestream_put_be32(&ptr, 0); /* our own SSRC */ - avio_flush(pb); - len = avio_close_dyn_buf(pb, &buf); - if ((len > 0) && buf) - ffurl_write(rtp_handle, buf, len); - av_free(buf); + ffurl_write(rtp_handle, buf, ptr - buf); } static int find_missing_packets(RTPDemuxContext *s, uint16_t *first_missing, @@ -531,6 +520,43 @@ return 0; } +static int opus_write_extradata(AVCodecParameters *codecpar) +{ + uint8_t *bs; + int ret; + + /* This function writes an extradata with a channel mapping family of 0. + * This mapping family only supports mono and stereo layouts. And RFC7587 + * specifies that the number of channels in the SDP must be 2. + */ + if (codecpar->channels > 2) { + return AVERROR_INVALIDDATA; + } + + ret = ff_alloc_extradata(codecpar, 19); + if (ret < 0) + return ret; + + bs = (uint8_t *)codecpar->extradata; + + /* Opus magic */ + bytestream_put_buffer(&bs, "OpusHead", 8); + /* Version */ + bytestream_put_byte (&bs, 0x1); + /* Channel count */ + bytestream_put_byte (&bs, codecpar->channels); + /* Pre skip */ + bytestream_put_le16 (&bs, 0); + /* Input sample rate */ + bytestream_put_le32 (&bs, 48000); + /* Output gain */ + bytestream_put_le16 (&bs, 0x0); + /* Mapping family */ + bytestream_put_byte (&bs, 0x0); + + return 0; +} + /** * open a new RTP parse context for stream 'st'. 'st' can be NULL for * MPEG-2 TS streams. @@ -539,6 +565,7 @@ int payload_type, int queue_size) { RTPDemuxContext *s; + int ret; s = av_mallocz(sizeof(RTPDemuxContext)); if (!s) @@ -562,6 +589,16 @@ if (st->codecpar->sample_rate == 8000) st->codecpar->sample_rate = 16000; break; + case AV_CODEC_ID_OPUS: + ret = opus_write_extradata(st->codecpar); + if (ret < 0) { + av_log(s1, AV_LOG_ERROR, + "Error creating opus extradata: %s\n", + av_err2str(ret)); + av_free(s); + return NULL; + } + break; default: break; } @@ -927,7 +964,7 @@ int ff_rtp_finalize_packet(AVPacket *pkt, AVIOContext **dyn_buf, int stream_idx) { int ret; - av_init_packet(pkt); + av_packet_unref(pkt); pkt->size = avio_close_dyn_buf(*dyn_buf, &pkt->data); pkt->stream_index = stream_idx; diff -Nru ffmpeg-4.2.2/libavformat/rtpdec.h ffmpeg-4.4/libavformat/rtpdec.h --- ffmpeg-4.2.2/libavformat/rtpdec.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec.h 2021-04-08 21:28:40.000000000 +0000 @@ -134,8 +134,6 @@ /** Parse handler for this dynamic packet */ DynamicPayloadPacketHandlerProc parse_packet; int (*need_keyframe)(PayloadContext *context); - - struct RTPDynamicProtocolHandler *next; }; typedef struct RTPPacket { diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_h263.c ffmpeg-4.4/libavformat/rtpdec_h263.c --- ffmpeg-4.2.2/libavformat/rtpdec_h263.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_h263.c 2020-07-11 10:39:30.000000000 +0000 @@ -30,7 +30,7 @@ { uint8_t *ptr; uint16_t header; - int startcode, vrc, picture_header; + int startcode, vrc, picture_header, ret; if (len < 2) { av_log(ctx, AV_LOG_ERROR, "Too short H.263 RTP packet\n"); @@ -73,9 +73,9 @@ return AVERROR_INVALIDDATA; } - if (av_new_packet(pkt, len + startcode)) { + if ((ret = av_new_packet(pkt, len + startcode)) < 0) { av_log(ctx, AV_LOG_ERROR, "Out of memory\n"); - return AVERROR(ENOMEM); + return ret; } pkt->stream_index = st->index; ptr = pkt->data; diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_hevc.c ffmpeg-4.4/libavformat/rtpdec_hevc.c --- ffmpeg-4.2.2/libavformat/rtpdec_hevc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_hevc.c 2020-07-11 10:39:30.000000000 +0000 @@ -25,6 +25,7 @@ #include "libavcodec/get_bits.h" #include "avformat.h" +#include "internal.h" #include "rtpdec.h" #include "rtpdec_formats.h" @@ -147,15 +148,9 @@ hevc_sdp_parse_fmtp_config); if (hevc_data->vps_size || hevc_data->sps_size || hevc_data->pps_size || hevc_data->sei_size) { - av_freep(&par->extradata); par->extradata_size = hevc_data->vps_size + hevc_data->sps_size + hevc_data->pps_size + hevc_data->sei_size; - par->extradata = av_malloc(par->extradata_size + - AV_INPUT_BUFFER_PADDING_SIZE); - if (!par->extradata) { - ret = AVERROR(ENOMEM); - par->extradata_size = 0; - } else { + if ((ret = ff_alloc_extradata(par, par->extradata_size)) >= 0) { int pos = 0; memcpy(par->extradata + pos, hevc_data->vps, hevc_data->vps_size); pos += hevc_data->vps_size; @@ -164,8 +159,6 @@ memcpy(par->extradata + pos, hevc_data->pps, hevc_data->pps_size); pos += hevc_data->pps_size; memcpy(par->extradata + pos, hevc_data->sei, hevc_data->sei_size); - pos += hevc_data->sei_size; - memset(par->extradata + pos, 0, AV_INPUT_BUFFER_PADDING_SIZE); } av_freep(&hevc_data->vps); diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_jpeg.c ffmpeg-4.4/libavformat/rtpdec_jpeg.c --- ffmpeg-4.2.2/libavformat/rtpdec_jpeg.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_jpeg.c 2021-04-08 21:28:40.000000000 +0000 @@ -112,7 +112,7 @@ jpeg_put_marker(&pbc, APP0); bytestream2_put_be16(&pbc, 16); bytestream2_put_buffer(&pbc, "JFIF", 5); - bytestream2_put_be16(&pbc, 0x0201); + bytestream2_put_be16(&pbc, 0x0102); bytestream2_put_byte(&pbc, 0); bytestream2_put_be16(&pbc, 1); bytestream2_put_be16(&pbc, 1); diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_latm.c ffmpeg-4.4/libavformat/rtpdec_latm.c --- ffmpeg-4.2.2/libavformat/rtpdec_latm.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_latm.c 2020-07-11 10:39:30.000000000 +0000 @@ -115,9 +115,8 @@ ret = AVERROR_PATCHWELCOME; goto end; } - av_freep(&st->codecpar->extradata); - if (ff_alloc_extradata(st->codecpar, (get_bits_left(&gb) + 7)/8)) { - ret = AVERROR(ENOMEM); + ret = ff_alloc_extradata(st->codecpar, (get_bits_left(&gb) + 7)/8); + if (ret < 0) { goto end; } for (i = 0; i < st->codecpar->extradata_size; i++) diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_mpa_robust.c ffmpeg-4.4/libavformat/rtpdec_mpa_robust.c --- ffmpeg-4.2.2/libavformat/rtpdec_mpa_robust.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_mpa_robust.c 2020-07-11 10:39:30.000000000 +0000 @@ -90,9 +90,9 @@ return AVERROR_INVALIDDATA; } - if (av_new_packet(pkt, adu_size)) { + if ((err = av_new_packet(pkt, adu_size)) < 0) { av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); - return AVERROR(ENOMEM); + return err; } pkt->stream_index = st->index; @@ -120,9 +120,9 @@ if (!continuation && adu_size <= len) { /* One or more complete frames */ - if (av_new_packet(pkt, adu_size)) { + if ((err = av_new_packet(pkt, adu_size)) < 0) { av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); - return AVERROR(ENOMEM); + return err; } pkt->stream_index = st->index; diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_mpeg12.c ffmpeg-4.4/libavformat/rtpdec_mpeg12.c --- ffmpeg-4.2.2/libavformat/rtpdec_mpeg12.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_mpeg12.c 2020-07-11 10:39:30.000000000 +0000 @@ -29,6 +29,7 @@ int flags) { unsigned int h; + int ret; if (len <= 4) return AVERROR_INVALIDDATA; h = AV_RB32(buf); @@ -41,8 +42,8 @@ buf += 4; len -= 4; } - if (av_new_packet(pkt, len) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, len)) < 0) + return ret; memcpy(pkt->data, buf, len); pkt->stream_index = st->index; return 0; diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_mpeg4.c ffmpeg-4.4/libavformat/rtpdec_mpeg4.c --- ffmpeg-4.2.2/libavformat/rtpdec_mpeg4.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_mpeg4.c 2020-07-11 10:39:30.000000000 +0000 @@ -70,6 +70,12 @@ const char *str; uint16_t type; uint32_t offset; + + /** Range for integer values */ + struct Range { + int min; + int max; + } range; } AttrNameMap; /* All known fmtp parameters and the corresponding RTPAttrTypeEnum */ @@ -77,18 +83,24 @@ #define ATTR_NAME_TYPE_STR 1 static const AttrNameMap attr_names[] = { { "SizeLength", ATTR_NAME_TYPE_INT, - offsetof(PayloadContext, sizelength) }, + offsetof(PayloadContext, sizelength), + {0, 32} }, // SizeLength number of bits used to encode AU-size integer value { "IndexLength", ATTR_NAME_TYPE_INT, - offsetof(PayloadContext, indexlength) }, + offsetof(PayloadContext, indexlength), + {0, 32} }, // IndexLength number of bits used to encode AU-Index integer value { "IndexDeltaLength", ATTR_NAME_TYPE_INT, - offsetof(PayloadContext, indexdeltalength) }, + offsetof(PayloadContext, indexdeltalength), + {0, 32} }, // IndexDeltaLength number of bits to encode AU-Index-delta integer value { "profile-level-id", ATTR_NAME_TYPE_INT, - offsetof(PayloadContext, profile_level_id) }, + offsetof(PayloadContext, profile_level_id), + {INT32_MIN, INT32_MAX} }, // It differs depending on StreamType { "StreamType", ATTR_NAME_TYPE_INT, - offsetof(PayloadContext, streamtype) }, + offsetof(PayloadContext, streamtype), + {0x00, 0x3F} }, // Values from ISO/IEC 14496-1, 'StreamType Values' table { "mode", ATTR_NAME_TYPE_STR, - offsetof(PayloadContext, mode) }, - { NULL, -1, -1 }, + offsetof(PayloadContext, mode), + {0} }, + { NULL, -1, -1, {0} }, }; static void close_context(PayloadContext *data) @@ -100,10 +112,10 @@ static int parse_fmtp_config(AVCodecParameters *par, const char *value) { /* decode the hexa encoded parameter */ - int len = ff_hex_to_data(NULL, value); - av_freep(&par->extradata); - if (ff_alloc_extradata(par, len)) - return AVERROR(ENOMEM); + int len = ff_hex_to_data(NULL, value), ret; + + if ((ret = ff_alloc_extradata(par, len)) < 0) + return ret; ff_hex_to_data(par->extradata, value); return 0; } @@ -289,15 +301,24 @@ for (i = 0; attr_names[i].str; ++i) { if (!av_strcasecmp(attr, attr_names[i].str)) { if (attr_names[i].type == ATTR_NAME_TYPE_INT) { - int val = atoi(value); - if (val > 32) { + char *end_ptr = NULL; + long long int val = strtoll(value, &end_ptr, 10); + if (end_ptr == value || end_ptr[0] != '\0') { av_log(s, AV_LOG_ERROR, - "The %s field size is invalid (%d)\n", - attr, val); + "The %s field value is not a valid number: %s\n", + attr, value); return AVERROR_INVALIDDATA; } + if (val < attr_names[i].range.min || + val > attr_names[i].range.max) { + av_log(s, AV_LOG_ERROR, + "fmtp field %s should be in range [%d,%d] (provided value: %lld)", + attr, attr_names[i].range.min, attr_names[i].range.max, val); + return AVERROR_INVALIDDATA; + } + *(int *)((char *)data+ - attr_names[i].offset) = val; + attr_names[i].offset) = (int) val; } else if (attr_names[i].type == ATTR_NAME_TYPE_STR) { char *val = av_strdup(value); if (!val) diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_qdm2.c ffmpeg-4.4/libavformat/rtpdec_qdm2.c --- ffmpeg-4.2.2/libavformat/rtpdec_qdm2.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_qdm2.c 2020-07-11 10:39:30.000000000 +0000 @@ -78,6 +78,7 @@ const uint8_t *buf, const uint8_t *end) { const uint8_t *p = buf; + int ret; while (end - p >= 2) { unsigned int item_len = p[0], config_item = p[1]; @@ -104,9 +105,10 @@ case 4: /* stream with extradata */ if (item_len < 30) return AVERROR_INVALIDDATA; - av_freep(&st->codecpar->extradata); - if (ff_alloc_extradata(st->codecpar, 26 + item_len)) { - return AVERROR(ENOMEM); + + ret = ff_alloc_extradata(st->codecpar, 26 + item_len); + if (ret < 0) { + return ret; } AV_WB32(st->codecpar->extradata, 12); memcpy(st->codecpar->extradata + 4, "frma", 4); diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_qt.c ffmpeg-4.4/libavformat/rtpdec_qt.c --- ffmpeg-4.2.2/libavformat/rtpdec_qt.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_qt.c 2021-04-08 21:28:40.000000000 +0000 @@ -34,11 +34,21 @@ #include "libavcodec/get_bits.h" struct PayloadContext { - AVPacket pkt; + AVPacket *pkt; int bytes_per_frame, remaining; uint32_t timestamp; }; +static av_cold int qt_rtp_init(AVFormatContext *ctx, int st_index, + PayloadContext *qt) +{ + qt->pkt = av_packet_alloc(); + if (!qt->pkt) + return AVERROR(ENOMEM); + + return 0; +} + static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, @@ -48,21 +58,21 @@ GetBitContext gb; int packing_scheme, has_payload_desc, has_packet_info, alen, has_marker_bit = flags & RTP_FLAG_MARKER, - keyframe; + keyframe, ret; if (qt->remaining) { - int num = qt->pkt.size / qt->bytes_per_frame; + int num = qt->pkt->size / qt->bytes_per_frame; - if (av_new_packet(pkt, qt->bytes_per_frame)) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, qt->bytes_per_frame)) < 0) + return ret; pkt->stream_index = st->index; - pkt->flags = qt->pkt.flags; + pkt->flags = qt->pkt->flags; memcpy(pkt->data, - &qt->pkt.data[(num - qt->remaining) * qt->bytes_per_frame], + &qt->pkt->data[(num - qt->remaining) * qt->bytes_per_frame], qt->bytes_per_frame); if (--qt->remaining == 0) { - av_freep(&qt->pkt.data); - qt->pkt.size = 0; + av_freep(&qt->pkt->data); + qt->pkt->size = 0; } return qt->remaining > 0; } @@ -171,31 +181,31 @@ switch (packing_scheme) { case 3: /* one data packet spread over 1 or multiple RTP packets */ - if (qt->pkt.size > 0 && qt->timestamp == *timestamp) { + if (qt->pkt->size > 0 && qt->timestamp == *timestamp) { int err; - if ((err = av_reallocp(&qt->pkt.data, qt->pkt.size + alen + + if ((err = av_reallocp(&qt->pkt->data, qt->pkt->size + alen + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) { - qt->pkt.size = 0; + qt->pkt->size = 0; return err; } } else { - av_freep(&qt->pkt.data); - av_init_packet(&qt->pkt); - qt->pkt.data = av_realloc(NULL, alen + AV_INPUT_BUFFER_PADDING_SIZE); - if (!qt->pkt.data) + av_freep(&qt->pkt->data); + av_packet_unref(qt->pkt); + qt->pkt->data = av_realloc(NULL, alen + AV_INPUT_BUFFER_PADDING_SIZE); + if (!qt->pkt->data) return AVERROR(ENOMEM); - qt->pkt.size = 0; + qt->pkt->size = 0; qt->timestamp = *timestamp; } - memcpy(qt->pkt.data + qt->pkt.size, buf + avio_tell(&pb), alen); - qt->pkt.size += alen; + memcpy(qt->pkt->data + qt->pkt->size, buf + avio_tell(&pb), alen); + qt->pkt->size += alen; if (has_marker_bit) { - int ret = av_packet_from_data(pkt, qt->pkt.data, qt->pkt.size); + int ret = av_packet_from_data(pkt, qt->pkt->data, qt->pkt->size); if (ret < 0) return ret; - qt->pkt.size = 0; - qt->pkt.data = NULL; + qt->pkt->size = 0; + qt->pkt->data = NULL; pkt->flags = keyframe ? AV_PKT_FLAG_KEY : 0; pkt->stream_index = st->index; memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE); @@ -208,23 +218,23 @@ alen % qt->bytes_per_frame != 0) return AVERROR_INVALIDDATA; /* wrongly padded */ qt->remaining = (alen / qt->bytes_per_frame) - 1; - if (av_new_packet(pkt, qt->bytes_per_frame)) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, qt->bytes_per_frame)) < 0) + return ret; memcpy(pkt->data, buf + avio_tell(&pb), qt->bytes_per_frame); pkt->flags = keyframe ? AV_PKT_FLAG_KEY : 0; pkt->stream_index = st->index; if (qt->remaining > 0) { - av_freep(&qt->pkt.data); - qt->pkt.data = av_realloc(NULL, qt->remaining * qt->bytes_per_frame); - if (!qt->pkt.data) { + av_freep(&qt->pkt->data); + qt->pkt->data = av_realloc(NULL, qt->remaining * qt->bytes_per_frame); + if (!qt->pkt->data) { av_packet_unref(pkt); return AVERROR(ENOMEM); } - qt->pkt.size = qt->remaining * qt->bytes_per_frame; - memcpy(qt->pkt.data, + qt->pkt->size = qt->remaining * qt->bytes_per_frame; + memcpy(qt->pkt->data, buf + avio_tell(&pb) + qt->bytes_per_frame, qt->remaining * qt->bytes_per_frame); - qt->pkt.flags = pkt->flags; + qt->pkt->flags = pkt->flags; return 1; } return 0; @@ -237,15 +247,17 @@ static void qt_rtp_close(PayloadContext *qt) { - av_freep(&qt->pkt.data); + av_freep(&qt->pkt->data); + av_packet_free(&qt->pkt); } #define RTP_QT_HANDLER(m, n, s, t) \ -RTPDynamicProtocolHandler ff_ ## m ## _rtp_ ## n ## _handler = { \ +const RTPDynamicProtocolHandler ff_ ## m ## _rtp_ ## n ## _handler = { \ .enc_name = s, \ .codec_type = t, \ .codec_id = AV_CODEC_ID_NONE, \ .priv_data_size = sizeof(PayloadContext), \ + .init = qt_rtp_init, \ .close = qt_rtp_close, \ .parse_packet = qt_rtp_parse_packet, \ } diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_svq3.c ffmpeg-4.4/libavformat/rtpdec_svq3.c --- ffmpeg-4.2.2/libavformat/rtpdec_svq3.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_svq3.c 2020-07-11 10:39:30.000000000 +0000 @@ -58,10 +58,6 @@ len -= 2; if (config_packet) { - - av_freep(&st->codecpar->extradata); - st->codecpar->extradata_size = 0; - if (len < 2 || ff_alloc_extradata(st->codecpar, len + 8)) return AVERROR_INVALIDDATA; diff -Nru ffmpeg-4.2.2/libavformat/rtpdec_xiph.c ffmpeg-4.4/libavformat/rtpdec_xiph.c --- ffmpeg-4.2.2/libavformat/rtpdec_xiph.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpdec_xiph.c 2020-07-11 10:39:30.000000000 +0000 @@ -63,7 +63,7 @@ int flags) { - int ident, fragmented, tdt, num_pkts, pkt_len; + int ident, fragmented, tdt, num_pkts, pkt_len, ret; if (!buf) { if (!data->split_buf || data->split_pos + 2 > data->split_buf_len || @@ -77,9 +77,9 @@ av_log(ctx, AV_LOG_ERROR, "Not enough data to return\n"); return AVERROR_INVALIDDATA; } - if (av_new_packet(pkt, pkt_len)) { + if ((ret = av_new_packet(pkt, pkt_len)) < 0) { av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); - return AVERROR(ENOMEM); + return ret; } pkt->stream_index = st->index; memcpy(pkt->data, data->split_buf + data->split_pos, pkt_len); @@ -123,9 +123,9 @@ len -= 6; if (fragmented == 0) { - if (av_new_packet(pkt, pkt_len)) { + if ((ret = av_new_packet(pkt, pkt_len)) < 0) { av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); - return AVERROR(ENOMEM); + return ret; } pkt->stream_index = st->index; memcpy(pkt->data, buf, pkt_len); @@ -228,6 +228,7 @@ { unsigned num_packed, num_headers, length, length1, length2, extradata_alloc; + int ret; uint8_t *ptr; if (packed_headers_end - packed_headers < 9) { @@ -264,9 +265,9 @@ * -- AV_INPUT_BUFFER_PADDING_SIZE required */ extradata_alloc = length + length/255 + 3 + AV_INPUT_BUFFER_PADDING_SIZE; - if (ff_alloc_extradata(par, extradata_alloc)) { + if ((ret = ff_alloc_extradata(par, extradata_alloc)) < 0) { av_log(s, AV_LOG_ERROR, "Out of memory\n"); - return AVERROR(ENOMEM); + return ret; } ptr = par->extradata; *ptr++ = 2; diff -Nru ffmpeg-4.2.2/libavformat/rtpenc.c ffmpeg-4.4/libavformat/rtpenc.c --- ffmpeg-4.2.2/libavformat/rtpenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -589,7 +589,7 @@ break; case AV_CODEC_ID_H263: if (s->flags & FF_RTP_FLAG_RFC2190) { - int mb_info_size = 0; + buffer_size_t mb_info_size; const uint8_t *mb_info = av_packet_get_side_data(pkt, AV_PKT_DATA_H263_MB_INFO, &mb_info_size); diff -Nru ffmpeg-4.2.2/libavformat/rtpenc_mpegts.c ffmpeg-4.4/libavformat/rtpenc_mpegts.c --- ffmpeg-4.2.2/libavformat/rtpenc_mpegts.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpenc_mpegts.c 2021-04-08 21:28:40.000000000 +0000 @@ -20,17 +20,22 @@ */ #include "libavutil/mathematics.h" +#include "libavutil/opt.h" #include "avformat.h" #include "avio_internal.h" -struct MuxChain { +typedef struct MuxChain { + const AVClass *class; AVFormatContext *mpegts_ctx; AVFormatContext *rtp_ctx; -}; + AVPacket *pkt; + AVDictionary* mpegts_muxer_options; + AVDictionary* rtp_muxer_options; +} MuxChain; static int rtp_mpegts_write_close(AVFormatContext *s) { - struct MuxChain *chain = s->priv_data; + MuxChain *chain = s->priv_data; if (chain->mpegts_ctx) { av_write_trailer(chain->mpegts_ctx); @@ -41,37 +46,53 @@ av_write_trailer(chain->rtp_ctx); avformat_free_context(chain->rtp_ctx); } + + av_packet_free(&chain->pkt); + return 0; } static int rtp_mpegts_write_header(AVFormatContext *s) { - struct MuxChain *chain = s->priv_data; + MuxChain *chain = s->priv_data; AVFormatContext *mpegts_ctx = NULL, *rtp_ctx = NULL; ff_const59 AVOutputFormat *mpegts_format = av_guess_format("mpegts", NULL, NULL); ff_const59 AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL); int i, ret = AVERROR(ENOMEM); AVStream *st; + AVDictionary *mpegts_muxer_options = NULL; + AVDictionary *rtp_muxer_options = NULL; if (!mpegts_format || !rtp_format) return AVERROR(ENOSYS); mpegts_ctx = avformat_alloc_context(); if (!mpegts_ctx) return AVERROR(ENOMEM); + chain->pkt = av_packet_alloc(); + if (!chain->pkt) + goto fail; mpegts_ctx->oformat = mpegts_format; mpegts_ctx->max_delay = s->max_delay; + av_dict_copy(&mpegts_ctx->metadata, s->metadata, 0); for (i = 0; i < s->nb_streams; i++) { AVStream* st = avformat_new_stream(mpegts_ctx, NULL); if (!st) goto fail; st->time_base = s->streams[i]->time_base; st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; + st->id = s->streams[i]->id; avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar); } if ((ret = avio_open_dyn_buf(&mpegts_ctx->pb)) < 0) goto fail; - if ((ret = avformat_write_header(mpegts_ctx, NULL)) < 0) + + av_dict_copy(&mpegts_muxer_options, chain->mpegts_muxer_options, 0); + + ret = avformat_write_header(mpegts_ctx, &mpegts_muxer_options); + av_dict_free(&mpegts_muxer_options); + if (ret < 0) goto fail; + for (i = 0; i < s->nb_streams; i++) s->streams[i]->time_base = mpegts_ctx->streams[i]->time_base; @@ -93,8 +114,12 @@ st->time_base.den = 90000; st->codecpar->codec_id = AV_CODEC_ID_MPEG2TS; rtp_ctx->pb = s->pb; - if ((ret = avformat_write_header(rtp_ctx, NULL)) < 0) + av_dict_copy(&rtp_muxer_options, chain->rtp_muxer_options, 0); + ret = avformat_write_header(rtp_ctx, &rtp_muxer_options); + av_dict_free(&rtp_muxer_options); + if (ret < 0) goto fail; + chain->rtp_ctx = rtp_ctx; return 0; @@ -102,20 +127,20 @@ fail: if (mpegts_ctx) { ffio_free_dyn_buf(&mpegts_ctx->pb); + av_dict_free(&mpegts_ctx->metadata); avformat_free_context(mpegts_ctx); } - if (rtp_ctx) - avformat_free_context(rtp_ctx); + avformat_free_context(rtp_ctx); rtp_mpegts_write_close(s); return ret; } static int rtp_mpegts_write_packet(AVFormatContext *s, AVPacket *pkt) { - struct MuxChain *chain = s->priv_data; + MuxChain *chain = s->priv_data; int ret = 0, size; uint8_t *buf; - AVPacket local_pkt; + AVPacket *local_pkt = chain->pkt; if (!chain->mpegts_ctx->pb) { if ((ret = avio_open_dyn_buf(&chain->mpegts_ctx->pb)) < 0) @@ -129,31 +154,47 @@ av_free(buf); return 0; } - av_init_packet(&local_pkt); - local_pkt.data = buf; - local_pkt.size = size; - local_pkt.stream_index = 0; + av_packet_unref(local_pkt); + local_pkt->data = buf; + local_pkt->size = size; + local_pkt->stream_index = 0; if (pkt->pts != AV_NOPTS_VALUE) - local_pkt.pts = av_rescale_q(pkt->pts, + local_pkt->pts = av_rescale_q(pkt->pts, s->streams[pkt->stream_index]->time_base, chain->rtp_ctx->streams[0]->time_base); if (pkt->dts != AV_NOPTS_VALUE) - local_pkt.dts = av_rescale_q(pkt->dts, + local_pkt->dts = av_rescale_q(pkt->dts, s->streams[pkt->stream_index]->time_base, chain->rtp_ctx->streams[0]->time_base); - ret = av_write_frame(chain->rtp_ctx, &local_pkt); + ret = av_write_frame(chain->rtp_ctx, local_pkt); av_free(buf); return ret; } +#define OFFSET(x) offsetof(MuxChain, x) +#define E AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "mpegts_muxer_options", "set list of options for the MPEG-TS muxer", OFFSET(mpegts_muxer_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E }, + { "rtp_muxer_options", "set list of options for the RTP muxer", OFFSET(rtp_muxer_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E }, + { NULL }, +}; + +static const AVClass rtp_mpegts_class = { + .class_name = "rtp_mpegts muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVOutputFormat ff_rtp_mpegts_muxer = { .name = "rtp_mpegts", .long_name = NULL_IF_CONFIG_SMALL("RTP/mpegts output format"), - .priv_data_size = sizeof(struct MuxChain), + .priv_data_size = sizeof(MuxChain), .audio_codec = AV_CODEC_ID_AAC, .video_codec = AV_CODEC_ID_MPEG4, .write_header = rtp_mpegts_write_header, .write_packet = rtp_mpegts_write_packet, .write_trailer = rtp_mpegts_write_close, + .priv_class = &rtp_mpegts_class, }; diff -Nru ffmpeg-4.2.2/libavformat/rtpproto.c ffmpeg-4.4/libavformat/rtpproto.c --- ffmpeg-4.2.2/libavformat/rtpproto.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtpproto.c 2021-04-08 21:28:40.000000000 +0000 @@ -60,6 +60,7 @@ char *sources; char *block; char *fec_options_str; + int64_t rw_timeout; } RTPContext; #define OFFSET(x) offsetof(RTPContext, x) @@ -75,6 +76,7 @@ { "write_to_source", "Send packets to the source address of the latest received packet", OFFSET(write_to_source), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E }, { "pkt_size", "Maximum packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "dscp", "DSCP class", OFFSET(dscp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "timeout", "set timeout (in microseconds) of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E }, { "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 }, @@ -265,6 +267,9 @@ if (av_find_info_tag(buf, sizeof(buf), "dscp", p)) { s->dscp = strtol(buf, NULL, 10); } + if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { + s->rw_timeout = strtol(buf, NULL, 10); + } if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { av_strlcpy(include_sources, buf, sizeof(include_sources)); ff_ip_parse_sources(h, buf, &s->filters); @@ -280,6 +285,8 @@ block = s->block; } } + if (s->rw_timeout >= 0) + h->rw_timeout = s->rw_timeout; if (s->fec_options_str) { p = s->fec_options_str; @@ -301,8 +308,7 @@ goto fail; } if (s->ttl > 0) { - snprintf(buf, sizeof (buf), "%d", s->ttl); - av_dict_set(&fec_opts, "ttl", buf, 0); + av_dict_set_int(&fec_opts, "ttl", s->ttl, 0); } } @@ -363,10 +369,8 @@ return 0; fail: - if (s->rtp_hd) - ffurl_close(s->rtp_hd); - if (s->rtcp_hd) - ffurl_close(s->rtcp_hd); + ffurl_closep(&s->rtp_hd); + ffurl_closep(&s->rtcp_hd); ffurl_closep(&s->fec_hd); av_free(fec_protocol); av_dict_free(&fec_opts); @@ -378,9 +382,10 @@ RTPContext *s = h->priv_data; int len, n, i; struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}}; - int poll_delay = h->flags & AVIO_FLAG_NONBLOCK ? 0 : 100; + int poll_delay = h->flags & AVIO_FLAG_NONBLOCK ? 0 : POLLING_TIME; struct sockaddr_storage *addrs[2] = { &s->last_rtp_source, &s->last_rtcp_source }; socklen_t *addr_lens[2] = { &s->last_rtp_source_len, &s->last_rtcp_source_len }; + int runs = h->rw_timeout / 1000 / POLLING_TIME; for(;;) { if (ff_check_interrupt(&h->interrupt_callback)) @@ -404,6 +409,8 @@ continue; return len; } + } else if (n == 0 && h->rw_timeout > 0 && --runs <= 0) { + return AVERROR(ETIMEDOUT); } else if (n < 0) { if (ff_neterrno() == AVERROR(EINTR)) continue; @@ -506,8 +513,8 @@ ff_ip_reset_filters(&s->filters); - ffurl_close(s->rtp_hd); - ffurl_close(s->rtcp_hd); + ffurl_closep(&s->rtp_hd); + ffurl_closep(&s->rtcp_hd); ffurl_closep(&s->fec_hd); return 0; } diff -Nru ffmpeg-4.2.2/libavformat/rtsp.c ffmpeg-4.4/libavformat/rtsp.c --- ffmpeg-4.2.2/libavformat/rtsp.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,6 +21,7 @@ #include "libavutil/avassert.h" #include "libavutil/base64.h" +#include "libavutil/bprint.h" #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" @@ -50,12 +51,8 @@ #include "rtpenc.h" #include "mpegts.h" -/* Timeout values for socket poll, in ms, - * and read_packet(), in seconds */ -#define POLL_TIMEOUT_MS 100 +/* Default timeout values for read packet in seconds */ #define READ_PACKET_TIMEOUT_S 10 -#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / POLL_TIMEOUT_MS -#define SDP_MAX_SIZE 16384 #define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH #define DEFAULT_REORDERING_DELAY 100000 @@ -92,12 +89,13 @@ RTSP_FLAG_OPTS("rtsp_flags", "set RTSP flags"), { "listen", "wait for incoming connections", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_LISTEN}, 0, 0, DEC, "rtsp_flags" }, { "prefer_tcp", "try RTP via TCP first, if available", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_PREFER_TCP}, 0, 0, DEC|ENC, "rtsp_flags" }, + { "satip_raw", "export raw MPEG-TS stream instead of demuxing", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_SATIP_RAW}, 0, 0, DEC, "rtsp_flags" }, RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"), { "min_port", "set minimum local UDP port", OFFSET(rtp_port_min), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MIN}, 0, 65535, DEC|ENC }, { "max_port", "set maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC }, { "listen_timeout", "set maximum timeout (in seconds) to wait for incoming connections (-1 is infinite, imply flag listen)", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC }, #if FF_API_OLD_RTSP_OPTIONS - { "timeout", "set maximum timeout (in seconds) to wait for incoming connections (-1 is infinite, imply flag listen) (deprecated, use listen_timeout)", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC }, + { "timeout", "set maximum timeout (in seconds) to wait for incoming connections (-1 is infinite, imply flag listen) (deprecated, use listen_timeout)", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC|AV_OPT_FLAG_DEPRECATED }, { "stimeout", "set timeout (in microseconds) of socket TCP I/O operations", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, #else { "timeout", "set timeout (in microseconds) of socket TCP I/O operations", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, @@ -105,7 +103,7 @@ COMMON_OPTS(), { "user_agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC }, #if FF_API_OLD_RTSP_OPTIONS - { "user-agent", "override User-Agent header (deprecated, use user_agent)", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC }, + { "user-agent", "override User-Agent header (deprecated, use user_agent)", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC|AV_OPT_FLAG_DEPRECATED }, #endif { NULL }, }; @@ -114,6 +112,7 @@ RTSP_FLAG_OPTS("sdp_flags", "SDP flags"), { "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(initial_timeout), AV_OPT_TYPE_INT, {.i64 = READ_PACKET_TIMEOUT_S}, INT_MIN, INT_MAX, DEC }, RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"), COMMON_OPTS(), { NULL }, @@ -121,6 +120,8 @@ 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(initial_timeout), AV_OPT_TYPE_INT, {.i64 = READ_PACKET_TIMEOUT_S}, INT_MIN, INT_MAX, DEC }, + RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"), COMMON_OPTS(), { NULL }, }; @@ -252,6 +253,35 @@ } } +static int init_satip_stream(AVFormatContext *s) +{ + RTSPState *rt = s->priv_data; + RTSPStream *rtsp_st = av_mallocz(sizeof(RTSPStream)); + if (!rtsp_st) + return AVERROR(ENOMEM); + dynarray_add(&rt->rtsp_streams, + &rt->nb_rtsp_streams, rtsp_st); + + rtsp_st->sdp_payload_type = 33; // MP2T + av_strlcpy(rtsp_st->control_url, + rt->control_uri, sizeof(rtsp_st->control_url)); + + if (rt->rtsp_flags & RTSP_FLAG_SATIP_RAW) { + AVStream *st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + st->id = rt->nb_rtsp_streams - 1; + rtsp_st->stream_index = st->index; + st->codecpar->codec_type = AVMEDIA_TYPE_DATA; + st->codecpar->codec_id = AV_CODEC_ID_MPEG2TS; + } else { + rtsp_st->stream_index = -1; + init_rtp_handler(&ff_mpegts_dynamic_handler, rtsp_st, NULL); + finalize_rtp_handler_init(s, rtsp_st, NULL); + } + return 0; +} + /* parse the rtpmap description: /[/] */ static int sdp_parse_rtpmap(AVFormatContext *s, AVStream *st, RTSPStream *rtsp_st, @@ -541,7 +571,7 @@ break; case 'a': if (av_strstart(p, "control:", &p)) { - if (s->nb_streams == 0) { + if (rt->nb_rtsp_streams == 0) { if (!strncmp(p, "rtsp://", 7)) av_strlcpy(rt->control_uri, p, sizeof(rt->control_uri)); @@ -687,15 +717,7 @@ { const char *p; int letter, i; - /* Some SDP lines, particularly for Realmedia or ASF RTSP streams, - * contain long SDP lines containing complete ASF Headers (several - * kB) or arrays of MDPR (RM stream descriptor) headers plus - * "rulebooks" describing their properties. Therefore, the SDP line - * buffer is large. - * - * The Vorbis FMTP line can be up to 16KB - see xiph_parse_sdp_line - * in rtpdec_xiph.c. */ - char buf[16384], *q; + char buf[SDP_MAX_SIZE], *q; SDPParseState sdp_parse_state = { { 0 } }, *s1 = &sdp_parse_state; p = content; @@ -762,9 +784,7 @@ ff_rtp_parse_close(rtsp_st->transport_priv); } rtsp_st->transport_priv = NULL; - if (rtsp_st->rtp_handle) - ffurl_close(rtsp_st->rtp_handle); - rtsp_st->rtp_handle = NULL; + ffurl_closep(&rtsp_st->rtp_handle); } } @@ -1035,7 +1055,7 @@ static void rtsp_parse_rtp_info(RTSPState *rt, const char *p) { int read = 0; - char key[20], value[1024], url[1024] = ""; + char key[20], value[MAX_URL_SIZE], url[MAX_URL_SIZE] = ""; uint32_t seq = 0, rtptime = 0; for (;;) { @@ -1126,6 +1146,9 @@ } else if (av_stristart(p, "Content-Type:", &p)) { p += strspn(p, SPACE_CHARS); av_strlcpy(reply->content_type, p, sizeof(reply->content_type)); + } else if (av_stristart(p, "com.ses.streamID:", &p)) { + p += strspn(p, SPACE_CHARS); + av_strlcpy(reply->stream_id, p, sizeof(reply->stream_id)); } } @@ -1134,7 +1157,7 @@ { RTSPState *rt = s->priv_data; int ret, len, len1; - uint8_t buf[1024]; + uint8_t buf[MAX_URL_SIZE]; ret = ffurl_read_complete(rt->rtsp_hd, buf, 3); if (ret != 3) @@ -1160,7 +1183,7 @@ int return_on_interleaved_data, const char *method) { RTSPState *rt = s->priv_data; - char buf[4096], buf1[1024], *q; + 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; @@ -1230,7 +1253,8 @@ content = av_malloc(content_length + 1); if (!content) return AVERROR(ENOMEM); - ffurl_read_complete(rt->rtsp_hd, content, content_length); + if (ffurl_read_complete(rt->rtsp_hd, content, content_length) != content_length) + return AVERROR(EIO); content[content_length] = '\0'; } if (content_ptr) @@ -1239,7 +1263,7 @@ av_freep(&content); if (request) { - char buf[1024]; + char buf[MAX_URL_SIZE]; char base64buf[AV_BASE64_SIZE(sizeof(buf))]; const char* ptr = buf; @@ -1315,11 +1339,11 @@ int send_content_length) { RTSPState *rt = s->priv_data; - char buf[4096], *out_buf; + char buf[MAX_URL_SIZE], *out_buf; char base64buf[AV_BASE64_SIZE(sizeof(buf))]; if (!rt->rtsp_hd_out) - return ENOTCONN; + return AVERROR(ENOTCONN); /* Add in RTSP headers */ out_buf = buf; @@ -1425,7 +1449,7 @@ int rtx = 0, j, i, err, interleave = 0, port_off; RTSPStream *rtsp_st; RTSPMessageHeader reply1, *reply = &reply1; - char cmd[2048]; + char cmd[MAX_URL_SIZE]; const char *trans_pref; if (rt->transport == RTSP_TRANSPORT_RDT) @@ -1446,7 +1470,7 @@ port_off -= port_off & 0x01; for (j = rt->rtp_port_min + port_off, i = 0; i < rt->nb_rtsp_streams; ++i) { - char transport[2048]; + char transport[MAX_URL_SIZE]; /* * WMS serves all UDP data over a single connection, the RTX, which @@ -1504,8 +1528,10 @@ rtp_opened: port = ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle); have_port: - snprintf(transport, sizeof(transport) - 1, - "%s/UDP;", trans_pref); + av_strlcpy(transport, trans_pref, sizeof(transport)); + av_strlcat(transport, + rt->server_type == RTSP_SERVER_SATIP ? ";" : "/UDP;", + sizeof(transport)); if (rt->server_type != RTSP_SERVER_REAL) av_strlcat(transport, "unicast;", sizeof(transport)); av_strlcatf(transport, sizeof(transport), @@ -1568,6 +1594,15 @@ goto fail; } + if (rt->server_type == RTSP_SERVER_SATIP && reply->stream_id[0]) { + char proto[128], host[128], path[512], auth[128]; + int port; + av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host), + &port, path, sizeof(path), rt->control_uri); + ff_url_join(rt->control_uri, sizeof(rt->control_uri), proto, NULL, host, + port, "/stream=%s", reply->stream_id); + } + /* XXX: same protocol for all streams is required */ if (i > 0) { if (reply->transports[0].lower_transport != rt->lower_transport || @@ -1595,7 +1630,7 @@ break; case RTSP_LOWER_TRANSPORT_UDP: { - char url[1024], options[30] = ""; + char url[MAX_URL_SIZE], options[30] = ""; const char *peer = host; if (rt->rtsp_flags & RTSP_FLAG_FILTER_SRC) @@ -1613,9 +1648,10 @@ break; } case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: { - char url[1024], namebuf[50], optbuf[20] = ""; + char url[MAX_URL_SIZE], namebuf[50], optbuf[20] = ""; struct sockaddr_storage addr; int port, ttl; + AVDictionary *opts = map_to_opts(rt); if (reply->transports[0].destination.ss_family) { addr = reply->transports[0].destination; @@ -1632,8 +1668,11 @@ namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); ff_url_join(url, sizeof(url), "rtp", NULL, namebuf, port, "%s", optbuf); - if (ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL) < 0) { + err = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, + &s->interrupt_callback, &opts, s->protocol_whitelist, s->protocol_blacklist, NULL); + av_dict_free(&opts); + + if (err < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1661,16 +1700,17 @@ void ff_rtsp_close_connections(AVFormatContext *s) { RTSPState *rt = s->priv_data; - if (rt->rtsp_hd_out != rt->rtsp_hd) ffurl_close(rt->rtsp_hd_out); - ffurl_close(rt->rtsp_hd); - rt->rtsp_hd = rt->rtsp_hd_out = NULL; + if (rt->rtsp_hd_out != rt->rtsp_hd) + ffurl_closep(&rt->rtsp_hd_out); + rt->rtsp_hd_out = NULL; + ffurl_closep(&rt->rtsp_hd); } int ff_rtsp_connect(AVFormatContext *s) { RTSPState *rt = s->priv_data; char proto[128], host[1024], path[1024]; - char tcpname[1024], cmd[2048], auth[128]; + char tcpname[1024], cmd[MAX_URL_SIZE], auth[128]; const char *lower_rtsp_proto = "tcp"; int port, err, tcp_fd; RTSPMessageHeader reply1, *reply = &reply1; @@ -1714,6 +1754,9 @@ lower_rtsp_proto = "tls"; default_port = RTSPS_DEFAULT_PORT; rt->lower_transport_mask = 1 << RTSP_LOWER_TRANSPORT_TCP; + } else if (!strcmp(proto, "satip")) { + av_strlcpy(proto, "rtsp", sizeof(proto)); + rt->server_type = RTSP_SERVER_SATIP; } if (*auth) { @@ -1861,7 +1904,9 @@ /* request options supported by the server; this also detects server * type */ - for (rt->server_type = RTSP_SERVER_RTP;;) { + if (rt->server_type != RTSP_SERVER_SATIP) + rt->server_type = RTSP_SERVER_RTP; + for (;;) { cmd[0] = 0; if (rt->server_type == RTSP_SERVER_REAL) av_strlcat(cmd, @@ -1896,9 +1941,15 @@ break; } - if (CONFIG_RTSP_DEMUXER && s->iformat) - err = ff_rtsp_setup_input_streams(s, reply); - else if (CONFIG_RTSP_MUXER) +#if CONFIG_RTSP_DEMUXER + if (s->iformat) { + if (rt->server_type == RTSP_SERVER_SATIP) + err = init_satip_stream(s); + else + err = ff_rtsp_setup_input_streams(s, reply); + } else +#endif + if (CONFIG_RTSP_MUXER) err = ff_rtsp_setup_output_streams(s, host); else av_assert0(0); @@ -1960,13 +2011,9 @@ if (rt->rtsp_flags & RTSP_FLAG_LISTEN) { if (rt->state == RTSP_STATE_STREAMING) { - if (!ff_rtsp_parse_streaming_commands(s)) - return AVERROR_EOF; - else - av_log(s, AV_LOG_WARNING, - "Unable to answer to TEARDOWN\n"); + return ff_rtsp_parse_streaming_commands(s); } else - return 0; + return AVERROR_EOF; } else { RTSPMessageHeader reply; ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL); @@ -1985,12 +2032,13 @@ { RTSPState *rt = s->priv_data; RTSPStream *rtsp_st; - int n, i, ret, timeout_cnt = 0; + int n, i, ret; struct pollfd *p = rt->p; int *fds = NULL, fdsnum, fdsidx; + int runs = rt->initial_timeout * 1000LL / POLLING_TIME; if (!p) { - p = rt->p = av_malloc_array(2 * (rt->nb_rtsp_streams + 1), sizeof(struct pollfd)); + p = rt->p = av_malloc_array(2 * rt->nb_rtsp_streams + 1, sizeof(*p)); if (!p) return AVERROR(ENOMEM); @@ -2025,10 +2073,9 @@ return AVERROR_EXIT; if (wait_end && wait_end - av_gettime_relative() < 0) return AVERROR(EAGAIN); - n = poll(p, rt->max_p, POLL_TIMEOUT_MS); + n = poll(p, rt->max_p, POLLING_TIME); if (n > 0) { int j = rt->rtsp_hd ? 1 : 0; - timeout_cnt = 0; for (i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; if (rtsp_st->rtp_handle) { @@ -2049,7 +2096,7 @@ } } #endif - } else if (n == 0 && ++timeout_cnt >= MAX_TIMEOUTS) { + } else if (n == 0 && rt->initial_timeout > 0 && --runs <= 0) { return AVERROR(ETIMEDOUT); } else if (n < 0 && errno != EINTR) return AVERROR(errno); @@ -2255,9 +2302,7 @@ s->start_time_realtime = av_rescale (rtpctx->first_rtcp_ntp_time - (NTP_OFFSET << 32), 1000000, 1LL << 32); if (rtpctx->st) { s->start_time_realtime -= - av_rescale (rtpctx->rtcp_ts_offset, - (uint64_t) rtpctx->st->time_base.num * 1000000, - rtpctx->st->time_base.den); + av_rescale_q (rtpctx->rtcp_ts_offset, rtpctx->st->time_base, AV_TIME_BASE_Q); } } } @@ -2334,7 +2379,7 @@ RTSPStream *rtsp_st; int size, i, err; char *content; - char url[1024]; + char url[MAX_URL_SIZE]; if (!ff_network_init()) return AVERROR(EIO); @@ -2347,11 +2392,14 @@ /* read the whole sdp file */ /* XXX: better loading */ content = av_malloc(SDP_MAX_SIZE); - if (!content) + if (!content) { + ff_network_close(); return AVERROR(ENOMEM); + } 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'; @@ -2447,7 +2495,7 @@ static int rtp_read_header(AVFormatContext *s) { uint8_t recvbuf[RTP_MAX_PACKET_LENGTH]; - char host[500], sdp[500]; + char host[500], filters_buf[1000]; int ret, port; URLContext* in = NULL; int payload_type; @@ -2456,12 +2504,17 @@ AVIOContext pb; socklen_t addrlen = sizeof(addr); RTSPState *rt = s->priv_data; + const char *p; + AVBPrint sdp; + AVDictionary *opts = NULL; if (!ff_network_init()) return AVERROR(EIO); + opts = map_to_opts(rt); ret = ffurl_open_whitelist(&in, s->url, AVIO_FLAG_READ, - &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL); + &s->interrupt_callback, &opts, s->protocol_whitelist, s->protocol_blacklist, NULL); + av_dict_free(&opts); if (ret) goto fail; @@ -2489,8 +2542,7 @@ break; } getsockname(ffurl_get_file_handle(in), (struct sockaddr*) &addr, &addrlen); - ffurl_close(in); - in = NULL; + ffurl_closep(&in); par = avcodec_parameters_alloc(); if (!par) { @@ -2502,6 +2554,7 @@ av_log(s, AV_LOG_ERROR, "Unable to receive RTP payload type %d " "without an SDP file describing it\n", payload_type); + ret = AVERROR_INVALIDDATA; goto fail; } if (par->codec_type != AVMEDIA_TYPE_DATA) { @@ -2513,31 +2566,60 @@ av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0, s->url); - snprintf(sdp, sizeof(sdp), - "v=0\r\nc=IN IP%d %s\r\nm=%s %d RTP/AVP %d\r\n", - addr.ss_family == AF_INET ? 4 : 6, host, - par->codec_type == AVMEDIA_TYPE_DATA ? "application" : - par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio", - port, payload_type); - av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp); + av_bprint_init(&sdp, 0, AV_BPRINT_SIZE_UNLIMITED); + av_bprintf(&sdp, "v=0\r\nc=IN IP%d %s\r\n", + addr.ss_family == AF_INET ? 4 : 6, host); + + p = strchr(s->url, '?'); + if (p) { + static const char filters[][2][8] = { { "sources", "incl" }, + { "block", "excl" } }; + int i; + char *q; + for (i = 0; i < FF_ARRAY_ELEMS(filters); i++) { + if (av_find_info_tag(filters_buf, sizeof(filters_buf), filters[i][0], p)) { + q = filters_buf; + while ((q = strchr(q, ',')) != NULL) + *q = ' '; + av_bprintf(&sdp, "a=source-filter:%s IN IP%d %s %s\r\n", + filters[i][1], + addr.ss_family == AF_INET ? 4 : 6, host, + filters_buf); + } + } + } + + av_bprintf(&sdp, "m=%s %d RTP/AVP %d\r\n", + par->codec_type == AVMEDIA_TYPE_DATA ? "application" : + par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio", + port, payload_type); + av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp.str); + if (!av_bprint_is_complete(&sdp)) + goto fail_nobuf; avcodec_parameters_free(&par); - ffio_init_context(&pb, sdp, strlen(sdp), 0, NULL, NULL, NULL, NULL); + ffio_init_context(&pb, sdp.str, sdp.len, 0, NULL, NULL, NULL, NULL); s->pb = &pb; - /* sdp_read_header initializes this again */ + /* if sdp_read_header() fails then following ff_network_close() cancels out */ + /* ff_network_init() at the start of this function. Otherwise it cancels out */ + /* ff_network_init() inside sdp_read_header() */ ff_network_close(); rt->media_type_mask = (1 << (AVMEDIA_TYPE_SUBTITLE+1)) - 1; ret = sdp_read_header(s); s->pb = NULL; + av_bprint_finalize(&sdp, NULL); return ret; +fail_nobuf: + ret = AVERROR(ENOMEM); + av_log(s, AV_LOG_ERROR, "rtp_read_header(): not enough buffer space for sdp-headers\n"); + av_bprint_finalize(&sdp, NULL); fail: avcodec_parameters_free(&par); - if (in) - ffurl_close(in); + ffurl_closep(&in); ff_network_close(); return ret; } diff -Nru ffmpeg-4.2.2/libavformat/rtspdec.c ffmpeg-4.4/libavformat/rtspdec.c --- ffmpeg-4.2.2/libavformat/rtspdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtspdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -97,7 +97,7 @@ const char *extracontent, uint16_t seq) { RTSPState *rt = s->priv_data; - char message[4096]; + char message[MAX_URL_SIZE]; int index = 0; while (status_messages[index].code) { if (status_messages[index].code == code) { @@ -143,7 +143,7 @@ const char *method) { RTSPState *rt = s->priv_data; - char rbuf[1024]; + char rbuf[MAX_URL_SIZE]; int rbuflen, ret; do { ret = read_line(s, rbuf, sizeof(rbuf), &rbuflen); @@ -172,7 +172,7 @@ { RTSPState *rt = s->priv_data; RTSPMessageHeader request = { 0 }; - char sdp[4096]; + char sdp[SDP_MAX_SIZE]; int ret; ret = rtsp_read_request(s, &request, "ANNOUNCE"); @@ -232,9 +232,9 @@ RTSPState *rt = s->priv_data; RTSPMessageHeader request = { 0 }; int ret = 0; - char url[1024]; + char url[MAX_URL_SIZE]; RTSPStream *rtsp_st; - char responseheaders[1024]; + char responseheaders[MAX_URL_SIZE]; int localport = -1; int transportidx = 0; int streamid = 0; @@ -274,6 +274,17 @@ rtsp_st = rt->rtsp_streams[streamid]; localport = rt->rtp_port_min; + /* check if the stream has already been setup */ + if (rtsp_st->transport_priv) { + if (CONFIG_RTPDEC && rt->transport == RTSP_TRANSPORT_RDT) + ff_rdt_parse_close(rtsp_st->transport_priv); + else if (CONFIG_RTPDEC && rt->transport == RTSP_TRANSPORT_RTP) + ff_rtp_parse_close(rtsp_st->transport_priv); + rtsp_st->transport_priv = NULL; + } + if (rtsp_st->rtp_handle) + ffurl_closep(&rtsp_st->rtp_handle); + if (request.transports[0].lower_transport == RTSP_LOWER_TRANSPORT_TCP) { rt->lower_transport = RTSP_LOWER_TRANSPORT_TCP; if ((ret = ff_rtsp_open_transport_ctx(s, rtsp_st))) { @@ -289,11 +300,9 @@ } else { do { AVDictionary *opts = NULL; - char buf[256]; - snprintf(buf, sizeof(buf), "%d", rt->buffer_size); - av_dict_set(&opts, "buffer_size", buf, 0); + av_dict_set_int(&opts, "buffer_size", rt->buffer_size, 0); ff_url_join(url, sizeof(url), "rtp", NULL, host, localport, NULL); - av_log(s, AV_LOG_TRACE, "Opening: %s", url); + av_log(s, AV_LOG_TRACE, "Opening: %s\n", url); ret = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, &s->interrupt_callback, &opts, s->protocol_whitelist, s->protocol_blacklist, NULL); @@ -306,7 +315,7 @@ return ret; } - av_log(s, AV_LOG_TRACE, "Listening on: %d", + av_log(s, AV_LOG_TRACE, "Listening on: %d\n", ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle)); if ((ret = ff_rtsp_open_transport_ctx(s, rtsp_st))) { rtsp_send_reply(s, RTSP_STATUS_TRANSPORT, NULL, request.seq); @@ -342,7 +351,7 @@ RTSPState *rt = s->priv_data; RTSPMessageHeader request = { 0 }; int ret = 0; - char responseheaders[1024]; + char responseheaders[MAX_URL_SIZE]; ret = rtsp_read_request(s, &request, "RECORD"); if (ret) @@ -465,7 +474,7 @@ int ff_rtsp_parse_streaming_commands(AVFormatContext *s) { RTSPState *rt = s->priv_data; - unsigned char rbuf[4096]; + unsigned char rbuf[MAX_URL_SIZE]; unsigned char method[10]; char uri[500]; int ret; @@ -476,6 +485,7 @@ ret = read_line(s, rbuf, sizeof(rbuf), &rbuflen); if (ret < 0) return ret; + av_log(s, AV_LOG_TRACE, "Parsing[%d]: %s\n", rbuflen, rbuf); ret = parse_command_line(s, rbuf, rbuflen, uri, sizeof(uri), method, sizeof(method), &methodcode); if (ret) { @@ -507,7 +517,7 @@ RTSPState *rt = s->priv_data; RTSPMessageHeader reply1, *reply = &reply1; int i; - char cmd[1024]; + char cmd[MAX_URL_SIZE]; av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state); rt->nb_byes = 0; @@ -593,7 +603,7 @@ int ff_rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply) { RTSPState *rt = s->priv_data; - char cmd[1024]; + char cmd[MAX_URL_SIZE]; unsigned char *content = NULL; int ret; @@ -636,12 +646,15 @@ int default_port = RTSP_DEFAULT_PORT; char tcpname[500]; const char *lower_proto = "tcp"; - unsigned char rbuf[4096]; + unsigned char rbuf[MAX_URL_SIZE]; unsigned char method[10]; int rbuflen = 0; int ret; enum RTSPMethod methodcode; + if (!ff_network_init()) + return AVERROR(EIO); + /* extract hostname and port */ av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host), &port, path, sizeof(path), s->url); @@ -666,19 +679,20 @@ &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL)) { av_log(s, AV_LOG_ERROR, "Unable to open RTSP for listening\n"); - return ret; + goto fail; } rt->state = RTSP_STATE_IDLE; rt->rtsp_hd_out = rt->rtsp_hd; for (;;) { /* Wait for incoming RTSP messages */ ret = read_line(s, rbuf, sizeof(rbuf), &rbuflen); if (ret < 0) - return ret; + goto fail; + av_log(s, AV_LOG_TRACE, "Parsing[%d]: %s\n", rbuflen, rbuf); ret = parse_command_line(s, rbuf, rbuflen, uri, sizeof(uri), method, sizeof(method), &methodcode); if (ret) { av_log(s, AV_LOG_ERROR, "RTSP: Unexpected Command\n"); - return ret; + goto fail; } if (methodcode == ANNOUNCE) { @@ -693,10 +707,15 @@ } else if (methodcode == SETUP) ret = rtsp_read_setup(s, host, uri); if (ret) { - ffurl_close(rt->rtsp_hd); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } } +fail: + ff_rtsp_close_streams(s); + ff_rtsp_close_connections(s); + ff_network_close(); + return ret; } static int rtsp_probe(const AVProbeData *p) @@ -705,6 +724,7 @@ #if CONFIG_TLS_PROTOCOL av_strstart(p->filename, "rtsps:", NULL) || #endif + av_strstart(p->filename, "satip:", NULL) || av_strstart(p->filename, "rtsp:", NULL)) return AVPROBE_SCORE_MAX; return 0; @@ -729,22 +749,26 @@ rt->real_setup_cache = !s->nb_streams ? NULL : av_mallocz_array(s->nb_streams, 2 * sizeof(*rt->real_setup_cache)); - if (!rt->real_setup_cache && s->nb_streams) - return AVERROR(ENOMEM); + if (!rt->real_setup_cache && s->nb_streams) { + ret = AVERROR(ENOMEM); + goto fail; + } rt->real_setup = rt->real_setup_cache + s->nb_streams; if (rt->initial_pause) { /* do not start immediately */ } else { - if ((ret = rtsp_read_play(s)) < 0) { - ff_rtsp_close_streams(s); - ff_rtsp_close_connections(s); - return ret; - } + ret = rtsp_read_play(s); + if (ret < 0) + goto fail; } } return 0; + +fail: + rtsp_read_close(s); + return ret; } int ff_rtsp_tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, @@ -770,7 +794,7 @@ } ret = ffurl_read_complete(rt->rtsp_hd, buf, 3); if (ret != 3) - return -1; + return AVERROR(EIO); id = buf[0]; len = AV_RB16(buf + 1); av_log(s, AV_LOG_TRACE, "id=%d len=%d\n", id, len); @@ -779,10 +803,10 @@ /* get the data */ ret = ffurl_read_complete(rt->rtsp_hd, buf, len); if (ret != len) - return -1; + return AVERROR(EIO); if (rt->transport == RTSP_TRANSPORT_RDT && - ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0) - return -1; + (ret = ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL)) < 0) + return ret; /* find the matching stream */ for (i = 0; i < rt->nb_rtsp_streams; i++) { @@ -815,7 +839,7 @@ RTSPState *rt = s->priv_data; int ret; RTSPMessageHeader reply1, *reply = &reply1; - char cmd[1024]; + char cmd[MAX_URL_SIZE]; retry: if (rt->server_type == RTSP_SERVER_REAL) { diff -Nru ffmpeg-4.2.2/libavformat/rtspenc.c ffmpeg-4.4/libavformat/rtspenc.c --- ffmpeg-4.2.2/libavformat/rtspenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtspenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -34,7 +34,6 @@ #include "libavutil/time.h" #include "url.h" -#define SDP_MAX_SIZE 16384 static const AVClass rtsp_muxer_class = { .class_name = "RTSP muxer", @@ -50,7 +49,7 @@ int i; char *sdp; AVFormatContext sdp_ctx, *ctx_array[1]; - char url[1024]; + char url[MAX_URL_SIZE]; if (s->start_time_realtime == 0 || s->start_time_realtime == AV_NOPTS_VALUE) s->start_time_realtime = av_gettime(); @@ -112,7 +111,7 @@ { RTSPState *rt = s->priv_data; RTSPMessageHeader reply1, *reply = &reply1; - char cmd[1024]; + char cmd[MAX_URL_SIZE]; snprintf(cmd, sizeof(cmd), "Range: npt=0.000-\r\n"); diff -Nru ffmpeg-4.2.2/libavformat/rtsp.h ffmpeg-4.4/libavformat/rtsp.h --- ffmpeg-4.2.2/libavformat/rtsp.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/rtsp.h 2021-04-08 21:28:40.000000000 +0000 @@ -27,6 +27,7 @@ #include "rtpdec.h" #include "network.h" #include "httpauth.h" +#include "internal.h" #include "libavutil/log.h" #include "libavutil/opt.h" @@ -78,6 +79,7 @@ #define RTSP_DEFAULT_AUDIO_SAMPLERATE 44100 #define RTSP_RTP_PORT_MIN 5000 #define RTSP_RTP_PORT_MAX 65000 +#define SDP_MAX_SIZE 16384 /** * This describes a single item in the "Transport:" line of one stream as @@ -186,6 +188,11 @@ * Content type header */ char content_type[64]; + + /** + * SAT>IP com.ses.streamID header + */ + char stream_id[64]; } RTSPMessageHeader; /** @@ -208,6 +215,7 @@ RTSP_SERVER_RTP, /**< Standards-compliant RTP-server */ RTSP_SERVER_REAL, /**< Realmedia-style server */ RTSP_SERVER_WMS, /**< Windows Media server */ + RTSP_SERVER_SATIP,/**< SAT>IP server */ RTSP_SERVER_NB }; @@ -315,7 +323,7 @@ /** some MS RTSP streams contain a URL in the SDP that we need to use * for all subsequent RTSP requests, rather than the input URI; in * other cases, this is a copy of AVFormatContext->filename. */ - char control_uri[1024]; + char control_uri[MAX_URL_SIZE]; /** The following are used for parsing raw mpegts in udp */ //@{ @@ -421,6 +429,7 @@ #define RTSP_FLAG_RTCP_TO_SOURCE 0x8 /**< Send RTCP packets to the source address of received packets. */ #define RTSP_FLAG_PREFER_TCP 0x10 /**< Try RTP via TCP first if possible. */ +#define RTSP_FLAG_SATIP_RAW 0x20 /**< Export SAT>IP stream as raw MPEG-TS */ typedef struct RTSPSource { char addr[128]; /**< Source-specific multicast include source IP address (from SDP content) */ @@ -443,7 +452,7 @@ * for the selected transport. Only used for TCP. */ int interleaved_min, interleaved_max; - char control_url[1024]; /**< url for this stream (from SDP) */ + char control_url[MAX_URL_SIZE]; /**< url for this stream (from SDP) */ /** The following are used only in SDP, not RTSP */ //@{ diff -Nru ffmpeg-4.2.2/libavformat/s337m.c ffmpeg-4.4/libavformat/s337m.c --- ffmpeg-4.2.2/libavformat/s337m.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/s337m.c 2020-07-11 10:39:30.000000000 +0000 @@ -31,7 +31,7 @@ #define IS_24LE_MARKER(state) ((state & 0xFFFFFFFFFFFF) == MARKER_24LE) #define IS_LE_MARKER(state) (IS_16LE_MARKER(state) || IS_20LE_MARKER(state) || IS_24LE_MARKER(state)) -static int s337m_get_offset_and_codec(AVFormatContext *s, +static int s337m_get_offset_and_codec(void *avc, uint64_t state, int data_type, int data_size, int *offset, enum AVCodecID *codec) @@ -50,8 +50,8 @@ } if ((data_type & 0x1F) != 0x1C) { - if (s) - avpriv_report_missing_feature(s, "Data type %#x in SMPTE 337M", data_type & 0x1F); + if (avc) + avpriv_report_missing_feature(avc, "Data type %#x in SMPTE 337M", data_type & 0x1F); return AVERROR_PATCHWELCOME; } @@ -72,8 +72,8 @@ *offset = 1601; break; default: - if (s) - avpriv_report_missing_feature(s, "Dolby E data size %d in SMPTE 337M", data_size); + if (avc) + avpriv_report_missing_feature(avc, "Dolby E data size %d in SMPTE 337M", data_size); return AVERROR_PATCHWELCOME; } @@ -174,7 +174,6 @@ pkt->pos = pos; if (avio_read(pb, pkt->data, pkt->size) < pkt->size) { - av_packet_unref(pkt); return AVERROR_EOF; } @@ -186,7 +185,6 @@ if (!s->nb_streams) { AVStream *st = avformat_new_stream(s, NULL); if (!st) { - av_packet_unref(pkt); return AVERROR(ENOMEM); } st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; diff -Nru ffmpeg-4.2.2/libavformat/samidec.c ffmpeg-4.4/libavformat/samidec.c --- ffmpeg-4.2.2/libavformat/samidec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/samidec.c 2021-04-08 21:28:40.000000000 +0000 @@ -89,12 +89,19 @@ sub = ff_subtitles_queue_insert(&sami->q, buf.str, buf.len, !is_sync); if (!sub) { res = AVERROR(ENOMEM); + av_bprint_finalize(&hdr_buf, NULL); goto end; } if (is_sync) { const char *p = ff_smil_get_attr_ptr(buf.str, "Start"); sub->pos = pos; sub->pts = p ? strtol(p, NULL, 10) : 0; + if (sub->pts <= INT64_MIN/2 || sub->pts >= INT64_MAX/2) { + res = AVERROR_PATCHWELCOME; + av_bprint_finalize(&hdr_buf, NULL); + goto end; + } + sub->duration = -1; } } @@ -108,6 +115,8 @@ ff_subtitles_queue_finalize(s, &sami->q); end: + if (res < 0) + ff_subtitles_queue_clean(&sami->q); av_bprint_finalize(&buf, NULL); return res; } diff -Nru ffmpeg-4.2.2/libavformat/sapdec.c ffmpeg-4.4/libavformat/sapdec.c --- ffmpeg-4.2.2/libavformat/sapdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/sapdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -54,8 +54,7 @@ struct SAPState *sap = s->priv_data; if (sap->sdp_ctx) avformat_close_input(&sap->sdp_ctx); - if (sap->ann_fd) - ffurl_close(sap->ann_fd); + ffurl_closep(&sap->ann_fd); av_freep(&sap->sdp); ff_network_close(); return 0; @@ -142,6 +141,10 @@ } sap->sdp = av_strdup(&recvbuf[pos]); + if (!sap->sdp) { + ret = AVERROR(ENOMEM); + goto fail; + } break; } @@ -221,7 +224,6 @@ int i = s->nb_streams; AVStream *st = avformat_new_stream(s, NULL); if (!st) { - av_packet_unref(pkt); return AVERROR(ENOMEM); } st->id = i; diff -Nru ffmpeg-4.2.2/libavformat/sapenc.c ffmpeg-4.4/libavformat/sapenc.c --- ffmpeg-4.2.2/libavformat/sapenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/sapenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -60,8 +60,7 @@ } av_freep(&sap->ann); - if (sap->ann_fd) - ffurl_close(sap->ann_fd); + ffurl_closep(&sap->ann_fd); ff_network_close(); return 0; } diff -Nru ffmpeg-4.2.2/libavformat/sbgdec.c ffmpeg-4.4/libavformat/sbgdec.c --- ffmpeg-4.2.2/libavformat/sbgdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/sbgdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -181,6 +181,7 @@ char *end; int hours, minutes; double seconds = 0; + int64_t ts = 0; if (*cur < '0' || *cur > '9') return 0; @@ -196,8 +197,9 @@ seconds = strtod(cur + 1, &end); if (end > cur + 1) cur = end; + ts = av_clipd(seconds * AV_TIME_BASE, INT64_MIN/2, INT64_MAX/2); } - *rtime = (hours * 3600LL + minutes * 60LL + seconds) * AV_TIME_BASE; + *rtime = av_sat_add64((hours * 3600LL + minutes * 60LL) * AV_TIME_BASE, ts); return cur - str; } @@ -474,6 +476,8 @@ while (lex_char(p, '+')) { if (!lex_time(p, &dt)) return AVERROR_INVALIDDATA; + if (av_sat_add64(rel, dt) - dt != rel) + return AVERROR_INVALIDDATA; rel += dt; r = 1; } @@ -536,6 +540,9 @@ return AVERROR_INVALIDDATA; } ts.type = p->current_time.type; + + if (av_sat_add64(p->current_time.t, rel_ts) != p->current_time.t + (uint64_t)rel_ts) + return AVERROR_INVALIDDATA; ts.t = p->current_time.t + rel_ts; r = parse_fade(p, &fade); if (r < 0) @@ -884,7 +891,7 @@ return size; } -static void expand_timestamps(void *log, struct sbg_script *s) +static int expand_timestamps(void *log, struct sbg_script *s) { int i, nb_rel = 0; int64_t now, cur_ts, delta = 0; @@ -932,10 +939,13 @@ AV_NOPTS_VALUE; /* may be overridden later by -E option */ cur_ts = now; for (i = 0; i < s->nb_tseq; i++) { + if (av_sat_add64(s->tseq[i].ts.t, delta) != s->tseq[i].ts.t + (uint64_t)delta) + return AVERROR_INVALIDDATA; if (s->tseq[i].ts.t + delta < cur_ts) delta += DAY_TS; cur_ts = s->tseq[i].ts.t += delta; } + return 0; } static int expand_tseq(void *log, struct sbg_script *s, int *nb_ev_max, @@ -988,7 +998,9 @@ { int i, r, nb_events_max = 0; - expand_timestamps(log, s); + r = expand_timestamps(log, s); + if (r < 0) + return r; for (i = 0; i < s->nb_tseq; i++) { r = expand_tseq(log, s, &nb_events_max, 0, &s->tseq[i]); if (r < 0) @@ -1327,7 +1339,7 @@ static int encode_intervals(struct sbg_script *s, AVCodecParameters *par, struct ws_intervals *inter) { - int i, edata_size = 4; + int i, edata_size = 4, ret; uint8_t *edata; for (i = 0; i < inter->nb_inter; i++) { @@ -1336,8 +1348,8 @@ if (edata_size < 0) return AVERROR(ENOMEM); } - if (ff_alloc_extradata(par, edata_size)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(par, edata_size)) < 0) + return ret; edata = par->extradata; #define ADD_EDATA32(v) do { AV_WL32(edata, (v)); edata += 4; } while(0) @@ -1411,6 +1423,11 @@ if (r < 0) goto fail; + if (script.end_ts != AV_NOPTS_VALUE && script.end_ts < script.start_ts) { + r = AVERROR_INVALIDDATA; + goto fail; + } + st = avformat_new_stream(avf, NULL); if (!st) return AVERROR(ENOMEM); @@ -1446,6 +1463,7 @@ static int sbg_read_packet(AVFormatContext *avf, AVPacket *packet) { int64_t ts, end_ts; + int ret; ts = avf->streams[0]->cur_dts; end_ts = ts + avf->streams[0]->codecpar->frame_size; @@ -1454,8 +1472,8 @@ end_ts); if (end_ts <= ts) return AVERROR_EOF; - if (av_new_packet(packet, 12) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(packet, 12)) < 0) + return ret; packet->dts = packet->pts = ts; packet->duration = end_ts - ts; AV_WL64(packet->data + 0, ts); diff -Nru ffmpeg-4.2.2/libavformat/sccdec.c ffmpeg-4.4/libavformat/sccdec.c --- ffmpeg-4.2.2/libavformat/sccdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/sccdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -22,6 +22,7 @@ #include "avformat.h" #include "internal.h" #include "subtitles.h" +#include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" @@ -62,9 +63,9 @@ { SCCContext *scc = s->priv_data; AVStream *st = avformat_new_stream(s, NULL); - char line[4096], line2[4096]; - int count = 0, ret = 0; - ptrdiff_t len2, len; + char line2[4096], line[4096]; + int64_t pos, ts, next_ts = AV_NOPTS_VALUE; + ptrdiff_t len; uint8_t out[4096]; FFTextReader tr; @@ -76,79 +77,107 @@ st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codecpar->codec_id = AV_CODEC_ID_EIA_608; - while (!ff_text_eof(&tr)) { - const int64_t pos = ff_text_pos(&tr); + while (!ff_text_eof(&tr) || next_ts == AV_NOPTS_VALUE || line2[0]) { char *saveptr = NULL, *lline; - int hh1, mm1, ss1, fs1, i; - int hh2, mm2, ss2, fs2; - int64_t ts_start, ts_end; + int hh, mm, ss, fs, i; AVPacket *sub; - if (count == 0) { + if (next_ts == AV_NOPTS_VALUE) { while (!ff_text_eof(&tr)) { len = ff_subtitles_read_line(&tr, line, sizeof(line)); - if (len > 13) + if (len <= 13) + continue; + if (!strncmp(line, "Scenarist_SCC V1.0", 18)) + continue; + if (av_sscanf(line, "%d:%d:%d%*[:;]%d", &hh, &mm, &ss, &fs) == 4) break; } - } - if (!strncmp(line, "Scenarist_SCC V1.0", 18)) - continue; - if (sscanf(line, "%d:%d:%d%*[:;]%d", &hh1, &mm1, &ss1, &fs1) != 4) - continue; - - ts_start = (hh1 * 3600LL + mm1 * 60LL + ss1) * 1000LL + fs1 * 33; - - while (!ff_text_eof(&tr)) { - len2 = ff_subtitles_read_line(&tr, line2, sizeof(line2)); - if (len2 > 13) - break; + ts = (hh * 3600LL + mm * 60LL + ss) * 1000LL + fs * 33LL; + + while (!ff_text_eof(&tr)) { + len = ff_subtitles_read_line(&tr, line2, sizeof(line2)); + if (len <= 13) + continue; + + if (av_sscanf(line2, "%d:%d:%d%*[:;]%d", &hh, &mm, &ss, &fs) == 4) + break; + } + } else { + memmove(line, line2, sizeof(line)); + line2[0] = 0; + + while (!ff_text_eof(&tr)) { + len = ff_subtitles_read_line(&tr, line2, sizeof(line2)); + if (len <= 13) + continue; + + if (av_sscanf(line2, "%d:%d:%d%*[:;]%d", &hh, &mm, &ss, &fs) == 4) + break; + } } - if (sscanf(line2, "%d:%d:%d%*[:;]%d", &hh2, &mm2, &ss2, &fs2) != 4) - continue; - ts_end = (hh2 * 3600LL + mm2 * 60LL + ss2) * 1000LL + fs2 * 33; - count++; + next_ts = (hh * 3600LL + mm * 60LL + ss) * 1000LL + fs * 33LL; -try_again: + pos = ff_text_pos(&tr); lline = (char *)&line; lline += 12; for (i = 0; i < 4095; i += 3) { char *ptr = av_strtok(lline, " ", &saveptr); char c1, c2, c3, c4; + uint8_t o1, o2; if (!ptr) break; - if (sscanf(ptr, "%c%c%c%c", &c1, &c2, &c3, &c4) != 4) + if (av_sscanf(ptr, "%c%c%c%c", &c1, &c2, &c3, &c4) != 4) break; + o1 = convert(c2) | (convert(c1) << 4); + o2 = convert(c4) | (convert(c3) << 4); lline = NULL; + + if (i > 12 && o1 == 0x94 && o2 == 0x20 && saveptr && + (av_strncasecmp(saveptr, "942f", 4) && !av_strncasecmp(saveptr, "942c", 4))) { + + out[i] = 0; + + sub = ff_subtitles_queue_insert(&scc->q, out, i, 0); + if (!sub) + goto fail; + + sub->pos = pos; + pos += i; + sub->pts = ts; + sub->duration = i * 11; + ts += sub->duration; + i = 0; + } + out[i+0] = 0xfc; - out[i+1] = convert(c2) | (convert(c1) << 4); - out[i+2] = convert(c4) | (convert(c3) << 4); + out[i+1] = o1; + out[i+2] = o2; } + out[i] = 0; sub = ff_subtitles_queue_insert(&scc->q, out, i, 0); if (!sub) - return AVERROR(ENOMEM); + goto fail; sub->pos = pos; - sub->pts = ts_start; - sub->duration = FFMAX(1200, ts_end - ts_start); - memmove(line, line2, sizeof(line)); - line2[0] = 0; - FFSWAP(ptrdiff_t, len, len2); + sub->pts = ts; + sub->duration = next_ts - ts; + ts = next_ts; } - if (line[0]) - goto try_again; - ff_subtitles_queue_finalize(s, &scc->q); - return ret; + return 0; +fail: + ff_subtitles_queue_clean(&scc->q); + return AVERROR(ENOMEM); } static int scc_read_packet(AVFormatContext *s, AVPacket *pkt) diff -Nru ffmpeg-4.2.2/libavformat/sdp.c ffmpeg-4.4/libavformat/sdp.c --- ffmpeg-4.2.2/libavformat/sdp.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/sdp.c 2021-04-08 21:28:40.000000000 +0000 @@ -212,7 +212,7 @@ p += strlen(p); r = r1; } - if (sps && sps_end - sps >= 4) { + if (sps && sps_end - sps >= 4 && p - psets <= MAX_PSET_SIZE - strlen(profile_string) - 7) { memcpy(p, profile_string, strlen(profile_string)); p += strlen(p); ff_data_to_hex(p, sps + 1, 3, 0); @@ -704,6 +704,8 @@ case AV_CODEC_ID_SPEEX: av_strlcatf(buff, size, "a=rtpmap:%d speex/%d\r\n", payload_type, p->sample_rate); +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS if (st->codec) { const char *mode; uint64_t vad_option; @@ -718,6 +720,8 @@ av_strlcatf(buff, size, "a=fmtp:%d vbr=%s\r\n", payload_type, mode); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif break; case AV_CODEC_ID_OPUS: /* The opus RTP draft says that all opus streams MUST be declared diff -Nru ffmpeg-4.2.2/libavformat/sdr2.c ffmpeg-4.4/libavformat/sdr2.c --- ffmpeg-4.2.2/libavformat/sdr2.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/sdr2.c 2020-07-11 10:39:30.000000000 +0000 @@ -90,12 +90,11 @@ avio_skip(s->pb, 30); if (pos == FIRST) { - if (av_new_packet(pkt, next - 52 + 24) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, next - 52 + 24)) < 0) + return ret; memcpy(pkt->data, header, 24); ret = avio_read(s->pb, pkt->data + 24, next - 52); if (ret < 0) { - av_packet_unref(pkt); return ret; } av_shrink_packet(pkt, ret + 24); diff -Nru ffmpeg-4.2.2/libavformat/sdsdec.c ffmpeg-4.4/libavformat/sdsdec.c --- ffmpeg-4.2.2/libavformat/sdsdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/sdsdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -43,7 +43,7 @@ int i; for (i = 0; i < 120; i += 2) { - unsigned sample = (src[i + 0] << 25) + (src[i + 1] << 18); + unsigned sample = ((unsigned)src[i + 0] << 25) + ((unsigned)src[i + 1] << 18); dst[i / 2] = sample; } @@ -56,7 +56,7 @@ for (i = 0; i < 120; i += 3) { unsigned sample; - sample = (src[i + 0] << 25) | (src[i + 1] << 18) | (src[i + 2] << 11); + sample = ((unsigned)src[i + 0] << 25) | ((unsigned)src[i + 1] << 18) | ((unsigned)src[i + 2] << 11); dst[i / 3] = sample; } } @@ -68,7 +68,7 @@ for (i = 0; i < 120; i += 4) { unsigned sample; - sample = (src[i + 0] << 25) | (src[i + 1] << 18) | (src[i + 2] << 11) | (src[i + 3] << 4); + sample = ((unsigned)src[i + 0] << 25) | ((unsigned)src[i + 1] << 18) | ((unsigned)src[i + 2] << 11) | ((unsigned)src[i + 3] << 4); dst[i / 4] = sample; } } diff -Nru ffmpeg-4.2.2/libavformat/segafilm.c ffmpeg-4.4/libavformat/segafilm.c --- ffmpeg-4.2.2/libavformat/segafilm.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/segafilm.c 2021-04-08 21:28:40.000000000 +0000 @@ -40,8 +40,8 @@ typedef struct film_sample { int stream; - int64_t sample_offset; unsigned int sample_size; + int64_t sample_offset; int64_t pts; int keyframe; } film_sample; @@ -144,8 +144,11 @@ film->video_type = AV_CODEC_ID_NONE; } + if (film->video_type == AV_CODEC_ID_NONE && film->audio_type == AV_CODEC_ID_NONE) + return AVERROR_INVALIDDATA; + /* initialize the decoder streams */ - if (film->video_type) { + if (film->video_type != AV_CODEC_ID_NONE) { st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); @@ -166,7 +169,7 @@ } } - if (film->audio_type) { + if (film->audio_type != AV_CODEC_ID_NONE) { st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); @@ -241,7 +244,7 @@ film->sample_table[i].pts = AV_RB32(&scratch[8]) & 0x7FFFFFFF; film->sample_table[i].keyframe = (scratch[8] & 0x80) ? 0 : AVINDEX_KEYFRAME; video_frame_counter++; - if (film->video_type) + if (film->video_type != AV_CODEC_ID_NONE) av_add_index_entry(s->streams[film->video_stream_index], film->sample_table[i].sample_offset, film->sample_table[i].pts, @@ -250,10 +253,10 @@ } } - if (film->audio_type) + if (film->audio_type != AV_CODEC_ID_NONE) s->streams[film->audio_stream_index]->duration = audio_frame_counter; - if (film->video_type) + if (film->video_type != AV_CODEC_ID_NONE) s->streams[film->video_stream_index]->duration = video_frame_counter; film->current_sample = 0; diff -Nru ffmpeg-4.2.2/libavformat/segafilmenc.c ffmpeg-4.4/libavformat/segafilmenc.c --- ffmpeg-4.2.2/libavformat/segafilmenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/segafilmenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -29,88 +29,28 @@ * http://wiki.multimedia.cx/index.php?title=Sega_FILM */ +#include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" +#include "libavcodec/bytestream.h" #include "avformat.h" #include "internal.h" #include "avio_internal.h" -typedef struct FILMPacket { - int audio; - int keyframe; - int32_t pts; - int32_t duration; - int32_t size; - int32_t index; - struct FILMPacket *next; -} FILMPacket; - typedef struct FILMOutputContext { - const AVClass *class; + AVIOContext *header; + unsigned index; int audio_index; int video_index; - int64_t stab_pos; - FILMPacket *start; - FILMPacket *last; - int64_t packet_count; } FILMOutputContext; -static int film_write_packet_to_header(AVFormatContext *format_context, FILMPacket *pkt) -{ - AVIOContext *pb = format_context->pb; - /* The bits in these two 32-bit integers contain info about the contents of this sample */ - int32_t info1 = 0; - int32_t info2 = 0; - - if (pkt->audio) { - /* Always the same, carries no more information than "this is audio" */ - info1 = 0xFFFFFFFF; - info2 = 1; - } else { - info1 = pkt->pts; - info2 = pkt->duration; - /* The top bit being set indicates a key frame */ - if (!pkt->keyframe) - info1 |= (1 << 31); - } - - /* Write the 16-byte sample info packet to the STAB chunk in the header */ - avio_wb32(pb, pkt->index); - avio_wb32(pb, pkt->size); - avio_wb32(pb, info1); - avio_wb32(pb, info2); - - return 0; -} - static int film_write_packet(AVFormatContext *format_context, AVPacket *pkt) { - FILMPacket *metadata; AVIOContext *pb = format_context->pb; FILMOutputContext *film = format_context->priv_data; - int encoded_buf_size = 0; + int encoded_buf_size, size = pkt->size; + uint32_t info1, info2; enum AVCodecID codec_id; - /* Track the metadata used to write the header and add it to the linked list */ - metadata = av_mallocz(sizeof(FILMPacket)); - if (!metadata) - return AVERROR(ENOMEM); - metadata->audio = pkt->stream_index == film->audio_index; - metadata->keyframe = pkt->flags & AV_PKT_FLAG_KEY; - metadata->pts = pkt->pts; - metadata->duration = pkt->duration; - metadata->size = pkt->size; - if (film->last == NULL) { - metadata->index = 0; - } else { - metadata->index = film->last->index + film->last->size; - film->last->next = metadata; - } - metadata->next = NULL; - if (film->start == NULL) - film->start = metadata; - film->packet_count++; - film->last = metadata; - codec_id = format_context->streams[pkt->stream_index]->codecpar->codec_id; /* Sega Cinepak has an extra two-byte header; write dummy data there, @@ -121,15 +61,14 @@ if (encoded_buf_size != pkt->size && (pkt->size % encoded_buf_size) != 0) { avio_write(pb, pkt->data, pkt->size); } else { - uint8_t padding[2] = {0, 0}; /* In Sega Cinepak, the reported size in the Cinepak header is * 8 bytes too short. However, the size in the STAB section of the header * is correct, taking into account the extra two bytes. */ AV_WB24(&pkt->data[1], pkt->size - 8 + 2); - metadata->size += 2; + size += 2; avio_write(pb, pkt->data, 10); - avio_write(pb, padding, 2); + avio_wb16(pb, 0); avio_write(pb, &pkt->data[10], pkt->size - 10); } } else { @@ -137,7 +76,27 @@ avio_write(pb, pkt->data, pkt->size); } - return 0; + /* Add the 16-byte sample info entry to the dynamic buffer + * for the STAB chunk in the header */ + pb = film->header; + avio_wb32(pb, film->index); + film->index += size; + avio_wb32(pb, size); + if (film->audio_index == pkt->stream_index) { + /* Always the same, carries no more information than "this is audio" */ + info1 = 0xFFFFFFFF; + info2 = 1; + } else { + info1 = pkt->pts; + info2 = pkt->duration; + /* The top bit being set indicates a key frame */ + if (!(pkt->flags & AV_PKT_FLAG_KEY)) + info1 |= 1U << 31; + } + avio_wb32(pb, info1); + avio_wb32(pb, info2); + + return pb->error; } static int get_audio_codec_id(enum AVCodecID codec_id) @@ -147,10 +106,8 @@ case AV_CODEC_ID_PCM_S8_PLANAR: case AV_CODEC_ID_PCM_S16BE_PLANAR: return 0; - break; case AV_CODEC_ID_ADPCM_ADX: return 2; - break; default: return -1; } @@ -158,14 +115,11 @@ static int film_init(AVFormatContext *format_context) { - AVStream *audio = NULL; FILMOutputContext *film = format_context->priv_data; + int ret; + film->audio_index = -1; film->video_index = -1; - film->stab_pos = 0; - film->packet_count = 0; - film->start = NULL; - film->last = NULL; for (int i = 0; i < format_context->nb_streams; i++) { AVStream *st = format_context->streams[i]; @@ -174,8 +128,12 @@ av_log(format_context, AV_LOG_ERROR, "Sega FILM allows a maximum of one audio stream.\n"); return AVERROR(EINVAL); } + if (get_audio_codec_id(st->codecpar->codec_id) < 0) { + av_log(format_context, AV_LOG_ERROR, + "Incompatible audio stream format.\n"); + return AVERROR(EINVAL); + } film->audio_index = i; - audio = st; } if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -183,37 +141,48 @@ av_log(format_context, AV_LOG_ERROR, "Sega FILM allows a maximum of one video stream.\n"); return AVERROR(EINVAL); } + if (st->codecpar->codec_id != AV_CODEC_ID_CINEPAK && + st->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO) { + av_log(format_context, AV_LOG_ERROR, + "Incompatible video stream format.\n"); + return AVERROR(EINVAL); + } + if (st->codecpar->format != AV_PIX_FMT_RGB24) { + av_log(format_context, AV_LOG_ERROR, + "Pixel format must be rgb24.\n"); + return AVERROR(EINVAL); + } film->video_index = i; } - - if (film->video_index == -1) { - av_log(format_context, AV_LOG_ERROR, "No video stream present.\n"); - return AVERROR(EINVAL); - } } - if (audio != NULL && get_audio_codec_id(audio->codecpar->codec_id) < 0) { - av_log(format_context, AV_LOG_ERROR, "Incompatible audio stream format.\n"); + if (film->video_index == -1) { + av_log(format_context, AV_LOG_ERROR, "No video stream present.\n"); return AVERROR(EINVAL); } + if ((ret = avio_open_dyn_buf(&film->header)) < 0) + return ret; + ffio_fill(film->header, 0, 16 + 32 + 16); return 0; } -static int shift_data(AVFormatContext *format_context, int64_t shift_size) +static int write_header(AVFormatContext *format_context, uint8_t *header, + unsigned header_size) { int ret = 0; - int64_t pos, pos_end = avio_tell(format_context->pb); + 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(shift_size * 2); + buf = av_malloc(header_size); if (!buf) return AVERROR(ENOMEM); read_buf[0] = buf; - read_buf[1] = buf + shift_size; + 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. */ @@ -226,25 +195,20 @@ return ret; } - /* mark the end of the shift to up to the last data we wrote, and get ready - * for writing */ - pos_end = avio_tell(format_context->pb); - avio_seek(format_context->pb, shift_size, SEEK_SET); + /* 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); /* start reading at where the new header will be placed */ avio_seek(read_pb, 0, SEEK_SET); - pos = avio_tell(read_pb); - -#define READ_BLOCK do { \ - read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], shift_size); \ - read_buf_id ^= 1; \ -} while (0) - /* shift data by chunk of at most shift_size */ - READ_BLOCK; + /* shift data by chunk of at most header_size */ do { int n; - READ_BLOCK; + 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; @@ -260,97 +224,75 @@ static int film_write_header(AVFormatContext *format_context) { int ret = 0; - int64_t sample_table_size, stabsize, headersize; - int8_t audio_codec; - AVIOContext *pb = format_context->pb; + unsigned stabsize, headersize, packet_count; FILMOutputContext *film = format_context->priv_data; - FILMPacket *prev, *packet; - AVStream *audio = NULL; AVStream *video = NULL; + uint8_t *header, *ptr; /* Calculate how much we need to reserve for the header; * this is the amount the rest of the data will be shifted up by. */ - sample_table_size = film->packet_count * 16; - stabsize = 16 + sample_table_size; + headersize = avio_get_dyn_buf(film->header, &header); + if (headersize < 64) { + av_assert1(film->header->error < 0); + return film->header->error; + } + packet_count = (headersize - 64) / 16; + stabsize = 16 + 16 * packet_count; headersize = 16 + /* FILM header base */ 32 + /* FDSC chunk */ stabsize; - ret = shift_data(format_context, headersize); - if (ret < 0) - return ret; - /* Seek back to the beginning to start writing the header now */ - avio_seek(pb, 0, SEEK_SET); - - if (film->audio_index > -1) - audio = format_context->streams[film->audio_index]; - if (film->video_index > -1) - video = format_context->streams[film->video_index]; - - if (audio != NULL) { - audio_codec = get_audio_codec_id(audio->codecpar->codec_id); - if (audio_codec < 0) { - av_log(format_context, AV_LOG_ERROR, "Incompatible audio stream format.\n"); - return AVERROR(EINVAL); - } - } - - if (video->codecpar->format != AV_PIX_FMT_RGB24) { - av_log(format_context, AV_LOG_ERROR, "Pixel format must be rgb24.\n"); - return AVERROR(EINVAL); - } - - /* First, write the FILM header; this is very simple */ - - ffio_wfourcc(pb, "FILM"); - avio_wb32(pb, 48 + stabsize); + /* Write the header at the position in the buffer reserved for it. + * First, write the FILM header; this is very simple */ + ptr = header; + bytestream_put_be32(&ptr, MKBETAG('F', 'I', 'L', 'M')); + bytestream_put_be32(&ptr, headersize); /* This seems to be okay to hardcode, since this muxer targets 1.09 features; * videos produced by this muxer are readable by 1.08 and lower players. */ - ffio_wfourcc(pb, "1.09"); - /* I have no idea what this field does, might be reserved */ - avio_wb32(pb, 0); + bytestream_put_be32(&ptr, MKBETAG('1', '.', '0', '9')); + /* I have no idea what the next four bytes do, might be reserved */ + ptr += 4; /* Next write the FDSC (file description) chunk */ - ffio_wfourcc(pb, "FDSC"); - avio_wb32(pb, 0x20); /* Size of FDSC chunk */ + bytestream_put_be32(&ptr, MKBETAG('F', 'D', 'S', 'C')); + bytestream_put_be32(&ptr, 0x20); /* Size of FDSC chunk */ + + video = format_context->streams[film->video_index]; /* The only two supported codecs; raw video is rare */ switch (video->codecpar->codec_id) { case AV_CODEC_ID_CINEPAK: - ffio_wfourcc(pb, "cvid"); + bytestream_put_be32(&ptr, MKBETAG('c', 'v', 'i', 'd')); break; case AV_CODEC_ID_RAWVIDEO: - ffio_wfourcc(pb, "raw "); + bytestream_put_be32(&ptr, MKBETAG('r', 'a', 'w', ' ')); break; - default: - av_log(format_context, AV_LOG_ERROR, "Incompatible video stream format.\n"); - return AVERROR(EINVAL); } - avio_wb32(pb, video->codecpar->height); - avio_wb32(pb, video->codecpar->width); - avio_w8(pb, 24); /* Bits per pixel - observed to always be 24 */ - - if (audio != NULL) { - avio_w8(pb, audio->codecpar->channels); /* Audio channels */ - avio_w8(pb, audio->codecpar->bits_per_coded_sample); /* Audio bit depth */ - avio_w8(pb, audio_codec); /* Compression - 0 is PCM, 2 is ADX */ - avio_wb16(pb, audio->codecpar->sample_rate); /* Audio sampling rate */ + bytestream_put_be32(&ptr, video->codecpar->height); + bytestream_put_be32(&ptr, video->codecpar->width); + bytestream_put_byte(&ptr, 24); /* Bits per pixel - observed to always be 24 */ + + if (film->audio_index > -1) { + AVStream *audio = format_context->streams[film->audio_index]; + int audio_codec = get_audio_codec_id(audio->codecpar->codec_id); + + bytestream_put_byte(&ptr, audio->codecpar->channels); /* Audio channels */ + bytestream_put_byte(&ptr, audio->codecpar->bits_per_coded_sample); /* Audio bit depth */ + bytestream_put_byte(&ptr, audio_codec); /* Compression - 0 is PCM, 2 is ADX */ + bytestream_put_be16(&ptr, audio->codecpar->sample_rate); /* Audio sampling rate */ } else { - /* Set all these fields to 0 if there's no audio */ - avio_w8(pb, 0); - avio_w8(pb, 0); - avio_w8(pb, 0); - avio_wb16(pb, 0); + /* If there is no audio, all the audio fields should be set to zero. + * ffio_fill() already did this for us. */ + ptr += 1 + 1 + 1 + 2; } /* I have no idea what this pair of fields does either, might be reserved */ - avio_wb32(pb, 0); - avio_wb16(pb, 0); + ptr += 4 + 2; /* Finally, write the STAB (sample table) chunk */ - ffio_wfourcc(pb, "STAB"); - avio_wb32(pb, 16 + (film->packet_count * 16)); + bytestream_put_be32(&ptr, MKBETAG('S', 'T', 'A', 'B')); + bytestream_put_be32(&ptr, stabsize); /* Framerate base frequency. Here we're assuming that the frame rate is even. * In real world Sega FILM files, there are usually a couple of approaches: * a) framerate base frequency is the same as the framerate, and ticks @@ -360,29 +302,24 @@ * The latter occurs even in cases where the frame rate is even; for example, in * Lunar: Silver Star Story, the base frequency is 600 and each frame, the ticks * are incremented by 25 for an evenly spaced framerate of 24fps. */ - avio_wb32(pb, av_q2d(av_inv_q(video->time_base))); + bytestream_put_be32(&ptr, av_q2d(av_inv_q(video->time_base))); - avio_wb32(pb, film->packet_count); + bytestream_put_be32(&ptr, packet_count); - avio_flush(pb); - - /* Finally, write out each packet's data to the header */ - packet = film->start; - while (packet != NULL) { - film_write_packet_to_header(format_context, packet); - prev = packet; - packet = packet->next; - av_freep(&prev); - } + /* Finally, shift the data and write out the header. */ + ret = write_header(format_context, header, headersize); + if (ret < 0) + return ret; return 0; } -static const AVClass film_muxer_class = { - .class_name = "Sega FILM muxer", - .item_name = av_default_item_name, - .version = LIBAVUTIL_VERSION_INT, -}; +static void film_deinit(AVFormatContext *format_context) +{ + FILMOutputContext *film = format_context->priv_data; + + ffio_free_dyn_buf(&film->header); +} AVOutputFormat ff_segafilm_muxer = { .name = "film_cpk", @@ -394,5 +331,5 @@ .init = film_init, .write_trailer = film_write_header, .write_packet = film_write_packet, - .priv_class = &film_muxer_class, + .deinit = film_deinit, }; diff -Nru ffmpeg-4.2.2/libavformat/segment.c ffmpeg-4.4/libavformat/segment.c --- ffmpeg-4.2.2/libavformat/segment.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/segment.c 2021-04-08 21:28:40.000000000 +0000 @@ -75,12 +75,12 @@ ff_const59 AVOutputFormat *oformat; AVFormatContext *avf; char *format; ///< format to use for output segment files - char *format_options_str; ///< format options to use for output segment files AVDictionary *format_options; char *list; ///< filename for the segment list file int list_flags; ///< flags affecting list generation int list_size; ///< number of entries for the segment list file + int is_nullctx; ///< whether avf->pb is a nullctx int use_clocktime; ///< flag to cut segments at regular clock time int64_t clocktime_offset; //< clock offset for cutting the segments at regular clock time int64_t clocktime_wrap_duration; //< wrapping duration considered for starting a new segment @@ -91,7 +91,6 @@ char *entry_prefix; ///< prefix to add to list entry filenames int list_type; ///< set the list type AVIOContext *list_pb; ///< list file put-byte context - char *time_str; ///< segment duration specification string int64_t time; ///< segment duration int use_strftime; ///< flag to expand filename with strftime int increment_tc; ///< flag to increment timecode if found @@ -163,12 +162,11 @@ oc->flags = s->flags; for (i = 0; i < s->nb_streams; i++) { - AVStream *st; - AVCodecParameters *ipar, *opar; + AVStream *st, *ist = s->streams[i]; + AVCodecParameters *ipar = ist->codecpar, *opar; if (!(st = avformat_new_stream(oc, NULL))) return AVERROR(ENOMEM); - ipar = s->streams[i]->codecpar; opar = st->codecpar; avcodec_parameters_copy(opar, ipar); if (!oc->oformat->codec_tag || @@ -178,16 +176,17 @@ } else { opar->codec_tag = 0; } - st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; - st->time_base = s->streams[i]->time_base; - st->avg_frame_rate = s->streams[i]->avg_frame_rate; + st->sample_aspect_ratio = ist->sample_aspect_ratio; + st->time_base = ist->time_base; + st->avg_frame_rate = ist->avg_frame_rate; + st->disposition = ist->disposition; #if FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS - if (s->streams[i]->codecpar->codec_tag == MKTAG('t','m','c','d')) - st->codec->time_base = s->streams[i]->codec->time_base; + if (ipar->codec_tag == MKTAG('t','m','c','d')) + st->codec->time_base = ist->codec->time_base; FF_ENABLE_DEPRECATION_WARNINGS #endif - av_dict_copy(&st->metadata, s->streams[i]->metadata, 0); + av_dict_copy(&st->metadata, ist->metadata, 0); } return 0; @@ -511,7 +510,7 @@ /* check on monotonicity */ if (i && (*times)[i-1] > (*times)[i]) { av_log(log_ctx, AV_LOG_ERROR, - "Specified time %f is greater than the following time %f\n", + "Specified time %f is smaller than the last time %f\n", (float)((*times)[i])/1000000, (float)((*times)[i-1])/1000000); FAIL(AVERROR(EINVAL)); } @@ -525,60 +524,52 @@ static int parse_frames(void *log_ctx, int **frames, int *nb_frames, const char *frames_str) { - char *p; - int i, ret = 0; - char *frames_str1 = av_strdup(frames_str); - char *saveptr = NULL; - - if (!frames_str1) - return AVERROR(ENOMEM); - -#define FAIL(err) ret = err; goto end + const char *p; + int i; *nb_frames = 1; - for (p = frames_str1; *p; p++) + for (p = frames_str; *p; p++) if (*p == ',') (*nb_frames)++; *frames = av_malloc_array(*nb_frames, sizeof(**frames)); if (!*frames) { av_log(log_ctx, AV_LOG_ERROR, "Could not allocate forced frames array\n"); - FAIL(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); } - p = frames_str1; + p = frames_str; for (i = 0; i < *nb_frames; i++) { long int f; char *tailptr; - char *fstr = av_strtok(p, ",", &saveptr); - p = NULL; - if (!fstr) { + if (*p == '\0' || *p == ',') { av_log(log_ctx, AV_LOG_ERROR, "Empty frame specification in frame list %s\n", frames_str); - FAIL(AVERROR(EINVAL)); + return AVERROR(EINVAL); } - f = strtol(fstr, &tailptr, 10); - if (*tailptr || f <= 0 || f >= INT_MAX) { + f = strtol(p, &tailptr, 10); + if (*tailptr != '\0' && *tailptr != ',' || f <= 0 || f >= INT_MAX) { av_log(log_ctx, AV_LOG_ERROR, - "Invalid argument '%s', must be a positive integer <= INT64_MAX\n", - fstr); - FAIL(AVERROR(EINVAL)); + "Invalid argument '%s', must be a positive integer < INT_MAX\n", + p); + return AVERROR(EINVAL); } + if (*tailptr == ',') + tailptr++; + p = tailptr; (*frames)[i] = f; /* check on monotonicity */ if (i && (*frames)[i-1] > (*frames)[i]) { av_log(log_ctx, AV_LOG_ERROR, - "Specified frame %d is greater than the following frame %d\n", + "Specified frame %d is smaller than the last frame %d\n", (*frames)[i], (*frames)[i-1]); - FAIL(AVERROR(EINVAL)); + return AVERROR(EINVAL); } } -end: - av_free(frames_str1); - return ret; + return 0; } static int open_null_ctx(AVIOContext **ctx) @@ -661,9 +652,28 @@ static void seg_free(AVFormatContext *s) { SegmentContext *seg = s->priv_data; - ff_format_io_close(seg->avf, &seg->list_pb); - avformat_free_context(seg->avf); - seg->avf = NULL; + SegmentListEntry *cur; + + ff_format_io_close(s, &seg->list_pb); + if (seg->avf) { + if (seg->is_nullctx) + close_null_ctxp(&seg->avf->pb); + else + ff_format_io_close(s, &seg->avf->pb); + avformat_free_context(seg->avf); + seg->avf = NULL; + } + av_freep(&seg->times); + av_freep(&seg->frames); + av_freep(&seg->cur_entry.filename); + + cur = seg->segment_list_entries; + while (cur) { + SegmentListEntry *next = cur->next; + av_freep(&cur->filename); + av_free(cur); + cur = next; + } } static int seg_init(AVFormatContext *s) @@ -688,7 +698,7 @@ "you can use output_ts_offset instead of it\n"); } - if (!!seg->time_str + !!seg->times_str + !!seg->frames_str > 1) { + if ((seg->time != 2000000) + !!seg->times_str + !!seg->frames_str > 1) { av_log(s, AV_LOG_ERROR, "segment_time, segment_times, and segment_frames options " "are mutually exclusive, select just one of them\n"); @@ -702,15 +712,6 @@ if ((ret = parse_frames(s, &seg->frames, &seg->nb_frames, seg->frames_str)) < 0) return ret; } else { - /* set default value if not specified */ - if (!seg->time_str) - seg->time_str = av_strdup("2"); - if ((ret = av_parse_time(&seg->time, seg->time_str, 1)) < 0) { - av_log(s, AV_LOG_ERROR, - "Invalid time duration specification '%s' for segment_time option\n", - seg->time_str); - return ret; - } if (seg->use_clocktime) { if (seg->time <= 0) { av_log(s, AV_LOG_ERROR, "Invalid negative segment_time with segment_atclocktime option set\n"); @@ -720,15 +721,6 @@ } } - if (seg->format_options_str) { - ret = av_dict_parse_string(&seg->format_options, seg->format_options_str, "=", ":", 0); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", - seg->format_options_str); - return ret; - } - } - if (seg->list) { if (seg->list_type == LIST_TYPE_UNDEFINED) { if (av_match_ext(seg->list, "csv" )) seg->list_type = LIST_TYPE_CSV; @@ -784,6 +776,7 @@ } else { if ((ret = open_null_ctx(&oc->pb)) < 0) return ret; + seg->is_nullctx = 1; } av_dict_copy(&options, seg->format_options, 0); @@ -791,14 +784,13 @@ ret = avformat_init_output(oc, &options); if (av_dict_count(options)) { av_log(s, AV_LOG_ERROR, - "Some of the provided format options in '%s' are not recognized\n", seg->format_options_str); + "Some of the provided format options are not recognized\n"); av_dict_free(&options); return AVERROR(EINVAL); } av_dict_free(&options); if (ret < 0) { - ff_format_io_close(oc, &oc->pb); return ret; } seg->segment_frame_count = 0; @@ -827,26 +819,9 @@ { SegmentContext *seg = s->priv_data; AVFormatContext *oc = seg->avf; - int ret, i; + int ret; if (!seg->header_written) { - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = oc->streams[i]; - AVCodecParameters *ipar, *opar; - - ipar = s->streams[i]->codecpar; - opar = oc->streams[i]->codecpar; - avcodec_parameters_copy(opar, ipar); - if (!oc->oformat->codec_tag || - av_codec_get_id (oc->oformat->codec_tag, ipar->codec_tag) == opar->codec_id || - av_codec_get_tag(oc->oformat->codec_tag, ipar->codec_id) <= 0) { - opar->codec_tag = ipar->codec_tag; - } else { - opar->codec_tag = 0; - } - st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; - st->time_base = s->streams[i]->time_base; - } ret = avformat_write_header(oc, NULL); if (ret < 0) return ret; @@ -858,6 +833,7 @@ ff_format_io_close(oc, &oc->pb); } else { close_null_ctxp(&oc->pb); + seg->is_nullctx = 0; } if ((ret = oc->io_open(oc, &oc->pb, oc->url, AVIO_FLAG_WRITE, NULL)) < 0) return ret; @@ -883,7 +859,7 @@ return AVERROR(EINVAL); if (!st->codecpar->extradata_size) { - int pkt_extradata_size = 0; + buffer_size_t pkt_extradata_size; uint8_t *pkt_extradata = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &pkt_extradata_size); if (pkt_extradata && pkt_extradata_size > 0) { ret = ff_alloc_extradata(st->codecpar, pkt_extradata_size); @@ -892,7 +868,6 @@ goto calc_times; } memcpy(st->codecpar->extradata, pkt_extradata, pkt_extradata_size); - st->codecpar->extradata_size = pkt_extradata_size; } } @@ -982,7 +957,8 @@ av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base)); - ret = ff_write_chained(seg->avf, pkt->stream_index, pkt, s, seg->initial_offset || seg->reset_timestamps); + ret = ff_write_chained(seg->avf, pkt->stream_index, pkt, s, + seg->initial_offset || seg->reset_timestamps || seg->avf->oformat->interleave_packet); fail: if (pkt->stream_index == seg->reference_stream_index) { @@ -997,42 +973,21 @@ { SegmentContext *seg = s->priv_data; AVFormatContext *oc = seg->avf; - SegmentListEntry *cur, *next; - int ret = 0; + int ret; if (!oc) - goto fail; + return 0; if (!seg->write_header_trailer) { if ((ret = segment_end(s, 0, 1)) < 0) - goto fail; + return ret; if ((ret = open_null_ctx(&oc->pb)) < 0) - goto fail; + return ret; + seg->is_nullctx = 1; ret = av_write_trailer(oc); - close_null_ctxp(&oc->pb); } else { ret = segment_end(s, 1, 1); } -fail: - if (seg->list) - ff_format_io_close(s, &seg->list_pb); - - av_dict_free(&seg->format_options); - av_opt_free(seg); - av_freep(&seg->times); - av_freep(&seg->frames); - av_freep(&seg->cur_entry.filename); - - cur = seg->segment_list_entries; - while (cur) { - next = cur->next; - av_freep(&cur->filename); - av_free(cur); - cur = next; - } - - avformat_free_context(oc); - seg->avf = NULL; return ret; } @@ -1045,10 +1000,8 @@ if (ret == 1) { AVStream *st = s->streams[pkt->stream_index]; AVStream *ost = oc->streams[pkt->stream_index]; - st->internal->bsfcs = ost->internal->bsfcs; - st->internal->nb_bsfcs = ost->internal->nb_bsfcs; - ost->internal->bsfcs = NULL; - ost->internal->nb_bsfcs = 0; + st->internal->bsfc = ost->internal->bsfc; + ost->internal->bsfc = NULL; } return ret; } @@ -1058,9 +1011,9 @@ #define OFFSET(x) offsetof(SegmentContext, x) #define E AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "reference_stream", "set reference stream", OFFSET(reference_stream_specifier), AV_OPT_TYPE_STRING, {.str = "auto"}, CHAR_MIN, CHAR_MAX, E }, + { "reference_stream", "set reference stream", OFFSET(reference_stream_specifier), AV_OPT_TYPE_STRING, {.str = "auto"}, 0, 0, E }, { "segment_format", "set container format used for the segments", OFFSET(format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, - { "segment_format_options", "set list of options for the container format used for the segments", OFFSET(format_options_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, + { "segment_format_options", "set list of options for the container format used for the segments", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E }, { "segment_list", "set the segment list filename", OFFSET(list), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, { "segment_header_filename", "write a single file containing the header", OFFSET(header_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, @@ -1081,7 +1034,7 @@ { "segment_atclocktime", "set segment to be cut at clocktime", OFFSET(use_clocktime), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E}, { "segment_clocktime_offset", "set segment clocktime offset", OFFSET(clocktime_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, 86400000000LL, E}, { "segment_clocktime_wrap_duration", "set segment clocktime wrapping duration", OFFSET(clocktime_wrap_duration), AV_OPT_TYPE_DURATION, {.i64 = INT64_MAX}, 0, INT64_MAX, E}, - { "segment_time", "set segment duration", OFFSET(time_str),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, + { "segment_time", "set segment duration", OFFSET(time),AV_OPT_TYPE_DURATION, {.i64 = 2000000}, INT64_MIN, INT64_MAX, E }, { "segment_time_delta","set approximation value used for the segment times", OFFSET(time_delta), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, E }, { "segment_times", "set segment split time points", OFFSET(times_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E }, { "segment_frames", "set segment split frame numbers", OFFSET(frames_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E }, diff -Nru ffmpeg-4.2.2/libavformat/sga.c ffmpeg-4.4/libavformat/sga.c --- ffmpeg-4.2.2/libavformat/sga.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/sga.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,479 @@ +/* + * Digital Pictures SGA game demuxer + * + * 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 "libavutil/intreadwrite.h" +#include "libavutil/avassert.h" +#include "libavutil/internal.h" +#include "avformat.h" +#include "internal.h" +#include "avio_internal.h" + +#define SEGA_CD_PCM_NUM 12500000 +#define SEGA_CD_PCM_DEN 786432 + +typedef struct SGADemuxContext { + int video_stream_index; + int audio_stream_index; + + uint8_t sector[65536 * 2]; + int sector_headers; + int sample_rate; + int first_audio_size; + int payload_size; + int packet_type; + int flags; + int idx; + int left; + int64_t pkt_pos; +} SGADemuxContext; + +static int sga_probe(const AVProbeData *p) +{ + const uint8_t *src = p->buf; + int score = 0, sectors = 1; + int last_left = 0; + int sample_rate = -1; + + if (p->buf_size < 2048) + return 0; + + for (int i = 0; i + 2 < p->buf_size; i += 2048) { + int header = AV_RB16(src + i); + + if ((header > 0x07FE && header < 0x8100) || + (header > 0x8200 && header < 0xA100) || + (header > 0xA200 && header < 0xC100)) { + sectors = 0; + break; + } + } + + for (int i = 0; i + 4 < p->buf_size;) { + int header = AV_RB16(src + i); + int left = AV_RB16(src + i + 2); + int offset, type, size; + + if (last_left < 0) + return 0; + if (sectors && header && last_left == 0) { + if (header >> 12) { + last_left = left; + } else { + last_left = left = header; + } + } else if (sectors && header) { + left = header; + last_left -= left; + if (header != 0x7FE && left < 7) + return 0; + } else if (sectors) { + if (left <= 8) + return 0; + i += sectors ? 2048 : left + 4; + last_left = 0; + continue; + } + + if (sectors && (i > 0 && left < 0x7fe) && + (i + left + 14 < p->buf_size)) { + offset = i + left + 2; + } else if (sectors && i > 0) { + i += 2048; + last_left -= FFMIN(last_left, 2046); + continue; + } else { + offset = 0; + last_left = left; + } + + header = AV_RB16(src + offset); + size = AV_RB16(src + offset + 2) + 4; + + while ((header & 0xFF00) == 0) { + offset++; + if (offset + 4 >= p->buf_size) + break; + header = AV_RB16(src + offset); + size = AV_RB16(src + offset + 2) + 4; + } + + if (offset + 12 >= p->buf_size) + break; + if ((header & 0xFF) > 1) + return 0; + type = header >> 8; + + if (type == 0xAA || + type == 0xA1 || + type == 0xA2 || + type == 0xA3) { + int new_rate; + + if (size <= 12) + return 0; + new_rate = AV_RB16(src + offset + 8); + if (sample_rate < 0) + sample_rate = new_rate; + if (sample_rate == 0 || new_rate != sample_rate) + return 0; + if (src[offset + 10] != 1) + return 0; + + score += 10; + } else if (type == 0xC1 || + type == 0xC6 || + type == 0xC7 || + type == 0xC8 || + type == 0xC9 || + type == 0xCB || + type == 0xCD || + type == 0xE7) { + int nb_pals = src[offset + 9]; + int tiles_w = src[offset + 10]; + int tiles_h = src[offset + 11]; + + if (size <= 12) + return 0; + if (nb_pals == 0 || nb_pals > 4) + return 0; + if (tiles_w == 0 || tiles_w > 80) + return 0; + if (tiles_h == 0 || tiles_h > 60) + return 0; + + score += 10; + } else if (header == 0x7FE) { + ; + } else { + return 0; + } + + i += sectors ? 2048 : size + 4; + last_left -= FFMIN(last_left, 2046); + + if (score < 0) + break; + } + + return av_clip(score, 0, AVPROBE_SCORE_MAX); +} + +static int sga_read_header(AVFormatContext *s) +{ + SGADemuxContext *sga = s->priv_data; + AVIOContext *pb = s->pb; + + sga->sector_headers = 1; + sga->first_audio_size = 0; + sga->video_stream_index = -1; + sga->audio_stream_index = -1; + sga->left = 2048; + sga->idx = 0; + + s->ctx_flags |= AVFMTCTX_NOHEADER; + + if (pb->seekable & AVIO_SEEKABLE_NORMAL) { + while (!avio_feof(pb)) { + int header = avio_rb16(pb); + int type = header >> 8; + int skip = 2046; + int clock; + + if (!sga->first_audio_size && + (type == 0xAA || + type == 0xA1 || + type == 0xA2 || + type == 0xA3)) { + sga->first_audio_size = avio_rb16(pb); + avio_skip(pb, 4); + clock = avio_rb16(pb); + sga->sample_rate = av_rescale(clock, + SEGA_CD_PCM_NUM, + SEGA_CD_PCM_DEN); + skip -= 8; + } + if ((header > 0x07FE && header < 0x8100) || + (header > 0x8200 && header < 0xA100) || + (header > 0xA200 && header < 0xC100)) { + sga->sector_headers = 0; + break; + } + + avio_skip(pb, skip); + } + + avio_seek(pb, 0, SEEK_SET); + } + + return 0; +} + +static void print_stats(AVFormatContext *s, const char *where) +{ + SGADemuxContext *sga = s->priv_data; + + av_log(s, AV_LOG_DEBUG, "START %s\n", where); + av_log(s, AV_LOG_DEBUG, "pos: %"PRIX64"\n", avio_tell(s->pb)); + av_log(s, AV_LOG_DEBUG, "idx: %X\n", sga->idx); + av_log(s, AV_LOG_DEBUG, "packet_type: %X\n", sga->packet_type); + av_log(s, AV_LOG_DEBUG, "payload_size: %X\n", sga->payload_size); + av_log(s, AV_LOG_DEBUG, "SECTOR: %016"PRIX64"\n", AV_RB64(sga->sector)); + av_log(s, AV_LOG_DEBUG, "stream: %X\n", sga->sector[1]); + av_log(s, AV_LOG_DEBUG, "END %s\n", where); +} + +static void update_type_size(AVFormatContext *s) +{ + SGADemuxContext *sga = s->priv_data; + + if (sga->idx >= 4) { + sga->packet_type = sga->sector[0]; + sga->payload_size = AV_RB16(sga->sector + 2); + } else { + sga->packet_type = 0; + sga->payload_size = 0; + } +} + +static int sga_video_packet(AVFormatContext *s, AVPacket *pkt) +{ + SGADemuxContext *sga = s->priv_data; + int ret; + + if (sga->payload_size <= 8) + return AVERROR_INVALIDDATA; + + if (sga->video_stream_index == -1) { + AVRational frame_rate; + + AVStream *st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->start_time = 0; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_tag = 0; + st->codecpar->codec_id = AV_CODEC_ID_SGA_VIDEO; + sga->video_stream_index = st->index; + + if (sga->first_audio_size > 0 && sga->sample_rate > 0) { + frame_rate.num = sga->sample_rate; + frame_rate.den = sga->first_audio_size; + } else { + frame_rate.num = 15; + frame_rate.den = 1; + } + avpriv_set_pts_info(st, 64, frame_rate.den, frame_rate.num); + } + + ret = av_new_packet(pkt, sga->payload_size + 4); + if (ret < 0) + return AVERROR(ENOMEM); + memcpy(pkt->data, sga->sector, sga->payload_size + 4); + av_assert0(sga->idx >= sga->payload_size + 4); + memmove(sga->sector, sga->sector + sga->payload_size + 4, sga->idx - sga->payload_size - 4); + + pkt->stream_index = sga->video_stream_index; + pkt->duration = 1; + pkt->pos = sga->pkt_pos; + pkt->flags |= sga->flags; + sga->idx -= sga->payload_size + 4; + sga->flags = 0; + update_type_size(s); + + av_log(s, AV_LOG_DEBUG, "VIDEO PACKET: %d:%016"PRIX64" i:%X\n", pkt->size, AV_RB64(sga->sector), sga->idx); + + return 0; +} + +static int sga_audio_packet(AVFormatContext *s, AVPacket *pkt) +{ + SGADemuxContext *sga = s->priv_data; + int ret; + + if (sga->payload_size <= 8) + return AVERROR_INVALIDDATA; + + if (sga->audio_stream_index == -1) { + AVStream *st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->start_time = 0; + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_tag = 0; + st->codecpar->codec_id = AV_CODEC_ID_PCM_SGA; + st->codecpar->channels = 1; + st->codecpar->channel_layout= AV_CH_LAYOUT_MONO; + st->codecpar->sample_rate = av_rescale(AV_RB16(sga->sector + 8), + SEGA_CD_PCM_NUM, + SEGA_CD_PCM_DEN); + sga->audio_stream_index = st->index; + + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); + } + + ret = av_new_packet(pkt, sga->payload_size - 8); + if (ret < 0) + return AVERROR(ENOMEM); + memcpy(pkt->data, sga->sector + 12, sga->payload_size - 8); + av_assert0(sga->idx >= sga->payload_size + 4); + memmove(sga->sector, sga->sector + sga->payload_size + 4, sga->idx - sga->payload_size - 4); + + pkt->stream_index = sga->audio_stream_index; + pkt->duration = pkt->size; + pkt->pos = sga->pkt_pos; + pkt->flags |= sga->flags; + sga->idx -= sga->payload_size + 4; + sga->flags = 0; + update_type_size(s); + + av_log(s, AV_LOG_DEBUG, "AUDIO PACKET: %d:%016"PRIX64" i:%X\n", pkt->size, AV_RB64(sga->sector), sga->idx); + + return 0; +} + +static int sga_packet(AVFormatContext *s, AVPacket *pkt) +{ + SGADemuxContext *sga = s->priv_data; + int ret = 0; + + if (sga->packet_type == 0xCD || + sga->packet_type == 0xCB || + sga->packet_type == 0xC9 || + sga->packet_type == 0xC8 || + sga->packet_type == 0xC7 || + sga->packet_type == 0xC6 || + sga->packet_type == 0xC1 || + sga->packet_type == 0xE7) { + ret = sga_video_packet(s, pkt); + } else if (sga->packet_type == 0xA1 || + sga->packet_type == 0xA2 || + sga->packet_type == 0xA3 || + sga->packet_type == 0xAA) { + ret = sga_audio_packet(s, pkt); + } else { + if (sga->idx == 0) + return AVERROR_EOF; + if (sga->sector[0]) + return AVERROR_INVALIDDATA; + memmove(sga->sector, sga->sector + 1, sga->idx - 1); + sga->idx--; + return AVERROR(EAGAIN); + } + + return ret; +} + +static int try_packet(AVFormatContext *s, AVPacket *pkt) +{ + SGADemuxContext *sga = s->priv_data; + int ret = AVERROR(EAGAIN); + + update_type_size(s); + if (sga->idx >= sga->payload_size + 4) { + print_stats(s, "before sga_packet"); + ret = sga_packet(s, pkt); + print_stats(s, "after sga_packet"); + if (ret != AVERROR(EAGAIN)) + return ret; + } + + return sga->idx < sga->payload_size + 4 ? AVERROR(EAGAIN) : ret; +} + +static int sga_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + SGADemuxContext *sga = s->priv_data; + AVIOContext *pb = s->pb; + int header, ret = 0; + + sga->pkt_pos = avio_tell(pb); + +retry: + update_type_size(s); + + print_stats(s, "start"); + if (avio_feof(pb) && + (!sga->payload_size || sga->idx < sga->payload_size + 4)) + return AVERROR_EOF; + + if (sga->idx < sga->payload_size + 4) { + ret = ffio_ensure_seekback(pb, 2); + if (ret < 0) + return ret; + + print_stats(s, "before read header"); + header = avio_rb16(pb); + if (!header) { + avio_skip(pb, 2046); + sga->left = 0; + } else if (!avio_feof(pb) && + ((header >> 15) || + !sga->sector_headers)) { + avio_seek(pb, -2, SEEK_CUR); + sga->flags = AV_PKT_FLAG_KEY; + sga->left = 2048; + } else { + sga->left = 2046; + } + + av_assert0(sga->idx + sga->left < sizeof(sga->sector)); + ret = avio_read(pb, sga->sector + sga->idx, sga->left); + if (ret > 0) + sga->idx += ret; + else if (ret != AVERROR_EOF && ret) + return ret; + print_stats(s, "after read header"); + + update_type_size(s); + } + + ret = try_packet(s, pkt); + if (ret == AVERROR(EAGAIN)) + goto retry; + + return ret; +} + +static int sga_seek(AVFormatContext *s, int stream_index, + int64_t timestamp, int flags) +{ + SGADemuxContext *sga = s->priv_data; + + sga->packet_type = sga->payload_size = sga->idx = 0; + memset(sga->sector, 0, sizeof(sga->sector)); + + return -1; +} + +AVInputFormat ff_sga_demuxer = { + .name = "sga", + .long_name = NULL_IF_CONFIG_SMALL("Digital Pictures SGA"), + .priv_data_size = sizeof(SGADemuxContext), + .read_probe = sga_probe, + .read_header = sga_read_header, + .read_packet = sga_read_packet, + .read_seek = sga_seek, + .extensions = "sga", + .flags = AVFMT_GENERIC_INDEX, +}; diff -Nru ffmpeg-4.2.2/libavformat/sierravmd.c ffmpeg-4.4/libavformat/sierravmd.c --- ffmpeg-4.2.2/libavformat/sierravmd.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/sierravmd.c 2021-04-08 21:28:27.000000000 +0000 @@ -127,8 +127,8 @@ vst->codecpar->width >>= 1; vst->codecpar->height >>= 1; } - if (ff_alloc_extradata(vst->codecpar, VMD_HEADER_SIZE)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(vst->codecpar, VMD_HEADER_SIZE)) < 0) + return ret; memcpy(vst->codecpar->extradata, vmd->vmd_header, VMD_HEADER_SIZE); } @@ -174,6 +174,8 @@ avpriv_set_pts_info(vst, 33, num, den); avpriv_set_pts_info(st, 33, num, den); } + if (!s->nb_streams) + return AVERROR_INVALIDDATA; toc_offset = AV_RL32(&vmd->vmd_header[812]); vmd->frame_count = AV_RL16(&vmd->vmd_header[6]); @@ -241,6 +243,8 @@ current_audio_pts++; break; case 2: /* Video Chunk */ + if (!vst) + break; vmd->frame_table[total_frames].frame_offset = current_offset; vmd->frame_table[total_frames].stream_index = vmd->video_stream_index; vmd->frame_table[total_frames].frame_size = size; @@ -283,8 +287,9 @@ if(ffio_limit(pb, frame->frame_size) != frame->frame_size) return AVERROR(EIO); - if (av_new_packet(pkt, frame->frame_size + BYTES_PER_FRAME_RECORD)) - return AVERROR(ENOMEM); + ret = av_new_packet(pkt, frame->frame_size + BYTES_PER_FRAME_RECORD); + if (ret < 0) + return ret; pkt->pos= avio_tell(pb); memcpy(pkt->data, frame->frame_record, BYTES_PER_FRAME_RECORD); if(vmd->is_indeo3 && frame->frame_record[0] == 0x02) @@ -294,7 +299,6 @@ frame->frame_size); if (ret != frame->frame_size) { - av_packet_unref(pkt); ret = AVERROR(EIO); } pkt->stream_index = frame->stream_index; diff -Nru ffmpeg-4.2.2/libavformat/siff.c ffmpeg-4.4/libavformat/siff.c --- ffmpeg-4.2.2/libavformat/siff.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/siff.c 2021-02-20 20:27:47.000000000 +0000 @@ -192,6 +192,7 @@ static int siff_read_packet(AVFormatContext *s, AVPacket *pkt) { SIFFContext *c = s->priv_data; + int ret; if (c->has_video) { unsigned int size; @@ -200,6 +201,8 @@ if (c->curstrm == -1) { c->pktsize = avio_rl32(s->pb) - 4; c->flags = avio_rl16(s->pb); + if (c->flags & VB_HAS_AUDIO && !c->has_audio) + return AVERROR_INVALIDDATA; c->gmcsize = (c->flags & VB_HAS_GMC) ? 4 : 0; if (c->gmcsize) avio_read(s->pb, c->gmc, c->gmcsize); @@ -213,13 +216,12 @@ size = c->pktsize - c->sndsize - c->gmcsize - 2; size = ffio_limit(s->pb, size); - if (av_new_packet(pkt, size + c->gmcsize + 2) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, size + c->gmcsize + 2)) < 0) + return ret; AV_WL16(pkt->data, c->flags); if (c->gmcsize) memcpy(pkt->data + 2, c->gmc, c->gmcsize); if (avio_read(s->pb, pkt->data + 2 + c->gmcsize, size) != size) { - av_packet_unref(pkt); return AVERROR_INVALIDDATA; } pkt->stream_index = 0; diff -Nru ffmpeg-4.2.2/libavformat/smacker.c ffmpeg-4.4/libavformat/smacker.c --- ffmpeg-4.2.2/libavformat/smacker.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/smacker.c 2021-04-08 21:28:40.000000000 +0000 @@ -25,10 +25,10 @@ #include -#include "libavutil/bswap.h" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "avio_internal.h" #include "internal.h" #define SMACKER_PAL 0x01 @@ -43,42 +43,25 @@ }; typedef struct SmackerContext { - /* Smacker file header */ - uint32_t magic; - uint32_t width, height; uint32_t frames; - int pts_inc; - uint32_t flags; - uint32_t audio[7]; - uint32_t treesize; - uint32_t mmap_size, mclr_size, full_size, type_size; - uint8_t aflags[7]; - uint32_t rates[7]; - uint32_t pad; /* frame info */ uint32_t *frm_size; uint8_t *frm_flags; /* internal variables */ + int64_t next_frame_pos; int cur_frame; - int is_ver4; - int64_t cur_pts; + int videoindex; + int indexes[7]; + int duration_size[7]; /* current frame for demuxing */ + uint32_t frame_size; + int flags; + int next_audio_index; + int new_palette; uint8_t pal[768]; - int indexes[7]; - int videoindex; - uint8_t *bufs[7]; - int buf_sizes[7]; - int stream_id[7]; - int curstream; - int64_t nextpos; int64_t aud_pts[7]; } SmackerContext; -typedef struct SmackerFrame { - int64_t pts; - int stream; -} SmackerFrame; - /* palette used in Smacker */ static const uint8_t smk_pal[64] = { 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C, @@ -108,199 +91,192 @@ { AVIOContext *pb = s->pb; SmackerContext *smk = s->priv_data; - AVStream *st, *ast[7]; - int i, ret; + AVStream *st; + AVCodecParameters *par; + uint32_t magic, width, height, flags, treesize; + int i, ret, pts_inc; int tbase; /* read and check header */ - smk->magic = avio_rl32(pb); - if (smk->magic != MKTAG('S', 'M', 'K', '2') && smk->magic != MKTAG('S', 'M', 'K', '4')) + magic = avio_rl32(pb); + if (magic != MKTAG('S', 'M', 'K', '2') && magic != MKTAG('S', 'M', 'K', '4')) return AVERROR_INVALIDDATA; - smk->width = avio_rl32(pb); - smk->height = avio_rl32(pb); + width = avio_rl32(pb); + height = avio_rl32(pb); smk->frames = avio_rl32(pb); - smk->pts_inc = (int32_t)avio_rl32(pb); - if (smk->pts_inc > INT_MAX / 100) { - av_log(s, AV_LOG_ERROR, "pts_inc %d is too large\n", smk->pts_inc); + pts_inc = avio_rl32(pb); + if (pts_inc > INT_MAX / 100 || pts_inc == INT_MIN) { + av_log(s, AV_LOG_ERROR, "pts_inc %d is invalid\n", pts_inc); return AVERROR_INVALIDDATA; } - smk->flags = avio_rl32(pb); - if(smk->flags & SMACKER_FLAG_RING_FRAME) + flags = avio_rl32(pb); + if (flags & SMACKER_FLAG_RING_FRAME) smk->frames++; - for(i = 0; i < 7; i++) - smk->audio[i] = avio_rl32(pb); - smk->treesize = avio_rl32(pb); - - if(smk->treesize >= UINT_MAX/4){ // smk->treesize + 16 must not overflow (this check is probably redundant) - av_log(s, AV_LOG_ERROR, "treesize too large\n"); - return AVERROR_INVALIDDATA; - } - -//FIXME remove extradata "rebuilding" - smk->mmap_size = avio_rl32(pb); - smk->mclr_size = avio_rl32(pb); - smk->full_size = avio_rl32(pb); - smk->type_size = avio_rl32(pb); - for(i = 0; i < 7; i++) { - smk->rates[i] = avio_rl24(pb); - smk->aflags[i] = avio_r8(pb); - } - smk->pad = avio_rl32(pb); - /* setup data */ - if(smk->frames > 0xFFFFFF) { + if (smk->frames > 0xFFFFFF) { av_log(s, AV_LOG_ERROR, "Too many frames: %"PRIu32"\n", smk->frames); return AVERROR_INVALIDDATA; } - smk->frm_size = av_malloc_array(smk->frames, sizeof(*smk->frm_size)); - smk->frm_flags = av_malloc(smk->frames); - if (!smk->frm_size || !smk->frm_flags) { - av_freep(&smk->frm_size); - av_freep(&smk->frm_flags); - return AVERROR(ENOMEM); - } - smk->is_ver4 = (smk->magic != MKTAG('S', 'M', 'K', '2')); + avio_skip(pb, 28); /* Unused audio related data */ - /* read frame info */ - for(i = 0; i < smk->frames; i++) { - smk->frm_size[i] = avio_rl32(pb); - } - for(i = 0; i < smk->frames; i++) { - smk->frm_flags[i] = avio_r8(pb); + treesize = avio_rl32(pb); + if (treesize >= UINT_MAX/4) { + // treesize + 16 must not overflow (this check is probably redundant) + av_log(s, AV_LOG_ERROR, "treesize too large\n"); + return AVERROR_INVALIDDATA; } - /* init video codec */ st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); + smk->videoindex = st->index; - st->codecpar->width = smk->width; - st->codecpar->height = smk->height; - st->codecpar->format = AV_PIX_FMT_PAL8; - st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - st->codecpar->codec_id = AV_CODEC_ID_SMACKVIDEO; - st->codecpar->codec_tag = smk->magic; /* Smacker uses 100000 as internal timebase */ - if(smk->pts_inc < 0) - smk->pts_inc = -smk->pts_inc; + if (pts_inc < 0) + pts_inc = -pts_inc; else - smk->pts_inc *= 100; + pts_inc *= 100; tbase = 100000; - av_reduce(&tbase, &smk->pts_inc, tbase, smk->pts_inc, (1UL<<31)-1); - avpriv_set_pts_info(st, 33, smk->pts_inc, tbase); + av_reduce(&tbase, &pts_inc, tbase, pts_inc, (1UL << 31) - 1); + avpriv_set_pts_info(st, 33, pts_inc, tbase); st->duration = smk->frames; + + /* init video codec */ + par = st->codecpar; + par->width = width; + par->height = height; + par->format = AV_PIX_FMT_PAL8; + par->codec_type = AVMEDIA_TYPE_VIDEO; + par->codec_id = AV_CODEC_ID_SMACKVIDEO; + par->codec_tag = magic; + + if ((ret = ff_alloc_extradata(par, treesize + 16)) < 0) { + av_log(s, AV_LOG_ERROR, + "Cannot allocate %"PRIu32" bytes of extradata\n", + treesize + 16); + return ret; + } + if ((ret = ffio_read_size(pb, par->extradata, 16)) < 0) + return ret; + /* handle possible audio streams */ - for(i = 0; i < 7; i++) { + for (i = 0; i < 7; i++) { + uint32_t rate = avio_rl24(pb); + uint8_t aflag = avio_r8(pb); + smk->indexes[i] = -1; - if (smk->rates[i]) { - ast[i] = avformat_new_stream(s, NULL); - if (!ast[i]) + + if (rate) { + AVStream *ast = avformat_new_stream(s, NULL); + AVCodecParameters *par; + if (!ast) return AVERROR(ENOMEM); - smk->indexes[i] = ast[i]->index; - ast[i]->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - if (smk->aflags[i] & SMK_AUD_BINKAUD) { - ast[i]->codecpar->codec_id = AV_CODEC_ID_BINKAUDIO_RDFT; - } else if (smk->aflags[i] & SMK_AUD_USEDCT) { - ast[i]->codecpar->codec_id = AV_CODEC_ID_BINKAUDIO_DCT; - } else if (smk->aflags[i] & SMK_AUD_PACKED){ - ast[i]->codecpar->codec_id = AV_CODEC_ID_SMACKAUDIO; - ast[i]->codecpar->codec_tag = MKTAG('S', 'M', 'K', 'A'); + + smk->indexes[i] = ast->index; + par = ast->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + if (aflag & SMK_AUD_BINKAUD) { + par->codec_id = AV_CODEC_ID_BINKAUDIO_RDFT; + } else if (aflag & SMK_AUD_USEDCT) { + par->codec_id = AV_CODEC_ID_BINKAUDIO_DCT; + } else if (aflag & SMK_AUD_PACKED) { + par->codec_id = AV_CODEC_ID_SMACKAUDIO; + par->codec_tag = MKTAG('S', 'M', 'K', 'A'); } else { - ast[i]->codecpar->codec_id = AV_CODEC_ID_PCM_U8; + par->codec_id = AV_CODEC_ID_PCM_U8; } - if (smk->aflags[i] & SMK_AUD_STEREO) { - ast[i]->codecpar->channels = 2; - ast[i]->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + if (aflag & SMK_AUD_STEREO) { + par->channels = 2; + par->channel_layout = AV_CH_LAYOUT_STEREO; } else { - ast[i]->codecpar->channels = 1; - ast[i]->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + par->channels = 1; + par->channel_layout = AV_CH_LAYOUT_MONO; } - ast[i]->codecpar->sample_rate = smk->rates[i]; - ast[i]->codecpar->bits_per_coded_sample = (smk->aflags[i] & SMK_AUD_16BITS) ? 16 : 8; - if(ast[i]->codecpar->bits_per_coded_sample == 16 && ast[i]->codecpar->codec_id == AV_CODEC_ID_PCM_U8) - ast[i]->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; - avpriv_set_pts_info(ast[i], 64, 1, ast[i]->codecpar->sample_rate - * ast[i]->codecpar->channels * ast[i]->codecpar->bits_per_coded_sample / 8); + par->sample_rate = rate; + par->bits_per_coded_sample = (aflag & SMK_AUD_16BITS) ? 16 : 8; + if (par->bits_per_coded_sample == 16 && + par->codec_id == AV_CODEC_ID_PCM_U8) + par->codec_id = AV_CODEC_ID_PCM_S16LE; + else + smk->duration_size[i] = 4; + avpriv_set_pts_info(ast, 64, 1, par->sample_rate * par->channels + * par->bits_per_coded_sample / 8); } } + avio_rl32(pb); /* padding */ - /* load trees to extradata, they will be unpacked by decoder */ - if(ff_alloc_extradata(st->codecpar, smk->treesize + 16)){ - av_log(s, AV_LOG_ERROR, - "Cannot allocate %"PRIu32" bytes of extradata\n", - smk->treesize + 16); - av_freep(&smk->frm_size); - av_freep(&smk->frm_flags); + /* setup data */ + st->priv_data = av_malloc_array(smk->frames, sizeof(*smk->frm_size) + + sizeof(*smk->frm_flags)); + if (!st->priv_data) return AVERROR(ENOMEM); - } - ret = avio_read(pb, st->codecpar->extradata + 16, st->codecpar->extradata_size - 16); - if(ret != st->codecpar->extradata_size - 16){ - av_freep(&smk->frm_size); - av_freep(&smk->frm_flags); - return AVERROR(EIO); - } - ((int32_t*)st->codecpar->extradata)[0] = av_le2ne32(smk->mmap_size); - ((int32_t*)st->codecpar->extradata)[1] = av_le2ne32(smk->mclr_size); - ((int32_t*)st->codecpar->extradata)[2] = av_le2ne32(smk->full_size); - ((int32_t*)st->codecpar->extradata)[3] = av_le2ne32(smk->type_size); + smk->frm_size = st->priv_data; + smk->frm_flags = (void*)(smk->frm_size + smk->frames); - smk->curstream = -1; - smk->nextpos = avio_tell(pb); + /* read frame info */ + for (i = 0; i < smk->frames; i++) { + smk->frm_size[i] = avio_rl32(pb); + } + if ((ret = ffio_read_size(pb, smk->frm_flags, smk->frames)) < 0 || + /* load trees to extradata, they will be unpacked by decoder */ + (ret = ffio_read_size(pb, par->extradata + 16, + par->extradata_size - 16)) < 0) { + return ret; + } return 0; } - static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) { SmackerContext *smk = s->priv_data; int flags; int ret; - int i; - int frame_size = 0; - int palchange = 0; if (avio_feof(s->pb) || smk->cur_frame >= smk->frames) return AVERROR_EOF; /* if we demuxed all streams, pass another frame */ - if(smk->curstream < 0) { - avio_seek(s->pb, smk->nextpos, 0); - frame_size = smk->frm_size[smk->cur_frame] & (~3); + if (!smk->next_audio_index) { + smk->frame_size = smk->frm_size[smk->cur_frame] & (~3); + smk->next_frame_pos = avio_tell(s->pb) + smk->frame_size; flags = smk->frm_flags[smk->cur_frame]; + smk->flags = flags >> 1; /* handle palette change event */ - if(flags & SMACKER_PAL){ + if (flags & SMACKER_PAL) { int size, sz, t, off, j, pos; uint8_t *pal = smk->pal; uint8_t oldpal[768]; memcpy(oldpal, pal, 768); size = avio_r8(s->pb); - size = size * 4 - 1; - if(size + 1 > frame_size) - return AVERROR_INVALIDDATA; - frame_size -= size; - frame_size--; + size = size * 4; + if (size > smk->frame_size) { + ret = AVERROR_INVALIDDATA; + goto next_frame; + } + smk->frame_size -= size--; sz = 0; pos = avio_tell(s->pb) + size; - while(sz < 256){ + while (sz < 256) { t = avio_r8(s->pb); - if(t & 0x80){ /* skip palette entries */ - sz += (t & 0x7F) + 1; + if (t & 0x80) { /* skip palette entries */ + sz += (t & 0x7F) + 1; pal += ((t & 0x7F) + 1) * 3; - } else if(t & 0x40){ /* copy with offset */ + } else if (t & 0x40) { /* copy with offset */ off = avio_r8(s->pb); j = (t & 0x3F) + 1; if (off + j > 0x100) { av_log(s, AV_LOG_ERROR, "Invalid palette update, offset=%d length=%d extends beyond palette size\n", off, j); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto next_frame; } off *= 3; - while(j-- && sz < 256) { + while (j-- && sz < 256) { *pal++ = oldpal[off + 0]; *pal++ = oldpal[off + 1]; *pal++ = oldpal[off + 2]; @@ -315,77 +291,97 @@ } } avio_seek(s->pb, pos, 0); - palchange |= 1; + smk->new_palette = 1; } - flags >>= 1; - smk->curstream = -1; - /* if audio chunks are present, put them to stack and retrieve later */ - for(i = 0; i < 7; i++) { - if(flags & 1) { - uint32_t size; - int err; - - size = avio_rl32(s->pb) - 4; - if (!size || size + 4LL > frame_size) { - av_log(s, AV_LOG_ERROR, "Invalid audio part size\n"); - return AVERROR_INVALIDDATA; - } - frame_size -= size; - frame_size -= 4; - smk->curstream++; - if ((err = av_reallocp(&smk->bufs[smk->curstream], size)) < 0) { - smk->buf_sizes[smk->curstream] = 0; - return err; - } - smk->buf_sizes[smk->curstream] = size; - ret = avio_read(s->pb, smk->bufs[smk->curstream], size); - if(ret != size) - return AVERROR(EIO); - smk->stream_id[smk->curstream] = smk->indexes[i]; + } + + for (int i = smk->next_audio_index; i < 7; i++) { + if (smk->flags & (1 << i)) { + uint32_t size; + + size = avio_rl32(s->pb); + if ((int)size < 4 + smk->duration_size[i] || size > smk->frame_size) { + av_log(s, AV_LOG_ERROR, "Invalid audio part size\n"); + ret = AVERROR_INVALIDDATA; + goto next_frame; + } + smk->frame_size -= size; + size -= 4; + + if (smk->indexes[i] < 0 || + s->streams[smk->indexes[i]]->discard >= AVDISCARD_ALL) { + smk->aud_pts[i] += smk->duration_size[i] ? avio_rl32(s->pb) + : size; + avio_skip(s->pb, size - smk->duration_size[i]); + continue; } - flags >>= 1; + if ((ret = av_get_packet(s->pb, pkt, size)) != size) { + ret = ret < 0 ? ret : AVERROR_INVALIDDATA; + goto next_frame; + } + pkt->stream_index = smk->indexes[i]; + pkt->pts = smk->aud_pts[i]; + pkt->duration = smk->duration_size[i] ? AV_RL32(pkt->data) + : size; + smk->aud_pts[i] += pkt->duration; + smk->next_audio_index = i + 1; + return 0; } - if (frame_size < 0 || frame_size >= INT_MAX/2) - return AVERROR_INVALIDDATA; - if (av_new_packet(pkt, frame_size + 769)) - return AVERROR(ENOMEM); - if(smk->frm_size[smk->cur_frame] & 1) - palchange |= 2; - pkt->data[0] = palchange; - memcpy(pkt->data + 1, smk->pal, 768); - ret = avio_read(s->pb, pkt->data + 769, frame_size); - if(ret != frame_size) - return AVERROR(EIO); - pkt->stream_index = smk->videoindex; - pkt->pts = smk->cur_frame; - pkt->size = ret + 769; - smk->cur_frame++; - smk->nextpos = avio_tell(s->pb); - } else { - if (smk->stream_id[smk->curstream] < 0 || !smk->bufs[smk->curstream]) - return AVERROR_INVALIDDATA; - if (av_new_packet(pkt, smk->buf_sizes[smk->curstream])) - return AVERROR(ENOMEM); - memcpy(pkt->data, smk->bufs[smk->curstream], smk->buf_sizes[smk->curstream]); - pkt->size = smk->buf_sizes[smk->curstream]; - pkt->stream_index = smk->stream_id[smk->curstream]; - pkt->pts = smk->aud_pts[smk->curstream]; - smk->aud_pts[smk->curstream] += AV_RL32(pkt->data); - smk->curstream--; } + if (s->streams[smk->videoindex]->discard >= AVDISCARD_ALL) { + ret = FFERROR_REDO; + goto next_frame; + } + if (smk->frame_size >= INT_MAX/2) { + ret = AVERROR_INVALIDDATA; + goto next_frame; + } + if ((ret = av_new_packet(pkt, smk->frame_size + 769)) < 0) + goto next_frame; + flags = smk->new_palette; + if (smk->frm_size[smk->cur_frame] & 1) + flags |= 2; + pkt->data[0] = flags; + memcpy(pkt->data + 1, smk->pal, 768); + ret = ffio_read_size(s->pb, pkt->data + 769, smk->frame_size); + if (ret < 0) + goto next_frame; + pkt->stream_index = smk->videoindex; + pkt->pts = smk->cur_frame; + smk->next_audio_index = 0; + smk->new_palette = 0; + smk->cur_frame++; + return 0; +next_frame: + avio_seek(s->pb, smk->next_frame_pos, SEEK_SET); + smk->next_audio_index = 0; + smk->cur_frame++; + return ret; } -static int smacker_read_close(AVFormatContext *s) +static int smacker_read_seek(AVFormatContext *s, int stream_index, + int64_t timestamp, int flags) { SmackerContext *smk = s->priv_data; - int i; + int64_t ret; + + /* only rewinding to start is supported */ + if (timestamp != 0) { + av_log(s, AV_LOG_ERROR, + "Random seeks are not supported (can only seek to start).\n"); + return AVERROR(EINVAL); + } + + if ((ret = avio_seek(s->pb, s->internal->data_offset, SEEK_SET)) < 0) + return ret; - for(i = 0; i < 7; i++) - av_freep(&smk->bufs[i]); - av_freep(&smk->frm_size); - av_freep(&smk->frm_flags); + smk->cur_frame = 0; + smk->next_audio_index = 0; + smk->new_palette = 0; + memset(smk->pal, 0, sizeof(smk->pal)); + memset(smk->aud_pts, 0, sizeof(smk->aud_pts)); return 0; } @@ -397,5 +393,5 @@ .read_probe = smacker_probe, .read_header = smacker_read_header, .read_packet = smacker_read_packet, - .read_close = smacker_read_close, + .read_seek = smacker_read_seek, }; diff -Nru ffmpeg-4.2.2/libavformat/smjpegdec.c ffmpeg-4.4/libavformat/smjpegdec.c --- ffmpeg-4.2.2/libavformat/smjpegdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/smjpegdec.c 2020-07-11 10:39:32.000000000 +0000 @@ -51,6 +51,9 @@ uint32_t version, htype, hlength, duration; char *comment; + sc->audio_stream_index = + sc->video_stream_index = -1; + avio_skip(pb, 8); // magic version = avio_rb32(pb); if (version) @@ -147,6 +150,8 @@ dtype = avio_rl32(s->pb); switch (dtype) { case SMJPEG_SNDD: + if (sc->audio_stream_index < 0) + return AVERROR_INVALIDDATA; timestamp = avio_rb32(s->pb); size = avio_rb32(s->pb); ret = av_get_packet(s->pb, pkt, size); @@ -155,6 +160,8 @@ pkt->pos = pos; break; case SMJPEG_VIDD: + if (sc->video_stream_index < 0) + return AVERROR_INVALIDDATA; timestamp = avio_rb32(s->pb); size = avio_rb32(s->pb); ret = av_get_packet(s->pb, pkt, size); diff -Nru ffmpeg-4.2.2/libavformat/smjpegenc.c ffmpeg-4.4/libavformat/smjpegenc.c --- ffmpeg-4.2.2/libavformat/smjpegenc.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/smjpegenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -88,7 +88,6 @@ } avio_wl32(pb, SMJPEG_HEND); - avio_flush(pb); return 0; } diff -Nru ffmpeg-4.2.2/libavformat/smoothstreamingenc.c ffmpeg-4.4/libavformat/smoothstreamingenc.c --- ffmpeg-4.2.2/libavformat/smoothstreamingenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/smoothstreamingenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -49,7 +49,6 @@ typedef struct OutputStream { AVFormatContext *ctx; - int ctx_inited; char dirname[1024]; uint8_t iobuf[32768]; URLContext *out; // Current output stream where all output is written @@ -99,14 +98,9 @@ if (whence != SEEK_SET) return AVERROR(ENOSYS); if (os->tail_out) { - if (os->out) { - ffurl_close(os->out); - } - if (os->out2) { - ffurl_close(os->out2); - } + ffurl_closep(&os->out); + ffurl_closep(&os->out2); os->out = os->tail_out; - os->out2 = NULL; os->tail_out = NULL; } if (offset >= os->cur_start_pos) { @@ -175,16 +169,12 @@ return; for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; - ffurl_close(os->out); - ffurl_close(os->out2); - ffurl_close(os->tail_out); - os->out = os->out2 = os->tail_out = NULL; - if (os->ctx && os->ctx_inited) - av_write_trailer(os->ctx); + ffurl_closep(&os->out); + ffurl_closep(&os->out2); + ffurl_closep(&os->tail_out); if (os->ctx && os->ctx->pb) avio_context_free(&os->ctx->pb); - if (os->ctx) - avformat_free_context(os->ctx); + avformat_free_context(os->ctx); av_freep(&os->private_str); for (j = 0; j < os->nb_fragments; j++) av_freep(&os->fragments[j]); @@ -296,21 +286,18 @@ ff_const59 AVOutputFormat *oformat; if (mkdir(s->url, 0777) == -1 && errno != EEXIST) { - ret = AVERROR(errno); av_log(s, AV_LOG_ERROR, "mkdir failed\n"); - goto fail; + return AVERROR(errno); } oformat = av_guess_format("ismv", NULL, NULL); if (!oformat) { - ret = AVERROR_MUXER_NOT_FOUND; - goto fail; + return AVERROR_MUXER_NOT_FOUND; } c->streams = av_mallocz_array(s->nb_streams, sizeof(*c->streams)); if (!c->streams) { - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } for (i = 0; i < s->nb_streams; i++) { @@ -328,23 +315,21 @@ } if (mkdir(os->dirname, 0777) == -1 && errno != EEXIST) { - ret = AVERROR(errno); av_log(s, AV_LOG_ERROR, "mkdir failed\n"); - goto fail; + return AVERROR(errno); } - ctx = avformat_alloc_context(); - if (!ctx || ff_copy_whiteblacklists(ctx, s) < 0) { - ret = AVERROR(ENOMEM); - goto fail; + os->ctx = ctx = avformat_alloc_context(); + if (!ctx) { + return AVERROR(ENOMEM); } - os->ctx = ctx; + if ((ret = ff_copy_whiteblacklists(ctx, s)) < 0) + return ret; ctx->oformat = oformat; ctx->interrupt_callback = s->interrupt_callback; if (!(st = avformat_new_stream(ctx, NULL))) { - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar); st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; @@ -352,18 +337,17 @@ ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), AVIO_FLAG_WRITE, os, NULL, ism_write, ism_seek); if (!ctx->pb) { - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } av_dict_set_int(&opts, "ism_lookahead", c->lookahead_count, 0); av_dict_set(&opts, "movflags", "frag_custom", 0); - if ((ret = avformat_write_header(ctx, &opts)) < 0) { - goto fail; + ret = avformat_write_header(ctx, &opts); + av_dict_free(&opts); + if (ret < 0) { + return ret; } - os->ctx_inited = 1; avio_flush(ctx->pb); - av_dict_free(&opts); s->streams[i]->time_base = st->time_base; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { c->has_video = 1; @@ -374,8 +358,7 @@ os->fourcc = "WVC1"; } else { av_log(s, AV_LOG_ERROR, "Unsupported video codec\n"); - ret = AVERROR(EINVAL); - goto fail; + return AVERROR(EINVAL); } } else { c->has_audio = 1; @@ -388,8 +371,7 @@ os->audio_tag = 0x0162; } else { av_log(s, AV_LOG_ERROR, "Unsupported audio codec\n"); - ret = AVERROR(EINVAL); - goto fail; + return AVERROR(EINVAL); } os->packet_size = st->codecpar->block_align ? st->codecpar->block_align : 4; } @@ -398,15 +380,13 @@ if (!c->has_video && c->min_frag_duration <= 0) { av_log(s, AV_LOG_WARNING, "no video stream and no min frag duration set\n"); - ret = AVERROR(EINVAL); - goto fail; + return AVERROR(EINVAL); } ret = write_manifest(s, 0); + if (ret < 0) + return ret; -fail: - if (ret) - ism_free(s); - return ret; + return 0; } static int parse_fragment(AVFormatContext *s, const char *filename, int64_t *start_ts, int64_t *duration, int64_t *moof_size, int64_t size) @@ -465,7 +445,7 @@ Fragment *frag; if (os->nb_fragments >= os->fragments_size) { os->fragments_size = (os->fragments_size + 1) * 2; - if ((err = av_reallocp(&os->fragments, sizeof(*os->fragments) * + if ((err = av_reallocp_array(&os->fragments, sizeof(*os->fragments), os->fragments_size)) < 0) { os->fragments_size = 0; os->nb_fragments = 0; @@ -538,8 +518,7 @@ if (!os->out || os->tail_out) return AVERROR(EIO); - ffurl_close(os->out); - os->out = NULL; + ffurl_closep(&os->out); size = os->tail_pos - os->cur_start_pos; if ((ret = parse_fragment(s, filename, &start_ts, &duration, &moof_size, size)) < 0) break; @@ -636,7 +615,6 @@ rmdir(s->url); } - ism_free(s); return 0; } @@ -669,5 +647,6 @@ .write_header = ism_write_header, .write_packet = ism_write_packet, .write_trailer = ism_write_trailer, + .deinit = ism_free, .priv_class = &ism_class, }; diff -Nru ffmpeg-4.2.2/libavformat/smush.c ffmpeg-4.4/libavformat/smush.c --- ffmpeg-4.2.2/libavformat/smush.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/smush.c 2020-07-11 10:39:30.000000000 +0000 @@ -51,6 +51,7 @@ uint32_t magic, nframes, size, subversion, i; uint32_t width = 0, height = 0, got_audio = 0, read = 0; uint32_t sample_rate, channels, palette[256]; + int ret; magic = avio_rb32(pb); avio_skip(pb, 4); // skip movie size @@ -157,8 +158,8 @@ vst->codecpar->height = height; if (!smush->version) { - if (ff_alloc_extradata(vst->codecpar, 1024 + 2)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(vst->codecpar, 1024 + 2)) < 0) + return ret; AV_WL16(vst->codecpar->extradata, subversion); for (i = 0; i < 256; i++) diff -Nru ffmpeg-4.2.2/libavformat/soxdec.c ffmpeg-4.4/libavformat/soxdec.c --- ffmpeg-4.2.2/libavformat/soxdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/soxdec.c 2021-02-20 20:27:47.000000000 +0000 @@ -90,7 +90,7 @@ sample_rate_frac); if ((header_size + 4) & 7 || header_size < SOX_FIXED_HDR + comment_size - || st->codecpar->channels > 65535) /* Reserve top 16 bits */ { + || st->codecpar->channels > 65535 || st->codecpar->channels <= 0) /* Reserve top 16 bits */ { av_log(s, AV_LOG_ERROR, "invalid header\n"); return AVERROR_INVALIDDATA; } diff -Nru ffmpeg-4.2.2/libavformat/soxenc.c ffmpeg-4.4/libavformat/soxenc.c --- ffmpeg-4.2.2/libavformat/soxenc.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/soxenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -80,8 +80,6 @@ ffio_fill(pb, 0, comment_size - comment_len); - avio_flush(pb); - return 0; } @@ -101,8 +99,6 @@ } else avio_wb64(pb, num_samples); avio_seek(pb, file_size, SEEK_SET); - - avio_flush(pb); } return 0; diff -Nru ffmpeg-4.2.2/libavformat/spdifdec.c ffmpeg-4.4/libavformat/spdifdec.c --- ffmpeg-4.2.2/libavformat/spdifdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/spdifdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -197,15 +197,13 @@ pkt->pos = avio_tell(pb) - BURST_HEADER_SIZE; if (avio_read(pb, pkt->data, pkt->size) < pkt->size) { - av_packet_unref(pkt); return AVERROR_EOF; } ff_spdif_bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, pkt->size >> 1); ret = spdif_get_offset_and_codec(s, data_type, pkt->data, &offset, &codec_id); - if (ret) { - av_packet_unref(pkt); + if (ret < 0) { return ret; } @@ -216,7 +214,6 @@ /* first packet, create a stream */ AVStream *st = avformat_new_stream(s, NULL); if (!st) { - av_packet_unref(pkt); return AVERROR(ENOMEM); } st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; diff -Nru ffmpeg-4.2.2/libavformat/spdifenc.c ffmpeg-4.4/libavformat/spdifenc.c --- ffmpeg-4.2.2/libavformat/spdifenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/spdifenc.c 2021-04-08 21:28:27.000000000 +0000 @@ -1,7 +1,7 @@ /* * IEC 61937 muxer * Copyright (c) 2009 Bartlomiej Wolowiec - * Copyright (c) 2010 Anssi Hannula + * Copyright (c) 2010, 2020 Anssi Hannula * Copyright (c) 2010 Carl Eugen Hoyos * * This file is part of FFmpeg. @@ -69,13 +69,18 @@ int use_preamble; ///< preamble enabled (disabled for exactly pre-padded DTS) int extra_bswap; ///< extra bswap for payload (for LE DTS => standard BE DTS) - uint8_t *hd_buf; ///< allocated buffer to concatenate hd audio frames - int hd_buf_size; ///< size of the hd audio buffer - int hd_buf_count; ///< number of frames in the hd audio buffer - int hd_buf_filled; ///< amount of bytes in the hd audio buffer + uint8_t *hd_buf[2]; ///< allocated buffers to concatenate hd audio frames + int hd_buf_size; ///< size of the hd audio buffer (eac3, dts4) + int hd_buf_count; ///< number of frames in the hd audio buffer (eac3) + int hd_buf_filled; ///< amount of bytes in the hd audio buffer (eac3, truehd) + int hd_buf_idx; ///< active hd buffer index (truehd) int dtshd_skip; ///< counter used for skipping DTS-HD frames + uint16_t truehd_prev_time; ///< input_timing from the last frame + int truehd_prev_size; ///< previous frame size in bytes, including any MAT codes + int truehd_samples_per_frame; ///< samples per frame for padding calculation + /* AVOptions: */ int dtshd_rate; int dtshd_fallback; @@ -117,16 +122,18 @@ IEC61937Context *ctx = s->priv_data; static const uint8_t eac3_repeat[4] = {6, 3, 2, 1}; int repeat = 1; + uint8_t *tmp; int bsid = pkt->data[5] >> 3; if (bsid > 10 && (pkt->data[4] & 0xc0) != 0xc0) /* fscod */ repeat = eac3_repeat[(pkt->data[4] & 0x30) >> 4]; /* numblkscod */ - ctx->hd_buf = av_fast_realloc(ctx->hd_buf, &ctx->hd_buf_size, ctx->hd_buf_filled + pkt->size); - if (!ctx->hd_buf) + tmp = av_fast_realloc(ctx->hd_buf[0], &ctx->hd_buf_size, ctx->hd_buf_filled + pkt->size); + if (!tmp) return AVERROR(ENOMEM); + ctx->hd_buf[0] = tmp; - memcpy(&ctx->hd_buf[ctx->hd_buf_filled], pkt->data, pkt->size); + memcpy(&ctx->hd_buf[0][ctx->hd_buf_filled], pkt->data, pkt->size); ctx->hd_buf_filled += pkt->size; if (++ctx->hd_buf_count < repeat){ @@ -135,7 +142,7 @@ } ctx->data_type = IEC61937_EAC3; ctx->pkt_offset = 24576; - ctx->out_buf = ctx->hd_buf; + ctx->out_buf = ctx->hd_buf[0]; ctx->out_bytes = ctx->hd_buf_filled; ctx->length_code = ctx->hd_buf_filled; @@ -228,15 +235,15 @@ * with some receivers, but the exact requirement is unconfirmed. */ ctx->length_code = FFALIGN(ctx->out_bytes + 0x8, 0x10) - 0x8; - av_fast_malloc(&ctx->hd_buf, &ctx->hd_buf_size, ctx->out_bytes); - if (!ctx->hd_buf) + av_fast_malloc(&ctx->hd_buf[0], &ctx->hd_buf_size, ctx->out_bytes); + if (!ctx->hd_buf[0]) return AVERROR(ENOMEM); - ctx->out_buf = ctx->hd_buf; + ctx->out_buf = ctx->hd_buf[0]; - memcpy(ctx->hd_buf, dtshd_start_code, sizeof(dtshd_start_code)); - AV_WB16(ctx->hd_buf + sizeof(dtshd_start_code), pkt_size); - memcpy(ctx->hd_buf + sizeof(dtshd_start_code) + 2, pkt->data, pkt_size); + memcpy(ctx->hd_buf[0], dtshd_start_code, sizeof(dtshd_start_code)); + AV_WB16(ctx->hd_buf[0] + sizeof(dtshd_start_code), pkt_size); + memcpy(ctx->hd_buf[0] + sizeof(dtshd_start_code) + 2, pkt->data, pkt_size); return 0; } @@ -384,62 +391,175 @@ /* * It seems Dolby TrueHD frames have to be encapsulated in MAT frames before * they can be encapsulated in IEC 61937. - * Here we encapsulate 24 TrueHD frames in a single MAT frame, padding them - * to achieve constant rate. - * The actual format of a MAT frame is unknown, but the below seems to work. - * However, it seems it is not actually necessary for the 24 TrueHD frames to - * be in an exact alignment with the MAT frame. */ +#define MAT_PKT_OFFSET 61440 #define MAT_FRAME_SIZE 61424 -#define TRUEHD_FRAME_OFFSET 2560 -#define MAT_MIDDLE_CODE_OFFSET -4 + +static const uint8_t mat_start_code[20] = { + 0x07, 0x9E, 0x00, 0x03, 0x84, 0x01, 0x01, 0x01, 0x80, 0x00, 0x56, 0xA5, 0x3B, 0xF4, 0x81, 0x83, + 0x49, 0x80, 0x77, 0xE0, +}; +static const uint8_t mat_middle_code[12] = { + 0xC3, 0xC1, 0x42, 0x49, 0x3B, 0xFA, 0x82, 0x83, 0x49, 0x80, 0x77, 0xE0, +}; +static const uint8_t mat_end_code[16] = { + 0xC3, 0xC2, 0xC0, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x11, +}; + +#define MAT_CODE(position, data) { .pos = position, .code = data, .len = sizeof(data) } + +static const struct { + unsigned int pos; + const uint8_t *code; + unsigned int len; +} mat_codes[] = { + MAT_CODE(0, mat_start_code), + MAT_CODE(30708, mat_middle_code), + MAT_CODE(MAT_FRAME_SIZE - sizeof(mat_end_code), mat_end_code), +}; static int spdif_header_truehd(AVFormatContext *s, AVPacket *pkt) { IEC61937Context *ctx = s->priv_data; - int mat_code_length = 0; - static const char mat_end_code[16] = { 0xC3, 0xC2, 0xC0, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x11 }; + uint8_t *hd_buf = ctx->hd_buf[ctx->hd_buf_idx]; + int ratebits; + int padding_remaining = 0; + uint16_t input_timing; + int total_frame_size = pkt->size; + const uint8_t *dataptr = pkt->data; + int data_remaining = pkt->size; + int have_pkt = 0; + int next_code_idx; - if (!ctx->hd_buf_count) { - static const char mat_start_code[20] = { 0x07, 0x9E, 0x00, 0x03, 0x84, 0x01, 0x01, 0x01, 0x80, 0x00, 0x56, 0xA5, 0x3B, 0xF4, 0x81, 0x83, 0x49, 0x80, 0x77, 0xE0 }; - mat_code_length = sizeof(mat_start_code) + BURST_HEADER_SIZE; - memcpy(ctx->hd_buf, mat_start_code, sizeof(mat_start_code)); - - } else if (ctx->hd_buf_count == 12) { - static const char mat_middle_code[12] = { 0xC3, 0xC1, 0x42, 0x49, 0x3B, 0xFA, 0x82, 0x83, 0x49, 0x80, 0x77, 0xE0 }; - mat_code_length = sizeof(mat_middle_code) + MAT_MIDDLE_CODE_OFFSET; - memcpy(&ctx->hd_buf[12 * TRUEHD_FRAME_OFFSET - BURST_HEADER_SIZE + MAT_MIDDLE_CODE_OFFSET], - mat_middle_code, sizeof(mat_middle_code)); - } - - if (pkt->size > TRUEHD_FRAME_OFFSET - mat_code_length) { - /* if such frames exist, we'd need some more complex logic to - * distribute the TrueHD frames in the MAT frame */ - avpriv_request_sample(s, "Too large TrueHD frame of %d bytes", - pkt->size); - return AVERROR_PATCHWELCOME; + if (pkt->size < 10) + return AVERROR_INVALIDDATA; + + if (AV_RB24(pkt->data + 4) == 0xf8726f) { + /* major sync unit, fetch sample rate */ + if (pkt->data[7] == 0xba) + ratebits = pkt->data[8] >> 4; + else if (pkt->data[7] == 0xbb) + ratebits = pkt->data[9] >> 4; + else + return AVERROR_INVALIDDATA; + + ctx->truehd_samples_per_frame = 40 << (ratebits & 3); + av_log(s, AV_LOG_TRACE, "TrueHD samples per frame: %d\n", + ctx->truehd_samples_per_frame); } - memcpy(&ctx->hd_buf[ctx->hd_buf_count * TRUEHD_FRAME_OFFSET - BURST_HEADER_SIZE + mat_code_length], - pkt->data, pkt->size); - if (ctx->hd_buf_count < 23) { - memset(&ctx->hd_buf[ctx->hd_buf_count * TRUEHD_FRAME_OFFSET - BURST_HEADER_SIZE + mat_code_length + pkt->size], - 0, TRUEHD_FRAME_OFFSET - pkt->size - mat_code_length); - } else { - size_t padding = MAT_FRAME_SIZE - (ctx->hd_buf_count * TRUEHD_FRAME_OFFSET - BURST_HEADER_SIZE + pkt->size); - memset(&ctx->hd_buf[MAT_FRAME_SIZE - padding], 0, padding); + if (!ctx->truehd_samples_per_frame) + return AVERROR_INVALIDDATA; + + input_timing = AV_RB16(pkt->data + 2); + if (ctx->truehd_prev_size) { + uint16_t delta_samples = input_timing - ctx->truehd_prev_time; + /* + * One multiple-of-48kHz frame is 1/1200 sec and the IEC 61937 rate + * is 768kHz = 768000*4 bytes/sec. + * The nominal space per frame is therefore + * (768000*4 bytes/sec) * (1/1200 sec) = 2560 bytes. + * For multiple-of-44.1kHz frames: 1/1102.5 sec, 705.6kHz, 2560 bytes. + * + * 2560 is divisible by truehd_samples_per_frame. + */ + int delta_bytes = delta_samples * 2560 / ctx->truehd_samples_per_frame; + + /* padding needed before this frame */ + padding_remaining = delta_bytes - ctx->truehd_prev_size; + + av_log(s, AV_LOG_TRACE, "delta_samples: %"PRIu16", delta_bytes: %d\n", + delta_samples, delta_bytes); + + /* sanity check */ + if (padding_remaining < 0 || padding_remaining >= MAT_FRAME_SIZE / 2) { + avpriv_request_sample(s, "Unusual frame timing: %"PRIu16" => %"PRIu16", %d samples/frame", + ctx->truehd_prev_time, input_timing, ctx->truehd_samples_per_frame); + padding_remaining = 0; + } + } + + for (next_code_idx = 0; next_code_idx < FF_ARRAY_ELEMS(mat_codes); next_code_idx++) + if (ctx->hd_buf_filled <= mat_codes[next_code_idx].pos) + break; + + if (next_code_idx >= FF_ARRAY_ELEMS(mat_codes)) + return AVERROR_BUG; + + while (padding_remaining || data_remaining || + mat_codes[next_code_idx].pos == ctx->hd_buf_filled) { + + if (mat_codes[next_code_idx].pos == ctx->hd_buf_filled) { + /* time to insert MAT code */ + int code_len = mat_codes[next_code_idx].len; + int code_len_remaining = code_len; + memcpy(hd_buf + mat_codes[next_code_idx].pos, + mat_codes[next_code_idx].code, code_len); + ctx->hd_buf_filled += code_len; + + next_code_idx++; + if (next_code_idx == FF_ARRAY_ELEMS(mat_codes)) { + next_code_idx = 0; + + /* this was the last code, move to the next MAT frame */ + have_pkt = 1; + ctx->out_buf = hd_buf; + ctx->hd_buf_idx ^= 1; + hd_buf = ctx->hd_buf[ctx->hd_buf_idx]; + ctx->hd_buf_filled = 0; + + /* inter-frame gap has to be counted as well, add it */ + code_len_remaining += MAT_PKT_OFFSET - MAT_FRAME_SIZE; + } + + if (padding_remaining) { + /* consider the MAT code as padding */ + int counted_as_padding = FFMIN(padding_remaining, + code_len_remaining); + padding_remaining -= counted_as_padding; + code_len_remaining -= counted_as_padding; + } + /* count the remainder of the code as part of frame size */ + if (code_len_remaining) + total_frame_size += code_len_remaining; + } + + if (padding_remaining) { + int padding_to_insert = FFMIN(mat_codes[next_code_idx].pos - ctx->hd_buf_filled, + padding_remaining); + + memset(hd_buf + ctx->hd_buf_filled, 0, padding_to_insert); + ctx->hd_buf_filled += padding_to_insert; + padding_remaining -= padding_to_insert; + + if (padding_remaining) + continue; /* time to insert MAT code */ + } + + if (data_remaining) { + int data_to_insert = FFMIN(mat_codes[next_code_idx].pos - ctx->hd_buf_filled, + data_remaining); + + memcpy(hd_buf + ctx->hd_buf_filled, dataptr, data_to_insert); + ctx->hd_buf_filled += data_to_insert; + dataptr += data_to_insert; + data_remaining -= data_to_insert; + } } - if (++ctx->hd_buf_count < 24){ + ctx->truehd_prev_size = total_frame_size; + ctx->truehd_prev_time = input_timing; + + av_log(s, AV_LOG_TRACE, "TrueHD frame inserted, total size %d, buffer position %d\n", + total_frame_size, ctx->hd_buf_filled); + + if (!have_pkt) { ctx->pkt_offset = 0; return 0; } - memcpy(&ctx->hd_buf[MAT_FRAME_SIZE - sizeof(mat_end_code)], mat_end_code, sizeof(mat_end_code)); - ctx->hd_buf_count = 0; ctx->data_type = IEC61937_TRUEHD; - ctx->pkt_offset = 61440; - ctx->out_buf = ctx->hd_buf; + ctx->pkt_offset = MAT_PKT_OFFSET; ctx->out_bytes = MAT_FRAME_SIZE; ctx->length_code = MAT_FRAME_SIZE; return 0; @@ -470,9 +590,11 @@ case AV_CODEC_ID_TRUEHD: case AV_CODEC_ID_MLP: ctx->header_info = spdif_header_truehd; - ctx->hd_buf = av_malloc(MAT_FRAME_SIZE); - if (!ctx->hd_buf) - return AVERROR(ENOMEM); + for (int i = 0; i < FF_ARRAY_ELEMS(ctx->hd_buf); i++) { + ctx->hd_buf[i] = av_malloc(MAT_FRAME_SIZE); + if (!ctx->hd_buf[i]) + return AVERROR(ENOMEM); + } break; default: avpriv_report_missing_feature(s, "Codec %d", @@ -482,12 +604,12 @@ return 0; } -static int spdif_write_trailer(AVFormatContext *s) +static void spdif_deinit(AVFormatContext *s) { IEC61937Context *ctx = s->priv_data; av_freep(&ctx->buffer); - av_freep(&ctx->hd_buf); - return 0; + for (int i = 0; i < FF_ARRAY_ELEMS(ctx->hd_buf); i++) + av_freep(&ctx->hd_buf[i]); } static av_always_inline void spdif_put_16(IEC61937Context *ctx, @@ -560,7 +682,7 @@ .video_codec = AV_CODEC_ID_NONE, .write_header = spdif_write_header, .write_packet = spdif_write_packet, - .write_trailer = spdif_write_trailer, + .deinit = spdif_deinit, .flags = AVFMT_NOTIMESTAMPS, .priv_class = &spdif_class, }; diff -Nru ffmpeg-4.2.2/libavformat/srtdec.c ffmpeg-4.4/libavformat/srtdec.c --- ffmpeg-4.2.2/libavformat/srtdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/srtdec.c 2020-07-09 09:17:49.000000000 +0000 @@ -207,6 +207,8 @@ ff_subtitles_queue_finalize(s, &srt->q); end: + if (res < 0) + ff_subtitles_queue_clean(&srt->q); av_bprint_finalize(&buf, NULL); return res; } diff -Nru ffmpeg-4.2.2/libavformat/srtenc.c ffmpeg-4.4/libavformat/srtenc.c --- ffmpeg-4.2.2/libavformat/srtenc.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/srtenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -61,7 +61,8 @@ SRTContext *srt = avf->priv_data; int64_t s = pkt->pts, e, d = pkt->duration; - int size, x1 = -1, y1 = -1, x2 = -1, y2 = -1; + buffer_size_t size; + int x1 = -1, y1 = -1, x2 = -1, y2 = -1; const uint8_t *p; p = av_packet_get_side_data(pkt, AV_PKT_DATA_SUBTITLE_POSITION, &size); diff -Nru ffmpeg-4.2.2/libavformat/srtpproto.c ffmpeg-4.4/libavformat/srtpproto.c --- ffmpeg-4.2.2/libavformat/srtpproto.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/srtpproto.c 2020-07-11 10:39:30.000000000 +0000 @@ -59,8 +59,7 @@ SRTPProtoContext *s = h->priv_data; ff_srtp_free(&s->srtp_out); ff_srtp_free(&s->srtp_in); - ffurl_close(s->rtp_hd); - s->rtp_hd = NULL; + ffurl_closep(&s->rtp_hd); return 0; } diff -Nru ffmpeg-4.2.2/libavformat/stldec.c ffmpeg-4.4/libavformat/stldec.c --- ffmpeg-4.2.2/libavformat/stldec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/stldec.c 2020-07-09 09:17:49.000000000 +0000 @@ -97,8 +97,10 @@ if (pts_start != AV_NOPTS_VALUE) { AVPacket *sub; sub = ff_subtitles_queue_insert(&stl->q, p, strlen(p), 0); - if (!sub) + if (!sub) { + ff_subtitles_queue_clean(&stl->q); return AVERROR(ENOMEM); + } sub->pos = pos; sub->pts = pts_start; sub->duration = duration; diff -Nru ffmpeg-4.2.2/libavformat/subfile.c ffmpeg-4.4/libavformat/subfile.c --- ffmpeg-4.2.2/libavformat/subfile.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/subfile.c 2020-07-11 10:39:30.000000000 +0000 @@ -86,7 +86,7 @@ return ret; c->pos = c->start; if ((ret = slave_seek(h)) < 0) { - ffurl_close(c->h); + ffurl_closep(&c->h); return ret; } return 0; @@ -95,7 +95,7 @@ static int subfile_close(URLContext *h) { SubfileContext *c = h->priv_data; - return ffurl_close(c->h); + return ffurl_closep(&c->h); } static int subfile_read(URLContext *h, unsigned char *buf, int size) @@ -116,7 +116,7 @@ static int64_t subfile_seek(URLContext *h, int64_t pos, int whence) { SubfileContext *c = h->priv_data; - int64_t new_pos = -1, end; + int64_t new_pos, end; int ret; if (whence == AVSEEK_SIZE || whence == SEEK_END) { @@ -132,10 +132,10 @@ new_pos = c->start + pos; break; case SEEK_CUR: - new_pos += pos; + new_pos = c->pos + pos; break; case SEEK_END: - new_pos = end + c->pos; + new_pos = end + pos; break; } if (new_pos < c->start) diff -Nru ffmpeg-4.2.2/libavformat/subtitles.c ffmpeg-4.4/libavformat/subtitles.c --- ffmpeg-4.2.2/libavformat/subtitles.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/subtitles.c 2021-04-08 21:28:40.000000000 +0000 @@ -111,13 +111,13 @@ AVPacket *ff_subtitles_queue_insert(FFDemuxSubtitlesQueue *q, const uint8_t *event, size_t len, int merge) { - AVPacket *subs, *sub; + AVPacket **subs, *sub; if (merge && q->nb_subs > 0) { /* merge with previous event */ int old_len; - sub = &q->subs[q->nb_subs - 1]; + sub = q->subs[q->nb_subs - 1]; old_len = sub->size; if (av_grow_packet(sub, len) < 0) return NULL; @@ -132,9 +132,14 @@ if (!subs) return NULL; q->subs = subs; - sub = &subs[q->nb_subs++]; - if (av_new_packet(sub, len) < 0) + sub = av_packet_alloc(); + if (!sub) return NULL; + if (av_new_packet(sub, len) < 0) { + av_packet_free(&sub); + return NULL; + } + subs[q->nb_subs++] = sub; sub->flags |= AV_PKT_FLAG_KEY; sub->pts = sub->dts = 0; memcpy(sub->data, event, len); @@ -144,8 +149,8 @@ static int cmp_pkt_sub_ts_pos(const void *a, const void *b) { - const AVPacket *s1 = a; - const AVPacket *s2 = b; + const AVPacket *s1 = *(const AVPacket **)a; + const AVPacket *s2 = *(const AVPacket **)b; if (s1->pts == s2->pts) return FFDIFFSIGN(s1->pos, s2->pos); return FFDIFFSIGN(s1->pts , s2->pts); @@ -153,8 +158,8 @@ static int cmp_pkt_sub_pos_ts(const void *a, const void *b) { - const AVPacket *s1 = a; - const AVPacket *s2 = b; + const AVPacket *s1 = *(const AVPacket **)a; + const AVPacket *s2 = *(const AVPacket **)b; if (s1->pos == s2->pos) { if (s1->pts == s2->pts) return 0; @@ -169,18 +174,18 @@ for (i = 1; i < q->nb_subs; i++) { const int last_id = i - 1 - drop; - const AVPacket *last = &q->subs[last_id]; + const AVPacket *last = q->subs[last_id]; - if (q->subs[i].pts == last->pts && - q->subs[i].duration == last->duration && - q->subs[i].stream_index == last->stream_index && - !strcmp(q->subs[i].data, last->data)) { + if (q->subs[i]->pts == last->pts && + q->subs[i]->duration == last->duration && + q->subs[i]->stream_index == last->stream_index && + !strcmp(q->subs[i]->data, last->data)) { - av_packet_unref(&q->subs[i]); + av_packet_free(&q->subs[i]); drop++; } else if (drop) { q->subs[last_id + 1] = q->subs[i]; - memset(&q->subs[i], 0, sizeof(q->subs[i])); // for safety + q->subs[i] = NULL; } } @@ -201,8 +206,8 @@ q->sort == SUB_SORT_TS_POS ? cmp_pkt_sub_ts_pos : cmp_pkt_sub_pos_ts); for (i = 0; i < q->nb_subs; i++) - if (q->subs[i].duration < 0 && i < q->nb_subs - 1) - q->subs[i].duration = q->subs[i + 1].pts - q->subs[i].pts; + if (q->subs[i]->duration < 0 && i < q->nb_subs - 1) + q->subs[i]->duration = q->subs[i + 1]->pts - q->subs[i]->pts; if (!q->keep_duplicates) drop_dups(log_ctx, q); @@ -210,12 +215,14 @@ int ff_subtitles_queue_read_packet(FFDemuxSubtitlesQueue *q, AVPacket *pkt) { - AVPacket *sub = q->subs + q->current_sub_idx; + AVPacket *sub; + int ret; if (q->current_sub_idx == q->nb_subs) return AVERROR_EOF; - if (av_packet_ref(pkt, sub) < 0) { - return AVERROR(ENOMEM); + sub = q->subs[q->current_sub_idx]; + if ((ret = av_packet_ref(pkt, sub)) < 0) { + return ret; } pkt->dts = pkt->pts; @@ -236,9 +243,9 @@ if (s1 == s2) return s1; if (s1 == s2 - 1) - return q->subs[s1].pts <= q->subs[s2].pts ? s1 : s2; + return q->subs[s1]->pts <= q->subs[s2]->pts ? s1 : s2; mid = (s1 + s2) / 2; - if (q->subs[mid].pts <= ts) + if (q->subs[mid]->pts <= ts) s1 = mid; else s2 = mid; @@ -260,24 +267,24 @@ if (idx < 0) return idx; - for (i = idx; i < q->nb_subs && q->subs[i].pts < min_ts; i++) - if (stream_index == -1 || q->subs[i].stream_index == stream_index) + for (i = idx; i < q->nb_subs && q->subs[i]->pts < min_ts; i++) + if (stream_index == -1 || q->subs[i]->stream_index == stream_index) idx = i; - for (i = idx; i > 0 && q->subs[i].pts > max_ts; i--) - if (stream_index == -1 || q->subs[i].stream_index == stream_index) + for (i = idx; i > 0 && q->subs[i]->pts > max_ts; i--) + if (stream_index == -1 || q->subs[i]->stream_index == stream_index) idx = i; - ts_selected = q->subs[idx].pts; + ts_selected = q->subs[idx]->pts; if (ts_selected < min_ts || ts_selected > max_ts) return AVERROR(ERANGE); /* look back in the latest subtitles for overlapping subtitles */ for (i = idx - 1; i >= 0; i--) { - int64_t pts = q->subs[i].pts; - if (q->subs[i].duration <= 0 || - (stream_index != -1 && q->subs[i].stream_index != stream_index)) + int64_t pts = q->subs[i]->pts; + if (q->subs[i]->duration <= 0 || + (stream_index != -1 && q->subs[i]->stream_index != stream_index)) continue; - if (pts >= min_ts && pts > ts_selected - q->subs[i].duration) + if (pts >= min_ts && pts > ts_selected - q->subs[i]->duration) idx = i; else break; @@ -289,7 +296,7 @@ * queue is ordered by pts and then filepos, so we can take the first * entry for a given timestamp. */ if (stream_index == -1) - while (idx > 0 && q->subs[idx - 1].pts == q->subs[idx].pts) + while (idx > 0 && q->subs[idx - 1]->pts == q->subs[idx]->pts) idx--; q->current_sub_idx = idx; @@ -302,7 +309,7 @@ int i; for (i = 0; i < q->nb_subs; i++) - av_packet_unref(&q->subs[i]); + av_packet_free(&q->subs[i]); av_freep(&q->subs); q->nb_subs = q->allocated_size = q->current_sub_idx = 0; } diff -Nru ffmpeg-4.2.2/libavformat/subtitles.h ffmpeg-4.4/libavformat/subtitles.h --- ffmpeg-4.2.2/libavformat/subtitles.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/subtitles.h 2021-04-08 21:28:40.000000000 +0000 @@ -100,7 +100,7 @@ void ff_text_read(FFTextReader *r, char *buf, size_t size); typedef struct { - AVPacket *subs; ///< array of subtitles packets + AVPacket **subs; ///< array of subtitles packets int nb_subs; ///< number of subtitles packets int allocated_size; ///< allocated size for subs int current_sub_idx; ///< current position for the read packet callback diff -Nru ffmpeg-4.2.2/libavformat/subviewer1dec.c ffmpeg-4.4/libavformat/subviewer1dec.c --- ffmpeg-4.2.2/libavformat/subviewer1dec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/subviewer1dec.c 2020-07-09 09:17:49.000000000 +0000 @@ -77,8 +77,10 @@ sub->duration = pts_start - sub->pts; } else { sub = ff_subtitles_queue_insert(&subviewer1->q, line, len, 0); - if (!sub) + if (!sub) { + ff_subtitles_queue_clean(&subviewer1->q); return AVERROR(ENOMEM); + } sub->pos = pos; sub->pts = pts_start; sub->duration = -1; diff -Nru ffmpeg-4.2.2/libavformat/subviewerdec.c ffmpeg-4.4/libavformat/subviewerdec.c --- ffmpeg-4.2.2/libavformat/subviewerdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/subviewerdec.c 2021-02-20 20:27:47.000000000 +0000 @@ -56,11 +56,21 @@ int64_t end; int hh1, mm1, ss1, ms1; int hh2, mm2, ss2, ms2; + int multiplier = 1; + if (sscanf(s, "%u:%u:%u.%2u,%u:%u:%u.%2u", + &hh1, &mm1, &ss1, &ms1, &hh2, &mm2, &ss2, &ms2) == 8) { + multiplier = 10; + } else if (sscanf(s, "%u:%u:%u.%1u,%u:%u:%u.%1u", + &hh1, &mm1, &ss1, &ms1, &hh2, &mm2, &ss2, &ms2) == 8) { + multiplier = 100; + } if (sscanf(s, "%u:%u:%u.%u,%u:%u:%u.%u", &hh1, &mm1, &ss1, &ms1, &hh2, &mm2, &ss2, &ms2) == 8) { - end = (hh2*3600LL + mm2*60LL + ss2) * 100LL + ms2; - *start = (hh1*3600LL + mm1*60LL + ss1) * 100LL + ms1; + ms1 = FFMIN(ms1, 999); + ms2 = FFMIN(ms2, 999); + end = (hh2*3600LL + mm2*60LL + ss2) * 1000LL + ms2 * multiplier; + *start = (hh1*3600LL + mm1*60LL + ss1) * 1000LL + ms1 * multiplier; *duration = end - *start; return 0; } @@ -84,7 +94,7 @@ return res; if (avio_rb24(s->pb) != 0xefbbbf) avio_seek(s->pb, -3, SEEK_CUR); - avpriv_set_pts_info(st, 64, 1, 100); + avpriv_set_pts_info(st, 64, 1, 1000); st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codecpar->codec_id = AV_CODEC_ID_SUBVIEWER; @@ -138,6 +148,10 @@ new_event = 1; pos = avio_tell(s->pb); } else if (*line) { + if (pts_start == AV_NOPTS_VALUE) { + res = AVERROR_INVALIDDATA; + goto end; + } if (!new_event) { sub = ff_subtitles_queue_insert(&subviewer->q, "\n", 1, 1); if (!sub) { @@ -162,6 +176,8 @@ ff_subtitles_queue_finalize(s, &subviewer->q); end: + if (res < 0) + ff_subtitles_queue_clean(&subviewer->q); av_bprint_finalize(&header, NULL); return res; } diff -Nru ffmpeg-4.2.2/libavformat/svs.c ffmpeg-4.4/libavformat/svs.c --- ffmpeg-4.2.2/libavformat/svs.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/svs.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,96 @@ +/* + * SVS demuxer + * Copyright (c) 2020 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "internal.h" + +static int svs_probe(const AVProbeData *p) +{ + if (p->buf_size < 32) + return 0; + + if (memcmp(p->buf, "SVS\00", 4)) + return 0; + + if (AV_RL32(p->buf + 16) == 0) + return 0; + + return AVPROBE_SCORE_MAX / 3; +} + +static int svs_read_header(AVFormatContext *s) +{ + AVStream *st; + uint32_t pitch; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + avio_skip(s->pb, 16); + pitch = avio_rl32(s->pb); + avio_skip(s->pb, 12); + + s->internal->data_offset = avio_tell(s->pb); + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; + st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->channels = 2; + st->codecpar->sample_rate = av_rescale_rnd(pitch, 48000, 4096, AV_ROUND_INF); + st->codecpar->block_align = 32; + st->start_time = 0; + if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) + st->duration = av_get_audio_frame_duration2(st->codecpar, + avio_size(s->pb) - 32); + + avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); + + return 0; +} + +static int svs_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + int ret; + + if (avio_feof(s->pb)) + return AVERROR_EOF; + + ret = av_get_packet(s->pb, pkt, 32 * 256); + if (ret != 32 * 256) { + if (ret < 0) + return ret; + pkt->flags &= ~AV_PKT_FLAG_CORRUPT; + } + pkt->stream_index = 0; + + return ret; +} + +AVInputFormat ff_svs_demuxer = { + .name = "svs", + .long_name = NULL_IF_CONFIG_SMALL("Square SVS"), + .read_probe = svs_probe, + .read_header = svs_read_header, + .read_packet = svs_read_packet, + .extensions = "svs", +}; diff -Nru ffmpeg-4.2.2/libavformat/swf.c ffmpeg-4.4/libavformat/swf.c --- ffmpeg-4.2.2/libavformat/swf.c 2016-03-29 02:25:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/swf.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,7 +23,9 @@ #include "internal.h" const AVCodecTag ff_swf_codec_tags[] = { - { AV_CODEC_ID_FLV1, 0x02 }, - { AV_CODEC_ID_VP6F, 0x04 }, - { AV_CODEC_ID_NONE, 0 }, + { AV_CODEC_ID_FLV1, 0x02 }, + { AV_CODEC_ID_FLASHSV, 0x03 }, + { AV_CODEC_ID_VP6F, 0x04 }, + { AV_CODEC_ID_VP6A, 0x05 }, + { AV_CODEC_ID_NONE, 0 }, }; diff -Nru ffmpeg-4.2.2/libavformat/swfdec.c ffmpeg-4.4/libavformat/swfdec.c --- ffmpeg-4.2.2/libavformat/swfdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/swfdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -33,6 +33,19 @@ #include "libavutil/intreadwrite.h" #include "libavcodec/get_bits.h" #include "swf.h" +#include "flv.h" + +typedef struct SWFDecContext { + int samples_per_frame; + int frame_rate; +#if CONFIG_ZLIB +#define ZBUF_SIZE 4096 + AVIOContext *zpb; + uint8_t *zbuf_in; + uint8_t *zbuf_out; + z_stream zstream; +#endif +} SWFDecContext; static const AVCodecTag swf_audio_codec_tags[] = { { AV_CODEC_ID_PCM_S16LE, 0x00 }, @@ -78,10 +91,9 @@ && p->buf[3] <= 20) return AVPROBE_SCORE_MAX / 4 + 1; - if (init_get_bits8(&gb, p->buf + 3, p->buf_size - 3) < 0) + if (init_get_bits8(&gb, p->buf + 8, p->buf_size - 8) < 0) return 0; - skip_bits(&gb, 40); len = get_bits(&gb, 5); if (!len) return 0; @@ -102,7 +114,7 @@ static int zlib_refill(void *opaque, uint8_t *buf, int buf_size) { AVFormatContext *s = opaque; - SWFContext *swf = s->priv_data; + SWFDecContext *swf = s->priv_data; z_stream *z = &swf->zstream; int ret; @@ -129,11 +141,13 @@ return buf_size - z->avail_out; } + +static av_cold int swf_read_close(AVFormatContext *avctx); #endif static int swf_read_header(AVFormatContext *s) { - SWFContext *swf = s->priv_data; + SWFDecContext *swf = s->priv_data; AVIOContext *pb = s->pb; int nbits, len, tag; @@ -143,17 +157,18 @@ if (tag == MKBETAG('C', 'W', 'S', 0)) { av_log(s, AV_LOG_INFO, "SWF compressed file detected\n"); #if CONFIG_ZLIB - swf->zbuf_in = av_malloc(ZBUF_SIZE); - swf->zbuf_out = av_malloc(ZBUF_SIZE); - swf->zpb = avio_alloc_context(swf->zbuf_out, ZBUF_SIZE, 0, s, - zlib_refill, NULL, NULL); - if (!swf->zbuf_in || !swf->zbuf_out || !swf->zpb) - return AVERROR(ENOMEM); - swf->zpb->seekable = 0; if (inflateInit(&swf->zstream) != Z_OK) { av_log(s, AV_LOG_ERROR, "Unable to init zlib context\n"); return AVERROR(EINVAL); } + if (!(swf->zbuf_in = av_malloc(ZBUF_SIZE)) || + !(swf->zbuf_out = av_malloc(ZBUF_SIZE)) || + !(swf->zpb = avio_alloc_context(swf->zbuf_out, ZBUF_SIZE, 0, + s, zlib_refill, NULL, NULL))) { + swf_read_close(s); + return AVERROR(ENOMEM); + } + swf->zpb->seekable = 0; pb = swf->zpb; #else av_log(s, AV_LOG_ERROR, "zlib support is required to read SWF compressed files\n"); @@ -201,7 +216,7 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) { - SWFContext *swf = s->priv_data; + SWFDecContext *swf = s->priv_data; AVIOContext *pb = s->pb; AVStream *vst = NULL, *ast = NULL, *st = 0; int tag, len, i, frame, v, res; @@ -278,7 +293,7 @@ return AVERROR(ENOMEM); ast->duration = avio_rl32(pb); // number of samples if (((v>>4) & 15) == 2) { // MP3 sound data record - ast->skip_samples = avio_rl16(pb); + ast->internal->skip_samples = avio_rl16(pb); len -= 2; } len -= 7; @@ -293,15 +308,24 @@ for(i=0; inb_streams; i++) { st = s->streams[i]; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id) { + int pkt_flags = 0; frame = avio_rl16(pb); len -= 2; if (len <= 0) goto skip; + if (st->codecpar->codec_id == AV_CODEC_ID_FLASHSV) { + unsigned flags = avio_r8(pb); + len--; + if (len <= 0) + goto skip; + pkt_flags |= (flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY ? AV_PKT_FLAG_KEY : 0; + } if ((res = av_get_packet(pb, pkt, len)) < 0) return res; pkt->pos = pos; pkt->pts = frame; pkt->stream_index = st->index; + pkt->flags |= pkt_flags; return pkt->size; } } @@ -353,15 +377,25 @@ ff_dlog(s, "bitmap: ch=%d fmt=%d %dx%d (linesize=%d) len=%d->%ld pal=%d\n", ch_id, bmp_fmt, width, height, linesize, len, out_len, colormapsize); + if (len * 17373LL < out_len) + goto bitmap_end_skip; + zbuf = av_malloc(len); - buf = av_malloc(out_len); - if (!zbuf || !buf) { + if (!zbuf) { res = AVERROR(ENOMEM); goto bitmap_end; } len = avio_read(pb, zbuf, len); - if (len < 0 || (res = uncompress(buf, &out_len, zbuf, len)) != Z_OK) { + if (len < 0) + goto bitmap_end_skip; + + buf = av_malloc(out_len); + if (!buf) { + res = AVERROR(ENOMEM); + goto bitmap_end; + } + if ((res = uncompress(buf, &out_len, zbuf, len)) != Z_OK) { av_log(s, AV_LOG_WARNING, "Failed to uncompress one bitmap\n"); goto bitmap_end_skip; } @@ -397,7 +431,6 @@ if (linesize * height > pkt->size) { res = AVERROR_INVALIDDATA; - av_packet_unref(pkt); goto bitmap_end; } @@ -487,7 +520,6 @@ if ((res = av_new_packet(pkt, len)) < 0) return res; if (avio_read(pb, pkt->data, 4) != 4) { - av_packet_unref(pkt); return AVERROR_INVALIDDATA; } if (AV_RB32(pkt->data) == 0xffd8ffd9 || @@ -504,7 +536,6 @@ } if (res != pkt->size) { if (res < 0) { - av_packet_unref(pkt); return res; } av_shrink_packet(pkt, res); @@ -527,7 +558,7 @@ #if CONFIG_ZLIB static av_cold int swf_read_close(AVFormatContext *avctx) { - SWFContext *s = avctx->priv_data; + SWFDecContext *s = avctx->priv_data; inflateEnd(&s->zstream); av_freep(&s->zbuf_in); av_freep(&s->zbuf_out); @@ -539,7 +570,7 @@ AVInputFormat ff_swf_demuxer = { .name = "swf", .long_name = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"), - .priv_data_size = sizeof(SWFContext), + .priv_data_size = sizeof(SWFDecContext), .read_probe = swf_probe, .read_header = swf_read_header, .read_packet = swf_read_packet, diff -Nru ffmpeg-4.2.2/libavformat/swfenc.c ffmpeg-4.4/libavformat/swfenc.c --- ffmpeg-4.2.2/libavformat/swfenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/swfenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -22,12 +22,30 @@ #include "libavcodec/put_bits.h" #include "libavutil/avassert.h" +#include "libavutil/fifo.h" #include "avformat.h" +#include "flv.h" #include "swf.h" +#define AUDIO_FIFO_SIZE 65536 + +typedef struct SWFEncContext { + int64_t duration_pos; + int64_t tag_pos; + int64_t vframes_pos; + int samples_per_frame; + int sound_samples; + int swf_frame_number; + int video_frame_number; + int tag; + AVFifoBuffer *audio_fifo; + AVCodecParameters *audio_par, *video_par; + AVStream *video_st; +} SWFEncContext; + static void put_swf_tag(AVFormatContext *s, int tag) { - SWFContext *swf = s->priv_data; + SWFEncContext *swf = s->priv_data; AVIOContext *pb = s->pb; swf->tag_pos = avio_tell(pb); @@ -43,7 +61,7 @@ static void put_swf_end_tag(AVFormatContext *s) { - SWFContext *swf = s->priv_data; + SWFEncContext *swf = s->priv_data; AVIOContext *pb = s->pb; int64_t pos; int tag_len, tag; @@ -173,7 +191,7 @@ static int swf_write_header(AVFormatContext *s) { - SWFContext *swf = s->priv_data; + SWFEncContext *swf = s->priv_data; AVIOContext *pb = s->pb; PutBitContext p; uint8_t buf1[256]; @@ -205,13 +223,13 @@ av_log(s, AV_LOG_ERROR, "SWF muxer only supports 1 video stream\n"); return AVERROR_INVALIDDATA; } - if (par->codec_id == AV_CODEC_ID_VP6F || - par->codec_id == AV_CODEC_ID_FLV1 || + if (ff_codec_get_tag(ff_swf_codec_tags, par->codec_id) || + par->codec_id == AV_CODEC_ID_PNG || par->codec_id == AV_CODEC_ID_MJPEG) { swf->video_st = s->streams[i]; swf->video_par = par; } else { - av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n"); + av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV, Flash Screen Video, PNG and MJPEG\n"); return -1; } } @@ -240,8 +258,12 @@ if (!strcmp("avm2", s->oformat->name)) version = 9; - else if (swf->video_par && swf->video_par->codec_id == AV_CODEC_ID_VP6F) - version = 8; /* version 8 and above support VP6 codec */ + else if (swf->video_par && (swf->video_par->codec_id == AV_CODEC_ID_VP6A || + swf->video_par->codec_id == AV_CODEC_ID_VP6F || + swf->video_par->codec_id == AV_CODEC_ID_PNG)) + version = 8; /* version 8 and above support VP6 and PNG codec */ + else if (swf->video_par && swf->video_par->codec_id == AV_CODEC_ID_FLASHSV) + version = 7; /* version 7 and above support Flash Screen Video codec */ else if (swf->video_par && swf->video_par->codec_id == AV_CODEC_ID_FLV1) version = 6; /* version 6 and above support FLV1 codec */ else @@ -256,19 +278,19 @@ av_log(s, AV_LOG_ERROR, "Invalid (too large) frame rate %d/%d\n", rate, rate_base); return AVERROR(EINVAL); } - avio_wl16(pb, (rate * 256) / rate_base); /* frame rate */ + avio_wl16(pb, (rate * 256LL) / rate_base); /* frame rate */ swf->duration_pos = avio_tell(pb); avio_wl16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */ - /* avm2/swf v9 (also v8?) files require a file attribute tag */ - if (version == 9) { + /* swf v8 and later files require a file attribute tag */ + if (version >= 8) { put_swf_tag(s, TAG_FILEATTRIBUTES); - avio_wl32(pb, 1<<3); /* set ActionScript v3/AVM2 flag */ + avio_wl32(pb, (version >= 9) << 3); /* set ActionScript v3/AVM2 flag */ put_swf_end_tag(s); } /* define a shape with the jpeg inside */ - if (swf->video_par && swf->video_par->codec_id == AV_CODEC_ID_MJPEG) { + if (swf->video_par && (swf->video_par->codec_id == AV_CODEC_ID_MJPEG || swf->video_par->codec_id == AV_CODEC_ID_PNG)) { put_swf_tag(s, TAG_DEFINESHAPE); avio_wl16(pb, SHAPE_ID); /* ID of shape */ @@ -337,22 +359,21 @@ put_swf_end_tag(s); } - avio_flush(s->pb); return 0; } static int swf_write_video(AVFormatContext *s, - AVCodecParameters *par, const uint8_t *buf, int size) + AVCodecParameters *par, const uint8_t *buf, int size, unsigned pkt_flags) { - SWFContext *swf = s->priv_data; + SWFEncContext *swf = s->priv_data; AVIOContext *pb = s->pb; + unsigned codec_tag = ff_codec_get_tag(ff_swf_codec_tags, par->codec_id); /* Flash Player limit */ if (swf->swf_frame_number == 16000) av_log(s, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n"); - if (par->codec_id == AV_CODEC_ID_VP6F || - par->codec_id == AV_CODEC_ID_FLV1) { + if (codec_tag) { if (swf->video_frame_number == 0) { /* create a new video object */ put_swf_tag(s, TAG_VIDEOSTREAM); @@ -362,7 +383,7 @@ avio_wl16(pb, par->width); avio_wl16(pb, par->height); avio_w8(pb, 0); - avio_w8(pb,ff_codec_get_tag(ff_swf_codec_tags, par->codec_id)); + avio_w8(pb, codec_tag); put_swf_end_tag(s); /* place the video object for the first time */ @@ -388,9 +409,14 @@ put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG); avio_wl16(pb, VIDEO_ID); avio_wl16(pb, swf->video_frame_number++); + if (par->codec_id == AV_CODEC_ID_FLASHSV) { + /* FrameType and CodecId is needed here even if it is not documented correctly in the SWF specs */ + int flags = codec_tag | (pkt_flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER); + avio_w8(pb, flags); + } avio_write(pb, buf, size); put_swf_end_tag(s); - } else if (par->codec_id == AV_CODEC_ID_MJPEG) { + } else if (par->codec_id == AV_CODEC_ID_MJPEG || par->codec_id == AV_CODEC_ID_PNG) { if (swf->swf_frame_number > 0) { /* remove the shape */ put_swf_tag(s, TAG_REMOVEOBJECT); @@ -409,8 +435,9 @@ avio_wl16(pb, BITMAP_ID); /* ID of the image */ /* a dummy jpeg header seems to be required */ - avio_wb32(pb, 0xffd8ffd9); - /* write the jpeg image */ + if (par->codec_id == AV_CODEC_ID_MJPEG) + avio_wb32(pb, 0xffd8ffd9); + /* write the jpeg/png image */ avio_write(pb, buf, size); put_swf_end_tag(s); @@ -449,7 +476,7 @@ static int swf_write_audio(AVFormatContext *s, AVCodecParameters *par, uint8_t *buf, int size) { - SWFContext *swf = s->priv_data; + SWFEncContext *swf = s->priv_data; /* Flash Player limit */ if (swf->swf_frame_number == 16000) @@ -465,7 +492,7 @@ /* if audio only stream make sure we add swf frames */ if (!swf->video_par) - swf_write_video(s, par, 0, 0); + swf_write_video(s, par, 0, 0, 0); return 0; } @@ -476,31 +503,20 @@ if (par->codec_type == AVMEDIA_TYPE_AUDIO) return swf_write_audio(s, par, pkt->data, pkt->size); else - return swf_write_video(s, par, pkt->data, pkt->size); + return swf_write_video(s, par, pkt->data, pkt->size, pkt->flags); } static int swf_write_trailer(AVFormatContext *s) { - SWFContext *swf = s->priv_data; + SWFEncContext *swf = s->priv_data; AVIOContext *pb = s->pb; - AVCodecParameters *par, *video_par; - int file_size, i; - - video_par = NULL; - for(i=0;inb_streams;i++) { - par = s->streams[i]->codecpar; - if (par->codec_type == AVMEDIA_TYPE_VIDEO) - video_par = par; - else { - av_fifo_freep(&swf->audio_fifo); - } - } + int file_size; put_swf_tag(s, TAG_END); put_swf_end_tag(s); /* patch file size and number of frames if not streamed */ - if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && video_par) { + if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && swf->video_par) { file_size = avio_tell(pb); avio_seek(pb, 4, SEEK_SET); avio_wl32(pb, file_size); @@ -515,18 +531,26 @@ return 0; } +static void swf_deinit(AVFormatContext *s) +{ + SWFEncContext *swf = s->priv_data; + + av_fifo_freep(&swf->audio_fifo); +} + #if CONFIG_SWF_MUXER AVOutputFormat ff_swf_muxer = { .name = "swf", .long_name = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"), .mime_type = "application/x-shockwave-flash", .extensions = "swf", - .priv_data_size = sizeof(SWFContext), + .priv_data_size = sizeof(SWFEncContext), .audio_codec = AV_CODEC_ID_MP3, .video_codec = AV_CODEC_ID_FLV1, .write_header = swf_write_header, .write_packet = swf_write_packet, .write_trailer = swf_write_trailer, + .deinit = swf_deinit, .flags = AVFMT_TS_NONSTRICT, }; #endif @@ -535,12 +559,13 @@ .name = "avm2", .long_name = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash) (AVM2)"), .mime_type = "application/x-shockwave-flash", - .priv_data_size = sizeof(SWFContext), + .priv_data_size = sizeof(SWFEncContext), .audio_codec = AV_CODEC_ID_MP3, .video_codec = AV_CODEC_ID_FLV1, .write_header = swf_write_header, .write_packet = swf_write_packet, .write_trailer = swf_write_trailer, + .deinit = swf_deinit, .flags = AVFMT_TS_NONSTRICT, }; #endif diff -Nru ffmpeg-4.2.2/libavformat/swf.h ffmpeg-4.4/libavformat/swf.h --- ffmpeg-4.2.2/libavformat/swf.h 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/swf.h 2021-04-08 21:28:40.000000000 +0000 @@ -23,15 +23,6 @@ #ifndef AVFORMAT_SWF_H #define AVFORMAT_SWF_H -#include "config.h" - -#if CONFIG_ZLIB -#include -#endif - -#include "libavutil/fifo.h" -#include "avformat.h" -#include "avio.h" #include "internal.h" /* should have a generic way to indicate probable size */ @@ -113,35 +104,11 @@ #define FLAG_SETFILL0 0x02 #define FLAG_SETFILL1 0x04 -#define AUDIO_FIFO_SIZE 65536 - /* character id used */ #define BITMAP_ID 0 #define VIDEO_ID 0 #define SHAPE_ID 1 -typedef struct SWFContext { - int64_t duration_pos; - int64_t tag_pos; - int64_t vframes_pos; - int samples_per_frame; - int sound_samples; - int swf_frame_number; - int video_frame_number; - int frame_rate; - int tag; - AVFifoBuffer *audio_fifo; - AVCodecParameters *audio_par, *video_par; - AVStream *video_st; -#if CONFIG_ZLIB -#define ZBUF_SIZE 4096 - AVIOContext *zpb; - uint8_t *zbuf_in; - uint8_t *zbuf_out; - z_stream zstream; -#endif -} SWFContext; - extern const AVCodecTag ff_swf_codec_tags[]; #endif /* AVFORMAT_SWF_H */ diff -Nru ffmpeg-4.2.2/libavformat/tedcaptionsdec.c ffmpeg-4.4/libavformat/tedcaptionsdec.c --- ffmpeg-4.2.2/libavformat/tedcaptionsdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tedcaptionsdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -94,25 +94,20 @@ { int ret; - av_bprint_init(bp, 0, full ? AV_BPRINT_SIZE_UNLIMITED : AV_BPRINT_SIZE_AUTOMATIC); ret = expect_byte(pb, cur_byte, '"'); if (ret < 0) - goto fail; + return ret; while (*cur_byte > 0 && *cur_byte != '"') { if (*cur_byte == '\\') { next_byte(pb, cur_byte); - if (*cur_byte < 0) { - ret = AVERROR_INVALIDDATA; - goto fail; - } + if (*cur_byte < 0) + return AVERROR_INVALIDDATA; if ((*cur_byte | 32) == 'u') { unsigned chr = 0, i; for (i = 0; i < 4; i++) { next_byte(pb, cur_byte); - if (!HEX_DIGIT_TEST(*cur_byte)) { - ret = ERR_CODE(*cur_byte); - goto fail; - } + if (!HEX_DIGIT_TEST(*cur_byte)) + return ERR_CODE(*cur_byte); chr = chr * 16 + HEX_DIGIT_VAL(*cur_byte); } av_bprint_utf8(bp, chr); @@ -126,22 +121,18 @@ } ret = expect_byte(pb, cur_byte, '"'); if (ret < 0) - goto fail; - if (full && !av_bprint_is_complete(bp)) { - ret = AVERROR(ENOMEM); - goto fail; - } - return 0; + return ret; + if (full && !av_bprint_is_complete(bp)) + return AVERROR(ENOMEM); -fail: - av_bprint_finalize(bp, NULL); - return ret; + return 0; } static int parse_label(AVIOContext *pb, int *cur_byte, AVBPrint *bp) { int ret; + av_bprint_init(bp, 0, AV_BPRINT_SIZE_AUTOMATIC); ret = parse_string(pb, cur_byte, bp, 0); if (ret < 0) return ret; @@ -181,6 +172,8 @@ if ((unsigned)*cur_byte - '0' > 9) return AVERROR_INVALIDDATA; while (BETWEEN(*cur_byte, '0', '9')) { + if (val > INT_MAX/10 - (*cur_byte - '0')) + return AVERROR_INVALIDDATA; val = val * 10 + (*cur_byte - '0'); next_byte(pb, cur_byte); } @@ -195,6 +188,8 @@ int64_t pos, start, duration; AVPacket *pkt; + av_bprint_init(&content, 0, AV_BPRINT_SIZE_UNLIMITED); + next_byte(pb, &cur_byte); ret = expect_byte(pb, &cur_byte, '{'); if (ret < 0) @@ -206,34 +201,34 @@ if (ret < 0) return AVERROR_INVALIDDATA; while (1) { - content.size = 0; start = duration = AV_NOPTS_VALUE; ret = expect_byte(pb, &cur_byte, '{'); if (ret < 0) - return ret; + goto fail; pos = avio_tell(pb) - 1; while (1) { ret = parse_label(pb, &cur_byte, &label); if (ret < 0) - return ret; + goto fail; if (!strcmp(label.str, "startOfParagraph")) { ret = parse_boolean(pb, &cur_byte, &start_of_par); if (ret < 0) - return ret; + goto fail; } else if (!strcmp(label.str, "content")) { ret = parse_string(pb, &cur_byte, &content, 1); if (ret < 0) - return ret; + goto fail; } else if (!strcmp(label.str, "startTime")) { ret = parse_int(pb, &cur_byte, &start); if (ret < 0) - return ret; + goto fail; } else if (!strcmp(label.str, "duration")) { ret = parse_int(pb, &cur_byte, &duration); if (ret < 0) - return ret; + goto fail; } else { - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } skip_spaces(pb, &cur_byte); if (cur_byte != ',') @@ -242,18 +237,22 @@ } ret = expect_byte(pb, &cur_byte, '}'); if (ret < 0) - return ret; + goto fail; if (!content.size || start == AV_NOPTS_VALUE || - duration == AV_NOPTS_VALUE) - return AVERROR_INVALIDDATA; + duration == AV_NOPTS_VALUE) { + ret = AVERROR_INVALIDDATA; + goto fail; + } pkt = ff_subtitles_queue_insert(subs, content.str, content.len, 0); - if (!pkt) - return AVERROR(ENOMEM); + if (!pkt) { + ret = AVERROR(ENOMEM); + goto fail; + } pkt->pos = pos; pkt->pts = start; pkt->duration = duration; - av_bprint_finalize(&content, NULL); + av_bprint_clear(&content); skip_spaces(pb, &cur_byte); if (cur_byte != ',') @@ -262,23 +261,28 @@ } ret = expect_byte(pb, &cur_byte, ']'); if (ret < 0) - return ret; + goto fail; ret = expect_byte(pb, &cur_byte, '}'); if (ret < 0) - return ret; + goto fail; skip_spaces(pb, &cur_byte); if (cur_byte != AVERROR_EOF) - return ERR_CODE(cur_byte); - return 0; + ret = ERR_CODE(cur_byte); +fail: + av_bprint_finalize(&content, NULL); + return ret; } static av_cold int tedcaptions_read_header(AVFormatContext *avf) { TEDCaptionsDemuxer *tc = avf->priv_data; - AVStream *st; + AVStream *st = avformat_new_stream(avf, NULL); int ret, i; AVPacket *last; + if (!st) + return AVERROR(ENOMEM); + ret = parse_file(avf->pb, &tc->subs); if (ret < 0) { if (ret == AVERROR_INVALIDDATA) @@ -289,12 +293,9 @@ } ff_subtitles_queue_finalize(avf, &tc->subs); for (i = 0; i < tc->subs.nb_subs; i++) - tc->subs.subs[i].pts += tc->start_time; + tc->subs.subs[i]->pts += tc->start_time; - last = &tc->subs.subs[tc->subs.nb_subs - 1]; - st = avformat_new_stream(avf, NULL); - if (!st) - return AVERROR(ENOMEM); + last = tc->subs.subs[tc->subs.nb_subs - 1]; st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codecpar->codec_id = AV_CODEC_ID_TEXT; avpriv_set_pts_info(st, 64, 1, 1000); diff -Nru ffmpeg-4.2.2/libavformat/tee.c ffmpeg-4.4/libavformat/tee.c --- ffmpeg-4.2.2/libavformat/tee.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tee.c 2021-04-08 21:28:40.000000000 +0000 @@ -56,7 +56,6 @@ TeeSlave *slaves; int use_fifo; AVDictionary *fifo_options; - char *fifo_options_str; } TeeContext; static const char *const slave_delim = "|"; @@ -67,8 +66,8 @@ static const AVOption options[] = { {"use_fifo", "Use fifo pseudo-muxer to separate actual muxers from encoder", OFFSET(use_fifo), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, - {"fifo_options", "fifo pseudo-muxer options", OFFSET(fifo_options_str), - AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM}, + {"fifo_options", "fifo pseudo-muxer options", OFFSET(fifo_options), + AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM}, {NULL} }; @@ -159,7 +158,7 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave) { int i, ret; - AVDictionary *options = NULL; + AVDictionary *options = NULL, *bsf_options = NULL; AVDictionaryEntry *entry; char *filename; char *format = NULL, *select = NULL, *on_fail = NULL; @@ -186,6 +185,12 @@ STEAL_OPTION("onfail", on_fail); STEAL_OPTION("use_fifo", use_fifo); STEAL_OPTION("fifo_options", fifo_options_str); + entry = NULL; + while ((entry = av_dict_get(options, "bsfs", entry, AV_DICT_IGNORE_SUFFIX))) { + /* trim out strlen("bsfs") characters from key */ + av_dict_set(&bsf_options, entry->key + 4, entry->value, 0); + av_dict_set(&options, entry->key, NULL, 0); + } ret = parse_slave_failure_policy_option(on_fail, tee_slave); if (ret < 0) { @@ -290,7 +295,7 @@ goto end; } - ret = ff_format_output_open(avf2, filename, NULL); + ret = ff_format_output_open(avf2, filename, &options); if (ret < 0) { av_log(avf, AV_LOG_ERROR, "Slave '%s': error opening: %s\n", slave, av_err2str(ret)); @@ -311,8 +316,8 @@ } entry = NULL; - while (entry = av_dict_get(options, "bsfs", NULL, AV_DICT_IGNORE_SUFFIX)) { - const char *spec = entry->key + strlen("bsfs"); + while (entry = av_dict_get(bsf_options, "", NULL, AV_DICT_IGNORE_SUFFIX)) { + const char *spec = entry->key; if (*spec) { if (strspn(spec, slave_bsfs_spec_sep) != 1) { av_log(avf, AV_LOG_ERROR, @@ -352,7 +357,7 @@ } } - av_dict_set(&options, entry->key, NULL, 0); + av_dict_set(&bsf_options, entry->key, NULL, 0); } for (i = 0; i < avf->nb_streams; i++){ @@ -399,6 +404,7 @@ av_free(select); av_free(on_fail); av_dict_free(&options); + av_dict_free(&bsf_options); av_freep(&tmp_select); return ret; } @@ -468,12 +474,6 @@ filename++; } - if (tee->fifo_options_str) { - ret = av_dict_parse_string(&tee->fifo_options, tee->fifo_options_str, "=", ":", 0); - if (ret < 0) - goto fail; - } - if (!(tee->slaves = av_mallocz_array(nb_slaves, sizeof(*tee->slaves)))) { ret = AVERROR(ENOMEM); goto fail; @@ -564,7 +564,6 @@ if (s2 < 0) continue; - memset(&pkt2, 0, sizeof(AVPacket)); if ((ret = av_packet_ref(&pkt2, pkt)) < 0) if (!ret_all) { ret_all = ret; @@ -615,5 +614,5 @@ .write_trailer = tee_write_trailer, .write_packet = tee_write_packet, .priv_class = &tee_muxer_class, - .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH, + .flags = AVFMT_NOFILE | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, }; diff -Nru ffmpeg-4.2.2/libavformat/tests/fifo_muxer.c ffmpeg-4.4/libavformat/tests/fifo_muxer.c --- ffmpeg-4.2.2/libavformat/tests/fifo_muxer.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tests/fifo_muxer.c 2021-04-08 21:28:40.000000000 +0000 @@ -41,21 +41,18 @@ static int prepare_packet(AVPacket *pkt, const FailingMuxerPacketData *pkt_data, int64_t pts) { - int ret; - FailingMuxerPacketData *data = av_malloc(sizeof(*data)); - if (!data) { - return AVERROR(ENOMEM); - } - memcpy(data, pkt_data, sizeof(FailingMuxerPacketData)); - ret = av_packet_from_data(pkt, (uint8_t*) data, sizeof(*data)); + int ret = av_new_packet(pkt, sizeof(*pkt_data)); + if (ret < 0) + return ret; + memcpy(pkt->data, pkt_data, sizeof(*pkt_data)); pkt->pts = pkt->dts = pts; pkt->duration = 1; - return ret; + return 0; } -static int initialize_fifo_tst_muxer_chain(AVFormatContext **oc) +static int initialize_fifo_tst_muxer_chain(AVFormatContext **oc, AVPacket **pkt) { int ret = 0; AVStream *s; @@ -71,20 +68,20 @@ if (!s) { fprintf(stderr, "Failed to create stream: %s\n", av_err2str(ret)); - ret = AVERROR(ENOMEM); + return AVERROR(ENOMEM); } - return ret; + *pkt = av_packet_alloc(); + if (!*pkt) + return AVERROR(ENOMEM); + + return 0; } static int fifo_basic_test(AVFormatContext *oc, AVDictionary **opts, - const FailingMuxerPacketData *pkt_data) + AVPacket *pkt, const FailingMuxerPacketData *pkt_data) { int ret = 0, i; - AVPacket pkt; - - av_init_packet(&pkt); - ret = avformat_write_header(oc, opts); if (ret) { @@ -94,14 +91,14 @@ } for (i = 0; i < 15; i++ ) { - ret = prepare_packet(&pkt, pkt_data, i); + ret = prepare_packet(pkt, pkt_data, i); if (ret < 0) { fprintf(stderr, "Failed to prepare test packet: %s\n", av_err2str(ret)); goto write_trailer_and_fail; } - ret = av_write_frame(oc, &pkt); - av_packet_unref(&pkt); + ret = av_write_frame(oc, pkt); + av_packet_unref(pkt); if (ret < 0) { fprintf(stderr, "Unexpected write_frame error: %s\n", av_err2str(ret)); @@ -131,13 +128,10 @@ } static int fifo_overflow_drop_test(AVFormatContext *oc, AVDictionary **opts, - const FailingMuxerPacketData *data) + AVPacket *pkt, const FailingMuxerPacketData *data) { int ret = 0, i; int64_t write_pkt_start, write_pkt_end, duration; - AVPacket pkt; - - av_init_packet(&pkt); ret = avformat_write_header(oc, opts); if (ret) { @@ -148,18 +142,19 @@ write_pkt_start = av_gettime_relative(); for (i = 0; i < 6; i++ ) { - ret = prepare_packet(&pkt, data, i); + ret = prepare_packet(pkt, data, i); if (ret < 0) { fprintf(stderr, "Failed to prepare test packet: %s\n", av_err2str(ret)); goto fail; } - ret = av_write_frame(oc, &pkt); - av_packet_unref(&pkt); + ret = av_write_frame(oc, pkt); + av_packet_unref(pkt); if (ret < 0) { break; } } + write_pkt_end = av_gettime_relative(); duration = write_pkt_end - write_pkt_start; if (duration > (SLEEPTIME_50_MS*6)/2) { @@ -185,7 +180,8 @@ } typedef struct TestCase { - int (*test_func)(AVFormatContext *, AVDictionary **,const FailingMuxerPacketData *pkt_data); + int (*test_func)(AVFormatContext *, AVDictionary **, + AVPacket *, const FailingMuxerPacketData *pkt_data); const char *test_name; const char *options; @@ -203,10 +199,11 @@ { AVDictionary *opts = NULL; AVFormatContext *oc = NULL; + AVPacket *pkt = NULL; char buffer[BUFFER_SIZE]; int ret, ret1; - ret = initialize_fifo_tst_muxer_chain(&oc); + ret = initialize_fifo_tst_muxer_chain(&oc, &pkt); if (ret < 0) { fprintf(stderr, "Muxer initialization failed: %s\n", av_err2str(ret)); goto end; @@ -232,11 +229,12 @@ goto end; } - ret = test->test_func(oc, &opts, &test->pkt_data); + ret = test->test_func(oc, &opts, pkt, &test->pkt_data); end: printf("%s: %s\n", test->test_name, ret < 0 ? "fail" : "ok"); avformat_free_context(oc); + av_packet_free(&pkt); av_dict_free(&opts); return ret; } diff -Nru ffmpeg-4.2.2/libavformat/tests/movenc.c ffmpeg-4.4/libavformat/tests/movenc.c --- ffmpeg-4.2.2/libavformat/tests/movenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tests/movenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -56,6 +56,7 @@ struct AVMD5* md5; uint8_t hash[HASH_SIZE]; +AVPacket *pkt; AVStream *video_st, *audio_st; int64_t audio_dts, video_dts; @@ -248,68 +249,67 @@ { int end_frames = frames + n; while (1) { - AVPacket pkt; uint8_t pktdata[8] = { 0 }; - av_init_packet(&pkt); + av_packet_unref(pkt); if (av_compare_ts(audio_dts, audio_st->time_base, video_dts, video_st->time_base) < 0) { - pkt.dts = pkt.pts = audio_dts; - pkt.stream_index = 1; - pkt.duration = audio_duration; + pkt->dts = pkt->pts = audio_dts; + pkt->stream_index = 1; + pkt->duration = audio_duration; audio_dts += audio_duration; } else { if (frames == end_frames) break; - pkt.dts = video_dts; - pkt.stream_index = 0; - pkt.duration = duration; + pkt->dts = video_dts; + pkt->stream_index = 0; + pkt->duration = duration; if ((frames % gop_size) == 0) { - pkt.flags |= AV_PKT_FLAG_KEY; + pkt->flags |= AV_PKT_FLAG_KEY; last_picture = AV_PICTURE_TYPE_I; - pkt.pts = pkt.dts + duration; - video_dts = pkt.pts; + pkt->pts = pkt->dts + duration; + video_dts = pkt->pts; } else { if (last_picture == AV_PICTURE_TYPE_P) { last_picture = AV_PICTURE_TYPE_B; - pkt.pts = pkt.dts; + pkt->pts = pkt->dts; video_dts = next_p_pts; } else { last_picture = AV_PICTURE_TYPE_P; if (((frames + 1) % gop_size) == 0) { - pkt.pts = pkt.dts + duration; - video_dts = pkt.pts; + pkt->pts = pkt->dts + duration; + video_dts = pkt->pts; } else { - next_p_pts = pkt.pts = pkt.dts + 2 * duration; + next_p_pts = pkt->pts = pkt->dts + 2 * duration; video_dts += duration; } } } if (!bframes) - pkt.pts = pkt.dts; + pkt->pts = pkt->dts; if (fake_pkt_duration) - pkt.duration = fake_pkt_duration; + pkt->duration = fake_pkt_duration; frames++; } if (clear_duration) - pkt.duration = 0; - AV_WB32(pktdata + 4, pkt.pts); - pkt.data = pktdata; - pkt.size = 8; + pkt->duration = 0; + AV_WB32(pktdata + 4, pkt->pts); + pkt->data = pktdata; + pkt->size = 8; if (skip_write) continue; - if (skip_write_audio && pkt.stream_index == 1) + if (skip_write_audio && pkt->stream_index == 1) continue; if (c) { - pkt.pts += (1LL<<32); - pkt.dts += (1LL<<32); + pkt->pts += (1LL<<32); + pkt->dts += (1LL<<32); } if (do_interleave) - av_interleaved_write_frame(ctx, &pkt); + av_interleaved_write_frame(ctx, pkt); else - av_write_frame(ctx, &pkt); + av_write_frame(ctx, pkt); } } @@ -327,19 +327,16 @@ static void signal_init_ts(void) { - AVPacket pkt; - av_init_packet(&pkt); - pkt.size = 0; - pkt.data = NULL; - - pkt.stream_index = 0; - pkt.dts = video_dts; - pkt.pts = 0; - av_write_frame(ctx, &pkt); - - pkt.stream_index = 1; - pkt.dts = pkt.pts = audio_dts; - av_write_frame(ctx, &pkt); + av_packet_unref(pkt); + + pkt->stream_index = 0; + pkt->dts = video_dts; + pkt->pts = 0; + av_write_frame(ctx, pkt); + + pkt->stream_index = 1; + pkt->dts = pkt->pts = audio_dts; + av_write_frame(ctx, pkt); } static void finish(void) @@ -382,6 +379,11 @@ md5 = av_md5_alloc(); if (!md5) return 1; + pkt = av_packet_alloc(); + if (!pkt) { + av_free(md5); + return 1; + } // Write a fragmented file with an initial moov that actually contains some // samples. One moov+mdat with 1 second of data and one moof+mdat with 1 @@ -786,6 +788,7 @@ close_out(); av_free(md5); + av_packet_free(&pkt); return check_faults > 0 ? 1 : 0; } diff -Nru ffmpeg-4.2.2/libavformat/tests/url.c ffmpeg-4.4/libavformat/tests/url.c --- ffmpeg-4.2.2/libavformat/tests/url.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/tests/url.c 2021-04-08 21:28:27.000000000 +0000 @@ -18,17 +18,61 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" #include "libavformat/url.h" +#include "libavformat/avformat.h" + +static void test_decompose(const char *url) +{ + URLComponents uc; + int len, ret; + + printf("%s =>\n", url); + ret = ff_url_decompose(&uc, url, NULL); + if (ret < 0) { + printf(" error: %s\n", av_err2str(ret)); + return; + } +#define PRINT_COMPONENT(comp) \ + len = uc.url_component_end_##comp - uc.comp; \ + if (len) printf(" "#comp": %.*s\n", len, uc.comp); + PRINT_COMPONENT(scheme); + PRINT_COMPONENT(authority); + PRINT_COMPONENT(userinfo); + PRINT_COMPONENT(host); + PRINT_COMPONENT(port); + PRINT_COMPONENT(path); + PRINT_COMPONENT(query); + PRINT_COMPONENT(fragment); + printf("\n"); +} static void test(const char *base, const char *rel) { - char buf[200], buf2[200]; - ff_make_absolute_url(buf, sizeof(buf), base, rel); - printf("%s\n", buf); + char buf[200], buf2[200], buf_dos[200], buf_native[200]; + int ret; + + ret = ff_make_absolute_url2(buf, sizeof(buf), base, rel, 0); + if (ret < 0) { + printf("%50s %-20s => error %s\n", base, rel, av_err2str(ret)); + return; + } + printf("%50s %-20s => %s\n", base, rel, buf); + ret = ff_make_absolute_url2(buf_dos, sizeof(buf_dos), base, rel, 1); + if (ret < 0) + snprintf(buf_dos, sizeof(buf_dos), "error %s", av_err2str(ret)); + ret = ff_make_absolute_url(buf_native, sizeof(buf_native), base, rel); + if (ret < 0) + snprintf(buf_native, sizeof(buf_native), "error %s", av_err2str(ret)); + if (strcmp(buf, buf_dos)) + printf("%50s %-20sDOS %s\n", base, rel, buf_dos); + if (HAVE_DOS_PATHS && strcmp(buf_dos, buf_native) || + !HAVE_DOS_PATHS && strcmp(buf, buf_native)) + printf("Native mismatch\n"); if (base) { /* Test in-buffer replacement */ snprintf(buf2, sizeof(buf2), "%s", base); - ff_make_absolute_url(buf2, sizeof(buf2), buf2, rel); + ff_make_absolute_url2(buf2, sizeof(buf2), buf2, rel, 0); if (strcmp(buf, buf2)) { printf("In-place handling of %s + %s failed\n", base, rel); exit(1); @@ -36,12 +80,37 @@ } } +static void test2(const char *url) +{ + char proto[64]; + char auth[256]; + char host[256]; + char path[256]; + int port=-1; + + av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host), &port, path, sizeof(path), url); + printf("%-60s => %-15s %-15s %-15s %5d %s\n", url, proto, auth, host, port, path); +} + int main(void) { + printf("Testing ff_url_decompose:\n\n"); + test_decompose("http://user:pass@ffmpeg:8080/dir/file?query#fragment"); + test_decompose("http://ffmpeg/dir/file"); + test_decompose("file:///dev/null"); + test_decompose("file:/dev/null"); + test_decompose("http://[::1]/dev/null"); + test_decompose("http://[::1]:8080/dev/null"); + test_decompose("//ffmpeg/dev/null"); + test_decompose("test?url=http://server/path"); + test_decompose("dummy.mp4#t=0:02:00,121.5"); + + printf("Testing ff_make_absolute_url:\n"); test(NULL, "baz"); test("/foo/bar", "baz"); test("/foo/bar", "../baz"); test("/foo/bar", "/baz"); + test("/foo/bar", "../../../baz"); test("http://server/foo/", "baz"); test("http://server/foo/bar", "baz"); test("http://server/foo/", "../baz"); @@ -51,5 +120,88 @@ test("http://server/foo/bar?param=value/with/slashes", "/baz"); test("http://server/foo/bar?param&otherparam", "?someparam"); test("http://server/foo/bar", "//other/url"); + test("http://server/foo/bar", "../../../../../other/url"); + test("http://server/foo/bar", "/../../../../../other/url"); + test("http://server/foo/bar", "/test/../../../../../other/url"); + test("http://server/foo/bar", "/test/../../test/../../../other/url"); + test("http://server/foo/bar", "file:../baz/qux"); + test("http://server/foo//bar/", "../../"); + test("file:../tmp/foo", "../bar/"); + test("file:../tmp/foo", "file:../bar/"); + test("http://server/foo/bar", "./"); + test("http://server/foo/bar", ".dotfile"); + test("http://server/foo/bar", "..doubledotfile"); + test("http://server/foo/bar", "double..dotfile"); + test("http://server/foo/bar", "doubledotfile.."); + test("file1", "file2"); + test("dir/file1", "file2"); + test("dir/file1", "../file2"); + test("dir\\file1", "file2"); + test("\\\\srv\\shr\\file", "..\\..\\dummy"); + test("\\\\srv\\shr\\file", "dummy"); + test("\\\\srv\\shr\\file", "\\\\srv2\\shr2\\file2"); + test("\\\\srv\\shr\\file", "d:/file"); + test("C:\\dir\\a", "..\\file"); + test("C:\\dir\\a", "\\\\srv\\shr\\file"); + test("C:\\dir\\a", "d:\\file"); + test("http://a/b", "\\\\srv\\shr\\file"); + test("http://a/b", "//srv/shr/file"); + test("http://a/b", "d:\\file"); + test("http://a/b", "C:/file"); + + /* From https://tools.ietf.org/html/rfc3986#section-5.4 */ + test("http://a/b/c/d;p?q", "g:h"); // g:h + test("http://a/b/c/d;p?q", "g"); // http://a/b/c/g + test("http://a/b/c/d;p?q", "./g"); // http://a/b/c/g + test("http://a/b/c/d;p?q", "g/"); // http://a/b/c/g/ + test("http://a/b/c/d;p?q", "/g"); // http://a/g + test("http://a/b/c/d;p?q", "//g"); // http://g + test("http://a/b/c/d;p?q", "?y"); // http://a/b/c/d;p?y + test("http://a/b/c/d;p?q", "g?y"); // http://a/b/c/g?y + test("http://a/b/c/d;p?q", "#s"); // http://a/b/c/d;p?q#s + test("http://a/b/c/d;p?q", "g#s"); // http://a/b/c/g#s + test("http://a/b/c/d;p?q", "g?y#s"); // http://a/b/c/g?y#s + test("http://a/b/c/d;p?q", ";x"); // http://a/b/c/;x + test("http://a/b/c/d;p?q", "g;x"); // http://a/b/c/g;x + test("http://a/b/c/d;p?q", "g;x?y#s"); // http://a/b/c/g;x?y#s + test("http://a/b/c/d;p?q", ""); // http://a/b/c/d;p?q + test("http://a/b/c/d;p?q", "."); // http://a/b/c/ + test("http://a/b/c/d;p?q", "./"); // http://a/b/c/ + test("http://a/b/c/d;p?q", ".."); // http://a/b/ + test("http://a/b/c/d;p?q", "../"); // http://a/b/ + test("http://a/b/c/d;p?q", "../g"); // http://a/b/g + test("http://a/b/c/d;p?q", "../.."); // http://a/ + test("http://a/b/c/d;p?q", "../../"); // http://a/ + test("http://a/b/c/d;p?q", "../../g"); // http://a/g + test("http://a/b/c/d;p?q", "../../../g"); // http://a/g + test("http://a/b/c/d;p?q", "../../../../g"); // http://a/g + test("http://a/b/c/d;p?q", "/./g"); // http://a/g + test("http://a/b/c/d;p?q", "/../g"); // http://a/g + test("http://a/b/c/d;p?q", "g."); // http://a/b/c/g. + test("http://a/b/c/d;p?q", ".g"); // http://a/b/c/.g + test("http://a/b/c/d;p?q", "g.."); // http://a/b/c/g.. + test("http://a/b/c/d;p?q", "..g"); // http://a/b/c/..g + test("http://a/b/c/d;p?q", "./../g"); // http://a/b/g + test("http://a/b/c/d;p?q", "./g/."); // http://a/b/c/g/ + test("http://a/b/c/d;p?q", "g/./h"); // http://a/b/c/g/h + test("http://a/b/c/d;p?q", "g/../h"); // http://a/b/c/h + test("http://a/b/c/d;p?q", "g;x=1/./y"); // http://a/b/c/g;x=1/y + test("http://a/b/c/d;p?q", "g;x=1/../y"); // http://a/b/c/y + test("http://a/b/c/d;p?q", "g?y/./x"); // http://a/b/c/g?y/./x + test("http://a/b/c/d;p?q", "g?y/../x"); // http://a/b/c/g?y/../x + test("http://a/b/c/d;p?q", "g#s/./x"); // http://a/b/c/g#s/./x + test("http://a/b/c/d;p?q", "g#s/../x"); // http://a/b/c/g#s/../x + + printf("\nTesting av_url_split:\n"); + test2("/foo/bar"); + test2("http://server/foo/"); + test2("http://example.com/foo/bar"); + test2("http://user:pass@localhost:8080/foo/bar/123"); + test2("http://server/foo/bar?param=value/with/slashes"); + test2("https://1l-lh.a.net/i/1LIVE_HDS@179577/master.m3u8"); + test2("ftp://u:p%2B%2F2@ftp.pbt.com/ExportHD.mpg"); + test2("https://key.dns.com?key_id=2&model_id=12345&&access_key="); + test2("http://example.com#tag"); + return 0; } diff -Nru ffmpeg-4.2.2/libavformat/thp.c ffmpeg-4.4/libavformat/thp.c --- ffmpeg-4.2.2/libavformat/thp.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/thp.c 2020-07-11 10:39:30.000000000 +0000 @@ -75,6 +75,8 @@ avio_rb32(pb); /* Max samples. */ thp->fps = av_d2q(av_int2float(avio_rb32(pb)), INT_MAX); + if (thp->fps.den <= 0 || thp->fps.num < 0) + return AVERROR_INVALIDDATA; thp->framecnt = avio_rb32(pb); thp->first_framesz = avio_rb32(pb); pb->maxsize = avio_rb32(pb); @@ -93,6 +95,9 @@ avio_seek (pb, thp->compoff, SEEK_SET); thp->compcount = avio_rb32(pb); + if (thp->compcount > FF_ARRAY_ELEMS(thp->components)) + return AVERROR_INVALIDDATA; + /* Read the list of component types. */ avio_read(pb, thp->components, 16); @@ -145,6 +150,9 @@ } } + if (!thp->vst) + return AVERROR_INVALIDDATA; + return 0; } @@ -181,7 +189,6 @@ if (ret < 0) return ret; if (ret != size) { - av_packet_unref(pkt); return AVERROR(EIO); } @@ -191,7 +198,6 @@ if (ret < 0) return ret; if (ret != thp->audiosize) { - av_packet_unref(pkt); return AVERROR(EIO); } diff -Nru ffmpeg-4.2.2/libavformat/tiertexseq.c ffmpeg-4.4/libavformat/tiertexseq.c --- ffmpeg-4.2.2/libavformat/tiertexseq.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tiertexseq.c 2020-07-11 10:39:30.000000000 +0000 @@ -273,8 +273,10 @@ /* video packet */ if (seq->current_pal_data_size + seq->current_video_data_size != 0) { - if (av_new_packet(pkt, 1 + seq->current_pal_data_size + seq->current_video_data_size)) - return AVERROR(ENOMEM); + rc = av_new_packet(pkt, 1 + seq->current_pal_data_size + + seq->current_video_data_size); + if (rc < 0) + return rc; pkt->data[0] = 0; if (seq->current_pal_data_size) { diff -Nru ffmpeg-4.2.2/libavformat/tls.c ffmpeg-4.4/libavformat/tls.c --- ffmpeg-4.2.2/libavformat/tls.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/tls.c 2021-04-08 21:28:40.000000000 +0000 @@ -89,7 +89,7 @@ if (!c->host && !(c->host = av_strdup(c->underlying_host))) return AVERROR(ENOMEM); - proxy_path = getenv("http_proxy"); + proxy_path = c->http_proxy ? c->http_proxy : getenv("http_proxy"); use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), c->underlying_host) && proxy_path && av_strstart(proxy_path, "http://", NULL); diff -Nru ffmpeg-4.2.2/libavformat/tls_gnutls.c ffmpeg-4.4/libavformat/tls_gnutls.c --- ffmpeg-4.2.2/libavformat/tls_gnutls.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tls_gnutls.c 2021-04-08 21:28:40.000000000 +0000 @@ -100,8 +100,7 @@ gnutls_deinit(c->session); if (c->cred) gnutls_certificate_free_credentials(c->cred); - if (c->tls_shared.tcp) - ffurl_close(c->tls_shared.tcp); + ffurl_closep(&c->tls_shared.tcp); ff_gnutls_deinit(); return 0; } @@ -183,6 +182,11 @@ gnutls_transport_set_ptr(p->session, c->tcp); gnutls_priority_set_direct(p->session, "NORMAL", NULL); do { + if (ff_check_interrupt(&h->interrupt_callback)) { + ret = AVERROR_EXIT; + goto fail; + } + ret = gnutls_handshake(p->session); if (gnutls_error_is_fatal(ret)) { ret = print_tls_error(h, ret); @@ -265,6 +269,12 @@ return ffurl_get_file_handle(c->tls_shared.tcp); } +static int tls_get_short_seek(URLContext *h) +{ + TLSContext *s = h->priv_data; + return ffurl_get_short_seek(s->tls_shared.tcp); +} + static const AVOption options[] = { TLS_COMMON_OPTIONS(TLSContext, tls_shared), { NULL } @@ -284,6 +294,7 @@ .url_write = tls_write, .url_close = tls_close, .url_get_file_handle = tls_get_file_handle, + .url_get_short_seek = tls_get_short_seek, .priv_data_size = sizeof(TLSContext), .flags = URL_PROTOCOL_FLAG_NETWORK, .priv_data_class = &tls_class, diff -Nru ffmpeg-4.2.2/libavformat/tls.h ffmpeg-4.4/libavformat/tls.h --- ffmpeg-4.2.2/libavformat/tls.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tls.h 2021-04-08 21:28:40.000000000 +0000 @@ -34,6 +34,7 @@ int listen; char *host; + char *http_proxy; char underlying_host[200]; int numerichost; @@ -49,7 +50,8 @@ {"cert_file", "Certificate file", offsetof(pstruct, options_field . cert_file), AV_OPT_TYPE_STRING, .flags = TLS_OPTFL }, \ {"key_file", "Private key file", offsetof(pstruct, options_field . key_file), AV_OPT_TYPE_STRING, .flags = TLS_OPTFL }, \ {"listen", "Listen for incoming connections", offsetof(pstruct, options_field . listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, .flags = TLS_OPTFL }, \ - {"verifyhost", "Verify against a specific hostname", offsetof(pstruct, options_field . host), AV_OPT_TYPE_STRING, .flags = TLS_OPTFL } + {"verifyhost", "Verify against a specific hostname", offsetof(pstruct, options_field . host), AV_OPT_TYPE_STRING, .flags = TLS_OPTFL }, \ + {"http_proxy", "Set proxy to tunnel through", offsetof(pstruct, options_field . http_proxy), AV_OPT_TYPE_STRING, .flags = TLS_OPTFL } int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options); diff -Nru ffmpeg-4.2.2/libavformat/tls_libtls.c ffmpeg-4.4/libavformat/tls_libtls.c --- ffmpeg-4.2.2/libavformat/tls_libtls.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tls_libtls.c 2021-04-08 21:28:40.000000000 +0000 @@ -44,8 +44,7 @@ tls_close(p->ctx); tls_free(p->ctx); } - if (p->tls_shared.tcp) - ffurl_close(p->tls_shared.tcp); + ffurl_closep(&p->tls_shared.tcp); return 0; } @@ -182,6 +181,12 @@ return ffurl_get_file_handle(c->tls_shared.tcp); } +static int tls_get_short_seek(URLContext *h) +{ + TLSContext *s = h->priv_data; + return ffurl_get_short_seek(s->tls_shared.tcp); +} + static const AVOption options[] = { TLS_COMMON_OPTIONS(TLSContext, tls_shared), { NULL } @@ -201,6 +206,7 @@ .url_write = ff_tls_write, .url_close = ff_tls_close, .url_get_file_handle = tls_get_file_handle, + .url_get_short_seek = tls_get_short_seek, .priv_data_size = sizeof(TLSContext), .flags = URL_PROTOCOL_FLAG_NETWORK, .priv_data_class = &tls_class, diff -Nru ffmpeg-4.2.2/libavformat/tls_mbedtls.c ffmpeg-4.4/libavformat/tls_mbedtls.c --- ffmpeg-4.2.2/libavformat/tls_mbedtls.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tls_mbedtls.c 2021-04-08 21:28:40.000000000 +0000 @@ -62,6 +62,7 @@ mbedtls_ctr_drbg_free(&tls_ctx->ctr_drbg_context); mbedtls_entropy_free(&tls_ctx->entropy_context); + ffurl_closep(&tls_ctx->tls_shared.tcp); return 0; } @@ -325,6 +326,12 @@ return ffurl_get_file_handle(c->tls_shared.tcp); } +static int tls_get_short_seek(URLContext *h) +{ + TLSContext *s = h->priv_data; + return ffurl_get_short_seek(s->tls_shared.tcp); +} + static const AVOption options[] = { TLS_COMMON_OPTIONS(TLSContext, tls_shared), \ {"key_password", "Password for the private key file", OFFSET(priv_key_pw), AV_OPT_TYPE_STRING, .flags = TLS_OPTFL }, \ @@ -345,6 +352,7 @@ .url_write = tls_write, .url_close = tls_close, .url_get_file_handle = tls_get_file_handle, + .url_get_short_seek = tls_get_short_seek, .priv_data_size = sizeof(TLSContext), .flags = URL_PROTOCOL_FLAG_NETWORK, .priv_data_class = &tls_class, diff -Nru ffmpeg-4.2.2/libavformat/tls_openssl.c ffmpeg-4.4/libavformat/tls_openssl.c --- ffmpeg-4.2.2/libavformat/tls_openssl.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tls_openssl.c 2021-04-08 21:28:40.000000000 +0000 @@ -48,7 +48,7 @@ #endif } TLSContext; -#if HAVE_THREADS +#if HAVE_THREADS && OPENSSL_VERSION_NUMBER < 0x10100000L #include pthread_mutex_t *openssl_mutexes; static void openssl_lock(int mode, int type, const char *file, int line) @@ -70,9 +70,16 @@ { ff_lock_avformat(); if (!openssl_init) { + /* OpenSSL 1.0.2 or below, then you would use SSL_library_init. If you are + * using OpenSSL 1.1.0 or above, then the library will initialize + * itself automatically. + * https://wiki.openssl.org/index.php/Library_Initialization + */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L SSL_library_init(); SSL_load_error_strings(); -#if HAVE_THREADS +#endif +#if HAVE_THREADS && OPENSSL_VERSION_NUMBER < 0x10100000L if (!CRYPTO_get_locking_callback()) { int i; openssl_mutexes = av_malloc_array(sizeof(pthread_mutex_t), CRYPTO_num_locks()); @@ -101,7 +108,7 @@ ff_lock_avformat(); openssl_init--; if (!openssl_init) { -#if HAVE_THREADS +#if HAVE_THREADS && OPENSSL_VERSION_NUMBER < 0x10100000L if (CRYPTO_get_locking_callback() == openssl_lock) { int i; CRYPTO_set_locking_callback(NULL); @@ -135,8 +142,7 @@ } if (c->ctx) SSL_CTX_free(c->ctx); - if (c->tls_shared.tcp) - ffurl_close(c->tls_shared.tcp); + ffurl_closep(&c->tls_shared.tcp); #if OPENSSL_VERSION_NUMBER >= 0x1010000fL if (c->url_bio_method) BIO_meth_free(c->url_bio_method); @@ -345,6 +351,12 @@ return ffurl_get_file_handle(c->tls_shared.tcp); } +static int tls_get_short_seek(URLContext *h) +{ + TLSContext *s = h->priv_data; + return ffurl_get_short_seek(s->tls_shared.tcp); +} + static const AVOption options[] = { TLS_COMMON_OPTIONS(TLSContext, tls_shared), { NULL } @@ -364,6 +376,7 @@ .url_write = tls_write, .url_close = tls_close, .url_get_file_handle = tls_get_file_handle, + .url_get_short_seek = tls_get_short_seek, .priv_data_size = sizeof(TLSContext), .flags = URL_PROTOCOL_FLAG_NETWORK, .priv_data_class = &tls_class, diff -Nru ffmpeg-4.2.2/libavformat/tls_schannel.c ffmpeg-4.4/libavformat/tls_schannel.c --- ffmpeg-4.2.2/libavformat/tls_schannel.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tls_schannel.c 2021-04-08 21:28:40.000000000 +0000 @@ -138,8 +138,7 @@ av_freep(&c->dec_buf); c->dec_buf_size = c->dec_buf_offset = 0; - if (c->tls_shared.tcp) - ffurl_close(c->tls_shared.tcp); + ffurl_closep(&c->tls_shared.tcp); return 0; } @@ -392,7 +391,12 @@ int size, ret; int min_enc_buf_size = len + SCHANNEL_FREE_BUFFER_SIZE; - if (len <= c->dec_buf_offset) + /* If we have some left-over data from previous network activity, + * return it first in case it is enough. It may contain + * data that is required to know whether this connection + * is still required or not, esp. in case of HTTP keep-alive + * connections. */ + if (c->dec_buf_offset > 0) goto cleanup; if (c->sspi_close_notify) @@ -424,7 +428,7 @@ c->enc_buf_offset += ret; } - while (c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK && c->dec_buf_offset < len) { + while (c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK) { /* input buffer */ init_sec_buffer(&inbuf[0], SECBUFFER_DATA, c->enc_buf, c->enc_buf_offset); @@ -585,6 +589,12 @@ return ffurl_get_file_handle(c->tls_shared.tcp); } +static int tls_get_short_seek(URLContext *h) +{ + TLSContext *s = h->priv_data; + return ffurl_get_short_seek(s->tls_shared.tcp); +} + static const AVOption options[] = { TLS_COMMON_OPTIONS(TLSContext, tls_shared), { NULL } @@ -604,6 +614,7 @@ .url_write = tls_write, .url_close = tls_close, .url_get_file_handle = tls_get_file_handle, + .url_get_short_seek = tls_get_short_seek, .priv_data_size = sizeof(TLSContext), .flags = URL_PROTOCOL_FLAG_NETWORK, .priv_data_class = &tls_class, diff -Nru ffmpeg-4.2.2/libavformat/tls_securetransport.c ffmpeg-4.4/libavformat/tls_securetransport.c --- ffmpeg-4.2.2/libavformat/tls_securetransport.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tls_securetransport.c 2021-04-08 21:28:40.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Rodger Combs + * Copyright (c) 2015 rcombs * * This file is part of FFmpeg. * @@ -251,8 +251,7 @@ } if (c->ca_array) CFRelease(c->ca_array); - if (c->tls_shared.tcp) - ffurl_close(c->tls_shared.tcp); + ffurl_closep(&c->tls_shared.tcp); return 0; } @@ -397,6 +396,12 @@ return ffurl_get_file_handle(c->tls_shared.tcp); } +static int tls_get_short_seek(URLContext *h) +{ + TLSContext *s = h->priv_data; + return ffurl_get_short_seek(s->tls_shared.tcp); +} + static const AVOption options[] = { TLS_COMMON_OPTIONS(TLSContext, tls_shared), { NULL } @@ -416,6 +421,7 @@ .url_write = tls_write, .url_close = tls_close, .url_get_file_handle = tls_get_file_handle, + .url_get_short_seek = tls_get_short_seek, .priv_data_size = sizeof(TLSContext), .flags = URL_PROTOCOL_FLAG_NETWORK, .priv_data_class = &tls_class, diff -Nru ffmpeg-4.2.2/libavformat/tta.c ffmpeg-4.4/libavformat/tta.c --- ffmpeg-4.2.2/libavformat/tta.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/tta.c 2021-02-20 20:27:47.000000000 +0000 @@ -119,7 +119,7 @@ for (i = 0; i < c->totalframes; i++) { uint32_t size = avio_rl32(s->pb); int r; - if ((r = av_add_index_entry(st, framepos, i * c->frame_size, size, 0, + if ((r = av_add_index_entry(st, framepos, i * (int64_t)c->frame_size, size, 0, AVINDEX_KEYFRAME)) < 0) return r; framepos += size; diff -Nru ffmpeg-4.2.2/libavformat/ttaenc.c ffmpeg-4.4/libavformat/ttaenc.c --- ffmpeg-4.2.2/libavformat/ttaenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ttaenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -22,6 +22,7 @@ #include "libavutil/crc.h" #include "libavutil/intreadwrite.h" +#include "libavcodec/packet_internal.h" #include "apetag.h" #include "avformat.h" #include "avio_internal.h" @@ -29,7 +30,7 @@ typedef struct TTAMuxContext { AVIOContext *seek_table; - AVPacketList *queue, *queue_end; + PacketList *queue, *queue_end; uint32_t nb_samples; int frame_size; int last_frame; @@ -93,8 +94,8 @@ TTAMuxContext *tta = s->priv_data; int ret; - ret = ff_packet_list_put(&tta->queue, &tta->queue_end, pkt, - FF_PACKETLIST_FLAG_REF_PACKET); + ret = avpriv_packet_list_put(&tta->queue, &tta->queue_end, pkt, + av_packet_ref, 0); if (ret < 0) { return ret; } @@ -125,7 +126,7 @@ AVPacket pkt; while (tta->queue) { - ff_packet_list_get(&tta->queue, &tta->queue_end, &pkt); + avpriv_packet_list_get(&tta->queue, &tta->queue_end, &pkt); avio_write(s->pb, pkt.data, pkt.size); av_packet_unref(&pkt); } @@ -145,19 +146,25 @@ /* Write Seek table */ crc = ffio_get_checksum(tta->seek_table) ^ UINT32_MAX; avio_wl32(tta->seek_table, crc); - size = avio_close_dyn_buf(tta->seek_table, &ptr); + size = avio_get_dyn_buf(tta->seek_table, &ptr); avio_write(s->pb, ptr, size); - av_free(ptr); /* Write audio data */ tta_queue_flush(s); ff_ape_write_tag(s); - avio_flush(s->pb); return 0; } +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); +} + AVOutputFormat ff_tta_muxer = { .name = "tta", .long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"), @@ -167,6 +174,7 @@ .audio_codec = AV_CODEC_ID_TTA, .video_codec = AV_CODEC_ID_NONE, .init = tta_init, + .deinit = tta_deinit, .write_header = tta_write_header, .write_packet = tta_write_packet, .write_trailer = tta_write_trailer, diff -Nru ffmpeg-4.2.2/libavformat/ttmlenc.c ffmpeg-4.4/libavformat/ttmlenc.c --- ffmpeg-4.2.2/libavformat/ttmlenc.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavformat/ttmlenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,174 @@ +/* + * TTML subtitle muxer + * Copyright (c) 2020 24i + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * TTML subtitle muxer + * @see https://www.w3.org/TR/ttml1/ + * @see https://www.w3.org/TR/ttml2/ + * @see https://www.w3.org/TR/ttml-imsc/rec + */ + +#include "avformat.h" +#include "internal.h" +#include "libavcodec/ttmlenc.h" +#include "libavutil/internal.h" + +enum TTMLPacketType { + PACKET_TYPE_PARAGRAPH, + PACKET_TYPE_DOCUMENT, +}; + +typedef struct TTMLMuxContext { + enum TTMLPacketType input_type; + unsigned int document_written; +} TTMLMuxContext; + +static const char ttml_header_text[] = +"\n" +"\n" +" \n" +"
\n"; + +static const char ttml_footer_text[] = +"
\n" +" \n" +"\n"; + +static void ttml_write_time(AVIOContext *pb, const char tag[], + int64_t millisec) +{ + int64_t sec, min, hour; + sec = millisec / 1000; + millisec -= 1000 * sec; + min = sec / 60; + sec -= 60 * min; + hour = min / 60; + min -= 60 * hour; + + avio_printf(pb, "%s=\"%02"PRId64":%02"PRId64":%02"PRId64".%03"PRId64"\"", + tag, hour, min, sec, millisec); +} + +static int ttml_write_header(AVFormatContext *ctx) +{ + TTMLMuxContext *ttml_ctx = ctx->priv_data; + ttml_ctx->document_written = 0; + + if (ctx->nb_streams != 1 || + ctx->streams[0]->codecpar->codec_id != AV_CODEC_ID_TTML) { + av_log(ctx, AV_LOG_ERROR, "Exactly one TTML stream is required!\n"); + return AVERROR(EINVAL); + } + + { + AVStream *st = ctx->streams[0]; + AVIOContext *pb = ctx->pb; + + AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, + 0); + const char *printed_lang = (lang && lang->value) ? lang->value : ""; + + // Not perfect, but decide whether the packet is a document or not + // by the existence of the lavc ttmlenc extradata. + ttml_ctx->input_type = (st->codecpar->extradata && + st->codecpar->extradata_size >= TTMLENC_EXTRADATA_SIGNATURE_SIZE && + !memcmp(st->codecpar->extradata, + TTMLENC_EXTRADATA_SIGNATURE, + TTMLENC_EXTRADATA_SIGNATURE_SIZE)) ? + PACKET_TYPE_PARAGRAPH : + PACKET_TYPE_DOCUMENT; + + avpriv_set_pts_info(st, 64, 1, 1000); + + if (ttml_ctx->input_type == PACKET_TYPE_PARAGRAPH) + avio_printf(pb, ttml_header_text, printed_lang); + } + + return 0; +} + +static int ttml_write_packet(AVFormatContext *ctx, AVPacket *pkt) +{ + TTMLMuxContext *ttml_ctx = ctx->priv_data; + AVIOContext *pb = ctx->pb; + + switch (ttml_ctx->input_type) { + case PACKET_TYPE_PARAGRAPH: + // write out a paragraph element with the given contents. + avio_printf(pb, " pts); + avio_w8(pb, '\n'); + ttml_write_time(pb, " end", pkt->pts + pkt->duration); + avio_printf(pb, ">"); + avio_write(pb, pkt->data, pkt->size); + avio_printf(pb, "

\n"); + break; + case PACKET_TYPE_DOCUMENT: + // dump the given document out as-is. + if (ttml_ctx->document_written) { + av_log(ctx, AV_LOG_ERROR, + "Attempting to write multiple TTML documents into a " + "single document! The XML specification forbids this " + "as there has to be a single root tag.\n"); + return AVERROR(EINVAL); + } + avio_write(pb, pkt->data, pkt->size); + ttml_ctx->document_written = 1; + break; + default: + av_log(ctx, AV_LOG_ERROR, + "Internal error: invalid TTML input packet type: %d!\n", + ttml_ctx->input_type); + return AVERROR_BUG; + } + + return 0; +} + +static int ttml_write_trailer(AVFormatContext *ctx) +{ + TTMLMuxContext *ttml_ctx = ctx->priv_data; + AVIOContext *pb = ctx->pb; + + if (ttml_ctx->input_type == PACKET_TYPE_PARAGRAPH) + avio_printf(pb, ttml_footer_text); + + return 0; +} + +AVOutputFormat ff_ttml_muxer = { + .name = "ttml", + .long_name = NULL_IF_CONFIG_SMALL("TTML subtitle"), + .extensions = "ttml", + .mime_type = "text/ttml", + .priv_data_size = sizeof(TTMLMuxContext), + .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | + AVFMT_TS_NONSTRICT, + .subtitle_codec = AV_CODEC_ID_TTML, + .write_header = ttml_write_header, + .write_packet = ttml_write_packet, + .write_trailer = ttml_write_trailer, +}; diff -Nru ffmpeg-4.2.2/libavformat/tty.c ffmpeg-4.4/libavformat/tty.c --- ffmpeg-4.2.2/libavformat/tty.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/tty.c 2020-07-11 10:39:30.000000000 +0000 @@ -34,6 +34,13 @@ #include "internal.h" #include "sauce.h" +static int isansicode(int x) +{ + return x == 0x1B || x == 0x0A || x == 0x0D || (x >= 0x20 && x < 0x7f); +} + +static const char tty_extensions[31] = "ans,art,asc,diz,ice,nfo,txt,vt"; + typedef struct TtyDemuxContext { AVClass *class; int chars_per_frame; @@ -42,6 +49,26 @@ AVRational framerate; /**< Set by a private option. */ } TtyDemuxContext; +static int read_probe(const AVProbeData *p) +{ + int cnt = 0; + + if (!p->buf_size) + return 0; + + for (int i = 0; i < 8 && i < p->buf_size; i++) + cnt += !!isansicode(p->buf[i]); + + if (cnt != 8) + return 0; + + for (int i = 8; i < p->buf_size; i++) + cnt += !!isansicode(p->buf[i]); + + return (cnt * 99LL / p->buf_size) * (cnt > 400) * + !!av_match_ext(p->filename, tty_extensions); +} + /** * Parse EFI header */ @@ -129,6 +156,8 @@ pkt->size = av_get_packet(avctx->pb, pkt, n); if (pkt->size < 0) return pkt->size; + pkt->stream_index = 0; + pkt->pts = pkt->pos / s->chars_per_frame; pkt->flags |= AV_PKT_FLAG_KEY; return 0; } @@ -153,8 +182,10 @@ .name = "tty", .long_name = NULL_IF_CONFIG_SMALL("Tele-typewriter"), .priv_data_size = sizeof(TtyDemuxContext), + .read_probe = read_probe, .read_header = read_header, .read_packet = read_packet, - .extensions = "ans,art,asc,diz,ice,nfo,txt,vt", + .extensions = tty_extensions, .priv_class = &tty_demuxer_class, + .flags = AVFMT_GENERIC_INDEX, }; diff -Nru ffmpeg-4.2.2/libavformat/ty.c ffmpeg-4.4/libavformat/ty.c --- ffmpeg-4.2.2/libavformat/ty.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/ty.c 2021-04-08 21:28:40.000000000 +0000 @@ -72,11 +72,6 @@ TIVO_AUDIO_MPEG } TiVo_audio; -typedef struct TySeqTable { - uint64_t timestamp; - uint8_t chunk_bitmask[8]; -} TySeqTable; - typedef struct TYDemuxContext { unsigned cur_chunk; unsigned cur_chunk_pos; @@ -90,7 +85,6 @@ int pes_buf_cnt; /* how many bytes in our buffer */ size_t ac3_pkt_size; /* length of ac3 pkt we've seen so far */ uint64_t last_ty_pts; /* last TY timestamp we've seen */ - unsigned seq_table_size; /* number of entries in SEQ table */ int64_t first_audio_pts; int64_t last_audio_pts; @@ -99,8 +93,6 @@ TyRecHdr *rec_hdrs; /* record headers array */ int cur_rec; /* current record in this chunk */ int num_recs; /* number of recs in this chunk */ - int seq_rec; /* record number where seq start is */ - TySeqTable *seq_table; /* table of SEQ entries from mstr chk */ int first_chunk; uint8_t chunk[CHUNK_SIZE]; @@ -339,58 +331,6 @@ return 0; } -/* parse a master chunk, filling the SEQ table and other variables. - * We assume the stream is currently pointing to it. - */ -static void parse_master(AVFormatContext *s) -{ - TYDemuxContext *ty = s->priv_data; - unsigned map_size; /* size of bitmask, in bytes */ - unsigned i, j; - - /* Note that the entries in the SEQ table in the stream may have - different sizes depending on the bits per entry. We store them - all in the same size structure, so we have to parse them out one - by one. If we had a dynamic structure, we could simply read the - entire table directly from the stream into memory in place. */ - - /* clear the SEQ table */ - av_freep(&ty->seq_table); - - /* parse header info */ - - map_size = AV_RB32(ty->chunk + 20); /* size of bitmask, in bytes */ - i = AV_RB32(ty->chunk + 28); /* size of SEQ table, in bytes */ - - ty->seq_table_size = i / (8LL + map_size); - - if (ty->seq_table_size == 0) { - ty->seq_table = NULL; - return; - } - - /* parse all the entries */ - ty->seq_table = av_calloc(ty->seq_table_size, sizeof(TySeqTable)); - if (ty->seq_table == NULL) { - ty->seq_table_size = 0; - return; - } - - ty->cur_chunk_pos = 32; - for (j = 0; j < ty->seq_table_size; j++) { - if (ty->cur_chunk_pos >= CHUNK_SIZE - 8) - return; - ty->seq_table[j].timestamp = AV_RB64(ty->chunk + ty->cur_chunk_pos); - ty->cur_chunk_pos += 8; - if (map_size > 8) { - av_log(s, AV_LOG_ERROR, "Unsupported SEQ bitmap size in master chunk.\n"); - ty->cur_chunk_pos += map_size; - } else { - memcpy(ty->seq_table[j].chunk_bitmask, ty->chunk + ty->cur_chunk_pos, map_size); - } - } -} - static int get_chunk(AVFormatContext *s) { TYDemuxContext *ty = s->priv_data; @@ -413,7 +353,7 @@ /* check if it's a PART Header */ if (AV_RB32(ty->chunk) == TIVO_PES_FILEID) { - parse_master(s); /* parse master chunk */ + /* skip master chunk and read new chunk */ return get_chunk(s); } @@ -421,14 +361,9 @@ if (ty->chunk[3] & 0x80) { /* 16 bit rec cnt */ ty->num_recs = num_recs = (ty->chunk[1] << 8) + ty->chunk[0]; - ty->seq_rec = (ty->chunk[3] << 8) + ty->chunk[2]; - if (ty->seq_rec != 0xffff) { - ty->seq_rec &= ~0x8000; - } } else { /* 8 bit reclen - TiVo 1.3 format */ ty->num_recs = num_recs = ty->chunk[0]; - ty->seq_rec = ty->chunk[1]; } ty->cur_rec = 0; ty->first_chunk = 0; @@ -454,7 +389,7 @@ TYDemuxContext *ty = s->priv_data; const int subrec_type = rec_hdr->subrec_type; const int64_t rec_size = rec_hdr->rec_size; - int es_offset1; + int es_offset1, ret; int got_packet = 0; if (subrec_type != 0x02 && subrec_type != 0x0c && @@ -474,8 +409,8 @@ int size = rec_hdr->rec_size - VIDEO_PES_LENGTH - es_offset1; ty->cur_chunk_pos += VIDEO_PES_LENGTH + es_offset1; - if (av_new_packet(pkt, size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, size)) < 0) + return ret; memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, size); ty->cur_chunk_pos += size; pkt->stream_index = 0; @@ -498,8 +433,8 @@ } if (!got_packet) { - if (av_new_packet(pkt, rec_size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, rec_size)) < 0) + return ret; memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size); ty->cur_chunk_pos += rec_size; pkt->stream_index = 0; @@ -578,7 +513,7 @@ TYDemuxContext *ty = s->priv_data; const int subrec_type = rec_hdr->subrec_type; const int64_t rec_size = rec_hdr->rec_size; - int es_offset1; + int es_offset1, ret; if (subrec_type == 2) { int need = 0; @@ -621,8 +556,8 @@ ty->pes_buf_cnt = 0; } - if (av_new_packet(pkt, rec_size - need) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, rec_size - need)) < 0) + return ret; memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size - need); ty->cur_chunk_pos += rec_size - need; pkt->stream_index = 1; @@ -643,8 +578,8 @@ } } } else if (subrec_type == 0x03) { - if (av_new_packet(pkt, rec_size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, rec_size)) < 0) + return ret; memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size); ty->cur_chunk_pos += rec_size; pkt->stream_index = 1; @@ -674,15 +609,15 @@ } else if (subrec_type == 0x04) { /* SA Audio with no PES Header */ /* ================================================ */ - if (av_new_packet(pkt, rec_size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, rec_size)) < 0) + return ret; memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size); ty->cur_chunk_pos += rec_size; pkt->stream_index = 1; pkt->pts = ty->last_audio_pts; } else if (subrec_type == 0x09) { - if (av_new_packet(pkt, rec_size) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, rec_size)) < 0) + return ret; memcpy(pkt->data, ty->chunk + ty->cur_chunk_pos, rec_size); ty->cur_chunk_pos += rec_size ; pkt->stream_index = 1; @@ -770,7 +705,6 @@ { TYDemuxContext *ty = s->priv_data; - av_freep(&ty->seq_table); av_freep(&ty->rec_hdrs); return 0; diff -Nru ffmpeg-4.2.2/libavformat/udp.c ffmpeg-4.4/libavformat/udp.c --- ffmpeg-4.2.2/libavformat/udp.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/udp.c 2021-04-08 21:28:40.000000000 +0000 @@ -61,8 +61,13 @@ #define IPPROTO_UDPLITE 136 #endif +#if HAVE_W32THREADS +#undef HAVE_PTHREAD_CANCEL +#define HAVE_PTHREAD_CANCEL 1 +#endif + #if HAVE_PTHREAD_CANCEL -#include +#include "libavutil/thread.h" #endif #ifndef IPV6_ADD_MEMBERSHIP @@ -71,6 +76,7 @@ #endif #define UDP_TX_BUF_SIZE 32768 +#define UDP_RX_BUF_SIZE 393216 #define UDP_MAX_PKT_SIZE 65536 #define UDP_HEADER_SIZE 8 @@ -132,7 +138,7 @@ { "connect", "set if connect() should be called on socket", OFFSET(is_connected), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E }, { "fifo_size", "set the UDP receiving circular buffer size, expressed as a number of packets with size of 188 bytes", OFFSET(circular_buffer_size), AV_OPT_TYPE_INT, {.i64 = 7*4096}, 0, INT_MAX, D }, { "overrun_nonfatal", "survive in case of UDP receiving circular buffer overrun", OFFSET(overrun_nonfatal), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, D }, - { "timeout", "set raise error timeout (only in read mode)", OFFSET(timeout), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, + { "timeout", "set raise error timeout, in microseconds (only in read mode)",OFFSET(timeout), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D }, { "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 }, { NULL } @@ -159,7 +165,7 @@ if (addr->sa_family == AF_INET) { if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL, sizeof(mcastTTL)) < 0) { ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_MULTICAST_TTL)"); - return -1; + return ff_neterrno(); } } #endif @@ -167,7 +173,7 @@ if (addr->sa_family == AF_INET6) { if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTL, sizeof(mcastTTL)) < 0) { ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_MULTICAST_HOPS)"); - return -1; + return ff_neterrno(); } } #endif @@ -184,10 +190,10 @@ if (local_addr) mreq.imr_interface= ((struct sockaddr_in *)local_addr)->sin_addr; else - mreq.imr_interface.s_addr= INADDR_ANY; + mreq.imr_interface.s_addr = INADDR_ANY; if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) { ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_MEMBERSHIP)"); - return -1; + return ff_neterrno(); } } #endif @@ -197,10 +203,10 @@ memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr)); //TODO: Interface index should be looked up from local_addr - mreq6.ipv6mr_interface= 0; + mreq6.ipv6mr_interface = 0; if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_ADD_MEMBERSHIP)"); - return -1; + return ff_neterrno(); } } #endif @@ -215,9 +221,9 @@ mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; if (local_addr) - mreq.imr_interface= ((struct sockaddr_in *)local_addr)->sin_addr; + mreq.imr_interface = ((struct sockaddr_in *)local_addr)->sin_addr; else - mreq.imr_interface.s_addr= INADDR_ANY; + mreq.imr_interface.s_addr = INADDR_ANY; if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) { ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_DROP_MEMBERSHIP)"); return -1; @@ -230,7 +236,7 @@ memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr)); //TODO: Interface index should be looked up from local_addr - mreq6.ipv6mr_interface= 0; + mreq6.ipv6mr_interface = 0; if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_DROP_MEMBERSHIP)"); return -1; @@ -274,7 +280,7 @@ } return 0; #else - av_log(NULL, AV_LOG_ERROR, + av_log(h, AV_LOG_ERROR, "Setting multicast sources only supported for IPv4\n"); return AVERROR(EINVAL); #endif @@ -283,24 +289,24 @@ for (i = 0; i < nb_sources; i++) { struct ip_mreq_source mreqs; if (sources[i].ss_family != AF_INET) { - av_log(NULL, AV_LOG_ERROR, "Source/block address %d is of incorrect protocol family\n", i + 1); + av_log(h, AV_LOG_ERROR, "Source/block address %d is of incorrect protocol family\n", i + 1); return AVERROR(EINVAL); } mreqs.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; if (local_addr) - mreqs.imr_interface= ((struct sockaddr_in *)local_addr)->sin_addr; + mreqs.imr_interface = ((struct sockaddr_in *)local_addr)->sin_addr; else - mreqs.imr_interface.s_addr= INADDR_ANY; + mreqs.imr_interface.s_addr = INADDR_ANY; mreqs.imr_sourceaddr.s_addr = ((struct sockaddr_in *)&sources[i])->sin_addr.s_addr; if (setsockopt(sockfd, IPPROTO_IP, include ? IP_ADD_SOURCE_MEMBERSHIP : IP_BLOCK_SOURCE, (const void *)&mreqs, sizeof(mreqs)) < 0) { if (include) - ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_SOURCE_MEMBERSHIP)"); + ff_log_net_error(h, AV_LOG_ERROR, "setsockopt(IP_ADD_SOURCE_MEMBERSHIP)"); else - ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_BLOCK_SOURCE)"); + ff_log_net_error(h, AV_LOG_ERROR, "setsockopt(IP_BLOCK_SOURCE)"); return ff_neterrno(); } } @@ -519,14 +525,12 @@ { URLContext *h = _URLContext; UDPContext *s = h->priv_data; - int old_cancelstate; int64_t target_timestamp = av_gettime_relative(); int64_t start_timestamp = av_gettime_relative(); int64_t sent_bits = 0; int64_t burst_interval = s->bitrate ? (s->burst_bits * 1000000 / s->bitrate) : 0; int64_t max_delay = s->bitrate ? ((int64_t)h->max_packet_size * 8 * 1000000 / s->bitrate + 1) : 0; - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelstate); pthread_mutex_lock(&s->mutex); if (ff_socket_nonblock(s->udp_fd, 0) < 0) { @@ -541,7 +545,7 @@ uint8_t tmp[4]; int64_t timestamp; - len=av_fifo_size(s->fifo); + len = av_fifo_size(s->fifo); while (len<4) { if (s->close_req) @@ -549,11 +553,11 @@ if (pthread_cond_wait(&s->cond, &s->mutex) < 0) { goto end; } - len=av_fifo_size(s->fifo); + len = av_fifo_size(s->fifo); } av_fifo_generic_read(s->fifo, tmp, 4, NULL); - len=AV_RL32(tmp); + len = AV_RL32(tmp); av_assert0(len >= 0); av_assert0(len <= sizeof(s->tmp)); @@ -561,7 +565,6 @@ av_fifo_generic_read(s->fifo, s->tmp, len, NULL); pthread_mutex_unlock(&s->mutex); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancelstate); if (s->bitrate) { timestamp = av_gettime_relative(); @@ -607,7 +610,6 @@ } } - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelstate); pthread_mutex_lock(&s->mutex); } @@ -631,26 +633,24 @@ char buf[256]; struct sockaddr_storage my_addr; socklen_t len; + int ret; h->is_streamed = 1; is_output = !(flags & AVIO_FLAG_READ); if (s->buffer_size < 0) - s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE; + s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_RX_BUF_SIZE; if (s->sources) { - if (ff_ip_parse_sources(h, s->sources, &s->filters) < 0) + if ((ret = ff_ip_parse_sources(h, s->sources, &s->filters)) < 0) goto fail; } if (s->block) { - if (ff_ip_parse_blocks(h, s->block, &s->filters) < 0) + if ((ret = ff_ip_parse_blocks(h, s->block, &s->filters)) < 0) goto fail; } - if (s->pkt_size > 0) - h->max_packet_size = s->pkt_size; - p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "reuse", p)) { @@ -713,11 +713,11 @@ av_strlcpy(localaddr, buf, sizeof(localaddr)); } if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { - if (ff_ip_parse_sources(h, buf, &s->filters) < 0) + if ((ret = ff_ip_parse_sources(h, buf, &s->filters)) < 0) goto fail; } if (av_find_info_tag(buf, sizeof(buf), "block", p)) { - if (ff_ip_parse_blocks(h, buf, &s->filters) < 0) + if ((ret = ff_ip_parse_blocks(h, buf, &s->filters)) < 0) goto fail; } if (!is_output && av_find_info_tag(buf, sizeof(buf), "timeout", p)) @@ -743,7 +743,7 @@ if (!(flags & AVIO_FLAG_READ)) goto fail; } else { - if (ff_udp_set_remote_url(h, uri) < 0) + if ((ret = ff_udp_set_remote_url(h, uri)) < 0) goto fail; } @@ -764,15 +764,22 @@ */ if (s->reuse_socket > 0 || (s->is_multicast && s->reuse_socket < 0)) { s->reuse_socket = 1; - if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0) + if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0) { + ret = ff_neterrno(); goto fail; + } } if (s->is_broadcast) { #ifdef SO_BROADCAST - if (setsockopt (udp_fd, SOL_SOCKET, SO_BROADCAST, &(s->is_broadcast), sizeof(s->is_broadcast)) != 0) + if (setsockopt (udp_fd, SOL_SOCKET, SO_BROADCAST, &(s->is_broadcast), sizeof(s->is_broadcast)) != 0) { + ret = ff_neterrno(); + goto fail; + } +#else + ret = AVERROR(ENOSYS); + goto fail; #endif - goto fail; } /* Set the checksum coverage for UDP-Lite (RFC 3828) for sending and receiving. @@ -789,15 +796,17 @@ if (dscp >= 0) { dscp <<= 2; - if (setsockopt (udp_fd, IPPROTO_IP, IP_TOS, &dscp, sizeof(dscp)) != 0) + if (setsockopt (udp_fd, IPPROTO_IP, IP_TOS, &dscp, sizeof(dscp)) != 0) { + ret = ff_neterrno(); goto fail; + } } /* If multicast, try binding the multicast address first, to avoid * receiving UDP packets from other sources aimed at the same UDP * port. This fails on windows. This makes sending to the same address * using sendto() fail, so only do it if we're opened in read-only mode. */ - if (s->is_multicast && !(h->flags & AVIO_FLAG_WRITE)) { + if (s->is_multicast && (h->flags & AVIO_FLAG_READ)) { bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len); } /* bind to the local address if not multicast or if the multicast @@ -805,6 +814,7 @@ /* the bind is needed to give a port to the socket now */ if (bind_ret < 0 && bind(udp_fd,(struct sockaddr *)&my_addr, len) < 0) { ff_log_net_error(h, AV_LOG_ERROR, "bind failed"); + ret = ff_neterrno(); goto fail; } @@ -815,28 +825,28 @@ if (s->is_multicast) { if (h->flags & AVIO_FLAG_WRITE) { /* output */ - if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0) + if ((ret = udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr)) < 0) goto fail; } if (h->flags & AVIO_FLAG_READ) { /* input */ if (s->filters.nb_include_addrs) { - if (udp_set_multicast_sources(h, udp_fd, + if ((ret = udp_set_multicast_sources(h, udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, &s->local_addr_storage, s->filters.include_addrs, - s->filters.nb_include_addrs, 1) < 0) + s->filters.nb_include_addrs, 1)) < 0) goto fail; } else { - if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr,(struct sockaddr *)&s->local_addr_storage) < 0) + if ((ret = udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr,(struct sockaddr *)&s->local_addr_storage)) < 0) goto fail; } if (s->filters.nb_exclude_addrs) { - if (udp_set_multicast_sources(h, udp_fd, + if ((ret = udp_set_multicast_sources(h, udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, &s->local_addr_storage, s->filters.exclude_addrs, - s->filters.nb_exclude_addrs, 0) < 0) + s->filters.nb_exclude_addrs, 0)) < 0) goto fail; } } @@ -847,10 +857,11 @@ tmp = s->buffer_size; if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) { ff_log_net_error(h, AV_LOG_ERROR, "setsockopt(SO_SNDBUF)"); + ret = ff_neterrno(); goto fail; } } else { - /* set udp recv buffer size to the requested value (default 64K) */ + /* set udp recv buffer size to the requested value (default UDP_RX_BUF_SIZE) */ tmp = s->buffer_size; if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) { ff_log_net_error(h, AV_LOG_WARNING, "setsockopt(SO_RECVBUF)"); @@ -861,7 +872,7 @@ } else { av_log(h, AV_LOG_DEBUG, "end receive buffer size reported is %d\n", tmp); if(tmp < s->buffer_size) - av_log(h, AV_LOG_WARNING, "attempted to set receive buffer to size %d but it only ended up set as %d", s->buffer_size, tmp); + av_log(h, AV_LOG_WARNING, "attempted to set receive buffer to size %d but it only ended up set as %d\n", s->buffer_size, tmp); } /* make the socket non-blocking */ @@ -870,6 +881,7 @@ if (s->is_connected) { if (connect(udp_fd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len)) { ff_log_net_error(h, AV_LOG_ERROR, "connect"); + ret = ff_neterrno(); goto fail; } } @@ -889,23 +901,28 @@ } if ((!is_output && s->circular_buffer_size) || (is_output && s->bitrate && s->circular_buffer_size)) { - int ret; - /* start the task going */ s->fifo = av_fifo_alloc(s->circular_buffer_size); + if (!s->fifo) { + ret = AVERROR(ENOMEM); + goto fail; + } ret = pthread_mutex_init(&s->mutex, NULL); if (ret != 0) { av_log(h, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", strerror(ret)); + ret = AVERROR(ret); goto fail; } ret = pthread_cond_init(&s->cond, NULL); if (ret != 0) { av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", strerror(ret)); + ret = AVERROR(ret); goto cond_fail; } ret = pthread_create(&s->circular_buffer_thread, NULL, is_output?circular_buffer_task_tx:circular_buffer_task_rx, h); if (ret != 0) { av_log(h, AV_LOG_ERROR, "pthread_create failed : %s\n", strerror(ret)); + ret = AVERROR(ret); goto thread_fail; } s->thread_started = 1; @@ -924,7 +941,7 @@ closesocket(udp_fd); av_fifo_freep(&s->fifo); ff_ip_reset_filters(&s->filters); - return AVERROR(EIO); + return ret; } static int udplite_open(URLContext *h, const char *uri, int flags) @@ -954,10 +971,10 @@ uint8_t tmp[4]; av_fifo_generic_read(s->fifo, tmp, 4, NULL); - avail= AV_RL32(tmp); + avail = AV_RL32(tmp); if(avail > size){ av_log(h, AV_LOG_WARNING, "Part of datagram lost due to insufficient buffer size\n"); - avail= size; + avail = size; } av_fifo_generic_read(s->fifo, buf, avail, NULL); @@ -971,20 +988,20 @@ } else if(nonblock) { pthread_mutex_unlock(&s->mutex); return AVERROR(EAGAIN); - } - else { + } else { /* FIXME: using the monotonic clock would be better, but it does not exist on all supported platforms. */ int64_t t = av_gettime() + 100000; struct timespec tv = { .tv_sec = t / 1000000, .tv_nsec = (t % 1000000) * 1000 }; - if (pthread_cond_timedwait(&s->cond, &s->mutex, &tv) < 0) { + int err = pthread_cond_timedwait(&s->cond, &s->mutex, &tv); + if (err) { pthread_mutex_unlock(&s->mutex); - return AVERROR(errno == ETIMEDOUT ? EAGAIN : errno); + return AVERROR(err == ETIMEDOUT ? EAGAIN : err); } nonblock = 1; } - } while( 1); + } while(1); } #endif @@ -1017,7 +1034,7 @@ Here we can't know on which packet error was, but it needs to know that error exists. */ if (s->circular_buffer_error<0) { - int err=s->circular_buffer_error; + int err = s->circular_buffer_error; pthread_mutex_unlock(&s->mutex); return err; } @@ -1071,8 +1088,17 @@ if (s->thread_started) { int ret; // Cancel only read, as write has been signaled as success to the user - if (h->flags & AVIO_FLAG_READ) + if (h->flags & AVIO_FLAG_READ) { +#ifdef _WIN32 + /* recvfrom() is not a cancellation point for win32, so we shutdown + * the socket and abort pending IO, subsequent recvfrom() calls + * will fail with WSAESHUTDOWN causing the thread to exit. */ + shutdown(s->udp_fd, SD_RECEIVE); + CancelIoEx((HANDLE)(SOCKET)s->udp_fd, NULL); +#else pthread_cancel(s->circular_buffer_thread); +#endif + } ret = pthread_join(s->circular_buffer_thread, NULL); if (ret != 0) av_log(h, AV_LOG_ERROR, "pthread_join(): %s\n", strerror(ret)); diff -Nru ffmpeg-4.2.2/libavformat/url.c ffmpeg-4.4/libavformat/url.c --- ffmpeg-4.2.2/libavformat/url.c 2017-12-31 22:35:49.000000000 +0000 +++ ffmpeg-4.4/libavformat/url.c 2021-04-08 21:28:27.000000000 +0000 @@ -21,11 +21,13 @@ #include "avformat.h" +#include "internal.h" #include "config.h" #include "url.h" #if CONFIG_NETWORK #include "network.h" #endif +#include "libavutil/avassert.h" #include "libavutil/avstring.h" /** @@ -77,73 +79,247 @@ return strlen(str); } -void ff_make_absolute_url(char *buf, int size, const char *base, - const char *rel) +static const char *find_delim(const char *delim, const char *cur, const char *end) { - char *sep, *path_query; - /* Absolute path, relative to the current server */ - if (base && strstr(base, "://") && rel[0] == '/') { - if (base != buf) - av_strlcpy(buf, base, size); - sep = strstr(buf, "://"); - if (sep) { - /* Take scheme from base url */ - if (rel[1] == '/') { - sep[1] = '\0'; - } else { - /* Take scheme and host from base url */ - sep += 3; - sep = strchr(sep, '/'); - if (sep) - *sep = '\0'; - } - } - av_strlcat(buf, rel, size); - return; - } - /* If rel actually is an absolute url, just copy it */ - if (!base || strstr(rel, "://") || rel[0] == '/') { - av_strlcpy(buf, rel, size); - return; - } - if (base != buf) - av_strlcpy(buf, base, size); - - /* Strip off any query string from base */ - path_query = strchr(buf, '?'); - if (path_query) - *path_query = '\0'; - - /* Is relative path just a new query part? */ - if (rel[0] == '?') { - av_strlcat(buf, rel, size); - return; - } - - /* Remove the file name from the base url */ - sep = strrchr(buf, '/'); - if (sep) - sep[1] = '\0'; - else - buf[0] = '\0'; - while (av_strstart(rel, "../", NULL) && sep) { - /* Remove the path delimiter at the end */ - sep[0] = '\0'; - sep = strrchr(buf, '/'); - /* If the next directory name to pop off is "..", break here */ - if (!strcmp(sep ? &sep[1] : buf, "..")) { - /* Readd the slash we just removed */ - av_strlcat(buf, "/", size); - break; - } - /* Cut off the directory name */ - if (sep) - sep[1] = '\0'; - else - buf[0] = '\0'; - rel += 3; + while (cur < end && !strchr(delim, *cur)) + cur++; + return cur; +} + +int ff_url_decompose(URLComponents *uc, const char *url, const char *end) +{ + const char *cur, *aend, *p; + + av_assert0(url); + if (!end) + end = url + strlen(url); + cur = uc->url = url; + + /* scheme */ + uc->scheme = cur; + p = find_delim(":/?#", cur, end); /* lavf "schemes" can contain options but not some RFC 3986 delimiters */ + if (*p == ':') + cur = p + 1; + + /* authority */ + uc->authority = cur; + if (end - cur >= 2 && cur[0] == '/' && cur[1] == '/') { + cur += 2; + aend = find_delim("/?#", cur, end); + + /* userinfo */ + uc->userinfo = cur; + p = find_delim("@", cur, aend); + if (*p == '@') + cur = p + 1; + + /* host */ + uc->host = cur; + if (*cur == '[') { /* hello IPv6, thanks for using colons! */ + p = find_delim("]", cur, aend); + if (*p != ']') + return AVERROR(EINVAL); + if (p + 1 < aend && p[1] != ':') + return AVERROR(EINVAL); + cur = p + 1; + } else { + cur = find_delim(":", cur, aend); + } + + /* port */ + uc->port = cur; + cur = aend; + } else { + uc->userinfo = uc->host = uc->port = cur; } - av_strlcat(buf, rel, size); + + /* path */ + uc->path = cur; + cur = find_delim("?#", cur, end); + + /* query */ + uc->query = cur; + if (*cur == '?') + cur = find_delim("#", cur, end); + + /* fragment */ + uc->fragment = cur; + + uc->end = end; + return 0; +} + +static int is_fq_dos_path(const char *path) +{ + if ((path[0] >= 'a' && path[0] <= 'z' || path[0] >= 'A' && path[0] <= 'Z') && + path[1] == ':' && + (path[2] == '/' || path[2] == '\\')) + return 1; + if ((path[0] == '/' || path[0] == '\\') && + (path[1] == '/' || path[1] == '\\')) + return 1; + return 0; +} + +static int append_path(char *root, char *out_end, char **rout, + const char *in, const char *in_end) +{ + char *out = *rout; + const char *d, *next; + + if (in < in_end && *in == '/') + in++; /* already taken care of */ + while (in < in_end) { + d = find_delim("/", in, in_end); + next = d + (d < in_end && *d == '/'); + if (d - in == 1 && in[0] == '.') { + /* skip */ + } else if (d - in == 2 && in[0] == '.' && in[1] == '.') { + av_assert1(out[-1] == '/'); + if (out - root > 1) + while (out > root && (--out)[-1] != '/'); + } else { + if (out_end - out < next - in) + return AVERROR(ENOMEM); + memmove(out, in, next - in); + out += next - in; + } + in = next; + } + *rout = out; + return 0; +} + +int ff_make_absolute_url2(char *buf, int size, const char *base, + const char *rel, int handle_dos_paths) +{ + URLComponents ub, uc; + char *out, *out_end, *path; + const char *keep, *base_path_end; + int use_base_path, simplify_path = 0, ret; + const char *base_separators = "/"; + + /* This is tricky. + For HTTP, http://server/site/page + ../media/file + should resolve into http://server/media/file + but for filesystem access, dir/playlist + ../media/file + should resolve into dir/../media/file + because dir could be a symlink, and .. points to + the actual parent of the target directory. + + We'll consider that URLs with an actual scheme and authority, + i.e. starting with scheme://, need parent dir simplification, + while bare paths or pseudo-URLs starting with proto: without + the double slash do not. + + For real URLs, the processing is similar to the algorithm described + here: + https://tools.ietf.org/html/rfc3986#section-5 + */ + + if (!size) + return AVERROR(ENOMEM); + out = buf; + out_end = buf + size - 1; + + if (!base) + base = ""; + if (handle_dos_paths) { + if ((ret = ff_url_decompose(&ub, base, NULL)) < 0) + goto error; + if (is_fq_dos_path(base) || av_strstart(base, "file:", NULL) || ub.path == ub.url) { + base_separators = "/\\"; + if (is_fq_dos_path(rel)) + base = ""; + } + } + if ((ret = ff_url_decompose(&ub, base, NULL)) < 0 || + (ret = ff_url_decompose(&uc, rel, NULL)) < 0) + goto error; + + keep = ub.url; +#define KEEP(component, also) do { \ + if (uc.url_component_end_##component == uc.url && \ + ub.url_component_end_##component > keep) { \ + keep = ub.url_component_end_##component; \ + also \ + } \ + } while (0) + KEEP(scheme, ); + KEEP(authority_full, simplify_path = 1;); + KEEP(path,); + KEEP(query,); + KEEP(fragment,); +#undef KEEP +#define COPY(start, end) do { \ + size_t len = end - start; \ + if (len > out_end - out) { \ + ret = AVERROR(ENOMEM); \ + goto error; \ + } \ + memmove(out, start, len); \ + out += len; \ + } while (0) + COPY(ub.url, keep); + COPY(uc.url, uc.path); + + use_base_path = URL_COMPONENT_HAVE(ub, path) && keep <= ub.path; + if (uc.path > uc.url) + use_base_path = 0; + if (URL_COMPONENT_HAVE(uc, path) && uc.path[0] == '/') + use_base_path = 0; + if (use_base_path) { + base_path_end = ub.url_component_end_path; + if (URL_COMPONENT_HAVE(uc, path)) + while (base_path_end > ub.path && !strchr(base_separators, base_path_end[-1])) + base_path_end--; + } + if (keep > ub.path) + simplify_path = 0; + if (URL_COMPONENT_HAVE(uc, scheme)) + simplify_path = 0; + if (URL_COMPONENT_HAVE(uc, authority)) + simplify_path = 1; + /* No path at all, leave it */ + if (!use_base_path && !URL_COMPONENT_HAVE(uc, path)) + simplify_path = 0; + + if (simplify_path) { + const char *root = "/"; + COPY(root, root + 1); + path = out; + if (use_base_path) { + ret = append_path(path, out_end, &out, ub.path, base_path_end); + if (ret < 0) + goto error; + } + if (URL_COMPONENT_HAVE(uc, path)) { + ret = append_path(path, out_end, &out, uc.path, uc.url_component_end_path); + if (ret < 0) + goto error; + } + } else { + if (use_base_path) + COPY(ub.path, base_path_end); + COPY(uc.path, uc.url_component_end_path); + } + + COPY(uc.url_component_end_path, uc.end); +#undef COPY + *out = 0; + return 0; + +error: + snprintf(buf, size, "invalid:%s", + ret == AVERROR(ENOMEM) ? "truncated" : + ret == AVERROR(EINVAL) ? "syntax_error" : ""); + return ret; +} + +int ff_make_absolute_url(char *buf, int size, const char *base, + const char *rel) +{ + return ff_make_absolute_url2(buf, size, base, rel, HAVE_DOS_PATHS); } AVIODirEntry *ff_alloc_dir_entry(void) diff -Nru ffmpeg-4.2.2/libavformat/urldecode.c ffmpeg-4.4/libavformat/urldecode.c --- ffmpeg-4.2.2/libavformat/urldecode.c 2016-03-29 02:25:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/urldecode.c 2020-07-11 10:39:30.000000000 +0000 @@ -32,7 +32,7 @@ #include "libavutil/avstring.h" #include "urldecode.h" -char *ff_urldecode(const char *url) +char *ff_urldecode(const char *url, int decode_plus_sign) { int s = 0, d = 0, url_len = 0; char c; @@ -74,7 +74,7 @@ dest[d++] = c2; dest[d++] = c3; } - } else if (c == '+') { + } else if (c == '+' && decode_plus_sign) { dest[d++] = ' '; } else { dest[d++] = c; diff -Nru ffmpeg-4.2.2/libavformat/urldecode.h ffmpeg-4.4/libavformat/urldecode.h --- ffmpeg-4.2.2/libavformat/urldecode.h 2016-03-29 02:25:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/urldecode.h 2020-07-11 10:39:30.000000000 +0000 @@ -26,10 +26,11 @@ * in that case the original string is duplicated. * * @param url a string to be decoded. + * @param decode_plus_sign if nonzero plus sign is decoded to space * @return new string with the URL decoded or NULL if decoding failed. * Note that the returned string should be explicitly freed when not * used anymore. */ -char *ff_urldecode(const char *url); +char *ff_urldecode(const char *url, int decode_plus_sign); #endif /* AVFORMAT_URLDECODE_H */ diff -Nru ffmpeg-4.2.2/libavformat/url.h ffmpeg-4.4/libavformat/url.h --- ffmpeg-4.2.2/libavformat/url.h 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/url.h 2021-04-08 21:28:40.000000000 +0000 @@ -56,8 +56,8 @@ int (*url_open)( URLContext *h, const char *url, int flags); /** * This callback is to be used by protocols which open further nested - * protocols. options are then to be passed to ffurl_open()/ffurl_connect() - * for those nested protocols. + * protocols. options are then to be passed to ffurl_open_whitelist() + * or ffurl_connect() for those nested protocols. */ int (*url_open2)(URLContext *h, const char *url, int flags, AVDictionary **options); int (*url_accept)(URLContext *s, URLContext **c); @@ -87,8 +87,8 @@ int *numhandles); int (*url_get_short_seek)(URLContext *h); int (*url_shutdown)(URLContext *h, int flags); - int priv_data_size; const AVClass *priv_data_class; + int priv_data_size; int flags; int (*url_check)(URLContext *h, int mask); int (*url_open_dir)(URLContext *h); @@ -148,9 +148,6 @@ const char *whitelist, const char* blacklist, URLContext *parent); -int ffurl_open(URLContext **puc, const char *filename, int flags, - const AVIOInterruptCB *int_cb, AVDictionary **options); - /** * Accept an URLContext c on an URLContext s * @@ -311,9 +308,19 @@ * @param size the size of buf * @param base the base url, may be equal to buf. * @param rel the new url, which is interpreted relative to base + * @param handle_dos_paths handle DOS paths for file or unspecified protocol + */ +int ff_make_absolute_url2(char *buf, int size, const char *base, + const char *rel, int handle_dos_paths); + +/** + * Convert a relative url into an absolute url, given a base url. + * + * Same as ff_make_absolute_url2 with handle_dos_paths being equal to + * HAVE_DOS_PATHS config variable. */ -void ff_make_absolute_url(char *buf, int size, const char *base, - const char *rel); +int ff_make_absolute_url(char *buf, int size, const char *base, + const char *rel); /** * Allocate directory entry with default values. @@ -322,7 +329,11 @@ */ AVIODirEntry *ff_alloc_dir_entry(void); +#if FF_API_CHILD_CLASS_NEXT const AVClass *ff_urlcontext_child_class_next(const AVClass *prev); +#endif + +const AVClass *ff_urlcontext_child_class_iterate(void **iter); /** * Construct a list of protocols matching a given whitelist and/or blacklist. @@ -340,4 +351,45 @@ const URLProtocol **ffurl_get_protocols(const char *whitelist, const char *blacklist); +typedef struct URLComponents { + const char *url; /**< whole URL, for reference */ + const char *scheme; /**< possibly including lavf-specific options */ + const char *authority; /**< "//" if it is a real URL */ + const char *userinfo; /**< including final '@' if present */ + const char *host; + const char *port; /**< including initial ':' if present */ + const char *path; + const char *query; /**< including initial '?' if present */ + const char *fragment; /**< including initial '#' if present */ + const char *end; +} URLComponents; + +#define url_component_end_scheme authority +#define url_component_end_authority userinfo +#define url_component_end_userinfo host +#define url_component_end_host port +#define url_component_end_port path +#define url_component_end_path query +#define url_component_end_query fragment +#define url_component_end_fragment end +#define url_component_end_authority_full path + +#define URL_COMPONENT_HAVE(uc, component) \ + ((uc).url_component_end_##component > (uc).component) + +/** + * Parse an URL to find the components. + * + * Each component runs until the start of the next component, + * possibly including a mandatory delimiter. + * + * @param uc structure to fill with pointers to the components. + * @param url URL to parse. + * @param end end of the URL, or NULL to parse to the end of string. + * + * @return >= 0 for success or an AVERROR code, especially if the URL is + * malformed. + */ +int ff_url_decompose(URLComponents *uc, const char *url, const char *end); + #endif /* AVFORMAT_URL_H */ diff -Nru ffmpeg-4.2.2/libavformat/utils.c ffmpeg-4.4/libavformat/utils.c --- ffmpeg-4.2.2/libavformat/utils.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/utils.c 2021-04-08 21:28:40.000000000 +0000 @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include #include "config.h" @@ -31,26 +30,23 @@ #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" -#include "libavutil/pixdesc.h" +#include "libavutil/pixfmt.h" #include "libavutil/thread.h" #include "libavutil/time.h" -#include "libavutil/time_internal.h" #include "libavutil/timestamp.h" #include "libavcodec/bytestream.h" #include "libavcodec/internal.h" +#include "libavcodec/packet_internal.h" #include "libavcodec/raw.h" -#include "audiointerleave.h" #include "avformat.h" #include "avio_internal.h" #include "id3v2.h" #include "internal.h" -#include "metadata.h" #if CONFIG_NETWORK #include "network.h" #endif -#include "riff.h" #include "url.h" #include "libavutil/ffversion.h" @@ -77,7 +73,7 @@ const char *avformat_license(void) { #define LICENSE_PREFIX "libavformat license: " - return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; } int ff_lock_avformat(void) @@ -105,13 +101,13 @@ */ static int64_t wrap_timestamp(const AVStream *st, int64_t timestamp) { - if (st->pts_wrap_behavior != AV_PTS_WRAP_IGNORE && - st->pts_wrap_reference != AV_NOPTS_VALUE && timestamp != AV_NOPTS_VALUE) { - if (st->pts_wrap_behavior == AV_PTS_WRAP_ADD_OFFSET && - timestamp < st->pts_wrap_reference) + if (st->internal->pts_wrap_behavior != AV_PTS_WRAP_IGNORE && st->pts_wrap_bits < 64 && + st->internal->pts_wrap_reference != AV_NOPTS_VALUE && timestamp != AV_NOPTS_VALUE) { + if (st->internal->pts_wrap_behavior == AV_PTS_WRAP_ADD_OFFSET && + timestamp < st->internal->pts_wrap_reference) return timestamp + (1ULL << st->pts_wrap_bits); - else if (st->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET && - timestamp >= st->pts_wrap_reference) + else if (st->internal->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET && + timestamp >= st->internal->pts_wrap_reference) return timestamp - (1ULL << st->pts_wrap_bits); } return timestamp; @@ -157,7 +153,7 @@ s->internal->inject_global_side_data = 1; for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - st->inject_global_side_data = 1; + st->internal->inject_global_side_data = 1; } } @@ -222,8 +218,9 @@ if (codec->capabilities & AV_CODEC_CAP_AVOID_PROBING) { const AVCodec *probe_codec = NULL; - while (probe_codec = av_codec_next(probe_codec)) { - if (probe_codec->id == codec_id && + void *iter = NULL; + while ((probe_codec = av_codec_iterate(&iter))) { + if (probe_codec->id == codec->id && av_codec_is_decoder(probe_codec) && !(probe_codec->capabilities & (AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_EXPERIMENTAL))) { return probe_codec; @@ -247,18 +244,23 @@ int ffio_limit(AVIOContext *s, int size) { if (s->maxsize>= 0) { - int64_t remaining= s->maxsize - avio_tell(s); + int64_t pos = avio_tell(s); + int64_t remaining= s->maxsize - pos; if (remaining < size) { int64_t newsize = avio_size(s); if (!s->maxsize || s->maxsizemaxsize = newsize - !newsize; - remaining= s->maxsize - avio_tell(s); - remaining= FFMAX(remaining, 0); + if (pos > s->maxsize && s->maxsize >= 0) + s->maxsize = AVERROR(EIO); + if (s->maxsize >= 0) + remaining = s->maxsize - pos; } - if (s->maxsize>= 0 && remaining+1 < size) { - av_log(NULL, remaining ? AV_LOG_ERROR : AV_LOG_DEBUG, "Truncating packet of size %d to %"PRId64"\n", size, remaining+1); - size = remaining+1; + if (s->maxsize >= 0 && remaining < size && size > 1) { + av_log(NULL, remaining ? AV_LOG_ERROR : AV_LOG_DEBUG, + "Truncating packet of size %d to %"PRId64"\n", + size, remaining + !remaining); + size = remaining + !remaining; } } return size; @@ -268,7 +270,6 @@ * Return the number of bytes read or an error. */ static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size) { - int64_t orig_pos = pkt->pos; // av_grow_packet might reset pos int orig_size = pkt->size; int ret; @@ -301,7 +302,6 @@ if (size > 0) pkt->flags |= AV_PKT_FLAG_CORRUPT; - pkt->pos = orig_pos; if (!pkt->size) av_packet_unref(pkt); return pkt->size > orig_size ? pkt->size - orig_size : ret; @@ -309,9 +309,15 @@ int av_get_packet(AVIOContext *s, AVPacket *pkt, int size) { +#if FF_API_INIT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS av_init_packet(pkt); pkt->data = NULL; pkt->size = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#else + av_packet_unref(pkt); +#endif pkt->pos = avio_tell(s); return append_packet_chunked(s, pkt, size); @@ -363,14 +369,14 @@ int i; av_log(s, AV_LOG_DEBUG, "Probe with size=%d, packets=%d detected %s with score=%d\n", - pd->buf_size, MAX_PROBE_PACKETS - st->probe_packets, + pd->buf_size, s->max_probe_packets - st->probe_packets, fmt->name, score); for (i = 0; fmt_id_type[i].name; i++) { if (!strcmp(fmt->name, fmt_id_type[i].name)) { if (fmt_id_type[i].type != AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate) continue; - if (st->request_probe > score && + if (st->internal->request_probe > score && st->codecpar->codec_id != fmt_id_type[i].id) continue; st->codecpar->codec_id = fmt_id_type[i].id; @@ -392,6 +398,7 @@ /************************************************************/ /* input media file */ +#if FF_API_DEMUXER_OPEN int av_demuxer_open(AVFormatContext *ic) { int err; @@ -411,7 +418,7 @@ return 0; } - +#endif /* Open input file and probe the format if necessary. */ static int init_input(AVFormatContext *s, const char *filename, AVDictionary **options) @@ -444,38 +451,6 @@ s, 0, s->format_probesize); } -int ff_packet_list_put(AVPacketList **packet_buffer, - AVPacketList **plast_pktl, - AVPacket *pkt, int flags) -{ - AVPacketList *pktl = av_mallocz(sizeof(AVPacketList)); - int ret; - - if (!pktl) - return AVERROR(ENOMEM); - - if (flags & FF_PACKETLIST_FLAG_REF_PACKET) { - if ((ret = av_packet_ref(&pktl->pkt, pkt)) < 0) { - av_free(pktl); - return ret; - } - } else { - // TODO: Adapt callers in this file so the line below can use - // av_packet_move_ref() to effectively move the reference - // to the list. - pktl->pkt = *pkt; - } - - if (*packet_buffer) - (*plast_pktl)->next = pktl; - else - *packet_buffer = pktl; - - /* Add the packet in the buffered packet list. */ - *plast_pktl = pktl; - return 0; -} - int avformat_queue_attached_pictures(AVFormatContext *s) { int i, ret; @@ -489,10 +464,10 @@ continue; } - ret = ff_packet_list_put(&s->internal->raw_packet_buffer, + ret = avpriv_packet_list_put(&s->internal->raw_packet_buffer, &s->internal->raw_packet_buffer_end, &s->streams[i]->attached_pic, - FF_PACKETLIST_FLAG_REF_PACKET); + av_packet_ref, 0); if (ret < 0) return ret; } @@ -626,8 +601,11 @@ if (s->pb) ff_id3v2_read_dict(s->pb, &s->internal->id3v2_meta, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); - +#if FF_API_DEMUXER_OPEN if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header) +#else + if (s->iformat->read_header) +#endif if ((ret = s->iformat->read_header(s)) < 0) goto fail; @@ -635,33 +613,32 @@ s->metadata = s->internal->id3v2_meta; s->internal->id3v2_meta = NULL; } else if (s->internal->id3v2_meta) { - int level = AV_LOG_WARNING; - if (s->error_recognition & AV_EF_COMPLIANT) - level = AV_LOG_ERROR; - av_log(s, level, "Discarding ID3 tags because more suitable tags were found.\n"); + av_log(s, AV_LOG_WARNING, "Discarding ID3 tags because more suitable tags were found.\n"); av_dict_free(&s->internal->id3v2_meta); - if (s->error_recognition & AV_EF_EXPLODE) - return AVERROR_INVALIDDATA; } if (id3v2_extra_meta) { if (!strcmp(s->iformat->name, "mp3") || !strcmp(s->iformat->name, "aac") || !strcmp(s->iformat->name, "tta") || !strcmp(s->iformat->name, "wav")) { - if ((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0) - goto fail; - if ((ret = ff_id3v2_parse_chapters(s, &id3v2_extra_meta)) < 0) - goto fail; - if ((ret = ff_id3v2_parse_priv(s, &id3v2_extra_meta)) < 0) - goto fail; + if ((ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0) + goto close; + if ((ret = ff_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0) + goto close; + if ((ret = ff_id3v2_parse_priv(s, id3v2_extra_meta)) < 0) + goto close; } else av_log(s, AV_LOG_DEBUG, "demuxer does not support additional id3 data, skipping\n"); } ff_id3v2_free_extra_meta(&id3v2_extra_meta); if ((ret = avformat_queue_attached_pictures(s)) < 0) - goto fail; + goto close; +#if FF_API_DEMUXER_OPEN if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->pb && !s->internal->data_offset) +#else + if (s->pb && !s->internal->data_offset) +#endif s->internal->data_offset = avio_tell(s->pb); s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; @@ -678,6 +655,9 @@ *ps = s; return 0; +close: + if (s->iformat->read_close) + s->iformat->read_close(s); fail: ff_id3v2_free_extra_meta(&id3v2_extra_meta); av_dict_free(&tmp); @@ -714,8 +694,8 @@ static int probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt) { - if (st->request_probe>0) { - AVProbeData *pd = &st->probe_data; + if (st->internal->request_probe>0) { + AVProbeData *pd = &st->internal->probe_data; int end; av_log(s, AV_LOG_DEBUG, "probing stream %d pp:%d\n", st->index, st->probe_packets); --st->probe_packets; @@ -750,7 +730,7 @@ || end) { pd->buf_size = 0; av_freep(&pd->buf); - st->request_probe = -1; + st->internal->request_probe = -1; if (st->codecpar->codec_id != AV_CODEC_ID_NONE) { av_log(s, AV_LOG_DEBUG, "probed stream %d\n", st->index); } else @@ -771,7 +751,7 @@ if (ref == AV_NOPTS_VALUE) ref = pkt->pts; - if (st->pts_wrap_reference != AV_NOPTS_VALUE || st->pts_wrap_bits >= 63 || ref == AV_NOPTS_VALUE || !s->correct_ts_overflow) + if (st->internal->pts_wrap_reference != AV_NOPTS_VALUE || st->pts_wrap_bits >= 63 || ref == AV_NOPTS_VALUE || !s->correct_ts_overflow) return 0; ref &= (1LL << st->pts_wrap_bits)-1; @@ -786,17 +766,17 @@ if (!first_program) { int default_stream_index = av_find_default_stream_index(s); - if (s->streams[default_stream_index]->pts_wrap_reference == AV_NOPTS_VALUE) { + if (s->streams[default_stream_index]->internal->pts_wrap_reference == AV_NOPTS_VALUE) { for (i = 0; i < s->nb_streams; i++) { if (av_find_program_from_stream(s, NULL, i)) continue; - s->streams[i]->pts_wrap_reference = pts_wrap_reference; - s->streams[i]->pts_wrap_behavior = pts_wrap_behavior; + s->streams[i]->internal->pts_wrap_reference = pts_wrap_reference; + s->streams[i]->internal->pts_wrap_behavior = pts_wrap_behavior; } } else { - st->pts_wrap_reference = s->streams[default_stream_index]->pts_wrap_reference; - st->pts_wrap_behavior = s->streams[default_stream_index]->pts_wrap_behavior; + st->internal->pts_wrap_reference = s->streams[default_stream_index]->internal->pts_wrap_reference; + st->internal->pts_wrap_behavior = s->streams[default_stream_index]->internal->pts_wrap_behavior; } } else { @@ -815,8 +795,8 @@ while (program) { if (program->pts_wrap_reference != pts_wrap_reference) { for (i = 0; inb_stream_indexes; i++) { - s->streams[program->stream_index[i]]->pts_wrap_reference = pts_wrap_reference; - s->streams[program->stream_index[i]]->pts_wrap_behavior = pts_wrap_behavior; + s->streams[program->stream_index[i]]->internal->pts_wrap_reference = pts_wrap_reference; + s->streams[program->stream_index[i]]->internal->pts_wrap_behavior = pts_wrap_behavior; } program->pts_wrap_reference = pts_wrap_reference; @@ -833,28 +813,37 @@ int ret, i, err; AVStream *st; +#if FF_API_INIT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS + pkt->data = NULL; + pkt->size = 0; + av_init_packet(pkt); +FF_ENABLE_DEPRECATION_WARNINGS +#else + av_packet_unref(pkt); +#endif + for (;;) { - AVPacketList *pktl = s->internal->raw_packet_buffer; + PacketList *pktl = s->internal->raw_packet_buffer; + const AVPacket *pkt1; if (pktl) { - *pkt = pktl->pkt; - st = s->streams[pkt->stream_index]; + st = s->streams[pktl->pkt.stream_index]; if (s->internal->raw_packet_buffer_remaining_size <= 0) if ((err = probe_codec(s, st, NULL)) < 0) return err; - if (st->request_probe <= 0) { - s->internal->raw_packet_buffer = pktl->next; + if (st->internal->request_probe <= 0) { + avpriv_packet_list_get(&s->internal->raw_packet_buffer, + &s->internal->raw_packet_buffer_end, pkt); s->internal->raw_packet_buffer_remaining_size += pkt->size; - av_free(pktl); return 0; } } - pkt->data = NULL; - pkt->size = 0; - av_init_packet(pkt); ret = s->iformat->read_packet(s, pkt); if (ret < 0) { + av_packet_unref(pkt); + /* Some demuxers return FFERROR_REDO when they consume data and discard it (ignored streams, junk, extradata). We must re-call the demuxer to get the real packet. */ @@ -864,35 +853,38 @@ return ret; for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; - if (st->probe_packets || st->request_probe > 0) + if (st->probe_packets || st->internal->request_probe > 0) if ((err = probe_codec(s, st, NULL)) < 0) return err; - av_assert0(st->request_probe <= 0); + av_assert0(st->internal->request_probe <= 0); } continue; } err = av_packet_make_refcounted(pkt); - if (err < 0) + if (err < 0) { + av_packet_unref(pkt); return err; + } - if ((s->flags & AVFMT_FLAG_DISCARD_CORRUPT) && - (pkt->flags & AV_PKT_FLAG_CORRUPT)) { + if (pkt->flags & AV_PKT_FLAG_CORRUPT) { av_log(s, AV_LOG_WARNING, - "Dropped corrupted packet (stream = %d)\n", - pkt->stream_index); - av_packet_unref(pkt); - continue; + "Packet corrupt (stream = %d, dts = %s)", + pkt->stream_index, av_ts2str(pkt->dts)); + if (s->flags & AVFMT_FLAG_DISCARD_CORRUPT) { + av_log(s, AV_LOG_WARNING, ", dropping it.\n"); + av_packet_unref(pkt); + continue; + } + av_log(s, AV_LOG_WARNING, ".\n"); } - if (pkt->stream_index >= (unsigned)s->nb_streams) { - av_log(s, AV_LOG_ERROR, "Invalid stream index %d\n", pkt->stream_index); - continue; - } + av_assert0(pkt->stream_index < (unsigned)s->nb_streams && + "Invalid stream index.\n"); st = s->streams[pkt->stream_index]; - if (update_wrap_reference(s, st, pkt->stream_index, pkt) && st->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET) { + if (update_wrap_reference(s, st, pkt->stream_index, pkt) && st->internal->pts_wrap_behavior == AV_PTS_WRAP_SUB_OFFSET) { // correct first time stamps to negative values if (!is_relative(st->first_dts)) st->first_dts = wrap_timestamp(st, st->first_dts); @@ -911,17 +903,20 @@ if (s->use_wallclock_as_timestamps) pkt->dts = pkt->pts = av_rescale_q(av_gettime(), AV_TIME_BASE_Q, st->time_base); - if (!pktl && st->request_probe <= 0) + if (!pktl && st->internal->request_probe <= 0) return ret; - err = ff_packet_list_put(&s->internal->raw_packet_buffer, + err = avpriv_packet_list_put(&s->internal->raw_packet_buffer, &s->internal->raw_packet_buffer_end, - pkt, 0); - if (err) + pkt, NULL, 0); + if (err < 0) { + av_packet_unref(pkt); return err; - s->internal->raw_packet_buffer_remaining_size -= pkt->size; + } + pkt1 = &s->internal->raw_packet_buffer_end->pkt; + s->internal->raw_packet_buffer_remaining_size -= pkt1->size; - if ((err = probe_codec(s, st, pkt)) < 0) + if ((err = probe_codec(s, st, pkt1)) < 0) return err; } } @@ -1008,12 +1003,13 @@ } } -static int is_intra_only(enum AVCodecID id) +int ff_is_intra_only(enum AVCodecID id) { const AVCodecDescriptor *d = avcodec_descriptor_get(id); if (!d) return 0; - if (d->type == AVMEDIA_TYPE_VIDEO && !(d->props & AV_CODEC_PROP_INTRA_ONLY)) + if ((d->type == AVMEDIA_TYPE_VIDEO || d->type == AVMEDIA_TYPE_AUDIO) && + !(d->props & AV_CODEC_PROP_INTRA_ONLY)) return 0; return 1; } @@ -1021,7 +1017,7 @@ static int has_decode_delay_been_guessed(AVStream *st) { if (st->codecpar->codec_id != AV_CODEC_ID_H264) return 1; - if (!st->info) // if we have left find_stream_info then nb_decoded_frames won't increase anymore for stream copy + if (!st->internal->info) // if we have left find_stream_info then nb_decoded_frames won't increase anymore for stream copy return 1; #if CONFIG_H264_DECODER if (st->internal->avctx->has_b_frames && @@ -1029,14 +1025,14 @@ return 1; #endif if (st->internal->avctx->has_b_frames<3) - return st->nb_decoded_frames >= 7; + return st->internal->nb_decoded_frames >= 7; else if (st->internal->avctx->has_b_frames<4) - return st->nb_decoded_frames >= 18; + return st->internal->nb_decoded_frames >= 18; else - return st->nb_decoded_frames >= 20; + return st->internal->nb_decoded_frames >= 20; } -static AVPacketList *get_next_pkt(AVFormatContext *s, AVStream *st, AVPacketList *pktl) +static PacketList *get_next_pkt(AVFormatContext *s, AVStream *st, PacketList *pktl) { if (pktl->next) return pktl->next; @@ -1056,8 +1052,8 @@ if (dts == AV_NOPTS_VALUE) { int64_t best_score = INT64_MAX; for (i = 0; ipts_reorder_error_count[i]) { - int64_t score = st->pts_reorder_error[i] / st->pts_reorder_error_count[i]; + if (st->internal->pts_reorder_error_count[i]) { + int64_t score = st->internal->pts_reorder_error[i] / st->internal->pts_reorder_error_count[i]; if (score < best_score) { best_score = score; dts = pts_buffer[i]; @@ -1068,13 +1064,13 @@ for (i = 0; ipts_reorder_error[i]; - diff = FFMAX(diff, st->pts_reorder_error[i]); - st->pts_reorder_error[i] = diff; - st->pts_reorder_error_count[i]++; - if (st->pts_reorder_error_count[i] > 250) { - st->pts_reorder_error[i] >>= 1; - st->pts_reorder_error_count[i] >>= 1; + + (uint64_t)st->internal->pts_reorder_error[i]; + diff = FFMAX(diff, st->internal->pts_reorder_error[i]); + st->internal->pts_reorder_error[i] = diff; + st->internal->pts_reorder_error_count[i]++; + if (st->internal->pts_reorder_error_count[i] > 250) { + st->internal->pts_reorder_error[i] >>= 1; + st->internal->pts_reorder_error_count[i] >>= 1; } } } @@ -1092,7 +1088,7 @@ * of the packets in a window. */ static void update_dts_from_pts(AVFormatContext *s, int stream_index, - AVPacketList *pkt_buffer) + PacketList *pkt_buffer) { AVStream *st = s->streams[stream_index]; int delay = st->internal->avctx->has_b_frames; @@ -1121,8 +1117,8 @@ int64_t dts, int64_t pts, AVPacket *pkt) { AVStream *st = s->streams[stream_index]; - AVPacketList *pktl = s->internal->packet_buffer ? s->internal->packet_buffer : s->internal->parse_queue; - AVPacketList *pktl_it; + PacketList *pktl = s->internal->packet_buffer ? s->internal->packet_buffer : s->internal->parse_queue; + PacketList *pktl_it; uint64_t shift; @@ -1130,6 +1126,7 @@ dts == AV_NOPTS_VALUE || st->cur_dts == AV_NOPTS_VALUE || st->cur_dts < INT_MIN + RELATIVE_TS_BASE || + dts < INT_MIN + (st->cur_dts - RELATIVE_TS_BASE) || is_relative(dts)) return; @@ -1152,7 +1149,7 @@ if (st->start_time == AV_NOPTS_VALUE && pktl_it->pkt.pts != AV_NOPTS_VALUE) { st->start_time = pktl_it->pkt.pts; if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate) - st->start_time += av_rescale_q(st->skip_samples, (AVRational){1, st->codecpar->sample_rate}, st->time_base); + st->start_time = av_sat_add64(st->start_time, av_rescale_q(st->internal->skip_samples, (AVRational){1, st->codecpar->sample_rate}, st->time_base)); } } @@ -1165,20 +1162,20 @@ st->start_time = pts; } if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate) - st->start_time += av_rescale_q(st->skip_samples, (AVRational){1, st->codecpar->sample_rate}, st->time_base); + st->start_time = av_sat_add64(st->start_time, av_rescale_q(st->internal->skip_samples, (AVRational){1, st->codecpar->sample_rate}, st->time_base)); } } static void update_initial_durations(AVFormatContext *s, AVStream *st, - int stream_index, int duration) + int stream_index, int64_t duration) { - AVPacketList *pktl = s->internal->packet_buffer ? s->internal->packet_buffer : s->internal->parse_queue; + PacketList *pktl = s->internal->packet_buffer ? s->internal->packet_buffer : s->internal->parse_queue; int64_t cur_dts = RELATIVE_TS_BASE; if (st->first_dts != AV_NOPTS_VALUE) { - if (st->update_initial_durations_done) + if (st->internal->update_initial_durations_done) return; - st->update_initial_durations_done = 1; + st->internal->update_initial_durations_done = 1; cur_dts = st->first_dts; for (; pktl; pktl = get_next_pkt(s, st, pktl)) { if (pktl->pkt.stream_index == stream_index) { @@ -1215,8 +1212,7 @@ pktl->pkt.dts = cur_dts; if (!st->internal->avctx->has_b_frames) pktl->pkt.pts = cur_dts; -// if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) - pktl->pkt.duration = duration; + pktl->pkt.duration = duration; } else break; cur_dts = pktl->pkt.dts + pktl->pkt.duration; @@ -1239,24 +1235,24 @@ return; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && pkt->dts != AV_NOPTS_VALUE) { - if (pkt->dts == pkt->pts && st->last_dts_for_order_check != AV_NOPTS_VALUE) { - if (st->last_dts_for_order_check <= pkt->dts) { - st->dts_ordered++; + if (pkt->dts == pkt->pts && st->internal->last_dts_for_order_check != AV_NOPTS_VALUE) { + if (st->internal->last_dts_for_order_check <= pkt->dts) { + st->internal->dts_ordered++; } else { - av_log(s, st->dts_misordered ? AV_LOG_DEBUG : AV_LOG_WARNING, + av_log(s, st->internal->dts_misordered ? AV_LOG_DEBUG : AV_LOG_WARNING, "DTS %"PRIi64" < %"PRIi64" out of order\n", pkt->dts, - st->last_dts_for_order_check); - st->dts_misordered++; + st->internal->last_dts_for_order_check); + st->internal->dts_misordered++; } - if (st->dts_ordered + st->dts_misordered > 250) { - st->dts_ordered >>= 1; - st->dts_misordered >>= 1; + if (st->internal->dts_ordered + st->internal->dts_misordered > 250) { + st->internal->dts_ordered >>= 1; + st->internal->dts_misordered >>= 1; } } - st->last_dts_for_order_check = pkt->dts; - if (st->dts_ordered < 8*st->dts_misordered && pkt->dts == pkt->pts) + st->internal->last_dts_for_order_check = pkt->dts; + if (st->internal->dts_ordered < 8*st->internal->dts_misordered && pkt->dts == pkt->pts) pkt->dts = AV_NOPTS_VALUE; } @@ -1279,7 +1275,7 @@ presentation_delayed = 1; if (pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && - st->pts_wrap_bits < 63 && + st->pts_wrap_bits < 63 && pkt->dts > INT64_MIN + (1LL << st->pts_wrap_bits) && pkt->dts - (1LL << (st->pts_wrap_bits - 1)) > pkt->pts) { if (is_relative(st->cur_dts) || pkt->dts - (1LL<<(st->pts_wrap_bits - 1)) > st->cur_dts) { pkt->dts -= 1LL << st->pts_wrap_bits; @@ -1300,7 +1296,7 @@ } duration = av_mul_q((AVRational) {pkt->duration, 1}, st->time_base); - if (pkt->duration == 0) { + if (pkt->duration <= 0) { ff_compute_frame_duration(s, &num, &den, st, pc, pkt); if (den && num) { duration = (AVRational) {num, den}; @@ -1311,7 +1307,7 @@ } } - if (pkt->duration != 0 && (s->internal->packet_buffer || s->internal->parse_queue)) + if (pkt->duration > 0 && (s->internal->packet_buffer || s->internal->parse_queue)) update_initial_durations(s, st, pkt->stream_index, pkt->duration); /* Correct timestamps with byte offset if demuxers only have timestamps @@ -1355,7 +1351,7 @@ if (st->last_IP_duration == 0 && (uint64_t)pkt->duration <= INT32_MAX) st->last_IP_duration = pkt->duration; if (pkt->dts != AV_NOPTS_VALUE) - st->cur_dts = pkt->dts + st->last_IP_duration; + st->cur_dts = av_sat_add64(pkt->dts, st->last_IP_duration); if (pkt->dts != AV_NOPTS_VALUE && pkt->pts == AV_NOPTS_VALUE && st->last_IP_duration > 0 && @@ -1371,7 +1367,7 @@ * by knowing the future. */ } else if (pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || - pkt->duration ) { + pkt->duration > 0 ) { /* presentation is not delayed : PTS and DTS are the same */ if (pkt->pts == AV_NOPTS_VALUE) @@ -1381,18 +1377,18 @@ if (pkt->pts == AV_NOPTS_VALUE) pkt->pts = st->cur_dts; pkt->dts = pkt->pts; - if (pkt->pts != AV_NOPTS_VALUE) + if (pkt->pts != AV_NOPTS_VALUE && duration.num >= 0) st->cur_dts = av_add_stable(st->time_base, pkt->pts, duration, 1); } } if (pkt->pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY) { - st->pts_buffer[0] = pkt->pts; - for (i = 0; ipts_buffer[i] > st->pts_buffer[i + 1]; i++) - FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i + 1]); + st->internal->pts_buffer[0] = pkt->pts; + for (i = 0; iinternal->pts_buffer[i] > st->internal->pts_buffer[i + 1]; i++) + FFSWAP(int64_t, st->internal->pts_buffer[i], st->internal->pts_buffer[i + 1]); if(has_decode_delay_been_guessed(st)) - pkt->dts = select_from_pts_buffer(st, st->pts_buffer, pkt->dts); + pkt->dts = select_from_pts_buffer(st, st->internal->pts_buffer, pkt->dts); } // We skipped it above so we try here. if (!onein_oneout) @@ -1406,7 +1402,7 @@ presentation_delayed, delay, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts), st->index, st->id); /* update flags */ - if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA || is_intra_only(st->codecpar->codec_id)) + if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA || ff_is_intra_only(st->codecpar->codec_id)) pkt->flags |= AV_PKT_FLAG_KEY; #if FF_API_CONVERGENCE_DURATION FF_DISABLE_DEPRECATION_WARNINGS @@ -1416,91 +1412,77 @@ #endif } -void ff_packet_list_free(AVPacketList **pkt_buf, AVPacketList **pkt_buf_end) -{ - AVPacketList *tmp = *pkt_buf; - - while (tmp) { - AVPacketList *pktl = tmp; - tmp = pktl->next; - av_packet_unref(&pktl->pkt); - av_freep(&pktl); - } - *pkt_buf = NULL; - *pkt_buf_end = NULL; -} - /** * Parse a packet, add all split parts to parse_queue. * - * @param pkt Packet to parse, NULL when flushing the parser at end of stream. + * @param pkt Packet to parse; must not be NULL. + * @param flush Indicates whether to flush. If set, pkt must be blank. */ -static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) +static int parse_packet(AVFormatContext *s, AVPacket *pkt, + int stream_index, int flush) { - AVPacket out_pkt = { 0 }, flush_pkt = { 0 }; + AVPacket *out_pkt = s->internal->parse_pkt; AVStream *st = s->streams[stream_index]; - uint8_t *data = pkt ? pkt->data : NULL; - int size = pkt ? pkt->size : 0; - int ret = 0, got_output = 0; - - if (!pkt) { - av_init_packet(&flush_pkt); - pkt = &flush_pkt; - got_output = 1; - } else if (!size && st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES) { + uint8_t *data = pkt->data; + int size = pkt->size; + int ret = 0, got_output = flush; + + if (size || flush) { + av_packet_unref(out_pkt); + } else if (st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES) { // preserve 0-size sync packets compute_pkt_fields(s, st, st->parser, pkt, AV_NOPTS_VALUE, AV_NOPTS_VALUE); } - while (size > 0 || (pkt == &flush_pkt && got_output)) { + while (size > 0 || (flush && got_output)) { int len; int64_t next_pts = pkt->pts; int64_t next_dts = pkt->dts; - av_init_packet(&out_pkt); len = av_parser_parse2(st->parser, st->internal->avctx, - &out_pkt.data, &out_pkt.size, data, size, + &out_pkt->data, &out_pkt->size, data, size, pkt->pts, pkt->dts, pkt->pos); pkt->pts = pkt->dts = AV_NOPTS_VALUE; pkt->pos = -1; /* increment read pointer */ - data += len; + av_assert1(data || !len); + data = len ? data + len : data; size -= len; - got_output = !!out_pkt.size; + got_output = !!out_pkt->size; - if (!out_pkt.size) + if (!out_pkt->size) continue; - if (pkt->buf && out_pkt.data == pkt->data) { - /* reference pkt->buf only when out_pkt.data is guaranteed to point + if (pkt->buf && out_pkt->data == pkt->data) { + /* reference pkt->buf only when out_pkt->data is guaranteed to point * to data in it and not in the parser's internal buffer. */ /* XXX: Ensure this is the case with all parsers when st->parser->flags * is PARSER_FLAG_COMPLETE_FRAMES and check for that instead? */ - out_pkt.buf = av_buffer_ref(pkt->buf); - if (!out_pkt.buf) { + out_pkt->buf = av_buffer_ref(pkt->buf); + if (!out_pkt->buf) { ret = AVERROR(ENOMEM); goto fail; } } else { - ret = av_packet_make_refcounted(&out_pkt); + ret = av_packet_make_refcounted(out_pkt); if (ret < 0) goto fail; } if (pkt->side_data) { - out_pkt.side_data = pkt->side_data; - out_pkt.side_data_elems = pkt->side_data_elems; + out_pkt->side_data = pkt->side_data; + out_pkt->side_data_elems = pkt->side_data_elems; pkt->side_data = NULL; pkt->side_data_elems = 0; } /* set the duration */ - out_pkt.duration = (st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES) ? pkt->duration : 0; + out_pkt->duration = (st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES) ? pkt->duration : 0; if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { if (st->internal->avctx->sample_rate > 0) { - out_pkt.duration = + out_pkt->duration = av_rescale_q_rnd(st->parser->duration, (AVRational) { 1, st->internal->avctx->sample_rate }, st->time_base, @@ -1508,36 +1490,36 @@ } } - out_pkt.stream_index = st->index; - out_pkt.pts = st->parser->pts; - out_pkt.dts = st->parser->dts; - out_pkt.pos = st->parser->pos; - out_pkt.flags |= pkt->flags & AV_PKT_FLAG_DISCARD; + out_pkt->stream_index = st->index; + out_pkt->pts = st->parser->pts; + out_pkt->dts = st->parser->dts; + out_pkt->pos = st->parser->pos; + out_pkt->flags |= pkt->flags & AV_PKT_FLAG_DISCARD; if (st->need_parsing == AVSTREAM_PARSE_FULL_RAW) - out_pkt.pos = st->parser->frame_offset; + out_pkt->pos = st->parser->frame_offset; if (st->parser->key_frame == 1 || (st->parser->key_frame == -1 && st->parser->pict_type == AV_PICTURE_TYPE_I)) - out_pkt.flags |= AV_PKT_FLAG_KEY; + out_pkt->flags |= AV_PKT_FLAG_KEY; if (st->parser->key_frame == -1 && st->parser->pict_type ==AV_PICTURE_TYPE_NONE && (pkt->flags&AV_PKT_FLAG_KEY)) - out_pkt.flags |= AV_PKT_FLAG_KEY; + out_pkt->flags |= AV_PKT_FLAG_KEY; - compute_pkt_fields(s, st, st->parser, &out_pkt, next_dts, next_pts); + compute_pkt_fields(s, st, st->parser, out_pkt, next_dts, next_pts); - ret = ff_packet_list_put(&s->internal->parse_queue, + ret = avpriv_packet_list_put(&s->internal->parse_queue, &s->internal->parse_queue_end, - &out_pkt, 0); + out_pkt, NULL, 0); if (ret < 0) { - av_packet_unref(&out_pkt); + av_packet_unref(out_pkt); goto fail; } } /* end of the stream => close and free the parser */ - if (pkt == &flush_pkt) { + if (flush) { av_parser_close(st->parser); st->parser = NULL; } @@ -1547,21 +1529,6 @@ return ret; } -int ff_packet_list_get(AVPacketList **pkt_buffer, - AVPacketList **pkt_buffer_end, - AVPacket *pkt) -{ - AVPacketList *pktl; - av_assert0(*pkt_buffer); - pktl = *pkt_buffer; - *pkt = pktl->pkt; - *pkt_buffer = pktl->next; - if (!pktl->next) - *pkt_buffer_end = NULL; - av_freep(&pktl); - return 0; -} - static int64_t ts_to_samples(AVStream *st, int64_t ts) { return av_rescale(ts, st->time_base.num * st->codecpar->sample_rate, st->time_base.den); @@ -1569,17 +1536,14 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) { - int ret = 0, i, got_packet = 0; + int ret, i, got_packet = 0; AVDictionary *metadata = NULL; - av_init_packet(pkt); - while (!got_packet && !s->internal->parse_queue) { AVStream *st; - AVPacket cur_pkt; /* read next packet */ - ret = ff_read_packet(s, &cur_pkt); + ret = ff_read_packet(s, pkt); if (ret < 0) { if (ret == AVERROR(EAGAIN)) return ret; @@ -1587,21 +1551,23 @@ for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; if (st->parser && st->need_parsing) - parse_packet(s, NULL, st->index); + parse_packet(s, pkt, st->index, 1); } /* all remaining packets are now in parse_queue => * really terminate parsing */ break; } ret = 0; - st = s->streams[cur_pkt.stream_index]; + st = s->streams[pkt->stream_index]; + + st->event_flags |= AVSTREAM_EVENT_FLAG_NEW_PACKETS; /* update context if required */ if (st->internal->need_context_update) { if (avcodec_is_open(st->internal->avctx)) { av_log(s, AV_LOG_DEBUG, "Demuxer context update while decoder is open, closing and trying to re-open\n"); avcodec_close(st->internal->avctx); - st->info->found_decoder = 0; + st->internal->info->found_decoder = 0; } /* close parser, because it depends on the codec */ @@ -1611,38 +1577,42 @@ } ret = avcodec_parameters_to_context(st->internal->avctx, st->codecpar); - if (ret < 0) + if (ret < 0) { + av_packet_unref(pkt); return ret; + } #if FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS /* update deprecated public codec context */ ret = avcodec_parameters_to_context(st->codec, st->codecpar); - if (ret < 0) + if (ret < 0) { + av_packet_unref(pkt); return ret; + } FF_ENABLE_DEPRECATION_WARNINGS #endif st->internal->need_context_update = 0; } - if (cur_pkt.pts != AV_NOPTS_VALUE && - cur_pkt.dts != AV_NOPTS_VALUE && - cur_pkt.pts < cur_pkt.dts) { + if (pkt->pts != AV_NOPTS_VALUE && + pkt->dts != AV_NOPTS_VALUE && + pkt->pts < pkt->dts) { av_log(s, AV_LOG_WARNING, "Invalid timestamps stream=%d, pts=%s, dts=%s, size=%d\n", - cur_pkt.stream_index, - av_ts2str(cur_pkt.pts), - av_ts2str(cur_pkt.dts), - cur_pkt.size); + pkt->stream_index, + av_ts2str(pkt->pts), + av_ts2str(pkt->dts), + pkt->size); } if (s->debug & FF_FDEBUG_TS) av_log(s, AV_LOG_DEBUG, "ff_read_packet stream=%d, pts=%s, dts=%s, size=%d, duration=%"PRId64", flags=%d\n", - cur_pkt.stream_index, - av_ts2str(cur_pkt.pts), - av_ts2str(cur_pkt.dts), - cur_pkt.size, cur_pkt.duration, cur_pkt.flags); + pkt->stream_index, + av_ts2str(pkt->pts), + av_ts2str(pkt->dts), + pkt->size, pkt->duration, pkt->flags); if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)) { st->parser = av_parser_init(st->codecpar->codec_id); @@ -1662,7 +1632,6 @@ if (!st->need_parsing || !st->parser) { /* no parsing needed: we just output the packet as is */ - *pkt = cur_pkt; compute_pkt_fields(s, st, NULL, pkt, AV_NOPTS_VALUE, AV_NOPTS_VALUE); if ((s->iformat->flags & AVFMT_GENERIC_INDEX) && (pkt->flags & AV_PKT_FLAG_KEY) && pkt->dts != AV_NOPTS_VALUE) { @@ -1672,7 +1641,7 @@ } got_packet = 1; } else if (st->discard < AVDISCARD_ALL) { - if ((ret = parse_packet(s, &cur_pkt, cur_pkt.stream_index)) < 0) + if ((ret = parse_packet(s, pkt, pkt->stream_index, 0)) < 0) return ret; st->codecpar->sample_rate = st->internal->avctx->sample_rate; st->codecpar->bit_rate = st->internal->avctx->bit_rate; @@ -1681,47 +1650,44 @@ st->codecpar->codec_id = st->internal->avctx->codec_id; } else { /* free packet */ - av_packet_unref(&cur_pkt); + av_packet_unref(pkt); } if (pkt->flags & AV_PKT_FLAG_KEY) - st->skip_to_keyframe = 0; - if (st->skip_to_keyframe) { - av_packet_unref(&cur_pkt); - if (got_packet) { - *pkt = cur_pkt; - } + st->internal->skip_to_keyframe = 0; + if (st->internal->skip_to_keyframe) { + av_packet_unref(pkt); got_packet = 0; } } if (!got_packet && s->internal->parse_queue) - ret = ff_packet_list_get(&s->internal->parse_queue, &s->internal->parse_queue_end, pkt); + ret = avpriv_packet_list_get(&s->internal->parse_queue, &s->internal->parse_queue_end, pkt); if (ret >= 0) { AVStream *st = s->streams[pkt->stream_index]; int discard_padding = 0; - if (st->first_discard_sample && pkt->pts != AV_NOPTS_VALUE) { + if (st->internal->first_discard_sample && pkt->pts != AV_NOPTS_VALUE) { int64_t pts = pkt->pts - (is_relative(pkt->pts) ? RELATIVE_TS_BASE : 0); int64_t sample = ts_to_samples(st, pts); int duration = ts_to_samples(st, pkt->duration); int64_t end_sample = sample + duration; - if (duration > 0 && end_sample >= st->first_discard_sample && - sample < st->last_discard_sample) - discard_padding = FFMIN(end_sample - st->first_discard_sample, duration); - } - if (st->start_skip_samples && (pkt->pts == 0 || pkt->pts == RELATIVE_TS_BASE)) - st->skip_samples = st->start_skip_samples; - if (st->skip_samples || discard_padding) { + if (duration > 0 && end_sample >= st->internal->first_discard_sample && + sample < st->internal->last_discard_sample) + discard_padding = FFMIN(end_sample - st->internal->first_discard_sample, duration); + } + if (st->internal->start_skip_samples && (pkt->pts == 0 || pkt->pts == RELATIVE_TS_BASE)) + st->internal->skip_samples = st->internal->start_skip_samples; + if (st->internal->skip_samples || discard_padding) { uint8_t *p = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10); if (p) { - AV_WL32(p, st->skip_samples); + AV_WL32(p, st->internal->skip_samples); AV_WL32(p + 4, discard_padding); - av_log(s, AV_LOG_DEBUG, "demuxer injecting skip %d / discard %d\n", st->skip_samples, discard_padding); + av_log(s, AV_LOG_DEBUG, "demuxer injecting skip %d / discard %d\n", st->internal->skip_samples, discard_padding); } - st->skip_samples = 0; + st->internal->skip_samples = 0; } - if (st->inject_global_side_data) { + if (st->internal->inject_global_side_data) { for (i = 0; i < st->nb_side_data; i++) { AVPacketSideData *src_sd = &st->side_data[i]; uint8_t *dst_data; @@ -1737,7 +1703,7 @@ memcpy(dst_data, src_sd->data, src_sd->size); } - st->inject_global_side_data = 0; + st->internal->inject_global_side_data = 0; } } @@ -1762,6 +1728,11 @@ av_ts2str(pkt->dts), pkt->size, pkt->duration, pkt->flags); + /* A demuxer might have returned EOF because of an IO error, let's + * propagate this back to the user. */ + if (ret == AVERROR_EOF && s->pb && s->pb->error < 0 && s->pb->error != AVERROR(EAGAIN)) + ret = s->pb->error; + return ret; } @@ -1774,7 +1745,7 @@ if (!genpts) { ret = s->internal->packet_buffer - ? ff_packet_list_get(&s->internal->packet_buffer, + ? avpriv_packet_list_get(&s->internal->packet_buffer, &s->internal->packet_buffer_end, pkt) : read_frame_internal(s, pkt); if (ret < 0) @@ -1783,7 +1754,7 @@ } for (;;) { - AVPacketList *pktl = s->internal->packet_buffer; + PacketList *pktl = s->internal->packet_buffer; if (pktl) { AVPacket *next_pkt = &pktl->pkt; @@ -1823,7 +1794,7 @@ 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 = ff_packet_list_get(&s->internal->packet_buffer, + ret = avpriv_packet_list_get(&s->internal->packet_buffer, &s->internal->packet_buffer_end, pkt); goto return_packet; } @@ -1838,12 +1809,13 @@ return ret; } - ret = ff_packet_list_put(&s->internal->packet_buffer, + ret = avpriv_packet_list_put(&s->internal->packet_buffer, &s->internal->packet_buffer_end, - pkt, FF_PACKETLIST_FLAG_REF_PACKET); - av_packet_unref(pkt); - if (ret < 0) + pkt, NULL, 0); + if (ret < 0) { + av_packet_unref(pkt); return ret; + } } return_packet: @@ -1867,9 +1839,9 @@ { if (!s->internal) return; - ff_packet_list_free(&s->internal->parse_queue, &s->internal->parse_queue_end); - ff_packet_list_free(&s->internal->packet_buffer, &s->internal->packet_buffer_end); - ff_packet_list_free(&s->internal->raw_packet_buffer, &s->internal->raw_packet_buffer_end); + avpriv_packet_list_free(&s->internal->parse_queue, &s->internal->parse_queue_end); + avpriv_packet_list_free(&s->internal->packet_buffer, &s->internal->packet_buffer_end); + avpriv_packet_list_free(&s->internal->raw_packet_buffer, &s->internal->raw_packet_buffer_end); s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; } @@ -1931,22 +1903,22 @@ st->parser = NULL; } st->last_IP_pts = AV_NOPTS_VALUE; - st->last_dts_for_order_check = AV_NOPTS_VALUE; + st->internal->last_dts_for_order_check = AV_NOPTS_VALUE; if (st->first_dts == AV_NOPTS_VALUE) st->cur_dts = RELATIVE_TS_BASE; else /* We set the current DTS to an unspecified origin. */ st->cur_dts = AV_NOPTS_VALUE; - st->probe_packets = MAX_PROBE_PACKETS; + st->probe_packets = s->max_probe_packets; for (j = 0; j < MAX_REORDER_DELAY + 1; j++) - st->pts_buffer[j] = AV_NOPTS_VALUE; + st->internal->pts_buffer[j] = AV_NOPTS_VALUE; if (s->internal->inject_global_side_data) - st->inject_global_side_data = 1; + st->internal->inject_global_side_data = 1; - st->skip_samples = 0; + st->internal->skip_samples = 0; } } @@ -2096,6 +2068,8 @@ //We could use URLProtocol flags here but as many user applications do not use URLProtocols this would be unreliable const char *proto = avio_find_protocol_name(s->url); + av_assert0(time_tolerance >= 0); + if (!proto) { av_log(s, AV_LOG_INFO, "Protocol name not provided, cannot determine if input is local or " @@ -2123,7 +2097,7 @@ for (; i2 < st2->nb_index_entries; i2++) { AVIndexEntry *e2 = &st2->index_entries[i2]; int64_t e2_pts = av_rescale_q(e2->timestamp, st2->time_base, AV_TIME_BASE_Q); - if (e2_pts - e1_pts < time_tolerance) + if (e2_pts < e1_pts || e2_pts - (uint64_t)e1_pts < time_tolerance) continue; pos_delta = FFMAX(pos_delta, e1->pos - e2->pos); break; @@ -2136,7 +2110,13 @@ /* XXX This could be adjusted depending on protocol*/ if (s->pb->buffer_size < pos_delta && pos_delta < (1<<24)) { av_log(s, AV_LOG_VERBOSE, "Reconfiguring buffers to size %"PRId64"\n", pos_delta); - ffio_set_buf_size(s->pb, pos_delta); + + /* realloc the buffer and the original data will be retained */ + if (ffio_realloc_buf(s->pb, pos_delta)) { + av_log(s, AV_LOG_ERROR, "Realloc buffer fail.\n"); + return; + } + s->pb->short_seek_threshold = FFMAX(s->pb->short_seek_threshold, pos_delta/2); } @@ -2409,7 +2389,7 @@ return -1; if (index < 0 || index == st->nb_index_entries - 1) { - AVPacket pkt; + AVPacket *pkt = s->internal->pkt; int nonkey = 0; if (st->nb_index_entries) { @@ -2422,25 +2402,26 @@ if ((ret = avio_seek(s->pb, s->internal->data_offset, SEEK_SET)) < 0) return ret; } + av_packet_unref(pkt); for (;;) { int read_status; do { - read_status = av_read_frame(s, &pkt); + read_status = av_read_frame(s, pkt); } while (read_status == AVERROR(EAGAIN)); if (read_status < 0) break; - if (stream_index == pkt.stream_index && pkt.dts > timestamp) { - if (pkt.flags & AV_PKT_FLAG_KEY) { - av_packet_unref(&pkt); + if (stream_index == pkt->stream_index && pkt->dts > timestamp) { + if (pkt->flags & AV_PKT_FLAG_KEY) { + av_packet_unref(pkt); break; } if (nonkey++ > 1000 && st->codecpar->codec_id != AV_CODEC_ID_CDGRAPHICS) { av_log(s, AV_LOG_ERROR,"seek_frame_generic failed as this stream seems to contain no keyframes after the target timestamp, %d non keyframes found\n", nonkey); - av_packet_unref(&pkt); + av_packet_unref(pkt); break; } } - av_packet_unref(&pkt); + av_packet_unref(pkt); } index = av_index_search_timestamp(st, timestamp, flags); } @@ -2768,7 +2749,7 @@ st = ic->streams[i]; if ( st->time_base.num <= INT64_MAX / ic->bit_rate && st->duration == AV_NOPTS_VALUE) { - duration = av_rescale(8 * filesize, st->time_base.den, + duration = av_rescale(filesize, 8LL * st->time_base.den, ic->bit_rate * (int64_t) st->time_base.num); st->duration = duration; @@ -2788,7 +2769,7 @@ /* only usable for MPEG-PS streams */ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) { - AVPacket pkt1, *pkt = &pkt1; + AVPacket *pkt = ic->internal->pkt; AVStream *st; int num, den, read_size, i, ret; int found_duration = 0; @@ -2860,10 +2841,10 @@ else duration -= st->first_dts; if (duration > 0) { - if (st->duration == AV_NOPTS_VALUE || st->info->last_duration<= 0 || - (st->duration < duration && FFABS(duration - st->info->last_duration) < 60LL*st->time_base.den / st->time_base.num)) + if (st->duration == AV_NOPTS_VALUE || st->internal->info->last_duration<= 0 || + (st->duration < duration && FFABS(duration - st->internal->info->last_duration) < 60LL*st->time_base.den / st->time_base.num)) st->duration = duration; - st->info->last_duration = duration; + st->internal->info->last_duration = duration; } } av_packet_unref(pkt); @@ -2896,9 +2877,9 @@ case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_AUDIO: if (st->start_time != AV_NOPTS_VALUE || st->first_dts != AV_NOPTS_VALUE) { - av_log(ic, AV_LOG_DEBUG, "stream %d : no PTS found at end of file, duration not set\n", i); + av_log(ic, AV_LOG_WARNING, "stream %d : no PTS found at end of file, duration not set\n", i); } else - av_log(ic, AV_LOG_DEBUG, "stream %d : no TS found at start of file, duration not set\n", i); + av_log(ic, AV_LOG_WARNING, "stream %d : no TS found at start of file, duration not set\n", i); } } } @@ -2912,12 +2893,24 @@ st = ic->streams[i]; st->cur_dts = st->first_dts; st->last_IP_pts = AV_NOPTS_VALUE; - st->last_dts_for_order_check = AV_NOPTS_VALUE; + st->internal->last_dts_for_order_check = AV_NOPTS_VALUE; for (j = 0; j < MAX_REORDER_DELAY + 1; j++) - st->pts_buffer[j] = AV_NOPTS_VALUE; + st->internal->pts_buffer[j] = AV_NOPTS_VALUE; } } +/* 1:1 map to AVDurationEstimationMethod */ +static const char *const duration_name[] = { + [AVFMT_DURATION_FROM_PTS] = "pts", + [AVFMT_DURATION_FROM_STREAM] = "stream", + [AVFMT_DURATION_FROM_BITRATE] = "bit rate", +}; + +static const char *duration_estimate_name(enum AVDurationEstimationMethod method) +{ + return duration_name[method]; +} + static void estimate_timings(AVFormatContext *ic, int64_t old_offset) { int64_t file_size; @@ -2940,7 +2933,11 @@ /* at least one component has timings - we use them for all * the components */ fill_all_stream_timings(ic); - ic->duration_estimation_method = AVFMT_DURATION_FROM_STREAM; + /* nut demuxer estimate the duration from PTS */ + if(!strcmp(ic->iformat->name, "nut")) + ic->duration_estimation_method = AVFMT_DURATION_FROM_PTS; + else + ic->duration_estimation_method = AVFMT_DURATION_FROM_STREAM; } else { /* less precise: use bitrate info */ estimate_timings_from_bit_rate(ic); @@ -2954,15 +2951,16 @@ for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; if (st->time_base.den) - av_log(ic, AV_LOG_TRACE, "stream %d: start_time: %0.3f duration: %0.3f\n", i, - (double) st->start_time * av_q2d(st->time_base), - (double) st->duration * av_q2d(st->time_base)); + av_log(ic, AV_LOG_TRACE, "stream %d: start_time: %s duration: %s\n", i, + av_ts2timestr(st->start_time, &st->time_base), + av_ts2timestr(st->duration, &st->time_base)); } av_log(ic, AV_LOG_TRACE, - "format: start_time: %0.3f duration: %0.3f bitrate=%"PRId64" kb/s\n", - (double) ic->start_time / AV_TIME_BASE, - (double) ic->duration / AV_TIME_BASE, - (int64_t)ic->bit_rate / 1000); + "format: start_time: %s duration: %s (estimate from %s) bitrate=%"PRId64" kb/s\n", + av_ts2timestr(ic->start_time, &AV_TIME_BASE_Q), + av_ts2timestr(ic->duration, &AV_TIME_BASE_Q), + duration_estimate_name(ic->duration_estimation_method), + (int64_t)ic->bit_rate / 1000); } } @@ -2983,20 +2981,20 @@ case AVMEDIA_TYPE_AUDIO: if (!avctx->frame_size && determinable_frame_size(avctx)) FAIL("unspecified frame size"); - if (st->info->found_decoder >= 0 && + if (st->internal->info->found_decoder >= 0 && avctx->sample_fmt == AV_SAMPLE_FMT_NONE) FAIL("unspecified sample format"); if (!avctx->sample_rate) FAIL("unspecified sample rate"); if (!avctx->channels) FAIL("unspecified number of channels"); - if (st->info->found_decoder >= 0 && !st->nb_decoded_frames && avctx->codec_id == AV_CODEC_ID_DTS) + if (st->internal->info->found_decoder >= 0 && !st->internal->nb_decoded_frames && avctx->codec_id == AV_CODEC_ID_DTS) FAIL("no decodable DTS frames"); break; case AVMEDIA_TYPE_VIDEO: if (!avctx->width) FAIL("unspecified size"); - if (st->info->found_decoder >= 0 && avctx->pix_fmt == AV_PIX_FMT_NONE) + if (st->internal->info->found_decoder >= 0 && avctx->pix_fmt == AV_PIX_FMT_NONE) FAIL("unspecified pixel format"); if (st->codecpar->codec_id == AV_CODEC_ID_RV30 || st->codecpar->codec_id == AV_CODEC_ID_RV40) if (!st->sample_aspect_ratio.num && !st->codecpar->sample_aspect_ratio.num && !st->codec_info_nb_frames) @@ -3014,8 +3012,8 @@ } /* returns 1 or 0 if or if not decoded data was returned, or a negative error */ -static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt, - AVDictionary **options) +static int try_decode_frame(AVFormatContext *s, AVStream *st, + const AVPacket *avpkt, AVDictionary **options) { AVCodecContext *avctx = st->internal->avctx; const AVCodec *codec; @@ -3030,14 +3028,14 @@ return AVERROR(ENOMEM); if (!avcodec_is_open(avctx) && - st->info->found_decoder <= 0 && - (st->codecpar->codec_id != -st->info->found_decoder || !st->codecpar->codec_id)) { + st->internal->info->found_decoder <= 0 && + (st->codecpar->codec_id != -st->internal->info->found_decoder || !st->codecpar->codec_id)) { AVDictionary *thread_opt = NULL; codec = find_probe_decoder(s, st, st->codecpar->codec_id); if (!codec) { - st->info->found_decoder = -st->codecpar->codec_id; + st->internal->info->found_decoder = -st->codecpar->codec_id; ret = -1; goto fail; } @@ -3045,20 +3043,24 @@ /* Force thread count to 1 since the H.264 decoder will not extract * SPS and PPS to extradata during multi-threaded decoding. */ av_dict_set(options ? options : &thread_opt, "threads", "1", 0); + /* Force lowres to 0. The decoder might reduce the video size by the + * lowres factor, and we don't want that propagated to the stream's + * codecpar */ + av_dict_set(options ? options : &thread_opt, "lowres", "0", 0); if (s->codec_whitelist) av_dict_set(options ? options : &thread_opt, "codec_whitelist", s->codec_whitelist, 0); ret = avcodec_open2(avctx, codec, options ? options : &thread_opt); if (!options) av_dict_free(&thread_opt); if (ret < 0) { - st->info->found_decoder = -avctx->codec_id; + st->internal->info->found_decoder = -avctx->codec_id; goto fail; } - st->info->found_decoder = 1; - } else if (!st->info->found_decoder) - st->info->found_decoder = 1; + st->internal->info->found_decoder = 1; + } else if (!st->internal->info->found_decoder) + st->internal->info->found_decoder = 1; - if (st->info->found_decoder < 0) { + if (st->internal->info->found_decoder < 0) { ret = -1; goto fail; } @@ -3090,12 +3092,14 @@ } else if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { ret = avcodec_decode_subtitle2(avctx, &subtitle, &got_picture, &pkt); + if (got_picture) + avsubtitle_free(&subtitle); if (ret >= 0) pkt.size = 0; } if (ret >= 0) { if (got_picture) - st->nb_decoded_frames++; + st->internal->nb_decoded_frames++; ret = got_picture; } } @@ -3219,31 +3223,51 @@ return AV_CODEC_ID_NONE; } -static void compute_chapters_end(AVFormatContext *s) +static int chapter_start_cmp(const void *p1, const void *p2) { - unsigned int i, j; + AVChapter *ch1 = *(AVChapter**)p1; + AVChapter *ch2 = *(AVChapter**)p2; + int delta = av_compare_ts(ch1->start, ch1->time_base, ch2->start, ch2->time_base); + if (delta) + return delta; + return (ch1 > ch2) - (ch1 < ch2); +} + +static int compute_chapters_end(AVFormatContext *s) +{ + unsigned int i; int64_t max_time = 0; + AVChapter **timetable = av_malloc(s->nb_chapters * sizeof(*timetable)); + + if (!timetable) + return AVERROR(ENOMEM); if (s->duration > 0 && s->start_time < INT64_MAX - s->duration) max_time = s->duration + ((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time); for (i = 0; i < s->nb_chapters; i++) - if (s->chapters[i]->end == AV_NOPTS_VALUE) { - AVChapter *ch = s->chapters[i]; + timetable[i] = s->chapters[i]; + qsort(timetable, s->nb_chapters, sizeof(*timetable), chapter_start_cmp); + + for (i = 0; i < s->nb_chapters; i++) + if (timetable[i]->end == AV_NOPTS_VALUE) { + AVChapter *ch = timetable[i]; int64_t end = max_time ? av_rescale_q(max_time, AV_TIME_BASE_Q, - ch->time_base) - : INT64_MAX; + ch->time_base) + : INT64_MAX; - for (j = 0; j < s->nb_chapters; j++) { - AVChapter *ch1 = s->chapters[j]; + if (i + 1 < s->nb_chapters) { + AVChapter *ch1 = timetable[i + 1]; int64_t next_start = av_rescale_q(ch1->start, ch1->time_base, - ch->time_base); - if (j != i && next_start > ch->start && next_start < end) + ch->time_base); + if (next_start > ch->start && next_start < end) end = next_start; } ch->end = (end == INT64_MAX || end < ch->start) ? ch->start : end; } + av_free(timetable); + return 0; } static int get_std_framerate(int i) @@ -3322,59 +3346,59 @@ int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t ts) { int i, j; - int64_t last = st->info->last_dts; + int64_t last = st->internal->info->last_dts; if ( ts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && ts > last && ts - (uint64_t)last < INT64_MAX) { double dts = (is_relative(ts) ? ts - RELATIVE_TS_BASE : ts) * av_q2d(st->time_base); int64_t duration = ts - last; - if (!st->info->duration_error) - st->info->duration_error = av_mallocz(sizeof(st->info->duration_error[0])*2); - if (!st->info->duration_error) + if (!st->internal->info->duration_error) + st->internal->info->duration_error = av_mallocz(sizeof(st->internal->info->duration_error[0])*2); + if (!st->internal->info->duration_error) return AVERROR(ENOMEM); // if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) // av_log(NULL, AV_LOG_ERROR, "%f\n", dts); for (i = 0; iinfo->duration_error[0][1][i] < 1e10) { + if (st->internal->info->duration_error[0][1][i] < 1e10) { int framerate = get_std_framerate(i); double sdts = dts*framerate/(1001*12); for (j= 0; j<2; j++) { int64_t ticks = llrint(sdts+j*0.5); double error= sdts - ticks + j*0.5; - st->info->duration_error[j][0][i] += error; - st->info->duration_error[j][1][i] += error*error; + st->internal->info->duration_error[j][0][i] += error; + st->internal->info->duration_error[j][1][i] += error*error; } } } - if (st->info->rfps_duration_sum <= INT64_MAX - duration) { - st->info->duration_count++; - st->info->rfps_duration_sum += duration; + if (st->internal->info->rfps_duration_sum <= INT64_MAX - duration) { + st->internal->info->duration_count++; + st->internal->info->rfps_duration_sum += duration; } - if (st->info->duration_count % 10 == 0) { - int n = st->info->duration_count; + if (st->internal->info->duration_count % 10 == 0) { + int n = st->internal->info->duration_count; for (i = 0; iinfo->duration_error[0][1][i] < 1e10) { - double a0 = st->info->duration_error[0][0][i] / n; - double error0 = st->info->duration_error[0][1][i] / n - a0*a0; - double a1 = st->info->duration_error[1][0][i] / n; - double error1 = st->info->duration_error[1][1][i] / n - a1*a1; + if (st->internal->info->duration_error[0][1][i] < 1e10) { + double a0 = st->internal->info->duration_error[0][0][i] / n; + double error0 = st->internal->info->duration_error[0][1][i] / n - a0*a0; + double a1 = st->internal->info->duration_error[1][0][i] / n; + double error1 = st->internal->info->duration_error[1][1][i] / n - a1*a1; if (error0 > 0.04 && error1 > 0.04) { - st->info->duration_error[0][1][i] = 2e10; - st->info->duration_error[1][1][i] = 2e10; + st->internal->info->duration_error[0][1][i] = 2e10; + st->internal->info->duration_error[1][1][i] = 2e10; } } } } // ignore the first 4 values, they might have some random jitter - if (st->info->duration_count > 3 && is_relative(ts) == is_relative(last)) - st->info->duration_gcd = av_gcd(st->info->duration_gcd, duration); + if (st->internal->info->duration_count > 3 && is_relative(ts) == is_relative(last)) + st->internal->info->duration_gcd = av_gcd(st->internal->info->duration_gcd, duration); } if (ts != AV_NOPTS_VALUE) - st->info->last_dts = ts; + st->internal->info->last_dts = ts; return 0; } @@ -3391,9 +3415,10 @@ // the check for tb_unreliable() is not completely correct, since this is not about handling // an unreliable/inexact time base, but a time base that is finer than necessary, as e.g. // ipmovie.c produces. - if (tb_unreliable(st->internal->avctx) && st->info->duration_count > 15 && st->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num) - av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * st->info->duration_gcd, INT_MAX); - if (st->info->duration_count>1 && !st->r_frame_rate.num + if (tb_unreliable(st->internal->avctx) && st->internal->info->duration_count > 15 && st->internal->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num && + st->internal->info->duration_gcd < INT64_MAX / st->time_base.num) + av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * st->internal->info->duration_gcd, INT_MAX); + if (st->internal->info->duration_count>1 && !st->r_frame_rate.num && tb_unreliable(st->internal->avctx)) { int num = 0; double best_error= 0.01; @@ -3402,19 +3427,19 @@ for (j= 0; jinfo->codec_info_duration && - st->info->codec_info_duration*av_q2d(st->time_base) < (1001*11.5)/get_std_framerate(j)) + if (st->internal->info->codec_info_duration && + st->internal->info->codec_info_duration*av_q2d(st->time_base) < (1001*11.5)/get_std_framerate(j)) continue; - if (!st->info->codec_info_duration && get_std_framerate(j) < 1001*12) + if (!st->internal->info->codec_info_duration && get_std_framerate(j) < 1001*12) continue; - if (av_q2d(st->time_base) * st->info->rfps_duration_sum / st->info->duration_count < (1001*12.0 * 0.8)/get_std_framerate(j)) + if (av_q2d(st->time_base) * st->internal->info->rfps_duration_sum / st->internal->info->duration_count < (1001*12.0 * 0.8)/get_std_framerate(j)) continue; for (k= 0; k<2; k++) { - int n = st->info->duration_count; - double a= st->info->duration_error[k][0][j] / n; - double error= st->info->duration_error[k][1][j]/n - a*a; + int n = st->internal->info->duration_count; + double a= st->internal->info->duration_error[k][0][j] / n; + double error= st->internal->info->duration_error[k][1][j]/n - a*a; if (error < best_error && best_error> 0.000000001) { best_error= error; @@ -3429,19 +3454,19 @@ av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX); } if ( !st->avg_frame_rate.num - && st->r_frame_rate.num && st->info->rfps_duration_sum - && st->info->codec_info_duration <= 0 - && st->info->duration_count > 2 - && fabs(1.0 / (av_q2d(st->r_frame_rate) * av_q2d(st->time_base)) - st->info->rfps_duration_sum / (double)st->info->duration_count) <= 1.0 + && st->r_frame_rate.num && st->internal->info->rfps_duration_sum + && st->internal->info->codec_info_duration <= 0 + && st->internal->info->duration_count > 2 + && fabs(1.0 / (av_q2d(st->r_frame_rate) * av_q2d(st->time_base)) - st->internal->info->rfps_duration_sum / (double)st->internal->info->duration_count) <= 1.0 ) { av_log(ic, AV_LOG_DEBUG, "Setting avg frame rate based on r frame rate\n"); st->avg_frame_rate = st->r_frame_rate; } - av_freep(&st->info->duration_error); - st->info->last_dts = AV_NOPTS_VALUE; - st->info->duration_count = 0; - st->info->rfps_duration_sum = 0; + av_freep(&st->internal->info->duration_error); + st->internal->info->last_dts = AV_NOPTS_VALUE; + st->internal->info->duration_count = 0; + st->internal->info->rfps_duration_sum = 0; } } @@ -3507,7 +3532,7 @@ return ret; } -static int extract_extradata(AVStream *st, AVPacket *pkt) +static int extract_extradata(AVStream *st, const AVPacket *pkt) { AVStreamInternal *sti = st->internal; AVPacket *pkt_ref; @@ -3534,9 +3559,6 @@ } while (ret >= 0 && !sti->avctx->extradata) { - int extradata_size; - uint8_t *extradata; - ret = av_bsf_receive_packet(sti->extract_extradata.bsf, pkt_ref); if (ret < 0) { if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) @@ -3544,19 +3566,15 @@ continue; } - extradata = av_packet_get_side_data(pkt_ref, AV_PKT_DATA_NEW_EXTRADATA, - &extradata_size); - - if (extradata) { - av_assert0(!sti->avctx->extradata); - if ((unsigned)extradata_size < FF_MAX_EXTRADATA_SIZE) - sti->avctx->extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!sti->avctx->extradata) { - av_packet_unref(pkt_ref); - return AVERROR(ENOMEM); + for (int i = 0; i < pkt_ref->side_data_elems; i++) { + AVPacketSideData *side_data = &pkt_ref->side_data[i]; + if (side_data->type == AV_PKT_DATA_NEW_EXTRADATA) { + sti->avctx->extradata = side_data->data; + sti->avctx->extradata_size = side_data->size; + side_data->data = NULL; + side_data->size = 0; + break; } - memcpy(sti->avctx->extradata, extradata, extradata_size); - sti->avctx->extradata_size = extradata_size; } av_packet_unref(pkt_ref); } @@ -3564,13 +3582,28 @@ return 0; } +static int add_coded_side_data(AVStream *st, AVCodecContext *avctx) +{ + int i; + + for (i = 0; i < avctx->nb_coded_side_data; i++) { + const AVPacketSideData *sd_src = &avctx->coded_side_data[i]; + uint8_t *dst_data; + dst_data = av_stream_new_side_data(st, sd_src->type, sd_src->size); + if (!dst_data) + return AVERROR(ENOMEM); + memcpy(dst_data, sd_src->data, sd_src->size); + } + return 0; +} + int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) { int i, count = 0, ret = 0, j; int64_t read_size; AVStream *st; AVCodecContext *avctx; - AVPacket pkt1, *pkt; + AVPacket *pkt1 = ic->internal->pkt; int64_t old_offset = avio_tell(ic->pb); // new streams might appear, no options for those int orig_nb_streams = ic->nb_streams; @@ -3627,7 +3660,7 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif // only for the split stuff - if (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE) && st->request_probe <= 0) { + if (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE) && st->internal->request_probe <= 0) { st->parser = av_parser_init(st->codecpar->codec_id); if (st->parser) { if (st->need_parsing == AVSTREAM_PARSE_HEADERS) { @@ -3648,7 +3681,7 @@ ret = avcodec_parameters_to_context(avctx, st->codecpar); if (ret < 0) goto find_stream_info_err; - if (st->request_probe <= 0) + if (st->internal->request_probe <= 0) st->internal->avctx_inited = 1; codec = find_probe_decoder(ic, st, st->codecpar->codec_id); @@ -3656,6 +3689,10 @@ /* Force thread count to 1 since the H.264 decoder will not extract * SPS and PPS to extradata during multi-threaded decoding. */ av_dict_set(options ? &options[i] : &thread_opt, "threads", "1", 0); + /* Force lowres to 0. The decoder might reduce the video size by the + * lowres factor, and we don't want that propagated to the stream's + * codecpar */ + av_dict_set(options ? &options[i] : &thread_opt, "lowres", "0", 0); if (ic->codec_whitelist) av_dict_set(options ? &options[i] : &thread_opt, "codec_whitelist", ic->codec_whitelist, 0); @@ -3669,7 +3706,7 @@ } // Try to just open decoders, in case this is enough to get parameters. - if (!has_codec_parameters(st, NULL) && st->request_probe <= 0) { + if (!has_codec_parameters(st, NULL) && st->internal->request_probe <= 0) { if (codec && !avctx->codec) if (avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt) < 0) av_log(ic, AV_LOG_WARNING, @@ -3681,14 +3718,15 @@ for (i = 0; i < ic->nb_streams; i++) { #if FF_API_R_FRAME_RATE - ic->streams[i]->info->last_dts = AV_NOPTS_VALUE; + ic->streams[i]->internal->info->last_dts = AV_NOPTS_VALUE; #endif - ic->streams[i]->info->fps_first_dts = AV_NOPTS_VALUE; - ic->streams[i]->info->fps_last_dts = AV_NOPTS_VALUE; + ic->streams[i]->internal->info->fps_first_dts = AV_NOPTS_VALUE; + ic->streams[i]->internal->info->fps_last_dts = AV_NOPTS_VALUE; } read_size = 0; for (;;) { + const AVPacket *pkt; int analyzed_all_streams; if (ff_check_interrupt(&ic->interrupt_callback)) { ret = AVERROR_EXIT; @@ -3717,8 +3755,8 @@ fps_analyze_framecount = 0; /* variable fps and no guess at the real fps */ count = (ic->iformat->flags & AVFMT_NOTIMESTAMPS) ? - st->info->codec_info_duration_fields/2 : - st->info->duration_count; + st->internal->info->codec_info_duration_fields/2 : + st->internal->info->duration_count; if (!(st->r_frame_rate.num && st->avg_frame_rate.num) && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { if (count < fps_analyze_framecount) @@ -3726,7 +3764,7 @@ } // Look at the first 3 frames if there is evidence of frame delay // but the decoder delay is not set. - if (st->info->frame_delay_evidence && count < 2 && st->internal->avctx->has_b_frames == 0) + if (st->internal->info->frame_delay_evidence && count < 2 && st->internal->avctx->has_b_frames == 0) break; if (!st->internal->avctx->extradata && (!st->internal->extract_extradata.inited || @@ -3742,18 +3780,18 @@ } analyzed_all_streams = 0; if (!missing_streams || !*missing_streams) - if (i == ic->nb_streams) { - analyzed_all_streams = 1; - /* NOTE: If the format has no header, then we need to read some - * packets to get most of the streams, so we cannot stop here. */ - if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) { - /* If we found the info for all the codecs, we can stop. */ - ret = count; - av_log(ic, AV_LOG_DEBUG, "All info found\n"); - flush_codecs = 0; - break; + if (i == ic->nb_streams) { + analyzed_all_streams = 1; + /* NOTE: If the format has no header, then we need to read some + * packets to get most of the streams, so we cannot stop here. */ + if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) { + /* If we found the info for all the codecs, we can stop. */ + ret = count; + av_log(ic, AV_LOG_DEBUG, "All info found\n"); + flush_codecs = 0; + break; + } } - } /* We did not get all the codec info, but we read too much data. */ if (read_size >= probesize) { ret = count; @@ -3761,7 +3799,7 @@ "Probe buffer size limit of %"PRId64" bytes reached\n", probesize); for (i = 0; i < ic->nb_streams; i++) if (!ic->streams[i]->r_frame_rate.num && - ic->streams[i]->info->duration_count <= 1 && + ic->streams[i]->internal->info->duration_count <= 1 && ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && strcmp(ic->iformat->name, "image2")) av_log(ic, AV_LOG_WARNING, @@ -3772,7 +3810,7 @@ /* NOTE: A new stream can be added there if no header in file * (AVFMTCTX_NOHEADER). */ - ret = read_frame_internal(ic, &pkt1); + ret = read_frame_internal(ic, pkt1); if (ret == AVERROR(EAGAIN)) continue; @@ -3782,14 +3820,16 @@ break; } - pkt = &pkt1; - if (!(ic->flags & AVFMT_FLAG_NOBUFFER)) { - ret = ff_packet_list_put(&ic->internal->packet_buffer, + ret = avpriv_packet_list_put(&ic->internal->packet_buffer, &ic->internal->packet_buffer_end, - pkt, 0); + pkt1, NULL, 0); if (ret < 0) - goto find_stream_info_err; + goto unref_then_goto_end; + + pkt = &ic->internal->packet_buffer_end->pkt; + } else { + pkt = pkt1; } st = ic->streams[pkt->stream_index]; @@ -3800,63 +3840,65 @@ if (!st->internal->avctx_inited) { ret = avcodec_parameters_to_context(avctx, st->codecpar); if (ret < 0) - goto find_stream_info_err; + goto unref_then_goto_end; st->internal->avctx_inited = 1; } if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) { /* check for non-increasing dts */ - if (st->info->fps_last_dts != AV_NOPTS_VALUE && - st->info->fps_last_dts >= pkt->dts) { + if (st->internal->info->fps_last_dts != AV_NOPTS_VALUE && + st->internal->info->fps_last_dts >= pkt->dts) { av_log(ic, AV_LOG_DEBUG, "Non-increasing DTS in stream %d: packet %d with DTS " "%"PRId64", packet %d with DTS %"PRId64"\n", - st->index, st->info->fps_last_dts_idx, - st->info->fps_last_dts, st->codec_info_nb_frames, + st->index, st->internal->info->fps_last_dts_idx, + st->internal->info->fps_last_dts, st->codec_info_nb_frames, pkt->dts); - st->info->fps_first_dts = - st->info->fps_last_dts = AV_NOPTS_VALUE; + st->internal->info->fps_first_dts = + st->internal->info->fps_last_dts = AV_NOPTS_VALUE; } /* Check for a discontinuity in dts. If the difference in dts * is more than 1000 times the average packet duration in the * sequence, we treat it as a discontinuity. */ - if (st->info->fps_last_dts != AV_NOPTS_VALUE && - st->info->fps_last_dts_idx > st->info->fps_first_dts_idx && - (pkt->dts - (uint64_t)st->info->fps_last_dts) / 1000 > - (st->info->fps_last_dts - (uint64_t)st->info->fps_first_dts) / - (st->info->fps_last_dts_idx - st->info->fps_first_dts_idx)) { + if (st->internal->info->fps_last_dts != AV_NOPTS_VALUE && + st->internal->info->fps_last_dts_idx > st->internal->info->fps_first_dts_idx && + (pkt->dts - (uint64_t)st->internal->info->fps_last_dts) / 1000 > + (st->internal->info->fps_last_dts - (uint64_t)st->internal->info->fps_first_dts) / + (st->internal->info->fps_last_dts_idx - st->internal->info->fps_first_dts_idx)) { av_log(ic, AV_LOG_WARNING, "DTS discontinuity in stream %d: packet %d with DTS " "%"PRId64", packet %d with DTS %"PRId64"\n", - st->index, st->info->fps_last_dts_idx, - st->info->fps_last_dts, st->codec_info_nb_frames, + st->index, st->internal->info->fps_last_dts_idx, + st->internal->info->fps_last_dts, st->codec_info_nb_frames, pkt->dts); - st->info->fps_first_dts = - st->info->fps_last_dts = AV_NOPTS_VALUE; + st->internal->info->fps_first_dts = + st->internal->info->fps_last_dts = AV_NOPTS_VALUE; } /* update stored dts values */ - if (st->info->fps_first_dts == AV_NOPTS_VALUE) { - st->info->fps_first_dts = pkt->dts; - st->info->fps_first_dts_idx = st->codec_info_nb_frames; + if (st->internal->info->fps_first_dts == AV_NOPTS_VALUE) { + st->internal->info->fps_first_dts = pkt->dts; + st->internal->info->fps_first_dts_idx = st->codec_info_nb_frames; } - st->info->fps_last_dts = pkt->dts; - st->info->fps_last_dts_idx = st->codec_info_nb_frames; + st->internal->info->fps_last_dts = pkt->dts; + st->internal->info->fps_last_dts_idx = st->codec_info_nb_frames; } if (st->codec_info_nb_frames>1) { int64_t t = 0; int64_t limit; if (st->time_base.den > 0) - t = av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q); + t = av_rescale_q(st->internal->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q); if (st->avg_frame_rate.num > 0) t = FFMAX(t, av_rescale_q(st->codec_info_nb_frames, av_inv_q(st->avg_frame_rate), AV_TIME_BASE_Q)); if ( t == 0 && st->codec_info_nb_frames>30 - && st->info->fps_first_dts != AV_NOPTS_VALUE - && st->info->fps_last_dts != AV_NOPTS_VALUE) - t = FFMAX(t, av_rescale_q(st->info->fps_last_dts - st->info->fps_first_dts, st->time_base, AV_TIME_BASE_Q)); + && st->internal->info->fps_first_dts != AV_NOPTS_VALUE + && st->internal->info->fps_last_dts != AV_NOPTS_VALUE) { + int64_t dur = av_sat_sub64(st->internal->info->fps_last_dts, st->internal->info->fps_first_dts); + t = FFMAX(t, av_rescale_q(dur, st->time_base, AV_TIME_BASE_Q)); + } if (analyzed_all_streams) limit = max_analyze_duration; else if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) limit = max_subtitle_analyze_duration; @@ -3867,15 +3909,15 @@ limit, t, pkt->stream_index); if (ic->flags & AVFMT_FLAG_NOBUFFER) - av_packet_unref(pkt); + av_packet_unref(pkt1); break; } if (pkt->duration) { if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE && pkt->pts != AV_NOPTS_VALUE && st->start_time != AV_NOPTS_VALUE && pkt->pts >= st->start_time) { - st->info->codec_info_duration = FFMIN(pkt->pts - st->start_time, st->info->codec_info_duration + pkt->duration); + st->internal->info->codec_info_duration = FFMIN(pkt->pts - st->start_time, st->internal->info->codec_info_duration + pkt->duration); } else - st->info->codec_info_duration += pkt->duration; - st->info->codec_info_duration_fields += st->parser && st->need_parsing && avctx->ticks_per_frame ==2 ? st->parser->repeat_pict + 1 : 2; + st->internal->info->codec_info_duration += pkt->duration; + st->internal->info->codec_info_duration_fields += st->parser && st->need_parsing && avctx->ticks_per_frame ==2 ? st->parser->repeat_pict + 1 : 2; } } if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -3883,12 +3925,12 @@ ff_rfps_add_frame(ic, st, pkt->dts); #endif if (pkt->dts != pkt->pts && pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE) - st->info->frame_delay_evidence = 1; + st->internal->info->frame_delay_evidence = 1; } if (!st->internal->avctx->extradata) { ret = extract_extradata(st, pkt); if (ret < 0) - goto find_stream_info_err; + goto unref_then_goto_end; } /* If still no information, we try to open the codec and to @@ -3904,7 +3946,7 @@ (options && i < orig_nb_streams) ? &options[i] : NULL); if (ic->flags & AVFMT_FLAG_NOBUFFER) - av_packet_unref(pkt); + av_packet_unref(pkt1); st->codec_info_nb_frames++; count++; @@ -3937,18 +3979,18 @@ } if (flush_codecs) { - AVPacket empty_pkt = { 0 }; + AVPacket *empty_pkt = ic->internal->pkt; int err = 0; - av_init_packet(&empty_pkt); + av_packet_unref(empty_pkt); for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; /* flush the decoders */ - if (st->info->found_decoder == 1) { + if (st->internal->info->found_decoder == 1) { do { - err = try_decode_frame(ic, st, &empty_pkt, + err = try_decode_frame(ic, st, empty_pkt, (options && i < orig_nb_streams) ? &options[i] : NULL); } while (err > 0 && !has_codec_parameters(st, NULL)); @@ -3974,20 +4016,20 @@ } /* estimate average framerate if not set by demuxer */ - if (st->info->codec_info_duration_fields && + if (st->internal->info->codec_info_duration_fields && !st->avg_frame_rate.num && - st->info->codec_info_duration) { + st->internal->info->codec_info_duration) { int best_fps = 0; double best_error = 0.01; AVRational codec_frame_rate = avctx->framerate; - if (st->info->codec_info_duration >= INT64_MAX / st->time_base.num / 2|| - st->info->codec_info_duration_fields >= INT64_MAX / st->time_base.den || - st->info->codec_info_duration < 0) + if (st->internal->info->codec_info_duration >= INT64_MAX / st->time_base.num / 2|| + st->internal->info->codec_info_duration_fields >= INT64_MAX / st->time_base.den || + st->internal->info->codec_info_duration < 0) continue; av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, - st->info->codec_info_duration_fields * (int64_t) st->time_base.den, - st->info->codec_info_duration * 2 * (int64_t) st->time_base.num, 60000); + st->internal->info->codec_info_duration_fields * (int64_t) st->time_base.den, + st->internal->info->codec_info_duration * 2 * (int64_t) st->time_base.num, 60000); /* Round guessed framerate to a "standard" framerate if it's * within 1% of the original estimate. */ @@ -4017,7 +4059,7 @@ if (!st->r_frame_rate.num) { if ( avctx->time_base.den * (int64_t) st->time_base.num - <= avctx->time_base.num * avctx->ticks_per_frame * (int64_t) st->time_base.den) { + <= avctx->time_base.num * avctx->ticks_per_frame * (uint64_t) st->time_base.den) { av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, avctx->time_base.den, (int64_t)avctx->time_base.num * avctx->ticks_per_frame, INT_MAX); } else { @@ -4025,9 +4067,9 @@ st->r_frame_rate.den = st->time_base.num; } } - if (st->display_aspect_ratio.num && st->display_aspect_ratio.den) { + if (st->internal->display_aspect_ratio.num && st->internal->display_aspect_ratio.den) { AVRational hw_ratio = { avctx->height, avctx->width }; - st->sample_aspect_ratio = av_mul_q(st->display_aspect_ratio, + st->sample_aspect_ratio = av_mul_q(st->internal->display_aspect_ratio, hw_ratio); } } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { @@ -4081,32 +4123,28 @@ avcodec_string(buf, sizeof(buf), st->internal->avctx, 0); av_log(ic, AV_LOG_WARNING, "Could not find codec parameters for stream %d (%s): %s\n" - "Consider increasing the value for the 'analyzeduration' and 'probesize' options\n", - i, buf, errmsg); + "Consider increasing the value for the 'analyzeduration' (%"PRId64") and 'probesize' (%"PRId64") options\n", + i, buf, errmsg, ic->max_analyze_duration, ic->probesize); } else { ret = 0; } } - compute_chapters_end(ic); + ret = compute_chapters_end(ic); + if (ret < 0) + goto find_stream_info_err; /* update the stream parameters from the internal codec contexts */ for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; if (st->internal->avctx_inited) { - int orig_w = st->codecpar->width; - int orig_h = st->codecpar->height; ret = avcodec_parameters_from_context(st->codecpar, st->internal->avctx); if (ret < 0) goto find_stream_info_err; -#if FF_API_LOWRES - // The decoder might reduce the video size by the lowres factor. - if (st->internal->avctx->lowres && orig_w) { - st->codecpar->width = orig_w; - st->codecpar->height = orig_h; - } -#endif + ret = add_coded_side_data(st, st->internal->avctx); + if (ret < 0) + goto find_stream_info_err; } #if FF_API_LAVF_AVCTX @@ -4115,7 +4153,6 @@ if (ret < 0) goto find_stream_info_err; -#if FF_API_LOWRES // The old API (AVStream.codec) "requires" the resolution to be adjusted // by the lowres factor. if (st->internal->avctx->lowres && st->internal->avctx->width) { @@ -4123,7 +4160,6 @@ st->codec->width = st->internal->avctx->width; st->codec->height = st->internal->avctx->height; } -#endif if (st->codec->codec_tag != MKTAG('t','m','c','d')) { st->codec->time_base = st->internal->avctx->time_base; @@ -4153,10 +4189,10 @@ find_stream_info_err: for (i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; - if (st->info) - av_freep(&st->info->duration_error); + if (st->internal->info) + av_freep(&st->internal->info->duration_error); avcodec_close(ic->streams[i]->internal->avctx); - av_freep(&ic->streams[i]->info); + av_freep(&ic->streams[i]->internal->info); av_bsf_free(&ic->streams[i]->internal->extract_extradata.bsf); av_packet_free(&ic->streams[i]->internal->extract_extradata.pkt); } @@ -4164,6 +4200,10 @@ av_log(ic, AV_LOG_DEBUG, "After avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d frames:%d\n", avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count, count); return ret; + +unref_then_goto_end: + av_packet_unref(pkt1); + goto find_stream_info_err; } AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s) @@ -4350,29 +4390,28 @@ if (st->internal) { avcodec_free_context(&st->internal->avctx); - for (i = 0; i < st->internal->nb_bsfcs; i++) { - av_bsf_free(&st->internal->bsfcs[i]); - av_freep(&st->internal->bsfcs); - } + av_bsf_free(&st->internal->bsfc); av_freep(&st->internal->priv_pts); + av_freep(&st->index_entries); + av_freep(&st->internal->probe_data.buf); + av_bsf_free(&st->internal->extract_extradata.bsf); av_packet_free(&st->internal->extract_extradata.pkt); + + if (st->internal->info) + av_freep(&st->internal->info->duration_error); + av_freep(&st->internal->info); } av_freep(&st->internal); av_dict_free(&st->metadata); avcodec_parameters_free(&st->codecpar); - av_freep(&st->probe_data.buf); - av_freep(&st->index_entries); #if FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS avcodec_free_context(&st->codec); FF_ENABLE_DEPRECATION_WARNINGS #endif av_freep(&st->priv_data); - if (st->info) - av_freep(&st->info->duration_error); - av_freep(&st->info); #if FF_API_LAVF_FFSERVER FF_DISABLE_DEPRECATION_WARNINGS av_freep(&st->recommended_encoder_configuration); @@ -4397,21 +4436,26 @@ if (!s) return; + if (s->oformat && s->oformat->deinit && s->internal->initialized) + s->oformat->deinit(s); + av_opt_free(s); if (s->iformat && s->iformat->priv_class && s->priv_data) av_opt_free(s->priv_data); if (s->oformat && s->oformat->priv_class && s->priv_data) av_opt_free(s->priv_data); - for (i = s->nb_streams - 1; i >= 0; i--) - ff_free_stream(s, s->streams[i]); - + for (i = 0; i < s->nb_streams; i++) + free_stream(&s->streams[i]); + s->nb_streams = 0; - for (i = s->nb_programs - 1; i >= 0; i--) { + for (i = 0; i < s->nb_programs; i++) { av_dict_free(&s->programs[i]->metadata); av_freep(&s->programs[i]->stream_index); av_freep(&s->programs[i]); } + s->nb_programs = 0; + av_freep(&s->programs); av_freep(&s->priv_data); while (s->nb_chapters--) { @@ -4421,6 +4465,8 @@ av_freep(&s->chapters); av_dict_free(&s->metadata); av_dict_free(&s->internal->id3v2_meta); + av_packet_free(&s->internal->pkt); + av_packet_free(&s->internal->parse_pkt); av_freep(&s->streams); flush_packet_queue(s); av_freep(&s->internal); @@ -4475,17 +4521,11 @@ st = av_mallocz(sizeof(AVStream)); if (!st) return NULL; - if (!(st->info = av_mallocz(sizeof(*st->info)))) { - av_free(st); - return NULL; - } - st->info->last_dts = AV_NOPTS_VALUE; #if FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS st->codec = avcodec_alloc_context3(c); if (!st->codec) { - av_free(st->info); av_free(st); return NULL; } @@ -4496,6 +4536,11 @@ if (!st->internal) goto fail; + st->internal->info = av_mallocz(sizeof(*st->internal->info)); + if (!st->internal->info) + goto fail; + st->internal->info->last_dts = AV_NOPTS_VALUE; + st->codecpar = avcodec_parameters_alloc(); if (!st->codecpar) goto fail; @@ -4527,24 +4572,24 @@ st->start_time = AV_NOPTS_VALUE; st->duration = AV_NOPTS_VALUE; st->first_dts = AV_NOPTS_VALUE; - st->probe_packets = MAX_PROBE_PACKETS; - st->pts_wrap_reference = AV_NOPTS_VALUE; - st->pts_wrap_behavior = AV_PTS_WRAP_IGNORE; + st->probe_packets = s->max_probe_packets; + st->internal->pts_wrap_reference = AV_NOPTS_VALUE; + st->internal->pts_wrap_behavior = AV_PTS_WRAP_IGNORE; st->last_IP_pts = AV_NOPTS_VALUE; - st->last_dts_for_order_check = AV_NOPTS_VALUE; + st->internal->last_dts_for_order_check = AV_NOPTS_VALUE; for (i = 0; i < MAX_REORDER_DELAY + 1; i++) - st->pts_buffer[i] = AV_NOPTS_VALUE; + st->internal->pts_buffer[i] = AV_NOPTS_VALUE; st->sample_aspect_ratio = (AVRational) { 0, 1 }; #if FF_API_R_FRAME_RATE - st->info->last_dts = AV_NOPTS_VALUE; + st->internal->info->last_dts = AV_NOPTS_VALUE; #endif - st->info->fps_first_dts = AV_NOPTS_VALUE; - st->info->fps_last_dts = AV_NOPTS_VALUE; + st->internal->info->fps_first_dts = AV_NOPTS_VALUE; + st->internal->info->fps_last_dts = AV_NOPTS_VALUE; - st->inject_global_side_data = s->internal->inject_global_side_data; + st->internal->inject_global_side_data = s->internal->inject_global_side_data; st->internal->need_context_update = 1; @@ -4558,7 +4603,7 @@ AVProgram *av_new_program(AVFormatContext *ac, int id) { AVProgram *program = NULL; - int i; + int i, ret; av_log(ac, AV_LOG_TRACE, "new_program: id=0x%04x\n", id); @@ -4570,40 +4615,55 @@ program = av_mallocz(sizeof(AVProgram)); if (!program) return NULL; - dynarray_add(&ac->programs, &ac->nb_programs, program); + ret = av_dynarray_add_nofree(&ac->programs, &ac->nb_programs, program); + if (ret < 0) { + av_free(program); + return NULL; + } program->discard = AVDISCARD_NONE; program->pmt_version = -1; + program->id = id; + program->pts_wrap_reference = AV_NOPTS_VALUE; + program->pts_wrap_behavior = AV_PTS_WRAP_IGNORE; + program->start_time = + program->end_time = AV_NOPTS_VALUE; } - program->id = id; - program->pts_wrap_reference = AV_NOPTS_VALUE; - program->pts_wrap_behavior = AV_PTS_WRAP_IGNORE; - - program->start_time = - program->end_time = AV_NOPTS_VALUE; - return program; } +#if FF_API_CHAPTER_ID_INT AVChapter *avpriv_new_chapter(AVFormatContext *s, int id, AVRational time_base, +#else +AVChapter *avpriv_new_chapter(AVFormatContext *s, int64_t id, AVRational time_base, +#endif int64_t start, int64_t end, const char *title) { AVChapter *chapter = NULL; - int i; + int i, ret; if (end != AV_NOPTS_VALUE && start > end) { av_log(s, AV_LOG_ERROR, "Chapter end time %"PRId64" before start %"PRId64"\n", end, start); return NULL; } - for (i = 0; i < s->nb_chapters; i++) - if (s->chapters[i]->id == id) - chapter = s->chapters[i]; + if (!s->nb_chapters) { + s->internal->chapter_ids_monotonic = 1; + } else if (!s->internal->chapter_ids_monotonic || s->chapters[s->nb_chapters-1]->id >= id) { + s->internal->chapter_ids_monotonic = 0; + for (i = 0; i < s->nb_chapters; i++) + if (s->chapters[i]->id == id) + chapter = s->chapters[i]; + } if (!chapter) { chapter = av_mallocz(sizeof(AVChapter)); if (!chapter) return NULL; - dynarray_add(&s->chapters, &s->nb_chapters, chapter); + ret = av_dynarray_add_nofree(&s->chapters, &s->nb_chapters, chapter); + if (ret < 0) { + av_free(chapter); + return NULL; + } } av_dict_set(&chapter->metadata, "title", title, 0); chapter->id = id; @@ -4685,8 +4745,11 @@ if (c == '%') { do { nd = 0; - while (av_isdigit(*p)) + while (av_isdigit(*p)) { + if (nd >= INT_MAX / 10 - 255) + goto fail; nd = nd * 10 + *p++ - '0'; + } c = *p++; } while (av_isdigit(c)); @@ -4734,7 +4797,7 @@ char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url) { - const char *p, *ls, *ls2, *at, *at2, *col, *brk; + const char *p, *ls, *at, *at2, *col, *brk; if (port_ptr) *port_ptr = -1; @@ -4762,16 +4825,8 @@ } /* separate path from hostname */ - ls = strchr(p, '/'); - ls2 = strchr(p, '?'); - if (!ls) - ls = ls2; - else if (ls && ls2) - ls = FFMIN(ls, ls2); - if (ls) - av_strlcpy(path, ls, path_size); - else - ls = &p[strlen(p)]; // XXX + ls = p + strcspn(p, "/?#"); + av_strlcpy(path, ls, path_size); /* the rest is hostname, use that to parse auth/port */ if (ls != p) { @@ -5407,7 +5462,7 @@ }; const uint8_t *data = NULL; - int size = 0; + int ret, size = 0; if (st->codecpar->width == 1920) { if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) { @@ -5436,16 +5491,15 @@ if (!size) return 0; - av_freep(&st->codecpar->extradata); - if (ff_alloc_extradata(st->codecpar, size)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0) + return ret; memcpy(st->codecpar->extradata, data, size); return 0; } uint8_t *av_stream_get_side_data(const AVStream *st, - enum AVPacketSideDataType type, int *size) + enum AVPacketSideDataType type, buffer_size_t *size) { int i; @@ -5456,6 +5510,8 @@ return st->side_data[i].data; } } + if (size) + *size = 0; return NULL; } @@ -5496,7 +5552,7 @@ } uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type, - int size) + buffer_size_t size) { int ret; uint8_t *data = av_malloc(size); @@ -5518,7 +5574,8 @@ int ret; const AVBitStreamFilter *bsf; AVBSFContext *bsfc; - AVCodecParameters *in_par; + + av_assert0(!st->internal->bsfc); if (!(bsf = av_bsf_get_by_name(name))) { av_log(NULL, AV_LOG_ERROR, "Unknown bitstream filter '%s'\n", name); @@ -5528,15 +5585,8 @@ if ((ret = av_bsf_alloc(bsf, &bsfc)) < 0) return ret; - if (st->internal->nb_bsfcs) { - in_par = st->internal->bsfcs[st->internal->nb_bsfcs - 1]->par_out; - bsfc->time_base_in = st->internal->bsfcs[st->internal->nb_bsfcs - 1]->time_base_out; - } else { - in_par = st->codecpar; - bsfc->time_base_in = st->time_base; - } - - if ((ret = avcodec_parameters_copy(bsfc->par_in, in_par)) < 0) { + bsfc->time_base_in = st->time_base; + if ((ret = avcodec_parameters_copy(bsfc->par_in, st->codecpar)) < 0) { av_bsf_free(&bsfc); return ret; } @@ -5559,10 +5609,7 @@ return ret; } - if ((ret = av_dynarray_add_nofree(&st->internal->bsfcs, &st->internal->nb_bsfcs, bsfc))) { - av_bsf_free(&bsfc); - return ret; - } + st->internal->bsfc = bsfc; av_log(NULL, AV_LOG_VERBOSE, "Automatically inserted bitstream filter '%s'; args='%s'\n", @@ -5679,7 +5726,7 @@ int ff_get_packet_palette(AVFormatContext *s, AVPacket *pkt, int ret, uint32_t *palette) { uint8_t *side_data; - int size; + buffer_size_t size; side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_PALETTE, &size); if (side_data) { @@ -5729,8 +5776,18 @@ enum AVTimebaseSource copy_tb) { //TODO: use [io]st->internal->avctx - const AVCodecContext *dec_ctx = ist->codec; - AVCodecContext *enc_ctx = ost->codec; + const AVCodecContext *dec_ctx; + AVCodecContext *enc_ctx; + +#if FF_API_LAVF_AVCTX +FF_DISABLE_DEPRECATION_WARNINGS + dec_ctx = ist->codec; + enc_ctx = ost->codec; +FF_ENABLE_DEPRECATION_WARNINGS +#else + dec_ctx = ist->internal->avctx; + enc_ctx = ost->internal->avctx; +#endif enc_ctx->time_base = ist->time_base; /* diff -Nru ffmpeg-4.2.2/libavformat/vc1test.c ffmpeg-4.4/libavformat/vc1test.c --- ffmpeg-4.2.2/libavformat/vc1test.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/vc1test.c 2020-07-11 10:39:30.000000000 +0000 @@ -51,7 +51,7 @@ { AVIOContext *pb = s->pb; AVStream *st; - int frames; + int frames, ret; uint32_t fps; uint32_t size; @@ -67,8 +67,8 @@ st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; st->codecpar->codec_id = AV_CODEC_ID_WMV3; - if (ff_get_extradata(s, st->codecpar, pb, VC1_EXTRADATA_SIZE) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_get_extradata(s, st->codecpar, pb, VC1_EXTRADATA_SIZE)) < 0) + return ret; avio_skip(pb, size - 4); st->codecpar->height = avio_rl32(pb); diff -Nru ffmpeg-4.2.2/libavformat/vc1testenc.c ffmpeg-4.4/libavformat/vc1testenc.c --- ffmpeg-4.2.2/libavformat/vc1testenc.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/vc1testenc.c 2020-07-11 10:39:30.000000000 +0000 @@ -76,7 +76,6 @@ if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { avio_seek(pb, 0, SEEK_SET); avio_wl24(pb, ctx->frames); - avio_flush(pb); } return 0; } diff -Nru ffmpeg-4.2.2/libavformat/version.h ffmpeg-4.4/libavformat/version.h --- ffmpeg-4.2.2/libavformat/version.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/version.h 2021-04-08 21:28:40.000000000 +0000 @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 58 -#define LIBAVFORMAT_VERSION_MINOR 29 +#define LIBAVFORMAT_VERSION_MINOR 76 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ @@ -106,6 +106,15 @@ #ifndef FF_API_AVIOFORMAT #define FF_API_AVIOFORMAT (LIBAVFORMAT_VERSION_MAJOR < 59) #endif +#ifndef FF_API_DEMUXER_OPEN +#define FF_API_DEMUXER_OPEN (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_CHAPTER_ID_INT +#define FF_API_CHAPTER_ID_INT (LIBAVFORMAT_VERSION_MAJOR < 59) +#endif +#ifndef FF_API_LAVF_PRIV_OPT +#define FF_API_LAVF_PRIV_OPT (LIBAVFORMAT_VERSION_MAJOR < 60) +#endif #ifndef FF_API_R_FRAME_RATE diff -Nru ffmpeg-4.2.2/libavformat/vividas.c ffmpeg-4.4/libavformat/vividas.c --- ffmpeg-4.2.2/libavformat/vividas.c 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/vividas.c 2021-04-08 21:28:40.000000000 +0000 @@ -28,6 +28,7 @@ * @sa http://wiki.multimedia.cx/index.php?title=Vividas_VIV */ +#include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" #include "avio_internal.h" #include "avformat.h" @@ -156,7 +157,7 @@ uint32_t tmpkey = *key_ptr - key; if (a2 > s) { a2 = s; - avpriv_request_sample(NULL, "tiny aligned block\n"); + avpriv_request_sample(NULL, "tiny aligned block"); } memcpy(tmp + align, src, a2); xor_block(tmp, tmp, 4, key, &tmpkey); @@ -266,7 +267,7 @@ *size = n; n -= 8; - if (avio_read(src, buf+8, n) < n) { + if (avio_read(src, buf+8, n) != n) { av_free(buf); return NULL; } @@ -278,15 +279,13 @@ static int track_header(VividasDemuxContext *viv, AVFormatContext *s, uint8_t *buf, int size) { - int i,j; + int i, j, ret; int64_t off; int val_1; int num_video; - AVIOContext *pb; + AVIOContext pb0, *pb = &pb0; - pb = avio_alloc_context(buf, size, 0, NULL, NULL, NULL, NULL); - if (!pb) - return AVERROR(ENOMEM); + ffio_init_context(pb, buf, size, 0, NULL, NULL, NULL, NULL); ffio_read_varlen(pb); // track_header_len avio_r8(pb); // '1' @@ -295,6 +294,8 @@ for (i=0;iid = i; @@ -329,8 +334,9 @@ off += ffio_read_varlen(pb); avio_r8(pb); // '3' avio_r8(pb); // val_7 - st->time_base.num = avio_rl32(pb); // frame_time - st->time_base.den = avio_rl32(pb); // time_base + num = avio_rl32(pb); // frame_time + den = avio_rl32(pb); // time_base + avpriv_set_pts_info(st, 64, num, den); st->nb_frames = avio_rl32(pb); // n frames st->codecpar->width = avio_rl16(pb); // width st->codecpar->height = avio_rl16(pb); // height @@ -352,6 +358,8 @@ for(i=0;inum_audio;i++) { int q; AVStream *st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); st->id = num_video + i; @@ -365,6 +373,8 @@ avio_rl16(pb); //codec_subid st->codecpar->channels = avio_rl16(pb); // channels st->codecpar->sample_rate = avio_rl32(pb); // sample_rate + if (st->codecpar->sample_rate <= 0 || st->codecpar->channels <= 0) + return AVERROR_INVALIDDATA; avio_seek(pb, 10, SEEK_CUR); // data_1 q = avio_r8(pb); avio_seek(pb, q, SEEK_CUR); // data_2 @@ -372,7 +382,7 @@ if (avio_tell(pb) < off) { int num_data; - int xd_size = 0; + int xd_size = 1; int data_len[256]; int offset = 1; uint8_t *p; @@ -381,30 +391,24 @@ ffio_read_varlen(pb); // len_3 num_data = avio_r8(pb); for (j = 0; j < num_data; j++) { - uint64_t len = ffio_read_varlen(pb); - if (len > INT_MAX/2 - xd_size) { - av_free(pb); + int64_t len = ffio_read_varlen(pb); + if (len < 0 || len > INT_MAX/2 - xd_size) { return AVERROR_INVALIDDATA; } data_len[j] = len; - xd_size += len; + xd_size += len + 1 + len/255; } - st->codecpar->extradata_size = 64 + xd_size + xd_size / 255; - if (ff_alloc_extradata(st->codecpar, st->codecpar->extradata_size)) { - av_free(pb); - return AVERROR(ENOMEM); - } + ret = ff_alloc_extradata(st->codecpar, xd_size); + if (ret < 0) + return ret; p = st->codecpar->extradata; p[0] = 2; for (j = 0; j < num_data - 1; j++) { unsigned delta = av_xiphlacing(&p[offset], data_len[j]); - if (delta > data_len[j]) { - av_free(pb); - return AVERROR_INVALIDDATA; - } + av_assert0(delta <= xd_size - offset); offset += delta; } @@ -415,6 +419,7 @@ av_freep(&st->codecpar->extradata); break; } + av_assert0(data_len[j] <= xd_size - offset); offset += data_len[j]; } @@ -423,7 +428,6 @@ } } - av_free(pb); return 0; } @@ -432,25 +436,23 @@ int64_t off; int64_t poff; int maxnp=0; - AVIOContext *pb; + AVIOContext pb0, *pb = &pb0; int i; int64_t filesize = avio_size(s->pb); + uint64_t n_sb_blocks_tmp; - pb = avio_alloc_context(buf, size, 0, NULL, NULL, NULL, NULL); - if (!pb) - return AVERROR(ENOMEM); + ffio_init_context(pb, buf, size, 0, NULL, NULL, NULL, NULL); ffio_read_varlen(pb); // track_index_len avio_r8(pb); // 'c' - viv->n_sb_blocks = ffio_read_varlen(pb); - if (viv->n_sb_blocks < 0 || viv->n_sb_blocks > size / 2) - goto error; - viv->sb_blocks = av_calloc(viv->n_sb_blocks, sizeof(VIV_SB_block)); + n_sb_blocks_tmp = ffio_read_varlen(pb); + if (n_sb_blocks_tmp > size / 2) + return AVERROR_INVALIDDATA; + viv->sb_blocks = av_calloc(n_sb_blocks_tmp, sizeof(*viv->sb_blocks)); if (!viv->sb_blocks) { - viv->n_sb_blocks = 0; - av_free(pb); return AVERROR(ENOMEM); } + viv->n_sb_blocks = n_sb_blocks_tmp; off = 0; poff = 0; @@ -460,7 +462,7 @@ uint64_t n_packets_tmp = ffio_read_varlen(pb); if (size_tmp > INT_MAX || n_packets_tmp > INT_MAX) - goto error; + return AVERROR_INVALIDDATA; viv->sb_blocks[i].byte_offset = off; viv->sb_blocks[i].packet_offset = poff; @@ -476,17 +478,13 @@ } if (filesize > 0 && poff > filesize) - goto error; + return AVERROR_INVALIDDATA; viv->sb_entries = av_calloc(maxnp, sizeof(VIV_SB_entry)); - av_free(pb); + if (!viv->sb_entries) + return AVERROR(ENOMEM); return 0; -error: - av_free(pb); - viv->n_sb_blocks = 0; - av_freep(&viv->sb_blocks); - return AVERROR_INVALIDDATA; } static void load_sb_block(AVFormatContext *s, VividasDemuxContext *viv, unsigned expected_size) @@ -615,7 +613,7 @@ ret = track_index(viv, s, buf, v); av_free(buf); if (ret < 0) - return ret; + goto fail; viv->sb_offset = avio_tell(pb); if (viv->n_sb_blocks > 0) { @@ -626,6 +624,9 @@ } return 0; +fail: + av_freep(&viv->sb_blocks); + return ret; } static int viv_read_packet(AVFormatContext *s, @@ -654,7 +655,7 @@ pkt->stream_index = 1; astream = s->streams[pkt->stream_index]; - pkt->pts = av_rescale(viv->audio_sample, astream->time_base.den, astream->time_base.num) / astream->codecpar->sample_rate; + pkt->pts = av_rescale_q(viv->audio_sample, av_make_q(1, astream->codecpar->sample_rate), astream->time_base); viv->audio_sample += viv->audio_subpackets[viv->current_audio_subpacket].pcm_bytes / 2 / astream->codecpar->channels; pkt->flags |= AV_PKT_FLAG_KEY; viv->current_audio_subpacket++; @@ -674,6 +675,10 @@ if (!pb) return AVERROR(EIO); off = avio_tell(pb); + + if (viv->current_sb_entry >= viv->n_sb_entries) + return AVERROR_INVALIDDATA; + off += viv->sb_entries[viv->current_sb_entry].size; if (viv->sb_entries[viv->current_sb_entry].flag == 0) { @@ -683,7 +688,7 @@ return AVERROR_INVALIDDATA; ffio_read_varlen(pb); - if (v_size > INT_MAX) + if (v_size > INT_MAX || !v_size) return AVERROR_INVALIDDATA; ret = av_get_packet(pb, pkt, v_size); if (ret < 0) @@ -712,7 +717,7 @@ } else { uint64_t v_size = ffio_read_varlen(pb); - if (v_size > INT_MAX) + if (v_size > INT_MAX || !v_size) return AVERROR_INVALIDDATA; ret = av_get_packet(pb, pkt, v_size); if (ret < 0) @@ -752,18 +757,23 @@ for (int i = 0; i < viv->n_sb_blocks; i++) { if (frame >= viv->sb_blocks[i].packet_offset && frame < viv->sb_blocks[i].packet_offset + viv->sb_blocks[i].n_packets) { - // flush audio packet queue - viv->current_audio_subpacket = 0; - viv->n_audio_subpackets = 0; viv->current_sb = i; // seek to ith sb block avio_seek(s->pb, viv->sb_offset + viv->sb_blocks[i].byte_offset, SEEK_SET); // load the block load_sb_block(s, viv, 0); - // most problematic part: guess audio offset - viv->audio_sample = av_rescale_q(viv->sb_blocks[i].packet_offset, av_make_q(s->streams[1]->codecpar->sample_rate, 1), av_inv_q(s->streams[0]->time_base)); - // hand-tuned 1.s a/v offset - viv->audio_sample += s->streams[1]->codecpar->sample_rate; + if (viv->num_audio) { + const AVCodecParameters *par = s->streams[1]->codecpar; + // flush audio packet queue + viv->current_audio_subpacket = 0; + viv->n_audio_subpackets = 0; + // most problematic part: guess audio offset + viv->audio_sample = av_rescale_q(viv->sb_blocks[i].packet_offset, + av_make_q(par->sample_rate, 1), + av_inv_q(s->streams[0]->time_base)); + // hand-tuned 1.s a/v offset + viv->audio_sample += par->sample_rate; + } viv->current_sb_entry = 0; return 1; } diff -Nru ffmpeg-4.2.2/libavformat/vivo.c ffmpeg-4.4/libavformat/vivo.c --- ffmpeg-4.2.2/libavformat/vivo.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/vivo.c 2020-07-11 10:39:30.000000000 +0000 @@ -36,6 +36,7 @@ int type; int sequence; int length; + int duration; uint8_t text[1024 + 1]; } VivoContext; @@ -59,9 +60,10 @@ if (c & 0x80 || length > 1024 || length < 21) return 0; - if (memcmp(buf, "\r\nVersion:Vivo/", 15)) + buf += 2; + if (memcmp(buf, "Version:Vivo/", 13)) return 0; - buf += 15; + buf += 13; if (*buf < '0' || *buf > '2') return 0; @@ -231,6 +233,12 @@ ast->codecpar->bits_per_coded_sample = 8; ast->codecpar->block_align = 24; ast->codecpar->bit_rate = 6400; + } else { + ast->codecpar->codec_id = AV_CODEC_ID_SIREN; + ast->codecpar->bits_per_coded_sample = 16; + ast->codecpar->block_align = 40; + ast->codecpar->bit_rate = 6400; + vivo->duration = 320; } ast->start_time = 0; @@ -246,7 +254,7 @@ VivoContext *vivo = s->priv_data; AVIOContext *pb = s->pb; unsigned old_sequence = vivo->sequence, old_type = vivo->type; - int stream_index, ret = 0; + int stream_index, duration, ret = 0; restart: @@ -262,10 +270,12 @@ case 1: case 2: // video stream_index = 0; + duration = 1; break; case 3: case 4: // audio stream_index = 1; + duration = vivo->duration; break; default: av_log(s, AV_LOG_ERROR, "unknown packet type %d\n", vivo->type); @@ -273,32 +283,29 @@ } if ((ret = av_get_packet(pb, pkt, vivo->length)) < 0) - goto fail; + return ret; // get next packet header if ((ret = vivo_get_packet_header(s)) < 0) - goto fail; + return ret; while (vivo->sequence == old_sequence && (((vivo->type - 1) >> 1) == ((old_type - 1) >> 1))) { if (avio_feof(pb)) { - ret = AVERROR_EOF; - break; + return AVERROR_EOF; } if ((ret = av_append_packet(pb, pkt, vivo->length)) < 0) - break; + return ret; // get next packet header if ((ret = vivo_get_packet_header(s)) < 0) - break; + return ret; } pkt->stream_index = stream_index; + pkt->duration = duration; -fail: - if (ret < 0) - av_packet_unref(pkt); return ret; } diff -Nru ffmpeg-4.2.2/libavformat/voc.c ffmpeg-4.4/libavformat/voc.c --- ffmpeg-4.2.2/libavformat/voc.c 2016-03-29 02:25:30.000000000 +0000 +++ ffmpeg-4.4/libavformat/voc.c 2021-04-08 21:28:40.000000000 +0000 @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" #include "voc.h" #include "internal.h" -const unsigned char ff_voc_magic[21] = "Creative Voice File\x1A"; const AVCodecTag ff_voc_codec_tags[] = { {AV_CODEC_ID_PCM_U8, 0x00}, @@ -35,3 +35,8 @@ {AV_CODEC_ID_ADPCM_CT, 0x0200}, {AV_CODEC_ID_NONE, 0}, }; + +#if CONFIG_VOC_DEMUXER || CONFIG_VOC_MUXER +const unsigned char ff_voc_magic[21] = "Creative Voice File\x1A"; +const AVCodecTag *const ff_voc_codec_tags_list[] = { ff_voc_codec_tags, NULL }; +#endif diff -Nru ffmpeg-4.2.2/libavformat/vocdec.c ffmpeg-4.4/libavformat/vocdec.c --- ffmpeg-4.2.2/libavformat/vocdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/vocdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -106,5 +106,5 @@ .read_header = voc_read_header, .read_packet = voc_read_packet, .read_seek = voc_read_seek, - .codec_tag = (const AVCodecTag* const []){ ff_voc_codec_tags, 0 }, + .codec_tag = ff_voc_codec_tags_list, }; diff -Nru ffmpeg-4.2.2/libavformat/vocenc.c ffmpeg-4.4/libavformat/vocenc.c --- ffmpeg-4.2.2/libavformat/vocenc.c 2018-11-01 18:34:27.000000000 +0000 +++ ffmpeg-4.4/libavformat/vocenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -106,6 +106,6 @@ .write_header = voc_write_header, .write_packet = voc_write_packet, .write_trailer = voc_write_trailer, - .codec_tag = (const AVCodecTag* const []){ ff_voc_codec_tags, 0 }, + .codec_tag = ff_voc_codec_tags_list, .flags = AVFMT_NOTIMESTAMPS, }; diff -Nru ffmpeg-4.2.2/libavformat/voc.h ffmpeg-4.4/libavformat/voc.h --- ffmpeg-4.2.2/libavformat/voc.h 2017-12-31 22:35:49.000000000 +0000 +++ ffmpeg-4.4/libavformat/voc.h 2021-04-08 21:28:40.000000000 +0000 @@ -45,6 +45,7 @@ extern const unsigned char ff_voc_magic[21]; extern const AVCodecTag ff_voc_codec_tags[]; +extern const AVCodecTag *const ff_voc_codec_tags_list[]; int ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size); diff -Nru ffmpeg-4.2.2/libavformat/voc_packet.c ffmpeg-4.4/libavformat/voc_packet.c --- ffmpeg-4.2.2/libavformat/voc_packet.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/voc_packet.c 2021-04-08 21:28:40.000000000 +0000 @@ -44,19 +44,29 @@ AVINDEX_KEYFRAME); while (!voc->remaining_size) { + if (max_size < 4) + max_size = 0; type = avio_r8(pb); if (type == VOC_TYPE_EOF) return AVERROR_EOF; voc->remaining_size = avio_rl24(pb); if (!voc->remaining_size) { + int64_t filesize; if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) return AVERROR(EIO); - voc->remaining_size = avio_size(pb) - avio_tell(pb); + filesize = avio_size(pb); + if (filesize - avio_tell(pb) > INT_MAX) + return AVERROR_INVALIDDATA; + voc->remaining_size = filesize - avio_tell(pb); } max_size -= 4; switch (type) { case VOC_TYPE_VOICE_DATA: + if (voc->remaining_size < 2) { + voc->remaining_size = 0; + return AVERROR_INVALIDDATA; + } if (!par->sample_rate) { par->sample_rate = 1000000 / (256 - avio_r8(pb)); if (sample_rate) @@ -85,6 +95,10 @@ break; case VOC_TYPE_NEW_VOICE_DATA: + if (voc->remaining_size < 12) { + voc->remaining_size = 0; + return AVERROR_INVALIDDATA; + } if (!par->sample_rate) { par->sample_rate = avio_rl32(pb); avpriv_set_pts_info(st, 64, 1, par->sample_rate); diff -Nru ffmpeg-4.2.2/libavformat/vorbiscomment.c ffmpeg-4.4/libavformat/vorbiscomment.c --- ffmpeg-4.2.2/libavformat/vorbiscomment.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/vorbiscomment.c 2020-07-11 10:39:30.000000000 +0000 @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "avio.h" #include "avformat.h" #include "metadata.h" #include "vorbiscomment.h" -#include "libavcodec/bytestream.h" #include "libavutil/dict.h" /** @@ -38,7 +38,7 @@ { 0 } }; -int64_t ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string, +int64_t ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string, AVChapter **chapters, unsigned int nb_chapters) { int64_t len = 8; @@ -62,31 +62,31 @@ return len; } -int ff_vorbiscomment_write(uint8_t **p, AVDictionary **m, +int ff_vorbiscomment_write(AVIOContext *pb, const AVDictionary *m, const char *vendor_string, AVChapter **chapters, unsigned int nb_chapters) { int cm_count = 0; - bytestream_put_le32(p, strlen(vendor_string)); - bytestream_put_buffer(p, vendor_string, strlen(vendor_string)); + avio_wl32(pb, strlen(vendor_string)); + avio_write(pb, vendor_string, strlen(vendor_string)); if (chapters && nb_chapters) { for (int i = 0; i < nb_chapters; i++) { cm_count += av_dict_count(chapters[i]->metadata) + 1; } } - if (*m) { - int count = av_dict_count(*m) + cm_count; + if (m) { + int count = av_dict_count(m) + cm_count; AVDictionaryEntry *tag = NULL; - bytestream_put_le32(p, count); - while ((tag = av_dict_get(*m, "", tag, AV_DICT_IGNORE_SUFFIX))) { + avio_wl32(pb, count); + while ((tag = av_dict_get(m, "", tag, AV_DICT_IGNORE_SUFFIX))) { int64_t len1 = strlen(tag->key); int64_t len2 = strlen(tag->value); if (len1+1+len2 > UINT32_MAX) return AVERROR(EINVAL); - bytestream_put_le32(p, len1+1+len2); - bytestream_put_buffer(p, tag->key, len1); - bytestream_put_byte(p, '='); - bytestream_put_buffer(p, tag->value, len2); + avio_wl32(pb, len1 + 1 + len2); + avio_write(pb, tag->key, len1); + avio_w8(pb, '='); + avio_write(pb, tag->value, len2); } for (int i = 0; i < nb_chapters; i++) { AVChapter *chp = chapters[i]; @@ -101,11 +101,11 @@ s = s % 60; snprintf(chapter_number, sizeof(chapter_number), "%03d", i); snprintf(chapter_time, sizeof(chapter_time), "%02d:%02d:%02d.%03d", h, m, s, ms); - bytestream_put_le32(p, 10+1+12); - bytestream_put_buffer(p, "CHAPTER", 7); - bytestream_put_buffer(p, chapter_number, 3); - bytestream_put_byte(p, '='); - bytestream_put_buffer(p, chapter_time, 12); + avio_wl32(pb, 10 + 1 + 12); + avio_write(pb, "CHAPTER", 7); + avio_write(pb, chapter_number, 3); + avio_w8(pb, '='); + avio_write(pb, chapter_time, 12); tag = NULL; while ((tag = av_dict_get(chapters[i]->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { @@ -113,18 +113,18 @@ int64_t len2 = strlen(tag->value); if (len1+1+len2+10 > UINT32_MAX) return AVERROR(EINVAL); - bytestream_put_le32(p, 10+len1+1+len2); - bytestream_put_buffer(p, "CHAPTER", 7); - bytestream_put_buffer(p, chapter_number, 3); + avio_wl32(pb, 10 + len1 + 1 + len2); + avio_write(pb, "CHAPTER", 7); + avio_write(pb, chapter_number, 3); if (!strcmp(tag->key, "title")) - bytestream_put_buffer(p, "NAME", 4); + avio_write(pb, "NAME", 4); else - bytestream_put_buffer(p, tag->key, len1); - bytestream_put_byte(p, '='); - bytestream_put_buffer(p, tag->value, len2); + avio_write(pb, tag->key, len1); + avio_w8(pb, '='); + avio_write(pb, tag->value, len2); } } } else - bytestream_put_le32(p, 0); + avio_wl32(pb, 0); return 0; } diff -Nru ffmpeg-4.2.2/libavformat/vorbiscomment.h ffmpeg-4.4/libavformat/vorbiscomment.h --- ffmpeg-4.2.2/libavformat/vorbiscomment.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/vorbiscomment.h 2020-07-11 10:39:30.000000000 +0000 @@ -34,22 +34,21 @@ * For no string, set to an empty string. * @return The length in bytes. */ -int64_t ff_vorbiscomment_length(AVDictionary *m, const char *vendor_string, +int64_t ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string, AVChapter **chapters, unsigned int nb_chapters); /** - * Write a VorbisComment into a buffer. The buffer, p, must have enough - * data to hold the whole VorbisComment. The minimum size required can be - * obtained by passing the same AVDictionary and vendor_string to + * Write a VorbisComment into an AVIOContext. The output size can be obtained + * in advance by passing the same chapters, AVDictionary and vendor_string to * ff_vorbiscomment_length() * - * @param p The buffer in which to write. + * @param pb The AVIOContext to write the output. * @param m The metadata struct to write. * @param vendor_string The vendor string to write. * @param chapters The chapters to write. * @param nb_chapters The number of chapters to write. */ -int ff_vorbiscomment_write(uint8_t **p, AVDictionary **m, +int ff_vorbiscomment_write(AVIOContext *pb, const AVDictionary *m, const char *vendor_string, AVChapter **chapters, unsigned int nb_chapters); diff -Nru ffmpeg-4.2.2/libavformat/vpk.c ffmpeg-4.4/libavformat/vpk.c --- ffmpeg-4.2.2/libavformat/vpk.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/vpk.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ #include "internal.h" typedef struct VPKDemuxContext { + unsigned data_start; unsigned block_count; unsigned current_block; unsigned last_block_size; @@ -70,6 +71,7 @@ if (offset < avio_tell(s->pb)) return AVERROR_INVALIDDATA; avio_skip(s->pb, offset - avio_tell(s->pb)); + vpk->data_start = offset; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); return 0; @@ -85,6 +87,7 @@ if (vpk->current_block == vpk->block_count) { unsigned size = vpk->last_block_size / par->channels; unsigned skip = (par->block_align - vpk->last_block_size) / par->channels; + uint64_t pos = avio_tell(s->pb); ret = av_new_packet(pkt, vpk->last_block_size); if (ret < 0) @@ -93,11 +96,10 @@ ret = avio_read(s->pb, pkt->data + i * size, size); avio_skip(s->pb, skip); if (ret != size) { - av_packet_unref(pkt); - ret = AVERROR(EIO); - break; + return AVERROR(EIO); } } + pkt->pos = pos; pkt->stream_index = 0; } else if (vpk->current_block < vpk->block_count) { ret = av_get_packet(s->pb, pkt, par->block_align); @@ -109,6 +111,29 @@ return ret; } +static int vpk_read_seek(AVFormatContext *s, int stream_index, + int64_t timestamp, int flags) +{ + AVStream *st = s->streams[stream_index]; + AVCodecParameters *par = st->codecpar; + VPKDemuxContext *vpk = s->priv_data; + int samples_per_block; + int64_t ret = 0; + + samples_per_block = av_get_audio_frame_duration2(par, par->block_align); + if (samples_per_block > 0) + timestamp /= samples_per_block; + else + return -1; + ret = avio_seek(s->pb, vpk->data_start + timestamp * par->block_align, SEEK_SET); + if (ret < 0) + return ret; + + vpk->current_block = timestamp; + ff_update_cur_dts(s, st, timestamp * samples_per_block); + return 0; +} + AVInputFormat ff_vpk_demuxer = { .name = "vpk", .long_name = NULL_IF_CONFIG_SMALL("Sony PS2 VPK"), @@ -116,5 +141,6 @@ .read_probe = vpk_probe, .read_header = vpk_read_header, .read_packet = vpk_read_packet, + .read_seek = vpk_read_seek, .extensions = "vpk", }; diff -Nru ffmpeg-4.2.2/libavformat/vplayerdec.c ffmpeg-4.4/libavformat/vplayerdec.c --- ffmpeg-4.2.2/libavformat/vplayerdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/vplayerdec.c 2020-07-09 09:17:49.000000000 +0000 @@ -83,8 +83,10 @@ AVPacket *sub; sub = ff_subtitles_queue_insert(&vplayer->q, p, strlen(p), 0); - if (!sub) + if (!sub) { + ff_subtitles_queue_clean(&vplayer->q); return AVERROR(ENOMEM); + } sub->pos = pos; sub->pts = pts_start; sub->duration = -1; diff -Nru ffmpeg-4.2.2/libavformat/vqf.c ffmpeg-4.4/libavformat/vqf.c --- ffmpeg-4.2.2/libavformat/vqf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/vqf.c 2021-02-20 20:27:47.000000000 +0000 @@ -97,7 +97,7 @@ int rate_flag = -1; int header_size; int read_bitrate = 0; - int size; + int size, ret; uint8_t comm_chunk[12]; if (!st) @@ -132,6 +132,9 @@ switch(chunk_tag){ case MKTAG('C','O','M','M'): + if (len < 12) + return AVERROR_INVALIDDATA; + avio_read(s->pb, comm_chunk, 12); st->codecpar->channels = AV_RB32(comm_chunk ) + 1; read_bitrate = AV_RB32(comm_chunk + 4); @@ -222,8 +225,8 @@ avpriv_set_pts_info(st, 64, size, st->codecpar->sample_rate); /* put first 12 bytes of COMM chunk in extradata */ - if (ff_alloc_extradata(st->codecpar, 12)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 12)) < 0) + return ret; memcpy(st->codecpar->extradata, comm_chunk, 12); ff_metadata_conv_ctx(s, NULL, vqf_metadata_conv); @@ -237,8 +240,8 @@ int ret; int size = (c->frame_bit_len - c->remaining_bits + 7)>>3; - if (av_new_packet(pkt, size+2) < 0) - return AVERROR(EIO); + if ((ret = av_new_packet(pkt, size + 2)) < 0) + return ret; pkt->pos = avio_tell(s->pb); pkt->stream_index = 0; @@ -249,7 +252,6 @@ ret = avio_read(s->pb, pkt->data+2, size); if (ret != size) { - av_packet_unref(pkt); return AVERROR(EIO); } diff -Nru ffmpeg-4.2.2/libavformat/wavdec.c ffmpeg-4.4/libavformat/wavdec.c --- ffmpeg-4.2.2/libavformat/wavdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/wavdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -6,6 +6,8 @@ * RF64 demuxer * Copyright (c) 2009 Daniel Verkamp * + * BW64 demuxer + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -25,6 +27,7 @@ #include +#include "config.h" #include "libavutil/avassert.h" #include "libavutil/dict.h" #include "libavutil/intreadwrite.h" @@ -54,13 +57,24 @@ int smv_eof; int audio_eof; int ignore_length; + int max_size; int spdif; - int smv_cur_pt; int smv_given_first; int unaligned; // e.g. if an odd number of bytes ID3 tag was prepended int rifx; // RIFX: integer byte order for parameters is big endian } WAVDemuxContext; +#define OFFSET(x) offsetof(WAVDemuxContext, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +static const AVOption demux_options[] = { +#define W64_DEMUXER_OPTIONS_OFFSET (1 * CONFIG_WAV_DEMUXER) +#if CONFIG_WAV_DEMUXER + { "ignore_length", "Ignore length", OFFSET(ignore_length), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC }, +#endif + { "max_size", "max size of single packet", OFFSET(max_size), AV_OPT_TYPE_INT, { .i64 = 4096 }, 1024, 1 << 22, DEC }, + { NULL }, +}; + static void set_spdif(AVFormatContext *s, WAVDemuxContext *wav) { if (CONFIG_SPDIF_DEMUXER && s->streams[0]->codecpar->codec_tag == 1) { @@ -69,7 +83,7 @@ int ret = ffio_ensure_seekback(s->pb, len); if (ret >= 0) { - uint8_t *buf = av_malloc(len); + uint8_t *buf = av_malloc(len + AV_INPUT_BUFFER_PADDING_SIZE); if (!buf) { ret = AVERROR(ENOMEM); } else { @@ -140,7 +154,8 @@ * its own, the returned score is decreased to avoid a probe * conflict between ACT and WAV. */ return AVPROBE_SCORE_MAX - 1; - else if (!memcmp(p->buf, "RF64", 4) && + else if ((!memcmp(p->buf, "RF64", 4) || + !memcmp(p->buf, "BW64", 4)) && !memcmp(p->buf + 12, "ds64", 4)) return AVPROBE_SCORE_MAX; } @@ -150,7 +165,7 @@ static void handle_stream_probing(AVStream *st) { if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE) { - st->request_probe = AVPROBE_SCORE_EXTENSION; + st->internal->request_probe = AVPROBE_SCORE_EXTENSION; st->probe_packets = FFMIN(st->probe_packets, 32); } } @@ -181,7 +196,7 @@ static int wav_parse_xma2_tag(AVFormatContext *s, int64_t size, AVStream **st) { AVIOContext *pb = s->pb; - int version, num_streams, i, channels = 0; + int version, num_streams, i, channels = 0, ret; if (size < 36) return AVERROR_INVALIDDATA; @@ -220,9 +235,8 @@ avpriv_set_pts_info(*st, 64, 1, (*st)->codecpar->sample_rate); avio_seek(pb, -size, SEEK_CUR); - av_freep(&(*st)->codecpar->extradata); - if (ff_get_extradata(s, (*st)->codecpar, pb, size) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_get_extradata(s, (*st)->codecpar, pb, size)) < 0) + return ret; return 0; } @@ -331,7 +345,7 @@ { int64_t size, av_uninit(data_size); int64_t sample_count = 0; - int rf64 = 0; + int rf64 = 0, bw64 = 0; uint32_t tag; AVIOContext *pb = s->pb; AVStream *st = NULL; @@ -354,6 +368,9 @@ case MKTAG('R', 'F', '6', '4'): rf64 = 1; break; + case MKTAG('B', 'W', '6', '4'): + bw64 = 1; + break; default: av_log(s, AV_LOG_ERROR, "invalid start code %s in RIFF header\n", av_fourcc2str(tag)); @@ -369,7 +386,7 @@ return AVERROR_INVALIDDATA; } - if (rf64) { + if (rf64 || bw64) { if (avio_rl32(pb) != MKTAG('d', 's', '6', '4')) return AVERROR_INVALIDDATA; size = avio_rl32(pb); @@ -424,7 +441,7 @@ return AVERROR_INVALIDDATA; } - if (rf64) { + if (rf64 || bw64) { next_tag_ofs = wav->data_end = avio_tell(pb) + data_size; } else if (size != 0xFFFFFFFF) { data_size = size; @@ -441,7 +458,7 @@ /* don't look for footer metadata if we can't seek or if we don't * know where the data tag ends */ - if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || (!rf64 && !size)) + if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || (!(rf64 && !bw64) && !size)) goto break_loop; break; case MKTAG('f', 'a', 'c', 't'): @@ -473,9 +490,9 @@ vst->codecpar->codec_id = AV_CODEC_ID_SMVJPEG; vst->codecpar->width = avio_rl24(pb); vst->codecpar->height = avio_rl24(pb); - if (ff_alloc_extradata(vst->codecpar, 4)) { + if ((ret = ff_alloc_extradata(vst->codecpar, 4)) < 0) { av_log(s, AV_LOG_ERROR, "Could not allocate extradata.\n"); - return AVERROR(ENOMEM); + return ret; } size = avio_rl24(pb); wav->smv_data_ofs = avio_tell(pb) + (size - 5) * 3; @@ -491,9 +508,9 @@ return AVERROR_INVALIDDATA; } AV_WL32(vst->codecpar->extradata, wav->smv_frames_per_jpeg); - wav->smv_cur_pt = 0; goto break_loop; case MKTAG('L', 'I', 'S', 'T'): + case MKTAG('l', 'i', 's', 't'): if (size < 4) { av_log(s, AV_LOG_ERROR, "too short LIST tag\n"); return AVERROR_INVALIDDATA; @@ -501,6 +518,33 @@ switch (avio_rl32(pb)) { case MKTAG('I', 'N', 'F', 'O'): ff_read_riff_info(s, size - 4); + break; + case MKTAG('a', 'd', 't', 'l'): + if (s->nb_chapters > 0) { + while (avio_tell(pb) < next_tag_ofs && + !avio_feof(pb)) { + char cue_label[512]; + unsigned id, sub_size; + + if (avio_rl32(pb) != MKTAG('l', 'a', 'b', 'l')) + break; + + sub_size = avio_rl32(pb); + if (sub_size < 5) + break; + id = avio_rl32(pb); + avio_get_str(pb, sub_size - 4, cue_label, sizeof(cue_label)); + avio_skip(pb, avio_tell(pb) & 1); + + for (int i = 0; i < s->nb_chapters; i++) { + if (s->chapters[i]->id == id) { + av_dict_set(&s->chapters[i]->metadata, "title", cue_label, 0); + break; + } + } + } + } + break; } break; case MKTAG('I', 'D', '3', ' '): @@ -508,13 +552,34 @@ ID3v2ExtraMeta *id3v2_extra_meta = NULL; ff_id3v2_read_dict(pb, &s->internal->id3v2_meta, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); if (id3v2_extra_meta) { - ff_id3v2_parse_apic(s, &id3v2_extra_meta); - ff_id3v2_parse_chapters(s, &id3v2_extra_meta); - ff_id3v2_parse_priv(s, &id3v2_extra_meta); + ff_id3v2_parse_apic(s, id3v2_extra_meta); + ff_id3v2_parse_chapters(s, id3v2_extra_meta); + ff_id3v2_parse_priv(s, id3v2_extra_meta); } ff_id3v2_free_extra_meta(&id3v2_extra_meta); } break; + case MKTAG('c', 'u', 'e', ' '): + if (size >= 4 && got_fmt && st->codecpar->sample_rate > 0) { + AVRational tb = {1, st->codecpar->sample_rate}; + unsigned nb_cues = avio_rl32(pb); + + if (size >= nb_cues * 24LL + 4LL) { + for (int i = 0; i < nb_cues; i++) { + unsigned offset, id = avio_rl32(pb); + + if (avio_feof(pb)) + return AVERROR_INVALIDDATA; + + avio_skip(pb, 16); + offset = avio_rl32(pb); + + if (!avpriv_new_chapter(s, id, tb, offset, AV_NOPTS_VALUE, NULL)) + return AVERROR(ENOMEM); + } + } + } + break; } /* seek to next tag unless we know that we'll run into EOF */ @@ -590,6 +655,9 @@ } else if (st->codecpar->codec_id == AV_CODEC_ID_XMA1 || st->codecpar->codec_id == AV_CODEC_ID_XMA2) { st->codecpar->block_align = 2048; + } else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS && st->codecpar->channels > 2 && + st->codecpar->block_align < INT_MAX / st->codecpar->channels) { + st->codecpar->block_align *= st->codecpar->channels; } ff_metadata_conv_ctx(s, NULL, wav_metadata_conv); @@ -612,7 +680,7 @@ while (!avio_feof(pb)) { avio_read(pb, guid, 16); size = avio_rl64(pb); - if (size <= 24) + if (size <= 24 || size > INT64_MAX - 8) return AVERROR_INVALIDDATA; if (!memcmp(guid, guid1, 16)) return size; @@ -621,8 +689,6 @@ return AVERROR_EOF; } -#define MAX_SIZE 4096 - static int wav_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret, size; @@ -662,12 +728,9 @@ if (ret < 0) goto smv_out; pkt->pos -= 3; - pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg + wav->smv_cur_pt; - wav->smv_cur_pt++; - if (wav->smv_frames_per_jpeg > 0) - wav->smv_cur_pt %= wav->smv_frames_per_jpeg; - if (!wav->smv_cur_pt) - wav->smv_block++; + pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg; + pkt->duration = wav->smv_frames_per_jpeg; + wav->smv_block++; pkt->stream_index = 1; smv_out: @@ -699,7 +762,7 @@ wav->data_end = avio_tell(s->pb) + left; } - size = MAX_SIZE; + size = wav->max_size; if (st->codecpar->block_align > 1) { if (size < st->codecpar->block_align) size = st->codecpar->block_align; @@ -729,7 +792,6 @@ timestamp = av_rescale_q(smv_timestamp, s->streams[1]->time_base, s->streams[0]->time_base); if (wav->smv_frames_per_jpeg > 0) { wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg; - wav->smv_cur_pt = smv_timestamp % wav->smv_frames_per_jpeg; } } @@ -748,13 +810,6 @@ return ff_pcm_read_seek(s, stream_index, timestamp, flags); } -#define OFFSET(x) offsetof(WAVDemuxContext, x) -#define DEC AV_OPT_FLAG_DECODING_PARAM -static const AVOption demux_options[] = { - { "ignore_length", "Ignore length", OFFSET(ignore_length), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, DEC }, - { NULL }, -}; - static const AVClass wav_demuxer_class = { .class_name = "WAV demuxer", .item_name = av_default_item_name, @@ -770,7 +825,7 @@ .read_packet = wav_read_packet, .read_seek = wav_read_seek, .flags = AVFMT_GENERIC_INDEX, - .codec_tag = (const AVCodecTag * const []) { ff_codec_wav_tags, 0 }, + .codec_tag = ff_wav_codec_tags_list, .priv_class = &wav_demuxer_class, }; #endif /* CONFIG_WAV_DEMUXER */ @@ -849,6 +904,7 @@ } else if (!memcmp(guid, ff_w64_guid_summarylist, 16)) { int64_t start, end, cur; uint32_t count, chunk_size, i; + int64_t filesize = avio_size(s->pb); start = avio_tell(pb); end = start + FFALIGN(size, INT64_C(8)) - 24; @@ -863,14 +919,18 @@ chunk_key[4] = 0; avio_read(pb, chunk_key, 4); chunk_size = avio_rl32(pb); - if (chunk_size == UINT32_MAX) + if (chunk_size == UINT32_MAX || (filesize >= 0 && chunk_size > filesize)) return AVERROR_INVALIDDATA; - value = av_mallocz(chunk_size + 1); + value = av_malloc(chunk_size + 1); if (!value) return AVERROR(ENOMEM); ret = avio_get_str16le(pb, chunk_size, value, chunk_size); + if (ret < 0) { + av_free(value); + return ret; + } avio_skip(pb, chunk_size - ret); av_dict_set(&s->metadata, chunk_key, value, AV_DICT_DONT_STRDUP_VAL); @@ -899,6 +959,13 @@ return 0; } +static const AVClass w64_demuxer_class = { + .class_name = "W64 demuxer", + .item_name = av_default_item_name, + .option = &demux_options[W64_DEMUXER_OPTIONS_OFFSET], + .version = LIBAVUTIL_VERSION_INT, +}; + AVInputFormat ff_w64_demuxer = { .name = "w64", .long_name = NULL_IF_CONFIG_SMALL("Sony Wave64"), @@ -908,6 +975,7 @@ .read_packet = wav_read_packet, .read_seek = wav_read_seek, .flags = AVFMT_GENERIC_INDEX, - .codec_tag = (const AVCodecTag * const []) { ff_codec_wav_tags, 0 }, + .codec_tag = ff_wav_codec_tags_list, + .priv_class = &w64_demuxer_class, }; #endif /* CONFIG_W64_DEMUXER */ diff -Nru ffmpeg-4.2.2/libavformat/wavenc.c ffmpeg-4.4/libavformat/wavenc.c --- ffmpeg-4.2.2/libavformat/wavenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/wavenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -50,8 +50,6 @@ #define RF64_NEVER 0 #define RF64_ALWAYS 1 -#define PEAK_BUFFER_SIZE 1024 - typedef enum { PEAK_OFF = 0, PEAK_ON, @@ -72,8 +70,9 @@ int64_t maxpts; int16_t *peak_maxpos, *peak_maxneg; uint32_t peak_num_frames; - uint32_t peak_outbuf_size; + unsigned peak_outbuf_size; uint32_t peak_outbuf_bytes; + unsigned size_increment; uint8_t *peak_output; int last_duration; int write_bext; @@ -141,7 +140,7 @@ ff_end_tag(s->pb, bext); } -static av_cold void peak_free_buffers(AVFormatContext *s) +static av_cold void wav_deinit(AVFormatContext *s) { WAVMuxContext *wav = s->priv_data; @@ -159,9 +158,8 @@ par->codec_id != AV_CODEC_ID_PCM_S16LE && par->codec_id != AV_CODEC_ID_PCM_U8 && par->codec_id != AV_CODEC_ID_PCM_U16LE) { - AVCodec *codec = avcodec_find_decoder(s->streams[0]->codecpar->codec_id); - av_log(s, AV_LOG_ERROR, "%s codec not supported for Peak Chunk\n", - codec ? codec->name : "NONE"); + av_log(s, AV_LOG_ERROR, "Codec %s not supported for Peak Chunk\n", + avcodec_get_name(par->codec_id)); return -1; } @@ -172,31 +170,40 @@ "Writing 16 bit peak for 8 bit audio does not make sense\n"); return AVERROR(EINVAL); } + if (par->channels > INT_MAX / (wav->peak_bps * wav->peak_ppv)) + return AVERROR(ERANGE); + wav->size_increment = par->channels * wav->peak_bps * wav->peak_ppv; wav->peak_maxpos = av_mallocz_array(par->channels, sizeof(*wav->peak_maxpos)); wav->peak_maxneg = av_mallocz_array(par->channels, sizeof(*wav->peak_maxneg)); - wav->peak_output = av_malloc(PEAK_BUFFER_SIZE); - if (!wav->peak_maxpos || !wav->peak_maxneg || !wav->peak_output) + if (!wav->peak_maxpos || !wav->peak_maxneg) goto nomem; - wav->peak_outbuf_size = PEAK_BUFFER_SIZE; - return 0; nomem: av_log(s, AV_LOG_ERROR, "Out of memory\n"); - peak_free_buffers(s); return AVERROR(ENOMEM); } -static void peak_write_frame(AVFormatContext *s) +static int peak_write_frame(AVFormatContext *s) { WAVMuxContext *wav = s->priv_data; AVCodecParameters *par = s->streams[0]->codecpar; + unsigned new_size = wav->peak_outbuf_bytes + wav->size_increment; + uint8_t *tmp; int c; - if (!wav->peak_output) - return; + if (new_size > INT_MAX) { + wav->write_peak = PEAK_OFF; + return AVERROR(ERANGE); + } + tmp = av_fast_realloc(wav->peak_output, &wav->peak_outbuf_size, new_size); + if (!tmp) { + wav->write_peak = PEAK_OFF; + return AVERROR(ENOMEM); + } + wav->peak_output = tmp; for (c = 0; c < par->channels; c++) { wav->peak_maxneg[c] = -wav->peak_maxneg[c]; @@ -210,17 +217,6 @@ wav->peak_maxpos[c] = FFMAX(wav->peak_maxpos[c], wav->peak_maxneg[c]); - if (wav->peak_outbuf_size - wav->peak_outbuf_bytes < - wav->peak_format * wav->peak_ppv) { - wav->peak_outbuf_size += PEAK_BUFFER_SIZE; - wav->peak_output = av_realloc(wav->peak_output, - wav->peak_outbuf_size); - if (!wav->peak_output) { - av_log(s, AV_LOG_ERROR, "No memory for peak data\n"); - return; - } - } - if (wav->peak_format == PEAK_FORMAT_UINT8) { wav->peak_output[wav->peak_outbuf_bytes++] = wav->peak_maxpos[c]; @@ -242,6 +238,8 @@ wav->peak_maxneg[c] = 0; } wav->peak_num_frames++; + + return 0; } static int peak_write_chunk(AVFormatContext *s) @@ -255,8 +253,11 @@ char timestamp[28]; /* Peak frame of incomplete block at end */ - if (wav->peak_block_pos) - peak_write_frame(s); + if (wav->peak_block_pos) { + int ret = peak_write_frame(s); + if (ret < 0) + return ret; + } memset(timestamp, 0, sizeof(timestamp)); if (!(s->flags & AVFMT_FLAG_BITEXACT)) { @@ -326,9 +327,8 @@ /* format header */ fmt = ff_start_tag(pb, "fmt "); if (ff_put_wav_header(s, pb, s->streams[0]->codecpar, 0) < 0) { - const AVCodecDescriptor *desc = avcodec_descriptor_get(s->streams[0]->codecpar->codec_id); - av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n", - desc ? desc->name : "unknown"); + av_log(s, AV_LOG_ERROR, "Codec %s not supported in WAVE format\n", + avcodec_get_name(s->streams[0]->codecpar->codec_id)); return AVERROR(ENOSYS); } ff_end_tag(pb, fmt); @@ -362,8 +362,6 @@ wav->data = ff_start_tag(pb, "data"); } - avio_flush(pb); - return 0; } @@ -389,7 +387,9 @@ if (++c == s->streams[0]->codecpar->channels) { c = 0; if (++wav->peak_block_pos == wav->peak_block_size) { - peak_write_frame(s); + int ret = peak_write_frame(s); + if (ret < 0) + return ret; wav->peak_block_pos = 0; } } @@ -414,17 +414,13 @@ int rf64 = 0; int ret = 0; - avio_flush(pb); - if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { if (wav->write_peak != PEAK_ONLY && avio_tell(pb) - wav->data < UINT32_MAX) { ff_end_tag(pb, wav->data); - avio_flush(pb); } if (wav->write_peak && wav->peak_output) { ret = peak_write_chunk(s); - avio_flush(pb); } /* update file size */ @@ -436,17 +432,14 @@ avio_seek(pb, 4, SEEK_SET); avio_wl32(pb, (uint32_t)(file_size - 8)); avio_seek(pb, file_size, SEEK_SET); - - avio_flush(pb); } else { av_log(s, AV_LOG_ERROR, "Filesize %"PRId64" invalid for wav, output file will be broken\n", file_size); } - - number_of_samples = av_rescale(wav->maxpts - wav->minpts + wav->last_duration, - s->streams[0]->codecpar->sample_rate * (int64_t)s->streams[0]->time_base.num, - s->streams[0]->time_base.den); + number_of_samples = av_rescale_q(wav->maxpts - wav->minpts + wav->last_duration, + s->streams[0]->time_base, + av_make_q(1, s->streams[0]->codecpar->sample_rate)); if(s->streams[0]->codecpar->codec_tag != 0x01) { /* Update num_samps in fact chunk */ @@ -457,7 +450,6 @@ } else { avio_wl32(pb, number_of_samples); avio_seek(pb, file_size, SEEK_SET); - avio_flush(pb); } } @@ -481,13 +473,9 @@ avio_wl32(pb, -1); avio_seek(pb, file_size, SEEK_SET); - avio_flush(pb); } } - if (wav->write_peak) - peak_free_buffers(s); - return ret; } @@ -527,8 +515,9 @@ .write_header = wav_write_header, .write_packet = wav_write_packet, .write_trailer = wav_write_trailer, + .deinit = wav_deinit, .flags = AVFMT_TS_NONSTRICT, - .codec_tag = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 }, + .codec_tag = ff_wav_codec_tags_list, .priv_class = &wav_muxer_class, }; #endif /* CONFIG_WAV_MUXER */ @@ -567,9 +556,8 @@ avio_write(pb, ff_w64_guid_wave, sizeof(ff_w64_guid_wave)); start_guid(pb, ff_w64_guid_fmt, &start); if ((ret = ff_put_wav_header(s, pb, s->streams[0]->codecpar, 0)) < 0) { - AVCodec *codec = avcodec_find_decoder(s->streams[0]->codecpar->codec_id); - av_log(s, AV_LOG_ERROR, "%s codec not supported\n", - codec ? codec->name : "NONE"); + av_log(s, AV_LOG_ERROR, "Codec %s not supported\n", + avcodec_get_name(s->streams[0]->codecpar->codec_id)); return ret; } end_guid(pb, start); @@ -610,7 +598,6 @@ } avio_seek(pb, file_size, SEEK_SET); - avio_flush(pb); } return 0; @@ -627,6 +614,6 @@ .write_packet = wav_write_packet, .write_trailer = w64_write_trailer, .flags = AVFMT_TS_NONSTRICT, - .codec_tag = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 }, + .codec_tag = ff_wav_codec_tags_list, }; #endif /* CONFIG_W64_MUXER */ diff -Nru ffmpeg-4.2.2/libavformat/wc3movie.c ffmpeg-4.4/libavformat/wc3movie.c --- ffmpeg-4.2.2/libavformat/wc3movie.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/wc3movie.c 2021-04-08 21:28:40.000000000 +0000 @@ -69,10 +69,19 @@ int video_stream_index; int audio_stream_index; - AVPacket vpkt; + AVPacket *vpkt; } Wc3DemuxContext; +static int wc3_read_close(AVFormatContext *s) +{ + Wc3DemuxContext *wc3 = s->priv_data; + + av_packet_free(&wc3->vpkt); + + return 0; +} + static int wc3_probe(const AVProbeData *p) { if (p->buf_size < 12) @@ -100,8 +109,9 @@ wc3->height = WC3_DEFAULT_HEIGHT; wc3->pts = 0; wc3->video_stream_index = wc3->audio_stream_index = 0; - av_init_packet(&wc3->vpkt); - wc3->vpkt.data = NULL; wc3->vpkt.size = 0; + wc3->vpkt = av_packet_alloc(); + if (!wc3->vpkt) + return AVERROR(ENOMEM); /* skip the first 3 32-bit numbers */ avio_skip(pb, 12); @@ -129,9 +139,15 @@ /* load up the name */ buffer = av_malloc(size+1); if (!buffer) - return AVERROR(ENOMEM); - if ((ret = avio_read(pb, buffer, size)) != size) - return AVERROR(EIO); + if (!buffer) { + ret = AVERROR(ENOMEM); + goto fail; + } + if ((ret = avio_read(pb, buffer, size)) != size) { + av_freep(&buffer); + ret = AVERROR(EIO); + goto fail; + } buffer[size] = 0; av_dict_set(&s->metadata, "title", buffer, AV_DICT_DONT_STRDUP_VAL); @@ -146,27 +162,32 @@ case PALT_TAG: /* one of several palettes */ avio_seek(pb, -8, SEEK_CUR); - av_append_packet(pb, &wc3->vpkt, 8 + PALETTE_SIZE); + av_append_packet(pb, wc3->vpkt, 8 + PALETTE_SIZE); break; default: av_log(s, AV_LOG_ERROR, "unrecognized WC3 chunk: %s\n", av_fourcc2str(fourcc_tag)); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } fourcc_tag = avio_rl32(pb); /* chunk sizes are 16-bit aligned */ size = (avio_rb32(pb) + 1) & (~1); - if (avio_feof(pb)) - return AVERROR(EIO); + if (avio_feof(pb)) { + ret = AVERROR(EIO); + goto fail; + } } while (fourcc_tag != BRCH_TAG); /* initialize the decoder streams */ st = avformat_new_stream(s, NULL); - if (!st) - return AVERROR(ENOMEM); + if (!st) { + ret = AVERROR(ENOMEM); + goto fail; + } avpriv_set_pts_info(st, 33, 1, WC3_FRAME_FPS); wc3->video_stream_index = st->index; st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; @@ -176,8 +197,10 @@ st->codecpar->height = wc3->height; st = avformat_new_stream(s, NULL); - if (!st) - return AVERROR(ENOMEM); + if (!st) { + ret = AVERROR(ENOMEM); + goto fail; + } avpriv_set_pts_info(st, 33, 1, WC3_FRAME_FPS); wc3->audio_stream_index = st->index; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; @@ -192,6 +215,9 @@ st->codecpar->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS; return 0; +fail: + wc3_read_close(s); + return ret; } static int wc3_read_packet(AVFormatContext *s, @@ -222,18 +248,17 @@ case SHOT_TAG: /* load up new palette */ avio_seek(pb, -8, SEEK_CUR); - av_append_packet(pb, &wc3->vpkt, 8 + 4); + av_append_packet(pb, wc3->vpkt, 8 + 4); break; case VGA__TAG: /* send out video chunk */ avio_seek(pb, -8, SEEK_CUR); - ret= av_append_packet(pb, &wc3->vpkt, 8 + size); + ret= av_append_packet(pb, wc3->vpkt, 8 + size); // ignore error if we have some data - if (wc3->vpkt.size > 0) + if (wc3->vpkt->size > 0) ret = 0; - *pkt = wc3->vpkt; - wc3->vpkt.data = NULL; wc3->vpkt.size = 0; + av_packet_move_ref(pkt, wc3->vpkt); pkt->stream_index = wc3->video_stream_index; pkt->pts = wc3->pts; packet_read = 1; @@ -284,16 +309,6 @@ return ret; } -static int wc3_read_close(AVFormatContext *s) -{ - Wc3DemuxContext *wc3 = s->priv_data; - - if (wc3->vpkt.size > 0) - av_packet_unref(&wc3->vpkt); - - return 0; -} - AVInputFormat ff_wc3_demuxer = { .name = "wc3movie", .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III movie"), diff -Nru ffmpeg-4.2.2/libavformat/webm_chunk.c ffmpeg-4.4/libavformat/webm_chunk.c --- ffmpeg-4.2.2/libavformat/webm_chunk.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/webm_chunk.c 2020-07-11 10:39:30.000000000 +0000 @@ -24,90 +24,130 @@ * chunk, followed by data chunks where each Cluster is written out as a Chunk. */ -#include -#include - #include "avformat.h" #include "avio.h" #include "avio_internal.h" #include "internal.h" -#include "libavutil/avassert.h" #include "libavutil/log.h" #include "libavutil/opt.h" -#include "libavutil/avstring.h" -#include "libavutil/parseutils.h" #include "libavutil/mathematics.h" -#include "libavutil/time.h" -#include "libavutil/time_internal.h" -#include "libavutil/timestamp.h" #define MAX_FILENAME_SIZE 1024 typedef struct WebMChunkContext { const AVClass *class; - int chunk_start_index; char *header_filename; int chunk_duration; int chunk_index; char *http_method; uint64_t duration_written; int64_t prev_pts; - ff_const59 AVOutputFormat *oformat; AVFormatContext *avf; + int header_written; } WebMChunkContext; -static int chunk_mux_init(AVFormatContext *s) +static int webm_chunk_init(AVFormatContext *s) { WebMChunkContext *wc = s->priv_data; + ff_const59 AVOutputFormat *oformat; AVFormatContext *oc; + AVStream *st, *ost = s->streams[0]; + AVDictionary *dict = NULL; int ret; - ret = avformat_alloc_output_context2(&wc->avf, wc->oformat, NULL, NULL); + // DASH Streams can only have one track per file. + if (s->nb_streams != 1) + return AVERROR(EINVAL); + + if (!wc->header_filename) { + av_log(s, AV_LOG_ERROR, "No header filename provided\n"); + return AVERROR(EINVAL); + } + + wc->prev_pts = AV_NOPTS_VALUE; + + oformat = av_guess_format("webm", s->url, "video/webm"); + if (!oformat) + return AVERROR_MUXER_NOT_FOUND; + + ret = avformat_alloc_output_context2(&wc->avf, oformat, NULL, NULL); if (ret < 0) return ret; oc = wc->avf; - oc->interrupt_callback = s->interrupt_callback; - oc->max_delay = s->max_delay; - av_dict_copy(&oc->metadata, s->metadata, 0); - - *(const AVClass**)oc->priv_data = oc->oformat->priv_class; - av_opt_set_defaults(oc->priv_data); - av_opt_set_int(oc->priv_data, "dash", 1, 0); - av_opt_set_int(oc->priv_data, "cluster_time_limit", wc->chunk_duration, 0); - av_opt_set_int(oc->priv_data, "live", 1, 0); + ff_format_set_url(oc, wc->header_filename); + wc->header_filename = NULL; + + oc->interrupt_callback = s->interrupt_callback; + oc->max_delay = s->max_delay; + oc->flags = s->flags & ~AVFMT_FLAG_FLUSH_PACKETS; + oc->strict_std_compliance = s->strict_std_compliance; + oc->avoid_negative_ts = s->avoid_negative_ts; - oc->streams = s->streams; - oc->nb_streams = s->nb_streams; + oc->flush_packets = 0; + + if ((ret = av_dict_copy(&oc->metadata, s->metadata, 0)) < 0) + return ret; + + if (!(st = avformat_new_stream(oc, NULL))) + return AVERROR(ENOMEM); + + if ((ret = avcodec_parameters_copy(st->codecpar, ost->codecpar)) < 0 || + (ret = av_dict_copy(&st->metadata, ost->metadata, 0)) < 0) + return ret; + + st->sample_aspect_ratio = ost->sample_aspect_ratio; + st->disposition = ost->disposition; + avpriv_set_pts_info(st, ost->pts_wrap_bits, ost->time_base.num, + ost->time_base.den); + + if (wc->http_method) + if ((ret = av_dict_set(&dict, "method", wc->http_method, 0)) < 0) + return ret; + ret = s->io_open(s, &oc->pb, oc->url, AVIO_FLAG_WRITE, &dict); + av_dict_free(&dict); + if (ret < 0) + return ret; + oc->pb->seekable = 0; + + if ((ret = av_dict_set_int(&dict, "dash", 1, 0)) < 0 || + (ret = av_dict_set_int(&dict, "cluster_time_limit", + wc->chunk_duration, 0)) < 0 || + (ret = av_dict_set_int(&dict, "live", 1, 0)) < 0) + goto fail; + + ret = avformat_init_output(oc, &dict); +fail: + av_dict_free(&dict); + if (ret < 0) + return ret; + + // Copy the timing info back to the original stream + // so that the timestamps of the packets are directly usable + avpriv_set_pts_info(ost, st->pts_wrap_bits, st->time_base.num, + st->time_base.den); + + // This ensures that the timestamps will already be properly shifted + // when the packets arrive here, so we don't need to shift again. + s->avoid_negative_ts = oc->avoid_negative_ts; + s->internal->avoid_negative_ts_use_pts = + oc->internal->avoid_negative_ts_use_pts; + oc->avoid_negative_ts = 0; return 0; } -static int get_chunk_filename(AVFormatContext *s, int is_header, char filename[MAX_FILENAME_SIZE]) +static int get_chunk_filename(AVFormatContext *s, char filename[MAX_FILENAME_SIZE]) { WebMChunkContext *wc = s->priv_data; - AVFormatContext *oc = wc->avf; if (!filename) { return AVERROR(EINVAL); } - if (is_header) { - int len; - if (!wc->header_filename) { - av_log(oc, AV_LOG_ERROR, "No header filename provided\n"); - return AVERROR(EINVAL); - } - len = av_strlcpy(filename, wc->header_filename, MAX_FILENAME_SIZE); - if (len >= MAX_FILENAME_SIZE) { - av_log(oc, AV_LOG_ERROR, "Header filename too long\n"); - return AVERROR(EINVAL); - } - } else { - if (av_get_frame_filename(filename, MAX_FILENAME_SIZE, - s->url, wc->chunk_index - 1) < 0) { - av_log(oc, AV_LOG_ERROR, "Invalid chunk filename template '%s'\n", s->url); - return AVERROR(EINVAL); - } + if (av_get_frame_filename(filename, MAX_FILENAME_SIZE, + s->url, wc->chunk_index - 1) < 0) { + av_log(s, AV_LOG_ERROR, "Invalid chunk filename template '%s'\n", s->url); + return AVERROR(EINVAL); } return 0; } @@ -115,49 +155,14 @@ static int webm_chunk_write_header(AVFormatContext *s) { WebMChunkContext *wc = s->priv_data; - AVFormatContext *oc = NULL; + AVFormatContext *oc = wc->avf; int ret; - int i; - AVDictionary *options = NULL; - char oc_filename[MAX_FILENAME_SIZE]; - char *oc_url; - - // DASH Streams can only have either one track per file. - if (s->nb_streams != 1) { return AVERROR_INVALIDDATA; } - - wc->chunk_index = wc->chunk_start_index; - wc->oformat = av_guess_format("webm", s->url, "video/webm"); - if (!wc->oformat) - return AVERROR_MUXER_NOT_FOUND; - wc->prev_pts = AV_NOPTS_VALUE; - ret = chunk_mux_init(s); - if (ret < 0) - return ret; - oc = wc->avf; - ret = get_chunk_filename(s, 1, oc_filename); - if (ret < 0) - return ret; - oc_url = av_strdup(oc_filename); - if (!oc_url) - return AVERROR(ENOMEM); - ff_format_set_url(oc, oc_url); - if (wc->http_method) - av_dict_set(&options, "method", wc->http_method, 0); - ret = s->io_open(s, &oc->pb, oc->url, AVIO_FLAG_WRITE, &options); - av_dict_free(&options); - if (ret < 0) - return ret; - - oc->pb->seekable = 0; - ret = oc->oformat->write_header(oc); + ret = avformat_write_header(oc, NULL); + ff_format_io_close(s, &oc->pb); + wc->header_written = 1; if (ret < 0) return ret; - ff_format_io_close(s, &oc->pb); - for (i = 0; i < s->nb_streams; i++) { - // ms precision is the de-facto standard timescale for mkv files. - avpriv_set_pts_info(s->streams[i], 64, 1, 1000); - } return 0; } @@ -190,21 +195,22 @@ if (flush) // Flush the cluster in WebM muxer. - oc->oformat->write_packet(oc, NULL); + av_write_frame(oc, NULL); buffer_size = avio_close_dyn_buf(oc->pb, &buffer); oc->pb = NULL; - ret = get_chunk_filename(s, 0, filename); + ret = get_chunk_filename(s, filename); if (ret < 0) goto fail; if (wc->http_method) - av_dict_set(&options, "method", wc->http_method, 0); + if ((ret = av_dict_set(&options, "method", wc->http_method, 0)) < 0) + goto fail; ret = s->io_open(s, &pb, filename, AVIO_FLAG_WRITE, &options); + av_dict_free(&options); if (ret < 0) goto fail; avio_write(pb, buffer, buffer_size); ff_format_io_close(s, &pb); fail: - av_dict_free(&options); av_free(buffer); return (ret < 0) ? ret : 0; } @@ -237,9 +243,8 @@ } } - ret = oc->oformat->write_packet(oc, pkt); - - return ret; + // We only have one stream, so use the non-interleaving av_write_frame. + return av_write_frame(oc, pkt); } static int webm_chunk_write_trailer(AVFormatContext *s) @@ -251,27 +256,38 @@ if (!oc->pb) { ret = chunk_start(s); if (ret < 0) - goto fail; + return ret; } - oc->oformat->write_trailer(oc); - ret = chunk_end(s, 0); -fail: - oc->streams = NULL; - oc->nb_streams = 0; - avformat_free_context(oc); - return ret; + ret = av_write_trailer(oc); + if (ret < 0) + return ret; + return chunk_end(s, 0); +} + +static void webm_chunk_deinit(AVFormatContext *s) +{ + WebMChunkContext *wc = s->priv_data; + + if (!wc->avf) + return; + + if (wc->header_written) + ffio_free_dyn_buf(&wc->avf->pb); + else + ff_format_io_close(s, &wc->avf->pb); + avformat_free_context(wc->avf); + wc->avf = NULL; } #define OFFSET(x) offsetof(WebMChunkContext, x) static const AVOption options[] = { - { "chunk_start_index", "start index of the chunk", OFFSET(chunk_start_index), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, - { "header", "filename of the header where the initialization data will be written", OFFSET(header_filename), AV_OPT_TYPE_STRING, { 0 }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, + { "chunk_start_index", "start index of the chunk", OFFSET(chunk_index), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, + { "header", "filename of the header where the initialization data will be written", OFFSET(header_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, { "audio_chunk_duration", "duration of each chunk in milliseconds", OFFSET(chunk_duration), AV_OPT_TYPE_INT, {.i64 = 5000}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, { "method", "set the HTTP method", OFFSET(http_method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, { NULL }, }; -#if CONFIG_WEBM_CHUNK_MUXER static const AVClass webm_chunk_class = { .class_name = "WebM Chunk Muxer", .item_name = av_default_item_name, @@ -287,9 +303,10 @@ .flags = AVFMT_NOFILE | AVFMT_GLOBALHEADER | AVFMT_NEEDNUMBER | AVFMT_TS_NONSTRICT, .priv_data_size = sizeof(WebMChunkContext), + .init = webm_chunk_init, .write_header = webm_chunk_write_header, .write_packet = webm_chunk_write_packet, .write_trailer = webm_chunk_write_trailer, + .deinit = webm_chunk_deinit, .priv_class = &webm_chunk_class, }; -#endif diff -Nru ffmpeg-4.2.2/libavformat/webmdashenc.c ffmpeg-4.4/libavformat/webmdashenc.c --- ffmpeg-4.2.2/libavformat/webmdashenc.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/webmdashenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -31,7 +31,6 @@ #include #include "avformat.h" -#include "avio_internal.h" #include "matroska.h" #include "libavutil/avstring.h" @@ -57,22 +56,11 @@ char *utc_timing_url; double time_shift_buffer_depth; int minimum_update_period; - int debug_mode; } WebMDashMuxContext; static const char *get_codec_name(int codec_id) { - switch (codec_id) { - case AV_CODEC_ID_VP8: - return "vp8"; - case AV_CODEC_ID_VP9: - return "vp9"; - case AV_CODEC_ID_VORBIS: - return "vorbis"; - case AV_CODEC_ID_OPUS: - return "opus"; - } - return NULL; + return avcodec_descriptor_get(codec_id)->name; } static double get_duration(AVFormatContext *s) @@ -91,19 +79,20 @@ static int write_header(AVFormatContext *s) { WebMDashMuxContext *w = s->priv_data; + AVIOContext *pb = s->pb; double min_buffer_time = 1.0; - avio_printf(s->pb, "\n"); - avio_printf(s->pb, "pb, " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"); - avio_printf(s->pb, " xmlns=\"urn:mpeg:DASH:schema:MPD:2011\"\n"); - avio_printf(s->pb, " xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011\"\n"); - avio_printf(s->pb, " type=\"%s\"\n", w->is_live ? "dynamic" : "static"); + avio_printf(pb, "\n"); + avio_printf(pb, "is_live ? "dynamic" : "static"); if (!w->is_live) { - avio_printf(s->pb, " mediaPresentationDuration=\"PT%gS\"\n", + avio_printf(pb, " mediaPresentationDuration=\"PT%gS\"\n", get_duration(s)); } - avio_printf(s->pb, " minBufferTime=\"PT%gS\"\n", min_buffer_time); - avio_printf(s->pb, " profiles=\"%s\"%s", + avio_printf(pb, " minBufferTime=\"PT%gS\"\n", min_buffer_time); + avio_printf(pb, " profiles=\"%s\"%s", w->is_live ? "urn:mpeg:dash:profile:isoff-live:2011" : "urn:webm:dash:profile:webm-on-demand:2012", w->is_live ? "\n" : ">\n"); if (w->is_live) { @@ -114,17 +103,17 @@ if (!strftime(gmt_iso, 21, "%Y-%m-%dT%H:%M:%SZ", gmt)) { return AVERROR_UNKNOWN; } - if (w->debug_mode) { + if (s->flags & AVFMT_FLAG_BITEXACT) { av_strlcpy(gmt_iso, "", 1); } - avio_printf(s->pb, " availabilityStartTime=\"%s\"\n", gmt_iso); - avio_printf(s->pb, " timeShiftBufferDepth=\"PT%gS\"\n", w->time_shift_buffer_depth); - avio_printf(s->pb, " minimumUpdatePeriod=\"PT%dS\"", w->minimum_update_period); - avio_printf(s->pb, ">\n"); + avio_printf(pb, " availabilityStartTime=\"%s\"\n", gmt_iso); + avio_printf(pb, " timeShiftBufferDepth=\"PT%gS\"\n", w->time_shift_buffer_depth); + avio_printf(pb, " minimumUpdatePeriod=\"PT%dS\"", w->minimum_update_period); + avio_printf(pb, ">\n"); if (w->utc_timing_url) { - avio_printf(s->pb, "pb, " schemeIdUri=\"urn:mpeg:dash:utc:http-iso:2014\"\n"); - avio_printf(s->pb, " value=\"%s\"/>\n", w->utc_timing_url); + avio_printf(pb, "\n", w->utc_timing_url); } } return 0; @@ -135,7 +124,8 @@ avio_printf(s->pb, "\n"); } -static int subsegment_alignment(AVFormatContext *s, AdaptationSet *as) { +static int subsegment_alignment(AVFormatContext *s, const AdaptationSet *as) +{ int i; AVDictionaryEntry *gold = av_dict_get(s->streams[as->streams[0]]->metadata, CUE_TIMESTAMPS, NULL, 0); @@ -143,26 +133,30 @@ for (i = 1; i < as->nb_streams; i++) { AVDictionaryEntry *ts = av_dict_get(s->streams[as->streams[i]]->metadata, CUE_TIMESTAMPS, NULL, 0); - if (!ts || strncmp(gold->value, ts->value, strlen(gold->value))) return 0; + if (!ts || !av_strstart(ts->value, gold->value, NULL)) return 0; } return 1; } -static int bitstream_switching(AVFormatContext *s, AdaptationSet *as) { +static int bitstream_switching(AVFormatContext *s, const AdaptationSet *as) +{ int i; - AVDictionaryEntry *gold_track_num = av_dict_get(s->streams[as->streams[0]]->metadata, + const AVStream *gold_st = s->streams[as->streams[0]]; + AVDictionaryEntry *gold_track_num = av_dict_get(gold_st->metadata, TRACK_NUMBER, NULL, 0); - AVCodecParameters *gold_par = s->streams[as->streams[0]]->codecpar; + AVCodecParameters *gold_par = gold_st->codecpar; if (!gold_track_num) return 0; for (i = 1; i < as->nb_streams; i++) { - AVDictionaryEntry *track_num = av_dict_get(s->streams[as->streams[i]]->metadata, + const AVStream *st = s->streams[as->streams[i]]; + AVDictionaryEntry *track_num = av_dict_get(st->metadata, TRACK_NUMBER, NULL, 0); - AVCodecParameters *par = s->streams[as->streams[i]]->codecpar; + AVCodecParameters *par = st->codecpar; if (!track_num || - strncmp(gold_track_num->value, track_num->value, strlen(gold_track_num->value)) || + !av_strstart(track_num->value, gold_track_num->value, NULL) || gold_par->codec_id != par->codec_id || gold_par->extradata_size != par->extradata_size || - memcmp(gold_par->extradata, par->extradata, par->extradata_size)) { + (par->extradata_size > 0 && + memcmp(gold_par->extradata, par->extradata, par->extradata_size))) { return 0; } } @@ -173,60 +167,65 @@ * Writes a Representation within an Adaptation Set. Returns 0 on success and * < 0 on failure. */ -static int write_representation(AVFormatContext *s, AVStream *stream, char *id, +static int write_representation(AVFormatContext *s, AVStream *st, char *id, int output_width, int output_height, - int output_sample_rate) { + int output_sample_rate) +{ WebMDashMuxContext *w = s->priv_data; - AVDictionaryEntry *irange = av_dict_get(stream->metadata, INITIALIZATION_RANGE, NULL, 0); - AVDictionaryEntry *cues_start = av_dict_get(stream->metadata, CUES_START, NULL, 0); - AVDictionaryEntry *cues_end = av_dict_get(stream->metadata, CUES_END, NULL, 0); - AVDictionaryEntry *filename = av_dict_get(stream->metadata, FILENAME, NULL, 0); - AVDictionaryEntry *bandwidth = av_dict_get(stream->metadata, BANDWIDTH, NULL, 0); + AVIOContext *pb = s->pb; + const AVCodecParameters *par = st->codecpar; + AVDictionaryEntry *bandwidth = av_dict_get(st->metadata, BANDWIDTH, NULL, 0); const char *bandwidth_str; - if ((w->is_live && (!filename)) || - (!w->is_live && (!irange || !cues_start || !cues_end || !filename || !bandwidth))) { - return AVERROR_INVALIDDATA; - } - avio_printf(s->pb, "is_live && !bandwidth) { - bandwidth_str = (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ? "128000" : "1000000"; - } else { + avio_printf(pb, "value; + } else if (w->is_live) { + // if bandwidth for live was not provided, use a default + bandwidth_str = (par->codec_type == AVMEDIA_TYPE_AUDIO) ? "128000" : "1000000"; + } else { + return AVERROR(EINVAL); } - avio_printf(s->pb, " bandwidth=\"%s\"", bandwidth_str); - if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && output_width) - avio_printf(s->pb, " width=\"%d\"", stream->codecpar->width); - if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && output_height) - avio_printf(s->pb, " height=\"%d\"", stream->codecpar->height); - if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && output_sample_rate) - avio_printf(s->pb, " audioSamplingRate=\"%d\"", stream->codecpar->sample_rate); + avio_printf(pb, " bandwidth=\"%s\"", bandwidth_str); + if (par->codec_type == AVMEDIA_TYPE_VIDEO && output_width) + avio_printf(pb, " width=\"%d\"", par->width); + if (par->codec_type == AVMEDIA_TYPE_VIDEO && output_height) + avio_printf(pb, " height=\"%d\"", par->height); + if (par->codec_type == AVMEDIA_TYPE_AUDIO && output_sample_rate) + avio_printf(pb, " audioSamplingRate=\"%d\"", par->sample_rate); if (w->is_live) { // For live streams, Codec and Mime Type always go in the Representation tag. - avio_printf(s->pb, " codecs=\"%s\"", get_codec_name(stream->codecpar->codec_id)); - avio_printf(s->pb, " mimeType=\"%s/webm\"", - stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); + avio_printf(pb, " codecs=\"%s\"", get_codec_name(par->codec_id)); + avio_printf(pb, " mimeType=\"%s/webm\"", + par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); // For live streams, subsegments always start with key frames. So this // is always 1. - avio_printf(s->pb, " startsWithSAP=\"1\""); - avio_printf(s->pb, ">"); + avio_printf(pb, " startsWithSAP=\"1\""); + avio_printf(pb, ">"); } else { - avio_printf(s->pb, ">\n"); - avio_printf(s->pb, "%s\n", filename->value); - avio_printf(s->pb, "pb, " indexRange=\"%s-%s\">\n", cues_start->value, cues_end->value); - avio_printf(s->pb, "pb, " range=\"0-%s\" />\n", irange->value); - avio_printf(s->pb, "\n"); + AVDictionaryEntry *irange = av_dict_get(st->metadata, INITIALIZATION_RANGE, NULL, 0); + AVDictionaryEntry *cues_start = av_dict_get(st->metadata, CUES_START, NULL, 0); + AVDictionaryEntry *cues_end = av_dict_get(st->metadata, CUES_END, NULL, 0); + AVDictionaryEntry *filename = av_dict_get(st->metadata, FILENAME, NULL, 0); + if (!irange || !cues_start || !cues_end || !filename) + return AVERROR(EINVAL); + + avio_printf(pb, ">\n"); + avio_printf(pb, "%s\n", filename->value); + avio_printf(pb, "\n", cues_start->value, cues_end->value); + avio_printf(pb, "\n", irange->value); + avio_printf(pb, "\n"); } - avio_printf(s->pb, "\n"); + avio_printf(pb, "\n"); return 0; } /* * Checks if width of all streams are the same. Returns 1 if true, 0 otherwise. */ -static int check_matching_width(AVFormatContext *s, AdaptationSet *as) { +static int check_matching_width(AVFormatContext *s, const AdaptationSet *as) +{ int first_width, i; if (as->nb_streams < 2) return 1; first_width = s->streams[as->streams[0]]->codecpar->width; @@ -239,7 +238,8 @@ /* * Checks if height of all streams are the same. Returns 1 if true, 0 otherwise. */ -static int check_matching_height(AVFormatContext *s, AdaptationSet *as) { +static int check_matching_height(AVFormatContext *s, const AdaptationSet *as) +{ int first_height, i; if (as->nb_streams < 2) return 1; first_height = s->streams[as->streams[0]]->codecpar->height; @@ -252,7 +252,8 @@ /* * Checks if sample rate of all streams are the same. Returns 1 if true, 0 otherwise. */ -static int check_matching_sample_rate(AVFormatContext *s, AdaptationSet *as) { +static int check_matching_sample_rate(AVFormatContext *s, const AdaptationSet *as) +{ int first_sample_rate, i; if (as->nb_streams < 2) return 1; first_sample_rate = s->streams[as->streams[0]]->codecpar->sample_rate; @@ -262,7 +263,8 @@ return 1; } -static void free_adaptation_sets(AVFormatContext *s) { +static void free_adaptation_sets(AVFormatContext *s) +{ WebMDashMuxContext *w = s->priv_data; int i; for (i = 0; i < w->nb_as; i++) { @@ -273,70 +275,24 @@ } /* - * Parses a live header filename and computes the representation id, - * initialization pattern and the media pattern. Pass NULL if you don't want to - * compute any of those 3. Returns 0 on success and non-zero on failure. + * Parses a live header filename and returns the position of the '_' and '.' + * delimiting and . * * Name of the header file should conform to the following pattern: * _.hdr where can be * anything. The chunks should be named according to the following pattern: * __.chk */ -static int parse_filename(char *filename, char **representation_id, - char **initialization_pattern, char **media_pattern) { - char *underscore_pos = NULL; - char *period_pos = NULL; - char *temp_pos = NULL; - char *filename_str = av_strdup(filename); - int ret = 0; - - if (!filename_str) { - ret = AVERROR(ENOMEM); - goto end; - } - temp_pos = av_stristr(filename_str, "_"); - while (temp_pos) { - underscore_pos = temp_pos + 1; - temp_pos = av_stristr(temp_pos + 1, "_"); - } - if (!underscore_pos) { - ret = AVERROR_INVALIDDATA; - goto end; - } - period_pos = av_stristr(underscore_pos, "."); - if (!period_pos) { - ret = AVERROR_INVALIDDATA; - goto end; - } - *(underscore_pos - 1) = 0; - if (representation_id) { - *representation_id = av_malloc(period_pos - underscore_pos + 1); - if (!(*representation_id)) { - ret = AVERROR(ENOMEM); - goto end; - } - av_strlcpy(*representation_id, underscore_pos, period_pos - underscore_pos + 1); - } - if (initialization_pattern) { - *initialization_pattern = av_asprintf("%s_$RepresentationID$.hdr", - filename_str); - if (!(*initialization_pattern)) { - ret = AVERROR(ENOMEM); - goto end; - } - } - if (media_pattern) { - *media_pattern = av_asprintf("%s_$RepresentationID$_$Number$.chk", - filename_str); - if (!(*media_pattern)) { - ret = AVERROR(ENOMEM); - goto end; - } - } - -end: - av_freep(&filename_str); - return ret; +static int split_filename(char *filename, char **underscore_pos, + char **period_pos) +{ + *underscore_pos = strrchr(filename, '_'); + if (!*underscore_pos) + return AVERROR(EINVAL); + *period_pos = strchr(*underscore_pos, '.'); + if (!*period_pos) + return AVERROR(EINVAL); + return 0; } /* @@ -346,8 +302,10 @@ { WebMDashMuxContext *w = s->priv_data; AdaptationSet *as = &w->as[as_index]; - AVCodecParameters *par = s->streams[as->streams[0]]->codecpar; + const AVStream *st = s->streams[as->streams[0]]; + AVCodecParameters *par = st->codecpar; AVDictionaryEntry *lang; + AVIOContext *pb = s->pb; int i; static const char boolean[2][6] = { "false", "true" }; int subsegmentStartsWithSAP = 1; @@ -358,30 +316,31 @@ // in the Representation tag. int width_in_as = 1, height_in_as = 1, sample_rate_in_as = 1; if (par->codec_type == AVMEDIA_TYPE_VIDEO) { - width_in_as = !w->is_live && check_matching_width(s, as); + width_in_as = !w->is_live && check_matching_width (s, as); height_in_as = !w->is_live && check_matching_height(s, as); } else { sample_rate_in_as = !w->is_live && check_matching_sample_rate(s, as); } - avio_printf(s->pb, "id); - avio_printf(s->pb, " mimeType=\"%s/webm\"", + avio_printf(pb, "id); + avio_printf(pb, " mimeType=\"%s/webm\"", par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); - avio_printf(s->pb, " codecs=\"%s\"", get_codec_name(par->codec_id)); + avio_printf(pb, " codecs=\"%s\"", get_codec_name(par->codec_id)); - lang = av_dict_get(s->streams[as->streams[0]]->metadata, "language", NULL, 0); - if (lang) avio_printf(s->pb, " lang=\"%s\"", lang->value); + lang = av_dict_get(st->metadata, "language", NULL, 0); + if (lang) + avio_printf(pb, " lang=\"%s\"", lang->value); if (par->codec_type == AVMEDIA_TYPE_VIDEO && width_in_as) - avio_printf(s->pb, " width=\"%d\"", par->width); + avio_printf(pb, " width=\"%d\"", par->width); if (par->codec_type == AVMEDIA_TYPE_VIDEO && height_in_as) - avio_printf(s->pb, " height=\"%d\"", par->height); + avio_printf(pb, " height=\"%d\"", par->height); if (par->codec_type == AVMEDIA_TYPE_AUDIO && sample_rate_in_as) - avio_printf(s->pb, " audioSamplingRate=\"%d\"", par->sample_rate); + avio_printf(pb, " audioSamplingRate=\"%d\"", par->sample_rate); - avio_printf(s->pb, " bitstreamSwitching=\"%s\"", + avio_printf(pb, " bitstreamSwitching=\"%s\"", boolean[bitstream_switching(s, as)]); - avio_printf(s->pb, " subsegmentAlignment=\"%s\"", + avio_printf(pb, " subsegmentAlignment=\"%s\"", boolean[w->is_live || subsegment_alignment(s, as)]); for (i = 0; i < as->nb_streams; i++) { @@ -389,66 +348,60 @@ CLUSTER_KEYFRAME, NULL, 0); if (!w->is_live && (!kf || !strncmp(kf->value, "0", 1))) subsegmentStartsWithSAP = 0; } - avio_printf(s->pb, " subsegmentStartsWithSAP=\"%d\"", subsegmentStartsWithSAP); - avio_printf(s->pb, ">\n"); + avio_printf(pb, " subsegmentStartsWithSAP=\"%d\"", subsegmentStartsWithSAP); + avio_printf(pb, ">\n"); if (w->is_live) { AVDictionaryEntry *filename = - av_dict_get(s->streams[as->streams[0]]->metadata, FILENAME, NULL, 0); - char *initialization_pattern = NULL; - char *media_pattern = NULL; - int ret = parse_filename(filename->value, NULL, &initialization_pattern, - &media_pattern); + av_dict_get(st->metadata, FILENAME, NULL, 0); + char *underscore_pos, *period_pos; + int ret; + if (!filename) + return AVERROR(EINVAL); + ret = split_filename(filename->value, &underscore_pos, &period_pos); if (ret) return ret; - avio_printf(s->pb, "\n", + *underscore_pos = '\0'; + avio_printf(pb, "\n", par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio"); - avio_printf(s->pb, "pb, " timescale=\"1000\""); - avio_printf(s->pb, " duration=\"%d\"", w->chunk_duration); - avio_printf(s->pb, " media=\"%s\"", media_pattern); - avio_printf(s->pb, " startNumber=\"%d\"", w->chunk_start_index); - avio_printf(s->pb, " initialization=\"%s\"", initialization_pattern); - avio_printf(s->pb, "/>\n"); - av_free(initialization_pattern); - av_free(media_pattern); + avio_printf(pb, "chunk_duration); + avio_printf(pb, " media=\"%s_$RepresentationID$_$Number$.chk\"", + filename->value); + avio_printf(pb, " startNumber=\"%d\"", w->chunk_start_index); + avio_printf(pb, " initialization=\"%s_$RepresentationID$.hdr\"", + filename->value); + avio_printf(pb, "/>\n"); + *underscore_pos = '_'; } for (i = 0; i < as->nb_streams; i++) { - char *representation_id = NULL; + char buf[25], *representation_id = buf, *underscore_pos, *period_pos; + AVStream *st = s->streams[as->streams[i]]; int ret; if (w->is_live) { AVDictionaryEntry *filename = - av_dict_get(s->streams[as->streams[i]]->metadata, FILENAME, NULL, 0); + av_dict_get(st->metadata, FILENAME, NULL, 0); if (!filename) return AVERROR(EINVAL); - if (ret = parse_filename(filename->value, &representation_id, NULL, NULL)) + ret = split_filename(filename->value, &underscore_pos, &period_pos); + if (ret < 0) return ret; + representation_id = underscore_pos + 1; + *period_pos = '\0'; } else { - representation_id = av_asprintf("%d", w->representation_id++); - if (!representation_id) return AVERROR(ENOMEM); + snprintf(buf, sizeof(buf), "%d", w->representation_id++); } - ret = write_representation(s, s->streams[as->streams[i]], - representation_id, !width_in_as, + ret = write_representation(s, st, representation_id, !width_in_as, !height_in_as, !sample_rate_in_as); - av_free(representation_id); if (ret) return ret; + if (w->is_live) + *period_pos = '.'; } avio_printf(s->pb, "\n"); return 0; } -static int to_integer(char *p, int len) -{ - int ret; - char *q = av_malloc(sizeof(char) * len); - if (!q) - return AVERROR(ENOMEM); - av_strlcpy(q, p, len); - ret = atoi(q); - av_free(q); - return ret; -} - static int parse_adaptation_sets(AVFormatContext *s) { WebMDashMuxContext *w = s->priv_data; @@ -461,10 +414,16 @@ } // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on state = new_set; - while (p < w->adaptation_sets + strlen(w->adaptation_sets)) { - if (*p == ' ') + while (1) { + if (*p == '\0') { + if (state == new_set) + break; + else + return AVERROR(EINVAL); + } else if (state == new_set && *p == ' ') { + p++; continue; - else if (state == new_set && !strncmp(p, "id=", 3)) { + } else if (state == new_set && !strncmp(p, "id=", 3)) { void *mem = av_realloc(w->as, sizeof(*w->as) * (w->nb_as + 1)); const char *comma; if (mem == NULL) @@ -489,17 +448,18 @@ state = parsing_streams; } else if (state == parsing_streams) { struct AdaptationSet *as = &w->as[w->nb_as - 1]; - q = p; - while (*q != '\0' && *q != ',' && *q != ' ') q++; - as->streams = av_realloc(as->streams, sizeof(*as->streams) * ++as->nb_streams); - if (as->streams == NULL) - return AVERROR(ENOMEM); - as->streams[as->nb_streams - 1] = to_integer(p, q - p + 1); - if (as->streams[as->nb_streams - 1] < 0 || - as->streams[as->nb_streams - 1] >= s->nb_streams) { + int64_t num; + int ret = av_reallocp_array(&as->streams, ++as->nb_streams, + sizeof(*as->streams)); + if (ret < 0) + return ret; + num = strtoll(p, &q, 10); + if (!av_isdigit(*p) || (*q != ' ' && *q != '\0' && *q != ',') || + num < 0 || num >= s->nb_streams) { av_log(s, AV_LOG_ERROR, "Invalid value for 'streams' in adapation_sets.\n"); return AVERROR(EINVAL); } + as->streams[as->nb_streams - 1] = num; if (*q == '\0') break; if (*q == ' ') state = new_set; p = ++q; @@ -516,6 +476,14 @@ double start = 0.0; int ret; WebMDashMuxContext *w = s->priv_data; + + for (unsigned i = 0; i < s->nb_streams; i++) { + enum AVCodecID codec_id = s->streams[i]->codecpar->codec_id; + if (codec_id != AV_CODEC_ID_VP8 && codec_id != AV_CODEC_ID_VP9 && + codec_id != AV_CODEC_ID_VORBIS && codec_id != AV_CODEC_ID_OPUS) + return AVERROR(EINVAL); + } + ret = parse_adaptation_sets(s); if (ret < 0) { goto fail; @@ -550,16 +518,9 @@ return AVERROR_EOF; } -static int webm_dash_manifest_write_trailer(AVFormatContext *s) -{ - free_adaptation_sets(s); - return 0; -} - #define OFFSET(x) offsetof(WebMDashMuxContext, x) static const AVOption options[] = { { "adaptation_sets", "Adaptation sets. Syntax: id=0,streams=0,1,2 id=1,streams=3,4 and so on", OFFSET(adaptation_sets), AV_OPT_TYPE_STRING, { 0 }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM }, - { "debug_mode", "[private option - users should never set this]. Create deterministic output", OFFSET(debug_mode), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, { "live", "create a live stream manifest", OFFSET(is_live), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, { "chunk_start_index", "start index of the chunk", OFFSET(chunk_start_index), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, { "chunk_duration_ms", "duration of each chunk (in milliseconds)", OFFSET(chunk_duration), AV_OPT_TYPE_INT, {.i64 = 1000}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, @@ -569,7 +530,6 @@ { NULL }, }; -#if CONFIG_WEBM_DASH_MANIFEST_MUXER static const AVClass webm_dash_class = { .class_name = "WebM DASH Manifest muxer", .item_name = av_default_item_name, @@ -585,7 +545,5 @@ .priv_data_size = sizeof(WebMDashMuxContext), .write_header = webm_dash_manifest_write_header, .write_packet = webm_dash_manifest_write_packet, - .write_trailer = webm_dash_manifest_write_trailer, .priv_class = &webm_dash_class, }; -#endif diff -Nru ffmpeg-4.2.2/libavformat/webpenc.c ffmpeg-4.4/libavformat/webpenc.c --- ffmpeg-4.2.2/libavformat/webpenc.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/webpenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -53,24 +53,22 @@ static int is_animated_webp_packet(AVPacket *pkt) { - if (pkt->size) { int skip = 0; unsigned flags = 0; if (pkt->size < 4) - return 0; + return AVERROR_INVALIDDATA; if (AV_RL32(pkt->data) == AV_RL32("RIFF")) skip = 12; - + // Safe to do this as a valid WebP bitstream is >=30 bytes. if (pkt->size < skip + 4) - return 0; + return AVERROR_INVALIDDATA; if (AV_RL32(pkt->data + skip) == AV_RL32("VP8X")) { flags |= pkt->data[skip + 4 + 4]; } if (flags & 2) // ANIMATION_FLAG is on return 1; - } return 0; } @@ -84,13 +82,9 @@ unsigned flags = 0; int vp8x = 0; - if (w->last_pkt.size < 4) - return 0; if (AV_RL32(w->last_pkt.data) == AV_RL32("RIFF")) skip = 12; - if (w->last_pkt.size < skip + 4) - return 0; // Safe to do this as a valid WebP bitstream is >=30 bytes. if (AV_RL32(w->last_pkt.data + skip) == AV_RL32("VP8X")) { flags |= w->last_pkt.data[skip + 4 + 4]; vp8x = 1; @@ -149,7 +143,14 @@ static int webp_write_packet(AVFormatContext *s, AVPacket *pkt) { WebpContext *w = s->priv_data; - w->using_webp_anim_encoder |= is_animated_webp_packet(pkt); + int ret; + + if (!pkt->size) + return 0; + ret = is_animated_webp_packet(pkt); + if (ret < 0) + return ret; + w->using_webp_anim_encoder |= ret; if (w->using_webp_anim_encoder) { avio_write(s->pb, pkt->data, pkt->size); @@ -190,6 +191,13 @@ return 0; } +static void webp_deinit(AVFormatContext *s) +{ + WebpContext *w = s->priv_data; + + av_packet_unref(&w->last_pkt); +} + #define OFFSET(x) offsetof(WebpContext, x) #define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { @@ -213,6 +221,7 @@ .write_header = webp_write_header, .write_packet = webp_write_packet, .write_trailer = webp_write_trailer, + .deinit = webp_deinit, .priv_class = &webp_muxer_class, .flags = AVFMT_VARIABLE_FPS, }; diff -Nru ffmpeg-4.2.2/libavformat/webvttdec.c ffmpeg-4.4/libavformat/webvttdec.c --- ffmpeg-4.2.2/libavformat/webvttdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/webvttdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -60,7 +60,7 @@ static int webvtt_read_header(AVFormatContext *s) { WebVTTContext *webvtt = s->priv_data; - AVBPrint header, cue; + AVBPrint cue; int res = 0; AVStream *st = avformat_new_stream(s, NULL); @@ -71,7 +71,6 @@ st->codecpar->codec_id = AV_CODEC_ID_WEBVTT; st->disposition |= webvtt->kind; - av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED); av_bprint_init(&cue, 0, AV_BPRINT_SIZE_UNLIMITED); for (;;) { @@ -126,7 +125,7 @@ break; /* optional cue settings */ - p += strcspn(p, "\n\t "); + p += strcspn(p, "\n\r\t "); while (*p == '\t' || *p == ' ') p++; settings = p; @@ -165,8 +164,9 @@ ff_subtitles_queue_finalize(s, &webvtt->q); end: + if (res < 0) + ff_subtitles_queue_clean(&webvtt->q); av_bprint_finalize(&cue, NULL); - av_bprint_finalize(&header, NULL); return res; } diff -Nru ffmpeg-4.2.2/libavformat/webvttenc.c ffmpeg-4.4/libavformat/webvttenc.c --- ffmpeg-4.2.2/libavformat/webvttenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/webvttenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -57,7 +57,6 @@ avpriv_set_pts_info(s, 64, 1, 1000); avio_printf(pb, "WEBVTT\n"); - avio_flush(pb); return 0; } @@ -65,7 +64,7 @@ static int webvtt_write_packet(AVFormatContext *ctx, AVPacket *pkt) { AVIOContext *pb = ctx->pb; - int id_size, settings_size; + buffer_size_t id_size, settings_size; uint8_t *id, *settings; avio_printf(pb, "\n"); diff -Nru ffmpeg-4.2.2/libavformat/westwood_vqa.c ffmpeg-4.4/libavformat/westwood_vqa.c --- ffmpeg-4.2.2/libavformat/westwood_vqa.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/westwood_vqa.c 2020-07-11 10:39:30.000000000 +0000 @@ -85,7 +85,7 @@ uint8_t scratch[VQA_PREAMBLE_SIZE]; uint32_t chunk_tag; uint32_t chunk_size; - int fps; + int fps, ret; /* initialize the video decoder stream */ st = avformat_new_stream(s, NULL); @@ -101,8 +101,8 @@ avio_seek(pb, 20, SEEK_SET); /* the VQA header needs to go to the decoder */ - if (ff_get_extradata(s, st->codecpar, pb, VQA_HEADER_SIZE) < 0) - return AVERROR(ENOMEM); + if ((ret = ff_get_extradata(s, st->codecpar, pb, VQA_HEADER_SIZE)) < 0) + return ret; header = st->codecpar->extradata; st->codecpar->width = AV_RL16(&header[6]); st->codecpar->height = AV_RL16(&header[8]); @@ -214,8 +214,8 @@ break; case SND2_TAG: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WS; - if (ff_alloc_extradata(st->codecpar, 2)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 2)) < 0) + return ret; AV_WL16(st->codecpar->extradata, wsvqa->version); break; } diff -Nru ffmpeg-4.2.2/libavformat/wsddec.c ffmpeg-4.4/libavformat/wsddec.c --- ffmpeg-4.2.2/libavformat/wsddec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/wsddec.c 2021-04-08 21:28:40.000000000 +0000 @@ -120,7 +120,7 @@ } avio_skip(pb, 4); - av_timecode_make_smpte_tc_string(playback_time, avio_rb32(pb), 0); + av_timecode_make_smpte_tc_string2(playback_time, (AVRational){1,1}, avio_rb32(pb) & 0x00ffffffU, 1, 1); av_dict_set(&s->metadata, "playback_time", playback_time, 0); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; diff -Nru ffmpeg-4.2.2/libavformat/wtvdec.c ffmpeg-4.4/libavformat/wtvdec.c --- ffmpeg-4.2.2/libavformat/wtvdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/wtvdec.c 2021-04-08 21:28:40.000000000 +0000 @@ -71,7 +71,7 @@ { WtvFile *wf = opaque; AVIOContext *pb = wf->pb_filesystem; - int nread = 0; + int nread = 0, n = 0; if (wf->error || pb->error) return -1; @@ -80,7 +80,6 @@ buf_size = FFMIN(buf_size, wf->length - wf->position); while(nread < buf_size) { - int n; int remaining_in_sector = (1 << wf->sector_bits) - (wf->position & ((1 << wf->sector_bits) - 1)); int read_request = FFMIN(buf_size - nread, remaining_in_sector); @@ -100,7 +99,7 @@ } } } - return nread; + return nread ? nread : n; } /** @@ -274,6 +273,11 @@ "bad filename length, remaining directory entries ignored\n"); break; } + if (dir_length == 0) { + av_log(s, AV_LOG_ERROR, + "bad dir length, remaining directory entries ignored\n"); + break; + } if (48 + (int64_t)name_size > buf_end - buf) { av_log(s, AV_LOG_ERROR, "filename exceeds buffer size; remaining directory entries ignored\n"); break; @@ -290,7 +294,7 @@ buf += dir_length; } - return 0; + return NULL; } #define wtvfile_open(s, buf, buf_size, filename) \ @@ -790,7 +794,7 @@ ff_get_guid(pb, &g); len = avio_rl32(pb); - if (len < 32) { + if (len < 32 || len > INT_MAX - 7) { int ret; if (avio_feof(pb)) return AVERROR_EOF; @@ -813,6 +817,8 @@ avio_skip(pb, 12); ff_get_guid(pb, &formattype); size = avio_rl32(pb); + if (size < 0 || size > INT_MAX - 92) + return AVERROR_INVALIDDATA; parse_media_type(s, 0, sid, mediatype, subtype, formattype, size); consumed += 92 + size; } @@ -827,6 +833,8 @@ avio_skip(pb, 12); ff_get_guid(pb, &formattype); size = avio_rl32(pb); + if (size < 0 || size > INT_MAX - 76) + return AVERROR_INVALIDDATA; parse_media_type(s, s->streams[stream_index], sid, mediatype, subtype, formattype, size); consumed += 76 + size; } @@ -904,10 +912,10 @@ wtv->last_valid_pts = wtv->pts; if (wtv->epoch == AV_NOPTS_VALUE || wtv->pts < wtv->epoch) wtv->epoch = wtv->pts; - if (mode == SEEK_TO_PTS && wtv->pts >= seekts) { - avio_skip(pb, WTV_PAD8(len) - consumed); - return 0; - } + if (mode == SEEK_TO_PTS && wtv->pts >= seekts) { + avio_skip(pb, WTV_PAD8(len) - consumed); + return 0; + } } } } else if (!ff_guidcmp(g, ff_data_guid)) { @@ -949,6 +957,9 @@ } else av_log(s, AV_LOG_WARNING, "unsupported chunk:"FF_PRI_GUID"\n", FF_ARG_GUID(g)); + if (avio_feof(pb)) + break; + avio_skip(pb, WTV_PAD8(len) - consumed); } return AVERROR_EOF; @@ -993,8 +1004,10 @@ } ret = parse_chunks(s, SEEK_TO_DATA, 0, 0); - if (ret < 0) + if (ret < 0) { + wtvfile_close(wtv->pb); return ret; + } avio_seek(wtv->pb, -32, SEEK_CUR); timeline_pos = avio_tell(s->pb); // save before opening another file diff -Nru ffmpeg-4.2.2/libavformat/wtvenc.c ffmpeg-4.4/libavformat/wtvenc.c --- ffmpeg-4.2.2/libavformat/wtvenc.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavformat/wtvenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -241,7 +241,7 @@ avio_wl32(pb, 0); avio_wl32(pb, 0); - ff_put_bmp_header(pb, st->codecpar, 0, 1); + ff_put_bmp_header(pb, st->codecpar, 0, 1, 0); if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) { int padding = (st->codecpar->extradata_size & 3) ? 4 - (st->codecpar->extradata_size & 3) : 0; @@ -823,8 +823,6 @@ avio_seek(pb, 0x5c, SEEK_SET); avio_wl32(pb, file_end_pos >> WTV_SECTOR_BITS); - avio_flush(pb); - av_free(wctx->sp_pairs); av_free(wctx->st_pairs); av_packet_unref(&wctx->thumbnail); @@ -841,6 +839,5 @@ .write_header = write_header, .write_packet = write_packet, .write_trailer = write_trailer, - .codec_tag = (const AVCodecTag* const []){ ff_codec_bmp_tags, - ff_codec_wav_tags, 0 }, + .codec_tag = ff_riff_codec_tags_list, }; diff -Nru ffmpeg-4.2.2/libavformat/wvdec.c ffmpeg-4.4/libavformat/wvdec.c --- ffmpeg-4.2.2/libavformat/wvdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/wvdec.c 2021-02-20 20:27:47.000000000 +0000 @@ -81,6 +81,7 @@ int ret; int rate, bpp, chan; uint32_t chmask, flags; + unsigned rate_x; wc->pos = avio_tell(pb); @@ -98,11 +99,6 @@ return ret; } - if (wc->header.flags & WV_DSD) { - avpriv_report_missing_feature(ctx, "WV DSD"); - return AVERROR_PATCHWELCOME; - } - if (wc->header.version < 0x402 || wc->header.version > 0x410) { avpriv_report_missing_feature(ctx, "WV version 0x%03X", wc->header.version); @@ -115,7 +111,8 @@ return 0; // parse flags flags = wc->header.flags; - bpp = ((flags & 3) + 1) << 3; + rate_x = (flags & WV_DSD) ? 4 : 1; + bpp = (flags & WV_DSD) ? 0 : ((flags & 3) + 1) << 3; chan = 1 + !(flags & WV_MONO); chmask = flags & WV_MONO ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; rate = wv_rates[(flags >> 23) & 0xF]; @@ -124,7 +121,7 @@ chan = wc->chan; chmask = wc->chmask; } - if ((rate == -1 || !chan) && !wc->block_parsed) { + if ((rate == -1 || !chan || flags & WV_DSD) && !wc->block_parsed) { int64_t block_end = avio_tell(pb) + wc->header.blocksize; if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) { av_log(ctx, AV_LOG_ERROR, @@ -177,6 +174,16 @@ return AVERROR_INVALIDDATA; } break; + case 0xE: + if (size <= 1) { + av_log(ctx, AV_LOG_ERROR, + "Invalid DSD block\n"); + return AVERROR_INVALIDDATA; + } + rate_x = 1U << (avio_r8(pb) & 0x1f); + if (size) + avio_skip(pb, size-1); + break; case 0x27: rate = avio_rl24(pb); break; @@ -186,7 +193,7 @@ if (id & 0x40) avio_skip(pb, 1); } - if (rate == -1) { + if (rate == -1 || rate * (uint64_t)rate_x >= INT_MAX) { av_log(ctx, AV_LOG_ERROR, "Cannot determine custom sampling rate\n"); return AVERROR_INVALIDDATA; @@ -200,7 +207,7 @@ if (!wc->chmask) wc->chmask = chmask; if (!wc->rate) - wc->rate = rate; + wc->rate = rate * rate_x; if (flags && bpp != wc->bpp) { av_log(ctx, AV_LOG_ERROR, @@ -214,10 +221,10 @@ chan, wc->chan); return AVERROR_INVALIDDATA; } - if (flags && rate != -1 && rate != wc->rate) { + if (flags && rate != -1 && !(flags & WV_DSD) && rate * rate_x != wc->rate) { av_log(ctx, AV_LOG_ERROR, "Sampling rate differ, this block: %i, header block: %i\n", - rate, wc->rate); + rate * rate_x, wc->rate); return AVERROR_INVALIDDATA; } return 0; @@ -244,6 +251,9 @@ st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 2)) < 0) + return ret; + AV_WL16(st->codecpar->extradata, wc->header.version); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_WAVPACK; st->codecpar->channels = wc->chan; @@ -282,30 +292,26 @@ } pos = wc->pos; - if (av_new_packet(pkt, wc->header.blocksize + WV_HEADER_SIZE) < 0) - return AVERROR(ENOMEM); + if ((ret = av_new_packet(pkt, wc->header.blocksize + WV_HEADER_SIZE)) < 0) + return ret; memcpy(pkt->data, wc->block_header, WV_HEADER_SIZE); ret = avio_read(s->pb, pkt->data + WV_HEADER_SIZE, wc->header.blocksize); if (ret != wc->header.blocksize) { - av_packet_unref(pkt); return AVERROR(EIO); } while (!(wc->header.flags & WV_FLAG_FINAL_BLOCK)) { if ((ret = wv_read_block_header(s, s->pb)) < 0) { - av_packet_unref(pkt); return ret; } off = pkt->size; if ((ret = av_grow_packet(pkt, WV_HEADER_SIZE + wc->header.blocksize)) < 0) { - av_packet_unref(pkt); return ret; } memcpy(pkt->data + off, wc->block_header, WV_HEADER_SIZE); ret = avio_read(s->pb, pkt->data + off + WV_HEADER_SIZE, wc->header.blocksize); if (ret != wc->header.blocksize) { - av_packet_unref(pkt); return (ret < 0) ? ret : AVERROR_EOF; } } diff -Nru ffmpeg-4.2.2/libavformat/xmv.c ffmpeg-4.4/libavformat/xmv.c --- ffmpeg-4.2.2/libavformat/xmv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/xmv.c 2020-07-11 10:39:30.000000000 +0000 @@ -397,8 +397,6 @@ av_assert0(xmv->video.stream_index < s->nb_streams); if (vst->codecpar->extradata_size < 4) { - av_freep(&vst->codecpar->extradata); - if ((ret = ff_alloc_extradata(vst->codecpar, 4)) < 0) return ret; } diff -Nru ffmpeg-4.2.2/libavformat/xwma.c ffmpeg-4.4/libavformat/xwma.c --- ffmpeg-4.2.2/libavformat/xwma.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/xwma.c 2021-02-20 20:27:47.000000000 +0000 @@ -60,16 +60,16 @@ /* check RIFF header */ tag = avio_rl32(pb); if (tag != MKTAG('R', 'I', 'F', 'F')) - return -1; + return AVERROR_INVALIDDATA; avio_rl32(pb); /* file size */ tag = avio_rl32(pb); if (tag != MKTAG('X', 'W', 'M', 'A')) - return -1; + return AVERROR_INVALIDDATA; /* parse fmt header */ tag = avio_rl32(pb); if (tag != MKTAG('f', 'm', 't', ' ')) - return -1; + return AVERROR_INVALIDDATA; size = avio_rl32(pb); st = avformat_new_stream(s, NULL); if (!st) @@ -130,15 +130,15 @@ avpriv_request_sample(s, "Unexpected extradata (%d bytes)", st->codecpar->extradata_size); } else if (st->codecpar->codec_id == AV_CODEC_ID_WMAPRO) { - if (ff_alloc_extradata(st->codecpar, 18)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 18)) < 0) + return ret; memset(st->codecpar->extradata, 0, st->codecpar->extradata_size); st->codecpar->extradata[ 0] = st->codecpar->bits_per_coded_sample; st->codecpar->extradata[14] = 224; } else { - if (ff_alloc_extradata(st->codecpar, 6)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 6)) < 0) + return ret; memset(st->codecpar->extradata, 0, st->codecpar->extradata_size); /* setup extradata with our experimentally obtained value */ @@ -211,6 +211,10 @@ } for (i = 0; i < dpds_table_size; ++i) { + if (avio_feof(pb)) { + ret = AVERROR_INVALIDDATA; + goto fail; + } dpds_table[i] = avio_rl32(pb); size -= 4; } diff -Nru ffmpeg-4.2.2/libavformat/yop.c ffmpeg-4.4/libavformat/yop.c --- ffmpeg-4.2.2/libavformat/yop.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/yop.c 2020-07-11 10:39:30.000000000 +0000 @@ -125,14 +125,11 @@ yop->video_packet.stream_index = 1; if (yop->video_packet.data) { - *pkt = yop->video_packet; - yop->video_packet.data = NULL; - yop->video_packet.buf = NULL; - yop->video_packet.size = 0; + av_packet_move_ref(pkt, &yop->video_packet); pkt->data[0] = yop->odd_frame; pkt->flags |= AV_PKT_FLAG_KEY; yop->odd_frame ^= 1; - return pkt->size; + return 0; } ret = av_new_packet(&yop->video_packet, yop->frame_size - yop->audio_block_length); @@ -166,7 +163,7 @@ av_shrink_packet(&yop->video_packet, yop->palette_size + ret); // Arbitrarily return the audio data first - return yop->audio_block_length; + return 0; err_out: av_packet_unref(&yop->video_packet); diff -Nru ffmpeg-4.2.2/libavformat/yuv4mpegdec.c ffmpeg-4.4/libavformat/yuv4mpegdec.c --- ffmpeg-4.2.2/libavformat/yuv4mpegdec.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/yuv4mpegdec.c 2020-07-11 10:39:30.000000000 +0000 @@ -26,7 +26,7 @@ #include "yuv4mpeg.h" /* Header size increased to allow room for optional flags */ -#define MAX_YUV4_HEADER 80 +#define MAX_YUV4_HEADER 96 #define MAX_FRAME_HEADER 80 static int yuv4_read_header(AVFormatContext *s) @@ -53,10 +53,14 @@ break; } } - if (i == MAX_YUV4_HEADER) - return -1; - if (strncmp(header, Y4M_MAGIC, strlen(Y4M_MAGIC))) - return -1; + if (i == MAX_YUV4_HEADER) { + av_log(s, AV_LOG_ERROR, "Header too large.\n"); + return AVERROR(EINVAL); + } + if (strncmp(header, Y4M_MAGIC, strlen(Y4M_MAGIC))) { + av_log(s, AV_LOG_ERROR, "Invalid magic number for yuv4mpeg.\n"); + return AVERROR(EINVAL); + } header_end = &header[i + 1]; // Include space for (tokstart = &header[strlen(Y4M_MAGIC) + 1]; @@ -120,9 +124,7 @@ } else if (strncmp("422", tokstart, 3) == 0) { pix_fmt = AV_PIX_FMT_YUV422P; } else if (strncmp("444alpha", tokstart, 8) == 0 ) { - av_log(s, AV_LOG_ERROR, "Cannot handle 4:4:4:4 " - "YUV4MPEG stream.\n"); - return -1; + pix_fmt = AV_PIX_FMT_YUVA444P; } else if (strncmp("444", tokstart, 3) == 0) { pix_fmt = AV_PIX_FMT_YUV444P; } else if (strncmp("mono16", tokstart, 6) == 0) { @@ -138,7 +140,7 @@ } else { av_log(s, AV_LOG_ERROR, "YUV4MPEG stream contains an unknown " "pixel format.\n"); - return -1; + return AVERROR_INVALIDDATA; } while (tokstart < header_end && *tokstart != 0x20) tokstart++; @@ -236,7 +238,7 @@ if (width == -1 || height == -1) { av_log(s, AV_LOG_ERROR, "YUV4MPEG has invalid header.\n"); - return -1; + return AVERROR_INVALIDDATA; } if (pix_fmt == AV_PIX_FMT_NONE) { @@ -310,7 +312,6 @@ if (ret < 0) return ret; else if (ret != s->packet_size - Y4M_FRAME_MAGIC_LEN) { - av_packet_unref(pkt); return s->pb->eof_reached ? AVERROR_EOF : AVERROR(EIO); } pkt->stream_index = 0; @@ -326,6 +327,8 @@ if (flags & AVSEEK_FLAG_BACKWARD) pts = FFMAX(0, pts - 1); + if (pts < 0) + return -1; pos = pts * s->packet_size; if (avio_seek(s->pb, pos + s->internal->data_offset, SEEK_SET) < 0) diff -Nru ffmpeg-4.2.2/libavformat/yuv4mpegenc.c ffmpeg-4.4/libavformat/yuv4mpegenc.c --- ffmpeg-4.2.2/libavformat/yuv4mpegenc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavformat/yuv4mpegenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,13 +24,12 @@ #include "internal.h" #include "yuv4mpeg.h" -#define Y4M_LINE_MAX 256 - -static int yuv4_generate_header(AVFormatContext *s, char* buf) +static int yuv4_write_header(AVFormatContext *s) { AVStream *st; + AVIOContext *pb = s->pb; int width, height; - int raten, rated, aspectn, aspectd, n; + int raten, rated, aspectn, aspectd, ret; char inter; const char *colorspace = ""; const char *colorrange = ""; @@ -168,12 +167,16 @@ break; } - /* construct stream header, if this is the first frame */ - n = snprintf(buf, Y4M_LINE_MAX, "%s W%d H%d F%d:%d I%c A%d:%d%s%s\n", - Y4M_MAGIC, width, height, raten, rated, inter, - aspectn, aspectd, colorspace, colorrange); + ret = avio_printf(pb, Y4M_MAGIC " W%d H%d F%d:%d I%c A%d:%d%s%s\n", + width, height, raten, rated, inter, + aspectn, aspectd, colorspace, colorrange); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, + "Error. YUV4MPEG stream header write failed.\n"); + return ret; + } - return n; + return 0; } @@ -181,30 +184,14 @@ { AVStream *st = s->streams[pkt->stream_index]; AVIOContext *pb = s->pb; - AVFrame *frame; - int* first_pkt = s->priv_data; + const AVFrame *frame = (const AVFrame *)pkt->data; int width, height, h_chroma_shift, v_chroma_shift; int i; - char buf2[Y4M_LINE_MAX + 1]; - uint8_t *ptr, *ptr1, *ptr2; - - frame = (AVFrame *)pkt->data; - - /* for the first packet we have to output the header as well */ - if (*first_pkt) { - *first_pkt = 0; - if (yuv4_generate_header(s, buf2) < 0) { - av_log(s, AV_LOG_ERROR, - "Error. YUV4MPEG stream header write failed.\n"); - return AVERROR(EIO); - } else { - avio_write(pb, buf2, strlen(buf2)); - } - } + const uint8_t *ptr, *ptr1, *ptr2; /* construct frame header */ - avio_printf(s->pb, "%s\n", Y4M_FRAME_MAGIC); + avio_printf(s->pb, Y4M_FRAME_MAGIC "\n"); width = st->codecpar->width; height = st->codecpar->height; @@ -279,10 +266,8 @@ return 0; } -static int yuv4_write_header(AVFormatContext *s) +static int yuv4_init(AVFormatContext *s) { - int *first_pkt = s->priv_data; - if (s->nb_streams != 1) return AVERROR(EIO); @@ -347,7 +332,6 @@ return AVERROR(EIO); } - *first_pkt = 1; return 0; } @@ -355,9 +339,9 @@ .name = "yuv4mpegpipe", .long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"), .extensions = "y4m", - .priv_data_size = sizeof(int), .audio_codec = AV_CODEC_ID_NONE, .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, + .init = yuv4_init, .write_header = yuv4_write_header, .write_packet = yuv4_write_packet, }; diff -Nru ffmpeg-4.2.2/libavutil/aarch64/asm.S ffmpeg-4.4/libavutil/aarch64/asm.S --- ffmpeg-4.2.2/libavutil/aarch64/asm.S 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/aarch64/asm.S 2020-07-11 10:39:30.000000000 +0000 @@ -32,6 +32,10 @@ # define FUNC # #endif +#ifndef __has_feature +# define __has_feature(x) 0 +#endif + .macro function name, export=0, align=2 .macro endfunc ELF .size \name, . - \name @@ -94,7 +98,11 @@ add \rd, \rd, :lo12:\val+(\offset) .endif #elif CONFIG_PIC +# if __has_feature(hwaddress_sanitizer) + adrp \rd, :pg_hi21_nc:\val+(\offset) +# else adrp \rd, \val+(\offset) +# endif add \rd, \rd, :lo12:\val+(\offset) #else ldr \rd, =\val+\offset @@ -104,3 +112,6 @@ #define GLUE(a, b) a ## b #define JOIN(a, b) GLUE(a, b) #define X(s) JOIN(EXTERN_ASM, s) + +#define x18 do_not_use_x18 +#define w18 do_not_use_w18 diff -Nru ffmpeg-4.2.2/libavutil/aarch64/timer.h ffmpeg-4.4/libavutil/aarch64/timer.h --- ffmpeg-4.2.2/libavutil/aarch64/timer.h 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavutil/aarch64/timer.h 2021-04-08 21:28:40.000000000 +0000 @@ -24,7 +24,13 @@ #include #include "config.h" -#if HAVE_INLINE_ASM +#if defined(__APPLE__) + +#include + +#define AV_READ_TIME mach_absolute_time + +#elif HAVE_INLINE_ASM #define AV_READ_TIME read_time diff -Nru ffmpeg-4.2.2/libavutil/adler32.c ffmpeg-4.4/libavutil/adler32.c --- ffmpeg-4.2.2/libavutil/adler32.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libavutil/adler32.c 2021-04-08 21:28:40.000000000 +0000 @@ -41,8 +41,12 @@ #define DO4(buf) DO1(buf); DO1(buf); DO1(buf); DO1(buf); #define DO16(buf) DO4(buf); DO4(buf); DO4(buf); DO4(buf); +#if FF_API_CRYPTO_SIZE_T unsigned long av_adler32_update(unsigned long adler, const uint8_t * buf, unsigned int len) +#else +AVAdler av_adler32_update(AVAdler adler, const uint8_t *buf, size_t len) +#endif { unsigned long s1 = adler & 0xffff; unsigned long s2 = adler >> 16; diff -Nru ffmpeg-4.2.2/libavutil/adler32.h ffmpeg-4.4/libavutil/adler32.h --- ffmpeg-4.2.2/libavutil/adler32.h 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libavutil/adler32.h 2021-04-08 21:28:40.000000000 +0000 @@ -27,8 +27,10 @@ #ifndef AVUTIL_ADLER32_H #define AVUTIL_ADLER32_H +#include #include #include "attributes.h" +#include "version.h" /** * @defgroup lavu_adler32 Adler-32 @@ -38,6 +40,12 @@ * @{ */ +#if FF_API_CRYPTO_SIZE_T +typedef unsigned long AVAdler; +#else +typedef uint32_t AVAdler; +#endif + /** * Calculate the Adler32 checksum of a buffer. * @@ -50,8 +58,12 @@ * @param len size of input buffer * @return updated checksum */ -unsigned long av_adler32_update(unsigned long adler, const uint8_t *buf, - unsigned int len) av_pure; +AVAdler av_adler32_update(AVAdler adler, const uint8_t *buf, +#if FF_API_CRYPTO_SIZE_T + unsigned int len) av_pure; +#else + size_t len) av_pure; +#endif /** * @} diff -Nru ffmpeg-4.2.2/libavutil/aes_internal.h ffmpeg-4.4/libavutil/aes_internal.h --- ffmpeg-4.2.2/libavutil/aes_internal.h 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavutil/aes_internal.h 2021-04-08 21:28:40.000000000 +0000 @@ -1,5 +1,5 @@ /* - * copyright (c) 2015 Rodger Combs + * copyright (c) 2015 rcombs * * This file is part of FFmpeg. * @@ -21,7 +21,7 @@ #ifndef AVUTIL_AES_INTERNAL_H #define AVUTIL_AES_INTERNAL_H -#include "mem.h" +#include "mem_internal.h" #include typedef union { diff -Nru ffmpeg-4.2.2/libavutil/arm/timer.h ffmpeg-4.4/libavutil/arm/timer.h --- ffmpeg-4.2.2/libavutil/arm/timer.h 2016-03-29 02:25:31.000000000 +0000 +++ ffmpeg-4.4/libavutil/arm/timer.h 2021-04-08 21:28:40.000000000 +0000 @@ -24,7 +24,13 @@ #include #include "config.h" -#if HAVE_INLINE_ASM && defined(__ARM_ARCH_7A__) +#if defined(__APPLE__) + +#include + +#define AV_READ_TIME mach_absolute_time + +#elif HAVE_INLINE_ASM && defined(__ARM_ARCH_7A__) #define AV_READ_TIME read_time diff -Nru ffmpeg-4.2.2/libavutil/attributes.h ffmpeg-4.4/libavutil/attributes.h --- ffmpeg-4.2.2/libavutil/attributes.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/attributes.h 2020-07-11 10:39:30.000000000 +0000 @@ -34,6 +34,12 @@ # define AV_GCC_VERSION_AT_MOST(x,y) 0 #endif +#ifdef __has_builtin +# define AV_HAS_BUILTIN(x) __has_builtin(x) +#else +# define AV_HAS_BUILTIN(x) 0 +#endif + #ifndef av_always_inline #if AV_GCC_VERSION_AT_LEAST(3,1) # define av_always_inline __attribute__((always_inline)) inline diff -Nru ffmpeg-4.2.2/libavutil/avsscanf.c ffmpeg-4.4/libavutil/avsscanf.c --- ffmpeg-4.2.2/libavutil/avsscanf.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/avsscanf.c 2021-04-08 21:28:40.000000000 +0000 @@ -113,7 +113,7 @@ } #define shlim(f, lim) ffshlim((f), (lim)) -#define shgetc(f) (((f)->rpos != (f)->shend) ? *(f)->rpos++ : ffshgetc(f)) +#define shgetc(f) (((f)->rpos < (f)->shend) ? *(f)->rpos++ : ffshgetc(f)) #define shunget(f) ((f)->shend ? (void)(f)->rpos-- : (void)0) static const unsigned char table[] = { -1, @@ -229,9 +229,9 @@ return LLONG_MIN; } for (x=0; c-'0'<10U && x= 0 */ av_bprint_escape(&dstbuf, src, special_chars, mode, flags); if (!av_bprint_is_complete(&dstbuf)) { av_bprint_finalize(&dstbuf, NULL); return AVERROR(ENOMEM); - } else { - av_bprint_finalize(&dstbuf, dst); - return dstbuf.len; } + if ((ret = av_bprint_finalize(&dstbuf, dst)) < 0) + return ret; + return dstbuf.len; } int av_match_name(const char *name, const char *names) diff -Nru ffmpeg-4.2.2/libavutil/avstring.h ffmpeg-4.4/libavutil/avstring.h --- ffmpeg-4.2.2/libavutil/avstring.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/avstring.h 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ #include #include #include "attributes.h" +#include "version.h" /** * @addtogroup lavu_string @@ -155,10 +156,14 @@ */ char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2); +#if FF_API_D2STR /** * Convert a number to an av_malloced string. + * @deprecated use av_asprintf() with "%f" or a more specific format */ +attribute_deprecated char *av_d2str(double d); +#endif /** * Unescape the given string until a non escaped terminating char, @@ -274,16 +279,21 @@ /** * Thread safe basename. - * @param path the path, on DOS both \ and / are considered separators. + * @param path the string to parse, on DOS both \ and / are considered separators. * @return pointer to the basename substring. + * If path does not contain a slash, the function returns a copy of path. + * If path is a NULL pointer or points to an empty string, a pointer + * to a string "." is returned. */ const char *av_basename(const char *path); /** * Thread safe dirname. - * @param path the path, on DOS both \ and / are considered separators. - * @return the path with the separator replaced by the string terminator or ".". - * @note the function may change the input string. + * @param path the string to parse, on DOS both \ and / are considered separators. + * @return A pointer to a string that's the parent directory of path. + * If path is a NULL pointer or points to an empty string, a pointer + * to a string "." is returned. + * @note the function may modify the contents of the path, so copies should be passed. */ const char *av_dirname(char *path); @@ -314,6 +324,7 @@ AV_ESCAPE_MODE_AUTO, ///< Use auto-selected escaping mode. AV_ESCAPE_MODE_BACKSLASH, ///< Use backslash escaping. AV_ESCAPE_MODE_QUOTE, ///< Use single-quote escaping. + AV_ESCAPE_MODE_XML, ///< Use XML non-markup character data escaping. }; /** @@ -334,6 +345,19 @@ #define AV_ESCAPE_FLAG_STRICT (1 << 1) /** + * Within AV_ESCAPE_MODE_XML, additionally escape single quotes for single + * quoted attributes. + */ +#define AV_ESCAPE_FLAG_XML_SINGLE_QUOTES (1 << 2) + +/** + * Within AV_ESCAPE_MODE_XML, additionally escape double quotes for double + * quoted attributes. + */ +#define AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES (1 << 3) + + +/** * Escape string in src, and put the escaped string in an allocated * string in *dst, which must be freed with av_free(). * diff -Nru ffmpeg-4.2.2/libavutil/base64.c ffmpeg-4.4/libavutil/base64.c --- ffmpeg-4.2.2/libavutil/base64.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libavutil/base64.c 2021-04-08 21:28:40.000000000 +0000 @@ -79,12 +79,16 @@ int av_base64_decode(uint8_t *out, const char *in_str, int out_size) { uint8_t *dst = out; - uint8_t *end = out + out_size; + uint8_t *end; // no sign extension const uint8_t *in = in_str; unsigned bits = 0xff; unsigned v; + if (!out) + goto validity_check; + + end = out + out_size; while (end - dst > 3) { BASE64_DEC_STEP(0); BASE64_DEC_STEP(1); @@ -108,6 +112,7 @@ *dst++ = v; in += 4; } +validity_check: while (1) { BASE64_DEC_STEP(0); in++; @@ -126,7 +131,7 @@ *dst++ = v >> 4; out1: out0: - return bits & 1 ? AVERROR_INVALIDDATA : dst - out; + return bits & 1 ? AVERROR_INVALIDDATA : out ? dst - out : 0; } /***************************************************************************** diff -Nru ffmpeg-4.2.2/libavutil/bprint.c ffmpeg-4.4/libavutil/bprint.c --- ffmpeg-4.2.2/libavutil/bprint.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libavutil/bprint.c 2021-04-08 21:28:40.000000000 +0000 @@ -283,6 +283,35 @@ av_bprint_chars(dstbuf, '\'', 1); break; + case AV_ESCAPE_MODE_XML: + /* escape XML non-markup character data as per 2.4 by default: */ + /* [^<&]* - ([^<&]* ']]>' [^<&]*) */ + + /* additionally, given one of the AV_ESCAPE_FLAG_XML_* flags, */ + /* escape those specific characters as required. */ + for (; *src; src++) { + switch (*src) { + case '&' : av_bprintf(dstbuf, "%s", "&"); break; + case '<' : av_bprintf(dstbuf, "%s", "<"); break; + case '>' : av_bprintf(dstbuf, "%s", ">"); break; + case '\'': + if (!(flags & AV_ESCAPE_FLAG_XML_SINGLE_QUOTES)) + goto XML_DEFAULT_HANDLING; + + av_bprintf(dstbuf, "%s", "'"); + break; + case '"' : + if (!(flags & AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES)) + goto XML_DEFAULT_HANDLING; + + av_bprintf(dstbuf, "%s", """); + break; +XML_DEFAULT_HANDLING: + default: av_bprint_chars(dstbuf, *src, 1); + } + } + break; + /* case AV_ESCAPE_MODE_BACKSLASH or unknown mode */ default: /* \-escape characters */ diff -Nru ffmpeg-4.2.2/libavutil/buffer.c ffmpeg-4.4/libavutil/buffer.c --- ffmpeg-4.2.2/libavutil/buffer.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/buffer.c 2021-04-08 21:28:40.000000000 +0000 @@ -20,12 +20,13 @@ #include #include +#include "avassert.h" #include "buffer_internal.h" #include "common.h" #include "mem.h" #include "thread.h" -AVBufferRef *av_buffer_create(uint8_t *data, int size, +AVBufferRef *av_buffer_create(uint8_t *data, buffer_size_t size, void (*free)(void *opaque, uint8_t *data), void *opaque, int flags) { @@ -43,8 +44,7 @@ atomic_init(&buf->refcount, 1); - if (flags & AV_BUFFER_FLAG_READONLY) - buf->flags |= BUFFER_FLAG_READONLY; + buf->flags = flags; ref = av_mallocz(sizeof(*ref)); if (!ref) { @@ -64,7 +64,7 @@ av_free(data); } -AVBufferRef *av_buffer_alloc(int size) +AVBufferRef *av_buffer_alloc(buffer_size_t size) { AVBufferRef *ret = NULL; uint8_t *data = NULL; @@ -80,7 +80,7 @@ return ret; } -AVBufferRef *av_buffer_allocz(int size) +AVBufferRef *av_buffer_allocz(buffer_size_t size) { AVBufferRef *ret = av_buffer_alloc(size); if (!ret) @@ -116,7 +116,7 @@ } else av_freep(dst); - if (atomic_fetch_add_explicit(&b->refcount, -1, memory_order_acq_rel) == 1) { + if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) { b->free(b->opaque, b->data); av_freep(&b); } @@ -166,10 +166,11 @@ return 0; } -int av_buffer_realloc(AVBufferRef **pbuf, int size) +int av_buffer_realloc(AVBufferRef **pbuf, buffer_size_t size) { AVBufferRef *buf = *pbuf; uint8_t *tmp; + int ret; if (!buf) { /* allocate a new buffer with av_realloc(), so it will be reallocatable @@ -184,21 +185,21 @@ return AVERROR(ENOMEM); } - buf->buffer->flags |= BUFFER_FLAG_REALLOCATABLE; + buf->buffer->flags_internal |= BUFFER_FLAG_REALLOCATABLE; *pbuf = buf; return 0; } else if (buf->size == size) return 0; - if (!(buf->buffer->flags & BUFFER_FLAG_REALLOCATABLE) || + if (!(buf->buffer->flags_internal & BUFFER_FLAG_REALLOCATABLE) || !av_buffer_is_writable(buf) || buf->data != buf->buffer->data) { /* cannot realloc, allocate a new reallocable buffer and copy data */ AVBufferRef *new = NULL; - av_buffer_realloc(&new, size); - if (!new) - return AVERROR(ENOMEM); + ret = av_buffer_realloc(&new, size); + if (ret < 0) + return ret; memcpy(new->data, buf->data, FFMIN(size, buf->size)); @@ -215,8 +216,34 @@ return 0; } -AVBufferPool *av_buffer_pool_init2(int size, void *opaque, - AVBufferRef* (*alloc)(void *opaque, int size), +int av_buffer_replace(AVBufferRef **pdst, AVBufferRef *src) +{ + AVBufferRef *dst = *pdst; + AVBufferRef *tmp; + + if (!src) { + av_buffer_unref(pdst); + return 0; + } + + if (dst && dst->buffer == src->buffer) { + /* make sure the data pointers match */ + dst->data = src->data; + dst->size = src->size; + return 0; + } + + tmp = av_buffer_ref(src); + if (!tmp) + return AVERROR(ENOMEM); + + av_buffer_unref(pdst); + *pdst = tmp; + return 0; +} + +AVBufferPool *av_buffer_pool_init2(buffer_size_t size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, buffer_size_t size), void (*pool_free)(void *opaque)) { AVBufferPool *pool = av_mallocz(sizeof(*pool)); @@ -228,6 +255,7 @@ pool->size = size; pool->opaque = opaque; pool->alloc2 = alloc; + pool->alloc = av_buffer_alloc; // fallback pool->pool_free = pool_free; atomic_init(&pool->refcount, 1); @@ -235,7 +263,7 @@ return pool; } -AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)) +AVBufferPool *av_buffer_pool_init(buffer_size_t size, AVBufferRef* (*alloc)(buffer_size_t size)) { AVBufferPool *pool = av_mallocz(sizeof(*pool)); if (!pool) @@ -251,11 +279,7 @@ return pool; } -/* - * This function gets called when the pool has been uninited and - * all the buffers returned to it. - */ -static void buffer_pool_free(AVBufferPool *pool) +static void buffer_pool_flush(AVBufferPool *pool) { while (pool->pool) { BufferPoolEntry *buf = pool->pool; @@ -264,6 +288,15 @@ buf->free(buf->opaque, buf->data); av_freep(&buf); } +} + +/* + * This function gets called when the pool has been uninited and + * all the buffers returned to it. + */ +static void buffer_pool_free(AVBufferPool *pool) +{ + buffer_pool_flush(pool); ff_mutex_destroy(&pool->mutex); if (pool->pool_free) @@ -281,7 +314,11 @@ pool = *ppool; *ppool = NULL; - if (atomic_fetch_add_explicit(&pool->refcount, -1, memory_order_acq_rel) == 1) + ff_mutex_lock(&pool->mutex); + buffer_pool_flush(pool); + ff_mutex_unlock(&pool->mutex); + + if (atomic_fetch_sub_explicit(&pool->refcount, 1, memory_order_acq_rel) == 1) buffer_pool_free(pool); } @@ -298,7 +335,7 @@ pool->pool = buf; ff_mutex_unlock(&pool->mutex); - if (atomic_fetch_add_explicit(&pool->refcount, -1, memory_order_acq_rel) == 1) + if (atomic_fetch_sub_explicit(&pool->refcount, 1, memory_order_acq_rel) == 1) buffer_pool_free(pool); } @@ -309,6 +346,8 @@ BufferPoolEntry *buf; AVBufferRef *ret; + av_assert0(pool->alloc || pool->alloc2); + ret = pool->alloc2 ? pool->alloc2(pool->opaque, pool->size) : pool->alloc(pool->size); if (!ret) @@ -355,3 +394,10 @@ return ret; } + +void *av_buffer_pool_buffer_get_opaque(AVBufferRef *ref) +{ + BufferPoolEntry *buf = ref->buffer->opaque; + av_assert0(buf); + return buf->opaque; +} diff -Nru ffmpeg-4.2.2/libavutil/buffer.h ffmpeg-4.4/libavutil/buffer.h --- ffmpeg-4.2.2/libavutil/buffer.h 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/buffer.h 2021-04-08 21:28:40.000000000 +0000 @@ -25,8 +25,11 @@ #ifndef AVUTIL_BUFFER_H #define AVUTIL_BUFFER_H +#include #include +#include "version.h" + /** * @defgroup lavu_buffer AVBuffer * @ingroup lavu_data @@ -90,7 +93,11 @@ /** * Size of data in bytes. */ +#if FF_API_BUFFER_SIZE_T int size; +#else + size_t size; +#endif } AVBufferRef; /** @@ -98,13 +105,21 @@ * * @return an AVBufferRef of given size or NULL when out of memory */ +#if FF_API_BUFFER_SIZE_T AVBufferRef *av_buffer_alloc(int size); +#else +AVBufferRef *av_buffer_alloc(size_t size); +#endif /** * Same as av_buffer_alloc(), except the returned buffer will be initialized * to zero. */ +#if FF_API_BUFFER_SIZE_T AVBufferRef *av_buffer_allocz(int size); +#else +AVBufferRef *av_buffer_allocz(size_t size); +#endif /** * Always treat the buffer as read-only, even when it has only one @@ -127,7 +142,11 @@ * * @return an AVBufferRef referring to data on success, NULL on failure. */ +#if FF_API_BUFFER_SIZE_T AVBufferRef *av_buffer_create(uint8_t *data, int size, +#else +AVBufferRef *av_buffer_create(uint8_t *data, size_t size, +#endif void (*free)(void *opaque, uint8_t *data), void *opaque, int flags); @@ -195,7 +214,27 @@ * reference to it (i.e. the one passed to this function). In all other cases * a new buffer is allocated and the data is copied. */ +#if FF_API_BUFFER_SIZE_T int av_buffer_realloc(AVBufferRef **buf, int size); +#else +int av_buffer_realloc(AVBufferRef **buf, size_t size); +#endif + +/** + * Ensure dst refers to the same data as src. + * + * When *dst is already equivalent to src, do nothing. Otherwise unreference dst + * and replace it with a new reference to src. + * + * @param dst Pointer to either a valid buffer reference or NULL. On success, + * this will point to a buffer reference equivalent to src. On + * failure, dst will be left untouched. + * @param src A buffer reference to replace dst with. May be NULL, then this + * function is equivalent to av_buffer_unref(dst). + * @return 0 on success + * AVERROR(ENOMEM) on memory allocation failure. + */ +int av_buffer_replace(AVBufferRef **dst, AVBufferRef *src); /** * @} @@ -246,7 +285,11 @@ * (av_buffer_alloc()). * @return newly created buffer pool on success, NULL on error. */ +#if FF_API_BUFFER_SIZE_T AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)); +#else +AVBufferPool *av_buffer_pool_init(size_t size, AVBufferRef* (*alloc)(size_t size)); +#endif /** * Allocate and initialize a buffer pool with a more complex allocator. @@ -254,16 +297,22 @@ * @param size size of each buffer in this pool * @param opaque arbitrary user data used by the allocator * @param alloc a function that will be used to allocate new buffers when the - * pool is empty. + * pool is empty. May be NULL, then the default allocator will be + * used (av_buffer_alloc()). * @param pool_free a function that will be called immediately before the pool * is freed. I.e. after av_buffer_pool_uninit() is called * by the caller and all the frames are returned to the pool * and freed. It is intended to uninitialize the user opaque - * data. + * data. May be NULL. * @return newly created buffer pool on success, NULL on error. */ +#if FF_API_BUFFER_SIZE_T AVBufferPool *av_buffer_pool_init2(int size, void *opaque, AVBufferRef* (*alloc)(void *opaque, int size), +#else +AVBufferPool *av_buffer_pool_init2(size_t size, void *opaque, + AVBufferRef* (*alloc)(void *opaque, size_t size), +#endif void (*pool_free)(void *opaque)); /** @@ -285,6 +334,19 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool); /** + * Query the original opaque parameter of an allocated buffer in the pool. + * + * @param ref a buffer reference to a buffer returned by av_buffer_pool_get. + * @return the opaque parameter set by the buffer allocator function of the + * buffer pool. + * + * @note the opaque parameter of ref is used by the buffer pool implementation, + * therefore you have to use this function to access the original opaque + * parameter of an allocated buffer. + */ +void *av_buffer_pool_buffer_get_opaque(AVBufferRef *ref); + +/** * @} */ diff -Nru ffmpeg-4.2.2/libavutil/buffer_internal.h ffmpeg-4.4/libavutil/buffer_internal.h --- ffmpeg-4.2.2/libavutil/buffer_internal.h 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/buffer_internal.h 2021-04-08 21:28:40.000000000 +0000 @@ -22,21 +22,18 @@ #include #include +#include "internal.h" #include "buffer.h" #include "thread.h" /** - * The buffer is always treated as read-only. - */ -#define BUFFER_FLAG_READONLY (1 << 0) -/** * The buffer was av_realloc()ed, so it is reallocatable. */ -#define BUFFER_FLAG_REALLOCATABLE (1 << 1) +#define BUFFER_FLAG_REALLOCATABLE (1 << 0) struct AVBuffer { uint8_t *data; /**< data described by this buffer */ - int size; /**< size of data in bytes */ + buffer_size_t size; /**< size of data in bytes */ /** * number of existing AVBufferRef instances referring to this buffer @@ -54,9 +51,14 @@ void *opaque; /** - * A combination of BUFFER_FLAG_* + * A combination of AV_BUFFER_FLAG_* */ int flags; + + /** + * A combination of BUFFER_FLAG_* + */ + int flags_internal; }; typedef struct BufferPoolEntry { @@ -88,10 +90,10 @@ */ atomic_uint refcount; - int size; + buffer_size_t size; void *opaque; - AVBufferRef* (*alloc)(int size); - AVBufferRef* (*alloc2)(void *opaque, int size); + AVBufferRef* (*alloc)(buffer_size_t size); + AVBufferRef* (*alloc2)(void *opaque, buffer_size_t size); void (*pool_free)(void *opaque); }; diff -Nru ffmpeg-4.2.2/libavutil/channel_layout.c ffmpeg-4.4/libavutil/channel_layout.c --- ffmpeg-4.2.2/libavutil/channel_layout.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/channel_layout.c 2021-04-08 21:28:40.000000000 +0000 @@ -62,6 +62,11 @@ [33] = { "SDL", "surround direct left" }, [34] = { "SDR", "surround direct right" }, [35] = { "LFE2", "low frequency 2" }, + [36] = { "TSL", "top side left" }, + [37] = { "TSR", "top side right" }, + [38] = { "BFC", "bottom front center" }, + [39] = { "BFL", "bottom front left" }, + [40] = { "BFR", "bottom front right" }, }; static const char *get_channel_name(int channel_id) @@ -104,6 +109,7 @@ { "octagonal", 8, AV_CH_LAYOUT_OCTAGONAL }, { "hexadecagonal", 16, AV_CH_LAYOUT_HEXADECAGONAL }, { "downmix", 2, AV_CH_LAYOUT_STEREO_DOWNMIX, }, + { "22.2", 24, AV_CH_LAYOUT_22POINT2, }, }; static uint64_t get_channel_layout_single(const char *name, int name_len) diff -Nru ffmpeg-4.2.2/libavutil/channel_layout.h ffmpeg-4.4/libavutil/channel_layout.h --- ffmpeg-4.2.2/libavutil/channel_layout.h 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/channel_layout.h 2021-04-08 21:28:40.000000000 +0000 @@ -71,6 +71,11 @@ #define AV_CH_SURROUND_DIRECT_LEFT 0x0000000200000000ULL #define AV_CH_SURROUND_DIRECT_RIGHT 0x0000000400000000ULL #define AV_CH_LOW_FREQUENCY_2 0x0000000800000000ULL +#define AV_CH_TOP_SIDE_LEFT 0x0000001000000000ULL +#define AV_CH_TOP_SIDE_RIGHT 0x0000002000000000ULL +#define AV_CH_BOTTOM_FRONT_CENTER 0x0000004000000000ULL +#define AV_CH_BOTTOM_FRONT_LEFT 0x0000008000000000ULL +#define AV_CH_BOTTOM_FRONT_RIGHT 0x0000010000000000ULL /** Channel mask value used for AVCodecContext.request_channel_layout to indicate that the user requests the channel order of the decoder output @@ -110,6 +115,7 @@ #define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT) #define AV_CH_LAYOUT_HEXADECAGONAL (AV_CH_LAYOUT_OCTAGONAL|AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT) #define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT) +#define AV_CH_LAYOUT_22POINT2 (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER|AV_CH_BACK_CENTER|AV_CH_LOW_FREQUENCY_2|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_CENTER|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_SIDE_LEFT|AV_CH_TOP_SIDE_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_BOTTOM_FRONT_CENTER|AV_CH_BOTTOM_FRONT_LEFT|AV_CH_BOTTOM_FRONT_RIGHT) enum AVMatrixEncoding { AV_MATRIX_ENCODING_NONE, diff -Nru ffmpeg-4.2.2/libavutil/common.h ffmpeg-4.4/libavutil/common.h --- ffmpeg-4.2.2/libavutil/common.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/common.h 2021-04-08 21:28:40.000000000 +0000 @@ -53,7 +53,7 @@ //rounded division & shift #define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) /* assume b>0 */ -#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) +#define ROUNDED_DIV(a,b) (((a)>=0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) /* Fast a/(1<=0 and b>=0 */ #define AV_CEIL_RSHIFT(a,b) (!av_builtin_constant_p(b) ? -((-(a)) >> (b)) \ : ((a) + (1<<(b)) - 1) >> (b)) @@ -81,6 +81,15 @@ #define FFNABS(a) ((a) <= 0 ? (a) : (-(a))) /** + * Unsigned Absolute value. + * This takes the absolute value of a signed int and returns it as a unsigned. + * This also works with INT_MIN which would otherwise not be representable + * As with many macros, this evaluates its argument twice. + */ +#define FFABSU(a) ((a) <= 0 ? -(unsigned)(a) : (unsigned)(a)) +#define FFABS64U(a) ((a) <= 0 ? -(uint64_t)(a) : (uint64_t)(a)) + +/** * Comparator. * For two numerical expressions x and y, gives 1 if x > y, -1 if x < y, and 0 * if x == y. This is useful for instance in a qsort comparator callback. @@ -106,8 +115,72 @@ # include "intmath.h" #endif -/* Pull in unguarded fallback defines at the end of this file. */ -#include "common.h" +#ifndef av_ceil_log2 +# define av_ceil_log2 av_ceil_log2_c +#endif +#ifndef av_clip +# define av_clip av_clip_c +#endif +#ifndef av_clip64 +# define av_clip64 av_clip64_c +#endif +#ifndef av_clip_uint8 +# define av_clip_uint8 av_clip_uint8_c +#endif +#ifndef av_clip_int8 +# define av_clip_int8 av_clip_int8_c +#endif +#ifndef av_clip_uint16 +# define av_clip_uint16 av_clip_uint16_c +#endif +#ifndef av_clip_int16 +# define av_clip_int16 av_clip_int16_c +#endif +#ifndef av_clipl_int32 +# define av_clipl_int32 av_clipl_int32_c +#endif +#ifndef av_clip_intp2 +# define av_clip_intp2 av_clip_intp2_c +#endif +#ifndef av_clip_uintp2 +# define av_clip_uintp2 av_clip_uintp2_c +#endif +#ifndef av_mod_uintp2 +# define av_mod_uintp2 av_mod_uintp2_c +#endif +#ifndef av_sat_add32 +# define av_sat_add32 av_sat_add32_c +#endif +#ifndef av_sat_dadd32 +# define av_sat_dadd32 av_sat_dadd32_c +#endif +#ifndef av_sat_sub32 +# define av_sat_sub32 av_sat_sub32_c +#endif +#ifndef av_sat_dsub32 +# define av_sat_dsub32 av_sat_dsub32_c +#endif +#ifndef av_sat_add64 +# define av_sat_add64 av_sat_add64_c +#endif +#ifndef av_sat_sub64 +# define av_sat_sub64 av_sat_sub64_c +#endif +#ifndef av_clipf +# define av_clipf av_clipf_c +#endif +#ifndef av_clipd +# define av_clipd av_clipd_c +#endif +#ifndef av_popcount +# define av_popcount av_popcount_c +#endif +#ifndef av_popcount64 +# define av_popcount64 av_popcount64_c +#endif +#ifndef av_parity +# define av_parity av_parity_c +#endif #ifndef av_log2 av_const int av_log2(unsigned v); @@ -240,7 +313,7 @@ */ static av_always_inline av_const unsigned av_mod_uintp2_c(unsigned a, unsigned p) { - return a & ((1 << p) - 1); + return a & ((1U << p) - 1); } /** @@ -292,6 +365,45 @@ } /** + * Add two signed 64-bit values with saturation. + * + * @param a one value + * @param b another value + * @return sum with signed saturation + */ +static av_always_inline int64_t av_sat_add64_c(int64_t a, int64_t b) { +#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_add_overflow) + int64_t tmp; + return !__builtin_add_overflow(a, b, &tmp) ? tmp : (tmp < 0 ? INT64_MAX : INT64_MIN); +#else + int64_t s = a+(uint64_t)b; + if ((int64_t)(a^b | ~s^b) >= 0) + return INT64_MAX ^ (b >> 63); + return s; +#endif +} + +/** + * Subtract two signed 64-bit values with saturation. + * + * @param a one value + * @param b another value + * @return difference with signed saturation + */ +static av_always_inline int64_t av_sat_sub64_c(int64_t a, int64_t b) { +#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_sub_overflow) + int64_t tmp; + return !__builtin_sub_overflow(a, b, &tmp) ? tmp : (tmp < 0 ? INT64_MAX : INT64_MIN); +#else + if (b <= 0 && a >= INT64_MAX + b) + return INT64_MAX; + if (b >= 0 && a <= INT64_MIN + b) + return INT64_MIN; + return a - b; +#endif +} + +/** * Clip a float value into the amin-amax range. * @param a value to clip * @param amin minimum value of the clip range @@ -331,7 +443,7 @@ */ static av_always_inline av_const int av_ceil_log2_c(int x) { - return av_log2((x - 1) << 1); + return av_log2((x - 1U) << 1); } /** @@ -373,7 +485,9 @@ * @param GET_BYTE Expression reading one byte from the input. * Evaluated up to 7 times (4 for the currently * assigned Unicode range). With a memory buffer - * input, this could be *ptr++. + * input, this could be *ptr++, or if you want to make sure + * that *ptr stops at the end of a NULL terminated string then + * *ptr ? *ptr++ : 0 * @param ERROR Expression to be evaluated on invalid input, * typically a goto statement. * @@ -387,11 +501,11 @@ {\ uint32_t top = (val & 128) >> 1;\ if ((val & 0xc0) == 0x80 || val >= 0xFE)\ - ERROR\ + {ERROR}\ while (val & top) {\ - int tmp= (GET_BYTE) - 128;\ + unsigned int tmp = (GET_BYTE) - 128;\ if(tmp>>6)\ - ERROR\ + {ERROR}\ val= (val<<6) + tmp;\ top <<= 5;\ }\ @@ -408,13 +522,13 @@ * typically a goto statement. */ #define GET_UTF16(val, GET_16BIT, ERROR)\ - val = GET_16BIT;\ + val = (GET_16BIT);\ {\ unsigned int hi = val - 0xD800;\ if (hi < 0x800) {\ - val = GET_16BIT - 0xDC00;\ + val = (GET_16BIT) - 0xDC00;\ if (val > 0x3FFU || hi > 0x3FFU)\ - ERROR\ + {ERROR}\ val += (hi<<10) + 0x10000;\ }\ }\ @@ -492,69 +606,3 @@ #endif /* HAVE_AV_CONFIG_H */ #endif /* AVUTIL_COMMON_H */ - -/* - * The following definitions are outside the multiple inclusion guard - * to ensure they are immediately available in intmath.h. - */ - -#ifndef av_ceil_log2 -# define av_ceil_log2 av_ceil_log2_c -#endif -#ifndef av_clip -# define av_clip av_clip_c -#endif -#ifndef av_clip64 -# define av_clip64 av_clip64_c -#endif -#ifndef av_clip_uint8 -# define av_clip_uint8 av_clip_uint8_c -#endif -#ifndef av_clip_int8 -# define av_clip_int8 av_clip_int8_c -#endif -#ifndef av_clip_uint16 -# define av_clip_uint16 av_clip_uint16_c -#endif -#ifndef av_clip_int16 -# define av_clip_int16 av_clip_int16_c -#endif -#ifndef av_clipl_int32 -# define av_clipl_int32 av_clipl_int32_c -#endif -#ifndef av_clip_intp2 -# define av_clip_intp2 av_clip_intp2_c -#endif -#ifndef av_clip_uintp2 -# define av_clip_uintp2 av_clip_uintp2_c -#endif -#ifndef av_mod_uintp2 -# define av_mod_uintp2 av_mod_uintp2_c -#endif -#ifndef av_sat_add32 -# define av_sat_add32 av_sat_add32_c -#endif -#ifndef av_sat_dadd32 -# define av_sat_dadd32 av_sat_dadd32_c -#endif -#ifndef av_sat_sub32 -# define av_sat_sub32 av_sat_sub32_c -#endif -#ifndef av_sat_dsub32 -# define av_sat_dsub32 av_sat_dsub32_c -#endif -#ifndef av_clipf -# define av_clipf av_clipf_c -#endif -#ifndef av_clipd -# define av_clipd av_clipd_c -#endif -#ifndef av_popcount -# define av_popcount av_popcount_c -#endif -#ifndef av_popcount64 -# define av_popcount64 av_popcount64_c -#endif -#ifndef av_parity -# define av_parity av_parity_c -#endif diff -Nru ffmpeg-4.2.2/libavutil/cpu.c ffmpeg-4.4/libavutil/cpu.c --- ffmpeg-4.2.2/libavutil/cpu.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/cpu.c 2021-04-08 21:28:40.000000000 +0000 @@ -51,6 +51,8 @@ static int get_cpu_flags(void) { + if (ARCH_MIPS) + return ff_get_cpu_flags_mips(); if (ARCH_AARCH64) return ff_get_cpu_flags_aarch64(); if (ARCH_ARM) @@ -169,6 +171,9 @@ { "armv8", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV8 }, .unit = "flags" }, { "neon", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON }, .unit = "flags" }, { "vfp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP }, .unit = "flags" }, +#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" }, #endif { NULL }, }; @@ -250,6 +255,9 @@ { "armv8", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV8 }, .unit = "flags" }, { "neon", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON }, .unit = "flags" }, { "vfp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP }, .unit = "flags" }, +#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" }, #endif { NULL }, }; @@ -308,6 +316,8 @@ size_t av_cpu_max_align(void) { + if (ARCH_MIPS) + return ff_get_cpu_max_align_mips(); if (ARCH_AARCH64) return ff_get_cpu_max_align_aarch64(); if (ARCH_ARM) diff -Nru ffmpeg-4.2.2/libavutil/cpu.h ffmpeg-4.4/libavutil/cpu.h --- ffmpeg-4.2.2/libavutil/cpu.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/cpu.h 2021-04-08 21:28:40.000000000 +0000 @@ -71,6 +71,9 @@ #define AV_CPU_FLAG_VFP_VM (1 << 7) ///< VFPv2 vector mode, deprecated in ARMv7-A and unavailable in various CPUs implementations #define AV_CPU_FLAG_SETEND (1 <<16) +#define AV_CPU_FLAG_MMI (1 << 0) +#define AV_CPU_FLAG_MSA (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 -Nru ffmpeg-4.2.2/libavutil/cpu_internal.h ffmpeg-4.4/libavutil/cpu_internal.h --- ffmpeg-4.2.2/libavutil/cpu_internal.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/cpu_internal.h 2021-04-08 21:28:40.000000000 +0000 @@ -41,11 +41,13 @@ #define CPUEXT_FAST(flags, cpuext) CPUEXT_SUFFIX_FAST(flags, , cpuext) #define CPUEXT_SLOW(flags, cpuext) CPUEXT_SUFFIX_SLOW(flags, , cpuext) +int ff_get_cpu_flags_mips(void); 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); +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); diff -Nru ffmpeg-4.2.2/libavutil/cuda_check.h ffmpeg-4.4/libavutil/cuda_check.h --- ffmpeg-4.2.2/libavutil/cuda_check.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/cuda_check.h 2021-04-08 21:28:40.000000000 +0000 @@ -20,6 +20,8 @@ #ifndef AVUTIL_CUDA_CHECK_H #define AVUTIL_CUDA_CHECK_H +#include "compat/cuda/dynlink_loader.h" + typedef CUresult CUDAAPI cuda_check_GetErrorName(CUresult error, const char** pstr); typedef CUresult CUDAAPI cuda_check_GetErrorString(CUresult error, const char** pstr); diff -Nru ffmpeg-4.2.2/libavutil/dict.c ffmpeg-4.4/libavutil/dict.c --- ffmpeg-4.2.2/libavutil/dict.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libavutil/dict.c 2020-07-11 10:39:30.000000000 +0000 @@ -103,8 +103,8 @@ av_free(tag->key); *tag = m->elems[--m->count]; } else if (copy_value) { - AVDictionaryEntry *tmp = av_realloc(m->elems, - (m->count + 1) * sizeof(*m->elems)); + AVDictionaryEntry *tmp = av_realloc_array(m->elems, + m->count + 1, sizeof(*m->elems)); if (!tmp) goto err_out; m->elems = tmp; diff -Nru ffmpeg-4.2.2/libavutil/dovi_meta.c ffmpeg-4.4/libavutil/dovi_meta.c --- ffmpeg-4.2.2/libavutil/dovi_meta.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/dovi_meta.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020 Jun Zhao + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "dovi_meta.h" +#include "mem.h" + +AVDOVIDecoderConfigurationRecord *av_dovi_alloc(size_t *size) +{ + AVDOVIDecoderConfigurationRecord *dovi = + av_mallocz(sizeof(AVDOVIDecoderConfigurationRecord)); + if (!dovi) + return NULL; + + if (size) + *size = sizeof(*dovi); + + return dovi; +} diff -Nru ffmpeg-4.2.2/libavutil/dovi_meta.h ffmpeg-4.4/libavutil/dovi_meta.h --- ffmpeg-4.2.2/libavutil/dovi_meta.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/dovi_meta.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020 Vacing Fang + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * DOVI configuration + */ + + +#ifndef AVUTIL_DOVI_META_H +#define AVUTIL_DOVI_META_H + +#include +#include + +/* + * DOVI configuration + * ref: dolby-vision-bitstreams-within-the-iso-base-media-file-format-v2.1.2 + dolby-vision-bitstreams-in-mpeg-2-transport-stream-multiplex-v1.2 + * @code + * uint8_t dv_version_major, the major version number that the stream complies with + * uint8_t dv_version_minor, the minor version number that the stream complies with + * uint8_t dv_profile, the Dolby Vision profile + * uint8_t dv_level, the Dolby Vision level + * uint8_t rpu_present_flag + * uint8_t el_present_flag + * uint8_t bl_present_flag + * uint8_t dv_bl_signal_compatibility_id + * @endcode + * + * @note The struct must be allocated with av_dovi_alloc() and + * its size is not a part of the public ABI. + */ +typedef struct AVDOVIDecoderConfigurationRecord { + uint8_t dv_version_major; + uint8_t dv_version_minor; + uint8_t dv_profile; + uint8_t dv_level; + uint8_t rpu_present_flag; + uint8_t el_present_flag; + uint8_t bl_present_flag; + uint8_t dv_bl_signal_compatibility_id; +} AVDOVIDecoderConfigurationRecord; + +/** + * Allocate a AVDOVIDecoderConfigurationRecord structure and initialize its + * fields to default values. + * + * @return the newly allocated struct or NULL on failure + */ +AVDOVIDecoderConfigurationRecord *av_dovi_alloc(size_t *size); + +#endif /* AVUTIL_DOVI_META_H */ diff -Nru ffmpeg-4.2.2/libavutil/encryption_info.c ffmpeg-4.4/libavutil/encryption_info.c --- ffmpeg-4.2.2/libavutil/encryption_info.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/encryption_info.c 2020-07-09 09:17:46.000000000 +0000 @@ -331,8 +331,10 @@ memcpy(cur_buffer, cur_info->key_ids[i], cur_info->key_id_size); cur_buffer += cur_info->key_id_size; } - memcpy(cur_buffer, cur_info->data, cur_info->data_size); - cur_buffer += cur_info->data_size; + if (cur_info->data_size > 0) { + memcpy(cur_buffer, cur_info->data, cur_info->data_size); + cur_buffer += cur_info->data_size; + } } return buffer; diff -Nru ffmpeg-4.2.2/libavutil/eval.c ffmpeg-4.4/libavutil/eval.c --- ffmpeg-4.2.2/libavutil/eval.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/eval.c 2021-04-08 21:28:40.000000000 +0000 @@ -163,10 +163,11 @@ e_last, e_st, e_while, e_taylor, e_root, e_floor, e_ceil, e_trunc, e_round, e_sqrt, e_not, e_random, e_hypot, e_gcd, e_if, e_ifnot, e_print, e_bitand, e_bitor, e_between, e_clip, e_atan2, e_lerp, + e_sgn, } type; double value; // is sign in other types + int const_index; union { - int const_index; double (*func0)(double); double (*func1)(void *, double); double (*func2)(void *, double, double); @@ -184,7 +185,7 @@ { switch (e->type) { case e_value: return e->value; - case e_const: return e->value * p->const_values[e->a.const_index]; + case e_const: return e->value * p->const_values[e->const_index]; case e_func0: return e->value * e->a.func0(eval_expr(p, e->param[0])); case e_func1: return e->value * e->a.func1(p->opaque, eval_expr(p, e->param[0])); case e_func2: return e->value * e->a.func2(p->opaque, eval_expr(p, e->param[0]), eval_expr(p, e->param[1])); @@ -197,6 +198,7 @@ case e_ceil : return e->value * ceil (eval_expr(p, e->param[0])); case e_trunc: return e->value * trunc(eval_expr(p, e->param[0])); case e_round: return e->value * round(eval_expr(p, e->param[0])); + case e_sgn: return e->value * FFDIFFSIGN(eval_expr(p, e->param[0]), 0); case e_sqrt: return e->value * sqrt (eval_expr(p, e->param[0])); case e_not: return e->value * (eval_expr(p, e->param[0]) == 0); case e_if: return e->value * (eval_expr(p, e->param[0]) ? eval_expr(p, e->param[1]) : @@ -304,7 +306,7 @@ double d = eval_expr(p, e->param[0]); double d2 = eval_expr(p, e->param[1]); switch (e->type) { - case e_mod: return e->value * (d - floor((!CONFIG_FTRAPV || d2) ? d / d2 : d * INFINITY) * d2); + case e_mod: return e->value * (d - floor(d2 ? d / d2 : d * INFINITY) * d2); case e_gcd: return e->value * av_gcd(d,d2); case e_max: return e->value * (d > d2 ? d : d2); case e_min: return e->value * (d < d2 ? d : d2); @@ -315,7 +317,7 @@ case e_lte: return e->value * (d <= d2 ? 1.0 : 0.0); case e_pow: return e->value * pow(d, d2); case e_mul: return e->value * (d * d2); - case e_div: return e->value * ((!CONFIG_FTRAPV || d2 ) ? (d / d2) : d * INFINITY); + case e_div: return e->value * (d2 ? (d / d2) : d * INFINITY); case e_add: return e->value * (d + d2); case e_last:return e->value * d2; case e_st : return e->value * (p->var[av_clip(d, 0, VARS-1)]= d2); @@ -365,7 +367,7 @@ if (strmatch(p->s, p->const_names[i])) { p->s+= strlen(p->const_names[i]); d->type = e_const; - d->a.const_index = i; + d->const_index = i; *e = d; return 0; } @@ -470,11 +472,13 @@ else if (strmatch(next, "clip" )) d->type = e_clip; else if (strmatch(next, "atan2" )) d->type = e_atan2; else if (strmatch(next, "lerp" )) d->type = e_lerp; + else if (strmatch(next, "sgn" )) d->type = e_sgn; else { for (i=0; p->func1_names && p->func1_names[i]; i++) { if (strmatch(next, p->func1_names[i])) { d->a.func1 = p->funcs1[i]; d->type = e_func1; + d->const_index = i; *e = d; return 0; } @@ -484,6 +488,7 @@ if (strmatch(next, p->func2_names[i])) { d->a.func2 = p->funcs2[i]; d->type = e_func2; + d->const_index = i; *e = d; return 0; } @@ -657,6 +662,7 @@ case e_sqrt: case e_not: case e_random: + case e_sgn: return verify_expr(e->param[0]) && !e->param[1]; case e_print: return verify_expr(e->param[0]) @@ -731,6 +737,32 @@ return ret; } +static int expr_count(AVExpr *e, unsigned *counter, int size, int type) +{ + int i; + + if (!e || !counter || !size) + return AVERROR(EINVAL); + + for (i = 0; e->type != type && i < 3 && e->param[i]; i++) + expr_count(e->param[i], counter, size, type); + + if (e->type == type && e->const_index < size) + counter[e->const_index]++; + + return 0; +} + +int av_expr_count_vars(AVExpr *e, unsigned *counter, int size) +{ + return expr_count(e, counter, size, e_const); +} + +int av_expr_count_func(AVExpr *e, unsigned *counter, int size, int arg) +{ + return expr_count(e, counter, size, ((int[]){e_const, e_func1, e_func2})[arg]); +} + double av_expr_eval(AVExpr *e, const double *const_values, void *opaque) { Parser p = { 0 }; diff -Nru ffmpeg-4.2.2/libavutil/eval.h ffmpeg-4.4/libavutil/eval.h --- ffmpeg-4.2.2/libavutil/eval.h 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavutil/eval.h 2020-07-11 10:39:30.000000000 +0000 @@ -87,6 +87,30 @@ double av_expr_eval(AVExpr *e, const double *const_values, void *opaque); /** + * Track the presence of variables and their number of occurrences in a parsed expression + * + * @param counter a zero-initialized array where the count of each variable will be stored + * @param size size of array + * @return 0 on success, a negative value indicates that no expression or array was passed + * or size was zero + */ +int av_expr_count_vars(AVExpr *e, unsigned *counter, int size); + +/** + * Track the presence of user provided functions and their number of occurrences + * in a parsed expression. + * + * @param counter a zero-initialized array where the count of each function will be stored + * if you passed 5 functions with 2 arguments to av_expr_parse() + * then for arg=2 this will use upto 5 entries. + * @param size size of array + * @param arg number of arguments the counted functions have + * @return 0 on success, a negative value indicates that no expression or array was passed + * or size was zero + */ +int av_expr_count_func(AVExpr *e, unsigned *counter, int size, int arg); + +/** * Free a parsed expression previously created with av_expr_parse(). */ void av_expr_free(AVExpr *e); diff -Nru ffmpeg-4.2.2/libavutil/file.c ffmpeg-4.4/libavutil/file.c --- ffmpeg-4.2.2/libavutil/file.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/file.c 2020-07-11 10:39:30.000000000 +0000 @@ -60,6 +60,7 @@ off_t off_size; char errbuf[128]; *bufptr = NULL; + *size = 0; if (fd < 0) { err = AVERROR(errno); @@ -97,6 +98,7 @@ av_strerror(err, errbuf, sizeof(errbuf)); av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in mmap(): %s\n", errbuf); close(fd); + *size = 0; return err; } *bufptr = ptr; @@ -108,6 +110,7 @@ if (!mh) { av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in CreateFileMapping()\n"); close(fd); + *size = 0; return -1; } @@ -116,6 +119,7 @@ if (!ptr) { av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in MapViewOfFile()\n"); close(fd); + *size = 0; return -1; } @@ -126,6 +130,7 @@ if (!*bufptr) { av_log(&file_log_ctx, AV_LOG_ERROR, "Memory allocation error occurred\n"); close(fd); + *size = 0; return AVERROR(ENOMEM); } read(fd, *bufptr, *size); @@ -138,7 +143,7 @@ void av_file_unmap(uint8_t *bufptr, size_t size) { - if (!size) + if (!size || !bufptr) return; #if HAVE_MMAP munmap(bufptr, size); diff -Nru ffmpeg-4.2.2/libavutil/film_grain_params.c ffmpeg-4.4/libavutil/film_grain_params.c --- ffmpeg-4.2.2/libavutil/film_grain_params.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/film_grain_params.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,42 @@ +/** + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "film_grain_params.h" + +AVFilmGrainParams *av_film_grain_params_alloc(size_t *size) +{ + AVFilmGrainParams *params = av_mallocz(sizeof(AVFilmGrainParams)); + + if (size) + *size = sizeof(*params); + + return params; +} + +AVFilmGrainParams *av_film_grain_params_create_side_data(AVFrame *frame) +{ + AVFrameSideData *side_data = av_frame_new_side_data(frame, + AV_FRAME_DATA_FILM_GRAIN_PARAMS, + sizeof(AVFilmGrainParams)); + if (!side_data) + return NULL; + + memset(side_data->data, 0, sizeof(AVFilmGrainParams)); + + return (AVFilmGrainParams *)side_data->data; +} diff -Nru ffmpeg-4.2.2/libavutil/film_grain_params.h ffmpeg-4.4/libavutil/film_grain_params.h --- ffmpeg-4.2.2/libavutil/film_grain_params.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/film_grain_params.h 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,168 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_FILM_GRAIN_PARAMS_H +#define AVUTIL_FILM_GRAIN_PARAMS_H + +#include "frame.h" + +enum AVFilmGrainParamsType { + AV_FILM_GRAIN_PARAMS_NONE = 0, + + /** + * The union is valid when interpreted as AVFilmGrainAOMParams (codec.aom) + */ + AV_FILM_GRAIN_PARAMS_AV1, +}; + +/** + * This structure describes how to handle film grain synthesis for AOM codecs. + * + * @note The struct must be allocated as part of AVFilmGrainParams using + * av_film_grain_params_alloc(). Its size is not a part of the public ABI. + */ +typedef struct AVFilmGrainAOMParams { + /** + * Number of points, and the scale and value for each point of the + * piecewise linear scaling function for the uma plane. + */ + int num_y_points; + uint8_t y_points[14][2 /* value, scaling */]; + + /** + * Signals whether to derive the chroma scaling function from the luma. + * Not equivalent to copying the luma values and scales. + */ + int chroma_scaling_from_luma; + + /** + * If chroma_scaling_from_luma is set to 0, signals the chroma scaling + * function parameters. + */ + int num_uv_points[2 /* cb, cr */]; + uint8_t uv_points[2 /* cb, cr */][10][2 /* value, scaling */]; + + /** + * Specifies the shift applied to the chroma components. For AV1, its within + * [8; 11] and determines the range and quantization of the film grain. + */ + int scaling_shift; + + /** + * Specifies the auto-regression lag. + */ + int ar_coeff_lag; + + /** + * Luma auto-regression coefficients. The number of coefficients is given by + * 2 * ar_coeff_lag * (ar_coeff_lag + 1). + */ + int8_t ar_coeffs_y[24]; + + /** + * Chroma auto-regression coefficients. The number of coefficients is given by + * 2 * ar_coeff_lag * (ar_coeff_lag + 1) + !!num_y_points. + */ + int8_t ar_coeffs_uv[2 /* cb, cr */][25]; + + /** + * Specifies the range of the auto-regressive coefficients. Values of 6, + * 7, 8 and so on represent a range of [-2, 2), [-1, 1), [-0.5, 0.5) and + * so on. For AV1 must be between 6 and 9. + */ + int ar_coeff_shift; + + /** + * Signals the down shift applied to the generated gaussian numbers during + * synthesis. + */ + int grain_scale_shift; + + /** + * Specifies the luma/chroma multipliers for the index to the component + * scaling function. + */ + int uv_mult[2 /* cb, cr */]; + int uv_mult_luma[2 /* cb, cr */]; + + /** + * Offset used for component scaling function. For AV1 its a 9-bit value + * with a range [-256, 255] + */ + int uv_offset[2 /* cb, cr */]; + + /** + * Signals whether to overlap film grain blocks. + */ + int overlap_flag; + + /** + * Signals to clip to limited color levels after film grain application. + */ + int limit_output_range; +} AVFilmGrainAOMParams; + +/** + * This structure describes how to handle film grain synthesis in video + * for specific codecs. Must be present on every frame where film grain is + * meant to be synthesised for correct presentation. + * + * @note The struct must be allocated with av_film_grain_params_alloc() and + * its size is not a part of the public ABI. + */ +typedef struct AVFilmGrainParams { + /** + * Specifies the codec for which this structure is valid. + */ + enum AVFilmGrainParamsType type; + + /** + * Seed to use for the synthesis process, if the codec allows for it. + */ + uint64_t seed; + + /** + * Additional fields may be added both here and in any structure included. + * If a codec's film grain structure differs slightly over another + * codec's, fields within may change meaning depending on the type. + */ + union { + AVFilmGrainAOMParams aom; + } codec; +} AVFilmGrainParams; + +/** + * Allocate an AVFilmGrainParams structure and set its fields to + * default values. The resulting struct can be freed using av_freep(). + * If size is not NULL it will be set to the number of bytes allocated. + * + * @return An AVFilmGrainParams filled with default values or NULL + * on failure. + */ +AVFilmGrainParams *av_film_grain_params_alloc(size_t *size); + +/** + * Allocate a complete AVFilmGrainParams and add it to the frame. + * + * @param frame The frame which side data is added to. + * + * @return The AVFilmGrainParams structure to be filled by caller. + */ +AVFilmGrainParams *av_film_grain_params_create_side_data(AVFrame *frame); + +#endif /* AVUTIL_FILM_GRAIN_PARAMS_H */ diff -Nru ffmpeg-4.2.2/libavutil/fixed_dsp.c ffmpeg-4.4/libavutil/fixed_dsp.c --- ffmpeg-4.2.2/libavutil/fixed_dsp.c 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavutil/fixed_dsp.c 2021-02-20 20:27:47.000000000 +0000 @@ -134,9 +134,10 @@ return (int)(p >> 31); } -static void butterflies_fixed_c(int *v1, int *v2, int len) +static void butterflies_fixed_c(int *v1s, int *v2, int len) { int i; + unsigned int *v1 = v1s; for (i = 0; i < len; i++){ int t = v1[i] - v2[i]; diff -Nru ffmpeg-4.2.2/libavutil/frame.c ffmpeg-4.4/libavutil/frame.c --- ffmpeg-4.2.2/libavutil/frame.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/frame.c 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,7 @@ #include "imgutils.h" #include "mem.h" #include "samplefmt.h" +#include "hwcontext.h" #if FF_API_FRAME_GET_SET MAKE_ACCESSORS(AVFrame, frame, int64_t, best_effort_timestamp) @@ -211,8 +212,10 @@ static int get_video_buffer(AVFrame *frame, int align) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); - int ret, i, padded_height; + int ret, i, padded_height, total_size; int plane_padding = FFMAX(16 + 16/*STRIDE_ALIGN*/, align); + ptrdiff_t linesizes[4]; + size_t sizes[4]; if (!desc) return AVERROR(EINVAL); @@ -237,12 +240,22 @@ frame->linesize[i] = FFALIGN(frame->linesize[i], align); } + for (i = 0; i < 4; i++) + linesizes[i] = frame->linesize[i]; + padded_height = FFALIGN(frame->height, 32); - if ((ret = av_image_fill_pointers(frame->data, frame->format, padded_height, - NULL, frame->linesize)) < 0) + if ((ret = av_image_fill_plane_sizes(sizes, frame->format, + padded_height, linesizes)) < 0) return ret; - frame->buf[0] = av_buffer_alloc(ret + 4*plane_padding); + total_size = 4*plane_padding; + for (i = 0; i < 4; i++) { + if (sizes[i] > INT_MAX - total_size) + return AVERROR(EINVAL); + total_size += sizes[i]; + } + + frame->buf[0] = av_buffer_alloc(total_size); if (!frame->buf[0]) { ret = AVERROR(ENOMEM); goto fail; @@ -336,7 +349,7 @@ static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy) { - int i; + int ret, i; dst->key_frame = src->key_frame; dst->pict_type = src->pict_type; @@ -413,31 +426,18 @@ dst->qscale_table = NULL; dst->qstride = 0; dst->qscale_type = 0; - av_buffer_unref(&dst->qp_table_buf); - if (src->qp_table_buf) { - dst->qp_table_buf = av_buffer_ref(src->qp_table_buf); - if (dst->qp_table_buf) { - dst->qscale_table = dst->qp_table_buf->data; - dst->qstride = src->qstride; - dst->qscale_type = src->qscale_type; - } + av_buffer_replace(&dst->qp_table_buf, src->qp_table_buf); + if (dst->qp_table_buf) { + dst->qscale_table = dst->qp_table_buf->data; + dst->qstride = src->qstride; + dst->qscale_type = src->qscale_type; } FF_ENABLE_DEPRECATION_WARNINGS #endif - av_buffer_unref(&dst->opaque_ref); - av_buffer_unref(&dst->private_ref); - if (src->opaque_ref) { - dst->opaque_ref = av_buffer_ref(src->opaque_ref); - if (!dst->opaque_ref) - return AVERROR(ENOMEM); - } - if (src->private_ref) { - dst->private_ref = av_buffer_ref(src->private_ref); - if (!dst->private_ref) - return AVERROR(ENOMEM); - } - return 0; + ret = av_buffer_replace(&dst->opaque_ref, src->opaque_ref); + ret |= av_buffer_replace(&dst->private_ref, src->private_ref); + return ret; } int av_frame_ref(AVFrame *dst, const AVFrame *src) @@ -456,17 +456,17 @@ ret = frame_copy_props(dst, src, 0); if (ret < 0) - return ret; + goto fail; /* duplicate the frame data if it's not refcounted */ if (!src->buf[0]) { - ret = av_frame_get_buffer(dst, 32); + ret = av_frame_get_buffer(dst, 0); if (ret < 0) - return ret; + goto fail; ret = av_frame_copy(dst, src); if (ret < 0) - av_frame_unref(dst); + goto fail; return ret; } @@ -626,7 +626,11 @@ tmp.channels = frame->channels; tmp.channel_layout = frame->channel_layout; tmp.nb_samples = frame->nb_samples; - ret = av_frame_get_buffer(&tmp, 32); + + if (frame->hw_frames_ctx) + ret = av_hwframe_get_buffer(frame->hw_frames_ctx, &tmp, 0); + else + ret = av_frame_get_buffer(&tmp, 0); if (ret < 0) return ret; @@ -721,7 +725,7 @@ AVFrameSideData *av_frame_new_side_data(AVFrame *frame, enum AVFrameSideDataType type, - int size) + buffer_size_t size) { AVFrameSideData *ret; AVBufferRef *buf = av_buffer_alloc(size); @@ -752,6 +756,9 @@ dst->height < src->height) return AVERROR(EINVAL); + if (src->hw_frames_ctx || dst->hw_frames_ctx) + return av_hwframe_transfer_data(dst, src, 0); + planes = av_pix_fmt_count_planes(dst->format); for (i = 0; i < planes; i++) if (!dst->data[i] || !src->data[i]) @@ -806,7 +813,7 @@ { int i; - for (i = 0; i < frame->nb_side_data; i++) { + for (i = frame->nb_side_data - 1; i >= 0; i--) { AVFrameSideData *sd = frame->side_data[i]; if (sd->type == type) { free_side_data(&frame->side_data[i]); @@ -842,6 +849,9 @@ #endif case AV_FRAME_DATA_DYNAMIC_HDR_PLUS: return "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)"; case AV_FRAME_DATA_REGIONS_OF_INTEREST: return "Regions Of Interest"; + case AV_FRAME_DATA_VIDEO_ENC_PARAMS: return "Video encoding parameters"; + case AV_FRAME_DATA_SEI_UNREGISTERED: return "H.26[45] User Data Unregistered SEI message"; + case AV_FRAME_DATA_FILM_GRAIN_PARAMS: return "Film grain parameters"; } return NULL; } diff -Nru ffmpeg-4.2.2/libavutil/frame.h ffmpeg-4.4/libavutil/frame.h --- ffmpeg-4.2.2/libavutil/frame.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/frame.h 2021-04-08 21:28:40.000000000 +0000 @@ -162,8 +162,8 @@ /** * Timecode which conforms to SMPTE ST 12-1. The data is an array of 4 uint32_t * where the first uint32_t describes how many (1-3) of the other timecodes are used. - * The timecode format is described in the av_timecode_get_smpte_from_framenum() - * function in libavutil/timecode.c. + * The timecode format is described in the documentation of av_timecode_get_smpte_from_framenum() + * function in libavutil/timecode.h. */ AV_FRAME_DATA_S12M_TIMECODE, @@ -179,6 +179,25 @@ * array element is implied by AVFrameSideData.size / AVRegionOfInterest.self_size. */ AV_FRAME_DATA_REGIONS_OF_INTEREST, + + /** + * Encoding parameters for a video frame, as described by AVVideoEncParams. + */ + AV_FRAME_DATA_VIDEO_ENC_PARAMS, + + /** + * User data unregistered metadata associated with a video frame. + * This is the H.26[45] UDU SEI message, and shouldn't be used for any other purpose + * The data is stored as uint8_t in AVFrameSideData.data which is 16 bytes of + * uuid_iso_iec_11578 followed by AVFrameSideData.size - 16 bytes of user_data_payload_byte. + */ + AV_FRAME_DATA_SEI_UNREGISTERED, + + /** + * Film grain parameters for a frame, described by AVFilmGrainParams. + * Must be present for every frame which should have film grain applied. + */ + AV_FRAME_DATA_FILM_GRAIN_PARAMS, }; enum AVActiveFormatDescription { @@ -201,7 +220,11 @@ typedef struct AVFrameSideData { enum AVFrameSideDataType type; uint8_t *data; +#if FF_API_BUFFER_SIZE_T int size; +#else + size_t size; +#endif AVDictionary *metadata; AVBufferRef *buf; } AVFrameSideData; @@ -894,7 +917,11 @@ */ AVFrameSideData *av_frame_new_side_data(AVFrame *frame, enum AVFrameSideDataType type, +#if FF_API_BUFFER_SIZE_T int size); +#else + size_t size); +#endif /** * Add a new side data to a frame from an existing AVBufferRef @@ -920,8 +947,7 @@ enum AVFrameSideDataType type); /** - * If side data of the supplied type exists in the frame, free it and remove it - * from the frame. + * Remove and free all side data instances of the given type. */ void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type); diff -Nru ffmpeg-4.2.2/libavutil/hash.c ffmpeg-4.4/libavutil/hash.c --- ffmpeg-4.2.2/libavutil/hash.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hash.c 2021-04-08 21:28:40.000000000 +0000 @@ -17,6 +17,8 @@ * 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 "hash.h" diff -Nru ffmpeg-4.2.2/libavutil/hash.h ffmpeg-4.4/libavutil/hash.h --- ffmpeg-4.2.2/libavutil/hash.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hash.h 2021-04-08 21:28:40.000000000 +0000 @@ -27,6 +27,7 @@ #ifndef AVUTIL_HASH_H #define AVUTIL_HASH_H +#include #include #include "version.h" diff -Nru ffmpeg-4.2.2/libavutil/hwcontext.c ffmpeg-4.4/libavutil/hwcontext.c --- ffmpeg-4.2.2/libavutil/hwcontext.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext.c 2020-07-11 10:39:30.000000000 +0000 @@ -59,6 +59,9 @@ #if CONFIG_MEDIACODEC &ff_hwcontext_type_mediacodec, #endif +#if CONFIG_VULKAN + &ff_hwcontext_type_vulkan, +#endif NULL, }; @@ -73,6 +76,7 @@ [AV_HWDEVICE_TYPE_VDPAU] = "vdpau", [AV_HWDEVICE_TYPE_VIDEOTOOLBOX] = "videotoolbox", [AV_HWDEVICE_TYPE_MEDIACODEC] = "mediacodec", + [AV_HWDEVICE_TYPE_VULKAN] = "vulkan", }; enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name) @@ -418,7 +422,7 @@ frame_tmp->width = ctx->width; frame_tmp->height = ctx->height; - ret = av_frame_get_buffer(frame_tmp, 32); + ret = av_frame_get_buffer(frame_tmp, 0); if (ret < 0) goto fail; @@ -444,21 +448,54 @@ if (!dst->buf[0]) return transfer_data_alloc(dst, src, flags); - if (src->hw_frames_ctx) { - ctx = (AVHWFramesContext*)src->hw_frames_ctx->data; + /* + * Hardware -> Hardware Transfer. + * Unlike Software -> Hardware or Hardware -> Software, the transfer + * function could be provided by either the src or dst, depending on + * the specific combination of hardware. + */ + if (src->hw_frames_ctx && dst->hw_frames_ctx) { + AVHWFramesContext *src_ctx = + (AVHWFramesContext*)src->hw_frames_ctx->data; + AVHWFramesContext *dst_ctx = + (AVHWFramesContext*)dst->hw_frames_ctx->data; + + if (src_ctx->internal->source_frames) { + av_log(src_ctx, AV_LOG_ERROR, + "A device with a derived frame context cannot be used as " + "the source of a HW -> HW transfer."); + return AVERROR(ENOSYS); + } - ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src); - if (ret < 0) - return ret; - } else if (dst->hw_frames_ctx) { - ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data; + if (dst_ctx->internal->source_frames) { + av_log(src_ctx, AV_LOG_ERROR, + "A device with a derived frame context cannot be used as " + "the destination of a HW -> HW transfer."); + return AVERROR(ENOSYS); + } - ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src); + ret = src_ctx->internal->hw_type->transfer_data_from(src_ctx, dst, src); + if (ret == AVERROR(ENOSYS)) + ret = dst_ctx->internal->hw_type->transfer_data_to(dst_ctx, dst, src); if (ret < 0) return ret; - } else - return AVERROR(ENOSYS); + } else { + if (src->hw_frames_ctx) { + ctx = (AVHWFramesContext*)src->hw_frames_ctx->data; + ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src); + if (ret < 0) + return ret; + } else if (dst->hw_frames_ctx) { + ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data; + + ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src); + if (ret < 0) + return ret; + } else { + return AVERROR(ENOSYS); + } + } return 0; } @@ -520,6 +557,8 @@ return ret; } + frame->extended_data = frame->data; + return 0; } @@ -604,9 +643,10 @@ return ret; } -int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, - enum AVHWDeviceType type, - AVBufferRef *src_ref, int flags) +int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, + enum AVHWDeviceType type, + AVBufferRef *src_ref, + AVDictionary *options, int flags) { AVBufferRef *dst_ref = NULL, *tmp_ref; AVHWDeviceContext *dst_ctx, *tmp_ctx; @@ -639,6 +679,7 @@ if (dst_ctx->internal->hw_type->device_derive) { ret = dst_ctx->internal->hw_type->device_derive(dst_ctx, tmp_ctx, + options, flags); if (ret == 0) { dst_ctx->internal->source_device = av_buffer_ref(src_ref); @@ -670,6 +711,14 @@ return ret; } +int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, + enum AVHWDeviceType type, + AVBufferRef *src_ref, int flags) +{ + return av_hwdevice_ctx_create_derived_opts(dst_ref_ptr, type, src_ref, + NULL, flags); +} + static void ff_hwframe_unmap(void *opaque, uint8_t *data) { HWMapDescriptor *hwmap = (HWMapDescriptor*)data; diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_cuda.c ffmpeg-4.4/libavutil/hwcontext_cuda.c --- ffmpeg-4.2.2/libavutil/hwcontext_cuda.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_cuda.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,27 +21,33 @@ #include "hwcontext.h" #include "hwcontext_internal.h" #include "hwcontext_cuda_internal.h" +#if CONFIG_VULKAN +#include "hwcontext_vulkan.h" +#endif #include "cuda_check.h" #include "mem.h" #include "pixdesc.h" #include "pixfmt.h" #include "imgutils.h" -#define CUDA_FRAME_ALIGNMENT 256 - typedef struct CUDAFramesContext { int shift_width, shift_height; + int tex_alignment; } CUDAFramesContext; static const enum AVPixelFormat supported_formats[] = { AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_P010, AV_PIX_FMT_P016, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_0RGB32, AV_PIX_FMT_0BGR32, +#if CONFIG_VULKAN + AV_PIX_FMT_VULKAN, +#endif }; #define CHECK_CU(x) FF_CUDA_CHECK_DL(device_ctx, cu, x) @@ -87,7 +93,7 @@ CHECK_CU(cu->cuCtxPopCurrent(&dummy)); } -static AVBufferRef *cuda_pool_alloc(void *opaque, int size) +static AVBufferRef *cuda_pool_alloc(void *opaque, buffer_size_t size) { AVHWFramesContext *ctx = opaque; AVHWDeviceContext *device_ctx = ctx->device_ctx; @@ -120,8 +126,11 @@ static int cuda_frames_init(AVHWFramesContext *ctx) { - CUDAFramesContext *priv = ctx->internal->priv; - int i; + AVHWDeviceContext *device_ctx = ctx->device_ctx; + AVCUDADeviceContext *hwctx = device_ctx->hwctx; + CUDAFramesContext *priv = ctx->internal->priv; + CudaFunctions *cu = hwctx->internal->cuda_dl; + int err, i; for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) { if (ctx->sw_format == supported_formats[i]) @@ -133,10 +142,24 @@ return AVERROR(ENOSYS); } + err = CHECK_CU(cu->cuDeviceGetAttribute(&priv->tex_alignment, + 14 /* CU_DEVICE_ATTRIBUTE_TEXTURE_ALIGNMENT */, + hwctx->internal->cuda_device)); + if (err < 0) + return err; + + av_log(ctx, AV_LOG_DEBUG, "CUDA texture alignment: %d\n", priv->tex_alignment); + + // YUV420P is a special case. + // Since nvenc expects the U/V planes to have half the linesize of the Y plane + // alignment has to be doubled to ensure the U/V planes still end up aligned. + if (ctx->sw_format == AV_PIX_FMT_YUV420P) + priv->tex_alignment *= 2; + av_pix_fmt_get_chroma_sub_sample(ctx->sw_format, &priv->shift_width, &priv->shift_height); if (!ctx->pool) { - int size = av_image_get_buffer_size(ctx->sw_format, ctx->width, ctx->height, CUDA_FRAME_ALIGNMENT); + int size = av_image_get_buffer_size(ctx->sw_format, ctx->width, ctx->height, priv->tex_alignment); if (size < 0) return size; @@ -150,6 +173,7 @@ static int cuda_get_buffer(AVHWFramesContext *ctx, AVFrame *frame) { + CUDAFramesContext *priv = ctx->internal->priv; int res; frame->buf[0] = av_buffer_pool_get(ctx->pool); @@ -157,7 +181,7 @@ return AVERROR(ENOMEM); res = av_image_fill_arrays(frame->data, frame->linesize, frame->buf[0]->data, - ctx->sw_format, ctx->width, ctx->height, CUDA_FRAME_ALIGNMENT); + ctx->sw_format, ctx->width, ctx->height, priv->tex_alignment); if (res < 0) return res; @@ -166,7 +190,7 @@ if (ctx->sw_format == AV_PIX_FMT_YUV420P) { frame->linesize[1] = frame->linesize[2] = frame->linesize[0] / 2; frame->data[2] = frame->data[1]; - frame->data[1] = frame->data[2] + frame->linesize[2] * ctx->height / 2; + frame->data[1] = frame->data[2] + frame->linesize[2] * (ctx->height / 2); } frame->format = AV_PIX_FMT_CUDA; @@ -194,8 +218,8 @@ return 0; } -static int cuda_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, - const AVFrame *src) +static int cuda_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src) { CUDAFramesContext *priv = ctx->internal->priv; AVHWDeviceContext *device_ctx = ctx->device_ctx; @@ -205,65 +229,45 @@ CUcontext dummy; int i, ret; + if ((src->hw_frames_ctx && ((AVHWFramesContext*)src->hw_frames_ctx->data)->format != AV_PIX_FMT_CUDA) || + (dst->hw_frames_ctx && ((AVHWFramesContext*)dst->hw_frames_ctx->data)->format != AV_PIX_FMT_CUDA)) + return AVERROR(ENOSYS); + ret = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx)); if (ret < 0) return ret; for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->data[i]; i++) { CUDA_MEMCPY2D cpy = { - .srcMemoryType = CU_MEMORYTYPE_DEVICE, - .dstMemoryType = CU_MEMORYTYPE_HOST, - .srcDevice = (CUdeviceptr)src->data[i], - .dstHost = dst->data[i], .srcPitch = src->linesize[i], .dstPitch = dst->linesize[i], .WidthInBytes = FFMIN(src->linesize[i], dst->linesize[i]), - .Height = src->height >> (i ? priv->shift_height : 0), + .Height = src->height >> ((i == 0 || i == 3) ? 0 : priv->shift_height), }; + if (src->hw_frames_ctx) { + cpy.srcMemoryType = CU_MEMORYTYPE_DEVICE; + cpy.srcDevice = (CUdeviceptr)src->data[i]; + } else { + cpy.srcMemoryType = CU_MEMORYTYPE_HOST; + cpy.srcHost = src->data[i]; + } + + if (dst->hw_frames_ctx) { + cpy.dstMemoryType = CU_MEMORYTYPE_DEVICE; + cpy.dstDevice = (CUdeviceptr)dst->data[i]; + } else { + cpy.dstMemoryType = CU_MEMORYTYPE_HOST; + cpy.dstHost = dst->data[i]; + } + ret = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, hwctx->stream)); if (ret < 0) goto exit; } - ret = CHECK_CU(cu->cuStreamSynchronize(hwctx->stream)); - if (ret < 0) - goto exit; - -exit: - CHECK_CU(cu->cuCtxPopCurrent(&dummy)); - - return 0; -} - -static int cuda_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, - const AVFrame *src) -{ - CUDAFramesContext *priv = ctx->internal->priv; - AVHWDeviceContext *device_ctx = ctx->device_ctx; - AVCUDADeviceContext *hwctx = device_ctx->hwctx; - CudaFunctions *cu = hwctx->internal->cuda_dl; - - CUcontext dummy; - int i, ret; - - ret = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx)); - if (ret < 0) - return ret; - - for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->data[i]; i++) { - CUDA_MEMCPY2D cpy = { - .srcMemoryType = CU_MEMORYTYPE_HOST, - .dstMemoryType = CU_MEMORYTYPE_DEVICE, - .srcHost = src->data[i], - .dstDevice = (CUdeviceptr)dst->data[i], - .srcPitch = src->linesize[i], - .dstPitch = dst->linesize[i], - .WidthInBytes = FFMIN(src->linesize[i], dst->linesize[i]), - .Height = src->height >> (i ? priv->shift_height : 0), - }; - - ret = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, hwctx->stream)); + if (!dst->hw_frames_ctx) { + ret = CHECK_CU(cu->cuStreamSynchronize(hwctx->stream)); if (ret < 0) goto exit; } @@ -280,10 +284,16 @@ if (hwctx->internal) { CudaFunctions *cu = hwctx->internal->cuda_dl; + if (hwctx->internal->is_allocated && hwctx->cuda_ctx) { - CHECK_CU(cu->cuCtxDestroy(hwctx->cuda_ctx)); + if (hwctx->internal->flags & AV_CUDA_USE_PRIMARY_CONTEXT) + CHECK_CU(cu->cuDevicePrimaryCtxRelease(hwctx->internal->cuda_device)); + else + CHECK_CU(cu->cuCtxDestroy(hwctx->cuda_ctx)); + hwctx->cuda_ctx = NULL; } + cuda_free_functions(&hwctx->internal->cuda_dl); } @@ -316,14 +326,62 @@ return ret; } +static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) { + AVCUDADeviceContext *hwctx = device_ctx->hwctx; + CudaFunctions *cu; + CUcontext dummy; + int ret, dev_active = 0; + unsigned int dev_flags = 0; + + const unsigned int desired_flags = CU_CTX_SCHED_BLOCKING_SYNC; + + cu = hwctx->internal->cuda_dl; + + hwctx->internal->flags = flags; + + if (flags & AV_CUDA_USE_PRIMARY_CONTEXT) { + ret = CHECK_CU(cu->cuDevicePrimaryCtxGetState(hwctx->internal->cuda_device, + &dev_flags, &dev_active)); + if (ret < 0) + return ret; + + if (dev_active && dev_flags != desired_flags) { + av_log(device_ctx, AV_LOG_ERROR, "Primary context already active with incompatible flags.\n"); + return AVERROR(ENOTSUP); + } else if (dev_flags != desired_flags) { + ret = CHECK_CU(cu->cuDevicePrimaryCtxSetFlags(hwctx->internal->cuda_device, + desired_flags)); + if (ret < 0) + return ret; + } + + ret = CHECK_CU(cu->cuDevicePrimaryCtxRetain(&hwctx->cuda_ctx, + hwctx->internal->cuda_device)); + if (ret < 0) + return ret; + } else { + ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx, desired_flags, + hwctx->internal->cuda_device)); + if (ret < 0) + return ret; + + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + } + + hwctx->internal->is_allocated = 1; + + // Setting stream to NULL will make functions automatically use the default CUstream + hwctx->stream = NULL; + + return 0; +} + static int cuda_device_create(AVHWDeviceContext *device_ctx, const char *device, AVDictionary *opts, int flags) { AVCUDADeviceContext *hwctx = device_ctx->hwctx; CudaFunctions *cu; - CUdevice cu_device; - CUcontext dummy; int ret, device_idx = 0; if (device) @@ -338,20 +396,98 @@ if (ret < 0) goto error; - ret = CHECK_CU(cu->cuDeviceGet(&cu_device, device_idx)); + ret = CHECK_CU(cu->cuDeviceGet(&hwctx->internal->cuda_device, device_idx)); if (ret < 0) goto error; - ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx, CU_CTX_SCHED_BLOCKING_SYNC, cu_device)); + ret = cuda_context_init(device_ctx, flags); if (ret < 0) goto error; - // Setting stream to NULL will make functions automatically use the default CUstream - hwctx->stream = NULL; + return 0; - CHECK_CU(cu->cuCtxPopCurrent(&dummy)); +error: + cuda_device_uninit(device_ctx); + return AVERROR_UNKNOWN; +} - hwctx->internal->is_allocated = 1; +static int cuda_device_derive(AVHWDeviceContext *device_ctx, + AVHWDeviceContext *src_ctx, AVDictionary *opts, + int flags) { + AVCUDADeviceContext *hwctx = device_ctx->hwctx; + CudaFunctions *cu; + const char *src_uuid = NULL; + int ret, i, device_count; + +#if CONFIG_VULKAN + VkPhysicalDeviceIDProperties vk_idp = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES, + }; +#endif + + switch (src_ctx->type) { +#if CONFIG_VULKAN + case AV_HWDEVICE_TYPE_VULKAN: { + AVVulkanDeviceContext *vkctx = src_ctx->hwctx; + VkPhysicalDeviceProperties2 vk_dev_props = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &vk_idp, + }; + vkGetPhysicalDeviceProperties2(vkctx->phys_dev, &vk_dev_props); + src_uuid = vk_idp.deviceUUID; + break; + } +#endif + default: + return AVERROR(ENOSYS); + } + + if (!src_uuid) { + av_log(device_ctx, AV_LOG_ERROR, + "Failed to get UUID of source device.\n"); + goto error; + } + + if (cuda_device_init(device_ctx) < 0) + goto error; + + cu = hwctx->internal->cuda_dl; + + ret = CHECK_CU(cu->cuInit(0)); + if (ret < 0) + goto error; + + ret = CHECK_CU(cu->cuDeviceGetCount(&device_count)); + if (ret < 0) + goto error; + + hwctx->internal->cuda_device = -1; + for (i = 0; i < device_count; i++) { + CUdevice dev; + CUuuid uuid; + + ret = CHECK_CU(cu->cuDeviceGet(&dev, i)); + if (ret < 0) + goto error; + + ret = CHECK_CU(cu->cuDeviceGetUuid(&uuid, dev)); + if (ret < 0) + goto error; + + if (memcmp(src_uuid, uuid.bytes, sizeof (uuid.bytes)) == 0) { + hwctx->internal->cuda_device = dev; + break; + } + } + + if (hwctx->internal->cuda_device == -1) { + av_log(device_ctx, AV_LOG_ERROR, "Could not derive CUDA device.\n"); + goto error; + } + + ret = cuda_context_init(device_ctx, flags); + if (ret < 0) + goto error; return 0; @@ -368,14 +504,15 @@ .frames_priv_size = sizeof(CUDAFramesContext), .device_create = cuda_device_create, + .device_derive = cuda_device_derive, .device_init = cuda_device_init, .device_uninit = cuda_device_uninit, .frames_get_constraints = cuda_frames_get_constraints, .frames_init = cuda_frames_init, .frames_get_buffer = cuda_get_buffer, .transfer_get_formats = cuda_transfer_get_formats, - .transfer_data_to = cuda_transfer_data_to, - .transfer_data_from = cuda_transfer_data_from, + .transfer_data_to = cuda_transfer_data, + .transfer_data_from = cuda_transfer_data, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE }, }; diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_cuda.h ffmpeg-4.4/libavutil/hwcontext_cuda.h --- ffmpeg-4.2.2/libavutil/hwcontext_cuda.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_cuda.h 2020-07-11 10:39:30.000000000 +0000 @@ -49,4 +49,21 @@ * AVHWFramesContext.hwctx is currently not used */ +/** + * @defgroup hwcontext_cuda Device context creation flags + * + * Flags for av_hwdevice_ctx_create. + * + * @{ + */ + +/** + * Use primary device context instead of creating a new one. + */ +#define AV_CUDA_USE_PRIMARY_CONTEXT (1 << 0) + +/** + * @} + */ + #endif /* AVUTIL_HWCONTEXT_CUDA_H */ diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_cuda_internal.h ffmpeg-4.4/libavutil/hwcontext_cuda_internal.h --- ffmpeg-4.2.2/libavutil/hwcontext_cuda_internal.h 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_cuda_internal.h 2020-07-11 10:39:30.000000000 +0000 @@ -31,6 +31,8 @@ struct AVCUDADeviceContextInternal { CudaFunctions *cuda_dl; int is_allocated; + CUdevice cuda_device; + int flags; }; #endif /* AVUTIL_HWCONTEXT_CUDA_INTERNAL_H */ diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_d3d11va.c ffmpeg-4.4/libavutil/hwcontext_d3d11va.c --- ffmpeg-4.2.2/libavutil/hwcontext_d3d11va.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_d3d11va.c 2021-04-08 21:28:40.000000000 +0000 @@ -39,6 +39,7 @@ #include "pixdesc.h" #include "pixfmt.h" #include "thread.h" +#include "compat/w32dlfcn.h" typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory); @@ -55,8 +56,8 @@ // from too many LoadLibrary calls. HANDLE d3dlib, dxgilib; - d3dlib = LoadLibrary("d3d11.dll"); - dxgilib = LoadLibrary("dxgi.dll"); + d3dlib = dlopen("d3d11.dll", 0); + dxgilib = dlopen("dxgi.dll", 0); if (!d3dlib || !dxgilib) return; @@ -201,7 +202,7 @@ return wrap_texture_buf(tex, 0); } -static AVBufferRef *d3d11va_pool_alloc(void *opaque, int size) +static AVBufferRef *d3d11va_pool_alloc(void *opaque, buffer_size_t size) { AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; D3D11VAFramesContext *s = ctx->internal->priv; diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_drm.c ffmpeg-4.4/libavutil/hwcontext_drm.c --- ffmpeg-4.2.2/libavutil/hwcontext_drm.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_drm.c 2021-04-08 21:28:40.000000000 +0000 @@ -16,10 +16,20 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + #include #include #include +/* This was introduced in version 4.6. And may not exist all without an + * optional package. So to prevent a hard dependency on needing the Linux + * kernel headers to compile, make this optional. */ +#if HAVE_LINUX_DMA_BUF_H +#include +#include +#endif + #include #include @@ -85,6 +95,8 @@ typedef struct DRMMapping { // Address and length of each mmap()ed region. int nb_regions; + int sync_flags; + int object[AV_DRM_MAX_PLANES]; void *address[AV_DRM_MAX_PLANES]; size_t length[AV_DRM_MAX_PLANES]; } DRMMapping; @@ -93,10 +105,14 @@ HWMapDescriptor *hwmap) { DRMMapping *map = hwmap->priv; - int i; - for (i = 0; i < map->nb_regions; i++) + for (int i = 0; i < map->nb_regions; i++) { +#if HAVE_LINUX_DMA_BUF_H + struct dma_buf_sync sync = { .flags = DMA_BUF_SYNC_END | map->sync_flags }; + ioctl(map->object[i], DMA_BUF_IOCTL_SYNC, &sync); +#endif munmap(map->address[i], map->length[i]); + } av_free(map); } @@ -105,6 +121,9 @@ AVFrame *dst, const AVFrame *src, int flags) { const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor*)src->data[0]; +#if HAVE_LINUX_DMA_BUF_H + struct dma_buf_sync sync_start = { 0 }; +#endif DRMMapping *map; int err, i, p, plane; int mmap_prot; @@ -120,6 +139,14 @@ if (flags & AV_HWFRAME_MAP_WRITE) mmap_prot |= PROT_WRITE; +#if HAVE_LINUX_DMA_BUF_H + if (flags & AV_HWFRAME_MAP_READ) + map->sync_flags |= DMA_BUF_SYNC_READ; + if (flags & AV_HWFRAME_MAP_WRITE) + map->sync_flags |= DMA_BUF_SYNC_WRITE; + sync_start.flags = DMA_BUF_SYNC_START | map->sync_flags; +#endif + av_assert0(desc->nb_objects <= AV_DRM_MAX_PLANES); for (i = 0; i < desc->nb_objects; i++) { addr = mmap(NULL, desc->objects[i].size, mmap_prot, MAP_SHARED, @@ -133,6 +160,13 @@ map->address[i] = addr; map->length[i] = desc->objects[i].size; + map->object[i] = desc->objects[i].fd; + +#if HAVE_LINUX_DMA_BUF_H + /* We're not checking for errors here because the kernel may not + * support the ioctl, in which case its okay to carry on */ + ioctl(desc->objects[i].fd, DMA_BUF_IOCTL_SYNC, &sync_start); +#endif } map->nb_regions = i; diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_dxva2.c ffmpeg-4.4/libavutil/hwcontext_dxva2.c --- ffmpeg-4.2.2/libavutil/hwcontext_dxva2.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_dxva2.c 2021-04-08 21:28:40.000000000 +0000 @@ -124,7 +124,7 @@ // released in dxva2_frames_uninit() } -static AVBufferRef *dxva2_pool_alloc(void *opaque, int size) +static AVBufferRef *dxva2_pool_alloc(void *opaque, buffer_size_t size) { AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; DXVA2FramesContext *s = ctx->internal->priv; diff -Nru ffmpeg-4.2.2/libavutil/hwcontext.h ffmpeg-4.4/libavutil/hwcontext.h --- ffmpeg-4.2.2/libavutil/hwcontext.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext.h 2020-07-11 10:39:30.000000000 +0000 @@ -36,6 +36,7 @@ AV_HWDEVICE_TYPE_DRM, AV_HWDEVICE_TYPE_OPENCL, AV_HWDEVICE_TYPE_MEDIACODEC, + AV_HWDEVICE_TYPE_VULKAN, }; typedef struct AVHWDeviceInternal AVHWDeviceInternal; @@ -327,6 +328,26 @@ enum AVHWDeviceType type, AVBufferRef *src_ctx, int flags); +/** + * Create a new device of the specified type from an existing device. + * + * This function performs the same action as av_hwdevice_ctx_create_derived, + * however, it is able to set options for the new device to be derived. + * + * @param dst_ctx On success, a reference to the newly-created + * AVHWDeviceContext. + * @param type The type of the new device to create. + * @param src_ctx A reference to an existing AVHWDeviceContext which will be + * used to create the new device. + * @param options Options for the new device to create, same format as in + * av_hwdevice_ctx_create. + * @param flags Currently unused; should be set to zero. + * @return Zero on success, a negative AVERROR code on failure. + */ +int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ctx, + enum AVHWDeviceType type, + AVBufferRef *src_ctx, + AVDictionary *options, int flags); /** * Allocate an AVHWFramesContext tied to a given device context. diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_internal.h ffmpeg-4.4/libavutil/hwcontext_internal.h --- ffmpeg-4.2.2/libavutil/hwcontext_internal.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_internal.h 2020-07-11 10:39:30.000000000 +0000 @@ -67,7 +67,8 @@ int (*device_create)(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags); int (*device_derive)(AVHWDeviceContext *dst_ctx, - AVHWDeviceContext *src_ctx, int flags); + AVHWDeviceContext *src_ctx, + AVDictionary *opts, int flags); int (*device_init)(AVHWDeviceContext *ctx); void (*device_uninit)(AVHWDeviceContext *ctx); @@ -172,5 +173,6 @@ extern const HWContextType ff_hwcontext_type_vdpau; extern const HWContextType ff_hwcontext_type_videotoolbox; extern const HWContextType ff_hwcontext_type_mediacodec; +extern const HWContextType ff_hwcontext_type_vulkan; #endif /* AVUTIL_HWCONTEXT_INTERNAL_H */ diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_opencl.c ffmpeg-4.4/libavutil/hwcontext_opencl.c --- ffmpeg-4.2.2/libavutil/hwcontext_opencl.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_opencl.c 2021-04-08 21:28:40.000000000 +0000 @@ -1194,7 +1194,7 @@ #endif static int opencl_device_derive(AVHWDeviceContext *hwdev, - AVHWDeviceContext *src_ctx, + AVHWDeviceContext *src_ctx, AVDictionary *opts, int flags) { int err; @@ -1207,16 +1207,16 @@ // Surface mapping works via DRM PRIME fds with no special // initialisation required in advance. This just finds the // Beignet ICD by name. - AVDictionary *opts = NULL; + AVDictionary *selector_opts = NULL; - err = av_dict_set(&opts, "platform_vendor", "Intel", 0); + err = av_dict_set(&selector_opts, "platform_vendor", "Intel", 0); if (err >= 0) - err = av_dict_set(&opts, "platform_version", "beignet", 0); + err = av_dict_set(&selector_opts, "platform_version", "beignet", 0); if (err >= 0) { OpenCLDeviceSelector selector = { .platform_index = -1, .device_index = 0, - .context = opts, + .context = selector_opts, .enumerate_platforms = &opencl_enumerate_platforms, .filter_platform = &opencl_filter_platform, .enumerate_devices = &opencl_enumerate_devices, @@ -1224,7 +1224,7 @@ }; err = opencl_device_create_internal(hwdev, &selector, NULL); } - av_dict_free(&opts); + av_dict_free(&selector_opts); } break; #endif @@ -1617,7 +1617,7 @@ av_free(desc); } -static AVBufferRef *opencl_pool_alloc(void *opaque, int size) +static AVBufferRef *opencl_pool_alloc(void *opaque, buffer_size_t size) { AVHWFramesContext *hwfc = opaque; AVOpenCLDeviceContext *hwctx = hwfc->device_ctx->hwctx; diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_qsv.c ffmpeg-4.4/libavutil/hwcontext_qsv.c --- ffmpeg-4.2.2/libavutil/hwcontext_qsv.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_qsv.c 2021-04-08 21:28:40.000000000 +0000 @@ -44,6 +44,10 @@ #include "pixdesc.h" #include "time.h" +#define QSV_VERSION_ATLEAST(MAJOR, MINOR) \ + (MFX_VERSION_MAJOR > (MAJOR) || \ + MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR)) + typedef struct QSVDevicePriv { AVBufferRef *child_device_ctx; } QSVDevicePriv; @@ -103,6 +107,14 @@ { AV_PIX_FMT_BGRA, MFX_FOURCC_RGB4 }, { AV_PIX_FMT_P010, MFX_FOURCC_P010 }, { AV_PIX_FMT_PAL8, MFX_FOURCC_P8 }, +#if CONFIG_VAAPI + { AV_PIX_FMT_YUYV422, + MFX_FOURCC_YUY2 }, +#if QSV_VERSION_ATLEAST(1, 27) + { AV_PIX_FMT_Y210, + MFX_FOURCC_Y210 }, +#endif +#endif }; static uint32_t qsv_fourcc_from_pix_fmt(enum AVPixelFormat pix_fmt) @@ -182,7 +194,7 @@ { } -static AVBufferRef *qsv_pool_alloc(void *opaque, int size) +static AVBufferRef *qsv_pool_alloc(void *opaque, buffer_size_t size) { AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; QSVFramesContext *s = ctx->internal->priv; @@ -773,7 +785,19 @@ surface->Data.R = frame->data[0] + 2; surface->Data.A = frame->data[0] + 3; break; +#if CONFIG_VAAPI + case AV_PIX_FMT_YUYV422: + surface->Data.Y = frame->data[0]; + surface->Data.U = frame->data[0] + 1; + surface->Data.V = frame->data[0] + 3; + break; + case AV_PIX_FMT_Y210: + surface->Data.Y16 = (mfxU16 *)frame->data[0]; + surface->Data.U16 = (mfxU16 *)frame->data[0] + 1; + surface->Data.V16 = (mfxU16 *)frame->data[0] + 3; + break; +#endif default: return MFX_ERR_UNSUPPORTED; } @@ -898,7 +922,7 @@ 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, 32); + ret = av_frame_get_buffer(&tmp_frame, 0); if (ret < 0) return ret; @@ -1180,11 +1204,6 @@ goto fail; } - ret = MFXQueryVersion(hwctx->session,&ver); - if (ret == MFX_ERR_NONE) { - av_log(ctx, AV_LOG_VERBOSE, "MFX compile/runtime API: %d.%d/%d.%d\n", - MFX_VERSION_MAJOR, MFX_VERSION_MINOR, ver.Major, ver.Minor); - } return 0; fail: @@ -1194,7 +1213,8 @@ } static int qsv_device_derive(AVHWDeviceContext *ctx, - AVHWDeviceContext *child_device_ctx, int flags) + AVHWDeviceContext *child_device_ctx, + AVDictionary *opts, int flags) { return qsv_device_derive_from_child(ctx, MFX_IMPL_HARDWARE_ANY, child_device_ctx, flags); @@ -1240,6 +1260,8 @@ ret = av_hwdevice_ctx_create(&priv->child_device_ctx, child_device_type, e ? e->value : NULL, child_device_opts, 0); + + av_dict_free(&child_device_opts); if (ret < 0) return ret; diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_vaapi.c ffmpeg-4.4/libavutil/hwcontext_vaapi.c --- ffmpeg-4.2.2/libavutil/hwcontext_vaapi.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_vaapi.c 2021-04-08 21:28:40.000000000 +0000 @@ -116,6 +116,9 @@ #endif MAP(UYVY, YUV422, UYVY422, 0), MAP(YUY2, YUV422, YUYV422, 0), +#ifdef VA_FOURCC_Y210 + MAP(Y210, YUV422_10, Y210, 0), +#endif MAP(411P, YUV411, YUV411P, 0), MAP(422V, YUV422, YUV440P, 0), MAP(444P, YUV444, YUV444P, 0), @@ -133,6 +136,9 @@ #endif MAP(ARGB, RGB32, ARGB, 0), MAP(XRGB, RGB32, 0RGB, 0), +#ifdef VA_FOURCC_X2R10G10B10 + MAP(X2R10G10B10, RGB32_10, X2RGB10, 0), +#endif }; #undef MAP @@ -262,14 +268,24 @@ } for (i = j = 0; i < attr_count; i++) { + int k; + if (attr_list[i].type != VASurfaceAttribPixelFormat) continue; fourcc = attr_list[i].value.value.i; pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc); - if (pix_fmt != AV_PIX_FMT_NONE) + + if (pix_fmt == AV_PIX_FMT_NONE) + continue; + + for (k = 0; k < j; k++) { + if (constraints->valid_sw_formats[k] == pix_fmt) + break; + } + + if (k == j) constraints->valid_sw_formats[j++] = pix_fmt; } - av_assert0(j == pix_fmt_count); constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE; } } else { @@ -281,9 +297,19 @@ err = AVERROR(ENOMEM); goto fail; } - for (i = 0; i < ctx->nb_formats; i++) - constraints->valid_sw_formats[i] = ctx->formats[i].pix_fmt; - constraints->valid_sw_formats[i] = AV_PIX_FMT_NONE; + for (i = j = 0; i < ctx->nb_formats; i++) { + int k; + + for (k = 0; k < j; k++) { + if (constraints->valid_sw_formats[k] == ctx->formats[i].pix_fmt) + break; + } + + if (k == j) + constraints->valid_sw_formats[j++] = ctx->formats[i].pix_fmt; + } + + constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE; } constraints->valid_hw_formats = av_malloc_array(2, sizeof(pix_fmt)); @@ -438,7 +464,7 @@ } } -static AVBufferRef *vaapi_pool_alloc(void *opaque, int size) +static AVBufferRef *vaapi_pool_alloc(void *opaque, buffer_size_t size) { AVHWFramesContext *hwfc = opaque; VAAPIFramesContext *ctx = hwfc->internal->priv; @@ -1621,13 +1647,15 @@ } static int vaapi_device_derive(AVHWDeviceContext *ctx, - AVHWDeviceContext *src_ctx, int flags) + AVHWDeviceContext *src_ctx, + AVDictionary *opts, int flags) { #if HAVE_VAAPI_DRM if (src_ctx->type == AV_HWDEVICE_TYPE_DRM) { AVDRMDeviceContext *src_hwctx = src_ctx->hwctx; VADisplay *display; VAAPIDevicePriv *priv; + int fd; if (src_hwctx->fd < 0) { av_log(ctx, AV_LOG_ERROR, "DRM instance requires an associated " @@ -1635,17 +1663,65 @@ return AVERROR(EINVAL); } +#if CONFIG_LIBDRM + { + int node_type = drmGetNodeTypeFromFd(src_hwctx->fd); + char *render_node; + if (node_type < 0) { + av_log(ctx, AV_LOG_ERROR, "DRM instance fd does not appear " + "to refer to a DRM device.\n"); + return AVERROR(EINVAL); + } + if (node_type == DRM_NODE_RENDER) { + fd = src_hwctx->fd; + } else { + render_node = drmGetRenderDeviceNameFromFd(src_hwctx->fd); + if (!render_node) { + av_log(ctx, AV_LOG_VERBOSE, "Using non-render node " + "because the device does not have an " + "associated render node.\n"); + fd = src_hwctx->fd; + } else { + fd = open(render_node, O_RDWR); + if (fd < 0) { + av_log(ctx, AV_LOG_VERBOSE, "Using non-render node " + "because the associated render node " + "could not be opened.\n"); + fd = src_hwctx->fd; + } else { + av_log(ctx, AV_LOG_VERBOSE, "Using render node %s " + "in place of non-render DRM device.\n", + render_node); + } + free(render_node); + } + } + } +#else + fd = src_hwctx->fd; +#endif + priv = av_mallocz(sizeof(*priv)); - if (!priv) + if (!priv) { + if (fd != src_hwctx->fd) { + // The fd was opened in this function. + close(fd); + } return AVERROR(ENOMEM); + } - // Inherits the fd from the source context, which will close it. - priv->drm_fd = -1; + if (fd == src_hwctx->fd) { + // The fd is inherited from the source context and we are holding + // a reference to that, we don't want to close it from here. + priv->drm_fd = -1; + } else { + priv->drm_fd = fd; + } ctx->user_opaque = priv; ctx->free = &vaapi_device_free; - display = vaGetDisplayDRM(src_hwctx->fd); + display = vaGetDisplayDRM(fd); if (!display) { av_log(ctx, AV_LOG_ERROR, "Failed to open a VA display from " "DRM device.\n"); diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_vdpau.c ffmpeg-4.4/libavutil/hwcontext_vdpau.c --- ffmpeg-4.2.2/libavutil/hwcontext_vdpau.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_vdpau.c 2021-04-08 21:28:40.000000000 +0000 @@ -32,27 +32,6 @@ #include "pixfmt.h" #include "pixdesc.h" -typedef struct VDPAUDeviceContext { - VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *get_transfer_caps; - VdpVideoSurfaceGetBitsYCbCr *get_data; - VdpVideoSurfacePutBitsYCbCr *put_data; - VdpVideoSurfaceCreate *surf_create; - VdpVideoSurfaceDestroy *surf_destroy; - - enum AVPixelFormat *pix_fmts[3]; - int nb_pix_fmts[3]; -} VDPAUDeviceContext; - -typedef struct VDPAUFramesContext { - VdpVideoSurfaceGetBitsYCbCr *get_data; - VdpVideoSurfacePutBitsYCbCr *put_data; - VdpChromaType chroma_type; - int chroma_idx; - - const enum AVPixelFormat *pix_fmts; - int nb_pix_fmts; -} VDPAUFramesContext; - typedef struct VDPAUPixFmtMap { VdpYCbCrFormat vdpau_fmt; enum AVPixelFormat pix_fmt; @@ -61,6 +40,10 @@ static const VDPAUPixFmtMap pix_fmts_420[] = { { VDP_YCBCR_FORMAT_NV12, AV_PIX_FMT_NV12 }, { VDP_YCBCR_FORMAT_YV12, AV_PIX_FMT_YUV420P }, +#ifdef VDP_YCBCR_FORMAT_P016 + { VDP_YCBCR_FORMAT_P016, AV_PIX_FMT_P016 }, + { VDP_YCBCR_FORMAT_P010, AV_PIX_FMT_P010 }, +#endif { 0, AV_PIX_FMT_NONE, }, }; @@ -76,6 +59,9 @@ #ifdef VDP_YCBCR_FORMAT_Y_U_V_444 { VDP_YCBCR_FORMAT_Y_U_V_444, AV_PIX_FMT_YUV444P }, #endif +#ifdef VDP_YCBCR_FORMAT_P016 + {VDP_YCBCR_FORMAT_Y_U_V_444_16, AV_PIX_FMT_YUV444P16}, +#endif { 0, AV_PIX_FMT_NONE, }, }; @@ -87,8 +73,36 @@ { VDP_CHROMA_TYPE_420, AV_PIX_FMT_YUV420P, pix_fmts_420 }, { VDP_CHROMA_TYPE_422, AV_PIX_FMT_YUV422P, pix_fmts_422 }, { VDP_CHROMA_TYPE_444, AV_PIX_FMT_YUV444P, pix_fmts_444 }, +#ifdef VDP_YCBCR_FORMAT_P016 + { VDP_CHROMA_TYPE_420_16, AV_PIX_FMT_YUV420P10, pix_fmts_420 }, + { VDP_CHROMA_TYPE_420_16, AV_PIX_FMT_YUV420P12, pix_fmts_420 }, + { VDP_CHROMA_TYPE_422_16, AV_PIX_FMT_YUV422P10, pix_fmts_422 }, + { VDP_CHROMA_TYPE_444_16, AV_PIX_FMT_YUV444P10, pix_fmts_444 }, + { VDP_CHROMA_TYPE_444_16, AV_PIX_FMT_YUV444P12, pix_fmts_444 }, +#endif }; +typedef struct VDPAUDeviceContext { + VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *get_transfer_caps; + VdpVideoSurfaceGetBitsYCbCr *get_data; + VdpVideoSurfacePutBitsYCbCr *put_data; + VdpVideoSurfaceCreate *surf_create; + VdpVideoSurfaceDestroy *surf_destroy; + + enum AVPixelFormat *pix_fmts[FF_ARRAY_ELEMS(vdpau_pix_fmts)]; + int nb_pix_fmts[FF_ARRAY_ELEMS(vdpau_pix_fmts)]; +} VDPAUDeviceContext; + +typedef struct VDPAUFramesContext { + VdpVideoSurfaceGetBitsYCbCr *get_data; + VdpVideoSurfacePutBitsYCbCr *put_data; + VdpChromaType chroma_type; + int chroma_idx; + + const enum AVPixelFormat *pix_fmts; + int nb_pix_fmts; +} VDPAUFramesContext; + static int count_pixfmts(const VDPAUPixFmtMap *map) { int count = 0; @@ -211,7 +225,7 @@ device_priv->surf_destroy(surf); } -static AVBufferRef *vdpau_pool_alloc(void *opaque, int size) +static AVBufferRef *vdpau_pool_alloc(void *opaque, buffer_size_t size) { AVHWFramesContext *ctx = opaque; VDPAUFramesContext *priv = ctx->internal->priv; @@ -355,6 +369,9 @@ #ifdef VDP_YCBCR_FORMAT_Y_U_V_444 || (vdpau_format == VDP_YCBCR_FORMAT_Y_U_V_444) #endif +#ifdef VDP_YCBCR_FORMAT_P016 + || (vdpau_format == VDP_YCBCR_FORMAT_Y_U_V_444_16) +#endif ) FFSWAP(void*, data[1], data[2]); diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_videotoolbox.c ffmpeg-4.4/libavutil/hwcontext_videotoolbox.c --- ffmpeg-4.2.2/libavutil/hwcontext_videotoolbox.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_videotoolbox.c 2020-07-11 10:39:30.000000000 +0000 @@ -34,16 +34,19 @@ static const struct { uint32_t cv_fmt; + bool full_range; enum AVPixelFormat pix_fmt; } cv_pix_fmts[] = { - { kCVPixelFormatType_420YpCbCr8Planar, AV_PIX_FMT_YUV420P }, - { kCVPixelFormatType_422YpCbCr8, AV_PIX_FMT_UYVY422 }, - { kCVPixelFormatType_32BGRA, AV_PIX_FMT_BGRA }, + { kCVPixelFormatType_420YpCbCr8Planar, false, AV_PIX_FMT_YUV420P }, + { kCVPixelFormatType_422YpCbCr8, false, AV_PIX_FMT_UYVY422 }, + { kCVPixelFormatType_32BGRA, false, AV_PIX_FMT_BGRA }, #ifdef kCFCoreFoundationVersionNumber10_7 - { kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, AV_PIX_FMT_NV12 }, + { kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV12 }, + { kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV12 }, #endif #if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE - { kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange, AV_PIX_FMT_P010 }, + { kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P010 }, + { kCVPixelFormatType_420YpCbCr10BiPlanarFullRange, true, AV_PIX_FMT_P010 }, #endif }; @@ -59,9 +62,14 @@ uint32_t av_map_videotoolbox_format_from_pixfmt(enum AVPixelFormat pix_fmt) { + return av_map_videotoolbox_format_from_pixfmt2(pix_fmt, false); +} + +uint32_t av_map_videotoolbox_format_from_pixfmt2(enum AVPixelFormat pix_fmt, bool full_range) +{ int i; for (i = 0; i < FF_ARRAY_ELEMS(cv_pix_fmts); i++) { - if (cv_pix_fmts[i].pix_fmt == pix_fmt) + if (cv_pix_fmts[i].pix_fmt == pix_fmt && cv_pix_fmts[i].full_range == full_range) return cv_pix_fmts[i].cv_fmt; } return 0; diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_videotoolbox.h ffmpeg-4.4/libavutil/hwcontext_videotoolbox.h --- ffmpeg-4.2.2/libavutil/hwcontext_videotoolbox.h 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_videotoolbox.h 2020-07-11 10:39:30.000000000 +0000 @@ -51,4 +51,10 @@ */ uint32_t av_map_videotoolbox_format_from_pixfmt(enum AVPixelFormat pix_fmt); +/** + * Same as av_map_videotoolbox_format_from_pixfmt function, but can map and + * return full range pixel formats via a flag. + */ +uint32_t av_map_videotoolbox_format_from_pixfmt2(enum AVPixelFormat pix_fmt, bool full_range); + #endif /* AVUTIL_HWCONTEXT_VIDEOTOOLBOX_H */ diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_vulkan.c ffmpeg-4.4/libavutil/hwcontext_vulkan.c --- ffmpeg-4.2.2/libavutil/hwcontext_vulkan.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_vulkan.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,3386 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "pixdesc.h" +#include "avstring.h" +#include "imgutils.h" +#include "hwcontext.h" +#include "hwcontext_internal.h" +#include "hwcontext_vulkan.h" + +#if CONFIG_LIBDRM +#include +#include +#include +#include "hwcontext_drm.h" +#if CONFIG_VAAPI +#include +#include "hwcontext_vaapi.h" +#endif +#endif + +#if CONFIG_CUDA +#include "hwcontext_cuda_internal.h" +#include "cuda_check.h" +#define CHECK_CU(x) FF_CUDA_CHECK_DL(cuda_cu, cu, x) +#endif + +typedef struct VulkanQueueCtx { + VkFence fence; + VkQueue queue; + int was_synchronous; + + /* Buffer dependencies */ + AVBufferRef **buf_deps; + int nb_buf_deps; + int buf_deps_alloc_size; +} VulkanQueueCtx; + +typedef struct VulkanExecCtx { + VkCommandPool pool; + VkCommandBuffer *bufs; + VulkanQueueCtx *queues; + int nb_queues; + int cur_queue_idx; +} VulkanExecCtx; + +typedef struct VulkanDevicePriv { + /* Properties */ + VkPhysicalDeviceProperties2 props; + VkPhysicalDeviceMemoryProperties mprops; + VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops; + + /* Queues */ + uint32_t qfs[3]; + int num_qfs; + + /* Debug callback */ + VkDebugUtilsMessengerEXT debug_ctx; + + /* Extensions */ + uint64_t extensions; + + /* Settings */ + int use_linear_images; + + /* Nvidia */ + int dev_is_nvidia; +} VulkanDevicePriv; + +typedef struct VulkanFramesPriv { + /* Image conversions */ + VulkanExecCtx conv_ctx; + + /* Image transfers */ + VulkanExecCtx upload_ctx; + VulkanExecCtx download_ctx; +} VulkanFramesPriv; + +typedef struct AVVkFrameInternal { +#if CONFIG_CUDA + /* Importing external memory into cuda is really expensive so we keep the + * memory imported all the time */ + AVBufferRef *cuda_fc_ref; /* Need to keep it around for uninit */ + CUexternalMemory ext_mem[AV_NUM_DATA_POINTERS]; + CUmipmappedArray cu_mma[AV_NUM_DATA_POINTERS]; + CUarray cu_array[AV_NUM_DATA_POINTERS]; + CUexternalSemaphore cu_sem[AV_NUM_DATA_POINTERS]; +#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 VK_LOAD_PFN(inst, name) PFN_##name pfn_##name = (PFN_##name) \ + vkGetInstanceProcAddr(inst, #name) + +#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); \ + if (!list) { \ + err = AVERROR(ENOMEM); \ + goto fail; \ + } \ + list[count - 1] = av_strdup(val); \ + if (!list[count - 1]) { \ + err = AVERROR(ENOMEM); \ + goto fail; \ + } \ + } while(0) + +static const struct { + enum AVPixelFormat pixfmt; + const VkFormat vkfmts[4]; +} vk_pixfmt_map[] = { + { AV_PIX_FMT_GRAY8, { VK_FORMAT_R8_UNORM } }, + { AV_PIX_FMT_GRAY16, { VK_FORMAT_R16_UNORM } }, + { AV_PIX_FMT_GRAYF32, { VK_FORMAT_R32_SFLOAT } }, + + { AV_PIX_FMT_NV12, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, + { AV_PIX_FMT_NV21, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, + { AV_PIX_FMT_P010, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, + { AV_PIX_FMT_P016, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } }, + + { AV_PIX_FMT_NV16, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, + + { AV_PIX_FMT_NV24, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, + { AV_PIX_FMT_NV42, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } }, + + { AV_PIX_FMT_YUV420P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, + { AV_PIX_FMT_YUV420P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { AV_PIX_FMT_YUV420P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { AV_PIX_FMT_YUV420P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + + { AV_PIX_FMT_YUV422P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, + { AV_PIX_FMT_YUV422P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { AV_PIX_FMT_YUV422P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { AV_PIX_FMT_YUV422P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + + { AV_PIX_FMT_YUV444P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, + { AV_PIX_FMT_YUV444P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { AV_PIX_FMT_YUV444P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { AV_PIX_FMT_YUV444P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + + { AV_PIX_FMT_YUVA420P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, + { AV_PIX_FMT_YUVA420P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + /* There is no AV_PIX_FMT_YUVA420P12 */ + { AV_PIX_FMT_YUVA420P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + + { AV_PIX_FMT_YUVA422P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, + { AV_PIX_FMT_YUVA422P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { AV_PIX_FMT_YUVA422P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { AV_PIX_FMT_YUVA422P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + + { AV_PIX_FMT_YUVA444P, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, + { AV_PIX_FMT_YUVA444P10, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { AV_PIX_FMT_YUVA444P12, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { AV_PIX_FMT_YUVA444P16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + + { AV_PIX_FMT_BGRA, { VK_FORMAT_B8G8R8A8_UNORM } }, + { AV_PIX_FMT_RGBA, { VK_FORMAT_R8G8B8A8_UNORM } }, + { AV_PIX_FMT_RGB24, { VK_FORMAT_R8G8B8_UNORM } }, + { AV_PIX_FMT_BGR24, { VK_FORMAT_B8G8R8_UNORM } }, + { AV_PIX_FMT_RGB48, { VK_FORMAT_R16G16B16_UNORM } }, + { AV_PIX_FMT_RGBA64, { VK_FORMAT_R16G16B16A16_UNORM } }, + { AV_PIX_FMT_RGBA64, { VK_FORMAT_R16G16B16A16_UNORM } }, + { AV_PIX_FMT_RGB565, { VK_FORMAT_R5G6B5_UNORM_PACK16 } }, + { AV_PIX_FMT_BGR565, { VK_FORMAT_B5G6R5_UNORM_PACK16 } }, + { AV_PIX_FMT_BGR0, { VK_FORMAT_B8G8R8A8_UNORM } }, + { AV_PIX_FMT_RGB0, { VK_FORMAT_R8G8B8A8_UNORM } }, + + /* Lower priority as there's an endianess-dependent overlap between these + * and rgba/bgr0, and PACK32 formats are more limited */ + { AV_PIX_FMT_BGR32, { VK_FORMAT_A8B8G8R8_UNORM_PACK32 } }, + { AV_PIX_FMT_0BGR32, { VK_FORMAT_A8B8G8R8_UNORM_PACK32 } }, + + { AV_PIX_FMT_X2RGB10, { VK_FORMAT_A2R10G10B10_UNORM_PACK32 } }, + + { AV_PIX_FMT_GBRAP, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } }, + { AV_PIX_FMT_GBRAP16, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } }, + { AV_PIX_FMT_GBRPF32, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } }, + { AV_PIX_FMT_GBRAPF32, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } }, +}; + +const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p) +{ + for (enum AVPixelFormat i = 0; i < FF_ARRAY_ELEMS(vk_pixfmt_map); i++) + if (vk_pixfmt_map[i].pixfmt == p) + return vk_pixfmt_map[i].vkfmts; + return NULL; +} + +static int pixfmt_is_supported(AVVulkanDeviceContext *hwctx, enum AVPixelFormat p, + int linear) +{ + const VkFormat *fmt = av_vkfmt_from_pixfmt(p); + int planes = av_pix_fmt_count_planes(p); + + if (!fmt) + return 0; + + for (int i = 0; i < planes; i++) { + VkFormatFeatureFlags flags; + VkFormatProperties2 prop = { + .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + }; + vkGetPhysicalDeviceFormatProperties2(hwctx->phys_dev, fmt[i], &prop); + flags = linear ? prop.formatProperties.linearTilingFeatures : + prop.formatProperties.optimalTilingFeatures; + if (!(flags & DEFAULT_USAGE_FLAGS)) + return 0; + } + + return 1; +} + +enum VulkanExtensions { + EXT_EXTERNAL_DMABUF_MEMORY = 1ULL << 0, /* VK_EXT_external_memory_dma_buf */ + EXT_DRM_MODIFIER_FLAGS = 1ULL << 1, /* VK_EXT_image_drm_format_modifier */ + EXT_EXTERNAL_FD_MEMORY = 1ULL << 2, /* VK_KHR_external_memory_fd */ + EXT_EXTERNAL_FD_SEM = 1ULL << 3, /* VK_KHR_external_semaphore_fd */ + EXT_EXTERNAL_HOST_MEMORY = 1ULL << 4, /* VK_EXT_external_memory_host */ + EXT_PUSH_DESCRIPTORS = 1ULL << 5, /* VK_KHR_push_descriptor */ + EXT_HOST_QUERY_RESET = 1ULL << 6, /* VK_EXT_host_query_reset */ + + EXT_NO_FLAG = 1ULL << 63, +}; + +typedef struct VulkanOptExtension { + const char *name; + uint64_t flag; +} VulkanOptExtension; + +static const VulkanOptExtension optional_instance_exts[] = { + /* For future use */ +}; + +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_HOST_QUERY_RESET, }, +}; + +/* Converts return values to strings */ +static const char *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); + CASE(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT); + CASE(VK_ERROR_INVALID_DEVICE_ADDRESS_EXT); + CASE(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT); + default: return "Unknown error"; + } +#undef CASE +} + +static VkBool32 vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT *data, + void *priv) +{ + int l; + AVHWDeviceContext *ctx = priv; + + switch (severity) { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: l = AV_LOG_VERBOSE; break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: l = AV_LOG_INFO; break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: l = AV_LOG_WARNING; break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: l = AV_LOG_ERROR; break; + default: l = AV_LOG_DEBUG; break; + } + + av_log(ctx, l, "%s\n", data->pMessage); + for (int i = 0; i < data->cmdBufLabelCount; i++) + av_log(ctx, l, "\t%i: %s\n", i, data->pCmdBufLabels[i].pLabelName); + + return 0; +} + +static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, + const char * const **dst, uint32_t *num, int debug) +{ + const char *tstr; + const char **extension_names = NULL; + VulkanDevicePriv *p = ctx->internal->priv; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + int err = 0, found, extensions_found = 0; + + const char *mod; + int optional_exts_num; + uint32_t sup_ext_count; + char *user_exts_str = NULL; + AVDictionaryEntry *user_exts; + VkExtensionProperties *sup_ext; + const VulkanOptExtension *optional_exts; + + if (!dev) { + mod = "instance"; + optional_exts = optional_instance_exts; + optional_exts_num = FF_ARRAY_ELEMS(optional_instance_exts); + user_exts = av_dict_get(opts, "instance_extensions", NULL, 0); + if (user_exts) { + user_exts_str = av_strdup(user_exts->value); + if (!user_exts_str) { + err = AVERROR(ENOMEM); + goto fail; + } + } + vkEnumerateInstanceExtensionProperties(NULL, &sup_ext_count, NULL); + sup_ext = av_malloc_array(sup_ext_count, sizeof(VkExtensionProperties)); + if (!sup_ext) + return AVERROR(ENOMEM); + vkEnumerateInstanceExtensionProperties(NULL, &sup_ext_count, sup_ext); + } else { + mod = "device"; + optional_exts = optional_device_exts; + optional_exts_num = FF_ARRAY_ELEMS(optional_device_exts); + user_exts = av_dict_get(opts, "device_extensions", NULL, 0); + if (user_exts) { + user_exts_str = av_strdup(user_exts->value); + if (!user_exts_str) { + err = AVERROR(ENOMEM); + goto fail; + } + } + vkEnumerateDeviceExtensionProperties(hwctx->phys_dev, NULL, + &sup_ext_count, NULL); + sup_ext = av_malloc_array(sup_ext_count, sizeof(VkExtensionProperties)); + if (!sup_ext) + return AVERROR(ENOMEM); + vkEnumerateDeviceExtensionProperties(hwctx->phys_dev, NULL, + &sup_ext_count, sup_ext); + } + + for (int i = 0; i < optional_exts_num; i++) { + tstr = optional_exts[i].name; + found = 0; + for (int j = 0; j < sup_ext_count; j++) { + if (!strcmp(tstr, sup_ext[j].extensionName)) { + found = 1; + break; + } + } + if (!found) + continue; + + 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); + } + + if (debug && !dev) { + tstr = VK_EXT_DEBUG_UTILS_EXTENSION_NAME; + found = 0; + for (int j = 0; j < sup_ext_count; j++) { + if (!strcmp(tstr, sup_ext[j].extensionName)) { + found = 1; + break; + } + } + if (found) { + av_log(ctx, AV_LOG_VERBOSE, "Using %s extension \"%s\"\n", mod, tstr); + ADD_VAL_TO_LIST(extension_names, extensions_found, tstr); + } else { + av_log(ctx, AV_LOG_ERROR, "Debug extension \"%s\" not found!\n", + tstr); + err = AVERROR(EINVAL); + goto fail; + } + } + + if (user_exts_str) { + char *save, *token = av_strtok(user_exts_str, "+", &save); + while (token) { + found = 0; + for (int j = 0; j < sup_ext_count; j++) { + if (!strcmp(token, sup_ext[j].extensionName)) { + found = 1; + break; + } + } + if (found) { + av_log(ctx, AV_LOG_VERBOSE, "Using %s extension \"%s\"\n", mod, token); + ADD_VAL_TO_LIST(extension_names, extensions_found, token); + } else { + av_log(ctx, AV_LOG_WARNING, "%s extension \"%s\" not found, excluding.\n", + mod, token); + } + token = av_strtok(NULL, "+", &save); + } + } + + *dst = extension_names; + *num = extensions_found; + + av_free(user_exts_str); + av_free(sup_ext); + return 0; + +fail: + if (extension_names) + for (int i = 0; i < extensions_found; i++) + av_free((void *)extension_names[i]); + av_free(extension_names); + av_free(user_exts_str); + av_free(sup_ext); + return err; +} + +/* Creates a VkInstance */ +static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) +{ + int err = 0; + VkResult ret; + VulkanDevicePriv *p = ctx->internal->priv; + 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, + .engineVersion = VK_MAKE_VERSION(LIBAVUTIL_VERSION_MAJOR, + LIBAVUTIL_VERSION_MINOR, + LIBAVUTIL_VERSION_MICRO), + }; + VkInstanceCreateInfo inst_props = { + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .pApplicationInfo = &application_info, + }; + + /* Check for present/missing extensions */ + err = check_extensions(ctx, 0, opts, &inst_props.ppEnabledExtensionNames, + &inst_props.enabledExtensionCount, debug_mode); + 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); + } + + /* Try to create the instance */ + ret = vkCreateInstance(&inst_props, hwctx->alloc, &hwctx->inst); + + /* Check for errors */ + 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; + } + + if (debug_mode) { + VkDebugUtilsMessengerCreateInfoEXT dbg = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, + .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, + .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, + .pfnUserCallback = vk_dbg_callback, + .pUserData = ctx, + }; + VK_LOAD_PFN(hwctx->inst, vkCreateDebugUtilsMessengerEXT); + + pfn_vkCreateDebugUtilsMessengerEXT(hwctx->inst, &dbg, + hwctx->alloc, &p->debug_ctx); + } + + hwctx->enabled_inst_extensions = inst_props.ppEnabledExtensionNames; + hwctx->nb_enabled_inst_extensions = inst_props.enabledExtensionCount; + + return 0; +} + +typedef struct VulkanDeviceSelection { + uint8_t uuid[VK_UUID_SIZE]; /* Will use this first unless !has_uuid */ + int has_uuid; + const char *name; /* Will use this second unless NULL */ + uint32_t pci_device; /* Will use this third unless 0x0 */ + uint32_t vendor_id; /* Last resort to find something deterministic */ + int index; /* Finally fall back to index */ +} VulkanDeviceSelection; + +static const char *vk_dev_type(enum VkPhysicalDeviceType type) +{ + switch (type) { + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return "integrated"; + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return "discrete"; + case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return "virtual"; + case VK_PHYSICAL_DEVICE_TYPE_CPU: return "software"; + default: return "unknown"; + } +} + +/* Finds a device */ +static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) +{ + int err = 0, choice = -1; + uint32_t num; + VkResult ret; + VkPhysicalDevice *devices = NULL; + VkPhysicalDeviceIDProperties *idp = NULL; + VkPhysicalDeviceProperties2 *prop = NULL; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + + ret = vkEnumeratePhysicalDevices(hwctx->inst, &num, NULL); + if (ret != VK_SUCCESS || !num) { + av_log(ctx, AV_LOG_ERROR, "No devices found: %s!\n", vk_ret2str(ret)); + return AVERROR(ENODEV); + } + + devices = av_malloc_array(num, sizeof(VkPhysicalDevice)); + if (!devices) + return AVERROR(ENOMEM); + + ret = vkEnumeratePhysicalDevices(hwctx->inst, &num, devices); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed enumerating devices: %s\n", + vk_ret2str(ret)); + err = AVERROR(ENODEV); + goto end; + } + + prop = av_mallocz_array(num, sizeof(*prop)); + if (!prop) { + err = AVERROR(ENOMEM); + goto end; + } + + idp = av_mallocz_array(num, sizeof(*idp)); + if (!idp) { + err = AVERROR(ENOMEM); + goto end; + } + + av_log(ctx, AV_LOG_VERBOSE, "GPU listing:\n"); + for (int i = 0; i < num; i++) { + idp[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES; + prop[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + prop[i].pNext = &idp[i]; + + vkGetPhysicalDeviceProperties2(devices[i], &prop[i]); + av_log(ctx, AV_LOG_VERBOSE, " %d: %s (%s) (0x%x)\n", i, + prop[i].properties.deviceName, + vk_dev_type(prop[i].properties.deviceType), + prop[i].properties.deviceID); + } + + if (select->has_uuid) { + for (int i = 0; i < num; i++) { + if (!strncmp(idp[i].deviceUUID, select->uuid, VK_UUID_SIZE)) { + choice = i; + goto end; + } + } + av_log(ctx, AV_LOG_ERROR, "Unable to find device by given UUID!\n"); + err = AVERROR(ENODEV); + goto end; + } else if (select->name) { + av_log(ctx, AV_LOG_VERBOSE, "Requested device: %s\n", select->name); + for (int i = 0; i < num; i++) { + if (strstr(prop[i].properties.deviceName, select->name)) { + choice = i; + goto end; + } + } + av_log(ctx, AV_LOG_ERROR, "Unable to find device \"%s\"!\n", + select->name); + err = AVERROR(ENODEV); + goto end; + } else if (select->pci_device) { + av_log(ctx, AV_LOG_VERBOSE, "Requested device: 0x%x\n", select->pci_device); + for (int i = 0; i < num; i++) { + if (select->pci_device == prop[i].properties.deviceID) { + choice = i; + goto end; + } + } + av_log(ctx, AV_LOG_ERROR, "Unable to find device with PCI ID 0x%x!\n", + select->pci_device); + err = AVERROR(EINVAL); + goto end; + } else if (select->vendor_id) { + av_log(ctx, AV_LOG_VERBOSE, "Requested vendor: 0x%x\n", select->vendor_id); + for (int i = 0; i < num; i++) { + if (select->vendor_id == prop[i].properties.vendorID) { + choice = i; + goto end; + } + } + av_log(ctx, AV_LOG_ERROR, "Unable to find device with Vendor ID 0x%x!\n", + select->vendor_id); + err = AVERROR(ENODEV); + goto end; + } else { + if (select->index < num) { + choice = select->index; + goto end; + } + av_log(ctx, AV_LOG_ERROR, "Unable to find device with index %i!\n", + select->index); + err = AVERROR(ENODEV); + goto end; + } + +end: + if (choice > -1) + hwctx->phys_dev = devices[choice]; + + av_free(devices); + av_free(prop); + av_free(idp); + + return err; +} + +static int search_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) +{ + uint32_t num; + float *weights; + VkQueueFamilyProperties *qs = NULL; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + int graph_index = -1, comp_index = -1, tx_index = -1; + VkDeviceQueueCreateInfo *pc = (VkDeviceQueueCreateInfo *)cd->pQueueCreateInfos; + + /* First get the number of queue families */ + vkGetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, NULL); + if (!num) { + av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n"); + return AVERROR_EXTERNAL; + } + + /* Then allocate memory */ + qs = av_malloc_array(num, sizeof(VkQueueFamilyProperties)); + if (!qs) + return AVERROR(ENOMEM); + + /* Finally retrieve the queue families */ + vkGetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, qs); + +#define SEARCH_FLAGS(expr, out) \ + for (int i = 0; i < num; i++) { \ + const VkQueueFlagBits flags = qs[i].queueFlags; \ + if (expr) { \ + out = i; \ + break; \ + } \ + } + + 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; + } + +#undef ADD_QUEUE + av_free(qs); + + 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, + int queue_family_index, int num_queues) +{ + VkResult ret; + AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + + VkCommandPoolCreateInfo cqueue_create = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, + .queueFamilyIndex = queue_family_index, + }; + VkCommandBufferAllocateInfo cbuf_create = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = num_queues, + }; + + cmd->nb_queues = num_queues; + + /* Create command pool */ + ret = vkCreateCommandPool(hwctx->act_dev, &cqueue_create, + hwctx->alloc, &cmd->pool); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Command pool creation failure: %s\n", + vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + cmd->bufs = av_mallocz(num_queues * sizeof(*cmd->bufs)); + if (!cmd->bufs) + return AVERROR(ENOMEM); + + cbuf_create.commandPool = cmd->pool; + + /* Allocate command buffer */ + ret = vkAllocateCommandBuffers(hwctx->act_dev, &cbuf_create, cmd->bufs); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Command buffer alloc failure: %s\n", + vk_ret2str(ret)); + av_freep(&cmd->bufs); + return AVERROR_EXTERNAL; + } + + cmd->queues = av_mallocz(num_queues * sizeof(*cmd->queues)); + if (!cmd->queues) + return AVERROR(ENOMEM); + + for (int i = 0; i < num_queues; i++) { + VulkanQueueCtx *q = &cmd->queues[i]; + vkGetDeviceQueue(hwctx->act_dev, queue_family_index, i, &q->queue); + q->was_synchronous = 1; + } + + return 0; +} + +static void free_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) +{ + AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + + if (cmd->queues) { + for (int i = 0; i < cmd->nb_queues; i++) { + VulkanQueueCtx *q = &cmd->queues[i]; + + /* Make sure all queues have finished executing */ + if (q->fence && !q->was_synchronous) { + vkWaitForFences(hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); + vkResetFences(hwctx->act_dev, 1, &q->fence); + } + + /* Free the fence */ + if (q->fence) + vkDestroyFence(hwctx->act_dev, q->fence, 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); + } + } + + if (cmd->bufs) + vkFreeCommandBuffers(hwctx->act_dev, cmd->pool, cmd->nb_queues, cmd->bufs); + if (cmd->pool) + vkDestroyCommandPool(hwctx->act_dev, cmd->pool, hwctx->alloc); + + av_freep(&cmd->queues); + av_freep(&cmd->bufs); + cmd->pool = NULL; +} + +static VkCommandBuffer get_buf_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) +{ + return cmd->bufs[cmd->cur_queue_idx]; +} + +static void unref_exec_ctx_deps(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) +{ + VulkanQueueCtx *q = &cmd->queues[cmd->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; +} + +static int wait_start_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) +{ + VkResult ret; + AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + VulkanQueueCtx *q = &cmd->queues[cmd->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(hwctx->act_dev, &fence_spawn, hwctx->alloc, + &q->fence); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to queue frame fence: %s\n", + vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } else if (!q->was_synchronous) { + vkWaitForFences(hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); + vkResetFences(hwctx->act_dev, 1, &q->fence); + } + + /* Discard queue dependencies */ + unref_exec_ctx_deps(hwfc, cmd); + + ret = vkBeginCommandBuffer(cmd->bufs[cmd->cur_queue_idx], &cmd_start); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Unable to init command buffer: %s\n", + vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + return 0; +} + +static int add_buf_dep_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, + AVBufferRef * const *deps, int nb_deps) +{ + AVBufferRef **dst; + VulkanQueueCtx *q = &cmd->queues[cmd->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] = av_buffer_ref(deps[i]); + if (!q->buf_deps[q->nb_buf_deps]) + goto err; + q->nb_buf_deps++; + } + + return 0; + +err: + unref_exec_ctx_deps(hwfc, cmd); + return AVERROR(ENOMEM); +} + +static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, + VkSubmitInfo *s_info, int synchronous) +{ + VkResult ret; + VulkanQueueCtx *q = &cmd->queues[cmd->cur_queue_idx]; + + ret = vkEndCommandBuffer(cmd->bufs[cmd->cur_queue_idx]); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Unable to finish command buffer: %s\n", + vk_ret2str(ret)); + unref_exec_ctx_deps(hwfc, cmd); + return AVERROR_EXTERNAL; + } + + s_info->pCommandBuffers = &cmd->bufs[cmd->cur_queue_idx]; + s_info->commandBufferCount = 1; + + ret = vkQueueSubmit(q->queue, 1, s_info, q->fence); + if (ret != VK_SUCCESS) { + unref_exec_ctx_deps(hwfc, cmd); + return AVERROR_EXTERNAL; + } + + q->was_synchronous = synchronous; + + if (synchronous) { + AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + vkWaitForFences(hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); + vkResetFences(hwctx->act_dev, 1, &q->fence); + unref_exec_ctx_deps(hwfc, cmd); + } else { /* Rotate queues */ + cmd->cur_queue_idx = (cmd->cur_queue_idx + 1) % cmd->nb_queues; + } + + return 0; +} + +static void vulkan_device_free(AVHWDeviceContext *ctx) +{ + VulkanDevicePriv *p = ctx->internal->priv; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + + vkDestroyDevice(hwctx->act_dev, hwctx->alloc); + + if (p->debug_ctx) { + VK_LOAD_PFN(hwctx->inst, vkDestroyDebugUtilsMessengerEXT); + pfn_vkDestroyDebugUtilsMessengerEXT(hwctx->inst, p->debug_ctx, + hwctx->alloc); + } + + vkDestroyInstance(hwctx->inst, hwctx->alloc); + + 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); +} + +static int vulkan_device_create_internal(AVHWDeviceContext *ctx, + VulkanDeviceSelection *dev_select, + AVDictionary *opts, int flags) +{ + int err = 0; + VkResult ret; + AVDictionaryEntry *opt_d; + VulkanDevicePriv *p = ctx->internal->priv; + 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, }, + }; + + 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; + ctx->free = vulkan_device_free; + + /* Create an instance if not given one */ + if ((err = create_instance(ctx, opts))) + goto end; + + /* Find a device (if not given one) */ + if ((err = find_device(ctx, dev_select))) + goto end; + + vkGetPhysicalDeviceFeatures(hwctx->phys_dev, &dev_features); +#define COPY_FEATURE(DST, NAME) (DST).features.NAME = dev_features.NAME; + COPY_FEATURE(hwctx->device_features, shaderImageGatherExtended) + COPY_FEATURE(hwctx->device_features, shaderStorageImageReadWithoutFormat) + COPY_FEATURE(hwctx->device_features, shaderStorageImageWriteWithoutFormat) + COPY_FEATURE(hwctx->device_features, fragmentStoresAndAtomics) + COPY_FEATURE(hwctx->device_features, vertexPipelineStoresAndAtomics) + COPY_FEATURE(hwctx->device_features, shaderInt64) +#undef COPY_FEATURE + + /* Search queue family */ + if ((err = search_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); + goto end; + } + + ret = vkCreateDevice(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); + + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Device creation failure: %s\n", + vk_ret2str(ret)); + for (int i = 0; i < dev_info.enabledExtensionCount; i++) + av_free((void *)dev_info.ppEnabledExtensionNames[i]); + av_free((void *)dev_info.ppEnabledExtensionNames); + err = AVERROR_EXTERNAL; + goto end; + } + + /* Tiled images setting, use them by default */ + opt_d = av_dict_get(opts, "linear_images", NULL, 0); + if (opt_d) + p->use_linear_images = strtol(opt_d->value, NULL, 10); + + hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames; + hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount; + +end: + return err; +} + +static int vulkan_device_init(AVHWDeviceContext *ctx) +{ + uint32_t queue_num; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + VulkanDevicePriv *p = ctx->internal->priv; + + /* 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; + } + } + } + + p->props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + p->props.pNext = &p->hprops; + p->hprops.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT; + + vkGetPhysicalDeviceProperties2(hwctx->phys_dev, &p->props); + av_log(ctx, AV_LOG_VERBOSE, "Using device: %s\n", + p->props.properties.deviceName); + av_log(ctx, AV_LOG_VERBOSE, "Alignments:\n"); + av_log(ctx, AV_LOG_VERBOSE, " optimalBufferCopyRowPitchAlignment: %li\n", + p->props.properties.limits.optimalBufferCopyRowPitchAlignment); + av_log(ctx, AV_LOG_VERBOSE, " minMemoryMapAlignment: %li\n", + p->props.properties.limits.minMemoryMapAlignment); + if (p->extensions & EXT_EXTERNAL_HOST_MEMORY) + av_log(ctx, AV_LOG_VERBOSE, " minImportedHostPointerAlignment: %li\n", + p->hprops.minImportedHostPointerAlignment); + + p->dev_is_nvidia = (p->props.properties.vendorID == 0x10de); + + vkGetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &queue_num, NULL); + if (!queue_num) { + av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n"); + 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); \ +} + + CHECK_QUEUE("graphics", hwctx->queue_family_index) + CHECK_QUEUE("upload", hwctx->queue_family_tx_index) + CHECK_QUEUE("compute", hwctx->queue_family_comp_index) + +#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 */ + vkGetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops); + + return 0; +} + +static int vulkan_device_create(AVHWDeviceContext *ctx, const char *device, + AVDictionary *opts, int flags) +{ + VulkanDeviceSelection dev_select = { 0 }; + if (device && device[0]) { + char *end = NULL; + dev_select.index = strtol(device, &end, 10); + if (end == device) { + dev_select.index = 0; + dev_select.name = device; + } + } + + return vulkan_device_create_internal(ctx, &dev_select, opts, flags); +} + +static int vulkan_device_derive(AVHWDeviceContext *ctx, + AVHWDeviceContext *src_ctx, + AVDictionary *opts, int flags) +{ + av_unused VulkanDeviceSelection dev_select = { 0 }; + + /* If there's only one device on the system, then even if its not covered + * by the following checks (e.g. non-PCIe ARM GPU), having an empty + * dev_select will mean it'll get picked. */ + switch(src_ctx->type) { +#if CONFIG_LIBDRM +#if CONFIG_VAAPI + case AV_HWDEVICE_TYPE_VAAPI: { + AVVAAPIDeviceContext *src_hwctx = src_ctx->hwctx; + + const char *vendor = vaQueryVendorString(src_hwctx->display); + if (!vendor) { + av_log(ctx, AV_LOG_ERROR, "Unable to get device info from VAAPI!\n"); + return AVERROR_EXTERNAL; + } + + if (strstr(vendor, "Intel")) + dev_select.vendor_id = 0x8086; + if (strstr(vendor, "AMD")) + dev_select.vendor_id = 0x1002; + + return vulkan_device_create_internal(ctx, &dev_select, opts, flags); + } +#endif + case AV_HWDEVICE_TYPE_DRM: { + AVDRMDeviceContext *src_hwctx = src_ctx->hwctx; + + drmDevice *drm_dev_info; + int err = drmGetDevice(src_hwctx->fd, &drm_dev_info); + if (err) { + av_log(ctx, AV_LOG_ERROR, "Unable to get device info from DRM fd!\n"); + return AVERROR_EXTERNAL; + } + + if (drm_dev_info->bustype == DRM_BUS_PCI) + dev_select.pci_device = drm_dev_info->deviceinfo.pci->device_id; + + drmFreeDevice(&drm_dev_info); + + return vulkan_device_create_internal(ctx, &dev_select, opts, flags); + } +#endif +#if CONFIG_CUDA + case AV_HWDEVICE_TYPE_CUDA: { + AVHWDeviceContext *cuda_cu = src_ctx; + AVCUDADeviceContext *src_hwctx = src_ctx->hwctx; + AVCUDADeviceContextInternal *cu_internal = src_hwctx->internal; + CudaFunctions *cu = cu_internal->cuda_dl; + + int ret = CHECK_CU(cu->cuDeviceGetUuid((CUuuid *)&dev_select.uuid, + cu_internal->cuda_device)); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Unable to get UUID from CUDA!\n"); + return AVERROR_EXTERNAL; + } + + dev_select.has_uuid = 1; + + return vulkan_device_create_internal(ctx, &dev_select, opts, flags); + } +#endif + default: + return AVERROR(ENOSYS); + } +} + +static int vulkan_frames_get_constraints(AVHWDeviceContext *ctx, + const void *hwconfig, + AVHWFramesConstraints *constraints) +{ + int count = 0; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + VulkanDevicePriv *p = ctx->internal->priv; + + for (enum AVPixelFormat i = 0; i < AV_PIX_FMT_NB; i++) + count += pixfmt_is_supported(hwctx, i, p->use_linear_images); + +#if CONFIG_CUDA + if (p->dev_is_nvidia) + count++; +#endif + + constraints->valid_sw_formats = av_malloc_array(count + 1, + sizeof(enum AVPixelFormat)); + if (!constraints->valid_sw_formats) + return AVERROR(ENOMEM); + + count = 0; + for (enum AVPixelFormat i = 0; i < AV_PIX_FMT_NB; i++) + if (pixfmt_is_supported(hwctx, i, p->use_linear_images)) + constraints->valid_sw_formats[count++] = i; + +#if CONFIG_CUDA + if (p->dev_is_nvidia) + constraints->valid_sw_formats[count++] = AV_PIX_FMT_CUDA; +#endif + constraints->valid_sw_formats[count++] = AV_PIX_FMT_NONE; + + constraints->min_width = 0; + constraints->min_height = 0; + constraints->max_width = p->props.properties.limits.maxImageDimension2D; + constraints->max_height = p->props.properties.limits.maxImageDimension2D; + + constraints->valid_hw_formats = av_malloc_array(2, sizeof(enum AVPixelFormat)); + if (!constraints->valid_hw_formats) + return AVERROR(ENOMEM); + + constraints->valid_hw_formats[0] = AV_PIX_FMT_VULKAN; + constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE; + + return 0; +} + +static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req, + VkMemoryPropertyFlagBits req_flags, const void *alloc_extension, + VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem) +{ + VkResult ret; + int index = -1; + VulkanDevicePriv *p = ctx->internal->priv; + AVVulkanDeviceContext *dev_hwctx = ctx->hwctx; + VkMemoryAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = alloc_extension, + .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 < p->mprops.memoryTypeCount; i++) { + const VkMemoryType *type = &p->mprops.memoryTypes[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 ((type->propertyFlags & req_flags) != req_flags) + continue; + + /* The memory type must be large enough */ + if (req->size > p->mprops.memoryHeaps[type->heapIndex].size) + continue; + + /* Found a suitable memory type */ + index = i; + break; + } + + if (index < 0) { + av_log(ctx, AV_LOG_ERROR, "No memory type found for flags 0x%x\n", + req_flags); + return AVERROR(EINVAL); + } + + alloc_info.memoryTypeIndex = index; + + ret = vkAllocateMemory(dev_hwctx->act_dev, &alloc_info, + dev_hwctx->alloc, mem); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory: %s\n", + vk_ret2str(ret)); + return AVERROR(ENOMEM); + } + + *mem_flags |= p->mprops.memoryTypes[index].propertyFlags; + + return 0; +} + +static void vulkan_free_internal(AVVkFrameInternal *internal) +{ + if (!internal) + return; + +#if CONFIG_CUDA + if (internal->cuda_fc_ref) { + AVHWFramesContext *cuda_fc = (AVHWFramesContext *)internal->cuda_fc_ref->data; + int planes = av_pix_fmt_count_planes(cuda_fc->sw_format); + AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx; + AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx; + AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal; + CudaFunctions *cu = cu_internal->cuda_dl; + + for (int i = 0; i < planes; i++) { + if (internal->cu_sem[i]) + CHECK_CU(cu->cuDestroyExternalSemaphore(internal->cu_sem[i])); + if (internal->cu_mma[i]) + CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[i])); + if (internal->ext_mem[i]) + CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[i])); + } + + av_buffer_unref(&internal->cuda_fc_ref); + } +#endif + + av_free(internal); +} + +static void vulkan_frame_free(void *opaque, uint8_t *data) +{ + AVVkFrame *f = (AVVkFrame *)data; + AVHWFramesContext *hwfc = opaque; + AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + int planes = av_pix_fmt_count_planes(hwfc->sw_format); + + vulkan_free_internal(f->internal); + + for (int i = 0; i < planes; i++) { + vkDestroyImage(hwctx->act_dev, f->img[i], hwctx->alloc); + vkFreeMemory(hwctx->act_dev, f->mem[i], hwctx->alloc); + vkDestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc); + } + + av_free(f); +} + +static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, + void *alloc_pnext, size_t alloc_pnext_stride) +{ + int err; + VkResult ret; + AVHWDeviceContext *ctx = hwfc->device_ctx; + VulkanDevicePriv *p = ctx->internal->priv; + const int planes = av_pix_fmt_count_planes(hwfc->sw_format); + VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } }; + + AVVulkanDeviceContext *hwctx = ctx->hwctx; + + for (int i = 0; i < planes; i++) { + int use_ded_mem; + VkImageMemoryRequirementsInfo2 req_desc = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, + .image = f->img[i], + }; + VkMemoryDedicatedAllocateInfo ded_alloc = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + .pNext = (void *)(((uint8_t *)alloc_pnext) + i*alloc_pnext_stride), + }; + VkMemoryDedicatedRequirements ded_req = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, + }; + VkMemoryRequirements2 req = { + .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + .pNext = &ded_req, + }; + + vkGetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req); + + if (f->tiling == VK_IMAGE_TILING_LINEAR) + req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size, + p->props.properties.limits.minMemoryMapAlignment); + + /* In case the implementation prefers/requires dedicated allocation */ + use_ded_mem = ded_req.prefersDedicatedAllocation | + ded_req.requiresDedicatedAllocation; + if (use_ded_mem) + ded_alloc.image = f->img[i]; + + /* Allocate memory */ + if ((err = alloc_mem(ctx, &req.memoryRequirements, + f->tiling == VK_IMAGE_TILING_LINEAR ? + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext, + &f->flags, &f->mem[i]))) + return err; + + f->size[i] = req.memoryRequirements.size; + bind_info[i].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; + bind_info[i].image = f->img[i]; + bind_info[i].memory = f->mem[i]; + } + + /* Bind the allocated memory to the images */ + ret = vkBindImageMemory2(hwctx->act_dev, planes, bind_info); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n", + vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + return 0; +} + +enum PrepMode { + PREP_MODE_WRITE, + PREP_MODE_RO_SHADER, + PREP_MODE_EXTERNAL_EXPORT, +}; + +static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, + AVVkFrame *frame, enum PrepMode pmode) +{ + int err; + uint32_t dst_qf; + VkImageLayout new_layout; + VkAccessFlags new_access; + const int planes = av_pix_fmt_count_planes(hwfc->sw_format); + + VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 }; + + VkSubmitInfo s_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pSignalSemaphores = frame->sem, + .signalSemaphoreCount = planes, + }; + + VkPipelineStageFlagBits wait_st[AV_NUM_DATA_POINTERS]; + for (int i = 0; i < planes; i++) + wait_st[i] = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + + switch (pmode) { + case PREP_MODE_WRITE: + new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + new_access = VK_ACCESS_TRANSFER_WRITE_BIT; + 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; + dst_qf = VK_QUEUE_FAMILY_IGNORED; + break; + case PREP_MODE_EXTERNAL_EXPORT: + new_layout = VK_IMAGE_LAYOUT_GENERAL; + new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; + dst_qf = VK_QUEUE_FAMILY_EXTERNAL_KHR; + s_info.pWaitSemaphores = frame->sem; + s_info.pWaitDstStageMask = wait_st; + s_info.waitSemaphoreCount = planes; + break; + } + + if ((err = wait_start_exec_ctx(hwfc, ectx))) + return err; + + /* Change the image layout to something more optimal for writes. + * This also signals the newly created semaphore, making it usable + * for synchronization */ + for (int i = 0; i < planes; i++) { + img_bar[i].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + img_bar[i].srcAccessMask = 0x0; + 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].dstQueueFamilyIndex = dst_qf; + img_bar[i].image = frame->img[i]; + img_bar[i].subresourceRange.levelCount = 1; + img_bar[i].subresourceRange.layerCount = 1; + img_bar[i].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + + frame->layout[i] = img_bar[i].newLayout; + frame->access[i] = img_bar[i].dstAccessMask; + } + + vkCmdPipelineBarrier(get_buf_exec_ctx(hwfc, ectx), + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, NULL, 0, NULL, planes, img_bar); + + return submit_exec_ctx(hwfc, ectx, &s_info, 0); +} + +static inline void get_plane_wh(int *w, int *h, enum AVPixelFormat format, + int frame_w, int frame_h, int plane) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format); + + /* Currently always true unless gray + alpha support is added */ + if (!plane || (plane == 3) || desc->flags & AV_PIX_FMT_FLAG_RGB || + !(desc->flags & AV_PIX_FMT_FLAG_PLANAR)) { + *w = frame_w; + *h = frame_h; + return; + } + + *w = AV_CEIL_RSHIFT(frame_w, desc->log2_chroma_w); + *h = AV_CEIL_RSHIFT(frame_h, desc->log2_chroma_h); +} + +static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, + VkImageTiling tiling, VkImageUsageFlagBits usage, + void *create_pnext) +{ + int err; + VkResult ret; + AVHWDeviceContext *ctx = hwfc->device_ctx; + VulkanDevicePriv *p = ctx->internal->priv; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + enum AVPixelFormat format = hwfc->sw_format; + const VkFormat *img_fmts = av_vkfmt_from_pixfmt(format); + const int planes = av_pix_fmt_count_planes(format); + + VkExportSemaphoreCreateInfo ext_sem_info = { + .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, + .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, + }; + + VkSemaphoreCreateInfo sem_spawn = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = p->extensions & EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, + }; + + AVVkFrame *f = av_vk_frame_alloc(); + if (!f) { + av_log(ctx, AV_LOG_ERROR, "Unable to allocate memory for AVVkFrame!\n"); + return AVERROR(ENOMEM); + } + + /* Create the images */ + for (int i = 0; i < planes; i++) { + VkImageCreateInfo create_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = create_pnext, + .imageType = VK_IMAGE_TYPE_2D, + .format = img_fmts[i], + .extent.depth = 1, + .mipLevels = 1, + .arrayLayers = 1, + .flags = VK_IMAGE_CREATE_ALIAS_BIT, + .tiling = tiling, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .usage = usage, + .samples = VK_SAMPLE_COUNT_1_BIT, + .pQueueFamilyIndices = p->qfs, + .queueFamilyIndexCount = p->num_qfs, + .sharingMode = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, + }; + + get_plane_wh(&create_info.extent.width, &create_info.extent.height, + format, hwfc->width, hwfc->height, i); + + ret = vkCreateImage(hwctx->act_dev, &create_info, + hwctx->alloc, &f->img[i]); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Image creation failure: %s\n", + vk_ret2str(ret)); + err = AVERROR(EINVAL); + goto fail; + } + + /* Create semaphore */ + ret = vkCreateSemaphore(hwctx->act_dev, &sem_spawn, + hwctx->alloc, &f->sem[i]); + if (ret != VK_SUCCESS) { + av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n", + vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + f->layout[i] = create_info.initialLayout; + f->access[i] = 0x0; + } + + f->flags = 0x0; + f->tiling = tiling; + + *frame = f; + return 0; + +fail: + vulkan_frame_free(hwfc, (uint8_t *)f); + return err; +} + +/* Checks if an export flag is enabled, and if it is ORs it with *iexp */ +static void try_export_flags(AVHWFramesContext *hwfc, + VkExternalMemoryHandleTypeFlags *comp_handle_types, + VkExternalMemoryHandleTypeFlagBits *iexp, + VkExternalMemoryHandleTypeFlagBits exp) +{ + VkResult ret; + AVVulkanFramesContext *hwctx = hwfc->hwctx; + AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; + VkExternalImageFormatProperties eprops = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, + }; + VkImageFormatProperties2 props = { + .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, + .pNext = &eprops, + }; + VkPhysicalDeviceExternalImageFormatInfo enext = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, + .handleType = exp, + }; + VkPhysicalDeviceImageFormatInfo2 pinfo = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, + .pNext = !exp ? NULL : &enext, + .format = av_vkfmt_from_pixfmt(hwfc->sw_format)[0], + .type = VK_IMAGE_TYPE_2D, + .tiling = hwctx->tiling, + .usage = hwctx->usage, + .flags = VK_IMAGE_CREATE_ALIAS_BIT, + }; + + ret = vkGetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, + &pinfo, &props); + if (ret == VK_SUCCESS) { + *iexp |= exp; + *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; + } +} + +static AVBufferRef *vulkan_pool_alloc(void *opaque, buffer_size_t size) +{ + int err; + AVVkFrame *f; + AVBufferRef *avbuf = NULL; + AVHWFramesContext *hwfc = opaque; + AVVulkanFramesContext *hwctx = hwfc->hwctx; + VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; + VulkanFramesPriv *fp = hwfc->internal->priv; + VkExportMemoryAllocateInfo eminfo[AV_NUM_DATA_POINTERS]; + VkExternalMemoryHandleTypeFlags e = 0x0; + + VkExternalMemoryImageCreateInfo eiinfo = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + .pNext = hwctx->create_pnext, + }; + + if (p->extensions & 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) + try_export_flags(hwfc, &eiinfo.handleTypes, &e, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); + + for (int i = 0; i < av_pix_fmt_count_planes(hwfc->sw_format); i++) { + eminfo[i].sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO; + eminfo[i].pNext = hwctx->alloc_pnext[i]; + eminfo[i].handleTypes = e; + } + + err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, + eiinfo.handleTypes ? &eiinfo : NULL); + if (err) + return NULL; + + err = alloc_bind_mem(hwfc, f, eminfo, sizeof(*eminfo)); + if (err) + goto fail; + + err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_WRITE); + if (err) + goto fail; + + avbuf = av_buffer_create((uint8_t *)f, sizeof(AVVkFrame), + vulkan_frame_free, hwfc, 0); + if (!avbuf) + goto fail; + + return avbuf; + +fail: + vulkan_frame_free(hwfc, (uint8_t *)f); + return NULL; +} + +static void vulkan_frames_uninit(AVHWFramesContext *hwfc) +{ + VulkanFramesPriv *fp = hwfc->internal->priv; + + free_exec_ctx(hwfc, &fp->conv_ctx); + free_exec_ctx(hwfc, &fp->upload_ctx); + free_exec_ctx(hwfc, &fp->download_ctx); +} + +static int vulkan_frames_init(AVHWFramesContext *hwfc) +{ + int err; + AVVkFrame *f; + AVVulkanFramesContext *hwctx = hwfc->hwctx; + VulkanFramesPriv *fp = hwfc->internal->priv; + AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; + VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; + + /* Default pool flags */ + hwctx->tiling = hwctx->tiling ? hwctx->tiling : p->use_linear_images ? + VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; + + if (!hwctx->usage) + hwctx->usage = DEFAULT_USAGE_FLAGS; + + err = create_exec_ctx(hwfc, &fp->conv_ctx, + dev_hwctx->queue_family_comp_index, + GET_QUEUE_COUNT(dev_hwctx, 0, 1, 0)); + 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)); + if (err) + return err; + + err = create_exec_ctx(hwfc, &fp->download_ctx, + dev_hwctx->queue_family_tx_index, 1); + if (err) + return err; + + /* Test to see if allocation will fail */ + err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, + hwctx->create_pnext); + if (err) + return err; + + vulkan_frame_free(hwfc, (uint8_t *)f); + + /* If user did not specify a pool, hwfc->pool will be set to the internal one + * in hwcontext.c just after this gets called */ + if (!hwfc->pool) { + hwfc->internal->pool_internal = av_buffer_pool_init2(sizeof(AVVkFrame), + hwfc, vulkan_pool_alloc, + NULL); + if (!hwfc->internal->pool_internal) + return AVERROR(ENOMEM); + } + + return 0; +} + +static int vulkan_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame) +{ + frame->buf[0] = av_buffer_pool_get(hwfc->pool); + if (!frame->buf[0]) + return AVERROR(ENOMEM); + + frame->data[0] = frame->buf[0]->data; + frame->format = AV_PIX_FMT_VULKAN; + frame->width = hwfc->width; + frame->height = hwfc->height; + + return 0; +} + +static int vulkan_transfer_get_formats(AVHWFramesContext *hwfc, + enum AVHWFrameTransferDirection dir, + enum AVPixelFormat **formats) +{ + enum AVPixelFormat *fmts = av_malloc_array(2, sizeof(*fmts)); + if (!fmts) + return AVERROR(ENOMEM); + + fmts[0] = hwfc->sw_format; + fmts[1] = AV_PIX_FMT_NONE; + + *formats = fmts; + return 0; +} + +typedef struct VulkanMapping { + AVVkFrame *frame; + int flags; +} VulkanMapping; + +static void vulkan_unmap_frame(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) +{ + VulkanMapping *map = hwmap->priv; + AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + const int planes = av_pix_fmt_count_planes(hwfc->sw_format); + + /* Check if buffer needs flushing */ + if ((map->flags & AV_HWFRAME_MAP_WRITE) && + !(map->frame->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { + VkResult ret; + VkMappedMemoryRange flush_ranges[AV_NUM_DATA_POINTERS] = { { 0 } }; + + for (int i = 0; i < planes; i++) { + flush_ranges[i].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + flush_ranges[i].memory = map->frame->mem[i]; + flush_ranges[i].size = VK_WHOLE_SIZE; + } + + ret = vkFlushMappedMemoryRanges(hwctx->act_dev, planes, + flush_ranges); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to flush memory: %s\n", + vk_ret2str(ret)); + } + } + + for (int i = 0; i < planes; i++) + vkUnmapMemory(hwctx->act_dev, map->frame->mem[i]); + + av_free(map); +} + +static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + VkResult ret; + int err, mapped_mem_count = 0; + AVVkFrame *f = (AVVkFrame *)src->data[0]; + AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + const int planes = av_pix_fmt_count_planes(hwfc->sw_format); + + VulkanMapping *map = av_mallocz(sizeof(VulkanMapping)); + if (!map) + return AVERROR(EINVAL); + + if (src->format != AV_PIX_FMT_VULKAN) { + av_log(hwfc, AV_LOG_ERROR, "Cannot map from pixel format %s!\n", + av_get_pix_fmt_name(src->format)); + err = AVERROR(EINVAL); + goto fail; + } + + if (!(f->flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) || + !(f->tiling == VK_IMAGE_TILING_LINEAR)) { + av_log(hwfc, AV_LOG_ERROR, "Unable to map frame, not host visible " + "and linear!\n"); + err = AVERROR(EINVAL); + goto fail; + } + + dst->width = src->width; + dst->height = src->height; + + for (int i = 0; i < planes; i++) { + ret = vkMapMemory(hwctx->act_dev, f->mem[i], 0, + VK_WHOLE_SIZE, 0, (void **)&dst->data[i]); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to map image memory: %s\n", + vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + mapped_mem_count++; + } + + /* 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)) { + VkMappedMemoryRange map_mem_ranges[AV_NUM_DATA_POINTERS] = { { 0 } }; + for (int i = 0; i < planes; i++) { + map_mem_ranges[i].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + map_mem_ranges[i].size = VK_WHOLE_SIZE; + map_mem_ranges[i].memory = f->mem[i]; + } + + ret = vkInvalidateMappedMemoryRanges(hwctx->act_dev, planes, + map_mem_ranges); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to invalidate memory: %s\n", + vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + } + + for (int i = 0; i < planes; i++) { + VkImageSubresource sub = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + }; + VkSubresourceLayout layout; + vkGetImageSubresourceLayout(hwctx->act_dev, f->img[i], &sub, &layout); + dst->linesize[i] = layout.rowPitch; + } + + map->frame = f; + map->flags = flags; + + err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, + &vulkan_unmap_frame, map); + if (err < 0) + goto fail; + + return 0; + +fail: + for (int i = 0; i < mapped_mem_count; i++) + vkUnmapMemory(hwctx->act_dev, f->mem[i]); + + av_free(map); + return err; +} + +#if CONFIG_LIBDRM +static void vulkan_unmap_from(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) +{ + VulkanMapping *map = hwmap->priv; + AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + const int planes = av_pix_fmt_count_planes(hwfc->sw_format); + + for (int i = 0; i < planes; i++) { + vkDestroyImage(hwctx->act_dev, map->frame->img[i], hwctx->alloc); + vkFreeMemory(hwctx->act_dev, map->frame->mem[i], hwctx->alloc); + vkDestroySemaphore(hwctx->act_dev, map->frame->sem[i], hwctx->alloc); + } + + av_freep(&map->frame); +} + +static const struct { + uint32_t drm_fourcc; + VkFormat vk_format; +} vulkan_drm_format_map[] = { + { DRM_FORMAT_R8, VK_FORMAT_R8_UNORM }, + { DRM_FORMAT_R16, VK_FORMAT_R16_UNORM }, + { DRM_FORMAT_GR88, VK_FORMAT_R8G8_UNORM }, + { DRM_FORMAT_RG88, VK_FORMAT_R8G8_UNORM }, + { DRM_FORMAT_GR1616, VK_FORMAT_R16G16_UNORM }, + { DRM_FORMAT_RG1616, VK_FORMAT_R16G16_UNORM }, + { DRM_FORMAT_ARGB8888, VK_FORMAT_B8G8R8A8_UNORM }, + { DRM_FORMAT_XRGB8888, VK_FORMAT_B8G8R8A8_UNORM }, + { DRM_FORMAT_ABGR8888, VK_FORMAT_R8G8B8A8_UNORM }, + { DRM_FORMAT_XBGR8888, VK_FORMAT_R8G8B8A8_UNORM }, +}; + +static inline VkFormat drm_to_vulkan_fmt(uint32_t drm_fourcc) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(vulkan_drm_format_map); i++) + if (vulkan_drm_format_map[i].drm_fourcc == drm_fourcc) + return vulkan_drm_format_map[i].vk_format; + return VK_FORMAT_UNDEFINED; +} + +static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **frame, + const AVFrame *src) +{ + int err = 0; + VkResult ret; + AVVkFrame *f; + int bind_counts = 0; + AVHWDeviceContext *ctx = hwfc->device_ctx; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + VulkanDevicePriv *p = ctx->internal->priv; + 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; + + VK_LOAD_PFN(hwctx->inst, vkGetMemoryFdPropertiesKHR); + + for (int i = 0; i < desc->nb_layers; i++) { + if (drm_to_vulkan_fmt(desc->layers[i].format) == VK_FORMAT_UNDEFINED) { + av_log(ctx, AV_LOG_ERROR, "Unsupported DMABUF layer format %#08x!\n", + desc->layers[i].format); + return AVERROR(EINVAL); + } + } + + if (!(f = av_vk_frame_alloc())) { + av_log(ctx, AV_LOG_ERROR, "Unable to allocate memory for AVVkFrame!\n"); + err = AVERROR(ENOMEM); + 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; + + for (int i = 0; i < desc->nb_layers; i++) { + const int planes = desc->layers[i].nb_planes; + VkImageDrmFormatModifierExplicitCreateInfoEXT drm_info = { + .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, + }; + + VkExternalMemoryImageCreateInfo einfo = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, + .pNext = has_modifiers ? &drm_info : NULL, + .handleTypes = htype, + }; + + VkSemaphoreCreateInfo sem_spawn = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + }; + + VkImageCreateInfo create_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = &einfo, + .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, + .tiling = f->tiling, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, /* specs say so */ + .usage = frames_hwctx->usage, + .samples = VK_SAMPLE_COUNT_1_BIT, + .pQueueFamilyIndices = p->qfs, + .queueFamilyIndexCount = p->num_qfs, + .sharingMode = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, + }; + + get_plane_wh(&create_info.extent.width, &create_info.extent.height, + hwfc->sw_format, src->width, src->height, i); + + 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; + } + + /* Create image */ + ret = vkCreateImage(hwctx->act_dev, &create_info, + hwctx->alloc, &f->img[i]); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Image creation failure: %s\n", + vk_ret2str(ret)); + err = AVERROR(EINVAL); + goto fail; + } + + ret = vkCreateSemaphore(hwctx->act_dev, &sem_spawn, + hwctx->alloc, &f->sem[i]); + if (ret != VK_SUCCESS) { + av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n", + vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + /* We'd import a semaphore onto the one we created using + * vkImportSemaphoreFdKHR but unfortunately neither DRM nor VAAPI + * offer us anything we could import and sync with, so instead + * just signal the semaphore we created. */ + + f->layout[i] = create_info.initialLayout; + f->access[i] = 0x0; + } + + for (int i = 0; i < desc->nb_objects; i++) { + int use_ded_mem = 0; + 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), + }; + VkMemoryDedicatedAllocateInfo ded_alloc = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + .pNext = &idesc, + }; + + ret = pfn_vkGetMemoryFdPropertiesKHR(hwctx->act_dev, htype, + idesc.fd, &fdmp); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to get FD properties: %s\n", + vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + close(idesc.fd); + goto fail; + } + + req.memoryTypeBits = fdmp.memoryTypeBits; + + /* 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, + }; + + vkGetImageMemoryRequirements2(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, + &f->flags, &f->mem[i]); + if (err) { + close(idesc.fd); + return err; + } + + f->size[i] = desc->objects[i].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].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].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; + bind_counts++; + } + } + + /* Bind the allocated memory to the images */ + ret = vkBindImageMemory2(hwctx->act_dev, bind_counts, bind_info); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n", + vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + /* 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); + if (err) + goto fail; + + *frame = f; + + return 0; + +fail: + for (int i = 0; i < desc->nb_layers; i++) { + vkDestroyImage(hwctx->act_dev, f->img[i], hwctx->alloc); + vkDestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc); + } + for (int i = 0; i < desc->nb_objects; i++) + vkFreeMemory(hwctx->act_dev, f->mem[i], hwctx->alloc); + + av_free(f); + + return err; +} + +static int vulkan_map_from_drm(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + int err = 0; + AVVkFrame *f; + VulkanMapping *map = NULL; + + if ((err = vulkan_map_from_drm_frame_desc(hwfc, &f, src))) + return err; + + /* The unmapping function will free this */ + dst->data[0] = (uint8_t *)f; + 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); + if (err < 0) + goto fail; + + av_log(hwfc, AV_LOG_DEBUG, "Mapped DRM object to Vulkan!\n"); + + return 0; + +fail: + vulkan_frame_free(hwfc->device_ctx->hwctx, (uint8_t *)f); + av_free(map); + return err; +} + +#if CONFIG_VAAPI +static int vulkan_map_from_vaapi(AVHWFramesContext *dst_fc, + AVFrame *dst, const AVFrame *src, + int flags) +{ + int err; + AVFrame *tmp = av_frame_alloc(); + AVHWFramesContext *vaapi_fc = (AVHWFramesContext*)src->hw_frames_ctx->data; + AVVAAPIDeviceContext *vaapi_ctx = vaapi_fc->device_ctx->hwctx; + VASurfaceID surface_id = (VASurfaceID)(uintptr_t)src->data[3]; + + if (!tmp) + return AVERROR(ENOMEM); + + /* We have to sync since like the previous comment said, no semaphores */ + vaSyncSurface(vaapi_ctx->display, surface_id); + + tmp->format = AV_PIX_FMT_DRM_PRIME; + + err = av_hwframe_map(tmp, src, flags); + if (err < 0) + goto fail; + + err = vulkan_map_from_drm(dst_fc, dst, tmp, flags); + if (err < 0) + goto fail; + + err = ff_hwframe_map_replace(dst, src); + +fail: + av_frame_free(&tmp); + return err; +} +#endif +#endif + +#if CONFIG_CUDA +static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, + AVBufferRef *cuda_hwfc, + const AVFrame *frame) +{ + int err; + VkResult ret; + AVVkFrame *dst_f; + AVVkFrameInternal *dst_int; + AVHWDeviceContext *ctx = hwfc->device_ctx; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + const int planes = av_pix_fmt_count_planes(hwfc->sw_format); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format); + VK_LOAD_PFN(hwctx->inst, vkGetMemoryFdKHR); + VK_LOAD_PFN(hwctx->inst, vkGetSemaphoreFdKHR); + + AVHWFramesContext *cuda_fc = (AVHWFramesContext*)cuda_hwfc->data; + AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx; + AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx; + AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal; + CudaFunctions *cu = cu_internal->cuda_dl; + CUarray_format cufmt = desc->comp[0].depth > 8 ? CU_AD_FORMAT_UNSIGNED_INT16 : + CU_AD_FORMAT_UNSIGNED_INT8; + + dst_f = (AVVkFrame *)frame->data[0]; + + dst_int = dst_f->internal; + if (!dst_int || !dst_int->cuda_fc_ref) { + if (!dst_f->internal) + dst_f->internal = dst_int = av_mallocz(sizeof(*dst_f->internal)); + + if (!dst_int) { + err = AVERROR(ENOMEM); + goto fail; + } + + dst_int->cuda_fc_ref = av_buffer_ref(cuda_hwfc); + if (!dst_int->cuda_fc_ref) { + err = AVERROR(ENOMEM); + goto fail; + } + + for (int i = 0; i < planes; i++) { + CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC tex_desc = { + .offset = 0, + .arrayDesc = { + .Depth = 0, + .Format = cufmt, + .NumChannels = 1 + ((planes == 2) && i), + .Flags = 0, + }, + .numLevels = 1, + }; + CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = { + .type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD, + .size = dst_f->size[i], + }; + VkMemoryGetFdInfoKHR export_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, + .memory = dst_f->mem[i], + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR, + }; + VkSemaphoreGetFdInfoKHR sem_export = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, + .semaphore = dst_f->sem[i], + .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, + }; + + 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 = pfn_vkGetMemoryFdKHR(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"); + 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; + } + + ret = CHECK_CU(cu->cuExternalMemoryGetMappedMipmappedArray(&dst_int->cu_mma[i], + dst_int->ext_mem[i], + &tex_desc)); + if (ret < 0) { + err = AVERROR_EXTERNAL; + goto fail; + } + + ret = CHECK_CU(cu->cuMipmappedArrayGetLevel(&dst_int->cu_array[i], + dst_int->cu_mma[i], 0)); + if (ret < 0) { + err = AVERROR_EXTERNAL; + goto fail; + } + + ret = pfn_vkGetSemaphoreFdKHR(hwctx->act_dev, &sem_export, + &ext_sem_desc.handle.fd); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to export semaphore: %s\n", + vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + + ret = CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[i], + &ext_sem_desc)); + if (ret < 0) { + err = AVERROR_EXTERNAL; + goto fail; + } + } + } + + return 0; + +fail: + return err; +} + +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; + const int planes = av_pix_fmt_count_planes(hwfc->sw_format); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format); + + AVHWFramesContext *cuda_fc = (AVHWFramesContext*)src->hw_frames_ctx->data; + AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx; + AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx; + AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal; + CudaFunctions *cu = cu_internal->cuda_dl; + 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) { + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + return ret; + } + + 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++) { + CUDA_MEMCPY2D cpy = { + .srcMemoryType = CU_MEMORYTYPE_DEVICE, + .srcDevice = (CUdeviceptr)src->data[i], + .srcPitch = src->linesize[i], + .srcY = 0, + + .dstMemoryType = CU_MEMORYTYPE_ARRAY, + .dstArray = dst_int->cu_array[i], + }; + + int p_w, p_h; + get_plane_wh(&p_w, &p_h, hwfc->sw_format, hwfc->width, hwfc->height, i); + + 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; + goto fail; + } + } + + ret = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par, + planes, cuda_dev->stream)); + if (ret < 0) { + err = AVERROR_EXTERNAL; + goto fail; + } + + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + + av_log(hwfc, AV_LOG_VERBOSE, "Transfered CUDA image to Vulkan!\n"); + + return 0; + +fail: + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + vulkan_free_internal(dst_int); + dst_f->internal = NULL; + av_buffer_unref(&dst->buf[0]); + return err; +} +#endif + +static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + av_unused VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; + + switch (src->format) { +#if CONFIG_LIBDRM +#if CONFIG_VAAPI + case AV_PIX_FMT_VAAPI: + if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + return vulkan_map_from_vaapi(hwfc, dst, src, flags); +#endif + case AV_PIX_FMT_DRM_PRIME: + if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + return vulkan_map_from_drm(hwfc, dst, src, flags); +#endif + default: + return AVERROR(ENOSYS); + } +} + +#if CONFIG_LIBDRM +typedef struct VulkanDRMMapping { + AVDRMFrameDescriptor drm_desc; + AVVkFrame *source; +} VulkanDRMMapping; + +static void vulkan_unmap_to_drm(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) +{ + AVDRMFrameDescriptor *drm_desc = hwmap->priv; + + for (int i = 0; i < drm_desc->nb_objects; i++) + close(drm_desc->objects[i].fd); + + av_free(drm_desc); +} + +static inline uint32_t vulkan_fmt_to_drm(VkFormat vkfmt) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(vulkan_drm_format_map); i++) + if (vulkan_drm_format_map[i].vk_format == vkfmt) + return vulkan_drm_format_map[i].drm_fourcc; + return DRM_FORMAT_INVALID; +} + +static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + int err = 0; + VkResult ret; + AVVkFrame *f = (AVVkFrame *)src->data[0]; + VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; + VulkanFramesPriv *fp = hwfc->internal->priv; + AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + const int planes = av_pix_fmt_count_planes(hwfc->sw_format); + VK_LOAD_PFN(hwctx->inst, vkGetMemoryFdKHR); + VkImageDrmFormatModifierPropertiesEXT drm_mod = { + .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT, + }; + + AVDRMFrameDescriptor *drm_desc = av_mallocz(sizeof(*drm_desc)); + if (!drm_desc) + return AVERROR(ENOMEM); + + err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_EXTERNAL_EXPORT); + if (err < 0) + goto end; + + 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) { + VK_LOAD_PFN(hwctx->inst, vkGetImageDrmFormatModifierPropertiesEXT); + ret = pfn_vkGetImageDrmFormatModifierPropertiesEXT(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++) { + VkMemoryGetFdInfoKHR export_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, + .memory = f->mem[i], + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + }; + + ret = pfn_vkGetMemoryFdKHR(hwctx->act_dev, &export_info, + &drm_desc->objects[i].fd); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a FD!\n"); + err = AVERROR_EXTERNAL; + goto end; + } + + drm_desc->nb_objects++; + drm_desc->objects[i].size = f->size[i]; + drm_desc->objects[i].format_modifier = drm_mod.drmFormatModifier; + } + + drm_desc->nb_layers = planes; + 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, + }; + VkFormat plane_vkfmt = av_vkfmt_from_pixfmt(hwfc->sw_format)[i]; + + drm_desc->layers[i].format = vulkan_fmt_to_drm(plane_vkfmt); + drm_desc->layers[i].nb_planes = 1; + + if (drm_desc->layers[i].format == DRM_FORMAT_INVALID) { + av_log(hwfc, AV_LOG_ERROR, "Cannot map to DRM layer, unsupported!\n"); + err = AVERROR_PATCHWELCOME; + goto end; + } + + drm_desc->layers[i].planes[0].object_index = FFMIN(i, drm_desc->nb_objects - 1); + + if (f->tiling == VK_IMAGE_TILING_OPTIMAL) + continue; + + vkGetImageSubresourceLayout(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; + } + + dst->width = src->width; + dst->height = src->height; + dst->data[0] = (uint8_t *)drm_desc; + + av_log(hwfc, AV_LOG_VERBOSE, "Mapped AVVkFrame to a DRM object!\n"); + + return 0; + +end: + av_free(drm_desc); + return err; +} + +#if CONFIG_VAAPI +static int vulkan_map_to_vaapi(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + int err; + AVFrame *tmp = av_frame_alloc(); + if (!tmp) + return AVERROR(ENOMEM); + + tmp->format = AV_PIX_FMT_DRM_PRIME; + + err = vulkan_map_to_drm(hwfc, tmp, src, flags); + if (err < 0) + goto fail; + + err = av_hwframe_map(dst, tmp, flags); + if (err < 0) + goto fail; + + err = ff_hwframe_map_replace(dst, src); + +fail: + av_frame_free(&tmp); + return err; +} +#endif +#endif + +static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + av_unused VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; + + switch (dst->format) { +#if CONFIG_LIBDRM + case AV_PIX_FMT_DRM_PRIME: + if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + return vulkan_map_to_drm(hwfc, dst, src, flags); +#if CONFIG_VAAPI + case AV_PIX_FMT_VAAPI: + if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + return vulkan_map_to_vaapi(hwfc, dst, src, flags); +#endif +#endif + default: + return vulkan_map_frame_to_mem(hwfc, dst, src, flags); + } +} + +typedef struct ImageBuffer { + VkBuffer buf; + VkDeviceMemory mem; + VkMemoryPropertyFlagBits flags; + int mapped_mem; +} ImageBuffer; + +static void free_buf(void *opaque, uint8_t *data) +{ + AVHWDeviceContext *ctx = opaque; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + ImageBuffer *vkbuf = (ImageBuffer *)data; + + if (vkbuf->buf) + vkDestroyBuffer(hwctx->act_dev, vkbuf->buf, hwctx->alloc); + if (vkbuf->mem) + vkFreeMemory(hwctx->act_dev, vkbuf->mem, hwctx->alloc); + + av_free(data); +} + +static size_t get_req_buffer_size(VulkanDevicePriv *p, int *stride, int height) +{ + size_t size; + *stride = FFALIGN(*stride, p->props.properties.limits.optimalBufferCopyRowPitchAlignment); + size = height*(*stride); + size = FFALIGN(size, p->props.properties.limits.minMemoryMapAlignment); + return size; +} + +static int create_buf(AVHWDeviceContext *ctx, AVBufferRef **buf, + VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags, + size_t size, uint32_t req_memory_bits, int host_mapped, + void *create_pnext, void *alloc_pnext) +{ + int err; + VkResult ret; + int use_ded_mem; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + + VkBufferCreateInfo buf_spawn = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = create_pnext, + .usage = usage, + .size = size, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + + VkBufferMemoryRequirementsInfo2 req_desc = { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, + }; + VkMemoryDedicatedAllocateInfo ded_alloc = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + .pNext = alloc_pnext, + }; + VkMemoryDedicatedRequirements ded_req = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, + }; + VkMemoryRequirements2 req = { + .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + .pNext = &ded_req, + }; + + ImageBuffer *vkbuf = av_mallocz(sizeof(*vkbuf)); + if (!vkbuf) + return AVERROR(ENOMEM); + + vkbuf->mapped_mem = host_mapped; + + ret = vkCreateBuffer(hwctx->act_dev, &buf_spawn, NULL, &vkbuf->buf); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to create buffer: %s\n", + vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + + req_desc.buffer = vkbuf->buf; + + vkGetBufferMemoryRequirements2(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 = vkbuf->buf; + + /* Additional requirements imposed on us */ + if (req_memory_bits) + req.memoryRequirements.memoryTypeBits &= req_memory_bits; + + err = alloc_mem(ctx, &req.memoryRequirements, flags, + use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext, + &vkbuf->flags, &vkbuf->mem); + if (err) + goto fail; + + ret = vkBindBufferMemory(hwctx->act_dev, vkbuf->buf, vkbuf->mem, 0); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n", + vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + + *buf = av_buffer_create((uint8_t *)vkbuf, sizeof(*vkbuf), free_buf, ctx, 0); + if (!(*buf)) { + err = AVERROR(ENOMEM); + goto fail; + } + + return 0; + +fail: + free_buf(ctx, (uint8_t *)vkbuf); + return err; +} + +/* Skips mapping of host mapped buffers but still invalidates them */ +static int map_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, uint8_t *mem[], + int nb_buffers, int invalidate) +{ + VkResult ret; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + VkMappedMemoryRange invalidate_ctx[AV_NUM_DATA_POINTERS]; + int invalidate_count = 0; + + for (int i = 0; i < nb_buffers; i++) { + ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; + if (vkbuf->mapped_mem) + continue; + + ret = vkMapMemory(hwctx->act_dev, vkbuf->mem, 0, + VK_WHOLE_SIZE, 0, (void **)&mem[i]); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to map buffer memory: %s\n", + vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + if (!invalidate) + return 0; + + for (int i = 0; i < nb_buffers; i++) { + ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; + const VkMappedMemoryRange ival_buf = { + .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + .memory = vkbuf->mem, + .size = VK_WHOLE_SIZE, + }; + + /* For host imported memory Vulkan says to use platform-defined + * sync methods, but doesn't really say not to call flush or invalidate + * on original host pointers. It does explicitly allow to do that on + * host-mapped pointers which are then mapped again using vkMapMemory, + * but known implementations return the original pointers when mapped + * again. */ + if (vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + continue; + + invalidate_ctx[invalidate_count++] = ival_buf; + } + + if (invalidate_count) { + ret = vkInvalidateMappedMemoryRanges(hwctx->act_dev, invalidate_count, + invalidate_ctx); + if (ret != VK_SUCCESS) + av_log(ctx, AV_LOG_WARNING, "Failed to invalidate memory: %s\n", + vk_ret2str(ret)); + } + + return 0; +} + +static int unmap_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, + int nb_buffers, int flush) +{ + int err = 0; + VkResult ret; + AVVulkanDeviceContext *hwctx = ctx->hwctx; + VkMappedMemoryRange flush_ctx[AV_NUM_DATA_POINTERS]; + int flush_count = 0; + + if (flush) { + for (int i = 0; i < nb_buffers; i++) { + ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; + const VkMappedMemoryRange flush_buf = { + .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + .memory = vkbuf->mem, + .size = VK_WHOLE_SIZE, + }; + + if (vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + continue; + + flush_ctx[flush_count++] = flush_buf; + } + } + + if (flush_count) { + ret = vkFlushMappedMemoryRanges(hwctx->act_dev, flush_count, flush_ctx); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Failed to flush memory: %s\n", + vk_ret2str(ret)); + err = AVERROR_EXTERNAL; /* We still want to try to unmap them */ + } + } + + for (int i = 0; i < nb_buffers; i++) { + ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; + if (vkbuf->mapped_mem) + continue; + + vkUnmapMemory(hwctx->act_dev, vkbuf->mem); + } + + return err; +} + +static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, + AVBufferRef **bufs, size_t *buf_offsets, + const int *buf_stride, int w, + int h, enum AVPixelFormat pix_fmt, int to_buf) +{ + int err; + AVVkFrame *frame = (AVVkFrame *)f->data[0]; + VulkanFramesPriv *fp = hwfc->internal->priv; + + int bar_num = 0; + VkPipelineStageFlagBits sem_wait_dst[AV_NUM_DATA_POINTERS]; + + const int planes = av_pix_fmt_count_planes(pix_fmt); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + + VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 }; + VulkanExecCtx *ectx = to_buf ? &fp->download_ctx : &fp->upload_ctx; + VkCommandBuffer cmd_buf = get_buf_exec_ctx(hwfc, ectx); + + VkSubmitInfo s_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pSignalSemaphores = frame->sem, + .pWaitSemaphores = frame->sem, + .pWaitDstStageMask = sem_wait_dst, + .signalSemaphoreCount = planes, + .waitSemaphoreCount = planes, + }; + + if ((err = wait_start_exec_ctx(hwfc, ectx))) + return err; + + /* Change the image layout to something more optimal for transfers */ + for (int i = 0; i < planes; i++) { + VkImageLayout new_layout = to_buf ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + VkAccessFlags new_access = to_buf ? VK_ACCESS_TRANSFER_READ_BIT : + VK_ACCESS_TRANSFER_WRITE_BIT; + + sem_wait_dst[i] = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + + /* If the layout matches and we have read access skip the barrier */ + if ((frame->layout[i] == new_layout) && (frame->access[i] & new_access)) + continue; + + img_bar[bar_num].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + img_bar[bar_num].srcAccessMask = 0x0; + img_bar[bar_num].dstAccessMask = new_access; + img_bar[bar_num].oldLayout = frame->layout[i]; + img_bar[bar_num].newLayout = new_layout; + img_bar[bar_num].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + img_bar[bar_num].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + img_bar[bar_num].image = frame->img[i]; + img_bar[bar_num].subresourceRange.levelCount = 1; + img_bar[bar_num].subresourceRange.layerCount = 1; + img_bar[bar_num].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + + frame->layout[i] = img_bar[bar_num].newLayout; + frame->access[i] = img_bar[bar_num].dstAccessMask; + + bar_num++; + } + + if (bar_num) + vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + 0, NULL, 0, NULL, bar_num, img_bar); + + /* Schedule a copy for each plane */ + for (int i = 0; i < planes; i++) { + ImageBuffer *vkbuf = (ImageBuffer *)bufs[i]->data; + VkBufferImageCopy buf_reg = { + .bufferOffset = buf_offsets[i], + .bufferRowLength = buf_stride[i] / desc->comp[i].step, + .imageSubresource.layerCount = 1, + .imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .imageOffset = { 0, 0, 0, }, + }; + + int p_w, p_h; + get_plane_wh(&p_w, &p_h, pix_fmt, w, h, i); + + buf_reg.bufferImageHeight = p_h; + buf_reg.imageExtent = (VkExtent3D){ p_w, p_h, 1, }; + + if (to_buf) + vkCmdCopyImageToBuffer(cmd_buf, frame->img[i], frame->layout[i], + vkbuf->buf, 1, &buf_reg); + else + vkCmdCopyBufferToImage(cmd_buf, vkbuf->buf, frame->img[i], + frame->layout[i], 1, &buf_reg); + } + + /* When uploading, do this asynchronously if the source is refcounted by + * keeping the buffers as a submission dependency. + * The hwcontext is guaranteed to not be freed until all frames are freed + * in the frames_unint function. + * When downloading to buffer, do this synchronously and wait for the + * queue submission to finish executing */ + if (!to_buf) { + int ref; + for (ref = 0; ref < AV_NUM_DATA_POINTERS; ref++) { + if (!f->buf[ref]) + break; + if ((err = add_buf_dep_exec_ctx(hwfc, ectx, &f->buf[ref], 1))) + return err; + } + if (ref && (err = add_buf_dep_exec_ctx(hwfc, ectx, bufs, planes))) + return err; + return submit_exec_ctx(hwfc, ectx, &s_info, !ref); + } else { + return submit_exec_ctx(hwfc, ectx, &s_info, 1); + } +} + +static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, + const AVFrame *swf, int from) +{ + int err = 0; + VkResult ret; + AVVkFrame *f = (AVVkFrame *)vkf->data[0]; + AVHWDeviceContext *dev_ctx = hwfc->device_ctx; + AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; + VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; + + AVFrame tmp; + AVBufferRef *bufs[AV_NUM_DATA_POINTERS] = { 0 }; + size_t buf_offsets[AV_NUM_DATA_POINTERS] = { 0 }; + + int p_w, p_h; + 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); + + VK_LOAD_PFN(hwctx->inst, vkGetMemoryHostPointerPropertiesEXT); + + 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"); + return AVERROR(EINVAL); + } + + if (swf->width > hwfc->width || swf->height > hwfc->height) + return AVERROR(EINVAL); + + /* For linear, host visiable images */ + if (f->tiling == VK_IMAGE_TILING_LINEAR && + f->flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { + AVFrame *map = av_frame_alloc(); + if (!map) + return AVERROR(ENOMEM); + map->format = swf->format; + + err = vulkan_map_frame_to_mem(hwfc, map, vkf, AV_HWFRAME_MAP_WRITE); + if (err) + return err; + + err = av_frame_copy((AVFrame *)(from ? swf : map), from ? map : swf); + av_frame_free(&map); + return err; + } + + /* Create buffers */ + for (int i = 0; i < planes; i++) { + size_t req_size; + + VkExternalMemoryBufferCreateInfo create_desc = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, + }; + + VkImportMemoryHostPointerInfoEXT import_desc = { + .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT, + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, + }; + + VkMemoryHostPointerPropertiesEXT p_props = { + .sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT, + }; + + get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); + + tmp.linesize[i] = FFABS(swf->linesize[i]); + + /* Do not map images with a negative stride */ + if (map_host && swf->linesize[i] > 0) { + size_t offs; + offs = (uintptr_t)swf->data[i] % p->hprops.minImportedHostPointerAlignment; + import_desc.pHostPointer = swf->data[i] - offs; + + /* We have to compensate for the few extra bytes of padding we + * completely ignore at the start */ + req_size = FFALIGN(offs + tmp.linesize[i] * p_h, + p->hprops.minImportedHostPointerAlignment); + + ret = pfn_vkGetMemoryHostPointerPropertiesEXT(hwctx->act_dev, + import_desc.handleType, + import_desc.pHostPointer, + &p_props); + + if (ret == VK_SUCCESS) { + host_mapped[i] = 1; + buf_offsets[i] = offs; + } + } + + if (!host_mapped[i]) + req_size = get_req_buffer_size(p, &tmp.linesize[i], p_h); + + err = create_buf(dev_ctx, &bufs[i], + from ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + req_size, p_props.memoryTypeBits, host_mapped[i], + host_mapped[i] ? &create_desc : NULL, + host_mapped[i] ? &import_desc : NULL); + if (err) + goto end; + } + + if (!from) { + /* Map, copy image to buffer, unmap */ + if ((err = map_buffers(dev_ctx, bufs, tmp.data, planes, 0))) + goto end; + + for (int i = 0; i < planes; i++) { + if (host_mapped[i]) + continue; + + get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); + + av_image_copy_plane(tmp.data[i], tmp.linesize[i], + (const uint8_t *)swf->data[i], swf->linesize[i], + FFMIN(tmp.linesize[i], FFABS(swf->linesize[i])), + p_h); + } + + if ((err = unmap_buffers(dev_ctx, bufs, planes, 1))) + goto end; + } + + /* Copy buffers into/from image */ + err = transfer_image_buf(hwfc, vkf, bufs, buf_offsets, tmp.linesize, + swf->width, swf->height, swf->format, from); + + if (from) { + /* Map, copy image to buffer, unmap */ + if ((err = map_buffers(dev_ctx, bufs, tmp.data, planes, 0))) + goto end; + + for (int i = 0; i < planes; i++) { + if (host_mapped[i]) + continue; + + get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); + + av_image_copy_plane(swf->data[i], swf->linesize[i], + (const uint8_t *)tmp.data[i], tmp.linesize[i], + FFMIN(tmp.linesize[i], FFABS(swf->linesize[i])), + p_h); + } + + if ((err = unmap_buffers(dev_ctx, bufs, planes, 1))) + goto end; + } + +end: + for (int i = 0; i < planes; i++) + av_buffer_unref(&bufs[i]); + + return err; +} + +static int vulkan_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src) +{ + av_unused VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; + + switch (src->format) { +#if CONFIG_CUDA + case AV_PIX_FMT_CUDA: + if ((p->extensions & EXT_EXTERNAL_FD_MEMORY) && + (p->extensions & EXT_EXTERNAL_FD_SEM)) + return vulkan_transfer_data_from_cuda(hwfc, dst, src); +#endif + default: + if (src->hw_frames_ctx) + return AVERROR(ENOSYS); + else + return vulkan_transfer_data(hwfc, dst, src, 0); + } +} + +#if CONFIG_CUDA +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; + const int planes = av_pix_fmt_count_planes(hwfc->sw_format); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format); + + AVHWFramesContext *cuda_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data; + AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx; + AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx; + AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal; + CudaFunctions *cu = cu_internal->cuda_dl; + 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 = vulkan_export_to_cuda(hwfc, dst->hw_frames_ctx, src); + if (err < 0) { + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + 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++) { + CUDA_MEMCPY2D cpy = { + .dstMemoryType = CU_MEMORYTYPE_DEVICE, + .dstDevice = (CUdeviceptr)dst->data[i], + .dstPitch = dst->linesize[i], + .dstY = 0, + + .srcMemoryType = CU_MEMORYTYPE_ARRAY, + .srcArray = dst_int->cu_array[i], + }; + + int w, h; + get_plane_wh(&w, &h, hwfc->sw_format, hwfc->width, hwfc->height, i); + + 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; + goto fail; + } + } + + ret = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par, + planes, cuda_dev->stream)); + if (ret < 0) { + err = AVERROR_EXTERNAL; + goto fail; + } + + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + + av_log(hwfc, AV_LOG_VERBOSE, "Transfered Vulkan image to CUDA!\n"); + + return 0; + +fail: + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + vulkan_free_internal(dst_int); + dst_f->internal = NULL; + av_buffer_unref(&dst->buf[0]); + return err; +} +#endif + +static int vulkan_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src) +{ + av_unused VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; + + switch (dst->format) { +#if CONFIG_CUDA + case AV_PIX_FMT_CUDA: + if ((p->extensions & EXT_EXTERNAL_FD_MEMORY) && + (p->extensions & EXT_EXTERNAL_FD_SEM)) + return vulkan_transfer_data_to_cuda(hwfc, dst, src); +#endif + default: + if (dst->hw_frames_ctx) + return AVERROR(ENOSYS); + else + return vulkan_transfer_data(hwfc, src, dst, 1); + } +} + +static int vulkan_frames_derive_to(AVHWFramesContext *dst_fc, + AVHWFramesContext *src_fc, int flags) +{ + return vulkan_frames_init(dst_fc); +} + +AVVkFrame *av_vk_frame_alloc(void) +{ + return av_mallocz(sizeof(AVVkFrame)); +} + +const HWContextType ff_hwcontext_type_vulkan = { + .type = AV_HWDEVICE_TYPE_VULKAN, + .name = "Vulkan", + + .device_hwctx_size = sizeof(AVVulkanDeviceContext), + .device_priv_size = sizeof(VulkanDevicePriv), + .frames_hwctx_size = sizeof(AVVulkanFramesContext), + .frames_priv_size = sizeof(VulkanFramesPriv), + + .device_init = &vulkan_device_init, + .device_create = &vulkan_device_create, + .device_derive = &vulkan_device_derive, + + .frames_get_constraints = &vulkan_frames_get_constraints, + .frames_init = vulkan_frames_init, + .frames_get_buffer = vulkan_get_buffer, + .frames_uninit = vulkan_frames_uninit, + + .transfer_get_formats = vulkan_transfer_get_formats, + .transfer_data_to = vulkan_transfer_data_to, + .transfer_data_from = vulkan_transfer_data_from, + + .map_to = vulkan_map_to, + .map_from = vulkan_map_from, + .frames_derive_to = &vulkan_frames_derive_to, + + .pix_fmts = (const enum AVPixelFormat []) { + AV_PIX_FMT_VULKAN, + AV_PIX_FMT_NONE + }, +}; diff -Nru ffmpeg-4.2.2/libavutil/hwcontext_vulkan.h ffmpeg-4.4/libavutil/hwcontext_vulkan.h --- ffmpeg-4.2.2/libavutil/hwcontext_vulkan.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/hwcontext_vulkan.h 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,204 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_HWCONTEXT_VULKAN_H +#define AVUTIL_HWCONTEXT_VULKAN_H + +#include + +#include "pixfmt.h" +#include "frame.h" + +/** + * @file + * API-specific header for AV_HWDEVICE_TYPE_VULKAN. + * + * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs + * with the data pointer set to an AVVkFrame. + */ + +/** + * Main Vulkan context, allocated as AVHWDeviceContext.hwctx. + * All of these can be set before init to change what the context uses + */ +typedef struct AVVulkanDeviceContext { + /** + * Custom memory allocator, else NULL + */ + const VkAllocationCallbacks *alloc; + /** + * Vulkan instance. Must be at least version 1.1. + */ + VkInstance inst; + /** + * Physical device + */ + VkPhysicalDevice phys_dev; + /** + * Active device + */ + VkDevice act_dev; + /** + * 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) + */ + 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. + */ + 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. + */ + int queue_family_comp_index; + int nb_comp_queues; + /** + * Enabled instance extensions. + * If supplying your own device context, set this to an array of strings, with + * each entry containing the specified Vulkan extension string to enable. + * Duplicates are possible and accepted. + * If no extensions are enabled, set these fields to NULL, and 0 respectively. + */ + const char * const *enabled_inst_extensions; + int nb_enabled_inst_extensions; + /** + * Enabled device extensions. By default, VK_KHR_external_memory_fd, + * VK_EXT_external_memory_dma_buf, VK_EXT_image_drm_format_modifier, + * VK_KHR_external_semaphore_fd and VK_EXT_external_memory_host are enabled if found. + * If supplying your own device context, these fields takes the same format as + * the above fields, with the same conditions that duplicates are possible + * and accepted, and that NULL and 0 respectively means no extensions are enabled. + */ + const char * const *enabled_dev_extensions; + int nb_enabled_dev_extensions; + /** + * This structure should be set to the set of features that present and enabled + * during device creation. When a device is created by FFmpeg, it will default to + * enabling all that are present of the shaderImageGatherExtended, + * fragmentStoresAndAtomics, shaderInt64 and vertexPipelineStoresAndAtomics features. + */ + VkPhysicalDeviceFeatures2 device_features; +} AVVulkanDeviceContext; + +/** + * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options + */ +typedef struct AVVulkanFramesContext { + /** + * Controls the tiling of allocated frames. + */ + VkImageTiling tiling; + /** + * Defines extra usage of output frames. If left as 0, the following bits + * are set: TRANSFER_SRC, TRANSFER_DST. SAMPLED and STORAGE. + */ + VkImageUsageFlagBits usage; + /** + * Extension data for image creation. + */ + void *create_pnext; + /** + * Extension data for memory allocation. Must have as many entries as + * the number of planes of the sw_format. + * This will be chained to VkExportMemoryAllocateInfo, which is used + * to make all pool images exportable to other APIs if the necessary + * extensions are present in enabled_dev_extensions. + */ + void *alloc_pnext[AV_NUM_DATA_POINTERS]; +} AVVulkanFramesContext; + +/* + * Frame structure, the VkFormat of the image will always match + * the pool's sw_format. + * 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, + * images will be created with the EXCLUSIVE sharing mode. Otherwise, all images + * will be created using the CONCURRENT sharing mode. + * + * @note the size of this structure is not part of the ABI, to allocate + * you must use @av_vk_frame_alloc(). + */ +typedef struct AVVkFrame { + /** + * Vulkan images to which the memory is bound to. + */ + VkImage img[AV_NUM_DATA_POINTERS]; + + /** + * The same tiling must be used for all images in the frame. + */ + VkImageTiling tiling; + + /** + * Memory backing the images. Could be less than the amount of images + * if importing from a DRM or VAAPI frame. + */ + VkDeviceMemory mem[AV_NUM_DATA_POINTERS]; + size_t size[AV_NUM_DATA_POINTERS]; + + /** + * OR'd flags for all memory allocated + */ + VkMemoryPropertyFlagBits flags; + + /** + * Updated after every barrier + */ + VkAccessFlagBits access[AV_NUM_DATA_POINTERS]; + 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. + */ + VkSemaphore sem[AV_NUM_DATA_POINTERS]; + + /** + * Internal data. + */ + struct AVVkFrameInternal *internal; +} AVVkFrame; + +/** + * Allocates a single AVVkFrame and initializes everything as 0. + * @note Must be freed via av_free() + */ +AVVkFrame *av_vk_frame_alloc(void); + +/** + * Returns the format of each image up to the number of planes for a given sw_format. + * Returns NULL on unsupported formats. + */ +const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p); + +#endif /* AVUTIL_HWCONTEXT_VULKAN_H */ diff -Nru ffmpeg-4.2.2/libavutil/imgutils.c ffmpeg-4.4/libavutil/imgutils.c --- ffmpeg-4.2.2/libavutil/imgutils.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/imgutils.c 2021-04-08 21:28:40.000000000 +0000 @@ -108,45 +108,69 @@ return 0; } -int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, - uint8_t *ptr, const int linesizes[4]) +int av_image_fill_plane_sizes(size_t sizes[4], enum AVPixelFormat pix_fmt, + int height, const ptrdiff_t linesizes[4]) { - int i, total_size, size[4] = { 0 }, has_plane[4] = { 0 }; + int i, has_plane[4] = { 0 }; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - memset(data , 0, sizeof(data[0])*4); + memset(sizes , 0, sizeof(sizes[0])*4); if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) return AVERROR(EINVAL); - data[0] = ptr; - if (linesizes[0] > (INT_MAX - 1024) / height) + if (linesizes[0] > SIZE_MAX / height) return AVERROR(EINVAL); - size[0] = linesizes[0] * height; + sizes[0] = linesizes[0] * (size_t)height; if (desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & FF_PSEUDOPAL) { - data[1] = ptr + size[0]; /* palette is stored here as 256 32 bits words */ - return size[0] + 256 * 4; + sizes[1] = 256 * 4; /* palette is stored here as 256 32 bits words */ + return 0; } for (i = 0; i < 4; i++) has_plane[desc->comp[i].plane] = 1; - total_size = size[0]; for (i = 1; i < 4 && has_plane[i]; i++) { int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; - data[i] = data[i-1] + size[i-1]; h = (height + (1 << s) - 1) >> s; - if (linesizes[i] > INT_MAX / h) + if (linesizes[i] > SIZE_MAX / h) return AVERROR(EINVAL); - size[i] = h * linesizes[i]; - if (total_size > INT_MAX - size[i]) + sizes[i] = (size_t)h * linesizes[i]; + } + + return 0; +} + +int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, + uint8_t *ptr, const int linesizes[4]) +{ + int i, ret; + ptrdiff_t linesizes1[4]; + size_t sizes[4]; + + memset(data , 0, sizeof(data[0])*4); + + for (i = 0; i < 4; i++) + linesizes1[i] = linesizes[i]; + + ret = av_image_fill_plane_sizes(sizes, pix_fmt, height, linesizes1); + if (ret < 0) + return ret; + + ret = 0; + for (i = 0; i < 4; i++) { + if (sizes[i] > INT_MAX - ret) return AVERROR(EINVAL); - total_size += size[i]; + ret += sizes[i]; } - return total_size; + data[0] = ptr; + for (i = 1; i < 4 && sizes[i]; i++) + data[i] = data[i - 1] + sizes[i - 1]; + + return ret; } int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt) @@ -194,6 +218,8 @@ { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int i, ret; + ptrdiff_t linesizes1[4]; + size_t total_size, sizes[4]; uint8_t *buf; if (!desc) @@ -204,12 +230,20 @@ if ((ret = av_image_fill_linesizes(linesizes, pix_fmt, align>7 ? FFALIGN(w, 8) : w)) < 0) return ret; - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { linesizes[i] = FFALIGN(linesizes[i], align); + linesizes1[i] = linesizes[i]; + } - if ((ret = av_image_fill_pointers(pointers, pix_fmt, h, NULL, linesizes)) < 0) + if ((ret = av_image_fill_plane_sizes(sizes, pix_fmt, h, linesizes1)) < 0) return ret; - buf = av_malloc(ret + align); + total_size = align; + for (i = 0; i < 4; i++) { + if (total_size > SIZE_MAX - sizes[i]) + return AVERROR(EINVAL); + total_size += sizes[i]; + } + buf = av_malloc(total_size); if (!buf) return AVERROR(ENOMEM); if ((ret = av_image_fill_pointers(pointers, pix_fmt, h, buf, linesizes)) < 0) { @@ -220,6 +254,7 @@ avpriv_set_systematic_pal2((uint32_t*)pointers[1], pix_fmt); if (align < 4) { av_log(NULL, AV_LOG_ERROR, "Formats with a palette require a minimum alignment of 4\n"); + av_free(buf); return AVERROR(EINVAL); } } @@ -431,9 +466,10 @@ int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align) { - uint8_t *data[4]; + int ret, i; int linesize[4]; - int ret; + ptrdiff_t aligned_linesize[4]; + size_t sizes[4]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); if (!desc) return AVERROR(EINVAL); @@ -446,8 +482,24 @@ if (desc->flags & FF_PSEUDOPAL) return FFALIGN(width, align) * height; - return av_image_fill_arrays(data, linesize, NULL, pix_fmt, - width, height, align); + ret = av_image_fill_linesizes(linesize, pix_fmt, width); + if (ret < 0) + return ret; + + for (i = 0; i < 4; i++) + aligned_linesize[i] = FFALIGN(linesize[i], align); + + ret = av_image_fill_plane_sizes(sizes, pix_fmt, height, aligned_linesize); + if (ret < 0) + return ret; + + ret = 0; + for (i = 0; i < 4; i++) { + if (sizes[i] > INT_MAX - ret) + return AVERROR(EINVAL); + ret += sizes[i]; + } + return ret; } int av_image_copy_to_buffer(uint8_t *dst, int dst_size, @@ -519,7 +571,6 @@ if (clear_size == 1) { memset(dst, clear[0], dst_size); - dst_size = 0; } else { if (clear_size > dst_size) clear_size = dst_size; diff -Nru ffmpeg-4.2.2/libavutil/imgutils.h ffmpeg-4.4/libavutil/imgutils.h --- ffmpeg-4.2.2/libavutil/imgutils.h 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/imgutils.h 2021-04-08 21:28:40.000000000 +0000 @@ -68,6 +68,20 @@ int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width); /** + * Fill plane sizes for an image with pixel format pix_fmt and height height. + * + * @param size the array to be filled with the size of each image plane + * @param linesizes the array containing the linesize for each + * plane, should be filled by av_image_fill_linesizes() + * @return >= 0 in case of success, a negative error code otherwise + * + * @note The linesize parameters have the type ptrdiff_t here, while they are + * int for av_image_fill_linesizes(). + */ +int av_image_fill_plane_sizes(size_t size[4], enum AVPixelFormat pix_fmt, + int height, const ptrdiff_t linesizes[4]); + +/** * Fill plane data pointers for an image with pixel format pix_fmt and * height height. * diff -Nru ffmpeg-4.2.2/libavutil/internal.h ffmpeg-4.4/libavutil/internal.h --- ffmpeg-4.2.2/libavutil/internal.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/internal.h 2021-04-08 21:28:40.000000000 +0000 @@ -43,7 +43,6 @@ #include "cpu.h" #include "dict.h" #include "macros.h" -#include "mem.h" #include "pixfmt.h" #include "version.h" @@ -92,10 +91,6 @@ type av_##name##_get_##field(const str *s) { return s->field; } \ void av_##name##_set_##field(str *s, type v) { s->field = v; } -// Some broken preprocessors need a second expansion -// to be forced to tokenize __VA_ARGS__ -#define E1(x) x - /* Check if the hard coded offset of a struct member still matches reality. * Induce a compilation failure if not. */ @@ -103,75 +98,11 @@ int x_##o[offsetof(s, m) == o? 1: -1]; \ } -#define LOCAL_ALIGNED_A(a, t, v, s, o, ...) \ - uint8_t la_##v[sizeof(t s o) + (a)]; \ - t (*v) o = (void *)FFALIGN((uintptr_t)la_##v, a) - -#define LOCAL_ALIGNED_D(a, t, v, s, o, ...) \ - DECLARE_ALIGNED(a, t, la_##v) s o; \ - t (*v) o = la_##v - -#define LOCAL_ALIGNED(a, t, v, ...) LOCAL_ALIGNED_##a(t, v, __VA_ARGS__) - -#if HAVE_LOCAL_ALIGNED -# define LOCAL_ALIGNED_4(t, v, ...) E1(LOCAL_ALIGNED_D(4, t, v, __VA_ARGS__,,)) -#else -# define LOCAL_ALIGNED_4(t, v, ...) E1(LOCAL_ALIGNED_A(4, t, v, __VA_ARGS__,,)) -#endif - -#if HAVE_LOCAL_ALIGNED -# define LOCAL_ALIGNED_8(t, v, ...) E1(LOCAL_ALIGNED_D(8, t, v, __VA_ARGS__,,)) -#else -# define LOCAL_ALIGNED_8(t, v, ...) E1(LOCAL_ALIGNED_A(8, t, v, __VA_ARGS__,,)) -#endif -#if HAVE_LOCAL_ALIGNED -# define LOCAL_ALIGNED_16(t, v, ...) E1(LOCAL_ALIGNED_D(16, t, v, __VA_ARGS__,,)) -#else -# define LOCAL_ALIGNED_16(t, v, ...) E1(LOCAL_ALIGNED_A(16, t, v, __VA_ARGS__,,)) -#endif +#define FF_ALLOC_TYPED_ARRAY(p, nelem) (p = av_malloc_array(nelem, sizeof(*p))) +#define FF_ALLOCZ_TYPED_ARRAY(p, nelem) (p = av_mallocz_array(nelem, sizeof(*p))) -#if HAVE_LOCAL_ALIGNED -# define LOCAL_ALIGNED_32(t, v, ...) E1(LOCAL_ALIGNED_D(32, t, v, __VA_ARGS__,,)) -#else -# define LOCAL_ALIGNED_32(t, v, ...) E1(LOCAL_ALIGNED_A(32, t, v, __VA_ARGS__,,)) -#endif - -#define FF_ALLOC_OR_GOTO(ctx, p, size, label)\ -{\ - p = av_malloc(size);\ - if (!(p) && (size) != 0) {\ - av_log(ctx, AV_LOG_ERROR, "Cannot allocate memory.\n");\ - goto label;\ - }\ -} - -#define FF_ALLOCZ_OR_GOTO(ctx, p, size, label)\ -{\ - p = av_mallocz(size);\ - if (!(p) && (size) != 0) {\ - av_log(ctx, AV_LOG_ERROR, "Cannot allocate memory.\n");\ - goto label;\ - }\ -} - -#define FF_ALLOC_ARRAY_OR_GOTO(ctx, p, nelem, elsize, label)\ -{\ - p = av_malloc_array(nelem, elsize);\ - if (!p) {\ - av_log(ctx, AV_LOG_ERROR, "Cannot allocate memory.\n");\ - goto label;\ - }\ -} - -#define FF_ALLOCZ_ARRAY_OR_GOTO(ctx, p, nelem, elsize, label)\ -{\ - p = av_mallocz_array(nelem, elsize);\ - if (!p) {\ - av_log(ctx, AV_LOG_ERROR, "Cannot allocate memory.\n");\ - goto label;\ - }\ -} +#define FF_PTR_ADD(ptr, off) ((off) ? (ptr) + (off) : (ptr)) #include "libm.h" @@ -353,7 +284,8 @@ /** * Set a dictionary value to an ISO-8601 compliant timestamp string. * - * @param s AVFormatContext + * @param dict pointer to a pointer to a dictionary struct. If *dict is NULL + * a dictionary struct is allocated and put in *dict. * @param key metadata key * @param timestamp unix timestamp in microseconds * @return <0 on error @@ -369,4 +301,11 @@ #define FF_PSEUDOPAL 0 #endif +// Temporary typedef to simplify porting all AVBufferRef users to size_t +#if FF_API_BUFFER_SIZE_T +typedef int buffer_size_t; +#else +typedef size_t buffer_size_t; +#endif + #endif /* AVUTIL_INTERNAL_H */ diff -Nru ffmpeg-4.2.2/libavutil/lls.h ffmpeg-4.4/libavutil/lls.h --- ffmpeg-4.2.2/libavutil/lls.h 2018-07-17 09:27:42.000000000 +0000 +++ ffmpeg-4.4/libavutil/lls.h 2021-04-08 21:28:40.000000000 +0000 @@ -24,7 +24,7 @@ #define AVUTIL_LLS_H #include "macros.h" -#include "mem.h" +#include "mem_internal.h" #include "version.h" #define MAX_VARS 32 diff -Nru ffmpeg-4.2.2/libavutil/log.c ffmpeg-4.4/libavutil/log.c --- ffmpeg-4.2.2/libavutil/log.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/log.c 2020-07-11 10:39:30.000000000 +0000 @@ -55,7 +55,7 @@ static int flags; #define NB_LEVELS 8 -#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE +#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE #include static const uint8_t color[16 + AV_CLASS_CATEGORY_NB] = { [AV_LOG_PANIC /8] = 12, @@ -120,50 +120,68 @@ #endif static int use_color = -1; +#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE +static void win_console_puts(const char *str) +{ + const uint8_t *q = str; + uint16_t line[LINE_SZ]; + + while (*q) { + uint16_t *buf = line; + DWORD nb_chars = 0; + DWORD written; + + while (*q && nb_chars < LINE_SZ - 1) { + uint32_t ch; + uint16_t tmp; + + GET_UTF8(ch, *q ? *q++ : 0, ch = 0xfffd; goto continue_on_invalid;) +continue_on_invalid: + PUT_UTF16(ch, tmp, *buf++ = tmp; nb_chars++;) + } + + WriteConsoleW(con, line, nb_chars, &written, NULL); + } +} +#endif + static void check_color_terminal(void) { -#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE + char *term = getenv("TERM"); + +#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE CONSOLE_SCREEN_BUFFER_INFO con_info; + DWORD dummy; con = GetStdHandle(STD_ERROR_HANDLE); - use_color = (con != INVALID_HANDLE_VALUE) && !getenv("NO_COLOR") && - !getenv("AV_LOG_FORCE_NOCOLOR"); - if (use_color) { + if (con != INVALID_HANDLE_VALUE && !GetConsoleMode(con, &dummy)) + con = INVALID_HANDLE_VALUE; + if (con != INVALID_HANDLE_VALUE) { GetConsoleScreenBufferInfo(con, &con_info); attr_orig = con_info.wAttributes; background = attr_orig & 0xF0; } +#endif + + if (getenv("AV_LOG_FORCE_NOCOLOR")) { + use_color = 0; + } else if (getenv("AV_LOG_FORCE_COLOR")) { + use_color = 1; + } else { +#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE + use_color = (con != INVALID_HANDLE_VALUE); #elif HAVE_ISATTY - char *term = getenv("TERM"); - use_color = !getenv("NO_COLOR") && !getenv("AV_LOG_FORCE_NOCOLOR") && - (getenv("TERM") && isatty(2) || getenv("AV_LOG_FORCE_COLOR")); - if ( getenv("AV_LOG_FORCE_256COLOR") - || (term && strstr(term, "256color"))) - use_color *= 256; + use_color = (term && isatty(2)); #else - use_color = getenv("AV_LOG_FORCE_COLOR") && !getenv("NO_COLOR") && - !getenv("AV_LOG_FORCE_NOCOLOR"); + use_color = 0; #endif + } + + if (getenv("AV_LOG_FORCE_256COLOR") || term && strstr(term, "256color")) + use_color *= 256; } -static void colored_fputs(int level, int tint, const char *str) +static void ansi_fputs(int level, int tint, const char *str, int local_use_color) { - int local_use_color; - if (!*str) - return; - - if (use_color < 0) - check_color_terminal(); - - if (level == AV_LOG_INFO/8) local_use_color = 0; - else local_use_color = use_color; - -#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE - if (local_use_color) - SetConsoleTextAttribute(con, background | color[level]); - fputs(str, stderr); - if (local_use_color) - SetConsoleTextAttribute(con, attr_orig); -#else if (local_use_color == 1) { fprintf(stderr, "\033[%"PRIu32";3%"PRIu32"m%s\033[0m", @@ -184,6 +202,32 @@ str); } else fputs(str, stderr); +} + +static void colored_fputs(int level, int tint, const char *str) +{ + int local_use_color; + if (!*str) + return; + + if (use_color < 0) + check_color_terminal(); + + if (level == AV_LOG_INFO/8) local_use_color = 0; + else local_use_color = use_color; + +#if defined(_WIN32) && HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE + if (con != INVALID_HANDLE_VALUE) { + if (local_use_color) + SetConsoleTextAttribute(con, background | color[level]); + win_console_puts(str); + if (local_use_color) + SetConsoleTextAttribute(con, attr_orig); + } else { + ansi_fputs(level, tint, str, local_use_color); + } +#else + ansi_fputs(level, tint, str, local_use_color); #endif } @@ -226,6 +270,8 @@ return "quiet"; case AV_LOG_DEBUG: return "debug"; + case AV_LOG_TRACE: + return "trace"; case AV_LOG_VERBOSE: return "verbose"; case AV_LOG_INFO: @@ -360,19 +406,28 @@ void av_log(void* avcl, int level, const char *fmt, ...) { - AVClass* avc = avcl ? *(AVClass **) avcl : NULL; va_list vl; va_start(vl, fmt); - if (avc && avc->version >= (50 << 16 | 15 << 8 | 2) && - avc->log_level_offset_offset && level >= AV_LOG_FATAL) - level += *(int *) (((uint8_t *) avcl) + avc->log_level_offset_offset); av_vlog(avcl, level, fmt, vl); va_end(vl); } +void av_log_once(void* avcl, int initial_level, int subsequent_level, int *state, const char *fmt, ...) +{ + va_list vl; + va_start(vl, fmt); + av_vlog(avcl, *state ? subsequent_level : initial_level, fmt, vl); + va_end(vl); + *state = 1; +} + void av_vlog(void* avcl, int level, const char *fmt, va_list vl) { + AVClass* avc = avcl ? *(AVClass **) avcl : NULL; void (*log_callback)(void*, int, const char*, va_list) = av_log_callback; + if (avc && avc->version >= (50 << 16 | 15 << 8 | 2) && + avc->log_level_offset_offset && level >= AV_LOG_FATAL) + level += *(int *) (((uint8_t *) avcl) + avc->log_level_offset_offset); if (log_callback) log_callback(avcl, level, fmt, vl); } @@ -412,7 +467,7 @@ "been implemented.\n"); if (sample) av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample " - "of this file to ftp://upload.ffmpeg.org/incoming/ " + "of this file to https://streams.videolan.org/upload/ " "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)\n"); } diff -Nru ffmpeg-4.2.2/libavutil/log.h ffmpeg-4.4/libavutil/log.h --- ffmpeg-4.2.2/libavutil/log.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/log.h 2021-04-08 21:28:40.000000000 +0000 @@ -112,6 +112,7 @@ */ void* (*child_next)(void *obj, void *prev); +#if FF_API_CHILD_CLASS_NEXT /** * Return an AVClass corresponding to the next potential * AVOptions-enabled child. @@ -120,7 +121,9 @@ * child_next iterates over _already existing_ objects, while * child_class_next iterates over _all possible_ children. */ + attribute_deprecated const struct AVClass* (*child_class_next)(const struct AVClass *prev); +#endif /** * Category used for visualization (like color) @@ -140,6 +143,21 @@ * available since version (52.12) */ int (*query_ranges)(struct AVOptionRanges **, void *obj, const char *key, int flags); + + /** + * Iterate over the AVClasses corresponding to potential AVOptions-enabled + * children. + * + * @param iter pointer to opaque iteration state. The caller must initialize + * *iter to NULL before the first call. + * @return AVClass for the next AVOptions-enabled child or NULL if there are + * no more such children. + * + * @note The difference between child_next and this is that child_next + * iterates over _already existing_ objects, while child_class_iterate + * iterates over _all possible_ children. + */ + const struct AVClass* (*child_class_iterate)(void **iter); } AVClass; /** @@ -233,6 +251,27 @@ */ void av_log(void *avcl, int level, const char *fmt, ...) av_printf_format(3, 4); +/** + * Send the specified message to the log once with the initial_level and then with + * the subsequent_level. By default, all logging messages are sent to + * stderr. This behavior can be altered by setting a different logging callback + * function. + * @see av_log + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct or NULL if general log. + * @param initial_level importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant" for the first occurance. + * @param subsequent_level importance level of the message expressed using a @ref + * lavu_log_constants "Logging Constant" after the first occurance. + * @param fmt The format string (printf-compatible) that specifies how + * subsequent arguments are converted to output. + * @param state a variable to keep trak of if a message has already been printed + * this must be initialized to 0 before the first use. The same state + * must not be accessed by 2 Threads simultaneously. + */ +void av_log_once(void* avcl, int initial_level, int subsequent_level, int *state, const char *fmt, ...) av_printf_format(5, 6); + /** * Send the specified message to the log if the level is less than or equal diff -Nru ffmpeg-4.2.2/libavutil/Makefile ffmpeg-4.4/libavutil/Makefile --- ffmpeg-4.2.2/libavutil/Makefile 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/Makefile 2021-04-08 21:28:40.000000000 +0000 @@ -23,6 +23,7 @@ des.h \ dict.h \ display.h \ + dovi_meta.h \ downmix_info.h \ encryption_info.h \ error.h \ @@ -40,9 +41,11 @@ hwcontext_dxva2.h \ hwcontext_qsv.h \ hwcontext_mediacodec.h \ + hwcontext_opencl.h \ hwcontext_vaapi.h \ hwcontext_videotoolbox.h \ hwcontext_vdpau.h \ + hwcontext_vulkan.h \ imgutils.h \ intfloat.h \ intreadwrite.h \ @@ -77,9 +80,11 @@ tree.h \ twofish.h \ version.h \ + video_enc_params.h \ xtea.h \ tea.h \ tx.h \ + film_grain_params.h \ HEADERS-$(CONFIG_LZO) += lzo.h @@ -110,6 +115,7 @@ des.o \ dict.o \ display.o \ + dovi_meta.o \ downmix_info.o \ encryption_info.o \ error.o \ @@ -161,6 +167,12 @@ xtea.o \ tea.o \ tx.o \ + tx_float.o \ + tx_double.o \ + tx_int32.o \ + video_enc_params.o \ + film_grain_params.o \ + OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o @@ -173,6 +185,7 @@ OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o +OBJS-$(CONFIG_VULKAN) += hwcontext_vulkan.o OBJS += $(COMPAT_OBJS:%=../compat/%) @@ -189,6 +202,7 @@ SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.h SKIPHEADERS-$(CONFIG_VDPAU) += hwcontext_vdpau.h +SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h TESTPROGS = adler32 \ aes \ diff -Nru ffmpeg-4.2.2/libavutil/mathematics.c ffmpeg-4.4/libavutil/mathematics.c --- ffmpeg-4.2.2/libavutil/mathematics.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/mathematics.c 2021-04-08 21:28:40.000000000 +0000 @@ -148,7 +148,7 @@ { int64_t a = tb_a.num * (int64_t)tb_b.den; int64_t b = tb_b.num * (int64_t)tb_a.den; - if ((FFABS(ts_a)|a|FFABS(ts_b)|b) <= INT_MAX) + if ((FFABS64U(ts_a)|a|FFABS64U(ts_b)|b) <= INT_MAX) return (ts_a*a > ts_b*b) - (ts_a*a < ts_b*b); if (av_rescale_rnd(ts_a, a, b, AV_ROUND_DOWN) < ts_b) return -1; @@ -198,7 +198,7 @@ m = inc_tb.num * (int64_t)ts_tb.den; d = inc_tb.den * (int64_t)ts_tb.num; - if (m % d == 0) + if (m % d == 0 && ts <= INT64_MAX - m / d) return ts + m / d; if (m < d) return ts; @@ -206,6 +206,10 @@ { int64_t old = av_rescale_q(ts, ts_tb, inc_tb); int64_t old_ts = av_rescale_q(old, inc_tb, ts_tb); - return av_rescale_q(old + 1, inc_tb, ts_tb) + (ts - old_ts); + + if (old == INT64_MAX || old == AV_NOPTS_VALUE || old_ts == AV_NOPTS_VALUE) + return ts; + + return av_sat_add64(av_rescale_q(old + 1, inc_tb, ts_tb), ts - old_ts); } } diff -Nru ffmpeg-4.2.2/libavutil/mem.c ffmpeg-4.4/libavutil/mem.c --- ffmpeg-4.2.2/libavutil/mem.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/mem.c 2020-07-11 10:39:30.000000000 +0000 @@ -78,8 +78,7 @@ { void *ptr = NULL; - /* let's disallow possibly ambiguous cases */ - if (size > (max_alloc_size - 32)) + if (size > max_alloc_size) return NULL; #if HAVE_POSIX_MEMALIGN @@ -134,8 +133,7 @@ void *av_realloc(void *ptr, size_t size) { - /* let's disallow possibly ambiguous cases */ - if (size > (max_alloc_size - 32)) + if (size > max_alloc_size) return NULL; #if HAVE_ALIGNED_MALLOC @@ -183,23 +181,26 @@ void *av_malloc_array(size_t nmemb, size_t size) { - if (!size || nmemb >= INT_MAX / size) + size_t result; + if (av_size_mult(nmemb, size, &result) < 0) return NULL; - return av_malloc(nmemb * size); + return av_malloc(result); } void *av_mallocz_array(size_t nmemb, size_t size) { - if (!size || nmemb >= INT_MAX / size) + size_t result; + if (av_size_mult(nmemb, size, &result) < 0) return NULL; - return av_mallocz(nmemb * size); + return av_mallocz(result); } void *av_realloc_array(void *ptr, size_t nmemb, size_t size) { - if (!size || nmemb >= INT_MAX / size) + size_t result; + if (av_size_mult(nmemb, size, &result) < 0) return NULL; - return av_realloc(ptr, nmemb * size); + return av_realloc(ptr, result); } int av_reallocp_array(void *ptr, size_t nmemb, size_t size) @@ -243,9 +244,10 @@ void *av_calloc(size_t nmemb, size_t size) { - if (size <= 0 || nmemb >= INT_MAX / size) + size_t result; + if (av_size_mult(nmemb, size, &result) < 0) return NULL; - return av_mallocz(nmemb * size); + return av_mallocz(result); } char *av_strdup(const char *s) @@ -478,12 +480,12 @@ if (min_size <= *size) return ptr; - if (min_size > max_alloc_size - 32) { + if (min_size > max_alloc_size) { *size = 0; return NULL; } - min_size = FFMIN(max_alloc_size - 32, FFMAX(min_size + min_size / 16 + 32, min_size)); + min_size = FFMIN(max_alloc_size, FFMAX(min_size + min_size / 16 + 32, min_size)); ptr = av_realloc(ptr, min_size); /* we could set this to the unmodified min_size but this is safer diff -Nru ffmpeg-4.2.2/libavutil/mem.h ffmpeg-4.4/libavutil/mem.h --- ffmpeg-4.2.2/libavutil/mem.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/mem.h 2021-04-08 21:28:40.000000000 +0000 @@ -33,6 +33,7 @@ #include "attributes.h" #include "error.h" #include "avutil.h" +#include "version.h" /** * @addtogroup lavu_mem @@ -49,6 +50,10 @@ * dealing with memory consistently possible on all platforms. * * @{ + */ + +#if FF_API_DECLARE_ALIGNED +/** * * @defgroup lavu_mem_macros Alignment Macros * Helper macros for declaring aligned variables. @@ -125,6 +130,7 @@ /** * @} */ +#endif /** * @defgroup lavu_mem_attrs Function Attributes diff -Nru ffmpeg-4.2.2/libavutil/mem_internal.h ffmpeg-4.4/libavutil/mem_internal.h --- ffmpeg-4.2.2/libavutil/mem_internal.h 2017-12-31 22:35:49.000000000 +0000 +++ ffmpeg-4.4/libavutil/mem_internal.h 2021-04-08 21:28:40.000000000 +0000 @@ -21,8 +21,120 @@ #ifndef AVUTIL_MEM_INTERNAL_H #define AVUTIL_MEM_INTERNAL_H +#include "config.h" + +#include + #include "avassert.h" #include "mem.h" +#include "version.h" + +#if !FF_API_DECLARE_ALIGNED +/** + * @def DECLARE_ALIGNED(n,t,v) + * Declare a variable that is aligned in memory. + * + * @code{.c} + * DECLARE_ALIGNED(16, uint16_t, aligned_int) = 42; + * DECLARE_ALIGNED(32, uint8_t, aligned_array)[128]; + * + * // The default-alignment equivalent would be + * uint16_t aligned_int = 42; + * uint8_t aligned_array[128]; + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + +/** + * @def DECLARE_ASM_ALIGNED(n,t,v) + * Declare an aligned variable appropriate for use in inline assembly code. + * + * @code{.c} + * DECLARE_ASM_ALIGNED(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008); + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + +/** + * @def DECLARE_ASM_CONST(n,t,v) + * Declare a static constant aligned variable appropriate for use in inline + * assembly code. + * + * @code{.c} + * DECLARE_ASM_CONST(16, uint64_t, pw_08) = UINT64_C(0x0008000800080008); + * @endcode + * + * @param n Minimum alignment in bytes + * @param t Type of the variable (or array element) + * @param v Name of the variable + */ + +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v +#elif defined(__DJGPP__) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (FFMIN(n, 16)))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v + #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (FFMIN(n, 16)))) v +#elif defined(__GNUC__) || defined(__clang__) + #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v + #define DECLARE_ASM_ALIGNED(n,t,v) t av_used __attribute__ ((aligned (n))) v + #define DECLARE_ASM_CONST(n,t,v) static const t av_used __attribute__ ((aligned (n))) v +#elif defined(_MSC_VER) + #define DECLARE_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_ALIGNED(n,t,v) __declspec(align(n)) t v + #define DECLARE_ASM_CONST(n,t,v) __declspec(align(n)) static const t v +#else + #define DECLARE_ALIGNED(n,t,v) t v + #define DECLARE_ASM_ALIGNED(n,t,v) t v + #define DECLARE_ASM_CONST(n,t,v) static const t v +#endif +#endif + +// Some broken preprocessors need a second expansion +// to be forced to tokenize __VA_ARGS__ +#define E1(x) x + +#define LOCAL_ALIGNED_A(a, t, v, s, o, ...) \ + uint8_t la_##v[sizeof(t s o) + (a)]; \ + t (*v) o = (void *)FFALIGN((uintptr_t)la_##v, a) + +#define LOCAL_ALIGNED_D(a, t, v, s, o, ...) \ + DECLARE_ALIGNED(a, t, la_##v) s o; \ + t (*v) o = la_##v + +#define LOCAL_ALIGNED(a, t, v, ...) LOCAL_ALIGNED_##a(t, v, __VA_ARGS__) + +#if HAVE_LOCAL_ALIGNED +# define LOCAL_ALIGNED_4(t, v, ...) E1(LOCAL_ALIGNED_D(4, t, v, __VA_ARGS__,,)) +#else +# define LOCAL_ALIGNED_4(t, v, ...) E1(LOCAL_ALIGNED_A(4, t, v, __VA_ARGS__,,)) +#endif + +#if HAVE_LOCAL_ALIGNED +# define LOCAL_ALIGNED_8(t, v, ...) E1(LOCAL_ALIGNED_D(8, t, v, __VA_ARGS__,,)) +#else +# define LOCAL_ALIGNED_8(t, v, ...) E1(LOCAL_ALIGNED_A(8, t, v, __VA_ARGS__,,)) +#endif + +#if HAVE_LOCAL_ALIGNED +# define LOCAL_ALIGNED_16(t, v, ...) E1(LOCAL_ALIGNED_D(16, t, v, __VA_ARGS__,,)) +#else +# define LOCAL_ALIGNED_16(t, v, ...) E1(LOCAL_ALIGNED_A(16, t, v, __VA_ARGS__,,)) +#endif + +#if HAVE_LOCAL_ALIGNED +# define LOCAL_ALIGNED_32(t, v, ...) E1(LOCAL_ALIGNED_D(32, t, v, __VA_ARGS__,,)) +#else +# define LOCAL_ALIGNED_32(t, v, ...) E1(LOCAL_ALIGNED_A(32, t, v, __VA_ARGS__,,)) +#endif static inline int ff_fast_malloc(void *ptr, unsigned int *size, size_t min_size, int zero_realloc) { diff -Nru ffmpeg-4.2.2/libavutil/mips/asmdefs.h ffmpeg-4.4/libavutil/mips/asmdefs.h --- ffmpeg-4.2.2/libavutil/mips/asmdefs.h 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libavutil/mips/asmdefs.h 2021-04-08 21:28:40.000000000 +0000 @@ -55,4 +55,46 @@ # define PTR_SLL "sll " #endif +/* + * parse_r var, r - Helper assembler macro for parsing register names. + * + * This converts the register name in $n form provided in \r to the + * corresponding register number, which is assigned to the variable \var. It is + * needed to allow explicit encoding of instructions in inline assembly where + * registers are chosen by the compiler in $n form, allowing us to avoid using + * fixed register numbers. + * + * It also allows newer instructions (not implemented by the assembler) to be + * transparently implemented using assembler macros, instead of needing separate + * cases depending on toolchain support. + * + * Simple usage example: + * __asm__ __volatile__("parse_r __rt, %0\n\t" + * ".insn\n\t" + * "# di %0\n\t" + * ".word (0x41606000 | (__rt << 16))" + * : "=r" (status); + */ + +/* Match an individual register number and assign to \var */ +#define _IFC_REG(n) \ + ".ifc \\r, $" #n "\n\t" \ + "\\var = " #n "\n\t" \ + ".endif\n\t" + +__asm__(".macro parse_r var r\n\t" + "\\var = -1\n\t" + _IFC_REG(0) _IFC_REG(1) _IFC_REG(2) _IFC_REG(3) + _IFC_REG(4) _IFC_REG(5) _IFC_REG(6) _IFC_REG(7) + _IFC_REG(8) _IFC_REG(9) _IFC_REG(10) _IFC_REG(11) + _IFC_REG(12) _IFC_REG(13) _IFC_REG(14) _IFC_REG(15) + _IFC_REG(16) _IFC_REG(17) _IFC_REG(18) _IFC_REG(19) + _IFC_REG(20) _IFC_REG(21) _IFC_REG(22) _IFC_REG(23) + _IFC_REG(24) _IFC_REG(25) _IFC_REG(26) _IFC_REG(27) + _IFC_REG(28) _IFC_REG(29) _IFC_REG(30) _IFC_REG(31) + ".iflt \\var\n\t" + ".error \"Unable to parse register name \\r\"\n\t" + ".endif\n\t" + ".endm"); + #endif /* AVCODEC_MIPS_ASMDEFS_H */ diff -Nru ffmpeg-4.2.2/libavutil/mips/cpu.c ffmpeg-4.4/libavutil/mips/cpu.c --- ffmpeg-4.2.2/libavutil/mips/cpu.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/mips/cpu.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,134 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/cpu.h" +#include "libavutil/cpu_internal.h" +#include "config.h" +#if defined __linux__ || defined __ANDROID__ +#include +#include +#include +#include +#include "asmdefs.h" +#include "libavutil/avstring.h" +#endif + +#if defined __linux__ || defined __ANDROID__ + +#define HWCAP_LOONGSON_CPUCFG (1 << 14) + +static int cpucfg_available(void) +{ + return getauxval(AT_HWCAP) & HWCAP_LOONGSON_CPUCFG; +} + +/* Most toolchains have no CPUCFG support yet */ +static uint32_t read_cpucfg(uint32_t reg) +{ + uint32_t __res; + + __asm__ __volatile__( + "parse_r __res,%0\n\t" + "parse_r reg,%1\n\t" + ".insn \n\t" + ".word (0xc8080118 | (reg << 21) | (__res << 11))\n\t" + :"=r"(__res) + :"r"(reg) + : + ); + return __res; +} + +#define LOONGSON_CFG1 0x1 + +#define LOONGSON_CFG1_MMI (1 << 4) +#define LOONGSON_CFG1_MSA1 (1 << 5) + +static int cpu_flags_cpucfg(void) +{ + int flags = 0; + uint32_t cfg1 = read_cpucfg(LOONGSON_CFG1); + + if (cfg1 & LOONGSON_CFG1_MMI) + flags |= AV_CPU_FLAG_MMI; + + if (cfg1 & LOONGSON_CFG1_MSA1) + flags |= AV_CPU_FLAG_MSA; + + return flags; +} + +static int cpu_flags_cpuinfo(void) +{ + FILE *f = fopen("/proc/cpuinfo", "r"); + char buf[200]; + int flags = 0; + + if (!f) + return -1; + + while (fgets(buf, sizeof(buf), f)) { + /* Legacy kernel may not export MMI in ASEs implemented */ + if (av_strstart(buf, "cpu model", NULL)) { + if (strstr(buf, "Loongson-3 ")) + flags |= AV_CPU_FLAG_MMI; + } + + if (av_strstart(buf, "ASEs implemented", NULL)) { + if (strstr(buf, " loongson-mmi")) + flags |= AV_CPU_FLAG_MMI; + if (strstr(buf, " msa")) + flags |= AV_CPU_FLAG_MSA; + + break; + } + } + fclose(f); + return flags; +} +#endif + +int ff_get_cpu_flags_mips(void) +{ +#if defined __linux__ || defined __ANDROID__ + if (cpucfg_available()) + return cpu_flags_cpucfg(); + else + return cpu_flags_cpuinfo(); +#else + /* Assume no SIMD ASE supported */ + return 0; +#endif +} + +size_t ff_get_cpu_max_align_mips(void) +{ + int flags = av_get_cpu_flags(); + + if (flags & AV_CPU_FLAG_MSA) + return 16; + + /* + * MMI itself is 64-bit but quad word load & store + * needs 128-bit align. + */ + if (flags & AV_CPU_FLAG_MMI) + return 16; + + return 8; +} diff -Nru ffmpeg-4.2.2/libavutil/mips/cpu.h ffmpeg-4.4/libavutil/mips/cpu.h --- ffmpeg-4.2.2/libavutil/mips/cpu.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/mips/cpu.h 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,28 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_MIPS_CPU_H +#define AVUTIL_MIPS_CPU_H + +#include "libavutil/cpu.h" +#include "libavutil/cpu_internal.h" + +#define have_mmi(flags) CPUEXT(flags, MMI) +#define have_msa(flags) CPUEXT(flags, MSA) + +#endif /* AVUTIL_MIPS_CPU_H */ diff -Nru ffmpeg-4.2.2/libavutil/mips/generic_macros_msa.h ffmpeg-4.4/libavutil/mips/generic_macros_msa.h --- ffmpeg-4.2.2/libavutil/mips/generic_macros_msa.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/mips/generic_macros_msa.h 2021-04-08 21:28:40.000000000 +0000 @@ -111,10 +111,11 @@ uint32_t val_lw_m; \ \ __asm__ volatile ( \ - "ulw %[val_lw_m], %[psrc_lw_m] \n\t" \ + "lwr %[val_lw_m], 0(%[psrc_lw_m]) \n\t" \ + "lwl %[val_lw_m], 3(%[psrc_lw_m]) \n\t" \ \ - : [val_lw_m] "=r" (val_lw_m) \ - : [psrc_lw_m] "m" (*psrc_lw_m) \ + : [val_lw_m] "=&r"(val_lw_m) \ + : [psrc_lw_m] "r"(psrc_lw_m) \ ); \ \ val_lw_m; \ @@ -127,10 +128,11 @@ uint64_t val_ld_m = 0; \ \ __asm__ volatile ( \ - "uld %[val_ld_m], %[psrc_ld_m] \n\t" \ + "ldr %[val_ld_m], 0(%[psrc_ld_m]) \n\t" \ + "ldl %[val_ld_m], 7(%[psrc_ld_m]) \n\t" \ \ - : [val_ld_m] "=r" (val_ld_m) \ - : [psrc_ld_m] "m" (*psrc_ld_m) \ + : [val_ld_m] "=&r" (val_ld_m) \ + : [psrc_ld_m] "r" (psrc_ld_m) \ ); \ \ val_ld_m; \ @@ -299,6 +301,7 @@ #define LD_SB4(...) LD_V4(v16i8, __VA_ARGS__) #define LD_UH4(...) LD_V4(v8u16, __VA_ARGS__) #define LD_SH4(...) LD_V4(v8i16, __VA_ARGS__) +#define LD_SW4(...) LD_V4(v4i32, __VA_ARGS__) #define LD_V5(RTYPE, psrc, stride, out0, out1, out2, out3, out4) \ { \ @@ -337,6 +340,7 @@ #define LD_SB8(...) LD_V8(v16i8, __VA_ARGS__) #define LD_UH8(...) LD_V8(v8u16, __VA_ARGS__) #define LD_SH8(...) LD_V8(v8i16, __VA_ARGS__) +#define LD_SW8(...) LD_V8(v4i32, __VA_ARGS__) #define LD_V16(RTYPE, psrc, stride, \ out0, out1, out2, out3, out4, out5, out6, out7, \ @@ -602,67 +606,48 @@ } #define AVER_UB4_UB(...) AVER_UB4(v16u8, __VA_ARGS__) -/* Description : Immediate number of columns to slide with zero - Arguments : Inputs - in0, in1, slide_val - Outputs - out0, out1 +/* Description : Immediate number of columns to slide + Arguments : Inputs - s, d, slide_val + Outputs - out Return Type - as per RTYPE - Details : Byte elements from 'zero_m' vector are slide into 'in0' by + Details : Byte elements from 'd' vector are slide into 's' by number of elements specified by 'slide_val' */ -#define SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val) \ -{ \ - v16i8 zero_m = { 0 }; \ - out0 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in0, slide_val); \ - out1 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in1, slide_val); \ -} -#define SLDI_B2_0_UB(...) SLDI_B2_0(v16u8, __VA_ARGS__) -#define SLDI_B2_0_SB(...) SLDI_B2_0(v16i8, __VA_ARGS__) -#define SLDI_B2_0_SW(...) SLDI_B2_0(v4i32, __VA_ARGS__) - -#define SLDI_B3_0(RTYPE, in0, in1, in2, out0, out1, out2, slide_val) \ -{ \ - v16i8 zero_m = { 0 }; \ - SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val); \ - out2 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in2, slide_val); \ -} -#define SLDI_B3_0_UB(...) SLDI_B3_0(v16u8, __VA_ARGS__) -#define SLDI_B3_0_SB(...) SLDI_B3_0(v16i8, __VA_ARGS__) - -#define SLDI_B4_0(RTYPE, in0, in1, in2, in3, \ - out0, out1, out2, out3, slide_val) \ -{ \ - SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val); \ - SLDI_B2_0(RTYPE, in2, in3, out2, out3, slide_val); \ +#define SLDI_B(RTYPE, d, s, slide_val, out) \ +{ \ + out = (RTYPE) __msa_sldi_b((v16i8) d, (v16i8) s, slide_val); \ } -#define SLDI_B4_0_UB(...) SLDI_B4_0(v16u8, __VA_ARGS__) -#define SLDI_B4_0_SB(...) SLDI_B4_0(v16i8, __VA_ARGS__) -#define SLDI_B4_0_SH(...) SLDI_B4_0(v8i16, __VA_ARGS__) -/* Description : Immediate number of columns to slide - Arguments : Inputs - in0_0, in0_1, in1_0, in1_1, slide_val - Outputs - out0, out1 - Return Type - as per RTYPE - Details : Byte elements from 'in0_0' vector are slide into 'in1_0' by - number of elements specified by 'slide_val' -*/ -#define SLDI_B2(RTYPE, in0_0, in0_1, in1_0, in1_1, out0, out1, slide_val) \ -{ \ - out0 = (RTYPE) __msa_sldi_b((v16i8) in0_0, (v16i8) in1_0, slide_val); \ - out1 = (RTYPE) __msa_sldi_b((v16i8) in0_1, (v16i8) in1_1, slide_val); \ +#define SLDI_B2(RTYPE, d0, s0, d1, s1, slide_val, out0, out1) \ +{ \ + SLDI_B(RTYPE, d0, s0, slide_val, out0) \ + SLDI_B(RTYPE, d1, s1, slide_val, out1) \ } #define SLDI_B2_UB(...) SLDI_B2(v16u8, __VA_ARGS__) #define SLDI_B2_SB(...) SLDI_B2(v16i8, __VA_ARGS__) #define SLDI_B2_SH(...) SLDI_B2(v8i16, __VA_ARGS__) +#define SLDI_B2_SW(...) SLDI_B2(v4i32, __VA_ARGS__) -#define SLDI_B3(RTYPE, in0_0, in0_1, in0_2, in1_0, in1_1, in1_2, \ - out0, out1, out2, slide_val) \ -{ \ - SLDI_B2(RTYPE, in0_0, in0_1, in1_0, in1_1, out0, out1, slide_val) \ - out2 = (RTYPE) __msa_sldi_b((v16i8) in0_2, (v16i8) in1_2, slide_val); \ +#define SLDI_B3(RTYPE, d0, s0, d1, s1, d2, s2, slide_val, \ + out0, out1, out2) \ +{ \ + SLDI_B2(RTYPE, d0, s0, d1, s1, slide_val, out0, out1) \ + SLDI_B(RTYPE, d2, s2, slide_val, out2) \ } +#define SLDI_B3_UB(...) SLDI_B3(v16u8, __VA_ARGS__) #define SLDI_B3_SB(...) SLDI_B3(v16i8, __VA_ARGS__) #define SLDI_B3_UH(...) SLDI_B3(v8u16, __VA_ARGS__) +#define SLDI_B4(RTYPE, d0, s0, d1, s1, d2, s2, d3, s3, \ + slide_val, out0, out1, out2, out3) \ +{ \ + SLDI_B2(RTYPE, d0, s0, d1, s1, slide_val, out0, out1) \ + SLDI_B2(RTYPE, d2, s2, d3, s3, slide_val, out2, out3) \ +} +#define SLDI_B4_UB(...) SLDI_B4(v16u8, __VA_ARGS__) +#define SLDI_B4_SB(...) SLDI_B4(v16i8, __VA_ARGS__) +#define SLDI_B4_SH(...) SLDI_B4(v8i16, __VA_ARGS__) + /* Description : Shuffle byte vector elements as per mask vector Arguments : Inputs - in0, in1, in2, in3, mask0, mask1 Outputs - out0, out1 @@ -933,99 +918,78 @@ /* Description : Clips 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_m (output vector with clipped elements) + Arguments : Inputs - in (input vector) + - min (min threshold) + - max (max threshold) + Outputs - in (output vector with clipped elements) Return Type - signed halfword */ -#define CLIP_SH(in, min, max) \ -( { \ - v8i16 out_m; \ - \ - out_m = __msa_max_s_h((v8i16) min, (v8i16) in); \ - out_m = __msa_min_s_h((v8i16) max, (v8i16) out_m); \ - out_m; \ -} ) +#define CLIP_SH(in, min, max) \ +{ \ + in = __msa_max_s_h((v8i16) min, (v8i16) in); \ + in = __msa_min_s_h((v8i16) max, (v8i16) in); \ +} /* Description : Clips all signed halfword elements of input vector between 0 & 255 - Arguments : Inputs - in (input vector) - Outputs - out_m (output vector with clipped elements) - Return Type - signed halfword + Arguments : Inputs - in (input vector) + Outputs - in (output vector with clipped elements) + Return Type - signed halfwords */ -#define CLIP_SH_0_255(in) \ -( { \ - v8i16 max_m = __msa_ldi_h(255); \ - v8i16 out_m; \ - \ - out_m = __msa_maxi_s_h((v8i16) in, 0); \ - out_m = __msa_min_s_h((v8i16) max_m, (v8i16) out_m); \ - out_m; \ -} ) +#define CLIP_SH_0_255(in) \ +{ \ + in = __msa_maxi_s_h((v8i16) in, 0); \ + in = (v8i16) __msa_sat_u_h((v8u16) in, 7); \ +} + #define CLIP_SH2_0_255(in0, in1) \ { \ - in0 = CLIP_SH_0_255(in0); \ - in1 = CLIP_SH_0_255(in1); \ + CLIP_SH_0_255(in0); \ + CLIP_SH_0_255(in1); \ } + #define CLIP_SH4_0_255(in0, in1, in2, in3) \ { \ CLIP_SH2_0_255(in0, in1); \ CLIP_SH2_0_255(in2, in3); \ } -#define CLIP_SH_0_255_MAX_SATU(in) \ -( { \ - v8i16 out_m; \ - \ - out_m = __msa_maxi_s_h((v8i16) in, 0); \ - out_m = (v8i16) __msa_sat_u_h((v8u16) out_m, 7); \ - out_m; \ -} ) -#define CLIP_SH2_0_255_MAX_SATU(in0, in1) \ -{ \ - in0 = CLIP_SH_0_255_MAX_SATU(in0); \ - in1 = CLIP_SH_0_255_MAX_SATU(in1); \ -} -#define CLIP_SH4_0_255_MAX_SATU(in0, in1, in2, in3) \ -{ \ - CLIP_SH2_0_255_MAX_SATU(in0, in1); \ - CLIP_SH2_0_255_MAX_SATU(in2, in3); \ +#define CLIP_SH8_0_255(in0, in1, in2, in3, \ + in4, in5, in6, in7) \ +{ \ + CLIP_SH4_0_255(in0, in1, in2, in3); \ + CLIP_SH4_0_255(in4, in5, in6, in7); \ } /* Description : Clips all signed word elements of input vector between 0 & 255 - Arguments : Inputs - in (input vector) - Outputs - out_m (output vector with clipped elements) + Arguments : Inputs - in (input vector) + Outputs - in (output vector with clipped elements) Return Type - signed word */ -#define CLIP_SW_0_255(in) \ -( { \ - v4i32 max_m = __msa_ldi_w(255); \ - v4i32 out_m; \ - \ - out_m = __msa_maxi_s_w((v4i32) in, 0); \ - out_m = __msa_min_s_w((v4i32) max_m, (v4i32) out_m); \ - out_m; \ -} ) +#define CLIP_SW_0_255(in) \ +{ \ + in = __msa_maxi_s_w((v4i32) in, 0); \ + in = (v4i32) __msa_sat_u_w((v4u32) in, 7); \ +} -#define CLIP_SW_0_255_MAX_SATU(in) \ -( { \ - v4i32 out_m; \ - \ - out_m = __msa_maxi_s_w((v4i32) in, 0); \ - out_m = (v4i32) __msa_sat_u_w((v4u32) out_m, 7); \ - out_m; \ -} ) -#define CLIP_SW2_0_255_MAX_SATU(in0, in1) \ -{ \ - in0 = CLIP_SW_0_255_MAX_SATU(in0); \ - in1 = CLIP_SW_0_255_MAX_SATU(in1); \ +#define CLIP_SW2_0_255(in0, in1) \ +{ \ + CLIP_SW_0_255(in0); \ + CLIP_SW_0_255(in1); \ } -#define CLIP_SW4_0_255_MAX_SATU(in0, in1, in2, in3) \ -{ \ - CLIP_SW2_0_255_MAX_SATU(in0, in1); \ - CLIP_SW2_0_255_MAX_SATU(in2, in3); \ + +#define CLIP_SW4_0_255(in0, in1, in2, in3) \ +{ \ + CLIP_SW2_0_255(in0, in1); \ + CLIP_SW2_0_255(in2, in3); \ +} + +#define CLIP_SW8_0_255(in0, in1, in2, in3, \ + in4, in5, in6, in7) \ +{ \ + CLIP_SW4_0_255(in0, in1, in2, in3); \ + CLIP_SW4_0_255(in4, in5, in6, in7); \ } /* Description : Addition of 4 signed word elements @@ -1422,6 +1386,7 @@ out4, out5, out6, out7); \ } #define ILVR_B8_UH(...) ILVR_B8(v8u16, __VA_ARGS__) +#define ILVR_B8_SW(...) ILVR_B8(v4i32, __VA_ARGS__) /* Description : Interleave right half of halfword elements from vectors Arguments : Inputs - in0, in1, in2, in3, in4, in5, in6, in7 @@ -2433,6 +2398,7 @@ { \ v16i8 tmp0_m, tmp1_m, tmp2_m, tmp3_m; \ v16i8 tmp4_m, tmp5_m, tmp6_m, tmp7_m; \ + v16i8 zeros = { 0 }; \ \ ILVR_B4_SB(in2, in0, in3, in1, in6, in4, in7, in5, \ tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ @@ -2440,8 +2406,8 @@ ILVRL_B2_SB(tmp3_m, tmp2_m, tmp6_m, tmp7_m); \ ILVRL_W2(RTYPE, tmp6_m, tmp4_m, out0, out2); \ ILVRL_W2(RTYPE, tmp7_m, tmp5_m, out4, out6); \ - SLDI_B2_0(RTYPE, out0, out2, out1, out3, 8); \ - SLDI_B2_0(RTYPE, out4, out6, out5, out7, 8); \ + SLDI_B4(RTYPE, zeros, out0, zeros, out2, zeros, out4, zeros, out6, \ + 8, out1, out3, out5, out7); \ } #define TRANSPOSE8x8_UB_UB(...) TRANSPOSE8x8_UB(v16u8, __VA_ARGS__) #define TRANSPOSE8x8_UB_UH(...) TRANSPOSE8x8_UB(v8u16, __VA_ARGS__) @@ -2523,8 +2489,6 @@ out5 = (v16u8) __msa_ilvod_w((v4i32) tmp3_m, (v4i32) tmp2_m); \ \ tmp2_m = (v16u8) __msa_ilvod_h((v8i16) tmp5_m, (v8i16) tmp4_m); \ - tmp2_m = (v16u8) __msa_ilvod_h((v8i16) tmp5_m, (v8i16) tmp4_m); \ - tmp3_m = (v16u8) __msa_ilvod_h((v8i16) tmp7_m, (v8i16) tmp6_m); \ tmp3_m = (v16u8) __msa_ilvod_h((v8i16) tmp7_m, (v8i16) tmp6_m); \ out3 = (v16u8) __msa_ilvev_w((v4i32) tmp3_m, (v4i32) tmp2_m); \ out7 = (v16u8) __msa_ilvod_w((v4i32) tmp3_m, (v4i32) tmp2_m); \ diff -Nru ffmpeg-4.2.2/libavutil/mips/Makefile ffmpeg-4.4/libavutil/mips/Makefile --- ffmpeg-4.2.2/libavutil/mips/Makefile 2016-03-29 02:25:32.000000000 +0000 +++ ffmpeg-4.4/libavutil/mips/Makefile 2021-04-08 21:28:40.000000000 +0000 @@ -1 +1 @@ -OBJS += mips/float_dsp_mips.o +OBJS += mips/float_dsp_mips.o mips/cpu.o diff -Nru ffmpeg-4.2.2/libavutil/mips/mmiutils.h ffmpeg-4.4/libavutil/mips/mmiutils.h --- ffmpeg-4.2.2/libavutil/mips/mmiutils.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/mips/mmiutils.h 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,8 @@ #define AVUTIL_MIPS_MMIUTILS_H #include "config.h" + +#include "libavutil/mem_internal.h" #include "libavutil/mips/asmdefs.h" #if HAVE_LOONGSON2 @@ -205,7 +207,7 @@ * backup register */ #define BACKUP_REG \ - double temp_backup_reg[8]; \ + LOCAL_ALIGNED_16(double, temp_backup_reg, [8]); \ if (_MIPS_SIM == _ABI64) \ __asm__ volatile ( \ "gssqc1 $f25, $f24, 0x00(%[temp]) \n\t" \ diff -Nru ffmpeg-4.2.2/libavutil/murmur3.c ffmpeg-4.4/libavutil/murmur3.c --- ffmpeg-4.2.2/libavutil/murmur3.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/murmur3.c 2021-04-08 21:28:40.000000000 +0000 @@ -17,6 +17,8 @@ * 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 "mem.h" #include "intreadwrite.h" diff -Nru ffmpeg-4.2.2/libavutil/murmur3.h ffmpeg-4.4/libavutil/murmur3.h --- ffmpeg-4.2.2/libavutil/murmur3.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/murmur3.h 2021-04-08 21:28:40.000000000 +0000 @@ -27,6 +27,7 @@ #ifndef AVUTIL_MURMUR3_H #define AVUTIL_MURMUR3_H +#include #include #include "version.h" diff -Nru ffmpeg-4.2.2/libavutil/opt.c ffmpeg-4.4/libavutil/opt.c --- ffmpeg-4.2.2/libavutil/opt.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/opt.c 2021-04-08 21:28:40.000000000 +0000 @@ -229,13 +229,15 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, const char *val, void *dst) { int ret = 0; - int num, den; - char c; - if (sscanf(val, "%d%*1[:/]%d%c", &num, &den, &c) == 2) { - if ((ret = write_number(obj, o, dst, 1, den, num)) >= 0) - return ret; - ret = 0; + if (o->type == AV_OPT_TYPE_RATIONAL || o->type == AV_OPT_TYPE_VIDEO_RATE) { + int num, den; + char c; + if (sscanf(val, "%d%*1[:/]%d%c", &num, &den, &c) == 2) { + if ((ret = write_number(obj, o, dst, 1, den, num)) >= 0) + return ret; + ret = 0; + } } for (;;) { @@ -254,11 +256,12 @@ } { - const AVOption *o_named = av_opt_find(target_obj, i ? buf : val, o->unit, 0, 0); int res; int ci = 0; double const_values[64]; const char * const_names[64]; + int search_flags = (o->flags & AV_OPT_FLAG_CHILD_CONSTS) ? AV_OPT_SEARCH_CHILDREN : 0; + const AVOption *o_named = av_opt_find(target_obj, i ? buf : val, o->unit, 0, search_flags); if (o_named && o_named->type == AV_OPT_TYPE_CONST) d = DEFAULT_NUMVAL(o_named); else { @@ -330,12 +333,7 @@ static int set_string_video_rate(void *obj, const AVOption *o, const char *val, AVRational *dst) { - int ret; - if (!val) { - ret = AVERROR(EINVAL); - } else { - ret = av_parse_video_rate(dst, val); - } + int ret = av_parse_video_rate(dst, val); if (ret < 0) av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as video rate\n", val); return ret; @@ -446,6 +444,24 @@ AV_SAMPLE_FMT_NB, av_get_sample_fmt, "sample format"); } +static int set_string_dict(void *obj, const AVOption *o, const char *val, uint8_t **dst) +{ + AVDictionary *options = NULL; + + if (val) { + int ret = av_dict_parse_string(&options, val, "=", ":", 0); + if (ret < 0) { + av_dict_free(&options); + return ret; + } + } + + av_dict_free((AVDictionary **)dst); + *dst = (uint8_t *)options; + + return 0; +} + int av_opt_set(void *obj, const char *name, const char *val, int search_flags) { int ret = 0; @@ -455,7 +471,7 @@ return AVERROR_OPTION_NOT_FOUND; if (!val && (o->type != AV_OPT_TYPE_STRING && o->type != AV_OPT_TYPE_PIXEL_FMT && o->type != AV_OPT_TYPE_SAMPLE_FMT && - o->type != AV_OPT_TYPE_IMAGE_SIZE && o->type != AV_OPT_TYPE_VIDEO_RATE && + o->type != AV_OPT_TYPE_IMAGE_SIZE && o->type != AV_OPT_TYPE_DURATION && o->type != AV_OPT_TYPE_COLOR && o->type != AV_OPT_TYPE_CHANNEL_LAYOUT && o->type != AV_OPT_TYPE_BOOL)) return AVERROR(EINVAL); @@ -527,6 +543,8 @@ return ret; } break; + case AV_OPT_TYPE_DICT: + return set_string_dict(obj, o, val, dst); } av_log(obj, AV_LOG_ERROR, "Invalid option type.\n"); @@ -855,6 +873,12 @@ i64 = *(int64_t *)dst; ret = snprintf(buf, sizeof(buf), "0x%"PRIx64, i64); break; + case AV_OPT_TYPE_DICT: + if (!*(AVDictionary **)dst && (search_flags & AV_OPT_ALLOW_NULL)) { + *out_val = NULL; + return 0; + } + return av_dict_get_string(*(AVDictionary **)dst, (char **)out_val, '=', ':'); default: return AVERROR(EINVAL); } @@ -1034,6 +1058,23 @@ return res & flag->default_val.i64; } +static void log_int_value(void *av_log_obj, int level, int64_t i) +{ + if (i == INT_MAX) { + av_log(av_log_obj, level, "INT_MAX"); + } else if (i == INT_MIN) { + av_log(av_log_obj, level, "INT_MIN"); + } else if (i == UINT32_MAX) { + av_log(av_log_obj, level, "UINT32_MAX"); + } else if (i == INT64_MAX) { + av_log(av_log_obj, level, "I64_MAX"); + } else if (i == INT64_MIN) { + av_log(av_log_obj, level, "I64_MIN"); + } else { + av_log(av_log_obj, level, "%"PRId64, i); + } +} + static void log_value(void *av_log_obj, int level, double d) { if (d == INT_MAX) { @@ -1102,7 +1143,7 @@ } static void opt_list(void *obj, void *av_log_obj, const char *unit, - int req_flags, int rej_flags) + int req_flags, int rej_flags, enum AVOptionType parent_type) { const AVOption *opt = NULL; AVOptionRanges *r; @@ -1157,6 +1198,9 @@ case AV_OPT_TYPE_BINARY: av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); break; + case AV_OPT_TYPE_DICT: + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); + break; case AV_OPT_TYPE_IMAGE_SIZE: av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); break; @@ -1182,6 +1226,11 @@ av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); break; case AV_OPT_TYPE_CONST: + if (parent_type == AV_OPT_TYPE_INT) + av_log(av_log_obj, AV_LOG_INFO, "%-12"PRId64" ", opt->default_val.i64); + else + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); + break; default: av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); break; @@ -1195,6 +1244,8 @@ av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_EXPORT) ? 'X' : '.'); av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_READONLY) ? 'R' : '.'); av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_BSF_PARAM) ? 'B' : '.'); + av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_RUNTIME_PARAM) ? 'T' : '.'); + av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DEPRECATED) ? 'P' : '.'); if (opt->help) av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help); @@ -1224,6 +1275,7 @@ !((opt->type == AV_OPT_TYPE_COLOR || opt->type == AV_OPT_TYPE_IMAGE_SIZE || opt->type == AV_OPT_TYPE_STRING || + opt->type == AV_OPT_TYPE_DICT || opt->type == AV_OPT_TYPE_VIDEO_RATE) && !opt->default_val.str)) { av_log(av_log_obj, AV_LOG_INFO, " (default "); @@ -1254,7 +1306,7 @@ if (def_const) av_log(av_log_obj, AV_LOG_INFO, "%s", def_const); else - log_value(av_log_obj, AV_LOG_INFO, opt->default_val.i64); + log_int_value(av_log_obj, AV_LOG_INFO, opt->default_val.i64); break; } case AV_OPT_TYPE_DOUBLE: @@ -1274,6 +1326,7 @@ case AV_OPT_TYPE_COLOR: case AV_OPT_TYPE_IMAGE_SIZE: case AV_OPT_TYPE_STRING: + case AV_OPT_TYPE_DICT: case AV_OPT_TYPE_VIDEO_RATE: av_log(av_log_obj, AV_LOG_INFO, "\"%s\"", opt->default_val.str); break; @@ -1286,7 +1339,7 @@ av_log(av_log_obj, AV_LOG_INFO, "\n"); if (opt->unit && opt->type != AV_OPT_TYPE_CONST) - opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags); + opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags, opt->type); } } @@ -1297,7 +1350,7 @@ av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass **)obj)->class_name); - opt_list(obj, av_log_obj, NULL, req_flags, rej_flags); + opt_list(obj, av_log_obj, NULL, req_flags, rej_flags, -1); return 0; } @@ -1363,8 +1416,8 @@ set_string_binary(s, opt, opt->default_val.str, dst); break; case AV_OPT_TYPE_DICT: - /* Cannot set defaults for these types */ - break; + set_string_dict(s, opt, opt->default_val.str, dst); + break; default: av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name); @@ -1627,8 +1680,9 @@ if (search_flags & AV_OPT_SEARCH_CHILDREN) { if (search_flags & AV_OPT_SEARCH_FAKE_OBJ) { - const AVClass *child = NULL; - while (child = av_opt_child_class_next(c, child)) + void *iter = NULL; + const AVClass *child; + while (child = av_opt_child_class_iterate(c, &iter)) if (o = av_opt_find2(&child, name, unit, opt_flags, search_flags, NULL)) return o; } else { @@ -1663,12 +1717,31 @@ return NULL; } +#if FF_API_CHILD_CLASS_NEXT +FF_DISABLE_DEPRECATION_WARNINGS const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev) { if (parent->child_class_next) return parent->child_class_next(prev); return NULL; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + +const AVClass *av_opt_child_class_iterate(const AVClass *parent, void **iter) +{ + if (parent->child_class_iterate) + return parent->child_class_iterate(iter); +#if FF_API_CHILD_CLASS_NEXT +FF_DISABLE_DEPRECATION_WARNINGS + if (parent->child_class_next) { + *iter = parent->child_class_next(*iter); + return *iter; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + return NULL; +} void *av_opt_ptr(const AVClass *class, void *obj, const char *name) { @@ -1948,9 +2021,23 @@ av_free(tmp.data); return ret; } - case AV_OPT_TYPE_DICT: - /* Binary and dict have not default support yet. Any pointer is not default. */ - return !!(*(void **)dst); + case AV_OPT_TYPE_DICT: { + AVDictionary *dict1 = NULL; + AVDictionary *dict2 = *(AVDictionary **)dst; + AVDictionaryEntry *en1 = NULL; + AVDictionaryEntry *en2 = NULL; + ret = av_dict_parse_string(&dict1, o->default_val.str, "=", ":", 0); + if (ret < 0) { + av_dict_free(&dict1); + return ret; + } + do { + en1 = av_dict_get(dict1, "", en1, AV_DICT_IGNORE_SUFFIX); + en2 = av_dict_get(dict2, "", en2, AV_DICT_IGNORE_SUFFIX); + } while (en1 && en2 && !strcmp(en1->key, en2->key) && !strcmp(en1->value, en2->value)); + av_dict_free(&dict1); + return (!en1 && !en2); + } case AV_OPT_TYPE_IMAGE_SIZE: if (!o->default_val.str || !strcmp(o->default_val.str, "none")) w = h = 0; @@ -2034,6 +2121,8 @@ av_freep(&buf); } } - av_bprint_finalize(&bprint, buffer); + ret = av_bprint_finalize(&bprint, buffer); + if (ret < 0) + return ret; return 0; } diff -Nru ffmpeg-4.2.2/libavutil/opt.h ffmpeg-4.4/libavutil/opt.h --- ffmpeg-4.2.2/libavutil/opt.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/opt.h 2021-04-08 21:28:40.000000000 +0000 @@ -114,7 +114,7 @@ * libavcodec exports generic options, while its priv_data field exports * codec-specific options). In such a case, it is possible to set up the * parent struct to export a child's options. To do that, simply - * implement AVClass.child_next() and AVClass.child_class_next() in the + * implement AVClass.child_next() and AVClass.child_class_iterate() in the * parent struct's AVClass. * Assuming that the test_struct from above now also contains a * child_struct field: @@ -143,23 +143,25 @@ * return t->child_struct; * return NULL * } - * const AVClass child_class_next(const AVClass *prev) + * const AVClass child_class_iterate(void **iter) * { - * return prev ? NULL : &child_class; + * const AVClass *c = *iter ? NULL : &child_class; + * *iter = (void*)(uintptr_t)c; + * return c; * } * @endcode - * Putting child_next() and child_class_next() as defined above into + * Putting child_next() and child_class_iterate() as defined above into * test_class will now make child_struct's options accessible through * test_struct (again, proper setup as described above needs to be done on * child_struct right after it is created). * * From the above example it might not be clear why both child_next() - * and child_class_next() are needed. The distinction is that child_next() - * iterates over actually existing objects, while child_class_next() + * and child_class_iterate() are needed. The distinction is that child_next() + * iterates over actually existing objects, while child_class_iterate() * iterates over all possible child classes. E.g. if an AVCodecContext * was initialized to use a codec which has private options, then its * child_next() will return AVCodecContext.priv_data and finish - * iterating. OTOH child_class_next() on AVCodecContext.av_class will + * iterating. OTOH child_class_iterate() on AVCodecContext.av_class will * iterate over all available codecs with private options. * * @subsection avoptions_implement_named_constants Named constants @@ -194,7 +196,7 @@ * For enumerating there are basically two cases. The first is when you want to * get all options that may potentially exist on the struct and its children * (e.g. when constructing documentation). In that case you should call - * av_opt_child_class_next() recursively on the parent struct's AVClass. The + * av_opt_child_class_iterate() recursively on the parent struct's AVClass. The * second case is when you have an already initialized struct with all its * children and you want to get all options that can be actually written or read * from it. In that case you should call av_opt_child_next() recursively (and @@ -288,8 +290,10 @@ */ #define AV_OPT_FLAG_READONLY 128 #define AV_OPT_FLAG_BSF_PARAM (1<<8) ///< a generic parameter which can be set by the user for bit stream filtering +#define AV_OPT_FLAG_RUNTIME_PARAM (1<<15) ///< a generic parameter which can be set by the user at runtime #define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering #define AV_OPT_FLAG_DEPRECATED (1<<17) ///< set if option is deprecated, users should refer to AVOption.help text for more information +#define AV_OPT_FLAG_CHILD_CONSTS (1<<18) ///< set if option constants can also reside in child objects //FIXME think about enc-audio, ... style flags /** @@ -644,13 +648,26 @@ */ void *av_opt_child_next(void *obj, void *prev); +#if FF_API_CHILD_CLASS_NEXT /** * Iterate over potential AVOptions-enabled children of parent. * * @param prev result of a previous call to this function or NULL * @return AVClass corresponding to next potential child or NULL + * + * @deprecated use av_opt_child_class_iterate */ +attribute_deprecated const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *prev); +#endif + +/** + * Iterate over potential AVOptions-enabled children of parent. + * + * @param iter a pointer where iteration state is stored. + * @return AVClass corresponding to next potential child or NULL + */ +const AVClass *av_opt_child_class_iterate(const AVClass *parent, void **iter); /** * @defgroup opt_set_funcs Option setting functions @@ -669,6 +686,9 @@ * scalars or named flags separated by '+' or '-'. Prefixing a flag * with '+' causes it to be set without affecting the other flags; * similarly, '-' unsets a flag. + * If the field is of a dictionary type, it has to be a ':' separated list of + * key=value parameters. Values containing ':' special characters must be + * escaped. * @param search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN * is passed here, then the option may be set on a child of obj. * @@ -729,9 +749,10 @@ /** * @note the returned string will be av_malloc()ed and must be av_free()ed by the caller * - * @note if AV_OPT_ALLOW_NULL is set in search_flags in av_opt_get, and the option has - * AV_OPT_TYPE_STRING or AV_OPT_TYPE_BINARY and is set to NULL, *out_val will be set - * to NULL instead of an allocated empty string. + * @note if AV_OPT_ALLOW_NULL is set in search_flags in av_opt_get, and the + * option is of type AV_OPT_TYPE_STRING, AV_OPT_TYPE_BINARY or AV_OPT_TYPE_DICT + * and is set to NULL, *out_val will be set to NULL instead of an allocated + * empty string. */ int av_opt_get (void *obj, const char *name, int search_flags, uint8_t **out_val); int av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val); diff -Nru ffmpeg-4.2.2/libavutil/parseutils.c ffmpeg-4.4/libavutil/parseutils.c --- ffmpeg-4.2.2/libavutil/parseutils.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/parseutils.c 2021-04-08 21:28:40.000000000 +0000 @@ -736,12 +736,14 @@ if (*q) return AVERROR(EINVAL); - if (INT64_MAX / suffix < t) + if (INT64_MAX / suffix < t || t < INT64_MIN / suffix) return AVERROR(ERANGE); t *= suffix; if (INT64_MAX - microseconds < t) return AVERROR(ERANGE); t += microseconds; + if (t == INT64_MIN && negative) + return AVERROR(ERANGE); *timeval = negative ? -t : t; return 0; } diff -Nru ffmpeg-4.2.2/libavutil/pixdesc.c ffmpeg-4.4/libavutil/pixdesc.c --- ffmpeg-4.2.2/libavutil/pixdesc.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/pixdesc.c 2021-04-08 21:28:40.000000000 +0000 @@ -205,6 +205,29 @@ { 0, 4, 1, 0, 8, 3, 7, 2 }, /* V */ }, }, + [AV_PIX_FMT_Y210LE] = { + .name = "y210le", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 4, 0, 6, 10, 3, 9, 1 }, /* Y */ + { 0, 8, 2, 6, 10, 7, 9, 3 }, /* U */ + { 0, 8, 6, 6, 10, 7, 9, 7 }, /* V */ + }, + }, + [AV_PIX_FMT_Y210BE] = { + .name = "y210be", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 4, 0, 6, 10, 3, 9, 1 }, /* Y */ + { 0, 8, 2, 6, 10, 7, 9, 3 }, /* U */ + { 0, 8, 6, 6, 10, 7, 9, 7 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_BE, + }, [AV_PIX_FMT_RGB24] = { .name = "rgb24", .nb_components = 3, @@ -229,6 +252,30 @@ }, .flags = AV_PIX_FMT_FLAG_RGB, }, + [AV_PIX_FMT_X2RGB10LE] = { + .name = "x2rgb10le", + .nb_components= 3, + .log2_chroma_w= 0, + .log2_chroma_h= 0, + .comp = { + { 0, 4, 2, 4, 10, 3, 9, 2 }, /* R */ + { 0, 4, 1, 2, 10, 3, 9, 3 }, /* G */ + { 0, 4, 0, 0, 10, 3, 9, 4 }, /* B */ + }, + .flags = AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_X2RGB10BE] = { + .name = "x2rgb10be", + .nb_components= 3, + .log2_chroma_w= 0, + .log2_chroma_h= 0, + .comp = { + { 0, 4, 0, 4, 10, 3, 9, 2 }, /* R */ + { 0, 4, 1, 2, 10, 3, 9, 3 }, /* G */ + { 0, 4, 2, 0, 10, 3, 9, 4 }, /* B */ + }, + .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_BE, + }, [AV_PIX_FMT_YUV422P] = { .name = "yuv422p", .nb_components = 3, @@ -2344,6 +2391,10 @@ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, + [AV_PIX_FMT_VULKAN] = { + .name = "vulkan", + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, }; #if FF_API_PLUS1_MINUS1 FF_ENABLE_DEPRECATION_WARNINGS @@ -2369,7 +2420,7 @@ [AVCOL_PRI_SMPTE428] = "smpte428", [AVCOL_PRI_SMPTE431] = "smpte431", [AVCOL_PRI_SMPTE432] = "smpte432", - [AVCOL_PRI_JEDEC_P22] = "jedec-p22", + [AVCOL_PRI_EBU3213] = "ebu3213", }; static const char * const color_transfer_names[] = { @@ -2608,7 +2659,7 @@ continue; av_read_image_line(tmp, (void*)data, linesize, d, 0, 0, j, 2, 0); av_assert0(tmp[0] == 0 && tmp[1] == 0); - tmp[0] = tmp[1] = (1<depth) - 1; + tmp[0] = tmp[1] = (1ULL << c->depth) - 1; av_write_image_line(tmp, data, linesize, d, 0, 0, j, 2); } } @@ -2651,11 +2702,13 @@ if(desc->nb_components == 1 || desc->nb_components == 2) return FF_COLOR_GRAY; - if(desc->name && !strncmp(desc->name, "yuvj", 4)) - return FF_COLOR_YUV_JPEG; + if (desc->name) { + if (av_strstart(desc->name, "yuvj", NULL)) + return FF_COLOR_YUV_JPEG; - if(desc->name && !strncmp(desc->name, "xyz", 3)) - return FF_COLOR_XYZ; + if (av_strstart(desc->name, "xyz", NULL)) + return FF_COLOR_XYZ; + } if(desc->flags & AV_PIX_FMT_FLAG_RGB) return FF_COLOR_RGB; @@ -2856,8 +2909,7 @@ int i; for (i = 0; i < FF_ARRAY_ELEMS(color_range_names); i++) { - size_t len = strlen(color_range_names[i]); - if (!strncmp(color_range_names[i], name, len)) + if (av_strstart(name, color_range_names[i], NULL)) return i; } @@ -2875,13 +2927,10 @@ int i; for (i = 0; i < FF_ARRAY_ELEMS(color_primaries_names); i++) { - size_t len; - if (!color_primaries_names[i]) continue; - len = strlen(color_primaries_names[i]); - if (!strncmp(color_primaries_names[i], name, len)) + if (av_strstart(name, color_primaries_names[i], NULL)) return i; } @@ -2899,13 +2948,10 @@ int i; for (i = 0; i < FF_ARRAY_ELEMS(color_transfer_names); i++) { - size_t len; - if (!color_transfer_names[i]) continue; - len = strlen(color_transfer_names[i]); - if (!strncmp(color_transfer_names[i], name, len)) + if (av_strstart(name, color_transfer_names[i], NULL)) return i; } @@ -2923,13 +2969,10 @@ int i; for (i = 0; i < FF_ARRAY_ELEMS(color_space_names); i++) { - size_t len; - if (!color_space_names[i]) continue; - len = strlen(color_space_names[i]); - if (!strncmp(color_space_names[i], name, len)) + if (av_strstart(name, color_space_names[i], NULL)) return i; } @@ -2947,13 +2990,10 @@ int i; for (i = 0; i < FF_ARRAY_ELEMS(chroma_location_names); i++) { - size_t len; - if (!chroma_location_names[i]) continue; - len = strlen(chroma_location_names[i]); - if (!strncmp(chroma_location_names[i], name, len)) + if (av_strstart(name, chroma_location_names[i], NULL)) return i; } diff -Nru ffmpeg-4.2.2/libavutil/pixdesc.h ffmpeg-4.4/libavutil/pixdesc.h --- ffmpeg-4.2.2/libavutil/pixdesc.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/pixdesc.h 2021-04-08 21:28:40.000000000 +0000 @@ -147,6 +147,7 @@ */ #define AV_PIX_FMT_FLAG_RGB (1 << 5) +#if FF_API_PSEUDOPAL /** * The pixel format is "pseudo-paletted". This means that it contains a * fixed palette in the 2nd plane but the palette is fixed/constant for each @@ -164,6 +165,7 @@ * before the deprecation, though). */ #define AV_PIX_FMT_FLAG_PSEUDOPAL (1 << 6) +#endif /** * The pixel format has an alpha channel. This is set on all formats that diff -Nru ffmpeg-4.2.2/libavutil/pixfmt.h ffmpeg-4.4/libavutil/pixfmt.h --- ffmpeg-4.2.2/libavutil/pixfmt.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/pixfmt.h 2021-04-08 21:28:40.000000000 +0000 @@ -257,18 +257,18 @@ AV_PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little-endian AV_PIX_FMT_YUVJ411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV411P and setting color_range - AV_PIX_FMT_BAYER_BGGR8, ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples */ - AV_PIX_FMT_BAYER_RGGB8, ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples */ - AV_PIX_FMT_BAYER_GBRG8, ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples */ - AV_PIX_FMT_BAYER_GRBG8, ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples */ - AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian */ - AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian */ - AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian */ - AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian */ - AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian */ - AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian */ - AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian */ - AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian */ + AV_PIX_FMT_BAYER_BGGR8, ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples + AV_PIX_FMT_BAYER_RGGB8, ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples + AV_PIX_FMT_BAYER_GBRG8, ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples + AV_PIX_FMT_BAYER_GRBG8, ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples + AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian + AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian + AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing @@ -348,6 +348,18 @@ AV_PIX_FMT_NV24, ///< planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V) AV_PIX_FMT_NV42, ///< as above, but U and V bytes are swapped + /** + * Vulkan hardware images. + * + * data[0] points to an AVVkFrame + */ + AV_PIX_FMT_VULKAN, + + AV_PIX_FMT_Y210BE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_Y210LE, ///< packed YUV 4:2:2 like YUYV422, 20bpp, data in the high bits, little-endian + + AV_PIX_FMT_X2RGB10LE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), little-endian, X=unused/undefined + AV_PIX_FMT_X2RGB10BE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined 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 }; @@ -436,6 +448,9 @@ #define AV_PIX_FMT_P010 AV_PIX_FMT_NE(P010BE, P010LE) #define AV_PIX_FMT_P016 AV_PIX_FMT_NE(P016BE, P016LE) +#define AV_PIX_FMT_Y210 AV_PIX_FMT_NE(Y210BE, Y210LE) +#define AV_PIX_FMT_X2RGB10 AV_PIX_FMT_NE(X2RGB10BE, X2RGB10LE) + /** * Chromaticity coordinates of the source primaries. * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.1. @@ -456,7 +471,8 @@ AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428, AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) / DCI P3 AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3 - AVCOL_PRI_JEDEC_P22 = 22, ///< JEDEC P22 phosphors + AVCOL_PRI_EBU3213 = 22, ///< EBU Tech. 3213-E / JEDEC P22 phosphors + AVCOL_PRI_JEDEC_P22 = AVCOL_PRI_EBU3213, AVCOL_PRI_NB ///< Not part of ABI }; @@ -514,12 +530,60 @@ }; /** - * MPEG vs JPEG YUV range. + * Visual content value range. + * + * These values are based on definitions that can be found in multiple + * specifications, such as ITU-T BT.709 (3.4 - Quantization of RGB, luminance + * and colour-difference signals), ITU-T BT.2020 (Table 5 - Digital + * Representation) as well as ITU-T BT.2100 (Table 9 - Digital 10- and 12-bit + * integer representation). At the time of writing, the BT.2100 one is + * recommended, as it also defines the full range representation. + * + * Common definitions: + * - For RGB and luminance planes such as Y in YCbCr and I in ICtCp, + * 'E' is the original value in range of 0.0 to 1.0. + * - For chrominance planes such as Cb,Cr and Ct,Cp, 'E' is the original + * value in range of -0.5 to 0.5. + * - 'n' is the output bit depth. + * - For additional definitions such as rounding and clipping to valid n + * bit unsigned integer range, please refer to BT.2100 (Table 9). */ enum AVColorRange { AVCOL_RANGE_UNSPECIFIED = 0, - AVCOL_RANGE_MPEG = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges - AVCOL_RANGE_JPEG = 2, ///< the normal 2^n-1 "JPEG" YUV ranges + + /** + * Narrow or limited range content. + * + * - For luminance planes: + * + * (219 * E + 16) * 2^(n-8) + * + * F.ex. the range of 16-235 for 8 bits + * + * - For chrominance planes: + * + * (224 * E + 128) * 2^(n-8) + * + * F.ex. the range of 16-240 for 8 bits + */ + AVCOL_RANGE_MPEG = 1, + + /** + * Full range content. + * + * - For RGB and luminance planes: + * + * (2^n - 1) * E + * + * F.ex. the range of 0-255 for 8 bits + * + * - For chrominance planes: + * + * (2^n - 1) * E + 2^(n - 1) + * + * F.ex. the range of 1-255 for 8 bits + */ + AVCOL_RANGE_JPEG = 2, AVCOL_RANGE_NB ///< Not part of ABI }; diff -Nru ffmpeg-4.2.2/libavutil/rational.c ffmpeg-4.4/libavutil/rational.c --- ffmpeg-4.2.2/libavutil/rational.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libavutil/rational.c 2020-07-11 10:39:30.000000000 +0000 @@ -182,3 +182,12 @@ return sign<<31 | (150-shift)<<23 | (n - (1<<23)); } + +AVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def) +{ + int64_t gcd, lcm; + + gcd = av_gcd(a.den, b.den); + lcm = (a.den / gcd) * b.den; + return lcm < max_den ? av_make_q(av_gcd(a.num, b.num), lcm) : def; +} diff -Nru ffmpeg-4.2.2/libavutil/rational.h ffmpeg-4.4/libavutil/rational.h --- ffmpeg-4.2.2/libavutil/rational.h 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libavutil/rational.h 2020-07-11 10:39:30.000000000 +0000 @@ -208,6 +208,12 @@ uint32_t av_q2intfloat(AVRational q); /** + * Return the best rational so that a and b are multiple of it. + * If the resulting denominator is larger than max_den, return def. + */ +AVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def); + +/** * @} */ diff -Nru ffmpeg-4.2.2/libavutil/ripemd.c ffmpeg-4.4/libavutil/ripemd.c --- ffmpeg-4.2.2/libavutil/ripemd.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/ripemd.c 2021-04-08 21:28:40.000000000 +0000 @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include "attributes.h" diff -Nru ffmpeg-4.2.2/libavutil/ripemd.h ffmpeg-4.4/libavutil/ripemd.h --- ffmpeg-4.2.2/libavutil/ripemd.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/ripemd.h 2021-04-08 21:28:40.000000000 +0000 @@ -28,6 +28,7 @@ #ifndef AVUTIL_RIPEMD_H #define AVUTIL_RIPEMD_H +#include #include #include "attributes.h" diff -Nru ffmpeg-4.2.2/libavutil/spherical.c ffmpeg-4.4/libavutil/spherical.c --- ffmpeg-4.2.2/libavutil/spherical.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/spherical.c 2021-04-08 21:28:40.000000000 +0000 @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "avstring.h" #include "mem.h" #include "spherical.h" @@ -51,7 +52,7 @@ *bottom = orig_height - height - *top; } -static const char *spherical_projection_names[] = { +static const char *const spherical_projection_names[] = { [AV_SPHERICAL_EQUIRECTANGULAR] = "equirectangular", [AV_SPHERICAL_CUBEMAP] = "cubemap", [AV_SPHERICAL_EQUIRECTANGULAR_TILE] = "tiled equirectangular", @@ -70,8 +71,7 @@ int i; for (i = 0; i < FF_ARRAY_ELEMS(spherical_projection_names); i++) { - size_t len = strlen(spherical_projection_names[i]); - if (!strncmp(spherical_projection_names[i], name, len)) + if (av_strstart(name, spherical_projection_names[i], NULL)) return i; } diff -Nru ffmpeg-4.2.2/libavutil/stereo3d.c ffmpeg-4.4/libavutil/stereo3d.c --- ffmpeg-4.2.2/libavutil/stereo3d.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/stereo3d.c 2021-04-08 21:28:40.000000000 +0000 @@ -18,9 +18,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include +#include "avstring.h" #include "common.h" #include "mem.h" #include "stereo3d.h" @@ -67,8 +67,7 @@ int i; for (i = 0; i < FF_ARRAY_ELEMS(stereo3d_type_names); i++) { - size_t len = strlen(stereo3d_type_names[i]); - if (!strncmp(stereo3d_type_names[i], name, len)) + if (av_strstart(name, stereo3d_type_names[i], NULL)) return i; } diff -Nru ffmpeg-4.2.2/libavutil/tests/aes_ctr.c ffmpeg-4.4/libavutil/tests/aes_ctr.c --- ffmpeg-4.2.2/libavutil/tests/aes_ctr.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/tests/aes_ctr.c 2021-04-08 21:28:40.000000000 +0000 @@ -18,6 +18,7 @@ #include "libavutil/log.h" #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavutil/aes_ctr.h" static const DECLARE_ALIGNED(8, uint8_t, plain)[] = { diff -Nru ffmpeg-4.2.2/libavutil/tests/avstring.c ffmpeg-4.4/libavutil/tests/avstring.c --- ffmpeg-4.2.2/libavutil/tests/avstring.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/tests/avstring.c 2021-04-08 21:28:40.000000000 +0000 @@ -109,6 +109,8 @@ TEST_STRIREPLACE(haystack, needle [2], "Education consists mainly in what we have instead."); TEST_STRIREPLACE(haystack, needle [1], "Education consists mainly in what we have instead"); +#if FF_API_D2STR +FF_DISABLE_DEPRECATION_WARNINGS /*Testing av_d2str()*/ #define TEST_D2STR(value, expected) \ if((ptr = av_d2str(value)) == NULL){ \ @@ -121,5 +123,7 @@ TEST_D2STR(0 , "0.000000"); TEST_D2STR(-1.2333234, "-1.233323"); TEST_D2STR(-1.2333237, "-1.233324"); +FF_ENABLE_DEPRECATION_WARNINGS +#endif return 0; } diff -Nru ffmpeg-4.2.2/libavutil/tests/cpu.c ffmpeg-4.4/libavutil/tests/cpu.c --- ffmpeg-4.2.2/libavutil/tests/cpu.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/tests/cpu.c 2021-04-08 21:28:40.000000000 +0000 @@ -49,6 +49,9 @@ { AV_CPU_FLAG_SETEND, "setend" }, #elif ARCH_PPC { AV_CPU_FLAG_ALTIVEC, "altivec" }, +#elif ARCH_MIPS + { AV_CPU_FLAG_MMI, "mmi" }, + { AV_CPU_FLAG_MSA, "msa" }, #elif ARCH_X86 { AV_CPU_FLAG_MMX, "mmx" }, { AV_CPU_FLAG_MMXEXT, "mmxext" }, diff -Nru ffmpeg-4.2.2/libavutil/tests/des.c ffmpeg-4.4/libavutil/tests/des.c --- ffmpeg-4.2.2/libavutil/tests/des.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/tests/des.c 2021-04-08 21:28:40.000000000 +0000 @@ -16,6 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mem_internal.h" #include "libavutil/timer.h" #include "libavutil/des.c" diff -Nru ffmpeg-4.2.2/libavutil/tests/imgutils.c ffmpeg-4.4/libavutil/tests/imgutils.c --- ffmpeg-4.2.2/libavutil/tests/imgutils.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/tests/imgutils.c 2021-04-08 21:28:40.000000000 +0000 @@ -22,6 +22,7 @@ int main(void) { + const AVPixFmtDescriptor *desc = NULL; int64_t x, y; for (y = -1; yname); + for (i = 0; i < 4 && data[i]; i++); + printf("planes: %d", i); + // Test the output of av_image_fill_linesizes() + printf(", linesizes:"); + for (i = 0; i < 4; i++) + printf(" %3d", linesizes[i]); + // Test the output of av_image_fill_plane_sizes() + printf(", plane_sizes:"); + for (i = 0; i < 4; i++) + printf(" %5"SIZE_SPECIFIER, sizes[i]); + // Test the output of av_image_fill_pointers() + for (i = 0; i < 3 && data[i + 1]; i++) + offsets[i] = data[i + 1] - data[i]; + printf(", plane_offsets:"); + for (i = 0; i < 3; i++) + printf(" %5"PTRDIFF_SPECIFIER, offsets[i]); + printf(", total_size: %d\n", total_size); + } return 0; } diff -Nru ffmpeg-4.2.2/libavutil/tests/lls.c ffmpeg-4.4/libavutil/tests/lls.c --- ffmpeg-4.2.2/libavutil/tests/lls.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libavutil/tests/lls.c 2021-04-08 21:28:40.000000000 +0000 @@ -22,6 +22,7 @@ #include "libavutil/internal.h" #include "libavutil/lfg.h" #include "libavutil/lls.h" +#include "libavutil/mem_internal.h" int main(void) { diff -Nru ffmpeg-4.2.2/libavutil/tests/opt.c ffmpeg-4.4/libavutil/tests/opt.c --- ffmpeg-4.2.2/libavutil/tests/opt.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/tests/opt.c 2020-07-11 10:39:30.000000000 +0000 @@ -55,6 +55,8 @@ int bool1; int bool2; int bool3; + AVDictionary *dict1; + AVDictionary *dict2; } TestContext; #define OFFSET(x) offsetof(TestContext, x) @@ -89,6 +91,8 @@ {"bool1", "set boolean value", OFFSET(bool1), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, 1 }, {"bool2", "set boolean value", OFFSET(bool2), AV_OPT_TYPE_BOOL, { .i64 = 1 }, -1, 1, 1 }, {"bool3", "set boolean value", OFFSET(bool3), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, 1 }, + {"dict1", "set dictionary value", OFFSET(dict1), AV_OPT_TYPE_DICT, { .str = NULL}, 0, 0, 1 }, + {"dict2", "set dictionary value", OFFSET(dict2), AV_OPT_TYPE_DICT, { .str = "happy=':-)'"}, 0, 0, 1 }, { NULL }, }; @@ -167,6 +171,47 @@ av_opt_free(&test_ctx); } + printf("\nTesting av_opt_get/av_opt_set()\n"); + { + TestContext test_ctx = { 0 }; + TestContext test2_ctx = { 0 }; + const AVOption *o = NULL; + test_ctx.class = &test_class; + test2_ctx.class = &test_class; + + av_log_set_level(AV_LOG_QUIET); + + av_opt_set_defaults(&test_ctx); + + while (o = av_opt_next(&test_ctx, o)) { + char *value1 = NULL; + char *value2 = NULL; + int ret1 = AVERROR_BUG; + int ret2 = AVERROR_BUG; + int ret3 = AVERROR_BUG; + + if (o->type == AV_OPT_TYPE_CONST) + continue; + + ret1 = av_opt_get(&test_ctx, o->name, 0, (uint8_t **)&value1); + if (ret1 >= 0) { + ret2 = av_opt_set(&test2_ctx, o->name, value1, 0); + if (ret2 >= 0) + ret3 = av_opt_get(&test2_ctx, o->name, 0, (uint8_t **)&value2); + } + + printf("name: %-11s get: %-16s set: %-16s get: %-16s %s\n", o->name, + ret1 >= 0 ? value1 : av_err2str(ret1), + ret2 >= 0 ? "OK" : av_err2str(ret2), + ret3 >= 0 ? value2 : av_err2str(ret3), + ret1 >= 0 && ret2 >= 0 && ret3 >= 0 && !strcmp(value1, value2) ? "OK" : "Mismatch"); + av_free(value1); + av_free(value2); + } + av_opt_free(&test_ctx); + av_opt_free(&test2_ctx); + } + printf("\nTest av_opt_serialize()\n"); { TestContext test_ctx = { 0 }; @@ -256,6 +301,7 @@ "dbl=101", "bool1=true", "bool2=auto", + "dict1='happy=\\:-):sad=\\:-('", }; test_ctx.class = &test_class; diff -Nru ffmpeg-4.2.2/libavutil/thread.h ffmpeg-4.4/libavutil/thread.h --- ffmpeg-4.2.2/libavutil/thread.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/thread.h 2020-07-11 10:39:30.000000000 +0000 @@ -33,16 +33,19 @@ #include "log.h" +#define ASSERT_PTHREAD_ABORT(func, ret) do { \ + char errbuf[AV_ERROR_MAX_STRING_SIZE] = ""; \ + av_log(NULL, AV_LOG_FATAL, AV_STRINGIFY(func) \ + " failed with error: %s\n", \ + av_make_error_string(errbuf, AV_ERROR_MAX_STRING_SIZE, \ + AVERROR(ret))); \ + abort(); \ +} while (0) + #define ASSERT_PTHREAD_NORET(func, ...) do { \ int ret = func(__VA_ARGS__); \ - if (ret) { \ - char errbuf[AV_ERROR_MAX_STRING_SIZE] = ""; \ - av_log(NULL, AV_LOG_FATAL, AV_STRINGIFY(func) \ - " failed with error: %s\n", \ - av_make_error_string(errbuf, AV_ERROR_MAX_STRING_SIZE, \ - AVERROR(ret))); \ - abort(); \ - } \ + if (ret) \ + ASSERT_PTHREAD_ABORT(func, ret); \ } while (0) #define ASSERT_PTHREAD(func, ...) do { \ @@ -109,6 +112,15 @@ ASSERT_PTHREAD(pthread_cond_wait, cond, mutex); } +static inline int strict_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + int ret = pthread_cond_timedwait(cond, mutex, abstime); + if (ret && ret != ETIMEDOUT) + ASSERT_PTHREAD_ABORT(pthread_cond_timedwait, ret); + return ret; +} + static inline int strict_pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) { ASSERT_PTHREAD(pthread_once, once_control, init_routine); @@ -124,6 +136,7 @@ #define pthread_cond_signal strict_pthread_cond_signal #define pthread_cond_broadcast strict_pthread_cond_broadcast #define pthread_cond_wait strict_pthread_cond_wait +#define pthread_cond_timedwait strict_pthread_cond_timedwait #define pthread_once strict_pthread_once #endif diff -Nru ffmpeg-4.2.2/libavutil/time.c ffmpeg-4.4/libavutil/time.c --- ffmpeg-4.2.2/libavutil/time.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/time.c 2021-04-08 21:28:40.000000000 +0000 @@ -57,7 +57,7 @@ { #if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC) #ifdef __APPLE__ - if (clock_gettime) + if (&clock_gettime) #endif { struct timespec ts; @@ -72,7 +72,7 @@ { #if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC) #ifdef __APPLE__ - if (!clock_gettime) + if (!&clock_gettime) return 0; #endif return 1; diff -Nru ffmpeg-4.2.2/libavutil/timecode.c ffmpeg-4.4/libavutil/timecode.c --- ffmpeg-4.2.2/libavutil/timecode.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/timecode.c 2021-04-08 21:28:40.000000000 +0000 @@ -33,23 +33,20 @@ int av_timecode_adjust_ntsc_framenum2(int framenum, int fps) { - /* only works for NTSC 29.97 and 59.94 */ + /* only works for multiples of NTSC 29.97 */ int drop_frames = 0; int d, m, frames_per_10mins; - if (fps == 30) { - drop_frames = 2; - frames_per_10mins = 17982; - } else if (fps == 60) { - drop_frames = 4; - frames_per_10mins = 35964; + if (fps && fps % 30 == 0) { + drop_frames = fps / 30 * 2; + frames_per_10mins = fps / 30 * 17982; } else return framenum; d = framenum / frames_per_10mins; m = framenum % frames_per_10mins; - return framenum + 9 * drop_frames * d + drop_frames * ((m - drop_frames) / (frames_per_10mins / 10)); + return framenum + 9U * drop_frames * d + drop_frames * ((m - drop_frames) / (frames_per_10mins / 10)); } uint32_t av_timecode_get_smpte_from_framenum(const AVTimecode *tc, int framenum) @@ -65,20 +62,41 @@ ss = framenum / fps % 60; mm = framenum / (fps*60) % 60; hh = framenum / (fps*3600) % 24; - return 0 << 31 | // color frame flag (0: unsync mode, 1: sync mode) - drop << 30 | // drop frame flag (0: non drop, 1: drop) - (ff / 10) << 28 | // tens of frames - (ff % 10) << 24 | // units of frames - 0 << 23 | // PC (NTSC) or BGF0 (PAL) - (ss / 10) << 20 | // tens of seconds - (ss % 10) << 16 | // units of seconds - 0 << 15 | // BGF0 (NTSC) or BGF2 (PAL) - (mm / 10) << 12 | // tens of minutes - (mm % 10) << 8 | // units of minutes - 0 << 7 | // BGF2 (NTSC) or PC (PAL) - 0 << 6 | // BGF1 - (hh / 10) << 4 | // tens of hours - (hh % 10); // units of hours + return av_timecode_get_smpte(tc->rate, drop, hh, mm, ss, ff); +} + +uint32_t av_timecode_get_smpte(AVRational rate, int drop, int hh, int mm, int ss, int ff) +{ + uint32_t tc = 0; + + /* For SMPTE 12-M timecodes, frame count is a special case if > 30 FPS. + See SMPTE ST 12-1:2014 Sec 12.1 for more info. */ + if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) { + if (ff % 2 == 1) { + if (av_cmp_q(rate, (AVRational) {50, 1}) == 0) + tc |= (1 << 7); + else + tc |= (1 << 23); + } + ff /= 2; + } + + hh = hh % 24; + mm = av_clip(mm, 0, 59); + ss = av_clip(ss, 0, 59); + ff = ff % 40; + + tc |= drop << 30; + tc |= (ff / 10) << 28; + tc |= (ff % 10) << 24; + tc |= (ss / 10) << 20; + tc |= (ss % 10) << 16; + tc |= (mm / 10) << 12; + tc |= (mm % 10) << 8; + tc |= (hh / 10) << 4; + tc |= (hh % 10); + + return tc; } char *av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum) @@ -96,8 +114,8 @@ } ff = framenum % fps; ss = framenum / fps % 60; - mm = framenum / (fps*60) % 60; - hh = framenum / (fps*3600); + mm = framenum / (fps*60LL) % 60; + hh = framenum / (fps*3600LL); if (tc->flags & AV_TIMECODE_FLAG_24HOURSMAX) hh = hh % 24; snprintf(buf, AV_TIMECODE_STR_SIZE, "%s%02d:%02d:%02d%c%02d", @@ -115,16 +133,33 @@ return low + 10*high; } -char *av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int prevent_df) +char *av_timecode_make_smpte_tc_string2(char *buf, AVRational rate, uint32_t tcsmpte, int prevent_df, int skip_field) { unsigned hh = bcd2uint(tcsmpte & 0x3f); // 6-bit hours unsigned mm = bcd2uint(tcsmpte>>8 & 0x7f); // 7-bit minutes unsigned ss = bcd2uint(tcsmpte>>16 & 0x7f); // 7-bit seconds unsigned ff = bcd2uint(tcsmpte>>24 & 0x3f); // 6-bit frames unsigned drop = tcsmpte & 1<<30 && !prevent_df; // 1-bit drop if not arbitrary bit + + if (av_cmp_q(rate, (AVRational) {30, 1}) == 1) { + ff <<= 1; + if (!skip_field) { + if (av_cmp_q(rate, (AVRational) {50, 1}) == 0) + ff += !!(tcsmpte & 1 << 7); + else + ff += !!(tcsmpte & 1 << 23); + } + } + snprintf(buf, AV_TIMECODE_STR_SIZE, "%02u:%02u:%02u%c%02u", hh, mm, ss, drop ? ';' : ':', ff); return buf; + +} + +char *av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int prevent_df) +{ + return av_timecode_make_smpte_tc_string2(buf, (AVRational){30, 1}, tcsmpte, prevent_df, 1); } char *av_timecode_make_mpeg_tc_string(char *buf, uint32_t tc25bit) @@ -158,8 +193,8 @@ av_log(log_ctx, AV_LOG_ERROR, "Valid timecode frame rate must be specified. Minimum value is 1\n"); return AVERROR(EINVAL); } - if ((tc->flags & AV_TIMECODE_FLAG_DROPFRAME) && tc->fps != 30 && tc->fps != 60) { - av_log(log_ctx, AV_LOG_ERROR, "Drop frame is only allowed with 30000/1001 or 60000/1001 FPS\n"); + if ((tc->flags & AV_TIMECODE_FLAG_DROPFRAME) && tc->fps % 30 != 0) { + av_log(log_ctx, AV_LOG_ERROR, "Drop frame is only allowed with multiples of 30000/1001 FPS\n"); return AVERROR(EINVAL); } if (check_fps(tc->fps) < 0) { @@ -191,19 +226,12 @@ return check_timecode(log_ctx, tc); } -int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx) +int av_timecode_init_from_components(AVTimecode *tc, AVRational rate, int flags, int hh, int mm, int ss, int ff, void *log_ctx) { - char c; - int hh, mm, ss, ff, ret; - - if (sscanf(str, "%d:%d:%d%c%d", &hh, &mm, &ss, &c, &ff) != 5) { - av_log(log_ctx, AV_LOG_ERROR, "Unable to parse timecode, " - "syntax: hh:mm:ss[:;.]ff\n"); - return AVERROR_INVALIDDATA; - } + int ret; memset(tc, 0, sizeof(*tc)); - tc->flags = c != ':' ? AV_TIMECODE_FLAG_DROPFRAME : 0; // drop if ';', '.', ... + tc->flags = flags; tc->rate = rate; tc->fps = fps_from_frame_rate(rate); @@ -214,7 +242,22 @@ tc->start = (hh*3600 + mm*60 + ss) * tc->fps + ff; if (tc->flags & AV_TIMECODE_FLAG_DROPFRAME) { /* adjust frame number */ int tmins = 60*hh + mm; - tc->start -= (tc->fps == 30 ? 2 : 4) * (tmins - tmins/10); + tc->start -= (tc->fps / 30 * 2) * (tmins - tmins/10); } return 0; } + +int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx) +{ + char c; + int hh, mm, ss, ff, flags; + + if (sscanf(str, "%d:%d:%d%c%d", &hh, &mm, &ss, &c, &ff) != 5) { + av_log(log_ctx, AV_LOG_ERROR, "Unable to parse timecode, " + "syntax: hh:mm:ss[:;.]ff\n"); + return AVERROR_INVALIDDATA; + } + flags = c != ':' ? AV_TIMECODE_FLAG_DROPFRAME : 0; // drop if ';', '.', ... + + return av_timecode_init_from_components(tc, rate, flags, hh, mm, ss, ff, log_ctx); +} diff -Nru ffmpeg-4.2.2/libavutil/timecode.h ffmpeg-4.4/libavutil/timecode.h --- ffmpeg-4.2.2/libavutil/timecode.h 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libavutil/timecode.h 2021-04-08 21:28:40.000000000 +0000 @@ -49,9 +49,9 @@ * Adjust frame number for NTSC drop frame time code. * * @param framenum frame number to adjust - * @param fps frame per second, 30 or 60 + * @param fps frame per second, multiples of 30 * @return adjusted frame number - * @warning adjustment is only valid in NTSC 29.97 and 59.94 + * @warning adjustment is only valid for multiples of NTSC 29.97 */ int av_timecode_adjust_ntsc_framenum2(int framenum, int fps); @@ -62,15 +62,40 @@ * @param framenum frame number * @return the SMPTE binary representation * + * See SMPTE ST 314M-2005 Sec 4.4.2.2.1 "Time code pack (TC)" + * the format description as follows: + * bits 0-5: hours, in BCD(6bits) + * bits 6: BGF1 + * bits 7: BGF2 (NTSC) or FIELD (PAL) + * bits 8-14: minutes, in BCD(7bits) + * bits 15: BGF0 (NTSC) or BGF2 (PAL) + * bits 16-22: seconds, in BCD(7bits) + * bits 23: FIELD (NTSC) or BGF0 (PAL) + * bits 24-29: frames, in BCD(6bits) + * bits 30: drop frame flag (0: non drop, 1: drop) + * bits 31: color frame flag (0: unsync mode, 1: sync mode) + * @note BCD numbers (6 or 7 bits): 4 or 5 lower bits for units, 2 higher bits for tens. * @note Frame number adjustment is automatically done in case of drop timecode, * you do NOT have to call av_timecode_adjust_ntsc_framenum2(). * @note The frame number is relative to tc->start. - * @note Color frame (CF), binary group flags (BGF) and biphase mark polarity - * correction (PC) bits are set to zero. + * @note Color frame (CF) and binary group flags (BGF) bits are set to zero. */ uint32_t av_timecode_get_smpte_from_framenum(const AVTimecode *tc, int framenum); /** + * Convert sei info to SMPTE 12M binary representation. + * + * @param rate frame rate in rational form + * @param drop drop flag + * @param hh hour + * @param mm minute + * @param ss second + * @param ff frame number + * @return the SMPTE binary representation + */ +uint32_t av_timecode_get_smpte(AVRational rate, int drop, int hh, int mm, int ss, int ff); + +/** * Load timecode string in buf. * * @param buf destination buffer, must be at least AV_TIMECODE_STR_SIZE long @@ -87,6 +112,23 @@ /** * Get the timecode string from the SMPTE timecode format. * + * In contrast to av_timecode_make_smpte_tc_string this function supports 50/60 + * fps timecodes by using the field bit. + * + * @param buf destination buffer, must be at least AV_TIMECODE_STR_SIZE long + * @param rate frame rate of the timecode + * @param tcsmpte the 32-bit SMPTE timecode + * @param prevent_df prevent the use of a drop flag when it is known the DF bit + * is arbitrary + * @param skip_field prevent the use of a field flag when it is known the field + * bit is arbitrary (e.g. because it is used as PC flag) + * @return the buf parameter + */ +char *av_timecode_make_smpte_tc_string2(char *buf, AVRational rate, uint32_t tcsmpte, int prevent_df, int skip_field); + +/** + * Get the timecode string from the SMPTE timecode format. + * * @param buf destination buffer, must be at least AV_TIMECODE_STR_SIZE long * @param tcsmpte the 32-bit SMPTE timecode * @param prevent_df prevent the use of a drop flag when it is known the DF bit @@ -119,6 +161,23 @@ int av_timecode_init(AVTimecode *tc, AVRational rate, int flags, int frame_start, void *log_ctx); /** + * Init a timecode struct from the passed timecode components. + * + * @param log_ctx a pointer to an arbitrary struct of which the first field + * is a pointer to an AVClass struct (used for av_log) + * @param tc pointer to an allocated AVTimecode + * @param rate frame rate in rational form + * @param flags miscellaneous flags such as drop frame, +24 hours, ... + * (see AVTimecodeFlag) + * @param hh hours + * @param mm minutes + * @param ss seconds + * @param ff frames + * @return 0 on success, AVERROR otherwise + */ +int av_timecode_init_from_components(AVTimecode *tc, AVRational rate, int flags, int hh, int mm, int ss, int ff, void *log_ctx); + +/** * Parse timecode representation (hh:mm:ss[:;.]ff). * * @param log_ctx a pointer to an arbitrary struct of which the first field is a diff -Nru ffmpeg-4.2.2/libavutil/timer.h ffmpeg-4.4/libavutil/timer.h --- ffmpeg-4.2.2/libavutil/timer.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/timer.h 2021-04-08 21:28:40.000000000 +0000 @@ -87,7 +87,7 @@ if (((tcount + tskip_count) & (tcount + tskip_count - 1)) == 0) { \ int i; \ av_log(NULL, AV_LOG_ERROR, \ - "%7"PRIu64" " FF_TIMER_UNITS " in %s,%8d runs,%7d skips", \ + "%7" PRIu64 " " FF_TIMER_UNITS " in %s,%8d runs,%7d skips",\ tsum * 10 / tcount, id, tcount, tskip_count); \ for (i = 0; i < 32; i++) \ av_log(NULL, AV_LOG_VERBOSE, " %2d", av_log2(2*thistogram[i]));\ diff -Nru ffmpeg-4.2.2/libavutil/tx.c ffmpeg-4.4/libavutil/tx.c --- ffmpeg-4.2.2/libavutil/tx.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/tx.c 2021-04-08 21:28:40.000000000 +0000 @@ -1,10 +1,4 @@ /* - * Copyright (c) 2019 Lynne - * Power of two FFT: - * Copyright (c) 2008 Loren Merritt - * Copyright (c) 2002 Fabrice Bellard - * Partly based on libdjbfft by D. J. Bernstein - * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -22,576 +16,22 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include "tx.h" -#include "thread.h" -#include "mem.h" -#include "avassert.h" - -typedef float FFTSample; -typedef AVComplexFloat FFTComplex; - -struct AVTXContext { - int n; /* Nptwo part */ - int m; /* Ptwo part */ - - FFTComplex *exptab; /* MDCT exptab */ - FFTComplex *tmp; /* Temporary buffer needed for all compound transforms */ - int *pfatab; /* Input/Output mapping for compound transforms */ - int *revtab; /* Input mapping for power of two transforms */ -}; - -#define FFT_NAME(x) x - -#define COSTABLE(size) \ - static DECLARE_ALIGNED(32, FFTSample, FFT_NAME(ff_cos_##size))[size/2] - -static FFTSample * const FFT_NAME(ff_cos_tabs)[18]; - -COSTABLE(16); -COSTABLE(32); -COSTABLE(64); -COSTABLE(128); -COSTABLE(256); -COSTABLE(512); -COSTABLE(1024); -COSTABLE(2048); -COSTABLE(4096); -COSTABLE(8192); -COSTABLE(16384); -COSTABLE(32768); -COSTABLE(65536); -COSTABLE(131072); - -static av_cold void init_ff_cos_tabs(int index) -{ - int m = 1 << index; - double freq = 2*M_PI/m; - FFTSample *tab = FFT_NAME(ff_cos_tabs)[index]; - for(int i = 0; i <= m/4; i++) - tab[i] = cos(i*freq); - for(int i = 1; i < m/4; i++) - tab[m/2 - i] = tab[i]; -} - -typedef struct CosTabsInitOnce { - void (*func)(void); - AVOnce control; -} CosTabsInitOnce; - -#define INIT_FF_COS_TABS_FUNC(index, size) \ -static av_cold void init_ff_cos_tabs_ ## size (void) \ -{ \ - init_ff_cos_tabs(index); \ -} - -INIT_FF_COS_TABS_FUNC(4, 16) -INIT_FF_COS_TABS_FUNC(5, 32) -INIT_FF_COS_TABS_FUNC(6, 64) -INIT_FF_COS_TABS_FUNC(7, 128) -INIT_FF_COS_TABS_FUNC(8, 256) -INIT_FF_COS_TABS_FUNC(9, 512) -INIT_FF_COS_TABS_FUNC(10, 1024) -INIT_FF_COS_TABS_FUNC(11, 2048) -INIT_FF_COS_TABS_FUNC(12, 4096) -INIT_FF_COS_TABS_FUNC(13, 8192) -INIT_FF_COS_TABS_FUNC(14, 16384) -INIT_FF_COS_TABS_FUNC(15, 32768) -INIT_FF_COS_TABS_FUNC(16, 65536) -INIT_FF_COS_TABS_FUNC(17, 131072) - -static CosTabsInitOnce cos_tabs_init_once[] = { - { NULL }, - { NULL }, - { NULL }, - { NULL }, - { init_ff_cos_tabs_16, AV_ONCE_INIT }, - { init_ff_cos_tabs_32, AV_ONCE_INIT }, - { init_ff_cos_tabs_64, AV_ONCE_INIT }, - { init_ff_cos_tabs_128, AV_ONCE_INIT }, - { init_ff_cos_tabs_256, AV_ONCE_INIT }, - { init_ff_cos_tabs_512, AV_ONCE_INIT }, - { init_ff_cos_tabs_1024, AV_ONCE_INIT }, - { init_ff_cos_tabs_2048, AV_ONCE_INIT }, - { init_ff_cos_tabs_4096, AV_ONCE_INIT }, - { init_ff_cos_tabs_8192, AV_ONCE_INIT }, - { init_ff_cos_tabs_16384, AV_ONCE_INIT }, - { init_ff_cos_tabs_32768, AV_ONCE_INIT }, - { init_ff_cos_tabs_65536, AV_ONCE_INIT }, - { init_ff_cos_tabs_131072, AV_ONCE_INIT }, -}; - -static FFTSample * const FFT_NAME(ff_cos_tabs)[] = { - NULL, NULL, NULL, NULL, - FFT_NAME(ff_cos_16), - FFT_NAME(ff_cos_32), - FFT_NAME(ff_cos_64), - FFT_NAME(ff_cos_128), - FFT_NAME(ff_cos_256), - FFT_NAME(ff_cos_512), - FFT_NAME(ff_cos_1024), - FFT_NAME(ff_cos_2048), - FFT_NAME(ff_cos_4096), - FFT_NAME(ff_cos_8192), - FFT_NAME(ff_cos_16384), - FFT_NAME(ff_cos_32768), - FFT_NAME(ff_cos_65536), - FFT_NAME(ff_cos_131072), -}; +#include "tx_priv.h" -static av_cold void ff_init_ff_cos_tabs(int index) +int ff_tx_type_is_mdct(enum AVTXType type) { - ff_thread_once(&cos_tabs_init_once[index].control, - cos_tabs_init_once[index].func); -} - -static AVOnce tabs_53_once = AV_ONCE_INIT; -static DECLARE_ALIGNED(32, FFTComplex, FFT_NAME(ff_53_tabs))[4]; - -static av_cold void ff_init_53_tabs(void) -{ - ff_53_tabs[0] = (FFTComplex){ cos(2 * M_PI / 12), cos(2 * M_PI / 12) }; - ff_53_tabs[1] = (FFTComplex){ 0.5, 0.5 }; - ff_53_tabs[2] = (FFTComplex){ cos(2 * M_PI / 5), sin(2 * M_PI / 5) }; - ff_53_tabs[3] = (FFTComplex){ cos(2 * M_PI / 10), sin(2 * M_PI / 10) }; -} - -#define BF(x, y, a, b) do { \ - x = (a) - (b); \ - y = (a) + (b); \ - } while (0) - -#define CMUL(dre, dim, are, aim, bre, bim) do { \ - (dre) = (are) * (bre) - (aim) * (bim); \ - (dim) = (are) * (bim) + (aim) * (bre); \ - } while (0) - -#define CMUL3(c, a, b) CMUL((c).re, (c).im, (a).re, (a).im, (b).re, (b).im) - -static av_always_inline void fft3(FFTComplex *out, FFTComplex *in, - ptrdiff_t stride) -{ - FFTComplex tmp[2]; - - tmp[0].re = in[1].im - in[2].im; - tmp[0].im = in[1].re - in[2].re; - tmp[1].re = in[1].re + in[2].re; - tmp[1].im = in[1].im + in[2].im; - - out[0*stride].re = in[0].re + tmp[1].re; - out[0*stride].im = in[0].im + tmp[1].im; - - tmp[0].re *= ff_53_tabs[0].re; - tmp[0].im *= ff_53_tabs[0].im; - tmp[1].re *= ff_53_tabs[1].re; - tmp[1].im *= ff_53_tabs[1].re; - - out[1*stride].re = in[0].re - tmp[1].re + tmp[0].re; - out[1*stride].im = in[0].im - tmp[1].im - tmp[0].im; - out[2*stride].re = in[0].re - tmp[1].re - tmp[0].re; - out[2*stride].im = in[0].im - tmp[1].im + tmp[0].im; -} - -#define DECL_FFT5(NAME, D0, D1, D2, D3, D4) \ -static av_always_inline void NAME(FFTComplex *out, FFTComplex *in, \ - ptrdiff_t stride) \ -{ \ - FFTComplex z0[4], t[6]; \ - \ - t[0].re = in[1].re + in[4].re; \ - t[0].im = in[1].im + in[4].im; \ - t[1].im = in[1].re - in[4].re; \ - t[1].re = in[1].im - in[4].im; \ - t[2].re = in[2].re + in[3].re; \ - t[2].im = in[2].im + in[3].im; \ - t[3].im = in[2].re - in[3].re; \ - t[3].re = in[2].im - in[3].im; \ - \ - out[D0*stride].re = in[0].re + in[1].re + in[2].re + \ - in[3].re + in[4].re; \ - out[D0*stride].im = in[0].im + in[1].im + in[2].im + \ - in[3].im + in[4].im; \ - \ - t[4].re = ff_53_tabs[2].re * t[2].re - ff_53_tabs[3].re * t[0].re; \ - t[4].im = ff_53_tabs[2].re * t[2].im - ff_53_tabs[3].re * t[0].im; \ - t[0].re = ff_53_tabs[2].re * t[0].re - ff_53_tabs[3].re * t[2].re; \ - t[0].im = ff_53_tabs[2].re * t[0].im - ff_53_tabs[3].re * t[2].im; \ - t[5].re = ff_53_tabs[2].im * t[3].re - ff_53_tabs[3].im * t[1].re; \ - t[5].im = ff_53_tabs[2].im * t[3].im - ff_53_tabs[3].im * t[1].im; \ - t[1].re = ff_53_tabs[2].im * t[1].re + ff_53_tabs[3].im * t[3].re; \ - t[1].im = ff_53_tabs[2].im * t[1].im + ff_53_tabs[3].im * t[3].im; \ - \ - z0[0].re = t[0].re - t[1].re; \ - z0[0].im = t[0].im - t[1].im; \ - z0[1].re = t[4].re + t[5].re; \ - z0[1].im = t[4].im + t[5].im; \ - \ - z0[2].re = t[4].re - t[5].re; \ - z0[2].im = t[4].im - t[5].im; \ - z0[3].re = t[0].re + t[1].re; \ - z0[3].im = t[0].im + t[1].im; \ - \ - out[D1*stride].re = in[0].re + z0[3].re; \ - out[D1*stride].im = in[0].im + z0[0].im; \ - out[D2*stride].re = in[0].re + z0[2].re; \ - out[D2*stride].im = in[0].im + z0[1].im; \ - out[D3*stride].re = in[0].re + z0[1].re; \ - out[D3*stride].im = in[0].im + z0[2].im; \ - out[D4*stride].re = in[0].re + z0[0].re; \ - out[D4*stride].im = in[0].im + z0[3].im; \ -} - -DECL_FFT5(fft5, 0, 1, 2, 3, 4) -DECL_FFT5(fft5_m1, 0, 6, 12, 3, 9) -DECL_FFT5(fft5_m2, 10, 1, 7, 13, 4) -DECL_FFT5(fft5_m3, 5, 11, 2, 8, 14) - -static av_always_inline void fft15(FFTComplex *out, FFTComplex *in, - ptrdiff_t stride) -{ - FFTComplex tmp[15]; - - for (int i = 0; i < 5; i++) - fft3(tmp + i, in + i*3, 5); - - fft5_m1(out, tmp + 0, stride); - fft5_m2(out, tmp + 5, stride); - fft5_m3(out, tmp + 10, stride); -} - -#define BUTTERFLIES(a0,a1,a2,a3) {\ - BF(t3, t5, t5, t1);\ - BF(a2.re, a0.re, a0.re, t5);\ - BF(a3.im, a1.im, a1.im, t3);\ - BF(t4, t6, t2, t6);\ - BF(a3.re, a1.re, a1.re, t4);\ - BF(a2.im, a0.im, a0.im, t6);\ -} - -// force loading all the inputs before storing any. -// this is slightly slower for small data, but avoids store->load aliasing -// for addresses separated by large powers of 2. -#define BUTTERFLIES_BIG(a0,a1,a2,a3) {\ - FFTSample r0=a0.re, i0=a0.im, r1=a1.re, i1=a1.im;\ - BF(t3, t5, t5, t1);\ - BF(a2.re, a0.re, r0, t5);\ - BF(a3.im, a1.im, i1, t3);\ - BF(t4, t6, t2, t6);\ - BF(a3.re, a1.re, r1, t4);\ - BF(a2.im, a0.im, i0, t6);\ -} - -#define TRANSFORM(a0,a1,a2,a3,wre,wim) {\ - CMUL(t1, t2, a2.re, a2.im, wre, -wim);\ - CMUL(t5, t6, a3.re, a3.im, wre, wim);\ - BUTTERFLIES(a0,a1,a2,a3)\ -} - -#define TRANSFORM_ZERO(a0,a1,a2,a3) {\ - t1 = a2.re;\ - t2 = a2.im;\ - t5 = a3.re;\ - t6 = a3.im;\ - BUTTERFLIES(a0,a1,a2,a3)\ -} - -/* z[0...8n-1], w[1...2n-1] */ -#define PASS(name)\ -static void name(FFTComplex *z, const FFTSample *wre, unsigned int n)\ -{\ - FFTSample t1, t2, t3, t4, t5, t6;\ - int o1 = 2*n;\ - int o2 = 4*n;\ - int o3 = 6*n;\ - const FFTSample *wim = wre+o1;\ - n--;\ -\ - TRANSFORM_ZERO(z[0],z[o1],z[o2],z[o3]);\ - TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]);\ - do {\ - z += 2;\ - wre += 2;\ - wim -= 2;\ - TRANSFORM(z[0],z[o1],z[o2],z[o3],wre[0],wim[0]);\ - TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]);\ - } while(--n);\ -} - -PASS(pass) -#undef BUTTERFLIES -#define BUTTERFLIES BUTTERFLIES_BIG -PASS(pass_big) - -#define DECL_FFT(n,n2,n4)\ -static void fft##n(FFTComplex *z)\ -{\ - fft##n2(z);\ - fft##n4(z+n4*2);\ - fft##n4(z+n4*3);\ - pass(z,FFT_NAME(ff_cos_##n),n4/2);\ -} - -static void fft4(FFTComplex *z) -{ - FFTSample t1, t2, t3, t4, t5, t6, t7, t8; - - BF(t3, t1, z[0].re, z[1].re); - BF(t8, t6, z[3].re, z[2].re); - BF(z[2].re, z[0].re, t1, t6); - BF(t4, t2, z[0].im, z[1].im); - BF(t7, t5, z[2].im, z[3].im); - BF(z[3].im, z[1].im, t4, t8); - BF(z[3].re, z[1].re, t3, t7); - BF(z[2].im, z[0].im, t2, t5); -} - -static void fft8(FFTComplex *z) -{ - FFTSample t1, t2, t3, t4, t5, t6; - - fft4(z); - - BF(t1, z[5].re, z[4].re, -z[5].re); - BF(t2, z[5].im, z[4].im, -z[5].im); - BF(t5, z[7].re, z[6].re, -z[7].re); - BF(t6, z[7].im, z[6].im, -z[7].im); - - BUTTERFLIES(z[0],z[2],z[4],z[6]); - TRANSFORM(z[1],z[3],z[5],z[7],M_SQRT1_2,M_SQRT1_2); -} - -static void fft16(FFTComplex *z) -{ - FFTSample t1, t2, t3, t4, t5, t6; - FFTSample cos_16_1 = FFT_NAME(ff_cos_16)[1]; - FFTSample cos_16_3 = FFT_NAME(ff_cos_16)[3]; - - fft8(z); - fft4(z+8); - fft4(z+12); - - TRANSFORM_ZERO(z[0],z[4],z[8],z[12]); - TRANSFORM(z[2],z[6],z[10],z[14],M_SQRT1_2,M_SQRT1_2); - TRANSFORM(z[1],z[5],z[9],z[13],cos_16_1,cos_16_3); - TRANSFORM(z[3],z[7],z[11],z[15],cos_16_3,cos_16_1); -} - -DECL_FFT(32,16,8) -DECL_FFT(64,32,16) -DECL_FFT(128,64,32) -DECL_FFT(256,128,64) -DECL_FFT(512,256,128) -#define pass pass_big -DECL_FFT(1024,512,256) -DECL_FFT(2048,1024,512) -DECL_FFT(4096,2048,1024) -DECL_FFT(8192,4096,2048) -DECL_FFT(16384,8192,4096) -DECL_FFT(32768,16384,8192) -DECL_FFT(65536,32768,16384) -DECL_FFT(131072,65536,32768) - -static void (* const fft_dispatch[])(FFTComplex*) = { - fft4, fft8, fft16, fft32, fft64, fft128, fft256, fft512, fft1024, - fft2048, fft4096, fft8192, fft16384, fft32768, fft65536, fft131072 -}; - -#define DECL_COMP_FFT(N) \ -static void compound_fft_##N##xM(AVTXContext *s, void *_out, \ - void *_in, ptrdiff_t stride) \ -{ \ - const int m = s->m, *in_map = s->pfatab, *out_map = in_map + N*m; \ - FFTComplex *in = _in; \ - FFTComplex *out = _out; \ - FFTComplex fft##N##in[N]; \ - void (*fftp)(FFTComplex *z) = fft_dispatch[av_log2(m) - 2]; \ - \ - for (int i = 0; i < m; i++) { \ - for (int j = 0; j < N; j++) \ - fft##N##in[j] = in[in_map[i*N + j]]; \ - fft##N(s->tmp + s->revtab[i], fft##N##in, m); \ - } \ - \ - for (int i = 0; i < N; i++) \ - fftp(s->tmp + m*i); \ - \ - for (int i = 0; i < N*m; i++) \ - out[i] = s->tmp[out_map[i]]; \ -} - -DECL_COMP_FFT(3) -DECL_COMP_FFT(5) -DECL_COMP_FFT(15) - -static void monolithic_fft(AVTXContext *s, void *_out, void *_in, - ptrdiff_t stride) -{ - FFTComplex *in = _in; - FFTComplex *out = _out; - int m = s->m, mb = av_log2(m) - 2; - for (int i = 0; i < m; i++) - out[s->revtab[i]] = in[i]; - fft_dispatch[mb](out); -} - -#define DECL_COMP_IMDCT(N) \ -static void compound_imdct_##N##xM(AVTXContext *s, void *_dst, void *_src, \ - ptrdiff_t stride) \ -{ \ - FFTComplex fft##N##in[N]; \ - FFTComplex *z = _dst, *exp = s->exptab; \ - const int m = s->m, len8 = N*m >> 1; \ - const int *in_map = s->pfatab, *out_map = in_map + N*m; \ - const float *src = _src, *in1, *in2; \ - void (*fftp)(FFTComplex *) = fft_dispatch[av_log2(m) - 2]; \ - \ - stride /= sizeof(*src); /* To convert it from bytes */ \ - in1 = src; \ - in2 = src + ((N*m*2) - 1) * stride; \ - \ - for (int i = 0; i < m; i++) { \ - for (int j = 0; j < N; j++) { \ - const int k = in_map[i*N + j]; \ - FFTComplex tmp = { in2[-k*stride], in1[k*stride] }; \ - CMUL3(fft##N##in[j], tmp, exp[k >> 1]); \ - } \ - fft##N(s->tmp + s->revtab[i], fft##N##in, m); \ - } \ - \ - for (int i = 0; i < N; i++) \ - fftp(s->tmp + m*i); \ - \ - for (int i = 0; i < len8; i++) { \ - const int i0 = len8 + i, i1 = len8 - i - 1; \ - const int s0 = out_map[i0], s1 = out_map[i1]; \ - FFTComplex src1 = { s->tmp[s1].im, s->tmp[s1].re }; \ - FFTComplex src0 = { s->tmp[s0].im, s->tmp[s0].re }; \ - \ - CMUL(z[i1].re, z[i0].im, src1.re, src1.im, exp[i1].im, exp[i1].re); \ - CMUL(z[i0].re, z[i1].im, src0.re, src0.im, exp[i0].im, exp[i0].re); \ - } \ -} - -DECL_COMP_IMDCT(3) -DECL_COMP_IMDCT(5) -DECL_COMP_IMDCT(15) - -#define DECL_COMP_MDCT(N) \ -static void compound_mdct_##N##xM(AVTXContext *s, void *_dst, void *_src, \ - ptrdiff_t stride) \ -{ \ - float *src = _src, *dst = _dst; \ - FFTComplex *exp = s->exptab, tmp, fft##N##in[N]; \ - const int m = s->m, len4 = N*m, len3 = len4 * 3, len8 = len4 >> 1; \ - const int *in_map = s->pfatab, *out_map = in_map + N*m; \ - void (*fftp)(FFTComplex *) = fft_dispatch[av_log2(m) - 2]; \ - \ - stride /= sizeof(*dst); \ - \ - for (int i = 0; i < m; i++) { /* Folding and pre-reindexing */ \ - for (int j = 0; j < N; j++) { \ - const int k = in_map[i*N + j]; \ - if (k < len4) { \ - tmp.re = -src[ len4 + k] + src[1*len4 - 1 - k]; \ - tmp.im = -src[ len3 + k] - src[1*len3 - 1 - k]; \ - } else { \ - tmp.re = -src[ len4 + k] - src[5*len4 - 1 - k]; \ - tmp.im = src[-len4 + k] - src[1*len3 - 1 - k]; \ - } \ - CMUL(fft##N##in[j].im, fft##N##in[j].re, tmp.re, tmp.im, \ - exp[k >> 1].re, exp[k >> 1].im); \ - } \ - fft##N(s->tmp + s->revtab[i], fft##N##in, m); \ - } \ - \ - for (int i = 0; i < N; i++) \ - fftp(s->tmp + m*i); \ - \ - for (int i = 0; i < len8; i++) { \ - const int i0 = len8 + i, i1 = len8 - i - 1; \ - const int s0 = out_map[i0], s1 = out_map[i1]; \ - FFTComplex src1 = { s->tmp[s1].re, s->tmp[s1].im }; \ - FFTComplex src0 = { s->tmp[s0].re, s->tmp[s0].im }; \ - \ - CMUL(dst[2*i1*stride + stride], dst[2*i0*stride], src0.re, src0.im, \ - exp[i0].im, exp[i0].re); \ - CMUL(dst[2*i0*stride + stride], dst[2*i1*stride], src1.re, src1.im, \ - exp[i1].im, exp[i1].re); \ - } \ -} - -DECL_COMP_MDCT(3) -DECL_COMP_MDCT(5) -DECL_COMP_MDCT(15) - -static void monolithic_imdct(AVTXContext *s, void *_dst, void *_src, - ptrdiff_t stride) -{ - FFTComplex *z = _dst, *exp = s->exptab; - const int m = s->m, len8 = m >> 1; - const float *src = _src, *in1, *in2; - void (*fftp)(FFTComplex *) = fft_dispatch[av_log2(m) - 2]; - - stride /= sizeof(*src); - in1 = src; - in2 = src + ((m*2) - 1) * stride; - - for (int i = 0; i < m; i++) { - FFTComplex tmp = { in2[-2*i*stride], in1[2*i*stride] }; - CMUL3(z[s->revtab[i]], tmp, exp[i]); - } - - fftp(z); - - for (int i = 0; i < len8; i++) { - const int i0 = len8 + i, i1 = len8 - i - 1; - FFTComplex src1 = { z[i1].im, z[i1].re }; - FFTComplex src0 = { z[i0].im, z[i0].re }; - - CMUL(z[i1].re, z[i0].im, src1.re, src1.im, exp[i1].im, exp[i1].re); - CMUL(z[i0].re, z[i1].im, src0.re, src0.im, exp[i0].im, exp[i0].re); - } -} - -static void monolithic_mdct(AVTXContext *s, void *_dst, void *_src, - ptrdiff_t stride) -{ - float *src = _src, *dst = _dst; - FFTComplex *exp = s->exptab, tmp, *z = _dst; - const int m = s->m, len4 = m, len3 = len4 * 3, len8 = len4 >> 1; - void (*fftp)(FFTComplex *) = fft_dispatch[av_log2(m) - 2]; - - stride /= sizeof(*dst); - - for (int i = 0; i < m; i++) { /* Folding and pre-reindexing */ - const int k = 2*i; - if (k < len4) { - tmp.re = -src[ len4 + k] + src[1*len4 - 1 - k]; - tmp.im = -src[ len3 + k] - src[1*len3 - 1 - k]; - } else { - tmp.re = -src[ len4 + k] - src[5*len4 - 1 - k]; - tmp.im = src[-len4 + k] - src[1*len3 - 1 - k]; - } - CMUL(z[s->revtab[i]].im, z[s->revtab[i]].re, tmp.re, tmp.im, - exp[i].re, exp[i].im); - } - - fftp(z); - - for (int i = 0; i < len8; i++) { - const int i0 = len8 + i, i1 = len8 - i - 1; - FFTComplex src1 = { z[i1].re, z[i1].im }; - FFTComplex src0 = { z[i0].re, z[i0].im }; - - CMUL(dst[2*i1*stride + stride], dst[2*i0*stride], src0.re, src0.im, - exp[i0].im, exp[i0].re); - CMUL(dst[2*i0*stride + stride], dst[2*i1*stride], src1.re, src1.im, - exp[i1].im, exp[i1].re); + switch (type) { + case AV_TX_FLOAT_MDCT: + case AV_TX_DOUBLE_MDCT: + case AV_TX_INT32_MDCT: + return 1; + default: + return 0; } } /* Calculates the modular multiplicative inverse, not fast, replace */ -static int mulinv(int n, int m) +static av_always_inline int mulinv(int n, int m) { n = n % m; for (int x = 1; x < m; x++) @@ -601,14 +41,16 @@ } /* Guaranteed to work for any n, m where gcd(n, m) == 1 */ -static int gen_compound_mapping(AVTXContext *s, int n, int m, int inv, - enum AVTXType type) +int ff_tx_gen_compound_mapping(AVTXContext *s) { int *in_map, *out_map; + const int n = s->n; + const int m = s->m; + const int inv = s->inv; const int len = n*m; const int m_inv = mulinv(m, n); const int n_inv = mulinv(n, m); - const int mdct = type == AV_TX_FLOAT_MDCT; + const int mdct = ff_tx_type_is_mdct(s->type); if (!(s->pfatab = av_malloc(2*len*sizeof(*s->pfatab)))) return AVERROR(ENOMEM); @@ -619,7 +61,7 @@ /* Ruritanian map for input, CRT map for output, can be swapped */ for (int j = 0; j < m; j++) { for (int i = 0; i < n; i++) { - /* Shifted by 1 to simplify forward MDCTs */ + /* Shifted by 1 to simplify MDCTs */ in_map[j*n + i] = ((i*m + j*n) % len) << mdct; out_map[(i*m*m_inv + j*n*n_inv) % len] = i*m + j; } @@ -649,49 +91,55 @@ return 0; } -static int split_radix_permutation(int i, int n, int inverse) +int ff_tx_gen_ptwo_revtab(AVTXContext *s, int invert_lookup) { - int m; - if (n <= 2) - return i & 1; - m = n >> 1; - if (!(i & m)) - return split_radix_permutation(i, m, inverse)*2; - m >>= 1; - if (inverse == !(i & m)) - return split_radix_permutation(i, m, inverse)*4 + 1; - else - return split_radix_permutation(i, m, inverse)*4 - 1; -} + const int m = s->m, inv = s->inv; -static int get_ptwo_revtab(AVTXContext *s, int m, int inv) -{ if (!(s->revtab = av_malloc(m*sizeof(*s->revtab)))) return AVERROR(ENOMEM); /* Default */ for (int i = 0; i < m; i++) { int k = -split_radix_permutation(i, m, inv) & (m - 1); - s->revtab[k] = i; + if (invert_lookup) + s->revtab[i] = k; + else + s->revtab[k] = i; } return 0; } -static int gen_mdct_exptab(AVTXContext *s, int len4, double scale) +int ff_tx_gen_ptwo_inplace_revtab_idx(AVTXContext *s) { - const double theta = (scale < 0 ? len4 : 0) + 1.0/8.0; + int nb_inplace_idx = 0; - if (!(s->exptab = av_malloc_array(len4, sizeof(*s->exptab)))) + if (!(s->inplace_idx = av_malloc(s->m*sizeof(*s->inplace_idx)))) return AVERROR(ENOMEM); - scale = sqrt(fabs(scale)); - for (int i = 0; i < len4; i++) { - const double alpha = M_PI_2 * (i + theta) / len4; - s->exptab[i].re = cos(alpha) * scale; - s->exptab[i].im = sin(alpha) * scale; + for (int src = 1; src < s->m; src++) { + int dst = s->revtab[src]; + int found = 0; + + if (dst <= src) + continue; + + do { + for (int j = 0; j < nb_inplace_idx; j++) { + if (dst == s->inplace_idx[j]) { + found = 1; + break; + } + } + dst = s->revtab[dst]; + } while (dst != src && !found); + + if (!found) + s->inplace_idx[nb_inplace_idx++] = src; } + s->inplace_idx[nb_inplace_idx++] = 0; + return 0; } @@ -703,76 +151,12 @@ av_free((*ctx)->pfatab); av_free((*ctx)->exptab); av_free((*ctx)->revtab); + av_free((*ctx)->inplace_idx); av_free((*ctx)->tmp); av_freep(ctx); } -static int init_mdct_fft(AVTXContext *s, av_tx_fn *tx, enum AVTXType type, - int inv, int len, const void *scale, uint64_t flags) -{ - int err, n = 1, m = 1, max_ptwo = 1 << (FF_ARRAY_ELEMS(fft_dispatch) + 1); - - if (type == AV_TX_FLOAT_MDCT) - len >>= 1; - -#define CHECK_FACTOR(DST, FACTOR, SRC) \ - if (DST == 1 && !(SRC % FACTOR)) { \ - DST = FACTOR; \ - SRC /= FACTOR; \ - } - CHECK_FACTOR(n, 15, len) - CHECK_FACTOR(n, 5, len) - CHECK_FACTOR(n, 3, len) -#undef CHECK_NPTWO_FACTOR - - /* len must be a power of two now */ - if (!(len & (len - 1)) && len >= 4 && len <= max_ptwo) { - m = len; - len = 1; - } - - /* Filter out direct 3, 5 and 15 transforms, too niche */ - if (len > 1 || m == 1) { - av_log(NULL, AV_LOG_ERROR, "Unsupported transform size: n = %i, " - "m = %i, residual = %i!\n", n, m, len); - return AVERROR(EINVAL); - } else if (n > 1 && m > 1) { /* 2D transform case */ - if ((err = gen_compound_mapping(s, n, m, inv, type))) - return err; - if (!(s->tmp = av_malloc(n*m*sizeof(*s->tmp)))) - return AVERROR(ENOMEM); - *tx = n == 3 ? compound_fft_3xM : - n == 5 ? compound_fft_5xM : - compound_fft_15xM; - if (type == AV_TX_FLOAT_MDCT) - *tx = n == 3 ? inv ? compound_imdct_3xM : compound_mdct_3xM : - n == 5 ? inv ? compound_imdct_5xM : compound_mdct_5xM : - inv ? compound_imdct_15xM : compound_mdct_15xM; - } else { /* Direct transform case */ - *tx = monolithic_fft; - if (type == AV_TX_FLOAT_MDCT) - *tx = inv ? monolithic_imdct : monolithic_mdct; - } - - if (n != 1) - ff_thread_once(&tabs_53_once, ff_init_53_tabs); - if (m != 1) { - get_ptwo_revtab(s, m, inv); - for (int i = 4; i <= av_log2(m); i++) - ff_init_ff_cos_tabs(i); - } - - if (type == AV_TX_FLOAT_MDCT) - if ((err = gen_mdct_exptab(s, n*m, *((float *)scale)))) - return err; - - s->n = n; - s->m = m; - - return 0; -} - av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags) { @@ -784,7 +168,17 @@ switch (type) { case AV_TX_FLOAT_FFT: case AV_TX_FLOAT_MDCT: - if ((err = init_mdct_fft(s, tx, type, inv, len, scale, flags))) + if ((err = ff_tx_init_mdct_fft_float(s, tx, type, inv, len, scale, flags))) + goto fail; + break; + case AV_TX_DOUBLE_FFT: + case AV_TX_DOUBLE_MDCT: + if ((err = ff_tx_init_mdct_fft_double(s, tx, type, inv, len, scale, flags))) + goto fail; + break; + case AV_TX_INT32_FFT: + case AV_TX_INT32_MDCT: + if ((err = ff_tx_init_mdct_fft_int32(s, tx, type, inv, len, scale, flags))) goto fail; break; default: diff -Nru ffmpeg-4.2.2/libavutil/tx_double.c ffmpeg-4.4/libavutil/tx_double.c --- ffmpeg-4.2.2/libavutil/tx_double.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/tx_double.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,21 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define TX_DOUBLE +#include "tx_priv.h" +#include "tx_template.c" diff -Nru ffmpeg-4.2.2/libavutil/tx_float.c ffmpeg-4.4/libavutil/tx_float.c --- ffmpeg-4.2.2/libavutil/tx_float.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/tx_float.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,21 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define TX_FLOAT +#include "tx_priv.h" +#include "tx_template.c" diff -Nru ffmpeg-4.2.2/libavutil/tx.h ffmpeg-4.4/libavutil/tx.h --- ffmpeg-4.2.2/libavutil/tx.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/tx.h 2021-04-08 21:28:40.000000000 +0000 @@ -28,17 +28,57 @@ float re, im; } AVComplexFloat; +typedef struct AVComplexDouble { + double re, im; +} AVComplexDouble; + +typedef struct AVComplexInt32 { + int32_t re, im; +} AVComplexInt32; + enum AVTXType { /** * Standard complex to complex FFT with sample data type AVComplexFloat. - * Scaling currently unsupported + * Output is not 1/len normalized. Scaling currently unsupported. + * The stride parameter is ignored. */ AV_TX_FLOAT_FFT = 0, + /** * Standard MDCT with sample data type of float and a scale type of * float. Length is the frame size, not the window size (which is 2x frame) + * For forward transforms, the stride specifies the spacing between each + * sample in the output array in bytes. The input must be a flat array. + * For inverse transforms, the stride specifies the spacing between each + * sample in the input array in bytes. The output will be a flat array. + * Stride must be a non-zero multiple of sizeof(float). + * NOTE: the inverse transform is half-length, meaning the output will not + * contain redundant data. This is what most codecs work with. */ AV_TX_FLOAT_MDCT = 1, + + /** + * Same as AV_TX_FLOAT_FFT with a data type of AVComplexDouble. + */ + AV_TX_DOUBLE_FFT = 2, + + /** + * Same as AV_TX_FLOAT_MDCT with data and scale type of double. + * Stride must be a non-zero multiple of sizeof(double). + */ + AV_TX_DOUBLE_MDCT = 3, + + /** + * Same as AV_TX_FLOAT_FFT with a data type of AVComplexInt32. + */ + AV_TX_INT32_FFT = 4, + + /** + * Same as AV_TX_FLOAT_MDCT with data type of int32_t and scale type of float. + * Only scale values less than or equal to 1.0 are supported. + * Stride must be a non-zero multiple of sizeof(int32_t). + */ + AV_TX_INT32_MDCT = 5, }; /** @@ -50,15 +90,29 @@ * @param s the transform context * @param out the output array * @param in the input array - * @param stride the input or output stride (depending on transform direction) - * in bytes, currently implemented for all MDCT transforms + * @param stride the input or output stride in bytes + * + * The out and in arrays must be aligned to the maximum required by the CPU + * architecture. + * The stride must follow the constraints the transform type has specified. */ typedef void (*av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride); /** + * Flags for av_tx_init() + */ +enum AVTXFlags { + /** + * Performs an in-place transformation on the input. The output argument + * of av_tn_fn() MUST match the input. May be unsupported or slower for some + * transform types. + */ + AV_TX_INPLACE = 1ULL << 0, +}; + +/** * Initialize a transform context with the given configuration - * Currently power of two lengths from 4 to 131072 are supported, along with - * any length decomposable to a power of two and either 3, 5 or 15. + * (i)MDCTs with an odd length are currently not supported. * * @param ctx the context to allocate, will be NULL on error * @param tx pointer to the transform function pointer to set @@ -66,7 +120,7 @@ * @param inv whether to do an inverse or a forward transform * @param len the size of the transform in samples * @param scale pointer to the value to scale the output if supported by type - * @param flags currently unused + * @param flags a bitmask of AVTXFlags or 0 * * @return 0 on success, negative error code on failure */ diff -Nru ffmpeg-4.2.2/libavutil/tx_int32.c ffmpeg-4.4/libavutil/tx_int32.c --- ffmpeg-4.2.2/libavutil/tx_int32.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/tx_int32.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,21 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define TX_INT32 +#include "tx_priv.h" +#include "tx_template.c" diff -Nru ffmpeg-4.2.2/libavutil/tx_priv.h ffmpeg-4.4/libavutil/tx_priv.h --- ffmpeg-4.2.2/libavutil/tx_priv.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/tx_priv.h 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,161 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_TX_PRIV_H +#define AVUTIL_TX_PRIV_H + +#include "tx.h" +#include +#include "thread.h" +#include "mem.h" +#include "mem_internal.h" +#include "avassert.h" +#include "attributes.h" + +#ifdef TX_FLOAT +#define TX_NAME(x) x ## _float +#define SCALE_TYPE float +typedef float FFTSample; +typedef AVComplexFloat FFTComplex; +#elif defined(TX_DOUBLE) +#define TX_NAME(x) x ## _double +#define SCALE_TYPE double +typedef double FFTSample; +typedef AVComplexDouble FFTComplex; +#elif defined(TX_INT32) +#define TX_NAME(x) x ## _int32 +#define SCALE_TYPE float +typedef int32_t FFTSample; +typedef AVComplexInt32 FFTComplex; +#else +typedef void FFTComplex; +#endif + +#if defined(TX_FLOAT) || defined(TX_DOUBLE) + +#define CMUL(dre, dim, are, aim, bre, bim) do { \ + (dre) = (are) * (bre) - (aim) * (bim); \ + (dim) = (are) * (bim) + (aim) * (bre); \ + } while (0) + +#define SMUL(dre, dim, are, aim, bre, bim) do { \ + (dre) = (are) * (bre) - (aim) * (bim); \ + (dim) = (are) * (bim) - (aim) * (bre); \ + } while (0) + +#define UNSCALE(x) (x) +#define RESCALE(x) (x) + +#define FOLD(a, b) ((a) + (b)) + +#elif defined(TX_INT32) + +/* Properly rounds the result */ +#define CMUL(dre, dim, are, aim, bre, bim) do { \ + int64_t accu; \ + (accu) = (int64_t)(bre) * (are); \ + (accu) -= (int64_t)(bim) * (aim); \ + (dre) = (int)(((accu) + 0x40000000) >> 31); \ + (accu) = (int64_t)(bim) * (are); \ + (accu) += (int64_t)(bre) * (aim); \ + (dim) = (int)(((accu) + 0x40000000) >> 31); \ + } while (0) + +#define SMUL(dre, dim, are, aim, bre, bim) do { \ + int64_t accu; \ + (accu) = (int64_t)(bre) * (are); \ + (accu) -= (int64_t)(bim) * (aim); \ + (dre) = (int)(((accu) + 0x40000000) >> 31); \ + (accu) = (int64_t)(bim) * (are); \ + (accu) -= (int64_t)(bre) * (aim); \ + (dim) = (int)(((accu) + 0x40000000) >> 31); \ + } while (0) + +#define UNSCALE(x) ((double)x/2147483648.0) +#define RESCALE(x) (av_clip64(lrintf((x) * 2147483648.0), INT32_MIN, INT32_MAX)) + +#define FOLD(x, y) ((int)((x) + (unsigned)(y) + 32) >> 6) + +#endif + +#define BF(x, y, a, b) do { \ + x = (a) - (b); \ + y = (a) + (b); \ + } while (0) + +#define CMUL3(c, a, b) \ + CMUL((c).re, (c).im, (a).re, (a).im, (b).re, (b).im) + +#define COSTABLE(size) \ + DECLARE_ALIGNED(32, FFTSample, TX_NAME(ff_cos_##size))[size/2] + +/* Used by asm, reorder with care */ +struct AVTXContext { + int n; /* Non-power-of-two part */ + int m; /* Power-of-two part */ + int inv; /* Is inverse */ + int type; /* Type */ + uint64_t flags; /* Flags */ + double scale; /* Scale */ + + FFTComplex *exptab; /* MDCT exptab */ + FFTComplex *tmp; /* Temporary buffer needed for all compound transforms */ + int *pfatab; /* Input/Output mapping for compound transforms */ + int *revtab; /* Input mapping for power of two transforms */ + int *inplace_idx; /* Required indices to revtab for in-place transforms */ +}; + +/* Shared functions */ +int ff_tx_type_is_mdct(enum AVTXType type); +int ff_tx_gen_compound_mapping(AVTXContext *s); +int ff_tx_gen_ptwo_revtab(AVTXContext *s, int invert_lookup); +int ff_tx_gen_ptwo_inplace_revtab_idx(AVTXContext *s); + +/* Also used by SIMD init */ +static inline int split_radix_permutation(int i, int n, int inverse) +{ + int m; + if (n <= 2) + return i & 1; + m = n >> 1; + if (!(i & m)) + return split_radix_permutation(i, m, inverse)*2; + m >>= 1; + if (inverse == !(i & m)) + return split_radix_permutation(i, m, inverse)*4 + 1; + else + return split_radix_permutation(i, m, inverse)*4 - 1; +} + +/* Templated functions */ +int ff_tx_init_mdct_fft_float(AVTXContext *s, av_tx_fn *tx, + enum AVTXType type, int inv, int len, + const void *scale, uint64_t flags); +int ff_tx_init_mdct_fft_double(AVTXContext *s, av_tx_fn *tx, + enum AVTXType type, int inv, int len, + const void *scale, uint64_t flags); +int ff_tx_init_mdct_fft_int32(AVTXContext *s, av_tx_fn *tx, + enum AVTXType type, int inv, int len, + const void *scale, uint64_t flags); + +typedef struct CosTabsInitOnce { + void (*func)(void); + AVOnce control; +} CosTabsInitOnce; + +#endif /* AVUTIL_TX_PRIV_H */ diff -Nru ffmpeg-4.2.2/libavutil/tx_template.c ffmpeg-4.4/libavutil/tx_template.c --- ffmpeg-4.2.2/libavutil/tx_template.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/tx_template.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,757 @@ +/* + * Copyright (c) 2019 Lynne + * Power of two FFT: + * Copyright (c) 2008 Loren Merritt + * Copyright (c) 2002 Fabrice Bellard + * Partly based on libdjbfft by D. J. Bernstein + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* All costabs for a type are defined here */ +COSTABLE(16); +COSTABLE(32); +COSTABLE(64); +COSTABLE(128); +COSTABLE(256); +COSTABLE(512); +COSTABLE(1024); +COSTABLE(2048); +COSTABLE(4096); +COSTABLE(8192); +COSTABLE(16384); +COSTABLE(32768); +COSTABLE(65536); +COSTABLE(131072); +DECLARE_ALIGNED(32, FFTComplex, TX_NAME(ff_cos_53))[4]; + +static FFTSample * const cos_tabs[18] = { + NULL, + NULL, + NULL, + NULL, + TX_NAME(ff_cos_16), + TX_NAME(ff_cos_32), + TX_NAME(ff_cos_64), + TX_NAME(ff_cos_128), + TX_NAME(ff_cos_256), + TX_NAME(ff_cos_512), + TX_NAME(ff_cos_1024), + TX_NAME(ff_cos_2048), + TX_NAME(ff_cos_4096), + TX_NAME(ff_cos_8192), + TX_NAME(ff_cos_16384), + TX_NAME(ff_cos_32768), + TX_NAME(ff_cos_65536), + TX_NAME(ff_cos_131072), +}; + +static av_always_inline void init_cos_tabs_idx(int index) +{ + int m = 1 << index; + double freq = 2*M_PI/m; + FFTSample *tab = cos_tabs[index]; + for(int i = 0; i <= m/4; i++) + tab[i] = RESCALE(cos(i*freq)); + for(int i = 1; i < m/4; i++) + tab[m/2 - i] = tab[i]; +} + +#define INIT_FF_COS_TABS_FUNC(index, size) \ +static av_cold void init_cos_tabs_ ## size (void) \ +{ \ + init_cos_tabs_idx(index); \ +} + +INIT_FF_COS_TABS_FUNC(4, 16) +INIT_FF_COS_TABS_FUNC(5, 32) +INIT_FF_COS_TABS_FUNC(6, 64) +INIT_FF_COS_TABS_FUNC(7, 128) +INIT_FF_COS_TABS_FUNC(8, 256) +INIT_FF_COS_TABS_FUNC(9, 512) +INIT_FF_COS_TABS_FUNC(10, 1024) +INIT_FF_COS_TABS_FUNC(11, 2048) +INIT_FF_COS_TABS_FUNC(12, 4096) +INIT_FF_COS_TABS_FUNC(13, 8192) +INIT_FF_COS_TABS_FUNC(14, 16384) +INIT_FF_COS_TABS_FUNC(15, 32768) +INIT_FF_COS_TABS_FUNC(16, 65536) +INIT_FF_COS_TABS_FUNC(17, 131072) + +static av_cold void ff_init_53_tabs(void) +{ + TX_NAME(ff_cos_53)[0] = (FFTComplex){ RESCALE(cos(2 * M_PI / 12)), RESCALE(cos(2 * M_PI / 12)) }; + TX_NAME(ff_cos_53)[1] = (FFTComplex){ RESCALE(cos(2 * M_PI / 6)), RESCALE(cos(2 * M_PI / 6)) }; + TX_NAME(ff_cos_53)[2] = (FFTComplex){ RESCALE(cos(2 * M_PI / 5)), RESCALE(sin(2 * M_PI / 5)) }; + TX_NAME(ff_cos_53)[3] = (FFTComplex){ RESCALE(cos(2 * M_PI / 10)), RESCALE(sin(2 * M_PI / 10)) }; +} + +static CosTabsInitOnce cos_tabs_init_once[] = { + { ff_init_53_tabs, AV_ONCE_INIT }, + { NULL }, + { NULL }, + { NULL }, + { init_cos_tabs_16, AV_ONCE_INIT }, + { init_cos_tabs_32, AV_ONCE_INIT }, + { init_cos_tabs_64, AV_ONCE_INIT }, + { init_cos_tabs_128, AV_ONCE_INIT }, + { init_cos_tabs_256, AV_ONCE_INIT }, + { init_cos_tabs_512, AV_ONCE_INIT }, + { init_cos_tabs_1024, AV_ONCE_INIT }, + { init_cos_tabs_2048, AV_ONCE_INIT }, + { init_cos_tabs_4096, AV_ONCE_INIT }, + { init_cos_tabs_8192, AV_ONCE_INIT }, + { init_cos_tabs_16384, AV_ONCE_INIT }, + { init_cos_tabs_32768, AV_ONCE_INIT }, + { init_cos_tabs_65536, AV_ONCE_INIT }, + { init_cos_tabs_131072, AV_ONCE_INIT }, +}; + +static av_cold void init_cos_tabs(int index) +{ + ff_thread_once(&cos_tabs_init_once[index].control, + cos_tabs_init_once[index].func); +} + +static av_always_inline void fft3(FFTComplex *out, FFTComplex *in, + ptrdiff_t stride) +{ + FFTComplex tmp[2]; +#ifdef TX_INT32 + int64_t mtmp[4]; +#endif + + BF(tmp[0].re, tmp[1].im, in[1].im, in[2].im); + BF(tmp[0].im, tmp[1].re, in[1].re, in[2].re); + + out[0*stride].re = in[0].re + tmp[1].re; + out[0*stride].im = in[0].im + tmp[1].im; + +#ifdef TX_INT32 + mtmp[0] = (int64_t)TX_NAME(ff_cos_53)[0].re * tmp[0].re; + mtmp[1] = (int64_t)TX_NAME(ff_cos_53)[0].im * tmp[0].im; + mtmp[2] = (int64_t)TX_NAME(ff_cos_53)[1].re * tmp[1].re; + mtmp[3] = (int64_t)TX_NAME(ff_cos_53)[1].re * tmp[1].im; + out[1*stride].re = in[0].re - (mtmp[2] + mtmp[0] + 0x40000000 >> 31); + out[1*stride].im = in[0].im - (mtmp[3] - mtmp[1] + 0x40000000 >> 31); + out[2*stride].re = in[0].re - (mtmp[2] - mtmp[0] + 0x40000000 >> 31); + out[2*stride].im = in[0].im - (mtmp[3] + mtmp[1] + 0x40000000 >> 31); +#else + tmp[0].re = TX_NAME(ff_cos_53)[0].re * tmp[0].re; + tmp[0].im = TX_NAME(ff_cos_53)[0].im * tmp[0].im; + tmp[1].re = TX_NAME(ff_cos_53)[1].re * tmp[1].re; + tmp[1].im = TX_NAME(ff_cos_53)[1].re * tmp[1].im; + out[1*stride].re = in[0].re - tmp[1].re + tmp[0].re; + out[1*stride].im = in[0].im - tmp[1].im - tmp[0].im; + out[2*stride].re = in[0].re - tmp[1].re - tmp[0].re; + out[2*stride].im = in[0].im - tmp[1].im + tmp[0].im; +#endif +} + +#define DECL_FFT5(NAME, D0, D1, D2, D3, D4) \ +static av_always_inline void NAME(FFTComplex *out, FFTComplex *in, \ + ptrdiff_t stride) \ +{ \ + FFTComplex z0[4], t[6]; \ + \ + BF(t[1].im, t[0].re, in[1].re, in[4].re); \ + BF(t[1].re, t[0].im, in[1].im, in[4].im); \ + BF(t[3].im, t[2].re, in[2].re, in[3].re); \ + BF(t[3].re, t[2].im, in[2].im, in[3].im); \ + \ + out[D0*stride].re = in[0].re + t[0].re + t[2].re; \ + out[D0*stride].im = in[0].im + t[0].im + t[2].im; \ + \ + SMUL(t[4].re, t[0].re, TX_NAME(ff_cos_53)[2].re, TX_NAME(ff_cos_53)[3].re, t[2].re, t[0].re); \ + SMUL(t[4].im, t[0].im, TX_NAME(ff_cos_53)[2].re, TX_NAME(ff_cos_53)[3].re, t[2].im, t[0].im); \ + CMUL(t[5].re, t[1].re, TX_NAME(ff_cos_53)[2].im, TX_NAME(ff_cos_53)[3].im, t[3].re, t[1].re); \ + CMUL(t[5].im, t[1].im, TX_NAME(ff_cos_53)[2].im, TX_NAME(ff_cos_53)[3].im, t[3].im, t[1].im); \ + \ + BF(z0[0].re, z0[3].re, t[0].re, t[1].re); \ + BF(z0[0].im, z0[3].im, t[0].im, t[1].im); \ + BF(z0[2].re, z0[1].re, t[4].re, t[5].re); \ + BF(z0[2].im, z0[1].im, t[4].im, t[5].im); \ + \ + out[D1*stride].re = in[0].re + z0[3].re; \ + out[D1*stride].im = in[0].im + z0[0].im; \ + out[D2*stride].re = in[0].re + z0[2].re; \ + out[D2*stride].im = in[0].im + z0[1].im; \ + out[D3*stride].re = in[0].re + z0[1].re; \ + out[D3*stride].im = in[0].im + z0[2].im; \ + out[D4*stride].re = in[0].re + z0[0].re; \ + out[D4*stride].im = in[0].im + z0[3].im; \ +} + +DECL_FFT5(fft5, 0, 1, 2, 3, 4) +DECL_FFT5(fft5_m1, 0, 6, 12, 3, 9) +DECL_FFT5(fft5_m2, 10, 1, 7, 13, 4) +DECL_FFT5(fft5_m3, 5, 11, 2, 8, 14) + +static av_always_inline void fft15(FFTComplex *out, FFTComplex *in, + ptrdiff_t stride) +{ + FFTComplex tmp[15]; + + for (int i = 0; i < 5; i++) + fft3(tmp + i, in + i*3, 5); + + fft5_m1(out, tmp + 0, stride); + fft5_m2(out, tmp + 5, stride); + fft5_m3(out, tmp + 10, stride); +} + +#define BUTTERFLIES(a0,a1,a2,a3) {\ + BF(t3, t5, t5, t1);\ + BF(a2.re, a0.re, a0.re, t5);\ + BF(a3.im, a1.im, a1.im, t3);\ + BF(t4, t6, t2, t6);\ + BF(a3.re, a1.re, a1.re, t4);\ + BF(a2.im, a0.im, a0.im, t6);\ +} + +// force loading all the inputs before storing any. +// this is slightly slower for small data, but avoids store->load aliasing +// for addresses separated by large powers of 2. +#define BUTTERFLIES_BIG(a0,a1,a2,a3) {\ + FFTSample r0=a0.re, i0=a0.im, r1=a1.re, i1=a1.im;\ + BF(t3, t5, t5, t1);\ + BF(a2.re, a0.re, r0, t5);\ + BF(a3.im, a1.im, i1, t3);\ + BF(t4, t6, t2, t6);\ + BF(a3.re, a1.re, r1, t4);\ + BF(a2.im, a0.im, i0, t6);\ +} + +#define TRANSFORM(a0,a1,a2,a3,wre,wim) {\ + CMUL(t1, t2, a2.re, a2.im, wre, -wim);\ + CMUL(t5, t6, a3.re, a3.im, wre, wim);\ + BUTTERFLIES(a0,a1,a2,a3)\ +} + +#define TRANSFORM_ZERO(a0,a1,a2,a3) {\ + t1 = a2.re;\ + t2 = a2.im;\ + t5 = a3.re;\ + t6 = a3.im;\ + BUTTERFLIES(a0,a1,a2,a3)\ +} + +/* z[0...8n-1], w[1...2n-1] */ +#define PASS(name)\ +static void name(FFTComplex *z, const FFTSample *wre, unsigned int n)\ +{\ + FFTSample t1, t2, t3, t4, t5, t6;\ + int o1 = 2*n;\ + int o2 = 4*n;\ + int o3 = 6*n;\ + const FFTSample *wim = wre+o1;\ + n--;\ +\ + TRANSFORM_ZERO(z[0],z[o1],z[o2],z[o3]);\ + TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]);\ + do {\ + z += 2;\ + wre += 2;\ + wim -= 2;\ + TRANSFORM(z[0],z[o1],z[o2],z[o3],wre[0],wim[0]);\ + TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]);\ + } while(--n);\ +} + +PASS(pass) +#undef BUTTERFLIES +#define BUTTERFLIES BUTTERFLIES_BIG +PASS(pass_big) + +#define DECL_FFT(n,n2,n4)\ +static void fft##n(FFTComplex *z)\ +{\ + fft##n2(z);\ + fft##n4(z+n4*2);\ + fft##n4(z+n4*3);\ + pass(z,TX_NAME(ff_cos_##n),n4/2);\ +} + +static void fft2(FFTComplex *z) +{ + FFTComplex tmp; + BF(tmp.re, z[0].re, z[0].re, z[1].re); + BF(tmp.im, z[0].im, z[0].im, z[1].im); + z[1] = tmp; +} + +static void fft4(FFTComplex *z) +{ + FFTSample t1, t2, t3, t4, t5, t6, t7, t8; + + BF(t3, t1, z[0].re, z[1].re); + BF(t8, t6, z[3].re, z[2].re); + BF(z[2].re, z[0].re, t1, t6); + BF(t4, t2, z[0].im, z[1].im); + BF(t7, t5, z[2].im, z[3].im); + BF(z[3].im, z[1].im, t4, t8); + BF(z[3].re, z[1].re, t3, t7); + BF(z[2].im, z[0].im, t2, t5); +} + +static void fft8(FFTComplex *z) +{ + FFTSample t1, t2, t3, t4, t5, t6; + + fft4(z); + + BF(t1, z[5].re, z[4].re, -z[5].re); + BF(t2, z[5].im, z[4].im, -z[5].im); + BF(t5, z[7].re, z[6].re, -z[7].re); + BF(t6, z[7].im, z[6].im, -z[7].im); + + BUTTERFLIES(z[0],z[2],z[4],z[6]); + TRANSFORM(z[1],z[3],z[5],z[7],RESCALE(M_SQRT1_2),RESCALE(M_SQRT1_2)); +} + +static void fft16(FFTComplex *z) +{ + FFTSample t1, t2, t3, t4, t5, t6; + FFTSample cos_16_1 = TX_NAME(ff_cos_16)[1]; + FFTSample cos_16_3 = TX_NAME(ff_cos_16)[3]; + + fft8(z); + fft4(z+8); + fft4(z+12); + + TRANSFORM_ZERO(z[0],z[4],z[8],z[12]); + TRANSFORM(z[2],z[6],z[10],z[14],RESCALE(M_SQRT1_2),RESCALE(M_SQRT1_2)); + TRANSFORM(z[1],z[5],z[9],z[13],cos_16_1,cos_16_3); + TRANSFORM(z[3],z[7],z[11],z[15],cos_16_3,cos_16_1); +} + +DECL_FFT(32,16,8) +DECL_FFT(64,32,16) +DECL_FFT(128,64,32) +DECL_FFT(256,128,64) +DECL_FFT(512,256,128) +#define pass pass_big +DECL_FFT(1024,512,256) +DECL_FFT(2048,1024,512) +DECL_FFT(4096,2048,1024) +DECL_FFT(8192,4096,2048) +DECL_FFT(16384,8192,4096) +DECL_FFT(32768,16384,8192) +DECL_FFT(65536,32768,16384) +DECL_FFT(131072,65536,32768) + +static void (* const fft_dispatch[])(FFTComplex*) = { + NULL, fft2, fft4, fft8, fft16, fft32, fft64, fft128, fft256, fft512, + fft1024, fft2048, fft4096, fft8192, fft16384, fft32768, fft65536, fft131072 +}; + +#define DECL_COMP_FFT(N) \ +static void compound_fft_##N##xM(AVTXContext *s, void *_out, \ + void *_in, ptrdiff_t stride) \ +{ \ + const int m = s->m, *in_map = s->pfatab, *out_map = in_map + N*m; \ + FFTComplex *in = _in; \ + FFTComplex *out = _out; \ + FFTComplex fft##N##in[N]; \ + void (*fftp)(FFTComplex *z) = fft_dispatch[av_log2(m)]; \ + \ + for (int i = 0; i < m; i++) { \ + for (int j = 0; j < N; j++) \ + fft##N##in[j] = in[in_map[i*N + j]]; \ + fft##N(s->tmp + s->revtab[i], fft##N##in, m); \ + } \ + \ + for (int i = 0; i < N; i++) \ + fftp(s->tmp + m*i); \ + \ + for (int i = 0; i < N*m; i++) \ + out[i] = s->tmp[out_map[i]]; \ +} + +DECL_COMP_FFT(3) +DECL_COMP_FFT(5) +DECL_COMP_FFT(15) + +static void monolithic_fft(AVTXContext *s, void *_out, void *_in, + ptrdiff_t stride) +{ + FFTComplex *in = _in; + FFTComplex *out = _out; + int m = s->m, mb = av_log2(m); + + if (s->flags & AV_TX_INPLACE) { + FFTComplex tmp; + int src, dst, *inplace_idx = s->inplace_idx; + + src = *inplace_idx++; + + do { + tmp = out[src]; + dst = s->revtab[src]; + do { + FFSWAP(FFTComplex, tmp, out[dst]); + dst = s->revtab[dst]; + } while (dst != src); /* Can be > as well, but is less predictable */ + out[dst] = tmp; + } while ((src = *inplace_idx++)); + } else { + for (int i = 0; i < m; i++) + out[i] = in[s->revtab[i]]; + } + + fft_dispatch[mb](out); +} + +static void naive_fft(AVTXContext *s, void *_out, void *_in, + ptrdiff_t stride) +{ + FFTComplex *in = _in; + FFTComplex *out = _out; + const int n = s->n; + double phase = s->inv ? 2.0*M_PI/n : -2.0*M_PI/n; + + for(int i = 0; i < n; i++) { + FFTComplex tmp = { 0 }; + for(int j = 0; j < n; j++) { + const double factor = phase*i*j; + const FFTComplex mult = { + RESCALE(cos(factor)), + RESCALE(sin(factor)), + }; + FFTComplex res; + CMUL3(res, in[j], mult); + tmp.re += res.re; + tmp.im += res.im; + } + out[i] = tmp; + } +} + +#define DECL_COMP_IMDCT(N) \ +static void compound_imdct_##N##xM(AVTXContext *s, void *_dst, void *_src, \ + ptrdiff_t stride) \ +{ \ + FFTComplex fft##N##in[N]; \ + FFTComplex *z = _dst, *exp = s->exptab; \ + const int m = s->m, len8 = N*m >> 1; \ + const int *in_map = s->pfatab, *out_map = in_map + N*m; \ + const FFTSample *src = _src, *in1, *in2; \ + void (*fftp)(FFTComplex *) = fft_dispatch[av_log2(m)]; \ + \ + stride /= sizeof(*src); /* To convert it from bytes */ \ + in1 = src; \ + in2 = src + ((N*m*2) - 1) * stride; \ + \ + for (int i = 0; i < m; i++) { \ + for (int j = 0; j < N; j++) { \ + const int k = in_map[i*N + j]; \ + FFTComplex tmp = { in2[-k*stride], in1[k*stride] }; \ + CMUL3(fft##N##in[j], tmp, exp[k >> 1]); \ + } \ + fft##N(s->tmp + s->revtab[i], fft##N##in, m); \ + } \ + \ + for (int i = 0; i < N; i++) \ + fftp(s->tmp + m*i); \ + \ + for (int i = 0; i < len8; i++) { \ + const int i0 = len8 + i, i1 = len8 - i - 1; \ + const int s0 = out_map[i0], s1 = out_map[i1]; \ + FFTComplex src1 = { s->tmp[s1].im, s->tmp[s1].re }; \ + FFTComplex src0 = { s->tmp[s0].im, s->tmp[s0].re }; \ + \ + CMUL(z[i1].re, z[i0].im, src1.re, src1.im, exp[i1].im, exp[i1].re); \ + CMUL(z[i0].re, z[i1].im, src0.re, src0.im, exp[i0].im, exp[i0].re); \ + } \ +} + +DECL_COMP_IMDCT(3) +DECL_COMP_IMDCT(5) +DECL_COMP_IMDCT(15) + +#define DECL_COMP_MDCT(N) \ +static void compound_mdct_##N##xM(AVTXContext *s, void *_dst, void *_src, \ + ptrdiff_t stride) \ +{ \ + FFTSample *src = _src, *dst = _dst; \ + FFTComplex *exp = s->exptab, tmp, fft##N##in[N]; \ + const int m = s->m, len4 = N*m, len3 = len4 * 3, len8 = len4 >> 1; \ + const int *in_map = s->pfatab, *out_map = in_map + N*m; \ + void (*fftp)(FFTComplex *) = fft_dispatch[av_log2(m)]; \ + \ + stride /= sizeof(*dst); \ + \ + for (int i = 0; i < m; i++) { /* Folding and pre-reindexing */ \ + for (int j = 0; j < N; j++) { \ + const int k = in_map[i*N + j]; \ + if (k < len4) { \ + tmp.re = FOLD(-src[ len4 + k], src[1*len4 - 1 - k]); \ + tmp.im = FOLD(-src[ len3 + k], -src[1*len3 - 1 - k]); \ + } else { \ + tmp.re = FOLD(-src[ len4 + k], -src[5*len4 - 1 - k]); \ + tmp.im = FOLD( src[-len4 + k], -src[1*len3 - 1 - k]); \ + } \ + CMUL(fft##N##in[j].im, fft##N##in[j].re, tmp.re, tmp.im, \ + exp[k >> 1].re, exp[k >> 1].im); \ + } \ + fft##N(s->tmp + s->revtab[i], fft##N##in, m); \ + } \ + \ + for (int i = 0; i < N; i++) \ + fftp(s->tmp + m*i); \ + \ + for (int i = 0; i < len8; i++) { \ + const int i0 = len8 + i, i1 = len8 - i - 1; \ + const int s0 = out_map[i0], s1 = out_map[i1]; \ + FFTComplex src1 = { s->tmp[s1].re, s->tmp[s1].im }; \ + FFTComplex src0 = { s->tmp[s0].re, s->tmp[s0].im }; \ + \ + CMUL(dst[2*i1*stride + stride], dst[2*i0*stride], src0.re, src0.im, \ + exp[i0].im, exp[i0].re); \ + CMUL(dst[2*i0*stride + stride], dst[2*i1*stride], src1.re, src1.im, \ + exp[i1].im, exp[i1].re); \ + } \ +} + +DECL_COMP_MDCT(3) +DECL_COMP_MDCT(5) +DECL_COMP_MDCT(15) + +static void monolithic_imdct(AVTXContext *s, void *_dst, void *_src, + ptrdiff_t stride) +{ + FFTComplex *z = _dst, *exp = s->exptab; + const int m = s->m, len8 = m >> 1; + const FFTSample *src = _src, *in1, *in2; + void (*fftp)(FFTComplex *) = fft_dispatch[av_log2(m)]; + + stride /= sizeof(*src); + in1 = src; + in2 = src + ((m*2) - 1) * stride; + + for (int i = 0; i < m; i++) { + FFTComplex tmp = { in2[-2*i*stride], in1[2*i*stride] }; + CMUL3(z[s->revtab[i]], tmp, exp[i]); + } + + fftp(z); + + for (int i = 0; i < len8; i++) { + const int i0 = len8 + i, i1 = len8 - i - 1; + FFTComplex src1 = { z[i1].im, z[i1].re }; + FFTComplex src0 = { z[i0].im, z[i0].re }; + + CMUL(z[i1].re, z[i0].im, src1.re, src1.im, exp[i1].im, exp[i1].re); + CMUL(z[i0].re, z[i1].im, src0.re, src0.im, exp[i0].im, exp[i0].re); + } +} + +static void monolithic_mdct(AVTXContext *s, void *_dst, void *_src, + ptrdiff_t stride) +{ + FFTSample *src = _src, *dst = _dst; + FFTComplex *exp = s->exptab, tmp, *z = _dst; + const int m = s->m, len4 = m, len3 = len4 * 3, len8 = len4 >> 1; + void (*fftp)(FFTComplex *) = fft_dispatch[av_log2(m)]; + + stride /= sizeof(*dst); + + for (int i = 0; i < m; i++) { /* Folding and pre-reindexing */ + const int k = 2*i; + if (k < len4) { + tmp.re = FOLD(-src[ len4 + k], src[1*len4 - 1 - k]); + tmp.im = FOLD(-src[ len3 + k], -src[1*len3 - 1 - k]); + } else { + tmp.re = FOLD(-src[ len4 + k], -src[5*len4 - 1 - k]); + tmp.im = FOLD( src[-len4 + k], -src[1*len3 - 1 - k]); + } + CMUL(z[s->revtab[i]].im, z[s->revtab[i]].re, tmp.re, tmp.im, + exp[i].re, exp[i].im); + } + + fftp(z); + + for (int i = 0; i < len8; i++) { + const int i0 = len8 + i, i1 = len8 - i - 1; + FFTComplex src1 = { z[i1].re, z[i1].im }; + FFTComplex src0 = { z[i0].re, z[i0].im }; + + CMUL(dst[2*i1*stride + stride], dst[2*i0*stride], src0.re, src0.im, + exp[i0].im, exp[i0].re); + CMUL(dst[2*i0*stride + stride], dst[2*i1*stride], src1.re, src1.im, + exp[i1].im, exp[i1].re); + } +} + +static void naive_imdct(AVTXContext *s, void *_dst, void *_src, + ptrdiff_t stride) +{ + int len = s->n; + int len2 = len*2; + FFTSample *src = _src; + FFTSample *dst = _dst; + double scale = s->scale; + const double phase = M_PI/(4.0*len2); + + stride /= sizeof(*src); + + for (int i = 0; i < len; i++) { + double sum_d = 0.0; + double sum_u = 0.0; + double i_d = phase * (4*len - 2*i - 1); + double i_u = phase * (3*len2 + 2*i + 1); + for (int j = 0; j < len2; j++) { + double a = (2 * j + 1); + double a_d = cos(a * i_d); + double a_u = cos(a * i_u); + double val = UNSCALE(src[j*stride]); + sum_d += a_d * val; + sum_u += a_u * val; + } + dst[i + 0] = RESCALE( sum_d*scale); + dst[i + len] = RESCALE(-sum_u*scale); + } +} + +static void naive_mdct(AVTXContext *s, void *_dst, void *_src, + ptrdiff_t stride) +{ + int len = s->n*2; + FFTSample *src = _src; + FFTSample *dst = _dst; + double scale = s->scale; + const double phase = M_PI/(4.0*len); + + stride /= sizeof(*dst); + + for (int i = 0; i < len; i++) { + double sum = 0.0; + for (int j = 0; j < len*2; j++) { + int a = (2*j + 1 + len) * (2*i + 1); + sum += UNSCALE(src[j]) * cos(a * phase); + } + dst[i*stride] = RESCALE(sum*scale); + } +} + +static int gen_mdct_exptab(AVTXContext *s, int len4, double scale) +{ + const double theta = (scale < 0 ? len4 : 0) + 1.0/8.0; + + if (!(s->exptab = av_malloc_array(len4, sizeof(*s->exptab)))) + return AVERROR(ENOMEM); + + scale = sqrt(fabs(scale)); + for (int i = 0; i < len4; i++) { + const double alpha = M_PI_2 * (i + theta) / len4; + s->exptab[i].re = RESCALE(cos(alpha) * scale); + s->exptab[i].im = RESCALE(sin(alpha) * scale); + } + + return 0; +} + +int TX_NAME(ff_tx_init_mdct_fft)(AVTXContext *s, av_tx_fn *tx, + enum AVTXType type, int inv, int len, + const void *scale, uint64_t flags) +{ + const int is_mdct = ff_tx_type_is_mdct(type); + int err, l, n = 1, m = 1, max_ptwo = 1 << (FF_ARRAY_ELEMS(fft_dispatch) - 1); + + if (is_mdct) + len >>= 1; + + l = len; + +#define CHECK_FACTOR(DST, FACTOR, SRC) \ + if (DST == 1 && !(SRC % FACTOR)) { \ + DST = FACTOR; \ + SRC /= FACTOR; \ + } + CHECK_FACTOR(n, 15, len) + CHECK_FACTOR(n, 5, len) + CHECK_FACTOR(n, 3, len) +#undef CHECK_FACTOR + + /* len must be a power of two now */ + if (!(len & (len - 1)) && len >= 2 && len <= max_ptwo) { + m = len; + len = 1; + } + + s->n = n; + s->m = m; + s->inv = inv; + s->type = type; + s->flags = flags; + + /* If we weren't able to split the length into factors we can handle, + * resort to using the naive and slow FT. This also filters out + * direct 3, 5 and 15 transforms as they're too niche. */ + if (len > 1 || m == 1) { + if (is_mdct && (l & 1)) /* Odd (i)MDCTs are not supported yet */ + return AVERROR(ENOSYS); + if (flags & AV_TX_INPLACE) /* Neither are in-place naive transforms */ + return AVERROR(ENOSYS); + s->n = l; + s->m = 1; + *tx = naive_fft; + if (is_mdct) { + s->scale = *((SCALE_TYPE *)scale); + *tx = inv ? naive_imdct : naive_mdct; + } + return 0; + } + + if (n > 1 && m > 1) { /* 2D transform case */ + if ((err = ff_tx_gen_compound_mapping(s))) + return err; + if (!(s->tmp = av_malloc(n*m*sizeof(*s->tmp)))) + return AVERROR(ENOMEM); + *tx = n == 3 ? compound_fft_3xM : + n == 5 ? compound_fft_5xM : + compound_fft_15xM; + if (is_mdct) + *tx = n == 3 ? inv ? compound_imdct_3xM : compound_mdct_3xM : + n == 5 ? inv ? compound_imdct_5xM : compound_mdct_5xM : + inv ? compound_imdct_15xM : compound_mdct_15xM; + } else { /* Direct transform case */ + *tx = monolithic_fft; + if (is_mdct) + *tx = inv ? monolithic_imdct : monolithic_mdct; + } + + if (n != 1) + init_cos_tabs(0); + if (m != 1) { + if ((err = ff_tx_gen_ptwo_revtab(s, n == 1 && !is_mdct && !(flags & AV_TX_INPLACE)))) + return err; + if (flags & AV_TX_INPLACE) { + if (is_mdct) /* In-place MDCTs are not supported yet */ + return AVERROR(ENOSYS); + if ((err = ff_tx_gen_ptwo_inplace_revtab_idx(s))) + return err; + } + for (int i = 4; i <= av_log2(m); i++) + init_cos_tabs(i); + } + + if (is_mdct) + return gen_mdct_exptab(s, n*m, *((SCALE_TYPE *)scale)); + + return 0; +} diff -Nru ffmpeg-4.2.2/libavutil/utils.c ffmpeg-4.4/libavutil/utils.c --- ffmpeg-4.2.2/libavutil/utils.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/utils.c 2020-07-11 10:39:30.000000000 +0000 @@ -70,7 +70,7 @@ const char *avutil_license(void) { #define LICENSE_PREFIX "libavutil license: " - return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; } const char *av_get_media_type_string(enum AVMediaType media_type) diff -Nru ffmpeg-4.2.2/libavutil/version.h ffmpeg-4.4/libavutil/version.h --- ffmpeg-4.2.2/libavutil/version.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/version.h 2021-04-08 21:28:40.000000000 +0000 @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 31 +#define LIBAVUTIL_VERSION_MINOR 70 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ @@ -129,7 +129,18 @@ #ifndef FF_API_PSEUDOPAL #define FF_API_PSEUDOPAL (LIBAVUTIL_VERSION_MAJOR < 57) #endif - +#ifndef FF_API_CHILD_CLASS_NEXT +#define FF_API_CHILD_CLASS_NEXT (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#ifndef FF_API_BUFFER_SIZE_T +#define FF_API_BUFFER_SIZE_T (LIBAVUTIL_VERSION_MAJOR < 57) +#endif +#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 /** * @} diff -Nru ffmpeg-4.2.2/libavutil/video_enc_params.c ffmpeg-4.4/libavutil/video_enc_params.c --- ffmpeg-4.2.2/libavutil/video_enc_params.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/video_enc_params.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "buffer.h" +#include "common.h" +#include "frame.h" +#include "mem.h" +#include "video_enc_params.h" + +AVVideoEncParams *av_video_enc_params_alloc(enum AVVideoEncParamsType type, + unsigned int nb_blocks, size_t *out_size) +{ + AVVideoEncParams *par; + size_t size; + + size = sizeof(*par); + if (nb_blocks > (SIZE_MAX - size) / sizeof(AVVideoBlockParams)) + return NULL; + size += sizeof(AVVideoBlockParams) * nb_blocks; + + par = av_mallocz(size); + if (!par) + return NULL; + + par->type = type; + par->nb_blocks = nb_blocks; + par->block_size = sizeof(AVVideoBlockParams); + par->blocks_offset = sizeof(*par); + + if (out_size) + *out_size = size; + + return par; +} + +AVVideoEncParams* +av_video_enc_params_create_side_data(AVFrame *frame, enum AVVideoEncParamsType type, + unsigned int nb_blocks) +{ + AVBufferRef *buf; + AVVideoEncParams *par; + size_t size; + + par = av_video_enc_params_alloc(type, nb_blocks, &size); + if (!par) + return NULL; + if (size > INT_MAX) { + av_free(par); + return NULL; + } + buf = av_buffer_create((uint8_t *)par, size, NULL, NULL, 0); + if (!buf) { + av_freep(&par); + return NULL; + } + + if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_VIDEO_ENC_PARAMS, buf)) { + av_buffer_unref(&buf); + return NULL; + } + + return par; +} diff -Nru ffmpeg-4.2.2/libavutil/video_enc_params.h ffmpeg-4.4/libavutil/video_enc_params.h --- ffmpeg-4.2.2/libavutil/video_enc_params.h 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libavutil/video_enc_params.h 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,171 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_VIDEO_ENC_PARAMS_H +#define AVUTIL_VIDEO_ENC_PARAMS_H + +#include +#include + +#include "libavutil/avassert.h" +#include "libavutil/frame.h" + +enum AVVideoEncParamsType { + AV_VIDEO_ENC_PARAMS_NONE = -1, + /** + * VP9 stores: + * - per-frame base (luma AC) quantizer index, exported as AVVideoEncParams.qp + * - deltas for luma DC, chroma AC and chroma DC, exported in the + * corresponding entries in AVVideoEncParams.delta_qp + * - per-segment delta, exported as for each block as AVVideoBlockParams.delta_qp + * + * To compute the resulting quantizer index for a block: + * - for luma AC, add the base qp and the per-block delta_qp, saturating to + * unsigned 8-bit. + * - for luma DC and chroma AC/DC, add the corresponding + * AVVideoBlockParams.delta_qp to the luma AC index, again saturating to + * unsigned 8-bit. + */ + AV_VIDEO_ENC_PARAMS_VP9, + + /** + * H.264 stores: + * - in PPS (per-picture): + * * initial QP_Y (luma) value, exported as AVVideoEncParams.qp + * * delta(s) for chroma QP values (same for both, or each separately), + * exported as in the corresponding entries in AVVideoEncParams.delta_qp + * - per-slice QP delta, not exported directly, added to the per-MB value + * - per-MB delta; not exported directly; the final per-MB quantizer + * parameter - QP_Y - minus the value in AVVideoEncParams.qp is exported + * as AVVideoBlockParams.qp_delta. + */ + AV_VIDEO_ENC_PARAMS_H264, + + /* + * MPEG-2-compatible quantizer. + * + * Summing the frame-level qp with the per-block delta_qp gives the + * resulting quantizer for the block. + */ + AV_VIDEO_ENC_PARAMS_MPEG2, +}; + +/** + * Video encoding parameters for a given frame. This struct is allocated along + * with an optional array of per-block AVVideoBlockParams descriptors. + * Must be allocated with av_video_enc_params_alloc(). + */ +typedef struct AVVideoEncParams { + /** + * Number of blocks in the array. + * + * May be 0, in which case no per-block information is present. In this case + * the values of blocks_offset / block_size are unspecified and should not + * be accessed. + */ + unsigned int nb_blocks; + /** + * Offset in bytes from the beginning of this structure at which the array + * of blocks starts. + */ + size_t blocks_offset; + /* + * Size of each block in bytes. May not match sizeof(AVVideoBlockParams). + */ + size_t block_size; + + /** + * Type of the parameters (the codec they are used with). + */ + enum AVVideoEncParamsType type; + + /** + * Base quantisation parameter for the frame. The final quantiser for a + * given block in a given plane is obtained from this value, possibly + * combined with {@code delta_qp} and the per-block delta in a manner + * documented for each type. + */ + int32_t qp; + + /** + * Quantisation parameter offset from the base (per-frame) qp for a given + * plane (first index) and AC/DC coefficients (second index). + */ + int32_t delta_qp[4][2]; +} AVVideoEncParams; + +/** + * Data structure for storing block-level encoding information. + * It is allocated as a part of AVVideoEncParams and should be retrieved with + * av_video_enc_params_block(). + * + * sizeof(AVVideoBlockParams) is not a part of the ABI and new fields may be + * added to it. + */ +typedef struct AVVideoBlockParams { + /** + * Distance in luma pixels from the top-left corner of the visible frame + * to the top-left corner of the block. + * Can be negative if top/right padding is present on the coded frame. + */ + int src_x, src_y; + /** + * Width and height of the block in luma pixels. + */ + int w, h; + + /** + * Difference between this block's final quantization parameter and the + * corresponding per-frame value. + */ + int32_t delta_qp; +} AVVideoBlockParams; + +/* + * Get the block at the specified {@code idx}. Must be between 0 and nb_blocks. + */ +static av_always_inline AVVideoBlockParams* +av_video_enc_params_block(AVVideoEncParams *par, unsigned int idx) +{ + av_assert0(idx < par->nb_blocks); + return (AVVideoBlockParams *)((uint8_t *)par + par->blocks_offset + + idx * par->block_size); +} + +/** + * Allocates memory for AVVideoEncParams of the given type, plus an array of + * {@code nb_blocks} AVVideoBlockParams and initializes the variables. Can be + * freed with a normal av_free() call. + * + * @param out_size if non-NULL, the size in bytes of the resulting data array is + * written here. + */ +AVVideoEncParams *av_video_enc_params_alloc(enum AVVideoEncParamsType type, + unsigned int nb_blocks, size_t *out_size); + +/** + * Allocates memory for AVEncodeInfoFrame plus an array of + * {@code nb_blocks} AVEncodeInfoBlock in the given AVFrame {@code frame} + * as AVFrameSideData of type AV_FRAME_DATA_VIDEO_ENC_PARAMS + * and initializes the variables. + */ +AVVideoEncParams* +av_video_enc_params_create_side_data(AVFrame *frame, enum AVVideoEncParamsType type, + unsigned int nb_blocks); + +#endif /* AVUTIL_VIDEO_ENC_PARAMS_H */ diff -Nru ffmpeg-4.2.2/libavutil/x86/bswap.h ffmpeg-4.4/libavutil/x86/bswap.h --- ffmpeg-4.2.2/libavutil/x86/bswap.h 2018-07-17 09:27:43.000000000 +0000 +++ ffmpeg-4.4/libavutil/x86/bswap.h 2020-07-11 10:39:30.000000000 +0000 @@ -26,6 +26,7 @@ #include #if defined(_MSC_VER) +#include #include #endif #include "config.h" diff -Nru ffmpeg-4.2.2/libavutil/x86/x86inc.asm ffmpeg-4.4/libavutil/x86/x86inc.asm --- ffmpeg-4.2.2/libavutil/x86/x86inc.asm 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libavutil/x86/x86inc.asm 2021-02-20 20:27:47.000000000 +0000 @@ -411,16 +411,6 @@ %endif %endmacro -%macro DEFINE_ARGS_INTERNAL 3+ - %ifnum %2 - DEFINE_ARGS %3 - %elif %1 == 4 - DEFINE_ARGS %2 - %elif %1 > 4 - DEFINE_ARGS %2, %3 - %endif -%endmacro - %if WIN64 ; Windows x64 ;================================================= DECLARE_REG 0, rcx @@ -439,7 +429,7 @@ DECLARE_REG 13, R12, 112 DECLARE_REG 14, R13, 120 -%macro PROLOGUE 2-5+ 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... +%macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... %assign num_args %1 %assign regs_used %2 ASSERT regs_used >= num_args @@ -451,7 +441,15 @@ WIN64_SPILL_XMM %3 %endif LOAD_IF_USED 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 - DEFINE_ARGS_INTERNAL %0, %4, %5 + %if %0 > 4 + %ifnum %4 + DEFINE_ARGS %5 + %else + DEFINE_ARGS %4, %5 + %endif + %elifnnum %4 + DEFINE_ARGS %4 + %endif %endmacro %macro WIN64_PUSH_XMM 0 @@ -547,7 +545,7 @@ DECLARE_REG 13, R12, 64 DECLARE_REG 14, R13, 72 -%macro PROLOGUE 2-5+ 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... +%macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... %assign num_args %1 %assign regs_used %2 %assign xmm_regs_used %3 @@ -557,7 +555,15 @@ PUSH_IF_USED 9, 10, 11, 12, 13, 14 ALLOC_STACK %4 LOAD_IF_USED 6, 7, 8, 9, 10, 11, 12, 13, 14 - DEFINE_ARGS_INTERNAL %0, %4, %5 + %if %0 > 4 + %ifnum %4 + DEFINE_ARGS %5 + %else + DEFINE_ARGS %4, %5 + %endif + %elifnnum %4 + DEFINE_ARGS %4 + %endif %endmacro %define has_epilogue regs_used > 9 || stack_size > 0 || vzeroupper_required @@ -598,7 +604,7 @@ DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14 -%macro PROLOGUE 2-5+ ; #args, #regs, #xmm_regs, [stack_size,] arg_names... +%macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names... %assign num_args %1 %assign regs_used %2 ASSERT regs_used >= num_args @@ -613,7 +619,15 @@ PUSH_IF_USED 3, 4, 5, 6 ALLOC_STACK %4 LOAD_IF_USED 0, 1, 2, 3, 4, 5, 6 - DEFINE_ARGS_INTERNAL %0, %4, %5 + %if %0 > 4 + %ifnum %4 + DEFINE_ARGS %5 + %else + DEFINE_ARGS %4, %5 + %endif + %elifnnum %4 + DEFINE_ARGS %4 + %endif %endmacro %define has_epilogue regs_used > 3 || stack_size > 0 || vzeroupper_required diff -Nru ffmpeg-4.2.2/libpostproc/postprocess_altivec_template.c ffmpeg-4.4/libpostproc/postprocess_altivec_template.c --- ffmpeg-4.2.2/libpostproc/postprocess_altivec_template.c 2016-03-29 02:25:33.000000000 +0000 +++ ffmpeg-4.4/libpostproc/postprocess_altivec_template.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,6 +21,7 @@ */ #include "libavutil/avutil.h" +#include "libavutil/mem_internal.h" #define ALTIVEC_TRANSPOSE_8x8_SHORT(src_a,src_b,src_c,src_d,src_e,src_f,src_g,src_h) \ do { \ diff -Nru ffmpeg-4.2.2/libpostproc/postprocess.c ffmpeg-4.4/libpostproc/postprocess.c --- ffmpeg-4.2.2/libpostproc/postprocess.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libpostproc/postprocess.c 2020-07-11 10:39:30.000000000 +0000 @@ -108,7 +108,7 @@ const char *postproc_license(void) { #define LICENSE_PREFIX "libpostproc license: " - return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; } #define GET_MODE_BUFFER_SIZE 500 @@ -407,7 +407,7 @@ const int QP= c->QP; const int dcOffset= ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1; const int dcThreshold= dcOffset*2 + 1; -//START_TIMER + src+= step*4; // src points to begin of the 8x8 Block for(y=0; y<8; y++){ int numEq= 0; @@ -511,11 +511,6 @@ src += stride; } -/*if(step==16){ - STOP_TIMER("step16") -}else{ - STOP_TIMER("stepX") -}*/ } //Note: we have C, MMX, MMX2, 3DNOW version there is no 3DNOW+MMX2 one diff -Nru ffmpeg-4.2.2/libpostproc/postprocess_internal.h ffmpeg-4.4/libpostproc/postprocess_internal.h --- ffmpeg-4.2.2/libpostproc/postprocess_internal.h 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libpostproc/postprocess_internal.h 2021-04-08 21:28:40.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/avutil.h" #include "libavutil/intmath.h" #include "libavutil/log.h" +#include "libavutil/mem_internal.h" #include "postprocess.h" #define V_DEBLOCK 0x01 diff -Nru ffmpeg-4.2.2/libpostproc/postprocess_template.c ffmpeg-4.4/libpostproc/postprocess_template.c --- ffmpeg-4.2.2/libpostproc/postprocess_template.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libpostproc/postprocess_template.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,6 +23,7 @@ * mmx/mmx2/3dnow postprocess code. */ +#include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" /* A single TEMPLATE_PP_* should be defined (to 1) when this template is @@ -2548,7 +2549,7 @@ int64_t dc_mask, eq_mask, both_masks; int64_t sums[10*8*2]; src+= step*3; // src points to begin of the 8x8 Block - //{ START_TIMER + __asm__ volatile( "movq %0, %%mm7 \n\t" "movq %1, %%mm6 \n\t" @@ -3071,12 +3072,6 @@ : "%"FF_REG_a ); } -/*if(step==16){ - STOP_TIMER("step16") -}else{ - STOP_TIMER("stepX") -} - } */ } #endif //TEMPLATE_PP_MMX diff -Nru ffmpeg-4.2.2/libpostproc/version.h ffmpeg-4.4/libpostproc/version.h --- ffmpeg-4.2.2/libpostproc/version.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libpostproc/version.h 2021-04-08 21:28:40.000000000 +0000 @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBPOSTPROC_VERSION_MAJOR 55 -#define LIBPOSTPROC_VERSION_MINOR 5 +#define LIBPOSTPROC_VERSION_MINOR 9 #define LIBPOSTPROC_VERSION_MICRO 100 #define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ diff -Nru ffmpeg-4.2.2/libswresample/audioconvert.c ffmpeg-4.4/libswresample/audioconvert.c --- ffmpeg-4.2.2/libswresample/audioconvert.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libswresample/audioconvert.c 2021-04-08 21:28:40.000000000 +0000 @@ -59,7 +59,7 @@ CONV_FUNC(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7))) CONV_FUNC(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S16, (*(const int16_t*)pi>>8) + 0x80) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi) -CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi<<16) +CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi * (1 << 16)) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16, (uint64_t)(*(const int16_t*)pi)<<48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0f/ (1<<15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0 / (1<<15))) @@ -73,18 +73,18 @@ CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S64, *(const int64_t*)pi>>48) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S64, *(const int64_t*)pi>>32) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S64, *(const int64_t*)pi) -CONV_FUNC(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S64, *(const int64_t*)pi*(1.0f/ (INT64_C(1)<<63))) -CONV_FUNC(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S64, *(const int64_t*)pi*(1.0 / (INT64_C(1)<<63))) +CONV_FUNC(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S64, *(const int64_t*)pi*(1.0f/ (UINT64_C(1)<<63))) +CONV_FUNC(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S64, *(const int64_t*)pi*(1.0 / (UINT64_C(1)<<63))) CONV_FUNC(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8( lrintf(*(const float*)pi * (1<<7)) + 0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16( lrintf(*(const float*)pi * (1<<15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float*)pi * (1U<<31)))) -CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float*)pi * (INT64_C(1)<<63))) +CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float*)pi * (UINT64_C(1)<<63))) CONV_FUNC(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_FLT, *(const float*)pi) CONV_FUNC(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_FLT, *(const float*)pi) CONV_FUNC(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8( lrint(*(const double*)pi * (1<<7)) + 0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16( lrint(*(const double*)pi * (1<<15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double*)pi * (1U<<31)))) -CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double*)pi * (INT64_C(1)<<63))) +CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double*)pi * (UINT64_C(1)<<63))) CONV_FUNC(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_DBL, *(const double*)pi) CONV_FUNC(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_DBL, *(const double*)pi) @@ -237,10 +237,10 @@ const int ich= ctx->ch_map ? ctx->ch_map[ch] : ch; const int is= ich < 0 ? 0 : (in->planar ? 1 : in->ch_count) * in->bps; const uint8_t *pi= ich < 0 ? ctx->silence : in->ch[ich]; - uint8_t *po= out->ch[ch]; - uint8_t *end= po + os*len; + uint8_t *end, *po = out->ch[ch]; if(!po) continue; + end = po + os * len; ctx->conv_f(po+off*os, pi+off*is, is, os, end); } return 0; diff -Nru ffmpeg-4.2.2/libswresample/rematrix.c ffmpeg-4.4/libswresample/rematrix.c --- ffmpeg-4.2.2/libswresample/rematrix.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libswresample/rematrix.c 2021-04-08 21:28:40.000000000 +0000 @@ -88,7 +88,7 @@ return 0; } -static int clean_layout(void *s, int64_t layout){ +static int64_t clean_layout(void *s, int64_t layout){ if(layout && layout != AV_CH_FRONT_CENTER && !(layout&(layout-1))) { char buf[128]; av_get_channel_layout_string(buf, sizeof(buf), -1, layout); @@ -141,6 +141,16 @@ ) in_ch_layout = AV_CH_LAYOUT_STEREO; + if (in_ch_layout == AV_CH_LAYOUT_22POINT2 && + out_ch_layout != AV_CH_LAYOUT_22POINT2) { + in_ch_layout = (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER); + av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout); + av_log(log_context, AV_LOG_WARNING, + "Full-on remixing from 22.2 has not yet been implemented! " + "Processing the input as '%s'\n", + buf); + } + if(!sane_layout(in_ch_layout)){ av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout_param); av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf); diff -Nru ffmpeg-4.2.2/libswresample/swresample.c ffmpeg-4.4/libswresample/swresample.c --- ffmpeg-4.2.2/libswresample/swresample.c 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libswresample/swresample.c 2020-07-11 10:39:30.000000000 +0000 @@ -46,7 +46,7 @@ const char *swresample_license(void) { #define LICENSE_PREFIX "libswresample license: " - return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; } int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map){ diff -Nru ffmpeg-4.2.2/libswresample/version.h ffmpeg-4.4/libswresample/version.h --- ffmpeg-4.2.2/libswresample/version.h 2019-12-31 21:35:24.000000000 +0000 +++ ffmpeg-4.4/libswresample/version.h 2021-04-08 21:28:40.000000000 +0000 @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBSWRESAMPLE_VERSION_MAJOR 3 -#define LIBSWRESAMPLE_VERSION_MINOR 5 +#define LIBSWRESAMPLE_VERSION_MINOR 9 #define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ diff -Nru ffmpeg-4.2.2/libswscale/aarch64/hscale.S ffmpeg-4.4/libswscale/aarch64/hscale.S --- ffmpeg-4.2.2/libswscale/aarch64/hscale.S 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libswscale/aarch64/hscale.S 2020-07-11 10:39:30.000000000 +0000 @@ -21,39 +21,60 @@ #include "libavutil/aarch64/asm.S" function ff_hscale_8_to_15_neon, export=1 - add x10, x4, w6, UXTW #1 // filter2 = filter + filterSize*2 (x2 because int16) -1: ldr w8, [x5], #4 // filterPos[0] - ldr w9, [x5], #4 // filterPos[1] - movi v4.4S, #0 // val sum part 1 (for dst[0]) - movi v5.4S, #0 // val sum part 2 (for dst[1]) - mov w7, w6 // filterSize counter - mov x13, x3 // srcp = src -2: add x11, x13, w8, UXTW // srcp + filterPos[0] - add x12, x13, w9, UXTW // srcp + filterPos[1] - ld1 {v0.8B}, [x11] // srcp[filterPos[0] + {0..7}] - ld1 {v1.8B}, [x12] // srcp[filterPos[1] + {0..7}] - ld1 {v2.8H}, [x4], #16 // load 8x16-bit filter values, part 1 - ld1 {v3.8H}, [x10], #16 // ditto at filter+filterSize for part 2 - uxtl v0.8H, v0.8B // unpack part 1 to 16-bit - uxtl v1.8H, v1.8B // unpack part 2 to 16-bit - smull v16.4S, v0.4H, v2.4H // v16.i32{0..3} = part 1 of: srcp[filterPos[0] + {0..7}] * filter[{0..7}] - smull v18.4S, v1.4H, v3.4H // v18.i32{0..3} = part 1 of: srcp[filterPos[1] + {0..7}] * filter[{0..7}] - smull2 v17.4S, v0.8H, v2.8H // v17.i32{0..3} = part 2 of: srcp[filterPos[0] + {0..7}] * filter[{0..7}] - smull2 v19.4S, v1.8H, v3.8H // v19.i32{0..3} = part 2 of: srcp[filterPos[1] + {0..7}] * filter[{0..7}] - addp v16.4S, v16.4S, v17.4S // horizontal pair adding of the 8x32-bit multiplied values for part 1 into 4x32-bit - addp v18.4S, v18.4S, v19.4S // horizontal pair adding of the 8x32-bit multiplied values for part 2 into 4x32-bit - add v4.4S, v4.4S, v16.4S // update val accumulator for part 1 - add v5.4S, v5.4S, v18.4S // update val accumulator for part 2 - add x13, x13, #8 // srcp += 8 - subs w7, w7, #8 // processed 8/filterSize + sbfiz x7, x6, #1, #32 // filterSize*2 (*2 because int16) +1: ldr w8, [x5], #4 // filterPos[idx] + ldr w0, [x5], #4 // filterPos[idx + 1] + ldr w11, [x5], #4 // filterPos[idx + 2] + ldr w9, [x5], #4 // filterPos[idx + 3] + mov x16, x4 // filter0 = filter + add x12, x16, x7 // filter1 = filter0 + filterSize*2 + add x13, x12, x7 // filter2 = filter1 + filterSize*2 + add x4, x13, x7 // filter3 = filter2 + filterSize*2 + movi v0.2D, #0 // val sum part 1 (for dst[0]) + movi v1.2D, #0 // val sum part 2 (for dst[1]) + movi v2.2D, #0 // val sum part 3 (for dst[2]) + movi v3.2D, #0 // val sum part 4 (for dst[3]) + add x17, x3, w8, UXTW // srcp + filterPos[0] + add x8, x3, w0, UXTW // srcp + filterPos[1] + add x0, x3, w11, UXTW // srcp + filterPos[2] + add x11, x3, w9, UXTW // srcp + filterPos[3] + mov w15, w6 // filterSize counter +2: ld1 {v4.8B}, [x17], #8 // srcp[filterPos[0] + {0..7}] + ld1 {v5.8H}, [x16], #16 // load 8x16-bit filter values, part 1 + ld1 {v6.8B}, [x8], #8 // srcp[filterPos[1] + {0..7}] + ld1 {v7.8H}, [x12], #16 // load 8x16-bit at filter+filterSize + uxtl v4.8H, v4.8B // unpack part 1 to 16-bit + smlal v0.4S, v4.4H, v5.4H // v0 accumulates srcp[filterPos[0] + {0..3}] * filter[{0..3}] + smlal2 v0.4S, v4.8H, v5.8H // v0 accumulates srcp[filterPos[0] + {4..7}] * filter[{4..7}] + ld1 {v16.8B}, [x0], #8 // srcp[filterPos[2] + {0..7}] + ld1 {v17.8H}, [x13], #16 // load 8x16-bit at filter+2*filterSize + uxtl v6.8H, v6.8B // unpack part 2 to 16-bit + smlal v1.4S, v6.4H, v7.4H // v1 accumulates srcp[filterPos[1] + {0..3}] * filter[{0..3}] + uxtl v16.8H, v16.8B // unpack part 3 to 16-bit + smlal v2.4S, v16.4H, v17.4H // v2 accumulates srcp[filterPos[2] + {0..3}] * filter[{0..3}] + smlal2 v2.4S, v16.8H, v17.8H // v2 accumulates srcp[filterPos[2] + {4..7}] * filter[{4..7}] + ld1 {v18.8B}, [x11], #8 // srcp[filterPos[3] + {0..7}] + smlal2 v1.4S, v6.8H, v7.8H // v1 accumulates srcp[filterPos[1] + {4..7}] * filter[{4..7}] + ld1 {v19.8H}, [x4], #16 // load 8x16-bit at filter+3*filterSize + subs w15, w15, #8 // j -= 8: processed 8/filterSize + uxtl v18.8H, v18.8B // unpack part 4 to 16-bit + smlal v3.4S, v18.4H, v19.4H // v3 accumulates srcp[filterPos[3] + {0..3}] * filter[{0..3}] + smlal2 v3.4S, v18.8H, v19.8H // v3 accumulates srcp[filterPos[3] + {4..7}] * filter[{4..7}] b.gt 2b // inner loop if filterSize not consumed completely - mov x4, x10 // filter = filter2 - add x10, x10, w6, UXTW #1 // filter2 += filterSize*2 - addp v4.4S, v4.4S, v5.4S // horizontal pair adding of the 8x32-bit sums into 4x32-bit - addp v4.4S, v4.4S, v4.4S // horizontal pair adding of the 4x32-bit sums into 2x32-bit - sqshrn v4.4H, v4.4S, #7 // shift and clip the 2x16-bit final values - st1 {v4.S}[0], [x1], #4 // write to destination - subs w2, w2, #2 // dstW -= 2 + addp v0.4S, v0.4S, v0.4S // part0 horizontal pair adding + addp v1.4S, v1.4S, v1.4S // part1 horizontal pair adding + addp v2.4S, v2.4S, v2.4S // part2 horizontal pair adding + addp v3.4S, v3.4S, v3.4S // part3 horizontal pair adding + addp v0.4S, v0.4S, v0.4S // part0 horizontal pair adding + addp v1.4S, v1.4S, v1.4S // part1 horizontal pair adding + addp v2.4S, v2.4S, v2.4S // part2 horizontal pair adding + addp v3.4S, v3.4S, v3.4S // part3 horizontal pair adding + zip1 v0.4S, v0.4S, v1.4S // part01 = zip values from part0 and part1 + zip1 v2.4S, v2.4S, v3.4S // part23 = zip values from part2 and part3 + mov v0.d[1], v2.d[0] // part0123 = zip values from part01 and part23 + subs w2, w2, #4 // dstW -= 4 + sqshrn v0.4H, v0.4S, #7 // shift and clip the 2x16-bit final values + st1 {v0.4H}, [x1], #8 // write to destination part0123 b.gt 1b // loop until end of line ret endfunc diff -Nru ffmpeg-4.2.2/libswscale/aarch64/Makefile ffmpeg-4.4/libswscale/aarch64/Makefile --- ffmpeg-4.2.2/libswscale/aarch64/Makefile 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libswscale/aarch64/Makefile 2020-07-11 10:39:30.000000000 +0000 @@ -1,6 +1,8 @@ -OBJS += aarch64/swscale.o \ +OBJS += aarch64/rgb2rgb.o \ + aarch64/swscale.o \ aarch64/swscale_unscaled.o \ NEON-OBJS += aarch64/hscale.o \ aarch64/output.o \ + aarch64/rgb2rgb_neon.o \ aarch64/yuv2rgb_neon.o \ diff -Nru ffmpeg-4.2.2/libswscale/aarch64/output.S ffmpeg-4.4/libswscale/aarch64/output.S --- ffmpeg-4.2.2/libswscale/aarch64/output.S 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libswscale/aarch64/output.S 2020-07-11 10:39:30.000000000 +0000 @@ -38,29 +38,21 @@ add x12, x12, x7, lsl #1 // &src[j+1][i] ld1 {v5.8H}, [x11] // read 8x16-bit @ src[j ][i + {0..7}]: A,B,C,D,E,F,G,H ld1 {v6.8H}, [x12] // read 8x16-bit @ src[j+1][i + {0..7}]: I,J,K,L,M,N,O,P - ldr w11, [x10], #4 // read 2x16-bit coeffs (X, Y) at (filter[j], filter[j+1]) - zip1 v16.8H, v5.8H, v6.8H // A,I,B,J,C,K,D,L - zip2 v17.8H, v5.8H, v6.8H // E,M,F,N,F,O,H,P - dup v7.4S, w11 // X,Y,X,Y,X,Y,X,Y - smull v18.4S, v16.4H, v7.4H // A.X I.Y B.X J.Y - smull v20.4S, v17.4H, v7.4H // E.X M.Y F.X N.Y - smull2 v19.4S, v16.8H, v7.8H // C.X K.Y D.X L.Y - smull2 v21.4S, v17.8H, v7.8H // G.X O.Y H.X P.Y - addp v16.4S, v18.4S, v19.4S // A.X+I.Y B.X+J.Y C.X+K.Y D.X+L.Y - addp v17.4S, v20.4S, v21.4S // E.X+M.Y F.X+N.Y F.X+O.Y H.X+P.Y - add v3.4S, v3.4S, v16.4S // update val accumulator for part 1 - add v4.4S, v4.4S, v17.4S // update val accumulator for part 2 + ld1r {v7.8H}, [x10], #2 // read 1x16-bit coeff X at filter[j ] and duplicate across lanes + ld1r {v16.8H}, [x10], #2 // read 1x16-bit coeff Y at filter[j+1] and duplicate across lanes + smlal v3.4S, v5.4H, v7.4H // val0 += {A,B,C,D} * X + smlal2 v4.4S, v5.8H, v7.8H // val1 += {E,F,G,H} * X + smlal v3.4S, v6.4H, v16.4H // val0 += {I,J,K,L} * Y + smlal2 v4.4S, v6.8H, v16.8H // val1 += {M,N,O,P} * Y subs w8, w8, #2 // tmpfilterSize -= 2 b.gt 3b // loop until filterSize consumed - sshr v3.4S, v3.4S, #19 // val>>19 (part 1) - sshr v4.4S, v4.4S, #19 // val>>19 (part 2) - sqxtun v3.4H, v3.4S // clip16(val>>19) (part 1) - sqxtun v4.4H, v4.4S // clip16(val>>19) (part 2) - mov v3.D[1], v4.D[0] // merge part 1 and part 2 - uqxtn v3.8B, v3.8H // clip8(val>>19) - st1 {v3.1D}, [x3], #8 // write to destination - add x7, x7, #8 // i += 8 + + sqshrun v3.4h, v3.4s, #16 // clip16(val0>>16) + sqshrun2 v3.8h, v4.4s, #16 // clip16(val1>>16) + uqshrn v3.8b, v3.8h, #3 // clip8(val>>19) + st1 {v3.8b}, [x3], #8 // write to destination subs w4, w4, #8 // dstW -= 8 + add x7, x7, #8 // i += 8 b.gt 2b // loop until width consumed ret endfunc diff -Nru ffmpeg-4.2.2/libswscale/aarch64/rgb2rgb.c ffmpeg-4.4/libswscale/aarch64/rgb2rgb.c --- ffmpeg-4.2.2/libswscale/aarch64/rgb2rgb.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libswscale/aarch64/rgb2rgb.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,41 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/aarch64/cpu.h" +#include "libavutil/cpu.h" +#include "libavutil/bswap.h" +#include "libswscale/rgb2rgb.h" +#include "libswscale/swscale.h" +#include "libswscale/swscale_internal.h" + +void ff_interleave_bytes_neon(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int width, int height, + int src1Stride, int src2Stride, int dstStride); + +av_cold void rgb2rgb_init_aarch64(void) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + interleaveBytes = ff_interleave_bytes_neon; + } +} diff -Nru ffmpeg-4.2.2/libswscale/aarch64/rgb2rgb_neon.S ffmpeg-4.4/libswscale/aarch64/rgb2rgb_neon.S --- ffmpeg-4.2.2/libswscale/aarch64/rgb2rgb_neon.S 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libswscale/aarch64/rgb2rgb_neon.S 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020 Martin Storsjo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/aarch64/asm.S" + +// void ff_interleave_bytes_neon(const uint8_t *src1, const uint8_t *src2, +// uint8_t *dest, int width, int height, +// int src1Stride, int src2Stride, int dstStride); +function ff_interleave_bytes_neon, export=1 + sub w5, w5, w3 + sub w6, w6, w3 + sub w7, w7, w3, lsl #1 +1: + ands w8, w3, #0xfffffff0 // & ~15 + b.eq 3f +2: + ld1 {v0.16b}, [x0], #16 + ld1 {v1.16b}, [x1], #16 + subs w8, w8, #16 + st2 {v0.16b, v1.16b}, [x2], #32 + b.gt 2b + + tst w3, #15 + b.eq 9f + +3: + tst w3, #8 + b.eq 4f + ld1 {v0.8b}, [x0], #8 + ld1 {v1.8b}, [x1], #8 + st2 {v0.8b, v1.8b}, [x2], #16 +4: + tst w3, #4 + b.eq 5f + + ld1 {v0.s}[0], [x0], #4 + ld1 {v1.s}[0], [x1], #4 + zip1 v0.8b, v0.8b, v1.8b + st1 {v0.8b}, [x2], #8 + +5: + ands w8, w3, #3 + b.eq 9f +6: + ldrb w9, [x0], #1 + ldrb w10, [x1], #1 + subs w8, w8, #1 + bfi w9, w10, #8, #8 + strh w9, [x2], #2 + b.gt 6b + +9: + subs w4, w4, #1 + b.eq 0f + add x0, x0, w5, sxtw + add x1, x1, w6, sxtw + add x2, x2, w7, sxtw + b 1b + +0: + ret +endfunc diff -Nru ffmpeg-4.2.2/libswscale/aarch64/swscale.c ffmpeg-4.4/libswscale/aarch64/swscale.c --- ffmpeg-4.2.2/libswscale/aarch64/swscale.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libswscale/aarch64/swscale.c 2020-07-11 10:39:30.000000000 +0000 @@ -34,7 +34,10 @@ int cpu_flags = av_get_cpu_flags(); if (have_neon(cpu_flags)) { - if (c->srcBpc == 8 && c->dstBpc <= 14) { + if (c->srcBpc == 8 && c->dstBpc <= 14 && + (c->hLumFilterSize % 8) == 0 && + (c->hChrFilterSize % 8) == 0) + { c->hyScale = c->hcScale = ff_hscale_8_to_15_neon; } if (c->dstBpc == 8) { diff -Nru ffmpeg-4.2.2/libswscale/aarch64/swscale_unscaled.c ffmpeg-4.4/libswscale/aarch64/swscale_unscaled.c --- ffmpeg-4.2.2/libswscale/aarch64/swscale_unscaled.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libswscale/aarch64/swscale_unscaled.c 2021-04-08 21:28:40.000000000 +0000 @@ -42,15 +42,14 @@ uint8_t *dst[], int dstStride[]) { \ const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE }; \ \ - ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH, \ - dst[0] + srcSliceY * dstStride[0], dstStride[0], \ - src[0], srcStride[0], \ - src[1], srcStride[1], \ - src[2], srcStride[2], \ - yuv2rgb_table, \ - c->yuv2rgb_y_offset >> 6, \ - c->yuv2rgb_y_coeff); \ - return 0; \ + return ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH, \ + dst[0] + srcSliceY * dstStride[0], dstStride[0], \ + src[0], srcStride[0], \ + src[1], srcStride[1], \ + src[2], srcStride[2], \ + yuv2rgb_table, \ + c->yuv2rgb_y_offset >> 6, \ + c->yuv2rgb_y_coeff); \ } \ #define DECLARE_FF_YUVX_TO_ALL_RGBX_FUNCS(yuvx) \ @@ -76,14 +75,12 @@ uint8_t *dst[], int dstStride[]) { \ const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE }; \ \ - ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH, \ - dst[0] + srcSliceY * dstStride[0], dstStride[0], \ - src[0], srcStride[0], src[1], srcStride[1], \ - yuv2rgb_table, \ - c->yuv2rgb_y_offset >> 6, \ - c->yuv2rgb_y_coeff); \ - \ - return 0; \ + return ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH, \ + dst[0] + srcSliceY * dstStride[0], dstStride[0], \ + src[0], srcStride[0], src[1], srcStride[1], \ + yuv2rgb_table, \ + c->yuv2rgb_y_offset >> 6, \ + c->yuv2rgb_y_coeff); \ } \ #define DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nvx) \ diff -Nru ffmpeg-4.2.2/libswscale/aarch64/yuv2rgb_neon.S ffmpeg-4.4/libswscale/aarch64/yuv2rgb_neon.S --- ffmpeg-4.2.2/libswscale/aarch64/yuv2rgb_neon.S 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libswscale/aarch64/yuv2rgb_neon.S 2021-04-08 21:28:40.000000000 +0000 @@ -142,6 +142,7 @@ .macro declare_func ifmt ofmt function ff_\ifmt\()_to_\ofmt\()_neon, export=1 load_args_\ifmt + mov w9, w1 1: mov w8, w0 // w8 = width 2: @@ -193,6 +194,7 @@ increment_\ifmt subs w1, w1, #1 // height -= 1 b.gt 1b + mov w0, w9 ret endfunc .endm diff -Nru ffmpeg-4.2.2/libswscale/arm/swscale.c ffmpeg-4.4/libswscale/arm/swscale.c --- ffmpeg-4.2.2/libswscale/arm/swscale.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libswscale/arm/swscale.c 2020-07-11 10:39:30.000000000 +0000 @@ -34,7 +34,10 @@ int cpu_flags = av_get_cpu_flags(); if (have_neon(cpu_flags)) { - if (c->srcBpc == 8 && c->dstBpc <= 14) { + if (c->srcBpc == 8 && c->dstBpc <= 14 && + (c->hLumFilterSize % 8) == 0 && + (c->hChrFilterSize % 8) == 0) + { c->hyScale = c->hcScale = ff_hscale_8_to_15_neon; } if (c->dstBpc == 8) { diff -Nru ffmpeg-4.2.2/libswscale/bayer_template.c ffmpeg-4.4/libswscale/bayer_template.c --- ffmpeg-4.2.2/libswscale/bayer_template.c 2017-12-31 22:35:49.000000000 +0000 +++ ffmpeg-4.4/libswscale/bayer_template.c 2021-04-08 21:28:40.000000000 +0000 @@ -118,6 +118,72 @@ B(1, 1) = (T(0, 1) + T(2, 1)) >> (1 + BAYER_SHIFT); #endif +#if defined(BAYER_BGGR) || defined(BAYER_RGGB) +#define BAYER_TO_RGB48_COPY \ + R(0, 0) = \ + R(0, 1) = \ + R(1, 1) = \ + R(1, 0) = S(1, 1); \ + \ + G(0, 1) = S(0, 1); \ + G(0, 0) = \ + G(1, 1) = (T(0, 1) + T(1, 0)) >> 1; \ + G(1, 0) = S(1, 0); \ + \ + B(1, 1) = \ + B(0, 0) = \ + B(0, 1) = \ + B(1, 0) = S(0, 0); +#define BAYER_TO_RGB48_INTERPOLATE \ + R(0, 0) = (T(-1, -1) + T(-1, 1) + T(1, -1) + T(1, 1)) >> 2; \ + G(0, 0) = (T(-1, 0) + T( 0, -1) + T(0, 1) + T(1, 0)) >> 2; \ + B(0, 0) = S(0, 0); \ + \ + R(0, 1) = (T(-1, 1) + T(1, 1)) >> 1; \ + G(0, 1) = S(0, 1); \ + B(0, 1) = (T(0, 0) + T(0, 2)) >> 1; \ + \ + R(1, 0) = (T(1, -1) + T(1, 1)) >> 1; \ + G(1, 0) = S(1, 0); \ + B(1, 0) = (T(0, 0) + T(2, 0)) >> 1; \ + \ + R(1, 1) = S(1, 1); \ + G(1, 1) = (T(0, 1) + T(1, 0) + T(1, 2) + T(2, 1)) >> 2; \ + B(1, 1) = (T(0, 0) + T(0, 2) + T(2, 0) + T(2, 2)) >> 2; +#else +#define BAYER_TO_RGB48_COPY \ + R(0, 0) = \ + R(0, 1) = \ + R(1, 1) = \ + R(1, 0) = S(1, 0); \ + \ + G(0, 0) = S(0, 0); \ + G(1, 1) = S(1, 1); \ + G(0, 1) = \ + G(1, 0) = (T(0, 0) + T(1, 1)) >> 1; \ + \ + B(1, 1) = \ + B(0, 0) = \ + B(0, 1) = \ + B(1, 0) = S(0, 1); +#define BAYER_TO_RGB48_INTERPOLATE \ + R(0, 0) = (T(-1, 0) + T(1, 0)) >> 1; \ + G(0, 0) = S(0, 0); \ + B(0, 0) = (T(0, -1) + T(0, 1)) >> 1; \ + \ + R(0, 1) = (T(-1, 0) + T(-1, 2) + T(1, 0) + T(1, 2)) >> 2; \ + G(0, 1) = (T(-1, 1) + T(0, 0) + T(0, 2) + T(1, 1)) >> 2; \ + B(0, 1) = S(0, 1); \ + \ + R(1, 0) = S(1, 0); \ + G(1, 0) = (T(0, 0) + T(1, -1) + T(1, 1) + T(2, 0)) >> 2; \ + B(1, 0) = (T(0, -1) + T(0, 1) + T(2, -1) + T(2, 1)) >> 2; \ + \ + R(1, 1) = (T(1, 0) + T(1, 2)) >> 1; \ + G(1, 1) = S(1, 1); \ + B(1, 1) = (T(0, 1) + T(2, 1)) >> 1; +#endif + /** * invoke ff_rgb24toyv12 for 2x2 pixels */ @@ -153,6 +219,40 @@ } } +static void BAYER_RENAME(rgb48_copy)(const uint8_t *src, int src_stride, uint8_t *ddst, int dst_stride, int width) +{ + uint16_t *dst = (uint16_t *)ddst; + int i; + + dst_stride /= 2; + for (i = 0 ; i < width; i+= 2) { + BAYER_TO_RGB48_COPY + src += 2 * BAYER_SIZEOF; + dst += 6; + } +} + +static void BAYER_RENAME(rgb48_interpolate)(const uint8_t *src, int src_stride, uint8_t *ddst, int dst_stride, int width) +{ + uint16_t *dst = (uint16_t *)ddst; + int i; + + dst_stride /= 2; + BAYER_TO_RGB48_COPY + src += 2 * BAYER_SIZEOF; + dst += 6; + + for (i = 2 ; i < width - 2; i+= 2) { + BAYER_TO_RGB48_INTERPOLATE + src += 2 * BAYER_SIZEOF; + dst += 6; + } + + if (width > 2) { + BAYER_TO_RGB48_COPY + } +} + static void BAYER_RENAME(yv12_copy)(const uint8_t *src, int src_stride, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, int luma_stride, int width, int32_t *rgb2yuv) { uint8_t dst[12]; @@ -203,6 +303,8 @@ #undef B #undef BAYER_TO_RGB24_COPY #undef BAYER_TO_RGB24_INTERPOLATE +#undef BAYER_TO_RGB48_COPY +#undef BAYER_TO_RGB48_INTERPOLATE #undef BAYER_RENAME diff -Nru ffmpeg-4.2.2/libswscale/input.c ffmpeg-4.4/libswscale/input.c --- ffmpeg-4.2.2/libswscale/input.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/input.c 2021-04-08 21:28:40.000000000 +0000 @@ -245,9 +245,11 @@ origin == AV_PIX_FMT_BGRA || \ origin == AV_PIX_FMT_ARGB || \ origin == AV_PIX_FMT_ABGR) \ - ? AV_RN32A(&src[(i) * 4]) \ - : (isBE(origin) ? AV_RB16(&src[(i) * 2]) \ - : AV_RL16(&src[(i) * 2]))) + ? AV_RN32A(&src[(i) * 4]) \ + : ((origin == AV_PIX_FMT_X2RGB10LE) \ + ? AV_RL32(&src[(i) * 4]) \ + : (isBE(origin) ? AV_RB16(&src[(i) * 2]) \ + : AV_RL16(&src[(i) * 2])))) static av_always_inline void rgb16_32ToY_c_template(int16_t *dst, const uint8_t *src, @@ -286,8 +288,8 @@ int gsh, int bsh, int S, int32_t *rgb2yuv) { - const int ru = rgb2yuv[RU_IDX] << rsh, gu = rgb2yuv[GU_IDX] << gsh, bu = rgb2yuv[BU_IDX] << bsh, - rv = rgb2yuv[RV_IDX] << rsh, gv = rgb2yuv[GV_IDX] << gsh, bv = rgb2yuv[BV_IDX] << bsh; + const int ru = rgb2yuv[RU_IDX] * (1 << rsh), gu = rgb2yuv[GU_IDX] * (1 << gsh), bu = rgb2yuv[BU_IDX] * (1 << bsh), + rv = rgb2yuv[RV_IDX] * (1 << rsh), gv = rgb2yuv[GV_IDX] * (1 << gsh), bv = rgb2yuv[BV_IDX] * (1 << bsh); const unsigned rnd = (256u<<((S)-1)) + (1<<(S-7)); int i; @@ -314,8 +316,8 @@ int gsh, int bsh, int S, int32_t *rgb2yuv) { - const int ru = rgb2yuv[RU_IDX] << rsh, gu = rgb2yuv[GU_IDX] << gsh, bu = rgb2yuv[BU_IDX] << bsh, - rv = rgb2yuv[RV_IDX] << rsh, gv = rgb2yuv[GV_IDX] << gsh, bv = rgb2yuv[BV_IDX] << bsh, + const int ru = rgb2yuv[RU_IDX] * (1 << rsh), gu = rgb2yuv[GU_IDX] * (1 << gsh), bu = rgb2yuv[BU_IDX] * (1 << bsh), + rv = rgb2yuv[RV_IDX] * (1 << rsh), gv = rgb2yuv[GV_IDX] * (1 << gsh), bv = rgb2yuv[BV_IDX] * (1 << bsh), maskgx = ~(maskr | maskb); const unsigned rnd = (256U<<(S)) + (1<<(S-6)); int i; @@ -391,6 +393,7 @@ rgb16_32_wrapper(AV_PIX_FMT_RGB565BE, rgb16be, 0, 0, 0, 0, 0xF800, 0x07E0, 0x001F, 0, 5, 11, RGB2YUV_SHIFT + 8) rgb16_32_wrapper(AV_PIX_FMT_RGB555BE, rgb15be, 0, 0, 0, 0, 0x7C00, 0x03E0, 0x001F, 0, 5, 10, RGB2YUV_SHIFT + 7) rgb16_32_wrapper(AV_PIX_FMT_RGB444BE, rgb12be, 0, 0, 0, 0, 0x0F00, 0x00F0, 0x000F, 0, 4, 8, RGB2YUV_SHIFT + 4) +rgb16_32_wrapper(AV_PIX_FMT_X2RGB10LE, rgb30le, 16, 6, 0, 0, 0x3FF00000, 0xFFC00, 0x3FF, 0, 0, 4, RGB2YUV_SHIFT + 6) static void gbr24pToUV_half_c(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *gsrc, const uint8_t *bsrc, const uint8_t *rsrc, @@ -437,7 +440,7 @@ int16_t *dst = (int16_t *)_dst; int i; for (i=0; i>2; } } @@ -446,7 +449,7 @@ int16_t *dst = (int16_t *)_dst; int i; for (i=0; i>2; } } @@ -457,7 +460,7 @@ for (i=0; i> 24)<<6; + dst[i]= (pal[d] >> 24)<<6 | pal[d]>>26; } } @@ -552,6 +555,24 @@ av_assert1(src1 == src2); } +static void y210le_UV_c(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused0, const uint8_t *src, + const uint8_t *unused1, int width, uint32_t *unused2) +{ + int i; + for (i = 0; i < width; i++) { + AV_WN16(dstU + i * 2, AV_RL16(src + i * 8 + 2) >> 6); + AV_WN16(dstV + i * 2, AV_RL16(src + i * 8 + 6) >> 6); + } +} + +static void y210le_Y_c(uint8_t *dst, const uint8_t *src, const uint8_t *unused0, + const uint8_t *unused1, int width, uint32_t *unused2) +{ + int i; + for (i = 0; i < width; i++) + AV_WN16(dst + i * 2, AV_RL16(src + i * 4) >> 6); +} + static void bswap16Y_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1, const uint8_t *unused2, int width, uint32_t *unused) { @@ -903,7 +924,7 @@ int b = rdpx(src[1] + i); int r = rdpx(src[2] + i); - dst[i] = ((ry*r + gy*g + by*b + (33 << (RGB2YUV_SHIFT + bpc - 9))) >> (RGB2YUV_SHIFT + shift - 14)); + dst[i] = (ry*r + gy*g + by*b + (16 << (RGB2YUV_SHIFT + bpc - 8)) + (1 << (RGB2YUV_SHIFT + shift - 15))) >> (RGB2YUV_SHIFT + shift - 14); } } @@ -936,10 +957,61 @@ int b = rdpx(src[1] + i); int r = rdpx(src[2] + i); - dstU[i] = (ru*r + gu*g + bu*b + (257 << (RGB2YUV_SHIFT + bpc - 9))) >> (RGB2YUV_SHIFT + shift - 14); - dstV[i] = (rv*r + gv*g + bv*b + (257 << (RGB2YUV_SHIFT + bpc - 9))) >> (RGB2YUV_SHIFT + shift - 14); + dstU[i] = (ru*r + gu*g + bu*b + (128 << (RGB2YUV_SHIFT + bpc - 8)) + (1 << (RGB2YUV_SHIFT + shift - 15))) >> (RGB2YUV_SHIFT + shift - 14); + dstV[i] = (rv*r + gv*g + bv*b + (128 << (RGB2YUV_SHIFT + bpc - 8)) + (1 << (RGB2YUV_SHIFT + shift - 15))) >> (RGB2YUV_SHIFT + shift - 14); + } +} +#undef rdpx + +#define rdpx(src) (is_be ? av_int2float(AV_RB32(src)): av_int2float(AV_RL32(src))) + +static av_always_inline void planar_rgbf32_to_a(uint8_t *_dst, const uint8_t *_src[4], int width, int is_be, int32_t *rgb2yuv) +{ + 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 * rdpx(src[3] + i))); + } +} + +static av_always_inline void planar_rgbf32_to_uv(uint8_t *_dstU, uint8_t *_dstV, const uint8_t *_src[4], int width, int is_be, int32_t *rgb2yuv) +{ + int i; + const float **src = (const float **)_src; + uint16_t *dstU = (uint16_t *)_dstU; + uint16_t *dstV = (uint16_t *)_dstV; + int32_t ru = rgb2yuv[RU_IDX], gu = rgb2yuv[GU_IDX], bu = rgb2yuv[BU_IDX]; + int32_t rv = rgb2yuv[RV_IDX], gv = rgb2yuv[GV_IDX], bv = rgb2yuv[BV_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))); + + dstU[i] = (ru*r + gu*g + bu*b + (0x10001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT; + dstV[i] = (rv*r + gv*g + bv*b + (0x10001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT; + } +} + +static av_always_inline void planar_rgbf32_to_y(uint8_t *_dst, const uint8_t *_src[4], int width, int is_be, int32_t *rgb2yuv) +{ + int i; + const float **src = (const float **)_src; + uint16_t *dst = (uint16_t *)_dst; + + 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))); + + 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, @@ -1004,6 +1076,26 @@ rgb9plus_planar_transparency_funcs(12) rgb9plus_planar_transparency_funcs(16) +#define rgbf32_planar_funcs_endian(endian_name, endian) \ +static void planar_rgbf32##endian_name##_to_y(uint8_t *dst, const uint8_t *src[4], \ + int w, int32_t *rgb2yuv) \ +{ \ + planar_rgbf32_to_y(dst, src, w, endian, rgb2yuv); \ +} \ +static void planar_rgbf32##endian_name##_to_uv(uint8_t *dstU, uint8_t *dstV, \ + const uint8_t *src[4], int w, int32_t *rgb2yuv) \ +{ \ + planar_rgbf32_to_uv(dstU, dstV, src, w, endian, rgb2yuv); \ +} \ +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); \ +} + +rgbf32_planar_funcs_endian(le, 0) +rgbf32_planar_funcs_endian(be, 1) + av_cold void ff_sws_init_input_funcs(SwsContext *c) { enum AVPixelFormat srcFormat = c->srcFormat; @@ -1052,6 +1144,10 @@ case AV_PIX_FMT_GBRP16LE: c->readChrPlanar = planar_rgb16le_to_uv; break; + case AV_PIX_FMT_GBRAPF32LE: + case AV_PIX_FMT_GBRPF32LE: + c->readChrPlanar = planar_rgbf32le_to_uv; + break; case AV_PIX_FMT_GBRP9BE: c->readChrPlanar = planar_rgb9be_to_uv; break; @@ -1070,6 +1166,10 @@ case AV_PIX_FMT_GBRP16BE: c->readChrPlanar = planar_rgb16be_to_uv; break; + case AV_PIX_FMT_GBRAPF32BE: + case AV_PIX_FMT_GBRPF32BE: + c->readChrPlanar = planar_rgbf32be_to_uv; + break; case AV_PIX_FMT_GBRAP: case AV_PIX_FMT_GBRP: c->readChrPlanar = planar_rgb_to_uv; @@ -1154,6 +1254,9 @@ case AV_PIX_FMT_P016BE: c->chrToYV12 = p016BEToUV_c; break; + case AV_PIX_FMT_Y210LE: + c->chrToYV12 = y210le_UV_c; + break; } if (c->chrSrcHSubSample) { switch (srcFormat) { @@ -1239,6 +1342,9 @@ case AV_PIX_FMT_RGB444BE: c->chrToYV12 = rgb12beToUV_half_c; break; + case AV_PIX_FMT_X2RGB10LE: + c->chrToYV12 = rgb30leToUV_half_c; + break; } } else { switch (srcFormat) { @@ -1320,6 +1426,9 @@ case AV_PIX_FMT_RGB444BE: c->chrToYV12 = rgb12beToUV_c; break; + case AV_PIX_FMT_X2RGB10LE: + c->chrToYV12 = rgb30leToUV_c; + break; } } @@ -1347,6 +1456,11 @@ case AV_PIX_FMT_GBRP16LE: c->readLumPlanar = planar_rgb16le_to_y; break; + case AV_PIX_FMT_GBRAPF32LE: + c->readAlpPlanar = planar_rgbf32le_to_a; + case AV_PIX_FMT_GBRPF32LE: + c->readLumPlanar = planar_rgbf32le_to_y; + break; case AV_PIX_FMT_GBRP9BE: c->readLumPlanar = planar_rgb9be_to_y; break; @@ -1368,6 +1482,11 @@ case AV_PIX_FMT_GBRP16BE: c->readLumPlanar = planar_rgb16be_to_y; break; + case AV_PIX_FMT_GBRAPF32BE: + c->readAlpPlanar = planar_rgbf32be_to_a; + case AV_PIX_FMT_GBRPF32BE: + c->readLumPlanar = planar_rgbf32be_to_y; + break; case AV_PIX_FMT_GBRAP: c->readAlpPlanar = planar_rgb_to_a; case AV_PIX_FMT_GBRP: @@ -1586,6 +1705,12 @@ c->lumToYV12 = grayf32ToY16_bswap_c; #endif break; + case AV_PIX_FMT_Y210LE: + c->lumToYV12 = y210le_Y_c; + break; + case AV_PIX_FMT_X2RGB10LE: + c->lumToYV12 =rgb30leToY_c; + break; } if (c->needAlpha) { if (is16BPS(srcFormat) || isNBPS(srcFormat)) { diff -Nru ffmpeg-4.2.2/libswscale/Makefile ffmpeg-4.4/libswscale/Makefile --- ffmpeg-4.2.2/libswscale/Makefile 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libswscale/Makefile 2021-04-08 21:28:40.000000000 +0000 @@ -25,5 +25,6 @@ SLIBOBJS-$(HAVE_GNU_WINDRES) += swscaleres.o TESTPROGS = colorspace \ + floatimg_cmp \ pixdesc_query \ swscale \ diff -Nru ffmpeg-4.2.2/libswscale/output.c ffmpeg-4.4/libswscale/output.c --- ffmpeg-4.2.2/libswscale/output.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/output.c 2021-04-08 21:28:40.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/cpu.h" #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" +#include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" #include "config.h" #include "rgb2rgb.h" @@ -180,7 +181,8 @@ } } -static void yuv2p016cX_c(SwsContext *c, const int16_t *chrFilter, int chrFilterSize, +static void yuv2p016cX_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) { @@ -188,7 +190,7 @@ const int32_t **uSrc = (const int32_t **)chrUSrc; const int32_t **vSrc = (const int32_t **)chrVSrc; int shift = 15; - int big_endian = c->dstFormat == AV_PIX_FMT_P016BE; + int big_endian = dstFormat == AV_PIX_FMT_P016BE; int i, j; for (i = 0; i < chrDstW; i++) { @@ -402,12 +404,11 @@ } } -static void yuv2nv12cX_c(SwsContext *c, const int16_t *chrFilter, int chrFilterSize, - const int16_t **chrUSrc, const int16_t **chrVSrc, - uint8_t *dest, int chrDstW) +static void yuv2nv12cX_c(enum AVPixelFormat dstFormat, const uint8_t *chrDither, + const int16_t *chrFilter, int chrFilterSize, + const int16_t **chrUSrc, const int16_t **chrVSrc, + uint8_t *dest, int chrDstW) { - enum AVPixelFormat dstFormat = c->dstFormat; - const uint8_t *chrDither = c->chrDither8; int i; if (dstFormat == AV_PIX_FMT_NV12 || @@ -477,13 +478,14 @@ } } -static void yuv2p010cX_c(SwsContext *c, const int16_t *chrFilter, int chrFilterSize, +static void yuv2p010cX_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) { uint16_t *dest = (uint16_t*)dest8; int shift = 17; - int big_endian = c->dstFormat == AV_PIX_FMT_P010BE; + int big_endian = dstFormat == AV_PIX_FMT_P010BE; int i, j; for (i = 0; i < chrDstW; i++) { @@ -630,28 +632,28 @@ } c->dither_error[0][i] = err; } else { - for (i = 0; i < dstW; i += 8) { - int Y, acc = 0; + for (i = 0; i < dstW; i += 8) { + int Y, acc = 0; - Y = (buf0[i + 0] * yalpha1 + buf1[i + 0] * yalpha) >> 19; - accumulate_bit(acc, Y + d128[0]); - Y = (buf0[i + 1] * yalpha1 + buf1[i + 1] * yalpha) >> 19; - accumulate_bit(acc, Y + d128[1]); - Y = (buf0[i + 2] * yalpha1 + buf1[i + 2] * yalpha) >> 19; - accumulate_bit(acc, Y + d128[2]); - Y = (buf0[i + 3] * yalpha1 + buf1[i + 3] * yalpha) >> 19; - accumulate_bit(acc, Y + d128[3]); - Y = (buf0[i + 4] * yalpha1 + buf1[i + 4] * yalpha) >> 19; - accumulate_bit(acc, Y + d128[4]); - Y = (buf0[i + 5] * yalpha1 + buf1[i + 5] * yalpha) >> 19; - accumulate_bit(acc, Y + d128[5]); - Y = (buf0[i + 6] * yalpha1 + buf1[i + 6] * yalpha) >> 19; - accumulate_bit(acc, Y + d128[6]); - Y = (buf0[i + 7] * yalpha1 + buf1[i + 7] * yalpha) >> 19; - accumulate_bit(acc, Y + d128[7]); + Y = (buf0[i + 0] * yalpha1 + buf1[i + 0] * yalpha) >> 19; + accumulate_bit(acc, Y + d128[0]); + Y = (buf0[i + 1] * yalpha1 + buf1[i + 1] * yalpha) >> 19; + accumulate_bit(acc, Y + d128[1]); + Y = (buf0[i + 2] * yalpha1 + buf1[i + 2] * yalpha) >> 19; + accumulate_bit(acc, Y + d128[2]); + Y = (buf0[i + 3] * yalpha1 + buf1[i + 3] * yalpha) >> 19; + accumulate_bit(acc, Y + d128[3]); + Y = (buf0[i + 4] * yalpha1 + buf1[i + 4] * yalpha) >> 19; + accumulate_bit(acc, Y + d128[4]); + Y = (buf0[i + 5] * yalpha1 + buf1[i + 5] * yalpha) >> 19; + accumulate_bit(acc, Y + d128[5]); + Y = (buf0[i + 6] * yalpha1 + buf1[i + 6] * yalpha) >> 19; + accumulate_bit(acc, Y + d128[6]); + Y = (buf0[i + 7] * yalpha1 + buf1[i + 7] * yalpha) >> 19; + accumulate_bit(acc, Y + d128[7]); - output_pixel(*dest++, acc); - } + output_pixel(*dest++, acc); + } } } @@ -687,19 +689,19 @@ } c->dither_error[0][i] = err; } else { - for (i = 0; i < dstW; i += 8) { - int acc = 0; - accumulate_bit(acc, ((buf0[i + 0] + 64) >> 7) + d128[0]); - accumulate_bit(acc, ((buf0[i + 1] + 64) >> 7) + d128[1]); - accumulate_bit(acc, ((buf0[i + 2] + 64) >> 7) + d128[2]); - accumulate_bit(acc, ((buf0[i + 3] + 64) >> 7) + d128[3]); - accumulate_bit(acc, ((buf0[i + 4] + 64) >> 7) + d128[4]); - accumulate_bit(acc, ((buf0[i + 5] + 64) >> 7) + d128[5]); - accumulate_bit(acc, ((buf0[i + 6] + 64) >> 7) + d128[6]); - accumulate_bit(acc, ((buf0[i + 7] + 64) >> 7) + d128[7]); + for (i = 0; i < dstW; i += 8) { + int acc = 0; + accumulate_bit(acc, ((buf0[i + 0] + 64) >> 7) + d128[0]); + accumulate_bit(acc, ((buf0[i + 1] + 64) >> 7) + d128[1]); + accumulate_bit(acc, ((buf0[i + 2] + 64) >> 7) + d128[2]); + accumulate_bit(acc, ((buf0[i + 3] + 64) >> 7) + d128[3]); + accumulate_bit(acc, ((buf0[i + 4] + 64) >> 7) + d128[4]); + accumulate_bit(acc, ((buf0[i + 5] + 64) >> 7) + d128[5]); + accumulate_bit(acc, ((buf0[i + 6] + 64) >> 7) + d128[6]); + accumulate_bit(acc, ((buf0[i + 7] + 64) >> 7) + d128[7]); - output_pixel(*dest++, acc); - } + output_pixel(*dest++, acc); + } } } @@ -904,25 +906,28 @@ for (i = 0; i < dstW; i++) { int j; - int Y = 1 << 18; - int64_t A = 0xffff<<14; + int Y = -0x40000000; + int A = 0xffff; for (j = 0; j < lumFilterSize; j++) Y += lumSrc[j][i] * lumFilter[j]; Y >>= 15; + Y += (1<<3) + 0x8000; Y = av_clip_uint16(Y); if (hasAlpha) { + A = -0x40000000 + (1<<14); for (j = 0; j < lumFilterSize; j++) A += alpSrc[j][i] * lumFilter[j]; A >>= 15; + A += 0x8000; A = av_clip_uint16(A); } output_pixel(&dest[2 * i ], Y); - output_pixel(&dest[2 * i + 1], hasAlpha ? A : 65535); + output_pixel(&dest[2 * i + 1], A); } } @@ -1599,6 +1604,13 @@ dest[i * 2 + 0] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1]; dest[i * 2 + 1] = r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2]; + } else if (target == AV_PIX_FMT_X2RGB10) { + uint32_t *dest = (uint32_t *) _dest; + const uint32_t *r = (const uint32_t *) _r; + const uint32_t *g = (const uint32_t *) _g; + const uint32_t *b = (const uint32_t *) _b; + dest[i * 2 + 0] = r[Y1] + g[Y1] + b[Y1]; + dest[i * 2 + 1] = r[Y2] + g[Y2] + b[Y2]; } else /* 8/4 bits */ { uint8_t *dest = (uint8_t *) _dest; const uint8_t *r = (const uint8_t *) _r; @@ -1836,6 +1848,7 @@ YUV2RGBWRAPPER(yuv2rgb,, 8, AV_PIX_FMT_RGB8, 0) YUV2RGBWRAPPER(yuv2rgb,, 4, AV_PIX_FMT_RGB4, 0) YUV2RGBWRAPPER(yuv2rgb,, 4b, AV_PIX_FMT_RGB4_BYTE, 0) +YUV2RGBWRAPPER(yuv2, rgb, x2rgb10, AV_PIX_FMT_X2RGB10, 0) static av_always_inline void yuv2rgb_write_full(SwsContext *c, uint8_t *dest, int i, int Y, int A, int U, int V, @@ -1847,9 +1860,9 @@ Y -= c->yuv2rgb_y_offset; Y *= c->yuv2rgb_y_coeff; Y += 1 << 21; - R = Y + V*c->yuv2rgb_v2r_coeff; - G = Y + V*c->yuv2rgb_v2g_coeff + U*c->yuv2rgb_u2g_coeff; - B = Y + U*c->yuv2rgb_u2b_coeff; + R = (unsigned)Y + V*c->yuv2rgb_v2r_coeff; + G = (unsigned)Y + V*c->yuv2rgb_v2g_coeff + U*c->yuv2rgb_u2g_coeff; + B = (unsigned)Y + U*c->yuv2rgb_u2b_coeff; if ((R | G | B) & 0xC0000000) { R = av_clip_uintp2(R, 30); G = av_clip_uintp2(G, 30); @@ -2090,7 +2103,7 @@ if (uvalpha < 2048) { int A = 0; //init to silence warning for (i = 0; i < dstW; i++) { - int Y = buf0[i] << 2; + int Y = buf0[i] * 4; int U = (ubuf0[i] - (128<<7)) * 4; int V = (vbuf0[i] - (128<<7)) * 4; @@ -2107,9 +2120,9 @@ const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1]; int A = 0; //init to silence warning for (i = 0; i < dstW; i++) { - int Y = buf0[i] << 2; - int U = (ubuf0[i] + ubuf1[i] - (128<<8)) << 1; - int V = (vbuf0[i] + vbuf1[i] - (128<<8)) << 1; + int Y = buf0[i] * 4; + int U = (ubuf0[i] + ubuf1[i] - (128<<8)) * 2; + int V = (vbuf0[i] + vbuf1[i] - (128<<8)) * 2; if (hasAlpha) { A = (abuf0[i] + 64) >> 7; @@ -2275,7 +2288,7 @@ A = -0x40000000; for (j = 0; j < lumFilterSize; j++) - A += alpSrc[j][i] * lumFilter[j]; + A += alpSrc[j][i] * (unsigned)lumFilter[j]; A >>= 1; A += 0x20002000; @@ -2310,6 +2323,82 @@ } static void +yuv2gbrpf32_full_X_c(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) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat); + int i; + int hasAlpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) && alpSrcx; + uint32_t **dest32 = (uint32_t**)dest; + const int32_t **lumSrc = (const int32_t**)lumSrcx; + const int32_t **chrUSrc = (const int32_t**)chrUSrcx; + const int32_t **chrVSrc = (const int32_t**)chrVSrcx; + const int32_t **alpSrc = (const int32_t**)alpSrcx; + static const float float_mult = 1.0f / 65535.0f; + + for (i = 0; i < dstW; i++) { + int j; + int Y = -0x40000000; + int U = -(128 << 23); + int V = -(128 << 23); + int R, G, B, A; + + for (j = 0; j < lumFilterSize; j++) + Y += lumSrc[j][i] * (unsigned)lumFilter[j]; + + for (j = 0; j < chrFilterSize; j++) { + U += chrUSrc[j][i] * (unsigned)chrFilter[j]; + V += chrVSrc[j][i] * (unsigned)chrFilter[j]; + } + + Y >>= 14; + Y += 0x10000; + U >>= 14; + V >>= 14; + + if (hasAlpha) { + A = -0x40000000; + + for (j = 0; j < lumFilterSize; j++) + A += alpSrc[j][i] * (unsigned)lumFilter[j]; + + A >>= 1; + A += 0x20002000; + } + + Y -= c->yuv2rgb_y_offset; + Y *= c->yuv2rgb_y_coeff; + Y += 1 << 13; + R = V * c->yuv2rgb_v2r_coeff; + G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff; + B = U * c->yuv2rgb_u2b_coeff; + + R = av_clip_uintp2(Y + R, 30); + G = av_clip_uintp2(Y + G, 30); + B = av_clip_uintp2(Y + B, 30); + + dest32[0][i] = av_float2int(float_mult * (float)(G >> 14)); + dest32[1][i] = av_float2int(float_mult * (float)(B >> 14)); + dest32[2][i] = av_float2int(float_mult * (float)(R >> 14)); + if (hasAlpha) + dest32[3][i] = av_float2int(float_mult * (float)(av_clip_uintp2(A, 30) >> 14)); + } + if ((!isBE(c->dstFormat)) != (!HAVE_BIGENDIAN)) { + for (i = 0; i < dstW; i++) { + dest32[0][i] = av_bswap32(dest32[0][i]); + dest32[1][i] = av_bswap32(dest32[1][i]); + dest32[2][i] = av_bswap32(dest32[2][i]); + if (hasAlpha) + dest32[3][i] = av_bswap32(dest32[3][i]); + } + } +} + +static void yuv2ya8_1_c(SwsContext *c, const int16_t *buf0, const int16_t *ubuf[2], const int16_t *vbuf[2], const int16_t *abuf0, uint8_t *dest, int dstW, @@ -2713,6 +2802,12 @@ case AV_PIX_FMT_GBRAP16LE: *yuv2anyX = yuv2gbrp16_full_X_c; break; + case AV_PIX_FMT_GBRPF32BE: + case AV_PIX_FMT_GBRPF32LE: + case AV_PIX_FMT_GBRAPF32BE: + case AV_PIX_FMT_GBRAPF32LE: + *yuv2anyX = yuv2gbrpf32_full_X_c; + break; } if (!*yuv2packedX && !*yuv2anyX) goto YUV_PACKED; @@ -2889,6 +2984,12 @@ *yuv2packed2 = yuv2rgb4b_2_c; *yuv2packedX = yuv2rgb4b_X_c; break; + case AV_PIX_FMT_X2RGB10LE: + case AV_PIX_FMT_X2RGB10BE: + *yuv2packed1 = yuv2x2rgb10_1_c; + *yuv2packed2 = yuv2x2rgb10_2_c; + *yuv2packedX = yuv2x2rgb10_X_c; + break; } } switch (dstFormat) { diff -Nru ffmpeg-4.2.2/libswscale/ppc/swscale_altivec.c ffmpeg-4.4/libswscale/ppc/swscale_altivec.c --- ffmpeg-4.2.2/libswscale/ppc/swscale_altivec.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/ppc/swscale_altivec.c 2020-07-11 10:39:30.000000000 +0000 @@ -153,13 +153,13 @@ const int add = (1 << (shift - 1)); const int clip = (1 << 16) - 1; const float fmult = 1.0f / 65535.0f; - const vector uint32_t vadd = (vector uint32_t) {add, add, add, add}; - const vector uint32_t vshift = (vector uint32_t) vec_splat_u32(shift); - const vector uint32_t vlargest = (vector uint32_t) {clip, clip, clip, clip}; - const vector float vmul = (vector float) {fmult, fmult, fmult, fmult}; - const vector float vzero = (vector float) {0, 0, 0, 0}; - vector uint32_t v; - vector float vd; + const vec_u32 vadd = (vec_u32) {add, add, add, add}; + const vec_u32 vshift = (vec_u32) vec_splat_u32(shift); + const vec_u32 vlargest = (vec_u32) {clip, clip, clip, clip}; + const vec_f vmul = (vec_f) {fmult, fmult, fmult, fmult}; + const vec_f vzero = (vec_f) {0, 0, 0, 0}; + vec_u32 v; + vec_f vd; int i; yuv2plane1_float_u(src, dest, dst_u, 0); @@ -186,15 +186,15 @@ const int add = (1 << (shift - 1)); const int clip = (1 << 16) - 1; const float fmult = 1.0f / 65535.0f; - const vector uint32_t vadd = (vector uint32_t) {add, add, add, add}; - const vector uint32_t vshift = (vector uint32_t) vec_splat_u32(shift); - const vector uint32_t vlargest = (vector uint32_t) {clip, clip, clip, clip}; - const vector float vmul = (vector float) {fmult, fmult, fmult, fmult}; - const vector float vzero = (vector float) {0, 0, 0, 0}; - const vector uint32_t vswapbig = (vector uint32_t) {16, 16, 16, 16}; - const vector uint16_t vswapsmall = vec_splat_u16(8); - vector uint32_t v; - vector float vd; + const vec_u32 vadd = (vec_u32) {add, add, add, add}; + const vec_u32 vshift = (vec_u32) vec_splat_u32(shift); + const vec_u32 vlargest = (vec_u32) {clip, clip, clip, clip}; + const vec_f vmul = (vec_f) {fmult, fmult, fmult, fmult}; + const vec_f vzero = (vec_f) {0, 0, 0, 0}; + const vec_u32 vswapbig = (vec_u32) {16, 16, 16, 16}; + const vec_u16 vswapsmall = vec_splat_u16(8); + vec_u32 v; + vec_f vd; int i; yuv2plane1_float_bswap_u(src, dest, dst_u, 0); @@ -208,8 +208,8 @@ vd = vec_ctf(v, 0); vd = vec_madd(vd, vmul, vzero); - vd = (vector float) vec_rl((vector uint32_t) vd, vswapbig); - vd = (vector float) vec_rl((vector uint16_t) vd, vswapsmall); + vd = (vec_f) vec_rl((vec_u32) vd, vswapbig); + vd = (vec_f) vec_rl((vec_u16) vd, vswapsmall); vec_st(vd, 0, (float *) &dest[i]); } diff -Nru ffmpeg-4.2.2/libswscale/ppc/swscale_ppc_template.c ffmpeg-4.4/libswscale/ppc/swscale_ppc_template.c --- ffmpeg-4.2.2/libswscale/ppc/swscale_ppc_template.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/ppc/swscale_ppc_template.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,6 +21,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mem_internal.h" + static void FUNC(yuv2planeX_8_16)(const int16_t *filter, int filterSize, const int16_t **src, uint8_t *dest, const uint8_t *dither, int offset, int x) diff -Nru ffmpeg-4.2.2/libswscale/ppc/swscale_vsx.c ffmpeg-4.4/libswscale/ppc/swscale_vsx.c --- ffmpeg-4.2.2/libswscale/ppc/swscale_vsx.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/ppc/swscale_vsx.c 2021-04-08 21:28:40.000000000 +0000 @@ -28,6 +28,7 @@ #include "libswscale/swscale_internal.h" #include "libavutil/attributes.h" #include "libavutil/cpu.h" +#include "libavutil/mem_internal.h" #include "yuv2rgb_altivec.h" #include "libavutil/ppc/util_altivec.h" @@ -103,9 +104,9 @@ const int dst_u = -(uintptr_t)dest & 15; int i, j; LOCAL_ALIGNED(16, int16_t, val, [16]); - const vector uint16_t shifts = (vector uint16_t) {7, 7, 7, 7, 7, 7, 7, 7}; - vector int16_t vi, vileft, ditherleft, ditherright; - vector uint8_t vd; + const vec_u16 shifts = (vec_u16) {7, 7, 7, 7, 7, 7, 7, 7}; + vec_s16 vi, vileft, ditherleft, ditherright; + vec_u8 vd; for (j = 0; j < 16; j++) { val[j] = dither[(dst_u + offset + j) & 7]; @@ -154,18 +155,20 @@ } } -static void yuv2plane1_nbps_vsx(const int16_t *src, uint16_t *dest, int dstW, - int big_endian, int output_bits) +static av_always_inline void yuv2plane1_nbps_vsx(const int16_t *src, + uint16_t *dest, int dstW, + const int big_endian, + const int output_bits) { const int dst_u = -(uintptr_t)dest & 7; const int shift = 15 - output_bits; const int add = (1 << (shift - 1)); const int clip = (1 << output_bits) - 1; - const vector uint16_t vadd = (vector uint16_t) {add, add, add, add, add, add, add, add}; - const vector uint16_t vswap = (vector uint16_t) vec_splat_u16(big_endian ? 8 : 0); - const vector uint16_t vshift = (vector uint16_t) vec_splat_u16(shift); - const vector uint16_t vlargest = (vector uint16_t) {clip, clip, clip, clip, clip, clip, clip, clip}; - vector uint16_t v; + const vec_u16 vadd = (vec_u16) {add, add, add, add, add, add, add, add}; + const vec_u16 vswap = (vec_u16) vec_splat_u16(big_endian ? 8 : 0); + const vec_u16 vshift = (vec_u16) vec_splat_u16(shift); + const vec_u16 vlargest = (vec_u16) {clip, clip, clip, clip, clip, clip, clip, clip}; + vec_u16 v; int i; yuv2plane1_nbps_u(src, dest, dst_u, big_endian, output_bits, 0); @@ -209,20 +212,20 @@ const int add = (1 << (shift - 1)); const int clip = (1 << output_bits) - 1; const uint16_t swap = big_endian ? 8 : 0; - const vector uint32_t vadd = (vector uint32_t) {add, add, add, add}; - const vector uint32_t vshift = (vector uint32_t) {shift, shift, shift, shift}; - const vector uint16_t vswap = (vector uint16_t) {swap, swap, swap, swap, swap, swap, swap, swap}; - const vector uint16_t vlargest = (vector uint16_t) {clip, clip, clip, clip, clip, clip, clip, clip}; - const vector int16_t vzero = vec_splat_s16(0); - const vector uint8_t vperm = (vector uint8_t) {0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15}; - vector int16_t vfilter[MAX_FILTER_SIZE], vin; - vector uint16_t v; - vector uint32_t vleft, vright, vtmp; + const vec_u32 vadd = (vec_u32) {add, add, add, add}; + const vec_u32 vshift = (vec_u32) {shift, shift, shift, shift}; + const vec_u16 vswap = (vec_u16) {swap, swap, swap, swap, swap, swap, swap, swap}; + const vec_u16 vlargest = (vec_u16) {clip, clip, clip, clip, clip, clip, clip, clip}; + const vec_s16 vzero = vec_splat_s16(0); + const vec_u8 vperm = (vec_u8) {0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15}; + vec_s16 vfilter[MAX_FILTER_SIZE], vin; + vec_u16 v; + vec_u32 vleft, vright, vtmp; int i, j; for (i = 0; i < filterSize; i++) { - vfilter[i] = (vector int16_t) {filter[i], filter[i], filter[i], filter[i], - filter[i], filter[i], filter[i], filter[i]}; + vfilter[i] = (vec_s16) {filter[i], filter[i], filter[i], filter[i], + filter[i], filter[i], filter[i], filter[i]}; } yuv2planeX_nbps_u(filter, filterSize, src, dest, dst_u, big_endian, output_bits, 0); @@ -232,16 +235,16 @@ for (j = 0; j < filterSize; j++) { vin = vec_vsx_ld(0, &src[j][i]); - vtmp = (vector uint32_t) vec_mule(vin, vfilter[j]); + vtmp = (vec_u32) vec_mule(vin, vfilter[j]); vleft = vec_add(vleft, vtmp); - vtmp = (vector uint32_t) vec_mulo(vin, vfilter[j]); + vtmp = (vec_u32) vec_mulo(vin, vfilter[j]); vright = vec_add(vright, vtmp); } vleft = vec_sra(vleft, vshift); vright = vec_sra(vright, vshift); v = vec_packsu(vleft, vright); - v = (vector uint16_t) vec_max((vector int16_t) v, vzero); + v = (vec_u16) vec_max((vec_s16) v, vzero); v = vec_min(v, vlargest); v = vec_rl(v, vswap); v = vec_perm(v, v, vperm); @@ -273,17 +276,19 @@ } } -static void yuv2plane1_16_vsx(const int32_t *src, uint16_t *dest, int dstW, - int big_endian, int output_bits) +static av_always_inline void yuv2plane1_16_vsx(const int32_t *src, + uint16_t *dest, int dstW, + const int big_endian, + int output_bits) { const int dst_u = -(uintptr_t)dest & 7; const int shift = 3; const int add = (1 << (shift - 1)); - const vector uint32_t vadd = (vector uint32_t) {add, add, add, add}; - const vector uint16_t vswap = (vector uint16_t) vec_splat_u16(big_endian ? 8 : 0); - const vector uint32_t vshift = (vector uint32_t) vec_splat_u32(shift); - vector uint32_t v, v2; - vector uint16_t vd; + const vec_u32 vadd = (vec_u32) {add, add, add, add}; + const vec_u16 vswap = (vec_u16) vec_splat_u16(big_endian ? 8 : 0); + const vec_u32 vshift = (vec_u32) vec_splat_u32(shift); + vec_u32 v, v2; + vec_u16 vd; int i; yuv2plane1_16_u(src, dest, dst_u, big_endian, output_bits, 0); @@ -341,18 +346,18 @@ const int bias = 0x8000; const int add = (1 << (shift - 1)) - 0x40000000; const uint16_t swap = big_endian ? 8 : 0; - const vector uint32_t vadd = (vector uint32_t) {add, add, add, add}; - const vector uint32_t vshift = (vector uint32_t) {shift, shift, shift, shift}; - const vector uint16_t vswap = (vector uint16_t) {swap, swap, swap, swap, swap, swap, swap, swap}; - const vector uint16_t vbias = (vector uint16_t) {bias, bias, bias, bias, bias, bias, bias, bias}; - vector int32_t vfilter[MAX_FILTER_SIZE]; - vector uint16_t v; - vector uint32_t vleft, vright, vtmp; - vector int32_t vin32l, vin32r; + const vec_u32 vadd = (vec_u32) {add, add, add, add}; + const vec_u32 vshift = (vec_u32) {shift, shift, shift, shift}; + const vec_u16 vswap = (vec_u16) {swap, swap, swap, swap, swap, swap, swap, swap}; + const vec_u16 vbias = (vec_u16) {bias, bias, bias, bias, bias, bias, bias, bias}; + vec_s32 vfilter[MAX_FILTER_SIZE]; + vec_u16 v; + vec_u32 vleft, vright, vtmp; + vec_s32 vin32l, vin32r; int i, j; for (i = 0; i < filterSize; i++) { - vfilter[i] = (vector int32_t) {filter[i], filter[i], filter[i], filter[i]}; + vfilter[i] = (vec_s32) {filter[i], filter[i], filter[i], filter[i]}; } yuv2planeX_16_u(filter, filterSize, src, dest, dst_u, big_endian, output_bits, 0); @@ -364,15 +369,15 @@ vin32l = vec_vsx_ld(0, &src[j][i]); vin32r = vec_vsx_ld(0, &src[j][i + 4]); - vtmp = (vector uint32_t) vec_mul(vin32l, vfilter[j]); + vtmp = (vec_u32) vec_mul(vin32l, vfilter[j]); vleft = vec_add(vleft, vtmp); - vtmp = (vector uint32_t) vec_mul(vin32r, vfilter[j]); + vtmp = (vec_u32) vec_mul(vin32r, vfilter[j]); vright = vec_add(vright, vtmp); } vleft = vec_sra(vleft, vshift); vright = vec_sra(vright, vshift); - v = (vector uint16_t) vec_packs((vector int32_t) vleft, (vector int32_t) vright); + v = (vec_u16) vec_packs((vec_s32) vleft, (vec_s32) vright); v = vec_add(v, vbias); v = vec_rl(v, vswap); vec_st(v, 0, &dest[i]); @@ -478,9 +483,9 @@ out0 = vec_mergeh(bd, gd); \ out1 = vec_mergeh(rd, ad); \ \ - tmp8 = (vector uint8_t) vec_mergeh((vector uint16_t) out0, (vector uint16_t) out1); \ + tmp8 = (vec_u8) vec_mergeh((vec_u16) out0, (vec_u16) out1); \ vec_vsx_st(tmp8, 0, dest); \ - tmp8 = (vector uint8_t) vec_mergel((vector uint16_t) out0, (vector uint16_t) out1); \ + tmp8 = (vec_u8) vec_mergel((vec_u16) out0, (vec_u16) out1); \ vec_vsx_st(tmp8, 16, dest); \ \ dest += 32; \ @@ -489,9 +494,9 @@ out0 = vec_mergeh(rd, gd); \ out1 = vec_mergeh(bd, ad); \ \ - tmp8 = (vector uint8_t) vec_mergeh((vector uint16_t) out0, (vector uint16_t) out1); \ + tmp8 = (vec_u8) vec_mergeh((vec_u16) out0, (vec_u16) out1); \ vec_vsx_st(tmp8, 0, dest); \ - tmp8 = (vector uint8_t) vec_mergel((vector uint16_t) out0, (vector uint16_t) out1); \ + tmp8 = (vec_u8) vec_mergel((vec_u16) out0, (vec_u16) out1); \ vec_vsx_st(tmp8, 16, dest); \ \ dest += 32; \ @@ -500,9 +505,9 @@ out0 = vec_mergeh(ad, rd); \ out1 = vec_mergeh(gd, bd); \ \ - tmp8 = (vector uint8_t) vec_mergeh((vector uint16_t) out0, (vector uint16_t) out1); \ + tmp8 = (vec_u8) vec_mergeh((vec_u16) out0, (vec_u16) out1); \ vec_vsx_st(tmp8, 0, dest); \ - tmp8 = (vector uint8_t) vec_mergel((vector uint16_t) out0, (vector uint16_t) out1); \ + tmp8 = (vec_u8) vec_mergel((vec_u16) out0, (vec_u16) out1); \ vec_vsx_st(tmp8, 16, dest); \ \ dest += 32; \ @@ -511,9 +516,9 @@ out0 = vec_mergeh(ad, bd); \ out1 = vec_mergeh(gd, rd); \ \ - tmp8 = (vector uint8_t) vec_mergeh((vector uint16_t) out0, (vector uint16_t) out1); \ + tmp8 = (vec_u8) vec_mergeh((vec_u16) out0, (vec_u16) out1); \ vec_vsx_st(tmp8, 0, dest); \ - tmp8 = (vector uint8_t) vec_mergel((vector uint16_t) out0, (vector uint16_t) out1); \ + tmp8 = (vec_u8) vec_mergel((vec_u16) out0, (vec_u16) out1); \ vec_vsx_st(tmp8, 16, dest); \ \ dest += 32; \ @@ -528,48 +533,48 @@ const int16_t **alpSrc, uint8_t *dest, int dstW, int y, enum AVPixelFormat target, int hasAlpha) { - vector int16_t vv; - vector int32_t vy32_l, vy32_r, vu32_l, vu32_r, vv32_l, vv32_r, tmp32; - vector int32_t R_l, R_r, G_l, G_r, B_l, B_r; - vector int32_t tmp, tmp2, tmp3, tmp4; - vector uint16_t rd16, gd16, bd16; - vector uint8_t rd, bd, gd, ad, out0, out1, tmp8; - vector int16_t vlumFilter[MAX_FILTER_SIZE], vchrFilter[MAX_FILTER_SIZE]; - const vector int32_t ystart = vec_splats(1 << 9); - const vector int32_t uvstart = vec_splats((1 << 9) - (128 << 19)); - const vector uint16_t zero16 = vec_splat_u16(0); - const vector int32_t y_offset = vec_splats(c->yuv2rgb_y_offset); - const vector int32_t y_coeff = vec_splats(c->yuv2rgb_y_coeff); - const vector int32_t y_add = vec_splats(1 << 21); - const vector int32_t v2r_coeff = vec_splats(c->yuv2rgb_v2r_coeff); - const vector int32_t v2g_coeff = vec_splats(c->yuv2rgb_v2g_coeff); - const vector int32_t u2g_coeff = vec_splats(c->yuv2rgb_u2g_coeff); - const vector int32_t u2b_coeff = vec_splats(c->yuv2rgb_u2b_coeff); - const vector int32_t rgbclip = vec_splats(1 << 30); - const vector int32_t zero32 = vec_splat_s32(0); - const vector uint32_t shift22 = vec_splats(22U); - const vector uint32_t shift10 = vec_splat_u32(10); + vec_s16 vv; + vec_s32 vy32_l, vy32_r, vu32_l, vu32_r, vv32_l, vv32_r, tmp32; + vec_s32 R_l, R_r, G_l, G_r, B_l, B_r; + vec_s32 tmp, tmp2, tmp3, tmp4; + vec_u16 rd16, gd16, bd16; + vec_u8 rd, bd, gd, ad, out0, out1, tmp8; + vec_s16 vlumFilter[MAX_FILTER_SIZE], vchrFilter[MAX_FILTER_SIZE]; + const vec_s32 ystart = vec_splats(1 << 9); + const vec_s32 uvstart = vec_splats((1 << 9) - (128 << 19)); + const vec_u16 zero16 = vec_splat_u16(0); + const vec_s32 y_offset = vec_splats(c->yuv2rgb_y_offset); + const vec_s32 y_coeff = vec_splats(c->yuv2rgb_y_coeff); + const vec_s32 y_add = vec_splats(1 << 21); + const vec_s32 v2r_coeff = vec_splats(c->yuv2rgb_v2r_coeff); + const vec_s32 v2g_coeff = vec_splats(c->yuv2rgb_v2g_coeff); + const vec_s32 u2g_coeff = vec_splats(c->yuv2rgb_u2g_coeff); + const vec_s32 u2b_coeff = vec_splats(c->yuv2rgb_u2b_coeff); + const vec_s32 rgbclip = vec_splats(1 << 30); + const vec_s32 zero32 = vec_splat_s32(0); + const vec_u32 shift22 = vec_splats(22U); + const vec_u32 shift10 = vec_splat_u32(10); int i, j; // Various permutations - const vector uint8_t perm3rg0 = (vector uint8_t) {0x0, 0x10, 0, - 0x1, 0x11, 0, - 0x2, 0x12, 0, - 0x3, 0x13, 0, - 0x4, 0x14, 0, - 0x5 }; - const vector uint8_t perm3rg1 = (vector uint8_t) { 0x15, 0, - 0x6, 0x16, 0, - 0x7, 0x17, 0 }; - const vector uint8_t perm3tb0 = (vector uint8_t) {0x0, 0x1, 0x10, - 0x3, 0x4, 0x11, - 0x6, 0x7, 0x12, - 0x9, 0xa, 0x13, - 0xc, 0xd, 0x14, - 0xf }; - const vector uint8_t perm3tb1 = (vector uint8_t) { 0x0, 0x15, - 0x2, 0x3, 0x16, - 0x5, 0x6, 0x17 }; + const vec_u8 perm3rg0 = (vec_u8) {0x0, 0x10, 0, + 0x1, 0x11, 0, + 0x2, 0x12, 0, + 0x3, 0x13, 0, + 0x4, 0x14, 0, + 0x5 }; + const vec_u8 perm3rg1 = (vec_u8) { 0x15, 0, + 0x6, 0x16, 0, + 0x7, 0x17, 0 }; + const vec_u8 perm3tb0 = (vec_u8) {0x0, 0x1, 0x10, + 0x3, 0x4, 0x11, + 0x6, 0x7, 0x12, + 0x9, 0xa, 0x13, + 0xc, 0xd, 0x14, + 0xf }; + const vec_u8 perm3tb1 = (vec_u8) { 0x0, 0x15, + 0x2, 0x3, 0x16, + 0x5, 0x6, 0x17 }; ad = vec_splats((uint8_t) 255); @@ -685,52 +690,52 @@ *abuf1 = hasAlpha ? abuf[1] : NULL; const int16_t yalpha1 = 4096 - yalpha; const int16_t uvalpha1 = 4096 - uvalpha; - vector int16_t vy, vu, vv, A = vec_splat_s16(0); - vector int32_t vy32_l, vy32_r, vu32_l, vu32_r, vv32_l, vv32_r, tmp32; - vector int32_t R_l, R_r, G_l, G_r, B_l, B_r; - vector int32_t tmp, tmp2, tmp3, tmp4, tmp5, tmp6; - vector uint16_t rd16, gd16, bd16; - vector uint8_t rd, bd, gd, ad, out0, out1, tmp8; - const vector int16_t vyalpha1 = vec_splats(yalpha1); - const vector int16_t vuvalpha1 = vec_splats(uvalpha1); - const vector int16_t vyalpha = vec_splats((int16_t) yalpha); - const vector int16_t vuvalpha = vec_splats((int16_t) uvalpha); - const vector uint16_t zero16 = vec_splat_u16(0); - const vector int32_t y_offset = vec_splats(c->yuv2rgb_y_offset); - const vector int32_t y_coeff = vec_splats(c->yuv2rgb_y_coeff); - const vector int32_t y_add = vec_splats(1 << 21); - const vector int32_t v2r_coeff = vec_splats(c->yuv2rgb_v2r_coeff); - const vector int32_t v2g_coeff = vec_splats(c->yuv2rgb_v2g_coeff); - const vector int32_t u2g_coeff = vec_splats(c->yuv2rgb_u2g_coeff); - const vector int32_t u2b_coeff = vec_splats(c->yuv2rgb_u2b_coeff); - const vector int32_t rgbclip = vec_splats(1 << 30); - const vector int32_t zero32 = vec_splat_s32(0); - const vector uint32_t shift19 = vec_splats(19U); - const vector uint32_t shift22 = vec_splats(22U); - const vector uint32_t shift10 = vec_splat_u32(10); - const vector int32_t dec128 = vec_splats(128 << 19); - const vector int32_t add18 = vec_splats(1 << 18); + vec_s16 vy, vu, vv, A = vec_splat_s16(0); + vec_s32 vy32_l, vy32_r, vu32_l, vu32_r, vv32_l, vv32_r, tmp32; + vec_s32 R_l, R_r, G_l, G_r, B_l, B_r; + vec_s32 tmp, tmp2, tmp3, tmp4, tmp5, tmp6; + vec_u16 rd16, gd16, bd16; + vec_u8 rd, bd, gd, ad, out0, out1, tmp8; + const vec_s16 vyalpha1 = vec_splats(yalpha1); + const vec_s16 vuvalpha1 = vec_splats(uvalpha1); + const vec_s16 vyalpha = vec_splats((int16_t) yalpha); + const vec_s16 vuvalpha = vec_splats((int16_t) uvalpha); + const vec_u16 zero16 = vec_splat_u16(0); + const vec_s32 y_offset = vec_splats(c->yuv2rgb_y_offset); + const vec_s32 y_coeff = vec_splats(c->yuv2rgb_y_coeff); + const vec_s32 y_add = vec_splats(1 << 21); + const vec_s32 v2r_coeff = vec_splats(c->yuv2rgb_v2r_coeff); + const vec_s32 v2g_coeff = vec_splats(c->yuv2rgb_v2g_coeff); + const vec_s32 u2g_coeff = vec_splats(c->yuv2rgb_u2g_coeff); + const vec_s32 u2b_coeff = vec_splats(c->yuv2rgb_u2b_coeff); + const vec_s32 rgbclip = vec_splats(1 << 30); + const vec_s32 zero32 = vec_splat_s32(0); + const vec_u32 shift19 = vec_splats(19U); + const vec_u32 shift22 = vec_splats(22U); + const vec_u32 shift10 = vec_splat_u32(10); + const vec_s32 dec128 = vec_splats(128 << 19); + const vec_s32 add18 = vec_splats(1 << 18); int i; // Various permutations - const vector uint8_t perm3rg0 = (vector uint8_t) {0x0, 0x10, 0, - 0x1, 0x11, 0, - 0x2, 0x12, 0, - 0x3, 0x13, 0, - 0x4, 0x14, 0, - 0x5 }; - const vector uint8_t perm3rg1 = (vector uint8_t) { 0x15, 0, - 0x6, 0x16, 0, - 0x7, 0x17, 0 }; - const vector uint8_t perm3tb0 = (vector uint8_t) {0x0, 0x1, 0x10, - 0x3, 0x4, 0x11, - 0x6, 0x7, 0x12, - 0x9, 0xa, 0x13, - 0xc, 0xd, 0x14, - 0xf }; - const vector uint8_t perm3tb1 = (vector uint8_t) { 0x0, 0x15, - 0x2, 0x3, 0x16, - 0x5, 0x6, 0x17 }; + const vec_u8 perm3rg0 = (vec_u8) {0x0, 0x10, 0, + 0x1, 0x11, 0, + 0x2, 0x12, 0, + 0x3, 0x13, 0, + 0x4, 0x14, 0, + 0x5 }; + const vec_u8 perm3rg1 = (vec_u8) { 0x15, 0, + 0x6, 0x16, 0, + 0x7, 0x17, 0 }; + const vec_u8 perm3tb0 = (vec_u8) {0x0, 0x1, 0x10, + 0x3, 0x4, 0x11, + 0x6, 0x7, 0x12, + 0x9, 0xa, 0x13, + 0xc, 0xd, 0x14, + 0xf }; + const vec_u8 perm3tb1 = (vec_u8) { 0x0, 0x15, + 0x2, 0x3, 0x16, + 0x5, 0x6, 0x17 }; av_assert2(yalpha <= 4096U); av_assert2(uvalpha <= 4096U); @@ -759,7 +764,7 @@ tmp3 = vec_sra(tmp3, shift19); tmp4 = vec_sra(tmp4, shift19); A = vec_packs(tmp3, tmp4); - ad = vec_packsu(A, (vector int16_t) zero16); + ad = vec_packsu(A, (vec_s16) zero16); } else { ad = vec_splats((uint8_t) 255); } @@ -807,60 +812,60 @@ *abuf1 = hasAlpha ? abuf[1] : NULL; const int16_t yalpha1 = 4096 - yalpha; const int16_t uvalpha1 = 4096 - uvalpha; - vector int16_t vy, vu, vv, A = vec_splat_s16(0); - vector int32_t vy32_l, vy32_r, vu32_l, vu32_r, vv32_l, vv32_r, tmp32; - vector int32_t R_l, R_r, G_l, G_r, B_l, B_r, vud32_l, vud32_r, vvd32_l, vvd32_r; - vector int32_t tmp, tmp2, tmp3, tmp4, tmp5, tmp6; - vector uint16_t rd16, gd16, bd16; - vector uint8_t rd, bd, gd, ad, out0, out1, tmp8; - const vector int16_t vyalpha1 = vec_splats(yalpha1); - const vector int16_t vuvalpha1 = vec_splats(uvalpha1); - const vector int16_t vyalpha = vec_splats((int16_t) yalpha); - const vector int16_t vuvalpha = vec_splats((int16_t) uvalpha); - const vector uint16_t zero16 = vec_splat_u16(0); - const vector int32_t y_offset = vec_splats(c->yuv2rgb_y_offset); - const vector int32_t y_coeff = vec_splats(c->yuv2rgb_y_coeff); - const vector int32_t y_add = vec_splats(1 << 21); - const vector int32_t v2r_coeff = vec_splats(c->yuv2rgb_v2r_coeff); - const vector int32_t v2g_coeff = vec_splats(c->yuv2rgb_v2g_coeff); - const vector int32_t u2g_coeff = vec_splats(c->yuv2rgb_u2g_coeff); - const vector int32_t u2b_coeff = vec_splats(c->yuv2rgb_u2b_coeff); - const vector int32_t rgbclip = vec_splats(1 << 30); - const vector int32_t zero32 = vec_splat_s32(0); - const vector uint32_t shift19 = vec_splats(19U); - const vector uint32_t shift22 = vec_splats(22U); - const vector uint32_t shift10 = vec_splat_u32(10); - const vector int32_t dec128 = vec_splats(128 << 19); - const vector int32_t add18 = vec_splats(1 << 18); + vec_s16 vy, vu, vv, A = vec_splat_s16(0); + vec_s32 vy32_l, vy32_r, vu32_l, vu32_r, vv32_l, vv32_r, tmp32; + vec_s32 R_l, R_r, G_l, G_r, B_l, B_r, vud32_l, vud32_r, vvd32_l, vvd32_r; + vec_s32 tmp, tmp2, tmp3, tmp4, tmp5, tmp6; + vec_u16 rd16, gd16, bd16; + vec_u8 rd, bd, gd, ad, out0, out1, tmp8; + const vec_s16 vyalpha1 = vec_splats(yalpha1); + const vec_s16 vuvalpha1 = vec_splats(uvalpha1); + const vec_s16 vyalpha = vec_splats((int16_t) yalpha); + const vec_s16 vuvalpha = vec_splats((int16_t) uvalpha); + const vec_u16 zero16 = vec_splat_u16(0); + const vec_s32 y_offset = vec_splats(c->yuv2rgb_y_offset); + const vec_s32 y_coeff = vec_splats(c->yuv2rgb_y_coeff); + const vec_s32 y_add = vec_splats(1 << 21); + const vec_s32 v2r_coeff = vec_splats(c->yuv2rgb_v2r_coeff); + const vec_s32 v2g_coeff = vec_splats(c->yuv2rgb_v2g_coeff); + const vec_s32 u2g_coeff = vec_splats(c->yuv2rgb_u2g_coeff); + const vec_s32 u2b_coeff = vec_splats(c->yuv2rgb_u2b_coeff); + const vec_s32 rgbclip = vec_splats(1 << 30); + const vec_s32 zero32 = vec_splat_s32(0); + const vec_u32 shift19 = vec_splats(19U); + const vec_u32 shift22 = vec_splats(22U); + const vec_u32 shift10 = vec_splat_u32(10); + const vec_s32 dec128 = vec_splats(128 << 19); + const vec_s32 add18 = vec_splats(1 << 18); int i; // Various permutations - const vector uint8_t doubleleft = (vector uint8_t) {0, 1, 2, 3, - 0, 1, 2, 3, - 4, 5, 6, 7, - 4, 5, 6, 7 }; - const vector uint8_t doubleright = (vector uint8_t) {8, 9, 10, 11, - 8, 9, 10, 11, - 12, 13, 14, 15, - 12, 13, 14, 15 }; - const vector uint8_t perm3rg0 = (vector uint8_t) {0x0, 0x10, 0, - 0x1, 0x11, 0, - 0x2, 0x12, 0, - 0x3, 0x13, 0, - 0x4, 0x14, 0, - 0x5 }; - const vector uint8_t perm3rg1 = (vector uint8_t) { 0x15, 0, - 0x6, 0x16, 0, - 0x7, 0x17, 0 }; - const vector uint8_t perm3tb0 = (vector uint8_t) {0x0, 0x1, 0x10, - 0x3, 0x4, 0x11, - 0x6, 0x7, 0x12, - 0x9, 0xa, 0x13, - 0xc, 0xd, 0x14, - 0xf }; - const vector uint8_t perm3tb1 = (vector uint8_t) { 0x0, 0x15, - 0x2, 0x3, 0x16, - 0x5, 0x6, 0x17 }; + const vec_u8 doubleleft = (vec_u8) {0, 1, 2, 3, + 0, 1, 2, 3, + 4, 5, 6, 7, + 4, 5, 6, 7 }; + const vec_u8 doubleright = (vec_u8) {8, 9, 10, 11, + 8, 9, 10, 11, + 12, 13, 14, 15, + 12, 13, 14, 15 }; + const vec_u8 perm3rg0 = (vec_u8) {0x0, 0x10, 0, + 0x1, 0x11, 0, + 0x2, 0x12, 0, + 0x3, 0x13, 0, + 0x4, 0x14, 0, + 0x5 }; + const vec_u8 perm3rg1 = (vec_u8) { 0x15, 0, + 0x6, 0x16, 0, + 0x7, 0x17, 0 }; + const vec_u8 perm3tb0 = (vec_u8) {0x0, 0x1, 0x10, + 0x3, 0x4, 0x11, + 0x6, 0x7, 0x12, + 0x9, 0xa, 0x13, + 0xc, 0xd, 0x14, + 0xf }; + const vec_u8 perm3tb1 = (vec_u8) { 0x0, 0x15, + 0x2, 0x3, 0x16, + 0x5, 0x6, 0x17 }; av_assert2(yalpha <= 4096U); av_assert2(uvalpha <= 4096U); @@ -889,7 +894,7 @@ tmp3 = vec_sra(tmp3, shift19); tmp4 = vec_sra(tmp4, shift19); A = vec_packs(tmp3, tmp4); - ad = vec_packsu(A, (vector int16_t) zero16); + ad = vec_packsu(A, (vec_s16) zero16); } else { ad = vec_splats((uint8_t) 255); } @@ -978,51 +983,51 @@ { const int16_t *ubuf0 = ubuf[0], *vbuf0 = vbuf[0]; const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1]; - vector int16_t vy, vu, vv, A = vec_splat_s16(0), tmp16; - vector int32_t vy32_l, vy32_r, vu32_l, vu32_r, vv32_l, vv32_r, tmp32, tmp32_2; - vector int32_t R_l, R_r, G_l, G_r, B_l, B_r; - vector uint16_t rd16, gd16, bd16; - vector uint8_t rd, bd, gd, ad, out0, out1, tmp8; - const vector uint16_t zero16 = vec_splat_u16(0); - const vector int32_t y_offset = vec_splats(c->yuv2rgb_y_offset); - const vector int32_t y_coeff = vec_splats(c->yuv2rgb_y_coeff); - const vector int32_t y_add = vec_splats(1 << 21); - const vector int32_t v2r_coeff = vec_splats(c->yuv2rgb_v2r_coeff); - const vector int32_t v2g_coeff = vec_splats(c->yuv2rgb_v2g_coeff); - const vector int32_t u2g_coeff = vec_splats(c->yuv2rgb_u2g_coeff); - const vector int32_t u2b_coeff = vec_splats(c->yuv2rgb_u2b_coeff); - const vector int32_t rgbclip = vec_splats(1 << 30); - const vector int32_t zero32 = vec_splat_s32(0); - const vector uint32_t shift2 = vec_splat_u32(2); - const vector uint32_t shift22 = vec_splats(22U); - const vector uint16_t sub7 = vec_splats((uint16_t) (128 << 7)); - const vector uint16_t sub8 = vec_splats((uint16_t) (128 << 8)); - const vector int16_t mul4 = vec_splat_s16(4); - const vector int16_t mul8 = vec_splat_s16(8); - const vector int16_t add64 = vec_splat_s16(64); - const vector uint16_t shift7 = vec_splat_u16(7); - const vector int16_t max255 = vec_splat_s16(255); + vec_s16 vy, vu, vv, A = vec_splat_s16(0), tmp16; + vec_s32 vy32_l, vy32_r, vu32_l, vu32_r, vv32_l, vv32_r, tmp32, tmp32_2; + vec_s32 R_l, R_r, G_l, G_r, B_l, B_r; + vec_u16 rd16, gd16, bd16; + vec_u8 rd, bd, gd, ad, out0, out1, tmp8; + const vec_u16 zero16 = vec_splat_u16(0); + const vec_s32 y_offset = vec_splats(c->yuv2rgb_y_offset); + const vec_s32 y_coeff = vec_splats(c->yuv2rgb_y_coeff); + const vec_s32 y_add = vec_splats(1 << 21); + const vec_s32 v2r_coeff = vec_splats(c->yuv2rgb_v2r_coeff); + const vec_s32 v2g_coeff = vec_splats(c->yuv2rgb_v2g_coeff); + const vec_s32 u2g_coeff = vec_splats(c->yuv2rgb_u2g_coeff); + const vec_s32 u2b_coeff = vec_splats(c->yuv2rgb_u2b_coeff); + const vec_s32 rgbclip = vec_splats(1 << 30); + const vec_s32 zero32 = vec_splat_s32(0); + const vec_u32 shift2 = vec_splat_u32(2); + const vec_u32 shift22 = vec_splats(22U); + const vec_u16 sub7 = vec_splats((uint16_t) (128 << 7)); + const vec_u16 sub8 = vec_splats((uint16_t) (128 << 8)); + const vec_s16 mul4 = vec_splat_s16(4); + const vec_s16 mul8 = vec_splat_s16(8); + const vec_s16 add64 = vec_splat_s16(64); + const vec_u16 shift7 = vec_splat_u16(7); + const vec_s16 max255 = vec_splat_s16(255); int i; // Various permutations - const vector uint8_t perm3rg0 = (vector uint8_t) {0x0, 0x10, 0, - 0x1, 0x11, 0, - 0x2, 0x12, 0, - 0x3, 0x13, 0, - 0x4, 0x14, 0, - 0x5 }; - const vector uint8_t perm3rg1 = (vector uint8_t) { 0x15, 0, - 0x6, 0x16, 0, - 0x7, 0x17, 0 }; - const vector uint8_t perm3tb0 = (vector uint8_t) {0x0, 0x1, 0x10, - 0x3, 0x4, 0x11, - 0x6, 0x7, 0x12, - 0x9, 0xa, 0x13, - 0xc, 0xd, 0x14, - 0xf }; - const vector uint8_t perm3tb1 = (vector uint8_t) { 0x0, 0x15, - 0x2, 0x3, 0x16, - 0x5, 0x6, 0x17 }; + const vec_u8 perm3rg0 = (vec_u8) {0x0, 0x10, 0, + 0x1, 0x11, 0, + 0x2, 0x12, 0, + 0x3, 0x13, 0, + 0x4, 0x14, 0, + 0x5 }; + const vec_u8 perm3rg1 = (vec_u8) { 0x15, 0, + 0x6, 0x16, 0, + 0x7, 0x17, 0 }; + const vec_u8 perm3tb0 = (vec_u8) {0x0, 0x1, 0x10, + 0x3, 0x4, 0x11, + 0x6, 0x7, 0x12, + 0x9, 0xa, 0x13, + 0xc, 0xd, 0x14, + 0xf }; + const vec_u8 perm3tb1 = (vec_u8) { 0x0, 0x15, + 0x2, 0x3, 0x16, + 0x5, 0x6, 0x17 }; for (i = 0; i < dstW; i += 8) { // The x86 asm also overwrites padding bytes. vy = vec_ld(0, &buf0[i]); @@ -1034,8 +1039,8 @@ vu = vec_ld(0, &ubuf0[i]); vv = vec_ld(0, &vbuf0[i]); if (uvalpha < 2048) { - vu = (vector int16_t) vec_sub((vector uint16_t) vu, sub7); - vv = (vector int16_t) vec_sub((vector uint16_t) vv, sub7); + vu = (vec_s16) vec_sub((vec_u16) vu, sub7); + vv = (vec_s16) vec_sub((vec_u16) vv, sub7); tmp32 = vec_mule(vu, mul4); tmp32_2 = vec_mulo(vu, mul4); @@ -1048,10 +1053,10 @@ } else { tmp16 = vec_ld(0, &ubuf1[i]); vu = vec_add(vu, tmp16); - vu = (vector int16_t) vec_sub((vector uint16_t) vu, sub8); + vu = (vec_s16) vec_sub((vec_u16) vu, sub8); tmp16 = vec_ld(0, &vbuf1[i]); vv = vec_add(vv, tmp16); - vv = (vector int16_t) vec_sub((vector uint16_t) vv, sub8); + vv = (vec_s16) vec_sub((vec_u16) vv, sub8); vu32_l = vec_mule(vu, mul8); vu32_r = vec_mulo(vu, mul8); @@ -1064,7 +1069,7 @@ A = vec_add(A, add64); A = vec_sr(A, shift7); A = vec_max(A, max255); - ad = vec_packsu(A, (vector int16_t) zero16); + ad = vec_packsu(A, (vec_s16) zero16); } else { ad = vec_splats((uint8_t) 255); } @@ -1107,60 +1112,60 @@ { const int16_t *ubuf0 = ubuf[0], *vbuf0 = vbuf[0]; const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1]; - vector int16_t vy, vu, vv, A = vec_splat_s16(0), tmp16; - vector int32_t vy32_l, vy32_r, vu32_l, vu32_r, vv32_l, vv32_r, tmp32, tmp32_2; - vector int32_t vud32_l, vud32_r, vvd32_l, vvd32_r; - vector int32_t R_l, R_r, G_l, G_r, B_l, B_r; - vector uint16_t rd16, gd16, bd16; - vector uint8_t rd, bd, gd, ad, out0, out1, tmp8; - const vector uint16_t zero16 = vec_splat_u16(0); - const vector int32_t y_offset = vec_splats(c->yuv2rgb_y_offset); - const vector int32_t y_coeff = vec_splats(c->yuv2rgb_y_coeff); - const vector int32_t y_add = vec_splats(1 << 21); - const vector int32_t v2r_coeff = vec_splats(c->yuv2rgb_v2r_coeff); - const vector int32_t v2g_coeff = vec_splats(c->yuv2rgb_v2g_coeff); - const vector int32_t u2g_coeff = vec_splats(c->yuv2rgb_u2g_coeff); - const vector int32_t u2b_coeff = vec_splats(c->yuv2rgb_u2b_coeff); - const vector int32_t rgbclip = vec_splats(1 << 30); - const vector int32_t zero32 = vec_splat_s32(0); - const vector uint32_t shift2 = vec_splat_u32(2); - const vector uint32_t shift22 = vec_splats(22U); - const vector uint16_t sub7 = vec_splats((uint16_t) (128 << 7)); - const vector uint16_t sub8 = vec_splats((uint16_t) (128 << 8)); - const vector int16_t mul4 = vec_splat_s16(4); - const vector int16_t mul8 = vec_splat_s16(8); - const vector int16_t add64 = vec_splat_s16(64); - const vector uint16_t shift7 = vec_splat_u16(7); - const vector int16_t max255 = vec_splat_s16(255); + vec_s16 vy, vu, vv, A = vec_splat_s16(0), tmp16; + vec_s32 vy32_l, vy32_r, vu32_l, vu32_r, vv32_l, vv32_r, tmp32, tmp32_2; + vec_s32 vud32_l, vud32_r, vvd32_l, vvd32_r; + vec_s32 R_l, R_r, G_l, G_r, B_l, B_r; + vec_u16 rd16, gd16, bd16; + vec_u8 rd, bd, gd, ad, out0, out1, tmp8; + const vec_u16 zero16 = vec_splat_u16(0); + const vec_s32 y_offset = vec_splats(c->yuv2rgb_y_offset); + const vec_s32 y_coeff = vec_splats(c->yuv2rgb_y_coeff); + const vec_s32 y_add = vec_splats(1 << 21); + const vec_s32 v2r_coeff = vec_splats(c->yuv2rgb_v2r_coeff); + const vec_s32 v2g_coeff = vec_splats(c->yuv2rgb_v2g_coeff); + const vec_s32 u2g_coeff = vec_splats(c->yuv2rgb_u2g_coeff); + const vec_s32 u2b_coeff = vec_splats(c->yuv2rgb_u2b_coeff); + const vec_s32 rgbclip = vec_splats(1 << 30); + const vec_s32 zero32 = vec_splat_s32(0); + const vec_u32 shift2 = vec_splat_u32(2); + const vec_u32 shift22 = vec_splats(22U); + const vec_u16 sub7 = vec_splats((uint16_t) (128 << 7)); + const vec_u16 sub8 = vec_splats((uint16_t) (128 << 8)); + const vec_s16 mul4 = vec_splat_s16(4); + const vec_s16 mul8 = vec_splat_s16(8); + const vec_s16 add64 = vec_splat_s16(64); + const vec_u16 shift7 = vec_splat_u16(7); + const vec_s16 max255 = vec_splat_s16(255); int i; // Various permutations - const vector uint8_t doubleleft = (vector uint8_t) {0, 1, 2, 3, - 0, 1, 2, 3, - 4, 5, 6, 7, - 4, 5, 6, 7 }; - const vector uint8_t doubleright = (vector uint8_t) {8, 9, 10, 11, - 8, 9, 10, 11, - 12, 13, 14, 15, - 12, 13, 14, 15 }; - const vector uint8_t perm3rg0 = (vector uint8_t) {0x0, 0x10, 0, - 0x1, 0x11, 0, - 0x2, 0x12, 0, - 0x3, 0x13, 0, - 0x4, 0x14, 0, - 0x5 }; - const vector uint8_t perm3rg1 = (vector uint8_t) { 0x15, 0, - 0x6, 0x16, 0, - 0x7, 0x17, 0 }; - const vector uint8_t perm3tb0 = (vector uint8_t) {0x0, 0x1, 0x10, - 0x3, 0x4, 0x11, - 0x6, 0x7, 0x12, - 0x9, 0xa, 0x13, - 0xc, 0xd, 0x14, - 0xf }; - const vector uint8_t perm3tb1 = (vector uint8_t) { 0x0, 0x15, - 0x2, 0x3, 0x16, - 0x5, 0x6, 0x17 }; + const vec_u8 doubleleft = (vec_u8) {0, 1, 2, 3, + 0, 1, 2, 3, + 4, 5, 6, 7, + 4, 5, 6, 7 }; + const vec_u8 doubleright = (vec_u8) {8, 9, 10, 11, + 8, 9, 10, 11, + 12, 13, 14, 15, + 12, 13, 14, 15 }; + const vec_u8 perm3rg0 = (vec_u8) {0x0, 0x10, 0, + 0x1, 0x11, 0, + 0x2, 0x12, 0, + 0x3, 0x13, 0, + 0x4, 0x14, 0, + 0x5 }; + const vec_u8 perm3rg1 = (vec_u8) { 0x15, 0, + 0x6, 0x16, 0, + 0x7, 0x17, 0 }; + const vec_u8 perm3tb0 = (vec_u8) {0x0, 0x1, 0x10, + 0x3, 0x4, 0x11, + 0x6, 0x7, 0x12, + 0x9, 0xa, 0x13, + 0xc, 0xd, 0x14, + 0xf }; + const vec_u8 perm3tb1 = (vec_u8) { 0x0, 0x15, + 0x2, 0x3, 0x16, + 0x5, 0x6, 0x17 }; for (i = 0; i < (dstW + 1) >> 1; i += 8) { // The x86 asm also overwrites padding bytes. vy = vec_ld(0, &buf0[i * 2]); @@ -1172,8 +1177,8 @@ vu = vec_ld(0, &ubuf0[i]); vv = vec_ld(0, &vbuf0[i]); if (uvalpha < 2048) { - vu = (vector int16_t) vec_sub((vector uint16_t) vu, sub7); - vv = (vector int16_t) vec_sub((vector uint16_t) vv, sub7); + vu = (vec_s16) vec_sub((vec_u16) vu, sub7); + vv = (vec_s16) vec_sub((vec_u16) vv, sub7); tmp32 = vec_mule(vu, mul4); tmp32_2 = vec_mulo(vu, mul4); @@ -1186,10 +1191,10 @@ } else { tmp16 = vec_ld(0, &ubuf1[i]); vu = vec_add(vu, tmp16); - vu = (vector int16_t) vec_sub((vector uint16_t) vu, sub8); + vu = (vec_s16) vec_sub((vec_u16) vu, sub8); tmp16 = vec_ld(0, &vbuf1[i]); vv = vec_add(vv, tmp16); - vv = (vector int16_t) vec_sub((vector uint16_t) vv, sub8); + vv = (vec_s16) vec_sub((vec_u16) vv, sub8); vu32_l = vec_mule(vu, mul8); vu32_r = vec_mulo(vu, mul8); @@ -1202,7 +1207,7 @@ A = vec_add(A, add64); A = vec_sr(A, shift7); A = vec_max(A, max255); - ad = vec_packsu(A, (vector int16_t) zero16); + ad = vec_packsu(A, (vec_s16) zero16); } else { ad = vec_splats((uint8_t) 255); } @@ -1358,41 +1363,41 @@ YUV2RGBWRAPPERX(yuv2, rgb_full, bgr24_full, AV_PIX_FMT_BGR24, 0) static av_always_inline void -write422(const vector int16_t vy1, const vector int16_t vy2, - const vector int16_t vu, const vector int16_t vv, +write422(const vec_s16 vy1, const vec_s16 vy2, + const vec_s16 vu, const vec_s16 vv, uint8_t *dest, const enum AVPixelFormat target) { - vector uint8_t vd1, vd2, tmp; - const vector uint8_t yuyv1 = (vector uint8_t) { - 0x0, 0x10, 0x1, 0x18, - 0x2, 0x11, 0x3, 0x19, - 0x4, 0x12, 0x5, 0x1a, - 0x6, 0x13, 0x7, 0x1b }; - const vector uint8_t yuyv2 = (vector uint8_t) { - 0x8, 0x14, 0x9, 0x1c, - 0xa, 0x15, 0xb, 0x1d, - 0xc, 0x16, 0xd, 0x1e, - 0xe, 0x17, 0xf, 0x1f }; - const vector uint8_t yvyu1 = (vector uint8_t) { - 0x0, 0x18, 0x1, 0x10, - 0x2, 0x19, 0x3, 0x11, - 0x4, 0x1a, 0x5, 0x12, - 0x6, 0x1b, 0x7, 0x13 }; - const vector uint8_t yvyu2 = (vector uint8_t) { - 0x8, 0x1c, 0x9, 0x14, - 0xa, 0x1d, 0xb, 0x15, - 0xc, 0x1e, 0xd, 0x16, - 0xe, 0x1f, 0xf, 0x17 }; - const vector uint8_t uyvy1 = (vector uint8_t) { - 0x10, 0x0, 0x18, 0x1, - 0x11, 0x2, 0x19, 0x3, - 0x12, 0x4, 0x1a, 0x5, - 0x13, 0x6, 0x1b, 0x7 }; - const vector uint8_t uyvy2 = (vector uint8_t) { - 0x14, 0x8, 0x1c, 0x9, - 0x15, 0xa, 0x1d, 0xb, - 0x16, 0xc, 0x1e, 0xd, - 0x17, 0xe, 0x1f, 0xf }; + vec_u8 vd1, vd2, tmp; + const vec_u8 yuyv1 = (vec_u8) { + 0x0, 0x10, 0x1, 0x18, + 0x2, 0x11, 0x3, 0x19, + 0x4, 0x12, 0x5, 0x1a, + 0x6, 0x13, 0x7, 0x1b }; + const vec_u8 yuyv2 = (vec_u8) { + 0x8, 0x14, 0x9, 0x1c, + 0xa, 0x15, 0xb, 0x1d, + 0xc, 0x16, 0xd, 0x1e, + 0xe, 0x17, 0xf, 0x1f }; + const vec_u8 yvyu1 = (vec_u8) { + 0x0, 0x18, 0x1, 0x10, + 0x2, 0x19, 0x3, 0x11, + 0x4, 0x1a, 0x5, 0x12, + 0x6, 0x1b, 0x7, 0x13 }; + const vec_u8 yvyu2 = (vec_u8) { + 0x8, 0x1c, 0x9, 0x14, + 0xa, 0x1d, 0xb, 0x15, + 0xc, 0x1e, 0xd, 0x16, + 0xe, 0x1f, 0xf, 0x17 }; + const vec_u8 uyvy1 = (vec_u8) { + 0x10, 0x0, 0x18, 0x1, + 0x11, 0x2, 0x19, 0x3, + 0x12, 0x4, 0x1a, 0x5, + 0x13, 0x6, 0x1b, 0x7 }; + const vec_u8 uyvy2 = (vec_u8) { + 0x14, 0x8, 0x1c, 0x9, + 0x15, 0xa, 0x1d, 0xb, + 0x16, 0xc, 0x1e, 0xd, + 0x17, 0xe, 0x1f, 0xf }; vd1 = vec_packsu(vy1, vy2); vd2 = vec_packsu(vu, vv); @@ -1428,11 +1433,11 @@ int y, enum AVPixelFormat target) { int i, j; - vector int16_t vy1, vy2, vu, vv; - vector int32_t vy32[4], vu32[2], vv32[2], tmp, tmp2, tmp3, tmp4; - vector int16_t vlumFilter[MAX_FILTER_SIZE], vchrFilter[MAX_FILTER_SIZE]; - const vector int32_t start = vec_splats(1 << 18); - const vector uint32_t shift19 = vec_splats(19U); + vec_s16 vy1, vy2, vu, vv; + vec_s32 vy32[4], vu32[2], vv32[2], tmp, tmp2, tmp3, tmp4; + vec_s16 vlumFilter[MAX_FILTER_SIZE], vchrFilter[MAX_FILTER_SIZE]; + const vec_s32 start = vec_splats(1 << 18); + const vec_u32 shift19 = vec_splats(19U); for (i = 0; i < lumFilterSize; i++) vlumFilter[i] = vec_splats(lumFilter[i]); @@ -1539,11 +1544,11 @@ *vbuf0 = vbuf[0], *vbuf1 = vbuf[1]; const int16_t yalpha1 = 4096 - yalpha; const int16_t uvalpha1 = 4096 - uvalpha; - vector int16_t vy1, vy2, vu, vv; - vector int32_t tmp, tmp2, tmp3, tmp4, tmp5, tmp6; - const vector int16_t vyalpha1 = vec_splats(yalpha1); - const vector int16_t vuvalpha1 = vec_splats(uvalpha1); - const vector uint32_t shift19 = vec_splats(19U); + vec_s16 vy1, vy2, vu, vv; + vec_s32 tmp, tmp2, tmp3, tmp4, tmp5, tmp6; + const vec_s16 vyalpha1 = vec_splats(yalpha1); + const vec_s16 vuvalpha1 = vec_splats(uvalpha1); + const vec_u32 shift19 = vec_splats(19U); int i; av_assert2(yalpha <= 4096U); av_assert2(uvalpha <= 4096U); @@ -1568,11 +1573,11 @@ int uvalpha, int y, enum AVPixelFormat target) { const int16_t *ubuf0 = ubuf[0], *vbuf0 = vbuf[0]; - vector int16_t vy1, vy2, vu, vv, tmp; - const vector int16_t add64 = vec_splats((int16_t) 64); - const vector int16_t add128 = vec_splats((int16_t) 128); - const vector uint16_t shift7 = vec_splat_u16(7); - const vector uint16_t shift8 = vec_splat_u16(8); + vec_s16 vy1, vy2, vu, vv, tmp; + const vec_s16 add64 = vec_splats((int16_t) 64); + const vec_s16 add128 = vec_splats((int16_t) 128); + const vec_u16 shift7 = vec_splat_u16(7); + const vec_u16 shift8 = vec_splat_u16(8); int i; if (uvalpha < 2048) { @@ -1666,18 +1671,18 @@ { int i; unsigned int xpos = 0, xx; - vector uint8_t vin, vin2, vperm; - vector int8_t vmul, valpha; - vector int16_t vtmp, vtmp2, vtmp3, vtmp4; - vector uint16_t vd_l, vd_r, vcoord16[2]; - vector uint32_t vcoord[4]; - const vector uint32_t vadd = (vector uint32_t) { + vec_u8 vin, vin2, vperm; + vec_s8 vmul, valpha; + vec_s16 vtmp, vtmp2, vtmp3, vtmp4; + vec_u16 vd_l, vd_r, vcoord16[2]; + vec_u32 vcoord[4]; + const vec_u32 vadd = (vec_u32) { 0, xInc * 1, xInc * 2, xInc * 3, }; - const vector uint16_t vadd16 = (vector uint16_t) { // Modulo math + const vec_u16 vadd16 = (vec_u16) { // Modulo math 0, xInc * 1, xInc * 2, @@ -1687,10 +1692,10 @@ xInc * 6, xInc * 7, }; - const vector uint32_t vshift16 = vec_splats((uint32_t) 16); - const vector uint16_t vshift9 = vec_splat_u16(9); - const vector uint8_t vzero = vec_splat_u8(0); - const vector uint16_t vshift = vec_splat_u16(7); + const vec_u32 vshift16 = vec_splats((uint32_t) 16); + const vec_u16 vshift9 = vec_splat_u16(9); + const vec_u8 vzero = vec_splat_u8(0); + const vec_u16 vshift = vec_splat_u16(7); for (i = 0; i < dstWidth; i += 16) { vcoord16[0] = vec_splats((uint16_t) xpos); @@ -1701,7 +1706,7 @@ vcoord16[0] = vec_sr(vcoord16[0], vshift9); vcoord16[1] = vec_sr(vcoord16[1], vshift9); - valpha = (vector int8_t) vec_pack(vcoord16[0], vcoord16[1]); + valpha = (vec_s8) vec_pack(vcoord16[0], vcoord16[1]); xx = xpos >> 16; vin = vec_vsx_ld(0, &src[xx]); @@ -1730,22 +1735,22 @@ vin2 = vec_vsx_ld(1, &src[xx]); vin2 = vec_perm(vin2, vin2, vperm); - vmul = (vector int8_t) vec_sub(vin2, vin); + vmul = (vec_s8) vec_sub(vin2, vin); vtmp = vec_mule(vmul, valpha); vtmp2 = vec_mulo(vmul, valpha); vtmp3 = vec_mergeh(vtmp, vtmp2); vtmp4 = vec_mergel(vtmp, vtmp2); - vd_l = (vector uint16_t) vec_mergeh(vin, vzero); - vd_r = (vector uint16_t) vec_mergel(vin, vzero); + vd_l = (vec_u16) vec_mergeh(vin, vzero); + vd_r = (vec_u16) vec_mergel(vin, vzero); vd_l = vec_sl(vd_l, vshift); vd_r = vec_sl(vd_r, vshift); - vd_l = vec_add(vd_l, (vector uint16_t) vtmp3); - vd_r = vec_add(vd_r, (vector uint16_t) vtmp4); + vd_l = vec_add(vd_l, (vec_u16) vtmp3); + vd_r = vec_add(vd_r, (vec_u16) vtmp4); - vec_st((vector int16_t) vd_l, 0, &dst[i]); - vec_st((vector int16_t) vd_r, 0, &dst[i + 8]); + vec_st((vec_s16) vd_l, 0, &dst[i]); + vec_st((vec_s16) vd_r, 0, &dst[i + 8]); xpos += xInc * 16; } @@ -1773,8 +1778,8 @@ vd_l = vec_add(vd_l, vtmp3); \ vd_r = vec_add(vd_r, vtmp4); \ \ - vec_st((vector int16_t) vd_l, 0, &out[i]); \ - vec_st((vector int16_t) vd_r, 0, &out[i + 8]) + vec_st((vec_s16) vd_l, 0, &out[i]); \ + vec_st((vec_s16) vd_r, 0, &out[i + 8]) static void hcscale_fast_vsx(SwsContext *c, int16_t *dst1, int16_t *dst2, int dstWidth, const uint8_t *src1, @@ -1782,19 +1787,19 @@ { int i; unsigned int xpos = 0, xx; - vector uint8_t vin, vin2, vperm; - vector uint8_t valpha, valphaxor; - vector uint16_t vtmp, vtmp2, vtmp3, vtmp4; - vector uint16_t vd_l, vd_r, vcoord16[2]; - vector uint32_t vcoord[4]; - const vector uint8_t vxor = vec_splats((uint8_t) 127); - const vector uint32_t vadd = (vector uint32_t) { + vec_u8 vin, vin2, vperm; + vec_u8 valpha, valphaxor; + vec_u16 vtmp, vtmp2, vtmp3, vtmp4; + vec_u16 vd_l, vd_r, vcoord16[2]; + vec_u32 vcoord[4]; + const vec_u8 vxor = vec_splats((uint8_t) 127); + const vec_u32 vadd = (vec_u32) { 0, xInc * 1, xInc * 2, xInc * 3, }; - const vector uint16_t vadd16 = (vector uint16_t) { // Modulo math + const vec_u16 vadd16 = (vec_u16) { // Modulo math 0, xInc * 1, xInc * 2, @@ -1804,8 +1809,8 @@ xInc * 6, xInc * 7, }; - const vector uint32_t vshift16 = vec_splats((uint32_t) 16); - const vector uint16_t vshift9 = vec_splat_u16(9); + const vec_u32 vshift16 = vec_splats((uint32_t) 16); + const vec_u16 vshift9 = vec_splat_u16(9); for (i = 0; i < dstWidth; i += 16) { vcoord16[0] = vec_splats((uint16_t) xpos); @@ -1859,29 +1864,29 @@ { int i, j; int32_t *dst = (int32_t *) _dst; - vector int16_t vfilter, vin; - vector uint8_t vin8; - vector int32_t vout; - const vector uint8_t vzero = vec_splat_u8(0); - const vector uint8_t vunusedtab[8] = { - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}, - (vector uint8_t) {0x0, 0x1, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0x10, 0x10}, + vec_s16 vfilter, vin; + vec_u8 vin8; + vec_s32 vout; + const vec_u8 vzero = vec_splat_u8(0); + const vec_u8 vunusedtab[8] = { + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}, + (vec_u8) {0x0, 0x1, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0x10, 0x10}, }; - const vector uint8_t vunused = vunusedtab[filterSize % 8]; + const vec_u8 vunused = vunusedtab[filterSize % 8]; if (filterSize == 1) { for (i = 0; i < dstW; i++) { @@ -1898,14 +1903,14 @@ vout = vec_splat_s32(0); for (j = 0; j < filterSize; j += 8) { vin8 = vec_vsx_ld(0, &src[srcPos + j]); - vin = (vector int16_t) vec_mergeh(vin8, vzero); + vin = (vec_s16) vec_mergeh(vin8, vzero); if (j + 8 > filterSize) // Remove the unused elements on the last round - vin = vec_perm(vin, (vector int16_t) vzero, vunused); + vin = vec_perm(vin, (vec_s16) vzero, vunused); vfilter = vec_vsx_ld(0, &filter[filterSize * i + j]); vout = vec_msums(vin, vfilter, vout); } - vout = vec_sums(vout, (vector int32_t) vzero); + vout = vec_sums(vout, (vec_s32) vzero); dst[i] = FFMIN(vout[3] >> 3, (1 << 19) - 1); } } @@ -1921,28 +1926,28 @@ const uint16_t *src = (const uint16_t *) _src; int bits = desc->comp[0].depth - 1; int sh = bits - 4; - vector int16_t vfilter, vin; - vector int32_t vout, vtmp, vtmp2, vfilter32_l, vfilter32_r; - const vector uint8_t vzero = vec_splat_u8(0); - const vector uint8_t vunusedtab[8] = { - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}, - (vector uint8_t) {0x0, 0x1, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0x10, 0x10}, + vec_s16 vfilter, vin; + vec_s32 vout, vtmp, vtmp2, vfilter32_l, vfilter32_r; + const vec_u8 vzero = vec_splat_u8(0); + const vec_u8 vunusedtab[8] = { + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}, + (vec_u8) {0x0, 0x1, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0x10, 0x10}, }; - const vector uint8_t vunused = vunusedtab[filterSize % 8]; + const vec_u8 vunused = vunusedtab[filterSize % 8]; if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { sh = 9; @@ -1966,16 +1971,16 @@ const int srcPos = filterPos[i]; vout = vec_splat_s32(0); for (j = 0; j < filterSize; j += 8) { - vin = (vector int16_t) vec_vsx_ld(0, &src[srcPos + j]); + vin = (vec_s16) vec_vsx_ld(0, &src[srcPos + j]); if (j + 8 > filterSize) // Remove the unused elements on the last round - vin = vec_perm(vin, (vector int16_t) vzero, vunused); + vin = vec_perm(vin, (vec_s16) vzero, vunused); vfilter = vec_vsx_ld(0, &filter[filterSize * i + j]); vfilter32_l = vec_unpackh(vfilter); vfilter32_r = vec_unpackl(vfilter); - vtmp = (vector int32_t) vec_mergeh(vin, (vector int16_t) vzero); - vtmp2 = (vector int32_t) vec_mergel(vin, (vector int16_t) vzero); + vtmp = (vec_s32) vec_mergeh(vin, (vec_s16) vzero); + vtmp2 = (vec_s32) vec_mergel(vin, (vec_s16) vzero); vtmp = vec_mul(vtmp, vfilter32_l); vtmp2 = vec_mul(vtmp2, vfilter32_r); @@ -1983,7 +1988,7 @@ vout = vec_adds(vout, vtmp); vout = vec_adds(vout, vtmp2); } - vout = vec_sums(vout, (vector int32_t) vzero); + vout = vec_sums(vout, (vec_s32) vzero); dst[i] = FFMIN(vout[3] >> sh, (1 << 19) - 1); } } @@ -1997,28 +2002,28 @@ int i, j; const uint16_t *src = (const uint16_t *) _src; int sh = desc->comp[0].depth - 1; - vector int16_t vfilter, vin; - vector int32_t vout, vtmp, vtmp2, vfilter32_l, vfilter32_r; - const vector uint8_t vzero = vec_splat_u8(0); - const vector uint8_t vunusedtab[8] = { - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}, - (vector uint8_t) {0x0, 0x1, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0x10, 0x10, 0x10, 0x10}, - (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0x10, 0x10}, + vec_s16 vfilter, vin; + vec_s32 vout, vtmp, vtmp2, vfilter32_l, vfilter32_r; + const vec_u8 vzero = vec_splat_u8(0); + const vec_u8 vunusedtab[8] = { + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}, + (vec_u8) {0x0, 0x1, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0x10, 0x10, 0x10, 0x10}, + (vec_u8) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0x10, 0x10}, }; - const vector uint8_t vunused = vunusedtab[filterSize % 8]; + const vec_u8 vunused = vunusedtab[filterSize % 8]; if (sh<15) { sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); @@ -2042,16 +2047,16 @@ const int srcPos = filterPos[i]; vout = vec_splat_s32(0); for (j = 0; j < filterSize; j += 8) { - vin = (vector int16_t) vec_vsx_ld(0, &src[srcPos + j]); + vin = (vec_s16) vec_vsx_ld(0, &src[srcPos + j]); if (j + 8 > filterSize) // Remove the unused elements on the last round - vin = vec_perm(vin, (vector int16_t) vzero, vunused); + vin = vec_perm(vin, (vec_s16) vzero, vunused); vfilter = vec_vsx_ld(0, &filter[filterSize * i + j]); vfilter32_l = vec_unpackh(vfilter); vfilter32_r = vec_unpackl(vfilter); - vtmp = (vector int32_t) vec_mergeh(vin, (vector int16_t) vzero); - vtmp2 = (vector int32_t) vec_mergel(vin, (vector int16_t) vzero); + vtmp = (vec_s32) vec_mergeh(vin, (vec_s16) vzero); + vtmp2 = (vec_s32) vec_mergel(vin, (vec_s16) vzero); vtmp = vec_mul(vtmp, vfilter32_l); vtmp2 = vec_mul(vtmp2, vfilter32_r); @@ -2059,7 +2064,7 @@ vout = vec_adds(vout, vtmp); vout = vec_adds(vout, vtmp2); } - vout = vec_sums(vout, (vector int32_t) vzero); + vout = vec_sums(vout, (vec_s32) vzero); dst[i] = FFMIN(vout[3] >> sh, (1 << 15) - 1); } } diff -Nru ffmpeg-4.2.2/libswscale/ppc/yuv2rgb_altivec.c ffmpeg-4.4/libswscale/ppc/yuv2rgb_altivec.c --- ffmpeg-4.2.2/libswscale/ppc/yuv2rgb_altivec.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libswscale/ppc/yuv2rgb_altivec.c 2021-04-08 21:28:40.000000000 +0000 @@ -96,6 +96,7 @@ #include "libswscale/swscale_internal.h" #include "libavutil/attributes.h" #include "libavutil/cpu.h" +#include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" #include "yuv2rgb_altivec.h" @@ -283,6 +284,16 @@ * ------------------------------------------------------------------------------ */ +#if !HAVE_VSX +static inline vector unsigned char vec_xl(signed long long offset, const ubyte *addr) +{ + const vector unsigned char *v_addr = (const vector unsigned char *) (addr + offset); + vector unsigned char align_perm = vec_lvsl(offset, addr); + + return (vector unsigned char) vec_perm(v_addr[0], v_addr[1], align_perm); +} +#endif /* !HAVE_VSX */ + #define DEFCSP420_CVT(name, out_pixels) \ static int altivec_ ## name(SwsContext *c, const unsigned char **in, \ int *instrides, int srcSliceY, int srcSliceH, \ @@ -305,9 +316,6 @@ vector signed short R1, G1, B1; \ vector unsigned char R, G, B; \ \ - const vector unsigned char *y1ivP, *y2ivP, *uivP, *vivP; \ - vector unsigned char align_perm; \ - \ vector signed short lCY = c->CY; \ vector signed short lOY = c->OY; \ vector signed short lCRV = c->CRV; \ @@ -338,26 +346,13 @@ vec_dstst(oute, (0x02000002 | (((w * 3 + 32) / 32) << 16)), 1); \ \ for (j = 0; j < w / 16; j++) { \ - y1ivP = (const vector unsigned char *) y1i; \ - y2ivP = (const vector unsigned char *) y2i; \ - uivP = (const vector unsigned char *) ui; \ - vivP = (const vector unsigned char *) vi; \ - \ - align_perm = vec_lvsl(0, y1i); \ - y0 = (vector unsigned char) \ - vec_perm(y1ivP[0], y1ivP[1], align_perm); \ - \ - align_perm = vec_lvsl(0, y2i); \ - y1 = (vector unsigned char) \ - vec_perm(y2ivP[0], y2ivP[1], align_perm); \ + y0 = vec_xl(0, y1i); \ \ - align_perm = vec_lvsl(0, ui); \ - u = (vector signed char) \ - vec_perm(uivP[0], uivP[1], align_perm); \ + y1 = vec_xl(0, y2i); \ \ - align_perm = vec_lvsl(0, vi); \ - v = (vector signed char) \ - vec_perm(vivP[0], vivP[1], align_perm); \ + u = (vector signed char) vec_xl(0, ui); \ + \ + v = (vector signed char) vec_xl(0, vi); \ \ u = (vector signed char) \ vec_sub(u, \ @@ -440,13 +435,13 @@ } #define out_abgr(a, b, c, ptr) \ - vec_mstrgb32(__typeof__(a), ((__typeof__(a)) { 255 }), c, b, a, ptr) + vec_mstrgb32(__typeof__(a), ((__typeof__(a)) vec_splat((__typeof__(a)){ 255 }, 0)), c, b, a, ptr) #define out_bgra(a, b, c, ptr) \ - vec_mstrgb32(__typeof__(a), c, b, a, ((__typeof__(a)) { 255 }), ptr) + vec_mstrgb32(__typeof__(a), c, b, a, ((__typeof__(a)) vec_splat((__typeof__(a)){ 255 }, 0)), ptr) #define out_rgba(a, b, c, ptr) \ - vec_mstrgb32(__typeof__(a), a, b, c, ((__typeof__(a)) { 255 }), ptr) + vec_mstrgb32(__typeof__(a), a, b, c, ((__typeof__(a)) vec_splat((__typeof__(a)){ 255 }, 0)), ptr) #define out_argb(a, b, c, ptr) \ - vec_mstrgb32(__typeof__(a), ((__typeof__(a)) { 255 }), a, b, c, ptr) + vec_mstrgb32(__typeof__(a), ((__typeof__(a)) vec_splat((__typeof__(a)){ 255 }, 0)), a, b, c, ptr) #define out_rgb24(a, b, c, ptr) vec_mstrgb24(a, b, c, ptr) #define out_bgr24(a, b, c, ptr) vec_mstbgr24(a, b, c, ptr) diff -Nru ffmpeg-4.2.2/libswscale/rgb2rgb.c ffmpeg-4.4/libswscale/rgb2rgb.c --- ffmpeg-4.2.2/libswscale/rgb2rgb.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/rgb2rgb.c 2020-07-11 10:39:30.000000000 +0000 @@ -137,6 +137,8 @@ av_cold void ff_sws_rgb2rgb_init(void) { rgb2rgb_init_c(); + if (ARCH_AARCH64) + rgb2rgb_init_aarch64(); if (ARCH_X86) rgb2rgb_init_x86(); } diff -Nru ffmpeg-4.2.2/libswscale/rgb2rgb.h ffmpeg-4.4/libswscale/rgb2rgb.h --- ffmpeg-4.2.2/libswscale/rgb2rgb.h 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/rgb2rgb.h 2020-07-11 10:39:30.000000000 +0000 @@ -169,6 +169,7 @@ void ff_sws_rgb2rgb_init(void); +void rgb2rgb_init_aarch64(void); void rgb2rgb_init_x86(void); #endif /* SWSCALE_RGB2RGB_H */ diff -Nru ffmpeg-4.2.2/libswscale/rgb2rgb_template.c ffmpeg-4.4/libswscale/rgb2rgb_template.c --- ffmpeg-4.2.2/libswscale/rgb2rgb_template.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/rgb2rgb_template.c 2021-04-08 21:28:40.000000000 +0000 @@ -342,7 +342,6 @@ } } -#if !HAVE_BIGENDIAN #define DEFINE_SHUFFLE_BYTES(name, a, b, c, d) \ static void shuffle_bytes_##name (const uint8_t *src, \ uint8_t *dst, int src_size) \ @@ -360,7 +359,6 @@ DEFINE_SHUFFLE_BYTES(1230_c, 1, 2, 3, 0) DEFINE_SHUFFLE_BYTES(3012_c, 3, 0, 1, 2) DEFINE_SHUFFLE_BYTES(3210_c, 3, 2, 1, 0) -#endif static inline void rgb24tobgr24_c(const uint8_t *src, uint8_t *dst, int src_size) { @@ -969,10 +967,10 @@ #else shuffle_bytes_0321 = shuffle_bytes_0321_c; shuffle_bytes_2103 = shuffle_bytes_2103_c; +#endif shuffle_bytes_1230 = shuffle_bytes_1230_c; shuffle_bytes_3012 = shuffle_bytes_3012_c; shuffle_bytes_3210 = shuffle_bytes_3210_c; -#endif rgb32tobgr16 = rgb32tobgr16_c; rgb32tobgr15 = rgb32tobgr15_c; yv12toyuy2 = yv12toyuy2_c; diff -Nru ffmpeg-4.2.2/libswscale/slice.c ffmpeg-4.4/libswscale/slice.c --- ffmpeg-4.2.2/libswscale/slice.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/libswscale/slice.c 2021-04-08 21:28:40.000000000 +0000 @@ -158,14 +158,10 @@ chrY + chrH, lumY + lumH}; - uint8_t *const src_[4] = {src[0] + (relative ? 0 : start[0]) * stride[0], - src[1] + (relative ? 0 : start[1]) * stride[1], - src[2] + (relative ? 0 : start[2]) * stride[2], - src[3] + (relative ? 0 : start[3]) * stride[3]}; - s->width = srcW; - for (i = 0; i < 4; ++i) { + for (i = 0; i < 4 && src[i] != NULL; ++i) { + uint8_t *const src_i = src[i] + (relative ? 0 : start[i]) * stride[i]; int j; int first = s->plane[i].sliceY; int n = s->plane[i].available_lines; @@ -175,13 +171,13 @@ if (start[i] >= first && n >= tot_lines) { s->plane[i].sliceH = FFMAX(tot_lines, s->plane[i].sliceH); for (j = 0; j < lines; j+= 1) - s->plane[i].line[start[i] - first + j] = src_[i] + j * stride[i]; + s->plane[i].line[start[i] - first + j] = src_i + j * stride[i]; } else { s->plane[i].sliceY = start[i]; lines = lines > n ? n : lines; s->plane[i].sliceH = lines; for (j = 0; j < lines; j+= 1) - s->plane[i].line[j] = src_[i] + j * stride[i]; + s->plane[i].line[j] = src_i + j * stride[i]; } } @@ -189,23 +185,26 @@ return 0; } -static void fill_ones(SwsSlice *s, int n, int is16bit) +static void fill_ones(SwsSlice *s, int n, int bpc) { - int i; + int i, j, k, size, end; + for (i = 0; i < 4; ++i) { - int j; - int size = s->plane[i].available_lines; + size = s->plane[i].available_lines; for (j = 0; j < size; ++j) { - int k; - int end = is16bit ? n>>1: n; - // fill also one extra element - end += 1; - if (is16bit) + if (bpc == 16) { + end = (n>>1) + 1; for (k = 0; k < end; ++k) ((int32_t*)(s->plane[i].line[j]))[k] = 1<<18; - else + } else if (bpc == 32) { + end = (n>>2) + 1; + for (k = 0; k < end; ++k) + ((int64_t*)(s->plane[i].line[j]))[k] = 1LL<<34; + } else { + end = n + 1; for (k = 0; k < end; ++k) ((int16_t*)(s->plane[i].line[j]))[k] = 1<<14; + } } } } @@ -272,6 +271,9 @@ if (c->dstBpc == 16) dst_stride <<= 1; + if (c->dstBpc == 32) + dst_stride <<= 2; + num_ydesc = need_lum_conv ? 2 : 1; num_cdesc = need_chr_conv ? 2 : 1; @@ -302,7 +304,7 @@ res = alloc_lines(&c->slice[i], dst_stride, c->dstW); if (res < 0) goto cleanup; - fill_ones(&c->slice[i], dst_stride>>1, c->dstBpc == 16); + fill_ones(&c->slice[i], dst_stride>>1, c->dstBpc); // vertical scaler output ++i; diff -Nru ffmpeg-4.2.2/libswscale/swscale.c ffmpeg-4.4/libswscale/swscale.c --- ffmpeg-4.2.2/libswscale/swscale.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/swscale.c 2021-04-08 21:28:40.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" +#include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" #include "config.h" #include "rgb2rgb.h" @@ -266,12 +267,9 @@ /* vars which will change and which we need to store back in the context */ int dstY = c->dstY; - int lumBufIndex = c->lumBufIndex; - int chrBufIndex = c->chrBufIndex; int lastInLumBuf = c->lastInLumBuf; int lastInChrBuf = c->lastInChrBuf; - int lumStart = 0; int lumEnd = c->descIndex[0]; int chrStart = lumEnd; @@ -283,25 +281,21 @@ SwsSlice *vout_slice = &c->slice[c->numSlice-1]; SwsFilterDescriptor *desc = c->desc; - int needAlpha = c->needAlpha; int hasLumHoles = 1; int hasChrHoles = 1; - if (isPacked(c->srcFormat)) { - src[0] = src[1] = src[2] = src[3] = src[0]; - srcStride[0] = srcStride[1] = srcStride[2] = srcStride[3] = srcStride[0]; } - srcStride[1] <<= c->vChrDrop; - srcStride[2] <<= c->vChrDrop; + srcStride[1] *= 1 << c->vChrDrop; + srcStride[2] *= 1 << c->vChrDrop; DEBUG_BUFFERS("swscale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n", src[0], srcStride[0], src[1], srcStride[1], @@ -341,8 +335,6 @@ * will not get executed. This is not really intended but works * currently, so people might do it. */ if (srcSliceY == 0) { - lumBufIndex = -1; - chrBufIndex = -1; dstY = 0; lastInLumBuf = -1; lastInChrBuf = -1; @@ -466,7 +458,6 @@ desc[i].process(c, &desc[i], firstPosY, lastPosY - firstPosY + 1); } - lumBufIndex += lastLumSrcY - lastInLumBuf; lastInLumBuf = lastLumSrcY; if (cPosY < lastChrSrcY + 1) { @@ -474,20 +465,13 @@ desc[i].process(c, &desc[i], firstCPosY, lastCPosY - firstCPosY + 1); } - chrBufIndex += lastChrSrcY - lastInChrBuf; lastInChrBuf = lastChrSrcY; - // wrap buf index around to stay inside the ring buffer - if (lumBufIndex >= vLumFilterSize) - lumBufIndex -= vLumFilterSize; - if (chrBufIndex >= vChrFilterSize) - chrBufIndex -= vChrFilterSize; if (!enough_lines) break; // we can't output a dstY line so let's try with the next slice #if HAVE_MMX_INLINE - ff_updateMMXDitherTables(c, dstY, lumBufIndex, chrBufIndex, - lastInLumBuf, lastInChrBuf); + ff_updateMMXDitherTables(c, dstY); #endif if (should_dither) { c->chrDither8 = ff_dither_8x8_128[chrDstY & 7]; @@ -517,6 +501,11 @@ fillPlane16(dst[3], dstStride[3], length, height, lastDstY, 1, desc->comp[3].depth, isBE(dstFormat)); + } else if (is32BPS(dstFormat)) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat); + fillPlane32(dst[3], dstStride[3], length, height, lastDstY, + 1, desc->comp[3].depth, + isBE(dstFormat), desc->flags & AV_PIX_FMT_FLAG_FLOAT); } else fillPlane(dst[3], dstStride[3], length, height, lastDstY, 255); } @@ -529,8 +518,6 @@ /* store changed local vars back in the context */ c->dstY = dstY; - c->lumBufIndex = lumBufIndex; - c->chrBufIndex = chrBufIndex; c->lastInLumBuf = lastInLumBuf; c->lastInChrBuf = lastInChrBuf; @@ -572,7 +559,6 @@ ff_sws_init_input_funcs(c); - if (c->srcBpc == 8) { if (c->dstBpc <= 14) { c->hyScale = c->hcScale = hScale8To15_c; @@ -790,8 +776,6 @@ } if (c->gamma_flag && c->cascaded_context[0]) { - - ret = sws_scale(c->cascaded_context[0], srcSlice, srcStride, srcSliceY, srcSliceH, c->cascaded_tmp, c->cascaded_tmpStride); @@ -985,7 +969,6 @@ c->sliceDir = 0; ret = c->swscale(c, src2, srcStride2, srcSliceY_internal, srcSliceH, dst2, dstStride2); - if (c->dstXYZ && !(c->srcXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) { int dstY = c->dstY ? c->dstY : srcSliceY + srcSliceH; uint16_t *dst16 = (uint16_t*)(dst2[0] + (dstY - ret) * dstStride2[0]); diff -Nru ffmpeg-4.2.2/libswscale/swscale_internal.h ffmpeg-4.4/libswscale/swscale_internal.h --- ffmpeg-4.2.2/libswscale/swscale_internal.h 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/swscale_internal.h 2021-04-08 21:28:40.000000000 +0000 @@ -29,6 +29,7 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "libavutil/log.h" +#include "libavutil/mem_internal.h" #include "libavutil/pixfmt.h" #include "libavutil/pixdesc.h" #include "libavutil/ppc/util_altivec.h" @@ -119,7 +120,8 @@ * Write one line of horizontally scaled chroma to interleaved output * with multi-point vertical scaling between input pixels. * - * @param c SWS scaling context + * @param dstFormat destination pixel format + * @param chrDither ordered dither array of type uint8_t and size 8 * @param chrFilter vertical chroma scaling coefficients, 12 bits [0,4096] * @param chrUSrc scaled chroma (U) source data, 15 bits for 8-10-bit * output, 19 bits for 16-bit output (in int32_t) @@ -130,7 +132,8 @@ * output, this is in uint16_t * @param dstW width of chroma planes */ -typedef void (*yuv2interleavedX_fn)(struct SwsContext *c, +typedef void (*yuv2interleavedX_fn)(enum AVPixelFormat dstFormat, + const uint8_t *chrDither, const int16_t *chrFilter, int chrFilterSize, const int16_t **chrUSrc, @@ -350,8 +353,6 @@ //@{ int lastInLumBuf; ///< Last scaled horizontal luma/alpha line from source in the ring buffer. int lastInChrBuf; ///< Last scaled horizontal chroma line from source in the ring buffer. - int lumBufIndex; ///< Index in ring buffer of the last scaled horizontal luma/alpha line from source. - int chrBufIndex; ///< Index in ring buffer of the last scaled horizontal chroma line from source. //@} uint8_t *formatConvBuffer; @@ -635,8 +636,7 @@ void ff_yuv2rgb_init_tables_ppc(SwsContext *c, const int inv_table[4], int brightness, int contrast, int saturation); -void ff_updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrBufIndex, - int lastInLumBuf, int lastInChrBuf); +void ff_updateMMXDitherTables(SwsContext *c, int dstY); av_cold void ff_sws_init_range_convert(SwsContext *c); @@ -650,6 +650,13 @@ return desc->comp[0].depth == 16; } +static av_always_inline int is32BPS(enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + av_assert0(desc); + return desc->comp[0].depth == 32; +} + static av_always_inline int isNBPS(enum AVPixelFormat pix_fmt) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); @@ -758,6 +765,13 @@ return !!(desc->flags & AV_PIX_FMT_FLAG_BAYER); } +static av_always_inline int isBayer16BPS(enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + av_assert0(desc); + return desc->comp[1].depth == 8; +} + static av_always_inline int isAnyRGB(enum AVPixelFormat pix_fmt) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); @@ -921,8 +935,37 @@ } ptr += stride; } +#undef FILL } +static inline void fillPlane32(uint8_t *plane, int stride, int width, int height, int y, + int alpha, int bits, const int big_endian, int is_float) +{ + int i, j; + uint8_t *ptr = plane + stride * y; + uint32_t v; + uint32_t onef32 = 0x3f800000; + if (is_float) + v = alpha ? onef32 : 0; + else + v = alpha ? 0xFFFFFFFF>>(32-bits) : (1<<(bits-1)); + + for (i = 0; i < height; i++) { +#define FILL(wfunc) \ + for (j = 0; j < width; j++) {\ + wfunc(ptr+4*j, v);\ + } + if (big_endian) { + FILL(AV_WB32); + } else { + FILL(AV_WL32); + } + ptr += stride; + } +#undef FILL +} + + #define MAX_SLICE_PLANES 4 /// Slice plane diff -Nru ffmpeg-4.2.2/libswscale/swscale_unscaled.c ffmpeg-4.4/libswscale/swscale_unscaled.c --- ffmpeg-4.2.2/libswscale/swscale_unscaled.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/swscale_unscaled.c 2021-04-08 21:28:40.000000000 +0000 @@ -30,6 +30,7 @@ #include "libavutil/cpu.h" #include "libavutil/avutil.h" #include "libavutil/mathematics.h" +#include "libavutil/mem_internal.h" #include "libavutil/bswap.h" #include "libavutil/pixdesc.h" #include "libavutil/avassert.h" @@ -491,6 +492,34 @@ return srcSliceH; } +static int bswap_32bpc(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *dst[], int dstStride[]) +{ + int i, j, p; + + for (p = 0; p < 4; p++) { + int srcstr = srcStride[p] / 4; + int dststr = dstStride[p] / 4; + uint32_t *dstPtr = (uint32_t *) dst[p]; + const uint32_t *srcPtr = (const uint32_t *) src[p]; + int min_stride = FFMIN(FFABS(srcstr), FFABS(dststr)); + if(!dstPtr || !srcPtr) + continue; + dstPtr += (srcSliceY >> c->chrDstVSubSample) * dststr; + for (i = 0; i < (srcSliceH >> c->chrDstVSubSample); i++) { + for (j = 0; j < min_stride; j++) { + dstPtr[j] = av_bswap32(srcPtr[j]); + } + srcPtr += srcstr; + dstPtr += dststr; + } + } + + return srcSliceH; +} + + static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]) @@ -1298,6 +1327,55 @@ return srcSliceH; } +static int bayer_to_rgb48_wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, + int srcSliceH, uint8_t* dst[], int dstStride[]) +{ + uint8_t *dstPtr= dst[0] + srcSliceY * dstStride[0]; + const uint8_t *srcPtr= src[0]; + int i; + void (*copy) (const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width); + void (*interpolate)(const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width); + + switch(c->srcFormat) { +#define CASE(pixfmt, prefix) \ + case pixfmt: copy = bayer_##prefix##_to_rgb48_copy; \ + interpolate = bayer_##prefix##_to_rgb48_interpolate; \ + break; + CASE(AV_PIX_FMT_BAYER_BGGR8, bggr8) + CASE(AV_PIX_FMT_BAYER_BGGR16LE, bggr16le) + CASE(AV_PIX_FMT_BAYER_BGGR16BE, bggr16be) + CASE(AV_PIX_FMT_BAYER_RGGB8, rggb8) + CASE(AV_PIX_FMT_BAYER_RGGB16LE, rggb16le) + CASE(AV_PIX_FMT_BAYER_RGGB16BE, rggb16be) + CASE(AV_PIX_FMT_BAYER_GBRG8, gbrg8) + CASE(AV_PIX_FMT_BAYER_GBRG16LE, gbrg16le) + CASE(AV_PIX_FMT_BAYER_GBRG16BE, gbrg16be) + CASE(AV_PIX_FMT_BAYER_GRBG8, grbg8) + CASE(AV_PIX_FMT_BAYER_GRBG16LE, grbg16le) + CASE(AV_PIX_FMT_BAYER_GRBG16BE, grbg16be) +#undef CASE + default: return 0; + } + + av_assert0(srcSliceH > 1); + + copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW); + srcPtr += 2 * srcStride[0]; + dstPtr += 2 * dstStride[0]; + + for (i = 2; i < srcSliceH - 2; i += 2) { + interpolate(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW); + srcPtr += 2 * srcStride[0]; + dstPtr += 2 * dstStride[0]; + } + + if (i + 1 == srcSliceH) { + copy(srcPtr, -srcStride[0], dstPtr, -dstStride[0], c->srcW); + } else if (i < srcSliceH) + copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW); + return srcSliceH; +} + static int bayer_to_yv12_wrapper(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[]) { @@ -1728,7 +1806,7 @@ const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat); const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat); int plane, i, j; - for (plane = 0; plane < 4; plane++) { + for (plane = 0; plane < 4 && dst[plane] != NULL; plane++) { int length = (plane == 0 || plane == 3) ? c->srcW : AV_CEIL_RSHIFT(c->srcW, c->chrDstHSubSample); int y = (plane == 0 || plane == 3) ? srcSliceY: AV_CEIL_RSHIFT(srcSliceY, c->chrDstVSubSample); int height = (plane == 0 || plane == 3) ? srcSliceH: AV_CEIL_RSHIFT(srcSliceH, c->chrDstVSubSample); @@ -1736,8 +1814,6 @@ uint8_t *dstPtr = dst[plane] + dstStride[plane] * y; int shiftonly = plane == 1 || plane == 2 || (!c->srcRange && plane == 0); - if (!dst[plane]) - continue; // ignore palette for GRAY8 if (plane == 1 && !dst[2]) continue; if (!src[plane] || (plane == 1 && !src[2])) { @@ -1993,6 +2069,7 @@ dstFormat == AV_PIX_FMT_GBRP12LE || dstFormat == AV_PIX_FMT_GBRP12BE || dstFormat == AV_PIX_FMT_GBRP14LE || dstFormat == AV_PIX_FMT_GBRP14BE || dstFormat == AV_PIX_FMT_GBRP16LE || dstFormat == AV_PIX_FMT_GBRP16BE || + dstFormat == AV_PIX_FMT_GBRAP10LE || dstFormat == AV_PIX_FMT_GBRAP10BE || dstFormat == AV_PIX_FMT_GBRAP12LE || dstFormat == AV_PIX_FMT_GBRAP12BE || dstFormat == AV_PIX_FMT_GBRAP16LE || dstFormat == AV_PIX_FMT_GBRAP16BE )) c->swscale = Rgb16ToPlanarRgb16Wrapper; @@ -2002,6 +2079,7 @@ srcFormat == AV_PIX_FMT_GBRP10LE || srcFormat == AV_PIX_FMT_GBRP10BE || srcFormat == AV_PIX_FMT_GBRP12LE || srcFormat == AV_PIX_FMT_GBRP12BE || srcFormat == AV_PIX_FMT_GBRP14LE || srcFormat == AV_PIX_FMT_GBRP14BE || + srcFormat == AV_PIX_FMT_GBRAP10LE || srcFormat == AV_PIX_FMT_GBRAP10BE || srcFormat == AV_PIX_FMT_GBRAP12LE || srcFormat == AV_PIX_FMT_GBRAP12BE || srcFormat == AV_PIX_FMT_GBRAP16LE || srcFormat == AV_PIX_FMT_GBRAP16BE) && (dstFormat == AV_PIX_FMT_RGB48LE || dstFormat == AV_PIX_FMT_RGB48BE || @@ -2017,6 +2095,8 @@ if (isBayer(srcFormat)) { if (dstFormat == AV_PIX_FMT_RGB24) c->swscale = bayer_to_rgb24_wrapper; + else if (dstFormat == AV_PIX_FMT_RGB48) + c->swscale = bayer_to_rgb48_wrapper; else if (dstFormat == AV_PIX_FMT_YUV420P) c->swscale = bayer_to_yv12_wrapper; else if (!isBayer(dstFormat)) { @@ -2032,7 +2112,6 @@ IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BAYER_GRBG16) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR444) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR48) || - IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR555) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR565) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) || @@ -2048,11 +2127,11 @@ IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP12) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP14) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP16) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP10) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP12) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP16) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB444) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB48) || - IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB555) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB565) || IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) || @@ -2076,6 +2155,11 @@ IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P16)) c->swscale = bswap_16bpc; + /* bswap 32 bits per pixel/component formats */ + if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRPF32) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAPF32)) + c->swscale = bswap_32bpc; + if (usePal(srcFormat) && isByteRGB(dstFormat)) c->swscale = palToRgbWrapper; diff -Nru ffmpeg-4.2.2/libswscale/tests/floatimg_cmp.c ffmpeg-4.4/libswscale/tests/floatimg_cmp.c --- ffmpeg-4.2.2/libswscale/tests/floatimg_cmp.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libswscale/tests/floatimg_cmp.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,296 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include + +#include "libavutil/avutil.h" +#include "libavutil/imgutils.h" +#include "libavutil/intfloat.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/lfg.h" +#include "libavutil/mem.h" +#include "libavutil/parseutils.h" +#include "libavutil/pixdesc.h" + +#include "libswscale/swscale.h" + +#define DEFAULT_W 96 +#define DEFAULT_H 96 + +static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV444P16LE, + AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV444P9LE, AV_PIX_FMT_YUV444P10LE, + AV_PIX_FMT_YUV444P12LE, AV_PIX_FMT_YUV444P14LE, + AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, + AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, + AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR, + AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0, + AV_PIX_FMT_RGB48LE, AV_PIX_FMT_BGR48LE, + AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_BGRA64LE, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, + AV_PIX_FMT_GBRP9LE, + AV_PIX_FMT_GBRP10LE, AV_PIX_FMT_GBRAP10LE, + AV_PIX_FMT_GBRP12LE, AV_PIX_FMT_GBRAP12LE, + AV_PIX_FMT_GBRP14LE, + AV_PIX_FMT_GBRP16LE, AV_PIX_FMT_GBRAP16LE +}; + +const char *usage = "floatimg_cmp -pixel_format -size -ref \n"; + +int main(int argc, char **argv) +{ + enum AVPixelFormat inFormat = AV_PIX_FMT_NONE; + enum AVPixelFormat dstFormat = AV_PIX_FMT_NONE; + const AVPixFmtDescriptor *desc; + uint8_t *ptr; + uint32_t *in, *out; + + uint8_t *rgbIn[4] = {NULL, NULL, NULL, NULL}; + uint8_t *rgbOut[4] = {NULL, NULL, NULL, NULL}; + int rgbStride[4]; + + uint8_t *dst[4] = {NULL, NULL, NULL, NULL}; + int dstStride[4]; + + int i, x, y, p, size, count; + int res = -1; + int w = -1; + int h = -1; + union av_intfloat32 v0, v1; + + double sum; + float minimum, maximum, diff; + + struct SwsContext *sws = NULL; + AVLFG rand; + FILE *fp = NULL; + + for (i = 1; i < argc; i += 2) { + if (argv[i][0] != '-' || i + 1 == argc) + goto bad_option; + if (!strcmp(argv[i], "-ref")) { + fp = fopen(argv[i + 1], "rb"); + if (!fp) { + fprintf(stderr, "could not open '%s'\n", argv[i + 1]); + goto end; + } + } else if (!strcmp(argv[i], "-size")) { + res = av_parse_video_size(&w, &h, argv[i + 1]); + if (res < 0) { + fprintf(stderr, "invalid video size %s\n", argv[i + 1]); + goto end; + } + } else if (!strcmp(argv[i], "-pixel_format")) { + inFormat = av_get_pix_fmt(argv[i + 1]); + if (inFormat == AV_PIX_FMT_NONE) { + fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]); + goto end; + } + } else { +bad_option: + fprintf(stderr, "%s", usage); + fprintf(stderr, "bad option or argument missing (%s)\n", argv[i]); + goto end; + }; + } + + if (!fp) { + inFormat = AV_PIX_FMT_GBRPF32LE; + w = DEFAULT_W; + h = DEFAULT_H; + } + + if (w <= 0 || h <= 0) { + fprintf(stderr, "%s", usage); + fprintf(stderr, "invalid -video_size\n"); + goto end; + } + + if (inFormat == AV_PIX_FMT_NONE) { + fprintf(stderr, "%s", usage); + fprintf(stderr, "invalid input pixel format\n"); + goto end; + } + + desc = av_pix_fmt_desc_get(inFormat); + if (!(desc->flags & AV_PIX_FMT_FLAG_FLOAT)) { + fprintf(stderr, "input pixel format not floating point.\n"); + goto end; + } + + res = av_image_fill_linesizes(rgbStride, inFormat, w); + if (res < 0) { + fprintf(stderr, "av_image_fill_linesizes failed\n"); + goto end; + } + for (p = 0; p < 4; p++) { + rgbStride[p] = FFALIGN(rgbStride[p], 16); + if (rgbStride[p]) { + rgbIn[p] = av_mallocz(rgbStride[p] * h + 16); + rgbOut[p] = av_mallocz(rgbStride[p] * h + 16); + } + if (rgbStride[p] && (!rgbIn[p] || !rgbOut[p])) { + goto end; + } + } + + for (i = 0; i < FF_ARRAY_ELEMS(pix_fmts); i++) { + dstFormat = pix_fmts[i]; + if (fp) { + fseek(fp, 0, SEEK_SET); + for (p = 0; p < 4; p++) { + if (!rgbStride[p]) + continue; + + ptr = rgbIn[p]; + for (y = 0; y < h; y++) { + size = fread(ptr, 1, w*4, fp); + if (size != w*4) { + fprintf(stderr, "read error: %d\n", size); + goto end; + } + ptr += rgbStride[p]; + } + } + } else { + // fill src with random values between 0.0 - 1.0 + av_lfg_init(&rand, 1); + for (p = 0; p < 4; p++) { + if (!rgbStride[p]) + continue; + + for (y = 0; y < h; y++) { + in = (uint32_t*)(rgbIn[p] + y * rgbStride[p]); + for (x = 0; x < w; x++) { + v0.f = (float)av_lfg_get(&rand)/(float)(UINT32_MAX); + *in++ = AV_RL32(&v0.i); + } + } + } + } + + // setup intermediate image + for (p = 0; p < 4; p++) { + av_freep(&dst[p]); + } + + res = av_image_fill_linesizes(dstStride, dstFormat, w); + if (res < 0) { + fprintf(stderr, "av_image_fill_linesizes failed\n"); + goto end; + } + for (p = 0; p < 4; p++) { + dstStride[p] = FFALIGN(dstStride[p], 16); + if (dstStride[p]) { + dst[p] = av_mallocz(dstStride[p] * h + 16); + } + if (dstStride[p] && !dst[p]) { + goto end; + } + } + + // srcFormat -> dstFormat + sws = sws_getContext(w, h, inFormat, w, h, + dstFormat, SWS_BILINEAR, NULL, NULL, NULL); + if (!sws) { + fprintf(stderr, "Failed to get %s -> %s\n", av_get_pix_fmt_name(inFormat), av_get_pix_fmt_name(dstFormat) ); + goto end; + } + + res = sws_scale(sws, (const uint8_t *const *)rgbIn, rgbStride, 0, h, dst, dstStride); + if (res < 0 || res != h) { + fprintf(stderr, "sws_scale failed\n"); + res = -1; + goto end; + } + sws_freeContext(sws); + + // dstFormat -> srcFormat + sws = sws_getContext(w, h, dstFormat, w, h, + inFormat, SWS_BILINEAR, NULL, NULL, NULL); + if(!sws) { + fprintf(stderr, "Failed to get %s -> %s\n", av_get_pix_fmt_name(dstFormat), av_get_pix_fmt_name(inFormat) ); + goto end; + } + + res = sws_scale(sws, (const uint8_t *const *)dst, dstStride, 0, h, rgbOut, rgbStride); + if (res < 0 || res != h) { + fprintf(stderr, "sws_scale failed\n"); + res = -1; + goto end; + } + sws_freeContext(sws); + sws = NULL; + + minimum = FLT_MAX; + maximum = -FLT_MAX; + count = 0; + sum = 0.0; + + for (p = 0; p < 4; p++) { + if (!rgbStride[p]) + continue; + + for (y = 0; y < h; y++) { + in = (uint32_t*)(rgbIn[p] + y * rgbStride[p]); + out = (uint32_t*)(rgbOut[p] + y * rgbStride[p]); + for (x = 0; x < w; x++) { + if (desc->flags & AV_PIX_FMT_FLAG_BE) { + v0.i = AV_RB32(in); + v1.i = AV_RB32(out); + } else { + v0.i = AV_RL32(in); + v1.i = AV_RL32(out); + } + + diff = fabsf(v0.f - v1.f); + sum += diff; + minimum = FFMIN(minimum, diff); + maximum = FFMAX(maximum, diff); + + count++; + in++; + out++; + } + } + } + + fprintf(stdout, "%s -> %s -> %s\n", av_get_pix_fmt_name(inFormat), av_get_pix_fmt_name(dstFormat), av_get_pix_fmt_name(inFormat) ); + fprintf(stdout, "avg diff: %f\nmin diff: %f\nmax diff: %f\n", sum / count, minimum, maximum); + res = 0; + } + +end: + sws_freeContext(sws); + for (p = 0; p < 4; p++) { + av_freep(&rgbIn[p]); + av_freep(&rgbOut[p]); + av_freep(&dst[p]); + } + if (fp) + fclose(fp); + + return res; +} diff -Nru ffmpeg-4.2.2/libswscale/tests/swscale.c ffmpeg-4.4/libswscale/tests/swscale.c --- ffmpeg-4.2.2/libswscale/tests/swscale.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/tests/swscale.c 2021-04-08 21:28:40.000000000 +0000 @@ -248,7 +248,7 @@ if (dstStride[i]) av_free(dst[i]); - return res; + return !!res; } static void selfTest(const uint8_t * const ref[4], int refStride[4], @@ -422,7 +422,11 @@ for (y = 0; y < H; y++) for (x = 0; x < W * 4; x++) rgb_data[ x + y * 4 * W] = av_lfg_get(&rand); - sws_scale(sws, rgb_src, rgb_stride, 0, H / 12, (uint8_t * const *) src, stride); + res = sws_scale(sws, rgb_src, rgb_stride, 0, H / 12, (uint8_t * const *) src, stride); + if (res < 0 || res != H) { + res = -1; + goto error; + } sws_freeContext(sws); av_free(rgb_data); diff -Nru ffmpeg-4.2.2/libswscale/utils.c ffmpeg-4.4/libswscale/utils.c --- ffmpeg-4.2.2/libswscale/utils.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/utils.c 2021-04-08 21:28:40.000000000 +0000 @@ -86,7 +86,7 @@ const char *swscale_license(void) { #define LICENSE_PREFIX "libswscale license: " - return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; } typedef struct FormatEntry { @@ -95,7 +95,7 @@ uint8_t is_supported_endianness :1; } FormatEntry; -static const FormatEntry format_entries[AV_PIX_FMT_NB] = { +static const FormatEntry format_entries[] = { [AV_PIX_FMT_YUV420P] = { 1, 1 }, [AV_PIX_FMT_YUYV422] = { 1, 1 }, [AV_PIX_FMT_RGB24] = { 1, 1 }, @@ -236,6 +236,10 @@ [AV_PIX_FMT_GBRP14BE] = { 1, 1 }, [AV_PIX_FMT_GBRP16LE] = { 1, 1 }, [AV_PIX_FMT_GBRP16BE] = { 1, 1 }, + [AV_PIX_FMT_GBRPF32LE] = { 1, 1 }, + [AV_PIX_FMT_GBRPF32BE] = { 1, 1 }, + [AV_PIX_FMT_GBRAPF32LE] = { 1, 1 }, + [AV_PIX_FMT_GBRAPF32BE] = { 1, 1 }, [AV_PIX_FMT_GBRAP] = { 1, 1 }, [AV_PIX_FMT_GBRAP16LE] = { 1, 1 }, [AV_PIX_FMT_GBRAP16BE] = { 1, 1 }, @@ -266,23 +270,25 @@ [AV_PIX_FMT_YUVA444P12LE] = { 1, 1 }, [AV_PIX_FMT_NV24] = { 1, 1 }, [AV_PIX_FMT_NV42] = { 1, 1 }, + [AV_PIX_FMT_Y210LE] = { 1, 0 }, + [AV_PIX_FMT_X2RGB10LE] = { 1, 1 }, }; int sws_isSupportedInput(enum AVPixelFormat pix_fmt) { - return (unsigned)pix_fmt < AV_PIX_FMT_NB ? + return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ? format_entries[pix_fmt].is_supported_in : 0; } int sws_isSupportedOutput(enum AVPixelFormat pix_fmt) { - return (unsigned)pix_fmt < AV_PIX_FMT_NB ? + return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ? format_entries[pix_fmt].is_supported_out : 0; } int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt) { - return (unsigned)pix_fmt < AV_PIX_FMT_NB ? + return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ? format_entries[pix_fmt].is_supported_endianness : 0; } @@ -347,13 +353,14 @@ emms_c(); // FIXME should not be required but IS (even for non-MMX versions) // NOTE: the +3 is for the MMX(+1) / SSE(+3) scaler which reads over the end - FF_ALLOC_ARRAY_OR_GOTO(NULL, *filterPos, (dstW + 3), sizeof(**filterPos), fail); + if (!FF_ALLOC_TYPED_ARRAY(*filterPos, dstW + 3)) + goto nomem; if (FFABS(xInc - 0x10000) < 10 && srcPos == dstPos) { // unscaled int i; filterSize = 1; - FF_ALLOCZ_ARRAY_OR_GOTO(NULL, filter, - dstW, sizeof(*filter) * filterSize, fail); + if (!FF_ALLOCZ_TYPED_ARRAY(filter, dstW * filterSize)) + goto nomem; for (i = 0; i < dstW; i++) { filter[i * filterSize] = fone; @@ -363,8 +370,8 @@ int i; int64_t xDstInSrc; filterSize = 1; - FF_ALLOC_ARRAY_OR_GOTO(NULL, filter, - dstW, sizeof(*filter) * filterSize, fail); + if (!FF_ALLOC_TYPED_ARRAY(filter, dstW * filterSize)) + goto nomem; xDstInSrc = ((dstPos*(int64_t)xInc)>>8) - ((srcPos*0x8000LL)>>7); for (i = 0; i < dstW; i++) { @@ -379,8 +386,8 @@ int i; int64_t xDstInSrc; filterSize = 2; - FF_ALLOC_ARRAY_OR_GOTO(NULL, filter, - dstW, sizeof(*filter) * filterSize, fail); + if (!FF_ALLOC_TYPED_ARRAY(filter, dstW * filterSize)) + goto nomem; xDstInSrc = ((dstPos*(int64_t)xInc)>>8) - ((srcPos*0x8000LL)>>7); for (i = 0; i < dstW; i++) { @@ -390,7 +397,7 @@ (*filterPos)[i] = xx; // bilinear upscale / linear interpolate / area averaging for (j = 0; j < filterSize; j++) { - int64_t coeff= fone - FFABS(((int64_t)xx<<16) - xDstInSrc)*(fone>>16); + int64_t coeff = fone - FFABS((int64_t)xx * (1 << 16) - xDstInSrc) * (fone >> 16); if (coeff < 0) coeff = 0; filter[i * filterSize + j] = coeff; @@ -420,9 +427,8 @@ filterSize = FFMIN(filterSize, srcW - 2); filterSize = FFMAX(filterSize, 1); - FF_ALLOC_ARRAY_OR_GOTO(NULL, filter, - dstW, sizeof(*filter) * filterSize, fail); - + if (!FF_ALLOC_TYPED_ARRAY(filter, dstW * filterSize)) + goto nomem; xDstInSrc = ((dstPos*(int64_t)xInc)>>7) - ((srcPos*0x10000LL)>>7); for (i = 0; i < dstW; i++) { int xx = (xDstInSrc - (filterSize - 2) * (1LL<<16)) / (1 << 17); @@ -520,8 +526,8 @@ if (dstFilter) filter2Size += dstFilter->length - 1; av_assert0(filter2Size > 0); - FF_ALLOCZ_ARRAY_OR_GOTO(NULL, filter2, dstW, filter2Size * sizeof(*filter2), fail); - + if (!FF_ALLOCZ_TYPED_ARRAY(filter2, dstW * filter2Size)) + goto nomem; for (i = 0; i < dstW; i++) { int j, k; @@ -606,7 +612,7 @@ av_assert0(filterSize > 0); filter = av_malloc_array(dstW, filterSize * sizeof(*filter)); if (!filter) - goto fail; + goto nomem; if (filterSize >= MAX_FILTER_SIZE * 16 / ((flags & SWS_ACCURATE_RND) ? APCK_SIZE : 16)) { ret = RETCODE_USE_CASCADE; @@ -679,8 +685,8 @@ // Note the +1 is for the MMX scaler which reads over the end /* align at 16 for AltiVec (needed by hScale_altivec_real) */ - FF_ALLOCZ_ARRAY_OR_GOTO(NULL, *outFilter, - (dstW + 3), *outFilterSize * sizeof(int16_t), fail); + if (!FF_ALLOCZ_TYPED_ARRAY(*outFilter, *outFilterSize * (dstW + 3))) + goto nomem; /* normalize & store in outFilter */ for (i = 0; i < dstW; i++) { @@ -716,10 +722,13 @@ } ret = 0; - + goto done; +nomem: + ret = AVERROR(ENOMEM); fail: if(ret < 0) av_log(NULL, ret == RETCODE_USE_CASCADE ? AV_LOG_DEBUG : AV_LOG_ERROR, "sws: initFilter failed\n"); +done: av_free(filter); av_free(filter2); return ret; @@ -855,6 +864,11 @@ } } +static int range_override_needed(enum AVPixelFormat format) +{ + return !isYUV(format) && !isGray(format); +} + 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) @@ -867,9 +881,9 @@ desc_dst = av_pix_fmt_desc_get(c->dstFormat); desc_src = av_pix_fmt_desc_get(c->srcFormat); - if(!isYUV(c->dstFormat) && !isGray(c->dstFormat)) + if(range_override_needed(c->dstFormat)) dstRange = 0; - if(!isYUV(c->srcFormat) && !isGray(c->srcFormat)) + if(range_override_needed(c->srcFormat)) srcRange = 0; if (c->srcRange != srcRange || @@ -999,8 +1013,8 @@ *inv_table = c->srcColorspaceTable; *table = c->dstColorspaceTable; - *srcRange = c->srcRange; - *dstRange = c->dstRange; + *srcRange = range_override_needed(c->srcFormat) ? 1 : c->srcRange; + *dstRange = range_override_needed(c->dstFormat) ? 1 : c->dstRange; *brightness = c->brightness; *contrast = c->contrast; *saturation = c->saturation; @@ -1400,6 +1414,8 @@ srcFormat != AV_PIX_FMT_GBRP14BE && srcFormat != AV_PIX_FMT_GBRP14LE && srcFormat != AV_PIX_FMT_GBRP16BE && srcFormat != AV_PIX_FMT_GBRP16LE && srcFormat != AV_PIX_FMT_GBRAP16BE && srcFormat != AV_PIX_FMT_GBRAP16LE && + srcFormat != AV_PIX_FMT_GBRPF32BE && srcFormat != AV_PIX_FMT_GBRPF32LE && + srcFormat != AV_PIX_FMT_GBRAPF32BE && srcFormat != AV_PIX_FMT_GBRAPF32LE && ((dstW >> c->chrDstHSubSample) <= (srcW >> 1) || (flags & SWS_FAST_BILINEAR))) c->chrSrcHSubSample = 1; @@ -1410,7 +1426,8 @@ c->chrDstW = AV_CEIL_RSHIFT(dstW, c->chrDstHSubSample); c->chrDstH = AV_CEIL_RSHIFT(dstH, c->chrDstVSubSample); - FF_ALLOCZ_OR_GOTO(c, c->formatConvBuffer, FFALIGN(srcW*2+78, 16) * 2, fail); + if (!FF_ALLOCZ_TYPED_ARRAY(c->formatConvBuffer, FFALIGN(srcW * 2 + 78, 16) * 2)) + goto nomem; c->srcBpc = desc_src->comp[0].depth; if (c->srcBpc < 8) @@ -1479,7 +1496,7 @@ srcW, srcH, tmpFmt, flags, NULL, NULL, c->param); if (!c->cascaded_context[0]) { - return -1; + return AVERROR(ENOMEM); } c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFmt, @@ -1487,7 +1504,7 @@ flags, srcFilter, dstFilter, c->param); if (!c->cascaded_context[1]) - return -1; + return AVERROR(ENOMEM); c2 = c->cascaded_context[1]; c2->is_internal_gamma = 1; @@ -1500,9 +1517,10 @@ // to properly create the gamma convert FilterDescriptor // we have to re-initialize it ff_free_filters(c2); - if (ff_init_filters(c2) < 0) { + if ((ret = ff_init_filters(c2)) < 0) { sws_freeContext(c2); - return -1; + c->cascaded_context[1] = NULL; + return ret; } c->cascaded_context[2] = NULL; @@ -1516,15 +1534,16 @@ dstW, dstH, dstFormat, flags, NULL, NULL, c->param); if (!c->cascaded_context[2]) - return -1; + return AVERROR(ENOMEM); } return 0; } if (isBayer(srcFormat)) { if (!unscaled || - (dstFormat != AV_PIX_FMT_RGB24 && dstFormat != AV_PIX_FMT_YUV420P)) { - enum AVPixelFormat tmpFormat = AV_PIX_FMT_RGB24; + (dstFormat != AV_PIX_FMT_RGB24 && dstFormat != AV_PIX_FMT_YUV420P && + dstFormat != AV_PIX_FMT_RGB48)) { + enum AVPixelFormat tmpFormat = isBayer16BPS(srcFormat) ? AV_PIX_FMT_RGB48 : AV_PIX_FMT_RGB24; ret = av_image_alloc(c->cascaded_tmp, c->cascaded_tmpStride, srcW, srcH, tmpFormat, 64); @@ -1535,13 +1554,13 @@ srcW, srcH, tmpFormat, flags, srcFilter, NULL, c->param); if (!c->cascaded_context[0]) - return -1; + return AVERROR(ENOMEM); c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFormat, dstW, dstH, dstFormat, flags, NULL, dstFilter, c->param); if (!c->cascaded_context[1]) - return -1; + return AVERROR(ENOMEM); return 0; } } @@ -1562,41 +1581,42 @@ if (CONFIG_SWSCALE_ALPHA && isALPHA(srcFormat) && !isALPHA(dstFormat)) { enum AVPixelFormat tmpFormat = alphaless_fmt(srcFormat); - if (tmpFormat != AV_PIX_FMT_NONE && c->alphablend != SWS_ALPHA_BLEND_NONE) - if (!unscaled || - dstFormat != tmpFormat || - usesHFilter || usesVFilter || - c->srcRange != c->dstRange - ) { - c->cascaded_mainindex = 1; - ret = av_image_alloc(c->cascaded_tmp, c->cascaded_tmpStride, - srcW, srcH, tmpFormat, 64); - if (ret < 0) - return ret; - - c->cascaded_context[0] = sws_alloc_set_opts(srcW, srcH, srcFormat, - srcW, srcH, tmpFormat, - flags, c->param); - if (!c->cascaded_context[0]) - return -1; - c->cascaded_context[0]->alphablend = c->alphablend; - ret = sws_init_context(c->cascaded_context[0], NULL , NULL); - if (ret < 0) - return ret; - - c->cascaded_context[1] = sws_alloc_set_opts(srcW, srcH, tmpFormat, - dstW, dstH, dstFormat, - flags, c->param); - if (!c->cascaded_context[1]) - return -1; - - c->cascaded_context[1]->srcRange = c->srcRange; - c->cascaded_context[1]->dstRange = c->dstRange; - ret = sws_init_context(c->cascaded_context[1], srcFilter , dstFilter); - if (ret < 0) - return ret; + if (tmpFormat != AV_PIX_FMT_NONE && c->alphablend != SWS_ALPHA_BLEND_NONE) { + if (!unscaled || + dstFormat != tmpFormat || + usesHFilter || usesVFilter || + c->srcRange != c->dstRange + ) { + c->cascaded_mainindex = 1; + ret = av_image_alloc(c->cascaded_tmp, c->cascaded_tmpStride, + srcW, srcH, tmpFormat, 64); + if (ret < 0) + return ret; + + c->cascaded_context[0] = sws_alloc_set_opts(srcW, srcH, srcFormat, + srcW, srcH, tmpFormat, + flags, c->param); + if (!c->cascaded_context[0]) + return AVERROR(EINVAL); + c->cascaded_context[0]->alphablend = c->alphablend; + ret = sws_init_context(c->cascaded_context[0], NULL , NULL); + if (ret < 0) + return ret; + + c->cascaded_context[1] = sws_alloc_set_opts(srcW, srcH, tmpFormat, + dstW, dstH, dstFormat, + flags, c->param); + if (!c->cascaded_context[1]) + return AVERROR(EINVAL); + + c->cascaded_context[1]->srcRange = c->srcRange; + c->cascaded_context[1]->dstRange = c->dstRange; + ret = sws_init_context(c->cascaded_context[1], srcFilter , dstFilter); + if (ret < 0) + return ret; - return 0; + return 0; + } } } @@ -1649,10 +1669,11 @@ return AVERROR(ENOMEM); } - FF_ALLOCZ_OR_GOTO(c, c->hLumFilter, (dstW / 8 + 8) * sizeof(int16_t), fail); - FF_ALLOCZ_OR_GOTO(c, c->hChrFilter, (c->chrDstW / 4 + 8) * sizeof(int16_t), fail); - FF_ALLOCZ_OR_GOTO(c, c->hLumFilterPos, (dstW / 2 / 8 + 8) * sizeof(int32_t), fail); - FF_ALLOCZ_OR_GOTO(c, c->hChrFilterPos, (c->chrDstW / 2 / 4 + 8) * sizeof(int32_t), fail); + if (!FF_ALLOCZ_TYPED_ARRAY(c->hLumFilter, dstW / 8 + 8) || + !FF_ALLOCZ_TYPED_ARRAY(c->hChrFilter, c->chrDstW / 4 + 8) || + !FF_ALLOCZ_TYPED_ARRAY(c->hLumFilterPos, dstW / 2 / 8 + 8) || + !FF_ALLOCZ_TYPED_ARRAY(c->hChrFilterPos, c->chrDstW / 2 / 4 + 8)) + goto nomem; ff_init_hscaler_mmxext( dstW, c->lumXInc, c->lumMmxextFilterCode, c->hLumFilter, (uint32_t*)c->hLumFilterPos, 8); @@ -1663,6 +1684,7 @@ if ( mprotect(c->lumMmxextFilterCode, c->lumMmxextFilterCodeSize, PROT_EXEC | PROT_READ) == -1 || mprotect(c->chrMmxextFilterCode, c->chrMmxextFilterCodeSize, PROT_EXEC | PROT_READ) == -1) { av_log(c, AV_LOG_ERROR, "mprotect failed, cannot use fast bilinear scaler\n"); + ret = AVERROR(EINVAL); goto fail; } #endif @@ -1720,8 +1742,9 @@ goto fail; #if HAVE_ALTIVEC - FF_ALLOC_OR_GOTO(c, c->vYCoeffsBank, sizeof(vector signed short) * c->vLumFilterSize * c->dstH, fail); - FF_ALLOC_OR_GOTO(c, c->vCCoeffsBank, sizeof(vector signed short) * c->vChrFilterSize * c->chrDstH, fail); + if (!FF_ALLOC_TYPED_ARRAY(c->vYCoeffsBank, c->vLumFilterSize * c->dstH) || + !FF_ALLOC_TYPED_ARRAY(c->vCCoeffsBank, c->vChrFilterSize * c->chrDstH)) + goto nomem; for (i = 0; i < c->vLumFilterSize * c->dstH; i++) { int j; @@ -1740,7 +1763,8 @@ } for (i = 0; i < 4; i++) - FF_ALLOCZ_OR_GOTO(c, c->dither_error[i], (c->dstW+2) * sizeof(int), fail); + if (!FF_ALLOCZ_TYPED_ARRAY(c->dither_error[i], c->dstW + 2)) + goto nomem; c->needAlpha = (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat)) ? 1 : 0; @@ -1830,6 +1854,8 @@ c->swscale = ff_getSwsFunc(c); return ff_init_filters(c); +nomem: + ret = AVERROR(ENOMEM); fail: // FIXME replace things by appropriate error codes if (ret == RETCODE_USE_CASCADE) { int tmpW = sqrt(srcW * (int64_t)dstW); @@ -1851,16 +1877,16 @@ tmpW, tmpH, tmpFormat, flags, srcFilter, NULL, c->param); if (!c->cascaded_context[0]) - return -1; + return AVERROR(ENOMEM); c->cascaded_context[1] = sws_getContext(tmpW, tmpH, tmpFormat, dstW, dstH, dstFormat, flags, NULL, dstFilter, c->param); if (!c->cascaded_context[1]) - return -1; + return AVERROR(ENOMEM); return 0; } - return -1; + return ret; } SwsContext *sws_alloc_set_opts(int srcW, int srcH, enum AVPixelFormat srcFormat, diff -Nru ffmpeg-4.2.2/libswscale/version.h ffmpeg-4.4/libswscale/version.h --- ffmpeg-4.2.2/libswscale/version.h 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/version.h 2021-04-08 21:28:40.000000000 +0000 @@ -27,7 +27,7 @@ #include "libavutil/version.h" #define LIBSWSCALE_VERSION_MAJOR 5 -#define LIBSWSCALE_VERSION_MINOR 5 +#define LIBSWSCALE_VERSION_MINOR 9 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ diff -Nru ffmpeg-4.2.2/libswscale/vscale.c ffmpeg-4.4/libswscale/vscale.c --- ffmpeg-4.2.2/libswscale/vscale.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libswscale/vscale.c 2021-04-08 21:28:40.000000000 +0000 @@ -25,7 +25,14 @@ int32_t *filter_pos; int filter_size; int isMMX; - void *pfn; + union { + yuv2planar1_fn yuv2planar1; + yuv2planarX_fn yuv2planarX; + yuv2interleavedX_fn yuv2interleavedX; + yuv2packed1_fn yuv2packed1; + yuv2packed2_fn yuv2packed2; + yuv2anyX_fn yuv2anyX; + } pfn; yuv2packedX_fn yuv2packedX; } VScalerContext; @@ -43,9 +50,9 @@ uint16_t *filter = inst->filter[0] + (inst->isMMX ? 0 : sliceY * inst->filter_size); if (inst->filter_size == 1) - ((yuv2planar1_fn)inst->pfn)((const int16_t*)src[0], dst[0], dstW, c->lumDither8, 0); + inst->pfn.yuv2planar1((const int16_t*)src[0], dst[0], dstW, c->lumDither8, 0); else - ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src, dst[0], dstW, c->lumDither8, 0); + inst->pfn.yuv2planarX(filter, inst->filter_size, (const int16_t**)src, dst[0], dstW, c->lumDither8, 0); if (desc->alpha) { int sp = first - desc->src->plane[3].sliceY; @@ -55,9 +62,9 @@ uint16_t *filter = inst->filter[1] + (inst->isMMX ? 0 : sliceY * inst->filter_size); if (inst->filter_size == 1) - ((yuv2planar1_fn)inst->pfn)((const int16_t*)src[0], dst[0], dstW, c->lumDither8, 0); + inst->pfn.yuv2planar1((const int16_t*)src[0], dst[0], dstW, c->lumDither8, 0); else - ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src, dst[0], dstW, c->lumDither8, 0); + inst->pfn.yuv2planarX(filter, inst->filter_size, (const int16_t**)src, dst[0], dstW, c->lumDither8, 0); } return 1; @@ -85,13 +92,13 @@ uint16_t *filter = inst->filter[0] + (inst->isMMX ? 0 : chrSliceY * inst->filter_size); if (c->yuv2nv12cX) { - ((yuv2interleavedX_fn)inst->pfn)(c, filter, inst->filter_size, (const int16_t**)src1, (const int16_t**)src2, dst1[0], dstW); + inst->pfn.yuv2interleavedX(c->dstFormat, c->chrDither8, filter, inst->filter_size, (const int16_t**)src1, (const int16_t**)src2, dst1[0], dstW); } else if (inst->filter_size == 1) { - ((yuv2planar1_fn)inst->pfn)((const int16_t*)src1[0], dst1[0], dstW, c->chrDither8, 0); - ((yuv2planar1_fn)inst->pfn)((const int16_t*)src2[0], dst2[0], dstW, c->chrDither8, 3); + inst->pfn.yuv2planar1((const int16_t*)src1[0], dst1[0], dstW, c->chrDither8, 0); + inst->pfn.yuv2planar1((const int16_t*)src2[0], dst2[0], dstW, c->chrDither8, 3); } else { - ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src1, dst1[0], dstW, c->chrDither8, 0); - ((yuv2planarX_fn)inst->pfn)(filter, inst->filter_size, (const int16_t**)src2, dst2[0], dstW, c->chrDither8, inst->isMMX ? (c->uv_offx2 >> 1) : 3); + inst->pfn.yuv2planarX(filter, inst->filter_size, (const int16_t**)src1, dst1[0], dstW, c->chrDither8, 0); + inst->pfn.yuv2planarX(filter, inst->filter_size, (const int16_t**)src2, dst2[0], dstW, c->chrDither8, inst->isMMX ? (c->uv_offx2 >> 1) : 3); } } @@ -125,13 +132,13 @@ if (c->yuv2packed1 && lum_fsize == 1 && chr_fsize == 1) { // unscaled RGB - ((yuv2packed1_fn)inst->pfn)(c, (const int16_t*)*src0, (const int16_t**)src1, (const int16_t**)src2, + inst->pfn.yuv2packed1(c, (const int16_t*)*src0, (const int16_t**)src1, (const int16_t**)src2, (const int16_t*)(desc->alpha ? *src3 : NULL), *dst, dstW, 0, sliceY); } else if (c->yuv2packed1 && lum_fsize == 1 && chr_fsize == 2 && chr_filter[2 * chrSliceY + 1] + chr_filter[2 * chrSliceY] == 4096 && chr_filter[2 * chrSliceY + 1] <= 4096U) { // unscaled RGB int chrAlpha = chr_filter[2 * chrSliceY + 1]; - ((yuv2packed1_fn)inst->pfn)(c, (const int16_t*)*src0, (const int16_t**)src1, (const int16_t**)src2, + inst->pfn.yuv2packed1(c, (const int16_t*)*src0, (const int16_t**)src1, (const int16_t**)src2, (const int16_t*)(desc->alpha ? *src3 : NULL), *dst, dstW, chrAlpha, sliceY); } else if (c->yuv2packed2 && lum_fsize == 2 && chr_fsize == 2 && lum_filter[2 * sliceY + 1] + lum_filter[2 * sliceY] == 4096 && @@ -145,7 +152,7 @@ c->lumMmxFilter[3] = lum_filter[2 * sliceY] * 0x10001; c->chrMmxFilter[2] = c->chrMmxFilter[3] = chr_filter[2 * chrSliceY] * 0x10001; - ((yuv2packed2_fn)inst->pfn)(c, (const int16_t**)src0, (const int16_t**)src1, (const int16_t**)src2, (const int16_t**)src3, + inst->pfn.yuv2packed2(c, (const int16_t**)src0, (const int16_t**)src1, (const int16_t**)src2, (const int16_t**)src3, *dst, dstW, lumAlpha, chrAlpha, sliceY); } else { // general RGB if ((c->yuv2packed1 && lum_fsize == 1 && chr_fsize == 2) || @@ -195,7 +202,7 @@ desc->alpha ? desc->dst->plane[3].line[dp3] : NULL }; av_assert1(!c->yuv2packed1 && !c->yuv2packed2); - ((yuv2anyX_fn)inst->pfn)(c, lum_filter + sliceY * lum_fsize, + inst->pfn.yuv2anyX(c, lum_filter + sliceY * lum_fsize, (const int16_t**)src0, lum_fsize, chr_filter + sliceY * chr_fsize, (const int16_t**)src1, (const int16_t**)src2, chr_fsize, (const int16_t**)src3, dst, dstW, sliceY); @@ -270,9 +277,9 @@ chrCtx->isMMX = use_mmx; --idx; - if (yuv2nv12cX) chrCtx->pfn = yuv2nv12cX; - else if (c->vChrFilterSize == 1) chrCtx->pfn = yuv2plane1; - else chrCtx->pfn = yuv2planeX; + if (yuv2nv12cX) chrCtx->pfn.yuv2interleavedX = yuv2nv12cX; + else if (c->vChrFilterSize == 1) chrCtx->pfn.yuv2planar1 = yuv2plane1; + else chrCtx->pfn.yuv2planarX = yuv2planeX; } lumCtx = c->desc[idx].instance; @@ -283,8 +290,8 @@ lumCtx->filter_pos = c->vLumFilterPos; lumCtx->isMMX = use_mmx; - if (c->vLumFilterSize == 1) lumCtx->pfn = yuv2plane1; - else lumCtx->pfn = yuv2planeX; + if (c->vLumFilterSize == 1) lumCtx->pfn.yuv2planar1 = yuv2plane1; + else lumCtx->pfn.yuv2planarX = yuv2planeX; } else { lumCtx = c->desc[idx].instance; @@ -303,12 +310,12 @@ if (yuv2packedX) { if (c->yuv2packed1 && c->vLumFilterSize == 1 && c->vChrFilterSize <= 2) - lumCtx->pfn = yuv2packed1; + lumCtx->pfn.yuv2packed1 = yuv2packed1; else if (c->yuv2packed2 && c->vLumFilterSize == 2 && c->vChrFilterSize == 2) - lumCtx->pfn = yuv2packed2; + lumCtx->pfn.yuv2packed2 = yuv2packed2; lumCtx->yuv2packedX = yuv2packedX; } else - lumCtx->pfn = yuv2anyX; + lumCtx->pfn.yuv2anyX = yuv2anyX; } } diff -Nru ffmpeg-4.2.2/libswscale/x86/hscale_fast_bilinear_simd.c ffmpeg-4.4/libswscale/x86/hscale_fast_bilinear_simd.c --- ffmpeg-4.2.2/libswscale/x86/hscale_fast_bilinear_simd.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libswscale/x86/hscale_fast_bilinear_simd.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,6 +21,7 @@ #include "../swscale_internal.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" +#include "libavutil/mem_internal.h" #define RET 0xC3 // near return opcode for x86 #define PREFETCH "prefetchnta" diff -Nru ffmpeg-4.2.2/libswscale/x86/Makefile ffmpeg-4.4/libswscale/x86/Makefile --- ffmpeg-4.2.2/libswscale/x86/Makefile 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/x86/Makefile 2021-04-08 21:28:40.000000000 +0000 @@ -12,3 +12,5 @@ x86/output.o \ x86/scale.o \ x86/rgb_2_rgb.o \ + x86/yuv_2_rgb.o \ + x86/yuv2yuvX.o \ diff -Nru ffmpeg-4.2.2/libswscale/x86/output.asm ffmpeg-4.4/libswscale/x86/output.asm --- ffmpeg-4.2.2/libswscale/x86/output.asm 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/libswscale/x86/output.asm 2021-04-08 21:28:40.000000000 +0000 @@ -2,6 +2,7 @@ ;* x86-optimized vertical line scaling functions ;* Copyright (c) 2011 Ronald S. Bultje ;* Kieran Kunhya +;* (c) 2020 Nelson Gomez ;* ;* This file is part of FFmpeg. ;* @@ -22,7 +23,7 @@ %include "libavutil/x86/x86util.asm" -SECTION_RODATA +SECTION_RODATA 32 minshort: times 8 dw 0x8000 yuv2yuvX_16_start: times 4 dd 0x4000 - 0x40000000 @@ -34,9 +35,20 @@ pd_4min0x40000:times 4 dd 4 - (0x40000) pw_16: times 8 dw 16 pw_32: times 8 dw 32 +pd_255: times 8 dd 255 pw_512: times 8 dw 512 pw_1024: times 8 dw 1024 +yuv2nv12_shuffle_mask: times 2 db 0, 4, 8, 12, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1 +yuv2nv21_shuffle_mask: times 2 db 4, 0, 12, 8, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1 +yuv2nv12_permute_mask: dd 0, 4, 1, 2, 3, 5, 6, 7 + SECTION .text ;----------------------------------------------------------------------------- @@ -423,3 +435,117 @@ yuv2plane1_fn 10, 5, 3 yuv2plane1_fn 16, 5, 3 %endif + +%undef movsx + +;----------------------------------------------------------------------------- +; AVX2 yuv2nv12cX implementation +; +; void ff_yuv2nv12cX_avx2(enum AVPixelFormat format, const uint8_t *dither, +; const int16_t *filter, int filterSize, +; const int16_t **u, const int16_t **v, +; uint8_t *dst, int dstWidth) +; +; void ff_yuv2nv21cX_avx2(enum AVPixelFormat format, const uint8_t *dither, +; const int16_t *filter, int filterSize, +; const int16_t **u, const int16_t **v, +; uint8_t *dst, int dstWidth) +;----------------------------------------------------------------------------- + +%if ARCH_X86_64 +%macro yuv2nv12cX_fn 1 +cglobal %1cX, 8, 11, 13, tmp1, dither, filter, filterSize, u, v, dst, dstWidth + + mov tmp1q, qword [ditherq] + movq xm0, tmp1q + ror tmp1q, 24 + movq xm1, tmp1q + + pmovzxbd m0, xm0 + pslld m0, m0, 12 ; ditherLo + pmovzxbd m1, xm1 + pslld m1, m1, 12 ; ditherHi + + pxor m9, m9 ; uint8_min dwords + mova m10, [pd_255] ; uint8_max dwords + mova m11, [%1_shuffle_mask] ; shuffle_mask + mova m12, [yuv2nv12_permute_mask] ; permute mask + + DEFINE_ARGS tmp1, tmp2, filter, filterSize, u, v, dst, dstWidth + + xor r8q, r8q + +nv12_outer_%1: + mova m2, m0 ; resultLo + mova m3, m1 ; resultHi + xor r9q, r9q + +nv12_inner_%1: + movsx r10d, word [filterq + (2 * r9q)] + movd xm4, r10d + vpbroadcastd m4, xm4 ; filter + + mov tmp1q, [uq + (gprsize * r9q)] + mova xm7, oword [tmp1q + 2 * r8q] + + mov tmp2q, [vq + (gprsize * r9q)] + mova xm8, oword [tmp2q + 2 * r8q] + + punpcklwd xm5, xm7, xm8 + pmovsxwd m5, xm5 ; multiplicandsLo + punpckhwd xm6, xm7, xm8 + pmovsxwd m6, xm6 ; multiplicandsHi + + pmulld m7, m5, m4 ; mulResultLo + pmulld m8, m6, m4 ; mulResultHi + paddd m2, m2, m7 ; resultLo += mulResultLo + paddd m3, m3, m8 ; resultHi += mulResultHi + + inc r9d + cmp r9d, filterSized + jl nv12_inner_%1 + ; end of inner loop + + psrad m2, m2, 19 + psrad m3, m3, 19 + + ; Vectorized av_clip_uint8 + pmaxsd m2, m2, m9 + pmaxsd m3, m3, m9 + pminsd m2, m2, m10 + pminsd m3, m3, m10 + + ; At this point we have clamped uint8s arranged in this order: + ; m2: u1 0 0 0 v1 0 0 0 [...] + ; m3: u5 0 0 0 v5 0 0 0 [...] + ; + ; First, we shuffle the bytes to make the bytes semi-contiguous. + ; AVX-2 doesn't have cross-lane shuffling, so we'll end up with: + ; m2: u1 v1 u2 v2 0 0 0 0 0 0 0 0 u3 v3 u4 v4 + ; m3: u5 v5 u6 v6 0 0 0 0 0 0 0 0 u7 v7 u8 v8 + pshufb m2, m2, m11 + pshufb m3, m3, m11 + + ; To fix the cross-lane shuffling issue, we'll then use cross-lane + ; permutation to combine the two segments + vpermd m2, m12, m2 + vpermd m3, m12, m3 + + ; Now we have the final results in the lower 8 bytes of each register + movq [dstq], xm2 + movq [dstq + 8], xm3 + + add r8d, 8 + add dstq, 16 + + cmp r8d, dstWidthd + jl nv12_outer_%1 + RET +%endmacro + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +yuv2nv12cX_fn yuv2nv12 +yuv2nv12cX_fn yuv2nv21 +%endif +%endif ; ARCH_X86_64 diff -Nru ffmpeg-4.2.2/libswscale/x86/rgb2rgb.c ffmpeg-4.4/libswscale/x86/rgb2rgb.c --- ffmpeg-4.2.2/libswscale/x86/rgb2rgb.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/x86/rgb2rgb.c 2021-04-08 21:28:40.000000000 +0000 @@ -30,6 +30,8 @@ #include "libavutil/x86/cpu.h" #include "libavutil/cpu.h" #include "libavutil/bswap.h" +#include "libavutil/mem_internal.h" + #include "libswscale/rgb2rgb.h" #include "libswscale/swscale.h" #include "libswscale/swscale_internal.h" @@ -38,12 +40,7 @@ DECLARE_ASM_CONST(8, uint64_t, mmx_ff) = 0x00000000000000FFULL; DECLARE_ASM_CONST(8, uint64_t, mmx_null) = 0x0000000000000000ULL; -DECLARE_ASM_CONST(8, uint64_t, mmx_one) = 0xFFFFFFFFFFFFFFFFULL; -DECLARE_ASM_CONST(8, uint64_t, mask32b) = 0x000000FF000000FFULL; -DECLARE_ASM_CONST(8, uint64_t, mask32g) = 0x0000FF000000FF00ULL; -DECLARE_ASM_CONST(8, uint64_t, mask32r) = 0x00FF000000FF0000ULL; DECLARE_ASM_CONST(8, uint64_t, mask32a) = 0xFF000000FF000000ULL; -DECLARE_ASM_CONST(8, uint64_t, mask32) = 0x00FFFFFF00FFFFFFULL; DECLARE_ASM_CONST(8, uint64_t, mask3216br) = 0x00F800F800F800F8ULL; DECLARE_ASM_CONST(8, uint64_t, mask3216g) = 0x0000FC000000FC00ULL; DECLARE_ASM_CONST(8, uint64_t, mask3215g) = 0x0000F8000000F800ULL; @@ -54,9 +51,6 @@ DECLARE_ASM_CONST(8, uint64_t, mask24r) = 0x0000FF0000FF0000ULL; DECLARE_ASM_CONST(8, uint64_t, mask24l) = 0x0000000000FFFFFFULL; DECLARE_ASM_CONST(8, uint64_t, mask24h) = 0x0000FFFFFF000000ULL; -DECLARE_ASM_CONST(8, uint64_t, mask24hh) = 0xffff000000000000ULL; -DECLARE_ASM_CONST(8, uint64_t, mask24hhh) = 0xffffffff00000000ULL; -DECLARE_ASM_CONST(8, uint64_t, mask24hhhh) = 0xffffffffffff0000ULL; DECLARE_ASM_CONST(8, uint64_t, mask15b) = 0x001F001F001F001FULL; /* 00000000 00011111 xxB */ DECLARE_ASM_CONST(8, uint64_t, mask15rg) = 0x7FE07FE07FE07FE0ULL; /* 01111111 11100000 RGx */ DECLARE_ASM_CONST(8, uint64_t, mask15s) = 0xFFE0FFE0FFE0FFE0ULL; diff -Nru ffmpeg-4.2.2/libswscale/x86/swscale.c ffmpeg-4.4/libswscale/x86/swscale.c --- ffmpeg-4.2.2/libswscale/x86/swscale.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/x86/swscale.c 2021-04-08 21:28:40.000000000 +0000 @@ -27,17 +27,9 @@ #include "libavutil/intreadwrite.h" #include "libavutil/x86/cpu.h" #include "libavutil/cpu.h" +#include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" -#if HAVE_INLINE_ASM - -#define DITHER1XBPP - -DECLARE_ASM_CONST(8, uint64_t, bF8)= 0xF8F8F8F8F8F8F8F8LL; -DECLARE_ASM_CONST(8, uint64_t, bFC)= 0xFCFCFCFCFCFCFCFCLL; -DECLARE_ASM_CONST(8, uint64_t, w10)= 0x0010001000100010LL; -DECLARE_ASM_CONST(8, uint64_t, w02)= 0x0002000200020002LL; - const DECLARE_ALIGNED(8, uint64_t, ff_dither4)[2] = { 0x0103010301030103LL, 0x0200020002000200LL,}; @@ -46,12 +38,12 @@ 0x0602060206020602LL, 0x0004000400040004LL,}; -DECLARE_ASM_CONST(8, uint64_t, b16Mask)= 0x001F001F001F001FLL; -DECLARE_ASM_CONST(8, uint64_t, g16Mask)= 0x07E007E007E007E0LL; -DECLARE_ASM_CONST(8, uint64_t, r16Mask)= 0xF800F800F800F800LL; -DECLARE_ASM_CONST(8, uint64_t, b15Mask)= 0x001F001F001F001FLL; -DECLARE_ASM_CONST(8, uint64_t, g15Mask)= 0x03E003E003E003E0LL; -DECLARE_ASM_CONST(8, uint64_t, r15Mask)= 0x7C007C007C007C00LL; +#if HAVE_INLINE_ASM + +#define DITHER1XBPP + +DECLARE_ASM_CONST(8, uint64_t, bF8)= 0xF8F8F8F8F8F8F8F8LL; +DECLARE_ASM_CONST(8, uint64_t, bFC)= 0xFCFCFCFCFCFCFCFCLL; DECLARE_ASM_ALIGNED(8, const uint64_t, ff_M24A) = 0x00FF0000FF0000FFLL; DECLARE_ASM_ALIGNED(8, const uint64_t, ff_M24B) = 0xFF0000FF0000FF00LL; @@ -79,8 +71,7 @@ #include "swscale_template.c" #endif -void ff_updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrBufIndex, - int lastInLumBuf, int lastInChrBuf) +void ff_updateMMXDitherTables(SwsContext *c, int dstY) { const int dstH= c->dstH; const int flags= c->flags; @@ -160,7 +151,7 @@ *(const void**)&lumMmxFilter[s*i+APCK_PTR2/4 ]= lumSrcPtr[i+(vLumFilterSize>1)]; lumMmxFilter[s*i+APCK_COEF/4 ]= lumMmxFilter[s*i+APCK_COEF/4+1]= vLumFilter[dstY*vLumFilterSize + i ] - + (vLumFilterSize>1 ? vLumFilter[dstY*vLumFilterSize + i + 1]<<16 : 0); + + (vLumFilterSize>1 ? vLumFilter[dstY*vLumFilterSize + i + 1] * (1 << 16) : 0); if (CONFIG_SWSCALE_ALPHA && hasAlpha) { *(const void**)&alpMmxFilter[s*i ]= alpSrcPtr[i ]; *(const void**)&alpMmxFilter[s*i+APCK_PTR2/4 ]= alpSrcPtr[i+(vLumFilterSize>1)]; @@ -173,7 +164,7 @@ *(const void**)&chrMmxFilter[s*i+APCK_PTR2/4 ]= chrUSrcPtr[i+(vChrFilterSize>1)]; chrMmxFilter[s*i+APCK_COEF/4 ]= chrMmxFilter[s*i+APCK_COEF/4+1]= vChrFilter[chrDstY*vChrFilterSize + i ] - + (vChrFilterSize>1 ? vChrFilter[chrDstY*vChrFilterSize + i + 1]<<16 : 0); + + (vChrFilterSize>1 ? vChrFilter[chrDstY*vChrFilterSize + i + 1] * (1 << 16) : 0); } } else { for (i=0; i 0) \ + ff_yuv2yuvX_ ##opt(filter, filterSize - 1, 0, dest - offset, dstW + offset, dither, offset); \ + return; \ } -#endif -#endif /* HAVE_INLINE_ASM */ +#define YUV2YUVX_FUNC(opt, step) \ +void ff_yuv2yuvX_ ##opt(const int16_t *filter, int filterSize, int srcOffset, \ + uint8_t *dest, int dstW, \ + const uint8_t *dither, int offset); \ +static void yuv2yuvX_ ##opt(const int16_t *filter, int filterSize, \ + const int16_t **src, uint8_t *dest, int dstW, \ + const uint8_t *dither, int offset) \ +{ \ + int remainder = (dstW % step); \ + int pixelsProcessed = dstW - remainder; \ + if(((uintptr_t)dest) & 15){ \ + yuv2yuvX_mmx(filter, filterSize, src, dest, dstW, dither, offset); \ + return; \ + } \ + if(pixelsProcessed > 0) \ + ff_yuv2yuvX_ ##opt(filter, filterSize - 1, 0, dest - offset, pixelsProcessed + offset, dither, offset); \ + if(remainder > 0){ \ + ff_yuv2yuvX_mmx(filter, filterSize - 1, pixelsProcessed, dest - offset, pixelsProcessed + remainder + offset, dither, offset); \ + } \ + return; \ +} + +#if HAVE_MMX_EXTERNAL +YUV2YUVX_FUNC_MMX(mmx, 16) +#endif +#if HAVE_MMXEXT_EXTERNAL +YUV2YUVX_FUNC_MMX(mmxext, 16) +#endif +#if HAVE_SSE3_EXTERNAL +YUV2YUVX_FUNC(sse3, 32) +#endif +#if HAVE_AVX2_EXTERNAL +YUV2YUVX_FUNC(avx2, 64) +#endif #define SCALE_FUNC(filter_n, from_bpc, to_bpc, opt) \ void ff_hscale ## from_bpc ## to ## to_bpc ## _ ## filter_n ## _ ## opt( \ @@ -381,6 +341,17 @@ INPUT_FUNCS(ssse3); INPUT_FUNCS(avx); +#if ARCH_X86_64 +#define YUV2NV_DECL(fmt, opt) \ +void ff_yuv2 ## fmt ## cX_ ## opt(enum AVPixelFormat format, const uint8_t *dither, \ + const int16_t *filter, int filterSize, \ + const int16_t **u, const int16_t **v, \ + uint8_t *dst, int dstWidth) + +YUV2NV_DECL(nv12, avx2); +YUV2NV_DECL(nv21, avx2); +#endif + av_cold void ff_sws_init_swscale_x86(SwsContext *c) { int cpu_flags = av_get_cpu_flags(); @@ -392,11 +363,25 @@ #if HAVE_MMXEXT_INLINE if (INLINE_MMXEXT(cpu_flags)) sws_init_swscale_mmxext(c); - if (cpu_flags & AV_CPU_FLAG_SSE3){ - if(c->use_mmx_vfilter && !(c->flags & SWS_ACCURATE_RND)) +#endif + if(c->use_mmx_vfilter && !(c->flags & SWS_ACCURATE_RND)) { +#if HAVE_MMX_EXTERNAL + if (EXTERNAL_MMX(cpu_flags)) + c->yuv2planeX = yuv2yuvX_mmx; +#endif +#if HAVE_MMXEXT_EXTERNAL + if (EXTERNAL_MMXEXT(cpu_flags)) + c->yuv2planeX = yuv2yuvX_mmxext; +#endif +#if HAVE_SSE3_EXTERNAL + if (EXTERNAL_SSE3(cpu_flags)) c->yuv2planeX = yuv2yuvX_sse3; - } #endif +#if HAVE_AVX2_EXTERNAL + if (EXTERNAL_AVX2_FAST(cpu_flags)) + c->yuv2planeX = yuv2yuvX_avx2; +#endif + } #define ASSIGN_SCALE_FUNC2(hscalefn, filtersize, opt1, opt2) do { \ if (c->srcBpc == 8) { \ @@ -581,4 +566,21 @@ break; } } + +#if ARCH_X86_64 + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + switch (c->dstFormat) { + case AV_PIX_FMT_NV12: + case AV_PIX_FMT_NV24: + c->yuv2nv12cX = ff_yuv2nv12cX_avx2; + break; + case AV_PIX_FMT_NV21: + case AV_PIX_FMT_NV42: + c->yuv2nv12cX = ff_yuv2nv21cX_avx2; + break; + default: + break; + } + } +#endif } diff -Nru ffmpeg-4.2.2/libswscale/x86/swscale_template.c ffmpeg-4.4/libswscale/x86/swscale_template.c --- ffmpeg-4.2.2/libswscale/x86/swscale_template.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/x86/swscale_template.c 2021-04-08 21:28:40.000000000 +0000 @@ -38,88 +38,6 @@ #endif #define MOVNTQ(a,b) REAL_MOVNTQ(a,b) -#if !COMPILE_TEMPLATE_MMXEXT -static av_always_inline void -dither_8to16(const uint8_t *srcDither, int rot) -{ - if (rot) { - __asm__ volatile("pxor %%mm0, %%mm0\n\t" - "movq (%0), %%mm3\n\t" - "movq %%mm3, %%mm4\n\t" - "psrlq $24, %%mm3\n\t" - "psllq $40, %%mm4\n\t" - "por %%mm4, %%mm3\n\t" - "movq %%mm3, %%mm4\n\t" - "punpcklbw %%mm0, %%mm3\n\t" - "punpckhbw %%mm0, %%mm4\n\t" - :: "r"(srcDither) - ); - } else { - __asm__ volatile("pxor %%mm0, %%mm0\n\t" - "movq (%0), %%mm3\n\t" - "movq %%mm3, %%mm4\n\t" - "punpcklbw %%mm0, %%mm3\n\t" - "punpckhbw %%mm0, %%mm4\n\t" - :: "r"(srcDither) - ); - } -} -#endif - -static void RENAME(yuv2yuvX)(const int16_t *filter, int filterSize, - const int16_t **src, uint8_t *dest, int dstW, - const uint8_t *dither, int offset) -{ - dither_8to16(dither, offset); - filterSize--; - __asm__ volatile( - "movd %0, %%mm1\n\t" - "punpcklwd %%mm1, %%mm1\n\t" - "punpckldq %%mm1, %%mm1\n\t" - "psllw $3, %%mm1\n\t" - "paddw %%mm1, %%mm3\n\t" - "paddw %%mm1, %%mm4\n\t" - "psraw $4, %%mm3\n\t" - "psraw $4, %%mm4\n\t" - ::"m"(filterSize) - ); - - __asm__ volatile(\ - "movq %%mm3, %%mm6\n\t" - "movq %%mm4, %%mm7\n\t" - "movl %3, %%ecx\n\t" - "mov %0, %%"FF_REG_d" \n\t"\ - "mov (%%"FF_REG_d"), %%"FF_REG_S" \n\t"\ - ".p2align 4 \n\t" /* FIXME Unroll? */\ - "1: \n\t"\ - "movq 8(%%"FF_REG_d"), %%mm0 \n\t" /* filterCoeff */\ - "movq (%%"FF_REG_S", %%"FF_REG_c", 2), %%mm2 \n\t" /* srcData */\ - "movq 8(%%"FF_REG_S", %%"FF_REG_c", 2), %%mm5 \n\t" /* srcData */\ - "add $16, %%"FF_REG_d" \n\t"\ - "mov (%%"FF_REG_d"), %%"FF_REG_S" \n\t"\ - "test %%"FF_REG_S", %%"FF_REG_S" \n\t"\ - "pmulhw %%mm0, %%mm2 \n\t"\ - "pmulhw %%mm0, %%mm5 \n\t"\ - "paddw %%mm2, %%mm3 \n\t"\ - "paddw %%mm5, %%mm4 \n\t"\ - " jnz 1b \n\t"\ - "psraw $3, %%mm3 \n\t"\ - "psraw $3, %%mm4 \n\t"\ - "packuswb %%mm4, %%mm3 \n\t" - MOVNTQ2 " %%mm3, (%1, %%"FF_REG_c")\n\t" - "add $8, %%"FF_REG_c" \n\t"\ - "cmp %2, %%"FF_REG_c" \n\t"\ - "movq %%mm6, %%mm3\n\t" - "movq %%mm7, %%mm4\n\t" - "mov %0, %%"FF_REG_d" \n\t"\ - "mov (%%"FF_REG_d"), %%"FF_REG_S" \n\t"\ - "jb 1b \n\t"\ - :: "g" (filter), - "r" (dest-offset), "g" ((x86_reg)(dstW+offset)), "m" (offset) - : "%"FF_REG_d, "%"FF_REG_S, "%"FF_REG_c - ); -} - #define YSCALEYUV2PACKEDX_UV \ __asm__ volatile(\ "xor %%"FF_REG_a", %%"FF_REG_a" \n\t"\ @@ -1517,7 +1435,6 @@ } } else { c->use_mmx_vfilter= 1; - c->yuv2planeX = RENAME(yuv2yuvX ); if (!(c->flags & SWS_FULL_CHR_H_INT)) { switch (c->dstFormat) { case AV_PIX_FMT_RGB32: c->yuv2packedX = RENAME(yuv2rgb32_X); break; diff -Nru ffmpeg-4.2.2/libswscale/x86/yuv_2_rgb.asm ffmpeg-4.4/libswscale/x86/yuv_2_rgb.asm --- ffmpeg-4.2.2/libswscale/x86/yuv_2_rgb.asm 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libswscale/x86/yuv_2_rgb.asm 2021-02-20 20:27:47.000000000 +0000 @@ -0,0 +1,383 @@ +;****************************************************************************** +;* software YUV to RGB converter +;* +;* Copyright (C) 2001-2007 Michael Niedermayer +;* (c) 2010 Konstantin Shishkov +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +; below variables are named like mask_dwXY, which means to preserve dword No.X & No.Y +mask_dw036 : db -1, -1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, -1, -1, 0, 0 +mask_dw147 : db 0, 0, -1, -1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, -1, -1 +mask_dw25 : db 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0 +rgb24_shuf1: db 0, 1, 6, 7, 12, 13, 2, 3, 8, 9, 14, 15, 4, 5, 10, 11 +rgb24_shuf2: db 10, 11, 0, 1, 6, 7, 12, 13, 2, 3, 8, 9, 14, 15, 4, 5 +rgb24_shuf3: db 4, 5, 10, 11, 0, 1, 6, 7, 12, 13, 2, 3, 8, 9, 14, 15 +pw_00ff: times 8 dw 255 +pb_f8: times 16 db 248 +pb_e0: times 16 db 224 +pb_03: times 16 db 3 +pb_07: times 16 db 7 + +mask_1101: dw -1, -1, 0, -1 +mask_0010: dw 0, 0, -1, 0 +mask_0110: dw 0, -1, -1, 0 +mask_1001: dw -1, 0, 0, -1 +mask_0100: dw 0, -1, 0, 0 + +SECTION .text + +;----------------------------------------------------------------------------- +; +; YUV420/YUVA420 to RGB/BGR 15/16/24/32 +; R = Y + ((vrCoff * (v - 128)) >> 8) +; G = Y - ((ugCoff * (u - 128) + vgCoff * (v - 128)) >> 8) +; B = Y + ((ubCoff * (u - 128)) >> 8) +; +;----------------------------------------------------------------------------- + +%macro MOV_H2L 1 +%if mmsize == 8 + psrlq %1, 32 +%else ; mmsize == 16 + psrldq %1, 8 +%endif +%endmacro + +%macro yuv2rgb_fn 3 + +%if %3 == 32 + %ifidn %1, yuva + %define parameters index, image, pu_index, pv_index, pointer_c_dither, py_2index, pa_2index + %define GPR_num 7 + %endif +%else + %define parameters index, image, pu_index, pv_index, pointer_c_dither, py_2index + %define GPR_num 6 +%endif + +%define m_green m2 +%define m_alpha m3 +%define m_y m6 +%define m_u m0 +%define m_v m1 +%ifidn %2, rgb +%define m_red m1 +%define m_blue m0 +%else +%define m_red m0 +%define m_blue m1 +%endif + +%if mmsize == 8 +%define time_num 1 +%define reg_num 8 +%define y_offset [pointer_c_ditherq + 8 * 8] +%define u_offset [pointer_c_ditherq + 9 * 8] +%define v_offset [pointer_c_ditherq + 10 * 8] +%define ug_coff [pointer_c_ditherq + 7 * 8] +%define vg_coff [pointer_c_ditherq + 6 * 8] +%define y_coff [pointer_c_ditherq + 3 * 8] +%define ub_coff [pointer_c_ditherq + 5 * 8] +%define vr_coff [pointer_c_ditherq + 4 * 8] +%elif mmsize == 16 +%define time_num 2 +%if ARCH_X86_32 +%define reg_num 8 +%define my_offset [pointer_c_ditherq + 8 * 8] +%define mu_offset [pointer_c_ditherq + 9 * 8] +%define mv_offset [pointer_c_ditherq + 10 * 8] +%define mug_coff [pointer_c_ditherq + 7 * 8] +%define mvg_coff [pointer_c_ditherq + 6 * 8] +%define my_coff [pointer_c_ditherq + 3 * 8] +%define mub_coff [pointer_c_ditherq + 5 * 8] +%define mvr_coff [pointer_c_ditherq + 4 * 8] +%else ; ARCH_X86_64 +%define reg_num 16 +%define y_offset m8 +%define u_offset m9 +%define v_offset m10 +%define ug_coff m11 +%define vg_coff m12 +%define y_coff m13 +%define ub_coff m14 +%define vr_coff m15 +%endif ; ARCH_X86_32/64 +%endif ; coeff define mmsize == 8/16 + +cglobal %1_420_%2%3, GPR_num, GPR_num, reg_num, parameters + +%if ARCH_X86_64 + movsxd indexq, indexd +%if mmsize == 16 + VBROADCASTSD y_offset, [pointer_c_ditherq + 8 * 8] + VBROADCASTSD u_offset, [pointer_c_ditherq + 9 * 8] + VBROADCASTSD v_offset, [pointer_c_ditherq + 10 * 8] + VBROADCASTSD ug_coff, [pointer_c_ditherq + 7 * 8] + VBROADCASTSD vg_coff, [pointer_c_ditherq + 6 * 8] + VBROADCASTSD y_coff, [pointer_c_ditherq + 3 * 8] + VBROADCASTSD ub_coff, [pointer_c_ditherq + 5 * 8] + VBROADCASTSD vr_coff, [pointer_c_ditherq + 4 * 8] +%endif +%endif + movu m_y, [py_2indexq + 2 * indexq] + movh m_u, [pu_indexq + indexq] + movh m_v, [pv_indexq + indexq] +.loop0: + pxor m4, m4 + mova m7, m6 + punpcklbw m0, m4 + punpcklbw m1, m4 + mova m2, [pw_00ff] + pand m6, m2 + psrlw m7, 8 + psllw m0, 3 + psllw m1, 3 + psllw m6, 3 + psllw m7, 3 +%if (ARCH_X86_32 && mmsize == 16) + VBROADCASTSD m2, mu_offset + VBROADCASTSD m3, mv_offset + VBROADCASTSD m4, my_offset + psubsw m0, m2 ; U = U - 128 + psubsw m1, m3 ; V = V - 128 + psubw m6, m4 + psubw m7, m4 + VBROADCASTSD m2, mug_coff + VBROADCASTSD m3, mvg_coff + VBROADCASTSD m4, my_coff + VBROADCASTSD m5, mub_coff + pmulhw m2, m0 + pmulhw m3, m1 + pmulhw m6, m4 + pmulhw m7, m4 + pmulhw m0, m5 + VBROADCASTSD m4, mvr_coff + pmulhw m1, m4 +%else ; ARCH_X86_64 || mmsize == 8 + psubsw m0, u_offset ; U = U - 128 + psubsw m1, v_offset ; V = V - 128 + psubw m6, y_offset + psubw m7, y_offset + mova m2, m0 + mova m3, m1 + pmulhw m2, ug_coff + pmulhw m3, vg_coff + pmulhw m6, y_coff + pmulhw m7, y_coff + pmulhw m0, ub_coff + pmulhw m1, vr_coff +%endif + paddsw m2, m3 + mova m3, m7 + mova m5, m7 + paddsw m3, m0 ; B1 B3 B5 B7 ... + paddsw m5, m1 ; R1 R3 R5 R7 ... + paddsw m7, m2 ; G1 G3 G4 G7 ... + paddsw m0, m6 ; B0 B2 B4 B6 ... + paddsw m1, m6 ; R0 R2 R4 R6 ... + paddsw m2, m6 ; G0 G2 G4 G6 ... + +%if %3 == 24 ; PACK RGB24 +%define depth 3 + packuswb m0, m3 ; R0 R2 R4 R6 ... R1 R3 R5 R7 ... + packuswb m1, m5 ; B0 B2 B4 B6 ... B1 B3 B5 B7 ... + packuswb m2, m7 ; G0 G2 G4 G6 ... G1 G3 G5 G7 ... + mova m3, m_red + mova m6, m_blue + MOV_H2L m_red + punpcklbw m3, m2 ; R0 G0 R2 G2 R4 G4 R6 G6 R8 G8 ... + punpcklbw m6, m_red ; B0 R1 B2 R3 B4 R5 B6 R7 B8 R9 ... + mova m5, m3 + punpckhbw m2, m_blue ; G1 B1 G3 B3 G5 B5 G7 B7 G9 B9 ... +%if mmsize == 8 + punpcklwd m3 ,m6 ; R0 G0 B0 R1 R2 G2 B2 R3 + punpckhwd m5, m6 ; R4 G4 B4 R5 R6 G6 B6 R7 +%if cpuflag(mmxext) + pshufw m1, m2, 0xc6 + pshufw m6, m3, 0x84 + pshufw m7, m5, 0x38 + pand m6, [mask_1101] ; R0 G0 B0 R1 -- -- R2 G2 + movq m0, m1 + pand m7, [mask_0110] ; -- -- R6 G6 B6 R7 -- -- + movq m2, m1 + pand m1, [mask_0100] ; -- -- G3 B3 -- -- -- -- + psrlq m3, 48 ; B2 R3 -- -- -- -- -- -- + pand m0, [mask_0010] ; -- -- -- -- G1 B1 -- -- + psllq m5, 32 ; -- -- -- -- R4 G4 B4 R5 + pand m2, [mask_1001] ; G5 B5 -- -- -- -- G7 B7 + por m1, m3 + por m0, m6 + por m1, m5 + por m2, m7 + movntq [imageq], m0 + movntq [imageq + 8], m1 + movntq [imageq + 16], m2 +%else ; cpuflag(mmx) + movd [imageq], m3 ; R0 G0 R2 G2 + movd [imageq + 4], m2 ; G1 B1 + psrlq m3, 32 + psrlq m2, 16 + movd [imageq + 6], m3 ; R2 G2 B2 R3 + movd [imageq + 10], m2 ; G3 B3 + psrlq m2, 16 + movd [imageq + 12], m5 ; R4 G4 B4 R5 + movd [imageq + 16], m2 ; G5 B5 + psrlq m5, 32 + movd [imageq + 20], m2 ; -- -- G7 B7 + movd [imageq + 18], m5 ; R6 G6 B6 R7 +%endif ; mmsize = 8 +%else ; mmsize == 16 + pshufb m3, [rgb24_shuf1] ; r0 g0 r6 g6 r12 g12 r2 g2 r8 g8 r14 g14 r4 g4 r10 g10 + pshufb m6, [rgb24_shuf2] ; b10 r11 b0 r1 b6 r7 b12 r13 b2 r3 b8 r9 b14 r15 b4 r5 + pshufb m2, [rgb24_shuf3] ; g5 b5 g11 b11 g1 b1 g7 b7 g13 b13 g3 b3 g9 b9 g15 b15 + mova m7, [mask_dw036] + mova m4, [mask_dw147] + mova m5, [mask_dw25] + pand m0, m7, m3 ; r0 g0 --- --- --- --- r2 g2 --- --- --- --- r4 g4 --- --- + pand m1, m4, m6 ; --- --- b0 r1 --- --- --- --- b2 r3 --- --- --- --- b4 r5 + por m0, m1 + pand m1, m5, m2 ; --- --- --- --- g1 b1 --- --- --- --- g3 b3 --- --- --- --- + por m0, m1 ; r0 g0 b0 r1 g1 b1 r2 g2 b2 r3 g3 b3 r4 g4 b4 r5 + pand m1, m7, m2 ; g5 b5 --- --- --- --- g7 b7 --- --- --- --- g9 b9 --- --- + pand m7, m6 ; b10 r11 --- --- --- --- b12 r13 --- --- --- --- b14 r15 --- --- + pand m6, m5 ; --- --- --- --- b6 r7 --- --- --- --- b8 r9 --- --- --- --- + por m1, m6 + pand m6, m4, m3 ; --- --- r6 g6 --- --- --- --- r8 g8 --- --- --- --- r10 g10 + pand m2, m4 ; --- --- g11 b11 --- --- --- --- g13 b13 --- --- --- --- g15 b15 + pand m3, m5 ; --- --- --- --- r12 g12 --- --- --- --- r14 g14 --- --- --- --- + por m2, m7 + por m1, m6 ; g5 b5 r6 g6 b6 r7 g7 b7 r8 g8 b8 r9 g9 b9 r10 g10 + por m2, m3 ; b10 r11 g11 b11 r12 g12 b12 r13 g13 b13 r14 g14 b14 r15 g15 b15 + movu [imageq], m0 + movu [imageq + 16], m1 + movu [imageq + 32], m2 +%endif ; mmsize = 16 +%else ; PACK RGB15/16/32 + packuswb m0, m1 + packuswb m3, m5 + packuswb m2, m2 + mova m1, m0 + packuswb m7, m7 + punpcklbw m0, m3 ; B0 B1 B2 B3 ... B7 + punpckhbw m1, m3 ; R0 R1 R2 R3 ... R7 + punpcklbw m2, m7 ; G0 G1 G2 G3 ... G7 +%if %3 == 32 ; PACK RGB32 +%define depth 4 +%ifidn %1, yuv + pcmpeqd m3, m3 ; Set alpha empty +%else + movu m3, [pa_2indexq + 2 * indexq] ; Load alpha +%endif + mova m5, m_blue + mova m6, m_red + punpckhbw m5, m_green + punpcklbw m_blue, m_green + punpckhbw m6, m_alpha + punpcklbw m_red, m_alpha + mova m_green, m_blue + mova m_alpha, m5 + punpcklwd m_blue, m_red + punpckhwd m_green, m_red + punpcklwd m5, m6 + punpckhwd m_alpha, m6 + movu [imageq + 0], m_blue + movu [imageq + 8 * time_num], m_green + movu [imageq + 16 * time_num], m5 + movu [imageq + 24 * time_num], m_alpha +%else ; PACK RGB15/16 +%define depth 2 +%if cpuflag(ssse3) + %define red_dither m3 + %define green_dither m4 + %define blue_dither m5 + VBROADCASTSD red_dither, [pointer_c_ditherq + 0 * 8] + VBROADCASTSD green_dither, [pointer_c_ditherq + 1 * 8] + VBROADCASTSD blue_dither, [pointer_c_ditherq + 2 * 8] +%else ; cpuflag(mmx/mmxext) +%define blue_dither [pointer_c_ditherq + 2 * 8] +%define green_dither [pointer_c_ditherq + 1 * 8] +%define red_dither [pointer_c_ditherq + 0 * 8] +%endif +%if %3 == 15 +%define gmask pb_03 +%define isRGB15 1 +%else +%define gmask pb_07 +%define isRGB15 0 +%endif + paddusb m0, blue_dither + paddusb m2, green_dither + paddusb m1, red_dither + pand m0, [pb_f8] + pand m1, [pb_f8] + mova m3, m2 + psllw m2, 3 - isRGB15 + psrlw m3, 5 + isRGB15 + psrlw m0, 3 + psrlw m1, isRGB15 + pand m2, [pb_e0] + pand m3, [gmask] + por m0, m2 + por m1, m3 + mova m2, m0 + punpcklbw m0, m1 + punpckhbw m2, m1 + movu [imageq], m0 + movu [imageq + 8 * time_num], m2 +%endif ; PACK RGB15/16 +%endif ; PACK RGB15/16/32 + +movu m_y, [py_2indexq + 2 * indexq + 8 * time_num] +movh m_v, [pv_indexq + indexq + 4 * time_num] +movh m_u, [pu_indexq + indexq + 4 * time_num] +add imageq, 8 * depth * time_num +add indexq, 4 * time_num +js .loop0 + +REP_RET + +%endmacro + +INIT_MMX mmx +yuv2rgb_fn yuv, rgb, 24 +yuv2rgb_fn yuv, bgr, 24 +yuv2rgb_fn yuv, rgb, 32 +yuv2rgb_fn yuv, bgr, 32 +yuv2rgb_fn yuva, rgb, 32 +yuv2rgb_fn yuva, bgr, 32 +yuv2rgb_fn yuv, rgb, 15 +yuv2rgb_fn yuv, rgb, 16 + +INIT_MMX mmxext +yuv2rgb_fn yuv, rgb, 24 +yuv2rgb_fn yuv, bgr, 24 + +INIT_XMM ssse3 +yuv2rgb_fn yuv, rgb, 24 +yuv2rgb_fn yuv, bgr, 24 +yuv2rgb_fn yuv, rgb, 32 +yuv2rgb_fn yuv, bgr, 32 +yuv2rgb_fn yuva, rgb, 32 +yuv2rgb_fn yuva, bgr, 32 +yuv2rgb_fn yuv, rgb, 15 +yuv2rgb_fn yuv, rgb, 16 diff -Nru ffmpeg-4.2.2/libswscale/x86/yuv2rgb.c ffmpeg-4.4/libswscale/x86/yuv2rgb.c --- ffmpeg-4.2.2/libswscale/x86/yuv2rgb.c 2016-03-29 02:25:33.000000000 +0000 +++ ffmpeg-4.4/libswscale/x86/yuv2rgb.c 2021-04-08 21:28:40.000000000 +0000 @@ -37,45 +37,70 @@ #include "libavutil/x86/cpu.h" #include "libavutil/cpu.h" -#if HAVE_INLINE_ASM +#if HAVE_X86ASM #define DITHER1XBPP // only for MMX -/* hope these constant values are cache line aligned */ -DECLARE_ASM_CONST(8, uint64_t, mmx_00ffw) = 0x00ff00ff00ff00ffULL; -DECLARE_ASM_CONST(8, uint64_t, mmx_redmask) = 0xf8f8f8f8f8f8f8f8ULL; -DECLARE_ASM_CONST(8, uint64_t, mmx_grnmask) = 0xfcfcfcfcfcfcfcfcULL; -DECLARE_ASM_CONST(8, uint64_t, pb_e0) = 0xe0e0e0e0e0e0e0e0ULL; -DECLARE_ASM_CONST(8, uint64_t, pb_03) = 0x0303030303030303ULL; -DECLARE_ASM_CONST(8, uint64_t, pb_07) = 0x0707070707070707ULL; - //MMX versions -#if HAVE_MMX_INLINE && HAVE_6REGS +#if HAVE_MMX #undef RENAME #undef COMPILE_TEMPLATE_MMXEXT #define COMPILE_TEMPLATE_MMXEXT 0 #define RENAME(a) a ## _mmx #include "yuv2rgb_template.c" -#endif /* HAVE_MMX_INLINE && HAVE_6REGS */ +#endif /* HAVE_MMX */ // MMXEXT versions -#if HAVE_MMXEXT_INLINE && HAVE_6REGS #undef RENAME #undef COMPILE_TEMPLATE_MMXEXT #define COMPILE_TEMPLATE_MMXEXT 1 #define RENAME(a) a ## _mmxext #include "yuv2rgb_template.c" -#endif /* HAVE_MMXEXT_INLINE && HAVE_6REGS */ -#endif /* HAVE_INLINE_ASM */ +//SSSE3 versions +#undef RENAME +#undef COMPILE_TEMPLATE_MMXEXT +#define COMPILE_TEMPLATE_MMXEXT 0 +#define RENAME(a) a ## _ssse3 +#include "yuv2rgb_template.c" + +#endif /* HAVE_X86ASM */ av_cold SwsFunc ff_yuv2rgb_init_x86(SwsContext *c) { -#if HAVE_MMX_INLINE && HAVE_6REGS +#if HAVE_X86ASM int cpu_flags = av_get_cpu_flags(); -#if HAVE_MMXEXT_INLINE - if (INLINE_MMXEXT(cpu_flags)) { + if (EXTERNAL_SSSE3(cpu_flags)) { + switch (c->dstFormat) { + case AV_PIX_FMT_RGB32: + if (c->srcFormat == AV_PIX_FMT_YUVA420P) { +#if CONFIG_SWSCALE_ALPHA + return yuva420_rgb32_ssse3; +#endif + break; + } else + return yuv420_rgb32_ssse3; + case AV_PIX_FMT_BGR32: + if (c->srcFormat == AV_PIX_FMT_YUVA420P) { +#if CONFIG_SWSCALE_ALPHA + return yuva420_bgr32_ssse3; +#endif + break; + } else + return yuv420_bgr32_ssse3; + case AV_PIX_FMT_RGB24: + return yuv420_rgb24_ssse3; + case AV_PIX_FMT_BGR24: + return yuv420_bgr24_ssse3; + case AV_PIX_FMT_RGB565: + return yuv420_rgb16_ssse3; + case AV_PIX_FMT_RGB555: + return yuv420_rgb15_ssse3; + } + } + + if (EXTERNAL_MMXEXT(cpu_flags)) { switch (c->dstFormat) { case AV_PIX_FMT_RGB24: return yuv420_rgb24_mmxext; @@ -83,13 +108,12 @@ return yuv420_bgr24_mmxext; } } -#endif - if (INLINE_MMX(cpu_flags)) { + if (EXTERNAL_MMX(cpu_flags)) { switch (c->dstFormat) { case AV_PIX_FMT_RGB32: if (c->srcFormat == AV_PIX_FMT_YUVA420P) { -#if HAVE_7REGS && CONFIG_SWSCALE_ALPHA +#if CONFIG_SWSCALE_ALPHA return yuva420_rgb32_mmx; #endif break; @@ -97,7 +121,7 @@ return yuv420_rgb32_mmx; case AV_PIX_FMT_BGR32: if (c->srcFormat == AV_PIX_FMT_YUVA420P) { -#if HAVE_7REGS && CONFIG_SWSCALE_ALPHA +#if CONFIG_SWSCALE_ALPHA return yuva420_bgr32_mmx; #endif break; @@ -113,7 +137,7 @@ return yuv420_rgb15_mmx; } } -#endif /* HAVE_MMX_INLINE && HAVE_6REGS */ +#endif /* HAVE_X86ASM */ return NULL; } diff -Nru ffmpeg-4.2.2/libswscale/x86/yuv2rgb_template.c ffmpeg-4.4/libswscale/x86/yuv2rgb_template.c --- ffmpeg-4.2.2/libswscale/x86/yuv2rgb_template.c 2016-03-29 02:25:33.000000000 +0000 +++ ffmpeg-4.4/libswscale/x86/yuv2rgb_template.c 2020-07-11 10:39:30.000000000 +0000 @@ -26,23 +26,6 @@ #include "libavutil/x86/asm.h" #include "libswscale/swscale_internal.h" -#undef MOVNTQ -#undef EMMS -#undef SFENCE - -#if COMPILE_TEMPLATE_MMXEXT -#define MOVNTQ "movntq" -#define SFENCE "sfence" -#else -#define MOVNTQ "movq" -#define SFENCE " # nop" -#endif - -#define REG_BLUE "0" -#define REG_RED "1" -#define REG_GREEN "2" -#define REG_ALPHA "3" - #define YUV2RGB_LOOP(depth) \ h_size = (c->dstW + 7) & ~7; \ if (h_size * depth > FFABS(dstStride[0])) \ @@ -50,7 +33,6 @@ \ vshift = c->srcFormat != AV_PIX_FMT_YUV422P; \ \ - __asm__ volatile ("pxor %mm4, %mm4\n\t"); \ for (y = 0; y < srcSliceH; y++) { \ uint8_t *image = dst[0] + (y + srcSliceY) * dstStride[0]; \ const uint8_t *py = src[0] + y * srcStride[0]; \ @@ -58,146 +40,33 @@ const uint8_t *pv = src[2] + (y >> vshift) * srcStride[2]; \ x86_reg index = -h_size / 2; \ -#define YUV2RGB_INITIAL_LOAD \ - __asm__ volatile ( \ - "movq (%5, %0, 2), %%mm6\n\t" \ - "movd (%2, %0), %%mm0\n\t" \ - "movd (%3, %0), %%mm1\n\t" \ - "1: \n\t" \ - -/* YUV2RGB core - * Conversion is performed in usual way: - * R = Y' * Ycoef + Vred * V' - * G = Y' * Ycoef + Vgreen * V' + Ugreen * U' - * B = Y' * Ycoef + Ublue * U' - * - * where X' = X * 8 - Xoffset (multiplication is performed to increase - * precision a bit). - * Since it operates in YUV420 colorspace, Y component is additionally - * split into Y1 and Y2 for even and odd pixels. - * - * Input: - * mm0 - U (4 elems), mm1 - V (4 elems), mm6 - Y (8 elems), mm4 - zero register - * Output: - * mm1 - R, mm2 - G, mm0 - B - */ -#define YUV2RGB \ - /* convert Y, U, V into Y1', Y2', U', V' */ \ - "movq %%mm6, %%mm7\n\t" \ - "punpcklbw %%mm4, %%mm0\n\t" \ - "punpcklbw %%mm4, %%mm1\n\t" \ - "pand "MANGLE(mmx_00ffw)", %%mm6\n\t" \ - "psrlw $8, %%mm7\n\t" \ - "psllw $3, %%mm0\n\t" \ - "psllw $3, %%mm1\n\t" \ - "psllw $3, %%mm6\n\t" \ - "psllw $3, %%mm7\n\t" \ - "psubsw "U_OFFSET"(%4), %%mm0\n\t" \ - "psubsw "V_OFFSET"(%4), %%mm1\n\t" \ - "psubw "Y_OFFSET"(%4), %%mm6\n\t" \ - "psubw "Y_OFFSET"(%4), %%mm7\n\t" \ -\ - /* multiply by coefficients */ \ - "movq %%mm0, %%mm2\n\t" \ - "movq %%mm1, %%mm3\n\t" \ - "pmulhw "UG_COEFF"(%4), %%mm2\n\t" \ - "pmulhw "VG_COEFF"(%4), %%mm3\n\t" \ - "pmulhw "Y_COEFF" (%4), %%mm6\n\t" \ - "pmulhw "Y_COEFF" (%4), %%mm7\n\t" \ - "pmulhw "UB_COEFF"(%4), %%mm0\n\t" \ - "pmulhw "VR_COEFF"(%4), %%mm1\n\t" \ - "paddsw %%mm3, %%mm2\n\t" \ - /* now: mm0 = UB, mm1 = VR, mm2 = CG */ \ - /* mm6 = Y1, mm7 = Y2 */ \ -\ - /* produce RGB */ \ - "movq %%mm7, %%mm3\n\t" \ - "movq %%mm7, %%mm5\n\t" \ - "paddsw %%mm0, %%mm3\n\t" \ - "paddsw %%mm1, %%mm5\n\t" \ - "paddsw %%mm2, %%mm7\n\t" \ - "paddsw %%mm6, %%mm0\n\t" \ - "paddsw %%mm6, %%mm1\n\t" \ - "paddsw %%mm6, %%mm2\n\t" \ - -#define RGB_PACK_INTERLEAVE \ - /* pack and interleave even/odd pixels */ \ - "packuswb %%mm1, %%mm0\n\t" \ - "packuswb %%mm5, %%mm3\n\t" \ - "packuswb %%mm2, %%mm2\n\t" \ - "movq %%mm0, %%mm1\n\n" \ - "packuswb %%mm7, %%mm7\n\t" \ - "punpcklbw %%mm3, %%mm0\n\t" \ - "punpckhbw %%mm3, %%mm1\n\t" \ - "punpcklbw %%mm7, %%mm2\n\t" \ - -#define YUV2RGB_ENDLOOP(depth) \ - "movq 8 (%5, %0, 2), %%mm6\n\t" \ - "movd 4 (%3, %0), %%mm1\n\t" \ - "movd 4 (%2, %0), %%mm0\n\t" \ - "add $"AV_STRINGIFY(depth * 8)", %1\n\t" \ - "add $4, %0\n\t" \ - "js 1b\n\t" \ - -#if COMPILE_TEMPLATE_MMXEXT -#undef RGB_PACK24_B_OPERANDS -#define RGB_PACK24_B_OPERANDS NAMED_CONSTRAINTS_ARRAY_ADD(mask1101,mask0110,mask0100,mask0010,mask1001) -#else -#undef RGB_PACK24_B_OPERANDS -#define RGB_PACK24_B_OPERANDS -#endif - -#define YUV2RGB_OPERANDS \ - : "+r" (index), "+r" (image) \ - : "r" (pu - index), "r" (pv - index), "r"(&c->redDither), \ - "r" (py - 2*index) \ - NAMED_CONSTRAINTS_ADD(mmx_00ffw,pb_03,pb_07,mmx_redmask,pb_e0) \ - RGB_PACK24_B_OPERANDS \ - : "memory" \ - ); \ - } \ - -#define YUV2RGB_OPERANDS_ALPHA \ - : "+r" (index), "+r" (image) \ - : "r" (pu - index), "r" (pv - index), "r"(&c->redDither), \ - "r" (py - 2*index), "r" (pa - 2*index) \ - NAMED_CONSTRAINTS_ADD(mmx_00ffw) \ - : "memory" \ - ); \ - } \ - -#define YUV2RGB_ENDFUNC \ - __asm__ volatile (SFENCE"\n\t" \ - "emms \n\t"); \ - return srcSliceH; \ - -#define IF0(x) -#define IF1(x) x - -#define RGB_PACK16(gmask, is15) \ - "pand "MANGLE(mmx_redmask)", %%mm0\n\t" \ - "pand "MANGLE(mmx_redmask)", %%mm1\n\t" \ - "movq %%mm2, %%mm3\n\t" \ - "psllw $"AV_STRINGIFY(3-is15)", %%mm2\n\t" \ - "psrlw $"AV_STRINGIFY(5+is15)", %%mm3\n\t" \ - "psrlw $3, %%mm0\n\t" \ - IF##is15("psrlw $1, %%mm1\n\t") \ - "pand "MANGLE(pb_e0)", %%mm2\n\t" \ - "pand "MANGLE(gmask)", %%mm3\n\t" \ - "por %%mm2, %%mm0\n\t" \ - "por %%mm3, %%mm1\n\t" \ - "movq %%mm0, %%mm2\n\t" \ - "punpcklbw %%mm1, %%mm0\n\t" \ - "punpckhbw %%mm1, %%mm2\n\t" \ - MOVNTQ " %%mm0, (%1)\n\t" \ - MOVNTQ " %%mm2, 8(%1)\n\t" \ - -#define DITHER_RGB \ - "paddusb "BLUE_DITHER"(%4), %%mm0\n\t" \ - "paddusb "GREEN_DITHER"(%4), %%mm2\n\t" \ - "paddusb "RED_DITHER"(%4), %%mm1\n\t" \ +extern void RENAME(ff_yuv_420_rgb24)(x86_reg index, uint8_t *image, const uint8_t *pu_index, + const uint8_t *pv_index, const uint64_t *pointer_c_dither, + const uint8_t *py_2index); +extern void RENAME(ff_yuv_420_bgr24)(x86_reg index, uint8_t *image, const uint8_t *pu_index, + const uint8_t *pv_index, const uint64_t *pointer_c_dither, + const uint8_t *py_2index); #if !COMPILE_TEMPLATE_MMXEXT +extern void RENAME(ff_yuv_420_rgb15)(x86_reg index, uint8_t *image, const uint8_t *pu_index, + const uint8_t *pv_index, const uint64_t *pointer_c_dither, + const uint8_t *py_2index); +extern void RENAME(ff_yuv_420_rgb16)(x86_reg index, uint8_t *image, const uint8_t *pu_index, + const uint8_t *pv_index, const uint64_t *pointer_c_dither, + const uint8_t *py_2index); +extern void RENAME(ff_yuv_420_rgb32)(x86_reg index, uint8_t *image, const uint8_t *pu_index, + const uint8_t *pv_index, const uint64_t *pointer_c_dither, + const uint8_t *py_2index); +extern void RENAME(ff_yuv_420_bgr32)(x86_reg index, uint8_t *image, const uint8_t *pu_index, + const uint8_t *pv_index, const uint64_t *pointer_c_dither, + const uint8_t *py_2index); +extern void RENAME(ff_yuva_420_rgb32)(x86_reg index, uint8_t *image, const uint8_t *pu_index, + const uint8_t *pv_index, const uint64_t *pointer_c_dither, + const uint8_t *py_2index, const uint8_t *pa_2index); +extern void RENAME(ff_yuva_420_bgr32)(x86_reg index, uint8_t *image, const uint8_t *pu_index, + const uint8_t *pv_index, const uint64_t *pointer_c_dither, + const uint8_t *py_2index, const uint8_t *pa_2index); + static inline int RENAME(yuv420_rgb15)(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, @@ -213,17 +82,9 @@ c->redDither = ff_dither8[(y + 1) & 1]; #endif - YUV2RGB_INITIAL_LOAD - YUV2RGB - RGB_PACK_INTERLEAVE -#ifdef DITHER1XBPP - DITHER_RGB -#endif - RGB_PACK16(pb_03, 1) - - YUV2RGB_ENDLOOP(2) - YUV2RGB_OPERANDS - YUV2RGB_ENDFUNC + RENAME(ff_yuv_420_rgb15)(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index); + } + return srcSliceH; } static inline int RENAME(yuv420_rgb16)(SwsContext *c, const uint8_t *src[], @@ -241,165 +102,54 @@ c->redDither = ff_dither8[(y + 1) & 1]; #endif - YUV2RGB_INITIAL_LOAD - YUV2RGB - RGB_PACK_INTERLEAVE -#ifdef DITHER1XBPP - DITHER_RGB -#endif - RGB_PACK16(pb_07, 0) - - YUV2RGB_ENDLOOP(2) - YUV2RGB_OPERANDS - YUV2RGB_ENDFUNC + RENAME(ff_yuv_420_rgb16)(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index); + } + return srcSliceH; } -#endif /* !COMPILE_TEMPLATE_MMXEXT */ - -#define RGB_PACK24(blue, red)\ - "packuswb %%mm3, %%mm0 \n" /* R0 R2 R4 R6 R1 R3 R5 R7 */\ - "packuswb %%mm5, %%mm1 \n" /* B0 B2 B4 B6 B1 B3 B5 B7 */\ - "packuswb %%mm7, %%mm2 \n" /* G0 G2 G4 G6 G1 G3 G5 G7 */\ - "movq %%mm"red", %%mm3 \n"\ - "movq %%mm"blue", %%mm6 \n"\ - "psrlq $32, %%mm"red" \n" /* R1 R3 R5 R7 */\ - "punpcklbw %%mm2, %%mm3 \n" /* R0 G0 R2 G2 R4 G4 R6 G6 */\ - "punpcklbw %%mm"red", %%mm6 \n" /* B0 R1 B2 R3 B4 R5 B6 R7 */\ - "movq %%mm3, %%mm5 \n"\ - "punpckhbw %%mm"blue", %%mm2 \n" /* G1 B1 G3 B3 G5 B5 G7 B7 */\ - "punpcklwd %%mm6, %%mm3 \n" /* R0 G0 B0 R1 R2 G2 B2 R3 */\ - "punpckhwd %%mm6, %%mm5 \n" /* R4 G4 B4 R5 R6 G6 B6 R7 */\ - RGB_PACK24_B - -#if COMPILE_TEMPLATE_MMXEXT -DECLARE_ASM_CONST(8, int16_t, mask1101[4]) = {-1,-1, 0,-1}; -DECLARE_ASM_CONST(8, int16_t, mask0010[4]) = { 0, 0,-1, 0}; -DECLARE_ASM_CONST(8, int16_t, mask0110[4]) = { 0,-1,-1, 0}; -DECLARE_ASM_CONST(8, int16_t, mask1001[4]) = {-1, 0, 0,-1}; -DECLARE_ASM_CONST(8, int16_t, mask0100[4]) = { 0,-1, 0, 0}; -#undef RGB_PACK24_B -#define RGB_PACK24_B\ - "pshufw $0xc6, %%mm2, %%mm1 \n"\ - "pshufw $0x84, %%mm3, %%mm6 \n"\ - "pshufw $0x38, %%mm5, %%mm7 \n"\ - "pand "MANGLE(mask1101)", %%mm6 \n" /* R0 G0 B0 R1 -- -- R2 G2 */\ - "movq %%mm1, %%mm0 \n"\ - "pand "MANGLE(mask0110)", %%mm7 \n" /* -- -- R6 G6 B6 R7 -- -- */\ - "movq %%mm1, %%mm2 \n"\ - "pand "MANGLE(mask0100)", %%mm1 \n" /* -- -- G3 B3 -- -- -- -- */\ - "psrlq $48, %%mm3 \n" /* B2 R3 -- -- -- -- -- -- */\ - "pand "MANGLE(mask0010)", %%mm0 \n" /* -- -- -- -- G1 B1 -- -- */\ - "psllq $32, %%mm5 \n" /* -- -- -- -- R4 G4 B4 R5 */\ - "pand "MANGLE(mask1001)", %%mm2 \n" /* G5 B5 -- -- -- -- G7 B7 */\ - "por %%mm3, %%mm1 \n"\ - "por %%mm6, %%mm0 \n"\ - "por %%mm5, %%mm1 \n"\ - "por %%mm7, %%mm2 \n"\ - MOVNTQ" %%mm0, (%1) \n"\ - MOVNTQ" %%mm1, 8(%1) \n"\ - MOVNTQ" %%mm2, 16(%1) \n"\ - -#else -#undef RGB_PACK24_B -#define RGB_PACK24_B\ - "movd %%mm3, (%1) \n" /* R0 G0 B0 R1 */\ - "movd %%mm2, 4(%1) \n" /* G1 B1 */\ - "psrlq $32, %%mm3 \n"\ - "psrlq $16, %%mm2 \n"\ - "movd %%mm3, 6(%1) \n" /* R2 G2 B2 R3 */\ - "movd %%mm2, 10(%1) \n" /* G3 B3 */\ - "psrlq $16, %%mm2 \n"\ - "movd %%mm5, 12(%1) \n" /* R4 G4 B4 R5 */\ - "movd %%mm2, 16(%1) \n" /* G5 B5 */\ - "psrlq $32, %%mm5 \n"\ - "movd %%mm2, 20(%1) \n" /* -- -- G7 B7 */\ - "movd %%mm5, 18(%1) \n" /* R6 G6 B6 R7 */\ - -#endif -static inline int RENAME(yuv420_rgb24)(SwsContext *c, const uint8_t *src[], +static inline int RENAME(yuv420_rgb32)(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]) { int y, h_size, vshift; - YUV2RGB_LOOP(3) + YUV2RGB_LOOP(4) - YUV2RGB_INITIAL_LOAD - YUV2RGB - RGB_PACK24(REG_BLUE, REG_RED) - - YUV2RGB_ENDLOOP(3) - YUV2RGB_OPERANDS - YUV2RGB_ENDFUNC + RENAME(ff_yuv_420_rgb32)(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index); + } + return srcSliceH; } -static inline int RENAME(yuv420_bgr24)(SwsContext *c, const uint8_t *src[], +static inline int RENAME(yuv420_bgr32)(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]) { int y, h_size, vshift; - YUV2RGB_LOOP(3) + YUV2RGB_LOOP(4) - YUV2RGB_INITIAL_LOAD - YUV2RGB - RGB_PACK24(REG_RED, REG_BLUE) - - YUV2RGB_ENDLOOP(3) - YUV2RGB_OPERANDS - YUV2RGB_ENDFUNC + RENAME(ff_yuv_420_bgr32)(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index); + } + return srcSliceH; } - -#define SET_EMPTY_ALPHA \ - "pcmpeqd %%mm"REG_ALPHA", %%mm"REG_ALPHA"\n\t" /* set alpha to 0xFF */ \ - -#define LOAD_ALPHA \ - "movq (%6, %0, 2), %%mm"REG_ALPHA"\n\t" \ - -#define RGB_PACK32(red, green, blue, alpha) \ - "movq %%mm"blue", %%mm5\n\t" \ - "movq %%mm"red", %%mm6\n\t" \ - "punpckhbw %%mm"green", %%mm5\n\t" \ - "punpcklbw %%mm"green", %%mm"blue"\n\t" \ - "punpckhbw %%mm"alpha", %%mm6\n\t" \ - "punpcklbw %%mm"alpha", %%mm"red"\n\t" \ - "movq %%mm"blue", %%mm"green"\n\t" \ - "movq %%mm5, %%mm"alpha"\n\t" \ - "punpcklwd %%mm"red", %%mm"blue"\n\t" \ - "punpckhwd %%mm"red", %%mm"green"\n\t" \ - "punpcklwd %%mm6, %%mm5\n\t" \ - "punpckhwd %%mm6, %%mm"alpha"\n\t" \ - MOVNTQ " %%mm"blue", 0(%1)\n\t" \ - MOVNTQ " %%mm"green", 8(%1)\n\t" \ - MOVNTQ " %%mm5, 16(%1)\n\t" \ - MOVNTQ " %%mm"alpha", 24(%1)\n\t" \ - -#if !COMPILE_TEMPLATE_MMXEXT -static inline int RENAME(yuv420_rgb32)(SwsContext *c, const uint8_t *src[], +static inline int RENAME(yuva420_rgb32)(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]) { int y, h_size, vshift; - YUV2RGB_LOOP(4) - YUV2RGB_INITIAL_LOAD - YUV2RGB - RGB_PACK_INTERLEAVE - SET_EMPTY_ALPHA - RGB_PACK32(REG_RED, REG_GREEN, REG_BLUE, REG_ALPHA) - - YUV2RGB_ENDLOOP(4) - YUV2RGB_OPERANDS - YUV2RGB_ENDFUNC + const uint8_t *pa = src[3] + y * srcStride[3]; + RENAME(ff_yuva_420_rgb32)(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index, pa - 2 * index); + } + return srcSliceH; } -#if HAVE_7REGS && CONFIG_SWSCALE_ALPHA -static inline int RENAME(yuva420_rgb32)(SwsContext *c, const uint8_t *src[], +static inline int RENAME(yuva420_bgr32)(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]) @@ -409,59 +159,37 @@ YUV2RGB_LOOP(4) const uint8_t *pa = src[3] + y * srcStride[3]; - YUV2RGB_INITIAL_LOAD - YUV2RGB - RGB_PACK_INTERLEAVE - LOAD_ALPHA - RGB_PACK32(REG_RED, REG_GREEN, REG_BLUE, REG_ALPHA) - - YUV2RGB_ENDLOOP(4) - YUV2RGB_OPERANDS_ALPHA - YUV2RGB_ENDFUNC + RENAME(ff_yuva_420_bgr32)(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index, pa - 2 * index); + } + return srcSliceH; } #endif -static inline int RENAME(yuv420_bgr32)(SwsContext *c, const uint8_t *src[], +static inline int RENAME(yuv420_rgb24)(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]) { int y, h_size, vshift; - YUV2RGB_LOOP(4) + YUV2RGB_LOOP(3) - YUV2RGB_INITIAL_LOAD - YUV2RGB - RGB_PACK_INTERLEAVE - SET_EMPTY_ALPHA - RGB_PACK32(REG_BLUE, REG_GREEN, REG_RED, REG_ALPHA) - - YUV2RGB_ENDLOOP(4) - YUV2RGB_OPERANDS - YUV2RGB_ENDFUNC + RENAME(ff_yuv_420_rgb24)(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index); + } + return srcSliceH; } -#if HAVE_7REGS && CONFIG_SWSCALE_ALPHA -static inline int RENAME(yuva420_bgr32)(SwsContext *c, const uint8_t *src[], +static inline int RENAME(yuv420_bgr24)(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[]) { int y, h_size, vshift; - YUV2RGB_LOOP(4) + YUV2RGB_LOOP(3) - const uint8_t *pa = src[3] + y * srcStride[3]; - YUV2RGB_INITIAL_LOAD - YUV2RGB - RGB_PACK_INTERLEAVE - LOAD_ALPHA - RGB_PACK32(REG_BLUE, REG_GREEN, REG_RED, REG_ALPHA) - - YUV2RGB_ENDLOOP(4) - YUV2RGB_OPERANDS_ALPHA - YUV2RGB_ENDFUNC + RENAME(ff_yuv_420_bgr24)(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index); + } + return srcSliceH; } -#endif -#endif /* !COMPILE_TEMPLATE_MMXEXT */ diff -Nru ffmpeg-4.2.2/libswscale/x86/yuv2yuvX.asm ffmpeg-4.4/libswscale/x86/yuv2yuvX.asm --- ffmpeg-4.2.2/libswscale/x86/yuv2yuvX.asm 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/libswscale/x86/yuv2yuvX.asm 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,136 @@ +;****************************************************************************** +;* x86-optimized yuv2yuvX +;* Copyright 2020 Google LLC +;* Copyright (C) 2001-2011 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 "libavutil/x86/x86util.asm" + +SECTION .text + +;----------------------------------------------------------------------------- +; yuv2yuvX +; +; void ff_yuv2yuvX_(const int16_t *filter, int filterSize, +; int srcOffset, uint8_t *dest, int dstW, +; const uint8_t *dither, int offset); +; +;----------------------------------------------------------------------------- + +%macro YUV2YUVX_FUNC 0 +cglobal yuv2yuvX, 7, 7, 8, filter, filterSize, src, dest, dstW, dither, offset +%if notcpuflag(sse3) +%define movr mova +%define unroll 1 +%else +%define movr movdqu +%define unroll 2 +%endif + movsxdifnidn dstWq, dstWd + movsxdifnidn offsetq, offsetd + movsxdifnidn srcq, srcd +%if cpuflag(avx2) + vpbroadcastq m3, [ditherq] +%else + movq xm3, [ditherq] +%endif ; avx2 + cmp offsetd, 0 + jz .offset + + ; offset != 0 path. + psrlq m5, m3, $18 + psllq m3, m3, $28 + por m3, m3, m5 + +.offset: + add offsetq, srcq + movd xm1, filterSized + SPLATW m1, xm1, 0 + pxor m0, m0, m0 + mov filterSizeq, filterq + mov srcq, [filterSizeq] + punpcklbw m3, m0 + psllw m1, m1, 3 + paddw m3, m3, m1 + psraw m7, m3, 4 +.outerloop: + mova m4, m7 + mova m3, m7 +%if cpuflag(sse3) + mova m6, m7 + mova m1, m7 +%endif +.loop: +%if cpuflag(avx2) + vpbroadcastq m0, [filterSizeq + 8] +%elif cpuflag(sse3) + movddup m0, [filterSizeq + 8] +%else + mova m0, [filterSizeq + 8] +%endif + pmulhw m2, m0, [srcq + offsetq * 2] + pmulhw m5, m0, [srcq + offsetq * 2 + mmsize] + paddw m3, m3, m2 + paddw m4, m4, m5 +%if cpuflag(sse3) + pmulhw m2, m0, [srcq + offsetq * 2 + 2 * mmsize] + pmulhw m5, m0, [srcq + offsetq * 2 + 3 * mmsize] + paddw m6, m6, m2 + paddw m1, m1, m5 +%endif + add filterSizeq, $10 + mov srcq, [filterSizeq] + test srcq, srcq + jnz .loop + psraw m3, m3, 3 + psraw m4, m4, 3 +%if cpuflag(sse3) + psraw m6, m6, 3 + psraw m1, m1, 3 +%endif + packuswb m3, m3, m4 +%if cpuflag(sse3) + packuswb m6, m6, m1 +%endif + mov srcq, [filterq] +%if cpuflag(avx2) + vpermq m3, m3, 216 + vpermq m6, m6, 216 +%endif + movr [destq + offsetq], m3 +%if cpuflag(sse3) + movr [destq + offsetq + mmsize], m6 +%endif + add offsetq, mmsize * unroll + mov filterSizeq, filterq + cmp offsetq, dstWq + jb .outerloop + REP_RET +%endmacro + +INIT_MMX mmx +YUV2YUVX_FUNC +INIT_MMX mmxext +YUV2YUVX_FUNC +INIT_XMM sse3 +YUV2YUVX_FUNC +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +YUV2YUVX_FUNC +%endif diff -Nru ffmpeg-4.2.2/libswscale/yuv2rgb.c ffmpeg-4.4/libswscale/yuv2rgb.c --- ffmpeg-4.2.2/libswscale/yuv2rgb.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/libswscale/yuv2rgb.c 2021-04-08 21:28:40.000000000 +0000 @@ -138,10 +138,11 @@ srcStride[2] *= 2; \ } \ for (y = 0; y < srcSliceH; y += 2) { \ + int yd = y + srcSliceY; \ dst_type *dst_1 = \ - (dst_type *)(dst[0] + (y + srcSliceY) * dstStride[0]); \ + (dst_type *)(dst[0] + (yd) * dstStride[0]); \ dst_type *dst_2 = \ - (dst_type *)(dst[0] + (y + srcSliceY + 1) * dstStride[0]); \ + (dst_type *)(dst[0] + (yd + 1) * dstStride[0]); \ 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]; \ @@ -498,8 +499,8 @@ // r, g, b, dst_1, dst_2 YUV2RGBFUNC(yuv2rgb_c_8_ordered_dither, uint8_t, 0) - const uint8_t *d32 = ff_dither_8x8_32[y & 7]; - const uint8_t *d64 = ff_dither_8x8_73[y & 7]; + const uint8_t *d32 = ff_dither_8x8_32[yd & 7]; + const uint8_t *d64 = ff_dither_8x8_73[yd & 7]; #define PUTRGB8(dst, src, i, o) \ Y = src[2 * i]; \ @@ -528,8 +529,8 @@ PUTRGB8(dst_1, py_1, 3, 6); ENDYUV2RGBLINE(8, 0) - const uint8_t *d32 = ff_dither_8x8_32[y & 7]; - const uint8_t *d64 = ff_dither_8x8_73[y & 7]; + const uint8_t *d32 = ff_dither_8x8_32[yd & 7]; + const uint8_t *d64 = ff_dither_8x8_73[yd & 7]; LOADCHROMA(0); PUTRGB8(dst_1, py_1, 0, 0); PUTRGB8(dst_2, py_2, 0, 0 + 8); @@ -539,8 +540,8 @@ PUTRGB8(dst_1, py_1, 1, 2); ENDYUV2RGBLINE(8, 1) - const uint8_t *d32 = ff_dither_8x8_32[y & 7]; - const uint8_t *d64 = ff_dither_8x8_73[y & 7]; + const uint8_t *d32 = ff_dither_8x8_32[yd & 7]; + const uint8_t *d64 = ff_dither_8x8_73[yd & 7]; LOADCHROMA(0); PUTRGB8(dst_1, py_1, 0, 0); PUTRGB8(dst_2, py_2, 0, 0 + 8); @@ -549,8 +550,8 @@ YUV2RGBFUNC(yuv2rgb_c_4_ordered_dither, uint8_t, 0) - const uint8_t * d64 = ff_dither_8x8_73[y & 7]; - const uint8_t *d128 = ff_dither_8x8_220[y & 7]; + const uint8_t * d64 = ff_dither_8x8_73[yd & 7]; + const uint8_t *d128 = ff_dither_8x8_220[yd & 7]; int acc; #define PUTRGB4D(dst, src, i, o) \ @@ -581,8 +582,8 @@ PUTRGB4D(dst_1, py_1, 3, 6); ENDYUV2RGBLINE(4, 0) - const uint8_t * d64 = ff_dither_8x8_73[y & 7]; - const uint8_t *d128 = ff_dither_8x8_220[y & 7]; + const uint8_t * d64 = ff_dither_8x8_73[yd & 7]; + const uint8_t *d128 = ff_dither_8x8_220[yd & 7]; int acc; LOADCHROMA(0); PUTRGB4D(dst_1, py_1, 0, 0); @@ -593,8 +594,8 @@ PUTRGB4D(dst_1, py_1, 1, 2); ENDYUV2RGBLINE(4, 1) - const uint8_t * d64 = ff_dither_8x8_73[y & 7]; - const uint8_t *d128 = ff_dither_8x8_220[y & 7]; + const uint8_t * d64 = ff_dither_8x8_73[yd & 7]; + const uint8_t *d128 = ff_dither_8x8_220[yd & 7]; int acc; LOADCHROMA(0); PUTRGB4D(dst_1, py_1, 0, 0); @@ -602,8 +603,8 @@ ENDYUV2RGBFUNC() YUV2RGBFUNC(yuv2rgb_c_4b_ordered_dither, uint8_t, 0) - const uint8_t *d64 = ff_dither_8x8_73[y & 7]; - const uint8_t *d128 = ff_dither_8x8_220[y & 7]; + const uint8_t *d64 = ff_dither_8x8_73[yd & 7]; + const uint8_t *d128 = ff_dither_8x8_220[yd & 7]; #define PUTRGB4DB(dst, src, i, o) \ Y = src[2 * i]; \ @@ -631,8 +632,8 @@ PUTRGB4DB(dst_2, py_2, 3, 6 + 8); PUTRGB4DB(dst_1, py_1, 3, 6); ENDYUV2RGBLINE(8, 0) - const uint8_t *d64 = ff_dither_8x8_73[y & 7]; - const uint8_t *d128 = ff_dither_8x8_220[y & 7]; + const uint8_t *d64 = ff_dither_8x8_73[yd & 7]; + const uint8_t *d128 = ff_dither_8x8_220[yd & 7]; LOADCHROMA(0); PUTRGB4DB(dst_1, py_1, 0, 0); PUTRGB4DB(dst_2, py_2, 0, 0 + 8); @@ -641,15 +642,15 @@ PUTRGB4DB(dst_2, py_2, 1, 2 + 8); PUTRGB4DB(dst_1, py_1, 1, 2); ENDYUV2RGBLINE(8, 1) - const uint8_t *d64 = ff_dither_8x8_73[y & 7]; - const uint8_t *d128 = ff_dither_8x8_220[y & 7]; + const uint8_t *d64 = ff_dither_8x8_73[yd & 7]; + const uint8_t *d128 = ff_dither_8x8_220[yd & 7]; LOADCHROMA(0); PUTRGB4DB(dst_1, py_1, 0, 0); PUTRGB4DB(dst_2, py_2, 0, 0 + 8); ENDYUV2RGBFUNC() YUV2RGBFUNC(yuv2rgb_c_1_ordered_dither, uint8_t, 0) - const uint8_t *d128 = ff_dither_8x8_220[y & 7]; + const uint8_t *d128 = ff_dither_8x8_220[yd & 7]; char out_1 = 0, out_2 = 0; g = c->table_gU[128 + YUVRGB_TABLE_HEADROOM] + c->table_gV[128 + YUVRGB_TABLE_HEADROOM]; @@ -792,7 +793,8 @@ c->dstFormat == AV_PIX_FMT_NE(RGB444LE, RGB444BE) || c->dstFormat == AV_PIX_FMT_NE(BGR565LE, BGR565BE) || c->dstFormat == AV_PIX_FMT_NE(BGR555LE, BGR555BE) || - c->dstFormat == AV_PIX_FMT_NE(BGR444LE, BGR444BE); + c->dstFormat == AV_PIX_FMT_NE(BGR444LE, BGR444BE) || + c->dstFormat == AV_PIX_FMT_NE(X2RGB10LE, X2RGB10BE); const int bpp = c->dstFormatBpp; uint8_t *y_table; uint16_t *y_table16; @@ -964,6 +966,32 @@ fill_table(c->table_bU, 1, cbu, y_table + yoffs); fill_gv_table(c->table_gV, 1, cgv); break; + case 30: + rbase = 20; + gbase = 10; + bbase = 0; + needAlpha = CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat); + if (!needAlpha) + abase = 30; + ALLOC_YUV_TABLE(table_plane_size * 3 * 4); + y_table32 = c->yuvTable; + yb = -(384 << 16) - YUVRGB_TABLE_LUMA_HEADROOM*cy - oy; + for (i = 0; i < table_plane_size; i++) { + unsigned yval = av_clip_uint8((yb + 0x8000) >> 16); + y_table32[i]= (yval << rbase) + (needAlpha ? 0 : (255u << abase)); + y_table32[i + table_plane_size] = yval << gbase; + y_table32[i + 2 * table_plane_size] = yval << bbase; + yb += cy; + } + if (isNotNe) { + for (i = 0; i < table_plane_size * 3; i++) + y_table32[i] = av_bswap32(y_table32[i]); + } + fill_table(c->table_rV, 4, crv, y_table32 + yoffs); + fill_table(c->table_gU, 4, cgu, y_table32 + yoffs + table_plane_size); + fill_table(c->table_bU, 4, cbu, y_table32 + yoffs + 2 * table_plane_size); + fill_gv_table(c->table_gV, 4, cgv); + break; case 32: case 64: base = (c->dstFormat == AV_PIX_FMT_RGB32_1 || diff -Nru ffmpeg-4.2.2/LICENSE.md ffmpeg-4.4/LICENSE.md --- ffmpeg-4.2.2/LICENSE.md 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/LICENSE.md 2020-07-11 10:39:30.000000000 +0000 @@ -21,10 +21,11 @@ - `compat/solaris/make_sunver.pl` - `doc/t2h.pm` - `doc/texi2pod.pl` - - `libswresample/swresample-test.c` + - `libswresample/tests/swresample.c` - `tests/checkasm/*` - `tests/tiny_ssim.c` - the following filters in libavfilter: + - `signature_lookup.c` - `vf_blackframe.c` - `vf_boxblur.c` - `vf_colormatrix.c` @@ -34,13 +35,13 @@ - `vf_eq.c` - `vf_find_rect.c` - `vf_fspp.c` - - `vf_geq.c` - `vf_histeq.c` - `vf_hqdn3d.c` - - `vf_interlace.c` - `vf_kerndeint.c` + - `vf_lensfun.c` (GPL version 3 or later) - `vf_mcdeint.c` - `vf_mpdecimate.c` + - `vf_nnedi.c` - `vf_owdenoise.c` - `vf_perspective.c` - `vf_phase.c` @@ -49,12 +50,14 @@ - `vf_pullup.c` - `vf_repeatfields.c` - `vf_sab.c` + - `vf_signature.c` - `vf_smartblur.c` - `vf_spp.c` - `vf_stereo3d.c` - `vf_super2xsai.c` - `vf_tinterlace.c` - `vf_uspp.c` + - `vf_vaguedenoiser.c` - `vsrc_mptestsrc.c` Should you, for whatever reason, prefer to use version 3 of the (L)GPL, then @@ -80,24 +83,39 @@ ### Compatible libraries -The following libraries are under GPL: +The following libraries are under GPL version 2: +- avisynth - frei0r - libcdio +- libdavs2 - librubberband - libvidstab - libx264 - libx265 - libxavs +- libxavs2 - libxvid When combining them with FFmpeg, FFmpeg needs to be licensed as GPL as well by passing `--enable-gpl` to configure. -The OpenCORE and VisualOn libraries are under the Apache License 2.0. That -license is incompatible with the LGPL v2.1 and the GPL v2, but not with +The following libraries are under LGPL version 3: +- gmp +- libaribb24 +- liblensfun + +When combining them with FFmpeg, use the configure option `--enable-version3` to +upgrade FFmpeg to the LGPL v3. + +The VMAF, mbedTLS, RK MPI, OpenCORE and VisualOn libraries are under the Apache License +2.0. That license is incompatible with the LGPL v2.1 and the GPL v2, but not with version 3 of those licenses. So to combine these libraries with FFmpeg, the license version needs to be upgraded by passing `--enable-version3` to configure. +The smbclient library is under the GPL v3, to combine it with FFmpeg, +the options `--enable-gpl` and `--enable-version3` have to be passed to +configure to upgrade FFmpeg to the GPL v3. + ### Incompatible libraries There are certain libraries you can combine with FFmpeg whose licenses are not diff -Nru ffmpeg-4.2.2/.mailmap ffmpeg-4.4/.mailmap --- ffmpeg-4.2.2/.mailmap 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/.mailmap 2021-04-08 21:28:39.000000000 +0000 @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + +rcombs + + + diff -Nru ffmpeg-4.2.2/MAINTAINERS ffmpeg-4.4/MAINTAINERS --- ffmpeg-4.2.2/MAINTAINERS 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/MAINTAINERS 2021-04-08 21:28:39.000000000 +0000 @@ -53,11 +53,11 @@ website Deby Barbara Lepage fate.ffmpeg.org Timothy Gu Trac bug tracker Alexander Strasser, Michael Niedermayer, Carl Eugen Hoyos +Patchwork Andriy Gelman mailing lists Baptiste Coudurier -Google+ Paul B Mahol, Michael Niedermayer, Alexander Strasser -Twitter Lou Logan, Reynaldo H. Verdejo Pinochet +Twitter Reynaldo H. Verdejo Pinochet Launchpad Timothy Gu -ffmpeg-security Andreas Cadhalpun, Carl Eugen Hoyos, Clément Bœsch, Michael Niedermayer, Reimar Doeffinger, Rodger Combs, wm4 +ffmpeg-security Andreas Cadhalpun, Carl Eugen Hoyos, Clément Bœsch, Michael Niedermayer, Reimar Doeffinger, rcombs, wm4 libavutil @@ -78,6 +78,7 @@ float_dsp Loren Merritt hash Reimar Doeffinger hwcontext_cuda* Timo Rothenpieler + hwcontext_vulkan* Lynne intfloat* Michael Niedermayer integer.c, integer.h Michael Niedermayer lzo Reimar Doeffinger @@ -88,6 +89,7 @@ rational.c, rational.h Michael Niedermayer rc4 Reimar Doeffinger ripemd.c, ripemd.h James Almer + tx* Lynne libavcodec @@ -142,7 +144,7 @@ ass* Aurelien Jacobs asv* Michael Niedermayer atrac3plus* Maxim Poliakovski - audiotoolbox* Rodger Combs + audiotoolbox* rcombs avs2* Huiwen Ren bgmc.c, bgmc.h Thilo Borgmann binkaudio.c Peter Ross @@ -192,12 +194,14 @@ libdavs2.c Huiwen Ren libgsm.c Michel Bardiaux libkvazaar.c Arttu Ylä-Outinen + libopenh264enc.c Martin Storsjo, Linjie Fu libopenjpeg.c Jaikrishnan Menon libopenjpegenc.c Michael Bradshaw libtheoraenc.c David Conrad libvorbis.c David Conrad libvpx* James Zern libxavs.c Stefan Gehrer + libxavs2.c Huiwen Ren libzvbi-teletextdec.c Marton Balint lzo.h, lzo.c Reimar Doeffinger mdec.c Michael Niedermayer @@ -213,6 +217,7 @@ msvideo1.c Mike Melanson nuv.c Reimar Doeffinger nvdec*, nvenc* Timo Rothenpieler + omx.c Martin Storsjo, Aman Gupta opus* Rostislav Pehlivanov paf.* Paul B Mahol pcx.c Ivo van Poorten @@ -230,7 +235,6 @@ rv10.c Michael Niedermayer s3tc* Ivo van Poorten smc.c Mike Melanson - smvjpegdec.c Ash Hughes snow* Michael Niedermayer, Loren Merritt sonic.c Alex Beregszaszi speedhq.c Steinar H. Gunderson @@ -368,6 +372,8 @@ Sources: vsrc_mandelbrot.c Michael Niedermayer +dnn Yejun Guo + libavformat =========== @@ -386,7 +392,12 @@ afc.c Paul B Mahol aiffdec.c Baptiste Coudurier, Matthieu Bouron aiffenc.c Baptiste Coudurier, Matthieu Bouron + alp.c Zane van Iperen + amvenc.c Zane van Iperen + apm.c Zane van Iperen apngdec.c Benoit Fouet + argo_asf.c Zane van Iperen + argo_brp.c Zane van Iperen ass* Aurelien Jacobs astdec.c Paul B Mahol astenc.c James Almer @@ -424,14 +435,15 @@ ircam* Paul B Mahol iss.c Stefan Gehrer jvdec.c Peter Ross + kvag.c Zane van Iperen libmodplug.c Clément Bœsch libopenmpt.c Josh de Kock lmlm4.c Ivo van Poorten lvfdec.c Paul B Mahol lxfdec.c Tomas Härdin - matroska.c Aurelien Jacobs - matroskadec.c Aurelien Jacobs - matroskaenc.c David Conrad + matroska.c Aurelien Jacobs, Andreas Rheinhardt + matroskadec.c Aurelien Jacobs, Andreas Rheinhardt + matroskaenc.c David Conrad, Andreas Rheinhardt matroska subtitles (matroskaenc.c) John Peebles metadata* Aurelien Jacobs mgsts.c Paul B Mahol @@ -446,7 +458,7 @@ mpegtsenc.c Baptiste Coudurier msnwc_tcp.c Ramiro Polla mtv.c Reynaldo H. Verdejo Pinochet - mxf* Baptiste Coudurier + mxf* Baptiste Coudurier, Tomas Härdin nistspheredec.c Paul B Mahol nsvdec.c Francois Revol nut* Michael Niedermayer @@ -454,9 +466,9 @@ oggdec.c, oggdec.h David Conrad oggenc.c Baptiste Coudurier oggparse*.c David Conrad - oggparsedaala* Rostislav Pehlivanov oma.c Maxim Poliakovski paf.c Paul B Mahol + pp_bnk.c Zane van Iperen psxstr.c Mike Melanson pva.c Ivo van Poorten pvfdec.c Paul B Mahol @@ -502,6 +514,7 @@ ftp.c Lukasz Marek http.c Ronald S. Bultje libssh.c Lukasz Marek + libzmq.c Andriy Gelman mms*.c Ronald S. Bultje udp.c Luca Abeni icecast.c Marvin Scholz @@ -557,6 +570,7 @@ Jun Zhao Kieran Kunhya Kirill Gavrilov +Limin Wang Martin Storsjö Panagiotis Issaris Pedro Arthur @@ -599,13 +613,14 @@ James Almer 7751 2E8C FD94 A169 57E6 9A7A 1463 01AD 7376 59E0 Jean Delvare 7CA6 9F44 60F1 BDC4 1FD2 C858 A552 6B9B B3CD 4E6A Loren Merritt ABD9 08F4 C920 3F65 D8BE 35D7 1540 DAA7 060F 56DE -Lou Logan (llogan) 7D68 DC73 CBEF EABB 671A B6CF 621C 2E28 82F8 DC3A +Lynne FE50 139C 6805 72CA FD52 1F8D A2FE A5F0 3F03 4464 Michael Niedermayer 9FF2 128B 147E F673 0BAD F133 611E C787 040B 0FAB Nicolas George 24CE 01CE 9ACC 5CEB 74D8 8D9D B063 D997 36E5 4C93 Nikolay Aleksandrov 8978 1D8C FB71 588E 4B27 EAA8 C4F0 B5FC E011 13B1 Panagiotis Issaris 6571 13A3 33D9 3726 F728 AA98 F643 B12E ECF3 E029 Peter Ross A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B Philip Langdale 5DC5 8D66 5FBA 3A43 18EC 045E F8D6 B194 6A75 682E +Ramiro Polla 7859 C65B 751B 1179 792E DAE8 8E95 8B2F 9B6C 5700 Reimar Doeffinger C61D 16E5 9E2C D10C 8958 38A4 0899 A2B9 06D4 D9C7 Reinhard Tartler 9300 5DC2 7E87 6C37 ED7B CA9A 9808 3544 9453 48A4 Reynaldo H. Verdejo Pinochet 6E27 CD34 170C C78E 4D4F 5F40 C18E 077F 3114 452A @@ -614,7 +629,9 @@ Stefano Sabatini 0D0B AD6B 5330 BBAD D3D6 6A0C 719C 2839 FC43 2D5F Steinar H. Gunderson C2E9 004F F028 C18E 4EAD DB83 7F61 7561 7797 8F76 Stephan Hilb 4F38 0B3A 5F39 B99B F505 E562 8D5C 5554 4E17 8863 +Thilo Borgmann (thilo) CE1D B7F4 4D20 FC3A DD9F FE5A 257C 5B8F 1D20 B92F Tiancheng "Timothy" Gu 9456 AFC0 814A 8139 E994 8351 7FE6 B095 B582 B0D4 Tim Nicholson 38CF DB09 3ED0 F607 8B67 6CED 0C0B FC44 8B0B FC83 Tomas Härdin (thardin) A79D 4E3D F38F 763F 91F5 8B33 A01E 8AE0 41BB 2551 Wei Gao 4269 7741 857A 0E60 9EC5 08D2 4744 4EFA 62C1 87B9 +Zane van Iperen (zane) 61AE D40F 368B 6F26 9DAE 3892 6861 6B2D 8AC4 DCC5 diff -Nru ffmpeg-4.2.2/Makefile ffmpeg-4.4/Makefile --- ffmpeg-4.2.2/Makefile 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/Makefile 2021-04-08 21:28:39.000000000 +0000 @@ -50,13 +50,26 @@ target_dec_%_fuzzer$(EXESUF): target_dec_%_fuzzer.o $(FF_DEP_LIBS) $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH) +tools/target_bsf_%_fuzzer$(EXESUF): tools/target_bsf_%_fuzzer.o $(FF_DEP_LIBS) + $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH) + +target_dem_%_fuzzer$(EXESUF): target_dem_%_fuzzer.o $(FF_DEP_LIBS) + $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH) + tools/target_dem_fuzzer$(EXESUF): tools/target_dem_fuzzer.o $(FF_DEP_LIBS) $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH) +tools/target_io_dem_fuzzer$(EXESUF): tools/target_io_dem_fuzzer.o $(FF_DEP_LIBS) + $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $^ $(ELIBS) $(FF_EXTRALIBS) $(LIBFUZZER_PATH) + + +tools/enum_options$(EXESUF): ELIBS = $(FF_EXTRALIBS) +tools/enum_options$(EXESUF): $(FF_DEP_LIBS) tools/sofa2wavs$(EXESUF): ELIBS = $(FF_EXTRALIBS) tools/uncoded_frame$(EXESUF): $(FF_DEP_LIBS) tools/uncoded_frame$(EXESUF): ELIBS = $(FF_EXTRALIBS) tools/target_dec_%_fuzzer$(EXESUF): $(FF_DEP_LIBS) +tools/target_dem_%_fuzzer$(EXESUF): $(FF_DEP_LIBS) CONFIGURABLE_COMPONENTS = \ $(wildcard $(FFLIBS:%=$(SRC_PATH)/lib%/all*.c)) \ @@ -97,7 +110,7 @@ include $(SRC_PATH)/doc/Makefile include $(SRC_PATH)/doc/examples/Makefile -libavcodec/utils.o libavformat/utils.o libavdevice/avdevice.o libavfilter/avfilter.o libavutil/utils.o libpostproc/postprocess.o libswresample/swresample.o libswscale/utils.o : libavutil/ffversion.h +libavcodec/avcodec.o libavformat/utils.o libavdevice/avdevice.o libavfilter/avfilter.o libavutil/utils.o libpostproc/postprocess.o libswresample/swresample.o libswscale/utils.o : libavutil/ffversion.h $(PROGS): %$(PROGSSUF)$(EXESUF): %$(PROGSSUF)_g$(EXESUF) ifeq ($(STRIPTYPE),direct) @@ -148,6 +161,7 @@ version.h libavutil/ffversion.h libavcodec/codec_names.h \ libavcodec/bsf_list.c libavformat/protocol_list.c \ libavcodec/codec_list.c libavcodec/parser_list.c \ + libavfilter/filter_list.c libavdevice/indev_list.c libavdevice/outdev_list.c \ libavformat/muxer_list.c libavformat/demuxer_list.c ifeq ($(SRC_LINK),src) $(RM) src diff -Nru ffmpeg-4.2.2/RELEASE ffmpeg-4.4/RELEASE --- ffmpeg-4.2.2/RELEASE 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/RELEASE 2021-04-08 21:28:39.000000000 +0000 @@ -1 +1 @@ -4.2.2 +4.4 diff -Nru ffmpeg-4.2.2/RELEASE_NOTES ffmpeg-4.4/RELEASE_NOTES --- ffmpeg-4.2.2/RELEASE_NOTES 2019-12-31 21:35:22.000000000 +0000 +++ ffmpeg-4.4/RELEASE_NOTES 2021-04-08 21:28:39.000000000 +0000 @@ -1,10 +1,10 @@ ┌────────────────────────────────────┐ - │ RELEASE NOTES for FFmpeg 4.2 "Ada" │ + │ RELEASE NOTES for FFmpeg 4.4 "Rao" │ └────────────────────────────────────┘ - The FFmpeg Project proudly presents FFmpeg 4.2 "Ada", about 8 - months after the release of FFmpeg 4.1. + The FFmpeg Project proudly presents FFmpeg 4.4 "Rao", about 10 + months after the release of FFmpeg 4.3. A complete Changelog is available at the root of the project, and the complete Git history on https://git.ffmpeg.org/gitweb/ffmpeg.git diff -Nru ffmpeg-4.2.2/tests/api/api-band-test.c ffmpeg-4.4/tests/api/api-band-test.c --- ffmpeg-4.2.2/tests/api/api-band-test.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/api/api-band-test.c 2021-04-08 21:28:40.000000000 +0000 @@ -71,14 +71,12 @@ AVCodecParameters *origin_par = NULL; uint8_t *byte_buffer = NULL; AVFrame *fr = NULL; - AVPacket pkt; + AVPacket *pkt; AVFormatContext *fmt_ctx = NULL; int number_of_written_bytes; int video_stream; - int got_frame = 0; int byte_buffer_size; int result; - int end_of_stream = 0; draw_horiz_band_called = 0; @@ -135,6 +133,12 @@ return AVERROR(ENOMEM); } + pkt = av_packet_alloc(); + if (!pkt) { + av_log(NULL, AV_LOG_ERROR, "Cannot allocate packet\n"); + return AVERROR(ENOMEM); + } + if (strcmp(codec->name, "flv") && strcmp(codec->name, "mpeg4") && strcmp(codec->name, "huffyuv")) { av_log(NULL, AV_LOG_ERROR, "Wrong codec\n"); return -1; @@ -155,50 +159,59 @@ memset(slice_byte_buffer, 0, byte_buffer_size); slice_byte_buffer_size = byte_buffer_size; - av_init_packet(&pkt); - do { - if (!end_of_stream) { - if (av_read_frame(fmt_ctx, &pkt) < 0) { - end_of_stream = 1; - } + result = 0; + while (result >= 0) { + result = av_read_frame(fmt_ctx, pkt); + if (result >= 0 && pkt->stream_index != video_stream) { + av_packet_unref(pkt); + continue; } - if (end_of_stream) { - pkt.data = NULL; - pkt.size = 0; + + // pkt will be empty on read error/EOF + result = avcodec_send_packet(ctx, pkt); + + av_packet_unref(pkt); + + if (result < 0) { + av_log(NULL, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); + return result; } - if (pkt.stream_index == video_stream || end_of_stream) { - got_frame = 0; - result = avcodec_decode_video2(ctx, fr, &got_frame, &pkt); - if (result < 0) { + + while (result >= 0) { + result = avcodec_receive_frame(ctx, fr); + if (result == AVERROR_EOF) + goto finish; + else if (result == AVERROR(EAGAIN)) { + result = 0; + break; + } else if (result < 0) { av_log(NULL, AV_LOG_ERROR, "Error decoding frame\n"); return result; } - if (got_frame) { - number_of_written_bytes = av_image_copy_to_buffer(byte_buffer, byte_buffer_size, - (const uint8_t* const *)fr->data, (const int*) fr->linesize, - ctx->pix_fmt, ctx->width, ctx->height, 1); - if (number_of_written_bytes < 0) { - av_log(NULL, AV_LOG_ERROR, "Can't copy image to buffer\n"); - return number_of_written_bytes; - } - if (draw_horiz_band_called == 0) { - av_log(NULL, AV_LOG_ERROR, "draw_horiz_band haven't been called!\n"); - return -1; - } - if (av_adler32_update(0, (const uint8_t*)byte_buffer, number_of_written_bytes) != - av_adler32_update(0, (const uint8_t*)slice_byte_buffer, number_of_written_bytes)) { - av_log(NULL, AV_LOG_ERROR, "Decoded frames with and without draw_horiz_band are not the same!\n"); - return -1; - } + + number_of_written_bytes = av_image_copy_to_buffer(byte_buffer, byte_buffer_size, + (const uint8_t* const *)fr->data, (const int*) fr->linesize, + ctx->pix_fmt, ctx->width, ctx->height, 1); + if (number_of_written_bytes < 0) { + av_log(NULL, AV_LOG_ERROR, "Can't copy image to buffer\n"); + return number_of_written_bytes; + } + if (draw_horiz_band_called == 0) { + av_log(NULL, AV_LOG_ERROR, "draw_horiz_band haven't been called!\n"); + return -1; + } + if (av_adler32_update(0, (const uint8_t*)byte_buffer, number_of_written_bytes) != + av_adler32_update(0, (const uint8_t*)slice_byte_buffer, number_of_written_bytes)) { + av_log(NULL, AV_LOG_ERROR, "Decoded frames with and without draw_horiz_band are not the same!\n"); + return -1; } - av_packet_unref(&pkt); - av_init_packet(&pkt); + av_frame_unref(fr); } - } while (!end_of_stream || got_frame); + } - av_packet_unref(&pkt); +finish: + av_packet_free(&pkt); av_frame_free(&fr); - avcodec_close(ctx); avformat_close_input(&fmt_ctx); avcodec_free_context(&ctx); av_freep(&byte_buffer); diff -Nru ffmpeg-4.2.2/tests/api/api-codec-param-test.c ffmpeg-4.4/tests/api/api-codec-param-test.c --- ffmpeg-4.2.2/tests/api/api-codec-param-test.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/api/api-codec-param-test.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2015 Matthieu Bouron - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include "libavformat/avformat.h" -#include "libavutil/pixdesc.h" -#include "libavcodec/internal.h" -#include "libavutil/avassert.h" -#include "libavutil/opt.h" - -static int try_decode_video_frame(AVCodecContext *codec_ctx, AVPacket *pkt, int decode) -{ - int ret = 0; - int got_frame = 0; - AVFrame *frame = NULL; - int skip_frame = codec_ctx->skip_frame; - - if (!avcodec_is_open(codec_ctx)) { - const AVCodec *codec = avcodec_find_decoder(codec_ctx->codec_id); - - ret = avcodec_open2(codec_ctx, codec, NULL); - if (ret < 0) { - av_log(codec_ctx, AV_LOG_ERROR, "Failed to open codec\n"); - goto end; - } - } - - frame = av_frame_alloc(); - if (!frame) { - av_log(NULL, AV_LOG_ERROR, "Failed to allocate frame\n"); - goto end; - } - - if (!decode && avpriv_codec_get_cap_skip_frame_fill_param(codec_ctx->codec)) { - codec_ctx->skip_frame = AVDISCARD_ALL; - } - - do { - ret = avcodec_decode_video2(codec_ctx, frame, &got_frame, pkt); - av_assert0(decode || (!decode && !got_frame)); - if (ret < 0) - break; - pkt->data += ret; - pkt->size -= ret; - - if (got_frame) { - break; - } - } while (pkt->size > 0); - -end: - codec_ctx->skip_frame = skip_frame; - - av_frame_free(&frame); - return ret; -} - -static int find_video_stream_info(AVFormatContext *fmt_ctx, int decode) -{ - int ret = 0; - int i, done = 0; - AVPacket pkt; - - av_init_packet(&pkt); - - while (!done) { - AVCodecContext *codec_ctx = NULL; - AVStream *st; - - if ((ret = av_read_frame(fmt_ctx, &pkt)) < 0) { - av_log(fmt_ctx, AV_LOG_ERROR, "Failed to read frame\n"); - goto end; - } - - st = fmt_ctx->streams[pkt.stream_index]; - codec_ctx = st->codec; - - /* Writing to AVStream.codec_info_nb_frames must not be done by - * user applications. It is done here for testing purposing as - * find_video_stream_info tries to mimic avformat_find_stream_info - * which writes to this field. - * */ - if (codec_ctx->codec_type != AVMEDIA_TYPE_VIDEO || - st->codec_info_nb_frames++ > 0) { - av_packet_unref(&pkt); - continue; - } - - ret = try_decode_video_frame(codec_ctx, &pkt, decode); - if (ret < 0) { - av_log(fmt_ctx, AV_LOG_ERROR, "Failed to decode video frame\n"); - goto end; - } - - av_packet_unref(&pkt); - - /* check if all video streams have demuxed a packet */ - done = 1; - for (i = 0; i < fmt_ctx->nb_streams; i++) { - st = fmt_ctx->streams[i]; - codec_ctx = st->codec; - - if (codec_ctx->codec_type != AVMEDIA_TYPE_VIDEO) - continue; - - done &= st->codec_info_nb_frames > 0; - } - } - -end: - av_packet_unref(&pkt); - - /* close all codecs opened in try_decode_video_frame */ - for (i = 0; i < fmt_ctx->nb_streams; i++) { - AVStream *st = fmt_ctx->streams[i]; - avcodec_close(st->codec); - } - - return ret < 0; -} - -static void dump_video_streams(const AVFormatContext *fmt_ctx, int decode) -{ - int i; - - for (i = 0; i < fmt_ctx->nb_streams; i++) { - const AVOption *opt = NULL; - const AVStream *st = fmt_ctx->streams[i]; - AVCodecContext *codec_ctx = st->codec; - - printf("stream=%d, decode=%d\n", i, decode); - while (opt = av_opt_next(codec_ctx, opt)) { - uint8_t *str; - - if (opt->type == AV_OPT_TYPE_CONST) - continue; - - if (!strcmp(opt->name, "frame_number")) - continue; - - if (av_opt_get(codec_ctx, opt->name, 0, &str) >= 0) { - printf(" %s=%s\n", opt->name, str); - av_free(str); - } - } - } -} - -static int open_and_probe_video_streams(AVFormatContext **fmt_ctx, const char *filename, int decode) -{ - int ret = 0; - - ret = avformat_open_input(fmt_ctx, filename, NULL, NULL); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Failed to open input '%s'", filename); - goto end; - } - - ret = find_video_stream_info(*fmt_ctx, decode); - if (ret < 0) { - goto end; - } - - dump_video_streams(*fmt_ctx, decode); - -end: - return ret; -} - -static int check_video_streams(const AVFormatContext *fmt_ctx1, const AVFormatContext *fmt_ctx2) -{ - int i; - int ret = 0; - - av_assert0(fmt_ctx1->nb_streams == fmt_ctx2->nb_streams); - for (i = 0; i < fmt_ctx1->nb_streams; i++) { - const AVOption *opt = NULL; - const AVStream *st1 = fmt_ctx1->streams[i]; - const AVStream *st2 = fmt_ctx2->streams[i]; - AVCodecContext *codec_ctx1 = st1->codec; - AVCodecContext *codec_ctx2 = st2->codec; - - if (codec_ctx1->codec_type != AVMEDIA_TYPE_VIDEO) - continue; - - while (opt = av_opt_next(codec_ctx1, opt)) { - uint8_t *str1 = NULL, *str2 = NULL; - - if (opt->type == AV_OPT_TYPE_CONST) - continue; - - if (!strcmp(opt->name, "frame_number")) - continue; - - av_assert0(av_opt_get(codec_ctx1, opt->name, 0, &str1) >= 0); - av_assert0(av_opt_get(codec_ctx2, opt->name, 0, &str2) >= 0); - if (strcmp(str1, str2)) { - av_log(NULL, AV_LOG_ERROR, "Field %s differs: %s %s", opt->name, str1, str2); - ret = AVERROR(EINVAL); - } - av_free(str1); - av_free(str2); - } - } - - return ret; -} - -int main(int argc, char* argv[]) -{ - int ret = 0; - AVFormatContext *fmt_ctx = NULL; - AVFormatContext *fmt_ctx_no_decode = NULL; - - if (argc < 2) { - av_log(NULL, AV_LOG_ERROR, "Usage: %s \n", argv[0]); - return -1; - } - - if ((ret = open_and_probe_video_streams(&fmt_ctx_no_decode, argv[1], 0)) < 0) { - av_log(NULL, AV_LOG_ERROR, "Failed to probe '%s' without frame decoding\n", argv[1]); - goto end; - } - - if ((ret = open_and_probe_video_streams(&fmt_ctx, argv[1], 1)) < 0) { - av_log(NULL, AV_LOG_ERROR, "Failed to probe '%s' with frame decoding\n", argv[1]); - goto end; - } - - ret = check_video_streams(fmt_ctx, fmt_ctx_no_decode); - -end: - avformat_close_input(&fmt_ctx); - avformat_close_input(&fmt_ctx_no_decode); - - return ret; -} diff -Nru ffmpeg-4.2.2/tests/api/api-flac-test.c ffmpeg-4.4/tests/api/api-flac-test.c --- ffmpeg-4.2.2/tests/api/api-flac-test.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/api/api-flac-test.c 2021-04-08 21:28:40.000000000 +0000 @@ -108,15 +108,20 @@ static int run_test(AVCodec *enc, AVCodec *dec, AVCodecContext *enc_ctx, AVCodecContext *dec_ctx) { - AVPacket enc_pkt; + AVPacket *enc_pkt; AVFrame *in_frame, *out_frame; uint8_t *raw_in = NULL, *raw_out = NULL; int in_offset = 0, out_offset = 0; int result = 0; - int got_output = 0; int i = 0; int in_frame_bytes, out_frame_bytes; + enc_pkt = av_packet_alloc(); + if (!enc_pkt) { + av_log(NULL, AV_LOG_ERROR, "Can't allocate output packet\n"); + return AVERROR(ENOMEM); + } + in_frame = av_frame_alloc(); if (!in_frame) { av_log(NULL, AV_LOG_ERROR, "Can't allocate input frame\n"); @@ -126,7 +131,7 @@ in_frame->nb_samples = enc_ctx->frame_size; in_frame->format = enc_ctx->sample_fmt; in_frame->channel_layout = enc_ctx->channel_layout; - if (av_frame_get_buffer(in_frame, 32) != 0) { + if (av_frame_get_buffer(in_frame, 0) != 0) { av_log(NULL, AV_LOG_ERROR, "Can't allocate a buffer for input frame\n"); return AVERROR(ENOMEM); } @@ -150,9 +155,9 @@ } for (i = 0; i < NUMBER_OF_AUDIO_FRAMES; i++) { - av_init_packet(&enc_pkt); - enc_pkt.data = NULL; - enc_pkt.size = 0; + result = av_frame_make_writable(in_frame); + if (result < 0) + return result; generate_raw_frame((uint16_t*)(in_frame->data[0]), i, enc_ctx->sample_rate, enc_ctx->channels, enc_ctx->frame_size); @@ -163,50 +168,63 @@ } memcpy(raw_in + in_offset, in_frame->data[0], in_frame_bytes); in_offset += in_frame_bytes; - result = avcodec_encode_audio2(enc_ctx, &enc_pkt, in_frame, &got_output); + result = avcodec_send_frame(enc_ctx, in_frame); if (result < 0) { - av_log(NULL, AV_LOG_ERROR, "Error encoding audio frame\n"); + av_log(NULL, AV_LOG_ERROR, "Error submitting a frame for encoding\n"); return result; } - /* if we get an encoded packet, feed it straight to the decoder */ - if (got_output) { - result = avcodec_decode_audio4(dec_ctx, out_frame, &got_output, &enc_pkt); + while (result >= 0) { + result = avcodec_receive_packet(enc_ctx, enc_pkt); + if (result == AVERROR(EAGAIN)) + break; + else if (result < 0 && result != AVERROR_EOF) { + av_log(NULL, AV_LOG_ERROR, "Error encoding audio frame\n"); + return result; + } + + /* if we get an encoded packet, feed it straight to the decoder */ + result = avcodec_send_packet(dec_ctx, enc_pkt); + av_packet_unref(enc_pkt); if (result < 0) { + av_log(NULL, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); + return result; + } + + result = avcodec_receive_frame(dec_ctx, out_frame); + if (result == AVERROR(EAGAIN)) { + result = 0; + continue; + } else if (result == AVERROR(EOF)) { + result = 0; + break; + } else if (result < 0) { av_log(NULL, AV_LOG_ERROR, "Error decoding audio packet\n"); return result; } - if (got_output) { - if (result != enc_pkt.size) { - av_log(NULL, AV_LOG_INFO, "Decoder consumed only part of a packet, it is allowed to do so -- need to update this test\n"); - return AVERROR_UNKNOWN; - } - - if (in_frame->nb_samples != out_frame->nb_samples) { - av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different number of samples\n"); - return AVERROR_UNKNOWN; - } - - if (in_frame->channel_layout != out_frame->channel_layout) { - av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different channel layout\n"); - return AVERROR_UNKNOWN; - } - - if (in_frame->format != out_frame->format) { - av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different sample format\n"); - return AVERROR_UNKNOWN; - } - out_frame_bytes = out_frame->nb_samples * out_frame->channels * sizeof(uint16_t); - if (out_frame_bytes > out_frame->linesize[0]) { - av_log(NULL, AV_LOG_ERROR, "Incorrect value of output frame linesize\n"); - return 1; - } - memcpy(raw_out + out_offset, out_frame->data[0], out_frame_bytes); - out_offset += out_frame_bytes; + if (in_frame->nb_samples != out_frame->nb_samples) { + av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different number of samples\n"); + return AVERROR_UNKNOWN; + } + + if (in_frame->channel_layout != out_frame->channel_layout) { + av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different channel layout\n"); + return AVERROR_UNKNOWN; } + + if (in_frame->format != out_frame->format) { + av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different sample format\n"); + return AVERROR_UNKNOWN; + } + out_frame_bytes = out_frame->nb_samples * out_frame->channels * sizeof(uint16_t); + if (out_frame_bytes > out_frame->linesize[0]) { + av_log(NULL, AV_LOG_ERROR, "Incorrect value of output frame linesize\n"); + return 1; + } + memcpy(raw_out + out_offset, out_frame->data[0], out_frame_bytes); + out_offset += out_frame_bytes; } - av_packet_unref(&enc_pkt); } if (memcmp(raw_in, raw_out, out_frame_bytes * NUMBER_OF_AUDIO_FRAMES) != 0) { @@ -218,25 +236,12 @@ av_freep(&raw_in); av_freep(&raw_out); + av_packet_free(&enc_pkt); av_frame_free(&in_frame); av_frame_free(&out_frame); return 0; } -static int close_encoder(AVCodecContext **enc_ctx) -{ - avcodec_close(*enc_ctx); - av_freep(enc_ctx); - return 0; -} - -static int close_decoder(AVCodecContext **dec_ctx) -{ - avcodec_close(*dec_ctx); - av_freep(dec_ctx); - return 0; -} - int main(void) { AVCodec *enc = NULL, *dec = NULL; @@ -265,8 +270,8 @@ return 1; if (run_test(enc, dec, enc_ctx, dec_ctx) != 0) return 1; - close_encoder(&enc_ctx); - close_decoder(&dec_ctx); + avcodec_free_context(&enc_ctx); + avcodec_free_context(&dec_ctx); } } diff -Nru ffmpeg-4.2.2/tests/api/api-h264-slice-test.c ffmpeg-4.4/tests/api/api-h264-slice-test.c --- ffmpeg-4.2.2/tests/api/api-h264-slice-test.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/api/api-h264-slice-test.c 2020-07-11 10:39:30.000000000 +0000 @@ -24,7 +24,6 @@ #include "config.h" -#include #include #include #include diff -Nru ffmpeg-4.2.2/tests/api/api-h264-test.c ffmpeg-4.4/tests/api/api-h264-test.c --- ffmpeg-4.2.2/tests/api/api-h264-test.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/api/api-h264-test.c 2021-04-08 21:28:40.000000000 +0000 @@ -37,15 +37,13 @@ AVCodecParameters *origin_par = NULL; AVFrame *fr = NULL; uint8_t *byte_buffer = NULL; - AVPacket pkt; + AVPacket *pkt; AVFormatContext *fmt_ctx = NULL; int number_of_written_bytes; int video_stream; - int got_frame = 0; int byte_buffer_size; int i = 0; int result; - int end_of_stream = 0; result = avformat_open_input(&fmt_ctx, input_filename, NULL, NULL); if (result < 0) { @@ -97,6 +95,12 @@ return AVERROR(ENOMEM); } + pkt = av_packet_alloc(); + if (!pkt) { + av_log(NULL, AV_LOG_ERROR, "Cannot allocate packet\n"); + return AVERROR(ENOMEM); + } + byte_buffer_size = av_image_get_buffer_size(ctx->pix_fmt, ctx->width, ctx->height, 16); byte_buffer = av_malloc(byte_buffer_size); if (!byte_buffer) { @@ -106,45 +110,61 @@ printf("#tb %d: %d/%d\n", video_stream, fmt_ctx->streams[video_stream]->time_base.num, fmt_ctx->streams[video_stream]->time_base.den); i = 0; - av_init_packet(&pkt); - do { - if (!end_of_stream) - if (av_read_frame(fmt_ctx, &pkt) < 0) - end_of_stream = 1; - if (end_of_stream) { - pkt.data = NULL; - pkt.size = 0; + + result = 0; + while (result >= 0) { + result = av_read_frame(fmt_ctx, pkt); + if (result >= 0 && pkt->stream_index != video_stream) { + av_packet_unref(pkt); + continue; + } + + if (result < 0) + result = avcodec_send_packet(ctx, NULL); + else { + if (pkt->pts == AV_NOPTS_VALUE) + pkt->pts = pkt->dts = i; + result = avcodec_send_packet(ctx, pkt); } - if (pkt.stream_index == video_stream || end_of_stream) { - got_frame = 0; - if (pkt.pts == AV_NOPTS_VALUE) - pkt.pts = pkt.dts = i; - result = avcodec_decode_video2(ctx, fr, &got_frame, &pkt); - if (result < 0) { + av_packet_unref(pkt); + + if (result < 0) { + av_log(NULL, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); + return result; + } + + while (result >= 0) { + result = avcodec_receive_frame(ctx, fr); + if (result == AVERROR_EOF) + goto finish; + else if (result == AVERROR(EAGAIN)) { + result = 0; + break; + } else if (result < 0) { av_log(NULL, AV_LOG_ERROR, "Error decoding frame\n"); return result; } - if (got_frame) { - number_of_written_bytes = av_image_copy_to_buffer(byte_buffer, byte_buffer_size, - (const uint8_t* const *)fr->data, (const int*) fr->linesize, - ctx->pix_fmt, ctx->width, ctx->height, 1); - if (number_of_written_bytes < 0) { - av_log(NULL, AV_LOG_ERROR, "Can't copy image to buffer\n"); - return number_of_written_bytes; - } - printf("%d, %s, %s, %8"PRId64", %8d, 0x%08lx\n", video_stream, - av_ts2str(fr->pts), av_ts2str(fr->pkt_dts), fr->pkt_duration, - number_of_written_bytes, av_adler32_update(0, (const uint8_t*)byte_buffer, number_of_written_bytes)); + + number_of_written_bytes = av_image_copy_to_buffer(byte_buffer, byte_buffer_size, + (const uint8_t* const *)fr->data, (const int*) fr->linesize, + ctx->pix_fmt, ctx->width, ctx->height, 1); + if (number_of_written_bytes < 0) { + av_log(NULL, AV_LOG_ERROR, "Can't copy image to buffer\n"); + av_frame_unref(fr); + return number_of_written_bytes; } - av_packet_unref(&pkt); - av_init_packet(&pkt); + printf("%d, %s, %s, %8"PRId64", %8d, 0x%08lx\n", video_stream, + av_ts2str(fr->pts), av_ts2str(fr->pkt_dts), fr->pkt_duration, + number_of_written_bytes, av_adler32_update(0, (const uint8_t*)byte_buffer, number_of_written_bytes)); + + av_frame_unref(fr); } i++; - } while (!end_of_stream || got_frame); + } - av_packet_unref(&pkt); +finish: + av_packet_free(&pkt); av_frame_free(&fr); - avcodec_close(ctx); avformat_close_input(&fmt_ctx); avcodec_free_context(&ctx); av_freep(&byte_buffer); diff -Nru ffmpeg-4.2.2/tests/api/api-seek-test.c ffmpeg-4.4/tests/api/api-seek-test.c --- ffmpeg-4.2.2/tests/api/api-seek-test.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/api/api-seek-test.c 2021-04-08 21:28:40.000000000 +0000 @@ -73,16 +73,14 @@ } static int compute_crc_of_packets(AVFormatContext *fmt_ctx, int video_stream, - AVCodecContext *ctx, AVFrame *fr, uint64_t ts_start, uint64_t ts_end, int no_seeking) + AVCodecContext *ctx, AVPacket *pkt, AVFrame *fr, + uint64_t ts_start, uint64_t ts_end, int no_seeking) { int number_of_written_bytes; - int got_frame = 0; int result; - int end_of_stream = 0; int byte_buffer_size; uint8_t *byte_buffer; uint32_t crc; - AVPacket pkt; byte_buffer_size = av_image_get_buffer_size(ctx->pix_fmt, ctx->width, ctx->height, 16); byte_buffer = av_malloc(byte_buffer_size); @@ -101,53 +99,66 @@ avcodec_flush_buffers(ctx); } - av_init_packet(&pkt); do { - if (!end_of_stream) - if (av_read_frame(fmt_ctx, &pkt) < 0) - end_of_stream = 1; - if (end_of_stream) { - pkt.data = NULL; - pkt.size = 0; - } - if (pkt.stream_index == video_stream || end_of_stream) { - got_frame = 0; - if ((pkt.pts == AV_NOPTS_VALUE) && (!end_of_stream)) { + result = av_read_frame(fmt_ctx, pkt); + if (result >= 0 && pkt->stream_index != video_stream) { + av_packet_unref(pkt); + continue; + } + + if (result < 0) + result = avcodec_send_packet(ctx, NULL); + else { + if (pkt->pts == AV_NOPTS_VALUE) { av_log(NULL, AV_LOG_ERROR, "Error: frames doesn't have pts values\n"); return -1; } - result = avcodec_decode_video2(ctx, fr, &got_frame, &pkt); - if (result < 0) { + result = avcodec_send_packet(ctx, pkt); + } + + av_packet_unref(pkt); + + if (result < 0) { + av_log(NULL, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); + return result; + } + + while (result >= 0) { + result = avcodec_receive_frame(ctx, fr); + if (result == AVERROR_EOF) + goto finish; + else if (result == AVERROR(EAGAIN)) { + result = 0; + break; + } else if (result < 0) { av_log(NULL, AV_LOG_ERROR, "Error decoding frame\n"); return result; } - if (got_frame) { - number_of_written_bytes = av_image_copy_to_buffer(byte_buffer, byte_buffer_size, - (const uint8_t* const *)fr->data, (const int*) fr->linesize, - ctx->pix_fmt, ctx->width, ctx->height, 1); - if (number_of_written_bytes < 0) { - av_log(NULL, AV_LOG_ERROR, "Can't copy image to buffer\n"); - return number_of_written_bytes; - } - if ((!no_seeking) && (fr->pts > ts_end)) - break; - crc = av_adler32_update(0, (const uint8_t*)byte_buffer, number_of_written_bytes); - printf("%10"PRId64", 0x%08"PRIx32"\n", fr->pts, crc); - if (no_seeking) { - if (add_crc_to_array(crc, fr->pts) < 0) - return -1; - } - else { - if (compare_crc_in_array(crc, fr->pts) < 0) - return -1; - } + + number_of_written_bytes = av_image_copy_to_buffer(byte_buffer, byte_buffer_size, + (const uint8_t* const *)fr->data, (const int*) fr->linesize, + ctx->pix_fmt, ctx->width, ctx->height, 1); + if (number_of_written_bytes < 0) { + av_log(NULL, AV_LOG_ERROR, "Can't copy image to buffer\n"); + return number_of_written_bytes; + } + if ((!no_seeking) && (fr->pts > ts_end)) + break; + crc = av_adler32_update(0, (const uint8_t*)byte_buffer, number_of_written_bytes); + printf("%10"PRId64", 0x%08"PRIx32"\n", fr->pts, crc); + if (no_seeking) { + if (add_crc_to_array(crc, fr->pts) < 0) + return -1; + } + else { + if (compare_crc_in_array(crc, fr->pts) < 0) + return -1; } + av_frame_unref(fr); } - av_packet_unref(&pkt); - av_init_packet(&pkt); - } while ((!end_of_stream || got_frame) && (no_seeking || (fr->pts + fr->pkt_duration <= ts_end))); + } while (result >= 0 && (no_seeking || (fr->pts + fr->pkt_duration <= ts_end))); - av_packet_unref(&pkt); +finish: av_freep(&byte_buffer); return 0; @@ -176,6 +187,7 @@ AVCodec *codec = NULL; AVCodecContext *ctx= NULL; AVCodecParameters *origin_par = NULL; + AVPacket *pkt = NULL; AVFrame *fr = NULL; AVFormatContext *fmt_ctx = NULL; int video_stream; @@ -250,13 +262,20 @@ goto end; } - result = compute_crc_of_packets(fmt_ctx, video_stream, ctx, fr, 0, 0, 1); + pkt = av_packet_alloc(); + if (!pkt) { + av_log(NULL, AV_LOG_ERROR, "Cannot allocate packet\n"); + result = AVERROR(ENOMEM); + goto end; + } + + result = compute_crc_of_packets(fmt_ctx, video_stream, ctx, pkt, fr, 0, 0, 1); if (result != 0) goto end; for (i = start_ts; i < end_ts; i += 100) { for (j = i + 100; j < end_ts; j += 100) { - result = compute_crc_of_packets(fmt_ctx, video_stream, ctx, fr, i, j, 0); + result = compute_crc_of_packets(fmt_ctx, video_stream, ctx, pkt, fr, i, j, 0); if (result != 0) break; } @@ -265,8 +284,8 @@ end: av_freep(&crc_array); av_freep(&pts_array); + av_packet_free(&pkt); av_frame_free(&fr); - avcodec_close(ctx); avformat_close_input(&fmt_ctx); avcodec_free_context(&ctx); return result; diff -Nru ffmpeg-4.2.2/tests/api/api-threadmessage-test.c ffmpeg-4.4/tests/api/api-threadmessage-test.c --- ffmpeg-4.2.2/tests/api/api-threadmessage-test.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/api/api-threadmessage-test.c 2020-07-11 10:39:30.000000000 +0000 @@ -101,7 +101,7 @@ msg.frame->format = AV_PIX_FMT_RGBA; msg.frame->width = 320; msg.frame->height = 240; - ret = av_frame_get_buffer(msg.frame, 32); + ret = av_frame_get_buffer(msg.frame, 0); if (ret < 0) { av_frame_free(&msg.frame); break; diff -Nru ffmpeg-4.2.2/tests/api/Makefile ffmpeg-4.4/tests/api/Makefile --- ffmpeg-4.2.2/tests/api/Makefile 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/api/Makefile 2021-04-08 21:28:40.000000000 +0000 @@ -2,7 +2,6 @@ APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice APITESTPROGS-yes += api-seek -APITESTPROGS-yes += api-codec-param APITESTPROGS-$(call DEMDEC, H263, H263) += api-band APITESTPROGS-$(HAVE_THREADS) += api-threadmessage APITESTPROGS += $(APITESTPROGS-yes) diff -Nru ffmpeg-4.2.2/tests/audiomatch.c ffmpeg-4.4/tests/audiomatch.c --- ffmpeg-4.2.2/tests/audiomatch.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/audiomatch.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ #define FFMIN(a,b) ((a) > (b) ? (b) : (a)) #define FFMAX(a,b) ((a) > (b) ? (a) : (b)) +#define FFABS(a) ((a) >= 0 ? (a) : (-(a))) static int64_t fsize(FILE *f) { int64_t end, pos = ftell(f); @@ -81,9 +82,9 @@ signal = malloc(siglen * sizeof(*signal)); if (fread(data , 1, datlen, f[0]) != datlen) - return 1; + goto read_fail; if (fread(signal, 1, siglen, f[1]) != siglen) - return 1; + goto read_fail; datlen /= 2; siglen /= 2; @@ -101,14 +102,21 @@ int j = pos + i; c += signal[i] * data[j]; } - if (fabs(c) > sigamp * 0.94) - maxshift = FFMIN(maxshift, fabs(pos)+32); - if (fabs(c) > fabs(bestc)) { + if (FFABS(c) > sigamp * 0.94) + maxshift = FFMIN(maxshift, FFABS(pos)+32); + if (FFABS(c) > FFABS(bestc)) { bestc = c; bestpos = pos; } } printf("presig: %d postsig:%d c:%7.4f lenerr:%d\n", bestpos, datlen - siglen - bestpos, bestc / sigamp, datlen - siglen); + free(data); + free(signal); return 0; + +read_fail: + free(data); + free(signal); + return 1; } diff -Nru ffmpeg-4.2.2/tests/checkasm/aacpsdsp.c ffmpeg-4.4/tests/checkasm/aacpsdsp.c --- ffmpeg-4.2.2/tests/checkasm/aacpsdsp.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/aacpsdsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -17,6 +17,8 @@ */ #include "libavcodec/aacpsdsp.h" +#include "libavutil/intfloat.h" +#include "libavutil/mem_internal.h" #include "checkasm.h" @@ -34,6 +36,16 @@ #define EPS 0.005 +static void clear_less_significant_bits(INTFLOAT *buf, int len, int bits) +{ + int i; + for (i = 0; i < len; i++) { + union av_intfloat32 u = { .f = buf[i] }; + u.i &= (0xffffffff << bits); + buf[i] = u.f; + } +} + static void test_add_squares(void) { LOCAL_ALIGNED_16(INTFLOAT, dst0, [BUF_SIZE]); @@ -198,6 +210,13 @@ randomize((INTFLOAT *)h, 2 * 4); randomize((INTFLOAT *)h_step, 2 * 4); + // Clear the least significant 14 bits of h_step, to avoid + // divergence when accumulating h_step BUF_SIZE times into + // a float variable which may or may not have extra intermediate + // precision. Therefore clear roughly log2(BUF_SIZE) less + // significant bits, to get the same result regardless of any + // extra precision in the accumulator. + clear_less_significant_bits((INTFLOAT *)h_step, 2 * 4, 14); call_ref(l0, r0, h, h_step, BUF_SIZE); call_new(l1, r1, h, h_step, BUF_SIZE); diff -Nru ffmpeg-4.2.2/tests/checkasm/aarch64/checkasm.S ffmpeg-4.4/tests/checkasm/aarch64/checkasm.S --- ffmpeg-4.2.2/tests/checkasm/aarch64/checkasm.S 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/aarch64/checkasm.S 2020-07-11 10:39:30.000000000 +0000 @@ -23,29 +23,31 @@ #include "libavutil/aarch64/asm.S" const register_init, align=4 - .quad 0x21f86d66c8ca00ce - .quad 0x75b6ba21077c48ad - .quad 0xed56bb2dcb3c7736 - .quad 0x8bda43d3fd1a7e06 - .quad 0xb64a9c9e5d318408 - .quad 0xdf9a54b303f1d3a3 - .quad 0x4a75479abd64e097 - .quad 0x249214109d5d1c88 - .quad 0x1a1b2550a612b48c - .quad 0x79445c159ce79064 - .quad 0x2eed899d5a28ddcd - .quad 0x86b2536fcd8cf636 - .quad 0xb0856806085e7943 - .quad 0x3f2bf84fc0fcca4e - .quad 0xacbd382dcf5b8de2 - .quad 0xd229e1f5b281303f - .quad 0x71aeaff20b095fd9 - .quad 0xab63e2e11fa38ed9 + .quad 0x21f86d66c8ca00ce + .quad 0x75b6ba21077c48ad + .quad 0xed56bb2dcb3c7736 + .quad 0x8bda43d3fd1a7e06 + .quad 0xb64a9c9e5d318408 + .quad 0xdf9a54b303f1d3a3 + .quad 0x4a75479abd64e097 + .quad 0x249214109d5d1c88 + .quad 0x1a1b2550a612b48c + .quad 0x79445c159ce79064 + .quad 0x2eed899d5a28ddcd + .quad 0x86b2536fcd8cf636 + .quad 0xb0856806085e7943 + .quad 0x3f2bf84fc0fcca4e + .quad 0xacbd382dcf5b8de2 + .quad 0xd229e1f5b281303f + .quad 0x71aeaff20b095fd9 + .quad 0xab63e2e11fa38ed9 endconst -const error_message - .asciz "failed to preserve register" +const error_message_register + .asciz "failed to preserve register" +error_message_stack: + .asciz "stack clobbered" endconst @@ -55,103 +57,142 @@ #define CLOBBER_STACK ((8*MAX_ARGS + 15) & ~15) function checkasm_stack_clobber, export=1 - mov x3, sp - mov x2, #CLOBBER_STACK + mov x3, sp + mov x2, #CLOBBER_STACK 1: - stp x0, x1, [sp, #-16]! - subs x2, x2, #16 - b.gt 1b - mov sp, x3 - ret + stp x0, x1, [sp, #-16]! + subs x2, x2, #16 + b.gt 1b + mov sp, x3 + ret endfunc -#define ARG_STACK ((8*(MAX_ARGS - 8) + 15) & ~15) +// + 16 for stack canary reference +#define ARG_STACK ((8*(MAX_ARGS - 8) + 15) & ~15 + 16) function checkasm_checked_call, export=1 - stp x29, x30, [sp, #-16]! - mov x29, sp - stp x19, x20, [sp, #-16]! - stp x21, x22, [sp, #-16]! - stp x23, x24, [sp, #-16]! - stp x25, x26, [sp, #-16]! - stp x27, x28, [sp, #-16]! - stp d8, d9, [sp, #-16]! - stp d10, d11, [sp, #-16]! - stp d12, d13, [sp, #-16]! - stp d14, d15, [sp, #-16]! - - movrel x9, register_init - ldp d8, d9, [x9], #16 - ldp d10, d11, [x9], #16 - ldp d12, d13, [x9], #16 - ldp d14, d15, [x9], #16 - ldp x19, x20, [x9], #16 - ldp x21, x22, [x9], #16 - ldp x23, x24, [x9], #16 - ldp x25, x26, [x9], #16 - ldp x27, x28, [x9], #16 + stp x29, x30, [sp, #-16]! + mov x29, sp + stp x19, x20, [sp, #-16]! + stp x21, x22, [sp, #-16]! + stp x23, x24, [sp, #-16]! + stp x25, x26, [sp, #-16]! + stp x27, x28, [sp, #-16]! + stp d8, d9, [sp, #-16]! + stp d10, d11, [sp, #-16]! + stp d12, d13, [sp, #-16]! + stp d14, d15, [sp, #-16]! + + movrel x9, register_init + ldp d8, d9, [x9], #16 + ldp d10, d11, [x9], #16 + ldp d12, d13, [x9], #16 + ldp d14, d15, [x9], #16 + ldp x19, x20, [x9], #16 + ldp x21, x22, [x9], #16 + ldp x23, x24, [x9], #16 + ldp x25, x26, [x9], #16 + ldp x27, x28, [x9], #16 - sub sp, sp, #ARG_STACK + sub sp, sp, #ARG_STACK .equ pos, 0 .rept MAX_ARGS-8 - // Skip the first 8 args, that are loaded into registers - ldr x9, [x29, #16 + 8*8 + pos] - str x9, [sp, #pos] + // Skip the first 8 args, that are loaded into registers + ldr x9, [x29, #16 + 8*8 + pos] + str x9, [sp, #pos] .equ pos, pos + 8 .endr - mov x12, x0 - ldp x0, x1, [x29, #16] - ldp x2, x3, [x29, #32] - ldp x4, x5, [x29, #48] - ldp x6, x7, [x29, #64] - blr x12 - add sp, sp, #ARG_STACK - stp x0, x1, [sp, #-16]! - movrel x9, register_init - movi v3.8h, #0 + // Fill x8-x17 with garbage. This doesn't have to be preserved, + // but avoids relying on them having any particular value. + movrel x9, register_init + ldp x10, x11, [x9], #32 + ldp x12, x13, [x9], #32 + ldp x14, x15, [x9], #32 + ldp x16, x17, [x9], #32 + ldp x8, x9, [x9] + + // For stack overflows, the callee is free to overwrite the parameters + // that were passed on the stack (if any), so we can only check after + // that point. First figure out how many parameters the function + // really took on the stack: + ldr w2, [x29, #16 + 8*8 + (MAX_ARGS-8)*8] + // Load the first non-parameter value from the stack, that should be + // left untouched by the function. Store a copy of it inverted, so that + // e.g. overwriting everything with zero would be noticed. + ldr x2, [sp, x2, lsl #3] + mvn x2, x2 + str x2, [sp, #ARG_STACK-8] + + // Load the in-register arguments + mov x12, x0 + ldp x0, x1, [x29, #16] + ldp x2, x3, [x29, #32] + ldp x4, x5, [x29, #48] + ldp x6, x7, [x29, #64] + // Call the target function + blr x12 + + // Load the number of stack parameters, stack canary and its reference + ldr w2, [x29, #16 + 8*8 + (MAX_ARGS-8)*8] + ldr x2, [sp, x2, lsl #3] + ldr x3, [sp, #ARG_STACK-8] + + add sp, sp, #ARG_STACK + stp x0, x1, [sp, #-16]! + + mvn x3, x3 + cmp x2, x3 + b.ne 2f + + movrel x9, register_init + movi v3.8h, #0 .macro check_reg_neon reg1, reg2 - ldr q1, [x9], #16 - uzp1 v2.2d, v\reg1\().2d, v\reg2\().2d - eor v1.16b, v1.16b, v2.16b - orr v3.16b, v3.16b, v1.16b + ldr q1, [x9], #16 + uzp1 v2.2d, v\reg1\().2d, v\reg2\().2d + eor v1.16b, v1.16b, v2.16b + orr v3.16b, v3.16b, v1.16b .endm - check_reg_neon 8, 9 - check_reg_neon 10, 11 - check_reg_neon 12, 13 - check_reg_neon 14, 15 - uqxtn v3.8b, v3.8h - umov x3, v3.d[0] + check_reg_neon 8, 9 + check_reg_neon 10, 11 + check_reg_neon 12, 13 + check_reg_neon 14, 15 + uqxtn v3.8b, v3.8h + umov x3, v3.d[0] .macro check_reg reg1, reg2 - ldp x0, x1, [x9], #16 - eor x0, x0, \reg1 - eor x1, x1, \reg2 - orr x3, x3, x0 - orr x3, x3, x1 + ldp x0, x1, [x9], #16 + eor x0, x0, \reg1 + eor x1, x1, \reg2 + orr x3, x3, x0 + orr x3, x3, x1 .endm - check_reg x19, x20 - check_reg x21, x22 - check_reg x23, x24 - check_reg x25, x26 - check_reg x27, x28 - - cbz x3, 0f - - movrel x0, error_message - bl X(checkasm_fail_func) + check_reg x19, x20 + check_reg x21, x22 + check_reg x23, x24 + check_reg x25, x26 + check_reg x27, x28 + + cbz x3, 0f + + movrel x0, error_message_register + b 1f +2: + movrel x0, error_message_stack +1: + bl X(checkasm_fail_func) 0: - ldp x0, x1, [sp], #16 - ldp d14, d15, [sp], #16 - ldp d12, d13, [sp], #16 - ldp d10, d11, [sp], #16 - ldp d8, d9, [sp], #16 - ldp x27, x28, [sp], #16 - ldp x25, x26, [sp], #16 - ldp x23, x24, [sp], #16 - ldp x21, x22, [sp], #16 - ldp x19, x20, [sp], #16 - ldp x29, x30, [sp], #16 - ret + ldp x0, x1, [sp], #16 + ldp d14, d15, [sp], #16 + ldp d12, d13, [sp], #16 + ldp d10, d11, [sp], #16 + ldp d8, d9, [sp], #16 + ldp x27, x28, [sp], #16 + ldp x25, x26, [sp], #16 + ldp x23, x24, [sp], #16 + ldp x21, x22, [sp], #16 + ldp x19, x20, [sp], #16 + ldp x29, x30, [sp], #16 + ret endfunc diff -Nru ffmpeg-4.2.2/tests/checkasm/af_afir.c ffmpeg-4.4/tests/checkasm/af_afir.c --- ffmpeg-4.2.2/tests/checkasm/af_afir.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/af_afir.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavfilter/af_afir.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #include "checkasm.h" #define LEN 256 @@ -53,7 +54,19 @@ call_ref(cdst, src1, src2, LEN); call_new(odst, src1, src2, LEN); for (i = 0; i <= LEN*2; i++) { - if (!float_near_abs_eps(cdst[i], odst[i], 6.2e-05)) { + int idx = i & ~1; + float cre = src2[idx]; + float cim = src2[idx + 1]; + float tre = src1[idx]; + float tim = src1[idx + 1]; + double t = fabs(src0[i]) + + fabs(tre) + fabs(tim) + fabs(cre) + fabs(cim) + + fabs(tre * cre) + fabs(tim * cim) + + fabs(tre * cim) + fabs(tim * cre) + + fabs(tre * cre - tim * cim) + + fabs(tre * cim + tim * cre) + + fabs(cdst[i]) + 1.0; + if (!float_near_abs_eps(cdst[i], odst[i], t * 2 * FLT_EPSILON)) { fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n", i, cdst[i], odst[i], cdst[i] - odst[i]); fail(); diff -Nru ffmpeg-4.2.2/tests/checkasm/alacdsp.c ffmpeg-4.4/tests/checkasm/alacdsp.c --- ffmpeg-4.2.2/tests/checkasm/alacdsp.c 2018-07-17 09:27:43.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/alacdsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavcodec/mathops.h" #include "libavutil/common.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" #define BUF_SIZE 256 #define MAX_CHANNELS 2 diff -Nru ffmpeg-4.2.2/tests/checkasm/arm/checkasm.S ffmpeg-4.4/tests/checkasm/arm/checkasm.S --- ffmpeg-4.2.2/tests/checkasm/arm/checkasm.S 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/arm/checkasm.S 2020-07-11 10:39:30.000000000 +0000 @@ -29,22 +29,24 @@ #endif const register_init, align=3 - .quad 0x21f86d66c8ca00ce - .quad 0x75b6ba21077c48ad - .quad 0xed56bb2dcb3c7736 - .quad 0x8bda43d3fd1a7e06 - .quad 0xb64a9c9e5d318408 - .quad 0xdf9a54b303f1d3a3 - .quad 0x4a75479abd64e097 - .quad 0x249214109d5d1c88 + .quad 0x21f86d66c8ca00ce + .quad 0x75b6ba21077c48ad + .quad 0xed56bb2dcb3c7736 + .quad 0x8bda43d3fd1a7e06 + .quad 0xb64a9c9e5d318408 + .quad 0xdf9a54b303f1d3a3 + .quad 0x4a75479abd64e097 + .quad 0x249214109d5d1c88 endconst const error_message_fpscr - .asciz "failed to preserve register FPSCR, changed bits: %x" + .asciz "failed to preserve register FPSCR, changed bits: %x" error_message_gpr: - .asciz "failed to preserve register r%d" + .asciz "failed to preserve register r%d" error_message_vfp: - .asciz "failed to preserve register d%d" + .asciz "failed to preserve register d%d" +error_message_stack: + .asciz "failed to preserve stack" endconst @ max number of args used by any asm function. @@ -52,113 +54,140 @@ #define ARG_STACK 4*(MAX_ARGS - 4) -@ align the used stack space to 8 to preserve the stack alignment -#define ARG_STACK_A (((ARG_STACK + pushed + 7) & ~7) - pushed) +@ Align the used stack space to 8 to preserve the stack alignment. +@ +8 for stack canary reference. +#define ARG_STACK_A (((ARG_STACK + pushed + 7) & ~7) - pushed + 8) .macro clobbercheck variant .equ pushed, 4*9 function checkasm_checked_call_\variant, export=1 - push {r4-r11, lr} + push {r4-r11, lr} .ifc \variant, vfp - vpush {d8-d15} - fmrx r4, FPSCR - push {r4} + vpush {d8-d15} + fmrx r4, FPSCR + push {r4} .equ pushed, pushed + 16*4 + 4 .endif - movrel r12, register_init + movrel r12, register_init .ifc \variant, vfp - vldm r12, {d8-d15} + vldm r12, {d8-d15} .endif - ldm r12, {r4-r11} + ldm r12, {r4-r11} - sub sp, sp, #ARG_STACK_A + sub sp, sp, #ARG_STACK_A .equ pos, 0 .rept MAX_ARGS-4 - ldr r12, [sp, #ARG_STACK_A + pushed + 8 + pos] - str r12, [sp, #pos] + ldr r12, [sp, #ARG_STACK_A + pushed + 8 + pos] + str r12, [sp, #pos] .equ pos, pos + 4 .endr - mov r12, r0 - mov r0, r2 - mov r1, r3 - ldrd r2, r3, [sp, #ARG_STACK_A + pushed] - blx r12 - add sp, sp, #ARG_STACK_A + @ For stack overflows, the callee is free to overwrite the parameters + @ that were passed on the stack (if any), so we can only check after + @ that point. First figure out how many parameters the function + @ really took on the stack: + ldr r12, [sp, #ARG_STACK_A + pushed + 8 + 4*(MAX_ARGS-4)] + @ Load the first non-parameter value from the stack, that should be + @ left untouched by the function. Store a copy of it inverted, so that + @ e.g. overwriting everything with zero would be noticed. + ldr r12, [sp, r12, lsl #2] + mvn r12, r12 + str r12, [sp, #ARG_STACK_A - 4] + + mov r12, r0 + mov r0, r2 + mov r1, r3 + ldrd r2, r3, [sp, #ARG_STACK_A + pushed] + @ Call the target function + blx r12 + + @ Load the number of stack parameters, stack canary and its reference + ldr r12, [sp, #ARG_STACK_A + pushed + 8 + 4*(MAX_ARGS-4)] + ldr r2, [sp, r12, lsl #2] + ldr r3, [sp, #ARG_STACK_A - 4] + + add sp, sp, #ARG_STACK_A + push {r0, r1} + + mvn r3, r3 + cmp r2, r3 + bne 5f - push {r0, r1} - movrel r12, register_init + movrel r12, register_init .ifc \variant, vfp .macro check_reg_vfp, dreg, offset - ldrd r2, r3, [r12, #8 * (\offset)] - vmov r0, lr, \dreg - eor r2, r2, r0 - eor r3, r3, lr - orrs r2, r2, r3 - bne 4f + ldrd r2, r3, [r12, #8 * (\offset)] + vmov r0, lr, \dreg + eor r2, r2, r0 + eor r3, r3, lr + orrs r2, r2, r3 + bne 4f .endm .irp n, 8, 9, 10, 11, 12, 13, 14, 15 - @ keep track of the checked double/SIMD register - mov r1, #\n - check_reg_vfp d\n, \n-8 + @ keep track of the checked double/SIMD register + mov r1, #\n + check_reg_vfp d\n, \n-8 .endr .purgem check_reg_vfp - fmrx r1, FPSCR - ldr r3, [sp, #8] - eor r1, r1, r3 - @ Ignore changes in bits 0-4 and 7 - bic r1, r1, #0x9f - @ Ignore changes in the topmost 5 bits - bics r1, r1, #0xf8000000 - bne 3f + fmrx r1, FPSCR + ldr r3, [sp, #8] + eor r1, r1, r3 + @ Ignore changes in bits 0-4 and 7 + bic r1, r1, #0x9f + @ Ignore changes in the topmost 5 bits + bics r1, r1, #0xf8000000 + bne 3f .endif - @ keep track of the checked GPR - mov r1, #4 + @ keep track of the checked GPR + mov r1, #4 .macro check_reg reg1, reg2= - ldrd r2, r3, [r12], #8 - eors r2, r2, \reg1 - bne 2f - add r1, r1, #1 + ldrd r2, r3, [r12], #8 + eors r2, r2, \reg1 + bne 2f + add r1, r1, #1 .ifnb \reg2 - eors r3, r3, \reg2 - bne 2f + eors r3, r3, \reg2 + bne 2f .endif - add r1, r1, #1 + add r1, r1, #1 .endm - check_reg r4, r5 - check_reg r6, r7 + check_reg r4, r5 + check_reg r6, r7 @ r9 is a volatile register in the ios ABI #ifdef __APPLE__ - check_reg r8 + check_reg r8 #else - check_reg r8, r9 + check_reg r8, r9 #endif - check_reg r10, r11 + check_reg r10, r11 .purgem check_reg - b 0f + b 0f +5: + movrel r0, error_message_stack + b 1f 4: - movrel r0, error_message_vfp - b 1f + movrel r0, error_message_vfp + b 1f 3: - movrel r0, error_message_fpscr - b 1f + movrel r0, error_message_fpscr + b 1f 2: - movrel r0, error_message_gpr + movrel r0, error_message_gpr 1: - blx X(checkasm_fail_func) + bl X(checkasm_fail_func) 0: - pop {r0, r1} + pop {r0, r1} .ifc \variant, vfp - pop {r2} - fmxr FPSCR, r2 - vpop {d8-d15} + pop {r2} + fmxr FPSCR, r2 + vpop {d8-d15} .endif - pop {r4-r11, pc} + pop {r4-r11, pc} endfunc .endm diff -Nru ffmpeg-4.2.2/tests/checkasm/audiodsp.c ffmpeg-4.4/tests/checkasm/audiodsp.c --- ffmpeg-4.2.2/tests/checkasm/audiodsp.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/audiodsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,7 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #include "checkasm.h" diff -Nru ffmpeg-4.2.2/tests/checkasm/blockdsp.c ffmpeg-4.4/tests/checkasm/blockdsp.c --- ffmpeg-4.2.2/tests/checkasm/blockdsp.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/blockdsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -27,6 +27,7 @@ #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #define randomize_buffers(size) \ do { \ diff -Nru ffmpeg-4.2.2/tests/checkasm/bswapdsp.c ffmpeg-4.4/tests/checkasm/bswapdsp.c --- ffmpeg-4.2.2/tests/checkasm/bswapdsp.c 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/bswapdsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #define BUF_SIZE 512 diff -Nru ffmpeg-4.2.2/tests/checkasm/checkasm.c ffmpeg-4.4/tests/checkasm/checkasm.c --- ffmpeg-4.2.2/tests/checkasm/checkasm.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/checkasm.c 2021-04-08 21:28:40.000000000 +0000 @@ -42,7 +42,7 @@ #include #endif -#if HAVE_SETCONSOLETEXTATTRIBUTE +#if HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE #include #define COLOR_RED FOREGROUND_RED #define COLOR_GREEN FOREGROUND_GREEN @@ -116,6 +116,16 @@ #if CONFIG_HEVC_DECODER { "hevc_add_res", checkasm_check_hevc_add_res }, { "hevc_idct", checkasm_check_hevc_idct }, + { "hevc_qpel", checkasm_check_hevc_qpel }, + { "hevc_qpel_uni", checkasm_check_hevc_qpel_uni }, + { "hevc_qpel_uni_w", checkasm_check_hevc_qpel_uni_w }, + { "hevc_qpel_bi", checkasm_check_hevc_qpel_bi }, + { "hevc_qpel_bi_w", checkasm_check_hevc_qpel_bi_w }, + { "hevc_epel", checkasm_check_hevc_epel }, + { "hevc_epel_uni", checkasm_check_hevc_epel_uni }, + { "hevc_epel_uni_w", checkasm_check_hevc_epel_uni_w }, + { "hevc_epel_bi", checkasm_check_hevc_epel_bi }, + { "hevc_epel_bi_w", checkasm_check_hevc_epel_bi_w }, { "hevc_sao", checkasm_check_hevc_sao }, #endif #if CONFIG_HUFFYUV_DECODER @@ -130,6 +140,9 @@ #if CONFIG_LLVIDENCDSP { "llviddspenc", checkasm_check_llviddspenc }, #endif + #if CONFIG_OPUS_DECODER + { "opusdsp", checkasm_check_opusdsp }, + #endif #if CONFIG_PIXBLOCKDSP { "pixblockdsp", checkasm_check_pixblockdsp }, #endif @@ -162,6 +175,9 @@ #if CONFIG_COLORSPACE_FILTER { "vf_colorspace", checkasm_check_colorspace }, #endif + #if CONFIG_EQ_FILTER + { "vf_eq", checkasm_check_vf_eq }, + #endif #if CONFIG_GBLUR_FILTER { "vf_gblur", checkasm_check_vf_gblur }, #endif @@ -177,6 +193,7 @@ #endif #if CONFIG_SWSCALE { "sw_rgb", checkasm_check_sw_rgb }, + { "sw_scale", checkasm_check_sw_scale }, #endif #if CONFIG_AVUTIL { "fixed_dsp", checkasm_check_fixed_dsp }, @@ -206,6 +223,9 @@ { "ALTIVEC", "altivec", AV_CPU_FLAG_ALTIVEC }, { "VSX", "vsx", AV_CPU_FLAG_VSX }, { "POWER8", "power8", AV_CPU_FLAG_POWER8 }, +#elif ARCH_MIPS + { "MMI", "mmi", AV_CPU_FLAG_MMI }, + { "MSA", "msa", AV_CPU_FLAG_MSA }, #elif ARCH_X86 { "MMX", "mmx", AV_CPU_FLAG_MMX|AV_CPU_FLAG_CMOV }, { "MMXEXT", "mmxext", AV_CPU_FLAG_MMXEXT }, @@ -262,6 +282,7 @@ int cpu_flag; const char *cpu_flag_name; const char *test_name; + int verbose; } state; /* PRNG state */ @@ -368,7 +389,7 @@ static int use_color = -1; va_list arg; -#if HAVE_SETCONSOLETEXTATTRIBUTE +#if HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE static HANDLE con; static WORD org_attributes; @@ -397,7 +418,7 @@ va_end(arg); if (use_color) { -#if HAVE_SETCONSOLETEXTATTRIBUTE +#if HAVE_SETCONSOLETEXTATTRIBUTE && HAVE_GETSTDHANDLE SetConsoleTextAttribute(con, org_attributes); #else fprintf(stderr, "\x1b[0m"); @@ -680,6 +701,8 @@ state.bench_pattern = ""; } else if (!strncmp(argv[1], "--test=", 7)) { state.test_name = argv[1] + 7; + } else if (!strcmp(argv[1], "--verbose") || !strcmp(argv[1], "-v")) { + state.verbose = 1; } else { seed = strtoul(argv[1], NULL, 10); } @@ -830,3 +853,42 @@ max_length = length; } } + +#define DEF_CHECKASM_CHECK_FUNC(type, fmt) \ +int checkasm_check_##type(const char *const file, const int line, \ + const type *buf1, ptrdiff_t stride1, \ + const type *buf2, ptrdiff_t stride2, \ + const int w, int h, const char *const name) \ +{ \ + int y = 0; \ + stride1 /= sizeof(*buf1); \ + stride2 /= sizeof(*buf2); \ + for (y = 0; y < h; y++) \ + if (memcmp(&buf1[y*stride1], &buf2[y*stride2], w*sizeof(*buf1))) \ + break; \ + if (y == h) \ + return 0; \ + checkasm_fail_func("%s:%d", file, line); \ + if (!state.verbose) \ + return 1; \ + fprintf(stderr, "%s:\n", name); \ + while (h--) { \ + for (int x = 0; x < w; x++) \ + fprintf(stderr, " " fmt, buf1[x]); \ + fprintf(stderr, " "); \ + for (int x = 0; x < w; x++) \ + fprintf(stderr, " " fmt, buf2[x]); \ + fprintf(stderr, " "); \ + for (int x = 0; x < w; x++) \ + fprintf(stderr, "%c", buf1[x] != buf2[x] ? 'x' : '.'); \ + buf1 += stride1; \ + buf2 += stride2; \ + fprintf(stderr, "\n"); \ + } \ + return 1; \ +} + +DEF_CHECKASM_CHECK_FUNC(uint8_t, "%02x") +DEF_CHECKASM_CHECK_FUNC(uint16_t, "%04x") +DEF_CHECKASM_CHECK_FUNC(int16_t, "%6d") +DEF_CHECKASM_CHECK_FUNC(int32_t, "%9d") diff -Nru ffmpeg-4.2.2/tests/checkasm/checkasm.h ffmpeg-4.4/tests/checkasm/checkasm.h --- ffmpeg-4.2.2/tests/checkasm/checkasm.h 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/checkasm.h 2021-04-08 21:28:40.000000000 +0000 @@ -58,19 +58,32 @@ void checkasm_check_h264qpel(void); void checkasm_check_hevc_add_res(void); void checkasm_check_hevc_idct(void); +void checkasm_check_hevc_qpel(void); +void checkasm_check_hevc_qpel_uni(void); +void checkasm_check_hevc_qpel_uni_w(void); +void checkasm_check_hevc_qpel_bi(void); +void checkasm_check_hevc_qpel_bi_w(void); +void checkasm_check_hevc_epel(void); +void checkasm_check_hevc_epel_uni(void); +void checkasm_check_hevc_epel_uni_w(void); +void checkasm_check_hevc_epel_bi(void); +void checkasm_check_hevc_epel_bi_w(void); void checkasm_check_hevc_sao(void); void checkasm_check_huffyuvdsp(void); void checkasm_check_jpeg2000dsp(void); void checkasm_check_llviddsp(void); void checkasm_check_llviddspenc(void); void checkasm_check_nlmeans(void); +void checkasm_check_opusdsp(void); void checkasm_check_pixblockdsp(void); void checkasm_check_sbrdsp(void); void checkasm_check_synth_filter(void); void checkasm_check_sw_rgb(void); +void checkasm_check_sw_scale(void); void checkasm_check_utvideodsp(void); void checkasm_check_v210dec(void); void checkasm_check_v210enc(void); +void checkasm_check_vf_eq(void); void checkasm_check_vf_gblur(void); void checkasm_check_vf_hflip(void); void checkasm_check_vf_threshold(void); @@ -174,17 +187,22 @@ void checkasm_checked_call_vfp(void *func, int dummy, ...); void checkasm_checked_call_novfp(void *func, int dummy, ...); extern void (*checkasm_checked_call)(void *func, int dummy, ...); -#define declare_new(ret, ...) ret (*checked_call)(void *, int dummy, __VA_ARGS__) = (void *)checkasm_checked_call; -#define call_new(...) checked_call(func_new, 0, __VA_ARGS__) +#define declare_new(ret, ...) ret (*checked_call)(void *, int dummy, __VA_ARGS__, \ + int, int, int, int, int, int, int, int, \ + int, int, int, int, int, int, int) = (void *)checkasm_checked_call; +#define call_new(...) checked_call(func_new, 0, __VA_ARGS__, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0) #elif ARCH_AARCH64 && !defined(__APPLE__) void checkasm_stack_clobber(uint64_t clobber, ...); void checkasm_checked_call(void *func, ...); -#define declare_new(ret, ...) ret (*checked_call)(void *, int, int, int, int, int, int, int, __VA_ARGS__)\ +#define declare_new(ret, ...) ret (*checked_call)(void *, int, int, int, int, int, int, int, __VA_ARGS__,\ + int, int, int, int, int, int, int, int,\ + int, int, int, int, int, int, int)\ = (void *)checkasm_checked_call; #define CLOB (UINT64_C(0xdeadbeefdeadbeef)) #define call_new(...) (checkasm_stack_clobber(CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,\ CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB,CLOB),\ - checked_call(func_new, 0, 0, 0, 0, 0, 0, 0, __VA_ARGS__)) + checked_call(func_new, 0, 0, 0, 0, 0, 0, 0, __VA_ARGS__,\ + 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0)) #else #define declare_new(ret, ...) #define declare_new_float(ret, ...) @@ -255,4 +273,20 @@ #define PERF_STOP(t) while(0) #endif +#define DECL_CHECKASM_CHECK_FUNC(type) \ +int checkasm_check_##type(const char *const file, const int line, \ + const type *const buf1, const ptrdiff_t stride1, \ + const type *const buf2, const ptrdiff_t stride2, \ + const int w, const int h, const char *const name) + +DECL_CHECKASM_CHECK_FUNC(uint8_t); +DECL_CHECKASM_CHECK_FUNC(uint16_t); +DECL_CHECKASM_CHECK_FUNC(int16_t); +DECL_CHECKASM_CHECK_FUNC(int32_t); + +#define PASTE(a,b) a ## b +#define CONCAT(a,b) PASTE(a,b) + +#define checkasm_check(prefix, ...) CONCAT(checkasm_check_, prefix)(__FILE__, __LINE__, __VA_ARGS__) + #endif /* TESTS_CHECKASM_CHECKASM_H */ diff -Nru ffmpeg-4.2.2/tests/checkasm/exrdsp.c ffmpeg-4.4/tests/checkasm/exrdsp.c --- ffmpeg-4.2.2/tests/checkasm/exrdsp.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/exrdsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavcodec/avcodec.h" #include "libavcodec/exrdsp.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #define BUF_SIZE 5120 #define PADDED_BUF_SIZE BUF_SIZE+AV_INPUT_BUFFER_PADDING_SIZE*2 diff -Nru ffmpeg-4.2.2/tests/checkasm/fixed_dsp.c ffmpeg-4.4/tests/checkasm/fixed_dsp.c --- ffmpeg-4.2.2/tests/checkasm/fixed_dsp.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/fixed_dsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/fixed_dsp.h" #include "libavutil/internal.h" #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #define BUF_SIZE 256 diff -Nru ffmpeg-4.2.2/tests/checkasm/flacdsp.c ffmpeg-4.4/tests/checkasm/flacdsp.c --- ffmpeg-4.2.2/tests/checkasm/flacdsp.c 2018-07-17 09:27:43.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/flacdsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #define BUF_SIZE 256 #define MAX_CHANNELS 8 diff -Nru ffmpeg-4.2.2/tests/checkasm/float_dsp.c ffmpeg-4.4/tests/checkasm/float_dsp.c --- ffmpeg-4.2.2/tests/checkasm/float_dsp.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/float_dsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,6 +23,8 @@ #include "libavutil/float_dsp.h" #include "libavutil/internal.h" +#include "libavutil/mem_internal.h" + #include "checkasm.h" #define LEN 256 @@ -51,7 +53,8 @@ call_ref(cdst, src0, src1, LEN); call_new(odst, src0, src1, LEN); for (i = 0; i < LEN; i++) { - if (!float_near_abs_eps(cdst[i], odst[i], FLT_EPSILON)) { + double t = fabs(src0[i]) + fabs(src1[i]) + fabs(src0[i] * src1[i]) + 1.0; + if (!float_near_abs_eps(cdst[i], odst[i], t * 2 * FLT_EPSILON)) { fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n", i, cdst[i], odst[i], cdst[i] - odst[i]); fail(); @@ -73,7 +76,8 @@ call_ref(cdst, src0, src1, LEN); call_new(odst, src0, src1, LEN); for (i = 0; i < LEN; i++) { - if (!double_near_abs_eps(cdst[i], odst[i], DBL_EPSILON)) { + double t = fabs(src0[i]) + fabs(src1[i]) + fabs(src0[i] * src1[i]) + 1.0; + if (!double_near_abs_eps(cdst[i], odst[i], t * 2 * DBL_EPSILON)) { fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n", i, cdst[i], odst[i], cdst[i] - odst[i]); fail(); @@ -117,7 +121,8 @@ call_ref(cdst, src0, src1[0], LEN); call_new(odst, src0, src1[0], LEN); for (i = 0; i < LEN; i++) { - if (!float_near_abs_eps(cdst[i], odst[i], FLT_EPSILON)) { + double t = fabs(src0[i]) + fabs(src1[0]) + fabs(src0[i] * src1[0]) + 1.0; + if (!float_near_abs_eps(cdst[i], odst[i], t * 2 * FLT_EPSILON)) { fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n", i, cdst[i], odst[i], cdst[i] - odst[i]); fail(); diff -Nru ffmpeg-4.2.2/tests/checkasm/fmtconvert.c ffmpeg-4.4/tests/checkasm/fmtconvert.c --- ffmpeg-4.2.2/tests/checkasm/fmtconvert.c 2018-07-17 09:27:43.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/fmtconvert.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,8 @@ #include "libavutil/internal.h" #include "libavutil/common.h" +#include "libavutil/mem_internal.h" + #include "libavcodec/fmtconvert.h" #include "checkasm.h" diff -Nru ffmpeg-4.2.2/tests/checkasm/h264dsp.c ffmpeg-4.4/tests/checkasm/h264dsp.c --- ffmpeg-4.2.2/tests/checkasm/h264dsp.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/h264dsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -26,6 +26,7 @@ #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" static const uint32_t pixel_mask[3] = { 0xffffffff, 0x01ff01ff, 0x03ff03ff }; static const uint32_t pixel_mask_lf[3] = { 0xff0fff0f, 0x01ff000f, 0x03ff000f }; diff -Nru ffmpeg-4.2.2/tests/checkasm/h264pred.c ffmpeg-4.4/tests/checkasm/h264pred.c --- ffmpeg-4.2.2/tests/checkasm/h264pred.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/h264pred.c 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,7 @@ #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" static const int codec_ids[4] = { AV_CODEC_ID_H264, AV_CODEC_ID_VP8, AV_CODEC_ID_RV40, AV_CODEC_ID_SVQ3 }; diff -Nru ffmpeg-4.2.2/tests/checkasm/h264qpel.c ffmpeg-4.4/tests/checkasm/h264qpel.c --- ffmpeg-4.2.2/tests/checkasm/h264qpel.c 2018-07-17 09:27:43.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/h264qpel.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" static const uint32_t pixel_mask[3] = { 0xffffffff, 0x01ff01ff, 0x03ff03ff }; diff -Nru ffmpeg-4.2.2/tests/checkasm/hevc_add_res.c ffmpeg-4.4/tests/checkasm/hevc_add_res.c --- ffmpeg-4.2.2/tests/checkasm/hevc_add_res.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/hevc_add_res.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,6 +21,7 @@ #include #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #include "libavcodec/hevcdsp.h" @@ -42,31 +43,42 @@ AV_WN16A(buf + j * 2, rnd() & 0x3FF); \ } while (0) -static void check_add_res(HEVCDSPContext h, int bit_depth) +static void compare_add_res(int size, ptrdiff_t stride, int overflow_test) { - int i; LOCAL_ALIGNED_32(int16_t, res0, [32 * 32]); LOCAL_ALIGNED_32(int16_t, res1, [32 * 32]); LOCAL_ALIGNED_32(uint8_t, dst0, [32 * 32 * 2]); LOCAL_ALIGNED_32(uint8_t, dst1, [32 * 32 * 2]); + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, int16_t *res, ptrdiff_t stride); + + randomize_buffers(res0, size); + randomize_buffers2(dst0, size); + if (overflow_test) + res0[0] = 0x8000; + memcpy(res1, res0, sizeof(*res0) * size); + memcpy(dst1, dst0, sizeof(int16_t) * size); + + call_ref(dst0, res0, stride); + call_new(dst1, res1, stride); + if (memcmp(dst0, dst1, size)) + fail(); + bench_new(dst1, res1, stride); +} + +static void check_add_res(HEVCDSPContext h, int bit_depth) +{ + int i; + for (i = 2; i <= 5; i++) { int block_size = 1 << i; int size = block_size * block_size; ptrdiff_t stride = block_size << (bit_depth > 8); - declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *dst, int16_t *res, ptrdiff_t stride); - - randomize_buffers(res0, size); - randomize_buffers2(dst0, size); - memcpy(res1, res0, sizeof(*res0) * size); - memcpy(dst1, dst0, sizeof(int16_t) * size); if (check_func(h.add_residual[i - 2], "hevc_add_res_%dx%d_%d", block_size, block_size, bit_depth)) { - call_ref(dst0, res0, stride); - call_new(dst1, res1, stride); - if (memcmp(dst0, dst1, size)) - fail(); - bench_new(dst1, res1, stride); + compare_add_res(size, stride, 0); + // overflow test for res = -32768 + compare_add_res(size, stride, 1); } } } diff -Nru ffmpeg-4.2.2/tests/checkasm/hevc_idct.c ffmpeg-4.4/tests/checkasm/hevc_idct.c --- ffmpeg-4.2.2/tests/checkasm/hevc_idct.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/hevc_idct.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,6 +21,7 @@ #include #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #include "libavcodec/hevcdsp.h" diff -Nru ffmpeg-4.2.2/tests/checkasm/hevc_pel.c ffmpeg-4.4/tests/checkasm/hevc_pel.c --- ffmpeg-4.2.2/tests/checkasm/hevc_pel.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/hevc_pel.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,524 @@ +/* + * Copyright (c) 2015 Henrik Gramner + * Copyright (c) 2021 Josh Dekker + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "checkasm.h" +#include "libavcodec/hevcdsp.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" + +static const uint32_t pixel_mask[] = { 0xffffffff, 0x01ff01ff, 0x03ff03ff, 0x07ff07ff, 0x0fff0fff }; +static const uint32_t pixel_mask16[] = { 0x00ff00ff, 0x01ff01ff, 0x03ff03ff, 0x07ff07ff, 0x0fff0fff }; +static const int sizes[] = { -1, 4, 6, 8, 12, 16, 24, 32, 48, 64 }; +static const int weights[] = { 0, 128, 255, -1 }; +static const int denoms[] = {0, 7, 12, -1 }; +static const int offsets[] = {0, 255, -1 }; + +#define SIZEOF_PIXEL ((bit_depth + 7) / 8) +#define BUF_SIZE (2 * MAX_PB_SIZE * (2 * 4 + MAX_PB_SIZE)) + +#define randomize_buffers() \ + do { \ + uint32_t mask = pixel_mask[bit_depth - 8]; \ + int k; \ + for (k = 0; k < BUF_SIZE; k += 4) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(buf0 + k, r); \ + AV_WN32A(buf1 + k, r); \ + r = rnd(); \ + AV_WN32A(dst0 + k, r); \ + AV_WN32A(dst1 + k, r); \ + } \ + } while (0) + +#define randomize_buffers_ref() \ + randomize_buffers(); \ + do { \ + uint32_t mask = pixel_mask16[bit_depth - 8]; \ + int k; \ + for (k = 0; k < BUF_SIZE; k += 2) { \ + uint32_t r = rnd() & mask; \ + AV_WN32A(ref0 + k, r); \ + AV_WN32A(ref1 + k, r); \ + } \ + } while (0) + +#define src0 (buf0 + 2 * 4 * MAX_PB_SIZE) /* hevc qpel functions read data from negative src pointer offsets */ +#define src1 (buf1 + 2 * 4 * MAX_PB_SIZE) + +void checkasm_check_hevc_qpel(void) +{ + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [BUF_SIZE]); + + HEVCDSPContext h; + int size, bit_depth, i, j, row; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, int16_t *dst, uint8_t *src, ptrdiff_t srcstride, + int height, intptr_t mx, intptr_t my, int width); + + for (bit_depth = 8; bit_depth <= 12; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (size = 1; size < 10; size++) { + const char *type; + switch ((j << 1) | i) { + case 0: type = "pel_pixels"; break; // 0 0 + case 1: type = "qpel_h"; break; // 0 1 + case 2: type = "qpel_v"; break; // 1 0 + case 3: type = "qpel_hv"; break; // 1 1 + } + + if (check_func(h.put_hevc_qpel[size][j][i], "put_hevc_%s%d_%d", type, sizes[size], bit_depth)) { + int16_t *dstw0 = (int16_t *) dst0, *dstw1 = (int16_t *) dst1; + randomize_buffers(); + call_ref(dstw0, src0, sizes[size] * SIZEOF_PIXEL, sizes[size], i, j, sizes[size]); + call_new(dstw1, src1, sizes[size] * SIZEOF_PIXEL, sizes[size], i, j, sizes[size]); + for (row = 0; row < size[sizes]; row++) { + if (memcmp(dstw0 + row * MAX_PB_SIZE, dstw1 + row * MAX_PB_SIZE, sizes[size] * SIZEOF_PIXEL)) + fail(); + } + bench_new(dstw1, src1, sizes[size] * SIZEOF_PIXEL, sizes[size], i, j, sizes[size]); + } + } + } + } + } + report("qpel"); +} + +void checkasm_check_hevc_qpel_uni(void) +{ + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [BUF_SIZE]); + + HEVCDSPContext h; + int size, bit_depth, i, j; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int height, intptr_t mx, intptr_t my, int width); + + for (bit_depth = 8; bit_depth <= 12; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (size = 1; size < 10; size++) { + const char *type; + switch ((j << 1) | i) { + case 0: type = "pel_uni_pixels"; break; // 0 0 + case 1: type = "qpel_uni_h"; break; // 0 1 + case 2: type = "qpel_uni_v"; break; // 1 0 + case 3: type = "qpel_uni_hv"; break; // 1 1 + } + + if (check_func(h.put_hevc_qpel_uni[size][j][i], "put_hevc_%s%d_%d", type, sizes[size], bit_depth)) { + randomize_buffers(); + call_ref(dst0, sizes[size] * SIZEOF_PIXEL, src0, sizes[size] * SIZEOF_PIXEL, sizes[size], i, j, sizes[size]); + call_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, sizes[size], i, j, sizes[size]); + if (memcmp(dst0, dst1, sizes[size] * sizes[size] * SIZEOF_PIXEL)) + fail(); + bench_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, sizes[size], i, j, sizes[size]); + } + } + } + } + } + report("qpel_uni"); +} + +void checkasm_check_hevc_qpel_uni_w(void) +{ + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [BUF_SIZE]); + + HEVCDSPContext h; + int size, bit_depth, i, j; + const int *denom, *wx, *ox; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width); + + for (bit_depth = 8; bit_depth <= 12; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (size = 1; size < 10; size++) { + const char *type; + switch ((j << 1) | i) { + case 0: type = "pel_uni_w_pixels"; break; // 0 0 + case 1: type = "qpel_uni_w_h"; break; // 0 1 + case 2: type = "qpel_uni_w_v"; break; // 1 0 + case 3: type = "qpel_uni_w_hv"; break; // 1 1 + } + + if (check_func(h.put_hevc_qpel_uni_w[size][j][i], "put_hevc_%s%d_%d", type, sizes[size], bit_depth)) { + for (denom = denoms; *denom >= 0; denom++) { + for (wx = weights; *wx >= 0; wx++) { + for (ox = offsets; *ox >= 0; ox++) { + randomize_buffers(); + call_ref(dst0, sizes[size] * SIZEOF_PIXEL, src0, sizes[size] * SIZEOF_PIXEL, sizes[size], *denom, *wx, *ox, i, j, sizes[size]); + call_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, sizes[size], *denom, *wx, *ox, i, j, sizes[size]); + if (memcmp(dst0, dst1, sizes[size] * sizes[size] * SIZEOF_PIXEL)) + fail(); + bench_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, sizes[size], *denom, *wx, *ox, i, j, sizes[size]); + } + } + } + } + } + } + } + } + report("qpel_uni_w"); +} + +void checkasm_check_hevc_qpel_bi(void) +{ + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [BUF_SIZE]); + LOCAL_ALIGNED_32(int16_t, ref0, [BUF_SIZE]); + LOCAL_ALIGNED_32(int16_t, ref1, [BUF_SIZE]); + + HEVCDSPContext h; + int size, bit_depth, i, j; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int16_t *src2, + int height, intptr_t mx, intptr_t my, int width); + + for (bit_depth = 8; bit_depth <= 12; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (size = 1; size < 10; size++) { + const char *type; + switch ((j << 1) | i) { + case 0: type = "pel_bi_pixels"; break; // 0 0 + case 1: type = "qpel_bi_h"; break; // 0 1 + case 2: type = "qpel_bi_v"; break; // 1 0 + case 3: type = "qpel_bi_hv"; break; // 1 1 + } + + if (check_func(h.put_hevc_qpel_bi[size][j][i], "put_hevc_%s%d_%d", type, sizes[size], bit_depth)) { + randomize_buffers_ref(); + call_ref(dst0, sizes[size] * SIZEOF_PIXEL, src0, sizes[size] * SIZEOF_PIXEL, ref0, sizes[size], i, j, sizes[size]); + call_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, ref1, sizes[size], i, j, sizes[size]); + if (memcmp(dst0, dst1, sizes[size] * sizes[size] * SIZEOF_PIXEL)) + fail(); + bench_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, ref1, sizes[size], i, j, sizes[size]); + } + } + } + } + } + report("qpel_bi"); +} + +void checkasm_check_hevc_qpel_bi_w(void) +{ + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [BUF_SIZE]); + LOCAL_ALIGNED_32(int16_t, ref0, [BUF_SIZE]); + LOCAL_ALIGNED_32(int16_t, ref1, [BUF_SIZE]); + + HEVCDSPContext h; + int size, bit_depth, i, j; + const int *denom, *wx, *ox; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int16_t *src2, + int height, int denom, int wx0, int wx1, + int ox0, int ox1, intptr_t mx, intptr_t my, int width); + + for (bit_depth = 8; bit_depth <= 12; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (size = 1; size < 10; size++) { + const char *type; + switch ((j << 1) | i) { + case 0: type = "pel_bi_w_pixels"; break; // 0 0 + case 1: type = "qpel_bi_w_h"; break; // 0 1 + case 2: type = "qpel_bi_w_v"; break; // 1 0 + case 3: type = "qpel_bi_w_hv"; break; // 1 1 + } + + if (check_func(h.put_hevc_qpel_bi_w[size][j][i], "put_hevc_%s%d_%d", type, sizes[size], bit_depth)) { + for (denom = denoms; *denom >= 0; denom++) { + for (wx = weights; *wx >= 0; wx++) { + for (ox = offsets; *ox >= 0; ox++) { + randomize_buffers_ref(); + call_ref(dst0, sizes[size] * SIZEOF_PIXEL, src0, sizes[size] * SIZEOF_PIXEL, ref0, sizes[size], *denom, *wx, *wx, *ox, *ox, i, j, sizes[size]); + call_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, ref1, sizes[size], *denom, *wx, *wx, *ox, *ox, i, j, sizes[size]); + if (memcmp(dst0, dst1, sizes[size] * sizes[size] * SIZEOF_PIXEL)) + fail(); + bench_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, ref1, sizes[size], *denom, *wx, *wx, *ox, *ox, i, j, sizes[size]); + } + } + } + } + } + } + } + } + report("qpel_bi_w"); +} + +void checkasm_check_hevc_epel(void) +{ + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [BUF_SIZE]); + + HEVCDSPContext h; + int size, bit_depth, i, j, row; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, int16_t *dst, uint8_t *src, ptrdiff_t srcstride, + int height, intptr_t mx, intptr_t my, int width); + + for (bit_depth = 8; bit_depth <= 12; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (size = 1; size < 10; size++) { + const char *type; + switch ((j << 1) | i) { + case 0: type = "pel_pixels"; break; // 0 0 + case 1: type = "epel_h"; break; // 0 1 + case 2: type = "epel_v"; break; // 1 0 + case 3: type = "epel_hv"; break; // 1 1 + } + + if (check_func(h.put_hevc_epel[size][j][i], "put_hevc_%s%d_%d", type, sizes[size], bit_depth)) { + int16_t *dstw0 = (int16_t *) dst0, *dstw1 = (int16_t *) dst1; + randomize_buffers(); + call_ref(dstw0, src0, sizes[size] * SIZEOF_PIXEL, sizes[size], i, j, sizes[size]); + call_new(dstw1, src1, sizes[size] * SIZEOF_PIXEL, sizes[size], i, j, sizes[size]); + for (row = 0; row < size[sizes]; row++) { + if (memcmp(dstw0 + row * MAX_PB_SIZE, dstw1 + row * MAX_PB_SIZE, sizes[size] * SIZEOF_PIXEL)) + fail(); + } + bench_new(dstw1, src1, sizes[size] * SIZEOF_PIXEL, sizes[size], i, j, sizes[size]); + } + } + } + } + } + report("epel"); +} + +void checkasm_check_hevc_epel_uni(void) +{ + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [BUF_SIZE]); + + HEVCDSPContext h; + int size, bit_depth, i, j; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int height, intptr_t mx, intptr_t my, int width); + + for (bit_depth = 8; bit_depth <= 12; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (size = 1; size < 10; size++) { + const char *type; + switch ((j << 1) | i) { + case 0: type = "pel_uni_pixels"; break; // 0 0 + case 1: type = "epel_uni_h"; break; // 0 1 + case 2: type = "epel_uni_v"; break; // 1 0 + case 3: type = "epel_uni_hv"; break; // 1 1 + } + + if (check_func(h.put_hevc_epel_uni[size][j][i], "put_hevc_%s%d_%d", type, sizes[size], bit_depth)) { + randomize_buffers(); + call_ref(dst0, sizes[size] * SIZEOF_PIXEL, src0, sizes[size] * SIZEOF_PIXEL, sizes[size], i, j, sizes[size]); + call_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, sizes[size], i, j, sizes[size]); + if (memcmp(dst0, dst1, sizes[size] * sizes[size] * SIZEOF_PIXEL)) + fail(); + bench_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, sizes[size], i, j, sizes[size]); + } + } + } + } + } + report("epel_uni"); +} + +void checkasm_check_hevc_epel_uni_w(void) +{ + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [BUF_SIZE]); + + HEVCDSPContext h; + int size, bit_depth, i, j; + const int *denom, *wx, *ox; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width); + + for (bit_depth = 8; bit_depth <= 12; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (size = 1; size < 10; size++) { + const char *type; + switch ((j << 1) | i) { + case 0: type = "pel_uni_w_pixels"; break; // 0 0 + case 1: type = "epel_uni_w_h"; break; // 0 1 + case 2: type = "epel_uni_w_v"; break; // 1 0 + case 3: type = "epel_uni_w_hv"; break; // 1 1 + } + + if (check_func(h.put_hevc_epel_uni_w[size][j][i], "put_hevc_%s%d_%d", type, sizes[size], bit_depth)) { + for (denom = denoms; *denom >= 0; denom++) { + for (wx = weights; *wx >= 0; wx++) { + for (ox = offsets; *ox >= 0; ox++) { + randomize_buffers(); + call_ref(dst0, sizes[size] * SIZEOF_PIXEL, src0, sizes[size] * SIZEOF_PIXEL, sizes[size], *denom, *wx, *ox, i, j, sizes[size]); + call_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, sizes[size], *denom, *wx, *ox, i, j, sizes[size]); + if (memcmp(dst0, dst1, sizes[size] * sizes[size] * SIZEOF_PIXEL)) + fail(); + bench_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, sizes[size], *denom, *wx, *ox, i, j, sizes[size]); + } + } + } + } + } + } + } + } + report("epel_uni_w"); +} + +void checkasm_check_hevc_epel_bi(void) +{ + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [BUF_SIZE]); + LOCAL_ALIGNED_32(int16_t, ref0, [BUF_SIZE]); + LOCAL_ALIGNED_32(int16_t, ref1, [BUF_SIZE]); + + HEVCDSPContext h; + int size, bit_depth, i, j; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int16_t *src2, + int height, intptr_t mx, intptr_t my, int width); + + for (bit_depth = 8; bit_depth <= 12; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (size = 1; size < 10; size++) { + const char *type; + switch ((j << 1) | i) { + case 0: type = "pel_bi_pixels"; break; // 0 0 + case 1: type = "epel_bi_h"; break; // 0 1 + case 2: type = "epel_bi_v"; break; // 1 0 + case 3: type = "epel_bi_hv"; break; // 1 1 + } + + if (check_func(h.put_hevc_epel_bi[size][j][i], "put_hevc_%s%d_%d", type, sizes[size], bit_depth)) { + randomize_buffers_ref(); + call_ref(dst0, sizes[size] * SIZEOF_PIXEL, src0, sizes[size] * SIZEOF_PIXEL, ref0, sizes[size], i, j, sizes[size]); + call_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, ref1, sizes[size], i, j, sizes[size]); + if (memcmp(dst0, dst1, sizes[size] * sizes[size] * SIZEOF_PIXEL)) + fail(); + bench_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, ref1, sizes[size], i, j, sizes[size]); + } + } + } + } + } + report("epel_bi"); +} + +void checkasm_check_hevc_epel_bi_w(void) +{ + LOCAL_ALIGNED_32(uint8_t, buf0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, buf1, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst0, [BUF_SIZE]); + LOCAL_ALIGNED_32(uint8_t, dst1, [BUF_SIZE]); + LOCAL_ALIGNED_32(int16_t, ref0, [BUF_SIZE]); + LOCAL_ALIGNED_32(int16_t, ref1, [BUF_SIZE]); + + HEVCDSPContext h; + int size, bit_depth, i, j; + const int *denom, *wx, *ox; + declare_func_emms(AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT, void, uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, + int16_t *src2, + int height, int denom, int wx0, int wx1, + int ox0, int ox1, intptr_t mx, intptr_t my, int width); + + for (bit_depth = 8; bit_depth <= 12; bit_depth++) { + ff_hevc_dsp_init(&h, bit_depth); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (size = 1; size < 10; size++) { + const char *type; + switch ((j << 1) | i) { + case 0: type = "pel_bi_w_pixels"; break; // 0 0 + case 1: type = "epel_bi_w_h"; break; // 0 1 + case 2: type = "epel_bi_w_v"; break; // 1 0 + case 3: type = "epel_bi_w_hv"; break; // 1 1 + } + + if (check_func(h.put_hevc_epel_bi_w[size][j][i], "put_hevc_%s%d_%d", type, sizes[size], bit_depth)) { + for (denom = denoms; *denom >= 0; denom++) { + for (wx = weights; *wx >= 0; wx++) { + for (ox = offsets; *ox >= 0; ox++) { + randomize_buffers_ref(); + call_ref(dst0, sizes[size] * SIZEOF_PIXEL, src0, sizes[size] * SIZEOF_PIXEL, ref0, sizes[size], *denom, *wx, *wx, *ox, *ox, i, j, sizes[size]); + call_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, ref1, sizes[size], *denom, *wx, *wx, *ox, *ox, i, j, sizes[size]); + if (memcmp(dst0, dst1, sizes[size] * sizes[size] * SIZEOF_PIXEL)) + fail(); + bench_new(dst1, sizes[size] * SIZEOF_PIXEL, src1, sizes[size] * SIZEOF_PIXEL, ref1, sizes[size], *denom, *wx, *wx, *ox, *ox, i, j, sizes[size]); + } + } + } + } + } + } + } + } + report("epel_bi_w"); +} diff -Nru ffmpeg-4.2.2/tests/checkasm/hevc_sao.c ffmpeg-4.4/tests/checkasm/hevc_sao.c --- ffmpeg-4.2.2/tests/checkasm/hevc_sao.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/hevc_sao.c 2021-04-08 21:28:40.000000000 +0000 @@ -21,6 +21,7 @@ #include #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #include "libavcodec/avcodec.h" diff -Nru ffmpeg-4.2.2/tests/checkasm/jpeg2000dsp.c ffmpeg-4.4/tests/checkasm/jpeg2000dsp.c --- ffmpeg-4.2.2/tests/checkasm/jpeg2000dsp.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/jpeg2000dsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #define BUF_SIZE 512 diff -Nru ffmpeg-4.2.2/tests/checkasm/llviddspenc.c ffmpeg-4.4/tests/checkasm/llviddspenc.c --- ffmpeg-4.2.2/tests/checkasm/llviddspenc.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/llviddspenc.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libavcodec/lossless_videoencdsp.h" diff -Nru ffmpeg-4.2.2/tests/checkasm/Makefile ffmpeg-4.4/tests/checkasm/Makefile --- ffmpeg-4.2.2/tests/checkasm/Makefile 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/Makefile 2021-04-08 21:28:40.000000000 +0000 @@ -22,8 +22,9 @@ AVCODECOBJS-$(CONFIG_EXR_DECODER) += exrdsp.o AVCODECOBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuvdsp.o AVCODECOBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dsp.o +AVCODECOBJS-$(CONFIG_OPUS_DECODER) += opusdsp.o AVCODECOBJS-$(CONFIG_PIXBLOCKDSP) += pixblockdsp.o -AVCODECOBJS-$(CONFIG_HEVC_DECODER) += hevc_add_res.o hevc_idct.o hevc_sao.o +AVCODECOBJS-$(CONFIG_HEVC_DECODER) += hevc_add_res.o hevc_idct.o hevc_sao.o hevc_pel.o AVCODECOBJS-$(CONFIG_UTVIDEO_DECODER) += utvideodsp.o AVCODECOBJS-$(CONFIG_V210_DECODER) += v210dec.o AVCODECOBJS-$(CONFIG_V210_ENCODER) += v210enc.o @@ -35,6 +36,7 @@ AVFILTEROBJS-$(CONFIG_AFIR_FILTER) += af_afir.o AVFILTEROBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o AVFILTEROBJS-$(CONFIG_COLORSPACE_FILTER) += vf_colorspace.o +AVFILTEROBJS-$(CONFIG_EQ_FILTER) += vf_eq.o AVFILTEROBJS-$(CONFIG_GBLUR_FILTER) += vf_gblur.o AVFILTEROBJS-$(CONFIG_HFLIP_FILTER) += vf_hflip.o AVFILTEROBJS-$(CONFIG_THRESHOLD_FILTER) += vf_threshold.o @@ -43,7 +45,7 @@ CHECKASMOBJS-$(CONFIG_AVFILTER) += $(AVFILTEROBJS-yes) # swscale tests -SWSCALEOBJS += sw_rgb.o +SWSCALEOBJS += sw_rgb.o sw_scale.o CHECKASMOBJS-$(CONFIG_SWSCALE) += $(SWSCALEOBJS) diff -Nru ffmpeg-4.2.2/tests/checkasm/opusdsp.c ffmpeg-4.4/tests/checkasm/opusdsp.c --- ffmpeg-4.2.2/tests/checkasm/opusdsp.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/opusdsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,105 @@ +/* + * 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 "libavutil/mem_internal.h" + +#include "libavcodec/opusdsp.h" + +#include "checkasm.h" + +#define randomize_float(buf, len) \ + do { \ + for (int i = 0; i < len; i++) { \ + float f = (float)rnd() / (UINT_MAX >> 5) - 16.0f; \ + buf[i] = f; \ + } \ + } while (0) + +#define EPS 0.005 +#define MAX_SIZE (960) + +/* period is between 15 and 1022, inclusive */ +static void test_postfilter(int period) +{ + LOCAL_ALIGNED(16, float, data0, [MAX_SIZE + 1024]); + LOCAL_ALIGNED(16, float, data1, [MAX_SIZE + 1024]); + + /* This filter can explode very easily, so use a tapset from the codec. + * In the codec these are usually multiplied by at least 0.09375f, + * so its outside the largest filter value, but the filter is still stable + * so use it. */ + float gains[3] = { 0.3066406250f, 0.2170410156f, 0.1296386719f }; + + /* The codec will always call with an offset which is aligned once + * (period + 2) is subtracted, but here we have to align it outselves. */ + int offset = FFALIGN(period + 2, 4); + + declare_func(void, float *data, int period, float *gains, int len); + + randomize_float(data0, MAX_SIZE + 1024); + memcpy(data1, data0, (MAX_SIZE + 1024)*sizeof(float)); + + call_ref(data0 + offset, period, gains, MAX_SIZE); + call_new(data1 + offset, period, gains, MAX_SIZE); + + if (!float_near_abs_eps_array(data0 + offset, data1 + offset, EPS, MAX_SIZE)) + fail(); + bench_new(data1 + offset, period, gains, MAX_SIZE); +} + +static void test_deemphasis(void) +{ + LOCAL_ALIGNED(16, float, src, [FFALIGN(MAX_SIZE, 4)]); + LOCAL_ALIGNED(16, float, dst0, [FFALIGN(MAX_SIZE, 4)]); + LOCAL_ALIGNED(16, float, dst1, [FFALIGN(MAX_SIZE, 4)]); + float coeff0 = (float)rnd() / (UINT_MAX >> 5) - 16.0f, coeff1 = coeff0; + + declare_func_float(float, float *out, float *in, float coeff, int len); + + randomize_float(src, MAX_SIZE); + + coeff0 = call_ref(dst0, src, coeff0, MAX_SIZE); + coeff1 = call_new(dst1, src, coeff1, MAX_SIZE); + + if (!float_near_abs_eps(coeff0, coeff1, EPS) || + !float_near_abs_eps_array(dst0, dst1, EPS, MAX_SIZE)) + fail(); + bench_new(dst1, src, coeff1, MAX_SIZE); +} + +void checkasm_check_opusdsp(void) +{ + OpusDSP ctx; + ff_opus_dsp_init(&ctx); + + if (check_func(ctx.postfilter, "postfilter_15")) + test_postfilter(15); + report("postfilter_15"); + + if (check_func(ctx.postfilter, "postfilter_512")) + test_postfilter(512); + report("postfilter_512"); + + if (check_func(ctx.postfilter, "postfilter_1022")) + test_postfilter(1022); + report("postfilter_1022"); + + if (check_func(ctx.deemphasis, "deemphasis")) + test_deemphasis(); + report("deemphasis"); +} diff -Nru ffmpeg-4.2.2/tests/checkasm/pixblockdsp.c ffmpeg-4.4/tests/checkasm/pixblockdsp.c --- ffmpeg-4.2.2/tests/checkasm/pixblockdsp.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/pixblockdsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #define BUF_UNITS 8 #define BUF_SIZE (BUF_UNITS * 128 + 8 * BUF_UNITS) @@ -44,13 +45,13 @@ } \ } while (0) -#define check_get_pixels(type) \ +#define check_get_pixels(type, aligned) \ do { \ int i; \ declare_func_emms(AV_CPU_FLAG_MMX, void, int16_t *block, const uint8_t *pixels, ptrdiff_t line_size); \ \ for (i = 0; i < BUF_UNITS; i++) { \ - int src_offset = i * 64 * sizeof(type) + 8 * i; /* Test various alignments */ \ + int src_offset = i * 64 * sizeof(type) + (aligned ? 8 : 1) * i; \ int dst_offset = i * 64; /* dst must be aligned */ \ randomize_buffers(); \ call_ref(dst0 + dst_offset, src10 + src_offset, 8); \ @@ -61,13 +62,13 @@ } \ } while (0) -#define check_diff_pixels(type) \ +#define check_diff_pixels(type, aligned) \ do { \ int i; \ declare_func_emms(AV_CPU_FLAG_MMX, void, int16_t *av_restrict block, const uint8_t *s1, const uint8_t *s2, ptrdiff_t stride); \ \ for (i = 0; i < BUF_UNITS; i++) { \ - int src_offset = i * 64 * sizeof(type) + 8 * i; /* Test various alignments */ \ + int src_offset = i * 64 * sizeof(type) + (aligned ? 8 : 1) * i; \ int dst_offset = i * 64; /* dst must be aligned */ \ randomize_buffers(); \ call_ref(dst0 + dst_offset, src10 + src_offset, src20 + src_offset, 8); \ @@ -96,12 +97,16 @@ ff_pixblockdsp_init(&h, &avctx); if (check_func(h.get_pixels, "get_pixels")) - check_get_pixels(uint8_t); + check_get_pixels(uint8_t, 1); + if (check_func(h.get_pixels_unaligned, "get_pixels_unaligned")) + check_get_pixels(uint8_t, 0); report("get_pixels"); if (check_func(h.diff_pixels, "diff_pixels")) - check_diff_pixels(uint8_t); + check_diff_pixels(uint8_t, 1); + if (check_func(h.diff_pixels_unaligned, "diff_pixels_unaligned")) + check_diff_pixels(uint8_t, 0); report("diff_pixels"); } diff -Nru ffmpeg-4.2.2/tests/checkasm/sbrdsp.c ffmpeg-4.4/tests/checkasm/sbrdsp.c --- ffmpeg-4.2.2/tests/checkasm/sbrdsp.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/sbrdsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -16,7 +16,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "libavutil/mem_internal.h" + #include "libavcodec/sbrdsp.h" +#include #include "checkasm.h" @@ -51,13 +54,14 @@ INTFLOAT res0; INTFLOAT res1; LOCAL_ALIGNED_16(INTFLOAT, src, [256], [2]); + double t = 4 * 256; declare_func_float(INTFLOAT, INTFLOAT (*x)[2], int n); randomize((INTFLOAT *)src, 256 * 2); res0 = call_ref(src, 256); res1 = call_new(src, 256); - if (!float_near_abs_eps(res0, res1, EPS)) + if (!float_near_abs_eps(res0, res1, t * 2 * FLT_EPSILON)) fail(); bench_new(src, 256); } diff -Nru ffmpeg-4.2.2/tests/checkasm/sw_rgb.c ffmpeg-4.4/tests/checkasm/sw_rgb.c --- ffmpeg-4.2.2/tests/checkasm/sw_rgb.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/sw_rgb.c 2021-04-08 21:28:40.000000000 +0000 @@ -22,6 +22,7 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" +#include "libavutil/mem_internal.h" #include "libswscale/rgb2rgb.h" @@ -111,6 +112,74 @@ } } +static void check_interleave_bytes(void) +{ + LOCAL_ALIGNED_16(uint8_t, src0_buf, [MAX_STRIDE*MAX_HEIGHT+1]); + LOCAL_ALIGNED_16(uint8_t, src1_buf, [MAX_STRIDE*MAX_HEIGHT+1]); + LOCAL_ALIGNED_16(uint8_t, dst0_buf, [2*MAX_STRIDE*MAX_HEIGHT+2]); + LOCAL_ALIGNED_16(uint8_t, dst1_buf, [2*MAX_STRIDE*MAX_HEIGHT+2]); + // Intentionally using unaligned buffers, as this function doesn't have + // any alignment requirements. + uint8_t *src0 = src0_buf + 1; + uint8_t *src1 = src1_buf + 1; + uint8_t *dst0 = dst0_buf + 2; + uint8_t *dst1 = dst1_buf + 2; + + declare_func_emms(AV_CPU_FLAG_MMX, void, const uint8_t *, const uint8_t *, + uint8_t *, int, int, int, int, int); + + randomize_buffers(src0, MAX_STRIDE * MAX_HEIGHT); + randomize_buffers(src1, MAX_STRIDE * MAX_HEIGHT); + + if (check_func(interleaveBytes, "interleave_bytes")) { + for (int i = 0; i <= 16; i++) { + // Try all widths [1,16], and try one random width. + + int w = i > 0 ? i : (1 + (rnd() % (MAX_STRIDE-2))); + int h = 1 + (rnd() % (MAX_HEIGHT-2)); + + int src0_offset = 0, src0_stride = MAX_STRIDE; + int src1_offset = 0, src1_stride = MAX_STRIDE; + int dst_offset = 0, dst_stride = 2 * MAX_STRIDE; + + memset(dst0, 0, 2 * MAX_STRIDE * MAX_HEIGHT); + memset(dst1, 0, 2 * MAX_STRIDE * MAX_HEIGHT); + + // Try different combinations of negative strides + if (i & 1) { + src0_offset = (h-1)*src0_stride; + src0_stride = -src0_stride; + } + if (i & 2) { + src1_offset = (h-1)*src1_stride; + src1_stride = -src1_stride; + } + if (i & 4) { + dst_offset = (h-1)*dst_stride; + dst_stride = -dst_stride; + } + + call_ref(src0 + src0_offset, src1 + src1_offset, dst0 + dst_offset, + w, h, src0_stride, src1_stride, dst_stride); + call_new(src0 + src0_offset, src1 + src1_offset, dst1 + dst_offset, + w, h, src0_stride, src1_stride, dst_stride); + // Check a one pixel-pair edge around the destination area, + // to catch overwrites past the end. + checkasm_check(uint8_t, dst0, 2*MAX_STRIDE, dst1, 2*MAX_STRIDE, + 2 * w + 2, h + 1, "dst"); + } + + bench_new(src0, src1, dst1, 127, MAX_HEIGHT, + MAX_STRIDE, MAX_STRIDE, 2*MAX_STRIDE); + } + if (check_func(interleaveBytes, "interleave_bytes_aligned")) { + // Bench the function in a more typical case, with aligned + // buffers and widths. + bench_new(src0_buf, src1_buf, dst1_buf, 128, MAX_HEIGHT, + MAX_STRIDE, MAX_STRIDE, 2*MAX_STRIDE); + } +} + void checkasm_check_sw_rgb(void) { ff_sws_rgb2rgb_init(); @@ -132,4 +201,7 @@ check_uyvy_to_422p(); report("uyvytoyuv422"); + + check_interleave_bytes(); + report("interleave_bytes"); } diff -Nru ffmpeg-4.2.2/tests/checkasm/sw_scale.c ffmpeg-4.4/tests/checkasm/sw_scale.c --- ffmpeg-4.2.2/tests/checkasm/sw_scale.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/sw_scale.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,236 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" +#include "libavutil/mem_internal.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) + +// This reference function is the same approximate algorithm employed by the +// SIMD functions +static void ref_function(const int16_t *filter, int filterSize, + const int16_t **src, uint8_t *dest, int dstW, + const uint8_t *dither, int offset) +{ + int i, d; + d = ((filterSize - 1) * 8 + dither[0]) >> 4; + for ( i = 0; i < dstW; i++) { + int16_t val = d; + int j; + union { + int val; + int16_t v[2]; + } t; + for (j = 0; j < filterSize; j++){ + t.val = (int)src[j][i + offset] * (int)filter[j]; + val += t.v[1]; + } + dest[i]= av_clip_uint8(val>>3); + } +} + +static void check_yuv2yuvX(void) +{ + struct SwsContext *ctx; + int fsi, osi, isi, i, j; + int dstW; +#define LARGEST_FILTER 16 +#define FILTER_SIZES 4 + static const int filter_sizes[FILTER_SIZES] = {1, 4, 8, 16}; +#define LARGEST_INPUT_SIZE 512 +#define INPUT_SIZES 6 + static const int input_sizes[INPUT_SIZES] = {8, 24, 128, 144, 256, 512}; + + declare_func_emms(AV_CPU_FLAG_MMX, void, const int16_t *filter, + int filterSize, const int16_t **src, uint8_t *dest, + int dstW, const uint8_t *dither, int offset); + + const int16_t **src; + LOCAL_ALIGNED_8(int16_t, src_pixels, [LARGEST_FILTER * LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int16_t, filter_coeff, [LARGEST_FILTER]); + LOCAL_ALIGNED_8(uint8_t, dst0, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(uint8_t, dst1, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(uint8_t, dither, [LARGEST_INPUT_SIZE]); + union VFilterData{ + const int16_t *src; + uint16_t coeff[8]; + } *vFilterData; + uint8_t d_val = rnd(); + memset(dither, d_val, LARGEST_INPUT_SIZE); + randomize_buffers((uint8_t*)src_pixels, LARGEST_FILTER * LARGEST_INPUT_SIZE * sizeof(int16_t)); + randomize_buffers((uint8_t*)filter_coeff, LARGEST_FILTER * sizeof(int16_t)); + ctx = sws_alloc_context(); + if (sws_init_context(ctx, NULL, NULL) < 0) + fail(); + + ff_getSwsFunc(ctx); + for(isi = 0; isi < INPUT_SIZES; ++isi){ + dstW = input_sizes[isi]; + for(osi = 0; osi < 64; osi += 16){ + for(fsi = 0; fsi < FILTER_SIZES; ++fsi){ + src = av_malloc(sizeof(int16_t*) * filter_sizes[fsi]); + vFilterData = av_malloc((filter_sizes[fsi] + 2) * sizeof(union VFilterData)); + memset(vFilterData, 0, (filter_sizes[fsi] + 2) * sizeof(union VFilterData)); + for(i = 0; i < filter_sizes[fsi]; ++i){ + src[i] = &src_pixels[i * LARGEST_INPUT_SIZE]; + vFilterData[i].src = src[i]; + for(j = 0; j < 4; ++j) + vFilterData[i].coeff[j + 4] = filter_coeff[i]; + } + if (check_func(ctx->yuv2planeX, "yuv2yuvX_%d_%d_%d", filter_sizes[fsi], osi, dstW)){ + memset(dst0, 0, LARGEST_INPUT_SIZE * sizeof(dst0[0])); + memset(dst1, 0, LARGEST_INPUT_SIZE * sizeof(dst1[0])); + + // The reference function is not the scalar function selected when mmx + // is deactivated as the SIMD functions do not give the same result as + // the scalar ones due to rounding. The SIMD functions are activated by + // the flag SWS_ACCURATE_RND + ref_function(&filter_coeff[0], filter_sizes[fsi], src, dst0, dstW - osi, dither, osi); + // There's no point in calling new for the reference function + if(ctx->use_mmx_vfilter){ + call_new((const int16_t*)vFilterData, filter_sizes[fsi], src, dst1, dstW - osi, dither, osi); + if (memcmp(dst0, dst1, LARGEST_INPUT_SIZE * sizeof(dst0[0]))) + fail(); + if(dstW == LARGEST_INPUT_SIZE) + bench_new((const int16_t*)vFilterData, filter_sizes[fsi], src, dst1, dstW - osi, dither, osi); + } + } + av_freep(&src); + av_freep(&vFilterData); + } + } + } + sws_freeContext(ctx); +#undef FILTER_SIZES +} + +#undef SRC_PIXELS +#define SRC_PIXELS 128 + +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 HSCALE_PAIRS 2 + static const int hscale_pairs[HSCALE_PAIRS][2] = { + { 8, 14 }, + { 8, 18 }, + }; + + int i, j, fsi, hpi, width; + struct SwsContext *ctx; + + // padded + LOCAL_ALIGNED_32(uint8_t, src, [FFALIGN(SRC_PIXELS + MAX_FILTER_WIDTH - 1, 4)]); + LOCAL_ALIGNED_32(uint32_t, dst0, [SRC_PIXELS]); + LOCAL_ALIGNED_32(uint32_t, dst1, [SRC_PIXELS]); + + // padded + LOCAL_ALIGNED_32(int16_t, filter, [SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH]); + LOCAL_ALIGNED_32(int32_t, filterPos, [SRC_PIXELS]); + + // The dst parameter here is either int16_t or int32_t but we use void* to + // just cover both cases. + declare_func_emms(AV_CPU_FLAG_MMX, void, void *c, void *dst, int dstW, + const uint8_t *src, const int16_t *filter, + const int32_t *filterPos, int filterSize); + + ctx = sws_alloc_context(); + if (sws_init_context(ctx, NULL, NULL) < 0) + fail(); + + randomize_buffers(src, SRC_PIXELS + MAX_FILTER_WIDTH - 1); + + for (hpi = 0; hpi < HSCALE_PAIRS; hpi++) { + for (fsi = 0; fsi < FILTER_SIZES; fsi++) { + width = filter_sizes[fsi]; + + ctx->srcBpc = hscale_pairs[hpi][0]; + ctx->dstBpc = hscale_pairs[hpi][1]; + ctx->hLumFilterSize = ctx->hChrFilterSize = width; + + for (i = 0; i < SRC_PIXELS; i++) { + filterPos[i] = i; + + // These filter cofficients are chosen to try break two corner + // cases, namely: + // + // - Negative filter coefficients. The filters output signed + // values, and it should be possible to end up with negative + // output values. + // + // - Positive clipping. The hscale filter function has clipping + // at (1<<15) - 1 + // + // The coefficients sum to the 1.0 point for the hscale + // functions (1 << 14). + + for (j = 0; j < width; j++) { + filter[i * width + j] = -((1 << 14) / (width - 1)); + } + filter[i * width + (rnd() % width)] = ((1 << 15) - 1); + } + + for (i = 0; i < MAX_FILTER_WIDTH; i++) { + // These values should be unused in SIMD implementations but + // may still be read, random coefficients here should help show + // issues where they are used in error. + + filter[SRC_PIXELS * width + i] = rnd(); + } + ff_getSwsFunc(ctx); + + 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); + if (memcmp(dst0, dst1, SRC_PIXELS * sizeof(dst0[0]))) + fail(); + bench_new(NULL, dst0, SRC_PIXELS, src, filter, filterPos, width); + } + } + } + sws_freeContext(ctx); +} + +void checkasm_check_sw_scale(void) +{ + check_hscale(); + report("hscale"); + check_yuv2yuvX(); + report("yuv2yuvX"); +} diff -Nru ffmpeg-4.2.2/tests/checkasm/synth_filter.c ffmpeg-4.4/tests/checkasm/synth_filter.c --- ffmpeg-4.2.2/tests/checkasm/synth_filter.c 2018-07-17 09:27:43.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/synth_filter.c 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,8 @@ #include "libavutil/internal.h" #include "libavutil/intfloat.h" +#include "libavutil/mem_internal.h" + #include "libavcodec/dcadata.h" #include "libavcodec/synth_filter.h" diff -Nru ffmpeg-4.2.2/tests/checkasm/utvideodsp.c ffmpeg-4.4/tests/checkasm/utvideodsp.c --- ffmpeg-4.2.2/tests/checkasm/utvideodsp.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/utvideodsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavcodec/avcodec.h" #include "libavcodec/utvideodsp.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #define WIDTH 240 #define HEIGHT 120 diff -Nru ffmpeg-4.2.2/tests/checkasm/v210enc.c ffmpeg-4.4/tests/checkasm/v210enc.c --- ffmpeg-4.2.2/tests/checkasm/v210enc.c 2018-07-17 09:27:43.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/v210enc.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #define BUF_SIZE 512 diff -Nru ffmpeg-4.2.2/tests/checkasm/vf_blend.c ffmpeg-4.4/tests/checkasm/vf_blend.c --- ffmpeg-4.2.2/tests/checkasm/vf_blend.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/vf_blend.c 2021-02-20 20:27:47.000000000 +0000 @@ -99,7 +99,7 @@ #define check_and_report(name, val, depth) \ param.mode = val; \ - ff_blend_init(¶m, depth - 1); \ + ff_blend_init(¶m, depth * 8); \ if (check_func(param.blend, #name)) \ check_blend_func(depth); diff -Nru ffmpeg-4.2.2/tests/checkasm/vf_colorspace.c ffmpeg-4.4/tests/checkasm/vf_colorspace.c --- ffmpeg-4.2.2/tests/checkasm/vf_colorspace.c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/vf_colorspace.c 2021-04-08 21:28:40.000000000 +0000 @@ -24,6 +24,7 @@ #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #define W 64 #define H 64 diff -Nru ffmpeg-4.2.2/tests/checkasm/vf_eq.c ffmpeg-4.4/tests/checkasm/vf_eq.c --- ffmpeg-4.2.2/tests/checkasm/vf_eq.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/vf_eq.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,80 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "checkasm.h" +#include "libavfilter/avfilter.h" +#include "libavfilter/vf_eq.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" + +#define WIDTH 256 +#define HEIGHT 256 +#define SRC_STRIDE 256 +#define PIXELS (WIDTH * HEIGHT) +#define RANDOM_RANGE 80000 +#define SCALE 10000 + +#define randomize_buffers(buf, size) \ + do { \ + int j; \ + uint8_t *tmp_buf = (uint8_t *)buf;\ + for (j = 0; j< size; j++) \ + tmp_buf[j] = rnd() & 0xFF; \ + } while (0) + +static void check_eq(void) +{ + LOCAL_ALIGNED_32(uint8_t, src, [PIXELS]); + LOCAL_ALIGNED_32(uint8_t, dst_ref, [PIXELS]); + LOCAL_ALIGNED_32(uint8_t, dst_new, [PIXELS]); + int w = WIDTH; + int h = HEIGHT; + int src_stride = SRC_STRIDE; + int dst_stride = SRC_STRIDE; + EQParameters pa; + EQContext eq; + declare_func(void, EQParameters *param, uint8_t *dst, int dst_stride, + const uint8_t *src, int src_stride, int w, int h); + + double rand_contrast = (int)(rnd() % (RANDOM_RANGE * 2) - RANDOM_RANGE) / + (SCALE * 1.0); + double rand_brightness = (int)(rnd() % (SCALE * 2) - SCALE) / + (SCALE * 1.0); + pa.contrast = rand_contrast; + pa.brightness = rand_brightness; + + memset(dst_ref, 0, PIXELS); + memset(dst_new, 0, PIXELS); + randomize_buffers(src, PIXELS); + ff_eq_init(&eq); + + if (check_func(eq.process, "process")) { + call_ref(&pa, dst_ref, dst_stride, src, src_stride, w, h); + call_new(&pa, dst_new, dst_stride, src, src_stride, w, h); + if (memcmp(dst_ref, dst_new, PIXELS)) + fail(); + bench_new(&pa, dst_new, dst_stride, src, src_stride, w, h); + } +} + +void checkasm_check_vf_eq(void) +{ + check_eq(); + report("eq"); +} diff -Nru ffmpeg-4.2.2/tests/checkasm/vf_gblur.c ffmpeg-4.4/tests/checkasm/vf_gblur.c --- ffmpeg-4.2.2/tests/checkasm/vf_gblur.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/vf_gblur.c 2021-04-08 21:28:40.000000000 +0000 @@ -16,6 +16,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include #include "checkasm.h" #include "libavfilter/gblur.h" @@ -33,18 +34,39 @@ tmp_buf[j] = (float)(rnd() & 0xFF); \ } while (0) -void checkasm_check_vf_gblur(void) +static void check_horiz_slice(float *dst_ref, float *dst_new) { - float *dst_ref = av_malloc(BUF_SIZE); - float *dst_new = av_malloc(BUF_SIZE); - int w = WIDTH; - int h = HEIGHT; int steps = 2; float nu = 0.101f; float bscale = 1.112f; - GBlurContext s; declare_func(void, float *dst, int w, int h, int steps, float nu, float bscale); + call_ref(dst_ref, WIDTH, HEIGHT, steps, nu, bscale); + call_new(dst_new, WIDTH, HEIGHT, steps, nu, bscale); + if (!float_near_abs_eps_array(dst_ref, dst_new, 0.01f, PIXELS)) { + fail(); + } + bench_new(dst_new, WIDTH, HEIGHT, 1, nu, bscale); +} + +static void check_postscale_slice(float *dst_ref, float *dst_new) +{ + float postscale = 0.0603f; + + declare_func(void, float *dst, int len, float postscale, float min, float max); + call_ref(dst_ref, PIXELS, postscale, -FLT_MAX, FLT_MAX); + call_new(dst_new, PIXELS, postscale, -FLT_MAX, FLT_MAX); + if (!float_near_abs_eps_array(dst_ref, dst_new, FLT_EPSILON, PIXELS)) { + fail(); + } + bench_new(dst_new, PIXELS, postscale, -FLT_MAX, FLT_MAX); +} + +void checkasm_check_vf_gblur(void) +{ + float *dst_ref = av_malloc(BUF_SIZE); + float *dst_new = av_malloc(BUF_SIZE); + GBlurContext s; randomize_buffers(dst_ref, PIXELS); memcpy(dst_new, dst_ref, BUF_SIZE); @@ -52,15 +74,17 @@ ff_gblur_init(&s); if (check_func(s.horiz_slice, "horiz_slice")) { - call_ref(dst_ref, w, h, steps, nu, bscale); - call_new(dst_new, w, h, steps, nu, bscale); - - if (!float_near_abs_eps_array(dst_ref, dst_new, 0.01f, PIXELS)) { - fail(); - } - bench_new(dst_new, w, h, 1, nu, bscale); + check_horiz_slice(dst_ref, dst_new); } report("horiz_slice"); + + randomize_buffers(dst_ref, PIXELS); + memcpy(dst_new, dst_ref, BUF_SIZE); + if (check_func(s.postscale_slice, "postscale_slice")) { + check_postscale_slice(dst_ref, dst_new); + } + report("postscale_slice"); + av_freep(&dst_ref); av_freep(&dst_new); } diff -Nru ffmpeg-4.2.2/tests/checkasm/vf_hflip.c ffmpeg-4.4/tests/checkasm/vf_hflip.c --- ffmpeg-4.2.2/tests/checkasm/vf_hflip.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/vf_hflip.c 2021-04-08 21:28:40.000000000 +0000 @@ -20,6 +20,7 @@ #include "checkasm.h" #include "libavfilter/hflip.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #define WIDTH 256 #define WIDTH_PADDED 256 + 32 @@ -43,6 +44,7 @@ declare_func(void, const uint8_t *src, uint8_t *dst, int w); + s.bayer_plus1 = 1; memset(src, 0, WIDTH_PADDED); memset(dst_ref, 0, WIDTH_PADDED); memset(dst_new, 0, WIDTH_PADDED); diff -Nru ffmpeg-4.2.2/tests/checkasm/vf_threshold.c ffmpeg-4.4/tests/checkasm/vf_threshold.c --- ffmpeg-4.2.2/tests/checkasm/vf_threshold.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/vf_threshold.c 2021-04-08 21:28:40.000000000 +0000 @@ -20,6 +20,7 @@ #include "checkasm.h" #include "libavfilter/threshold.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #define WIDTH 256 #define WIDTH_PADDED 256 + 32 diff -Nru ffmpeg-4.2.2/tests/checkasm/videodsp.c ffmpeg-4.4/tests/checkasm/videodsp.c --- ffmpeg-4.2.2/tests/checkasm/videodsp.c 2018-07-17 09:27:43.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/videodsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -23,6 +23,7 @@ #include "libavcodec/videodsp.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #define randomize_buffers(w, h) \ do { \ diff -Nru ffmpeg-4.2.2/tests/checkasm/vp8dsp.c ffmpeg-4.4/tests/checkasm/vp8dsp.c --- ffmpeg-4.2.2/tests/checkasm/vp8dsp.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/vp8dsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,7 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" #include "checkasm.h" diff -Nru ffmpeg-4.2.2/tests/checkasm/vp9dsp.c ffmpeg-4.4/tests/checkasm/vp9dsp.c --- ffmpeg-4.2.2/tests/checkasm/vp9dsp.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/checkasm/vp9dsp.c 2021-04-08 21:28:40.000000000 +0000 @@ -27,6 +27,7 @@ #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" +#include "libavutil/mem_internal.h" static const uint32_t pixel_mask[3] = { 0xffffffff, 0x03ff03ff, 0x0fff0fff }; #define SIZEOF_PIXEL ((bit_depth + 7) / 8) diff -Nru ffmpeg-4.2.2/tests/dnn/dnn-layer-avgpool-test.c ffmpeg-4.4/tests/dnn/dnn-layer-avgpool-test.c --- ffmpeg-4.2.2/tests/dnn/dnn-layer-avgpool-test.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/dnn/dnn-layer-avgpool-test.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "libavfilter/dnn/dnn_backend_native_layer_avgpool.h" + +#define EPSON 0.00001 + +static int test_with_same(void) +{ + // the input data and expected data are generated with below python code. + /* + import tensorflow as tf + import numpy as np + + x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) + y = tf.layers.average_pooling2d(x, pool_size=[2,2], strides=[1,1], padding='VALID') + data = np.random.rand(1, 5, 6, 3); + + sess=tf.Session() + sess.run(tf.global_variables_initializer()) + + output = sess.run(y, feed_dict={x: data}) + + print("input:") + print(data.shape) + print(list(data.flatten())) + + print("output:") + print(output.shape) + print(list(output.flatten())) + */ + + AvgPoolParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[1*5*6*3] = { + 0.7461309859908424, 0.7567538372797069, 0.07662743569678687, 0.8882112610336333, 0.9720443314026668, 0.3337200343220823, 0.4421032129780248, + 0.14940809044964876, 0.6773177061961277, 0.9778844630669781, 0.6522650522626998, 0.0317651530878591, 0.31259897552911364, 0.6235936821891896, + 0.40016094349542775, 0.4599222930032276, 0.7893807222960093, 0.8475986363538283, 0.5058802717647394, 0.7827005363222633, 0.3032188123727916, + 0.8983728631302361, 0.20622408444965523, 0.22966072303869878, 0.09535751273161308, 0.8760709100995375, 0.9982324154558745, 0.7904595468621013, + 0.13883671508879347, 0.9332751439533138, 0.0010861680752152214, 0.3607210449251048, 0.6600652759586171, 0.7629572058138805, 0.29441975810476106, + 0.2683471432889405, 0.22574580829831536, 0.8893251976212904, 0.3907737043801005, 0.6421829842863968, 0.6670373870457297, 0.9383850793160277, + 0.4120458907436003, 0.3589847212711481, 0.48047736550128983, 0.6428192648418949, 0.0313661686292348, 0.429357100401472, 0.5123413386514056, + 0.8492446404097114, 0.9045286128486804, 0.8123708563814285, 0.3943245008451698, 0.9576713003177785, 0.5985610965938726, 0.9350833279543561, + 0.8010079897491659, 0.45882114217642866, 0.35275037908941487, 0.4555844661432271, 0.12352455940255314, 0.37801756635035544, 0.2824056214573083, + 0.6229462823245029, 0.7235305681391472, 0.5408259266122064, 0.12142224381781208, 0.34431198802873686, 0.7112823816321276, 0.6307144385115417, + 0.8136734589018082, 0.842095618140585, 0.8602767724004784, 0.6649236853766185, 0.5184782829419623, 0.9119607270982825, 0.3084111974561645, + 0.39460705638161364, 0.17710447526170836, 0.1715485945814199, 0.17277563576521882, 0.40188232428735704, 0.22847985411491878, 0.4135361701550696, + 0.24621846601980057, 0.6576588108454774, 0.6063336087333997, 0.6452342242996931, 0.7071689702737508, 0.1973416063225648 + }; + float expected_output[] = { + 0.75964886, 0.6794307, 0.23580676, 0.5810112, 0.5509369, 0.55973274, 0.5764512, 0.45414522, 0.6601476, 0.52050734, 0.44385415, + 0.50631666, 0.38414115, 0.5170288, 0.544043, 0.61143976, 0.5419003, 0.5579729, 0.5680455, 0.6363218, 0.4655096, 0.51198983, + 0.5270792, 0.66168886, 0.48517057, 0.3513146, 0.7103355, 0.48667657, 0.34504217, 0.7318065, 0.5221889, 0.4746775, 0.69765306, + 0.78766406, 0.34437215, 0.6130092, 0.48132777, 0.7110491, 0.6464378, 0.40914366, 0.4391975, 0.5392131, 0.45033398, 0.37297475, + 0.43326652, 0.4748823, 0.48711336, 0.64649844, 0.51921225, 0.60038865, 0.8538945, 0.7215426, 0.60399896, 0.89988345, 0.707405, + 0.5652921, 0.54241943, 0.41785273, 0.30268195, 0.3263432, 0.3313644, 0.37539417, 0.35238582, 0.34811732, 0.48849532, 0.56799453, + 0.41089734, 0.63070333, 0.5892633, 0.6379743, 0.7604212, 0.5197186, 0.88611877, 0.48666745, 0.45654267, 0.5445326, 0.2399799, + 0.28369135, 0.28949338, 0.20001422, 0.2931559, 0.3240504, 0.44306934, 0.5099349, 0.44572634, 0.68241394, 0.40183762, 0.6452342, + 0.707169, 0.1973416 + }; + float *output; + + params.strides = 1; + params.kernel_size = 2; + params.padding_method = SAME; + + operands[0].data = input; + operands[0].dims[0] = 1; + operands[0].dims[1] = 5; + operands[0].dims[2] = 6; + operands[0].dims[3] = 3; + operands[1].data = NULL; + + input_indexes[0] = 0; + ff_dnn_execute_layer_avg_pool(operands, input_indexes, 1, ¶ms, NULL); + + output = operands[1].data; + for (int i = 0; i < sizeof(expected_output) / sizeof(float); ++i) { + if (fabs(output[i] - expected_output[i]) > EPSON) { + printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; +} + +static int test_with_valid(void) +{ + // the input data and expected data are generated with below python code. + /* + import tensorflow as tf + import numpy as np + + x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) + y = tf.layers.average_pooling2d(x, pool_size=[2,2], strides=[1,1], padding='VALID') + data = np.random.rand(1, 5, 6, 3); + + sess=tf.Session() + sess.run(tf.global_variables_initializer()) + + output = sess.run(y, feed_dict={x: data}) + + print("input:") + print(data.shape) + print(list(data.flatten())) + + print("output:") + print(output.shape) + print(list(output.flatten())) + */ + + AvgPoolParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[1*5*6*3] = { + 0.5046741692941682, 0.9273653202485155, 0.8193878359859937, 0.1904059431360905, 0.8664919633253656, 0.7484625128286059, 0.984534184632278, + 0.31900804890072254, 0.3259426099940872, 0.05388974903570376, 0.7356610151331133, 0.46710858713311965, 0.718553768817036, 0.062478421853278676, + 0.7813224786584609, 0.4826837517658389, 0.9748095400220147, 0.8078547703898341, 0.11976750668368585, 0.8713586777195065, 0.41447321551284355, + 0.9818788239089807, 0.4335715767584073, 0.4059793452147419, 0.3677205907204525, 0.47919995923571, 0.8341395256258882, 0.7059726374074609, + 0.5478504551919791, 0.8622900484790175, 0.8343709722511167, 0.05089827275068537, 0.6465283980840416, 0.544539116066677, 0.39812057257884337, + 0.9578115576866337, 0.25012888117580145, 0.579333516024662, 0.5556732133051457, 0.6119862111181243, 0.0018736758772316398, 0.9795490254040474, + 0.4488085008883018, 0.28947489777011737, 0.4834108668633247, 0.9280490084385024, 0.9895821458049648, 0.31777618554697606, 0.42679693258977847, + 0.74447844466923, 0.9752225305081498, 0.17564130841849335, 0.22382692067314292, 0.009602884447469373, 0.5144884415025782, 0.031622570708844555, + 0.8277532752502512, 0.4111593210409763, 0.5272084646575664, 0.28856508082905297, 0.11317726946036655, 0.7203328275540273, 0.8310055019972384, + 0.8535951508685228, 0.40230347305233227, 0.2819703265132867, 0.6243143957791139, 0.7512463693822311, 0.7523056340495644, 0.8838077258040928, + 0.5472240664033092, 0.2550538284454935, 0.5560317774456567, 0.8966847087518931, 0.6728358284165321, 0.30361297147530875, 0.464343925441822, + 0.34507695659461224, 0.6333175615390685, 0.26661369038523497, 0.9926748632253231, 0.9994267301382666, 0.8684917986974414, 0.3598754806113009, + 0.49550268625464666, 0.03652458679973214, 0.13469081713137177, 0.4579424049273835, 0.48641107969110353, 0.9670250266945365 + }; + float expected_output[1*4*5*3] = { + 0.44918162, 0.7746969, 0.5970757, 0.63113487, 0.5245679, 0.578631, 0.52802926, 0.52042985, 0.6223702, 0.57819676, 0.34922206, + 0.6893124, 0.64503694, 0.37157673, 0.7983793, 0.49094033, 0.47153437, 0.5889187, 0.6025985, 0.30103004, 0.6757697, 0.6126377, + 0.5765268, 0.62440413, 0.7237974, 0.5832023, 0.7004543, 0.49533707, 0.35433105, 0.6472913, 0.44694072, 0.28500956, 0.6628852, + 0.39628282, 0.38472247, 0.6456326, 0.58590746, 0.60042334, 0.47854072, 0.7081889, 0.7219026, 0.5818187, 0.5276401, 0.56669396, + 0.49804622, 0.4463231, 0.4799649, 0.5335578, 0.36531678, 0.4946247, 0.6143306, 0.6498792, 0.5644355, 0.6163815, 0.7432098, + 0.5146416, 0.38221055, 0.6153918, 0.45535153, 0.5272688 + }; + float *output; + + params.strides = 1; + params.kernel_size = 2; + params.padding_method = VALID; + + operands[0].data = input; + operands[0].dims[0] = 1; + operands[0].dims[1] = 5; + operands[0].dims[2] = 6; + operands[0].dims[3] = 3; + operands[1].data = NULL; + + input_indexes[0] = 0; + ff_dnn_execute_layer_avg_pool(operands, input_indexes, 1, ¶ms, NULL); + + output = operands[1].data; + for (int i = 0; i < sizeof(expected_output) / sizeof(float); ++i) { + if (fabs(output[i] - expected_output[i]) > EPSON) { + printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; +} + +int main(int argc, char **argv) +{ + if (test_with_same()) + return 1; + if (test_with_valid()) + return 1; + + return 0; +} diff -Nru ffmpeg-4.2.2/tests/dnn/dnn-layer-conv2d-test.c ffmpeg-4.4/tests/dnn/dnn-layer-conv2d-test.c --- ffmpeg-4.2.2/tests/dnn/dnn-layer-conv2d-test.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/dnn/dnn-layer-conv2d-test.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2019 Guo Yejun + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "libavfilter/dnn/dnn_backend_native_layer_conv2d.h" + +#define EPSON 0.00001 + +static int test_with_same_dilate(void) +{ + // the input data and expected data are generated with below python code. + /* + x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) + y = tf.layers.conv2d(x, 2, 3, activation=tf.nn.tanh, padding='same', dilation_rate=(2, 2), bias_initializer=tf.keras.initializers.he_normal()) + data = np.random.rand(1, 5, 6, 3); + + sess=tf.Session() + sess.run(tf.global_variables_initializer()) + + weights = dict([(var.name, sess.run(var)) for var in tf.trainable_variables()]) + kernel = weights['conv2d/kernel:0'] + kernel = np.transpose(kernel, [3, 0, 1, 2]) + print("kernel:") + print(kernel.shape) + print(list(kernel.flatten())) + + bias = weights['conv2d/bias:0'] + print("bias:") + print(bias.shape) + print(list(bias.flatten())) + + output = sess.run(y, feed_dict={x: data}) + + print("input:") + print(data.shape) + print(list(data.flatten())) + + print("output:") + print(output.shape) + print(list(output.flatten())) + */ + + ConvolutionalParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[1*5*6*3] = { + 0.7012556460308194, 0.4233847954643357, 0.19515900664313612, 0.16343083004926495, 0.5758261611052848, 0.9510767434014871, 0.11014085055947687, + 0.906327053637727, 0.8136794715542507, 0.45371764543639526, 0.5768443343523952, 0.19543668786046986, 0.15648326047898609, 0.2099500241141279, + 0.17658777090552413, 0.059335724777169196, 0.1729991838469117, 0.8150514704819208, 0.4435535466703049, 0.3752188477566878, 0.749936650421431, + 0.6823494635284907, 0.10776389679424747, 0.34247481674596836, 0.5147867256244629, 0.9063709728129032, 0.12423605800856818, 0.6064872945412728, + 0.5891681538551459, 0.9865836236466314, 0.9002163879294677, 0.003968273184274618, 0.8628374809643967, 0.1327176268279583, 0.8449799925703798, + 0.1937671869354366, 0.41524410152707425, 0.02038786604756837, 0.49792466069597496, 0.8881874553848784, 0.9683921035597336, 0.4122972568010813, + 0.843553550993252, 0.9588482762501964, 0.5190350762645546, 0.4283584264145317, 0.09781496073714646, 0.9501058833776156, 0.8665541760152776, + 0.31669272550095806, 0.07133074675453632, 0.606438007334886, 0.7007157020538224, 0.4827996264130444, 0.5167615606392761, 0.6385043039312651, + 0.23069664707810555, 0.058233497329354456, 0.06323892961591071, 0.24816458893245974, 0.8646369065257812, 0.24742185893094837, 0.09991225948167437, + 0.625700606979606, 0.7678541502111257, 0.6215834594679912, 0.5623003956582483, 0.07389123942681242, 0.7659100715711249, 0.486061471642225, + 0.9947455699829012, 0.9094911797643259, 0.7644355876253265, 0.05384315321492239, 0.13565394382783613, 0.9810628204953316, 0.007386389078887889, + 0.226182754156241, 0.2609021390764772, 0.24182802076928933, 0.13264782451941648, 0.2035816485767682, 0.005504188177612557, 0.7014619934040155, + 0.956215988391991, 0.5670398541013633, 0.9809764721750784, 0.6886338100487461, 0.5758152317218274, 0.7137823176776179 + }; + float expected_output[1*5*6*2] = { + -0.9480655, -0.7169147, -0.9404794, -0.5567385, -0.8991124, -0.8306558, -0.94487447, -0.8932543, -0.88238764, -0.7301602, + -0.8974813, -0.7026703, -0.8858988, -0.53203243, -0.92881465, -0.5648504, -0.8871471, -0.7000097, -0.91754407, -0.79684794, + -0.760465, -0.117928326, -0.88302773, -0.8975289, -0.70615053, 0.19231977, -0.8318776, -0.386184, -0.80698484, -0.8556624, + -0.7336671, -0.6168619, -0.7658234, -0.63449603, -0.73314047, -0.87502456, -0.58158904, -0.4184259, -0.52618927, -0.13613208, + -0.5093187, -0.21027721, -0.39455596, -0.44507834, -0.22269244, -0.73400885, -0.77655095, -0.74408925, -0.57313335, -0.15333457, + -0.74620694, -0.34858236, -0.42586932, -0.5240488, 0.1634339, -0.2447881, -0.57927346, -0.62732303, -0.82287043, -0.8474058 + }; + float *output; + float kernel[2*3*3*3] = { + 0.26025516, 0.16536498, -0.24351254, 0.33892477, -0.34005195, 0.35202783, 0.34056443, 0.01422739, 0.13799345, 0.29489166, + 0.2781723, 0.178585, 0.22122234, 0.044115514, 0.13134438, 0.31705368, 0.22527462, -0.021323413, 0.115134746, -0.18216397, + -0.21197563, -0.027848959, -0.01704529, -0.12401503, -0.23415318, -0.12661739, -0.35338148, 0.20049328, -0.076153606, + -0.23642601, -0.3125769, -0.025851756, -0.30006272, 0.050762743, 0.32003498, 0.3052225, -0.0017385483, 0.25337684, -0.25664508, + 0.27846587, -0.3112659, 0.2066065, 0.31499845, 0.113178134, 0.09449363, -0.11828774, -0.12671001, -0.36259216, 0.2710235, + -0.19676702, 0.023612618, -0.2596915, -0.34949252, -0.108270735 + }; + float bias[2] = { -1.6574852, -0.72915393 }; + + NativeContext ctx; + ctx.class = NULL; + ctx.options.conv2d_threads = 1; + + params.activation = TANH; + params.has_bias = 1; + params.biases = bias; + params.dilation = 2; + params.input_num = 3; + params.kernel = kernel; + params.kernel_size = 3; + params.output_num = 2; + params.padding_method = SAME; + + operands[0].data = input; + operands[0].dims[0] = 1; + operands[0].dims[1] = 5; + operands[0].dims[2] = 6; + operands[0].dims[3] = 3; + operands[1].data = NULL; + + input_indexes[0] = 0; + ff_dnn_execute_layer_conv2d(operands, input_indexes, 1, ¶ms, &ctx); + + output = operands[1].data; + for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { + if (fabs(output[i] - expected_output[i]) > EPSON) { + printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; +} + +static int test_with_valid(void) +{ + // the input data and expected data are generated with below python code. + /* + x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) + y = tf.layers.conv2d(x, 2, 3, activation=tf.nn.tanh, padding='valid', bias_initializer=tf.keras.initializers.he_normal()) + data = np.random.rand(1, 5, 6, 3); + + sess=tf.Session() + sess.run(tf.global_variables_initializer()) + + weights = dict([(var.name, sess.run(var)) for var in tf.trainable_variables()]) + kernel = weights['conv2d/kernel:0'] + kernel = np.transpose(kernel, [3, 0, 1, 2]) + print("kernel:") + print(kernel.shape) + print(list(kernel.flatten())) + + bias = weights['conv2d/bias:0'] + print("bias:") + print(bias.shape) + print(list(bias.flatten())) + + output = sess.run(y, feed_dict={x: data}) + + print("input:") + print(data.shape) + print(list(data.flatten())) + + print("output:") + print(output.shape) + print(list(output.flatten())) + */ + + ConvolutionalParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[1*5*6*3] = { + 0.26126657468269665, 0.42762216215337556, 0.7466274030131497, 0.802550266787863, 0.3709323443076644, 0.5919817068197668, 0.49274512279324967, + 0.7170132295090351, 0.0911793215410649, 0.5134213878288361, 0.670132600785118, 0.49417034512633484, 0.03887389460089885, 0.436785102836845, + 0.1490231658611978, 0.6413606121498127, 0.8595987991375995, 0.9132593077586231, 0.7075959004873255, 0.17754995944845464, 0.5212507214937141, + 0.35379732738215475, 0.25205107358505296, 0.3928792840544273, 0.09485294189485782, 0.8685115437448666, 0.6489046799288605, 0.509253797582924, + 0.8993255536791972, 0.18740056466602373, 0.34237617336313986, 0.3871438962989183, 0.1488532571774911, 0.5187002331293636, 0.8137098818752955, + 0.521761863717401, 0.4622312310118274, 0.29038411334638825, 0.16194915718170566, 0.5175999923925211, 0.8852230040101133, 0.0218263385047206, + 0.08482355352852367, 0.3463638568376264, 0.28627127120619733, 0.9553293378948409, 0.4803391055970835, 0.841635695030805, 0.3556828280031952, + 0.06778527221541808, 0.28193560357091596, 0.8399957619031576, 0.03305536359456385, 0.6625039162109645, 0.9300552020023897, 0.8551529138204146, + 0.6133216915522418, 0.222427800857393, 0.1315422686800336, 0.6189144989185527, 0.5346184916866876, 0.8348888624532548, 0.6544834567840291, + 0.2844062293389934, 0.28780026600883324, 0.5372272015684924, 0.6250226011503823, 0.28119106062279453, 0.49655812908420094, 0.6451488959145951, + 0.7362580606834843, 0.44815578616664087, 0.6454760235835586, 0.6794062414265861, 0.045378883014935756, 0.9008388543865096, 0.7949752851269782, + 0.4179928876222264, 0.28733419007048644, 0.996902319501908, 0.5690851338677467, 0.9511814013279738, 0.025323788678181636, 0.5594359732604794, + 0.1213732595086251, 0.7172624313368294, 0.6759328959074691, 0.07252138454885071, 0.17557735158403442, 0.5988895455048769 + }; + float expected_output[1*3*4*2] = { + -0.556947, -0.42143887, -0.092070885, 0.27404794, -0.41886684, 0.0862887, -0.25001016, -0.342721, 0.020730592, 0.04016919, -0.69839877, + -0.06136704, 0.14186388, -0.11655602, -0.23489095, -0.3845829, -0.19017771, 0.1595885, -0.18308741, -0.3071209, -0.5848686, -0.22509028, + -0.6023201, -0.14448485 + }; + float *output; + float kernel[2*3*3*3] = { + -0.25291282, 0.22402048, 0.028642118, -0.14615723, -0.27362752, -0.34801802, -0.2759148, 0.19594926, -0.25029412, 0.34606284, 0.10376671, + -0.1015394, 0.23616093, 0.2134214, 0.35285157, 0.05893758, 0.0024731457, -0.17143056, 0.35758412, 0.2186206, -0.28384736, -0.21206513, + -0.20871592, 0.27070445, 0.25878823, 0.11136332, -0.33737376, 0.08353335, -0.34290665, 0.041805506, -0.09738535, 0.3284936, -0.16838405, + -0.032494456, -0.29193437, 0.033259362, -0.09272635, -0.2802651, -0.28648436, 0.3542878, 0.2432127, -0.24551713, 0.27813476, 0.21024024, + -0.013690501, -0.1350077, -0.07826337, -0.34563828, 0.3220685, -0.07571727, 0.19420576, 0.20783454, 0.18738335, 0.16672492 + }; + float bias[2] = { -0.4773722, -0.19620377 }; + + NativeContext ctx; + ctx.class = NULL; + ctx.options.conv2d_threads = 1; + + params.activation = TANH; + params.has_bias = 1; + params.biases = bias; + params.dilation = 1; + params.input_num = 3; + params.kernel = kernel; + params.kernel_size = 3; + params.output_num = 2; + params.padding_method = VALID; + + operands[0].data = input; + operands[0].dims[0] = 1; + operands[0].dims[1] = 5; + operands[0].dims[2] = 6; + operands[0].dims[3] = 3; + operands[1].data = NULL; + + input_indexes[0] = 0; + ff_dnn_execute_layer_conv2d(operands, input_indexes, 1, ¶ms, &ctx); + + output = operands[1].data; + for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { + if (fabs(output[i] - expected_output[i]) > EPSON) { + printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; +} + +int main(int argc, char **argv) +{ + if (test_with_valid()) + return 1; + if (test_with_same_dilate()) + return 1; + + return 0; +} diff -Nru ffmpeg-4.2.2/tests/dnn/dnn-layer-dense-test.c ffmpeg-4.4/tests/dnn/dnn-layer-dense-test.c --- ffmpeg-4.2.2/tests/dnn/dnn-layer-dense-test.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/dnn/dnn-layer-dense-test.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "libavfilter/dnn/dnn_backend_native_layer_dense.h" + +#define EPSON 0.00001 + +static int test(void) +{ + // the input data and expected data are generated with below python code. + /* + x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) + y = tf.layers.dense(input_x, 3, activation=tf.nn.sigmoid, bias_initializer=tf.keras.initializers.he_normal()) + data = np.random.rand(1, 5, 6, 3); + + sess=tf.Session() + sess.run(tf.global_variables_initializer()) + + weights = dict([(var.name, sess.run(var)) for var in tf.trainable_variables()]) + kernel = weights['dense/kernel:0'] + kernel = np.transpose(kernel, [1, 0]) + print("kernel:") + print(kernel.shape) + print(list(kernel.flatten())) + + bias = weights['dense/bias:0'] + print("bias:") + print(bias.shape) + print(list(bias.flatten())) + + output = sess.run(y, feed_dict={x: data}) + + print("input:") + print(data.shape) + print(list(data.flatten())) + + print("output:") + print(output.shape) + print(list(output.flatten())) + */ + + DenseParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[1*5*6*3] = { + 0.5552418686576308, 0.20653189262022464, 0.31115120939398877, 0.5897014433221428, 0.37340078861060655, 0.6470921693941893, 0.8039950367872679, 0.8762700891949274, + 0.6556655583829558, 0.5911096107039339, 0.18640250865290997, 0.2803248779238966, 0.31586613136402053, 0.9447300740056483, 0.9443980824873418, 0.8158851991115941, + 0.5631010340387631, 0.9407402251929046, 0.6485434876551682, 0.5631376966470001, 0.17581924875609634, 0.7033802439103178, 0.04802402495561675, 0.9183681450194972, + 0.46059317944364, 0.07964160481596883, 0.871787076270302, 0.973743142324361, 0.15923146943258415, 0.8212946080584571, 0.5415954459227064, 0.9552813822803975, + 0.4908552668172057, 0.33723691635292274, 0.46588057864910026, 0.8994239961321776, 0.09845220457674186, 0.1713400292123486, 0.39570294912818826, 0.08018956486392803, + 0.5290478278169032, 0.7141906125920976, 0.0320878067840098, 0.6412406575332606, 0.0075712007102423096, 0.7150828462386156, 0.1311989216968138, 0.4706847944253756, + 0.5447610794883336, 0.3430923933318001, 0.536082357943209, 0.4371629342483694, 0.40227962985019927, 0.3553806249465469, 0.031806622424259245, 0.7053916426174, + 0.3261570237309813, 0.419500213292063, 0.3155691223480851, 0.05664028113178088, 0.3636491555914486, 0.8502419746667123, 0.9836596530684955, 0.1628681802975801, + 0.09410832912479894, 0.28407218939480294, 0.7983417928813697, 0.24132158596506748, 0.8154729498062224, 0.29173768373895637, 0.13407102008052096, 0.18705786678800385, + 0.7167943621295573, 0.09222004247174376, 0.2319220738766018, 0.17708964382285064, 0.1391440370249517, 0.3254088083499256, 0.4013916894718289, 0.4819742663322323, + 0.15080103744648077, 0.9302407847555013, 0.9397597961319524, 0.5719200825550793, 0.9538938024682824, 0.9583882089203861, 0.5168861091262276, 0.1926396841842669, + 0.6781176744337578, 0.719366447288566 + }; + float expected_output[1*5*6*3] = { + -0.3921688, -0.9243112, -0.29659146, -0.64000785, -0.9466343, -0.62125254, -0.71759033, -0.9171336, -0.735589, -0.34365994, + -0.92100817, -0.23903961, -0.8962277, -0.9521279, -0.90962386, -0.7488303, -0.9563761, -0.7701762, -0.40800542, -0.87684774, + -0.3339763, -0.6354543, -0.97068924, -0.6246325, -0.6992075, -0.9706726, -0.6818918, -0.51864433, -0.9592881, -0.51187396, + -0.7423632, -0.89911884, -0.7457824, -0.82009757, -0.96402895, -0.8235518, -0.61980766, -0.94494647, -0.5410502, -0.8281218, + -0.95508635, -0.8201453, -0.5937325, -0.8679507, -0.500767, -0.39430764, -0.93967676, -0.32183182, -0.58913624, -0.939717, + -0.55179894, -0.55004454, -0.9214453, -0.4889004, -0.75294703, -0.9118363, -0.7200309, -0.3248641, -0.8878874, -0.18977344, + -0.8873837, -0.9571257, -0.90145934, -0.50521654, -0.93739635, -0.39051685, -0.61143184, -0.9591179, -0.605999, -0.40008977, + -0.92219675, -0.26732883, -0.19607787, -0.9172511, -0.07068595, -0.5409857, -0.9387041, -0.44181606, -0.4705004, -0.8899935, + -0.37997037, -0.66105115, -0.89754754, -0.68141997, -0.6324047, -0.886776, -0.65066385, -0.8334821, -0.94801456, -0.83297 + }; + float *output; + float kernel[3*3] = { + 0.56611896, -0.5144603, -0.82600045, 0.19219112, 0.3835776, -0.7475352, 0.5209291, -0.6301091, -0.99442935}; + float bias[3] = {-0.3654299, -1.5711838, -0.15546428}; + + params.activation = TANH; + params.has_bias = 1; + params.biases = bias; + params.input_num = 3; + params.kernel = kernel; + params.output_num = 3; + + operands[0].data = input; + operands[0].dims[0] = 1; + operands[0].dims[1] = 5; + operands[0].dims[2] = 6; + operands[0].dims[3] = 3; + operands[1].data = NULL; + + input_indexes[0] = 0; + ff_dnn_execute_layer_dense(operands, input_indexes, 1, ¶ms, NULL); + + output = operands[1].data; + for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { + if (fabs(output[i] - expected_output[i]) > EPSON) { + printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; +} + +int main(int argc, char **argv) +{ + if (test()) + return 1; + + return 0; +} diff -Nru ffmpeg-4.2.2/tests/dnn/dnn-layer-depth2space-test.c ffmpeg-4.4/tests/dnn/dnn-layer-depth2space-test.c --- ffmpeg-4.2.2/tests/dnn/dnn-layer-depth2space-test.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/dnn/dnn-layer-depth2space-test.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2019 Guo Yejun + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "libavfilter/dnn/dnn_backend_native.h" +#include "libavfilter/dnn/dnn_backend_native_layer_depth2space.h" + +#define EPSON 0.00001 + +static int test(void) +{ + // the input data and expected data are generated with below python code. + /* + x = tf.placeholder(tf.float32, shape=[1, None, None, 4]) + y = tf.depth_to_space(x, 2) + data = np.random.rand(1, 5, 3, 4); + + sess=tf.Session() + sess.run(tf.global_variables_initializer()) + + output = sess.run(y, feed_dict={x: data}) + + print("input:") + print(data.shape) + print(list(data.flatten())) + + print("output:") + print(output.shape) + print(list(output.flatten())) + */ + + DepthToSpaceParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[1*5*3*4] = { + 0.09771065121566602, 0.6336807372403175, 0.5142416549709786, 0.8027206567330333, 0.2154276025069397, 0.12112878462616772, 0.913936596765778, + 0.38881443647542646, 0.5850447615898835, 0.9311499327398275, 0.3613660929428246, 0.5420722002125493, 0.6002131190230359, 0.44800665702299525, + 0.7271322557896777, 0.3869293511885826, 0.5144404769364138, 0.6910844856987723, 0.6142102742269762, 0.6249991371621018, 0.45663376215836626, + 0.19523477129943423, 0.2483895888532045, 0.64326768256278, 0.5485877602998981, 0.45442067849873546, 0.529374943304256, 0.30439850391811885, + 0.11961343361340993, 0.2909643484561082, 0.9810970344127848, 0.8886928489786549, 0.6112237084436409, 0.8852482695156674, 0.9110868043114374, + 0.21242780027585217, 0.7101536973207572, 0.9709717457443375, 0.2702666770969332, 0.7718295953780221, 0.3957005164588574, 0.24383544252475453, + 0.040143453532367035, 0.26358051835323115, 0.013130251443791319, 0.3016550481482074, 0.03582340459943956, 0.718025513612361, 0.09844204177633753, + 0.04433767496953056, 0.6221895044119757, 0.6190414032940228, 0.8963550834625371, 0.5642449700064629, 0.2482982014723497, 0.17824909294583013, + 0.024401882408643272, 0.21742800875253465, 0.6794724473181843, 0.4814830479242237 + }; + float expected_output[1*10*6*1] = { + 0.097710654, 0.63368076, 0.2154276, 0.12112878, 0.58504474, 0.93114996, 0.51424164, 0.80272067, 0.9139366, 0.38881445, + 0.3613661, 0.5420722, 0.6002131, 0.44800666, 0.5144405, 0.6910845, 0.45663378, 0.19523478, 0.72713226, 0.38692936, + 0.61421025, 0.62499917, 0.24838959, 0.6432677, 0.54858774, 0.4544207, 0.11961343, 0.29096434, 0.6112237, 0.88524824, + 0.52937496, 0.3043985, 0.98109704, 0.88869286, 0.9110868, 0.2124278, 0.7101537, 0.97097176, 0.3957005, 0.24383545, + 0.013130251, 0.30165505, 0.27026668, 0.7718296, 0.040143453, 0.26358053, 0.035823405, 0.7180255, 0.09844204, + 0.044337675, 0.8963551, 0.564245, 0.024401883, 0.21742801, 0.6221895, 0.6190414, 0.2482982, 0.17824909, 0.67947245, 0.48148304 + }; + float *output; + + operands[0].data = input; + operands[0].dims[0] = 1; + operands[0].dims[1] = 5; + operands[0].dims[2] = 3; + operands[0].dims[3] = 4; + operands[1].data = NULL; + + input_indexes[0] = 0; + params.block_size = 2; + ff_dnn_execute_layer_depth2space(operands, input_indexes, 1, ¶ms, NULL); + + output = operands[1].data; + for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { + if (fabs(output[i] - expected_output[i]) > EPSON) { + printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; +} + +int main(int argc, char **argv) +{ + return test(); +} diff -Nru ffmpeg-4.2.2/tests/dnn/dnn-layer-mathbinary-test.c ffmpeg-4.4/tests/dnn/dnn-layer-mathbinary-test.c --- ffmpeg-4.2.2/tests/dnn/dnn-layer-mathbinary-test.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/dnn/dnn-layer-mathbinary-test.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "libavfilter/dnn/dnn_backend_native_layer_mathbinary.h" +#include "libavutil/avassert.h" + +#define EPSON 0.00005 + +static float get_expected(float f1, float f2, DNNMathBinaryOperation op) +{ + switch (op) + { + case DMBO_SUB: + return f1 - f2; + case DMBO_ADD: + return f1 + f2; + case DMBO_MUL: + return f1 * f2; + case DMBO_REALDIV: + return f1 / f2; + case DMBO_MINIMUM: + return (f1 < f2) ? f1 : f2; + case DMBO_FLOORMOD: + return (float)((int)(f1) % (int)(f2)); + default: + av_assert0(!"not supported yet"); + return 0.f; + } +} + +static int test_broadcast_input0(DNNMathBinaryOperation op) +{ + DnnLayerMathBinaryParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[1*1*2*3] = { + -3, 2.5, 2, -2.1, 7.8, 100 + }; + float *output; + + params.bin_op = op; + params.input0_broadcast = 1; + params.input1_broadcast = 0; + params.v = 7.28; + + operands[0].data = input; + operands[0].dims[0] = 1; + operands[0].dims[1] = 1; + operands[0].dims[2] = 2; + operands[0].dims[3] = 3; + operands[1].data = NULL; + + input_indexes[0] = 0; + ff_dnn_execute_layer_math_binary(operands, input_indexes, 1, ¶ms, NULL); + + output = operands[1].data; + for (int i = 0; i < sizeof(input) / sizeof(float); i++) { + float expected_output = get_expected(params.v, input[i], op); + if (fabs(output[i] - expected_output) > EPSON) { + printf("op %d, at index %d, output: %f, expected_output: %f (%s:%d)\n", + op, i, output[i], expected_output, __FILE__, __LINE__); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; +} + +static int test_broadcast_input1(DNNMathBinaryOperation op) +{ + DnnLayerMathBinaryParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[1*1*2*3] = { + -3, 2.5, 2, -2.1, 7.8, 100 + }; + float *output; + + params.bin_op = op; + params.input0_broadcast = 0; + params.input1_broadcast = 1; + params.v = 7.28; + + operands[0].data = input; + operands[0].dims[0] = 1; + operands[0].dims[1] = 1; + operands[0].dims[2] = 2; + operands[0].dims[3] = 3; + operands[1].data = NULL; + + input_indexes[0] = 0; + ff_dnn_execute_layer_math_binary(operands, input_indexes, 1, ¶ms, NULL); + + output = operands[1].data; + for (int i = 0; i < sizeof(input) / sizeof(float); i++) { + float expected_output = get_expected(input[i], params.v, op); + if (fabs(output[i] - expected_output) > EPSON) { + printf("op %d, at index %d, output: %f, expected_output: %f (%s:%d)\n", + op, i, output[i], expected_output, __FILE__, __LINE__); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; +} + +static int test_no_broadcast(DNNMathBinaryOperation op) +{ + DnnLayerMathBinaryParams params; + DnnOperand operands[3]; + int32_t input_indexes[2]; + float input0[1*1*2*3] = { + -3, 2.5, 2, -2.1, 7.8, 100 + }; + float input1[1*1*2*3] = { + -1, 2, 3, -21, 8, 10.0 + }; + float *output; + + params.bin_op = op; + params.input0_broadcast = 0; + params.input1_broadcast = 0; + + operands[0].data = input0; + operands[0].dims[0] = 1; + operands[0].dims[1] = 1; + operands[0].dims[2] = 2; + operands[0].dims[3] = 3; + operands[1].data = input1; + operands[1].dims[0] = 1; + operands[1].dims[1] = 1; + operands[1].dims[2] = 2; + operands[1].dims[3] = 3; + operands[2].data = NULL; + + input_indexes[0] = 0; + input_indexes[1] = 1; + ff_dnn_execute_layer_math_binary(operands, input_indexes, 2, ¶ms, NULL); + + output = operands[2].data; + for (int i = 0; i < sizeof(input0) / sizeof(float); i++) { + float expected_output = get_expected(input0[i], input1[i], op); + if (fabs(output[i] - expected_output) > EPSON) { + printf("op %d, at index %d, output: %f, expected_output: %f (%s:%d)\n", + op, i, output[i], expected_output, __FILE__, __LINE__); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; +} + +static int test(DNNMathBinaryOperation op) +{ + if (test_broadcast_input0(op)) + return 1; + + if (test_broadcast_input1(op)) + return 1; + + if (test_no_broadcast(op)) + return 1; + + return 0; +} + +int main(int argc, char **argv) +{ + if (test(DMBO_SUB)) + return 1; + + if (test(DMBO_ADD)) + return 1; + + if (test(DMBO_MUL)) + return 1; + + if (test(DMBO_REALDIV)) + return 1; + + if (test(DMBO_MINIMUM)) + return 1; + + if (test(DMBO_FLOORMOD)) + return 1; + + return 0; +} diff -Nru ffmpeg-4.2.2/tests/dnn/dnn-layer-mathunary-test.c ffmpeg-4.4/tests/dnn/dnn-layer-mathunary-test.c --- ffmpeg-4.2.2/tests/dnn/dnn-layer-mathunary-test.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/dnn/dnn-layer-mathunary-test.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2020 + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "libavfilter/dnn/dnn_backend_native_layer_mathunary.h" +#include "libavutil/avassert.h" + +#define EPS 0.00001 + +static float get_expected(float f, DNNMathUnaryOperation op) +{ + switch (op) + { + case DMUO_ABS: + return (f >= 0) ? f : -f; + case DMUO_SIN: + return sin(f); + case DMUO_COS: + return cos(f); + case DMUO_TAN: + return tan(f); + case DMUO_ASIN: + return asin(f); + case DMUO_ACOS: + return acos(f); + case DMUO_ATAN: + return atan(f); + case DMUO_SINH: + return sinh(f); + case DMUO_COSH: + return cosh(f); + case DMUO_TANH: + return tanh(f); + case DMUO_ASINH: + return asinh(f); + case DMUO_ACOSH: + return acosh(f); + case DMUO_ATANH: + return atanh(f); + case DMUO_CEIL: + return ceil(f); + case DMUO_FLOOR: + return floor(f); + case DMUO_ROUND: + return round(f); + default: + av_assert0(!"not supported yet"); + return 0.f; + } +} + +static int test(DNNMathUnaryOperation op) +{ + DnnLayerMathUnaryParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[1*1*3*3] = { + 0.1, 0.5, 0.75, -3, 2.5, 2, -2.1, 7.8, 100}; + float *output; + + params.un_op = op; + + operands[0].data = input; + operands[0].dims[0] = 1; + operands[0].dims[1] = 1; + operands[0].dims[2] = 3; + operands[0].dims[3] = 3; + operands[1].data = NULL; + + input_indexes[0] = 0; + ff_dnn_execute_layer_math_unary(operands, input_indexes, 1, ¶ms, NULL); + + output = operands[1].data; + for (int i = 0; i < sizeof(input) / sizeof(float); ++i) { + float expected_output = get_expected(input[i], op); + int output_nan = isnan(output[i]); + int expected_nan = isnan(expected_output); + if ((!output_nan && !expected_nan && fabs(output[i] - expected_output) > EPS) || + (output_nan && !expected_nan) || (!output_nan && expected_nan)) { + printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; +} + +int main(int agrc, char **argv) +{ + if (test(DMUO_ABS)) + return 1; + if (test(DMUO_SIN)) + return 1; + if (test(DMUO_COS)) + return 1; + if (test(DMUO_TAN)) + return 1; + if (test(DMUO_ASIN)) + return 1; + if (test(DMUO_ACOS)) + return 1; + if (test(DMUO_ATAN)) + return 1; + if (test(DMUO_SINH)) + return 1; + if (test(DMUO_COSH)) + return 1; + if (test(DMUO_TANH)) + return 1; + if (test(DMUO_ASINH)) + return 1; + if (test(DMUO_ACOSH)) + return 1; + if (test(DMUO_ATANH)) + return 1; + if (test(DMUO_CEIL)) + return 1; + if (test(DMUO_FLOOR)) + return 1; + if (test(DMUO_ROUND)) + return 1; + return 0; +} diff -Nru ffmpeg-4.2.2/tests/dnn/dnn-layer-maximum-test.c ffmpeg-4.4/tests/dnn/dnn-layer-maximum-test.c --- ffmpeg-4.2.2/tests/dnn/dnn-layer-maximum-test.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/dnn/dnn-layer-maximum-test.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019 Guo Yejun + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "libavfilter/dnn/dnn_backend_native_layer_maximum.h" + +#define EPSON 0.00001 + +static int test(void) +{ + DnnLayerMaximumParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[1*1*2*3] = { + -3, 2.5, 2, -2.1, 7.8, 100 + }; + float *output; + + params.val.y = 2.3; + + operands[0].data = input; + operands[0].dims[0] = 1; + operands[0].dims[1] = 1; + operands[0].dims[2] = 2; + operands[0].dims[3] = 3; + operands[1].data = NULL; + + input_indexes[0] = 0; + ff_dnn_execute_layer_maximum(operands, input_indexes, 1, ¶ms, NULL); + + output = operands[1].data; + for (int i = 0; i < sizeof(input) / sizeof(float); i++) { + float expected_output = input[i] > params.val.y ? input[i] : params.val.y; + if (fabs(output[i] - expected_output) > EPSON) { + printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; + +} + +int main(int argc, char **argv) +{ + if (test()) + return 1; + + return 0; +} diff -Nru ffmpeg-4.2.2/tests/dnn/dnn-layer-pad-test.c ffmpeg-4.4/tests/dnn/dnn-layer-pad-test.c --- ffmpeg-4.2.2/tests/dnn/dnn-layer-pad-test.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/dnn/dnn-layer-pad-test.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2019 Guo Yejun + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "libavfilter/dnn/dnn_backend_native_layer_pad.h" + +#define EPSON 0.00001 + +static int test_with_mode_symmetric(void) +{ + // the input data and expected data are generated with below python code. + /* + x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) + y = tf.pad(x, [[0, 0], [2, 3], [3, 2], [0, 0]], 'SYMMETRIC') + data = np.arange(48).reshape(1, 4, 4, 3); + + sess=tf.Session() + sess.run(tf.global_variables_initializer()) + output = sess.run(y, feed_dict={x: data}) + + print(list(data.flatten())) + print(list(output.flatten())) + print(data.shape) + print(output.shape) + */ + + LayerPadParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[1*4*4*3] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47 + }; + float expected_output[1*9*9*3] = { + 18.0, 19.0, 20.0, 15.0, 16.0, 17.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 21.0, 22.0, 23.0, 18.0, 19.0, 20.0, 6.0, 7.0, 8.0, 3.0, + 4.0, 5.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 9.0, 10.0, 11.0, 6.0, 7.0, 8.0, 6.0, 7.0, 8.0, 3.0, 4.0, 5.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 3.0, + 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 9.0, 10.0, 11.0, 6.0, 7.0, 8.0, 18.0, 19.0, 20.0, 15.0, 16.0, 17.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, + 21.0, 22.0, 23.0, 21.0, 22.0, 23.0, 18.0, 19.0, 20.0, 30.0, 31.0, 32.0, 27.0, 28.0, 29.0, 24.0, 25.0, 26.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 33.0, + 34.0, 35.0, 30.0, 31.0, 32.0, 42.0, 43.0, 44.0, 39.0, 40.0, 41.0, 36.0, 37.0, 38.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 45.0, 46.0, 47.0, 42.0, 43.0, + 44.0, 42.0, 43.0, 44.0, 39.0, 40.0, 41.0, 36.0, 37.0, 38.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 45.0, 46.0, 47.0, 42.0, 43.0, 44.0, 30.0, 31.0, 32.0, + 27.0, 28.0, 29.0, 24.0, 25.0, 26.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 33.0, 34.0, 35.0, 30.0, 31.0, 32.0, 18.0, 19.0, 20.0, 15.0, 16.0, 17.0, 12.0, + 13.0, 14.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 21.0, 22.0, 23.0, 18.0, 19.0, 20.0 + }; + float *output; + + params.mode = LPMP_SYMMETRIC; + params.paddings[0][0] = 0; + params.paddings[0][1] = 0; + params.paddings[1][0] = 2; + params.paddings[1][1] = 3; + params.paddings[2][0] = 3; + params.paddings[2][1] = 2; + params.paddings[3][0] = 0; + params.paddings[3][1] = 0; + + operands[0].data = input; + operands[0].dims[0] = 1; + operands[0].dims[1] = 4; + operands[0].dims[2] = 4; + operands[0].dims[3] = 3; + operands[1].data = NULL; + + input_indexes[0] = 0; + ff_dnn_execute_layer_pad(operands, input_indexes, 1, ¶ms, NULL); + + output = operands[1].data; + for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { + if (fabs(output[i] - expected_output[i]) > EPSON) { + printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; + +} + +static int test_with_mode_reflect(void) +{ + // the input data and expected data are generated with below python code. + /* + x = tf.placeholder(tf.float32, shape=[3, None, None, 3]) + y = tf.pad(x, [[1, 2], [0, 0], [0, 0], [0, 0]], 'REFLECT') + data = np.arange(36).reshape(3, 2, 2, 3); + + sess=tf.Session() + sess.run(tf.global_variables_initializer()) + output = sess.run(y, feed_dict={x: data}) + + print(list(data.flatten())) + print(list(output.flatten())) + print(data.shape) + print(output.shape) + */ + + LayerPadParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[3*2*2*3] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 + }; + float expected_output[6*2*2*3] = { + 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, + 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, + 35.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0 + }; + float *output; + + params.mode = LPMP_REFLECT; + params.paddings[0][0] = 1; + params.paddings[0][1] = 2; + params.paddings[1][0] = 0; + params.paddings[1][1] = 0; + params.paddings[2][0] = 0; + params.paddings[2][1] = 0; + params.paddings[3][0] = 0; + params.paddings[3][1] = 0; + + operands[0].data = input; + operands[0].dims[0] = 3; + operands[0].dims[1] = 2; + operands[0].dims[2] = 2; + operands[0].dims[3] = 3; + operands[1].data = NULL; + + input_indexes[0] = 0; + ff_dnn_execute_layer_pad(operands, input_indexes, 1, ¶ms, NULL); + + output = operands[1].data; + for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { + if (fabs(output[i] - expected_output[i]) > EPSON) { + printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; + +} + +static int test_with_mode_constant(void) +{ + // the input data and expected data are generated with below python code. + /* + x = tf.placeholder(tf.float32, shape=[1, None, None, 3]) + y = tf.pad(x, [[0, 0], [1, 0], [0, 0], [1, 2]], 'CONSTANT', constant_values=728) + data = np.arange(12).reshape(1, 2, 2, 3); + + sess=tf.Session() + sess.run(tf.global_variables_initializer()) + output = sess.run(y, feed_dict={x: data}) + + print(list(data.flatten())) + print(list(output.flatten())) + print(data.shape) + print(output.shape) + */ + + LayerPadParams params; + DnnOperand operands[2]; + int32_t input_indexes[1]; + float input[1*2*2*3] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 + }; + float expected_output[1*3*2*6] = { + 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, 728.0, + 728.0, 728.0, 0.0, 1.0, 2.0, 728.0, 728.0, 728.0, 3.0, 4.0, 5.0, 728.0, 728.0, + 728.0, 6.0, 7.0, 8.0, 728.0, 728.0, 728.0, 9.0, 10.0, 11.0, 728.0, 728.0 + }; + float *output; + + params.mode = LPMP_CONSTANT; + params.constant_values = 728; + params.paddings[0][0] = 0; + params.paddings[0][1] = 0; + params.paddings[1][0] = 1; + params.paddings[1][1] = 0; + params.paddings[2][0] = 0; + params.paddings[2][1] = 0; + params.paddings[3][0] = 1; + params.paddings[3][1] = 2; + + operands[0].data = input; + operands[0].dims[0] = 1; + operands[0].dims[1] = 2; + operands[0].dims[2] = 2; + operands[0].dims[3] = 3; + operands[1].data = NULL; + + input_indexes[0] = 0; + ff_dnn_execute_layer_pad(operands, input_indexes, 1, ¶ms, NULL); + + output = operands[1].data; + for (int i = 0; i < sizeof(expected_output) / sizeof(float); i++) { + if (fabs(output[i] - expected_output[i]) > EPSON) { + printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output[i]); + av_freep(&output); + return 1; + } + } + + av_freep(&output); + return 0; + +} + +int main(int argc, char **argv) +{ + if (test_with_mode_symmetric()) + return 1; + + if (test_with_mode_reflect()) + return 1; + + if (test_with_mode_constant()) + return 1; +} diff -Nru ffmpeg-4.2.2/tests/dnn/Makefile ffmpeg-4.4/tests/dnn/Makefile --- ffmpeg-4.2.2/tests/dnn/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/dnn/Makefile 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,18 @@ +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 -Nru ffmpeg-4.2.2/tests/fate/aac.mak ffmpeg-4.4/tests/fate/aac.mak --- ffmpeg-4.2.2/tests/fate/aac.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/aac.mak 2021-04-08 21:28:40.000000000 +0000 @@ -150,7 +150,7 @@ FATE_AAC_ENCODE += fate-aac-aref-encode fate-aac-aref-encode: ./tests/data/asynth-44100-2.wav -fate-aac-aref-encode: CMD = enc_dec_pcm adts wav s16le $(REF) -c:a aac -aac_is 0 -aac_pns 0 -aac_ms 0 -aac_tns 0 -b:a 512k +fate-aac-aref-encode: CMD = enc_dec_pcm adts wav s16le $(REF) -c:a aac -aac_is 0 -aac_pns 0 -aac_ms 0 -aac_tns 0 -b:a 512k -fflags +bitexact -flags +bitexact fate-aac-aref-encode: CMP = stddev fate-aac-aref-encode: REF = ./tests/data/asynth-44100-2.wav fate-aac-aref-encode: CMP_SHIFT = -4096 @@ -159,7 +159,7 @@ fate-aac-aref-encode: FUZZ = 89 FATE_AAC_ENCODE += fate-aac-ln-encode -fate-aac-ln-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -c:a aac -aac_is 0 -aac_pns 0 -aac_ms 0 -aac_tns 0 -b:a 512k +fate-aac-ln-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -c:a aac -aac_is 0 -aac_pns 0 -aac_ms 0 -aac_tns 0 -b:a 512k -fflags +bitexact -flags +bitexact fate-aac-ln-encode: CMP = stddev fate-aac-ln-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-ln-encode: CMP_SHIFT = -4096 @@ -168,7 +168,7 @@ fate-aac-ln-encode: FUZZ = 30 FATE_AAC_ENCODE += fate-aac-ln-encode-128k -fate-aac-ln-encode-128k: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -c:a aac -aac_is 0 -aac_pns 0 -aac_ms 0 -aac_tns 0 -b:a 128k -cutoff 22050 +fate-aac-ln-encode-128k: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -c:a aac -aac_is 0 -aac_pns 0 -aac_ms 0 -aac_tns 0 -b:a 128k -cutoff 22050 -fflags +bitexact -flags +bitexact fate-aac-ln-encode-128k: CMP = stddev fate-aac-ln-encode-128k: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-ln-encode-128k: CMP_SHIFT = -4096 @@ -195,7 +195,7 @@ fate-aac-tns-encode: SIZE_TOLERANCE = 3560 FATE_AAC_ENCODE += fate-aac-is-encode -fate-aac-is-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -c:a aac -aac_pns 0 -aac_is 1 -aac_ms 0 -b:a 128k -aac_tns 0 -cutoff 22050 +fate-aac-is-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -c:a aac -aac_pns 0 -aac_is 1 -aac_ms 0 -b:a 128k -aac_tns 0 -cutoff 22050 -fflags +bitexact -flags +bitexact fate-aac-is-encode: CMP = stddev fate-aac-is-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-is-encode: CMP_SHIFT = -4096 @@ -204,7 +204,7 @@ fate-aac-is-encode: FUZZ = 10 FATE_AAC_ENCODE += fate-aac-ms-encode -fate-aac-ms-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -c:a aac -aac_pns 0 -aac_is 0 -aac_ms 1 -aac_tns 0 -b:a 128k -cutoff 22050 +fate-aac-ms-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -c:a aac -aac_pns 0 -aac_is 0 -aac_ms 1 -aac_tns 0 -b:a 128k -cutoff 22050 -fflags +bitexact -flags +bitexact fate-aac-ms-encode: CMP = stddev fate-aac-ms-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-ms-encode: CMP_SHIFT = -4096 @@ -224,7 +224,7 @@ FATE_AAC_ENCODE += fate-aac-pred-encode -fate-aac-pred-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -profile:a aac_main -c:a aac -aac_is 0 -aac_pns 0 -aac_ms 0 -aac_tns 0 -b:a 128k -cutoff 22050 +fate-aac-pred-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -profile:a aac_main -c:a aac -aac_is 0 -aac_pns 0 -aac_ms 0 -aac_tns 0 -b:a 128k -cutoff 22050 -fflags +bitexact -flags +bitexact fate-aac-pred-encode: CMP = stddev fate-aac-pred-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav fate-aac-pred-encode: CMP_SHIFT = -4096 diff -Nru ffmpeg-4.2.2/tests/fate/ac3.mak ffmpeg-4.4/tests/fate/ac3.mak --- ffmpeg-4.2.2/tests/fate/ac3.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/ac3.mak 2021-04-08 21:28:40.000000000 +0000 @@ -88,9 +88,9 @@ FATE_AC3-$(call ENCMUX, AC3_FIXED, AC3) += fate-ac3-fixed-encode fate-ac3-fixed-encode: tests/data/asynth-44100-2.wav fate-ac3-fixed-encode: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-ac3-fixed-encode: CMD = md5 -i $(SRC) -c ac3_fixed -ab 128k -f ac3 -flags +bitexact +fate-ac3-fixed-encode: CMD = md5 -i $(SRC) -c ac3_fixed -ab 128k -f ac3 -flags +bitexact -af aresample fate-ac3-fixed-encode: CMP = oneline -fate-ac3-fixed-encode: REF = a1d1fc116463b771abf5aef7ed37d7b1 +fate-ac3-fixed-encode: REF = 1f548175e11a95e62ce20e442fcc8d08 FATE_EAC3-$(call ALLYES, EAC3_DEMUXER EAC3_MUXER EAC3_CORE_BSF) += fate-eac3-core-bsf fate-eac3-core-bsf: CMD = md5pipe -i $(TARGET_SAMPLES)/eac3/the_great_wall_7.1.eac3 -c:a copy -bsf:a eac3_core -fflags +bitexact -f eac3 diff -Nru ffmpeg-4.2.2/tests/fate/acodec.mak ffmpeg-4.4/tests/fate/acodec.mak --- ffmpeg-4.2.2/tests/fate/acodec.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/acodec.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,6 +1,6 @@ fate-acodec-%: CODEC = $(@:fate-acodec-%=%) fate-acodec-%: SRC = tests/data/asynth-44100-2.wav -fate-acodec-%: CMD = enc_dec wav $(SRC) $(FMT) "-b:a 128k -c $(CODEC) $(ENCOPTS)" wav "-c pcm_s16le $(DECOPTS)" -keep +fate-acodec-%: CMD = enc_dec wav $(SRC) $(FMT) "-b:a 128k -c $(CODEC) $(ENCOPTS)" wav "-c pcm_s16le $(DECOPTS)" "$(KEEP_OVERRIDE)" fate-acodec-%: CMP_UNIT = 2 fate-acodec-%: REF = $(SRC_PATH)/tests/ref/acodec/$(@:fate-acodec-%=%) @@ -44,12 +44,17 @@ fate-acodec-pcm-u%le: FMT = nut fate-acodec-pcm-f%be: FMT = au -FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_ADX, ADX) += adx -FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_QT, AIFF) += ima_qt -FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_WAV, WAV) += ima_wav -FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_MS, WAV) += ms -FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_SWF, FLV) += swf -FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_YAMAHA, WAV) += yamaha +FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_ADX, ADX) += adx +FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_ARGO, ARGO_ASF) += argo +FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_APM, APM) += ima_apm +FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_ALP, ALP) += ima_alp +FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_QT, AIFF) += ima_qt +FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_SSI, KVAG) += ima_ssi +FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_WAV, WAV) += ima_wav +FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_MS, WAV) += ms +FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_SWF, FLV) += swf +FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_SWF, WAV) += swf-wav +FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_YAMAHA, WAV) += yamaha FATE_ACODEC_ADPCM := $(FATE_ACODEC_ADPCM-yes:%=fate-acodec-adpcm-%) FATE_ACODEC += $(FATE_ACODEC_ADPCM) @@ -58,12 +63,21 @@ fate-acodec-adpcm-%: CODEC = adpcm_$(@:fate-acodec-adpcm-%=%) fate-acodec-adpcm-adx: FMT = adx +fate-acodec-adpcm-argo: FMT = argo_asf +fate-acodec-adpcm-ima_apm: FMT = apm fate-acodec-adpcm-ima_qt: FMT = aiff +fate-acodec-adpcm-ima_ssi: FMT = kvag fate-acodec-adpcm-ima_wav: FMT = wav fate-acodec-adpcm-ms: FMT = wav fate-acodec-adpcm-swf: FMT = flv fate-acodec-adpcm-yamaha: FMT = wav +fate-acodec-adpcm-swf-wav: FMT = wav +fate-acodec-adpcm-swf-wav: CODEC = adpcm_swf + +fate-acodec-adpcm-ima_alp: FMT = alp +fate-acodec-adpcm-ima_alp: ENCOPTS = -type pcm + FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_ADX, ADX) += adx FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_IMA_QT, AIFF) += ima_qt FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_IMA_WAV, WAV) += ima_wav @@ -102,12 +116,12 @@ FATE_ACODEC-$(call ENCDEC, DCA, DTS) += fate-acodec-dca fate-acodec-dca: tests/data/asynth-44100-2.wav fate-acodec-dca: SRC = tests/data/asynth-44100-2.wav -fate-acodec-dca: CMD = md5 -i $(TARGET_PATH)/$(SRC) -c:a dca -strict -2 -f dts -flags +bitexact +fate-acodec-dca: CMD = md5 -i $(TARGET_PATH)/$(SRC) -c:a dca -strict -2 -f dts -flags +bitexact -af aresample fate-acodec-dca: CMP = oneline fate-acodec-dca: REF = 2aa580ac67820fce4f581b96ebb34acc FATE_ACODEC-$(call ENCDEC, DCA, WAV) += fate-acodec-dca2 -fate-acodec-dca2: CMD = enc_dec_pcm dts wav s16le $(SRC) -c:a dca -strict -2 -flags +bitexact +fate-acodec-dca2: CMD = enc_dec_pcm dts wav s16le $(SRC) -c:a dca -strict -2 -flags +bitexact -af aresample fate-acodec-dca2: REF = $(SRC) fate-acodec-dca2: CMP = stddev fate-acodec-dca2: CMP_SHIFT = -2048 diff -Nru ffmpeg-4.2.2/tests/fate/adpcm.mak ffmpeg-4.4/tests/fate/adpcm.mak --- ffmpeg-4.2.2/tests/fate/adpcm.mak 2016-03-29 02:25:33.000000000 +0000 +++ ffmpeg-4.4/tests/fate/adpcm.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,8 +1,8 @@ FATE_ADPCM-$(call DEMDEC, FOURXM, ADPCM_4XM) += fate-adpcm-4xm -fate-adpcm-4xm: CMD = framecrc -i $(TARGET_SAMPLES)/4xm/dracula.4xm -vn -map 0:6 +fate-adpcm-4xm: CMD = framecrc -i $(TARGET_SAMPLES)/4xm/dracula.4xm -vn -map 0:6 -af aresample FATE_ADPCM-$(call DEMDEC, AST, ADPCM_AFC) += fate-adpcm-afc -fate-adpcm-afc: CMD = framecrc -i $(TARGET_SAMPLES)/ast/demo11_02_partial.ast +fate-adpcm-afc: CMD = framecrc -i $(TARGET_SAMPLES)/ast/demo11_02_partial.ast -af aresample FATE_ADPCM-$(call DEMDEC, WAV, ADPCM_CT) += fate-adpcm-creative fate-adpcm-creative: CMD = md5 -i $(TARGET_SAMPLES)/creative/intro-partial.wav -f s16le @@ -17,7 +17,7 @@ fate-adpcm-creative-8-4bit: CMD = md5 -i $(TARGET_SAMPLES)/creative/BBC_4BIT.VOC -f s16le FATE_ADPCM-$(call DEMDEC, ADP, ADPCM_DTK) += fate-adpcm-dtk -fate-adpcm-dtk: CMD = framecrc -i $(TARGET_SAMPLES)/adp/shakespr_partial.adp -f s16le +fate-adpcm-dtk: CMD = framecrc -i $(TARGET_SAMPLES)/adp/shakespr_partial.adp -f s16le -af aresample FATE_ADPCM-$(call DEMDEC, EA, ADPCM_EA) += fate-adpcm-ea-1 fate-adpcm-ea-1: CMD = framecrc -i $(TARGET_SAMPLES)/ea-wve/networkBackbone-partial.wve -frames:a 26 -vn @@ -29,13 +29,13 @@ fate-adpcm-ea-maxis-xa: CMD = framecrc -i $(TARGET_SAMPLES)/maxis-xa/SC2KBUG.XA -frames:a 30 FATE_ADPCM-$(call DEMDEC, EA, ADPCM_EA_R1) += fate-adpcm-ea-r1 -fate-adpcm-ea-r1: CMD = framecrc -i $(TARGET_SAMPLES)/ea-mad/NFS6LogoE.mad -vn +fate-adpcm-ea-r1: CMD = framecrc -i $(TARGET_SAMPLES)/ea-mad/NFS6LogoE.mad -vn -af aresample FATE_ADPCM-$(call DEMDEC, EA, ADPCM_EA_R2) += fate-adpcm-ea-r2 -fate-adpcm-ea-r2: CMD = crc -i $(TARGET_SAMPLES)/ea-mpc/THX_logo.mpc -vn +fate-adpcm-ea-r2: CMD = crc -i $(TARGET_SAMPLES)/ea-mpc/THX_logo.mpc -vn -af aresample FATE_ADPCM-$(call DEMDEC, EA, ADPCM_EA_R3) += fate-adpcm-ea-r3 -fate-adpcm-ea-r3: CMD = crc -i $(TARGET_SAMPLES)/ea-vp6/THX_logo.vp6 -vn +fate-adpcm-ea-r3: CMD = crc -i $(TARGET_SAMPLES)/ea-vp6/THX_logo.vp6 -vn -af aresample FATE_ADPCM-$(call DEMDEC, AVI, ADPCM_IMA_AMV) += fate-adpcm-ima-amv fate-adpcm-ima-amv: CMD = framecrc -i $(TARGET_SAMPLES)/amv/MTV_high_res_320x240_sample_Penguin_Joke_MTV_from_WMV.amv -t 10 -vn @@ -68,7 +68,7 @@ fate-adpcm-ima-smjpeg: CMD = framecrc -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -vn FATE_ADPCM-$(call DEMDEC, MOV, ADPCM_IMA_WAV) += fate-adpcm-ima_wav-stereo -fate-adpcm-ima_wav-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-L-ms11.mov -f s16le +fate-adpcm-ima_wav-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-L-ms11.mov -f s16le -af aresample FATE_ADPCM-$(call DEMDEC, WSVQA, ADPCM_IMA_WS) += fate-adpcm-ima-ws fate-adpcm-ima-ws: CMD = framecrc -i $(TARGET_SAMPLES)/vqa/cc-demo1-partial.vqa -vn @@ -80,13 +80,67 @@ fate-adpcm_ms-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-L-ms02.mov -f s16le FATE_ADPCM-$(call DEMDEC, THP, ADPCM_THP) += fate-adpcm-thp -fate-adpcm-thp: CMD = framecrc -i $(TARGET_SAMPLES)/thp/pikmin2-opening1-partial.thp -vn +fate-adpcm-thp: CMD = framecrc -i $(TARGET_SAMPLES)/thp/pikmin2-opening1-partial.thp -vn -af aresample FATE_ADPCM-$(call DEMDEC, SMUSH, ADPCM_VIMA) += fate-adpcm-vima fate-adpcm-vima: CMD = framecrc -i $(TARGET_SAMPLES)/smush/ronin_part.znm -vn FATE_ADPCM-$(call DEMDEC, STR, ADPCM_XA) += fate-adpcm-xa -fate-adpcm-xa: CMD = framecrc -i $(TARGET_SAMPLES)/psx-str/abc000_cut.str -vn +fate-adpcm-xa: CMD = framecrc -i $(TARGET_SAMPLES)/psx-str/abc000_cut.str -vn -af aresample + +FATE_ADPCM-$(call DEMDEC, ARGO_ASF, ADPCM_ARGO) += fate-adpcm-argo-mono +fate-adpcm-argo-mono: CMD = md5 -i $(TARGET_SAMPLES)/argo-asf/PWIN22M.ASF -f s16le -af aresample + +FATE_ADPCM-$(call DEMDEC, ARGO_ASF, ADPCM_ARGO) += fate-adpcm-argo-stereo +fate-adpcm-argo-stereo: CMD = md5 -i $(TARGET_SAMPLES)/argo-asf/CBK2_cut.asf -f s16le -af aresample + +FATE_ADPCM-$(call DEMDEC, KVAG, ADPCM_IMA_SSI) += fate-adpcm-ima-ssi-mono +fate-adpcm-ima-ssi-mono: CMD = md5 -i $(TARGET_SAMPLES)/kvag/mull1_cut.vag -f s16le + +FATE_ADPCM-$(call DEMDEC, KVAG, ADPCM_IMA_SSI) += fate-adpcm-ima-ssi-stereo +fate-adpcm-ima-ssi-stereo: CMD = md5 -i $(TARGET_SAMPLES)/kvag/credits_cut.vag -f s16le + +FATE_ADPCM-$(call DEMDEC, APM, ADPCM_IMA_APM) += fate-adpcm-ima-apm-mono +fate-adpcm-ima-apm-mono: CMD = md5 -i $(TARGET_SAMPLES)/apm/outro1.apm -f s16le + +FATE_ADPCM-$(call DEMDEC, APM, ADPCM_IMA_APM) += fate-adpcm-ima-apm-stereo +fate-adpcm-ima-apm-stereo: CMD = md5 -i $(TARGET_SAMPLES)/apm/AS01.apm -f s16le + +FATE_ADPCM-$(call DEMDEC, ALP, ADPCM_IMA_ALP) += fate-adpcm-ima-alp-mono +fate-adpcm-ima-alp-mono: CMD = md5 -i $(TARGET_SAMPLES)/alp/AD_P11.PCM -f s16le + +FATE_ADPCM-$(call DEMDEC, ALP, ADPCM_IMA_ALP) += fate-adpcm-ima-alp-stereo +fate-adpcm-ima-alp-stereo: CMD = md5 -i $(TARGET_SAMPLES)/alp/theme-cut.tun -f s16le + +FATE_ADPCM-$(call DEMDEC, PP_BNK, ADPCM_IMA_CUNNING) += fate-adpcm-ima-cunning-single +fate-adpcm-ima-cunning-single: CMD = md5 -y -i $(TARGET_SAMPLES)/pp_bnk/GD-cut.5c -f s16le -af aresample + +FATE_ADPCM-$(call DEMDEC, PP_BNK, ADPCM_IMA_CUNNING) += fate-adpcm-ima-cunning-track0 +fate-adpcm-ima-cunning-track0: CMD = md5 -y -i $(TARGET_SAMPLES)/pp_bnk/VIDEOMOD-cut.11c -map 0:a:0 -f s16le -af aresample + +FATE_ADPCM-$(call DEMDEC, PP_BNK, ADPCM_IMA_CUNNING) += fate-adpcm-ima-cunning-track1 +fate-adpcm-ima-cunning-track1: CMD = md5 -y -i $(TARGET_SAMPLES)/pp_bnk/VIDEOMOD-cut.11c -map 0:a:1 -f s16le -af aresample + +FATE_ADPCM-$(call DEMDEC, PP_BNK, ADPCM_IMA_CUNNING) += fate-adpcm-ima-cunning-trunc-t1 +fate-adpcm-ima-cunning-trunc-t1: CMD = md5 -y -i $(TARGET_SAMPLES)/pp_bnk/VIDEOMOD-trunc-t1.11c -map 0:a:0 -f s16le -af aresample + +FATE_ADPCM-$(call DEMDEC, PP_BNK, ADPCM_IMA_CUNNING) += fate-adpcm-ima-cunning-trunc-t2-track0 +fate-adpcm-ima-cunning-trunc-t2-track0: CMD = md5 -y -i $(TARGET_SAMPLES)/pp_bnk/VIDEOMOD-trunc-t2.11c -map 0:a:0 -f s16le -af aresample + +FATE_ADPCM-$(call DEMDEC, PP_BNK, ADPCM_IMA_CUNNING) += fate-adpcm-ima-cunning-trunc-t2-track1 +fate-adpcm-ima-cunning-trunc-t2-track1: CMD = md5 -y -i $(TARGET_SAMPLES)/pp_bnk/VIDEOMOD-trunc-t2.11c -map 0:a:1 -f s16le -af aresample + +FATE_ADPCM-$(call DEMDEC, PP_BNK, ADPCM_IMA_CUNNING) += fate-adpcm-ima-cunning-trunc-t2a-track0 +fate-adpcm-ima-cunning-trunc-t2a-track0: CMD = md5 -y -i $(TARGET_SAMPLES)/pp_bnk/VIDEOMOD-trunc-t2a.11c -map 0:a:0 -f s16le -af aresample + +FATE_ADPCM-$(call DEMDEC, PP_BNK, ADPCM_IMA_CUNNING) += fate-adpcm-ima-cunning-trunc-t2a-track1 +fate-adpcm-ima-cunning-trunc-t2a-track1: CMD = md5 -y -i $(TARGET_SAMPLES)/pp_bnk/VIDEOMOD-trunc-t2a.11c -map 0:a:1 -f s16le -af aresample + +FATE_ADPCM-$(call DEMDEC, PP_BNK, ADPCM_IMA_CUNNING) += fate-adpcm-ima-cunning-trunc-h2 +fate-adpcm-ima-cunning-trunc-h2: CMD = md5 -y -i $(TARGET_SAMPLES)/pp_bnk/VIDEOMOD-trunc-h2.11c -map 0:a:0 -f s16le -af aresample + +FATE_ADPCM-$(call DEMDEC, PP_BNK, ADPCM_IMA_CUNNING) += fate-adpcm-ima-cunning-stereo +fate-adpcm-ima-cunning-stereo: CMD = md5 -y -i $(TARGET_SAMPLES)/pp_bnk/MOGODON2-cut.44c -f s16le -af aresample FATE_SAMPLES_AVCONV += $(FATE_ADPCM-yes) fate-adpcm: $(FATE_ADPCM-yes) diff -Nru ffmpeg-4.2.2/tests/fate/als.mak ffmpeg-4.4/tests/fate/als.mak --- ffmpeg-4.2.2/tests/fate/als.mak 2016-03-29 02:25:33.000000000 +0000 +++ ffmpeg-4.4/tests/fate/als.mak 2020-07-11 10:39:30.000000000 +0000 @@ -7,5 +7,9 @@ $(foreach N,$(ALS_SUITE),$(eval $(call FATE_ALS_SUITE,$(N)))) +FATE_ALS += fate-mpeg4-als-conformance-09 + +fate-mpeg4-als-conformance-09: CMD = crc -i $(TARGET_SAMPLES)/lossless-audio/als_09_512ch2k16b.mp4 + FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, ALS) += $(FATE_ALS) fate-als: $(FATE_ALS) diff -Nru ffmpeg-4.2.2/tests/fate/api.mak ffmpeg-4.4/tests/fate/api.mak --- ffmpeg-4.2.2/tests/fate/api.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/api.mak 2021-04-08 21:28:40.000000000 +0000 @@ -21,14 +21,6 @@ fate-api-seek: CMD = run $(APITESTSDIR)/api-seek-test$(EXESUF) $(TARGET_PATH)/tests/data/lavf/lavf.flv 0 720 fate-api-seek: CMP = null -FATE_API_SAMPLES_LIBAVFORMAT-$(call DEMDEC, IMAGE2, PNG) += fate-api-png-codec-param -fate-api-png-codec-param: $(APITESTSDIR)/api-codec-param-test$(EXESUF) -fate-api-png-codec-param: CMD = run $(APITESTSDIR)/api-codec-param-test$(EXESUF) $(TARGET_SAMPLES)/png1/lena-rgba.png - -FATE_API_SAMPLES_LIBAVFORMAT-$(call DEMDEC, IMAGE2, MJPEG) += fate-api-mjpeg-codec-param -fate-api-mjpeg-codec-param: $(APITESTSDIR)/api-codec-param-test$(EXESUF) -fate-api-mjpeg-codec-param: CMD = run $(APITESTSDIR)/api-codec-param-test$(EXESUF) $(TARGET_SAMPLES)/exif/image_small.jpg - FATE_API-$(HAVE_THREADS) += fate-api-threadmessage fate-api-threadmessage: $(APITESTSDIR)/api-threadmessage-test$(EXESUF) fate-api-threadmessage: CMD = run $(APITESTSDIR)/api-threadmessage-test$(EXESUF) 3 10 30 50 2 20 40 diff -Nru ffmpeg-4.2.2/tests/fate/apng.mak ffmpeg-4.4/tests/fate/apng.mak --- ffmpeg-4.2.2/tests/fate/apng.mak 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/fate/apng.mak 2021-04-08 21:28:40.000000000 +0000 @@ -4,6 +4,9 @@ FATE_APNG += fate-apng-osample fate-apng-osample: CMD = framecrc -i $(TARGET_SAMPLES)/apng/o_sample.png +FATE_APNG += fate-apng-dispose-previous +fate-apng-dispose-previous: CMD = framecrc -i $(TARGET_SAMPLES)/apng/apng_out_of_order_frames.png + FATE_APNG-$(call DEMDEC, APNG, APNG) += $(FATE_APNG) FATE_SAMPLES_FFMPEG += $(FATE_APNG-yes) diff -Nru ffmpeg-4.2.2/tests/fate/audio.mak ffmpeg-4.4/tests/fate/audio.mak --- ffmpeg-4.2.2/tests/fate/audio.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/audio.mak 2021-04-08 21:28:40.000000000 +0000 @@ -25,7 +25,7 @@ fate-dolby-e: REF = $(SAMPLES)/dolby_e/16-11.pcm FATE_SAMPLES_AUDIO-$(call DEMDEC, DSS, DSS_SP) += fate-dss-lp fate-dss-sp -fate-dss-lp: CMD = framecrc -i $(TARGET_SAMPLES)/dss/lp.dss -frames 30 +fate-dss-lp: CMD = framecrc -i $(TARGET_SAMPLES)/dss/lp.dss -frames 30 -af aresample fate-dss-sp: CMD = framecrc -i $(TARGET_SAMPLES)/dss/sp.dss -frames 30 FATE_SAMPLES_AUDIO-$(call DEMDEC, DSF, DST) += fate-dsf-dst @@ -53,19 +53,19 @@ fate-nellymoser-aref-encode: SIZE_TOLERANCE = 268 FATE_SAMPLES_AUDIO-$(call DEMDEC, AVI, ON2AVC) += fate-on2avc -fate-on2avc: CMD = framecrc -i $(TARGET_SAMPLES)/vp7/potter-40.vp7 -frames 30 -vn +fate-on2avc: CMD = framecrc -i $(TARGET_SAMPLES)/vp7/potter-40.vp7 -frames 30 -vn -af aresample FATE_SAMPLES_AUDIO-$(call DEMDEC, PAF, PAF_AUDIO) += fate-paf-audio fate-paf-audio: CMD = framecrc -i $(TARGET_SAMPLES)/paf/hod1-partial.paf -vn FATE_SAMPLES_AUDIO-$(call DEMDEC, VMD, VMDAUDIO) += fate-sierra-vmd-audio -fate-sierra-vmd-audio: CMD = framecrc -i $(TARGET_SAMPLES)/vmd/12.vmd -vn +fate-sierra-vmd-audio: CMD = framecrc -i $(TARGET_SAMPLES)/vmd/12.vmd -vn -af aresample FATE_SAMPLES_AUDIO-$(call DEMDEC, SMACKER, SMACKAUD) += fate-smacker-audio -fate-smacker-audio: CMD = framecrc -i $(TARGET_SAMPLES)/smacker/wetlogo.smk -vn +fate-smacker-audio: CMD = framecrc -i $(TARGET_SAMPLES)/smacker/wetlogo.smk -vn -af aresample FATE_SAMPLES_AUDIO-$(call DEMDEC, WSVQA, WS_SND1) += fate-ws_snd -fate-ws_snd: CMD = md5 -i $(TARGET_SAMPLES)/vqa/ws_snd.vqa -f s16le +fate-ws_snd: CMD = md5 -i $(TARGET_SAMPLES)/vqa/ws_snd.vqa -f s16le -af aresample fate-flcl1905: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_frames -show_packets -print_format compact $(TARGET_SAMPLES)/wav/FLCL_Ending_My-short.wav diff -Nru ffmpeg-4.2.2/tests/fate/bmp.mak ffmpeg-4.4/tests/fate/bmp.mak --- ffmpeg-4.2.2/tests/fate/bmp.mak 2016-03-29 02:25:33.000000000 +0000 +++ ffmpeg-4.4/tests/fate/bmp.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,41 +1,41 @@ FATE_BMP += fate-bmp-1bit -fate-bmp-1bit: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test1.bmp -pix_fmt rgb24 +fate-bmp-1bit: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test1.bmp -pix_fmt rgb24 -vf scale FATE_BMP += fate-bmp-4bit -fate-bmp-4bit: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test4.bmp -pix_fmt rgb24 +fate-bmp-4bit: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test4.bmp -pix_fmt rgb24 -vf scale FATE_BMP += fate-bmp-4bit-os2 -fate-bmp-4bit-os2: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test4os2v2.bmp -pix_fmt rgb24 +fate-bmp-4bit-os2: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test4os2v2.bmp -pix_fmt rgb24 -vf scale FATE_BMP += fate-bmp-8bit -fate-bmp-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test8.bmp -pix_fmt rgb24 +fate-bmp-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test8.bmp -pix_fmt rgb24 -vf scale FATE_BMP += fate-bmp-8bit-os2 -fate-bmp-8bit-os2: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test8os2.bmp -pix_fmt rgb24 +fate-bmp-8bit-os2: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test8os2.bmp -pix_fmt rgb24 -vf scale FATE_BMP += fate-bmp-15bit -fate-bmp-15bit: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test16.bmp -pix_fmt rgb555le +fate-bmp-15bit: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test16.bmp -pix_fmt rgb555le -vf scale FATE_BMP += fate-bmp-15bit-mask -fate-bmp-15bit-mask: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test16bf555.bmp -pix_fmt rgb555le +fate-bmp-15bit-mask: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test16bf555.bmp -pix_fmt rgb555le -vf scale FATE_BMP += fate-bmp-16bit-mask -fate-bmp-16bit-mask: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test16bf565.bmp -pix_fmt rgb565le +fate-bmp-16bit-mask: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test16bf565.bmp -pix_fmt rgb565le -vf scale FATE_BMP += fate-bmp-24bit fate-bmp-24bit: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test24.bmp FATE_BMP += fate-bmp-32bit -fate-bmp-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test32.bmp -pix_fmt bgr24 +fate-bmp-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test32.bmp -pix_fmt bgr24 -vf scale FATE_BMP += fate-bmp-32bit-mask -fate-bmp-32bit-mask: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test32bf.bmp -pix_fmt bgr24 +fate-bmp-32bit-mask: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test32bf.bmp -pix_fmt bgr24 -vf scale FATE_BMP += fate-bmp-rle4 -fate-bmp-rle4: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/testcompress4.bmp -pix_fmt rgb24 +fate-bmp-rle4: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/testcompress4.bmp -pix_fmt rgb24 -vf scale FATE_BMP += fate-bmp-rle8 -fate-bmp-rle8: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/testcompress8.bmp -pix_fmt rgb24 +fate-bmp-rle8: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/testcompress8.bmp -pix_fmt rgb24 -vf scale FATE_BMP-$(call DEMDEC, IMAGE2, BMP) += $(FATE_BMP) diff -Nru ffmpeg-4.2.2/tests/fate/canopus.mak ffmpeg-4.4/tests/fate/canopus.mak --- ffmpeg-4.2.2/tests/fate/canopus.mak 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/fate/canopus.mak 2021-04-08 21:28:40.000000000 +0000 @@ -25,10 +25,10 @@ fate-canopus-hq_hqa: $(FATE_CANOPUS_HQ_HQA) FATE_CANOPUS_HQX += fate-canopus-hqx422 -fate-canopus-hqx422: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hqx422.avi -pix_fmt yuv422p16be -an +fate-canopus-hqx422: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hqx422.avi -pix_fmt yuv422p16be -an -vf scale FATE_CANOPUS_HQX += fate-canopus-hqx422a -fate-canopus-hqx422a: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hqx422a.avi -pix_fmt yuv422p16be -an +fate-canopus-hqx422a: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hqx422a.avi -pix_fmt yuv422p16be -an -vf scale FATE_SAMPLES_FFMPEG-$(call DEMDEC, AVI, HQX) += $(FATE_CANOPUS_HQX) fate-canopus-hqx: $(FATE_CANOPUS_HQX) diff -Nru ffmpeg-4.2.2/tests/fate/cbs.mak ffmpeg-4.4/tests/fate/cbs.mak --- ffmpeg-4.2.2/tests/fate/cbs.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/cbs.mak 2021-04-08 21:28:40.000000000 +0000 @@ -2,16 +2,45 @@ # arguments, it decomposes the stream fully and then recomposes it # without making any changes. -fate-cbs: fate-cbs-h264 fate-cbs-hevc fate-cbs-mpeg2 fate-cbs-vp9 +fate-cbs: fate-cbs-av1 fate-cbs-h264 fate-cbs-hevc fate-cbs-mpeg2 fate-cbs-vp9 FATE_CBS_DEPS = $(call ALLYES, $(1)_DEMUXER $(2)_PARSER $(3)_METADATA_BSF $(4)_DECODER $(5)_MUXER) define FATE_CBS_TEST # (codec, test_name, sample_file, output_format) FATE_CBS_$(1) += fate-cbs-$(1)-$(2) -fate-cbs-$(1)-$(2): CMD = md5 -i $(TARGET_SAMPLES)/$(3) -c:v copy -y -bsf:v $(1)_metadata -f $(4) +fate-cbs-$(1)-$(2): CMD = md5 -c:v $(3) -i $(TARGET_SAMPLES)/$(4) -c:v copy -y -bsf:v $(1)_metadata -f $(5) endef +# AV1 read/write + +FATE_CBS_AV1_CONFORMANCE_SAMPLES = \ + av1-1-b8-02-allintra.ivf \ + av1-1-b8-03-sizedown.ivf \ + av1-1-b8-03-sizeup.ivf \ + av1-1-b8-04-cdfupdate.ivf \ + av1-1-b8-05-mv.ivf \ + av1-1-b8-06-mfmv.ivf \ + av1-1-b8-22-svc-L1T2.ivf \ + av1-1-b8-22-svc-L2T1.ivf \ + av1-1-b8-22-svc-L2T2.ivf \ + av1-1-b8-23-film_grain-50.ivf \ + av1-1-b10-23-film_grain-50.ivf + +FATE_CBS_AV1_SAMPLES = \ + decode_model.ivf \ + frames_refs_short_signaling.ivf \ + non_uniform_tiling.ivf \ + seq_hdr_op_param_info.ivf \ + switch_frame.ivf + +$(foreach N,$(FATE_CBS_AV1_CONFORMANCE_SAMPLES),$(eval $(call FATE_CBS_TEST,av1,$(basename $(N)),av1,av1-test-vectors/$(N),rawvideo))) +$(foreach N,$(FATE_CBS_AV1_SAMPLES),$(eval $(call FATE_CBS_TEST,av1,$(basename $(N)),av1,av1/$(N),rawvideo))) + +FATE_CBS_AV1-$(call FATE_CBS_DEPS, IVF, AV1, AV1, AV1, RAWVIDEO) = $(FATE_CBS_av1) +FATE_SAMPLES_AVCONV += $(FATE_CBS_AV1-yes) +fate-cbs-av1: $(FATE_CBS_AV1-yes) + # H.264 read/write FATE_CBS_H264_CONFORMANCE_SAMPLES = \ @@ -33,8 +62,8 @@ FATE_CBS_H264_SAMPLES = \ sei-1.h264 -$(foreach N,$(FATE_CBS_H264_CONFORMANCE_SAMPLES),$(eval $(call FATE_CBS_TEST,h264,$(basename $(N)),h264-conformance/$(N),h264))) -$(foreach N,$(FATE_CBS_H264_SAMPLES),$(eval $(call FATE_CBS_TEST,h264,$(basename $(N)),h264/$(N),h264))) +$(foreach N,$(FATE_CBS_H264_CONFORMANCE_SAMPLES),$(eval $(call FATE_CBS_TEST,h264,$(basename $(N)),h264,h264-conformance/$(N),h264))) +$(foreach N,$(FATE_CBS_H264_SAMPLES),$(eval $(call FATE_CBS_TEST,h264,$(basename $(N)),h264,h264/$(N),h264))) FATE_CBS_H264-$(call FATE_CBS_DEPS, H264, H264, H264, H264, H264) = $(FATE_CBS_h264) FATE_SAMPLES_AVCONV += $(FATE_CBS_H264-yes) @@ -64,7 +93,7 @@ HRD_A_Fujitsu_2.bit \ SLPPLP_A_VIDYO_2.bit -$(foreach N,$(FATE_CBS_HEVC_SAMPLES),$(eval $(call FATE_CBS_TEST,hevc,$(basename $(N)),hevc-conformance/$(N),hevc))) +$(foreach N,$(FATE_CBS_HEVC_SAMPLES),$(eval $(call FATE_CBS_TEST,hevc,$(basename $(N)),hevc,hevc-conformance/$(N),hevc))) FATE_CBS_HEVC-$(call FATE_CBS_DEPS, HEVC, HEVC, HEVC, HEVC, HEVC) = $(FATE_CBS_hevc) FATE_SAMPLES_AVCONV += $(FATE_CBS_HEVC-yes) @@ -77,7 +106,7 @@ sony-ct3.bs \ tcela-6.bits -$(foreach N,$(FATE_CBS_MPEG2_SAMPLES),$(eval $(call FATE_CBS_TEST,mpeg2,$(basename $(N)),mpeg2/$(N),mpeg2video))) +$(foreach N,$(FATE_CBS_MPEG2_SAMPLES),$(eval $(call FATE_CBS_TEST,mpeg2,$(basename $(N)),mpeg2video,mpeg2/$(N),mpeg2video))) FATE_CBS_MPEG2-$(call FATE_CBS_DEPS, MPEGVIDEO, MPEGVIDEO, MPEG2, MPEG2VIDEO, MPEG2VIDEO) = $(FATE_CBS_mpeg2) FATE_SAMPLES_AVCONV += $(FATE_CBS_MPEG2-yes) @@ -101,7 +130,7 @@ vp93-2-20-10bit-yuv422.webm \ vp93-2-20-12bit-yuv444.webm -$(foreach N,$(FATE_CBS_VP9_SAMPLES),$(eval $(call FATE_CBS_TEST,vp9,$(basename $(N)),vp9-test-vectors/$(N),ivf))) +$(foreach N,$(FATE_CBS_VP9_SAMPLES),$(eval $(call FATE_CBS_TEST,vp9,$(basename $(N)),vp9,vp9-test-vectors/$(N),ivf))) FATE_CBS_VP9-$(call FATE_CBS_DEPS, IVF, VP9, VP9, VP9, IVF) = $(FATE_CBS_vp9) FATE_SAMPLES_AVCONV += $(FATE_CBS_VP9-yes) diff -Nru ffmpeg-4.2.2/tests/fate/cdxl.mak ffmpeg-4.4/tests/fate/cdxl.mak --- ffmpeg-4.2.2/tests/fate/cdxl.mak 2016-03-29 02:25:33.000000000 +0000 +++ ffmpeg-4.4/tests/fate/cdxl.mak 2021-04-08 21:28:40.000000000 +0000 @@ -8,10 +8,10 @@ fate-cdxl-ham8: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/mirage.cdxl -an -frames:v 1 FATE_CDXL += fate-cdxl-pal8 -fate-cdxl-pal8: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/maku.cdxl -pix_fmt rgb24 -frames:v 11 +fate-cdxl-pal8: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/maku.cdxl -pix_fmt rgb24 -frames:v 11 -vf scale FATE_CDXL += fate-cdxl-pal8-small -fate-cdxl-pal8-small: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/fruit.cdxl -an -pix_fmt rgb24 -frames:v 46 +fate-cdxl-pal8-small: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/fruit.cdxl -an -pix_fmt rgb24 -frames:v 46 -vf scale FATE_CDXL-$(call DEMDEC, CDXL, CDXL) += $(FATE_CDXL) diff -Nru ffmpeg-4.2.2/tests/fate/checkasm.mak ffmpeg-4.4/tests/fate/checkasm.mak --- ffmpeg-4.2.2/tests/fate/checkasm.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/checkasm.mak 2020-07-11 10:39:30.000000000 +0000 @@ -19,14 +19,17 @@ fate-checkasm-jpeg2000dsp \ fate-checkasm-llviddsp \ fate-checkasm-llviddspenc \ + fate-checkasm-opusdsp \ fate-checkasm-pixblockdsp \ fate-checkasm-sbrdsp \ fate-checkasm-synth_filter \ fate-checkasm-sw_rgb \ + fate-checkasm-sw_scale \ fate-checkasm-v210dec \ fate-checkasm-v210enc \ fate-checkasm-vf_blend \ fate-checkasm-vf_colorspace \ + fate-checkasm-vf_eq \ fate-checkasm-vf_gblur \ fate-checkasm-vf_hflip \ fate-checkasm-vf_threshold \ diff -Nru ffmpeg-4.2.2/tests/fate/dca.mak ffmpeg-4.4/tests/fate/dca.mak --- ffmpeg-4.2.2/tests/fate/dca.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/dca.mak 2021-04-08 21:28:40.000000000 +0000 @@ -23,14 +23,14 @@ define FATE_DCADEC_LOSSLESS_SUITE FATE_DCADEC_LOSSLESS += fate-dca-$(1) fate-dca-$(1)-dmix_2 fate-dca-$(1)-dmix_6 -fate-dca-$(1): CMD = framemd5 -i $(TARGET_SAMPLES)/dts/dcadec-suite/$(1).dtshd -c:a pcm_$(2) -fate-dca-$(1)-dmix_2: CMD = framemd5 -request_channel_layout 0x3 -i $(TARGET_SAMPLES)/dts/dcadec-suite/$(1).dtshd -c:a pcm_$(2) -fate-dca-$(1)-dmix_6: CMD = framemd5 -request_channel_layout 0x60f -i $(TARGET_SAMPLES)/dts/dcadec-suite/$(1).dtshd -c:a pcm_$(2) +fate-dca-$(1): CMD = framemd5 -i $(TARGET_SAMPLES)/dts/dcadec-suite/$(1).dtshd -c:a pcm_$(2) -af aresample +fate-dca-$(1)-dmix_2: CMD = framemd5 -request_channel_layout 0x3 -i $(TARGET_SAMPLES)/dts/dcadec-suite/$(1).dtshd -c:a pcm_$(2) -af aresample +fate-dca-$(1)-dmix_6: CMD = framemd5 -request_channel_layout 0x60f -i $(TARGET_SAMPLES)/dts/dcadec-suite/$(1).dtshd -c:a pcm_$(2) -af aresample endef define FATE_DCADEC_LOSSY_SUITE FATE_DCADEC_LOSSY += fate-dca-$(1) -fate-dca-$(1): CMD = ffmpeg -i $(TARGET_SAMPLES)/dts/dcadec-suite/$(1).dtshd -f f32le - +fate-dca-$(1): CMD = ffmpeg -i $(TARGET_SAMPLES)/dts/dcadec-suite/$(1).dtshd -f f32le -af aresample - fate-dca-$(1): REF = $(SAMPLES)/dts/dcadec-suite/$(1).f32 endef @@ -40,20 +40,20 @@ # lossy downmix tests FATE_DCADEC_LOSSY += fate-dca-core_51_24_48_768_1-dmix_2 -fate-dca-core_51_24_48_768_1-dmix_2: CMD = ffmpeg -request_channel_layout 0x3 -i $(TARGET_SAMPLES)/dts/dcadec-suite/core_51_24_48_768_1.dtshd -f f32le - +fate-dca-core_51_24_48_768_1-dmix_2: CMD = ffmpeg -request_channel_layout 0x3 -i $(TARGET_SAMPLES)/dts/dcadec-suite/core_51_24_48_768_1.dtshd -f f32le -af aresample - fate-dca-core_51_24_48_768_1-dmix_2: REF = $(SAMPLES)/dts/dcadec-suite/core_51_24_48_768_1-dmix_2.f32 FATE_DCADEC_LOSSY += fate-dca-x96_xxch_71_24_96_3840-dmix_2 -fate-dca-x96_xxch_71_24_96_3840-dmix_2: CMD = ffmpeg -request_channel_layout 0x3 -i $(TARGET_SAMPLES)/dts/dcadec-suite/x96_xxch_71_24_96_3840.dtshd -f f32le - +fate-dca-x96_xxch_71_24_96_3840-dmix_2: CMD = ffmpeg -request_channel_layout 0x3 -i $(TARGET_SAMPLES)/dts/dcadec-suite/x96_xxch_71_24_96_3840.dtshd -f f32le -af aresample - # intentionally uses the dmix_6 reference because the sample does not contain stereo downmix coefficients fate-dca-x96_xxch_71_24_96_3840-dmix_2: REF = $(SAMPLES)/dts/dcadec-suite/x96_xxch_71_24_96_3840-dmix_6.f32 FATE_DCADEC_LOSSY += fate-dca-x96_xxch_71_24_96_3840-dmix_6 -fate-dca-x96_xxch_71_24_96_3840-dmix_6: CMD = ffmpeg -request_channel_layout 0x60f -i $(TARGET_SAMPLES)/dts/dcadec-suite/x96_xxch_71_24_96_3840.dtshd -f f32le - +fate-dca-x96_xxch_71_24_96_3840-dmix_6: CMD = ffmpeg -request_channel_layout 0x60f -i $(TARGET_SAMPLES)/dts/dcadec-suite/x96_xxch_71_24_96_3840.dtshd -f f32le -af aresample - fate-dca-x96_xxch_71_24_96_3840-dmix_6: REF = $(SAMPLES)/dts/dcadec-suite/x96_xxch_71_24_96_3840-dmix_6.f32 FATE_DCADEC_LOSSY += fate-dca-xch_61_24_48_768-dmix_6 -fate-dca-xch_61_24_48_768-dmix_6: CMD = ffmpeg -request_channel_layout 0x60f -i $(TARGET_SAMPLES)/dts/dcadec-suite/xch_61_24_48_768.dtshd -f f32le - +fate-dca-xch_61_24_48_768-dmix_6: CMD = ffmpeg -request_channel_layout 0x60f -i $(TARGET_SAMPLES)/dts/dcadec-suite/xch_61_24_48_768.dtshd -f f32le -af aresample - fate-dca-xch_61_24_48_768-dmix_6: REF = $(SAMPLES)/dts/dcadec-suite/xch_61_24_48_768-dmix_6.f32 $(FATE_DCADEC_LOSSY): CMP = oneoff @@ -68,7 +68,7 @@ fate-dca-core: REF = $(SAMPLES)/dts/dts.pcm FATE_DCA-$(call DEMDEC, DTS, DCA) += fate-dca-xll -fate-dca-xll: CMD = md5 -i $(TARGET_SAMPLES)/dts/master_audio_7.1_24bit.dts -f s24le +fate-dca-xll: CMD = md5 -i $(TARGET_SAMPLES)/dts/master_audio_7.1_24bit.dts -f s24le -af aresample FATE_DCA-$(call DEMDEC, DTS, DCA) += fate-dts_es fate-dts_es: CMD = pcm -i $(TARGET_SAMPLES)/dts/dts_es.dts diff -Nru ffmpeg-4.2.2/tests/fate/demux.mak ffmpeg-4.4/tests/fate/demux.mak --- ffmpeg-4.2.2/tests/fate/demux.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/demux.mak 2021-04-08 21:28:40.000000000 +0000 @@ -7,9 +7,15 @@ fate-adts-id3v2-demux: CMD = framecrc -f aac -i $(TARGET_SAMPLES)/aac/id3v2.aac -c:a copy fate-adts-id3v2-two-tags-demux: CMD = framecrc -i $(TARGET_SAMPLES)/aac/id3v2_two_tags.aac -c:a copy +FATE_SAMPLES_DEMUX-$(CONFIG_AA_DEMUXER) += fate-aa-demux +fate-aa-demux: CMD = framecrc -i $(TARGET_SAMPLES)/aa/bush.aa -c:a copy + FATE_SAMPLES_DEMUX-$(CONFIG_AEA_DEMUXER) += fate-aea-demux fate-aea-demux: CMD = crc -i $(TARGET_SAMPLES)/aea/chirp.aea -c:a copy +FATE_SAMPLES_DEMUX-$(call DEMDEC, AV1, AV1) += fate-av1-annexb-demux +fate-av1-annexb-demux: CMD = framecrc -c:v av1 -i $(TARGET_SAMPLES)/av1/annexb.obu -c:v copy + FATE_SAMPLES_DEMUX-$(CONFIG_AST_DEMUXER) += fate-ast fate-ast: CMD = crc -i $(TARGET_SAMPLES)/ast/demo11_02_partial.ast -c copy diff -Nru ffmpeg-4.2.2/tests/fate/dfa.mak ffmpeg-4.4/tests/fate/dfa.mak --- ffmpeg-4.2.2/tests/fate/dfa.mak 2016-03-29 02:25:33.000000000 +0000 +++ ffmpeg-4.4/tests/fate/dfa.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,35 +1,35 @@ FATE_DFA += fate-dfa1 -fate-dfa1: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0000.dfa -pix_fmt rgb24 +fate-dfa1: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0000.dfa -pix_fmt rgb24 -vf scale FATE_DFA += fate-dfa2 -fate-dfa2: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0001.dfa -pix_fmt rgb24 +fate-dfa2: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0001.dfa -pix_fmt rgb24 -vf scale FATE_DFA += fate-dfa3 -fate-dfa3: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0002.dfa -pix_fmt rgb24 +fate-dfa3: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0002.dfa -pix_fmt rgb24 -vf scale FATE_DFA += fate-dfa4 -fate-dfa4: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0003.dfa -pix_fmt rgb24 +fate-dfa4: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0003.dfa -pix_fmt rgb24 -vf scale FATE_DFA += fate-dfa5 -fate-dfa5: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0004.dfa -pix_fmt rgb24 +fate-dfa5: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0004.dfa -pix_fmt rgb24 -vf scale FATE_DFA += fate-dfa6 -fate-dfa6: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0005.dfa -pix_fmt rgb24 +fate-dfa6: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0005.dfa -pix_fmt rgb24 -vf scale FATE_DFA += fate-dfa7 -fate-dfa7: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0006.dfa -pix_fmt rgb24 +fate-dfa7: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0006.dfa -pix_fmt rgb24 -vf scale FATE_DFA += fate-dfa8 -fate-dfa8: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0007.dfa -pix_fmt rgb24 +fate-dfa8: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0007.dfa -pix_fmt rgb24 -vf scale FATE_DFA += fate-dfa9 -fate-dfa9: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0008.dfa -pix_fmt rgb24 +fate-dfa9: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0008.dfa -pix_fmt rgb24 -vf scale FATE_DFA += fate-dfa10 -fate-dfa10: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0009.dfa -pix_fmt rgb24 +fate-dfa10: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0009.dfa -pix_fmt rgb24 -vf scale FATE_DFA += fate-dfa11 -fate-dfa11: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0010.dfa -pix_fmt rgb24 +fate-dfa11: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0010.dfa -pix_fmt rgb24 -vf scale FATE_DFA-$(call DEMDEC, DFA, DFA) += $(FATE_DFA) diff -Nru ffmpeg-4.2.2/tests/fate/dnn.mak ffmpeg-4.4/tests/fate/dnn.mak --- ffmpeg-4.2.2/tests/fate/dnn.mak 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/fate/dnn.mak 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,43 @@ +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: 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: 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: 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: 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: 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: 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: 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: CMP = null + +FATE-$(CONFIG_DNN) += $(FATE_DNN) + +fate-dnn: $(FATE_DNN) diff -Nru ffmpeg-4.2.2/tests/fate/dnxhd.mak ffmpeg-4.4/tests/fate/dnxhd.mak --- ffmpeg-4.2.2/tests/fate/dnxhd.mak 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/fate/dnxhd.mak 2021-04-08 21:28:40.000000000 +0000 @@ -11,9 +11,9 @@ FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, DNXHD) += $(FATE_DNXHD) fate-dnxhd: $(FATE_DNXHD) $(FATE_VCODEC_DNXHD) -fate-dnxhd-mbaff: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/dnxhd100_cid1260.mov -pix_fmt yuv422p10le -fate-dnxhr-444: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/dnxhr444_cid1270.mov -pix_fmt yuv444p10le -fate-dnxhr-12bit: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/dnxhr_cid1271_12bit.mov -pix_fmt yuv422p12le +fate-dnxhd-mbaff: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/dnxhd100_cid1260.mov -pix_fmt yuv422p10le -vf scale +fate-dnxhr-444: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/dnxhr444_cid1270.mov -pix_fmt yuv444p10le -vf scale +fate-dnxhr-12bit: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/dnxhr_cid1271_12bit.mov -pix_fmt yuv422p12le -vf scale fate-dnxhr-parse: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/dnxhr_cid1274.dnxhr -pix_fmt yuv422p fate-dnxhr-prefix1: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/prefix-256x1536.dnxhr -pix_fmt yuv422p fate-dnxhr-prefix2: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/prefix-256x1716.dnxhr -pix_fmt yuv422p diff -Nru ffmpeg-4.2.2/tests/fate/ea.mak ffmpeg-4.4/tests/fate/ea.mak --- ffmpeg-4.2.2/tests/fate/ea.mak 2016-03-29 02:25:33.000000000 +0000 +++ ffmpeg-4.4/tests/fate/ea.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,8 +1,8 @@ FATE_SAMPLES_EA-$(call DEMDEC, EA_CDATA, ADPCM_EA_XAS) += fate-ea-cdata -fate-ea-cdata: CMD = md5 -i $(TARGET_SAMPLES)/ea-cdata/166b084d.46410f77.0009b440.24be960c.cdata -f s16le +fate-ea-cdata: CMD = md5 -i $(TARGET_SAMPLES)/ea-cdata/166b084d.46410f77.0009b440.24be960c.cdata -f s16le -af aresample FATE_SAMPLES_EA-$(call DEMDEC, EA, EACMV) += fate-ea-cmv -fate-ea-cmv: CMD = framecrc -i $(TARGET_SAMPLES)/ea-cmv/TITLE.CMV -pix_fmt rgb24 +fate-ea-cmv: CMD = framecrc -i $(TARGET_SAMPLES)/ea-cmv/TITLE.CMV -pix_fmt rgb24 -vf scale FATE_SAMPLES_EA-$(call DEMDEC, EA, EAMAD) += fate-ea-mad fate-ea-mad: CMD = framecrc -i $(TARGET_SAMPLES)/ea-mad/NFS6LogoE.mad -an @@ -11,10 +11,10 @@ fate-ea-tgq: CMD = framecrc -i $(TARGET_SAMPLES)/ea-tgq/v27.tgq -an FATE_EA_TGV += fate-ea-tgv-1 -fate-ea-tgv-1: CMD = framecrc -i $(TARGET_SAMPLES)/ea-tgv/INTRO8K-partial.TGV -pix_fmt rgb24 -an +fate-ea-tgv-1: CMD = framecrc -i $(TARGET_SAMPLES)/ea-tgv/INTRO8K-partial.TGV -pix_fmt rgb24 -an -vf scale FATE_EA_TGV += fate-ea-tgv-2 -fate-ea-tgv-2: CMD = framecrc -i $(TARGET_SAMPLES)/ea-tgv/INTEL_S.TGV -pix_fmt rgb24 -an +fate-ea-tgv-2: CMD = framecrc -i $(TARGET_SAMPLES)/ea-tgv/INTEL_S.TGV -pix_fmt rgb24 -an -vf scale FATE_SAMPLES_EA-$(call DEMDEC, EA, EATGV) += $(FATE_EA_TGV) fate-ea-tgv: $(FATE_EA_TGV) diff -Nru ffmpeg-4.2.2/tests/fate/ffmpeg.mak ffmpeg-4.4/tests/fate/ffmpeg.mak --- ffmpeg-4.2.2/tests/fate/ffmpeg.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/ffmpeg.mak 2021-04-08 21:28:40.000000000 +0000 @@ -4,7 +4,7 @@ FATE_MAPCHAN-$(CONFIG_CHANNELMAP_FILTER) += fate-mapchan-6ch-extract-2-downmix-mono fate-mapchan-6ch-extract-2-downmix-mono: tests/data/asynth-22050-6.wav -fate-mapchan-6ch-extract-2-downmix-mono: CMD = md5 -i $(TARGET_PATH)/tests/data/asynth-22050-6.wav -map_channel 0.0.1 -map_channel 0.0.0 -ac 1 -fflags +bitexact -f wav +fate-mapchan-6ch-extract-2-downmix-mono: CMD = md5 -auto_conversion_filters -i $(TARGET_PATH)/tests/data/asynth-22050-6.wav -map_channel 0.0.1 -map_channel 0.0.0 -ac 1 -fflags +bitexact -f wav FATE_MAPCHAN-$(CONFIG_CHANNELMAP_FILTER) += fate-mapchan-silent-mono fate-mapchan-silent-mono: tests/data/asynth-22050-1.wav @@ -28,15 +28,15 @@ # Ticket 6603 FATE_FFMPEG-$(call ALLYES, AEVALSRC_FILTER ASETNSAMPLES_FILTER AC3_FIXED_ENCODER) += fate-ffmpeg-filter_complex_audio -fate-ffmpeg-filter_complex_audio: CMD = framecrc -filter_complex "aevalsrc=0:d=0.1,asetnsamples=1537" -c ac3_fixed +fate-ffmpeg-filter_complex_audio: CMD = framecrc -auto_conversion_filters -filter_complex "aevalsrc=0:d=0.1,asetnsamples=1537" -c ac3_fixed # Ticket 6375, use case of NoX FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER PNG_DECODER ALAC_DECODER PCM_S16LE_ENCODER RAWVIDEO_ENCODER) += fate-ffmpeg-attached_pics -fate-ffmpeg-attached_pics: CMD = threads=2 framecrc -i $(TARGET_SAMPLES)/lossless-audio/inside.m4a -c:a pcm_s16le -max_muxing_queue_size 16 +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_SAMPLES_FFMPEG-$(CONFIG_COLORKEY_FILTER) += fate-ffmpeg-filter_colorkey fate-ffmpeg-filter_colorkey: tests/data/filtergraphs/colorkey -fate-ffmpeg-filter_colorkey: CMD = framecrc -idct simple -fflags +bitexact -flags +bitexact -sws_flags +accurate_rnd+bitexact -i $(TARGET_SAMPLES)/cavs/cavs.mpg -fflags +bitexact -flags +bitexact -sws_flags +accurate_rnd+bitexact -i $(TARGET_SAMPLES)/lena.pnm -an -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/colorkey -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -qscale 2 -frames:v 10 +fate-ffmpeg-filter_colorkey: CMD = framecrc -auto_conversion_filters -idct simple -fflags +bitexact -flags +bitexact -sws_flags +accurate_rnd+bitexact -i $(TARGET_SAMPLES)/cavs/cavs.mpg -fflags +bitexact -flags +bitexact -sws_flags +accurate_rnd+bitexact -i $(TARGET_SAMPLES)/lena.pnm -an -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/colorkey -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -qscale 2 -frames:v 10 FATE_FFMPEG-$(CONFIG_COLOR_FILTER) += fate-ffmpeg-lavfi fate-ffmpeg-lavfi: CMD = framecrc -lavfi color=d=1:r=5 -fflags +bitexact @@ -50,12 +50,31 @@ FATE_SAMPLES_FFMPEG-$(call ALLYES, VOBSUB_DEMUXER DVDSUB_DECODER AVFILTER OVERLAY_FILTER DVDSUB_ENCODER) += fate-sub2video fate-sub2video: tests/data/vsynth_lena.yuv -fate-sub2video: CMD = framecrc \ +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 +# Very basic sub2video example, decode and convert to AVFrame with sub2video. +# Attempt to not touch timestamps. +FATE_SAMPLES_FFMPEG-$(call ALLYES, VOBSUB_DEMUXER DVDSUB_DECODER AVFILTER) += fate-sub2video_basic +fate-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 + +# Time-limited run with a sample that doesn't require seeking and +# contains samples within the initial period. +FATE_SAMPLES_FFMPEG-$(call ALLYES, SUP_DEMUXER PGSSUB_DECODER AVFILTER) += fate-sub2video_time_limited +fate-sub2video_time_limited: CMD = framecrc -auto_conversion_filters \ + -i $(TARGET_SAMPLES)/sub/pgs_sub.sup \ + -vsync passthrough -copyts \ + -t 15 \ + -filter_complex "sws_flags=+accurate_rnd+bitexact\;[0:s:0]scale" \ + -c:v rawvideo + 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) fate-unknown_layout-pcm: CMD = md5 \ @@ -63,33 +82,33 @@ FATE_FFMPEG-$(call ALLYES, PCM_S16LE_DEMUXER AC3_MUXER PCM_S16LE_DECODER AC3_FIXED_ENCODER) += fate-unknown_layout-ac3 fate-unknown_layout-ac3: $(AREF) -fate-unknown_layout-ac3: CMD = md5 \ - -guess_layout_max 0 -f s16le -ac 1 -ar 44100 -i $(TARGET_PATH)/$(AREF) \ +fate-unknown_layout-ac3: CMD = md5 -auto_conversion_filters \ + -guess_layout_max 0 -f s32le -ac 1 -ar 44100 -i $(TARGET_PATH)/$(AREF) \ -f ac3 -flags +bitexact -c ac3_fixed FATE_STREAMCOPY-$(call ALLYES, EAC3_DEMUXER MOV_MUXER) += fate-copy-trac3074 -fate-copy-trac3074: $(TARGET_SAMPLES)/eac3/csi_miami_stereo_128_spx.eac3 +fate-copy-trac3074: $(SAMPLES)/eac3/csi_miami_stereo_128_spx.eac3 fate-copy-trac3074: CMD = transcode eac3 $(TARGET_SAMPLES)/eac3/csi_miami_stereo_128_spx.eac3\ mp4 "-codec copy -map 0" "-codec copy" FATE_STREAMCOPY-$(call ALLYES, MOV_DEMUXER MOV_MUXER) += fate-copy-trac236 -fate-copy-trac236: $(TARGET_SAMPLES)/mov/fcp_export8-236.mov +fate-copy-trac236: $(SAMPLES)/mov/fcp_export8-236.mov fate-copy-trac236: CMD = transcode mov $(TARGET_SAMPLES)/mov/fcp_export8-236.mov\ mov "-codec copy -map 0" FATE_STREAMCOPY-$(call ALLYES, MPEGTS_DEMUXER MXF_MUXER PCM_S16LE_ENCODER) += fate-copy-trac4914 -fate-copy-trac4914: $(TARGET_SAMPLES)/mpeg2/xdcam8mp2-1s_small.ts +fate-copy-trac4914: $(SAMPLES)/mpeg2/xdcam8mp2-1s_small.ts fate-copy-trac4914: CMD = transcode mpegts $(TARGET_SAMPLES)/mpeg2/xdcam8mp2-1s_small.ts\ - mxf "-c:a pcm_s16le -c:v copy" + mxf "-c:a pcm_s16le -af aresample -c:v copy" FATE_STREAMCOPY-$(call ALLYES, MPEGTS_DEMUXER AVI_MUXER) += fate-copy-trac4914-avi -fate-copy-trac4914-avi: $(TARGET_SAMPLES)/mpeg2/xdcam8mp2-1s_small.ts +fate-copy-trac4914-avi: $(SAMPLES)/mpeg2/xdcam8mp2-1s_small.ts fate-copy-trac4914-avi: CMD = transcode mpegts $(TARGET_SAMPLES)/mpeg2/xdcam8mp2-1s_small.ts\ - avi "-c:a copy -c:v copy" + avi "-c:a copy -c:v copy" "-af aresample" FATE_STREAMCOPY-$(call ALLYES, H264_DEMUXER AVI_MUXER) += fate-copy-trac2211-avi -fate-copy-trac2211-avi: $(TARGET_SAMPLES)/h264/bbc2.sample.h264 +fate-copy-trac2211-avi: $(SAMPLES)/h264/bbc2.sample.h264 fate-copy-trac2211-avi: CMD = transcode "h264 -r 14" $(TARGET_SAMPLES)/h264/bbc2.sample.h264\ avi "-c:a copy -c:v copy" @@ -98,30 +117,34 @@ fate-copy-apng: CMD = transcode apng tests/data/lavf/lavf.apng apng "-c:v copy" FATE_STREAMCOPY-$(call DEMMUX, OGG, OGG) += fate-limited_input_seek fate-limited_input_seek-copyts -fate-limited_input_seek: $(TARGET_SAMPLES)/vorbis/moog_small.ogg +fate-limited_input_seek: $(SAMPLES)/vorbis/moog_small.ogg fate-limited_input_seek: CMD = md5 -ss 1.5 -t 1.3 -i $(TARGET_SAMPLES)/vorbis/moog_small.ogg -c:a copy -fflags +bitexact -f ogg -fate-limited_input_seek-copyts: $(TARGET_SAMPLES)/vorbis/moog_small.ogg +fate-limited_input_seek-copyts: $(SAMPLES)/vorbis/moog_small.ogg fate-limited_input_seek-copyts: CMD = md5 -ss 1.5 -t 1.3 -i $(TARGET_SAMPLES)/vorbis/moog_small.ogg -c:a copy -copyts -fflags +bitexact -f ogg FATE_STREAMCOPY-$(call ALLYES, MOV_DEMUXER MOV_MUXER) += fate-copy-psp -fate-copy-psp: $(TARGET_SAMPLES)/h264/wwwq_cut.mp4 +fate-copy-psp: $(SAMPLES)/h264/wwwq_cut.mp4 fate-copy-psp: CMD = transcode "mov" $(TARGET_SAMPLES)/h264/wwwq_cut.mp4\ psp "-c copy" "-codec copy" +FATE_STREAMCOPY-$(CONFIG_FLV_DEMUXER) += fate-ffmpeg-streamloop +fate-ffmpeg-streamloop: $(SAMPLES)/flv/streamloop.flv +fate-ffmpeg-streamloop: CMD = framemd5 -stream_loop 2 -i $(TARGET_SAMPLES)/flv/streamloop.flv -c copy + fate-streamcopy: $(FATE_STREAMCOPY-yes) FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER MATROSKA_MUXER) += fate-rgb24-mkv -fate-rgb24-mkv: $(TARGET_SAMPLES)/qtrle/aletrek-rle.mov +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" FATE_SAMPLES_FFMPEG-$(call ALLYES, AAC_DEMUXER MOV_MUXER) += fate-adtstoasc_ticket3715 -fate-adtstoasc_ticket3715: $(TARGET_SAMPLES)/aac/foo.aac +fate-adtstoasc_ticket3715: $(SAMPLES)/aac/foo.aac fate-adtstoasc_ticket3715: CMD = transcode "aac" $(TARGET_SAMPLES)/aac/foo.aac\ mov "-c copy -bsf:a aac_adtstoasc" "-codec copy" FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER H264_MUXER H264_MP4TOANNEXB_BSF) += fate-h264_mp4toannexb_ticket2991 -fate-h264_mp4toannexb_ticket2991: $(TARGET_SAMPLES)/h264/wwwq_cut.mp4 +fate-h264_mp4toannexb_ticket2991: $(SAMPLES)/h264/wwwq_cut.mp4 fate-h264_mp4toannexb_ticket2991: CMD = transcode "mp4" $(TARGET_SAMPLES)/h264/wwwq_cut.mp4\ h264 "-c:v copy -bsf:v h264_mp4toannexb" "-codec copy" @@ -132,13 +155,13 @@ h264 "-c:v copy -an" "-c:v copy" FATE_SAMPLES_FFMPEG-$(call ALLYES, MPEGPS_DEMUXER AVI_MUXER REMOVE_EXTRADATA_BSF) += fate-ffmpeg-bsf-remove-k fate-ffmpeg-bsf-remove-r fate-ffmpeg-bsf-remove-e -fate-ffmpeg-bsf-remove-k: $(TARGET_SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg +fate-ffmpeg-bsf-remove-k: $(SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg fate-ffmpeg-bsf-remove-k: CMD = transcode "mpeg" $(TARGET_SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg\ avi "-vbsf remove_extra=k" "-codec copy" -fate-ffmpeg-bsf-remove-r: $(TARGET_SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg +fate-ffmpeg-bsf-remove-r: $(SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg fate-ffmpeg-bsf-remove-r: CMD = transcode "mpeg" $(TARGET_SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg\ avi "-vbsf remove_extra=keyframe" "-codec copy" -fate-ffmpeg-bsf-remove-e: $(TARGET_SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg +fate-ffmpeg-bsf-remove-e: $(SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg fate-ffmpeg-bsf-remove-e: CMD = transcode "mpeg" $(TARGET_SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg\ avi "-vbsf remove_extra=e" "-codec copy" @@ -146,7 +169,7 @@ FATE_SAMPLES_FFMPEG-yes += $(FATE_STREAMCOPY-yes) FATE_TIME_BASE-$(call ALLYES, MPEGPS_DEMUXER MXF_MUXER) += fate-time_base -fate-time_base: $(TARGET_SAMPLES)/mpeg2/dvd_single_frame.vob +fate-time_base: $(SAMPLES)/mpeg2/dvd_single_frame.vob fate-time_base: CMD = md5 -i $(TARGET_SAMPLES)/mpeg2/dvd_single_frame.vob -an -sn -c:v copy -r 25 -time_base 1001:30000 -fflags +bitexact -f mxf FATE_SAMPLES_FFMPEG-yes += $(FATE_TIME_BASE-yes) diff -Nru ffmpeg-4.2.2/tests/fate/ffprobe.mak ffmpeg-4.4/tests/fate/ffprobe.mak --- ffmpeg-4.2.2/tests/fate/ffprobe.mak 2018-07-17 09:27:43.000000000 +0000 +++ ffmpeg-4.4/tests/fate/ffprobe.mak 2020-07-11 10:39:30.000000000 +0000 @@ -1,5 +1,5 @@ FFPROBE_TEST_FILE=tests/data/ffprobe-test.nut -FFPROBE_COMMAND=ffprobe$(PROGSSUF)$(EXESUF) -show_streams -show_packets -show_format -show_frames -bitexact $(FFPROBE_TEST_FILE) +FFPROBE_COMMAND=ffprobe$(PROGSSUF)$(EXESUF) -show_streams -show_packets -show_format -show_frames -bitexact $(TARGET_PATH)/$(FFPROBE_TEST_FILE) -print_filename $(FFPROBE_TEST_FILE) FATE_FFPROBE-$(CONFIG_AVDEVICE) += fate-ffprobe_compact fate-ffprobe_compact: $(FFPROBE_TEST_FILE) diff -Nru ffmpeg-4.2.2/tests/fate/fft.mak ffmpeg-4.4/tests/fate/fft.mak --- ffmpeg-4.2.2/tests/fate/fft.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/fft.mak 2021-04-08 21:28:40.000000000 +0000 @@ -26,27 +26,7 @@ $(FATE_FFT_ALL): libavcodec/tests/fft$(EXESUF) $(FATE_FFT_ALL): CMD = run libavcodec/tests/fft$(EXESUF) $(CPUFLAGS:%=-c%) $(ARGS) -define DEF_FFT_FIXED -FATE_FFT_FIXED-$(CONFIG_FFT) += fate-fft-fixed-$(1) fate-ifft-fixed-$(1) -FATE_MDCT_FIXED-$(CONFIG_MDCT) += fate-mdct-fixed-$(1) fate-imdct-fixed-$(1) - -fate-fft-fixed-$(1): ARGS = -n$(1) -fate-ifft-fixed-$(1): ARGS = -n$(1) -i -fate-mdct-fixed-$(1): ARGS = -n$(1) -m -fate-imdct-fixed-$(1): ARGS = -n$(1) -m -i -endef - -$(foreach N, 4 5 6 7 8 9 10 11 12, $(eval $(call DEF_FFT_FIXED,$(N)))) - -fate-fft-fixed: $(FATE_FFT_FIXED-yes) -fate-mdct-fixed: $(FATE_MDCT_FIXED-yes) - -FATE_FFT_FIXED_ALL = $(FATE_FFT_FIXED-yes) $(FATE_MDCT_FIXED-yes) - -$(FATE_FFT_FIXED_ALL): libavcodec/tests/fft-fixed$(EXESUF) -$(FATE_FFT_FIXED_ALL): CMD = run libavcodec/tests/fft-fixed$(EXESUF) $(CPUFLAGS:%=-c%) $(ARGS) - -$(FATE_FFT_ALL) $(FATE_FFT_FIXED_ALL): CMP = null +$(FATE_FFT_ALL): CMP = null define DEF_FFT_FIXED32 FATE_FFT_FIXED32 += fate-fft-fixed32-$(1) fate-ifft-fixed32-$(1) \ @@ -95,9 +75,9 @@ $(FATE_AV_FFT_ALL): CMP = null fate-dct: fate-dct-float -fate-fft: fate-fft-float fate-fft-fixed fate-fft-fixed32 -fate-mdct: fate-mdct-float fate-mdct-fixed +fate-fft: fate-fft-float fate-fft-fixed32 +fate-mdct: fate-mdct-float fate-rdft: fate-rdft-float -FATE-$(call ALLYES, AVCODEC FFT MDCT) += $(FATE_FFT_ALL) $(FATE_FFT_FIXED_ALL) $(FATE_FFT_FIXED32) $(FATE_AV_FFT_ALL) -fate-fft-all: $(FATE_FFT_ALL) $(FATE_FFT_FIXED_ALL) $(FATE_FFT_FIXED32) $(FATE_AV_FFT_ALL) +FATE-$(call ALLYES, AVCODEC FFT MDCT) += $(FATE_FFT_ALL) $(FATE_FFT_FIXED32) $(FATE_AV_FFT_ALL) +fate-fft-all: $(FATE_FFT_ALL) $(FATE_FFT_FIXED32) $(FATE_AV_FFT_ALL) diff -Nru ffmpeg-4.2.2/tests/fate/filter-audio.mak ffmpeg-4.4/tests/fate/filter-audio.mak --- ffmpeg-4.2.2/tests/fate/filter-audio.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/filter-audio.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,22 +1,22 @@ FATE_AFILTER-$(call FILTERDEMDECENCMUX, ADELAY, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-adelay fate-filter-adelay: tests/data/asynth-44100-2.wav fate-filter-adelay: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-filter-adelay: CMD = framecrc -i $(SRC) -af adelay=42 +fate-filter-adelay: CMD = framecrc -i $(SRC) -af aresample,adelay=42,aresample FATE_AFILTER-$(call FILTERDEMDECENCMUX, AECHO, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-aecho fate-filter-aecho: tests/data/asynth-44100-2.wav fate-filter-aecho: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-filter-aecho: CMD = framecrc -i $(SRC) -af aecho=0.5:0.5:32:0.5 +fate-filter-aecho: CMD = framecrc -i $(SRC) -af aresample,aecho=0.5:0.5:32:0.5,aresample FATE_FILTER_AEMPHASIS += fate-filter-aemphasis-50fm fate-filter-aemphasis-50fm: tests/data/asynth-44100-2.wav fate-filter-aemphasis-50fm: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-filter-aemphasis-50fm: CMD = framecrc -i $(SRC) -af aemphasis=1:5:reproduction:50fm +fate-filter-aemphasis-50fm: CMD = framecrc -i $(SRC) -af aresample,aemphasis=1:5:reproduction:50fm,aresample FATE_FILTER_AEMPHASIS += fate-filter-aemphasis-75kf fate-filter-aemphasis-75kf: tests/data/asynth-44100-2.wav fate-filter-aemphasis-75kf: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-filter-aemphasis-75kf: CMD = framecrc -i $(SRC) -af aemphasis=2:8:reproduction:75kf +fate-filter-aemphasis-75kf: CMD = framecrc -i $(SRC) -af aresample,aemphasis=2:8:reproduction:75kf,aresample FATE_AFILTER-$(call FILTERDEMDECENCMUX, AEMPHASIS, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_FILTER_AEMPHASIS) @@ -61,12 +61,12 @@ FATE_AFILTER-$(call FILTERDEMDECENCMUX, AFADE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-agate fate-filter-agate: tests/data/asynth-44100-2.wav fate-filter-agate: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-filter-agate: CMD = framecrc -i $(SRC) -af agate=level_in=10:range=0:threshold=1:ratio=1:attack=1:knee=1:makeup=4 +fate-filter-agate: CMD = framecrc -i $(SRC) -af aresample,agate=level_in=10:range=0:threshold=1:ratio=1:attack=1:knee=1:makeup=4,aresample FATE_AFILTER-$(call FILTERDEMDECENCMUX, AFADE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-alimiter fate-filter-alimiter: tests/data/asynth-44100-2.wav fate-filter-alimiter: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-filter-alimiter: CMD = framecrc -i $(SRC) -af alimiter=level_in=1:level_out=2:limit=0.2 +fate-filter-alimiter: CMD = framecrc -i $(SRC) -af aresample,alimiter=level_in=1:level_out=2:limit=0.2,aresample FATE_AFILTER-$(call FILTERDEMDECENCMUX, AMERGE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-amerge fate-filter-amerge: tests/data/asynth-44100-1.wav @@ -82,7 +82,7 @@ fate-filter-anequalizer: tests/data/asynth-44100-2.wav fate-filter-anequalizer: tests/data/filtergraphs/anequalizer fate-filter-anequalizer: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-filter-anequalizer: CMD = framecrc -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/anequalizer +fate-filter-anequalizer: CMD = framecrc -auto_conversion_filters -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/anequalizer FATE_AFILTER-$(call FILTERDEMDECENCMUX, ASETNSAMPLES, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-asetnsamples-pad fate-filter-asetnsamples-pad: tests/data/asynth-44100-2.wav @@ -102,28 +102,28 @@ FATE_AFILTER-$(call FILTERDEMDECENCMUX, CHORUS, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-chorus fate-filter-chorus: tests/data/asynth-22050-1.wav fate-filter-chorus: SRC = $(TARGET_PATH)/tests/data/asynth-22050-1.wav -fate-filter-chorus: CMD = framecrc -i $(SRC) -frames:a 10 -af chorus=0.050001:0.050002:64:0.050001:0.025003:2.00004 +fate-filter-chorus: CMD = framecrc -i $(SRC) -frames:a 10 -af aresample,chorus=0.050001:0.050002:64:0.050001:0.025003:2.00004,aresample FATE_AFILTER-$(call FILTERDEMDECENCMUX, DCSHIFT, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-dcshift fate-filter-dcshift: tests/data/asynth-44100-2.wav fate-filter-dcshift: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-filter-dcshift: CMD = framecrc -i $(SRC) -frames:a 20 -af dcshift=shift=0.25:limitergain=0.05 +fate-filter-dcshift: CMD = framecrc -i $(SRC) -frames:a 20 -af aresample,dcshift=shift=0.25:limitergain=0.05,aresample FATE_AFILTER-$(call FILTERDEMDECENCMUX, EARWAX, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-earwax fate-filter-earwax: tests/data/asynth-44100-2.wav fate-filter-earwax: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-filter-earwax: CMD = framecrc -i $(SRC) -frames:a 20 -af earwax +fate-filter-earwax: CMD = framecrc -i $(SRC) -frames:a 20 -af aresample,earwax,aresample FATE_AFILTER-$(call FILTERDEMDECENCMUX, EXTRASTEREO, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-extrastereo fate-filter-extrastereo: tests/data/asynth-44100-2.wav fate-filter-extrastereo: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-filter-extrastereo: CMD = framecrc -i $(SRC) -frames:a 20 -af extrastereo=m=2 +fate-filter-extrastereo: CMD = framecrc -i $(SRC) -frames:a 20 -af aresample,extrastereo=m=2,aresample FATE_AFILTER-$(call FILTERDEMDECENCMUX, FIREQUALIZER ATRIM VOLUME, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-firequalizer fate-filter-firequalizer: tests/data/asynth-44100-2.wav fate-filter-firequalizer: tests/data/filtergraphs/firequalizer fate-filter-firequalizer: REF = tests/data/asynth-44100-2.wav -fate-filter-firequalizer: CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-44100-2.wav -filter_script $(TARGET_PATH)/tests/data/filtergraphs/firequalizer -f wav -c:a pcm_s16le - +fate-filter-firequalizer: CMD = ffmpeg -auto_conversion_filters -i $(TARGET_PATH)/tests/data/asynth-44100-2.wav -filter_script $(TARGET_PATH)/tests/data/filtergraphs/firequalizer -f wav -c:a pcm_s16le - fate-filter-firequalizer: CMP = oneoff fate-filter-firequalizer: CMP_UNIT = s16 fate-filter-firequalizer: SIZE_TOLERANCE = 1058400 - 1097208 @@ -180,22 +180,25 @@ FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, SILENCEREMOVE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-silenceremove fate-filter-silenceremove: SRC = $(TARGET_SAMPLES)/audio-reference/divertimenti_2ch_96kHz_s24.wav -fate-filter-silenceremove: CMD = framecrc -i $(SRC) -frames:a 30 -af silenceremove=start_periods=0:start_duration=0:start_threshold=0:stop_periods=-1:stop_duration=0:stop_threshold=-90dB +fate-filter-silenceremove: CMD = framecrc -i $(SRC) -frames:a 30 -af aresample,silenceremove=start_periods=0:start_duration=0:start_threshold=0:stop_periods=-1:stop_duration=0:stop_threshold=-90dB,aresample FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, STEREOTOOLS, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-stereotools fate-filter-stereotools: SRC = $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -fate-filter-stereotools: CMD = framecrc -i $(SRC) -frames:a 20 -af stereotools=mlev=0.015625 +fate-filter-stereotools: CMD = framecrc -i $(SRC) -frames:a 20 -af aresample,stereotools=mlev=0.015625,aresample -FATE_AFILTER-$(call FILTERDEMDECENCMUX, TREMOLO, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-tremolo +FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, TREMOLO, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-tremolo fate-filter-tremolo: tests/data/asynth-44100-2.wav fate-filter-tremolo: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-filter-tremolo: CMD = framecrc -i $(SRC) -frames:a 20 -af tremolo +fate-filter-tremolo: CMD = ffmpeg -auto_conversion_filters -i $(SRC) -frames:a 20 -af tremolo -f wav -f s16le - +fate-filter-tremolo: REF = $(SAMPLES)/filter/tremolo.pcm +fate-filter-tremolo: CMP = oneoff +fate-filter-tremolo: CMP_UNIT = s16 FATE_AFILTER-$(call FILTERDEMDECENCMUX, COMPAND, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-compand fate-filter-compand: tests/data/asynth-44100-2.wav fate-filter-compand: tests/data/filtergraphs/compand fate-filter-compand: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav -fate-filter-compand: CMD = framecrc -i $(SRC) -frames:a 20 -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/compand +fate-filter-compand: CMD = framecrc -auto_conversion_filters -i $(SRC) -frames:a 20 -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/compand tests/data/hls-list.m3u8: TAG = GEN tests/data/hls-list.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data @@ -205,7 +208,7 @@ FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-filter-hls fate-filter-hls: tests/data/hls-list.m3u8 -fate-filter-hls: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hls-list.m3u8 +fate-filter-hls: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hls-list.m3u8 -af aresample tests/data/hls-list-append.m3u8: TAG = GEN tests/data/hls-list-append.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data @@ -219,20 +222,20 @@ FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-filter-hls-append fate-filter-hls-append: tests/data/hls-list-append.m3u8 -fate-filter-hls-append: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hls-list-append.m3u8 -af asetpts=N*23 +fate-filter-hls-append: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hls-list-append.m3u8 -af asetpts=N*23,aresample FATE_AMIX += fate-filter-amix-simple -fate-filter-amix-simple: CMD = ffmpeg -filter_complex amix -i $(SRC) -ss 3 -i $(SRC1) -f f32le - +fate-filter-amix-simple: CMD = ffmpeg -auto_conversion_filters -filter_complex amix -i $(SRC) -ss 3 -i $(SRC1) -f f32le - fate-filter-amix-simple: REF = $(SAMPLES)/filter/amix_simple.pcm FATE_AMIX += fate-filter-amix-first -fate-filter-amix-first: CMD = ffmpeg -filter_complex amix=duration=first -ss 4 -i $(SRC) -i $(SRC1) -f f32le - +fate-filter-amix-first: CMD = ffmpeg -auto_conversion_filters -filter_complex amix=duration=first -ss 4 -i $(SRC) -i $(SRC1) -f f32le - fate-filter-amix-first: REF = $(SAMPLES)/filter/amix_first.pcm FATE_AMIX += fate-filter-amix-transition fate-filter-amix-transition: tests/data/asynth-44100-2-3.wav fate-filter-amix-transition: SRC2 = $(TARGET_PATH)/tests/data/asynth-44100-2-3.wav -fate-filter-amix-transition: CMD = ffmpeg -filter_complex amix=inputs=3:dropout_transition=0.5 -i $(SRC) -ss 2 -i $(SRC1) -ss 4 -i $(SRC2) -f f32le - +fate-filter-amix-transition: CMD = ffmpeg -auto_conversion_filters -filter_complex amix=inputs=3:dropout_transition=0.5 -i $(SRC) -ss 2 -i $(SRC1) -ss 4 -i $(SRC2) -f f32le - fate-filter-amix-transition: REF = $(SAMPLES)/filter/amix_transition.pcm FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, AMIX, WAV, PCM_S16LE, PCM_F32LE, PCM_F32LE) += $(FATE_AMIX) @@ -268,7 +271,7 @@ fate-filter-channelmap-one-int: tests/data/filtergraphs/channelmap_one_int fate-filter-channelmap-one-int: SRC = $(TARGET_PATH)/tests/data/asynth-44100-6.wav fate-filter-channelmap-one-int: tests/data/asynth-44100-6.wav -fate-filter-channelmap-one-int: CMD = md5 -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/channelmap_one_int -f wav -fflags +bitexact +fate-filter-channelmap-one-int: CMD = md5 -auto_conversion_filters -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/channelmap_one_int -f wav -fflags +bitexact fate-filter-channelmap-one-int: CMP = oneline fate-filter-channelmap-one-int: REF = 8cfe553d65ed4696756d8c1b824fcdd3 @@ -276,7 +279,7 @@ fate-filter-channelmap-one-str: tests/data/filtergraphs/channelmap_one_str fate-filter-channelmap-one-str: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav fate-filter-channelmap-one-str: tests/data/asynth-44100-2.wav -fate-filter-channelmap-one-str: CMD = md5 -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/channelmap_one_str -f wav -fflags +bitexact +fate-filter-channelmap-one-str: CMD = md5 -auto_conversion_filters -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/channelmap_one_str -f wav -fflags +bitexact fate-filter-channelmap-one-str: CMP = oneline fate-filter-channelmap-one-str: REF = 0ea3052e482c95d5d3bd9da6dac1b5fa @@ -285,7 +288,7 @@ FATE_AFILTER-$(call FILTERDEMDECENCMUX, CHANNELSPLIT, WAV, PCM_S16LE, PCM_S16LE, PCM_S16LE) += fate-filter-channelsplit fate-filter-channelsplit: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav fate-filter-channelsplit: tests/data/asynth-44100-2.wav -fate-filter-channelsplit: CMD = md5 -i $(SRC) -filter_complex channelsplit -f s16le +fate-filter-channelsplit: CMD = md5 -auto_conversion_filters -i $(SRC) -filter_complex channelsplit -f s16le fate-filter-channelsplit: CMP = oneline fate-filter-channelsplit: REF = d92988d0fe2dd92236763f47b07ab597 @@ -293,7 +296,7 @@ fate-filter-join: SRC1 = $(TARGET_PATH)/tests/data/asynth-44100-2.wav fate-filter-join: SRC2 = $(TARGET_PATH)/tests/data/asynth-44100-3.wav fate-filter-join: tests/data/asynth-44100-2.wav tests/data/asynth-44100-3.wav -fate-filter-join: CMD = md5 -i $(SRC1) -i $(SRC2) -filter_complex join=channel_layout=5c -f s16le +fate-filter-join: CMD = md5 -auto_conversion_filters -i $(SRC1) -i $(SRC2) -filter_complex join=channel_layout=5c -f s16le fate-filter-join: CMP = oneline fate-filter-join: REF = 88b0d24a64717ba8635b29e8dac6ecd8 @@ -312,47 +315,47 @@ fate-filter-hdcd-mix: SRC = $(TARGET_SAMPLES)/filter/hdcd-mix.flac fate-filter-hdcd-mix: CMD = md5 -i $(SRC) -af hdcd -f s24le fate-filter-hdcd-mix: CMP = oneline -fate-filter-hdcd-mix: REF = e7079913e90c124460cdbc712df5b84c +fate-filter-hdcd-mix: REF = 77443573e0bd3532de52a8bc0e825da7 # output will be different because of the gain mismatch in the second and third parts FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, HDCD, FLAC, FLAC, PCM_S24LE, PCM_S24LE) += fate-filter-hdcd-mix-psoff fate-filter-hdcd-mix-psoff: SRC = $(TARGET_SAMPLES)/filter/hdcd-mix.flac fate-filter-hdcd-mix-psoff: CMD = md5 -i $(SRC) -af hdcd=process_stereo=false -f s24le fate-filter-hdcd-mix-psoff: CMP = oneline -fate-filter-hdcd-mix-psoff: REF = bd0e81fe17696b825ee3515ab928e6bb +fate-filter-hdcd-mix-psoff: REF = 89e57885917a436b30855db4d478cefb # test the different analyze modes FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, HDCD, FLAC, FLAC, PCM_S24LE, PCM_S24LE) += fate-filter-hdcd-analyze-pe fate-filter-hdcd-analyze-pe: SRC = $(TARGET_SAMPLES)/filter/hdcd-mix.flac fate-filter-hdcd-analyze-pe: CMD = md5 -i $(SRC) -af hdcd=analyze_mode=pe -f s24le fate-filter-hdcd-analyze-pe: CMP = oneline -fate-filter-hdcd-analyze-pe: REF = bb83e97bbd0064b9b1c0ef2f2c8f0c77 +fate-filter-hdcd-analyze-pe: REF = 2d839d8a1cf73b10a566ce3d4cfaa79e FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, HDCD, FLAC, FLAC, PCM_S24LE, PCM_S24LE) += fate-filter-hdcd-analyze-lle fate-filter-hdcd-analyze-lle: SRC = $(TARGET_SAMPLES)/filter/hdcd-mix.flac fate-filter-hdcd-analyze-lle: CMD = md5 -i $(SRC) -af hdcd=analyze_mode=lle -f s24le fate-filter-hdcd-analyze-lle: CMP = oneline -fate-filter-hdcd-analyze-lle: REF = 121cc4a681aa0caef5c664fece7a3ddc +fate-filter-hdcd-analyze-lle: REF = b4b185332b7025c191062f49a2c015f1 FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, HDCD, FLAC, FLAC, PCM_S24LE, PCM_S24LE) += fate-filter-hdcd-analyze-cdt fate-filter-hdcd-analyze-cdt: SRC = $(TARGET_SAMPLES)/filter/hdcd-mix.flac fate-filter-hdcd-analyze-cdt: CMD = md5 -i $(SRC) -af hdcd=analyze_mode=cdt -f s24le fate-filter-hdcd-analyze-cdt: CMP = oneline -fate-filter-hdcd-analyze-cdt: REF = 12136e6a00dd532994f6edcc347af1d4 +fate-filter-hdcd-analyze-cdt: REF = afa6577675c63e87da3edbd442b7b6e2 FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, HDCD, FLAC, FLAC, PCM_S24LE, PCM_S24LE) += fate-filter-hdcd-analyze-tgm fate-filter-hdcd-analyze-tgm: SRC = $(TARGET_SAMPLES)/filter/hdcd-mix.flac fate-filter-hdcd-analyze-tgm: CMD = md5 -i $(SRC) -af hdcd=analyze_mode=tgm -f s24le fate-filter-hdcd-analyze-tgm: CMP = oneline -fate-filter-hdcd-analyze-tgm: REF = a3c39f62e9b9b42c9c440d0045d5fb2f +fate-filter-hdcd-analyze-tgm: REF = 285f0fd2249b4903cd5e1ad5ce004219 # the two additional analyze modes from libhdcd FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, HDCD, FLAC, FLAC, PCM_S24LE, PCM_S24LE) += fate-filter-hdcd-analyze-ltgm fate-filter-hdcd-analyze-ltgm: SRC = $(TARGET_SAMPLES)/filter/hdcd-mix.flac fate-filter-hdcd-analyze-ltgm: CMD = md5 -i $(SRC) -af hdcd=analyze_mode=lle:process_stereo=false -f s24le fate-filter-hdcd-analyze-ltgm: CMP = oneline -fate-filter-hdcd-analyze-ltgm: REF = 76ffd86b762b5a93332039f27e4c0c0e +fate-filter-hdcd-analyze-ltgm: REF = 404dc2301ea97e9f96c3d6d2ebcfeaa5 FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, HDCD, FLAC, FLAC, PCM_S24LE, PCM_S24LE) += fate-filter-hdcd-analyze-pel fate-filter-hdcd-analyze-pel: SRC = $(TARGET_SAMPLES)/filter/hdcd-mix.flac fate-filter-hdcd-analyze-pel: CMD = md5 -i $(SRC) -af hdcd=analyze_mode=pe:force_pe=true -f s24le fate-filter-hdcd-analyze-pel: CMP = oneline -fate-filter-hdcd-analyze-pel: REF = 8156c5a3658d789ab46447d62151f5e9 +fate-filter-hdcd-analyze-pel: REF = 9342983208ec1a7f2b3e332ac4dcb723 FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, HDCD, FLAC, FLAC, PCM_S24LE, PCM_S24LE) += fate-filter-hdcd-false-positive fate-filter-hdcd-false-positive: SRC = $(TARGET_SAMPLES)/filter/hdcd-false-positive.flac diff -Nru ffmpeg-4.2.2/tests/fate/filter-video.mak ffmpeg-4.4/tests/fate/filter-video.mak --- ffmpeg-4.2.2/tests/fate/filter-video.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/filter-video.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,6 +1,6 @@ FATE_FILTER_SAMPLES-$(call ALLYES, SMJPEG_DEMUXER MJPEG_DECODER PERMS_FILTER OWDENOISE_FILTER) += fate-filter-owdenoise-sample -fate-filter-owdenoise-sample: CMD = ffmpeg -idct simple -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -vf "trim=duration=0.5,perms=random,owdenoise=10:20:20:enable=not(between(t\,0.2\,1.2))" -an -f rawvideo - -fate-filter-owdenoise-sample: REF = $(TARGET_SAMPLES)/filter-reference/owdenoise-scenwin.raw +fate-filter-owdenoise-sample: CMD = ffmpeg -auto_conversion_filters -idct simple -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -vf "trim=duration=0.5,perms=random,owdenoise=10:20:20:enable=not(between(t\,0.2\,1.2))" -an -f rawvideo - +fate-filter-owdenoise-sample: REF = $(SAMPLES)/filter-reference/owdenoise-scenwin.raw fate-filter-owdenoise-sample: CMP_TARGET = 1 fate-filter-owdenoise-sample: FUZZ = 3539 fate-filter-owdenoise-sample: CMP = oneoff @@ -15,10 +15,10 @@ fate-filter-yadif-mode1: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 59 -vf yadif=1 FATE_YADIF += fate-filter-yadif10 -fate-filter-yadif10: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p10le -frames:v 30 -vf yadif=0 +fate-filter-yadif10: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p10le -frames:v 30 -vf yadif=0,scale FATE_YADIF += fate-filter-yadif16 -fate-filter-yadif16: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p16le -frames:v 30 -vf yadif=0 +fate-filter-yadif16: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p16le -frames:v 30 -vf yadif=0,scale FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, YADIF, MPEGTS, MPEG2VIDEO) += $(FATE_YADIF) @@ -42,25 +42,25 @@ fate-filter-codecview-mvs: CMD = framecrc -flags2 +export_mvs -i $(TARGET_SAMPLES)/real/spygames-2MB.rmvb -vf codecview=mv=pf+bf+bb -frames:v 60 -an FATE_FILTER_SAMPLES-$(call ALLYES, SHOWPALETTE_FILTER FLIC_DEMUXER FLIC_DECODER) += fate-filter-showpalette -fate-filter-showpalette: CMD = framecrc -i $(TARGET_SAMPLES)/fli/fli-engines.fli -vf showpalette=3 -pix_fmt bgra +fate-filter-showpalette: CMD = framecrc -i $(TARGET_SAMPLES)/fli/fli-engines.fli -vf showpalette=3,scale -pix_fmt bgra FATE_FILTER_PALETTEGEN += fate-filter-palettegen-1 -fate-filter-palettegen-1: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -vf palettegen -pix_fmt bgra +fate-filter-palettegen-1: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -vf scale,palettegen,scale -pix_fmt bgra FATE_FILTER_PALETTEGEN += fate-filter-palettegen-2 -fate-filter-palettegen-2: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -vf palettegen=max_colors=128:reserve_transparent=0:stats_mode=diff -pix_fmt bgra +fate-filter-palettegen-2: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -vf scale,palettegen=max_colors=128:reserve_transparent=0:stats_mode=diff,scale -pix_fmt bgra fate-filter-palettegen: $(FATE_FILTER_PALETTEGEN) FATE_FILTER_SAMPLES-$(call ALLYES, PALETTEGEN_FILTER MATROSKA_DEMUXER H264_DECODER) += $(FATE_FILTER_PALETTEGEN) FATE_FILTER_PALETTEUSE += fate-filter-paletteuse-nodither -fate-filter-paletteuse-nodither: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -i $(TARGET_SAMPLES)/filter/anim-palette.png -lavfi paletteuse=none -pix_fmt bgra +fate-filter-paletteuse-nodither: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/filter/anim.mkv -i $(TARGET_SAMPLES)/filter/anim-palette.png -lavfi paletteuse=none -pix_fmt bgra FATE_FILTER_PALETTEUSE += fate-filter-paletteuse-bayer -fate-filter-paletteuse-bayer: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -i $(TARGET_SAMPLES)/filter/anim-palette.png -lavfi paletteuse=bayer -pix_fmt bgra +fate-filter-paletteuse-bayer: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/filter/anim.mkv -i $(TARGET_SAMPLES)/filter/anim-palette.png -lavfi paletteuse=bayer -pix_fmt bgra FATE_FILTER_PALETTEUSE += fate-filter-paletteuse-sierra2_4a -fate-filter-paletteuse-sierra2_4a: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -i $(TARGET_SAMPLES)/filter/anim-palette.png -lavfi paletteuse=sierra2_4a:diff_mode=rectangle -pix_fmt bgra +fate-filter-paletteuse-sierra2_4a: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/filter/anim.mkv -i $(TARGET_SAMPLES)/filter/anim-palette.png -lavfi paletteuse=sierra2_4a:diff_mode=rectangle -pix_fmt bgra fate-filter-paletteuse: $(FATE_FILTER_PALETTEUSE) FATE_FILTER_SAMPLES-$(call ALLYES, PALETTEUSE_FILTER MATROSKA_DEMUXER H264_DECODER IMAGE2_DEMUXER PNG_DECODER) += $(FATE_FILTER_PALETTEUSE) @@ -108,7 +108,7 @@ fate-filter-yuvtestsrc-yuv444p: CMD = framecrc -lavfi yuvtestsrc=rate=5:duration=1 -pix_fmt yuv444p FATE_FILTER-$(call ALLYES, LAVFI_INDEV YUVTESTSRC_FILTER) += fate-filter-yuvtestsrc-yuv444p12 -fate-filter-yuvtestsrc-yuv444p12: CMD = framecrc -lavfi yuvtestsrc=rate=5:duration=1,format=yuv444p12 -pix_fmt yuv444p12le +fate-filter-yuvtestsrc-yuv444p12: CMD = framecrc -lavfi yuvtestsrc=rate=5:duration=1,format=yuv444p12,scale -pix_fmt yuv444p12le FATE_FILTER-$(call ALLYES, AVDEVICE TESTSRC_FILTER FORMAT_FILTER CONCAT_FILTER SCALE_FILTER) += fate-filter-lavd-scalenorm fate-filter-lavd-scalenorm: tests/data/filtergraphs/scalenorm @@ -119,14 +119,18 @@ fate-filter-framerate-down: CMD = framecrc -lavfi testsrc2=r=2:d=10,framerate=fps=1 -t 1 FATE_FILTER-$(call ALLYES, FRAMERATE_FILTER TESTSRC2_FILTER FORMAT_FILTER) += fate-filter-framerate-12bit-up fate-filter-framerate-12bit-down -fate-filter-framerate-12bit-up: CMD = framecrc -lavfi testsrc2=r=50:d=1,format=pix_fmts=yuv422p12le,framerate=fps=60 -t 1 -pix_fmt yuv422p12le -fate-filter-framerate-12bit-down: CMD = framecrc -lavfi testsrc2=r=60:d=1,format=pix_fmts=yuv422p12le,framerate=fps=50 -t 1 -pix_fmt yuv422p12le +fate-filter-framerate-12bit-up: CMD = framecrc -lavfi testsrc2=r=50:d=1,format=pix_fmts=yuv422p12le,scale,framerate=fps=60,scale -t 1 -pix_fmt yuv422p12le +fate-filter-framerate-12bit-down: CMD = framecrc -lavfi testsrc2=r=60:d=1,format=pix_fmts=yuv422p12le,scale,framerate=fps=50,scale -t 1 -pix_fmt yuv422p12le + +FATE_FILTER-$(call ALLYES, MINTERPOLATE_FILTER TESTSRC2_FILTER) += fate-filter-minterpolate-up fate-filter-minterpolate-down +fate-filter-minterpolate-up: CMD = framecrc -lavfi testsrc2=r=2:d=10,minterpolate=fps=10 -t 1 +fate-filter-minterpolate-down: CMD = framecrc -lavfi testsrc2=r=2:d=10,minterpolate=fps=1 -t 1 FATE_FILTER_VSYNTH-$(CONFIG_BOXBLUR_FILTER) += fate-filter-boxblur fate-filter-boxblur: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf boxblur=2:1 FATE_FILTER_VSYNTH-$(call ALLYES, COLORCHANNELMIXER_FILTER FORMAT_FILTER PERMS_FILTER) += fate-filter-colorchannelmixer -fate-filter-colorchannelmixer: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf format=rgb24,perms=random,colorchannelmixer=.31415927:.4:.31415927:0:.27182818:.8:.27182818:0:.2:.6:.2:0 -flags +bitexact -sws_flags +accurate_rnd+bitexact +fate-filter-colorchannelmixer: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=rgb24,perms=random,colorchannelmixer=.31415927:.4:.31415927:0:.27182818:.8:.27182818:0:.2:.6:.2:0 -flags +bitexact -sws_flags +accurate_rnd+bitexact FATE_FILTER_VSYNTH-$(CONFIG_DRAWBOX_FILTER) += fate-filter-drawbox fate-filter-drawbox: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf drawbox=224:24:88:72:red@0.5 @@ -135,7 +139,7 @@ fate-filter-fade: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf fade=in:5:15,fade=out:30:15 FATE_FILTER_VSYNTH-$(call ALLYES, INTERLACE_FILTER FIELDORDER_FILTER) += fate-filter-fieldorder -fate-filter-fieldorder: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf interlace=tff,fieldorder=bff -sws_flags +accurate_rnd+bitexact +fate-filter-fieldorder: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf interlace=tff,scale,fieldorder=bff -sws_flags +accurate_rnd+bitexact define FATE_FPFILTER_SUITE FATE_FILTER_FRAMEPACK += fate-filter-framepack-$(1) @@ -193,7 +197,7 @@ fate-filter-vectorscope_color4: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf vectorscope=color4 -sws_flags +accurate_rnd+bitexact -frames:v 3 FATE_FILTER_VSYNTH-$(CONFIG_VECTORSCOPE_FILTER) += fate-filter-vectorscope_xy -fate-filter-vectorscope_xy: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf vectorscope=x=0:y=1 -sws_flags +accurate_rnd+bitexact -frames:v 3 +fate-filter-vectorscope_xy: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -vf vectorscope=x=0:y=1 -sws_flags +accurate_rnd+bitexact -frames:v 3 FATE_FILTER_VSYNTH-$(CONFIG_MERGEPLANES_FILTER) += fate-filter-mergeplanes fate-filter-mergeplanes: tests/data/filtergraphs/mergeplanes @@ -213,46 +217,54 @@ FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_rgb fate-filter-overlay_rgb: tests/data/filtergraphs/overlay_rgb -fate-filter-overlay_rgb: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_rgb +fate-filter-overlay_rgb: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_rgb FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv420 fate-filter-overlay_yuv420: tests/data/filtergraphs/overlay_yuv420 fate-filter-overlay_yuv420: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv420 +FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv420p10 +fate-filter-overlay_yuv420p10: tests/data/filtergraphs/overlay_yuv420p10 +fate-filter-overlay_yuv420p10: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv420p10 -pix_fmt yuv420p10le -frames:v 3 + FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_nv12 fate-filter-overlay_nv12: tests/data/filtergraphs/overlay_nv12 -fate-filter-overlay_nv12: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_nv12 +fate-filter-overlay_nv12: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_nv12 fate-filter-overlay_nv12: REF = $(SRC_PATH)/tests/ref/fate/filter-overlay_yuv420 FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_nv21 fate-filter-overlay_nv21: tests/data/filtergraphs/overlay_nv21 -fate-filter-overlay_nv21: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_nv21 +fate-filter-overlay_nv21: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_nv21 fate-filter-overlay_nv21: REF = $(SRC_PATH)/tests/ref/fate/filter-overlay_yuv420 FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv422 fate-filter-overlay_yuv422: tests/data/filtergraphs/overlay_yuv422 -fate-filter-overlay_yuv422: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv422 +fate-filter-overlay_yuv422: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv422 + +FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv422p10 +fate-filter-overlay_yuv422p10: tests/data/filtergraphs/overlay_yuv422p10 +fate-filter-overlay_yuv422p10: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv422p10 -pix_fmt yuv422p10le -frames:v 3 FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv444 fate-filter-overlay_yuv444: tests/data/filtergraphs/overlay_yuv444 -fate-filter-overlay_yuv444: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv444 +fate-filter-overlay_yuv444: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv444 FATE_FILTER_OVERLAY_ALPHA += fate-filter-overlay_yuv420_yuva420 fate-filter-overlay_yuv422_yuva422 fate-filter-overlay_yuv444_yuva444 fate-filter-overlay_rgb_rgba fate-filter-overlay_gbrp_gbrap FATE_FILTER_OVERLAY_ALPHA += fate-filter-overlay_yuva420_yuva420 fate-filter-overlay_yuva422_yuva422 fate-filter-overlay_yuva444_yuva444 fate-filter-overlay_rgba_rgba fate-filter-overlay_gbrap_gbrap $(FATE_FILTER_OVERLAY_ALPHA): SRC = $(TARGET_SAMPLES)/png1/lena-rgba.png $(FATE_FILTER_OVERLAY_ALPHA): CMD = framecrc -i $(SRC) -sws_flags +accurate_rnd+bitexact -vf $(FILTER) -frames:v 1 -fate-filter-overlay_yuv420_yuva420: FILTER = "format=yuva420p[over];color=black:128x128,format=yuv420p[main];[main][over]overlay=format=yuv420" -fate-filter-overlay_yuv422_yuva422: FILTER = "format=yuva422p[over];color=black:128x128,format=yuv422p[main];[main][over]overlay=format=yuv422" -fate-filter-overlay_yuv444_yuva444: FILTER = "format=yuva444p[over];color=black:128x128,format=yuv444p[main];[main][over]overlay=format=yuv444" -fate-filter-overlay_rgb_rgba: FILTER = "format=rgba[over];color=black:128x128,format=rgb24[main];[main][over]overlay=format=rgb" -fate-filter-overlay_gbrp_gbrap: FILTER = "format=gbrap[over];color=black:128x128,format=gbrp[main];[main][over]overlay=format=gbrp" - -fate-filter-overlay_yuva420_yuva420: FILTER = "format=yuva420p[over];color=black:128x128,format=yuva420p[main];[main][over]overlay=format=yuv420" -fate-filter-overlay_yuva422_yuva422: FILTER = "format=yuva422p[over];color=black:128x128,format=yuva422p[main];[main][over]overlay=format=yuv422" -fate-filter-overlay_yuva444_yuva444: FILTER = "format=yuva444p[over];color=black:128x128,format=yuva444p[main];[main][over]overlay=format=yuv444" -fate-filter-overlay_rgba_rgba: FILTER = "format=rgba[over];color=black:128x128,format=rgba[main];[main][over]overlay=format=rgb" -fate-filter-overlay_gbrap_gbrap: FILTER = "format=gbrap[over];color=black:128x128,format=gbrap[main];[main][over]overlay=format=gbrp" +fate-filter-overlay_yuv420_yuva420: FILTER = "scale,format=yuva420p[over];color=black:128x128,format=yuv420p[main];[main][over]overlay=format=yuv420" +fate-filter-overlay_yuv422_yuva422: FILTER = "scale,format=yuva422p[over];color=black:128x128,format=yuv422p[main];[main][over]overlay=format=yuv422" +fate-filter-overlay_yuv444_yuva444: FILTER = "scale,format=yuva444p[over];color=black:128x128,format=yuv444p[main];[main][over]overlay=format=yuv444" +fate-filter-overlay_rgb_rgba: FILTER = "scale,format=rgba[over];color=black:128x128,format=rgb24[main];[main][over]overlay=format=rgb" +fate-filter-overlay_gbrp_gbrap: FILTER = "scale,format=gbrap[over];color=black:128x128,format=gbrp[main];[main][over]overlay=format=gbrp" + +fate-filter-overlay_yuva420_yuva420: FILTER = "scale,format=yuva420p[over];color=black:128x128,format=yuva420p[main];[main][over]overlay=format=yuv420" +fate-filter-overlay_yuva422_yuva422: FILTER = "scale,format=yuva422p[over];color=black:128x128,format=yuva422p[main];[main][over]overlay=format=yuv422" +fate-filter-overlay_yuva444_yuva444: FILTER = "scale,format=yuva444p[over];color=black:128x128,format=yuva444p[main];[main][over]overlay=format=yuv444" +fate-filter-overlay_rgba_rgba: FILTER = "scale,format=rgba[over];color=black:128x128,format=rgba[main];[main][over]overlay=format=rgb" +fate-filter-overlay_gbrap_gbrap: FILTER = "scale,format=gbrap[over];color=black:128x128,format=gbrap[main];[main][over]overlay=format=gbrp" FATE_FILTER_SAMPLES-$(call ALLYES, PNG_DECODER APNG_DEMUXER FORMAT_FILTER COLOR_FILTER OVERLAY_FILTER) += $(FATE_FILTER_OVERLAY_ALPHA) @@ -357,10 +369,10 @@ FATE_FILTER_VSYNTH-$(CONFIG_SHUFFLEFRAMES_FILTER) += $(FATE_SHUFFLEFRAMES) FATE_SHUFFLEPLANES += fate-filter-shuffleplanes-dup-luma -fate-filter-shuffleplanes-dup-luma: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf format=yuva444p,shuffleplanes=0:0:0:0 +fate-filter-shuffleplanes-dup-luma: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=yuva444p,shuffleplanes=0:0:0:0 FATE_SHUFFLEPLANES += fate-filter-shuffleplanes-swapuv -fate-filter-shuffleplanes-swapuv: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf shuffleplanes=0:2:1 +fate-filter-shuffleplanes-swapuv: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf shuffleplanes=0:2:1:0 FATE_FILTER_VSYNTH-$(CONFIG_SHUFFLEPLANES_FILTER) += $(FATE_SHUFFLEPLANES) @@ -392,29 +404,35 @@ FATE_FILTER_VSYNTH-$(CONFIG_TRIM_FILTER) += $(FATE_TRIM) +FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER UNTILE_FILTER) += fate-filter-untile +fate-filter-untile: CMD = framecrc -lavfi testsrc2=d=1:r=2,untile=2x2 + FATE_FILTER_VSYNTH-$(CONFIG_UNSHARP_FILTER) += fate-filter-unsharp fate-filter-unsharp: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf unsharp=11:11:-1.5:11:11:-1.5 +FATE_FILTER_VSYNTH-$(CONFIG_UNSHARP_FILTER) += fate-filter-unsharp-yuv420p10 +fate-filter-unsharp-yuv420p10: CMD = framecrc -lavfi testsrc2=r=2:d=10,scale,format=yuv420p10,unsharp=11:11:-1.5:11:11:-1.5,scale -pix_fmt yuv420p10le -flags +bitexact -sws_flags +accurate_rnd+bitexact + FATE_FILTER_SAMPLES-$(call ALLYES, SMJPEG_DEMUXER MJPEG_DECODER PERMS_FILTER HQDN3D_FILTER) += fate-filter-hqdn3d-sample fate-filter-hqdn3d-sample: tests/data/filtergraphs/hqdn3d fate-filter-hqdn3d-sample: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/hqdn3d -an FATE_FILTER_SAMPLES-$(call ALLYES, MATROSKA_DEMUXER OVERLAY_FILTER H264_DECODER DVDSUB_DECODER) += fate-filter-overlay-dvdsub-2397 fate-filter-overlay-dvdsub-2397: tests/data/filtergraphs/overlay-dvdsub-2397 -fate-filter-overlay-dvdsub-2397: CMD = framecrc -flags bitexact -i $(TARGET_SAMPLES)/filter/242_4.mkv -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay-dvdsub-2397 -c:a copy +fate-filter-overlay-dvdsub-2397: CMD = framecrc -auto_conversion_filters -flags bitexact -i $(TARGET_SAMPLES)/filter/242_4.mkv -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay-dvdsub-2397 -c:a copy FATE_FILTER_HQX-$(call ALLYES, IMAGE2_DEMUXER PNG_DECODER HQX_FILTER) = fate-filter-hq2x fate-filter-hq3x fate-filter-hq4x FATE_FILTER_SAMPLES-yes += $(FATE_FILTER_HQX-yes) -fate-filter-hq2x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf hqx=2 -pix_fmt bgra -fate-filter-hq3x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf hqx=3 -pix_fmt bgra -fate-filter-hq4x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf hqx=4 -pix_fmt bgra +fate-filter-hq2x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,format=rgb32,hqx=2,scale,format=bgra +fate-filter-hq3x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,format=rgb32,hqx=3,scale,format=bgra +fate-filter-hq4x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,format=rgb32,hqx=4,scale,format=bgra fate-filter-hqx: $(FATE_FILTER_HQX-yes) FATE_FILTER_XBR-$(call ALLYES, IMAGE2_DEMUXER PNG_DECODER XBR_FILTER) = fate-filter-2xbr fate-filter-3xbr fate-filter-4xbr FATE_FILTER_SAMPLES-yes += $(FATE_FILTER_XBR-yes) -fate-filter-2xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf xbr=2 -pix_fmt bgra -fate-filter-3xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf xbr=3 -pix_fmt bgra -fate-filter-4xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf xbr=4 -pix_fmt bgra +fate-filter-2xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,xbr=2,scale -pix_fmt bgra +fate-filter-3xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,xbr=3,scale -pix_fmt bgra +fate-filter-4xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,xbr=4,scale -pix_fmt bgra fate-filter-xbr: $(FATE_FILTER_XBR-yes) FATE_FILTER_SAMPLES-$(call ALLYES, UTVIDEO_DECODER AVI_DEMUXER PERMS_FILTER CURVES_FILTER) += fate-filter-curves @@ -422,11 +440,13 @@ FATE_FILTER_SAMPLES-$(call ALLYES, VMD_DEMUXER VMDVIDEO_DECODER FORMAT_FILTER PERMS_FILTER GRADFUN_FILTER) += fate-filter-gradfun-sample fate-filter-gradfun-sample: tests/data/filtergraphs/gradfun -fate-filter-gradfun-sample: CMD = framecrc -i $(TARGET_SAMPLES)/vmd/12.vmd -filter_script $(TARGET_PATH)/tests/data/filtergraphs/gradfun -an -frames:v 20 +fate-filter-gradfun-sample: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/vmd/12.vmd -filter_script $(TARGET_PATH)/tests/data/filtergraphs/gradfun -an -frames:v 20 -FATE_FILTER-$(call ALLYES, TESTSRC_FILTER SINE_FILTER CONCAT_FILTER) += fate-filter-concat +FATE_FILTER-$(call ALLYES, TESTSRC_FILTER SINE_FILTER CONCAT_FILTER) += fate-filter-concat fate-filter-concat-vfr fate-filter-concat: tests/data/filtergraphs/concat fate-filter-concat: CMD = framecrc -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/concat +fate-filter-concat-vfr: tests/data/filtergraphs/concat-vfr +fate-filter-concat-vfr: CMD = framecrc -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/concat-vfr FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER FPS_FILTER MPDECIMATE_FILTER) += fate-filter-mpdecimate fate-filter-mpdecimate: CMD = framecrc -lavfi testsrc2=r=2:d=10,fps=3,mpdecimate -r 3 -pix_fmt yuv420p @@ -443,17 +463,17 @@ fate-filter-fps-start-fill: CMD = framecrc -lavfi testsrc2=r=7:d=1.5,setpts=PTS+14,fps=3:start_time=1.5 FATE_FILTER_SAMPLES-$(call ALLYES, MOV_DEMUXER FPS_FILTER QTRLE_DECODER) += fate-filter-fps-cfr fate-filter-fps fate-filter-fps-r -fate-filter-fps-cfr: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vsync cfr -pix_fmt yuv420p -fate-filter-fps-r: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vf fps -pix_fmt yuv420p -fate-filter-fps: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -vf fps=30 -pix_fmt yuv420p +fate-filter-fps-cfr: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vsync cfr -pix_fmt yuv420p +fate-filter-fps-r: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vf fps -pix_fmt yuv420p +fate-filter-fps: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -vf fps=30 -pix_fmt yuv420p FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER SPLIT_FILTER ALPHAEXTRACT_FILTER ALPHAMERGE_FILTER) += fate-filter-alphaextract_alphamerge_rgb fate-filter-alphaextract_alphamerge_rgb: tests/data/filtergraphs/alphamerge_alphaextract_rgb -fate-filter-alphaextract_alphamerge_rgb: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/alphamerge_alphaextract_rgb +fate-filter-alphaextract_alphamerge_rgb: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/alphamerge_alphaextract_rgb FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER SPLIT_FILTER ALPHAEXTRACT_FILTER ALPHAMERGE_FILTER) += fate-filter-alphaextract_alphamerge_yuv fate-filter-alphaextract_alphamerge_yuv: tests/data/filtergraphs/alphamerge_alphaextract_yuv -fate-filter-alphaextract_alphamerge_yuv: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/alphamerge_alphaextract_yuv +fate-filter-alphaextract_alphamerge_yuv: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/alphamerge_alphaextract_yuv FATE_FILTER_VSYNTH-$(CONFIG_CROP_FILTER) += fate-filter-crop fate-filter-crop: CMD = video_filter "crop=iw-100:ih-100:100:100" @@ -482,11 +502,29 @@ FATE_FILTER_VSYNTH-$(CONFIG_SCALE_FILTER) += fate-filter-scalechroma fate-filter-scalechroma: tests/data/vsynth1.yuv -fate-filter-scalechroma: CMD = framecrc -flags bitexact -s 352x288 -pix_fmt yuv444p -i tests/data/vsynth1.yuv -pix_fmt yuv420p -sws_flags +bitexact -vf scale=out_v_chr_pos=33:out_h_chr_pos=151 +fate-filter-scalechroma: CMD = framecrc -flags bitexact -s 352x288 -pix_fmt yuv444p -i $(TARGET_PATH)/tests/data/vsynth1.yuv -pix_fmt yuv420p -sws_flags +bitexact -vf scale=out_v_chr_pos=33:out_h_chr_pos=151 FATE_FILTER_VSYNTH-$(CONFIG_VFLIP_FILTER) += fate-filter-vflip fate-filter-vflip: CMD = video_filter "vflip" +FATE_FILTER_VSYNTH-$(CONFIG_COLORLEVELS_FILTER) += fate-filter-colorlevels +fate-filter-colorlevels: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=rgb24,colorlevels -flags +bitexact -sws_flags +accurate_rnd+bitexact + +FATE_FILTER_VSYNTH-$(CONFIG_COLORLEVELS_FILTER) += fate-filter-colorlevels-16 +fate-filter-colorlevels-16: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=rgb48,colorlevels,scale -pix_fmt rgb48le -flags +bitexact -sws_flags +accurate_rnd+bitexact + +FATE_FILTER_VSYNTH-$(CONFIG_COLORBALANCE_FILTER) += fate-filter-colorbalance +fate-filter-colorbalance: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=rgb24,colorbalance=rs=.2 -flags +bitexact -sws_flags +accurate_rnd+bitexact -frames:v 3 + +FATE_FILTER_VSYNTH-$(CONFIG_COLORBALANCE_FILTER) += fate-filter-colorbalance-gbrap +fate-filter-colorbalance-gbrap: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=gbrap,colorbalance=gh=.2 -flags +bitexact -sws_flags +accurate_rnd+bitexact -frames:v 3 + +FATE_FILTER_VSYNTH-$(CONFIG_COLORBALANCE_FILTER) += fate-filter-colorbalance-rgba64 +fate-filter-colorbalance-rgba64: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=rgba64,colorbalance=rm=.2,scale -pix_fmt rgba64le -flags +bitexact -sws_flags +accurate_rnd+bitexact -frames:v 3 + +FATE_FILTER_VSYNTH-$(CONFIG_COLORBALANCE_FILTER) += fate-filter-colorbalance-gbrap-16 +fate-filter-colorbalance-gbrap-16: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=gbrap,colorbalance=bh=.2 -pix_fmt gbrap -flags +bitexact -sws_flags +accurate_rnd+bitexact -frames:v 3 + FATE_FILTER_VSYNTH-$(CONFIG_COLORMATRIX_FILTER) += fate-filter-colormatrix1 fate-filter-colormatrix1: CMD = video_filter "colormatrix=bt601:smpte240m,colormatrix=smpte240m:fcc,colormatrix=fcc:bt601,colormatrix=bt601:fcc,colormatrix=fcc:smpte240m,colormatrix=smpte240m:bt709" @@ -500,10 +538,10 @@ fate-filter-vflip_vflip: CMD = video_filter "vflip,vflip" FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER PERMS_FILTER EDGEDETECT_FILTER) += fate-filter-edgedetect -fate-filter-edgedetect: CMD = video_filter "format=gray,perms=random,edgedetect" -frames:v 20 +fate-filter-edgedetect: CMD = video_filter "scale,format=gray,perms=random,edgedetect" -frames:v 20 FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER PERMS_FILTER EDGEDETECT_FILTER) += fate-filter-edgedetect-colormix -fate-filter-edgedetect-colormix: CMD = video_filter "format=gbrp,perms=random,edgedetect=mode=colormix" -frames:v 20 +fate-filter-edgedetect-colormix: CMD = video_filter "scale,format=gbrp,perms=random,edgedetect=mode=colormix" -frames:v 20 FATE_FILTER_VSYNTH-$(call ALLYES, PERMS_FILTER HUE_FILTER) += fate-filter-hue1 fate-filter-hue1: CMD = video_filter "perms=random,hue=s=sin(2*PI*t)+1" -frames:v 20 @@ -515,7 +553,7 @@ fate-filter-hue3: CMD = video_filter "perms=random,hue=b=n-10" -frames:v 20 FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER PERMS_FILTER HUE_FILTER) += fate-filter-hue4 -fate-filter-hue4: CMD = video_filter "format=yuv422p10,perms=random,hue=h=18*n:s=n/10" -frames:v 20 -pix_fmt yuv422p10le +fate-filter-hue4: CMD = video_filter "scale,format=yuv422p10,perms=random,hue=h=18*n:s=n/10,scale" -frames:v 20 -pix_fmt yuv422p10le FATE_FILTER_VSYNTH-$(CONFIG_IDET_FILTER) += fate-filter-idet fate-filter-idet: CMD = framecrc -flags bitexact -idct simple -i $(SRC) -vf idet -frames:v 25 -flags +bitexact @@ -526,17 +564,30 @@ FATE_FILTER_PP = fate-filter-pp fate-filter-pp1 fate-filter-pp2 fate-filter-pp3 fate-filter-pp4 fate-filter-pp5 fate-filter-pp6 FATE_FILTER_VSYNTH-$(CONFIG_PP_FILTER) += $(FATE_FILTER_PP) $(FATE_FILTER_PP): fate-vsynth1-mpeg4-qprd +fate-vsynth1-mpeg4-qprd: KEEP_OVERRIDE= -keep -fate-filter-pp: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_PATH)/tests/data/fate/vsynth1-mpeg4-qprd.avi -frames:v 5 -flags +bitexact -vf "pp=be/hb/vb/tn/l5/al" +fate-filter-pp: CMD = framecrc -flags bitexact -export_side_data venc_params -idct simple -i $(TARGET_PATH)/tests/data/fate/vsynth1-mpeg4-qprd.avi -frames:v 5 -flags +bitexact -vf "pp=be/hb/vb/tn/l5/al" fate-filter-pp1: CMD = video_filter "pp=fq|4/be/hb/vb/tn/l5/al" -fate-filter-pp2: CMD = video_filter "qp=x+y,pp=be/h1/v1/lb" -fate-filter-pp3: CMD = video_filter "qp=x+y,pp=be/ha|128|7/va/li" +fate-filter-pp2: CMD = video_filter "qp=2*(x+y),pp=be/h1/v1/lb" +fate-filter-pp3: CMD = video_filter "qp=2*(x+y),pp=be/ha|128|7/va/li" fate-filter-pp4: CMD = video_filter "pp=be/ci" fate-filter-pp5: CMD = video_filter "pp=md" fate-filter-pp6: CMD = video_filter "pp=be/fd" +FATE_FILTER_VSYNTH-$(CONFIG_PP7_FILTER) += fate-filter-pp7 +fate-filter-pp7: fate-vsynth1-mpeg4-qprd +fate-filter-pp7: CMD = framecrc -flags bitexact -export_side_data venc_params -idct simple -i $(TARGET_PATH)/tests/data/fate/vsynth1-mpeg4-qprd.avi -frames:v 5 -flags +bitexact -vf "pp7" + +FATE_FILTER_VSYNTH-$(CONFIG_SPP_FILTER) += fate-filter-spp +fate-filter-spp: fate-vsynth1-mpeg4-qprd +fate-filter-spp: CMD = framecrc -flags bitexact -export_side_data venc_params -idct simple -i $(TARGET_PATH)/tests/data/fate/vsynth1-mpeg4-qprd.avi -frames:v 5 -flags +bitexact -vf "spp=idct=simple:dct=int" + +FATE_FILTER_VSYNTH-$(CONFIG_CODECVIEW_FILTER) += fate-filter-codecview +fate-filter-codecview: fate-vsynth1-mpeg4-qprd +fate-filter-codecview: CMD = framecrc -flags bitexact -idct simple -flags2 +export_mvs -i $(TARGET_PATH)/tests/data/fate/vsynth1-mpeg4-qprd.avi -frames:v 5 -flags +bitexact -vf codecview=mv=pf+bf+bb + FATE_FILTER_VSYNTH-$(call ALLYES, QP_FILTER PP_FILTER) += fate-filter-qp -fate-filter-qp: CMD = video_filter "qp=17,pp=be/hb/vb/tn/l5/al" +fate-filter-qp: CMD = video_filter "qp=34,pp=be/hb/vb/tn/l5/al" FATE_FILTER_VSYNTH-$(CONFIG_SELECT_FILTER) += fate-filter-select fate-filter-select: CMD = framecrc -flags bitexact -idct simple -i $(SRC) -vf "select=not(eq(mod(n\,2)\,0)+eq(mod(n\,3)\,0))" -frames:v 25 -flags +bitexact @@ -548,76 +599,76 @@ fate-filter-setsar: CMD = video_filter "setsar=sar=16/11" FATE_STEREO3D += fate-filter-stereo3d-al-sbsl -fate-filter-stereo3d-al-sbsl: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=al:sbsl +fate-filter-stereo3d-al-sbsl: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=al:sbsl FATE_STEREO3D += fate-filter-stereo3d-ar-abl -fate-filter-stereo3d-ar-abl: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=ar:abl +fate-filter-stereo3d-ar-abl: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=ar:abl FATE_STEREO3D += fate-filter-stereo3d-abr-mr -fate-filter-stereo3d-abr-mr: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=abr:mr +fate-filter-stereo3d-abr-mr: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=abr:mr FATE_STEREO3D += fate-filter-stereo3d-abr-ml -fate-filter-stereo3d-abr-ml: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=abr:ml +fate-filter-stereo3d-abr-ml: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=abr:ml FATE_STEREO3D += fate-filter-stereo3d-sbsl-abl -fate-filter-stereo3d-sbsl-abl: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:abl +fate-filter-stereo3d-sbsl-abl: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:abl FATE_STEREO3D += fate-filter-stereo3d-sbsl-abr -fate-filter-stereo3d-sbsl-abr: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:abr +fate-filter-stereo3d-sbsl-abr: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:abr FATE_STEREO3D += fate-filter-stereo3d-sbsl-al -fate-filter-stereo3d-sbsl-al: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:al +fate-filter-stereo3d-sbsl-al: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:al FATE_STEREO3D += fate-filter-stereo3d-sbsl-sbsr -fate-filter-stereo3d-sbsl-sbsr: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:sbsr +fate-filter-stereo3d-sbsl-sbsr: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:sbsr FATE_STEREO3D += fate-filter-stereo3d-sbsl-agmc -fate-filter-stereo3d-sbsl-agmc: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:agmc +fate-filter-stereo3d-sbsl-agmc: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:agmc FATE_STEREO3D += fate-filter-stereo3d-sbsl-agmd -fate-filter-stereo3d-sbsl-agmd: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:agmd +fate-filter-stereo3d-sbsl-agmd: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:agmd FATE_STEREO3D += fate-filter-stereo3d-sbsl-agmg -fate-filter-stereo3d-sbsl-agmg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:agmg +fate-filter-stereo3d-sbsl-agmg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:agmg FATE_STEREO3D += fate-filter-stereo3d-sbsl-agmh -fate-filter-stereo3d-sbsl-agmh: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:agmh +fate-filter-stereo3d-sbsl-agmh: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:agmh FATE_STEREO3D += fate-filter-stereo3d-sbsl-arbg -fate-filter-stereo3d-sbsl-arbg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:arbg +fate-filter-stereo3d-sbsl-arbg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:arbg FATE_STEREO3D += fate-filter-stereo3d-sbsl-arcc -fate-filter-stereo3d-sbsl-arcc: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:arcc +fate-filter-stereo3d-sbsl-arcc: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:arcc FATE_STEREO3D += fate-filter-stereo3d-sbsl-arcd -fate-filter-stereo3d-sbsl-arcd: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:arcd +fate-filter-stereo3d-sbsl-arcd: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:arcd FATE_STEREO3D += fate-filter-stereo3d-sbsl-arcg -fate-filter-stereo3d-sbsl-arcg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:arcg +fate-filter-stereo3d-sbsl-arcg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:arcg FATE_STEREO3D += fate-filter-stereo3d-sbsl-arch -fate-filter-stereo3d-sbsl-arch: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:arch +fate-filter-stereo3d-sbsl-arch: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:arch FATE_STEREO3D += fate-filter-stereo3d-sbsl-argg -fate-filter-stereo3d-sbsl-argg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:argg +fate-filter-stereo3d-sbsl-argg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:argg FATE_STEREO3D += fate-filter-stereo3d-sbsl-aybc -fate-filter-stereo3d-sbsl-aybc: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:aybc +fate-filter-stereo3d-sbsl-aybc: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:aybc FATE_STEREO3D += fate-filter-stereo3d-sbsl-aybd -fate-filter-stereo3d-sbsl-aybd: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:aybd +fate-filter-stereo3d-sbsl-aybd: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:aybd FATE_STEREO3D += fate-filter-stereo3d-sbsl-aybg -fate-filter-stereo3d-sbsl-aybg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:aybg +fate-filter-stereo3d-sbsl-aybg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:aybg FATE_STEREO3D += fate-filter-stereo3d-sbsl-aybh -fate-filter-stereo3d-sbsl-aybh: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf stereo3d=sbsl:aybh +fate-filter-stereo3d-sbsl-aybh: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:aybh fate-filter-stereo3d: $(FATE_STEREO3D) FATE_FILTER_VSYNTH-$(CONFIG_STEREO3D_FILTER) += $(FATE_STEREO3D) FATE_FILTER_VSYNTH-$(CONFIG_THUMBNAIL_FILTER) += fate-filter-thumbnail -fate-filter-thumbnail: CMD = video_filter "thumbnail=10" +fate-filter-thumbnail: CMD = video_filter "scale,thumbnail=10" FATE_FILTER_VSYNTH-$(CONFIG_TILE_FILTER) += fate-filter-tile fate-filter-tile: CMD = video_filter "tile=3x3:nb_frames=5:padding=7:margin=2" @@ -637,7 +688,7 @@ define PIXDESC_TEST FATE_FILTER_PIXDESC-$(CONFIG_FORMAT_FILTER) += fate-filter-pixdesc-$(1) -fate-filter-pixdesc-$(1): CMD = video_filter "format=$(1),pixdesctest" -pix_fmt $(1) +fate-filter-pixdesc-$(1): CMD = video_filter "scale,format=$(1),pixdesctest" -pix_fmt $(1) endef $(foreach fmt, $(PIXFMTS), $(eval $(call PIXDESC_TEST,$(fmt)))) @@ -734,7 +785,13 @@ AVCODEC AVDEVICE MOV_DEMUXER SVQ3_DECODER ZLIB FATE_METADATA_FILTER-$(call ALLYES, $(SCENEDETECT_DEPS)) += fate-filter-metadata-scenedetect fate-filter-metadata-scenedetect: SRC = $(TARGET_SAMPLES)/svq3/Vertical400kbit.sorenson3.mov -fate-filter-metadata-scenedetect: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;movie='$(SRC)',select=gt(scene\,.4)" +fate-filter-metadata-scenedetect: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;movie='$(SRC)',select=gt(scene\,.25)" + +SCDET_DEPS = FFPROBE LAVFI_INDEV MOVIE_FILTER SCDET_FILTER SCALE_FILTER \ + AVCODEC AVDEVICE MOV_DEMUXER SVQ3_DECODER ZLIB +FATE_METADATA_FILTER-$(call ALLYES, $(SCDET_DEPS)) += fate-filter-metadata-scdet +fate-filter-metadata-scdet: SRC = $(TARGET_SAMPLES)/svq3/Vertical400kbit.sorenson3.mov +fate-filter-metadata-scdet: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;movie='$(SRC)',scdet=s=1" CROPDETECT_DEPS = FFPROBE LAVFI_INDEV MOVIE_FILTER CROPDETECT_FILTER SCALE_FILTER \ AVCODEC AVDEVICE MOV_DEMUXER H264_DECODER @@ -742,10 +799,19 @@ fate-filter-metadata-cropdetect: SRC = $(TARGET_SAMPLES)/filter/cropdetect.mp4 fate-filter-metadata-cropdetect: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;movie='$(SRC)',cropdetect=max_outliers=3" +FREEZEDETECT_DEPS = FFPROBE AVDEVICE LAVFI_INDEV MPTESTSRC_FILTER SCALE_FILTER FREEZEDETECT_FILTER +FATE_METADATA_FILTER-$(call ALLYES, $(FREEZEDETECT_DEPS)) += fate-filter-metadata-freezedetect +fate-filter-metadata-freezedetect: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;mptestsrc=r=25:d=10:m=51,freezedetect" + +SIGNALSTATS_DEPS = FFPROBE AVDEVICE LAVFI_INDEV COLOR_FILTER SCALE_FILTER SIGNALSTATS_FILTER +FATE_METADATA_FILTER-$(call ALLYES, $(SIGNALSTATS_DEPS)) += fate-filter-metadata-signalstats-yuv420p fate-filter-metadata-signalstats-yuv420p10 +fate-filter-metadata-signalstats-yuv420p: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;color=white:duration=1:r=1,signalstats" +fate-filter-metadata-signalstats-yuv420p10: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;color=white:duration=1:r=1,format=yuv420p10,signalstats" + SILENCEDETECT_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER TTA_DEMUXER TTA_DECODER SILENCEDETECT_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(SILENCEDETECT_DEPS)) += fate-filter-metadata-silencedetect fate-filter-metadata-silencedetect: SRC = $(TARGET_SAMPLES)/lossless-audio/inside.tta -fate-filter-metadata-silencedetect: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',silencedetect=n=-33.5dB:d=.2" +fate-filter-metadata-silencedetect: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',silencedetect=n=-33.5dB:d=0.2" EBUR128_METADATA_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER FLAC_DEMUXER FLAC_DECODER EBUR128_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(EBUR128_METADATA_DEPS)) += fate-filter-metadata-ebur128 @@ -777,7 +843,7 @@ FATE_FILTER_SAMPLES-$(call ALLYES, MOV_DEMUXER H264_DECODER AAC_FIXED_DECODER PCM_S16LE_ENCODER MOV_MUXER) += fate-filter-meta-4560-rotate0 fate-filter-meta-4560-rotate0: tests/data/file4560-override2rotate0.mov -fate-filter-meta-4560-rotate0: CMD = framecrc -flags +bitexact -c:a aac_fixed -i $(TARGET_PATH)/tests/data/file4560-override2rotate0.mov +fate-filter-meta-4560-rotate0: CMD = framecrc -auto_conversion_filters -flags +bitexact -c:a aac_fixed -i $(TARGET_PATH)/tests/data/file4560-override2rotate0.mov REFCMP_DEPS = FFMPEG LAVFI_INDEV TESTSRC2_FILTER AVGBLUR_FILTER METADATA_FILTER diff -Nru ffmpeg-4.2.2/tests/fate/fits.mak ffmpeg-4.4/tests/fate/fits.mak --- ffmpeg-4.2.2/tests/fate/fits.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/fits.mak 2021-04-08 21:28:40.000000000 +0000 @@ -5,6 +5,7 @@ -y $(TARGET_PATH)/$(@) 2>/dev/null #mapping of fits file formats to png filenames +# TODO: Use an actual 64bit input file and fix the gbrp16 test on big-endian map.tests/data/lena-gray.fits := gray8 map.tests/data/lena-gbrp.fits := rgb24 map.tests/data/lena-gbrp16.fits := rgb48 @@ -18,16 +19,16 @@ -y $(TARGET_PATH)/$(@) 2>/dev/null FATE_FITS_DEC-$(call DEMDEC, FITS, FITS) += fate-fitsdec-ext_data_min_max -fate-fitsdec-ext_data_min_max: CMD = framecrc -i $(TARGET_SAMPLES)/fits/x0cj010ct_d0h.fit -pix_fmt gray16le +fate-fitsdec-ext_data_min_max: CMD = framecrc -i $(TARGET_SAMPLES)/fits/x0cj010ct_d0h.fit -pix_fmt gray16le -vf scale FATE_FITS_DEC-$(call DEMDEC, FITS, FITS) += fate-fitsdec-blank_bitpix32 -fate-fitsdec-blank_bitpix32: CMD = framecrc -blank_value 65535 -i $(TARGET_SAMPLES)/fits/file008.fits -pix_fmt gray16le +fate-fitsdec-blank_bitpix32: CMD = framecrc -blank_value 65535 -i $(TARGET_SAMPLES)/fits/file008.fits -pix_fmt gray16le -vf scale FATE_FITS_DEC-$(call DEMDEC, FITS, FITS) += fate-fitsdec-bitpix-32 -fate-fitsdec-bitpix-32: CMD = framecrc -i $(TARGET_SAMPLES)/fits/tst0005.fits -pix_fmt gray16le +fate-fitsdec-bitpix-32: CMD = framecrc -i $(TARGET_SAMPLES)/fits/tst0005.fits -pix_fmt gray16le -vf scale FATE_FITS_DEC-$(call DEMDEC, FITS, FITS) += fate-fitsdec-bitpix-64 -fate-fitsdec-bitpix-64: CMD = framecrc -i $(TARGET_SAMPLES)/fits/tst0006.fits -pix_fmt gray16le +fate-fitsdec-bitpix-64: CMD = framecrc -i $(TARGET_SAMPLES)/fits/tst0006.fits -pix_fmt gray16le -vf scale FATE_FITS_DEC-$(call ALLYES, GIF_DEMUXER FITS_DEMUXER GIF_DECODER FITS_DECODER FITS_ENCODER FITS_MUXER) += fate-fitsdec-multi fate-fitsdec-multi: tests/data/fits-multi.fits @@ -46,7 +47,7 @@ fate-fitsenc%: PIXFMT = $(word 3, $(subst -, ,$(@))) fate-fitsenc%: SRC = $(TARGET_PATH)/tests/data/fits-multi.fits -fate-fitsenc%: CMD = framecrc -i $(SRC) -c:v fits -pix_fmt $(PIXFMT) +fate-fitsenc%: CMD = framecrc -auto_conversion_filters -i $(SRC) -c:v fits -pix_fmt $(PIXFMT) FATE_FITS_ENC_PIXFMT = gray gray16be gbrp gbrap gbrp16be gbrap16be $(FATE_FITS_ENC_PIXFMT:%=fate-fitsenc-%): tests/data/fits-multi.fits diff -Nru ffmpeg-4.2.2/tests/fate/gapless.mak ffmpeg-4.4/tests/fate/gapless.mak --- ffmpeg-4.2.2/tests/fate/gapless.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/gapless.mak 2020-07-11 10:39:30.000000000 +0000 @@ -2,7 +2,7 @@ fate-gapless-mp3: CMD = gapless $(TARGET_SAMPLES)/gapless/gapless.mp3 "-c:a mp3" FATE_GAPLESS-$(CONFIG_MP3_DEMUXER) += fate-audiomatch-square-mp3 -fate-audiomatch-square-mp3: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/square3.mp3 $(TARGET_SAMPLES)/audiomatch/square3.wav +fate-audiomatch-square-mp3: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/square3.mp3 $(SAMPLES)/audiomatch/square3.wav FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-square-aac FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-afconvert-16000-mono-lc-adts fate-audiomatch-afconvert-16000-mono-lc-m4a @@ -40,57 +40,57 @@ FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-quicktime7-44100-stereo-lc-mp4 fate-audiomatch-quicktimeX-44100-stereo-lc-m4a -fate-audiomatch-square-aac: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/square3.m4a $(TARGET_SAMPLES)/audiomatch/square3.wav +fate-audiomatch-square-aac: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/square3.m4a $(SAMPLES)/audiomatch/square3.wav -fate-audiomatch-afconvert-16000-mono-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_lc.adts $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav -fate-audiomatch-afconvert-16000-mono-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav -fate-audiomatch-afconvert-16000-mono-he-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_he.adts $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav "-ac 1 -ar 16000" -fate-audiomatch-afconvert-16000-mono-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_he.m4a $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav "-ac 1 -ar 16000" -fate-audiomatch-afconvert-16000-stereo-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_lc.adts $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav -fate-audiomatch-afconvert-16000-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav -fate-audiomatch-afconvert-16000-stereo-he-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_he.adts $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav "-ar 16000" -fate-audiomatch-afconvert-16000-stereo-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_he.m4a $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav "-ar 16000" -fate-audiomatch-afconvert-16000-stereo-he2-adts:CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_he2.adts $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav "-ar 16000" -fate-audiomatch-afconvert-16000-stereo-he2-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_he2.m4a $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav "-ar 16000" -fate-audiomatch-afconvert-44100-mono-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_mono_aac_lc.adts $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav -fate-audiomatch-afconvert-44100-mono-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_mono_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav -fate-audiomatch-afconvert-44100-mono-he-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_mono_aac_he.adts $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav "-ac 1" -fate-audiomatch-afconvert-44100-mono-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_mono_aac_he.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav "-ac 1" -fate-audiomatch-afconvert-44100-stereo-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_lc.adts $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav -fate-audiomatch-afconvert-44100-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav -fate-audiomatch-afconvert-44100-stereo-he-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he.adts $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav -fate-audiomatch-afconvert-44100-stereo-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav -fate-audiomatch-afconvert-44100-stereo-he2-adts:CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he2.adts $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav -fate-audiomatch-afconvert-44100-stereo-he2-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he2.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav - -fate-audiomatch-dolby-44100-mono-lc-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_mono_aac_lc.mp4 $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav -fate-audiomatch-dolby-44100-mono-he-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_mono_aac_he.mp4 $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav "-ac 1" -fate-audiomatch-dolby-44100-stereo-lc-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_stereo_aac_lc.mp4 $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav -fate-audiomatch-dolby-44100-stereo-he-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_stereo_aac_he.mp4 $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav -fate-audiomatch-dolby-44100-stereo-he2-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_stereo_aac_he2.mp4 $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav - -fate-audiomatch-faac-16000-mono-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_16000_mono_aac_lc.adts $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav -fate-audiomatch-faac-16000-mono-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_16000_mono_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav -fate-audiomatch-faac-16000-stereo-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_16000_stereo_aac_lc.adts $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav -fate-audiomatch-faac-16000-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_16000_stereo_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav -fate-audiomatch-faac-44100-mono-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_44100_mono_aac_lc.adts $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav -fate-audiomatch-faac-44100-mono-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_44100_mono_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav -fate-audiomatch-faac-44100-stereo-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_44100_stereo_aac_lc.adts $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav -fate-audiomatch-faac-44100-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_44100_stereo_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav - -fate-audiomatch-nero-16000-mono-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_mono_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav -fate-audiomatch-nero-16000-mono-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_mono_aac_he.m4a $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav -fate-audiomatch-nero-16000-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_stereo_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav -fate-audiomatch-nero-16000-stereo-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_stereo_aac_he.m4a $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav -fate-audiomatch-nero-16000-stereo-he2-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_stereo_aac_he2.m4a $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav -fate-audiomatch-nero-44100-mono-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_mono_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav -fate-audiomatch-nero-44100-mono-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_mono_aac_he.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav -fate-audiomatch-nero-44100-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_stereo_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav -fate-audiomatch-nero-44100-stereo-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_stereo_aac_he.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav -fate-audiomatch-nero-44100-stereo-he2-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_stereo_aac_he2.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-afconvert-16000-mono-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_lc.adts $(SAMPLES)/audiomatch/tones_16000_mono.wav +fate-audiomatch-afconvert-16000-mono-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_lc.m4a $(SAMPLES)/audiomatch/tones_16000_mono.wav +fate-audiomatch-afconvert-16000-mono-he-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_he.adts $(SAMPLES)/audiomatch/tones_16000_mono.wav "-ac 1 -ar 16000" +fate-audiomatch-afconvert-16000-mono-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_he.m4a $(SAMPLES)/audiomatch/tones_16000_mono.wav "-ac 1 -ar 16000" +fate-audiomatch-afconvert-16000-stereo-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_lc.adts $(SAMPLES)/audiomatch/tones_16000_stereo.wav +fate-audiomatch-afconvert-16000-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_lc.m4a $(SAMPLES)/audiomatch/tones_16000_stereo.wav +fate-audiomatch-afconvert-16000-stereo-he-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_he.adts $(SAMPLES)/audiomatch/tones_16000_stereo.wav "-ar 16000" +fate-audiomatch-afconvert-16000-stereo-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_he.m4a $(SAMPLES)/audiomatch/tones_16000_stereo.wav "-ar 16000" +fate-audiomatch-afconvert-16000-stereo-he2-adts:CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_he2.adts $(SAMPLES)/audiomatch/tones_16000_stereo.wav "-ar 16000" +fate-audiomatch-afconvert-16000-stereo-he2-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_he2.m4a $(SAMPLES)/audiomatch/tones_16000_stereo.wav "-ar 16000" +fate-audiomatch-afconvert-44100-mono-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_mono_aac_lc.adts $(SAMPLES)/audiomatch/tones_44100_mono.wav +fate-audiomatch-afconvert-44100-mono-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_mono_aac_lc.m4a $(SAMPLES)/audiomatch/tones_44100_mono.wav +fate-audiomatch-afconvert-44100-mono-he-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_mono_aac_he.adts $(SAMPLES)/audiomatch/tones_44100_mono.wav "-ac 1" +fate-audiomatch-afconvert-44100-mono-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_mono_aac_he.m4a $(SAMPLES)/audiomatch/tones_44100_mono.wav "-ac 1" +fate-audiomatch-afconvert-44100-stereo-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_lc.adts $(SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-afconvert-44100-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_lc.m4a $(SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-afconvert-44100-stereo-he-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he.adts $(SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-afconvert-44100-stereo-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he.m4a $(SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-afconvert-44100-stereo-he2-adts:CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he2.adts $(SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-afconvert-44100-stereo-he2-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he2.m4a $(SAMPLES)/audiomatch/tones_44100_stereo.wav + +fate-audiomatch-dolby-44100-mono-lc-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_mono_aac_lc.mp4 $(SAMPLES)/audiomatch/tones_44100_mono.wav +fate-audiomatch-dolby-44100-mono-he-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_mono_aac_he.mp4 $(SAMPLES)/audiomatch/tones_44100_mono.wav "-ac 1" +fate-audiomatch-dolby-44100-stereo-lc-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_stereo_aac_lc.mp4 $(SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-dolby-44100-stereo-he-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_stereo_aac_he.mp4 $(SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-dolby-44100-stereo-he2-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_stereo_aac_he2.mp4 $(SAMPLES)/audiomatch/tones_44100_stereo.wav + +fate-audiomatch-faac-16000-mono-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_16000_mono_aac_lc.adts $(SAMPLES)/audiomatch/tones_16000_mono.wav +fate-audiomatch-faac-16000-mono-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_16000_mono_aac_lc.m4a $(SAMPLES)/audiomatch/tones_16000_mono.wav +fate-audiomatch-faac-16000-stereo-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_16000_stereo_aac_lc.adts $(SAMPLES)/audiomatch/tones_16000_stereo.wav +fate-audiomatch-faac-16000-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_16000_stereo_aac_lc.m4a $(SAMPLES)/audiomatch/tones_16000_stereo.wav +fate-audiomatch-faac-44100-mono-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_44100_mono_aac_lc.adts $(SAMPLES)/audiomatch/tones_44100_mono.wav +fate-audiomatch-faac-44100-mono-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_44100_mono_aac_lc.m4a $(SAMPLES)/audiomatch/tones_44100_mono.wav +fate-audiomatch-faac-44100-stereo-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_44100_stereo_aac_lc.adts $(SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-faac-44100-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_44100_stereo_aac_lc.m4a $(SAMPLES)/audiomatch/tones_44100_stereo.wav + +fate-audiomatch-nero-16000-mono-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_mono_aac_lc.m4a $(SAMPLES)/audiomatch/tones_16000_mono.wav +fate-audiomatch-nero-16000-mono-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_mono_aac_he.m4a $(SAMPLES)/audiomatch/tones_16000_mono.wav +fate-audiomatch-nero-16000-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_stereo_aac_lc.m4a $(SAMPLES)/audiomatch/tones_16000_stereo.wav +fate-audiomatch-nero-16000-stereo-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_stereo_aac_he.m4a $(SAMPLES)/audiomatch/tones_16000_stereo.wav +fate-audiomatch-nero-16000-stereo-he2-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_stereo_aac_he2.m4a $(SAMPLES)/audiomatch/tones_16000_stereo.wav +fate-audiomatch-nero-44100-mono-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_mono_aac_lc.m4a $(SAMPLES)/audiomatch/tones_44100_mono.wav +fate-audiomatch-nero-44100-mono-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_mono_aac_he.m4a $(SAMPLES)/audiomatch/tones_44100_mono.wav +fate-audiomatch-nero-44100-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_stereo_aac_lc.m4a $(SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-nero-44100-stereo-he-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_stereo_aac_he.m4a $(SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-nero-44100-stereo-he2-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_stereo_aac_he2.m4a $(SAMPLES)/audiomatch/tones_44100_stereo.wav -fate-audiomatch-quicktime7-44100-stereo-lc-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_quicktime7_44100_stereo_aac_lc.mp4 $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav -fate-audiomatch-quicktimeX-44100-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_quicktimeX_44100_stereo_aac_lc.m4a $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-quicktime7-44100-stereo-lc-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_quicktime7_44100_stereo_aac_lc.mp4 $(SAMPLES)/audiomatch/tones_44100_stereo.wav +fate-audiomatch-quicktimeX-44100-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_quicktimeX_44100_stereo_aac_lc.m4a $(SAMPLES)/audiomatch/tones_44100_stereo.wav FATE_GAPLESS = $(FATE_GAPLESS-yes) diff -Nru ffmpeg-4.2.2/tests/fate/gif.mak ffmpeg-4.4/tests/fate/gif.mak --- ffmpeg-4.2.2/tests/fate/gif.mak 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/fate/gif.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,22 +1,22 @@ FATE_GIF += fate-gif-color -fate-gif-color: CMD = framecrc -i $(TARGET_SAMPLES)/gif/tc217.gif -pix_fmt bgra +fate-gif-color: CMD = framecrc -i $(TARGET_SAMPLES)/gif/tc217.gif -pix_fmt bgra -vf scale FATE_GIF += fate-gif-disposal-background -fate-gif-disposal-background: CMD = framecrc -trans_color 0 -i $(TARGET_SAMPLES)/gif/m4nb.gif -pix_fmt bgra +fate-gif-disposal-background: CMD = framecrc -trans_color 0 -i $(TARGET_SAMPLES)/gif/m4nb.gif -pix_fmt bgra -vf scale FATE_GIF += fate-gif-disposal-restore -fate-gif-disposal-restore: CMD = framecrc -i $(TARGET_SAMPLES)/gif/banner2.gif -pix_fmt bgra +fate-gif-disposal-restore: CMD = framecrc -i $(TARGET_SAMPLES)/gif/banner2.gif -pix_fmt bgra -vf scale FATE_GIF += fate-gif-gray -fate-gif-gray: CMD = framecrc -i $(TARGET_SAMPLES)/gif/Newtons_cradle_animation_book_2.gif -pix_fmt bgra +fate-gif-gray: CMD = framecrc -i $(TARGET_SAMPLES)/gif/Newtons_cradle_animation_book_2.gif -pix_fmt bgra -vf scale FATE_GIF += fate-gif-deal -fate-gif-deal: CMD = framecrc -i $(TARGET_SAMPLES)/gif/deal.gif -vsync cfr -pix_fmt bgra +fate-gif-deal: CMD = framecrc -i $(TARGET_SAMPLES)/gif/deal.gif -vsync cfr -pix_fmt bgra -auto_conversion_filters fate-gifenc%: fate-gif-color fate-gifenc%: PIXFMT = $(word 3, $(subst -, ,$(@))) fate-gifenc%: SRC = $(TARGET_SAMPLES)/gif/tc217.gif -fate-gifenc%: CMD = framecrc -i $(SRC) -c:v gif -pix_fmt $(PIXFMT) +fate-gifenc%: CMD = framecrc -i $(SRC) -c:v gif -pix_fmt $(PIXFMT) -sws_flags +accurate_rnd+bitexact -vf scale FATE_GIF_ENC_PIXFMT = rgb8 bgr8 rgb4_byte bgr4_byte gray pal8 FATE_GIF_ENC-$(call ENCDEC, GIF, GIF) = $(FATE_GIF_ENC_PIXFMT:%=fate-gifenc-%) diff -Nru ffmpeg-4.2.2/tests/fate/h264.mak ffmpeg-4.4/tests/fate/h264.mak --- ffmpeg-4.2.2/tests/fate/h264.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/h264.mak 2021-04-08 21:28:40.000000000 +0000 @@ -196,7 +196,8 @@ fate-h264-3386 \ fate-h264-missing-frame \ fate-h264-ref-pic-mod-overflow \ - fate-h264-timecode + fate-h264-timecode \ + fate-h264-encparams FATE_H264-$(call DEMDEC, H264, H264) += $(FATE_H264) FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-crop-to-container @@ -232,7 +233,7 @@ FATE_SAMPLES_FFPROBE += $(FATE_H264_FFPROBE-yes) fate-h264: $(FATE_H264-yes) $(FATE_H264_FFPROBE-yes) -fate-h264-conformance-aud_mw_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/AUD_MW_E.264 +fate-h264-conformance-aud_mw_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/AUD_MW_E.264 #force framerate so that the option is tested, theres no other case that tests it, its not needed at all otherwise here fate-h264-conformance-ba1_ft_c: CMD = framecrc -framerate 19 -i $(TARGET_SAMPLES)/h264-conformance/BA1_FT_C.264 @@ -252,173 +253,173 @@ fate-h264-conformance-caba3_sony_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABA3_Sony_C.jsv fate-h264-conformance-caba3_sva_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABA3_SVA_B.264 fate-h264-conformance-caba3_toshiba_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABA3_TOSHIBA_E.264 -fate-h264-conformance-cabac_mot_fld0_full: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/camp_mot_fld0_full.26l -fate-h264-conformance-cabac_mot_frm0_full: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/camp_mot_frm0_full.26l -fate-h264-conformance-cabac_mot_mbaff0_full: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/camp_mot_mbaff0_full.26l -fate-h264-conformance-cabac_mot_picaff0_full: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/camp_mot_picaff0_full.26l -fate-h264-conformance-cabaci3_sony_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CABACI3_Sony_B.jsv -fate-h264-conformance-cabast3_sony_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CABAST3_Sony_E.jsv -fate-h264-conformance-cabastbr3_sony_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CABASTBR3_Sony_B.jsv -fate-h264-conformance-cabref3_sand_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CABREF3_Sand_D.264 -fate-h264-conformance-cacqp3_sony_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CACQP3_Sony_D.jsv -fate-h264-conformance-cafi1_sva_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAFI1_SVA_C.264 -fate-h264-conformance-cama1_sony_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAMA1_Sony_C.jsv -fate-h264-conformance-cama1_toshiba_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAMA1_TOSHIBA_B.264 -fate-h264-conformance-cama1_vtc_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/cama1_vtc_c.avc -fate-h264-conformance-cama2_vtc_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/cama2_vtc_b.avc -fate-h264-conformance-cama3_sand_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAMA3_Sand_E.264 -fate-h264-conformance-cama3_vtc_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/cama3_vtc_b.avc -fate-h264-conformance-camaci3_sony_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAMACI3_Sony_C.jsv -fate-h264-conformance-camanl1_toshiba_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAMANL1_TOSHIBA_B.264 -fate-h264-conformance-camanl2_toshiba_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAMANL2_TOSHIBA_B.264 -fate-h264-conformance-camanl3_sand_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAMANL3_Sand_E.264 -fate-h264-conformance-camasl3_sony_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAMASL3_Sony_B.jsv -fate-h264-conformance-camp_mot_mbaff_l30: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAMP_MOT_MBAFF_L30.26l -fate-h264-conformance-camp_mot_mbaff_l31: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAMP_MOT_MBAFF_L31.26l -fate-h264-conformance-canl1_sony_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CANL1_Sony_E.jsv -fate-h264-conformance-canl1_sva_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CANL1_SVA_B.264 -fate-h264-conformance-canl1_toshiba_g: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CANL1_TOSHIBA_G.264 -fate-h264-conformance-canl2_sony_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CANL2_Sony_E.jsv -fate-h264-conformance-canl2_sva_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CANL2_SVA_B.264 -fate-h264-conformance-canl3_sony_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CANL3_Sony_C.jsv -fate-h264-conformance-canl3_sva_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CANL3_SVA_B.264 -fate-h264-conformance-canl4_sva_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CANL4_SVA_B.264 -fate-h264-conformance-canlma2_sony_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CANLMA2_Sony_C.jsv -fate-h264-conformance-canlma3_sony_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CANLMA3_Sony_C.jsv -fate-h264-conformance-capa1_toshiba_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAPA1_TOSHIBA_B.264 -fate-h264-conformance-capama3_sand_f: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAPAMA3_Sand_F.264 -fate-h264-conformance-capcm1_sand_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAPCM1_Sand_E.264 -fate-h264-conformance-capcmnl1_sand_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAPCMNL1_Sand_E.264 -fate-h264-conformance-capm3_sony_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAPM3_Sony_D.jsv -fate-h264-conformance-caqp1_sony_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAQP1_Sony_B.jsv -fate-h264-conformance-cavlc_mot_fld0_full_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/cvmp_mot_fld0_full_B.26l -fate-h264-conformance-cavlc_mot_frm0_full_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/cvmp_mot_frm0_full_B.26l -fate-h264-conformance-cavlc_mot_mbaff0_full_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/cvmp_mot_mbaff0_full_B.26l -fate-h264-conformance-cavlc_mot_picaff0_full_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/cvmp_mot_picaff0_full_B.26l -fate-h264-conformance-cawp1_toshiba_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAWP1_TOSHIBA_E.264 -fate-h264-conformance-cawp5_toshiba_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CAWP5_TOSHIBA_E.264 -fate-h264-conformance-ci1_ft_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CI1_FT_B.264 -fate-h264-conformance-ci_mw_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CI_MW_D.264 -fate-h264-conformance-cvbs3_sony_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVBS3_Sony_C.jsv -fate-h264-conformance-cvcanlma2_sony_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVCANLMA2_Sony_C.jsv +fate-h264-conformance-cabac_mot_fld0_full: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/camp_mot_fld0_full.26l +fate-h264-conformance-cabac_mot_frm0_full: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/camp_mot_frm0_full.26l +fate-h264-conformance-cabac_mot_mbaff0_full: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/camp_mot_mbaff0_full.26l +fate-h264-conformance-cabac_mot_picaff0_full: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/camp_mot_picaff0_full.26l +fate-h264-conformance-cabaci3_sony_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABACI3_Sony_B.jsv +fate-h264-conformance-cabast3_sony_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABAST3_Sony_E.jsv +fate-h264-conformance-cabastbr3_sony_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABASTBR3_Sony_B.jsv +fate-h264-conformance-cabref3_sand_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABREF3_Sand_D.264 +fate-h264-conformance-cacqp3_sony_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CACQP3_Sony_D.jsv +fate-h264-conformance-cafi1_sva_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAFI1_SVA_C.264 +fate-h264-conformance-cama1_sony_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAMA1_Sony_C.jsv +fate-h264-conformance-cama1_toshiba_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAMA1_TOSHIBA_B.264 +fate-h264-conformance-cama1_vtc_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/cama1_vtc_c.avc +fate-h264-conformance-cama2_vtc_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/cama2_vtc_b.avc +fate-h264-conformance-cama3_sand_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAMA3_Sand_E.264 +fate-h264-conformance-cama3_vtc_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/cama3_vtc_b.avc +fate-h264-conformance-camaci3_sony_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAMACI3_Sony_C.jsv +fate-h264-conformance-camanl1_toshiba_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAMANL1_TOSHIBA_B.264 +fate-h264-conformance-camanl2_toshiba_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAMANL2_TOSHIBA_B.264 +fate-h264-conformance-camanl3_sand_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAMANL3_Sand_E.264 +fate-h264-conformance-camasl3_sony_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAMASL3_Sony_B.jsv +fate-h264-conformance-camp_mot_mbaff_l30: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAMP_MOT_MBAFF_L30.26l +fate-h264-conformance-camp_mot_mbaff_l31: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAMP_MOT_MBAFF_L31.26l +fate-h264-conformance-canl1_sony_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CANL1_Sony_E.jsv +fate-h264-conformance-canl1_sva_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CANL1_SVA_B.264 +fate-h264-conformance-canl1_toshiba_g: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CANL1_TOSHIBA_G.264 +fate-h264-conformance-canl2_sony_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CANL2_Sony_E.jsv +fate-h264-conformance-canl2_sva_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CANL2_SVA_B.264 +fate-h264-conformance-canl3_sony_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CANL3_Sony_C.jsv +fate-h264-conformance-canl3_sva_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CANL3_SVA_B.264 +fate-h264-conformance-canl4_sva_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CANL4_SVA_B.264 +fate-h264-conformance-canlma2_sony_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CANLMA2_Sony_C.jsv +fate-h264-conformance-canlma3_sony_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CANLMA3_Sony_C.jsv +fate-h264-conformance-capa1_toshiba_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAPA1_TOSHIBA_B.264 +fate-h264-conformance-capama3_sand_f: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAPAMA3_Sand_F.264 +fate-h264-conformance-capcm1_sand_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAPCM1_Sand_E.264 +fate-h264-conformance-capcmnl1_sand_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAPCMNL1_Sand_E.264 +fate-h264-conformance-capm3_sony_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAPM3_Sony_D.jsv +fate-h264-conformance-caqp1_sony_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAQP1_Sony_B.jsv +fate-h264-conformance-cavlc_mot_fld0_full_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/cvmp_mot_fld0_full_B.26l +fate-h264-conformance-cavlc_mot_frm0_full_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/cvmp_mot_frm0_full_B.26l +fate-h264-conformance-cavlc_mot_mbaff0_full_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/cvmp_mot_mbaff0_full_B.26l +fate-h264-conformance-cavlc_mot_picaff0_full_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/cvmp_mot_picaff0_full_B.26l +fate-h264-conformance-cawp1_toshiba_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAWP1_TOSHIBA_E.264 +fate-h264-conformance-cawp5_toshiba_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CAWP5_TOSHIBA_E.264 +fate-h264-conformance-ci1_ft_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CI1_FT_B.264 +fate-h264-conformance-ci_mw_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CI_MW_D.264 +fate-h264-conformance-cvbs3_sony_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVBS3_Sony_C.jsv +fate-h264-conformance-cvcanlma2_sony_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVCANLMA2_Sony_C.jsv fate-h264-conformance-cvfc1_sony_c: CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/h264-conformance/CVFC1_Sony_C.jsv -fate-h264-conformance-cvfi1_sony_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVFI1_Sony_D.jsv -fate-h264-conformance-cvfi1_sva_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVFI1_SVA_C.264 -fate-h264-conformance-cvfi2_sony_h: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVFI2_Sony_H.jsv -fate-h264-conformance-cvfi2_sva_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVFI2_SVA_C.264 -fate-h264-conformance-cvma1_sony_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVMA1_Sony_D.jsv -fate-h264-conformance-cvma1_toshiba_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVMA1_TOSHIBA_B.264 -fate-h264-conformance-cvmanl1_toshiba_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVMANL1_TOSHIBA_B.264 -fate-h264-conformance-cvmanl2_toshiba_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVMANL2_TOSHIBA_B.264 -fate-h264-conformance-cvmapaqp3_sony_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVMAPAQP3_Sony_E.jsv -fate-h264-conformance-cvmaqp2_sony_g: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVMAQP2_Sony_G.jsv -fate-h264-conformance-cvmaqp3_sony_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVMAQP3_Sony_D.jsv -fate-h264-conformance-cvmp_mot_fld_l30_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVMP_MOT_FLD_L30_B.26l -fate-h264-conformance-cvmp_mot_frm_l31_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVMP_MOT_FRM_L31_B.26l -fate-h264-conformance-cvnlfi1_sony_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVNLFI1_Sony_C.jsv -fate-h264-conformance-cvnlfi2_sony_h: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVNLFI2_Sony_H.jsv -fate-h264-conformance-cvpa1_toshiba_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVPA1_TOSHIBA_B.264 -fate-h264-conformance-cvpcmnl1_sva_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVPCMNL1_SVA_C.264 -fate-h264-conformance-cvpcmnl2_sva_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVPCMNL2_SVA_C.264 -fate-h264-conformance-cvwp1_toshiba_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVWP1_TOSHIBA_E.264 -fate-h264-conformance-cvwp2_toshiba_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVWP2_TOSHIBA_E.264 -fate-h264-conformance-cvwp3_toshiba_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVWP3_TOSHIBA_E.264 -fate-h264-conformance-cvwp5_toshiba_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CVWP5_TOSHIBA_E.264 -fate-h264-conformance-fi1_sony_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FI1_Sony_E.jsv -fate-h264-conformance-frext-alphaconformanceg: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/test8b43.264 -fate-h264-conformance-frext-bcrm_freh10: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh10.264 -vsync drop -fate-h264-conformance-frext-brcm_freh11: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh11.264 -vsync drop -fate-h264-conformance-frext-brcm_freh3: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh3.264 -fate-h264-conformance-frext-brcm_freh4: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh4.264 -vsync drop -fate-h264-conformance-frext-brcm_freh5: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh5.264 -fate-h264-conformance-frext-brcm_freh8: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh8.264 -fate-h264-conformance-frext-brcm_freh9: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh9.264 -fate-h264-conformance-frext-freh12_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/Freh12_B.264 -fate-h264-conformance-frext-freh1_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/Freh1_B.264 -fate-h264-conformance-frext-freh2_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/Freh2_B.264 -fate-h264-conformance-frext-freh6: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh6.264 -vsync drop -fate-h264-conformance-frext-freh7_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/Freh7_B.264 -vsync drop -fate-h264-conformance-frext-frext01_jvc_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/FREXT01_JVC_D.264 -fate-h264-conformance-frext-frext02_jvc_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/FREXT02_JVC_C.264 -fate-h264-conformance-frext-frext1_panasonic_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt1_Panasonic.avc -fate-h264-conformance-frext-frext2_panasonic_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt2_Panasonic.avc -vsync 0 -fate-h264-conformance-frext-frext3_panasonic_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt3_Panasonic.avc -fate-h264-conformance-frext-frext4_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt4_Panasonic.avc -fate-h264-conformance-frext-frext_mmco4_sony_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt_MMCO4_Sony_B.264 -fate-h264-conformance-frext-hcaff1_hhi_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HCAFF1_HHI.264 -fate-h264-conformance-frext-hcafr1_hhi_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HCAFR1_HHI.264 -fate-h264-conformance-frext-hcafr2_hhi_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HCAFR2_HHI.264 -fate-h264-conformance-frext-hcafr3_hhi_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HCAFR3_HHI.264 -fate-h264-conformance-frext-hcafr4_hhi_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HCAFR4_HHI.264 -fate-h264-conformance-frext-hcamff1_hhi_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HCAMFF1_HHI.264 -fate-h264-conformance-frext-hi422fr10_sony_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/Hi422FR10_SONY_B.264 -fate-h264-conformance-frext-hi422fr13_sony_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/Hi422FR13_SONY_B.264 -pix_fmt yuv422p10le -fate-h264-conformance-frext-hi422fr1_sony_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/Hi422FR1_SONY_A.jsv -fate-h264-conformance-frext-hi422fr6_sony_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/Hi422FR6_SONY_A.jsv -pix_fmt yuv422p10le -fate-h264-conformance-frext-hpca_brcm_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCA_BRCM_C.264 -fate-h264-conformance-frext-hpcadq_brcm_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCADQ_BRCM_B.264 -fate-h264-conformance-frext-hpcafl_bcrm_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAFL_BRCM_C.264 -vsync drop -fate-h264-conformance-frext-hpcaflnl_bcrm_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAFLNL_BRCM_C.264 -vsync drop -fate-h264-conformance-frext-hpcalq_brcm_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCALQ_BRCM_B.264 -fate-h264-conformance-frext-hpcamapalq_bcrm_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAMAPALQ_BRCM_B.264 -vsync 0 -fate-h264-conformance-frext-hpcamolq_brcm_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAMOLQ_BRCM_B.264 -fate-h264-conformance-frext-hpcanl_brcm_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCANL_BRCM_C.264 -fate-h264-conformance-frext-hpcaq2lq_brcm_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAQ2LQ_BRCM_B.264 -fate-h264-conformance-frext-hpcv_brcm_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCV_BRCM_A.264 -fate-h264-conformance-frext-hpcvfl_bcrm_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCVFL_BRCM_A.264 -vsync drop -fate-h264-conformance-frext-hpcvflnl_bcrm_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCVFLNL_BRCM_A.264 -vsync drop -fate-h264-conformance-frext-hpcvmolq_brcm_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCVMOLQ_BRCM_B.264 -fate-h264-conformance-frext-hpcvnl_brcm_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCVNL_BRCM_A.264 -fate-h264-conformance-frext-pph10i1_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I1_Panasonic_A.264 -pix_fmt yuv420p10le -fate-h264-conformance-frext-pph10i2_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I2_Panasonic_A.264 -pix_fmt yuv420p10le -fate-h264-conformance-frext-pph10i3_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I3_Panasonic_A.264 -pix_fmt yuv420p10le -fate-h264-conformance-frext-pph10i4_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I4_Panasonic_A.264 -pix_fmt yuv420p10le -fate-h264-conformance-frext-pph10i5_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I5_Panasonic_A.264 -pix_fmt yuv420p10le -fate-h264-conformance-frext-pph10i6_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I6_Panasonic_A.264 -pix_fmt yuv420p10le -fate-h264-conformance-frext-pph10i7_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I7_Panasonic_A.264 -pix_fmt yuv420p10le -fate-h264-conformance-frext-pph422i1_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I1_Panasonic_A.264 -pix_fmt yuv422p10le -fate-h264-conformance-frext-pph422i2_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I2_Panasonic_A.264 -pix_fmt yuv422p10le -fate-h264-conformance-frext-pph422i3_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I3_Panasonic_A.264 -pix_fmt yuv422p10le -fate-h264-conformance-frext-pph422i4_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I4_Panasonic_A.264 -pix_fmt yuv422p10le -fate-h264-conformance-frext-pph422i5_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I5_Panasonic_A.264 -pix_fmt yuv422p10le -fate-h264-conformance-frext-pph422i6_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I6_Panasonic_A.264 -pix_fmt yuv422p10le -fate-h264-conformance-frext-pph422i7_panasonic_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I7_Panasonic_A.264 -pix_fmt yuv422p10le -fate-h264-conformance-hcbp2_hhi_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/HCBP2_HHI_A.264 -fate-h264-conformance-hcmp1_hhi_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/HCMP1_HHI_A.264 -fate-h264-conformance-ls_sva_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/LS_SVA_D.264 -fate-h264-conformance-midr_mw_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MIDR_MW_D.264 -fate-h264-conformance-mps_mw_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MPS_MW_A.264 -fate-h264-conformance-mr1_bt_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MR1_BT_A.h264 -fate-h264-conformance-mr1_mw_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MR1_MW_A.264 -fate-h264-conformance-mr2_mw_a: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MR2_MW_A.264 -fate-h264-conformance-mr2_tandberg_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MR2_TANDBERG_E.264 -fate-h264-conformance-mr3_tandberg_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MR3_TANDBERG_B.264 -fate-h264-conformance-mr4_tandberg_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MR4_TANDBERG_C.264 -fate-h264-conformance-mr5_tandberg_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MR5_TANDBERG_C.264 -fate-h264-conformance-mr6_bt_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MR6_BT_B.h264 -fate-h264-conformance-mr7_bt_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MR7_BT_B.h264 -fate-h264-conformance-mr8_bt_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MR8_BT_B.h264 -fate-h264-conformance-mr9_bt_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/MR9_BT_B.h264 -fate-h264-conformance-mv1_brcm_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/src19td.IBP.264 -fate-h264-conformance-nl1_sony_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/NL1_Sony_D.jsv -fate-h264-conformance-nl2_sony_h: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/NL2_Sony_H.jsv -fate-h264-conformance-nl3_sva_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/NL3_SVA_E.264 -fate-h264-conformance-nlmq1_jvc_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/NLMQ1_JVC_C.264 -fate-h264-conformance-nlmq2_jvc_c: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/NLMQ2_JVC_C.264 -fate-h264-conformance-nrf_mw_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/NRF_MW_E.264 -fate-h264-conformance-sharp_mp_field_1_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/Sharp_MP_Field_1_B.jvt -fate-h264-conformance-sharp_mp_field_2_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/Sharp_MP_Field_2_B.jvt -fate-h264-conformance-sharp_mp_field_3_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/Sharp_MP_Field_3_B.jvt -fate-h264-conformance-sharp_mp_paff_1r2: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/Sharp_MP_PAFF_1r2.jvt -fate-h264-conformance-sharp_mp_paff_2r: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/Sharp_MP_PAFF_2.jvt -fate-h264-conformance-sl1_sva_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/SL1_SVA_B.264 -fate-h264-conformance-sva_ba1_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/SVA_BA1_B.264 -fate-h264-conformance-sva_ba2_d: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/SVA_BA2_D.264 -fate-h264-conformance-sva_base_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/SVA_Base_B.264 -fate-h264-conformance-sva_cl1_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/SVA_CL1_E.264 -fate-h264-conformance-sva_fm1_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/SVA_FM1_E.264 -fate-h264-conformance-sva_nl1_b: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/SVA_NL1_B.264 -fate-h264-conformance-sva_nl2_e: CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/SVA_NL2_E.264 +fate-h264-conformance-cvfi1_sony_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVFI1_Sony_D.jsv +fate-h264-conformance-cvfi1_sva_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVFI1_SVA_C.264 +fate-h264-conformance-cvfi2_sony_h: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVFI2_Sony_H.jsv +fate-h264-conformance-cvfi2_sva_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVFI2_SVA_C.264 +fate-h264-conformance-cvma1_sony_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVMA1_Sony_D.jsv +fate-h264-conformance-cvma1_toshiba_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVMA1_TOSHIBA_B.264 +fate-h264-conformance-cvmanl1_toshiba_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVMANL1_TOSHIBA_B.264 +fate-h264-conformance-cvmanl2_toshiba_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVMANL2_TOSHIBA_B.264 +fate-h264-conformance-cvmapaqp3_sony_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVMAPAQP3_Sony_E.jsv +fate-h264-conformance-cvmaqp2_sony_g: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVMAQP2_Sony_G.jsv +fate-h264-conformance-cvmaqp3_sony_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVMAQP3_Sony_D.jsv +fate-h264-conformance-cvmp_mot_fld_l30_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVMP_MOT_FLD_L30_B.26l +fate-h264-conformance-cvmp_mot_frm_l31_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVMP_MOT_FRM_L31_B.26l +fate-h264-conformance-cvnlfi1_sony_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVNLFI1_Sony_C.jsv +fate-h264-conformance-cvnlfi2_sony_h: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVNLFI2_Sony_H.jsv +fate-h264-conformance-cvpa1_toshiba_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVPA1_TOSHIBA_B.264 +fate-h264-conformance-cvpcmnl1_sva_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVPCMNL1_SVA_C.264 +fate-h264-conformance-cvpcmnl2_sva_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVPCMNL2_SVA_C.264 +fate-h264-conformance-cvwp1_toshiba_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVWP1_TOSHIBA_E.264 +fate-h264-conformance-cvwp2_toshiba_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVWP2_TOSHIBA_E.264 +fate-h264-conformance-cvwp3_toshiba_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVWP3_TOSHIBA_E.264 +fate-h264-conformance-cvwp5_toshiba_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CVWP5_TOSHIBA_E.264 +fate-h264-conformance-fi1_sony_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FI1_Sony_E.jsv +fate-h264-conformance-frext-alphaconformanceg: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/test8b43.264 +fate-h264-conformance-frext-bcrm_freh10: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh10.264 +fate-h264-conformance-frext-brcm_freh11: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh11.264 +fate-h264-conformance-frext-brcm_freh3: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh3.264 +fate-h264-conformance-frext-brcm_freh4: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh4.264 +fate-h264-conformance-frext-brcm_freh5: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh5.264 +fate-h264-conformance-frext-brcm_freh8: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh8.264 +fate-h264-conformance-frext-brcm_freh9: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh9.264 +fate-h264-conformance-frext-freh12_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/Freh12_B.264 +fate-h264-conformance-frext-freh1_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/Freh1_B.264 +fate-h264-conformance-frext-freh2_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/Freh2_B.264 +fate-h264-conformance-frext-freh6: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/freh6.264 +fate-h264-conformance-frext-freh7_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/Freh7_B.264 +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-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 +fate-h264-conformance-frext-hcaff1_hhi_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HCAFF1_HHI.264 +fate-h264-conformance-frext-hcafr1_hhi_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HCAFR1_HHI.264 +fate-h264-conformance-frext-hcafr2_hhi_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HCAFR2_HHI.264 +fate-h264-conformance-frext-hcafr3_hhi_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HCAFR3_HHI.264 +fate-h264-conformance-frext-hcafr4_hhi_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HCAFR4_HHI.264 +fate-h264-conformance-frext-hcamff1_hhi_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HCAMFF1_HHI.264 +fate-h264-conformance-frext-hi422fr10_sony_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/Hi422FR10_SONY_B.264 +fate-h264-conformance-frext-hi422fr13_sony_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/Hi422FR13_SONY_B.264 -pix_fmt yuv422p10le -vf scale +fate-h264-conformance-frext-hi422fr1_sony_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/Hi422FR1_SONY_A.jsv +fate-h264-conformance-frext-hi422fr6_sony_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/Hi422FR6_SONY_A.jsv -pix_fmt yuv422p10le -vf scale +fate-h264-conformance-frext-hpca_brcm_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCA_BRCM_C.264 +fate-h264-conformance-frext-hpcadq_brcm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCADQ_BRCM_B.264 +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-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 +fate-h264-conformance-frext-hpcv_brcm_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCV_BRCM_A.264 +fate-h264-conformance-frext-hpcvfl_bcrm_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCVFL_BRCM_A.264 +fate-h264-conformance-frext-hpcvflnl_bcrm_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCVFLNL_BRCM_A.264 +fate-h264-conformance-frext-hpcvmolq_brcm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCVMOLQ_BRCM_B.264 +fate-h264-conformance-frext-hpcvnl_brcm_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCVNL_BRCM_A.264 +fate-h264-conformance-frext-pph10i1_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I1_Panasonic_A.264 -pix_fmt yuv420p10le -vf scale +fate-h264-conformance-frext-pph10i2_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I2_Panasonic_A.264 -pix_fmt yuv420p10le -vf scale +fate-h264-conformance-frext-pph10i3_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I3_Panasonic_A.264 -pix_fmt yuv420p10le -vf scale +fate-h264-conformance-frext-pph10i4_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I4_Panasonic_A.264 -pix_fmt yuv420p10le -vf scale +fate-h264-conformance-frext-pph10i5_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I5_Panasonic_A.264 -pix_fmt yuv420p10le -vf scale +fate-h264-conformance-frext-pph10i6_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I6_Panasonic_A.264 -pix_fmt yuv420p10le -vf scale +fate-h264-conformance-frext-pph10i7_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH10I7_Panasonic_A.264 -pix_fmt yuv420p10le -vf scale +fate-h264-conformance-frext-pph422i1_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I1_Panasonic_A.264 -pix_fmt yuv422p10le -vf scale +fate-h264-conformance-frext-pph422i2_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I2_Panasonic_A.264 -pix_fmt yuv422p10le -vf scale +fate-h264-conformance-frext-pph422i3_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I3_Panasonic_A.264 -pix_fmt yuv422p10le -vf scale +fate-h264-conformance-frext-pph422i4_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I4_Panasonic_A.264 -pix_fmt yuv422p10le -vf scale +fate-h264-conformance-frext-pph422i5_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I5_Panasonic_A.264 -pix_fmt yuv422p10le -vf scale +fate-h264-conformance-frext-pph422i6_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I6_Panasonic_A.264 -pix_fmt yuv422p10le -vf scale +fate-h264-conformance-frext-pph422i7_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/PPH422I7_Panasonic_A.264 -pix_fmt yuv422p10le -vf scale +fate-h264-conformance-hcbp2_hhi_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/HCBP2_HHI_A.264 +fate-h264-conformance-hcmp1_hhi_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/HCMP1_HHI_A.264 +fate-h264-conformance-ls_sva_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/LS_SVA_D.264 +fate-h264-conformance-midr_mw_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MIDR_MW_D.264 +fate-h264-conformance-mps_mw_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MPS_MW_A.264 +fate-h264-conformance-mr1_bt_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MR1_BT_A.h264 +fate-h264-conformance-mr1_mw_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MR1_MW_A.264 +fate-h264-conformance-mr2_mw_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MR2_MW_A.264 +fate-h264-conformance-mr2_tandberg_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MR2_TANDBERG_E.264 +fate-h264-conformance-mr3_tandberg_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MR3_TANDBERG_B.264 +fate-h264-conformance-mr4_tandberg_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MR4_TANDBERG_C.264 +fate-h264-conformance-mr5_tandberg_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MR5_TANDBERG_C.264 +fate-h264-conformance-mr6_bt_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MR6_BT_B.h264 +fate-h264-conformance-mr7_bt_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MR7_BT_B.h264 +fate-h264-conformance-mr8_bt_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MR8_BT_B.h264 +fate-h264-conformance-mr9_bt_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/MR9_BT_B.h264 +fate-h264-conformance-mv1_brcm_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/src19td.IBP.264 +fate-h264-conformance-nl1_sony_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/NL1_Sony_D.jsv +fate-h264-conformance-nl2_sony_h: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/NL2_Sony_H.jsv +fate-h264-conformance-nl3_sva_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/NL3_SVA_E.264 +fate-h264-conformance-nlmq1_jvc_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/NLMQ1_JVC_C.264 +fate-h264-conformance-nlmq2_jvc_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/NLMQ2_JVC_C.264 +fate-h264-conformance-nrf_mw_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/NRF_MW_E.264 +fate-h264-conformance-sharp_mp_field_1_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/Sharp_MP_Field_1_B.jvt +fate-h264-conformance-sharp_mp_field_2_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/Sharp_MP_Field_2_B.jvt +fate-h264-conformance-sharp_mp_field_3_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/Sharp_MP_Field_3_B.jvt +fate-h264-conformance-sharp_mp_paff_1r2: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/Sharp_MP_PAFF_1r2.jvt +fate-h264-conformance-sharp_mp_paff_2r: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/Sharp_MP_PAFF_2.jvt +fate-h264-conformance-sl1_sva_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/SL1_SVA_B.264 +fate-h264-conformance-sva_ba1_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/SVA_BA1_B.264 +fate-h264-conformance-sva_ba2_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/SVA_BA2_D.264 +fate-h264-conformance-sva_base_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/SVA_Base_B.264 +fate-h264-conformance-sva_cl1_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/SVA_CL1_E.264 +fate-h264-conformance-sva_fm1_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/SVA_FM1_E.264 +fate-h264-conformance-sva_nl1_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/SVA_NL1_B.264 +fate-h264-conformance-sva_nl2_e: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/SVA_NL2_E.264 fate-h264-bsf-mp4toannexb: CMD = md5 -i $(TARGET_SAMPLES)/h264/interlaced_crop.mp4 -c:v copy -f h264 @@ -428,12 +429,12 @@ fate-h264-extreme-plane-pred: CMD = framemd5 -i $(TARGET_SAMPLES)/h264/extreme-plane-pred.h264 fate-h264-interlace-crop: CMD = framecrc -i $(TARGET_SAMPLES)/h264/interlaced_crop.mp4 -frames:v 3 fate-h264-brokensps-2580: CMD = framecrc -i $(TARGET_SAMPLES)/h264/brokensps.flv -vf format=yuv420p,scale=w=192:h=144 -sws_flags bitexact+bilinear -fate-h264-xavc-4389: CMD = framecrc -i $(TARGET_SAMPLES)/h264/SonyXAVC_LongGOP_green_pixelation_early_Frames.MXF -pix_fmt yuv422p10le +fate-h264-xavc-4389: CMD = framecrc -i $(TARGET_SAMPLES)/h264/SonyXAVC_LongGOP_green_pixelation_early_Frames.MXF -pix_fmt yuv422p10le -vf scale -af aresample fate-h264-attachment-631: CMD = framecrc -i $(TARGET_SAMPLES)/h264/attachment631-small.mp4 -an -max_error_rate 0.96 -fate-h264-skip-nokey: CMD = framecrc -skip_frame nokey -i $(TARGET_SAMPLES)/h264/h264_intra_first-small.ts -fate-h264-skip-nointra: CMD = framecrc -skip_frame nointra -i $(TARGET_SAMPLES)/h264/h264_intra_first-small.ts +fate-h264-skip-nokey: CMD = framecrc -skip_frame nokey -i $(TARGET_SAMPLES)/h264/h264_intra_first-small.ts -vf scale -af aresample +fate-h264-skip-nointra: CMD = framecrc -skip_frame nointra -i $(TARGET_SAMPLES)/h264/h264_intra_first-small.ts -vf scale -af aresample fate-h264-intra-refresh-recovery: CMD = framecrc -i $(TARGET_SAMPLES)/h264/intra_refresh.h264 -frames:v 10 -fate-h264-invalid-ref-mod: CMD = framecrc -i $(TARGET_SAMPLES)/h264/h264refframeregression.mp4 -an -frames 10 -pix_fmt yuv420p10le +fate-h264-invalid-ref-mod: CMD = framecrc -i $(TARGET_SAMPLES)/h264/h264refframeregression.mp4 -an -frames 10 -pix_fmt yuv420p10le -vf scale fate-h264-lossless: CMD = framecrc -i $(TARGET_SAMPLES)/h264/lossless.h264 fate-h264-mixed-nal-coding: CMD = framecrc -i $(TARGET_SAMPLES)/h264/mixed-nal-coding.mp4 fate-h264-ref-pic-mod-overflow: CMD = framecrc -i $(TARGET_SAMPLES)/h264/ref-pic-mod-overflow.h264 @@ -443,6 +444,9 @@ fate-h264-missing-frame: CMD = framecrc -i $(TARGET_SAMPLES)/h264/nondeterministic_cut.h264 fate-h264-timecode: CMD = framecrc -i $(TARGET_SAMPLES)/h264/crew_cif_timecode-2.h264 -fate-h264-reinit-%: CMD = framecrc -i $(TARGET_SAMPLES)/h264/$(@:fate-h264-%=%).h264 -vf format=yuv444p10le,scale=w=352:h=288 +fate-h264-reinit-%: CMD = framecrc -i $(TARGET_SAMPLES)/h264/$(@:fate-h264-%=%).h264 -vf scale,format=yuv444p10le,scale=w=352:h=288 fate-h264-dts_5frames: CMD = probeframes $(TARGET_SAMPLES)/h264/dts_5frames.mkv + +fate-h264-encparams: CMD = venc_data $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt_MMCO4_Sony_B.264 0 1 +FATE_SAMPLES_DUMP_DATA += fate-h264-encparams diff -Nru ffmpeg-4.2.2/tests/fate/hevc.mak ffmpeg-4.4/tests/fate/hevc.mak --- ffmpeg-4.2.2/tests/fate/hevc.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/hevc.mak 2021-04-08 21:28:40.000000000 +0000 @@ -160,6 +160,8 @@ HEVC_SAMPLES_422_10BIN = \ Main_422_10_A_RExt_Sony_1 \ + +HEVC_SAMPLES_422_10BIN_LARGE = \ Main_422_10_B_RExt_Sony_1 \ HEVC_SAMPLES_444_8BIT = \ @@ -169,6 +171,8 @@ IPCM_B_RExt_NEC \ PERSIST_RPARAM_A_RExt_Sony_1\ PERSIST_RPARAM_A_RExt_Sony_3\ + +HEVC_SAMPLES_444_12BIT_LARGE = \ SAO_A_RExt_MediaTek_1 \ @@ -188,22 +192,27 @@ define FATE_HEVC_TEST FATE_HEVC += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -vsync drop -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv420p +fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv420p endef define FATE_HEVC_TEST_10BIT FATE_HEVC += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv420p10le +fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv420p10le -vf scale endef define FATE_HEVC_TEST_422_10BIT FATE_HEVC += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv422p10le +fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv422p10le -vf scale endef define FATE_HEVC_TEST_422_10BIN FATE_HEVC += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bin -pix_fmt yuv422p10le +fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bin -pix_fmt yuv422p10le -vf scale +endef + +define FATE_HEVC_TEST_422_10BIN_LARGE +FATE_HEVC_LARGE += fate-hevc-conformance-$(1) +fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bin -pix_fmt yuv422p10le -vf scale endef define FATE_HEVC_TEST_444_8BIT @@ -213,21 +222,25 @@ define FATE_HEVC_TEST_444_12BIT FATE_HEVC += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv444p12le +fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv444p12le -vf scale +endef + +define FATE_HEVC_TEST_444_12BIT_LARGE +FATE_HEVC_LARGE += fate-hevc-conformance-$(1) +fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv444p12le -vf scale endef $(foreach N,$(HEVC_SAMPLES),$(eval $(call FATE_HEVC_TEST,$(N)))) $(foreach N,$(HEVC_SAMPLES_10BIT),$(eval $(call FATE_HEVC_TEST_10BIT,$(N)))) $(foreach N,$(HEVC_SAMPLES_422_10BIT),$(eval $(call FATE_HEVC_TEST_422_10BIT,$(N)))) $(foreach N,$(HEVC_SAMPLES_422_10BIN),$(eval $(call FATE_HEVC_TEST_422_10BIN,$(N)))) +$(foreach N,$(HEVC_SAMPLES_422_10BIN_LARGE),$(eval $(call FATE_HEVC_TEST_422_10BIN_LARGE,$(N)))) $(foreach N,$(HEVC_SAMPLES_444_8BIT),$(eval $(call FATE_HEVC_TEST_444_8BIT,$(N)))) $(foreach N,$(HEVC_SAMPLES_444_12BIT),$(eval $(call FATE_HEVC_TEST_444_12BIT,$(N)))) +$(foreach N,$(HEVC_SAMPLES_444_12BIT_LARGE),$(eval $(call FATE_HEVC_TEST_444_12BIT_LARGE,$(N)))) fate-hevc-paramchange-yuv420p-yuv420p10: CMD = framecrc -vsync 0 -i $(TARGET_SAMPLES)/hevc/paramchange_yuv420p_yuv420p10.hevc -sws_flags area+accurate_rnd+bitexact -FATE_HEVC += fate-hevc-paramchange-yuv420p-yuv420p10 - -fate-hevc-paired-fields: CMD = probeframes -show_entries frame=interlaced_frame,top_field_first $(TARGET_SAMPLES)/hevc/paired_fields.hevc -FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-paired-fields +FATE_HEVC_LARGE += fate-hevc-paramchange-yuv420p-yuv420p10 tests/data/hevc-mp4.mov: TAG = GEN tests/data/hevc-mp4.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data @@ -244,18 +257,31 @@ FATE_HEVC += fate-hevc-skiploopfilter FATE_HEVC-$(call DEMDEC, HEVC, HEVC) += $(FATE_HEVC) +FATE_HEVC-$(call ALLYES, HEVC_DEMUXER HEVC_DECODER LARGE_TESTS) += $(FATE_HEVC_LARGE) # this sample has two stsd entries and needs to reload extradata FATE_HEVC-$(call DEMDEC, MOV, HEVC) += fate-hevc-extradata-reload fate-hevc-extradata-reload: CMD = framemd5 -i $(TARGET_SAMPLES)/hevc/extradata-reload-multi-stsd.mov -sws_flags bitexact +fate-hevc-paired-fields: CMD = probeframes -show_entries frame=interlaced_frame,top_field_first $(TARGET_SAMPLES)/hevc/paired_fields.hevc +FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-paired-fields + fate-hevc-monochrome-crop: CMD = probeframes -show_entries frame=width,height:stream=width,height $(TARGET_SAMPLES)/hevc/hevc-monochrome.hevc FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-monochrome-crop +fate-hevc-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-two-first-slice: CMD = threads=2 framemd5 -i $(TARGET_SAMPLES)/hevc/two_first_slice.mp4 -sws_flags bitexact -t 00:02.00 -an FATE_HEVC-$(call DEMDEC, MOV, HEVC) += fate-hevc-two-first-slice +fate-hevc-cabac-tudepth: CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc/cbf_cr_cb_TUDepth_4_circle.h265 -pix_fmt yuv444p +FATE_HEVC-$(call DEMDEC, HEVC, HEVC) += fate-hevc-cabac-tudepth + +fate-hevc-small422chroma: CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc/food.hevc -pix_fmt yuv422p10le -vf scale +FATE_HEVC-$(call DEMDEC, HEVC, HEVC) += fate-hevc-small422chroma + FATE_SAMPLES_AVCONV += $(FATE_HEVC-yes) FATE_SAMPLES_FFPROBE += $(FATE_HEVC_FFPROBE-yes) diff -Nru ffmpeg-4.2.2/tests/fate/hlsenc.mak ffmpeg-4.4/tests/fate/hlsenc.mak --- ffmpeg-4.2.2/tests/fate/hlsenc.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/hlsenc.mak 2021-04-08 21:28:40.000000000 +0000 @@ -5,7 +5,7 @@ -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 -FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-live-no-endlist +FATE_HLSENC-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-live-no-endlist fate-hls-live-no-endlist: tests/data/live_no_endlist.m3u8 fate-hls-live-no-endlist: SRC = $(TARGET_PATH)/tests/data/live_no_endlist.m3u8 fate-hls-live-no-endlist: CMD = md5 -i $(SRC) -af hdcd=process_stereo=false -t 6 -f s24le @@ -19,7 +19,7 @@ -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 -FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-live-last-endlist +FATE_HLSENC-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-live-last-endlist fate-hls-live-last-endlist: tests/data/live_last_endlist.m3u8 fate-hls-live-last-endlist: SRC = $(TARGET_PATH)/tests/data/live_last_endlist.m3u8 fate-hls-live-last-endlist: CMD = md5 -i $(SRC) -af hdcd=process_stereo=false -t 6 -f s24le @@ -34,7 +34,7 @@ -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 -FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-live-endlist +FATE_HLSENC-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-live-endlist fate-hls-live-endlist: tests/data/live_endlist.m3u8 fate-hls-live-endlist: SRC = $(TARGET_PATH)/tests/data/live_endlist.m3u8 fate-hls-live-endlist: CMD = md5 -i $(SRC) -af hdcd=process_stereo=false -t 20 -f s24le @@ -48,9 +48,20 @@ -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 -FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-segment-size +FATE_HLSENC-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-segment-size fate-hls-segment-size: tests/data/hls_segment_size.m3u8 -fate-hls-segment-size: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hls_segment_size.m3u8 -vf setpts=N*23 +fate-hls-segment-size: CMD = framecrc -auto_conversion_filters -flags +bitexact -i $(TARGET_PATH)/tests/data/hls_segment_size.m3u8 -vf setpts=N*23 + +tests/data/hls_segment_single.m3u8: TAG = GEN +tests/data/hls_segment_single.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -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 + +FATE_HLSENC-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-segment-single +fate-hls-segment-single: tests/data/hls_segment_single.m3u8 +fate-hls-segment-single: CMD = framecrc -auto_conversion_filters -flags +bitexact -i $(TARGET_PATH)/tests/data/hls_segment_single.m3u8 -vf setpts=N*23 tests/data/hls_init_time.m3u8: TAG = GEN tests/data/hls_init_time.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data @@ -59,9 +70,9 @@ -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 -FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-init-time +FATE_HLSENC-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-init-time fate-hls-init-time: tests/data/hls_init_time.m3u8 -fate-hls-init-time: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hls_init_time.m3u8 -vf setpts=N*23 +fate-hls-init-time: CMD = framecrc -auto_conversion_filters -flags +bitexact -i $(TARGET_PATH)/tests/data/hls_init_time.m3u8 -vf setpts=N*23 tests/data/hls_list_size.m3u8: TAG = GEN tests/data/hls_list_size.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data @@ -70,19 +81,34 @@ -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 -FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-list-size +FATE_HLSENC-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-list-size fate-hls-list-size: tests/data/hls_list_size.m3u8 -fate-hls-list-size: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hls_list_size.m3u8 -vf setpts=N*23 +fate-hls-list-size: CMD = framecrc -auto_conversion_filters -flags +bitexact -i $(TARGET_PATH)/tests/data/hls_list_size.m3u8 -vf setpts=N*23 -tests/data/hls_segment_type_fmp4.m3u8: TAG = GEN -tests/data/hls_segment_type_fmp4.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data +tests/data/hls_fmp4.m3u8: TAG = GEN +tests/data/hls_fmp4.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ -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" \ $(TARGET_PATH)/tests/data/hls_fmp4.m3u8 2>/dev/null -FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-fmp4 -fate-hls-fmp4: tests/data/hls_segment_type_fmp4.m3u8 -fate-hls-fmp4: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hls_fmp4.m3u8 -vf setpts=N*23 - +FATE_HLSENC-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-hls-fmp4 +fate-hls-fmp4: tests/data/hls_fmp4.m3u8 +fate-hls-fmp4: CMD = framecrc -auto_conversion_filters -flags +bitexact -i $(TARGET_PATH)/tests/data/hls_fmp4.m3u8 -vf setpts=N*23 + +tests/data/hls_fmp4_ac3.m3u8: TAG = GEN +tests/data/hls_fmp4_ac3.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + -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" \ + $(TARGET_PATH)/tests/data/hls_fmp4_ac3.m3u8 2>/dev/null + +FATE_HLSENC_PROBE-$(call ALLYES, HLS_DEMUXER EAC3_DEMUXER) += fate-hls-fmp4_ac3 +fate-hls-fmp4_ac3: tests/data/hls_fmp4_ac3.m3u8 +fate-hls-fmp4_ac3: CMD = probeaudiostream $(TARGET_PATH)/tests/data/now_ac3.mp4 + +FATE_SAMPLES_FFMPEG += $(FATE_HLSENC-yes) +FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_HLSENC_PROBE-yes) +fate-hlsenc: $(FATE_HLSENC-yes) $(FATE_HLSENC_PROBE-yes) diff -Nru ffmpeg-4.2.2/tests/fate/image.mak ffmpeg-4.4/tests/fate/image.mak --- ffmpeg-4.2.2/tests/fate/image.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/image.mak 2021-04-08 21:28:40.000000000 +0000 @@ -15,10 +15,10 @@ fate-brenderpix-565: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/maximafront.pix FATE_BRENDERPIX += fate-brenderpix-defpal -fate-brenderpix-defpal: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/rivrock1.pix -pix_fmt rgb24 +fate-brenderpix-defpal: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/rivrock1.pix -pix_fmt rgb24 -vf scale FATE_BRENDERPIX += fate-brenderpix-intpal -fate-brenderpix-intpal: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/testtex.pix -pix_fmt rgb24 +fate-brenderpix-intpal: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/testtex.pix -pix_fmt rgb24 -vf scale FATE_BRENDERPIX += fate-brenderpix-y400a fate-brenderpix-y400a: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/gears.pix @@ -28,11 +28,11 @@ fate-brenderpix: $(FATE_BRENDERPIX-yes) FATE_IMAGE-$(call PARSERDEMDEC, BMP, IMAGE2PIPE, BMP) += fate-bmpparser -fate-bmpparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/bmp/numbers.bmp -pix_fmt rgb24 +fate-bmpparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/bmp/numbers.bmp -pix_fmt rgb24 -vf scale define FATE_IMGSUITE_DDS FATE_DDS += fate-dds-$(1) -fate-dds-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/dds/fate_$(1).dds $(DDS_OPTS_$(1)) +fate-dds-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/dds/fate_$(1).dds $(DDS_OPTS_$(1)) -vf scale endef DDS_OPTS_pal = -sws_flags +accurate_rnd+bitexact -pix_fmt rgba @@ -97,155 +97,158 @@ FATE_SAMPLES_AVCONV-$(call PARSERDEMDEC, DPX, IMAGE2PIPE, DPX) += fate-dpxparser fate-dpxparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/dpx/lena_4x_concat.dpx -sws_flags +accurate_rnd+bitexact +FATE_IMAGE_PROBE-$(call DEMDEC, IMAGE2, DPX) += fate-dpx-probe +fate-dpx-probe: CMD = probeframes -show_entries frame=color_transfer,color_range,color_space,color_primaries,sample_aspect_ratio $(TARGET_SAMPLES)/dpx/cyan.dpx + FATE_EXR += fate-exr-slice-raw -fate-exr-slice-raw: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_slice_raw.exr -pix_fmt rgba64le +fate-exr-slice-raw: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_slice_raw.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-slice-rle -fate-exr-slice-rle: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_slice_rle.exr -pix_fmt rgba64le +fate-exr-slice-rle: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_slice_rle.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-slice-zip1 -fate-exr-slice-zip1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_slice_zip1.exr -pix_fmt rgba64le +fate-exr-slice-zip1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_slice_zip1.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-slice-zip16 -fate-exr-slice-zip16: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_slice_zip16.exr -pix_fmt rgba64le +fate-exr-slice-zip16: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_slice_zip16.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-slice-pxr24 -fate-exr-slice-pxr24: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_slice_pxr24.exr -pix_fmt rgb48le +fate-exr-slice-pxr24: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_slice_pxr24.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-pxr24-float-12x8 -fate-exr-rgb-scanline-pxr24-float-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_float_12x8.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-pxr24-float-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_float_12x8.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgba-multiscanline-half-b44 -fate-exr-rgba-multiscanline-half-b44: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_multiscanline_half_b44.exr -pix_fmt rgba64le +fate-exr-rgba-multiscanline-half-b44: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_multiscanline_half_b44.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-scanline-float-b44 -fate-exr-rgb-scanline-float-b44: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_float_b44.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-float-b44: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_float_b44.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-half-b44-12x8 -fate-exr-rgb-scanline-half-b44-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_b44_12x8.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-half-b44-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_b44_12x8.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-half-b44-13x9 -fate-exr-rgb-scanline-half-b44-13x9: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_b44_13x9.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-half-b44-13x9: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_b44_13x9.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-tile-float-raw-12x8 -fate-exr-rgb-tile-float-raw-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_float_raw_12x8.exr -pix_fmt rgb48le +fate-exr-rgb-tile-float-raw-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_float_raw_12x8.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-tile-float-raw-150x130 -fate-exr-rgb-tile-float-raw-150x130: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_float_raw_150x130.exr -pix_fmt rgb48le +fate-exr-rgb-tile-float-raw-150x130: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_float_raw_150x130.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-tile-half-raw-12x8 -fate-exr-rgb-tile-half-raw-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_half_raw_12x8.exr -pix_fmt rgb48le +fate-exr-rgb-tile-half-raw-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_half_raw_12x8.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgba-scanline-float-half-b44-13x9-l1 -fate-exr-rgba-scanline-float-half-b44-13x9-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44_13x9.exr -pix_fmt rgba64le +fate-exr-rgba-scanline-float-half-b44-13x9-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44_13x9.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgba-scanline-float-half-b44-13x9-l2 -fate-exr-rgba-scanline-float-half-b44-13x9-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44_13x9.exr -pix_fmt rgba64le +fate-exr-rgba-scanline-float-half-b44-13x9-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44_13x9.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgba-scanline-float-half-b44-12x8-l1 -fate-exr-rgba-scanline-float-half-b44-12x8-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44_12x8.exr -pix_fmt rgba64le +fate-exr-rgba-scanline-float-half-b44-12x8-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44_12x8.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgba-scanline-float-half-b44-12x8-l2 -fate-exr-rgba-scanline-float-half-b44-12x8-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44_12x8.exr -pix_fmt rgba64le +fate-exr-rgba-scanline-float-half-b44-12x8-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44_12x8.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgba-scanline-float-half-b44a-12x8-l1 -fate-exr-rgba-scanline-float-half-b44a-12x8-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44a_12x8.exr -pix_fmt rgba64le +fate-exr-rgba-scanline-float-half-b44a-12x8-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44a_12x8.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgba-scanline-float-half-b44a-12x8-l2 -fate-exr-rgba-scanline-float-half-b44a-12x8-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44a_12x8.exr -pix_fmt rgba64le +fate-exr-rgba-scanline-float-half-b44a-12x8-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44a_12x8.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgba-scanline-float-half-b44a-13x9-l1 -fate-exr-rgba-scanline-float-half-b44a-13x9-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44a_13x9.exr -pix_fmt rgba64le +fate-exr-rgba-scanline-float-half-b44a-13x9-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44a_13x9.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgba-scanline-float-half-b44a-13x9-l2 -fate-exr-rgba-scanline-float-half-b44a-13x9-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44a_13x9.exr -pix_fmt rgba64le +fate-exr-rgba-scanline-float-half-b44a-13x9-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgba_scanline_float_half_b44a_13x9.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-tile-pxr24-float-half-l1 -fate-exr-rgb-tile-pxr24-float-half-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_pxr24_float_half.exr -pix_fmt rgb48le +fate-exr-rgb-tile-pxr24-float-half-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_pxr24_float_half.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-tile-pxr24-float-half-l2 -fate-exr-rgb-tile-pxr24-float-half-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_pxr24_float_half.exr -pix_fmt rgba64le +fate-exr-rgb-tile-pxr24-float-half-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_pxr24_float_half.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-tile-pxr24-half-float-l1 -fate-exr-rgb-tile-pxr24-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_pxr24_half_float.exr -pix_fmt rgb48le +fate-exr-rgb-tile-pxr24-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_pxr24_half_float.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-tile-pxr24-half-float-l2 -fate-exr-rgb-tile-pxr24-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_pxr24_half_float.exr -pix_fmt rgba64le +fate-exr-rgb-tile-pxr24-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_pxr24_half_float.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-tile-half-float-b44-12x8-l1 -fate-exr-rgb-tile-half-float-b44-12x8-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_half_float_b44_12x8.exr -pix_fmt rgb48le +fate-exr-rgb-tile-half-float-b44-12x8-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_half_float_b44_12x8.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-tile-half-float-b44-12x8-l2 -fate-exr-rgb-tile-half-float-b44-12x8-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_half_float_b44_12x8.exr -pix_fmt rgba64le +fate-exr-rgb-tile-half-float-b44-12x8-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_half_float_b44_12x8.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-tile-zip-half-float-l1 -fate-exr-rgb-tile-zip-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_zip_half_float.exr -pix_fmt rgb48le +fate-exr-rgb-tile-zip-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_zip_half_float.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-tile-zip-half-float-l2 -fate-exr-rgb-tile-zip-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_zip_half_float.exr -pix_fmt rgba64le +fate-exr-rgb-tile-zip-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_zip_half_float.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-tile-zip1-half-float-l1 -fate-exr-rgb-tile-zip1-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_zip1_half_float.exr -pix_fmt rgb48le +fate-exr-rgb-tile-zip1-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_zip1_half_float.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-tile-zip1-half-float-l2 -fate-exr-rgb-tile-zip1-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_zip1_half_float.exr -pix_fmt rgba64le +fate-exr-rgb-tile-zip1-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_zip1_half_float.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-tile-rle-half-float-l1 -fate-exr-rgb-tile-rle-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_rle_half_float.exr -pix_fmt rgb48le +fate-exr-rgb-tile-rle-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_rle_half_float.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-tile-rle-half-float-l2 -fate-exr-rgb-tile-rle-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_rle_half_float.exr -pix_fmt rgba64le +fate-exr-rgb-tile-rle-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_rle_half_float.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-tile-raw-half-float-l1 -fate-exr-rgb-tile-raw-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_raw_half_float.exr -pix_fmt rgb48le +fate-exr-rgb-tile-raw-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_raw_half_float.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-tile-raw-half-float-l2 -fate-exr-rgb-tile-raw-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_raw_half_float.exr -pix_fmt rgba64le +fate-exr-rgb-tile-raw-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_tile_raw_half_float.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-scanline-b44-half-float-12x8-l1 -fate-exr-rgb-scanline-b44-half-float-12x8-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_b44_half_float_12x8.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-b44-half-float-12x8-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_b44_half_float_12x8.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-b44-half-float-12x8-l2 -fate-exr-rgb-scanline-b44-half-float-12x8-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_b44_half_float_12x8.exr -pix_fmt rgba64le +fate-exr-rgb-scanline-b44-half-float-12x8-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_b44_half_float_12x8.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-scanline-pxr24-half-float-l1 -fate-exr-rgb-scanline-pxr24-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_half_float.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-pxr24-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_half_float.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-pxr24-half-float-l2 -fate-exr-rgb-scanline-pxr24-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_half_float.exr -pix_fmt rgba64le +fate-exr-rgb-scanline-pxr24-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_half_float.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-scanline-pxr24-float-half-l1 -fate-exr-rgb-scanline-pxr24-float-half-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_float_half.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-pxr24-float-half-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_float_half.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-pxr24-float-half-l2 -fate-exr-rgb-scanline-pxr24-float-half-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_float_half.exr -pix_fmt rgba64le +fate-exr-rgb-scanline-pxr24-float-half-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_float_half.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-scanline-pxr24-half-uint32-13x9 -fate-exr-rgb-scanline-pxr24-half-uint32-13x9: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_half_uint32_13x9.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-pxr24-half-uint32-13x9: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_half_uint32_13x9.exr -pix_fmt rgb48le -vf scale FATE_EXR += fate-exr-rgb-scanline-zip-half-float-l1 -fate-exr-rgb-scanline-zip-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_zip_half_float.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-zip-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_zip_half_float.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-zip-half-float-l2 -fate-exr-rgb-scanline-zip-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_zip_half_float.exr -pix_fmt rgba64le +fate-exr-rgb-scanline-zip-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_zip_half_float.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-scanline-zip1-half-float-l1 -fate-exr-rgb-scanline-zip1-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_zip1_half_float.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-zip1-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_zip1_half_float.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-zip1-half-float-l2 -fate-exr-rgb-scanline-zip1-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_zip1_half_float.exr -pix_fmt rgba64le +fate-exr-rgb-scanline-zip1-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_zip1_half_float.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-scanline-rle-half-float-l1 -fate-exr-rgb-scanline-rle-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_rle_half_float.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-rle-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_rle_half_float.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-rle-half-float-l2 -fate-exr-rgb-scanline-rle-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_rle_half_float.exr -pix_fmt rgba64le +fate-exr-rgb-scanline-rle-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_rle_half_float.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-scanline-raw-half-float-l1 -fate-exr-rgb-scanline-raw-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_raw_half_float.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-raw-half-float-l1: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_raw_half_float.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-raw-half-float-l2 -fate-exr-rgb-scanline-raw-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_raw_half_float.exr -pix_fmt rgba64le +fate-exr-rgb-scanline-raw-half-float-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_raw_half_float.exr -pix_fmt gbrapf32le FATE_EXR += fate-exr-rgb-scanline-b44-uint32 fate-exr-rgb-scanline-b44-uint32: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_b44_uint32.exr -pix_fmt rgb48le @@ -254,38 +257,71 @@ fate-exr-rgb-scanline-pxr24-uint32: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_uint32.exr -pix_fmt rgb48le FATE_EXR += fate-exr-rgb-scanline-zip1-half-float-l1-zero-offsets -fate-exr-rgb-scanline-zip1-half-float-l1-zero-offsets: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_zip1_half_float_zero_offsets.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-zip1-half-float-l1-zero-offsets: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_zip1_half_float_zero_offsets.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-half-piz-bw -fate-exr-rgb-scanline-half-piz-bw: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_piz_bw.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-half-piz-bw: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_piz_bw.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-half-piz-color -fate-exr-rgb-scanline-half-piz-color: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_piz_color.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-half-piz-color: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_piz_color.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-half-piz-dw-t01 -fate-exr-rgb-scanline-half-piz-dw-t01: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_piz_dw_t01.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-half-piz-dw-t01: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_piz_dw_t01.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-float-piz-48x32 -fate-exr-rgb-scanline-float-piz-48x32: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_float_piz_48x32.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-float-piz-48x32: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_float_piz_48x32.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-scanline-none-negative-red -fate-exr-rgb-scanline-none-negative-red: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_none_negative_red.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-none-negative-red: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_none_negative_red.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgb-b44a-half-negative-4x4 -fate-exr-rgb-b44a-half-negative-4x4: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_b44a_half_negative_4x4.exr -pix_fmt rgb48le +fate-exr-rgb-b44a-half-negative-4x4: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_b44a_half_negative_4x4.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-y-tile-zip-half-12x8 -fate-exr-y-tile-zip-half-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/y_tile_zip_half_12x8.exr -pix_fmt gray16le +fate-exr-y-tile-zip-half-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/y_tile_zip_half_12x8.exr -pix_fmt grayf32le FATE_EXR += fate-exr-y-scanline-zip-half-12x8 -fate-exr-y-scanline-zip-half-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/y_scanline_zip_half_12x8.exr -pix_fmt gray16le +fate-exr-y-scanline-zip-half-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/y_scanline_zip_half_12x8.exr -pix_fmt grayf32le FATE_EXR += fate-exr-rgb-scanline-half-piz-dw-t08 -fate-exr-rgb-scanline-half-piz-dw-t08: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_piz_dw_t08.exr -pix_fmt rgb48le +fate-exr-rgb-scanline-half-piz-dw-t08: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_piz_dw_t08.exr -pix_fmt gbrpf32le FATE_EXR += fate-exr-rgba-zip16-16x32-flag4 -fate-exr-rgba-zip16-16x32-flag4: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_zip16_16x32_flag4.exr -pix_fmt rgba64le +fate-exr-rgba-zip16-16x32-flag4: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_zip16_16x32_flag4.exr -pix_fmt gbrapf32le + +FATE_EXR += fate-exr-ya-scanline-zip-half-12x8 +fate-exr-ya-scanline-zip-half-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/ya_scanline_zip_half_12x8.exr -pix_fmt gbrapf32le + +FATE_EXR += fate-exr-rgb-tile-half-zip +fate-exr-rgb-tile-half-zip: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_half_zip.exr -pix_fmt gbrpf32le + +FATE_EXR += fate-exr-rgb-scanline-float-zip-dw-large +fate-exr-rgb-scanline-float-zip-dw-large: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_float_zip_dw_large.exr -pix_fmt gbrpf32le + +FATE_EXR += fate-exr-rgb-scanline-half-piz-dw-large +fate-exr-rgb-scanline-half-piz-dw-large: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_piz_dw_large.exr -pix_fmt gbrpf32le + +FATE_EXR += fate-exr-rgb-scanline-half-zip-dw-large +fate-exr-rgb-scanline-half-zip-dw-large: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_zip_dw_large.exr -pix_fmt gbrpf32le + +FATE_EXR += fate-exr-rgb-scanline-uint32-piz-dw-large +fate-exr-rgb-scanline-uint32-piz-dw-large: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_uint32_piz_dw_large.exr -pix_fmt rgb48le + +FATE_EXR += fate-exr-rgb-tile-half-piz-dw-large +fate-exr-rgb-tile-half-piz-dw-large: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_half_piz_dw_large.exr -pix_fmt gbrpf32le + +FATE_EXR += fate-exr-rgb-tile-uint32-piz-dw-large +fate-exr-rgb-tile-uint32-piz-dw-large: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_uint32_piz_dw_large.exr -pix_fmt rgb48le + +FATE_EXR += fate-exr-rgb-scanline-half-zip-dw-outside +fate-exr-rgb-scanline-half-zip-dw-outside: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_zip_dw_outside.exr -pix_fmt gbrpf32le + +FATE_EXR += fate-exr-rgb-tile-half-zip-dw-outside +fate-exr-rgb-tile-half-zip-dw-outside: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_half_zip_dw_outside.exr -pix_fmt gbrpf32le + +FATE_EXR += fate-exr-rgb-scanline-zip-half-0x0-0xFFFF +fate-exr-rgb-scanline-zip-half-0x0-0xFFFF: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_zip_half_float_0x0_to_0xFFFF.exr -pix_fmt gbrpf32le FATE_EXR-$(call DEMDEC, IMAGE2, EXR) += $(FATE_EXR) @@ -293,7 +329,7 @@ fate-exr: $(FATE_EXR-yes) FATE_JPG += fate-jpg-12bpp -fate-jpg-12bpp: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/12bpp.jpg -f rawvideo -pix_fmt gray16le -vf setsar=sar=sar +fate-jpg-12bpp: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/12bpp.jpg -f rawvideo -pix_fmt gray16le -vf setsar=sar=sar,scale FATE_JPG += fate-jpg-jfif fate-jpg-jfif: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/20242.jpg @@ -306,32 +342,32 @@ fate-pict: CMD = framecrc -i $(TARGET_SAMPLES)/quickdraw/TRU256.PCT -pix_fmt rgb24 FATE_IMAGE-$(call DEMDEC, IMAGE2, PICTOR) += fate-pictor -fate-pictor: CMD = framecrc -i $(TARGET_SAMPLES)/pictor/MFISH.PIC -pix_fmt rgb24 +fate-pictor: CMD = framecrc -i $(TARGET_SAMPLES)/pictor/MFISH.PIC -pix_fmt rgb24 -vf scale FATE_IMAGE-$(call PARSERDEMDEC, PNG, IMAGE2PIPE, PNG) += fate-pngparser fate-pngparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/png1/feed_4x_concat.png -pix_fmt rgba define FATE_IMGSUITE_PNG FATE_PNG += fate-png-$(1) -fate-png-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/png1/lena-$(1).png -sws_flags +accurate_rnd+bitexact -pix_fmt rgb24 +fate-png-$(1): CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/png1/lena-$(1).png -sws_flags +accurate_rnd+bitexact -pix_fmt rgb24 endef PNG_COLORSPACES = gray8 gray16 rgb24 rgb48 rgba rgba64 ya8 ya16 $(foreach CLSP,$(PNG_COLORSPACES),$(eval $(call FATE_IMGSUITE_PNG,$(CLSP)))) FATE_PNG += fate-png-int-rgb24 -fate-png-int-rgb24: CMD = framecrc -i $(TARGET_SAMPLES)/png1/lena-int_rgb24.png -sws_flags +accurate_rnd+bitexact -pix_fmt rgb24 +fate-png-int-rgb24: CMD = framecrc -i $(TARGET_SAMPLES)/png1/lena-int_rgb24.png -sws_flags +accurate_rnd+bitexact FATE_PNG-$(call DEMDEC, IMAGE2, PNG) += $(FATE_PNG) FATE_IMAGE += $(FATE_PNG-yes) fate-png: $(FATE_PNG-yes) FATE_IMAGE-$(call DEMDEC, IMAGE2, PTX) += fate-ptx -fate-ptx: CMD = framecrc -i $(TARGET_SAMPLES)/ptx/_113kw_pic.ptx -pix_fmt rgb24 +fate-ptx: CMD = framecrc -i $(TARGET_SAMPLES)/ptx/_113kw_pic.ptx -pix_fmt rgb24 -vf scale define FATE_IMGSUITE_PSD FATE_PSD += fate-psd-$(1) -fate-psd-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/psd/lena-$(1).psd -sws_flags +accurate_rnd+bitexact -pix_fmt rgb24 +fate-psd-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/psd/lena-$(1).psd -sws_flags +accurate_rnd+bitexact -pix_fmt rgb24 -vf scale endef PSD_COLORSPACES = gray8 gray16 rgb24 rgb48 rgba rgba64 ya8 ya16 @@ -383,13 +419,13 @@ fate-sunraster-1bit-rle: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-1bit-rle.sun FATE_SUNRASTER += fate-sunraster-8bit-raw -fate-sunraster-8bit-raw: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-8bit-raw.sun -pix_fmt rgb24 +fate-sunraster-8bit-raw: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-8bit-raw.sun -pix_fmt rgb24 -vf scale FATE_SUNRASTER += fate-sunraster-8bit_gray-raw fate-sunraster-8bit_gray-raw: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/gray.ras FATE_SUNRASTER += fate-sunraster-8bit-rle -fate-sunraster-8bit-rle: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-8bit-rle.sun -pix_fmt rgb24 +fate-sunraster-8bit-rle: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-8bit-rle.sun -pix_fmt rgb24 -vf scale FATE_SUNRASTER += fate-sunraster-24bit-raw fate-sunraster-24bit-raw: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-24bit-raw.sun @@ -422,12 +458,12 @@ fate-targa: $(FATE_TARGA-yes) fate-targa-conformance-CBW8: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/CBW8.TGA -fate-targa-conformance-CCM8: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/CCM8.TGA -pix_fmt rgba +fate-targa-conformance-CCM8: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/CCM8.TGA -pix_fmt rgba -vf scale fate-targa-conformance-CTC16: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/CTC16.TGA -pix_fmt rgb555le fate-targa-conformance-CTC24: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/CTC24.TGA fate-targa-conformance-CTC32: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/CTC32.TGA -pix_fmt bgra fate-targa-conformance-UBW8: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/UBW8.TGA -fate-targa-conformance-UCM8: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/UCM8.TGA -pix_fmt rgba +fate-targa-conformance-UCM8: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/UCM8.TGA -pix_fmt rgba -vf scale fate-targa-conformance-UTC16: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/UTC16.TGA -pix_fmt rgb555le fate-targa-conformance-UTC24: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/UTC24.TGA fate-targa-conformance-UTC32: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/UTC32.TGA -pix_fmt bgra @@ -452,7 +488,7 @@ fate-webp-rgb-lena-lossless: CMD = framecrc -i $(TARGET_SAMPLES)/webp/rgb_lena_lossless.webp FATE_WEBP += fate-webp-rgb-lena-lossless-rgb24 -fate-webp-rgb-lena-lossless-rgb24: CMD = framecrc -i $(TARGET_SAMPLES)/webp/rgb_lena_lossless.webp -pix_fmt rgb24 +fate-webp-rgb-lena-lossless-rgb24: CMD = framecrc -i $(TARGET_SAMPLES)/webp/rgb_lena_lossless.webp -pix_fmt rgb24 -vf scale FATE_WEBP += fate-webp-rgba-lossless fate-webp-rgba-lossless: CMD = framecrc -i $(TARGET_SAMPLES)/webp/rgba_lossless.webp @@ -481,6 +517,9 @@ fate-xbm: $(FATE_XBM-yes) FATE_IMAGE += $(FATE_IMAGE-yes) +FATE_IMAGE_PROBE += $(FATE_IMAGE_PROBE-yes) FATE_SAMPLES_FFMPEG += $(FATE_IMAGE) -fate-image: $(FATE_IMAGE) +FATE_SAMPLES_FFPROBE += $(FATE_IMAGE_PROBE) + +fate-image: $(FATE_IMAGE) $(FATE_IMAGE_PROBE) diff -Nru ffmpeg-4.2.2/tests/fate/lavf-audio.mak ffmpeg-4.4/tests/fate/lavf-audio.mak --- ffmpeg-4.2.2/tests/fate/lavf-audio.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/lavf-audio.mak 2021-04-08 21:28:40.000000000 +0000 @@ -36,3 +36,8 @@ FATE_AVCONV += $(FATE_LAVF_AUDIO) fate-lavf-audio fate-lavf: $(FATE_LAVF_AUDIO) + +FATE_WAV_FFPROBE-$(CONFIG_WAV_DEMUXER) += fate-wav-chapters +fate-wav-chapters: CMD = probechapters $(TARGET_SAMPLES)/wav/200828-005.wav + +FATE_SAMPLES_FFPROBE += $(FATE_WAV_FFPROBE-yes) diff -Nru ffmpeg-4.2.2/tests/fate/lavf-container.mak ffmpeg-4.4/tests/fate/lavf-container.mak --- ffmpeg-4.2.2/tests/fate/lavf-container.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/lavf-container.mak 2020-07-11 10:39:30.000000000 +0000 @@ -56,6 +56,9 @@ FATE_AVCONV += $(FATE_LAVF_CONTAINER) fate-lavf-container fate-lavf: $(FATE_LAVF_CONTAINER) +FATE_LAVF_CONTAINER_FATE-$(call ALLYES, IVF_DEMUXER AV1_PARSER MOV_MUXER) += av1.mp4 +FATE_LAVF_CONTAINER_FATE-$(call ALLYES, IVF_DEMUXER AV1_PARSER MATROSKA_MUXER) += av1.mkv +FATE_LAVF_CONTAINER_FATE-$(call ALLYES, H264_DEMUXER H264_PARSER MOV_MUXER) += h264.mp4 FATE_LAVF_CONTAINER_FATE-$(call ALLYES, MATROSKA_DEMUXER OGG_MUXER) += vp3.ogg FATE_LAVF_CONTAINER_FATE-$(call ALLYES, MATROSKA_DEMUXER OGV_MUXER) += vp8.ogg FATE_LAVF_CONTAINER_FATE-$(call ALLYES, MOV_DEMUXER LATM_MUXER) += latm @@ -68,6 +71,9 @@ $(FATE_LAVF_CONTAINER_FATE): REF = $(SRC_PATH)/tests/ref/lavf-fate/$(@:fate-lavf-fate-%=%) $(FATE_LAVF_CONTAINER_FATE): $(AREF) $(VREF) +fate-lavf-fate-av1.mp4: CMD = lavf_container_fate "av1-test-vectors/av1-1-b8-05-mv.ivf" "" "-c:v copy" +fate-lavf-fate-av1.mkv: CMD = lavf_container_fate "av1-test-vectors/av1-1-b8-05-mv.ivf" "" "-c:v copy" +fate-lavf-fate-h264.mp4: CMD = lavf_container_fate "h264/intra_refresh.h264" "" "-c:v copy" fate-lavf-fate-vp3.ogg: CMD = lavf_container_fate "vp3/coeff_level64.mkv" "-idct auto" fate-lavf-fate-vp8.ogg: CMD = lavf_container_fate "vp8/RRSF49-short.webm" "" "-acodec copy" fate-lavf-fate-latm: CMD = lavf_container_fate "aac/al04_44.mp4" "" "-acodec copy" diff -Nru ffmpeg-4.2.2/tests/fate/lavf-video.mak ffmpeg-4.4/tests/fate/lavf-video.mak --- ffmpeg-4.2.2/tests/fate/lavf-video.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/lavf-video.mak 2020-07-09 09:17:46.000000000 +0000 @@ -6,7 +6,7 @@ FATE_LAVF_VIDEO-$(call ENCDEC, FITS, FITS) += gbrap.fits FATE_LAVF_VIDEO-$(call ENCDEC, FITS, FITS) += gbrp16be.fits FATE_LAVF_VIDEO-$(call ENCDEC, FITS, FITS) += gbrap16be.fits -FATE_LAVF_VIDEO-$(call ENCDEC, GIF, FITS) += gif +FATE_LAVF_VIDEO-$(call ENCDEC, GIF, GIF) += gif FATE_LAVF_VIDEO-$(CONFIG_YUV4MPEGPIPE_MUXER) += y4m FATE_LAVF_VIDEO = $(FATE_LAVF_VIDEO-yes:%=fate-lavf-%) diff -Nru ffmpeg-4.2.2/tests/fate/libavcodec.mak ffmpeg-4.4/tests/fate/libavcodec.mak --- ffmpeg-4.2.2/tests/fate/libavcodec.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/libavcodec.mak 2021-04-08 21:28:40.000000000 +0000 @@ -53,7 +53,7 @@ FATE_LIBAVCODEC-$(CONFIG_HEVC_METADATA_BSF) += fate-h265-levels fate-h265-levels: libavcodec/tests/h265_levels$(EXESUF) -fate-h265-levels: CMD = run libavcodec/tests/h265_levels +fate-h265-levels: CMD = run libavcodec/tests/h265_levels$(EXESUF) fate-h265-levels: REF = /dev/null FATE_LIBAVCODEC-$(CONFIG_IIRFILTER) += fate-iirfilter @@ -65,10 +65,6 @@ fate-mpeg12framerate: CMD = run libavcodec/tests/mpeg12framerate$(EXESUF) fate-mpeg12framerate: REF = /dev/null -FATE_LIBAVCODEC-yes += fate-libavcodec-options -fate-libavcodec-options: libavcodec/tests/options$(EXESUF) -fate-libavcodec-options: CMD = run libavcodec/tests/options$(EXESUF) - FATE_LIBAVCODEC-$(CONFIG_RANGECODER) += fate-rangecoder fate-rangecoder: libavcodec/tests/rangecoder$(EXESUF) fate-rangecoder: CMD = run libavcodec/tests/rangecoder$(EXESUF) diff -Nru ffmpeg-4.2.2/tests/fate/libswresample.mak ffmpeg-4.4/tests/fate/libswresample.mak --- ffmpeg-4.2.2/tests/fate/libswresample.mak 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/fate/libswresample.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1089,7 +1089,7 @@ FATE_SWR_AUDIOCONVERT-$(call FILTERDEMDECENCMUX, AFORMAT AEVAL, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-swr-audioconvert fate-swr-audioconvert: tests/data/asynth-44100-1.wav fate-swr-audioconvert: REF = tests/data/asynth-44100-1.wav -fate-swr-audioconvert: CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-44100-1.wav -af "aformat=fltp,aeval=val(0)+(random(0)-0.5)/33000,aformat=fltp" -f wav -c:a pcm_s16le - +fate-swr-audioconvert: CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-44100-1.wav -af "aresample,aformat=fltp,aresample,aeval=val(0)+(random(0)-0.5)/33000,aresample,aformat=fltp,aresample" -f wav -c:a pcm_s16le - fate-swr-audioconvert: CMP = stddev fate-swr-audioconvert: FUZZ = 0 diff -Nru ffmpeg-4.2.2/tests/fate/libswscale.mak ffmpeg-4.4/tests/fate/libswscale.mak --- ffmpeg-4.2.2/tests/fate/libswscale.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/libswscale.mak 2021-04-08 21:28:40.000000000 +0000 @@ -2,6 +2,10 @@ fate-sws-pixdesc-query: libswscale/tests/pixdesc_query$(EXESUF) fate-sws-pixdesc-query: CMD = run libswscale/tests/pixdesc_query$(EXESUF) +FATE_LIBSWSCALE += fate-sws-floatimg-cmp +fate-sws-floatimg-cmp: libswscale/tests/floatimg_cmp$(EXESUF) +fate-sws-floatimg-cmp: CMD = run libswscale/tests/floatimg_cmp$(EXESUF) + FATE_LIBSWSCALE += $(FATE_LIBSWSCALE-yes) FATE-$(CONFIG_SWSCALE) += $(FATE_LIBSWSCALE) fate-libswscale: $(FATE_LIBSWSCALE) diff -Nru ffmpeg-4.2.2/tests/fate/lossless-audio.mak ffmpeg-4.4/tests/fate/lossless-audio.mak --- ffmpeg-4.2.2/tests/fate/lossless-audio.mak 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/fate/lossless-audio.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,23 +1,17 @@ FATE_SAMPLES_LOSSLESS_AUDIO-$(call DEMDEC, MOV, ALAC) += fate-lossless-alac -fate-lossless-alac: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/inside.m4a -f s16le +fate-lossless-alac: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/inside.m4a -f s16le -af aresample FATE_SAMPLES_LOSSLESS_AUDIO-$(call DEMDEC, MLP, MLP) += fate-lossless-meridianaudio fate-lossless-meridianaudio: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.mlp -f s16le FATE_SAMPLES_LOSSLESS_AUDIO-$(call DEMDEC, RM, RALF) += fate-ralf -fate-ralf: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.rmvb -vn -f s16le +fate-ralf: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.rmvb -vn -f s16le -af aresample FATE_SAMPLES_LOSSLESS_AUDIO-$(call DEMDEC, SHORTEN, SHORTEN) += fate-lossless-shorten -fate-lossless-shorten: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.shn -f s16le +fate-lossless-shorten: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.shn -f s16le -af aresample FATE_SAMPLES_LOSSLESS_AUDIO-$(call DEMDEC, TAK, TAK) += fate-lossless-tak -fate-lossless-tak: CMD = crc -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.tak - -FATE_TRUEHD = fate-lossless-truehd-5.1 fate-lossless-truehd-5.1-downmix-2.0 -fate-lossless-truehd-5.1: CMD = md5 -f truehd -i $(TARGET_SAMPLES)/lossless-audio/truehd_5.1.raw -f s32le -fate-lossless-truehd-5.1-downmix-2.0: CMD = md5 -f truehd -request_channel_layout 2 -i $(TARGET_SAMPLES)/lossless-audio/truehd_5.1.raw -f s32le -fate-lossless-truehd: $(FATE_TRUEHD) -FATE_SAMPLES_LOSSLESS_AUDIO-$(call DEMDEC, TRUEHD, TRUEHD) += $(FATE_TRUEHD) +fate-lossless-tak: CMD = crc -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.tak -af aresample FATE_SAMPLES_LOSSLESS_AUDIO-$(call DEMDEC, TTA, TTA) += fate-lossless-tta fate-lossless-tta: CMD = crc -i $(TARGET_SAMPLES)/lossless-audio/inside.tta @@ -26,10 +20,10 @@ fate-lossless-tta-encrypted: CMD = crc -password ffmpeg -i $(TARGET_SAMPLES)/lossless-audio/encrypted.tta FATE_SAMPLES_LOSSLESS_AUDIO-$(call DEMDEC, ASF, WMALOSSLESS) += fate-lossless-wma fate-lossless-wma24-1 fate-lossless-wma24-2 fate-lossless-wma24-rawtile -fate-lossless-wma: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.wma -f s16le -frames 209 -fate-lossless-wma24-1: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/master_audio_2.0_24bit.wma -f s24le -fate-lossless-wma24-2: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/Mega_Weird_Audio_Test_24bit.wma -f s24le -fate-lossless-wma24-rawtile: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/g2_24bit.wma -f s24le +fate-lossless-wma: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.wma -f s16le -frames 209 -af aresample +fate-lossless-wma24-1: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/master_audio_2.0_24bit.wma -f s24le -af aresample +fate-lossless-wma24-2: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/Mega_Weird_Audio_Test_24bit.wma -f s24le -af aresample +fate-lossless-wma24-rawtile: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/g2_24bit.wma -f s24le -af aresample fate-lossless-wmall: fate-lossless-wma fate-lossless-wma24-1 fate-lossless-wma24-2 fate-lossless-wma24-rawtile FATE_SAMPLES_LOSSLESS_AUDIO += $(FATE_SAMPLES_LOSSLESS_AUDIO-yes) diff -Nru ffmpeg-4.2.2/tests/fate/lossless-video.mak ffmpeg-4.4/tests/fate/lossless-video.mak --- ffmpeg-4.2.2/tests/fate/lossless-video.mak 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/fate/lossless-video.mak 2021-04-08 21:28:40.000000000 +0000 @@ -2,7 +2,7 @@ fate-lagarith-rgb24: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lag-rgb24.avi FATE_LAGARITH += fate-lagarith-rgb32 -fate-lagarith-rgb32: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lag-rgb32.avi -pix_fmt bgra +fate-lagarith-rgb32: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lag-rgb32.avi -pix_fmt bgra -vf scale FATE_LAGARITH += fate-lagarith-yuy2 fate-lagarith-yuy2: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lag-yuy2.avi @@ -13,12 +13,11 @@ FATE_LAGARITH += fate-lagarith-red fate-lagarith-red: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-red.avi -FATE_LAGARITH += fate-lagarith-ticket4119 fate-lagarith-ticket4119-cfr fate-lagarith-ticket4119-vfr fate-lagarith-ticket4119-pass fate-lagarith-ticket4119-drop +FATE_LAGARITH += fate-lagarith-ticket4119 fate-lagarith-ticket4119-cfr fate-lagarith-ticket4119-vfr fate-lagarith-ticket4119-pass fate-lagarith-ticket4119: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-1.3.27-black-frames-and-off-by-ones.avi fate-lagarith-ticket4119-cfr : CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-1.3.27-black-frames-and-off-by-ones.avi -vsync cfr fate-lagarith-ticket4119-vfr : CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-1.3.27-black-frames-and-off-by-ones.avi -vsync vfr fate-lagarith-ticket4119-pass: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-1.3.27-black-frames-and-off-by-ones.avi -vsync passthrough -fate-lagarith-ticket4119-drop: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-1.3.27-black-frames-and-off-by-ones.avi -vsync drop FATE_LOSSLESS_VIDEO-$(call DEMDEC, AVI, LAGARITH) += $(FATE_LAGARITH) fate-lagarith: $(FATE_LAGARITH) @@ -33,7 +32,7 @@ fate-loco: $(FATE_LOCO) FATE_LOSSLESS_VIDEO-$(call DEMDEC, AVI, MSRLE) += fate-msrle-8bit -fate-msrle-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/msrle/Search-RLE.avi -pix_fmt rgb24 +fate-msrle-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/msrle/Search-RLE.avi -pix_fmt rgb24 -vf scale FATE_LOSSLESS_VIDEO-$(call DEMDEC, AVI, MSZH) += fate-mszh fate-mszh: CMD = framecrc -i $(TARGET_SAMPLES)/lcl/mszh-1frame.avi diff -Nru ffmpeg-4.2.2/tests/fate/matroska.mak ffmpeg-4.4/tests/fate/matroska.mak --- ffmpeg-4.2.2/tests/fate/matroska.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/matroska.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,13 +1,118 @@ +FATE_MATROSKA-$(call ALLYES, MATROSKA_DEMUXER ZLIB) += fate-matroska-prores-zlib +fate-matroska-prores-zlib: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/prores_zlib.mkv -c:v copy + +# This tests that the matroska demuxer correctly adds the icpf header atom +# upon demuxing; it also tests bz2 decompression and unknown-length cluster. +FATE_MATROSKA-$(call ALLYES, MATROSKA_DEMUXER BZLIB) += fate-matroska-prores-header-insertion-bz2 +fate-matroska-prores-header-insertion-bz2: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/prores_bz2.mkv -map 0 -c copy + # This tests that the matroska demuxer supports modifying the colorspace # properties in remuxing (-c:v copy) # It also tests automatic insertion of the vp9_superframe bitstream filter FATE_MATROSKA-$(call DEMMUX, MATROSKA, MATROSKA) += fate-matroska-remux fate-matroska-remux: CMD = md5pipe -i $(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-2pass-akiyo.webm -color_trc 4 -c:v copy -fflags +bitexact -strict -2 -f matroska fate-matroska-remux: CMP = oneline -fate-matroska-remux: REF = e5457e5fa606d564a54914bd12f426c8 +fate-matroska-remux: REF = 26fabd90326e3de4bb6afe1b216ce232 + +FATE_MATROSKA-$(call ALLYES, MATROSKA_DEMUXER VORBIS_PARSER) += fate-matroska-xiph-lacing +fate-matroska-xiph-lacing: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/xiph_lacing.mka -c:a copy + +# This tests that the Matroska demuxer correctly demuxes WavPack +# without CodecPrivate; it also tests zlib compressed WavPack. +FATE_MATROSKA-$(call ALLYES, MATROSKA_DEMUXER ZLIB) += fate-matroska-wavpack-missing-codecprivate +fate-matroska-wavpack-missing-codecprivate: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/wavpack_missing_codecprivate.mka -c copy + +# This tests that the matroska demuxer supports decompressing +# zlib compressed tracks (both the CodecPrivate as well as the actual frames). +FATE_MATROSKA-$(call ALLYES, MATROSKA_DEMUXER ZLIB) += fate-matroska-zlib-decompression +fate-matroska-zlib-decompression: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/subtitle_zlib.mks -c:s copy + +# This tests that the matroska demuxer can decompress lzo compressed tracks. +FATE_MATROSKA-$(call ALLYES, MATROSKA_DEMUXER LZO) += fate-matroska-lzo-decompression +fate-matroska-lzo-decompression: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/lzo.mka -c copy + +# This tests that the matroska demuxer correctly propagates +# the channel layout contained in vorbis comments in the CodecPrivate +# of flac tracks. It also tests header removal compression. +FATE_MATROSKA-$(call ALLYES, MATROSKA_DEMUXER FLAC_PARSER) += fate-matroska-flac-channel-mapping +fate-matroska-flac-channel-mapping: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/flac_channel_layouts.mka -map 0 -c:a copy + +# This tests that the Matroska muxer writes the channel layout +# of FLAC tracks as a Vorbis comment in the CodecPrivate if necessary +# and that FLAC extradata is correctly updated when a packet +# with sidedata containing new extradata is encountered. +# Furthermore it tests everything the matroska-flac-channel-mapping test +# tests and it also tests the FLAC decoder and encoder, in particular +# the latter's ability to send updated extradata. +FATE_MATROSKA-$(call ALLYES, FLAC_DECODER FLAC_ENCODER FLAC_PARSER \ + MATROSKA_DEMUXER MATROSKA_MUXER) += fate-matroska-flac-extradata-update +fate-matroska-flac-extradata-update: CMD = transcode matroska $(TARGET_SAMPLES)/mkv/flac_channel_layouts.mka \ + matroska "-map 0 -map 0:0 -c flac -frames:a:2 8" "-map 0 -c copy" + +# This test tests demuxing Vorbis and chapters from ogg and muxing it in and +# demuxing it from Matroska/WebM. It furthermore tests the WebM muxer, in +# particular its DASH mode. Finally, it tests writing the Cues at the front. +FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, MATROSKA_DEMUXER OGG_DEMUXER \ + VORBIS_DECODER VORBIS_PARSER WEBM_MUXER) \ + += fate-webm-dash-chapters +fate-webm-dash-chapters: CMD = transcode ogg $(TARGET_SAMPLES)/vorbis/vorbis_chapter_extension_demo.ogg webm "-c copy -cluster_time_limit 1500 -dash 1 -dash_track_number 124 -reserve_index_space 400" "-c copy -t 0.5" "" -show_chapters + +# The input file has a Block whose payload has a size of zero before reversing +# header removal compression; it furthermore uses chained SeekHeads and has +# level 1-elements after the Cluster. This is tested on the demuxer's side. +# For the muxer this tests that it can correctly write huge TrackNumbers and +# that it can expand the Cues element's length field by one byte if necessary. +# It furthermore tests correct propagation of the description tag. +FATE_MATROSKA_FFMPEG_FFPROBE-$(call DEMMUX, MATROSKA, MATROSKA) \ + += fate-matroska-zero-length-block +fate-matroska-zero-length-block: CMD = transcode matroska $(TARGET_SAMPLES)/mkv/zero_length_block.mks matroska "-c:s copy -dash 1 -dash_track_number 2000000000 -reserve_index_space 62 -metadata_header_padding 1" "-c:s copy" "" "-show_entries stream_tags=description" + +# This test the following features of the Matroska muxer: Writing projection +# stream side-data; not setting any track to default if the user requested it; +# and modifying and writing colorspace properties. +FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, MATROSKA_DEMUXER MATROSKA_MUXER \ + H264_DECODER H264_PARSER) \ + += fate-matroska-spherical-mono-remux +fate-matroska-spherical-mono-remux: CMD = transcode matroska $(TARGET_SAMPLES)/mkv/spherical.mkv matroska "-map 0 -map 0 -c copy -disposition:0 -default+forced -disposition:1 -default -default_mode passthrough -color_primaries:1 bt709 -color_trc:1 smpte170m -colorspace:1 bt2020c -color_range:1 pc" "-map 0 -c copy -t 0" "" "-show_entries stream_side_data_list:stream_disposition=default,forced:stream=color_range,color_space,color_primaries,color_transfer" + +# The input file of the following test contains Content Light Level as well as +# Mastering Display Metadata and so this test tests correct muxing and demuxing +# of these. It furthermore also tests that this data is correctly propagated +# when reencoding (here to ffv1). +# Both input audio tracks are completely zero, so the noise bsf is used +# to make this test interesting. +FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL MXF_DEMUXER \ + PRORES_DECODER PCM_S24LE_DECODER \ + FFV1_ENCODER ARESAMPLE_FILTER \ + PCM_S16BE_ENCODER NOISE_BSF \ + MATROSKA_MUXER MATROSKA_DEMUXER \ + FRAMECRC_MUXER PIPE_PROTOCOL) \ + += fate-matroska-mastering-display-metadata +fate-matroska-mastering-display-metadata: CMD = transcode mxf $(TARGET_SAMPLES)/mxf/Meridian-Apple_ProResProxy-HDR10.mxf matroska "-map 0 -map 0:0 -c:v:0 copy -c:v:1 ffv1 -c:a:0 copy -bsf:a:0 noise=amount=3 -filter:a:1 aresample -c:a:1 pcm_s16be -bsf:a:1 noise=dropamount=4" "-map 0 -c copy" "" "-show_entries stream_side_data_list:stream=index,codec_name" + +# Tests writing BlockAdditional and BlockGroups with ReferenceBlock elements; +# it also tests setting a track as suitable for hearing impaired. +# It also tests the capability of the VP8 parser to set the keyframe flag +# (the input file lacks ReferenceBlock elements making everything a keyframe). +FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL MATROSKA_DEMUXER \ + VP8_PARSER MATROSKA_MUXER \ + FRAMECRC_MUXER PIPE_PROTOCOL) \ + += fate-matroska-vp8-alpha-remux +fate-matroska-vp8-alpha-remux: CMD = transcode matroska $(TARGET_SAMPLES)/vp8_alpha/vp8_video_with_alpha.webm matroska "-c copy -disposition +hearing_impaired -cluster_size_limit 100000" "-c copy -t 0.2" "" "-show_entries stream_disposition:stream_side_data_list" + +# The audio stream to be remuxed here has AV_DISPOSITION_VISUAL_IMPAIRED. +FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL MPEGTS_DEMUXER \ + AC3_DECODER MATROSKA_MUXER \ + MATROSKA_DEMUXER FRAMECRC_MUXER \ + PIPE_PROTOCOL) \ + += fate-matroska-mpegts-remux +fate-matroska-mpegts-remux: CMD = transcode mpegts $(TARGET_SAMPLES)/mpegts/pmtchange.ts matroska "-map 0:2 -map 0:2 -c copy -disposition:a:1 -visual_impaired+hearing_impaired" "-map 0 -c copy" "" "-show_entries stream_disposition:stream=index" FATE_MATROSKA_FFPROBE-$(call ALLYES, MATROSKA_DEMUXER) += fate-matroska-spherical-mono fate-matroska-spherical-mono: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream_side_data_list -select_streams v -v 0 $(TARGET_SAMPLES)/mkv/spherical.mkv FATE_SAMPLES_AVCONV += $(FATE_MATROSKA-yes) FATE_SAMPLES_FFPROBE += $(FATE_MATROSKA_FFPROBE-yes) +FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_MATROSKA_FFMPEG_FFPROBE-yes) + +fate-matroska: $(FATE_MATROSKA-yes) $(FATE_MATROSKA_FFPROBE-yes) $(FATE_MATROSKA_FFMPEG_FFPROBE-yes) diff -Nru ffmpeg-4.2.2/tests/fate/microsoft.mak ffmpeg-4.4/tests/fate/microsoft.mak --- ffmpeg-4.2.2/tests/fate/microsoft.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/microsoft.mak 2021-04-08 21:28:40.000000000 +0000 @@ -11,10 +11,10 @@ fate-mss2-pals: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/rlepals.wmv FATE_MSS2 += fate-mss2-rgb555 -fate-mss2-rgb555: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/rle555.wmv -pix_fmt rgb555le +fate-mss2-rgb555: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/rle555.wmv -pix_fmt rgb555le -vf scale FATE_MSS2 += fate-mss2-rgb555s -fate-mss2-rgb555s: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/rle555s.wmv -pix_fmt rgb555le +fate-mss2-rgb555s: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/rle555s.wmv -pix_fmt rgb555le -vf scale FATE_MSS2 += fate-mss2-wmv fate-mss2-wmv: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/msscreencodec.wmv -an -frames 100 @@ -29,10 +29,10 @@ fate-mts2: $(FATE_MTS2) FATE_MSVIDEO1 += fate-msvideo1-8bit -fate-msvideo1-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/cram/skating.avi -t 1 -pix_fmt rgb24 +fate-msvideo1-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/cram/skating.avi -t 1 -pix_fmt rgb24 -vf scale FATE_MSVIDEO1 += fate-msvideo1-16bit -fate-msvideo1-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/cram/clock-cram16.avi -pix_fmt rgb24 +fate-msvideo1-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/cram/clock-cram16.avi -pix_fmt rgb24 -vf scale FATE_MICROSOFT-$(call DEMDEC, AVI, MSVIDEO1) += $(FATE_MSVIDEO1) fate-msvideo1: $(FATE_MSVIDEO1) diff -Nru ffmpeg-4.2.2/tests/fate/monkeysaudio.mak ffmpeg-4.4/tests/fate/monkeysaudio.mak --- ffmpeg-4.2.2/tests/fate/monkeysaudio.mak 2016-03-29 02:25:34.000000000 +0000 +++ ffmpeg-4.4/tests/fate/monkeysaudio.mak 2021-04-08 21:28:40.000000000 +0000 @@ -2,11 +2,11 @@ define FATE_APE_SUITE FATE_APE += fate-lossless-monkeysaudio-$(1)-normal -fate-lossless-monkeysaudio-$(1)-normal: CMD = crc -i $(TARGET_SAMPLES)/lossless-audio/luckynight-mac$(1)-c2000.ape -af atrim=end_sample=73728 +fate-lossless-monkeysaudio-$(1)-normal: CMD = crc -auto_conversion_filters -i $(TARGET_SAMPLES)/lossless-audio/luckynight-mac$(1)-c2000.ape -af atrim=end_sample=73728 fate-lossless-monkeysaudio-$(1)-normal: REF = CRC=0x5d08c17e fate-lossless-monkeysaudio-$(1)-normal: CMP = oneline FATE_APE += fate-lossless-monkeysaudio-$(1)-extrahigh -fate-lossless-monkeysaudio-$(1)-extrahigh: CMD = crc -i $(TARGET_SAMPLES)/lossless-audio/luckynight-mac$(1)-c4000.ape -af atrim=end_sample=73728 +fate-lossless-monkeysaudio-$(1)-extrahigh: CMD = crc -auto_conversion_filters -i $(TARGET_SAMPLES)/lossless-audio/luckynight-mac$(1)-c4000.ape -af atrim=end_sample=73728 fate-lossless-monkeysaudio-$(1)-extrahigh: REF = CRC=0x5d08c17e fate-lossless-monkeysaudio-$(1)-extrahigh: CMP = oneline endef @@ -14,7 +14,7 @@ $(foreach N,$(APE_VERSIONS),$(eval $(call FATE_APE_SUITE,$(N)))) FATE_APE += fate-lossless-monkeysaudio-399 -fate-lossless-monkeysaudio-399: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.ape -f s16le +fate-lossless-monkeysaudio-399: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.ape -f s16le -af aresample FATE_SAMPLES_AVCONV-$(call DEMDEC, APE, APE) += $(FATE_APE) fate-lossless-monkeysaudio: $(FATE_APE) diff -Nru ffmpeg-4.2.2/tests/fate/mov.mak ffmpeg-4.4/tests/fate/mov.mak --- ffmpeg-4.2.2/tests/fate/mov.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/mov.mak 2021-04-08 21:28:40.000000000 +0000 @@ -29,6 +29,7 @@ fate-mov-guess-delay-2 \ fate-mov-guess-delay-3 \ fate-mov-mp4-with-mov-in24-ver \ + fate-mov-mp4-extended-atom \ FATE_MOV_FASTSTART = fate-mov-faststart-4gb-overflow \ @@ -68,7 +69,7 @@ fate-mov-elst-ends-betn-b-and-i: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/elst_ends_betn_b_and_i.mp4 # Makes sure that we handle edit lists and start padding correctly. -fate-mov-440hz-10ms: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/440hz-10ms.m4a +fate-mov-440hz-10ms: CMD = framemd5 -i $(TARGET_SAMPLES)/mov/440hz-10ms.m4a -af aresample # Makes sure that we handle invalid edit list entry count correctly. fate-mov-invalid-elst-entry-count: CMD = framemd5 -idct simple -flags +bitexact -i $(TARGET_SAMPLES)/mov/invalid_elst_entry_count.mov @@ -86,7 +87,7 @@ # Makes sure that we pick the right frames according to edit list when there is no keyframe with PTS < edit list start. # For example, when video starts on a B-frame, and edit list starts on that B-frame too. # GOP structure : B B I in presentation order. -fate-mov-bbi-elst-starts-b: CMD = framemd5 -flags +bitexact -acodec aac_fixed -i $(TARGET_SAMPLES)/h264/twofields_packet.mp4 +fate-mov-bbi-elst-starts-b: CMD = framemd5 -flags +bitexact -acodec aac_fixed -i $(TARGET_SAMPLES)/h264/twofields_packet.mp4 -af aresample # Makes sure that the stream start_time is not negative when the first packet is a DISCARD packet with negative timestamp. fate-mov-neg-firstpts-discard: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=start_time -bitexact $(TARGET_SAMPLES)/mov/mov_neg_first_pts_discard.mov @@ -113,14 +114,16 @@ fate-mov-gpmf-remux: CMD = md5 -i $(TARGET_SAMPLES)/mov/fake-gp-media-with-real-gpmf.mp4 -map 0 -c copy -fflags +bitexact -f mp4 fate-mov-gpmf-remux: CMP = oneline -fate-mov-gpmf-remux: REF = 8f48e435ee1f6b7e173ea756141eabf3 +fate-mov-gpmf-remux: REF = 6361cf3c2b9e6962c2eafbda138125f4 fate-mov-guess-delay-1: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=has_b_frames -select_streams v $(TARGET_SAMPLES)/h264/h264_3bf_nopyramid_nobsrestriction.mp4 fate-mov-guess-delay-2: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=has_b_frames -select_streams v $(TARGET_SAMPLES)/h264/h264_3bf_pyramid_nobsrestriction.mp4 fate-mov-guess-delay-3: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=has_b_frames -select_streams v $(TARGET_SAMPLES)/h264/h264_4bf_pyramid_nobsrestriction.mp4 -fate-mov-faststart-4gb-overflow: CMD = run tools/qt-faststart$(EXESUF) $(TARGET_SAMPLES)/mov/faststart-4gb-overflow.mov faststart-4gb-overflow-output.mov > /dev/null ; do_md5sum faststart-4gb-overflow-output.mov | cut -d " " -f1 ; rm faststart-4gb-overflow-output.mov +fate-mov-faststart-4gb-overflow: CMD = run tools/qt-faststart$(EXESUF) $(TARGET_SAMPLES)/mov/faststart-4gb-overflow.mov $(TARGET_PATH)/faststart-4gb-overflow-output.mov > /dev/null ; do_md5sum faststart-4gb-overflow-output.mov | cut -d " " -f1 ; rm faststart-4gb-overflow-output.mov fate-mov-faststart-4gb-overflow: CMP = oneline fate-mov-faststart-4gb-overflow: REF = bc875921f151871e787c4b4023269b29 fate-mov-mp4-with-mov-in24-ver: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=codec_name -select_streams 1 $(TARGET_SAMPLES)/mov/mp4-with-mov-in24-ver.mp4 + +fate-mov-mp4-extended-atom: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_packets -print_format compact -select_streams v $(TARGET_SAMPLES)/mov/extended_atom_size_probe diff -Nru ffmpeg-4.2.2/tests/fate/mp3.mak ffmpeg-4.4/tests/fate/mp3.mak --- ffmpeg-4.2.2/tests/fate/mp3.mak 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/fate/mp3.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,33 +1,33 @@ FATE_MP3 += fate-mp3-float-conf-compl -fate-mp3-float-conf-compl: CMD = ffmpeg -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/compl.bit -f f32le - +fate-mp3-float-conf-compl: CMD = ffmpeg -auto_conversion_filters -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/compl.bit -f f32le - fate-mp3-float-conf-compl: REF = $(SAMPLES)/mp3-conformance/compl.f32 FATE_MP3 += fate-mp3-float-conf-he_32khz -fate-mp3-float-conf-he_32khz: CMD = ffmpeg -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/he_32khz.bit -af atrim=end_sample=171648 -f f32le - +fate-mp3-float-conf-he_32khz: CMD = ffmpeg -auto_conversion_filters -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/he_32khz.bit -af atrim=end_sample=171648 -f f32le - fate-mp3-float-conf-he_32khz: REF = $(SAMPLES)/mp3-conformance/he_32khz.f32 FATE_MP3 += fate-mp3-float-conf-he_44khz -fate-mp3-float-conf-he_44khz: CMD = ffmpeg -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/he_44khz.bit -af atrim=end_sample=471168 -f f32le - +fate-mp3-float-conf-he_44khz: CMD = ffmpeg -auto_conversion_filters -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/he_44khz.bit -af atrim=end_sample=471168 -f f32le - fate-mp3-float-conf-he_44khz: REF = $(SAMPLES)/mp3-conformance/he_44khz.f32 FATE_MP3 += fate-mp3-float-conf-he_48khz -fate-mp3-float-conf-he_48khz: CMD = ffmpeg -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/he_48khz.bit -af atrim=end_sample=171648 -f f32le - +fate-mp3-float-conf-he_48khz: CMD = ffmpeg -auto_conversion_filters -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/he_48khz.bit -af atrim=end_sample=171648 -f f32le - fate-mp3-float-conf-he_48khz: REF = $(SAMPLES)/mp3-conformance/he_48khz.f32 FATE_MP3 += fate-mp3-float-conf-hecommon -fate-mp3-float-conf-hecommon: CMD = ffmpeg -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/hecommon.bit -af atrim=end_sample=33408 -f f32le - +fate-mp3-float-conf-hecommon: CMD = ffmpeg -auto_conversion_filters -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/hecommon.bit -af atrim=end_sample=33408 -f f32le - fate-mp3-float-conf-hecommon: REF = $(SAMPLES)/mp3-conformance/hecommon.f32 FATE_MP3 += fate-mp3-float-conf-si -fate-mp3-float-conf-si: CMD = ffmpeg -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/si.bit -af atrim=end_sample=134784 -f f32le - +fate-mp3-float-conf-si: CMD = ffmpeg -auto_conversion_filters -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/si.bit -af atrim=end_sample=134784 -f f32le - fate-mp3-float-conf-si: REF = $(SAMPLES)/mp3-conformance/si.f32 FATE_MP3 += fate-mp3-float-conf-si_block -fate-mp3-float-conf-si_block: CMD = ffmpeg -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/si_block.bit -af atrim=end_sample=72576 -f f32le - +fate-mp3-float-conf-si_block: CMD = ffmpeg -auto_conversion_filters -c:a mp3float -i $(TARGET_SAMPLES)/mp3-conformance/si_block.bit -af atrim=end_sample=72576 -f f32le - fate-mp3-float-conf-si_block: REF = $(SAMPLES)/mp3-conformance/si_block.f32 FATE_MP3 += fate-mp3-float-extra_overread -fate-mp3-float-extra_overread: CMD = ffmpeg -c:a mp3float -i $(TARGET_SAMPLES)/mpegaudio/extra_overread.mp3 -f f32le - +fate-mp3-float-extra_overread: CMD = ffmpeg -auto_conversion_filters -c:a mp3float -i $(TARGET_SAMPLES)/mpegaudio/extra_overread.mp3 -f f32le - fate-mp3-float-extra_overread: REF = $(SAMPLES)/mpegaudio/extra_overread.f32 $(FATE_MP3): CMP = oneoff diff -Nru ffmpeg-4.2.2/tests/fate/mpc.mak ffmpeg-4.4/tests/fate/mpc.mak --- ffmpeg-4.2.2/tests/fate/mpc.mak 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/fate/mpc.mak 2021-04-08 21:28:40.000000000 +0000 @@ -9,5 +9,12 @@ fate-musepack7: CMP = oneoff fate-musepack7: REF = $(SAMPLES)/musepack/inside-mp7.pcm +FATE_MPC-$(call ALLYES, FILE_PROTOCOL MPC8_DEMUXER MPC8_DECODER \ + ARESAMPLE_FILTER PCM_S16LE_ENCODER \ + FRAMECRC_MUXER PIPE_PROTOCOL) += fate-musepack8 +fate-musepack8: CMD = pcm -i $(TARGET_SAMPLES)/musepack/inside-mp8.mpc -ss 8.4 -af aresample +fate-musepack8: CMP = oneoff +fate-musepack8: REF = $(SAMPLES)/musepack/inside-mp8.pcm + FATE_SAMPLES_AVCONV += $(FATE_MPC-yes) fate-mpc: $(FATE_MPC-yes) diff -Nru ffmpeg-4.2.2/tests/fate/mpegps.mak ffmpeg-4.4/tests/fate/mpegps.mak --- ffmpeg-4.2.2/tests/fate/mpegps.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/mpegps.mak 2020-07-11 10:39:30.000000000 +0000 @@ -1,6 +1,6 @@ # This tests that a 16-bit pcm_dvd stream is correctly remuxed in mpegps FATE_MPEGPS-$(call DEMMUX, MPEGPS, MPEG1SYSTEM) += fate-mpegps-remuxed-pcm-demux -fate-mpegps-remuxed-pcm-demux: $(TARGET_SAMPLES)/mpegps/pcm_aud.mpg +fate-mpegps-remuxed-pcm-demux: $(SAMPLES)/mpegps/pcm_aud.mpg fate-mpegps-remuxed-pcm-demux: CMD = stream_remux "mpeg" "$(TARGET_SAMPLES)/mpegps/pcm_aud.mpg" "mpeg" "-map 0:a:0" "-codec copy" FATE_SAMPLES_FFMPEG += $(FATE_MPEGPS-yes) diff -Nru ffmpeg-4.2.2/tests/fate/mxf.mak ffmpeg-4.4/tests/fate/mxf.mak --- ffmpeg-4.2.2/tests/fate/mxf.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/mxf.mak 2021-04-08 21:28:40.000000000 +0000 @@ -33,26 +33,30 @@ fate-mxf-probe-dv25: SRC = $(TARGET_SAMPLES)/mxf/Avid-00005.mxf fate-mxf-probe-dv25: CMD = run $(PROBE_FORMAT_STREAMS_COMMAND) -i "$(SRC)" +FATE_MXF_PROBE-$(call ENCDEC2, PRORES, PCM_S24LE, MXF) += fate-mxf-probe-applehdr10 +fate-mxf-probe-applehdr10: SRC = $(TARGET_SAMPLES)/mxf/Meridian-Apple_ProResProxy-HDR10.mxf +fate-mxf-probe-applehdr10: CMD = run $(PROBE_FORMAT_STREAMS_COMMAND) -i "$(SRC)" | sed -e "s/yuv422p10../yuv422p10/" + FATE_MXF_REEL_NAME-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += fate-mxf-reel_name -fate-mxf-reel_name: $(TARGET_SAMPLES)/mxf/Sony-00001.mxf +fate-mxf-reel_name: $(SAMPLES)/mxf/Sony-00001.mxf fate-mxf-reel_name: CMD = md5 -y -i $(TARGET_SAMPLES)/mxf/Sony-00001.mxf -c copy -timecode 00:00:00:00 -metadata "reel_name=test_reel" -fflags +bitexact -f mxf FATE_MXF_USER_COMMENTS-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += fate-mxf-user-comments -fate-mxf-user-comments: $(TARGET_SAMPLES)/mxf/Sony-00001.mxf +fate-mxf-user-comments: $(SAMPLES)/mxf/Sony-00001.mxf fate-mxf-user-comments: CMD = md5 -y -i $(TARGET_SAMPLES)/mxf/Sony-00001.mxf -c copy -metadata "comment_test=value" -fflags +bitexact -f mxf -FATE_MXF_D10_USER_COMMENTS-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += fate-mxf-d10-user-comments -fate-mxf-d10-user-comments: $(TARGET_SAMPLES)/mxf/Sony-00001.mxf -fate-mxf-d10-user-comments: CMD = md5 -y -i $(TARGET_SAMPLES)/mxf/Sony-00001.mxf -c copy -metadata "comment_test=value" -store_user_comments 1 -fflags +bitexact -f mxf_d10 +FATE_MXF_D10_USER_COMMENTS-$(call ALLYES, FILE_PROTOCOL MXF_DEMUXER DVVIDEO_DECODER SCALE_FILTER MPEG2VIDEO_ENCODER MXF_D10_MUXER EXTRACT_EXTRADATA_BSF MPEGVIDEO_PARSER PIPE_PROTOCOL FRAMECRC_MUXER) += fate-mxf-d10-user-comments +fate-mxf-d10-user-comments: CMD = transcode mxf $(TARGET_SAMPLES)/mxf/Avid-00005.mxf mxf_d10 "-c:v mpeg2video -b:v 30000k -minrate:v 30000k -maxrate:v 30000k -bufsize:v 30000k -rc_init_occupancy 30000k -vf scale=w=1280:h=720 -an -metadata comment_test=value -metadata company_name=FATE-company -metadata product_name=FATE-test -metadata product_version=3.14159 -store_user_comments 1" "-c copy -frames:v 5" "" "-show_entries format_tags" FATE_MXF_OPATOM_USER_COMMENTS-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += fate-mxf-opatom-user-comments -fate-mxf-opatom-user-comments: $(TARGET_SAMPLES)/mxf/Sony-00001.mxf +fate-mxf-opatom-user-comments: $(SAMPLES)/mxf/Sony-00001.mxf fate-mxf-opatom-user-comments: CMD = md5 -y -i $(TARGET_SAMPLES)/mxf/Sony-00001.mxf -an -vcodec copy -metadata "comment_test=value" -fflags +bitexact -f mxf_opatom FATE_MXF-$(CONFIG_MXF_DEMUXER) += $(FATE_MXF) FATE_SAMPLES_AVCONV += $(FATE_MXF-yes) $(FATE_MXF_REEL_NAME-yes) -FATE_SAMPLES_AVCONV += $(FATE_MXF_USER_COMMENTS-yes) $(FATE_MXF_D10_USER_COMMENTS-yes) $(FATE_MXF_OPATOM_USER_COMMENTS-yes) +FATE_SAMPLES_AVCONV += $(FATE_MXF_USER_COMMENTS-yes) $(FATE_MXF_OPATOM_USER_COMMENTS-yes) +FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_MXF_D10_USER_COMMENTS-yes) FATE_SAMPLES_FFPROBE += $(FATE_MXF_PROBE-yes) fate-mxf: $(FATE_MXF-yes) $(FATE_MXF_PROBE-yes) $(FATE_MXF_REEL_NAME-yes) $(FATE_MXF_USER_COMMENTS-yes) $(FATE_MXF_D10_USER_COMMENTS-yes) $(FATE_MXF_OPATOM_USER_COMMENTS-yes) diff -Nru ffmpeg-4.2.2/tests/fate/opus.mak ffmpeg-4.4/tests/fate/opus.mak --- ffmpeg-4.2.2/tests/fate/opus.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/opus.mak 2021-04-08 21:28:40.000000000 +0000 @@ -10,7 +10,7 @@ define FATE_OPUS_TEST FATE_OPUS += fate-opus-$(1) FATE_OPUS$(2) += fate-opus-$(1) -fate-opus-$(1): CMD = ffmpeg -i $(TARGET_SAMPLES)/opus/$(1).mka -f s16le - +fate-opus-$(1): CMD = ffmpeg -i $(TARGET_SAMPLES)/opus/$(1).mka -f s16le -af aresample - fate-opus-$(1): REF = $(SAMPLES)/opus/$(1)$(2).dec endef diff -Nru ffmpeg-4.2.2/tests/fate/pcm.mak ffmpeg-4.4/tests/fate/pcm.mak --- ffmpeg-4.2.2/tests/fate/pcm.mak 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/fate/pcm.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,11 +1,11 @@ FATE_SAMPLES_PCM-$(call DEMDEC, WAV, PCM_U8) += fate-iff-pcm -fate-iff-pcm: CMD = md5 -i $(TARGET_SAMPLES)/iff/Bells -f s16le +fate-iff-pcm: CMD = md5 -i $(TARGET_SAMPLES)/iff/Bells -f s16le -af aresample FATE_SAMPLES_PCM-$(call DEMDEC, MPEGPS, PCM_DVD) += fate-pcm_dvd -fate-pcm_dvd: CMD = framecrc -i $(TARGET_SAMPLES)/pcm-dvd/coolitnow-partial.vob -vn +fate-pcm_dvd: CMD = framecrc -i $(TARGET_SAMPLES)/pcm-dvd/coolitnow-partial.vob -vn -af aresample FATE_SAMPLES_PCM-$(call DEMDEC, EA, PCM_S16LE_PLANAR) += fate-pcm-planar -fate-pcm-planar: CMD = framecrc -i $(TARGET_SAMPLES)/ea-mad/xeasport.mad -vn +fate-pcm-planar: CMD = framecrc -i $(TARGET_SAMPLES)/ea-mad/xeasport.mad -vn -af aresample FATE_SAMPLES_PCM-$(call DEMDEC, MOV, PCM_S16BE) += fate-pcm_s16be-stereo fate-pcm_s16be-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-B-twos.mov -f s16le @@ -14,10 +14,10 @@ fate-pcm_s16le-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-L-sowt.mov -f s16le FATE_SAMPLES_PCM-$(call DEMDEC, MOV, PCM_U8) += fate-pcm_u8-mono -fate-pcm_u8-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-8-raw.mov -f s16le +fate-pcm_u8-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-8-raw.mov -f s16le -af aresample FATE_SAMPLES_PCM-$(call DEMDEC, MOV, PCM_U8) += fate-pcm_u8-stereo -fate-pcm_u8-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-8-raw.mov -f s16le +fate-pcm_u8-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-8-raw.mov -f s16le -af aresample FATE_SAMPLES_PCM-$(call DEMDEC, W64, PCM_S16LE) += fate-w64 fate-w64: CMD = crc -i $(TARGET_SAMPLES)/w64/w64-pcm16.w64 diff -Nru ffmpeg-4.2.2/tests/fate/pixlet.mak ffmpeg-4.4/tests/fate/pixlet.mak --- ffmpeg-4.2.2/tests/fate/pixlet.mak 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/fate/pixlet.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,5 +1,5 @@ FATE_PIXLET += fate-pixlet-rgb -fate-pixlet-rgb: CMD = framecrc -i $(TARGET_SAMPLES)/pixlet/pixlet_rgb.mov -an -pix_fmt yuv420p16le +fate-pixlet-rgb: CMD = framecrc -i $(TARGET_SAMPLES)/pixlet/pixlet_rgb.mov -an -pix_fmt yuv420p16le -vf scale FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, PIXLET) += $(FATE_PIXLET) fate-pixlet: $(FATE_PIXLET) diff -Nru ffmpeg-4.2.2/tests/fate/prores.mak ffmpeg-4.4/tests/fate/prores.mak --- ffmpeg-4.2.2/tests/fate/prores.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/prores.mak 2021-04-08 21:28:40.000000000 +0000 @@ -11,15 +11,15 @@ FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, PRORES) += $(FATE_PRORES) fate-prores: $(FATE_PRORES) -fate-prores-422: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_422.mov -pix_fmt yuv422p10le -fate-prores-422_hq: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_422_HQ.mov -pix_fmt yuv422p10le -fate-prores-422_lt: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_422_LT.mov -pix_fmt yuv422p10le -fate-prores-422_proxy: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_422_Proxy.mov -pix_fmt yuv422p10le -fate-prores-alpha: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_with_Alpha.mov -pix_fmt yuva444p12le -fate-prores-alpha_skip: CMD = framecrc -flags +bitexact -skip_alpha 1 -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_with_Alpha.mov -pix_fmt yuv444p12le -fate-prores-transparency: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/prores4444_with_transparency.mov -pix_fmt yuva444p12le -fate-prores-transparency_skip: CMD = framecrc -flags +bitexact -skip_alpha 1 -i $(TARGET_SAMPLES)/prores/prores4444_with_transparency.mov -pix_fmt yuv444p12le -fate-prores-gray: CMD = framecrc -flags +bitexact -c:a aac_fixed -i $(TARGET_SAMPLES)/prores/gray.mov -pix_fmt yuv422p10le +fate-prores-422: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_422.mov -pix_fmt yuv422p10le -vf scale +fate-prores-422_hq: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_422_HQ.mov -pix_fmt yuv422p10le -vf scale +fate-prores-422_lt: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_422_LT.mov -pix_fmt yuv422p10le -vf scale +fate-prores-422_proxy: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_422_Proxy.mov -pix_fmt yuv422p10le -vf scale +fate-prores-alpha: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_with_Alpha.mov -pix_fmt yuva444p12le -vf scale +fate-prores-alpha_skip: CMD = framecrc -flags +bitexact -skip_alpha 1 -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_with_Alpha.mov -pix_fmt yuv444p12le -vf scale +fate-prores-transparency: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/prores4444_with_transparency.mov -pix_fmt yuva444p12le -vf scale +fate-prores-transparency_skip: CMD = framecrc -flags +bitexact -skip_alpha 1 -i $(TARGET_SAMPLES)/prores/prores4444_with_transparency.mov -pix_fmt yuv444p12le -vf scale +fate-prores-gray: CMD = framecrc -flags +bitexact -c:a aac_fixed -i $(TARGET_SAMPLES)/prores/gray.mov -pix_fmt yuv422p10le -vf scale -af aresample #Test bsf prores-metadata FATE_PRORES_METADATA_BSF += fate-prores-metadata diff -Nru ffmpeg-4.2.2/tests/fate/qt.mak ffmpeg-4.4/tests/fate/qt.mak --- ffmpeg-4.2.2/tests/fate/qt.mak 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/fate/qt.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,5 +1,5 @@ FATE_QT-$(call DEMDEC, MOV, EIGHTBPS) += fate-8bps -fate-8bps: CMD = framecrc -i $(TARGET_SAMPLES)/8bps/full9iron-partial.mov -pix_fmt rgb24 +fate-8bps: CMD = framecrc -i $(TARGET_SAMPLES)/8bps/full9iron-partial.mov -pix_fmt rgb24 -vf scale -af aresample FATE_QT-$(call DEMDEC, MOV, QDM2) += fate-qdm2 fate-qdm2: CMD = pcm -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-B-QDM2.mov @@ -14,22 +14,22 @@ fate-qt-alaw-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-B-alaw.mov -f s16le FATE_QT-$(call DEMDEC, MOV, ADPCM_IMA_QT) += fate-qt-ima4-mono -fate-qt-ima4-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-16-B-ima4.mov -f s16le +fate-qt-ima4-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-16-B-ima4.mov -f s16le -af aresample FATE_QT-$(call DEMDEC, MOV, ADPCM_IMA_QT) += fate-qt-ima4-stereo -fate-qt-ima4-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-B-ima4.mov -f s16le +fate-qt-ima4-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-B-ima4.mov -f s16le -af aresample FATE_QT-$(call DEMDEC, MOV, MACE3) += fate-qt-mac3-mono -fate-qt-mac3-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-8-MAC3.mov -f s16le +fate-qt-mac3-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-8-MAC3.mov -f s16le -af aresample FATE_QT-$(call DEMDEC, MOV, MACE3) += fate-qt-mac3-stereo -fate-qt-mac3-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-8-MAC3.mov -f s16le +fate-qt-mac3-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-8-MAC3.mov -f s16le -af aresample FATE_QT-$(call DEMDEC, MOV, MACE6) += fate-qt-mac6-mono -fate-qt-mac6-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-8-MAC6.mov -f s16le +fate-qt-mac6-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-8-MAC6.mov -f s16le -af aresample FATE_QT-$(call DEMDEC, MOV, MACE6) += fate-qt-mac6-stereo -fate-qt-mac6-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-8-MAC6.mov -f s16le +fate-qt-mac6-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-8-MAC6.mov -f s16le -af aresample FATE_QT-$(call DEMDEC, MOV, PCM_MULAW) += fate-qt-ulaw-mono fate-qt-ulaw-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-16-B-ulaw.mov -f s16le @@ -38,10 +38,10 @@ fate-qt-ulaw-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-B-ulaw.mov -f s16le FATE_QT-$(call DEMDEC, MOV, QDRAW) += fate-quickdraw -fate-quickdraw: CMD = framecrc -i $(TARGET_SAMPLES)/quickdraw/Airplane.mov -pix_fmt rgb24 +fate-quickdraw: CMD = framecrc -i $(TARGET_SAMPLES)/quickdraw/Airplane.mov -pix_fmt rgb24 -vf scale FATE_QT-$(call DEMDEC, MOV, RPZA) += fate-rpza -fate-rpza: CMD = framecrc -i $(TARGET_SAMPLES)/rpza/rpza2.mov -t 2 -pix_fmt rgb24 +fate-rpza: CMD = framecrc -i $(TARGET_SAMPLES)/rpza/rpza2.mov -t 2 -pix_fmt rgb24 -vf scale FATE_QT-$(call DEMDEC, MOV, SVQ1) += fate-svq1 fate-svq1: CMD = framecrc -i $(TARGET_SAMPLES)/svq1/marymary-shackles.mov -an -t 10 diff -Nru ffmpeg-4.2.2/tests/fate/qtrle.mak ffmpeg-4.4/tests/fate/qtrle.mak --- ffmpeg-4.2.2/tests/fate/qtrle.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/qtrle.mak 2021-04-08 21:28:40.000000000 +0000 @@ -2,22 +2,22 @@ fate-qtrle-1bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/Animation-Monochrome.mov -an FATE_QTRLE += fate-qtrle-2bit -fate-qtrle-2bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/Animation-4Greys.mov -pix_fmt rgb24 -an +fate-qtrle-2bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/Animation-4Greys.mov -pix_fmt rgb24 -an -vf scale FATE_QTRLE += fate-qtrle-4bit -fate-qtrle-4bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/Animation-16Greys.mov -pix_fmt rgb24 -an +fate-qtrle-4bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/Animation-16Greys.mov -pix_fmt rgb24 -an -vf scale FATE_QTRLE += fate-qtrle-8bit -fate-qtrle-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/criticalpath-credits.mov -pix_fmt rgb24 -an +fate-qtrle-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/criticalpath-credits.mov -pix_fmt rgb24 -an -vf scale FATE_QTRLE += fate-qtrle-16bit -fate-qtrle-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/mr-cork-rle.mov -pix_fmt rgb24 +fate-qtrle-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/mr-cork-rle.mov -pix_fmt rgb24 -vf scale FATE_QTRLE += fate-qtrle-24bit fate-qtrle-24bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/aletrek-rle.mov FATE_QTRLE += fate-qtrle-32bit -fate-qtrle-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/ultra_demo_720_480_32bpp_rle.mov -pix_fmt bgra +fate-qtrle-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/ultra_demo_720_480_32bpp_rle.mov -pix_fmt bgra -vf scale FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, QTRLE) += $(FATE_QTRLE) fate-qtrle: $(FATE_QTRLE) diff -Nru ffmpeg-4.2.2/tests/fate/screen.mak ffmpeg-4.4/tests/fate/screen.mak --- ffmpeg-4.2.2/tests/fate/screen.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/screen.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,6 +1,6 @@ # FIXME dropped frames in this test because of coarse timebase FATE_SCREEN-$(call DEMDEC, AVI, CSCD) += fate-cscd -fate-cscd: CMD = framecrc -i $(TARGET_SAMPLES)/CSCD/sample_video.avi -an -pix_fmt rgb24 +fate-cscd: CMD = framecrc -i $(TARGET_SAMPLES)/CSCD/sample_video.avi -an -pix_fmt rgb24 -vf scale FATE_SCREEN-$(call DEMDEC, AVI, DXTORY) += fate-dxtory fate-dxtory: CMD = framecrc -i $(TARGET_SAMPLES)/dxtory/dxtory_mic.avi -an @@ -27,7 +27,7 @@ fate-fraps-v2: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/test3-nosound-partial.avi FATE_FRAPS += fate-fraps-v3 -fate-fraps-v3: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/psclient-partial.avi -pix_fmt rgb24 +fate-fraps-v3: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/psclient-partial.avi -pix_fmt rgb24 -vf scale FATE_FRAPS += fate-fraps-v4 fate-fraps-v4: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/WoW_2006-11-03_14-58-17-19-nosound-partial.avi @@ -54,7 +54,7 @@ fate-iscc: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/pip.avi -an FATE_RSCC += fate-rscc-8bit -fate-rscc-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/8bpp.avi -an -pix_fmt rgb24 +fate-rscc-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/8bpp.avi -an -pix_fmt rgb24 -vf scale FATE_RSCC += fate-rscc-16bit fate-rscc-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/16bpp_555.avi -an @@ -84,10 +84,10 @@ fate-tdsc: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/tdsc/tdsc.asf -an -pix_fmt bgr24 FATE_TSCC += fate-tscc-15bit -fate-tscc-15bit: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/oneminute.avi -t 15 -pix_fmt rgb24 +fate-tscc-15bit: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/oneminute.avi -t 15 -pix_fmt rgb24 -vf scale FATE_TSCC += fate-tscc-32bit -fate-tscc-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/2004-12-17-uebung9-partial.avi -pix_fmt rgb24 -an +fate-tscc-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/2004-12-17-uebung9-partial.avi -pix_fmt rgb24 -an -vf scale FATE_SCREEN-$(call DEMDEC, AVI, TSCC) += $(FATE_TSCC) fate-tscc: $(FATE_TSCC) @@ -102,25 +102,25 @@ fate-tscc2: $(FATE_TSCC2-yes) FATE_VMNC += fate-vmnc-16bit -fate-vmnc-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/VMnc/test.avi -pix_fmt rgb24 +fate-vmnc-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/VMnc/test.avi -pix_fmt rgb24 -vf scale FATE_VMNC += fate-vmnc-32bit -fate-vmnc-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/VMnc/VS2k5DebugDemo-01-partial.avi -pix_fmt rgb24 +fate-vmnc-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/VMnc/VS2k5DebugDemo-01-partial.avi -pix_fmt rgb24 -vf scale FATE_SCREEN-$(call DEMDEC, AVI, VMNC) += $(FATE_VMNC) fate-vmnc: $(FATE_VMNC) FATE_ZMBV += fate-zmbv-8bit -fate-zmbv-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/zmbv/wc2_001-partial.avi -an -pix_fmt rgb24 +fate-zmbv-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/zmbv/wc2_001-partial.avi -an -pix_fmt rgb24 -vf scale FATE_ZMBV += fate-zmbv-15bit -fate-zmbv-15bit: CMD = framecrc -i $(TARGET_SAMPLES)/zmbv/zmbv_15bit.avi -pix_fmt rgb24 -t 25 +fate-zmbv-15bit: CMD = framecrc -i $(TARGET_SAMPLES)/zmbv/zmbv_15bit.avi -pix_fmt rgb24 -t 25 -vf scale FATE_ZMBV += fate-zmbv-16bit -fate-zmbv-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/zmbv/zmbv_16bit.avi -pix_fmt rgb24 -t 25 +fate-zmbv-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/zmbv/zmbv_16bit.avi -pix_fmt rgb24 -t 25 -vf scale FATE_ZMBV += fate-zmbv-32bit -fate-zmbv-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/zmbv/zmbv_32bit.avi -pix_fmt rgb24 -t 25 +fate-zmbv-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/zmbv/zmbv_32bit.avi -pix_fmt rgb24 -t 25 -vf scale FATE_SCREEN-$(call DEMDEC, AVI, ZMBV) += $(FATE_ZMBV) fate-zmbv: $(FATE_ZMBV) diff -Nru ffmpeg-4.2.2/tests/fate/seek.mak ffmpeg-4.4/tests/fate/seek.mak --- ffmpeg-4.2.2/tests/fate/seek.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/seek.mak 2021-04-08 21:28:40.000000000 +0000 @@ -64,7 +64,6 @@ FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, ASV2, AVI) += asv2 FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, DNXHD, DNXHD) += dnxhd-720p FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, DNXHD, DNXHD) += dnxhd-720p-rd -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, DNXHD, DNXHD) += dnxhd-4k-hr-lb FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, DNXHD, MOV) += dnxhd-1080i FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, DVVIDEO, DV) += dv FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, DVVIDEO, DV) += dv-411 @@ -80,6 +79,8 @@ FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, LJPEG MJPEG, AVI) += ljpeg FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MJPEG, AVI) += mjpeg +FATE_SEEK_VSYNTH_LENA-$(call ALLYES, DNXHD_ENCODER DNXHD_DECODER LARGE_TESTS) += dnxhd-4k-hr-lb + FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MPEG1VIDEO, MPEG1VIDEO MPEGVIDEO) += \ mpeg1 \ mpeg1b @@ -260,7 +261,7 @@ fate-seek-empty-edit-mp4: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/mov/empty_edit_5s.mp4 -duration 15 -frames 4 fate-seek-test-iibbibb-mp4: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/mov/test_iibbibb.mp4 -duration 13 -frames 4 fate-seek-test-iibbibb-neg-ctts-mp4: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/mov/test_iibbibb_neg_ctts.mp4 -duration 13 -frames 4 -fate-seek-cache-pipe: CMD = cat $(TARGET_SAMPLES)/gapless/gapless.mp3 | run libavformat/tests/seek$(EXESUF) cache:pipe:0 -read_ahead_limit -1 +fate-seek-cache-pipe: CMD = cat $(SAMPLES)/gapless/gapless.mp3 | run libavformat/tests/seek$(EXESUF) cache:pipe:0 -read_ahead_limit -1 fate-seek-mkv-codec-delay: CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/mkv/codec_delay_opus.mkv FATE_SEEK_EXTRA += $(FATE_SEEK_EXTRA-yes) @@ -269,6 +270,7 @@ $(FATE_SEEK) $(FATE_SAMPLES_SEEK) $(FATE_SEEK_EXTRA): libavformat/tests/seek$(EXESUF) $(FATE_SEEK) $(FATE_SAMPLES_SEEK): CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_PATH)/tests/data/$(SRC) $(FATE_SEEK) $(FATE_SAMPLES_SEEK): fate-seek-%: fate-% +$(subst fate-seek-,fate-,$(FATE_SAMPLES_SEEK) $(FATE_SEEK)): KEEP_OVERRIDE = -keep fate-seek-%: REF = $(SRC_PATH)/tests/ref/seek/$(@:fate-seek-%=%) FATE_AVCONV += $(FATE_SEEK) diff -Nru ffmpeg-4.2.2/tests/fate/subtitles.mak ffmpeg-4.4/tests/fate/subtitles.mak --- ffmpeg-4.2.2/tests/fate/subtitles.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/subtitles.mak 2021-04-08 21:28:40.000000000 +0000 @@ -103,6 +103,12 @@ FATE_SUBTITLES-$(call DEMDEC, SCC, CCAPTION) += fate-sub-scc fate-sub-scc: CMD = fmtstdout ass -ss 57 -i $(TARGET_SAMPLES)/sub/witch.scc +FATE_SUBTITLES-$(call ALLYES, MPEGTS_DEMUXER DVBSUB_DECODER DVBSUB_ENCODER) += fate-sub-dvb +fate-sub-dvb: CMD = framecrc -i $(TARGET_SAMPLES)/sub/dvbsubtest_filter.ts -map s:0 -c dvbsub + +FATE_SUBTITLES-$(call ALLYES, FILE_PROTOCOL PIPE_PROTOCOL SRT_DEMUXER SUBRIP_DECODER TTML_ENCODER TTML_MUXER) += fate-sub-ttmlenc +fate-sub-ttmlenc: CMD = fmtstdout ttml -i $(TARGET_SAMPLES)/sub/SubRip_capability_tester.srt + FATE_SUBTITLES-$(call ENCMUX, ASS, ASS) += $(FATE_SUBTITLES_ASS-yes) FATE_SUBTITLES += $(FATE_SUBTITLES-yes) diff -Nru ffmpeg-4.2.2/tests/fate/truehd.mak ffmpeg-4.4/tests/fate/truehd.mak --- ffmpeg-4.2.2/tests/fate/truehd.mak 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/fate/truehd.mak 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,17 @@ +FATE_TRUEHD-$(call DEMDEC, TRUEHD, TRUEHD) += fate-truehd-5.1 +fate-truehd-5.1: CMD = md5pipe -f truehd -i $(TARGET_SAMPLES)/lossless-audio/truehd_5.1.raw -f s32le +fate-truehd-5.1: CMP = oneline +fate-truehd-5.1: REF = 95d8aac39dd9f0d7fb83dc7b6f88df35 + +FATE_TRUEHD-$(call DEMDEC, TRUEHD, TRUEHD) += fate-truehd-5.1-downmix-2.0 +fate-truehd-5.1-downmix-2.0: CMD = md5pipe -f truehd -request_channel_layout 2 -i $(TARGET_SAMPLES)/lossless-audio/truehd_5.1.raw -f s32le +fate-truehd-5.1-downmix-2.0: CMP = oneline +fate-truehd-5.1-downmix-2.0: REF = a269aee0051d4400c9117136f08c9767 + +FATE_TRUEHD-$(call ALLYES, TRUEHD_DEMUXER TRUEHD_MUXER TRUEHD_CORE_BSF) += fate-truehd-core-bsf +fate-truehd-core-bsf: CMD = md5pipe -i $(TARGET_SAMPLES)/truehd/atmos.thd -c:a copy -bsf:a truehd_core -fflags +bitexact -f truehd +fate-truehd-core-bsf: CMP = oneline +fate-truehd-core-bsf: REF = 3aa5d0c7825051f3657b71fd6135183b + +FATE_SAMPLES_AUDIO += $(FATE_TRUEHD-yes) +fate-truehd: $(FATE_TRUEHD-yes) diff -Nru ffmpeg-4.2.2/tests/fate/utvideo.mak ffmpeg-4.4/tests/fate/utvideo.mak --- ffmpeg-4.2.2/tests/fate/utvideo.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/utvideo.mak 2021-04-08 21:28:40.000000000 +0000 @@ -67,7 +67,7 @@ FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, UTVIDEO) += $(FATE_UTVIDEO) fate-utvideo: $(FATE_UTVIDEO) -fate-utvideoenc%: CMD = framemd5 -f image2 -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -c:v utvideo -slices 1 -sws_flags +accurate_rnd+bitexact ${OPTS} +fate-utvideoenc%: CMD = framemd5 -f image2 -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -c:v utvideo -slices 1 -sws_flags +accurate_rnd+bitexact ${OPTS} -vf scale FATE_UTVIDEOENC += fate-utvideoenc_rgba_left fate-utvideoenc_rgba_left: OPTS = -pix_fmt gbrap -pred left diff -Nru ffmpeg-4.2.2/tests/fate/vcodec.mak ffmpeg-4.4/tests/fate/vcodec.mak --- ffmpeg-4.2.2/tests/fate/vcodec.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/vcodec.mak 2021-04-08 21:28:40.000000000 +0000 @@ -4,8 +4,8 @@ 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 "$(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)" -keep "$(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 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%: CMP_UNIT = 1 fate-vsynth%: REF = $(SRC_PATH)/tests/ref/vsynth/$(@:fate-%=%) @@ -29,13 +29,15 @@ dnxhd-720p-rd \ dnxhd-720p-10bit \ dnxhd-720p-hr-lb \ - dnxhd-4k-hr-lb \ - dnxhd-uhd-hr-sq \ - dnxhd-2k-hr-hq \ dnxhd-edge1-hr \ dnxhd-edge2-hr \ dnxhd-edge3-hr +FATE_VCODEC-$(call ALLYES, DNXHD_ENCODER DNXHD_DECODER LARGE_TESTS) += dnxhd-4k-hr-lb \ + dnxhd-2k-hr-hq \ + dnxhd-uhd-hr-sq + + FATE_VCODEC-$(call ENCDEC, VC2 DIRAC, MOV) += vc2-420p vc2-420p10 vc2-420p12 \ vc2-422p vc2-422p10 vc2-422p12 \ vc2-444p vc2-444p10 vc2-444p12 \ @@ -135,7 +137,7 @@ fate-vsynth%-dnxhd-hr-hq-mov: DECOPTS = -sws_flags area+accurate_rnd+bitexact fate-vsynth%-dnxhd-hr-hq-mov: FMT = mov -FATE_VCODEC-$(call ENCDEC, DVVIDEO, DV) += dv dv-411 dv-50 +FATE_VCODEC-$(call ENCDEC, DVVIDEO, DV) += dv dv-411 dv-50 dv-hd dv-fhd fate-vsynth%-dv: CODEC = dvvideo fate-vsynth%-dv: ENCOPTS = -dct int -s pal fate-vsynth%-dv: FMT = dv @@ -152,6 +154,18 @@ fate-vsynth%-dv-50: DECOPTS = -sws_flags neighbor fate-vsynth%-dv-50: FMT = dv +fate-vsynth%-dv-fhd: CODEC = dvvideo +fate-vsynth%-dv-fhd: ENCOPTS = -dct int -s 1440x1080 -pix_fmt yuv422p \ + -sws_flags neighbor +fate-vsynth%-dv-fhd: DECOPTS = -sws_flags neighbor +fate-vsynth%-dv-fhd: FMT = dv + +fate-vsynth%-dv-hd: CODEC = dvvideo +fate-vsynth%-dv-hd: ENCOPTS = -dct int -s 960x720 -pix_fmt yuv422p \ + -sws_flags neighbor +fate-vsynth%-dv-hd: DECOPTS = -sws_flags neighbor +fate-vsynth%-dv-hd: FMT = dv + FATE_VCODEC-$(call ENCDEC, FFV1, AVI) += ffv1 ffv1-v0 \ ffv1-v3-yuv420p ffv1-v3-yuv422p10 ffv1-v3-yuv444p16 \ ffv1-v3-bgr0 ffv1-v3-rgb48 @@ -309,7 +323,7 @@ fate-vsynth%-mpeg4-nsse: ENCOPTS = -qscale 7 -cmp nsse -subcmp nsse \ -mbcmp nsse -precmp nsse \ - -skipcmp nsse + -skip_cmp nsse fate-vsynth%-mpeg4-qpel: ENCOPTS = -qscale 7 -flags +mv4+qpel -mbd 2 \ -bf 2 -cmp 1 -subcmp 2 diff -Nru ffmpeg-4.2.2/tests/fate/video.mak ffmpeg-4.4/tests/fate/video.mak --- ffmpeg-4.2.2/tests/fate/video.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/video.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,17 +1,17 @@ FATE_4XM += fate-4xm-1 -fate-4xm-1: CMD = framecrc -i $(TARGET_SAMPLES)/4xm/version1.4xm -pix_fmt rgb24 -an +fate-4xm-1: CMD = framecrc -i $(TARGET_SAMPLES)/4xm/version1.4xm -pix_fmt rgb24 -an -vf scale FATE_4XM += fate-4xm-2 -fate-4xm-2: CMD = framecrc -i $(TARGET_SAMPLES)/4xm/version2.4xm -pix_fmt rgb24 -an +fate-4xm-2: CMD = framecrc -i $(TARGET_SAMPLES)/4xm/version2.4xm -pix_fmt rgb24 -an -vf scale FATE_VIDEO-$(call DEMDEC, FOURXM, FOURXM) += $(FATE_4XM) fate-4xm: $(FATE_4XM) FATE_VIDEO-$(call DEMDEC, AVI, ZERO12V) += fate-012v -fate-012v: CMD = framecrc -i $(TARGET_SAMPLES)/012v/sample.avi -pix_fmt yuv422p16le +fate-012v: CMD = framecrc -i $(TARGET_SAMPLES)/012v/sample.avi -pix_fmt yuv422p16le -vf scale FATE_VIDEO-$(call DEMDEC, AVI, AASC) += fate-aasc -fate-aasc: CMD = framecrc -i $(TARGET_SAMPLES)/aasc/AASC-1.5MB.AVI -pix_fmt rgb24 +fate-aasc: CMD = framecrc -i $(TARGET_SAMPLES)/aasc/AASC-1.5MB.AVI -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, MOV, AIC) += fate-aic fate-aic: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/aic/small_apple_intermediate_codec.mov -an -frames:v 15 @@ -20,19 +20,19 @@ fate-aic-oddsize: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/aic/aic_odd_dimensions.mov FATE_VIDEO-$(call DEMDEC, MM, MMVIDEO) += fate-alg-mm -fate-alg-mm: CMD = framecrc -i $(TARGET_SAMPLES)/alg-mm/ibmlogo.mm -an -pix_fmt rgb24 +fate-alg-mm: CMD = framecrc -i $(TARGET_SAMPLES)/alg-mm/ibmlogo.mm -an -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, AVI, AMV) += fate-amv fate-amv: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/amv/MTV_high_res_320x240_sample_Penguin_Joke_MTV_from_WMV.amv -t 10 -an FATE_VIDEO-$(call DEMDEC, TTY, ANSI) += fate-ansi -fate-ansi: CMD = framecrc -chars_per_frame 44100 -i $(TARGET_SAMPLES)/ansi/TRE-IOM5.ANS -pix_fmt rgb24 +fate-ansi: CMD = framecrc -chars_per_frame 44100 -i $(TARGET_SAMPLES)/ansi/TRE-IOM5.ANS -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, TTY, ANSI) += fate-ansi256 -fate-ansi256: CMD = framecrc -chars_per_frame 44100 -i $(TARGET_SAMPLES)/ansi/ansi256.ans -pix_fmt rgb24 +fate-ansi256: CMD = framecrc -chars_per_frame 44100 -i $(TARGET_SAMPLES)/ansi/ansi256.ans -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, RPL, ESCAPE124) += fate-armovie-escape124 -fate-armovie-escape124: CMD = framecrc -i $(TARGET_SAMPLES)/rpl/ESCAPE.RPL -pix_fmt rgb24 +fate-armovie-escape124: CMD = framecrc -i $(TARGET_SAMPLES)/rpl/ESCAPE.RPL -pix_fmt rgb24 -vf scale -af aresample FATE_VIDEO-$(call DEMDEC, RPL, ESCAPE130) += fate-armovie-escape130 fate-armovie-escape130: CMD = framecrc -i $(TARGET_SAMPLES)/rpl/landing.rpl -an @@ -43,11 +43,17 @@ FATE_VIDEO-$(call DEMDEC, AVI, AURA2) += fate-auravision-v2 fate-auravision-v2: CMD = framecrc -i $(TARGET_SAMPLES)/auravision/salma-hayek-in-ugly-betty-partial-avi -an +FATE_VIDEO-$(call DEMDEC, AVI, AVRN) += fate-avid-interlaced +fate-avid-interlaced: CMD = framecrc -i $(TARGET_SAMPLES)/avid/avid_ntsc_interlaced.avi + +FATE_VIDEO-$(call DEMDEC, MOV, MJPEG) += fate-avid-meridian +fate-avid-meridian: CMD = framecrc -i $(TARGET_SAMPLES)/avid/avidmeridianntsc.mov + FATE_VIDEO-$(call DEMDEC, BETHSOFTVID, BETHSOFTVID) += fate-bethsoft-vid -fate-bethsoft-vid: CMD = framecrc -i $(TARGET_SAMPLES)/bethsoft-vid/ANIM0001.VID -t 5 -pix_fmt rgb24 +fate-bethsoft-vid: CMD = framecrc -i $(TARGET_SAMPLES)/bethsoft-vid/ANIM0001.VID -t 5 -pix_fmt rgb24 -vf scale -af aresample FATE_VIDEO-$(call DEMDEC, BFI, BFI) += fate-bfi -fate-bfi: CMD = framecrc -i $(TARGET_SAMPLES)/bfi/2287.bfi -pix_fmt rgb24 +fate-bfi: CMD = framecrc -i $(TARGET_SAMPLES)/bfi/2287.bfi -pix_fmt rgb24 -vf scale -af aresample FATE_BINK_VIDEO += fate-bink-video-b fate-bink-video-b: CMD = framecrc -i $(TARGET_SAMPLES)/bink/RISE.BIK -frames 30 @@ -61,22 +67,22 @@ FATE_VIDEO-$(call DEMDEC, BINK, BINK) += $(FATE_BINK_VIDEO) FATE_VIDEO-$(call DEMDEC, BMV, BMV_VIDEO) += fate-bmv-video -fate-bmv-video: CMD = framecrc -i $(TARGET_SAMPLES)/bmv/SURFING-partial.BMV -pix_fmt rgb24 -an +fate-bmv-video: CMD = framecrc -i $(TARGET_SAMPLES)/bmv/SURFING-partial.BMV -pix_fmt rgb24 -an -vf scale -vf scale FATE_VIDEO-$(call DEMDEC, MPEGPS, CAVS) += fate-cavs fate-cavs: CMD = framecrc -i $(TARGET_SAMPLES)/cavs/cavs.mpg -an FATE_VIDEO-$(call DEMDEC, CDG, CDGRAPHICS) += fate-cdgraphics -fate-cdgraphics: CMD = framecrc -i $(TARGET_SAMPLES)/cdgraphics/BrotherJohn.cdg -pix_fmt rgba -t 1 +fate-cdgraphics: CMD = framecrc -i $(TARGET_SAMPLES)/cdgraphics/BrotherJohn.cdg -pix_fmt rgba -t 1 -vf scale FATE_CFHD-$(CONFIG_AVI_DEMUXER) += fate-cfhd-1 -fate-cfhd-1: CMD = framecrc -i $(TARGET_SAMPLES)/cfhd/cfhd_422.avi -pix_fmt yuv422p10le +fate-cfhd-1: CMD = framecrc -i $(TARGET_SAMPLES)/cfhd/cfhd_422.avi -pix_fmt yuv422p10le -vf scale FATE_CFHD-$(CONFIG_AVI_DEMUXER) += fate-cfhd-2 -fate-cfhd-2: CMD = framecrc -i $(TARGET_SAMPLES)/cfhd/cfhd_444.avi -pix_fmt gbrp12le +fate-cfhd-2: CMD = framecrc -i $(TARGET_SAMPLES)/cfhd/cfhd_444.avi -pix_fmt gbrp12le -vf scale FATE_CFHD-$(CONFIG_MOV_DEMUXER) += fate-cfhd-3 -fate-cfhd-3: CMD = framecrc -i $(TARGET_SAMPLES)/cfhd/cfhd_odd.mov -pix_fmt yuv422p10le +fate-cfhd-3: CMD = framecrc -i $(TARGET_SAMPLES)/cfhd/cfhd_odd.mov -pix_fmt yuv422p10le -vf scale FATE_VIDEO-$(CONFIG_CFHD_DECODER) += $(FATE_CFHD-yes) fate-cfhd: $(FATE_CFHD-yes) @@ -85,16 +91,16 @@ fate-cljr: CMD = framecrc -i $(TARGET_SAMPLES)/cljr/testcljr-partial.avi FATE_VIDEO-$(call DEMDEC, AVI, PNG) += fate-corepng -fate-corepng: CMD = framecrc -i $(TARGET_SAMPLES)/png1/corepng-partial.avi +fate-corepng: CMD = framecrc -i $(TARGET_SAMPLES)/png1/corepng-partial.avi -vf scale -af aresample FATE_VIDEO-$(call DEMDEC, AVI, PNG) += fate-rgbapng-4816 fate-rgbapng-4816: CMD = framecrc -i $(TARGET_SAMPLES)/png1/55c99e750a5fd6_50314226.png FATE_VIDEO-$(call DEMDEC, AVS, AVS) += fate-creatureshock-avs -fate-creatureshock-avs: CMD = framecrc -i $(TARGET_SAMPLES)/creatureshock-avs/OUTATIME.AVS -pix_fmt rgb24 +fate-creatureshock-avs: CMD = framecrc -i $(TARGET_SAMPLES)/creatureshock-avs/OUTATIME.AVS -pix_fmt rgb24 -vf scale -af aresample FATE_CVID-$(CONFIG_MOV_DEMUXER) += fate-cvid-palette -fate-cvid-palette: CMD = framecrc -i $(TARGET_SAMPLES)/cvid/catfight-cvid-pal8-partial.mov -pix_fmt rgb24 -an +fate-cvid-palette: CMD = framecrc -i $(TARGET_SAMPLES)/cvid/catfight-cvid-pal8-partial.mov -pix_fmt rgb24 -an -vf scale FATE_CVID-$(CONFIG_AVI_DEMUXER) += fate-cvid-partial fate-cvid-partial: CMD = framecrc -i $(TARGET_SAMPLES)/cvid/laracroft-cinepak-partial.avi -an @@ -106,16 +112,16 @@ fate-cvid: $(FATE_CVID-yes) FATE_VIDEO-$(call DEMDEC, C93, C93) += fate-cyberia-c93 -fate-cyberia-c93: CMD = framecrc -i $(TARGET_SAMPLES)/cyberia-c93/intro1.c93 -t 3 -pix_fmt rgb24 +fate-cyberia-c93: CMD = framecrc -i $(TARGET_SAMPLES)/cyberia-c93/intro1.c93 -t 3 -pix_fmt rgb24 -vf scale -af aresample FATE_VIDEO-$(call DEMDEC, AVI, CYUV) += fate-cyuv fate-cyuv: CMD = framecrc -i $(TARGET_SAMPLES)/cyuv/cyuv.avi FATE_VIDEO-$(call DEMDEC, DSICIN, DSICINVIDEO) += fate-delphine-cin-video -fate-delphine-cin-video: CMD = framecrc -i $(TARGET_SAMPLES)/delphine-cin/LOGO-partial.CIN -pix_fmt rgb24 -an +fate-delphine-cin-video: CMD = framecrc -i $(TARGET_SAMPLES)/delphine-cin/LOGO-partial.CIN -pix_fmt rgb24 -an -vf scale FATE_VIDEO-$(call DEMDEC, ANM, ANM) += fate-deluxepaint-anm -fate-deluxepaint-anm: CMD = framecrc -i $(TARGET_SAMPLES)/deluxepaint-anm/INTRO1.ANM -pix_fmt rgb24 +fate-deluxepaint-anm: CMD = framecrc -i $(TARGET_SAMPLES)/deluxepaint-anm/INTRO1.ANM -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, DIRAC, DIRAC) += fate-dirac fate-dirac: CMD = framecrc -i $(TARGET_SAMPLES)/dirac/vts.profile-main.drc @@ -124,10 +130,10 @@ fate-dirac-low-delay: CMD = framecrc -i $(TARGET_SAMPLES)/dirac/vts.profile-vc2-low-delay.drc FATE_DXA += fate-dxa-feeble -fate-dxa-feeble: CMD = framecrc -i $(TARGET_SAMPLES)/dxa/meetsquid.dxa -t 2 -pix_fmt rgb24 -an +fate-dxa-feeble: CMD = framecrc -i $(TARGET_SAMPLES)/dxa/meetsquid.dxa -t 2 -pix_fmt rgb24 -an -vf scale FATE_DXA += fate-dxa-scummvm -fate-dxa-scummvm: CMD = framecrc -i $(TARGET_SAMPLES)/dxa/scummvm.dxa -pix_fmt rgb24 +fate-dxa-scummvm: CMD = framecrc -i $(TARGET_SAMPLES)/dxa/scummvm.dxa -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, DXA, DXA) += $(FATE_DXA) fate-dxa: $(FATE_DXA) @@ -151,13 +157,13 @@ fate-film-cvid: CMD = framecrc -i $(TARGET_SAMPLES)/film/logo-capcom.cpk -an FATE_FLIC += fate-flic-af11-palette-change -fate-flic-af11-palette-change: CMD = framecrc -i $(TARGET_SAMPLES)/fli/fli-engines.fli -t 3.31 -pix_fmt rgb24 +fate-flic-af11-palette-change: CMD = framecrc -i $(TARGET_SAMPLES)/fli/fli-engines.fli -t 3.31 -pix_fmt rgb24 -vf scale FATE_FLIC += fate-flic-af12 -fate-flic-af12: CMD = framecrc -i $(TARGET_SAMPLES)/fli/jj00c2.fli -pix_fmt rgb24 +fate-flic-af12: CMD = framecrc -i $(TARGET_SAMPLES)/fli/jj00c2.fli -pix_fmt rgb24 -vf scale FATE_FLIC += fate-flic-magiccarpet -fate-flic-magiccarpet: CMD = framecrc -i $(TARGET_SAMPLES)/fli/intel.dat -pix_fmt rgb24 +fate-flic-magiccarpet: CMD = framecrc -i $(TARGET_SAMPLES)/fli/intel.dat -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, FLIC, FLIC) += $(FATE_FLIC) fate-flic: $(FATE_FLIC) @@ -166,40 +172,43 @@ fate-frwu: CMD = framecrc -i $(TARGET_SAMPLES)/frwu/frwu.avi FATE_VIDEO-$(call DEMDEC, IDCIN, IDCIN) += fate-id-cin-video -fate-id-cin-video: CMD = framecrc -i $(TARGET_SAMPLES)/idcin/idlog-2MB.cin -pix_fmt rgb24 +fate-id-cin-video: CMD = framecrc -i $(TARGET_SAMPLES)/idcin/idlog-2MB.cin -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call ENCDEC, ROQ PGMYUV, ROQ IMAGE2) += fate-idroq-video-encode -fate-idroq-video-encode: CMD = md5 -f image2 -c:v pgmyuv -i $(TARGET_SAMPLES)/ffmpeg-synthetic/vsynth1/%02d.pgm -r 30 -sws_flags +bitexact -vf pad=512:512:80:112 -f roq -t 0.2 +fate-idroq-video-encode: CMD = md5 -auto_conversion_filters -f image2 -c:v pgmyuv -i $(TARGET_SAMPLES)/ffmpeg-synthetic/vsynth1/%02d.pgm -r 30 -sws_flags +bitexact -vf pad=512:512:80:112 -f roq -t 0.2 FATE_IFF-$(CONFIG_IFF_ILBM_DECODER) += fate-iff-byterun1 -fate-iff-byterun1: CMD = framecrc -i $(TARGET_SAMPLES)/iff/ASH.LBM -pix_fmt rgb24 +fate-iff-byterun1: CMD = framecrc -i $(TARGET_SAMPLES)/iff/ASH.LBM -pix_fmt rgb24 -vf scale FATE_IFF-$(CONFIG_EIGHTSVX_FIB_DECODER) += fate-iff-fibonacci -fate-iff-fibonacci: CMD = md5 -i $(TARGET_SAMPLES)/iff/dasboot-in-compressed -f s16le +fate-iff-fibonacci: CMD = md5 -i $(TARGET_SAMPLES)/iff/dasboot-in-compressed -f s16le -vf scale -af aresample FATE_IFF-$(CONFIG_IFF_ILBM_DECODER) += fate-iff-ilbm -fate-iff-ilbm: CMD = framecrc -i $(TARGET_SAMPLES)/iff/lms-matriks.ilbm -pix_fmt rgb24 +fate-iff-ilbm: CMD = framecrc -i $(TARGET_SAMPLES)/iff/lms-matriks.ilbm -pix_fmt rgb24 -vf scale FATE_VIDEO-$(CONFIG_IFF_DEMUXER) += $(FATE_IFF-yes) fate-iff: $(FATE_IFF-yes) FATE_VIDEO-$(call DEMDEC, IPMOVIE, INTERPLAY_VIDEO) += fate-interplay-mve-8bit -fate-interplay-mve-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/interplay-mve/interplay-logo-2MB.mve -pix_fmt rgb24 -an +fate-interplay-mve-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/interplay-mve/interplay-logo-2MB.mve -pix_fmt rgb24 -an -vf scale FATE_VIDEO-$(call DEMDEC, IPMOVIE, INTERPLAY_VIDEO) += fate-interplay-mve-16bit -fate-interplay-mve-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/interplay-mve/descent3-level5-16bit-partial.mve -pix_fmt rgb24 -an +fate-interplay-mve-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/interplay-mve/descent3-level5-16bit-partial.mve -pix_fmt rgb24 -an -vf scale FATE_VIDEO-$(call DEMDEC, MXF, JPEG2000) += fate-jpeg2000-dcinema -fate-jpeg2000-dcinema: CMD = framecrc -flags +bitexact -c:v jpeg2000 -i $(TARGET_SAMPLES)/jpeg2000/chiens_dcinema2K.mxf -pix_fmt xyz12le +fate-jpeg2000-dcinema: CMD = framecrc -flags +bitexact -c:v jpeg2000 -i $(TARGET_SAMPLES)/jpeg2000/chiens_dcinema2K.mxf -pix_fmt xyz12le -vf scale FATE_VIDEO-$(call DEMDEC, JV, JV) += fate-jv -fate-jv: CMD = framecrc -i $(TARGET_SAMPLES)/jv/intro.jv -an -pix_fmt rgb24 +fate-jv: CMD = framecrc -i $(TARGET_SAMPLES)/jv/intro.jv -an -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, AVI, KGV1) += fate-kgv1 -fate-kgv1: CMD = framecrc -i $(TARGET_SAMPLES)/kega/kgv1.avi -pix_fmt rgb555le -an +fate-kgv1: CMD = framecrc -i $(TARGET_SAMPLES)/kega/kgv1.avi -pix_fmt rgb555le -an -vf scale FATE_VIDEO-$(call DEMDEC, AVI, KMVC) += fate-kmvc -fate-kmvc: CMD = framecrc -i $(TARGET_SAMPLES)/KMVC/LOGO1.AVI -an -t 3 -pix_fmt rgb24 +fate-kmvc: CMD = framecrc -i $(TARGET_SAMPLES)/KMVC/LOGO1.AVI -an -t 3 -pix_fmt rgb24 -vf scale + +FATE_VIDEO-$(call DEMDEC, AVI, LSCR) += fate-lscr +fate-lscr: CMD = framecrc -i $(TARGET_SAMPLES)/lscr/lscr_compr9_short.avi FATE_MAGICYUV += fate-magicyuv-y4444i \ fate-magicyuv-y400i \ @@ -232,8 +241,11 @@ FATE_VIDEO-$(call DEMDEC, MOV, MJPEGB) += fate-mjpegb fate-mjpegb: CMD = framecrc -idct simple -fflags +bitexact -i $(TARGET_SAMPLES)/mjpegb/mjpegb_part.mov -an +FATE_VIDEO-$(call DEMDEC, AVI, MJPEG) += fate-mjpeg-ticket3229 +fate-mjpeg-ticket3229: CMD = framecrc -idct simple -fflags +bitexact -i $(TARGET_SAMPLES)/mjpeg/mjpeg_field_order.avi -an + FATE_VIDEO-$(call DEMDEC, MVI, MOTIONPIXELS) += fate-motionpixels -fate-motionpixels: CMD = framecrc -i $(TARGET_SAMPLES)/motion-pixels/INTRO-partial.MVI -an -pix_fmt rgb24 -frames:v 111 +fate-motionpixels: CMD = framecrc -i $(TARGET_SAMPLES)/motion-pixels/INTRO-partial.MVI -an -pix_fmt rgb24 -frames:v 111 -vf scale FATE_VIDEO-$(call DEMDEC, MPEGTS, MPEG2VIDEO) += fate-mpeg2-field-enc fate-mpeg2-ticket186 fate-mpeg2-field-enc: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -an -frames:v 30 @@ -243,13 +255,13 @@ fate-mpeg2-ticket6024: CMD = framecrc -flags +bitexact -idct simple -flags +truncated -i $(TARGET_SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg -an FATE_VIDEO-$(call DEMDEC, MPEGVIDEO, MPEG2VIDEO) += fate-mpeg2-ticket6677 -fate-mpeg2-ticket6677: CMD = framecrc -flags +bitexact -idct simple -vsync drop -i $(TARGET_SAMPLES)/mpeg2/sony-ct3.bs +fate-mpeg2-ticket6677: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/sony-ct3.bs FATE_VIDEO-$(call DEMDEC, MV, MVC1) += fate-mv-mvc1 -fate-mv-mvc1: CMD = framecrc -i $(TARGET_SAMPLES)/mv/posture.mv -an -frames 25 -pix_fmt rgb555le +fate-mv-mvc1: CMD = framecrc -i $(TARGET_SAMPLES)/mv/posture.mv -an -frames 25 -pix_fmt rgb555le -vf scale FATE_VIDEO-$(call DEMDEC, MV, MVC2) += fate-mv-mvc2 -fate-mv-mvc2: CMD = framecrc -i $(TARGET_SAMPLES)/mv/12345.mv -an -frames 30 -pix_fmt bgra +fate-mv-mvc2: CMD = framecrc -i $(TARGET_SAMPLES)/mv/12345.mv -an -frames 30 -pix_fmt bgra -vf scale FATE_VIDEO-$(call DEMDEC, MV, SGIRLE) += fate-mv-sgirle fate-mv-sgirle: CMD = framecrc -i $(TARGET_SAMPLES)/mv/pet-rle.movie -an @@ -268,43 +280,43 @@ fate-nuv: $(FATE_NUV) FATE_VIDEO-$(call DEMDEC, PAF, PAF_VIDEO) += fate-paf-video -fate-paf-video: CMD = framecrc -i $(TARGET_SAMPLES)/paf/hod1-partial.paf -pix_fmt rgb24 -an +fate-paf-video: CMD = framecrc -i $(TARGET_SAMPLES)/paf/hod1-partial.paf -pix_fmt rgb24 -an -vf scale FATE_VIDEO-$(call DEMDEC, AVI, QPEG) += fate-qpeg -fate-qpeg: CMD = framecrc -i $(TARGET_SAMPLES)/qpeg/Clock.avi -an -pix_fmt rgb24 +fate-qpeg: CMD = framecrc -i $(TARGET_SAMPLES)/qpeg/Clock.avi -an -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, AVI, R210) += fate-r210 -fate-r210: CMD = framecrc -i $(TARGET_SAMPLES)/r210/r210.avi -pix_fmt rgb48le +fate-r210: CMD = framecrc -i $(TARGET_SAMPLES)/r210/r210.avi -pix_fmt rgb48le -vf scale FATE_VIDEO-$(call DEMDEC, RL2, RL2) += fate-rl2 -fate-rl2: CMD = framecrc -i $(TARGET_SAMPLES)/rl2/Z4915300.RL2 -pix_fmt rgb24 -an +fate-rl2: CMD = framecrc -i $(TARGET_SAMPLES)/rl2/Z4915300.RL2 -pix_fmt rgb24 -an -vf scale FATE_VIDEO-$(call DEMDEC, ROQ, ROQ) += fate-roqvideo fate-roqvideo: CMD = framecrc -i $(TARGET_SAMPLES)/idroq/idlogo.roq -an FATE_VIDEO-$(call DEMDEC, SMUSH, SANM) += fate-sanm -fate-sanm: CMD = framecrc -i $(TARGET_SAMPLES)/smush/ronin_part.znm -an -pix_fmt rgb24 +fate-sanm: CMD = framecrc -i $(TARGET_SAMPLES)/smush/ronin_part.znm -an -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, VMD, VMDVIDEO) += fate-sierra-vmd-video -fate-sierra-vmd-video: CMD = framecrc -i $(TARGET_SAMPLES)/vmd/12.vmd -pix_fmt rgb24 -an +fate-sierra-vmd-video: CMD = framecrc -i $(TARGET_SAMPLES)/vmd/12.vmd -pix_fmt rgb24 -an -vf scale FATE_VIDEO-$(call DEMDEC, SMACKER, SMACKER) += fate-smacker-video -fate-smacker-video: CMD = framecrc -i $(TARGET_SAMPLES)/smacker/wetlogo.smk -pix_fmt rgb24 -an +fate-smacker-video: CMD = framecrc -i $(TARGET_SAMPLES)/smacker/wetlogo.smk -pix_fmt rgb24 -an -vf scale FATE_VIDEO-$(call DEMDEC, MOV, SMC) += fate-smc -fate-smc: CMD = framecrc -i $(TARGET_SAMPLES)/smc/cass_schi.qt -pix_fmt rgb24 +fate-smc: CMD = framecrc -i $(TARGET_SAMPLES)/smc/cass_schi.qt -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, AVI, SP5X) += fate-sp5x -fate-sp5x: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/sp5x/sp5x_problem.avi +fate-sp5x: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/sp5x/sp5x_problem.avi -vf scale -af aresample FATE_VIDEO-$(call DEMDEC, THP, THP) += fate-thp fate-thp: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/thp/pikmin2-opening1-partial.thp -an FATE_VIDEO-$(call DEMDEC, TIERTEXSEQ, TIERTEXSEQVIDEO) += fate-tiertex-seq -fate-tiertex-seq: CMD = framecrc -i $(TARGET_SAMPLES)/tiertex-seq/Gameover.seq -pix_fmt rgb24 +fate-tiertex-seq: CMD = framecrc -i $(TARGET_SAMPLES)/tiertex-seq/Gameover.seq -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, TMV, TMV) += fate-tmv -fate-tmv: CMD = framecrc -i $(TARGET_SAMPLES)/tmv/pop-partial.tmv -pix_fmt rgb24 +fate-tmv: CMD = framecrc -i $(TARGET_SAMPLES)/tmv/pop-partial.tmv -pix_fmt rgb24 -vf scale -af aresample FATE_TXD += fate-txd-16bpp fate-txd-16bpp: CMD = framecrc -i $(TARGET_SAMPLES)/txd/misc.txd -an @@ -313,7 +325,7 @@ fate-txd-odd: CMD = framecrc -i $(TARGET_SAMPLES)/txd/odd.txd -an FATE_TXD += fate-txd-pal8 -fate-txd-pal8: CMD = framecrc -i $(TARGET_SAMPLES)/txd/outro.txd -pix_fmt rgb24 -an +fate-txd-pal8: CMD = framecrc -i $(TARGET_SAMPLES)/txd/outro.txd -pix_fmt rgb24 -an -vf scale FATE_VIDEO-$(call DEMDEC, TXD, TXD) += $(FATE_TXD) fate-txd: $(FATE_TXD) @@ -322,17 +334,17 @@ fate-ulti: CMD = framecrc -i $(TARGET_SAMPLES)/ulti/hit12w.avi -an FATE_VIDEO-$(call DEMDEC, AVI, V210) += fate-v210 -fate-v210: CMD = framecrc -i $(TARGET_SAMPLES)/v210/v210_720p-partial.avi -pix_fmt yuv422p16be -an +fate-v210: CMD = framecrc -i $(TARGET_SAMPLES)/v210/v210_720p-partial.avi -pix_fmt yuv422p16be -an -vf scale FATE_VIDEO-$(call DEMDEC, MOV, V410) += fate-v410dec -fate-v410dec: CMD = framecrc -i $(TARGET_SAMPLES)/v410/lenav410.mov -pix_fmt yuv444p10le +fate-v410dec: CMD = framecrc -i $(TARGET_SAMPLES)/v410/lenav410.mov -pix_fmt yuv444p10le -vf scale FATE_VIDEO-$(call ENCDEC, V410 PGMYUV, AVI IMAGE2) += fate-v410enc fate-v410enc: $(VREF) -fate-v410enc: CMD = md5 -f image2 -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -fflags +bitexact -c:v v410 -f avi +fate-v410enc: CMD = md5 -f image2 -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -fflags +bitexact -c:v v410 -f avi -vf scale FATE_VIDEO-$(call DEMDEC, SIFF, VB) += fate-vb -fate-vb: CMD = framecrc -i $(TARGET_SAMPLES)/SIFF/INTRO_B.VB -t 3 -pix_fmt rgb24 -an +fate-vb: CMD = framecrc -i $(TARGET_SAMPLES)/SIFF/INTRO_B.VB -t 3 -pix_fmt rgb24 -an -vf scale FATE_VIDEO-$(call DEMDEC, AVI, VCR1) += fate-vcr1 fate-vcr1: CMD = framecrc -i $(TARGET_SAMPLES)/vcr1/VCR1test.avi -an @@ -344,16 +356,16 @@ fate-videoxl: CMD = framecrc -i $(TARGET_SAMPLES)/vixl/pig-vixl.avi FATE_VIDEO-$(call DEMDEC, WSVQA, VQA) += fate-vqa-cc -fate-vqa-cc: CMD = framecrc -i $(TARGET_SAMPLES)/vqa/cc-demo1-partial.vqa -pix_fmt rgb24 -an +fate-vqa-cc: CMD = framecrc -i $(TARGET_SAMPLES)/vqa/cc-demo1-partial.vqa -pix_fmt rgb24 -an -vf scale FATE_VIDEO-$(call DEMDEC, WC3, XAN_WC3) += fate-wc3movie-xan -fate-wc3movie-xan: CMD = framecrc -i $(TARGET_SAMPLES)/wc3movie/SC_32-part.MVE -pix_fmt rgb24 +fate-wc3movie-xan: CMD = framecrc -i $(TARGET_SAMPLES)/wc3movie/SC_32-part.MVE -pix_fmt rgb24 -vf scale FATE_VIDEO-$(call DEMDEC, AVI, WNV1) += fate-wnv1 fate-wnv1: CMD = framecrc -i $(TARGET_SAMPLES)/wnv1/wnv1-codec.avi -an FATE_VIDEO-$(call DEMDEC, YOP, YOP) += fate-yop -fate-yop: CMD = framecrc -i $(TARGET_SAMPLES)/yop/test1.yop -pix_fmt rgb24 -an +fate-yop: CMD = framecrc -i $(TARGET_SAMPLES)/yop/test1.yop -pix_fmt rgb24 -an -vf scale FATE_VIDEO-$(call DEMDEC, AVI, XAN_WC4) += fate-xxan-wc4 fate-xxan-wc4: CMD = framecrc -i $(TARGET_SAMPLES)/wc4-xan/wc4trailer-partial.avi -an diff -Nru ffmpeg-4.2.2/tests/fate/voice.mak ffmpeg-4.4/tests/fate/voice.mak --- ffmpeg-4.2.2/tests/fate/voice.mak 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/fate/voice.mak 2021-04-08 21:28:40.000000000 +0000 @@ -10,28 +10,28 @@ fate-g722: $(FATE_G722-yes) FATE_G723_1 += fate-g723_1-dec-1 -fate-g723_1-dec-1: CMD = framecrc -postfilter 0 -i $(TARGET_SAMPLES)/g723_1/ineqd53.tco +fate-g723_1-dec-1: CMD = framecrc -postfilter 0 -i $(TARGET_SAMPLES)/g723_1/ineqd53.tco -af aresample FATE_G723_1 += fate-g723_1-dec-2 -fate-g723_1-dec-2: CMD = framecrc -postfilter 0 -i $(TARGET_SAMPLES)/g723_1/overd53.tco +fate-g723_1-dec-2: CMD = framecrc -postfilter 0 -i $(TARGET_SAMPLES)/g723_1/overd53.tco -af aresample FATE_G723_1 += fate-g723_1-dec-3 -fate-g723_1-dec-3: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/overd63p.tco +fate-g723_1-dec-3: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/overd63p.tco -af aresample FATE_G723_1 += fate-g723_1-dec-4 -fate-g723_1-dec-4: CMD = framecrc -postfilter 0 -i $(TARGET_SAMPLES)/g723_1/pathd53.tco +fate-g723_1-dec-4: CMD = framecrc -postfilter 0 -i $(TARGET_SAMPLES)/g723_1/pathd53.tco -af aresample FATE_G723_1 += fate-g723_1-dec-5 -fate-g723_1-dec-5: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/pathd63p.tco +fate-g723_1-dec-5: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/pathd63p.tco -af aresample FATE_G723_1 += fate-g723_1-dec-6 -fate-g723_1-dec-6: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/tamed63p.tco +fate-g723_1-dec-6: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/tamed63p.tco -af aresample FATE_G723_1 += fate-g723_1-dec-7 -fate-g723_1-dec-7: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/dtx63b.tco +fate-g723_1-dec-7: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/dtx63b.tco -af aresample FATE_G723_1 += fate-g723_1-dec-8 -fate-g723_1-dec-8: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/dtx63e.tco +fate-g723_1-dec-8: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/dtx63e.tco -af aresample FATE_VOICE-$(call DEMDEC, G723_1, G723_1) += $(FATE_G723_1) fate-g723_1: $(FATE_G723_1) diff -Nru ffmpeg-4.2.2/tests/fate/vpx.mak ffmpeg-4.4/tests/fate/vpx.mak --- ffmpeg-4.2.2/tests/fate/vpx.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/vpx.mak 2021-04-08 21:28:40.000000000 +0000 @@ -1,8 +1,8 @@ FATE_TRUEMOTION1 += fate-truemotion1-15 -fate-truemotion1-15: CMD = framecrc -i $(TARGET_SAMPLES)/duck/phant2-940.duk -pix_fmt rgb24 -an +fate-truemotion1-15: CMD = framecrc -i $(TARGET_SAMPLES)/duck/phant2-940.duk -pix_fmt rgb24 -an -vf scale FATE_TRUEMOTION1 += fate-truemotion1-24 -fate-truemotion1-24: CMD = framecrc -i $(TARGET_SAMPLES)/duck/sonic3dblast_intro-partial.avi -pix_fmt rgb24 -an +fate-truemotion1-24: CMD = framecrc -i $(TARGET_SAMPLES)/duck/sonic3dblast_intro-partial.avi -pix_fmt rgb24 -an -vf scale FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, TRUEMOTION1) += $(FATE_TRUEMOTION1) fate-truemotion1: $(FATE_TRUEMOTION1) @@ -71,10 +71,10 @@ fate-webm-dash-manifest-representations: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video4.webm -c copy -map 0 -map 1 -f webm_dash_manifest -adaptation_sets "id=0,streams=0,1" - FATE_VP8-$(CONFIG_WEBM_DASH_MANIFEST_DEMUXER) += fate-webm-dash-manifest-live -fate-webm-dash-manifest-live: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -live 1 -i $(TARGET_SAMPLES)/vp8/dash_live_video_360.hdr -f webm_dash_manifest -live 1 -i $(TARGET_SAMPLES)/vp8/dash_live_audio_171.hdr -c copy -map 0 -map 1 -f webm_dash_manifest -live 1 -adaptation_sets "id=0,streams=0 id=1,streams=1" -chunk_start_index 1 -chunk_duration_ms 5000 -time_shift_buffer_depth 7200 -minimum_update_period 60 -debug_mode 1 - +fate-webm-dash-manifest-live: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -live 1 -i $(TARGET_SAMPLES)/vp8/dash_live_video_360.hdr -f webm_dash_manifest -live 1 -i $(TARGET_SAMPLES)/vp8/dash_live_audio_171.hdr -c copy -map 0 -map 1 -fflags +bitexact -f webm_dash_manifest -live 1 -adaptation_sets "id=0,streams=0 id=1,streams=1" -chunk_start_index 1 -chunk_duration_ms 5000 -time_shift_buffer_depth 7200 -minimum_update_period 60 - FATE_VP8-$(CONFIG_WEBM_DASH_MANIFEST_DEMUXER) += fate-webm-dash-manifest-live-bandwidth -fate-webm-dash-manifest-live-bandwidth: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -live 1 -bandwidth 100 -i $(TARGET_SAMPLES)/vp8/dash_live_video_360.hdr -f webm_dash_manifest -live 1 -bandwidth 200 -i $(TARGET_SAMPLES)/vp8/dash_live_audio_171.hdr -c copy -map 0 -map 1 -f webm_dash_manifest -live 1 -adaptation_sets "id=0,streams=0 id=1,streams=1" -chunk_start_index 1 -chunk_duration_ms 5000 -time_shift_buffer_depth 7200 -minimum_update_period 60 -debug_mode 1 - +fate-webm-dash-manifest-live-bandwidth: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -live 1 -bandwidth 100 -i $(TARGET_SAMPLES)/vp8/dash_live_video_360.hdr -f webm_dash_manifest -live 1 -bandwidth 200 -i $(TARGET_SAMPLES)/vp8/dash_live_audio_171.hdr -c copy -map 0 -map 1 -fflags +bitexact -f webm_dash_manifest -live 1 -adaptation_sets "id=0,streams=0 id=1,streams=1" -chunk_start_index 1 -chunk_duration_ms 5000 -time_shift_buffer_depth 7200 -minimum_update_period 60 - FATE_VP8-$(call DEMDEC, MATROSKA, VP8) += fate-vp8-2451 fate-vp8-2451: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp8/RRSF49-short.webm -vsync cfr -an @@ -141,8 +141,8 @@ $(foreach W,$(VP9_SIZE_B),$(eval $(foreach H,$(VP9_SIZE_B),$(eval $(call FATE_VP9_SUITE,03-size-$(W)x$(H)))))) $(eval $(call FATE_VP9_SUITE,03-deltaq)) $(foreach SS,$(VP9_CHROMA_SUBSAMPLE),$(eval $(call FATE_VP9_PROFILE_SUITE,04-yuv$(SS),1,))) -$(foreach BD,$(VP9_HIGH_BITDEPTH),$(eval $(call FATE_VP9_PROFILE_SUITE,20-$(BD)bit-yuv420,2,-pix_fmt yuv420p$(BD)le))) -$(foreach BD,$(VP9_HIGH_BITDEPTH),$(eval $(foreach SS,$(VP9_CHROMA_SUBSAMPLE),$(eval $(call FATE_VP9_PROFILE_SUITE,20-$(BD)bit-yuv$(SS),3,-pix_fmt yuv$(SS)p$(BD)le))))) +$(foreach BD,$(VP9_HIGH_BITDEPTH),$(eval $(call FATE_VP9_PROFILE_SUITE,20-$(BD)bit-yuv420,2,-pix_fmt yuv420p$(BD)le -vf scale))) +$(foreach BD,$(VP9_HIGH_BITDEPTH),$(eval $(foreach SS,$(VP9_CHROMA_SUBSAMPLE),$(eval $(call FATE_VP9_PROFILE_SUITE,20-$(BD)bit-yuv$(SS),3,-pix_fmt yuv$(SS)p$(BD)le -vf scale))))) $(eval $(call FATE_VP9_SUITE,06-bilinear)) $(eval $(call FATE_VP9_SUITE,09-lf_deltas)) $(eval $(call FATE_VP9_SUITE,10-show-existing-frame)) @@ -163,5 +163,10 @@ fate-vp9-05-resize: CMD = framemd5 -i $(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-05-resize.ivf -s 352x288 -sws_flags bitexact+bilinear fate-vp9-05-resize: REF = $(SRC_PATH)/tests/ref/fate/vp9-05-resize +fate-vp9-encparams: CMD = venc_data $(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-segmentation-aq-akiyo.webm 0 5 +FATE_SAMPLES_DUMP_DATA += fate-vp9-encparams + +FATE_VP9-$(CONFIG_MATROSKA_DEMUXER) += fate-vp9-encparams + FATE_SAMPLES_AVCONV-$(CONFIG_VP9_DECODER) += $(FATE_VP9-yes) fate-vp9: $(FATE_VP9-yes) diff -Nru ffmpeg-4.2.2/tests/fate/wavpack.mak ffmpeg-4.4/tests/fate/wavpack.mak --- ffmpeg-4.2.2/tests/fate/wavpack.mak 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/fate/wavpack.mak 2021-04-08 21:28:40.000000000 +0000 @@ -3,100 +3,100 @@ # lossless FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossless-8bit -fate-wavpack-lossless-8bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/8bit-partial.wv -f s8 +fate-wavpack-lossless-8bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/8bit-partial.wv -f s8 -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossless-12bit -fate-wavpack-lossless-12bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/12bit-partial.wv -f s16le +fate-wavpack-lossless-12bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/12bit-partial.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossless-16bit -fate-wavpack-lossless-16bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/16bit-partial.wv -f s16le +fate-wavpack-lossless-16bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/16bit-partial.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossless-24bit -fate-wavpack-lossless-24bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/24bit-partial.wv -f s24le +fate-wavpack-lossless-24bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/24bit-partial.wv -f s24le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossless-32bit -fate-wavpack-lossless-32bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/32bit_int-partial.wv -f s32le +fate-wavpack-lossless-32bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/32bit_int-partial.wv -f s32le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossless-float -fate-wavpack-lossless-float: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/32bit_float-partial.wv -f f32le +fate-wavpack-lossless-float: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/32bit_float-partial.wv -f f32le -af aresample # lossy FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossy-8bit -fate-wavpack-lossy-8bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_8-bit.wv -f s8 +fate-wavpack-lossy-8bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_8-bit.wv -f s8 -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossy-16bit -fate-wavpack-lossy-16bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_16-bit.wv -f s16le +fate-wavpack-lossy-16bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_16-bit.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossy-24bit -fate-wavpack-lossy-24bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_24-bit.wv -f s24le +fate-wavpack-lossy-24bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_24-bit.wv -f s24le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossy-32bit -fate-wavpack-lossy-32bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_32-bit_int.wv -f s32le +fate-wavpack-lossy-32bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_32-bit_int.wv -f s32le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossy-float -fate-wavpack-lossy-float: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/2.0_32-bit_float.wv -f f32le +fate-wavpack-lossy-float: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/2.0_32-bit_float.wv -f f32le -af aresample # channel configurations FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-channels-monofloat -fate-wavpack-channels-monofloat: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_float-partial.wv -f f32le +fate-wavpack-channels-monofloat: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_float-partial.wv -f f32le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-channels-monoint -fate-wavpack-channels-monoint: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -f s16le +fate-wavpack-channels-monoint: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-channels-4.0 -fate-wavpack-channels-4.0: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/edward_4.0_16bit-partial.wv -f s16le +fate-wavpack-channels-4.0: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/edward_4.0_16bit-partial.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-channels-5.1 -fate-wavpack-channels-5.1: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/panslab_sample_5.1_16bit-partial.wv -f s16le +fate-wavpack-channels-5.1: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/panslab_sample_5.1_16bit-partial.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-channels-6.1 -fate-wavpack-channels-6.1: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -f s16le +fate-wavpack-channels-6.1: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-channels-7.1 -fate-wavpack-channels-7.1: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/panslab_sample_7.1_16bit-partial.wv -f s16le +fate-wavpack-channels-7.1: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/panslab_sample_7.1_16bit-partial.wv -f s16le -af aresample # speed modes FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-speed-default -fate-wavpack-speed-default: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/speed_modes/default-partial.wv -f s16le +fate-wavpack-speed-default: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/speed_modes/default-partial.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-speed-fast -fate-wavpack-speed-fast: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/speed_modes/fast-partial.wv -f s16le +fate-wavpack-speed-fast: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/speed_modes/fast-partial.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-speed-high -fate-wavpack-speed-high: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/speed_modes/high-partial.wv -f s16le +fate-wavpack-speed-high: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/speed_modes/high-partial.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-speed-vhigh -fate-wavpack-speed-vhigh: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/speed_modes/vhigh-partial.wv -f s16le +fate-wavpack-speed-vhigh: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/speed_modes/vhigh-partial.wv -f s16le -af aresample # special cases FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-clipping -fate-wavpack-clipping: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/clipping.wv -f s16le +fate-wavpack-clipping: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/clipping.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-cuesheet -fate-wavpack-cuesheet: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/cue_sheet.wv -f s16le +fate-wavpack-cuesheet: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/cue_sheet.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-falsestereo -fate-wavpack-falsestereo: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/false_stereo.wv -f s16le +fate-wavpack-falsestereo: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/false_stereo.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-zerolsbs -fate-wavpack-zerolsbs: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/zero_lsbs.wv -f s16le +fate-wavpack-zerolsbs: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/zero_lsbs.wv -f s16le -af aresample FATE_WAVPACK-$(call DEMDEC, MATROSKA, WAVPACK) += fate-wavpack-matroskamode -fate-wavpack-matroskamode: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/matroska_mode.mka -f s16le +fate-wavpack-matroskamode: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/matroska_mode.mka -f s16le -af aresample FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) += fate-wavpack-matroska_mux-mono fate-wavpack-matroska_mux-mono: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -c copy -fflags +bitexact -f matroska fate-wavpack-matroska_mux-mono: CMP = oneline -fate-wavpack-matroska_mux-mono: REF = c5a2b46d8b31c9c2e7bfb436f9d56f02 +fate-wavpack-matroska_mux-mono: REF = 0a10b6cd4d64c25ced75f52d1c6929a7 FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) += fate-wavpack-matroska_mux-61 fate-wavpack-matroska_mux-61: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -c copy -fflags +bitexact -f matroska fate-wavpack-matroska_mux-61: CMP = oneline -fate-wavpack-matroska_mux-61: REF = 22fc2a591be22657d19cab89ad6eef55 +fate-wavpack-matroska_mux-61: REF = fee4bb1d6cf2d54f78eddc4483e7c990 FATE_SAMPLES_AVCONV += $(FATE_WAVPACK-yes) fate-wavpack: $(FATE_WAVPACK-yes) diff -Nru ffmpeg-4.2.2/tests/fate-run.sh ffmpeg-4.4/tests/fate-run.sh --- ffmpeg-4.2.2/tests/fate-run.sh 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/tests/fate-run.sh 2021-04-08 21:28:40.000000000 +0000 @@ -86,11 +86,15 @@ } probefmt(){ - run ffprobe${PROGSUF}${EXECSUF} -show_entries format=format_name -print_format default=nw=1:nk=1 -v 0 "$@" + run ffprobe${PROGSUF}${EXECSUF} -show_entries format=format_name -print_format default=nw=1:nk=1 "$@" +} + +probeaudiostream(){ + run ffprobe${PROGSUF}${EXECSUF} -show_entries stream=codec_name,codec_time_base,sample_fmt,channels,channel_layout "$@" } probetags(){ - run ffprobe${PROGSUF}${EXECSUF} -show_entries format_tags -v 0 "$@" + run ffprobe${PROGSUF}${EXECSUF} -show_entries format_tags "$@" } runlocal(){ @@ -99,31 +103,31 @@ } probeframes(){ - run ffprobe${PROGSUF}${EXECSUF} -show_frames -v 0 "$@" + run ffprobe${PROGSUF}${EXECSUF} -show_frames "$@" } probechapters(){ - run ffprobe${PROGSUF}${EXECSUF} -show_chapters -v 0 "$@" + run ffprobe${PROGSUF}${EXECSUF} -show_chapters "$@" } probegaplessinfo(){ filename="$1" shift - run ffprobe${PROGSUF}${EXECSUF} -bitexact -select_streams a -show_entries format=start_time,duration:stream=index,start_pts,duration_ts -v 0 "$filename" "$@" + run ffprobe${PROGSUF}${EXECSUF} -bitexact -select_streams a -show_entries format=start_time,duration:stream=index,start_pts,duration_ts "$filename" "$@" pktfile1="${outdir}/${test}.pkts" framefile1="${outdir}/${test}.frames" cleanfiles="$cleanfiles $pktfile1 $framefile1" - run ffprobe${PROGSUF}${EXECSUF} -bitexact -select_streams a -of compact -count_packets -show_entries packet=pts,dts,duration,flags:stream=nb_read_packets -v 0 "$filename" "$@" > "$pktfile1" + run ffprobe${PROGSUF}${EXECSUF} -bitexact -select_streams a -of compact -count_packets -show_entries packet=pts,dts,duration,flags:stream=nb_read_packets "$filename" "$@" > "$pktfile1" head -n 8 "$pktfile1" tail -n 9 "$pktfile1" - run ffprobe${PROGSUF}${EXECSUF} -bitexact -select_streams a -of compact -count_frames -show_entries frame=pkt_pts,pkt_dts,best_effort_timestamp,pkt_duration,nb_samples:stream=nb_read_frames -v 0 "$filename" "$@" > "$framefile1" + run ffprobe${PROGSUF}${EXECSUF} -bitexact -select_streams a -of compact -count_frames -show_entries frame=pkt_pts,pkt_dts,best_effort_timestamp,pkt_duration,nb_samples:stream=nb_read_frames "$filename" "$@" > "$framefile1" head -n 8 "$framefile1" tail -n 9 "$framefile1" } ffmpeg(){ dec_opts="-hwaccel $hwaccel -threads $threads -thread_type $thread_type" - ffmpeg_args="-nostdin -nostats -cpuflags $cpuflags" + ffmpeg_args="-nostdin -nostats -noauto_conversion_filters -cpuflags $cpuflags" for arg in $@; do [ x${arg} = x-i ] && ffmpeg_args="${ffmpeg_args} ${dec_opts}" ffmpeg_args="${ffmpeg_args} ${arg}" @@ -154,12 +158,12 @@ md5(){ encfile="${outdir}/${test}.out" cleanfiles="$cleanfiles $encfile" - ffmpeg "$@" $encfile + ffmpeg -y "$@" $(target_path $encfile) || return do_md5sum $encfile | awk '{print $1}' } pcm(){ - ffmpeg "$@" -vn -f s16le - + ffmpeg -auto_conversion_filters "$@" -vn -f s16le - } fmtstdout(){ @@ -177,8 +181,8 @@ encfile="${outdir}/${test}.${out_fmt}" cleanfiles=$encfile encfile=$(target_path ${encfile}) - ffmpeg -i $src_file "$@" -f $out_fmt -y ${encfile} || return - ffmpeg -bitexact -i ${encfile} -c:a pcm_${pcm_fmt} -fflags +bitexact -f ${dec_fmt} - + ffmpeg -auto_conversion_filters -i $src_file "$@" -f $out_fmt -y ${encfile} || return + ffmpeg -auto_conversion_filters -bitexact -i ${encfile} -c:a pcm_${pcm_fmt} -fflags +bitexact -f ${dec_fmt} - } FLAGS="-flags +bitexact -sws_flags +accurate_rnd+bitexact -fflags +bitexact" @@ -192,6 +196,7 @@ enc_opt=$4 dec_fmt=$5 dec_opt=$6 + ffprobe_opts=$9 encfile="${outdir}/${test}.${enc_fmt}" decfile="${outdir}/${test}.out.${dec_fmt}" cleanfiles="$cleanfiles $decfile" @@ -199,14 +204,16 @@ tsrcfile=$(target_path $srcfile) tencfile=$(target_path $encfile) tdecfile=$(target_path $decfile) - ffmpeg -f $src_fmt $DEC_OPTS -i $tsrcfile $ENC_OPTS $enc_opt $FLAGS \ + ffmpeg -auto_conversion_filters -f $src_fmt $DEC_OPTS -i $tsrcfile $ENC_OPTS $enc_opt $FLAGS \ -f $enc_fmt -y $tencfile || return do_md5sum $encfile echo $(wc -c $encfile) - ffmpeg $8 $DEC_OPTS -i $tencfile $ENC_OPTS $dec_opt $FLAGS \ + ffmpeg -auto_conversion_filters $8 $DEC_OPTS -i $tencfile $ENC_OPTS $dec_opt $FLAGS \ -f $dec_fmt -y $tdecfile || return do_md5sum $decfile tests/tiny_psnr${HOSTEXECSUF} $srcfile $decfile $cmp_unit $cmp_shift + test -z $ffprobe_opts || \ + run ffprobe${PROGSUF}${EXECSUF} $ffprobe_opts $tencfile || return } transcode(){ @@ -215,16 +222,19 @@ enc_fmt=$3 enc_opt=$4 final_decode=$5 + ffprobe_opts=$7 encfile="${outdir}/${test}.${enc_fmt}" - test "$7" = -keep || cleanfiles="$cleanfiles $encfile" + test "$6" = -keep || cleanfiles="$cleanfiles $encfile" tsrcfile=$(target_path $srcfile) tencfile=$(target_path $encfile) ffmpeg -f $src_fmt $DEC_OPTS -i $tsrcfile $ENC_OPTS $enc_opt $FLAGS \ -f $enc_fmt -y $tencfile || return do_md5sum $encfile echo $(wc -c $encfile) - ffmpeg $DEC_OPTS -i $encfile $ENC_OPTS $FLAGS $final_decode \ + ffmpeg $DEC_OPTS -i $tencfile $ENC_OPTS $FLAGS $final_decode \ -f framecrc - || return + test -z $ffprobe_opts || \ + run ffprobe${PROGSUF}${EXECSUF} $ffprobe_opts $tencfile || return } stream_remux(){ @@ -233,14 +243,17 @@ enc_fmt=$3 stream_maps=$4 final_decode=$5 + ffprobe_opts=$7 encfile="${outdir}/${test}.${enc_fmt}" - test "$7" = -keep || cleanfiles="$cleanfiles $encfile" + test "$6" = -keep || cleanfiles="$cleanfiles $encfile" tsrcfile=$(target_path $srcfile) tencfile=$(target_path $encfile) ffmpeg -f $src_fmt -i $tsrcfile $stream_maps -codec copy $FLAGS \ -f $enc_fmt -y $tencfile || return - ffmpeg $DEC_OPTS -i $encfile $ENC_OPTS $FLAGS $final_decode \ + ffmpeg $DEC_OPTS -i $tencfile $ENC_OPTS $FLAGS $final_decode \ -f framecrc - || return + test -z $ffprobe_opts || \ + run ffprobe${PROGSUF}${EXECSUF} $ffprobe_opts $tencfile || return } # FIXME: There is a certain duplication between the avconv-related helper @@ -257,7 +270,7 @@ echo "$@" >&3 } -AVCONV_OPTS="-nostdin -nostats -y -cpuflags $cpuflags" +AVCONV_OPTS="-nostdin -nostats -noauto_conversion_filters -y -cpuflags $cpuflags" COMMON_OPTS="-flags +bitexact -idct simple -sws_flags +accurate_rnd+bitexact -fflags +bitexact" DEC_OPTS="$COMMON_OPTS -threads $threads" ENC_OPTS="$COMMON_OPTS -threads 1 -dct fastint" @@ -287,17 +300,17 @@ t="${test#lavf-}" outdir="tests/data/lavf" file=${outdir}/lavf.$t - do_avconv $file $DEC_OPTS $1 -ar 44100 -f s16le -i $pcm_src "$ENC_OPTS -metadata title=lavftest" -t 1 -qscale 10 $2 - do_avconv_crc $file $DEC_OPTS $3 -i $target_path/$file + do_avconv $file -auto_conversion_filters $DEC_OPTS $1 -ar 44100 -f s16le -i $pcm_src "$ENC_OPTS -metadata title=lavftest" -t 1 -qscale 10 $2 + do_avconv_crc $file -auto_conversion_filters $DEC_OPTS $3 -i $target_path/$file } lavf_container(){ t="${test#lavf-}" outdir="tests/data/lavf" file=${outdir}/lavf.$t - do_avconv $file $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src $DEC_OPTS -ar 44100 -f s16le $1 -i $pcm_src "$ENC_OPTS -metadata title=lavftest" -b:a 64k -t 1 -qscale:v 10 $2 + do_avconv $file -auto_conversion_filters $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src $DEC_OPTS -ar 44100 -f s16le $1 -i $pcm_src "$ENC_OPTS -metadata title=lavftest" -b:a 64k -t 1 -qscale:v 10 $2 test "$3" = "disable_crc" || - do_avconv_crc $file $DEC_OPTS -i $target_path/$file $3 + do_avconv_crc $file -auto_conversion_filters $DEC_OPTS -i $target_path/$file $3 } lavf_container_attach() { lavf_container "" "$1 -attach ${raw_src%/*}/00.pgm -metadata:s:t mimetype=image/x-portable-greymap"; } @@ -317,8 +330,8 @@ outdir="tests/data/lavf-fate" file=${outdir}/lavf.$t input="${target_samples}/$1" - do_avconv $file $DEC_OPTS $2 -i "$input" "$ENC_OPTS -metadata title=lavftest" -vcodec copy -acodec copy - do_avconv_crc $file $DEC_OPTS -i $target_path/$file $3 + do_avconv $file -auto_conversion_filters $DEC_OPTS $2 -i "$input" "$ENC_OPTS -metadata title=lavftest" -vcodec copy -acodec copy + do_avconv_crc $file -auto_conversion_filters $DEC_OPTS -i $target_path/$file $3 } lavf_image(){ @@ -326,9 +339,9 @@ outdir="tests/data/images/$t" mkdir -p "$outdir" file=${outdir}/%02d.$t - run_avconv $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src $1 "$ENC_OPTS -metadata title=lavftest" -frames 13 -y -qscale 10 $target_path/$file + run_avconv $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src $1 "$ENC_OPTS -metadata title=lavftest" -vf scale -frames 13 -y -qscale 10 $target_path/$file do_md5sum ${outdir}/02.$t - do_avconv_crc $file $DEC_OPTS $2 -i $target_path/$file $2 + do_avconv_crc $file -auto_conversion_filters $DEC_OPTS $2 -i $target_path/$file $2 echo $(wc -c ${outdir}/02.$t) } @@ -337,16 +350,16 @@ t="${t%pipe}" outdir="tests/data/lavf" file=${outdir}/${t}pipe.$t - do_avconv $file $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src -f image2pipe "$ENC_OPTS -metadata title=lavftest" -t 1 -qscale 10 - do_avconv_crc $file $DEC_OPTS -f image2pipe -i $target_path/$file + do_avconv $file -auto_conversion_filters $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src -f image2pipe "$ENC_OPTS -metadata title=lavftest" -t 1 -qscale 10 + do_avconv_crc $file -auto_conversion_filters $DEC_OPTS -f image2pipe -i $target_path/$file } lavf_video(){ t="${test#lavf-}" outdir="tests/data/lavf" file=${outdir}/lavf.$t - do_avconv $file $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src "$ENC_OPTS -metadata title=lavftest" -t 1 -qscale 10 $1 $2 - do_avconv_crc $file $DEC_OPTS -i $target_path/$file $1 + do_avconv $file -auto_conversion_filters $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src "$ENC_OPTS -metadata title=lavftest" -t 1 -qscale 10 $1 $2 + do_avconv_crc $file -auto_conversion_filters $DEC_OPTS -i $target_path/$file $1 } refcmp_metadata(){ @@ -403,7 +416,7 @@ outertest=$test for pix_fmt in $pix_fmts; do test=$pix_fmt - video_filter "${prefilter_chain}format=$pix_fmt,$filter=$filter_args" -pix_fmt $pix_fmt -frames:v $nframes + video_filter "${prefilter_chain}scale,format=$pix_fmt,$filter=$filter_args" -pix_fmt $pix_fmt -frames:v $nframes done rm $in_fmts $scale_in_fmts $scale_out_fmts $scale_exclude_fmts @@ -420,16 +433,16 @@ cleanfiles="$cleanfiles $decfile1 $decfile2 $decfile3" # test packet data - ffmpeg $extra_args -i "$sample" -bitexact -c:a copy -f framecrc -y $decfile1 + ffmpeg -auto_conversion_filters $extra_args -i "$sample" -bitexact -c:a copy -f framecrc -y $(target_path $decfile1) do_md5sum $decfile1 # test decoded (and cut) data - ffmpeg $extra_args -i "$sample" -bitexact -f wav md5: + ffmpeg -auto_conversion_filters $extra_args -i "$sample" -bitexact -f wav md5: # the same as above again, with seeking to the start - ffmpeg $extra_args -ss 0 -seek_timestamp 1 -i "$sample" -bitexact -c:a copy -f framecrc -y $decfile2 + ffmpeg -auto_conversion_filters $extra_args -ss 0 -seek_timestamp 1 -i "$sample" -bitexact -c:a copy -f framecrc -y $(target_path $decfile2) do_md5sum $decfile2 - ffmpeg $extra_args -ss 0 -seek_timestamp 1 -i "$sample" -bitexact -f wav md5: + ffmpeg -auto_conversion_filters $extra_args -ss 0 -seek_timestamp 1 -i "$sample" -bitexact -f wav md5: # test packet data, with seeking to a specific position - ffmpeg $extra_args -ss 5 -seek_timestamp 1 -i "$sample" -bitexact -c:a copy -f framecrc -y $decfile3 + ffmpeg -auto_conversion_filters $extra_args -ss 5 -seek_timestamp 1 -i "$sample" -bitexact -c:a copy -f framecrc -y $(target_path $decfile3) do_md5sum $decfile3 } @@ -442,19 +455,19 @@ cleanfiles="$cleanfiles $file1" # test data after reencoding - ffmpeg -i "$sample" -bitexact -map 0:a -c:a $codec -f $format -y "$file1" - probegaplessinfo "$file1" + ffmpeg -i "$sample" -bitexact -map 0:a -c:a $codec -af aresample -f $format -y "$(target_path "$file1")" + probegaplessinfo "$(target_path "$file1")" } audio_match(){ sample=$(target_path $1) - trefile=$(target_path $2) + trefile=$2 extra_args=$3 decfile="${outdir}/${test}.wav" cleanfiles="$cleanfiles $decfile" - ffmpeg -i "$sample" -bitexact $extra_args -y $decfile + ffmpeg -auto_conversion_filters -i "$sample" -bitexact $extra_args -y $(target_path $decfile) tests/audiomatch${HOSTEXECSUF} $decfile $trefile } @@ -471,13 +484,20 @@ awk "{gsub(/%SRCFILE%/, \"$sample\"); print}" $template > $concatfile if [ "$mode" = "md5" ]; then - run ffprobe${PROGSUF}${EXECSUF} -bitexact -show_streams -show_packets -v 0 -fflags keepside -safe 0 $extra_args $concatfile | tr -d '\r' > $packetfile + run ffprobe${PROGSUF}${EXECSUF} -bitexact -show_streams -show_packets -safe 0 $extra_args $(target_path $concatfile) | tr -d '\r' > $packetfile do_md5sum $packetfile else - run ffprobe${PROGSUF}${EXECSUF} -bitexact -show_streams -show_packets -v 0 -of compact=p=0:nk=1 -fflags keepside -safe 0 $extra_args $concatfile + run ffprobe${PROGSUF}${EXECSUF} -bitexact -show_streams -show_packets -of compact=p=0:nk=1 -safe 0 $extra_args $(target_path $concatfile) fi } +venc_data(){ + file=$1 + stream=$2 + frames=$3 + run tools/venc_data_dump${EXECSUF} ${file} ${stream} ${frames} ${threads} ${thread_type} +} + null(){ : } diff -Nru ffmpeg-4.2.2/tests/filtergraphs/concat-vfr ffmpeg-4.4/tests/filtergraphs/concat-vfr --- ffmpeg-4.2.2/tests/filtergraphs/concat-vfr 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/filtergraphs/concat-vfr 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,8 @@ +testsrc=r=5:n=1:d=2 [v1]; +sine=440:b=2:d=1 [a1]; +testsrc=r=15:n=1:d=1 [v2]; +sine=622:b=2:d=2 [a2]; +testsrc=r=8:n=1:d=1 [v3]; +sine=880:b=2:d=1 [a3]; + +[v1][a1][v2][a2][v3][a3] concat=v=1:a=1:n=3 diff -Nru ffmpeg-4.2.2/tests/filtergraphs/overlay_yuv420p10 ffmpeg-4.4/tests/filtergraphs/overlay_yuv420p10 --- ffmpeg-4.2.2/tests/filtergraphs/overlay_yuv420p10 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/filtergraphs/overlay_yuv420p10 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,5 @@ +sws_flags=+accurate_rnd+bitexact; +split [main][over]; +[over] scale=88:72, format=yuv420p10, pad=96:80:4:4 [overf]; +[main] format=yuv420p10 [mainf]; +[mainf][overf] overlay=240:16:format=yuv420p10 diff -Nru ffmpeg-4.2.2/tests/filtergraphs/overlay_yuv422p10 ffmpeg-4.4/tests/filtergraphs/overlay_yuv422p10 --- ffmpeg-4.2.2/tests/filtergraphs/overlay_yuv422p10 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/filtergraphs/overlay_yuv422p10 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,5 @@ +sws_flags=+accurate_rnd+bitexact; +split [main][over]; +[over] scale=88:72, format=yuv420p10, pad=96:80:4:4 [overf]; +[main] format=yuv420p10 [mainf]; +[mainf][overf] overlay=240:16:format=yuv422p10 diff -Nru ffmpeg-4.2.2/tests/Makefile ffmpeg-4.4/tests/Makefile --- ffmpeg-4.2.2/tests/Makefile 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/Makefile 2020-07-11 10:39:30.000000000 +0000 @@ -10,7 +10,8 @@ $(AREF): CMP= APITESTSDIR := tests/api -FATE_OUTDIRS = tests/data tests/data/fate tests/data/filtergraphs tests/data/lavf tests/data/lavf-fate tests/data/pixfmt tests/vsynth1 $(APITESTSDIR) +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) OUTDIRS += $(FATE_OUTDIRS) $(VREF): tests/videogen$(HOSTEXESUF) | tests/vsynth1 @@ -84,7 +85,18 @@ PARSERDEMDEC = $(call ALLYES, $(1)_PARSER $(2)_DEMUXER $(3)_DECODER) +# Allow overriding CONFIG_LARGE_TESTS via LARGE_TESTS, if set on the +# make command line. +ifeq ($(LARGE_TESTS), yes) +CONFIG_LARGE_TESTS:=yes +!CONFIG_LARGE_TESTS:= +else ifeq ($(LARGE_TESTS), no) +CONFIG_LARGE_TESTS:= +!CONFIG_LARGE_TESTS:=yes +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 @@ -118,6 +130,7 @@ include $(SRC_PATH)/tests/fate/dca.mak include $(SRC_PATH)/tests/fate/demux.mak include $(SRC_PATH)/tests/fate/dfa.mak +include $(SRC_PATH)/tests/fate/dnn.mak include $(SRC_PATH)/tests/fate/dnxhd.mak include $(SRC_PATH)/tests/fate/dpcm.mak include $(SRC_PATH)/tests/fate/ea.mak @@ -174,6 +187,7 @@ include $(SRC_PATH)/tests/fate/source.mak include $(SRC_PATH)/tests/fate/speedhq.mak include $(SRC_PATH)/tests/fate/subtitles.mak +include $(SRC_PATH)/tests/fate/truehd.mak include $(SRC_PATH)/tests/fate/utvideo.mak include $(SRC_PATH)/tests/fate/video.mak include $(SRC_PATH)/tests/fate/voice.mak @@ -187,25 +201,29 @@ FATE_FFMPEG += $(FATE_FFMPEG-yes) $(FATE_AVCONV) $(FATE_AVCONV-yes) FATE-$(CONFIG_FFMPEG) += $(FATE_FFMPEG) FATE-$(CONFIG_FFPROBE) += $(FATE_FFPROBE) +FATE-$(call ALLYES, FFMPEG FFPROBE) += $(FATE_FFMPEG_FFPROBE) FATE_SAMPLES_AVCONV += $(FATE_SAMPLES_AVCONV-yes) FATE_SAMPLES_FFMPEG += $(FATE_SAMPLES_FFMPEG-yes) -FATE_EXTERN-$(CONFIG_FFMPEG) += $(FATE_SAMPLES_AVCONV) $(FATE_SAMPLES_FFMPEG) $(FATE_SAMPLES_FFPROBE) $(FATE_SAMPLES_FASTSTART) -FATE_EXTERN += $(FATE_EXTERN-yes) +FATE_EXTERN-$(CONFIG_FFMPEG) += $(FATE_SAMPLES_AVCONV) $(FATE_SAMPLES_FFMPEG) +FATE_EXTERN-$(CONFIG_FFPROBE) += $(FATE_SAMPLES_FFPROBE) +FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_SAMPLES_FFMPEG_FFPROBE-yes) +FATE_EXTERN-$(call ALLYES, FFMPEG FFPROBE) += $(FATE_SAMPLES_FFMPEG_FFPROBE) +FATE_EXTERN += $(FATE_EXTERN-yes) $(FATE_SAMPLES_FASTSTART) FATE += $(FATE-yes) RSYNC_OPTIONS-$(HAVE_RSYNC_CONTIMEOUT) += --contimeout=60 RSYNC_OPTIONS = -vrltLW --timeout=60 $(RSYNC_OPTIONS-yes) -$(FATE_FFMPEG) $(FATE_SAMPLES_AVCONV) $(FATE_SAMPLES_FFMPEG): ffmpeg$(PROGSSUF)$(EXESUF) +$(FATE_FFMPEG) $(FATE_FFMPEG_FFPROBE) $(FATE_SAMPLES_AVCONV) $(FATE_SAMPLES_FFMPEG) $(FATE_SAMPLES_FFMPEG_FFPROBE): ffmpeg$(PROGSSUF)$(EXESUF) -$(FATE_FFPROBE) $(FATE_SAMPLES_FFPROBE): ffprobe$(PROGSSUF)$(EXESUF) +$(FATE_FFPROBE) $(FATE_FFMPEG_FFPROBE) $(FATE_SAMPLES_FFPROBE) $(FATE_SAMPLES_FFMPEG_FFPROBE): ffprobe$(PROGSSUF)$(EXESUF) $(FATE_SAMPLES_FASTSTART): tools/qt-faststart$(EXESUF) +$(FATE_SAMPLES_DUMP_DATA): tools/venc_data_dump$(EXESUF) ifdef SAMPLES -FATE += $(FATE_FULL) $(FATE_FULL-yes) FATE += $(FATE_EXTERN) fate-rsync: rsync $(RSYNC_OPTIONS) rsync://fate-suite.ffmpeg.org/fate-suite/ $(SAMPLES) diff -Nru ffmpeg-4.2.2/tests/ref/acodec/adpcm-adx ffmpeg-4.4/tests/ref/acodec/adpcm-adx --- ffmpeg-4.2.2/tests/ref/acodec/adpcm-adx 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/acodec/adpcm-adx 2020-07-11 10:39:30.000000000 +0000 @@ -1,4 +1,4 @@ -6bf1a8e5ec9cc958a31cb2b1b66bfc75 *tests/data/fate/acodec-adpcm-adx.adx -297720 tests/data/fate/acodec-adpcm-adx.adx +c257001314241b469a6512616fd56548 *tests/data/fate/acodec-adpcm-adx.adx +297738 tests/data/fate/acodec-adpcm-adx.adx 5b5a436ec9d528d6eb0bebaf667521b0 *tests/data/fate/acodec-adpcm-adx.out.wav stddev: 2549.93 PSNR: 28.20 MAXDIFF:57514 bytes: 1058400/ 1058432 diff -Nru ffmpeg-4.2.2/tests/ref/acodec/adpcm-adx-trellis ffmpeg-4.4/tests/ref/acodec/adpcm-adx-trellis --- ffmpeg-4.2.2/tests/ref/acodec/adpcm-adx-trellis 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/acodec/adpcm-adx-trellis 2020-07-11 10:39:30.000000000 +0000 @@ -1,4 +1,4 @@ -6bf1a8e5ec9cc958a31cb2b1b66bfc75 *tests/data/fate/acodec-adpcm-adx-trellis.adx -297720 tests/data/fate/acodec-adpcm-adx-trellis.adx +c257001314241b469a6512616fd56548 *tests/data/fate/acodec-adpcm-adx-trellis.adx +297738 tests/data/fate/acodec-adpcm-adx-trellis.adx 5b5a436ec9d528d6eb0bebaf667521b0 *tests/data/fate/acodec-adpcm-adx-trellis.out.wav stddev: 2549.93 PSNR: 28.20 MAXDIFF:57514 bytes: 1058400/ 1058432 diff -Nru ffmpeg-4.2.2/tests/ref/acodec/adpcm-argo ffmpeg-4.4/tests/ref/acodec/adpcm-argo --- ffmpeg-4.2.2/tests/ref/acodec/adpcm-argo 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/acodec/adpcm-argo 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,4 @@ +14b2507d14e95c20bb7ae49b4fcbcbf1 *tests/data/fate/acodec-adpcm-argo.argo_asf +281190 tests/data/fate/acodec-adpcm-argo.argo_asf +cc5e5c695adeaebaa2b1f0df5ebd59ee *tests/data/fate/acodec-adpcm-argo.out.wav +stddev: 1542.05 PSNR: 32.57 MAXDIFF:59667 bytes: 1058400/ 1058432 diff -Nru ffmpeg-4.2.2/tests/ref/acodec/adpcm-ima_alp ffmpeg-4.4/tests/ref/acodec/adpcm-ima_alp --- ffmpeg-4.2.2/tests/ref/acodec/adpcm-ima_alp 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/acodec/adpcm-ima_alp 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,4 @@ +d84466bdfbe6405fa31e44df255f6aad *tests/data/fate/acodec-adpcm-ima_alp.alp +264620 tests/data/fate/acodec-adpcm-ima_alp.alp +d60c48654568a1cf0abd56b565b12f00 *tests/data/fate/acodec-adpcm-ima_alp.out.wav +stddev: 1467.15 PSNR: 33.00 MAXDIFF:33866 bytes: 1058400/ 1058400 diff -Nru ffmpeg-4.2.2/tests/ref/acodec/adpcm-ima_apm ffmpeg-4.4/tests/ref/acodec/adpcm-ima_apm --- ffmpeg-4.2.2/tests/ref/acodec/adpcm-ima_apm 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/acodec/adpcm-ima_apm 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,4 @@ +2e795c6c06baabe01ab92864d963e71b *tests/data/fate/acodec-adpcm-ima_apm.apm +264700 tests/data/fate/acodec-adpcm-ima_apm.apm +201607bf7610f062b9a1e6524354c569 *tests/data/fate/acodec-adpcm-ima_apm.out.wav +stddev: 904.76 PSNR: 37.20 MAXDIFF:34029 bytes: 1058400/ 1058400 diff -Nru ffmpeg-4.2.2/tests/ref/acodec/adpcm-ima_ssi ffmpeg-4.4/tests/ref/acodec/adpcm-ima_ssi --- ffmpeg-4.2.2/tests/ref/acodec/adpcm-ima_ssi 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/acodec/adpcm-ima_ssi 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,4 @@ +91c6a0d8eb3544e402af17a1b77a22e5 *tests/data/fate/acodec-adpcm-ima_ssi.kvag +264614 tests/data/fate/acodec-adpcm-ima_ssi.kvag +201607bf7610f062b9a1e6524354c569 *tests/data/fate/acodec-adpcm-ima_ssi.out.wav +stddev: 904.76 PSNR: 37.20 MAXDIFF:34029 bytes: 1058400/ 1058400 diff -Nru ffmpeg-4.2.2/tests/ref/acodec/adpcm-swf ffmpeg-4.4/tests/ref/acodec/adpcm-swf --- ffmpeg-4.2.2/tests/ref/acodec/adpcm-swf 2016-03-29 02:25:34.000000000 +0000 +++ ffmpeg-4.4/tests/ref/acodec/adpcm-swf 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -42d4639866ed4d692eaf126228a4fa2a *tests/data/fate/acodec-adpcm-swf.flv -269166 tests/data/fate/acodec-adpcm-swf.flv -628089745a7059ae4055c2515b6d668b *tests/data/fate/acodec-adpcm-swf.out.wav -stddev: 933.58 PSNR: 36.93 MAXDIFF:51119 bytes: 1058400/ 1064960 +64aedd1487cb355406dde36d2bba374f *tests/data/fate/acodec-adpcm-swf.flv +267801 tests/data/fate/acodec-adpcm-swf.flv +9d061488fdc1a557bdc454b9d1aba59c *tests/data/fate/acodec-adpcm-swf.out.wav +stddev: 919.82 PSNR: 37.06 MAXDIFF:51119 bytes: 1058400/ 1064960 diff -Nru ffmpeg-4.2.2/tests/ref/acodec/adpcm-swf-trellis ffmpeg-4.4/tests/ref/acodec/adpcm-swf-trellis --- ffmpeg-4.2.2/tests/ref/acodec/adpcm-swf-trellis 2016-03-29 02:25:34.000000000 +0000 +++ ffmpeg-4.4/tests/ref/acodec/adpcm-swf-trellis 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -ec8859b3206ea0c45701fbdcf60dbe48 *tests/data/fate/acodec-adpcm-swf-trellis.flv -269166 tests/data/fate/acodec-adpcm-swf-trellis.flv -29820ce5b95b3b0a2feafa808cc264a7 *tests/data/fate/acodec-adpcm-swf-trellis.out.wav -stddev: 747.92 PSNR: 38.85 MAXDIFF:51119 bytes: 1058400/ 1064960 +fde151ce9b8be0e144e72113508bcff6 *tests/data/fate/acodec-adpcm-swf-trellis.flv +267801 tests/data/fate/acodec-adpcm-swf-trellis.flv +6a0007e42d92a225a8becddedccf9a0f *tests/data/fate/acodec-adpcm-swf-trellis.out.wav +stddev: 731.05 PSNR: 39.05 MAXDIFF:51119 bytes: 1058400/ 1064960 diff -Nru ffmpeg-4.2.2/tests/ref/acodec/adpcm-swf-wav ffmpeg-4.4/tests/ref/acodec/adpcm-swf-wav --- ffmpeg-4.2.2/tests/ref/acodec/adpcm-swf-wav 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/acodec/adpcm-swf-wav 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,4 @@ +a21ee5ba531ec89e306d78c861eb6ed1 *tests/data/fate/acodec-adpcm-swf-wav.wav +266624 tests/data/fate/acodec-adpcm-swf-wav.wav +9d061488fdc1a557bdc454b9d1aba59c *tests/data/fate/acodec-adpcm-swf-wav.out.wav +stddev: 919.82 PSNR: 37.06 MAXDIFF:51119 bytes: 1058400/ 1064960 diff -Nru ffmpeg-4.2.2/tests/ref/acodec/s302m ffmpeg-4.4/tests/ref/acodec/s302m --- ffmpeg-4.2.2/tests/ref/acodec/s302m 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/acodec/s302m 2020-07-11 10:39:30.000000000 +0000 @@ -1,4 +1,4 @@ -165d022ab86306d069797acff0c1e295 *tests/data/fate/acodec-s302m.mpegts -1589164 tests/data/fate/acodec-s302m.mpegts +0bf5457fd41a22fc5cdd99ae5ad4e273 *tests/data/fate/acodec-s302m.mpegts +1527688 tests/data/fate/acodec-s302m.mpegts 31f25a0020fd9017de9c3c608316854b *tests/data/fate/acodec-s302m.out.wav stddev: 986.94 PSNR: 36.44 MAXDIFF:18571 bytes: 1058400/ 1056708 diff -Nru ffmpeg-4.2.2/tests/ref/fate/aac-autobsf-adtstoasc ffmpeg-4.4/tests/ref/fate/aac-autobsf-adtstoasc --- ffmpeg-4.2.2/tests/ref/fate/aac-autobsf-adtstoasc 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/aac-autobsf-adtstoasc 2020-07-11 10:39:30.000000000 +0000 @@ -1,5 +1,5 @@ -b09fc2f554712adbf84fe7899eb679d4 *tests/data/fate/aac-autobsf-adtstoasc.matroska -6695 tests/data/fate/aac-autobsf-adtstoasc.matroska +5088977b7f13181d707a4077771e4552 *tests/data/fate/aac-autobsf-adtstoasc.matroska +6648 tests/data/fate/aac-autobsf-adtstoasc.matroska #extradata 0: 2, 0x0030001c #tb 0: 1/1000 #media_type 0: audio diff -Nru ffmpeg-4.2.2/tests/ref/fate/aa-demux ffmpeg-4.4/tests/ref/fate/aa-demux --- ffmpeg-4.2.2/tests/ref/fate/aa-demux 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/aa-demux 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,283 @@ +#tb 0: 1/1062500 +#media_type 0: audio +#codec_id 0: sipr +#sample_rate 0: 8500 +#channel_layout 0: 4 +#channel_layout_name 0: mono +0, 0, 0, 18000, 19, 0x36e10529 +0, 18000, 18000, 18000, 19, 0x70810a69 +0, 36000, 36000, 18000, 19, 0x618f08a0 +0, 54000, 54000, 18000, 19, 0x65a508bd +0, 72000, 72000, 18000, 19, 0x50420796 +0, 90000, 90000, 18000, 19, 0x6468084f +0, 108000, 108000, 18000, 19, 0x75020a84 +0, 126000, 126000, 18000, 19, 0x68be09ae +0, 144000, 144000, 18000, 19, 0x6cb709b8 +0, 162000, 162000, 18000, 19, 0x3fee061e +0, 180000, 180000, 18000, 19, 0x53220770 +0, 198000, 198000, 18000, 19, 0x57590888 +0, 216000, 216000, 18000, 19, 0x6653089c +0, 234000, 234000, 18000, 19, 0x55eb081f +0, 252000, 252000, 18000, 19, 0x79750ad6 +0, 270000, 270000, 18000, 19, 0x5e340927 +0, 288000, 288000, 18000, 19, 0x60c80974 +0, 306000, 306000, 18000, 19, 0x6c5008f5 +0, 324000, 324000, 18000, 19, 0x6f5609ca +0, 342000, 342000, 18000, 19, 0x79a609f5 +0, 360000, 360000, 18000, 19, 0x6fa308d5 +0, 378000, 378000, 18000, 19, 0x56de0789 +0, 396000, 396000, 18000, 19, 0x567408bf +0, 414000, 414000, 18000, 19, 0x62800968 +0, 432000, 432000, 18000, 19, 0x64ae0a88 +0, 450000, 450000, 18000, 19, 0x73eb0af5 +0, 468000, 468000, 18000, 19, 0x6f1e0ac0 +0, 486000, 486000, 18000, 19, 0x5d0e0a34 +0, 504000, 504000, 18000, 19, 0x61990a70 +0, 522000, 522000, 18000, 19, 0x71e00a8a +0, 540000, 540000, 18000, 19, 0x6c400a3f +0, 558000, 558000, 18000, 19, 0x5f850921 +0, 576000, 576000, 18000, 19, 0x6e7e0a5e +0, 594000, 594000, 18000, 19, 0x4bbe08cd +0, 612000, 612000, 18000, 19, 0x62c407d5 +0, 630000, 630000, 18000, 19, 0x475f07b9 +0, 648000, 648000, 18000, 19, 0x6f480a68 +0, 666000, 666000, 18000, 19, 0x65710a4d +0, 684000, 684000, 18000, 19, 0x4b2d0841 +0, 702000, 702000, 18000, 19, 0x64a80a03 +0, 720000, 720000, 18000, 19, 0x61f608fa +0, 738000, 738000, 18000, 19, 0x6fb70a5e +0, 756000, 756000, 18000, 19, 0x5f4e0a48 +0, 774000, 774000, 18000, 19, 0x5a200919 +0, 792000, 792000, 18000, 19, 0x69af0a1f +0, 810000, 810000, 18000, 19, 0x643d094a +0, 828000, 828000, 18000, 19, 0x56e707f7 +0, 846000, 846000, 18000, 19, 0x60ed0923 +0, 864000, 864000, 18000, 19, 0x6d5d099c +0, 882000, 882000, 18000, 19, 0x736d0abd +0, 900000, 900000, 18000, 19, 0x578d0981 +0, 918000, 918000, 18000, 19, 0x621f0979 +0, 936000, 936000, 18000, 19, 0x690a0938 +0, 954000, 954000, 18000, 19, 0x55df096f +0, 972000, 972000, 18000, 19, 0x5b900945 +0, 990000, 990000, 18000, 19, 0x595e090a +0, 1008000, 1008000, 18000, 19, 0x6f3a0b0d +0, 1026000, 1026000, 18000, 19, 0x5df80902 +0, 1044000, 1044000, 18000, 19, 0x61fa08f6 +0, 1062000, 1062000, 18000, 19, 0x6a8e0a90 +0, 1080000, 1080000, 18000, 19, 0x7ec40b7d +0, 1098000, 1098000, 18000, 19, 0x554707e3 +0, 1116000, 1116000, 18000, 19, 0x5ef9097a +0, 1134000, 1134000, 18000, 19, 0x74d40c65 +0, 1152000, 1152000, 18000, 19, 0x52c909a3 +0, 1170000, 1170000, 18000, 19, 0x79740b0c +0, 1188000, 1188000, 18000, 19, 0x64350b42 +0, 1206000, 1206000, 18000, 19, 0x65f109f4 +0, 1224000, 1224000, 18000, 19, 0x53760920 +0, 1242000, 1242000, 18000, 19, 0x5600091a +0, 1260000, 1260000, 18000, 19, 0x5b4e08c2 +0, 1278000, 1278000, 18000, 19, 0x672d09d0 +0, 1296000, 1296000, 18000, 19, 0x658e09bc +0, 1314000, 1314000, 18000, 19, 0x5a560999 +0, 1332000, 1332000, 18000, 19, 0x69a40ae0 +0, 1350000, 1350000, 18000, 19, 0x602a0855 +0, 1368000, 1368000, 18000, 19, 0x4f8606ed +0, 1386000, 1386000, 18000, 19, 0x78cb0afe +0, 1404000, 1404000, 18000, 19, 0x661609dc +0, 1422000, 1422000, 18000, 19, 0x6ea50b3d +0, 1440000, 1440000, 18000, 19, 0x60a709dd +0, 1458000, 1458000, 18000, 19, 0x55ef082b +0, 1476000, 1476000, 18000, 19, 0x6ab70a57 +0, 1494000, 1494000, 18000, 19, 0x68cb0b92 +0, 1512000, 1512000, 18000, 19, 0x752809f5 +0, 1530000, 1530000, 18000, 19, 0x4e810789 +0, 1548000, 1548000, 18000, 19, 0x60130987 +0, 1566000, 1566000, 18000, 19, 0x5ea40a08 +0, 1584000, 1584000, 18000, 19, 0x628507d4 +0, 1602000, 1602000, 18000, 19, 0x5fc2096c +0, 1620000, 1620000, 18000, 19, 0x52a70775 +0, 1638000, 1638000, 18000, 19, 0x6e4b09af +0, 1656000, 1656000, 18000, 19, 0x79750aab +0, 1674000, 1674000, 18000, 19, 0x5e23085a +0, 1692000, 1692000, 18000, 19, 0x4fb8081b +0, 1710000, 1710000, 18000, 19, 0x574b07fc +0, 1728000, 1728000, 18000, 19, 0x59d407b2 +0, 1746000, 1746000, 18000, 19, 0x56d308d4 +0, 1764000, 1764000, 18000, 19, 0x61310856 +0, 1782000, 1782000, 18000, 19, 0x4df90867 +0, 1800000, 1800000, 18000, 19, 0x3d760522 +0, 1818000, 1818000, 18000, 19, 0x5a0f0917 +0, 1836000, 1836000, 18000, 19, 0x5e8d0939 +0, 1854000, 1854000, 18000, 19, 0x65ee081a +0, 1872000, 1872000, 18000, 19, 0x4665056f +0, 1890000, 1890000, 18000, 19, 0x55c70851 +0, 1908000, 1908000, 18000, 19, 0x6cf00a94 +0, 1926000, 1926000, 18000, 19, 0x698308f0 +0, 1944000, 1944000, 18000, 19, 0x4c9106c9 +0, 1962000, 1962000, 18000, 19, 0x719d0a28 +0, 1980000, 1980000, 18000, 19, 0x491f06cc +0, 1998000, 1998000, 18000, 19, 0x61fa0972 +0, 2016000, 2016000, 18000, 19, 0x49b105cb +0, 2034000, 2034000, 18000, 19, 0x4b5f071f +0, 2052000, 2052000, 18000, 19, 0x5e8e08b3 +0, 2070000, 2070000, 18000, 19, 0x5d2309bb +0, 2088000, 2088000, 18000, 19, 0x4e8806d1 +0, 2106000, 2106000, 18000, 19, 0x566607dc +0, 2124000, 2124000, 18000, 19, 0x4b2506ee +0, 2142000, 2142000, 18000, 19, 0x4d810687 +0, 2160000, 2160000, 18000, 19, 0x51990841 +0, 2178000, 2178000, 18000, 19, 0x5e220870 +0, 2196000, 2196000, 18000, 19, 0x4b2f0787 +0, 2214000, 2214000, 18000, 19, 0x4a4b05f0 +0, 2232000, 2232000, 18000, 19, 0x485106b5 +0, 2250000, 2250000, 18000, 19, 0x58d20755 +0, 2268000, 2268000, 18000, 19, 0x51b807ad +0, 2286000, 2286000, 18000, 19, 0x475b06d0 +0, 2304000, 2304000, 18000, 19, 0x4f93072f +0, 2322000, 2322000, 18000, 19, 0x5841082a +0, 2340000, 2340000, 18000, 19, 0x5e7f08f6 +0, 2358000, 2358000, 18000, 19, 0x4cb7075c +0, 2376000, 2376000, 18000, 19, 0x560807b9 +0, 2394000, 2394000, 18000, 19, 0x49fb0732 +0, 2412000, 2412000, 18000, 19, 0x56790830 +0, 2430000, 2430000, 18000, 19, 0x4962066b +0, 2448000, 2448000, 18000, 19, 0x4f410703 +0, 2466000, 2466000, 18000, 19, 0x517c078f +0, 2484000, 2484000, 18000, 19, 0x594c0850 +0, 2502000, 2502000, 18000, 19, 0x5df7089d +0, 2520000, 2520000, 18000, 19, 0x4b0c0813 +0, 2538000, 2538000, 18000, 19, 0x5b4d08ec +0, 2556000, 2556000, 18000, 19, 0x66840a37 +0, 2574000, 2574000, 18000, 19, 0x60d20942 +0, 2592000, 2592000, 18000, 19, 0x5049082e +0, 2610000, 2610000, 18000, 19, 0x64a60b38 +0, 2628000, 2628000, 18000, 19, 0x49400889 +0, 2646000, 2646000, 18000, 19, 0x598608f6 +0, 2664000, 2664000, 18000, 19, 0x496e0736 +0, 2682000, 2682000, 18000, 19, 0x5c5008af +0, 2700000, 2700000, 18000, 19, 0x633b0aa7 +0, 2718000, 2718000, 18000, 19, 0x58ae0888 +0, 2736000, 2736000, 18000, 19, 0x3da106b3 +0, 2754000, 2754000, 18000, 19, 0x3f7b077b +0, 2772000, 2772000, 18000, 19, 0x4ba60917 +0, 2790000, 2790000, 18000, 19, 0x5637099b +0, 2808000, 2808000, 18000, 19, 0x61e10a50 +0, 2826000, 2826000, 18000, 19, 0x5157078e +0, 2844000, 2844000, 18000, 19, 0x55cf0943 +0, 2862000, 2862000, 18000, 19, 0x59b308cb +0, 2880000, 2880000, 18000, 19, 0x61920a8e +0, 2898000, 2898000, 18000, 19, 0x6ee20b7b +0, 2916000, 2916000, 18000, 19, 0x67620a9a +0, 2934000, 2934000, 18000, 19, 0x57cb0933 +0, 2952000, 2952000, 18000, 19, 0x618209d8 +0, 2970000, 2970000, 18000, 19, 0x65bb0a22 +0, 2988000, 2988000, 18000, 19, 0x55ec0911 +0, 3006000, 3006000, 18000, 19, 0x607e0966 +0, 3024000, 3024000, 18000, 19, 0x40ee05f0 +0, 3042000, 3042000, 18000, 19, 0x5b9308f5 +0, 3060000, 3060000, 18000, 19, 0x5eb3089a +0, 3078000, 3078000, 18000, 19, 0x555a0842 +0, 3096000, 3096000, 18000, 19, 0x66980839 +0, 3114000, 3114000, 18000, 19, 0x532e08d2 +0, 3132000, 3132000, 18000, 19, 0x672d0a76 +0, 3150000, 3150000, 18000, 19, 0x5c780996 +0, 3168000, 3168000, 18000, 19, 0x51d408cc +0, 3186000, 3186000, 18000, 19, 0x6ee10c12 +0, 3204000, 3204000, 18000, 19, 0x463c081d +0, 3222000, 3222000, 18000, 19, 0x65850aa0 +0, 3240000, 3240000, 18000, 19, 0x6d1c0a88 +0, 3258000, 3258000, 18000, 19, 0x5ace08d7 +0, 3276000, 3276000, 18000, 19, 0x5fef096a +0, 3294000, 3294000, 18000, 19, 0x590607e9 +0, 3312000, 3312000, 18000, 19, 0x61bd0a65 +0, 3330000, 3330000, 18000, 19, 0x633808c2 +0, 3348000, 3348000, 18000, 19, 0x3ea2063a +0, 3366000, 3366000, 18000, 19, 0x5ff70a03 +0, 3384000, 3384000, 18000, 19, 0x6c020997 +0, 3402000, 3402000, 18000, 19, 0x82b00c41 +0, 3420000, 3420000, 18000, 19, 0x6b9509d2 +0, 3438000, 3438000, 18000, 19, 0x54af0943 +0, 3456000, 3456000, 18000, 19, 0x49d40802 +0, 3474000, 3474000, 18000, 19, 0x52de08df +0, 3492000, 3492000, 18000, 19, 0x6dae0ad8 +0, 3510000, 3510000, 18000, 19, 0x5fbc0883 +0, 3528000, 3528000, 18000, 19, 0x56620873 +0, 3546000, 3546000, 18000, 19, 0x5203093c +0, 3564000, 3564000, 18000, 19, 0x653d0b5f +0, 3582000, 3582000, 18000, 19, 0x6068097d +0, 3600000, 3600000, 18000, 19, 0x57700810 +0, 3618000, 3618000, 18000, 19, 0x562809ce +0, 3636000, 3636000, 18000, 19, 0x57ad0849 +0, 3654000, 3654000, 18000, 19, 0x5dde099d +0, 3672000, 3672000, 18000, 19, 0x66700947 +0, 3690000, 3690000, 18000, 19, 0x5ca108fb +0, 3708000, 3708000, 18000, 19, 0x53270773 +0, 3726000, 3726000, 18000, 19, 0x63a50a30 +0, 3744000, 3744000, 18000, 19, 0x64f20a63 +0, 3762000, 3762000, 18000, 19, 0x654509e0 +0, 3780000, 3780000, 18000, 19, 0x560207f2 +0, 3798000, 3798000, 18000, 19, 0x54bf0811 +0, 3816000, 3816000, 18000, 19, 0x5bb70a2d +0, 3834000, 3834000, 18000, 19, 0x661d08dd +0, 3852000, 3852000, 18000, 19, 0x4f130960 +0, 3870000, 3870000, 18000, 19, 0x56000920 +0, 3888000, 3888000, 18000, 19, 0x59110a1d +0, 3906000, 3906000, 18000, 19, 0x588009c7 +0, 3924000, 3924000, 18000, 19, 0x60b40a23 +0, 3942000, 3942000, 18000, 19, 0x5ab708dd +0, 3960000, 3960000, 18000, 19, 0x510208b6 +0, 3978000, 3978000, 18000, 19, 0x4cbb07fd +0, 3996000, 3996000, 18000, 19, 0x5a990938 +0, 4014000, 4014000, 18000, 19, 0x671b09f7 +0, 4032000, 4032000, 18000, 19, 0x76d90a8a +0, 4050000, 4050000, 18000, 19, 0x81350b4b +0, 4068000, 4068000, 18000, 19, 0x5eeb08b8 +0, 4086000, 4086000, 18000, 19, 0x538d0a68 +0, 4104000, 4104000, 18000, 19, 0x649a0962 +0, 4122000, 4122000, 18000, 19, 0x64130a0b +0, 4140000, 4140000, 18000, 19, 0x5ef30948 +0, 4158000, 4158000, 18000, 19, 0x585a0824 +0, 4176000, 4176000, 18000, 19, 0x46ce07ff +0, 4194000, 4194000, 18000, 19, 0x50bc08da +0, 4212000, 4212000, 18000, 19, 0x5b1d08a5 +0, 4230000, 4230000, 18000, 19, 0x5da50993 +0, 4248000, 4248000, 18000, 19, 0x4d15087b +0, 4266000, 4266000, 18000, 19, 0x472106a1 +0, 4284000, 4284000, 18000, 19, 0x6713098a +0, 4302000, 4302000, 18000, 19, 0x4bec0881 +0, 4320000, 4320000, 18000, 19, 0x607109d9 +0, 4338000, 4338000, 18000, 19, 0x631a0af3 +0, 4356000, 4356000, 18000, 19, 0x7b020b89 +0, 4374000, 4374000, 18000, 19, 0x6cc80ae5 +0, 4392000, 4392000, 18000, 19, 0x5bce0a35 +0, 4410000, 4410000, 18000, 19, 0x71750a72 +0, 4428000, 4428000, 18000, 19, 0x61330af8 +0, 4446000, 4446000, 18000, 19, 0x80390d10 +0, 4464000, 4464000, 18000, 19, 0x60300a32 +0, 4482000, 4482000, 18000, 19, 0x4bbb0764 +0, 4500000, 4500000, 18000, 19, 0x749c0a92 +0, 4518000, 4518000, 18000, 19, 0x5d0709ce +0, 4536000, 4536000, 18000, 19, 0x75400bd2 +0, 4554000, 4554000, 18000, 19, 0x56b008ed +0, 4572000, 4572000, 18000, 19, 0x5b5309ec +0, 4590000, 4590000, 18000, 19, 0x4f110862 +0, 4608000, 4608000, 18000, 19, 0x574e0869 +0, 4626000, 4626000, 18000, 19, 0x58e409a7 +0, 4644000, 4644000, 18000, 19, 0x636108d7 +0, 4662000, 4662000, 18000, 19, 0x5a8b0862 +0, 4680000, 4680000, 18000, 19, 0x508908ec +0, 4698000, 4698000, 18000, 19, 0x4bdd06d8 +0, 4716000, 4716000, 18000, 19, 0x6abb0a58 +0, 4734000, 4734000, 18000, 19, 0x674b0ab4 +0, 4752000, 4752000, 18000, 19, 0x587d08be +0, 4770000, 4770000, 18000, 19, 0x63f808b9 +0, 4788000, 4788000, 18000, 19, 0x662609e4 +0, 4806000, 4806000, 18000, 19, 0x6c490b07 +0, 4824000, 4824000, 18000, 19, 0x41df075a +0, 4842000, 4842000, 18000, 19, 0x5f870a0f +0, 4860000, 4860000, 18000, 19, 0x600f0a87 +0, 4878000, 4878000, 18000, 19, 0x535f0880 +0, 4896000, 4896000, 18000, 19, 0x5f3a09e5 +0, 4914000, 4914000, 18000, 19, 0x529d08d4 +0, 4932000, 4932000, 18000, 19, 0x67630a76 +0, 4950000, 4950000, 18000, 19, 0x4bc40844 +0, 4968000, 4968000, 18000, 19, 0x5091083a diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-argo-mono ffmpeg-4.4/tests/ref/fate/adpcm-argo-mono --- ffmpeg-4.2.2/tests/ref/fate/adpcm-argo-mono 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-argo-mono 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +3876d24a376b1ab1f6d207b7abda635e diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-argo-stereo ffmpeg-4.4/tests/ref/fate/adpcm-argo-stereo --- ffmpeg-4.2.2/tests/ref/fate/adpcm-argo-stereo 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-argo-stereo 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +53ad310be0175583a5c3c0e5fe341b18 diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-alp-mono ffmpeg-4.4/tests/ref/fate/adpcm-ima-alp-mono --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-alp-mono 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-alp-mono 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +288d1ce2e92240ccebfe2586fc22d01b diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-alp-stereo ffmpeg-4.4/tests/ref/fate/adpcm-ima-alp-stereo --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-alp-stereo 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-alp-stereo 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +a100877e7e02b8a6ad63154682c844f4 diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-amv ffmpeg-4.4/tests/ref/fate/adpcm-ima-amv --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-amv 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-amv 2021-04-08 21:28:40.000000000 +0000 @@ -8,159 +8,159 @@ 0, 1378, 1378, 1378, 2756, 0x8462443f 0, 2756, 2756, 1378, 2756, 0x9f493ba6 0, 4134, 4134, 1378, 2756, 0x634e5f06 -0, 5512, 5512, 1380, 2760, 0x51f35cd4 -0, 6892, 6892, 1378, 2756, 0x011c51e5 -0, 8270, 8270, 1378, 2756, 0x8c2c198c -0, 9648, 9648, 1378, 2756, 0x2b4a3397 -0, 11026, 11026, 1378, 2756, 0x63794f22 -0, 12404, 12404, 1378, 2756, 0xfc363898 -0, 13782, 13782, 1378, 2756, 0x0da5486e -0, 15160, 15160, 1378, 2756, 0xbae17a5f -0, 16538, 16538, 1380, 2760, 0xba266e1b -0, 17918, 17918, 1378, 2756, 0xdfb61002 -0, 19296, 19296, 1378, 2756, 0x15d029da -0, 20674, 20674, 1378, 2756, 0x7bc82012 -0, 22052, 22052, 1378, 2756, 0x002e6999 -0, 23430, 23430, 1378, 2756, 0x96346ba6 -0, 24808, 24808, 1378, 2756, 0x3d54543b -0, 26186, 26186, 1380, 2760, 0x601786e1 -0, 27566, 27566, 1378, 2756, 0xf22a5793 -0, 28944, 28944, 1378, 2756, 0x21f54d49 -0, 30322, 30322, 1378, 2756, 0x0c6d4399 -0, 31700, 31700, 1378, 2756, 0x17282f8e -0, 33078, 33078, 1378, 2756, 0xeb698f75 -0, 34456, 34456, 1378, 2756, 0x935e1de2 -0, 35834, 35834, 1380, 2760, 0xb6fb4293 -0, 37214, 37214, 1378, 2756, 0x485053dc -0, 38592, 38592, 1378, 2756, 0x24c35027 -0, 39970, 39970, 1378, 2756, 0x09f323ee -0, 41348, 41348, 1378, 2756, 0xbc7d58d5 -0, 42726, 42726, 1378, 2756, 0xaefd487c -0, 44104, 44104, 1378, 2756, 0xaca16cc0 -0, 45482, 45482, 1380, 2760, 0x98a76091 -0, 46862, 46862, 1378, 2756, 0x5d357141 -0, 48240, 48240, 1378, 2756, 0x65ea2657 -0, 49618, 49618, 1378, 2756, 0xb5e1334a -0, 50996, 50996, 1378, 2756, 0x32cd5d91 -0, 52374, 52374, 1378, 2756, 0xdc23722b -0, 53752, 53752, 1378, 2756, 0x2ba34684 -0, 55130, 55130, 1378, 2756, 0xf9755ba8 -0, 56508, 56508, 1380, 2760, 0x24221ddb -0, 57888, 57888, 1378, 2756, 0xef843aa4 -0, 59266, 59266, 1378, 2756, 0x420442fe -0, 60644, 60644, 1378, 2756, 0x5a0933cb -0, 62022, 62022, 1378, 2756, 0xef5f6d61 -0, 63400, 63400, 1378, 2756, 0xe57e6dc0 -0, 64778, 64778, 1378, 2756, 0xc0f0495a -0, 66156, 66156, 1380, 2760, 0x2c3b55df -0, 67536, 67536, 1378, 2756, 0x39c2586c -0, 68914, 68914, 1378, 2756, 0x7ffc46e5 -0, 70292, 70292, 1378, 2756, 0xa2766664 -0, 71670, 71670, 1378, 2756, 0xacb50c6c -0, 73048, 73048, 1378, 2756, 0x7f659084 -0, 74426, 74426, 1378, 2756, 0xc72e6a12 -0, 75804, 75804, 1380, 2760, 0xdb6944df -0, 77184, 77184, 1378, 2756, 0x954f45c1 -0, 78562, 78562, 1378, 2756, 0xa9484240 -0, 79940, 79940, 1378, 2756, 0x1d595349 -0, 81318, 81318, 1378, 2756, 0xcf2a565e -0, 82696, 82696, 1378, 2756, 0x391028d5 -0, 84074, 84074, 1378, 2756, 0x348db7ad -0, 85452, 85452, 1380, 2760, 0xb69b5e3a -0, 86832, 86832, 1378, 2756, 0xe3635fbe -0, 88210, 88210, 1378, 2756, 0xdcad3654 -0, 89588, 89588, 1378, 2756, 0x5c17abef -0, 90966, 90966, 1378, 2756, 0xb3235184 -0, 92344, 92344, 1378, 2756, 0xdabb64a6 -0, 93722, 93722, 1378, 2756, 0xa95dc58d -0, 95100, 95100, 1380, 2760, 0x8e7ac9eb -0, 96480, 96480, 1378, 2756, 0x492b658e -0, 97858, 97858, 1378, 2756, 0x377483ab -0, 99236, 99236, 1378, 2756, 0x2c250279 -0, 100614, 100614, 1378, 2756, 0x704dbdb3 -0, 101992, 101992, 1378, 2756, 0x800d7da2 -0, 103370, 103370, 1378, 2756, 0x872aa32e -0, 104748, 104748, 1378, 2756, 0x2d4837fe -0, 106126, 106126, 1380, 2760, 0xc89ea57e -0, 107506, 107506, 1378, 2756, 0x6447d7ef -0, 108884, 108884, 1378, 2756, 0x144f59cc -0, 110262, 110262, 1378, 2756, 0xc667154e -0, 111640, 111640, 1378, 2756, 0xf0de66ae -0, 113018, 113018, 1378, 2756, 0xeabf3c32 -0, 114396, 114396, 1378, 2756, 0xe98e81d1 -0, 115774, 115774, 1380, 2760, 0x56aa5889 -0, 117154, 117154, 1378, 2756, 0x4fd34c0e -0, 118532, 118532, 1378, 2756, 0x67cf6912 -0, 119910, 119910, 1378, 2756, 0xfa944def -0, 121288, 121288, 1378, 2756, 0xc12f23b2 -0, 122666, 122666, 1378, 2756, 0x5ea325a2 -0, 124044, 124044, 1378, 2756, 0x2b245824 -0, 125422, 125422, 1380, 2760, 0x90ac533e -0, 126802, 126802, 1378, 2756, 0xcca34d26 -0, 128180, 128180, 1378, 2756, 0xb5f820d0 -0, 129558, 129558, 1378, 2756, 0x27f24335 -0, 130936, 130936, 1378, 2756, 0x4a9e87b7 -0, 132314, 132314, 1378, 2756, 0xbd076129 -0, 133692, 133692, 1378, 2756, 0x2e0e3f2e -0, 135070, 135070, 1380, 2760, 0xdf534478 -0, 136450, 136450, 1378, 2756, 0xca000a2e -0, 137828, 137828, 1378, 2756, 0x87472df3 -0, 139206, 139206, 1378, 2756, 0x16733810 -0, 140584, 140584, 1378, 2756, 0xfa0734b4 -0, 141962, 141962, 1378, 2756, 0x5eff3fc4 -0, 143340, 143340, 1378, 2756, 0xf35346bd -0, 144718, 144718, 1378, 2756, 0xac6411c5 -0, 146096, 146096, 1380, 2760, 0x478c3c56 -0, 147476, 147476, 1378, 2756, 0xebd30bdd -0, 148854, 148854, 1378, 2756, 0xaef95a31 -0, 150232, 150232, 1378, 2756, 0x8aad29d1 -0, 151610, 151610, 1378, 2756, 0x626863f0 -0, 152988, 152988, 1378, 2756, 0x68c05707 -0, 154366, 154366, 1378, 2756, 0x437c5e8d -0, 155744, 155744, 1380, 2760, 0x8eca4bdb -0, 157124, 157124, 1378, 2756, 0x62bd4162 -0, 158502, 158502, 1378, 2756, 0x9f744aa4 -0, 159880, 159880, 1378, 2756, 0x0f3f6409 -0, 161258, 161258, 1378, 2756, 0x3fee827a -0, 162636, 162636, 1378, 2756, 0x48a0ac19 -0, 164014, 164014, 1378, 2756, 0x8e4ce0d0 -0, 165392, 165392, 1380, 2760, 0xcda82236 -0, 166772, 166772, 1378, 2756, 0x0e523255 -0, 168150, 168150, 1378, 2756, 0x84103d30 -0, 169528, 169528, 1378, 2756, 0x13941cde -0, 170906, 170906, 1378, 2756, 0x9fc834c5 -0, 172284, 172284, 1378, 2756, 0xc0217a77 -0, 173662, 173662, 1378, 2756, 0x3f643659 -0, 175040, 175040, 1380, 2760, 0x9dbd6002 -0, 176420, 176420, 1378, 2756, 0x94f046fb -0, 177798, 177798, 1378, 2756, 0xab01fb12 -0, 179176, 179176, 1378, 2756, 0x04cffe5c -0, 180554, 180554, 1378, 2756, 0xef661c5e -0, 181932, 181932, 1378, 2756, 0x094c5fc5 -0, 183310, 183310, 1378, 2756, 0xe0c1486a -0, 184688, 184688, 1380, 2760, 0x8c3535b7 -0, 186068, 186068, 1378, 2756, 0x594934aa -0, 187446, 187446, 1378, 2756, 0x74007238 -0, 188824, 188824, 1378, 2756, 0x61f1394d -0, 190202, 190202, 1378, 2756, 0x72584f07 -0, 191580, 191580, 1378, 2756, 0xced9acf9 -0, 192958, 192958, 1378, 2756, 0x7d2e3ea1 -0, 194336, 194336, 1378, 2756, 0x56c06897 -0, 195714, 195714, 1380, 2760, 0x19983bbf -0, 197094, 197094, 1378, 2756, 0x4f884f27 -0, 198472, 198472, 1378, 2756, 0x81ab2f63 -0, 199850, 199850, 1378, 2756, 0x448e681d -0, 201228, 201228, 1378, 2756, 0x0ba9826e -0, 202606, 202606, 1378, 2756, 0x049f36fa -0, 203984, 203984, 1378, 2756, 0x096a2b62 -0, 205362, 205362, 1380, 2760, 0x579e2035 -0, 206742, 206742, 1378, 2756, 0xd13e30e1 -0, 208120, 208120, 1378, 2756, 0x30b6412b -0, 209498, 209498, 1378, 2756, 0xbb1c3268 -0, 210876, 210876, 1378, 2756, 0xbc175b6a -0, 212254, 212254, 1378, 2756, 0xf8d160e2 -0, 213632, 213632, 1378, 2756, 0xc1048154 -0, 215010, 215010, 1380, 2760, 0xb83548f4 -0, 216390, 216390, 1378, 2756, 0x22647962 -0, 217768, 217768, 1378, 2756, 0x14ca54d3 -0, 219146, 219146, 1354, 2708, 0x85e82e8d +0, 5512, 5512, 1379, 2758, 0x983d5ccb +0, 6891, 6891, 1378, 2756, 0x011c51e5 +0, 8269, 8269, 1378, 2756, 0x8c2c198c +0, 9647, 9647, 1378, 2756, 0x2b4a3397 +0, 11025, 11025, 1378, 2756, 0x63794f22 +0, 12403, 12403, 1378, 2756, 0xfc363898 +0, 13781, 13781, 1378, 2756, 0x0da5486e +0, 15159, 15159, 1378, 2756, 0xbae17a5f +0, 16537, 16537, 1379, 2758, 0xdde86dc6 +0, 17916, 17916, 1378, 2756, 0xdfb61002 +0, 19294, 19294, 1378, 2756, 0x15d029da +0, 20672, 20672, 1378, 2756, 0x7bc82012 +0, 22050, 22050, 1378, 2756, 0x002e6999 +0, 23428, 23428, 1378, 2756, 0x96346ba6 +0, 24806, 24806, 1378, 2756, 0x3d54543b +0, 26184, 26184, 1379, 2758, 0x5248862b +0, 27563, 27563, 1378, 2756, 0xf22a5793 +0, 28941, 28941, 1378, 2756, 0x21f54d49 +0, 30319, 30319, 1378, 2756, 0x0c6d4399 +0, 31697, 31697, 1378, 2756, 0x17282f8e +0, 33075, 33075, 1378, 2756, 0xeb698f75 +0, 34453, 34453, 1378, 2756, 0x935e1de2 +0, 35831, 35831, 1379, 2758, 0x31d5425d +0, 37210, 37210, 1378, 2756, 0x485053dc +0, 38588, 38588, 1378, 2756, 0x24c35027 +0, 39966, 39966, 1378, 2756, 0x09f323ee +0, 41344, 41344, 1378, 2756, 0xbc7d58d5 +0, 42722, 42722, 1378, 2756, 0xaefd487c +0, 44100, 44100, 1378, 2756, 0xaca16cc0 +0, 45478, 45478, 1379, 2758, 0xd8745ed3 +0, 46857, 46857, 1378, 2756, 0x5d357141 +0, 48235, 48235, 1378, 2756, 0x65ea2657 +0, 49613, 49613, 1378, 2756, 0xb5e1334a +0, 50991, 50991, 1378, 2756, 0x32cd5d91 +0, 52369, 52369, 1378, 2756, 0xdc23722b +0, 53747, 53747, 1378, 2756, 0x2ba34684 +0, 55125, 55125, 1378, 2756, 0xf9755ba8 +0, 56503, 56503, 1379, 2758, 0xe95c1ca8 +0, 57882, 57882, 1378, 2756, 0xef843aa4 +0, 59260, 59260, 1378, 2756, 0x420442fe +0, 60638, 60638, 1378, 2756, 0x5a0933cb +0, 62016, 62016, 1378, 2756, 0xef5f6d61 +0, 63394, 63394, 1378, 2756, 0xe57e6dc0 +0, 64772, 64772, 1378, 2756, 0xc0f0495a +0, 66150, 66150, 1379, 2758, 0x806e55de +0, 67529, 67529, 1378, 2756, 0x39c2586c +0, 68907, 68907, 1378, 2756, 0x7ffc46e5 +0, 70285, 70285, 1378, 2756, 0xa2766664 +0, 71663, 71663, 1378, 2756, 0xacb50c6c +0, 73041, 73041, 1378, 2756, 0x7f659084 +0, 74419, 74419, 1378, 2756, 0xc72e6a12 +0, 75797, 75797, 1379, 2758, 0x51ab446d +0, 77176, 77176, 1378, 2756, 0x954f45c1 +0, 78554, 78554, 1378, 2756, 0xa9484240 +0, 79932, 79932, 1378, 2756, 0x1d595349 +0, 81310, 81310, 1378, 2756, 0xcf2a565e +0, 82688, 82688, 1378, 2756, 0x391028d5 +0, 84066, 84066, 1378, 2756, 0x348db7ad +0, 85444, 85444, 1379, 2758, 0xfa185e28 +0, 86823, 86823, 1378, 2756, 0xe3635fbe +0, 88201, 88201, 1378, 2756, 0xdcad3654 +0, 89579, 89579, 1378, 2756, 0x5c17abef +0, 90957, 90957, 1378, 2756, 0xb3235184 +0, 92335, 92335, 1378, 2756, 0xdabb64a6 +0, 93713, 93713, 1378, 2756, 0xa95dc58d +0, 95091, 95091, 1379, 2758, 0xfa89c99b +0, 96470, 96470, 1378, 2756, 0x492b658e +0, 97848, 97848, 1378, 2756, 0x377483ab +0, 99226, 99226, 1378, 2756, 0x2c250279 +0, 100604, 100604, 1378, 2756, 0x704dbdb3 +0, 101982, 101982, 1378, 2756, 0x800d7da2 +0, 103360, 103360, 1378, 2756, 0x872aa32e +0, 104738, 104738, 1378, 2756, 0x2d4837fe +0, 106116, 106116, 1379, 2758, 0x7d93a536 +0, 107495, 107495, 1378, 2756, 0x6447d7ef +0, 108873, 108873, 1378, 2756, 0x144f59cc +0, 110251, 110251, 1378, 2756, 0xc667154e +0, 111629, 111629, 1378, 2756, 0xf0de66ae +0, 113007, 113007, 1378, 2756, 0xeabf3c32 +0, 114385, 114385, 1378, 2756, 0xe98e81d1 +0, 115763, 115763, 1379, 2758, 0xa58a57f4 +0, 117142, 117142, 1378, 2756, 0x4fd34c0e +0, 118520, 118520, 1378, 2756, 0x67cf6912 +0, 119898, 119898, 1378, 2756, 0xfa944def +0, 121276, 121276, 1378, 2756, 0xc12f23b2 +0, 122654, 122654, 1378, 2756, 0x5ea325a2 +0, 124032, 124032, 1378, 2756, 0x2b245824 +0, 125410, 125410, 1379, 2758, 0xeb1f5203 +0, 126789, 126789, 1378, 2756, 0xcca34d26 +0, 128167, 128167, 1378, 2756, 0xb5f820d0 +0, 129545, 129545, 1378, 2756, 0x27f24335 +0, 130923, 130923, 1378, 2756, 0x4a9e87b7 +0, 132301, 132301, 1378, 2756, 0xbd076129 +0, 133679, 133679, 1378, 2756, 0x2e0e3f2e +0, 135057, 135057, 1379, 2758, 0x5664442c +0, 136436, 136436, 1378, 2756, 0xca000a2e +0, 137814, 137814, 1378, 2756, 0x87472df3 +0, 139192, 139192, 1378, 2756, 0x16733810 +0, 140570, 140570, 1378, 2756, 0xfa0734b4 +0, 141948, 141948, 1378, 2756, 0x5eff3fc4 +0, 143326, 143326, 1378, 2756, 0xf35346bd +0, 144704, 144704, 1378, 2756, 0xac6411c5 +0, 146082, 146082, 1379, 2758, 0xcfcf3ae7 +0, 147461, 147461, 1378, 2756, 0xebd30bdd +0, 148839, 148839, 1378, 2756, 0xaef95a31 +0, 150217, 150217, 1378, 2756, 0x8aad29d1 +0, 151595, 151595, 1378, 2756, 0x626863f0 +0, 152973, 152973, 1378, 2756, 0x68c05707 +0, 154351, 154351, 1378, 2756, 0x437c5e8d +0, 155729, 155729, 1379, 2758, 0xf7054b53 +0, 157108, 157108, 1378, 2756, 0x62bd4162 +0, 158486, 158486, 1378, 2756, 0x9f744aa4 +0, 159864, 159864, 1378, 2756, 0x0f3f6409 +0, 161242, 161242, 1378, 2756, 0x3fee827a +0, 162620, 162620, 1378, 2756, 0x48a0ac19 +0, 163998, 163998, 1378, 2756, 0x8e4ce0d0 +0, 165376, 165376, 1379, 2758, 0x8a3b207f +0, 166755, 166755, 1378, 2756, 0x0e523255 +0, 168133, 168133, 1378, 2756, 0x84103d30 +0, 169511, 169511, 1378, 2756, 0x13941cde +0, 170889, 170889, 1378, 2756, 0x9fc834c5 +0, 172267, 172267, 1378, 2756, 0xc0217a77 +0, 173645, 173645, 1378, 2756, 0x3f643659 +0, 175023, 175023, 1379, 2758, 0xddac5fc3 +0, 176402, 176402, 1378, 2756, 0x94f046fb +0, 177780, 177780, 1378, 2756, 0xab01fb12 +0, 179158, 179158, 1378, 2756, 0x04cffe5c +0, 180536, 180536, 1378, 2756, 0xef661c5e +0, 181914, 181914, 1378, 2756, 0x094c5fc5 +0, 183292, 183292, 1378, 2756, 0xe0c1486a +0, 184670, 184670, 1379, 2758, 0x21c03448 +0, 186049, 186049, 1378, 2756, 0x594934aa +0, 187427, 187427, 1378, 2756, 0x74007238 +0, 188805, 188805, 1378, 2756, 0x61f1394d +0, 190183, 190183, 1378, 2756, 0x72584f07 +0, 191561, 191561, 1378, 2756, 0xced9acf9 +0, 192939, 192939, 1378, 2756, 0x7d2e3ea1 +0, 194317, 194317, 1378, 2756, 0x56c06897 +0, 195695, 195695, 1379, 2758, 0xa20b3b1b +0, 197074, 197074, 1378, 2756, 0x4f884f27 +0, 198452, 198452, 1378, 2756, 0x81ab2f63 +0, 199830, 199830, 1378, 2756, 0x448e681d +0, 201208, 201208, 1378, 2756, 0x0ba9826e +0, 202586, 202586, 1378, 2756, 0x049f36fa +0, 203964, 203964, 1378, 2756, 0x096a2b62 +0, 205342, 205342, 1379, 2758, 0x17361fbb +0, 206721, 206721, 1378, 2756, 0xd13e30e1 +0, 208099, 208099, 1378, 2756, 0x30b6412b +0, 209477, 209477, 1378, 2756, 0xbb1c3268 +0, 210855, 210855, 1378, 2756, 0xbc175b6a +0, 212233, 212233, 1378, 2756, 0xf8d160e2 +0, 213611, 213611, 1378, 2756, 0xc1048154 +0, 214989, 214989, 1379, 2758, 0x26564885 +0, 216368, 216368, 1378, 2756, 0x22647962 +0, 217746, 217746, 1378, 2756, 0x14ca54d3 +0, 219124, 219124, 1376, 2752, 0x2c374add diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-apm-mono ffmpeg-4.4/tests/ref/fate/adpcm-ima-apm-mono --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-apm-mono 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-apm-mono 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +a5cb56a035ab4b79adceba6fe4a428d2 diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-apm-stereo ffmpeg-4.4/tests/ref/fate/adpcm-ima-apm-stereo --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-apm-stereo 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-apm-stereo 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +e7ceb7f846f831b0bb3728d8ec18fdd4 diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-single ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-single --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-single 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-single 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +dd6ba6151c3e74d09be3c54005465aab diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-stereo ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-stereo --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-stereo 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-stereo 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1 @@ +c508235656525c97429153c639dbe8eb diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-track0 ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-track0 --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-track0 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-track0 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +fb8db1eef33860c1adde4932e7a250ac diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-track1 ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-track1 --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-track1 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-track1 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +4b2f9c416ae676526754c82f2a669c91 diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-trunc-h2 ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-trunc-h2 --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-trunc-h2 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-trunc-h2 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +fb8db1eef33860c1adde4932e7a250ac diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-trunc-t1 ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-trunc-t1 --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-trunc-t1 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-trunc-t1 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +a0eaad31febdcf1cfb94a4d418e1e140 diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-trunc-t2a-track0 ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-trunc-t2a-track0 --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-trunc-t2a-track0 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-trunc-t2a-track0 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +fb8db1eef33860c1adde4932e7a250ac diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-trunc-t2a-track1 ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-trunc-t2a-track1 --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-trunc-t2a-track1 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-trunc-t2a-track1 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +af0d42f01108333ab356061f9cab9403 diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-trunc-t2-track0 ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-trunc-t2-track0 --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-trunc-t2-track0 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-trunc-t2-track0 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +fb8db1eef33860c1adde4932e7a250ac diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-trunc-t2-track1 ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-trunc-t2-track1 --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-cunning-trunc-t2-track1 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-cunning-trunc-t2-track1 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +d41d8cd98f00b204e9800998ecf8427e diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-ssi-mono ffmpeg-4.4/tests/ref/fate/adpcm-ima-ssi-mono --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-ssi-mono 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-ssi-mono 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +18decd2cd6da6957f0b323f7598b2d42 diff -Nru ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-ssi-stereo ffmpeg-4.4/tests/ref/fate/adpcm-ima-ssi-stereo --- ffmpeg-4.2.2/tests/ref/fate/adpcm-ima-ssi-stereo 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adpcm-ima-ssi-stereo 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +c4be97a96aea1d6b15f1fe7d97ef7db8 diff -Nru ffmpeg-4.2.2/tests/ref/fate/adtstoasc_ticket3715 ffmpeg-4.4/tests/ref/fate/adtstoasc_ticket3715 --- ffmpeg-4.2.2/tests/ref/fate/adtstoasc_ticket3715 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/adtstoasc_ticket3715 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -4110be924e21846d0e174fac679b062e *tests/data/fate/adtstoasc_ticket3715.mov +29ef0632a8eb5c336bf45a1d5076626e *tests/data/fate/adtstoasc_ticket3715.mov 33324 tests/data/fate/adtstoasc_ticket3715.mov #extradata 0: 2, 0x00340022 #tb 0: 1/44100 diff -Nru ffmpeg-4.2.2/tests/ref/fate/api-mjpeg-codec-param ffmpeg-4.4/tests/ref/fate/api-mjpeg-codec-param --- ffmpeg-4.2.2/tests/ref/fate/api-mjpeg-codec-param 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/api-mjpeg-codec-param 1970-01-01 00:00:00.000000000 +0000 @@ -1,282 +0,0 @@ -stream=0, decode=0 - b=0 - ab=0 - bt=4000000 - flags=0x00000000 - flags2=0x00000000 - time_base=0/1 - g=12 - ar=0 - ac=0 - cutoff=0 - frame_size=0 - delay=0 - qcomp=0.500000 - qblur=0.500000 - qmin=2 - qmax=31 - qdiff=3 - bf=0 - b_qfactor=1.250000 - b_strategy=0 - ps=0 - mv_bits=0 - header_bits=0 - i_tex_bits=0 - p_tex_bits=0 - i_count=0 - p_count=0 - skip_count=0 - misc_bits=0 - frame_bits=0 - codec_tag=0 - bug=0x00000001 - strict=0 - b_qoffset=1.250000 - err_detect=0x00000000 - has_b_frames=0 - block_align=0 - mpeg_quant=0 - rc_override_count=0 - maxrate=0 - minrate=0 - bufsize=0 - i_qfactor=-0.800000 - i_qoffset=0.000000 - dct=0 - lumi_mask=0.000000 - tcplx_mask=0.000000 - scplx_mask=0.000000 - p_mask=0.000000 - dark_mask=0.000000 - idct=0 - slice_count=0 - ec=0x00000003 - bits_per_coded_sample=0 - pred=0 - aspect=180/180 - sar=180/180 - debug=0x00000000 - dia_size=0 - last_pred=0 - preme=0 - pre_dia_size=0 - subq=8 - me_range=0 - global_quality=0 - coder=0 - context=0 - slice_flags=0 - mbd=0 - sc_threshold=0 - nr=0 - rc_init_occupancy=0 - threads=1 - dc=0 - nssew=8 - skip_top=0 - skip_bottom=0 - profile=192 - level=-99 - lowres=0 - skip_threshold=0 - skip_factor=0 - skip_exp=0 - skipcmp=13 - cmp=0 - subcmp=0 - mbcmp=0 - ildctcmp=8 - precmp=0 - mblmin=236 - mblmax=3658 - mepc=256 - skip_loop_filter=0 - skip_idct=0 - skip_frame=0 - bidir_refine=1 - brd_scale=0 - keyint_min=25 - refs=1 - chromaoffset=0 - trellis=0 - mv0_threshold=256 - b_sensitivity=40 - compression_level=-1 - min_prediction_order=-1 - max_prediction_order=-1 - timecode_frame_start=-1 - bits_per_raw_sample=8 - channel_layout=0 - request_channel_layout=0 - rc_max_vbv_use=0.000000 - rc_min_vbv_use=3.000000 - ticks_per_frame=1 - color_primaries=2 - color_trc=2 - colorspace=5 - color_range=2 - chroma_sample_location=2 - log_level_offset=0 - slices=0 - thread_type=0x00000003 - audio_service_type=0 - request_sample_fmt=none - pkt_timebase=1/25 - sub_charenc= - sub_charenc_mode=0x00000000 - sub_text_format=1 - refcounted_frames=false - side_data_only_packets=true - apply_cropping=true - skip_alpha=false - field_order=0 - dump_separator= - codec_whitelist= - pixel_format=yuvj422p - video_size=400x225 - max_pixels=2147483647 - hwaccel_flags=0x00000001 - extra_hw_frames=-1 - discard_damaged_percentage=95 -stream=0, decode=1 - b=0 - ab=0 - bt=4000000 - flags=0x00000000 - flags2=0x00000000 - time_base=0/1 - g=12 - ar=0 - ac=0 - cutoff=0 - frame_size=0 - delay=0 - qcomp=0.500000 - qblur=0.500000 - qmin=2 - qmax=31 - qdiff=3 - bf=0 - b_qfactor=1.250000 - b_strategy=0 - ps=0 - mv_bits=0 - header_bits=0 - i_tex_bits=0 - p_tex_bits=0 - i_count=0 - p_count=0 - skip_count=0 - misc_bits=0 - frame_bits=0 - codec_tag=0 - bug=0x00000001 - strict=0 - b_qoffset=1.250000 - err_detect=0x00000000 - has_b_frames=0 - block_align=0 - mpeg_quant=0 - rc_override_count=0 - maxrate=0 - minrate=0 - bufsize=0 - i_qfactor=-0.800000 - i_qoffset=0.000000 - dct=0 - lumi_mask=0.000000 - tcplx_mask=0.000000 - scplx_mask=0.000000 - p_mask=0.000000 - dark_mask=0.000000 - idct=0 - slice_count=0 - ec=0x00000003 - bits_per_coded_sample=0 - pred=0 - aspect=180/180 - sar=180/180 - debug=0x00000000 - dia_size=0 - last_pred=0 - preme=0 - pre_dia_size=0 - subq=8 - me_range=0 - global_quality=0 - coder=0 - context=0 - slice_flags=0 - mbd=0 - sc_threshold=0 - nr=0 - rc_init_occupancy=0 - threads=1 - dc=0 - nssew=8 - skip_top=0 - skip_bottom=0 - profile=192 - level=-99 - lowres=0 - skip_threshold=0 - skip_factor=0 - skip_exp=0 - skipcmp=13 - cmp=0 - subcmp=0 - mbcmp=0 - ildctcmp=8 - precmp=0 - mblmin=236 - mblmax=3658 - mepc=256 - skip_loop_filter=0 - skip_idct=0 - skip_frame=0 - bidir_refine=1 - brd_scale=0 - keyint_min=25 - refs=1 - chromaoffset=0 - trellis=0 - mv0_threshold=256 - b_sensitivity=40 - compression_level=-1 - min_prediction_order=-1 - max_prediction_order=-1 - timecode_frame_start=-1 - bits_per_raw_sample=8 - channel_layout=0 - request_channel_layout=0 - rc_max_vbv_use=0.000000 - rc_min_vbv_use=3.000000 - ticks_per_frame=1 - color_primaries=2 - color_trc=2 - colorspace=5 - color_range=2 - chroma_sample_location=2 - log_level_offset=0 - slices=0 - thread_type=0x00000003 - audio_service_type=0 - request_sample_fmt=none - pkt_timebase=1/25 - sub_charenc= - sub_charenc_mode=0x00000000 - sub_text_format=1 - refcounted_frames=false - side_data_only_packets=true - apply_cropping=true - skip_alpha=false - field_order=0 - dump_separator= - codec_whitelist= - pixel_format=yuvj422p - video_size=400x225 - max_pixels=2147483647 - hwaccel_flags=0x00000001 - extra_hw_frames=-1 - discard_damaged_percentage=95 diff -Nru ffmpeg-4.2.2/tests/ref/fate/api-png-codec-param ffmpeg-4.4/tests/ref/fate/api-png-codec-param --- ffmpeg-4.2.2/tests/ref/fate/api-png-codec-param 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/api-png-codec-param 1970-01-01 00:00:00.000000000 +0000 @@ -1,282 +0,0 @@ -stream=0, decode=0 - b=0 - ab=0 - bt=4000000 - flags=0x00000000 - flags2=0x00000000 - time_base=0/1 - g=12 - ar=0 - ac=0 - cutoff=0 - frame_size=0 - delay=0 - qcomp=0.500000 - qblur=0.500000 - qmin=2 - qmax=31 - qdiff=3 - bf=0 - b_qfactor=1.250000 - b_strategy=0 - ps=0 - mv_bits=0 - header_bits=0 - i_tex_bits=0 - p_tex_bits=0 - i_count=0 - p_count=0 - skip_count=0 - misc_bits=0 - frame_bits=0 - codec_tag=0 - bug=0x00000001 - strict=0 - b_qoffset=1.250000 - err_detect=0x00000000 - has_b_frames=0 - block_align=0 - mpeg_quant=0 - rc_override_count=0 - maxrate=0 - minrate=0 - bufsize=0 - i_qfactor=-0.800000 - i_qoffset=0.000000 - dct=0 - lumi_mask=0.000000 - tcplx_mask=0.000000 - scplx_mask=0.000000 - p_mask=0.000000 - dark_mask=0.000000 - idct=0 - slice_count=0 - ec=0x00000003 - bits_per_coded_sample=0 - pred=0 - aspect=2835/2835 - sar=2835/2835 - debug=0x00000000 - dia_size=0 - last_pred=0 - preme=0 - pre_dia_size=0 - subq=8 - me_range=0 - global_quality=0 - coder=0 - context=0 - slice_flags=0 - mbd=0 - sc_threshold=0 - nr=0 - rc_init_occupancy=0 - threads=1 - dc=0 - nssew=8 - skip_top=0 - skip_bottom=0 - profile=-99 - level=-99 - lowres=0 - skip_threshold=0 - skip_factor=0 - skip_exp=0 - skipcmp=13 - cmp=0 - subcmp=0 - mbcmp=0 - ildctcmp=8 - precmp=0 - mblmin=236 - mblmax=3658 - mepc=256 - skip_loop_filter=0 - skip_idct=0 - skip_frame=0 - bidir_refine=1 - brd_scale=0 - keyint_min=25 - refs=1 - chromaoffset=0 - trellis=0 - mv0_threshold=256 - b_sensitivity=40 - compression_level=-1 - min_prediction_order=-1 - max_prediction_order=-1 - timecode_frame_start=-1 - bits_per_raw_sample=0 - channel_layout=0 - request_channel_layout=0 - rc_max_vbv_use=0.000000 - rc_min_vbv_use=3.000000 - ticks_per_frame=1 - color_primaries=2 - color_trc=2 - colorspace=2 - color_range=2 - chroma_sample_location=0 - log_level_offset=0 - slices=0 - thread_type=0x00000003 - audio_service_type=0 - request_sample_fmt=none - pkt_timebase=1/25 - sub_charenc= - sub_charenc_mode=0x00000000 - sub_text_format=1 - refcounted_frames=false - side_data_only_packets=true - apply_cropping=true - skip_alpha=false - field_order=0 - dump_separator= - codec_whitelist= - pixel_format=rgba - video_size=128x128 - max_pixels=2147483647 - hwaccel_flags=0x00000001 - extra_hw_frames=-1 - discard_damaged_percentage=95 -stream=0, decode=1 - b=0 - ab=0 - bt=4000000 - flags=0x00000000 - flags2=0x00000000 - time_base=0/1 - g=12 - ar=0 - ac=0 - cutoff=0 - frame_size=0 - delay=0 - qcomp=0.500000 - qblur=0.500000 - qmin=2 - qmax=31 - qdiff=3 - bf=0 - b_qfactor=1.250000 - b_strategy=0 - ps=0 - mv_bits=0 - header_bits=0 - i_tex_bits=0 - p_tex_bits=0 - i_count=0 - p_count=0 - skip_count=0 - misc_bits=0 - frame_bits=0 - codec_tag=0 - bug=0x00000001 - strict=0 - b_qoffset=1.250000 - err_detect=0x00000000 - has_b_frames=0 - block_align=0 - mpeg_quant=0 - rc_override_count=0 - maxrate=0 - minrate=0 - bufsize=0 - i_qfactor=-0.800000 - i_qoffset=0.000000 - dct=0 - lumi_mask=0.000000 - tcplx_mask=0.000000 - scplx_mask=0.000000 - p_mask=0.000000 - dark_mask=0.000000 - idct=0 - slice_count=0 - ec=0x00000003 - bits_per_coded_sample=0 - pred=0 - aspect=2835/2835 - sar=2835/2835 - debug=0x00000000 - dia_size=0 - last_pred=0 - preme=0 - pre_dia_size=0 - subq=8 - me_range=0 - global_quality=0 - coder=0 - context=0 - slice_flags=0 - mbd=0 - sc_threshold=0 - nr=0 - rc_init_occupancy=0 - threads=1 - dc=0 - nssew=8 - skip_top=0 - skip_bottom=0 - profile=-99 - level=-99 - lowres=0 - skip_threshold=0 - skip_factor=0 - skip_exp=0 - skipcmp=13 - cmp=0 - subcmp=0 - mbcmp=0 - ildctcmp=8 - precmp=0 - mblmin=236 - mblmax=3658 - mepc=256 - skip_loop_filter=0 - skip_idct=0 - skip_frame=0 - bidir_refine=1 - brd_scale=0 - keyint_min=25 - refs=1 - chromaoffset=0 - trellis=0 - mv0_threshold=256 - b_sensitivity=40 - compression_level=-1 - min_prediction_order=-1 - max_prediction_order=-1 - timecode_frame_start=-1 - bits_per_raw_sample=0 - channel_layout=0 - request_channel_layout=0 - rc_max_vbv_use=0.000000 - rc_min_vbv_use=3.000000 - ticks_per_frame=1 - color_primaries=2 - color_trc=2 - colorspace=2 - color_range=2 - chroma_sample_location=0 - log_level_offset=0 - slices=0 - thread_type=0x00000003 - audio_service_type=0 - request_sample_fmt=none - pkt_timebase=1/25 - sub_charenc= - sub_charenc_mode=0x00000000 - sub_text_format=1 - refcounted_frames=false - side_data_only_packets=true - apply_cropping=true - skip_alpha=false - field_order=0 - dump_separator= - codec_whitelist= - pixel_format=rgba - video_size=128x128 - max_pixels=2147483647 - hwaccel_flags=0x00000001 - extra_hw_frames=-1 - discard_damaged_percentage=95 diff -Nru ffmpeg-4.2.2/tests/ref/fate/apng-dispose-previous ffmpeg-4.4/tests/ref/fate/apng-dispose-previous --- ffmpeg-4.2.2/tests/ref/fate/apng-dispose-previous 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/apng-dispose-previous 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,139 @@ +#tb 0: 1/10 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 85x128 +#sar 0: 0/1 +0, 0, 0, 1, 43520, 0xff012b7c +0, 1, 1, 1, 43520, 0x76842464 +0, 2, 2, 1, 43520, 0xa35de191 +0, 3, 3, 1, 43520, 0x7ece479c +0, 4, 4, 1, 43520, 0xea12fa4a +0, 5, 5, 1, 43520, 0xcb2c2256 +0, 6, 6, 1, 43520, 0x7d225965 +0, 7, 7, 1, 43520, 0xc0d95d3f +0, 8, 8, 1, 43520, 0xee864d84 +0, 9, 9, 1, 43520, 0x1fadbb0e +0, 10, 10, 1, 43520, 0xab89647b +0, 11, 11, 1, 43520, 0x206141bc +0, 12, 12, 1, 43520, 0x6432e720 +0, 13, 13, 1, 43520, 0xe25ab561 +0, 14, 14, 1, 43520, 0xc2df7c6b +0, 15, 15, 1, 43520, 0x372768c3 +0, 16, 16, 1, 43520, 0xfeea0d7b +0, 17, 17, 1, 43520, 0x89c1f76d +0, 18, 18, 1, 43520, 0xae16c8b3 +0, 19, 19, 1, 43520, 0x98949570 +0, 20, 20, 1, 43520, 0x5bb75099 +0, 21, 21, 1, 43520, 0xb4c73263 +0, 22, 22, 1, 43520, 0xcf26f441 +0, 23, 23, 1, 43520, 0xba47d23b +0, 24, 24, 1, 43520, 0x4c3e87da +0, 25, 25, 1, 43520, 0xe95b7398 +0, 26, 26, 1, 43520, 0x00575c74 +0, 27, 27, 1, 43520, 0xea1d59f6 +0, 28, 28, 1, 43520, 0xbede4d2e +0, 29, 29, 1, 43520, 0x9ed736a6 +0, 30, 30, 1, 43520, 0x8b027f56 +0, 31, 31, 1, 43520, 0x1db24f15 +0, 32, 32, 1, 43520, 0x1835a2dd +0, 33, 33, 1, 43520, 0xfda26b24 +0, 34, 34, 1, 43520, 0x52f3e8eb +0, 35, 35, 1, 43520, 0xda01102f +0, 36, 36, 1, 43520, 0x443adff3 +0, 37, 37, 1, 43520, 0x46c72f9a +0, 38, 38, 1, 43520, 0x3ec78642 +0, 39, 39, 1, 43520, 0x12033c40 +0, 40, 40, 1, 43520, 0x41fe0964 +0, 41, 41, 1, 43520, 0xc7a53be5 +0, 42, 42, 1, 43520, 0x4b185aa0 +0, 43, 43, 1, 43520, 0xf45cc1f0 +0, 44, 44, 1, 43520, 0x8bdc77cd +0, 45, 45, 1, 43520, 0x94c5ac41 +0, 46, 46, 1, 43520, 0xfbabeefe +0, 47, 47, 1, 43520, 0x92d657d9 +0, 48, 48, 1, 43520, 0x09dbd475 +0, 49, 49, 1, 43520, 0x5f9926e4 +0, 50, 50, 1, 43520, 0x4fdb5a64 +0, 51, 51, 1, 43520, 0xc0a382f6 +0, 52, 52, 1, 43520, 0x104f9b45 +0, 53, 53, 1, 43520, 0xfaf5d8f7 +0, 54, 54, 1, 43520, 0x2559e38b +0, 55, 55, 1, 43520, 0x82890381 +0, 56, 56, 1, 43520, 0xfe7aec01 +0, 57, 57, 1, 43520, 0x4543f499 +0, 58, 58, 1, 43520, 0x60d7cbd1 +0, 59, 59, 1, 43520, 0x576fc249 +0, 60, 60, 1, 43520, 0xc96d9035 +0, 61, 61, 1, 43520, 0x40857b3a +0, 62, 62, 1, 43520, 0x422a2eef +0, 63, 63, 1, 43520, 0xb1510101 +0, 64, 64, 1, 43520, 0x3f619ad7 +0, 65, 65, 1, 43520, 0x497f42fa +0, 66, 66, 1, 43520, 0x8b4b1ce2 +0, 67, 67, 1, 43520, 0x21f2f75b +0, 68, 68, 1, 43520, 0x8b4b1ce2 +0, 69, 69, 1, 43520, 0x497f42fa +0, 70, 70, 1, 43520, 0x3f619ad7 +0, 71, 71, 1, 43520, 0xb1510101 +0, 72, 72, 1, 43520, 0x422a2eef +0, 73, 73, 1, 43520, 0x40857b3a +0, 74, 74, 1, 43520, 0xc96d9035 +0, 75, 75, 1, 43520, 0x576fc249 +0, 76, 76, 1, 43520, 0x60d7cbd1 +0, 77, 77, 1, 43520, 0x4543f499 +0, 78, 78, 1, 43520, 0xfe7aec01 +0, 79, 79, 1, 43520, 0x82890381 +0, 80, 80, 1, 43520, 0x2559e38b +0, 81, 81, 1, 43520, 0xfaf5d8f7 +0, 82, 82, 1, 43520, 0x104f9b45 +0, 83, 83, 1, 43520, 0xc0a382f6 +0, 84, 84, 1, 43520, 0x4fdb5a64 +0, 85, 85, 1, 43520, 0x5f9926e4 +0, 86, 86, 1, 43520, 0x09dbd475 +0, 87, 87, 1, 43520, 0x92d657d9 +0, 88, 88, 1, 43520, 0xfbabeefe +0, 89, 89, 1, 43520, 0x94c5ac41 +0, 90, 90, 1, 43520, 0x8bdc77cd +0, 91, 91, 1, 43520, 0xf45cc1f0 +0, 92, 92, 1, 43520, 0x4b185aa0 +0, 93, 93, 1, 43520, 0xc7a53be5 +0, 94, 94, 1, 43520, 0x41fe0964 +0, 95, 95, 1, 43520, 0x12033c40 +0, 96, 96, 1, 43520, 0x3ec78642 +0, 97, 97, 1, 43520, 0x46c72f9a +0, 98, 98, 1, 43520, 0x443adff3 +0, 99, 99, 1, 43520, 0xda01102f +0, 100, 100, 1, 43520, 0x52f3e8eb +0, 101, 101, 1, 43520, 0xfda26b24 +0, 102, 102, 1, 43520, 0x1835a2dd +0, 103, 103, 1, 43520, 0x1db24f15 +0, 104, 104, 1, 43520, 0x8b027f56 +0, 105, 105, 1, 43520, 0x9ed736a6 +0, 106, 106, 1, 43520, 0xbede4d2e +0, 107, 107, 1, 43520, 0xea1d59f6 +0, 108, 108, 1, 43520, 0x00575c74 +0, 109, 109, 1, 43520, 0xe95b7398 +0, 110, 110, 1, 43520, 0x4c3e87da +0, 111, 111, 1, 43520, 0xba47d23b +0, 112, 112, 1, 43520, 0xcf26f441 +0, 113, 113, 1, 43520, 0xb4c73263 +0, 114, 114, 1, 43520, 0x5bb75099 +0, 115, 115, 1, 43520, 0x98949570 +0, 116, 116, 1, 43520, 0xae16c8b3 +0, 117, 117, 1, 43520, 0x89c1f76d +0, 118, 118, 1, 43520, 0xfeea0d7b +0, 119, 119, 1, 43520, 0x372768c3 +0, 120, 120, 1, 43520, 0xc2df7c6b +0, 121, 121, 1, 43520, 0xe25ab561 +0, 122, 122, 1, 43520, 0x6432e720 +0, 123, 123, 1, 43520, 0x206141bc +0, 124, 124, 1, 43520, 0xab89647b +0, 125, 125, 1, 43520, 0x1fadbb0e +0, 126, 126, 1, 43520, 0xee864d84 +0, 127, 127, 1, 43520, 0xc0d95d3f +0, 128, 128, 1, 43520, 0x7d225965 +0, 129, 129, 1, 43520, 0xcb2c2256 +0, 130, 130, 1, 43520, 0xea12fa4a +0, 131, 131, 1, 43520, 0x7ece479c +0, 132, 132, 1, 43520, 0xa35de191 +0, 133, 133, 1, 43520, 0x76842464 diff -Nru ffmpeg-4.2.2/tests/ref/fate/asf-repldata ffmpeg-4.4/tests/ref/fate/asf-repldata --- ffmpeg-4.2.2/tests/ref/fate/asf-repldata 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/asf-repldata 2021-04-08 21:28:40.000000000 +0000 @@ -3,17 +3,17 @@ #codec_id 0: msmpeg4v3 #dimensions 0: 640x480 #sar 0: 0/1 -0, 0, 0, 0, 23374, 0x8725b3b8 -0, 122, 122, 0, 13732, 0x3ac8531a, F=0x0 -0, 245, 245, 0, 615, 0xd31641b4, F=0x0 -0, 367, 367, 0, 6361, 0xf263af54, F=0x0 -0, 490, 490, 0, 320, 0xd6f2d6b8, F=0x0 -0, 612, 612, 0, 3750, 0xfcf1d501, F=0x0 -0, 735, 735, 0, 2541, 0xd9fc04f9, F=0x0 -0, 857, 857, 0, 205, 0x4d38a947, F=0x0 -0, 980, 980, 0, 2166, 0x2f1e7d74, F=0x0 -0, 1102, 1102, 0, 1667, 0x0cd84b61, F=0x0 -0, 1224, 1224, 0, 13645, 0x543bd032, F=0x0 -0, 1347, 1347, 0, 5953, 0xc3037c73, F=0x0 -0, 1469, 1469, 0, 36169, 0xca9f716d -0, 1592, 1592, 0, 3030, 0x9aba5683, F=0x0 +0, 0, 0, 122, 23374, 0x8725b3b8 +0, 122, 122, 122, 13732, 0x3ac8531a, F=0x0 +0, 245, 245, 122, 615, 0xd31641b4, F=0x0 +0, 367, 367, 122, 6361, 0xf263af54, F=0x0 +0, 490, 490, 122, 320, 0xd6f2d6b8, F=0x0 +0, 612, 612, 122, 3750, 0xfcf1d501, F=0x0 +0, 735, 735, 122, 2541, 0xd9fc04f9, F=0x0 +0, 857, 857, 122, 205, 0x4d38a947, F=0x0 +0, 980, 980, 122, 2166, 0x2f1e7d74, F=0x0 +0, 1102, 1102, 122, 1667, 0x0cd84b61, F=0x0 +0, 1224, 1224, 122, 13645, 0x543bd032, F=0x0 +0, 1347, 1347, 122, 5953, 0xc3037c73, F=0x0 +0, 1469, 1469, 122, 36169, 0xca9f716d +0, 1592, 1592, 122, 3030, 0x9aba5683, F=0x0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/av1-annexb-demux ffmpeg-4.4/tests/ref/fate/av1-annexb-demux --- ffmpeg-4.2.2/tests/ref/fate/av1-annexb-demux 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/av1-annexb-demux 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,16 @@ +#extradata 0: 13, 0x0e4c033a +#tb 0: 1/1200000 +#media_type 0: video +#codec_id 0: av1 +#dimensions 0: 300x300 +#sar 0: 1/1 +0, 0, 0, 48000, 12691, 0xf0adcc79 +0, 48000, 48000, 48000, 4975, 0x1742a45f, F=0x0 +0, 96000, 96000, 48000, 928, 0x7408be1a, F=0x0 +0, 144000, 144000, 48000, 702, 0x1d4464ca, F=0x0 +0, 192000, 192000, 48000, 1372, 0x37999ccf, F=0x0 +0, 240000, 240000, 48000, 1085, 0x06b61548, F=0x0 +0, 288000, 288000, 48000, 1533, 0x5e05dea3, F=0x0 +0, 336000, 336000, 48000, 1416, 0x31d4b906, F=0x0 +0, 384000, 384000, 48000, 108, 0xf52a2c59, F=0x0 +0, 432000, 432000, 48000, 1740, 0x1f065d09, F=0x0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/avid-interlaced ffmpeg-4.4/tests/ref/fate/avid-interlaced --- ffmpeg-4.2.2/tests/ref/fate/avid-interlaced 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/avid-interlaced 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,7 @@ +#tb 0: 100/2397 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 720x486 +#sar 0: 0/1 +0, 0, 0, 1, 699840, 0xc59a264e +0, 1, 1, 1, 699840, 0x06f13712 diff -Nru ffmpeg-4.2.2/tests/ref/fate/avid-meridian ffmpeg-4.4/tests/ref/fate/avid-meridian --- ffmpeg-4.2.2/tests/ref/fate/avid-meridian 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/avid-meridian 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,15 @@ +#tb 0: 20859/500000 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 0/1 +0, 0, 0, 1, 153600, 0xbfd35869 +0, 1, 1, 1, 153600, 0xbe7c74a0 +0, 2, 2, 1, 153600, 0x9f2524ee +0, 3, 3, 1, 153600, 0x3c8df375 +0, 4, 4, 1, 153600, 0xe0ac5d7d +0, 5, 5, 1, 153600, 0xf0c6da50 +0, 6, 6, 1, 153600, 0xbd50751f +0, 7, 7, 1, 153600, 0x51caf5f7 +0, 8, 8, 1, 153600, 0x27752d4f +0, 9, 9, 1, 153600, 0x63a0d0dc diff -Nru ffmpeg-4.2.2/tests/ref/fate/binsub-mksenc ffmpeg-4.4/tests/ref/fate/binsub-mksenc --- ffmpeg-4.2.2/tests/ref/fate/binsub-mksenc 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/binsub-mksenc 2020-07-11 10:39:30.000000000 +0000 @@ -1 +1 @@ -a5811caa0caba3a3f9a449b91569745c +5706cf33f9ded660eb404275ec136127 diff -Nru ffmpeg-4.2.2/tests/ref/fate/binsub-movtextenc ffmpeg-4.4/tests/ref/fate/binsub-movtextenc --- ffmpeg-4.2.2/tests/ref/fate/binsub-movtextenc 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/binsub-movtextenc 2020-07-11 10:39:30.000000000 +0000 @@ -1 +1 @@ -66b25412f7ca699ee525ba162246edb6 +fc6d07679ac1f718aa50de687924cd97 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cavs ffmpeg-4.4/tests/ref/fate/cavs --- ffmpeg-4.2.2/tests/ref/fate/cavs 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cavs 2020-07-11 10:39:30.000000000 +0000 @@ -172,4 +172,4 @@ 0, 166, 166, 1, 622080, 0x05496a5d 0, 167, 167, 1, 622080, 0xdcb4cee8 0, 168, 168, 1, 622080, 0xb41172e5 -0, 169, 169, 1, 622080, 0x56c72478 +0, 169, 169, 1, 622080, 0x84ff3af9 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b10-23-film_grain-50 ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b10-23-film_grain-50 --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b10-23-film_grain-50 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b10-23-film_grain-50 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +0ab934a437181d0275dc6c26bb9f6281 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-02-allintra ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-02-allintra --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-02-allintra 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-02-allintra 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +134b447b04086088de4da127a97731f3 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-03-sizedown ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-03-sizedown --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-03-sizedown 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-03-sizedown 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +e5924930773efdbbd82da02c96747f27 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-03-sizeup ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-03-sizeup --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-03-sizeup 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-03-sizeup 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +0348fba6ebf6caadfe80b19a6ad93caa diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-04-cdfupdate ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-04-cdfupdate --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-04-cdfupdate 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-04-cdfupdate 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +aec87cd950fb985b1e345d0366709aea diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-05-mv ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-05-mv --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-05-mv 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-05-mv 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +33f548eeef87e12b93b9bf4a3b79c70e diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-06-mfmv ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-06-mfmv --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-06-mfmv 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-06-mfmv 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +2e20870d44ba5ec5a8e1450b287e20b4 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-22-svc-L1T2 ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-22-svc-L1T2 --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-22-svc-L1T2 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-22-svc-L1T2 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +f7138eaa1e572260a8a34f73f91e058a diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-22-svc-L2T1 ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-22-svc-L2T1 --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-22-svc-L2T1 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-22-svc-L2T1 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +4f51af7abcf75eba35ab1c4796793681 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-22-svc-L2T2 ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-22-svc-L2T2 --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-22-svc-L2T2 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-22-svc-L2T2 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +d52adb1719a0422782e40352e44c6cb0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-23-film_grain-50 ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-23-film_grain-50 --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-av1-1-b8-23-film_grain-50 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-av1-1-b8-23-film_grain-50 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +99a635753d7e4e7deb99fd2ba866818e diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-decode_model ffmpeg-4.4/tests/ref/fate/cbs-av1-decode_model --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-decode_model 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-decode_model 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +171ebf527c4cd57179d6a4e5c4f23ce4 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-frames_refs_short_signaling ffmpeg-4.4/tests/ref/fate/cbs-av1-frames_refs_short_signaling --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-frames_refs_short_signaling 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-frames_refs_short_signaling 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +d1b05cf934aeda64b25a93423904c14d diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-non_uniform_tiling ffmpeg-4.4/tests/ref/fate/cbs-av1-non_uniform_tiling --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-non_uniform_tiling 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-non_uniform_tiling 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +3e204ee8a71273cf0247f48e977e64b7 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-seq_hdr_op_param_info ffmpeg-4.4/tests/ref/fate/cbs-av1-seq_hdr_op_param_info --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-seq_hdr_op_param_info 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-seq_hdr_op_param_info 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +10e7bdd7cab67f203520e44b28a6477c diff -Nru ffmpeg-4.2.2/tests/ref/fate/cbs-av1-switch_frame ffmpeg-4.4/tests/ref/fate/cbs-av1-switch_frame --- ffmpeg-4.2.2/tests/ref/fate/cbs-av1-switch_frame 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cbs-av1-switch_frame 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +156b5297ca32c18183ca41a102a09a02 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cdxl-bitline-ham6 ffmpeg-4.4/tests/ref/fate/cdxl-bitline-ham6 --- ffmpeg-4.2.2/tests/ref/fate/cdxl-bitline-ham6 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cdxl-bitline-ham6 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -#tb 0: 1/50 +#tb 0: 1/15 #media_type 0: video #codec_id 0: rawvideo #dimensions 0: 162x130 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cdxl-demux ffmpeg-4.4/tests/ref/fate/cdxl-demux --- ffmpeg-4.2.2/tests/ref/fate/cdxl-demux 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cdxl-demux 2021-04-08 21:28:40.000000000 +0000 @@ -1,30 +1,30 @@ -#tb 0: 1/11025 +#tb 0: 628/3675 #media_type 0: video #codec_id 0: cdxl #dimensions 0: 176x128 #sar 0: 0/1 #tb 1: 1/11025 #media_type 1: audio -#codec_id 1: pcm_s8 +#codec_id 1: pcm_s8_planar #sample_rate 1: 11025 #channel_layout 1: 4 #channel_layout_name 1: mono -0, 0, 0, 1884, 22688, 0xc954a244 +0, 0, 0, 1, 22688, 0xc954a244 1, 0, 0, 1884, 1884, 0x06925e3e -0, 1884, 1884, 1884, 22688, 0x3ee4a304 +0, 1, 1, 1, 22688, 0x3ee4a304 1, 1884, 1884, 1884, 1884, 0x1957ab65 -0, 3768, 3768, 1884, 22688, 0x9777a305 +0, 2, 2, 1, 22688, 0x9777a305 1, 3768, 3768, 1884, 1884, 0x7fcd6e47 -0, 5652, 5652, 1884, 22688, 0xf00aa306 +0, 3, 3, 1, 22688, 0xf00aa306 1, 5652, 5652, 1884, 1884, 0xc974878e -0, 7536, 7536, 1884, 22688, 0x48aca307 +0, 4, 4, 1, 22688, 0x48aca307 1, 7536, 7536, 1884, 1884, 0xecb5c4c8 -0, 9420, 9420, 1884, 22688, 0xa13fa308 +0, 5, 5, 1, 22688, 0xa13fa308 1, 9420, 9420, 1884, 1884, 0x87adce5f -0, 11304, 11304, 1884, 22688, 0xf9d2a309 +0, 6, 6, 1, 22688, 0xf9d2a309 1, 11304, 11304, 1884, 1884, 0x3cf097e4 -0, 13188, 13188, 1884, 22688, 0x5274a30a +0, 7, 7, 1, 22688, 0x5274a30a 1, 13188, 13188, 1884, 1884, 0xcc218105 -0, 15072, 15072, 1884, 22688, 0xab07a30b +0, 8, 8, 1, 22688, 0xab07a30b 1, 15072, 15072, 1884, 1884, 0xf685762f -0, 16956, 16956, 1884, 17896, 0x1a696b6e +0, 9, 9, 1, 17896, 0x1a696b6e diff -Nru ffmpeg-4.2.2/tests/ref/fate/cdxl-ham6 ffmpeg-4.4/tests/ref/fate/cdxl-ham6 --- ffmpeg-4.2.2/tests/ref/fate/cdxl-ham6 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cdxl-ham6 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -#tb 0: 52/525 +#tb 0: 12/121 #media_type 0: video #codec_id 0: rawvideo #dimensions 0: 160x120 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cdxl-ham8 ffmpeg-4.4/tests/ref/fate/cdxl-ham8 --- ffmpeg-4.2.2/tests/ref/fate/cdxl-ham8 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cdxl-ham8 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -#tb 0: 12/281 +#tb 0: 628/3675 #media_type 0: video #codec_id 0: rawvideo #dimensions 0: 176x128 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cdxl-pal8 ffmpeg-4.4/tests/ref/fate/cdxl-pal8 --- ffmpeg-4.2.2/tests/ref/fate/cdxl-pal8 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cdxl-pal8 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -#tb 0: 1/50 +#tb 0: 1/15 #media_type 0: video #codec_id 0: rawvideo #dimensions 0: 176x128 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cdxl-pal8-small ffmpeg-4.4/tests/ref/fate/cdxl-pal8-small --- ffmpeg-4.2.2/tests/ref/fate/cdxl-pal8-small 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cdxl-pal8-small 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -#tb 0: 368/11025 +#tb 0: 1001/30000 #media_type 0: video #codec_id 0: rawvideo #dimensions 0: 128x80 diff -Nru ffmpeg-4.2.2/tests/ref/fate/cfhd-3 ffmpeg-4.4/tests/ref/fate/cfhd-3 --- ffmpeg-4.2.2/tests/ref/fate/cfhd-3 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/cfhd-3 2021-04-08 21:28:40.000000000 +0000 @@ -3,13 +3,13 @@ #codec_id 0: rawvideo #dimensions 0: 496x241 #sar 0: 0/1 -0, 0, 0, 1, 478144, 0x48a01dbb -0, 1, 1, 1, 478144, 0x48a01dbb -0, 2, 2, 1, 478144, 0x48a01dbb -0, 3, 3, 1, 478144, 0xb978a72f -0, 4, 4, 1, 478144, 0x7bbb4679 -0, 5, 5, 1, 478144, 0xc3fd3f59 -0, 6, 6, 1, 478144, 0xfd2a4816 -0, 7, 7, 1, 478144, 0x207f65d3 -0, 8, 8, 1, 478144, 0x207f65d3 -0, 9, 9, 1, 478144, 0x207f65d3 +0, 0, 0, 1, 478144, 0x1e5a0d6c +0, 1, 1, 1, 478144, 0x1e5a0d6c +0, 2, 2, 1, 478144, 0x1e5a0d6c +0, 3, 3, 1, 478144, 0x88788c7d +0, 4, 4, 1, 478144, 0x78643db8 +0, 5, 5, 1, 478144, 0x84303909 +0, 6, 6, 1, 478144, 0x8ddd4828 +0, 7, 7, 1, 478144, 0xc0845d58 +0, 8, 8, 1, 478144, 0xc0845d58 +0, 9, 9, 1, 478144, 0xc0845d58 diff -Nru ffmpeg-4.2.2/tests/ref/fate/concat-demuxer-extended-lavf-mxf ffmpeg-4.4/tests/ref/fate/concat-demuxer-extended-lavf-mxf --- ffmpeg-4.2.2/tests/ref/fate/concat-demuxer-extended-lavf-mxf 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/concat-demuxer-extended-lavf-mxf 2021-04-08 21:28:40.000000000 +0000 @@ -1 +1 @@ -a6fb9c37dc71cb43eb9664a8ae9f1c66 *tests/data/fate/concat-demuxer-extended-lavf-mxf.ffprobe +c70ba87645ddecc8554036eb83a90e59 *tests/data/fate/concat-demuxer-extended-lavf-mxf.ffprobe diff -Nru ffmpeg-4.2.2/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 ffmpeg-4.4/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 --- ffmpeg-4.2.2/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 2021-04-08 21:28:40.000000000 +0000 @@ -1 +1 @@ -cb7c8eac6f8917e39658e1fa4a250da8 *tests/data/fate/concat-demuxer-extended-lavf-mxf_d10.ffprobe +d17d5c3291b408d624205aca9e7ad6b4 *tests/data/fate/concat-demuxer-extended-lavf-mxf_d10.ffprobe diff -Nru ffmpeg-4.2.2/tests/ref/fate/concat-demuxer-simple1-lavf-mxf ffmpeg-4.4/tests/ref/fate/concat-demuxer-simple1-lavf-mxf --- ffmpeg-4.2.2/tests/ref/fate/concat-demuxer-simple1-lavf-mxf 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/concat-demuxer-simple1-lavf-mxf 2021-04-08 21:28:40.000000000 +0000 @@ -1,124 +1,124 @@ -video|0|0|0.000000|-1|-0.040000|1|0.040000|N/A|N/A|24801|7168|K_ -audio|1|0|0.000000|0|0.000000|1920|0.040000|N/A|N/A|3840|32256|K_ -video|0|3|0.120000|0|0.000000|1|0.040000|N/A|N/A|16743|36864|__ -audio|1|1920|0.040000|1920|0.040000|1920|0.040000|N/A|N/A|3840|53760|K_ -video|0|1|0.040000|1|0.040000|1|0.040000|N/A|N/A|13812|58368|__ -audio|1|3840|0.080000|3840|0.080000|1920|0.040000|N/A|N/A|3840|72704|K_ -video|0|2|0.080000|2|0.080000|1|0.040000|N/A|N/A|13607|77312|__ -audio|1|5760|0.120000|5760|0.120000|1920|0.040000|N/A|N/A|3840|91136|K_ -video|0|6|0.240000|3|0.120000|1|0.040000|N/A|N/A|16158|95744|__ -audio|1|7680|0.160000|7680|0.160000|1920|0.040000|N/A|N/A|3840|112128|K_ -video|0|4|0.160000|4|0.160000|1|0.040000|N/A|N/A|13943|116736|__ -audio|1|9600|0.200000|9600|0.200000|1920|0.040000|N/A|N/A|3840|131072|K_ -video|0|5|0.200000|5|0.200000|1|0.040000|N/A|N/A|11223|135680|__ -audio|1|11520|0.240000|11520|0.240000|1920|0.040000|N/A|N/A|3840|146944|K_ -video|0|9|0.360000|6|0.240000|1|0.040000|N/A|N/A|20298|151552|__ -audio|1|13440|0.280000|13440|0.280000|1920|0.040000|N/A|N/A|3840|172032|K_ -video|0|7|0.280000|7|0.280000|1|0.040000|N/A|N/A|13341|176640|__ -audio|1|15360|0.320000|15360|0.320000|1920|0.040000|N/A|N/A|3840|190464|K_ -video|0|8|0.320000|8|0.320000|1|0.040000|N/A|N/A|12362|195072|__ -audio|1|17280|0.360000|17280|0.360000|1920|0.040000|N/A|N/A|3840|207872|K_ -video|0|12|0.480000|9|0.360000|1|0.040000|N/A|N/A|24786|212480|K_ -audio|1|19200|0.400000|19200|0.400000|1920|0.040000|N/A|N/A|3840|237568|K_ -video|0|10|0.400000|10|0.400000|1|0.040000|N/A|N/A|13377|242176|__ -audio|1|21120|0.440000|21120|0.440000|1920|0.040000|N/A|N/A|3840|256000|K_ -video|0|11|0.440000|11|0.440000|1|0.040000|N/A|N/A|15624|260608|__ -audio|1|23040|0.480000|23040|0.480000|1920|0.040000|N/A|N/A|3840|276480|K_ -video|0|15|0.600000|12|0.480000|1|0.040000|N/A|N/A|22597|281088|__ -audio|1|24960|0.520000|24960|0.520000|1920|0.040000|N/A|N/A|3840|304128|K_ -video|0|13|0.520000|13|0.520000|1|0.040000|N/A|N/A|15028|308736|__ -audio|1|26880|0.560000|26880|0.560000|1920|0.040000|N/A|N/A|3840|324096|K_ -video|0|14|0.560000|14|0.560000|1|0.040000|N/A|N/A|14014|328704|__ -audio|1|28800|0.600000|28800|0.600000|1920|0.040000|N/A|N/A|3840|343040|K_ -video|0|18|0.720000|15|0.600000|1|0.040000|N/A|N/A|20731|347648|__ -audio|1|30720|0.640000|30720|0.640000|1920|0.040000|N/A|N/A|3840|368640|K_ -video|0|16|0.640000|16|0.640000|1|0.040000|N/A|N/A|11946|373248|__ -audio|1|32640|0.680000|32640|0.680000|1920|0.040000|N/A|N/A|3840|385536|K_ -video|0|17|0.680000|17|0.680000|1|0.040000|N/A|N/A|14464|390144|__ -audio|1|34560|0.720000|34560|0.720000|1920|0.040000|N/A|N/A|3840|404992|K_ -video|0|21|0.840000|18|0.720000|1|0.040000|N/A|N/A|16189|409600|__ -audio|1|36480|0.760000|36480|0.760000|1920|0.040000|N/A|N/A|3840|425984|K_ -video|0|19|0.760000|19|0.760000|1|0.040000|N/A|N/A|10524|430592|__ -audio|1|38400|0.800000|38400|0.800000|1920|0.040000|N/A|N/A|3840|441344|K_ -video|0|20|0.800000|20|0.800000|1|0.040000|N/A|N/A|10599|445952|__ -audio|1|40320|0.840000|40320|0.840000|1920|0.040000|N/A|N/A|3840|456704|K_ -video|0|24|0.960000|21|0.840000|1|0.040000|N/A|N/A|24711|461312|K_ -audio|1|42240|0.880000|42240|0.880000|1920|0.040000|N/A|N/A|3840|486400|K_ -video|0|22|0.880000|22|0.880000|1|0.040000|N/A|N/A|10840|491008|__ -audio|1|44160|0.920000|44160|0.920000|1920|0.040000|N/A|N/A|3840|502272|K_ -video|0|23|0.920000|23|0.920000|1|0.040000|N/A|N/A|13350|506880|__ -audio|1|46080|0.960000|46080|0.960000|1920|0.040000|N/A|N/A|3840|520704|K_ -video|0|17|0.680000|14|0.560000|1|0.040000|N/A|N/A|24786|212480|K_ -audio|1|28800|0.600000|28800|0.600000|1920|0.040000|N/A|N/A|3840|237568|K_ -video|0|15|0.600000|15|0.600000|1|0.040000|N/A|N/A|13377|242176|__ -audio|1|30720|0.640000|30720|0.640000|1920|0.040000|N/A|N/A|3840|256000|K_ -video|0|16|0.640000|16|0.640000|1|0.040000|N/A|N/A|15624|260608|__ -audio|1|32640|0.680000|32640|0.680000|1920|0.040000|N/A|N/A|3840|276480|K_ -video|0|20|0.800000|17|0.680000|1|0.040000|N/A|N/A|22597|281088|__ -audio|1|34560|0.720000|34560|0.720000|1920|0.040000|N/A|N/A|3840|304128|K_ -video|0|18|0.720000|18|0.720000|1|0.040000|N/A|N/A|15028|308736|__ -audio|1|36480|0.760000|36480|0.760000|1920|0.040000|N/A|N/A|3840|324096|K_ -video|0|19|0.760000|19|0.760000|1|0.040000|N/A|N/A|14014|328704|__ -audio|1|38400|0.800000|38400|0.800000|1920|0.040000|N/A|N/A|3840|343040|K_ -video|0|23|0.920000|20|0.800000|1|0.040000|N/A|N/A|20731|347648|__ -audio|1|40320|0.840000|40320|0.840000|1920|0.040000|N/A|N/A|3840|368640|K_ -video|0|21|0.840000|21|0.840000|1|0.040000|N/A|N/A|11946|373248|__ -audio|1|42240|0.880000|42240|0.880000|1920|0.040000|N/A|N/A|3840|385536|K_ -video|0|22|0.880000|22|0.880000|1|0.040000|N/A|N/A|14464|390144|__ -audio|1|44160|0.920000|44160|0.920000|1920|0.040000|N/A|N/A|3840|404992|K_ -video|0|26|1.040000|23|0.920000|1|0.040000|N/A|N/A|16189|409600|__ -audio|1|46080|0.960000|46080|0.960000|1920|0.040000|N/A|N/A|3840|425984|K_ -video|0|24|0.960000|24|0.960000|1|0.040000|N/A|N/A|10524|430592|__ -audio|1|48000|1.000000|48000|1.000000|1920|0.040000|N/A|N/A|3840|441344|K_ -video|0|25|1.000000|25|1.000000|1|0.040000|N/A|N/A|10599|445952|__ -audio|1|49920|1.040000|49920|1.040000|1920|0.040000|N/A|N/A|3840|456704|K_ -video|0|29|1.160000|26|1.040000|1|0.040000|N/A|N/A|24711|461312|K_ -audio|1|51840|1.080000|51840|1.080000|1920|0.040000|N/A|N/A|3840|486400|K_ -video|0|27|1.080000|27|1.080000|1|0.040000|N/A|N/A|10840|491008|__ -audio|1|53760|1.120000|53760|1.120000|1920|0.040000|N/A|N/A|3840|502272|K_ -video|0|28|1.120000|28|1.120000|1|0.040000|N/A|N/A|13350|506880|__ -audio|1|55680|1.160000|55680|1.160000|1920|0.040000|N/A|N/A|3840|520704|K_ -video|0|25|1.000000|24|0.960000|1|0.040000|N/A|N/A|24801|7168|K_|1 -Strings Metadata -audio|1|48000|1.000000|48000|1.000000|1920|0.040000|N/A|N/A|3840|32256|K_|1 -Strings Metadata -video|0|28|1.120000|25|1.000000|1|0.040000|N/A|N/A|16743|36864|__|1 -Strings Metadata -audio|1|49920|1.040000|49920|1.040000|1920|0.040000|N/A|N/A|3840|53760|K_|1 -Strings Metadata -video|0|26|1.040000|26|1.040000|1|0.040000|N/A|N/A|13812|58368|__|1 -Strings Metadata -audio|1|51840|1.080000|51840|1.080000|1920|0.040000|N/A|N/A|3840|72704|K_|1 -Strings Metadata -video|0|27|1.080000|27|1.080000|1|0.040000|N/A|N/A|13607|77312|__|1 -Strings Metadata -audio|1|53760|1.120000|53760|1.120000|1920|0.040000|N/A|N/A|3840|91136|K_|1 -Strings Metadata -video|0|31|1.240000|28|1.120000|1|0.040000|N/A|N/A|16158|95744|__|1 -Strings Metadata -audio|1|55680|1.160000|55680|1.160000|1920|0.040000|N/A|N/A|3840|112128|K_|1 -Strings Metadata -video|0|29|1.160000|29|1.160000|1|0.040000|N/A|N/A|13943|116736|__|1 -Strings Metadata -audio|1|57600|1.200000|57600|1.200000|1920|0.040000|N/A|N/A|3840|131072|K_|1 -Strings Metadata -video|0|30|1.200000|30|1.200000|1|0.040000|N/A|N/A|11223|135680|__|1 -Strings Metadata -audio|1|59520|1.240000|59520|1.240000|1920|0.040000|N/A|N/A|3840|146944|K_|1 -Strings Metadata -video|0|34|1.360000|31|1.240000|1|0.040000|N/A|N/A|20298|151552|__|1 -Strings Metadata -audio|1|61440|1.280000|61440|1.280000|1920|0.040000|N/A|N/A|3840|172032|K_|1 -Strings Metadata -video|0|32|1.280000|32|1.280000|1|0.040000|N/A|N/A|13341|176640|__|1 -Strings Metadata -audio|1|63360|1.320000|63360|1.320000|1920|0.040000|N/A|N/A|3840|190464|K_|1 +video|0|0|0.000000|-1|-0.040000|1|0.040000|24801|7168|K_ +audio|1|0|0.000000|0|0.000000|1920|0.040000|3840|32256|K_ +video|0|3|0.120000|0|0.000000|1|0.040000|16743|36864|__ +audio|1|1920|0.040000|1920|0.040000|1920|0.040000|3840|53760|K_ +video|0|1|0.040000|1|0.040000|1|0.040000|13812|58368|__ +audio|1|3840|0.080000|3840|0.080000|1920|0.040000|3840|72704|K_ +video|0|2|0.080000|2|0.080000|1|0.040000|13607|77312|__ +audio|1|5760|0.120000|5760|0.120000|1920|0.040000|3840|91136|K_ +video|0|6|0.240000|3|0.120000|1|0.040000|16158|95744|__ +audio|1|7680|0.160000|7680|0.160000|1920|0.040000|3840|112128|K_ +video|0|4|0.160000|4|0.160000|1|0.040000|13943|116736|__ +audio|1|9600|0.200000|9600|0.200000|1920|0.040000|3840|131072|K_ +video|0|5|0.200000|5|0.200000|1|0.040000|11223|135680|__ +audio|1|11520|0.240000|11520|0.240000|1920|0.040000|3840|146944|K_ +video|0|9|0.360000|6|0.240000|1|0.040000|20298|151552|__ +audio|1|13440|0.280000|13440|0.280000|1920|0.040000|3840|172032|K_ +video|0|7|0.280000|7|0.280000|1|0.040000|13341|176640|__ +audio|1|15360|0.320000|15360|0.320000|1920|0.040000|3840|190464|K_ +video|0|8|0.320000|8|0.320000|1|0.040000|12362|195072|__ +audio|1|17280|0.360000|17280|0.360000|1920|0.040000|3840|207872|K_ +video|0|12|0.480000|9|0.360000|1|0.040000|24786|212480|K_ +audio|1|19200|0.400000|19200|0.400000|1920|0.040000|3840|237568|K_ +video|0|10|0.400000|10|0.400000|1|0.040000|13377|242176|__ +audio|1|21120|0.440000|21120|0.440000|1920|0.040000|3840|256000|K_ +video|0|11|0.440000|11|0.440000|1|0.040000|15624|260608|__ +audio|1|23040|0.480000|23040|0.480000|1920|0.040000|3840|276480|K_ +video|0|15|0.600000|12|0.480000|1|0.040000|22597|281088|__ +audio|1|24960|0.520000|24960|0.520000|1920|0.040000|3840|304128|K_ +video|0|13|0.520000|13|0.520000|1|0.040000|15028|308736|__ +audio|1|26880|0.560000|26880|0.560000|1920|0.040000|3840|324096|K_ +video|0|14|0.560000|14|0.560000|1|0.040000|14014|328704|__ +audio|1|28800|0.600000|28800|0.600000|1920|0.040000|3840|343040|K_ +video|0|18|0.720000|15|0.600000|1|0.040000|20731|347648|__ +audio|1|30720|0.640000|30720|0.640000|1920|0.040000|3840|368640|K_ +video|0|16|0.640000|16|0.640000|1|0.040000|11946|373248|__ +audio|1|32640|0.680000|32640|0.680000|1920|0.040000|3840|385536|K_ +video|0|17|0.680000|17|0.680000|1|0.040000|14464|390144|__ +audio|1|34560|0.720000|34560|0.720000|1920|0.040000|3840|404992|K_ +video|0|21|0.840000|18|0.720000|1|0.040000|16189|409600|__ +audio|1|36480|0.760000|36480|0.760000|1920|0.040000|3840|425984|K_ +video|0|19|0.760000|19|0.760000|1|0.040000|10524|430592|__ +audio|1|38400|0.800000|38400|0.800000|1920|0.040000|3840|441344|K_ +video|0|20|0.800000|20|0.800000|1|0.040000|10599|445952|__ +audio|1|40320|0.840000|40320|0.840000|1920|0.040000|3840|456704|K_ +video|0|24|0.960000|21|0.840000|1|0.040000|24711|461312|K_ +audio|1|42240|0.880000|42240|0.880000|1920|0.040000|3840|486400|K_ +video|0|22|0.880000|22|0.880000|1|0.040000|10840|491008|__ +audio|1|44160|0.920000|44160|0.920000|1920|0.040000|3840|502272|K_ +video|0|23|0.920000|23|0.920000|1|0.040000|13350|506880|__ +audio|1|46080|0.960000|46080|0.960000|1920|0.040000|3840|520704|K_ +video|0|17|0.680000|14|0.560000|1|0.040000|24786|212480|K_ +audio|1|28800|0.600000|28800|0.600000|1920|0.040000|3840|237568|K_ +video|0|15|0.600000|15|0.600000|1|0.040000|13377|242176|__ +audio|1|30720|0.640000|30720|0.640000|1920|0.040000|3840|256000|K_ +video|0|16|0.640000|16|0.640000|1|0.040000|15624|260608|__ +audio|1|32640|0.680000|32640|0.680000|1920|0.040000|3840|276480|K_ +video|0|20|0.800000|17|0.680000|1|0.040000|22597|281088|__ +audio|1|34560|0.720000|34560|0.720000|1920|0.040000|3840|304128|K_ +video|0|18|0.720000|18|0.720000|1|0.040000|15028|308736|__ +audio|1|36480|0.760000|36480|0.760000|1920|0.040000|3840|324096|K_ +video|0|19|0.760000|19|0.760000|1|0.040000|14014|328704|__ +audio|1|38400|0.800000|38400|0.800000|1920|0.040000|3840|343040|K_ +video|0|23|0.920000|20|0.800000|1|0.040000|20731|347648|__ +audio|1|40320|0.840000|40320|0.840000|1920|0.040000|3840|368640|K_ +video|0|21|0.840000|21|0.840000|1|0.040000|11946|373248|__ +audio|1|42240|0.880000|42240|0.880000|1920|0.040000|3840|385536|K_ +video|0|22|0.880000|22|0.880000|1|0.040000|14464|390144|__ +audio|1|44160|0.920000|44160|0.920000|1920|0.040000|3840|404992|K_ +video|0|26|1.040000|23|0.920000|1|0.040000|16189|409600|__ +audio|1|46080|0.960000|46080|0.960000|1920|0.040000|3840|425984|K_ +video|0|24|0.960000|24|0.960000|1|0.040000|10524|430592|__ +audio|1|48000|1.000000|48000|1.000000|1920|0.040000|3840|441344|K_ +video|0|25|1.000000|25|1.000000|1|0.040000|10599|445952|__ +audio|1|49920|1.040000|49920|1.040000|1920|0.040000|3840|456704|K_ +video|0|29|1.160000|26|1.040000|1|0.040000|24711|461312|K_ +audio|1|51840|1.080000|51840|1.080000|1920|0.040000|3840|486400|K_ +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|N/A|N/A|12362|195072|__|1 +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|N/A|N/A|3840|207872|K_|1 +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|N/A|N/A|24786|212480|K_|1 +video|0|37|1.480000|34|1.360000|1|0.040000|24786|212480|K_|1 Strings Metadata -0|mpeg2video|4|video|1/25|[0][0][0][0]|0x0000|352|288|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|N/A|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|0x060A2B340101010501010D001300000000000000000000000000000000000001 -1|pcm_s16le|unknown|audio|1/48000|[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|0x060A2B340101010501010D001300000000000000000000000000000000000001 +0|mpeg2video|4|video|[0][0][0][0]|0x0000|352|288|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|0x060A2B340101010501010D001300000000000000000000000000000000000001 +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|0x060A2B340101010501010D001300000000000000000000000000000000000001 diff -Nru ffmpeg-4.2.2/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 ffmpeg-4.4/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 --- ffmpeg-4.2.2/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 2021-04-08 21:28:40.000000000 +0000 @@ -1,82 +1,82 @@ -video|0|0|0.000000|0|0.000000|1|0.040000|N/A|N/A|150000|7168|K_ -audio|1|0|0.000000|0|0.000000|1920|0.040000|N/A|N/A|7680|157696|K_ -video|0|1|0.040000|1|0.040000|1|0.040000|N/A|N/A|150000|220160|K_ -audio|1|1920|0.040000|1920|0.040000|1920|0.040000|N/A|N/A|7680|370688|K_ -video|0|2|0.080000|2|0.080000|1|0.040000|N/A|N/A|150000|433152|K_ -audio|1|3840|0.080000|3840|0.080000|1920|0.040000|N/A|N/A|7680|583680|K_ -video|0|3|0.120000|3|0.120000|1|0.040000|N/A|N/A|150000|646144|K_ -audio|1|5760|0.120000|5760|0.120000|1920|0.040000|N/A|N/A|7680|796672|K_ -video|0|4|0.160000|4|0.160000|1|0.040000|N/A|N/A|150000|859136|K_ -audio|1|7680|0.160000|7680|0.160000|1920|0.040000|N/A|N/A|7680|1009664|K_ -video|0|5|0.200000|5|0.200000|1|0.040000|N/A|N/A|150000|1072128|K_ -audio|1|9600|0.200000|9600|0.200000|1920|0.040000|N/A|N/A|7680|1222656|K_ -video|0|6|0.240000|6|0.240000|1|0.040000|N/A|N/A|150000|1285120|K_ -audio|1|11520|0.240000|11520|0.240000|1920|0.040000|N/A|N/A|7680|1435648|K_ -video|0|7|0.280000|7|0.280000|1|0.040000|N/A|N/A|150000|1498112|K_ -audio|1|13440|0.280000|13440|0.280000|1920|0.040000|N/A|N/A|7680|1648640|K_ -video|0|8|0.320000|8|0.320000|1|0.040000|N/A|N/A|150000|1711104|K_ -audio|1|15360|0.320000|15360|0.320000|1920|0.040000|N/A|N/A|7680|1861632|K_ -video|0|9|0.360000|9|0.360000|1|0.040000|N/A|N/A|150000|1924096|K_ -audio|1|17280|0.360000|17280|0.360000|1920|0.040000|N/A|N/A|7680|2074624|K_ -video|0|10|0.400000|10|0.400000|1|0.040000|N/A|N/A|150000|2137088|K_ -audio|1|19200|0.400000|19200|0.400000|1920|0.040000|N/A|N/A|7680|2287616|K_ -video|0|11|0.440000|11|0.440000|1|0.040000|N/A|N/A|150000|2350080|K_ -audio|1|21120|0.440000|21120|0.440000|1920|0.040000|N/A|N/A|7680|2500608|K_ -video|0|12|0.480000|12|0.480000|1|0.040000|N/A|N/A|150000|2563072|K_ -audio|1|23040|0.480000|23040|0.480000|1920|0.040000|N/A|N/A|7680|2713600|K_ -video|0|13|0.520000|13|0.520000|1|0.040000|N/A|N/A|150000|2776064|K_ -audio|1|24960|0.520000|24960|0.520000|1920|0.040000|N/A|N/A|7680|2926592|K_ -video|0|14|0.560000|14|0.560000|1|0.040000|N/A|N/A|150000|2989056|K_ -audio|1|26880|0.560000|26880|0.560000|1920|0.040000|N/A|N/A|7680|3139584|K_ -video|0|15|0.600000|15|0.600000|1|0.040000|N/A|N/A|150000|3202048|K_ -audio|1|28800|0.600000|28800|0.600000|1920|0.040000|N/A|N/A|7680|3352576|K_ -video|0|16|0.640000|16|0.640000|1|0.040000|N/A|N/A|150000|3415040|K_ -audio|1|30720|0.640000|30720|0.640000|1920|0.040000|N/A|N/A|7680|3565568|K_ -video|0|17|0.680000|17|0.680000|1|0.040000|N/A|N/A|150000|3628032|K_ -audio|1|32640|0.680000|32640|0.680000|1920|0.040000|N/A|N/A|7680|3778560|K_ -video|0|18|0.720000|18|0.720000|1|0.040000|N/A|N/A|150000|3841024|K_ -audio|1|34560|0.720000|34560|0.720000|1920|0.040000|N/A|N/A|7680|3991552|K_ -video|0|19|0.760000|19|0.760000|1|0.040000|N/A|N/A|150000|4054016|K_ -audio|1|36480|0.760000|36480|0.760000|1920|0.040000|N/A|N/A|7680|4204544|K_ -video|0|20|0.800000|20|0.800000|1|0.040000|N/A|N/A|150000|4267008|K_ -audio|1|38400|0.800000|38400|0.800000|1920|0.040000|N/A|N/A|7680|4417536|K_ -video|0|21|0.840000|21|0.840000|1|0.040000|N/A|N/A|150000|4480000|K_ -audio|1|40320|0.840000|40320|0.840000|1920|0.040000|N/A|N/A|7680|4630528|K_ -video|0|22|0.880000|22|0.880000|1|0.040000|N/A|N/A|150000|4692992|K_ -audio|1|42240|0.880000|42240|0.880000|1920|0.040000|N/A|N/A|7680|4843520|K_ -video|0|23|0.920000|23|0.920000|1|0.040000|N/A|N/A|150000|4905984|K_ -audio|1|44160|0.920000|44160|0.920000|1920|0.040000|N/A|N/A|7680|5056512|K_ -video|0|24|0.960000|24|0.960000|1|0.040000|N/A|N/A|150000|5118976|K_ -audio|1|46080|0.960000|46080|0.960000|1920|0.040000|N/A|N/A|7680|5269504|K_ -video|0|25|1.000000|25|1.000000|1|0.040000|N/A|N/A|150000|4267008|K_ -audio|1|48000|1.000000|48000|1.000000|1920|0.040000|N/A|N/A|7680|4417536|K_ -video|0|26|1.040000|26|1.040000|1|0.040000|N/A|N/A|150000|4480000|K_ -audio|1|49920|1.040000|49920|1.040000|1920|0.040000|N/A|N/A|7680|4630528|K_ -video|0|27|1.080000|27|1.080000|1|0.040000|N/A|N/A|150000|4692992|K_ -audio|1|51840|1.080000|51840|1.080000|1920|0.040000|N/A|N/A|7680|4843520|K_ -video|0|28|1.120000|28|1.120000|1|0.040000|N/A|N/A|150000|4905984|K_ -audio|1|53760|1.120000|53760|1.120000|1920|0.040000|N/A|N/A|7680|5056512|K_ -video|0|29|1.160000|29|1.160000|1|0.040000|N/A|N/A|150000|5118976|K_ -audio|1|55680|1.160000|55680|1.160000|1920|0.040000|N/A|N/A|7680|5269504|K_ -video|0|30|1.200000|30|1.200000|1|0.040000|N/A|N/A|150000|1072128|K_|1 -Strings Metadata -audio|1|57600|1.200000|57600|1.200000|1920|0.040000|N/A|N/A|7680|1222656|K_|1 -Strings Metadata -video|0|31|1.240000|31|1.240000|1|0.040000|N/A|N/A|150000|1285120|K_|1 -Strings Metadata -audio|1|59520|1.240000|59520|1.240000|1920|0.040000|N/A|N/A|7680|1435648|K_|1 -Strings Metadata -video|0|32|1.280000|32|1.280000|1|0.040000|N/A|N/A|150000|1498112|K_|1 -Strings Metadata -audio|1|61440|1.280000|61440|1.280000|1920|0.040000|N/A|N/A|7680|1648640|K_|1 -Strings Metadata -video|0|33|1.320000|33|1.320000|1|0.040000|N/A|N/A|150000|1711104|K_|1 +video|0|0|0.000000|0|0.000000|1|0.040000|150000|7168|K_ +audio|1|0|0.000000|0|0.000000|1920|0.040000|7680|157696|K_ +video|0|1|0.040000|1|0.040000|1|0.040000|150000|220160|K_ +audio|1|1920|0.040000|1920|0.040000|1920|0.040000|7680|370688|K_ +video|0|2|0.080000|2|0.080000|1|0.040000|150000|433152|K_ +audio|1|3840|0.080000|3840|0.080000|1920|0.040000|7680|583680|K_ +video|0|3|0.120000|3|0.120000|1|0.040000|150000|646144|K_ +audio|1|5760|0.120000|5760|0.120000|1920|0.040000|7680|796672|K_ +video|0|4|0.160000|4|0.160000|1|0.040000|150000|859136|K_ +audio|1|7680|0.160000|7680|0.160000|1920|0.040000|7680|1009664|K_ +video|0|5|0.200000|5|0.200000|1|0.040000|150000|1072128|K_ +audio|1|9600|0.200000|9600|0.200000|1920|0.040000|7680|1222656|K_ +video|0|6|0.240000|6|0.240000|1|0.040000|150000|1285120|K_ +audio|1|11520|0.240000|11520|0.240000|1920|0.040000|7680|1435648|K_ +video|0|7|0.280000|7|0.280000|1|0.040000|150000|1498112|K_ +audio|1|13440|0.280000|13440|0.280000|1920|0.040000|7680|1648640|K_ +video|0|8|0.320000|8|0.320000|1|0.040000|150000|1711104|K_ +audio|1|15360|0.320000|15360|0.320000|1920|0.040000|7680|1861632|K_ +video|0|9|0.360000|9|0.360000|1|0.040000|150000|1924096|K_ +audio|1|17280|0.360000|17280|0.360000|1920|0.040000|7680|2074624|K_ +video|0|10|0.400000|10|0.400000|1|0.040000|150000|2137088|K_ +audio|1|19200|0.400000|19200|0.400000|1920|0.040000|7680|2287616|K_ +video|0|11|0.440000|11|0.440000|1|0.040000|150000|2350080|K_ +audio|1|21120|0.440000|21120|0.440000|1920|0.040000|7680|2500608|K_ +video|0|12|0.480000|12|0.480000|1|0.040000|150000|2563072|K_ +audio|1|23040|0.480000|23040|0.480000|1920|0.040000|7680|2713600|K_ +video|0|13|0.520000|13|0.520000|1|0.040000|150000|2776064|K_ +audio|1|24960|0.520000|24960|0.520000|1920|0.040000|7680|2926592|K_ +video|0|14|0.560000|14|0.560000|1|0.040000|150000|2989056|K_ +audio|1|26880|0.560000|26880|0.560000|1920|0.040000|7680|3139584|K_ +video|0|15|0.600000|15|0.600000|1|0.040000|150000|3202048|K_ +audio|1|28800|0.600000|28800|0.600000|1920|0.040000|7680|3352576|K_ +video|0|16|0.640000|16|0.640000|1|0.040000|150000|3415040|K_ +audio|1|30720|0.640000|30720|0.640000|1920|0.040000|7680|3565568|K_ +video|0|17|0.680000|17|0.680000|1|0.040000|150000|3628032|K_ +audio|1|32640|0.680000|32640|0.680000|1920|0.040000|7680|3778560|K_ +video|0|18|0.720000|18|0.720000|1|0.040000|150000|3841024|K_ +audio|1|34560|0.720000|34560|0.720000|1920|0.040000|7680|3991552|K_ +video|0|19|0.760000|19|0.760000|1|0.040000|150000|4054016|K_ +audio|1|36480|0.760000|36480|0.760000|1920|0.040000|7680|4204544|K_ +video|0|20|0.800000|20|0.800000|1|0.040000|150000|4267008|K_ +audio|1|38400|0.800000|38400|0.800000|1920|0.040000|7680|4417536|K_ +video|0|21|0.840000|21|0.840000|1|0.040000|150000|4480000|K_ +audio|1|40320|0.840000|40320|0.840000|1920|0.040000|7680|4630528|K_ +video|0|22|0.880000|22|0.880000|1|0.040000|150000|4692992|K_ +audio|1|42240|0.880000|42240|0.880000|1920|0.040000|7680|4843520|K_ +video|0|23|0.920000|23|0.920000|1|0.040000|150000|4905984|K_ +audio|1|44160|0.920000|44160|0.920000|1920|0.040000|7680|5056512|K_ +video|0|24|0.960000|24|0.960000|1|0.040000|150000|5118976|K_ +audio|1|46080|0.960000|46080|0.960000|1920|0.040000|7680|5269504|K_ +video|0|25|1.000000|25|1.000000|1|0.040000|150000|4267008|K_ +audio|1|48000|1.000000|48000|1.000000|1920|0.040000|7680|4417536|K_ +video|0|26|1.040000|26|1.040000|1|0.040000|150000|4480000|K_ +audio|1|49920|1.040000|49920|1.040000|1920|0.040000|7680|4630528|K_ +video|0|27|1.080000|27|1.080000|1|0.040000|150000|4692992|K_ +audio|1|51840|1.080000|51840|1.080000|1920|0.040000|7680|4843520|K_ +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|N/A|N/A|7680|1861632|K_|1 +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|N/A|N/A|150000|1924096|K_|1 +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|N/A|N/A|7680|2074624|K_|1 +audio|1|65280|1.360000|65280|1.360000|1920|0.040000|7680|2074624|K_|1 Strings Metadata -0|mpeg2video|0|video|1/25|[0][0][0][0]|0x0000|720|608|0|0|0|1:1|45:38|yuv422p|5|tv|unknown|unknown|unknown|topleft|tt|N/A|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|0x060A2B340101010501010D001300000000000000000000000000000000000001 -1|pcm_s16le|unknown|audio|1/48000|[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|0x060A2B340101010501010D001300000000000000000000000000000000000001 +0|mpeg2video|0|video|[0][0][0][0]|0x0000|720|608|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|0x060A2B340101010501010D001300000000000000000000000000000000000001 +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|0x060A2B340101010501010D001300000000000000000000000000000000000001 diff -Nru ffmpeg-4.2.2/tests/ref/fate/concat-demuxer-simple2-lavf-ts ffmpeg-4.4/tests/ref/fate/concat-demuxer-simple2-lavf-ts --- ffmpeg-4.2.2/tests/ref/fate/concat-demuxer-simple2-lavf-ts 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/concat-demuxer-simple2-lavf-ts 2021-04-08 21:28:40.000000000 +0000 @@ -1,215 +1,215 @@ -video|1|982|0.010911|-2618|-0.029089|3600|0.040000|N/A|N/A|24801|564|K_MPEGTS Stream ID +video|1|982|0.010911|-2618|-0.029089|3600|0.040000|24801|564|K_MPEGTS Stream ID -video|1|4582|0.050911|982|0.010911|3600|0.040000|N/A|N/A|16429|27072|__MPEGTS Stream ID +video|1|4582|0.050911|982|0.010911|3600|0.040000|16429|25944|__MPEGTS Stream ID -video|1|8182|0.090911|4582|0.050911|3600|0.040000|N/A|N/A|14508|44932|__MPEGTS Stream ID +video|1|8182|0.090911|4582|0.050911|3600|0.040000|14508|42864|__MPEGTS Stream ID -video|1|11782|0.130911|8182|0.090911|3600|0.040000|N/A|N/A|12622|60536|__MPEGTS Stream ID +video|1|11782|0.130911|8182|0.090911|3600|0.040000|12622|58092|__MPEGTS Stream ID -video|1|15382|0.170911|11782|0.130911|3600|0.040000|N/A|N/A|13393|74260|__MPEGTS Stream ID +video|1|15382|0.170911|11782|0.130911|3600|0.040000|13393|71064|__MPEGTS Stream ID -video|1|18982|0.210911|15382|0.170911|3600|0.040000|N/A|N/A|13092|88924|__MPEGTS Stream ID +video|1|18982|0.210911|15382|0.170911|3600|0.040000|13092|84788|__MPEGTS Stream ID -video|1|22582|0.250911|18982|0.210911|3600|0.040000|N/A|N/A|12755|102836|__MPEGTS Stream ID +video|1|22582|0.250911|18982|0.210911|3600|0.040000|12755|98700|__MPEGTS Stream ID -video|1|26182|0.290911|22582|0.250911|3600|0.040000|N/A|N/A|12023|116748|__MPEGTS Stream ID +video|1|26182|0.290911|22582|0.250911|3600|0.040000|12023|111860|__MPEGTS Stream ID -audio|0|0|0.000000|0|0.000000|2351|0.026122|N/A|N/A|208|159988|K_MPEGTS Stream ID +audio|0|0|0.000000|0|0.000000|2351|0.026122|208|152844|K_MPEGTS Stream ID -audio|0|2351|0.026122|2351|0.026122|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|4702|0.052244|4702|0.052244|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|7053|0.078367|7053|0.078367|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|9404|0.104489|9404|0.104489|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|11755|0.130611|11755|0.130611|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|14106|0.156733|14106|0.156733|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|16457|0.182856|16457|0.182856|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|18808|0.208978|18808|0.208978|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|21159|0.235100|21159|0.235100|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|23510|0.261222|23510|0.261222|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|25861|0.287344|25861|0.287344|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|28212|0.313467|28212|0.313467|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|30563|0.339589|30563|0.339589|2351|0.026122|N/A|N/A|209|N/A|K_ -video|1|29782|0.330911|26182|0.290911|3600|0.040000|N/A|N/A|14098|130096|__MPEGTS Stream ID +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_ +audio|0|7053|0.078367|7053|0.078367|2351|0.026122|209|N/A|K_ +audio|0|9404|0.104489|9404|0.104489|2351|0.026122|209|N/A|K_ +audio|0|11755|0.130611|11755|0.130611|2351|0.026122|209|N/A|K_ +audio|0|14106|0.156733|14106|0.156733|2351|0.026122|209|N/A|K_ +audio|0|16457|0.182856|16457|0.182856|2351|0.026122|209|N/A|K_ +audio|0|18808|0.208978|18808|0.208978|2351|0.026122|209|N/A|K_ +audio|0|21159|0.235100|21159|0.235100|2351|0.026122|209|N/A|K_ +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 -video|1|33382|0.370911|29782|0.330911|3600|0.040000|N/A|N/A|13329|145324|__MPEGTS Stream ID +video|1|33382|0.370911|29782|0.330911|3600|0.040000|13329|139120|__MPEGTS Stream ID -video|1|36982|0.410911|33382|0.370911|3600|0.040000|N/A|N/A|12135|162996|__MPEGTS Stream ID +video|1|36982|0.410911|33382|0.370911|3600|0.040000|12135|155852|__MPEGTS Stream ID -video|1|40582|0.450911|36982|0.410911|3600|0.040000|N/A|N/A|12282|176344|__MPEGTS Stream ID +video|1|40582|0.450911|36982|0.410911|3600|0.040000|12282|168448|__MPEGTS Stream ID -video|1|44182|0.490911|40582|0.450911|3600|0.040000|N/A|N/A|24786|189692|K_MPEGTS Stream ID +video|1|44182|0.490911|40582|0.450911|3600|0.040000|24786|181420|K_MPEGTS Stream ID -video|1|47782|0.530911|44182|0.490911|3600|0.040000|N/A|N/A|17440|216388|__MPEGTS Stream ID +video|1|47782|0.530911|44182|0.490911|3600|0.040000|17440|206988|__MPEGTS Stream ID -video|1|51382|0.570911|47782|0.530911|3600|0.040000|N/A|N/A|15019|235000|__MPEGTS Stream ID +video|1|51382|0.570911|47782|0.530911|3600|0.040000|15019|224848|__MPEGTS Stream ID -video|1|54982|0.610911|51382|0.570911|3600|0.040000|N/A|N/A|13449|251356|__MPEGTS Stream ID +video|1|54982|0.610911|51382|0.570911|3600|0.040000|13449|240640|__MPEGTS Stream ID -video|1|58582|0.650911|54982|0.610911|3600|0.040000|N/A|N/A|12398|266020|__MPEGTS Stream ID +video|1|58582|0.650911|54982|0.610911|3600|0.040000|12398|254552|__MPEGTS Stream ID -video|1|62182|0.690911|58582|0.650911|3600|0.040000|N/A|N/A|13455|279744|__MPEGTS Stream ID +video|1|62182|0.690911|58582|0.650911|3600|0.040000|13455|267336|__MPEGTS Stream ID -audio|0|32915|0.365722|32915|0.365722|2351|0.026122|N/A|N/A|209|322608|K_MPEGTS Stream ID +audio|0|32915|0.365722|32915|0.365722|2351|0.026122|209|308508|K_MPEGTS Stream ID -audio|0|35266|0.391844|35266|0.391844|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|37617|0.417967|37617|0.417967|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|39968|0.444089|39968|0.444089|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|42319|0.470211|42319|0.470211|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|44670|0.496333|44670|0.496333|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|47021|0.522456|47021|0.522456|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|49372|0.548578|49372|0.548578|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|51723|0.574700|51723|0.574700|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|54074|0.600822|54074|0.600822|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|56425|0.626944|56425|0.626944|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|58776|0.653067|58776|0.653067|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|61127|0.679189|61127|0.679189|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|63478|0.705311|63478|0.705311|2351|0.026122|N/A|N/A|209|N/A|K_ -video|1|65782|0.730911|62182|0.690911|3600|0.040000|N/A|N/A|13836|294408|__MPEGTS Stream ID +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_ +audio|0|39968|0.444089|39968|0.444089|2351|0.026122|209|N/A|K_ +audio|0|42319|0.470211|42319|0.470211|2351|0.026122|209|N/A|K_ +audio|0|44670|0.496333|44670|0.496333|2351|0.026122|209|N/A|K_ +audio|0|47021|0.522456|47021|0.522456|2351|0.026122|209|N/A|K_ +audio|0|49372|0.548578|49372|0.548578|2351|0.026122|209|N/A|K_ +audio|0|51723|0.574700|51723|0.574700|2351|0.026122|209|N/A|K_ +audio|0|54074|0.600822|54074|0.600822|2351|0.026122|209|N/A|K_ +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 -video|1|69382|0.770911|65782|0.730911|3600|0.040000|N/A|N/A|12163|309448|__MPEGTS Stream ID +video|1|69382|0.770911|65782|0.730911|3600|0.040000|12163|295912|__MPEGTS Stream ID -video|1|72982|0.810911|69382|0.770911|3600|0.040000|N/A|N/A|12692|325992|__MPEGTS Stream ID +video|1|72982|0.810911|69382|0.770911|3600|0.040000|12692|311516|__MPEGTS Stream ID -video|1|76582|0.850911|72982|0.810911|3600|0.040000|N/A|N/A|10824|339528|__MPEGTS Stream ID +video|1|76582|0.850911|72982|0.810911|3600|0.040000|10824|325052|__MPEGTS Stream ID -video|1|80182|0.890911|76582|0.850911|3600|0.040000|N/A|N/A|11286|351372|__MPEGTS Stream ID +video|1|80182|0.890911|76582|0.850911|3600|0.040000|11286|336144|__MPEGTS Stream ID -audio|0|65829|0.731433|65829|0.731433|2351|0.026122|N/A|N/A|209|404576|K_MPEGTS Stream ID +audio|0|65829|0.731433|65829|0.731433|2351|0.026122|209|386716|K_MPEGTS Stream ID -audio|0|68180|0.757556|68180|0.757556|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|70531|0.783678|70531|0.783678|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|72882|0.809800|72882|0.809800|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|75233|0.835922|75233|0.835922|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|77584|0.862044|77584|0.862044|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|79935|0.888167|79935|0.888167|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|82286|0.914289|82286|0.914289|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|84637|0.940411|84637|0.940411|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|86988|0.966533|86988|0.966533|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|89339|0.992656|89339|0.992656|2351|0.026122|N/A|N/A|209|N/A|K_ -video|1|83782|0.930911|80182|0.890911|3600|0.040000|N/A|N/A|12678|363592|__MPEGTS Stream ID +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_ +audio|0|72882|0.809800|72882|0.809800|2351|0.026122|209|N/A|K_ +audio|0|75233|0.835922|75233|0.835922|2351|0.026122|209|N/A|K_ +audio|0|77584|0.862044|77584|0.862044|2351|0.026122|209|N/A|K_ +audio|0|79935|0.888167|79935|0.888167|2351|0.026122|209|N/A|K_ +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 -video|1|87382|0.970911|83782|0.930911|3600|0.040000|N/A|N/A|24711|377880|K_ -video|1|91964|1.021822|88364|0.981822|3600|0.040000|N/A|N/A|24801|564|K_MPEGTS Stream ID +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 -video|1|95564|1.061822|91964|1.021822|3600|0.040000|N/A|N/A|16429|27072|__MPEGTS Stream ID +video|1|95564|1.061822|91964|1.021822|3600|0.040000|16429|25944|__MPEGTS Stream ID -video|1|99164|1.101822|95564|1.061822|3600|0.040000|N/A|N/A|14508|44932|__MPEGTS Stream ID +video|1|99164|1.101822|95564|1.061822|3600|0.040000|14508|42864|__MPEGTS Stream ID -video|1|102764|1.141822|99164|1.101822|3600|0.040000|N/A|N/A|12622|60536|__MPEGTS Stream ID +video|1|102764|1.141822|99164|1.101822|3600|0.040000|12622|58092|__MPEGTS Stream ID -video|1|106364|1.181822|102764|1.141822|3600|0.040000|N/A|N/A|13393|74260|__MPEGTS Stream ID +video|1|106364|1.181822|102764|1.141822|3600|0.040000|13393|71064|__MPEGTS Stream ID -video|1|109964|1.221822|106364|1.181822|3600|0.040000|N/A|N/A|13092|88924|__MPEGTS Stream ID +video|1|109964|1.221822|106364|1.181822|3600|0.040000|13092|84788|__MPEGTS Stream ID -video|1|113564|1.261822|109964|1.221822|3600|0.040000|N/A|N/A|12755|102836|__MPEGTS Stream ID +video|1|113564|1.261822|109964|1.221822|3600|0.040000|12755|98700|__MPEGTS Stream ID -video|1|117164|1.301822|113564|1.261822|3600|0.040000|N/A|N/A|12023|116748|__MPEGTS Stream ID +video|1|117164|1.301822|113564|1.261822|3600|0.040000|12023|111860|__MPEGTS Stream ID -audio|0|90982|1.010911|90982|1.010911|2351|0.026122|N/A|N/A|208|159988|K_MPEGTS Stream ID +audio|0|90982|1.010911|90982|1.010911|2351|0.026122|208|152844|K_MPEGTS Stream ID -audio|0|93333|1.037033|93333|1.037033|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|95684|1.063156|95684|1.063156|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|98035|1.089278|98035|1.089278|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|100386|1.115400|100386|1.115400|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|102737|1.141522|102737|1.141522|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|105088|1.167644|105088|1.167644|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|107439|1.193767|107439|1.193767|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|109790|1.219889|109790|1.219889|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|112141|1.246011|112141|1.246011|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|114492|1.272133|114492|1.272133|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|116843|1.298256|116843|1.298256|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|119194|1.324378|119194|1.324378|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|121545|1.350500|121545|1.350500|2351|0.026122|N/A|N/A|209|N/A|K_ -video|1|120764|1.341822|117164|1.301822|3600|0.040000|N/A|N/A|14098|130096|__MPEGTS Stream ID +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_ +audio|0|98035|1.089278|98035|1.089278|2351|0.026122|209|N/A|K_ +audio|0|100386|1.115400|100386|1.115400|2351|0.026122|209|N/A|K_ +audio|0|102737|1.141522|102737|1.141522|2351|0.026122|209|N/A|K_ +audio|0|105088|1.167644|105088|1.167644|2351|0.026122|209|N/A|K_ +audio|0|107439|1.193767|107439|1.193767|2351|0.026122|209|N/A|K_ +audio|0|109790|1.219889|109790|1.219889|2351|0.026122|209|N/A|K_ +audio|0|112141|1.246011|112141|1.246011|2351|0.026122|209|N/A|K_ +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 -video|1|124364|1.381822|120764|1.341822|3600|0.040000|N/A|N/A|13329|145324|__MPEGTS Stream ID +video|1|124364|1.381822|120764|1.341822|3600|0.040000|13329|139120|__MPEGTS Stream ID -video|1|127964|1.421822|124364|1.381822|3600|0.040000|N/A|N/A|12135|162996|__MPEGTS Stream ID +video|1|127964|1.421822|124364|1.381822|3600|0.040000|12135|155852|__MPEGTS Stream ID -video|1|131564|1.461822|127964|1.421822|3600|0.040000|N/A|N/A|12282|176344|__MPEGTS Stream ID +video|1|131564|1.461822|127964|1.421822|3600|0.040000|12282|168448|__MPEGTS Stream ID -video|1|135164|1.501822|131564|1.461822|3600|0.040000|N/A|N/A|24786|189692|K_MPEGTS Stream ID +video|1|135164|1.501822|131564|1.461822|3600|0.040000|24786|181420|K_MPEGTS Stream ID -video|1|138764|1.541822|135164|1.501822|3600|0.040000|N/A|N/A|17440|216388|__MPEGTS Stream ID +video|1|138764|1.541822|135164|1.501822|3600|0.040000|17440|206988|__MPEGTS Stream ID -video|1|142364|1.581822|138764|1.541822|3600|0.040000|N/A|N/A|15019|235000|__MPEGTS Stream ID +video|1|142364|1.581822|138764|1.541822|3600|0.040000|15019|224848|__MPEGTS Stream ID -video|1|145964|1.621822|142364|1.581822|3600|0.040000|N/A|N/A|13449|251356|__MPEGTS Stream ID +video|1|145964|1.621822|142364|1.581822|3600|0.040000|13449|240640|__MPEGTS Stream ID -video|1|149564|1.661822|145964|1.621822|3600|0.040000|N/A|N/A|12398|266020|__MPEGTS Stream ID +video|1|149564|1.661822|145964|1.621822|3600|0.040000|12398|254552|__MPEGTS Stream ID -video|1|153164|1.701822|149564|1.661822|3600|0.040000|N/A|N/A|13455|279744|__MPEGTS Stream ID +video|1|153164|1.701822|149564|1.661822|3600|0.040000|13455|267336|__MPEGTS Stream ID -audio|0|123897|1.376633|123897|1.376633|2351|0.026122|N/A|N/A|209|322608|K_MPEGTS Stream ID +audio|0|123897|1.376633|123897|1.376633|2351|0.026122|209|308508|K_MPEGTS Stream ID -audio|0|126248|1.402756|126248|1.402756|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|128599|1.428878|128599|1.428878|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|130950|1.455000|130950|1.455000|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|133301|1.481122|133301|1.481122|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|135652|1.507244|135652|1.507244|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|138003|1.533367|138003|1.533367|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|140354|1.559489|140354|1.559489|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|142705|1.585611|142705|1.585611|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|145056|1.611733|145056|1.611733|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|147407|1.637856|147407|1.637856|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|149758|1.663978|149758|1.663978|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|152109|1.690100|152109|1.690100|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|154460|1.716222|154460|1.716222|2351|0.026122|N/A|N/A|209|N/A|K_ -video|1|156764|1.741822|153164|1.701822|3600|0.040000|N/A|N/A|13836|294408|__MPEGTS Stream ID +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_ +audio|0|130950|1.455000|130950|1.455000|2351|0.026122|209|N/A|K_ +audio|0|133301|1.481122|133301|1.481122|2351|0.026122|209|N/A|K_ +audio|0|135652|1.507244|135652|1.507244|2351|0.026122|209|N/A|K_ +audio|0|138003|1.533367|138003|1.533367|2351|0.026122|209|N/A|K_ +audio|0|140354|1.559489|140354|1.559489|2351|0.026122|209|N/A|K_ +audio|0|142705|1.585611|142705|1.585611|2351|0.026122|209|N/A|K_ +audio|0|145056|1.611733|145056|1.611733|2351|0.026122|209|N/A|K_ +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 -video|1|160364|1.781822|156764|1.741822|3600|0.040000|N/A|N/A|12163|309448|__MPEGTS Stream ID +video|1|160364|1.781822|156764|1.741822|3600|0.040000|12163|295912|__MPEGTS Stream ID -video|1|163964|1.821822|160364|1.781822|3600|0.040000|N/A|N/A|12692|325992|__MPEGTS Stream ID +video|1|163964|1.821822|160364|1.781822|3600|0.040000|12692|311516|__MPEGTS Stream ID -video|1|167564|1.861822|163964|1.821822|3600|0.040000|N/A|N/A|10824|339528|__MPEGTS Stream ID +video|1|167564|1.861822|163964|1.821822|3600|0.040000|10824|325052|__MPEGTS Stream ID -video|1|171164|1.901822|167564|1.861822|3600|0.040000|N/A|N/A|11286|351372|__MPEGTS Stream ID +video|1|171164|1.901822|167564|1.861822|3600|0.040000|11286|336144|__MPEGTS Stream ID -audio|0|156811|1.742344|156811|1.742344|2351|0.026122|N/A|N/A|209|404576|K_MPEGTS Stream ID +audio|0|156811|1.742344|156811|1.742344|2351|0.026122|209|386716|K_MPEGTS Stream ID -audio|0|159162|1.768467|159162|1.768467|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|161513|1.794589|161513|1.794589|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|163864|1.820711|163864|1.820711|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|166215|1.846833|166215|1.846833|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|168566|1.872956|168566|1.872956|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|170917|1.899078|170917|1.899078|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|173268|1.925200|173268|1.925200|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|175619|1.951322|175619|1.951322|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|177970|1.977444|177970|1.977444|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|180321|2.003567|180321|2.003567|2351|0.026122|N/A|N/A|209|N/A|K_ -video|1|174764|1.941822|171164|1.901822|3600|0.040000|N/A|N/A|12678|363592|__MPEGTS Stream ID +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_ +audio|0|163864|1.820711|163864|1.820711|2351|0.026122|209|N/A|K_ +audio|0|166215|1.846833|166215|1.846833|2351|0.026122|209|N/A|K_ +audio|0|168566|1.872956|168566|1.872956|2351|0.026122|209|N/A|K_ +audio|0|170917|1.899078|170917|1.899078|2351|0.026122|209|N/A|K_ +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 -video|1|178364|1.981822|174764|1.941822|3600|0.040000|N/A|N/A|24711|377880|K_ -video|1|139582|1.550911|135982|1.510911|3600|0.040000|N/A|N/A|12692|325992|__MPEGTS Stream ID +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 -video|1|143182|1.590911|139582|1.550911|3600|0.040000|N/A|N/A|10824|339528|__MPEGTS Stream ID +video|1|143182|1.590911|139582|1.550911|3600|0.040000|10824|325052|__MPEGTS Stream ID -video|1|146782|1.630911|143182|1.590911|3600|0.040000|N/A|N/A|11286|351372|__MPEGTS Stream ID +video|1|146782|1.630911|143182|1.590911|3600|0.040000|11286|336144|__MPEGTS Stream ID -audio|0|132429|1.471433|132429|1.471433|2351|0.026122|N/A|N/A|209|404576|K_MPEGTS Stream ID +audio|0|132429|1.471433|132429|1.471433|2351|0.026122|209|386716|K_MPEGTS Stream ID -audio|0|134780|1.497556|134780|1.497556|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|137131|1.523678|137131|1.523678|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|139482|1.549800|139482|1.549800|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|141833|1.575922|141833|1.575922|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|144184|1.602044|144184|1.602044|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|146535|1.628167|146535|1.628167|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|148886|1.654289|148886|1.654289|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|151237|1.680411|151237|1.680411|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|153588|1.706533|153588|1.706533|2351|0.026122|N/A|N/A|209|N/A|K_ -audio|0|155939|1.732656|155939|1.732656|2351|0.026122|N/A|N/A|209|N/A|K_ -video|1|150382|1.670911|146782|1.630911|3600|0.040000|N/A|N/A|12678|363592|__MPEGTS Stream ID +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_ +audio|0|139482|1.549800|139482|1.549800|2351|0.026122|209|N/A|K_ +audio|0|141833|1.575922|141833|1.575922|2351|0.026122|209|N/A|K_ +audio|0|144184|1.602044|144184|1.602044|2351|0.026122|209|N/A|K_ +audio|0|146535|1.628167|146535|1.628167|2351|0.026122|209|N/A|K_ +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 -video|1|153982|1.710911|150382|1.670911|3600|0.040000|N/A|N/A|24711|377880|K_ -video|1|161182|1.790911|157582|1.750911|3600|0.040000|N/A|N/A|12135|162996|__MPEGTS Stream ID +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 -video|1|164782|1.830911|161182|1.790911|3600|0.040000|N/A|N/A|12282|176344|__MPEGTS Stream ID +video|1|164782|1.830911|161182|1.790911|3600|0.040000|12282|168448|__MPEGTS Stream ID -video|1|168382|1.870911|164782|1.830911|3600|0.040000|N/A|N/A|24786|189692|K_MPEGTS Stream ID +video|1|168382|1.870911|164782|1.830911|3600|0.040000|24786|181420|K_MPEGTS Stream ID -video|1|171982|1.910911|168382|1.870911|3600|0.040000|N/A|N/A|17440|216388|__MPEGTS Stream ID +video|1|171982|1.910911|168382|1.870911|3600|0.040000|17440|206988|__MPEGTS Stream ID -video|1|175582|1.950911|171982|1.910911|3600|0.040000|N/A|N/A|15019|235000|__MPEGTS Stream ID +video|1|175582|1.950911|171982|1.910911|3600|0.040000|15019|224848|__MPEGTS Stream ID -0|mp2|unknown|audio|1/44100|[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 -1|mpeg2video|4|video|1/25|[2][0][0][0]|0x0002|352|288|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|N/A|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|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 +1|mpeg2video|4|video|[2][0][0][0]|0x0002|352|288|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 diff -Nru ffmpeg-4.2.2/tests/ref/fate/copy-psp ffmpeg-4.4/tests/ref/fate/copy-psp --- ffmpeg-4.2.2/tests/ref/fate/copy-psp 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/copy-psp 2020-07-11 10:39:30.000000000 +0000 @@ -1,4 +1,4 @@ -65a177552e03123c9a62ddb942970d05 *tests/data/fate/copy-psp.psp +8578401522773d0832f538ac915ad0b0 *tests/data/fate/copy-psp.psp 2041445 tests/data/fate/copy-psp.psp #extradata 0: 51, 0xaf6d1012 #extradata 1: 2, 0x00b200a1 diff -Nru ffmpeg-4.2.2/tests/ref/fate/copy-trac236 ffmpeg-4.4/tests/ref/fate/copy-trac236 --- ffmpeg-4.2.2/tests/ref/fate/copy-trac236 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/copy-trac236 2021-04-08 21:28:40.000000000 +0000 @@ -1,5 +1,5 @@ -959a4d78c6c11936e361fc3101a013eb *tests/data/fate/copy-trac236.mov -630860 tests/data/fate/copy-trac236.mov +34b0ad38518b0eb8464aff04e6d0e143 *tests/data/fate/copy-trac236.mov +630878 tests/data/fate/copy-trac236.mov #tb 0: 100/2997 #media_type 0: video #codec_id 0: rawvideo diff -Nru ffmpeg-4.2.2/tests/ref/fate/copy-trac3074 ffmpeg-4.4/tests/ref/fate/copy-trac3074 --- ffmpeg-4.2.2/tests/ref/fate/copy-trac3074 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/copy-trac3074 2021-04-08 21:28:40.000000000 +0000 @@ -1,5 +1,5 @@ -f92a201033712bda262f1e071e25544a *tests/data/fate/copy-trac3074.mp4 -333992 tests/data/fate/copy-trac3074.mp4 +da6122873fb83ce4340cf5d0ab8d475e *tests/data/fate/copy-trac3074.mp4 +334012 tests/data/fate/copy-trac3074.mp4 #tb 0: 1/48000 #media_type 0: audio #codec_id 0: eac3 diff -Nru ffmpeg-4.2.2/tests/ref/fate/copy-trac4914 ffmpeg-4.4/tests/ref/fate/copy-trac4914 --- ffmpeg-4.2.2/tests/ref/fate/copy-trac4914 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/copy-trac4914 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -b37c4d5693cdb5b9ed9b33501ffb682a *tests/data/fate/copy-trac4914.mxf +f5150fb82c1bb5a90906fce93dcc3f76 *tests/data/fate/copy-trac4914.mxf 561721 tests/data/fate/copy-trac4914.mxf #tb 0: 1001/30000 #media_type 0: video diff -Nru ffmpeg-4.2.2/tests/ref/fate/dpx-probe ffmpeg-4.4/tests/ref/fate/dpx-probe --- ffmpeg-4.2.2/tests/ref/fate/dpx-probe 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/dpx-probe 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,16 @@ +[FRAME] +sample_aspect_ratio=1:1 +color_range=pc +color_space=gbr +color_primaries=bt709 +color_transfer=unknown +TAG:timecode=00:00:01:18 +TAG:Creator=Apple Compressor +TAG:Input Device= +[SIDE_DATA] +side_data_type=SMPTE 12-1 timecode +[TIMECODE] +value=00:00:01:18 +[/TIMECODE] +[/SIDE_DATA] +[/FRAME] diff -Nru ffmpeg-4.2.2/tests/ref/fate/exif-image-embedded ffmpeg-4.4/tests/ref/fate/exif-image-embedded --- ffmpeg-4.2.2/tests/ref/fate/exif-image-embedded 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exif-image-embedded 2021-04-08 21:28:40.000000000 +0000 @@ -29,12 +29,6 @@ chroma_location=center TAG:UserComment=AppleMark -[SIDE_DATA] -side_data_type=QP table data -[/SIDE_DATA] -[SIDE_DATA] -side_data_type=QP table properties -[/SIDE_DATA] [/FRAME] [FRAME] media_type=audio @@ -44,8 +38,8 @@ pkt_pts_time=0.025057 pkt_dts=353600 pkt_dts_time=0.025057 -best_effort_timestamp=0 -best_effort_timestamp_time=0.000000 +best_effort_timestamp=353600 +best_effort_timestamp_time=0.025057 pkt_duration=15040 pkt_duration_time=0.001066 pkt_pos=16292 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exif-image-jpg ffmpeg-4.4/tests/ref/fate/exif-image-jpg --- ffmpeg-4.2.2/tests/ref/fate/exif-image-jpg 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exif-image-jpg 2021-04-08 21:28:40.000000000 +0000 @@ -229,10 +229,4 @@ TAG:WhiteBalance= 0 TAG:DigitalZoomRatio= 4000:4000 TAG:SceneCaptureType= 0 -[SIDE_DATA] -side_data_type=QP table data -[/SIDE_DATA] -[SIDE_DATA] -side_data_type=QP table properties -[/SIDE_DATA] [/FRAME] diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgba-multiscanline-half-b44 ffmpeg-4.4/tests/ref/fate/exr-rgba-multiscanline-half-b44 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgba-multiscanline-half-b44 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgba-multiscanline-half-b44 2021-04-08 21:28:40.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 935x251 #sar 0: 1/1 -0, 0, 0, 1, 1877480, 0x6f28b860 +0, 0, 0, 1, 3754960, 0x8d9af112 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44-12x8-l1 ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44-12x8-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44-12x8-l1 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44-12x8-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 9/10 -0, 0, 0, 1, 768, 0x1de5c7f1 +0, 0, 0, 1, 1536, 0xd5802c0c diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44-12x8-l2 ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44-12x8-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44-12x8-l2 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44-12x8-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 9/10 -0, 0, 0, 1, 768, 0xe08ca6d3 +0, 0, 0, 1, 1536, 0x0fca2ff9 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44-13x9-l1 ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44-13x9-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44-13x9-l1 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44-13x9-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 13x9 #sar 0: 9/10 -0, 0, 0, 1, 936, 0xdcb42186 +0, 0, 0, 1, 1872, 0xe9968f61 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44-13x9-l2 ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44-13x9-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44-13x9-l2 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44-13x9-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 13x9 #sar 0: 9/10 -0, 0, 0, 1, 936, 0x7f710bf5 +0, 0, 0, 1, 1872, 0xf99e750e diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44a-12x8-l1 ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44a-12x8-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44a-12x8-l1 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44a-12x8-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 9/10 -0, 0, 0, 1, 768, 0xe200c160 +0, 0, 0, 1, 1536, 0x4dec255f diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44a-12x8-l2 ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44a-12x8-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44a-12x8-l2 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44a-12x8-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 9/10 -0, 0, 0, 1, 768, 0xe08ca6d3 +0, 0, 0, 1, 1536, 0x0fca2ff9 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44a-13x9-l1 ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44a-13x9-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44a-13x9-l1 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44a-13x9-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 13x9 #sar 0: 9/10 -0, 0, 0, 1, 936, 0x911718ac +0, 0, 0, 1, 1872, 0x84b88e40 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44a-13x9-l2 ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44a-13x9-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgba-scanline-float-half-b44a-13x9-l2 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgba-scanline-float-half-b44a-13x9-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 13x9 #sar 0: 9/10 -0, 0, 0, 1, 936, 0x7f710bf5 +0, 0, 0, 1, 1872, 0xf99e750e diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgba-zip16-16x32-flag4 ffmpeg-4.4/tests/ref/fate/exr-rgba-zip16-16x32-flag4 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgba-zip16-16x32-flag4 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgba-zip16-16x32-flag4 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 16x32 #sar 0: 1/1 -0, 0, 0, 1, 4096, 0xf90ab1e9 +0, 0, 0, 1, 8192, 0x87767180 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-b44a-half-negative-4x4 ffmpeg-4.4/tests/ref/fate/exr-rgb-b44a-half-negative-4x4 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-b44a-half-negative-4x4 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-b44a-half-negative-4x4 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 4x4 #sar 0: 1/1 -0, 0, 0, 1, 96, 0x70600260 +0, 0, 0, 1, 192, 0x5b8e39c0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-b44-half-float-12x8-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-b44-half-float-12x8-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-b44-half-float-12x8-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-b44-half-float-12x8-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0xa1a70fac +0, 0, 0, 1, 1152, 0x577d5150 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-b44-half-float-12x8-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-b44-half-float-12x8-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-b44-half-float-12x8-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-b44-half-float-12x8-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0x22f77b1c +0, 0, 0, 1, 1536, 0xb8d48218 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-float-b44 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-float-b44 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-float-b44 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-float-b44 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x39c8e03e +0, 0, 0, 1, 1152, 0x18e0f4d9 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-float-piz-48x32 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-float-piz-48x32 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-float-piz-48x32 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-float-piz-48x32 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 48x32 #sar 0: 1/1 -0, 0, 0, 1, 9216, 0x5b3f7a8e +0, 0, 0, 1, 18432, 0x479e42a8 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-float-zip-dw-large ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-float-zip-dw-large --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-float-zip-dw-large 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-float-zip-dw-large 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 50x50 +#sar 0: 1/1 +0, 0, 0, 1, 30000, 0x947ce379 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-b44-12x8 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-b44-12x8 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-b44-12x8 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-b44-12x8 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x506469f9 +0, 0, 0, 1, 1152, 0xe84d5b9d diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-b44-13x9 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-b44-13x9 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-b44-13x9 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-b44-13x9 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 13x9 #sar 0: 1/1 -0, 0, 0, 1, 702, 0x6914838a +0, 0, 0, 1, 1404, 0x252cc156 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-piz-bw ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-piz-bw --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-piz-bw 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-piz-bw 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 34x27 #sar 0: 1/1 -0, 0, 0, 1, 5508, 0x36d15e2e +0, 0, 0, 1, 11016, 0x1644e1f9 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-piz-color ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-piz-color --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-piz-color 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-piz-color 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 34x40 #sar 0: 1/1 -0, 0, 0, 1, 8160, 0x9dd67b7d +0, 0, 0, 1, 16320, 0xc40939ad diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-piz-dw-large ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-piz-dw-large --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-piz-dw-large 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-piz-dw-large 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 50x50 +#sar 0: 1/1 +0, 0, 0, 1, 30000, 0xb329ee9c diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-piz-dw-t01 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-piz-dw-t01 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-piz-dw-t01 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-piz-dw-t01 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 400x300 #sar 0: 1/1 -0, 0, 0, 1, 720000, 0xe50fc9f8 +0, 0, 0, 1, 1440000, 0x4800b00b diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-piz-dw-t08 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-piz-dw-t08 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-piz-dw-t08 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-piz-dw-t08 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 501x401 #sar 0: 1/1 -0, 0, 0, 1, 1205406, 0xc45cc9f8 +0, 0, 0, 1, 2410812, 0x2dd1b00b diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-zip-dw-large ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-zip-dw-large --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-zip-dw-large 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-zip-dw-large 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 50x50 +#sar 0: 1/1 +0, 0, 0, 1, 30000, 0xb329ee9c diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-zip-dw-outside ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-zip-dw-outside --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-half-zip-dw-outside 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-half-zip-dw-outside 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 501x401 +#sar 0: 1/1 +0, 0, 0, 1, 2410812, 0x00000000 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-none-negative-red ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-none-negative-red --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-none-negative-red 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-none-negative-red 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 4x4 #sar 0: 1/1 -0, 0, 0, 1, 96, 0x27bc131b +0, 0, 0, 1, 192, 0xc87b5685 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-pxr24-float-12x8 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-pxr24-float-12x8 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-pxr24-float-12x8 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-pxr24-float-12x8 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x7120e072 +0, 0, 0, 1, 1152, 0x046e63d0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-pxr24-float-half-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-pxr24-float-half-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-pxr24-float-half-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-pxr24-float-half-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0xbd350af8 +0, 0, 0, 1, 1152, 0xd9575c2d diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-pxr24-float-half-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-pxr24-float-half-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-pxr24-float-half-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-pxr24-float-half-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0xadb27043 +0, 0, 0, 1, 1536, 0x04e1137d diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-pxr24-half-float-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-pxr24-half-float-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-pxr24-half-float-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-pxr24-half-float-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x5ede004c +0, 0, 0, 1, 1152, 0x8f8c4a81 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-pxr24-half-float-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-pxr24-half-float-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-pxr24-half-float-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-pxr24-half-float-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0x78317b56 +0, 0, 0, 1, 1536, 0x03fb2399 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-pxr24-half-uint32-13x9 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-pxr24-half-uint32-13x9 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-pxr24-half-uint32-13x9 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-pxr24-half-uint32-13x9 2021-04-08 21:28:40.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 13x9 #sar 0: 9/10 -0, 0, 0, 1, 702, 0xf0212f1d +0, 0, 0, 1, 702, 0x86132f10 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-raw-half-float-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-raw-half-float-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-raw-half-float-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-raw-half-float-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x5ede004c +0, 0, 0, 1, 1152, 0x8f8c4a81 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-raw-half-float-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-raw-half-float-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-raw-half-float-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-raw-half-float-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0x22f77b1c +0, 0, 0, 1, 1536, 0xb8d48218 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-rle-half-float-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-rle-half-float-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-rle-half-float-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-rle-half-float-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x5ede004c +0, 0, 0, 1, 1152, 0x8f8c4a81 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-rle-half-float-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-rle-half-float-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-rle-half-float-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-rle-half-float-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0x22f77b1c +0, 0, 0, 1, 1536, 0xb8d48218 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-uint32-piz-dw-large ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-uint32-piz-dw-large --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-uint32-piz-dw-large 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-uint32-piz-dw-large 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 50x50 +#sar 0: 1/1 +0, 0, 0, 1, 15000, 0xeeacd171 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-zip1-half-float-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-zip1-half-float-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-zip1-half-float-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-zip1-half-float-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x5ede004c +0, 0, 0, 1, 1152, 0x8f8c4a81 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-zip1-half-float-l1-zero-offsets ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-zip1-half-float-l1-zero-offsets --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-zip1-half-float-l1-zero-offsets 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-zip1-half-float-l1-zero-offsets 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x5ede004c +0, 0, 0, 1, 1152, 0x8f8c4a81 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-zip1-half-float-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-zip1-half-float-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-zip1-half-float-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-zip1-half-float-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0x22f77b1c +0, 0, 0, 1, 1536, 0xb8d48218 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-zip-half-0x0-0xFFFF ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-zip-half-0x0-0xFFFF --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-zip-half-0x0-0xFFFF 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-zip-half-0x0-0xFFFF 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 256x256 +#sar 0: 1/1 +0, 0, 0, 1, 786432, 0x1445e411 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-zip-half-float-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-zip-half-float-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-zip-half-float-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-zip-half-float-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x5ede004c +0, 0, 0, 1, 1152, 0x8f8c4a81 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-zip-half-float-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-zip-half-float-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-scanline-zip-half-float-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-scanline-zip-half-float-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0x22f77b1c +0, 0, 0, 1, 1536, 0xb8d48218 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-float-raw-12x8 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-float-raw-12x8 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-float-raw-12x8 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-float-raw-12x8 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x6b950ce3 +0, 0, 0, 1, 1152, 0xea4ae7b7 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-float-raw-150x130 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-float-raw-150x130 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-float-raw-150x130 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-float-raw-150x130 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 150x130 #sar 0: 1/1 -0, 0, 0, 1, 117000, 0xabc5eab2 +0, 0, 0, 1, 234000, 0xeb8582d5 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-half-float-b44-12x8-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-half-float-b44-12x8-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-half-float-b44-12x8-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-half-float-b44-12x8-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0xa1a70fac +0, 0, 0, 1, 1152, 0x577d5150 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-half-float-b44-12x8-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-half-float-b44-12x8-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-half-float-b44-12x8-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-half-float-b44-12x8-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0x22f77b1c +0, 0, 0, 1, 1536, 0xb8d48218 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-half-piz-dw-large ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-half-piz-dw-large --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-half-piz-dw-large 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-half-piz-dw-large 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 50x50 +#sar 0: 1/1 +0, 0, 0, 1, 30000, 0xb329ee9c diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-half-raw-12x8 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-half-raw-12x8 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-half-raw-12x8 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-half-raw-12x8 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x667903f5 +0, 0, 0, 1, 1152, 0xd3614640 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-half-zip ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-half-zip --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-half-zip 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-half-zip 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 501x401 +#sar 0: 1/1 +0, 0, 0, 1, 2410812, 0x2dd1b00b diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-half-zip-dw-outside ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-half-zip-dw-outside --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-half-zip-dw-outside 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-half-zip-dw-outside 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 501x401 +#sar 0: 1/1 +0, 0, 0, 1, 2410812, 0x00000000 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-pxr24-float-half-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-pxr24-float-half-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-pxr24-float-half-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-pxr24-float-half-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0xbd350af8 +0, 0, 0, 1, 1152, 0xd9575c2d diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-pxr24-float-half-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-pxr24-float-half-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-pxr24-float-half-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-pxr24-float-half-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0xadb27043 +0, 0, 0, 1, 1536, 0x04e1137d diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-pxr24-half-float-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-pxr24-half-float-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-pxr24-half-float-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-pxr24-half-float-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x5ede004c +0, 0, 0, 1, 1152, 0x8f8c4a81 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-pxr24-half-float-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-pxr24-half-float-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-pxr24-half-float-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-pxr24-half-float-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0x78317b56 +0, 0, 0, 1, 1536, 0x03fb2399 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-raw-half-float-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-raw-half-float-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-raw-half-float-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-raw-half-float-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x5ede004c +0, 0, 0, 1, 1152, 0x8f8c4a81 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-raw-half-float-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-raw-half-float-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-raw-half-float-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-raw-half-float-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0x22f77b1c +0, 0, 0, 1, 1536, 0xb8d48218 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-rle-half-float-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-rle-half-float-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-rle-half-float-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-rle-half-float-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x5ede004c +0, 0, 0, 1, 1152, 0x8f8c4a81 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-rle-half-float-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-rle-half-float-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-rle-half-float-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-rle-half-float-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0x22f77b1c +0, 0, 0, 1, 1536, 0xb8d48218 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-uint32-piz-dw-large ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-uint32-piz-dw-large --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-uint32-piz-dw-large 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-uint32-piz-dw-large 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 50x50 +#sar 0: 1/1 +0, 0, 0, 1, 15000, 0xeeacd171 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-zip1-half-float-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-zip1-half-float-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-zip1-half-float-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-zip1-half-float-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x5ede004c +0, 0, 0, 1, 1152, 0x8f8c4a81 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-zip1-half-float-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-zip1-half-float-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-zip1-half-float-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-zip1-half-float-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0x22f77b1c +0, 0, 0, 1, 1536, 0xb8d48218 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-zip-half-float-l1 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-zip-half-float-l1 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-zip-half-float-l1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-zip-half-float-l1 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 576, 0x5ede004c +0, 0, 0, 1, 1152, 0x8f8c4a81 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-zip-half-float-l2 ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-zip-half-float-l2 --- ffmpeg-4.2.2/tests/ref/fate/exr-rgb-tile-zip-half-float-l2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-rgb-tile-zip-half-float-l2 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 768, 0x22f77b1c +0, 0, 0, 1, 1536, 0xb8d48218 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-slice-pxr24 ffmpeg-4.4/tests/ref/fate/exr-slice-pxr24 --- ffmpeg-4.2.2/tests/ref/fate/exr-slice-pxr24 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-slice-pxr24 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 800x800 #sar 0: 1/1 -0, 0, 0, 1, 3840000, 0xdcfb341d +0, 0, 0, 1, 7680000, 0x98f60162 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-slice-raw ffmpeg-4.4/tests/ref/fate/exr-slice-raw --- ffmpeg-4.2.2/tests/ref/fate/exr-slice-raw 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-slice-raw 2021-04-08 21:28:40.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 587x675 #sar 0: 1/1 -0, 0, 0, 1, 3169800, 0x6a356d0d +0, 0, 0, 1, 6339600, 0xda3e31df diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-slice-rle ffmpeg-4.4/tests/ref/fate/exr-slice-rle --- ffmpeg-4.2.2/tests/ref/fate/exr-slice-rle 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-slice-rle 2021-04-08 21:28:40.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 587x675 #sar 0: 1/1 -0, 0, 0, 1, 3169800, 0x6a356d0d +0, 0, 0, 1, 6339600, 0xda3e31df diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-slice-zip1 ffmpeg-4.4/tests/ref/fate/exr-slice-zip1 --- ffmpeg-4.2.2/tests/ref/fate/exr-slice-zip1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-slice-zip1 2021-04-08 21:28:40.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 587x675 #sar 0: 1/1 -0, 0, 0, 1, 3169800, 0x6a356d0d +0, 0, 0, 1, 6339600, 0xda3e31df diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-slice-zip16 ffmpeg-4.4/tests/ref/fate/exr-slice-zip16 --- ffmpeg-4.2.2/tests/ref/fate/exr-slice-zip16 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-slice-zip16 2021-04-08 21:28:40.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 587x675 #sar 0: 1/1 -0, 0, 0, 1, 3169800, 0x6a356d0d +0, 0, 0, 1, 6339600, 0xda3e31df diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-ya-scanline-zip-half-12x8 ffmpeg-4.4/tests/ref/fate/exr-ya-scanline-zip-half-12x8 --- ffmpeg-4.2.2/tests/ref/fate/exr-ya-scanline-zip-half-12x8 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-ya-scanline-zip-half-12x8 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 12x8 +#sar 0: 1/1 +0, 0, 0, 1, 1536, 0x9473ee5c diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-y-scanline-zip-half-12x8 ffmpeg-4.4/tests/ref/fate/exr-y-scanline-zip-half-12x8 --- ffmpeg-4.2.2/tests/ref/fate/exr-y-scanline-zip-half-12x8 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-y-scanline-zip-half-12x8 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 192, 0xdd5759b5 +0, 0, 0, 1, 384, 0x911475c4 diff -Nru ffmpeg-4.2.2/tests/ref/fate/exr-y-tile-zip-half-12x8 ffmpeg-4.4/tests/ref/fate/exr-y-tile-zip-half-12x8 --- ffmpeg-4.2.2/tests/ref/fate/exr-y-tile-zip-half-12x8 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/exr-y-tile-zip-half-12x8 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 12x8 #sar 0: 1/1 -0, 0, 0, 1, 192, 0xdd5759b5 +0, 0, 0, 1, 384, 0x911475c4 diff -Nru ffmpeg-4.2.2/tests/ref/fate/ffmpeg-attached_pics ffmpeg-4.4/tests/ref/fate/ffmpeg-attached_pics --- ffmpeg-4.2.2/tests/ref/fate/ffmpeg-attached_pics 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/ffmpeg-attached_pics 2021-04-08 21:28:40.000000000 +0000 @@ -9,7 +9,7 @@ #sample_rate 1: 44100 #channel_layout 1: 3 #channel_layout_name 1: stereo -0, 0, 0, 0, 120000, 0x748cc771 +0, 0, 0, 1, 120000, 0x748cc771 1, 0, 0, 4096, 16384, 0x00000000 1, 4096, 4096, 4096, 16384, 0x29cd639d 1, 8192, 8192, 4096, 16384, 0xd52066e5 diff -Nru ffmpeg-4.2.2/tests/ref/fate/ffmpeg-filter_colorkey ffmpeg-4.4/tests/ref/fate/ffmpeg-filter_colorkey --- ffmpeg-4.2.2/tests/ref/fate/ffmpeg-filter_colorkey 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/ffmpeg-filter_colorkey 2020-07-11 10:39:30.000000000 +0000 @@ -3,13 +3,13 @@ #codec_id 0: rawvideo #dimensions 0: 720x576 #sar 0: 0/1 -0, 0, 0, 1, 622080, 0x4e30accb -0, 1, 1, 1, 622080, 0x7d941c14 -0, 2, 2, 1, 622080, 0xf7451c5b -0, 3, 3, 1, 622080, 0xb2c74319 -0, 4, 4, 1, 622080, 0xc9b80b79 -0, 5, 5, 1, 622080, 0x92ce1194 -0, 6, 6, 1, 622080, 0x43ae99ac -0, 7, 7, 1, 622080, 0x4ec3a554 -0, 8, 8, 1, 622080, 0x3200250c -0, 9, 9, 1, 622080, 0x94ebb3f3 +0, 0, 0, 1, 622080, 0x5775bb12 +0, 1, 1, 1, 622080, 0x84d8395a +0, 2, 2, 1, 622080, 0x599d3a6b +0, 3, 3, 1, 622080, 0x1df1e9dc +0, 4, 4, 1, 622080, 0xf3255836 +0, 5, 5, 1, 622080, 0xf46bc26e +0, 6, 6, 1, 622080, 0x76d491da +0, 7, 7, 1, 622080, 0x2c9f3ca6 +0, 8, 8, 1, 622080, 0x5713e203 +0, 9, 9, 1, 622080, 0x47776493 diff -Nru ffmpeg-4.2.2/tests/ref/fate/ffmpeg-streamloop ffmpeg-4.4/tests/ref/fate/ffmpeg-streamloop --- ffmpeg-4.2.2/tests/ref/fate/ffmpeg-streamloop 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/ffmpeg-streamloop 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,85 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#extradata 0, 42, eb4ec433b0b59dcc24620891ef779635 +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: h264 +#dimensions 0: 320x240 +#sar 0: 1/1 +#stream#, dts, pts, duration, size, hash +0, -80, 0, 40, 5131, fb6a475e53addc2ffa79e1b75de81050 +0, -40, 160, 40, 2479, fc64a1f7054d22741fffc68891ff4887 +0, 0, 80, 40, 1354, 344ee1f5e8f0fe2785639dd530cf85ca +0, 40, 40, 40, 965, cbea2691414063d4e1199b781586cac4 +0, 80, 120, 40, 1031, 69245957d44a7a9211e5d6fe872dec52 +0, 120, 320, 40, 2165, 6ddd38bbf1c85be10e1b17d5578b26f5 +0, 160, 240, 40, 1214, 981b555d6f810dc6b3faa4efb6beebaf +0, 200, 200, 40, 942, 492ec5f73a56fcffff81ad1ec800dc53 +0, 240, 280, 40, 945, 1763cb0f5f1d4a054d54803715de83b3 +0, 280, 480, 40, 2026, 7a208cad2e04578047482a8874ba567a +0, 320, 400, 40, 1275, a29002e40743ccdddd66f47e3b98e276 +0, 360, 360, 40, 851, c764eb2d5cb752cd607e81b69f78b799 +0, 400, 440, 40, 897, a01da8a716eae006ea6b24d8acb89fd7 +0, 440, 640, 40, 1764, 18ddd7bae5732b44fdef045f21e90f46 +0, 480, 560, 40, 1328, 7f42357fdc0df07ba22c1f803baa6fdc +0, 520, 520, 40, 952, 83827ebe12f9104a72627b52170ff9e5 +0, 560, 600, 40, 1003, 41f8be66b69231439540e4cf0b07558c +0, 600, 800, 40, 1839, 929c25e4201d66c471482d090db24b5b +0, 640, 720, 40, 1133, bdc6f506ac07ff78cc33f33956de6efb +0, 680, 680, 40, 984, 5264d530093275ade55efc816dea5c7e +0, 720, 760, 40, 802, fd5f7a018a8c940d5978b36e2e6e9801 +0, 760, 960, 40, 1454, 4eac58bac2b54a8fcdaaaf16e7167917 +0, 800, 880, 40, 1269, 79632bd3f7325797f34874621f3a6dd3 +0, 840, 840, 40, 1013, 8a48271049e24a9a86fa48300bc75d34 +0, 880, 920, 40, 981, 759407123505076c31688ec8740d2db9 +0, 920, 1000, 40, 5131, fb6a475e53addc2ffa79e1b75de81050 +0, 960, 1160, 40, 2479, fc64a1f7054d22741fffc68891ff4887 +0, 1000, 1080, 40, 1354, 344ee1f5e8f0fe2785639dd530cf85ca +0, 1040, 1040, 40, 965, cbea2691414063d4e1199b781586cac4 +0, 1080, 1120, 40, 1031, 69245957d44a7a9211e5d6fe872dec52 +0, 1120, 1320, 40, 2165, 6ddd38bbf1c85be10e1b17d5578b26f5 +0, 1160, 1240, 40, 1214, 981b555d6f810dc6b3faa4efb6beebaf +0, 1200, 1200, 40, 942, 492ec5f73a56fcffff81ad1ec800dc53 +0, 1240, 1280, 40, 945, 1763cb0f5f1d4a054d54803715de83b3 +0, 1280, 1480, 40, 2026, 7a208cad2e04578047482a8874ba567a +0, 1320, 1400, 40, 1275, a29002e40743ccdddd66f47e3b98e276 +0, 1360, 1360, 40, 851, c764eb2d5cb752cd607e81b69f78b799 +0, 1400, 1440, 40, 897, a01da8a716eae006ea6b24d8acb89fd7 +0, 1440, 1640, 40, 1764, 18ddd7bae5732b44fdef045f21e90f46 +0, 1480, 1560, 40, 1328, 7f42357fdc0df07ba22c1f803baa6fdc +0, 1520, 1520, 40, 952, 83827ebe12f9104a72627b52170ff9e5 +0, 1560, 1600, 40, 1003, 41f8be66b69231439540e4cf0b07558c +0, 1600, 1800, 40, 1839, 929c25e4201d66c471482d090db24b5b +0, 1640, 1720, 40, 1133, bdc6f506ac07ff78cc33f33956de6efb +0, 1680, 1680, 40, 984, 5264d530093275ade55efc816dea5c7e +0, 1720, 1760, 40, 802, fd5f7a018a8c940d5978b36e2e6e9801 +0, 1760, 1960, 40, 1454, 4eac58bac2b54a8fcdaaaf16e7167917 +0, 1800, 1880, 40, 1269, 79632bd3f7325797f34874621f3a6dd3 +0, 1840, 1840, 40, 1013, 8a48271049e24a9a86fa48300bc75d34 +0, 1880, 1920, 40, 981, 759407123505076c31688ec8740d2db9 +0, 1920, 2000, 40, 5131, fb6a475e53addc2ffa79e1b75de81050 +0, 1960, 2160, 40, 2479, fc64a1f7054d22741fffc68891ff4887 +0, 2000, 2080, 40, 1354, 344ee1f5e8f0fe2785639dd530cf85ca +0, 2040, 2040, 40, 965, cbea2691414063d4e1199b781586cac4 +0, 2080, 2120, 40, 1031, 69245957d44a7a9211e5d6fe872dec52 +0, 2120, 2320, 40, 2165, 6ddd38bbf1c85be10e1b17d5578b26f5 +0, 2160, 2240, 40, 1214, 981b555d6f810dc6b3faa4efb6beebaf +0, 2200, 2200, 40, 942, 492ec5f73a56fcffff81ad1ec800dc53 +0, 2240, 2280, 40, 945, 1763cb0f5f1d4a054d54803715de83b3 +0, 2280, 2480, 40, 2026, 7a208cad2e04578047482a8874ba567a +0, 2320, 2400, 40, 1275, a29002e40743ccdddd66f47e3b98e276 +0, 2360, 2360, 40, 851, c764eb2d5cb752cd607e81b69f78b799 +0, 2400, 2440, 40, 897, a01da8a716eae006ea6b24d8acb89fd7 +0, 2440, 2640, 40, 1764, 18ddd7bae5732b44fdef045f21e90f46 +0, 2480, 2560, 40, 1328, 7f42357fdc0df07ba22c1f803baa6fdc +0, 2520, 2520, 40, 952, 83827ebe12f9104a72627b52170ff9e5 +0, 2560, 2600, 40, 1003, 41f8be66b69231439540e4cf0b07558c +0, 2600, 2800, 40, 1839, 929c25e4201d66c471482d090db24b5b +0, 2640, 2720, 40, 1133, bdc6f506ac07ff78cc33f33956de6efb +0, 2680, 2680, 40, 984, 5264d530093275ade55efc816dea5c7e +0, 2720, 2760, 40, 802, fd5f7a018a8c940d5978b36e2e6e9801 +0, 2760, 2960, 40, 1454, 4eac58bac2b54a8fcdaaaf16e7167917 +0, 2800, 2880, 40, 1269, 79632bd3f7325797f34874621f3a6dd3 +0, 2840, 2840, 40, 1013, 8a48271049e24a9a86fa48300bc75d34 +0, 2880, 2920, 40, 981, 759407123505076c31688ec8740d2db9 diff -Nru ffmpeg-4.2.2/tests/ref/fate/ffprobe_compact ffmpeg-4.4/tests/ref/fate/ffprobe_compact --- ffmpeg-4.2.2/tests/ref/fate/ffprobe_compact 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/ffprobe_compact 2021-04-08 21:28:40.000000000 +0000 @@ -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|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=647|flags=K_ +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|pkt_pts=0|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=2722|flags=K_ +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|pkt_pts=0|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=233143|flags=K_ +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|pkt_pts=0|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=263148|flags=K_ +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|pkt_pts=1024|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=265226|flags=K_ +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|pkt_pts=2048|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=495650|flags=K_ +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|pkt_pts=2048|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=525655|flags=K_ +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|pkt_pts=2048|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=527726|flags=K_ +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|pkt_pts=3072|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=529804|flags=K_ +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|pkt_pts=4096|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=760228|flags=K_ +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|pkt_pts=4096|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=790233|flags=K_ +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|pkt_pts=4096|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=786|pos=792304|flags=K_ +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|pkt_pts=5120|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=793120|flags=K_ +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|pkt_pts=6144|pkt_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|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=1023544|flags=K_ +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|pkt_pts=6144|pkt_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 -stream|index=0|codec_name=pcm_s16le|profile=unknown|codec_type=audio|codec_time_base=1/44100|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|tag:E=mc²|tag:encoder=Lavc pcm_s16le -stream|index=1|codec_name=rawvideo|profile=unknown|codec_type=video|codec_time_base=1/25|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=320|height=240|coded_width=320|coded_height=240|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|timecode=N/A|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|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_time_base=1/25|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=100|height=100|coded_width=100|coded_height=100|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|timecode=N/A|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|tag:encoder=Lavc rawvideo +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|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|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|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|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|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€ diff -Nru ffmpeg-4.2.2/tests/ref/fate/ffprobe_csv ffmpeg-4.4/tests/ref/fate/ffprobe_csv --- ffmpeg-4.2.2/tests/ref/fate/ffprobe_csv 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/ffprobe_csv 2021-04-08 21:28:40.000000000 +0000 @@ -1,32 +1,32 @@ -packet,audio,0,0,0.000000,0,0.000000,1024,0.023220,N/A,N/A,2048,647,K_ +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,N/A,N/A,230400,2722,K_ +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,N/A,N/A,30000,233143,K_ +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,N/A,N/A,2048,263148,K_ +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,N/A,N/A,230400,265226,K_ +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,N/A,N/A,30000,495650,K_ +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,N/A,N/A,2048,525655,K_ +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,N/A,N/A,2048,527726,K_ +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,N/A,N/A,230400,529804,K_ +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,N/A,N/A,30000,760228,K_ +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,N/A,N/A,2048,790233,K_ +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,N/A,N/A,786,792304,K_ +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,N/A,N/A,230400,793120,K_ +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,N/A,N/A,30000,1023544,K_ +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 -stream,0,pcm_s16le,unknown,audio,1/44100,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,mc²,Lavc pcm_s16le -stream,1,rawvideo,unknown,video,1/25,RGB[24],0x18424752,320,240,320,240,0,1:1,4:3,rgb24,-99,unknown,unknown,unknown,unknown,unspecified,unknown,N/A,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,foobar,field-and-tags-conflict-attempt,Lavc rawvideo -stream,2,rawvideo,unknown,video,1/25,RGB[24],0x18424752,100,100,100,100,0,1:1,1:1,rgb24,-99,unknown,unknown,unknown,unknown,unspecified,unknown,N/A,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,Lavc rawvideo +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,mc²,Lavc pcm_s16le +stream,1,rawvideo,unknown,video,RGB[24],0x18424752,320,240,320,240,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,foobar,field-and-tags-conflict-attempt,Lavc rawvideo +stream,2,rawvideo,unknown,video,RGB[24],0x18424752,100,100,100,100,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,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€ diff -Nru ffmpeg-4.2.2/tests/ref/fate/ffprobe_default ffmpeg-4.4/tests/ref/fate/ffprobe_default --- ffmpeg-4.2.2/tests/ref/fate/ffprobe_default 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/ffprobe_default 2021-04-08 21:28:40.000000000 +0000 @@ -7,8 +7,6 @@ dts_time=0.000000 duration=1024 duration_time=0.023220 -convergence_duration=N/A -convergence_duration_time=N/A size=2048 pos=647 flags=K_ @@ -41,8 +39,6 @@ dts_time=0.000000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=230400 pos=2722 flags=K_ @@ -86,8 +82,6 @@ dts_time=0.000000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=30000 pos=233143 flags=K_ @@ -131,8 +125,6 @@ dts_time=0.023220 duration=1024 duration_time=0.023220 -convergence_duration=N/A -convergence_duration_time=N/A size=2048 pos=263148 flags=K_ @@ -165,8 +157,6 @@ dts_time=0.040000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=230400 pos=265226 flags=K_ @@ -210,8 +200,6 @@ dts_time=0.040000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=30000 pos=495650 flags=K_ @@ -255,8 +243,6 @@ dts_time=0.046440 duration=1024 duration_time=0.023220 -convergence_duration=N/A -convergence_duration_time=N/A size=2048 pos=525655 flags=K_ @@ -289,8 +275,6 @@ dts_time=0.069660 duration=1024 duration_time=0.023220 -convergence_duration=N/A -convergence_duration_time=N/A size=2048 pos=527726 flags=K_ @@ -323,8 +307,6 @@ dts_time=0.080000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=230400 pos=529804 flags=K_ @@ -368,8 +350,6 @@ dts_time=0.080000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=30000 pos=760228 flags=K_ @@ -413,8 +393,6 @@ dts_time=0.092880 duration=1024 duration_time=0.023220 -convergence_duration=N/A -convergence_duration_time=N/A size=2048 pos=790233 flags=K_ @@ -447,8 +425,6 @@ dts_time=0.116100 duration=393 duration_time=0.008912 -convergence_duration=N/A -convergence_duration_time=N/A size=786 pos=792304 flags=K_ @@ -481,8 +457,6 @@ dts_time=0.120000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=230400 pos=793120 flags=K_ @@ -526,8 +500,6 @@ dts_time=0.120000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=30000 pos=1023544 flags=K_ @@ -567,7 +539,6 @@ codec_name=pcm_s16le profile=unknown codec_type=audio -codec_time_base=1/44100 codec_tag_string=PSD[16] codec_tag=0x10445350 sample_fmt=s16 @@ -609,13 +580,13 @@ codec_name=rawvideo profile=unknown codec_type=video -codec_time_base=1/25 codec_tag_string=RGB[24] codec_tag=0x18424752 width=320 height=240 coded_width=320 coded_height=240 +closed_captions=0 has_b_frames=0 sample_aspect_ratio=1:1 display_aspect_ratio=4:3 @@ -627,7 +598,6 @@ color_primaries=unknown chroma_location=unspecified field_order=unknown -timecode=N/A refs=1 id=N/A r_frame_rate=25/1 @@ -664,13 +634,13 @@ codec_name=rawvideo profile=unknown codec_type=video -codec_time_base=1/25 codec_tag_string=RGB[24] codec_tag=0x18424752 width=100 height=100 coded_width=100 coded_height=100 +closed_captions=0 has_b_frames=0 sample_aspect_ratio=1:1 display_aspect_ratio=1:1 @@ -682,7 +652,6 @@ color_primaries=unknown chroma_location=unspecified field_order=unknown -timecode=N/A refs=1 id=N/A r_frame_rate=25/1 diff -Nru ffmpeg-4.2.2/tests/ref/fate/ffprobe_flat ffmpeg-4.4/tests/ref/fate/ffprobe_flat --- ffmpeg-4.2.2/tests/ref/fate/ffprobe_flat 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/ffprobe_flat 2021-04-08 21:28:40.000000000 +0000 @@ -6,8 +6,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.0.convergence_duration_time="N/A" packets_and_frames.packet.0.size="2048" packets_and_frames.packet.0.pos="647" packets_and_frames.packet.0.flags="K_" @@ -36,8 +34,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.1.convergence_duration_time="N/A" packets_and_frames.packet.1.size="230400" packets_and_frames.packet.1.pos="2722" packets_and_frames.packet.1.flags="K_" @@ -77,8 +73,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.2.convergence_duration_time="N/A" packets_and_frames.packet.2.size="30000" packets_and_frames.packet.2.pos="233143" packets_and_frames.packet.2.flags="K_" @@ -118,8 +112,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.3.convergence_duration_time="N/A" packets_and_frames.packet.3.size="2048" packets_and_frames.packet.3.pos="263148" packets_and_frames.packet.3.flags="K_" @@ -148,8 +140,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.4.convergence_duration_time="N/A" packets_and_frames.packet.4.size="230400" packets_and_frames.packet.4.pos="265226" packets_and_frames.packet.4.flags="K_" @@ -189,8 +179,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.5.convergence_duration_time="N/A" packets_and_frames.packet.5.size="30000" packets_and_frames.packet.5.pos="495650" packets_and_frames.packet.5.flags="K_" @@ -230,8 +218,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.6.convergence_duration_time="N/A" packets_and_frames.packet.6.size="2048" packets_and_frames.packet.6.pos="525655" packets_and_frames.packet.6.flags="K_" @@ -260,8 +246,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.7.convergence_duration_time="N/A" packets_and_frames.packet.7.size="2048" packets_and_frames.packet.7.pos="527726" packets_and_frames.packet.7.flags="K_" @@ -290,8 +274,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.8.convergence_duration_time="N/A" packets_and_frames.packet.8.size="230400" packets_and_frames.packet.8.pos="529804" packets_and_frames.packet.8.flags="K_" @@ -331,8 +313,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.9.convergence_duration_time="N/A" packets_and_frames.packet.9.size="30000" packets_and_frames.packet.9.pos="760228" packets_and_frames.packet.9.flags="K_" @@ -372,8 +352,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.10.convergence_duration_time="N/A" packets_and_frames.packet.10.size="2048" packets_and_frames.packet.10.pos="790233" packets_and_frames.packet.10.flags="K_" @@ -402,8 +380,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.11.convergence_duration_time="N/A" packets_and_frames.packet.11.size="786" packets_and_frames.packet.11.pos="792304" packets_and_frames.packet.11.flags="K_" @@ -432,8 +408,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.12.convergence_duration_time="N/A" packets_and_frames.packet.12.size="230400" packets_and_frames.packet.12.pos="793120" packets_and_frames.packet.12.flags="K_" @@ -473,8 +447,6 @@ 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.convergence_duration="N/A" -packets_and_frames.packet.13.convergence_duration_time="N/A" packets_and_frames.packet.13.size="30000" packets_and_frames.packet.13.pos="1023544" packets_and_frames.packet.13.flags="K_" @@ -510,7 +482,6 @@ streams.stream.0.codec_name="pcm_s16le" streams.stream.0.profile="unknown" streams.stream.0.codec_type="audio" -streams.stream.0.codec_time_base="1/44100" streams.stream.0.codec_tag_string="PSD[16]" streams.stream.0.codec_tag="0x10445350" streams.stream.0.sample_fmt="s16" @@ -550,13 +521,13 @@ streams.stream.1.codec_name="rawvideo" streams.stream.1.profile="unknown" streams.stream.1.codec_type="video" -streams.stream.1.codec_time_base="1/25" streams.stream.1.codec_tag_string="RGB[24]" streams.stream.1.codec_tag="0x18424752" streams.stream.1.width=320 streams.stream.1.height=240 streams.stream.1.coded_width=320 streams.stream.1.coded_height=240 +streams.stream.1.closed_captions=0 streams.stream.1.has_b_frames=0 streams.stream.1.sample_aspect_ratio="1:1" streams.stream.1.display_aspect_ratio="4:3" @@ -568,7 +539,6 @@ streams.stream.1.color_primaries="unknown" streams.stream.1.chroma_location="unspecified" streams.stream.1.field_order="unknown" -streams.stream.1.timecode="N/A" streams.stream.1.refs=1 streams.stream.1.id="N/A" streams.stream.1.r_frame_rate="25/1" @@ -603,13 +573,13 @@ streams.stream.2.codec_name="rawvideo" streams.stream.2.profile="unknown" streams.stream.2.codec_type="video" -streams.stream.2.codec_time_base="1/25" streams.stream.2.codec_tag_string="RGB[24]" streams.stream.2.codec_tag="0x18424752" streams.stream.2.width=100 streams.stream.2.height=100 streams.stream.2.coded_width=100 streams.stream.2.coded_height=100 +streams.stream.2.closed_captions=0 streams.stream.2.has_b_frames=0 streams.stream.2.sample_aspect_ratio="1:1" streams.stream.2.display_aspect_ratio="1:1" @@ -621,7 +591,6 @@ streams.stream.2.color_primaries="unknown" streams.stream.2.chroma_location="unspecified" streams.stream.2.field_order="unknown" -streams.stream.2.timecode="N/A" streams.stream.2.refs=1 streams.stream.2.id="N/A" streams.stream.2.r_frame_rate="25/1" diff -Nru ffmpeg-4.2.2/tests/ref/fate/ffprobe_ini ffmpeg-4.4/tests/ref/fate/ffprobe_ini --- ffmpeg-4.2.2/tests/ref/fate/ffprobe_ini 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/ffprobe_ini 2021-04-08 21:28:40.000000000 +0000 @@ -9,8 +9,6 @@ dts_time=0.000000 duration=1024 duration_time=0.023220 -convergence_duration=N/A -convergence_duration_time=N/A size=2048 pos=647 flags=K_ @@ -43,8 +41,6 @@ dts_time=0.000000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=230400 pos=2722 flags=K_ @@ -88,8 +84,6 @@ dts_time=0.000000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=30000 pos=233143 flags=K_ @@ -133,8 +127,6 @@ dts_time=0.023220 duration=1024 duration_time=0.023220 -convergence_duration=N/A -convergence_duration_time=N/A size=2048 pos=263148 flags=K_ @@ -167,8 +159,6 @@ dts_time=0.040000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=230400 pos=265226 flags=K_ @@ -212,8 +202,6 @@ dts_time=0.040000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=30000 pos=495650 flags=K_ @@ -257,8 +245,6 @@ dts_time=0.046440 duration=1024 duration_time=0.023220 -convergence_duration=N/A -convergence_duration_time=N/A size=2048 pos=525655 flags=K_ @@ -291,8 +277,6 @@ dts_time=0.069660 duration=1024 duration_time=0.023220 -convergence_duration=N/A -convergence_duration_time=N/A size=2048 pos=527726 flags=K_ @@ -325,8 +309,6 @@ dts_time=0.080000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=230400 pos=529804 flags=K_ @@ -370,8 +352,6 @@ dts_time=0.080000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=30000 pos=760228 flags=K_ @@ -415,8 +395,6 @@ dts_time=0.092880 duration=1024 duration_time=0.023220 -convergence_duration=N/A -convergence_duration_time=N/A size=2048 pos=790233 flags=K_ @@ -449,8 +427,6 @@ dts_time=0.116100 duration=393 duration_time=0.008912 -convergence_duration=N/A -convergence_duration_time=N/A size=786 pos=792304 flags=K_ @@ -483,8 +459,6 @@ dts_time=0.120000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=230400 pos=793120 flags=K_ @@ -528,8 +502,6 @@ dts_time=0.120000 duration=2048 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=30000 pos=1023544 flags=K_ @@ -569,7 +541,6 @@ codec_name=pcm_s16le profile=unknown codec_type=audio -codec_time_base=1/44100 codec_tag_string=PSD[16] codec_tag=0x10445350 sample_fmt=s16 @@ -615,13 +586,13 @@ codec_name=rawvideo profile=unknown codec_type=video -codec_time_base=1/25 codec_tag_string=RGB[24] codec_tag=0x18424752 width=320 height=240 coded_width=320 coded_height=240 +closed_captions=0 has_b_frames=0 sample_aspect_ratio=1\:1 display_aspect_ratio=4\:3 @@ -633,7 +604,6 @@ color_primaries=unknown chroma_location=unspecified field_order=unknown -timecode=N/A refs=1 id=N/A r_frame_rate=25/1 @@ -674,13 +644,13 @@ codec_name=rawvideo profile=unknown codec_type=video -codec_time_base=1/25 codec_tag_string=RGB[24] codec_tag=0x18424752 width=100 height=100 coded_width=100 coded_height=100 +closed_captions=0 has_b_frames=0 sample_aspect_ratio=1\:1 display_aspect_ratio=1\:1 @@ -692,7 +662,6 @@ color_primaries=unknown chroma_location=unspecified field_order=unknown -timecode=N/A refs=1 id=N/A r_frame_rate=25/1 diff -Nru ffmpeg-4.2.2/tests/ref/fate/ffprobe_json ffmpeg-4.4/tests/ref/fate/ffprobe_json --- ffmpeg-4.2.2/tests/ref/fate/ffprobe_json 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/ffprobe_json 2021-04-08 21:28:40.000000000 +0000 @@ -524,7 +524,6 @@ "index": 0, "codec_name": "pcm_s16le", "codec_type": "audio", - "codec_time_base": "1/44100", "codec_tag_string": "PSD[16]", "codec_tag": "0x10445350", "sample_fmt": "s16", @@ -562,13 +561,13 @@ "index": 1, "codec_name": "rawvideo", "codec_type": "video", - "codec_time_base": "1/25", "codec_tag_string": "RGB[24]", "codec_tag": "0x18424752", "width": 320, "height": 240, "coded_width": 320, "coded_height": 240, + "closed_captions": 0, "has_b_frames": 0, "sample_aspect_ratio": "1:1", "display_aspect_ratio": "4:3", @@ -606,13 +605,13 @@ "index": 2, "codec_name": "rawvideo", "codec_type": "video", - "codec_time_base": "1/25", "codec_tag_string": "RGB[24]", "codec_tag": "0x18424752", "width": 100, "height": 100, "coded_width": 100, "coded_height": 100, + "closed_captions": 0, "has_b_frames": 0, "sample_aspect_ratio": "1:1", "display_aspect_ratio": "1:1", diff -Nru ffmpeg-4.2.2/tests/ref/fate/ffprobe_xml ffmpeg-4.4/tests/ref/fate/ffprobe_xml --- ffmpeg-4.2.2/tests/ref/fate/ffprobe_xml 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/ffprobe_xml 2021-04-08 21:28:40.000000000 +0000 @@ -32,18 +32,18 @@ - + - + - + @@ -51,7 +51,7 @@ - + diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-codecview ffmpeg-4.4/tests/ref/fate/filter-codecview --- ffmpeg-4.2.2/tests/ref/fate/filter-codecview 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-codecview 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,10 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 1/1 +0, 1, 1, 1, 152064, 0x69a58723 +0, 2, 2, 1, 152064, 0xb42d52c3 +0, 3, 3, 1, 152064, 0x9376ce65 +0, 4, 4, 1, 152064, 0x796543f9 +0, 5, 5, 1, 152064, 0x5027b118 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-colorbalance ffmpeg-4.4/tests/ref/fate/filter-colorbalance --- ffmpeg-4.2.2/tests/ref/fate/filter-colorbalance 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-colorbalance 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,8 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 304128, 0xf68fadfd +0, 1, 1, 1, 304128, 0xa6302d9a +0, 2, 2, 1, 304128, 0x758d165a diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-colorbalance-gbrap ffmpeg-4.4/tests/ref/fate/filter-colorbalance-gbrap --- ffmpeg-4.2.2/tests/ref/fate/filter-colorbalance-gbrap 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-colorbalance-gbrap 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,8 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 405504, 0xdcc71df0 +0, 1, 1, 1, 405504, 0x48d56675 +0, 2, 2, 1, 405504, 0x68058bf0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-colorbalance-gbrap-16 ffmpeg-4.4/tests/ref/fate/filter-colorbalance-gbrap-16 --- ffmpeg-4.2.2/tests/ref/fate/filter-colorbalance-gbrap-16 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-colorbalance-gbrap-16 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,8 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 405504, 0xa497ca1b +0, 1, 1, 1, 405504, 0x92c24b0e +0, 2, 2, 1, 405504, 0x965270bd diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-colorbalance-rgba64 ffmpeg-4.4/tests/ref/fate/filter-colorbalance-rgba64 --- ffmpeg-4.2.2/tests/ref/fate/filter-colorbalance-rgba64 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-colorbalance-rgba64 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,8 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 811008, 0xc5f7e6ba +0, 1, 1, 1, 811008, 0x266955bf +0, 2, 2, 1, 811008, 0x55360c6e diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-colorlevels ffmpeg-4.4/tests/ref/fate/filter-colorlevels --- ffmpeg-4.2.2/tests/ref/fate/filter-colorlevels 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-colorlevels 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,55 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 304128, 0x348bb7a0 +0, 1, 1, 1, 304128, 0xaf9634d7 +0, 2, 2, 1, 304128, 0x81161fd3 +0, 3, 3, 1, 304128, 0x6839b383 +0, 4, 4, 1, 304128, 0xa55299b8 +0, 5, 5, 1, 304128, 0x66fb65b3 +0, 6, 6, 1, 304128, 0xe6be2a99 +0, 7, 7, 1, 304128, 0xfb33cb55 +0, 8, 8, 1, 304128, 0x51ab3d74 +0, 9, 9, 1, 304128, 0x67dc44ee +0, 10, 10, 1, 304128, 0x2eac3b50 +0, 11, 11, 1, 304128, 0xd4a4c377 +0, 12, 12, 1, 304128, 0x1eefe29c +0, 13, 13, 1, 304128, 0x3a84d488 +0, 14, 14, 1, 304128, 0x70d3b165 +0, 15, 15, 1, 304128, 0x578e58d4 +0, 16, 16, 1, 304128, 0x08bba87e +0, 17, 17, 1, 304128, 0xccc86c47 +0, 18, 18, 1, 304128, 0x70bf9aa2 +0, 19, 19, 1, 304128, 0x3fc3d5b5 +0, 20, 20, 1, 304128, 0xef52590b +0, 21, 21, 1, 304128, 0x4f7adde0 +0, 22, 22, 1, 304128, 0xc076ef54 +0, 23, 23, 1, 304128, 0xed2bba2d +0, 24, 24, 1, 304128, 0x6fce6367 +0, 25, 25, 1, 304128, 0x71fe3c07 +0, 26, 26, 1, 304128, 0x6395fc7c +0, 27, 27, 1, 304128, 0xa800ea2c +0, 28, 28, 1, 304128, 0x758dfa57 +0, 29, 29, 1, 304128, 0x7fbba7c6 +0, 30, 30, 1, 304128, 0x2842e2a7 +0, 31, 31, 1, 304128, 0xafc2787c +0, 32, 32, 1, 304128, 0x01e9a76b +0, 33, 33, 1, 304128, 0x32a2377b +0, 34, 34, 1, 304128, 0x10e0af2f +0, 35, 35, 1, 304128, 0x8ab789ca +0, 36, 36, 1, 304128, 0x3a3a5c1d +0, 37, 37, 1, 304128, 0xeecb3f50 +0, 38, 38, 1, 304128, 0x317f8a3f +0, 39, 39, 1, 304128, 0x0b90ba72 +0, 40, 40, 1, 304128, 0x1d6a509e +0, 41, 41, 1, 304128, 0x11416b22 +0, 42, 42, 1, 304128, 0x325014ed +0, 43, 43, 1, 304128, 0xb36a830c +0, 44, 44, 1, 304128, 0xf67fd957 +0, 45, 45, 1, 304128, 0x091ad040 +0, 46, 46, 1, 304128, 0xd6b4b00e +0, 47, 47, 1, 304128, 0x440b3f2a +0, 48, 48, 1, 304128, 0x7c329040 +0, 49, 49, 1, 304128, 0xf6619a69 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-colorlevels-16 ffmpeg-4.4/tests/ref/fate/filter-colorlevels-16 --- ffmpeg-4.2.2/tests/ref/fate/filter-colorlevels-16 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-colorlevels-16 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,55 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 608256, 0x60865484 +0, 1, 1, 1, 608256, 0x3c9bad01 +0, 2, 2, 1, 608256, 0x809b6b5d +0, 3, 3, 1, 608256, 0x4d873004 +0, 4, 4, 1, 608256, 0xff1651c8 +0, 5, 5, 1, 608256, 0x48fd0353 +0, 6, 6, 1, 608256, 0x184ce147 +0, 7, 7, 1, 608256, 0x9802722f +0, 8, 8, 1, 608256, 0x9413376e +0, 9, 9, 1, 608256, 0xfbb733e9 +0, 10, 10, 1, 608256, 0x573ae5a4 +0, 11, 11, 1, 608256, 0x8697c4a4 +0, 12, 12, 1, 608256, 0xc7b364c1 +0, 13, 13, 1, 608256, 0x512770ec +0, 14, 14, 1, 608256, 0x2adee98f +0, 15, 15, 1, 608256, 0xcfb7d642 +0, 16, 16, 1, 608256, 0xc303accb +0, 17, 17, 1, 608256, 0xc738fee1 +0, 18, 18, 1, 608256, 0xd28c5669 +0, 19, 19, 1, 608256, 0xd3ce495a +0, 20, 20, 1, 608256, 0x34fe368d +0, 21, 21, 1, 608256, 0xbafe49a4 +0, 22, 22, 1, 608256, 0x68da4a93 +0, 23, 23, 1, 608256, 0xfd632bde +0, 24, 24, 1, 608256, 0x92275713 +0, 25, 25, 1, 608256, 0xcb569e86 +0, 26, 26, 1, 608256, 0x84674f8a +0, 27, 27, 1, 608256, 0xd8b7f0d5 +0, 28, 28, 1, 608256, 0xe3e6f966 +0, 29, 29, 1, 608256, 0x084d3d4c +0, 30, 30, 1, 608256, 0x6e9c5c63 +0, 31, 31, 1, 608256, 0x71c71484 +0, 32, 32, 1, 608256, 0xa89dedd1 +0, 33, 33, 1, 608256, 0x4c481ca6 +0, 34, 34, 1, 608256, 0xa52bc63b +0, 35, 35, 1, 608256, 0x59f0efa5 +0, 36, 36, 1, 608256, 0xafb82d42 +0, 37, 37, 1, 608256, 0x887b8458 +0, 38, 38, 1, 608256, 0x8a2c6984 +0, 39, 39, 1, 608256, 0xe75e4737 +0, 40, 40, 1, 608256, 0xe41ed81c +0, 41, 41, 1, 608256, 0xbf816b8d +0, 42, 42, 1, 608256, 0x8cd1af16 +0, 43, 43, 1, 608256, 0x31883468 +0, 44, 44, 1, 608256, 0x380c2bf8 +0, 45, 45, 1, 608256, 0x25e7483e +0, 46, 46, 1, 608256, 0xe73edd67 +0, 47, 47, 1, 608256, 0x3e9670ef +0, 48, 48, 1, 608256, 0xd5b871fd +0, 49, 49, 1, 608256, 0xe075789f diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-concat-vfr ffmpeg-4.4/tests/ref/fate/filter-concat-vfr --- ffmpeg-4.2.2/tests/ref/fate/filter-concat-vfr 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-concat-vfr 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,224 @@ +#tb 0: 1/1000000 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +#tb 1: 1/44100 +#media_type 1: audio +#codec_id 1: pcm_s16le +#sample_rate 1: 44100 +#channel_layout 1: 4 +#channel_layout_name 1: mono +0, 0, 0, 0, 230400, 0x88c4d19a +1, 0, 0, 1024, 2048, 0xb3f10192 +1, 1024, 1024, 1024, 2048, 0xb340fe4e +1, 2048, 2048, 1024, 2048, 0x0a5f0111 +1, 3072, 3072, 1024, 2048, 0x51be06b8 +1, 4096, 4096, 1024, 2048, 0x71a1ffcb +1, 5120, 5120, 1024, 2048, 0x7f64f50f +1, 6144, 6144, 1024, 2048, 0x70a8fa17 +1, 7168, 7168, 1024, 2048, 0x0dad072a +1, 8192, 8192, 1024, 2048, 0x5e810c51 +0, 200000, 200000, 0, 230400, 0x0d77c977 +1, 9216, 9216, 1024, 2048, 0xbe5bf462 +1, 10240, 10240, 1024, 2048, 0xbcd9faeb +1, 11264, 11264, 1024, 2048, 0x0d5bfe9c +1, 12288, 12288, 1024, 2048, 0x97d80297 +1, 13312, 13312, 1024, 2048, 0xba0f0894 +1, 14336, 14336, 1024, 2048, 0xcc22f291 +1, 15360, 15360, 1024, 2048, 0x11a9fa03 +1, 16384, 16384, 1024, 2048, 0x9a920378 +1, 17408, 17408, 1024, 2048, 0x901b0525 +0, 400000, 400000, 0, 230400, 0x242629d7 +1, 18432, 18432, 1024, 2048, 0x74b2003f +1, 19456, 19456, 1024, 2048, 0xa20ef3ed +1, 20480, 20480, 1024, 2048, 0x44cef9de +1, 21504, 21504, 1024, 2048, 0x4b2e039b +1, 22528, 22528, 1024, 2048, 0x198509a1 +1, 23552, 23552, 1024, 2048, 0xcab6f9e5 +1, 24576, 24576, 1024, 2048, 0x67f8f608 +1, 25600, 25600, 1024, 2048, 0x8d7f03fa +0, 600000, 600000, 0, 230400, 0x62cdc018 +1, 26624, 26624, 1024, 2048, 0x3e1e0566 +1, 27648, 27648, 1024, 2048, 0x2cfe0308 +1, 28672, 28672, 1024, 2048, 0x1ceaf702 +1, 29696, 29696, 1024, 2048, 0x38a9f3d1 +1, 30720, 30720, 1024, 2048, 0x6c3306b7 +1, 31744, 31744, 1024, 2048, 0x600f0579 +1, 32768, 32768, 1024, 2048, 0x3e5afa28 +1, 33792, 33792, 1024, 2048, 0x053ff47a +1, 34816, 34816, 1024, 2048, 0x0d28fed9 +0, 800000, 800000, 0, 230400, 0x248ad058 +1, 35840, 35840, 1024, 2048, 0x279805cc +1, 36864, 36864, 1024, 2048, 0xb16a0a12 +1, 37888, 37888, 1024, 2048, 0xb45af340 +1, 38912, 38912, 1024, 2048, 0x1834f972 +1, 39936, 39936, 1024, 2048, 0xb5d206ae +1, 40960, 40960, 1024, 2048, 0xc5760375 +1, 41984, 41984, 1024, 2048, 0x503800ce +1, 43008, 43008, 1024, 2048, 0xa3bbf4af +1, 44032, 44032, 68, 136, 0xc8d751c7 +0, 1000000, 1000000, 0, 230400, 0x223d134f +1, 44100, 44100, 9600, 19200, 0x00000000 +0, 1200000, 1200000, 0, 230400, 0xbf1c3d34 +1, 53700, 53700, 9600, 19200, 0x00000000 +0, 1400000, 1400000, 0, 230400, 0xae0efe96 +1, 63300, 63300, 9600, 19200, 0x00000000 +0, 1600000, 1600000, 0, 230400, 0x0cd624d1 +1, 72900, 72900, 9600, 19200, 0x00000000 +0, 1800000, 1800000, 0, 230400, 0x6dedf2c0 +1, 82500, 82500, 5700, 11400, 0x00000000 +0, 2000000, 2000000, 0, 230400, 0x88c4d19a +1, 88200, 88200, 1024, 2048, 0x283efb3a +1, 89224, 89224, 1024, 2048, 0x7692fb8f +1, 90248, 90248, 1024, 2048, 0xbaaafcc0 +0, 2066667, 2066667, 0, 230400, 0x5bbc2f63 +1, 91272, 91272, 1024, 2048, 0xadc8017e +1, 92296, 92296, 1024, 2048, 0x4f4dffdc +1, 93320, 93320, 1024, 2048, 0x7ffbff48 +0, 2133333, 2133333, 0, 230400, 0x3becbfad +1, 94344, 94344, 1024, 2048, 0x2f990719 +1, 95368, 95368, 1024, 2048, 0xe2caf65c +1, 96392, 96392, 1024, 2048, 0x825208e4 +0, 2200000, 2200000, 0, 230400, 0x0d77c977 +1, 97416, 97416, 1024, 2048, 0xf563f13b +1, 98440, 98440, 1024, 2048, 0x855d03e9 +1, 99464, 99464, 1024, 2048, 0x0ba9fa4b +0, 2266667, 2266667, 0, 230400, 0x436cf4b2 +1, 100488, 100488, 1024, 2048, 0x83e1fb92 +1, 101512, 101512, 1024, 2048, 0x1162f965 +1, 102536, 102536, 1024, 2048, 0x0cfef73d +0, 2333333, 2333333, 0, 230400, 0x39210f27 +1, 103560, 103560, 1024, 2048, 0x5688ff75 +1, 104584, 104584, 1024, 2048, 0xf6c0ede9 +1, 105608, 105608, 1024, 2048, 0xfdb20602 +0, 2400000, 2400000, 0, 230400, 0x242629d7 +1, 106632, 106632, 1024, 2048, 0x40c5f17b +1, 107656, 107656, 1024, 2048, 0x559600b1 +1, 108680, 108680, 1024, 2048, 0xccc3f930 +0, 2466667, 2466667, 0, 230400, 0x771c2293 +1, 109704, 109704, 1024, 2048, 0xdc800045 +1, 110728, 110728, 1024, 2048, 0xdce4fb3e +0, 2533333, 2533333, 0, 230400, 0xec2af9a9 +1, 111752, 111752, 1024, 2048, 0x1e5efba9 +1, 112776, 112776, 1024, 2048, 0x8c2e0832 +1, 113800, 113800, 1024, 2048, 0x5c42f66d +0, 2600000, 2600000, 0, 230400, 0x62cdc018 +1, 114824, 114824, 1024, 2048, 0x08e20b1e +1, 115848, 115848, 1024, 2048, 0x4cf7f903 +1, 116872, 116872, 1024, 2048, 0xe6b90794 +0, 2666667, 2666667, 0, 230400, 0xf02c8693 +1, 117896, 117896, 1024, 2048, 0x5956f8e6 +1, 118920, 118920, 1024, 2048, 0x6632ff16 +1, 119944, 119944, 1024, 2048, 0x46c8fe11 +0, 2733333, 2733333, 0, 230400, 0x14436efb +1, 120968, 120968, 1024, 2048, 0x7431f732 +1, 121992, 121992, 1024, 2048, 0xa258049f +1, 123016, 123016, 1024, 2048, 0xdb71f00e +0, 2800000, 2800000, 0, 230400, 0x248ad058 +1, 124040, 124040, 1024, 2048, 0xa89b0359 +1, 125064, 125064, 1024, 2048, 0xe0aff0f2 +1, 126088, 126088, 1024, 2048, 0xc33e0085 +0, 2866667, 2866667, 0, 230400, 0xe87f6c52 +1, 127112, 127112, 1024, 2048, 0x9d09f379 +1, 128136, 128136, 1024, 2048, 0x8c78fd06 +1, 129160, 129160, 1024, 2048, 0x532bfbdd +0, 2933333, 2933333, 0, 230400, 0x6a0c196b +1, 130184, 130184, 1024, 2048, 0xfc36f5cd +1, 131208, 131208, 1024, 2048, 0x2e8f0699 +1, 132232, 132232, 1024, 2048, 0x52382578 +1, 133256, 133256, 1024, 2048, 0x97ed1a28 +1, 134280, 134280, 1024, 2048, 0xabcdf73f +1, 135304, 135304, 1024, 2048, 0x3a24082c +1, 136328, 136328, 1024, 2048, 0xbe1cfc3d +1, 137352, 137352, 1024, 2048, 0xad5800a5 +1, 138376, 138376, 1024, 2048, 0x90b80522 +1, 139400, 139400, 1024, 2048, 0x1fa1f912 +1, 140424, 140424, 1024, 2048, 0x733a0878 +1, 141448, 141448, 1024, 2048, 0x9a3eee47 +1, 142472, 142472, 1024, 2048, 0x5d900759 +1, 143496, 143496, 1024, 2048, 0x1287f540 +1, 144520, 144520, 1024, 2048, 0x941cfe5d +1, 145544, 145544, 1024, 2048, 0x1587f8a9 +1, 146568, 146568, 1024, 2048, 0xb9e7f888 +1, 147592, 147592, 1024, 2048, 0xe9defbe2 +1, 148616, 148616, 1024, 2048, 0x3a5ef312 +1, 149640, 149640, 1024, 2048, 0xdcbe0544 +1, 150664, 150664, 1024, 2048, 0xbe51ecc5 +1, 151688, 151688, 1024, 2048, 0x21a60721 +1, 152712, 152712, 1024, 2048, 0xf29ff318 +1, 153736, 153736, 1024, 2048, 0xcd4c02ea +1, 154760, 154760, 1024, 2048, 0xa424faac +1, 155784, 155784, 1024, 2048, 0xbaedfdab +1, 156808, 156808, 1024, 2048, 0xcbff047c +1, 157832, 157832, 1024, 2048, 0x9ac8f96b +1, 158856, 158856, 1024, 2048, 0x43220bee +1, 159880, 159880, 1024, 2048, 0x547bf351 +1, 160904, 160904, 1024, 2048, 0x7dd10d6e +1, 161928, 161928, 1024, 2048, 0x77cbf603 +1, 162952, 162952, 1024, 2048, 0xb6fcff50 +1, 163976, 163976, 1024, 2048, 0x927bfde5 +1, 165000, 165000, 1024, 2048, 0x5bd0fca5 +1, 166024, 166024, 1024, 2048, 0x672cff2a +1, 167048, 167048, 1024, 2048, 0x3e3ef01c +1, 168072, 168072, 1024, 2048, 0xe52607af +1, 169096, 169096, 1024, 2048, 0x66bceaf5 +1, 170120, 170120, 1024, 2048, 0xe065046b +1, 171144, 171144, 1024, 2048, 0x350bf21f +1, 172168, 172168, 1024, 2048, 0x60b1fca4 +1, 173192, 173192, 1024, 2048, 0x8b1efa55 +1, 174216, 174216, 1024, 2048, 0xf86ff855 +1, 175240, 175240, 1024, 2048, 0x6934061b +1, 176264, 176264, 136, 272, 0x4a458a45 +0, 4000000, 4000000, 0, 230400, 0x88c4d19a +1, 176400, 176400, 1024, 2048, 0xdb0cfe95 +1, 177424, 177424, 1024, 2048, 0xcff3fdf1 +1, 178448, 178448, 1024, 2048, 0x070cf585 +1, 179472, 179472, 1024, 2048, 0xe9b8007f +1, 180496, 180496, 1024, 2048, 0xc51ffd64 +1, 181520, 181520, 1024, 2048, 0xede2fbf9 +0, 4125000, 4125000, 0, 230400, 0x05c1b733 +1, 182544, 182544, 1024, 2048, 0x51510410 +1, 183568, 183568, 1024, 2048, 0x198af498 +1, 184592, 184592, 1024, 2048, 0xae3603a2 +1, 185616, 185616, 1024, 2048, 0x6200f7a1 +1, 186640, 186640, 1024, 2048, 0xe6e3fe32 +0, 4250000, 4250000, 0, 230400, 0x0446ec19 +1, 187664, 187664, 1024, 2048, 0xb2e2fd77 +1, 188688, 188688, 1024, 2048, 0x063dff2f +1, 189712, 189712, 1024, 2048, 0xa89ffe21 +1, 190736, 190736, 1024, 2048, 0x9e6ffa6d +1, 191760, 191760, 1024, 2048, 0x028b004e +1, 192784, 192784, 1024, 2048, 0x57edfa23 +0, 4375000, 4375000, 0, 230400, 0x0f9b1744 +1, 193808, 193808, 1024, 2048, 0x6d8efe1f +1, 194832, 194832, 1024, 2048, 0x774bfe54 +1, 195856, 195856, 1024, 2048, 0xa931fcfb +1, 196880, 196880, 1024, 2048, 0x3505004b +1, 197904, 197904, 1024, 2048, 0x5001f576 +0, 4500000, 4500000, 0, 230400, 0x30cf070a +1, 198928, 198928, 1024, 2048, 0x78ea049b +1, 199952, 199952, 1024, 2048, 0xd45bf733 +1, 200976, 200976, 1024, 2048, 0x6395fead +1, 202000, 202000, 1024, 2048, 0xc126015e +1, 203024, 203024, 1024, 2048, 0xbecff8aa +0, 4625000, 4625000, 0, 230400, 0x9175aaa9 +1, 204048, 204048, 1024, 2048, 0x0fea06c3 +1, 205072, 205072, 1024, 2048, 0xdea6f351 +1, 206096, 206096, 1024, 2048, 0x35b808f0 +1, 207120, 207120, 1024, 2048, 0x5487ee73 +1, 208144, 208144, 1024, 2048, 0xac69050e +1, 209168, 209168, 1024, 2048, 0xcc5ffb00 +0, 4750000, 4750000, 0, 230400, 0x597f5628 +1, 210192, 210192, 1024, 2048, 0x328c00cb +1, 211216, 211216, 1024, 2048, 0xa707fd82 +1, 212240, 212240, 1024, 2048, 0xe442f73d +1, 213264, 213264, 1024, 2048, 0x545c0418 +1, 214288, 214288, 1024, 2048, 0x744ff3f7 +0, 4875000, 4875000, 0, 230400, 0x38a45a85 +1, 215312, 215312, 1024, 2048, 0x01aa04fd +1, 216336, 216336, 1024, 2048, 0xa885f7cd +1, 217360, 217360, 1024, 2048, 0xcfca04f4 +1, 218384, 218384, 1024, 2048, 0x67fdf91b +1, 219408, 219408, 1024, 2048, 0xce2b001d +1, 220432, 220432, 68, 136, 0x33e64a0d diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-earwax ffmpeg-4.4/tests/ref/fate/filter-earwax --- ffmpeg-4.2.2/tests/ref/fate/filter-earwax 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-earwax 2021-04-08 21:28:40.000000000 +0000 @@ -4,23 +4,23 @@ #sample_rate 0: 44100 #channel_layout 0: 3 #channel_layout_name 0: stereo -0, 0, 0, 1024, 4096, 0x900af751 -0, 1024, 1024, 1024, 4096, 0xad570065 -0, 2048, 2048, 1024, 4096, 0x93d5f494 -0, 3072, 3072, 1024, 4096, 0x2c65ef7d -0, 4096, 4096, 1024, 4096, 0xdc8af6d2 -0, 5120, 5120, 1024, 4096, 0x7ae00249 -0, 6144, 6144, 1024, 4096, 0xaab5fdd0 -0, 7168, 7168, 1024, 4096, 0x4373ef39 -0, 8192, 8192, 1024, 4096, 0x0756eb43 -0, 9216, 9216, 1024, 4096, 0x494d06e0 -0, 10240, 10240, 1024, 4096, 0x4393ffae -0, 11264, 11264, 1024, 4096, 0x6972f97e -0, 12288, 12288, 1024, 4096, 0xb834ea05 -0, 13312, 13312, 1024, 4096, 0x39b8f871 -0, 14336, 14336, 1024, 4096, 0xf032fccd -0, 15360, 15360, 1024, 4096, 0xefcd0709 -0, 16384, 16384, 1024, 4096, 0x0590ebc0 -0, 17408, 17408, 1024, 4096, 0x2e75f264 -0, 18432, 18432, 1024, 4096, 0xbea1fd03 -0, 19456, 19456, 1024, 4096, 0x9bbe0434 +0, 0, 0, 1024, 4096, 0xb7e1f437 +0, 1024, 1024, 1024, 4096, 0xa031042a +0, 2048, 2048, 1024, 4096, 0x9b72ed0f +0, 3072, 3072, 1024, 4096, 0xff14ed33 +0, 4096, 4096, 1024, 4096, 0x96eef519 +0, 5120, 5120, 1024, 4096, 0x290d0ca0 +0, 6144, 6144, 1024, 4096, 0x0393fbf5 +0, 7168, 7168, 1024, 4096, 0xed89ef59 +0, 8192, 8192, 1024, 4096, 0xf664e969 +0, 9216, 9216, 1024, 4096, 0x261a05e4 +0, 10240, 10240, 1024, 4096, 0xc334ff5b +0, 11264, 11264, 1024, 4096, 0x030ffa65 +0, 12288, 12288, 1024, 4096, 0xcfb4e835 +0, 13312, 13312, 1024, 4096, 0xd9adf7ff +0, 14336, 14336, 1024, 4096, 0x5e9001ae +0, 15360, 15360, 1024, 4096, 0xbfaf0174 +0, 16384, 16384, 1024, 4096, 0x8cf3f061 +0, 17408, 17408, 1024, 4096, 0x35ffece5 +0, 18432, 18432, 1024, 4096, 0x1de801e2 +0, 19456, 19456, 1024, 4096, 0xa1a40372 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-edgedetect ffmpeg-4.4/tests/ref/fate/filter-edgedetect --- ffmpeg-4.2.2/tests/ref/fate/filter-edgedetect 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-edgedetect 2021-04-08 21:28:40.000000000 +0000 @@ -1 +1 @@ -edgedetect 93ceace33f6636bcdbeb037317c65745 +edgedetect 04ff46bb35edff3dbad4102391516d25 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-edgedetect-colormix ffmpeg-4.4/tests/ref/fate/filter-edgedetect-colormix --- ffmpeg-4.2.2/tests/ref/fate/filter-edgedetect-colormix 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-edgedetect-colormix 2021-04-08 21:28:40.000000000 +0000 @@ -1 +1 @@ -edgedetect-colormix 1b8658252e2f03fbae30e6d63dd24c7c +edgedetect-colormix 9f50c5586f899a8f5a10059154d64bde diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-fps-down ffmpeg-4.4/tests/ref/fate/filter-fps-down --- ffmpeg-4.2.2/tests/ref/fate/filter-fps-down 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-fps-down 2021-04-08 21:28:40.000000000 +0000 @@ -13,3 +13,4 @@ 0, 7, 7, 1, 115200, 0xc705ccd9 0, 8, 8, 1, 115200, 0x5635daa5 0, 9, 9, 1, 115200, 0x7161ef8f +0, 10, 10, 1, 115200, 0xccf02fed diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-fps-up ffmpeg-4.4/tests/ref/fate/filter-fps-up --- ffmpeg-4.2.2/tests/ref/fate/filter-fps-up 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-fps-up 2021-04-08 21:28:40.000000000 +0000 @@ -15,3 +15,5 @@ 0, 9, 9, 1, 115200, 0xb0dfacf8 0, 10, 10, 1, 115200, 0xb0dfacf8 0, 11, 11, 1, 115200, 0xb0dfacf8 +0, 12, 12, 1, 115200, 0x53d5b181 +0, 13, 13, 1, 115200, 0x53d5b181 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-fps-up-round-down ffmpeg-4.4/tests/ref/fate/filter-fps-up-round-down --- ffmpeg-4.2.2/tests/ref/fate/filter-fps-up-round-down 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-fps-up-round-down 2021-04-08 21:28:40.000000000 +0000 @@ -14,3 +14,6 @@ 0, 8, 8, 1, 115200, 0x33f15918 0, 9, 9, 1, 115200, 0xb0dfacf8 0, 10, 10, 1, 115200, 0xb0dfacf8 +0, 11, 11, 1, 115200, 0x53d5b181 +0, 12, 12, 1, 115200, 0x53d5b181 +0, 13, 13, 1, 115200, 0x53d5b181 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-fps-up-round-up ffmpeg-4.4/tests/ref/fate/filter-fps-up-round-up --- ffmpeg-4.2.2/tests/ref/fate/filter-fps-up-round-up 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-fps-up-round-up 2021-04-08 21:28:40.000000000 +0000 @@ -15,3 +15,5 @@ 0, 9, 9, 1, 115200, 0x33f15918 0, 10, 10, 1, 115200, 0xb0dfacf8 0, 11, 11, 1, 115200, 0xb0dfacf8 +0, 12, 12, 1, 115200, 0x53d5b181 +0, 13, 13, 1, 115200, 0x53d5b181 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-metadata-freezedetect ffmpeg-4.4/tests/ref/fate/filter-metadata-freezedetect --- ffmpeg-4.2.2/tests/ref/fate/filter-metadata-freezedetect 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-metadata-freezedetect 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,251 @@ +pkt_pts=0 +pkt_pts=1 +pkt_pts=2 +pkt_pts=3 +pkt_pts=4 +pkt_pts=5 +pkt_pts=6 +pkt_pts=7 +pkt_pts=8 +pkt_pts=9 +pkt_pts=10 +pkt_pts=11 +pkt_pts=12 +pkt_pts=13 +pkt_pts=14 +pkt_pts=15 +pkt_pts=16 +pkt_pts=17 +pkt_pts=18 +pkt_pts=19 +pkt_pts=20 +pkt_pts=21 +pkt_pts=22 +pkt_pts=23 +pkt_pts=24 +pkt_pts=25 +pkt_pts=26 +pkt_pts=27 +pkt_pts=28 +pkt_pts=29 +pkt_pts=30 +pkt_pts=31 +pkt_pts=32 +pkt_pts=33 +pkt_pts=34 +pkt_pts=35 +pkt_pts=36 +pkt_pts=37 +pkt_pts=38 +pkt_pts=39 +pkt_pts=40 +pkt_pts=41 +pkt_pts=42 +pkt_pts=43 +pkt_pts=44 +pkt_pts=45 +pkt_pts=46 +pkt_pts=47 +pkt_pts=48 +pkt_pts=49 +pkt_pts=50 +pkt_pts=51 +pkt_pts=52 +pkt_pts=53 +pkt_pts=54 +pkt_pts=55 +pkt_pts=56 +pkt_pts=57 +pkt_pts=58 +pkt_pts=59 +pkt_pts=60 +pkt_pts=61 +pkt_pts=62 +pkt_pts=63 +pkt_pts=64 +pkt_pts=65 +pkt_pts=66 +pkt_pts=67 +pkt_pts=68 +pkt_pts=69 +pkt_pts=70 +pkt_pts=71 +pkt_pts=72 +pkt_pts=73 +pkt_pts=74 +pkt_pts=75 +pkt_pts=76 +pkt_pts=77 +pkt_pts=78 +pkt_pts=79 +pkt_pts=80 +pkt_pts=81 +pkt_pts=82 +pkt_pts=83 +pkt_pts=84 +pkt_pts=85 +pkt_pts=86 +pkt_pts=87 +pkt_pts=88 +pkt_pts=89 +pkt_pts=90 +pkt_pts=91 +pkt_pts=92 +pkt_pts=93 +pkt_pts=94 +pkt_pts=95 +pkt_pts=96 +pkt_pts=97 +pkt_pts=98 +pkt_pts=99 +pkt_pts=100 +pkt_pts=101 +pkt_pts=102 +pkt_pts=103 +pkt_pts=104 +pkt_pts=105 +pkt_pts=106 +pkt_pts=107 +pkt_pts=108 +pkt_pts=109 +pkt_pts=110 +pkt_pts=111 +pkt_pts=112 +pkt_pts=113 +pkt_pts=114 +pkt_pts=115 +pkt_pts=116 +pkt_pts=117 +pkt_pts=118 +pkt_pts=119 +pkt_pts=120 +pkt_pts=121 +pkt_pts=122 +pkt_pts=123 +pkt_pts=124 +pkt_pts=125 +pkt_pts=126 +pkt_pts=127 +pkt_pts=128 +pkt_pts=129 +pkt_pts=130 +pkt_pts=131 +pkt_pts=132 +pkt_pts=133 +pkt_pts=134 +pkt_pts=135 +pkt_pts=136 +pkt_pts=137 +pkt_pts=138 +pkt_pts=139 +pkt_pts=140 +pkt_pts=141 +pkt_pts=142 +pkt_pts=143 +pkt_pts=144 +pkt_pts=145 +pkt_pts=146 +pkt_pts=147 +pkt_pts=148 +pkt_pts=149 +pkt_pts=150 +pkt_pts=151 +pkt_pts=152 +pkt_pts=153|tag:lavfi.freezedetect.freeze_start=4.12|tag:lavfi.freezedetect.freeze_duration=2|tag:lavfi.freezedetect.freeze_end=6.12 +pkt_pts=154 +pkt_pts=155 +pkt_pts=156 +pkt_pts=157 +pkt_pts=158 +pkt_pts=159 +pkt_pts=160 +pkt_pts=161 +pkt_pts=162 +pkt_pts=163 +pkt_pts=164 +pkt_pts=165 +pkt_pts=166 +pkt_pts=167 +pkt_pts=168 +pkt_pts=169 +pkt_pts=170 +pkt_pts=171 +pkt_pts=172 +pkt_pts=173 +pkt_pts=174 +pkt_pts=175 +pkt_pts=176 +pkt_pts=177 +pkt_pts=178 +pkt_pts=179 +pkt_pts=180 +pkt_pts=181 +pkt_pts=182 +pkt_pts=183 +pkt_pts=184 +pkt_pts=185 +pkt_pts=186 +pkt_pts=187 +pkt_pts=188 +pkt_pts=189 +pkt_pts=190 +pkt_pts=191 +pkt_pts=192 +pkt_pts=193 +pkt_pts=194 +pkt_pts=195 +pkt_pts=196 +pkt_pts=197 +pkt_pts=198 +pkt_pts=199 +pkt_pts=200 +pkt_pts=201 +pkt_pts=202 +pkt_pts=203 +pkt_pts=204|tag:lavfi.freezedetect.freeze_start=6.16|tag:lavfi.freezedetect.freeze_duration=2|tag:lavfi.freezedetect.freeze_end=8.16 +pkt_pts=205 +pkt_pts=206 +pkt_pts=207 +pkt_pts=208 +pkt_pts=209 +pkt_pts=210 +pkt_pts=211 +pkt_pts=212 +pkt_pts=213 +pkt_pts=214 +pkt_pts=215 +pkt_pts=216 +pkt_pts=217 +pkt_pts=218 +pkt_pts=219 +pkt_pts=220 +pkt_pts=221 +pkt_pts=222 +pkt_pts=223 +pkt_pts=224 +pkt_pts=225 +pkt_pts=226 +pkt_pts=227 +pkt_pts=228 +pkt_pts=229 +pkt_pts=230 +pkt_pts=231 +pkt_pts=232 +pkt_pts=233 +pkt_pts=234 +pkt_pts=235 +pkt_pts=236 +pkt_pts=237 +pkt_pts=238 +pkt_pts=239 +pkt_pts=240 +pkt_pts=241 +pkt_pts=242 +pkt_pts=243 +pkt_pts=244 +pkt_pts=245 +pkt_pts=246 +pkt_pts=247 +pkt_pts=248 +pkt_pts=249 +pkt_pts=250 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-metadata-scdet ffmpeg-4.4/tests/ref/fate/filter-metadata-scdet --- ffmpeg-4.2.2/tests/ref/fate/filter-metadata-scdet 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-metadata-scdet 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,11 @@ +pkt_pts=1620|tag:lavfi.scd.mafd=60.175|tag:lavfi.scd.score=59.252|tag:lavfi.scd.time=2.7 +pkt_pts=4140|tag:lavfi.scd.mafd=44.209|tag:lavfi.scd.score=36.070|tag:lavfi.scd.time=6.9 +pkt_pts=5800|tag:lavfi.scd.mafd=55.819|tag:lavfi.scd.score=55.819|tag:lavfi.scd.time=9.66667 +pkt_pts=6720|tag:lavfi.scd.mafd=22.505|tag:lavfi.scd.score=18.580|tag:lavfi.scd.time=11.2 +pkt_pts=8160|tag:lavfi.scd.mafd=49.444|tag:lavfi.scd.score=49.240|tag:lavfi.scd.time=13.6 +pkt_pts=9760|tag:lavfi.scd.mafd=51.801|tag:lavfi.scd.score=51.497|tag:lavfi.scd.time=16.2667 +pkt_pts=14080|tag:lavfi.scd.mafd=34.337|tag:lavfi.scd.score=34.165|tag:lavfi.scd.time=23.4667 +pkt_pts=15700|tag:lavfi.scd.mafd=58.315|tag:lavfi.scd.score=58.310|tag:lavfi.scd.time=26.1667 +pkt_pts=18500|tag:lavfi.scd.mafd=19.603|tag:lavfi.scd.score=16.504|tag:lavfi.scd.time=30.8333 +pkt_pts=20040|tag:lavfi.scd.mafd=19.060|tag:lavfi.scd.score=13.764|tag:lavfi.scd.time=33.4 +pkt_pts=21760|tag:lavfi.scd.mafd=64.551|tag:lavfi.scd.score=64.451|tag:lavfi.scd.time=36.2667 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-metadata-scenedetect ffmpeg-4.4/tests/ref/fate/filter-metadata-scenedetect --- ffmpeg-4.2.2/tests/ref/fate/filter-metadata-scenedetect 2016-03-29 02:25:35.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-metadata-scenedetect 2020-07-11 10:39:30.000000000 +0000 @@ -1,10 +1,11 @@ pkt_pts=1620|tag:lavfi.scene_score=1.000000 -pkt_pts=4140|tag:lavfi.scene_score=0.875036 +pkt_pts=4140|tag:lavfi.scene_score=0.923403 pkt_pts=5800|tag:lavfi.scene_score=1.000000 -pkt_pts=6720|tag:lavfi.scene_score=0.461625 +pkt_pts=6720|tag:lavfi.scene_score=0.475643 pkt_pts=8160|tag:lavfi.scene_score=1.000000 pkt_pts=9760|tag:lavfi.scene_score=1.000000 -pkt_pts=14080|tag:lavfi.scene_score=0.838916 +pkt_pts=14080|tag:lavfi.scene_score=0.874623 pkt_pts=15700|tag:lavfi.scene_score=1.000000 -pkt_pts=18500|tag:lavfi.scene_score=0.474948 +pkt_pts=18500|tag:lavfi.scene_score=0.422509 +pkt_pts=20040|tag:lavfi.scene_score=0.352360 pkt_pts=21760|tag:lavfi.scene_score=1.000000 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-metadata-signalstats-yuv420p ffmpeg-4.4/tests/ref/fate/filter-metadata-signalstats-yuv420p --- ffmpeg-4.2.2/tests/ref/fate/filter-metadata-signalstats-yuv420p 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-metadata-signalstats-yuv420p 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +pkt_pts=0|tag:lavfi.signalstats.YMIN=235|tag:lavfi.signalstats.YLOW=235|tag:lavfi.signalstats.YAVG=235|tag:lavfi.signalstats.YHIGH=235|tag:lavfi.signalstats.YMAX=235|tag:lavfi.signalstats.UMIN=128|tag:lavfi.signalstats.ULOW=128|tag:lavfi.signalstats.UAVG=128|tag:lavfi.signalstats.UHIGH=128|tag:lavfi.signalstats.UMAX=128|tag:lavfi.signalstats.VMIN=128|tag:lavfi.signalstats.VLOW=128|tag:lavfi.signalstats.VAVG=128|tag:lavfi.signalstats.VHIGH=128|tag:lavfi.signalstats.VMAX=128|tag:lavfi.signalstats.SATMIN=0|tag:lavfi.signalstats.SATLOW=0|tag:lavfi.signalstats.SATAVG=0|tag:lavfi.signalstats.SATHIGH=0|tag:lavfi.signalstats.SATMAX=0|tag:lavfi.signalstats.HUEMED=180|tag:lavfi.signalstats.HUEAVG=180|tag:lavfi.signalstats.YDIF=0|tag:lavfi.signalstats.UDIF=0|tag:lavfi.signalstats.VDIF=0|tag:lavfi.signalstats.YBITDEPTH=6|tag:lavfi.signalstats.UBITDEPTH=1|tag:lavfi.signalstats.VBITDEPTH=1 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-metadata-signalstats-yuv420p10 ffmpeg-4.4/tests/ref/fate/filter-metadata-signalstats-yuv420p10 --- ffmpeg-4.2.2/tests/ref/fate/filter-metadata-signalstats-yuv420p10 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-metadata-signalstats-yuv420p10 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +pkt_pts=0|tag:lavfi.signalstats.YMIN=940|tag:lavfi.signalstats.YLOW=940|tag:lavfi.signalstats.YAVG=940|tag:lavfi.signalstats.YHIGH=940|tag:lavfi.signalstats.YMAX=940|tag:lavfi.signalstats.UMIN=512|tag:lavfi.signalstats.ULOW=512|tag:lavfi.signalstats.UAVG=512|tag:lavfi.signalstats.UHIGH=512|tag:lavfi.signalstats.UMAX=512|tag:lavfi.signalstats.VMIN=512|tag:lavfi.signalstats.VLOW=512|tag:lavfi.signalstats.VAVG=512|tag:lavfi.signalstats.VHIGH=512|tag:lavfi.signalstats.VMAX=512|tag:lavfi.signalstats.SATMIN=0|tag:lavfi.signalstats.SATLOW=0|tag:lavfi.signalstats.SATAVG=0|tag:lavfi.signalstats.SATHIGH=0|tag:lavfi.signalstats.SATMAX=0|tag:lavfi.signalstats.HUEMED=180|tag:lavfi.signalstats.HUEAVG=180|tag:lavfi.signalstats.YDIF=0|tag:lavfi.signalstats.UDIF=0|tag:lavfi.signalstats.VDIF=0|tag:lavfi.signalstats.YBITDEPTH=6|tag:lavfi.signalstats.UBITDEPTH=1|tag:lavfi.signalstats.VBITDEPTH=1 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-minterpolate-down ffmpeg-4.4/tests/ref/fate/filter-minterpolate-down --- ffmpeg-4.2.2/tests/ref/fate/filter-minterpolate-down 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-minterpolate-down 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/1 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0x3744b3ed diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-minterpolate-up ffmpeg-4.4/tests/ref/fate/filter-minterpolate-up --- ffmpeg-4.2.2/tests/ref/fate/filter-minterpolate-up 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-minterpolate-up 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,15 @@ +#tb 0: 1/10 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0x3744b3ed +0, 1, 1, 1, 115200, 0xf54dba9a +0, 2, 2, 1, 115200, 0xd0b30f49 +0, 3, 3, 1, 115200, 0x61720dac +0, 4, 4, 1, 115200, 0xb93a0baa +0, 5, 5, 1, 115200, 0x6e318ba0 +0, 6, 6, 1, 115200, 0xbce5157a +0, 7, 7, 1, 115200, 0xe16418a3 +0, 8, 8, 1, 115200, 0xdd91079c +0, 9, 9, 1, 115200, 0xdf69f73c diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-mpdecimate ffmpeg-4.4/tests/ref/fate/filter-mpdecimate --- ffmpeg-4.2.2/tests/ref/fate/filter-mpdecimate 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-mpdecimate 2021-04-08 21:28:40.000000000 +0000 @@ -22,3 +22,4 @@ 0, 24, 24, 1, 115200, 0x056d40ca 0, 26, 26, 1, 115200, 0xa4374737 0, 27, 27, 1, 115200, 0x3eaa3ae8 +0, 29, 29, 1, 115200, 0x7551e9ee diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-overlay-dvdsub-2397 ffmpeg-4.4/tests/ref/fate/filter-overlay-dvdsub-2397 --- ffmpeg-4.2.2/tests/ref/fate/filter-overlay-dvdsub-2397 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-overlay-dvdsub-2397 2020-07-11 10:39:30.000000000 +0000 @@ -490,368 +490,368 @@ 1, 3877, 3877, 10, 2013, 0x95a39f9c 1, 3887, 3887, 10, 2013, 0x4f7ea123 1, 3897, 3897, 10, 2013, 0x9efb9ba1 -0, 117, 117, 1, 518400, 0x949e1e8b +0, 117, 117, 1, 518400, 0xbf8523da 1, 3907, 3907, 10, 2013, 0xf395b2cd 1, 3917, 3917, 10, 2013, 0x261a881e 1, 3927, 3927, 10, 2013, 0x7f2d9f72 1, 3937, 3937, 10, 2013, 0x0105b38d -0, 118, 118, 1, 518400, 0xfc6c09aa +0, 118, 118, 1, 518400, 0x41890ed6 1, 3952, 3952, 10, 2013, 0x0e5db67e 1, 3962, 3962, 10, 2013, 0xfc9baf97 -0, 119, 119, 1, 518400, 0x561c2ff5 +0, 119, 119, 1, 518400, 0x588534fc 1, 3972, 3972, 10, 2013, 0x8e02a1b1 1, 3982, 3982, 10, 2013, 0x6eecaac8 1, 3992, 3992, 10, 2013, 0xf5558f0c 1, 4002, 4002, 10, 2013, 0x512ba99b -0, 120, 120, 1, 518400, 0xfd62e6bd +0, 120, 120, 1, 518400, 0x2145ebc1 1, 4012, 4012, 10, 2013, 0x932b9932 1, 4022, 4022, 10, 2013, 0xc01ea987 -0, 121, 121, 1, 518400, 0x0427a070 +0, 121, 121, 1, 518400, 0x28bca595 1, 4038, 4038, 10, 2013, 0x10879cf7 1, 4048, 4048, 10, 2013, 0x90679338 1, 4058, 4058, 10, 2013, 0x077d8a9e 1, 4068, 4068, 10, 2013, 0x969fa57c -0, 122, 122, 1, 518400, 0x0bf48fff +0, 122, 122, 1, 518400, 0x77dc951e 1, 4078, 4078, 10, 2013, 0xe049ab07 1, 4088, 4088, 10, 2013, 0xf535b3b3 1, 4098, 4098, 10, 2013, 0xfe76bd37 -0, 123, 123, 1, 518400, 0x354d4700 +0, 123, 123, 1, 518400, 0xe8924c17 1, 4108, 4108, 10, 2013, 0xde79ad8c 1, 4123, 4123, 10, 2013, 0xe89b9c47 1, 4133, 4133, 10, 2013, 0xc570b0f0 -0, 124, 124, 1, 518400, 0x6081c80c +0, 124, 124, 1, 518400, 0xadb4cccc 1, 4143, 4143, 10, 2013, 0xee709cd9 1, 4153, 4153, 10, 2013, 0xcfe5afab 1, 4163, 4163, 10, 2013, 0x98ff8ce4 -0, 125, 125, 1, 518400, 0x9c6c51c6 +0, 125, 125, 1, 518400, 0x1d7b56ac 1, 4173, 4173, 10, 2013, 0x9d19b44c 1, 4183, 4183, 10, 2013, 0x4349917a 1, 4193, 4193, 10, 2013, 0xbf54a59a -0, 126, 126, 1, 518400, 0xaacd34d7 +0, 126, 126, 1, 518400, 0xad5739a4 1, 4208, 4208, 10, 2013, 0xc4a399e0 1, 4218, 4218, 10, 2013, 0x1bf58ff0 1, 4228, 4228, 10, 2013, 0x3518ac56 -0, 127, 127, 1, 518400, 0x566bce8e +0, 127, 127, 1, 518400, 0x2733d35a 1, 4238, 4238, 10, 2013, 0xcd38c1de 1, 4248, 4248, 10, 2013, 0xbe7d9c4d 1, 4258, 4258, 10, 2013, 0xe113a306 1, 4268, 4268, 10, 2013, 0x083197ea -0, 128, 128, 1, 518400, 0xb14f68b3 +0, 128, 128, 1, 518400, 0x78e76da2 1, 4278, 4278, 10, 2013, 0x1929b1eb 1, 4294, 4294, 10, 2013, 0x5d6ea5af 1, 4304, 4304, 10, 2013, 0x05519d53 -0, 129, 129, 1, 518400, 0x00545b29 +0, 129, 129, 1, 518400, 0x6c076013 1, 4314, 4314, 10, 2013, 0x5773b380 1, 4324, 4324, 10, 2013, 0xaa70a8f5 1, 4334, 4334, 10, 2013, 0x990db0ec -0, 130, 130, 1, 518400, 0x984bede5 +0, 130, 130, 1, 518400, 0x7854f2b1 1, 4344, 4344, 10, 2013, 0x91d3a623 1, 4354, 4354, 10, 2013, 0xc91f9824 1, 4364, 4364, 10, 2013, 0x1d058abf -0, 131, 131, 1, 518400, 0x6b9319c6 +0, 131, 131, 1, 518400, 0xd2ae1ecd 1, 4379, 4379, 10, 2013, 0x8de1b8d5 1, 4389, 4389, 10, 2013, 0x7872b06b 1, 4399, 4399, 10, 2013, 0xa084c203 -0, 132, 132, 1, 518400, 0x1582ae8c +0, 132, 132, 1, 518400, 0xf5eab38d 1, 4409, 4409, 10, 2013, 0xff90ae8d 1, 4419, 4419, 10, 2013, 0x61dead8e 1, 4429, 4429, 10, 2013, 0xee76b284 -0, 133, 133, 1, 518400, 0xece339b6 +0, 133, 133, 1, 518400, 0x994d3e9c 1, 4439, 4439, 10, 2013, 0xe888af7f 1, 4449, 4449, 10, 2013, 0x5d57b115 1, 4464, 4464, 10, 2013, 0xcdbfb1d0 -0, 134, 134, 1, 518400, 0x74946b8b +0, 134, 134, 1, 518400, 0x95ab705a 1, 4474, 4474, 10, 2013, 0x2e28a952 1, 4484, 4484, 10, 2013, 0x4795a994 1, 4494, 4494, 10, 2013, 0x7e7ea304 1, 4504, 4504, 10, 2013, 0x9502c1e1 -0, 135, 135, 1, 518400, 0x5dffc0d6 +0, 135, 135, 1, 518400, 0x3c83c5ce 1, 4514, 4514, 10, 2013, 0xf7c78ab2 1, 4524, 4524, 10, 2013, 0x24049816 1, 4534, 4534, 10, 2013, 0x52089dcf -0, 136, 136, 1, 518400, 0x3f85c053 +0, 136, 136, 1, 518400, 0xfa22c508 1, 4550, 4550, 10, 2013, 0x2150a0b1 1, 4560, 4560, 10, 2013, 0x3c2e9b93 1, 4570, 4570, 10, 2013, 0x491f932b -0, 137, 137, 1, 518400, 0x7124125d +0, 137, 137, 1, 518400, 0xddda1712 1, 4580, 4580, 10, 2013, 0x31359cf8 1, 4590, 4590, 10, 2013, 0x1b00ac3f 1, 4600, 4600, 10, 2013, 0x8d7ab3cb -0, 138, 138, 1, 518400, 0x46b736d5 +0, 138, 138, 1, 518400, 0x985a3b93 1, 4610, 4610, 10, 2013, 0xb2c2a4de 1, 4620, 4620, 10, 2013, 0x80a4abf2 1, 4635, 4635, 10, 2013, 0x0701a4ee -0, 139, 139, 1, 518400, 0x7bcac123 +0, 139, 139, 1, 518400, 0xea63c5e7 1, 4645, 4645, 10, 2013, 0xdc1ba5bc 1, 4655, 4655, 10, 2013, 0x6083a8a4 1, 4665, 4665, 10, 2013, 0x6226ad45 -0, 140, 140, 1, 518400, 0x79899382 +0, 140, 140, 1, 518400, 0xef64983d 1, 4675, 4675, 10, 2013, 0x2732a205 1, 4685, 4685, 10, 2013, 0x0f62a0d3 1, 4695, 4695, 10, 2013, 0xc1799249 -0, 141, 141, 1, 518400, 0x4a56acef +0, 141, 141, 1, 518400, 0x747bb193 1, 4705, 4705, 10, 2013, 0xbccfa9c8 1, 4720, 4720, 10, 2013, 0xded096e7 1, 4730, 4730, 10, 2013, 0x7f0daf43 -0, 142, 142, 1, 518400, 0xb0a983e5 +0, 142, 142, 1, 518400, 0xb8748862 1, 4740, 4740, 10, 2013, 0xc47ea682 1, 4750, 4750, 10, 2013, 0x5a72b07a 1, 4760, 4760, 10, 2013, 0x386faa8c 1, 4770, 4770, 10, 2013, 0xf9919a91 -0, 143, 143, 1, 518400, 0xb49255cc +0, 143, 143, 1, 518400, 0xaab55a5f 1, 4780, 4780, 10, 2013, 0x4908897e 1, 4790, 4790, 10, 2013, 0x4882b594 -0, 144, 144, 1, 518400, 0x48808663 +0, 144, 144, 1, 518400, 0x7b468add 1, 4806, 4806, 10, 2013, 0x113e98d1 1, 4816, 4816, 10, 2013, 0x5098b30d 1, 4826, 4826, 10, 2013, 0x0ef7b857 1, 4836, 4836, 10, 2013, 0x216ea176 -0, 145, 145, 1, 518400, 0xf5be828c +0, 145, 145, 1, 518400, 0xf2078707 1, 4846, 4846, 10, 2013, 0xf906944a 1, 4856, 4856, 10, 2013, 0xee9b92fb 1, 4866, 4866, 10, 2013, 0xd6029209 -0, 146, 146, 1, 518400, 0xb6688ea3 +0, 146, 146, 1, 518400, 0x6a2d931e 1, 4876, 4876, 10, 2013, 0x2256a12e 1, 4891, 4891, 10, 2013, 0x89de8e4a 1, 4901, 4901, 10, 2013, 0x0bf0a584 -0, 147, 147, 1, 518400, 0x9eb2bfd1 +0, 147, 147, 1, 518400, 0xbbe3c417 1, 4911, 4911, 10, 2013, 0x6a5ebd58 1, 4921, 4921, 10, 2013, 0x3edd9aa4 1, 4931, 4931, 10, 2013, 0xbd66ac26 -0, 148, 148, 1, 518400, 0xab3bdfb5 +0, 148, 148, 1, 518400, 0x6294e449 1, 4941, 4941, 10, 2013, 0x313896ea 1, 4951, 4951, 10, 2013, 0x6b83a6a0 1, 4961, 4961, 10, 2013, 0x9aafb109 -0, 149, 149, 1, 518400, 0xe65f1d81 +0, 149, 149, 1, 518400, 0xa05721e7 1, 4976, 4976, 10, 2013, 0x5192a85a 1, 4986, 4986, 10, 2013, 0x1f919f79 1, 4996, 4996, 10, 2013, 0xc0799c40 -0, 150, 150, 1, 518400, 0x61ca8d13 +0, 150, 150, 1, 518400, 0x37749183 1, 5006, 5006, 10, 2013, 0x2988bcd8 1, 5016, 5016, 10, 2013, 0x1482913a 1, 5026, 5026, 10, 2013, 0x74da9a94 1, 5036, 5036, 10, 2013, 0x763eb709 -0, 151, 151, 1, 518400, 0xbdd0d82f +0, 151, 151, 1, 518400, 0xf9d9dca0 1, 5046, 5046, 10, 2013, 0x1285b405 1, 5062, 5062, 10, 2013, 0xb6ab9dfc -0, 152, 152, 1, 518400, 0xab1acaad +0, 152, 152, 1, 518400, 0x5f8ccf08 1, 5072, 5072, 10, 2013, 0xe4c8bf19 1, 5082, 5082, 10, 2013, 0xabbbade8 1, 5092, 5092, 10, 2013, 0xf8b69d89 1, 5102, 5102, 10, 2013, 0xce04a866 -0, 153, 153, 1, 518400, 0x1889f31c +0, 153, 153, 1, 518400, 0x7303f77b 1, 5112, 5112, 10, 2013, 0x07528abf 1, 5122, 5122, 10, 2013, 0x74fb98bf 1, 5132, 5132, 10, 2013, 0x579fb1c9 -0, 154, 154, 1, 518400, 0x02484cce +0, 154, 154, 1, 518400, 0x22b0513f 1, 5147, 5147, 10, 2013, 0x7ddea2ed 1, 5157, 5157, 10, 2013, 0x296caa2c 1, 5167, 5167, 10, 2013, 0x346d9c4f -0, 155, 155, 1, 518400, 0x59998165 +0, 155, 155, 1, 518400, 0x330485d2 1, 5177, 5177, 10, 2013, 0x3e1fba15 1, 5187, 5187, 10, 2013, 0x48a2908f 1, 5197, 5197, 10, 2013, 0xc1938d09 -0, 156, 156, 1, 518400, 0x0f3dd671 +0, 156, 156, 1, 518400, 0x7f83daea 1, 5207, 5207, 10, 2013, 0x0e96a060 1, 5217, 5217, 10, 2013, 0x7b6a9e06 1, 5232, 5232, 10, 2013, 0x5b779d28 -0, 157, 157, 1, 518400, 0x378bee63 +0, 157, 157, 1, 518400, 0xee19f2df 1, 5242, 5242, 10, 2013, 0xf600aca1 1, 5252, 5252, 10, 2013, 0x3a6c9e68 1, 5262, 5262, 10, 2013, 0x0c8dc1b0 -0, 158, 158, 1, 518400, 0x0d8e17d2 +0, 158, 158, 1, 518400, 0xb71b1c77 1, 5272, 5272, 10, 2013, 0x26beb245 1, 5282, 5282, 10, 2013, 0x2bc09557 1, 5292, 5292, 10, 2013, 0x27fc8845 1, 5302, 5302, 10, 2013, 0x1025aa47 -0, 159, 159, 1, 518400, 0x61f113bf +0, 159, 159, 1, 518400, 0xbffc1856 1, 5318, 5318, 10, 2013, 0xc2e69baa 1, 5328, 5328, 10, 2013, 0xdb249b92 1, 5338, 5338, 10, 2013, 0x6ccda29e -0, 160, 160, 1, 518400, 0x44ec211a +0, 160, 160, 1, 518400, 0xabc125aa 1, 5348, 5348, 10, 2013, 0xeaf6a1cf 1, 5358, 5358, 10, 2013, 0x509ba397 1, 5368, 5368, 10, 2013, 0xfaf8a2df -0, 161, 161, 1, 518400, 0xcb036306 +0, 161, 161, 1, 518400, 0x5ee467f8 1, 5378, 5378, 10, 2013, 0x41388f28 1, 5388, 5388, 10, 2013, 0xfe5eab39 1, 5403, 5403, 10, 2013, 0xd5ffa066 -0, 162, 162, 1, 518400, 0x7f1dec7d +0, 162, 162, 1, 518400, 0x6c2cf168 1, 5413, 5413, 10, 2013, 0x6813a30a 1, 5423, 5423, 10, 2013, 0x9be89718 1, 5433, 5433, 10, 2013, 0xaec3a27b -0, 163, 163, 1, 518400, 0x8b8c6640 +0, 163, 163, 1, 518400, 0x63996b26 1, 5446, 5446, 10, 2013, 0x579a983e 1, 5456, 5456, 10, 2013, 0x98cea21f 1, 5466, 5466, 10, 2013, 0xca77a58a -0, 164, 164, 1, 518400, 0xea04737c +0, 164, 164, 1, 518400, 0xb34d789a 1, 5476, 5476, 10, 2013, 0xcbc3b1ee 1, 5486, 5486, 10, 2013, 0xf3bb8f07 1, 5496, 5496, 10, 2013, 0x6aeebd92 -0, 165, 165, 1, 518400, 0xe779fe0c +0, 165, 165, 1, 518400, 0xf49c030f 1, 5506, 5506, 10, 2013, 0xe955a449 1, 5516, 5516, 10, 2013, 0x9436aa5b 1, 5531, 5531, 10, 2013, 0x4f0a8f9f -0, 166, 166, 1, 518400, 0xcd78bf13 +0, 166, 166, 1, 518400, 0x092dc41a 1, 5541, 5541, 10, 2013, 0x3551b22d 1, 5551, 5551, 10, 2013, 0x0959a3d4 1, 5561, 5561, 10, 2013, 0x2ed5a11b 1, 5571, 5571, 10, 2013, 0x8f52a5c3 -0, 167, 167, 1, 518400, 0x45b0c048 +0, 167, 167, 1, 518400, 0x4134c577 1, 5581, 5581, 10, 2013, 0x6552978d 1, 5591, 5591, 10, 2013, 0x7dcca0c1 1, 5601, 5601, 10, 2013, 0xbcd4a3c9 -0, 168, 168, 1, 518400, 0x9783dcd8 +0, 168, 168, 1, 518400, 0x261de1ed 1, 5616, 5616, 10, 2013, 0xfe41a8d8 1, 5626, 5626, 10, 2013, 0xc85aae14 1, 5636, 5636, 10, 2013, 0x1185b346 -0, 169, 169, 1, 518400, 0xbcd1514c +0, 169, 169, 1, 518400, 0xcbc8566a 1, 5646, 5646, 10, 2013, 0xf7429a0d 1, 5656, 5656, 10, 2013, 0x48c2a160 1, 5666, 5666, 10, 2013, 0x9d85a85d -0, 170, 170, 1, 518400, 0xf229575f +0, 170, 170, 1, 518400, 0x407a5c76 1, 5676, 5676, 10, 2013, 0xbbe89fe9 1, 5686, 5686, 10, 2013, 0xea429fe2 1, 5702, 5702, 10, 2013, 0x221ca1d4 -0, 171, 171, 1, 518400, 0x576e365e +0, 171, 171, 1, 518400, 0x1ed73bb2 1, 5712, 5712, 10, 2013, 0x394b925b 1, 5722, 5722, 10, 2013, 0x556dc26f 1, 5732, 5732, 10, 2013, 0xce21a5e1 -0, 172, 172, 1, 518400, 0xa2d2d87b +0, 172, 172, 1, 518400, 0x8467ddb5 1, 5742, 5742, 10, 2013, 0xbc87c0a8 1, 5752, 5752, 10, 2013, 0xbac4ac07 1, 5762, 5762, 10, 2013, 0xdeefa4aa 1, 5772, 5772, 10, 2013, 0x1f15b362 -0, 173, 173, 1, 518400, 0x3804d74a +0, 173, 173, 1, 518400, 0x0523dc73 1, 5787, 5787, 10, 2013, 0x6406b7b2 1, 5797, 5797, 10, 2013, 0x8030a03d -0, 174, 174, 1, 518400, 0xf05de372 +0, 174, 174, 1, 518400, 0x81f5e895 1, 5807, 5807, 10, 2013, 0x0373a5b1 1, 5817, 5817, 10, 2013, 0x34ef93da 1, 5827, 5827, 10, 2013, 0x94c198fe 1, 5837, 5837, 10, 2013, 0xfefcabad -0, 175, 175, 1, 518400, 0x21035b4f +0, 175, 175, 1, 518400, 0xfc74608d 1, 5847, 5847, 10, 2013, 0x8755b3ec 1, 5857, 5857, 10, 2013, 0xe436a6fd 1, 5872, 5872, 10, 2013, 0x9cf5a11e -0, 176, 176, 1, 518400, 0x6e97d583 +0, 176, 176, 1, 518400, 0xc4e0dae0 1, 5882, 5882, 10, 2013, 0x03b8a98c 1, 5892, 5892, 10, 2013, 0x6216a138 1, 5902, 5902, 10, 2013, 0xd87b9f12 -0, 177, 177, 1, 518400, 0x197879a9 +0, 177, 177, 1, 518400, 0x98367f5b 1, 5912, 5912, 10, 2013, 0x4ce99653 1, 5922, 5922, 10, 2013, 0x6c2ea9e2 1, 5932, 5932, 10, 2013, 0x918cae4c -0, 178, 178, 1, 518400, 0x787780ee +0, 178, 178, 1, 518400, 0x0f1a869d 1, 5942, 5942, 10, 2013, 0xd19fa5f2 1, 5958, 5958, 10, 2013, 0x0bdda7c6 1, 5968, 5968, 10, 2013, 0x0f9ab0ca -0, 179, 179, 1, 518400, 0x13fcc74d +0, 179, 179, 1, 518400, 0x45b6ccf2 1, 5978, 5978, 10, 2013, 0x410a92b1 1, 5988, 5988, 10, 2013, 0xcfbe9d1c 1, 5998, 5998, 10, 2013, 0x59ed9d15 -0, 180, 180, 1, 518400, 0x9bd1c5da +0, 180, 180, 1, 518400, 0x5f9ccb77 1, 6008, 6008, 10, 2013, 0x4e129e27 1, 6018, 6018, 10, 2013, 0x7bb9ac0a 1, 6028, 6028, 10, 2013, 0x826ca82b -0, 181, 181, 1, 518400, 0x8e21e4ba +0, 181, 181, 1, 518400, 0x5f15ea31 1, 6043, 6043, 10, 2013, 0x9ad5a74b 1, 6053, 6053, 10, 2013, 0x6c5f969a 1, 6063, 6063, 10, 2013, 0x8479a0e5 -0, 182, 182, 1, 518400, 0x5fe59996 +0, 182, 182, 1, 518400, 0x86369f27 1, 6073, 6073, 10, 2013, 0x165298ef 1, 6083, 6083, 10, 2013, 0xdcadb4a1 1, 6093, 6093, 10, 2013, 0xa90e987c 1, 6103, 6103, 10, 2013, 0x1ac5b510 -0, 183, 183, 1, 518400, 0x308af432 +0, 183, 183, 1, 518400, 0x2e27f9fa 1, 6113, 6113, 10, 2013, 0x66728d85 1, 6128, 6128, 10, 2013, 0xe4859fc5 1, 6138, 6138, 10, 2013, 0x9901786e -0, 184, 184, 1, 518400, 0xc05a9eb1 +0, 184, 184, 1, 518400, 0xc029a44d 1, 6148, 6148, 10, 2013, 0x6aebb406 1, 6158, 6158, 10, 2013, 0x7d13a2cc 1, 6168, 6168, 10, 2013, 0x99b7a8cc -0, 185, 185, 1, 518400, 0xb9a02e51 +0, 185, 185, 1, 518400, 0xebee33b0 1, 6178, 6178, 10, 2013, 0x80b8a624 1, 6188, 6188, 10, 2013, 0xbb6aa271 1, 6198, 6198, 10, 2013, 0x17af9e4a -0, 186, 186, 1, 518400, 0xbd9543aa +0, 186, 186, 1, 518400, 0x19e5494f 1, 6214, 6214, 10, 2013, 0xfaf0a8f1 1, 6224, 6224, 10, 2013, 0xd6849b93 1, 6234, 6234, 10, 2013, 0xe9829669 -0, 187, 187, 1, 518400, 0x0a0cb795 +0, 187, 187, 1, 518400, 0xf697bd7c 1, 6244, 6244, 10, 2013, 0x7ec98944 1, 6254, 6254, 10, 2013, 0x2b2099a4 1, 6264, 6264, 10, 2013, 0x1033a82f -0, 188, 188, 1, 518400, 0xe4bb8a0c +0, 188, 188, 1, 518400, 0x82569002 1, 6274, 6274, 10, 2013, 0x5ec88990 1, 6284, 6284, 10, 2013, 0xd2a19b3d 1, 6299, 6299, 10, 2013, 0xa377b268 -0, 189, 189, 1, 518400, 0x226fd11e +0, 189, 189, 1, 518400, 0xfcb6d707 1, 6309, 6309, 10, 2013, 0xfa859901 1, 6319, 6319, 10, 2013, 0x1713955a 1, 6329, 6329, 10, 2013, 0x70aab0da 1, 6339, 6339, 10, 2013, 0xcdaea422 -0, 190, 190, 1, 518400, 0x76e1604d +0, 190, 190, 1, 518400, 0x82a9662b 1, 6349, 6349, 10, 2013, 0x65c3bf80 1, 6359, 6359, 10, 2013, 0x1d75a55f 1, 6369, 6369, 10, 2013, 0xa5bea4de -0, 191, 191, 1, 518400, 0xca06117c +0, 191, 191, 1, 518400, 0x212e16ee 1, 6384, 6384, 10, 2013, 0x184db71c 1, 6394, 6394, 10, 2013, 0x99858ec8 1, 6404, 6404, 10, 2013, 0xb8f2aee5 -0, 192, 192, 1, 518400, 0xeca14952 +0, 192, 192, 1, 518400, 0x2ca34dca 1, 6414, 6414, 10, 2013, 0x4435b2ef 1, 6424, 6424, 10, 2013, 0x8acfa6c7 1, 6434, 6434, 10, 2013, 0x42b4c01f -0, 193, 193, 1, 518400, 0x3106dbee +0, 193, 193, 1, 518400, 0xe9ebe0a5 1, 6444, 6444, 10, 2013, 0x6e308c13 1, 6454, 6454, 10, 2013, 0x8227a0f6 1, 6470, 6470, 10, 2013, 0x6f12a7a2 -0, 194, 194, 1, 518400, 0x57fa6392 +0, 194, 194, 1, 518400, 0x4e6b6917 1, 6480, 6480, 10, 2013, 0x785392be 1, 6490, 6490, 10, 2013, 0x81849c2b 1, 6500, 6500, 10, 2013, 0x5cf2af65 -0, 195, 195, 1, 518400, 0x47651ac8 +0, 195, 195, 1, 518400, 0x7dcf20ab 1, 6510, 6510, 10, 2013, 0x0c6ca6b4 1, 6520, 6520, 10, 2013, 0x412fab9f 1, 6530, 6530, 10, 2013, 0x08e792b4 -0, 196, 196, 1, 518400, 0x3c1ba6a5 +0, 196, 196, 1, 518400, 0xf30fac97 1, 6540, 6540, 10, 2013, 0x407aace3 1, 6555, 6555, 10, 2013, 0xd26bac16 1, 6565, 6565, 10, 2013, 0xac8bb295 -0, 197, 197, 1, 518400, 0xbc3ec05b +0, 197, 197, 1, 518400, 0xcb9fc692 1, 6575, 6575, 10, 2013, 0xddd1949c 1, 6585, 6585, 10, 2013, 0x6b26b868 1, 6595, 6595, 10, 2013, 0x5eaba587 1, 6605, 6605, 10, 2013, 0xef0793b9 -0, 198, 198, 1, 518400, 0xd6ae59da +0, 198, 198, 1, 518400, 0x5d05601e 1, 6615, 6615, 10, 2013, 0xdef19bd6 1, 6625, 6625, 10, 2013, 0xca98a635 -0, 199, 199, 1, 518400, 0xc62f0e63 +0, 199, 199, 1, 518400, 0x456c1417 1, 6640, 6640, 10, 2013, 0x06269a5a 1, 6650, 6650, 10, 2013, 0x32cb9952 1, 6660, 6660, 10, 2013, 0xf01fa95a 1, 6670, 6670, 10, 2013, 0xefab9e55 -0, 200, 200, 1, 518400, 0xae96cc02 +0, 200, 200, 1, 518400, 0x9a0fd1ad 1, 6680, 6680, 10, 2013, 0x55a3b63a 1, 6690, 6690, 10, 2013, 0xcd36a553 1, 6700, 6700, 10, 2013, 0x2ec19877 -0, 201, 201, 1, 518400, 0x2aa0917b +0, 201, 201, 1, 518400, 0x55db9716 1, 6710, 6710, 10, 2013, 0xc18b924c 1, 6726, 6726, 10, 2013, 0xf132b04c 1, 6736, 6736, 10, 2013, 0x7975a44d -0, 202, 202, 1, 518400, 0xf0d13b48 +0, 202, 202, 1, 518400, 0x1f0d40d6 1, 6746, 6746, 10, 2013, 0x2aaf94cb 1, 6756, 6756, 10, 2013, 0x58cfa60f 1, 6766, 6766, 10, 2013, 0x9757a658 -0, 203, 203, 1, 518400, 0x067f56f8 +0, 203, 203, 1, 518400, 0x73695c82 1, 6776, 6776, 10, 2013, 0x67ebc0d5 1, 6786, 6786, 10, 2013, 0x3c50a70e 1, 6796, 6796, 10, 2013, 0x9c5799c6 -0, 204, 204, 1, 518400, 0x1026025c +0, 204, 204, 1, 518400, 0xb0f10812 1, 6811, 6811, 10, 2013, 0x018d85b2 1, 6821, 6821, 10, 2013, 0x5367a956 -0, 205, 205, 1, 518400, 0x11ee7f7f -0, 208, 208, 1, 518400, 0x30a6b398 +0, 205, 205, 1, 518400, 0xdec18505 +0, 208, 208, 1, 518400, 0xb147b947 0, 240, 240, 1, 518400, 0x9d2e3977 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-overlay_gbrap_gbrap ffmpeg-4.4/tests/ref/fate/filter-overlay_gbrap_gbrap --- ffmpeg-4.2.2/tests/ref/fate/filter-overlay_gbrap_gbrap 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-overlay_gbrap_gbrap 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 128x128 #sar 0: 1/1 -0, 0, 0, 1, 65536, 0xbac99946 +0, 0, 0, 1, 65536, 0x821bcb9b diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-overlay_gbrp_gbrap ffmpeg-4.4/tests/ref/fate/filter-overlay_gbrp_gbrap --- ffmpeg-4.2.2/tests/ref/fate/filter-overlay_gbrp_gbrap 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-overlay_gbrp_gbrap 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 128x128 #sar 0: 1/1 -0, 0, 0, 1, 49152, 0xa905d586 +0, 0, 0, 1, 49152, 0x738d07ea diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuv420p10 ffmpeg-4.4/tests/ref/fate/filter-overlay_yuv420p10 --- ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuv420p10 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-overlay_yuv420p10 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,8 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 304128, 0x29a6ca86 +0, 1, 1, 1, 304128, 0x82950e6f +0, 2, 2, 1, 304128, 0x8363d1d8 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuv420_yuva420 ffmpeg-4.4/tests/ref/fate/filter-overlay_yuv420_yuva420 --- ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuv420_yuva420 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-overlay_yuv420_yuva420 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 128x128 #sar 0: 1/1 -0, 0, 0, 1, 24576, 0x1505f000 +0, 0, 0, 1, 24576, 0xf104fedd diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuv422p10 ffmpeg-4.4/tests/ref/fate/filter-overlay_yuv422p10 --- ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuv422p10 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-overlay_yuv422p10 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,8 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 405504, 0x11108b36 +0, 1, 1, 1, 405504, 0x9d5f7c2a +0, 2, 2, 1, 405504, 0x25373098 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuv422_yuva422 ffmpeg-4.4/tests/ref/fate/filter-overlay_yuv422_yuva422 --- ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuv422_yuva422 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-overlay_yuv422_yuva422 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 128x128 #sar 0: 1/1 -0, 0, 0, 1, 32768, 0x2d88b114 +0, 0, 0, 1, 32768, 0x180ac096 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuv444_yuva444 ffmpeg-4.4/tests/ref/fate/filter-overlay_yuv444_yuva444 --- ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuv444_yuva444 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-overlay_yuv444_yuva444 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 128x128 #sar 0: 1/1 -0, 0, 0, 1, 49152, 0x92da3b63 +0, 0, 0, 1, 49152, 0x42ec4c43 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuva420_yuva420 ffmpeg-4.4/tests/ref/fate/filter-overlay_yuva420_yuva420 --- ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuva420_yuva420 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-overlay_yuva420_yuva420 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 128x128 #sar 0: 1/1 -0, 0, 0, 1, 40960, 0x0a1ab3c0 +0, 0, 0, 1, 40960, 0x5de1c29d diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuva422_yuva422 ffmpeg-4.4/tests/ref/fate/filter-overlay_yuva422_yuva422 --- ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuva422_yuva422 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-overlay_yuva422_yuva422 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 128x128 #sar 0: 1/1 -0, 0, 0, 1, 49152, 0x369974d4 +0, 0, 0, 1, 49152, 0xdb3b8456 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuva444_yuva444 ffmpeg-4.4/tests/ref/fate/filter-overlay_yuva444_yuva444 --- ffmpeg-4.2.2/tests/ref/fate/filter-overlay_yuva444_yuva444 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-overlay_yuva444_yuva444 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 128x128 #sar 0: 1/1 -0, 0, 0, 1, 65536, 0xa279ff14 +0, 0, 0, 1, 65536, 0x91d31003 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-gbrapf32be ffmpeg-4.4/tests/ref/fate/filter-pixdesc-gbrapf32be --- ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-gbrapf32be 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixdesc-gbrapf32be 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +pixdesc-gbrapf32be a4fd00f17d746849f30597c496923107 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-gbrapf32le ffmpeg-4.4/tests/ref/fate/filter-pixdesc-gbrapf32le --- ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-gbrapf32le 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixdesc-gbrapf32le 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +pixdesc-gbrapf32le 26af38a6975e2ce425e9fec477e6b2ba diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-gbrpf32be ffmpeg-4.4/tests/ref/fate/filter-pixdesc-gbrpf32be --- ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-gbrpf32be 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixdesc-gbrpf32be 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +pixdesc-gbrpf32be 3ee0b82f5aaea48ca3c01f4294505d73 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-gbrpf32le ffmpeg-4.4/tests/ref/fate/filter-pixdesc-gbrpf32le --- ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-gbrpf32le 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixdesc-gbrpf32le 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +pixdesc-gbrpf32le 0e6b20215ac9b475e917c7bb4cbee349 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-x2rgb10le ffmpeg-4.4/tests/ref/fate/filter-pixdesc-x2rgb10le --- ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-x2rgb10le 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixdesc-x2rgb10le 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1 @@ +pixdesc-x2rgb10le 98d697ed4668daf535163d5e08c903bb diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-ya16be ffmpeg-4.4/tests/ref/fate/filter-pixdesc-ya16be --- ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-ya16be 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixdesc-ya16be 2020-07-11 10:39:30.000000000 +0000 @@ -1 +1 @@ -pixdesc-ya16be c5bf539478020302a30f36c5059b7695 +pixdesc-ya16be 86059502198a6d6febb5558e984a30fb diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-ya16le ffmpeg-4.4/tests/ref/fate/filter-pixdesc-ya16le --- ffmpeg-4.2.2/tests/ref/fate/filter-pixdesc-ya16le 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixdesc-ya16le 2020-07-11 10:39:30.000000000 +0000 @@ -1 +1 @@ -pixdesc-ya16le d238b5905b3ab79f7f00d5ea03ee4b87 +pixdesc-ya16le f19f6f76d395a18b88accc83d333cc50 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-copy ffmpeg-4.4/tests/ref/fate/filter-pixfmts-copy --- ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-copy 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixfmts-copy 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,8 @@ gbrap12le 5f1d8c663d4c28863e687192433b34a4 gbrap16be e4edca4361d643794034e5aa9ef290b1 gbrap16le 9a95b389d2bf556179e8f4b27fb550ab +gbrapf32be d908f0950d3735863fe6f0793fa24f76 +gbrapf32le f6eab5a145cffc52c055e07c26d3995f gbrp 5fbc319e30110d19d539f5b274eddb6d gbrp10be 703a17591a2a5c236675c5101c349bcc gbrp10le ee014153f55c011918df5b2394815780 @@ -36,6 +38,8 @@ gbrp16le fb9323a5bd060282bec7bfd7d38dc230 gbrp9be a4dc6f6f9bb051de2dc348b592ad4282 gbrp9le 699da3a3b324f3fd001a56aee9683384 +gbrpf32be ae33c2d738af01ae66a5d2b08a7a60b7 +gbrpf32le 4e3305c619337beeeacc5e6b2f42c793 gray 188590b1231afd231ea910815aef2b25 gray10be d486558ecd2e27afc17930be861f0e4c gray10le 917d687103b2adcca7132bfc070ca54a @@ -76,10 +80,11 @@ rgba64be ae2ae04b5efedca3505f47c4dd6ea6ea rgba64le b91e1d77f799eb92241a2d2d28437b15 uyvy422 3bcf3c80047592f2211fae3260b1b65d +x2rgb10le b0a0c8056521beeaa3fea4985ca87176 xyz12be a1ef56bf746d71f59669c28e48fc8450 xyz12le 831ff03c1ba4ef19374686f16a064d8c -ya16be 2f2c27f1854ac00c73d13861dcab2705 -ya16le 2c1fbd127c9f0435adc0e9b2ea3f486b +ya16be 37c07787e544f900c87b853253bfc8dd +ya16le e8cab8fad88cba6d285b224d8bf0d4df ya8 dbb99fbcdc204aaa1a7397ff561f1a67 yuv410p 5d4d992a7728431aa4e0700f87fb7fd8 yuv411p 7e1300e89f5bc07939e2c4a6acbdf267 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-crop ffmpeg-4.4/tests/ref/fate/filter-pixfmts-crop --- ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-crop 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixfmts-crop 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,8 @@ gbrap12le 3f80453c1ac6c5d1b2febf3ef141b476 gbrap16be 21c98d0d7e7de2a93f9f095e5bb5c227 gbrap16le ea9a96870c1b742dd9f065c5db568184 +gbrapf32be ec06b3b168dc74048100f29a4412da90 +gbrapf32le 57ee44f9ca41e7b5e6410cdd105442d6 gbrp ec671f573c2105072ab68a1933c58fee gbrp10be 6f0130a41f01e58593d3840446dd94b7 gbrp10le 9c152b7dfb7ad7bc477518d97316d04f @@ -36,6 +38,8 @@ gbrp16le 0768a2462783829f63ed0bfd53d01222 gbrp9be 4af43999e5e9742992b6550ea5ad9b23 gbrp9le b4cbfa7878706a14295f09212e41f7fe +gbrpf32be 4f06588a3de6ed0f30436f814eda0909 +gbrpf32le b2a9df783d8c2156c5aafc561989918d gray 0d70b54b4b888ec4dbd89713620ac1ee gray10be 18ed76cab145ab9058cc353fcec6d3c4 gray10le fd83f7489880160783ddb125615b4638 @@ -73,10 +77,11 @@ rgba 9488ac85abceaf99a9309eac5a87697e rgba64be 89910046972ab3c68e2a348302cc8ca9 rgba64le fea8ebfc869b52adf353778f29eac7a7 +x2rgb10le 5c0789f76a713f343c2ed42a371d441d xyz12be cb4571f9aaa7b59f999ef327276104b7 xyz12le cd6aae8d26b18bdb4b9d068586276d91 -ya16be 029a3b7c523de988e3161484d41ea15c -ya16le 32929a08d11982aec66ea1e665cfba3a +ya16be a3d18014454942a96f15a49947c0c55d +ya16le 3d90169aeab9e9637945cf00ab3e95ae ya8 51a8dd297e35d40b06d3ebe8f4717895 yuv410p 3bb6c7b64f2c46bc5e8b77198ce4ea58 yuv411p 693e4afe96998e6dd91734037d75d887 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-field ffmpeg-4.4/tests/ref/fate/filter-pixfmts-field --- ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-field 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixfmts-field 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,8 @@ gbrap12le 886207e5aa379a0312485b94e5fd5edd gbrap16be eaa0158f27ebc40cde9e3d6eef1e2ba1 gbrap16le 6cf68992d4fcac2aa025d1014b669d24 +gbrapf32be 37c627796dee55ca6f4e7ca965460680 +gbrapf32le 3ff02eb8465b921c09182ec5cfda434a gbrp 838025a3062f7f31e99196ce66961ad7 gbrp10be f63c2555ea19fc78b00fd5b3e2b48e8c gbrp10le be64c374ab318235d912372e99a0516a @@ -36,6 +38,8 @@ gbrp16le 0ab77b498d4a39905515b6e1f0329ed2 gbrp9be 170da3a8644cbea61c3caeadc45354c5 gbrp9le da5d80e6f12cabaa7081bb85d3b7fd30 +gbrpf32be cd5b0edd510652a0bcfd7e36935e3cb0 +gbrpf32le 9d42fc5331376b5307268498a06613ce gray 57fd8e6e00f6be8752726005974cce1b gray10be 437713f3d081238cddb738e106e5a27d gray10le c749b80049b152f4ba3e66a72c0c5acc @@ -76,10 +80,11 @@ rgba64be 23c8c0edaabe3eaec89ce69633fb0048 rgba64le dfdba4de4a7cac9abf08852666c341d3 uyvy422 1c49e44ab3f060e85fc4a3a9464f045e +x2rgb10le a7a5dcdfe1d4b6bd71e40b01c735f144 xyz12be d2fa69ec91d3ed862f2dac3f8e7a3437 xyz12le 02bccd5e0b6824779a1f848b0ea3e3b5 -ya16be c0ce74d2a3da641ea634a3898dda7455 -ya16le 9b098d425e5bc27fa8a8ac8b176d592d +ya16be 40403b5277364777e0671da4d38e01ac +ya16le 54f3295f5326a13d456ac53e973ba398 ya8 28cea4f98ed452bd3da9c752e5e3399c yuv410p a85920d6bd26f51306e2ecbe71d1c554 yuv411p 9106e283d5dbcfba01c611886d58871a diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-fieldorder ffmpeg-4.4/tests/ref/fate/filter-pixfmts-fieldorder --- ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-fieldorder 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixfmts-fieldorder 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,8 @@ gbrap12le ae2d6db2c9c825f06d92389de21263d2 gbrap16be 52c10d8046d123dfc4a478276906467c gbrap16le 2317737b8f5140add27d121de8f5ba95 +gbrapf32be 6781751ef9d444d150cb0a1e1cefe141 +gbrapf32le f2ffc9e45dbc9919d516304abb514306 gbrp 506dea2fe492e985a396d1b11ccd8db3 gbrp10be 55bbfe2d472780dcbadf3027778caa0e gbrp10le 13a39077ab1b2c3b49afd3e250b84a77 @@ -36,6 +38,8 @@ gbrp16le c7813a905f94aabb2bcade79c9b7e39e gbrp9be b8d294d4bc81ceef1fb529e917c02e48 gbrp9le 0d42cc9e222d806c33172781b45cb3e3 +gbrpf32be cef1384ac5c95cf4b3ea2e49133dbef0 +gbrpf32le c053b8bf8314196099b1e2e1d0617b75 gray d96e0f1c73d3f0b9506d691b5cd36c73 gray10be c26c73de96b630f1207ff589b6553ebd gray10le 16e4db1d611ec3fa5c9fd8fbdbf1ffcc @@ -67,10 +71,11 @@ rgba64be 5598f44514d122b9a57c5c92c20bbc61 rgba64le b34e6e30621ae579519a2d91a96a0acf uyvy422 75de70e31c435dde878002d3f22b238a +x2rgb10le 636c90498c64abba1cc0624c5209a61f xyz12be 15f5cda71de5fef9cec5e75e3833b6bc xyz12le 7be6c8781f38c21a6b8f602f62ca31e6 -ya16be 205d6a21890c1f057c9c20fbbba590e2 -ya16le f35616fdb5d3fbf767a4f11118cf8ad1 +ya16be 0f13e0f52586d172aaa07710fa3e8f31 +ya16le d481d93ea1a1a04d759d9994958983de ya8 055ac5ab5ff8533dd319edc17a398af1 yuv411p e4a040e0e786c4dae07d9d3f90a54905 yuv422p 16ce67249c6ce7ef57a433646ad6dfc1 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-hflip ffmpeg-4.4/tests/ref/fate/filter-pixfmts-hflip --- ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-hflip 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixfmts-hflip 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,8 @@ gbrap12le 88a85c1b3c5e19e299fdd209b73ac1ba gbrap16be 3117e84b258433a7efb9288bbb8815d4 gbrap16le 3ad08cf8b49d8eb31a1b356ec4b7b88b +gbrapf32be d82e48eb62c1e2d2ce5d614aeda38a99 +gbrapf32le 323259d76d5c5350091704813f22bf57 gbrp 0ecfeca171ba3a1a2ff4e92f572b71cf gbrp10be 774398c2f81757a536c094f16cfc541a gbrp10le e9a6434d691be541f789f850963da181 @@ -36,6 +38,8 @@ gbrp16le 6ce6093b24d09c0edcd55b2d6fec89a0 gbrp9be 174de037c2a9f2b6fb4d9444ae0ff82f gbrp9le ba7c2631fb2967aa909c66509bd243fe +gbrpf32be a53fc24a298bf419051fb57c63cc4cef +gbrpf32le b44dae0881043398bfd704a944094737 gray 8bd4ece1dbf89b20ee785e0515356e07 gray10be 160dd03e30d33379de92c70ee52c01fd gray10le 6baac1da6be3789409b67cd506afe7da @@ -73,10 +77,11 @@ rgba 51961c723ea6707e0a410cd3f21f15d3 rgba64be c910444019f4cfbf4d995227af55da8d rgba64le 0c810d8b3a6bca10321788e1cb145340 +x2rgb10le 9f99dce306383daf25cd1542b2517fef xyz12be 25f90259ff8a226befdaec3dfe82996e xyz12le 926c0791d59aaff61b2778e8ada3316d -ya16be 632b2e6e8e20c3edcfe99356fa7fca9e -ya16le e2ff5a2fb969c70dcc862937f9224873 +ya16be d5b342355bdd9e3197e01b13b7c6301e +ya16le d58f154cbbbff85af9917cdb34e819a4 ya8 4ad5920716de3d2fbbc49f95adb60345 yuv410p c49fd0c55c41185b1580aac77211992b yuv411p c416371077dce13d31bf1dc706111ae7 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-il ffmpeg-4.4/tests/ref/fate/filter-pixfmts-il --- ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-il 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixfmts-il 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,8 @@ gbrap12le e3b5342c8e47820f2de7e2dd61872312 gbrap16be 696c84c8b009c7320cad7f3847bb35da gbrap16le 9bacb81fbbe9cdfd04d71eb55a9719d2 +gbrapf32be 5995aba2bf66254f63d5413cd9860353 +gbrapf32le aab9c11ec483fe28f7156bfeb9f015a3 gbrp dc06edb62e70024a216c8e303b79b328 gbrp10be 321e7f061d8b9b5801221b6cf3c99666 gbrp10le 799ed3afca01076439a0b6785b3dc4bb @@ -36,6 +38,8 @@ gbrp16le c95c9d7c2b19826b73ff1811d9fe6bdb gbrp9be f029d87fa642f4261160471ad27fd53f gbrp9le b310d3cf37f7b41d706155993f8f0584 +gbrpf32be 83722ee41b4397e19bb075ab305147b5 +gbrpf32le 82210a8f9e8708968fa13cf8cf64afe4 gray 52ae18648161ac43144f5c9cd2127786 gray10be 8400dec0eefb172849b785d35fc55674 gray10le b7d6e49e8d1291f2b0a57d55e9478ef1 @@ -75,10 +79,11 @@ rgba64be db70d33aa6c06f3e0a1c77bd11284261 rgba64le a8a2daae04374a27219bc1c890204007 uyvy422 d6ee3ca43356d08c392382b24b22cda5 +x2rgb10le a01ea7dd339e028780e04971012d826d xyz12be 7c7d54c55f136cbbc50b18029f3be0b3 xyz12le 090ba6b1170baf2b1358b43b971d33b0 -ya16be bf2cf1e89c9fdb5bc10425db567ba2da -ya16le 4e9c9097fae615b8a5f4c3b237f752f0 +ya16be 7bc720918bc0132e9717acbde89874e0 +ya16le 61203295a8d39601b841de90f2c9797b ya8 a38d6e288f582f1a04310232ed764afc yuv410p dea1ab8843465adf5b8240b2d98fd85b yuv411p 8bf73777a5ff43c126be274245aceff1 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-null ffmpeg-4.4/tests/ref/fate/filter-pixfmts-null --- ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-null 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixfmts-null 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,8 @@ gbrap12le 5f1d8c663d4c28863e687192433b34a4 gbrap16be e4edca4361d643794034e5aa9ef290b1 gbrap16le 9a95b389d2bf556179e8f4b27fb550ab +gbrapf32be d908f0950d3735863fe6f0793fa24f76 +gbrapf32le f6eab5a145cffc52c055e07c26d3995f gbrp 5fbc319e30110d19d539f5b274eddb6d gbrp10be 703a17591a2a5c236675c5101c349bcc gbrp10le ee014153f55c011918df5b2394815780 @@ -36,6 +38,8 @@ gbrp16le fb9323a5bd060282bec7bfd7d38dc230 gbrp9be a4dc6f6f9bb051de2dc348b592ad4282 gbrp9le 699da3a3b324f3fd001a56aee9683384 +gbrpf32be ae33c2d738af01ae66a5d2b08a7a60b7 +gbrpf32le 4e3305c619337beeeacc5e6b2f42c793 gray 188590b1231afd231ea910815aef2b25 gray10be d486558ecd2e27afc17930be861f0e4c gray10le 917d687103b2adcca7132bfc070ca54a @@ -76,10 +80,11 @@ rgba64be ae2ae04b5efedca3505f47c4dd6ea6ea rgba64le b91e1d77f799eb92241a2d2d28437b15 uyvy422 3bcf3c80047592f2211fae3260b1b65d +x2rgb10le b0a0c8056521beeaa3fea4985ca87176 xyz12be a1ef56bf746d71f59669c28e48fc8450 xyz12le 831ff03c1ba4ef19374686f16a064d8c -ya16be 2f2c27f1854ac00c73d13861dcab2705 -ya16le 2c1fbd127c9f0435adc0e9b2ea3f486b +ya16be 37c07787e544f900c87b853253bfc8dd +ya16le e8cab8fad88cba6d285b224d8bf0d4df ya8 dbb99fbcdc204aaa1a7397ff561f1a67 yuv410p 5d4d992a7728431aa4e0700f87fb7fd8 yuv411p 7e1300e89f5bc07939e2c4a6acbdf267 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-pad ffmpeg-4.4/tests/ref/fate/filter-pixfmts-pad --- ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-pad 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixfmts-pad 2021-04-08 21:28:40.000000000 +0000 @@ -28,8 +28,9 @@ rgb0 78d500c8361ab6423a4826a00268c908 rgb24 17f9e2e0c609009acaf2175c42d4a2a5 rgba b157c90191463d34fb3ce77b36c96386 +x2rgb10le c240f8a8dfa647c57c0974d061c9652a xyz12le 85abf80b77a9236a76ba0b00fcbdea2d -ya16le 17cbe58356d56ff0f0f00280a31e6ca6 +ya16le 940fafa240b9916de5f73cb20a552f24 ya8 5fc0f471207ddf7aa01b07027d56b672 yuv410p cb871dcc1e84a7ef1d21f9237b88cf6e yuv411p aec2c1740de9a62db0d41f4dda9121b0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-scale ffmpeg-4.4/tests/ref/fate/filter-pixfmts-scale --- ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-scale 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixfmts-scale 2021-04-08 21:28:40.000000000 +0000 @@ -19,23 +19,27 @@ bgra64be 4e6a1b9f9c18b881c27d76611d45f737 bgra64le efeee0abcc658ebcff049d5e74d74943 gbrap 4a100f750ac846b34bfeef0d6893c3de -gbrap10be 6d89abb9248006c3e9017545e9474654 -gbrap10le cf974e23f485a10740f5de74a5c8c3df -gbrap12be 1d9b57766ba9c2192403f43967cb9af0 -gbrap12le bb1ba1c157717db3dd612a76d38a018e -gbrap16be c72b935a6e57a8e1c37bff08c2db55b1 -gbrap16le 13eb0e62b1ac9c1c86c81521eaefab5f +gbrap10be dc6aea3559ea4fcdda1ccc4f23d2f2fb +gbrap10le 6e1cba57029fdf0f9d46b5e5cd55112b +gbrap12be dbe3a662c016563529032cd4dfb80262 +gbrap12le 24f5ecb32435b73353517e017c165e31 +gbrap16be 31968e6872a46e8174fb57f8920ed10d +gbrap16le 8c6758f33671b673b6d30969fc05a23d +gbrapf32be 366b804d5697276e8c481c4bdf05a00b +gbrapf32le 558a268e6d6b907449d1056afab78f29 gbrp dc3387f925f972c61aae7eb23cdc19f0 -gbrp10be 0277d4c3a8498d75e2783fb81379e481 -gbrp10le f3d70f8ab845c3c9b8f7452e4a6e285a -gbrp12be fbd4e149c452c351c6d1c11d6b6e176a -gbrp12le c51d51c3b753d735eb22983397262c88 -gbrp14be cd20808592e62cc439786c18a14b3e70 -gbrp14le 456f7d1ff5990aa6379137d84dd63862 -gbrp16be 5fc826cfabebfc1442cb793c4b6303e2 -gbrp16le 1b3e0b63d47a3e1b6b20931316883bf2 -gbrp9be d9c88968001e1452ff31fbc8d16b18a0 -gbrp9le 2ccfed0816bf6bd4bb3a5b7591d9603a +gbrp10be a318ea42e53a7b80a55aa7c19c9a0ab5 +gbrp10le 994e8fc6a1e5b230f4c55893fd7618d6 +gbrp12be bfbd419dd18c0a5677d4bce55ab24e2e +gbrp12le 95af1f8495b2a7a7ad67802e3e8bca01 +gbrp14be 9d8113c9a5182c02dbe4576509f59a96 +gbrp14le 952f39881e500ed684c8b216185f4b80 +gbrp16be 5241eee3465096efa111b86b30c3aaaa +gbrp16le 5b8b997378ce31207f37059dbfb40c4a +gbrp9be d7caf58cc3a74a036e11f924f03fc04c +gbrp9le 010f7bcd8b2e17065d01a09f0d483218 +gbrpf32be f3d0cefdf11c861001880772d817aac8 +gbrpf32le 290468205c1c18a0667edfca45061aee gray 221201cc7cfc4964eacd8b3e426fd276 gray10be 9452756d0b37f4f5c7cae7635e22d747 gray10le 37fd2e1ec6b66410212d39a342e864df @@ -76,10 +80,11 @@ rgba64be ee73e57923af984b31cc7795d13929da rgba64le 783d2779adfafe3548bdb671ec0de69e uyvy422 aeb4ba4f9f003ae21f6d18089198244f +x2rgb10le 591fe7942544c8fc40e5d30e0e589f49 xyz12be c7ba8345998c0141ddc079cdd29b1a40 xyz12le 95f5d3a0de834cc495c9032a14987cde -ya16be 372195dc947eee1bcb6f733a3544272e -ya16le 3923551514cfa588cf528e6f48e8cb9a +ya16be 20d4842899d61068f5fb6af478bf26a6 +ya16le 6a05895adce85143ae1c1b3470cb4070 ya8 0a9db5bb4b009de9197eede5e9d19e16 yuv410p e8f49b5fb9335b62c074f7f8bb0234fc yuv411p 5af32557c93beb482e26e7af693104c6 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-transpose ffmpeg-4.4/tests/ref/fate/filter-pixfmts-transpose --- ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-transpose 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixfmts-transpose 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,8 @@ gbrap12le 714fe318af81a46f83655c6e7e13351e gbrap16be 39d488528aacff466aac7539c9b948a8 gbrap16le 5426ac9457289927bfe2ec03038a8780 +gbrapf32be ea02b3912372c8671ff4eacbcbda740a +gbrapf32le 3021d477bdbeba4e2ae7a6bc6cff33e5 gbrp 7b4b6a2f1cdc51455b25515c3ecea944 gbrp10be d7401725699b2ddf954caa16a0878a1e gbrp10le 6036711969eae1979be6358f688bd9c8 @@ -36,6 +38,8 @@ gbrp16le a1c09038fa4636c9843ab8dd2b7601ea gbrp9be df381b4b27be25d172fa556434478807 gbrp9le a5301e978f68b29bfc613b2462ec4888 +gbrpf32be b90d6189e71afd6ec1f379489884cc8e +gbrpf32le 48dee2c9cee8ac6582492fd1c7acb183 gray c5f8bc6636fd15dbc57deb4bba1e7379 gray10be 48b421da79c195fd91dffb8fca79a8a2 gray10le 7774e3296916b896afa46f626334a280 @@ -72,10 +76,11 @@ rgba 4d76a9542143752a4ac30f82f88f68f1 rgba64be a60041217f4c0cd796d19d3940a12a41 rgba64le ad47197774858858ae7b0c177dffa459 +x2rgb10le a64d4d901b09bea9d59eda58be5e88ff xyz12be 68e5cba640f6e4ef72dff950e88b5342 xyz12le 8b6b6a6db4d7561e80db88ccaecce7a9 -ya16be 41b7ad48693e3ce8b4d3220016ef6b15 -ya16le 8ea70315667011a6ed50b6750f42b142 +ya16be 3e161cb5f225922a80fefdc9cc02a4f9 +ya16le 5b3f6c06850b1678cbfc2c79cc448547 ya8 d4b7a62f80681fa44c977ff3a64f4ce4 yuv410p 4c0143429edd30aa01493447c90132ea yuv420p 2fa5b2201c75034206cc20e2c6134aed diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-vflip ffmpeg-4.4/tests/ref/fate/filter-pixfmts-vflip --- ffmpeg-4.2.2/tests/ref/fate/filter-pixfmts-vflip 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pixfmts-vflip 2021-04-08 21:28:40.000000000 +0000 @@ -25,6 +25,8 @@ gbrap12le 6ef8a3ac4129ec23c34aec14ac41f249 gbrap16be 70b020b6b9e1896b72f890de3570ffda gbrap16le e0cf341cdbaf1f5c40016f181bc9d7d4 +gbrapf32be e82323abcb665014346a3a34a4b084c3 +gbrapf32le b24471278a899eb2f9cb563632d29b09 gbrp 413b0f6ea51588d4be5f0c76d43d8796 gbrp10be d02bd50db83213667808f5bacefe667c gbrp10le 2d4a5ebc773ffc3d857a6ef24afbe10e @@ -36,6 +38,8 @@ gbrp16le f3b2b76fe707f77eb1376640759f5168 gbrp9be 99c694dd47d12ae48fc8f47a0c410333 gbrp9le 26e103a4ab99fb3f58667df490997a36 +gbrpf32be 3eaa2d475754c2b4ae3c59dbdb7ccd84 +gbrpf32le 0267e215c3d11ae22414c3e29e665896 gray 41811422d5819ed69389357294384c10 gray10be 52710b3ab3ccf6101d28109f58cd48c4 gray10le 9c432a163f0cfe9ee2a4b72ae8a7c307 @@ -76,10 +80,11 @@ rgba64be 17e6273323b5779b5f3f775f150c1011 rgba64le 48f45b10503b7dd140329c3dd0d54c98 uyvy422 3a237e8376264e0cfa78f8a3fdadec8a +x2rgb10le 332a6f5f5012008a562cb031836da028 xyz12be 810644e008deb231850d779aaa27cc7e xyz12le 829701db461b43533cf9241e0743bc61 -ya16be 01fa2780505ce1bd187ae7f9dcc5fcc3 -ya16le 492f528782acf22769b0b633187be212 +ya16be 55b1dbbe4d56ed0d22461685ce85520d +ya16le d5bf02471823a16dc523a46cace0101a ya8 4299c6ca3b470a7d8a420e26eb485b1d yuv410p c7adfe96c8e043a6cb9290c39bf8063c yuv411p 3fce29db403a25f81be39e01aaf6ff3a diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-pp7 ffmpeg-4.4/tests/ref/fate/filter-pp7 --- ffmpeg-4.2.2/tests/ref/fate/filter-pp7 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-pp7 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,10 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 1/1 +0, 1, 1, 1, 152064, 0x4c5d7fe0 +0, 2, 2, 1, 152064, 0xc8857ae1 +0, 3, 3, 1, 152064, 0x3232f092 +0, 4, 4, 1, 152064, 0x5bc481c7 +0, 5, 5, 1, 152064, 0x91fec184 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-spp ffmpeg-4.4/tests/ref/fate/filter-spp --- ffmpeg-4.2.2/tests/ref/fate/filter-spp 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-spp 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,10 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 1/1 +0, 1, 1, 1, 152064, 0xecd18291 +0, 2, 2, 1, 152064, 0xea34708a +0, 3, 3, 1, 152064, 0xd73debe7 +0, 4, 4, 1, 152064, 0x47f57fbb +0, 5, 5, 1, 152064, 0x508dba95 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-stereo3d-sbsl-arcd ffmpeg-4.4/tests/ref/fate/filter-stereo3d-sbsl-arcd --- ffmpeg-4.2.2/tests/ref/fate/filter-stereo3d-sbsl-arcd 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-stereo3d-sbsl-arcd 2020-07-11 10:39:30.000000000 +0000 @@ -3,8 +3,8 @@ #codec_id 0: rawvideo #dimensions 0: 176x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0xa0261570 -0, 1, 1, 1, 152064, 0x678403c8 -0, 2, 2, 1, 152064, 0x1087e7b6 -0, 3, 3, 1, 152064, 0xa3909df3 -0, 4, 4, 1, 152064, 0x87e4c4d4 +0, 0, 0, 1, 152064, 0x34b1fb03 +0, 1, 1, 1, 152064, 0x2045eadd +0, 2, 2, 1, 152064, 0x1266cdde +0, 3, 3, 1, 152064, 0xc9f083bd +0, 4, 4, 1, 152064, 0x0701ab16 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-stereo3d-sbsl-aybd ffmpeg-4.4/tests/ref/fate/filter-stereo3d-sbsl-aybd --- ffmpeg-4.2.2/tests/ref/fate/filter-stereo3d-sbsl-aybd 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-stereo3d-sbsl-aybd 2020-07-11 10:39:30.000000000 +0000 @@ -3,8 +3,8 @@ #codec_id 0: rawvideo #dimensions 0: 176x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x7dc98468 -0, 1, 1, 1, 152064, 0xf72db6c9 -0, 2, 2, 1, 152064, 0x1630f53f -0, 3, 3, 1, 152064, 0xc1765599 -0, 4, 4, 1, 152064, 0x12e35db1 +0, 0, 0, 1, 152064, 0xf576742c +0, 1, 1, 1, 152064, 0x2ce36ae4 +0, 2, 2, 1, 152064, 0x2dc99849 +0, 3, 3, 1, 152064, 0x940413b6 +0, 4, 4, 1, 152064, 0x48a600d3 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-thumbnail ffmpeg-4.4/tests/ref/fate/filter-thumbnail --- ffmpeg-4.2.2/tests/ref/fate/filter-thumbnail 2016-03-29 02:25:35.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-thumbnail 2021-04-08 21:28:40.000000000 +0000 @@ -1 +1 @@ -thumbnail cd429b3d92c33bcc257e8e6a3284dbf7 +thumbnail 8b54dbc891b9cc05742dd0f5b74c0727 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-tremolo ffmpeg-4.4/tests/ref/fate/filter-tremolo --- ffmpeg-4.2.2/tests/ref/fate/filter-tremolo 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-tremolo 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -#tb 0: 1/44100 -#media_type 0: audio -#codec_id 0: pcm_s16le -#sample_rate 0: 44100 -#channel_layout 0: 3 -#channel_layout_name 0: stereo -0, 0, 0, 1024, 4096, 0x5d3be907 -0, 1024, 1024, 1024, 4096, 0xea151fbe -0, 2048, 2048, 1024, 4096, 0xa5bc19f4 -0, 3072, 3072, 1024, 4096, 0x8706ec6d -0, 4096, 4096, 1024, 4096, 0x334ff275 -0, 5120, 5120, 1024, 4096, 0xcd0ff7ad -0, 6144, 6144, 1024, 4096, 0x29a1e9c9 -0, 7168, 7168, 1024, 4096, 0x1d41e77f -0, 8192, 8192, 1024, 4096, 0x99e7fe07 -0, 9216, 9216, 1024, 4096, 0x4bbf09ce -0, 10240, 10240, 1024, 4096, 0x94600236 -0, 11264, 11264, 1024, 4096, 0xc8af0c9e -0, 12288, 12288, 1024, 4096, 0x70eef88f -0, 13312, 13312, 1024, 4096, 0xb222ec47 -0, 14336, 14336, 1024, 4096, 0x1071ee27 -0, 15360, 15360, 1024, 4096, 0x7c390bd2 -0, 16384, 16384, 1024, 4096, 0x68bdf655 -0, 17408, 17408, 1024, 4096, 0x810cfacb -0, 18432, 18432, 1024, 4096, 0x9639e41f -0, 19456, 19456, 1024, 4096, 0xa30be70f diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-unsharp-yuv420p10 ffmpeg-4.4/tests/ref/fate/filter-unsharp-yuv420p10 --- ffmpeg-4.2.2/tests/ref/fate/filter-unsharp-yuv420p10 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-unsharp-yuv420p10 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,25 @@ +#tb 0: 1/2 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 230400, 0x091f3ed7 +0, 1, 1, 1, 230400, 0x4151292d +0, 2, 2, 1, 230400, 0xe7066e96 +0, 3, 3, 1, 230400, 0x57c20d15 +0, 4, 4, 1, 230400, 0x01269a37 +0, 5, 5, 1, 230400, 0xb2b04e5c +0, 6, 6, 1, 230400, 0x98fc479f +0, 7, 7, 1, 230400, 0x561915bb +0, 8, 8, 1, 230400, 0xd60c45f7 +0, 9, 9, 1, 230400, 0x747d8a28 +0, 10, 10, 1, 230400, 0x92505d36 +0, 11, 11, 1, 230400, 0x9476af1f +0, 12, 12, 1, 230400, 0x1382c3d0 +0, 13, 13, 1, 230400, 0x94ea40bd +0, 14, 14, 1, 230400, 0x8d46229a +0, 15, 15, 1, 230400, 0xe5736654 +0, 16, 16, 1, 230400, 0x04bd4db2 +0, 17, 17, 1, 230400, 0x4d721ad2 +0, 18, 18, 1, 230400, 0xebe151a2 +0, 19, 19, 1, 230400, 0xa1263f01 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-untile ffmpeg-4.4/tests/ref/fate/filter-untile --- ffmpeg-4.2.2/tests/ref/fate/filter-untile 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-untile 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,13 @@ +#tb 0: 1/8 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 160x120 +#sar 0: 1/1 +0, 0, 0, 1, 28800, 0xb3725302 +0, 1, 1, 1, 28800, 0xf9612057 +0, 2, 2, 1, 28800, 0x9b207db0 +0, 3, 3, 1, 28800, 0x1331c2d5 +0, 4, 4, 1, 28800, 0x2edf3ee4 +0, 5, 5, 1, 28800, 0x84105711 +0, 6, 6, 1, 28800, 0xa7a35f25 +0, 7, 7, 1, 28800, 0xa9c49677 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-vectorscope_color ffmpeg-4.4/tests/ref/fate/filter-vectorscope_color --- ffmpeg-4.2.2/tests/ref/fate/filter-vectorscope_color 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-vectorscope_color 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 256x256 #sar 0: 1/1 -0, 0, 0, 1, 196608, 0xf6e3aa30 -0, 1, 1, 1, 196608, 0x5584acf9 -0, 2, 2, 1, 196608, 0xa862775d +0, 0, 0, 1, 196608, 0x7c431d1f +0, 1, 1, 1, 196608, 0xb7e82028 +0, 2, 2, 1, 196608, 0x2feeeb61 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-vectorscope_color2 ffmpeg-4.4/tests/ref/fate/filter-vectorscope_color2 --- ffmpeg-4.2.2/tests/ref/fate/filter-vectorscope_color2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-vectorscope_color2 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 256x256 #sar 0: 1/1 -0, 0, 0, 1, 196608, 0x5e62fae5 -0, 1, 1, 1, 196608, 0x4c27fcbf -0, 2, 2, 1, 196608, 0xb7531088 +0, 0, 0, 1, 196608, 0xdad38823 +0, 1, 1, 1, 196608, 0xeb8589bd +0, 2, 2, 1, 196608, 0x31a79c93 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-vectorscope_color3 ffmpeg-4.4/tests/ref/fate/filter-vectorscope_color3 --- ffmpeg-4.2.2/tests/ref/fate/filter-vectorscope_color3 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-vectorscope_color3 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 256x256 #sar 0: 1/1 -0, 0, 0, 1, 196608, 0x83df8770 -0, 1, 1, 1, 196608, 0xa6a674a7 -0, 2, 2, 1, 196608, 0x11757143 +0, 0, 0, 1, 196608, 0x005f14ae +0, 1, 1, 1, 196608, 0x461301a5 +0, 2, 2, 1, 196608, 0x8bbafd4e diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-vectorscope_color4 ffmpeg-4.4/tests/ref/fate/filter-vectorscope_color4 --- ffmpeg-4.2.2/tests/ref/fate/filter-vectorscope_color4 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-vectorscope_color4 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 256x256 #sar 0: 1/1 -0, 0, 0, 1, 196608, 0x326953c4 -0, 1, 1, 1, 196608, 0x870e1dcc -0, 2, 2, 1, 196608, 0x87cb8800 +0, 0, 0, 1, 196608, 0xaedae0f3 +0, 1, 1, 1, 196608, 0x267baabb +0, 2, 2, 1, 196608, 0x021f141a diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-vectorscope_gray ffmpeg-4.4/tests/ref/fate/filter-vectorscope_gray --- ffmpeg-4.2.2/tests/ref/fate/filter-vectorscope_gray 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-vectorscope_gray 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 256x256 #sar 0: 1/1 -0, 0, 0, 1, 196608, 0x79ba71e2 -0, 1, 1, 1, 196608, 0x909271e2 -0, 2, 2, 1, 196608, 0x143971e2 +0, 0, 0, 1, 196608, 0xf62bff11 +0, 1, 1, 1, 196608, 0x2ffffed1 +0, 2, 2, 1, 196608, 0x8e7efded diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-vectorscope_xy ffmpeg-4.4/tests/ref/fate/filter-vectorscope_xy --- ffmpeg-4.2.2/tests/ref/fate/filter-vectorscope_xy 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-vectorscope_xy 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 256x256 #sar 0: 1/1 -0, 0, 0, 1, 196608, 0xa2899af1 -0, 1, 1, 1, 196608, 0x26409af1 -0, 2, 2, 1, 196608, 0xf5209af1 +0, 0, 0, 1, 196608, 0xd2bfcc40 +0, 1, 1, 1, 196608, 0x2851cb74 +0, 2, 2, 1, 196608, 0x48efcc64 diff -Nru ffmpeg-4.2.2/tests/ref/fate/filter-waveform_uv ffmpeg-4.4/tests/ref/fate/filter-waveform_uv --- ffmpeg-4.2.2/tests/ref/fate/filter-waveform_uv 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/filter-waveform_uv 2020-07-11 10:39:30.000000000 +0000 @@ -3,53 +3,53 @@ #codec_id 0: rawvideo #dimensions 0: 352x512 #sar 0: 1/1 -0, 0, 0, 1, 540672, 0x8a2521d6 -0, 1, 1, 1, 540672, 0xb9a321d6 -0, 2, 2, 1, 540672, 0x325421d6 -0, 3, 3, 1, 540672, 0xafee21d2 -0, 4, 4, 1, 540672, 0x172121d6 -0, 5, 5, 1, 540672, 0x24d121d6 -0, 6, 6, 1, 540672, 0x7fec21d6 -0, 7, 7, 1, 540672, 0xa8a021d6 -0, 8, 8, 1, 540672, 0x29fd21d6 -0, 9, 9, 1, 540672, 0x6dfe21d6 -0, 10, 10, 1, 540672, 0xe39821d6 -0, 11, 11, 1, 540672, 0x83f521d6 -0, 12, 12, 1, 540672, 0x57aa21d6 -0, 13, 13, 1, 540672, 0x67b221d6 -0, 14, 14, 1, 540672, 0x535821d6 -0, 15, 15, 1, 540672, 0xb8ac21d6 -0, 16, 16, 1, 540672, 0x27f621d6 -0, 17, 17, 1, 540672, 0x775221d6 -0, 18, 18, 1, 540672, 0x8e6621d6 -0, 19, 19, 1, 540672, 0x74c921d6 -0, 20, 20, 1, 540672, 0x04cd21d6 -0, 21, 21, 1, 540672, 0xccd421d6 -0, 22, 22, 1, 540672, 0x317221d6 -0, 23, 23, 1, 540672, 0xd79321d6 -0, 24, 24, 1, 540672, 0xa2ac21d6 -0, 25, 25, 1, 540672, 0x7f0a21d6 -0, 26, 26, 1, 540672, 0x483521d6 -0, 27, 27, 1, 540672, 0xb65721d6 -0, 28, 28, 1, 540672, 0xb77021d6 -0, 29, 29, 1, 540672, 0x9fd521d6 -0, 30, 30, 1, 540672, 0xb72121d6 -0, 31, 31, 1, 540672, 0x540221d6 -0, 32, 32, 1, 540672, 0xa34121d6 -0, 33, 33, 1, 540672, 0xe01421d6 -0, 34, 34, 1, 540672, 0x6fc721d6 -0, 35, 35, 1, 540672, 0x7fa621d6 -0, 36, 36, 1, 540672, 0xc48c21d6 -0, 37, 37, 1, 540672, 0x40f021d6 -0, 38, 38, 1, 540672, 0xdf3f21d6 -0, 39, 39, 1, 540672, 0xb04321d6 -0, 40, 40, 1, 540672, 0x222821d6 -0, 41, 41, 1, 540672, 0x2a5521d6 -0, 42, 42, 1, 540672, 0x6a4621be -0, 43, 43, 1, 540672, 0xed7f21d6 -0, 44, 44, 1, 540672, 0xb16521d6 -0, 45, 45, 1, 540672, 0x9f5621d6 -0, 46, 46, 1, 540672, 0x204321d6 -0, 47, 47, 1, 540672, 0xc26e21d6 -0, 48, 48, 1, 540672, 0x3e8321d6 -0, 49, 49, 1, 540672, 0xaaee21d6 +0, 0, 0, 1, 540672, 0xe33821d6 +0, 1, 1, 1, 540672, 0x12c521d6 +0, 2, 2, 1, 540672, 0x8b6721d6 +0, 3, 3, 1, 540672, 0x6fd321d6 +0, 4, 4, 1, 540672, 0x703421d6 +0, 5, 5, 1, 540672, 0x7de421d6 +0, 6, 6, 1, 540672, 0xd8ff21d6 +0, 7, 7, 1, 540672, 0x01c221d6 +0, 8, 8, 1, 540672, 0x831021d6 +0, 9, 9, 1, 540672, 0xc71121d6 +0, 10, 10, 1, 540672, 0x3cba21d6 +0, 11, 11, 1, 540672, 0xdd0821d6 +0, 12, 12, 1, 540672, 0xb0bd21d6 +0, 13, 13, 1, 540672, 0xc0c521d6 +0, 14, 14, 1, 540672, 0xac6b21d6 +0, 15, 15, 1, 540672, 0x11ce21d6 +0, 16, 16, 1, 540672, 0x810921d6 +0, 17, 17, 1, 540672, 0xd06521d6 +0, 18, 18, 1, 540672, 0xe77921d6 +0, 19, 19, 1, 540672, 0xcddc21d6 +0, 20, 20, 1, 540672, 0x5de021d6 +0, 21, 21, 1, 540672, 0x25f621d6 +0, 22, 22, 1, 540672, 0x8a8521d6 +0, 23, 23, 1, 540672, 0x30b521d6 +0, 24, 24, 1, 540672, 0xfbbf21d6 +0, 25, 25, 1, 540672, 0xd81d21d6 +0, 26, 26, 1, 540672, 0xa14821d6 +0, 27, 27, 1, 540672, 0x0f7921d6 +0, 28, 28, 1, 540672, 0x109221d6 +0, 29, 29, 1, 540672, 0xf8e821d6 +0, 30, 30, 1, 540672, 0x104321d6 +0, 31, 31, 1, 540672, 0xad1521d6 +0, 32, 32, 1, 540672, 0xfc5421d6 +0, 33, 33, 1, 540672, 0x393621d6 +0, 34, 34, 1, 540672, 0xc8da21d6 +0, 35, 35, 1, 540672, 0xd8b921d6 +0, 36, 36, 1, 540672, 0x1dae21d6 +0, 37, 37, 1, 540672, 0x9a0321d6 +0, 38, 38, 1, 540672, 0x386121d6 +0, 39, 39, 1, 540672, 0x096521d6 +0, 40, 40, 1, 540672, 0x7b3b21d6 +0, 41, 41, 1, 540672, 0x836821d6 +0, 42, 42, 1, 540672, 0x97bd21d6 +0, 43, 43, 1, 540672, 0x46a121d6 +0, 44, 44, 1, 540672, 0x0a8721d6 +0, 45, 45, 1, 540672, 0xf86921d6 +0, 46, 46, 1, 540672, 0x795621d6 +0, 47, 47, 1, 540672, 0x1b9021d6 +0, 48, 48, 1, 540672, 0x979621d6 +0, 49, 49, 1, 540672, 0x041021d6 diff -Nru ffmpeg-4.2.2/tests/ref/fate/fitsdec-gray ffmpeg-4.4/tests/ref/fate/fitsdec-gray --- ffmpeg-4.2.2/tests/ref/fate/fitsdec-gray 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/fitsdec-gray 2021-04-08 21:28:40.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 128x128 #sar 0: 0/1 -0, 0, 0, 1, 16384, 0x353dbacd +0, 0, 0, 1, 16384, 0xeff50901 diff -Nru ffmpeg-4.2.2/tests/ref/fate/fits-demux ffmpeg-4.4/tests/ref/fate/fits-demux --- ffmpeg-4.2.2/tests/ref/fate/fits-demux 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/fits-demux 2021-04-08 21:28:40.000000000 +0000 @@ -3,8 +3,8 @@ #codec_id 0: fits #dimensions 0: 72x36 #sar 0: 0/1 -0, 0, 0, 1, 14320, 0x0ecf72e0 -0, 1, 1, 1, 14320, 0xd94af6eb -0, 2, 2, 1, 14320, 0x15c21892 -0, 3, 3, 1, 14320, 0xb18adc01 -0, 4, 4, 1, 14320, 0xc2be706d +0, 0, 0, 1, 14320, 0xa9ee75a4 +0, 1, 1, 1, 14320, 0xb9daf9af +0, 2, 2, 1, 14320, 0xf6431b56 +0, 3, 3, 1, 14320, 0x921adec5 +0, 4, 4, 1, 14320, 0xa34e7331 diff -Nru ffmpeg-4.2.2/tests/ref/fate/flcl1905 ffmpeg-4.4/tests/ref/fate/flcl1905 --- ffmpeg-4.2.2/tests/ref/fate/flcl1905 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/flcl1905 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=56|flags=K_ +packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=22528|duration_time=0.510839|size=4092|pos=56|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=56|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=56|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=56|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -10,7 +10,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=56|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=56|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=56|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=22528|pts_time=0.510839|dts=22528|dts_time=0.510839|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=4148|flags=K_ +packet|codec_type=audio|stream_index=0|pts=22528|pts_time=0.510839|dts=22528|dts_time=0.510839|duration=22528|duration_time=0.510839|size=4092|pos=4148|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=22528|pkt_pts_time=0.510839|pkt_dts=22528|pkt_dts_time=0.510839|best_effort_timestamp=22528|best_effort_timestamp_time=0.510839|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=4148|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=4148|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=4148|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -22,7 +22,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=4148|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=4148|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=4148|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=45056|pts_time=1.021678|dts=45056|dts_time=1.021678|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=8240|flags=K_ +packet|codec_type=audio|stream_index=0|pts=45056|pts_time=1.021678|dts=45056|dts_time=1.021678|duration=22528|duration_time=0.510839|size=4092|pos=8240|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=45056|pkt_pts_time=1.021678|pkt_dts=45056|pkt_dts_time=1.021678|best_effort_timestamp=45056|best_effort_timestamp_time=1.021678|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=8240|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=8240|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=8240|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -34,7 +34,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=8240|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=8240|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=8240|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=67584|pts_time=1.532517|dts=67584|dts_time=1.532517|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=12332|flags=K_ +packet|codec_type=audio|stream_index=0|pts=67584|pts_time=1.532517|dts=67584|dts_time=1.532517|duration=22528|duration_time=0.510839|size=4092|pos=12332|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=67584|pkt_pts_time=1.532517|pkt_dts=67584|pkt_dts_time=1.532517|best_effort_timestamp=67584|best_effort_timestamp_time=1.532517|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=12332|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=12332|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=12332|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -46,7 +46,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=12332|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=12332|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=12332|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=90112|pts_time=2.043356|dts=90112|dts_time=2.043356|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=16424|flags=K_ +packet|codec_type=audio|stream_index=0|pts=90112|pts_time=2.043356|dts=90112|dts_time=2.043356|duration=22528|duration_time=0.510839|size=4092|pos=16424|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=90112|pkt_pts_time=2.043356|pkt_dts=90112|pkt_dts_time=2.043356|best_effort_timestamp=90112|best_effort_timestamp_time=2.043356|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=16424|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=16424|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=16424|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -58,7 +58,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=16424|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=16424|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=16424|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=112640|pts_time=2.554195|dts=112640|dts_time=2.554195|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=20516|flags=K_ +packet|codec_type=audio|stream_index=0|pts=112640|pts_time=2.554195|dts=112640|dts_time=2.554195|duration=22528|duration_time=0.510839|size=4092|pos=20516|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=112640|pkt_pts_time=2.554195|pkt_dts=112640|pkt_dts_time=2.554195|best_effort_timestamp=112640|best_effort_timestamp_time=2.554195|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=20516|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=20516|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=20516|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -70,7 +70,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=20516|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=20516|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=20516|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=135168|pts_time=3.065034|dts=135168|dts_time=3.065034|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=24608|flags=K_ +packet|codec_type=audio|stream_index=0|pts=135168|pts_time=3.065034|dts=135168|dts_time=3.065034|duration=22528|duration_time=0.510839|size=4092|pos=24608|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=135168|pkt_pts_time=3.065034|pkt_dts=135168|pkt_dts_time=3.065034|best_effort_timestamp=135168|best_effort_timestamp_time=3.065034|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=24608|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=24608|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=24608|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -82,7 +82,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=24608|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=24608|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=24608|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=157696|pts_time=3.575873|dts=157696|dts_time=3.575873|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=28700|flags=K_ +packet|codec_type=audio|stream_index=0|pts=157696|pts_time=3.575873|dts=157696|dts_time=3.575873|duration=22528|duration_time=0.510839|size=4092|pos=28700|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=157696|pkt_pts_time=3.575873|pkt_dts=157696|pkt_dts_time=3.575873|best_effort_timestamp=157696|best_effort_timestamp_time=3.575873|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=28700|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=28700|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=28700|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -94,7 +94,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=28700|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=28700|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=28700|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=180224|pts_time=4.086712|dts=180224|dts_time=4.086712|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=32792|flags=K_ +packet|codec_type=audio|stream_index=0|pts=180224|pts_time=4.086712|dts=180224|dts_time=4.086712|duration=22528|duration_time=0.510839|size=4092|pos=32792|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=180224|pkt_pts_time=4.086712|pkt_dts=180224|pkt_dts_time=4.086712|best_effort_timestamp=180224|best_effort_timestamp_time=4.086712|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=32792|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=32792|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=32792|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -106,7 +106,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=32792|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=32792|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=32792|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=202752|pts_time=4.597551|dts=202752|dts_time=4.597551|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=36884|flags=K_ +packet|codec_type=audio|stream_index=0|pts=202752|pts_time=4.597551|dts=202752|dts_time=4.597551|duration=22528|duration_time=0.510839|size=4092|pos=36884|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=202752|pkt_pts_time=4.597551|pkt_dts=202752|pkt_dts_time=4.597551|best_effort_timestamp=202752|best_effort_timestamp_time=4.597551|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=36884|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=36884|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=36884|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -118,7 +118,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=36884|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=36884|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=36884|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=225280|pts_time=5.108390|dts=225280|dts_time=5.108390|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=40976|flags=K_ +packet|codec_type=audio|stream_index=0|pts=225280|pts_time=5.108390|dts=225280|dts_time=5.108390|duration=22528|duration_time=0.510839|size=4092|pos=40976|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=225280|pkt_pts_time=5.108390|pkt_dts=225280|pkt_dts_time=5.108390|best_effort_timestamp=225280|best_effort_timestamp_time=5.108390|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=40976|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=40976|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=40976|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -130,7 +130,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=40976|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=40976|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=40976|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=247808|pts_time=5.619229|dts=247808|dts_time=5.619229|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=45068|flags=K_ +packet|codec_type=audio|stream_index=0|pts=247808|pts_time=5.619229|dts=247808|dts_time=5.619229|duration=22528|duration_time=0.510839|size=4092|pos=45068|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=247808|pkt_pts_time=5.619229|pkt_dts=247808|pkt_dts_time=5.619229|best_effort_timestamp=247808|best_effort_timestamp_time=5.619229|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=45068|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=45068|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=45068|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -142,7 +142,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=45068|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=45068|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=45068|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=270336|pts_time=6.130068|dts=270336|dts_time=6.130068|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=49160|flags=K_ +packet|codec_type=audio|stream_index=0|pts=270336|pts_time=6.130068|dts=270336|dts_time=6.130068|duration=22528|duration_time=0.510839|size=4092|pos=49160|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=270336|pkt_pts_time=6.130068|pkt_dts=270336|pkt_dts_time=6.130068|best_effort_timestamp=270336|best_effort_timestamp_time=6.130068|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=49160|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=49160|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=49160|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -154,7 +154,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=49160|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=49160|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=49160|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=292864|pts_time=6.640907|dts=292864|dts_time=6.640907|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=53252|flags=K_ +packet|codec_type=audio|stream_index=0|pts=292864|pts_time=6.640907|dts=292864|dts_time=6.640907|duration=22528|duration_time=0.510839|size=4092|pos=53252|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=292864|pkt_pts_time=6.640907|pkt_dts=292864|pkt_dts_time=6.640907|best_effort_timestamp=292864|best_effort_timestamp_time=6.640907|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=53252|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=53252|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=53252|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -166,7 +166,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=53252|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=53252|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=53252|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=315392|pts_time=7.151746|dts=315392|dts_time=7.151746|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=57344|flags=K_ +packet|codec_type=audio|stream_index=0|pts=315392|pts_time=7.151746|dts=315392|dts_time=7.151746|duration=22528|duration_time=0.510839|size=4092|pos=57344|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=315392|pkt_pts_time=7.151746|pkt_dts=315392|pkt_dts_time=7.151746|best_effort_timestamp=315392|best_effort_timestamp_time=7.151746|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=57344|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=57344|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=57344|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -178,7 +178,7 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=57344|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=57344|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=57344|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=337920|pts_time=7.662585|dts=337920|dts_time=7.662585|duration=22528|duration_time=0.510839|convergence_duration=N/A|convergence_duration_time=N/A|size=4092|pos=61436|flags=K_ +packet|codec_type=audio|stream_index=0|pts=337920|pts_time=7.662585|dts=337920|dts_time=7.662585|duration=22528|duration_time=0.510839|size=4092|pos=61436|flags=K_ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=337920|pkt_pts_time=7.662585|pkt_dts=337920|pkt_dts_time=7.662585|best_effort_timestamp=337920|best_effort_timestamp_time=7.662585|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=61436|pkt_size=4092|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=61436|pkt_size=3720|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=61436|pkt_size=3348|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown @@ -190,4 +190,4 @@ frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=61436|pkt_size=1116|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=61436|pkt_size=744|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=N/A|pkt_pts_time=N/A|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=N/A|best_effort_timestamp_time=N/A|pkt_duration=22528|pkt_duration_time=0.510839|pkt_pos=61436|pkt_size=372|sample_fmt=fltp|nb_samples=2048|channels=2|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=360448|pts_time=8.173424|dts=360448|dts_time=8.173424|duration=44|duration_time=0.000998|convergence_duration=N/A|convergence_duration_time=N/A|size=8|pos=65528|flags=K_ +packet|codec_type=audio|stream_index=0|pts=360448|pts_time=8.173424|dts=360448|dts_time=8.173424|duration=44|duration_time=0.000998|size=8|pos=65528|flags=K_ diff -Nru ffmpeg-4.2.2/tests/ref/fate/g2m2 ffmpeg-4.4/tests/ref/fate/g2m2 --- ffmpeg-4.2.2/tests/ref/fate/g2m2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/g2m2 2021-04-08 21:28:40.000000000 +0000 @@ -3,163 +3,163 @@ #codec_id 0: rawvideo #dimensions 0: 1024x768 #sar 0: 0/1 -0, 47, 47, 0, 2359296, 0xb4434e4f -0, 62, 62, 0, 2359296, 0x59cb5027 -0, 78, 78, 0, 2359296, 0xe9bc578d -0, 109, 109, 0, 2359296, 0x5d17554f -0, 125, 125, 0, 2359296, 0x6d685457 -0, 437, 437, 0, 2359296, 0x13205420 -0, 438, 438, 0, 2359296, 0xb8e15116 -0, 453, 453, 0, 2359296, 0x2ca55195 -0, 469, 469, 0, 2359296, 0x767d1c45 -0, 484, 484, 0, 2359296, 0x0af42016 -0, 500, 500, 0, 2359296, 0xa2083e69 -0, 516, 516, 0, 2359296, 0xb68a1308 -0, 531, 531, 0, 2359296, 0x4f334c0e -0, 547, 547, 0, 2359296, 0x98b74e4f -0, 562, 562, 0, 2359296, 0xd9de4e4f -0, 578, 578, 0, 2359296, 0xa17c4e4f -0, 594, 594, 0, 2359296, 0xa49a665d -0, 609, 609, 0, 2359296, 0xf5f87360 -0, 781, 781, 0, 2359296, 0x75747360 -0, 797, 797, 0, 2359296, 0x745d7360 -0, 812, 812, 0, 2359296, 0x33047360 -0, 828, 828, 0, 2359296, 0xf19c7360 -0, 844, 844, 0, 2359296, 0xb0437360 -0, 859, 859, 0, 2359296, 0xaf2c7360 -0, 875, 875, 0, 2359296, 0x2ea87360 -0, 891, 891, 0, 2359296, 0xee577360 -0, 953, 953, 0, 2359296, 0x6dd37360 -0, 1078, 1078, 0, 2359296, 0xab327965 -0, 1094, 1094, 0, 2359296, 0x5f8677d0 -0, 1109, 1109, 0, 2359296, 0x02135eb4 -0, 1125, 1125, 0, 2359296, 0x09784e4f -0, 1141, 1141, 0, 2359296, 0xa140a62d -0, 1156, 1156, 0, 2359296, 0xa140a62d -0, 1484, 1484, 0, 2359296, 0xa140a62d -0, 1516, 1516, 0, 2359296, 0xa140a62d -0, 1547, 1547, 0, 2359296, 0xa140a62d -0, 1641, 1641, 0, 2359296, 0xa140a62d -0, 1642, 1642, 0, 2359296, 0xa140a62d -0, 1656, 1656, 0, 2359296, 0xa140a62d -0, 1657, 1657, 0, 2359296, 0xa140a62d -0, 1672, 1672, 0, 2359296, 0xa140a62d -0, 1673, 1673, 0, 2359296, 0x92024e4f -0, 1687, 1687, 0, 2359296, 0xb1754dbe -0, 1688, 1688, 0, 2359296, 0x15ee5eb4 -0, 1703, 1703, 0, 2359296, 0xb1d9746e -0, 1719, 1719, 0, 2359296, 0xabe77360 -0, 1734, 1734, 0, 2359296, 0xaad07360 -0, 1750, 1750, 0, 2359296, 0x2a4c7360 -0, 1766, 1766, 0, 2359296, 0x69777360 -0, 1781, 1781, 0, 2359296, 0xe8e47360 -0, 2328, 2328, 0, 2359296, 0x29357360 -0, 3031, 3031, 0, 2359296, 0x69777360 -0, 3078, 3078, 0, 2359296, 0xa9b97360 -0, 3109, 3109, 0, 2359296, 0xd2697707 -0, 3141, 3141, 0, 2359296, 0x22a07965 -0, 3156, 3156, 0, 2359296, 0xf9327aa7 -0, 3172, 3172, 0, 2359296, 0xa5d277d0 -0, 3203, 3203, 0, 2359296, 0x97b6746e -0, 3328, 3328, 0, 2359296, 0x80bb746e -0, 4562, 4562, 0, 2359296, 0x530b719a -0, 4672, 4672, 0, 2359296, 0x4827665d -0, 4703, 4703, 0, 2359296, 0xc48c5eb4 -0, 5391, 5391, 0, 2359296, 0xe6465eb4 -0, 5578, 5578, 0, 2359296, 0xece455ec -0, 5594, 5594, 0, 2359296, 0xb5344dbe -0, 5609, 5609, 0, 2359296, 0xa140a62d -0, 5625, 5625, 0, 2359296, 0xa140a62d -0, 5641, 5641, 0, 2359296, 0xa140a62d -0, 5642, 5642, 0, 2359296, 0xa140a62d -0, 5656, 5656, 0, 2359296, 0xa140a62d -0, 5672, 5672, 0, 2359296, 0xa140a62d -0, 5703, 5703, 0, 2359296, 0xa140a62d -0, 5750, 5750, 0, 2359296, 0xa140a62d -0, 5766, 5766, 0, 2359296, 0xa140a62d -0, 5781, 5781, 0, 2359296, 0xa140a62d -0, 5797, 5797, 0, 2359296, 0xa140a62d -0, 5812, 5812, 0, 2359296, 0xa140a62d -0, 5875, 5875, 0, 2359296, 0xa140a62d -0, 5922, 5922, 0, 2359296, 0xa140a62d -0, 5984, 5984, 0, 2359296, 0xa140a62d -0, 6031, 6031, 0, 2359296, 0xa140a62d -0, 6047, 6047, 0, 2359296, 0xa140a62d -0, 6062, 6062, 0, 2359296, 0xa140a62d -0, 6406, 6406, 0, 2359296, 0xa140a62d -0, 6453, 6453, 0, 2359296, 0xa140a62d -0, 6469, 6469, 0, 2359296, 0xa140a62d -0, 6484, 6484, 0, 2359296, 0xa140a62d -0, 6500, 6500, 0, 2359296, 0xa140a62d -0, 6516, 6516, 0, 2359296, 0xa140a62d -0, 6531, 6531, 0, 2359296, 0xa140a62d -0, 6547, 6547, 0, 2359296, 0xa140a62d -0, 6562, 6562, 0, 2359296, 0x5c2a4cd9 -0, 6578, 6578, 0, 2359296, 0x28f94e4f -0, 6594, 6594, 0, 2359296, 0x9acb4820 -0, 6609, 6609, 0, 2359296, 0x9ec716e1 -0, 6625, 6625, 0, 2359296, 0xaf5f3fa4 -0, 6641, 6641, 0, 2359296, 0x7d633218 -0, 6642, 6642, 0, 2359296, 0x34fb2016 -0, 6656, 6656, 0, 2359296, 0x61351665 -0, 6812, 6812, 0, 2359296, 0xb23c1039 -0, 6828, 6828, 0, 2359296, 0x59290d69 -0, 6844, 6844, 0, 2359296, 0x639c132d -0, 6859, 6859, 0, 2359296, 0x0b252237 -0, 6875, 6875, 0, 2359296, 0xe66f2fc5 -0, 6891, 6891, 0, 2359296, 0xa8b33761 -0, 6906, 6906, 0, 2359296, 0x81a63f8b -0, 6969, 6969, 0, 2359296, 0x18074843 -0, 6984, 6984, 0, 2359296, 0x434a5195 -0, 7000, 7000, 0, 2359296, 0x6da15116 -0, 7001, 7001, 0, 2359296, 0xca755420 -0, 7016, 7016, 0, 2359296, 0xe6fc5457 -0, 7017, 7017, 0, 2359296, 0x271d53fd -0, 7031, 7031, 0, 2359296, 0xa15b554f -0, 7281, 7281, 0, 2359296, 0x49f6578d -0, 7282, 7282, 0, 2359296, 0x2c0c4e4f -0, 7297, 7297, 0, 2359296, 0x7e924e4f -0, 7298, 7298, 0, 2359296, 0x32ff4e4f -0, 7312, 7312, 0, 2359296, 0x23ad4e4f -0, 7313, 7313, 0, 2359296, 0x7ddc4e4f -0, 7328, 7328, 0, 2359296, 0xd0624e4f -0, 7329, 7329, 0, 2359296, 0x22f74e4f -0, 7781, 7781, 0, 2359296, 0x49fa4e4f -0, 7797, 7797, 0, 2359296, 0x6a5a5027 -0, 7812, 7812, 0, 2359296, 0x9f935027 -0, 7828, 7828, 0, 2359296, 0xc5e55027 -0, 7844, 7844, 0, 2359296, 0xd4cc5027 -0, 8250, 8250, 0, 2359296, 0xd2ab5027 -0, 8266, 8266, 0, 2359296, 0x68f04e4f -0, 8281, 8281, 0, 2359296, 0xd0b44e4f -0, 8297, 8297, 0, 2359296, 0xfced4e4f -0, 8298, 8298, 0, 2359296, 0x8b0d4e4f -0, 8312, 8312, 0, 2359296, 0x09db4e4f -0, 8328, 8328, 0, 2359296, 0x4d0f4e4f -0, 8329, 8329, 0, 2359296, 0xad824dbe -0, 8344, 8344, 0, 2359296, 0x9aca4dbe -0, 8345, 8345, 0, 2359296, 0x755a4dbe -0, 8359, 8359, 0, 2359296, 0xc6824d2d -0, 8360, 8360, 0, 2359296, 0x7c344c0e -0, 8375, 8375, 0, 2359296, 0x50f04c0e -0, 8391, 8391, 0, 2359296, 0xfa594c0e -0, 8406, 8406, 0, 2359296, 0x4d494c0e -0, 8422, 8422, 0, 2359296, 0xf6b24c0e -0, 8437, 8437, 0, 2359296, 0xcb6e4c0e -0, 8453, 8453, 0, 2359296, 0xbd024c0e -0, 8516, 8516, 0, 2359296, 0x245b4dbe -0, 8531, 8531, 0, 2359296, 0x47874e4f -0, 8547, 8547, 0, 2359296, 0xdead4e4f -0, 8562, 8562, 0, 2359296, 0x847e4e4f -0, 9344, 9344, 0, 2359296, 0x1a13e47c -0, 9345, 9345, 0, 2359296, 0x46b3e321 -0, 9876, 9876, 0, 2359296, 0x76c0e35d -0, 9922, 9922, 0, 2359296, 0xf6d9e519 -0, 9938, 9938, 0, 2359296, 0xac0fe4b3 -0, 9954, 9954, 0, 2359296, 0x3a3fe424 -0, 9955, 9955, 0, 2359296, 0xa97ce1a8 -0, 9969, 9969, 0, 2359296, 0x12fae01d -0, 9970, 9970, 0, 2359296, 0x65b4df14 -0, 9985, 9985, 0, 2359296, 0x82d0e032 -0, 9986, 9986, 0, 2359296, 0xa452e0cf -0, 10001, 10001, 0, 2359296, 0x22d6df37 +0, 47, 47, 1, 2359296, 0xb4434e4f +0, 62, 62, 1, 2359296, 0x59cb5027 +0, 78, 78, 1, 2359296, 0xe9bc578d +0, 109, 109, 1, 2359296, 0x5d17554f +0, 125, 125, 1, 2359296, 0x6d685457 +0, 437, 437, 1, 2359296, 0x13205420 +0, 438, 438, 1, 2359296, 0xb8e15116 +0, 453, 453, 1, 2359296, 0x2ca55195 +0, 469, 469, 1, 2359296, 0x767d1c45 +0, 484, 484, 1, 2359296, 0x0af42016 +0, 500, 500, 1, 2359296, 0xa2083e69 +0, 516, 516, 1, 2359296, 0xb68a1308 +0, 531, 531, 1, 2359296, 0x4f334c0e +0, 547, 547, 1, 2359296, 0x98b74e4f +0, 562, 562, 1, 2359296, 0xd9de4e4f +0, 578, 578, 1, 2359296, 0xa17c4e4f +0, 594, 594, 1, 2359296, 0xa49a665d +0, 609, 609, 1, 2359296, 0xf5f87360 +0, 781, 781, 1, 2359296, 0x75747360 +0, 797, 797, 1, 2359296, 0x745d7360 +0, 812, 812, 1, 2359296, 0x33047360 +0, 828, 828, 1, 2359296, 0xf19c7360 +0, 844, 844, 1, 2359296, 0xb0437360 +0, 859, 859, 1, 2359296, 0xaf2c7360 +0, 875, 875, 1, 2359296, 0x2ea87360 +0, 891, 891, 1, 2359296, 0xee577360 +0, 953, 953, 1, 2359296, 0x6dd37360 +0, 1078, 1078, 1, 2359296, 0xab327965 +0, 1094, 1094, 1, 2359296, 0x5f8677d0 +0, 1109, 1109, 1, 2359296, 0x02135eb4 +0, 1125, 1125, 1, 2359296, 0x09784e4f +0, 1141, 1141, 1, 2359296, 0xa140a62d +0, 1156, 1156, 1, 2359296, 0xa140a62d +0, 1484, 1484, 1, 2359296, 0xa140a62d +0, 1516, 1516, 1, 2359296, 0xa140a62d +0, 1547, 1547, 1, 2359296, 0xa140a62d +0, 1641, 1641, 1, 2359296, 0xa140a62d +0, 1642, 1642, 1, 2359296, 0xa140a62d +0, 1656, 1656, 1, 2359296, 0xa140a62d +0, 1657, 1657, 1, 2359296, 0xa140a62d +0, 1672, 1672, 1, 2359296, 0xa140a62d +0, 1673, 1673, 1, 2359296, 0x92024e4f +0, 1687, 1687, 1, 2359296, 0xb1754dbe +0, 1688, 1688, 1, 2359296, 0x15ee5eb4 +0, 1703, 1703, 1, 2359296, 0xb1d9746e +0, 1719, 1719, 1, 2359296, 0xabe77360 +0, 1734, 1734, 1, 2359296, 0xaad07360 +0, 1750, 1750, 1, 2359296, 0x2a4c7360 +0, 1766, 1766, 1, 2359296, 0x69777360 +0, 1781, 1781, 1, 2359296, 0xe8e47360 +0, 2328, 2328, 1, 2359296, 0x29357360 +0, 3031, 3031, 1, 2359296, 0x69777360 +0, 3078, 3078, 1, 2359296, 0xa9b97360 +0, 3109, 3109, 1, 2359296, 0xd2697707 +0, 3141, 3141, 1, 2359296, 0x22a07965 +0, 3156, 3156, 1, 2359296, 0xf9327aa7 +0, 3172, 3172, 1, 2359296, 0xa5d277d0 +0, 3203, 3203, 1, 2359296, 0x97b6746e +0, 3328, 3328, 1, 2359296, 0x80bb746e +0, 4562, 4562, 1, 2359296, 0x530b719a +0, 4672, 4672, 1, 2359296, 0x4827665d +0, 4703, 4703, 1, 2359296, 0xc48c5eb4 +0, 5391, 5391, 1, 2359296, 0xe6465eb4 +0, 5578, 5578, 1, 2359296, 0xece455ec +0, 5594, 5594, 1, 2359296, 0xb5344dbe +0, 5609, 5609, 1, 2359296, 0xa140a62d +0, 5625, 5625, 1, 2359296, 0xa140a62d +0, 5641, 5641, 1, 2359296, 0xa140a62d +0, 5642, 5642, 1, 2359296, 0xa140a62d +0, 5656, 5656, 1, 2359296, 0xa140a62d +0, 5672, 5672, 1, 2359296, 0xa140a62d +0, 5703, 5703, 1, 2359296, 0xa140a62d +0, 5750, 5750, 1, 2359296, 0xa140a62d +0, 5766, 5766, 1, 2359296, 0xa140a62d +0, 5781, 5781, 1, 2359296, 0xa140a62d +0, 5797, 5797, 1, 2359296, 0xa140a62d +0, 5812, 5812, 1, 2359296, 0xa140a62d +0, 5875, 5875, 1, 2359296, 0xa140a62d +0, 5922, 5922, 1, 2359296, 0xa140a62d +0, 5984, 5984, 1, 2359296, 0xa140a62d +0, 6031, 6031, 1, 2359296, 0xa140a62d +0, 6047, 6047, 1, 2359296, 0xa140a62d +0, 6062, 6062, 1, 2359296, 0xa140a62d +0, 6406, 6406, 1, 2359296, 0xa140a62d +0, 6453, 6453, 1, 2359296, 0xa140a62d +0, 6469, 6469, 1, 2359296, 0xa140a62d +0, 6484, 6484, 1, 2359296, 0xa140a62d +0, 6500, 6500, 1, 2359296, 0xa140a62d +0, 6516, 6516, 1, 2359296, 0xa140a62d +0, 6531, 6531, 1, 2359296, 0xa140a62d +0, 6547, 6547, 1, 2359296, 0xa140a62d +0, 6562, 6562, 1, 2359296, 0x5c2a4cd9 +0, 6578, 6578, 1, 2359296, 0x28f94e4f +0, 6594, 6594, 1, 2359296, 0x9acb4820 +0, 6609, 6609, 1, 2359296, 0x9ec716e1 +0, 6625, 6625, 1, 2359296, 0xaf5f3fa4 +0, 6641, 6641, 1, 2359296, 0x7d633218 +0, 6642, 6642, 1, 2359296, 0x34fb2016 +0, 6656, 6656, 1, 2359296, 0x61351665 +0, 6812, 6812, 1, 2359296, 0xb23c1039 +0, 6828, 6828, 1, 2359296, 0x59290d69 +0, 6844, 6844, 1, 2359296, 0x639c132d +0, 6859, 6859, 1, 2359296, 0x0b252237 +0, 6875, 6875, 1, 2359296, 0xe66f2fc5 +0, 6891, 6891, 1, 2359296, 0xa8b33761 +0, 6906, 6906, 1, 2359296, 0x81a63f8b +0, 6969, 6969, 1, 2359296, 0x18074843 +0, 6984, 6984, 1, 2359296, 0x434a5195 +0, 7000, 7000, 1, 2359296, 0x6da15116 +0, 7001, 7001, 1, 2359296, 0xca755420 +0, 7016, 7016, 1, 2359296, 0xe6fc5457 +0, 7017, 7017, 1, 2359296, 0x271d53fd +0, 7031, 7031, 1, 2359296, 0xa15b554f +0, 7281, 7281, 1, 2359296, 0x49f6578d +0, 7282, 7282, 1, 2359296, 0x2c0c4e4f +0, 7297, 7297, 1, 2359296, 0x7e924e4f +0, 7298, 7298, 1, 2359296, 0x32ff4e4f +0, 7312, 7312, 1, 2359296, 0x23ad4e4f +0, 7313, 7313, 1, 2359296, 0x7ddc4e4f +0, 7328, 7328, 1, 2359296, 0xd0624e4f +0, 7329, 7329, 1, 2359296, 0x22f74e4f +0, 7781, 7781, 1, 2359296, 0x49fa4e4f +0, 7797, 7797, 1, 2359296, 0x6a5a5027 +0, 7812, 7812, 1, 2359296, 0x9f935027 +0, 7828, 7828, 1, 2359296, 0xc5e55027 +0, 7844, 7844, 1, 2359296, 0xd4cc5027 +0, 8250, 8250, 1, 2359296, 0xd2ab5027 +0, 8266, 8266, 1, 2359296, 0x68f04e4f +0, 8281, 8281, 1, 2359296, 0xd0b44e4f +0, 8297, 8297, 1, 2359296, 0xfced4e4f +0, 8298, 8298, 1, 2359296, 0x8b0d4e4f +0, 8312, 8312, 1, 2359296, 0x09db4e4f +0, 8328, 8328, 1, 2359296, 0x4d0f4e4f +0, 8329, 8329, 1, 2359296, 0xad824dbe +0, 8344, 8344, 1, 2359296, 0x9aca4dbe +0, 8345, 8345, 1, 2359296, 0x755a4dbe +0, 8359, 8359, 1, 2359296, 0xc6824d2d +0, 8360, 8360, 1, 2359296, 0x7c344c0e +0, 8375, 8375, 1, 2359296, 0x50f04c0e +0, 8391, 8391, 1, 2359296, 0xfa594c0e +0, 8406, 8406, 1, 2359296, 0x4d494c0e +0, 8422, 8422, 1, 2359296, 0xf6b24c0e +0, 8437, 8437, 1, 2359296, 0xcb6e4c0e +0, 8453, 8453, 1, 2359296, 0xbd024c0e +0, 8516, 8516, 1, 2359296, 0x245b4dbe +0, 8531, 8531, 1, 2359296, 0x47874e4f +0, 8547, 8547, 1, 2359296, 0xdead4e4f +0, 8562, 8562, 1, 2359296, 0x847e4e4f +0, 9344, 9344, 1, 2359296, 0x1a13e47c +0, 9345, 9345, 1, 2359296, 0x46b3e321 +0, 9876, 9876, 1, 2359296, 0x76c0e35d +0, 9922, 9922, 1, 2359296, 0xf6d9e519 +0, 9938, 9938, 1, 2359296, 0xac0fe4b3 +0, 9954, 9954, 1, 2359296, 0x3a3fe424 +0, 9955, 9955, 1, 2359296, 0xa97ce1a8 +0, 9969, 9969, 1, 2359296, 0x12fae01d +0, 9970, 9970, 1, 2359296, 0x65b4df14 +0, 9985, 9985, 1, 2359296, 0x82d0e032 +0, 9986, 9986, 1, 2359296, 0xa452e0cf +0, 10001, 10001, 1, 2359296, 0x22d6df37 diff -Nru ffmpeg-4.2.2/tests/ref/fate/gaplessenc-itunes-to-ipod-aac ffmpeg-4.4/tests/ref/fate/gaplessenc-itunes-to-ipod-aac --- ffmpeg-4.2.2/tests/ref/fate/gaplessenc-itunes-to-ipod-aac 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/gaplessenc-itunes-to-ipod-aac 2021-04-08 21:28:40.000000000 +0000 @@ -5,7 +5,7 @@ [/STREAM] [FORMAT] start_time=0.000000 -duration=2.367000 +duration=2.344000 [/FORMAT] packet|pts=-1024|dts=-1024|duration=1024|flags=KDside_data| diff -Nru ffmpeg-4.2.2/tests/ref/fate/gaplessenc-pcm-to-mov-aac ffmpeg-4.4/tests/ref/fate/gaplessenc-pcm-to-mov-aac --- ffmpeg-4.2.2/tests/ref/fate/gaplessenc-pcm-to-mov-aac 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/gaplessenc-pcm-to-mov-aac 2021-04-08 21:28:40.000000000 +0000 @@ -5,7 +5,7 @@ [/STREAM] [FORMAT] start_time=0.000000 -duration=12.024000 +duration=12.000000 [/FORMAT] packet|pts=-1024|dts=-1024|duration=1024|flags=KDside_data| diff -Nru ffmpeg-4.2.2/tests/ref/fate/gaplessinfo-itunes1 ffmpeg-4.4/tests/ref/fate/gaplessinfo-itunes1 --- ffmpeg-4.2.2/tests/ref/fate/gaplessinfo-itunes1 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/gaplessinfo-itunes1 2021-04-08 21:28:40.000000000 +0000 @@ -24,7 +24,7 @@ packet|pts=1292288|dts=1292288|duration=1024|flags=K_ packet|pts=1293312|dts=1293312|duration=1024|flags=K_ stream|nb_read_packets=1264 -frame|pkt_pts=2112|pkt_dts=2112|best_effort_timestamp=2048|pkt_duration=960|nb_samples=960 +frame|pkt_pts=2112|pkt_dts=2112|best_effort_timestamp=2112|pkt_duration=960|nb_samples=960 frame|pkt_pts=3072|pkt_dts=3072|best_effort_timestamp=3072|pkt_duration=1024|nb_samples=1024 frame|pkt_pts=4096|pkt_dts=4096|best_effort_timestamp=4096|pkt_duration=1024|nb_samples=1024 frame|pkt_pts=5120|pkt_dts=5120|best_effort_timestamp=5120|pkt_duration=1024|nb_samples=1024 diff -Nru ffmpeg-4.2.2/tests/ref/fate/gaplessinfo-itunes2 ffmpeg-4.4/tests/ref/fate/gaplessinfo-itunes2 --- ffmpeg-4.2.2/tests/ref/fate/gaplessinfo-itunes2 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/gaplessinfo-itunes2 2021-04-08 21:28:40.000000000 +0000 @@ -24,7 +24,7 @@ packet|pts=103424|dts=103424|duration=1024|flags=K_ packet|pts=104448|dts=104448|duration=1024|flags=K_ stream|nb_read_packets=103 -frame|pkt_pts=2112|pkt_dts=2112|best_effort_timestamp=2048|pkt_duration=960|nb_samples=960 +frame|pkt_pts=2112|pkt_dts=2112|best_effort_timestamp=2112|pkt_duration=960|nb_samples=960 frame|pkt_pts=3072|pkt_dts=3072|best_effort_timestamp=3072|pkt_duration=1024|nb_samples=1024 frame|pkt_pts=4096|pkt_dts=4096|best_effort_timestamp=4096|pkt_duration=1024|nb_samples=1024 frame|pkt_pts=5120|pkt_dts=5120|best_effort_timestamp=5120|pkt_duration=1024|nb_samples=1024 diff -Nru ffmpeg-4.2.2/tests/ref/fate/gifenc-bgr4_byte ffmpeg-4.4/tests/ref/fate/gifenc-bgr4_byte --- ffmpeg-4.2.2/tests/ref/fate/gifenc-bgr4_byte 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/gifenc-bgr4_byte 2020-07-11 10:39:30.000000000 +0000 @@ -4,175 +4,175 @@ #dimensions 0: 217x217 #sar 0: 0/1 0, 0, 0, 1, 1297, 0x53e8b1c1 -0, 1, 1, 1, 221, 0x52d24d05, F=0x0 -0, 2, 2, 1, 139, 0xc9e32ab4, F=0x0 -0, 3, 3, 1, 392, 0x9244a858, F=0x0 -0, 4, 4, 1, 389, 0xc5bea3e0, F=0x0 -0, 5, 5, 1, 438, 0xfa2ab3d6, F=0x0 -0, 6, 6, 1, 526, 0x281ed94f, F=0x0 -0, 7, 7, 1, 543, 0xa53ee752, F=0x0 -0, 8, 8, 1, 446, 0x41d0b8ee, F=0x0 -0, 9, 9, 1, 931, 0xe8efa4aa, F=0x0 -0, 10, 10, 1, 702, 0x2d1c4ad3, F=0x0 -0, 11, 11, 1, 1202, 0xf0cc2be3, F=0x0 -0, 12, 12, 1, 1299, 0x189f54cb, F=0x0 -0, 13, 13, 1, 1253, 0xcb883414, F=0x0 -0, 14, 14, 1, 1338, 0xad6a52d2, F=0x0 -0, 15, 15, 1, 1284, 0x14993a0a, F=0x0 -0, 16, 16, 1, 1483, 0x216c991d, F=0x0 -0, 17, 17, 1, 1792, 0x58eb4c1e, F=0x0 -0, 18, 18, 1, 1683, 0x0b49fbbe, F=0x0 -0, 19, 19, 1, 1517, 0x9b57ab38, F=0x0 -0, 20, 20, 1, 1713, 0x23f21b0d, F=0x0 -0, 21, 21, 1, 1753, 0xe1e21eec, F=0x0 -0, 22, 22, 1, 1650, 0xf258037d, F=0x0 -0, 23, 23, 1, 1726, 0x73111ff6, F=0x0 -0, 24, 24, 1, 1908, 0x430b7b09, F=0x0 -0, 25, 25, 1, 1815, 0xa5af5368, F=0x0 -0, 26, 26, 1, 1923, 0x497f847c, F=0x0 -0, 27, 27, 1, 2108, 0x5e2ed19b, F=0x0 -0, 28, 28, 1, 2708, 0x6064f1c3, F=0x0 -0, 29, 29, 1, 2681, 0x7c4ea945, F=0x0 -0, 30, 30, 1, 2903, 0x7cbf4985, F=0x0 -0, 31, 31, 1, 3265, 0x81f7d05c, F=0x0 -0, 32, 32, 1, 3187, 0x6077c273, F=0x0 -0, 33, 33, 1, 3304, 0x3632e867, F=0x0 -0, 34, 34, 1, 3608, 0x7961776c, F=0x0 -0, 35, 35, 1, 3707, 0x515aa11b, F=0x0 -0, 36, 36, 1, 3822, 0x4a03d52c, F=0x0 -0, 37, 37, 1, 3635, 0x67607edf, F=0x0 -0, 38, 38, 1, 2958, 0x18e8618d, F=0x0 -0, 39, 39, 1, 3094, 0x1f1990fa, F=0x0 -0, 40, 40, 1, 3102, 0xde16868b, F=0x0 -0, 41, 41, 1, 3464, 0x7e6f2dba, F=0x0 -0, 42, 42, 1, 4116, 0x91585d9e, F=0x0 -0, 43, 43, 1, 4225, 0x9c785cdc, F=0x0 -0, 44, 44, 1, 3621, 0x0d0a4ebb, F=0x0 -0, 45, 45, 1, 3918, 0xa70ae7ca, F=0x0 -0, 46, 46, 1, 4469, 0xa318e475, F=0x0 -0, 47, 47, 1, 4601, 0x1ae12f09, F=0x0 -0, 48, 48, 1, 4830, 0x57b999bb, F=0x0 -0, 49, 49, 1, 5406, 0x744cc456, F=0x0 -0, 50, 50, 1, 5274, 0x3d6996e2, F=0x0 -0, 51, 51, 1, 5424, 0xc587e525, F=0x0 -0, 52, 52, 1, 5527, 0xd5870857, F=0x0 -0, 53, 53, 1, 5709, 0xbd715dd4, F=0x0 -0, 54, 54, 1, 6168, 0xa5c13fbb, F=0x0 -0, 55, 55, 1, 6241, 0x46485256, F=0x0 -0, 56, 56, 1, 5919, 0xc0bcc64e, F=0x0 -0, 57, 57, 1, 6005, 0x5443fb4d, F=0x0 -0, 58, 58, 1, 5954, 0xe7efef37, F=0x0 -0, 59, 59, 1, 6476, 0x1aadccc4, F=0x0 -0, 60, 60, 1, 6745, 0x6af23ae4, F=0x0 -0, 61, 61, 1, 6283, 0x07049084, F=0x0 -0, 62, 62, 1, 6649, 0x2c1f3be5, F=0x0 -0, 63, 63, 1, 6386, 0xb9848778, F=0x0 -0, 64, 64, 1, 6265, 0xce725997, F=0x0 -0, 65, 65, 1, 6916, 0xdfac7154, F=0x0 -0, 66, 66, 1, 7238, 0x2ace2606, F=0x0 -0, 67, 67, 1, 7564, 0x8cf9a84a, F=0x0 -0, 68, 68, 1, 7421, 0xaa1a71dc, F=0x0 -0, 69, 69, 1, 7484, 0xc67ba899, F=0x0 -0, 70, 70, 1, 7604, 0x2479e569, F=0x0 -0, 71, 71, 1, 7764, 0x0a1906f8, F=0x0 -0, 72, 72, 1, 8023, 0x27206bb7, F=0x0 -0, 73, 73, 1, 8136, 0x7705bf63, F=0x0 -0, 74, 74, 1, 8109, 0xe05cb4da, F=0x0 -0, 75, 75, 1, 7871, 0xce733f35, F=0x0 -0, 76, 76, 1, 7968, 0x27ef92ba, F=0x0 -0, 77, 77, 1, 8246, 0x5fe7ee2b, F=0x0 -0, 78, 78, 1, 8329, 0x809e4b94, F=0x0 -0, 79, 79, 1, 8570, 0x179fc163, F=0x0 -0, 80, 80, 1, 8754, 0xdb870edf, F=0x0 -0, 81, 81, 1, 8586, 0x280ca5f9, F=0x0 -0, 82, 82, 1, 8886, 0x445e5b51, F=0x0 -0, 83, 83, 1, 9085, 0xba37592e, F=0x0 -0, 84, 84, 1, 9318, 0xe970f8b2, F=0x0 -0, 85, 85, 1, 9402, 0x37ee4456, F=0x0 -0, 86, 86, 1, 9169, 0x171196bf, F=0x0 -0, 87, 87, 1, 9470, 0x793837fb, F=0x0 -0, 88, 88, 1, 9658, 0x489294a6, F=0x0 -0, 89, 89, 1, 9709, 0x980c9d78, F=0x0 -0, 90, 90, 1, 9531, 0xc7a83dbb, F=0x0 -0, 91, 91, 1, 9899, 0x658f0fcb, F=0x0 -0, 92, 92, 1, 10013, 0x434c4b1f, F=0x0 -0, 93, 93, 1, 10046, 0x3cdf2e5d, F=0x0 -0, 94, 94, 1, 10094, 0xfeb546c5, F=0x0 -0, 95, 95, 1, 10446, 0xf0d10017, F=0x0 -0, 96, 96, 1, 10591, 0xf90f55af, F=0x0 -0, 97, 97, 1, 10589, 0xd4948126, F=0x0 -0, 98, 98, 1, 10815, 0x5cb2d81b, F=0x0 -0, 99, 99, 1, 11119, 0x25ca4d4b, F=0x0 -0, 100, 100, 1, 11202, 0xae566cab, F=0x0 -0, 101, 101, 1, 11248, 0x5731a277, F=0x0 -0, 102, 102, 1, 11491, 0x1021f4fd, F=0x0 -0, 103, 103, 1, 11688, 0x6cb05cf9, F=0x0 -0, 104, 104, 1, 11793, 0xf036b8cb, F=0x0 -0, 105, 105, 1, 11444, 0x46d90941, F=0x0 -0, 106, 106, 1, 11936, 0x204acadf, F=0x0 -0, 107, 107, 1, 11940, 0x4bddbdf6, F=0x0 -0, 108, 108, 1, 12289, 0x902d708b, F=0x0 -0, 109, 109, 1, 12342, 0xc85680b0, F=0x0 -0, 110, 110, 1, 12460, 0xf3beb2c0, F=0x0 -0, 111, 111, 1, 12703, 0x96493c66, F=0x0 -0, 112, 112, 1, 12676, 0xdc9250b1, F=0x0 -0, 113, 113, 1, 12965, 0x08dba0c4, F=0x0 -0, 114, 114, 1, 13062, 0xac2ce092, F=0x0 -0, 115, 115, 1, 13155, 0xb6552cf5, F=0x0 -0, 116, 116, 1, 13179, 0x03d61a97, F=0x0 -0, 117, 117, 1, 13206, 0x0d8a5a0c, F=0x0 -0, 118, 118, 1, 13219, 0x039862cb, F=0x0 -0, 119, 119, 1, 13218, 0xede6623f, F=0x0 -0, 120, 120, 1, 13475, 0x7672a260, F=0x0 -0, 121, 121, 1, 13673, 0xaf0ddf16, F=0x0 -0, 122, 122, 1, 13700, 0x1ec9ed11, F=0x0 -0, 123, 123, 1, 13829, 0xc6cb2f9a, F=0x0 -0, 124, 124, 1, 13954, 0x3f89936d, F=0x0 -0, 125, 125, 1, 14071, 0x72d2d42d, F=0x0 -0, 126, 126, 1, 14132, 0x6c34cbf9, F=0x0 -0, 127, 127, 1, 14339, 0x4c695263, F=0x0 -0, 128, 128, 1, 14477, 0xfbcda593, F=0x0 -0, 129, 129, 1, 14544, 0xb3d3a37a, F=0x0 -0, 130, 130, 1, 14616, 0xb704d286, F=0x0 -0, 131, 131, 1, 14906, 0xca9226c6, F=0x0 -0, 132, 132, 1, 14986, 0x54e8a122, F=0x0 -0, 133, 133, 1, 15150, 0x40bed744, F=0x0 -0, 134, 134, 1, 15137, 0x6c4ebc1f, F=0x0 -0, 135, 135, 1, 15251, 0xca081273, F=0x0 -0, 136, 136, 1, 15345, 0x4d266373, F=0x0 -0, 137, 137, 1, 15646, 0x3f64a238, F=0x0 -0, 138, 138, 1, 15920, 0xe12020ea, F=0x0 -0, 139, 139, 1, 16049, 0x6bbb437e, F=0x0 -0, 140, 140, 1, 16236, 0x31a6016d, F=0x0 -0, 141, 141, 1, 16270, 0x40f1eb89, F=0x0 -0, 142, 142, 1, 16379, 0xe4d0092a, F=0x0 -0, 143, 143, 1, 16669, 0x6f22a6ca, F=0x0 -0, 144, 144, 1, 16925, 0x564a191d, F=0x0 -0, 145, 145, 1, 17157, 0xf1c7cb79, F=0x0 -0, 146, 146, 1, 17180, 0xc4b3b5d7, F=0x0 -0, 147, 147, 1, 17323, 0xa670a9d8, F=0x0 -0, 148, 148, 1, 17405, 0xf499125a, F=0x0 -0, 149, 149, 1, 17439, 0xd76af40b, F=0x0 -0, 150, 150, 1, 17584, 0x364d53e5, F=0x0 -0, 151, 151, 1, 17772, 0xbc218e98, F=0x0 -0, 152, 152, 1, 17834, 0xcc19808f, F=0x0 -0, 153, 153, 1, 17926, 0x12639cd7, F=0x0 -0, 154, 154, 1, 17831, 0xb0f9c051, F=0x0 -0, 155, 155, 1, 18150, 0x574022e1, F=0x0 -0, 156, 156, 1, 18265, 0x73458364, F=0x0 -0, 157, 157, 1, 18345, 0x2d31c3b1, F=0x0 -0, 158, 158, 1, 18301, 0x9028389e, F=0x0 -0, 159, 159, 1, 18426, 0xe701be30, F=0x0 -0, 160, 160, 1, 18615, 0x1bfd4868, F=0x0 -0, 161, 161, 1, 18924, 0xa269bcfe, F=0x0 -0, 162, 162, 1, 19081, 0xb2f5052e, F=0x0 -0, 163, 163, 1, 19176, 0x0676ff5f, F=0x0 -0, 164, 164, 1, 19218, 0xfbb40323, F=0x0 -0, 165, 165, 1, 19406, 0x714664fe, F=0x0 -0, 166, 166, 1, 19488, 0x1acf9f93, F=0x0 -0, 167, 167, 1, 19667, 0x50bd11c0, F=0x0 -0, 168, 168, 1, 19680, 0xe322168b, F=0x0 -0, 169, 169, 1, 19944, 0x25b763c2, F=0x0 -0, 170, 170, 1, 19983, 0xfd109bea, F=0x0 -0, 171, 171, 1, 20029, 0x565d8efd, F=0x0 -0, 172, 172, 1, 20068, 0xadee793f, F=0x0 +0, 1, 1, 1, 158, 0xe1873465, F=0x0 +0, 2, 2, 1, 143, 0x56992b17, F=0x0 +0, 3, 3, 1, 169, 0x4f0434c7, F=0x0 +0, 4, 4, 1, 254, 0xb4845bf3, F=0x0 +0, 5, 5, 1, 221, 0xa02a4ae2, F=0x0 +0, 6, 6, 1, 176, 0xdcfc3a8b, F=0x0 +0, 7, 7, 1, 189, 0xb45f3f8d, F=0x0 +0, 8, 8, 1, 139, 0xf2622fc0, F=0x0 +0, 9, 9, 1, 160, 0xf77b327d, F=0x0 +0, 10, 10, 1, 149, 0x56b62de9, F=0x0 +0, 11, 11, 1, 190, 0x1eca3f72, F=0x0 +0, 12, 12, 1, 308, 0xfc7373fc, F=0x0 +0, 13, 13, 1, 193, 0x94304232, F=0x0 +0, 14, 14, 1, 191, 0x82e84504, F=0x0 +0, 15, 15, 1, 198, 0xd31944a2, F=0x0 +0, 16, 16, 1, 417, 0x9547ac22, F=0x0 +0, 17, 17, 1, 163, 0xb55537d0, F=0x0 +0, 18, 18, 1, 383, 0x634f9f88, F=0x0 +0, 19, 19, 1, 193, 0xf6d24046, F=0x0 +0, 20, 20, 1, 337, 0x45d6916f, F=0x0 +0, 21, 21, 1, 199, 0xabb34a72, F=0x0 +0, 22, 22, 1, 308, 0x097f7e58, F=0x0 +0, 23, 23, 1, 186, 0x369b41cc, F=0x0 +0, 24, 24, 1, 199, 0xa93c4113, F=0x0 +0, 25, 25, 1, 163, 0x16823904, F=0x0 +0, 26, 26, 1, 302, 0xaf1d78da, F=0x0 +0, 27, 27, 1, 189, 0x3f7a3bde, F=0x0 +0, 28, 28, 1, 157, 0x45e23500, F=0x0 +0, 29, 29, 1, 205, 0x797b4510, F=0x0 +0, 30, 30, 1, 160, 0x20e533d1, F=0x0 +0, 31, 31, 1, 202, 0xd3b748b3, F=0x0 +0, 32, 32, 1, 160, 0x207c371f, F=0x0 +0, 33, 33, 1, 215, 0x079951b6, F=0x0 +0, 34, 34, 1, 422, 0xbb9db080, F=0x0 +0, 35, 35, 1, 184, 0x3a044098, F=0x0 +0, 36, 36, 1, 289, 0xf2757206, F=0x0 +0, 37, 37, 1, 190, 0xc3264203, F=0x0 +0, 38, 38, 1, 195, 0x28544262, F=0x0 +0, 39, 39, 1, 199, 0x32db4bba, F=0x0 +0, 40, 40, 1, 448, 0x64a8bfe8, F=0x0 +0, 41, 41, 1, 170, 0x62a536d7, F=0x0 +0, 42, 42, 1, 279, 0xe1df6ff6, F=0x0 +0, 43, 43, 1, 180, 0x762f3aac, F=0x0 +0, 44, 44, 1, 303, 0x73727c79, F=0x0 +0, 45, 45, 1, 209, 0xf4a8515c, F=0x0 +0, 46, 46, 1, 198, 0xe09f451e, F=0x0 +0, 47, 47, 1, 194, 0x301e4b04, F=0x0 +0, 48, 48, 1, 186, 0x7c66421b, F=0x0 +0, 49, 49, 1, 1200, 0xe55e34e7, F=0x0 +0, 50, 50, 1, 204, 0x25534779, F=0x0 +0, 51, 51, 1, 1066, 0x9792efa8, F=0x0 +0, 52, 52, 1, 187, 0xd82e41f0, F=0x0 +0, 53, 53, 1, 323, 0x0f9d8485, F=0x0 +0, 54, 54, 1, 205, 0x86ef4c75, F=0x0 +0, 55, 55, 1, 213, 0x6e515113, F=0x0 +0, 56, 56, 1, 208, 0x1ac84bed, F=0x0 +0, 57, 57, 1, 737, 0x68a047be, F=0x0 +0, 58, 58, 1, 181, 0x84353a71, F=0x0 +0, 59, 59, 1, 614, 0x3c9a142a, F=0x0 +0, 60, 60, 1, 215, 0xacaf535d, F=0x0 +0, 61, 61, 1, 291, 0x4dab7020, F=0x0 +0, 62, 62, 1, 208, 0x3dd84d1f, F=0x0 +0, 63, 63, 1, 208, 0x8ccb45cc, F=0x0 +0, 64, 64, 1, 203, 0xa905456b, F=0x0 +0, 65, 65, 1, 531, 0x6b32eaf4, F=0x0 +0, 66, 66, 1, 178, 0xd30b3bff, F=0x0 +0, 67, 67, 1, 446, 0x881abe2a, F=0x0 +0, 68, 68, 1, 188, 0xb5a43e6b, F=0x0 +0, 69, 69, 1, 177, 0x9255436c, F=0x0 +0, 70, 70, 1, 112, 0x2990213a, F=0x0 +0, 71, 71, 1, 296, 0x7d6e7183, F=0x0 +0, 72, 72, 1, 153, 0x35053313, F=0x0 +0, 73, 73, 1, 218, 0xcf105015, F=0x0 +0, 74, 74, 1, 202, 0xb4634837, F=0x0 +0, 75, 75, 1, 239, 0x0a4b5b7b, F=0x0 +0, 76, 76, 1, 139, 0x18d92e35, F=0x0 +0, 77, 77, 1, 467, 0x784dc79e, F=0x0 +0, 78, 78, 1, 274, 0x1e9b78ef, F=0x0 +0, 79, 79, 1, 404, 0xb5c6ab9b, F=0x0 +0, 80, 80, 1, 257, 0x7aaa66ce, F=0x0 +0, 81, 81, 1, 419, 0xcb62b6cb, F=0x0 +0, 82, 82, 1, 208, 0xcbba506d, F=0x0 +0, 83, 83, 1, 294, 0x031a76f9, F=0x0 +0, 84, 84, 1, 191, 0x5ba83f77, F=0x0 +0, 85, 85, 1, 181, 0xfc454323, F=0x0 +0, 86, 86, 1, 218, 0xcd7e540e, F=0x0 +0, 87, 87, 1, 423, 0xdcebc01f, F=0x0 +0, 88, 88, 1, 202, 0x160a4ab6, F=0x0 +0, 89, 89, 1, 317, 0xff2b8104, F=0x0 +0, 90, 90, 1, 172, 0x68753e2d, F=0x0 +0, 91, 91, 1, 275, 0x7f766cd1, F=0x0 +0, 92, 92, 1, 214, 0xf37e5043, F=0x0 +0, 93, 93, 1, 182, 0x5e5544f6, F=0x0 +0, 94, 94, 1, 151, 0xf74532b7, F=0x0 +0, 95, 95, 1, 157, 0xe99b33b0, F=0x0 +0, 96, 96, 1, 202, 0x77994327, F=0x0 +0, 97, 97, 1, 162, 0x93f235fc, F=0x0 +0, 98, 98, 1, 186, 0xc25d3f3f, F=0x0 +0, 99, 99, 1, 318, 0xdf547809, F=0x0 +0, 100, 100, 1, 225, 0xf8074f18, F=0x0 +0, 101, 101, 1, 207, 0x12204757, F=0x0 +0, 102, 102, 1, 212, 0xd2ec4c59, F=0x0 +0, 103, 103, 1, 153, 0x0e1c33cd, F=0x0 +0, 104, 104, 1, 196, 0x45d4455d, F=0x0 +0, 105, 105, 1, 146, 0x5dba32b0, F=0x0 +0, 106, 106, 1, 194, 0x13a8490b, F=0x0 +0, 107, 107, 1, 304, 0xcf73832f, F=0x0 +0, 108, 108, 1, 194, 0x68fd43c9, F=0x0 +0, 109, 109, 1, 190, 0xdbc64442, F=0x0 +0, 110, 110, 1, 204, 0x8eb94b27, F=0x0 +0, 111, 111, 1, 136, 0xd0162d03, F=0x0 +0, 112, 112, 1, 171, 0xbb8b3d15, F=0x0 +0, 113, 113, 1, 140, 0x4cb930a9, F=0x0 +0, 114, 114, 1, 158, 0xdebb32d2, F=0x0 +0, 115, 115, 1, 94, 0x16a71c65, F=0x0 +0, 116, 116, 1, 110, 0x358d20bf, F=0x0 +0, 117, 117, 1, 256, 0x49a469b7, F=0x0 +0, 118, 118, 1, 220, 0x08b95486, F=0x0 +0, 119, 119, 1, 221, 0xe0af4f92, F=0x0 +0, 120, 120, 1, 205, 0x7ac444a5, F=0x0 +0, 121, 121, 1, 169, 0x62c039d3, F=0x0 +0, 122, 122, 1, 970, 0xc8f6c8a6, F=0x0 +0, 123, 123, 1, 181, 0x0d9c42ba, F=0x0 +0, 124, 124, 1, 955, 0xdf5dba5e, F=0x0 +0, 125, 125, 1, 158, 0xa01833fd, F=0x0 +0, 126, 126, 1, 344, 0xd17989f3, F=0x0 +0, 127, 127, 1, 627, 0x8c611977, F=0x0 +0, 128, 128, 1, 172, 0x7cf83c63, F=0x0 +0, 129, 129, 1, 494, 0xadccdc2b, F=0x0 +0, 130, 130, 1, 184, 0x4e784407, F=0x0 +0, 131, 131, 1, 352, 0x852f992b, F=0x0 +0, 132, 132, 1, 351, 0x99e78bb8, F=0x0 +0, 133, 133, 1, 170, 0x9f4b3869, F=0x0 +0, 134, 134, 1, 275, 0x29b96b3c, F=0x0 +0, 135, 135, 1, 168, 0x98d0399b, F=0x0 +0, 136, 136, 1, 169, 0x015039aa, F=0x0 +0, 137, 137, 1, 521, 0x3c33db57, F=0x0 +0, 138, 138, 1, 1262, 0x9cf44321, F=0x0 +0, 139, 139, 1, 994, 0x5ea8bcd4, F=0x0 +0, 140, 140, 1, 290, 0xf24f72b0, F=0x0 +0, 141, 141, 1, 188, 0x36cb408f, F=0x0 +0, 142, 142, 1, 164, 0x6c813b02, F=0x0 +0, 143, 143, 1, 212, 0x1dfb463e, F=0x0 +0, 144, 144, 1, 870, 0xd89e94ed, F=0x0 +0, 145, 145, 1, 635, 0x87bf1ae2, F=0x0 +0, 146, 146, 1, 290, 0x34ff78fe, F=0x0 +0, 147, 147, 1, 211, 0x9f755207, F=0x0 +0, 148, 148, 1, 177, 0x3f003c44, F=0x0 +0, 149, 149, 1, 182, 0xe8c23eea, F=0x0 +0, 150, 150, 1, 588, 0xb4b9fc5d, F=0x0 +0, 151, 151, 1, 163, 0x3078356b, F=0x0 +0, 152, 152, 1, 407, 0x4161b245, F=0x0 +0, 153, 153, 1, 204, 0xe2a64478, F=0x0 +0, 154, 154, 1, 290, 0x5cc079af, F=0x0 +0, 155, 155, 1, 308, 0xf5958253, F=0x0 +0, 156, 156, 1, 196, 0xb1cb46f0, F=0x0 +0, 157, 157, 1, 181, 0x0aee4103, F=0x0 +0, 158, 158, 1, 203, 0x36784ee0, F=0x0 +0, 159, 159, 1, 227, 0x23fd5b71, F=0x0 +0, 160, 160, 1, 524, 0x18a6e404, F=0x0 +0, 161, 161, 1, 377, 0x1f5697de, F=0x0 +0, 162, 162, 1, 196, 0x72304538, F=0x0 +0, 163, 163, 1, 250, 0xb8e46580, F=0x0 +0, 164, 164, 1, 214, 0xe9df51b6, F=0x0 +0, 165, 165, 1, 323, 0xacbb9067, F=0x0 +0, 166, 166, 1, 176, 0xa12a410c, F=0x0 +0, 167, 167, 1, 305, 0x21227d7a, F=0x0 +0, 168, 168, 1, 179, 0x3dac422b, F=0x0 +0, 169, 169, 1, 245, 0x948963cd, F=0x0 +0, 170, 170, 1, 181, 0x407140fb, F=0x0 +0, 171, 171, 1, 241, 0xd2a35a7a, F=0x0 +0, 172, 172, 1, 172, 0x9fa83e96, F=0x0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/gifenc-bgr8 ffmpeg-4.4/tests/ref/fate/gifenc-bgr8 --- ffmpeg-4.2.2/tests/ref/fate/gifenc-bgr8 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/gifenc-bgr8 2020-07-11 10:39:30.000000000 +0000 @@ -4,175 +4,175 @@ #dimensions 0: 217x217 #sar 0: 0/1 0, 0, 0, 1, 1341, 0xe4e2af18 -0, 1, 1, 1, 305, 0xefa98bbd, F=0x0 -0, 2, 2, 1, 446, 0x9499cf43, F=0x0 -0, 3, 3, 1, 458, 0x8cb7d0d5, F=0x0 -0, 4, 4, 1, 555, 0x41f2fe63, F=0x0 -0, 5, 5, 1, 622, 0x3651212e, F=0x0 -0, 6, 6, 1, 650, 0x67542087, F=0x0 -0, 7, 7, 1, 668, 0x392934ca, F=0x0 -0, 8, 8, 1, 829, 0x6cd07a33, F=0x0 -0, 9, 9, 1, 1165, 0xb64b2ec9, F=0x0 -0, 10, 10, 1, 187, 0x114a52a4, F=0x0 -0, 11, 11, 1, 1341, 0x6ca57064, F=0x0 -0, 12, 12, 1, 1646, 0xcdd90fae, F=0x0 -0, 13, 13, 1, 1539, 0xbf75e55f, F=0x0 -0, 14, 14, 1, 1728, 0x96b14714, F=0x0 -0, 15, 15, 1, 1918, 0xffd08446, F=0x0 -0, 16, 16, 1, 2132, 0x3d5ae258, F=0x0 -0, 17, 17, 1, 2256, 0x359526d9, F=0x0 -0, 18, 18, 1, 2319, 0x553c382b, F=0x0 -0, 19, 19, 1, 2416, 0x7ac37066, F=0x0 -0, 20, 20, 1, 2609, 0x552bc27f, F=0x0 -0, 21, 21, 1, 2695, 0xbb0c020e, F=0x0 -0, 22, 22, 1, 2792, 0x46670f7d, F=0x0 -0, 23, 23, 1, 2892, 0x5674481e, F=0x0 -0, 24, 24, 1, 2990, 0x015a7bfd, F=0x0 -0, 25, 25, 1, 3109, 0xc73e9d14, F=0x0 -0, 26, 26, 1, 3261, 0x8a77f522, F=0x0 -0, 27, 27, 1, 3337, 0xf6f92558, F=0x0 -0, 28, 28, 1, 3580, 0x23408bc8, F=0x0 -0, 29, 29, 1, 3815, 0x781dfb1b, F=0x0 -0, 30, 30, 1, 2758, 0xf5cd1d5b, F=0x0 -0, 31, 31, 1, 4039, 0x7909712e, F=0x0 -0, 32, 32, 1, 3033, 0x39089d44, F=0x0 -0, 33, 33, 1, 4303, 0x667b0c60, F=0x0 -0, 34, 34, 1, 2052, 0x9edfba63, F=0x0 -0, 35, 35, 1, 3220, 0x5a56f015, F=0x0 -0, 36, 36, 1, 2300, 0x1719645c, F=0x0 -0, 37, 37, 1, 3641, 0x71c49a57, F=0x0 -0, 38, 38, 1, 3560, 0x377575b8, F=0x0 -0, 39, 39, 1, 3698, 0x165adce0, F=0x0 -0, 40, 40, 1, 1567, 0x6ecbf672, F=0x0 -0, 41, 41, 1, 962, 0x21eccba1, F=0x0 -0, 42, 42, 1, 281, 0x7a5a7ac3, F=0x0 -0, 43, 43, 1, 938, 0x659bb1ec, F=0x0 -0, 44, 44, 1, 279, 0x71e181bc, F=0x0 -0, 45, 45, 1, 204, 0xe0765316, F=0x0 -0, 46, 46, 1, 4307, 0xdbdd0e7d, F=0x0 -0, 47, 47, 1, 4903, 0xd8d24194, F=0x0 -0, 48, 48, 1, 4936, 0x6e9f1aff, F=0x0 -0, 49, 49, 1, 4949, 0xb3115902, F=0x0 -0, 50, 50, 1, 4162, 0xee2cad5b, F=0x0 -0, 51, 51, 1, 4686, 0xd583c178, F=0x0 -0, 52, 52, 1, 4749, 0x8c93b6a9, F=0x0 -0, 53, 53, 1, 4990, 0x12f957fd, F=0x0 -0, 54, 54, 1, 5187, 0xf3bcc7c9, F=0x0 -0, 55, 55, 1, 5054, 0xa27684fb, F=0x0 -0, 56, 56, 1, 5148, 0xe76cbad7, F=0x0 -0, 57, 57, 1, 4309, 0x79f7f067, F=0x0 -0, 58, 58, 1, 5087, 0xa2e29f29, F=0x0 -0, 59, 59, 1, 5292, 0xd158e4db, F=0x0 -0, 60, 60, 1, 5434, 0xe0be16f5, F=0x0 -0, 61, 61, 1, 4653, 0x0a3d8a5e, F=0x0 -0, 62, 62, 1, 5271, 0x4412d0a5, F=0x0 -0, 63, 63, 1, 5229, 0x3e06c4f2, F=0x0 -0, 64, 64, 1, 5225, 0x9bc39cfa, F=0x0 -0, 65, 65, 1, 5403, 0x798b009d, F=0x0 -0, 66, 66, 1, 5228, 0x14f2dded, F=0x0 -0, 67, 67, 1, 5712, 0x8724debe, F=0x0 -0, 68, 68, 1, 5644, 0x49d3a383, F=0x0 -0, 69, 69, 1, 5826, 0xde72e0ba, F=0x0 -0, 70, 70, 1, 5771, 0x62efd718, F=0x0 -0, 71, 71, 1, 6124, 0xb2a68c70, F=0x0 -0, 72, 72, 1, 6077, 0xb48b693f, F=0x0 -0, 73, 73, 1, 5804, 0xb700db6c, F=0x0 -0, 74, 74, 1, 6007, 0x02953898, F=0x0 -0, 75, 75, 1, 6228, 0x87a7b197, F=0x0 -0, 76, 76, 1, 6382, 0x49e7e65b, F=0x0 -0, 77, 77, 1, 6473, 0x3b9b6c3d, F=0x0 -0, 78, 78, 1, 7027, 0x2a4e1c17, F=0x0 -0, 79, 79, 1, 7263, 0x2e48c2e7, F=0x0 -0, 80, 80, 1, 8205, 0x013b701a, F=0x0 -0, 81, 81, 1, 8366, 0xcca97b10, F=0x0 -0, 82, 82, 1, 7716, 0x3b088fb3, F=0x0 -0, 83, 83, 1, 7420, 0xefdd1187, F=0x0 -0, 84, 84, 1, 7549, 0x1731227c, F=0x0 -0, 85, 85, 1, 7956, 0x8186ceb3, F=0x0 -0, 86, 86, 1, 8416, 0x23add53c, F=0x0 -0, 87, 87, 1, 8064, 0x09c616c4, F=0x0 -0, 88, 88, 1, 7409, 0x9d98af03, F=0x0 -0, 89, 89, 1, 7502, 0x0b81ebf3, F=0x0 -0, 90, 90, 1, 7814, 0x2f0d75cb, F=0x0 -0, 91, 91, 1, 7776, 0x45d6800f, F=0x0 -0, 92, 92, 1, 7757, 0x777f98b6, F=0x0 -0, 93, 93, 1, 8055, 0x4eea1634, F=0x0 -0, 94, 94, 1, 7626, 0xfb3931fd, F=0x0 -0, 95, 95, 1, 7987, 0x22a1d052, F=0x0 -0, 96, 96, 1, 12070, 0x3aa2924d, F=0x0 -0, 97, 97, 1, 12325, 0xda6cd811, F=0x0 -0, 98, 98, 1, 12225, 0xd478e671, F=0x0 -0, 99, 99, 1, 11235, 0xc6c09240, F=0x0 -0, 100, 100, 1, 11116, 0x95050c25, F=0x0 -0, 101, 101, 1, 11374, 0x14a68e3d, F=0x0 -0, 102, 102, 1, 11904, 0xb14436f2, F=0x0 -0, 103, 103, 1, 11487, 0xa3358311, F=0x0 -0, 104, 104, 1, 13403, 0xccf33a00, F=0x0 -0, 105, 105, 1, 12921, 0xbf7e4759, F=0x0 -0, 106, 106, 1, 13872, 0x7dace890, F=0x0 -0, 107, 107, 1, 13559, 0xb6c868f9, F=0x0 -0, 108, 108, 1, 14049, 0xa5d569b0, F=0x0 -0, 109, 109, 1, 14152, 0x8c9c31fb, F=0x0 -0, 110, 110, 1, 14285, 0x2ffe3bc3, F=0x0 -0, 111, 111, 1, 14432, 0x27abe196, F=0x0 -0, 112, 112, 1, 14697, 0x20d1aedd, F=0x0 -0, 113, 113, 1, 14606, 0xbcbe586d, F=0x0 -0, 114, 114, 1, 15221, 0x515f8224, F=0x0 -0, 115, 115, 1, 15433, 0x68089081, F=0x0 -0, 116, 116, 1, 15603, 0x8ff4e6fd, F=0x0 -0, 117, 117, 1, 15606, 0xc8527e30, F=0x0 -0, 118, 118, 1, 15871, 0x056ddca3, F=0x0 -0, 119, 119, 1, 15725, 0xc1871caf, F=0x0 -0, 120, 120, 1, 16086, 0x063e257b, F=0x0 -0, 121, 121, 1, 16233, 0xf683823b, F=0x0 -0, 122, 122, 1, 16143, 0x576df609, F=0x0 -0, 123, 123, 1, 16669, 0x3d02346b, F=0x0 -0, 124, 124, 1, 16627, 0xe35236cc, F=0x0 -0, 125, 125, 1, 16837, 0x389c996c, F=0x0 -0, 126, 126, 1, 16952, 0xc833af9f, F=0x0 -0, 127, 127, 1, 17127, 0xbf124531, F=0x0 -0, 128, 128, 1, 17158, 0x7abbfe59, F=0x0 -0, 129, 129, 1, 17329, 0x8102cc38, F=0x0 -0, 130, 130, 1, 17403, 0xa9468cad, F=0x0 -0, 131, 131, 1, 17674, 0x46d8038c, F=0x0 -0, 132, 132, 1, 17738, 0x5ee865ce, F=0x0 -0, 133, 133, 1, 17942, 0xc2449873, F=0x0 -0, 134, 134, 1, 17952, 0x3aafedbc, F=0x0 -0, 135, 135, 1, 18246, 0xdd930054, F=0x0 -0, 136, 136, 1, 18399, 0x68a59331, F=0x0 -0, 137, 137, 1, 18551, 0x1301c157, F=0x0 -0, 138, 138, 1, 18947, 0xbed8a9b4, F=0x0 -0, 139, 139, 1, 19153, 0xe338fea2, F=0x0 -0, 140, 140, 1, 19128, 0xbf05820e, F=0x0 -0, 141, 141, 1, 19138, 0x73b5cd49, F=0x0 -0, 142, 142, 1, 19502, 0xd8d68603, F=0x0 -0, 143, 143, 1, 19542, 0x84b47563, F=0x0 -0, 144, 144, 1, 19755, 0x7194b230, F=0x0 -0, 145, 145, 1, 20122, 0x83633f5e, F=0x0 -0, 146, 146, 1, 20265, 0x7365b06b, F=0x0 -0, 147, 147, 1, 20378, 0x1aaf1a98, F=0x0 -0, 148, 148, 1, 20300, 0x1da6d336, F=0x0 -0, 149, 149, 1, 20499, 0x72d54d30, F=0x0 -0, 150, 150, 1, 20655, 0x6996b124, F=0x0 -0, 151, 151, 1, 20674, 0xa883abd2, F=0x0 -0, 152, 152, 1, 21015, 0x96cf4018, F=0x0 -0, 153, 153, 1, 21066, 0x307e4479, F=0x0 -0, 154, 154, 1, 21161, 0xd45a2c38, F=0x0 -0, 155, 155, 1, 21086, 0xcf0e597d, F=0x0 -0, 156, 156, 1, 21466, 0xcc4032fe, F=0x0 -0, 157, 157, 1, 21677, 0x755ccb7b, F=0x0 -0, 158, 158, 1, 21589, 0x5d74fb47, F=0x0 -0, 159, 159, 1, 21662, 0x0c459189, F=0x0 -0, 160, 160, 1, 21995, 0x43d46eb3, F=0x0 -0, 161, 161, 1, 22213, 0x68455c92, F=0x0 -0, 162, 162, 1, 22483, 0xdc83c15a, F=0x0 -0, 163, 163, 1, 22498, 0xfae1251e, F=0x0 -0, 164, 164, 1, 22468, 0x7944b1d4, F=0x0 -0, 165, 165, 1, 22869, 0xff8c10ac, F=0x0 -0, 166, 166, 1, 22754, 0xd8183b84, F=0x0 -0, 167, 167, 1, 23173, 0x6c3c48d5, F=0x0 -0, 168, 168, 1, 23281, 0xc32ca477, F=0x0 -0, 169, 169, 1, 23219, 0x4dc26193, F=0x0 -0, 170, 170, 1, 23656, 0xb85ee15f, F=0x0 -0, 171, 171, 1, 23683, 0x26ba4915, F=0x0 -0, 172, 172, 1, 23882, 0xf57285de, F=0x0 +0, 1, 1, 1, 236, 0x332769fd, F=0x0 +0, 2, 2, 1, 186, 0x770d5061, F=0x0 +0, 3, 3, 1, 208, 0x55784c8f, F=0x0 +0, 4, 4, 1, 282, 0x98e8825d, F=0x0 +0, 5, 5, 1, 209, 0x4cc15280, F=0x0 +0, 6, 6, 1, 225, 0xf8785d6c, F=0x0 +0, 7, 7, 1, 204, 0x322754b4, F=0x0 +0, 8, 8, 1, 181, 0x9f4f4d10, F=0x0 +0, 9, 9, 1, 200, 0x64a453a1, F=0x0 +0, 10, 10, 1, 184, 0x79c344d3, F=0x0 +0, 11, 11, 1, 191, 0x7097487b, F=0x0 +0, 12, 12, 1, 290, 0x1f998186, F=0x0 +0, 13, 13, 1, 153, 0xfe4c3a7c, F=0x0 +0, 14, 14, 1, 175, 0xfdf442e0, F=0x0 +0, 15, 15, 1, 187, 0x393845f2, F=0x0 +0, 16, 16, 1, 418, 0xe94bc757, F=0x0 +0, 17, 17, 1, 200, 0x8dab52be, F=0x0 +0, 18, 18, 1, 347, 0xae379838, F=0x0 +0, 19, 19, 1, 176, 0x868742d2, F=0x0 +0, 20, 20, 1, 294, 0xb1fb8365, F=0x0 +0, 21, 21, 1, 166, 0x06e44260, F=0x0 +0, 22, 22, 1, 306, 0x29e983b7, F=0x0 +0, 23, 23, 1, 180, 0xfa4a44eb, F=0x0 +0, 24, 24, 1, 207, 0x99de52c8, F=0x0 +0, 25, 25, 1, 204, 0x73944c35, F=0x0 +0, 26, 26, 1, 259, 0xa0637375, F=0x0 +0, 27, 27, 1, 181, 0x130f4b9a, F=0x0 +0, 28, 28, 1, 152, 0x4be93cae, F=0x0 +0, 29, 29, 1, 194, 0x81e34e1d, F=0x0 +0, 30, 30, 1, 159, 0x5913380b, F=0x0 +0, 31, 31, 1, 162, 0xf0683bb1, F=0x0 +0, 32, 32, 1, 178, 0xce32498c, F=0x0 +0, 33, 33, 1, 187, 0x5d61509f, F=0x0 +0, 34, 34, 1, 336, 0xe5569440, F=0x0 +0, 35, 35, 1, 184, 0x3fa349ea, F=0x0 +0, 36, 36, 1, 227, 0x7cad5f66, F=0x0 +0, 37, 37, 1, 182, 0xf23a4522, F=0x0 +0, 38, 38, 1, 162, 0x2a053dcc, F=0x0 +0, 39, 39, 1, 187, 0xc18a4686, F=0x0 +0, 40, 40, 1, 503, 0xa5a7e669, F=0x0 +0, 41, 41, 1, 167, 0xa28a43e8, F=0x0 +0, 42, 42, 1, 289, 0xf1968090, F=0x0 +0, 43, 43, 1, 194, 0xedbb4eb7, F=0x0 +0, 44, 44, 1, 285, 0x82e7818b, F=0x0 +0, 45, 45, 1, 199, 0x5e725190, F=0x0 +0, 46, 46, 1, 197, 0x0c6a4fb9, F=0x0 +0, 47, 47, 1, 203, 0x05684b96, F=0x0 +0, 48, 48, 1, 208, 0xd33457ad, F=0x0 +0, 49, 49, 1, 1198, 0x029f5f1b, F=0x0 +0, 50, 50, 1, 175, 0xf4e94c40, F=0x0 +0, 51, 51, 1, 740, 0x6e096787, F=0x0 +0, 52, 52, 1, 180, 0xf34f45be, F=0x0 +0, 53, 53, 1, 238, 0xfbed6adb, F=0x0 +0, 54, 54, 1, 198, 0x6f3a5344, F=0x0 +0, 55, 55, 1, 196, 0x8bbb4b02, F=0x0 +0, 56, 56, 1, 224, 0x92c55d92, F=0x0 +0, 57, 57, 1, 765, 0xd16e6d65, F=0x0 +0, 58, 58, 1, 149, 0x97aa38d2, F=0x0 +0, 59, 59, 1, 479, 0x1030d73b, F=0x0 +0, 60, 60, 1, 179, 0x441e493a, F=0x0 +0, 61, 61, 1, 217, 0x16c259b7, F=0x0 +0, 62, 62, 1, 190, 0x5b2349ca, F=0x0 +0, 63, 63, 1, 155, 0x422f39ff, F=0x0 +0, 64, 64, 1, 167, 0x28444898, F=0x0 +0, 65, 65, 1, 649, 0x57b331e2, F=0x0 +0, 66, 66, 1, 196, 0x99a1574f, F=0x0 +0, 67, 67, 1, 427, 0xfd45d548, F=0x0 +0, 68, 68, 1, 175, 0x90cc42ce, F=0x0 +0, 69, 69, 1, 284, 0x49398208, F=0x0 +0, 70, 70, 1, 131, 0x18e42fc2, F=0x0 +0, 71, 71, 1, 256, 0xac896bbe, F=0x0 +0, 72, 72, 1, 186, 0x522d4974, F=0x0 +0, 73, 73, 1, 190, 0x5e064e04, F=0x0 +0, 74, 74, 1, 216, 0x863f53fa, F=0x0 +0, 75, 75, 1, 154, 0x17f1383f, F=0x0 +0, 76, 76, 1, 113, 0x20f827ee, F=0x0 +0, 77, 77, 1, 402, 0xce2caf45, F=0x0 +0, 78, 78, 1, 198, 0x0bc851ae, F=0x0 +0, 79, 79, 1, 466, 0xb31ad387, F=0x0 +0, 80, 80, 1, 322, 0x20018e02, F=0x0 +0, 81, 81, 1, 387, 0x5038b1b8, F=0x0 +0, 82, 82, 1, 158, 0xc6ac3feb, F=0x0 +0, 83, 83, 1, 278, 0x59f17c03, F=0x0 +0, 84, 84, 1, 190, 0xd7665022, F=0x0 +0, 85, 85, 1, 175, 0x1a6e4225, F=0x0 +0, 86, 86, 1, 206, 0xc3f44e3a, F=0x0 +0, 87, 87, 1, 379, 0xb1e6b77e, F=0x0 +0, 88, 88, 1, 202, 0x17975145, F=0x0 +0, 89, 89, 1, 225, 0x96985fd2, F=0x0 +0, 90, 90, 1, 175, 0x71b1497a, F=0x0 +0, 91, 91, 1, 235, 0x2bdc5faa, F=0x0 +0, 92, 92, 1, 185, 0x68124958, F=0x0 +0, 93, 93, 1, 182, 0x120c4c63, F=0x0 +0, 94, 94, 1, 114, 0xdd9b2b02, F=0x0 +0, 95, 95, 1, 176, 0x0d5b4b46, F=0x0 +0, 96, 96, 1, 214, 0xfb5e5b47, F=0x0 +0, 97, 97, 1, 182, 0xf4c54860, F=0x0 +0, 98, 98, 1, 195, 0x6e075188, F=0x0 +0, 99, 99, 1, 303, 0x4c158465, F=0x0 +0, 100, 100, 1, 191, 0x12005055, F=0x0 +0, 101, 101, 1, 177, 0x01ed4929, F=0x0 +0, 102, 102, 1, 172, 0x86984280, F=0x0 +0, 103, 103, 1, 179, 0xb854481c, F=0x0 +0, 104, 104, 1, 188, 0xeacd47ed, F=0x0 +0, 105, 105, 1, 177, 0x36be4889, F=0x0 +0, 106, 106, 1, 215, 0x6aa65c99, F=0x0 +0, 107, 107, 1, 339, 0x1af496b2, F=0x0 +0, 108, 108, 1, 189, 0x941045fa, F=0x0 +0, 109, 109, 1, 209, 0x37445651, F=0x0 +0, 110, 110, 1, 205, 0x9cf85222, F=0x0 +0, 111, 111, 1, 185, 0x8b964cb5, F=0x0 +0, 112, 112, 1, 211, 0xd03d59ce, F=0x0 +0, 113, 113, 1, 178, 0xe40e4c08, F=0x0 +0, 114, 114, 1, 195, 0x971d4d92, F=0x0 +0, 115, 115, 1, 116, 0x5f9a2d3f, F=0x0 +0, 116, 116, 1, 116, 0x5c4e2d06, F=0x0 +0, 117, 117, 1, 427, 0x6128c7da, F=0x0 +0, 118, 118, 1, 182, 0x8a9a4a85, F=0x0 +0, 119, 119, 1, 267, 0x94e16d98, F=0x0 +0, 120, 120, 1, 191, 0x8cd6499b, F=0x0 +0, 121, 121, 1, 195, 0x2955524a, F=0x0 +0, 122, 122, 1, 755, 0x21115eef, F=0x0 +0, 123, 123, 1, 179, 0x89ff45fd, F=0x0 +0, 124, 124, 1, 522, 0x1b1cf19d, F=0x0 +0, 125, 125, 1, 171, 0x48034194, F=0x0 +0, 126, 126, 1, 379, 0x3914a793, F=0x0 +0, 127, 127, 1, 539, 0x7155fc34, F=0x0 +0, 128, 128, 1, 199, 0xb8674f8a, F=0x0 +0, 129, 129, 1, 458, 0x0a87ce97, F=0x0 +0, 130, 130, 1, 177, 0xac704b44, F=0x0 +0, 131, 131, 1, 299, 0x49318aa9, F=0x0 +0, 132, 132, 1, 333, 0xa188949d, F=0x0 +0, 133, 133, 1, 179, 0x2474436d, F=0x0 +0, 134, 134, 1, 263, 0x84e871f8, F=0x0 +0, 135, 135, 1, 177, 0xf7904597, F=0x0 +0, 136, 136, 1, 184, 0xb053486d, F=0x0 +0, 137, 137, 1, 433, 0xd3c0c5a1, F=0x0 +0, 138, 138, 1, 1138, 0xd5af3462, F=0x0 +0, 139, 139, 1, 863, 0xdce99f4f, F=0x0 +0, 140, 140, 1, 328, 0x608a949d, F=0x0 +0, 141, 141, 1, 222, 0xecb75a19, F=0x0 +0, 142, 142, 1, 171, 0x6cf94548, F=0x0 +0, 143, 143, 1, 222, 0xcf8d5778, F=0x0 +0, 144, 144, 1, 738, 0x9cf358a2, F=0x0 +0, 145, 145, 1, 444, 0x3798cdf6, F=0x0 +0, 146, 146, 1, 267, 0x8ca87717, F=0x0 +0, 147, 147, 1, 187, 0x4d734c80, F=0x0 +0, 148, 148, 1, 186, 0x9def4fb6, F=0x0 +0, 149, 149, 1, 196, 0x49214f94, F=0x0 +0, 150, 150, 1, 589, 0x02e2142f, F=0x0 +0, 151, 151, 1, 188, 0x285c4dad, F=0x0 +0, 152, 152, 1, 339, 0x8a0fa092, F=0x0 +0, 153, 153, 1, 179, 0x775543d4, F=0x0 +0, 154, 154, 1, 294, 0x0c8885eb, F=0x0 +0, 155, 155, 1, 291, 0xd78084b1, F=0x0 +0, 156, 156, 1, 144, 0xd7323963, F=0x0 +0, 157, 157, 1, 182, 0x97194ede, F=0x0 +0, 158, 158, 1, 195, 0x410f50a6, F=0x0 +0, 159, 159, 1, 268, 0xb878789a, F=0x0 +0, 160, 160, 1, 526, 0x6e13fb3e, F=0x0 +0, 161, 161, 1, 372, 0xf1fca999, F=0x0 +0, 162, 162, 1, 171, 0x86033fb7, F=0x0 +0, 163, 163, 1, 344, 0x8db8a374, F=0x0 +0, 164, 164, 1, 159, 0xa3463fb6, F=0x0 +0, 165, 165, 1, 391, 0x6ab1aa7d, F=0x0 +0, 166, 166, 1, 180, 0x55d04d01, F=0x0 +0, 167, 167, 1, 303, 0xac779365, F=0x0 +0, 168, 168, 1, 180, 0x54e94840, F=0x0 +0, 169, 169, 1, 269, 0x56e57720, F=0x0 +0, 170, 170, 1, 199, 0x510b5589, F=0x0 +0, 171, 171, 1, 287, 0xd70d8529, F=0x0 +0, 172, 172, 1, 217, 0x04a0649e, F=0x0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/gifenc-pal8 ffmpeg-4.4/tests/ref/fate/gifenc-pal8 --- ffmpeg-4.2.2/tests/ref/fate/gifenc-pal8 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/gifenc-pal8 2020-07-11 10:39:30.000000000 +0000 @@ -4,175 +4,175 @@ #dimensions 0: 217x217 #sar 0: 0/1 0, 0, 0, 1, 2109, 0x39642b3d -0, 1, 1, 1, 305, 0xefa98bbd, F=0x0 -0, 2, 2, 1, 446, 0x9499cf43, F=0x0 -0, 3, 3, 1, 458, 0x8cb7d0d5, F=0x0 -0, 4, 4, 1, 555, 0x41f2fe63, F=0x0 -0, 5, 5, 1, 622, 0x3651212e, F=0x0 -0, 6, 6, 1, 650, 0x67542087, F=0x0 -0, 7, 7, 1, 668, 0x392934ca, F=0x0 -0, 8, 8, 1, 829, 0x6cd07a33, F=0x0 -0, 9, 9, 1, 1165, 0xb64b2ec9, F=0x0 -0, 10, 10, 1, 187, 0x114a52a4, F=0x0 -0, 11, 11, 1, 1341, 0x6ca57064, F=0x0 -0, 12, 12, 1, 1646, 0xcdd90fae, F=0x0 -0, 13, 13, 1, 1539, 0xbf75e55f, F=0x0 -0, 14, 14, 1, 1728, 0x96b14714, F=0x0 -0, 15, 15, 1, 1918, 0xffd08446, F=0x0 -0, 16, 16, 1, 2132, 0x3d5ae258, F=0x0 -0, 17, 17, 1, 2256, 0x359526d9, F=0x0 -0, 18, 18, 1, 2319, 0x553c382b, F=0x0 -0, 19, 19, 1, 2416, 0x7ac37066, F=0x0 -0, 20, 20, 1, 2609, 0x552bc27f, F=0x0 -0, 21, 21, 1, 2695, 0xbb0c020e, F=0x0 -0, 22, 22, 1, 2792, 0x46670f7d, F=0x0 -0, 23, 23, 1, 2892, 0x5674481e, F=0x0 -0, 24, 24, 1, 2990, 0x015a7bfd, F=0x0 -0, 25, 25, 1, 3109, 0xc73e9d14, F=0x0 -0, 26, 26, 1, 3261, 0x8a77f522, F=0x0 -0, 27, 27, 1, 3337, 0xf6f92558, F=0x0 -0, 28, 28, 1, 3580, 0x23408bc8, F=0x0 -0, 29, 29, 1, 3815, 0x781dfb1b, F=0x0 -0, 30, 30, 1, 2758, 0xf5cd1d5b, F=0x0 -0, 31, 31, 1, 4039, 0x7909712e, F=0x0 -0, 32, 32, 1, 3033, 0x39089d44, F=0x0 -0, 33, 33, 1, 4303, 0x667b0c60, F=0x0 -0, 34, 34, 1, 2052, 0x9edfba63, F=0x0 -0, 35, 35, 1, 3220, 0x5a56f015, F=0x0 -0, 36, 36, 1, 2300, 0x1719645c, F=0x0 -0, 37, 37, 1, 3641, 0x71c49a57, F=0x0 -0, 38, 38, 1, 3560, 0x377575b8, F=0x0 -0, 39, 39, 1, 3698, 0x165adce0, F=0x0 -0, 40, 40, 1, 1567, 0x6ecbf672, F=0x0 -0, 41, 41, 1, 962, 0x21eccba1, F=0x0 -0, 42, 42, 1, 281, 0x7a5a7ac3, F=0x0 -0, 43, 43, 1, 938, 0x659bb1ec, F=0x0 -0, 44, 44, 1, 279, 0x71e181bc, F=0x0 -0, 45, 45, 1, 204, 0xe0765316, F=0x0 -0, 46, 46, 1, 4307, 0xdbdd0e7d, F=0x0 -0, 47, 47, 1, 4903, 0xd8d24194, F=0x0 -0, 48, 48, 1, 4936, 0x6e9f1aff, F=0x0 -0, 49, 49, 1, 4949, 0xb3115902, F=0x0 -0, 50, 50, 1, 4162, 0xee2cad5b, F=0x0 -0, 51, 51, 1, 4686, 0xd583c178, F=0x0 -0, 52, 52, 1, 4749, 0x8c93b6a9, F=0x0 -0, 53, 53, 1, 4990, 0x12f957fd, F=0x0 -0, 54, 54, 1, 5187, 0xf3bcc7c9, F=0x0 -0, 55, 55, 1, 5054, 0xa27684fb, F=0x0 -0, 56, 56, 1, 5148, 0xe76cbad7, F=0x0 -0, 57, 57, 1, 4309, 0x79f7f067, F=0x0 -0, 58, 58, 1, 5087, 0xa2e29f29, F=0x0 -0, 59, 59, 1, 5292, 0xd158e4db, F=0x0 -0, 60, 60, 1, 5434, 0xe0be16f5, F=0x0 -0, 61, 61, 1, 4653, 0x0a3d8a5e, F=0x0 -0, 62, 62, 1, 5271, 0x4412d0a5, F=0x0 -0, 63, 63, 1, 5229, 0x3e06c4f2, F=0x0 -0, 64, 64, 1, 5225, 0x9bc39cfa, F=0x0 -0, 65, 65, 1, 5403, 0x798b009d, F=0x0 -0, 66, 66, 1, 5228, 0x14f2dded, F=0x0 -0, 67, 67, 1, 5712, 0x8724debe, F=0x0 -0, 68, 68, 1, 5644, 0x49d3a383, F=0x0 -0, 69, 69, 1, 5826, 0xde72e0ba, F=0x0 -0, 70, 70, 1, 5771, 0x62efd718, F=0x0 -0, 71, 71, 1, 6124, 0xb2a68c70, F=0x0 -0, 72, 72, 1, 6077, 0xb48b693f, F=0x0 -0, 73, 73, 1, 5804, 0xb700db6c, F=0x0 -0, 74, 74, 1, 6007, 0x02953898, F=0x0 -0, 75, 75, 1, 6228, 0x87a7b197, F=0x0 -0, 76, 76, 1, 6382, 0x49e7e65b, F=0x0 -0, 77, 77, 1, 6473, 0x3b9b6c3d, F=0x0 -0, 78, 78, 1, 7027, 0x2a4e1c17, F=0x0 -0, 79, 79, 1, 7263, 0x2e48c2e7, F=0x0 -0, 80, 80, 1, 8205, 0x013b701a, F=0x0 -0, 81, 81, 1, 8366, 0xcca97b10, F=0x0 -0, 82, 82, 1, 7716, 0x3b088fb3, F=0x0 -0, 83, 83, 1, 7420, 0xefdd1187, F=0x0 -0, 84, 84, 1, 7549, 0x1731227c, F=0x0 -0, 85, 85, 1, 7956, 0x8186ceb3, F=0x0 -0, 86, 86, 1, 8416, 0x23add53c, F=0x0 -0, 87, 87, 1, 8064, 0x09c616c4, F=0x0 -0, 88, 88, 1, 7409, 0x9d98af03, F=0x0 -0, 89, 89, 1, 7502, 0x0b81ebf3, F=0x0 -0, 90, 90, 1, 7814, 0x2f0d75cb, F=0x0 -0, 91, 91, 1, 7776, 0x45d6800f, F=0x0 -0, 92, 92, 1, 7757, 0x777f98b6, F=0x0 -0, 93, 93, 1, 8055, 0x4eea1634, F=0x0 -0, 94, 94, 1, 7626, 0xfb3931fd, F=0x0 -0, 95, 95, 1, 7987, 0x22a1d052, F=0x0 -0, 96, 96, 1, 12070, 0x3aa2924d, F=0x0 -0, 97, 97, 1, 12325, 0xda6cd811, F=0x0 -0, 98, 98, 1, 12225, 0xd478e671, F=0x0 -0, 99, 99, 1, 11235, 0xc6c09240, F=0x0 -0, 100, 100, 1, 11116, 0x95050c25, F=0x0 -0, 101, 101, 1, 11374, 0x14a68e3d, F=0x0 -0, 102, 102, 1, 11904, 0xb14436f2, F=0x0 -0, 103, 103, 1, 11487, 0xa3358311, F=0x0 -0, 104, 104, 1, 13403, 0xccf33a00, F=0x0 -0, 105, 105, 1, 12921, 0xbf7e4759, F=0x0 -0, 106, 106, 1, 13872, 0x7dace890, F=0x0 -0, 107, 107, 1, 13559, 0xb6c868f9, F=0x0 -0, 108, 108, 1, 14049, 0xa5d569b0, F=0x0 -0, 109, 109, 1, 14152, 0x8c9c31fb, F=0x0 -0, 110, 110, 1, 14285, 0x2ffe3bc3, F=0x0 -0, 111, 111, 1, 14432, 0x27abe196, F=0x0 -0, 112, 112, 1, 14697, 0x20d1aedd, F=0x0 -0, 113, 113, 1, 14606, 0xbcbe586d, F=0x0 -0, 114, 114, 1, 15221, 0x515f8224, F=0x0 -0, 115, 115, 1, 15433, 0x68089081, F=0x0 -0, 116, 116, 1, 15603, 0x8ff4e6fd, F=0x0 -0, 117, 117, 1, 15606, 0xc8527e30, F=0x0 -0, 118, 118, 1, 15871, 0x056ddca3, F=0x0 -0, 119, 119, 1, 15725, 0xc1871caf, F=0x0 -0, 120, 120, 1, 16086, 0x063e257b, F=0x0 -0, 121, 121, 1, 16233, 0xf683823b, F=0x0 -0, 122, 122, 1, 16143, 0x576df609, F=0x0 -0, 123, 123, 1, 16669, 0x3d02346b, F=0x0 -0, 124, 124, 1, 16627, 0xe35236cc, F=0x0 -0, 125, 125, 1, 16837, 0x389c996c, F=0x0 -0, 126, 126, 1, 16952, 0xc833af9f, F=0x0 -0, 127, 127, 1, 17127, 0xbf124531, F=0x0 -0, 128, 128, 1, 17158, 0x7abbfe59, F=0x0 -0, 129, 129, 1, 17329, 0x8102cc38, F=0x0 -0, 130, 130, 1, 17403, 0xa9468cad, F=0x0 -0, 131, 131, 1, 17674, 0x46d8038c, F=0x0 -0, 132, 132, 1, 17738, 0x5ee865ce, F=0x0 -0, 133, 133, 1, 17942, 0xc2449873, F=0x0 -0, 134, 134, 1, 17952, 0x3aafedbc, F=0x0 -0, 135, 135, 1, 18246, 0xdd930054, F=0x0 -0, 136, 136, 1, 18399, 0x68a59331, F=0x0 -0, 137, 137, 1, 18551, 0x1301c157, F=0x0 -0, 138, 138, 1, 18947, 0xbed8a9b4, F=0x0 -0, 139, 139, 1, 19153, 0xe338fea2, F=0x0 -0, 140, 140, 1, 19128, 0xbf05820e, F=0x0 -0, 141, 141, 1, 19138, 0x73b5cd49, F=0x0 -0, 142, 142, 1, 19502, 0xd8d68603, F=0x0 -0, 143, 143, 1, 19542, 0x84b47563, F=0x0 -0, 144, 144, 1, 19755, 0x7194b230, F=0x0 -0, 145, 145, 1, 20122, 0x83633f5e, F=0x0 -0, 146, 146, 1, 20265, 0x7365b06b, F=0x0 -0, 147, 147, 1, 20378, 0x1aaf1a98, F=0x0 -0, 148, 148, 1, 20300, 0x1da6d336, F=0x0 -0, 149, 149, 1, 20499, 0x72d54d30, F=0x0 -0, 150, 150, 1, 20655, 0x6996b124, F=0x0 -0, 151, 151, 1, 20674, 0xa883abd2, F=0x0 -0, 152, 152, 1, 21015, 0x96cf4018, F=0x0 -0, 153, 153, 1, 21066, 0x307e4479, F=0x0 -0, 154, 154, 1, 21161, 0xd45a2c38, F=0x0 -0, 155, 155, 1, 21086, 0xcf0e597d, F=0x0 -0, 156, 156, 1, 21466, 0xcc4032fe, F=0x0 -0, 157, 157, 1, 21677, 0x755ccb7b, F=0x0 -0, 158, 158, 1, 21589, 0x5d74fb47, F=0x0 -0, 159, 159, 1, 21662, 0x0c459189, F=0x0 -0, 160, 160, 1, 21995, 0x43d46eb3, F=0x0 -0, 161, 161, 1, 22213, 0x68455c92, F=0x0 -0, 162, 162, 1, 22483, 0xdc83c15a, F=0x0 -0, 163, 163, 1, 22498, 0xfae1251e, F=0x0 -0, 164, 164, 1, 22468, 0x7944b1d4, F=0x0 -0, 165, 165, 1, 22869, 0xff8c10ac, F=0x0 -0, 166, 166, 1, 22754, 0xd8183b84, F=0x0 -0, 167, 167, 1, 23173, 0x6c3c48d5, F=0x0 -0, 168, 168, 1, 23281, 0xc32ca477, F=0x0 -0, 169, 169, 1, 23219, 0x4dc26193, F=0x0 -0, 170, 170, 1, 23656, 0xb85ee15f, F=0x0 -0, 171, 171, 1, 23683, 0x26ba4915, F=0x0 -0, 172, 172, 1, 23882, 0xf57285de, F=0x0 +0, 1, 1, 1, 236, 0x332769fd, F=0x0 +0, 2, 2, 1, 186, 0x770d5061, F=0x0 +0, 3, 3, 1, 208, 0x55784c8f, F=0x0 +0, 4, 4, 1, 282, 0x98e8825d, F=0x0 +0, 5, 5, 1, 209, 0x4cc15280, F=0x0 +0, 6, 6, 1, 225, 0xf8785d6c, F=0x0 +0, 7, 7, 1, 204, 0x322754b4, F=0x0 +0, 8, 8, 1, 181, 0x9f4f4d10, F=0x0 +0, 9, 9, 1, 200, 0x64a453a1, F=0x0 +0, 10, 10, 1, 184, 0x79c344d3, F=0x0 +0, 11, 11, 1, 191, 0x7097487b, F=0x0 +0, 12, 12, 1, 290, 0x1f998186, F=0x0 +0, 13, 13, 1, 153, 0xfe4c3a7c, F=0x0 +0, 14, 14, 1, 175, 0xfdf442e0, F=0x0 +0, 15, 15, 1, 187, 0x393845f2, F=0x0 +0, 16, 16, 1, 418, 0xe94bc757, F=0x0 +0, 17, 17, 1, 200, 0x8dab52be, F=0x0 +0, 18, 18, 1, 347, 0xae379838, F=0x0 +0, 19, 19, 1, 176, 0x868742d2, F=0x0 +0, 20, 20, 1, 294, 0xb1fb8365, F=0x0 +0, 21, 21, 1, 166, 0x06e44260, F=0x0 +0, 22, 22, 1, 306, 0x29e983b7, F=0x0 +0, 23, 23, 1, 180, 0xfa4a44eb, F=0x0 +0, 24, 24, 1, 207, 0x99de52c8, F=0x0 +0, 25, 25, 1, 204, 0x73944c35, F=0x0 +0, 26, 26, 1, 259, 0xa0637375, F=0x0 +0, 27, 27, 1, 181, 0x130f4b9a, F=0x0 +0, 28, 28, 1, 152, 0x4be93cae, F=0x0 +0, 29, 29, 1, 194, 0x81e34e1d, F=0x0 +0, 30, 30, 1, 159, 0x5913380b, F=0x0 +0, 31, 31, 1, 162, 0xf0683bb1, F=0x0 +0, 32, 32, 1, 178, 0xce32498c, F=0x0 +0, 33, 33, 1, 187, 0x5d61509f, F=0x0 +0, 34, 34, 1, 336, 0xe5569440, F=0x0 +0, 35, 35, 1, 184, 0x3fa349ea, F=0x0 +0, 36, 36, 1, 227, 0x7cad5f66, F=0x0 +0, 37, 37, 1, 182, 0xf23a4522, F=0x0 +0, 38, 38, 1, 162, 0x2a053dcc, F=0x0 +0, 39, 39, 1, 187, 0xc18a4686, F=0x0 +0, 40, 40, 1, 503, 0xa5a7e669, F=0x0 +0, 41, 41, 1, 167, 0xa28a43e8, F=0x0 +0, 42, 42, 1, 289, 0xf1968090, F=0x0 +0, 43, 43, 1, 194, 0xedbb4eb7, F=0x0 +0, 44, 44, 1, 285, 0x82e7818b, F=0x0 +0, 45, 45, 1, 199, 0x5e725190, F=0x0 +0, 46, 46, 1, 197, 0x0c6a4fb9, F=0x0 +0, 47, 47, 1, 203, 0x05684b96, F=0x0 +0, 48, 48, 1, 208, 0xd33457ad, F=0x0 +0, 49, 49, 1, 1198, 0x029f5f1b, F=0x0 +0, 50, 50, 1, 175, 0xf4e94c40, F=0x0 +0, 51, 51, 1, 740, 0x6e096787, F=0x0 +0, 52, 52, 1, 180, 0xf34f45be, F=0x0 +0, 53, 53, 1, 238, 0xfbed6adb, F=0x0 +0, 54, 54, 1, 198, 0x6f3a5344, F=0x0 +0, 55, 55, 1, 196, 0x8bbb4b02, F=0x0 +0, 56, 56, 1, 224, 0x92c55d92, F=0x0 +0, 57, 57, 1, 765, 0xd16e6d65, F=0x0 +0, 58, 58, 1, 149, 0x97aa38d2, F=0x0 +0, 59, 59, 1, 479, 0x1030d73b, F=0x0 +0, 60, 60, 1, 179, 0x441e493a, F=0x0 +0, 61, 61, 1, 217, 0x16c259b7, F=0x0 +0, 62, 62, 1, 190, 0x5b2349ca, F=0x0 +0, 63, 63, 1, 155, 0x422f39ff, F=0x0 +0, 64, 64, 1, 167, 0x28444898, F=0x0 +0, 65, 65, 1, 649, 0x57b331e2, F=0x0 +0, 66, 66, 1, 196, 0x99a1574f, F=0x0 +0, 67, 67, 1, 427, 0xfd45d548, F=0x0 +0, 68, 68, 1, 175, 0x90cc42ce, F=0x0 +0, 69, 69, 1, 284, 0x49398208, F=0x0 +0, 70, 70, 1, 131, 0x18e42fc2, F=0x0 +0, 71, 71, 1, 256, 0xac896bbe, F=0x0 +0, 72, 72, 1, 186, 0x522d4974, F=0x0 +0, 73, 73, 1, 190, 0x5e064e04, F=0x0 +0, 74, 74, 1, 216, 0x863f53fa, F=0x0 +0, 75, 75, 1, 154, 0x17f1383f, F=0x0 +0, 76, 76, 1, 113, 0x20f827ee, F=0x0 +0, 77, 77, 1, 402, 0xce2caf45, F=0x0 +0, 78, 78, 1, 198, 0x0bc851ae, F=0x0 +0, 79, 79, 1, 466, 0xb31ad387, F=0x0 +0, 80, 80, 1, 322, 0x20018e02, F=0x0 +0, 81, 81, 1, 387, 0x5038b1b8, F=0x0 +0, 82, 82, 1, 158, 0xc6ac3feb, F=0x0 +0, 83, 83, 1, 278, 0x59f17c03, F=0x0 +0, 84, 84, 1, 190, 0xd7665022, F=0x0 +0, 85, 85, 1, 175, 0x1a6e4225, F=0x0 +0, 86, 86, 1, 206, 0xc3f44e3a, F=0x0 +0, 87, 87, 1, 379, 0xb1e6b77e, F=0x0 +0, 88, 88, 1, 202, 0x17975145, F=0x0 +0, 89, 89, 1, 225, 0x96985fd2, F=0x0 +0, 90, 90, 1, 175, 0x71b1497a, F=0x0 +0, 91, 91, 1, 235, 0x2bdc5faa, F=0x0 +0, 92, 92, 1, 185, 0x68124958, F=0x0 +0, 93, 93, 1, 182, 0x120c4c63, F=0x0 +0, 94, 94, 1, 114, 0xdd9b2b02, F=0x0 +0, 95, 95, 1, 176, 0x0d5b4b46, F=0x0 +0, 96, 96, 1, 214, 0xfb5e5b47, F=0x0 +0, 97, 97, 1, 182, 0xf4c54860, F=0x0 +0, 98, 98, 1, 195, 0x6e075188, F=0x0 +0, 99, 99, 1, 303, 0x4c158465, F=0x0 +0, 100, 100, 1, 191, 0x12005055, F=0x0 +0, 101, 101, 1, 177, 0x01ed4929, F=0x0 +0, 102, 102, 1, 172, 0x86984280, F=0x0 +0, 103, 103, 1, 179, 0xb854481c, F=0x0 +0, 104, 104, 1, 188, 0xeacd47ed, F=0x0 +0, 105, 105, 1, 177, 0x36be4889, F=0x0 +0, 106, 106, 1, 215, 0x6aa65c99, F=0x0 +0, 107, 107, 1, 339, 0x1af496b2, F=0x0 +0, 108, 108, 1, 189, 0x941045fa, F=0x0 +0, 109, 109, 1, 209, 0x37445651, F=0x0 +0, 110, 110, 1, 205, 0x9cf85222, F=0x0 +0, 111, 111, 1, 185, 0x8b964cb5, F=0x0 +0, 112, 112, 1, 211, 0xd03d59ce, F=0x0 +0, 113, 113, 1, 178, 0xe40e4c08, F=0x0 +0, 114, 114, 1, 195, 0x971d4d92, F=0x0 +0, 115, 115, 1, 116, 0x5f9a2d3f, F=0x0 +0, 116, 116, 1, 116, 0x5c4e2d06, F=0x0 +0, 117, 117, 1, 427, 0x6128c7da, F=0x0 +0, 118, 118, 1, 182, 0x8a9a4a85, F=0x0 +0, 119, 119, 1, 267, 0x94e16d98, F=0x0 +0, 120, 120, 1, 191, 0x8cd6499b, F=0x0 +0, 121, 121, 1, 195, 0x2955524a, F=0x0 +0, 122, 122, 1, 755, 0x21115eef, F=0x0 +0, 123, 123, 1, 179, 0x89ff45fd, F=0x0 +0, 124, 124, 1, 522, 0x1b1cf19d, F=0x0 +0, 125, 125, 1, 171, 0x48034194, F=0x0 +0, 126, 126, 1, 379, 0x3914a793, F=0x0 +0, 127, 127, 1, 539, 0x7155fc34, F=0x0 +0, 128, 128, 1, 199, 0xb8674f8a, F=0x0 +0, 129, 129, 1, 458, 0x0a87ce97, F=0x0 +0, 130, 130, 1, 177, 0xac704b44, F=0x0 +0, 131, 131, 1, 299, 0x49318aa9, F=0x0 +0, 132, 132, 1, 333, 0xa188949d, F=0x0 +0, 133, 133, 1, 179, 0x2474436d, F=0x0 +0, 134, 134, 1, 263, 0x84e871f8, F=0x0 +0, 135, 135, 1, 177, 0xf7904597, F=0x0 +0, 136, 136, 1, 184, 0xb053486d, F=0x0 +0, 137, 137, 1, 433, 0xd3c0c5a1, F=0x0 +0, 138, 138, 1, 1138, 0xd5af3462, F=0x0 +0, 139, 139, 1, 863, 0xdce99f4f, F=0x0 +0, 140, 140, 1, 328, 0x608a949d, F=0x0 +0, 141, 141, 1, 222, 0xecb75a19, F=0x0 +0, 142, 142, 1, 171, 0x6cf94548, F=0x0 +0, 143, 143, 1, 222, 0xcf8d5778, F=0x0 +0, 144, 144, 1, 738, 0x9cf358a2, F=0x0 +0, 145, 145, 1, 444, 0x3798cdf6, F=0x0 +0, 146, 146, 1, 267, 0x8ca87717, F=0x0 +0, 147, 147, 1, 187, 0x4d734c80, F=0x0 +0, 148, 148, 1, 186, 0x9def4fb6, F=0x0 +0, 149, 149, 1, 196, 0x49214f94, F=0x0 +0, 150, 150, 1, 589, 0x02e2142f, F=0x0 +0, 151, 151, 1, 188, 0x285c4dad, F=0x0 +0, 152, 152, 1, 339, 0x8a0fa092, F=0x0 +0, 153, 153, 1, 179, 0x775543d4, F=0x0 +0, 154, 154, 1, 294, 0x0c8885eb, F=0x0 +0, 155, 155, 1, 291, 0xd78084b1, F=0x0 +0, 156, 156, 1, 144, 0xd7323963, F=0x0 +0, 157, 157, 1, 182, 0x97194ede, F=0x0 +0, 158, 158, 1, 195, 0x410f50a6, F=0x0 +0, 159, 159, 1, 268, 0xb878789a, F=0x0 +0, 160, 160, 1, 526, 0x6e13fb3e, F=0x0 +0, 161, 161, 1, 372, 0xf1fca999, F=0x0 +0, 162, 162, 1, 171, 0x86033fb7, F=0x0 +0, 163, 163, 1, 344, 0x8db8a374, F=0x0 +0, 164, 164, 1, 159, 0xa3463fb6, F=0x0 +0, 165, 165, 1, 391, 0x6ab1aa7d, F=0x0 +0, 166, 166, 1, 180, 0x55d04d01, F=0x0 +0, 167, 167, 1, 303, 0xac779365, F=0x0 +0, 168, 168, 1, 180, 0x54e94840, F=0x0 +0, 169, 169, 1, 269, 0x56e57720, F=0x0 +0, 170, 170, 1, 199, 0x510b5589, F=0x0 +0, 171, 171, 1, 287, 0xd70d8529, F=0x0 +0, 172, 172, 1, 217, 0x04a0649e, F=0x0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/gifenc-rgb4_byte ffmpeg-4.4/tests/ref/fate/gifenc-rgb4_byte --- ffmpeg-4.2.2/tests/ref/fate/gifenc-rgb4_byte 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/gifenc-rgb4_byte 2020-07-11 10:39:30.000000000 +0000 @@ -4,175 +4,175 @@ #dimensions 0: 217x217 #sar 0: 0/1 0, 0, 0, 1, 1297, 0x5618fe71 -0, 1, 1, 1, 221, 0x230c4e66, F=0x0 -0, 2, 2, 1, 139, 0xf87a2b65, F=0x0 -0, 3, 3, 1, 392, 0x7794a5e6, F=0x0 -0, 4, 4, 1, 389, 0xf856a3f1, F=0x0 -0, 5, 5, 1, 438, 0x0f95b4fb, F=0x0 -0, 6, 6, 1, 526, 0x7885d860, F=0x0 -0, 7, 7, 1, 543, 0x859fe7df, F=0x0 -0, 8, 8, 1, 446, 0xb34dba74, F=0x0 -0, 9, 9, 1, 931, 0x1c2fa48d, F=0x0 -0, 10, 10, 1, 702, 0x1ce74b4d, F=0x0 -0, 11, 11, 1, 1202, 0x2f232db8, F=0x0 -0, 12, 12, 1, 1299, 0x904e56af, F=0x0 -0, 13, 13, 1, 1253, 0x20803653, F=0x0 -0, 14, 14, 1, 1338, 0x24e052f6, F=0x0 -0, 15, 15, 1, 1284, 0x590a3a42, F=0x0 -0, 16, 16, 1, 1483, 0x93e09883, F=0x0 -0, 17, 17, 1, 1792, 0x70984bdf, F=0x0 -0, 18, 18, 1, 1683, 0x23b9fc30, F=0x0 -0, 19, 19, 1, 1517, 0x0fc1acf6, F=0x0 -0, 20, 20, 1, 1713, 0x6b4c1861, F=0x0 -0, 21, 21, 1, 1753, 0x896b20c1, F=0x0 -0, 22, 22, 1, 1650, 0x2f26027f, F=0x0 -0, 23, 23, 1, 1726, 0x9f731df0, F=0x0 -0, 24, 24, 1, 1908, 0xebd67b41, F=0x0 -0, 25, 25, 1, 1815, 0xf2685278, F=0x0 -0, 26, 26, 1, 1923, 0xbe18821e, F=0x0 -0, 27, 27, 1, 2108, 0x1318d306, F=0x0 -0, 28, 28, 1, 2708, 0x5e28f23c, F=0x0 -0, 29, 29, 1, 2681, 0xb96da855, F=0x0 -0, 30, 30, 1, 2903, 0x61cf4983, F=0x0 -0, 31, 31, 1, 3265, 0x95a1d25d, F=0x0 -0, 32, 32, 1, 3187, 0x6a67c299, F=0x0 -0, 33, 33, 1, 3304, 0x1c5ce63e, F=0x0 -0, 34, 34, 1, 3608, 0x2ed2770f, F=0x0 -0, 35, 35, 1, 3707, 0xa075a17b, F=0x0 -0, 36, 36, 1, 3822, 0xc842d6b6, F=0x0 -0, 37, 37, 1, 3635, 0x814680c7, F=0x0 -0, 38, 38, 1, 2958, 0x64de62cf, F=0x0 -0, 39, 39, 1, 3094, 0x2c338e84, F=0x0 -0, 40, 40, 1, 3102, 0xec5e8757, F=0x0 -0, 41, 41, 1, 3464, 0xea4f2bce, F=0x0 -0, 42, 42, 1, 4116, 0xded05ff3, F=0x0 -0, 43, 43, 1, 4225, 0x21825a2c, F=0x0 -0, 44, 44, 1, 3621, 0xa3125130, F=0x0 -0, 45, 45, 1, 3918, 0x35e0e876, F=0x0 -0, 46, 46, 1, 4469, 0xa408e1f7, F=0x0 -0, 47, 47, 1, 4601, 0x6f7d3081, F=0x0 -0, 48, 48, 1, 4830, 0x023e9cab, F=0x0 -0, 49, 49, 1, 5406, 0xf67ac12c, F=0x0 -0, 50, 50, 1, 5274, 0xf14e9768, F=0x0 -0, 51, 51, 1, 5424, 0x2af8e2a7, F=0x0 -0, 52, 52, 1, 5527, 0x80f70710, F=0x0 -0, 53, 53, 1, 5709, 0x89975c2f, F=0x0 -0, 54, 54, 1, 6168, 0xf5a542af, F=0x0 -0, 55, 55, 1, 6241, 0x091651ad, F=0x0 -0, 56, 56, 1, 5919, 0x32a7c5a2, F=0x0 -0, 57, 57, 1, 6005, 0x88adf6be, F=0x0 -0, 58, 58, 1, 5954, 0x3f92f18d, F=0x0 -0, 59, 59, 1, 6476, 0x9d90d099, F=0x0 -0, 60, 60, 1, 6745, 0xdf4f3cb1, F=0x0 -0, 61, 61, 1, 6283, 0x6e7e8f63, F=0x0 -0, 62, 62, 1, 6649, 0x5c1f366c, F=0x0 -0, 63, 63, 1, 6386, 0xa09389c3, F=0x0 -0, 64, 64, 1, 6265, 0xe5b85888, F=0x0 -0, 65, 65, 1, 6916, 0x445e734f, F=0x0 -0, 66, 66, 1, 7238, 0x30a52626, F=0x0 -0, 67, 67, 1, 7564, 0x1ddaa7cc, F=0x0 -0, 68, 68, 1, 7421, 0x118e7850, F=0x0 -0, 69, 69, 1, 7484, 0x5459acd8, F=0x0 -0, 70, 70, 1, 7604, 0x66f9e6a5, F=0x0 -0, 71, 71, 1, 7764, 0x862c0630, F=0x0 -0, 72, 72, 1, 8023, 0x06e16db8, F=0x0 -0, 73, 73, 1, 8136, 0xce28c084, F=0x0 -0, 74, 74, 1, 8109, 0x61c4aef6, F=0x0 -0, 75, 75, 1, 7871, 0x631d4073, F=0x0 -0, 76, 76, 1, 7968, 0x3b7692f0, F=0x0 -0, 77, 77, 1, 8246, 0x531bebc2, F=0x0 -0, 78, 78, 1, 8329, 0xe1fd48c9, F=0x0 -0, 79, 79, 1, 8570, 0x996fc156, F=0x0 -0, 80, 80, 1, 8754, 0x99fb0c5a, F=0x0 -0, 81, 81, 1, 8586, 0xf3eba620, F=0x0 -0, 82, 82, 1, 8886, 0xa08258a9, F=0x0 -0, 83, 83, 1, 9085, 0x229359d3, F=0x0 -0, 84, 84, 1, 9318, 0x3baaf9b9, F=0x0 -0, 85, 85, 1, 9402, 0xe27a4804, F=0x0 -0, 86, 86, 1, 9169, 0x23fd9a49, F=0x0 -0, 87, 87, 1, 9470, 0xe389379c, F=0x0 -0, 88, 88, 1, 9658, 0x6a409434, F=0x0 -0, 89, 89, 1, 9709, 0x42969ccd, F=0x0 -0, 90, 90, 1, 9531, 0x473139f3, F=0x0 -0, 91, 91, 1, 9899, 0xb85e0cd0, F=0x0 -0, 92, 92, 1, 10013, 0xda4d4db8, F=0x0 -0, 93, 93, 1, 10046, 0x0cc12baa, F=0x0 -0, 94, 94, 1, 10094, 0x22b6451c, F=0x0 -0, 95, 95, 1, 10446, 0x03a604aa, F=0x0 -0, 96, 96, 1, 10591, 0x3c8d599a, F=0x0 -0, 97, 97, 1, 10589, 0x3936826f, F=0x0 -0, 98, 98, 1, 10815, 0xb795dc11, F=0x0 -0, 99, 99, 1, 11119, 0x506c5187, F=0x0 -0, 100, 100, 1, 11202, 0x92856baf, F=0x0 -0, 101, 101, 1, 11248, 0xdf29a1db, F=0x0 -0, 102, 102, 1, 11491, 0x656df632, F=0x0 -0, 103, 103, 1, 11688, 0xeb175aa9, F=0x0 -0, 104, 104, 1, 11793, 0x99ccb713, F=0x0 -0, 105, 105, 1, 11444, 0x602c0c0d, F=0x0 -0, 106, 106, 1, 11936, 0xe89cc9bd, F=0x0 -0, 107, 107, 1, 11940, 0xc668bf2f, F=0x0 -0, 108, 108, 1, 12289, 0x9bd5780d, F=0x0 -0, 109, 109, 1, 12342, 0xd9c680fb, F=0x0 -0, 110, 110, 1, 12460, 0xb539b50f, F=0x0 -0, 111, 111, 1, 12703, 0x07473fac, F=0x0 -0, 112, 112, 1, 12676, 0x743052ae, F=0x0 -0, 113, 113, 1, 12965, 0xf6aaa045, F=0x0 -0, 114, 114, 1, 13062, 0xea13e513, F=0x0 -0, 115, 115, 1, 13155, 0x82312fa0, F=0x0 -0, 116, 116, 1, 13179, 0xd59c1dda, F=0x0 -0, 117, 117, 1, 13206, 0xde825850, F=0x0 -0, 118, 118, 1, 13219, 0x0b375f69, F=0x0 -0, 119, 119, 1, 13218, 0x14036301, F=0x0 -0, 120, 120, 1, 13475, 0x259da599, F=0x0 -0, 121, 121, 1, 13673, 0x9b43dd2a, F=0x0 -0, 122, 122, 1, 13700, 0x190bebf1, F=0x0 -0, 123, 123, 1, 13829, 0x9f802c28, F=0x0 -0, 124, 124, 1, 13954, 0x5236926c, F=0x0 -0, 125, 125, 1, 14071, 0xf5c3d36a, F=0x0 -0, 126, 126, 1, 14132, 0xbf35cdb9, F=0x0 -0, 127, 127, 1, 14339, 0x9cf65120, F=0x0 -0, 128, 128, 1, 14477, 0x3a9eabb7, F=0x0 -0, 129, 129, 1, 14544, 0xed09a2d3, F=0x0 -0, 130, 130, 1, 14616, 0xa138d2a0, F=0x0 -0, 131, 131, 1, 14906, 0x13bd28eb, F=0x0 -0, 132, 132, 1, 14986, 0x5454a127, F=0x0 -0, 133, 133, 1, 15150, 0x585cdb9b, F=0x0 -0, 134, 134, 1, 15137, 0x191bbaae, F=0x0 -0, 135, 135, 1, 15251, 0xa8461431, F=0x0 -0, 136, 136, 1, 15345, 0x2015670e, F=0x0 -0, 137, 137, 1, 15646, 0x772da02d, F=0x0 -0, 138, 138, 1, 15920, 0xfabc27f3, F=0x0 -0, 139, 139, 1, 16049, 0x2a66498f, F=0x0 -0, 140, 140, 1, 16236, 0x29750328, F=0x0 -0, 141, 141, 1, 16270, 0x4528e71c, F=0x0 -0, 142, 142, 1, 16379, 0x9a450fab, F=0x0 -0, 143, 143, 1, 16669, 0x31ffaac8, F=0x0 -0, 144, 144, 1, 16925, 0x6c4318ac, F=0x0 -0, 145, 145, 1, 17157, 0xf4b1cf0c, F=0x0 -0, 146, 146, 1, 17180, 0xd1bab36c, F=0x0 -0, 147, 147, 1, 17323, 0x419eaee3, F=0x0 -0, 148, 148, 1, 17405, 0xdf3f16ee, F=0x0 -0, 149, 149, 1, 17439, 0x7153f9f8, F=0x0 -0, 150, 150, 1, 17584, 0x1612557d, F=0x0 -0, 151, 151, 1, 17772, 0xffa78d73, F=0x0 -0, 152, 152, 1, 17834, 0x3e33866a, F=0x0 -0, 153, 153, 1, 17926, 0xdfc39bcd, F=0x0 -0, 154, 154, 1, 17831, 0x5f8ebc12, F=0x0 -0, 155, 155, 1, 18150, 0xc25e1f7f, F=0x0 -0, 156, 156, 1, 18265, 0x9b688807, F=0x0 -0, 157, 157, 1, 18345, 0xdc6abd59, F=0x0 -0, 158, 158, 1, 18301, 0x14d43a0e, F=0x0 -0, 159, 159, 1, 18426, 0x3b2cbcde, F=0x0 -0, 160, 160, 1, 18615, 0x6fa5492e, F=0x0 -0, 161, 161, 1, 18924, 0xa370be9b, F=0x0 -0, 162, 162, 1, 19081, 0xe019041b, F=0x0 -0, 163, 163, 1, 19176, 0x1acc040f, F=0x0 -0, 164, 164, 1, 19218, 0x27080108, F=0x0 -0, 165, 165, 1, 19406, 0xae676585, F=0x0 -0, 166, 166, 1, 19488, 0x9619a232, F=0x0 -0, 167, 167, 1, 19667, 0x88e71365, F=0x0 -0, 168, 168, 1, 19680, 0xd20d1a77, F=0x0 -0, 169, 169, 1, 19944, 0xc3d0647e, F=0x0 -0, 170, 170, 1, 19983, 0xbca79c59, F=0x0 -0, 171, 171, 1, 20029, 0x2c238ced, F=0x0 -0, 172, 172, 1, 20068, 0xaad778bc, F=0x0 +0, 1, 1, 1, 158, 0xfa673468, F=0x0 +0, 2, 2, 1, 143, 0x61cf2b35, F=0x0 +0, 3, 3, 1, 169, 0x152a369a, F=0x0 +0, 4, 4, 1, 254, 0x22935c08, F=0x0 +0, 5, 5, 1, 221, 0x9972496f, F=0x0 +0, 6, 6, 1, 176, 0xf6af3ab2, F=0x0 +0, 7, 7, 1, 189, 0xcdc23f20, F=0x0 +0, 8, 8, 1, 139, 0x081e3020, F=0x0 +0, 9, 9, 1, 160, 0x9153335f, F=0x0 +0, 10, 10, 1, 149, 0x8fa12e7d, F=0x0 +0, 11, 11, 1, 190, 0x43ef3de1, F=0x0 +0, 12, 12, 1, 308, 0x95c77160, F=0x0 +0, 13, 13, 1, 193, 0xf9084196, F=0x0 +0, 14, 14, 1, 191, 0x07784447, F=0x0 +0, 15, 15, 1, 198, 0x7d72420a, F=0x0 +0, 16, 16, 1, 417, 0xbf40acdc, F=0x0 +0, 17, 17, 1, 163, 0xf7df3842, F=0x0 +0, 18, 18, 1, 383, 0xadcf9e8e, F=0x0 +0, 19, 19, 1, 193, 0xba544052, F=0x0 +0, 20, 20, 1, 337, 0x1510922f, F=0x0 +0, 21, 21, 1, 199, 0x11d64936, F=0x0 +0, 22, 22, 1, 308, 0x79597dbc, F=0x0 +0, 23, 23, 1, 186, 0x25d04175, F=0x0 +0, 24, 24, 1, 199, 0x8b65402f, F=0x0 +0, 25, 25, 1, 163, 0x128e38b6, F=0x0 +0, 26, 26, 1, 302, 0xacc979b2, F=0x0 +0, 27, 27, 1, 189, 0x491f3c5c, F=0x0 +0, 28, 28, 1, 157, 0x50783600, F=0x0 +0, 29, 29, 1, 205, 0xad9045b3, F=0x0 +0, 30, 30, 1, 160, 0xcbf332f8, F=0x0 +0, 31, 31, 1, 202, 0xc72c48bf, F=0x0 +0, 32, 32, 1, 160, 0xe6c436dd, F=0x0 +0, 33, 33, 1, 215, 0x4f705072, F=0x0 +0, 34, 34, 1, 422, 0xed27b0b0, F=0x0 +0, 35, 35, 1, 184, 0x6ba8415a, F=0x0 +0, 36, 36, 1, 289, 0x0b5f73a3, F=0x0 +0, 37, 37, 1, 190, 0xea5b4316, F=0x0 +0, 38, 38, 1, 195, 0xd9f2441d, F=0x0 +0, 39, 39, 1, 199, 0x47e34e05, F=0x0 +0, 40, 40, 1, 448, 0xec8bbf56, F=0x0 +0, 41, 41, 1, 170, 0x42fb3755, F=0x0 +0, 42, 42, 1, 279, 0x87cc6f54, F=0x0 +0, 43, 43, 1, 180, 0x085f398a, F=0x0 +0, 44, 44, 1, 303, 0x46fe7c55, F=0x0 +0, 45, 45, 1, 209, 0xc60b5116, F=0x0 +0, 46, 46, 1, 198, 0x795f4655, F=0x0 +0, 47, 47, 1, 194, 0xeb1b4abe, F=0x0 +0, 48, 48, 1, 186, 0x97b44251, F=0x0 +0, 49, 49, 1, 1200, 0xeb5a36ba, F=0x0 +0, 50, 50, 1, 204, 0x00bc4594, F=0x0 +0, 51, 51, 1, 1066, 0xdc39eee0, F=0x0 +0, 52, 52, 1, 187, 0x344b4304, F=0x0 +0, 53, 53, 1, 323, 0x899f8522, F=0x0 +0, 54, 54, 1, 205, 0x48af49da, F=0x0 +0, 55, 55, 1, 213, 0xf2534ff5, F=0x0 +0, 56, 56, 1, 208, 0x8fba4b25, F=0x0 +0, 57, 57, 1, 737, 0x1612477c, F=0x0 +0, 58, 58, 1, 181, 0x903b38ad, F=0x0 +0, 59, 59, 1, 614, 0xb154157d, F=0x0 +0, 60, 60, 1, 215, 0x4e82532e, F=0x0 +0, 61, 61, 1, 291, 0x69476efd, F=0x0 +0, 62, 62, 1, 208, 0x471d4ea1, F=0x0 +0, 63, 63, 1, 208, 0xa2b04628, F=0x0 +0, 64, 64, 1, 203, 0x96d646b2, F=0x0 +0, 65, 65, 1, 531, 0xd085ea85, F=0x0 +0, 66, 66, 1, 178, 0x51663ad1, F=0x0 +0, 67, 67, 1, 446, 0x00adbe2d, F=0x0 +0, 68, 68, 1, 188, 0x7ccb3dda, F=0x0 +0, 69, 69, 1, 177, 0xd881441a, F=0x0 +0, 70, 70, 1, 112, 0x44cc2135, F=0x0 +0, 71, 71, 1, 296, 0x717d7172, F=0x0 +0, 72, 72, 1, 153, 0xbd403424, F=0x0 +0, 73, 73, 1, 218, 0x1d9a4f26, F=0x0 +0, 74, 74, 1, 202, 0x6ee647eb, F=0x0 +0, 75, 75, 1, 239, 0x71245ad2, F=0x0 +0, 76, 76, 1, 139, 0xbbdd2d23, F=0x0 +0, 77, 77, 1, 467, 0x6e1cc838, F=0x0 +0, 78, 78, 1, 274, 0xea1079c5, F=0x0 +0, 79, 79, 1, 404, 0xbf5caaa0, F=0x0 +0, 80, 80, 1, 257, 0xac4865e5, F=0x0 +0, 81, 81, 1, 419, 0xa45ab5fc, F=0x0 +0, 82, 82, 1, 208, 0xb5dd4fc3, F=0x0 +0, 83, 83, 1, 294, 0xcf5176ee, F=0x0 +0, 84, 84, 1, 191, 0xed7e3e98, F=0x0 +0, 85, 85, 1, 181, 0x9105450e, F=0x0 +0, 86, 86, 1, 218, 0x445c54ae, F=0x0 +0, 87, 87, 1, 423, 0x5dc9bec5, F=0x0 +0, 88, 88, 1, 202, 0xdfde4a35, F=0x0 +0, 89, 89, 1, 317, 0x9a918033, F=0x0 +0, 90, 90, 1, 172, 0x081e3d8c, F=0x0 +0, 91, 91, 1, 275, 0x37536b50, F=0x0 +0, 92, 92, 1, 214, 0xecfc4e8f, F=0x0 +0, 93, 93, 1, 182, 0x85bf44e5, F=0x0 +0, 94, 94, 1, 151, 0x4c8230ae, F=0x0 +0, 95, 95, 1, 157, 0xa02a32eb, F=0x0 +0, 96, 96, 1, 202, 0xb24a4355, F=0x0 +0, 97, 97, 1, 162, 0x632d3576, F=0x0 +0, 98, 98, 1, 186, 0x6f9c407c, F=0x0 +0, 99, 99, 1, 318, 0xade078ca, F=0x0 +0, 100, 100, 1, 225, 0xd2754eee, F=0x0 +0, 101, 101, 1, 207, 0xdedb4552, F=0x0 +0, 102, 102, 1, 212, 0x25384cd1, F=0x0 +0, 103, 103, 1, 153, 0x489434d3, F=0x0 +0, 104, 104, 1, 196, 0x659145f9, F=0x0 +0, 105, 105, 1, 146, 0x8b223366, F=0x0 +0, 106, 106, 1, 194, 0x0bc14890, F=0x0 +0, 107, 107, 1, 304, 0xdece8235, F=0x0 +0, 108, 108, 1, 194, 0x7737464d, F=0x0 +0, 109, 109, 1, 190, 0x945e43a4, F=0x0 +0, 110, 110, 1, 204, 0x8de14af3, F=0x0 +0, 111, 111, 1, 136, 0xd0862cb1, F=0x0 +0, 112, 112, 1, 171, 0xff6f3da8, F=0x0 +0, 113, 113, 1, 140, 0x3475307b, F=0x0 +0, 114, 114, 1, 158, 0x8f31321e, F=0x0 +0, 115, 115, 1, 94, 0xf6691c01, F=0x0 +0, 116, 116, 1, 110, 0x66e52218, F=0x0 +0, 117, 117, 1, 256, 0x4b086864, F=0x0 +0, 118, 118, 1, 220, 0x6fb75337, F=0x0 +0, 119, 119, 1, 221, 0x69a94e72, F=0x0 +0, 120, 120, 1, 205, 0xbae94509, F=0x0 +0, 121, 121, 1, 169, 0xdd3c388b, F=0x0 +0, 122, 122, 1, 970, 0x9771c82f, F=0x0 +0, 123, 123, 1, 181, 0xec794298, F=0x0 +0, 124, 124, 1, 955, 0x23edba10, F=0x0 +0, 125, 125, 1, 158, 0x3ad83314, F=0x0 +0, 126, 126, 1, 344, 0x29aa8843, F=0x0 +0, 127, 127, 1, 627, 0x6d3f18dc, F=0x0 +0, 128, 128, 1, 172, 0x985d3cc5, F=0x0 +0, 129, 129, 1, 494, 0x591cdcc3, F=0x0 +0, 130, 130, 1, 184, 0x83ca42c1, F=0x0 +0, 131, 131, 1, 352, 0x68169925, F=0x0 +0, 132, 132, 1, 351, 0x06998cfa, F=0x0 +0, 133, 133, 1, 170, 0xaec83809, F=0x0 +0, 134, 134, 1, 275, 0xd1ea6a74, F=0x0 +0, 135, 135, 1, 168, 0xe9b93a2e, F=0x0 +0, 136, 136, 1, 169, 0xa27f3870, F=0x0 +0, 137, 137, 1, 521, 0xf195dc2e, F=0x0 +0, 138, 138, 1, 1262, 0x52b34497, F=0x0 +0, 139, 139, 1, 994, 0x9d72bc25, F=0x0 +0, 140, 140, 1, 290, 0xb2c17360, F=0x0 +0, 141, 141, 1, 188, 0x2c30402b, F=0x0 +0, 142, 142, 1, 164, 0x8bb13b7a, F=0x0 +0, 143, 143, 1, 212, 0x69af44ca, F=0x0 +0, 144, 144, 1, 870, 0xebc09472, F=0x0 +0, 145, 145, 1, 635, 0x1f781aee, F=0x0 +0, 146, 146, 1, 290, 0x01a5786c, F=0x0 +0, 147, 147, 1, 211, 0xec4d5052, F=0x0 +0, 148, 148, 1, 177, 0x56db3c7b, F=0x0 +0, 149, 149, 1, 182, 0x312c3f58, F=0x0 +0, 150, 150, 1, 588, 0x9924fcca, F=0x0 +0, 151, 151, 1, 163, 0xe23a370e, F=0x0 +0, 152, 152, 1, 407, 0x525ab1a8, F=0x0 +0, 153, 153, 1, 204, 0x0b84449d, F=0x0 +0, 154, 154, 1, 290, 0xa97e7886, F=0x0 +0, 155, 155, 1, 308, 0xac988116, F=0x0 +0, 156, 156, 1, 196, 0x6d6c47fa, F=0x0 +0, 157, 157, 1, 181, 0x7a413f71, F=0x0 +0, 158, 158, 1, 203, 0xb03b4fa8, F=0x0 +0, 159, 159, 1, 227, 0xb3d55aeb, F=0x0 +0, 160, 160, 1, 524, 0xa731e285, F=0x0 +0, 161, 161, 1, 377, 0x4ac097de, F=0x0 +0, 162, 162, 1, 196, 0x78264511, F=0x0 +0, 163, 163, 1, 250, 0x6d4f65a1, F=0x0 +0, 164, 164, 1, 214, 0x31534ffe, F=0x0 +0, 165, 165, 1, 323, 0xd4d78fa2, F=0x0 +0, 166, 166, 1, 176, 0x642e40ab, F=0x0 +0, 167, 167, 1, 305, 0x63db7e18, F=0x0 +0, 168, 168, 1, 179, 0x4c4042da, F=0x0 +0, 169, 169, 1, 245, 0x645264fb, F=0x0 +0, 170, 170, 1, 181, 0x0a3e403e, F=0x0 +0, 171, 171, 1, 241, 0x592e57b1, F=0x0 +0, 172, 172, 1, 172, 0xf5cb3f7f, F=0x0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/gifenc-rgb8 ffmpeg-4.4/tests/ref/fate/gifenc-rgb8 --- ffmpeg-4.2.2/tests/ref/fate/gifenc-rgb8 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/gifenc-rgb8 2020-07-11 10:39:30.000000000 +0000 @@ -4,175 +4,175 @@ #dimensions 0: 217x217 #sar 0: 0/1 0, 0, 0, 1, 1341, 0xaa85adb1 -0, 1, 1, 1, 305, 0xa970896f, F=0x0 -0, 2, 2, 1, 446, 0x4a20d47a, F=0x0 -0, 3, 3, 1, 458, 0x32ded2af, F=0x0 -0, 4, 4, 1, 555, 0x622205e4, F=0x0 -0, 5, 5, 1, 622, 0xde06214f, F=0x0 -0, 6, 6, 1, 650, 0x8f482007, F=0x0 -0, 7, 7, 1, 668, 0xd3df3a59, F=0x0 -0, 8, 8, 1, 829, 0x812f80d4, F=0x0 -0, 9, 9, 1, 1165, 0x8e402ff5, F=0x0 -0, 10, 10, 1, 187, 0xdda45544, F=0x0 -0, 11, 11, 1, 1341, 0x2f2d71cf, F=0x0 -0, 12, 12, 1, 1646, 0xfe910a65, F=0x0 -0, 13, 13, 1, 1539, 0xbc77e727, F=0x0 -0, 14, 14, 1, 1728, 0x9bd9486b, F=0x0 -0, 15, 15, 1, 1918, 0xcf948795, F=0x0 -0, 16, 16, 1, 2132, 0x4618dbf8, F=0x0 -0, 17, 17, 1, 2256, 0xcdce2bb0, F=0x0 -0, 18, 18, 1, 2319, 0x4f1b36d7, F=0x0 -0, 19, 19, 1, 2416, 0xcba76df1, F=0x0 -0, 20, 20, 1, 2609, 0xb2eec38f, F=0x0 -0, 21, 21, 1, 2695, 0x29d40439, F=0x0 -0, 22, 22, 1, 2792, 0x663f0f16, F=0x0 -0, 23, 23, 1, 2892, 0xd6924cc1, F=0x0 -0, 24, 24, 1, 2990, 0x8bed794d, F=0x0 -0, 25, 25, 1, 3109, 0x48789f36, F=0x0 -0, 26, 26, 1, 3261, 0x3eaff7a0, F=0x0 -0, 27, 27, 1, 3337, 0x3bcd1c99, F=0x0 -0, 28, 28, 1, 3580, 0xcf0c8b7a, F=0x0 -0, 29, 29, 1, 3815, 0x53d40009, F=0x0 -0, 30, 30, 1, 2758, 0x73fd20c6, F=0x0 -0, 31, 31, 1, 4039, 0xab517451, F=0x0 -0, 32, 32, 1, 3033, 0x66d29fbc, F=0x0 -0, 33, 33, 1, 4303, 0x30e50ba8, F=0x0 -0, 34, 34, 1, 2052, 0x4843c19a, F=0x0 -0, 35, 35, 1, 3220, 0x73f7f1b7, F=0x0 -0, 36, 36, 1, 2300, 0xca376466, F=0x0 -0, 37, 37, 1, 3641, 0x1e3a9bcb, F=0x0 -0, 38, 38, 1, 3560, 0x014776da, F=0x0 -0, 39, 39, 1, 3698, 0xd3bcde35, F=0x0 -0, 40, 40, 1, 1567, 0x6c8bf458, F=0x0 -0, 41, 41, 1, 962, 0x0389caed, F=0x0 -0, 42, 42, 1, 281, 0x575f7959, F=0x0 -0, 43, 43, 1, 938, 0x2d7aaf67, F=0x0 -0, 44, 44, 1, 279, 0xd39d81d7, F=0x0 -0, 45, 45, 1, 204, 0x90a9544a, F=0x0 -0, 46, 46, 1, 4307, 0xcf9d0eae, F=0x0 -0, 47, 47, 1, 4903, 0xe9743ace, F=0x0 -0, 48, 48, 1, 4936, 0x3cf21510, F=0x0 -0, 49, 49, 1, 4949, 0xcbff5648, F=0x0 -0, 50, 50, 1, 4162, 0x94a9b9ce, F=0x0 -0, 51, 51, 1, 4686, 0x5098c461, F=0x0 -0, 52, 52, 1, 4749, 0x7304bc6d, F=0x0 -0, 53, 53, 1, 4990, 0x9d025a9f, F=0x0 -0, 54, 54, 1, 5187, 0x0566c4c9, F=0x0 -0, 55, 55, 1, 5054, 0x574f81f5, F=0x0 -0, 56, 56, 1, 5148, 0xe7bac30f, F=0x0 -0, 57, 57, 1, 4309, 0x7844f361, F=0x0 -0, 58, 58, 1, 5087, 0xacf4a406, F=0x0 -0, 59, 59, 1, 5292, 0x9e7be109, F=0x0 -0, 60, 60, 1, 5434, 0x85541f7f, F=0x0 -0, 61, 61, 1, 4653, 0xf5118b09, F=0x0 -0, 62, 62, 1, 5271, 0x54f3d911, F=0x0 -0, 63, 63, 1, 5229, 0xc520cb6b, F=0x0 -0, 64, 64, 1, 5225, 0x2a449e23, F=0x0 -0, 65, 65, 1, 5403, 0x4a2502f3, F=0x0 -0, 66, 66, 1, 5228, 0x8002e47d, F=0x0 -0, 67, 67, 1, 5712, 0x9c9ed686, F=0x0 -0, 68, 68, 1, 5644, 0xfdf5a30d, F=0x0 -0, 69, 69, 1, 5826, 0xb142ece5, F=0x0 -0, 70, 70, 1, 5771, 0xd22ac8b9, F=0x0 -0, 71, 71, 1, 6124, 0x5e4e8f58, F=0x0 -0, 72, 72, 1, 6077, 0x94ab6503, F=0x0 -0, 73, 73, 1, 5804, 0x5c56e07a, F=0x0 -0, 74, 74, 1, 6007, 0x3e453829, F=0x0 -0, 75, 75, 1, 6228, 0xa4e0b278, F=0x0 -0, 76, 76, 1, 6382, 0xd488ebcd, F=0x0 -0, 77, 77, 1, 6473, 0xb1bb78b2, F=0x0 -0, 78, 78, 1, 7027, 0x98ce29cb, F=0x0 -0, 79, 79, 1, 7263, 0xecadb896, F=0x0 -0, 80, 80, 1, 8205, 0x36cb6ba1, F=0x0 -0, 81, 81, 1, 8366, 0xdbbe8308, F=0x0 -0, 82, 82, 1, 7716, 0xd6959765, F=0x0 -0, 83, 83, 1, 7420, 0x60fd1316, F=0x0 -0, 84, 84, 1, 7549, 0x668a1ae9, F=0x0 -0, 85, 85, 1, 7956, 0xe146cb65, F=0x0 -0, 86, 86, 1, 8416, 0x47c3d590, F=0x0 -0, 87, 87, 1, 8064, 0x9a0e249f, F=0x0 -0, 88, 88, 1, 7409, 0x9e5eb771, F=0x0 -0, 89, 89, 1, 7502, 0x1906fad6, F=0x0 -0, 90, 90, 1, 7814, 0x8e117365, F=0x0 -0, 91, 91, 1, 7776, 0xd0077a82, F=0x0 -0, 92, 92, 1, 7757, 0x74a49d3a, F=0x0 -0, 93, 93, 1, 8055, 0x70ef25d2, F=0x0 -0, 94, 94, 1, 7626, 0x4a003537, F=0x0 -0, 95, 95, 1, 7987, 0x1c14c607, F=0x0 -0, 96, 96, 1, 12070, 0x4a729eba, F=0x0 -0, 97, 97, 1, 12325, 0xbff1dd34, F=0x0 -0, 98, 98, 1, 12225, 0xb1ffee58, F=0x0 -0, 99, 99, 1, 11235, 0xea998fe1, F=0x0 -0, 100, 100, 1, 11116, 0x855407b4, F=0x0 -0, 101, 101, 1, 11374, 0xaa019a67, F=0x0 -0, 102, 102, 1, 11904, 0xf8384969, F=0x0 -0, 103, 103, 1, 11487, 0xce63834d, F=0x0 -0, 104, 104, 1, 13403, 0x36444d9a, F=0x0 -0, 105, 105, 1, 12921, 0x86af447b, F=0x0 -0, 106, 106, 1, 13872, 0x104af758, F=0x0 -0, 107, 107, 1, 13559, 0x37d07d0f, F=0x0 -0, 108, 108, 1, 14049, 0xa47572e1, F=0x0 -0, 109, 109, 1, 14152, 0x217c3e45, F=0x0 -0, 110, 110, 1, 14285, 0xf37e5a5d, F=0x0 -0, 111, 111, 1, 14432, 0xd841f100, F=0x0 -0, 112, 112, 1, 14697, 0xf25cd254, F=0x0 -0, 113, 113, 1, 14606, 0x4f3069dc, F=0x0 -0, 114, 114, 1, 15221, 0x222f9680, F=0x0 -0, 115, 115, 1, 15433, 0x3e43af1c, F=0x0 -0, 116, 116, 1, 15603, 0x038a0ae1, F=0x0 -0, 117, 117, 1, 15606, 0x9040acec, F=0x0 -0, 118, 118, 1, 15871, 0xd63f0294, F=0x0 -0, 119, 119, 1, 15725, 0xe95d42ec, F=0x0 -0, 120, 120, 1, 16086, 0x27223bb4, F=0x0 -0, 121, 121, 1, 16233, 0xebfca656, F=0x0 -0, 122, 122, 1, 16143, 0x1a7717ba, F=0x0 -0, 123, 123, 1, 16669, 0x56926ea6, F=0x0 -0, 124, 124, 1, 16627, 0xe0ac5c7e, F=0x0 -0, 125, 125, 1, 16837, 0x67b5c267, F=0x0 -0, 126, 126, 1, 16952, 0x2d9bd2b7, F=0x0 -0, 127, 127, 1, 17127, 0xcab06c88, F=0x0 -0, 128, 128, 1, 17158, 0x10be3e59, F=0x0 -0, 129, 129, 1, 17329, 0x53d2ef82, F=0x0 -0, 130, 130, 1, 17403, 0x37a5ca9c, F=0x0 -0, 131, 131, 1, 17674, 0x0e34434b, F=0x0 -0, 132, 132, 1, 17738, 0xc1ef86db, F=0x0 -0, 133, 133, 1, 17942, 0xbf37caa5, F=0x0 -0, 134, 134, 1, 17952, 0x256e0aee, F=0x0 -0, 135, 135, 1, 18246, 0xd818335f, F=0x0 -0, 136, 136, 1, 18399, 0x6b84c5b2, F=0x0 -0, 137, 137, 1, 18551, 0x5e02f360, F=0x0 -0, 138, 138, 1, 18947, 0x5cdbdb83, F=0x0 -0, 139, 139, 1, 19153, 0x97f52a72, F=0x0 -0, 140, 140, 1, 19128, 0x537baaeb, F=0x0 -0, 141, 141, 1, 19138, 0xa629eee4, F=0x0 -0, 142, 142, 1, 19502, 0x4b8da41b, F=0x0 -0, 143, 143, 1, 19542, 0x21a5a87a, F=0x0 -0, 144, 144, 1, 19755, 0xc5d0c4a1, F=0x0 -0, 145, 145, 1, 20122, 0x913a698c, F=0x0 -0, 146, 146, 1, 20265, 0xfdbcdb4e, F=0x0 -0, 147, 147, 1, 20378, 0x173f3952, F=0x0 -0, 148, 148, 1, 20300, 0xff58f32f, F=0x0 -0, 149, 149, 1, 20499, 0x89246e44, F=0x0 -0, 150, 150, 1, 20655, 0xff78de6d, F=0x0 -0, 151, 151, 1, 20674, 0x9ccbc9cc, F=0x0 -0, 152, 152, 1, 21015, 0x289450a5, F=0x0 -0, 153, 153, 1, 21066, 0x006d6bc5, F=0x0 -0, 154, 154, 1, 21161, 0x306b4b03, F=0x0 -0, 155, 155, 1, 21086, 0x5c4f8181, F=0x0 -0, 156, 156, 1, 21466, 0x5be353c4, F=0x0 -0, 157, 157, 1, 21677, 0xbc05e406, F=0x0 -0, 158, 158, 1, 21589, 0xa69322d7, F=0x0 -0, 159, 159, 1, 21662, 0x64e7ac40, F=0x0 -0, 160, 160, 1, 21995, 0xbfa18826, F=0x0 -0, 161, 161, 1, 22213, 0xb9fa745d, F=0x0 -0, 162, 162, 1, 22483, 0x3070e144, F=0x0 -0, 163, 163, 1, 22498, 0x1feb3894, F=0x0 -0, 164, 164, 1, 22468, 0xb34dbd26, F=0x0 -0, 165, 165, 1, 22869, 0x67c63638, F=0x0 -0, 166, 166, 1, 22754, 0xaa2d573d, F=0x0 -0, 167, 167, 1, 23173, 0x9f7767cb, F=0x0 -0, 168, 168, 1, 23281, 0x3f319c01, F=0x0 -0, 169, 169, 1, 23219, 0xb706632d, F=0x0 -0, 170, 170, 1, 23656, 0x7e2ff143, F=0x0 -0, 171, 171, 1, 23683, 0x729d61e1, F=0x0 -0, 172, 172, 1, 23882, 0x8fb999ed, F=0x0 +0, 1, 1, 1, 236, 0xa46f676e, F=0x0 +0, 2, 2, 1, 186, 0xd99b4ec2, F=0x0 +0, 3, 3, 1, 208, 0xb9be5007, F=0x0 +0, 4, 4, 1, 282, 0xe43d8422, F=0x0 +0, 5, 5, 1, 209, 0xda215145, F=0x0 +0, 6, 6, 1, 225, 0xc6375b19, F=0x0 +0, 7, 7, 1, 204, 0x467a54c1, F=0x0 +0, 8, 8, 1, 181, 0x1c0e4dae, F=0x0 +0, 9, 9, 1, 200, 0xc55e53c1, F=0x0 +0, 10, 10, 1, 184, 0x87644454, F=0x0 +0, 11, 11, 1, 191, 0x3847484a, F=0x0 +0, 12, 12, 1, 290, 0x9ce37f1f, F=0x0 +0, 13, 13, 1, 153, 0x7ab03afc, F=0x0 +0, 14, 14, 1, 175, 0x64bc4621, F=0x0 +0, 15, 15, 1, 187, 0x9284451d, F=0x0 +0, 16, 16, 1, 418, 0x7b18c8a5, F=0x0 +0, 17, 17, 1, 200, 0xf8e5527f, F=0x0 +0, 18, 18, 1, 347, 0xbc6494eb, F=0x0 +0, 19, 19, 1, 176, 0x8d1842e5, F=0x0 +0, 20, 20, 1, 294, 0x52fe8678, F=0x0 +0, 21, 21, 1, 166, 0x614142a1, F=0x0 +0, 22, 22, 1, 306, 0xafe8850d, F=0x0 +0, 23, 23, 1, 180, 0xa2cc44a0, F=0x0 +0, 24, 24, 1, 207, 0x91e25233, F=0x0 +0, 25, 25, 1, 204, 0x0f174cb7, F=0x0 +0, 26, 26, 1, 259, 0x629071c3, F=0x0 +0, 27, 27, 1, 181, 0x950e4a15, F=0x0 +0, 28, 28, 1, 152, 0x77023d8a, F=0x0 +0, 29, 29, 1, 194, 0x890b4d08, F=0x0 +0, 30, 30, 1, 159, 0xaa5a397d, F=0x0 +0, 31, 31, 1, 162, 0x8ae73c95, F=0x0 +0, 32, 32, 1, 178, 0x7fba4974, F=0x0 +0, 33, 33, 1, 187, 0x41fd52cc, F=0x0 +0, 34, 34, 1, 336, 0xd8139332, F=0x0 +0, 35, 35, 1, 184, 0x61b3484a, F=0x0 +0, 36, 36, 1, 227, 0x8be2607e, F=0x0 +0, 37, 37, 1, 182, 0x9bc84478, F=0x0 +0, 38, 38, 1, 162, 0x33423e3c, F=0x0 +0, 39, 39, 1, 187, 0x62fd4805, F=0x0 +0, 40, 40, 1, 503, 0xfc0ce5c8, F=0x0 +0, 41, 41, 1, 167, 0x40bd40d7, F=0x0 +0, 42, 42, 1, 289, 0xe5ad805c, F=0x0 +0, 43, 43, 1, 194, 0xc0174c24, F=0x0 +0, 44, 44, 1, 285, 0x48f38060, F=0x0 +0, 45, 45, 1, 199, 0x62bd52dc, F=0x0 +0, 46, 46, 1, 197, 0xcc1f4d1d, F=0x0 +0, 47, 47, 1, 203, 0xa0cb4c90, F=0x0 +0, 48, 48, 1, 208, 0x460155cd, F=0x0 +0, 49, 49, 1, 1198, 0x0b795bb1, F=0x0 +0, 50, 50, 1, 175, 0x36cc4a76, F=0x0 +0, 51, 51, 1, 740, 0xeb6f68b9, F=0x0 +0, 52, 52, 1, 180, 0xa22544ba, F=0x0 +0, 53, 53, 1, 238, 0x08ff6b12, F=0x0 +0, 54, 54, 1, 198, 0x3d4d50dd, F=0x0 +0, 55, 55, 1, 196, 0xbef74ccd, F=0x0 +0, 56, 56, 1, 224, 0x47c05ea9, F=0x0 +0, 57, 57, 1, 765, 0xb89e6f01, F=0x0 +0, 58, 58, 1, 149, 0x26bb3969, F=0x0 +0, 59, 59, 1, 479, 0xcdd6d6bf, F=0x0 +0, 60, 60, 1, 179, 0x537948eb, F=0x0 +0, 61, 61, 1, 217, 0x6b9b5b06, F=0x0 +0, 62, 62, 1, 190, 0x56b54a3a, F=0x0 +0, 63, 63, 1, 155, 0x487439ef, F=0x0 +0, 64, 64, 1, 167, 0x1bb947ba, F=0x0 +0, 65, 65, 1, 649, 0xb44a3058, F=0x0 +0, 66, 66, 1, 196, 0x66ae5688, F=0x0 +0, 67, 67, 1, 427, 0x8b0bd38d, F=0x0 +0, 68, 68, 1, 175, 0xbb9d4294, F=0x0 +0, 69, 69, 1, 284, 0x9f768221, F=0x0 +0, 70, 70, 1, 131, 0x612d2e14, F=0x0 +0, 71, 71, 1, 256, 0x701a69b4, F=0x0 +0, 72, 72, 1, 186, 0xf7114a80, F=0x0 +0, 73, 73, 1, 190, 0x53144c4d, F=0x0 +0, 74, 74, 1, 216, 0xc67b53e5, F=0x0 +0, 75, 75, 1, 154, 0xc04e39ba, F=0x0 +0, 76, 76, 1, 113, 0x4800284b, F=0x0 +0, 77, 77, 1, 402, 0xee43b0dd, F=0x0 +0, 78, 78, 1, 198, 0x55e451cc, F=0x0 +0, 79, 79, 1, 466, 0xb3c8cff3, F=0x0 +0, 80, 80, 1, 322, 0x5ade8d02, F=0x0 +0, 81, 81, 1, 387, 0x72edb2f7, F=0x0 +0, 82, 82, 1, 158, 0x12a5402c, F=0x0 +0, 83, 83, 1, 278, 0xd6727a4a, F=0x0 +0, 84, 84, 1, 190, 0x58205087, F=0x0 +0, 85, 85, 1, 175, 0x9a58432a, F=0x0 +0, 86, 86, 1, 206, 0x85954c9e, F=0x0 +0, 87, 87, 1, 379, 0x4f1db56a, F=0x0 +0, 88, 88, 1, 202, 0x19b05154, F=0x0 +0, 89, 89, 1, 225, 0xf4166005, F=0x0 +0, 90, 90, 1, 175, 0x44414761, F=0x0 +0, 91, 91, 1, 235, 0xe01c603f, F=0x0 +0, 92, 92, 1, 185, 0xfab74905, F=0x0 +0, 93, 93, 1, 182, 0x9c5f4ae7, F=0x0 +0, 94, 94, 1, 114, 0xe0542abd, F=0x0 +0, 95, 95, 1, 176, 0x6e274c2e, F=0x0 +0, 96, 96, 1, 214, 0x44725ac3, F=0x0 +0, 97, 97, 1, 182, 0x54e9482e, F=0x0 +0, 98, 98, 1, 195, 0x6231525e, F=0x0 +0, 99, 99, 1, 303, 0xf63c84a1, F=0x0 +0, 100, 100, 1, 191, 0x4aa84e6f, F=0x0 +0, 101, 101, 1, 177, 0xfd82496d, F=0x0 +0, 102, 102, 1, 172, 0x13d041cb, F=0x0 +0, 103, 103, 1, 179, 0x89f54866, F=0x0 +0, 104, 104, 1, 188, 0xf39d4d8d, F=0x0 +0, 105, 105, 1, 177, 0x4d0e4882, F=0x0 +0, 106, 106, 1, 215, 0xca7b5a6f, F=0x0 +0, 107, 107, 1, 339, 0x1dd598fe, F=0x0 +0, 108, 108, 1, 189, 0xe2d94497, F=0x0 +0, 109, 109, 1, 209, 0x682356be, F=0x0 +0, 110, 110, 1, 205, 0xa5af51b7, F=0x0 +0, 111, 111, 1, 185, 0xa1224e22, F=0x0 +0, 112, 112, 1, 211, 0x09a95a00, F=0x0 +0, 113, 113, 1, 178, 0x31ab47cc, F=0x0 +0, 114, 114, 1, 195, 0x960f4c9c, F=0x0 +0, 115, 115, 1, 116, 0x8f8b2da3, F=0x0 +0, 116, 116, 1, 116, 0xf30c2b3d, F=0x0 +0, 117, 117, 1, 427, 0xa3dcc81b, F=0x0 +0, 118, 118, 1, 182, 0xce37489b, F=0x0 +0, 119, 119, 1, 267, 0x516c6f3e, F=0x0 +0, 120, 120, 1, 191, 0xff5c4af7, F=0x0 +0, 121, 121, 1, 195, 0x49cd5178, F=0x0 +0, 122, 122, 1, 755, 0xb9b4608d, F=0x0 +0, 123, 123, 1, 179, 0x6d0c4600, F=0x0 +0, 124, 124, 1, 522, 0xffe5f236, F=0x0 +0, 125, 125, 1, 171, 0xea4c40b8, F=0x0 +0, 126, 126, 1, 379, 0xbf2fa98b, F=0x0 +0, 127, 127, 1, 539, 0xace2f7b5, F=0x0 +0, 128, 128, 1, 199, 0xe0534e3d, F=0x0 +0, 129, 129, 1, 458, 0x2b54d13e, F=0x0 +0, 130, 130, 1, 177, 0x6ff04b91, F=0x0 +0, 131, 131, 1, 299, 0x51d1893e, F=0x0 +0, 132, 132, 1, 333, 0x5cba941f, F=0x0 +0, 133, 133, 1, 179, 0x2381453b, F=0x0 +0, 134, 134, 1, 263, 0xac907176, F=0x0 +0, 135, 135, 1, 177, 0xb87546d9, F=0x0 +0, 136, 136, 1, 184, 0x761c4765, F=0x0 +0, 137, 137, 1, 433, 0x55f0c2d6, F=0x0 +0, 138, 138, 1, 1138, 0x3b7137a0, F=0x0 +0, 139, 139, 1, 863, 0x5afd9dae, F=0x0 +0, 140, 140, 1, 328, 0x4537973f, F=0x0 +0, 141, 141, 1, 222, 0xadb859e4, F=0x0 +0, 142, 142, 1, 171, 0x7ce844b6, F=0x0 +0, 143, 143, 1, 222, 0xa5815a1f, F=0x0 +0, 144, 144, 1, 738, 0x3fe75c6a, F=0x0 +0, 145, 145, 1, 444, 0x320fd03e, F=0x0 +0, 146, 146, 1, 267, 0x288273f3, F=0x0 +0, 147, 147, 1, 187, 0x07594c67, F=0x0 +0, 148, 148, 1, 186, 0xbd1c50de, F=0x0 +0, 149, 149, 1, 196, 0xf3e14fdb, F=0x0 +0, 150, 150, 1, 589, 0x127314a0, F=0x0 +0, 151, 151, 1, 188, 0x22d74d85, F=0x0 +0, 152, 152, 1, 339, 0xcadaa1b6, F=0x0 +0, 153, 153, 1, 179, 0x6a1843a7, F=0x0 +0, 154, 154, 1, 294, 0xe04184fa, F=0x0 +0, 155, 155, 1, 291, 0x4b018587, F=0x0 +0, 156, 156, 1, 144, 0x470f3737, F=0x0 +0, 157, 157, 1, 182, 0x3b994dcd, F=0x0 +0, 158, 158, 1, 195, 0x7f884fd3, F=0x0 +0, 159, 159, 1, 268, 0xb6097b3b, F=0x0 +0, 160, 160, 1, 526, 0x40e0fd27, F=0x0 +0, 161, 161, 1, 372, 0x9dffaa6d, F=0x0 +0, 162, 162, 1, 171, 0xc06841eb, F=0x0 +0, 163, 163, 1, 344, 0xc47da473, F=0x0 +0, 164, 164, 1, 159, 0xacf64002, F=0x0 +0, 165, 165, 1, 391, 0x520cad43, F=0x0 +0, 166, 166, 1, 180, 0x05c04cac, F=0x0 +0, 167, 167, 1, 303, 0x748493c3, F=0x0 +0, 168, 168, 1, 180, 0x3fc54928, F=0x0 +0, 169, 169, 1, 269, 0xcd227967, F=0x0 +0, 170, 170, 1, 199, 0x3a3053e8, F=0x0 +0, 171, 171, 1, 287, 0x3c37840b, F=0x0 +0, 172, 172, 1, 217, 0xabd063fc, F=0x0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-attachment-631 ffmpeg-4.4/tests/ref/fate/h264-attachment-631 --- ffmpeg-4.2.2/tests/ref/fate/h264-attachment-631 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-attachment-631 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,154 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 8/9 +0, 6, 6, 1, 518400, 0xd2068698 +0, 10, 10, 1, 518400, 0x2ee4865f +0, 14, 14, 1, 518400, 0x2a01b188 +0, 18, 18, 1, 518400, 0xa4bc9572 +0, 22, 22, 1, 518400, 0x4e882f72 +0, 26, 26, 1, 518400, 0xf79cfc9c +0, 30, 30, 1, 518400, 0x93afec23 +0, 34, 34, 1, 518400, 0xadf210e6 +0, 38, 38, 1, 518400, 0xb0bdd1f1 +0, 42, 42, 1, 518400, 0x4bbb4a24 +0, 46, 46, 1, 518400, 0x49db06c8 +0, 50, 50, 1, 518400, 0xf9781bfb +0, 54, 54, 1, 518400, 0xd3a373bc +0, 58, 58, 1, 518400, 0xccfb31c5 +0, 62, 62, 1, 518400, 0x276423a7 +0, 66, 66, 1, 518400, 0xb3729230 +0, 70, 70, 1, 518400, 0xeaf4586d +0, 74, 74, 1, 518400, 0x9e629b29 +0, 78, 78, 1, 518400, 0x921d6e58 +0, 82, 82, 1, 518400, 0xc988f527 +0, 86, 86, 1, 518400, 0x4e1fed4b +0, 90, 90, 1, 518400, 0xe3819724 +0, 94, 94, 1, 518400, 0xc07602ba +0, 98, 98, 1, 518400, 0xc6b1e8d0 +0, 102, 102, 1, 518400, 0x12d94755 +0, 106, 106, 1, 518400, 0x257a5264 +0, 110, 110, 1, 518400, 0x4f985461 +0, 114, 114, 1, 518400, 0x77577244 +0, 118, 118, 1, 518400, 0x81a59edf +0, 122, 122, 1, 518400, 0x9f33c0fa +0, 126, 126, 1, 518400, 0xa89cbb3f +0, 130, 130, 1, 518400, 0x6b1bcc1c +0, 134, 134, 1, 518400, 0x520acb74 +0, 138, 138, 1, 518400, 0x006dda91 +0, 142, 142, 1, 518400, 0x7377f96f +0, 146, 146, 1, 518400, 0x0b713224 +0, 150, 150, 1, 518400, 0x98943e53 +0, 154, 154, 1, 518400, 0x59f967e2 +0, 158, 158, 1, 518400, 0x976a2461 +0, 162, 162, 1, 518400, 0xcb4d3872 +0, 166, 166, 1, 518400, 0x0a174f59 +0, 170, 170, 1, 518400, 0x7cbe6c4f +0, 174, 174, 1, 518400, 0x475cbce4 +0, 178, 178, 1, 518400, 0x2c281bb9 +0, 182, 182, 1, 518400, 0xadee7826 +0, 186, 186, 1, 518400, 0x936059a6 +0, 190, 190, 1, 518400, 0xba09ae20 +0, 194, 194, 1, 518400, 0x355e94d7 +0, 198, 198, 1, 518400, 0xafc3a0b3 +0, 202, 202, 1, 518400, 0x55bd78af +0, 206, 206, 1, 518400, 0x9678c886 +0, 210, 210, 1, 518400, 0x4d69a62a +0, 214, 214, 1, 518400, 0x406e617c +0, 218, 218, 1, 518400, 0x7031ebdb +0, 222, 222, 1, 518400, 0xf862127d +0, 226, 226, 1, 518400, 0x619b8a53 +0, 230, 230, 1, 518400, 0x0fde6b72 +0, 234, 234, 1, 518400, 0xd137deff +0, 238, 238, 1, 518400, 0x9ae6ac2e +0, 242, 242, 1, 518400, 0x6cefb571 +0, 246, 246, 1, 518400, 0x7694dda2 +0, 250, 250, 1, 518400, 0x2253f6a2 +0, 254, 254, 1, 518400, 0x770db468 +0, 258, 258, 1, 518400, 0xf4c815a5 +0, 262, 262, 1, 518400, 0x0a0f38b6 +0, 266, 266, 1, 518400, 0x17490907 +0, 270, 270, 1, 518400, 0xbc362ed6 +0, 274, 274, 1, 518400, 0x24de1b5c +0, 278, 278, 1, 518400, 0x55d20b2a +0, 282, 282, 1, 518400, 0xca1af9b1 +0, 286, 286, 1, 518400, 0x7e7b7473 +0, 290, 290, 1, 518400, 0xed30dd23 +0, 294, 294, 1, 518400, 0xb694c58f +0, 298, 298, 1, 518400, 0x8270deb7 +0, 302, 302, 1, 518400, 0x91b3b4f7 +0, 306, 306, 1, 518400, 0x37fcb63c +0, 310, 310, 1, 518400, 0x7ebcafca +0, 314, 314, 1, 518400, 0x8508b6da +0, 318, 318, 1, 518400, 0xe7e0b15e +0, 322, 322, 1, 518400, 0x9618fa0e +0, 326, 326, 1, 518400, 0xd4c3b20c +0, 330, 330, 1, 518400, 0x1aad03d1 +0, 334, 334, 1, 518400, 0xb5c18e20 +0, 338, 338, 1, 518400, 0x70144034 +0, 342, 342, 1, 518400, 0x937ee203 +0, 346, 346, 1, 518400, 0x680d72ad +0, 350, 350, 1, 518400, 0x8c9647b1 +0, 354, 354, 1, 518400, 0x65fce70a +0, 358, 358, 1, 518400, 0xa3d785dd +0, 362, 362, 1, 518400, 0xaf1a54c2 +0, 366, 366, 1, 518400, 0x301c6f4c +0, 370, 370, 1, 518400, 0x0255b5ac +0, 374, 374, 1, 518400, 0x967da8de +0, 378, 378, 1, 518400, 0x1f7e6c8c +0, 382, 382, 1, 518400, 0xb41badbf +0, 386, 386, 1, 518400, 0xca853613 +0, 390, 390, 1, 518400, 0x9f8696cb +0, 394, 394, 1, 518400, 0x55ec8427 +0, 398, 398, 1, 518400, 0x08779f91 +0, 402, 402, 1, 518400, 0x171fbc34 +0, 406, 406, 1, 518400, 0x5e9c6ddd +0, 410, 410, 1, 518400, 0xd9a55786 +0, 414, 414, 1, 518400, 0xdb509948 +0, 418, 418, 1, 518400, 0x2a326178 +0, 422, 422, 1, 518400, 0x4842c411 +0, 426, 426, 1, 518400, 0x35399db4 +0, 430, 430, 1, 518400, 0xa182b9aa +0, 434, 434, 1, 518400, 0xb6df772d +0, 438, 438, 1, 518400, 0xfe61b651 +0, 442, 442, 1, 518400, 0x031cb305 +0, 446, 446, 1, 518400, 0xde553506 +0, 450, 450, 1, 518400, 0x24ab8557 +0, 454, 454, 1, 518400, 0xadf5e251 +0, 458, 458, 1, 518400, 0xb3a3c6c5 +0, 462, 462, 1, 518400, 0x9cedc6ac +0, 466, 466, 1, 518400, 0x6ddf9b26 +0, 470, 470, 1, 518400, 0x3bfaf200 +0, 474, 474, 1, 518400, 0x0337d6f1 +0, 478, 478, 1, 518400, 0x71367bc7 +0, 482, 482, 1, 518400, 0x9e1876b8 +0, 486, 486, 1, 518400, 0x37b89366 +0, 490, 490, 1, 518400, 0x6e349056 +0, 494, 494, 1, 518400, 0x718a9543 +0, 498, 498, 1, 518400, 0x48e46e57 +0, 502, 502, 1, 518400, 0xb2ae494c +0, 506, 506, 1, 518400, 0x0ec937dc +0, 510, 510, 1, 518400, 0xb1e88149 +0, 514, 514, 1, 518400, 0xedbba51d +0, 518, 518, 1, 518400, 0x8955d114 +0, 522, 522, 1, 518400, 0x951e8716 +0, 526, 526, 1, 518400, 0x119064de +0, 530, 530, 1, 518400, 0xc06bd99a +0, 534, 534, 1, 518400, 0xdfccd738 +0, 538, 538, 1, 518400, 0x6c2de0a5 +0, 542, 542, 1, 518400, 0x11c1fdf7 +0, 546, 546, 1, 518400, 0xdcd26a62 +0, 550, 550, 1, 518400, 0x0ff63f3d +0, 554, 554, 1, 518400, 0x6443382a +0, 558, 558, 1, 518400, 0x28ce5ce3 +0, 562, 562, 1, 518400, 0xe0d47fbd +0, 566, 566, 1, 518400, 0xfdc0beed +0, 570, 570, 1, 518400, 0x9adeddc4 +0, 574, 574, 1, 518400, 0x8e5669fc +0, 578, 578, 1, 518400, 0xf0beb8ae +0, 582, 582, 1, 518400, 0xbdd68806 +0, 586, 586, 1, 518400, 0xe3c6ae23 +0, 590, 590, 1, 518400, 0xeba952c1 +0, 594, 594, 1, 518400, 0x734ff153 0, 598, 598, 1, 518400, 0xc3c0f1cf 0, 603, 603, 1, 518400, 0x21a5df80 0, 607, 607, 1, 518400, 0x5b8e115b diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-bsf-mp4toannexb ffmpeg-4.4/tests/ref/fate/h264-bsf-mp4toannexb --- ffmpeg-4.2.2/tests/ref/fate/h264-bsf-mp4toannexb 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-bsf-mp4toannexb 2020-07-11 10:39:30.000000000 +0000 @@ -1 +1 @@ -f340e7ca9a46d437af4e96f6c8de221c +5f04c27cc6ee8625fe2405fb0f7da9a3 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cabac_mot_fld0_full ffmpeg-4.4/tests/ref/fate/h264-conformance-cabac_mot_fld0_full --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cabac_mot_fld0_full 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cabac_mot_fld0_full 2021-04-08 21:28:40.000000000 +0000 @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0xbf168f4e -0, 1, 1, 1, 518400, 0xeda5e54f -0, 2, 2, 1, 518400, 0xef496d43 -0, 3, 3, 1, 518400, 0x6b68dad5 -0, 4, 4, 1, 518400, 0x9a40a7de -0, 5, 5, 1, 518400, 0x0c21c018 -0, 6, 6, 1, 518400, 0x4ac5a846 -0, 7, 7, 1, 518400, 0x3a1aa817 -0, 8, 8, 1, 518400, 0xcc4eb434 -0, 9, 9, 1, 518400, 0x4368a3c2 -0, 10, 10, 1, 518400, 0xb923682f -0, 11, 11, 1, 518400, 0xd95460a8 -0, 12, 12, 1, 518400, 0x8e8518aa -0, 13, 13, 1, 518400, 0x292a1a80 -0, 14, 14, 1, 518400, 0xbada388e -0, 15, 15, 1, 518400, 0xa67f63c9 -0, 16, 16, 1, 518400, 0x9fc77e21 -0, 17, 17, 1, 518400, 0xe99dc2ac -0, 18, 18, 1, 518400, 0x17d7d080 -0, 19, 19, 1, 518400, 0x41760c0b -0, 20, 20, 1, 518400, 0x3c70f34d -0, 21, 21, 1, 518400, 0x0d640285 -0, 22, 22, 1, 518400, 0x448893e8 -0, 23, 23, 1, 518400, 0x08194490 -0, 24, 24, 1, 518400, 0xcf227031 -0, 25, 25, 1, 518400, 0x8d94587d -0, 26, 26, 1, 518400, 0x696fca01 -0, 27, 27, 1, 518400, 0xe0ab234b -0, 28, 28, 1, 518400, 0x0620153b -0, 29, 29, 1, 518400, 0xb78c146c +0, 1, 1, 1, 518400, 0xbf168f4e +0, 2, 2, 1, 518400, 0xeda5e54f +0, 3, 3, 1, 518400, 0xef496d43 +0, 4, 4, 1, 518400, 0x6b68dad5 +0, 5, 5, 1, 518400, 0x9a40a7de +0, 6, 6, 1, 518400, 0x0c21c018 +0, 7, 7, 1, 518400, 0x4ac5a846 +0, 8, 8, 1, 518400, 0x3a1aa817 +0, 9, 9, 1, 518400, 0xcc4eb434 +0, 10, 10, 1, 518400, 0x4368a3c2 +0, 11, 11, 1, 518400, 0xb923682f +0, 12, 12, 1, 518400, 0xd95460a8 +0, 13, 13, 1, 518400, 0x8e8518aa +0, 14, 14, 1, 518400, 0x292a1a80 +0, 15, 15, 1, 518400, 0xbada388e +0, 16, 16, 1, 518400, 0xa67f63c9 +0, 17, 17, 1, 518400, 0x9fc77e21 +0, 18, 18, 1, 518400, 0xe99dc2ac +0, 19, 19, 1, 518400, 0x17d7d080 +0, 20, 20, 1, 518400, 0x41760c0b +0, 21, 21, 1, 518400, 0x3c70f34d +0, 22, 22, 1, 518400, 0x0d640285 +0, 23, 23, 1, 518400, 0x448893e8 +0, 24, 24, 1, 518400, 0x08194490 +0, 25, 25, 1, 518400, 0xcf227031 +0, 26, 26, 1, 518400, 0x8d94587d +0, 27, 27, 1, 518400, 0x696fca01 +0, 28, 28, 1, 518400, 0xe0ab234b +0, 29, 29, 1, 518400, 0x0620153b +0, 30, 30, 1, 518400, 0xb78c146c diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cabac_mot_picaff0_full ffmpeg-4.4/tests/ref/fate/h264-conformance-cabac_mot_picaff0_full --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cabac_mot_picaff0_full 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cabac_mot_picaff0_full 2021-04-08 21:28:40.000000000 +0000 @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0xd8b58a23 -0, 1, 1, 1, 518400, 0xe53b4aba -0, 2, 2, 1, 518400, 0x6cbca47a -0, 3, 3, 1, 518400, 0xceb51253 -0, 4, 4, 1, 518400, 0x60cb3cdd -0, 5, 5, 1, 518400, 0x7b633553 -0, 6, 6, 1, 518400, 0x10c012c9 -0, 7, 7, 1, 518400, 0xa340ee20 -0, 8, 8, 1, 518400, 0x574c22c2 -0, 9, 9, 1, 518400, 0xbcdb1bf7 -0, 10, 10, 1, 518400, 0x57811e9a -0, 11, 11, 1, 518400, 0xdd4af748 -0, 12, 12, 1, 518400, 0xb931a637 -0, 13, 13, 1, 518400, 0xcef6ce95 -0, 14, 14, 1, 518400, 0xd28c7085 -0, 15, 15, 1, 518400, 0xae9daf53 -0, 16, 16, 1, 518400, 0xca29d819 -0, 17, 17, 1, 518400, 0x3c4bd7eb -0, 18, 18, 1, 518400, 0x912ee227 -0, 19, 19, 1, 518400, 0xb67d0e27 -0, 20, 20, 1, 518400, 0x8cf7309d -0, 21, 21, 1, 518400, 0x358ad344 -0, 22, 22, 1, 518400, 0x4462c642 -0, 23, 23, 1, 518400, 0x3bb43428 -0, 24, 24, 1, 518400, 0x12d6f8ca -0, 25, 25, 1, 518400, 0x003f13aa -0, 26, 26, 1, 518400, 0x6cd8c432 -0, 27, 27, 1, 518400, 0xee5ff01b -0, 28, 28, 1, 518400, 0xba0616ee -0, 29, 29, 1, 518400, 0x37fa7891 +0, 1, 1, 1, 518400, 0xd8b58a23 +0, 2, 2, 1, 518400, 0xe53b4aba +0, 3, 3, 1, 518400, 0x6cbca47a +0, 4, 4, 1, 518400, 0xceb51253 +0, 5, 5, 1, 518400, 0x60cb3cdd +0, 6, 6, 1, 518400, 0x7b633553 +0, 7, 7, 1, 518400, 0x10c012c9 +0, 8, 8, 1, 518400, 0xa340ee20 +0, 9, 9, 1, 518400, 0x574c22c2 +0, 10, 10, 1, 518400, 0xbcdb1bf7 +0, 11, 11, 1, 518400, 0x57811e9a +0, 12, 12, 1, 518400, 0xdd4af748 +0, 13, 13, 1, 518400, 0xb931a637 +0, 14, 14, 1, 518400, 0xcef6ce95 +0, 15, 15, 1, 518400, 0xd28c7085 +0, 16, 16, 1, 518400, 0xae9daf53 +0, 17, 17, 1, 518400, 0xca29d819 +0, 18, 18, 1, 518400, 0x3c4bd7eb +0, 19, 19, 1, 518400, 0x912ee227 +0, 20, 20, 1, 518400, 0xb67d0e27 +0, 21, 21, 1, 518400, 0x8cf7309d +0, 22, 22, 1, 518400, 0x358ad344 +0, 23, 23, 1, 518400, 0x4462c642 +0, 24, 24, 1, 518400, 0x3bb43428 +0, 25, 25, 1, 518400, 0x12d6f8ca +0, 26, 26, 1, 518400, 0x003f13aa +0, 27, 27, 1, 518400, 0x6cd8c432 +0, 28, 28, 1, 518400, 0xee5ff01b +0, 29, 29, 1, 518400, 0xba0616ee +0, 30, 30, 1, 518400, 0x37fa7891 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cabref3_sand_d ffmpeg-4.4/tests/ref/fate/h264-conformance-cabref3_sand_d --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cabref3_sand_d 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cabref3_sand_d 2021-04-08 21:28:40.000000000 +0000 @@ -3,53 +3,53 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x2061bbd0 -0, 1, 1, 1, 152064, 0x41adb750 -0, 2, 2, 1, 152064, 0x6e889e90 -0, 3, 3, 1, 152064, 0xbb5e60f5 -0, 4, 4, 1, 152064, 0x5a32eca7 -0, 5, 5, 1, 152064, 0x5cb05e88 -0, 6, 6, 1, 152064, 0x2fff3e6c -0, 7, 7, 1, 152064, 0xd917c85e -0, 8, 8, 1, 152064, 0x6eac446f -0, 9, 9, 1, 152064, 0x238b24b0 -0, 10, 10, 1, 152064, 0x3f3bd44c -0, 11, 11, 1, 152064, 0x73982bc5 -0, 12, 12, 1, 152064, 0xf6188a82 -0, 13, 13, 1, 152064, 0x818c5b41 -0, 14, 14, 1, 152064, 0x000d1012 -0, 15, 15, 1, 152064, 0xc4a8750e -0, 16, 16, 1, 152064, 0x1689bb77 -0, 17, 17, 1, 152064, 0x8f52f338 -0, 18, 18, 1, 152064, 0xbf5ee06b -0, 19, 19, 1, 152064, 0x89508ad7 -0, 20, 20, 1, 152064, 0x2b1986a6 -0, 21, 21, 1, 152064, 0xe6fd6b0e -0, 22, 22, 1, 152064, 0x883e2e4e -0, 23, 23, 1, 152064, 0xd133db07 -0, 24, 24, 1, 152064, 0x39b3bb22 -0, 25, 25, 1, 152064, 0x8447410a -0, 26, 26, 1, 152064, 0x9c66c6e5 -0, 27, 27, 1, 152064, 0x514de9cc -0, 28, 28, 1, 152064, 0x08d9f1da -0, 29, 29, 1, 152064, 0x8f10f536 -0, 30, 30, 1, 152064, 0x57d4b27b -0, 31, 31, 1, 152064, 0x46f56d3c -0, 32, 32, 1, 152064, 0x5d260230 -0, 33, 33, 1, 152064, 0x4a72aeac -0, 34, 34, 1, 152064, 0x5cfe187f -0, 35, 35, 1, 152064, 0x08e55cb2 -0, 36, 36, 1, 152064, 0x4727f34f -0, 37, 37, 1, 152064, 0xd6a26f1c -0, 38, 38, 1, 152064, 0xcc1fcf9c -0, 39, 39, 1, 152064, 0x3681b775 -0, 40, 40, 1, 152064, 0xf580c7d9 -0, 41, 41, 1, 152064, 0xaa6747fb -0, 42, 42, 1, 152064, 0x2e22f9f9 -0, 43, 43, 1, 152064, 0xb3ee6d81 -0, 44, 44, 1, 152064, 0x930b0145 -0, 45, 45, 1, 152064, 0xae36af99 -0, 46, 46, 1, 152064, 0xeb58fd26 -0, 47, 47, 1, 152064, 0xb9004da3 -0, 48, 48, 1, 152064, 0x2b25e444 -0, 49, 49, 1, 152064, 0xb36927de +0, 1, 1, 1, 152064, 0x2061bbd0 +0, 2, 2, 1, 152064, 0x41adb750 +0, 3, 3, 1, 152064, 0x6e889e90 +0, 4, 4, 1, 152064, 0xbb5e60f5 +0, 5, 5, 1, 152064, 0x5a32eca7 +0, 6, 6, 1, 152064, 0x5cb05e88 +0, 7, 7, 1, 152064, 0x2fff3e6c +0, 8, 8, 1, 152064, 0xd917c85e +0, 9, 9, 1, 152064, 0x6eac446f +0, 10, 10, 1, 152064, 0x238b24b0 +0, 11, 11, 1, 152064, 0x3f3bd44c +0, 12, 12, 1, 152064, 0x73982bc5 +0, 13, 13, 1, 152064, 0xf6188a82 +0, 14, 14, 1, 152064, 0x818c5b41 +0, 15, 15, 1, 152064, 0x000d1012 +0, 16, 16, 1, 152064, 0xc4a8750e +0, 17, 17, 1, 152064, 0x1689bb77 +0, 18, 18, 1, 152064, 0x8f52f338 +0, 19, 19, 1, 152064, 0xbf5ee06b +0, 20, 20, 1, 152064, 0x89508ad7 +0, 21, 21, 1, 152064, 0x2b1986a6 +0, 22, 22, 1, 152064, 0xe6fd6b0e +0, 23, 23, 1, 152064, 0x883e2e4e +0, 24, 24, 1, 152064, 0xd133db07 +0, 25, 25, 1, 152064, 0x39b3bb22 +0, 26, 26, 1, 152064, 0x8447410a +0, 27, 27, 1, 152064, 0x9c66c6e5 +0, 28, 28, 1, 152064, 0x514de9cc +0, 29, 29, 1, 152064, 0x08d9f1da +0, 30, 30, 1, 152064, 0x8f10f536 +0, 31, 31, 1, 152064, 0x57d4b27b +0, 32, 32, 1, 152064, 0x46f56d3c +0, 33, 33, 1, 152064, 0x5d260230 +0, 34, 34, 1, 152064, 0x4a72aeac +0, 35, 35, 1, 152064, 0x5cfe187f +0, 36, 36, 1, 152064, 0x08e55cb2 +0, 37, 37, 1, 152064, 0x4727f34f +0, 38, 38, 1, 152064, 0xd6a26f1c +0, 39, 39, 1, 152064, 0xcc1fcf9c +0, 40, 40, 1, 152064, 0x3681b775 +0, 41, 41, 1, 152064, 0xf580c7d9 +0, 42, 42, 1, 152064, 0xaa6747fb +0, 43, 43, 1, 152064, 0x2e22f9f9 +0, 44, 44, 1, 152064, 0xb3ee6d81 +0, 45, 45, 1, 152064, 0x930b0145 +0, 46, 46, 1, 152064, 0xae36af99 +0, 47, 47, 1, 152064, 0xeb58fd26 +0, 48, 48, 1, 152064, 0xb9004da3 +0, 49, 49, 1, 152064, 0x2b25e444 +0, 50, 50, 1, 152064, 0xb36927de diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cafi1_sva_c ffmpeg-4.4/tests/ref/fate/h264-conformance-cafi1_sva_c --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cafi1_sva_c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cafi1_sva_c 2021-04-08 21:28:40.000000000 +0000 @@ -3,36 +3,36 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0x47bd73fa -0, 1, 1, 1, 518400, 0xfe3ea7cc -0, 2, 2, 1, 518400, 0x9bc549ae -0, 3, 3, 1, 518400, 0x7bb7f0a1 -0, 4, 4, 1, 518400, 0x328903d4 -0, 5, 5, 1, 518400, 0x96ab366b -0, 6, 6, 1, 518400, 0xa923eed3 -0, 7, 7, 1, 518400, 0x162b08f6 -0, 8, 8, 1, 518400, 0xe711bd8b -0, 9, 9, 1, 518400, 0x55e2d4ed -0, 10, 10, 1, 518400, 0x7dd3107b -0, 11, 11, 1, 518400, 0x0ed20bcf -0, 12, 12, 1, 518400, 0x352f5743 -0, 13, 13, 1, 518400, 0x0a3aeb5e -0, 14, 14, 1, 518400, 0xc458eda3 -0, 15, 15, 1, 518400, 0xe8d5fec5 -0, 16, 16, 1, 518400, 0x18fc6c37 -0, 17, 17, 1, 518400, 0x448add76 -0, 18, 18, 1, 518400, 0x8741ead7 -0, 19, 19, 1, 518400, 0x7008a751 -0, 20, 20, 1, 518400, 0x4ca0633d -0, 21, 21, 1, 518400, 0x021ab800 -0, 22, 22, 1, 518400, 0xfb91ba57 -0, 23, 23, 1, 518400, 0x90e71dd0 -0, 24, 24, 1, 518400, 0xac859de5 -0, 25, 25, 1, 518400, 0xce9790bd -0, 26, 26, 1, 518400, 0x010ade8b -0, 27, 27, 1, 518400, 0xd0b3a399 -0, 28, 28, 1, 518400, 0x6cafcff3 -0, 29, 29, 1, 518400, 0xc32284c0 -0, 30, 30, 1, 518400, 0x1af8f73e -0, 31, 31, 1, 518400, 0x3babd71e -0, 32, 32, 1, 518400, 0xd77cb86b +0, 1, 1, 1, 518400, 0x47bd73fa +0, 2, 2, 1, 518400, 0xfe3ea7cc +0, 3, 3, 1, 518400, 0x9bc549ae +0, 4, 4, 1, 518400, 0x7bb7f0a1 +0, 5, 5, 1, 518400, 0x328903d4 +0, 6, 6, 1, 518400, 0x96ab366b +0, 7, 7, 1, 518400, 0xa923eed3 +0, 8, 8, 1, 518400, 0x162b08f6 +0, 9, 9, 1, 518400, 0xe711bd8b +0, 10, 10, 1, 518400, 0x55e2d4ed +0, 11, 11, 1, 518400, 0x7dd3107b +0, 12, 12, 1, 518400, 0x0ed20bcf +0, 13, 13, 1, 518400, 0x352f5743 +0, 14, 14, 1, 518400, 0x0a3aeb5e +0, 15, 15, 1, 518400, 0xc458eda3 +0, 16, 16, 1, 518400, 0xe8d5fec5 +0, 17, 17, 1, 518400, 0x18fc6c37 +0, 18, 18, 1, 518400, 0x448add76 +0, 19, 19, 1, 518400, 0x8741ead7 +0, 20, 20, 1, 518400, 0x7008a751 +0, 21, 21, 1, 518400, 0x4ca0633d +0, 22, 22, 1, 518400, 0x021ab800 +0, 23, 23, 1, 518400, 0xfb91ba57 +0, 24, 24, 1, 518400, 0x90e71dd0 +0, 25, 25, 1, 518400, 0xac859de5 +0, 26, 26, 1, 518400, 0xce9790bd +0, 27, 27, 1, 518400, 0x010ade8b +0, 28, 28, 1, 518400, 0xd0b3a399 +0, 29, 29, 1, 518400, 0x6cafcff3 +0, 30, 30, 1, 518400, 0xc32284c0 +0, 31, 31, 1, 518400, 0x1af8f73e +0, 32, 32, 1, 518400, 0x3babd71e +0, 33, 33, 1, 518400, 0xd77cb86b diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-capa1_toshiba_b ffmpeg-4.4/tests/ref/fate/h264-conformance-capa1_toshiba_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-capa1_toshiba_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-capa1_toshiba_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,93 +3,93 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x4040d2fc -0, 1, 1, 1, 152064, 0x0d8f9897 -0, 2, 2, 1, 152064, 0xc23321cd -0, 3, 3, 1, 152064, 0x3c9225eb -0, 4, 4, 1, 152064, 0x8927006f -0, 5, 5, 1, 152064, 0xf706a302 -0, 6, 6, 1, 152064, 0x8219c106 -0, 7, 7, 1, 152064, 0x06c990ea -0, 8, 8, 1, 152064, 0x3a0f1135 -0, 9, 9, 1, 152064, 0x4cff21d3 -0, 10, 10, 1, 152064, 0x6be0e050 -0, 11, 11, 1, 152064, 0x718b6c7b -0, 12, 12, 1, 152064, 0x24b38713 -0, 13, 13, 1, 152064, 0x500553fb -0, 14, 14, 1, 152064, 0x531ae610 -0, 15, 15, 1, 152064, 0x46f4ff1b -0, 16, 16, 1, 152064, 0xe5abe5ff -0, 17, 17, 1, 152064, 0x97daa351 -0, 18, 18, 1, 152064, 0xfbef0a8f -0, 19, 19, 1, 152064, 0xbe76134f -0, 20, 20, 1, 152064, 0xa4bf10ea -0, 21, 21, 1, 152064, 0xb2fb32af -0, 22, 22, 1, 152064, 0xd33027a5 -0, 23, 23, 1, 152064, 0x78e20c2b -0, 24, 24, 1, 152064, 0xefda2d6f -0, 25, 25, 1, 152064, 0xb99126f0 -0, 26, 26, 1, 152064, 0x89d7e465 -0, 27, 27, 1, 152064, 0x6150ff97 -0, 28, 28, 1, 152064, 0xde03d937 -0, 29, 29, 1, 152064, 0xd90ca874 -0, 30, 30, 1, 152064, 0xb120b294 -0, 31, 31, 1, 152064, 0x644eade4 -0, 32, 32, 1, 152064, 0xd1bb004f -0, 33, 33, 1, 152064, 0x99806a8b -0, 34, 34, 1, 152064, 0x8c6b635f -0, 35, 35, 1, 152064, 0xa269fa8b -0, 36, 36, 1, 152064, 0xc11c0e64 -0, 37, 37, 1, 152064, 0xac13f5eb -0, 38, 38, 1, 152064, 0x895799cf -0, 39, 39, 1, 152064, 0x95a9bea1 -0, 40, 40, 1, 152064, 0xe998dfba -0, 41, 41, 1, 152064, 0xc72d8460 -0, 42, 42, 1, 152064, 0xd1cb9b9a -0, 43, 43, 1, 152064, 0xb49aadd3 -0, 44, 44, 1, 152064, 0x8bc38547 -0, 45, 45, 1, 152064, 0x3485984b -0, 46, 46, 1, 152064, 0xdf305c0a -0, 47, 47, 1, 152064, 0x6a1ec990 -0, 48, 48, 1, 152064, 0x595e0de4 -0, 49, 49, 1, 152064, 0xe1baf7c4 -0, 50, 50, 1, 152064, 0xf08b9b47 -0, 51, 51, 1, 152064, 0x6532ba6f -0, 52, 52, 1, 152064, 0x3de67da6 -0, 53, 53, 1, 152064, 0x439ffd04 -0, 54, 54, 1, 152064, 0x6e6c1e97 -0, 55, 55, 1, 152064, 0x8e5aee7a -0, 56, 56, 1, 152064, 0xd634999a -0, 57, 57, 1, 152064, 0xadfa9e8b -0, 58, 58, 1, 152064, 0x1b9090f5 -0, 59, 59, 1, 152064, 0x29094dfc -0, 60, 60, 1, 152064, 0x56748851 -0, 61, 61, 1, 152064, 0x2316719d -0, 62, 62, 1, 152064, 0x2ee0060b -0, 63, 63, 1, 152064, 0x3edb36d4 -0, 64, 64, 1, 152064, 0x9ef437a3 -0, 65, 65, 1, 152064, 0x8d9af72e -0, 66, 66, 1, 152064, 0xab86389c -0, 67, 67, 1, 152064, 0xd3b34576 -0, 68, 68, 1, 152064, 0x9e5b04f4 -0, 69, 69, 1, 152064, 0x6a164c17 -0, 70, 70, 1, 152064, 0xcecf20ab -0, 71, 71, 1, 152064, 0x07c8e273 -0, 72, 72, 1, 152064, 0x9b46fe6a -0, 73, 73, 1, 152064, 0xc1e8002b -0, 74, 74, 1, 152064, 0xdebdbe53 -0, 75, 75, 1, 152064, 0x0d2dfd99 -0, 76, 76, 1, 152064, 0xe8ae925f -0, 77, 77, 1, 152064, 0xe1fe6272 -0, 78, 78, 1, 152064, 0xbb74d5e6 -0, 79, 79, 1, 152064, 0xc7b5d949 -0, 80, 80, 1, 152064, 0x9b15b020 -0, 81, 81, 1, 152064, 0xc8201f44 -0, 82, 82, 1, 152064, 0x30d03303 -0, 83, 83, 1, 152064, 0x9f66fbc2 -0, 84, 84, 1, 152064, 0x482b71ec -0, 85, 85, 1, 152064, 0x1c9e50bf -0, 86, 86, 1, 152064, 0x89f247e4 -0, 87, 87, 1, 152064, 0xaa5f9141 -0, 88, 88, 1, 152064, 0xb816aa8c -0, 89, 89, 1, 152064, 0x3112a619 +0, 1, 1, 1, 152064, 0x4040d2fc +0, 2, 2, 1, 152064, 0x0d8f9897 +0, 3, 3, 1, 152064, 0xc23321cd +0, 4, 4, 1, 152064, 0x3c9225eb +0, 5, 5, 1, 152064, 0x8927006f +0, 6, 6, 1, 152064, 0xf706a302 +0, 7, 7, 1, 152064, 0x8219c106 +0, 8, 8, 1, 152064, 0x06c990ea +0, 9, 9, 1, 152064, 0x3a0f1135 +0, 10, 10, 1, 152064, 0x4cff21d3 +0, 11, 11, 1, 152064, 0x6be0e050 +0, 12, 12, 1, 152064, 0x718b6c7b +0, 13, 13, 1, 152064, 0x24b38713 +0, 14, 14, 1, 152064, 0x500553fb +0, 15, 15, 1, 152064, 0x531ae610 +0, 16, 16, 1, 152064, 0x46f4ff1b +0, 17, 17, 1, 152064, 0xe5abe5ff +0, 18, 18, 1, 152064, 0x97daa351 +0, 19, 19, 1, 152064, 0xfbef0a8f +0, 20, 20, 1, 152064, 0xbe76134f +0, 21, 21, 1, 152064, 0xa4bf10ea +0, 22, 22, 1, 152064, 0xb2fb32af +0, 23, 23, 1, 152064, 0xd33027a5 +0, 24, 24, 1, 152064, 0x78e20c2b +0, 25, 25, 1, 152064, 0xefda2d6f +0, 26, 26, 1, 152064, 0xb99126f0 +0, 27, 27, 1, 152064, 0x89d7e465 +0, 28, 28, 1, 152064, 0x6150ff97 +0, 29, 29, 1, 152064, 0xde03d937 +0, 30, 30, 1, 152064, 0xd90ca874 +0, 31, 31, 1, 152064, 0xb120b294 +0, 32, 32, 1, 152064, 0x644eade4 +0, 33, 33, 1, 152064, 0xd1bb004f +0, 34, 34, 1, 152064, 0x99806a8b +0, 35, 35, 1, 152064, 0x8c6b635f +0, 36, 36, 1, 152064, 0xa269fa8b +0, 37, 37, 1, 152064, 0xc11c0e64 +0, 38, 38, 1, 152064, 0xac13f5eb +0, 39, 39, 1, 152064, 0x895799cf +0, 40, 40, 1, 152064, 0x95a9bea1 +0, 41, 41, 1, 152064, 0xe998dfba +0, 42, 42, 1, 152064, 0xc72d8460 +0, 43, 43, 1, 152064, 0xd1cb9b9a +0, 44, 44, 1, 152064, 0xb49aadd3 +0, 45, 45, 1, 152064, 0x8bc38547 +0, 46, 46, 1, 152064, 0x3485984b +0, 47, 47, 1, 152064, 0xdf305c0a +0, 48, 48, 1, 152064, 0x6a1ec990 +0, 49, 49, 1, 152064, 0x595e0de4 +0, 50, 50, 1, 152064, 0xe1baf7c4 +0, 51, 51, 1, 152064, 0xf08b9b47 +0, 52, 52, 1, 152064, 0x6532ba6f +0, 53, 53, 1, 152064, 0x3de67da6 +0, 54, 54, 1, 152064, 0x439ffd04 +0, 55, 55, 1, 152064, 0x6e6c1e97 +0, 56, 56, 1, 152064, 0x8e5aee7a +0, 57, 57, 1, 152064, 0xd634999a +0, 58, 58, 1, 152064, 0xadfa9e8b +0, 59, 59, 1, 152064, 0x1b9090f5 +0, 60, 60, 1, 152064, 0x29094dfc +0, 61, 61, 1, 152064, 0x56748851 +0, 62, 62, 1, 152064, 0x2316719d +0, 63, 63, 1, 152064, 0x2ee0060b +0, 64, 64, 1, 152064, 0x3edb36d4 +0, 65, 65, 1, 152064, 0x9ef437a3 +0, 66, 66, 1, 152064, 0x8d9af72e +0, 67, 67, 1, 152064, 0xab86389c +0, 68, 68, 1, 152064, 0xd3b34576 +0, 69, 69, 1, 152064, 0x9e5b04f4 +0, 70, 70, 1, 152064, 0x6a164c17 +0, 71, 71, 1, 152064, 0xcecf20ab +0, 72, 72, 1, 152064, 0x07c8e273 +0, 73, 73, 1, 152064, 0x9b46fe6a +0, 74, 74, 1, 152064, 0xc1e8002b +0, 75, 75, 1, 152064, 0xdebdbe53 +0, 76, 76, 1, 152064, 0x0d2dfd99 +0, 77, 77, 1, 152064, 0xe8ae925f +0, 78, 78, 1, 152064, 0xe1fe6272 +0, 79, 79, 1, 152064, 0xbb74d5e6 +0, 80, 80, 1, 152064, 0xc7b5d949 +0, 81, 81, 1, 152064, 0x9b15b020 +0, 82, 82, 1, 152064, 0xc8201f44 +0, 83, 83, 1, 152064, 0x30d03303 +0, 84, 84, 1, 152064, 0x9f66fbc2 +0, 85, 85, 1, 152064, 0x482b71ec +0, 86, 86, 1, 152064, 0x1c9e50bf +0, 87, 87, 1, 152064, 0x89f247e4 +0, 88, 88, 1, 152064, 0xaa5f9141 +0, 89, 89, 1, 152064, 0xb816aa8c +0, 90, 90, 1, 152064, 0x3112a619 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-capama3_sand_f ffmpeg-4.4/tests/ref/fate/h264-conformance-capama3_sand_f --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-capama3_sand_f 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-capama3_sand_f 2021-04-08 21:28:40.000000000 +0000 @@ -3,53 +3,53 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0xf772f152 -0, 1, 1, 1, 152064, 0xc416d300 -0, 2, 2, 1, 152064, 0xc2275c94 -0, 3, 3, 1, 152064, 0x1bd35645 -0, 4, 4, 1, 152064, 0x60327bf5 -0, 5, 5, 1, 152064, 0x7f5541bd -0, 6, 6, 1, 152064, 0x52e5ebad -0, 7, 7, 1, 152064, 0xb8e5c1f3 -0, 8, 8, 1, 152064, 0x2b4e3653 -0, 9, 9, 1, 152064, 0x9a8f8499 -0, 10, 10, 1, 152064, 0x32d4e9fb -0, 11, 11, 1, 152064, 0x0bc73d7a -0, 12, 12, 1, 152064, 0xb58a8b87 -0, 13, 13, 1, 152064, 0xddbc5468 -0, 14, 14, 1, 152064, 0xcfa30b64 -0, 15, 15, 1, 152064, 0xad411f36 -0, 16, 16, 1, 152064, 0x2f8c4d9b -0, 17, 17, 1, 152064, 0xc8523359 -0, 18, 18, 1, 152064, 0x86be9861 -0, 19, 19, 1, 152064, 0x7518d731 -0, 20, 20, 1, 152064, 0x425fbfab -0, 21, 21, 1, 152064, 0x4f00250d -0, 22, 22, 1, 152064, 0x12b40617 -0, 23, 23, 1, 152064, 0x65ff925d -0, 24, 24, 1, 152064, 0xc76a94c9 -0, 25, 25, 1, 152064, 0x640170d5 -0, 26, 26, 1, 152064, 0xd338a090 -0, 27, 27, 1, 152064, 0xce715174 -0, 28, 28, 1, 152064, 0x7bded195 -0, 29, 29, 1, 152064, 0x09e7d3b9 -0, 30, 30, 1, 152064, 0x651e1518 -0, 31, 31, 1, 152064, 0x03cadc5f -0, 32, 32, 1, 152064, 0x08906919 -0, 33, 33, 1, 152064, 0x3303ebe0 -0, 34, 34, 1, 152064, 0xa28676c5 -0, 35, 35, 1, 152064, 0x3900ecaf -0, 36, 36, 1, 152064, 0xeb795a05 -0, 37, 37, 1, 152064, 0x870034df -0, 38, 38, 1, 152064, 0x69b0527a -0, 39, 39, 1, 152064, 0xb2b314f9 -0, 40, 40, 1, 152064, 0x1a44ea1a -0, 41, 41, 1, 152064, 0xe6eaec87 -0, 42, 42, 1, 152064, 0xd9ad818e -0, 43, 43, 1, 152064, 0x9c7ff76e -0, 44, 44, 1, 152064, 0x74c45abb -0, 45, 45, 1, 152064, 0x2f4fa5c6 -0, 46, 46, 1, 152064, 0x19620702 -0, 47, 47, 1, 152064, 0xfc9601f3 -0, 48, 48, 1, 152064, 0x33e0d8e7 -0, 49, 49, 1, 152064, 0xdf7f2a80 +0, 1, 1, 1, 152064, 0xf772f152 +0, 2, 2, 1, 152064, 0xc416d300 +0, 3, 3, 1, 152064, 0xc2275c94 +0, 4, 4, 1, 152064, 0x1bd35645 +0, 5, 5, 1, 152064, 0x60327bf5 +0, 6, 6, 1, 152064, 0x7f5541bd +0, 7, 7, 1, 152064, 0x52e5ebad +0, 8, 8, 1, 152064, 0xb8e5c1f3 +0, 9, 9, 1, 152064, 0x2b4e3653 +0, 10, 10, 1, 152064, 0x9a8f8499 +0, 11, 11, 1, 152064, 0x32d4e9fb +0, 12, 12, 1, 152064, 0x0bc73d7a +0, 13, 13, 1, 152064, 0xb58a8b87 +0, 14, 14, 1, 152064, 0xddbc5468 +0, 15, 15, 1, 152064, 0xcfa30b64 +0, 16, 16, 1, 152064, 0xad411f36 +0, 17, 17, 1, 152064, 0x2f8c4d9b +0, 18, 18, 1, 152064, 0xc8523359 +0, 19, 19, 1, 152064, 0x86be9861 +0, 20, 20, 1, 152064, 0x7518d731 +0, 21, 21, 1, 152064, 0x425fbfab +0, 22, 22, 1, 152064, 0x4f00250d +0, 23, 23, 1, 152064, 0x12b40617 +0, 24, 24, 1, 152064, 0x65ff925d +0, 25, 25, 1, 152064, 0xc76a94c9 +0, 26, 26, 1, 152064, 0x640170d5 +0, 27, 27, 1, 152064, 0xd338a090 +0, 28, 28, 1, 152064, 0xce715174 +0, 29, 29, 1, 152064, 0x7bded195 +0, 30, 30, 1, 152064, 0x09e7d3b9 +0, 31, 31, 1, 152064, 0x651e1518 +0, 32, 32, 1, 152064, 0x03cadc5f +0, 33, 33, 1, 152064, 0x08906919 +0, 34, 34, 1, 152064, 0x3303ebe0 +0, 35, 35, 1, 152064, 0xa28676c5 +0, 36, 36, 1, 152064, 0x3900ecaf +0, 37, 37, 1, 152064, 0xeb795a05 +0, 38, 38, 1, 152064, 0x870034df +0, 39, 39, 1, 152064, 0x69b0527a +0, 40, 40, 1, 152064, 0xb2b314f9 +0, 41, 41, 1, 152064, 0x1a44ea1a +0, 42, 42, 1, 152064, 0xe6eaec87 +0, 43, 43, 1, 152064, 0xd9ad818e +0, 44, 44, 1, 152064, 0x9c7ff76e +0, 45, 45, 1, 152064, 0x74c45abb +0, 46, 46, 1, 152064, 0x2f4fa5c6 +0, 47, 47, 1, 152064, 0x19620702 +0, 48, 48, 1, 152064, 0xfc9601f3 +0, 49, 49, 1, 152064, 0x33e0d8e7 +0, 50, 50, 1, 152064, 0xdf7f2a80 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cavlc_mot_fld0_full_b ffmpeg-4.4/tests/ref/fate/h264-conformance-cavlc_mot_fld0_full_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cavlc_mot_fld0_full_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cavlc_mot_fld0_full_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0x99d0df36 -0, 1, 1, 1, 518400, 0xa8601c1a -0, 2, 2, 1, 518400, 0x4a17d235 -0, 3, 3, 1, 518400, 0x75f23abf -0, 4, 4, 1, 518400, 0x746aad53 -0, 5, 5, 1, 518400, 0xb0b8913e -0, 6, 6, 1, 518400, 0x60a27f57 -0, 7, 7, 1, 518400, 0xfa227f3e -0, 8, 8, 1, 518400, 0x7a1e57c2 -0, 9, 9, 1, 518400, 0xcbbaa84f -0, 10, 10, 1, 518400, 0xf9c1bd13 -0, 11, 11, 1, 518400, 0x9e80caaf -0, 12, 12, 1, 518400, 0x14cc6928 -0, 13, 13, 1, 518400, 0xca0353ef -0, 14, 14, 1, 518400, 0xcad65e5f -0, 15, 15, 1, 518400, 0xd5bc47b3 -0, 16, 16, 1, 518400, 0xa9893d36 -0, 17, 17, 1, 518400, 0x69bd9085 -0, 18, 18, 1, 518400, 0xff33c476 -0, 19, 19, 1, 518400, 0x9538adf7 -0, 20, 20, 1, 518400, 0xd4ff3b62 -0, 21, 21, 1, 518400, 0x021a11fd -0, 22, 22, 1, 518400, 0x293e6f9f -0, 23, 23, 1, 518400, 0x5d38e4c3 -0, 24, 24, 1, 518400, 0xd1f4ad49 -0, 25, 25, 1, 518400, 0xf13dd946 -0, 26, 26, 1, 518400, 0x0359e9ff -0, 27, 27, 1, 518400, 0xb61098ad -0, 28, 28, 1, 518400, 0xa855b11c -0, 29, 29, 1, 518400, 0x7fcf9343 +0, 1, 1, 1, 518400, 0x99d0df36 +0, 2, 2, 1, 518400, 0xa8601c1a +0, 3, 3, 1, 518400, 0x4a17d235 +0, 4, 4, 1, 518400, 0x75f23abf +0, 5, 5, 1, 518400, 0x746aad53 +0, 6, 6, 1, 518400, 0xb0b8913e +0, 7, 7, 1, 518400, 0x60a27f57 +0, 8, 8, 1, 518400, 0xfa227f3e +0, 9, 9, 1, 518400, 0x7a1e57c2 +0, 10, 10, 1, 518400, 0xcbbaa84f +0, 11, 11, 1, 518400, 0xf9c1bd13 +0, 12, 12, 1, 518400, 0x9e80caaf +0, 13, 13, 1, 518400, 0x14cc6928 +0, 14, 14, 1, 518400, 0xca0353ef +0, 15, 15, 1, 518400, 0xcad65e5f +0, 16, 16, 1, 518400, 0xd5bc47b3 +0, 17, 17, 1, 518400, 0xa9893d36 +0, 18, 18, 1, 518400, 0x69bd9085 +0, 19, 19, 1, 518400, 0xff33c476 +0, 20, 20, 1, 518400, 0x9538adf7 +0, 21, 21, 1, 518400, 0xd4ff3b62 +0, 22, 22, 1, 518400, 0x021a11fd +0, 23, 23, 1, 518400, 0x293e6f9f +0, 24, 24, 1, 518400, 0x5d38e4c3 +0, 25, 25, 1, 518400, 0xd1f4ad49 +0, 26, 26, 1, 518400, 0xf13dd946 +0, 27, 27, 1, 518400, 0x0359e9ff +0, 28, 28, 1, 518400, 0xb61098ad +0, 29, 29, 1, 518400, 0xa855b11c +0, 30, 30, 1, 518400, 0x7fcf9343 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cavlc_mot_picaff0_full_b ffmpeg-4.4/tests/ref/fate/h264-conformance-cavlc_mot_picaff0_full_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cavlc_mot_picaff0_full_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cavlc_mot_picaff0_full_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0xf6b83a0e -0, 1, 1, 1, 518400, 0xc5e8b8ee -0, 2, 2, 1, 518400, 0xb3bc6e43 -0, 3, 3, 1, 518400, 0x5b08dc73 -0, 4, 4, 1, 518400, 0x4a7f7690 -0, 5, 5, 1, 518400, 0x8a9f4275 -0, 6, 6, 1, 518400, 0xc7cb92fd -0, 7, 7, 1, 518400, 0xc721e231 -0, 8, 8, 1, 518400, 0xfb31371b -0, 9, 9, 1, 518400, 0xac57f5d9 -0, 10, 10, 1, 518400, 0x92b7debc -0, 11, 11, 1, 518400, 0xfe3e533e -0, 12, 12, 1, 518400, 0x1b3a7a72 -0, 13, 13, 1, 518400, 0x98df2d81 -0, 14, 14, 1, 518400, 0xe0ce9c52 -0, 15, 15, 1, 518400, 0x6a31166d -0, 16, 16, 1, 518400, 0x64ffd4d2 -0, 17, 17, 1, 518400, 0x3ec062ef -0, 18, 18, 1, 518400, 0x3480fae1 -0, 19, 19, 1, 518400, 0xa87ae4b7 -0, 20, 20, 1, 518400, 0xd301319f -0, 21, 21, 1, 518400, 0xa9284989 -0, 22, 22, 1, 518400, 0x3de73b50 -0, 23, 23, 1, 518400, 0x30a79f84 -0, 24, 24, 1, 518400, 0x7d5152d4 -0, 25, 25, 1, 518400, 0x25514095 -0, 26, 26, 1, 518400, 0x1749a05f -0, 27, 27, 1, 518400, 0x598139a7 -0, 28, 28, 1, 518400, 0x3cece862 -0, 29, 29, 1, 518400, 0xe1c27efe +0, 1, 1, 1, 518400, 0xf6b83a0e +0, 2, 2, 1, 518400, 0xc5e8b8ee +0, 3, 3, 1, 518400, 0xb3bc6e43 +0, 4, 4, 1, 518400, 0x5b08dc73 +0, 5, 5, 1, 518400, 0x4a7f7690 +0, 6, 6, 1, 518400, 0x8a9f4275 +0, 7, 7, 1, 518400, 0xc7cb92fd +0, 8, 8, 1, 518400, 0xc721e231 +0, 9, 9, 1, 518400, 0xfb31371b +0, 10, 10, 1, 518400, 0xac57f5d9 +0, 11, 11, 1, 518400, 0x92b7debc +0, 12, 12, 1, 518400, 0xfe3e533e +0, 13, 13, 1, 518400, 0x1b3a7a72 +0, 14, 14, 1, 518400, 0x98df2d81 +0, 15, 15, 1, 518400, 0xe0ce9c52 +0, 16, 16, 1, 518400, 0x6a31166d +0, 17, 17, 1, 518400, 0x64ffd4d2 +0, 18, 18, 1, 518400, 0x3ec062ef +0, 19, 19, 1, 518400, 0x3480fae1 +0, 20, 20, 1, 518400, 0xa87ae4b7 +0, 21, 21, 1, 518400, 0xd301319f +0, 22, 22, 1, 518400, 0xa9284989 +0, 23, 23, 1, 518400, 0x3de73b50 +0, 24, 24, 1, 518400, 0x30a79f84 +0, 25, 25, 1, 518400, 0x7d5152d4 +0, 26, 26, 1, 518400, 0x25514095 +0, 27, 27, 1, 518400, 0x1749a05f +0, 28, 28, 1, 518400, 0x598139a7 +0, 29, 29, 1, 518400, 0x3cece862 +0, 30, 30, 1, 518400, 0xe1c27efe diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvfi1_sony_d ffmpeg-4.4/tests/ref/fate/h264-conformance-cvfi1_sony_d --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvfi1_sony_d 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cvfi1_sony_d 2021-04-08 21:28:40.000000000 +0000 @@ -3,20 +3,20 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0xd9444d71 -0, 1, 1, 1, 518400, 0x5d8928cd -0, 2, 2, 1, 518400, 0xea5bc08b -0, 3, 3, 1, 518400, 0xb4465d31 -0, 4, 4, 1, 518400, 0x983b5dbb -0, 5, 5, 1, 518400, 0x54936746 -0, 6, 6, 1, 518400, 0x7ae38b02 -0, 7, 7, 1, 518400, 0xc2a0dd83 -0, 8, 8, 1, 518400, 0x61cac7a6 -0, 9, 9, 1, 518400, 0xb0038443 -0, 10, 10, 1, 518400, 0x16514296 -0, 11, 11, 1, 518400, 0xa68dd470 -0, 12, 12, 1, 518400, 0x2572f868 -0, 13, 13, 1, 518400, 0x770a3239 -0, 14, 14, 1, 518400, 0xdd04f6d2 -0, 15, 15, 1, 518400, 0xa5e5d01e -0, 16, 16, 1, 518400, 0x5fe25c86 +0, 1, 1, 1, 518400, 0xd9444d71 +0, 2, 2, 1, 518400, 0x5d8928cd +0, 3, 3, 1, 518400, 0xea5bc08b +0, 4, 4, 1, 518400, 0xb4465d31 +0, 5, 5, 1, 518400, 0x983b5dbb +0, 6, 6, 1, 518400, 0x54936746 +0, 7, 7, 1, 518400, 0x7ae38b02 +0, 8, 8, 1, 518400, 0xc2a0dd83 +0, 9, 9, 1, 518400, 0x61cac7a6 +0, 10, 10, 1, 518400, 0xb0038443 +0, 11, 11, 1, 518400, 0x16514296 +0, 12, 12, 1, 518400, 0xa68dd470 +0, 13, 13, 1, 518400, 0x2572f868 +0, 14, 14, 1, 518400, 0x770a3239 +0, 15, 15, 1, 518400, 0xdd04f6d2 +0, 16, 16, 1, 518400, 0xa5e5d01e +0, 17, 17, 1, 518400, 0x5fe25c86 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvfi1_sva_c ffmpeg-4.4/tests/ref/fate/h264-conformance-cvfi1_sva_c --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvfi1_sva_c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cvfi1_sva_c 2021-04-08 21:28:40.000000000 +0000 @@ -3,10 +3,10 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0x8f022263 -0, 1, 1, 1, 518400, 0x02692654 -0, 2, 2, 1, 518400, 0x55eff579 -0, 3, 3, 1, 518400, 0x6c1bdf1d -0, 4, 4, 1, 518400, 0xbbedf5e4 -0, 5, 5, 1, 518400, 0xb90d740d -0, 6, 6, 1, 518400, 0x81300adb +0, 1, 1, 1, 518400, 0x8f022263 +0, 2, 2, 1, 518400, 0x02692654 +0, 3, 3, 1, 518400, 0x55eff579 +0, 4, 4, 1, 518400, 0x6c1bdf1d +0, 5, 5, 1, 518400, 0xbbedf5e4 +0, 6, 6, 1, 518400, 0xb90d740d +0, 7, 7, 1, 518400, 0x81300adb diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvfi2_sony_h ffmpeg-4.4/tests/ref/fate/h264-conformance-cvfi2_sony_h --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvfi2_sony_h 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cvfi2_sony_h 2021-04-08 21:28:40.000000000 +0000 @@ -3,20 +3,20 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0xd9444d71 -0, 1, 1, 1, 518400, 0x491faf75 -0, 2, 2, 1, 518400, 0xf8b4d15c -0, 3, 3, 1, 518400, 0x99d9f60c -0, 4, 4, 1, 518400, 0x46c17a6d -0, 5, 5, 1, 518400, 0x30b9447d -0, 6, 6, 1, 518400, 0x135d0c76 -0, 7, 7, 1, 518400, 0x1b831a3c -0, 8, 8, 1, 518400, 0x5910def8 -0, 9, 9, 1, 518400, 0x8db90147 -0, 10, 10, 1, 518400, 0x6a2b79c7 -0, 11, 11, 1, 518400, 0xc8d302e5 -0, 12, 12, 1, 518400, 0x515bb024 -0, 13, 13, 1, 518400, 0xedf7836c -0, 14, 14, 1, 518400, 0x7e247b9d -0, 15, 15, 1, 518400, 0x10c9bb10 -0, 16, 16, 1, 518400, 0xe38e2807 +0, 1, 1, 1, 518400, 0xd9444d71 +0, 2, 2, 1, 518400, 0x491faf75 +0, 3, 3, 1, 518400, 0xf8b4d15c +0, 4, 4, 1, 518400, 0x99d9f60c +0, 5, 5, 1, 518400, 0x46c17a6d +0, 6, 6, 1, 518400, 0x30b9447d +0, 7, 7, 1, 518400, 0x135d0c76 +0, 8, 8, 1, 518400, 0x1b831a3c +0, 9, 9, 1, 518400, 0x5910def8 +0, 10, 10, 1, 518400, 0x8db90147 +0, 11, 11, 1, 518400, 0x6a2b79c7 +0, 12, 12, 1, 518400, 0xc8d302e5 +0, 13, 13, 1, 518400, 0x515bb024 +0, 14, 14, 1, 518400, 0xedf7836c +0, 15, 15, 1, 518400, 0x7e247b9d +0, 16, 16, 1, 518400, 0x10c9bb10 +0, 17, 17, 1, 518400, 0xe38e2807 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvfi2_sva_c ffmpeg-4.4/tests/ref/fate/h264-conformance-cvfi2_sva_c --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvfi2_sva_c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cvfi2_sva_c 2021-04-08 21:28:40.000000000 +0000 @@ -3,16 +3,16 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0x4073cc0b -0, 1, 1, 1, 518400, 0x5f599a48 -0, 2, 2, 1, 518400, 0xc6fe555a -0, 3, 3, 1, 518400, 0xe63ac345 -0, 4, 4, 1, 518400, 0x9b4f0c5c -0, 5, 5, 1, 518400, 0x98aaba2d -0, 6, 6, 1, 518400, 0xd629bd09 -0, 7, 7, 1, 518400, 0xe9796c37 -0, 8, 8, 1, 518400, 0xba54d16e -0, 9, 9, 1, 518400, 0xe396c3eb -0, 10, 10, 1, 518400, 0x63ee4b81 -0, 11, 11, 1, 518400, 0x68ac6986 -0, 12, 12, 1, 518400, 0xe0d53000 +0, 1, 1, 1, 518400, 0x4073cc0b +0, 2, 2, 1, 518400, 0x5f599a48 +0, 3, 3, 1, 518400, 0xc6fe555a +0, 4, 4, 1, 518400, 0xe63ac345 +0, 5, 5, 1, 518400, 0x9b4f0c5c +0, 6, 6, 1, 518400, 0x98aaba2d +0, 7, 7, 1, 518400, 0xd629bd09 +0, 8, 8, 1, 518400, 0xe9796c37 +0, 9, 9, 1, 518400, 0xba54d16e +0, 10, 10, 1, 518400, 0xe396c3eb +0, 11, 11, 1, 518400, 0x63ee4b81 +0, 12, 12, 1, 518400, 0x68ac6986 +0, 13, 13, 1, 518400, 0xe0d53000 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvmapaqp3_sony_e ffmpeg-4.4/tests/ref/fate/h264-conformance-cvmapaqp3_sony_e --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvmapaqp3_sony_e 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cvmapaqp3_sony_e 2021-04-08 21:28:40.000000000 +0000 @@ -4,10 +4,10 @@ #dimensions 0: 720x480 #sar 0: 0/1 0, 0, 0, 1, 518400, 0x80dffda2 -0, 1, 1, 1, 518400, 0x9450183b -0, 2, 2, 1, 518400, 0x85d429a7 -0, 3, 3, 1, 518400, 0xe1f3b686 -0, 4, 4, 1, 518400, 0x2180c761 -0, 5, 5, 1, 518400, 0x30269c7c -0, 6, 6, 1, 518400, 0xe9aa575a -0, 7, 7, 1, 518400, 0x7b815a0a +0, 2, 2, 1, 518400, 0x9450183b +0, 3, 3, 1, 518400, 0x85d429a7 +0, 4, 4, 1, 518400, 0xe1f3b686 +0, 5, 5, 1, 518400, 0x2180c761 +0, 6, 6, 1, 518400, 0x30269c7c +0, 7, 7, 1, 518400, 0xe9aa575a +0, 8, 8, 1, 518400, 0x7b815a0a diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvmp_mot_fld_l30_b ffmpeg-4.4/tests/ref/fate/h264-conformance-cvmp_mot_fld_l30_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvmp_mot_fld_l30_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cvmp_mot_fld_l30_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0xe9c7643e -0, 1, 1, 1, 518400, 0xba7456ec -0, 2, 2, 1, 518400, 0xdeb96749 -0, 3, 3, 1, 518400, 0xa101a986 -0, 4, 4, 1, 518400, 0x3db7baa5 -0, 5, 5, 1, 518400, 0xf3dfcec7 -0, 6, 6, 1, 518400, 0x79b4f537 -0, 7, 7, 1, 518400, 0x9e64fe68 -0, 8, 8, 1, 518400, 0x0e810b53 -0, 9, 9, 1, 518400, 0x20baf3b8 -0, 10, 10, 1, 518400, 0x0a49d341 -0, 11, 11, 1, 518400, 0xa8304ab5 -0, 12, 12, 1, 518400, 0x2600e98f -0, 13, 13, 1, 518400, 0x9253e3e8 -0, 14, 14, 1, 518400, 0xd6e12783 -0, 15, 15, 1, 518400, 0x6894fc79 -0, 16, 16, 1, 518400, 0xfb60d3e3 -0, 17, 17, 1, 518400, 0x523602be -0, 18, 18, 1, 518400, 0x4979f409 -0, 19, 19, 1, 518400, 0x50d4e2ab -0, 20, 20, 1, 518400, 0xa8c2140a -0, 21, 21, 1, 518400, 0x45c0bc15 -0, 22, 22, 1, 518400, 0xaef78cab -0, 23, 23, 1, 518400, 0xec539d02 -0, 24, 24, 1, 518400, 0x602585ea -0, 25, 25, 1, 518400, 0xda263463 -0, 26, 26, 1, 518400, 0xa03d8922 -0, 27, 27, 1, 518400, 0x43ea1c1d -0, 28, 28, 1, 518400, 0xb1e055a6 -0, 29, 29, 1, 518400, 0x6fff9398 +0, 1, 1, 1, 518400, 0xe9c7643e +0, 2, 2, 1, 518400, 0xba7456ec +0, 3, 3, 1, 518400, 0xdeb96749 +0, 4, 4, 1, 518400, 0xa101a986 +0, 5, 5, 1, 518400, 0x3db7baa5 +0, 6, 6, 1, 518400, 0xf3dfcec7 +0, 7, 7, 1, 518400, 0x79b4f537 +0, 8, 8, 1, 518400, 0x9e64fe68 +0, 9, 9, 1, 518400, 0x0e810b53 +0, 10, 10, 1, 518400, 0x20baf3b8 +0, 11, 11, 1, 518400, 0x0a49d341 +0, 12, 12, 1, 518400, 0xa8304ab5 +0, 13, 13, 1, 518400, 0x2600e98f +0, 14, 14, 1, 518400, 0x9253e3e8 +0, 15, 15, 1, 518400, 0xd6e12783 +0, 16, 16, 1, 518400, 0x6894fc79 +0, 17, 17, 1, 518400, 0xfb60d3e3 +0, 18, 18, 1, 518400, 0x523602be +0, 19, 19, 1, 518400, 0x4979f409 +0, 20, 20, 1, 518400, 0x50d4e2ab +0, 21, 21, 1, 518400, 0xa8c2140a +0, 22, 22, 1, 518400, 0x45c0bc15 +0, 23, 23, 1, 518400, 0xaef78cab +0, 24, 24, 1, 518400, 0xec539d02 +0, 25, 25, 1, 518400, 0x602585ea +0, 26, 26, 1, 518400, 0xda263463 +0, 27, 27, 1, 518400, 0xa03d8922 +0, 28, 28, 1, 518400, 0x43ea1c1d +0, 29, 29, 1, 518400, 0xb1e055a6 +0, 30, 30, 1, 518400, 0x6fff9398 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvmp_mot_frm_l31_b ffmpeg-4.4/tests/ref/fate/h264-conformance-cvmp_mot_frm_l31_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvmp_mot_frm_l31_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cvmp_mot_frm_l31_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,33 +3,33 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0x7b2475e3 -0, 1, 1, 1, 518400, 0xda786a87 -0, 2, 2, 1, 518400, 0xb1dd8108 -0, 3, 3, 1, 518400, 0x760ed65d -0, 4, 4, 1, 518400, 0x8632d20c -0, 5, 5, 1, 518400, 0xdd81e625 -0, 6, 6, 1, 518400, 0x853f1c41 -0, 7, 7, 1, 518400, 0x20191585 -0, 8, 8, 1, 518400, 0x0367e357 -0, 9, 9, 1, 518400, 0x60521167 -0, 10, 10, 1, 518400, 0xa887d4cc -0, 11, 11, 1, 518400, 0x9a450f9e -0, 12, 12, 1, 518400, 0xe9620841 -0, 13, 13, 1, 518400, 0xb482fb0e -0, 14, 14, 1, 518400, 0x7b79f670 -0, 15, 15, 1, 518400, 0x9d37f1d1 -0, 16, 16, 1, 518400, 0xe358d323 -0, 17, 17, 1, 518400, 0x62ade59c -0, 18, 18, 1, 518400, 0xdd78da66 -0, 19, 19, 1, 518400, 0xd97b867b -0, 20, 20, 1, 518400, 0x8a90cf8c -0, 21, 21, 1, 518400, 0x9d386610 -0, 22, 22, 1, 518400, 0x2c590f46 -0, 23, 23, 1, 518400, 0x92662861 -0, 24, 24, 1, 518400, 0x6979f563 -0, 25, 25, 1, 518400, 0xdd0fa1b2 -0, 26, 26, 1, 518400, 0xccbf1c1c -0, 27, 27, 1, 518400, 0x7e358112 -0, 28, 28, 1, 518400, 0xb7c0d89d -0, 29, 29, 1, 518400, 0xc6b03973 +0, 1, 1, 1, 518400, 0x7b2475e3 +0, 2, 2, 1, 518400, 0xda786a87 +0, 3, 3, 1, 518400, 0xb1dd8108 +0, 4, 4, 1, 518400, 0x760ed65d +0, 5, 5, 1, 518400, 0x8632d20c +0, 6, 6, 1, 518400, 0xdd81e625 +0, 7, 7, 1, 518400, 0x853f1c41 +0, 8, 8, 1, 518400, 0x20191585 +0, 9, 9, 1, 518400, 0x0367e357 +0, 10, 10, 1, 518400, 0x60521167 +0, 11, 11, 1, 518400, 0xa887d4cc +0, 12, 12, 1, 518400, 0x9a450f9e +0, 13, 13, 1, 518400, 0xe9620841 +0, 14, 14, 1, 518400, 0xb482fb0e +0, 15, 15, 1, 518400, 0x7b79f670 +0, 16, 16, 1, 518400, 0x9d37f1d1 +0, 17, 17, 1, 518400, 0xe358d323 +0, 18, 18, 1, 518400, 0x62ade59c +0, 19, 19, 1, 518400, 0xdd78da66 +0, 20, 20, 1, 518400, 0xd97b867b +0, 21, 21, 1, 518400, 0x8a90cf8c +0, 22, 22, 1, 518400, 0x9d386610 +0, 23, 23, 1, 518400, 0x2c590f46 +0, 24, 24, 1, 518400, 0x92662861 +0, 25, 25, 1, 518400, 0x6979f563 +0, 26, 26, 1, 518400, 0xdd0fa1b2 +0, 27, 27, 1, 518400, 0xccbf1c1c +0, 28, 28, 1, 518400, 0x7e358112 +0, 29, 29, 1, 518400, 0xb7c0d89d +0, 30, 30, 1, 518400, 0xc6b03973 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvnlfi1_sony_c ffmpeg-4.4/tests/ref/fate/h264-conformance-cvnlfi1_sony_c --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvnlfi1_sony_c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cvnlfi1_sony_c 2021-04-08 21:28:40.000000000 +0000 @@ -3,20 +3,20 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0x0fbb4e71 -0, 1, 1, 1, 518400, 0x4b816734 -0, 2, 2, 1, 518400, 0x0c350f19 -0, 3, 3, 1, 518400, 0xda049cb6 -0, 4, 4, 1, 518400, 0x1f3e7bb9 -0, 5, 5, 1, 518400, 0x995cbe66 -0, 6, 6, 1, 518400, 0x07f7e65c -0, 7, 7, 1, 518400, 0xfcb7487f -0, 8, 8, 1, 518400, 0xb080f48a -0, 9, 9, 1, 518400, 0x3ef5b7e4 -0, 10, 10, 1, 518400, 0xa1518e1c -0, 11, 11, 1, 518400, 0xb36f1cc9 -0, 12, 12, 1, 518400, 0x86ea48af -0, 13, 13, 1, 518400, 0xe42373b7 -0, 14, 14, 1, 518400, 0xa8435828 -0, 15, 15, 1, 518400, 0xc942ea0e -0, 16, 16, 1, 518400, 0xcc597514 +0, 1, 1, 1, 518400, 0x0fbb4e71 +0, 2, 2, 1, 518400, 0x4b816734 +0, 3, 3, 1, 518400, 0x0c350f19 +0, 4, 4, 1, 518400, 0xda049cb6 +0, 5, 5, 1, 518400, 0x1f3e7bb9 +0, 6, 6, 1, 518400, 0x995cbe66 +0, 7, 7, 1, 518400, 0x07f7e65c +0, 8, 8, 1, 518400, 0xfcb7487f +0, 9, 9, 1, 518400, 0xb080f48a +0, 10, 10, 1, 518400, 0x3ef5b7e4 +0, 11, 11, 1, 518400, 0xa1518e1c +0, 12, 12, 1, 518400, 0xb36f1cc9 +0, 13, 13, 1, 518400, 0x86ea48af +0, 14, 14, 1, 518400, 0xe42373b7 +0, 15, 15, 1, 518400, 0xa8435828 +0, 16, 16, 1, 518400, 0xc942ea0e +0, 17, 17, 1, 518400, 0xcc597514 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvnlfi2_sony_h ffmpeg-4.4/tests/ref/fate/h264-conformance-cvnlfi2_sony_h --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvnlfi2_sony_h 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cvnlfi2_sony_h 2021-04-08 21:28:40.000000000 +0000 @@ -3,20 +3,20 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0x0fbb4e71 -0, 1, 1, 1, 518400, 0xc46bec04 -0, 2, 2, 1, 518400, 0xc50ffc1d -0, 3, 3, 1, 518400, 0x684b07b7 -0, 4, 4, 1, 518400, 0xde799af0 -0, 5, 5, 1, 518400, 0xed497b27 -0, 6, 6, 1, 518400, 0x3e9d1e3a -0, 7, 7, 1, 518400, 0x154d3c5c -0, 8, 8, 1, 518400, 0x5257e37c -0, 9, 9, 1, 518400, 0x6e15139a -0, 10, 10, 1, 518400, 0x5dc39c59 -0, 11, 11, 1, 518400, 0xe1803100 -0, 12, 12, 1, 518400, 0xb4d4d535 -0, 13, 13, 1, 518400, 0x7a97a25d -0, 14, 14, 1, 518400, 0xf86b8923 -0, 15, 15, 1, 518400, 0x3355be98 -0, 16, 16, 1, 518400, 0x8f555830 +0, 1, 1, 1, 518400, 0x0fbb4e71 +0, 2, 2, 1, 518400, 0xc46bec04 +0, 3, 3, 1, 518400, 0xc50ffc1d +0, 4, 4, 1, 518400, 0x684b07b7 +0, 5, 5, 1, 518400, 0xde799af0 +0, 6, 6, 1, 518400, 0xed497b27 +0, 7, 7, 1, 518400, 0x3e9d1e3a +0, 8, 8, 1, 518400, 0x154d3c5c +0, 9, 9, 1, 518400, 0x5257e37c +0, 10, 10, 1, 518400, 0x6e15139a +0, 11, 11, 1, 518400, 0x5dc39c59 +0, 12, 12, 1, 518400, 0xe1803100 +0, 13, 13, 1, 518400, 0xb4d4d535 +0, 14, 14, 1, 518400, 0x7a97a25d +0, 15, 15, 1, 518400, 0xf86b8923 +0, 16, 16, 1, 518400, 0x3355be98 +0, 17, 17, 1, 518400, 0x8f555830 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvpa1_toshiba_b ffmpeg-4.4/tests/ref/fate/h264-conformance-cvpa1_toshiba_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-cvpa1_toshiba_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-cvpa1_toshiba_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,93 +3,93 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x128cd77a -0, 1, 1, 1, 152064, 0x565b9fc1 -0, 2, 2, 1, 152064, 0xbe322679 -0, 3, 3, 1, 152064, 0x0ea4238f -0, 4, 4, 1, 152064, 0x1e08fb3c -0, 5, 5, 1, 152064, 0x6da3a93c -0, 6, 6, 1, 152064, 0x75e5b181 -0, 7, 7, 1, 152064, 0xa0b39334 -0, 8, 8, 1, 152064, 0xa0d10d6d -0, 9, 9, 1, 152064, 0x33842bcb -0, 10, 10, 1, 152064, 0x9a74e1e4 -0, 11, 11, 1, 152064, 0xc2037244 -0, 12, 12, 1, 152064, 0x364b8ae4 -0, 13, 13, 1, 152064, 0x18c04971 -0, 14, 14, 1, 152064, 0x7234ecb5 -0, 15, 15, 1, 152064, 0x3719f8bc -0, 16, 16, 1, 152064, 0x1285ead1 -0, 17, 17, 1, 152064, 0xd3bfab18 -0, 18, 18, 1, 152064, 0x898111e2 -0, 19, 19, 1, 152064, 0x681c15fc -0, 20, 20, 1, 152064, 0x8e501572 -0, 21, 21, 1, 152064, 0xd7c838be -0, 22, 22, 1, 152064, 0xede424b2 -0, 23, 23, 1, 152064, 0xcfc20240 -0, 24, 24, 1, 152064, 0x13992e86 -0, 25, 25, 1, 152064, 0x56fb251a -0, 26, 26, 1, 152064, 0xee9be320 -0, 27, 27, 1, 152064, 0xea650153 -0, 28, 28, 1, 152064, 0x2cb6dabe -0, 29, 29, 1, 152064, 0xf44fa4b5 -0, 30, 30, 1, 152064, 0xdac2adff -0, 31, 31, 1, 152064, 0x9e15a1dc -0, 32, 32, 1, 152064, 0x28d00970 -0, 33, 33, 1, 152064, 0xe4277347 -0, 34, 34, 1, 152064, 0xebd25ad1 -0, 35, 35, 1, 152064, 0x029402da -0, 36, 36, 1, 152064, 0x1a2311ef -0, 37, 37, 1, 152064, 0xb86bf96a -0, 38, 38, 1, 152064, 0x67d7a5b0 -0, 39, 39, 1, 152064, 0x573abc2d -0, 40, 40, 1, 152064, 0xbe97dec0 -0, 41, 41, 1, 152064, 0x592b91a4 -0, 42, 42, 1, 152064, 0x9adda65e -0, 43, 43, 1, 152064, 0x0354b2cb -0, 44, 44, 1, 152064, 0x91e27ff9 -0, 45, 45, 1, 152064, 0x389f8625 -0, 46, 46, 1, 152064, 0x90175850 -0, 47, 47, 1, 152064, 0x2d36c427 -0, 48, 48, 1, 152064, 0xc0dd14ab -0, 49, 49, 1, 152064, 0xd49bf131 -0, 50, 50, 1, 152064, 0x0d4a9b92 -0, 51, 51, 1, 152064, 0xae9bb2f1 -0, 52, 52, 1, 152064, 0x36847ade -0, 53, 53, 1, 152064, 0x74810382 -0, 54, 54, 1, 152064, 0xc56d1d9f -0, 55, 55, 1, 152064, 0xcfefe3ae -0, 56, 56, 1, 152064, 0xeaa39353 -0, 57, 57, 1, 152064, 0x14289aef -0, 58, 58, 1, 152064, 0x74ba8f3b -0, 59, 59, 1, 152064, 0xdcaa518d -0, 60, 60, 1, 152064, 0x6e4881c2 -0, 61, 61, 1, 152064, 0xa4db767d -0, 62, 62, 1, 152064, 0x239b0b19 -0, 63, 63, 1, 152064, 0x5d054236 -0, 64, 64, 1, 152064, 0x6f392d7c -0, 65, 65, 1, 152064, 0x5c2af146 -0, 66, 66, 1, 152064, 0x26b439af -0, 67, 67, 1, 152064, 0xba7043ab -0, 68, 68, 1, 152064, 0x0816000c -0, 69, 69, 1, 152064, 0x3a713c05 -0, 70, 70, 1, 152064, 0xb3111f6d -0, 71, 71, 1, 152064, 0xdbf8dae2 -0, 72, 72, 1, 152064, 0x09ddf22e -0, 73, 73, 1, 152064, 0x8871fa7e -0, 74, 74, 1, 152064, 0x9f5db7a1 -0, 75, 75, 1, 152064, 0xcc38f225 -0, 76, 76, 1, 152064, 0xa1d18df9 -0, 77, 77, 1, 152064, 0x9b1c5d6a -0, 78, 78, 1, 152064, 0x9f2bc696 -0, 79, 79, 1, 152064, 0xc39bd11a -0, 80, 80, 1, 152064, 0x4ceca7d0 -0, 81, 81, 1, 152064, 0x63a60f1d -0, 82, 82, 1, 152064, 0x4cd31f28 -0, 83, 83, 1, 152064, 0x9c9af5d1 -0, 84, 84, 1, 152064, 0x6def65fc -0, 85, 85, 1, 152064, 0x1011466d -0, 86, 86, 1, 152064, 0xfeca406d -0, 87, 87, 1, 152064, 0xd1ca8a1e -0, 88, 88, 1, 152064, 0x30caa195 -0, 89, 89, 1, 152064, 0x31a09a48 +0, 1, 1, 1, 152064, 0x128cd77a +0, 2, 2, 1, 152064, 0x565b9fc1 +0, 3, 3, 1, 152064, 0xbe322679 +0, 4, 4, 1, 152064, 0x0ea4238f +0, 5, 5, 1, 152064, 0x1e08fb3c +0, 6, 6, 1, 152064, 0x6da3a93c +0, 7, 7, 1, 152064, 0x75e5b181 +0, 8, 8, 1, 152064, 0xa0b39334 +0, 9, 9, 1, 152064, 0xa0d10d6d +0, 10, 10, 1, 152064, 0x33842bcb +0, 11, 11, 1, 152064, 0x9a74e1e4 +0, 12, 12, 1, 152064, 0xc2037244 +0, 13, 13, 1, 152064, 0x364b8ae4 +0, 14, 14, 1, 152064, 0x18c04971 +0, 15, 15, 1, 152064, 0x7234ecb5 +0, 16, 16, 1, 152064, 0x3719f8bc +0, 17, 17, 1, 152064, 0x1285ead1 +0, 18, 18, 1, 152064, 0xd3bfab18 +0, 19, 19, 1, 152064, 0x898111e2 +0, 20, 20, 1, 152064, 0x681c15fc +0, 21, 21, 1, 152064, 0x8e501572 +0, 22, 22, 1, 152064, 0xd7c838be +0, 23, 23, 1, 152064, 0xede424b2 +0, 24, 24, 1, 152064, 0xcfc20240 +0, 25, 25, 1, 152064, 0x13992e86 +0, 26, 26, 1, 152064, 0x56fb251a +0, 27, 27, 1, 152064, 0xee9be320 +0, 28, 28, 1, 152064, 0xea650153 +0, 29, 29, 1, 152064, 0x2cb6dabe +0, 30, 30, 1, 152064, 0xf44fa4b5 +0, 31, 31, 1, 152064, 0xdac2adff +0, 32, 32, 1, 152064, 0x9e15a1dc +0, 33, 33, 1, 152064, 0x28d00970 +0, 34, 34, 1, 152064, 0xe4277347 +0, 35, 35, 1, 152064, 0xebd25ad1 +0, 36, 36, 1, 152064, 0x029402da +0, 37, 37, 1, 152064, 0x1a2311ef +0, 38, 38, 1, 152064, 0xb86bf96a +0, 39, 39, 1, 152064, 0x67d7a5b0 +0, 40, 40, 1, 152064, 0x573abc2d +0, 41, 41, 1, 152064, 0xbe97dec0 +0, 42, 42, 1, 152064, 0x592b91a4 +0, 43, 43, 1, 152064, 0x9adda65e +0, 44, 44, 1, 152064, 0x0354b2cb +0, 45, 45, 1, 152064, 0x91e27ff9 +0, 46, 46, 1, 152064, 0x389f8625 +0, 47, 47, 1, 152064, 0x90175850 +0, 48, 48, 1, 152064, 0x2d36c427 +0, 49, 49, 1, 152064, 0xc0dd14ab +0, 50, 50, 1, 152064, 0xd49bf131 +0, 51, 51, 1, 152064, 0x0d4a9b92 +0, 52, 52, 1, 152064, 0xae9bb2f1 +0, 53, 53, 1, 152064, 0x36847ade +0, 54, 54, 1, 152064, 0x74810382 +0, 55, 55, 1, 152064, 0xc56d1d9f +0, 56, 56, 1, 152064, 0xcfefe3ae +0, 57, 57, 1, 152064, 0xeaa39353 +0, 58, 58, 1, 152064, 0x14289aef +0, 59, 59, 1, 152064, 0x74ba8f3b +0, 60, 60, 1, 152064, 0xdcaa518d +0, 61, 61, 1, 152064, 0x6e4881c2 +0, 62, 62, 1, 152064, 0xa4db767d +0, 63, 63, 1, 152064, 0x239b0b19 +0, 64, 64, 1, 152064, 0x5d054236 +0, 65, 65, 1, 152064, 0x6f392d7c +0, 66, 66, 1, 152064, 0x5c2af146 +0, 67, 67, 1, 152064, 0x26b439af +0, 68, 68, 1, 152064, 0xba7043ab +0, 69, 69, 1, 152064, 0x0816000c +0, 70, 70, 1, 152064, 0x3a713c05 +0, 71, 71, 1, 152064, 0xb3111f6d +0, 72, 72, 1, 152064, 0xdbf8dae2 +0, 73, 73, 1, 152064, 0x09ddf22e +0, 74, 74, 1, 152064, 0x8871fa7e +0, 75, 75, 1, 152064, 0x9f5db7a1 +0, 76, 76, 1, 152064, 0xcc38f225 +0, 77, 77, 1, 152064, 0xa1d18df9 +0, 78, 78, 1, 152064, 0x9b1c5d6a +0, 79, 79, 1, 152064, 0x9f2bc696 +0, 80, 80, 1, 152064, 0xc39bd11a +0, 81, 81, 1, 152064, 0x4ceca7d0 +0, 82, 82, 1, 152064, 0x63a60f1d +0, 83, 83, 1, 152064, 0x4cd31f28 +0, 84, 84, 1, 152064, 0x9c9af5d1 +0, 85, 85, 1, 152064, 0x6def65fc +0, 86, 86, 1, 152064, 0x1011466d +0, 87, 87, 1, 152064, 0xfeca406d +0, 88, 88, 1, 152064, 0xd1ca8a1e +0, 89, 89, 1, 152064, 0x30caa195 +0, 90, 90, 1, 152064, 0x31a09a48 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-fi1_sony_e ffmpeg-4.4/tests/ref/fate/h264-conformance-fi1_sony_e --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-fi1_sony_e 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-fi1_sony_e 2021-04-08 21:28:40.000000000 +0000 @@ -3,20 +3,20 @@ #codec_id 0: rawvideo #dimensions 0: 192x128 #sar 0: 0/1 -0, 0, 0, 1, 36864, 0x3d54d3e3 -0, 1, 1, 1, 36864, 0xa9573ef0 -0, 2, 2, 1, 36864, 0x0ea5f263 -0, 3, 3, 1, 36864, 0x5a849fb9 -0, 4, 4, 1, 36864, 0x7ddb1eff -0, 5, 5, 1, 36864, 0x5e73e3b7 -0, 6, 6, 1, 36864, 0x7d50d329 -0, 7, 7, 1, 36864, 0xf2c2cd27 -0, 8, 8, 1, 36864, 0xdf4f4628 -0, 9, 9, 1, 36864, 0xddd6d5be -0, 10, 10, 1, 36864, 0xb530e1aa -0, 11, 11, 1, 36864, 0xeca42470 -0, 12, 12, 1, 36864, 0xa5701caf -0, 13, 13, 1, 36864, 0x6f5d28fc -0, 14, 14, 1, 36864, 0xd4ab4ab2 -0, 15, 15, 1, 36864, 0xf2dfcc22 -0, 16, 16, 1, 36864, 0xcaa87e79 +0, 1, 1, 1, 36864, 0x3d54d3e3 +0, 2, 2, 1, 36864, 0xa9573ef0 +0, 3, 3, 1, 36864, 0x0ea5f263 +0, 4, 4, 1, 36864, 0x5a849fb9 +0, 5, 5, 1, 36864, 0x7ddb1eff +0, 6, 6, 1, 36864, 0x5e73e3b7 +0, 7, 7, 1, 36864, 0x7d50d329 +0, 8, 8, 1, 36864, 0xf2c2cd27 +0, 9, 9, 1, 36864, 0xdf4f4628 +0, 10, 10, 1, 36864, 0xddd6d5be +0, 11, 11, 1, 36864, 0xb530e1aa +0, 12, 12, 1, 36864, 0xeca42470 +0, 13, 13, 1, 36864, 0xa5701caf +0, 14, 14, 1, 36864, 0x6f5d28fc +0, 15, 15, 1, 36864, 0xd4ab4ab2 +0, 16, 16, 1, 36864, 0xf2dfcc22 +0, 17, 17, 1, 36864, 0xcaa87e79 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-bcrm_freh10 ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-bcrm_freh10 --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-bcrm_freh10 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-bcrm_freh10 2021-04-08 21:28:40.000000000 +0000 @@ -3,103 +3,103 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0xbdc2b880 -0, 1, 1, 1, 152064, 0x4ebf93fe -0, 2, 2, 1, 152064, 0xe30d6871 -0, 3, 3, 1, 152064, 0x04f46b9b -0, 4, 4, 1, 152064, 0xd7dd219a -0, 5, 5, 1, 152064, 0x02fc6511 -0, 6, 6, 1, 152064, 0x98868faa -0, 7, 7, 1, 152064, 0x54b94f92 -0, 8, 8, 1, 152064, 0xe3b6be4b -0, 9, 9, 1, 152064, 0xf148cf10 -0, 10, 10, 1, 152064, 0xda3239b8 -0, 11, 11, 1, 152064, 0x6c5d7331 -0, 12, 12, 1, 152064, 0x825f1fea -0, 13, 13, 1, 152064, 0x47791056 -0, 14, 14, 1, 152064, 0xc08e8a58 -0, 15, 15, 1, 152064, 0x020299f3 -0, 16, 16, 1, 152064, 0x0dfd4457 -0, 17, 17, 1, 152064, 0xcf005e68 -0, 18, 18, 1, 152064, 0x1f9e2c32 -0, 19, 19, 1, 152064, 0xa8359324 -0, 20, 20, 1, 152064, 0x4b03752d -0, 21, 21, 1, 152064, 0xd6281621 -0, 22, 22, 1, 152064, 0xc97ac928 -0, 23, 23, 1, 152064, 0xded90dcd -0, 24, 24, 1, 152064, 0xd6883255 -0, 25, 25, 1, 152064, 0x6edb4d4f -0, 26, 26, 1, 152064, 0xd6f93a80 -0, 27, 27, 1, 152064, 0x163d6153 -0, 28, 28, 1, 152064, 0x04b90c06 -0, 29, 29, 1, 152064, 0xee8730c1 -0, 30, 30, 1, 152064, 0xd5f5c669 -0, 31, 31, 1, 152064, 0xcc600b1f -0, 32, 32, 1, 152064, 0x15ddde03 -0, 33, 33, 1, 152064, 0xd0388dd0 -0, 34, 34, 1, 152064, 0xa292ab7d -0, 35, 35, 1, 152064, 0xacf584e9 -0, 36, 36, 1, 152064, 0xcef42714 -0, 37, 37, 1, 152064, 0xeb162f35 -0, 38, 38, 1, 152064, 0x0a07de7b -0, 39, 39, 1, 152064, 0x7ae76c81 -0, 40, 40, 1, 152064, 0x139c8fda -0, 41, 41, 1, 152064, 0x43724411 -0, 42, 42, 1, 152064, 0x07b2ddea -0, 43, 43, 1, 152064, 0x831a1cc7 -0, 44, 44, 1, 152064, 0x092f5073 -0, 45, 45, 1, 152064, 0xe5b6d380 -0, 46, 46, 1, 152064, 0xdd30d69e -0, 47, 47, 1, 152064, 0x887020b2 -0, 48, 48, 1, 152064, 0x84436510 -0, 49, 49, 1, 152064, 0x49f63606 -0, 50, 50, 1, 152064, 0x6b96e959 -0, 51, 51, 1, 152064, 0xc6247cc7 -0, 52, 52, 1, 152064, 0x7a67c532 -0, 53, 53, 1, 152064, 0x93f4c476 -0, 54, 54, 1, 152064, 0x3c119654 -0, 55, 55, 1, 152064, 0xa45f7c72 -0, 56, 56, 1, 152064, 0x2ac50cb0 -0, 57, 57, 1, 152064, 0x9bf16d06 -0, 58, 58, 1, 152064, 0xfa0750d9 -0, 59, 59, 1, 152064, 0x02197630 -0, 60, 60, 1, 152064, 0x6d44f9b5 -0, 61, 61, 1, 152064, 0x86b211f5 -0, 62, 62, 1, 152064, 0xf4fda5d0 -0, 63, 63, 1, 152064, 0x36f840a7 -0, 64, 64, 1, 152064, 0x42412992 -0, 65, 65, 1, 152064, 0xd0c9ba37 -0, 66, 66, 1, 152064, 0xc40eba62 -0, 67, 67, 1, 152064, 0x2d093b53 -0, 68, 68, 1, 152064, 0xee39c69c -0, 69, 69, 1, 152064, 0xcbbf8968 -0, 70, 70, 1, 152064, 0xfddc1704 -0, 71, 71, 1, 152064, 0x8dc47c61 -0, 72, 72, 1, 152064, 0xf15580bf -0, 73, 73, 1, 152064, 0x9c71a8b0 -0, 74, 74, 1, 152064, 0x19b90b9f -0, 75, 75, 1, 152064, 0xb65ae287 -0, 76, 76, 1, 152064, 0xf265693d -0, 77, 77, 1, 152064, 0x721714a1 -0, 78, 78, 1, 152064, 0x383e8ac5 -0, 79, 79, 1, 152064, 0x02558677 -0, 80, 80, 1, 152064, 0xdaab3cdf -0, 81, 81, 1, 152064, 0xc939a2f6 -0, 82, 82, 1, 152064, 0x977afa7f -0, 83, 83, 1, 152064, 0xe5e65f35 -0, 84, 84, 1, 152064, 0x247546fa -0, 85, 85, 1, 152064, 0x49ff2094 -0, 86, 86, 1, 152064, 0x9fd58cda -0, 87, 87, 1, 152064, 0x3e31b6e3 -0, 88, 88, 1, 152064, 0x75c6d796 -0, 89, 89, 1, 152064, 0x4ab3e7bb -0, 90, 90, 1, 152064, 0x393935ea -0, 91, 91, 1, 152064, 0xc8e62905 -0, 92, 92, 1, 152064, 0xbb149e61 -0, 93, 93, 1, 152064, 0x2553c4c5 -0, 94, 94, 1, 152064, 0x7f82a8b4 -0, 95, 95, 1, 152064, 0x26ef31e6 -0, 96, 96, 1, 152064, 0xf029744a -0, 97, 97, 1, 152064, 0x0a6f191a -0, 98, 98, 1, 152064, 0x55808643 -0, 99, 99, 1, 152064, 0x27576172 +0, 1, 1, 1, 152064, 0xbdc2b880 +0, 2, 2, 1, 152064, 0x4ebf93fe +0, 3, 3, 1, 152064, 0xe30d6871 +0, 4, 4, 1, 152064, 0x04f46b9b +0, 5, 5, 1, 152064, 0xd7dd219a +0, 6, 6, 1, 152064, 0x02fc6511 +0, 7, 7, 1, 152064, 0x98868faa +0, 8, 8, 1, 152064, 0x54b94f92 +0, 9, 9, 1, 152064, 0xe3b6be4b +0, 10, 10, 1, 152064, 0xf148cf10 +0, 11, 11, 1, 152064, 0xda3239b8 +0, 12, 12, 1, 152064, 0x6c5d7331 +0, 13, 13, 1, 152064, 0x825f1fea +0, 14, 14, 1, 152064, 0x47791056 +0, 15, 15, 1, 152064, 0xc08e8a58 +0, 16, 16, 1, 152064, 0x020299f3 +0, 17, 17, 1, 152064, 0x0dfd4457 +0, 18, 18, 1, 152064, 0xcf005e68 +0, 19, 19, 1, 152064, 0x1f9e2c32 +0, 20, 20, 1, 152064, 0xa8359324 +0, 21, 21, 1, 152064, 0x4b03752d +0, 22, 22, 1, 152064, 0xd6281621 +0, 23, 23, 1, 152064, 0xc97ac928 +0, 24, 24, 1, 152064, 0xded90dcd +0, 25, 25, 1, 152064, 0xd6883255 +0, 26, 26, 1, 152064, 0x6edb4d4f +0, 27, 27, 1, 152064, 0xd6f93a80 +0, 28, 28, 1, 152064, 0x163d6153 +0, 29, 29, 1, 152064, 0x04b90c06 +0, 30, 30, 1, 152064, 0xee8730c1 +0, 31, 31, 1, 152064, 0xd5f5c669 +0, 32, 32, 1, 152064, 0xcc600b1f +0, 33, 33, 1, 152064, 0x15ddde03 +0, 34, 34, 1, 152064, 0xd0388dd0 +0, 35, 35, 1, 152064, 0xa292ab7d +0, 36, 36, 1, 152064, 0xacf584e9 +0, 37, 37, 1, 152064, 0xcef42714 +0, 38, 38, 1, 152064, 0xeb162f35 +0, 39, 39, 1, 152064, 0x0a07de7b +0, 40, 40, 1, 152064, 0x7ae76c81 +0, 41, 41, 1, 152064, 0x139c8fda +0, 42, 42, 1, 152064, 0x43724411 +0, 43, 43, 1, 152064, 0x07b2ddea +0, 44, 44, 1, 152064, 0x831a1cc7 +0, 45, 45, 1, 152064, 0x092f5073 +0, 46, 46, 1, 152064, 0xe5b6d380 +0, 47, 47, 1, 152064, 0xdd30d69e +0, 48, 48, 1, 152064, 0x887020b2 +0, 49, 49, 1, 152064, 0x84436510 +0, 50, 50, 1, 152064, 0x49f63606 +0, 51, 51, 1, 152064, 0x6b96e959 +0, 52, 52, 1, 152064, 0xc6247cc7 +0, 53, 53, 1, 152064, 0x7a67c532 +0, 54, 54, 1, 152064, 0x93f4c476 +0, 55, 55, 1, 152064, 0x3c119654 +0, 56, 56, 1, 152064, 0xa45f7c72 +0, 57, 57, 1, 152064, 0x2ac50cb0 +0, 58, 58, 1, 152064, 0x9bf16d06 +0, 59, 59, 1, 152064, 0xfa0750d9 +0, 60, 60, 1, 152064, 0x02197630 +0, 61, 61, 1, 152064, 0x6d44f9b5 +0, 62, 62, 1, 152064, 0x86b211f5 +0, 63, 63, 1, 152064, 0xf4fda5d0 +0, 64, 64, 1, 152064, 0x36f840a7 +0, 65, 65, 1, 152064, 0x42412992 +0, 66, 66, 1, 152064, 0xd0c9ba37 +0, 67, 67, 1, 152064, 0xc40eba62 +0, 68, 68, 1, 152064, 0x2d093b53 +0, 69, 69, 1, 152064, 0xee39c69c +0, 70, 70, 1, 152064, 0xcbbf8968 +0, 71, 71, 1, 152064, 0xfddc1704 +0, 72, 72, 1, 152064, 0x8dc47c61 +0, 73, 73, 1, 152064, 0xf15580bf +0, 74, 74, 1, 152064, 0x9c71a8b0 +0, 75, 75, 1, 152064, 0x19b90b9f +0, 76, 76, 1, 152064, 0xb65ae287 +0, 77, 77, 1, 152064, 0xf265693d +0, 78, 78, 1, 152064, 0x721714a1 +0, 79, 79, 1, 152064, 0x383e8ac5 +0, 80, 80, 1, 152064, 0x02558677 +0, 81, 81, 1, 152064, 0xdaab3cdf +0, 82, 82, 1, 152064, 0xc939a2f6 +0, 83, 83, 1, 152064, 0x977afa7f +0, 84, 84, 1, 152064, 0xe5e65f35 +0, 85, 85, 1, 152064, 0x247546fa +0, 86, 86, 1, 152064, 0x49ff2094 +0, 87, 87, 1, 152064, 0x9fd58cda +0, 88, 88, 1, 152064, 0x3e31b6e3 +0, 89, 89, 1, 152064, 0x75c6d796 +0, 90, 90, 1, 152064, 0x4ab3e7bb +0, 91, 91, 1, 152064, 0x393935ea +0, 92, 92, 1, 152064, 0xc8e62905 +0, 93, 93, 1, 152064, 0xbb149e61 +0, 94, 94, 1, 152064, 0x2553c4c5 +0, 95, 95, 1, 152064, 0x7f82a8b4 +0, 96, 96, 1, 152064, 0x26ef31e6 +0, 97, 97, 1, 152064, 0xf029744a +0, 98, 98, 1, 152064, 0x0a6f191a +0, 99, 99, 1, 152064, 0x55808643 +0, 100, 100, 1, 152064, 0x27576172 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-brcm_freh11 ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-brcm_freh11 --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-brcm_freh11 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-brcm_freh11 2021-04-08 21:28:40.000000000 +0000 @@ -3,103 +3,103 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x9744ac59 -0, 1, 1, 1, 152064, 0x3eba88bf -0, 2, 2, 1, 152064, 0xd4105c5a -0, 3, 3, 1, 152064, 0x452966a3 -0, 4, 4, 1, 152064, 0x30071add -0, 5, 5, 1, 152064, 0x0eb75245 -0, 6, 6, 1, 152064, 0x4daa80fa -0, 7, 7, 1, 152064, 0xf53a43a1 -0, 8, 8, 1, 152064, 0xa55ab43d -0, 9, 9, 1, 152064, 0x915ec82e -0, 10, 10, 1, 152064, 0xadce2f9a -0, 11, 11, 1, 152064, 0xf7a25715 -0, 12, 12, 1, 152064, 0x90c91c7d -0, 13, 13, 1, 152064, 0x4f0df4ef -0, 14, 14, 1, 152064, 0xf6e0783c -0, 15, 15, 1, 152064, 0x417c8ca8 -0, 16, 16, 1, 152064, 0xd33d29d8 -0, 17, 17, 1, 152064, 0xc9723fa3 -0, 18, 18, 1, 152064, 0x3e4f22f4 -0, 19, 19, 1, 152064, 0xd5aa7bd8 -0, 20, 20, 1, 152064, 0x2a425b54 -0, 21, 21, 1, 152064, 0x2d400788 -0, 22, 22, 1, 152064, 0x12fab3a4 -0, 23, 23, 1, 152064, 0x5544f881 -0, 24, 24, 1, 152064, 0xd0612cc5 -0, 25, 25, 1, 152064, 0x157b3654 -0, 26, 26, 1, 152064, 0x04b61fe0 -0, 27, 27, 1, 152064, 0x897d600a -0, 28, 28, 1, 152064, 0x0d94fa29 -0, 29, 29, 1, 152064, 0xc0fe249d -0, 30, 30, 1, 152064, 0x65abc1d6 -0, 31, 31, 1, 152064, 0x2bd5f09d -0, 32, 32, 1, 152064, 0xd3eebd28 -0, 33, 33, 1, 152064, 0x93458649 -0, 34, 34, 1, 152064, 0x55e793a6 -0, 35, 35, 1, 152064, 0x9fc378ce -0, 36, 36, 1, 152064, 0x24c32731 -0, 37, 37, 1, 152064, 0x3c321c50 -0, 38, 38, 1, 152064, 0xcef3ca8b -0, 39, 39, 1, 152064, 0x97116676 -0, 40, 40, 1, 152064, 0x73ae78f6 -0, 41, 41, 1, 152064, 0xdeec219e -0, 42, 42, 1, 152064, 0xc061d584 -0, 43, 43, 1, 152064, 0xcf47f6c9 -0, 44, 44, 1, 152064, 0x280d3a2d -0, 45, 45, 1, 152064, 0xb660c846 -0, 46, 46, 1, 152064, 0xe167c588 -0, 47, 47, 1, 152064, 0x08f808de -0, 48, 48, 1, 152064, 0x9de65c0b -0, 49, 49, 1, 152064, 0xc52a1937 -0, 50, 50, 1, 152064, 0xf5a4d86f -0, 51, 51, 1, 152064, 0xbef86d37 -0, 52, 52, 1, 152064, 0xa227b21b -0, 53, 53, 1, 152064, 0x0601ad35 -0, 54, 54, 1, 152064, 0x15198730 -0, 55, 55, 1, 152064, 0x9af764c6 -0, 56, 56, 1, 152064, 0x1a95e99a -0, 57, 57, 1, 152064, 0x6bef5aa8 -0, 58, 58, 1, 152064, 0x92f03267 -0, 59, 59, 1, 152064, 0x0a3d56cb -0, 60, 60, 1, 152064, 0xd9c9f62e -0, 61, 61, 1, 152064, 0xcd81ea16 -0, 62, 62, 1, 152064, 0x8ed789c0 -0, 63, 63, 1, 152064, 0x5a5e356f -0, 64, 64, 1, 152064, 0x2f260ebf -0, 65, 65, 1, 152064, 0xa0379c89 -0, 66, 66, 1, 152064, 0x100cb40c -0, 67, 67, 1, 152064, 0xaad2220a -0, 68, 68, 1, 152064, 0xec82aa8d -0, 69, 69, 1, 152064, 0x91088303 -0, 70, 70, 1, 152064, 0x0cce0e9e -0, 71, 71, 1, 152064, 0xf3bc716a -0, 72, 72, 1, 152064, 0x989879c5 -0, 73, 73, 1, 152064, 0x491297a0 -0, 74, 74, 1, 152064, 0xdc16f30d -0, 75, 75, 1, 152064, 0xb9bfdd57 -0, 76, 76, 1, 152064, 0x5fba59c2 -0, 77, 77, 1, 152064, 0x89c40529 -0, 78, 78, 1, 152064, 0x1b3e7b54 -0, 79, 79, 1, 152064, 0x5d0d7903 -0, 80, 80, 1, 152064, 0x2e3434e1 -0, 81, 81, 1, 152064, 0x1f47a276 -0, 82, 82, 1, 152064, 0xa22de2b1 -0, 83, 83, 1, 152064, 0x77344844 -0, 84, 84, 1, 152064, 0x6a6b3fce -0, 85, 85, 1, 152064, 0x82660651 -0, 86, 86, 1, 152064, 0x51e67cc9 -0, 87, 87, 1, 152064, 0xb790ae51 -0, 88, 88, 1, 152064, 0x906bc6b6 -0, 89, 89, 1, 152064, 0x55c5dc21 -0, 90, 90, 1, 152064, 0xb51f3004 -0, 91, 91, 1, 152064, 0x68500a25 -0, 92, 92, 1, 152064, 0x5dbc812e -0, 93, 93, 1, 152064, 0x895eb6ed -0, 94, 94, 1, 152064, 0x2f5594fc -0, 95, 95, 1, 152064, 0x04a222a9 -0, 96, 96, 1, 152064, 0x90036f6a -0, 97, 97, 1, 152064, 0x8b8b064c -0, 98, 98, 1, 152064, 0xd47c7334 -0, 99, 99, 1, 152064, 0x13f06213 +0, 1, 1, 1, 152064, 0x9744ac59 +0, 2, 2, 1, 152064, 0x3eba88bf +0, 3, 3, 1, 152064, 0xd4105c5a +0, 4, 4, 1, 152064, 0x452966a3 +0, 5, 5, 1, 152064, 0x30071add +0, 6, 6, 1, 152064, 0x0eb75245 +0, 7, 7, 1, 152064, 0x4daa80fa +0, 8, 8, 1, 152064, 0xf53a43a1 +0, 9, 9, 1, 152064, 0xa55ab43d +0, 10, 10, 1, 152064, 0x915ec82e +0, 11, 11, 1, 152064, 0xadce2f9a +0, 12, 12, 1, 152064, 0xf7a25715 +0, 13, 13, 1, 152064, 0x90c91c7d +0, 14, 14, 1, 152064, 0x4f0df4ef +0, 15, 15, 1, 152064, 0xf6e0783c +0, 16, 16, 1, 152064, 0x417c8ca8 +0, 17, 17, 1, 152064, 0xd33d29d8 +0, 18, 18, 1, 152064, 0xc9723fa3 +0, 19, 19, 1, 152064, 0x3e4f22f4 +0, 20, 20, 1, 152064, 0xd5aa7bd8 +0, 21, 21, 1, 152064, 0x2a425b54 +0, 22, 22, 1, 152064, 0x2d400788 +0, 23, 23, 1, 152064, 0x12fab3a4 +0, 24, 24, 1, 152064, 0x5544f881 +0, 25, 25, 1, 152064, 0xd0612cc5 +0, 26, 26, 1, 152064, 0x157b3654 +0, 27, 27, 1, 152064, 0x04b61fe0 +0, 28, 28, 1, 152064, 0x897d600a +0, 29, 29, 1, 152064, 0x0d94fa29 +0, 30, 30, 1, 152064, 0xc0fe249d +0, 31, 31, 1, 152064, 0x65abc1d6 +0, 32, 32, 1, 152064, 0x2bd5f09d +0, 33, 33, 1, 152064, 0xd3eebd28 +0, 34, 34, 1, 152064, 0x93458649 +0, 35, 35, 1, 152064, 0x55e793a6 +0, 36, 36, 1, 152064, 0x9fc378ce +0, 37, 37, 1, 152064, 0x24c32731 +0, 38, 38, 1, 152064, 0x3c321c50 +0, 39, 39, 1, 152064, 0xcef3ca8b +0, 40, 40, 1, 152064, 0x97116676 +0, 41, 41, 1, 152064, 0x73ae78f6 +0, 42, 42, 1, 152064, 0xdeec219e +0, 43, 43, 1, 152064, 0xc061d584 +0, 44, 44, 1, 152064, 0xcf47f6c9 +0, 45, 45, 1, 152064, 0x280d3a2d +0, 46, 46, 1, 152064, 0xb660c846 +0, 47, 47, 1, 152064, 0xe167c588 +0, 48, 48, 1, 152064, 0x08f808de +0, 49, 49, 1, 152064, 0x9de65c0b +0, 50, 50, 1, 152064, 0xc52a1937 +0, 51, 51, 1, 152064, 0xf5a4d86f +0, 52, 52, 1, 152064, 0xbef86d37 +0, 53, 53, 1, 152064, 0xa227b21b +0, 54, 54, 1, 152064, 0x0601ad35 +0, 55, 55, 1, 152064, 0x15198730 +0, 56, 56, 1, 152064, 0x9af764c6 +0, 57, 57, 1, 152064, 0x1a95e99a +0, 58, 58, 1, 152064, 0x6bef5aa8 +0, 59, 59, 1, 152064, 0x92f03267 +0, 60, 60, 1, 152064, 0x0a3d56cb +0, 61, 61, 1, 152064, 0xd9c9f62e +0, 62, 62, 1, 152064, 0xcd81ea16 +0, 63, 63, 1, 152064, 0x8ed789c0 +0, 64, 64, 1, 152064, 0x5a5e356f +0, 65, 65, 1, 152064, 0x2f260ebf +0, 66, 66, 1, 152064, 0xa0379c89 +0, 67, 67, 1, 152064, 0x100cb40c +0, 68, 68, 1, 152064, 0xaad2220a +0, 69, 69, 1, 152064, 0xec82aa8d +0, 70, 70, 1, 152064, 0x91088303 +0, 71, 71, 1, 152064, 0x0cce0e9e +0, 72, 72, 1, 152064, 0xf3bc716a +0, 73, 73, 1, 152064, 0x989879c5 +0, 74, 74, 1, 152064, 0x491297a0 +0, 75, 75, 1, 152064, 0xdc16f30d +0, 76, 76, 1, 152064, 0xb9bfdd57 +0, 77, 77, 1, 152064, 0x5fba59c2 +0, 78, 78, 1, 152064, 0x89c40529 +0, 79, 79, 1, 152064, 0x1b3e7b54 +0, 80, 80, 1, 152064, 0x5d0d7903 +0, 81, 81, 1, 152064, 0x2e3434e1 +0, 82, 82, 1, 152064, 0x1f47a276 +0, 83, 83, 1, 152064, 0xa22de2b1 +0, 84, 84, 1, 152064, 0x77344844 +0, 85, 85, 1, 152064, 0x6a6b3fce +0, 86, 86, 1, 152064, 0x82660651 +0, 87, 87, 1, 152064, 0x51e67cc9 +0, 88, 88, 1, 152064, 0xb790ae51 +0, 89, 89, 1, 152064, 0x906bc6b6 +0, 90, 90, 1, 152064, 0x55c5dc21 +0, 91, 91, 1, 152064, 0xb51f3004 +0, 92, 92, 1, 152064, 0x68500a25 +0, 93, 93, 1, 152064, 0x5dbc812e +0, 94, 94, 1, 152064, 0x895eb6ed +0, 95, 95, 1, 152064, 0x2f5594fc +0, 96, 96, 1, 152064, 0x04a222a9 +0, 97, 97, 1, 152064, 0x90036f6a +0, 98, 98, 1, 152064, 0x8b8b064c +0, 99, 99, 1, 152064, 0xd47c7334 +0, 100, 100, 1, 152064, 0x13f06213 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-brcm_freh4 ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-brcm_freh4 --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-brcm_freh4 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-brcm_freh4 2021-04-08 21:28:40.000000000 +0000 @@ -3,103 +3,103 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x9744ac59 -0, 1, 1, 1, 152064, 0xe1c69d97 -0, 2, 2, 1, 152064, 0x9ae85f93 -0, 3, 3, 1, 152064, 0x452966a3 -0, 4, 4, 1, 152064, 0xe8192823 -0, 5, 5, 1, 152064, 0x58b764eb -0, 6, 6, 1, 152064, 0x51b686b1 -0, 7, 7, 1, 152064, 0x4bca5822 -0, 8, 8, 1, 152064, 0x29abc41c -0, 9, 9, 1, 152064, 0x850ec94f -0, 10, 10, 1, 152064, 0xac2c34f8 -0, 11, 11, 1, 152064, 0x080c6e67 -0, 12, 12, 1, 152064, 0x5e4e14d2 -0, 13, 13, 1, 152064, 0x978b054c -0, 14, 14, 1, 152064, 0x861d8c3c -0, 15, 15, 1, 152064, 0xe0818918 -0, 16, 16, 1, 152064, 0x8b834511 -0, 17, 17, 1, 152064, 0x223f567c -0, 18, 18, 1, 152064, 0x6d61298d -0, 19, 19, 1, 152064, 0xfe30826e -0, 20, 20, 1, 152064, 0x4bad4f98 -0, 21, 21, 1, 152064, 0x69d5fdca -0, 22, 22, 1, 152064, 0xe45bba1b -0, 23, 23, 1, 152064, 0xa6d81298 -0, 24, 24, 1, 152064, 0x7f3f2c91 -0, 25, 25, 1, 152064, 0x658754b9 -0, 26, 26, 1, 152064, 0x2c6d3eba -0, 27, 27, 1, 152064, 0x4500600c -0, 28, 28, 1, 152064, 0xa745f74b -0, 29, 29, 1, 152064, 0x2bf21fca -0, 30, 30, 1, 152064, 0x08b8bdb3 -0, 31, 31, 1, 152064, 0x5a9d0a8b -0, 32, 32, 1, 152064, 0x3a57d523 -0, 33, 33, 1, 152064, 0x3606826e -0, 34, 34, 1, 152064, 0x3b91a8fb -0, 35, 35, 1, 152064, 0x37c28959 -0, 36, 36, 1, 152064, 0xb51d1e75 -0, 37, 37, 1, 152064, 0x13be3f58 -0, 38, 38, 1, 152064, 0x0ed0e7cf -0, 39, 39, 1, 152064, 0x298560d4 -0, 40, 40, 1, 152064, 0x62b68373 -0, 41, 41, 1, 152064, 0xf8bb4520 -0, 42, 42, 1, 152064, 0x90dfd6af -0, 43, 43, 1, 152064, 0xf4770d20 -0, 44, 44, 1, 152064, 0x0d9549a0 -0, 45, 45, 1, 152064, 0x004eccb1 -0, 46, 46, 1, 152064, 0x3146d46b -0, 47, 47, 1, 152064, 0x078d1808 -0, 48, 48, 1, 152064, 0x5d8d60cd -0, 49, 49, 1, 152064, 0x8ff52dd8 -0, 50, 50, 1, 152064, 0x5aa3ccf7 -0, 51, 51, 1, 152064, 0x5bec6c39 -0, 52, 52, 1, 152064, 0xd44cae9d -0, 53, 53, 1, 152064, 0xa1b0a151 -0, 54, 54, 1, 152064, 0xe3be7bb2 -0, 55, 55, 1, 152064, 0x50096775 -0, 56, 56, 1, 152064, 0xdffff851 -0, 57, 57, 1, 152064, 0x1d7250eb -0, 58, 58, 1, 152064, 0x69663ca7 -0, 59, 59, 1, 152064, 0x62f77fc7 -0, 60, 60, 1, 152064, 0xbab8f471 -0, 61, 61, 1, 152064, 0x6af31785 -0, 62, 62, 1, 152064, 0xcbb2a9aa -0, 63, 63, 1, 152064, 0xc57c32b9 -0, 64, 64, 1, 152064, 0xecbe2ce0 -0, 65, 65, 1, 152064, 0x2fbebf81 -0, 66, 66, 1, 152064, 0xa168af68 -0, 67, 67, 1, 152064, 0x1e5631ac -0, 68, 68, 1, 152064, 0xe69fc927 -0, 69, 69, 1, 152064, 0x8e5c81d8 -0, 70, 70, 1, 152064, 0x42402010 -0, 71, 71, 1, 152064, 0xd7267482 -0, 72, 72, 1, 152064, 0x64b280df -0, 73, 73, 1, 152064, 0xc4cbafcc -0, 74, 74, 1, 152064, 0xcf2f1e8b -0, 75, 75, 1, 152064, 0x4d6fdb3f -0, 76, 76, 1, 152064, 0xf22d6fed -0, 77, 77, 1, 152064, 0x625b167c -0, 78, 78, 1, 152064, 0x41348089 -0, 79, 79, 1, 152064, 0x6db2779b -0, 80, 80, 1, 152064, 0xe87030a8 -0, 81, 81, 1, 152064, 0x91b29cdd -0, 82, 82, 1, 152064, 0xe824f242 -0, 83, 83, 1, 152064, 0xac995380 -0, 84, 84, 1, 152064, 0x7efe361b -0, 85, 85, 1, 152064, 0xe10c0c26 -0, 86, 86, 1, 152064, 0x93108260 -0, 87, 87, 1, 152064, 0xbf4caed7 -0, 88, 88, 1, 152064, 0xb6a4d826 -0, 89, 89, 1, 152064, 0x78beea4e -0, 90, 90, 1, 152064, 0xdf612df9 -0, 91, 91, 1, 152064, 0xa9ef2830 -0, 92, 92, 1, 152064, 0x06448895 -0, 93, 93, 1, 152064, 0x332eb6d5 -0, 94, 94, 1, 152064, 0x935ba2c5 -0, 95, 95, 1, 152064, 0x62a22656 -0, 96, 96, 1, 152064, 0x06a670a7 -0, 97, 97, 1, 152064, 0xf60b1af0 -0, 98, 98, 1, 152064, 0x85177c10 -0, 99, 99, 1, 152064, 0x5e4e5c4b +0, 1, 1, 1, 152064, 0x9744ac59 +0, 2, 2, 1, 152064, 0xe1c69d97 +0, 3, 3, 1, 152064, 0x9ae85f93 +0, 4, 4, 1, 152064, 0x452966a3 +0, 5, 5, 1, 152064, 0xe8192823 +0, 6, 6, 1, 152064, 0x58b764eb +0, 7, 7, 1, 152064, 0x51b686b1 +0, 8, 8, 1, 152064, 0x4bca5822 +0, 9, 9, 1, 152064, 0x29abc41c +0, 10, 10, 1, 152064, 0x850ec94f +0, 11, 11, 1, 152064, 0xac2c34f8 +0, 12, 12, 1, 152064, 0x080c6e67 +0, 13, 13, 1, 152064, 0x5e4e14d2 +0, 14, 14, 1, 152064, 0x978b054c +0, 15, 15, 1, 152064, 0x861d8c3c +0, 16, 16, 1, 152064, 0xe0818918 +0, 17, 17, 1, 152064, 0x8b834511 +0, 18, 18, 1, 152064, 0x223f567c +0, 19, 19, 1, 152064, 0x6d61298d +0, 20, 20, 1, 152064, 0xfe30826e +0, 21, 21, 1, 152064, 0x4bad4f98 +0, 22, 22, 1, 152064, 0x69d5fdca +0, 23, 23, 1, 152064, 0xe45bba1b +0, 24, 24, 1, 152064, 0xa6d81298 +0, 25, 25, 1, 152064, 0x7f3f2c91 +0, 26, 26, 1, 152064, 0x658754b9 +0, 27, 27, 1, 152064, 0x2c6d3eba +0, 28, 28, 1, 152064, 0x4500600c +0, 29, 29, 1, 152064, 0xa745f74b +0, 30, 30, 1, 152064, 0x2bf21fca +0, 31, 31, 1, 152064, 0x08b8bdb3 +0, 32, 32, 1, 152064, 0x5a9d0a8b +0, 33, 33, 1, 152064, 0x3a57d523 +0, 34, 34, 1, 152064, 0x3606826e +0, 35, 35, 1, 152064, 0x3b91a8fb +0, 36, 36, 1, 152064, 0x37c28959 +0, 37, 37, 1, 152064, 0xb51d1e75 +0, 38, 38, 1, 152064, 0x13be3f58 +0, 39, 39, 1, 152064, 0x0ed0e7cf +0, 40, 40, 1, 152064, 0x298560d4 +0, 41, 41, 1, 152064, 0x62b68373 +0, 42, 42, 1, 152064, 0xf8bb4520 +0, 43, 43, 1, 152064, 0x90dfd6af +0, 44, 44, 1, 152064, 0xf4770d20 +0, 45, 45, 1, 152064, 0x0d9549a0 +0, 46, 46, 1, 152064, 0x004eccb1 +0, 47, 47, 1, 152064, 0x3146d46b +0, 48, 48, 1, 152064, 0x078d1808 +0, 49, 49, 1, 152064, 0x5d8d60cd +0, 50, 50, 1, 152064, 0x8ff52dd8 +0, 51, 51, 1, 152064, 0x5aa3ccf7 +0, 52, 52, 1, 152064, 0x5bec6c39 +0, 53, 53, 1, 152064, 0xd44cae9d +0, 54, 54, 1, 152064, 0xa1b0a151 +0, 55, 55, 1, 152064, 0xe3be7bb2 +0, 56, 56, 1, 152064, 0x50096775 +0, 57, 57, 1, 152064, 0xdffff851 +0, 58, 58, 1, 152064, 0x1d7250eb +0, 59, 59, 1, 152064, 0x69663ca7 +0, 60, 60, 1, 152064, 0x62f77fc7 +0, 61, 61, 1, 152064, 0xbab8f471 +0, 62, 62, 1, 152064, 0x6af31785 +0, 63, 63, 1, 152064, 0xcbb2a9aa +0, 64, 64, 1, 152064, 0xc57c32b9 +0, 65, 65, 1, 152064, 0xecbe2ce0 +0, 66, 66, 1, 152064, 0x2fbebf81 +0, 67, 67, 1, 152064, 0xa168af68 +0, 68, 68, 1, 152064, 0x1e5631ac +0, 69, 69, 1, 152064, 0xe69fc927 +0, 70, 70, 1, 152064, 0x8e5c81d8 +0, 71, 71, 1, 152064, 0x42402010 +0, 72, 72, 1, 152064, 0xd7267482 +0, 73, 73, 1, 152064, 0x64b280df +0, 74, 74, 1, 152064, 0xc4cbafcc +0, 75, 75, 1, 152064, 0xcf2f1e8b +0, 76, 76, 1, 152064, 0x4d6fdb3f +0, 77, 77, 1, 152064, 0xf22d6fed +0, 78, 78, 1, 152064, 0x625b167c +0, 79, 79, 1, 152064, 0x41348089 +0, 80, 80, 1, 152064, 0x6db2779b +0, 81, 81, 1, 152064, 0xe87030a8 +0, 82, 82, 1, 152064, 0x91b29cdd +0, 83, 83, 1, 152064, 0xe824f242 +0, 84, 84, 1, 152064, 0xac995380 +0, 85, 85, 1, 152064, 0x7efe361b +0, 86, 86, 1, 152064, 0xe10c0c26 +0, 87, 87, 1, 152064, 0x93108260 +0, 88, 88, 1, 152064, 0xbf4caed7 +0, 89, 89, 1, 152064, 0xb6a4d826 +0, 90, 90, 1, 152064, 0x78beea4e +0, 91, 91, 1, 152064, 0xdf612df9 +0, 92, 92, 1, 152064, 0xa9ef2830 +0, 93, 93, 1, 152064, 0x06448895 +0, 94, 94, 1, 152064, 0x332eb6d5 +0, 95, 95, 1, 152064, 0x935ba2c5 +0, 96, 96, 1, 152064, 0x62a22656 +0, 97, 97, 1, 152064, 0x06a670a7 +0, 98, 98, 1, 152064, 0xf60b1af0 +0, 99, 99, 1, 152064, 0x85177c10 +0, 100, 100, 1, 152064, 0x5e4e5c4b diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-freh6 ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-freh6 --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-freh6 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-freh6 2021-04-08 21:28:40.000000000 +0000 @@ -3,103 +3,103 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x3b21d6cd -0, 1, 1, 1, 152064, 0xc32088c6 -0, 2, 2, 1, 152064, 0x65a64cee -0, 3, 3, 1, 152064, 0x0bd45a5b -0, 4, 4, 1, 152064, 0xb2210d4d -0, 5, 5, 1, 152064, 0xf5b15527 -0, 6, 6, 1, 152064, 0x806572ad -0, 7, 7, 1, 152064, 0x6ecb1fc8 -0, 8, 8, 1, 152064, 0xc25e96d5 -0, 9, 9, 1, 152064, 0x5593b825 -0, 10, 10, 1, 152064, 0xf3be1cff -0, 11, 11, 1, 152064, 0xa9155072 -0, 12, 12, 1, 152064, 0xd5552e26 -0, 13, 13, 1, 152064, 0x7bf0dbee -0, 14, 14, 1, 152064, 0x998b4911 -0, 15, 15, 1, 152064, 0xcc71bbe0 -0, 16, 16, 1, 152064, 0x602415b8 -0, 17, 17, 1, 152064, 0xcfff37cf -0, 18, 18, 1, 152064, 0x7cf824a8 -0, 19, 19, 1, 152064, 0x34816ee5 -0, 20, 20, 1, 152064, 0x1480540c -0, 21, 21, 1, 152064, 0xc2351aaf -0, 22, 22, 1, 152064, 0x3b8eac9f -0, 23, 23, 1, 152064, 0x92a8faf8 -0, 24, 24, 1, 152064, 0x7b6121c8 -0, 25, 25, 1, 152064, 0xe73a3bac -0, 26, 26, 1, 152064, 0xcd6e1e36 -0, 27, 27, 1, 152064, 0xb24660b1 -0, 28, 28, 1, 152064, 0xa290ec25 -0, 29, 29, 1, 152064, 0x308915ff -0, 30, 30, 1, 152064, 0x1e8dd4db -0, 31, 31, 1, 152064, 0x1372f2e0 -0, 32, 32, 1, 152064, 0xa07cc1d0 -0, 33, 33, 1, 152064, 0x34bb872c -0, 34, 34, 1, 152064, 0x59e6a565 -0, 35, 35, 1, 152064, 0x9a097932 -0, 36, 36, 1, 152064, 0x938f2e20 -0, 37, 37, 1, 152064, 0x59a8157d -0, 38, 38, 1, 152064, 0x5cacd404 -0, 39, 39, 1, 152064, 0xdad068f5 -0, 40, 40, 1, 152064, 0x7ba67d47 -0, 41, 41, 1, 152064, 0xc2a11e2d -0, 42, 42, 1, 152064, 0xd37fdef7 -0, 43, 43, 1, 152064, 0x19a3f80a -0, 44, 44, 1, 152064, 0x7ec7426a -0, 45, 45, 1, 152064, 0x8ffedb61 -0, 46, 46, 1, 152064, 0x82aebdd0 -0, 47, 47, 1, 152064, 0xdfc920cc -0, 48, 48, 1, 152064, 0x2a467698 -0, 49, 49, 1, 152064, 0xd08a37d5 -0, 50, 50, 1, 152064, 0xe606e66a -0, 51, 51, 1, 152064, 0x0e7b8bd8 -0, 52, 52, 1, 152064, 0xf983c732 -0, 53, 53, 1, 152064, 0x9b82c2e7 -0, 54, 54, 1, 152064, 0xa990a47e -0, 55, 55, 1, 152064, 0x2d5679f1 -0, 56, 56, 1, 152064, 0x7f1c0201 -0, 57, 57, 1, 152064, 0xc38b709d -0, 58, 58, 1, 152064, 0x040246d8 -0, 59, 59, 1, 152064, 0xbc856021 -0, 60, 60, 1, 152064, 0x81e01a78 -0, 61, 61, 1, 152064, 0xaff1e7f1 -0, 62, 62, 1, 152064, 0x1fee7715 -0, 63, 63, 1, 152064, 0x65053711 -0, 64, 64, 1, 152064, 0x238a0118 -0, 65, 65, 1, 152064, 0x563491b4 -0, 66, 66, 1, 152064, 0x5974a6cc -0, 67, 67, 1, 152064, 0xd8682c35 -0, 68, 68, 1, 152064, 0x85c49e96 -0, 69, 69, 1, 152064, 0x29486faa -0, 70, 70, 1, 152064, 0x1a4f0579 -0, 71, 71, 1, 152064, 0x6ab86c2f -0, 72, 72, 1, 152064, 0x36a36d2b -0, 73, 73, 1, 152064, 0x3bd77543 -0, 74, 74, 1, 152064, 0x8fbddc41 -0, 75, 75, 1, 152064, 0xccc6e0a5 -0, 76, 76, 1, 152064, 0x00a9539e -0, 77, 77, 1, 152064, 0x07ba0714 -0, 78, 78, 1, 152064, 0xbab2735d -0, 79, 79, 1, 152064, 0x79cb5ba0 -0, 80, 80, 1, 152064, 0xdbcc1c92 -0, 81, 81, 1, 152064, 0xffec952c -0, 82, 82, 1, 152064, 0xc31ac68e -0, 83, 83, 1, 152064, 0x24293eb9 -0, 84, 84, 1, 152064, 0x7b9b2cb4 -0, 85, 85, 1, 152064, 0x9dd4fe95 -0, 86, 86, 1, 152064, 0xb62e8baf -0, 87, 87, 1, 152064, 0x9fefc174 -0, 88, 88, 1, 152064, 0xe027c24e -0, 89, 89, 1, 152064, 0xe38adc70 -0, 90, 90, 1, 152064, 0xc7bf536f -0, 91, 91, 1, 152064, 0x4448f330 -0, 92, 92, 1, 152064, 0x4dad5339 -0, 93, 93, 1, 152064, 0x48fbab15 -0, 94, 94, 1, 152064, 0xe6c97b2c -0, 95, 95, 1, 152064, 0x3c3829ee -0, 96, 96, 1, 152064, 0x927772c0 -0, 97, 97, 1, 152064, 0xbb0f0ef4 -0, 98, 98, 1, 152064, 0xe65780a7 -0, 99, 99, 1, 152064, 0xaf8f6d72 +0, 1, 1, 1, 152064, 0x3b21d6cd +0, 2, 2, 1, 152064, 0xc32088c6 +0, 3, 3, 1, 152064, 0x65a64cee +0, 4, 4, 1, 152064, 0x0bd45a5b +0, 5, 5, 1, 152064, 0xb2210d4d +0, 6, 6, 1, 152064, 0xf5b15527 +0, 7, 7, 1, 152064, 0x806572ad +0, 8, 8, 1, 152064, 0x6ecb1fc8 +0, 9, 9, 1, 152064, 0xc25e96d5 +0, 10, 10, 1, 152064, 0x5593b825 +0, 11, 11, 1, 152064, 0xf3be1cff +0, 12, 12, 1, 152064, 0xa9155072 +0, 13, 13, 1, 152064, 0xd5552e26 +0, 14, 14, 1, 152064, 0x7bf0dbee +0, 15, 15, 1, 152064, 0x998b4911 +0, 16, 16, 1, 152064, 0xcc71bbe0 +0, 17, 17, 1, 152064, 0x602415b8 +0, 18, 18, 1, 152064, 0xcfff37cf +0, 19, 19, 1, 152064, 0x7cf824a8 +0, 20, 20, 1, 152064, 0x34816ee5 +0, 21, 21, 1, 152064, 0x1480540c +0, 22, 22, 1, 152064, 0xc2351aaf +0, 23, 23, 1, 152064, 0x3b8eac9f +0, 24, 24, 1, 152064, 0x92a8faf8 +0, 25, 25, 1, 152064, 0x7b6121c8 +0, 26, 26, 1, 152064, 0xe73a3bac +0, 27, 27, 1, 152064, 0xcd6e1e36 +0, 28, 28, 1, 152064, 0xb24660b1 +0, 29, 29, 1, 152064, 0xa290ec25 +0, 30, 30, 1, 152064, 0x308915ff +0, 31, 31, 1, 152064, 0x1e8dd4db +0, 32, 32, 1, 152064, 0x1372f2e0 +0, 33, 33, 1, 152064, 0xa07cc1d0 +0, 34, 34, 1, 152064, 0x34bb872c +0, 35, 35, 1, 152064, 0x59e6a565 +0, 36, 36, 1, 152064, 0x9a097932 +0, 37, 37, 1, 152064, 0x938f2e20 +0, 38, 38, 1, 152064, 0x59a8157d +0, 39, 39, 1, 152064, 0x5cacd404 +0, 40, 40, 1, 152064, 0xdad068f5 +0, 41, 41, 1, 152064, 0x7ba67d47 +0, 42, 42, 1, 152064, 0xc2a11e2d +0, 43, 43, 1, 152064, 0xd37fdef7 +0, 44, 44, 1, 152064, 0x19a3f80a +0, 45, 45, 1, 152064, 0x7ec7426a +0, 46, 46, 1, 152064, 0x8ffedb61 +0, 47, 47, 1, 152064, 0x82aebdd0 +0, 48, 48, 1, 152064, 0xdfc920cc +0, 49, 49, 1, 152064, 0x2a467698 +0, 50, 50, 1, 152064, 0xd08a37d5 +0, 51, 51, 1, 152064, 0xe606e66a +0, 52, 52, 1, 152064, 0x0e7b8bd8 +0, 53, 53, 1, 152064, 0xf983c732 +0, 54, 54, 1, 152064, 0x9b82c2e7 +0, 55, 55, 1, 152064, 0xa990a47e +0, 56, 56, 1, 152064, 0x2d5679f1 +0, 57, 57, 1, 152064, 0x7f1c0201 +0, 58, 58, 1, 152064, 0xc38b709d +0, 59, 59, 1, 152064, 0x040246d8 +0, 60, 60, 1, 152064, 0xbc856021 +0, 61, 61, 1, 152064, 0x81e01a78 +0, 62, 62, 1, 152064, 0xaff1e7f1 +0, 63, 63, 1, 152064, 0x1fee7715 +0, 64, 64, 1, 152064, 0x65053711 +0, 65, 65, 1, 152064, 0x238a0118 +0, 66, 66, 1, 152064, 0x563491b4 +0, 67, 67, 1, 152064, 0x5974a6cc +0, 68, 68, 1, 152064, 0xd8682c35 +0, 69, 69, 1, 152064, 0x85c49e96 +0, 70, 70, 1, 152064, 0x29486faa +0, 71, 71, 1, 152064, 0x1a4f0579 +0, 72, 72, 1, 152064, 0x6ab86c2f +0, 73, 73, 1, 152064, 0x36a36d2b +0, 74, 74, 1, 152064, 0x3bd77543 +0, 75, 75, 1, 152064, 0x8fbddc41 +0, 76, 76, 1, 152064, 0xccc6e0a5 +0, 77, 77, 1, 152064, 0x00a9539e +0, 78, 78, 1, 152064, 0x07ba0714 +0, 79, 79, 1, 152064, 0xbab2735d +0, 80, 80, 1, 152064, 0x79cb5ba0 +0, 81, 81, 1, 152064, 0xdbcc1c92 +0, 82, 82, 1, 152064, 0xffec952c +0, 83, 83, 1, 152064, 0xc31ac68e +0, 84, 84, 1, 152064, 0x24293eb9 +0, 85, 85, 1, 152064, 0x7b9b2cb4 +0, 86, 86, 1, 152064, 0x9dd4fe95 +0, 87, 87, 1, 152064, 0xb62e8baf +0, 88, 88, 1, 152064, 0x9fefc174 +0, 89, 89, 1, 152064, 0xe027c24e +0, 90, 90, 1, 152064, 0xe38adc70 +0, 91, 91, 1, 152064, 0xc7bf536f +0, 92, 92, 1, 152064, 0x4448f330 +0, 93, 93, 1, 152064, 0x4dad5339 +0, 94, 94, 1, 152064, 0x48fbab15 +0, 95, 95, 1, 152064, 0xe6c97b2c +0, 96, 96, 1, 152064, 0x3c3829ee +0, 97, 97, 1, 152064, 0x927772c0 +0, 98, 98, 1, 152064, 0xbb0f0ef4 +0, 99, 99, 1, 152064, 0xe65780a7 +0, 100, 100, 1, 152064, 0xaf8f6d72 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-freh7_b ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-freh7_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-freh7_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-freh7_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,103 +3,103 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x89f2e8d5 -0, 1, 1, 1, 152064, 0x35b99397 -0, 2, 2, 1, 152064, 0x6ef46744 -0, 3, 3, 1, 152064, 0xec4d6c1c -0, 4, 4, 1, 152064, 0xad6e0c70 -0, 5, 5, 1, 152064, 0x2db534b3 -0, 6, 6, 1, 152064, 0xcbd25ddd -0, 7, 7, 1, 152064, 0xd90708b4 -0, 8, 8, 1, 152064, 0xc2aa52df -0, 9, 9, 1, 152064, 0xbcfc84dc -0, 10, 10, 1, 152064, 0xa5a6d269 -0, 11, 11, 1, 152064, 0x27220ce9 -0, 12, 12, 1, 152064, 0xf075ee6d -0, 13, 13, 1, 152064, 0x9fd3c2ac -0, 14, 14, 1, 152064, 0xcba24c2d -0, 15, 15, 1, 152064, 0x41cd9441 -0, 16, 16, 1, 152064, 0x0126efa3 -0, 17, 17, 1, 152064, 0xf62112af -0, 18, 18, 1, 152064, 0x35aff50f -0, 19, 19, 1, 152064, 0xcb0b276f -0, 20, 20, 1, 152064, 0xc7ef0214 -0, 21, 21, 1, 152064, 0x7f78d387 -0, 22, 22, 1, 152064, 0x266c673d -0, 23, 23, 1, 152064, 0x1d39c073 -0, 24, 24, 1, 152064, 0x6a3ae455 -0, 25, 25, 1, 152064, 0xe4ce0230 -0, 26, 26, 1, 152064, 0x7f95e87b -0, 27, 27, 1, 152064, 0x7c552236 -0, 28, 28, 1, 152064, 0x24c799b9 -0, 29, 29, 1, 152064, 0x5042d974 -0, 30, 30, 1, 152064, 0xe934a5b8 -0, 31, 31, 1, 152064, 0x6d59c884 -0, 32, 32, 1, 152064, 0xd00f7fdb -0, 33, 33, 1, 152064, 0x62ac3ebd -0, 34, 34, 1, 152064, 0xb40a6c25 -0, 35, 35, 1, 152064, 0x8706188c -0, 36, 36, 1, 152064, 0x7682e339 -0, 37, 37, 1, 152064, 0x1061d943 -0, 38, 38, 1, 152064, 0x50fa684a -0, 39, 39, 1, 152064, 0xab4b1975 -0, 40, 40, 1, 152064, 0x2d043acb -0, 41, 41, 1, 152064, 0xe3c2ec0a -0, 42, 42, 1, 152064, 0xb9bc99dc -0, 43, 43, 1, 152064, 0x051fb857 -0, 44, 44, 1, 152064, 0x71d1fe52 -0, 45, 45, 1, 152064, 0x4230c694 -0, 46, 46, 1, 152064, 0xb412a137 -0, 47, 47, 1, 152064, 0x2f50f90d -0, 48, 48, 1, 152064, 0x68a1466f -0, 49, 49, 1, 152064, 0x77e3f47b -0, 50, 50, 1, 152064, 0x4d08de2b -0, 51, 51, 1, 152064, 0x1fc663be -0, 52, 52, 1, 152064, 0x2c8ba712 -0, 53, 53, 1, 152064, 0xd50d85b9 -0, 54, 54, 1, 152064, 0xe8483437 -0, 55, 55, 1, 152064, 0x4e331e4c -0, 56, 56, 1, 152064, 0x0f64a7a0 -0, 57, 57, 1, 152064, 0x797b0b8c -0, 58, 58, 1, 152064, 0x1b91e6d8 -0, 59, 59, 1, 152064, 0xf3a1f3b6 -0, 60, 60, 1, 152064, 0x2b94bd52 -0, 61, 61, 1, 152064, 0x1f30962e -0, 62, 62, 1, 152064, 0x853321cf -0, 63, 63, 1, 152064, 0x8266c0ac -0, 64, 64, 1, 152064, 0x25498be0 -0, 65, 65, 1, 152064, 0x0f653af9 -0, 66, 66, 1, 152064, 0x0a025f7e -0, 67, 67, 1, 152064, 0x1cfbae04 -0, 68, 68, 1, 152064, 0x3a874757 -0, 69, 69, 1, 152064, 0x2c67006e -0, 70, 70, 1, 152064, 0x1d409bce -0, 71, 71, 1, 152064, 0xfe43121f -0, 72, 72, 1, 152064, 0x43411830 -0, 73, 73, 1, 152064, 0x536d26ca -0, 74, 74, 1, 152064, 0x9eb873ea -0, 75, 75, 1, 152064, 0x093f93ec -0, 76, 76, 1, 152064, 0xdf6f0381 -0, 77, 77, 1, 152064, 0xa9f4b5e5 -0, 78, 78, 1, 152064, 0x08f71ef8 -0, 79, 79, 1, 152064, 0x7a68f820 -0, 80, 80, 1, 152064, 0xae0c73e7 -0, 81, 81, 1, 152064, 0x886ae6c7 -0, 82, 82, 1, 152064, 0x9357f433 -0, 83, 83, 1, 152064, 0xcc335068 -0, 84, 84, 1, 152064, 0x2ea108ab -0, 85, 85, 1, 152064, 0x06d7dcb0 -0, 86, 86, 1, 152064, 0x81dc81bc -0, 87, 87, 1, 152064, 0xfb32b626 -0, 88, 88, 1, 152064, 0x2787d1c7 -0, 89, 89, 1, 152064, 0x69e51118 -0, 90, 90, 1, 152064, 0xba15d94d -0, 91, 91, 1, 152064, 0xc41c09cf -0, 92, 92, 1, 152064, 0x7e50e12f -0, 93, 93, 1, 152064, 0x0763ddbe -0, 94, 94, 1, 152064, 0x8a09bb88 -0, 95, 95, 1, 152064, 0x530752b7 -0, 96, 96, 1, 152064, 0x9b159923 -0, 97, 97, 1, 152064, 0xcbb83ed3 -0, 98, 98, 1, 152064, 0xdeb5ac0e -0, 99, 99, 1, 152064, 0x189299d4 +0, 1, 1, 1, 152064, 0x89f2e8d5 +0, 2, 2, 1, 152064, 0x35b99397 +0, 3, 3, 1, 152064, 0x6ef46744 +0, 4, 4, 1, 152064, 0xec4d6c1c +0, 5, 5, 1, 152064, 0xad6e0c70 +0, 6, 6, 1, 152064, 0x2db534b3 +0, 7, 7, 1, 152064, 0xcbd25ddd +0, 8, 8, 1, 152064, 0xd90708b4 +0, 9, 9, 1, 152064, 0xc2aa52df +0, 10, 10, 1, 152064, 0xbcfc84dc +0, 11, 11, 1, 152064, 0xa5a6d269 +0, 12, 12, 1, 152064, 0x27220ce9 +0, 13, 13, 1, 152064, 0xf075ee6d +0, 14, 14, 1, 152064, 0x9fd3c2ac +0, 15, 15, 1, 152064, 0xcba24c2d +0, 16, 16, 1, 152064, 0x41cd9441 +0, 17, 17, 1, 152064, 0x0126efa3 +0, 18, 18, 1, 152064, 0xf62112af +0, 19, 19, 1, 152064, 0x35aff50f +0, 20, 20, 1, 152064, 0xcb0b276f +0, 21, 21, 1, 152064, 0xc7ef0214 +0, 22, 22, 1, 152064, 0x7f78d387 +0, 23, 23, 1, 152064, 0x266c673d +0, 24, 24, 1, 152064, 0x1d39c073 +0, 25, 25, 1, 152064, 0x6a3ae455 +0, 26, 26, 1, 152064, 0xe4ce0230 +0, 27, 27, 1, 152064, 0x7f95e87b +0, 28, 28, 1, 152064, 0x7c552236 +0, 29, 29, 1, 152064, 0x24c799b9 +0, 30, 30, 1, 152064, 0x5042d974 +0, 31, 31, 1, 152064, 0xe934a5b8 +0, 32, 32, 1, 152064, 0x6d59c884 +0, 33, 33, 1, 152064, 0xd00f7fdb +0, 34, 34, 1, 152064, 0x62ac3ebd +0, 35, 35, 1, 152064, 0xb40a6c25 +0, 36, 36, 1, 152064, 0x8706188c +0, 37, 37, 1, 152064, 0x7682e339 +0, 38, 38, 1, 152064, 0x1061d943 +0, 39, 39, 1, 152064, 0x50fa684a +0, 40, 40, 1, 152064, 0xab4b1975 +0, 41, 41, 1, 152064, 0x2d043acb +0, 42, 42, 1, 152064, 0xe3c2ec0a +0, 43, 43, 1, 152064, 0xb9bc99dc +0, 44, 44, 1, 152064, 0x051fb857 +0, 45, 45, 1, 152064, 0x71d1fe52 +0, 46, 46, 1, 152064, 0x4230c694 +0, 47, 47, 1, 152064, 0xb412a137 +0, 48, 48, 1, 152064, 0x2f50f90d +0, 49, 49, 1, 152064, 0x68a1466f +0, 50, 50, 1, 152064, 0x77e3f47b +0, 51, 51, 1, 152064, 0x4d08de2b +0, 52, 52, 1, 152064, 0x1fc663be +0, 53, 53, 1, 152064, 0x2c8ba712 +0, 54, 54, 1, 152064, 0xd50d85b9 +0, 55, 55, 1, 152064, 0xe8483437 +0, 56, 56, 1, 152064, 0x4e331e4c +0, 57, 57, 1, 152064, 0x0f64a7a0 +0, 58, 58, 1, 152064, 0x797b0b8c +0, 59, 59, 1, 152064, 0x1b91e6d8 +0, 60, 60, 1, 152064, 0xf3a1f3b6 +0, 61, 61, 1, 152064, 0x2b94bd52 +0, 62, 62, 1, 152064, 0x1f30962e +0, 63, 63, 1, 152064, 0x853321cf +0, 64, 64, 1, 152064, 0x8266c0ac +0, 65, 65, 1, 152064, 0x25498be0 +0, 66, 66, 1, 152064, 0x0f653af9 +0, 67, 67, 1, 152064, 0x0a025f7e +0, 68, 68, 1, 152064, 0x1cfbae04 +0, 69, 69, 1, 152064, 0x3a874757 +0, 70, 70, 1, 152064, 0x2c67006e +0, 71, 71, 1, 152064, 0x1d409bce +0, 72, 72, 1, 152064, 0xfe43121f +0, 73, 73, 1, 152064, 0x43411830 +0, 74, 74, 1, 152064, 0x536d26ca +0, 75, 75, 1, 152064, 0x9eb873ea +0, 76, 76, 1, 152064, 0x093f93ec +0, 77, 77, 1, 152064, 0xdf6f0381 +0, 78, 78, 1, 152064, 0xa9f4b5e5 +0, 79, 79, 1, 152064, 0x08f71ef8 +0, 80, 80, 1, 152064, 0x7a68f820 +0, 81, 81, 1, 152064, 0xae0c73e7 +0, 82, 82, 1, 152064, 0x886ae6c7 +0, 83, 83, 1, 152064, 0x9357f433 +0, 84, 84, 1, 152064, 0xcc335068 +0, 85, 85, 1, 152064, 0x2ea108ab +0, 86, 86, 1, 152064, 0x06d7dcb0 +0, 87, 87, 1, 152064, 0x81dc81bc +0, 88, 88, 1, 152064, 0xfb32b626 +0, 89, 89, 1, 152064, 0x2787d1c7 +0, 90, 90, 1, 152064, 0x69e51118 +0, 91, 91, 1, 152064, 0xba15d94d +0, 92, 92, 1, 152064, 0xc41c09cf +0, 93, 93, 1, 152064, 0x7e50e12f +0, 94, 94, 1, 152064, 0x0763ddbe +0, 95, 95, 1, 152064, 0x8a09bb88 +0, 96, 96, 1, 152064, 0x530752b7 +0, 97, 97, 1, 152064, 0x9b159923 +0, 98, 98, 1, 152064, 0xcbb83ed3 +0, 99, 99, 1, 152064, 0xdeb5ac0e +0, 100, 100, 1, 152064, 0x189299d4 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-hcaff1_hhi_b ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-hcaff1_hhi_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-hcaff1_hhi_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-hcaff1_hhi_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,13 +3,13 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0xb055a9bd -0, 1, 1, 1, 152064, 0x9e1eadb6 -0, 2, 2, 1, 152064, 0x48f117d2 -0, 3, 3, 1, 152064, 0x3e3ff049 -0, 4, 4, 1, 152064, 0x2ff80943 -0, 5, 5, 1, 152064, 0xc5ee16a6 -0, 6, 6, 1, 152064, 0x38c33f28 -0, 7, 7, 1, 152064, 0x3e8444c7 -0, 8, 8, 1, 152064, 0x14ca4ab2 -0, 9, 9, 1, 152064, 0xe20e78f7 +0, 1, 1, 1, 152064, 0xb055a9bd +0, 2, 2, 1, 152064, 0x9e1eadb6 +0, 3, 3, 1, 152064, 0x48f117d2 +0, 4, 4, 1, 152064, 0x3e3ff049 +0, 5, 5, 1, 152064, 0x2ff80943 +0, 6, 6, 1, 152064, 0xc5ee16a6 +0, 7, 7, 1, 152064, 0x38c33f28 +0, 8, 8, 1, 152064, 0x3e8444c7 +0, 9, 9, 1, 152064, 0x14ca4ab2 +0, 10, 10, 1, 152064, 0xe20e78f7 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-hpcafl_bcrm_c ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-hpcafl_bcrm_c --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-hpcafl_bcrm_c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-hpcafl_bcrm_c 2021-04-08 21:28:40.000000000 +0000 @@ -3,303 +3,303 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x502ec077 -0, 1, 1, 1, 152064, 0x84807243 -0, 2, 2, 1, 152064, 0xd7474a6e -0, 3, 3, 1, 152064, 0x793469bb -0, 4, 4, 1, 152064, 0xb7a0faf7 -0, 5, 5, 1, 152064, 0x1d3d3cba -0, 6, 6, 1, 152064, 0xb62583de -0, 7, 7, 1, 152064, 0xc8422fb1 -0, 8, 8, 1, 152064, 0x321dc699 -0, 9, 9, 1, 152064, 0x7a34d350 -0, 10, 10, 1, 152064, 0xaa4c302d -0, 11, 11, 1, 152064, 0x45fa7ab0 -0, 12, 12, 1, 152064, 0xc7262e41 -0, 13, 13, 1, 152064, 0x3550000c -0, 14, 14, 1, 152064, 0xf4bab54b -0, 15, 15, 1, 152064, 0xaccf9c1a -0, 16, 16, 1, 152064, 0x9bee20e9 -0, 17, 17, 1, 152064, 0x47fb7720 -0, 18, 18, 1, 152064, 0x12c63ffb -0, 19, 19, 1, 152064, 0xfa2b8b4d -0, 20, 20, 1, 152064, 0x279964bd -0, 21, 21, 1, 152064, 0xb8b01c7e -0, 22, 22, 1, 152064, 0x816fa010 -0, 23, 23, 1, 152064, 0x59fe1c8c -0, 24, 24, 1, 152064, 0x13393fad -0, 25, 25, 1, 152064, 0x991a50a4 -0, 26, 26, 1, 152064, 0x57df3eb7 -0, 27, 27, 1, 152064, 0x744371df -0, 28, 28, 1, 152064, 0xe9f6d3ff -0, 29, 29, 1, 152064, 0xc506fba0 -0, 30, 30, 1, 152064, 0x6295b90e -0, 31, 31, 1, 152064, 0xa19cee2d -0, 32, 32, 1, 152064, 0xf8c1b3ca -0, 33, 33, 1, 152064, 0x69f68ce0 -0, 34, 34, 1, 152064, 0x80558bb6 -0, 35, 35, 1, 152064, 0x27824fa5 -0, 36, 36, 1, 152064, 0x27c929a1 -0, 37, 37, 1, 152064, 0xc0fe06d1 -0, 38, 38, 1, 152064, 0xc52bc58c -0, 39, 39, 1, 152064, 0x0a5363c7 -0, 40, 40, 1, 152064, 0xd0f45a0d -0, 41, 41, 1, 152064, 0x274710f9 -0, 42, 42, 1, 152064, 0x89d2d390 -0, 43, 43, 1, 152064, 0x12a9bfb0 -0, 44, 44, 1, 152064, 0x04501a93 -0, 45, 45, 1, 152064, 0xf92cbbf4 -0, 46, 46, 1, 152064, 0xf6d1b27d -0, 47, 47, 1, 152064, 0xe3e904c3 -0, 48, 48, 1, 152064, 0x58f8516d -0, 49, 49, 1, 152064, 0x70370c2b -0, 50, 50, 1, 152064, 0xfeebc88c -0, 51, 51, 1, 152064, 0x974c6ed6 -0, 52, 52, 1, 152064, 0x401bdcf2 -0, 53, 53, 1, 152064, 0xfe61e278 -0, 54, 54, 1, 152064, 0x96ba8bb9 -0, 55, 55, 1, 152064, 0x988492fd -0, 56, 56, 1, 152064, 0xd1d913a9 -0, 57, 57, 1, 152064, 0x6bc46f0e -0, 58, 58, 1, 152064, 0x695ef706 -0, 59, 59, 1, 152064, 0x142045c9 -0, 60, 60, 1, 152064, 0xb390ed87 -0, 61, 61, 1, 152064, 0xb9e6d2e5 -0, 62, 62, 1, 152064, 0xe348797f -0, 63, 63, 1, 152064, 0x1cbd29d6 -0, 64, 64, 1, 152064, 0xbd7dd694 -0, 65, 65, 1, 152064, 0x516873c3 -0, 66, 66, 1, 152064, 0x27bba182 -0, 67, 67, 1, 152064, 0x7541f920 -0, 68, 68, 1, 152064, 0xfdf67042 -0, 69, 69, 1, 152064, 0x6c3c7896 -0, 70, 70, 1, 152064, 0xed86c467 -0, 71, 71, 1, 152064, 0x4ea83ca2 -0, 72, 72, 1, 152064, 0xa3e6725b -0, 73, 73, 1, 152064, 0x917f5f16 -0, 74, 74, 1, 152064, 0x8cf2d2e1 -0, 75, 75, 1, 152064, 0x57a8d116 -0, 76, 76, 1, 152064, 0x0db267d4 -0, 77, 77, 1, 152064, 0xce782ac5 -0, 78, 78, 1, 152064, 0x1c9d8518 -0, 79, 79, 1, 152064, 0x47598ac7 -0, 80, 80, 1, 152064, 0xc5033d97 -0, 81, 81, 1, 152064, 0xd7aaa3a4 -0, 82, 82, 1, 152064, 0x078afc96 -0, 83, 83, 1, 152064, 0xc9fe673d -0, 84, 84, 1, 152064, 0xe9284066 -0, 85, 85, 1, 152064, 0xbc570982 -0, 86, 86, 1, 152064, 0x0aac8574 -0, 87, 87, 1, 152064, 0x098cbeee -0, 88, 88, 1, 152064, 0x19c36a9d -0, 89, 89, 1, 152064, 0x8fe4a893 -0, 90, 90, 1, 152064, 0x0b652f17 -0, 91, 91, 1, 152064, 0x10f2e6bf -0, 92, 92, 1, 152064, 0x7ce5634e -0, 93, 93, 1, 152064, 0x8fe4ac6c -0, 94, 94, 1, 152064, 0xcaba749e -0, 95, 95, 1, 152064, 0x5f8a0d5c -0, 96, 96, 1, 152064, 0xcaa66bbc -0, 97, 97, 1, 152064, 0xc87ae617 -0, 98, 98, 1, 152064, 0xe8ef4dd7 -0, 99, 99, 1, 152064, 0xdfca5a07 -0, 100, 100, 1, 152064, 0x5f7eab7d -0, 101, 101, 1, 152064, 0x8a65ebbb -0, 102, 102, 1, 152064, 0x4beab4a0 -0, 103, 103, 1, 152064, 0xb5e6ab30 -0, 104, 104, 1, 152064, 0x8fe4f4d4 -0, 105, 105, 1, 152064, 0x95bde1ca -0, 106, 106, 1, 152064, 0xcc5e3a53 -0, 107, 107, 1, 152064, 0xf09f1dd7 -0, 108, 108, 1, 152064, 0x10179672 -0, 109, 109, 1, 152064, 0x4ad16184 -0, 110, 110, 1, 152064, 0x9efa0e23 -0, 111, 111, 1, 152064, 0x22f59522 -0, 112, 112, 1, 152064, 0x4d38f09d -0, 113, 113, 1, 152064, 0x4c5ebf56 -0, 114, 114, 1, 152064, 0xb19d5077 -0, 115, 115, 1, 152064, 0xa98576b9 -0, 116, 116, 1, 152064, 0x65324239 -0, 117, 117, 1, 152064, 0x709e4031 -0, 118, 118, 1, 152064, 0xf8e81681 -0, 119, 119, 1, 152064, 0x058514e5 -0, 120, 120, 1, 152064, 0xd1d1c806 -0, 121, 121, 1, 152064, 0x0e4dde57 -0, 122, 122, 1, 152064, 0x49e9c2bb -0, 123, 123, 1, 152064, 0x01417ce6 -0, 124, 124, 1, 152064, 0xda7ebbf1 -0, 125, 125, 1, 152064, 0xa22906b7 -0, 126, 126, 1, 152064, 0x32e2df87 -0, 127, 127, 1, 152064, 0x69917c8f -0, 128, 128, 1, 152064, 0xea8ed2cc -0, 129, 129, 1, 152064, 0x0b8d57f1 -0, 130, 130, 1, 152064, 0x5f683bcd -0, 131, 131, 1, 152064, 0x5162fe2f -0, 132, 132, 1, 152064, 0x49c052f8 -0, 133, 133, 1, 152064, 0x990b69ba -0, 134, 134, 1, 152064, 0xa6d4f99f -0, 135, 135, 1, 152064, 0xe79ef4da -0, 136, 136, 1, 152064, 0x5e8a3847 -0, 137, 137, 1, 152064, 0x38b1e75f -0, 138, 138, 1, 152064, 0xf5c91bed -0, 139, 139, 1, 152064, 0xd59a6d26 -0, 140, 140, 1, 152064, 0xc361de06 -0, 141, 141, 1, 152064, 0x63ed2229 -0, 142, 142, 1, 152064, 0xb8229205 -0, 143, 143, 1, 152064, 0x7c6619af -0, 144, 144, 1, 152064, 0x4126b02f -0, 145, 145, 1, 152064, 0x9250b99b -0, 146, 146, 1, 152064, 0x589778f9 -0, 147, 147, 1, 152064, 0xed1fa45b -0, 148, 148, 1, 152064, 0x700b6f32 -0, 149, 149, 1, 152064, 0x0590df55 -0, 150, 150, 1, 152064, 0x3e9c4018 -0, 151, 151, 1, 152064, 0x957b8860 -0, 152, 152, 1, 152064, 0x56161560 -0, 153, 153, 1, 152064, 0xbc43bc3b -0, 154, 154, 1, 152064, 0x508d8632 -0, 155, 155, 1, 152064, 0xbc5736d8 -0, 156, 156, 1, 152064, 0xed7d3aef -0, 157, 157, 1, 152064, 0x1dcdda9f -0, 158, 158, 1, 152064, 0x8ef6d5c9 -0, 159, 159, 1, 152064, 0x15466acc -0, 160, 160, 1, 152064, 0x45d4cf67 -0, 161, 161, 1, 152064, 0x8c900b9d -0, 162, 162, 1, 152064, 0x747006e0 -0, 163, 163, 1, 152064, 0xac920a0c -0, 164, 164, 1, 152064, 0xb8210c27 -0, 165, 165, 1, 152064, 0x7dbb873a -0, 166, 166, 1, 152064, 0x0d4d7584 -0, 167, 167, 1, 152064, 0xefb3fe60 -0, 168, 168, 1, 152064, 0x905e2644 -0, 169, 169, 1, 152064, 0x7c04e534 -0, 170, 170, 1, 152064, 0x8889972a -0, 171, 171, 1, 152064, 0x21c7d8ad -0, 172, 172, 1, 152064, 0x1c641176 -0, 173, 173, 1, 152064, 0xf71489a4 -0, 174, 174, 1, 152064, 0xd7ac5555 -0, 175, 175, 1, 152064, 0xb4609c6d -0, 176, 176, 1, 152064, 0xf5b2bd5e -0, 177, 177, 1, 152064, 0x9f43ce57 -0, 178, 178, 1, 152064, 0x77642dd3 -0, 179, 179, 1, 152064, 0x3e79565c -0, 180, 180, 1, 152064, 0x95f40b8e -0, 181, 181, 1, 152064, 0x3c8ca4d4 -0, 182, 182, 1, 152064, 0xa02ac497 -0, 183, 183, 1, 152064, 0x4c93b377 -0, 184, 184, 1, 152064, 0x55f5ac68 -0, 185, 185, 1, 152064, 0xf8652eca -0, 186, 186, 1, 152064, 0x56e94574 -0, 187, 187, 1, 152064, 0x6d8302e1 -0, 188, 188, 1, 152064, 0x29a57061 -0, 189, 189, 1, 152064, 0x24e4cfdc -0, 190, 190, 1, 152064, 0xf5a5d62a -0, 191, 191, 1, 152064, 0x998870c1 -0, 192, 192, 1, 152064, 0xa15b1f4e -0, 193, 193, 1, 152064, 0xb0ccb51f -0, 194, 194, 1, 152064, 0xeaaf59ab -0, 195, 195, 1, 152064, 0x7e2b4fe6 -0, 196, 196, 1, 152064, 0x72299fea -0, 197, 197, 1, 152064, 0x769da8b2 -0, 198, 198, 1, 152064, 0xefad7ef8 -0, 199, 199, 1, 152064, 0x24819983 -0, 200, 200, 1, 152064, 0x2aad32ab -0, 201, 201, 1, 152064, 0xc80cac79 -0, 202, 202, 1, 152064, 0x1659d628 -0, 203, 203, 1, 152064, 0xef941f66 -0, 204, 204, 1, 152064, 0x0d7fcdb5 -0, 205, 205, 1, 152064, 0x7c1853fa -0, 206, 206, 1, 152064, 0xb94c4d3c -0, 207, 207, 1, 152064, 0xc47adfc2 -0, 208, 208, 1, 152064, 0x366a6729 -0, 209, 209, 1, 152064, 0x7eb37b70 -0, 210, 210, 1, 152064, 0xafd54c27 -0, 211, 211, 1, 152064, 0x67b18636 -0, 212, 212, 1, 152064, 0x93b22dcf -0, 213, 213, 1, 152064, 0xa64991f1 -0, 214, 214, 1, 152064, 0xd32a7102 -0, 215, 215, 1, 152064, 0xff665d1c -0, 216, 216, 1, 152064, 0xf107cc31 -0, 217, 217, 1, 152064, 0xf5b25652 -0, 218, 218, 1, 152064, 0x8caf783d -0, 219, 219, 1, 152064, 0x72f3eb00 -0, 220, 220, 1, 152064, 0xb5aea5f8 -0, 221, 221, 1, 152064, 0xee70e870 -0, 222, 222, 1, 152064, 0x7c3a0156 -0, 223, 223, 1, 152064, 0x871b6383 -0, 224, 224, 1, 152064, 0x48d831ff -0, 225, 225, 1, 152064, 0xca233913 -0, 226, 226, 1, 152064, 0xe14bc5eb -0, 227, 227, 1, 152064, 0x9b1d27e7 -0, 228, 228, 1, 152064, 0xfb9637f7 -0, 229, 229, 1, 152064, 0x0c022157 -0, 230, 230, 1, 152064, 0x16d35fc9 -0, 231, 231, 1, 152064, 0x6d935f71 -0, 232, 232, 1, 152064, 0xae4066fa -0, 233, 233, 1, 152064, 0xcef94fdc -0, 234, 234, 1, 152064, 0xc234edb9 -0, 235, 235, 1, 152064, 0x26a4f2e2 -0, 236, 236, 1, 152064, 0xd29ac23e -0, 237, 237, 1, 152064, 0xb7604395 -0, 238, 238, 1, 152064, 0x408084f6 -0, 239, 239, 1, 152064, 0x0a02026c -0, 240, 240, 1, 152064, 0x78b33c7c -0, 241, 241, 1, 152064, 0xcb02b874 -0, 242, 242, 1, 152064, 0xf566513b -0, 243, 243, 1, 152064, 0xb34e52b1 -0, 244, 244, 1, 152064, 0xf55ff493 -0, 245, 245, 1, 152064, 0xb0e8282a -0, 246, 246, 1, 152064, 0xe9510bbe -0, 247, 247, 1, 152064, 0x292e8c5a -0, 248, 248, 1, 152064, 0x62b9d2b0 -0, 249, 249, 1, 152064, 0x3a8cc827 -0, 250, 250, 1, 152064, 0x25cc465e -0, 251, 251, 1, 152064, 0xf2bc32e2 -0, 252, 252, 1, 152064, 0x6141f914 -0, 253, 253, 1, 152064, 0x1171256f -0, 254, 254, 1, 152064, 0x13cb2ded -0, 255, 255, 1, 152064, 0x3d4ca557 -0, 256, 256, 1, 152064, 0xf2b9e72e -0, 257, 257, 1, 152064, 0x03f7547a -0, 258, 258, 1, 152064, 0xc7302955 -0, 259, 259, 1, 152064, 0xe78a46d3 -0, 260, 260, 1, 152064, 0x3726a270 -0, 261, 261, 1, 152064, 0x2f65722a -0, 262, 262, 1, 152064, 0x55acce40 -0, 263, 263, 1, 152064, 0xf6fa9db2 -0, 264, 264, 1, 152064, 0x70a36937 -0, 265, 265, 1, 152064, 0x9313742d -0, 266, 266, 1, 152064, 0x2eb14e53 -0, 267, 267, 1, 152064, 0x3d47c9c3 -0, 268, 268, 1, 152064, 0xd0a90348 -0, 269, 269, 1, 152064, 0x6ad48088 -0, 270, 270, 1, 152064, 0x68e64738 -0, 271, 271, 1, 152064, 0x04c3735a -0, 272, 272, 1, 152064, 0x51d0593f -0, 273, 273, 1, 152064, 0x42cf2b48 -0, 274, 274, 1, 152064, 0xa5496a0c -0, 275, 275, 1, 152064, 0x84c25549 -0, 276, 276, 1, 152064, 0x96691600 -0, 277, 277, 1, 152064, 0x423135db -0, 278, 278, 1, 152064, 0x8d2e08b6 -0, 279, 279, 1, 152064, 0xaeb4c840 -0, 280, 280, 1, 152064, 0xf3e71780 -0, 281, 281, 1, 152064, 0x8858228b -0, 282, 282, 1, 152064, 0xf28613f8 -0, 283, 283, 1, 152064, 0xb5327882 -0, 284, 284, 1, 152064, 0xbb60bb85 -0, 285, 285, 1, 152064, 0x345ab1c9 -0, 286, 286, 1, 152064, 0x8aac2cba -0, 287, 287, 1, 152064, 0x7ce15b4c -0, 288, 288, 1, 152064, 0xc09c55c0 -0, 289, 289, 1, 152064, 0x8482ddd6 -0, 290, 290, 1, 152064, 0xab222a13 -0, 291, 291, 1, 152064, 0xd39b0dea -0, 292, 292, 1, 152064, 0x6dab6e06 -0, 293, 293, 1, 152064, 0xec0891bd -0, 294, 294, 1, 152064, 0x88bd9701 -0, 295, 295, 1, 152064, 0xdf13072a -0, 296, 296, 1, 152064, 0x23b33081 -0, 297, 297, 1, 152064, 0x63943137 -0, 298, 298, 1, 152064, 0xab6a9052 -0, 299, 299, 1, 152064, 0x05485494 +0, 1, 1, 1, 152064, 0x502ec077 +0, 2, 2, 1, 152064, 0x84807243 +0, 3, 3, 1, 152064, 0xd7474a6e +0, 4, 4, 1, 152064, 0x793469bb +0, 5, 5, 1, 152064, 0xb7a0faf7 +0, 6, 6, 1, 152064, 0x1d3d3cba +0, 7, 7, 1, 152064, 0xb62583de +0, 8, 8, 1, 152064, 0xc8422fb1 +0, 9, 9, 1, 152064, 0x321dc699 +0, 10, 10, 1, 152064, 0x7a34d350 +0, 11, 11, 1, 152064, 0xaa4c302d +0, 12, 12, 1, 152064, 0x45fa7ab0 +0, 13, 13, 1, 152064, 0xc7262e41 +0, 14, 14, 1, 152064, 0x3550000c +0, 15, 15, 1, 152064, 0xf4bab54b +0, 16, 16, 1, 152064, 0xaccf9c1a +0, 17, 17, 1, 152064, 0x9bee20e9 +0, 18, 18, 1, 152064, 0x47fb7720 +0, 19, 19, 1, 152064, 0x12c63ffb +0, 20, 20, 1, 152064, 0xfa2b8b4d +0, 21, 21, 1, 152064, 0x279964bd +0, 22, 22, 1, 152064, 0xb8b01c7e +0, 23, 23, 1, 152064, 0x816fa010 +0, 24, 24, 1, 152064, 0x59fe1c8c +0, 25, 25, 1, 152064, 0x13393fad +0, 26, 26, 1, 152064, 0x991a50a4 +0, 27, 27, 1, 152064, 0x57df3eb7 +0, 28, 28, 1, 152064, 0x744371df +0, 29, 29, 1, 152064, 0xe9f6d3ff +0, 30, 30, 1, 152064, 0xc506fba0 +0, 31, 31, 1, 152064, 0x6295b90e +0, 32, 32, 1, 152064, 0xa19cee2d +0, 33, 33, 1, 152064, 0xf8c1b3ca +0, 34, 34, 1, 152064, 0x69f68ce0 +0, 35, 35, 1, 152064, 0x80558bb6 +0, 36, 36, 1, 152064, 0x27824fa5 +0, 37, 37, 1, 152064, 0x27c929a1 +0, 38, 38, 1, 152064, 0xc0fe06d1 +0, 39, 39, 1, 152064, 0xc52bc58c +0, 40, 40, 1, 152064, 0x0a5363c7 +0, 41, 41, 1, 152064, 0xd0f45a0d +0, 42, 42, 1, 152064, 0x274710f9 +0, 43, 43, 1, 152064, 0x89d2d390 +0, 44, 44, 1, 152064, 0x12a9bfb0 +0, 45, 45, 1, 152064, 0x04501a93 +0, 46, 46, 1, 152064, 0xf92cbbf4 +0, 47, 47, 1, 152064, 0xf6d1b27d +0, 48, 48, 1, 152064, 0xe3e904c3 +0, 49, 49, 1, 152064, 0x58f8516d +0, 50, 50, 1, 152064, 0x70370c2b +0, 51, 51, 1, 152064, 0xfeebc88c +0, 52, 52, 1, 152064, 0x974c6ed6 +0, 53, 53, 1, 152064, 0x401bdcf2 +0, 54, 54, 1, 152064, 0xfe61e278 +0, 55, 55, 1, 152064, 0x96ba8bb9 +0, 56, 56, 1, 152064, 0x988492fd +0, 57, 57, 1, 152064, 0xd1d913a9 +0, 58, 58, 1, 152064, 0x6bc46f0e +0, 59, 59, 1, 152064, 0x695ef706 +0, 60, 60, 1, 152064, 0x142045c9 +0, 61, 61, 1, 152064, 0xb390ed87 +0, 62, 62, 1, 152064, 0xb9e6d2e5 +0, 63, 63, 1, 152064, 0xe348797f +0, 64, 64, 1, 152064, 0x1cbd29d6 +0, 65, 65, 1, 152064, 0xbd7dd694 +0, 66, 66, 1, 152064, 0x516873c3 +0, 67, 67, 1, 152064, 0x27bba182 +0, 68, 68, 1, 152064, 0x7541f920 +0, 69, 69, 1, 152064, 0xfdf67042 +0, 70, 70, 1, 152064, 0x6c3c7896 +0, 71, 71, 1, 152064, 0xed86c467 +0, 72, 72, 1, 152064, 0x4ea83ca2 +0, 73, 73, 1, 152064, 0xa3e6725b +0, 74, 74, 1, 152064, 0x917f5f16 +0, 75, 75, 1, 152064, 0x8cf2d2e1 +0, 76, 76, 1, 152064, 0x57a8d116 +0, 77, 77, 1, 152064, 0x0db267d4 +0, 78, 78, 1, 152064, 0xce782ac5 +0, 79, 79, 1, 152064, 0x1c9d8518 +0, 80, 80, 1, 152064, 0x47598ac7 +0, 81, 81, 1, 152064, 0xc5033d97 +0, 82, 82, 1, 152064, 0xd7aaa3a4 +0, 83, 83, 1, 152064, 0x078afc96 +0, 84, 84, 1, 152064, 0xc9fe673d +0, 85, 85, 1, 152064, 0xe9284066 +0, 86, 86, 1, 152064, 0xbc570982 +0, 87, 87, 1, 152064, 0x0aac8574 +0, 88, 88, 1, 152064, 0x098cbeee +0, 89, 89, 1, 152064, 0x19c36a9d +0, 90, 90, 1, 152064, 0x8fe4a893 +0, 91, 91, 1, 152064, 0x0b652f17 +0, 92, 92, 1, 152064, 0x10f2e6bf +0, 93, 93, 1, 152064, 0x7ce5634e +0, 94, 94, 1, 152064, 0x8fe4ac6c +0, 95, 95, 1, 152064, 0xcaba749e +0, 96, 96, 1, 152064, 0x5f8a0d5c +0, 97, 97, 1, 152064, 0xcaa66bbc +0, 98, 98, 1, 152064, 0xc87ae617 +0, 99, 99, 1, 152064, 0xe8ef4dd7 +0, 100, 100, 1, 152064, 0xdfca5a07 +0, 101, 101, 1, 152064, 0x5f7eab7d +0, 102, 102, 1, 152064, 0x8a65ebbb +0, 103, 103, 1, 152064, 0x4beab4a0 +0, 104, 104, 1, 152064, 0xb5e6ab30 +0, 105, 105, 1, 152064, 0x8fe4f4d4 +0, 106, 106, 1, 152064, 0x95bde1ca +0, 107, 107, 1, 152064, 0xcc5e3a53 +0, 108, 108, 1, 152064, 0xf09f1dd7 +0, 109, 109, 1, 152064, 0x10179672 +0, 110, 110, 1, 152064, 0x4ad16184 +0, 111, 111, 1, 152064, 0x9efa0e23 +0, 112, 112, 1, 152064, 0x22f59522 +0, 113, 113, 1, 152064, 0x4d38f09d +0, 114, 114, 1, 152064, 0x4c5ebf56 +0, 115, 115, 1, 152064, 0xb19d5077 +0, 116, 116, 1, 152064, 0xa98576b9 +0, 117, 117, 1, 152064, 0x65324239 +0, 118, 118, 1, 152064, 0x709e4031 +0, 119, 119, 1, 152064, 0xf8e81681 +0, 120, 120, 1, 152064, 0x058514e5 +0, 121, 121, 1, 152064, 0xd1d1c806 +0, 122, 122, 1, 152064, 0x0e4dde57 +0, 123, 123, 1, 152064, 0x49e9c2bb +0, 124, 124, 1, 152064, 0x01417ce6 +0, 125, 125, 1, 152064, 0xda7ebbf1 +0, 126, 126, 1, 152064, 0xa22906b7 +0, 127, 127, 1, 152064, 0x32e2df87 +0, 128, 128, 1, 152064, 0x69917c8f +0, 129, 129, 1, 152064, 0xea8ed2cc +0, 130, 130, 1, 152064, 0x0b8d57f1 +0, 131, 131, 1, 152064, 0x5f683bcd +0, 132, 132, 1, 152064, 0x5162fe2f +0, 133, 133, 1, 152064, 0x49c052f8 +0, 134, 134, 1, 152064, 0x990b69ba +0, 135, 135, 1, 152064, 0xa6d4f99f +0, 136, 136, 1, 152064, 0xe79ef4da +0, 137, 137, 1, 152064, 0x5e8a3847 +0, 138, 138, 1, 152064, 0x38b1e75f +0, 139, 139, 1, 152064, 0xf5c91bed +0, 140, 140, 1, 152064, 0xd59a6d26 +0, 141, 141, 1, 152064, 0xc361de06 +0, 142, 142, 1, 152064, 0x63ed2229 +0, 143, 143, 1, 152064, 0xb8229205 +0, 144, 144, 1, 152064, 0x7c6619af +0, 145, 145, 1, 152064, 0x4126b02f +0, 146, 146, 1, 152064, 0x9250b99b +0, 147, 147, 1, 152064, 0x589778f9 +0, 148, 148, 1, 152064, 0xed1fa45b +0, 149, 149, 1, 152064, 0x700b6f32 +0, 150, 150, 1, 152064, 0x0590df55 +0, 151, 151, 1, 152064, 0x3e9c4018 +0, 152, 152, 1, 152064, 0x957b8860 +0, 153, 153, 1, 152064, 0x56161560 +0, 154, 154, 1, 152064, 0xbc43bc3b +0, 155, 155, 1, 152064, 0x508d8632 +0, 156, 156, 1, 152064, 0xbc5736d8 +0, 157, 157, 1, 152064, 0xed7d3aef +0, 158, 158, 1, 152064, 0x1dcdda9f +0, 159, 159, 1, 152064, 0x8ef6d5c9 +0, 160, 160, 1, 152064, 0x15466acc +0, 161, 161, 1, 152064, 0x45d4cf67 +0, 162, 162, 1, 152064, 0x8c900b9d +0, 163, 163, 1, 152064, 0x747006e0 +0, 164, 164, 1, 152064, 0xac920a0c +0, 165, 165, 1, 152064, 0xb8210c27 +0, 166, 166, 1, 152064, 0x7dbb873a +0, 167, 167, 1, 152064, 0x0d4d7584 +0, 168, 168, 1, 152064, 0xefb3fe60 +0, 169, 169, 1, 152064, 0x905e2644 +0, 170, 170, 1, 152064, 0x7c04e534 +0, 171, 171, 1, 152064, 0x8889972a +0, 172, 172, 1, 152064, 0x21c7d8ad +0, 173, 173, 1, 152064, 0x1c641176 +0, 174, 174, 1, 152064, 0xf71489a4 +0, 175, 175, 1, 152064, 0xd7ac5555 +0, 176, 176, 1, 152064, 0xb4609c6d +0, 177, 177, 1, 152064, 0xf5b2bd5e +0, 178, 178, 1, 152064, 0x9f43ce57 +0, 179, 179, 1, 152064, 0x77642dd3 +0, 180, 180, 1, 152064, 0x3e79565c +0, 181, 181, 1, 152064, 0x95f40b8e +0, 182, 182, 1, 152064, 0x3c8ca4d4 +0, 183, 183, 1, 152064, 0xa02ac497 +0, 184, 184, 1, 152064, 0x4c93b377 +0, 185, 185, 1, 152064, 0x55f5ac68 +0, 186, 186, 1, 152064, 0xf8652eca +0, 187, 187, 1, 152064, 0x56e94574 +0, 188, 188, 1, 152064, 0x6d8302e1 +0, 189, 189, 1, 152064, 0x29a57061 +0, 190, 190, 1, 152064, 0x24e4cfdc +0, 191, 191, 1, 152064, 0xf5a5d62a +0, 192, 192, 1, 152064, 0x998870c1 +0, 193, 193, 1, 152064, 0xa15b1f4e +0, 194, 194, 1, 152064, 0xb0ccb51f +0, 195, 195, 1, 152064, 0xeaaf59ab +0, 196, 196, 1, 152064, 0x7e2b4fe6 +0, 197, 197, 1, 152064, 0x72299fea +0, 198, 198, 1, 152064, 0x769da8b2 +0, 199, 199, 1, 152064, 0xefad7ef8 +0, 200, 200, 1, 152064, 0x24819983 +0, 201, 201, 1, 152064, 0x2aad32ab +0, 202, 202, 1, 152064, 0xc80cac79 +0, 203, 203, 1, 152064, 0x1659d628 +0, 204, 204, 1, 152064, 0xef941f66 +0, 205, 205, 1, 152064, 0x0d7fcdb5 +0, 206, 206, 1, 152064, 0x7c1853fa +0, 207, 207, 1, 152064, 0xb94c4d3c +0, 208, 208, 1, 152064, 0xc47adfc2 +0, 209, 209, 1, 152064, 0x366a6729 +0, 210, 210, 1, 152064, 0x7eb37b70 +0, 211, 211, 1, 152064, 0xafd54c27 +0, 212, 212, 1, 152064, 0x67b18636 +0, 213, 213, 1, 152064, 0x93b22dcf +0, 214, 214, 1, 152064, 0xa64991f1 +0, 215, 215, 1, 152064, 0xd32a7102 +0, 216, 216, 1, 152064, 0xff665d1c +0, 217, 217, 1, 152064, 0xf107cc31 +0, 218, 218, 1, 152064, 0xf5b25652 +0, 219, 219, 1, 152064, 0x8caf783d +0, 220, 220, 1, 152064, 0x72f3eb00 +0, 221, 221, 1, 152064, 0xb5aea5f8 +0, 222, 222, 1, 152064, 0xee70e870 +0, 223, 223, 1, 152064, 0x7c3a0156 +0, 224, 224, 1, 152064, 0x871b6383 +0, 225, 225, 1, 152064, 0x48d831ff +0, 226, 226, 1, 152064, 0xca233913 +0, 227, 227, 1, 152064, 0xe14bc5eb +0, 228, 228, 1, 152064, 0x9b1d27e7 +0, 229, 229, 1, 152064, 0xfb9637f7 +0, 230, 230, 1, 152064, 0x0c022157 +0, 231, 231, 1, 152064, 0x16d35fc9 +0, 232, 232, 1, 152064, 0x6d935f71 +0, 233, 233, 1, 152064, 0xae4066fa +0, 234, 234, 1, 152064, 0xcef94fdc +0, 235, 235, 1, 152064, 0xc234edb9 +0, 236, 236, 1, 152064, 0x26a4f2e2 +0, 237, 237, 1, 152064, 0xd29ac23e +0, 238, 238, 1, 152064, 0xb7604395 +0, 239, 239, 1, 152064, 0x408084f6 +0, 240, 240, 1, 152064, 0x0a02026c +0, 241, 241, 1, 152064, 0x78b33c7c +0, 242, 242, 1, 152064, 0xcb02b874 +0, 243, 243, 1, 152064, 0xf566513b +0, 244, 244, 1, 152064, 0xb34e52b1 +0, 245, 245, 1, 152064, 0xf55ff493 +0, 246, 246, 1, 152064, 0xb0e8282a +0, 247, 247, 1, 152064, 0xe9510bbe +0, 248, 248, 1, 152064, 0x292e8c5a +0, 249, 249, 1, 152064, 0x62b9d2b0 +0, 250, 250, 1, 152064, 0x3a8cc827 +0, 251, 251, 1, 152064, 0x25cc465e +0, 252, 252, 1, 152064, 0xf2bc32e2 +0, 253, 253, 1, 152064, 0x6141f914 +0, 254, 254, 1, 152064, 0x1171256f +0, 255, 255, 1, 152064, 0x13cb2ded +0, 256, 256, 1, 152064, 0x3d4ca557 +0, 257, 257, 1, 152064, 0xf2b9e72e +0, 258, 258, 1, 152064, 0x03f7547a +0, 259, 259, 1, 152064, 0xc7302955 +0, 260, 260, 1, 152064, 0xe78a46d3 +0, 261, 261, 1, 152064, 0x3726a270 +0, 262, 262, 1, 152064, 0x2f65722a +0, 263, 263, 1, 152064, 0x55acce40 +0, 264, 264, 1, 152064, 0xf6fa9db2 +0, 265, 265, 1, 152064, 0x70a36937 +0, 266, 266, 1, 152064, 0x9313742d +0, 267, 267, 1, 152064, 0x2eb14e53 +0, 268, 268, 1, 152064, 0x3d47c9c3 +0, 269, 269, 1, 152064, 0xd0a90348 +0, 270, 270, 1, 152064, 0x6ad48088 +0, 271, 271, 1, 152064, 0x68e64738 +0, 272, 272, 1, 152064, 0x04c3735a +0, 273, 273, 1, 152064, 0x51d0593f +0, 274, 274, 1, 152064, 0x42cf2b48 +0, 275, 275, 1, 152064, 0xa5496a0c +0, 276, 276, 1, 152064, 0x84c25549 +0, 277, 277, 1, 152064, 0x96691600 +0, 278, 278, 1, 152064, 0x423135db +0, 279, 279, 1, 152064, 0x8d2e08b6 +0, 280, 280, 1, 152064, 0xaeb4c840 +0, 281, 281, 1, 152064, 0xf3e71780 +0, 282, 282, 1, 152064, 0x8858228b +0, 283, 283, 1, 152064, 0xf28613f8 +0, 284, 284, 1, 152064, 0xb5327882 +0, 285, 285, 1, 152064, 0xbb60bb85 +0, 286, 286, 1, 152064, 0x345ab1c9 +0, 287, 287, 1, 152064, 0x8aac2cba +0, 288, 288, 1, 152064, 0x7ce15b4c +0, 289, 289, 1, 152064, 0xc09c55c0 +0, 290, 290, 1, 152064, 0x8482ddd6 +0, 291, 291, 1, 152064, 0xab222a13 +0, 292, 292, 1, 152064, 0xd39b0dea +0, 293, 293, 1, 152064, 0x6dab6e06 +0, 294, 294, 1, 152064, 0xec0891bd +0, 295, 295, 1, 152064, 0x88bd9701 +0, 296, 296, 1, 152064, 0xdf13072a +0, 297, 297, 1, 152064, 0x23b33081 +0, 298, 298, 1, 152064, 0x63943137 +0, 299, 299, 1, 152064, 0xab6a9052 +0, 300, 300, 1, 152064, 0x05485494 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-hpcaflnl_bcrm_c ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-hpcaflnl_bcrm_c --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-hpcaflnl_bcrm_c 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-hpcaflnl_bcrm_c 2021-04-08 21:28:40.000000000 +0000 @@ -3,303 +3,303 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x3e39c08b -0, 1, 1, 1, 152064, 0xabc67990 -0, 2, 2, 1, 152064, 0x19614e74 -0, 3, 3, 1, 152064, 0xa3776beb -0, 4, 4, 1, 152064, 0xcce6ffdf -0, 5, 5, 1, 152064, 0xb0e94746 -0, 6, 6, 1, 152064, 0xdb1a84ef -0, 7, 7, 1, 152064, 0xb2624509 -0, 8, 8, 1, 152064, 0x32e2d826 -0, 9, 9, 1, 152064, 0xb3bddf0b -0, 10, 10, 1, 152064, 0x2e273ce3 -0, 11, 11, 1, 152064, 0x67af7e4d -0, 12, 12, 1, 152064, 0x505c3261 -0, 13, 13, 1, 152064, 0xa43d015e -0, 14, 14, 1, 152064, 0xad41c1f6 -0, 15, 15, 1, 152064, 0x633ba55f -0, 16, 16, 1, 152064, 0xe80634f0 -0, 17, 17, 1, 152064, 0x80a07dc9 -0, 18, 18, 1, 152064, 0x0e7a3bbf -0, 19, 19, 1, 152064, 0xcb099196 -0, 20, 20, 1, 152064, 0x57c96db5 -0, 21, 21, 1, 152064, 0xccd422fa -0, 22, 22, 1, 152064, 0x0850b7a7 -0, 23, 23, 1, 152064, 0x30e33156 -0, 24, 24, 1, 152064, 0x34e13f9a -0, 25, 25, 1, 152064, 0x03d36000 -0, 26, 26, 1, 152064, 0xbf7d49da -0, 27, 27, 1, 152064, 0x77336d09 -0, 28, 28, 1, 152064, 0xca8be5a9 -0, 29, 29, 1, 152064, 0xe57c0b08 -0, 30, 30, 1, 152064, 0xbe77c093 -0, 31, 31, 1, 152064, 0x6bf1ff05 -0, 32, 32, 1, 152064, 0x9142babf -0, 33, 33, 1, 152064, 0x08db8e67 -0, 34, 34, 1, 152064, 0x69ac8cb6 -0, 35, 35, 1, 152064, 0xaa3b5c88 -0, 36, 36, 1, 152064, 0x9bd32638 -0, 37, 37, 1, 152064, 0x7972115a -0, 38, 38, 1, 152064, 0x5c1dd47b -0, 39, 39, 1, 152064, 0x8a196e02 -0, 40, 40, 1, 152064, 0xa89672bc -0, 41, 41, 1, 152064, 0x27b220e4 -0, 42, 42, 1, 152064, 0xfa38dc4a -0, 43, 43, 1, 152064, 0x4784c639 -0, 44, 44, 1, 152064, 0xa5e4229a -0, 45, 45, 1, 152064, 0xa986bdfc -0, 46, 46, 1, 152064, 0x2951b47b -0, 47, 47, 1, 152064, 0x4df404a6 -0, 48, 48, 1, 152064, 0xc75155e8 -0, 49, 49, 1, 152064, 0xfc05248c -0, 50, 50, 1, 152064, 0x5d53da10 -0, 51, 51, 1, 152064, 0x284376ec -0, 52, 52, 1, 152064, 0x19fce380 -0, 53, 53, 1, 152064, 0x876be6c9 -0, 54, 54, 1, 152064, 0x39eb8ff9 -0, 55, 55, 1, 152064, 0x289c9543 -0, 56, 56, 1, 152064, 0x24dd2356 -0, 57, 57, 1, 152064, 0x1dc17d3c -0, 58, 58, 1, 152064, 0xd17c00ac -0, 59, 59, 1, 152064, 0xc2ad54de -0, 60, 60, 1, 152064, 0xbe11ee2f -0, 61, 61, 1, 152064, 0x3db9dc89 -0, 62, 62, 1, 152064, 0xac0d7bc2 -0, 63, 63, 1, 152064, 0x8dab2dde -0, 64, 64, 1, 152064, 0x566ad225 -0, 65, 65, 1, 152064, 0x587c7853 -0, 66, 66, 1, 152064, 0x601c9c80 -0, 67, 67, 1, 152064, 0x2afaf751 -0, 68, 68, 1, 152064, 0x1c9f7e3a -0, 69, 69, 1, 152064, 0x899475bf -0, 70, 70, 1, 152064, 0x0d65c7d9 -0, 71, 71, 1, 152064, 0xafd63d12 -0, 72, 72, 1, 152064, 0x162e62b9 -0, 73, 73, 1, 152064, 0x5c9554be -0, 74, 74, 1, 152064, 0x35fbdaa2 -0, 75, 75, 1, 152064, 0x6438cbd8 -0, 76, 76, 1, 152064, 0xde0772c9 -0, 77, 77, 1, 152064, 0x79f82854 -0, 78, 78, 1, 152064, 0x86957840 -0, 79, 79, 1, 152064, 0xd9468cbf -0, 80, 80, 1, 152064, 0x23e74609 -0, 81, 81, 1, 152064, 0x3919a146 -0, 82, 82, 1, 152064, 0xd641078b -0, 83, 83, 1, 152064, 0x24397220 -0, 84, 84, 1, 152064, 0xe7fc3a7c -0, 85, 85, 1, 152064, 0x3997154a -0, 86, 86, 1, 152064, 0x2af3952c -0, 87, 87, 1, 152064, 0x274ac07a -0, 88, 88, 1, 152064, 0x288f7b09 -0, 89, 89, 1, 152064, 0xe6f9b022 -0, 90, 90, 1, 152064, 0xf09e2fbb -0, 91, 91, 1, 152064, 0x7244e477 -0, 92, 92, 1, 152064, 0x0dfc72eb -0, 93, 93, 1, 152064, 0x0322b21f -0, 94, 94, 1, 152064, 0x18b08205 -0, 95, 95, 1, 152064, 0x6606153e -0, 96, 96, 1, 152064, 0x85186272 -0, 97, 97, 1, 152064, 0x3369f064 -0, 98, 98, 1, 152064, 0xbe0d5a44 -0, 99, 99, 1, 152064, 0x320258bb -0, 100, 100, 1, 152064, 0x4d6fb091 -0, 101, 101, 1, 152064, 0xc9bbf5e7 -0, 102, 102, 1, 152064, 0x0aa1b69b -0, 103, 103, 1, 152064, 0x85b9ac11 -0, 104, 104, 1, 152064, 0xb25ff818 -0, 105, 105, 1, 152064, 0xa155dc25 -0, 106, 106, 1, 152064, 0xa8e03bfd -0, 107, 107, 1, 152064, 0x0a862956 -0, 108, 108, 1, 152064, 0x11b49264 -0, 109, 109, 1, 152064, 0xa94e664e -0, 110, 110, 1, 152064, 0x330e0fa2 -0, 111, 111, 1, 152064, 0xaf3d9518 -0, 112, 112, 1, 152064, 0x0836f2e8 -0, 113, 113, 1, 152064, 0xbf6dc578 -0, 114, 114, 1, 152064, 0x7b524d20 -0, 115, 115, 1, 152064, 0x9ef7677f -0, 116, 116, 1, 152064, 0xeacf3f34 -0, 117, 117, 1, 152064, 0xfb4e3dbe -0, 118, 118, 1, 152064, 0xb46e25cb -0, 119, 119, 1, 152064, 0x363c1603 -0, 120, 120, 1, 152064, 0x263fc542 -0, 121, 121, 1, 152064, 0xf106e548 -0, 122, 122, 1, 152064, 0xde43c56a -0, 123, 123, 1, 152064, 0xc2c4770a -0, 124, 124, 1, 152064, 0x122fce19 -0, 125, 125, 1, 152064, 0x3ba01434 -0, 126, 126, 1, 152064, 0x0e8ce5ee -0, 127, 127, 1, 152064, 0x6ceb82e1 -0, 128, 128, 1, 152064, 0xa23ee21c -0, 129, 129, 1, 152064, 0xc6d960f9 -0, 130, 130, 1, 152064, 0x0de15258 -0, 131, 131, 1, 152064, 0x187b0333 -0, 132, 132, 1, 152064, 0x92e6582f -0, 133, 133, 1, 152064, 0xb9586ce0 -0, 134, 134, 1, 152064, 0xefd803b5 -0, 135, 135, 1, 152064, 0x24eafb29 -0, 136, 136, 1, 152064, 0x20c73b14 -0, 137, 137, 1, 152064, 0xbd7ceaaa -0, 138, 138, 1, 152064, 0x775216c8 -0, 139, 139, 1, 152064, 0xa08971c7 -0, 140, 140, 1, 152064, 0xef0ee865 -0, 141, 141, 1, 152064, 0x9ac61c2f -0, 142, 142, 1, 152064, 0x52ae8ea9 -0, 143, 143, 1, 152064, 0x06571c14 -0, 144, 144, 1, 152064, 0x6e78ad33 -0, 145, 145, 1, 152064, 0xad01c627 -0, 146, 146, 1, 152064, 0xbfe074d3 -0, 147, 147, 1, 152064, 0x9357a183 -0, 148, 148, 1, 152064, 0x8de7767f -0, 149, 149, 1, 152064, 0xa5e6e76e -0, 150, 150, 1, 152064, 0xa6f646fe -0, 151, 151, 1, 152064, 0x132e99f8 -0, 152, 152, 1, 152064, 0xb79f27de -0, 153, 153, 1, 152064, 0x36d3cdcf -0, 154, 154, 1, 152064, 0xdc938336 -0, 155, 155, 1, 152064, 0xacaa3a7f -0, 156, 156, 1, 152064, 0xc61a37fd -0, 157, 157, 1, 152064, 0x4fe1ddf0 -0, 158, 158, 1, 152064, 0xc0f7d660 -0, 159, 159, 1, 152064, 0xd72458ea -0, 160, 160, 1, 152064, 0x6978d123 -0, 161, 161, 1, 152064, 0x64e60ccf -0, 162, 162, 1, 152064, 0xaa07004c -0, 163, 163, 1, 152064, 0x07cd1064 -0, 164, 164, 1, 152064, 0xa82320e5 -0, 165, 165, 1, 152064, 0xaedd8d30 -0, 166, 166, 1, 152064, 0x79b082ea -0, 167, 167, 1, 152064, 0x9ed800ab -0, 168, 168, 1, 152064, 0xde592bb4 -0, 169, 169, 1, 152064, 0xd966df88 -0, 170, 170, 1, 152064, 0xf921988a -0, 171, 171, 1, 152064, 0x557ad9ae -0, 172, 172, 1, 152064, 0xc3f31a9a -0, 173, 173, 1, 152064, 0x65248561 -0, 174, 174, 1, 152064, 0x63df4aa6 -0, 175, 175, 1, 152064, 0x618da0a9 -0, 176, 176, 1, 152064, 0xe6f1c435 -0, 177, 177, 1, 152064, 0x9f90c38f -0, 178, 178, 1, 152064, 0xd2853e14 -0, 179, 179, 1, 152064, 0x6e0268a9 -0, 180, 180, 1, 152064, 0x393712d1 -0, 181, 181, 1, 152064, 0x470da25f -0, 182, 182, 1, 152064, 0xaf55cb3d -0, 183, 183, 1, 152064, 0x6935b8b9 -0, 184, 184, 1, 152064, 0x5409a15f -0, 185, 185, 1, 152064, 0x09073fee -0, 186, 186, 1, 152064, 0xfb274e82 -0, 187, 187, 1, 152064, 0x1a770581 -0, 188, 188, 1, 152064, 0x17277d0d -0, 189, 189, 1, 152064, 0xd4dcd982 -0, 190, 190, 1, 152064, 0x6b04eaf3 -0, 191, 191, 1, 152064, 0x8a3d822e -0, 192, 192, 1, 152064, 0x1b971ec9 -0, 193, 193, 1, 152064, 0x14e0c0f6 -0, 194, 194, 1, 152064, 0x00667450 -0, 195, 195, 1, 152064, 0xd2385902 -0, 196, 196, 1, 152064, 0x905da6ab -0, 197, 197, 1, 152064, 0xa3ffb18b -0, 198, 198, 1, 152064, 0x10d48b19 -0, 199, 199, 1, 152064, 0xb2c7a3bd -0, 200, 200, 1, 152064, 0x45593e96 -0, 201, 201, 1, 152064, 0x47a0b60c -0, 202, 202, 1, 152064, 0x68c6d1b9 -0, 203, 203, 1, 152064, 0xbc881fcc -0, 204, 204, 1, 152064, 0x422cc6f2 -0, 205, 205, 1, 152064, 0x9b686410 -0, 206, 206, 1, 152064, 0x35dc5e86 -0, 207, 207, 1, 152064, 0x247bedaa -0, 208, 208, 1, 152064, 0x22b76fd1 -0, 209, 209, 1, 152064, 0x67cc7a75 -0, 210, 210, 1, 152064, 0xa197521e -0, 211, 211, 1, 152064, 0x428c8662 -0, 212, 212, 1, 152064, 0x33dc2c73 -0, 213, 213, 1, 152064, 0x5b538903 -0, 214, 214, 1, 152064, 0x3c4176b6 -0, 215, 215, 1, 152064, 0x774364ba -0, 216, 216, 1, 152064, 0xf237d03e -0, 217, 217, 1, 152064, 0xac8746fb -0, 218, 218, 1, 152064, 0x6b306a84 -0, 219, 219, 1, 152064, 0xa2ace513 -0, 220, 220, 1, 152064, 0x709c9be7 -0, 221, 221, 1, 152064, 0x2403f373 -0, 222, 222, 1, 152064, 0x147bf717 -0, 223, 223, 1, 152064, 0xe58964c8 -0, 224, 224, 1, 152064, 0xa0da36fc -0, 225, 225, 1, 152064, 0x1ac1355c -0, 226, 226, 1, 152064, 0x8a31c9f2 -0, 227, 227, 1, 152064, 0x42ba205c -0, 228, 228, 1, 152064, 0xa11b3575 -0, 229, 229, 1, 152064, 0xcb35207c -0, 230, 230, 1, 152064, 0x528f6189 -0, 231, 231, 1, 152064, 0x34f05bd7 -0, 232, 232, 1, 152064, 0x72317356 -0, 233, 233, 1, 152064, 0xaabd5028 -0, 234, 234, 1, 152064, 0x13dbeb7b -0, 235, 235, 1, 152064, 0x62f1e8a8 -0, 236, 236, 1, 152064, 0x1723bfcd -0, 237, 237, 1, 152064, 0x5c083c00 -0, 238, 238, 1, 152064, 0x52137894 -0, 239, 239, 1, 152064, 0xef1e082c -0, 240, 240, 1, 152064, 0x664b3d53 -0, 241, 241, 1, 152064, 0x2eb9b296 -0, 242, 242, 1, 152064, 0xd0ca511e -0, 243, 243, 1, 152064, 0x012d4724 -0, 244, 244, 1, 152064, 0xa847f5af -0, 245, 245, 1, 152064, 0x483a2fde -0, 246, 246, 1, 152064, 0xd1ab0257 -0, 247, 247, 1, 152064, 0x414692c7 -0, 248, 248, 1, 152064, 0x0b79df88 -0, 249, 249, 1, 152064, 0xdaa2c4a3 -0, 250, 250, 1, 152064, 0xd1b44500 -0, 251, 251, 1, 152064, 0xfd3d2cf3 -0, 252, 252, 1, 152064, 0xfdc0f748 -0, 253, 253, 1, 152064, 0xce762a2a -0, 254, 254, 1, 152064, 0x08b63572 -0, 255, 255, 1, 152064, 0x5a46a38d -0, 256, 256, 1, 152064, 0x03cee9c0 -0, 257, 257, 1, 152064, 0x9ee45473 -0, 258, 258, 1, 152064, 0x5a432386 -0, 259, 259, 1, 152064, 0x54c83d87 -0, 260, 260, 1, 152064, 0xc9caa1de -0, 261, 261, 1, 152064, 0xa28367f1 -0, 262, 262, 1, 152064, 0x2607cdf1 -0, 263, 263, 1, 152064, 0x06baa8de -0, 264, 264, 1, 152064, 0xf5346e32 -0, 265, 265, 1, 152064, 0x6d3e732b -0, 266, 266, 1, 152064, 0x798c584b -0, 267, 267, 1, 152064, 0x4076c948 -0, 268, 268, 1, 152064, 0x868cf63a -0, 269, 269, 1, 152064, 0x23107ac5 -0, 270, 270, 1, 152064, 0x306f3fe2 -0, 271, 271, 1, 152064, 0xbd1d71d6 -0, 272, 272, 1, 152064, 0x1429545f -0, 273, 273, 1, 152064, 0xaded29aa -0, 274, 274, 1, 152064, 0x9b455a94 -0, 275, 275, 1, 152064, 0xb3774ce7 -0, 276, 276, 1, 152064, 0x92580986 -0, 277, 277, 1, 152064, 0x0eae2f95 -0, 278, 278, 1, 152064, 0x599208b2 -0, 279, 279, 1, 152064, 0x4804c04c -0, 280, 280, 1, 152064, 0x5f730e8f -0, 281, 281, 1, 152064, 0x3e501d1e -0, 282, 282, 1, 152064, 0x32100740 -0, 283, 283, 1, 152064, 0x62226ff8 -0, 284, 284, 1, 152064, 0x7683b622 -0, 285, 285, 1, 152064, 0xc3e0aec1 -0, 286, 286, 1, 152064, 0xfac12608 -0, 287, 287, 1, 152064, 0xb21a5781 -0, 288, 288, 1, 152064, 0x8f1e4964 -0, 289, 289, 1, 152064, 0x0f62dd6e -0, 290, 290, 1, 152064, 0xac062ac4 -0, 291, 291, 1, 152064, 0x1b320f7a -0, 292, 292, 1, 152064, 0x346e7211 -0, 293, 293, 1, 152064, 0xe47592f3 -0, 294, 294, 1, 152064, 0xa3a7919c -0, 295, 295, 1, 152064, 0xa3580fa6 -0, 296, 296, 1, 152064, 0xc73430c1 -0, 297, 297, 1, 152064, 0x994a2c18 -0, 298, 298, 1, 152064, 0x0b5d8d45 -0, 299, 299, 1, 152064, 0x9eed5109 +0, 1, 1, 1, 152064, 0x3e39c08b +0, 2, 2, 1, 152064, 0xabc67990 +0, 3, 3, 1, 152064, 0x19614e74 +0, 4, 4, 1, 152064, 0xa3776beb +0, 5, 5, 1, 152064, 0xcce6ffdf +0, 6, 6, 1, 152064, 0xb0e94746 +0, 7, 7, 1, 152064, 0xdb1a84ef +0, 8, 8, 1, 152064, 0xb2624509 +0, 9, 9, 1, 152064, 0x32e2d826 +0, 10, 10, 1, 152064, 0xb3bddf0b +0, 11, 11, 1, 152064, 0x2e273ce3 +0, 12, 12, 1, 152064, 0x67af7e4d +0, 13, 13, 1, 152064, 0x505c3261 +0, 14, 14, 1, 152064, 0xa43d015e +0, 15, 15, 1, 152064, 0xad41c1f6 +0, 16, 16, 1, 152064, 0x633ba55f +0, 17, 17, 1, 152064, 0xe80634f0 +0, 18, 18, 1, 152064, 0x80a07dc9 +0, 19, 19, 1, 152064, 0x0e7a3bbf +0, 20, 20, 1, 152064, 0xcb099196 +0, 21, 21, 1, 152064, 0x57c96db5 +0, 22, 22, 1, 152064, 0xccd422fa +0, 23, 23, 1, 152064, 0x0850b7a7 +0, 24, 24, 1, 152064, 0x30e33156 +0, 25, 25, 1, 152064, 0x34e13f9a +0, 26, 26, 1, 152064, 0x03d36000 +0, 27, 27, 1, 152064, 0xbf7d49da +0, 28, 28, 1, 152064, 0x77336d09 +0, 29, 29, 1, 152064, 0xca8be5a9 +0, 30, 30, 1, 152064, 0xe57c0b08 +0, 31, 31, 1, 152064, 0xbe77c093 +0, 32, 32, 1, 152064, 0x6bf1ff05 +0, 33, 33, 1, 152064, 0x9142babf +0, 34, 34, 1, 152064, 0x08db8e67 +0, 35, 35, 1, 152064, 0x69ac8cb6 +0, 36, 36, 1, 152064, 0xaa3b5c88 +0, 37, 37, 1, 152064, 0x9bd32638 +0, 38, 38, 1, 152064, 0x7972115a +0, 39, 39, 1, 152064, 0x5c1dd47b +0, 40, 40, 1, 152064, 0x8a196e02 +0, 41, 41, 1, 152064, 0xa89672bc +0, 42, 42, 1, 152064, 0x27b220e4 +0, 43, 43, 1, 152064, 0xfa38dc4a +0, 44, 44, 1, 152064, 0x4784c639 +0, 45, 45, 1, 152064, 0xa5e4229a +0, 46, 46, 1, 152064, 0xa986bdfc +0, 47, 47, 1, 152064, 0x2951b47b +0, 48, 48, 1, 152064, 0x4df404a6 +0, 49, 49, 1, 152064, 0xc75155e8 +0, 50, 50, 1, 152064, 0xfc05248c +0, 51, 51, 1, 152064, 0x5d53da10 +0, 52, 52, 1, 152064, 0x284376ec +0, 53, 53, 1, 152064, 0x19fce380 +0, 54, 54, 1, 152064, 0x876be6c9 +0, 55, 55, 1, 152064, 0x39eb8ff9 +0, 56, 56, 1, 152064, 0x289c9543 +0, 57, 57, 1, 152064, 0x24dd2356 +0, 58, 58, 1, 152064, 0x1dc17d3c +0, 59, 59, 1, 152064, 0xd17c00ac +0, 60, 60, 1, 152064, 0xc2ad54de +0, 61, 61, 1, 152064, 0xbe11ee2f +0, 62, 62, 1, 152064, 0x3db9dc89 +0, 63, 63, 1, 152064, 0xac0d7bc2 +0, 64, 64, 1, 152064, 0x8dab2dde +0, 65, 65, 1, 152064, 0x566ad225 +0, 66, 66, 1, 152064, 0x587c7853 +0, 67, 67, 1, 152064, 0x601c9c80 +0, 68, 68, 1, 152064, 0x2afaf751 +0, 69, 69, 1, 152064, 0x1c9f7e3a +0, 70, 70, 1, 152064, 0x899475bf +0, 71, 71, 1, 152064, 0x0d65c7d9 +0, 72, 72, 1, 152064, 0xafd63d12 +0, 73, 73, 1, 152064, 0x162e62b9 +0, 74, 74, 1, 152064, 0x5c9554be +0, 75, 75, 1, 152064, 0x35fbdaa2 +0, 76, 76, 1, 152064, 0x6438cbd8 +0, 77, 77, 1, 152064, 0xde0772c9 +0, 78, 78, 1, 152064, 0x79f82854 +0, 79, 79, 1, 152064, 0x86957840 +0, 80, 80, 1, 152064, 0xd9468cbf +0, 81, 81, 1, 152064, 0x23e74609 +0, 82, 82, 1, 152064, 0x3919a146 +0, 83, 83, 1, 152064, 0xd641078b +0, 84, 84, 1, 152064, 0x24397220 +0, 85, 85, 1, 152064, 0xe7fc3a7c +0, 86, 86, 1, 152064, 0x3997154a +0, 87, 87, 1, 152064, 0x2af3952c +0, 88, 88, 1, 152064, 0x274ac07a +0, 89, 89, 1, 152064, 0x288f7b09 +0, 90, 90, 1, 152064, 0xe6f9b022 +0, 91, 91, 1, 152064, 0xf09e2fbb +0, 92, 92, 1, 152064, 0x7244e477 +0, 93, 93, 1, 152064, 0x0dfc72eb +0, 94, 94, 1, 152064, 0x0322b21f +0, 95, 95, 1, 152064, 0x18b08205 +0, 96, 96, 1, 152064, 0x6606153e +0, 97, 97, 1, 152064, 0x85186272 +0, 98, 98, 1, 152064, 0x3369f064 +0, 99, 99, 1, 152064, 0xbe0d5a44 +0, 100, 100, 1, 152064, 0x320258bb +0, 101, 101, 1, 152064, 0x4d6fb091 +0, 102, 102, 1, 152064, 0xc9bbf5e7 +0, 103, 103, 1, 152064, 0x0aa1b69b +0, 104, 104, 1, 152064, 0x85b9ac11 +0, 105, 105, 1, 152064, 0xb25ff818 +0, 106, 106, 1, 152064, 0xa155dc25 +0, 107, 107, 1, 152064, 0xa8e03bfd +0, 108, 108, 1, 152064, 0x0a862956 +0, 109, 109, 1, 152064, 0x11b49264 +0, 110, 110, 1, 152064, 0xa94e664e +0, 111, 111, 1, 152064, 0x330e0fa2 +0, 112, 112, 1, 152064, 0xaf3d9518 +0, 113, 113, 1, 152064, 0x0836f2e8 +0, 114, 114, 1, 152064, 0xbf6dc578 +0, 115, 115, 1, 152064, 0x7b524d20 +0, 116, 116, 1, 152064, 0x9ef7677f +0, 117, 117, 1, 152064, 0xeacf3f34 +0, 118, 118, 1, 152064, 0xfb4e3dbe +0, 119, 119, 1, 152064, 0xb46e25cb +0, 120, 120, 1, 152064, 0x363c1603 +0, 121, 121, 1, 152064, 0x263fc542 +0, 122, 122, 1, 152064, 0xf106e548 +0, 123, 123, 1, 152064, 0xde43c56a +0, 124, 124, 1, 152064, 0xc2c4770a +0, 125, 125, 1, 152064, 0x122fce19 +0, 126, 126, 1, 152064, 0x3ba01434 +0, 127, 127, 1, 152064, 0x0e8ce5ee +0, 128, 128, 1, 152064, 0x6ceb82e1 +0, 129, 129, 1, 152064, 0xa23ee21c +0, 130, 130, 1, 152064, 0xc6d960f9 +0, 131, 131, 1, 152064, 0x0de15258 +0, 132, 132, 1, 152064, 0x187b0333 +0, 133, 133, 1, 152064, 0x92e6582f +0, 134, 134, 1, 152064, 0xb9586ce0 +0, 135, 135, 1, 152064, 0xefd803b5 +0, 136, 136, 1, 152064, 0x24eafb29 +0, 137, 137, 1, 152064, 0x20c73b14 +0, 138, 138, 1, 152064, 0xbd7ceaaa +0, 139, 139, 1, 152064, 0x775216c8 +0, 140, 140, 1, 152064, 0xa08971c7 +0, 141, 141, 1, 152064, 0xef0ee865 +0, 142, 142, 1, 152064, 0x9ac61c2f +0, 143, 143, 1, 152064, 0x52ae8ea9 +0, 144, 144, 1, 152064, 0x06571c14 +0, 145, 145, 1, 152064, 0x6e78ad33 +0, 146, 146, 1, 152064, 0xad01c627 +0, 147, 147, 1, 152064, 0xbfe074d3 +0, 148, 148, 1, 152064, 0x9357a183 +0, 149, 149, 1, 152064, 0x8de7767f +0, 150, 150, 1, 152064, 0xa5e6e76e +0, 151, 151, 1, 152064, 0xa6f646fe +0, 152, 152, 1, 152064, 0x132e99f8 +0, 153, 153, 1, 152064, 0xb79f27de +0, 154, 154, 1, 152064, 0x36d3cdcf +0, 155, 155, 1, 152064, 0xdc938336 +0, 156, 156, 1, 152064, 0xacaa3a7f +0, 157, 157, 1, 152064, 0xc61a37fd +0, 158, 158, 1, 152064, 0x4fe1ddf0 +0, 159, 159, 1, 152064, 0xc0f7d660 +0, 160, 160, 1, 152064, 0xd72458ea +0, 161, 161, 1, 152064, 0x6978d123 +0, 162, 162, 1, 152064, 0x64e60ccf +0, 163, 163, 1, 152064, 0xaa07004c +0, 164, 164, 1, 152064, 0x07cd1064 +0, 165, 165, 1, 152064, 0xa82320e5 +0, 166, 166, 1, 152064, 0xaedd8d30 +0, 167, 167, 1, 152064, 0x79b082ea +0, 168, 168, 1, 152064, 0x9ed800ab +0, 169, 169, 1, 152064, 0xde592bb4 +0, 170, 170, 1, 152064, 0xd966df88 +0, 171, 171, 1, 152064, 0xf921988a +0, 172, 172, 1, 152064, 0x557ad9ae +0, 173, 173, 1, 152064, 0xc3f31a9a +0, 174, 174, 1, 152064, 0x65248561 +0, 175, 175, 1, 152064, 0x63df4aa6 +0, 176, 176, 1, 152064, 0x618da0a9 +0, 177, 177, 1, 152064, 0xe6f1c435 +0, 178, 178, 1, 152064, 0x9f90c38f +0, 179, 179, 1, 152064, 0xd2853e14 +0, 180, 180, 1, 152064, 0x6e0268a9 +0, 181, 181, 1, 152064, 0x393712d1 +0, 182, 182, 1, 152064, 0x470da25f +0, 183, 183, 1, 152064, 0xaf55cb3d +0, 184, 184, 1, 152064, 0x6935b8b9 +0, 185, 185, 1, 152064, 0x5409a15f +0, 186, 186, 1, 152064, 0x09073fee +0, 187, 187, 1, 152064, 0xfb274e82 +0, 188, 188, 1, 152064, 0x1a770581 +0, 189, 189, 1, 152064, 0x17277d0d +0, 190, 190, 1, 152064, 0xd4dcd982 +0, 191, 191, 1, 152064, 0x6b04eaf3 +0, 192, 192, 1, 152064, 0x8a3d822e +0, 193, 193, 1, 152064, 0x1b971ec9 +0, 194, 194, 1, 152064, 0x14e0c0f6 +0, 195, 195, 1, 152064, 0x00667450 +0, 196, 196, 1, 152064, 0xd2385902 +0, 197, 197, 1, 152064, 0x905da6ab +0, 198, 198, 1, 152064, 0xa3ffb18b +0, 199, 199, 1, 152064, 0x10d48b19 +0, 200, 200, 1, 152064, 0xb2c7a3bd +0, 201, 201, 1, 152064, 0x45593e96 +0, 202, 202, 1, 152064, 0x47a0b60c +0, 203, 203, 1, 152064, 0x68c6d1b9 +0, 204, 204, 1, 152064, 0xbc881fcc +0, 205, 205, 1, 152064, 0x422cc6f2 +0, 206, 206, 1, 152064, 0x9b686410 +0, 207, 207, 1, 152064, 0x35dc5e86 +0, 208, 208, 1, 152064, 0x247bedaa +0, 209, 209, 1, 152064, 0x22b76fd1 +0, 210, 210, 1, 152064, 0x67cc7a75 +0, 211, 211, 1, 152064, 0xa197521e +0, 212, 212, 1, 152064, 0x428c8662 +0, 213, 213, 1, 152064, 0x33dc2c73 +0, 214, 214, 1, 152064, 0x5b538903 +0, 215, 215, 1, 152064, 0x3c4176b6 +0, 216, 216, 1, 152064, 0x774364ba +0, 217, 217, 1, 152064, 0xf237d03e +0, 218, 218, 1, 152064, 0xac8746fb +0, 219, 219, 1, 152064, 0x6b306a84 +0, 220, 220, 1, 152064, 0xa2ace513 +0, 221, 221, 1, 152064, 0x709c9be7 +0, 222, 222, 1, 152064, 0x2403f373 +0, 223, 223, 1, 152064, 0x147bf717 +0, 224, 224, 1, 152064, 0xe58964c8 +0, 225, 225, 1, 152064, 0xa0da36fc +0, 226, 226, 1, 152064, 0x1ac1355c +0, 227, 227, 1, 152064, 0x8a31c9f2 +0, 228, 228, 1, 152064, 0x42ba205c +0, 229, 229, 1, 152064, 0xa11b3575 +0, 230, 230, 1, 152064, 0xcb35207c +0, 231, 231, 1, 152064, 0x528f6189 +0, 232, 232, 1, 152064, 0x34f05bd7 +0, 233, 233, 1, 152064, 0x72317356 +0, 234, 234, 1, 152064, 0xaabd5028 +0, 235, 235, 1, 152064, 0x13dbeb7b +0, 236, 236, 1, 152064, 0x62f1e8a8 +0, 237, 237, 1, 152064, 0x1723bfcd +0, 238, 238, 1, 152064, 0x5c083c00 +0, 239, 239, 1, 152064, 0x52137894 +0, 240, 240, 1, 152064, 0xef1e082c +0, 241, 241, 1, 152064, 0x664b3d53 +0, 242, 242, 1, 152064, 0x2eb9b296 +0, 243, 243, 1, 152064, 0xd0ca511e +0, 244, 244, 1, 152064, 0x012d4724 +0, 245, 245, 1, 152064, 0xa847f5af +0, 246, 246, 1, 152064, 0x483a2fde +0, 247, 247, 1, 152064, 0xd1ab0257 +0, 248, 248, 1, 152064, 0x414692c7 +0, 249, 249, 1, 152064, 0x0b79df88 +0, 250, 250, 1, 152064, 0xdaa2c4a3 +0, 251, 251, 1, 152064, 0xd1b44500 +0, 252, 252, 1, 152064, 0xfd3d2cf3 +0, 253, 253, 1, 152064, 0xfdc0f748 +0, 254, 254, 1, 152064, 0xce762a2a +0, 255, 255, 1, 152064, 0x08b63572 +0, 256, 256, 1, 152064, 0x5a46a38d +0, 257, 257, 1, 152064, 0x03cee9c0 +0, 258, 258, 1, 152064, 0x9ee45473 +0, 259, 259, 1, 152064, 0x5a432386 +0, 260, 260, 1, 152064, 0x54c83d87 +0, 261, 261, 1, 152064, 0xc9caa1de +0, 262, 262, 1, 152064, 0xa28367f1 +0, 263, 263, 1, 152064, 0x2607cdf1 +0, 264, 264, 1, 152064, 0x06baa8de +0, 265, 265, 1, 152064, 0xf5346e32 +0, 266, 266, 1, 152064, 0x6d3e732b +0, 267, 267, 1, 152064, 0x798c584b +0, 268, 268, 1, 152064, 0x4076c948 +0, 269, 269, 1, 152064, 0x868cf63a +0, 270, 270, 1, 152064, 0x23107ac5 +0, 271, 271, 1, 152064, 0x306f3fe2 +0, 272, 272, 1, 152064, 0xbd1d71d6 +0, 273, 273, 1, 152064, 0x1429545f +0, 274, 274, 1, 152064, 0xaded29aa +0, 275, 275, 1, 152064, 0x9b455a94 +0, 276, 276, 1, 152064, 0xb3774ce7 +0, 277, 277, 1, 152064, 0x92580986 +0, 278, 278, 1, 152064, 0x0eae2f95 +0, 279, 279, 1, 152064, 0x599208b2 +0, 280, 280, 1, 152064, 0x4804c04c +0, 281, 281, 1, 152064, 0x5f730e8f +0, 282, 282, 1, 152064, 0x3e501d1e +0, 283, 283, 1, 152064, 0x32100740 +0, 284, 284, 1, 152064, 0x62226ff8 +0, 285, 285, 1, 152064, 0x7683b622 +0, 286, 286, 1, 152064, 0xc3e0aec1 +0, 287, 287, 1, 152064, 0xfac12608 +0, 288, 288, 1, 152064, 0xb21a5781 +0, 289, 289, 1, 152064, 0x8f1e4964 +0, 290, 290, 1, 152064, 0x0f62dd6e +0, 291, 291, 1, 152064, 0xac062ac4 +0, 292, 292, 1, 152064, 0x1b320f7a +0, 293, 293, 1, 152064, 0x346e7211 +0, 294, 294, 1, 152064, 0xe47592f3 +0, 295, 295, 1, 152064, 0xa3a7919c +0, 296, 296, 1, 152064, 0xa3580fa6 +0, 297, 297, 1, 152064, 0xc73430c1 +0, 298, 298, 1, 152064, 0x994a2c18 +0, 299, 299, 1, 152064, 0x0b5d8d45 +0, 300, 300, 1, 152064, 0x9eed5109 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-hpcamapalq_bcrm_b ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-hpcamapalq_bcrm_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-hpcamapalq_bcrm_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-hpcamapalq_bcrm_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,78 +3,78 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0xf8248ceb -0, 1, 1, 1, 152064, 0xb6204c81 +0, 1, 1, 1, 152064, 0xf8248ceb +0, 2, 2, 1, 152064, 0xb6204c81 0, 2, 2, 1, 152064, 0x22fb1737 0, 3, 3, 1, 152064, 0xce8c3fd7 -0, 4, 4, 1, 152064, 0xee88cedc +0, 5, 5, 1, 152064, 0xee88cedc 0, 5, 5, 1, 152064, 0x1d4209ca -0, 6, 6, 1, 152064, 0x6fb15238 -0, 7, 7, 1, 152064, 0x505200c2 +0, 7, 7, 1, 152064, 0x6fb15238 +0, 8, 8, 1, 152064, 0x505200c2 0, 8, 8, 1, 152064, 0xb73574ba 0, 9, 9, 1, 152064, 0x0586a097 -0, 10, 10, 1, 152064, 0xed50fe02 +0, 11, 11, 1, 152064, 0xed50fe02 0, 11, 11, 1, 152064, 0x222221ab 0, 12, 12, 1, 152064, 0x8afefd46 -0, 13, 13, 1, 152064, 0x6832c5cc -0, 14, 14, 1, 152064, 0xba4c8110 +0, 14, 14, 1, 152064, 0x6832c5cc +0, 15, 15, 1, 152064, 0xba4c8110 0, 15, 15, 1, 152064, 0x95c07e1e 0, 16, 16, 1, 152064, 0xc5d6fde9 -0, 17, 17, 1, 152064, 0xe75a4921 -0, 18, 18, 1, 152064, 0x53b61688 +0, 18, 18, 1, 152064, 0xe75a4921 +0, 19, 19, 1, 152064, 0x53b61688 0, 19, 19, 1, 152064, 0x0335424b -0, 20, 20, 1, 152064, 0x621742c7 -0, 21, 21, 1, 152064, 0x4f69f41b +0, 21, 21, 1, 152064, 0x621742c7 +0, 22, 22, 1, 152064, 0x4f69f41b 0, 22, 22, 1, 152064, 0x6b3f65d7 -0, 23, 23, 1, 152064, 0x8dfde04f +0, 24, 24, 1, 152064, 0x8dfde04f 0, 24, 24, 1, 152064, 0x30750ff5 -0, 25, 25, 1, 152064, 0xe3d70f3c +0, 26, 26, 1, 152064, 0xe3d70f3c 0, 26, 26, 1, 152064, 0x0c1af825 -0, 27, 27, 1, 152064, 0x58a53935 +0, 28, 28, 1, 152064, 0x58a53935 0, 28, 28, 1, 152064, 0xc63d9e98 -0, 29, 29, 1, 152064, 0xa85fdc48 +0, 30, 30, 1, 152064, 0xa85fdc48 0, 30, 30, 1, 152064, 0x01bb9784 -0, 31, 31, 1, 152064, 0xdd5cb509 +0, 32, 32, 1, 152064, 0xdd5cb509 0, 32, 32, 1, 152064, 0x29ae7d2b -0, 33, 33, 1, 152064, 0xdb08593e -0, 34, 34, 1, 152064, 0x372d5d4e -0, 35, 35, 1, 152064, 0x31522664 -0, 36, 36, 1, 152064, 0x3f13f335 +0, 34, 34, 1, 152064, 0xdb08593e +0, 35, 35, 1, 152064, 0x372d5d4e +0, 36, 36, 1, 152064, 0x31522664 +0, 37, 37, 1, 152064, 0x3f13f335 0, 37, 37, 1, 152064, 0xfd10c19a -0, 38, 38, 1, 152064, 0xef728975 -0, 39, 39, 1, 152064, 0x8e79234d -0, 40, 40, 1, 152064, 0x47022791 +0, 39, 39, 1, 152064, 0xef728975 +0, 40, 40, 1, 152064, 0x8e79234d +0, 41, 41, 1, 152064, 0x47022791 0, 41, 41, 1, 152064, 0x1ef9d297 0, 42, 42, 1, 152064, 0x77bf9738 0, 43, 43, 1, 152064, 0xd6bc8f03 -0, 44, 44, 1, 152064, 0x283ded4a -0, 45, 45, 1, 152064, 0xd87098d1 +0, 45, 45, 1, 152064, 0x283ded4a +0, 46, 46, 1, 152064, 0xd87098d1 0, 46, 46, 1, 152064, 0x300077a2 0, 47, 47, 1, 152064, 0x30ffbea4 -0, 48, 48, 1, 152064, 0x5dc5356b +0, 49, 49, 1, 152064, 0x5dc5356b 0, 49, 49, 1, 152064, 0x31cce185 0, 50, 50, 1, 152064, 0x47fc9148 -0, 51, 51, 1, 152064, 0x1641491e +0, 52, 52, 1, 152064, 0x1641491e 0, 52, 52, 1, 152064, 0x2184937d -0, 53, 53, 1, 152064, 0x126eb74a +0, 54, 54, 1, 152064, 0x126eb74a 0, 54, 54, 1, 152064, 0x25c07593 0, 55, 55, 1, 152064, 0xb1294e7e -0, 56, 56, 1, 152064, 0x8b35f45d -0, 57, 57, 1, 152064, 0x54765025 +0, 57, 57, 1, 152064, 0x8b35f45d +0, 58, 58, 1, 152064, 0x54765025 0, 58, 58, 1, 152064, 0x1d17e901 -0, 59, 59, 1, 152064, 0xaeab358d -0, 60, 60, 1, 152064, 0xf682c91f +0, 60, 60, 1, 152064, 0xaeab358d +0, 61, 61, 1, 152064, 0xf682c91f 0, 61, 61, 1, 152064, 0x0b4c9b06 0, 62, 62, 1, 152064, 0x45f326dc -0, 63, 63, 1, 152064, 0x132eeda3 +0, 64, 64, 1, 152064, 0x132eeda3 0, 64, 64, 1, 152064, 0x3c9b8e16 0, 65, 65, 1, 152064, 0x1be133c1 0, 66, 66, 1, 152064, 0xfa876720 -0, 67, 67, 1, 152064, 0x1666cdb8 +0, 68, 68, 1, 152064, 0x1666cdb8 0, 68, 68, 1, 152064, 0x362f418f 0, 69, 69, 1, 152064, 0x926b4a96 0, 70, 70, 1, 152064, 0xee3da1df -0, 71, 71, 1, 152064, 0xc11f025d +0, 72, 72, 1, 152064, 0xc11f025d 0, 72, 72, 1, 152064, 0x9ba62c19 0, 73, 73, 1, 152064, 0x0d66194f 0, 74, 74, 1, 152064, 0x2fd09340 @@ -82,224 +82,224 @@ 0, 76, 76, 1, 152064, 0xa3192ce6 0, 77, 77, 1, 152064, 0x6bfce0e1 0, 78, 78, 1, 152064, 0x3b7c5286 -0, 79, 79, 1, 152064, 0xb52f4bf5 -0, 80, 80, 1, 152064, 0x30870027 +0, 80, 80, 1, 152064, 0xb52f4bf5 +0, 81, 81, 1, 152064, 0x30870027 0, 81, 81, 1, 152064, 0x6f8e71c3 0, 82, 82, 1, 152064, 0x8d41b09a 0, 83, 83, 1, 152064, 0xc1ff1d05 0, 84, 84, 1, 152064, 0xca54125c 0, 85, 85, 1, 152064, 0x3342d823 -0, 86, 86, 1, 152064, 0xcc4a7542 -0, 87, 87, 1, 152064, 0x21fc9a9d +0, 87, 87, 1, 152064, 0xcc4a7542 +0, 88, 88, 1, 152064, 0x21fc9a9d 0, 88, 88, 1, 152064, 0x91587574 0, 89, 89, 1, 152064, 0x30929cc2 0, 90, 90, 1, 152064, 0xf07606b7 -0, 91, 91, 1, 152064, 0x0476b876 -0, 92, 92, 1, 152064, 0x213333dc +0, 92, 92, 1, 152064, 0x0476b876 +0, 93, 93, 1, 152064, 0x213333dc 0, 93, 93, 1, 152064, 0x87c67597 -0, 94, 94, 1, 152064, 0x05434641 -0, 95, 95, 1, 152064, 0x959eeffc +0, 95, 95, 1, 152064, 0x05434641 +0, 96, 96, 1, 152064, 0x959eeffc 0, 96, 96, 1, 152064, 0x92a130b4 -0, 97, 97, 1, 152064, 0x53d0b544 -0, 98, 98, 1, 152064, 0xaf8c233e -0, 99, 99, 1, 152064, 0xd3d4259a -0, 100, 100, 1, 152064, 0xa0287753 +0, 98, 98, 1, 152064, 0x53d0b544 +0, 99, 99, 1, 152064, 0xaf8c233e +0, 100, 100, 1, 152064, 0xd3d4259a +0, 101, 101, 1, 152064, 0xa0287753 0, 101, 101, 1, 152064, 0xfa23972a 0, 102, 102, 1, 152064, 0xacae756d -0, 103, 103, 1, 152064, 0xd8b58b5c +0, 104, 104, 1, 152064, 0xd8b58b5c 0, 104, 104, 1, 152064, 0x7db2c755 -0, 105, 105, 1, 152064, 0x31e7b79a -0, 106, 106, 1, 152064, 0xd8660d98 +0, 106, 106, 1, 152064, 0x31e7b79a +0, 107, 107, 1, 152064, 0xd8660d98 0, 107, 107, 1, 152064, 0xdcf0d10d 0, 108, 108, 1, 152064, 0x3e6567e6 -0, 109, 109, 1, 152064, 0xec3530fd +0, 110, 110, 1, 152064, 0xec3530fd 0, 110, 110, 1, 152064, 0xf686c61a 0, 111, 111, 1, 152064, 0x6e706804 -0, 112, 112, 1, 152064, 0x5fd4a1a3 -0, 113, 113, 1, 152064, 0xbb3384f7 +0, 113, 113, 1, 152064, 0x5fd4a1a3 +0, 114, 114, 1, 152064, 0xbb3384f7 0, 114, 114, 1, 152064, 0x8ffb14dd -0, 115, 115, 1, 152064, 0x01253a73 -0, 116, 116, 1, 152064, 0xf89c15df +0, 116, 116, 1, 152064, 0x01253a73 +0, 117, 117, 1, 152064, 0xf89c15df 0, 117, 117, 1, 152064, 0xda2b0b4c -0, 118, 118, 1, 152064, 0xfc9dfcc1 -0, 119, 119, 1, 152064, 0xfef4f0fa +0, 119, 119, 1, 152064, 0xfc9dfcc1 +0, 120, 120, 1, 152064, 0xfef4f0fa 0, 120, 120, 1, 152064, 0x91669bea -0, 121, 121, 1, 152064, 0x3664a565 +0, 122, 122, 1, 152064, 0x3664a565 0, 122, 122, 1, 152064, 0x32dd7923 0, 123, 123, 1, 152064, 0x26825231 0, 124, 124, 1, 152064, 0x5f81896e -0, 125, 125, 1, 152064, 0x0c64ca2f +0, 126, 126, 1, 152064, 0x0c64ca2f 0, 126, 126, 1, 152064, 0x488bb665 -0, 127, 127, 1, 152064, 0x4d183a0f +0, 128, 128, 1, 152064, 0x4d183a0f 0, 128, 128, 1, 152064, 0xed169321 0, 129, 129, 1, 152064, 0xcec22917 0, 130, 130, 1, 152064, 0xbe04ea6c -0, 131, 131, 1, 152064, 0x32b8bf9f -0, 132, 132, 1, 152064, 0x9c7c2e13 -0, 133, 133, 1, 152064, 0x232e3016 -0, 134, 134, 1, 152064, 0x1b76c08e -0, 135, 135, 1, 152064, 0x7425d821 +0, 132, 132, 1, 152064, 0x32b8bf9f +0, 133, 133, 1, 152064, 0x9c7c2e13 +0, 134, 134, 1, 152064, 0x232e3016 +0, 135, 135, 1, 152064, 0x1b76c08e +0, 136, 136, 1, 152064, 0x7425d821 0, 136, 136, 1, 152064, 0x0818ff3c 0, 137, 137, 1, 152064, 0xb4f2c42b 0, 138, 138, 1, 152064, 0xe029f979 -0, 139, 139, 1, 152064, 0x97c54c2f -0, 140, 140, 1, 152064, 0xd101c3b5 +0, 140, 140, 1, 152064, 0x97c54c2f +0, 141, 141, 1, 152064, 0xd101c3b5 0, 141, 141, 1, 152064, 0x5ed1f5d4 -0, 142, 142, 1, 152064, 0xc28264d1 +0, 143, 143, 1, 152064, 0xc28264d1 0, 143, 143, 1, 152064, 0xa162dd31 0, 144, 144, 1, 152064, 0x2ee872ce -0, 145, 145, 1, 152064, 0x809a8fce +0, 146, 146, 1, 152064, 0x809a8fce 0, 146, 146, 1, 152064, 0xcfcc3ef9 -0, 147, 147, 1, 152064, 0xa5be6ce3 +0, 148, 148, 1, 152064, 0xa5be6ce3 0, 148, 148, 1, 152064, 0xd75930a0 -0, 149, 149, 1, 152064, 0x28acb80f -0, 150, 150, 1, 152064, 0x223f2152 -0, 151, 151, 1, 152064, 0x0cf070cb +0, 150, 150, 1, 152064, 0x28acb80f +0, 151, 151, 1, 152064, 0x223f2152 +0, 152, 152, 1, 152064, 0x0cf070cb 0, 152, 152, 1, 152064, 0xcc7d011e -0, 153, 153, 1, 152064, 0xb2c2a63c +0, 154, 154, 1, 152064, 0xb2c2a63c 0, 154, 154, 1, 152064, 0x15514caa -0, 155, 155, 1, 152064, 0x0c6d18ee +0, 156, 156, 1, 152064, 0x0c6d18ee 0, 156, 156, 1, 152064, 0x33b4265d 0, 157, 157, 1, 152064, 0xb4abaaaf -0, 158, 158, 1, 152064, 0x26a7a856 +0, 159, 159, 1, 152064, 0x26a7a856 0, 159, 159, 1, 152064, 0xc75249cc -0, 160, 160, 1, 152064, 0x59ccb0e1 -0, 161, 161, 1, 152064, 0xc613f202 -0, 162, 162, 1, 152064, 0xd1c0e171 +0, 161, 161, 1, 152064, 0x59ccb0e1 +0, 162, 162, 1, 152064, 0xc613f202 +0, 163, 163, 1, 152064, 0xd1c0e171 0, 163, 163, 1, 152064, 0xa195da2b 0, 164, 164, 1, 152064, 0xbc7ed475 0, 165, 165, 1, 152064, 0x99206e2c -0, 166, 166, 1, 152064, 0x0ef04e03 -0, 167, 167, 1, 152064, 0x68cbc6a1 +0, 167, 167, 1, 152064, 0x0ef04e03 +0, 168, 168, 1, 152064, 0x68cbc6a1 0, 168, 168, 1, 152064, 0x2a5304b1 0, 169, 169, 1, 152064, 0xf017978b 0, 170, 170, 1, 152064, 0x94f5641a -0, 171, 171, 1, 152064, 0xd681bd8f +0, 172, 172, 1, 152064, 0xd681bd8f 0, 172, 172, 1, 152064, 0x16e1e3a3 -0, 173, 173, 1, 152064, 0xe4486c7e -0, 174, 174, 1, 152064, 0xa1bd394e +0, 174, 174, 1, 152064, 0xe4486c7e +0, 175, 175, 1, 152064, 0xa1bd394e 0, 175, 175, 1, 152064, 0x49ad5959 -0, 176, 176, 1, 152064, 0x82219b70 -0, 177, 177, 1, 152064, 0x64e2abcf -0, 178, 178, 1, 152064, 0x6d7d05d8 -0, 179, 179, 1, 152064, 0xd9ac2251 +0, 177, 177, 1, 152064, 0x82219b70 +0, 178, 178, 1, 152064, 0x64e2abcf +0, 179, 179, 1, 152064, 0x6d7d05d8 +0, 180, 180, 1, 152064, 0xd9ac2251 0, 180, 180, 1, 152064, 0xf477eee5 -0, 181, 181, 1, 152064, 0xb9826a78 +0, 182, 182, 1, 152064, 0xb9826a78 0, 182, 182, 1, 152064, 0x97828a37 -0, 183, 183, 1, 152064, 0x12099b1f +0, 184, 184, 1, 152064, 0x12099b1f 0, 184, 184, 1, 152064, 0x1ec45fa7 -0, 185, 185, 1, 152064, 0xfd5501c9 +0, 186, 186, 1, 152064, 0xfd5501c9 0, 186, 186, 1, 152064, 0x6a8b26a3 -0, 187, 187, 1, 152064, 0xae58ff40 -0, 188, 188, 1, 152064, 0xc0f47aa1 +0, 188, 188, 1, 152064, 0xae58ff40 +0, 189, 189, 1, 152064, 0xc0f47aa1 0, 189, 189, 1, 152064, 0x08bfa548 0, 190, 190, 1, 152064, 0x7f2ff5ef -0, 191, 191, 1, 152064, 0x5efa94a3 -0, 192, 192, 1, 152064, 0xf786f970 -0, 193, 193, 1, 152064, 0xab6bc712 +0, 192, 192, 1, 152064, 0x5efa94a3 +0, 193, 193, 1, 152064, 0xf786f970 +0, 194, 194, 1, 152064, 0xab6bc712 0, 194, 194, 1, 152064, 0x25647bee -0, 195, 195, 1, 152064, 0x54333ad5 -0, 196, 196, 1, 152064, 0xb3a99413 +0, 196, 196, 1, 152064, 0x54333ad5 +0, 197, 197, 1, 152064, 0xb3a99413 0, 197, 197, 1, 152064, 0xe7a78a0d -0, 198, 198, 1, 152064, 0xa5054abc -0, 199, 199, 1, 152064, 0xb94896ea +0, 199, 199, 1, 152064, 0xa5054abc +0, 200, 200, 1, 152064, 0xb94896ea 0, 200, 200, 1, 152064, 0x9f641bca -0, 201, 201, 1, 152064, 0x7363901c +0, 202, 202, 1, 152064, 0x7363901c 0, 202, 202, 1, 152064, 0xd340a000 0, 203, 203, 1, 152064, 0x0217f413 0, 204, 204, 1, 152064, 0xbbdba6e6 0, 205, 205, 1, 152064, 0xabc42617 -0, 206, 206, 1, 152064, 0xa3442925 -0, 207, 207, 1, 152064, 0x7d06c7e9 +0, 207, 207, 1, 152064, 0xa3442925 +0, 208, 208, 1, 152064, 0x7d06c7e9 0, 208, 208, 1, 152064, 0xa45e32df 0, 209, 209, 1, 152064, 0xf5ed407f -0, 210, 210, 1, 152064, 0x5ec235d5 -0, 211, 211, 1, 152064, 0xa5706635 -0, 212, 212, 1, 152064, 0xa44a209b -0, 213, 213, 1, 152064, 0xf2137e37 -0, 214, 214, 1, 152064, 0x5220508f +0, 211, 211, 1, 152064, 0x5ec235d5 +0, 212, 212, 1, 152064, 0xa5706635 +0, 213, 213, 1, 152064, 0xa44a209b +0, 214, 214, 1, 152064, 0xf2137e37 +0, 215, 215, 1, 152064, 0x5220508f 0, 215, 215, 1, 152064, 0xae6b37da -0, 216, 216, 1, 152064, 0xdf09b6cd +0, 217, 217, 1, 152064, 0xdf09b6cd 0, 217, 217, 1, 152064, 0x2d39e1c0 -0, 218, 218, 1, 152064, 0xc8284a76 -0, 219, 219, 1, 152064, 0x7d7bbe76 +0, 219, 219, 1, 152064, 0xc8284a76 +0, 220, 220, 1, 152064, 0x7d7bbe76 0, 220, 220, 1, 152064, 0xcfed7416 0, 221, 221, 1, 152064, 0x81caaedd 0, 222, 222, 1, 152064, 0x9dcdd771 -0, 223, 223, 1, 152064, 0x46c1331b -0, 224, 224, 1, 152064, 0xace60efa +0, 224, 224, 1, 152064, 0x46c1331b +0, 225, 225, 1, 152064, 0xace60efa 0, 225, 225, 1, 152064, 0x9e0909f7 -0, 226, 226, 1, 152064, 0x72f5a321 +0, 227, 227, 1, 152064, 0x72f5a321 0, 227, 227, 1, 152064, 0x68f8cdcc 0, 228, 228, 1, 152064, 0xcc59fdd9 -0, 229, 229, 1, 152064, 0xc0a700c6 -0, 230, 230, 1, 152064, 0xf4254dcf +0, 230, 230, 1, 152064, 0xc0a700c6 +0, 231, 231, 1, 152064, 0xf4254dcf 0, 231, 231, 1, 152064, 0xc59b46d1 -0, 232, 232, 1, 152064, 0x2e5b2524 -0, 233, 233, 1, 152064, 0x46051293 +0, 233, 233, 1, 152064, 0x2e5b2524 +0, 234, 234, 1, 152064, 0x46051293 0, 234, 234, 1, 152064, 0x3cbcd1cd 0, 235, 235, 1, 152064, 0x9f308587 -0, 236, 236, 1, 152064, 0x6b91633f +0, 237, 237, 1, 152064, 0x6b91633f 0, 237, 237, 1, 152064, 0xb7191012 -0, 238, 238, 1, 152064, 0xd2fd030f -0, 239, 239, 1, 152064, 0x15a0ae2e -0, 240, 240, 1, 152064, 0xac3920d0 +0, 239, 239, 1, 152064, 0xd2fd030f +0, 240, 240, 1, 152064, 0x15a0ae2e +0, 241, 241, 1, 152064, 0xac3920d0 0, 241, 241, 1, 152064, 0x0eef80aa 0, 242, 242, 1, 152064, 0x319008f1 -0, 243, 243, 1, 152064, 0x7734450c +0, 244, 244, 1, 152064, 0x7734450c 0, 244, 244, 1, 152064, 0xf112df62 0, 245, 245, 1, 152064, 0x1dd8ffae -0, 246, 246, 1, 152064, 0x655ef429 +0, 247, 247, 1, 152064, 0x655ef429 0, 247, 247, 1, 152064, 0x27026213 -0, 248, 248, 1, 152064, 0x5c14b015 -0, 249, 249, 1, 152064, 0x9512abeb -0, 250, 250, 1, 152064, 0x961812b2 +0, 249, 249, 1, 152064, 0x5c14b015 +0, 250, 250, 1, 152064, 0x9512abeb +0, 251, 251, 1, 152064, 0x961812b2 0, 251, 251, 1, 152064, 0xb8890aea 0, 252, 252, 1, 152064, 0x4519db9a 0, 253, 253, 1, 152064, 0xf358034a -0, 254, 254, 1, 152064, 0x45d9f2ab +0, 255, 255, 1, 152064, 0x45d9f2ab 0, 255, 255, 1, 152064, 0xebd47e7d 0, 256, 256, 1, 152064, 0x15578be9 -0, 257, 257, 1, 152064, 0x1b373b2d +0, 258, 258, 1, 152064, 0x1b373b2d 0, 258, 258, 1, 152064, 0xbbe707e5 0, 259, 259, 1, 152064, 0x5bf62385 -0, 260, 260, 1, 152064, 0x832e6ef5 -0, 261, 261, 1, 152064, 0x761e5968 +0, 261, 261, 1, 152064, 0x832e6ef5 +0, 262, 262, 1, 152064, 0x761e5968 0, 262, 262, 1, 152064, 0x251f984d -0, 263, 263, 1, 152064, 0xbda48899 +0, 264, 264, 1, 152064, 0xbda48899 0, 264, 264, 1, 152064, 0x3fd843b9 -0, 265, 265, 1, 152064, 0x00485425 -0, 266, 266, 1, 152064, 0x4e282b39 -0, 267, 267, 1, 152064, 0x2630a8ea -0, 268, 268, 1, 152064, 0x5ea5c973 -0, 269, 269, 1, 152064, 0xfc436d21 -0, 270, 270, 1, 152064, 0x69852ef5 -0, 271, 271, 1, 152064, 0x44cb5589 -0, 272, 272, 1, 152064, 0x32f32725 -0, 273, 273, 1, 152064, 0x54d50aca -0, 274, 274, 1, 152064, 0xe7a639bb -0, 275, 275, 1, 152064, 0x01be2ad5 -0, 276, 276, 1, 152064, 0x5c63eca4 -0, 277, 277, 1, 152064, 0x94e91116 +0, 266, 266, 1, 152064, 0x00485425 +0, 267, 267, 1, 152064, 0x4e282b39 +0, 268, 268, 1, 152064, 0x2630a8ea +0, 269, 269, 1, 152064, 0x5ea5c973 +0, 270, 270, 1, 152064, 0xfc436d21 +0, 271, 271, 1, 152064, 0x69852ef5 +0, 272, 272, 1, 152064, 0x44cb5589 +0, 273, 273, 1, 152064, 0x32f32725 +0, 274, 274, 1, 152064, 0x54d50aca +0, 275, 275, 1, 152064, 0xe7a639bb +0, 276, 276, 1, 152064, 0x01be2ad5 +0, 277, 277, 1, 152064, 0x5c63eca4 +0, 278, 278, 1, 152064, 0x94e91116 0, 278, 278, 1, 152064, 0x9a8be637 0, 279, 279, 1, 152064, 0x165d9a12 -0, 280, 280, 1, 152064, 0x8c25ca0a -0, 281, 281, 1, 152064, 0x4ee2ed32 -0, 282, 282, 1, 152064, 0x4b2fe0c6 -0, 283, 283, 1, 152064, 0x521e434e -0, 284, 284, 1, 152064, 0x97679d7e -0, 285, 285, 1, 152064, 0x886b9506 +0, 281, 281, 1, 152064, 0x8c25ca0a +0, 282, 282, 1, 152064, 0x4ee2ed32 +0, 283, 283, 1, 152064, 0x4b2fe0c6 +0, 284, 284, 1, 152064, 0x521e434e +0, 285, 285, 1, 152064, 0x97679d7e +0, 286, 286, 1, 152064, 0x886b9506 0, 286, 286, 1, 152064, 0x4283eda8 -0, 287, 287, 1, 152064, 0xef793c49 +0, 288, 288, 1, 152064, 0xef793c49 0, 288, 288, 1, 152064, 0x68ac2afe -0, 289, 289, 1, 152064, 0x3d1ab510 +0, 290, 290, 1, 152064, 0x3d1ab510 0, 290, 290, 1, 152064, 0x98d3ec95 0, 291, 291, 1, 152064, 0x09f7e512 -0, 292, 292, 1, 152064, 0x801355dd -0, 293, 293, 1, 152064, 0xf2e87a11 +0, 293, 293, 1, 152064, 0x801355dd +0, 294, 294, 1, 152064, 0xf2e87a11 0, 294, 294, 1, 152064, 0x16757601 0, 295, 295, 1, 152064, 0x3074d74a -0, 296, 296, 1, 152064, 0xec8c1290 -0, 297, 297, 1, 152064, 0x46fb1877 +0, 297, 297, 1, 152064, 0xec8c1290 +0, 298, 298, 1, 152064, 0x46fb1877 0, 298, 298, 1, 152064, 0xf0b662c4 0, 299, 299, 1, 152064, 0xf8683940 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-hpcvfl_bcrm_a ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-hpcvfl_bcrm_a --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-hpcvfl_bcrm_a 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-hpcvfl_bcrm_a 2021-04-08 21:28:40.000000000 +0000 @@ -3,303 +3,303 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x502ec077 -0, 1, 1, 1, 152064, 0x84807243 -0, 2, 2, 1, 152064, 0xd7474a6e -0, 3, 3, 1, 152064, 0x793469bb -0, 4, 4, 1, 152064, 0xb7a0faf7 -0, 5, 5, 1, 152064, 0x1d3d3cba -0, 6, 6, 1, 152064, 0xb62583de -0, 7, 7, 1, 152064, 0xc8422fb1 -0, 8, 8, 1, 152064, 0x321dc699 -0, 9, 9, 1, 152064, 0x7a34d350 -0, 10, 10, 1, 152064, 0xaa4c302d -0, 11, 11, 1, 152064, 0x45fa7ab0 -0, 12, 12, 1, 152064, 0xc7262e41 -0, 13, 13, 1, 152064, 0x3550000c -0, 14, 14, 1, 152064, 0xf4bab54b -0, 15, 15, 1, 152064, 0xaccf9c1a -0, 16, 16, 1, 152064, 0x9bee20e9 -0, 17, 17, 1, 152064, 0x47fb7720 -0, 18, 18, 1, 152064, 0x12c63ffb -0, 19, 19, 1, 152064, 0xfa2b8b4d -0, 20, 20, 1, 152064, 0x279964bd -0, 21, 21, 1, 152064, 0xb8b01c7e -0, 22, 22, 1, 152064, 0x816fa010 -0, 23, 23, 1, 152064, 0x59fe1c8c -0, 24, 24, 1, 152064, 0x13393fad -0, 25, 25, 1, 152064, 0x991a50a4 -0, 26, 26, 1, 152064, 0x57df3eb7 -0, 27, 27, 1, 152064, 0x744371df -0, 28, 28, 1, 152064, 0xe9f6d3ff -0, 29, 29, 1, 152064, 0xc506fba0 -0, 30, 30, 1, 152064, 0x6295b90e -0, 31, 31, 1, 152064, 0xa19cee2d -0, 32, 32, 1, 152064, 0xf8c1b3ca -0, 33, 33, 1, 152064, 0x69f68ce0 -0, 34, 34, 1, 152064, 0x80558bb6 -0, 35, 35, 1, 152064, 0x27824fa5 -0, 36, 36, 1, 152064, 0x27c929a1 -0, 37, 37, 1, 152064, 0xc0fe06d1 -0, 38, 38, 1, 152064, 0xc52bc58c -0, 39, 39, 1, 152064, 0x0a5363c7 -0, 40, 40, 1, 152064, 0xd0f45a0d -0, 41, 41, 1, 152064, 0x274710f9 -0, 42, 42, 1, 152064, 0x89d2d390 -0, 43, 43, 1, 152064, 0x12a9bfb0 -0, 44, 44, 1, 152064, 0x04501a93 -0, 45, 45, 1, 152064, 0xf92cbbf4 -0, 46, 46, 1, 152064, 0xf6d1b27d -0, 47, 47, 1, 152064, 0xe3e904c3 -0, 48, 48, 1, 152064, 0x58f8516d -0, 49, 49, 1, 152064, 0x70370c2b -0, 50, 50, 1, 152064, 0xfeebc88c -0, 51, 51, 1, 152064, 0x974c6ed6 -0, 52, 52, 1, 152064, 0x401bdcf2 -0, 53, 53, 1, 152064, 0xfe61e278 -0, 54, 54, 1, 152064, 0x96ba8bb9 -0, 55, 55, 1, 152064, 0x988492fd -0, 56, 56, 1, 152064, 0xd1d913a9 -0, 57, 57, 1, 152064, 0x6bc46f0e -0, 58, 58, 1, 152064, 0x695ef706 -0, 59, 59, 1, 152064, 0x142045c9 -0, 60, 60, 1, 152064, 0xb390ed87 -0, 61, 61, 1, 152064, 0xb9e6d2e5 -0, 62, 62, 1, 152064, 0xe348797f -0, 63, 63, 1, 152064, 0x1cbd29d6 -0, 64, 64, 1, 152064, 0xbd7dd694 -0, 65, 65, 1, 152064, 0x516873c3 -0, 66, 66, 1, 152064, 0x27bba182 -0, 67, 67, 1, 152064, 0x7541f920 -0, 68, 68, 1, 152064, 0xfdf67042 -0, 69, 69, 1, 152064, 0x6c3c7896 -0, 70, 70, 1, 152064, 0xed86c467 -0, 71, 71, 1, 152064, 0x4ea83ca2 -0, 72, 72, 1, 152064, 0xa3e6725b -0, 73, 73, 1, 152064, 0x917f5f16 -0, 74, 74, 1, 152064, 0x8cf2d2e1 -0, 75, 75, 1, 152064, 0x57a8d116 -0, 76, 76, 1, 152064, 0x0db267d4 -0, 77, 77, 1, 152064, 0xce782ac5 -0, 78, 78, 1, 152064, 0x1c9d8518 -0, 79, 79, 1, 152064, 0x47598ac7 -0, 80, 80, 1, 152064, 0xc5033d97 -0, 81, 81, 1, 152064, 0xd7aaa3a4 -0, 82, 82, 1, 152064, 0x078afc96 -0, 83, 83, 1, 152064, 0xc9fe673d -0, 84, 84, 1, 152064, 0xe9284066 -0, 85, 85, 1, 152064, 0xbc570982 -0, 86, 86, 1, 152064, 0x0aac8574 -0, 87, 87, 1, 152064, 0x098cbeee -0, 88, 88, 1, 152064, 0x19c36a9d -0, 89, 89, 1, 152064, 0x8fe4a893 -0, 90, 90, 1, 152064, 0x0b652f17 -0, 91, 91, 1, 152064, 0x10f2e6bf -0, 92, 92, 1, 152064, 0x7ce5634e -0, 93, 93, 1, 152064, 0x8fe4ac6c -0, 94, 94, 1, 152064, 0xcaba749e -0, 95, 95, 1, 152064, 0x5f8a0d5c -0, 96, 96, 1, 152064, 0xcaa66bbc -0, 97, 97, 1, 152064, 0xc87ae617 -0, 98, 98, 1, 152064, 0xe8ef4dd7 -0, 99, 99, 1, 152064, 0xdfca5a07 -0, 100, 100, 1, 152064, 0x5f7eab7d -0, 101, 101, 1, 152064, 0x8a65ebbb -0, 102, 102, 1, 152064, 0x4beab4a0 -0, 103, 103, 1, 152064, 0xb5e6ab30 -0, 104, 104, 1, 152064, 0x8fe4f4d4 -0, 105, 105, 1, 152064, 0x95bde1ca -0, 106, 106, 1, 152064, 0xcc5e3a53 -0, 107, 107, 1, 152064, 0xf09f1dd7 -0, 108, 108, 1, 152064, 0x10179672 -0, 109, 109, 1, 152064, 0x4ad16184 -0, 110, 110, 1, 152064, 0x9efa0e23 -0, 111, 111, 1, 152064, 0x22f59522 -0, 112, 112, 1, 152064, 0x4d38f09d -0, 113, 113, 1, 152064, 0x4c5ebf56 -0, 114, 114, 1, 152064, 0xb19d5077 -0, 115, 115, 1, 152064, 0xa98576b9 -0, 116, 116, 1, 152064, 0x65324239 -0, 117, 117, 1, 152064, 0x709e4031 -0, 118, 118, 1, 152064, 0xf8e81681 -0, 119, 119, 1, 152064, 0x058514e5 -0, 120, 120, 1, 152064, 0xd1d1c806 -0, 121, 121, 1, 152064, 0x0e4dde57 -0, 122, 122, 1, 152064, 0x49e9c2bb -0, 123, 123, 1, 152064, 0x01417ce6 -0, 124, 124, 1, 152064, 0xda7ebbf1 -0, 125, 125, 1, 152064, 0xa22906b7 -0, 126, 126, 1, 152064, 0x32e2df87 -0, 127, 127, 1, 152064, 0x69917c8f -0, 128, 128, 1, 152064, 0xea8ed2cc -0, 129, 129, 1, 152064, 0x0b8d57f1 -0, 130, 130, 1, 152064, 0x5f683bcd -0, 131, 131, 1, 152064, 0x5162fe2f -0, 132, 132, 1, 152064, 0x49c052f8 -0, 133, 133, 1, 152064, 0x990b69ba -0, 134, 134, 1, 152064, 0xa6d4f99f -0, 135, 135, 1, 152064, 0xe79ef4da -0, 136, 136, 1, 152064, 0x5e8a3847 -0, 137, 137, 1, 152064, 0x38b1e75f -0, 138, 138, 1, 152064, 0xf5c91bed -0, 139, 139, 1, 152064, 0xd59a6d26 -0, 140, 140, 1, 152064, 0xc361de06 -0, 141, 141, 1, 152064, 0x63ed2229 -0, 142, 142, 1, 152064, 0xb8229205 -0, 143, 143, 1, 152064, 0x7c6619af -0, 144, 144, 1, 152064, 0x4126b02f -0, 145, 145, 1, 152064, 0x9250b99b -0, 146, 146, 1, 152064, 0x589778f9 -0, 147, 147, 1, 152064, 0xed1fa45b -0, 148, 148, 1, 152064, 0x700b6f32 -0, 149, 149, 1, 152064, 0x0590df55 -0, 150, 150, 1, 152064, 0x3e9c4018 -0, 151, 151, 1, 152064, 0x957b8860 -0, 152, 152, 1, 152064, 0x56161560 -0, 153, 153, 1, 152064, 0xbc43bc3b -0, 154, 154, 1, 152064, 0x508d8632 -0, 155, 155, 1, 152064, 0xbc5736d8 -0, 156, 156, 1, 152064, 0xed7d3aef -0, 157, 157, 1, 152064, 0x1dcdda9f -0, 158, 158, 1, 152064, 0x8ef6d5c9 -0, 159, 159, 1, 152064, 0x15466acc -0, 160, 160, 1, 152064, 0x45d4cf67 -0, 161, 161, 1, 152064, 0x8c900b9d -0, 162, 162, 1, 152064, 0x747006e0 -0, 163, 163, 1, 152064, 0xac920a0c -0, 164, 164, 1, 152064, 0xb8210c27 -0, 165, 165, 1, 152064, 0x7dbb873a -0, 166, 166, 1, 152064, 0x0d4d7584 -0, 167, 167, 1, 152064, 0xefb3fe60 -0, 168, 168, 1, 152064, 0x905e2644 -0, 169, 169, 1, 152064, 0x7c04e534 -0, 170, 170, 1, 152064, 0x8889972a -0, 171, 171, 1, 152064, 0x21c7d8ad -0, 172, 172, 1, 152064, 0x1c641176 -0, 173, 173, 1, 152064, 0xf71489a4 -0, 174, 174, 1, 152064, 0xd7ac5555 -0, 175, 175, 1, 152064, 0xb4609c6d -0, 176, 176, 1, 152064, 0xf5b2bd5e -0, 177, 177, 1, 152064, 0x9f43ce57 -0, 178, 178, 1, 152064, 0x77642dd3 -0, 179, 179, 1, 152064, 0x3e79565c -0, 180, 180, 1, 152064, 0x95f40b8e -0, 181, 181, 1, 152064, 0x3c8ca4d4 -0, 182, 182, 1, 152064, 0xa02ac497 -0, 183, 183, 1, 152064, 0x4c93b377 -0, 184, 184, 1, 152064, 0x55f5ac68 -0, 185, 185, 1, 152064, 0xf8652eca -0, 186, 186, 1, 152064, 0x56e94574 -0, 187, 187, 1, 152064, 0x6d8302e1 -0, 188, 188, 1, 152064, 0x29a57061 -0, 189, 189, 1, 152064, 0x24e4cfdc -0, 190, 190, 1, 152064, 0xf5a5d62a -0, 191, 191, 1, 152064, 0x998870c1 -0, 192, 192, 1, 152064, 0xa15b1f4e -0, 193, 193, 1, 152064, 0xb0ccb51f -0, 194, 194, 1, 152064, 0xeaaf59ab -0, 195, 195, 1, 152064, 0x7e2b4fe6 -0, 196, 196, 1, 152064, 0x72299fea -0, 197, 197, 1, 152064, 0x769da8b2 -0, 198, 198, 1, 152064, 0xefad7ef8 -0, 199, 199, 1, 152064, 0x24819983 -0, 200, 200, 1, 152064, 0x2aad32ab -0, 201, 201, 1, 152064, 0xc80cac79 -0, 202, 202, 1, 152064, 0x1659d628 -0, 203, 203, 1, 152064, 0xef941f66 -0, 204, 204, 1, 152064, 0x0d7fcdb5 -0, 205, 205, 1, 152064, 0x7c1853fa -0, 206, 206, 1, 152064, 0xb94c4d3c -0, 207, 207, 1, 152064, 0xc47adfc2 -0, 208, 208, 1, 152064, 0x366a6729 -0, 209, 209, 1, 152064, 0x7eb37b70 -0, 210, 210, 1, 152064, 0xafd54c27 -0, 211, 211, 1, 152064, 0x67b18636 -0, 212, 212, 1, 152064, 0x93b22dcf -0, 213, 213, 1, 152064, 0xa64991f1 -0, 214, 214, 1, 152064, 0xd32a7102 -0, 215, 215, 1, 152064, 0xff665d1c -0, 216, 216, 1, 152064, 0xf107cc31 -0, 217, 217, 1, 152064, 0xf5b25652 -0, 218, 218, 1, 152064, 0x8caf783d -0, 219, 219, 1, 152064, 0x72f3eb00 -0, 220, 220, 1, 152064, 0xb5aea5f8 -0, 221, 221, 1, 152064, 0xee70e870 -0, 222, 222, 1, 152064, 0x7c3a0156 -0, 223, 223, 1, 152064, 0x871b6383 -0, 224, 224, 1, 152064, 0x48d831ff -0, 225, 225, 1, 152064, 0xca233913 -0, 226, 226, 1, 152064, 0xe14bc5eb -0, 227, 227, 1, 152064, 0x9b1d27e7 -0, 228, 228, 1, 152064, 0xfb9637f7 -0, 229, 229, 1, 152064, 0x0c022157 -0, 230, 230, 1, 152064, 0x16d35fc9 -0, 231, 231, 1, 152064, 0x6d935f71 -0, 232, 232, 1, 152064, 0xae4066fa -0, 233, 233, 1, 152064, 0xcef94fdc -0, 234, 234, 1, 152064, 0xc234edb9 -0, 235, 235, 1, 152064, 0x26a4f2e2 -0, 236, 236, 1, 152064, 0xd29ac23e -0, 237, 237, 1, 152064, 0xb7604395 -0, 238, 238, 1, 152064, 0x408084f6 -0, 239, 239, 1, 152064, 0x0a02026c -0, 240, 240, 1, 152064, 0x78b33c7c -0, 241, 241, 1, 152064, 0xcb02b874 -0, 242, 242, 1, 152064, 0xf566513b -0, 243, 243, 1, 152064, 0xb34e52b1 -0, 244, 244, 1, 152064, 0xf55ff493 -0, 245, 245, 1, 152064, 0xb0e8282a -0, 246, 246, 1, 152064, 0xe9510bbe -0, 247, 247, 1, 152064, 0x292e8c5a -0, 248, 248, 1, 152064, 0x62b9d2b0 -0, 249, 249, 1, 152064, 0x3a8cc827 -0, 250, 250, 1, 152064, 0x25cc465e -0, 251, 251, 1, 152064, 0xf2bc32e2 -0, 252, 252, 1, 152064, 0x6141f914 -0, 253, 253, 1, 152064, 0x1171256f -0, 254, 254, 1, 152064, 0x13cb2ded -0, 255, 255, 1, 152064, 0x3d4ca557 -0, 256, 256, 1, 152064, 0xf2b9e72e -0, 257, 257, 1, 152064, 0x03f7547a -0, 258, 258, 1, 152064, 0xc7302955 -0, 259, 259, 1, 152064, 0xe78a46d3 -0, 260, 260, 1, 152064, 0x3726a270 -0, 261, 261, 1, 152064, 0x2f65722a -0, 262, 262, 1, 152064, 0x55acce40 -0, 263, 263, 1, 152064, 0xf6fa9db2 -0, 264, 264, 1, 152064, 0x70a36937 -0, 265, 265, 1, 152064, 0x9313742d -0, 266, 266, 1, 152064, 0x2eb14e53 -0, 267, 267, 1, 152064, 0x3d47c9c3 -0, 268, 268, 1, 152064, 0xd0a90348 -0, 269, 269, 1, 152064, 0x6ad48088 -0, 270, 270, 1, 152064, 0x68e64738 -0, 271, 271, 1, 152064, 0x04c3735a -0, 272, 272, 1, 152064, 0x51d0593f -0, 273, 273, 1, 152064, 0x42cf2b48 -0, 274, 274, 1, 152064, 0xa5496a0c -0, 275, 275, 1, 152064, 0x84c25549 -0, 276, 276, 1, 152064, 0x96691600 -0, 277, 277, 1, 152064, 0x423135db -0, 278, 278, 1, 152064, 0x8d2e08b6 -0, 279, 279, 1, 152064, 0xaeb4c840 -0, 280, 280, 1, 152064, 0xf3e71780 -0, 281, 281, 1, 152064, 0x8858228b -0, 282, 282, 1, 152064, 0xf28613f8 -0, 283, 283, 1, 152064, 0xb5327882 -0, 284, 284, 1, 152064, 0xbb60bb85 -0, 285, 285, 1, 152064, 0x345ab1c9 -0, 286, 286, 1, 152064, 0x8aac2cba -0, 287, 287, 1, 152064, 0x7ce15b4c -0, 288, 288, 1, 152064, 0xc09c55c0 -0, 289, 289, 1, 152064, 0x8482ddd6 -0, 290, 290, 1, 152064, 0xab222a13 -0, 291, 291, 1, 152064, 0xd39b0dea -0, 292, 292, 1, 152064, 0x6dab6e06 -0, 293, 293, 1, 152064, 0xec0891bd -0, 294, 294, 1, 152064, 0x88bd9701 -0, 295, 295, 1, 152064, 0xdf13072a -0, 296, 296, 1, 152064, 0x23b33081 -0, 297, 297, 1, 152064, 0x63943137 -0, 298, 298, 1, 152064, 0xab6a9052 -0, 299, 299, 1, 152064, 0x05485494 +0, 1, 1, 1, 152064, 0x502ec077 +0, 2, 2, 1, 152064, 0x84807243 +0, 3, 3, 1, 152064, 0xd7474a6e +0, 4, 4, 1, 152064, 0x793469bb +0, 5, 5, 1, 152064, 0xb7a0faf7 +0, 6, 6, 1, 152064, 0x1d3d3cba +0, 7, 7, 1, 152064, 0xb62583de +0, 8, 8, 1, 152064, 0xc8422fb1 +0, 9, 9, 1, 152064, 0x321dc699 +0, 10, 10, 1, 152064, 0x7a34d350 +0, 11, 11, 1, 152064, 0xaa4c302d +0, 12, 12, 1, 152064, 0x45fa7ab0 +0, 13, 13, 1, 152064, 0xc7262e41 +0, 14, 14, 1, 152064, 0x3550000c +0, 15, 15, 1, 152064, 0xf4bab54b +0, 16, 16, 1, 152064, 0xaccf9c1a +0, 17, 17, 1, 152064, 0x9bee20e9 +0, 18, 18, 1, 152064, 0x47fb7720 +0, 19, 19, 1, 152064, 0x12c63ffb +0, 20, 20, 1, 152064, 0xfa2b8b4d +0, 21, 21, 1, 152064, 0x279964bd +0, 22, 22, 1, 152064, 0xb8b01c7e +0, 23, 23, 1, 152064, 0x816fa010 +0, 24, 24, 1, 152064, 0x59fe1c8c +0, 25, 25, 1, 152064, 0x13393fad +0, 26, 26, 1, 152064, 0x991a50a4 +0, 27, 27, 1, 152064, 0x57df3eb7 +0, 28, 28, 1, 152064, 0x744371df +0, 29, 29, 1, 152064, 0xe9f6d3ff +0, 30, 30, 1, 152064, 0xc506fba0 +0, 31, 31, 1, 152064, 0x6295b90e +0, 32, 32, 1, 152064, 0xa19cee2d +0, 33, 33, 1, 152064, 0xf8c1b3ca +0, 34, 34, 1, 152064, 0x69f68ce0 +0, 35, 35, 1, 152064, 0x80558bb6 +0, 36, 36, 1, 152064, 0x27824fa5 +0, 37, 37, 1, 152064, 0x27c929a1 +0, 38, 38, 1, 152064, 0xc0fe06d1 +0, 39, 39, 1, 152064, 0xc52bc58c +0, 40, 40, 1, 152064, 0x0a5363c7 +0, 41, 41, 1, 152064, 0xd0f45a0d +0, 42, 42, 1, 152064, 0x274710f9 +0, 43, 43, 1, 152064, 0x89d2d390 +0, 44, 44, 1, 152064, 0x12a9bfb0 +0, 45, 45, 1, 152064, 0x04501a93 +0, 46, 46, 1, 152064, 0xf92cbbf4 +0, 47, 47, 1, 152064, 0xf6d1b27d +0, 48, 48, 1, 152064, 0xe3e904c3 +0, 49, 49, 1, 152064, 0x58f8516d +0, 50, 50, 1, 152064, 0x70370c2b +0, 51, 51, 1, 152064, 0xfeebc88c +0, 52, 52, 1, 152064, 0x974c6ed6 +0, 53, 53, 1, 152064, 0x401bdcf2 +0, 54, 54, 1, 152064, 0xfe61e278 +0, 55, 55, 1, 152064, 0x96ba8bb9 +0, 56, 56, 1, 152064, 0x988492fd +0, 57, 57, 1, 152064, 0xd1d913a9 +0, 58, 58, 1, 152064, 0x6bc46f0e +0, 59, 59, 1, 152064, 0x695ef706 +0, 60, 60, 1, 152064, 0x142045c9 +0, 61, 61, 1, 152064, 0xb390ed87 +0, 62, 62, 1, 152064, 0xb9e6d2e5 +0, 63, 63, 1, 152064, 0xe348797f +0, 64, 64, 1, 152064, 0x1cbd29d6 +0, 65, 65, 1, 152064, 0xbd7dd694 +0, 66, 66, 1, 152064, 0x516873c3 +0, 67, 67, 1, 152064, 0x27bba182 +0, 68, 68, 1, 152064, 0x7541f920 +0, 69, 69, 1, 152064, 0xfdf67042 +0, 70, 70, 1, 152064, 0x6c3c7896 +0, 71, 71, 1, 152064, 0xed86c467 +0, 72, 72, 1, 152064, 0x4ea83ca2 +0, 73, 73, 1, 152064, 0xa3e6725b +0, 74, 74, 1, 152064, 0x917f5f16 +0, 75, 75, 1, 152064, 0x8cf2d2e1 +0, 76, 76, 1, 152064, 0x57a8d116 +0, 77, 77, 1, 152064, 0x0db267d4 +0, 78, 78, 1, 152064, 0xce782ac5 +0, 79, 79, 1, 152064, 0x1c9d8518 +0, 80, 80, 1, 152064, 0x47598ac7 +0, 81, 81, 1, 152064, 0xc5033d97 +0, 82, 82, 1, 152064, 0xd7aaa3a4 +0, 83, 83, 1, 152064, 0x078afc96 +0, 84, 84, 1, 152064, 0xc9fe673d +0, 85, 85, 1, 152064, 0xe9284066 +0, 86, 86, 1, 152064, 0xbc570982 +0, 87, 87, 1, 152064, 0x0aac8574 +0, 88, 88, 1, 152064, 0x098cbeee +0, 89, 89, 1, 152064, 0x19c36a9d +0, 90, 90, 1, 152064, 0x8fe4a893 +0, 91, 91, 1, 152064, 0x0b652f17 +0, 92, 92, 1, 152064, 0x10f2e6bf +0, 93, 93, 1, 152064, 0x7ce5634e +0, 94, 94, 1, 152064, 0x8fe4ac6c +0, 95, 95, 1, 152064, 0xcaba749e +0, 96, 96, 1, 152064, 0x5f8a0d5c +0, 97, 97, 1, 152064, 0xcaa66bbc +0, 98, 98, 1, 152064, 0xc87ae617 +0, 99, 99, 1, 152064, 0xe8ef4dd7 +0, 100, 100, 1, 152064, 0xdfca5a07 +0, 101, 101, 1, 152064, 0x5f7eab7d +0, 102, 102, 1, 152064, 0x8a65ebbb +0, 103, 103, 1, 152064, 0x4beab4a0 +0, 104, 104, 1, 152064, 0xb5e6ab30 +0, 105, 105, 1, 152064, 0x8fe4f4d4 +0, 106, 106, 1, 152064, 0x95bde1ca +0, 107, 107, 1, 152064, 0xcc5e3a53 +0, 108, 108, 1, 152064, 0xf09f1dd7 +0, 109, 109, 1, 152064, 0x10179672 +0, 110, 110, 1, 152064, 0x4ad16184 +0, 111, 111, 1, 152064, 0x9efa0e23 +0, 112, 112, 1, 152064, 0x22f59522 +0, 113, 113, 1, 152064, 0x4d38f09d +0, 114, 114, 1, 152064, 0x4c5ebf56 +0, 115, 115, 1, 152064, 0xb19d5077 +0, 116, 116, 1, 152064, 0xa98576b9 +0, 117, 117, 1, 152064, 0x65324239 +0, 118, 118, 1, 152064, 0x709e4031 +0, 119, 119, 1, 152064, 0xf8e81681 +0, 120, 120, 1, 152064, 0x058514e5 +0, 121, 121, 1, 152064, 0xd1d1c806 +0, 122, 122, 1, 152064, 0x0e4dde57 +0, 123, 123, 1, 152064, 0x49e9c2bb +0, 124, 124, 1, 152064, 0x01417ce6 +0, 125, 125, 1, 152064, 0xda7ebbf1 +0, 126, 126, 1, 152064, 0xa22906b7 +0, 127, 127, 1, 152064, 0x32e2df87 +0, 128, 128, 1, 152064, 0x69917c8f +0, 129, 129, 1, 152064, 0xea8ed2cc +0, 130, 130, 1, 152064, 0x0b8d57f1 +0, 131, 131, 1, 152064, 0x5f683bcd +0, 132, 132, 1, 152064, 0x5162fe2f +0, 133, 133, 1, 152064, 0x49c052f8 +0, 134, 134, 1, 152064, 0x990b69ba +0, 135, 135, 1, 152064, 0xa6d4f99f +0, 136, 136, 1, 152064, 0xe79ef4da +0, 137, 137, 1, 152064, 0x5e8a3847 +0, 138, 138, 1, 152064, 0x38b1e75f +0, 139, 139, 1, 152064, 0xf5c91bed +0, 140, 140, 1, 152064, 0xd59a6d26 +0, 141, 141, 1, 152064, 0xc361de06 +0, 142, 142, 1, 152064, 0x63ed2229 +0, 143, 143, 1, 152064, 0xb8229205 +0, 144, 144, 1, 152064, 0x7c6619af +0, 145, 145, 1, 152064, 0x4126b02f +0, 146, 146, 1, 152064, 0x9250b99b +0, 147, 147, 1, 152064, 0x589778f9 +0, 148, 148, 1, 152064, 0xed1fa45b +0, 149, 149, 1, 152064, 0x700b6f32 +0, 150, 150, 1, 152064, 0x0590df55 +0, 151, 151, 1, 152064, 0x3e9c4018 +0, 152, 152, 1, 152064, 0x957b8860 +0, 153, 153, 1, 152064, 0x56161560 +0, 154, 154, 1, 152064, 0xbc43bc3b +0, 155, 155, 1, 152064, 0x508d8632 +0, 156, 156, 1, 152064, 0xbc5736d8 +0, 157, 157, 1, 152064, 0xed7d3aef +0, 158, 158, 1, 152064, 0x1dcdda9f +0, 159, 159, 1, 152064, 0x8ef6d5c9 +0, 160, 160, 1, 152064, 0x15466acc +0, 161, 161, 1, 152064, 0x45d4cf67 +0, 162, 162, 1, 152064, 0x8c900b9d +0, 163, 163, 1, 152064, 0x747006e0 +0, 164, 164, 1, 152064, 0xac920a0c +0, 165, 165, 1, 152064, 0xb8210c27 +0, 166, 166, 1, 152064, 0x7dbb873a +0, 167, 167, 1, 152064, 0x0d4d7584 +0, 168, 168, 1, 152064, 0xefb3fe60 +0, 169, 169, 1, 152064, 0x905e2644 +0, 170, 170, 1, 152064, 0x7c04e534 +0, 171, 171, 1, 152064, 0x8889972a +0, 172, 172, 1, 152064, 0x21c7d8ad +0, 173, 173, 1, 152064, 0x1c641176 +0, 174, 174, 1, 152064, 0xf71489a4 +0, 175, 175, 1, 152064, 0xd7ac5555 +0, 176, 176, 1, 152064, 0xb4609c6d +0, 177, 177, 1, 152064, 0xf5b2bd5e +0, 178, 178, 1, 152064, 0x9f43ce57 +0, 179, 179, 1, 152064, 0x77642dd3 +0, 180, 180, 1, 152064, 0x3e79565c +0, 181, 181, 1, 152064, 0x95f40b8e +0, 182, 182, 1, 152064, 0x3c8ca4d4 +0, 183, 183, 1, 152064, 0xa02ac497 +0, 184, 184, 1, 152064, 0x4c93b377 +0, 185, 185, 1, 152064, 0x55f5ac68 +0, 186, 186, 1, 152064, 0xf8652eca +0, 187, 187, 1, 152064, 0x56e94574 +0, 188, 188, 1, 152064, 0x6d8302e1 +0, 189, 189, 1, 152064, 0x29a57061 +0, 190, 190, 1, 152064, 0x24e4cfdc +0, 191, 191, 1, 152064, 0xf5a5d62a +0, 192, 192, 1, 152064, 0x998870c1 +0, 193, 193, 1, 152064, 0xa15b1f4e +0, 194, 194, 1, 152064, 0xb0ccb51f +0, 195, 195, 1, 152064, 0xeaaf59ab +0, 196, 196, 1, 152064, 0x7e2b4fe6 +0, 197, 197, 1, 152064, 0x72299fea +0, 198, 198, 1, 152064, 0x769da8b2 +0, 199, 199, 1, 152064, 0xefad7ef8 +0, 200, 200, 1, 152064, 0x24819983 +0, 201, 201, 1, 152064, 0x2aad32ab +0, 202, 202, 1, 152064, 0xc80cac79 +0, 203, 203, 1, 152064, 0x1659d628 +0, 204, 204, 1, 152064, 0xef941f66 +0, 205, 205, 1, 152064, 0x0d7fcdb5 +0, 206, 206, 1, 152064, 0x7c1853fa +0, 207, 207, 1, 152064, 0xb94c4d3c +0, 208, 208, 1, 152064, 0xc47adfc2 +0, 209, 209, 1, 152064, 0x366a6729 +0, 210, 210, 1, 152064, 0x7eb37b70 +0, 211, 211, 1, 152064, 0xafd54c27 +0, 212, 212, 1, 152064, 0x67b18636 +0, 213, 213, 1, 152064, 0x93b22dcf +0, 214, 214, 1, 152064, 0xa64991f1 +0, 215, 215, 1, 152064, 0xd32a7102 +0, 216, 216, 1, 152064, 0xff665d1c +0, 217, 217, 1, 152064, 0xf107cc31 +0, 218, 218, 1, 152064, 0xf5b25652 +0, 219, 219, 1, 152064, 0x8caf783d +0, 220, 220, 1, 152064, 0x72f3eb00 +0, 221, 221, 1, 152064, 0xb5aea5f8 +0, 222, 222, 1, 152064, 0xee70e870 +0, 223, 223, 1, 152064, 0x7c3a0156 +0, 224, 224, 1, 152064, 0x871b6383 +0, 225, 225, 1, 152064, 0x48d831ff +0, 226, 226, 1, 152064, 0xca233913 +0, 227, 227, 1, 152064, 0xe14bc5eb +0, 228, 228, 1, 152064, 0x9b1d27e7 +0, 229, 229, 1, 152064, 0xfb9637f7 +0, 230, 230, 1, 152064, 0x0c022157 +0, 231, 231, 1, 152064, 0x16d35fc9 +0, 232, 232, 1, 152064, 0x6d935f71 +0, 233, 233, 1, 152064, 0xae4066fa +0, 234, 234, 1, 152064, 0xcef94fdc +0, 235, 235, 1, 152064, 0xc234edb9 +0, 236, 236, 1, 152064, 0x26a4f2e2 +0, 237, 237, 1, 152064, 0xd29ac23e +0, 238, 238, 1, 152064, 0xb7604395 +0, 239, 239, 1, 152064, 0x408084f6 +0, 240, 240, 1, 152064, 0x0a02026c +0, 241, 241, 1, 152064, 0x78b33c7c +0, 242, 242, 1, 152064, 0xcb02b874 +0, 243, 243, 1, 152064, 0xf566513b +0, 244, 244, 1, 152064, 0xb34e52b1 +0, 245, 245, 1, 152064, 0xf55ff493 +0, 246, 246, 1, 152064, 0xb0e8282a +0, 247, 247, 1, 152064, 0xe9510bbe +0, 248, 248, 1, 152064, 0x292e8c5a +0, 249, 249, 1, 152064, 0x62b9d2b0 +0, 250, 250, 1, 152064, 0x3a8cc827 +0, 251, 251, 1, 152064, 0x25cc465e +0, 252, 252, 1, 152064, 0xf2bc32e2 +0, 253, 253, 1, 152064, 0x6141f914 +0, 254, 254, 1, 152064, 0x1171256f +0, 255, 255, 1, 152064, 0x13cb2ded +0, 256, 256, 1, 152064, 0x3d4ca557 +0, 257, 257, 1, 152064, 0xf2b9e72e +0, 258, 258, 1, 152064, 0x03f7547a +0, 259, 259, 1, 152064, 0xc7302955 +0, 260, 260, 1, 152064, 0xe78a46d3 +0, 261, 261, 1, 152064, 0x3726a270 +0, 262, 262, 1, 152064, 0x2f65722a +0, 263, 263, 1, 152064, 0x55acce40 +0, 264, 264, 1, 152064, 0xf6fa9db2 +0, 265, 265, 1, 152064, 0x70a36937 +0, 266, 266, 1, 152064, 0x9313742d +0, 267, 267, 1, 152064, 0x2eb14e53 +0, 268, 268, 1, 152064, 0x3d47c9c3 +0, 269, 269, 1, 152064, 0xd0a90348 +0, 270, 270, 1, 152064, 0x6ad48088 +0, 271, 271, 1, 152064, 0x68e64738 +0, 272, 272, 1, 152064, 0x04c3735a +0, 273, 273, 1, 152064, 0x51d0593f +0, 274, 274, 1, 152064, 0x42cf2b48 +0, 275, 275, 1, 152064, 0xa5496a0c +0, 276, 276, 1, 152064, 0x84c25549 +0, 277, 277, 1, 152064, 0x96691600 +0, 278, 278, 1, 152064, 0x423135db +0, 279, 279, 1, 152064, 0x8d2e08b6 +0, 280, 280, 1, 152064, 0xaeb4c840 +0, 281, 281, 1, 152064, 0xf3e71780 +0, 282, 282, 1, 152064, 0x8858228b +0, 283, 283, 1, 152064, 0xf28613f8 +0, 284, 284, 1, 152064, 0xb5327882 +0, 285, 285, 1, 152064, 0xbb60bb85 +0, 286, 286, 1, 152064, 0x345ab1c9 +0, 287, 287, 1, 152064, 0x8aac2cba +0, 288, 288, 1, 152064, 0x7ce15b4c +0, 289, 289, 1, 152064, 0xc09c55c0 +0, 290, 290, 1, 152064, 0x8482ddd6 +0, 291, 291, 1, 152064, 0xab222a13 +0, 292, 292, 1, 152064, 0xd39b0dea +0, 293, 293, 1, 152064, 0x6dab6e06 +0, 294, 294, 1, 152064, 0xec0891bd +0, 295, 295, 1, 152064, 0x88bd9701 +0, 296, 296, 1, 152064, 0xdf13072a +0, 297, 297, 1, 152064, 0x23b33081 +0, 298, 298, 1, 152064, 0x63943137 +0, 299, 299, 1, 152064, 0xab6a9052 +0, 300, 300, 1, 152064, 0x05485494 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-hpcvflnl_bcrm_a ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-hpcvflnl_bcrm_a --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-frext-hpcvflnl_bcrm_a 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-frext-hpcvflnl_bcrm_a 2021-04-08 21:28:40.000000000 +0000 @@ -3,303 +3,303 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0x3e39c08b -0, 1, 1, 1, 152064, 0xabc67990 -0, 2, 2, 1, 152064, 0x19614e74 -0, 3, 3, 1, 152064, 0xa3776beb -0, 4, 4, 1, 152064, 0xcce6ffdf -0, 5, 5, 1, 152064, 0xb0e94746 -0, 6, 6, 1, 152064, 0xdb1a84ef -0, 7, 7, 1, 152064, 0xb2624509 -0, 8, 8, 1, 152064, 0x32e2d826 -0, 9, 9, 1, 152064, 0xb3bddf0b -0, 10, 10, 1, 152064, 0x2e273ce3 -0, 11, 11, 1, 152064, 0x67af7e4d -0, 12, 12, 1, 152064, 0x505c3261 -0, 13, 13, 1, 152064, 0xa43d015e -0, 14, 14, 1, 152064, 0xad41c1f6 -0, 15, 15, 1, 152064, 0x633ba55f -0, 16, 16, 1, 152064, 0xe80634f0 -0, 17, 17, 1, 152064, 0x80a07dc9 -0, 18, 18, 1, 152064, 0x0e7a3bbf -0, 19, 19, 1, 152064, 0xcb099196 -0, 20, 20, 1, 152064, 0x57c96db5 -0, 21, 21, 1, 152064, 0xccd422fa -0, 22, 22, 1, 152064, 0x0850b7a7 -0, 23, 23, 1, 152064, 0x30e33156 -0, 24, 24, 1, 152064, 0x34e13f9a -0, 25, 25, 1, 152064, 0x03d36000 -0, 26, 26, 1, 152064, 0xbf7d49da -0, 27, 27, 1, 152064, 0x77336d09 -0, 28, 28, 1, 152064, 0xca8be5a9 -0, 29, 29, 1, 152064, 0xe57c0b08 -0, 30, 30, 1, 152064, 0xbe77c093 -0, 31, 31, 1, 152064, 0x6bf1ff05 -0, 32, 32, 1, 152064, 0x9142babf -0, 33, 33, 1, 152064, 0x08db8e67 -0, 34, 34, 1, 152064, 0x69ac8cb6 -0, 35, 35, 1, 152064, 0xaa3b5c88 -0, 36, 36, 1, 152064, 0x9bd32638 -0, 37, 37, 1, 152064, 0x7972115a -0, 38, 38, 1, 152064, 0x5c1dd47b -0, 39, 39, 1, 152064, 0x8a196e02 -0, 40, 40, 1, 152064, 0xa89672bc -0, 41, 41, 1, 152064, 0x27b220e4 -0, 42, 42, 1, 152064, 0xfa38dc4a -0, 43, 43, 1, 152064, 0x4784c639 -0, 44, 44, 1, 152064, 0xa5e4229a -0, 45, 45, 1, 152064, 0xa986bdfc -0, 46, 46, 1, 152064, 0x2951b47b -0, 47, 47, 1, 152064, 0x4df404a6 -0, 48, 48, 1, 152064, 0xc75155e8 -0, 49, 49, 1, 152064, 0xfc05248c -0, 50, 50, 1, 152064, 0x5d53da10 -0, 51, 51, 1, 152064, 0x284376ec -0, 52, 52, 1, 152064, 0x19fce380 -0, 53, 53, 1, 152064, 0x876be6c9 -0, 54, 54, 1, 152064, 0x39eb8ff9 -0, 55, 55, 1, 152064, 0x289c9543 -0, 56, 56, 1, 152064, 0x24dd2356 -0, 57, 57, 1, 152064, 0x1dc17d3c -0, 58, 58, 1, 152064, 0xd17c00ac -0, 59, 59, 1, 152064, 0xc2ad54de -0, 60, 60, 1, 152064, 0xbe11ee2f -0, 61, 61, 1, 152064, 0x3db9dc89 -0, 62, 62, 1, 152064, 0xac0d7bc2 -0, 63, 63, 1, 152064, 0x8dab2dde -0, 64, 64, 1, 152064, 0x566ad225 -0, 65, 65, 1, 152064, 0x587c7853 -0, 66, 66, 1, 152064, 0x601c9c80 -0, 67, 67, 1, 152064, 0x2afaf751 -0, 68, 68, 1, 152064, 0x1c9f7e3a -0, 69, 69, 1, 152064, 0x899475bf -0, 70, 70, 1, 152064, 0x0d65c7d9 -0, 71, 71, 1, 152064, 0xafd63d12 -0, 72, 72, 1, 152064, 0x162e62b9 -0, 73, 73, 1, 152064, 0x5c9554be -0, 74, 74, 1, 152064, 0x35fbdaa2 -0, 75, 75, 1, 152064, 0x6438cbd8 -0, 76, 76, 1, 152064, 0xde0772c9 -0, 77, 77, 1, 152064, 0x79f82854 -0, 78, 78, 1, 152064, 0x86957840 -0, 79, 79, 1, 152064, 0xd9468cbf -0, 80, 80, 1, 152064, 0x23e74609 -0, 81, 81, 1, 152064, 0x3919a146 -0, 82, 82, 1, 152064, 0xd641078b -0, 83, 83, 1, 152064, 0x24397220 -0, 84, 84, 1, 152064, 0xe7fc3a7c -0, 85, 85, 1, 152064, 0x3997154a -0, 86, 86, 1, 152064, 0x2af3952c -0, 87, 87, 1, 152064, 0x274ac07a -0, 88, 88, 1, 152064, 0x288f7b09 -0, 89, 89, 1, 152064, 0xe6f9b022 -0, 90, 90, 1, 152064, 0xf09e2fbb -0, 91, 91, 1, 152064, 0x7244e477 -0, 92, 92, 1, 152064, 0x0dfc72eb -0, 93, 93, 1, 152064, 0x0322b21f -0, 94, 94, 1, 152064, 0x18b08205 -0, 95, 95, 1, 152064, 0x6606153e -0, 96, 96, 1, 152064, 0x85186272 -0, 97, 97, 1, 152064, 0x3369f064 -0, 98, 98, 1, 152064, 0xbe0d5a44 -0, 99, 99, 1, 152064, 0x320258bb -0, 100, 100, 1, 152064, 0x4d6fb091 -0, 101, 101, 1, 152064, 0xc9bbf5e7 -0, 102, 102, 1, 152064, 0x0aa1b69b -0, 103, 103, 1, 152064, 0x85b9ac11 -0, 104, 104, 1, 152064, 0xb25ff818 -0, 105, 105, 1, 152064, 0xa155dc25 -0, 106, 106, 1, 152064, 0xa8e03bfd -0, 107, 107, 1, 152064, 0x0a862956 -0, 108, 108, 1, 152064, 0x11b49264 -0, 109, 109, 1, 152064, 0xa94e664e -0, 110, 110, 1, 152064, 0x330e0fa2 -0, 111, 111, 1, 152064, 0xaf3d9518 -0, 112, 112, 1, 152064, 0x0836f2e8 -0, 113, 113, 1, 152064, 0xbf6dc578 -0, 114, 114, 1, 152064, 0x7b524d20 -0, 115, 115, 1, 152064, 0x9ef7677f -0, 116, 116, 1, 152064, 0xeacf3f34 -0, 117, 117, 1, 152064, 0xfb4e3dbe -0, 118, 118, 1, 152064, 0xb46e25cb -0, 119, 119, 1, 152064, 0x363c1603 -0, 120, 120, 1, 152064, 0x263fc542 -0, 121, 121, 1, 152064, 0xf106e548 -0, 122, 122, 1, 152064, 0xde43c56a -0, 123, 123, 1, 152064, 0xc2c4770a -0, 124, 124, 1, 152064, 0x122fce19 -0, 125, 125, 1, 152064, 0x3ba01434 -0, 126, 126, 1, 152064, 0x0e8ce5ee -0, 127, 127, 1, 152064, 0x6ceb82e1 -0, 128, 128, 1, 152064, 0xa23ee21c -0, 129, 129, 1, 152064, 0xc6d960f9 -0, 130, 130, 1, 152064, 0x0de15258 -0, 131, 131, 1, 152064, 0x187b0333 -0, 132, 132, 1, 152064, 0x92e6582f -0, 133, 133, 1, 152064, 0xb9586ce0 -0, 134, 134, 1, 152064, 0xefd803b5 -0, 135, 135, 1, 152064, 0x24eafb29 -0, 136, 136, 1, 152064, 0x20c73b14 -0, 137, 137, 1, 152064, 0xbd7ceaaa -0, 138, 138, 1, 152064, 0x775216c8 -0, 139, 139, 1, 152064, 0xa08971c7 -0, 140, 140, 1, 152064, 0xef0ee865 -0, 141, 141, 1, 152064, 0x9ac61c2f -0, 142, 142, 1, 152064, 0x52ae8ea9 -0, 143, 143, 1, 152064, 0x06571c14 -0, 144, 144, 1, 152064, 0x6e78ad33 -0, 145, 145, 1, 152064, 0xad01c627 -0, 146, 146, 1, 152064, 0xbfe074d3 -0, 147, 147, 1, 152064, 0x9357a183 -0, 148, 148, 1, 152064, 0x8de7767f -0, 149, 149, 1, 152064, 0xa5e6e76e -0, 150, 150, 1, 152064, 0xa6f646fe -0, 151, 151, 1, 152064, 0x132e99f8 -0, 152, 152, 1, 152064, 0xb79f27de -0, 153, 153, 1, 152064, 0x36d3cdcf -0, 154, 154, 1, 152064, 0xdc938336 -0, 155, 155, 1, 152064, 0xacaa3a7f -0, 156, 156, 1, 152064, 0xc61a37fd -0, 157, 157, 1, 152064, 0x4fe1ddf0 -0, 158, 158, 1, 152064, 0xc0f7d660 -0, 159, 159, 1, 152064, 0xd72458ea -0, 160, 160, 1, 152064, 0x6978d123 -0, 161, 161, 1, 152064, 0x64e60ccf -0, 162, 162, 1, 152064, 0xaa07004c -0, 163, 163, 1, 152064, 0x07cd1064 -0, 164, 164, 1, 152064, 0xa82320e5 -0, 165, 165, 1, 152064, 0xaedd8d30 -0, 166, 166, 1, 152064, 0x79b082ea -0, 167, 167, 1, 152064, 0x9ed800ab -0, 168, 168, 1, 152064, 0xde592bb4 -0, 169, 169, 1, 152064, 0xd966df88 -0, 170, 170, 1, 152064, 0xf921988a -0, 171, 171, 1, 152064, 0x557ad9ae -0, 172, 172, 1, 152064, 0xc3f31a9a -0, 173, 173, 1, 152064, 0x65248561 -0, 174, 174, 1, 152064, 0x63df4aa6 -0, 175, 175, 1, 152064, 0x618da0a9 -0, 176, 176, 1, 152064, 0xe6f1c435 -0, 177, 177, 1, 152064, 0x9f90c38f -0, 178, 178, 1, 152064, 0xd2853e14 -0, 179, 179, 1, 152064, 0x6e0268a9 -0, 180, 180, 1, 152064, 0x393712d1 -0, 181, 181, 1, 152064, 0x470da25f -0, 182, 182, 1, 152064, 0xaf55cb3d -0, 183, 183, 1, 152064, 0x6935b8b9 -0, 184, 184, 1, 152064, 0x5409a15f -0, 185, 185, 1, 152064, 0x09073fee -0, 186, 186, 1, 152064, 0xfb274e82 -0, 187, 187, 1, 152064, 0x1a770581 -0, 188, 188, 1, 152064, 0x17277d0d -0, 189, 189, 1, 152064, 0xd4dcd982 -0, 190, 190, 1, 152064, 0x6b04eaf3 -0, 191, 191, 1, 152064, 0x8a3d822e -0, 192, 192, 1, 152064, 0x1b971ec9 -0, 193, 193, 1, 152064, 0x14e0c0f6 -0, 194, 194, 1, 152064, 0x00667450 -0, 195, 195, 1, 152064, 0xd2385902 -0, 196, 196, 1, 152064, 0x905da6ab -0, 197, 197, 1, 152064, 0xa3ffb18b -0, 198, 198, 1, 152064, 0x10d48b19 -0, 199, 199, 1, 152064, 0xb2c7a3bd -0, 200, 200, 1, 152064, 0x45593e96 -0, 201, 201, 1, 152064, 0x47a0b60c -0, 202, 202, 1, 152064, 0x68c6d1b9 -0, 203, 203, 1, 152064, 0xbc881fcc -0, 204, 204, 1, 152064, 0x422cc6f2 -0, 205, 205, 1, 152064, 0x9b686410 -0, 206, 206, 1, 152064, 0x35dc5e86 -0, 207, 207, 1, 152064, 0x247bedaa -0, 208, 208, 1, 152064, 0x22b76fd1 -0, 209, 209, 1, 152064, 0x67cc7a75 -0, 210, 210, 1, 152064, 0xa197521e -0, 211, 211, 1, 152064, 0x428c8662 -0, 212, 212, 1, 152064, 0x33dc2c73 -0, 213, 213, 1, 152064, 0x5b538903 -0, 214, 214, 1, 152064, 0x3c4176b6 -0, 215, 215, 1, 152064, 0x774364ba -0, 216, 216, 1, 152064, 0xf237d03e -0, 217, 217, 1, 152064, 0xac8746fb -0, 218, 218, 1, 152064, 0x6b306a84 -0, 219, 219, 1, 152064, 0xa2ace513 -0, 220, 220, 1, 152064, 0x709c9be7 -0, 221, 221, 1, 152064, 0x2403f373 -0, 222, 222, 1, 152064, 0x147bf717 -0, 223, 223, 1, 152064, 0xe58964c8 -0, 224, 224, 1, 152064, 0xa0da36fc -0, 225, 225, 1, 152064, 0x1ac1355c -0, 226, 226, 1, 152064, 0x8a31c9f2 -0, 227, 227, 1, 152064, 0x42ba205c -0, 228, 228, 1, 152064, 0xa11b3575 -0, 229, 229, 1, 152064, 0xcb35207c -0, 230, 230, 1, 152064, 0x528f6189 -0, 231, 231, 1, 152064, 0x34f05bd7 -0, 232, 232, 1, 152064, 0x72317356 -0, 233, 233, 1, 152064, 0xaabd5028 -0, 234, 234, 1, 152064, 0x13dbeb7b -0, 235, 235, 1, 152064, 0x62f1e8a8 -0, 236, 236, 1, 152064, 0x1723bfcd -0, 237, 237, 1, 152064, 0x5c083c00 -0, 238, 238, 1, 152064, 0x52137894 -0, 239, 239, 1, 152064, 0xef1e082c -0, 240, 240, 1, 152064, 0x664b3d53 -0, 241, 241, 1, 152064, 0x2eb9b296 -0, 242, 242, 1, 152064, 0xd0ca511e -0, 243, 243, 1, 152064, 0x012d4724 -0, 244, 244, 1, 152064, 0xa847f5af -0, 245, 245, 1, 152064, 0x483a2fde -0, 246, 246, 1, 152064, 0xd1ab0257 -0, 247, 247, 1, 152064, 0x414692c7 -0, 248, 248, 1, 152064, 0x0b79df88 -0, 249, 249, 1, 152064, 0xdaa2c4a3 -0, 250, 250, 1, 152064, 0xd1b44500 -0, 251, 251, 1, 152064, 0xfd3d2cf3 -0, 252, 252, 1, 152064, 0xfdc0f748 -0, 253, 253, 1, 152064, 0xce762a2a -0, 254, 254, 1, 152064, 0x08b63572 -0, 255, 255, 1, 152064, 0x5a46a38d -0, 256, 256, 1, 152064, 0x03cee9c0 -0, 257, 257, 1, 152064, 0x9ee45473 -0, 258, 258, 1, 152064, 0x5a432386 -0, 259, 259, 1, 152064, 0x54c83d87 -0, 260, 260, 1, 152064, 0xc9caa1de -0, 261, 261, 1, 152064, 0xa28367f1 -0, 262, 262, 1, 152064, 0x2607cdf1 -0, 263, 263, 1, 152064, 0x06baa8de -0, 264, 264, 1, 152064, 0xf5346e32 -0, 265, 265, 1, 152064, 0x6d3e732b -0, 266, 266, 1, 152064, 0x798c584b -0, 267, 267, 1, 152064, 0x4076c948 -0, 268, 268, 1, 152064, 0x868cf63a -0, 269, 269, 1, 152064, 0x23107ac5 -0, 270, 270, 1, 152064, 0x306f3fe2 -0, 271, 271, 1, 152064, 0xbd1d71d6 -0, 272, 272, 1, 152064, 0x1429545f -0, 273, 273, 1, 152064, 0xaded29aa -0, 274, 274, 1, 152064, 0x9b455a94 -0, 275, 275, 1, 152064, 0xb3774ce7 -0, 276, 276, 1, 152064, 0x92580986 -0, 277, 277, 1, 152064, 0x0eae2f95 -0, 278, 278, 1, 152064, 0x599208b2 -0, 279, 279, 1, 152064, 0x4804c04c -0, 280, 280, 1, 152064, 0x5f730e8f -0, 281, 281, 1, 152064, 0x3e501d1e -0, 282, 282, 1, 152064, 0x32100740 -0, 283, 283, 1, 152064, 0x62226ff8 -0, 284, 284, 1, 152064, 0x7683b622 -0, 285, 285, 1, 152064, 0xc3e0aec1 -0, 286, 286, 1, 152064, 0xfac12608 -0, 287, 287, 1, 152064, 0xb21a5781 -0, 288, 288, 1, 152064, 0x8f1e4964 -0, 289, 289, 1, 152064, 0x0f62dd6e -0, 290, 290, 1, 152064, 0xac062ac4 -0, 291, 291, 1, 152064, 0x1b320f7a -0, 292, 292, 1, 152064, 0x346e7211 -0, 293, 293, 1, 152064, 0xe47592f3 -0, 294, 294, 1, 152064, 0xa3a7919c -0, 295, 295, 1, 152064, 0xa3580fa6 -0, 296, 296, 1, 152064, 0xc73430c1 -0, 297, 297, 1, 152064, 0x994a2c18 -0, 298, 298, 1, 152064, 0x0b5d8d45 -0, 299, 299, 1, 152064, 0x9eed5109 +0, 1, 1, 1, 152064, 0x3e39c08b +0, 2, 2, 1, 152064, 0xabc67990 +0, 3, 3, 1, 152064, 0x19614e74 +0, 4, 4, 1, 152064, 0xa3776beb +0, 5, 5, 1, 152064, 0xcce6ffdf +0, 6, 6, 1, 152064, 0xb0e94746 +0, 7, 7, 1, 152064, 0xdb1a84ef +0, 8, 8, 1, 152064, 0xb2624509 +0, 9, 9, 1, 152064, 0x32e2d826 +0, 10, 10, 1, 152064, 0xb3bddf0b +0, 11, 11, 1, 152064, 0x2e273ce3 +0, 12, 12, 1, 152064, 0x67af7e4d +0, 13, 13, 1, 152064, 0x505c3261 +0, 14, 14, 1, 152064, 0xa43d015e +0, 15, 15, 1, 152064, 0xad41c1f6 +0, 16, 16, 1, 152064, 0x633ba55f +0, 17, 17, 1, 152064, 0xe80634f0 +0, 18, 18, 1, 152064, 0x80a07dc9 +0, 19, 19, 1, 152064, 0x0e7a3bbf +0, 20, 20, 1, 152064, 0xcb099196 +0, 21, 21, 1, 152064, 0x57c96db5 +0, 22, 22, 1, 152064, 0xccd422fa +0, 23, 23, 1, 152064, 0x0850b7a7 +0, 24, 24, 1, 152064, 0x30e33156 +0, 25, 25, 1, 152064, 0x34e13f9a +0, 26, 26, 1, 152064, 0x03d36000 +0, 27, 27, 1, 152064, 0xbf7d49da +0, 28, 28, 1, 152064, 0x77336d09 +0, 29, 29, 1, 152064, 0xca8be5a9 +0, 30, 30, 1, 152064, 0xe57c0b08 +0, 31, 31, 1, 152064, 0xbe77c093 +0, 32, 32, 1, 152064, 0x6bf1ff05 +0, 33, 33, 1, 152064, 0x9142babf +0, 34, 34, 1, 152064, 0x08db8e67 +0, 35, 35, 1, 152064, 0x69ac8cb6 +0, 36, 36, 1, 152064, 0xaa3b5c88 +0, 37, 37, 1, 152064, 0x9bd32638 +0, 38, 38, 1, 152064, 0x7972115a +0, 39, 39, 1, 152064, 0x5c1dd47b +0, 40, 40, 1, 152064, 0x8a196e02 +0, 41, 41, 1, 152064, 0xa89672bc +0, 42, 42, 1, 152064, 0x27b220e4 +0, 43, 43, 1, 152064, 0xfa38dc4a +0, 44, 44, 1, 152064, 0x4784c639 +0, 45, 45, 1, 152064, 0xa5e4229a +0, 46, 46, 1, 152064, 0xa986bdfc +0, 47, 47, 1, 152064, 0x2951b47b +0, 48, 48, 1, 152064, 0x4df404a6 +0, 49, 49, 1, 152064, 0xc75155e8 +0, 50, 50, 1, 152064, 0xfc05248c +0, 51, 51, 1, 152064, 0x5d53da10 +0, 52, 52, 1, 152064, 0x284376ec +0, 53, 53, 1, 152064, 0x19fce380 +0, 54, 54, 1, 152064, 0x876be6c9 +0, 55, 55, 1, 152064, 0x39eb8ff9 +0, 56, 56, 1, 152064, 0x289c9543 +0, 57, 57, 1, 152064, 0x24dd2356 +0, 58, 58, 1, 152064, 0x1dc17d3c +0, 59, 59, 1, 152064, 0xd17c00ac +0, 60, 60, 1, 152064, 0xc2ad54de +0, 61, 61, 1, 152064, 0xbe11ee2f +0, 62, 62, 1, 152064, 0x3db9dc89 +0, 63, 63, 1, 152064, 0xac0d7bc2 +0, 64, 64, 1, 152064, 0x8dab2dde +0, 65, 65, 1, 152064, 0x566ad225 +0, 66, 66, 1, 152064, 0x587c7853 +0, 67, 67, 1, 152064, 0x601c9c80 +0, 68, 68, 1, 152064, 0x2afaf751 +0, 69, 69, 1, 152064, 0x1c9f7e3a +0, 70, 70, 1, 152064, 0x899475bf +0, 71, 71, 1, 152064, 0x0d65c7d9 +0, 72, 72, 1, 152064, 0xafd63d12 +0, 73, 73, 1, 152064, 0x162e62b9 +0, 74, 74, 1, 152064, 0x5c9554be +0, 75, 75, 1, 152064, 0x35fbdaa2 +0, 76, 76, 1, 152064, 0x6438cbd8 +0, 77, 77, 1, 152064, 0xde0772c9 +0, 78, 78, 1, 152064, 0x79f82854 +0, 79, 79, 1, 152064, 0x86957840 +0, 80, 80, 1, 152064, 0xd9468cbf +0, 81, 81, 1, 152064, 0x23e74609 +0, 82, 82, 1, 152064, 0x3919a146 +0, 83, 83, 1, 152064, 0xd641078b +0, 84, 84, 1, 152064, 0x24397220 +0, 85, 85, 1, 152064, 0xe7fc3a7c +0, 86, 86, 1, 152064, 0x3997154a +0, 87, 87, 1, 152064, 0x2af3952c +0, 88, 88, 1, 152064, 0x274ac07a +0, 89, 89, 1, 152064, 0x288f7b09 +0, 90, 90, 1, 152064, 0xe6f9b022 +0, 91, 91, 1, 152064, 0xf09e2fbb +0, 92, 92, 1, 152064, 0x7244e477 +0, 93, 93, 1, 152064, 0x0dfc72eb +0, 94, 94, 1, 152064, 0x0322b21f +0, 95, 95, 1, 152064, 0x18b08205 +0, 96, 96, 1, 152064, 0x6606153e +0, 97, 97, 1, 152064, 0x85186272 +0, 98, 98, 1, 152064, 0x3369f064 +0, 99, 99, 1, 152064, 0xbe0d5a44 +0, 100, 100, 1, 152064, 0x320258bb +0, 101, 101, 1, 152064, 0x4d6fb091 +0, 102, 102, 1, 152064, 0xc9bbf5e7 +0, 103, 103, 1, 152064, 0x0aa1b69b +0, 104, 104, 1, 152064, 0x85b9ac11 +0, 105, 105, 1, 152064, 0xb25ff818 +0, 106, 106, 1, 152064, 0xa155dc25 +0, 107, 107, 1, 152064, 0xa8e03bfd +0, 108, 108, 1, 152064, 0x0a862956 +0, 109, 109, 1, 152064, 0x11b49264 +0, 110, 110, 1, 152064, 0xa94e664e +0, 111, 111, 1, 152064, 0x330e0fa2 +0, 112, 112, 1, 152064, 0xaf3d9518 +0, 113, 113, 1, 152064, 0x0836f2e8 +0, 114, 114, 1, 152064, 0xbf6dc578 +0, 115, 115, 1, 152064, 0x7b524d20 +0, 116, 116, 1, 152064, 0x9ef7677f +0, 117, 117, 1, 152064, 0xeacf3f34 +0, 118, 118, 1, 152064, 0xfb4e3dbe +0, 119, 119, 1, 152064, 0xb46e25cb +0, 120, 120, 1, 152064, 0x363c1603 +0, 121, 121, 1, 152064, 0x263fc542 +0, 122, 122, 1, 152064, 0xf106e548 +0, 123, 123, 1, 152064, 0xde43c56a +0, 124, 124, 1, 152064, 0xc2c4770a +0, 125, 125, 1, 152064, 0x122fce19 +0, 126, 126, 1, 152064, 0x3ba01434 +0, 127, 127, 1, 152064, 0x0e8ce5ee +0, 128, 128, 1, 152064, 0x6ceb82e1 +0, 129, 129, 1, 152064, 0xa23ee21c +0, 130, 130, 1, 152064, 0xc6d960f9 +0, 131, 131, 1, 152064, 0x0de15258 +0, 132, 132, 1, 152064, 0x187b0333 +0, 133, 133, 1, 152064, 0x92e6582f +0, 134, 134, 1, 152064, 0xb9586ce0 +0, 135, 135, 1, 152064, 0xefd803b5 +0, 136, 136, 1, 152064, 0x24eafb29 +0, 137, 137, 1, 152064, 0x20c73b14 +0, 138, 138, 1, 152064, 0xbd7ceaaa +0, 139, 139, 1, 152064, 0x775216c8 +0, 140, 140, 1, 152064, 0xa08971c7 +0, 141, 141, 1, 152064, 0xef0ee865 +0, 142, 142, 1, 152064, 0x9ac61c2f +0, 143, 143, 1, 152064, 0x52ae8ea9 +0, 144, 144, 1, 152064, 0x06571c14 +0, 145, 145, 1, 152064, 0x6e78ad33 +0, 146, 146, 1, 152064, 0xad01c627 +0, 147, 147, 1, 152064, 0xbfe074d3 +0, 148, 148, 1, 152064, 0x9357a183 +0, 149, 149, 1, 152064, 0x8de7767f +0, 150, 150, 1, 152064, 0xa5e6e76e +0, 151, 151, 1, 152064, 0xa6f646fe +0, 152, 152, 1, 152064, 0x132e99f8 +0, 153, 153, 1, 152064, 0xb79f27de +0, 154, 154, 1, 152064, 0x36d3cdcf +0, 155, 155, 1, 152064, 0xdc938336 +0, 156, 156, 1, 152064, 0xacaa3a7f +0, 157, 157, 1, 152064, 0xc61a37fd +0, 158, 158, 1, 152064, 0x4fe1ddf0 +0, 159, 159, 1, 152064, 0xc0f7d660 +0, 160, 160, 1, 152064, 0xd72458ea +0, 161, 161, 1, 152064, 0x6978d123 +0, 162, 162, 1, 152064, 0x64e60ccf +0, 163, 163, 1, 152064, 0xaa07004c +0, 164, 164, 1, 152064, 0x07cd1064 +0, 165, 165, 1, 152064, 0xa82320e5 +0, 166, 166, 1, 152064, 0xaedd8d30 +0, 167, 167, 1, 152064, 0x79b082ea +0, 168, 168, 1, 152064, 0x9ed800ab +0, 169, 169, 1, 152064, 0xde592bb4 +0, 170, 170, 1, 152064, 0xd966df88 +0, 171, 171, 1, 152064, 0xf921988a +0, 172, 172, 1, 152064, 0x557ad9ae +0, 173, 173, 1, 152064, 0xc3f31a9a +0, 174, 174, 1, 152064, 0x65248561 +0, 175, 175, 1, 152064, 0x63df4aa6 +0, 176, 176, 1, 152064, 0x618da0a9 +0, 177, 177, 1, 152064, 0xe6f1c435 +0, 178, 178, 1, 152064, 0x9f90c38f +0, 179, 179, 1, 152064, 0xd2853e14 +0, 180, 180, 1, 152064, 0x6e0268a9 +0, 181, 181, 1, 152064, 0x393712d1 +0, 182, 182, 1, 152064, 0x470da25f +0, 183, 183, 1, 152064, 0xaf55cb3d +0, 184, 184, 1, 152064, 0x6935b8b9 +0, 185, 185, 1, 152064, 0x5409a15f +0, 186, 186, 1, 152064, 0x09073fee +0, 187, 187, 1, 152064, 0xfb274e82 +0, 188, 188, 1, 152064, 0x1a770581 +0, 189, 189, 1, 152064, 0x17277d0d +0, 190, 190, 1, 152064, 0xd4dcd982 +0, 191, 191, 1, 152064, 0x6b04eaf3 +0, 192, 192, 1, 152064, 0x8a3d822e +0, 193, 193, 1, 152064, 0x1b971ec9 +0, 194, 194, 1, 152064, 0x14e0c0f6 +0, 195, 195, 1, 152064, 0x00667450 +0, 196, 196, 1, 152064, 0xd2385902 +0, 197, 197, 1, 152064, 0x905da6ab +0, 198, 198, 1, 152064, 0xa3ffb18b +0, 199, 199, 1, 152064, 0x10d48b19 +0, 200, 200, 1, 152064, 0xb2c7a3bd +0, 201, 201, 1, 152064, 0x45593e96 +0, 202, 202, 1, 152064, 0x47a0b60c +0, 203, 203, 1, 152064, 0x68c6d1b9 +0, 204, 204, 1, 152064, 0xbc881fcc +0, 205, 205, 1, 152064, 0x422cc6f2 +0, 206, 206, 1, 152064, 0x9b686410 +0, 207, 207, 1, 152064, 0x35dc5e86 +0, 208, 208, 1, 152064, 0x247bedaa +0, 209, 209, 1, 152064, 0x22b76fd1 +0, 210, 210, 1, 152064, 0x67cc7a75 +0, 211, 211, 1, 152064, 0xa197521e +0, 212, 212, 1, 152064, 0x428c8662 +0, 213, 213, 1, 152064, 0x33dc2c73 +0, 214, 214, 1, 152064, 0x5b538903 +0, 215, 215, 1, 152064, 0x3c4176b6 +0, 216, 216, 1, 152064, 0x774364ba +0, 217, 217, 1, 152064, 0xf237d03e +0, 218, 218, 1, 152064, 0xac8746fb +0, 219, 219, 1, 152064, 0x6b306a84 +0, 220, 220, 1, 152064, 0xa2ace513 +0, 221, 221, 1, 152064, 0x709c9be7 +0, 222, 222, 1, 152064, 0x2403f373 +0, 223, 223, 1, 152064, 0x147bf717 +0, 224, 224, 1, 152064, 0xe58964c8 +0, 225, 225, 1, 152064, 0xa0da36fc +0, 226, 226, 1, 152064, 0x1ac1355c +0, 227, 227, 1, 152064, 0x8a31c9f2 +0, 228, 228, 1, 152064, 0x42ba205c +0, 229, 229, 1, 152064, 0xa11b3575 +0, 230, 230, 1, 152064, 0xcb35207c +0, 231, 231, 1, 152064, 0x528f6189 +0, 232, 232, 1, 152064, 0x34f05bd7 +0, 233, 233, 1, 152064, 0x72317356 +0, 234, 234, 1, 152064, 0xaabd5028 +0, 235, 235, 1, 152064, 0x13dbeb7b +0, 236, 236, 1, 152064, 0x62f1e8a8 +0, 237, 237, 1, 152064, 0x1723bfcd +0, 238, 238, 1, 152064, 0x5c083c00 +0, 239, 239, 1, 152064, 0x52137894 +0, 240, 240, 1, 152064, 0xef1e082c +0, 241, 241, 1, 152064, 0x664b3d53 +0, 242, 242, 1, 152064, 0x2eb9b296 +0, 243, 243, 1, 152064, 0xd0ca511e +0, 244, 244, 1, 152064, 0x012d4724 +0, 245, 245, 1, 152064, 0xa847f5af +0, 246, 246, 1, 152064, 0x483a2fde +0, 247, 247, 1, 152064, 0xd1ab0257 +0, 248, 248, 1, 152064, 0x414692c7 +0, 249, 249, 1, 152064, 0x0b79df88 +0, 250, 250, 1, 152064, 0xdaa2c4a3 +0, 251, 251, 1, 152064, 0xd1b44500 +0, 252, 252, 1, 152064, 0xfd3d2cf3 +0, 253, 253, 1, 152064, 0xfdc0f748 +0, 254, 254, 1, 152064, 0xce762a2a +0, 255, 255, 1, 152064, 0x08b63572 +0, 256, 256, 1, 152064, 0x5a46a38d +0, 257, 257, 1, 152064, 0x03cee9c0 +0, 258, 258, 1, 152064, 0x9ee45473 +0, 259, 259, 1, 152064, 0x5a432386 +0, 260, 260, 1, 152064, 0x54c83d87 +0, 261, 261, 1, 152064, 0xc9caa1de +0, 262, 262, 1, 152064, 0xa28367f1 +0, 263, 263, 1, 152064, 0x2607cdf1 +0, 264, 264, 1, 152064, 0x06baa8de +0, 265, 265, 1, 152064, 0xf5346e32 +0, 266, 266, 1, 152064, 0x6d3e732b +0, 267, 267, 1, 152064, 0x798c584b +0, 268, 268, 1, 152064, 0x4076c948 +0, 269, 269, 1, 152064, 0x868cf63a +0, 270, 270, 1, 152064, 0x23107ac5 +0, 271, 271, 1, 152064, 0x306f3fe2 +0, 272, 272, 1, 152064, 0xbd1d71d6 +0, 273, 273, 1, 152064, 0x1429545f +0, 274, 274, 1, 152064, 0xaded29aa +0, 275, 275, 1, 152064, 0x9b455a94 +0, 276, 276, 1, 152064, 0xb3774ce7 +0, 277, 277, 1, 152064, 0x92580986 +0, 278, 278, 1, 152064, 0x0eae2f95 +0, 279, 279, 1, 152064, 0x599208b2 +0, 280, 280, 1, 152064, 0x4804c04c +0, 281, 281, 1, 152064, 0x5f730e8f +0, 282, 282, 1, 152064, 0x3e501d1e +0, 283, 283, 1, 152064, 0x32100740 +0, 284, 284, 1, 152064, 0x62226ff8 +0, 285, 285, 1, 152064, 0x7683b622 +0, 286, 286, 1, 152064, 0xc3e0aec1 +0, 287, 287, 1, 152064, 0xfac12608 +0, 288, 288, 1, 152064, 0xb21a5781 +0, 289, 289, 1, 152064, 0x8f1e4964 +0, 290, 290, 1, 152064, 0x0f62dd6e +0, 291, 291, 1, 152064, 0xac062ac4 +0, 292, 292, 1, 152064, 0x1b320f7a +0, 293, 293, 1, 152064, 0x346e7211 +0, 294, 294, 1, 152064, 0xe47592f3 +0, 295, 295, 1, 152064, 0xa3a7919c +0, 296, 296, 1, 152064, 0xa3580fa6 +0, 297, 297, 1, 152064, 0xc73430c1 +0, 298, 298, 1, 152064, 0x994a2c18 +0, 299, 299, 1, 152064, 0x0b5d8d45 +0, 300, 300, 1, 152064, 0x9eed5109 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-mr3_tandberg_b ffmpeg-4.4/tests/ref/fate/h264-conformance-mr3_tandberg_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-mr3_tandberg_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-mr3_tandberg_b 2021-04-08 21:28:40.000000000 +0000 @@ -12,294 +12,294 @@ 0, 6, 6, 1, 38016, 0x7cc17319 0, 7, 7, 1, 38016, 0x0f7e8cab 0, 8, 8, 1, 38016, 0x1876abee -0, 9, 9, 1, 38016, 0xda748c2f -0, 10, 10, 1, 38016, 0x7b4dbff0 -0, 11, 11, 1, 38016, 0xd4a1b24a -0, 12, 12, 1, 38016, 0x714cb4cc -0, 13, 13, 1, 38016, 0x2c6d80f0 -0, 14, 14, 1, 38016, 0x92266151 -0, 15, 15, 1, 38016, 0x6b766a23 -0, 16, 16, 1, 38016, 0xb24f7efe -0, 17, 17, 1, 38016, 0x8410838e -0, 18, 18, 1, 38016, 0x67fe872a -0, 19, 19, 1, 38016, 0x55b49d36 -0, 20, 20, 1, 38016, 0x7a1c9c41 -0, 21, 21, 1, 38016, 0xb4818e0e -0, 22, 22, 1, 38016, 0x25f6683c -0, 23, 23, 1, 38016, 0xe4d141a4 -0, 24, 24, 1, 38016, 0x808216ad -0, 25, 25, 1, 38016, 0x2acf0baf -0, 26, 26, 1, 38016, 0xf3de13c4 -0, 27, 27, 1, 38016, 0x5f412187 -0, 28, 28, 1, 38016, 0xb31a340a -0, 29, 29, 1, 38016, 0x019d42d1 -0, 30, 30, 1, 38016, 0xeeb94b9b -0, 31, 31, 1, 38016, 0xef55472e -0, 32, 32, 1, 38016, 0xdb5e3697 -0, 33, 33, 1, 38016, 0x8565303e -0, 34, 34, 1, 38016, 0x5f9c2c1b -0, 35, 35, 1, 38016, 0xeb3d27f4 -0, 36, 36, 1, 38016, 0x9a43282d -0, 37, 37, 1, 38016, 0xe04720c6 -0, 38, 38, 1, 38016, 0x19cc0eba -0, 39, 39, 1, 38016, 0x218efeb6 -0, 40, 40, 1, 38016, 0x7733f491 -0, 41, 41, 1, 38016, 0x7f3bede9 -0, 42, 42, 1, 38016, 0x49c5ec0d -0, 43, 43, 1, 38016, 0x803cf19e -0, 44, 44, 1, 38016, 0x31de0d3f -0, 45, 45, 1, 38016, 0xa7e30426 -0, 46, 46, 1, 38016, 0xba37f068 -0, 47, 47, 1, 38016, 0x2842bdf8 -0, 48, 48, 1, 38016, 0x76df97dc -0, 49, 49, 1, 38016, 0xf3246d26 -0, 50, 50, 1, 38016, 0x0a384d72 -0, 51, 51, 1, 38016, 0x40964f41 -0, 52, 52, 1, 38016, 0x46364324 -0, 53, 53, 1, 38016, 0x7cbf3db4 -0, 54, 54, 1, 38016, 0x7a223bec -0, 55, 55, 1, 38016, 0x458651c1 -0, 56, 56, 1, 38016, 0xb82d7e3c -0, 57, 57, 1, 38016, 0x0f50a55d -0, 58, 58, 1, 38016, 0xc306cae4 -0, 59, 59, 1, 38016, 0x9d6ddfcb -0, 60, 60, 1, 38016, 0xb602e8e9 -0, 61, 61, 1, 38016, 0xbf0ae386 -0, 62, 62, 1, 38016, 0x0a8bd46e -0, 63, 63, 1, 38016, 0xd437c5c1 -0, 64, 64, 1, 38016, 0xd61d9959 -0, 65, 65, 1, 38016, 0x70639b56 -0, 66, 66, 1, 38016, 0x36fd407b -0, 67, 67, 1, 38016, 0x58ce3ddd -0, 68, 68, 1, 38016, 0x86cc1d8c -0, 69, 69, 1, 38016, 0xee422dc2 -0, 70, 70, 1, 38016, 0xab475639 -0, 71, 71, 1, 38016, 0xc1327ad8 -0, 72, 72, 1, 38016, 0x63d196d4 -0, 73, 73, 1, 38016, 0x1aba8ebd -0, 74, 74, 1, 38016, 0x74a269ac -0, 75, 75, 1, 38016, 0x267f3563 -0, 76, 76, 1, 38016, 0xa18ff180 -0, 77, 77, 1, 38016, 0x70c9c9fd -0, 78, 78, 1, 38016, 0xa6c59f9c -0, 79, 79, 1, 38016, 0xd7cd8927 -0, 80, 80, 1, 38016, 0xd30b7345 -0, 81, 81, 1, 38016, 0x679a4dda -0, 82, 82, 1, 38016, 0xeb0562de -0, 83, 83, 1, 38016, 0xdd7d6cdb -0, 84, 84, 1, 38016, 0xd6e26b73 -0, 85, 85, 1, 38016, 0xa65a860f -0, 86, 86, 1, 38016, 0xae95c71e -0, 87, 87, 1, 38016, 0x1a89ca86 -0, 88, 88, 1, 38016, 0xa33ecee6 -0, 89, 89, 1, 38016, 0x821da6cb -0, 90, 90, 1, 38016, 0xf0e1612f -0, 91, 91, 1, 38016, 0x67b8516b -0, 92, 92, 1, 38016, 0x62f965bc -0, 93, 93, 1, 38016, 0xd1917aa6 -0, 94, 94, 1, 38016, 0xe72db54d -0, 95, 95, 1, 38016, 0x9b64e721 -0, 96, 96, 1, 38016, 0xa819efda -0, 97, 97, 1, 38016, 0xeacfdacb -0, 98, 98, 1, 38016, 0x52f235e1 -0, 99, 99, 1, 38016, 0x2b512cb8 -0, 100, 100, 1, 38016, 0xaac73fb3 -0, 101, 101, 1, 38016, 0x7d2d504f -0, 102, 102, 1, 38016, 0x396d503a -0, 103, 103, 1, 38016, 0x97905235 -0, 104, 104, 1, 38016, 0xf0056693 -0, 105, 105, 1, 38016, 0x728a6a9e -0, 106, 106, 1, 38016, 0x0eed7824 -0, 107, 107, 1, 38016, 0x59506237 -0, 108, 108, 1, 38016, 0xd4304c93 -0, 109, 109, 1, 38016, 0x7e663ee8 -0, 110, 110, 1, 38016, 0x0ebc2d11 -0, 111, 111, 1, 38016, 0x52db2112 -0, 112, 112, 1, 38016, 0x74aa1815 -0, 113, 113, 1, 38016, 0x57a60dc6 -0, 114, 114, 1, 38016, 0x86e9fa32 -0, 115, 115, 1, 38016, 0x67e8ff09 -0, 116, 116, 1, 38016, 0x26e8f7ea -0, 117, 117, 1, 38016, 0x183dff56 -0, 118, 118, 1, 38016, 0xa470af8d -0, 119, 119, 1, 38016, 0xe017d594 -0, 120, 120, 1, 38016, 0xb899d48b -0, 121, 121, 1, 38016, 0x0d3bc5f7 -0, 122, 122, 1, 38016, 0xd68bbb0d -0, 123, 123, 1, 38016, 0x8bf5b4cb -0, 124, 124, 1, 38016, 0x6bfcaa47 -0, 125, 125, 1, 38016, 0x29a9b01b -0, 126, 126, 1, 38016, 0xcdedbdb7 -0, 127, 127, 1, 38016, 0xdb5ad9c3 -0, 128, 128, 1, 38016, 0x468aeef6 -0, 129, 129, 1, 38016, 0xdc2b143e -0, 130, 130, 1, 38016, 0x6776277c -0, 131, 131, 1, 38016, 0xb78d5294 -0, 132, 132, 1, 38016, 0x1dfb63ab -0, 133, 133, 1, 38016, 0xbd1f99bc -0, 134, 134, 1, 38016, 0xde16b89a -0, 135, 135, 1, 38016, 0xbf46edca -0, 136, 136, 1, 38016, 0x6306e8c4 -0, 137, 137, 1, 38016, 0x7b09d224 -0, 138, 138, 1, 38016, 0xfea1aff6 -0, 139, 139, 1, 38016, 0x183686b0 -0, 140, 140, 1, 38016, 0x665a61ff -0, 141, 141, 1, 38016, 0xc8af42d1 -0, 142, 142, 1, 38016, 0xe2326bc1 -0, 143, 143, 1, 38016, 0x56dbde82 -0, 144, 144, 1, 38016, 0xa0254f97 -0, 145, 145, 1, 38016, 0x3b74a0b4 -0, 146, 146, 1, 38016, 0x9aee9b7f -0, 147, 147, 1, 38016, 0xd94b6133 -0, 148, 148, 1, 38016, 0x5819f795 -0, 149, 149, 1, 38016, 0xc45a8c02 -0, 150, 150, 1, 38016, 0x2f9204a0 -0, 151, 151, 1, 38016, 0xbe09e051 -0, 152, 152, 1, 38016, 0xb542badd -0, 153, 153, 1, 38016, 0x23bd9e00 -0, 154, 154, 1, 38016, 0x4f338d3d -0, 155, 155, 1, 38016, 0x8c91e8f3 -0, 156, 156, 1, 38016, 0xa7347d57 -0, 157, 157, 1, 38016, 0x6d91de4d -0, 158, 158, 1, 38016, 0x3443d936 -0, 159, 159, 1, 38016, 0x9d25b4e2 -0, 160, 160, 1, 38016, 0xd93cd4b3 -0, 161, 161, 1, 38016, 0xa1c9e9a0 -0, 162, 162, 1, 38016, 0x1482f220 -0, 163, 163, 1, 38016, 0x1295f270 -0, 164, 164, 1, 38016, 0x399ae9da -0, 165, 165, 1, 38016, 0x85dcdf28 -0, 166, 166, 1, 38016, 0x4207b9e5 -0, 167, 167, 1, 38016, 0xad1c9d75 -0, 168, 168, 1, 38016, 0x4a266c14 -0, 169, 169, 1, 38016, 0x3afc4508 -0, 170, 170, 1, 38016, 0x2b1b2385 -0, 171, 171, 1, 38016, 0x738f005f -0, 172, 172, 1, 38016, 0xfec3d833 -0, 173, 173, 1, 38016, 0x3f7f6ae9 -0, 174, 174, 1, 38016, 0xd8551823 -0, 175, 175, 1, 38016, 0x6df03570 -0, 176, 176, 1, 38016, 0x767c3054 -0, 177, 177, 1, 38016, 0x89bd342c -0, 178, 178, 1, 38016, 0x77ba806c -0, 179, 179, 1, 38016, 0x1c98005c -0, 180, 180, 1, 38016, 0xa13ce2a3 -0, 181, 181, 1, 38016, 0x1be59915 -0, 182, 182, 1, 38016, 0x279c6027 -0, 183, 183, 1, 38016, 0x96ac11a2 -0, 184, 184, 1, 38016, 0x3ae95131 -0, 185, 185, 1, 38016, 0xae19f7fe -0, 186, 186, 1, 38016, 0xcde4efe6 -0, 187, 187, 1, 38016, 0x5ecc3f7a -0, 188, 188, 1, 38016, 0x79645152 -0, 189, 189, 1, 38016, 0x1ee2e89f -0, 190, 190, 1, 38016, 0x91d34bb4 -0, 191, 191, 1, 38016, 0xf019d464 -0, 192, 192, 1, 38016, 0x8eb07205 -0, 193, 193, 1, 38016, 0x5399bb5b -0, 194, 194, 1, 38016, 0x61f0c77a -0, 195, 195, 1, 38016, 0xb2bd8726 -0, 196, 196, 1, 38016, 0x47b89243 -0, 197, 197, 1, 38016, 0xebfe4d76 -0, 198, 198, 1, 38016, 0xe8f87d91 -0, 199, 199, 1, 38016, 0x5e9fb239 -0, 200, 200, 1, 38016, 0x357ca1f8 -0, 201, 201, 1, 38016, 0x757d2e02 -0, 202, 202, 1, 38016, 0x40672e7c -0, 203, 203, 1, 38016, 0xd966abca -0, 204, 204, 1, 38016, 0xe98d0d47 -0, 205, 205, 1, 38016, 0x341babf5 -0, 206, 206, 1, 38016, 0xd12d5a0c -0, 207, 207, 1, 38016, 0xea2f99ab -0, 208, 208, 1, 38016, 0x14bce88e -0, 209, 209, 1, 38016, 0xe4bda9e8 -0, 210, 210, 1, 38016, 0x2c57ec89 -0, 211, 211, 1, 38016, 0x28bbb83e -0, 212, 212, 1, 38016, 0xf8444b54 -0, 213, 213, 1, 38016, 0x3aba03cd -0, 214, 214, 1, 38016, 0x373daa20 -0, 215, 215, 1, 38016, 0x69586597 -0, 216, 216, 1, 38016, 0xc0c70d53 -0, 217, 217, 1, 38016, 0x76a5df5a -0, 218, 218, 1, 38016, 0x1afde8f0 -0, 219, 219, 1, 38016, 0x9638285a -0, 220, 220, 1, 38016, 0x9f0686c0 -0, 221, 221, 1, 38016, 0xc65b2238 -0, 222, 222, 1, 38016, 0x0d61b610 -0, 223, 223, 1, 38016, 0x78e14e1f -0, 224, 224, 1, 38016, 0xcf80ac4a -0, 225, 225, 1, 38016, 0xe094083d -0, 226, 226, 1, 38016, 0xee5e612e -0, 227, 227, 1, 38016, 0x51cdad9d -0, 228, 228, 1, 38016, 0xae41100e -0, 229, 229, 1, 38016, 0x77558f58 -0, 230, 230, 1, 38016, 0xb9503b95 -0, 231, 231, 1, 38016, 0xb71dffeb -0, 232, 232, 1, 38016, 0x1872e3e6 -0, 233, 233, 1, 38016, 0x29c3d252 -0, 234, 234, 1, 38016, 0x1c77c6ec -0, 235, 235, 1, 38016, 0x26feb194 -0, 236, 236, 1, 38016, 0x3307c3c4 -0, 237, 237, 1, 38016, 0x8e5a8080 -0, 238, 238, 1, 38016, 0x933472f7 -0, 239, 239, 1, 38016, 0xd4768d84 -0, 240, 240, 1, 38016, 0x3324485f -0, 241, 241, 1, 38016, 0xd50af078 -0, 242, 242, 1, 38016, 0x53820752 -0, 243, 243, 1, 38016, 0xbe7f1c47 -0, 244, 244, 1, 38016, 0xe43d3a34 -0, 245, 245, 1, 38016, 0x57194b82 -0, 246, 246, 1, 38016, 0x68a052ed -0, 247, 247, 1, 38016, 0x5c898052 -0, 248, 248, 1, 38016, 0x7104a6ad -0, 249, 249, 1, 38016, 0x1676b5e8 -0, 250, 250, 1, 38016, 0xe1cfd375 -0, 251, 251, 1, 38016, 0x16fede04 -0, 252, 252, 1, 38016, 0xca49dd4a -0, 253, 253, 1, 38016, 0x7b98d9d1 -0, 254, 254, 1, 38016, 0x4020d210 -0, 255, 255, 1, 38016, 0x62c5d1e4 -0, 256, 256, 1, 38016, 0x756abdb4 -0, 257, 257, 1, 38016, 0x558fb00f -0, 258, 258, 1, 38016, 0x4ab0b1f1 -0, 259, 259, 1, 38016, 0x7c9fb0c2 -0, 260, 260, 1, 38016, 0xcecfbdd0 -0, 261, 261, 1, 38016, 0x70e6d174 -0, 262, 262, 1, 38016, 0x83d7ddde -0, 263, 263, 1, 38016, 0xbbcde2d9 -0, 264, 264, 1, 38016, 0xc89eeaef -0, 265, 265, 1, 38016, 0x8565e15c -0, 266, 266, 1, 38016, 0x28e0db24 -0, 267, 267, 1, 38016, 0x1d9dd334 -0, 268, 268, 1, 38016, 0xce02c452 -0, 269, 269, 1, 38016, 0xe29dbd0c -0, 270, 270, 1, 38016, 0x4aa3b638 -0, 271, 271, 1, 38016, 0x5533c135 -0, 272, 272, 1, 38016, 0x6c57b65f -0, 273, 273, 1, 38016, 0x23d3b851 -0, 274, 274, 1, 38016, 0xd8cbb960 -0, 275, 275, 1, 38016, 0x02edb916 -0, 276, 276, 1, 38016, 0xa622bd42 -0, 277, 277, 1, 38016, 0x4ba5be1c -0, 278, 278, 1, 38016, 0xe69bb625 -0, 279, 279, 1, 38016, 0xbca5b292 -0, 280, 280, 1, 38016, 0xde38b1c8 -0, 281, 281, 1, 38016, 0xe9e3b617 -0, 282, 282, 1, 38016, 0x216cc574 -0, 283, 283, 1, 38016, 0x3780c5ad -0, 284, 284, 1, 38016, 0x5531e3f9 -0, 285, 285, 1, 38016, 0xe2c5f5d4 -0, 286, 286, 1, 38016, 0x24cefc6e -0, 287, 287, 1, 38016, 0xa3ce003d -0, 288, 288, 1, 38016, 0x42d01c9e -0, 289, 289, 1, 38016, 0xbfc13689 -0, 290, 290, 1, 38016, 0x122647a9 -0, 291, 291, 1, 38016, 0xe45254da -0, 292, 292, 1, 38016, 0xad955b0c -0, 293, 293, 1, 38016, 0x4b086abb -0, 294, 294, 1, 38016, 0xd4857b8c -0, 295, 295, 1, 38016, 0xa71594ce -0, 296, 296, 1, 38016, 0x04e4a73d -0, 297, 297, 1, 38016, 0x295abf63 -0, 298, 298, 1, 38016, 0xbe4ed5dd -0, 299, 299, 1, 38016, 0x087bcf64 +0, 10, 10, 1, 38016, 0xda748c2f +0, 11, 11, 1, 38016, 0x7b4dbff0 +0, 12, 12, 1, 38016, 0xd4a1b24a +0, 13, 13, 1, 38016, 0x714cb4cc +0, 14, 14, 1, 38016, 0x2c6d80f0 +0, 15, 15, 1, 38016, 0x92266151 +0, 16, 16, 1, 38016, 0x6b766a23 +0, 17, 17, 1, 38016, 0xb24f7efe +0, 18, 18, 1, 38016, 0x8410838e +0, 19, 19, 1, 38016, 0x67fe872a +0, 20, 20, 1, 38016, 0x55b49d36 +0, 21, 21, 1, 38016, 0x7a1c9c41 +0, 22, 22, 1, 38016, 0xb4818e0e +0, 23, 23, 1, 38016, 0x25f6683c +0, 24, 24, 1, 38016, 0xe4d141a4 +0, 25, 25, 1, 38016, 0x808216ad +0, 26, 26, 1, 38016, 0x2acf0baf +0, 27, 27, 1, 38016, 0xf3de13c4 +0, 28, 28, 1, 38016, 0x5f412187 +0, 29, 29, 1, 38016, 0xb31a340a +0, 30, 30, 1, 38016, 0x019d42d1 +0, 31, 31, 1, 38016, 0xeeb94b9b +0, 32, 32, 1, 38016, 0xef55472e +0, 33, 33, 1, 38016, 0xdb5e3697 +0, 34, 34, 1, 38016, 0x8565303e +0, 35, 35, 1, 38016, 0x5f9c2c1b +0, 36, 36, 1, 38016, 0xeb3d27f4 +0, 37, 37, 1, 38016, 0x9a43282d +0, 38, 38, 1, 38016, 0xe04720c6 +0, 39, 39, 1, 38016, 0x19cc0eba +0, 40, 40, 1, 38016, 0x218efeb6 +0, 41, 41, 1, 38016, 0x7733f491 +0, 42, 42, 1, 38016, 0x7f3bede9 +0, 43, 43, 1, 38016, 0x49c5ec0d +0, 44, 44, 1, 38016, 0x803cf19e +0, 45, 45, 1, 38016, 0x31de0d3f +0, 46, 46, 1, 38016, 0xa7e30426 +0, 47, 47, 1, 38016, 0xba37f068 +0, 48, 48, 1, 38016, 0x2842bdf8 +0, 49, 49, 1, 38016, 0x76df97dc +0, 50, 50, 1, 38016, 0xf3246d26 +0, 51, 51, 1, 38016, 0x0a384d72 +0, 52, 52, 1, 38016, 0x40964f41 +0, 53, 53, 1, 38016, 0x46364324 +0, 54, 54, 1, 38016, 0x7cbf3db4 +0, 55, 55, 1, 38016, 0x7a223bec +0, 56, 56, 1, 38016, 0x458651c1 +0, 57, 57, 1, 38016, 0xb82d7e3c +0, 58, 58, 1, 38016, 0x0f50a55d +0, 59, 59, 1, 38016, 0xc306cae4 +0, 60, 60, 1, 38016, 0x9d6ddfcb +0, 61, 61, 1, 38016, 0xb602e8e9 +0, 62, 62, 1, 38016, 0xbf0ae386 +0, 63, 63, 1, 38016, 0x0a8bd46e +0, 64, 64, 1, 38016, 0xd437c5c1 +0, 65, 65, 1, 38016, 0xd61d9959 +0, 66, 66, 1, 38016, 0x70639b56 +0, 67, 67, 1, 38016, 0x36fd407b +0, 68, 68, 1, 38016, 0x58ce3ddd +0, 69, 69, 1, 38016, 0x86cc1d8c +0, 70, 70, 1, 38016, 0xee422dc2 +0, 71, 71, 1, 38016, 0xab475639 +0, 72, 72, 1, 38016, 0xc1327ad8 +0, 73, 73, 1, 38016, 0x63d196d4 +0, 74, 74, 1, 38016, 0x1aba8ebd +0, 75, 75, 1, 38016, 0x74a269ac +0, 76, 76, 1, 38016, 0x267f3563 +0, 77, 77, 1, 38016, 0xa18ff180 +0, 78, 78, 1, 38016, 0x70c9c9fd +0, 79, 79, 1, 38016, 0xa6c59f9c +0, 80, 80, 1, 38016, 0xd7cd8927 +0, 81, 81, 1, 38016, 0xd30b7345 +0, 82, 82, 1, 38016, 0x679a4dda +0, 83, 83, 1, 38016, 0xeb0562de +0, 84, 84, 1, 38016, 0xdd7d6cdb +0, 85, 85, 1, 38016, 0xd6e26b73 +0, 86, 86, 1, 38016, 0xa65a860f +0, 87, 87, 1, 38016, 0xae95c71e +0, 88, 88, 1, 38016, 0x1a89ca86 +0, 89, 89, 1, 38016, 0xa33ecee6 +0, 90, 90, 1, 38016, 0x821da6cb +0, 91, 91, 1, 38016, 0xf0e1612f +0, 92, 92, 1, 38016, 0x67b8516b +0, 93, 93, 1, 38016, 0x62f965bc +0, 94, 94, 1, 38016, 0xd1917aa6 +0, 95, 95, 1, 38016, 0xe72db54d +0, 96, 96, 1, 38016, 0x9b64e721 +0, 97, 97, 1, 38016, 0xa819efda +0, 98, 98, 1, 38016, 0xeacfdacb +0, 99, 99, 1, 38016, 0x52f235e1 +0, 100, 100, 1, 38016, 0x2b512cb8 +0, 101, 101, 1, 38016, 0xaac73fb3 +0, 102, 102, 1, 38016, 0x7d2d504f +0, 103, 103, 1, 38016, 0x396d503a +0, 104, 104, 1, 38016, 0x97905235 +0, 105, 105, 1, 38016, 0xf0056693 +0, 106, 106, 1, 38016, 0x728a6a9e +0, 107, 107, 1, 38016, 0x0eed7824 +0, 108, 108, 1, 38016, 0x59506237 +0, 109, 109, 1, 38016, 0xd4304c93 +0, 110, 110, 1, 38016, 0x7e663ee8 +0, 111, 111, 1, 38016, 0x0ebc2d11 +0, 112, 112, 1, 38016, 0x52db2112 +0, 113, 113, 1, 38016, 0x74aa1815 +0, 114, 114, 1, 38016, 0x57a60dc6 +0, 115, 115, 1, 38016, 0x86e9fa32 +0, 116, 116, 1, 38016, 0x67e8ff09 +0, 117, 117, 1, 38016, 0x26e8f7ea +0, 118, 118, 1, 38016, 0x183dff56 +0, 119, 119, 1, 38016, 0xa470af8d +0, 120, 120, 1, 38016, 0xe017d594 +0, 121, 121, 1, 38016, 0xb899d48b +0, 122, 122, 1, 38016, 0x0d3bc5f7 +0, 123, 123, 1, 38016, 0xd68bbb0d +0, 124, 124, 1, 38016, 0x8bf5b4cb +0, 125, 125, 1, 38016, 0x6bfcaa47 +0, 126, 126, 1, 38016, 0x29a9b01b +0, 127, 127, 1, 38016, 0xcdedbdb7 +0, 128, 128, 1, 38016, 0xdb5ad9c3 +0, 129, 129, 1, 38016, 0x468aeef6 +0, 130, 130, 1, 38016, 0xdc2b143e +0, 131, 131, 1, 38016, 0x6776277c +0, 132, 132, 1, 38016, 0xb78d5294 +0, 133, 133, 1, 38016, 0x1dfb63ab +0, 134, 134, 1, 38016, 0xbd1f99bc +0, 135, 135, 1, 38016, 0xde16b89a +0, 136, 136, 1, 38016, 0xbf46edca +0, 137, 137, 1, 38016, 0x6306e8c4 +0, 138, 138, 1, 38016, 0x7b09d224 +0, 139, 139, 1, 38016, 0xfea1aff6 +0, 140, 140, 1, 38016, 0x183686b0 +0, 141, 141, 1, 38016, 0x665a61ff +0, 142, 142, 1, 38016, 0xc8af42d1 +0, 143, 143, 1, 38016, 0xe2326bc1 +0, 144, 144, 1, 38016, 0x56dbde82 +0, 145, 145, 1, 38016, 0xa0254f97 +0, 146, 146, 1, 38016, 0x3b74a0b4 +0, 147, 147, 1, 38016, 0x9aee9b7f +0, 148, 148, 1, 38016, 0xd94b6133 +0, 149, 149, 1, 38016, 0x5819f795 +0, 150, 150, 1, 38016, 0xc45a8c02 +0, 151, 151, 1, 38016, 0x2f9204a0 +0, 152, 152, 1, 38016, 0xbe09e051 +0, 153, 153, 1, 38016, 0xb542badd +0, 154, 154, 1, 38016, 0x23bd9e00 +0, 155, 155, 1, 38016, 0x4f338d3d +0, 156, 156, 1, 38016, 0x8c91e8f3 +0, 157, 157, 1, 38016, 0xa7347d57 +0, 158, 158, 1, 38016, 0x6d91de4d +0, 159, 159, 1, 38016, 0x3443d936 +0, 160, 160, 1, 38016, 0x9d25b4e2 +0, 161, 161, 1, 38016, 0xd93cd4b3 +0, 162, 162, 1, 38016, 0xa1c9e9a0 +0, 163, 163, 1, 38016, 0x1482f220 +0, 164, 164, 1, 38016, 0x1295f270 +0, 165, 165, 1, 38016, 0x399ae9da +0, 166, 166, 1, 38016, 0x85dcdf28 +0, 167, 167, 1, 38016, 0x4207b9e5 +0, 168, 168, 1, 38016, 0xad1c9d75 +0, 169, 169, 1, 38016, 0x4a266c14 +0, 170, 170, 1, 38016, 0x3afc4508 +0, 171, 171, 1, 38016, 0x2b1b2385 +0, 172, 172, 1, 38016, 0x738f005f +0, 173, 173, 1, 38016, 0xfec3d833 +0, 174, 174, 1, 38016, 0x3f7f6ae9 +0, 175, 175, 1, 38016, 0xd8551823 +0, 176, 176, 1, 38016, 0x6df03570 +0, 177, 177, 1, 38016, 0x767c3054 +0, 178, 178, 1, 38016, 0x89bd342c +0, 179, 179, 1, 38016, 0x77ba806c +0, 180, 180, 1, 38016, 0x1c98005c +0, 181, 181, 1, 38016, 0xa13ce2a3 +0, 182, 182, 1, 38016, 0x1be59915 +0, 183, 183, 1, 38016, 0x279c6027 +0, 184, 184, 1, 38016, 0x96ac11a2 +0, 185, 185, 1, 38016, 0x3ae95131 +0, 186, 186, 1, 38016, 0xae19f7fe +0, 187, 187, 1, 38016, 0xcde4efe6 +0, 188, 188, 1, 38016, 0x5ecc3f7a +0, 189, 189, 1, 38016, 0x79645152 +0, 190, 190, 1, 38016, 0x1ee2e89f +0, 191, 191, 1, 38016, 0x91d34bb4 +0, 192, 192, 1, 38016, 0xf019d464 +0, 193, 193, 1, 38016, 0x8eb07205 +0, 194, 194, 1, 38016, 0x5399bb5b +0, 195, 195, 1, 38016, 0x61f0c77a +0, 196, 196, 1, 38016, 0xb2bd8726 +0, 197, 197, 1, 38016, 0x47b89243 +0, 198, 198, 1, 38016, 0xebfe4d76 +0, 199, 199, 1, 38016, 0xe8f87d91 +0, 200, 200, 1, 38016, 0x5e9fb239 +0, 201, 201, 1, 38016, 0x357ca1f8 +0, 202, 202, 1, 38016, 0x757d2e02 +0, 203, 203, 1, 38016, 0x40672e7c +0, 204, 204, 1, 38016, 0xd966abca +0, 205, 205, 1, 38016, 0xe98d0d47 +0, 206, 206, 1, 38016, 0x341babf5 +0, 207, 207, 1, 38016, 0xd12d5a0c +0, 208, 208, 1, 38016, 0xea2f99ab +0, 209, 209, 1, 38016, 0x14bce88e +0, 210, 210, 1, 38016, 0xe4bda9e8 +0, 211, 211, 1, 38016, 0x2c57ec89 +0, 212, 212, 1, 38016, 0x28bbb83e +0, 213, 213, 1, 38016, 0xf8444b54 +0, 214, 214, 1, 38016, 0x3aba03cd +0, 215, 215, 1, 38016, 0x373daa20 +0, 216, 216, 1, 38016, 0x69586597 +0, 217, 217, 1, 38016, 0xc0c70d53 +0, 218, 218, 1, 38016, 0x76a5df5a +0, 219, 219, 1, 38016, 0x1afde8f0 +0, 220, 220, 1, 38016, 0x9638285a +0, 221, 221, 1, 38016, 0x9f0686c0 +0, 222, 222, 1, 38016, 0xc65b2238 +0, 223, 223, 1, 38016, 0x0d61b610 +0, 224, 224, 1, 38016, 0x78e14e1f +0, 225, 225, 1, 38016, 0xcf80ac4a +0, 226, 226, 1, 38016, 0xe094083d +0, 227, 227, 1, 38016, 0xee5e612e +0, 228, 228, 1, 38016, 0x51cdad9d +0, 229, 229, 1, 38016, 0xae41100e +0, 230, 230, 1, 38016, 0x77558f58 +0, 231, 231, 1, 38016, 0xb9503b95 +0, 232, 232, 1, 38016, 0xb71dffeb +0, 233, 233, 1, 38016, 0x1872e3e6 +0, 234, 234, 1, 38016, 0x29c3d252 +0, 235, 235, 1, 38016, 0x1c77c6ec +0, 236, 236, 1, 38016, 0x26feb194 +0, 237, 237, 1, 38016, 0x3307c3c4 +0, 238, 238, 1, 38016, 0x8e5a8080 +0, 239, 239, 1, 38016, 0x933472f7 +0, 240, 240, 1, 38016, 0xd4768d84 +0, 241, 241, 1, 38016, 0x3324485f +0, 242, 242, 1, 38016, 0xd50af078 +0, 243, 243, 1, 38016, 0x53820752 +0, 244, 244, 1, 38016, 0xbe7f1c47 +0, 245, 245, 1, 38016, 0xe43d3a34 +0, 246, 246, 1, 38016, 0x57194b82 +0, 247, 247, 1, 38016, 0x68a052ed +0, 248, 248, 1, 38016, 0x5c898052 +0, 249, 249, 1, 38016, 0x7104a6ad +0, 250, 250, 1, 38016, 0x1676b5e8 +0, 251, 251, 1, 38016, 0xe1cfd375 +0, 252, 252, 1, 38016, 0x16fede04 +0, 253, 253, 1, 38016, 0xca49dd4a +0, 254, 254, 1, 38016, 0x7b98d9d1 +0, 255, 255, 1, 38016, 0x4020d210 +0, 256, 256, 1, 38016, 0x62c5d1e4 +0, 257, 257, 1, 38016, 0x756abdb4 +0, 258, 258, 1, 38016, 0x558fb00f +0, 259, 259, 1, 38016, 0x4ab0b1f1 +0, 260, 260, 1, 38016, 0x7c9fb0c2 +0, 261, 261, 1, 38016, 0xcecfbdd0 +0, 262, 262, 1, 38016, 0x70e6d174 +0, 263, 263, 1, 38016, 0x83d7ddde +0, 264, 264, 1, 38016, 0xbbcde2d9 +0, 265, 265, 1, 38016, 0xc89eeaef +0, 266, 266, 1, 38016, 0x8565e15c +0, 267, 267, 1, 38016, 0x28e0db24 +0, 268, 268, 1, 38016, 0x1d9dd334 +0, 269, 269, 1, 38016, 0xce02c452 +0, 270, 270, 1, 38016, 0xe29dbd0c +0, 271, 271, 1, 38016, 0x4aa3b638 +0, 272, 272, 1, 38016, 0x5533c135 +0, 273, 273, 1, 38016, 0x6c57b65f +0, 274, 274, 1, 38016, 0x23d3b851 +0, 275, 275, 1, 38016, 0xd8cbb960 +0, 276, 276, 1, 38016, 0x02edb916 +0, 277, 277, 1, 38016, 0xa622bd42 +0, 278, 278, 1, 38016, 0x4ba5be1c +0, 279, 279, 1, 38016, 0xe69bb625 +0, 280, 280, 1, 38016, 0xbca5b292 +0, 281, 281, 1, 38016, 0xde38b1c8 +0, 282, 282, 1, 38016, 0xe9e3b617 +0, 283, 283, 1, 38016, 0x216cc574 +0, 284, 284, 1, 38016, 0x3780c5ad +0, 285, 285, 1, 38016, 0x5531e3f9 +0, 286, 286, 1, 38016, 0xe2c5f5d4 +0, 287, 287, 1, 38016, 0x24cefc6e +0, 288, 288, 1, 38016, 0xa3ce003d +0, 289, 289, 1, 38016, 0x42d01c9e +0, 290, 290, 1, 38016, 0xbfc13689 +0, 291, 291, 1, 38016, 0x122647a9 +0, 292, 292, 1, 38016, 0xe45254da +0, 293, 293, 1, 38016, 0xad955b0c +0, 294, 294, 1, 38016, 0x4b086abb +0, 295, 295, 1, 38016, 0xd4857b8c +0, 296, 296, 1, 38016, 0xa71594ce +0, 297, 297, 1, 38016, 0x04e4a73d +0, 298, 298, 1, 38016, 0x295abf63 +0, 299, 299, 1, 38016, 0xbe4ed5dd +0, 300, 300, 1, 38016, 0x087bcf64 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-mr6_bt_b ffmpeg-4.4/tests/ref/fate/h264-conformance-mr6_bt_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-mr6_bt_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-mr6_bt_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,63 +3,63 @@ #codec_id 0: rawvideo #dimensions 0: 192x128 #sar 0: 0/1 -0, 0, 0, 1, 36864, 0x954464be -0, 1, 1, 1, 36864, 0xace1d90b -0, 2, 2, 1, 36864, 0x8f149f03 -0, 3, 3, 1, 36864, 0xea9b21eb -0, 4, 4, 1, 36864, 0xb51d9fe3 -0, 5, 5, 1, 36864, 0x61bd11d7 -0, 6, 6, 1, 36864, 0x9d36980f -0, 7, 7, 1, 36864, 0xa4192c5e -0, 8, 8, 1, 36864, 0x11006433 -0, 9, 9, 1, 36864, 0x4a243e46 -0, 10, 10, 1, 36864, 0x1807b5e8 -0, 11, 11, 1, 36864, 0xbe37743c -0, 12, 12, 1, 36864, 0x82491319 -0, 13, 13, 1, 36864, 0x006e9914 -0, 14, 14, 1, 36864, 0xa5261884 -0, 15, 15, 1, 36864, 0x2030c9d6 -0, 16, 16, 1, 36864, 0xc80eb1ce -0, 17, 17, 1, 36864, 0x4d559791 -0, 18, 18, 1, 36864, 0xf5f900ee -0, 19, 19, 1, 36864, 0x2cc9c0d7 -0, 20, 20, 1, 36864, 0x5ba14186 -0, 21, 21, 1, 36864, 0x47a46865 -0, 22, 22, 1, 36864, 0x5ba180b7 -0, 23, 23, 1, 36864, 0xc67c4876 -0, 24, 24, 1, 36864, 0x4311d75d -0, 25, 25, 1, 36864, 0x56edb851 -0, 26, 26, 1, 36864, 0x7e5aa3e0 -0, 27, 27, 1, 36864, 0x8df8283a -0, 28, 28, 1, 36864, 0xb8583ddf -0, 29, 29, 1, 36864, 0xf33fb779 -0, 30, 30, 1, 36864, 0xe9942ddc -0, 31, 31, 1, 36864, 0x2bc5f7fa -0, 32, 32, 1, 36864, 0xc7b66c65 -0, 33, 33, 1, 36864, 0x1a524319 -0, 34, 34, 1, 36864, 0xf60c6141 -0, 35, 35, 1, 36864, 0x113f41f2 -0, 36, 36, 1, 36864, 0xad191a31 -0, 37, 37, 1, 36864, 0x3898264a -0, 38, 38, 1, 36864, 0x3c2f34a4 -0, 39, 39, 1, 36864, 0xd0fc76aa -0, 40, 40, 1, 36864, 0x2870b546 -0, 41, 41, 1, 36864, 0x7d326fb4 -0, 42, 42, 1, 36864, 0xd7ed14e1 -0, 43, 43, 1, 36864, 0x205174aa -0, 44, 44, 1, 36864, 0xa3a88be9 -0, 45, 45, 1, 36864, 0xd6f01751 -0, 46, 46, 1, 36864, 0x5420bb80 -0, 47, 47, 1, 36864, 0xe14518f9 -0, 48, 48, 1, 36864, 0x931db61e -0, 49, 49, 1, 36864, 0x052ecfae -0, 50, 50, 1, 36864, 0x29b1b0f5 -0, 51, 51, 1, 36864, 0xa3057117 -0, 52, 52, 1, 36864, 0x954464be -0, 53, 53, 1, 36864, 0xace1d90b -0, 54, 54, 1, 36864, 0x8f149f03 -0, 55, 55, 1, 36864, 0x485722c5 -0, 56, 56, 1, 36864, 0x534b18f9 -0, 57, 57, 1, 36864, 0xc893a0a6 -0, 58, 58, 1, 36864, 0x8b04e1dd -0, 59, 59, 1, 36864, 0xaf536964 +0, 1, 1, 1, 36864, 0x954464be +0, 2, 2, 1, 36864, 0xace1d90b +0, 3, 3, 1, 36864, 0x8f149f03 +0, 4, 4, 1, 36864, 0xea9b21eb +0, 5, 5, 1, 36864, 0xb51d9fe3 +0, 6, 6, 1, 36864, 0x61bd11d7 +0, 7, 7, 1, 36864, 0x9d36980f +0, 8, 8, 1, 36864, 0xa4192c5e +0, 9, 9, 1, 36864, 0x11006433 +0, 10, 10, 1, 36864, 0x4a243e46 +0, 11, 11, 1, 36864, 0x1807b5e8 +0, 12, 12, 1, 36864, 0xbe37743c +0, 13, 13, 1, 36864, 0x82491319 +0, 14, 14, 1, 36864, 0x006e9914 +0, 15, 15, 1, 36864, 0xa5261884 +0, 16, 16, 1, 36864, 0x2030c9d6 +0, 17, 17, 1, 36864, 0xc80eb1ce +0, 18, 18, 1, 36864, 0x4d559791 +0, 19, 19, 1, 36864, 0xf5f900ee +0, 20, 20, 1, 36864, 0x2cc9c0d7 +0, 21, 21, 1, 36864, 0x5ba14186 +0, 22, 22, 1, 36864, 0x47a46865 +0, 23, 23, 1, 36864, 0x5ba180b7 +0, 24, 24, 1, 36864, 0xc67c4876 +0, 25, 25, 1, 36864, 0x4311d75d +0, 26, 26, 1, 36864, 0x56edb851 +0, 27, 27, 1, 36864, 0x7e5aa3e0 +0, 28, 28, 1, 36864, 0x8df8283a +0, 29, 29, 1, 36864, 0xb8583ddf +0, 30, 30, 1, 36864, 0xf33fb779 +0, 31, 31, 1, 36864, 0xe9942ddc +0, 32, 32, 1, 36864, 0x2bc5f7fa +0, 33, 33, 1, 36864, 0xc7b66c65 +0, 34, 34, 1, 36864, 0x1a524319 +0, 35, 35, 1, 36864, 0xf60c6141 +0, 36, 36, 1, 36864, 0x113f41f2 +0, 37, 37, 1, 36864, 0xad191a31 +0, 38, 38, 1, 36864, 0x3898264a +0, 39, 39, 1, 36864, 0x3c2f34a4 +0, 40, 40, 1, 36864, 0xd0fc76aa +0, 41, 41, 1, 36864, 0x2870b546 +0, 42, 42, 1, 36864, 0x7d326fb4 +0, 43, 43, 1, 36864, 0xd7ed14e1 +0, 44, 44, 1, 36864, 0x205174aa +0, 45, 45, 1, 36864, 0xa3a88be9 +0, 46, 46, 1, 36864, 0xd6f01751 +0, 47, 47, 1, 36864, 0x5420bb80 +0, 48, 48, 1, 36864, 0xe14518f9 +0, 49, 49, 1, 36864, 0x931db61e +0, 50, 50, 1, 36864, 0x052ecfae +0, 51, 51, 1, 36864, 0x29b1b0f5 +0, 52, 52, 1, 36864, 0xa3057117 +0, 53, 53, 1, 36864, 0x954464be +0, 54, 54, 1, 36864, 0xace1d90b +0, 55, 55, 1, 36864, 0x8f149f03 +0, 56, 56, 1, 36864, 0x485722c5 +0, 57, 57, 1, 36864, 0x534b18f9 +0, 58, 58, 1, 36864, 0xc893a0a6 +0, 59, 59, 1, 36864, 0x8b04e1dd +0, 60, 60, 1, 36864, 0xaf536964 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-mr7_bt_b ffmpeg-4.4/tests/ref/fate/h264-conformance-mr7_bt_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-mr7_bt_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-mr7_bt_b 2021-04-08 21:28:40.000000000 +0000 @@ -13,53 +13,53 @@ 0, 7, 7, 1, 36864, 0xf2f324dd 0, 8, 8, 1, 36864, 0x592b5a01 0, 9, 9, 1, 36864, 0x4c2f2d91 -0, 10, 10, 1, 36864, 0x8baeb610 -0, 11, 11, 1, 36864, 0x86d47617 -0, 12, 12, 1, 36864, 0xf11011cc -0, 13, 13, 1, 36864, 0xe56a9daa -0, 14, 14, 1, 36864, 0xd57119d6 -0, 15, 15, 1, 36864, 0xe28fcde7 -0, 16, 16, 1, 36864, 0x9aeeba86 -0, 17, 17, 1, 36864, 0xa518a7c5 -0, 18, 18, 1, 36864, 0x9af410be -0, 19, 19, 1, 36864, 0x1fedd12f -0, 20, 20, 1, 36864, 0xa8032e03 -0, 21, 21, 1, 36864, 0x579e6274 -0, 22, 22, 1, 36864, 0x99846ef6 -0, 23, 23, 1, 36864, 0xb5ad3ca7 -0, 24, 24, 1, 36864, 0x7845cb90 -0, 25, 25, 1, 36864, 0x569fae24 -0, 26, 26, 1, 36864, 0x8a3c9f98 -0, 27, 27, 1, 36864, 0x0b7722af -0, 28, 28, 1, 36864, 0x699c2dd8 -0, 29, 29, 1, 36864, 0xd477af13 -0, 30, 30, 1, 36864, 0x17b62d7c -0, 31, 31, 1, 36864, 0xb1ecf6a7 -0, 32, 32, 1, 36864, 0xf9c17e4c -0, 33, 33, 1, 36864, 0xe7c44618 -0, 34, 34, 1, 36864, 0x7e23654e -0, 35, 35, 1, 36864, 0xd8a0457c -0, 36, 36, 1, 36864, 0x57e11df1 -0, 37, 37, 1, 36864, 0xd54d2a43 -0, 38, 38, 1, 36864, 0xc6f03950 -0, 39, 39, 1, 36864, 0x687e750e -0, 40, 40, 1, 36864, 0x2870b546 -0, 41, 41, 1, 36864, 0xda0370d0 -0, 42, 42, 1, 36864, 0x5a2e0bff -0, 43, 43, 1, 36864, 0xe1f07533 -0, 44, 44, 1, 36864, 0x3de892b9 -0, 45, 45, 1, 36864, 0xe5c31505 -0, 46, 46, 1, 36864, 0x96b8c082 -0, 47, 47, 1, 36864, 0x55391423 -0, 48, 48, 1, 36864, 0xc285bd71 -0, 49, 49, 1, 36864, 0xf702d9f3 -0, 50, 50, 1, 36864, 0x7afbadf8 -0, 51, 51, 1, 36864, 0xd9b568f7 -0, 52, 52, 1, 36864, 0x579e6274 -0, 53, 53, 1, 36864, 0x8650c61c -0, 54, 54, 1, 36864, 0xbc359647 -0, 55, 55, 1, 36864, 0x5522328c -0, 56, 56, 1, 36864, 0x02821fd6 -0, 57, 57, 1, 36864, 0xb4ee9562 -0, 58, 58, 1, 36864, 0xcefedb68 -0, 59, 59, 1, 36864, 0xd959782e +0, 11, 11, 1, 36864, 0x8baeb610 +0, 12, 12, 1, 36864, 0x86d47617 +0, 13, 13, 1, 36864, 0xf11011cc +0, 14, 14, 1, 36864, 0xe56a9daa +0, 15, 15, 1, 36864, 0xd57119d6 +0, 16, 16, 1, 36864, 0xe28fcde7 +0, 17, 17, 1, 36864, 0x9aeeba86 +0, 18, 18, 1, 36864, 0xa518a7c5 +0, 19, 19, 1, 36864, 0x9af410be +0, 20, 20, 1, 36864, 0x1fedd12f +0, 21, 21, 1, 36864, 0xa8032e03 +0, 22, 22, 1, 36864, 0x579e6274 +0, 23, 23, 1, 36864, 0x99846ef6 +0, 24, 24, 1, 36864, 0xb5ad3ca7 +0, 25, 25, 1, 36864, 0x7845cb90 +0, 26, 26, 1, 36864, 0x569fae24 +0, 27, 27, 1, 36864, 0x8a3c9f98 +0, 28, 28, 1, 36864, 0x0b7722af +0, 29, 29, 1, 36864, 0x699c2dd8 +0, 30, 30, 1, 36864, 0xd477af13 +0, 31, 31, 1, 36864, 0x17b62d7c +0, 32, 32, 1, 36864, 0xb1ecf6a7 +0, 33, 33, 1, 36864, 0xf9c17e4c +0, 34, 34, 1, 36864, 0xe7c44618 +0, 35, 35, 1, 36864, 0x7e23654e +0, 36, 36, 1, 36864, 0xd8a0457c +0, 37, 37, 1, 36864, 0x57e11df1 +0, 38, 38, 1, 36864, 0xd54d2a43 +0, 39, 39, 1, 36864, 0xc6f03950 +0, 40, 40, 1, 36864, 0x687e750e +0, 41, 41, 1, 36864, 0x2870b546 +0, 42, 42, 1, 36864, 0xda0370d0 +0, 43, 43, 1, 36864, 0x5a2e0bff +0, 44, 44, 1, 36864, 0xe1f07533 +0, 45, 45, 1, 36864, 0x3de892b9 +0, 46, 46, 1, 36864, 0xe5c31505 +0, 47, 47, 1, 36864, 0x96b8c082 +0, 48, 48, 1, 36864, 0x55391423 +0, 49, 49, 1, 36864, 0xc285bd71 +0, 50, 50, 1, 36864, 0xf702d9f3 +0, 51, 51, 1, 36864, 0x7afbadf8 +0, 52, 52, 1, 36864, 0xd9b568f7 +0, 53, 53, 1, 36864, 0x579e6274 +0, 54, 54, 1, 36864, 0x8650c61c +0, 55, 55, 1, 36864, 0xbc359647 +0, 56, 56, 1, 36864, 0x5522328c +0, 57, 57, 1, 36864, 0x02821fd6 +0, 58, 58, 1, 36864, 0xb4ee9562 +0, 59, 59, 1, 36864, 0xcefedb68 +0, 60, 60, 1, 36864, 0xd959782e diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-mr8_bt_b ffmpeg-4.4/tests/ref/fate/h264-conformance-mr8_bt_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-mr8_bt_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-mr8_bt_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,61 +3,61 @@ #codec_id 0: rawvideo #dimensions 0: 192x128 #sar 0: 0/1 -0, 0, 0, 1, 36864, 0x36df68f4 -0, 1, 1, 1, 36864, 0x52d4c6d9 -0, 2, 2, 1, 36864, 0xad16b0be -0, 3, 3, 1, 36864, 0xf8c72556 -0, 4, 4, 1, 36864, 0x70aaad30 -0, 5, 5, 1, 36864, 0x53cffd5e -0, 6, 6, 1, 36864, 0xb3fa8abc -0, 7, 7, 1, 36864, 0x9c894009 -0, 8, 8, 1, 36864, 0xfbc08050 -0, 9, 9, 1, 36864, 0x9d5b2d65 -0, 10, 10, 1, 36864, 0x3bd8bb5d -0, 11, 11, 1, 36864, 0x8d976ecf -0, 12, 12, 1, 36864, 0x25010368 -0, 13, 13, 1, 36864, 0xb6e6a11c -0, 14, 14, 1, 36864, 0x595a3967 -0, 15, 15, 1, 36864, 0x4fbcb9a8 -0, 16, 16, 1, 36864, 0xc7c5c16b -0, 17, 17, 1, 36864, 0x661ae1eb -0, 18, 18, 1, 36864, 0x169f04a7 -0, 19, 19, 1, 36864, 0xd124c93a -0, 20, 20, 1, 36864, 0x3f642dba -0, 21, 21, 1, 36864, 0xe7ad6956 -0, 22, 22, 1, 36864, 0x47dc76d3 -0, 23, 23, 1, 36864, 0x496a3917 -0, 24, 24, 1, 36864, 0xa976d5f3 -0, 25, 25, 1, 36864, 0x507bb685 -0, 26, 26, 1, 36864, 0x2f61ac12 -0, 27, 27, 1, 36864, 0x527818d8 -0, 28, 28, 1, 36864, 0xa4983396 -0, 29, 29, 1, 36864, 0x3ec9b07b -0, 30, 30, 1, 36864, 0x7db52d99 -0, 31, 31, 1, 36864, 0xe974fd00 -0, 32, 32, 1, 36864, 0x9c677a4f -0, 33, 33, 1, 36864, 0x108f3a05 -0, 34, 34, 1, 36864, 0x23a56ba2 -0, 35, 35, 1, 36864, 0x4c8d47e8 -0, 36, 36, 1, 36864, 0x9e0b0f09 -0, 37, 37, 1, 36864, 0x4d262b16 -0, 38, 38, 1, 36864, 0x6122402e -0, 39, 39, 1, 36864, 0xed037036 -0, 40, 40, 1, 36864, 0x62b3ba08 -0, 41, 41, 1, 36864, 0x7f876930 -0, 42, 42, 1, 36864, 0x4a6c0983 -0, 43, 43, 1, 36864, 0xf9787086 -0, 44, 44, 1, 36864, 0x01d1b1b5 -0, 45, 45, 1, 36864, 0xc1622655 -0, 46, 46, 1, 36864, 0x27e8e0f7 -0, 47, 47, 1, 36864, 0xc1622655 -0, 48, 48, 1, 36864, 0x12c2b7e9 -0, 49, 49, 1, 36864, 0xd752d2ef -0, 50, 50, 1, 36864, 0xcbb1c3a7 -0, 51, 51, 1, 36864, 0x18c56fba -0, 52, 52, 1, 36864, 0xb1b3771c -0, 53, 53, 1, 36864, 0x284ef3c4 -0, 54, 54, 1, 36864, 0xda6eb5a0 -0, 55, 55, 1, 36864, 0x17ad337c -0, 56, 56, 1, 36864, 0xe2801e4f -0, 57, 57, 1, 36864, 0x6c33bd17 +0, 1, 1, 1, 36864, 0x36df68f4 +0, 2, 2, 1, 36864, 0x52d4c6d9 +0, 3, 3, 1, 36864, 0xad16b0be +0, 4, 4, 1, 36864, 0xf8c72556 +0, 5, 5, 1, 36864, 0x70aaad30 +0, 6, 6, 1, 36864, 0x53cffd5e +0, 7, 7, 1, 36864, 0xb3fa8abc +0, 8, 8, 1, 36864, 0x9c894009 +0, 9, 9, 1, 36864, 0xfbc08050 +0, 10, 10, 1, 36864, 0x9d5b2d65 +0, 11, 11, 1, 36864, 0x3bd8bb5d +0, 12, 12, 1, 36864, 0x8d976ecf +0, 13, 13, 1, 36864, 0x25010368 +0, 14, 14, 1, 36864, 0xb6e6a11c +0, 15, 15, 1, 36864, 0x595a3967 +0, 16, 16, 1, 36864, 0x4fbcb9a8 +0, 17, 17, 1, 36864, 0xc7c5c16b +0, 18, 18, 1, 36864, 0x661ae1eb +0, 19, 19, 1, 36864, 0x169f04a7 +0, 20, 20, 1, 36864, 0xd124c93a +0, 21, 21, 1, 36864, 0x3f642dba +0, 22, 22, 1, 36864, 0xe7ad6956 +0, 23, 23, 1, 36864, 0x47dc76d3 +0, 24, 24, 1, 36864, 0x496a3917 +0, 25, 25, 1, 36864, 0xa976d5f3 +0, 26, 26, 1, 36864, 0x507bb685 +0, 27, 27, 1, 36864, 0x2f61ac12 +0, 28, 28, 1, 36864, 0x527818d8 +0, 29, 29, 1, 36864, 0xa4983396 +0, 30, 30, 1, 36864, 0x3ec9b07b +0, 31, 31, 1, 36864, 0x7db52d99 +0, 32, 32, 1, 36864, 0xe974fd00 +0, 33, 33, 1, 36864, 0x9c677a4f +0, 34, 34, 1, 36864, 0x108f3a05 +0, 35, 35, 1, 36864, 0x23a56ba2 +0, 36, 36, 1, 36864, 0x4c8d47e8 +0, 37, 37, 1, 36864, 0x9e0b0f09 +0, 38, 38, 1, 36864, 0x4d262b16 +0, 39, 39, 1, 36864, 0x6122402e +0, 40, 40, 1, 36864, 0xed037036 +0, 41, 41, 1, 36864, 0x62b3ba08 +0, 42, 42, 1, 36864, 0x7f876930 +0, 43, 43, 1, 36864, 0x4a6c0983 +0, 44, 44, 1, 36864, 0xf9787086 +0, 45, 45, 1, 36864, 0x01d1b1b5 +0, 46, 46, 1, 36864, 0xc1622655 +0, 47, 47, 1, 36864, 0x27e8e0f7 +0, 48, 48, 1, 36864, 0xc1622655 +0, 49, 49, 1, 36864, 0x12c2b7e9 +0, 50, 50, 1, 36864, 0xd752d2ef +0, 51, 51, 1, 36864, 0xcbb1c3a7 +0, 52, 52, 1, 36864, 0x18c56fba +0, 53, 53, 1, 36864, 0xb1b3771c +0, 54, 54, 1, 36864, 0x284ef3c4 +0, 55, 55, 1, 36864, 0xda6eb5a0 +0, 56, 56, 1, 36864, 0x17ad337c +0, 57, 57, 1, 36864, 0xe2801e4f +0, 58, 58, 1, 36864, 0x6c33bd17 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-mr9_bt_b ffmpeg-4.4/tests/ref/fate/h264-conformance-mr9_bt_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-mr9_bt_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-mr9_bt_b 2021-04-08 21:28:40.000000000 +0000 @@ -13,51 +13,51 @@ 0, 7, 7, 1, 36864, 0x75122807 0, 8, 8, 1, 36864, 0x27036a2b 0, 9, 9, 1, 36864, 0x00072654 -0, 10, 10, 1, 36864, 0x49fab4fd -0, 11, 11, 1, 36864, 0x975a7545 -0, 12, 12, 1, 36864, 0x9b080a2f -0, 13, 13, 1, 36864, 0x78db960e -0, 14, 14, 1, 36864, 0xd7a928d4 -0, 15, 15, 1, 36864, 0x0a83ba1b -0, 16, 16, 1, 36864, 0xad6bb30c -0, 17, 17, 1, 36864, 0xf6addb0d -0, 18, 18, 1, 36864, 0x00540a0a -0, 19, 19, 1, 36864, 0x049cc748 -0, 20, 20, 1, 36864, 0x5b1e2291 -0, 21, 21, 1, 36864, 0x2367706e -0, 22, 22, 1, 36864, 0x88ef6b11 -0, 23, 23, 1, 36864, 0x85b73230 -0, 24, 24, 1, 36864, 0xe46cd522 -0, 25, 25, 1, 36864, 0x98489c05 -0, 26, 26, 1, 36864, 0x7e439564 -0, 27, 27, 1, 36864, 0x71330799 -0, 28, 28, 1, 36864, 0x81a6239e -0, 29, 29, 1, 36864, 0x8005a302 -0, 30, 30, 1, 36864, 0xdf132e3f -0, 31, 31, 1, 36864, 0x2a1d00de -0, 32, 32, 1, 36864, 0x7bb57e14 -0, 33, 33, 1, 36864, 0xf2a637cf -0, 34, 34, 1, 36864, 0xae6f6916 -0, 35, 35, 1, 36864, 0x2f1d4763 -0, 36, 36, 1, 36864, 0xa4e1145e -0, 37, 37, 1, 36864, 0xc1644392 -0, 38, 38, 1, 36864, 0x21853537 -0, 39, 39, 1, 36864, 0x0bc45bac -0, 40, 40, 1, 36864, 0x84ccb8ee -0, 41, 41, 1, 36864, 0x65de651c -0, 42, 42, 1, 36864, 0x33ff027e -0, 43, 43, 1, 36864, 0xefe47056 -0, 44, 44, 1, 36864, 0x8952b47c -0, 45, 45, 1, 36864, 0x78730fcf -0, 46, 46, 1, 36864, 0x14bae79f -0, 47, 47, 1, 36864, 0x53230fbe -0, 48, 48, 1, 36864, 0x15b0b245 -0, 49, 49, 1, 36864, 0x45fbd155 -0, 50, 50, 1, 36864, 0x41cfbac4 -0, 51, 51, 1, 36864, 0x0d635d61 -0, 52, 52, 1, 36864, 0x55aa8d3c -0, 53, 53, 1, 36864, 0x8f02fbaf -0, 54, 54, 1, 36864, 0xb17fac3f -0, 55, 55, 1, 36864, 0xc12627f9 -0, 56, 56, 1, 36864, 0xa5971e4a -0, 57, 57, 1, 36864, 0x3677abfe +0, 11, 11, 1, 36864, 0x49fab4fd +0, 12, 12, 1, 36864, 0x975a7545 +0, 13, 13, 1, 36864, 0x9b080a2f +0, 14, 14, 1, 36864, 0x78db960e +0, 15, 15, 1, 36864, 0xd7a928d4 +0, 16, 16, 1, 36864, 0x0a83ba1b +0, 17, 17, 1, 36864, 0xad6bb30c +0, 18, 18, 1, 36864, 0xf6addb0d +0, 19, 19, 1, 36864, 0x00540a0a +0, 20, 20, 1, 36864, 0x049cc748 +0, 21, 21, 1, 36864, 0x5b1e2291 +0, 22, 22, 1, 36864, 0x2367706e +0, 23, 23, 1, 36864, 0x88ef6b11 +0, 24, 24, 1, 36864, 0x85b73230 +0, 25, 25, 1, 36864, 0xe46cd522 +0, 26, 26, 1, 36864, 0x98489c05 +0, 27, 27, 1, 36864, 0x7e439564 +0, 28, 28, 1, 36864, 0x71330799 +0, 29, 29, 1, 36864, 0x81a6239e +0, 30, 30, 1, 36864, 0x8005a302 +0, 31, 31, 1, 36864, 0xdf132e3f +0, 32, 32, 1, 36864, 0x2a1d00de +0, 33, 33, 1, 36864, 0x7bb57e14 +0, 34, 34, 1, 36864, 0xf2a637cf +0, 35, 35, 1, 36864, 0xae6f6916 +0, 36, 36, 1, 36864, 0x2f1d4763 +0, 37, 37, 1, 36864, 0xa4e1145e +0, 38, 38, 1, 36864, 0xc1644392 +0, 39, 39, 1, 36864, 0x21853537 +0, 40, 40, 1, 36864, 0x0bc45bac +0, 41, 41, 1, 36864, 0x84ccb8ee +0, 42, 42, 1, 36864, 0x65de651c +0, 43, 43, 1, 36864, 0x33ff027e +0, 44, 44, 1, 36864, 0xefe47056 +0, 45, 45, 1, 36864, 0x8952b47c +0, 46, 46, 1, 36864, 0x78730fcf +0, 47, 47, 1, 36864, 0x14bae79f +0, 48, 48, 1, 36864, 0x53230fbe +0, 49, 49, 1, 36864, 0x15b0b245 +0, 50, 50, 1, 36864, 0x45fbd155 +0, 51, 51, 1, 36864, 0x41cfbac4 +0, 52, 52, 1, 36864, 0x0d635d61 +0, 53, 53, 1, 36864, 0x55aa8d3c +0, 54, 54, 1, 36864, 0x8f02fbaf +0, 55, 55, 1, 36864, 0xb17fac3f +0, 56, 56, 1, 36864, 0xc12627f9 +0, 57, 57, 1, 36864, 0xa5971e4a +0, 58, 58, 1, 36864, 0x3677abfe diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-sharp_mp_field_1_b ffmpeg-4.4/tests/ref/fate/h264-conformance-sharp_mp_field_1_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-sharp_mp_field_1_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-sharp_mp_field_1_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,18 +3,18 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0xc93c7c47 -0, 1, 1, 1, 518400, 0xa3f2e502 -0, 2, 2, 1, 518400, 0xb98920a4 -0, 3, 3, 1, 518400, 0xad098ec1 -0, 4, 4, 1, 518400, 0x3009b7aa -0, 5, 5, 1, 518400, 0xcf514018 -0, 6, 6, 1, 518400, 0xd869038d -0, 7, 7, 1, 518400, 0x3ce5e188 -0, 8, 8, 1, 518400, 0x029b4c14 -0, 9, 9, 1, 518400, 0xd2224afc -0, 10, 10, 1, 518400, 0xbbca027c -0, 11, 11, 1, 518400, 0x1f3fa0ac -0, 12, 12, 1, 518400, 0x823b0125 -0, 13, 13, 1, 518400, 0xaaa27cfb -0, 14, 14, 1, 518400, 0x5e926a4a +0, 1, 1, 1, 518400, 0xc93c7c47 +0, 2, 2, 1, 518400, 0xa3f2e502 +0, 3, 3, 1, 518400, 0xb98920a4 +0, 4, 4, 1, 518400, 0xad098ec1 +0, 5, 5, 1, 518400, 0x3009b7aa +0, 6, 6, 1, 518400, 0xcf514018 +0, 7, 7, 1, 518400, 0xd869038d +0, 8, 8, 1, 518400, 0x3ce5e188 +0, 9, 9, 1, 518400, 0x029b4c14 +0, 10, 10, 1, 518400, 0xd2224afc +0, 11, 11, 1, 518400, 0xbbca027c +0, 12, 12, 1, 518400, 0x1f3fa0ac +0, 13, 13, 1, 518400, 0x823b0125 +0, 14, 14, 1, 518400, 0xaaa27cfb +0, 15, 15, 1, 518400, 0x5e926a4a diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-sharp_mp_field_2_b ffmpeg-4.4/tests/ref/fate/h264-conformance-sharp_mp_field_2_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-sharp_mp_field_2_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-sharp_mp_field_2_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,18 +3,18 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0xc93c7c47 -0, 1, 1, 1, 518400, 0xf0c4b44a -0, 2, 2, 1, 518400, 0x3f5dc91c -0, 3, 3, 1, 518400, 0x03dc8453 -0, 4, 4, 1, 518400, 0x5e5227af -0, 5, 5, 1, 518400, 0x9e7136af -0, 6, 6, 1, 518400, 0x963a2e3a -0, 7, 7, 1, 518400, 0xa544be6c -0, 8, 8, 1, 518400, 0xefa1f63a -0, 9, 9, 1, 518400, 0x62155ff1 -0, 10, 10, 1, 518400, 0x253eb857 -0, 11, 11, 1, 518400, 0x73530327 -0, 12, 12, 1, 518400, 0x8920c9a3 -0, 13, 13, 1, 518400, 0x4bdd038c -0, 14, 14, 1, 518400, 0xea6016dd +0, 1, 1, 1, 518400, 0xc93c7c47 +0, 2, 2, 1, 518400, 0xf0c4b44a +0, 3, 3, 1, 518400, 0x3f5dc91c +0, 4, 4, 1, 518400, 0x03dc8453 +0, 5, 5, 1, 518400, 0x5e5227af +0, 6, 6, 1, 518400, 0x9e7136af +0, 7, 7, 1, 518400, 0x963a2e3a +0, 8, 8, 1, 518400, 0xa544be6c +0, 9, 9, 1, 518400, 0xefa1f63a +0, 10, 10, 1, 518400, 0x62155ff1 +0, 11, 11, 1, 518400, 0x253eb857 +0, 12, 12, 1, 518400, 0x73530327 +0, 13, 13, 1, 518400, 0x8920c9a3 +0, 14, 14, 1, 518400, 0x4bdd038c +0, 15, 15, 1, 518400, 0xea6016dd diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-sharp_mp_field_3_b ffmpeg-4.4/tests/ref/fate/h264-conformance-sharp_mp_field_3_b --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-sharp_mp_field_3_b 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-sharp_mp_field_3_b 2021-04-08 21:28:40.000000000 +0000 @@ -3,18 +3,18 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 0/1 -0, 0, 0, 1, 518400, 0xc93c7c47 -0, 1, 1, 1, 518400, 0x7112ac25 -0, 2, 2, 1, 518400, 0x28bc28d2 -0, 3, 3, 1, 518400, 0x6fc36875 -0, 4, 4, 1, 518400, 0x3de99be0 -0, 5, 5, 1, 518400, 0x97125499 -0, 6, 6, 1, 518400, 0xb96fca3a -0, 7, 7, 1, 518400, 0x1ec56c0f -0, 8, 8, 1, 518400, 0xc65901d0 -0, 9, 9, 1, 518400, 0x2baa1bfa -0, 10, 10, 1, 518400, 0x244fc6b7 -0, 11, 11, 1, 518400, 0xc3536383 -0, 12, 12, 1, 518400, 0xbcf40d5a -0, 13, 13, 1, 518400, 0x955f4734 -0, 14, 14, 1, 518400, 0xe1b0275e +0, 1, 1, 1, 518400, 0xc93c7c47 +0, 2, 2, 1, 518400, 0x7112ac25 +0, 3, 3, 1, 518400, 0x28bc28d2 +0, 4, 4, 1, 518400, 0x6fc36875 +0, 5, 5, 1, 518400, 0x3de99be0 +0, 6, 6, 1, 518400, 0x97125499 +0, 7, 7, 1, 518400, 0xb96fca3a +0, 8, 8, 1, 518400, 0x1ec56c0f +0, 9, 9, 1, 518400, 0xc65901d0 +0, 10, 10, 1, 518400, 0x2baa1bfa +0, 11, 11, 1, 518400, 0x244fc6b7 +0, 12, 12, 1, 518400, 0xc3536383 +0, 13, 13, 1, 518400, 0xbcf40d5a +0, 14, 14, 1, 518400, 0x955f4734 +0, 15, 15, 1, 518400, 0xe1b0275e diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-sharp_mp_paff_1r2 ffmpeg-4.4/tests/ref/fate/h264-conformance-sharp_mp_paff_1r2 --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-sharp_mp_paff_1r2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-sharp_mp_paff_1r2 2021-04-08 21:28:40.000000000 +0000 @@ -5,16 +5,16 @@ #sar 0: 0/1 0, 0, 0, 1, 518400, 0xc93c7c47 0, 1, 1, 1, 518400, 0xfb452a9c -0, 2, 2, 1, 518400, 0x2f7a35bd -0, 3, 3, 1, 518400, 0xe63e30b9 -0, 4, 4, 1, 518400, 0x39628205 -0, 5, 5, 1, 518400, 0x17fa1ea4 -0, 6, 6, 1, 518400, 0xd5ee83e2 -0, 7, 7, 1, 518400, 0x611ee98d -0, 8, 8, 1, 518400, 0x07c1eeb8 -0, 9, 9, 1, 518400, 0x9dff3418 -0, 10, 10, 1, 518400, 0x87cd2f56 -0, 11, 11, 1, 518400, 0x88675628 -0, 12, 12, 1, 518400, 0x9bb8c9a0 -0, 13, 13, 1, 518400, 0xe6c1df00 -0, 14, 14, 1, 518400, 0xfcaab7a7 +0, 3, 3, 1, 518400, 0x2f7a35bd +0, 4, 4, 1, 518400, 0xe63e30b9 +0, 5, 5, 1, 518400, 0x39628205 +0, 6, 6, 1, 518400, 0x17fa1ea4 +0, 7, 7, 1, 518400, 0xd5ee83e2 +0, 8, 8, 1, 518400, 0x611ee98d +0, 9, 9, 1, 518400, 0x07c1eeb8 +0, 10, 10, 1, 518400, 0x9dff3418 +0, 11, 11, 1, 518400, 0x87cd2f56 +0, 12, 12, 1, 518400, 0x88675628 +0, 13, 13, 1, 518400, 0x9bb8c9a0 +0, 14, 14, 1, 518400, 0xe6c1df00 +0, 15, 15, 1, 518400, 0xfcaab7a7 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-conformance-sharp_mp_paff_2r ffmpeg-4.4/tests/ref/fate/h264-conformance-sharp_mp_paff_2r --- ffmpeg-4.2.2/tests/ref/fate/h264-conformance-sharp_mp_paff_2r 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-conformance-sharp_mp_paff_2r 2021-04-08 21:28:40.000000000 +0000 @@ -5,16 +5,16 @@ #sar 0: 0/1 0, 0, 0, 1, 518400, 0xc93c7c47 0, 1, 1, 1, 518400, 0xfb452a9c -0, 2, 2, 1, 518400, 0x2f7a35bd -0, 3, 3, 1, 518400, 0xe63e30b9 -0, 4, 4, 1, 518400, 0x39628205 -0, 5, 5, 1, 518400, 0x17fa1ea4 -0, 6, 6, 1, 518400, 0xd5ee83e2 -0, 7, 7, 1, 518400, 0x4fd6d5c9 -0, 8, 8, 1, 518400, 0x8703c999 -0, 9, 9, 1, 518400, 0x1a87e2d3 -0, 10, 10, 1, 518400, 0xa27fc4d0 -0, 11, 11, 1, 518400, 0x6effab5d -0, 12, 12, 1, 518400, 0x51ea02c9 -0, 13, 13, 1, 518400, 0xbcf84c88 -0, 14, 14, 1, 518400, 0x1d41076b +0, 3, 3, 1, 518400, 0x2f7a35bd +0, 4, 4, 1, 518400, 0xe63e30b9 +0, 5, 5, 1, 518400, 0x39628205 +0, 6, 6, 1, 518400, 0x17fa1ea4 +0, 7, 7, 1, 518400, 0xd5ee83e2 +0, 8, 8, 1, 518400, 0x4fd6d5c9 +0, 9, 9, 1, 518400, 0x8703c999 +0, 10, 10, 1, 518400, 0x1a87e2d3 +0, 11, 11, 1, 518400, 0xa27fc4d0 +0, 12, 12, 1, 518400, 0x6effab5d +0, 13, 13, 1, 518400, 0x51ea02c9 +0, 14, 14, 1, 518400, 0xbcf84c88 +0, 15, 15, 1, 518400, 0x1d41076b diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264-encparams ffmpeg-4.4/tests/ref/fate/h264-encparams --- ffmpeg-4.2.2/tests/ref/fate/h264-encparams 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264-encparams 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,404 @@ +frame 0 +AVVideoEncParams 1 +qp 28 +delta_qp[1][0] 3 +delta_qp[1][1] 3 +delta_qp[2][0] -2 +delta_qp[2][1] -2 +nb_blocks 396 +block 0 0:0 16x16 0 +block 1 16:0 16x16 0 +block 2 32:0 16x16 0 +block 3 48:0 16x16 0 +block 4 64:0 16x16 0 +block 5 80:0 16x16 0 +block 6 96:0 16x16 0 +block 7 112:0 16x16 0 +block 8 128:0 16x16 0 +block 9 144:0 16x16 0 +block 10 160:0 16x16 0 +block 11 176:0 16x16 0 +block 12 192:0 16x16 0 +block 13 208:0 16x16 0 +block 14 224:0 16x16 0 +block 15 240:0 16x16 0 +block 16 256:0 16x16 0 +block 17 272:0 16x16 0 +block 18 288:0 16x16 0 +block 19 304:0 16x16 0 +block 20 320:0 16x16 0 +block 21 336:0 16x16 0 +block 22 0:16 16x16 0 +block 23 16:16 16x16 0 +block 24 32:16 16x16 0 +block 25 48:16 16x16 0 +block 26 64:16 16x16 0 +block 27 80:16 16x16 0 +block 28 96:16 16x16 0 +block 29 112:16 16x16 0 +block 30 128:16 16x16 0 +block 31 144:16 16x16 0 +block 32 160:16 16x16 0 +block 33 176:16 16x16 0 +block 34 192:16 16x16 0 +block 35 208:16 16x16 0 +block 36 224:16 16x16 0 +block 37 240:16 16x16 0 +block 38 256:16 16x16 0 +block 39 272:16 16x16 0 +block 40 288:16 16x16 0 +block 41 304:16 16x16 0 +block 42 320:16 16x16 0 +block 43 336:16 16x16 0 +block 44 0:32 16x16 0 +block 45 16:32 16x16 0 +block 46 32:32 16x16 0 +block 47 48:32 16x16 0 +block 48 64:32 16x16 0 +block 49 80:32 16x16 0 +block 50 96:32 16x16 0 +block 51 112:32 16x16 0 +block 52 128:32 16x16 0 +block 53 144:32 16x16 0 +block 54 160:32 16x16 0 +block 55 176:32 16x16 0 +block 56 192:32 16x16 0 +block 57 208:32 16x16 0 +block 58 224:32 16x16 0 +block 59 240:32 16x16 0 +block 60 256:32 16x16 0 +block 61 272:32 16x16 0 +block 62 288:32 16x16 0 +block 63 304:32 16x16 0 +block 64 320:32 16x16 0 +block 65 336:32 16x16 0 +block 66 0:48 16x16 0 +block 67 16:48 16x16 0 +block 68 32:48 16x16 0 +block 69 48:48 16x16 0 +block 70 64:48 16x16 0 +block 71 80:48 16x16 0 +block 72 96:48 16x16 0 +block 73 112:48 16x16 0 +block 74 128:48 16x16 0 +block 75 144:48 16x16 0 +block 76 160:48 16x16 0 +block 77 176:48 16x16 0 +block 78 192:48 16x16 0 +block 79 208:48 16x16 0 +block 80 224:48 16x16 0 +block 81 240:48 16x16 0 +block 82 256:48 16x16 0 +block 83 272:48 16x16 0 +block 84 288:48 16x16 0 +block 85 304:48 16x16 0 +block 86 320:48 16x16 0 +block 87 336:48 16x16 0 +block 88 0:64 16x16 0 +block 89 16:64 16x16 0 +block 90 32:64 16x16 0 +block 91 48:64 16x16 0 +block 92 64:64 16x16 0 +block 93 80:64 16x16 0 +block 94 96:64 16x16 0 +block 95 112:64 16x16 0 +block 96 128:64 16x16 0 +block 97 144:64 16x16 0 +block 98 160:64 16x16 0 +block 99 176:64 16x16 0 +block 100 192:64 16x16 0 +block 101 208:64 16x16 0 +block 102 224:64 16x16 0 +block 103 240:64 16x16 0 +block 104 256:64 16x16 0 +block 105 272:64 16x16 0 +block 106 288:64 16x16 0 +block 107 304:64 16x16 0 +block 108 320:64 16x16 0 +block 109 336:64 16x16 0 +block 110 0:80 16x16 0 +block 111 16:80 16x16 0 +block 112 32:80 16x16 0 +block 113 48:80 16x16 0 +block 114 64:80 16x16 0 +block 115 80:80 16x16 0 +block 116 96:80 16x16 0 +block 117 112:80 16x16 0 +block 118 128:80 16x16 0 +block 119 144:80 16x16 0 +block 120 160:80 16x16 0 +block 121 176:80 16x16 0 +block 122 192:80 16x16 0 +block 123 208:80 16x16 0 +block 124 224:80 16x16 0 +block 125 240:80 16x16 0 +block 126 256:80 16x16 0 +block 127 272:80 16x16 0 +block 128 288:80 16x16 0 +block 129 304:80 16x16 0 +block 130 320:80 16x16 0 +block 131 336:80 16x16 0 +block 132 0:96 16x16 0 +block 133 16:96 16x16 0 +block 134 32:96 16x16 0 +block 135 48:96 16x16 0 +block 136 64:96 16x16 0 +block 137 80:96 16x16 0 +block 138 96:96 16x16 0 +block 139 112:96 16x16 0 +block 140 128:96 16x16 0 +block 141 144:96 16x16 0 +block 142 160:96 16x16 0 +block 143 176:96 16x16 0 +block 144 192:96 16x16 0 +block 145 208:96 16x16 0 +block 146 224:96 16x16 0 +block 147 240:96 16x16 0 +block 148 256:96 16x16 0 +block 149 272:96 16x16 0 +block 150 288:96 16x16 0 +block 151 304:96 16x16 0 +block 152 320:96 16x16 0 +block 153 336:96 16x16 0 +block 154 0:112 16x16 0 +block 155 16:112 16x16 0 +block 156 32:112 16x16 0 +block 157 48:112 16x16 0 +block 158 64:112 16x16 0 +block 159 80:112 16x16 0 +block 160 96:112 16x16 0 +block 161 112:112 16x16 0 +block 162 128:112 16x16 0 +block 163 144:112 16x16 0 +block 164 160:112 16x16 0 +block 165 176:112 16x16 0 +block 166 192:112 16x16 0 +block 167 208:112 16x16 0 +block 168 224:112 16x16 0 +block 169 240:112 16x16 0 +block 170 256:112 16x16 0 +block 171 272:112 16x16 0 +block 172 288:112 16x16 0 +block 173 304:112 16x16 0 +block 174 320:112 16x16 0 +block 175 336:112 16x16 0 +block 176 0:128 16x16 0 +block 177 16:128 16x16 0 +block 178 32:128 16x16 0 +block 179 48:128 16x16 0 +block 180 64:128 16x16 0 +block 181 80:128 16x16 0 +block 182 96:128 16x16 0 +block 183 112:128 16x16 0 +block 184 128:128 16x16 0 +block 185 144:128 16x16 0 +block 186 160:128 16x16 0 +block 187 176:128 16x16 0 +block 188 192:128 16x16 0 +block 189 208:128 16x16 0 +block 190 224:128 16x16 0 +block 191 240:128 16x16 0 +block 192 256:128 16x16 0 +block 193 272:128 16x16 0 +block 194 288:128 16x16 0 +block 195 304:128 16x16 0 +block 196 320:128 16x16 0 +block 197 336:128 16x16 0 +block 198 0:144 16x16 0 +block 199 16:144 16x16 0 +block 200 32:144 16x16 0 +block 201 48:144 16x16 0 +block 202 64:144 16x16 0 +block 203 80:144 16x16 0 +block 204 96:144 16x16 0 +block 205 112:144 16x16 0 +block 206 128:144 16x16 0 +block 207 144:144 16x16 0 +block 208 160:144 16x16 0 +block 209 176:144 16x16 0 +block 210 192:144 16x16 0 +block 211 208:144 16x16 0 +block 212 224:144 16x16 0 +block 213 240:144 16x16 0 +block 214 256:144 16x16 0 +block 215 272:144 16x16 0 +block 216 288:144 16x16 0 +block 217 304:144 16x16 0 +block 218 320:144 16x16 0 +block 219 336:144 16x16 0 +block 220 0:160 16x16 0 +block 221 16:160 16x16 0 +block 222 32:160 16x16 0 +block 223 48:160 16x16 0 +block 224 64:160 16x16 0 +block 225 80:160 16x16 0 +block 226 96:160 16x16 0 +block 227 112:160 16x16 0 +block 228 128:160 16x16 0 +block 229 144:160 16x16 0 +block 230 160:160 16x16 0 +block 231 176:160 16x16 0 +block 232 192:160 16x16 0 +block 233 208:160 16x16 0 +block 234 224:160 16x16 0 +block 235 240:160 16x16 0 +block 236 256:160 16x16 0 +block 237 272:160 16x16 0 +block 238 288:160 16x16 0 +block 239 304:160 16x16 0 +block 240 320:160 16x16 0 +block 241 336:160 16x16 0 +block 242 0:176 16x16 0 +block 243 16:176 16x16 0 +block 244 32:176 16x16 0 +block 245 48:176 16x16 0 +block 246 64:176 16x16 0 +block 247 80:176 16x16 0 +block 248 96:176 16x16 0 +block 249 112:176 16x16 0 +block 250 128:176 16x16 0 +block 251 144:176 16x16 0 +block 252 160:176 16x16 0 +block 253 176:176 16x16 0 +block 254 192:176 16x16 0 +block 255 208:176 16x16 0 +block 256 224:176 16x16 0 +block 257 240:176 16x16 0 +block 258 256:176 16x16 0 +block 259 272:176 16x16 0 +block 260 288:176 16x16 0 +block 261 304:176 16x16 0 +block 262 320:176 16x16 0 +block 263 336:176 16x16 0 +block 264 0:192 16x16 0 +block 265 16:192 16x16 0 +block 266 32:192 16x16 0 +block 267 48:192 16x16 0 +block 268 64:192 16x16 0 +block 269 80:192 16x16 0 +block 270 96:192 16x16 0 +block 271 112:192 16x16 0 +block 272 128:192 16x16 0 +block 273 144:192 16x16 0 +block 274 160:192 16x16 0 +block 275 176:192 16x16 0 +block 276 192:192 16x16 0 +block 277 208:192 16x16 0 +block 278 224:192 16x16 0 +block 279 240:192 16x16 0 +block 280 256:192 16x16 0 +block 281 272:192 16x16 0 +block 282 288:192 16x16 0 +block 283 304:192 16x16 0 +block 284 320:192 16x16 0 +block 285 336:192 16x16 0 +block 286 0:208 16x16 0 +block 287 16:208 16x16 0 +block 288 32:208 16x16 0 +block 289 48:208 16x16 0 +block 290 64:208 16x16 0 +block 291 80:208 16x16 0 +block 292 96:208 16x16 0 +block 293 112:208 16x16 0 +block 294 128:208 16x16 0 +block 295 144:208 16x16 0 +block 296 160:208 16x16 0 +block 297 176:208 16x16 0 +block 298 192:208 16x16 0 +block 299 208:208 16x16 0 +block 300 224:208 16x16 0 +block 301 240:208 16x16 0 +block 302 256:208 16x16 0 +block 303 272:208 16x16 0 +block 304 288:208 16x16 0 +block 305 304:208 16x16 0 +block 306 320:208 16x16 0 +block 307 336:208 16x16 0 +block 308 0:224 16x16 0 +block 309 16:224 16x16 0 +block 310 32:224 16x16 0 +block 311 48:224 16x16 0 +block 312 64:224 16x16 0 +block 313 80:224 16x16 0 +block 314 96:224 16x16 0 +block 315 112:224 16x16 0 +block 316 128:224 16x16 0 +block 317 144:224 16x16 0 +block 318 160:224 16x16 0 +block 319 176:224 16x16 0 +block 320 192:224 16x16 0 +block 321 208:224 16x16 0 +block 322 224:224 16x16 0 +block 323 240:224 16x16 0 +block 324 256:224 16x16 0 +block 325 272:224 16x16 0 +block 326 288:224 16x16 0 +block 327 304:224 16x16 0 +block 328 320:224 16x16 0 +block 329 336:224 16x16 0 +block 330 0:240 16x16 0 +block 331 16:240 16x16 0 +block 332 32:240 16x16 0 +block 333 48:240 16x16 0 +block 334 64:240 16x16 0 +block 335 80:240 16x16 0 +block 336 96:240 16x16 0 +block 337 112:240 16x16 0 +block 338 128:240 16x16 0 +block 339 144:240 16x16 0 +block 340 160:240 16x16 0 +block 341 176:240 16x16 0 +block 342 192:240 16x16 0 +block 343 208:240 16x16 0 +block 344 224:240 16x16 0 +block 345 240:240 16x16 0 +block 346 256:240 16x16 0 +block 347 272:240 16x16 0 +block 348 288:240 16x16 0 +block 349 304:240 16x16 0 +block 350 320:240 16x16 0 +block 351 336:240 16x16 0 +block 352 0:256 16x16 0 +block 353 16:256 16x16 0 +block 354 32:256 16x16 0 +block 355 48:256 16x16 0 +block 356 64:256 16x16 0 +block 357 80:256 16x16 0 +block 358 96:256 16x16 0 +block 359 112:256 16x16 0 +block 360 128:256 16x16 0 +block 361 144:256 16x16 0 +block 362 160:256 16x16 0 +block 363 176:256 16x16 0 +block 364 192:256 16x16 0 +block 365 208:256 16x16 0 +block 366 224:256 16x16 0 +block 367 240:256 16x16 0 +block 368 256:256 16x16 0 +block 369 272:256 16x16 0 +block 370 288:256 16x16 0 +block 371 304:256 16x16 0 +block 372 320:256 16x16 0 +block 373 336:256 16x16 0 +block 374 0:272 16x16 0 +block 375 16:272 16x16 0 +block 376 32:272 16x16 0 +block 377 48:272 16x16 0 +block 378 64:272 16x16 0 +block 379 80:272 16x16 0 +block 380 96:272 16x16 0 +block 381 112:272 16x16 0 +block 382 128:272 16x16 0 +block 383 144:272 16x16 0 +block 384 160:272 16x16 0 +block 385 176:272 16x16 0 +block 386 192:272 16x16 0 +block 387 208:272 16x16 0 +block 388 224:272 16x16 0 +block 389 240:272 16x16 0 +block 390 256:272 16x16 0 +block 391 272:272 16x16 0 +block 392 288:272 16x16 0 +block 393 304:272 16x16 0 +block 394 320:272 16x16 0 +block 395 336:272 16x16 0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264_mp4toannexb_ticket2991 ffmpeg-4.4/tests/ref/fate/h264_mp4toannexb_ticket2991 --- ffmpeg-4.2.2/tests/ref/fate/h264_mp4toannexb_ticket2991 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264_mp4toannexb_ticket2991 2020-07-11 10:39:30.000000000 +0000 @@ -1,12 +1,12 @@ -dba672c154b41414cf26aae967c27eef *tests/data/fate/h264_mp4toannexb_ticket2991.h264 -1985823 tests/data/fate/h264_mp4toannexb_ticket2991.h264 -#extradata 0: 48, 0x47ae0d55 +05d66e60ab22ee004720e0051af0fe74 *tests/data/fate/h264_mp4toannexb_ticket2991.h264 +1985815 tests/data/fate/h264_mp4toannexb_ticket2991.h264 +#extradata 0: 47, 0x3a590d55 #tb 0: 1/1200000 #media_type 0: video #codec_id 0: h264 #dimensions 0: 1280x720 #sar 0: 3/4 -0, 0, 0, 48000, 37127, 0xc125184c +0, 0, 0, 48000, 37126, 0xb020184c 0, 48000, 48000, 40040, 6920, 0x8512361a, F=0x0 0, 88040, 88040, 40040, 7550, 0x1bc56ed4, F=0x0 0, 128081, 128081, 40040, 8752, 0xb8c6f0a1, F=0x0 @@ -21,7 +21,7 @@ 0, 488444, 488444, 40040, 11234, 0x83cbd9fd, F=0x0 0, 528485, 528485, 40040, 17616, 0xfdf95104, F=0x0 0, 568525, 568525, 40040, 10689, 0x9633d32b, F=0x0 -0, 608566, 608566, 40040, 45292, 0x66dd2cf6 +0, 608566, 608566, 40040, 45291, 0x543c2cf6 0, 648606, 648606, 40040, 20837, 0x051abfab, F=0x0 0, 688646, 688646, 40040, 21418, 0xe2a59d70, F=0x0 0, 728687, 728687, 40040, 15643, 0x15cf2cec, F=0x0 @@ -36,7 +36,7 @@ 0, 1089050, 1089050, 40040, 13130, 0xcbb6bb8e, F=0x0 0, 1129091, 1129091, 40040, 16180, 0x5d188a7a, F=0x0 0, 1169131, 1169131, 40040, 14961, 0x9ff2f463, F=0x0 -0, 1209172, 1209172, 40040, 54297, 0xf98d30ed +0, 1209172, 1209172, 40040, 54296, 0xe6ec30ed 0, 1249212, 1249212, 40040, 11500, 0x8c4852c9, F=0x0 0, 1289252, 1289252, 40040, 12065, 0xfb7954c3, F=0x0 0, 1329293, 1329293, 40040, 12532, 0xf0a935d3, F=0x0 @@ -51,7 +51,7 @@ 0, 1689656, 1689656, 40040, 13250, 0xfed0deb8, F=0x0 0, 1729697, 1729697, 40040, 13360, 0xbf92d476, F=0x0 0, 1769737, 1769737, 40040, 11749, 0x3041eaf1, F=0x0 -0, 1809778, 1809778, 40040, 23998, 0xee87d5c4 +0, 1809778, 1809778, 40040, 23997, 0xdbe6d5c4 0, 1849818, 1849818, 40040, 16065, 0xe8f715b7, F=0x0 0, 1889858, 1889858, 40040, 16441, 0x0a4e060f, F=0x0 0, 1929899, 1929899, 40040, 17395, 0xa8edecc2, F=0x0 @@ -66,7 +66,7 @@ 0, 2290262, 2290262, 40040, 13748, 0xed26aeb4, F=0x0 0, 2330303, 2330303, 40040, 15092, 0x3c983538, F=0x0 0, 2370343, 2370343, 40040, 14636, 0x9b278a6c, F=0x0 -0, 2410384, 2410384, 40040, 29135, 0x0a34be18 +0, 2410384, 2410384, 40040, 29134, 0xf784be18 0, 2450424, 2450424, 40040, 10232, 0x5408e15b, F=0x0 0, 2490464, 2490464, 40040, 9769, 0xc93cb7f9, F=0x0 0, 2530505, 2530505, 40040, 14454, 0x45230dbe, F=0x0 @@ -81,7 +81,7 @@ 0, 2890868, 2890868, 40040, 14801, 0x40bae016, F=0x0 0, 2930909, 2930909, 40040, 17303, 0x9ce1fd31, F=0x0 0, 2970949, 2970949, 40040, 17678, 0x9bd66141, F=0x0 -0, 3010990, 3010990, 40040, 48673, 0x44b6ce46 +0, 3010990, 3010990, 40040, 48672, 0x3215ce46 0, 3051030, 3051030, 40040, 11894, 0x12e1fece, F=0x0 0, 3091070, 3091070, 40040, 16514, 0xc57aed05, F=0x0 0, 3131111, 3131111, 40040, 13044, 0x61914fa0, F=0x0 @@ -96,7 +96,7 @@ 0, 3491474, 3491474, 40040, 12208, 0x81a587c0, F=0x0 0, 3531515, 3531515, 40040, 14709, 0x5dffbe04, F=0x0 0, 3571555, 3571555, 40040, 14390, 0xbfd1e041, F=0x0 -0, 3611596, 3611596, 40040, 37237, 0xfa9a24b1 +0, 3611596, 3611596, 40040, 37236, 0xe7f924b1 0, 3651636, 3651636, 40040, 14056, 0x24714c7c, F=0x0 0, 3691676, 3691676, 40040, 19438, 0x0c50dcd5, F=0x0 0, 3731717, 3731717, 40040, 21728, 0x7eea4a11, F=0x0 @@ -111,7 +111,7 @@ 0, 4092080, 4092080, 40040, 16878, 0x98efbae2, F=0x0 0, 4132121, 4132121, 40040, 14685, 0x1bf78d65, F=0x0 0, 4172161, 4172161, 40040, 13127, 0x0b91881d, F=0x0 -0, 4212202, 4212202, 40040, 29391, 0x0955ed6b +0, 4212202, 4212202, 40040, 29390, 0xf6a5ed6b 0, 4252242, 4252242, 40040, 12576, 0xe9845ded, F=0x0 0, 4292282, 4292282, 40040, 12599, 0x96a79ab8, F=0x0 0, 4332323, 4332323, 40040, 16134, 0xb4c36d3f, F=0x0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264_mp4toannexb_ticket5927 ffmpeg-4.4/tests/ref/fate/h264_mp4toannexb_ticket5927 --- ffmpeg-4.2.2/tests/ref/fate/h264_mp4toannexb_ticket5927 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264_mp4toannexb_ticket5927 2020-07-11 10:39:30.000000000 +0000 @@ -1,12 +1,12 @@ -562487bfea635cdadbc23d390322b589 *tests/data/fate/h264_mp4toannexb_ticket5927.h264 -595585 tests/data/fate/h264_mp4toannexb_ticket5927.h264 -#extradata 0: 34, 0x8df608f8 +a3b02fd09392e01619cebc959d4d9ff2 *tests/data/fate/h264_mp4toannexb_ticket5927.h264 +595583 tests/data/fate/h264_mp4toannexb_ticket5927.h264 +#extradata 0: 33, 0x84fe08f8 #tb 0: 1/1200000 #media_type 0: video #codec_id 0: h264 #dimensions 0: 1920x1080 #sar 0: 0/1 -0, -48000, -9223372036854775808, 48000, 247994, 0x2e1e21ea +0, -48000, -9223372036854775808, 48000, 247993, 0x1ce821ea 0, 0, -9223372036854775808, 48000, 43354, 0xa05dca6f, F=0x0 0, 48000, -9223372036854775808, 48000, 11423, 0x5e8086dd, F=0x0 0, 96000, -9223372036854775808, 48000, 50798, 0x145fbe4f, F=0x0 @@ -18,4 +18,4 @@ 0, 384000, -9223372036854775808, 48000, 54483, 0xefead99f, F=0x0 0, 432000, -9223372036854775808, 48000, 13705, 0x23cd27e8, F=0x0 0, 480000, -9223372036854775808, 48000, 22308, 0x4093b5af, F=0x0 -0, 528000, -9223372036854775808, 48000, 6370, 0x96c12aa1 +0, 528000, -9223372036854775808, 48000, 6369, 0x858b2aa1 diff -Nru ffmpeg-4.2.2/tests/ref/fate/h264_mp4toannexb_ticket5927_2 ffmpeg-4.4/tests/ref/fate/h264_mp4toannexb_ticket5927_2 --- ffmpeg-4.2.2/tests/ref/fate/h264_mp4toannexb_ticket5927_2 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/h264_mp4toannexb_ticket5927_2 2020-07-11 10:39:30.000000000 +0000 @@ -1,12 +1,12 @@ -562487bfea635cdadbc23d390322b589 *tests/data/fate/h264_mp4toannexb_ticket5927_2.h264 -595585 tests/data/fate/h264_mp4toannexb_ticket5927_2.h264 -#extradata 0: 34, 0x8df608f8 +a3b02fd09392e01619cebc959d4d9ff2 *tests/data/fate/h264_mp4toannexb_ticket5927_2.h264 +595583 tests/data/fate/h264_mp4toannexb_ticket5927_2.h264 +#extradata 0: 33, 0x84fe08f8 #tb 0: 1/1200000 #media_type 0: video #codec_id 0: h264 #dimensions 0: 1920x1080 #sar 0: 0/1 -0, -48000, -9223372036854775808, 48000, 247994, 0x2e1e21ea +0, -48000, -9223372036854775808, 48000, 247993, 0x1ce821ea 0, 0, -9223372036854775808, 48000, 43354, 0xa05dca6f, F=0x0 0, 48000, -9223372036854775808, 48000, 11423, 0x5e8086dd, F=0x0 0, 96000, -9223372036854775808, 48000, 50798, 0x145fbe4f, F=0x0 @@ -18,4 +18,4 @@ 0, 384000, -9223372036854775808, 48000, 54483, 0xefead99f, F=0x0 0, 432000, -9223372036854775808, 48000, 13705, 0x23cd27e8, F=0x0 0, 480000, -9223372036854775808, 48000, 22308, 0x4093b5af, F=0x0 -0, 528000, -9223372036854775808, 48000, 6370, 0x96c12aa1 +0, 528000, -9223372036854775808, 48000, 6369, 0x858b2aa1 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov ffmpeg-4.4/tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov --- ffmpeg-4.2.2/tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov 2021-04-08 21:28:40.000000000 +0000 @@ -7,8 +7,6 @@ dts_time=0.000000 duration=512 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=4612 pos=36 flags=K_ @@ -19,13 +17,13 @@ codec_name=hap profile=unknown codec_type=video -codec_time_base=1/25 codec_tag_string=HapA codec_tag=0x41706148 width=127 height=71 coded_width=128 coded_height=72 +closed_captions=0 has_b_frames=0 sample_aspect_ratio=1:1 display_aspect_ratio=127:71 @@ -37,7 +35,6 @@ color_primaries=unknown chroma_location=unspecified field_order=unknown -timecode=N/A refs=1 id=N/A r_frame_rate=25/1 @@ -68,5 +65,6 @@ DISPOSITION:timed_thumbnails=0 TAG:language=eng TAG:handler_name=Module de gestion video +TAG:vendor_id=FFMP TAG:encoder=HAPAlpha Only [/STREAM] diff -Nru ffmpeg-4.2.2/tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov ffmpeg-4.4/tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov --- ffmpeg-4.2.2/tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov 2021-04-08 21:28:40.000000000 +0000 @@ -7,8 +7,6 @@ dts_time=0.000000 duration=512 duration_time=0.040000 -convergence_duration=N/A -convergence_duration_time=N/A size=9220 pos=36 flags=K_ @@ -19,13 +17,13 @@ codec_name=hap profile=unknown codec_type=video -codec_time_base=1/25 codec_tag_string=HapY codec_tag=0x59706148 width=127 height=71 coded_width=128 coded_height=72 +closed_captions=0 has_b_frames=0 sample_aspect_ratio=1:1 display_aspect_ratio=127:71 @@ -37,7 +35,6 @@ color_primaries=unknown chroma_location=unspecified field_order=unknown -timecode=N/A refs=1 id=N/A r_frame_rate=25/1 @@ -68,5 +65,6 @@ DISPOSITION:timed_thumbnails=0 TAG:language=eng TAG:handler_name=Module de gestion video +TAG:vendor_id=FFMP TAG:encoder=HAPQ [/STREAM] diff -Nru ffmpeg-4.2.2/tests/ref/fate/hapqa-extract-snappy16-to-hapalphaonly ffmpeg-4.4/tests/ref/fate/hapqa-extract-snappy16-to-hapalphaonly --- ffmpeg-4.2.2/tests/ref/fate/hapqa-extract-snappy16-to-hapalphaonly 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hapqa-extract-snappy16-to-hapalphaonly 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: hap #dimensions 0: 127x71 #sar 0: 1/1 -0, 0, 0, 1, 3513, 0x69c7014f +0, 0, 0, 1, 3513, 0x69c7014f, F=0x11 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hapqa-extract-snappy16-to-hapq ffmpeg-4.4/tests/ref/fate/hapqa-extract-snappy16-to-hapq --- ffmpeg-4.2.2/tests/ref/fate/hapqa-extract-snappy16-to-hapq 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hapqa-extract-snappy16-to-hapq 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: hap #dimensions 0: 127x71 #sar 0: 1/1 -0, 0, 0, 1, 8726, 0xf889691c +0, 0, 0, 1, 8726, 0xf889691c, F=0x11 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hapqa-extract-snappy1-to-hapalphaonly ffmpeg-4.4/tests/ref/fate/hapqa-extract-snappy1-to-hapalphaonly --- ffmpeg-4.2.2/tests/ref/fate/hapqa-extract-snappy1-to-hapalphaonly 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hapqa-extract-snappy1-to-hapalphaonly 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: hap #dimensions 0: 127x71 #sar 0: 1/1 -0, 0, 0, 1, 3044, 0xcaf6ddd0 +0, 0, 0, 1, 3044, 0xcaf6ddd0, F=0x11 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hapqa-extract-snappy1-to-hapq ffmpeg-4.4/tests/ref/fate/hapqa-extract-snappy1-to-hapq --- ffmpeg-4.2.2/tests/ref/fate/hapqa-extract-snappy1-to-hapq 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hapqa-extract-snappy1-to-hapq 2020-07-11 10:39:30.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: hap #dimensions 0: 127x71 #sar 0: 1/1 -0, 0, 0, 1, 8217, 0x04271f0f +0, 0, 0, 1, 8217, 0x04271f0f, F=0x11 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-cabac-tudepth ffmpeg-4.4/tests/ref/fate/hevc-cabac-tudepth --- ffmpeg-4.2.2/tests/ref/fate/hevc-cabac-tudepth 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-cabac-tudepth 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 64x64 +#sar 0: 0/1 +0, 0, 0, 1, 12288, 0x0127a0d9 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-BUMPING_A_ericsson_1 ffmpeg-4.4/tests/ref/fate/hevc-conformance-BUMPING_A_ericsson_1 --- ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-BUMPING_A_ericsson_1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-conformance-BUMPING_A_ericsson_1 2021-04-08 21:28:40.000000000 +0000 @@ -7,48 +7,48 @@ 0, 1, 1, 1, 149760, 0x73610669 0, 2, 2, 1, 149760, 0xc01620f4 0, 3, 3, 1, 149760, 0x847a4297 -0, 4, 4, 1, 149760, 0x8b2db700 -0, 5, 5, 1, 149760, 0x17b1d77c -0, 6, 6, 1, 149760, 0xc31ee8a5 -0, 7, 7, 1, 149760, 0x19541295 -0, 8, 8, 1, 149760, 0xd050be45 -0, 9, 9, 1, 149760, 0x45cf8e84 -0, 10, 10, 1, 149760, 0x0dd3e4d4 -0, 11, 11, 1, 149760, 0xc8347a7c -0, 12, 12, 1, 149760, 0x24089674 -0, 13, 13, 1, 149760, 0xdf2c44e4 -0, 14, 14, 1, 149760, 0x83f5100b -0, 15, 15, 1, 149760, 0x9a060faf -0, 16, 16, 1, 149760, 0x4cdc6101 -0, 17, 17, 1, 149760, 0xe492ad68 -0, 18, 18, 1, 149760, 0x35b73887 -0, 19, 19, 1, 149760, 0x259f898a -0, 20, 20, 1, 149760, 0x21df021b -0, 21, 21, 1, 149760, 0xdddc1cfe -0, 22, 22, 1, 149760, 0x53841bf5 -0, 23, 23, 1, 149760, 0x16745d74 -0, 24, 24, 1, 149760, 0x66e79e6a -0, 25, 25, 1, 149760, 0x35f04b5a -0, 26, 26, 1, 149760, 0x1472eee7 -0, 27, 27, 1, 149760, 0x42d0147c -0, 28, 28, 1, 149760, 0x57c9bdc2 -0, 29, 29, 1, 149760, 0x20ad4cc7 -0, 30, 30, 1, 149760, 0x1617ef6c -0, 31, 31, 1, 149760, 0xccdf4da2 -0, 32, 32, 1, 149760, 0xc173b762 -0, 33, 33, 1, 149760, 0xe7390c69 -0, 34, 34, 1, 149760, 0xfd0c97d3 -0, 35, 35, 1, 149760, 0xaeb2d61f -0, 36, 36, 1, 149760, 0xe7b114d2 -0, 37, 37, 1, 149760, 0x1b771de4 -0, 38, 38, 1, 149760, 0xd3e03840 -0, 39, 39, 1, 149760, 0x702ef44b -0, 40, 40, 1, 149760, 0xe96f848b -0, 41, 41, 1, 149760, 0xa0ae24d9 -0, 42, 42, 1, 149760, 0x1b9efdfb -0, 43, 43, 1, 149760, 0xceac9bc7 -0, 44, 44, 1, 149760, 0x73078700 -0, 45, 45, 1, 149760, 0xa736637e -0, 46, 46, 1, 149760, 0xbd353c9d -0, 47, 47, 1, 149760, 0x750a23ba -0, 48, 48, 1, 149760, 0x4144c56e +0, 8, 8, 1, 149760, 0x8b2db700 +0, 9, 9, 1, 149760, 0x17b1d77c +0, 10, 10, 1, 149760, 0xc31ee8a5 +0, 11, 11, 1, 149760, 0x19541295 +0, 12, 12, 1, 149760, 0xd050be45 +0, 13, 13, 1, 149760, 0x45cf8e84 +0, 14, 14, 1, 149760, 0x0dd3e4d4 +0, 16, 16, 1, 149760, 0xc8347a7c +0, 17, 17, 1, 149760, 0x24089674 +0, 18, 18, 1, 149760, 0xdf2c44e4 +0, 19, 19, 1, 149760, 0x83f5100b +0, 20, 20, 1, 149760, 0x9a060faf +0, 24, 24, 1, 149760, 0x4cdc6101 +0, 25, 25, 1, 149760, 0xe492ad68 +0, 26, 26, 1, 149760, 0x35b73887 +0, 27, 27, 1, 149760, 0x259f898a +0, 28, 28, 1, 149760, 0x21df021b +0, 29, 29, 1, 149760, 0xdddc1cfe +0, 32, 32, 1, 149760, 0x53841bf5 +0, 33, 33, 1, 149760, 0x16745d74 +0, 34, 34, 1, 149760, 0x66e79e6a +0, 35, 35, 1, 149760, 0x35f04b5a +0, 40, 40, 1, 149760, 0x1472eee7 +0, 41, 41, 1, 149760, 0x42d0147c +0, 42, 42, 1, 149760, 0x57c9bdc2 +0, 43, 43, 1, 149760, 0x20ad4cc7 +0, 44, 44, 1, 149760, 0x1617ef6c +0, 45, 45, 1, 149760, 0xccdf4da2 +0, 46, 46, 1, 149760, 0xc173b762 +0, 47, 47, 1, 149760, 0xe7390c69 +0, 48, 48, 1, 149760, 0xfd0c97d3 +0, 49, 49, 1, 149760, 0xaeb2d61f +0, 50, 50, 1, 149760, 0xe7b114d2 +0, 51, 51, 1, 149760, 0x1b771de4 +0, 52, 52, 1, 149760, 0xd3e03840 +0, 53, 53, 1, 149760, 0x702ef44b +0, 57, 57, 1, 149760, 0xe96f848b +0, 58, 58, 1, 149760, 0xa0ae24d9 +0, 59, 59, 1, 149760, 0x1b9efdfb +0, 60, 60, 1, 149760, 0xceac9bc7 +0, 61, 61, 1, 149760, 0x73078700 +0, 62, 62, 1, 149760, 0xa736637e +0, 63, 63, 1, 149760, 0xbd353c9d +0, 64, 64, 1, 149760, 0x750a23ba +0, 65, 65, 1, 149760, 0x4144c56e diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-CIP_A_Panasonic_3 ffmpeg-4.4/tests/ref/fate/hevc-conformance-CIP_A_Panasonic_3 --- ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-CIP_A_Panasonic_3 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-conformance-CIP_A_Panasonic_3 2021-04-08 21:28:40.000000000 +0000 @@ -3,5 +3,5 @@ #codec_id 0: rawvideo #dimensions 0: 416x240 #sar 0: 0/1 -0, 0, 0, 1, 149760, 0x6e1f16d0 -0, 1, 1, 1, 149760, 0x5be5bde9 +0, 2, 2, 1, 149760, 0x6e1f16d0 +0, 3, 3, 1, 149760, 0x5be5bde9 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-CIP_C_Panasonic_2 ffmpeg-4.4/tests/ref/fate/hevc-conformance-CIP_C_Panasonic_2 --- ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-CIP_C_Panasonic_2 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-conformance-CIP_C_Panasonic_2 2021-04-08 21:28:40.000000000 +0000 @@ -3,5 +3,5 @@ #codec_id 0: rawvideo #dimensions 0: 416x240 #sar 0: 0/1 -0, 0, 0, 1, 149760, 0xcd1019b2 -0, 1, 1, 1, 149760, 0xeb39efeb +0, 2, 2, 1, 149760, 0xcd1019b2 +0, 3, 3, 1, 149760, 0xeb39efeb diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4 ffmpeg-4.4/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4 --- ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4 2021-04-08 21:28:40.000000000 +0000 @@ -98,4 +98,4 @@ 0, 92, 92, 1, 3133440, 0x761571be 0, 93, 93, 1, 3133440, 0x34dc14a1 0, 94, 94, 1, 3133440, 0xbb94c2d4 -0, 95, 95, 1, 3133440, 0x5300e459 +0, 96, 96, 1, 3133440, 0x5300e459 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 ffmpeg-4.4/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 --- ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 2021-04-08 21:28:40.000000000 +0000 @@ -25,21 +25,21 @@ 0, 19, 19, 1, 599040, 0x4227009b 0, 20, 20, 1, 599040, 0x1bda8be4 0, 21, 21, 1, 599040, 0xd1d5dcb4 -0, 22, 22, 1, 599040, 0x00a0249f -0, 23, 23, 1, 599040, 0x7263f7cf -0, 24, 24, 1, 599040, 0x47054be4 -0, 25, 25, 1, 599040, 0xda083f52 -0, 26, 26, 1, 599040, 0xf2906ab1 -0, 27, 27, 1, 599040, 0x20936797 -0, 28, 28, 1, 599040, 0x644d7c3e -0, 29, 29, 1, 599040, 0x7c00e8bf -0, 30, 30, 1, 599040, 0x041f8a48 -0, 31, 31, 1, 599040, 0xcef6e936 -0, 32, 32, 1, 599040, 0x361461e9 -0, 33, 33, 1, 599040, 0xf663ba0a -0, 34, 34, 1, 599040, 0x4d3371d3 -0, 35, 35, 1, 599040, 0xed6b5c92 -0, 36, 36, 1, 599040, 0xdec67f6e -0, 37, 37, 1, 599040, 0xbafa50c0 -0, 38, 38, 1, 599040, 0xc9181637 -0, 39, 39, 1, 599040, 0x95834e17 +0, 32, 32, 1, 599040, 0x00a0249f +0, 33, 33, 1, 599040, 0x7263f7cf +0, 34, 34, 1, 599040, 0x47054be4 +0, 35, 35, 1, 599040, 0xda083f52 +0, 36, 36, 1, 599040, 0xf2906ab1 +0, 37, 37, 1, 599040, 0x20936797 +0, 38, 38, 1, 599040, 0x644d7c3e +0, 39, 39, 1, 599040, 0x7c00e8bf +0, 40, 40, 1, 599040, 0x041f8a48 +0, 41, 41, 1, 599040, 0xcef6e936 +0, 42, 42, 1, 599040, 0x361461e9 +0, 43, 43, 1, 599040, 0xf663ba0a +0, 44, 44, 1, 599040, 0x4d3371d3 +0, 45, 45, 1, 599040, 0xed6b5c92 +0, 46, 46, 1, 599040, 0xdec67f6e +0, 47, 47, 1, 599040, 0xbafa50c0 +0, 48, 48, 1, 599040, 0xc9181637 +0, 49, 49, 1, 599040, 0x95834e17 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1 ffmpeg-4.4/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1 --- ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1 2021-04-08 21:28:40.000000000 +0000 @@ -25,28 +25,28 @@ 0, 19, 19, 1, 599040, 0x4227009b 0, 20, 20, 1, 599040, 0x1bda8be4 0, 21, 21, 1, 599040, 0xd1d5dcb4 -0, 22, 22, 1, 599040, 0x00d87745 -0, 23, 23, 1, 599040, 0x9b689b16 -0, 24, 24, 1, 599040, 0x40ae530a -0, 25, 25, 1, 599040, 0x8284f649 -0, 26, 26, 1, 599040, 0x37423ae4 -0, 27, 27, 1, 599040, 0xb3f72b02 -0, 28, 28, 1, 599040, 0xc0cc5860 -0, 29, 29, 1, 599040, 0x00a0249f -0, 30, 30, 1, 599040, 0x7263f7cf -0, 31, 31, 1, 599040, 0x47054be4 -0, 32, 32, 1, 599040, 0xda083f52 -0, 33, 33, 1, 599040, 0xf2906ab1 -0, 34, 34, 1, 599040, 0x20936797 -0, 35, 35, 1, 599040, 0x644d7c3e -0, 36, 36, 1, 599040, 0x7c00e8bf -0, 37, 37, 1, 599040, 0x041f8a48 -0, 38, 38, 1, 599040, 0xcef6e936 -0, 39, 39, 1, 599040, 0x361461e9 -0, 40, 40, 1, 599040, 0xf663ba0a -0, 41, 41, 1, 599040, 0x4d3371d3 -0, 42, 42, 1, 599040, 0xed6b5c92 -0, 43, 43, 1, 599040, 0xdec67f6e -0, 44, 44, 1, 599040, 0xbafa50c0 -0, 45, 45, 1, 599040, 0xc9181637 -0, 46, 46, 1, 599040, 0x95834e17 +0, 25, 25, 1, 599040, 0x00d87745 +0, 26, 26, 1, 599040, 0x9b689b16 +0, 27, 27, 1, 599040, 0x40ae530a +0, 28, 28, 1, 599040, 0x8284f649 +0, 29, 29, 1, 599040, 0x37423ae4 +0, 30, 30, 1, 599040, 0xb3f72b02 +0, 31, 31, 1, 599040, 0xc0cc5860 +0, 32, 32, 1, 599040, 0x00a0249f +0, 33, 33, 1, 599040, 0x7263f7cf +0, 34, 34, 1, 599040, 0x47054be4 +0, 35, 35, 1, 599040, 0xda083f52 +0, 36, 36, 1, 599040, 0xf2906ab1 +0, 37, 37, 1, 599040, 0x20936797 +0, 38, 38, 1, 599040, 0x644d7c3e +0, 39, 39, 1, 599040, 0x7c00e8bf +0, 40, 40, 1, 599040, 0x041f8a48 +0, 41, 41, 1, 599040, 0xcef6e936 +0, 42, 42, 1, 599040, 0x361461e9 +0, 43, 43, 1, 599040, 0xf663ba0a +0, 44, 44, 1, 599040, 0x4d3371d3 +0, 45, 45, 1, 599040, 0xed6b5c92 +0, 46, 46, 1, 599040, 0xdec67f6e +0, 47, 47, 1, 599040, 0xbafa50c0 +0, 48, 48, 1, 599040, 0xc9181637 +0, 49, 49, 1, 599040, 0x95834e17 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-NUT_A_ericsson_5 ffmpeg-4.4/tests/ref/fate/hevc-conformance-NUT_A_ericsson_5 --- ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-NUT_A_ericsson_5 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-conformance-NUT_A_ericsson_5 2021-04-08 21:28:40.000000000 +0000 @@ -25,15 +25,15 @@ 0, 19, 19, 1, 149760, 0x0580f2be 0, 20, 20, 1, 149760, 0x8e4cea96 0, 21, 21, 1, 149760, 0x6c98d019 -0, 22, 22, 1, 149760, 0x842803c8 -0, 23, 23, 1, 149760, 0xddc196ee -0, 24, 24, 1, 149760, 0x89e45523 -0, 25, 25, 1, 149760, 0x2a36b008 -0, 26, 26, 1, 149760, 0x14a319f7 -0, 27, 27, 1, 149760, 0x7394854c -0, 28, 28, 1, 149760, 0x26dcf933 -0, 29, 29, 1, 149760, 0x5b000b7e -0, 30, 30, 1, 149760, 0x6e76bded -0, 31, 31, 1, 149760, 0x0284d92d -0, 32, 32, 1, 149760, 0xf14a25e0 -0, 33, 33, 1, 149760, 0x10c03d98 +0, 24, 24, 1, 149760, 0x842803c8 +0, 25, 25, 1, 149760, 0xddc196ee +0, 26, 26, 1, 149760, 0x89e45523 +0, 27, 27, 1, 149760, 0x2a36b008 +0, 28, 28, 1, 149760, 0x14a319f7 +0, 29, 29, 1, 149760, 0x7394854c +0, 30, 30, 1, 149760, 0x26dcf933 +0, 31, 31, 1, 149760, 0x5b000b7e +0, 32, 32, 1, 149760, 0x6e76bded +0, 33, 33, 1, 149760, 0x0284d92d +0, 34, 34, 1, 149760, 0xf14a25e0 +0, 35, 35, 1, 149760, 0x10c03d98 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1 ffmpeg-4.4/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1 --- ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1 2021-04-08 21:28:40.000000000 +0000 @@ -42,62 +42,62 @@ 0, 36, 36, 1, 599040, 0xd2152e6b 0, 37, 37, 1, 599040, 0xe4c37cc7 0, 38, 38, 1, 599040, 0xec3393c3 -0, 39, 39, 1, 599040, 0x1fe16574 -0, 40, 40, 1, 599040, 0xa3a8c14d -0, 41, 41, 1, 599040, 0x32eb90aa -0, 42, 42, 1, 599040, 0xebca8310 -0, 43, 43, 1, 599040, 0x7888627f -0, 44, 44, 1, 599040, 0xe048335c -0, 45, 45, 1, 599040, 0xe2262b9c -0, 46, 46, 1, 599040, 0xb8c2b115 -0, 47, 47, 1, 599040, 0x2ff4194b -0, 48, 48, 1, 599040, 0x3a9b5520 -0, 49, 49, 1, 599040, 0xbd8c0486 -0, 50, 50, 1, 599040, 0xc8b8f29e -0, 51, 51, 1, 599040, 0xbc12f62c -0, 52, 52, 1, 599040, 0x04bb6438 -0, 53, 53, 1, 599040, 0x07971646 -0, 54, 54, 1, 599040, 0x0193dabe -0, 55, 55, 1, 599040, 0x20f41d9e -0, 56, 56, 1, 599040, 0x04b40718 -0, 57, 57, 1, 599040, 0x75d2c51c -0, 58, 58, 1, 599040, 0x9b8c2c50 -0, 59, 59, 1, 599040, 0x970e39ea -0, 60, 60, 1, 599040, 0x7c4264aa -0, 61, 61, 1, 599040, 0xe939a6fd -0, 62, 62, 1, 599040, 0xc8b95f8d -0, 63, 63, 1, 599040, 0x9e2f384a -0, 64, 64, 1, 599040, 0x7dc74724 -0, 65, 65, 1, 599040, 0x7e93bc5f -0, 66, 66, 1, 599040, 0x99b2c09d -0, 67, 67, 1, 599040, 0x284e436f -0, 68, 68, 1, 599040, 0xaa303eee -0, 69, 69, 1, 599040, 0x65e54342 -0, 70, 70, 1, 599040, 0x2fe183cd -0, 71, 71, 1, 599040, 0x5953c191 -0, 72, 72, 1, 599040, 0x0fc9a701 -0, 73, 73, 1, 599040, 0x0eea5327 -0, 74, 74, 1, 599040, 0x118752f1 -0, 75, 75, 1, 599040, 0x778c7711 -0, 76, 76, 1, 599040, 0x6f3ad6a5 -0, 77, 77, 1, 599040, 0xf70fcd3d -0, 78, 78, 1, 599040, 0x85a366cb -0, 79, 79, 1, 599040, 0xdda47432 -0, 80, 80, 1, 599040, 0x86379004 -0, 81, 81, 1, 599040, 0xfc539512 -0, 82, 82, 1, 599040, 0x04e70786 -0, 83, 83, 1, 599040, 0x7dddc8f7 -0, 84, 84, 1, 599040, 0xa76a3b6e -0, 85, 85, 1, 599040, 0x44183060 -0, 86, 86, 1, 599040, 0x6f691c5a -0, 87, 87, 1, 599040, 0x39d25e12 -0, 88, 88, 1, 599040, 0xfe3aad0d -0, 89, 89, 1, 599040, 0x57f76928 -0, 90, 90, 1, 599040, 0x4e68eed5 -0, 91, 91, 1, 599040, 0x3a589d50 -0, 92, 92, 1, 599040, 0x92ec69b8 -0, 93, 93, 1, 599040, 0x9f78926e -0, 94, 94, 1, 599040, 0xa1ca1b1d -0, 95, 95, 1, 599040, 0x140240eb -0, 96, 96, 1, 599040, 0x61fa01af -0, 97, 97, 1, 599040, 0x79f9e3ae +0, 40, 40, 1, 599040, 0x1fe16574 +0, 41, 41, 1, 599040, 0xa3a8c14d +0, 42, 42, 1, 599040, 0x32eb90aa +0, 43, 43, 1, 599040, 0xebca8310 +0, 44, 44, 1, 599040, 0x7888627f +0, 45, 45, 1, 599040, 0xe048335c +0, 46, 46, 1, 599040, 0xe2262b9c +0, 47, 47, 1, 599040, 0xb8c2b115 +0, 48, 48, 1, 599040, 0x2ff4194b +0, 49, 49, 1, 599040, 0x3a9b5520 +0, 50, 50, 1, 599040, 0xbd8c0486 +0, 51, 51, 1, 599040, 0xc8b8f29e +0, 52, 52, 1, 599040, 0xbc12f62c +0, 53, 53, 1, 599040, 0x04bb6438 +0, 54, 54, 1, 599040, 0x07971646 +0, 55, 55, 1, 599040, 0x0193dabe +0, 56, 56, 1, 599040, 0x20f41d9e +0, 57, 57, 1, 599040, 0x04b40718 +0, 58, 58, 1, 599040, 0x75d2c51c +0, 59, 59, 1, 599040, 0x9b8c2c50 +0, 60, 60, 1, 599040, 0x970e39ea +0, 61, 61, 1, 599040, 0x7c4264aa +0, 62, 62, 1, 599040, 0xe939a6fd +0, 63, 63, 1, 599040, 0xc8b95f8d +0, 64, 64, 1, 599040, 0x9e2f384a +0, 65, 65, 1, 599040, 0x7dc74724 +0, 66, 66, 1, 599040, 0x7e93bc5f +0, 67, 67, 1, 599040, 0x99b2c09d +0, 68, 68, 1, 599040, 0x284e436f +0, 69, 69, 1, 599040, 0xaa303eee +0, 70, 70, 1, 599040, 0x65e54342 +0, 71, 71, 1, 599040, 0x2fe183cd +0, 72, 72, 1, 599040, 0x5953c191 +0, 74, 74, 1, 599040, 0x0fc9a701 +0, 75, 75, 1, 599040, 0x0eea5327 +0, 76, 76, 1, 599040, 0x118752f1 +0, 77, 77, 1, 599040, 0x778c7711 +0, 78, 78, 1, 599040, 0x6f3ad6a5 +0, 79, 79, 1, 599040, 0xf70fcd3d +0, 80, 80, 1, 599040, 0x85a366cb +0, 81, 81, 1, 599040, 0xdda47432 +0, 82, 82, 1, 599040, 0x86379004 +0, 83, 83, 1, 599040, 0xfc539512 +0, 84, 84, 1, 599040, 0x04e70786 +0, 85, 85, 1, 599040, 0x7dddc8f7 +0, 86, 86, 1, 599040, 0xa76a3b6e +0, 87, 87, 1, 599040, 0x44183060 +0, 88, 88, 1, 599040, 0x6f691c5a +0, 89, 89, 1, 599040, 0x39d25e12 +0, 90, 90, 1, 599040, 0xfe3aad0d +0, 91, 91, 1, 599040, 0x57f76928 +0, 92, 92, 1, 599040, 0x4e68eed5 +0, 93, 93, 1, 599040, 0x3a589d50 +0, 94, 94, 1, 599040, 0x92ec69b8 +0, 95, 95, 1, 599040, 0x9f78926e +0, 96, 96, 1, 599040, 0xa1ca1b1d +0, 97, 97, 1, 599040, 0x140240eb +0, 98, 98, 1, 599040, 0x61fa01af +0, 99, 99, 1, 599040, 0x79f9e3ae diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1 ffmpeg-4.4/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1 --- ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1 2021-04-08 21:28:40.000000000 +0000 @@ -18,84 +18,84 @@ 0, 12, 12, 1, 599040, 0x1991f1f9 0, 13, 13, 1, 599040, 0x36e54ba2 0, 14, 14, 1, 599040, 0x698ce0c6 -0, 15, 15, 1, 599040, 0xc6dd131e -0, 16, 16, 1, 599040, 0x0a22f4c5 -0, 17, 17, 1, 599040, 0xd6a0c196 -0, 18, 18, 1, 599040, 0x699a3e69 -0, 19, 19, 1, 599040, 0x4227009b -0, 20, 20, 1, 599040, 0xd1d5dcb4 -0, 21, 21, 1, 599040, 0x58b2edb3 -0, 22, 22, 1, 599040, 0xd1f795d8 -0, 23, 23, 1, 599040, 0x3331d5e6 -0, 24, 24, 1, 599040, 0x5e5ec2c9 -0, 25, 25, 1, 599040, 0x3b907bf5 -0, 26, 26, 1, 599040, 0xefcbf471 -0, 27, 27, 1, 599040, 0x2769a578 -0, 28, 28, 1, 599040, 0x812ce986 -0, 29, 29, 1, 599040, 0xf07c212c -0, 30, 30, 1, 599040, 0x00a0249f -0, 31, 31, 1, 599040, 0x7263f7cf -0, 32, 32, 1, 599040, 0x47054be4 -0, 33, 33, 1, 599040, 0xda083f52 -0, 34, 34, 1, 599040, 0xf2906ab1 -0, 35, 35, 1, 599040, 0x20936797 -0, 36, 36, 1, 599040, 0x644d7c3e -0, 37, 37, 1, 599040, 0x7c00e8bf -0, 38, 38, 1, 599040, 0x041f8a48 -0, 39, 39, 1, 599040, 0xcef6e936 -0, 40, 40, 1, 599040, 0x361461e9 -0, 41, 41, 1, 599040, 0xf663ba0a -0, 42, 42, 1, 599040, 0x4d3371d3 -0, 43, 43, 1, 599040, 0xed6b5c92 -0, 44, 44, 1, 599040, 0xdec67f6e -0, 45, 45, 1, 599040, 0xbafa50c0 -0, 46, 46, 1, 599040, 0xc9181637 -0, 47, 47, 1, 599040, 0x29eadcac -0, 48, 48, 1, 599040, 0xb258430f -0, 49, 49, 1, 599040, 0x49dc8716 -0, 50, 50, 1, 599040, 0x80b0a3b3 -0, 51, 51, 1, 599040, 0x5d8275a7 -0, 52, 52, 1, 599040, 0xe236242d -0, 53, 53, 1, 599040, 0x3e14bb43 -0, 54, 54, 1, 599040, 0x20e6e2d7 -0, 55, 55, 1, 599040, 0x19cad4ee -0, 56, 56, 1, 599040, 0x13fd16f1 -0, 57, 57, 1, 599040, 0x98e56b95 -0, 58, 58, 1, 599040, 0x028e4c6a -0, 59, 59, 1, 599040, 0x5bd1131d -0, 60, 60, 1, 599040, 0x0afe3873 -0, 61, 61, 1, 599040, 0xea93e425 -0, 62, 62, 1, 599040, 0xeb301be1 -0, 63, 63, 1, 599040, 0x443ca0a3 -0, 64, 64, 1, 599040, 0xb68b40a1 -0, 65, 65, 1, 599040, 0xf58f75b9 -0, 66, 66, 1, 599040, 0xefa27c52 -0, 67, 67, 1, 599040, 0xac676fa5 -0, 68, 68, 1, 599040, 0x688d1582 -0, 69, 69, 1, 599040, 0x9067a4ef -0, 70, 70, 1, 599040, 0xdc753d6c -0, 71, 71, 1, 599040, 0x6f6da304 -0, 72, 72, 1, 599040, 0xa7606f97 -0, 73, 73, 1, 599040, 0xb53c8c18 -0, 74, 74, 1, 599040, 0x3572d550 -0, 75, 75, 1, 599040, 0x123d5423 -0, 76, 76, 1, 599040, 0x89f11e50 -0, 77, 77, 1, 599040, 0x702649cc -0, 78, 78, 1, 599040, 0x2b4767c4 -0, 79, 79, 1, 599040, 0xf18b9628 -0, 80, 80, 1, 599040, 0x1ef72a6b -0, 81, 81, 1, 599040, 0x0a8c9641 -0, 82, 82, 1, 599040, 0xf2fa0233 -0, 83, 83, 1, 599040, 0x99385e51 -0, 84, 84, 1, 599040, 0x77b413cf -0, 85, 85, 1, 599040, 0x6360c9e3 -0, 86, 86, 1, 599040, 0xe216b383 -0, 87, 87, 1, 599040, 0x54df8826 -0, 88, 88, 1, 599040, 0x6691e1ee -0, 89, 89, 1, 599040, 0x37bebd20 -0, 90, 90, 1, 599040, 0xf05184e4 -0, 91, 91, 1, 599040, 0xbd7fab4f -0, 92, 92, 1, 599040, 0x70211cdc -0, 93, 93, 1, 599040, 0x4f4c375b -0, 94, 94, 1, 599040, 0x2d645b5a -0, 95, 95, 1, 599040, 0x475d263f +0, 16, 16, 1, 599040, 0xc6dd131e +0, 17, 17, 1, 599040, 0x0a22f4c5 +0, 18, 18, 1, 599040, 0xd6a0c196 +0, 19, 19, 1, 599040, 0x699a3e69 +0, 20, 20, 1, 599040, 0x4227009b +0, 21, 21, 1, 599040, 0xd1d5dcb4 +0, 22, 22, 1, 599040, 0x58b2edb3 +0, 23, 23, 1, 599040, 0xd1f795d8 +0, 24, 24, 1, 599040, 0x3331d5e6 +0, 25, 25, 1, 599040, 0x5e5ec2c9 +0, 26, 26, 1, 599040, 0x3b907bf5 +0, 27, 27, 1, 599040, 0xefcbf471 +0, 28, 28, 1, 599040, 0x2769a578 +0, 30, 30, 1, 599040, 0x812ce986 +0, 31, 31, 1, 599040, 0xf07c212c +0, 32, 32, 1, 599040, 0x00a0249f +0, 33, 33, 1, 599040, 0x7263f7cf +0, 34, 34, 1, 599040, 0x47054be4 +0, 35, 35, 1, 599040, 0xda083f52 +0, 36, 36, 1, 599040, 0xf2906ab1 +0, 37, 37, 1, 599040, 0x20936797 +0, 38, 38, 1, 599040, 0x644d7c3e +0, 39, 39, 1, 599040, 0x7c00e8bf +0, 40, 40, 1, 599040, 0x041f8a48 +0, 41, 41, 1, 599040, 0xcef6e936 +0, 42, 42, 1, 599040, 0x361461e9 +0, 43, 43, 1, 599040, 0xf663ba0a +0, 44, 44, 1, 599040, 0x4d3371d3 +0, 45, 45, 1, 599040, 0xed6b5c92 +0, 47, 47, 1, 599040, 0xdec67f6e +0, 48, 48, 1, 599040, 0xbafa50c0 +0, 49, 49, 1, 599040, 0xc9181637 +0, 50, 50, 1, 599040, 0x29eadcac +0, 51, 51, 1, 599040, 0xb258430f +0, 52, 52, 1, 599040, 0x49dc8716 +0, 53, 53, 1, 599040, 0x80b0a3b3 +0, 54, 54, 1, 599040, 0x5d8275a7 +0, 55, 55, 1, 599040, 0xe236242d +0, 56, 56, 1, 599040, 0x3e14bb43 +0, 57, 57, 1, 599040, 0x20e6e2d7 +0, 58, 58, 1, 599040, 0x19cad4ee +0, 59, 59, 1, 599040, 0x13fd16f1 +0, 60, 60, 1, 599040, 0x98e56b95 +0, 61, 61, 1, 599040, 0x028e4c6a +0, 63, 63, 1, 599040, 0x5bd1131d +0, 64, 64, 1, 599040, 0x0afe3873 +0, 65, 65, 1, 599040, 0xea93e425 +0, 66, 66, 1, 599040, 0xeb301be1 +0, 67, 67, 1, 599040, 0x443ca0a3 +0, 68, 68, 1, 599040, 0xb68b40a1 +0, 69, 69, 1, 599040, 0xf58f75b9 +0, 70, 70, 1, 599040, 0xefa27c52 +0, 71, 71, 1, 599040, 0xac676fa5 +0, 72, 72, 1, 599040, 0x688d1582 +0, 73, 73, 1, 599040, 0x9067a4ef +0, 74, 74, 1, 599040, 0xdc753d6c +0, 75, 75, 1, 599040, 0x6f6da304 +0, 76, 76, 1, 599040, 0xa7606f97 +0, 77, 77, 1, 599040, 0xb53c8c18 +0, 78, 78, 1, 599040, 0x3572d550 +0, 79, 79, 1, 599040, 0x123d5423 +0, 80, 80, 1, 599040, 0x89f11e50 +0, 81, 81, 1, 599040, 0x702649cc +0, 82, 82, 1, 599040, 0x2b4767c4 +0, 83, 83, 1, 599040, 0xf18b9628 +0, 84, 84, 1, 599040, 0x1ef72a6b +0, 85, 85, 1, 599040, 0x0a8c9641 +0, 86, 86, 1, 599040, 0xf2fa0233 +0, 87, 87, 1, 599040, 0x99385e51 +0, 88, 88, 1, 599040, 0x77b413cf +0, 89, 89, 1, 599040, 0x6360c9e3 +0, 90, 90, 1, 599040, 0xe216b383 +0, 91, 91, 1, 599040, 0x54df8826 +0, 92, 92, 1, 599040, 0x6691e1ee +0, 93, 93, 1, 599040, 0x37bebd20 +0, 94, 94, 1, 599040, 0xf05184e4 +0, 95, 95, 1, 599040, 0xbd7fab4f +0, 96, 96, 1, 599040, 0x70211cdc +0, 97, 97, 1, 599040, 0x4f4c375b +0, 98, 98, 1, 599040, 0x2d645b5a +0, 99, 99, 1, 599040, 0x475d263f diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-RAP_A_docomo_4 ffmpeg-4.4/tests/ref/fate/hevc-conformance-RAP_A_docomo_4 --- ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-RAP_A_docomo_4 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-conformance-RAP_A_docomo_4 2021-04-08 21:28:40.000000000 +0000 @@ -3,89 +3,89 @@ #codec_id 0: rawvideo #dimensions 0: 416x240 #sar 0: 0/1 -0, 0, 0, 1, 149760, 0x1ae5f13d -0, 1, 1, 1, 149760, 0x0a6ad0e3 -0, 2, 2, 1, 149760, 0x2415af05 -0, 3, 3, 1, 149760, 0xf50f6eef -0, 4, 4, 1, 149760, 0xef65835c -0, 5, 5, 1, 149760, 0x4929b5cb -0, 6, 6, 1, 149760, 0x165c6f55 -0, 7, 7, 1, 149760, 0x9caaa249 -0, 8, 8, 1, 149760, 0x6c25c4cf -0, 9, 9, 1, 149760, 0x4678cef0 -0, 10, 10, 1, 149760, 0x72e04433 -0, 11, 11, 1, 149760, 0x36f8aa9d -0, 12, 12, 1, 149760, 0x255189ad -0, 13, 13, 1, 149760, 0x712d7f7f -0, 14, 14, 1, 149760, 0x4d088988 -0, 15, 15, 1, 149760, 0xc0da3925 -0, 16, 16, 1, 149760, 0x9990db7c -0, 17, 17, 1, 149760, 0xb02cc0e8 -0, 18, 18, 1, 149760, 0x3e859d8f -0, 19, 19, 1, 149760, 0xce786bc1 -0, 20, 20, 1, 149760, 0x87555e5f -0, 21, 21, 1, 149760, 0x3c95fb7e -0, 22, 22, 1, 149760, 0xf092b65e -0, 23, 23, 1, 149760, 0x7db2c04c -0, 24, 24, 1, 149760, 0x7d39eb21 -0, 25, 25, 1, 149760, 0x2cfd7d57 -0, 26, 26, 1, 149760, 0xb1902c06 -0, 27, 27, 1, 149760, 0xe0eae1d7 -0, 28, 28, 1, 149760, 0xf8212977 -0, 29, 29, 1, 149760, 0x6cb31328 -0, 30, 30, 1, 149760, 0x862ab736 -0, 31, 31, 1, 149760, 0xc7a87f44 -0, 32, 32, 1, 149760, 0x8ff7a1a1 -0, 33, 33, 1, 149760, 0xd7bee49b -0, 34, 34, 1, 149760, 0x1925db84 -0, 35, 35, 1, 149760, 0xf32a7dc6 -0, 36, 36, 1, 149760, 0x02a1e3b6 -0, 37, 37, 1, 149760, 0xb6398aad -0, 38, 38, 1, 149760, 0xa3756e2d -0, 39, 39, 1, 149760, 0xf90f3732 -0, 40, 40, 1, 149760, 0x3b05115a -0, 41, 41, 1, 149760, 0x81ca9bdb -0, 42, 42, 1, 149760, 0xa75ee938 -0, 43, 43, 1, 149760, 0x9e5c232f -0, 44, 44, 1, 149760, 0x64cb04e9 -0, 45, 45, 1, 149760, 0x4064df52 -0, 46, 46, 1, 149760, 0x47fa0afc -0, 47, 47, 1, 149760, 0xd209252e -0, 48, 48, 1, 149760, 0x2f811f02 -0, 49, 49, 1, 149760, 0x733b6721 -0, 50, 50, 1, 149760, 0x30b12427 -0, 51, 51, 1, 149760, 0xdf58d3e2 -0, 52, 52, 1, 149760, 0xc144d7be -0, 53, 53, 1, 149760, 0x48f0ac79 -0, 54, 54, 1, 149760, 0xb8d8a2c6 -0, 55, 55, 1, 149760, 0x2a7d916d -0, 56, 56, 1, 149760, 0xd9d38cd5 -0, 57, 57, 1, 149760, 0xd7c7f9a6 -0, 58, 58, 1, 149760, 0x64d0df7a -0, 59, 59, 1, 149760, 0x4e365cff -0, 60, 60, 1, 149760, 0x74bc2a8b -0, 61, 61, 1, 149760, 0x70a7cd2b -0, 62, 62, 1, 149760, 0x0836b51e -0, 63, 63, 1, 149760, 0xbc37b5d7 -0, 64, 64, 1, 149760, 0xb6d651e5 -0, 65, 65, 1, 149760, 0x7aa0e35f -0, 66, 66, 1, 149760, 0x0fbc89a3 -0, 67, 67, 1, 149760, 0x2ca2f2a6 -0, 68, 68, 1, 149760, 0xf742c5c5 -0, 69, 69, 1, 149760, 0x4117208f -0, 70, 70, 1, 149760, 0xec392efb -0, 71, 71, 1, 149760, 0xbfba5063 -0, 72, 72, 1, 149760, 0xb2499f48 -0, 73, 73, 1, 149760, 0xf1183244 -0, 74, 74, 1, 149760, 0x364a6400 -0, 75, 75, 1, 149760, 0xfcfddf36 -0, 76, 76, 1, 149760, 0xbcc1b37e -0, 77, 77, 1, 149760, 0xab364748 -0, 78, 78, 1, 149760, 0xebb27fcd -0, 79, 79, 1, 149760, 0xe2e7a723 -0, 80, 80, 1, 149760, 0xf671b5e0 -0, 81, 81, 1, 149760, 0xbf0cc349 -0, 82, 82, 1, 149760, 0xf195d868 -0, 83, 83, 1, 149760, 0xe0097460 -0, 84, 84, 1, 149760, 0x3d4c1812 -0, 85, 85, 1, 149760, 0x133cd867 +0, 7, 7, 1, 149760, 0x1ae5f13d +0, 8, 8, 1, 149760, 0x0a6ad0e3 +0, 9, 9, 1, 149760, 0x2415af05 +0, 10, 10, 1, 149760, 0xf50f6eef +0, 11, 11, 1, 149760, 0xef65835c +0, 12, 12, 1, 149760, 0x4929b5cb +0, 13, 13, 1, 149760, 0x165c6f55 +0, 14, 14, 1, 149760, 0x9caaa249 +0, 15, 15, 1, 149760, 0x6c25c4cf +0, 16, 16, 1, 149760, 0x4678cef0 +0, 17, 17, 1, 149760, 0x72e04433 +0, 18, 18, 1, 149760, 0x36f8aa9d +0, 19, 19, 1, 149760, 0x255189ad +0, 20, 20, 1, 149760, 0x712d7f7f +0, 21, 21, 1, 149760, 0x4d088988 +0, 22, 22, 1, 149760, 0xc0da3925 +0, 23, 23, 1, 149760, 0x9990db7c +0, 24, 24, 1, 149760, 0xb02cc0e8 +0, 25, 25, 1, 149760, 0x3e859d8f +0, 26, 26, 1, 149760, 0xce786bc1 +0, 27, 27, 1, 149760, 0x87555e5f +0, 28, 28, 1, 149760, 0x3c95fb7e +0, 29, 29, 1, 149760, 0xf092b65e +0, 30, 30, 1, 149760, 0x7db2c04c +0, 31, 31, 1, 149760, 0x7d39eb21 +0, 32, 32, 1, 149760, 0x2cfd7d57 +0, 33, 33, 1, 149760, 0xb1902c06 +0, 34, 34, 1, 149760, 0xe0eae1d7 +0, 35, 35, 1, 149760, 0xf8212977 +0, 36, 36, 1, 149760, 0x6cb31328 +0, 37, 37, 1, 149760, 0x862ab736 +0, 38, 38, 1, 149760, 0xc7a87f44 +0, 39, 39, 1, 149760, 0x8ff7a1a1 +0, 40, 40, 1, 149760, 0xd7bee49b +0, 41, 41, 1, 149760, 0x1925db84 +0, 42, 42, 1, 149760, 0xf32a7dc6 +0, 43, 43, 1, 149760, 0x02a1e3b6 +0, 44, 44, 1, 149760, 0xb6398aad +0, 45, 45, 1, 149760, 0xa3756e2d +0, 46, 46, 1, 149760, 0xf90f3732 +0, 47, 47, 1, 149760, 0x3b05115a +0, 48, 48, 1, 149760, 0x81ca9bdb +0, 49, 49, 1, 149760, 0xa75ee938 +0, 50, 50, 1, 149760, 0x9e5c232f +0, 51, 51, 1, 149760, 0x64cb04e9 +0, 52, 52, 1, 149760, 0x4064df52 +0, 53, 53, 1, 149760, 0x47fa0afc +0, 54, 54, 1, 149760, 0xd209252e +0, 55, 55, 1, 149760, 0x2f811f02 +0, 56, 56, 1, 149760, 0x733b6721 +0, 57, 57, 1, 149760, 0x30b12427 +0, 58, 58, 1, 149760, 0xdf58d3e2 +0, 59, 59, 1, 149760, 0xc144d7be +0, 60, 60, 1, 149760, 0x48f0ac79 +0, 61, 61, 1, 149760, 0xb8d8a2c6 +0, 62, 62, 1, 149760, 0x2a7d916d +0, 63, 63, 1, 149760, 0xd9d38cd5 +0, 64, 64, 1, 149760, 0xd7c7f9a6 +0, 65, 65, 1, 149760, 0x64d0df7a +0, 66, 66, 1, 149760, 0x4e365cff +0, 67, 67, 1, 149760, 0x74bc2a8b +0, 68, 68, 1, 149760, 0x70a7cd2b +0, 69, 69, 1, 149760, 0x0836b51e +0, 70, 70, 1, 149760, 0xbc37b5d7 +0, 71, 71, 1, 149760, 0xb6d651e5 +0, 72, 72, 1, 149760, 0x7aa0e35f +0, 73, 73, 1, 149760, 0x0fbc89a3 +0, 74, 74, 1, 149760, 0x2ca2f2a6 +0, 75, 75, 1, 149760, 0xf742c5c5 +0, 76, 76, 1, 149760, 0x4117208f +0, 77, 77, 1, 149760, 0xec392efb +0, 78, 78, 1, 149760, 0xbfba5063 +0, 79, 79, 1, 149760, 0xb2499f48 +0, 80, 80, 1, 149760, 0xf1183244 +0, 81, 81, 1, 149760, 0x364a6400 +0, 82, 82, 1, 149760, 0xfcfddf36 +0, 83, 83, 1, 149760, 0xbcc1b37e +0, 84, 84, 1, 149760, 0xab364748 +0, 85, 85, 1, 149760, 0xebb27fcd +0, 86, 86, 1, 149760, 0xe2e7a723 +0, 87, 87, 1, 149760, 0xf671b5e0 +0, 88, 88, 1, 149760, 0xbf0cc349 +0, 89, 89, 1, 149760, 0xf195d868 +0, 90, 90, 1, 149760, 0xe0097460 +0, 91, 91, 1, 149760, 0x3d4c1812 +0, 92, 92, 1, 149760, 0x133cd867 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 ffmpeg-4.4/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 --- ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 2021-04-08 21:28:40.000000000 +0000 @@ -70,16 +70,16 @@ 0, 64, 64, 1, 149760, 0x3362678b 0, 65, 65, 1, 149760, 0x6e7fc851 0, 66, 66, 1, 149760, 0x33f96449 -0, 67, 67, 1, 149760, 0xb3ba8cfb -0, 68, 68, 1, 149760, 0x64787995 -0, 69, 69, 1, 149760, 0xc10de4c4 -0, 70, 70, 1, 149760, 0x18dd343f -0, 71, 71, 1, 149760, 0xa1c51358 -0, 72, 72, 1, 149760, 0x91fe6361 -0, 73, 73, 1, 149760, 0xeec85f94 -0, 74, 74, 1, 149760, 0x00a57402 -0, 75, 75, 1, 149760, 0x4e88cc16 -0, 76, 76, 1, 149760, 0xdbd51976 -0, 77, 77, 1, 149760, 0xfebf6b1a -0, 78, 78, 1, 149760, 0x052546d2 -0, 79, 79, 1, 149760, 0x046cd73b +0, 77, 77, 1, 149760, 0xb3ba8cfb +0, 78, 78, 1, 149760, 0x64787995 +0, 79, 79, 1, 149760, 0xc10de4c4 +0, 80, 80, 1, 149760, 0x18dd343f +0, 81, 81, 1, 149760, 0xa1c51358 +0, 82, 82, 1, 149760, 0x91fe6361 +0, 83, 83, 1, 149760, 0xeec85f94 +0, 84, 84, 1, 149760, 0x00a57402 +0, 85, 85, 1, 149760, 0x4e88cc16 +0, 86, 86, 1, 149760, 0xdbd51976 +0, 87, 87, 1, 149760, 0xfebf6b1a +0, 88, 88, 1, 149760, 0x052546d2 +0, 89, 89, 1, 149760, 0x046cd73b diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-SDH_A_Orange_3 ffmpeg-4.4/tests/ref/fate/hevc-conformance-SDH_A_Orange_3 --- ffmpeg-4.2.2/tests/ref/fate/hevc-conformance-SDH_A_Orange_3 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-conformance-SDH_A_Orange_3 2021-04-08 21:28:40.000000000 +0000 @@ -3,5 +3,5 @@ #codec_id 0: rawvideo #dimensions 0: 1920x1080 #sar 0: 0/1 -0, 0, 0, 1, 3110400, 0x0117aa5d -0, 1, 1, 1, 3110400, 0xa737bc56 +0, 2, 2, 1, 3110400, 0x0117aa5d +0, 3, 3, 1, 3110400, 0xa737bc56 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-hdr10-plus-metadata ffmpeg-4.4/tests/ref/fate/hevc-hdr10-plus-metadata --- ffmpeg-4.2.2/tests/ref/fate/hevc-hdr10-plus-metadata 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-hdr10-plus-metadata 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,62 @@ +[FRAME] +[SIDE_DATA] +side_data_type=Mastering display metadata +red_x=13250/50000 +red_y=34500/50000 +green_x=7500/50000 +green_y=3000/50000 +blue_x=34000/50000 +blue_y=16000/50000 +white_point_x=15635/50000 +white_point_y=16450/50000 +min_luminance=50/10000 +max_luminance=10000000/10000 +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Content light level metadata +max_content=1000 +max_average=200 +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=HDR Dynamic Metadata SMPTE2094-40 (HDR10+) +application version=1 +num_windows=1 +targeted_system_display_maximum_luminance=400/1 +maxscl=3340/100000 +maxscl=2870/100000 +maxscl=2720/100000 +average_maxrgb=510/100000 +num_distribution_maxrgb_percentiles=9 +distribution_maxrgb_percentage=1 +distribution_maxrgb_percentile=30/100000 +distribution_maxrgb_percentage=5 +distribution_maxrgb_percentile=2940/100000 +distribution_maxrgb_percentage=10 +distribution_maxrgb_percentile=255/100000 +distribution_maxrgb_percentage=25 +distribution_maxrgb_percentile=70/100000 +distribution_maxrgb_percentage=50 +distribution_maxrgb_percentile=1340/100000 +distribution_maxrgb_percentage=75 +distribution_maxrgb_percentile=1600/100000 +distribution_maxrgb_percentage=90 +distribution_maxrgb_percentile=1850/100000 +distribution_maxrgb_percentage=95 +distribution_maxrgb_percentile=1950/100000 +distribution_maxrgb_percentage=99 +distribution_maxrgb_percentile=2940/100000 +fraction_bright_pixels=1/1000 +knee_point_x=0/4095 +knee_point_y=0/4095 +num_bezier_curve_anchors=9 +bezier_curve_anchors=102/1023 +bezier_curve_anchors=205/1023 +bezier_curve_anchors=307/1023 +bezier_curve_anchors=410/1023 +bezier_curve_anchors=512/1023 +bezier_curve_anchors=614/1023 +bezier_curve_anchors=717/1023 +bezier_curve_anchors=819/1023 +bezier_curve_anchors=922/1023 +[/SIDE_DATA] +[/FRAME] diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-monochrome-crop ffmpeg-4.4/tests/ref/fate/hevc-monochrome-crop --- ffmpeg-4.2.2/tests/ref/fate/hevc-monochrome-crop 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-monochrome-crop 2021-04-08 21:28:40.000000000 +0000 @@ -1,6 +1,9 @@ [FRAME] width=384 height=240 +[SIDE_DATA] +side_data_type=H.26[45] User Data Unregistered SEI message +[/SIDE_DATA] [/FRAME] [STREAM] width=384 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hevc-small422chroma ffmpeg-4.4/tests/ref/fate/hevc-small422chroma --- ffmpeg-4.2.2/tests/ref/fate/hevc-small422chroma 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hevc-small422chroma 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,6 @@ +#tb 0: 1/50 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 3840x2160 +#sar 0: 1/1 +0, 11, 11, 1, 33177600, 0x53015e18 diff -Nru ffmpeg-4.2.2/tests/ref/fate/hls-fmp4_ac3 ffmpeg-4.4/tests/ref/fate/hls-fmp4_ac3 --- ffmpeg-4.2.2/tests/ref/fate/hls-fmp4_ac3 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hls-fmp4_ac3 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,8 @@ +[STREAM] +codec_name=ac3 +sample_fmt=fltp +channels=6 +channel_layout=5.1(side) +[SIDE_DATA] +[/SIDE_DATA] +[/STREAM] diff -Nru ffmpeg-4.2.2/tests/ref/fate/hls-segment-single ffmpeg-4.4/tests/ref/fate/hls-segment-single --- ffmpeg-4.2.2/tests/ref/fate/hls-segment-single 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/hls-segment-single 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,772 @@ +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout 0: 4 +#channel_layout_name 0: mono +0, 0, 0, 1152, 2304, 0x907cb7fa +0, 1152, 1152, 1152, 2304, 0xb8dc7525 +0, 2304, 2304, 1152, 2304, 0x3e7d6905 +0, 3456, 3456, 1152, 2304, 0xef47877b +0, 4608, 4608, 1152, 2304, 0xfe916b7e +0, 5760, 5760, 1152, 2304, 0xe3d08cde +0, 6912, 6912, 1152, 2304, 0xff7f86cf +0, 8064, 8064, 1152, 2304, 0x843e6f95 +0, 9216, 9216, 1152, 2304, 0x81577c26 +0, 10368, 10368, 1152, 2304, 0x04a085d5 +0, 11520, 11520, 1152, 2304, 0x1c5a76f5 +0, 12672, 12672, 1152, 2304, 0x4ee78623 +0, 13824, 13824, 1152, 2304, 0x8ec861dc +0, 14976, 14976, 1152, 2304, 0x0ca179d8 +0, 16128, 16128, 1152, 2304, 0xc6da750f +0, 17280, 17280, 1152, 2304, 0xf6bf79b5 +0, 18432, 18432, 1152, 2304, 0x97b88a43 +0, 19584, 19584, 1152, 2304, 0xf13c7b9c +0, 20736, 20736, 1152, 2304, 0xdfba83af +0, 21888, 21888, 1152, 2304, 0xc9467d4b +0, 23040, 23040, 1152, 2304, 0xbbb58e2b +0, 24192, 24192, 1152, 2304, 0x3a1078ea +0, 25344, 25344, 1152, 2304, 0xe9587a5c +0, 26496, 26496, 1152, 2304, 0xef5a8039 +0, 27648, 27648, 1152, 2304, 0x9d5f782f +0, 28800, 28800, 1152, 2304, 0x1a548291 +0, 29952, 29952, 1152, 2304, 0x07517701 +0, 31104, 31104, 1152, 2304, 0x78127d6e +0, 32256, 32256, 1152, 2304, 0x62e2788a +0, 33408, 33408, 1152, 2304, 0x29397ad9 +0, 34560, 34560, 1152, 2304, 0x45da82d6 +0, 35712, 35712, 1152, 2304, 0x8ed66e51 +0, 36864, 36864, 1152, 2304, 0x660775cd +0, 38016, 38016, 1152, 2304, 0x802c767a +0, 39168, 39168, 1152, 2304, 0xcc055840 +0, 40320, 40320, 1152, 2304, 0x701b7eaf +0, 41472, 41472, 1152, 2304, 0x8290749f +0, 42624, 42624, 1152, 2304, 0x2c7b7d30 +0, 43776, 43776, 1152, 2304, 0xe4f17743 +0, 44928, 44928, 1152, 2304, 0x0e747d6e +0, 46080, 46080, 1152, 2304, 0xbe7775a0 +0, 47232, 47232, 1152, 2304, 0xcf797673 +0, 48384, 48384, 1152, 2304, 0x29cb7800 +0, 49536, 49536, 1152, 2304, 0xfc947890 +0, 50688, 50688, 1152, 2304, 0x62757fc6 +0, 51840, 51840, 1152, 2304, 0x098876d0 +0, 52992, 52992, 1152, 2304, 0xa9567ee2 +0, 54144, 54144, 1152, 2304, 0xe3bb9173 +0, 55296, 55296, 1152, 2304, 0xcc2d6dee +0, 56448, 56448, 1152, 2304, 0xe94591ab +0, 57600, 57600, 1152, 2304, 0x5c7588de +0, 58752, 58752, 1152, 2304, 0xfd83643c +0, 59904, 59904, 1152, 2304, 0x528177f1 +0, 61056, 61056, 1152, 2304, 0x65d08474 +0, 62208, 62208, 1152, 2304, 0x738d765b +0, 63360, 63360, 1152, 2304, 0xdd3d810e +0, 64512, 64512, 1152, 2304, 0xef4f90d3 +0, 65664, 65664, 1152, 2304, 0x61e28d43 +0, 66816, 66816, 1152, 2304, 0x9a11796b +0, 67968, 67968, 1152, 2304, 0x96c97dcd +0, 69120, 69120, 1152, 2304, 0xa8fe8621 +0, 70272, 70272, 1152, 2304, 0x499b7d38 +0, 71424, 71424, 1152, 2304, 0xfcb078a9 +0, 72576, 72576, 1152, 2304, 0x40d78651 +0, 73728, 73728, 1152, 2304, 0xa4af7234 +0, 74880, 74880, 1152, 2304, 0x6831870a +0, 76032, 76032, 1152, 2304, 0x030e7b9d +0, 77184, 77184, 1152, 2304, 0x445a75b6 +0, 78336, 78336, 1152, 2304, 0x09857389 +0, 79488, 79488, 1152, 2304, 0x0d018866 +0, 80640, 80640, 1152, 2304, 0x2afe810a +0, 81792, 81792, 1152, 2304, 0x0bcf7c43 +0, 82944, 82944, 1152, 2304, 0x13737c12 +0, 84096, 84096, 1152, 2304, 0x716c7bba +0, 85248, 85248, 1152, 2304, 0xb801823b +0, 86400, 86400, 1152, 2304, 0x0fd573ee +0, 87552, 87552, 1152, 2304, 0xe1ab879c +0, 88704, 88704, 1152, 2304, 0x49e6764f +0, 89856, 89856, 1152, 2304, 0xd5f26ddc +0, 91008, 91008, 1152, 2304, 0x076775ff +0, 92160, 92160, 1152, 2304, 0xfbb86fce +0, 93312, 93312, 1152, 2304, 0x20c56858 +0, 94464, 94464, 1152, 2304, 0x043e6891 +0, 95616, 95616, 1152, 2304, 0x59648729 +0, 96768, 96768, 1152, 2304, 0xd4907a63 +0, 97920, 97920, 1152, 2304, 0xd0208a4c +0, 99072, 99072, 1152, 2304, 0xce968383 +0, 100224, 100224, 1152, 2304, 0x3cfc7cd1 +0, 101376, 101376, 1152, 2304, 0x628a7bf5 +0, 102528, 102528, 1152, 2304, 0x9cfe8a4f +0, 103680, 103680, 1152, 2304, 0xdf6f7c6d +0, 104832, 104832, 1152, 2304, 0x6cf6882a +0, 105984, 105984, 1152, 2304, 0x099773a3 +0, 107136, 107136, 1152, 2304, 0x4a1c7649 +0, 108288, 108288, 1152, 2304, 0x31ea71cb +0, 109440, 109440, 1152, 2304, 0xed127ed9 +0, 110592, 110592, 1152, 2304, 0x5b156954 +0, 111744, 111744, 1152, 2304, 0xdd638532 +0, 112896, 112896, 1152, 2304, 0xf1a271f2 +0, 114048, 114048, 1152, 2304, 0x779184d7 +0, 115200, 115200, 1152, 2304, 0x49a88aa8 +0, 116352, 116352, 1152, 2304, 0xa11b7c90 +0, 117504, 117504, 1152, 2304, 0xbf488274 +0, 118656, 118656, 1152, 2304, 0x002f79a8 +0, 119808, 119808, 1152, 2304, 0x0ed97e2f +0, 120960, 120960, 1152, 2304, 0x7845878f +0, 122112, 122112, 1152, 2304, 0x46d777dc +0, 123264, 123264, 1152, 2304, 0x8d0179e3 +0, 124416, 124416, 1152, 2304, 0x38917f9f +0, 125568, 125568, 1152, 2304, 0x449876e7 +0, 126720, 126720, 1152, 2304, 0x001a8769 +0, 127872, 127872, 1152, 2304, 0x06c1826b +0, 129024, 129024, 1152, 2304, 0x41b68047 +0, 130176, 130176, 1152, 2304, 0xeb9782c6 +0, 131328, 131328, 1152, 2304, 0x7cd9719c +0, 132480, 132480, 1152, 2304, 0x3a4a767c +0, 133632, 133632, 1152, 2304, 0x7f887e81 +0, 134784, 134784, 1152, 2304, 0xf75d714b +0, 135936, 135936, 1152, 2304, 0x33b57e9f +0, 137088, 137088, 1152, 2304, 0xc732749e +0, 138240, 138240, 1152, 2304, 0x386f7e1a +0, 139392, 139392, 1152, 2304, 0x6b9c767d +0, 140544, 140544, 1152, 2304, 0x701c83e5 +0, 141696, 141696, 1152, 2304, 0xb92571e1 +0, 142848, 142848, 1152, 2304, 0x833a84bc +0, 144000, 144000, 1152, 2304, 0x1b6984e0 +0, 145152, 145152, 1152, 2304, 0x1b2474ba +0, 146304, 146304, 1152, 2304, 0xc22775a6 +0, 147456, 147456, 1152, 2304, 0x3e8f7972 +0, 148608, 148608, 1152, 2304, 0x17a28a65 +0, 149760, 149760, 1152, 2304, 0x9b6178a4 +0, 150912, 150912, 1152, 2304, 0x5d707873 +0, 152064, 152064, 1152, 2304, 0x68e2645a +0, 153216, 153216, 1152, 2304, 0x1e377d28 +0, 154368, 154368, 1152, 2304, 0x54b384be +0, 155520, 155520, 1152, 2304, 0x0617808c +0, 156672, 156672, 1152, 2304, 0xbc2b8a6c +0, 157824, 157824, 1152, 2304, 0x7ced7180 +0, 158976, 158976, 1152, 2304, 0xf22180ab +0, 160128, 160128, 1152, 2304, 0xf13682c9 +0, 161280, 161280, 1152, 2304, 0x7eff87fd +0, 162432, 162432, 1152, 2304, 0x5a0b5cec +0, 163584, 163584, 1152, 2304, 0x57c18906 +0, 164736, 164736, 1152, 2304, 0xb55a6a16 +0, 165888, 165888, 1152, 2304, 0xf2608371 +0, 167040, 167040, 1152, 2304, 0x36df7576 +0, 168192, 168192, 1152, 2304, 0xdb106fb4 +0, 169344, 169344, 1152, 2304, 0x7e4f85d0 +0, 170496, 170496, 1152, 2304, 0xe3ee78ab +0, 171648, 171648, 1152, 2304, 0xd36b7dc7 +0, 172800, 172800, 1152, 2304, 0xadab7c5c +0, 173952, 173952, 1152, 2304, 0x70786f26 +0, 175104, 175104, 1152, 2304, 0xcd5d717e +0, 176256, 176256, 1152, 2304, 0xc1a96f9a +0, 177408, 177408, 1152, 2304, 0xad777887 +0, 178560, 178560, 1152, 2304, 0x98277c16 +0, 179712, 179712, 1152, 2304, 0x868882c5 +0, 180864, 180864, 1152, 2304, 0xc48092b9 +0, 182016, 182016, 1152, 2304, 0x230069da +0, 183168, 183168, 1152, 2304, 0x14147ad6 +0, 184320, 184320, 1152, 2304, 0xc9007172 +0, 185472, 185472, 1152, 2304, 0x85d67bcc +0, 186624, 186624, 1152, 2304, 0x22418bab +0, 187776, 187776, 1152, 2304, 0xe53c8b71 +0, 188928, 188928, 1152, 2304, 0x5a1a9053 +0, 190080, 190080, 1152, 2304, 0x9cd179af +0, 191232, 191232, 1152, 2304, 0xbb3c7d72 +0, 192384, 192384, 1152, 2304, 0x477a8677 +0, 193536, 193536, 1152, 2304, 0xe3337834 +0, 194688, 194688, 1152, 2304, 0x1cb56d77 +0, 195840, 195840, 1152, 2304, 0xe89d6dac +0, 196992, 196992, 1152, 2304, 0xd468827e +0, 198144, 198144, 1152, 2304, 0xebc46b87 +0, 199296, 199296, 1152, 2304, 0x5fbb78d2 +0, 200448, 200448, 1152, 2304, 0xa1b483d6 +0, 201600, 201600, 1152, 2304, 0x6fec7cab +0, 202752, 202752, 1152, 2304, 0xd86d6f6c +0, 203904, 203904, 1152, 2304, 0x8c2c7d51 +0, 205056, 205056, 1152, 2304, 0xe8377cd7 +0, 206208, 206208, 1152, 2304, 0xb57071b4 +0, 207360, 207360, 1152, 2304, 0xc35c71fd +0, 208512, 208512, 1152, 2304, 0x789079e9 +0, 209664, 209664, 1152, 2304, 0x413b710e +0, 210816, 210816, 1152, 2304, 0x82678332 +0, 211968, 211968, 1152, 2304, 0xe1576e75 +0, 213120, 213120, 1152, 2304, 0x7c0b7ad6 +0, 214272, 214272, 1152, 2304, 0xc6b6786d +0, 215424, 215424, 1152, 2304, 0x736f7b89 +0, 216576, 216576, 1152, 2304, 0x0ded72f1 +0, 217728, 217728, 1152, 2304, 0xcb877a3c +0, 218880, 218880, 1152, 2304, 0x7c497d40 +0, 220032, 220032, 1152, 2304, 0xaefc798c +0, 221184, 221184, 1152, 2304, 0x4cce748c +0, 222336, 222336, 1152, 2304, 0xaa187fbe +0, 223488, 223488, 1152, 2304, 0x1aa77db9 +0, 224640, 224640, 1152, 2304, 0x9e0074b8 +0, 225792, 225792, 1152, 2304, 0x74ee822b +0, 226944, 226944, 1152, 2304, 0x975c6ff6 +0, 228096, 228096, 1152, 2304, 0xe1847bb4 +0, 229248, 229248, 1152, 2304, 0xe0828777 +0, 230400, 230400, 1152, 2304, 0xf4027205 +0, 231552, 231552, 1152, 2304, 0x535e7a20 +0, 232704, 232704, 1152, 2304, 0x5bd88404 +0, 233856, 233856, 1152, 2304, 0xf29478b1 +0, 235008, 235008, 1152, 2304, 0x9b7c7d88 +0, 236160, 236160, 1152, 2304, 0xaeb07335 +0, 237312, 237312, 1152, 2304, 0xbef06e08 +0, 238464, 238464, 1152, 2304, 0x795f7b8c +0, 239616, 239616, 1152, 2304, 0x435a674d +0, 240768, 240768, 1152, 2304, 0xd8ee7a09 +0, 241920, 241920, 1152, 2304, 0x9059812e +0, 243072, 243072, 1152, 2304, 0x7481744a +0, 244224, 244224, 1152, 2304, 0xdff27475 +0, 245376, 245376, 1152, 2304, 0xb17783ab +0, 246528, 246528, 1152, 2304, 0x42e9706b +0, 247680, 247680, 1152, 2304, 0x9f0d86b4 +0, 248832, 248832, 1152, 2304, 0x2963955f +0, 249984, 249984, 1152, 2304, 0x059a6957 +0, 251136, 251136, 1152, 2304, 0x85948206 +0, 252288, 252288, 1152, 2304, 0x185e8400 +0, 253440, 253440, 1152, 2304, 0xe98e70df +0, 254592, 254592, 1152, 2304, 0x69057b27 +0, 255744, 255744, 1152, 2304, 0x49e26f21 +0, 256896, 256896, 1152, 2304, 0xb0867da5 +0, 258048, 258048, 1152, 2304, 0x785980ff +0, 259200, 259200, 1152, 2304, 0xf4b774be +0, 260352, 260352, 1152, 2304, 0x63897e8c +0, 261504, 261504, 1152, 2304, 0x248b89af +0, 262656, 262656, 1152, 2304, 0xd3627c4a +0, 263808, 263808, 1152, 2304, 0x5a4d9349 +0, 264960, 264960, 1152, 2304, 0xe2ce7c4c +0, 266112, 266112, 1152, 2304, 0x321f6c0b +0, 267264, 267264, 1152, 2304, 0x51ac74e0 +0, 268416, 268416, 1152, 2304, 0x8efa91ba +0, 269568, 269568, 1152, 2304, 0x8b4b784c +0, 270720, 270720, 1152, 2304, 0xe9e4879e +0, 271872, 271872, 1152, 2304, 0x8dc28081 +0, 273024, 273024, 1152, 2304, 0x44b477b0 +0, 274176, 274176, 1152, 2304, 0xf7b67084 +0, 275328, 275328, 1152, 2304, 0x4b198c17 +0, 276480, 276480, 1152, 2304, 0x9c947194 +0, 277632, 277632, 1152, 2304, 0x6eaa7f15 +0, 278784, 278784, 1152, 2304, 0x119f7c1d +0, 279936, 279936, 1152, 2304, 0x157b7f43 +0, 281088, 281088, 1152, 2304, 0xcd2e7acc +0, 282240, 282240, 1152, 2304, 0x97597247 +0, 283392, 283392, 1152, 2304, 0x7ba06acb +0, 284544, 284544, 1152, 2304, 0x233c7995 +0, 285696, 285696, 1152, 2304, 0x08e28587 +0, 286848, 286848, 1152, 2304, 0x92be84b5 +0, 288000, 288000, 1152, 2304, 0xbb857d43 +0, 289152, 289152, 1152, 2304, 0x168e7c74 +0, 290304, 290304, 1152, 2304, 0xac5465d9 +0, 291456, 291456, 1152, 2304, 0x18f58831 +0, 292608, 292608, 1152, 2304, 0x19b48196 +0, 293760, 293760, 1152, 2304, 0x20297653 +0, 294912, 294912, 1152, 2304, 0x93397a82 +0, 296064, 296064, 1152, 2304, 0x65ea7deb +0, 297216, 297216, 1152, 2304, 0xd7316e20 +0, 298368, 298368, 1152, 2304, 0x94107f2b +0, 299520, 299520, 1152, 2304, 0xec3b7dc6 +0, 300672, 300672, 1152, 2304, 0x2d3783aa +0, 301824, 301824, 1152, 2304, 0x07e47340 +0, 302976, 302976, 1152, 2304, 0xbc117893 +0, 304128, 304128, 1152, 2304, 0x8bd97851 +0, 305280, 305280, 1152, 2304, 0xc27376a9 +0, 306432, 306432, 1152, 2304, 0x30d88c83 +0, 307584, 307584, 1152, 2304, 0x19c2704c +0, 308736, 308736, 1152, 2304, 0x093b7b6e +0, 309888, 309888, 1152, 2304, 0x221a7349 +0, 311040, 311040, 1152, 2304, 0xa4fd82cd +0, 312192, 312192, 1152, 2304, 0x762e6bc9 +0, 313344, 313344, 1152, 2304, 0x270075d4 +0, 314496, 314496, 1152, 2304, 0xa5f27b90 +0, 315648, 315648, 1152, 2304, 0xf72e7edc +0, 316800, 316800, 1152, 2304, 0x42178486 +0, 317952, 317952, 1152, 2304, 0x5f7978e8 +0, 319104, 319104, 1152, 2304, 0x5d7c6703 +0, 320256, 320256, 1152, 2304, 0x2c4483d5 +0, 321408, 321408, 1152, 2304, 0x31bd951d +0, 322560, 322560, 1152, 2304, 0x99487af0 +0, 323712, 323712, 1152, 2304, 0x0bd27ee7 +0, 324864, 324864, 1152, 2304, 0xc3e07ac4 +0, 326016, 326016, 1152, 2304, 0x98a16ba7 +0, 327168, 327168, 1152, 2304, 0xd7a5747b +0, 328320, 328320, 1152, 2304, 0x96fb811c +0, 329472, 329472, 1152, 2304, 0x7cee8109 +0, 330624, 330624, 1152, 2304, 0x52b18ba2 +0, 331776, 331776, 1152, 2304, 0x33be8861 +0, 332928, 332928, 1152, 2304, 0xf41282a0 +0, 334080, 334080, 1152, 2304, 0xb4268993 +0, 335232, 335232, 1152, 2304, 0x52126a1c +0, 336384, 336384, 1152, 2304, 0x050b6f7a +0, 337536, 337536, 1152, 2304, 0x67a26fc3 +0, 338688, 338688, 1152, 2304, 0x966c7cf2 +0, 339840, 339840, 1152, 2304, 0x22097750 +0, 340992, 340992, 1152, 2304, 0xfbb0796c +0, 342144, 342144, 1152, 2304, 0xbd508964 +0, 343296, 343296, 1152, 2304, 0xc24478d8 +0, 344448, 344448, 1152, 2304, 0x3913769d +0, 345600, 345600, 1152, 2304, 0x8aab872f +0, 346752, 346752, 1152, 2304, 0x7cb4822f +0, 347904, 347904, 1152, 2304, 0xea318144 +0, 349056, 349056, 1152, 2304, 0xaf0f86d2 +0, 350208, 350208, 1152, 2304, 0x24f27598 +0, 351360, 351360, 1152, 2304, 0xd76f6d40 +0, 352512, 352512, 1152, 2304, 0x085071a7 +0, 353664, 353664, 1152, 2304, 0x1d11704c +0, 354816, 354816, 1152, 2304, 0x21517cbd +0, 355968, 355968, 1152, 2304, 0xcdca8d32 +0, 357120, 357120, 1152, 2304, 0x71c18433 +0, 358272, 358272, 1152, 2304, 0xd39d7d81 +0, 359424, 359424, 1152, 2304, 0x7a0d7a43 +0, 360576, 360576, 1152, 2304, 0x007c8884 +0, 361728, 361728, 1152, 2304, 0x403282d0 +0, 362880, 362880, 1152, 2304, 0xe3737214 +0, 364032, 364032, 1152, 2304, 0xaf906f47 +0, 365184, 365184, 1152, 2304, 0x54f57b3b +0, 366336, 366336, 1152, 2304, 0x29be7791 +0, 367488, 367488, 1152, 2304, 0xe3c663d5 +0, 368640, 368640, 1152, 2304, 0xd7258238 +0, 369792, 369792, 1152, 2304, 0x3719820d +0, 370944, 370944, 1152, 2304, 0xbe04814f +0, 372096, 372096, 1152, 2304, 0x556c815e +0, 373248, 373248, 1152, 2304, 0xb2447e10 +0, 374400, 374400, 1152, 2304, 0x7c16867c +0, 375552, 375552, 1152, 2304, 0x6a7b78ed +0, 376704, 376704, 1152, 2304, 0x5d307b81 +0, 377856, 377856, 1152, 2304, 0xaab680d3 +0, 379008, 379008, 1152, 2304, 0xb5d37a23 +0, 380160, 380160, 1152, 2304, 0x7f7d6f76 +0, 381312, 381312, 1152, 2304, 0x317a8296 +0, 382464, 382464, 1152, 2304, 0x8a987b3d +0, 383616, 383616, 1152, 2304, 0x4f317a27 +0, 384768, 384768, 1152, 2304, 0xfc65852f +0, 385920, 385920, 1152, 2304, 0x40527719 +0, 387072, 387072, 1152, 2304, 0x84988e13 +0, 388224, 388224, 1152, 2304, 0x318b6ddc +0, 389376, 389376, 1152, 2304, 0x94cf7939 +0, 390528, 390528, 1152, 2304, 0x6f22819d +0, 391680, 391680, 1152, 2304, 0xa7dd80a9 +0, 392832, 392832, 1152, 2304, 0x1c7968fa +0, 393984, 393984, 1152, 2304, 0xd9937bae +0, 395136, 395136, 1152, 2304, 0xf7137cf9 +0, 396288, 396288, 1152, 2304, 0xeadb84b5 +0, 397440, 397440, 1152, 2304, 0x9a2390ac +0, 398592, 398592, 1152, 2304, 0xdb6a73f6 +0, 399744, 399744, 1152, 2304, 0x69e07507 +0, 400896, 400896, 1152, 2304, 0xbc8478b2 +0, 402048, 402048, 1152, 2304, 0x32cf8638 +0, 403200, 403200, 1152, 2304, 0x2b8d755a +0, 404352, 404352, 1152, 2304, 0x52e05bd2 +0, 405504, 405504, 1152, 2304, 0x2aed8c49 +0, 406656, 406656, 1152, 2304, 0x587a896e +0, 407808, 407808, 1152, 2304, 0x6dd87dee +0, 408960, 408960, 1152, 2304, 0xd2858338 +0, 410112, 410112, 1152, 2304, 0xd90f7842 +0, 411264, 411264, 1152, 2304, 0xd6fb6d4a +0, 412416, 412416, 1152, 2304, 0x85498aea +0, 413568, 413568, 1152, 2304, 0x18597790 +0, 414720, 414720, 1152, 2304, 0x3cd78fea +0, 415872, 415872, 1152, 2304, 0x94377fbc +0, 417024, 417024, 1152, 2304, 0xf9db73f5 +0, 418176, 418176, 1152, 2304, 0x14fb6fca +0, 419328, 419328, 1152, 2304, 0xe9d17d69 +0, 420480, 420480, 1152, 2304, 0xdeb57286 +0, 421632, 421632, 1152, 2304, 0xa5d37e17 +0, 422784, 422784, 1152, 2304, 0xcf6882fb +0, 423936, 423936, 1152, 2304, 0x31758066 +0, 425088, 425088, 1152, 2304, 0x6b4d8175 +0, 426240, 426240, 1152, 2304, 0x2a3d7f8e +0, 427392, 427392, 1152, 2304, 0xc066743b +0, 428544, 428544, 1152, 2304, 0xcab88146 +0, 429696, 429696, 1152, 2304, 0x2b4c6e13 +0, 430848, 430848, 1152, 2304, 0x00b36b6f +0, 432000, 432000, 1152, 2304, 0x664a88d3 +0, 433152, 433152, 1152, 2304, 0x18a66f76 +0, 434304, 434304, 1152, 2304, 0x4f828a8b +0, 435456, 435456, 1152, 2304, 0x9cc7728e +0, 436608, 436608, 1152, 2304, 0xbe357936 +0, 437760, 437760, 1152, 2304, 0x19878f8d +0, 438912, 438912, 1152, 2304, 0x227b7c71 +0, 440064, 440064, 1152, 2304, 0xf7c879ec +0, 441216, 441216, 1152, 2304, 0x0bca7b50 +0, 442368, 442368, 1152, 2304, 0xe4398304 +0, 443520, 443520, 1152, 2304, 0xf5da75c7 +0, 444672, 444672, 1152, 2304, 0x9f9070a3 +0, 445824, 445824, 1152, 2304, 0x789076f6 +0, 446976, 446976, 1152, 2304, 0x362977cc +0, 448128, 448128, 1152, 2304, 0x4d0a8928 +0, 449280, 449280, 1152, 2304, 0x1bb767ec +0, 450432, 450432, 1152, 2304, 0xbe727fa5 +0, 451584, 451584, 1152, 2304, 0x27f38347 +0, 452736, 452736, 1152, 2304, 0x0a3c8783 +0, 453888, 453888, 1152, 2304, 0x8249639c +0, 455040, 455040, 1152, 2304, 0x3b076f69 +0, 456192, 456192, 1152, 2304, 0xd9597ee3 +0, 457344, 457344, 1152, 2304, 0x026e7fad +0, 458496, 458496, 1152, 2304, 0xbd7a6de4 +0, 459648, 459648, 1152, 2304, 0x7d718a4d +0, 460800, 460800, 1152, 2304, 0x1f5e83b4 +0, 461952, 461952, 1152, 2304, 0x597d7755 +0, 463104, 463104, 1152, 2304, 0x3fb080bd +0, 464256, 464256, 1152, 2304, 0xdcbd7b16 +0, 465408, 465408, 1152, 2304, 0x5c48865f +0, 466560, 466560, 1152, 2304, 0xcda37ae8 +0, 467712, 467712, 1152, 2304, 0x4810796d +0, 468864, 468864, 1152, 2304, 0x34317fd0 +0, 470016, 470016, 1152, 2304, 0x5c0e7456 +0, 471168, 471168, 1152, 2304, 0x44d78040 +0, 472320, 472320, 1152, 2304, 0x88587882 +0, 473472, 473472, 1152, 2304, 0x77687d5e +0, 474624, 474624, 1152, 2304, 0x116d68bb +0, 475776, 475776, 1152, 2304, 0x3e5b6f60 +0, 476928, 476928, 1152, 2304, 0x64ea783c +0, 478080, 478080, 1152, 2304, 0x23547f7d +0, 479232, 479232, 1152, 2304, 0x2eee7892 +0, 480384, 480384, 1152, 2304, 0xfb837cba +0, 481536, 481536, 1152, 2304, 0x86518209 +0, 482688, 482688, 1152, 2304, 0x672f7bba +0, 483840, 483840, 1152, 2304, 0x6ab583fb +0, 484992, 484992, 1152, 2304, 0xc1297428 +0, 486144, 486144, 1152, 2304, 0x164e7717 +0, 487296, 487296, 1152, 2304, 0xb754976d +0, 488448, 488448, 1152, 2304, 0xb99d81b2 +0, 489600, 489600, 1152, 2304, 0x79046fd6 +0, 490752, 490752, 1152, 2304, 0x9a3f8426 +0, 491904, 491904, 1152, 2304, 0x896371f5 +0, 493056, 493056, 1152, 2304, 0x63d1799f +0, 494208, 494208, 1152, 2304, 0x4842844e +0, 495360, 495360, 1152, 2304, 0x850e8372 +0, 496512, 496512, 1152, 2304, 0x85d07022 +0, 497664, 497664, 1152, 2304, 0x9e6683d1 +0, 498816, 498816, 1152, 2304, 0x301b8981 +0, 499968, 499968, 1152, 2304, 0x1f1e98c5 +0, 501120, 501120, 1152, 2304, 0xc8797b03 +0, 502272, 502272, 1152, 2304, 0xf9d189f5 +0, 503424, 503424, 1152, 2304, 0x0e0d88be +0, 504576, 504576, 1152, 2304, 0x6c1d7843 +0, 505728, 505728, 1152, 2304, 0xd13b8a38 +0, 506880, 506880, 1152, 2304, 0x9b8f773c +0, 508032, 508032, 1152, 2304, 0x9acd7309 +0, 509184, 509184, 1152, 2304, 0x5e7d7d15 +0, 510336, 510336, 1152, 2304, 0xf09d7640 +0, 511488, 511488, 1152, 2304, 0xaebb718f +0, 512640, 512640, 1152, 2304, 0x0c8570f4 +0, 513792, 513792, 1152, 2304, 0x3c93862c +0, 514944, 514944, 1152, 2304, 0xcee46696 +0, 516096, 516096, 1152, 2304, 0x01ba7e20 +0, 517248, 517248, 1152, 2304, 0x7fcb7a09 +0, 518400, 518400, 1152, 2304, 0xddf18c14 +0, 519552, 519552, 1152, 2304, 0xd2e97eeb +0, 520704, 520704, 1152, 2304, 0x514d8719 +0, 521856, 521856, 1152, 2304, 0xe89279c9 +0, 523008, 523008, 1152, 2304, 0x806d6a95 +0, 524160, 524160, 1152, 2304, 0xbc7a8a60 +0, 525312, 525312, 1152, 2304, 0x302f8fa8 +0, 526464, 526464, 1152, 2304, 0xb136784c +0, 527616, 527616, 1152, 2304, 0x9b0f6aab +0, 528768, 528768, 1152, 2304, 0xd8e27582 +0, 529920, 529920, 1152, 2304, 0xdaaf78b1 +0, 531072, 531072, 1152, 2304, 0x65967f5f +0, 532224, 532224, 1152, 2304, 0x6f917aa4 +0, 533376, 533376, 1152, 2304, 0x7f607444 +0, 534528, 534528, 1152, 2304, 0xfd316f2c +0, 535680, 535680, 1152, 2304, 0x776e83c7 +0, 536832, 536832, 1152, 2304, 0xb9c17e16 +0, 537984, 537984, 1152, 2304, 0xdf287de8 +0, 539136, 539136, 1152, 2304, 0xf33d96a3 +0, 540288, 540288, 1152, 2304, 0xad216e5b +0, 541440, 541440, 1152, 2304, 0x4a328342 +0, 542592, 542592, 1152, 2304, 0xcf3f8079 +0, 543744, 543744, 1152, 2304, 0xb46f77b0 +0, 544896, 544896, 1152, 2304, 0x3199713d +0, 546048, 546048, 1152, 2304, 0x5e667a0d +0, 547200, 547200, 1152, 2304, 0xa3047ae3 +0, 548352, 548352, 1152, 2304, 0x9edf8594 +0, 549504, 549504, 1152, 2304, 0xd16382d5 +0, 550656, 550656, 1152, 2304, 0x6e838328 +0, 551808, 551808, 1152, 2304, 0xa1f697c1 +0, 552960, 552960, 1152, 2304, 0xefcc749c +0, 554112, 554112, 1152, 2304, 0x1f94839e +0, 555264, 555264, 1152, 2304, 0x429e7c5b +0, 556416, 556416, 1152, 2304, 0x9b59711c +0, 557568, 557568, 1152, 2304, 0xdac27323 +0, 558720, 558720, 1152, 2304, 0xa4856d2b +0, 559872, 559872, 1152, 2304, 0x07a37498 +0, 561024, 561024, 1152, 2304, 0xe1ce7512 +0, 562176, 562176, 1152, 2304, 0x15e182c3 +0, 563328, 563328, 1152, 2304, 0x0fa46b8c +0, 564480, 564480, 1152, 2304, 0xbdf07bfd +0, 565632, 565632, 1152, 2304, 0xe0238b2a +0, 566784, 566784, 1152, 2304, 0xab537267 +0, 567936, 567936, 1152, 2304, 0xd46b75f3 +0, 569088, 569088, 1152, 2304, 0xec73794b +0, 570240, 570240, 1152, 2304, 0x680580c1 +0, 571392, 571392, 1152, 2304, 0x1ace8f6c +0, 572544, 572544, 1152, 2304, 0x19d583ac +0, 573696, 573696, 1152, 2304, 0x4b6b8105 +0, 574848, 574848, 1152, 2304, 0x392a78b2 +0, 576000, 576000, 1152, 2304, 0xd3916dad +0, 577152, 577152, 1152, 2304, 0x569c7a75 +0, 578304, 578304, 1152, 2304, 0xf5ac814b +0, 579456, 579456, 1152, 2304, 0x18d77e98 +0, 580608, 580608, 1152, 2304, 0x007074ce +0, 581760, 581760, 1152, 2304, 0x0fe38373 +0, 582912, 582912, 1152, 2304, 0x5a967920 +0, 584064, 584064, 1152, 2304, 0x22167501 +0, 585216, 585216, 1152, 2304, 0xf0828cab +0, 586368, 586368, 1152, 2304, 0xaeec71b7 +0, 587520, 587520, 1152, 2304, 0xc47b62ff +0, 588672, 588672, 1152, 2304, 0xab688478 +0, 589824, 589824, 1152, 2304, 0xf35e7bd2 +0, 590976, 590976, 1152, 2304, 0x9cff763e +0, 592128, 592128, 1152, 2304, 0x59568dc8 +0, 593280, 593280, 1152, 2304, 0x51a278ac +0, 594432, 594432, 1152, 2304, 0xc08a6e68 +0, 595584, 595584, 1152, 2304, 0xd3067ef4 +0, 596736, 596736, 1152, 2304, 0x54767c49 +0, 597888, 597888, 1152, 2304, 0xf8ff8386 +0, 599040, 599040, 1152, 2304, 0xef267f63 +0, 600192, 600192, 1152, 2304, 0xe2537cd9 +0, 601344, 601344, 1152, 2304, 0x77a57680 +0, 602496, 602496, 1152, 2304, 0x325c74ad +0, 603648, 603648, 1152, 2304, 0xd7fe87c4 +0, 604800, 604800, 1152, 2304, 0x2e756310 +0, 605952, 605952, 1152, 2304, 0x6a81796b +0, 607104, 607104, 1152, 2304, 0x2f057daf +0, 608256, 608256, 1152, 2304, 0xcd9f7c9d +0, 609408, 609408, 1152, 2304, 0xc91560a0 +0, 610560, 610560, 1152, 2304, 0x962a91eb +0, 611712, 611712, 1152, 2304, 0xa0ff7416 +0, 612864, 612864, 1152, 2304, 0xcb5c7dff +0, 614016, 614016, 1152, 2304, 0xd3527041 +0, 615168, 615168, 1152, 2304, 0xc89d77c2 +0, 616320, 616320, 1152, 2304, 0xe1ce7ccf +0, 617472, 617472, 1152, 2304, 0xe3417c4c +0, 618624, 618624, 1152, 2304, 0x3f1a7166 +0, 619776, 619776, 1152, 2304, 0xcdcc7e23 +0, 620928, 620928, 1152, 2304, 0x4e727e97 +0, 622080, 622080, 1152, 2304, 0x53427ff1 +0, 623232, 623232, 1152, 2304, 0x173f6ca9 +0, 624384, 624384, 1152, 2304, 0x962887ec +0, 625536, 625536, 1152, 2304, 0xcbec67f4 +0, 626688, 626688, 1152, 2304, 0x7a2c943d +0, 627840, 627840, 1152, 2304, 0x8b877570 +0, 628992, 628992, 1152, 2304, 0xcf337323 +0, 630144, 630144, 1152, 2304, 0x8c8682a4 +0, 631296, 631296, 1152, 2304, 0x94c3753c +0, 632448, 632448, 1152, 2304, 0x86898d79 +0, 633600, 633600, 1152, 2304, 0xdf667312 +0, 634752, 634752, 1152, 2304, 0x062f8ba8 +0, 635904, 635904, 1152, 2304, 0xa2c36f08 +0, 637056, 637056, 1152, 2304, 0x5bca7358 +0, 638208, 638208, 1152, 2304, 0x5648804d +0, 639360, 639360, 1152, 2304, 0xefac87c8 +0, 640512, 640512, 1152, 2304, 0x66bf7dcf +0, 641664, 641664, 1152, 2304, 0x62ad73bc +0, 642816, 642816, 1152, 2304, 0x72fe630c +0, 643968, 643968, 1152, 2304, 0xeebe87da +0, 645120, 645120, 1152, 2304, 0x11c870cf +0, 646272, 646272, 1152, 2304, 0x18fb7c27 +0, 647424, 647424, 1152, 2304, 0x39047145 +0, 648576, 648576, 1152, 2304, 0xdcf07032 +0, 649728, 649728, 1152, 2304, 0x61027c50 +0, 650880, 650880, 1152, 2304, 0x6e2e89de +0, 652032, 652032, 1152, 2304, 0xc50c6d1d +0, 653184, 653184, 1152, 2304, 0xeed587ee +0, 654336, 654336, 1152, 2304, 0xe38269c7 +0, 655488, 655488, 1152, 2304, 0xcf66806e +0, 656640, 656640, 1152, 2304, 0x2d3b7c1b +0, 657792, 657792, 1152, 2304, 0xa4127d48 +0, 658944, 658944, 1152, 2304, 0x480b8325 +0, 660096, 660096, 1152, 2304, 0xc1527221 +0, 661248, 661248, 1152, 2304, 0x94c1769a +0, 662400, 662400, 1152, 2304, 0xcfb37271 +0, 663552, 663552, 1152, 2304, 0x946d7a96 +0, 664704, 664704, 1152, 2304, 0xdfc18e50 +0, 665856, 665856, 1152, 2304, 0x10c48393 +0, 667008, 667008, 1152, 2304, 0x58556b10 +0, 668160, 668160, 1152, 2304, 0x997b7993 +0, 669312, 669312, 1152, 2304, 0x4a787992 +0, 670464, 670464, 1152, 2304, 0x11406c20 +0, 671616, 671616, 1152, 2304, 0x04a4874a +0, 672768, 672768, 1152, 2304, 0xf3077164 +0, 673920, 673920, 1152, 2304, 0x08ac80e3 +0, 675072, 675072, 1152, 2304, 0x268370d0 +0, 676224, 676224, 1152, 2304, 0x1d137778 +0, 677376, 677376, 1152, 2304, 0xfa148e97 +0, 678528, 678528, 1152, 2304, 0xec50717c +0, 679680, 679680, 1152, 2304, 0xcbf46b75 +0, 680832, 680832, 1152, 2304, 0xd4168038 +0, 681984, 681984, 1152, 2304, 0xdd9577f0 +0, 683136, 683136, 1152, 2304, 0xc7077685 +0, 684288, 684288, 1152, 2304, 0x34d25e91 +0, 685440, 685440, 1152, 2304, 0x96537e6d +0, 686592, 686592, 1152, 2304, 0xb12e7940 +0, 687744, 687744, 1152, 2304, 0x861d64c0 +0, 688896, 688896, 1152, 2304, 0xa2bc64ed +0, 690048, 690048, 1152, 2304, 0x0c5f8261 +0, 691200, 691200, 1152, 2304, 0x540584ff +0, 692352, 692352, 1152, 2304, 0xe8328b09 +0, 693504, 693504, 1152, 2304, 0x1e777079 +0, 694656, 694656, 1152, 2304, 0x453483b4 +0, 695808, 695808, 1152, 2304, 0x1cab7a1e +0, 696960, 696960, 1152, 2304, 0xcb37856d +0, 698112, 698112, 1152, 2304, 0x5a4883ed +0, 699264, 699264, 1152, 2304, 0xd1f27cbf +0, 700416, 700416, 1152, 2304, 0x0d377a4d +0, 701568, 701568, 1152, 2304, 0x264e76df +0, 702720, 702720, 1152, 2304, 0x2a68771e +0, 703872, 703872, 1152, 2304, 0xcb317a31 +0, 705024, 705024, 1152, 2304, 0xfc5d7a27 +0, 706176, 706176, 1152, 2304, 0x6e067d96 +0, 707328, 707328, 1152, 2304, 0x0c538560 +0, 708480, 708480, 1152, 2304, 0xfbad717a +0, 709632, 709632, 1152, 2304, 0xf9fc7608 +0, 710784, 710784, 1152, 2304, 0xb1817c8f +0, 711936, 711936, 1152, 2304, 0x57c37f82 +0, 713088, 713088, 1152, 2304, 0x8cac8356 +0, 714240, 714240, 1152, 2304, 0x97108186 +0, 715392, 715392, 1152, 2304, 0x095d81bb +0, 716544, 716544, 1152, 2304, 0x475f6b2b +0, 717696, 717696, 1152, 2304, 0xdf7c8cc5 +0, 718848, 718848, 1152, 2304, 0x979c77be +0, 720000, 720000, 1152, 2304, 0x56a7844b +0, 721152, 721152, 1152, 2304, 0x7ee46b21 +0, 722304, 722304, 1152, 2304, 0x05b67220 +0, 723456, 723456, 1152, 2304, 0x25787252 +0, 724608, 724608, 1152, 2304, 0x8ad278ad +0, 725760, 725760, 1152, 2304, 0x67bd722e +0, 726912, 726912, 1152, 2304, 0x204f77be +0, 728064, 728064, 1152, 2304, 0x82d27ae2 +0, 729216, 729216, 1152, 2304, 0x23fa82e4 +0, 730368, 730368, 1152, 2304, 0xa9cf8159 +0, 731520, 731520, 1152, 2304, 0x13f08749 +0, 732672, 732672, 1152, 2304, 0xf84f71b5 +0, 733824, 733824, 1152, 2304, 0x1cb777c8 +0, 734976, 734976, 1152, 2304, 0x11236722 +0, 736128, 736128, 1152, 2304, 0x10197cac +0, 737280, 737280, 1152, 2304, 0xbd417e65 +0, 738432, 738432, 1152, 2304, 0x9a1c7d05 +0, 739584, 739584, 1152, 2304, 0x4c3a85de +0, 740736, 740736, 1152, 2304, 0x03816eb7 +0, 741888, 741888, 1152, 2304, 0x80186e6c +0, 743040, 743040, 1152, 2304, 0x5c097928 +0, 744192, 744192, 1152, 2304, 0x94aa823d +0, 745344, 745344, 1152, 2304, 0xa1c27f04 +0, 746496, 746496, 1152, 2304, 0x6ddb74a9 +0, 747648, 747648, 1152, 2304, 0x5ea67901 +0, 748800, 748800, 1152, 2304, 0xd710742d +0, 749952, 749952, 1152, 2304, 0xf8c27add +0, 751104, 751104, 1152, 2304, 0xf1717011 +0, 752256, 752256, 1152, 2304, 0xb59072d0 +0, 753408, 753408, 1152, 2304, 0xc8dc84a7 +0, 754560, 754560, 1152, 2304, 0x33116737 +0, 755712, 755712, 1152, 2304, 0x86216bdd +0, 756864, 756864, 1152, 2304, 0xa2f87866 +0, 758016, 758016, 1152, 2304, 0x5d77771e +0, 759168, 759168, 1152, 2304, 0x5d8c77fd +0, 760320, 760320, 1152, 2304, 0x23cc89cb +0, 761472, 761472, 1152, 2304, 0x334e7407 +0, 762624, 762624, 1152, 2304, 0x01c976ff +0, 763776, 763776, 1152, 2304, 0x3a3b7b15 +0, 764928, 764928, 1152, 2304, 0xfa427de9 +0, 766080, 766080, 1152, 2304, 0xbeaa7c91 +0, 767232, 767232, 1152, 2304, 0xd6988b31 +0, 768384, 768384, 1152, 2304, 0x4db47f80 +0, 769536, 769536, 1152, 2304, 0xea687d9e +0, 770688, 770688, 1152, 2304, 0x1a6281ce +0, 771840, 771840, 1152, 2304, 0xe1958003 +0, 772992, 772992, 1152, 2304, 0xb4ae7c5e +0, 774144, 774144, 1152, 2304, 0x28827c8a +0, 775296, 775296, 1152, 2304, 0x1fb88b25 +0, 776448, 776448, 1152, 2304, 0x588d71e8 +0, 777600, 777600, 1152, 2304, 0x68227c34 +0, 778752, 778752, 1152, 2304, 0xee4d73e8 +0, 779904, 779904, 1152, 2304, 0x69287c6d +0, 781056, 781056, 1152, 2304, 0xbb04926a +0, 782208, 782208, 1152, 2304, 0x89456cec +0, 783360, 783360, 1152, 2304, 0xabe18992 +0, 784512, 784512, 1152, 2304, 0x50cc7f6c +0, 785664, 785664, 1152, 2304, 0x6d7270be +0, 786816, 786816, 1152, 2304, 0x664c6fef +0, 787968, 787968, 1152, 2304, 0x7f7982f3 +0, 789120, 789120, 1152, 2304, 0x6ca170e9 +0, 790272, 790272, 1152, 2304, 0x36437d5b +0, 791424, 791424, 1152, 2304, 0xfd2380e8 +0, 792576, 792576, 1152, 2304, 0x2e3c6e9f +0, 793728, 793728, 1152, 2304, 0xc8427f3f +0, 794880, 794880, 1152, 2304, 0x962a79ad +0, 796032, 796032, 1152, 2304, 0xc9597c8b +0, 797184, 797184, 1152, 2304, 0x899580bb +0, 798336, 798336, 1152, 2304, 0x2d179dff +0, 799488, 799488, 1152, 2304, 0x4ac1707c +0, 800640, 800640, 1152, 2304, 0x32ea7e95 +0, 801792, 801792, 1152, 2304, 0x265e9a2d +0, 802944, 802944, 1152, 2304, 0x1c6484d0 +0, 804096, 804096, 1152, 2304, 0x39ae6884 +0, 805248, 805248, 1152, 2304, 0x82ed7bc5 +0, 806400, 806400, 1152, 2304, 0x556b7b3c +0, 807552, 807552, 1152, 2304, 0xb7f778dd +0, 808704, 808704, 1152, 2304, 0x74447d55 +0, 809856, 809856, 1152, 2304, 0x0c66861e +0, 811008, 811008, 1152, 2304, 0x15ba7932 +0, 812160, 812160, 1152, 2304, 0xb19170fc +0, 813312, 813312, 1152, 2304, 0x19d37551 +0, 814464, 814464, 1152, 2304, 0xdc529142 +0, 815616, 815616, 1152, 2304, 0xf2637e77 +0, 816768, 816768, 1152, 2304, 0xd065944b +0, 817920, 817920, 1152, 2304, 0x22878123 +0, 819072, 819072, 1152, 2304, 0xc21a8bf7 +0, 820224, 820224, 1152, 2304, 0x2e3582dc +0, 821376, 821376, 1152, 2304, 0xd42f7987 +0, 822528, 822528, 1152, 2304, 0x69b88236 +0, 823680, 823680, 1152, 2304, 0x7c988f90 +0, 824832, 824832, 1152, 2304, 0x2cd66ded +0, 825984, 825984, 1152, 2304, 0x3e65828b +0, 827136, 827136, 1152, 2304, 0x7e9871c9 +0, 828288, 828288, 1152, 2304, 0xf1f2806b +0, 829440, 829440, 1152, 2304, 0xf5087c7b +0, 830592, 830592, 1152, 2304, 0x62b98097 +0, 831744, 831744, 1152, 2304, 0xec457c43 +0, 832896, 832896, 1152, 2304, 0x87af87a6 +0, 834048, 834048, 1152, 2304, 0x97cc757d +0, 835200, 835200, 1152, 2304, 0x08ca76bd +0, 836352, 836352, 1152, 2304, 0x14ae7cbd +0, 837504, 837504, 1152, 2304, 0x1f79709a +0, 838656, 838656, 1152, 2304, 0x17948207 +0, 839808, 839808, 1152, 2304, 0x16ee7228 +0, 840960, 840960, 1152, 2304, 0x76cc82d7 +0, 842112, 842112, 1152, 2304, 0x8f327a8e +0, 843264, 843264, 1152, 2304, 0x14ee7756 +0, 844416, 844416, 1152, 2304, 0x15996d2f +0, 845568, 845568, 1152, 2304, 0x4c707d5c +0, 846720, 846720, 1152, 2304, 0x268c6fee +0, 847872, 847872, 1152, 2304, 0x6d838c76 +0, 849024, 849024, 1152, 2304, 0xafa17e64 +0, 850176, 850176, 1152, 2304, 0xb6546e66 +0, 851328, 851328, 1152, 2304, 0x945d8b9f +0, 852480, 852480, 1152, 2304, 0x5bfb7446 +0, 853632, 853632, 1152, 2304, 0xae6086f9 +0, 854784, 854784, 1152, 2304, 0xa01380cd +0, 855936, 855936, 1152, 2304, 0x06f0828f +0, 857088, 857088, 1152, 2304, 0x0ae07176 +0, 858240, 858240, 1152, 2304, 0x66f07522 +0, 859392, 859392, 1152, 2304, 0x44018106 +0, 860544, 860544, 1152, 2304, 0x8cd283da +0, 861696, 861696, 1152, 2304, 0x14257f45 +0, 862848, 862848, 1152, 2304, 0x04979537 +0, 864000, 864000, 1152, 2304, 0x8b5f797c +0, 865152, 865152, 1152, 2304, 0x12d67493 +0, 866304, 866304, 1152, 2304, 0xc8886a25 +0, 867456, 867456, 1152, 2304, 0x614b803a +0, 868608, 868608, 1152, 2304, 0x75667d35 +0, 869760, 869760, 1152, 2304, 0xe42c7b00 +0, 870912, 870912, 1152, 2304, 0x37787927 +0, 872064, 872064, 1152, 2304, 0x85db8409 +0, 873216, 873216, 1152, 2304, 0x823b822c +0, 874368, 874368, 1152, 2304, 0xa1658479 +0, 875520, 875520, 1152, 2304, 0xdbe58ff7 +0, 876672, 876672, 1152, 2304, 0x725175e2 +0, 877824, 877824, 1152, 2304, 0xb2ae7741 +0, 878976, 878976, 1152, 2304, 0x4de169e4 +0, 880128, 880128, 1152, 2304, 0x3cb18530 +0, 881280, 881280, 1152, 2304, 0x5a0c5e7b diff -Nru ffmpeg-4.2.2/tests/ref/fate/iff-byterun1 ffmpeg-4.4/tests/ref/fate/iff-byterun1 --- ffmpeg-4.2.2/tests/ref/fate/iff-byterun1 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/iff-byterun1 2021-04-08 21:28:40.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 5/6 -0, 0, 0, 0, 230400, 0x35e51c62 +0, 0, 0, 1, 230400, 0x35e51c62 diff -Nru ffmpeg-4.2.2/tests/ref/fate/iff-ilbm ffmpeg-4.4/tests/ref/fate/iff-ilbm --- ffmpeg-4.2.2/tests/ref/fate/iff-ilbm 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/iff-ilbm 2021-04-08 21:28:40.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 1/1 -0, 0, 0, 0, 230400, 0x0929e342 +0, 0, 0, 1, 230400, 0x0929e342 diff -Nru ffmpeg-4.2.2/tests/ref/fate/imgutils ffmpeg-4.4/tests/ref/fate/imgutils --- ffmpeg-4.2.2/tests/ref/fate/imgutils 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/imgutils 2021-04-08 21:28:40.000000000 +0000 @@ -53,3 +53,186 @@ 0000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000 + +yuv420p planes: 3, linesizes: 64 32 32 0, plane_sizes: 3072 768 768 0, plane_offsets: 3072 768 0, total_size: 4608 +yuyv422 planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +rgb24 planes: 1, linesizes: 192 0 0 0, plane_sizes: 9216 0 0 0, plane_offsets: 0 0 0, total_size: 9216 +bgr24 planes: 1, linesizes: 192 0 0 0, plane_sizes: 9216 0 0 0, plane_offsets: 0 0 0, total_size: 9216 +yuv422p planes: 3, linesizes: 64 32 32 0, plane_sizes: 3072 1536 1536 0, plane_offsets: 3072 1536 0, total_size: 6144 +yuv444p planes: 3, linesizes: 64 64 64 0, plane_sizes: 3072 3072 3072 0, plane_offsets: 3072 3072 0, total_size: 9216 +yuv410p planes: 3, linesizes: 64 16 16 0, plane_sizes: 3072 192 192 0, plane_offsets: 3072 192 0, total_size: 3456 +yuv411p planes: 3, linesizes: 64 16 16 0, plane_sizes: 3072 768 768 0, plane_offsets: 3072 768 0, total_size: 4608 +gray planes: 2, linesizes: 64 0 0 0, plane_sizes: 3072 1024 0 0, plane_offsets: 3072 0 0, total_size: 4096 +monow planes: 1, linesizes: 8 0 0 0, plane_sizes: 384 0 0 0, plane_offsets: 0 0 0, total_size: 384 +monob planes: 1, linesizes: 8 0 0 0, plane_sizes: 384 0 0 0, plane_offsets: 0 0 0, total_size: 384 +pal8 planes: 2, linesizes: 64 0 0 0, plane_sizes: 3072 1024 0 0, plane_offsets: 3072 0 0, total_size: 4096 +yuvj420p planes: 3, linesizes: 64 32 32 0, plane_sizes: 3072 768 768 0, plane_offsets: 3072 768 0, total_size: 4608 +yuvj422p planes: 3, linesizes: 64 32 32 0, plane_sizes: 3072 1536 1536 0, plane_offsets: 3072 1536 0, total_size: 6144 +yuvj444p planes: 3, linesizes: 64 64 64 0, plane_sizes: 3072 3072 3072 0, plane_offsets: 3072 3072 0, total_size: 9216 +uyvy422 planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +uyyvyy411 planes: 1, linesizes: 96 0 0 0, plane_sizes: 4608 0 0 0, plane_offsets: 0 0 0, total_size: 4608 +bgr8 planes: 2, linesizes: 64 0 0 0, plane_sizes: 3072 1024 0 0, plane_offsets: 3072 0 0, total_size: 4096 +bgr4 planes: 1, linesizes: 32 0 0 0, plane_sizes: 1536 0 0 0, plane_offsets: 0 0 0, total_size: 1536 +bgr4_byte planes: 2, linesizes: 64 0 0 0, plane_sizes: 3072 1024 0 0, plane_offsets: 3072 0 0, total_size: 4096 +rgb8 planes: 2, linesizes: 64 0 0 0, plane_sizes: 3072 1024 0 0, plane_offsets: 3072 0 0, total_size: 4096 +rgb4 planes: 1, linesizes: 32 0 0 0, plane_sizes: 1536 0 0 0, plane_offsets: 0 0 0, total_size: 1536 +rgb4_byte planes: 2, linesizes: 64 0 0 0, plane_sizes: 3072 1024 0 0, plane_offsets: 3072 0 0, total_size: 4096 +nv12 planes: 2, linesizes: 64 64 0 0, plane_sizes: 3072 1536 0 0, plane_offsets: 3072 0 0, total_size: 4608 +nv21 planes: 2, linesizes: 64 64 0 0, plane_sizes: 3072 1536 0 0, plane_offsets: 3072 0 0, total_size: 4608 +argb planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +rgba planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +abgr planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +bgra planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +gray16be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +gray16le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +yuv440p planes: 3, linesizes: 64 64 64 0, plane_sizes: 3072 1536 1536 0, plane_offsets: 3072 1536 0, total_size: 6144 +yuvj440p planes: 3, linesizes: 64 64 64 0, plane_sizes: 3072 1536 1536 0, plane_offsets: 3072 1536 0, total_size: 6144 +yuva420p planes: 4, linesizes: 64 32 32 64, plane_sizes: 3072 768 768 3072, plane_offsets: 3072 768 768, total_size: 7680 +rgb48be planes: 1, linesizes: 384 0 0 0, plane_sizes: 18432 0 0 0, plane_offsets: 0 0 0, total_size: 18432 +rgb48le planes: 1, linesizes: 384 0 0 0, plane_sizes: 18432 0 0 0, plane_offsets: 0 0 0, total_size: 18432 +rgb565be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +rgb565le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +rgb555be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +rgb555le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bgr565be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bgr565le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bgr555be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bgr555le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +yuv420p16le planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 1536 1536 0, plane_offsets: 6144 1536 0, total_size: 9216 +yuv420p16be planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 1536 1536 0, plane_offsets: 6144 1536 0, total_size: 9216 +yuv422p16le planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +yuv422p16be planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +yuv444p16le planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +yuv444p16be planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +rgb444le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +rgb444be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bgr444le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bgr444be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +ya8 planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bgr48be planes: 1, linesizes: 384 0 0 0, plane_sizes: 18432 0 0 0, plane_offsets: 0 0 0, total_size: 18432 +bgr48le planes: 1, linesizes: 384 0 0 0, plane_sizes: 18432 0 0 0, plane_offsets: 0 0 0, total_size: 18432 +yuv420p9be planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 1536 1536 0, plane_offsets: 6144 1536 0, total_size: 9216 +yuv420p9le planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 1536 1536 0, plane_offsets: 6144 1536 0, total_size: 9216 +yuv420p10be planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 1536 1536 0, plane_offsets: 6144 1536 0, total_size: 9216 +yuv420p10le planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 1536 1536 0, plane_offsets: 6144 1536 0, total_size: 9216 +yuv422p10be planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +yuv422p10le planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +yuv444p9be planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +yuv444p9le planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +yuv444p10be planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +yuv444p10le planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +yuv422p9be planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +yuv422p9le planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +gbrp planes: 3, linesizes: 64 64 64 0, plane_sizes: 3072 3072 3072 0, plane_offsets: 3072 3072 0, total_size: 9216 +gbrp9be planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +gbrp9le planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +gbrp10be planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +gbrp10le planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +gbrp16be planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +gbrp16le planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +yuva422p planes: 4, linesizes: 64 32 32 64, plane_sizes: 3072 1536 1536 3072, plane_offsets: 3072 1536 1536, total_size: 9216 +yuva444p planes: 4, linesizes: 64 64 64 64, plane_sizes: 3072 3072 3072 3072, plane_offsets: 3072 3072 3072, total_size: 12288 +yuva420p9be planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 1536 1536 6144, plane_offsets: 6144 1536 1536, total_size: 15360 +yuva420p9le planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 1536 1536 6144, plane_offsets: 6144 1536 1536, total_size: 15360 +yuva422p9be planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 3072 3072 6144, plane_offsets: 6144 3072 3072, total_size: 18432 +yuva422p9le planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 3072 3072 6144, plane_offsets: 6144 3072 3072, total_size: 18432 +yuva444p9be planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +yuva444p9le planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +yuva420p10be planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 1536 1536 6144, plane_offsets: 6144 1536 1536, total_size: 15360 +yuva420p10le planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 1536 1536 6144, plane_offsets: 6144 1536 1536, total_size: 15360 +yuva422p10be planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 3072 3072 6144, plane_offsets: 6144 3072 3072, total_size: 18432 +yuva422p10le planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 3072 3072 6144, plane_offsets: 6144 3072 3072, total_size: 18432 +yuva444p10be planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +yuva444p10le planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +yuva420p16be planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 1536 1536 6144, plane_offsets: 6144 1536 1536, total_size: 15360 +yuva420p16le planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 1536 1536 6144, plane_offsets: 6144 1536 1536, total_size: 15360 +yuva422p16be planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 3072 3072 6144, plane_offsets: 6144 3072 3072, total_size: 18432 +yuva422p16le planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 3072 3072 6144, plane_offsets: 6144 3072 3072, total_size: 18432 +yuva444p16be planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +yuva444p16le planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +xyz12le planes: 1, linesizes: 384 0 0 0, plane_sizes: 18432 0 0 0, plane_offsets: 0 0 0, total_size: 18432 +xyz12be planes: 1, linesizes: 384 0 0 0, plane_sizes: 18432 0 0 0, plane_offsets: 0 0 0, total_size: 18432 +nv16 planes: 2, linesizes: 64 64 0 0, plane_sizes: 3072 3072 0 0, plane_offsets: 3072 0 0, total_size: 6144 +nv20le planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 6144 0 0, plane_offsets: 6144 0 0, total_size: 12288 +nv20be planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 6144 0 0, plane_offsets: 6144 0 0, total_size: 12288 +rgba64be planes: 1, linesizes: 512 0 0 0, plane_sizes: 24576 0 0 0, plane_offsets: 0 0 0, total_size: 24576 +rgba64le planes: 1, linesizes: 512 0 0 0, plane_sizes: 24576 0 0 0, plane_offsets: 0 0 0, total_size: 24576 +bgra64be planes: 1, linesizes: 512 0 0 0, plane_sizes: 24576 0 0 0, plane_offsets: 0 0 0, total_size: 24576 +bgra64le planes: 1, linesizes: 512 0 0 0, plane_sizes: 24576 0 0 0, plane_offsets: 0 0 0, total_size: 24576 +yvyu422 planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +ya16be planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +ya16le planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +gbrap planes: 4, linesizes: 64 64 64 64, plane_sizes: 3072 3072 3072 3072, plane_offsets: 3072 3072 3072, total_size: 12288 +gbrap16be planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +gbrap16le planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +0rgb planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +rgb0 planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +0bgr planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +bgr0 planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +yuv420p12be planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 1536 1536 0, plane_offsets: 6144 1536 0, total_size: 9216 +yuv420p12le planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 1536 1536 0, plane_offsets: 6144 1536 0, total_size: 9216 +yuv420p14be planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 1536 1536 0, plane_offsets: 6144 1536 0, total_size: 9216 +yuv420p14le planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 1536 1536 0, plane_offsets: 6144 1536 0, total_size: 9216 +yuv422p12be planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +yuv422p12le planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +yuv422p14be planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +yuv422p14le planes: 3, linesizes: 128 64 64 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +yuv444p12be planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +yuv444p12le planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +yuv444p14be planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +yuv444p14le planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +gbrp12be planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +gbrp12le planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +gbrp14be planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +gbrp14le planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 6144 6144 0, plane_offsets: 6144 6144 0, total_size: 18432 +yuvj411p planes: 3, linesizes: 64 16 16 0, plane_sizes: 3072 768 768 0, plane_offsets: 3072 768 0, total_size: 4608 +bayer_bggr8 planes: 1, linesizes: 64 0 0 0, plane_sizes: 3072 0 0 0, plane_offsets: 0 0 0, total_size: 3072 +bayer_rggb8 planes: 1, linesizes: 64 0 0 0, plane_sizes: 3072 0 0 0, plane_offsets: 0 0 0, total_size: 3072 +bayer_gbrg8 planes: 1, linesizes: 64 0 0 0, plane_sizes: 3072 0 0 0, plane_offsets: 0 0 0, total_size: 3072 +bayer_grbg8 planes: 1, linesizes: 64 0 0 0, plane_sizes: 3072 0 0 0, plane_offsets: 0 0 0, total_size: 3072 +bayer_bggr16le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bayer_bggr16be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bayer_rggb16le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bayer_rggb16be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bayer_gbrg16le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bayer_gbrg16be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bayer_grbg16le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +bayer_grbg16be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +yuv440p10le planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +yuv440p10be planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +yuv440p12le planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +yuv440p12be planes: 3, linesizes: 128 128 128 0, plane_sizes: 6144 3072 3072 0, plane_offsets: 6144 3072 0, total_size: 12288 +ayuv64le planes: 1, linesizes: 512 0 0 0, plane_sizes: 24576 0 0 0, plane_offsets: 0 0 0, total_size: 24576 +ayuv64be planes: 1, linesizes: 512 0 0 0, plane_sizes: 24576 0 0 0, plane_offsets: 0 0 0, total_size: 24576 +p010le planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 3072 0 0, plane_offsets: 6144 0 0, total_size: 9216 +p010be planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 3072 0 0, plane_offsets: 6144 0 0, total_size: 9216 +gbrap12be planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +gbrap12le planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +gbrap10be planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +gbrap10le planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +gray12be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +gray12le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +gray10be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +gray10le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +p016le planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 3072 0 0, plane_offsets: 6144 0 0, total_size: 9216 +p016be planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 3072 0 0, plane_offsets: 6144 0 0, total_size: 9216 +gray9be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +gray9le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +gbrpf32be planes: 3, linesizes: 256 256 256 0, plane_sizes: 12288 12288 12288 0, plane_offsets: 12288 12288 0, total_size: 36864 +gbrpf32le planes: 3, linesizes: 256 256 256 0, plane_sizes: 12288 12288 12288 0, plane_offsets: 12288 12288 0, total_size: 36864 +gbrapf32be planes: 4, linesizes: 256 256 256 256, plane_sizes: 12288 12288 12288 12288, plane_offsets: 12288 12288 12288, total_size: 49152 +gbrapf32le planes: 4, linesizes: 256 256 256 256, plane_sizes: 12288 12288 12288 12288, plane_offsets: 12288 12288 12288, total_size: 49152 +gray14be planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +gray14le planes: 1, linesizes: 128 0 0 0, plane_sizes: 6144 0 0 0, plane_offsets: 0 0 0, total_size: 6144 +grayf32be planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +grayf32le planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +yuva422p12be planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 3072 3072 6144, plane_offsets: 6144 3072 3072, total_size: 18432 +yuva422p12le planes: 4, linesizes: 128 64 64 128, plane_sizes: 6144 3072 3072 6144, plane_offsets: 6144 3072 3072, total_size: 18432 +yuva444p12be planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +yuva444p12le planes: 4, linesizes: 128 128 128 128, plane_sizes: 6144 6144 6144 6144, plane_offsets: 6144 6144 6144, total_size: 24576 +nv24 planes: 2, linesizes: 64 128 0 0, plane_sizes: 3072 6144 0 0, plane_offsets: 3072 0 0, total_size: 9216 +nv42 planes: 2, linesizes: 64 128 0 0, plane_sizes: 3072 6144 0 0, plane_offsets: 3072 0 0, total_size: 9216 +y210be planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +y210le planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +x2rgb10le planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +x2rgb10be planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 diff -Nru ffmpeg-4.2.2/tests/ref/fate/iv8-demux ffmpeg-4.4/tests/ref/fate/iv8-demux --- ffmpeg-4.2.2/tests/ref/fate/iv8-demux 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/iv8-demux 2021-04-08 21:28:40.000000000 +0000 @@ -4,28 +4,28 @@ #codec_id 0: mpeg4 #dimensions 0: 704x576 #sar 0: 1/1 -0, 0, 0, 0, 20883, 0x347191e2 -0, 3600, 3600, 0, 20882, 0xe1573905 -0, 7200, 7200, 0, 20894, 0xd54f516a -0, 10800, 10800, 0, 20891, 0x1b5c5039 -0, 14400, 14400, 0, 20883, 0x8e785b4d -0, 18000, 18000, 0, 20870, 0xd26ca1f6 -0, 21600, 21600, 0, 21448, 0x946f5b2b -0, 25200, 25200, 0, 21433, 0xb18687c5 -0, 28800, 28800, 0, 20865, 0xc0eb3fce -0, 32399, 32399, 0, 20842, 0x9d0728ba -0, 35999, 35999, 0, 20878, 0xf60f5dee -0, 39600, 39600, 0, 20866, 0x3bde568f -0, 43200, 43200, 0, 20884, 0x22736993 -0, 46800, 46800, 0, 20860, 0xf56f2fca -0, 50400, 50400, 0, 20872, 0xf39e3cb3 -0, 53999, 53999, 0, 20835, 0xa3c4363b -0, 57600, 57600, 0, 20905, 0x552853d1 -0, 61200, 61200, 0, 20874, 0xed0b91ec -0, 64799, 64799, 0, 20877, 0xe1623e01 -0, 68399, 68399, 0, 20933, 0x19906564 -0, 72000, 72000, 0, 20891, 0x3d064fd3 -0, 75600, 75600, 0, 20834, 0xcb774dbc -0, 79200, 79200, 0, 20870, 0xbc536589 -0, 82800, 82800, 0, 21421, 0xc99a68e4 -0, 86400, 86400, 0, 12869, 0x5684e304 +0, 0, 0, 3600, 20883, 0x347191e2 +0, 3600, 3600, 3600, 20882, 0xe1573905 +0, 7200, 7200, 3600, 20894, 0xd54f516a +0, 10800, 10800, 3600, 20891, 0x1b5c5039 +0, 14400, 14400, 3600, 20883, 0x8e785b4d +0, 18000, 18000, 3600, 20870, 0xd26ca1f6 +0, 21600, 21600, 3600, 21448, 0x946f5b2b +0, 25200, 25200, 3600, 21433, 0xb18687c5 +0, 28800, 28800, 3600, 20865, 0xc0eb3fce +0, 32399, 32399, 3600, 20842, 0x9d0728ba +0, 35999, 35999, 3600, 20878, 0xf60f5dee +0, 39600, 39600, 3600, 20866, 0x3bde568f +0, 43200, 43200, 3600, 20884, 0x22736993 +0, 46800, 46800, 3600, 20860, 0xf56f2fca +0, 50400, 50400, 3600, 20872, 0xf39e3cb3 +0, 53999, 53999, 3600, 20835, 0xa3c4363b +0, 57600, 57600, 3600, 20905, 0x552853d1 +0, 61200, 61200, 3600, 20874, 0xed0b91ec +0, 64799, 64799, 3600, 20877, 0xe1623e01 +0, 68399, 68399, 3600, 20933, 0x19906564 +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, 86400, 86400, 3600, 12869, 0x5684e304 diff -Nru ffmpeg-4.2.2/tests/ref/fate/lagarith-ticket4119-drop ffmpeg-4.4/tests/ref/fate/lagarith-ticket4119-drop --- ffmpeg-4.2.2/tests/ref/fate/lagarith-ticket4119-drop 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/lagarith-ticket4119-drop 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#tb 0: 1/25 -#media_type 0: video -#codec_id 0: rawvideo -#dimensions 0: 640x360 -#sar 0: 0/1 -0, 0, 0, 1, 691200, 0x00000000 -0, 1, 1, 1, 691200, 0x1c4a6f24 -0, 2, 2, 1, 691200, 0x1fa0474c diff -Nru ffmpeg-4.2.2/tests/ref/fate/libavcodec-options ffmpeg-4.4/tests/ref/fate/libavcodec-options --- ffmpeg-4.2.2/tests/ref/fate/libavcodec-options 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/libavcodec-options 1970-01-01 00:00:00.000000000 +0000 @@ -1,161 +0,0 @@ -testing avcodec_copy_context() -dummy_v1_codec -> dummy_v1_codec -closed: -dummy_v1_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v1_codec: 128x128 prv: set opts: 1500100900 i'm src default value -opened: -dummy_v1_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v1_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v1_codec -> dummy_v2_codec -closed: -dummy_v1_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v2_codec: 128x128 prv: set opts: 667 i'm dest value before copy -opened: -dummy_v1_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v2_codec: 128x128 prv: set opts: 667 i'm dest value before copy -dummy_v1_codec -> dummy_v3_codec -closed: -dummy_v1_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v3_codec: 128x128 prv: set -opened: -dummy_v1_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v3_codec: 128x128 prv: set -dummy_v1_codec -> dummy_v4_codec -closed: -dummy_v1_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v4_codec: 128x128 prv: null -opened: -dummy_v1_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v4_codec: 128x128 prv: null -dummy_v1_codec -> NULL -closed: -dummy_v1_codec: 128x128 prv: set opts: 1500100900 i'm src default value -NULL : 128x128 prv: null -opened: -dummy_v1_codec: 128x128 prv: set opts: 1500100900 i'm src default value -NULL : 128x128 prv: null -dummy_v2_codec -> dummy_v1_codec -closed: -dummy_v2_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v1_codec: 128x128 prv: set opts: 667 i'm dest value before copy -opened: -dummy_v2_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v1_codec: 128x128 prv: set opts: 667 i'm dest value before copy -dummy_v2_codec -> dummy_v2_codec -closed: -dummy_v2_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v2_codec: 128x128 prv: set opts: 1500100900 i'm src default value -opened: -dummy_v2_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v2_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v2_codec -> dummy_v3_codec -closed: -dummy_v2_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v3_codec: 128x128 prv: set -opened: -dummy_v2_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v3_codec: 128x128 prv: set -dummy_v2_codec -> dummy_v4_codec -closed: -dummy_v2_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v4_codec: 128x128 prv: null -opened: -dummy_v2_codec: 128x128 prv: set opts: 1500100900 i'm src default value -dummy_v4_codec: 128x128 prv: null -dummy_v2_codec -> NULL -closed: -dummy_v2_codec: 128x128 prv: set opts: 1500100900 i'm src default value -NULL : 128x128 prv: null -opened: -dummy_v2_codec: 128x128 prv: set opts: 1500100900 i'm src default value -NULL : 128x128 prv: null -dummy_v3_codec -> dummy_v1_codec -closed: -dummy_v3_codec: 128x128 prv: set -dummy_v1_codec: 128x128 prv: set opts: 667 i'm dest value before copy -opened: -dummy_v3_codec: 128x128 prv: set -dummy_v1_codec: 128x128 prv: set opts: 667 i'm dest value before copy -dummy_v3_codec -> dummy_v2_codec -closed: -dummy_v3_codec: 128x128 prv: set -dummy_v2_codec: 128x128 prv: set opts: 667 i'm dest value before copy -opened: -dummy_v3_codec: 128x128 prv: set -dummy_v2_codec: 128x128 prv: set opts: 667 i'm dest value before copy -dummy_v3_codec -> dummy_v3_codec -closed: -dummy_v3_codec: 128x128 prv: set -dummy_v3_codec: 128x128 prv: set -opened: -dummy_v3_codec: 128x128 prv: set -dummy_v3_codec: 128x128 prv: set -dummy_v3_codec -> dummy_v4_codec -closed: -dummy_v3_codec: 128x128 prv: set -dummy_v4_codec: 128x128 prv: null -opened: -dummy_v3_codec: 128x128 prv: set -dummy_v4_codec: 128x128 prv: null -dummy_v3_codec -> NULL -closed: -dummy_v3_codec: 128x128 prv: set -NULL : 128x128 prv: null -opened: -dummy_v3_codec: 128x128 prv: set -NULL : 128x128 prv: null -dummy_v4_codec -> dummy_v1_codec -closed: -dummy_v4_codec: 128x128 prv: null -dummy_v1_codec: 128x128 prv: set opts: 667 i'm dest value before copy -opened: -dummy_v4_codec: 128x128 prv: null -dummy_v1_codec: 128x128 prv: set opts: 667 i'm dest value before copy -dummy_v4_codec -> dummy_v2_codec -closed: -dummy_v4_codec: 128x128 prv: null -dummy_v2_codec: 128x128 prv: set opts: 667 i'm dest value before copy -opened: -dummy_v4_codec: 128x128 prv: null -dummy_v2_codec: 128x128 prv: set opts: 667 i'm dest value before copy -dummy_v4_codec -> dummy_v3_codec -closed: -dummy_v4_codec: 128x128 prv: null -dummy_v3_codec: 128x128 prv: set -opened: -dummy_v4_codec: 128x128 prv: null -dummy_v3_codec: 128x128 prv: set -dummy_v4_codec -> dummy_v4_codec -closed: -dummy_v4_codec: 128x128 prv: null -dummy_v4_codec: 128x128 prv: null -opened: -dummy_v4_codec: 128x128 prv: null -dummy_v4_codec: 128x128 prv: null -dummy_v4_codec -> NULL -closed: -dummy_v4_codec: 128x128 prv: null -NULL : 128x128 prv: null -opened: -dummy_v4_codec: 128x128 prv: null -NULL : 128x128 prv: null -NULL -> dummy_v1_codec -closed: -NULL : 128x128 prv: null -dummy_v1_codec: 128x128 prv: set opts: 667 i'm dest value before copy -NULL -> dummy_v2_codec -closed: -NULL : 128x128 prv: null -dummy_v2_codec: 128x128 prv: set opts: 667 i'm dest value before copy -NULL -> dummy_v3_codec -closed: -NULL : 128x128 prv: null -dummy_v3_codec: 128x128 prv: set -NULL -> dummy_v4_codec -closed: -NULL : 128x128 prv: null -dummy_v4_codec: 128x128 prv: null -NULL -> NULL -closed: -NULL : 128x128 prv: null -NULL : 128x128 prv: null diff -Nru ffmpeg-4.2.2/tests/ref/fate/lossless-truehd-5.1 ffmpeg-4.4/tests/ref/fate/lossless-truehd-5.1 --- ffmpeg-4.2.2/tests/ref/fate/lossless-truehd-5.1 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/lossless-truehd-5.1 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -95d8aac39dd9f0d7fb83dc7b6f88df35 diff -Nru ffmpeg-4.2.2/tests/ref/fate/lossless-truehd-5.1-downmix-2.0 ffmpeg-4.4/tests/ref/fate/lossless-truehd-5.1-downmix-2.0 --- ffmpeg-4.2.2/tests/ref/fate/lossless-truehd-5.1-downmix-2.0 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/lossless-truehd-5.1-downmix-2.0 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -a269aee0051d4400c9117136f08c9767 diff -Nru ffmpeg-4.2.2/tests/ref/fate/lscr ffmpeg-4.4/tests/ref/fate/lscr --- ffmpeg-4.2.2/tests/ref/fate/lscr 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/lscr 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,21 @@ +#tb 0: 100/2397 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 0/1 +0, 0, 0, 1, 230400, 0x07c93bd9 +0, 1, 1, 1, 230400, 0xdcacc274 +0, 2, 2, 1, 230400, 0x6115dc34 +0, 3, 3, 1, 230400, 0x7317f35c +0, 4, 4, 1, 230400, 0xca18d9a6 +0, 5, 5, 1, 230400, 0x0c104d49 +0, 6, 6, 1, 230400, 0xc4c415cf +0, 7, 7, 1, 230400, 0xd1e4149f +0, 8, 8, 1, 230400, 0x5973ae25 +0, 9, 9, 1, 230400, 0xd77893e6 +0, 10, 10, 1, 230400, 0x7f9cac97 +0, 11, 11, 1, 230400, 0xc8f81940 +0, 12, 12, 1, 230400, 0xa2b6f5d4 +0, 13, 13, 1, 230400, 0x620c3222 +0, 14, 14, 1, 230400, 0x60d097a0 +0, 15, 15, 1, 230400, 0x47201c65 diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-flac-channel-mapping ffmpeg-4.4/tests/ref/fate/matroska-flac-channel-mapping --- ffmpeg-4.2.2/tests/ref/fate/matroska-flac-channel-mapping 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-flac-channel-mapping 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,38 @@ +#extradata 0: 34, 0x7a7909e5 +#extradata 1: 34, 0x7a7909e5 +#tb 0: 651/31250000 +#media_type 0: audio +#codec_id 0: flac +#sample_rate 0: 48000 +#channel_layout 0: 3f +#channel_layout_name 0: 5.1 +#tb 1: 651/31250000 +#media_type 1: audio +#codec_id 1: flac +#sample_rate 1: 48000 +#channel_layout 1: 60f +#channel_layout_name 1: 5.1(side) +0, 0, 0, 4096, 26, 0x50f80431 +1, 0, 0, 4096, 26, 0x50f80431 +0, 4096, 4096, 4096, 26, 0x50d30416 +1, 4096, 4096, 4096, 26, 0x50d30416 +0, 8192, 8192, 4096, 26, 0x51ee046f +1, 8192, 8192, 4096, 26, 0x51ee046f +0, 12288, 12288, 4096, 26, 0x521d0458 +1, 12288, 12288, 4096, 26, 0x521d0458 +0, 16385, 16385, 4096, 26, 0x531c043d +1, 16385, 16385, 4096, 26, 0x531c043d +0, 20481, 20481, 4096, 26, 0x53cf0442 +1, 20481, 20481, 4096, 26, 0x53cf0442 +0, 24577, 24577, 4096, 26, 0x536a0473 +1, 24577, 24577, 4096, 26, 0x536a0473 +0, 28673, 28673, 4096, 26, 0x5321046c +1, 28673, 28673, 4096, 26, 0x5321046c +0, 32770, 32770, 4096, 26, 0x51b00449 +1, 32770, 32770, 4096, 26, 0x51b00449 +0, 36866, 36866, 4096, 26, 0x518b042e +1, 36866, 36866, 4096, 26, 0x518b042e +0, 40962, 40962, 4096, 26, 0x50f60447 +1, 40962, 40962, 4096, 26, 0x50f60447 +0, 45059, 45059, 3072, 28, 0x72540504 +1, 45059, 45059, 3072, 28, 0x72540504 diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-flac-extradata-update ffmpeg-4.4/tests/ref/fate/matroska-flac-extradata-update --- ffmpeg-4.2.2/tests/ref/fate/matroska-flac-extradata-update 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-flac-extradata-update 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,53 @@ +3c721898cf2cf3e2e6c43ad58952bd2d *tests/data/fate/matroska-flac-extradata-update.matroska +2032 tests/data/fate/matroska-flac-extradata-update.matroska +#extradata 0: 34, 0x7acb09e7 +#extradata 1: 34, 0x7acb09e7 +#extradata 2: 34, 0x443402dd +#tb 0: 1/1000 +#media_type 0: audio +#codec_id 0: flac +#sample_rate 0: 48000 +#channel_layout 0: 3f +#channel_layout_name 0: 5.1 +#tb 1: 1/1000 +#media_type 1: audio +#codec_id 1: flac +#sample_rate 1: 48000 +#channel_layout 1: 60f +#channel_layout_name 1: 5.1(side) +#tb 2: 1/1000 +#media_type 2: audio +#codec_id 2: flac +#sample_rate 2: 48000 +#channel_layout 2: 3f +#channel_layout_name 2: 5.1 +0, 0, 0, 96, 26, 0x4e160341 +1, 0, 0, 96, 26, 0x4e160341 +2, 0, 0, 96, 26, 0x4e160341 +0, 96, 96, 96, 26, 0x4e17035c +1, 96, 96, 96, 26, 0x4e17035c +2, 96, 96, 96, 26, 0x4e17035c +0, 192, 192, 96, 26, 0x4de40383 +1, 192, 192, 96, 26, 0x4de40383 +2, 192, 192, 96, 26, 0x4de40383 +0, 288, 288, 96, 26, 0x4e3903a2 +1, 288, 288, 96, 26, 0x4e3903a2 +2, 288, 288, 96, 26, 0x4e3903a2 +0, 384, 384, 96, 26, 0x4f9a03d5 +1, 384, 384, 96, 26, 0x4f9a03d5 +2, 384, 384, 96, 26, 0x4f9a03d5 +0, 480, 480, 96, 26, 0x501303e0 +1, 480, 480, 96, 26, 0x501303e0 +2, 480, 480, 96, 26, 0x501303e0 +0, 576, 576, 96, 26, 0x5160042f +1, 576, 576, 96, 26, 0x5160042f +2, 576, 576, 96, 26, 0x5160042f +0, 672, 672, 96, 26, 0x50dd042e +1, 672, 672, 96, 26, 0x50dd042e +2, 672, 672, 96, 26, 0x50dd042e +0, 768, 768, 96, 26, 0x53de0499 +1, 768, 768, 96, 26, 0x53de0499 +0, 864, 864, 96, 26, 0x53df04b4 +1, 864, 864, 96, 26, 0x53df04b4 +0, 960, 960, 42, 26, 0x5740044b +1, 960, 960, 42, 26, 0x5740044b diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-lzo-decompression ffmpeg-4.4/tests/ref/fate/matroska-lzo-decompression --- ffmpeg-4.2.2/tests/ref/fate/matroska-lzo-decompression 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-lzo-decompression 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,10 @@ +#tb 0: 11337/500000000 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout 0: 3 +#channel_layout_name 0: stereo +0, 0, 0, 4096, 16384, 0x00000000 +0, 4096, 4096, 4096, 16384, 0xad7eebf4 +0, 8192, 8192, 4096, 16384, 0x1d1ff9d9 +0, 12288, 12288, 4097, 16384, 0xf1d9e2e2 diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-mastering-display-metadata ffmpeg-4.4/tests/ref/fate/matroska-mastering-display-metadata --- ffmpeg-4.2.2/tests/ref/fate/matroska-mastering-display-metadata 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-mastering-display-metadata 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,97 @@ +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 +#media_type 0: video +#codec_id 0: prores +#dimensions 0: 1280x720 +#sar 0: 1/1 +#tb 1: 1/1000 +#media_type 1: audio +#codec_id 1: pcm_s24le +#sample_rate 1: 48000 +#channel_layout 1: 4 +#channel_layout_name 1: mono +#tb 2: 1/1000 +#media_type 2: audio +#codec_id 2: pcm_s16be +#sample_rate 2: 48000 +#channel_layout 2: 4 +#channel_layout_name 2: mono +#tb 3: 1/1000 +#media_type 3: video +#codec_id 3: ffv1 +#dimensions 3: 1280x720 +#sar 3: 1/1 +0, 0, 0, 16, 57008, 0x43416399, S=2, 8, 0x08e5014f, 88, 0xd65a04db +1, 0, 0, 16, 2403, 0xaa818522 +3, 0, 0, 16, 274117, 0xc439610f, S=2, 8, 0x08e5014f, 88, 0xd65a04db +0, 17, 17, 16, 57248, 0xa06cd7b5 +1, 17, 17, 16, 2403, 0xe1a991e5 +2, 17, 17, 16, 1602, 0x5d868171 +3, 17, 17, 16, 273691, 0x5a3b88a5, F=0x0 +0, 33, 33, 16, 57200, 0x5623da10 +1, 33, 33, 16, 2400, 0x6650907f +2, 33, 33, 16, 1600, 0xa90f0044 +3, 33, 33, 16, 272987, 0x48c443e7, F=0x0 +0, 50, 50, 16, 57152, 0x52d89d3f +1, 50, 50, 16, 2403, 0x43398a08 +2, 50, 50, 16, 1602, 0x3a350084 +3, 50, 50, 16, 271465, 0x251b9cbe, F=0x0 +0, 67, 67, 16, 56960, 0x431d5189 +1, 67, 67, 16, 2403, 0x61cd96cb +2, 67, 67, 16, 1602, 0xd74800c6 +3, 67, 67, 16, 270800, 0x8fb2e217, F=0x0 +[STREAM] +index=0 +codec_name=prores +[SIDE_DATA] +side_data_type=Content light level metadata +max_content=1000 +max_average=100 +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Mastering display metadata +red_x=17/25 +red_y=8/25 +green_x=53/200 +green_y=69/100 +blue_x=3/20 +blue_y=3/50 +white_point_x=3127/10000 +white_point_y=329/1000 +min_luminance=0/1 +max_luminance=1000/1 +[/SIDE_DATA] +[/STREAM] +[STREAM] +index=1 +codec_name=pcm_s24le +[/STREAM] +[STREAM] +index=2 +codec_name=pcm_s16be +[/STREAM] +[STREAM] +index=3 +codec_name=ffv1 +[SIDE_DATA] +side_data_type=Content light level metadata +max_content=1000 +max_average=100 +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Mastering display metadata +red_x=17/25 +red_y=8/25 +green_x=53/200 +green_y=69/100 +blue_x=3/20 +blue_y=3/50 +white_point_x=3127/10000 +white_point_y=329/1000 +min_luminance=0/1 +max_luminance=1000/1 +[/SIDE_DATA] +[/STREAM] diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-mpegts-remux ffmpeg-4.4/tests/ref/fate/matroska-mpegts-remux --- ffmpeg-4.2.2/tests/ref/fate/matroska-mpegts-remux 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-mpegts-remux 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,52 @@ +4e6253c1f5f96ff64ae855dea426547d *tests/data/fate/matroska-mpegts-remux.matroska +6509 tests/data/fate/matroska-mpegts-remux.matroska +#tb 0: 1/1000 +#media_type 0: audio +#codec_id 0: ac3 +#sample_rate 0: 48000 +#channel_layout 0: 3 +#channel_layout_name 0: stereo +#tb 1: 1/1000 +#media_type 1: audio +#codec_id 1: ac3 +#sample_rate 1: 48000 +#channel_layout 1: 3 +#channel_layout_name 1: stereo +0, 0, 0, 32, 768, 0xa63778d4 +1, 0, 0, 32, 768, 0xa63778d4 +0, 32, 32, 32, 768, 0x7d577f3f +1, 32, 32, 32, 768, 0x7d577f3f +0, 64, 64, 32, 768, 0xd86b7c8f +1, 64, 64, 32, 768, 0xd86b7c8f +0, 96, 96, 32, 626, 0x09f4382f +1, 96, 96, 32, 626, 0x09f4382f +[STREAM] +index=0 +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=1 +DISPOSITION:clean_effects=0 +DISPOSITION:attached_pic=0 +DISPOSITION:timed_thumbnails=0 +[/STREAM] +[STREAM] +index=1 +DISPOSITION:default=0 +DISPOSITION:dub=0 +DISPOSITION:original=0 +DISPOSITION:comment=0 +DISPOSITION:lyrics=0 +DISPOSITION:karaoke=0 +DISPOSITION:forced=0 +DISPOSITION:hearing_impaired=1 +DISPOSITION:visual_impaired=0 +DISPOSITION:clean_effects=0 +DISPOSITION:attached_pic=0 +DISPOSITION:timed_thumbnails=0 +[/STREAM] diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-prores-header-insertion-bz2 ffmpeg-4.4/tests/ref/fate/matroska-prores-header-insertion-bz2 --- ffmpeg-4.2.2/tests/ref/fate/matroska-prores-header-insertion-bz2 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-prores-header-insertion-bz2 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,16 @@ +#extradata 0: 4, 0x0402019c +#extradata 1: 4, 0x0402019c +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: prores +#dimensions 0: 720x480 +#sar 0: 186/157 +#tb 1: 1/1000 +#media_type 1: video +#codec_id 1: prores +#dimensions 1: 720x480 +#sar 1: 186/157 +0, 0, 0, 0, 4304, 0x3625b1fc +1, 0, 0, 0, 4304, 0x3625b1fc +0, 42, 42, 0, 4304, 0x3625b1fc +1, 42, 42, 0, 4304, 0x3625b1fc diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-prores-zlib ffmpeg-4.4/tests/ref/fate/matroska-prores-zlib --- ffmpeg-4.2.2/tests/ref/fate/matroska-prores-zlib 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-prores-zlib 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,8 @@ +#extradata 0: 4, 0x040801a2 +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: prores +#dimensions 0: 1920x1080 +#sar 0: 1/1 +0, 0, 0, 33, 82240, 0x5271abe6 +0, 33, 33, 33, 82240, 0x5271abe6 diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-spherical-mono-remux ffmpeg-4.4/tests/ref/fate/matroska-spherical-mono-remux --- ffmpeg-4.2.2/tests/ref/fate/matroska-spherical-mono-remux 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-spherical-mono-remux 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,66 @@ +9176856edc1ff2b401e323f422fd8e78 *tests/data/fate/matroska-spherical-mono-remux.matroska +161583 tests/data/fate/matroska-spherical-mono-remux.matroska +#extradata 0: 43, 0x2b0e0d7b +#extradata 1: 43, 0x2b0e0d7b +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: h264 +#dimensions 0: 1920x1080 +#sar 0: 0/1 +#tb 1: 1/1000 +#media_type 1: video +#codec_id 1: h264 +#dimensions 1: 1920x1080 +#sar 1: 0/1 +0, -80, 0, 40, 69118, 0x73cb52f0, S=2, 12, 0x00000000, 36, 0x2cf8035c +1, -80, 0, 40, 69118, 0x73cb52f0, S=2, 12, 0x00000000, 36, 0x2cf8035c +0, -40, 160, 40, 1103, 0x082a059f, F=0x0 +1, -40, 160, 40, 1103, 0x082a059f, F=0x0 +[STREAM] +color_range=unknown +color_space=unknown +color_transfer=unknown +color_primaries=unknown +DISPOSITION:default=0 +DISPOSITION:forced=1 +[SIDE_DATA] +side_data_type=Stereo 3D +type=2D +inverted=0 +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Spherical Mapping +projection=tiled equirectangular +bound_left=148 +bound_top=73 +bound_right=147 +bound_bottom=72 +yaw=45 +pitch=30 +roll=15 +[/SIDE_DATA] +[/STREAM] +[STREAM] +color_range=pc +color_space=bt2020c +color_transfer=smpte170m +color_primaries=bt709 +DISPOSITION:default=0 +DISPOSITION:forced=0 +[SIDE_DATA] +side_data_type=Stereo 3D +type=2D +inverted=0 +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Spherical Mapping +projection=tiled equirectangular +bound_left=148 +bound_top=73 +bound_right=147 +bound_bottom=72 +yaw=45 +pitch=30 +roll=15 +[/SIDE_DATA] +[/STREAM] diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-vp8-alpha-remux ffmpeg-4.4/tests/ref/fate/matroska-vp8-alpha-remux --- ffmpeg-4.2.2/tests/ref/fate/matroska-vp8-alpha-remux 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-vp8-alpha-remux 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,33 @@ +d06be833da8e8d9d00bf334e0dfe8a58 *tests/data/fate/matroska-vp8-alpha-remux.matroska +237192 tests/data/fate/matroska-vp8-alpha-remux.matroska +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: vp8 +#dimensions 0: 320x213 +#sar 0: 1/1 +0, 0, 0, 33, 2108, 0x59b92a34, S=2, 1900, 0x8fb3adc5, 12, 0x00000000 +0, 32, 32, 33, 142, 0x2f2a3fed, F=0x0, S=1, 160, 0xa13346af +0, 65, 65, 33, 157, 0x17804767, F=0x0, S=1, 209, 0x64115f15 +0, 99, 99, 33, 206, 0x537262ca, F=0x0, S=1, 317, 0x44a09dd0 +0, 132, 132, 33, 259, 0x73ff74b6, F=0x0, S=1, 384, 0x2ee2c588 +0, 165, 165, 33, 320, 0x0fcf8ce4, F=0x0, S=1, 415, 0xff68c953 +0, 199, 199, 33, 377, 0x8fffb5f5, F=0x0, S=1, 475, 0x4166f3eb +[STREAM] +DISPOSITION:default=1 +DISPOSITION:dub=0 +DISPOSITION:original=0 +DISPOSITION:comment=0 +DISPOSITION:lyrics=0 +DISPOSITION:karaoke=0 +DISPOSITION:forced=0 +DISPOSITION:hearing_impaired=1 +DISPOSITION:visual_impaired=0 +DISPOSITION:clean_effects=0 +DISPOSITION:attached_pic=0 +DISPOSITION:timed_thumbnails=0 +[SIDE_DATA] +side_data_type=Stereo 3D +type=2D +inverted=0 +[/SIDE_DATA] +[/STREAM] diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-wavpack-missing-codecprivate ffmpeg-4.4/tests/ref/fate/matroska-wavpack-missing-codecprivate --- ffmpeg-4.2.2/tests/ref/fate/matroska-wavpack-missing-codecprivate 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-wavpack-missing-codecprivate 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,9 @@ +#extradata 0: 2, 0x00240014 +#tb 0: 11337/500000000 +#media_type 0: audio +#codec_id 0: wavpack +#sample_rate 0: 44100 +#channel_layout 0: 3 +#channel_layout_name 0: stereo +0, 0, 0, 22051, 14778, 0x02819286 +0, 22051, 22051, 22052, 14756, 0x21976243 diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-xiph-lacing ffmpeg-4.4/tests/ref/fate/matroska-xiph-lacing --- ffmpeg-4.2.2/tests/ref/fate/matroska-xiph-lacing 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-xiph-lacing 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,91 @@ +#extradata 0: 3766, 0xde3392f7 +#tb 0: 11337/500000000 +#media_type 0: audio +#codec_id 0: vorbis +#sample_rate 0: 44100 +#channel_layout 0: 3 +#channel_layout_name 0: stereo +0, 0, 0, 128, 84, 0x1beb2cc9 +0, 128, 128, 576, 533, 0xa5d425e9 +0, 704, 704, 1024, 505, 0x4b970e01 +0, 1728, 1728, 1024, 503, 0x8f4b0607 +0, 2752, 2752, 1024, 507, 0x546e0bc6 +0, 3776, 3776, 1024, 507, 0xe006103f +0, 4800, 4800, 1024, 502, 0xc7770a66 +0, 5824, 5824, 1024, 500, 0x89690d08 +0, 6785, 6785, 1024, 501, 0x47c50720 +0, 7809, 7809, 1024, 490, 0x4b5efd2d +0, 8833, 8833, 1024, 510, 0xa5110fdf +0, 9857, 9857, 576, 80, 0x6d1129bd +0, 10433, 10433, 128, 84, 0x18272cc1 +0, 10561, 10561, 128, 79, 0x7720262e +0, 10689, 10689, 128, 83, 0x5d1c2d22 +0, 10817, 10817, 128, 84, 0xbbdc2c28 +0, 10945, 10945, 128, 154, 0x2c41556c +0, 11073, 11073, 128, 148, 0xdd135006 +0, 11201, 11201, 128, 151, 0xf4b253b4 +0, 11329, 11329, 128, 91, 0x258a34b8 +0, 11457, 11457, 128, 79, 0x654923dc +0, 11585, 11585, 128, 88, 0xb3853007 +0, 11713, 11713, 128, 84, 0x33a72c00 +0, 11841, 11841, 128, 86, 0x38802c2f +0, 11969, 11969, 128, 155, 0x923253ce +0, 12097, 12097, 128, 138, 0x0d3a408d +0, 12225, 12225, 128, 140, 0x95ca470e +0, 12353, 12353, 576, 481, 0x6d6de7fd +0, 12929, 12929, 1024, 474, 0x74bee6fb +0, 13953, 13953, 1024, 446, 0x777be048 +0, 14977, 14977, 1024, 469, 0x9b49e7bd +0, 16001, 16001, 1024, 458, 0xb728df34 +0, 17025, 17025, 1024, 460, 0x1519e267 +0, 18049, 18049, 1024, 467, 0x391ff1ab +0, 19073, 19073, 1024, 464, 0x7b4ff249 +0, 20097, 20097, 576, 144, 0x9daa47e4 +0, 20673, 20673, 128, 151, 0xc8b24f08 +0, 20801, 20801, 128, 134, 0xfda444ec +0, 20929, 20929, 576, 428, 0x2ad8d2de +0, 21505, 21505, 576, 80, 0xcdf12536 +0, 22082, 22082, 128, 143, 0x935a4d4e +0, 22210, 22210, 128, 140, 0xb99a4ee5 +0, 22338, 22338, 128, 141, 0xf36954b9 +0, 22466, 22466, 128, 151, 0x13b9505c +0, 22594, 22594, 128, 142, 0xd8734a5f +0, 22722, 22722, 576, 465, 0x9e6ceade +0, 23298, 23298, 1024, 480, 0x6e98f308 +0, 24322, 24322, 1024, 465, 0xeecdeac4 +0, 25346, 25346, 1024, 464, 0x2a0cec3c +0, 26370, 26370, 1024, 487, 0xc66d0123 +0, 27394, 27394, 1024, 505, 0x0d1f0d85 +0, 28418, 28418, 1024, 479, 0x8d3af09e +0, 29442, 29442, 1024, 485, 0x4927fa6a +0, 30466, 30466, 1024, 483, 0x95c102a7 +0, 31490, 31490, 1024, 467, 0x7646ec5b +0, 32514, 32514, 1024, 492, 0x967505e9 +0, 33539, 33539, 1024, 491, 0x06670254 +0, 34563, 34563, 576, 76, 0x994e25d8 +0, 35139, 35139, 128, 84, 0xc8ba2a76 +0, 35267, 35267, 128, 90, 0x0008339a +0, 35395, 35395, 128, 84, 0x3d722790 +0, 35523, 35523, 128, 76, 0x3d5c23bf +0, 35651, 35651, 128, 82, 0x4cba28a1 +0, 35779, 35779, 128, 157, 0xf79058e2 +0, 35907, 35907, 128, 141, 0x72a24a6c +0, 36035, 36035, 576, 498, 0x5a200efb +0, 36611, 36611, 1024, 489, 0x135dfd19 +0, 37635, 37635, 1024, 509, 0x98580e17 +0, 38659, 38659, 1024, 508, 0x05851706 +0, 39683, 39683, 576, 89, 0xc7872e24 +0, 40259, 40259, 128, 87, 0x956e2e17 +0, 40387, 40387, 128, 91, 0x382e2fd0 +0, 40515, 40515, 128, 90, 0x6a6830f1 +0, 40643, 40643, 128, 88, 0xa50432da +0, 40771, 40771, 128, 85, 0xac5f30b2 +0, 40899, 40899, 128, 155, 0x4fa559da +0, 41027, 41027, 128, 154, 0x62535bad +0, 41155, 41155, 128, 155, 0x056c5a66 +0, 41283, 41283, 576, 499, 0xa19af50c +0, 41859, 41859, 1024, 495, 0xdd9c008b +0, 42883, 42883, 576, 83, 0x85722403 +0, 43459, 43459, 128, 155, 0x43ad5339 +0, 43587, 43587, 128, 144, 0x70804dd2 +0, 43715, 43715, 576, 480, 0x8b6101c7 diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-zero-length-block ffmpeg-4.4/tests/ref/fate/matroska-zero-length-block --- ffmpeg-4.2.2/tests/ref/fate/matroska-zero-length-block 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-zero-length-block 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,10 @@ +ba78b3e846d57002711bc481fa806717 *tests/data/fate/matroska-zero-length-block.matroska +643 tests/data/fate/matroska-zero-length-block.matroska +#tb 0: 1/1000 +#media_type 0: subtitle +#codec_id 0: subrip +0, 1000, 1000, 2000, 5, 0x05b801df +0, 3300, 3300, 3700, 16, 0x300705b2 +[STREAM] +TAG:DESCRIPTION=This track uses header removal compression and has a Block of size zero before reversing it. +[/STREAM] diff -Nru ffmpeg-4.2.2/tests/ref/fate/matroska-zlib-decompression ffmpeg-4.4/tests/ref/fate/matroska-zlib-decompression --- ffmpeg-4.2.2/tests/ref/fate/matroska-zlib-decompression 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/matroska-zlib-decompression 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,5 @@ +#extradata 0: 348, 0x5f625922 +#tb 0: 1/1000 +#media_type 0: subtitle +#codec_id 0: dvd_subtitle +0, 1000, 1000, 1991, 191, 0x52f74934 diff -Nru ffmpeg-4.2.2/tests/ref/fate/mimic ffmpeg-4.4/tests/ref/fate/mimic --- ffmpeg-4.2.2/tests/ref/fate/mimic 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mimic 2021-04-08 21:28:40.000000000 +0000 @@ -3,79 +3,79 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 0/1 -0, 0, 0, 0, 115200, 0xa974d407 -0, 548, 548, 0, 115200, 0x72618b84 -0, 1088, 1088, 0, 115200, 0x87768573 -0, 1759, 1759, 0, 115200, 0x5d218e3e -0, 2437, 2437, 0, 115200, 0x0c0db41c -0, 3076, 3076, 0, 115200, 0xb777fd48 -0, 3908, 3908, 0, 115200, 0x40765de7 -0, 4545, 4545, 0, 115200, 0x370a3c90 -0, 5092, 5092, 0, 115200, 0xc605785a -0, 6016, 6016, 0, 115200, 0x49468b23 -0, 6560, 6560, 0, 115200, 0x986b6fd4 -0, 7648, 7648, 0, 115200, 0x30f22ef8 -0, 8164, 8164, 0, 115200, 0xa90bd608 -0, 8836, 8836, 0, 115200, 0x9cf36518 -0, 9632, 9632, 0, 115200, 0x4ef1a679 -0, 9922, 9922, 0, 115200, 0x0df65873 -0, 10316, 10316, 0, 115200, 0xfecd4233 -0, 11104, 11104, 0, 115200, 0xee2f26cb -0, 11776, 11776, 0, 115200, 0x795f612d -0, 12321, 12321, 0, 115200, 0xbbb90125 -0, 12992, 12992, 0, 115200, 0x9230fb6e -0, 13805, 13805, 0, 115200, 0x11869996 -0, 14468, 14468, 0, 115200, 0x6b5c892b -0, 15136, 15136, 0, 115200, 0x88bdb9cd -0, 15937, 15937, 0, 115200, 0x364bc5a0 -0, 16608, 16608, 0, 115200, 0x6b66d817 -0, 17281, 17281, 0, 115200, 0xd3a41252 -0, 18089, 18089, 0, 115200, 0x0cf5612f -0, 18754, 18754, 0, 115200, 0x9752d055 -0, 19808, 19808, 0, 115200, 0x486e9f6f -0, 20484, 20484, 0, 115200, 0x3eab62f8 -0, 21031, 21031, 0, 115200, 0xa7f52762 -0, 21957, 21957, 0, 115200, 0xfd4c4bbc -0, 22498, 22498, 0, 115200, 0x194023f6 -0, 22880, 22880, 0, 115200, 0xd4668dad -0, 23680, 23680, 0, 115200, 0x6b20d64b -0, 24353, 24353, 0, 115200, 0xf2572aae -0, 24901, 24901, 0, 115200, 0xc3554f25 -0, 25695, 25695, 0, 115200, 0xeeb5073a -0, 26495, 26495, 0, 115200, 0xbd46291f -0, 27040, 27040, 0, 115200, 0x0526838d -0, 28107, 28107, 0, 115200, 0x85b2e864 -0, 28778, 28778, 0, 115200, 0xcfd894bc -0, 29316, 29316, 0, 115200, 0x644f10fb -0, 30240, 30240, 0, 115200, 0x556e4d88 -0, 30786, 30786, 0, 115200, 0x93243614 -0, 31983, 31983, 0, 115200, 0x754275c5 -0, 32929, 32929, 0, 115200, 0x7f648bf3 -0, 33600, 33600, 0, 115200, 0xece18c9b -0, 34271, 34271, 0, 115200, 0x385d52c1 -0, 35201, 35201, 0, 115200, 0xafc58e4a -0, 35743, 35743, 0, 115200, 0x50daf750 -0, 36384, 36384, 0, 115200, 0xf6bc67d1 -0, 37344, 37344, 0, 115200, 0xb64b6e07 -0, 38028, 38028, 0, 115200, 0x8751ed15 -0, 38657, 38657, 0, 115200, 0x329ce803 -0, 39334, 39334, 0, 115200, 0x40b2cb05 -0, 40129, 40129, 0, 115200, 0x60f3517d -0, 40802, 40802, 0, 115200, 0xe0d46fdf -0, 41472, 41472, 0, 115200, 0x204529fa -0, 42276, 42276, 0, 115200, 0xd5afaf22 -0, 42944, 42944, 0, 115200, 0xd3cb3d4c -0, 43616, 43616, 0, 115200, 0x87973a79 -0, 44421, 44421, 0, 115200, 0xe3b2f917 -0, 45092, 45092, 0, 115200, 0xf1923238 -0, 45632, 45632, 0, 115200, 0x51494d71 -0, 46561, 46561, 0, 115200, 0x58bc59bb -0, 47105, 47105, 0, 115200, 0xd0273fdb -0, 47776, 47776, 0, 115200, 0x6cc79700 -0, 48294, 48294, 0, 115200, 0xc8172d31 -0, 48960, 48960, 0, 115200, 0x8eb037ef -0, 49504, 49504, 0, 115200, 0xc0bc2d76 -0, 50053, 50053, 0, 115200, 0x663c467a -0, 50597, 50597, 0, 115200, 0xd085e950 -0, 51520, 51520, 0, 115200, 0x7d198d72 -0, 52092, 52092, 0, 115200, 0x6ebacda0 +0, 0, 0, 1, 115200, 0xa974d407 +0, 548, 548, 1, 115200, 0x72618b84 +0, 1088, 1088, 1, 115200, 0x87768573 +0, 1759, 1759, 1, 115200, 0x5d218e3e +0, 2437, 2437, 1, 115200, 0x0c0db41c +0, 3076, 3076, 1, 115200, 0xb777fd48 +0, 3908, 3908, 1, 115200, 0x40765de7 +0, 4545, 4545, 1, 115200, 0x370a3c90 +0, 5092, 5092, 1, 115200, 0xc605785a +0, 6016, 6016, 1, 115200, 0x49468b23 +0, 6560, 6560, 1, 115200, 0x986b6fd4 +0, 7648, 7648, 1, 115200, 0x30f22ef8 +0, 8164, 8164, 1, 115200, 0xa90bd608 +0, 8836, 8836, 1, 115200, 0x9cf36518 +0, 9632, 9632, 1, 115200, 0x4ef1a679 +0, 9922, 9922, 1, 115200, 0x0df65873 +0, 10316, 10316, 1, 115200, 0xfecd4233 +0, 11104, 11104, 1, 115200, 0xee2f26cb +0, 11776, 11776, 1, 115200, 0x795f612d +0, 12321, 12321, 1, 115200, 0xbbb90125 +0, 12992, 12992, 1, 115200, 0x9230fb6e +0, 13805, 13805, 1, 115200, 0x11869996 +0, 14468, 14468, 1, 115200, 0x6b5c892b +0, 15136, 15136, 1, 115200, 0x88bdb9cd +0, 15937, 15937, 1, 115200, 0x364bc5a0 +0, 16608, 16608, 1, 115200, 0x6b66d817 +0, 17281, 17281, 1, 115200, 0xd3a41252 +0, 18089, 18089, 1, 115200, 0x0cf5612f +0, 18754, 18754, 1, 115200, 0x9752d055 +0, 19808, 19808, 1, 115200, 0x486e9f6f +0, 20484, 20484, 1, 115200, 0x3eab62f8 +0, 21031, 21031, 1, 115200, 0xa7f52762 +0, 21957, 21957, 1, 115200, 0xfd4c4bbc +0, 22498, 22498, 1, 115200, 0x194023f6 +0, 22880, 22880, 1, 115200, 0xd4668dad +0, 23680, 23680, 1, 115200, 0x6b20d64b +0, 24353, 24353, 1, 115200, 0xf2572aae +0, 24901, 24901, 1, 115200, 0xc3554f25 +0, 25695, 25695, 1, 115200, 0xeeb5073a +0, 26495, 26495, 1, 115200, 0xbd46291f +0, 27040, 27040, 1, 115200, 0x0526838d +0, 28107, 28107, 1, 115200, 0x85b2e864 +0, 28778, 28778, 1, 115200, 0xcfd894bc +0, 29316, 29316, 1, 115200, 0x644f10fb +0, 30240, 30240, 1, 115200, 0x556e4d88 +0, 30786, 30786, 1, 115200, 0x93243614 +0, 31983, 31983, 1, 115200, 0x754275c5 +0, 32929, 32929, 1, 115200, 0x7f648bf3 +0, 33600, 33600, 1, 115200, 0xece18c9b +0, 34271, 34271, 1, 115200, 0x385d52c1 +0, 35201, 35201, 1, 115200, 0xafc58e4a +0, 35743, 35743, 1, 115200, 0x50daf750 +0, 36384, 36384, 1, 115200, 0xf6bc67d1 +0, 37344, 37344, 1, 115200, 0xb64b6e07 +0, 38028, 38028, 1, 115200, 0x8751ed15 +0, 38657, 38657, 1, 115200, 0x329ce803 +0, 39334, 39334, 1, 115200, 0x40b2cb05 +0, 40129, 40129, 1, 115200, 0x60f3517d +0, 40802, 40802, 1, 115200, 0xe0d46fdf +0, 41472, 41472, 1, 115200, 0x204529fa +0, 42276, 42276, 1, 115200, 0xd5afaf22 +0, 42944, 42944, 1, 115200, 0xd3cb3d4c +0, 43616, 43616, 1, 115200, 0x87973a79 +0, 44421, 44421, 1, 115200, 0xe3b2f917 +0, 45092, 45092, 1, 115200, 0xf1923238 +0, 45632, 45632, 1, 115200, 0x51494d71 +0, 46561, 46561, 1, 115200, 0x58bc59bb +0, 47105, 47105, 1, 115200, 0xd0273fdb +0, 47776, 47776, 1, 115200, 0x6cc79700 +0, 48294, 48294, 1, 115200, 0xc8172d31 +0, 48960, 48960, 1, 115200, 0x8eb037ef +0, 49504, 49504, 1, 115200, 0xc0bc2d76 +0, 50053, 50053, 1, 115200, 0x663c467a +0, 50597, 50597, 1, 115200, 0xd085e950 +0, 51520, 51520, 1, 115200, 0x7d198d72 +0, 52092, 52092, 1, 115200, 0x6ebacda0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/mjpeg-ticket3229 ffmpeg-4.4/tests/ref/fate/mjpeg-ticket3229 --- ffmpeg-4.2.2/tests/ref/fate/mjpeg-ticket3229 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mjpeg-ticket3229 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,8 @@ +#tb 0: 1/30 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 468x312 +#sar 0: 0/1 +0, 0, 0, 1, 292032, 0x3af3a5f7 +0, 6, 6, 1, 292032, 0xe97fb504 +0, 8, 8, 1, 292032, 0xd448db04 diff -Nru ffmpeg-4.2.2/tests/ref/fate/mov-aac-2048-priming ffmpeg-4.4/tests/ref/fate/mov-aac-2048-priming --- ffmpeg-4.2.2/tests/ref/fate/mov-aac-2048-priming 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mov-aac-2048-priming 2021-04-08 21:28:40.000000000 +0000 @@ -1,218 +1,218 @@ -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|convergence_duration=N/A|convergence_duration_time=N/A|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=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=-1024|pts_time=-0.023220|dts=-1024|dts_time=-0.023220|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|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|convergence_duration=N/A|convergence_duration_time=N/A|size=146|pos=552|flags=K_ -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|convergence_duration=N/A|convergence_duration_time=N/A|size=186|pos=698|flags=K_ -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|convergence_duration=N/A|convergence_duration_time=N/A|size=222|pos=884|flags=K_ -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|convergence_duration=N/A|convergence_duration_time=N/A|size=186|pos=1106|flags=K_ -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|convergence_duration=N/A|convergence_duration_time=N/A|size=206|pos=1292|flags=K_ -packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=199|pos=1498|flags=K_ -packet|codec_type=audio|stream_index=0|pts=6144|pts_time=0.139320|dts=6144|dts_time=0.139320|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=236|pos=1697|flags=K_ -packet|codec_type=audio|stream_index=0|pts=7168|pts_time=0.162540|dts=7168|dts_time=0.162540|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=208|pos=1933|flags=K_ -packet|codec_type=audio|stream_index=0|pts=8192|pts_time=0.185760|dts=8192|dts_time=0.185760|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=238|pos=2141|flags=K_ -packet|codec_type=audio|stream_index=0|pts=9216|pts_time=0.208980|dts=9216|dts_time=0.208980|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=222|pos=2379|flags=K_ -packet|codec_type=audio|stream_index=0|pts=10240|pts_time=0.232200|dts=10240|dts_time=0.232200|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=211|pos=2601|flags=K_ -packet|codec_type=audio|stream_index=0|pts=11264|pts_time=0.255420|dts=11264|dts_time=0.255420|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=153|pos=2812|flags=K_ -packet|codec_type=audio|stream_index=0|pts=12288|pts_time=0.278639|dts=12288|dts_time=0.278639|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=191|pos=2965|flags=K_ -packet|codec_type=audio|stream_index=0|pts=13312|pts_time=0.301859|dts=13312|dts_time=0.301859|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=208|pos=3156|flags=K_ -packet|codec_type=audio|stream_index=0|pts=14336|pts_time=0.325079|dts=14336|dts_time=0.325079|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=188|pos=3364|flags=K_ -packet|codec_type=audio|stream_index=0|pts=15360|pts_time=0.348299|dts=15360|dts_time=0.348299|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=170|pos=3552|flags=K_ -packet|codec_type=audio|stream_index=0|pts=16384|pts_time=0.371519|dts=16384|dts_time=0.371519|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=221|pos=3722|flags=K_ -packet|codec_type=audio|stream_index=0|pts=17408|pts_time=0.394739|dts=17408|dts_time=0.394739|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=247|pos=3943|flags=K_ -packet|codec_type=audio|stream_index=0|pts=18432|pts_time=0.417959|dts=18432|dts_time=0.417959|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=202|pos=4190|flags=K_ -packet|codec_type=audio|stream_index=0|pts=19456|pts_time=0.441179|dts=19456|dts_time=0.441179|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=186|pos=4392|flags=K_ -packet|codec_type=audio|stream_index=0|pts=20480|pts_time=0.464399|dts=20480|dts_time=0.464399|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=196|pos=4578|flags=K_ -packet|codec_type=audio|stream_index=0|pts=21504|pts_time=0.487619|dts=21504|dts_time=0.487619|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=200|pos=4774|flags=K_ -packet|codec_type=audio|stream_index=0|pts=22528|pts_time=0.510839|dts=22528|dts_time=0.510839|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=170|pos=4974|flags=K_ -packet|codec_type=audio|stream_index=0|pts=23552|pts_time=0.534059|dts=23552|dts_time=0.534059|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=172|pos=5144|flags=K_ -packet|codec_type=audio|stream_index=0|pts=24576|pts_time=0.557279|dts=24576|dts_time=0.557279|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=206|pos=5316|flags=K_ -packet|codec_type=audio|stream_index=0|pts=25600|pts_time=0.580499|dts=25600|dts_time=0.580499|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=208|pos=5522|flags=K_ -packet|codec_type=audio|stream_index=0|pts=26624|pts_time=0.603719|dts=26624|dts_time=0.603719|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=217|pos=5730|flags=K_ -packet|codec_type=audio|stream_index=0|pts=27648|pts_time=0.626939|dts=27648|dts_time=0.626939|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=252|pos=5947|flags=K_ -packet|codec_type=audio|stream_index=0|pts=28672|pts_time=0.650159|dts=28672|dts_time=0.650159|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=171|pos=6199|flags=K_ -packet|codec_type=audio|stream_index=0|pts=29696|pts_time=0.673379|dts=29696|dts_time=0.673379|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=206|pos=6370|flags=K_ -packet|codec_type=audio|stream_index=0|pts=30720|pts_time=0.696599|dts=30720|dts_time=0.696599|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=237|pos=6576|flags=K_ -packet|codec_type=audio|stream_index=0|pts=31744|pts_time=0.719819|dts=31744|dts_time=0.719819|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=210|pos=6813|flags=K_ -packet|codec_type=audio|stream_index=0|pts=32768|pts_time=0.743039|dts=32768|dts_time=0.743039|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=166|pos=7023|flags=K_ -packet|codec_type=audio|stream_index=0|pts=33792|pts_time=0.766259|dts=33792|dts_time=0.766259|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=166|pos=7189|flags=K_ -packet|codec_type=audio|stream_index=0|pts=34816|pts_time=0.789478|dts=34816|dts_time=0.789478|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=177|pos=7355|flags=K_ -packet|codec_type=audio|stream_index=0|pts=35840|pts_time=0.812698|dts=35840|dts_time=0.812698|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=188|pos=7532|flags=K_ -packet|codec_type=audio|stream_index=0|pts=36864|pts_time=0.835918|dts=36864|dts_time=0.835918|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=193|pos=7720|flags=K_ -packet|codec_type=audio|stream_index=0|pts=37888|pts_time=0.859138|dts=37888|dts_time=0.859138|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=195|pos=7913|flags=K_ -packet|codec_type=audio|stream_index=0|pts=38912|pts_time=0.882358|dts=38912|dts_time=0.882358|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=211|pos=8108|flags=K_ -packet|codec_type=audio|stream_index=0|pts=39936|pts_time=0.905578|dts=39936|dts_time=0.905578|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=249|pos=8319|flags=K_ -packet|codec_type=audio|stream_index=0|pts=40960|pts_time=0.928798|dts=40960|dts_time=0.928798|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=223|pos=8568|flags=K_ -packet|codec_type=audio|stream_index=0|pts=41984|pts_time=0.952018|dts=41984|dts_time=0.952018|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=230|pos=8791|flags=K_ -packet|codec_type=audio|stream_index=0|pts=43008|pts_time=0.975238|dts=43008|dts_time=0.975238|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=203|pos=9021|flags=K_ -packet|codec_type=audio|stream_index=0|pts=44032|pts_time=0.998458|dts=44032|dts_time=0.998458|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=180|pos=9224|flags=K_ -packet|codec_type=audio|stream_index=0|pts=45056|pts_time=1.021678|dts=45056|dts_time=1.021678|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=172|pos=9404|flags=K_ -packet|codec_type=audio|stream_index=0|pts=46080|pts_time=1.044898|dts=46080|dts_time=1.044898|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=240|pos=9576|flags=K_ -packet|codec_type=audio|stream_index=0|pts=47104|pts_time=1.068118|dts=47104|dts_time=1.068118|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=179|pos=9816|flags=K_ -packet|codec_type=audio|stream_index=0|pts=48128|pts_time=1.091338|dts=48128|dts_time=1.091338|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=191|pos=9995|flags=K_ -packet|codec_type=audio|stream_index=0|pts=49152|pts_time=1.114558|dts=49152|dts_time=1.114558|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=184|pos=10186|flags=K_ -packet|codec_type=audio|stream_index=0|pts=50176|pts_time=1.137778|dts=50176|dts_time=1.137778|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=214|pos=10370|flags=K_ -packet|codec_type=audio|stream_index=0|pts=51200|pts_time=1.160998|dts=51200|dts_time=1.160998|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=194|pos=10584|flags=K_ -packet|codec_type=audio|stream_index=0|pts=52224|pts_time=1.184218|dts=52224|dts_time=1.184218|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=235|pos=10778|flags=K_ -packet|codec_type=audio|stream_index=0|pts=53248|pts_time=1.207438|dts=53248|dts_time=1.207438|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=195|pos=11013|flags=K_ -packet|codec_type=audio|stream_index=0|pts=54272|pts_time=1.230658|dts=54272|dts_time=1.230658|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=220|pos=11208|flags=K_ -packet|codec_type=audio|stream_index=0|pts=55296|pts_time=1.253878|dts=55296|dts_time=1.253878|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=187|pos=11428|flags=K_ -packet|codec_type=audio|stream_index=0|pts=56320|pts_time=1.277098|dts=56320|dts_time=1.277098|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=238|pos=11615|flags=K_ -packet|codec_type=audio|stream_index=0|pts=57344|pts_time=1.300317|dts=57344|dts_time=1.300317|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=175|pos=11853|flags=K_ -packet|codec_type=audio|stream_index=0|pts=58368|pts_time=1.323537|dts=58368|dts_time=1.323537|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=178|pos=12028|flags=K_ -packet|codec_type=audio|stream_index=0|pts=59392|pts_time=1.346757|dts=59392|dts_time=1.346757|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=219|pos=12206|flags=K_ -packet|codec_type=audio|stream_index=0|pts=60416|pts_time=1.369977|dts=60416|dts_time=1.369977|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=179|pos=12425|flags=K_ -packet|codec_type=audio|stream_index=0|pts=61440|pts_time=1.393197|dts=61440|dts_time=1.393197|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=193|pos=12604|flags=K_ -packet|codec_type=audio|stream_index=0|pts=62464|pts_time=1.416417|dts=62464|dts_time=1.416417|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=200|pos=12797|flags=K_ -packet|codec_type=audio|stream_index=0|pts=63488|pts_time=1.439637|dts=63488|dts_time=1.439637|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=218|pos=12997|flags=K_ -packet|codec_type=audio|stream_index=0|pts=64512|pts_time=1.462857|dts=64512|dts_time=1.462857|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=215|pos=13215|flags=K_ -packet|codec_type=audio|stream_index=0|pts=65536|pts_time=1.486077|dts=65536|dts_time=1.486077|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=209|pos=13430|flags=K_ -packet|codec_type=audio|stream_index=0|pts=66560|pts_time=1.509297|dts=66560|dts_time=1.509297|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=171|pos=13639|flags=K_ -packet|codec_type=audio|stream_index=0|pts=67584|pts_time=1.532517|dts=67584|dts_time=1.532517|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=179|pos=13810|flags=K_ -packet|codec_type=audio|stream_index=0|pts=68608|pts_time=1.555737|dts=68608|dts_time=1.555737|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=185|pos=13989|flags=K_ -packet|codec_type=audio|stream_index=0|pts=69632|pts_time=1.578957|dts=69632|dts_time=1.578957|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=225|pos=14174|flags=K_ -packet|codec_type=audio|stream_index=0|pts=70656|pts_time=1.602177|dts=70656|dts_time=1.602177|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=221|pos=14399|flags=K_ -packet|codec_type=audio|stream_index=0|pts=71680|pts_time=1.625397|dts=71680|dts_time=1.625397|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=201|pos=14620|flags=K_ -packet|codec_type=audio|stream_index=0|pts=72704|pts_time=1.648617|dts=72704|dts_time=1.648617|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=206|pos=14821|flags=K_ -packet|codec_type=audio|stream_index=0|pts=73728|pts_time=1.671837|dts=73728|dts_time=1.671837|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=182|pos=15027|flags=K_ -packet|codec_type=audio|stream_index=0|pts=74752|pts_time=1.695057|dts=74752|dts_time=1.695057|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=176|pos=15209|flags=K_ -packet|codec_type=audio|stream_index=0|pts=75776|pts_time=1.718277|dts=75776|dts_time=1.718277|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=233|pos=15385|flags=K_ -packet|codec_type=audio|stream_index=0|pts=76800|pts_time=1.741497|dts=76800|dts_time=1.741497|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=199|pos=15618|flags=K_ -packet|codec_type=audio|stream_index=0|pts=77824|pts_time=1.764717|dts=77824|dts_time=1.764717|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=220|pos=15817|flags=K_ -packet|codec_type=audio|stream_index=0|pts=78848|pts_time=1.787937|dts=78848|dts_time=1.787937|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=190|pos=16037|flags=K_ -packet|codec_type=audio|stream_index=0|pts=79872|pts_time=1.811156|dts=79872|dts_time=1.811156|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=210|pos=16227|flags=K_ -packet|codec_type=audio|stream_index=0|pts=80896|pts_time=1.834376|dts=80896|dts_time=1.834376|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=204|pos=16437|flags=K_ -packet|codec_type=audio|stream_index=0|pts=81920|pts_time=1.857596|dts=81920|dts_time=1.857596|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=171|pos=16641|flags=K_ -packet|codec_type=audio|stream_index=0|pts=82944|pts_time=1.880816|dts=82944|dts_time=1.880816|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=167|pos=16812|flags=K_ -packet|codec_type=audio|stream_index=0|pts=83968|pts_time=1.904036|dts=83968|dts_time=1.904036|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=200|pos=16979|flags=K_ -packet|codec_type=audio|stream_index=0|pts=84992|pts_time=1.927256|dts=84992|dts_time=1.927256|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=254|pos=17179|flags=K_ -packet|codec_type=audio|stream_index=0|pts=86016|pts_time=1.950476|dts=86016|dts_time=1.950476|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=205|pos=17433|flags=K_ -packet|codec_type=audio|stream_index=0|pts=87040|pts_time=1.973696|dts=87040|dts_time=1.973696|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=196|pos=17638|flags=K_ -packet|codec_type=audio|stream_index=0|pts=88064|pts_time=1.996916|dts=88064|dts_time=1.996916|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=190|pos=17834|flags=K_ -packet|codec_type=audio|stream_index=0|pts=89088|pts_time=2.020136|dts=89088|dts_time=2.020136|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=197|pos=18024|flags=K_ -packet|codec_type=audio|stream_index=0|pts=90112|pts_time=2.043356|dts=90112|dts_time=2.043356|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=186|pos=18221|flags=K_ -packet|codec_type=audio|stream_index=0|pts=91136|pts_time=2.066576|dts=91136|dts_time=2.066576|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=194|pos=18407|flags=K_ -packet|codec_type=audio|stream_index=0|pts=92160|pts_time=2.089796|dts=92160|dts_time=2.089796|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=227|pos=18601|flags=K_ -packet|codec_type=audio|stream_index=0|pts=93184|pts_time=2.113016|dts=93184|dts_time=2.113016|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=195|pos=18828|flags=K_ -packet|codec_type=audio|stream_index=0|pts=94208|pts_time=2.136236|dts=94208|dts_time=2.136236|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=228|pos=19023|flags=K_ -packet|codec_type=audio|stream_index=0|pts=95232|pts_time=2.159456|dts=95232|dts_time=2.159456|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=196|pos=19251|flags=K_ -packet|codec_type=audio|stream_index=0|pts=96256|pts_time=2.182676|dts=96256|dts_time=2.182676|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=197|pos=19447|flags=K_ -packet|codec_type=audio|stream_index=0|pts=97280|pts_time=2.205896|dts=97280|dts_time=2.205896|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=186|pos=19644|flags=K_ -packet|codec_type=audio|stream_index=0|pts=98304|pts_time=2.229116|dts=98304|dts_time=2.229116|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=191|pos=19830|flags=K_ -packet|codec_type=audio|stream_index=0|pts=99328|pts_time=2.252336|dts=99328|dts_time=2.252336|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=215|pos=20021|flags=K_ -packet|codec_type=audio|stream_index=0|pts=100352|pts_time=2.275556|dts=100352|dts_time=2.275556|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=203|pos=20236|flags=K_ -packet|codec_type=audio|stream_index=0|pts=101376|pts_time=2.298776|dts=101376|dts_time=2.298776|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=205|pos=20439|flags=K_ -packet|codec_type=audio|stream_index=0|pts=102400|pts_time=2.321995|dts=102400|dts_time=2.321995|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=205|pos=20644|flags=K_ -packet|codec_type=audio|stream_index=0|pts=103424|pts_time=2.345215|dts=103424|dts_time=2.345215|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=213|pos=20849|flags=K_ -packet|codec_type=audio|stream_index=0|pts=104448|pts_time=2.368435|dts=104448|dts_time=2.368435|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=198|pos=21062|flags=K_ -packet|codec_type=audio|stream_index=0|pts=105472|pts_time=2.391655|dts=105472|dts_time=2.391655|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=178|pos=21260|flags=K_ -packet|codec_type=audio|stream_index=0|pts=106496|pts_time=2.414875|dts=106496|dts_time=2.414875|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=195|pos=21438|flags=K_ -packet|codec_type=audio|stream_index=0|pts=107520|pts_time=2.438095|dts=107520|dts_time=2.438095|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=227|pos=21633|flags=K_ -packet|codec_type=audio|stream_index=0|pts=108544|pts_time=2.461315|dts=108544|dts_time=2.461315|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=185|pos=21860|flags=K_ -packet|codec_type=audio|stream_index=0|pts=109568|pts_time=2.484535|dts=109568|dts_time=2.484535|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=206|pos=22045|flags=K_ -packet|codec_type=audio|stream_index=0|pts=110592|pts_time=2.507755|dts=110592|dts_time=2.507755|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=183|pos=22251|flags=K_ -packet|codec_type=audio|stream_index=0|pts=111616|pts_time=2.530975|dts=111616|dts_time=2.530975|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=208|pos=22434|flags=K_ -packet|codec_type=audio|stream_index=0|pts=112640|pts_time=2.554195|dts=112640|dts_time=2.554195|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=204|pos=22642|flags=K_ -packet|codec_type=audio|stream_index=0|pts=113664|pts_time=2.577415|dts=113664|dts_time=2.577415|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=192|pos=22846|flags=K_ -packet|codec_type=audio|stream_index=0|pts=114688|pts_time=2.600635|dts=114688|dts_time=2.600635|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=190|pos=23038|flags=K_ -packet|codec_type=audio|stream_index=0|pts=115712|pts_time=2.623855|dts=115712|dts_time=2.623855|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=199|pos=23228|flags=K_ -packet|codec_type=audio|stream_index=0|pts=116736|pts_time=2.647075|dts=116736|dts_time=2.647075|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=229|pos=23427|flags=K_ -packet|codec_type=audio|stream_index=0|pts=117760|pts_time=2.670295|dts=117760|dts_time=2.670295|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=208|pos=23656|flags=K_ -packet|codec_type=audio|stream_index=0|pts=118784|pts_time=2.693515|dts=118784|dts_time=2.693515|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=195|pos=23864|flags=K_ -packet|codec_type=audio|stream_index=0|pts=119808|pts_time=2.716735|dts=119808|dts_time=2.716735|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=190|pos=24059|flags=K_ -packet|codec_type=audio|stream_index=0|pts=120832|pts_time=2.739955|dts=120832|dts_time=2.739955|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=190|pos=24249|flags=K_ -packet|codec_type=audio|stream_index=0|pts=121856|pts_time=2.763175|dts=121856|dts_time=2.763175|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=192|pos=24439|flags=K_ -packet|codec_type=audio|stream_index=0|pts=122880|pts_time=2.786395|dts=122880|dts_time=2.786395|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=226|pos=24631|flags=K_ -packet|codec_type=audio|stream_index=0|pts=123904|pts_time=2.809615|dts=123904|dts_time=2.809615|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=195|pos=24857|flags=K_ -packet|codec_type=audio|stream_index=0|pts=124928|pts_time=2.832834|dts=124928|dts_time=2.832834|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=230|pos=25052|flags=K_ -packet|codec_type=audio|stream_index=0|pts=125952|pts_time=2.856054|dts=125952|dts_time=2.856054|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=198|pos=25282|flags=K_ -packet|codec_type=audio|stream_index=0|pts=126976|pts_time=2.879274|dts=126976|dts_time=2.879274|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=183|pos=25480|flags=K_ -packet|codec_type=audio|stream_index=0|pts=128000|pts_time=2.902494|dts=128000|dts_time=2.902494|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=199|pos=25663|flags=K_ -packet|codec_type=audio|stream_index=0|pts=129024|pts_time=2.925714|dts=129024|dts_time=2.925714|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=196|pos=25862|flags=K_ -packet|codec_type=audio|stream_index=0|pts=130048|pts_time=2.948934|dts=130048|dts_time=2.948934|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=186|pos=26058|flags=K_ -packet|codec_type=audio|stream_index=0|pts=131072|pts_time=2.972154|dts=131072|dts_time=2.972154|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=200|pos=26244|flags=K_ -packet|codec_type=audio|stream_index=0|pts=132096|pts_time=2.995374|dts=132096|dts_time=2.995374|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=210|pos=26444|flags=K_ -packet|codec_type=audio|stream_index=0|pts=133120|pts_time=3.018594|dts=133120|dts_time=3.018594|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=196|pos=26654|flags=K_ -packet|codec_type=audio|stream_index=0|pts=134144|pts_time=3.041814|dts=134144|dts_time=3.041814|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=214|pos=26850|flags=K_ -packet|codec_type=audio|stream_index=0|pts=135168|pts_time=3.065034|dts=135168|dts_time=3.065034|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=185|pos=27064|flags=K_ -packet|codec_type=audio|stream_index=0|pts=136192|pts_time=3.088254|dts=136192|dts_time=3.088254|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=198|pos=27249|flags=K_ -packet|codec_type=audio|stream_index=0|pts=137216|pts_time=3.111474|dts=137216|dts_time=3.111474|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=200|pos=27447|flags=K_ -packet|codec_type=audio|stream_index=0|pts=138240|pts_time=3.134694|dts=138240|dts_time=3.134694|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=208|pos=27647|flags=K_ -packet|codec_type=audio|stream_index=0|pts=139264|pts_time=3.157914|dts=139264|dts_time=3.157914|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=212|pos=27855|flags=K_ -packet|codec_type=audio|stream_index=0|pts=140288|pts_time=3.181134|dts=140288|dts_time=3.181134|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=208|pos=28067|flags=K_ -packet|codec_type=audio|stream_index=0|pts=141312|pts_time=3.204354|dts=141312|dts_time=3.204354|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=192|pos=28275|flags=K_ -packet|codec_type=audio|stream_index=0|pts=142336|pts_time=3.227574|dts=142336|dts_time=3.227574|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=192|pos=28467|flags=K_ -packet|codec_type=audio|stream_index=0|pts=143360|pts_time=3.250794|dts=143360|dts_time=3.250794|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=211|pos=28659|flags=K_ -packet|codec_type=audio|stream_index=0|pts=144384|pts_time=3.274014|dts=144384|dts_time=3.274014|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=195|pos=28870|flags=K_ -packet|codec_type=audio|stream_index=0|pts=145408|pts_time=3.297234|dts=145408|dts_time=3.297234|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=208|pos=29065|flags=K_ -packet|codec_type=audio|stream_index=0|pts=146432|pts_time=3.320454|dts=146432|dts_time=3.320454|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=195|pos=29273|flags=K_ -packet|codec_type=audio|stream_index=0|pts=147456|pts_time=3.343673|dts=147456|dts_time=3.343673|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=204|pos=29468|flags=K_ -packet|codec_type=audio|stream_index=0|pts=148480|pts_time=3.366893|dts=148480|dts_time=3.366893|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=209|pos=29672|flags=K_ -packet|codec_type=audio|stream_index=0|pts=149504|pts_time=3.390113|dts=149504|dts_time=3.390113|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=195|pos=29881|flags=K_ -packet|codec_type=audio|stream_index=0|pts=150528|pts_time=3.413333|dts=150528|dts_time=3.413333|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=191|pos=30076|flags=K_ -packet|codec_type=audio|stream_index=0|pts=151552|pts_time=3.436553|dts=151552|dts_time=3.436553|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=210|pos=30267|flags=K_ -packet|codec_type=audio|stream_index=0|pts=152576|pts_time=3.459773|dts=152576|dts_time=3.459773|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=209|pos=30477|flags=K_ -packet|codec_type=audio|stream_index=0|pts=153600|pts_time=3.482993|dts=153600|dts_time=3.482993|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=175|pos=30686|flags=K_ -packet|codec_type=audio|stream_index=0|pts=154624|pts_time=3.506213|dts=154624|dts_time=3.506213|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=244|pos=30861|flags=K_ -packet|codec_type=audio|stream_index=0|pts=155648|pts_time=3.529433|dts=155648|dts_time=3.529433|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=177|pos=31105|flags=K_ -packet|codec_type=audio|stream_index=0|pts=156672|pts_time=3.552653|dts=156672|dts_time=3.552653|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=217|pos=31282|flags=K_ -packet|codec_type=audio|stream_index=0|pts=157696|pts_time=3.575873|dts=157696|dts_time=3.575873|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=182|pos=31499|flags=K_ -packet|codec_type=audio|stream_index=0|pts=158720|pts_time=3.599093|dts=158720|dts_time=3.599093|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=181|pos=31681|flags=K_ -packet|codec_type=audio|stream_index=0|pts=159744|pts_time=3.622313|dts=159744|dts_time=3.622313|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=203|pos=31862|flags=K_ -packet|codec_type=audio|stream_index=0|pts=160768|pts_time=3.645533|dts=160768|dts_time=3.645533|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=198|pos=32065|flags=K_ -packet|codec_type=audio|stream_index=0|pts=161792|pts_time=3.668753|dts=161792|dts_time=3.668753|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=217|pos=32263|flags=K_ -packet|codec_type=audio|stream_index=0|pts=162816|pts_time=3.691973|dts=162816|dts_time=3.691973|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=195|pos=32480|flags=K_ -packet|codec_type=audio|stream_index=0|pts=163840|pts_time=3.715193|dts=163840|dts_time=3.715193|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=198|pos=32675|flags=K_ -packet|codec_type=audio|stream_index=0|pts=164864|pts_time=3.738413|dts=164864|dts_time=3.738413|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=202|pos=32873|flags=K_ -packet|codec_type=audio|stream_index=0|pts=165888|pts_time=3.761633|dts=165888|dts_time=3.761633|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=185|pos=33075|flags=K_ -packet|codec_type=audio|stream_index=0|pts=166912|pts_time=3.784853|dts=166912|dts_time=3.784853|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=196|pos=33260|flags=K_ -packet|codec_type=audio|stream_index=0|pts=167936|pts_time=3.808073|dts=167936|dts_time=3.808073|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=226|pos=33456|flags=K_ -packet|codec_type=audio|stream_index=0|pts=168960|pts_time=3.831293|dts=168960|dts_time=3.831293|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=187|pos=33682|flags=K_ -packet|codec_type=audio|stream_index=0|pts=169984|pts_time=3.854512|dts=169984|dts_time=3.854512|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=193|pos=33869|flags=K_ -packet|codec_type=audio|stream_index=0|pts=171008|pts_time=3.877732|dts=171008|dts_time=3.877732|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=218|pos=34062|flags=K_ -packet|codec_type=audio|stream_index=0|pts=172032|pts_time=3.900952|dts=172032|dts_time=3.900952|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=200|pos=34280|flags=K_ -packet|codec_type=audio|stream_index=0|pts=173056|pts_time=3.924172|dts=173056|dts_time=3.924172|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=200|pos=34480|flags=K_ -packet|codec_type=audio|stream_index=0|pts=174080|pts_time=3.947392|dts=174080|dts_time=3.947392|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=198|pos=34680|flags=K_ -packet|codec_type=audio|stream_index=0|pts=175104|pts_time=3.970612|dts=175104|dts_time=3.970612|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=200|pos=34878|flags=K_ -packet|codec_type=audio|stream_index=0|pts=176128|pts_time=3.993832|dts=176128|dts_time=3.993832|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=197|pos=35078|flags=K_ -packet|codec_type=audio|stream_index=0|pts=177152|pts_time=4.017052|dts=177152|dts_time=4.017052|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=209|pos=35275|flags=K_ -packet|codec_type=audio|stream_index=0|pts=178176|pts_time=4.040272|dts=178176|dts_time=4.040272|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=205|pos=35484|flags=K_ -packet|codec_type=audio|stream_index=0|pts=179200|pts_time=4.063492|dts=179200|dts_time=4.063492|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=199|pos=35689|flags=K_ -packet|codec_type=audio|stream_index=0|pts=180224|pts_time=4.086712|dts=180224|dts_time=4.086712|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=192|pos=35888|flags=K_ -packet|codec_type=audio|stream_index=0|pts=181248|pts_time=4.109932|dts=181248|dts_time=4.109932|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=201|pos=36080|flags=K_ -packet|codec_type=audio|stream_index=0|pts=182272|pts_time=4.133152|dts=182272|dts_time=4.133152|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=200|pos=36281|flags=K_ -packet|codec_type=audio|stream_index=0|pts=183296|pts_time=4.156372|dts=183296|dts_time=4.156372|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=202|pos=36481|flags=K_ -packet|codec_type=audio|stream_index=0|pts=184320|pts_time=4.179592|dts=184320|dts_time=4.179592|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=196|pos=36683|flags=K_ -packet|codec_type=audio|stream_index=0|pts=185344|pts_time=4.202812|dts=185344|dts_time=4.202812|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=200|pos=36879|flags=K_ -packet|codec_type=audio|stream_index=0|pts=186368|pts_time=4.226032|dts=186368|dts_time=4.226032|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=209|pos=37079|flags=K_ -packet|codec_type=audio|stream_index=0|pts=187392|pts_time=4.249252|dts=187392|dts_time=4.249252|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=201|pos=37288|flags=K_ -packet|codec_type=audio|stream_index=0|pts=188416|pts_time=4.272472|dts=188416|dts_time=4.272472|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=201|pos=37489|flags=K_ -packet|codec_type=audio|stream_index=0|pts=189440|pts_time=4.295692|dts=189440|dts_time=4.295692|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=201|pos=37690|flags=K_ -packet|codec_type=audio|stream_index=0|pts=190464|pts_time=4.318912|dts=190464|dts_time=4.318912|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=199|pos=37891|flags=K_ -packet|codec_type=audio|stream_index=0|pts=191488|pts_time=4.342132|dts=191488|dts_time=4.342132|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=198|pos=38090|flags=K_ -packet|codec_type=audio|stream_index=0|pts=192512|pts_time=4.365351|dts=192512|dts_time=4.365351|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=205|pos=38288|flags=K_ -packet|codec_type=audio|stream_index=0|pts=193536|pts_time=4.388571|dts=193536|dts_time=4.388571|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=190|pos=38493|flags=K_ -packet|codec_type=audio|stream_index=0|pts=194560|pts_time=4.411791|dts=194560|dts_time=4.411791|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=207|pos=38683|flags=K_ -packet|codec_type=audio|stream_index=0|pts=195584|pts_time=4.435011|dts=195584|dts_time=4.435011|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=204|pos=38890|flags=K_ -packet|codec_type=audio|stream_index=0|pts=196608|pts_time=4.458231|dts=196608|dts_time=4.458231|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=192|pos=39094|flags=K_ -packet|codec_type=audio|stream_index=0|pts=197632|pts_time=4.481451|dts=197632|dts_time=4.481451|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=211|pos=39286|flags=K_ -packet|codec_type=audio|stream_index=0|pts=198656|pts_time=4.504671|dts=198656|dts_time=4.504671|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=195|pos=39497|flags=K_ -packet|codec_type=audio|stream_index=0|pts=199680|pts_time=4.527891|dts=199680|dts_time=4.527891|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=214|pos=39692|flags=K_ -packet|codec_type=audio|stream_index=0|pts=200704|pts_time=4.551111|dts=200704|dts_time=4.551111|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=195|pos=39906|flags=K_ -packet|codec_type=audio|stream_index=0|pts=201728|pts_time=4.574331|dts=201728|dts_time=4.574331|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=199|pos=40101|flags=K_ -packet|codec_type=audio|stream_index=0|pts=202752|pts_time=4.597551|dts=202752|dts_time=4.597551|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=183|pos=40300|flags=K_ -packet|codec_type=audio|stream_index=0|pts=203776|pts_time=4.620771|dts=203776|dts_time=4.620771|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=211|pos=40483|flags=K_ -packet|codec_type=audio|stream_index=0|pts=204800|pts_time=4.643991|dts=204800|dts_time=4.643991|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=200|pos=40694|flags=K_ -packet|codec_type=audio|stream_index=0|pts=205824|pts_time=4.667211|dts=205824|dts_time=4.667211|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=199|pos=40894|flags=K_ -packet|codec_type=audio|stream_index=0|pts=206848|pts_time=4.690431|dts=206848|dts_time=4.690431|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=213|pos=41093|flags=K_ -packet|codec_type=audio|stream_index=0|pts=207872|pts_time=4.713651|dts=207872|dts_time=4.713651|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=191|pos=41306|flags=K_ -packet|codec_type=audio|stream_index=0|pts=208896|pts_time=4.736871|dts=208896|dts_time=4.736871|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=211|pos=41497|flags=K_ -packet|codec_type=audio|stream_index=0|pts=209920|pts_time=4.760091|dts=209920|dts_time=4.760091|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=198|pos=41708|flags=K_ -packet|codec_type=audio|stream_index=0|pts=210944|pts_time=4.783311|dts=210944|dts_time=4.783311|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=203|pos=41906|flags=K_ -packet|codec_type=audio|stream_index=0|pts=211968|pts_time=4.806531|dts=211968|dts_time=4.806531|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=196|pos=42109|flags=K_ -packet|codec_type=audio|stream_index=0|pts=212992|pts_time=4.829751|dts=212992|dts_time=4.829751|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=197|pos=42305|flags=K_ -packet|codec_type=audio|stream_index=0|pts=214016|pts_time=4.852971|dts=214016|dts_time=4.852971|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=190|pos=42502|flags=K_ -packet|codec_type=audio|stream_index=0|pts=215040|pts_time=4.876190|dts=215040|dts_time=4.876190|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=208|pos=42692|flags=K_ -packet|codec_type=audio|stream_index=0|pts=216064|pts_time=4.899410|dts=216064|dts_time=4.899410|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=203|pos=42900|flags=K_ -packet|codec_type=audio|stream_index=0|pts=217088|pts_time=4.922630|dts=217088|dts_time=4.922630|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=198|pos=43103|flags=K_ -packet|codec_type=audio|stream_index=0|pts=218112|pts_time=4.945850|dts=218112|dts_time=4.945850|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=284|pos=43301|flags=K_ -packet|codec_type=audio|stream_index=0|pts=219136|pts_time=4.969070|dts=219136|dts_time=4.969070|duration=1364|duration_time=0.030930|convergence_duration=N/A|convergence_duration_time=N/A|size=5|pos=43585|flags=K_ +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_ +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=186|pos=698|flags=K_ +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=222|pos=884|flags=K_ +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=186|pos=1106|flags=K_ +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=206|pos=1292|flags=K_ +packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=1024|duration_time=0.023220|size=199|pos=1498|flags=K_ +packet|codec_type=audio|stream_index=0|pts=6144|pts_time=0.139320|dts=6144|dts_time=0.139320|duration=1024|duration_time=0.023220|size=236|pos=1697|flags=K_ +packet|codec_type=audio|stream_index=0|pts=7168|pts_time=0.162540|dts=7168|dts_time=0.162540|duration=1024|duration_time=0.023220|size=208|pos=1933|flags=K_ +packet|codec_type=audio|stream_index=0|pts=8192|pts_time=0.185760|dts=8192|dts_time=0.185760|duration=1024|duration_time=0.023220|size=238|pos=2141|flags=K_ +packet|codec_type=audio|stream_index=0|pts=9216|pts_time=0.208980|dts=9216|dts_time=0.208980|duration=1024|duration_time=0.023220|size=222|pos=2379|flags=K_ +packet|codec_type=audio|stream_index=0|pts=10240|pts_time=0.232200|dts=10240|dts_time=0.232200|duration=1024|duration_time=0.023220|size=211|pos=2601|flags=K_ +packet|codec_type=audio|stream_index=0|pts=11264|pts_time=0.255420|dts=11264|dts_time=0.255420|duration=1024|duration_time=0.023220|size=153|pos=2812|flags=K_ +packet|codec_type=audio|stream_index=0|pts=12288|pts_time=0.278639|dts=12288|dts_time=0.278639|duration=1024|duration_time=0.023220|size=191|pos=2965|flags=K_ +packet|codec_type=audio|stream_index=0|pts=13312|pts_time=0.301859|dts=13312|dts_time=0.301859|duration=1024|duration_time=0.023220|size=208|pos=3156|flags=K_ +packet|codec_type=audio|stream_index=0|pts=14336|pts_time=0.325079|dts=14336|dts_time=0.325079|duration=1024|duration_time=0.023220|size=188|pos=3364|flags=K_ +packet|codec_type=audio|stream_index=0|pts=15360|pts_time=0.348299|dts=15360|dts_time=0.348299|duration=1024|duration_time=0.023220|size=170|pos=3552|flags=K_ +packet|codec_type=audio|stream_index=0|pts=16384|pts_time=0.371519|dts=16384|dts_time=0.371519|duration=1024|duration_time=0.023220|size=221|pos=3722|flags=K_ +packet|codec_type=audio|stream_index=0|pts=17408|pts_time=0.394739|dts=17408|dts_time=0.394739|duration=1024|duration_time=0.023220|size=247|pos=3943|flags=K_ +packet|codec_type=audio|stream_index=0|pts=18432|pts_time=0.417959|dts=18432|dts_time=0.417959|duration=1024|duration_time=0.023220|size=202|pos=4190|flags=K_ +packet|codec_type=audio|stream_index=0|pts=19456|pts_time=0.441179|dts=19456|dts_time=0.441179|duration=1024|duration_time=0.023220|size=186|pos=4392|flags=K_ +packet|codec_type=audio|stream_index=0|pts=20480|pts_time=0.464399|dts=20480|dts_time=0.464399|duration=1024|duration_time=0.023220|size=196|pos=4578|flags=K_ +packet|codec_type=audio|stream_index=0|pts=21504|pts_time=0.487619|dts=21504|dts_time=0.487619|duration=1024|duration_time=0.023220|size=200|pos=4774|flags=K_ +packet|codec_type=audio|stream_index=0|pts=22528|pts_time=0.510839|dts=22528|dts_time=0.510839|duration=1024|duration_time=0.023220|size=170|pos=4974|flags=K_ +packet|codec_type=audio|stream_index=0|pts=23552|pts_time=0.534059|dts=23552|dts_time=0.534059|duration=1024|duration_time=0.023220|size=172|pos=5144|flags=K_ +packet|codec_type=audio|stream_index=0|pts=24576|pts_time=0.557279|dts=24576|dts_time=0.557279|duration=1024|duration_time=0.023220|size=206|pos=5316|flags=K_ +packet|codec_type=audio|stream_index=0|pts=25600|pts_time=0.580499|dts=25600|dts_time=0.580499|duration=1024|duration_time=0.023220|size=208|pos=5522|flags=K_ +packet|codec_type=audio|stream_index=0|pts=26624|pts_time=0.603719|dts=26624|dts_time=0.603719|duration=1024|duration_time=0.023220|size=217|pos=5730|flags=K_ +packet|codec_type=audio|stream_index=0|pts=27648|pts_time=0.626939|dts=27648|dts_time=0.626939|duration=1024|duration_time=0.023220|size=252|pos=5947|flags=K_ +packet|codec_type=audio|stream_index=0|pts=28672|pts_time=0.650159|dts=28672|dts_time=0.650159|duration=1024|duration_time=0.023220|size=171|pos=6199|flags=K_ +packet|codec_type=audio|stream_index=0|pts=29696|pts_time=0.673379|dts=29696|dts_time=0.673379|duration=1024|duration_time=0.023220|size=206|pos=6370|flags=K_ +packet|codec_type=audio|stream_index=0|pts=30720|pts_time=0.696599|dts=30720|dts_time=0.696599|duration=1024|duration_time=0.023220|size=237|pos=6576|flags=K_ +packet|codec_type=audio|stream_index=0|pts=31744|pts_time=0.719819|dts=31744|dts_time=0.719819|duration=1024|duration_time=0.023220|size=210|pos=6813|flags=K_ +packet|codec_type=audio|stream_index=0|pts=32768|pts_time=0.743039|dts=32768|dts_time=0.743039|duration=1024|duration_time=0.023220|size=166|pos=7023|flags=K_ +packet|codec_type=audio|stream_index=0|pts=33792|pts_time=0.766259|dts=33792|dts_time=0.766259|duration=1024|duration_time=0.023220|size=166|pos=7189|flags=K_ +packet|codec_type=audio|stream_index=0|pts=34816|pts_time=0.789478|dts=34816|dts_time=0.789478|duration=1024|duration_time=0.023220|size=177|pos=7355|flags=K_ +packet|codec_type=audio|stream_index=0|pts=35840|pts_time=0.812698|dts=35840|dts_time=0.812698|duration=1024|duration_time=0.023220|size=188|pos=7532|flags=K_ +packet|codec_type=audio|stream_index=0|pts=36864|pts_time=0.835918|dts=36864|dts_time=0.835918|duration=1024|duration_time=0.023220|size=193|pos=7720|flags=K_ +packet|codec_type=audio|stream_index=0|pts=37888|pts_time=0.859138|dts=37888|dts_time=0.859138|duration=1024|duration_time=0.023220|size=195|pos=7913|flags=K_ +packet|codec_type=audio|stream_index=0|pts=38912|pts_time=0.882358|dts=38912|dts_time=0.882358|duration=1024|duration_time=0.023220|size=211|pos=8108|flags=K_ +packet|codec_type=audio|stream_index=0|pts=39936|pts_time=0.905578|dts=39936|dts_time=0.905578|duration=1024|duration_time=0.023220|size=249|pos=8319|flags=K_ +packet|codec_type=audio|stream_index=0|pts=40960|pts_time=0.928798|dts=40960|dts_time=0.928798|duration=1024|duration_time=0.023220|size=223|pos=8568|flags=K_ +packet|codec_type=audio|stream_index=0|pts=41984|pts_time=0.952018|dts=41984|dts_time=0.952018|duration=1024|duration_time=0.023220|size=230|pos=8791|flags=K_ +packet|codec_type=audio|stream_index=0|pts=43008|pts_time=0.975238|dts=43008|dts_time=0.975238|duration=1024|duration_time=0.023220|size=203|pos=9021|flags=K_ +packet|codec_type=audio|stream_index=0|pts=44032|pts_time=0.998458|dts=44032|dts_time=0.998458|duration=1024|duration_time=0.023220|size=180|pos=9224|flags=K_ +packet|codec_type=audio|stream_index=0|pts=45056|pts_time=1.021678|dts=45056|dts_time=1.021678|duration=1024|duration_time=0.023220|size=172|pos=9404|flags=K_ +packet|codec_type=audio|stream_index=0|pts=46080|pts_time=1.044898|dts=46080|dts_time=1.044898|duration=1024|duration_time=0.023220|size=240|pos=9576|flags=K_ +packet|codec_type=audio|stream_index=0|pts=47104|pts_time=1.068118|dts=47104|dts_time=1.068118|duration=1024|duration_time=0.023220|size=179|pos=9816|flags=K_ +packet|codec_type=audio|stream_index=0|pts=48128|pts_time=1.091338|dts=48128|dts_time=1.091338|duration=1024|duration_time=0.023220|size=191|pos=9995|flags=K_ +packet|codec_type=audio|stream_index=0|pts=49152|pts_time=1.114558|dts=49152|dts_time=1.114558|duration=1024|duration_time=0.023220|size=184|pos=10186|flags=K_ +packet|codec_type=audio|stream_index=0|pts=50176|pts_time=1.137778|dts=50176|dts_time=1.137778|duration=1024|duration_time=0.023220|size=214|pos=10370|flags=K_ +packet|codec_type=audio|stream_index=0|pts=51200|pts_time=1.160998|dts=51200|dts_time=1.160998|duration=1024|duration_time=0.023220|size=194|pos=10584|flags=K_ +packet|codec_type=audio|stream_index=0|pts=52224|pts_time=1.184218|dts=52224|dts_time=1.184218|duration=1024|duration_time=0.023220|size=235|pos=10778|flags=K_ +packet|codec_type=audio|stream_index=0|pts=53248|pts_time=1.207438|dts=53248|dts_time=1.207438|duration=1024|duration_time=0.023220|size=195|pos=11013|flags=K_ +packet|codec_type=audio|stream_index=0|pts=54272|pts_time=1.230658|dts=54272|dts_time=1.230658|duration=1024|duration_time=0.023220|size=220|pos=11208|flags=K_ +packet|codec_type=audio|stream_index=0|pts=55296|pts_time=1.253878|dts=55296|dts_time=1.253878|duration=1024|duration_time=0.023220|size=187|pos=11428|flags=K_ +packet|codec_type=audio|stream_index=0|pts=56320|pts_time=1.277098|dts=56320|dts_time=1.277098|duration=1024|duration_time=0.023220|size=238|pos=11615|flags=K_ +packet|codec_type=audio|stream_index=0|pts=57344|pts_time=1.300317|dts=57344|dts_time=1.300317|duration=1024|duration_time=0.023220|size=175|pos=11853|flags=K_ +packet|codec_type=audio|stream_index=0|pts=58368|pts_time=1.323537|dts=58368|dts_time=1.323537|duration=1024|duration_time=0.023220|size=178|pos=12028|flags=K_ +packet|codec_type=audio|stream_index=0|pts=59392|pts_time=1.346757|dts=59392|dts_time=1.346757|duration=1024|duration_time=0.023220|size=219|pos=12206|flags=K_ +packet|codec_type=audio|stream_index=0|pts=60416|pts_time=1.369977|dts=60416|dts_time=1.369977|duration=1024|duration_time=0.023220|size=179|pos=12425|flags=K_ +packet|codec_type=audio|stream_index=0|pts=61440|pts_time=1.393197|dts=61440|dts_time=1.393197|duration=1024|duration_time=0.023220|size=193|pos=12604|flags=K_ +packet|codec_type=audio|stream_index=0|pts=62464|pts_time=1.416417|dts=62464|dts_time=1.416417|duration=1024|duration_time=0.023220|size=200|pos=12797|flags=K_ +packet|codec_type=audio|stream_index=0|pts=63488|pts_time=1.439637|dts=63488|dts_time=1.439637|duration=1024|duration_time=0.023220|size=218|pos=12997|flags=K_ +packet|codec_type=audio|stream_index=0|pts=64512|pts_time=1.462857|dts=64512|dts_time=1.462857|duration=1024|duration_time=0.023220|size=215|pos=13215|flags=K_ +packet|codec_type=audio|stream_index=0|pts=65536|pts_time=1.486077|dts=65536|dts_time=1.486077|duration=1024|duration_time=0.023220|size=209|pos=13430|flags=K_ +packet|codec_type=audio|stream_index=0|pts=66560|pts_time=1.509297|dts=66560|dts_time=1.509297|duration=1024|duration_time=0.023220|size=171|pos=13639|flags=K_ +packet|codec_type=audio|stream_index=0|pts=67584|pts_time=1.532517|dts=67584|dts_time=1.532517|duration=1024|duration_time=0.023220|size=179|pos=13810|flags=K_ +packet|codec_type=audio|stream_index=0|pts=68608|pts_time=1.555737|dts=68608|dts_time=1.555737|duration=1024|duration_time=0.023220|size=185|pos=13989|flags=K_ +packet|codec_type=audio|stream_index=0|pts=69632|pts_time=1.578957|dts=69632|dts_time=1.578957|duration=1024|duration_time=0.023220|size=225|pos=14174|flags=K_ +packet|codec_type=audio|stream_index=0|pts=70656|pts_time=1.602177|dts=70656|dts_time=1.602177|duration=1024|duration_time=0.023220|size=221|pos=14399|flags=K_ +packet|codec_type=audio|stream_index=0|pts=71680|pts_time=1.625397|dts=71680|dts_time=1.625397|duration=1024|duration_time=0.023220|size=201|pos=14620|flags=K_ +packet|codec_type=audio|stream_index=0|pts=72704|pts_time=1.648617|dts=72704|dts_time=1.648617|duration=1024|duration_time=0.023220|size=206|pos=14821|flags=K_ +packet|codec_type=audio|stream_index=0|pts=73728|pts_time=1.671837|dts=73728|dts_time=1.671837|duration=1024|duration_time=0.023220|size=182|pos=15027|flags=K_ +packet|codec_type=audio|stream_index=0|pts=74752|pts_time=1.695057|dts=74752|dts_time=1.695057|duration=1024|duration_time=0.023220|size=176|pos=15209|flags=K_ +packet|codec_type=audio|stream_index=0|pts=75776|pts_time=1.718277|dts=75776|dts_time=1.718277|duration=1024|duration_time=0.023220|size=233|pos=15385|flags=K_ +packet|codec_type=audio|stream_index=0|pts=76800|pts_time=1.741497|dts=76800|dts_time=1.741497|duration=1024|duration_time=0.023220|size=199|pos=15618|flags=K_ +packet|codec_type=audio|stream_index=0|pts=77824|pts_time=1.764717|dts=77824|dts_time=1.764717|duration=1024|duration_time=0.023220|size=220|pos=15817|flags=K_ +packet|codec_type=audio|stream_index=0|pts=78848|pts_time=1.787937|dts=78848|dts_time=1.787937|duration=1024|duration_time=0.023220|size=190|pos=16037|flags=K_ +packet|codec_type=audio|stream_index=0|pts=79872|pts_time=1.811156|dts=79872|dts_time=1.811156|duration=1024|duration_time=0.023220|size=210|pos=16227|flags=K_ +packet|codec_type=audio|stream_index=0|pts=80896|pts_time=1.834376|dts=80896|dts_time=1.834376|duration=1024|duration_time=0.023220|size=204|pos=16437|flags=K_ +packet|codec_type=audio|stream_index=0|pts=81920|pts_time=1.857596|dts=81920|dts_time=1.857596|duration=1024|duration_time=0.023220|size=171|pos=16641|flags=K_ +packet|codec_type=audio|stream_index=0|pts=82944|pts_time=1.880816|dts=82944|dts_time=1.880816|duration=1024|duration_time=0.023220|size=167|pos=16812|flags=K_ +packet|codec_type=audio|stream_index=0|pts=83968|pts_time=1.904036|dts=83968|dts_time=1.904036|duration=1024|duration_time=0.023220|size=200|pos=16979|flags=K_ +packet|codec_type=audio|stream_index=0|pts=84992|pts_time=1.927256|dts=84992|dts_time=1.927256|duration=1024|duration_time=0.023220|size=254|pos=17179|flags=K_ +packet|codec_type=audio|stream_index=0|pts=86016|pts_time=1.950476|dts=86016|dts_time=1.950476|duration=1024|duration_time=0.023220|size=205|pos=17433|flags=K_ +packet|codec_type=audio|stream_index=0|pts=87040|pts_time=1.973696|dts=87040|dts_time=1.973696|duration=1024|duration_time=0.023220|size=196|pos=17638|flags=K_ +packet|codec_type=audio|stream_index=0|pts=88064|pts_time=1.996916|dts=88064|dts_time=1.996916|duration=1024|duration_time=0.023220|size=190|pos=17834|flags=K_ +packet|codec_type=audio|stream_index=0|pts=89088|pts_time=2.020136|dts=89088|dts_time=2.020136|duration=1024|duration_time=0.023220|size=197|pos=18024|flags=K_ +packet|codec_type=audio|stream_index=0|pts=90112|pts_time=2.043356|dts=90112|dts_time=2.043356|duration=1024|duration_time=0.023220|size=186|pos=18221|flags=K_ +packet|codec_type=audio|stream_index=0|pts=91136|pts_time=2.066576|dts=91136|dts_time=2.066576|duration=1024|duration_time=0.023220|size=194|pos=18407|flags=K_ +packet|codec_type=audio|stream_index=0|pts=92160|pts_time=2.089796|dts=92160|dts_time=2.089796|duration=1024|duration_time=0.023220|size=227|pos=18601|flags=K_ +packet|codec_type=audio|stream_index=0|pts=93184|pts_time=2.113016|dts=93184|dts_time=2.113016|duration=1024|duration_time=0.023220|size=195|pos=18828|flags=K_ +packet|codec_type=audio|stream_index=0|pts=94208|pts_time=2.136236|dts=94208|dts_time=2.136236|duration=1024|duration_time=0.023220|size=228|pos=19023|flags=K_ +packet|codec_type=audio|stream_index=0|pts=95232|pts_time=2.159456|dts=95232|dts_time=2.159456|duration=1024|duration_time=0.023220|size=196|pos=19251|flags=K_ +packet|codec_type=audio|stream_index=0|pts=96256|pts_time=2.182676|dts=96256|dts_time=2.182676|duration=1024|duration_time=0.023220|size=197|pos=19447|flags=K_ +packet|codec_type=audio|stream_index=0|pts=97280|pts_time=2.205896|dts=97280|dts_time=2.205896|duration=1024|duration_time=0.023220|size=186|pos=19644|flags=K_ +packet|codec_type=audio|stream_index=0|pts=98304|pts_time=2.229116|dts=98304|dts_time=2.229116|duration=1024|duration_time=0.023220|size=191|pos=19830|flags=K_ +packet|codec_type=audio|stream_index=0|pts=99328|pts_time=2.252336|dts=99328|dts_time=2.252336|duration=1024|duration_time=0.023220|size=215|pos=20021|flags=K_ +packet|codec_type=audio|stream_index=0|pts=100352|pts_time=2.275556|dts=100352|dts_time=2.275556|duration=1024|duration_time=0.023220|size=203|pos=20236|flags=K_ +packet|codec_type=audio|stream_index=0|pts=101376|pts_time=2.298776|dts=101376|dts_time=2.298776|duration=1024|duration_time=0.023220|size=205|pos=20439|flags=K_ +packet|codec_type=audio|stream_index=0|pts=102400|pts_time=2.321995|dts=102400|dts_time=2.321995|duration=1024|duration_time=0.023220|size=205|pos=20644|flags=K_ +packet|codec_type=audio|stream_index=0|pts=103424|pts_time=2.345215|dts=103424|dts_time=2.345215|duration=1024|duration_time=0.023220|size=213|pos=20849|flags=K_ +packet|codec_type=audio|stream_index=0|pts=104448|pts_time=2.368435|dts=104448|dts_time=2.368435|duration=1024|duration_time=0.023220|size=198|pos=21062|flags=K_ +packet|codec_type=audio|stream_index=0|pts=105472|pts_time=2.391655|dts=105472|dts_time=2.391655|duration=1024|duration_time=0.023220|size=178|pos=21260|flags=K_ +packet|codec_type=audio|stream_index=0|pts=106496|pts_time=2.414875|dts=106496|dts_time=2.414875|duration=1024|duration_time=0.023220|size=195|pos=21438|flags=K_ +packet|codec_type=audio|stream_index=0|pts=107520|pts_time=2.438095|dts=107520|dts_time=2.438095|duration=1024|duration_time=0.023220|size=227|pos=21633|flags=K_ +packet|codec_type=audio|stream_index=0|pts=108544|pts_time=2.461315|dts=108544|dts_time=2.461315|duration=1024|duration_time=0.023220|size=185|pos=21860|flags=K_ +packet|codec_type=audio|stream_index=0|pts=109568|pts_time=2.484535|dts=109568|dts_time=2.484535|duration=1024|duration_time=0.023220|size=206|pos=22045|flags=K_ +packet|codec_type=audio|stream_index=0|pts=110592|pts_time=2.507755|dts=110592|dts_time=2.507755|duration=1024|duration_time=0.023220|size=183|pos=22251|flags=K_ +packet|codec_type=audio|stream_index=0|pts=111616|pts_time=2.530975|dts=111616|dts_time=2.530975|duration=1024|duration_time=0.023220|size=208|pos=22434|flags=K_ +packet|codec_type=audio|stream_index=0|pts=112640|pts_time=2.554195|dts=112640|dts_time=2.554195|duration=1024|duration_time=0.023220|size=204|pos=22642|flags=K_ +packet|codec_type=audio|stream_index=0|pts=113664|pts_time=2.577415|dts=113664|dts_time=2.577415|duration=1024|duration_time=0.023220|size=192|pos=22846|flags=K_ +packet|codec_type=audio|stream_index=0|pts=114688|pts_time=2.600635|dts=114688|dts_time=2.600635|duration=1024|duration_time=0.023220|size=190|pos=23038|flags=K_ +packet|codec_type=audio|stream_index=0|pts=115712|pts_time=2.623855|dts=115712|dts_time=2.623855|duration=1024|duration_time=0.023220|size=199|pos=23228|flags=K_ +packet|codec_type=audio|stream_index=0|pts=116736|pts_time=2.647075|dts=116736|dts_time=2.647075|duration=1024|duration_time=0.023220|size=229|pos=23427|flags=K_ +packet|codec_type=audio|stream_index=0|pts=117760|pts_time=2.670295|dts=117760|dts_time=2.670295|duration=1024|duration_time=0.023220|size=208|pos=23656|flags=K_ +packet|codec_type=audio|stream_index=0|pts=118784|pts_time=2.693515|dts=118784|dts_time=2.693515|duration=1024|duration_time=0.023220|size=195|pos=23864|flags=K_ +packet|codec_type=audio|stream_index=0|pts=119808|pts_time=2.716735|dts=119808|dts_time=2.716735|duration=1024|duration_time=0.023220|size=190|pos=24059|flags=K_ +packet|codec_type=audio|stream_index=0|pts=120832|pts_time=2.739955|dts=120832|dts_time=2.739955|duration=1024|duration_time=0.023220|size=190|pos=24249|flags=K_ +packet|codec_type=audio|stream_index=0|pts=121856|pts_time=2.763175|dts=121856|dts_time=2.763175|duration=1024|duration_time=0.023220|size=192|pos=24439|flags=K_ +packet|codec_type=audio|stream_index=0|pts=122880|pts_time=2.786395|dts=122880|dts_time=2.786395|duration=1024|duration_time=0.023220|size=226|pos=24631|flags=K_ +packet|codec_type=audio|stream_index=0|pts=123904|pts_time=2.809615|dts=123904|dts_time=2.809615|duration=1024|duration_time=0.023220|size=195|pos=24857|flags=K_ +packet|codec_type=audio|stream_index=0|pts=124928|pts_time=2.832834|dts=124928|dts_time=2.832834|duration=1024|duration_time=0.023220|size=230|pos=25052|flags=K_ +packet|codec_type=audio|stream_index=0|pts=125952|pts_time=2.856054|dts=125952|dts_time=2.856054|duration=1024|duration_time=0.023220|size=198|pos=25282|flags=K_ +packet|codec_type=audio|stream_index=0|pts=126976|pts_time=2.879274|dts=126976|dts_time=2.879274|duration=1024|duration_time=0.023220|size=183|pos=25480|flags=K_ +packet|codec_type=audio|stream_index=0|pts=128000|pts_time=2.902494|dts=128000|dts_time=2.902494|duration=1024|duration_time=0.023220|size=199|pos=25663|flags=K_ +packet|codec_type=audio|stream_index=0|pts=129024|pts_time=2.925714|dts=129024|dts_time=2.925714|duration=1024|duration_time=0.023220|size=196|pos=25862|flags=K_ +packet|codec_type=audio|stream_index=0|pts=130048|pts_time=2.948934|dts=130048|dts_time=2.948934|duration=1024|duration_time=0.023220|size=186|pos=26058|flags=K_ +packet|codec_type=audio|stream_index=0|pts=131072|pts_time=2.972154|dts=131072|dts_time=2.972154|duration=1024|duration_time=0.023220|size=200|pos=26244|flags=K_ +packet|codec_type=audio|stream_index=0|pts=132096|pts_time=2.995374|dts=132096|dts_time=2.995374|duration=1024|duration_time=0.023220|size=210|pos=26444|flags=K_ +packet|codec_type=audio|stream_index=0|pts=133120|pts_time=3.018594|dts=133120|dts_time=3.018594|duration=1024|duration_time=0.023220|size=196|pos=26654|flags=K_ +packet|codec_type=audio|stream_index=0|pts=134144|pts_time=3.041814|dts=134144|dts_time=3.041814|duration=1024|duration_time=0.023220|size=214|pos=26850|flags=K_ +packet|codec_type=audio|stream_index=0|pts=135168|pts_time=3.065034|dts=135168|dts_time=3.065034|duration=1024|duration_time=0.023220|size=185|pos=27064|flags=K_ +packet|codec_type=audio|stream_index=0|pts=136192|pts_time=3.088254|dts=136192|dts_time=3.088254|duration=1024|duration_time=0.023220|size=198|pos=27249|flags=K_ +packet|codec_type=audio|stream_index=0|pts=137216|pts_time=3.111474|dts=137216|dts_time=3.111474|duration=1024|duration_time=0.023220|size=200|pos=27447|flags=K_ +packet|codec_type=audio|stream_index=0|pts=138240|pts_time=3.134694|dts=138240|dts_time=3.134694|duration=1024|duration_time=0.023220|size=208|pos=27647|flags=K_ +packet|codec_type=audio|stream_index=0|pts=139264|pts_time=3.157914|dts=139264|dts_time=3.157914|duration=1024|duration_time=0.023220|size=212|pos=27855|flags=K_ +packet|codec_type=audio|stream_index=0|pts=140288|pts_time=3.181134|dts=140288|dts_time=3.181134|duration=1024|duration_time=0.023220|size=208|pos=28067|flags=K_ +packet|codec_type=audio|stream_index=0|pts=141312|pts_time=3.204354|dts=141312|dts_time=3.204354|duration=1024|duration_time=0.023220|size=192|pos=28275|flags=K_ +packet|codec_type=audio|stream_index=0|pts=142336|pts_time=3.227574|dts=142336|dts_time=3.227574|duration=1024|duration_time=0.023220|size=192|pos=28467|flags=K_ +packet|codec_type=audio|stream_index=0|pts=143360|pts_time=3.250794|dts=143360|dts_time=3.250794|duration=1024|duration_time=0.023220|size=211|pos=28659|flags=K_ +packet|codec_type=audio|stream_index=0|pts=144384|pts_time=3.274014|dts=144384|dts_time=3.274014|duration=1024|duration_time=0.023220|size=195|pos=28870|flags=K_ +packet|codec_type=audio|stream_index=0|pts=145408|pts_time=3.297234|dts=145408|dts_time=3.297234|duration=1024|duration_time=0.023220|size=208|pos=29065|flags=K_ +packet|codec_type=audio|stream_index=0|pts=146432|pts_time=3.320454|dts=146432|dts_time=3.320454|duration=1024|duration_time=0.023220|size=195|pos=29273|flags=K_ +packet|codec_type=audio|stream_index=0|pts=147456|pts_time=3.343673|dts=147456|dts_time=3.343673|duration=1024|duration_time=0.023220|size=204|pos=29468|flags=K_ +packet|codec_type=audio|stream_index=0|pts=148480|pts_time=3.366893|dts=148480|dts_time=3.366893|duration=1024|duration_time=0.023220|size=209|pos=29672|flags=K_ +packet|codec_type=audio|stream_index=0|pts=149504|pts_time=3.390113|dts=149504|dts_time=3.390113|duration=1024|duration_time=0.023220|size=195|pos=29881|flags=K_ +packet|codec_type=audio|stream_index=0|pts=150528|pts_time=3.413333|dts=150528|dts_time=3.413333|duration=1024|duration_time=0.023220|size=191|pos=30076|flags=K_ +packet|codec_type=audio|stream_index=0|pts=151552|pts_time=3.436553|dts=151552|dts_time=3.436553|duration=1024|duration_time=0.023220|size=210|pos=30267|flags=K_ +packet|codec_type=audio|stream_index=0|pts=152576|pts_time=3.459773|dts=152576|dts_time=3.459773|duration=1024|duration_time=0.023220|size=209|pos=30477|flags=K_ +packet|codec_type=audio|stream_index=0|pts=153600|pts_time=3.482993|dts=153600|dts_time=3.482993|duration=1024|duration_time=0.023220|size=175|pos=30686|flags=K_ +packet|codec_type=audio|stream_index=0|pts=154624|pts_time=3.506213|dts=154624|dts_time=3.506213|duration=1024|duration_time=0.023220|size=244|pos=30861|flags=K_ +packet|codec_type=audio|stream_index=0|pts=155648|pts_time=3.529433|dts=155648|dts_time=3.529433|duration=1024|duration_time=0.023220|size=177|pos=31105|flags=K_ +packet|codec_type=audio|stream_index=0|pts=156672|pts_time=3.552653|dts=156672|dts_time=3.552653|duration=1024|duration_time=0.023220|size=217|pos=31282|flags=K_ +packet|codec_type=audio|stream_index=0|pts=157696|pts_time=3.575873|dts=157696|dts_time=3.575873|duration=1024|duration_time=0.023220|size=182|pos=31499|flags=K_ +packet|codec_type=audio|stream_index=0|pts=158720|pts_time=3.599093|dts=158720|dts_time=3.599093|duration=1024|duration_time=0.023220|size=181|pos=31681|flags=K_ +packet|codec_type=audio|stream_index=0|pts=159744|pts_time=3.622313|dts=159744|dts_time=3.622313|duration=1024|duration_time=0.023220|size=203|pos=31862|flags=K_ +packet|codec_type=audio|stream_index=0|pts=160768|pts_time=3.645533|dts=160768|dts_time=3.645533|duration=1024|duration_time=0.023220|size=198|pos=32065|flags=K_ +packet|codec_type=audio|stream_index=0|pts=161792|pts_time=3.668753|dts=161792|dts_time=3.668753|duration=1024|duration_time=0.023220|size=217|pos=32263|flags=K_ +packet|codec_type=audio|stream_index=0|pts=162816|pts_time=3.691973|dts=162816|dts_time=3.691973|duration=1024|duration_time=0.023220|size=195|pos=32480|flags=K_ +packet|codec_type=audio|stream_index=0|pts=163840|pts_time=3.715193|dts=163840|dts_time=3.715193|duration=1024|duration_time=0.023220|size=198|pos=32675|flags=K_ +packet|codec_type=audio|stream_index=0|pts=164864|pts_time=3.738413|dts=164864|dts_time=3.738413|duration=1024|duration_time=0.023220|size=202|pos=32873|flags=K_ +packet|codec_type=audio|stream_index=0|pts=165888|pts_time=3.761633|dts=165888|dts_time=3.761633|duration=1024|duration_time=0.023220|size=185|pos=33075|flags=K_ +packet|codec_type=audio|stream_index=0|pts=166912|pts_time=3.784853|dts=166912|dts_time=3.784853|duration=1024|duration_time=0.023220|size=196|pos=33260|flags=K_ +packet|codec_type=audio|stream_index=0|pts=167936|pts_time=3.808073|dts=167936|dts_time=3.808073|duration=1024|duration_time=0.023220|size=226|pos=33456|flags=K_ +packet|codec_type=audio|stream_index=0|pts=168960|pts_time=3.831293|dts=168960|dts_time=3.831293|duration=1024|duration_time=0.023220|size=187|pos=33682|flags=K_ +packet|codec_type=audio|stream_index=0|pts=169984|pts_time=3.854512|dts=169984|dts_time=3.854512|duration=1024|duration_time=0.023220|size=193|pos=33869|flags=K_ +packet|codec_type=audio|stream_index=0|pts=171008|pts_time=3.877732|dts=171008|dts_time=3.877732|duration=1024|duration_time=0.023220|size=218|pos=34062|flags=K_ +packet|codec_type=audio|stream_index=0|pts=172032|pts_time=3.900952|dts=172032|dts_time=3.900952|duration=1024|duration_time=0.023220|size=200|pos=34280|flags=K_ +packet|codec_type=audio|stream_index=0|pts=173056|pts_time=3.924172|dts=173056|dts_time=3.924172|duration=1024|duration_time=0.023220|size=200|pos=34480|flags=K_ +packet|codec_type=audio|stream_index=0|pts=174080|pts_time=3.947392|dts=174080|dts_time=3.947392|duration=1024|duration_time=0.023220|size=198|pos=34680|flags=K_ +packet|codec_type=audio|stream_index=0|pts=175104|pts_time=3.970612|dts=175104|dts_time=3.970612|duration=1024|duration_time=0.023220|size=200|pos=34878|flags=K_ +packet|codec_type=audio|stream_index=0|pts=176128|pts_time=3.993832|dts=176128|dts_time=3.993832|duration=1024|duration_time=0.023220|size=197|pos=35078|flags=K_ +packet|codec_type=audio|stream_index=0|pts=177152|pts_time=4.017052|dts=177152|dts_time=4.017052|duration=1024|duration_time=0.023220|size=209|pos=35275|flags=K_ +packet|codec_type=audio|stream_index=0|pts=178176|pts_time=4.040272|dts=178176|dts_time=4.040272|duration=1024|duration_time=0.023220|size=205|pos=35484|flags=K_ +packet|codec_type=audio|stream_index=0|pts=179200|pts_time=4.063492|dts=179200|dts_time=4.063492|duration=1024|duration_time=0.023220|size=199|pos=35689|flags=K_ +packet|codec_type=audio|stream_index=0|pts=180224|pts_time=4.086712|dts=180224|dts_time=4.086712|duration=1024|duration_time=0.023220|size=192|pos=35888|flags=K_ +packet|codec_type=audio|stream_index=0|pts=181248|pts_time=4.109932|dts=181248|dts_time=4.109932|duration=1024|duration_time=0.023220|size=201|pos=36080|flags=K_ +packet|codec_type=audio|stream_index=0|pts=182272|pts_time=4.133152|dts=182272|dts_time=4.133152|duration=1024|duration_time=0.023220|size=200|pos=36281|flags=K_ +packet|codec_type=audio|stream_index=0|pts=183296|pts_time=4.156372|dts=183296|dts_time=4.156372|duration=1024|duration_time=0.023220|size=202|pos=36481|flags=K_ +packet|codec_type=audio|stream_index=0|pts=184320|pts_time=4.179592|dts=184320|dts_time=4.179592|duration=1024|duration_time=0.023220|size=196|pos=36683|flags=K_ +packet|codec_type=audio|stream_index=0|pts=185344|pts_time=4.202812|dts=185344|dts_time=4.202812|duration=1024|duration_time=0.023220|size=200|pos=36879|flags=K_ +packet|codec_type=audio|stream_index=0|pts=186368|pts_time=4.226032|dts=186368|dts_time=4.226032|duration=1024|duration_time=0.023220|size=209|pos=37079|flags=K_ +packet|codec_type=audio|stream_index=0|pts=187392|pts_time=4.249252|dts=187392|dts_time=4.249252|duration=1024|duration_time=0.023220|size=201|pos=37288|flags=K_ +packet|codec_type=audio|stream_index=0|pts=188416|pts_time=4.272472|dts=188416|dts_time=4.272472|duration=1024|duration_time=0.023220|size=201|pos=37489|flags=K_ +packet|codec_type=audio|stream_index=0|pts=189440|pts_time=4.295692|dts=189440|dts_time=4.295692|duration=1024|duration_time=0.023220|size=201|pos=37690|flags=K_ +packet|codec_type=audio|stream_index=0|pts=190464|pts_time=4.318912|dts=190464|dts_time=4.318912|duration=1024|duration_time=0.023220|size=199|pos=37891|flags=K_ +packet|codec_type=audio|stream_index=0|pts=191488|pts_time=4.342132|dts=191488|dts_time=4.342132|duration=1024|duration_time=0.023220|size=198|pos=38090|flags=K_ +packet|codec_type=audio|stream_index=0|pts=192512|pts_time=4.365351|dts=192512|dts_time=4.365351|duration=1024|duration_time=0.023220|size=205|pos=38288|flags=K_ +packet|codec_type=audio|stream_index=0|pts=193536|pts_time=4.388571|dts=193536|dts_time=4.388571|duration=1024|duration_time=0.023220|size=190|pos=38493|flags=K_ +packet|codec_type=audio|stream_index=0|pts=194560|pts_time=4.411791|dts=194560|dts_time=4.411791|duration=1024|duration_time=0.023220|size=207|pos=38683|flags=K_ +packet|codec_type=audio|stream_index=0|pts=195584|pts_time=4.435011|dts=195584|dts_time=4.435011|duration=1024|duration_time=0.023220|size=204|pos=38890|flags=K_ +packet|codec_type=audio|stream_index=0|pts=196608|pts_time=4.458231|dts=196608|dts_time=4.458231|duration=1024|duration_time=0.023220|size=192|pos=39094|flags=K_ +packet|codec_type=audio|stream_index=0|pts=197632|pts_time=4.481451|dts=197632|dts_time=4.481451|duration=1024|duration_time=0.023220|size=211|pos=39286|flags=K_ +packet|codec_type=audio|stream_index=0|pts=198656|pts_time=4.504671|dts=198656|dts_time=4.504671|duration=1024|duration_time=0.023220|size=195|pos=39497|flags=K_ +packet|codec_type=audio|stream_index=0|pts=199680|pts_time=4.527891|dts=199680|dts_time=4.527891|duration=1024|duration_time=0.023220|size=214|pos=39692|flags=K_ +packet|codec_type=audio|stream_index=0|pts=200704|pts_time=4.551111|dts=200704|dts_time=4.551111|duration=1024|duration_time=0.023220|size=195|pos=39906|flags=K_ +packet|codec_type=audio|stream_index=0|pts=201728|pts_time=4.574331|dts=201728|dts_time=4.574331|duration=1024|duration_time=0.023220|size=199|pos=40101|flags=K_ +packet|codec_type=audio|stream_index=0|pts=202752|pts_time=4.597551|dts=202752|dts_time=4.597551|duration=1024|duration_time=0.023220|size=183|pos=40300|flags=K_ +packet|codec_type=audio|stream_index=0|pts=203776|pts_time=4.620771|dts=203776|dts_time=4.620771|duration=1024|duration_time=0.023220|size=211|pos=40483|flags=K_ +packet|codec_type=audio|stream_index=0|pts=204800|pts_time=4.643991|dts=204800|dts_time=4.643991|duration=1024|duration_time=0.023220|size=200|pos=40694|flags=K_ +packet|codec_type=audio|stream_index=0|pts=205824|pts_time=4.667211|dts=205824|dts_time=4.667211|duration=1024|duration_time=0.023220|size=199|pos=40894|flags=K_ +packet|codec_type=audio|stream_index=0|pts=206848|pts_time=4.690431|dts=206848|dts_time=4.690431|duration=1024|duration_time=0.023220|size=213|pos=41093|flags=K_ +packet|codec_type=audio|stream_index=0|pts=207872|pts_time=4.713651|dts=207872|dts_time=4.713651|duration=1024|duration_time=0.023220|size=191|pos=41306|flags=K_ +packet|codec_type=audio|stream_index=0|pts=208896|pts_time=4.736871|dts=208896|dts_time=4.736871|duration=1024|duration_time=0.023220|size=211|pos=41497|flags=K_ +packet|codec_type=audio|stream_index=0|pts=209920|pts_time=4.760091|dts=209920|dts_time=4.760091|duration=1024|duration_time=0.023220|size=198|pos=41708|flags=K_ +packet|codec_type=audio|stream_index=0|pts=210944|pts_time=4.783311|dts=210944|dts_time=4.783311|duration=1024|duration_time=0.023220|size=203|pos=41906|flags=K_ +packet|codec_type=audio|stream_index=0|pts=211968|pts_time=4.806531|dts=211968|dts_time=4.806531|duration=1024|duration_time=0.023220|size=196|pos=42109|flags=K_ +packet|codec_type=audio|stream_index=0|pts=212992|pts_time=4.829751|dts=212992|dts_time=4.829751|duration=1024|duration_time=0.023220|size=197|pos=42305|flags=K_ +packet|codec_type=audio|stream_index=0|pts=214016|pts_time=4.852971|dts=214016|dts_time=4.852971|duration=1024|duration_time=0.023220|size=190|pos=42502|flags=K_ +packet|codec_type=audio|stream_index=0|pts=215040|pts_time=4.876190|dts=215040|dts_time=4.876190|duration=1024|duration_time=0.023220|size=208|pos=42692|flags=K_ +packet|codec_type=audio|stream_index=0|pts=216064|pts_time=4.899410|dts=216064|dts_time=4.899410|duration=1024|duration_time=0.023220|size=203|pos=42900|flags=K_ +packet|codec_type=audio|stream_index=0|pts=217088|pts_time=4.922630|dts=217088|dts_time=4.922630|duration=1024|duration_time=0.023220|size=198|pos=43103|flags=K_ +packet|codec_type=audio|stream_index=0|pts=218112|pts_time=4.945850|dts=218112|dts_time=4.945850|duration=1024|duration_time=0.023220|size=284|pos=43301|flags=K_ +packet|codec_type=audio|stream_index=0|pts=219136|pts_time=4.969070|dts=219136|dts_time=4.969070|duration=1364|duration_time=0.030930|size=5|pos=43585|flags=K_ diff -Nru ffmpeg-4.2.2/tests/ref/fate/movenc ffmpeg-4.4/tests/ref/fate/movenc --- ffmpeg-4.2.2/tests/ref/fate/movenc 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/movenc 2021-04-08 21:28:40.000000000 +0000 @@ -1,128 +1,128 @@ write_data len 36, time nopts, type header atom ftyp -write_data len 2389, time nopts, type header atom - +write_data len 2429, time nopts, type header atom - write_data len 788, time 1000000, type sync atom moof write_data len 110, time nopts, type trailer atom - -17a37691eba8b858cf15e60aa9a7dbf7 3323 non-empty-moov +6f06e338c71468d56580df40ff265066 3363 non-empty-moov write_data len 36, time nopts, type header atom ftyp -write_data len 2721, time nopts, type header atom - +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 - -0026ffe059c06c592021f972bf2c5e79 3775 non-empty-moov-elst +caf0876986b5f033efc0958c338289cc 3815 non-empty-moov-elst write_data len 36, time nopts, type header atom ftyp -write_data len 2629, time nopts, type header atom - +write_data len 2669, time nopts, type header atom - write_data len 908, time 1000000, type sync atom moof write_data len 110, time nopts, type trailer atom - -c184e168ac1e5bb3d9c70e580ab6179c 3683 non-empty-moov-no-elst -write_data len 20, time nopts, type header atom ftyp +e106084014ed245ed7c4a30f1d11a3ac 3723 non-empty-moov-no-elst +write_data len 24, time nopts, type header atom ftyp write_data len 1171, time nopts, type header atom - write_data len 728, time 0, type sync atom moof write_data len 828, time nopts, type unknown atom - -write_data len 728, time 1046439, type sync atom moof +write_data len 728, time 999999, type sync atom moof write_data len 812, time nopts, type unknown atom - write_data len 148, time nopts, type trailer atom - -49bf122c4c732a344ef68b58acd19be5 4435 ismv +92ce825ff40505ec8676191705adb7e7 4439 ismv write_data len 36, time nopts, type header atom ftyp write_data len 1123, time nopts, type header atom - write_data len 796, time 0, type sync atom moof write_data len 788, time 1000000, type sync atom moof write_data len 148, time nopts, type trailer atom - -ed8506ebfce4c41732205ae26a4759fd 2891 empty-moov +08f4b3ad3a3ea224b2ee731476b9056b 2891 empty-moov write_data len 36, time nopts, type header atom ftyp write_data len 1123, time nopts, type header atom - write_data len 1068, time 0, type sync atom moof write_data len 908, time 1000000, type sync atom moof write_data len 148, time nopts, type trailer atom - -1844ee6d19fd1e6daf2655632cf26310 3283 empty-moov-no-elst +d7a2dcb43eb0f95f92669f55fc7adeba 3283 empty-moov-no-elst write_data len 36, time nopts, type header atom ftyp write_data len 1123, time nopts, type header atom - write_data len 900, time -33333, type sync atom moof write_data len 908, time 966667, type sync atom moof write_data len 148, time nopts, type trailer atom - -139b27dbe2a80c2dc088d0c755f26033 3115 empty-moov-no-elst-no-adjust +ea70ca697306976879be408431c27aee 3115 empty-moov-no-elst-no-adjust write_data len 1159, time nopts, type header atom ftyp write_data len 796, time 0, type sync atom moof write_data len 788, time 1000000, type sync atom moof write_data len 148, time nopts, type trailer atom - -ed8506ebfce4c41732205ae26a4759fd 2891 delay-moov +08f4b3ad3a3ea224b2ee731476b9056b 2891 delay-moov write_data len 1231, time nopts, type header atom ftyp write_data len 916, time -33333, type sync atom moof write_data len 908, time 966667, type sync atom moof write_data len 148, time nopts, type trailer atom - -3ece148745cd64b4428530a4d1080a2d 3203 delay-moov-elst +314cc3b6296f4ee583b328a34be50b2f 3203 delay-moov-elst write_data len 1195, time nopts, type header atom ftyp write_data len 836, time 0, type sync atom moof write_data len 67, time nopts, type trailer atom - -9562946a369e6fb570fb2fd7aa2fe728 2098 delay-moov-empty-track +95d6f59a7354b0cfe7ce49927baada4e 2098 delay-moov-empty-track write_data len 1195, time nopts, type header atom ftyp write_data len 360, time 0, type sync atom moof write_data len 360, time 1000000, type sync atom moof write_data len 86, time nopts, type trailer atom - -4c7832b81836331c6c37155dc31d95be 2001 delay-moov-empty-track-flush +8805d72a27b340ea229c16edde78f974 2001 delay-moov-empty-track-flush write_data len 36, time nopts, type header atom ftyp write_data len 1123, time nopts, type header atom - -b7e3c768b9094ebe2fda44979a7f8985 1159 empty-moov-header +351ae2c8b6d35d98b4848c309cce6704 1159 empty-moov-header write_data len 796, time 0, type sync atom moof write_data len 788, time 1000000, type sync atom moof -a0165f4a26a409212b0946e981bdefb9 1584 empty-moov-content +289ee982188d66988a374a462b0b5376 1584 empty-moov-content write_data len 148, time nopts, type trailer atom - write_data len 1159, time nopts, type header atom ftyp -b7e3c768b9094ebe2fda44979a7f8985 1159 delay-moov-header +351ae2c8b6d35d98b4848c309cce6704 1159 delay-moov-header write_data len 796, time 0, type sync atom moof write_data len 788, time 1000000, type sync atom moof -a0165f4a26a409212b0946e981bdefb9 1584 delay-moov-content +289ee982188d66988a374a462b0b5376 1584 delay-moov-content write_data len 148, time nopts, type trailer atom - -write_data len 24, time nopts, type header atom - +write_data len 28, time nopts, type header atom - write_data len 1123, time nopts, type header atom - write_data len 884, time 0, type sync atom sidx write_data len 876, time 1000000, type sync atom sidx -272a474cfd2a68cc5f05b426b14a2b7d 876 empty-moov-second-frag +c0307f99a2a362205b7e3d65b1066f86 876 empty-moov-second-frag write_data len 148, time nopts, type trailer atom - -write_data len 24, time nopts, type header atom - +write_data len 28, time nopts, type header atom - write_data len 1123, time nopts, type header atom - write_data len 876, time 1000000, type sync atom sidx -272a474cfd2a68cc5f05b426b14a2b7d 876 empty-moov-second-frag-discont +c0307f99a2a362205b7e3d65b1066f86 876 empty-moov-second-frag-discont write_data len 110, time nopts, type trailer atom - -write_data len 1219, time nopts, type header atom - +write_data len 1223, time nopts, type header atom - write_data len 876, time 1000000, type sync atom sidx -272a474cfd2a68cc5f05b426b14a2b7d 876 delay-moov-second-frag-discont +c0307f99a2a362205b7e3d65b1066f86 876 delay-moov-second-frag-discont write_data len 110, time nopts, type trailer atom - -write_data len 1219, time nopts, type header atom ftyp -6ec3698bcc86013e0016e3d47d230363 1219 delay-moov-elst-init +write_data len 1223, time nopts, type header atom ftyp +b3811928793ed0749927eb2f7958421c 1223 delay-moov-elst-init write_data len 988, time -33333, type sync atom sidx write_data len 996, time 966667, type sync atom sidx -fcae8f40e015b59aabc8d4a99a759ca1 996 delay-moov-elst-second-frag +0df125407c7e81978ce722e0ae4f6f84 996 delay-moov-elst-second-frag write_data len 148, time nopts, type trailer atom - -write_data len 1219, time nopts, type header atom ftyp -6ec3698bcc86013e0016e3d47d230363 1219 delay-moov-elst-init-discont +write_data len 1223, time nopts, type header atom ftyp +b3811928793ed0749927eb2f7958421c 1223 delay-moov-elst-init-discont write_data len 996, time 966667, type sync atom sidx -fcae8f40e015b59aabc8d4a99a759ca1 996 delay-moov-elst-second-frag-discont +0df125407c7e81978ce722e0ae4f6f84 996 delay-moov-elst-second-frag-discont write_data len 110, time nopts, type trailer atom - -write_data len 1219, time nopts, type header atom ftyp -c3681590a292cb9ca19a5a982e530166 1219 delay-moov-elst-signal-init +write_data len 1223, time nopts, type header atom ftyp +041ac8efc35a0d023c26d05eedb20403 1223 delay-moov-elst-signal-init write_data len 1004, time -33333, type sync atom sidx write_data len 996, time 966667, type sync atom sidx -aa5462cc0d2144f72154d9c309edb57d 996 delay-moov-elst-signal-second-frag +5a583d89318827d2569eecbeaa18c238 996 delay-moov-elst-signal-second-frag write_data len 148, time nopts, type trailer atom - -write_data len 1219, time nopts, type header atom ftyp -c3681590a292cb9ca19a5a982e530166 1219 delay-moov-elst-signal-init-discont +write_data len 1223, time nopts, type header atom ftyp +041ac8efc35a0d023c26d05eedb20403 1223 delay-moov-elst-signal-init-discont write_data len 996, time 966667, type sync atom sidx -aa5462cc0d2144f72154d9c309edb57d 996 delay-moov-elst-signal-second-frag-discont +5a583d89318827d2569eecbeaa18c238 996 delay-moov-elst-signal-second-frag-discont write_data len 110, time nopts, type trailer atom - -write_data len 1243, time nopts, type header atom ftyp -dac14c8795d5cbd91ae770c6e2880c62 1243 delay-moov-elst-signal-init-discont-largets +write_data len 1247, time nopts, type header atom ftyp +80511a51d1ac9cde62337eed7176ae03 1247 delay-moov-elst-signal-init-discont-largets write_data len 996, time 279621233333, type sync atom sidx -41cac4c3df656a87bb38363fdcd745e6 996 delay-moov-elst-signal-second-frag-discont-largets +dc695d65e8a0cdafee28acd8a5ccf81a 996 delay-moov-elst-signal-second-frag-discont-largets write_data len 110, time nopts, type trailer atom - -write_data len 1219, time nopts, type header atom ftyp +write_data len 1223, time nopts, type header atom ftyp write_data len 2572, time -333333, type sync atom sidx write_data len 996, time 5166667, type sync atom sidx write_data len 148, time nopts, type trailer atom - -f12d4a0e054abcc508cc0d28cb320e57 4935 vfr -write_data len 1219, time nopts, type header atom ftyp +d37a7eda807912b9ed05ccfe003a9e4f 4939 vfr +write_data len 1223, time nopts, type header atom ftyp write_data len 2572, time -333333, type sync atom sidx write_data len 996, time 5166667, type sync atom sidx write_data len 148, time nopts, type trailer atom - -f12d4a0e054abcc508cc0d28cb320e57 4935 vfr-noduration +d37a7eda807912b9ed05ccfe003a9e4f 4939 vfr-noduration write_data len 1231, time nopts, type header atom ftyp write_data len 1500, time -333333, type sync atom moof write_data len 1500, time nopts, type unknown atom - @@ -131,7 +131,7 @@ write_data len 1500, time nopts, type unknown atom - write_data len 1004, time nopts, type unknown atom - write_data len 148, time nopts, type trailer atom - -3c2c3f98c8a047f0ecefff07570fd457 9299 large_frag +08b6401dc81912e5264245b7233c4ab3 9299 large_frag write_data len 1231, time nopts, type header atom ftyp write_data len 684, time -33333, type sync atom moof write_data len 504, time 800000, type boundary atom moof @@ -139,15 +139,15 @@ write_data len 668, time 1566667, type sync atom moof write_data len 440, time 2233333, type boundary atom moof write_data len 262, time nopts, type trailer atom - -edd19deae2b70afcf2cd744b89b7013d 4209 vfr-noduration-interleave +a5d087611a9229ba91eb0964cf2f17d9 4209 vfr-noduration-interleave write_data len 1231, time nopts, type header atom ftyp write_data len 916, time 0, type sync atom moof write_data len 908, time 1000000, type sync atom moof write_data len 148, time nopts, type trailer atom - -781dbfd228f36903178e29faa727d78b 3203 delay-moov-elst-neg-cts +d81c3a0ce5940a2db74c99ad435e0560 3203 delay-moov-elst-neg-cts write_data len 36, time nopts, type header atom ftyp write_data len 1123, time nopts, type header atom - -write_data len 1188, time 0, type sync atom moof -write_data len 908, time 1033333, type sync atom moof +write_data len 900, time 0, type sync atom moof +write_data len 908, time 1000000, type sync atom moof write_data len 148, time nopts, type trailer atom - -7630fdf358e02c79e88f312f82a260b7 3403 empty-moov-neg-cts +3be575022e446855bca1e45b7942cc0c 3115 empty-moov-neg-cts diff -Nru ffmpeg-4.2.2/tests/ref/fate/mov-init-nonkeyframe ffmpeg-4.4/tests/ref/fate/mov-init-nonkeyframe --- ffmpeg-4.2.2/tests/ref/fate/mov-init-nonkeyframe 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mov-init-nonkeyframe 2021-04-08 21:28:40.000000000 +0000 @@ -1,120 +1,120 @@ -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=599|pos=48|flags=__ -packet|codec_type=video|stream_index=0|pts=2002|pts_time=0.066733|dts=1001|dts_time=0.033367|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2944|pos=1674|flags=__ -packet|codec_type=video|stream_index=0|pts=7007|pts_time=0.233567|dts=2002|dts_time=0.066733|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=21987|pos=5335|flags=__ -packet|codec_type=video|stream_index=0|pts=5005|pts_time=0.166833|dts=3003|dts_time=0.100100|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=4145|pos=28605|flags=__ -packet|codec_type=video|stream_index=0|pts=4004|pts_time=0.133467|dts=4004|dts_time=0.133467|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3093|pos=33425|flags=__ -packet|codec_type=video|stream_index=0|pts=6006|pts_time=0.200200|dts=5005|dts_time=0.166833|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=572|pos=37769|flags=__ -packet|codec_type=video|stream_index=0|pts=11011|pts_time=0.367033|dts=6006|dts_time=0.200200|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=21599|pos=38999|flags=__ -packet|codec_type=video|stream_index=0|pts=9009|pts_time=0.300300|dts=7007|dts_time=0.233567|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=6287|pos=61922|flags=__ -packet|codec_type=video|stream_index=0|pts=8008|pts_time=0.266933|dts=8008|dts_time=0.266933|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2720|pos=68909|flags=__ -packet|codec_type=video|stream_index=0|pts=10010|pts_time=0.333667|dts=9009|dts_time=0.300300|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2715|pos=72301|flags=__ -packet|codec_type=video|stream_index=0|pts=15015|pts_time=0.500500|dts=10010|dts_time=0.333667|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=20221|pos=76433|flags=__ -packet|codec_type=video|stream_index=0|pts=13013|pts_time=0.433767|dts=11011|dts_time=0.367033|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=9505|pos=97381|flags=__ -packet|codec_type=video|stream_index=0|pts=12012|pts_time=0.400400|dts=12012|dts_time=0.400400|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=522|pos=108391|flags=__ -packet|codec_type=video|stream_index=0|pts=14014|pts_time=0.467133|dts=13013|dts_time=0.433767|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2360|pos=109683|flags=__ -packet|codec_type=video|stream_index=0|pts=17017|pts_time=0.567233|dts=14014|dts_time=0.467133|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=22156|pos=113572|flags=__ -packet|codec_type=video|stream_index=0|pts=16016|pts_time=0.533867|dts=15015|dts_time=0.500500|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=1801|pos=136496|flags=__ -packet|codec_type=video|stream_index=0|pts=21021|pts_time=0.700700|dts=16016|dts_time=0.533867|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=20181|pos=139074|flags=__ -packet|codec_type=video|stream_index=0|pts=19019|pts_time=0.633967|dts=17017|dts_time=0.567233|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3608|pos=160959|flags=__ -packet|codec_type=video|stream_index=0|pts=18018|pts_time=0.600600|dts=18018|dts_time=0.600600|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=368|pos=165305|flags=__ -packet|codec_type=video|stream_index=0|pts=20020|pts_time=0.667333|dts=19019|dts_time=0.633967|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2989|pos=167054|flags=__ -packet|codec_type=video|stream_index=0|pts=25025|pts_time=0.834167|dts=20020|dts_time=0.667333|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=24475|pos=170801|flags=__ -packet|codec_type=video|stream_index=0|pts=23023|pts_time=0.767433|dts=21021|dts_time=0.700700|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=10682|pos=196732|flags=__ -packet|codec_type=video|stream_index=0|pts=22022|pts_time=0.734067|dts=22022|dts_time=0.734067|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3198|pos=208151|flags=__ -packet|codec_type=video|stream_index=0|pts=24024|pts_time=0.800800|dts=23023|dts_time=0.767433|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=479|pos=212958|flags=__ -packet|codec_type=video|stream_index=0|pts=29029|pts_time=0.967633|dts=24024|dts_time=0.800800|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=21240|pos=214384|flags=__ -packet|codec_type=video|stream_index=0|pts=27027|pts_time=0.900900|dts=25025|dts_time=0.834167|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=4409|pos=236946|flags=__ -packet|codec_type=video|stream_index=0|pts=26026|pts_time=0.867533|dts=26026|dts_time=0.867533|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3106|pos=242647|flags=__ -packet|codec_type=video|stream_index=0|pts=28028|pts_time=0.934267|dts=27027|dts_time=0.900900|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=453|pos=246428|flags=__ -packet|codec_type=video|stream_index=0|pts=33033|pts_time=1.101100|dts=28028|dts_time=0.934267|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=20668|pos=248308|flags=__ -packet|codec_type=video|stream_index=0|pts=31031|pts_time=1.034367|dts=29029|dts_time=0.967633|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=6668|pos=269708|flags=__ -packet|codec_type=video|stream_index=0|pts=30030|pts_time=1.001000|dts=30030|dts_time=1.001000|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3027|pos=277789|flags=__ -packet|codec_type=video|stream_index=0|pts=32032|pts_time=1.067733|dts=31031|dts_time=1.034367|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2884|pos=281613|flags=__ -packet|codec_type=video|stream_index=0|pts=37037|pts_time=1.234567|dts=32032|dts_time=1.067733|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=21313|pos=285261|flags=__ -packet|codec_type=video|stream_index=0|pts=35035|pts_time=1.167833|dts=33033|dts_time=1.101100|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=9890|pos=308303|flags=__ -packet|codec_type=video|stream_index=0|pts=34034|pts_time=1.134467|dts=34034|dts_time=1.134467|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=501|pos=318919|flags=__ -packet|codec_type=video|stream_index=0|pts=36036|pts_time=1.201200|dts=35035|dts_time=1.167833|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3123|pos=320824|flags=__ -packet|codec_type=video|stream_index=0|pts=39039|pts_time=1.301300|dts=36036|dts_time=1.201200|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=21768|pos=324664|flags=__ -packet|codec_type=video|stream_index=0|pts=38038|pts_time=1.267933|dts=37037|dts_time=1.234567|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2664|pos=347922|flags=__ -packet|codec_type=video|stream_index=0|pts=43043|pts_time=1.434767|dts=38038|dts_time=1.267933|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=19144|pos=351354|flags=__ -packet|codec_type=video|stream_index=0|pts=41041|pts_time=1.368033|dts=39039|dts_time=1.301300|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=4118|pos=371991|flags=__ -packet|codec_type=video|stream_index=0|pts=40040|pts_time=1.334667|dts=40040|dts_time=1.334667|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=423|pos=376899|flags=__ -packet|codec_type=video|stream_index=0|pts=42042|pts_time=1.401400|dts=41041|dts_time=1.368033|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2785|pos=378037|flags=__ -packet|codec_type=video|stream_index=0|pts=45045|pts_time=1.501500|dts=42042|dts_time=1.401400|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=24489|pos=382144|flags=__ -packet|codec_type=video|stream_index=0|pts=44044|pts_time=1.468133|dts=43043|dts_time=1.434767|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2984|pos=407344|flags=__ -packet|codec_type=video|stream_index=0|pts=49049|pts_time=1.634967|dts=44044|dts_time=1.468133|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=19174|pos=411791|flags=__ -packet|codec_type=video|stream_index=0|pts=47047|pts_time=1.568233|dts=45045|dts_time=1.501500|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=4905|pos=431740|flags=__ -packet|codec_type=video|stream_index=0|pts=46046|pts_time=1.534867|dts=46046|dts_time=1.534867|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=412|pos=438183|flags=__ -packet|codec_type=video|stream_index=0|pts=48048|pts_time=1.601600|dts=47047|dts_time=1.568233|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3215|pos=439373|flags=__ -packet|codec_type=video|stream_index=0|pts=51051|pts_time=1.701700|dts=48048|dts_time=1.601600|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=21572|pos=443371|flags=__ -packet|codec_type=video|stream_index=0|pts=50050|pts_time=1.668333|dts=49049|dts_time=1.634967|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2644|pos=466486|flags=__ -packet|codec_type=video|stream_index=0|pts=55055|pts_time=1.835167|dts=50050|dts_time=1.668333|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=19417|pos=470462|flags=__ -packet|codec_type=video|stream_index=0|pts=53053|pts_time=1.768433|dts=51051|dts_time=1.701700|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3685|pos=491335|flags=__ -packet|codec_type=video|stream_index=0|pts=52052|pts_time=1.735067|dts=52052|dts_time=1.735067|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=355|pos=495771|flags=__ -packet|codec_type=video|stream_index=0|pts=54054|pts_time=1.801800|dts=53053|dts_time=1.768433|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3021|pos=497714|flags=__ -packet|codec_type=video|stream_index=0|pts=59059|pts_time=1.968633|dts=54054|dts_time=1.801800|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=21464|pos=501431|flags=__ -packet|codec_type=video|stream_index=0|pts=57057|pts_time=1.901900|dts=55055|dts_time=1.835167|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=9340|pos=524392|flags=__ -packet|codec_type=video|stream_index=0|pts=56056|pts_time=1.868533|dts=56056|dts_time=1.868533|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=406|pos=534504|flags=__ -packet|codec_type=video|stream_index=0|pts=58058|pts_time=1.935267|dts=57057|dts_time=1.901900|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3277|pos=535694|flags=__ -packet|codec_type=video|stream_index=0|pts=63063|pts_time=2.102100|dts=58058|dts_time=1.935267|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=21388|pos=541090|flags=__ -packet|codec_type=video|stream_index=0|pts=61061|pts_time=2.035367|dts=59059|dts_time=1.968633|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=4466|pos=563132|flags=__ -packet|codec_type=video|stream_index=0|pts=60060|pts_time=2.002000|dts=60060|dts_time=2.002000|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3467|pos=569245|flags=__ -packet|codec_type=video|stream_index=0|pts=62062|pts_time=2.068733|dts=61061|dts_time=2.035367|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=499|pos=573478|flags=__ -packet|codec_type=video|stream_index=0|pts=67067|pts_time=2.235567|dts=62062|dts_time=2.068733|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=25972|pos=575469|flags=__ -packet|codec_type=video|stream_index=0|pts=65065|pts_time=2.168833|dts=63063|dts_time=2.102100|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=6643|pos=602163|flags=__ -packet|codec_type=video|stream_index=0|pts=64064|pts_time=2.135467|dts=64064|dts_time=2.135467|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3069|pos=609558|flags=__ -packet|codec_type=video|stream_index=0|pts=66066|pts_time=2.202200|dts=65065|dts_time=2.168833|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3049|pos=614133|flags=__ -packet|codec_type=video|stream_index=0|pts=68068|pts_time=2.268933|dts=66066|dts_time=2.202200|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=4559|pos=618551|flags=__ -packet|codec_type=video|stream_index=0|pts=72072|pts_time=2.402400|dts=67067|dts_time=2.235567|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=21251|pos=624621|flags=__ -packet|codec_type=video|stream_index=0|pts=70070|pts_time=2.335667|dts=68068|dts_time=2.268933|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=7108|pos=646657|flags=__ -packet|codec_type=video|stream_index=0|pts=69069|pts_time=2.302300|dts=69069|dts_time=2.302300|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3250|pos=655299|flags=__ -packet|codec_type=video|stream_index=0|pts=71071|pts_time=2.369033|dts=70070|dts_time=2.335667|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3365|pos=659310|flags=__ -packet|codec_type=video|stream_index=0|pts=73073|pts_time=2.435767|dts=71071|dts_time=2.369033|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=24803|pos=664201|flags=__ -packet|codec_type=video|stream_index=0|pts=77077|pts_time=2.569233|dts=72072|dts_time=2.402400|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=22185|pos=689763|flags=__ -packet|codec_type=video|stream_index=0|pts=75075|pts_time=2.502500|dts=73073|dts_time=2.435767|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=5088|pos=712679|flags=__ -packet|codec_type=video|stream_index=0|pts=74074|pts_time=2.469133|dts=74074|dts_time=2.469133|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=537|pos=719128|flags=__ -packet|codec_type=video|stream_index=0|pts=76076|pts_time=2.535867|dts=75075|dts_time=2.502500|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3765|pos=720413|flags=__ -packet|codec_type=video|stream_index=0|pts=81081|pts_time=2.702700|dts=76076|dts_time=2.535867|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=20654|pos=725583|flags=__ -packet|codec_type=video|stream_index=0|pts=79079|pts_time=2.635967|dts=77077|dts_time=2.569233|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=10202|pos=746999|flags=__ -packet|codec_type=video|stream_index=0|pts=78078|pts_time=2.602600|dts=78078|dts_time=2.602600|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3970|pos=758705|flags=__ -packet|codec_type=video|stream_index=0|pts=80080|pts_time=2.669333|dts=79079|dts_time=2.635967|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=421|pos=763442|flags=__ -packet|codec_type=video|stream_index=0|pts=84084|pts_time=2.802800|dts=80080|dts_time=2.669333|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=25685|pos=764653|flags=__ -packet|codec_type=video|stream_index=0|pts=82082|pts_time=2.736067|dts=81081|dts_time=2.702700|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=4077|pos=791911|flags=__ -packet|codec_type=video|stream_index=0|pts=83083|pts_time=2.769433|dts=82082|dts_time=2.736067|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3049|pos=796780|flags=__ -packet|codec_type=video|stream_index=0|pts=88088|pts_time=2.936267|dts=83083|dts_time=2.769433|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=8924|pos=801473|flags=__ -packet|codec_type=video|stream_index=0|pts=86086|pts_time=2.869533|dts=84084|dts_time=2.802800|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2512|pos=811078|flags=__ -packet|codec_type=video|stream_index=0|pts=85085|pts_time=2.836167|dts=85085|dts_time=2.836167|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=163|pos=815033|flags=__ -packet|codec_type=video|stream_index=0|pts=87087|pts_time=2.902900|dts=86086|dts_time=2.869533|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=1734|pos=815934|flags=__ -packet|codec_type=video|stream_index=0|pts=90090|pts_time=3.003000|dts=87087|dts_time=2.902900|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=11505|pos=819088|flags=__ -packet|codec_type=video|stream_index=0|pts=89089|pts_time=2.969633|dts=88088|dts_time=2.936267|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=1431|pos=831367|flags=__ -packet|codec_type=video|stream_index=0|pts=92092|pts_time=3.069733|dts=89089|dts_time=2.969633|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=5269|pos=833580|flags=__ -packet|codec_type=video|stream_index=0|pts=91091|pts_time=3.036367|dts=90090|dts_time=3.003000|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=199|pos=840352|flags=__ -packet|codec_type=video|stream_index=0|pts=93093|pts_time=3.103100|dts=91091|dts_time=3.036367|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=85650|pos=841722|flags=K_ -packet|codec_type=video|stream_index=0|pts=95095|pts_time=3.169833|dts=92092|dts_time=3.069733|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=13261|pos=928747|flags=__ -packet|codec_type=video|stream_index=0|pts=94094|pts_time=3.136467|dts=93093|dts_time=3.103100|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=1667|pos=942741|flags=__ -packet|codec_type=video|stream_index=0|pts=99099|pts_time=3.303300|dts=94094|dts_time=3.136467|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=20143|pos=945841|flags=__ -packet|codec_type=video|stream_index=0|pts=97097|pts_time=3.236567|dts=95095|dts_time=3.169833|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2484|pos=966681|flags=__ -packet|codec_type=video|stream_index=0|pts=96096|pts_time=3.203200|dts=96096|dts_time=3.203200|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=278|pos=969887|flags=__ -packet|codec_type=video|stream_index=0|pts=98098|pts_time=3.269933|dts=97097|dts_time=3.236567|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=1539|pos=971696|flags=__ -packet|codec_type=video|stream_index=0|pts=101101|pts_time=3.370033|dts=98098|dts_time=3.269933|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=20270|pos=974088|flags=__ -packet|codec_type=video|stream_index=0|pts=100100|pts_time=3.336667|dts=99099|dts_time=3.303300|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=1754|pos=995975|flags=__ -packet|codec_type=video|stream_index=0|pts=105105|pts_time=3.503500|dts=100100|dts_time=3.336667|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=19154|pos=998420|flags=__ -packet|codec_type=video|stream_index=0|pts=103103|pts_time=3.436767|dts=101101|dts_time=3.370033|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3359|pos=1019010|flags=__ -packet|codec_type=video|stream_index=0|pts=102102|pts_time=3.403400|dts=102102|dts_time=3.403400|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=287|pos=1023138|flags=__ -packet|codec_type=video|stream_index=0|pts=104104|pts_time=3.470133|dts=103103|dts_time=3.436767|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2111|pos=1024928|flags=__ -packet|codec_type=video|stream_index=0|pts=109109|pts_time=3.636967|dts=104104|dts_time=3.470133|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=17178|pos=1027833|flags=__ -packet|codec_type=video|stream_index=0|pts=107107|pts_time=3.570233|dts=105105|dts_time=3.503500|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=7205|pos=1045716|flags=__ -packet|codec_type=video|stream_index=0|pts=106106|pts_time=3.536867|dts=106106|dts_time=3.536867|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2209|pos=1054354|flags=__ -packet|codec_type=video|stream_index=0|pts=108108|pts_time=3.603600|dts=107107|dts_time=3.570233|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=359|pos=1057226|flags=__ -packet|codec_type=video|stream_index=0|pts=113113|pts_time=3.770433|dts=108108|dts_time=3.603600|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=18469|pos=1059024|flags=__ -packet|codec_type=video|stream_index=0|pts=111111|pts_time=3.703700|dts=109109|dts_time=3.636967|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=3314|pos=1078213|flags=__ -packet|codec_type=video|stream_index=0|pts=110110|pts_time=3.670333|dts=110110|dts_time=3.670333|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2556|pos=1083059|flags=__ -packet|codec_type=video|stream_index=0|pts=112112|pts_time=3.737067|dts=111111|dts_time=3.703700|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=437|pos=1086388|flags=__ -packet|codec_type=video|stream_index=0|pts=117117|pts_time=3.903900|dts=112112|dts_time=3.737067|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=19707|pos=1087610|flags=__ -packet|codec_type=video|stream_index=0|pts=115115|pts_time=3.837167|dts=113113|dts_time=3.770433|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=5917|pos=1108845|flags=__ -packet|codec_type=video|stream_index=0|pts=114114|pts_time=3.803800|dts=114114|dts_time=3.803800|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2613|pos=1115495|flags=__ -packet|codec_type=video|stream_index=0|pts=116116|pts_time=3.870533|dts=115115|dts_time=3.837167|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2672|pos=1119530|flags=__ -packet|codec_type=video|stream_index=0|pts=121121|pts_time=4.037367|dts=116116|dts_time=3.870533|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=19091|pos=1122970|flags=_D -packet|codec_type=video|stream_index=0|pts=119119|pts_time=3.970633|dts=117117|dts_time=3.903900|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=9244|pos=1143585|flags=__ -packet|codec_type=video|stream_index=0|pts=118118|pts_time=3.937267|dts=118118|dts_time=3.937267|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=284|pos=1153587|flags=__ -packet|codec_type=video|stream_index=0|pts=120120|pts_time=4.004000|dts=119119|dts_time=3.970633|duration=1001|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=2381|pos=1155393|flags=_D +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1001|duration_time=0.033367|size=599|pos=48|flags=__ +packet|codec_type=video|stream_index=0|pts=2002|pts_time=0.066733|dts=1001|dts_time=0.033367|duration=1001|duration_time=0.033367|size=2944|pos=1674|flags=__ +packet|codec_type=video|stream_index=0|pts=7007|pts_time=0.233567|dts=2002|dts_time=0.066733|duration=1001|duration_time=0.033367|size=21987|pos=5335|flags=__ +packet|codec_type=video|stream_index=0|pts=5005|pts_time=0.166833|dts=3003|dts_time=0.100100|duration=1001|duration_time=0.033367|size=4145|pos=28605|flags=__ +packet|codec_type=video|stream_index=0|pts=4004|pts_time=0.133467|dts=4004|dts_time=0.133467|duration=1001|duration_time=0.033367|size=3093|pos=33425|flags=__ +packet|codec_type=video|stream_index=0|pts=6006|pts_time=0.200200|dts=5005|dts_time=0.166833|duration=1001|duration_time=0.033367|size=572|pos=37769|flags=__ +packet|codec_type=video|stream_index=0|pts=11011|pts_time=0.367033|dts=6006|dts_time=0.200200|duration=1001|duration_time=0.033367|size=21599|pos=38999|flags=__ +packet|codec_type=video|stream_index=0|pts=9009|pts_time=0.300300|dts=7007|dts_time=0.233567|duration=1001|duration_time=0.033367|size=6287|pos=61922|flags=__ +packet|codec_type=video|stream_index=0|pts=8008|pts_time=0.266933|dts=8008|dts_time=0.266933|duration=1001|duration_time=0.033367|size=2720|pos=68909|flags=__ +packet|codec_type=video|stream_index=0|pts=10010|pts_time=0.333667|dts=9009|dts_time=0.300300|duration=1001|duration_time=0.033367|size=2715|pos=72301|flags=__ +packet|codec_type=video|stream_index=0|pts=15015|pts_time=0.500500|dts=10010|dts_time=0.333667|duration=1001|duration_time=0.033367|size=20221|pos=76433|flags=__ +packet|codec_type=video|stream_index=0|pts=13013|pts_time=0.433767|dts=11011|dts_time=0.367033|duration=1001|duration_time=0.033367|size=9505|pos=97381|flags=__ +packet|codec_type=video|stream_index=0|pts=12012|pts_time=0.400400|dts=12012|dts_time=0.400400|duration=1001|duration_time=0.033367|size=522|pos=108391|flags=__ +packet|codec_type=video|stream_index=0|pts=14014|pts_time=0.467133|dts=13013|dts_time=0.433767|duration=1001|duration_time=0.033367|size=2360|pos=109683|flags=__ +packet|codec_type=video|stream_index=0|pts=17017|pts_time=0.567233|dts=14014|dts_time=0.467133|duration=1001|duration_time=0.033367|size=22156|pos=113572|flags=__ +packet|codec_type=video|stream_index=0|pts=16016|pts_time=0.533867|dts=15015|dts_time=0.500500|duration=1001|duration_time=0.033367|size=1801|pos=136496|flags=__ +packet|codec_type=video|stream_index=0|pts=21021|pts_time=0.700700|dts=16016|dts_time=0.533867|duration=1001|duration_time=0.033367|size=20181|pos=139074|flags=__ +packet|codec_type=video|stream_index=0|pts=19019|pts_time=0.633967|dts=17017|dts_time=0.567233|duration=1001|duration_time=0.033367|size=3608|pos=160959|flags=__ +packet|codec_type=video|stream_index=0|pts=18018|pts_time=0.600600|dts=18018|dts_time=0.600600|duration=1001|duration_time=0.033367|size=368|pos=165305|flags=__ +packet|codec_type=video|stream_index=0|pts=20020|pts_time=0.667333|dts=19019|dts_time=0.633967|duration=1001|duration_time=0.033367|size=2989|pos=167054|flags=__ +packet|codec_type=video|stream_index=0|pts=25025|pts_time=0.834167|dts=20020|dts_time=0.667333|duration=1001|duration_time=0.033367|size=24475|pos=170801|flags=__ +packet|codec_type=video|stream_index=0|pts=23023|pts_time=0.767433|dts=21021|dts_time=0.700700|duration=1001|duration_time=0.033367|size=10682|pos=196732|flags=__ +packet|codec_type=video|stream_index=0|pts=22022|pts_time=0.734067|dts=22022|dts_time=0.734067|duration=1001|duration_time=0.033367|size=3198|pos=208151|flags=__ +packet|codec_type=video|stream_index=0|pts=24024|pts_time=0.800800|dts=23023|dts_time=0.767433|duration=1001|duration_time=0.033367|size=479|pos=212958|flags=__ +packet|codec_type=video|stream_index=0|pts=29029|pts_time=0.967633|dts=24024|dts_time=0.800800|duration=1001|duration_time=0.033367|size=21240|pos=214384|flags=__ +packet|codec_type=video|stream_index=0|pts=27027|pts_time=0.900900|dts=25025|dts_time=0.834167|duration=1001|duration_time=0.033367|size=4409|pos=236946|flags=__ +packet|codec_type=video|stream_index=0|pts=26026|pts_time=0.867533|dts=26026|dts_time=0.867533|duration=1001|duration_time=0.033367|size=3106|pos=242647|flags=__ +packet|codec_type=video|stream_index=0|pts=28028|pts_time=0.934267|dts=27027|dts_time=0.900900|duration=1001|duration_time=0.033367|size=453|pos=246428|flags=__ +packet|codec_type=video|stream_index=0|pts=33033|pts_time=1.101100|dts=28028|dts_time=0.934267|duration=1001|duration_time=0.033367|size=20668|pos=248308|flags=__ +packet|codec_type=video|stream_index=0|pts=31031|pts_time=1.034367|dts=29029|dts_time=0.967633|duration=1001|duration_time=0.033367|size=6668|pos=269708|flags=__ +packet|codec_type=video|stream_index=0|pts=30030|pts_time=1.001000|dts=30030|dts_time=1.001000|duration=1001|duration_time=0.033367|size=3027|pos=277789|flags=__ +packet|codec_type=video|stream_index=0|pts=32032|pts_time=1.067733|dts=31031|dts_time=1.034367|duration=1001|duration_time=0.033367|size=2884|pos=281613|flags=__ +packet|codec_type=video|stream_index=0|pts=37037|pts_time=1.234567|dts=32032|dts_time=1.067733|duration=1001|duration_time=0.033367|size=21313|pos=285261|flags=__ +packet|codec_type=video|stream_index=0|pts=35035|pts_time=1.167833|dts=33033|dts_time=1.101100|duration=1001|duration_time=0.033367|size=9890|pos=308303|flags=__ +packet|codec_type=video|stream_index=0|pts=34034|pts_time=1.134467|dts=34034|dts_time=1.134467|duration=1001|duration_time=0.033367|size=501|pos=318919|flags=__ +packet|codec_type=video|stream_index=0|pts=36036|pts_time=1.201200|dts=35035|dts_time=1.167833|duration=1001|duration_time=0.033367|size=3123|pos=320824|flags=__ +packet|codec_type=video|stream_index=0|pts=39039|pts_time=1.301300|dts=36036|dts_time=1.201200|duration=1001|duration_time=0.033367|size=21768|pos=324664|flags=__ +packet|codec_type=video|stream_index=0|pts=38038|pts_time=1.267933|dts=37037|dts_time=1.234567|duration=1001|duration_time=0.033367|size=2664|pos=347922|flags=__ +packet|codec_type=video|stream_index=0|pts=43043|pts_time=1.434767|dts=38038|dts_time=1.267933|duration=1001|duration_time=0.033367|size=19144|pos=351354|flags=__ +packet|codec_type=video|stream_index=0|pts=41041|pts_time=1.368033|dts=39039|dts_time=1.301300|duration=1001|duration_time=0.033367|size=4118|pos=371991|flags=__ +packet|codec_type=video|stream_index=0|pts=40040|pts_time=1.334667|dts=40040|dts_time=1.334667|duration=1001|duration_time=0.033367|size=423|pos=376899|flags=__ +packet|codec_type=video|stream_index=0|pts=42042|pts_time=1.401400|dts=41041|dts_time=1.368033|duration=1001|duration_time=0.033367|size=2785|pos=378037|flags=__ +packet|codec_type=video|stream_index=0|pts=45045|pts_time=1.501500|dts=42042|dts_time=1.401400|duration=1001|duration_time=0.033367|size=24489|pos=382144|flags=__ +packet|codec_type=video|stream_index=0|pts=44044|pts_time=1.468133|dts=43043|dts_time=1.434767|duration=1001|duration_time=0.033367|size=2984|pos=407344|flags=__ +packet|codec_type=video|stream_index=0|pts=49049|pts_time=1.634967|dts=44044|dts_time=1.468133|duration=1001|duration_time=0.033367|size=19174|pos=411791|flags=__ +packet|codec_type=video|stream_index=0|pts=47047|pts_time=1.568233|dts=45045|dts_time=1.501500|duration=1001|duration_time=0.033367|size=4905|pos=431740|flags=__ +packet|codec_type=video|stream_index=0|pts=46046|pts_time=1.534867|dts=46046|dts_time=1.534867|duration=1001|duration_time=0.033367|size=412|pos=438183|flags=__ +packet|codec_type=video|stream_index=0|pts=48048|pts_time=1.601600|dts=47047|dts_time=1.568233|duration=1001|duration_time=0.033367|size=3215|pos=439373|flags=__ +packet|codec_type=video|stream_index=0|pts=51051|pts_time=1.701700|dts=48048|dts_time=1.601600|duration=1001|duration_time=0.033367|size=21572|pos=443371|flags=__ +packet|codec_type=video|stream_index=0|pts=50050|pts_time=1.668333|dts=49049|dts_time=1.634967|duration=1001|duration_time=0.033367|size=2644|pos=466486|flags=__ +packet|codec_type=video|stream_index=0|pts=55055|pts_time=1.835167|dts=50050|dts_time=1.668333|duration=1001|duration_time=0.033367|size=19417|pos=470462|flags=__ +packet|codec_type=video|stream_index=0|pts=53053|pts_time=1.768433|dts=51051|dts_time=1.701700|duration=1001|duration_time=0.033367|size=3685|pos=491335|flags=__ +packet|codec_type=video|stream_index=0|pts=52052|pts_time=1.735067|dts=52052|dts_time=1.735067|duration=1001|duration_time=0.033367|size=355|pos=495771|flags=__ +packet|codec_type=video|stream_index=0|pts=54054|pts_time=1.801800|dts=53053|dts_time=1.768433|duration=1001|duration_time=0.033367|size=3021|pos=497714|flags=__ +packet|codec_type=video|stream_index=0|pts=59059|pts_time=1.968633|dts=54054|dts_time=1.801800|duration=1001|duration_time=0.033367|size=21464|pos=501431|flags=__ +packet|codec_type=video|stream_index=0|pts=57057|pts_time=1.901900|dts=55055|dts_time=1.835167|duration=1001|duration_time=0.033367|size=9340|pos=524392|flags=__ +packet|codec_type=video|stream_index=0|pts=56056|pts_time=1.868533|dts=56056|dts_time=1.868533|duration=1001|duration_time=0.033367|size=406|pos=534504|flags=__ +packet|codec_type=video|stream_index=0|pts=58058|pts_time=1.935267|dts=57057|dts_time=1.901900|duration=1001|duration_time=0.033367|size=3277|pos=535694|flags=__ +packet|codec_type=video|stream_index=0|pts=63063|pts_time=2.102100|dts=58058|dts_time=1.935267|duration=1001|duration_time=0.033367|size=21388|pos=541090|flags=__ +packet|codec_type=video|stream_index=0|pts=61061|pts_time=2.035367|dts=59059|dts_time=1.968633|duration=1001|duration_time=0.033367|size=4466|pos=563132|flags=__ +packet|codec_type=video|stream_index=0|pts=60060|pts_time=2.002000|dts=60060|dts_time=2.002000|duration=1001|duration_time=0.033367|size=3467|pos=569245|flags=__ +packet|codec_type=video|stream_index=0|pts=62062|pts_time=2.068733|dts=61061|dts_time=2.035367|duration=1001|duration_time=0.033367|size=499|pos=573478|flags=__ +packet|codec_type=video|stream_index=0|pts=67067|pts_time=2.235567|dts=62062|dts_time=2.068733|duration=1001|duration_time=0.033367|size=25972|pos=575469|flags=__ +packet|codec_type=video|stream_index=0|pts=65065|pts_time=2.168833|dts=63063|dts_time=2.102100|duration=1001|duration_time=0.033367|size=6643|pos=602163|flags=__ +packet|codec_type=video|stream_index=0|pts=64064|pts_time=2.135467|dts=64064|dts_time=2.135467|duration=1001|duration_time=0.033367|size=3069|pos=609558|flags=__ +packet|codec_type=video|stream_index=0|pts=66066|pts_time=2.202200|dts=65065|dts_time=2.168833|duration=1001|duration_time=0.033367|size=3049|pos=614133|flags=__ +packet|codec_type=video|stream_index=0|pts=68068|pts_time=2.268933|dts=66066|dts_time=2.202200|duration=1001|duration_time=0.033367|size=4559|pos=618551|flags=__ +packet|codec_type=video|stream_index=0|pts=72072|pts_time=2.402400|dts=67067|dts_time=2.235567|duration=1001|duration_time=0.033367|size=21251|pos=624621|flags=__ +packet|codec_type=video|stream_index=0|pts=70070|pts_time=2.335667|dts=68068|dts_time=2.268933|duration=1001|duration_time=0.033367|size=7108|pos=646657|flags=__ +packet|codec_type=video|stream_index=0|pts=69069|pts_time=2.302300|dts=69069|dts_time=2.302300|duration=1001|duration_time=0.033367|size=3250|pos=655299|flags=__ +packet|codec_type=video|stream_index=0|pts=71071|pts_time=2.369033|dts=70070|dts_time=2.335667|duration=1001|duration_time=0.033367|size=3365|pos=659310|flags=__ +packet|codec_type=video|stream_index=0|pts=73073|pts_time=2.435767|dts=71071|dts_time=2.369033|duration=1001|duration_time=0.033367|size=24803|pos=664201|flags=__ +packet|codec_type=video|stream_index=0|pts=77077|pts_time=2.569233|dts=72072|dts_time=2.402400|duration=1001|duration_time=0.033367|size=22185|pos=689763|flags=__ +packet|codec_type=video|stream_index=0|pts=75075|pts_time=2.502500|dts=73073|dts_time=2.435767|duration=1001|duration_time=0.033367|size=5088|pos=712679|flags=__ +packet|codec_type=video|stream_index=0|pts=74074|pts_time=2.469133|dts=74074|dts_time=2.469133|duration=1001|duration_time=0.033367|size=537|pos=719128|flags=__ +packet|codec_type=video|stream_index=0|pts=76076|pts_time=2.535867|dts=75075|dts_time=2.502500|duration=1001|duration_time=0.033367|size=3765|pos=720413|flags=__ +packet|codec_type=video|stream_index=0|pts=81081|pts_time=2.702700|dts=76076|dts_time=2.535867|duration=1001|duration_time=0.033367|size=20654|pos=725583|flags=__ +packet|codec_type=video|stream_index=0|pts=79079|pts_time=2.635967|dts=77077|dts_time=2.569233|duration=1001|duration_time=0.033367|size=10202|pos=746999|flags=__ +packet|codec_type=video|stream_index=0|pts=78078|pts_time=2.602600|dts=78078|dts_time=2.602600|duration=1001|duration_time=0.033367|size=3970|pos=758705|flags=__ +packet|codec_type=video|stream_index=0|pts=80080|pts_time=2.669333|dts=79079|dts_time=2.635967|duration=1001|duration_time=0.033367|size=421|pos=763442|flags=__ +packet|codec_type=video|stream_index=0|pts=84084|pts_time=2.802800|dts=80080|dts_time=2.669333|duration=1001|duration_time=0.033367|size=25685|pos=764653|flags=__ +packet|codec_type=video|stream_index=0|pts=82082|pts_time=2.736067|dts=81081|dts_time=2.702700|duration=1001|duration_time=0.033367|size=4077|pos=791911|flags=__ +packet|codec_type=video|stream_index=0|pts=83083|pts_time=2.769433|dts=82082|dts_time=2.736067|duration=1001|duration_time=0.033367|size=3049|pos=796780|flags=__ +packet|codec_type=video|stream_index=0|pts=88088|pts_time=2.936267|dts=83083|dts_time=2.769433|duration=1001|duration_time=0.033367|size=8924|pos=801473|flags=__ +packet|codec_type=video|stream_index=0|pts=86086|pts_time=2.869533|dts=84084|dts_time=2.802800|duration=1001|duration_time=0.033367|size=2512|pos=811078|flags=__ +packet|codec_type=video|stream_index=0|pts=85085|pts_time=2.836167|dts=85085|dts_time=2.836167|duration=1001|duration_time=0.033367|size=163|pos=815033|flags=__ +packet|codec_type=video|stream_index=0|pts=87087|pts_time=2.902900|dts=86086|dts_time=2.869533|duration=1001|duration_time=0.033367|size=1734|pos=815934|flags=__ +packet|codec_type=video|stream_index=0|pts=90090|pts_time=3.003000|dts=87087|dts_time=2.902900|duration=1001|duration_time=0.033367|size=11505|pos=819088|flags=__ +packet|codec_type=video|stream_index=0|pts=89089|pts_time=2.969633|dts=88088|dts_time=2.936267|duration=1001|duration_time=0.033367|size=1431|pos=831367|flags=__ +packet|codec_type=video|stream_index=0|pts=92092|pts_time=3.069733|dts=89089|dts_time=2.969633|duration=1001|duration_time=0.033367|size=5269|pos=833580|flags=__ +packet|codec_type=video|stream_index=0|pts=91091|pts_time=3.036367|dts=90090|dts_time=3.003000|duration=1001|duration_time=0.033367|size=199|pos=840352|flags=__ +packet|codec_type=video|stream_index=0|pts=93093|pts_time=3.103100|dts=91091|dts_time=3.036367|duration=1001|duration_time=0.033367|size=85650|pos=841722|flags=K_ +packet|codec_type=video|stream_index=0|pts=95095|pts_time=3.169833|dts=92092|dts_time=3.069733|duration=1001|duration_time=0.033367|size=13261|pos=928747|flags=__ +packet|codec_type=video|stream_index=0|pts=94094|pts_time=3.136467|dts=93093|dts_time=3.103100|duration=1001|duration_time=0.033367|size=1667|pos=942741|flags=__ +packet|codec_type=video|stream_index=0|pts=99099|pts_time=3.303300|dts=94094|dts_time=3.136467|duration=1001|duration_time=0.033367|size=20143|pos=945841|flags=__ +packet|codec_type=video|stream_index=0|pts=97097|pts_time=3.236567|dts=95095|dts_time=3.169833|duration=1001|duration_time=0.033367|size=2484|pos=966681|flags=__ +packet|codec_type=video|stream_index=0|pts=96096|pts_time=3.203200|dts=96096|dts_time=3.203200|duration=1001|duration_time=0.033367|size=278|pos=969887|flags=__ +packet|codec_type=video|stream_index=0|pts=98098|pts_time=3.269933|dts=97097|dts_time=3.236567|duration=1001|duration_time=0.033367|size=1539|pos=971696|flags=__ +packet|codec_type=video|stream_index=0|pts=101101|pts_time=3.370033|dts=98098|dts_time=3.269933|duration=1001|duration_time=0.033367|size=20270|pos=974088|flags=__ +packet|codec_type=video|stream_index=0|pts=100100|pts_time=3.336667|dts=99099|dts_time=3.303300|duration=1001|duration_time=0.033367|size=1754|pos=995975|flags=__ +packet|codec_type=video|stream_index=0|pts=105105|pts_time=3.503500|dts=100100|dts_time=3.336667|duration=1001|duration_time=0.033367|size=19154|pos=998420|flags=__ +packet|codec_type=video|stream_index=0|pts=103103|pts_time=3.436767|dts=101101|dts_time=3.370033|duration=1001|duration_time=0.033367|size=3359|pos=1019010|flags=__ +packet|codec_type=video|stream_index=0|pts=102102|pts_time=3.403400|dts=102102|dts_time=3.403400|duration=1001|duration_time=0.033367|size=287|pos=1023138|flags=__ +packet|codec_type=video|stream_index=0|pts=104104|pts_time=3.470133|dts=103103|dts_time=3.436767|duration=1001|duration_time=0.033367|size=2111|pos=1024928|flags=__ +packet|codec_type=video|stream_index=0|pts=109109|pts_time=3.636967|dts=104104|dts_time=3.470133|duration=1001|duration_time=0.033367|size=17178|pos=1027833|flags=__ +packet|codec_type=video|stream_index=0|pts=107107|pts_time=3.570233|dts=105105|dts_time=3.503500|duration=1001|duration_time=0.033367|size=7205|pos=1045716|flags=__ +packet|codec_type=video|stream_index=0|pts=106106|pts_time=3.536867|dts=106106|dts_time=3.536867|duration=1001|duration_time=0.033367|size=2209|pos=1054354|flags=__ +packet|codec_type=video|stream_index=0|pts=108108|pts_time=3.603600|dts=107107|dts_time=3.570233|duration=1001|duration_time=0.033367|size=359|pos=1057226|flags=__ +packet|codec_type=video|stream_index=0|pts=113113|pts_time=3.770433|dts=108108|dts_time=3.603600|duration=1001|duration_time=0.033367|size=18469|pos=1059024|flags=__ +packet|codec_type=video|stream_index=0|pts=111111|pts_time=3.703700|dts=109109|dts_time=3.636967|duration=1001|duration_time=0.033367|size=3314|pos=1078213|flags=__ +packet|codec_type=video|stream_index=0|pts=110110|pts_time=3.670333|dts=110110|dts_time=3.670333|duration=1001|duration_time=0.033367|size=2556|pos=1083059|flags=__ +packet|codec_type=video|stream_index=0|pts=112112|pts_time=3.737067|dts=111111|dts_time=3.703700|duration=1001|duration_time=0.033367|size=437|pos=1086388|flags=__ +packet|codec_type=video|stream_index=0|pts=117117|pts_time=3.903900|dts=112112|dts_time=3.737067|duration=1001|duration_time=0.033367|size=19707|pos=1087610|flags=__ +packet|codec_type=video|stream_index=0|pts=115115|pts_time=3.837167|dts=113113|dts_time=3.770433|duration=1001|duration_time=0.033367|size=5917|pos=1108845|flags=__ +packet|codec_type=video|stream_index=0|pts=114114|pts_time=3.803800|dts=114114|dts_time=3.803800|duration=1001|duration_time=0.033367|size=2613|pos=1115495|flags=__ +packet|codec_type=video|stream_index=0|pts=116116|pts_time=3.870533|dts=115115|dts_time=3.837167|duration=1001|duration_time=0.033367|size=2672|pos=1119530|flags=__ +packet|codec_type=video|stream_index=0|pts=121121|pts_time=4.037367|dts=116116|dts_time=3.870533|duration=1001|duration_time=0.033367|size=19091|pos=1122970|flags=_D +packet|codec_type=video|stream_index=0|pts=119119|pts_time=3.970633|dts=117117|dts_time=3.903900|duration=1001|duration_time=0.033367|size=9244|pos=1143585|flags=__ +packet|codec_type=video|stream_index=0|pts=118118|pts_time=3.937267|dts=118118|dts_time=3.937267|duration=1001|duration_time=0.033367|size=284|pos=1153587|flags=__ +packet|codec_type=video|stream_index=0|pts=120120|pts_time=4.004000|dts=119119|dts_time=3.970633|duration=1001|duration_time=0.033367|size=2381|pos=1155393|flags=_D diff -Nru ffmpeg-4.2.2/tests/ref/fate/mov-mp4-extended-atom ffmpeg-4.4/tests/ref/fate/mov-mp4-extended-atom --- ffmpeg-4.2.2/tests/ref/fate/mov-mp4-extended-atom 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mov-mp4-extended-atom 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1 @@ +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1001|duration_time=0.033367|size=14798|pos=16|flags=K_ diff -Nru ffmpeg-4.2.2/tests/ref/fate/mov-zombie ffmpeg-4.4/tests/ref/fate/mov-zombie --- ffmpeg-4.2.2/tests/ref/fate/mov-zombie 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mov-zombie 2021-04-08 21:28:40.000000000 +0000 @@ -1,133 +1,198 @@ -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-3004|dts_time=-0.033378|duration=3003|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=4133|pos=11309|flags=K_ -packet|codec_type=video|stream_index=0|pts=5440|pts_time=0.060444|dts=-567|dts_time=-0.006300|duration=3003|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=1077|pos=15442|flags=__ -frame|media_type=video|stream_index=0|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=-567|pkt_dts_time=-0.006300|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=11309|pkt_size=4133|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft -packet|codec_type=video|stream_index=0|pts=2437|pts_time=0.027078|dts=2436|dts_time=0.027067|duration=3003|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=355|pos=16519|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=2437|pkt_pts_time=0.027078|pkt_dts=2436|pkt_dts_time=0.027067|best_effort_timestamp=2437|best_effort_timestamp_time=0.027078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=16519|pkt_size=355|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=2|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft -packet|codec_type=video|stream_index=0|pts=11446|pts_time=0.127178|dts=5439|dts_time=0.060433|duration=3003|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=1110|pos=16874|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=5440|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=430|pos=17984|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=8443|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1485|pos=18414|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=11446|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1005|pos=19899|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=14449|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1976|pos=20904|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=17452|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=904|pos=22880|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=20455|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1254|pos=23784|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=23458|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=700|pos=25038|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=26461|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1311|pos=25738|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=29464|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=631|pos=27049|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=32467|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1296|pos=27680|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=35470|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=466|pos=28976|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=38473|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1638|pos=29442|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=41476|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=907|pos=31080|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=44479|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1362|pos=31987|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=47482|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=682|pos=33349|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=50485|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=2917|pos=34031|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=53488|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1174|pos=36948|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=56491|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1748|pos=38122|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=59494|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=926|pos=39870|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=62497|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=918|pos=40796|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=65500|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=3846|pos=41714|flags=K_ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=68503|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1932|pos=45560|flags=__ -frame|media_type=video|stream_index=0|key_frame=1|pkt_pts=71506|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1159|pos=47492|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=74509|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1522|pos=48651|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=77512|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=719|pos=50173|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=80515|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1700|pos=50892|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=83518|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1099|pos=52592|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=86521|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=2558|pos=53691|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=89524|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1008|pos=56249|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=92527|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1236|pos=57257|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=95530|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=607|pos=58493|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=98533|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1883|pos=59100|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=101536|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=893|pos=60983|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=104539|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1305|pos=61876|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=107542|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=472|pos=63181|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=110545|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1411|pos=63653|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=113548|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=616|pos=65064|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=116551|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1291|pos=65680|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=119554|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=470|pos=66971|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=122557|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1977|pos=67441|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=125560|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=436|pos=69418|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=128563|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=2566|pos=69854|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=131566|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=886|pos=72420|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=134569|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1330|pos=73306|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=137572|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=2227|pos=74636|flags=K_ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=140575|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=2210|pos=76863|flags=__ -frame|media_type=video|stream_index=0|key_frame=1|pkt_pts=143578|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1498|pos=79073|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=146581|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1721|pos=80571|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=149584|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1238|pos=82292|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=152587|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1753|pos=83530|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=155590|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1014|pos=85283|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=158593|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=2408|pos=86297|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=161596|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1727|pos=88705|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=164599|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1504|pos=90432|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=167602|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=957|pos=91936|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=170605|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1890|pos=92893|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=173608|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1239|pos=94783|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=176611|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1856|pos=96022|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=179614|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1302|pos=97878|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=182617|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=1666|pos=99180|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=185620|pkt_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 -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|convergence_duration=N/A|convergence_duration_time=N/A|size=974|pos=100846|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=188623|pkt_pts_time=2.095811|pkt_dts=188622|pkt_dts_time=2.095800|best_effort_timestamp=188623|best_effort_timestamp_time=2.095811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=100846|pkt_size=974|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=64|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft -packet|codec_type=video|stream_index=0|pts=197632|pts_time=2.195911|dts=191625|dts_time=2.129167|duration=3003|duration_time=0.033367|convergence_duration=N/A|convergence_duration_time=N/A|size=580|pos=101820|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pkt_pts=191626|pkt_pts_time=2.129178|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=191626|best_effort_timestamp_time=2.129178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=99180|pkt_size=1666|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=63|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft -stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_time_base=212521/12744000|codec_tag_string=avc1|codec_tag=0x31637661|width=160|height=240|coded_width=160|coded_height=240|has_b_frames=1|sample_aspect_ratio=2:1|display_aspect_ratio=4:3|pix_fmt=yuv420p|level=12|color_range=tv|color_space=smpte170m|color_transfer=bt709|color_primaries=smpte170m|chroma_location=topleft|field_order=unknown|timecode=N/A|refs=2|is_avc=true|nal_length_size=4|id=N/A|r_frame_rate=30000/1001|avg_frame_rate=6372000/212521|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=2125200|duration=23.613333|bit_rate=333874|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=708|nb_read_frames=65|nb_read_packets=66|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|tag:rotate=0|tag:creation_time=2008-05-12T20:59:27.000000Z|tag:language=eng|tag:handler_name=Apple Video Media Handler|tag:encoder=H.264 +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|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=-567|pkt_dts_time=-0.006300|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=11309|pkt_size=4133|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_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|pkt_pts=2437|pkt_pts_time=0.027078|pkt_dts=2436|pkt_dts_time=0.027067|best_effort_timestamp=2437|best_effort_timestamp_time=0.027078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=16519|pkt_size=355|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=2|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_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|pkt_pts=5440|pkt_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 + +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|pkt_pts=8443|pkt_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 + +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|pkt_pts=11446|pkt_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 + +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|pkt_pts=14449|pkt_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 + +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|pkt_pts=17452|pkt_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 + +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|pkt_pts=20455|pkt_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 + +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|pkt_pts=23458|pkt_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 + +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|pkt_pts=26461|pkt_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 + +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|pkt_pts=29464|pkt_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 + +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|pkt_pts=32467|pkt_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 + +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|pkt_pts=35470|pkt_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 + +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|pkt_pts=38473|pkt_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 + +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|pkt_pts=41476|pkt_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 + +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|pkt_pts=44479|pkt_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 + +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|pkt_pts=47482|pkt_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 + +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|pkt_pts=50485|pkt_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 + +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|pkt_pts=53488|pkt_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 + +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|pkt_pts=56491|pkt_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 + +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|pkt_pts=59494|pkt_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 + +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|pkt_pts=62497|pkt_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 + +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|pkt_pts=65500|pkt_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 + +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|pkt_pts=68503|pkt_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 + +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|pkt_pts=71506|pkt_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 + +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|pkt_pts=74509|pkt_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 + +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|pkt_pts=77512|pkt_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 + +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|pkt_pts=80515|pkt_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 + +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|pkt_pts=83518|pkt_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 + +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|pkt_pts=86521|pkt_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 + +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|pkt_pts=89524|pkt_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 + +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|pkt_pts=92527|pkt_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 + +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|pkt_pts=95530|pkt_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 + +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|pkt_pts=98533|pkt_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 + +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|pkt_pts=101536|pkt_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 + +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|pkt_pts=104539|pkt_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 + +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|pkt_pts=107542|pkt_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 + +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|pkt_pts=110545|pkt_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 + +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|pkt_pts=113548|pkt_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 + +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|pkt_pts=116551|pkt_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 + +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|pkt_pts=119554|pkt_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 + +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|pkt_pts=122557|pkt_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 + +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|pkt_pts=125560|pkt_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 + +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|pkt_pts=128563|pkt_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 + +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|pkt_pts=131566|pkt_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 + +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|pkt_pts=134569|pkt_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 + +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|pkt_pts=137572|pkt_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 + +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|pkt_pts=140575|pkt_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 + +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|pkt_pts=143578|pkt_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 + +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|pkt_pts=146581|pkt_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 + +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|pkt_pts=149584|pkt_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 + +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|pkt_pts=152587|pkt_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 + +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|pkt_pts=155590|pkt_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 + +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|pkt_pts=158593|pkt_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 + +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|pkt_pts=161596|pkt_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 + +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|pkt_pts=164599|pkt_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 + +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|pkt_pts=167602|pkt_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 + +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|pkt_pts=170605|pkt_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 + +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|pkt_pts=173608|pkt_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 + +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|pkt_pts=176611|pkt_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 + +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|pkt_pts=179614|pkt_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 + +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|pkt_pts=182617|pkt_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 + +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|pkt_pts=185620|pkt_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 + +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|pkt_pts=188623|pkt_pts_time=2.095811|pkt_dts=188622|pkt_dts_time=2.095800|best_effort_timestamp=188623|best_effort_timestamp_time=2.095811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=100846|pkt_size=974|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=64|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_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|pkt_pts=191626|pkt_pts_time=2.129178|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=191626|best_effort_timestamp_time=2.129178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=99180|pkt_size=1666|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=63|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_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|has_b_frames=1|sample_aspect_ratio=2:1|display_aspect_ratio=4:3|pix_fmt=yuv420p|level=12|color_range=tv|color_space=smpte170m|color_transfer=bt709|color_primaries=smpte170m|chroma_location=topleft|field_order=unknown|refs=2|is_avc=true|nal_length_size=4|id=N/A|r_frame_rate=30000/1001|avg_frame_rate=6372000/212521|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=2125200|duration=23.613333|bit_rate=333874|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=708|nb_read_frames=65|nb_read_packets=66|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|tag:rotate=0|tag:creation_time=2008-05-12T20:59:27.000000Z|tag:language=eng|tag:handler_name=Apple 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 -Nru ffmpeg-4.2.2/tests/ref/fate/mpeg2-ticket6677 ffmpeg-4.4/tests/ref/fate/mpeg2-ticket6677 --- ffmpeg-4.2.2/tests/ref/fate/mpeg2-ticket6677 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mpeg2-ticket6677 2021-04-08 21:28:40.000000000 +0000 @@ -3,10 +3,10 @@ #codec_id 0: rawvideo #dimensions 0: 720x480 #sar 0: 8/9 -0, 0, 0, 1, 518400, 0xc1866f5f -0, 1, 1, 1, 518400, 0x9ba32764 -0, 2, 2, 1, 518400, 0xa9031bb8 -0, 3, 3, 1, 518400, 0x5e2c3502 -0, 4, 4, 1, 518400, 0xe860027a -0, 5, 5, 1, 518400, 0xa9152430 -0, 6, 6, 1, 518400, 0xb98dd9f7 +0, 1, 1, 1, 518400, 0xc1866f5f +0, 2, 2, 1, 518400, 0x9ba32764 +0, 4, 4, 1, 518400, 0xa9031bb8 +0, 5, 5, 1, 518400, 0x5e2c3502 +0, 6, 6, 1, 518400, 0xe860027a +0, 7, 7, 1, 518400, 0xa9152430 +0, 9, 9, 1, 518400, 0xb98dd9f7 diff -Nru ffmpeg-4.2.2/tests/ref/fate/mpeg4-als-conformance-09 ffmpeg-4.4/tests/ref/fate/mpeg4-als-conformance-09 --- ffmpeg-4.2.2/tests/ref/fate/mpeg4-als-conformance-09 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mpeg4-als-conformance-09 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1 @@ +CRC=0xbf3e7189 diff -Nru ffmpeg-4.2.2/tests/ref/fate/mpegts-probe-latm ffmpeg-4.4/tests/ref/fate/mpegts-probe-latm --- ffmpeg-4.2.2/tests/ref/fate/mpegts-probe-latm 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mpegts-probe-latm 2020-07-11 10:39:30.000000000 +0000 @@ -12,3 +12,6 @@ [STREAM] codec_name=aac_latm [/STREAM] +[STREAM] +codec_name=epg +[/STREAM] diff -Nru ffmpeg-4.2.2/tests/ref/fate/mss2-pal ffmpeg-4.4/tests/ref/fate/mss2-pal --- ffmpeg-4.2.2/tests/ref/fate/mss2-pal 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mss2-pal 2021-04-08 21:28:40.000000000 +0000 @@ -3,5 +3,5 @@ #codec_id 0: rawvideo #dimensions 0: 64x48 #sar 0: 0/1 -0, 0, 0, 0, 9216, 0xd3c106ef -0, 100, 100, 0, 9216, 0x8871f7c2 +0, 0, 0, 1, 9216, 0xd3c106ef +0, 100, 100, 1, 9216, 0x8871f7c2 diff -Nru ffmpeg-4.2.2/tests/ref/fate/mss2-pals ffmpeg-4.4/tests/ref/fate/mss2-pals --- ffmpeg-4.2.2/tests/ref/fate/mss2-pals 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mss2-pals 2021-04-08 21:28:40.000000000 +0000 @@ -3,5 +3,5 @@ #codec_id 0: rawvideo #dimensions 0: 64x48 #sar 0: 0/1 -0, 0, 0, 0, 9216, 0xd3c106ef -0, 100, 100, 0, 9216, 0x8871f7c2 +0, 0, 0, 1, 9216, 0xd3c106ef +0, 100, 100, 1, 9216, 0x8871f7c2 diff -Nru ffmpeg-4.2.2/tests/ref/fate/mss2-rgb555 ffmpeg-4.4/tests/ref/fate/mss2-rgb555 --- ffmpeg-4.2.2/tests/ref/fate/mss2-rgb555 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mss2-rgb555 2021-04-08 21:28:40.000000000 +0000 @@ -3,5 +3,5 @@ #codec_id 0: rawvideo #dimensions 0: 64x48 #sar 0: 0/1 -0, 0, 0, 0, 6144, 0x4145b7ae -0, 100, 100, 0, 6144, 0x3b2b38de +0, 0, 0, 1, 6144, 0x4145b7ae +0, 100, 100, 1, 6144, 0x3b2b38de diff -Nru ffmpeg-4.2.2/tests/ref/fate/mss2-rgb555s ffmpeg-4.4/tests/ref/fate/mss2-rgb555s --- ffmpeg-4.2.2/tests/ref/fate/mss2-rgb555s 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mss2-rgb555s 2021-04-08 21:28:40.000000000 +0000 @@ -3,5 +3,5 @@ #codec_id 0: rawvideo #dimensions 0: 64x48 #sar 0: 0/1 -0, 0, 0, 0, 6144, 0x4145b7ae -0, 100, 100, 0, 6144, 0x3b2b38de +0, 0, 0, 1, 6144, 0x4145b7ae +0, 100, 100, 1, 6144, 0x3b2b38de diff -Nru ffmpeg-4.2.2/tests/ref/fate/mxf-d10-user-comments ffmpeg-4.4/tests/ref/fate/mxf-d10-user-comments --- ffmpeg-4.2.2/tests/ref/fate/mxf-d10-user-comments 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mxf-d10-user-comments 2021-04-08 21:28:40.000000000 +0000 @@ -1 +1,28 @@ -b659c1204f8d04e2a5607af083590dca +6dc13ae283257e898e069e5041ac8435 *tests/data/fate/mxf-d10-user-comments.mxf_d10 +3782189 tests/data/fate/mxf-d10-user-comments.mxf_d10 +#extradata 0: 34, 0x716b05c4 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: mpeg2video +#dimensions 0: 1280x720 +#sar 0: 3/4 +0, -1, 0, 1, 150000, 0x0547870d, S=1, 24, 0x5aa90ad0 +0, 0, 1, 1, 150000, 0xe80a1612, F=0x0 +0, 1, 2, 1, 150000, 0xc5c50e2f, F=0x0 +0, 2, 3, 1, 150000, 0x51e28a04, F=0x0 +0, 3, 4, 1, 150000, 0x9bbe6feb, F=0x0 +[FORMAT] +TAG:operational_pattern_ul=060e2b34.04010101.0d010201.01010900 +TAG:uid=adab4424-2f25-4dc7-92ff-29bd000c0000 +TAG:generation_uid=adab4424-2f25-4dc7-92ff-29bd000c0001 +TAG:company_name=FATE-company +TAG:product_name=FATE-test +TAG:product_version_num=0.0.0.0.0 +TAG:product_version=3.14159 +TAG:application_platform=Lavf +TAG:product_uid=adab4424-2f25-4dc7-92ff-29bd000c0002 +TAG:toolkit_version_num=0.0.0.0.0 +TAG:material_package_umid=0x060A2B340101010501010D001300000000000000000000000000000000000000 +TAG:comment_test=value +TAG:timecode=01:00:00:00 +[/FORMAT] diff -Nru ffmpeg-4.2.2/tests/ref/fate/mxf-opatom-user-comments ffmpeg-4.4/tests/ref/fate/mxf-opatom-user-comments --- ffmpeg-4.2.2/tests/ref/fate/mxf-opatom-user-comments 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mxf-opatom-user-comments 2021-04-08 21:28:40.000000000 +0000 @@ -1 +1 @@ -892cf02e44bf7d61b6d6f01e41db9375 +8475bebf3448a972ae89ba59309fd7d6 diff -Nru ffmpeg-4.2.2/tests/ref/fate/mxf-probe-applehdr10 ffmpeg-4.4/tests/ref/fate/mxf-probe-applehdr10 --- ffmpeg-4.2.2/tests/ref/fate/mxf-probe-applehdr10 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mxf-probe-applehdr10 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,166 @@ +[STREAM] +index=0 +codec_name=prores +profile=0 +codec_type=video +codec_tag_string=apco +codec_tag=0x6f637061 +width=1280 +height=720 +coded_width=1280 +coded_height=720 +closed_captions=0 +has_b_frames=0 +sample_aspect_ratio=1:1 +display_aspect_ratio=16:9 +pix_fmt=yuv422p10 +level=-99 +color_range=tv +color_space=bt2020nc +color_transfer=smpte2084 +color_primaries=bt2020 +chroma_location=unspecified +field_order=progressive +refs=1 +id=N/A +r_frame_rate=60000/1001 +avg_frame_rate=0/0 +time_base=1001/60000 +start_pts=0 +start_time=0.000000 +duration_ts=5 +duration=0.083417 +bit_rate=N/A +max_bit_rate=N/A +bits_per_raw_sample=10 +nb_frames=N/A +nb_read_frames=N/A +nb_read_packets=N/A +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 +TAG:file_package_umid=0x060A2B340101010501010D201300000040ECCE167353449C92D6F2693A9F1D75 +[SIDE_DATA] +side_data_type=Mastering display metadata +red_x=34000/50000 +red_y=16000/50000 +green_x=13250/50000 +green_y=34500/50000 +blue_x=7500/50000 +blue_y=3000/50000 +white_point_x=15635/50000 +white_point_y=16450/50000 +min_luminance=0/10000 +max_luminance=10000000/10000 +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Content light level metadata +max_content=1000 +max_average=100 +[/SIDE_DATA] +[/STREAM] +[STREAM] +index=1 +codec_name=pcm_s24le +profile=unknown +codec_type=audio +codec_tag_string=[0][0][0][0] +codec_tag=0x0000 +sample_fmt=s32 +sample_rate=48000 +channels=1 +channel_layout=unknown +bits_per_sample=24 +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=4004 +duration=0.083417 +bit_rate=1152000 +max_bit_rate=N/A +bits_per_raw_sample=24 +nb_frames=N/A +nb_read_frames=N/A +nb_read_packets=N/A +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 +TAG:file_package_umid=0x060A2B340101010501010D201300000040ECCE167353449C92D6F2693A9F1D75 +[/STREAM] +[STREAM] +index=2 +codec_name=pcm_s24le +profile=unknown +codec_type=audio +codec_tag_string=[0][0][0][0] +codec_tag=0x0000 +sample_fmt=s32 +sample_rate=48000 +channels=1 +channel_layout=unknown +bits_per_sample=24 +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=4004 +duration=0.083417 +bit_rate=1152000 +max_bit_rate=N/A +bits_per_raw_sample=24 +nb_frames=N/A +nb_read_frames=N/A +nb_read_packets=N/A +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 +TAG:file_package_umid=0x060A2B340101010501010D201300000040ECCE167353449C92D6F2693A9F1D75 +[/STREAM] +[FORMAT] +format_name=mxf +duration=0.083417 +bit_rate=30913698 +TAG:operational_pattern_ul=060e2b34.04010101.0d010201.01010900 +TAG:uid=0002475a-49e3-430b-85d9-3b35d180e3b5 +TAG:generation_uid=240f15ec-50ee-4285-83bf-7c17122fac0c +TAG:company_name=Apple Inc. +TAG:product_name=Compressor +TAG:product_version=4.4.7 (4.4.7) +TAG:product_uid=00000000-0000-0000-0000-000000000000 +TAG:modification_date=2020-09-08T16:18:57.036000Z +TAG:toolkit_version_num=3.8.0.171.1 +TAG:material_package_umid=0x060A2B340101010501010D201300000045843C9FE69D4B8FA90DDAAA1602A2E8 +TAG:timecode=00:01:15;26 +[/FORMAT] diff -Nru ffmpeg-4.2.2/tests/ref/fate/mxf-probe-d10 ffmpeg-4.4/tests/ref/fate/mxf-probe-d10 --- ffmpeg-4.2.2/tests/ref/fate/mxf-probe-d10 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mxf-probe-d10 2021-04-08 21:28:40.000000000 +0000 @@ -3,13 +3,13 @@ codec_name=mpeg2video profile=0 codec_type=video -codec_time_base=1/25 codec_tag_string=[0][0][0][0] codec_tag=0x0000 width=720 height=608 coded_width=0 coded_height=0 +closed_captions=0 has_b_frames=0 sample_aspect_ratio=152:135 display_aspect_ratio=4:3 @@ -17,11 +17,10 @@ level=5 color_range=tv color_space=unknown -color_transfer=unknown +color_transfer=bt470m color_primaries=unknown chroma_location=topleft field_order=tt -timecode=N/A refs=1 id=N/A r_frame_rate=25/1 @@ -50,13 +49,15 @@ DISPOSITION:attached_pic=0 DISPOSITION:timed_thumbnails=0 TAG:file_package_umid=0x060A2B340101010501010D1313000000AE86B200913105800000080046A54011 +[SIDE_DATA] +side_data_type=CPB properties +[/SIDE_DATA] [/STREAM] [STREAM] index=1 codec_name=pcm_s16le profile=unknown codec_type=audio -codec_time_base=1/48000 codec_tag_string=[0][0][0][0] codec_tag=0x0000 sample_fmt=s16 diff -Nru ffmpeg-4.2.2/tests/ref/fate/mxf-probe-dnxhd ffmpeg-4.4/tests/ref/fate/mxf-probe-dnxhd --- ffmpeg-4.2.2/tests/ref/fate/mxf-probe-dnxhd 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mxf-probe-dnxhd 2021-04-08 21:28:40.000000000 +0000 @@ -111,25 +111,24 @@ codec_name=dnxhd profile=1 codec_type=video -codec_time_base=0/1 codec_tag_string=[0][0][0][0] codec_tag=0x0000 width=640 height=480 coded_width=640 coded_height=480 +closed_captions=0 has_b_frames=0 sample_aspect_ratio=1:1 display_aspect_ratio=4:3 pix_fmt=yuv422p level=-99 -color_range=unknown +color_range=tv color_space=bt709 -color_transfer=unknown -color_primaries=unknown +color_transfer=bt709 +color_primaries=bt709 chroma_location=unspecified field_order=progressive -timecode=N/A refs=1 id=N/A r_frame_rate=24000/1001 @@ -172,9 +171,11 @@ TAG:uid=784c8132-ae36-ed4d-b0ff-2edf1f3f2d92 TAG:generation_uid=b6bcfcab-70ff-7331-c47c-478869de11d2 TAG:application_platform=AAFSDK (MacOS X) +TAG:toolkit_version_num=1.1.0.0.0 TAG:modification_date=2016-09-18T19:25:25.000000Z TAG:product_uid=acfbf03a-4f42-a231-d0b7-c06ecd3d4ad7 TAG:product_version=Unknown version +TAG:product_version_num=8.6.0.0.1 TAG:product_name=Avid Media Composer 8.6.3.43955 TAG:company_name=Avid Technology, Inc. TAG:material_package_umid=0x060A2B340101010101010F001300000057DEEA1570665313060E2B347F7F2A80 diff -Nru ffmpeg-4.2.2/tests/ref/fate/mxf-probe-dv25 ffmpeg-4.4/tests/ref/fate/mxf-probe-dv25 --- ffmpeg-4.2.2/tests/ref/fate/mxf-probe-dv25 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mxf-probe-dv25 2021-04-08 21:28:40.000000000 +0000 @@ -3,25 +3,24 @@ codec_name=dvvideo profile=unknown codec_type=video -codec_time_base=1/25 codec_tag_string=[0][0][0][0] codec_tag=0x0000 width=720 height=576 coded_width=720 coded_height=576 +closed_captions=0 has_b_frames=0 sample_aspect_ratio=16:15 display_aspect_ratio=4:3 pix_fmt=yuv420p level=-99 -color_range=unknown +color_range=tv color_space=unknown -color_transfer=unknown +color_transfer=bt470m color_primaries=unknown chroma_location=topleft field_order=bb -timecode=N/A refs=1 id=N/A r_frame_rate=25/1 @@ -56,7 +55,6 @@ codec_name=pcm_s16le profile=unknown codec_type=audio -codec_time_base=1/48000 codec_tag_string=[0][0][0][0] codec_tag=0x0000 sample_fmt=s16 @@ -97,7 +95,6 @@ codec_name=pcm_s16le profile=unknown codec_type=audio -codec_time_base=1/48000 codec_tag_string=[0][0][0][0] codec_tag=0x0000 sample_fmt=s16 diff -Nru ffmpeg-4.2.2/tests/ref/fate/mxf-reel_name ffmpeg-4.4/tests/ref/fate/mxf-reel_name --- ffmpeg-4.2.2/tests/ref/fate/mxf-reel_name 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mxf-reel_name 2021-04-08 21:28:40.000000000 +0000 @@ -1 +1 @@ -a788589c14f343dcc6d75aaaec0f0266 +ce49a0361d3f79106e1952d387eace51 diff -Nru ffmpeg-4.2.2/tests/ref/fate/mxf-user-comments ffmpeg-4.4/tests/ref/fate/mxf-user-comments --- ffmpeg-4.2.2/tests/ref/fate/mxf-user-comments 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/mxf-user-comments 2021-04-08 21:28:40.000000000 +0000 @@ -1 +1 @@ -683bacb0105e5bc5bbf46aa430c644d1 +956f653cd75e1a319569caec9df81b4f diff -Nru ffmpeg-4.2.2/tests/ref/fate/nuv-rtjpeg ffmpeg-4.4/tests/ref/fate/nuv-rtjpeg --- ffmpeg-4.2.2/tests/ref/fate/nuv-rtjpeg 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/nuv-rtjpeg 2021-04-08 21:28:40.000000000 +0000 @@ -3,11 +3,11 @@ #codec_id 0: rawvideo #dimensions 0: 640x480 #sar 0: 1/1 -0, 118, 118, 0, 460800, 0x54aedafe -0, 152, 152, 0, 460800, 0xb7aa8b56 -0, 177, 177, 0, 460800, 0x283ea3b5 -0, 202, 202, 0, 460800, 0x283ea3b5 -0, 235, 235, 0, 460800, 0x10e577de -0, 269, 269, 0, 460800, 0x4e091ee2 -0, 302, 302, 0, 460800, 0x2ea88828 -0, 335, 335, 0, 460800, 0x4b7f4df0 +0, 118, 118, 1, 460800, 0x54aedafe +0, 152, 152, 1, 460800, 0xb7aa8b56 +0, 177, 177, 1, 460800, 0x283ea3b5 +0, 202, 202, 1, 460800, 0x283ea3b5 +0, 235, 235, 1, 460800, 0x10e577de +0, 269, 269, 1, 460800, 0x4e091ee2 +0, 302, 302, 1, 460800, 0x2ea88828 +0, 335, 335, 1, 460800, 0x4b7f4df0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/oggopus-demux ffmpeg-4.4/tests/ref/fate/oggopus-demux --- ffmpeg-4.2.2/tests/ref/fate/oggopus-demux 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/oggopus-demux 2020-07-11 10:39:30.000000000 +0000 @@ -5,7 +5,7 @@ #sample_rate 0: 48000 #channel_layout 0: 3 #channel_layout_name 0: stereo -0, -356, -356, 960, 402, 0x89b1c40f +0, -356, -356, 960, 402, 0x89b1c40f, S=1, 10, 0x03f10065 0, 604, 604, 960, 216, 0x7bf97146 0, 1564, 1564, 960, 215, 0x6cb86d8b 0, 2524, 2524, 960, 218, 0x9cfd691c diff -Nru ffmpeg-4.2.2/tests/ref/fate/opt ffmpeg-4.4/tests/ref/fate/opt --- ffmpeg-4.2.2/tests/ref/fate/opt 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/opt 2021-04-08 21:28:40.000000000 +0000 @@ -18,31 +18,33 @@ flt=0.333333 dbl=0.333333 TestContext AVOptions: - -num E........ set num (from 0 to 100) (default 0) - -toggle E........ set toggle (from 0 to 1) (default 1) - -rational E........ set rational (from 0 to 10) (default 1/1) - -string E........ set string (default "default") - -escape E........ set escape str (default "\=,") - -flags E........ set flags (default cool) - cool E........ set cool flag - lame E........ set lame flag - mu E........ set mu flag - -size E........ set size (default "200x300") - -pix_fmt E........ set pixfmt (default 0bgr) - -sample_fmt E........ set samplefmt (default s16) - -video_rate E........ set videorate (default "25") - -duration E........ set duration (default 0.001) - -color E........ set color (default "pink") - -cl E........ set channel layout (default 0x137) - -bin E........ set binary value - -bin1 E........ set binary value - -bin2 E........ set binary value - -num64 E........ set num 64bit (from 0 to 100) (default 1) - -flt E........ set float (from 0 to 100) (default 0.333333) - -dbl E........ set double (from 0 to 100) (default 0.333333) - -bool1 E........ set boolean value (default auto) - -bool2 E........ set boolean value (default true) - -bool3 E........ set boolean value (default false) + -num E.......... set num (from 0 to 100) (default 0) + -toggle E.......... set toggle (from 0 to 1) (default 1) + -rational E.......... set rational (from 0 to 10) (default 1/1) + -string E.......... set string (default "default") + -escape E.......... set escape str (default "\=,") + -flags E.......... set flags (default cool) + cool E.......... set cool flag + lame E.......... set lame flag + mu E.......... set mu flag + -size E.......... set size (default "200x300") + -pix_fmt E.......... set pixfmt (default 0bgr) + -sample_fmt E.......... set samplefmt (default s16) + -video_rate E.......... set videorate (default "25") + -duration E.......... set duration (default 0.001) + -color E.......... set color (default "pink") + -cl E.......... set channel layout (default 0x137) + -bin E.......... set binary value + -bin1 E.......... set binary value + -bin2 E.......... set binary value + -num64 E.......... set num 64bit (from 0 to 100) (default 1) + -flt E.......... set float (from 0 to 100) (default 0.333333) + -dbl E.......... set double (from 0 to 100) (default 0.333333) + -bool1 E.......... set boolean value (default auto) + -bool2 E.......... set boolean value (default true) + -bool3 E.......... set boolean value (default false) + -dict1 E.......... set dictionary value + -dict2 E.......... set dictionary value (default "happy=':-)'") Testing av_opt_is_set_to_default() name: num default:1 error: @@ -70,6 +72,8 @@ name: bool1 default:0 error: name: bool2 default:0 error: name: bool3 default:1 error: +name: dict1 default:1 error: +name: dict2 default:0 error: name: num default:1 error: name: toggle default:1 error: name: rational default:1 error: @@ -95,9 +99,37 @@ name: bool1 default:1 error: name: bool2 default:1 error: name: bool3 default:1 error: +name: dict1 default:1 error: +name: dict2 default:1 error: + +Testing av_opt_get/av_opt_set() +name: num get: 0 set: OK get: 0 OK +name: toggle get: 1 set: OK get: 1 OK +name: rational get: 1/1 set: OK get: 1/1 OK +name: string get: default set: OK get: default OK +name: escape get: \=, set: OK get: \=, OK +name: flags get: 0x00000001 set: OK get: 0x00000001 OK +name: size get: 200x300 set: OK get: 200x300 OK +name: pix_fmt get: 0bgr set: OK get: 0bgr OK +name: sample_fmt get: s16 set: OK get: s16 OK +name: video_rate get: 25/1 set: OK get: 25/1 OK +name: duration get: 0.001 set: OK get: 0.001 OK +name: color get: 0xffc0cbff set: OK get: 0xffc0cbff OK +name: cl get: 0x137 set: OK get: 0x137 OK +name: bin get: 62696E00 set: OK get: 62696E00 OK +name: bin1 get: set: OK get: OK +name: bin2 get: set: OK get: OK +name: num64 get: 1 set: OK get: 1 OK +name: flt get: 0.333333 set: OK get: 0.333333 OK +name: dbl get: 0.333333 set: OK get: 0.333333 OK +name: bool1 get: auto set: OK get: auto OK +name: bool2 get: true set: OK get: true OK +name: bool3 get: false set: OK get: false OK +name: dict1 get: set: OK get: OK +name: dict2 get: happy=\:-) set: OK get: happy=\:-) OK Test av_opt_serialize() -num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0.001,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333,bool1=auto,bool2=true,bool3=false +num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0.001,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333,bool1=auto,bool2=true,bool3=false,dict1=,dict2=happy\=\\:-) Setting entry with key 'num' to value '0' Setting entry with key 'toggle' to value '1' Setting entry with key 'rational' to value '1/1' @@ -120,7 +152,9 @@ Setting entry with key 'bool1' to value 'auto' Setting entry with key 'bool2' to value 'true' Setting entry with key 'bool3' to value 'false' -num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0.001,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333,bool1=auto,bool2=true,bool3=false +Setting entry with key 'dict1' to value '' +Setting entry with key 'dict2' to value 'happy=\:-)' +num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0.001,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333,bool1=auto,bool2=true,bool3=false,dict1=,dict2=happy\=\\:-) Testing av_set_options_string() Setting options string '' @@ -341,6 +375,9 @@ Setting options string 'bool2=auto' Setting entry with key 'bool2' to value 'auto' OK 'bool2=auto' +Setting options string 'dict1='happy=\:-):sad=\:-('' +Setting entry with key 'dict1' to value 'happy=\:-):sad=\:-(' +OK 'dict1='happy=\:-):sad=\:-('' Testing av_opt_set_from_string() Setting options string '' diff -Nru ffmpeg-4.2.2/tests/ref/fate/psd-rgb48 ffmpeg-4.4/tests/ref/fate/psd-rgb48 --- ffmpeg-4.2.2/tests/ref/fate/psd-rgb48 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/psd-rgb48 2021-04-08 21:28:40.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 128x128 #sar 0: 0/1 -0, 0, 0, 1, 49152, 0x0bc6503a +0, 0, 0, 1, 49152, 0x9fb6903c diff -Nru ffmpeg-4.2.2/tests/ref/fate/psd-rgba64 ffmpeg-4.4/tests/ref/fate/psd-rgba64 --- ffmpeg-4.2.2/tests/ref/fate/psd-rgba64 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/psd-rgba64 2021-04-08 21:28:40.000000000 +0000 @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 128x128 #sar 0: 0/1 -0, 0, 0, 1, 49152, 0xb847fd73 +0, 0, 0, 1, 49152, 0x05856a20 diff -Nru ffmpeg-4.2.2/tests/ref/fate/qtrle-8bit ffmpeg-4.4/tests/ref/fate/qtrle-8bit --- ffmpeg-4.2.2/tests/ref/fate/qtrle-8bit 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/qtrle-8bit 2020-07-11 10:39:30.000000000 +0000 @@ -4,60 +4,169 @@ #dimensions 0: 640x480 #sar 0: 0/1 0, 0, 0, 1, 921600, 0x1492e3ed +0, 1, 1, 1, 921600, 0x1492e3ed +0, 2, 2, 1, 921600, 0x1492e3ed 0, 3, 3, 1, 921600, 0x23ef4fc7 +0, 4, 4, 1, 921600, 0x23ef4fc7 0, 5, 5, 1, 921600, 0xe406d4be +0, 6, 6, 1, 921600, 0xe406d4be +0, 7, 7, 1, 921600, 0xe406d4be 0, 8, 8, 1, 921600, 0x62b8b5a1 +0, 9, 9, 1, 921600, 0x62b8b5a1 0, 10, 10, 1, 921600, 0x7d8ba674 +0, 11, 11, 1, 921600, 0x7d8ba674 +0, 12, 12, 1, 921600, 0x7d8ba674 0, 13, 13, 1, 921600, 0xfe666be7 +0, 14, 14, 1, 921600, 0xfe666be7 0, 15, 15, 1, 921600, 0x721baec0 +0, 16, 16, 1, 921600, 0x721baec0 +0, 17, 17, 1, 921600, 0x721baec0 0, 18, 18, 1, 921600, 0xc237180a +0, 19, 19, 1, 921600, 0xc237180a 0, 20, 20, 1, 921600, 0xf03a7482 +0, 21, 21, 1, 921600, 0xf03a7482 +0, 22, 22, 1, 921600, 0xf03a7482 0, 23, 23, 1, 921600, 0x5612a391 +0, 24, 24, 1, 921600, 0x5612a391 0, 25, 25, 1, 921600, 0x9dbcc46a +0, 26, 26, 1, 921600, 0x9dbcc46a +0, 27, 27, 1, 921600, 0x9dbcc46a 0, 28, 28, 1, 921600, 0xa128a5d5 +0, 29, 29, 1, 921600, 0xa128a5d5 0, 30, 30, 1, 921600, 0x63e0025c +0, 31, 31, 1, 921600, 0x63e0025c +0, 32, 32, 1, 921600, 0x63e0025c 0, 33, 33, 1, 921600, 0x262359ed +0, 34, 34, 1, 921600, 0x262359ed 0, 35, 35, 1, 921600, 0x343688e8 +0, 36, 36, 1, 921600, 0x343688e8 +0, 37, 37, 1, 921600, 0x343688e8 +0, 38, 38, 1, 921600, 0x343688e8 +0, 39, 39, 1, 921600, 0x343688e8 +0, 40, 40, 1, 921600, 0x343688e8 +0, 41, 41, 1, 921600, 0x343688e8 +0, 42, 42, 1, 921600, 0x343688e8 +0, 43, 43, 1, 921600, 0x343688e8 +0, 44, 44, 1, 921600, 0x343688e8 0, 45, 45, 1, 921600, 0xe4b29d57 +0, 46, 46, 1, 921600, 0xe4b29d57 +0, 47, 47, 1, 921600, 0xe4b29d57 0, 48, 48, 1, 921600, 0x198e8a4a +0, 49, 49, 1, 921600, 0x198e8a4a 0, 50, 50, 1, 921600, 0x0cad8dc9 +0, 51, 51, 1, 921600, 0x0cad8dc9 +0, 52, 52, 1, 921600, 0x0cad8dc9 0, 53, 53, 1, 921600, 0x1f74cf3d +0, 54, 54, 1, 921600, 0x1f74cf3d 0, 55, 55, 1, 921600, 0xec5b5449 +0, 56, 56, 1, 921600, 0xec5b5449 +0, 57, 57, 1, 921600, 0xec5b5449 0, 58, 58, 1, 921600, 0x39829711 +0, 59, 59, 1, 921600, 0x39829711 0, 60, 60, 1, 921600, 0x6de5b9c6 +0, 61, 61, 1, 921600, 0x6de5b9c6 +0, 62, 62, 1, 921600, 0x6de5b9c6 0, 63, 63, 1, 921600, 0x47b0e9d4 +0, 64, 64, 1, 921600, 0x47b0e9d4 0, 65, 65, 1, 921600, 0x756452b8 +0, 66, 66, 1, 921600, 0x756452b8 +0, 67, 67, 1, 921600, 0x756452b8 0, 68, 68, 1, 921600, 0x6fce3478 +0, 69, 69, 1, 921600, 0x6fce3478 0, 70, 70, 1, 921600, 0x372397cd +0, 71, 71, 1, 921600, 0x372397cd +0, 72, 72, 1, 921600, 0x372397cd 0, 73, 73, 1, 921600, 0xe3999ba1 +0, 74, 74, 1, 921600, 0xe3999ba1 0, 75, 75, 1, 921600, 0x6ba26b43 +0, 76, 76, 1, 921600, 0x6ba26b43 +0, 77, 77, 1, 921600, 0x6ba26b43 0, 78, 78, 1, 921600, 0x4e9ee49e +0, 79, 79, 1, 921600, 0x4e9ee49e 0, 80, 80, 1, 921600, 0xdb5fd6e7 +0, 81, 81, 1, 921600, 0xdb5fd6e7 +0, 82, 82, 1, 921600, 0xdb5fd6e7 0, 83, 83, 1, 921600, 0x8f2254a5 +0, 84, 84, 1, 921600, 0x8f2254a5 +0, 85, 85, 1, 921600, 0x8f2254a5 +0, 86, 86, 1, 921600, 0x8f2254a5 +0, 87, 87, 1, 921600, 0x8f2254a5 +0, 88, 88, 1, 921600, 0x8f2254a5 +0, 89, 89, 1, 921600, 0x8f2254a5 +0, 90, 90, 1, 921600, 0x8f2254a5 +0, 91, 91, 1, 921600, 0x8f2254a5 +0, 92, 92, 1, 921600, 0x8f2254a5 0, 93, 93, 1, 921600, 0x57e95c32 +0, 94, 94, 1, 921600, 0x57e95c32 0, 95, 95, 1, 921600, 0x41627a9b +0, 96, 96, 1, 921600, 0x41627a9b +0, 97, 97, 1, 921600, 0x41627a9b 0, 98, 98, 1, 921600, 0x7412dcee +0, 99, 99, 1, 921600, 0x7412dcee 0, 100, 100, 1, 921600, 0xaebe10ed +0, 101, 101, 1, 921600, 0xaebe10ed +0, 102, 102, 1, 921600, 0xaebe10ed 0, 103, 103, 1, 921600, 0x411a91f6 +0, 104, 104, 1, 921600, 0x411a91f6 0, 105, 105, 1, 921600, 0xb059df3f +0, 106, 106, 1, 921600, 0xb059df3f +0, 107, 107, 1, 921600, 0xb059df3f 0, 108, 108, 1, 921600, 0x4d6f5a77 +0, 109, 109, 1, 921600, 0x4d6f5a77 0, 110, 110, 1, 921600, 0xbbf06df4 +0, 111, 111, 1, 921600, 0xbbf06df4 +0, 112, 112, 1, 921600, 0xbbf06df4 0, 113, 113, 1, 921600, 0xe27f7bf6 +0, 114, 114, 1, 921600, 0xe27f7bf6 0, 115, 115, 1, 921600, 0xd7e8360e +0, 116, 116, 1, 921600, 0xd7e8360e +0, 117, 117, 1, 921600, 0xd7e8360e 0, 118, 118, 1, 921600, 0x1dd4c344 +0, 119, 119, 1, 921600, 0x1dd4c344 0, 120, 120, 1, 921600, 0x7995a7ce +0, 121, 121, 1, 921600, 0x7995a7ce +0, 122, 122, 1, 921600, 0x7995a7ce 0, 123, 123, 1, 921600, 0x2ef3c566 +0, 124, 124, 1, 921600, 0x2ef3c566 0, 125, 125, 1, 921600, 0xf296736e +0, 126, 126, 1, 921600, 0xf296736e +0, 127, 127, 1, 921600, 0xf296736e +0, 128, 128, 1, 921600, 0xf296736e +0, 129, 129, 1, 921600, 0xf296736e +0, 130, 130, 1, 921600, 0xf296736e +0, 131, 131, 1, 921600, 0xf296736e +0, 132, 132, 1, 921600, 0xf296736e +0, 133, 133, 1, 921600, 0xf296736e +0, 134, 134, 1, 921600, 0xf296736e 0, 135, 135, 1, 921600, 0x1a488311 +0, 136, 136, 1, 921600, 0x1a488311 +0, 137, 137, 1, 921600, 0x1a488311 0, 138, 138, 1, 921600, 0x9e28011b +0, 139, 139, 1, 921600, 0x9e28011b 0, 140, 140, 1, 921600, 0x84d1ea80 +0, 141, 141, 1, 921600, 0x84d1ea80 +0, 142, 142, 1, 921600, 0x84d1ea80 0, 143, 143, 1, 921600, 0x9ed41052 +0, 144, 144, 1, 921600, 0x9ed41052 0, 145, 145, 1, 921600, 0xd4db7206 +0, 146, 146, 1, 921600, 0xd4db7206 +0, 147, 147, 1, 921600, 0xd4db7206 0, 148, 148, 1, 921600, 0x55f695a9 +0, 149, 149, 1, 921600, 0x55f695a9 0, 150, 150, 1, 921600, 0x9d8c667f +0, 151, 151, 1, 921600, 0x9d8c667f +0, 152, 152, 1, 921600, 0x9d8c667f 0, 153, 153, 1, 921600, 0x9b6037ec +0, 154, 154, 1, 921600, 0x9b6037ec 0, 155, 155, 1, 921600, 0x57c5e835 +0, 156, 156, 1, 921600, 0x57c5e835 +0, 157, 157, 1, 921600, 0x57c5e835 0, 158, 158, 1, 921600, 0x476dad89 +0, 159, 159, 1, 921600, 0x476dad89 0, 160, 160, 1, 921600, 0xcfd6ad2b +0, 161, 161, 1, 921600, 0xcfd6ad2b +0, 162, 162, 1, 921600, 0xcfd6ad2b 0, 163, 163, 1, 921600, 0x3b372379 +0, 164, 164, 1, 921600, 0x3b372379 0, 165, 165, 1, 921600, 0x36f245f5 +0, 166, 166, 1, 921600, 0x36f245f5 diff -Nru ffmpeg-4.2.2/tests/ref/fate/rgb24-mkv ffmpeg-4.4/tests/ref/fate/rgb24-mkv --- ffmpeg-4.2.2/tests/ref/fate/rgb24-mkv 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/rgb24-mkv 2021-04-08 21:28:40.000000000 +0000 @@ -1,5 +1,5 @@ -ffe2c21083d56764aaae7945fd146326 *tests/data/fate/rgb24-mkv.matroska -58305 tests/data/fate/rgb24-mkv.matroska +6244b8750d4155d3c9357bab26396ef9 *tests/data/fate/rgb24-mkv.matroska +58245 tests/data/fate/rgb24-mkv.matroska #tb 0: 1/10 #media_type 0: video #codec_id 0: rawvideo diff -Nru ffmpeg-4.2.2/tests/ref/fate/segment-mp4-to-ts ffmpeg-4.4/tests/ref/fate/segment-mp4-to-ts --- ffmpeg-4.2.2/tests/ref/fate/segment-mp4-to-ts 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/segment-mp4-to-ts 2021-04-08 21:28:40.000000000 +0000 @@ -1,38 +1,38 @@ -#extradata 0: 51, 0x5d140df9 +#extradata 0: 50, 0x4f1b0df9 #tb 0: 1/90000 #media_type 0: video #codec_id 0: h264 #dimensions 0: 640x360 #sar 0: 1/1 -0, -7200, 0, 0, 22631, 0x9cec9541, S=1, 1, 0x00e000e0 -0, -3600, 14400, 0, 4021, 0xbf7cdb02, F=0x0, S=1, 1, 0x00e000e0 -0, 0, 7200, 0, 1096, 0x4f162690, F=0x0, S=1, 1, 0x00e000e0 -0, 3600, 3600, 0, 687, 0x00394b95, F=0x0, S=1, 1, 0x00e000e0 -0, 7200, 10800, 0, 445, 0x08c3d065, F=0x0, S=1, 1, 0x00e000e0 -0, 10800, 28800, 0, 4212, 0x56d12b8f, F=0x0, S=1, 1, 0x00e000e0 -0, 14400, 21600, 0, 1117, 0xd521260b, F=0x0, S=1, 1, 0x00e000e0 -0, 18000, 18000, 0, 892, 0x4262bdbc, F=0x0, S=1, 1, 0x00e000e0 -0, 21600, 25200, 0, 480, 0x3be1ef0b, F=0x0, S=1, 1, 0x00e000e0 -0, 25200, 43200, 0, 4065, 0x40dee237, F=0x0, S=1, 1, 0x00e000e0 -0, 28800, 36000, 0, 962, 0x31a4ceb1, F=0x0, S=1, 1, 0x00e000e0 -0, 32400, 32400, 0, 651, 0xb2aa317a, F=0x0, S=1, 1, 0x00e000e0 -0, 36000, 39600, 0, 543, 0x9c4e0024, F=0x0, S=1, 1, 0x00e000e0 -0, 39600, 57600, 0, 4221, 0x77c23977, F=0x0, S=1, 1, 0x00e000e0 -0, 43200, 50400, 0, 1040, 0x482cfa34, F=0x0, S=1, 1, 0x00e000e0 -0, 46800, 46800, 0, 576, 0x2686136a, F=0x0, S=1, 1, 0x00e000e0 -0, 50400, 54000, 0, 607, 0xc53c2339, F=0x0, S=1, 1, 0x00e000e0 -0, 54000, 72000, 0, 4755, 0x2f642b58, F=0x0, S=1, 1, 0x00e000e0 -0, 57600, 64800, 0, 1182, 0xbe1a4847, F=0x0, S=1, 1, 0x00e000e0 -0, 61200, 61200, 0, 809, 0x8d948a4e, F=0x0, S=1, 1, 0x00e000e0 -0, 64800, 68400, 0, 656, 0x4fa03c2b, F=0x0, S=1, 1, 0x00e000e0 -0, 68400, 86400, 0, 26555, 0x5629b584, S=1, 1, 0x00e000e0 -0, 72000, 79200, 0, 1141, 0x761b31e8, F=0x0, S=1, 1, 0x00e000e0 -0, 75600, 75600, 0, 717, 0x57746351, F=0x0, S=1, 1, 0x00e000e0 -0, 79200, 82800, 0, 693, 0x78b24263, F=0x0, S=1, 1, 0x00e000e0 -0, 82800, 100800, 0, 3417, 0x560dbc89, F=0x0, S=1, 1, 0x00e000e0 -0, 86400, 93600, 0, 1128, 0xc0f1383c, F=0x0, S=1, 1, 0x00e000e0 -0, 90000, 90000, 0, 650, 0xc3ad485e, F=0x0, S=1, 1, 0x00e000e0 -0, 93600, 97200, 0, 766, 0xd3e9757d, F=0x0, S=1, 1, 0x00e000e0 +0, -7200, 0, 3600, 22630, 0x9b109541, S=1, 1, 0x00e000e0 +0, -3600, 14400, 3600, 4021, 0xbf7cdb02, F=0x0, S=1, 1, 0x00e000e0 +0, 0, 7200, 3600, 1096, 0x4f162690, F=0x0, S=1, 1, 0x00e000e0 +0, 3600, 3600, 3600, 687, 0x00394b95, F=0x0, S=1, 1, 0x00e000e0 +0, 7200, 10800, 3600, 445, 0x08c3d065, F=0x0, S=1, 1, 0x00e000e0 +0, 10800, 28800, 3600, 4212, 0x56d12b8f, F=0x0, S=1, 1, 0x00e000e0 +0, 14400, 21600, 3600, 1117, 0xd521260b, F=0x0, S=1, 1, 0x00e000e0 +0, 18000, 18000, 3600, 892, 0x4262bdbc, F=0x0, S=1, 1, 0x00e000e0 +0, 21600, 25200, 3600, 480, 0x3be1ef0b, F=0x0, S=1, 1, 0x00e000e0 +0, 25200, 43200, 3600, 4065, 0x40dee237, F=0x0, S=1, 1, 0x00e000e0 +0, 28800, 36000, 3600, 962, 0x31a4ceb1, F=0x0, S=1, 1, 0x00e000e0 +0, 32400, 32400, 3600, 651, 0xb2aa317a, F=0x0, S=1, 1, 0x00e000e0 +0, 36000, 39600, 3600, 543, 0x9c4e0024, F=0x0, S=1, 1, 0x00e000e0 +0, 39600, 57600, 3600, 4221, 0x77c23977, F=0x0, S=1, 1, 0x00e000e0 +0, 43200, 50400, 3600, 1040, 0x482cfa34, F=0x0, S=1, 1, 0x00e000e0 +0, 46800, 46800, 3600, 576, 0x2686136a, F=0x0, S=1, 1, 0x00e000e0 +0, 50400, 54000, 3600, 607, 0xc53c2339, F=0x0, S=1, 1, 0x00e000e0 +0, 54000, 72000, 3600, 4755, 0x2f642b58, F=0x0, S=1, 1, 0x00e000e0 +0, 57600, 64800, 3600, 1182, 0xbe1a4847, F=0x0, S=1, 1, 0x00e000e0 +0, 61200, 61200, 3600, 809, 0x8d948a4e, F=0x0, S=1, 1, 0x00e000e0 +0, 64800, 68400, 3600, 656, 0x4fa03c2b, F=0x0, S=1, 1, 0x00e000e0 +0, 68400, 86400, 3600, 26555, 0x5629b584, S=1, 1, 0x00e000e0 +0, 72000, 79200, 3600, 1141, 0x761b31e8, F=0x0, S=1, 1, 0x00e000e0 +0, 75600, 75600, 3600, 717, 0x57746351, F=0x0, S=1, 1, 0x00e000e0 +0, 79200, 82800, 3600, 693, 0x78b24263, F=0x0, S=1, 1, 0x00e000e0 +0, 82800, 100800, 3600, 3417, 0x560dbc89, F=0x0, S=1, 1, 0x00e000e0 +0, 86400, 93600, 3600, 1128, 0xc0f1383c, F=0x0, S=1, 1, 0x00e000e0 +0, 90000, 90000, 3600, 650, 0xc3ad485e, F=0x0, S=1, 1, 0x00e000e0 +0, 93600, 97200, 3600, 766, 0xd3e9757d, F=0x0, S=1, 1, 0x00e000e0 0, 97200, 115200, 3600, 4268, 0xec1235b5, F=0x0, S=1, 1, 0x00e000e0 0, 100800, 108000, 3600, 1119, 0x65f51fb7, F=0x0, S=1, 1, 0x00e000e0 0, 104400, 104400, 3600, 766, 0x213b78d3, F=0x0, S=1, 1, 0x00e000e0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/smjpeg-demux ffmpeg-4.4/tests/ref/fate/smjpeg-demux --- ffmpeg-4.2.2/tests/ref/fate/smjpeg-demux 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/smjpeg-demux 2021-04-08 21:28:40.000000000 +0000 @@ -9,239 +9,239 @@ #sample_rate 1: 22050 #channel_layout 1: 4 #channel_layout_name 1: mono -0, 0, 0, 0, 734, 0x5a042c2c +0, 0, 0, 111, 734, 0x5a042c2c 1, 0, 0, 23, 260, 0x00000000 1, 23, 23, 23, 260, 0x00000000 1, 46, 46, 23, 260, 0xac9e0a9b 1, 69, 69, 23, 260, 0x89256f5b 1, 92, 92, 23, 260, 0x8e646e36 -0, 111, 111, 0, 763, 0xb5893f2f +0, 111, 111, 111, 763, 0xb5893f2f 1, 116, 116, 23, 260, 0x3ab972fc 1, 139, 139, 23, 260, 0xaea86bb2 1, 162, 162, 23, 260, 0x2366447a 1, 185, 185, 23, 260, 0x82c14f9c 1, 208, 208, 23, 260, 0xcdcf6fa8 -0, 222, 222, 0, 3023, 0x0f3907d3 +0, 222, 222, 111, 3023, 0x0f3907d3 1, 232, 232, 23, 260, 0xb3ed64bd 1, 255, 255, 23, 260, 0xac304b92 1, 278, 278, 23, 260, 0xc8bc553b 1, 301, 301, 23, 260, 0xd35572b4 1, 325, 325, 23, 260, 0x182f6190 -0, 333, 333, 0, 4800, 0x22e6e18a +0, 333, 333, 111, 4800, 0x22e6e18a 1, 348, 348, 23, 260, 0xbf9145c0 1, 371, 371, 23, 260, 0x0ec85a7e 1, 394, 394, 23, 260, 0x3684720e 1, 417, 417, 23, 260, 0xe985616a 1, 441, 441, 23, 260, 0x12b147dc -0, 444, 444, 0, 6417, 0x427adde5 +0, 444, 444, 111, 6417, 0x427adde5 1, 464, 464, 23, 260, 0xb8b55dd9 1, 487, 487, 23, 260, 0xfd4a7007 1, 510, 510, 23, 260, 0xfcc05c9a 1, 534, 534, 23, 260, 0x20f74aea -0, 555, 555, 0, 6776, 0x7a74c6ad +0, 555, 555, 111, 6776, 0x7a74c6ad 1, 557, 557, 23, 260, 0x025359ca 1, 580, 580, 23, 260, 0xace44ba1 1, 603, 603, 23, 260, 0x03506929 1, 626, 626, 23, 260, 0x8a926f17 1, 650, 650, 23, 260, 0x4a7061e7 -0, 666, 666, 0, 6808, 0x1f6eb7c3 +0, 666, 666, 111, 6808, 0x1f6eb7c3 1, 673, 673, 23, 260, 0xf8b66cc9 1, 696, 696, 23, 260, 0xe8c96dec 1, 719, 719, 23, 260, 0x672a54a6 1, 743, 743, 23, 260, 0xe97b5698 1, 766, 766, 23, 260, 0x377f684d -0, 777, 777, 0, 6726, 0x452087e6 +0, 777, 777, 111, 6726, 0x452087e6 1, 789, 789, 23, 260, 0xe9a66786 1, 812, 812, 23, 260, 0xf8e17080 1, 835, 835, 23, 260, 0x65eb662a 1, 859, 859, 23, 260, 0xd8d361e9 1, 882, 882, 23, 260, 0xb8115a0b -0, 888, 888, 0, 6829, 0xee82b109 +0, 888, 888, 111, 6829, 0xee82b109 1, 905, 905, 23, 260, 0xa5a85461 1, 928, 928, 23, 260, 0xf401663b 1, 952, 952, 23, 260, 0x042f714e 1, 975, 975, 23, 260, 0xdf195820 1, 998, 998, 23, 260, 0x0a67653c -0, 999, 999, 0, 7055, 0xf41f1108 +0, 999, 999, 111, 7055, 0xf41f1108 1, 1021, 1021, 23, 260, 0xe9b44d02 1, 1044, 1044, 23, 260, 0xbd4747b9 1, 1068, 1068, 23, 260, 0x3ef66738 1, 1091, 1091, 23, 260, 0x0f4a6e44 -0, 1111, 1111, 0, 6977, 0xf8fe1ede +0, 1111, 1111, 111, 6977, 0xf8fe1ede 1, 1114, 1114, 23, 260, 0xaa3d6eb6 1, 1137, 1137, 23, 260, 0xb9a46c4a 1, 1160, 1160, 23, 260, 0x4f974c2e 1, 1184, 1184, 23, 260, 0x9e714a00 1, 1207, 1207, 23, 260, 0x601a7152 -0, 1222, 1222, 0, 6942, 0x9ad105c6 +0, 1222, 1222, 111, 6942, 0x9ad105c6 1, 1230, 1230, 23, 260, 0xaf317064 1, 1253, 1253, 23, 260, 0x163d4829 1, 1277, 1277, 23, 260, 0xc56b4f1a 1, 1300, 1300, 23, 260, 0x7623729c 1, 1323, 1323, 23, 260, 0xa514694f -0, 1333, 1333, 0, 6926, 0xe239dad6 +0, 1333, 1333, 111, 6926, 0xe239dad6 1, 1346, 1346, 23, 260, 0x93ee4ad8 1, 1369, 1369, 23, 260, 0x6d8e573f 1, 1393, 1393, 23, 260, 0x13256d68 1, 1416, 1416, 23, 260, 0x187761a2 1, 1439, 1439, 23, 260, 0x426045e7 -0, 1444, 1444, 0, 6966, 0x81dcfab1 +0, 1444, 1444, 111, 6966, 0x81dcfab1 1, 1462, 1462, 23, 260, 0x7e7e5891 1, 1486, 1486, 23, 260, 0xd6926dcc 1, 1509, 1509, 23, 260, 0xf0196061 1, 1532, 1532, 23, 260, 0x7cac49a3 -0, 1555, 1555, 0, 6896, 0x31e6cc02 +0, 1555, 1555, 111, 6896, 0x31e6cc02 1, 1555, 1555, 23, 260, 0x24f4549a 1, 1578, 1578, 23, 260, 0x937f551d 1, 1602, 1602, 23, 260, 0x9bf462c5 1, 1625, 1625, 23, 260, 0xd1e07436 1, 1648, 1648, 23, 260, 0xdab36215 -0, 1666, 1666, 0, 6889, 0x1cc1006e +0, 1666, 1666, 111, 6889, 0x1cc1006e 1, 1671, 1671, 23, 260, 0xabc5662b 1, 1695, 1695, 23, 260, 0xa24f6bf1 1, 1718, 1718, 23, 260, 0x39e664b2 1, 1741, 1741, 23, 260, 0xf5dc54ca 1, 1764, 1764, 23, 260, 0xc3b16974 -0, 1777, 1777, 0, 6933, 0xc303f87f +0, 1777, 1777, 111, 6933, 0xc303f87f 1, 1787, 1787, 23, 260, 0x6cf46bca 1, 1811, 1811, 23, 260, 0x7a6b69b9 1, 1834, 1834, 23, 260, 0xc02f69b9 1, 1857, 1857, 23, 260, 0x7fc764a9 1, 1880, 1880, 23, 260, 0xd9705b09 -0, 1888, 1888, 0, 7034, 0xb4970a20 +0, 1888, 1888, 111, 7034, 0xb4970a20 1, 1904, 1904, 23, 260, 0x17b05f49 1, 1927, 1927, 23, 260, 0x10ad647c 1, 1950, 1950, 23, 260, 0xf9636d69 1, 1973, 1973, 23, 260, 0x622b5ad9 1, 1996, 1996, 23, 260, 0x175b646d -0, 1999, 1999, 0, 6961, 0xf064095d +0, 1999, 1999, 111, 6961, 0xf064095d 1, 2020, 2020, 23, 260, 0x722b5827 1, 2043, 2043, 23, 260, 0x83614974 1, 2066, 2066, 23, 260, 0x80366587 1, 2089, 2089, 23, 260, 0x050f6bf9 -0, 2111, 2111, 0, 7089, 0x5ba350f9 +0, 2111, 2111, 111, 7089, 0x5ba350f9 1, 2113, 2113, 23, 260, 0x949d6735 1, 2136, 2136, 23, 260, 0x62cd7184 1, 2159, 2159, 23, 260, 0x21e45713 1, 2182, 2182, 23, 260, 0x56314509 1, 2205, 2205, 23, 260, 0x7a1570d3 -0, 2222, 2222, 0, 7078, 0xa83f3e88 +0, 2222, 2222, 111, 7078, 0xa83f3e88 1, 2229, 2229, 23, 260, 0x205a6ffb 1, 2252, 2252, 23, 260, 0xead94483 1, 2275, 2275, 23, 260, 0x93c84f10 1, 2298, 2298, 23, 260, 0xdf45726f 1, 2321, 2321, 23, 260, 0x35016f1e -0, 2333, 2333, 0, 7147, 0xcda66cfc +0, 2333, 2333, 111, 7147, 0xcda66cfc 1, 2345, 2345, 23, 260, 0xa8114bcd 1, 2368, 2368, 23, 260, 0x14c45130 1, 2391, 2391, 23, 260, 0x97b07052 1, 2414, 2414, 23, 260, 0x039b6c77 1, 2438, 2438, 23, 260, 0x46f74635 -0, 2444, 2444, 0, 7173, 0xb7455859 +0, 2444, 2444, 111, 7173, 0xb7455859 1, 2461, 2461, 23, 260, 0x4116540d 1, 2484, 2484, 23, 260, 0x26747067 1, 2507, 2507, 23, 260, 0x37f16485 1, 2530, 2530, 23, 260, 0x631d4a33 1, 2554, 2554, 23, 260, 0x14ed598d -0, 2555, 2555, 0, 7213, 0x97b89994 +0, 2555, 2555, 111, 7213, 0x97b89994 1, 2577, 2577, 23, 260, 0x3f9349e7 1, 2600, 2600, 23, 260, 0x91295757 1, 2623, 2623, 23, 260, 0x95de72bc 1, 2647, 2647, 23, 260, 0xc7ee5ddb -0, 2666, 2666, 0, 7170, 0xca8b2948 +0, 2666, 2666, 111, 7170, 0xca8b2948 1, 2670, 2670, 23, 260, 0x38e965cd 1, 2693, 2693, 23, 260, 0xfae169e9 1, 2716, 2716, 23, 260, 0x9c226143 1, 2739, 2739, 23, 260, 0x1a804dbe 1, 2763, 2763, 23, 260, 0x4aeb633c -0, 2777, 2777, 0, 7174, 0xc7cc6bbb +0, 2777, 2777, 111, 7174, 0xc7cc6bbb 1, 2786, 2786, 23, 260, 0xa66e6bbb 1, 2809, 2809, 23, 260, 0x51d17109 1, 2832, 2832, 23, 260, 0x2bc86b9b 1, 2856, 2856, 23, 260, 0xe56e6378 1, 2879, 2879, 23, 260, 0x95665b47 -0, 2888, 2888, 0, 7235, 0xc2e68d2b +0, 2888, 2888, 111, 7235, 0xc2e68d2b 1, 2902, 2902, 23, 260, 0x1c255fdb 1, 2925, 2925, 23, 260, 0x3a2456cb 1, 2948, 2948, 23, 260, 0xe18e7270 1, 2972, 2972, 23, 260, 0x55b65c60 1, 2995, 2995, 23, 260, 0x62be6515 -0, 3000, 3000, 0, 7261, 0x8204a423 +0, 3000, 3000, 111, 7261, 0x8204a423 1, 3018, 3018, 23, 260, 0xdba25d09 1, 3041, 3041, 23, 260, 0xd7cc4e40 1, 3065, 3065, 23, 260, 0x335661be 1, 3088, 3088, 23, 260, 0xc3286de3 -0, 3111, 3111, 0, 7353, 0xacc7e7c0 +0, 3111, 3111, 111, 7353, 0xacc7e7c0 1, 3111, 3111, 23, 260, 0x47e76e35 1, 3134, 3134, 23, 260, 0x4b716f77 1, 3157, 3157, 23, 260, 0x0716519e 1, 3181, 3181, 23, 260, 0x032b4490 1, 3204, 3204, 23, 260, 0x15f067e8 -0, 3222, 3222, 0, 7065, 0x45035c5c +0, 3222, 3222, 111, 7065, 0x45035c5c 1, 3227, 3227, 23, 260, 0x16766ffa 1, 3250, 3250, 23, 260, 0xc94154ac 1, 3274, 3274, 23, 260, 0x74764bcd 1, 3297, 3297, 23, 260, 0x3fad6f8f 1, 3320, 3320, 23, 260, 0x5fa972a9 -0, 3333, 3333, 0, 7269, 0x72edbb76 +0, 3333, 3333, 111, 7269, 0x72edbb76 1, 3343, 3343, 23, 260, 0xde2a4b7b 1, 3366, 3366, 23, 260, 0xd8494408 1, 3390, 3390, 23, 260, 0x843d71a6 1, 3413, 3413, 23, 260, 0x87fd6b60 1, 3436, 3436, 23, 260, 0x1cc04a39 -0, 3444, 3444, 0, 7220, 0xb926772f +0, 3444, 3444, 111, 7220, 0xb926772f 1, 3459, 3459, 23, 260, 0x9ca24d94 1, 3482, 3482, 23, 260, 0x820a7087 1, 3506, 3506, 23, 260, 0x631166b2 1, 3529, 3529, 23, 260, 0x2f20492a 1, 3552, 3552, 23, 260, 0x932156d0 -0, 3555, 3555, 0, 7326, 0x0a66c632 +0, 3555, 3555, 111, 7326, 0x0a66c632 1, 3575, 3575, 23, 260, 0xdad54c90 1, 3599, 3599, 23, 260, 0xcce84fc9 1, 3622, 3622, 23, 260, 0xba317486 1, 3645, 3645, 23, 260, 0xf5a4626a -0, 3666, 3666, 0, 7225, 0xe39076ab +0, 3666, 3666, 111, 7225, 0xe39076ab 1, 3668, 3668, 23, 260, 0x324669fd 1, 3691, 3691, 23, 260, 0xc7d37113 1, 3715, 3715, 23, 260, 0xc6e0644f 1, 3738, 3738, 23, 260, 0x1b91522e 1, 3761, 3761, 23, 260, 0x9b84667d -0, 3777, 3777, 0, 7265, 0xe0209036 +0, 3777, 3777, 111, 7265, 0xe0209036 1, 3784, 3784, 23, 260, 0xed7e66eb 1, 3808, 3808, 23, 260, 0xaf806d1f 1, 3831, 3831, 23, 260, 0x13a66941 1, 3854, 3854, 23, 260, 0x13095a41 1, 3877, 3877, 23, 260, 0x5ba05491 -0, 3888, 3888, 0, 7337, 0x7a5dc093 +0, 3888, 3888, 111, 7337, 0x7a5dc093 1, 3900, 3900, 23, 260, 0xbf785887 1, 3924, 3924, 23, 260, 0x21965973 1, 3947, 3947, 23, 260, 0xd9aa7134 1, 3970, 3970, 23, 260, 0x3add62bc 1, 3993, 3993, 23, 260, 0xb9626260 -0, 4000, 4000, 0, 7246, 0x519a7a3c +0, 4000, 4000, 111, 7246, 0x519a7a3c 1, 4017, 4017, 23, 260, 0x5b08629f 1, 4040, 4040, 23, 260, 0x43a34659 1, 4063, 4063, 23, 260, 0x68575bda 1, 4086, 4086, 23, 260, 0xd98b715a 1, 4109, 4109, 23, 260, 0x7d816a77 -0, 4111, 4111, 0, 7266, 0x352c8078 +0, 4111, 4111, 111, 7266, 0x352c8078 1, 4133, 4133, 23, 260, 0x16af6ff1 1, 4156, 4156, 23, 260, 0x6d4557a7 1, 4179, 4179, 23, 260, 0x0743401a 1, 4202, 4202, 23, 260, 0x410563d8 -0, 4222, 4222, 0, 7323, 0xcaf69d7c +0, 4222, 4222, 111, 7323, 0xcaf69d7c 1, 4226, 4226, 23, 260, 0x561371d1 1, 4249, 4249, 23, 260, 0x3ef15872 1, 4272, 4272, 23, 260, 0x1dd04972 1, 4295, 4295, 23, 260, 0xed226c62 1, 4318, 4318, 23, 260, 0x20857046 -0, 4333, 4333, 0, 7309, 0x98c1e6f7 +0, 4333, 4333, 111, 7309, 0x98c1e6f7 1, 4342, 4342, 23, 260, 0xed7f4724 1, 4365, 4365, 23, 260, 0x7a7445cf 1, 4388, 4388, 23, 260, 0x06ad6a93 1, 4411, 4411, 23, 260, 0xdd1b6c91 1, 4435, 4435, 23, 260, 0x05b94d27 -0, 4444, 4444, 0, 7121, 0x913d5bd6 +0, 4444, 4444, 111, 7121, 0x913d5bd6 1, 4458, 4458, 23, 260, 0x12cc5062 1, 4481, 4481, 23, 260, 0x44526d0f 1, 4504, 4504, 23, 260, 0xf2ac6d95 diff -Nru ffmpeg-4.2.2/tests/ref/fate/smvjpeg ffmpeg-4.4/tests/ref/fate/smvjpeg --- ffmpeg-4.2.2/tests/ref/fate/smvjpeg 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/smvjpeg 2021-04-08 21:28:40.000000000 +0000 @@ -2,7 +2,7 @@ #media_type 0: video #codec_id 0: rawvideo #dimensions 0: 128x160 -#sar 0: 0/1 +#sar 0: 72/72 0, 0, 0, 1, 30720, 0x3a821807 0, 1, 1, 1, 30720, 0x95168e5d 0, 2, 2, 1, 30720, 0xd4d98e45 diff -Nru ffmpeg-4.2.2/tests/ref/fate/source ffmpeg-4.4/tests/ref/fate/source --- ffmpeg-4.2.2/tests/ref/fate/source 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/source 2020-07-11 10:39:30.000000000 +0000 @@ -1,6 +1,4 @@ Files without standard license headers: -compat/avisynth/windowsPorts/basicDataTypeConversions.h -compat/avisynth/windowsPorts/windows2linux.h libavcodec/file_open.c libavcodec/ilbcdata.h libavcodec/ilbcdec.c @@ -9,6 +7,7 @@ libavcodec/reverse.c libavdevice/file_open.c libavdevice/reverse.c +libavfilter/af_arnndn.c libavfilter/log2_tab.c libavformat/file_open.c libavformat/golomb_tab.c @@ -18,13 +17,6 @@ tools/uncoded_frame.c tools/yuvcmp.c Headers without standard inclusion guards: -compat/avisynth/avisynth_c.h -compat/avisynth/avs/capi.h -compat/avisynth/avs/config.h -compat/avisynth/avs/types.h -compat/avisynth/avxsynth_c.h -compat/avisynth/windowsPorts/basicDataTypeConversions.h -compat/avisynth/windowsPorts/windows2linux.h compat/djgpp/math.h compat/float/float.h compat/float/limits.h diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub2video ffmpeg-4.4/tests/ref/fate/sub2video --- ffmpeg-4.2.2/tests/ref/fate/sub2video 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub2video 2020-07-11 10:39:30.000000000 +0000 @@ -10,7 +10,7 @@ 0, 0, 0, 1, 518400, 0x83c27b82 0, 1, 1, 1, 518400, 0x4051c7f9 0, 2, 2, 1, 518400, 0xfb00e17e -1, 499000, 499000, 4960000, 1015, 0x19e092d2, F=0x0 +1, 499000, 499000, 4960000, 1015, 0x19e092d2 0, 3, 3, 1, 518400, 0x192abb74 0, 4, 4, 1, 518400, 0x4669a88b 0, 5, 5, 1, 518400, 0xaababe00 @@ -58,129 +58,129 @@ 0, 47, 47, 1, 518400, 0xde69683f 0, 48, 48, 1, 518400, 0x7df08fba 0, 49, 49, 1, 518400, 0xbab197ea -1, 15355000, 15355000, 4733000, 2094, 0x3c171425, F=0x0 +1, 15355000, 15355000, 4733000, 2094, 0x3c171425 0, 77, 77, 1, 518400, 0x902285d9 0, 100, 100, 1, 518400, 0xbab197ea -1, 48797000, 48797000, 2560000, 2480, 0x7c0edf21, F=0x0 +1, 48797000, 48797000, 2560000, 2480, 0x7c0edf21 0, 244, 244, 1, 518400, 0x7a11c812 0, 257, 257, 1, 518400, 0xbab197ea -1, 51433000, 51433000, 2366000, 3059, 0xc95b8a05, F=0x0 +1, 51433000, 51433000, 2366000, 3059, 0xc95b8a05 0, 258, 258, 1, 518400, 0x34cdddee 0, 269, 269, 1, 518400, 0xbab197ea -1, 53910000, 53910000, 2696000, 2095, 0x61bb15ed, F=0x0 +1, 53910000, 53910000, 2696000, 2095, 0x61bb15ed 0, 270, 270, 1, 518400, 0x4db4ce51 0, 283, 283, 1, 518400, 0xbab197ea -1, 56663000, 56663000, 1262000, 1013, 0xc9ae89b7, F=0x0 +1, 56663000, 56663000, 1262000, 1013, 0xc9ae89b7 0, 284, 284, 1, 518400, 0xe6bc0ea9 0, 290, 290, 1, 518400, 0xbab197ea -1, 58014000, 58014000, 1661000, 969, 0xe01878f0, F=0x0 +1, 58014000, 58014000, 1661000, 969, 0xe01878f0 0, 291, 291, 1, 518400, 0xa8643af7 0, 298, 298, 1, 518400, 0xbab197ea -1, 67724000, 67724000, 1365000, 844, 0xe7db4fc1, F=0x0 +1, 67724000, 67724000, 1365000, 844, 0xe7db4fc1 0, 339, 339, 1, 518400, 0xb1885c67 0, 345, 345, 1, 518400, 0xbab197ea -1, 69175000, 69175000, 1558000, 802, 0xf48531ba, F=0x0 +1, 69175000, 69175000, 1558000, 802, 0xf48531ba 0, 346, 346, 1, 518400, 0x378e3fd0 0, 354, 354, 1, 518400, 0xbab197ea -1, 70819000, 70819000, 1865000, 1709, 0xb4d5a1bd, F=0x0 +1, 70819000, 70819000, 1865000, 1709, 0xb4d5a1bd 0, 355, 355, 1, 518400, 0xa3782469 0, 363, 363, 1, 518400, 0xbab197ea -1, 72762000, 72762000, 1968000, 2438, 0x99d7bc82, F=0x0 +1, 72762000, 72762000, 1968000, 2438, 0x99d7bc82 0, 364, 364, 1, 518400, 0xba23a0d5 0, 374, 374, 1, 518400, 0xbab197ea -1, 74806000, 74806000, 1831000, 2116, 0x96514097, F=0x0 +1, 74806000, 74806000, 1831000, 2116, 0x96514097 0, 375, 375, 1, 518400, 0x129de2f8 0, 383, 383, 1, 518400, 0xbab197ea -1, 76716000, 76716000, 1262000, 1822, 0xefccc72e, F=0x0 +1, 76716000, 76716000, 1262000, 1822, 0xefccc72e 0, 384, 384, 1, 518400, 0x19772f0f 0, 390, 390, 1, 518400, 0xbab197ea -1, 78051000, 78051000, 1524000, 987, 0x7b927a27, F=0x0 +1, 78051000, 78051000, 1524000, 987, 0x7b927a27 0, 391, 391, 1, 518400, 0x56f54e73 0, 398, 398, 1, 518400, 0xbab197ea -1, 79644000, 79644000, 2662000, 2956, 0x190778f7, F=0x0 +1, 79644000, 79644000, 2662000, 2956, 0x190778f7 0, 399, 399, 1, 518400, 0x300b5247 -1, 82380000, 82380000, 2764000, 3094, 0xc021b7d3, F=0x0 +1, 82380000, 82380000, 2764000, 3094, 0xc021b7d3 0, 412, 412, 1, 518400, 0xbab197ea 0, 413, 413, 1, 518400, 0x6fd028fa 0, 426, 426, 1, 518400, 0xbab197ea -1, 85225000, 85225000, 2366000, 2585, 0x74d0048f, F=0x0 +1, 85225000, 85225000, 2366000, 2585, 0x74d0048f 0, 427, 427, 1, 518400, 0x01f80e9d 0, 438, 438, 1, 518400, 0xbab197ea -1, 87652000, 87652000, 1831000, 634, 0x8832fda1, F=0x0 +1, 87652000, 87652000, 1831000, 634, 0x8832fda1 0, 439, 439, 1, 518400, 0xb48d90c0 0, 447, 447, 1, 518400, 0xbab197ea -1, 91531000, 91531000, 2332000, 2080, 0x97a1146f, F=0x0 +1, 91531000, 91531000, 2332000, 2080, 0x97a1146f 0, 458, 458, 1, 518400, 0xcb5a0173 0, 469, 469, 1, 518400, 0xbab197ea -1, 95510000, 95510000, 3299000, 2964, 0x8b8f6684, F=0x0 +1, 95510000, 95510000, 3299000, 2964, 0x8b8f6684 0, 478, 478, 1, 518400, 0xb8a323e4 0, 494, 494, 1, 518400, 0xbab197ea -1, 98872000, 98872000, 2161000, 1875, 0x9002ef71, F=0x0 +1, 98872000, 98872000, 2161000, 1875, 0x9002ef71 0, 495, 495, 1, 518400, 0xc43518ba 0, 505, 505, 1, 518400, 0xbab197ea -1, 101124000, 101124000, 4096000, 3872, 0x20c6ed9c, F=0x0 +1, 101124000, 101124000, 4096000, 3872, 0x20c6ed9c 0, 506, 506, 1, 518400, 0x04e38692 0, 526, 526, 1, 518400, 0xbab197ea -1, 105303000, 105303000, 2730000, 3094, 0xf203a663, F=0x0 +1, 105303000, 105303000, 2730000, 3094, 0xf203a663 0, 527, 527, 1, 518400, 0x856b0ee5 0, 540, 540, 1, 518400, 0xbab197ea -1, 108106000, 108106000, 2059000, 2404, 0x41a7b429, F=0x0 +1, 108106000, 108106000, 2059000, 2404, 0x41a7b429 0, 541, 541, 1, 518400, 0x3e5beee2 0, 551, 551, 1, 518400, 0xbab197ea -1, 141556000, 141556000, 1661000, 1088, 0xde20aa20, F=0x0 +1, 141556000, 141556000, 1661000, 1088, 0xde20aa20 0, 708, 708, 1, 518400, 0xb8bc1365 0, 716, 716, 1, 518400, 0xbab197ea 0, 817, 817, 1, 518400, 0x83efa32d -1, 163445000, 163445000, 1331000, 339, 0x8bd186ef, F=0x0 +1, 163445000, 163445000, 1331000, 339, 0x8bd186ef 0, 824, 824, 1, 518400, 0xbab197ea 0, 840, 840, 1, 518400, 0x03ea0e90 -1, 168049000, 168049000, 1900000, 1312, 0x0bf20e8d, F=0x0 +1, 168049000, 168049000, 1900000, 1312, 0x0bf20e8d 0, 850, 850, 1, 518400, 0xbab197ea -1, 170035000, 170035000, 1524000, 1279, 0xb6c2dafe, F=0x0 +1, 170035000, 170035000, 1524000, 1279, 0xb6c2dafe 0, 851, 851, 1, 518400, 0x8780239e 0, 858, 858, 1, 518400, 0xbab197ea 0, 861, 861, 1, 518400, 0x6eb72347 -1, 172203000, 172203000, 1695000, 1826, 0x9a1ac769, F=0x0 +1, 172203000, 172203000, 1695000, 1826, 0x9a1ac769 0, 869, 869, 1, 518400, 0xbab197ea -1, 173947000, 173947000, 1934000, 1474, 0xa9b03cdc, F=0x0 +1, 173947000, 173947000, 1934000, 1474, 0xa9b03cdc 0, 870, 870, 1, 518400, 0x9c4a3a3d 0, 879, 879, 1, 518400, 0xbab197ea -1, 175957000, 175957000, 1763000, 1019, 0x20409355, F=0x0 +1, 175957000, 175957000, 1763000, 1019, 0x20409355 0, 880, 880, 1, 518400, 0xc9ebfa89 0, 889, 889, 1, 518400, 0xbab197ea 0, 946, 946, 1, 518400, 0xbaf801ef -1, 189295000, 189295000, 1968000, 1596, 0x408c726e, F=0x0 +1, 189295000, 189295000, 1968000, 1596, 0x408c726e 0, 956, 956, 1, 518400, 0xbab197ea -1, 191356000, 191356000, 1228000, 1517, 0xae8c5c2b, F=0x0 +1, 191356000, 191356000, 1228000, 1517, 0xae8c5c2b 0, 957, 957, 1, 518400, 0x59f4e72f 0, 963, 963, 1, 518400, 0xbab197ea -1, 192640000, 192640000, 1763000, 2506, 0xa458d6d4, F=0x0 +1, 192640000, 192640000, 1763000, 2506, 0xa458d6d4 0, 964, 964, 1, 518400, 0x9d5b9d69 0, 972, 972, 1, 518400, 0xbab197ea -1, 195193000, 195193000, 1092000, 1074, 0x397ba9a8, F=0x0 +1, 195193000, 195193000, 1092000, 1074, 0x397ba9a8 0, 976, 976, 1, 518400, 0x923d1ce7 0, 981, 981, 1, 518400, 0xbab197ea -1, 196361000, 196361000, 1524000, 1715, 0x695ca41e, F=0x0 +1, 196361000, 196361000, 1524000, 1715, 0x695ca41e 0, 982, 982, 1, 518400, 0x6e652cd2 0, 989, 989, 1, 518400, 0xbab197ea -1, 197946000, 197946000, 1160000, 789, 0xc63a189e, F=0x0 +1, 197946000, 197946000, 1160000, 789, 0xc63a189e 0, 990, 990, 1, 518400, 0x25113966 0, 996, 996, 1, 518400, 0xbab197ea -1, 199230000, 199230000, 1627000, 1846, 0xeea8c599, F=0x0 +1, 199230000, 199230000, 1627000, 1846, 0xeea8c599 0, 997, 997, 1, 518400, 0x2dc83609 0, 1004, 1004, 1, 518400, 0xbab197ea -1, 200924000, 200924000, 1763000, 922, 0xd4a87222, F=0x0 +1, 200924000, 200924000, 1763000, 922, 0xd4a87222 0, 1005, 1005, 1, 518400, 0x90483bc6 0, 1013, 1013, 1, 518400, 0xbab197ea 0, 1053, 1053, 1, 518400, 0x3de86ab7 -1, 210600000, 210600000, 1831000, 665, 0x55580135, F=0x0 +1, 210600000, 210600000, 1831000, 665, 0x55580135 0, 1062, 1062, 1, 518400, 0xbab197ea -1, 214771000, 214771000, 1558000, 1216, 0x50d1f6c5, F=0x0 +1, 214771000, 214771000, 1558000, 1216, 0x50d1f6c5 0, 1074, 1074, 1, 518400, 0x8c320e68 0, 1082, 1082, 1, 518400, 0xbab197ea 0, 1128, 1128, 1, 518400, 0x81e977b2 -1, 225640000, 225640000, 2127000, 2133, 0x670c11a5, F=0x0 +1, 225640000, 225640000, 2127000, 2133, 0x670c11a5 0, 1139, 1139, 1, 518400, 0xbab197ea -1, 227834000, 227834000, 1262000, 1264, 0xc1d9fc57, F=0x0 +1, 227834000, 227834000, 1262000, 1264, 0xc1d9fc57 0, 1140, 1140, 1, 518400, 0xb046dd30 0, 1145, 1145, 1, 518400, 0xbab197ea diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub2video_basic ffmpeg-4.4/tests/ref/fate/sub2video_basic --- ffmpeg-4.2.2/tests/ref/fate/sub2video_basic 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub2video_basic 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,95 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 720x480 +#sar 0: 0/1 +0, 3312, 3312, 1, 1382400, 0x00000000 +0, 3312, 3312, 1, 1382400, 0x8c93c2ba +0, 3436, 3436, 1, 1382400, 0x00000000 +0, 3684, 3684, 1, 1382400, 0xb02e32ca +0, 3802, 3802, 1, 1382400, 0x00000000 +0, 4520, 4520, 1, 1382400, 0x83b71116 +0, 4584, 4584, 1, 1382400, 0x00000000 +0, 4586, 4586, 1, 1382400, 0x85547fd1 +0, 4645, 4645, 1, 1382400, 0x00000000 +0, 4648, 4648, 1, 1382400, 0x00000000 +0, 4648, 4648, 1, 1382400, 0xb6a8f181 +0, 4715, 4715, 1, 1382400, 0x00000000 +0, 4717, 4717, 1, 1382400, 0xb64d1a2c +0, 4748, 4748, 1, 1382400, 0x00000000 +0, 4750, 4750, 1, 1382400, 0x7b37ecf3 +0, 4792, 4792, 1, 1382400, 0x00000000 +0, 4993, 4993, 1, 1382400, 0xdc025bd1 +0, 5027, 5027, 1, 1382400, 0x00000000 +0, 5029, 5029, 1, 1382400, 0x688b294d +0, 5068, 5068, 1, 1382400, 0x00000000 +0, 5070, 5070, 1, 1382400, 0xa2b33d1b +0, 5117, 5117, 1, 1382400, 0x00000000 +0, 5119, 5119, 1, 1382400, 0xb3e525e3 +0, 5168, 5168, 1, 1382400, 0x00000000 +0, 5170, 5170, 1, 1382400, 0xaa8fbdd7 +0, 5216, 5216, 1, 1382400, 0x00000000 +0, 5218, 5218, 1, 1382400, 0x7b7f26dd +0, 5249, 5249, 1, 1382400, 0x00000000 +0, 5251, 5251, 1, 1382400, 0x15e2f836 +0, 5289, 5289, 1, 1382400, 0x00000000 +0, 5291, 5291, 1, 1382400, 0x0fee9b0c +0, 5358, 5358, 1, 1382400, 0x00000000 +0, 5360, 5360, 1, 1382400, 0x89d62791 +0, 5429, 5429, 1, 1382400, 0x00000000 +0, 5431, 5431, 1, 1382400, 0xa6a9fd74 +0, 5490, 5490, 1, 1382400, 0x00000000 +0, 5491, 5491, 1, 1382400, 0x7896178d +0, 5537, 5537, 1, 1382400, 0x00000000 +0, 5588, 5588, 1, 1382400, 0x01751a52 +0, 5647, 5647, 1, 1382400, 0x00000000 +0, 5688, 5688, 1, 1382400, 0xa3959c6f +0, 5770, 5770, 1, 1382400, 0x00000000 +0, 5772, 5772, 1, 1382400, 0x3d3ea47b +0, 5826, 5826, 1, 1382400, 0x00000000 +0, 5828, 5828, 1, 1382400, 0x593f8b24 +0, 5931, 5931, 1, 1382400, 0x00000000 +0, 5933, 5933, 1, 1382400, 0x171f05ba +0, 6001, 6001, 1, 1382400, 0x00000000 +0, 6003, 6003, 1, 1382400, 0xb014cdf1 +0, 6054, 6054, 1, 1382400, 0x00000000 +0, 6839, 6839, 1, 1382400, 0xd918e667 +0, 6880, 6880, 1, 1382400, 0x00000000 +0, 7386, 7386, 1, 1382400, 0xc9406331 +0, 7419, 7419, 1, 1382400, 0x00000000 +0, 7501, 7501, 1, 1382400, 0xaf08b10d +0, 7549, 7549, 1, 1382400, 0x00000000 +0, 7551, 7551, 1, 1382400, 0x00000000 +0, 7551, 7551, 1, 1382400, 0x853a9d93 +0, 7589, 7589, 1, 1382400, 0x00000000 +0, 7605, 7605, 1, 1382400, 0x7491a87d +0, 7647, 7647, 1, 1382400, 0x00000000 +0, 7649, 7649, 1, 1382400, 0xf7383c58 +0, 7697, 7697, 1, 1382400, 0x00000000 +0, 7699, 7699, 1, 1382400, 0xe66be411 +0, 7743, 7743, 1, 1382400, 0x00000000 +0, 8032, 8032, 1, 1382400, 0xd6850362 +0, 8082, 8082, 1, 1382400, 0x00000000 +0, 8084, 8084, 1, 1382400, 0x3e1ed109 +0, 8115, 8115, 1, 1382400, 0x00000000 +0, 8116, 8116, 1, 1382400, 0x39c1b7bd +0, 8160, 8160, 1, 1382400, 0x00000000 +0, 8180, 8180, 1, 1382400, 0x35b85f2e +0, 8207, 8207, 1, 1382400, 0x00000000 +0, 8209, 8209, 1, 1382400, 0x00000000 +0, 8209, 8209, 1, 1382400, 0x83f103e5 +0, 8247, 8247, 1, 1382400, 0x00000000 +0, 8249, 8249, 1, 1382400, 0xbc1ca9b3 +0, 8278, 8278, 1, 1382400, 0x00000000 +0, 8281, 8281, 1, 1382400, 0x94d4a51e +0, 8321, 8321, 1, 1382400, 0x00000000 +0, 8323, 8323, 1, 1382400, 0xf88cdfde +0, 8367, 8367, 1, 1382400, 0x00000000 +0, 8565, 8565, 1, 1382400, 0xdd51423b +0, 8611, 8611, 1, 1382400, 0x00000000 +0, 8669, 8669, 1, 1382400, 0x08259fa4 +0, 8708, 8708, 1, 1382400, 0x00000000 +0, 8941, 8941, 1, 1382400, 0x1663fa34 +0, 8994, 8994, 1, 1382400, 0x00000000 +0, 8996, 8996, 1, 1382400, 0xda2ceb55 +0, 9027, 9027, 1, 1382400, 0x00000000 diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub2video_time_limited ffmpeg-4.4/tests/ref/fate/sub2video_time_limited --- ffmpeg-4.2.2/tests/ref/fate/sub2video_time_limited 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub2video_time_limited 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,8 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 1920x1080 +#sar 0: 0/1 +0, 2, 2, 1, 8294400, 0x00000000 +0, 2, 2, 1, 8294400, 0xa87c518f +0, 10, 10, 1, 8294400, 0xa87c518f diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-aqtitle ffmpeg-4.4/tests/ref/fate/sub-aqtitle --- ffmpeg-4.2.2/tests/ref/fate/sub-aqtitle 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-aqtitle 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-cc ffmpeg-4.4/tests/ref/fate/sub-cc --- ffmpeg-4.2.2/tests/ref/fate/sub-cc 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-cc 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-cc-realtime ffmpeg-4.4/tests/ref/fate/sub-cc-realtime --- ffmpeg-4.2.2/tests/ref/fate/sub-cc-realtime 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-cc-realtime 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-cc-scte20 ffmpeg-4.4/tests/ref/fate/sub-cc-scte20 --- ffmpeg-4.2.2/tests/ref/fate/sub-cc-scte20 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-cc-scte20 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-charenc ffmpeg-4.4/tests/ref/fate/sub-charenc --- ffmpeg-4.2.2/tests/ref/fate/sub-charenc 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-charenc 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-dvb ffmpeg-4.4/tests/ref/fate/sub-dvb --- ffmpeg-4.2.2/tests/ref/fate/sub-dvb 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-dvb 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,75 @@ +#tb 0: 1/1000000 +#media_type 0: subtitle +#codec_id 0: dvb_subtitle +0, 15600000, 15600000, 159000, 1168, 0xd0f89d82 +0, 15759000, 15759000, 159000, 14, 0x064900eb +0, 15760000, 15760000, 239000, 1544, 0xe60f1751 +0, 15999000, 15999000, 239000, 14, 0x0729010b +0, 16000000, 16000000, 339000, 1658, 0xbe343093 +0, 16339000, 16339000, 339000, 14, 0x0809012b +0, 16340000, 16340000, 599000, 2343, 0xc68f07ef +0, 16939000, 16939000, 599000, 14, 0x08e9014b +0, 16940000, 16940000, 459000, 2568, 0x0ee657b1 +0, 17399000, 17399000, 459000, 14, 0x09c9016b +0, 17400000, 17400000, 359000, 3422, 0xba5b63ce +0, 17759000, 17759000, 359000, 14, 0x0aa9018b +0, 17760000, 17760000, 219000, 5078, 0x95b19902 +0, 17979000, 17979000, 219000, 14, 0x0b8901ab +0, 17980000, 17980000, 959000, 5808, 0xc9717b89 +0, 18939000, 18939000, 959000, 14, 0x0c6901cb +0, 18940000, 18940000, 219000, 6015, 0x0becbfac +0, 19159000, 19159000, 219000, 14, 0x064900eb +0, 19160000, 19160000, 259000, 6519, 0xfcd24d26 +0, 19419000, 19419000, 259000, 14, 0x0729010b +0, 19420000, 19420000, 99000, 7061, 0xf0320408 +0, 19519000, 19519000, 99000, 14, 0x0809012b +0, 19520000, 19520000, 219000, 4773, 0x66c93074 +0, 19739000, 19739000, 219000, 14, 0x08e9014b +0, 19740000, 19740000, 219000, 5546, 0x06052c81 +0, 19959000, 19959000, 219000, 14, 0x09c9016b +0, 19960000, 19960000, 239000, 5754, 0x904f7325 +0, 20199000, 20199000, 239000, 14, 0x0aa9018b +0, 20200000, 20200000, 139000, 6099, 0xe30cde07 +0, 20339000, 20339000, 139000, 14, 0x0b8901ab +0, 20340000, 20340000, 799000, 6839, 0x770fcb6c +0, 21139000, 21139000, 799000, 14, 0x0c6901cb +0, 21140000, 21140000, 239000, 4744, 0xa91e1b41 +0, 21379000, 21379000, 239000, 14, 0x064900eb +0, 21380000, 21380000, 339000, 5824, 0xcf6d782b +0, 21719000, 21719000, 339000, 14, 0x0729010b +0, 21720000, 21720000, 1439000, 6212, 0xabf8f7cf +0, 23159000, 23159000, 1439000, 14, 0x0809012b +0, 23160000, 23160000, 1319000, 7082, 0xd7ca10f2 +0, 24479000, 24479000, 1319000, 14, 0x08e9014b +0, 24480000, 24480000, 219000, 5345, 0x12b2cae0 +0, 24699000, 24699000, 219000, 14, 0x09c9016b +0, 24700000, 24700000, 219000, 5765, 0xc7d46192 +0, 24919000, 24919000, 219000, 14, 0x0aa9018b +0, 24920000, 24920000, 599000, 6557, 0xcb995d30 +0, 25519000, 25519000, 599000, 14, 0x0b8901ab +0, 25520000, 25520000, 219000, 7091, 0xe6ea0559 +0, 25739000, 25739000, 219000, 14, 0x0c6901cb +0, 25740000, 25740000, 239000, 7305, 0xb66c404e +0, 25979000, 25979000, 239000, 14, 0x064900eb +0, 25980000, 25980000, 359000, 7590, 0x0cc2a481 +0, 26339000, 26339000, 359000, 14, 0x0729010b +0, 26340000, 26340000, 219000, 4629, 0xe18cfea8 +0, 26559000, 26559000, 219000, 14, 0x0809012b +0, 26560000, 26560000, 719000, 4785, 0x82043fc0 +0, 27279000, 27279000, 719000, 14, 0x08e9014b +0, 27280000, 27280000, 459000, 6061, 0xbde7d245 +0, 27739000, 27739000, 459000, 14, 0x09c9016b +0, 27740000, 27740000, 239000, 6301, 0x92d01a51 +0, 27979000, 27979000, 239000, 14, 0x0aa9018b +0, 27980000, 27980000, 99000, 6736, 0xbd25a134 +0, 28079000, 28079000, 99000, 14, 0x0b8901ab +0, 28080000, 28080000, 219000, 7214, 0x7ef93c13 +0, 28299000, 28299000, 219000, 14, 0x0c6901cb +0, 28300000, 28300000, 239000, 7366, 0x5bed7fcd +0, 28539000, 28539000, 239000, 14, 0x064900eb +0, 28540000, 28540000, 599000, 4564, 0x7f4c014b +0, 29139000, 29139000, 599000, 14, 0x0729010b +0, 29140000, 29140000, 219000, 4637, 0x682626b7 +0, 29359000, 29359000, 219000, 14, 0x0809012b +0, 29360000, 29360000, 1679000, 5358, 0x29e30c48 +0, 31039000, 31039000, 1679000, 14, 0x08e9014b diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-jacosub ffmpeg-4.4/tests/ref/fate/sub-jacosub --- ffmpeg-4.2.2/tests/ref/fate/sub-jacosub 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-jacosub 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-microdvd ffmpeg-4.4/tests/ref/fate/sub-microdvd --- ffmpeg-4.2.2/tests/ref/fate/sub-microdvd 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-microdvd 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding Binary files /tmp/tmpyldaobvy/Ij2zYBKrQi/ffmpeg-4.2.2/tests/ref/fate/sub-microdvd-remux and /tmp/tmpyldaobvy/lFTJZ9mq3G/ffmpeg-4.4/tests/ref/fate/sub-microdvd-remux differ diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-movtext ffmpeg-4.4/tests/ref/fate/sub-movtext --- ffmpeg-4.2.2/tests/ref/fate/sub-movtext 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-movtext 2020-07-11 10:39:30.000000000 +0000 @@ -3,10 +3,11 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding -Style: Default,Serif,18,&Hffffff,&Hffffff,&H0,&H0,0,0,0,0,100,100,0,0,1,1,0,2,10,10,10,0 +Style: Default,Serif,18,&Hffffff,&Hffffff,&Hff000000,&Hff000000,0,0,0,0,100,100,0,0,1,1,0,2,10,10,10,0 [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-mpl2 ffmpeg-4.4/tests/ref/fate/sub-mpl2 --- ffmpeg-4.2.2/tests/ref/fate/sub-mpl2 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-mpl2 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-mpsub ffmpeg-4.4/tests/ref/fate/sub-mpsub --- ffmpeg-4.2.2/tests/ref/fate/sub-mpsub 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-mpsub 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-mpsub-frames ffmpeg-4.4/tests/ref/fate/sub-mpsub-frames --- ffmpeg-4.2.2/tests/ref/fate/sub-mpsub-frames 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-mpsub-frames 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding @@ -10,5 +11,5 @@ [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text -Dialogue: 0,0:00:01.00,0:00:02.48,Default,,0,0,0,,Start at 1sec,\Nlast 1.5 seconds -Dialogue: 0,0:00:02.52,0:00:11.52,Default,,0,0,0,,One frame later,\Nduring 9 seconds +Dialogue: 0,0:00:01.00,0:00:02.50,Default,,0,0,0,,Start at 1sec,\Nlast 1.5 seconds +Dialogue: 0,0:00:02.54,0:00:11.54,Default,,0,0,0,,One frame later,\Nduring 9 seconds diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-pjs ffmpeg-4.4/tests/ref/fate/sub-pjs --- ffmpeg-4.2.2/tests/ref/fate/sub-pjs 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-pjs 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-realtext ffmpeg-4.4/tests/ref/fate/sub-realtext --- ffmpeg-4.2.2/tests/ref/fate/sub-realtext 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-realtext 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-sami ffmpeg-4.4/tests/ref/fate/sub-sami --- ffmpeg-4.2.2/tests/ref/fate/sub-sami 2018-07-17 09:27:43.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-sami 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-sami2 ffmpeg-4.4/tests/ref/fate/sub-sami2 --- ffmpeg-4.2.2/tests/ref/fate/sub-sami2 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-sami2 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-scc ffmpeg-4.4/tests/ref/fate/sub-scc --- ffmpeg-4.2.2/tests/ref/fate/sub-scc 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-scc 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-srt ffmpeg-4.4/tests/ref/fate/sub-srt --- ffmpeg-4.2.2/tests/ref/fate/sub-srt 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-srt 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-srt-badsyntax ffmpeg-4.4/tests/ref/fate/sub-srt-badsyntax --- ffmpeg-4.2.2/tests/ref/fate/sub-srt-badsyntax 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-srt-badsyntax 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-stl ffmpeg-4.4/tests/ref/fate/sub-stl --- ffmpeg-4.2.2/tests/ref/fate/sub-stl 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-stl 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-subviewer ffmpeg-4.4/tests/ref/fate/sub-subviewer --- ffmpeg-4.2.2/tests/ref/fate/sub-subviewer 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-subviewer 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-subviewer1 ffmpeg-4.4/tests/ref/fate/sub-subviewer1 --- ffmpeg-4.2.2/tests/ref/fate/sub-subviewer1 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-subviewer1 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-ttmlenc ffmpeg-4.4/tests/ref/fate/sub-ttmlenc --- ffmpeg-4.2.2/tests/ref/fate/sub-ttmlenc 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-ttmlenc 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,122 @@ + + + +
+

Don't show this text it may be used to insert hidden data

+

SubRip subtitles capability tester 1.3o by ale5000
Use VLC 1.1 or higher as reference for most things and MPC Home Cinema for others
This text should be blue
This text should be red
This text should be black
If you see this with the normal font, the player don't (fully) support font face

+

Hidden

+

This text should be small
This text should be normal
This text should be big

+

This should be an E with an accent: È
日本語
This text should be bold, italics and underline
This text should be small and green
This text should be small and red
This text should be big and brown

+

This line should be bold
This line should be italics
This line should be underline
This line should be strikethrough
Both lines
should be underline

+

>
It would be a good thing to
hide invalid html tags that are closed and show the text in them
but show un-closed invalid html tags
Show not opened tags
<

+

and also
hide invalid html tags with parameters that are closed and show the text in them
but show un-closed invalid html tags
This text should be showed underlined without problems also: 2<3,5>1,4<6
This shouldn't be underlined

+

This text should be in the normal position...

+

This text should NOT be in the normal position

+

Implementation is the same of the ASS tag
This text should be at the
top and horizontally centered

+

This text should be at the
middle and horizontally centered

+

This text should be at the
bottom and horizontally centered

+

This text should be at the
top and horizontally at the left

+

This text should be at the
middle and horizontally at the left
(The second position must be ignored)

+

This text should be at the
bottom and horizontally at the left

+

This text should be at the
top and horizontally at the right

+

This text should be at the
middle and horizontally at the right

+

This text should be at the
bottom and horizontally at the right

+

This could be the most difficult thing to implement

+

First text

+

Second, it shouldn't overlap first

+

Third, it should replace second

+

Fourth, it shouldn't overlap first and third

+

Fifth, it should replace third

+

Sixth, it shouldn't be
showed overlapped

+

TEXT 1 (bottom)

+

text 2

+

Hide these tags:
also hide these tags:
but show this: {normal text}

+


\ N is a forced line break
\ h is a hard space
Normal spaces at the start and at the end of the line are trimmed while hard spaces are not trimmed.
The\hline\hwill\hnever\hbreak\hautomatically\hright\hbefore\hor\hafter\ha\hhard\hspace.\h:-D

+


\h\h\h\h\hA (05 hard spaces followed by a letter)
A (Normal spaces followed by a letter)
A (No hard spaces followed by a letter)

+

\h\h\h\h\hA (05 hard spaces followed by a letter)
A (Normal spaces followed by a letter)
A (No hard spaces followed by a letter)
Show this: \TEST and this: \-)

+


A letter followed by 05 hard spaces: A\h\h\h\h\h
A letter followed by normal spaces: A
A letter followed by no hard spaces: A
05 hard spaces between letters: A\h\h\h\h\hA
5 normal spaces between letters: A A

^--Forced line break

+

Both line should be strikethrough,
yes.
Correctly closed tags
should be hidden.

+

It shouldn't be strikethrough,
not opened tag showed as text.
Not opened tag showed as text.

+

Three lines should be strikethrough,
yes.
Not closed tags showed as text

+

Both line should be strikethrough but
the wrong closing tag should be showed

+
+ +
diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-vplayer ffmpeg-4.4/tests/ref/fate/sub-vplayer --- ffmpeg-4.2.2/tests/ref/fate/sub-vplayer 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-vplayer 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-webvtt ffmpeg-4.4/tests/ref/fate/sub-webvtt --- ffmpeg-4.2.2/tests/ref/fate/sub-webvtt 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-webvtt 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sub-webvtt2 ffmpeg-4.4/tests/ref/fate/sub-webvtt2 --- ffmpeg-4.2.2/tests/ref/fate/sub-webvtt2 2018-07-17 09:27:43.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sub-webvtt2 2020-07-11 10:39:30.000000000 +0000 @@ -3,6 +3,7 @@ ScriptType: v4.00+ PlayResX: 384 PlayResY: 288 +ScaledBorderAndShadow: yes [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding diff -Nru ffmpeg-4.2.2/tests/ref/fate/sws-floatimg-cmp ffmpeg-4.4/tests/ref/fate/sws-floatimg-cmp --- ffmpeg-4.2.2/tests/ref/fate/sws-floatimg-cmp 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sws-floatimg-cmp 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,120 @@ +gbrpf32le -> yuv444p16le -> gbrpf32le +avg diff: 0.000125 +min diff: 0.000000 +max diff: 0.000501 +gbrpf32le -> yuv444p -> gbrpf32le +avg diff: 0.001804 +min diff: 0.000000 +max diff: 0.006399 +gbrpf32le -> yuv444p9le -> gbrpf32le +avg diff: 0.000906 +min diff: 0.000000 +max diff: 0.003313 +gbrpf32le -> yuv444p10le -> gbrpf32le +avg diff: 0.000467 +min diff: 0.000000 +max diff: 0.001912 +gbrpf32le -> yuv444p12le -> gbrpf32le +avg diff: 0.000166 +min diff: 0.000000 +max diff: 0.000802 +gbrpf32le -> yuv444p14le -> gbrpf32le +avg diff: 0.000127 +min diff: 0.000000 +max diff: 0.000524 +gbrpf32le -> rgb24 -> gbrpf32le +avg diff: 0.001011 +min diff: 0.000000 +max diff: 0.004229 +gbrpf32le -> bgr24 -> gbrpf32le +avg diff: 0.001011 +min diff: 0.000000 +max diff: 0.004229 +gbrpf32le -> rgba -> gbrpf32le +avg diff: 0.001011 +min diff: 0.000000 +max diff: 0.004229 +gbrpf32le -> bgra -> gbrpf32le +avg diff: 0.001011 +min diff: 0.000000 +max diff: 0.004229 +gbrpf32le -> argb -> gbrpf32le +avg diff: 0.001011 +min diff: 0.000000 +max diff: 0.004229 +gbrpf32le -> abgr -> gbrpf32le +avg diff: 0.001011 +min diff: 0.000000 +max diff: 0.004229 +gbrpf32le -> 0rgb -> gbrpf32le +avg diff: 0.001011 +min diff: 0.000000 +max diff: 0.004229 +gbrpf32le -> 0bgr -> gbrpf32le +avg diff: 0.001011 +min diff: 0.000000 +max diff: 0.004229 +gbrpf32le -> rgb0 -> gbrpf32le +avg diff: 0.001011 +min diff: 0.000000 +max diff: 0.004229 +gbrpf32le -> bgr0 -> gbrpf32le +avg diff: 0.001011 +min diff: 0.000000 +max diff: 0.004229 +gbrpf32le -> rgb48le -> gbrpf32le +avg diff: 0.000249 +min diff: 0.000000 +max diff: 0.000990 +gbrpf32le -> bgr48le -> gbrpf32le +avg diff: 0.000249 +min diff: 0.000000 +max diff: 0.000990 +gbrpf32le -> rgba64le -> gbrpf32le +avg diff: 0.000249 +min diff: 0.000000 +max diff: 0.000990 +gbrpf32le -> bgra64le -> gbrpf32le +avg diff: 0.000249 +min diff: 0.000000 +max diff: 0.000990 +gbrpf32le -> gbrp -> gbrpf32le +avg diff: 0.001011 +min diff: 0.000000 +max diff: 0.004229 +gbrpf32le -> gbrap -> gbrpf32le +avg diff: 0.001011 +min diff: 0.000000 +max diff: 0.004229 +gbrpf32le -> gbrp9le -> gbrpf32le +avg diff: 0.000545 +min diff: 0.000000 +max diff: 0.002245 +gbrpf32le -> gbrp10le -> gbrpf32le +avg diff: 0.000350 +min diff: 0.000000 +max diff: 0.001475 +gbrpf32le -> gbrap10le -> gbrpf32le +avg diff: 0.000350 +min diff: 0.000000 +max diff: 0.001475 +gbrpf32le -> gbrp12le -> gbrpf32le +avg diff: 0.000260 +min diff: 0.000000 +max diff: 0.001135 +gbrpf32le -> gbrap12le -> gbrpf32le +avg diff: 0.000260 +min diff: 0.000000 +max diff: 0.001135 +gbrpf32le -> gbrp14le -> gbrpf32le +avg diff: 0.000253 +min diff: 0.000000 +max diff: 0.001068 +gbrpf32le -> gbrp16le -> gbrpf32le +avg diff: 0.000249 +min diff: 0.000000 +max diff: 0.000990 +gbrpf32le -> gbrap16le -> gbrpf32le +avg diff: 0.000249 +min diff: 0.000000 +max diff: 0.000990 diff -Nru ffmpeg-4.2.2/tests/ref/fate/sws-pixdesc-query ffmpeg-4.4/tests/ref/fate/sws-pixdesc-query --- ffmpeg-4.2.2/tests/ref/fate/sws-pixdesc-query 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/sws-pixdesc-query 2021-04-08 21:28:40.000000000 +0000 @@ -57,8 +57,12 @@ nv20le p010be p010le + x2rgb10be + x2rgb10le xyz12be xyz12le + y210be + y210le yuv420p10be yuv420p10le yuv420p12be @@ -139,7 +143,9 @@ rgb555be rgb565be rgba64be + x2rgb10be xyz12be + y210be ya16be yuv420p10be yuv420p12be @@ -188,6 +194,8 @@ uyyvyy411 xyz12be xyz12le + y210be + y210le ya16be ya16le ya8 @@ -431,6 +439,8 @@ rgb8 rgba64be rgba64le + x2rgb10be + x2rgb10le Gray: gray @@ -577,6 +587,8 @@ rgb8 rgba64be rgba64le + x2rgb10be + x2rgb10le ALPHA: ayuv64be @@ -684,8 +696,12 @@ rgba64le uyvy422 uyyvyy411 + x2rgb10be + x2rgb10le xyz12be xyz12le + y210be + y210le ya16be ya16le ya8 @@ -846,6 +862,8 @@ rgb8 rgba64be rgba64le + x2rgb10be + x2rgb10le PlanarRGB: gbrap diff -Nru ffmpeg-4.2.2/tests/ref/fate/time_base ffmpeg-4.4/tests/ref/fate/time_base --- ffmpeg-4.2.2/tests/ref/fate/time_base 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/time_base 2021-04-08 21:28:40.000000000 +0000 @@ -1 +1 @@ -42863a53f6c63efbc8c5a2eb76f13f5f +78ac0348027b75d73acb8bea14e67a59 diff -Nru ffmpeg-4.2.2/tests/ref/fate/ts-demux ffmpeg-4.4/tests/ref/fate/ts-demux --- ffmpeg-4.2.2/tests/ref/fate/ts-demux 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/ts-demux 2020-07-11 10:39:30.000000000 +0000 @@ -15,7 +15,7 @@ 1, 5760, 5760, 2880, 1536, 0xbab5129c 1, 8640, 8640, 2880, 1536, 0x602f034b, S=1, 1, 0x00bd00bd 1, 11520, 11520, 2880, 906, 0x69cdcbcd -0, 32037, 36541, 1501, 114336, 0x37a215a8, S=1, 1, 0x00e000e0 +0, 32037, 36541, 1501, 114336, 0x37a215a8, S=2, 1, 0x00e000e0, 24, 0x663d0b52 0, 33538, 33538, 1501, 12560, 0xb559a3d4, F=0x0, S=1, 1, 0x00e000e0 0, 35040, 35040, 1501, 12704, 0x2614adf4, F=0x0, S=1, 1, 0x00e000e0 0, 36541, 41046, 1501, 51976, 0x9ff1dbfe, F=0x0, S=1, 1, 0x00e000e0 diff -Nru ffmpeg-4.2.2/tests/ref/fate/unknown_layout-ac3 ffmpeg-4.4/tests/ref/fate/unknown_layout-ac3 --- ffmpeg-4.2.2/tests/ref/fate/unknown_layout-ac3 2016-03-29 02:25:35.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/unknown_layout-ac3 2021-04-08 21:28:40.000000000 +0000 @@ -1 +1 @@ -bbb7550d6d93973c10f4ee13c87cf799 +febdb165cfd6cba375aa086195e61213 diff -Nru ffmpeg-4.2.2/tests/ref/fate/url ffmpeg-4.4/tests/ref/fate/url --- ffmpeg-4.2.2/tests/ref/fate/url 2016-03-29 02:25:35.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/url 2021-04-08 21:28:27.000000000 +0000 @@ -1,13 +1,153 @@ -baz -/foo/baz -/baz -/baz -http://server/foo/baz -http://server/foo/baz -http://server/baz -http://server/baz -http://server/baz -https://other/url -http://server/baz -http://server/foo/bar?someparam -http://other/url +Testing ff_url_decompose: + +http://user:pass@ffmpeg:8080/dir/file?query#fragment => + scheme: http: + authority: // + userinfo: user:pass@ + host: ffmpeg + port: :8080 + path: /dir/file + query: ?query + fragment: #fragment + +http://ffmpeg/dir/file => + scheme: http: + authority: // + host: ffmpeg + path: /dir/file + +file:///dev/null => + scheme: file: + authority: // + path: /dev/null + +file:/dev/null => + scheme: file: + path: /dev/null + +http://[::1]/dev/null => + scheme: http: + authority: // + host: [::1] + path: /dev/null + +http://[::1]:8080/dev/null => + scheme: http: + authority: // + host: [::1] + port: :8080 + path: /dev/null + +//ffmpeg/dev/null => + authority: // + host: ffmpeg + path: /dev/null + +test?url=http://server/path => + path: test + query: ?url=http://server/path + +dummy.mp4#t=0:02:00,121.5 => + path: dummy.mp4 + fragment: #t=0:02:00,121.5 + +Testing ff_make_absolute_url: + (null) baz => baz + /foo/bar baz => /foo/baz + /foo/bar ../baz => /foo/../baz + /foo/bar /baz => /baz + /foo/bar ../../../baz => /foo/../../../baz + http://server/foo/ baz => http://server/foo/baz + http://server/foo/bar baz => http://server/foo/baz + http://server/foo/ ../baz => http://server/baz + http://server/foo/bar/123 ../../baz => http://server/baz + http://server/foo/bar/123 /baz => http://server/baz + http://server/foo/bar/123 https://other/url => https://other/url + http://server/foo/bar?param=value/with/slashes /baz => http://server/baz + http://server/foo/bar?param&otherparam ?someparam => http://server/foo/bar?someparam + http://server/foo/bar //other/url => http://other/url + http://server/foo/bar ../../../../../other/url => http://server/other/url + http://server/foo/bar /../../../../../other/url => http://server/other/url + http://server/foo/bar /test/../../../../../other/url => http://server/other/url + http://server/foo/bar /test/../../test/../../../other/url => http://server/other/url + http://server/foo/bar file:../baz/qux => file:../baz/qux + http://server/foo//bar/ ../../ => http://server/foo/ + file:../tmp/foo ../bar/ => file:../tmp/../bar/ + file:../tmp/foo file:../bar/ => file:../bar/ + http://server/foo/bar ./ => http://server/foo/ + http://server/foo/bar .dotfile => http://server/foo/.dotfile + http://server/foo/bar ..doubledotfile => http://server/foo/..doubledotfile + http://server/foo/bar double..dotfile => http://server/foo/double..dotfile + http://server/foo/bar doubledotfile.. => http://server/foo/doubledotfile.. + file1 file2 => file2 + dir/file1 file2 => dir/file2 + dir/file1 ../file2 => dir/../file2 + dir\file1 file2 => file2 + dir\file1 file2 DOS dir\file2 + \\srv\shr\file ..\..\dummy => ..\..\dummy + \\srv\shr\file ..\..\dummy DOS \\srv\shr\..\..\dummy + \\srv\shr\file dummy => dummy + \\srv\shr\file dummy DOS \\srv\shr\dummy + \\srv\shr\file \\srv2\shr2\file2 => \\srv2\shr2\file2 + \\srv\shr\file d:/file => d:/file + C:\dir\a ..\file => C:..\file + C:\dir\a ..\file DOS C:\dir\..\file + C:\dir\a \\srv\shr\file => C:\\srv\shr\file + C:\dir\a \\srv\shr\file DOS \\srv\shr\file + C:\dir\a d:\file => d:\file + http://a/b \\srv\shr\file => http://a/\\srv\shr\file + http://a/b //srv/shr/file => http://srv/shr/file + http://a/b d:\file => d:\file + http://a/b C:/file => C:/file + http://a/b/c/d;p?q g:h => g:h + http://a/b/c/d;p?q g => http://a/b/c/g + http://a/b/c/d;p?q ./g => http://a/b/c/g + http://a/b/c/d;p?q g/ => http://a/b/c/g/ + http://a/b/c/d;p?q /g => http://a/g + http://a/b/c/d;p?q //g => http://g + http://a/b/c/d;p?q ?y => http://a/b/c/d;p?y + http://a/b/c/d;p?q g?y => http://a/b/c/g?y + http://a/b/c/d;p?q #s => http://a/b/c/d;p?q#s + http://a/b/c/d;p?q g#s => http://a/b/c/g#s + http://a/b/c/d;p?q g?y#s => http://a/b/c/g?y#s + http://a/b/c/d;p?q ;x => http://a/b/c/;x + http://a/b/c/d;p?q g;x => http://a/b/c/g;x + http://a/b/c/d;p?q g;x?y#s => http://a/b/c/g;x?y#s + http://a/b/c/d;p?q => http://a/b/c/d;p?q + http://a/b/c/d;p?q . => http://a/b/c/ + http://a/b/c/d;p?q ./ => http://a/b/c/ + http://a/b/c/d;p?q .. => http://a/b/ + http://a/b/c/d;p?q ../ => http://a/b/ + http://a/b/c/d;p?q ../g => http://a/b/g + http://a/b/c/d;p?q ../.. => http://a/ + http://a/b/c/d;p?q ../../ => http://a/ + http://a/b/c/d;p?q ../../g => http://a/g + http://a/b/c/d;p?q ../../../g => http://a/g + http://a/b/c/d;p?q ../../../../g => http://a/g + http://a/b/c/d;p?q /./g => http://a/g + http://a/b/c/d;p?q /../g => http://a/g + http://a/b/c/d;p?q g. => http://a/b/c/g. + http://a/b/c/d;p?q .g => http://a/b/c/.g + http://a/b/c/d;p?q g.. => http://a/b/c/g.. + http://a/b/c/d;p?q ..g => http://a/b/c/..g + http://a/b/c/d;p?q ./../g => http://a/b/g + http://a/b/c/d;p?q ./g/. => http://a/b/c/g/ + http://a/b/c/d;p?q g/./h => http://a/b/c/g/h + http://a/b/c/d;p?q g/../h => http://a/b/c/h + http://a/b/c/d;p?q g;x=1/./y => http://a/b/c/g;x=1/y + http://a/b/c/d;p?q g;x=1/../y => http://a/b/c/y + http://a/b/c/d;p?q g?y/./x => http://a/b/c/g?y/./x + http://a/b/c/d;p?q g?y/../x => http://a/b/c/g?y/../x + http://a/b/c/d;p?q g#s/./x => http://a/b/c/g#s/./x + http://a/b/c/d;p?q g#s/../x => http://a/b/c/g#s/../x + +Testing av_url_split: +/foo/bar => -1 /foo/bar +http://server/foo/ => http server -1 /foo/ +http://example.com/foo/bar => http example.com -1 /foo/bar +http://user:pass@localhost:8080/foo/bar/123 => http user:pass localhost 8080 /foo/bar/123 +http://server/foo/bar?param=value/with/slashes => http server -1 /foo/bar?param=value/with/slashes +https://1l-lh.a.net/i/1LIVE_HDS@179577/master.m3u8 => https 1l-lh.a.net -1 /i/1LIVE_HDS@179577/master.m3u8 +ftp://u:p%2B%2F2@ftp.pbt.com/ExportHD.mpg => ftp u:p%2B%2F2 ftp.pbt.com -1 /ExportHD.mpg +https://key.dns.com?key_id=2&model_id=12345&&access_key= => https key.dns.com -1 ?key_id=2&model_id=12345&&access_key= +http://example.com#tag => http example.com -1 #tag diff -Nru ffmpeg-4.2.2/tests/ref/fate/vp9-encparams ffmpeg-4.4/tests/ref/fate/vp9-encparams --- ffmpeg-4.2.2/tests/ref/fate/vp9-encparams 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/vp9-encparams 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,937 @@ +frame 0 +AVVideoEncParams 0 +qp 65 +nb_blocks 731 +block 0 0:0 64x64 33 +block 1 64:0 16x16 -12 +block 2 80:0 16x16 -12 +block 3 64:16 16x8 0 +block 4 64:24 16x8 0 +block 5 80:16 8x16 0 +block 6 88:16 8x16 0 +block 7 96:0 32x16 -23 +block 8 96:16 32x16 0 +block 9 64:32 16x32 0 +block 10 80:32 16x32 0 +block 11 96:32 16x32 16 +block 12 112:32 16x32 -32 +block 13 128:0 32x16 -32 +block 14 128:16 32x16 -32 +block 15 160:0 32x16 -23 +block 16 160:16 32x16 -32 +block 17 128:32 16x16 -32 +block 18 144:32 16x8 16 +block 19 144:40 16x8 16 +block 20 128:48 8x8 -12 +block 21 136:48 8x8 -12 +block 22 128:56 8x8 -12 +block 23 136:56 8x8 -12 +block 24 144:48 16x16 16 +block 25 160:32 8x8 33 +block 26 168:32 8x8 33 +block 27 160:40 8x8 33 +block 28 168:40 8x8 33 +block 29 176:32 8x8 33 +block 30 184:32 8x8 33 +block 31 176:40 8x8 33 +block 32 184:40 8x8 33 +block 33 160:48 8x16 0 +block 34 168:48 8x16 0 +block 35 176:48 16x8 0 +block 36 176:56 16x8 0 +block 37 192:0 8x16 -23 +block 38 200:0 8x16 -23 +block 39 208:0 16x8 -23 +block 40 208:8 16x8 -23 +block 41 192:16 16x16 0 +block 42 208:16 16x16 16 +block 43 224:0 16x32 16 +block 44 240:0 16x32 16 +block 45 192:32 8x8 33 +block 46 200:32 8x8 33 +block 47 192:40 8x8 33 +block 48 200:40 8x8 33 +block 49 208:32 16x16 -12 +block 50 192:48 8x8 33 +block 51 200:48 8x8 33 +block 52 192:56 8x8 33 +block 53 200:56 8x8 33 +block 54 208:48 8x8 16 +block 55 216:48 8x8 16 +block 56 208:56 8x8 16 +block 57 216:56 8x8 16 +block 58 224:32 16x16 -32 +block 59 240:32 16x16 -23 +block 60 224:48 16x16 16 +block 61 240:48 16x16 16 +block 62 256:0 16x16 -12 +block 63 272:0 16x16 -23 +block 64 256:16 16x16 16 +block 65 272:16 16x16 16 +block 66 288:0 32x16 -23 +block 67 288:16 32x16 0 +block 68 256:32 16x16 -23 +block 69 272:32 16x16 -32 +block 70 256:48 16x16 16 +block 71 272:48 16x16 33 +block 72 288:32 32x32 16 +block 73 320:0 8x8 -23 +block 74 328:0 8x8 -23 +block 75 320:8 8x8 -23 +block 76 328:8 8x8 -23 +block 77 336:0 8x8 -12 +block 78 344:0 8x8 -12 +block 79 336:8 8x8 -12 +block 80 344:8 8x8 -12 +block 81 320:16 8x8 -12 +block 82 328:16 8x8 -12 +block 83 320:24 8x8 -12 +block 84 328:24 8x8 -12 +block 85 336:16 16x16 -12 +block 86 320:32 8x8 0 +block 87 328:32 8x8 0 +block 88 320:40 8x8 0 +block 89 328:40 8x8 0 +block 90 336:32 16x16 -12 +block 91 320:48 16x16 16 +block 92 336:48 16x16 -12 +block 93 0:64 16x32 -23 +block 94 16:64 16x32 -23 +block 95 32:64 8x8 0 +block 96 40:64 8x8 0 +block 97 32:72 8x8 0 +block 98 40:72 8x8 0 +block 99 48:64 8x8 16 +block 100 56:64 8x8 16 +block 101 48:72 8x8 16 +block 102 56:72 8x8 16 +block 103 32:80 16x16 -32 +block 104 48:80 16x16 -32 +block 105 0:96 16x16 -32 +block 106 16:96 16x16 -32 +block 107 0:112 16x16 -32 +block 108 16:112 16x16 -32 +block 109 32:96 16x16 -12 +block 110 48:96 16x16 -12 +block 111 32:112 16x16 -12 +block 112 48:112 16x16 -32 +block 113 64:64 16x16 16 +block 114 80:64 8x8 0 +block 115 88:64 8x8 0 +block 116 80:72 8x8 0 +block 117 88:72 8x8 0 +block 118 64:80 16x16 -32 +block 119 80:80 16x16 -32 +block 120 96:64 16x16 16 +block 121 112:64 16x16 -32 +block 122 96:80 16x16 16 +block 123 112:80 16x16 -32 +block 124 64:96 16x16 -12 +block 125 80:96 8x16 -12 +block 126 88:96 8x16 -12 +block 127 64:112 16x16 -12 +block 128 80:112 16x16 0 +block 129 96:96 16x32 16 +block 130 112:96 16x32 -32 +block 131 128:64 8x8 0 +block 132 136:64 8x8 0 +block 133 128:72 8x8 0 +block 134 136:72 8x8 0 +block 135 144:64 16x16 0 +block 136 128:80 16x16 -12 +block 137 144:80 16x16 33 +block 138 160:64 16x16 33 +block 139 176:64 8x8 33 +block 140 184:64 8x8 33 +block 141 176:72 8x8 33 +block 142 184:72 8x8 33 +block 143 160:80 8x8 33 +block 144 168:80 8x8 33 +block 145 160:88 8x8 33 +block 146 168:88 8x8 33 +block 147 176:80 8x8 0 +block 148 184:80 8x8 0 +block 149 176:88 8x8 0 +block 150 184:88 8x8 0 +block 151 128:96 16x32 33 +block 152 144:96 16x32 33 +block 153 160:96 8x8 33 +block 154 168:96 8x8 33 +block 155 160:104 8x8 33 +block 156 168:104 8x8 33 +block 157 176:96 16x16 33 +block 158 160:112 8x8 16 +block 159 168:112 8x8 16 +block 160 160:120 8x8 16 +block 161 168:120 8x8 16 +block 162 176:112 8x8 33 +block 163 184:112 8x8 33 +block 164 176:120 8x8 33 +block 165 184:120 8x8 33 +block 166 192:64 8x8 33 +block 167 200:64 8x8 33 +block 168 192:72 8x8 33 +block 169 200:72 8x8 33 +block 170 208:64 8x8 33 +block 171 216:64 8x8 33 +block 172 208:72 8x8 33 +block 173 216:72 8x8 33 +block 174 192:80 8x8 33 +block 175 200:80 8x8 33 +block 176 192:88 8x8 33 +block 177 200:88 8x8 33 +block 178 208:80 8x16 33 +block 179 216:80 8x16 33 +block 180 224:64 16x16 0 +block 181 240:64 16x16 0 +block 182 224:80 8x8 -12 +block 183 232:80 8x8 -12 +block 184 224:88 8x8 -12 +block 185 232:88 8x8 -12 +block 186 240:80 8x16 -12 +block 187 248:80 8x16 -12 +block 188 192:96 8x8 33 +block 189 200:96 8x8 33 +block 190 192:104 8x8 33 +block 191 200:104 8x8 33 +block 192 208:96 16x16 33 +block 193 192:112 8x8 33 +block 194 200:112 8x8 33 +block 195 192:120 8x8 33 +block 196 200:120 8x8 33 +block 197 208:112 8x8 33 +block 198 216:112 8x8 33 +block 199 208:120 8x8 33 +block 200 216:120 8x8 33 +block 201 224:96 8x8 16 +block 202 232:96 8x8 16 +block 203 224:104 8x8 16 +block 204 232:104 8x8 16 +block 205 240:96 16x16 -32 +block 206 224:112 8x8 33 +block 207 232:112 8x8 33 +block 208 224:120 8x8 33 +block 209 232:120 8x8 33 +block 210 240:112 16x16 -32 +block 211 256:64 16x16 0 +block 212 272:64 16x16 16 +block 213 256:80 16x8 0 +block 214 256:88 16x8 0 +block 215 272:80 16x8 0 +block 216 272:88 16x8 0 +block 217 288:64 8x8 16 +block 218 296:64 8x8 16 +block 219 288:72 8x8 16 +block 220 296:72 8x8 16 +block 221 304:64 16x16 0 +block 222 288:80 16x8 -12 +block 223 288:88 16x8 -12 +block 224 304:80 8x8 -12 +block 225 312:80 8x8 -12 +block 226 304:88 8x8 -12 +block 227 312:88 8x8 -12 +block 228 256:96 16x16 -32 +block 229 272:96 16x16 -32 +block 230 256:112 16x16 -32 +block 231 272:112 16x16 -32 +block 232 288:96 16x16 -32 +block 233 304:96 16x16 -12 +block 234 288:112 16x16 -32 +block 235 304:112 16x16 0 +block 236 320:64 8x16 -12 +block 237 328:64 8x16 -12 +block 238 336:64 16x16 -12 +block 239 320:80 16x8 0 +block 240 320:88 16x8 0 +block 241 336:80 16x16 -12 +block 242 320:96 8x16 0 +block 243 328:96 8x16 0 +block 244 336:96 16x16 -12 +block 245 320:112 16x16 0 +block 246 336:112 16x16 -12 +block 247 0:128 16x16 16 +block 248 16:128 16x16 16 +block 249 0:144 16x16 -12 +block 250 16:144 16x16 -12 +block 251 32:128 8x8 16 +block 252 40:128 8x8 16 +block 253 32:136 8x8 16 +block 254 40:136 8x8 16 +block 255 48:128 16x16 16 +block 256 32:144 16x16 -23 +block 257 48:144 16x16 -23 +block 258 0:160 16x16 -12 +block 259 16:160 16x16 -12 +block 260 0:176 16x16 -32 +block 261 16:176 8x8 -32 +block 262 24:176 8x8 -32 +block 263 16:184 8x8 -32 +block 264 24:184 8x8 -32 +block 265 32:160 32x32 -12 +block 266 64:128 16x16 16 +block 267 80:128 16x16 16 +block 268 64:144 16x16 -23 +block 269 80:144 16x16 -12 +block 270 96:128 8x8 0 +block 271 104:128 8x8 0 +block 272 96:136 8x8 0 +block 273 104:136 8x8 0 +block 274 112:128 16x16 -32 +block 275 96:144 8x8 -12 +block 276 104:144 8x8 -12 +block 277 96:152 8x8 -12 +block 278 104:152 8x8 -12 +block 279 112:144 16x16 -32 +block 280 64:160 16x16 0 +block 281 80:160 16x16 0 +block 282 64:176 16x16 -32 +block 283 80:176 16x8 -12 +block 284 80:184 16x8 -12 +block 285 96:160 16x16 -12 +block 286 112:160 16x16 -32 +block 287 96:176 16x8 44 +block 288 96:184 16x8 44 +block 289 112:176 8x8 44 +block 290 120:176 8x8 44 +block 291 112:184 8x8 44 +block 292 120:184 8x8 44 +block 293 128:128 8x8 44 +block 294 136:128 8x8 44 +block 295 128:136 8x8 44 +block 296 136:136 8x8 44 +block 297 144:128 8x8 0 +block 298 152:128 8x8 0 +block 299 144:136 8x8 0 +block 300 152:136 8x8 0 +block 301 128:144 8x8 16 +block 302 136:144 8x8 16 +block 303 128:152 8x8 16 +block 304 136:152 8x8 16 +block 305 144:144 8x8 44 +block 306 152:144 8x8 44 +block 307 144:152 8x8 44 +block 308 152:152 8x8 44 +block 309 160:128 16x16 0 +block 310 176:128 8x8 16 +block 311 184:128 8x8 16 +block 312 176:136 8x8 16 +block 313 184:136 8x8 16 +block 314 160:144 8x8 33 +block 315 168:144 8x8 33 +block 316 160:152 8x8 33 +block 317 168:152 8x8 33 +block 318 176:144 8x8 33 +block 319 184:144 8x8 33 +block 320 176:152 8x8 33 +block 321 184:152 8x8 33 +block 322 128:160 8x8 16 +block 323 136:160 8x8 16 +block 324 128:168 8x8 16 +block 325 136:168 8x8 16 +block 326 144:160 8x8 44 +block 327 152:160 8x8 44 +block 328 144:168 8x8 44 +block 329 152:168 8x8 44 +block 330 128:176 16x8 33 +block 331 128:184 16x8 33 +block 332 144:176 8x8 16 +block 333 152:176 8x8 16 +block 334 144:184 8x8 16 +block 335 152:184 8x8 16 +block 336 160:160 8x8 16 +block 337 168:160 8x8 16 +block 338 160:168 8x8 16 +block 339 168:168 8x8 16 +block 340 176:160 8x8 16 +block 341 184:160 8x8 16 +block 342 176:168 8x8 16 +block 343 184:168 8x8 16 +block 344 160:176 8x8 33 +block 345 168:176 8x8 33 +block 346 160:184 8x8 33 +block 347 168:184 8x8 33 +block 348 176:176 8x16 33 +block 349 184:176 8x16 33 +block 350 192:128 16x16 0 +block 351 208:128 8x16 44 +block 352 216:128 8x16 44 +block 353 192:144 16x16 0 +block 354 208:144 8x8 33 +block 355 216:144 8x8 33 +block 356 208:152 8x8 33 +block 357 216:152 8x8 33 +block 358 224:128 8x8 33 +block 359 232:128 8x8 33 +block 360 224:136 8x8 33 +block 361 232:136 8x8 33 +block 362 240:128 16x16 16 +block 363 224:144 16x8 0 +block 364 224:152 16x8 0 +block 365 240:144 16x16 -12 +block 366 192:160 16x16 16 +block 367 208:160 8x8 44 +block 368 216:160 8x8 44 +block 369 208:168 8x8 44 +block 370 216:168 8x8 44 +block 371 192:176 8x8 33 +block 372 200:176 8x8 33 +block 373 192:184 8x8 33 +block 374 200:184 8x8 33 +block 375 208:176 8x8 33 +block 376 216:176 8x8 33 +block 377 208:184 8x8 33 +block 378 216:184 8x8 33 +block 379 224:160 8x8 0 +block 380 232:160 8x8 0 +block 381 224:168 8x8 0 +block 382 232:168 8x8 0 +block 383 240:160 16x16 0 +block 384 224:176 8x8 44 +block 385 232:176 8x8 44 +block 386 224:184 8x8 44 +block 387 232:184 8x8 44 +block 388 240:176 16x8 44 +block 389 240:184 16x8 44 +block 390 256:128 16x16 16 +block 391 272:128 16x16 16 +block 392 256:144 16x16 -12 +block 393 272:144 16x16 -12 +block 394 288:128 16x8 16 +block 395 288:136 16x8 16 +block 396 304:128 16x16 16 +block 397 288:144 16x16 -12 +block 398 304:144 16x16 -12 +block 399 256:160 16x16 -23 +block 400 272:160 16x16 -23 +block 401 256:176 8x8 44 +block 402 264:176 8x8 44 +block 403 256:184 8x8 44 +block 404 264:184 8x8 44 +block 405 272:176 16x8 33 +block 406 272:184 16x8 33 +block 407 288:160 32x16 -23 +block 408 288:176 32x16 -32 +block 409 320:128 8x8 -12 +block 410 328:128 8x8 -12 +block 411 320:136 8x8 -12 +block 412 328:136 8x8 -12 +block 413 336:128 8x16 -12 +block 414 344:128 8x16 -12 +block 415 320:144 16x16 -23 +block 416 336:144 16x16 -12 +block 417 320:160 16x16 -23 +block 418 336:160 16x16 0 +block 419 320:176 16x16 -32 +block 420 336:176 16x16 0 +block 421 0:192 16x16 -32 +block 422 16:192 8x8 -32 +block 423 24:192 8x8 -32 +block 424 16:200 8x8 -32 +block 425 24:200 8x8 -32 +block 426 0:208 16x16 0 +block 427 16:208 16x16 0 +block 428 32:192 32x32 -32 +block 429 0:224 16x16 0 +block 430 16:224 16x16 0 +block 431 0:240 16x16 0 +block 432 16:240 16x16 0 +block 433 32:224 32x16 0 +block 434 32:240 32x16 33 +block 435 64:192 8x8 44 +block 436 72:192 8x8 44 +block 437 64:200 8x8 44 +block 438 72:200 8x8 44 +block 439 80:192 8x8 44 +block 440 88:192 8x8 44 +block 441 80:200 8x8 44 +block 442 88:200 8x8 44 +block 443 64:208 8x8 44 +block 444 72:208 8x8 44 +block 445 64:216 8x8 44 +block 446 72:216 8x8 44 +block 447 80:208 8x8 -12 +block 448 88:208 8x8 -12 +block 449 80:216 8x8 -12 +block 450 88:216 8x8 -12 +block 451 96:192 8x8 -23 +block 452 104:192 8x8 -23 +block 453 96:200 8x8 -23 +block 454 104:200 8x8 -23 +block 455 112:192 16x16 -23 +block 456 96:208 16x16 -23 +block 457 112:208 16x16 0 +block 458 64:224 32x16 16 +block 459 64:240 32x16 0 +block 460 96:224 16x16 -12 +block 461 112:224 8x16 0 +block 462 120:224 8x16 0 +block 463 96:240 16x16 -12 +block 464 112:240 8x8 0 +block 465 120:240 8x8 0 +block 466 112:248 8x8 0 +block 467 120:248 8x8 0 +block 468 128:192 8x8 0 +block 469 136:192 8x8 0 +block 470 128:200 8x8 0 +block 471 136:200 8x8 0 +block 472 144:192 8x16 0 +block 473 152:192 8x16 0 +block 474 128:208 8x8 -23 +block 475 136:208 8x8 -23 +block 476 128:216 8x8 -23 +block 477 136:216 8x8 -23 +block 478 144:208 8x16 0 +block 479 152:208 8x16 0 +block 480 160:192 8x8 44 +block 481 168:192 8x8 44 +block 482 160:200 8x8 44 +block 483 168:200 8x8 44 +block 484 176:192 8x8 0 +block 485 184:192 8x8 0 +block 486 176:200 8x8 0 +block 487 184:200 8x8 0 +block 488 160:208 8x8 33 +block 489 168:208 8x8 33 +block 490 160:216 8x8 33 +block 491 168:216 8x8 33 +block 492 176:208 8x8 44 +block 493 184:208 8x8 44 +block 494 176:216 8x8 44 +block 495 184:216 8x8 44 +block 496 128:224 16x16 -32 +block 497 144:224 16x16 -12 +block 498 128:240 8x16 -12 +block 499 136:240 8x16 -12 +block 500 144:240 16x16 -23 +block 501 160:224 8x8 33 +block 502 168:224 8x8 33 +block 503 160:232 8x8 33 +block 504 168:232 8x8 33 +block 505 176:224 8x8 33 +block 506 184:224 8x8 33 +block 507 176:232 8x8 33 +block 508 184:232 8x8 33 +block 509 160:240 8x8 33 +block 510 168:240 8x8 33 +block 511 160:248 8x8 33 +block 512 168:248 8x8 33 +block 513 176:240 8x8 33 +block 514 184:240 8x8 33 +block 515 176:248 8x8 33 +block 516 184:248 8x8 33 +block 517 192:192 16x8 33 +block 518 192:200 16x8 33 +block 519 208:192 8x16 16 +block 520 216:192 8x16 16 +block 521 192:208 16x16 16 +block 522 208:208 8x8 0 +block 523 216:208 8x8 0 +block 524 208:216 8x8 0 +block 525 216:216 8x8 0 +block 526 224:192 8x8 -12 +block 527 232:192 8x8 -12 +block 528 224:200 8x8 -12 +block 529 232:200 8x8 -12 +block 530 240:192 8x16 0 +block 531 248:192 8x16 0 +block 532 224:208 16x16 -23 +block 533 240:208 16x8 16 +block 534 240:216 16x8 16 +block 535 192:224 16x16 33 +block 536 208:224 8x8 0 +block 537 216:224 8x8 0 +block 538 208:232 8x8 0 +block 539 216:232 8x8 0 +block 540 192:240 8x8 33 +block 541 200:240 8x8 33 +block 542 192:248 8x8 33 +block 543 200:248 8x8 33 +block 544 208:240 8x8 0 +block 545 216:240 8x8 0 +block 546 208:248 8x8 0 +block 547 216:248 8x8 0 +block 548 224:224 16x16 -23 +block 549 240:224 8x8 33 +block 550 248:224 8x8 33 +block 551 240:232 8x8 33 +block 552 248:232 8x8 33 +block 553 224:240 8x8 -23 +block 554 232:240 8x8 -23 +block 555 224:248 8x8 -23 +block 556 232:248 8x8 -23 +block 557 240:240 8x8 33 +block 558 248:240 8x8 33 +block 559 240:248 8x8 33 +block 560 248:248 8x8 33 +block 561 256:192 16x16 -23 +block 562 272:192 16x8 16 +block 563 272:200 16x8 16 +block 564 256:208 8x8 -23 +block 565 264:208 8x8 -23 +block 566 256:216 8x8 -23 +block 567 264:216 8x8 -23 +block 568 272:208 8x8 -32 +block 569 280:208 8x8 -32 +block 570 272:216 8x8 -32 +block 571 280:216 8x8 -32 +block 572 288:192 8x8 44 +block 573 296:192 8x8 44 +block 574 288:200 8x8 44 +block 575 296:200 8x8 44 +block 576 304:192 8x8 -32 +block 577 312:192 8x8 -32 +block 578 304:200 8x8 -32 +block 579 312:200 8x8 -32 +block 580 288:208 16x16 33 +block 581 304:208 8x16 -12 +block 582 312:208 8x16 -12 +block 583 256:224 16x16 -23 +block 584 272:224 16x16 -23 +block 585 256:240 8x8 -12 +block 586 264:240 8x8 -12 +block 587 256:248 8x8 -12 +block 588 264:248 8x8 -12 +block 589 272:240 8x8 0 +block 590 280:240 8x8 0 +block 591 272:248 8x8 0 +block 592 280:248 8x8 0 +block 593 288:224 16x16 33 +block 594 304:224 16x8 16 +block 595 304:232 16x8 16 +block 596 288:240 16x16 33 +block 597 304:240 8x8 44 +block 598 312:240 8x8 44 +block 599 304:248 8x8 44 +block 600 312:248 8x8 44 +block 601 320:192 8x8 -32 +block 602 328:192 8x8 -32 +block 603 320:200 8x8 -32 +block 604 328:200 8x8 -32 +block 605 336:192 8x16 0 +block 606 344:192 8x16 0 +block 607 320:208 8x8 -32 +block 608 328:208 8x8 -32 +block 609 320:216 8x8 -32 +block 610 328:216 8x8 -32 +block 611 336:208 8x16 0 +block 612 344:208 8x16 0 +block 613 320:224 16x16 -32 +block 614 336:224 16x16 0 +block 615 320:240 16x16 -32 +block 616 336:240 8x8 0 +block 617 344:240 8x8 0 +block 618 336:248 8x8 0 +block 619 344:248 8x8 0 +block 620 0:256 16x16 0 +block 621 16:256 16x16 -23 +block 622 0:272 16x16 -32 +block 623 16:272 16x16 -32 +block 624 32:256 16x16 -32 +block 625 48:256 8x8 44 +block 626 56:256 8x8 44 +block 627 48:264 8x8 44 +block 628 56:264 8x8 44 +block 629 32:272 16x16 -32 +block 630 48:272 8x8 44 +block 631 56:272 8x8 44 +block 632 48:280 8x8 44 +block 633 56:280 8x8 44 +block 634 64:256 8x8 0 +block 635 72:256 8x8 0 +block 636 64:264 8x8 0 +block 637 72:264 8x8 0 +block 638 80:256 8x8 0 +block 639 88:256 8x8 0 +block 640 80:264 8x8 0 +block 641 88:264 8x8 0 +block 642 64:272 8x8 -12 +block 643 72:272 8x8 -12 +block 644 64:280 8x8 -12 +block 645 72:280 8x8 -12 +block 646 80:272 16x16 0 +block 647 96:256 16x16 -23 +block 648 112:256 8x8 -12 +block 649 120:256 8x8 -12 +block 650 112:264 8x8 -12 +block 651 120:264 8x8 -12 +block 652 96:272 16x16 -12 +block 653 112:272 8x8 -23 +block 654 120:272 8x8 -23 +block 655 112:280 8x8 -23 +block 656 120:280 8x8 -23 +block 657 128:256 32x32 -32 +block 658 160:256 8x8 33 +block 659 168:256 8x8 33 +block 660 160:264 8x8 33 +block 661 168:264 8x8 33 +block 662 176:256 8x8 33 +block 663 184:256 8x8 33 +block 664 176:264 8x8 33 +block 665 184:264 8x8 33 +block 666 160:272 8x8 33 +block 667 168:272 8x8 33 +block 668 160:280 8x8 33 +block 669 168:280 8x8 33 +block 670 176:272 8x16 0 +block 671 184:272 8x16 0 +block 672 192:256 8x8 33 +block 673 200:256 8x8 33 +block 674 192:264 8x8 33 +block 675 200:264 8x8 33 +block 676 208:256 8x8 44 +block 677 216:256 8x8 44 +block 678 208:264 8x8 44 +block 679 216:264 8x8 44 +block 680 192:272 8x8 33 +block 681 200:272 8x8 33 +block 682 192:280 8x8 33 +block 683 200:280 8x8 33 +block 684 208:272 8x8 33 +block 685 216:272 8x8 33 +block 686 208:280 8x8 33 +block 687 216:280 8x8 33 +block 688 224:256 8x8 0 +block 689 232:256 8x8 0 +block 690 224:264 8x8 0 +block 691 232:264 8x8 0 +block 692 240:256 8x8 33 +block 693 248:256 8x8 33 +block 694 240:264 8x8 33 +block 695 248:264 8x8 33 +block 696 224:272 16x8 -32 +block 697 224:280 16x8 -32 +block 698 240:272 8x8 33 +block 699 248:272 8x8 33 +block 700 240:280 8x8 33 +block 701 248:280 8x8 33 +block 702 256:256 16x16 0 +block 703 272:256 8x8 33 +block 704 280:256 8x8 33 +block 705 272:264 8x8 33 +block 706 280:264 8x8 33 +block 707 256:272 8x8 33 +block 708 264:272 8x8 33 +block 709 256:280 8x8 33 +block 710 264:280 8x8 33 +block 711 272:272 8x8 33 +block 712 280:272 8x8 33 +block 713 272:280 8x8 33 +block 714 280:280 8x8 33 +block 715 288:256 16x16 33 +block 716 304:256 8x8 44 +block 717 312:256 8x8 44 +block 718 304:264 8x8 44 +block 719 312:264 8x8 44 +block 720 288:272 16x16 0 +block 721 304:272 8x16 44 +block 722 312:272 8x16 44 +block 723 320:256 16x8 -32 +block 724 320:264 16x8 -32 +block 725 336:256 8x8 0 +block 726 344:256 8x8 0 +block 727 336:264 8x8 0 +block 728 344:264 8x8 0 +block 729 320:272 16x16 -32 +block 730 336:272 16x16 0 +frame 1 +AVVideoEncParams 0 +qp 183 +nb_blocks 37 +block 0 0:0 64x64 21 +block 1 64:0 64x64 21 +block 2 128:0 64x64 11 +block 3 192:0 64x64 21 +block 4 256:0 64x64 21 +block 5 320:0 32x32 -10 +block 6 320:32 32x32 0 +block 7 0:64 64x64 0 +block 8 64:64 64x64 21 +block 9 128:64 64x64 32 +block 10 192:64 64x64 21 +block 11 256:64 64x64 11 +block 12 320:64 32x32 0 +block 13 320:96 32x32 0 +block 14 0:128 64x64 0 +block 15 64:128 64x64 21 +block 16 128:128 64x64 32 +block 17 192:128 64x64 32 +block 18 256:128 64x64 21 +block 19 320:128 32x32 -10 +block 20 320:160 32x32 -10 +block 21 0:192 64x64 11 +block 22 64:192 64x64 21 +block 23 128:192 64x64 21 +block 24 192:192 64x64 21 +block 25 256:192 64x64 32 +block 26 320:192 32x32 -10 +block 27 320:224 32x32 -10 +block 28 0:256 32x32 -10 +block 29 32:256 32x32 32 +block 30 64:256 32x32 0 +block 31 96:256 32x32 -10 +block 32 128:256 32x32 -32 +block 33 160:256 32x32 21 +block 34 192:256 64x32 21 +block 35 256:256 64x32 21 +block 36 320:256 32x32 -10 +frame 2 +AVVideoEncParams 0 +qp 188 +nb_blocks 40 +block 0 0:0 64x64 21 +block 1 64:0 64x64 21 +block 2 128:0 64x64 11 +block 3 192:0 64x64 21 +block 4 256:0 64x64 21 +block 5 320:0 32x32 -10 +block 6 320:32 32x32 0 +block 7 0:64 64x64 0 +block 8 64:64 64x64 21 +block 9 128:64 64x64 31 +block 10 192:64 64x64 21 +block 11 256:64 64x64 11 +block 12 320:64 32x32 0 +block 13 320:96 32x32 0 +block 14 0:128 64x64 0 +block 15 64:128 64x64 21 +block 16 128:128 32x64 31 +block 17 160:128 32x64 21 +block 18 192:128 64x64 31 +block 19 256:128 64x64 21 +block 20 320:128 32x32 -10 +block 21 320:160 32x32 -10 +block 22 0:192 64x64 11 +block 23 64:192 64x64 21 +block 24 128:192 64x64 21 +block 25 192:192 64x64 21 +block 26 256:192 64x64 31 +block 27 320:192 32x32 -10 +block 28 320:224 32x32 -10 +block 29 0:256 32x32 -10 +block 30 32:256 32x32 31 +block 31 64:256 32x32 0 +block 32 96:256 32x32 -10 +block 33 128:256 32x32 -32 +block 34 160:256 32x32 21 +block 35 192:256 32x32 31 +block 36 224:256 32x32 21 +block 37 256:256 32x32 21 +block 38 288:256 32x32 31 +block 39 320:256 32x32 -10 +frame 3 +AVVideoEncParams 0 +qp 192 +nb_blocks 39 +block 0 0:0 64x64 21 +block 1 64:0 64x64 21 +block 2 128:0 64x64 11 +block 3 192:0 64x64 21 +block 4 256:0 64x64 21 +block 5 320:0 32x32 -10 +block 6 320:32 32x32 0 +block 7 0:64 64x64 0 +block 8 64:64 64x64 21 +block 9 128:64 64x64 31 +block 10 192:64 64x64 21 +block 11 256:64 64x64 11 +block 12 320:64 32x32 0 +block 13 320:96 32x32 0 +block 14 0:128 64x64 0 +block 15 64:128 64x64 21 +block 16 128:128 64x64 31 +block 17 192:128 64x64 31 +block 18 256:128 64x64 21 +block 19 320:128 32x32 -10 +block 20 320:160 32x32 -10 +block 21 0:192 64x64 11 +block 22 64:192 64x64 21 +block 23 128:192 64x64 21 +block 24 192:192 64x64 21 +block 25 256:192 64x64 31 +block 26 320:192 32x32 -10 +block 27 320:224 32x32 -10 +block 28 0:256 32x32 -10 +block 29 32:256 32x32 31 +block 30 64:256 32x32 0 +block 31 96:256 32x32 -10 +block 32 128:256 32x32 -32 +block 33 160:256 32x32 21 +block 34 192:256 32x32 31 +block 35 224:256 32x32 21 +block 36 256:256 32x32 21 +block 37 288:256 32x32 31 +block 38 320:256 32x32 -10 +frame 4 +AVVideoEncParams 0 +qp 196 +nb_blocks 70 +block 0 0:0 64x64 21 +block 1 64:0 64x64 21 +block 2 128:0 64x64 11 +block 3 192:0 64x64 21 +block 4 256:0 64x64 21 +block 5 320:0 32x32 -10 +block 6 320:32 32x32 0 +block 7 0:64 64x64 0 +block 8 64:64 64x64 21 +block 9 128:64 32x32 11 +block 10 160:64 32x32 31 +block 11 128:96 16x16 21 +block 12 144:96 16x16 21 +block 13 128:112 16x16 31 +block 14 144:112 8x8 21 +block 15 152:112 8x8 21 +block 16 144:120 8x8 21 +block 17 152:120 8x8 21 +block 18 160:96 16x16 21 +block 19 176:96 8x8 21 +block 20 184:96 8x8 21 +block 21 176:104 8x8 21 +block 22 184:104 8x8 21 +block 23 160:112 16x16 11 +block 24 176:112 8x8 21 +block 25 184:112 8x8 21 +block 26 176:120 8x8 21 +block 27 184:120 8x8 21 +block 28 192:64 32x32 21 +block 29 224:64 32x32 0 +block 30 192:96 8x8 11 +block 31 200:96 8x8 11 +block 32 192:104 8x8 11 +block 33 200:104 8x8 11 +block 34 208:96 16x16 21 +block 35 192:112 8x8 21 +block 36 200:112 8x8 21 +block 37 192:120 8x8 21 +block 38 200:120 8x8 21 +block 39 208:112 16x16 21 +block 40 224:96 32x16 0 +block 41 224:112 32x16 21 +block 42 256:64 64x64 11 +block 43 320:64 32x32 0 +block 44 320:96 32x32 0 +block 45 0:128 64x64 0 +block 46 64:128 64x64 21 +block 47 128:128 64x64 31 +block 48 192:128 64x64 31 +block 49 256:128 64x64 21 +block 50 320:128 32x32 -10 +block 51 320:160 32x32 -10 +block 52 0:192 64x64 11 +block 53 64:192 64x64 21 +block 54 128:192 64x64 21 +block 55 192:192 64x64 21 +block 56 256:192 64x64 31 +block 57 320:192 32x32 -10 +block 58 320:224 32x32 -10 +block 59 0:256 32x32 -10 +block 60 32:256 32x32 31 +block 61 64:256 32x32 0 +block 62 96:256 32x32 -10 +block 63 128:256 32x32 -32 +block 64 160:256 32x32 21 +block 65 192:256 32x32 31 +block 66 224:256 32x32 21 +block 67 256:256 32x32 21 +block 68 288:256 32x32 31 +block 69 320:256 32x32 -10 diff -Nru ffmpeg-4.2.2/tests/ref/fate/vp9-tiling-pedestrian ffmpeg-4.4/tests/ref/fate/vp9-tiling-pedestrian --- ffmpeg-4.2.2/tests/ref/fate/vp9-tiling-pedestrian 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/vp9-tiling-pedestrian 2021-04-08 21:28:40.000000000 +0000 @@ -7,5 +7,5 @@ #dimensions 0: 1920x1080 #sar 0: 1/1 #stream#, dts, pts, duration, size, hash -0, 0, 0, 0, 3110400, 1e6c2e768a5107e57e6d626f0511193a -0, 40, 40, 0, 3110400, 972d3e2b5ee2e3b0907218a243e4cb7d +0, 0, 0, 1, 3110400, 1e6c2e768a5107e57e6d626f0511193a +0, 40, 40, 1, 3110400, 972d3e2b5ee2e3b0907218a243e4cb7d diff -Nru ffmpeg-4.2.2/tests/ref/fate/wav-chapters ffmpeg-4.4/tests/ref/fate/wav-chapters --- ffmpeg-4.2.2/tests/ref/fate/wav-chapters 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/wav-chapters 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,45 @@ +[CHAPTER] +id=1 +time_base=1/48000 +start=148992 +start_time=3.104000 +end=226560 +end_time=4.720000 +TAG:title=01 +[/CHAPTER] +[CHAPTER] +id=2 +time_base=1/48000 +start=226560 +start_time=4.720000 +end=301728 +end_time=6.286000 +TAG:title=02 +[/CHAPTER] +[CHAPTER] +id=3 +time_base=1/48000 +start=301728 +start_time=6.286000 +end=314016 +end_time=6.542000 +TAG:title=03 +[/CHAPTER] +[CHAPTER] +id=4 +time_base=1/48000 +start=314016 +start_time=6.542000 +end=396528 +end_time=8.261000 +TAG:title=04 +[/CHAPTER] +[CHAPTER] +id=5 +time_base=1/48000 +start=396528 +start_time=8.261000 +end=614464 +end_time=12.801333 +TAG:title=05 +[/CHAPTER] diff -Nru ffmpeg-4.2.2/tests/ref/fate/webm-dash-chapters ffmpeg-4.4/tests/ref/fate/webm-dash-chapters --- ffmpeg-4.2.2/tests/ref/fate/webm-dash-chapters 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/fate/webm-dash-chapters 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,74 @@ +e7fde2ecc9683a7a5296dab33b028653 *tests/data/fate/webm-dash-chapters.webm +111220 tests/data/fate/webm-dash-chapters.webm +#extradata 0: 3469, 0xc6769ddc +#tb 0: 1/1000 +#media_type 0: audio +#codec_id 0: vorbis +#sample_rate 0: 44100 +#channel_layout 0: 4 +#channel_layout_name 0: mono +0, 0, 0, 5, 28, 0xefcf103e +0, 6, 6, 26, 198, 0xfbbe5eb5 +0, 32, 32, 46, 198, 0xabd95c6c +0, 99, 99, 26, 41, 0x954b12a5 +0, 105, 105, 5, 41, 0xbccd1463 +0, 110, 110, 5, 44, 0x4fa218a1 +0, 116, 116, 5, 43, 0xf87716d4 +0, 122, 122, 5, 32, 0x0fdc1057 +0, 128, 128, 5, 67, 0xd5352244 +0, 134, 134, 5, 68, 0x36e91faf +0, 140, 140, 5, 57, 0xe6f51928 +0, 145, 145, 5, 49, 0x3bb416e1 +0, 151, 151, 5, 54, 0x678f1777 +0, 157, 157, 5, 57, 0x56601ef3 +0, 163, 163, 5, 52, 0xc0fe1a12 +0, 169, 169, 26, 236, 0xfe396f02 +0, 195, 195, 46, 208, 0x018e62d3 +0, 241, 241, 46, 223, 0x9fa76917 +0, 308, 308, 26, 46, 0xd8c314f9 +0, 314, 314, 5, 46, 0x199018bc +0, 319, 319, 5, 46, 0xbe8314cd +0, 325, 325, 5, 45, 0xe0ad1622 +0, 331, 331, 5, 43, 0xe52a1659 +0, 337, 337, 5, 58, 0xd5e01f9c +0, 343, 343, 5, 67, 0x5bbc2201 +0, 348, 348, 26, 226, 0x04887569 +0, 375, 375, 46, 217, 0x4b6564ab +0, 421, 421, 46, 211, 0xb7e868da +0, 467, 467, 46, 198, 0x7bf65d8a +[CHAPTER] +id=1 +time_base=1/1000000000 +start=0 +start_time=0.000000 +end=5000000000 +end_time=5.000000 +TAG:title=start +[/CHAPTER] +[CHAPTER] +id=2 +time_base=1/1000000000 +start=5000000000 +start_time=5.000000 +end=10500000000 +end_time=10.500000 +TAG:title=Five Seconds +[/CHAPTER] +[CHAPTER] +id=3 +time_base=1/1000000000 +start=10500000000 +start_time=10.500000 +end=15000000000 +end_time=15.000000 +TAG:title=Ten point 5 seconds +[/CHAPTER] +[CHAPTER] +id=4 +time_base=1/1000000000 +start=15000000000 +start_time=15.000000 +end=19849000000 +end_time=19.849000 +TAG:title=15 sec - over soon +[/CHAPTER] diff -Nru ffmpeg-4.2.2/tests/ref/lavf/fits ffmpeg-4.4/tests/ref/lavf/fits --- ffmpeg-4.2.2/tests/ref/lavf/fits 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/fits 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -ed9fd697d0d782df6201f6a2db184552 *./tests/data/lavf/graylavf.fits -5328000 ./tests/data/lavf/graylavf.fits -./tests/data/lavf/graylavf.fits CRC=0xbacf446c -48e6caf6a59e32f9a8a39979c9183a7f *./tests/data/lavf/gray16belavf.fits -10368000 ./tests/data/lavf/gray16belavf.fits -./tests/data/lavf/gray16belavf.fits CRC=0xae2b58d4 -be2f7112fd193c9a909304c81e662769 *./tests/data/lavf/gbrplavf.fits -15408000 ./tests/data/lavf/gbrplavf.fits -./tests/data/lavf/gbrplavf.fits CRC=0x04ed3828 -c89a72185cfad363aa9cc42e84fed301 *./tests/data/lavf/gbraplavf.fits -20448000 ./tests/data/lavf/gbraplavf.fits -./tests/data/lavf/gbraplavf.fits CRC=0x032a6409 -d539b9e02f5ab8fb85717c8adb60b6cc *./tests/data/lavf/gbrp16belavf.fits -30672000 ./tests/data/lavf/gbrp16belavf.fits -./tests/data/lavf/gbrp16belavf.fits CRC=0x81897ff7 -3dc3622fb09a338b406d8a12a30f2545 *./tests/data/lavf/gbrap16belavf.fits -40752000 ./tests/data/lavf/gbrap16belavf.fits -./tests/data/lavf/gbrap16belavf.fits CRC=0x247dd7b9 diff -Nru ffmpeg-4.2.2/tests/ref/lavf/gbrap16be.fits ffmpeg-4.4/tests/ref/lavf/gbrap16be.fits --- ffmpeg-4.2.2/tests/ref/lavf/gbrap16be.fits 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/gbrap16be.fits 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -ff5fb24a67aeabd4f56088ca8b03d8b0 *tests/data/lavf/lavf.gbrap16be.fits +e9a04d25104fc43ddc62b58eb33ecd08 *tests/data/lavf/lavf.gbrap16be.fits 20376000 tests/data/lavf/lavf.gbrap16be.fits tests/data/lavf/lavf.gbrap16be.fits CRC=0xa981271b diff -Nru ffmpeg-4.2.2/tests/ref/lavf/gbrap.fits ffmpeg-4.4/tests/ref/lavf/gbrap.fits --- ffmpeg-4.2.2/tests/ref/lavf/gbrap.fits 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/gbrap.fits 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -28eb102547b82acca57ef097a6c639d8 *tests/data/lavf/lavf.gbrap.fits +d953a6a2c719de9d922d0624a7eb796b *tests/data/lavf/lavf.gbrap.fits 10224000 tests/data/lavf/lavf.gbrap.fits tests/data/lavf/lavf.gbrap.fits CRC=0x883af247 diff -Nru ffmpeg-4.2.2/tests/ref/lavf/gbrp16be.fits ffmpeg-4.4/tests/ref/lavf/gbrp16be.fits --- ffmpeg-4.2.2/tests/ref/lavf/gbrp16be.fits 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/gbrp16be.fits 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -693ea80c33eb9b348db27a0bc4a5cc8a *tests/data/lavf/lavf.gbrp16be.fits +caf72fec125df9c7a1d59c9d1bc70b80 *tests/data/lavf/lavf.gbrp16be.fits 15336000 tests/data/lavf/lavf.gbrp16be.fits tests/data/lavf/lavf.gbrp16be.fits CRC=0x9573fb2b diff -Nru ffmpeg-4.2.2/tests/ref/lavf/gbrp.fits ffmpeg-4.4/tests/ref/lavf/gbrp.fits --- ffmpeg-4.2.2/tests/ref/lavf/gbrp.fits 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/gbrp.fits 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -dae49b5f6eb58981ba91e3e108355717 *tests/data/lavf/lavf.gbrp.fits +3952247f7f9669f968826c909852bbd7 *tests/data/lavf/lavf.gbrp.fits 7704000 tests/data/lavf/lavf.gbrp.fits tests/data/lavf/lavf.gbrp.fits CRC=0x80745c5e diff -Nru ffmpeg-4.2.2/tests/ref/lavf/gray16be.fits ffmpeg-4.4/tests/ref/lavf/gray16be.fits --- ffmpeg-4.2.2/tests/ref/lavf/gray16be.fits 2019-12-31 21:35:30.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/gray16be.fits 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -15e85a553bbd07783f92377ed369308b *tests/data/lavf/lavf.gray16be.fits +262658f437a256cd843db2b401bc20a9 *tests/data/lavf/lavf.gray16be.fits 5184000 tests/data/lavf/lavf.gray16be.fits -tests/data/lavf/lavf.gray16be.fits CRC=0x8cdcbeb2 +tests/data/lavf/lavf.gray16be.fits CRC=0x737e8998 diff -Nru ffmpeg-4.2.2/tests/ref/lavf/gray.fits ffmpeg-4.4/tests/ref/lavf/gray.fits --- ffmpeg-4.2.2/tests/ref/lavf/gray.fits 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/gray.fits 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -d76b46a5a336b56f73451817cdf3897c *tests/data/lavf/lavf.gray.fits +e690dc6db533b87f5f843737007ed070 *tests/data/lavf/lavf.gray.fits 2664000 tests/data/lavf/lavf.gray.fits tests/data/lavf/lavf.gray.fits CRC=0x7aa0122f diff -Nru ffmpeg-4.2.2/tests/ref/lavf/ismv ffmpeg-4.4/tests/ref/lavf/ismv --- ffmpeg-4.2.2/tests/ref/lavf/ismv 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/ismv 2021-04-08 21:28:40.000000000 +0000 @@ -1,9 +1,9 @@ -bd88b50defa57766619c092ea89f25a6 *tests/data/lavf/lavf.ismv -313165 tests/data/lavf/lavf.ismv +48fb8d7a5d19bd60f3a49ccf4b7d6593 *tests/data/lavf/lavf.ismv +313169 tests/data/lavf/lavf.ismv tests/data/lavf/lavf.ismv CRC=0x9d9a638a -805a2557bf952c84835f3c10b6893e15 *tests/data/lavf/lavf.ismv -322071 tests/data/lavf/lavf.ismv +d19cd8e310a2e94fe0a0d11c5dc29217 *tests/data/lavf/lavf.ismv +322075 tests/data/lavf/lavf.ismv tests/data/lavf/lavf.ismv CRC=0xe8130120 -96053075a3f60d271131fe2d0765c267 *tests/data/lavf/lavf.ismv -312542 tests/data/lavf/lavf.ismv +3b6023766845b51b075aed474c00f73c *tests/data/lavf/lavf.ismv +312546 tests/data/lavf/lavf.ismv tests/data/lavf/lavf.ismv CRC=0x9d9a638a diff -Nru ffmpeg-4.2.2/tests/ref/lavf/mka ffmpeg-4.4/tests/ref/lavf/mka --- ffmpeg-4.2.2/tests/ref/lavf/mka 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/mka 2020-07-11 10:39:30.000000000 +0000 @@ -1,3 +1,3 @@ -a91bfdb08ff5a1e62b039748d16b07f7 *tests/data/lavf/lavf.mka -43652 tests/data/lavf/lavf.mka +ea812a6619f4f0d266bec82fcfa54e78 *tests/data/lavf/lavf.mka +43580 tests/data/lavf/lavf.mka tests/data/lavf/lavf.mka CRC=0x3a1da17e diff -Nru ffmpeg-4.2.2/tests/ref/lavf/mkv ffmpeg-4.4/tests/ref/lavf/mkv --- ffmpeg-4.2.2/tests/ref/lavf/mkv 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/mkv 2020-07-11 10:39:30.000000000 +0000 @@ -1,3 +1,3 @@ -3cddd26ed41f34925d3f34acabab174e *tests/data/lavf/lavf.mkv -320555 tests/data/lavf/lavf.mkv +c984a76e996f43943d2fe9eb5f2495e4 *tests/data/lavf/lavf.mkv +320432 tests/data/lavf/lavf.mkv tests/data/lavf/lavf.mkv CRC=0xec6c3c68 diff -Nru ffmpeg-4.2.2/tests/ref/lavf/mkv_attachment ffmpeg-4.4/tests/ref/lavf/mkv_attachment --- ffmpeg-4.2.2/tests/ref/lavf/mkv_attachment 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/mkv_attachment 2020-07-11 10:39:30.000000000 +0000 @@ -1,3 +1,3 @@ -4a25c53150c09537cd4fcbff8f8f14ff *tests/data/lavf/lavf.mkv_attachment -472706 tests/data/lavf/lavf.mkv_attachment +8182124c770de9579e6d0d6759d01655 *tests/data/lavf/lavf.mkv_attachment +472587 tests/data/lavf/lavf.mkv_attachment tests/data/lavf/lavf.mkv_attachment CRC=0xec6c3c68 diff -Nru ffmpeg-4.2.2/tests/ref/lavf/mp4 ffmpeg-4.4/tests/ref/lavf/mp4 --- ffmpeg-4.2.2/tests/ref/lavf/mp4 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/mp4 2021-04-08 21:28:40.000000000 +0000 @@ -1,9 +1,9 @@ -ebca72c186a4f3ba9bb17d9cb5b74fef *tests/data/lavf/lavf.mp4 -312457 tests/data/lavf/lavf.mp4 +71c4ff2e747fe6f8169ff29244fe181d *tests/data/lavf/lavf.mp4 +312477 tests/data/lavf/lavf.mp4 tests/data/lavf/lavf.mp4 CRC=0x9d9a638a -9944512475d82d2d601f3c96101bdf9c *tests/data/lavf/lavf.mp4 -321343 tests/data/lavf/lavf.mp4 +3c5734ad6d05e4afc2ccefef1385e882 *tests/data/lavf/lavf.mp4 +321363 tests/data/lavf/lavf.mp4 tests/data/lavf/lavf.mp4 CRC=0xe8130120 -7b3e71f294901067046c09f03a426bdc *tests/data/lavf/lavf.mp4 -312001 tests/data/lavf/lavf.mp4 +07348e31d11d92396e1eedc48ea14802 *tests/data/lavf/lavf.mp4 +312021 tests/data/lavf/lavf.mp4 tests/data/lavf/lavf.mp4 CRC=0x9d9a638a diff -Nru ffmpeg-4.2.2/tests/ref/lavf/mxf ffmpeg-4.4/tests/ref/lavf/mxf --- ffmpeg-4.2.2/tests/ref/lavf/mxf 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/mxf 2021-04-08 21:28:40.000000000 +0000 @@ -1,9 +1,9 @@ -649009e3d3d62eb3b6c56334d057cc4d *tests/data/lavf/lavf.mxf +8938d5c4a396ff1b24d10d4f917ae1c9 *tests/data/lavf/lavf.mxf 526393 tests/data/lavf/lavf.mxf tests/data/lavf/lavf.mxf CRC=0x8dddfaab -9076b7015cffe8aa72883e900a2041a5 *tests/data/lavf/lavf.mxf +93ea2cfdf5dda7fffdc0d2fdcfb6a9a4 *tests/data/lavf/lavf.mxf 561721 tests/data/lavf/lavf.mxf tests/data/lavf/lavf.mxf CRC=0x96ff1b48 -02bf8f0cd8951a49e277306691cb1538 *tests/data/lavf/lavf.mxf +87bdf844ae34bcc758e44419e80177a0 *tests/data/lavf/lavf.mxf 526393 tests/data/lavf/lavf.mxf tests/data/lavf/lavf.mxf CRC=0x8dddfaab diff -Nru ffmpeg-4.2.2/tests/ref/lavf/mxf_d10 ffmpeg-4.4/tests/ref/lavf/mxf_d10 --- ffmpeg-4.2.2/tests/ref/lavf/mxf_d10 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/mxf_d10 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -e597f73ef9c9819710d2f815813eb91f *tests/data/lavf/lavf.mxf_d10 +7f16902e28718c2a92bc082400a1c6ee *tests/data/lavf/lavf.mxf_d10 5332013 tests/data/lavf/lavf.mxf_d10 tests/data/lavf/lavf.mxf_d10 CRC=0x6c74d488 diff -Nru ffmpeg-4.2.2/tests/ref/lavf/mxf_dv25 ffmpeg-4.4/tests/ref/lavf/mxf_dv25 --- ffmpeg-4.2.2/tests/ref/lavf/mxf_dv25 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/mxf_dv25 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -0fc964fa22bc8b3a389b81b9a2efccb3 *tests/data/lavf/lavf.mxf_dv25 +106e33eb1634595623f0334e92204b65 *tests/data/lavf/lavf.mxf_dv25 3834413 tests/data/lavf/lavf.mxf_dv25 tests/data/lavf/lavf.mxf_dv25 CRC=0xbdaf7f52 diff -Nru ffmpeg-4.2.2/tests/ref/lavf/mxf_dvcpro50 ffmpeg-4.4/tests/ref/lavf/mxf_dvcpro50 --- ffmpeg-4.2.2/tests/ref/lavf/mxf_dvcpro50 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/mxf_dvcpro50 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -aa81ea83af44a69e73849e327cc4bd12 *tests/data/lavf/lavf.mxf_dvcpro50 +3d5a303c22666996700f0e8f6e4cb938 *tests/data/lavf/lavf.mxf_dvcpro50 7431213 tests/data/lavf/lavf.mxf_dvcpro50 tests/data/lavf/lavf.mxf_dvcpro50 CRC=0xe3bbe4b4 diff -Nru ffmpeg-4.2.2/tests/ref/lavf/mxf_opatom ffmpeg-4.4/tests/ref/lavf/mxf_opatom --- ffmpeg-4.2.2/tests/ref/lavf/mxf_opatom 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/mxf_opatom 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -06a1816aa91c733e1ef7e45d82e4f1d3 *tests/data/lavf/lavf.mxf_opatom +5d235c127ace64b1f4fe6c79a7ca8be6 *tests/data/lavf/lavf.mxf_opatom 4717625 tests/data/lavf/lavf.mxf_opatom tests/data/lavf/lavf.mxf_opatom CRC=0xf55aa22a diff -Nru ffmpeg-4.2.2/tests/ref/lavf/mxf_opatom_audio ffmpeg-4.4/tests/ref/lavf/mxf_opatom_audio --- ffmpeg-4.2.2/tests/ref/lavf/mxf_opatom_audio 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/mxf_opatom_audio 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -c45bb140605339556a77e751fda2c449 *tests/data/lavf/lavf.mxf_opatom_audio +c356a3fdd49a1e015961678e837c12bb *tests/data/lavf/lavf.mxf_opatom_audio 102969 tests/data/lavf/lavf.mxf_opatom_audio tests/data/lavf/lavf.mxf_opatom_audio CRC=0xd155c6ff diff -Nru ffmpeg-4.2.2/tests/ref/lavf/rm ffmpeg-4.4/tests/ref/lavf/rm --- ffmpeg-4.2.2/tests/ref/lavf/rm 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/rm 2021-04-08 21:28:40.000000000 +0000 @@ -1,2 +1,2 @@ -e30681d05d6f3d24108d3614600bf116 *tests/data/lavf/lavf.rm +8dfb8d4556d61d3615e0d0012ffe540c *tests/data/lavf/lavf.rm 346424 tests/data/lavf/lavf.rm diff -Nru ffmpeg-4.2.2/tests/ref/lavf/ts ffmpeg-4.4/tests/ref/lavf/ts --- ffmpeg-4.2.2/tests/ref/lavf/ts 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/ts 2020-07-11 10:39:30.000000000 +0000 @@ -1,3 +1,3 @@ -38f4b14d43a0e416be8d598628997cbc *tests/data/lavf/lavf.ts -407020 tests/data/lavf/lavf.ts +371dc016eb3155116bea27e3b4eeb928 *tests/data/lavf/lavf.ts +389160 tests/data/lavf/lavf.ts tests/data/lavf/lavf.ts CRC=0x71287e25 diff -Nru ffmpeg-4.2.2/tests/ref/lavf/xbm ffmpeg-4.4/tests/ref/lavf/xbm --- ffmpeg-4.2.2/tests/ref/lavf/xbm 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf/xbm 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -0629055fd82366317c651a0af4bb82d7 *tests/data/images/xbm/02.xbm +83ed197cc88f382d9253365ffef70ec5 *tests/data/images/xbm/02.xbm tests/data/images/xbm/%02d.xbm CRC=0xc9a20204 -76411 tests/data/images/xbm/02.xbm +76410 tests/data/images/xbm/02.xbm diff -Nru ffmpeg-4.2.2/tests/ref/lavf-fate/av1.mkv ffmpeg-4.4/tests/ref/lavf-fate/av1.mkv --- ffmpeg-4.2.2/tests/ref/lavf-fate/av1.mkv 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf-fate/av1.mkv 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,3 @@ +77138a0e07ebd1c6ff2f69305e2f5c79 *tests/data/lavf-fate/lavf.av1.mkv +55653 tests/data/lavf-fate/lavf.av1.mkv +tests/data/lavf-fate/lavf.av1.mkv CRC=0x7c27cc15 diff -Nru ffmpeg-4.2.2/tests/ref/lavf-fate/av1.mp4 ffmpeg-4.4/tests/ref/lavf-fate/av1.mp4 --- ffmpeg-4.2.2/tests/ref/lavf-fate/av1.mp4 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf-fate/av1.mp4 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,3 @@ +d6afef355cf1bcf1a71b9cfb98c32fba *tests/data/lavf-fate/lavf.av1.mp4 +55976 tests/data/lavf-fate/lavf.av1.mp4 +tests/data/lavf-fate/lavf.av1.mp4 CRC=0x7c27cc15 diff -Nru ffmpeg-4.2.2/tests/ref/lavf-fate/h264.mp4 ffmpeg-4.4/tests/ref/lavf-fate/h264.mp4 --- ffmpeg-4.2.2/tests/ref/lavf-fate/h264.mp4 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf-fate/h264.mp4 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,3 @@ +fe299ea5205b71a48281f917b1256a5d *tests/data/lavf-fate/lavf.h264.mp4 +547928 tests/data/lavf-fate/lavf.h264.mp4 +tests/data/lavf-fate/lavf.h264.mp4 CRC=0x9da2c999 diff -Nru ffmpeg-4.2.2/tests/ref/lavf-fate/vp8.ogg ffmpeg-4.4/tests/ref/lavf-fate/vp8.ogg --- ffmpeg-4.2.2/tests/ref/lavf-fate/vp8.ogg 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/lavf-fate/vp8.ogg 2021-04-08 21:28:40.000000000 +0000 @@ -1,3 +1,3 @@ -c56d8dce728d46d4f0ab4c7cc9f86abc *tests/data/lavf-fate/lavf.vp8.ogg +20f1e9b1714513a0ba85ca636e818784 *tests/data/lavf-fate/lavf.vp8.ogg 95009 tests/data/lavf-fate/lavf.vp8.ogg -tests/data/lavf-fate/lavf.vp8.ogg CRC=0x8c067a66 +tests/data/lavf-fate/lavf.vp8.ogg CRC=0xa5857a66 diff -Nru ffmpeg-4.2.2/tests/ref/seek/acodec-adpcm-swf ffmpeg-4.4/tests/ref/seek/acodec-adpcm-swf --- ffmpeg-4.2.2/tests/ref/seek/acodec-adpcm-swf 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/seek/acodec-adpcm-swf 2021-04-08 21:28:40.000000000 +0000 @@ -1,49 +1,49 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 4101 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 4101 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 1.858000 pts: 1.858000 pos: 82956 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.858000 pts: 1.858000 pos: 82536 size: 4101 ret: 0 st: 0 flags:0 ts: 0.788000 -ret: 0 st: 0 flags:1 dts: 0.789000 pts: 0.789000 pos: 35369 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.836000 pts: 0.836000 pos: 37249 size: 4101 ret:-1 st: 0 flags:1 ts:-0.317000 ret: 0 st:-1 flags:0 ts: 2.576668 -ret: 0 st: 0 flags:1 dts: 2.601000 pts: 2.601000 pos: 116060 size: 2053 +ret: 0 st: 0 flags:1 dts: 2.601000 pts: 2.601000 pos: 115472 size: 4101 ret: 0 st:-1 flags:1 ts: 1.470835 -ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 64335 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.393000 pts: 1.393000 pos: 61951 size: 4101 ret: 0 st: 0 flags:0 ts: 0.365000 -ret: 0 st: 0 flags:1 dts: 0.372000 pts: 0.372000 pos: 16748 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.372000 pts: 0.372000 pos: 16664 size: 4101 ret:-1 st: 0 flags:1 ts:-0.741000 ret: 0 st:-1 flags:0 ts: 2.153336 -ret: 0 st: 0 flags:1 dts: 2.183000 pts: 2.183000 pos: 97439 size: 2053 +ret: 0 st: 0 flags:1 dts: 2.229000 pts: 2.229000 pos: 99004 size: 4101 ret: 0 st:-1 flags:1 ts: 1.047503 -ret: 0 st: 0 flags:1 dts: 1.022000 pts: 1.022000 pos: 45714 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.022000 pts: 1.022000 pos: 45483 size: 4101 ret: 0 st: 0 flags:0 ts:-0.058000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 4101 ret: 0 st: 0 flags:1 ts: 2.836000 -ret: 0 st: 0 flags:1 dts: 2.833000 pts: 2.833000 pos: 126405 size: 2053 +ret: 0 st: 0 flags:1 dts: 2.786000 pts: 2.786000 pos: 123706 size: 4101 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 1.765000 pts: 1.765000 pos: 78818 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.765000 pts: 1.765000 pos: 78419 size: 4101 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.604000 pts: 0.604000 pos: 27093 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.557000 pts: 0.557000 pos: 24898 size: 4101 ret: 0 st: 0 flags:0 ts:-0.482000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 4101 ret: 0 st: 0 flags:1 ts: 2.413000 -ret: 0 st: 0 flags:1 dts: 2.368000 pts: 2.368000 pos: 105715 size: 2053 +ret: 0 st: 0 flags:1 dts: 2.322000 pts: 2.322000 pos: 103121 size: 4101 ret: 0 st:-1 flags:0 ts: 1.306672 -ret: 0 st: 0 flags:1 dts: 1.347000 pts: 1.347000 pos: 60197 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.393000 pts: 1.393000 pos: 61951 size: 4101 ret: 0 st:-1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.186000 pts: 0.186000 pos: 8472 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.186000 pts: 0.186000 pos: 8430 size: 4101 ret: 0 st: 0 flags:0 ts:-0.905000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 4101 ret: 0 st: 0 flags:1 ts: 1.989000 -ret: 0 st: 0 flags:1 dts: 1.950000 pts: 1.950000 pos: 87094 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.950000 pts: 1.950000 pos: 86653 size: 4101 ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.929000 pts: 0.929000 pos: 41576 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.929000 pts: 0.929000 pos: 41366 size: 4101 ret:-1 st:-1 flags:1 ts:-0.222493 ret: 0 st: 0 flags:0 ts: 2.672000 -ret: 0 st: 0 flags:1 dts: 2.694000 pts: 2.694000 pos: 120198 size: 2053 +ret: 0 st: 0 flags:1 dts: 2.694000 pts: 2.694000 pos: 119589 size: 4101 ret: 0 st: 0 flags:1 ts: 1.566000 -ret: 0 st: 0 flags:1 dts: 1.533000 pts: 1.533000 pos: 68473 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.486000 pts: 1.486000 pos: 66068 size: 4101 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.464000 pts: 0.464000 pos: 20886 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.464000 pts: 0.464000 pos: 20781 size: 4101 ret:-1 st:-1 flags:1 ts:-0.645825 diff -Nru ffmpeg-4.2.2/tests/ref/seek/acodec-adpcm-swf-trellis ffmpeg-4.4/tests/ref/seek/acodec-adpcm-swf-trellis --- ffmpeg-4.2.2/tests/ref/seek/acodec-adpcm-swf-trellis 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/seek/acodec-adpcm-swf-trellis 2021-04-08 21:28:40.000000000 +0000 @@ -1,49 +1,49 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 4101 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 4101 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 1.858000 pts: 1.858000 pos: 82956 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.858000 pts: 1.858000 pos: 82536 size: 4101 ret: 0 st: 0 flags:0 ts: 0.788000 -ret: 0 st: 0 flags:1 dts: 0.789000 pts: 0.789000 pos: 35369 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.836000 pts: 0.836000 pos: 37249 size: 4101 ret:-1 st: 0 flags:1 ts:-0.317000 ret: 0 st:-1 flags:0 ts: 2.576668 -ret: 0 st: 0 flags:1 dts: 2.601000 pts: 2.601000 pos: 116060 size: 2053 +ret: 0 st: 0 flags:1 dts: 2.601000 pts: 2.601000 pos: 115472 size: 4101 ret: 0 st:-1 flags:1 ts: 1.470835 -ret: 0 st: 0 flags:1 dts: 1.440000 pts: 1.440000 pos: 64335 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.393000 pts: 1.393000 pos: 61951 size: 4101 ret: 0 st: 0 flags:0 ts: 0.365000 -ret: 0 st: 0 flags:1 dts: 0.372000 pts: 0.372000 pos: 16748 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.372000 pts: 0.372000 pos: 16664 size: 4101 ret:-1 st: 0 flags:1 ts:-0.741000 ret: 0 st:-1 flags:0 ts: 2.153336 -ret: 0 st: 0 flags:1 dts: 2.183000 pts: 2.183000 pos: 97439 size: 2053 +ret: 0 st: 0 flags:1 dts: 2.229000 pts: 2.229000 pos: 99004 size: 4101 ret: 0 st:-1 flags:1 ts: 1.047503 -ret: 0 st: 0 flags:1 dts: 1.022000 pts: 1.022000 pos: 45714 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.022000 pts: 1.022000 pos: 45483 size: 4101 ret: 0 st: 0 flags:0 ts:-0.058000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 4101 ret: 0 st: 0 flags:1 ts: 2.836000 -ret: 0 st: 0 flags:1 dts: 2.833000 pts: 2.833000 pos: 126405 size: 2053 +ret: 0 st: 0 flags:1 dts: 2.786000 pts: 2.786000 pos: 123706 size: 4101 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 1.765000 pts: 1.765000 pos: 78818 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.765000 pts: 1.765000 pos: 78419 size: 4101 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.604000 pts: 0.604000 pos: 27093 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.557000 pts: 0.557000 pos: 24898 size: 4101 ret: 0 st: 0 flags:0 ts:-0.482000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 4101 ret: 0 st: 0 flags:1 ts: 2.413000 -ret: 0 st: 0 flags:1 dts: 2.368000 pts: 2.368000 pos: 105715 size: 2053 +ret: 0 st: 0 flags:1 dts: 2.322000 pts: 2.322000 pos: 103121 size: 4101 ret: 0 st:-1 flags:0 ts: 1.306672 -ret: 0 st: 0 flags:1 dts: 1.347000 pts: 1.347000 pos: 60197 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.393000 pts: 1.393000 pos: 61951 size: 4101 ret: 0 st:-1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.186000 pts: 0.186000 pos: 8472 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.186000 pts: 0.186000 pos: 8430 size: 4101 ret: 0 st: 0 flags:0 ts:-0.905000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 196 size: 4101 ret: 0 st: 0 flags:1 ts: 1.989000 -ret: 0 st: 0 flags:1 dts: 1.950000 pts: 1.950000 pos: 87094 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.950000 pts: 1.950000 pos: 86653 size: 4101 ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 0.929000 pts: 0.929000 pos: 41576 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.929000 pts: 0.929000 pos: 41366 size: 4101 ret:-1 st:-1 flags:1 ts:-0.222493 ret: 0 st: 0 flags:0 ts: 2.672000 -ret: 0 st: 0 flags:1 dts: 2.694000 pts: 2.694000 pos: 120198 size: 2053 +ret: 0 st: 0 flags:1 dts: 2.694000 pts: 2.694000 pos: 119589 size: 4101 ret: 0 st: 0 flags:1 ts: 1.566000 -ret: 0 st: 0 flags:1 dts: 1.533000 pts: 1.533000 pos: 68473 size: 2053 +ret: 0 st: 0 flags:1 dts: 1.486000 pts: 1.486000 pos: 66068 size: 4101 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.464000 pts: 0.464000 pos: 20886 size: 2053 +ret: 0 st: 0 flags:1 dts: 0.464000 pts: 0.464000 pos: 20781 size: 4101 ret:-1 st:-1 flags:1 ts:-0.645825 diff -Nru ffmpeg-4.2.2/tests/ref/seek/lavf-al ffmpeg-4.4/tests/ref/seek/lavf-al --- ffmpeg-4.2.2/tests/ref/seek/lavf-al 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/seek/lavf-al 2021-04-08 21:28:40.000000000 +0000 @@ -7,22 +7,20 @@ ret: 0 st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos: 17383 size: 882 ret: 0 st: 0 flags:1 ts:-0.317506 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 -ret: 0 st:-1 flags:0 ts: 2.576668 -ret:-EOF +ret:-1 st:-1 flags:0 ts: 2.576668 ret: 0 st:-1 flags:1 ts: 1.470835 ret: 0 st: 0 flags:1 dts: 1.470839 pts: 1.470839 pos: 32432 size: 882 ret: 0 st: 0 flags:0 ts: 0.364989 ret: 0 st: 0 flags:1 dts: 0.364989 pts: 0.364989 pos: 8048 size: 882 ret: 0 st: 0 flags:1 ts:-0.740816 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 -ret: 0 st:-1 flags:0 ts: 2.153336 -ret:-EOF +ret:-1 st:-1 flags:0 ts: 2.153336 ret: 0 st:-1 flags:1 ts: 1.047503 ret: 0 st: 0 flags:1 dts: 1.047483 pts: 1.047483 pos: 23097 size: 882 ret: 0 st: 0 flags:0 ts:-0.058322 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st: 0 flags:1 ts: 2.835828 -ret:-EOF +ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos: 43218 size: 882 ret: 0 st:-1 flags:0 ts: 1.730004 ret: 0 st: 0 flags:1 dts: 1.730023 pts: 1.730023 pos: 38147 size: 882 ret: 0 st:-1 flags:1 ts: 0.624171 @@ -30,7 +28,7 @@ ret: 0 st: 0 flags:0 ts:-0.481678 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st: 0 flags:1 ts: 2.412517 -ret:-EOF +ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos: 43218 size: 882 ret: 0 st:-1 flags:0 ts: 1.306672 ret: 0 st: 0 flags:1 dts: 1.306667 pts: 1.306667 pos: 28812 size: 882 ret: 0 st:-1 flags:1 ts: 0.200839 @@ -43,8 +41,7 @@ ret: 0 st: 0 flags:1 dts: 0.883356 pts: 0.883356 pos: 19478 size: 882 ret: 0 st:-1 flags:1 ts:-0.222493 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 -ret: 0 st: 0 flags:0 ts: 2.671655 -ret:-EOF +ret:-1 st: 0 flags:0 ts: 2.671655 ret: 0 st: 0 flags:1 ts: 1.565850 ret: 0 st: 0 flags:1 dts: 1.565850 pts: 1.565850 pos: 34527 size: 882 ret: 0 st:-1 flags:0 ts: 0.460008 diff -Nru ffmpeg-4.2.2/tests/ref/seek/lavf-dv ffmpeg-4.4/tests/ref/seek/lavf-dv --- ffmpeg-4.2.2/tests/ref/seek/lavf-dv 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/seek/lavf-dv 2021-04-08 21:28:40.000000000 +0000 @@ -7,9 +7,9 @@ ret: 0 st: 0 flags:1 dts: 0.800000 pts: 0.800000 pos:2880000 size:144000 ret: 0 st: 0 flags:1 ts:-0.320000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 1 flags:0 ts: 2.576667 +ret: 0 st: 1 flags:0 ts: 2.560000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 1 flags:1 ts: 1.470833 +ret: 0 st: 1 flags:1 ts: 1.480000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 ret: 0 st:-1 flags:0 ts: 0.365002 ret: 0 st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos:1296000 size:144000 @@ -19,9 +19,9 @@ ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 ret: 0 st: 0 flags:1 ts: 1.040000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 1 flags:0 ts:-0.058333 +ret: 0 st: 1 flags:0 ts:-0.040000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 1 flags:1 ts: 2.835833 +ret: 0 st: 1 flags:1 ts: 2.840000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 ret: 0 st:-1 flags:0 ts: 1.730004 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 @@ -31,10 +31,10 @@ ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st: 0 flags:1 ts: 2.400000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 1 flags:0 ts: 1.306667 -ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 1 flags:1 ts: 0.200833 +ret: 0 st: 1 flags:0 ts: 1.320000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 +ret: 0 st: 1 flags:1 ts: 0.200000 +ret: 0 st: 0 flags:1 dts: 0.200000 pts: 0.200000 pos: 720000 size:144000 ret: 0 st:-1 flags:0 ts:-0.904994 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 ret: 0 st:-1 flags:1 ts: 1.989173 @@ -43,9 +43,9 @@ ret: 0 st: 0 flags:1 dts: 0.880000 pts: 0.880000 pos:3168000 size:144000 ret: 0 st: 0 flags:1 ts:-0.240000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size:144000 -ret: 0 st: 1 flags:0 ts: 2.671667 +ret: 0 st: 1 flags:0 ts: 2.680000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 -ret: 0 st: 1 flags:1 ts: 1.565833 +ret: 0 st: 1 flags:1 ts: 1.560000 ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:3456000 size:144000 ret: 0 st:-1 flags:0 ts: 0.460008 ret: 0 st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos:1728000 size:144000 diff -Nru ffmpeg-4.2.2/tests/ref/seek/lavf-mkv ffmpeg-4.4/tests/ref/seek/lavf-mkv --- ffmpeg-4.2.2/tests/ref/seek/lavf-mkv 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/seek/lavf-mkv 2020-07-11 10:39:30.000000000 +0000 @@ -1,48 +1,48 @@ -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 803 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 680 size: 208 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1019 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 896 size: 27837 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292435 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292312 size: 27834 ret: 0 st: 0 flags:0 ts: 0.788000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292435 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292312 size: 27834 ret: 0 st: 0 flags:1 ts:-0.317000 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1019 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 896 size: 27837 ret:-1 st: 1 flags:0 ts: 2.577000 ret: 0 st: 1 flags:1 ts: 1.471000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320276 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320153 size: 209 ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146987 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146864 size: 27925 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1019 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 896 size: 27837 ret:-1 st: 0 flags:0 ts: 2.153000 ret: 0 st: 0 flags:1 ts: 1.048000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292435 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292312 size: 27834 ret: 0 st: 1 flags:0 ts:-0.058000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 803 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 680 size: 208 ret: 0 st: 1 flags:1 ts: 2.836000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320276 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320153 size: 209 ret:-1 st:-1 flags:0 ts: 1.730004 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146987 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146864 size: 27925 ret: 0 st: 0 flags:0 ts:-0.482000 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1019 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 896 size: 27837 ret: 0 st: 0 flags:1 ts: 2.413000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292435 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292312 size: 27834 ret:-1 st: 1 flags:0 ts: 1.307000 ret: 0 st: 1 flags:1 ts: 0.201000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 803 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 680 size: 208 ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1019 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 896 size: 27837 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292435 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292312 size: 27834 ret: 0 st: 0 flags:0 ts: 0.883000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292435 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292312 size: 27834 ret: 0 st: 0 flags:1 ts:-0.222000 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1019 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 896 size: 27837 ret:-1 st: 1 flags:0 ts: 2.672000 ret: 0 st: 1 flags:1 ts: 1.566000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320276 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320153 size: 209 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146987 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146864 size: 27925 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1019 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 896 size: 27837 diff -Nru ffmpeg-4.2.2/tests/ref/seek/lavf-ts ffmpeg-4.4/tests/ref/seek/lavf-ts --- ffmpeg-4.2.2/tests/ref/seek/lavf-ts 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tests/ref/seek/lavf-ts 2020-07-11 10:39:30.000000000 +0000 @@ -2,51 +2,51 @@ ret: 0 st:-1 flags:0 ts:-1.000000 ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 1.880000 pts: 1.920000 pos: 189692 size: 24786 +ret: 0 st: 0 flags:1 dts: 1.880000 pts: 1.920000 pos: 181420 size: 24786 ret: 0 st: 0 flags:0 ts: 0.788333 ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801 ret: 0 st: 0 flags:1 ts:-0.317500 ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801 ret: 0 st: 1 flags:0 ts: 2.576667 -ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size: 209 +ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 386716 size: 209 ret: 0 st: 1 flags:1 ts: 1.470833 -ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size: 208 +ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 152844 size: 208 ret: 0 st:-1 flags:0 ts: 0.365002 ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801 ret: 0 st:-1 flags:1 ts:-0.740831 ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801 ret: 0 st: 0 flags:0 ts: 2.153333 -ret: 0 st: 1 flags:1 dts: 1.794811 pts: 1.794811 pos: 322608 size: 209 +ret: 0 st: 1 flags:1 dts: 1.794811 pts: 1.794811 pos: 308508 size: 209 ret: 0 st: 0 flags:1 ts: 1.047500 ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801 ret: 0 st: 1 flags:0 ts:-0.058333 -ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size: 208 +ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 152844 size: 208 ret: 0 st: 1 flags:1 ts: 2.835833 -ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size: 209 +ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 386716 size: 209 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size: 208 +ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 152844 size: 208 ret: 0 st:-1 flags:1 ts: 0.624171 ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801 ret: 0 st: 0 flags:0 ts:-0.481667 ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801 ret: 0 st: 0 flags:1 ts: 2.412500 -ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size: 209 +ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 386716 size: 209 ret: 0 st: 1 flags:0 ts: 1.306667 -ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size: 208 +ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 152844 size: 208 ret: 0 st: 1 flags:1 ts: 0.200844 -ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size: 208 +ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 152844 size: 208 ret: 0 st:-1 flags:0 ts:-0.904994 ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 0 flags:0 dts: 1.960000 pts: 2.000000 pos: 235000 size: 15019 +ret: 0 st: 0 flags:0 dts: 1.960000 pts: 2.000000 pos: 224848 size: 15019 ret: 0 st: 0 flags:0 ts: 0.883344 ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801 ret: 0 st: 0 flags:1 ts:-0.222489 ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801 ret: 0 st: 1 flags:0 ts: 2.671678 -ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size: 209 +ret: 0 st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 386716 size: 209 ret: 0 st: 1 flags:1 ts: 1.565844 -ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size: 208 +ret: 0 st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 152844 size: 208 ret: 0 st:-1 flags:0 ts: 0.460008 ret: 0 st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos: 564 size: 24801 ret: 0 st:-1 flags:1 ts:-0.645825 diff -Nru ffmpeg-4.2.2/tests/ref/seek/lavf-ul ffmpeg-4.4/tests/ref/seek/lavf-ul --- ffmpeg-4.2.2/tests/ref/seek/lavf-ul 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/seek/lavf-ul 2021-04-08 21:28:40.000000000 +0000 @@ -7,22 +7,20 @@ ret: 0 st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos: 17383 size: 882 ret: 0 st: 0 flags:1 ts:-0.317506 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 -ret: 0 st:-1 flags:0 ts: 2.576668 -ret:-EOF +ret:-1 st:-1 flags:0 ts: 2.576668 ret: 0 st:-1 flags:1 ts: 1.470835 ret: 0 st: 0 flags:1 dts: 1.470839 pts: 1.470839 pos: 32432 size: 882 ret: 0 st: 0 flags:0 ts: 0.364989 ret: 0 st: 0 flags:1 dts: 0.364989 pts: 0.364989 pos: 8048 size: 882 ret: 0 st: 0 flags:1 ts:-0.740816 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 -ret: 0 st:-1 flags:0 ts: 2.153336 -ret:-EOF +ret:-1 st:-1 flags:0 ts: 2.153336 ret: 0 st:-1 flags:1 ts: 1.047503 ret: 0 st: 0 flags:1 dts: 1.047483 pts: 1.047483 pos: 23097 size: 882 ret: 0 st: 0 flags:0 ts:-0.058322 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st: 0 flags:1 ts: 2.835828 -ret:-EOF +ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos: 43218 size: 882 ret: 0 st:-1 flags:0 ts: 1.730004 ret: 0 st: 0 flags:1 dts: 1.730023 pts: 1.730023 pos: 38147 size: 882 ret: 0 st:-1 flags:1 ts: 0.624171 @@ -30,7 +28,7 @@ ret: 0 st: 0 flags:0 ts:-0.481678 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 ret: 0 st: 0 flags:1 ts: 2.412517 -ret:-EOF +ret: 0 st: 0 flags:1 dts: 1.960000 pts: 1.960000 pos: 43218 size: 882 ret: 0 st:-1 flags:0 ts: 1.306672 ret: 0 st: 0 flags:1 dts: 1.306667 pts: 1.306667 pos: 28812 size: 882 ret: 0 st:-1 flags:1 ts: 0.200839 @@ -43,8 +41,7 @@ ret: 0 st: 0 flags:1 dts: 0.883356 pts: 0.883356 pos: 19478 size: 882 ret: 0 st:-1 flags:1 ts:-0.222493 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 0 size: 882 -ret: 0 st: 0 flags:0 ts: 2.671655 -ret:-EOF +ret:-1 st: 0 flags:0 ts: 2.671655 ret: 0 st: 0 flags:1 ts: 1.565850 ret: 0 st: 0 flags:1 dts: 1.565850 pts: 1.565850 pos: 34527 size: 882 ret: 0 st:-1 flags:0 ts: 0.460008 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-dnxhd-1080i-colr ffmpeg-4.4/tests/ref/vsynth/vsynth1-dnxhd-1080i-colr --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-dnxhd-1080i-colr 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth1-dnxhd-1080i-colr 2020-07-11 10:39:30.000000000 +0000 @@ -1,4 +1,4 @@ -2caca2edcb519c88543c38e129ded03b *tests/data/fate/vsynth1-dnxhd-1080i-colr.mov +5571f4ff9e29d352a7e373a14a9ed2ed *tests/data/fate/vsynth1-dnxhd-1080i-colr.mov 3031929 tests/data/fate/vsynth1-dnxhd-1080i-colr.mov 6f2d5429ffc4529a76acfeb28b560542 *tests/data/fate/vsynth1-dnxhd-1080i-colr.out.rawvideo stddev: 5.65 PSNR: 33.09 MAXDIFF: 55 bytes: 7603200/ 760320 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-dv-fhd ffmpeg-4.4/tests/ref/vsynth/vsynth1-dv-fhd --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-dv-fhd 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth1-dv-fhd 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,4 @@ +74315a8678d12c7f592c02990dc8952d *tests/data/fate/vsynth1-dv-fhd.dv +28800000 tests/data/fate/vsynth1-dv-fhd.dv +c95b309bc128b162e5c8241374eb66a9 *tests/data/fate/vsynth1-dv-fhd.out.rawvideo +stddev: 2.53 PSNR: 40.03 MAXDIFF: 35 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-dv-hd ffmpeg-4.4/tests/ref/vsynth/vsynth1-dv-hd --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-dv-hd 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth1-dv-hd 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,4 @@ +b2bcafc74dec5f9ca516cb25dd07459b *tests/data/fate/vsynth1-dv-hd.dv +14400000 tests/data/fate/vsynth1-dv-hd.dv +34b78cf725346c7f819c9d6209b8299a *tests/data/fate/vsynth1-dv-hd.out.rawvideo +stddev: 4.30 PSNR: 35.45 MAXDIFF: 74 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-ffv1-v3-rgb48 ffmpeg-4.4/tests/ref/vsynth/vsynth1-ffv1-v3-rgb48 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-ffv1-v3-rgb48 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth1-ffv1-v3-rgb48 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ f457dba7d58f0c28aedcfef518758d23 *tests/data/fate/vsynth1-ffv1-v3-rgb48.avi 16858304 tests/data/fate/vsynth1-ffv1-v3-rgb48.avi -b91ddc45eb70b4377dc7439e16733232 *tests/data/fate/vsynth1-ffv1-v3-rgb48.out.rawvideo -stddev: 3.58 PSNR: 37.04 MAXDIFF: 75 bytes: 7603200/ 7603200 +e2542b84193de462b04da530ab941f31 *tests/data/fate/vsynth1-ffv1-v3-rgb48.out.rawvideo +stddev: 3.52 PSNR: 37.19 MAXDIFF: 74 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-jpeg2000 ffmpeg-4.4/tests/ref/vsynth/vsynth1-jpeg2000 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-jpeg2000 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth1-jpeg2000 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -d2a06ad916711d29b30977a06335bb76 *tests/data/fate/vsynth1-jpeg2000.avi -2265698 tests/data/fate/vsynth1-jpeg2000.avi -15a8e49f6fd014193bbafd72f84936c7 *tests/data/fate/vsynth1-jpeg2000.out.rawvideo -stddev: 5.36 PSNR: 33.55 MAXDIFF: 61 bytes: 7603200/ 7603200 +95add005faf68fcf8f16e86eab079ca2 *tests/data/fate/vsynth1-jpeg2000.avi +2263192 tests/data/fate/vsynth1-jpeg2000.avi +b7f48a8965f78011c76483277befc6fc *tests/data/fate/vsynth1-jpeg2000.out.rawvideo +stddev: 5.35 PSNR: 33.56 MAXDIFF: 59 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-jpeg2000-97 ffmpeg-4.4/tests/ref/vsynth/vsynth1-jpeg2000-97 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-jpeg2000-97 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth1-jpeg2000-97 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -8bb707e596f97451fd325dec2dd610a7 *tests/data/fate/vsynth1-jpeg2000-97.avi -3654620 tests/data/fate/vsynth1-jpeg2000-97.avi -5073771a78e1f5366a7eb0df341662fc *tests/data/fate/vsynth1-jpeg2000-97.out.rawvideo +e4d03b2e3c03e56c7f831b1e662c4031 *tests/data/fate/vsynth1-jpeg2000-97.avi +3643928 tests/data/fate/vsynth1-jpeg2000-97.avi +a2262f1da2f49bc196b780a6b47ec4e8 *tests/data/fate/vsynth1-jpeg2000-97.out.rawvideo stddev: 4.23 PSNR: 35.59 MAXDIFF: 53 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-mpeg4 ffmpeg-4.4/tests/ref/vsynth/vsynth1-mpeg4 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-mpeg4 2016-03-29 02:25:36.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth1-mpeg4 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -b4e8871c504a22c8c874c7e845b73da7 *tests/data/fate/vsynth1-mpeg4.mp4 -540085 tests/data/fate/vsynth1-mpeg4.mp4 +a7e57333c57e0f8a551374b063a41d9e *tests/data/fate/vsynth1-mpeg4.mp4 +540105 tests/data/fate/vsynth1-mpeg4.mp4 f80ec173d37f2f91add031e95579a220 *tests/data/fate/vsynth1-mpeg4.out.rawvideo stddev: 7.97 PSNR: 30.10 MAXDIFF: 105 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-r210 ffmpeg-4.4/tests/ref/vsynth/vsynth1-r210 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth1-r210 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth1-r210 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ 1a522a30ddd8c2865a731a5659001717 *tests/data/fate/vsynth1-r210.avi 22125252 tests/data/fate/vsynth1-r210.avi -b6444935d6c4d8c75fe63d5978f5b457 *tests/data/fate/vsynth1-r210.out.rawvideo -stddev: 3.73 PSNR: 36.68 MAXDIFF: 48 bytes: 7603200/ 7603200 +d118531accba75fb3b6ebf2a3a4a2e8e *tests/data/fate/vsynth1-r210.out.rawvideo +stddev: 3.70 PSNR: 36.77 MAXDIFF: 47 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-dnxhd-1080i-colr ffmpeg-4.4/tests/ref/vsynth/vsynth2-dnxhd-1080i-colr --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-dnxhd-1080i-colr 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth2-dnxhd-1080i-colr 2020-07-11 10:39:30.000000000 +0000 @@ -1,4 +1,4 @@ -e7e5cd8d6d1596596ded1007f37c3193 *tests/data/fate/vsynth2-dnxhd-1080i-colr.mov +eee674d012c850c1d2bb5e816b668cdf *tests/data/fate/vsynth2-dnxhd-1080i-colr.mov 3031929 tests/data/fate/vsynth2-dnxhd-1080i-colr.mov ec40a8014b819d02951b2f06bee7b514 *tests/data/fate/vsynth2-dnxhd-1080i-colr.out.rawvideo stddev: 1.54 PSNR: 44.33 MAXDIFF: 33 bytes: 7603200/ 760320 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-dv-fhd ffmpeg-4.4/tests/ref/vsynth/vsynth2-dv-fhd --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-dv-fhd 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth2-dv-fhd 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,4 @@ +1f96ce7c1a5f09ec9d30c51c7271cf77 *tests/data/fate/vsynth2-dv-fhd.dv +28800000 tests/data/fate/vsynth2-dv-fhd.dv +cff30e2430730522bf67c6d94cf1352e *tests/data/fate/vsynth2-dv-fhd.out.rawvideo +stddev: 1.16 PSNR: 46.82 MAXDIFF: 21 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-dv-hd ffmpeg-4.4/tests/ref/vsynth/vsynth2-dv-hd --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-dv-hd 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth2-dv-hd 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,4 @@ +a9a4c750f7720e83d538d36c318be787 *tests/data/fate/vsynth2-dv-hd.dv +14400000 tests/data/fate/vsynth2-dv-hd.dv +15dbe911532aca81c67bdd2846419027 *tests/data/fate/vsynth2-dv-hd.out.rawvideo +stddev: 1.75 PSNR: 43.26 MAXDIFF: 34 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-ffv1-v3-rgb48 ffmpeg-4.4/tests/ref/vsynth/vsynth2-ffv1-v3-rgb48 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-ffv1-v3-rgb48 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth2-ffv1-v3-rgb48 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ 99b39b0286428ccf9c788545dfccb49f *tests/data/fate/vsynth2-ffv1-v3-rgb48.avi 15089212 tests/data/fate/vsynth2-ffv1-v3-rgb48.avi -b7278d99ea84fe8becf02de773fee0a5 *tests/data/fate/vsynth2-ffv1-v3-rgb48.out.rawvideo -stddev: 1.43 PSNR: 44.97 MAXDIFF: 28 bytes: 7603200/ 7603200 +370aa3829b8e828e97ec777f04375b26 *tests/data/fate/vsynth2-ffv1-v3-rgb48.out.rawvideo +stddev: 1.24 PSNR: 46.23 MAXDIFF: 28 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-jpeg2000 ffmpeg-4.4/tests/ref/vsynth/vsynth2-jpeg2000 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-jpeg2000 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth2-jpeg2000 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -6c2f979e4a33a36f36aec86f2d464143 *tests/data/fate/vsynth2-jpeg2000.avi -1494516 tests/data/fate/vsynth2-jpeg2000.avi -36afd96d6e55bc83166fd615351ba366 *tests/data/fate/vsynth2-jpeg2000.out.rawvideo -stddev: 5.00 PSNR: 34.15 MAXDIFF: 59 bytes: 7603200/ 7603200 +8c8a68ca748190c71b3ea43e5ab7f502 *tests/data/fate/vsynth2-jpeg2000.avi +1538736 tests/data/fate/vsynth2-jpeg2000.avi +64fadc87447268cf90503cb294db7f61 *tests/data/fate/vsynth2-jpeg2000.out.rawvideo +stddev: 4.91 PSNR: 34.29 MAXDIFF: 55 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-jpeg2000-97 ffmpeg-4.4/tests/ref/vsynth/vsynth2-jpeg2000-97 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-jpeg2000-97 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth2-jpeg2000-97 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -2e43f004a55f4a55a19c4b79fc8e8743 *tests/data/fate/vsynth2-jpeg2000-97.avi -2448706 tests/data/fate/vsynth2-jpeg2000-97.avi -a6e2453118a0de135836a868b2ca0e60 *tests/data/fate/vsynth2-jpeg2000-97.out.rawvideo -stddev: 3.23 PSNR: 37.94 MAXDIFF: 29 bytes: 7603200/ 7603200 +c8f76055f59804ca72dbd66eb4db83a2 *tests/data/fate/vsynth2-jpeg2000-97.avi +2464138 tests/data/fate/vsynth2-jpeg2000-97.avi +1f63c8b065e847e4c63d57ce23442ea8 *tests/data/fate/vsynth2-jpeg2000-97.out.rawvideo +stddev: 3.21 PSNR: 37.99 MAXDIFF: 26 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-mpeg4 ffmpeg-4.4/tests/ref/vsynth/vsynth2-mpeg4 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-mpeg4 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth2-mpeg4 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -adbd883d1701beabd04522d003dafab6 *tests/data/fate/vsynth2-mpeg4.mp4 -159310 tests/data/fate/vsynth2-mpeg4.mp4 +b751a2d3b4e693ca39d4fafa0175fc9d *tests/data/fate/vsynth2-mpeg4.mp4 +159330 tests/data/fate/vsynth2-mpeg4.mp4 2645405bc5350acc85ad72f3352f5135 *tests/data/fate/vsynth2-mpeg4.out.rawvideo stddev: 6.02 PSNR: 32.53 MAXDIFF: 89 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-r210 ffmpeg-4.4/tests/ref/vsynth/vsynth2-r210 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth2-r210 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth2-r210 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ 9a27c0c96f9e658d610d2590b61416a1 *tests/data/fate/vsynth2-r210.avi 22125252 tests/data/fate/vsynth2-r210.avi -d43196c64fd611f6e9c046e0ef3e570e *tests/data/fate/vsynth2-r210.out.rawvideo -stddev: 1.37 PSNR: 45.34 MAXDIFF: 14 bytes: 7603200/ 7603200 +8c370aac5d744c870049aed0741e20a3 *tests/data/fate/vsynth2-r210.out.rawvideo +stddev: 1.20 PSNR: 46.54 MAXDIFF: 14 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-dnxhd-1080i-colr ffmpeg-4.4/tests/ref/vsynth/vsynth3-dnxhd-1080i-colr --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-dnxhd-1080i-colr 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth3-dnxhd-1080i-colr 2020-07-11 10:39:30.000000000 +0000 @@ -1,4 +1,4 @@ -f5a7d7f837a750784458c60fb7b4d091 *tests/data/fate/vsynth3-dnxhd-1080i-colr.mov +92a2f67cf77abf3428fe2d4f53ba2027 *tests/data/fate/vsynth3-dnxhd-1080i-colr.mov 3031929 tests/data/fate/vsynth3-dnxhd-1080i-colr.mov f907fd2d48bedbc5283fbfc3fb9f61a0 *tests/data/fate/vsynth3-dnxhd-1080i-colr.out.rawvideo stddev: 6.92 PSNR: 31.32 MAXDIFF: 50 bytes: 86700/ 8670 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-dv-fhd ffmpeg-4.4/tests/ref/vsynth/vsynth3-dv-fhd --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-dv-fhd 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth3-dv-fhd 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,4 @@ +5b8b7f1dc31d7076af891e94c2e88c06 *tests/data/fate/vsynth3-dv-fhd.dv +28800000 tests/data/fate/vsynth3-dv-fhd.dv +a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-dv-fhd.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-dv-hd ffmpeg-4.4/tests/ref/vsynth/vsynth3-dv-hd --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-dv-hd 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth3-dv-hd 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,4 @@ +63512193a0da09e15815c1be1b9c4fa5 *tests/data/fate/vsynth3-dv-hd.dv +14400000 tests/data/fate/vsynth3-dv-hd.dv +a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-dv-hd.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-ffv1-v3-rgb48 ffmpeg-4.4/tests/ref/vsynth/vsynth3-ffv1-v3-rgb48 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-ffv1-v3-rgb48 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth3-ffv1-v3-rgb48 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ 3bec2f4381dc362c24d1bbc304d0af58 *tests/data/fate/vsynth3-ffv1-v3-rgb48.avi 244742 tests/data/fate/vsynth3-ffv1-v3-rgb48.avi -d37e1507abd3233e27b0b00441149ddc *tests/data/fate/vsynth3-ffv1-v3-rgb48.out.rawvideo -stddev: 3.52 PSNR: 37.19 MAXDIFF: 59 bytes: 86700/ 86700 +a3dd456a61aa1abcf4fc2bc9ffd0617a *tests/data/fate/vsynth3-ffv1-v3-rgb48.out.rawvideo +stddev: 3.48 PSNR: 37.30 MAXDIFF: 59 bytes: 86700/ 86700 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-jpeg2000 ffmpeg-4.4/tests/ref/vsynth/vsynth3-jpeg2000 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-jpeg2000 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth3-jpeg2000 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -0b8aa8113c10772cffff60f9c8ffd902 *tests/data/fate/vsynth3-jpeg2000.avi -65548 tests/data/fate/vsynth3-jpeg2000.avi -2d8bd94d558755c47d7e23fd9556e164 *tests/data/fate/vsynth3-jpeg2000.out.rawvideo -stddev: 5.48 PSNR: 33.34 MAXDIFF: 47 bytes: 86700/ 86700 +776bf3234cbf25002f129b89baab42ea *tests/data/fate/vsynth3-jpeg2000.avi +67400 tests/data/fate/vsynth3-jpeg2000.avi +098f5980667e1fcd50452b1dc1a74f61 *tests/data/fate/vsynth3-jpeg2000.out.rawvideo +stddev: 5.47 PSNR: 33.36 MAXDIFF: 48 bytes: 86700/ 86700 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-jpeg2000-97 ffmpeg-4.4/tests/ref/vsynth/vsynth3-jpeg2000-97 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-jpeg2000-97 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth3-jpeg2000-97 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -b6c88a623c3296ca945346d2203f0af0 *tests/data/fate/vsynth3-jpeg2000-97.avi -83870 tests/data/fate/vsynth3-jpeg2000-97.avi -0cd707bfb1bbe5312b00c094f695b1fa *tests/data/fate/vsynth3-jpeg2000-97.out.rawvideo -stddev: 4.52 PSNR: 35.02 MAXDIFF: 47 bytes: 86700/ 86700 +cd023db503f03ef72dd83e4617a90c7b *tests/data/fate/vsynth3-jpeg2000-97.avi +85606 tests/data/fate/vsynth3-jpeg2000-97.avi +8def36ad1413ab3a5c2af2e1af4603f9 *tests/data/fate/vsynth3-jpeg2000-97.out.rawvideo +stddev: 4.51 PSNR: 35.04 MAXDIFF: 47 bytes: 86700/ 86700 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-mpeg4 ffmpeg-4.4/tests/ref/vsynth/vsynth3-mpeg4 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-mpeg4 2016-03-29 02:25:36.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth3-mpeg4 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -ddcff996543900496f0b374a2d5cae74 *tests/data/fate/vsynth3-mpeg4.mp4 -26017 tests/data/fate/vsynth3-mpeg4.mp4 +7ca3bbb8bed55d558346d258f5bea440 *tests/data/fate/vsynth3-mpeg4.mp4 +26037 tests/data/fate/vsynth3-mpeg4.mp4 fc0d8c1e58d254031e6207dfcae8f867 *tests/data/fate/vsynth3-mpeg4.out.rawvideo stddev: 9.66 PSNR: 28.43 MAXDIFF: 79 bytes: 86700/ 86700 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-r210 ffmpeg-4.4/tests/ref/vsynth/vsynth3-r210 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth3-r210 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth3-r210 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ fd12f6dde75d0872ccf9012b342208de *tests/data/fate/vsynth3-r210.avi 442052 tests/data/fate/vsynth3-r210.avi -a2c4e460ebede1109bd794b1b7b05a1f *tests/data/fate/vsynth3-r210.out.rawvideo -stddev: 4.10 PSNR: 35.87 MAXDIFF: 48 bytes: 86700/ 86700 +e09fcdcbbd4a247c7ad16b74eecb1ec7 *tests/data/fate/vsynth3-r210.out.rawvideo +stddev: 4.07 PSNR: 35.93 MAXDIFF: 47 bytes: 86700/ 86700 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-dnxhd-1080i-colr ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-dnxhd-1080i-colr --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-dnxhd-1080i-colr 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-dnxhd-1080i-colr 2020-07-11 10:39:30.000000000 +0000 @@ -1,4 +1,4 @@ -3a681c0e174ccf85fe1504cdf8546788 *tests/data/fate/vsynth_lena-dnxhd-1080i-colr.mov +f80be8c3350ca8b22ae8aa8724b2ef20 *tests/data/fate/vsynth_lena-dnxhd-1080i-colr.mov 3031929 tests/data/fate/vsynth_lena-dnxhd-1080i-colr.mov ce4993a69ef55c8c4b18138716f17b6f *tests/data/fate/vsynth_lena-dnxhd-1080i-colr.out.rawvideo stddev: 1.33 PSNR: 45.59 MAXDIFF: 22 bytes: 7603200/ 760320 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-dv-fhd ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-dv-fhd --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-dv-fhd 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-dv-fhd 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,4 @@ +3a33e512f8b3f4213477c98d4e7e2559 *tests/data/fate/vsynth_lena-dv-fhd.dv +28800000 tests/data/fate/vsynth_lena-dv-fhd.dv +b97e0a057202359ef93f2ec0b9fdfec4 *tests/data/fate/vsynth_lena-dv-fhd.out.rawvideo +stddev: 1.03 PSNR: 47.80 MAXDIFF: 14 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-dv-hd ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-dv-hd --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-dv-hd 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-dv-hd 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,4 @@ +f17abb38ed2f416d57f3b956fae5dc82 *tests/data/fate/vsynth_lena-dv-hd.dv +14400000 tests/data/fate/vsynth_lena-dv-hd.dv +4db4175c80ea1f16b7ec303611b8873a *tests/data/fate/vsynth_lena-dv-hd.out.rawvideo +stddev: 1.49 PSNR: 44.66 MAXDIFF: 27 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-ffv1-v3-rgb48 ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-ffv1-v3-rgb48 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-ffv1-v3-rgb48 2018-11-01 18:34:28.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-ffv1-v3-rgb48 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ 294d4f9fdf53ba0fe9d224d28ba700f0 *tests/data/fate/vsynth_lena-ffv1-v3-rgb48.avi 13795036 tests/data/fate/vsynth_lena-ffv1-v3-rgb48.avi -7bd82d1860095ae1e10ec0ace9cb04b6 *tests/data/fate/vsynth_lena-ffv1-v3-rgb48.out.rawvideo -stddev: 0.91 PSNR: 48.91 MAXDIFF: 21 bytes: 7603200/ 7603200 +832a42fafb18d52b35422ae0f34fe48c *tests/data/fate/vsynth_lena-ffv1-v3-rgb48.out.rawvideo +stddev: 0.66 PSNR: 51.63 MAXDIFF: 21 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-jpeg2000 ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-jpeg2000 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-jpeg2000 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-jpeg2000 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -1f2cf6061c78905b8011091a9a7c425f *tests/data/fate/vsynth_lena-jpeg2000.avi -1138054 tests/data/fate/vsynth_lena-jpeg2000.avi -955653ca7a08447e7b1501b444f24562 *tests/data/fate/vsynth_lena-jpeg2000.out.rawvideo -stddev: 4.40 PSNR: 35.25 MAXDIFF: 58 bytes: 7603200/ 7603200 +b8aaa45236f77a2a626791d462fd8ac1 *tests/data/fate/vsynth_lena-jpeg2000.avi +1188886 tests/data/fate/vsynth_lena-jpeg2000.avi +39a2c5b61cd0cf2821c6fb4cceba2fa8 *tests/data/fate/vsynth_lena-jpeg2000.out.rawvideo +stddev: 4.30 PSNR: 35.45 MAXDIFF: 45 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-jpeg2000-97 ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-jpeg2000-97 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-jpeg2000-97 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-jpeg2000-97 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -e5a756e97910420c90e76259c56261cb *tests/data/fate/vsynth_lena-jpeg2000-97.avi -1918956 tests/data/fate/vsynth_lena-jpeg2000-97.avi -93a4ba0c230f2430a813df594676e58a *tests/data/fate/vsynth_lena-jpeg2000-97.out.rawvideo -stddev: 2.84 PSNR: 39.04 MAXDIFF: 28 bytes: 7603200/ 7603200 +b2d9525433c6300674f504922d762437 *tests/data/fate/vsynth_lena-jpeg2000-97.avi +1937232 tests/data/fate/vsynth_lena-jpeg2000-97.avi +1b97333a8dc115a5ba609b0070d89d4d *tests/data/fate/vsynth_lena-jpeg2000-97.out.rawvideo +stddev: 2.82 PSNR: 39.10 MAXDIFF: 24 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-mpeg4 ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-mpeg4 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-mpeg4 2017-12-31 22:35:50.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-mpeg4 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ -4a029747434d24d128b078a5e6aa1e88 *tests/data/fate/vsynth_lena-mpeg4.mp4 -119722 tests/data/fate/vsynth_lena-mpeg4.mp4 +a0d0edee19f6658d0e93d294e32a1a6f *tests/data/fate/vsynth_lena-mpeg4.mp4 +119742 tests/data/fate/vsynth_lena-mpeg4.mp4 9a1e085d9e488c5ead0c940c9612a37a *tests/data/fate/vsynth_lena-mpeg4.out.rawvideo stddev: 5.34 PSNR: 33.57 MAXDIFF: 83 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-r210 ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-r210 --- ffmpeg-4.2.2/tests/ref/vsynth/vsynth_lena-r210 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tests/ref/vsynth/vsynth_lena-r210 2021-04-08 21:28:40.000000000 +0000 @@ -1,4 +1,4 @@ 61fd53566d99b725e75212747b35893f *tests/data/fate/vsynth_lena-r210.avi 22125252 tests/data/fate/vsynth_lena-r210.avi -4b7425191bb6a7fc4ca0dc649d9ba202 *tests/data/fate/vsynth_lena-r210.out.rawvideo -stddev: 0.93 PSNR: 48.72 MAXDIFF: 11 bytes: 7603200/ 7603200 +8ecccadf5147bd5e7158afef5e155413 *tests/data/fate/vsynth_lena-r210.out.rawvideo +stddev: 0.75 PSNR: 50.57 MAXDIFF: 12 bytes: 7603200/ 7603200 diff -Nru ffmpeg-4.2.2/tools/aviocat.c ffmpeg-4.4/tools/aviocat.c --- ffmpeg-4.2.2/tools/aviocat.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tools/aviocat.c 2020-07-11 10:39:30.000000000 +0000 @@ -26,14 +26,14 @@ static int usage(const char *argv0, int ret) { - fprintf(stderr, "%s [-b bytespersec] [-d duration] [-oi ] [-oo ] input_url output_url\n", argv0); + fprintf(stderr, "%s [-b bytespersec] [-d duration] [-oi ] [-oo ] [-v] input_url output_url\n", argv0); fprintf(stderr, ": AVOptions expressed as key=value, :-separated\n"); return ret; } int main(int argc, char **argv) { - int bps = 0, duration = 0, ret, i; + int bps = 0, duration = 0, verbose = 0, ret, i; const char *input_url = NULL, *output_url = NULL; int64_t stream_pos = 0; int64_t start_time; @@ -65,6 +65,8 @@ return usage(argv[0], 1); } i++; + } else if (!strcmp(argv[i], "-v")) { + verbose = 1; } else if (!input_url) { input_url = argv[i]; } else if (!output_url) { @@ -82,6 +84,14 @@ fprintf(stderr, "Unable to open %s: %s\n", input_url, errbuf); return 1; } + if (verbose) { + int64_t size = avio_seek(input, 0, AVSEEK_SIZE); + if (size >= 0) { + fprintf(stderr, "aviocat: input size: %"PRId64"\n", size); + } else { + fprintf(stderr, "aviocat: input size: unknown\n"); + } + } if (duration && !bps) { int64_t size = avio_size(input); if (size < 0) { diff -Nru ffmpeg-4.2.2/tools/enum_options.c ffmpeg-4.4/tools/enum_options.c --- ffmpeg-4.2.2/tools/enum_options.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tools/enum_options.c 2021-04-08 21:28:40.000000000 +0000 @@ -40,14 +40,14 @@ { printf("@item -%s @var{", o->name); switch (o->type) { - case FF_OPT_TYPE_BINARY: printf("hexadecimal string"); break; - case FF_OPT_TYPE_STRING: printf("string"); break; - case FF_OPT_TYPE_INT: - case FF_OPT_TYPE_INT64: printf("integer"); break; - case FF_OPT_TYPE_FLOAT: - case FF_OPT_TYPE_DOUBLE: printf("float"); break; - case FF_OPT_TYPE_RATIONAL: printf("rational number"); break; - case FF_OPT_TYPE_FLAGS: printf("flags"); break; + case AV_OPT_TYPE_BINARY: printf("hexadecimal string"); break; + case AV_OPT_TYPE_STRING: printf("string"); break; + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_INT64: printf("integer"); break; + case AV_OPT_TYPE_FLOAT: + case AV_OPT_TYPE_DOUBLE: printf("float"); break; + case AV_OPT_TYPE_RATIONAL: printf("rational number"); break; + case AV_OPT_TYPE_FLAGS: printf("flags"); break; default: printf("value"); break; } printf("} (@emph{"); @@ -68,8 +68,8 @@ const AVOption *u = NULL; printf("\nPossible values:\n@table @samp\n"); - while ((u = av_next_option(&class, u))) - if (u->type == FF_OPT_TYPE_CONST && u->unit && !strcmp(u->unit, o->unit)) + while ((u = av_opt_next(&class, u))) + if (u->type == AV_OPT_TYPE_CONST && u->unit && !strcmp(u->unit, o->unit)) printf("@item %s\n%s\n", u->name, u->help ? u->help : ""); printf("@end table\n"); } @@ -80,28 +80,30 @@ const AVOption *o = NULL; printf("@table @option\n"); - while ((o = av_next_option(&class, o))) - if (o->type != FF_OPT_TYPE_CONST) + while ((o = av_opt_next(&class, o))) + if (o->type != AV_OPT_TYPE_CONST) print_option(class, o); printf("@end table\n"); } static void show_format_opts(void) { - AVInputFormat *iformat = NULL; - AVOutputFormat *oformat = NULL; + const AVInputFormat *iformat = NULL; + const AVOutputFormat *oformat = NULL; + void *iformat_opaque = NULL; + void *oformat_opaque = NULL; printf("@section Generic format AVOptions\n"); show_opts(avformat_get_class()); printf("@section Format-specific AVOptions\n"); - while ((iformat = av_iformat_next(iformat))) { + while ((iformat = av_demuxer_iterate(&iformat_opaque))) { if (!iformat->priv_class) continue; printf("@subsection %s AVOptions\n", iformat->priv_class->class_name); show_opts(iformat->priv_class); } - while ((oformat = av_oformat_next(oformat))) { + while ((oformat = av_muxer_iterate(&oformat_opaque))) { if (!oformat->priv_class) continue; printf("@subsection %s AVOptions\n", oformat->priv_class->class_name); @@ -111,13 +113,14 @@ static void show_codec_opts(void) { - AVCodec *c = NULL; + void *iter = NULL; + const AVCodec *c; printf("@section Generic codec AVOptions\n"); show_opts(avcodec_get_class()); printf("@section Codec-specific AVOptions\n"); - while ((c = av_codec_next(c))) { + while ((c = av_codec_iterate(&iter))) { if (!c->priv_class) continue; printf("@subsection %s AVOptions\n", c->priv_class->class_name); diff -Nru ffmpeg-4.2.2/tools/ffescape.c ffmpeg-4.4/tools/ffescape.c --- ffmpeg-4.2.2/tools/ffescape.c 2016-03-29 02:25:36.000000000 +0000 +++ ffmpeg-4.4/tools/ffescape.c 2021-04-08 21:28:40.000000000 +0000 @@ -78,8 +78,10 @@ infilename = optarg; break; case 'f': - if (!strcmp(optarg, "whitespace")) escape_flags |= AV_ESCAPE_FLAG_WHITESPACE; - else if (!strcmp(optarg, "strict")) escape_flags |= AV_ESCAPE_FLAG_STRICT; + if (!strcmp(optarg, "whitespace")) escape_flags |= AV_ESCAPE_FLAG_WHITESPACE; + else if (!strcmp(optarg, "strict")) escape_flags |= AV_ESCAPE_FLAG_STRICT; + else if (!strcmp(optarg, "xml_single_quotes")) escape_flags |= AV_ESCAPE_FLAG_XML_SINGLE_QUOTES; + else if (!strcmp(optarg, "xml_double_quotes")) escape_flags |= AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES; else { av_log(NULL, AV_LOG_ERROR, "Invalid value '%s' for option -f, " @@ -104,6 +106,7 @@ if (!strcmp(optarg, "auto")) escape_mode = AV_ESCAPE_MODE_AUTO; else if (!strcmp(optarg, "backslash")) escape_mode = AV_ESCAPE_MODE_BACKSLASH; else if (!strcmp(optarg, "quote")) escape_mode = AV_ESCAPE_MODE_QUOTE; + else if (!strcmp(optarg, "xml")) escape_mode = AV_ESCAPE_MODE_XML; else { av_log(NULL, AV_LOG_ERROR, "Invalid value '%s' for option -m, " diff -Nru ffmpeg-4.2.2/tools/Makefile ffmpeg-4.4/tools/Makefile --- ffmpeg-4.2.2/tools/Makefile 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tools/Makefile 2021-04-08 21:28:40.000000000 +0000 @@ -1,12 +1,21 @@ -TOOLS = qt-faststart trasher uncoded_frame +TOOLS = enum_options qt-faststart trasher uncoded_frame TOOLS-$(CONFIG_LIBMYSOFA) += sofa2wavs TOOLS-$(CONFIG_ZLIB) += cws2fws tools/target_dec_%_fuzzer.o: tools/target_dec_fuzzer.c $(COMPILE_C) -DFFMPEG_DECODER=$* +tools/target_bsf_%_fuzzer.o: tools/target_bsf_fuzzer.c + $(COMPILE_C) -DFFMPEG_BSF=$* + +tools/target_dem_%_fuzzer.o: tools/target_dem_fuzzer.c + $(COMPILE_C) -DFFMPEG_DEMUXER=$* -DIO_FLAT=0 + tools/target_dem_fuzzer.o: tools/target_dem_fuzzer.c - $(COMPILE_C) + $(COMPILE_C) -DIO_FLAT=1 + +tools/target_io_dem_fuzzer.o: tools/target_dem_fuzzer.c + $(COMPILE_C) -DIO_FLAT=0 OUTDIRS += tools diff -Nru ffmpeg-4.2.2/tools/patcheck ffmpeg-4.4/tools/patcheck --- ffmpeg-4.2.2/tools/patcheck 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tools/patcheck 2020-07-11 10:39:30.000000000 +0000 @@ -50,7 +50,6 @@ hiegrep2 '\b_[a-zA-Z0-9_]{1,}' '__(asm|attribute)([^a-zA-Z0-9]|$)' 'reserved identifer' $* hiegrep '//[-/<\* ]*$' 'empty comment' $* hiegrep '/\*[-<\* ]*\*/' 'empty comment' $* -hiegrep 'for *\( *'"$ERE_PRITYP"' ' 'not gcc 2.95 compatible' $* hiegrep '(static|inline|const) *\1[^_a-zA-Z]' 'duplicate word' $* hiegrep 'INIT_VLC_USE_STATIC' 'forbidden ancient vlc type' $* hiegrep '=[-+\*\&] ' 'looks like compound assignment' $* diff -Nru ffmpeg-4.2.2/tools/pktdumper.c ffmpeg-4.4/tools/pktdumper.c --- ffmpeg-4.2.2/tools/pktdumper.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tools/pktdumper.c 2021-04-08 21:28:40.000000000 +0000 @@ -54,7 +54,7 @@ char fntemplate[FILENAME_BUF_SIZE]; char pktfilename[FILENAME_BUF_SIZE]; AVFormatContext *fctx = NULL; - AVPacket pkt; + AVPacket *pkt; int64_t pktnum = 0; int64_t maxpkts = 0; int donotquit = 0; @@ -101,30 +101,35 @@ return 1; } - av_init_packet(&pkt); + pkt = av_packet_alloc(); + if (!pkt) { + fprintf(stderr, "av_packet_alloc: error %d\n", AVERROR(ENOMEM)); + return 1; + } - while ((err = av_read_frame(fctx, &pkt)) >= 0) { + while ((err = av_read_frame(fctx, pkt)) >= 0) { int fd; snprintf(pktfilename, sizeof(pktfilename), fntemplate, pktnum, - pkt.stream_index, pkt.pts, pkt.size, - (pkt.flags & AV_PKT_FLAG_KEY) ? 'K' : '_'); - printf(PKTFILESUFF "\n", pktnum, pkt.stream_index, pkt.pts, pkt.size, - (pkt.flags & AV_PKT_FLAG_KEY) ? 'K' : '_'); + pkt->stream_index, pkt->pts, pkt->size, + (pkt->flags & AV_PKT_FLAG_KEY) ? 'K' : '_'); + printf(PKTFILESUFF "\n", pktnum, pkt->stream_index, pkt->pts, pkt->size, + (pkt->flags & AV_PKT_FLAG_KEY) ? 'K' : '_'); if (!nowrite) { fd = open(pktfilename, O_WRONLY | O_CREAT, 0644); - err = write(fd, pkt.data, pkt.size); + err = write(fd, pkt->data, pkt->size); if (err < 0) { fprintf(stderr, "write: error %d\n", err); return 1; } close(fd); } - av_packet_unref(&pkt); + av_packet_unref(pkt); pktnum++; if (maxpkts && (pktnum >= maxpkts)) break; } + av_packet_free(&pkt); avformat_close_input(&fctx); while (donotquit) diff -Nru ffmpeg-4.2.2/tools/probetest.c ffmpeg-4.4/tools/probetest.c --- ffmpeg-4.2.2/tools/probetest.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tools/probetest.c 2020-07-11 10:39:30.000000000 +0000 @@ -38,9 +38,10 @@ static void probe(AVProbeData *pd, int type, int p, int size) { int i = 0; - AVInputFormat *fmt = NULL; + const AVInputFormat *fmt = NULL; + void *fmt_opaque = NULL; - while ((fmt = av_iformat_next(fmt))) { + while ((fmt = av_demuxer_iterate(&fmt_opaque))) { if (fmt->flags & AVFMT_NOFILE) continue; if (fmt->read_probe && @@ -65,9 +66,10 @@ static void print_times(void) { int i = 0; - AVInputFormat *fmt = NULL; + const AVInputFormat *fmt = NULL; + void *fmt_opaque = NULL; - while ((fmt = av_iformat_next(fmt))) { + while ((fmt = av_demuxer_iterate(&fmt_opaque))) { if (fmt->flags & AVFMT_NOFILE) continue; if (time_array[i] > 1000000) { diff -Nru ffmpeg-4.2.2/tools/python/convert_from_tensorflow.py ffmpeg-4.4/tools/python/convert_from_tensorflow.py --- ffmpeg-4.2.2/tools/python/convert_from_tensorflow.py 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tools/python/convert_from_tensorflow.py 2021-04-08 21:28:40.000000000 +0000 @@ -20,58 +20,155 @@ import tensorflow as tf import numpy as np import sys, struct +import convert_header as header __all__ = ['convert_from_tensorflow'] -# as the first step to be compatible with vf_sr, it is not general. -# it will be refined step by step. +class Operand(object): + IOTYPE_INPUT = 1 + IOTYPE_OUTPUT = 2 + IOTYPE_INTERMEDIATE = IOTYPE_INPUT | IOTYPE_OUTPUT + DTYPE_FLOAT = 1 + DTYPE_UINT8 = 4 + index = 0 + def __init__(self, name, dtype, dims): + self.name = name + self.dtype = dtype + self.dims = dims + self.iotype = 0 + self.used_count = 0 + self.index = Operand.index + Operand.index = Operand.index + 1 + self.iotype2str = {Operand.IOTYPE_INPUT: 'in', Operand.IOTYPE_OUTPUT: 'out', Operand.IOTYPE_INTERMEDIATE: 'inout'} + self.dtype2str = {Operand.DTYPE_FLOAT: 'DT_FLOAT', Operand.DTYPE_UINT8: 'DT_UINT8'} + + def add_iotype(self, iotype): + self.iotype = self.iotype | iotype + if iotype == Operand.IOTYPE_INPUT: + self.used_count = self.used_count + 1 + + def __str__(self): + return "{}: (name: {}, iotype: {}, dtype: {}, dims: {}, used_count: {})".format(self.index, + self.name, self.iotype2str[self.iotype], self.dtype2str[self.dtype], + self.dims, self.used_count) + + def __lt__(self, other): + return self.index < other.index class TFConverter: - def __init__(self, graph_def, nodes, outfile): + def __init__(self, graph_def, nodes, outfile, dump4tb): self.graph_def = graph_def self.nodes = nodes self.outfile = outfile + self.dump4tb = dump4tb self.layer_number = 0 self.output_names = [] self.name_node_dict = {} self.edges = {} - self.conv_activations = {'Relu':0, 'Tanh':1, 'Sigmoid':2, 'LeakyRelu':4} - self.conv_paddings = {'VALID':2, 'SAME':1} + self.conv_activations = {'Relu':0, 'Tanh':1, 'Sigmoid':2, 'None':3, 'LeakyRelu':4} + self.conv_paddings = {'VALID':0, 'SAME':1} + self.pool_paddings = {'VALID':0, 'SAME':1} self.converted_nodes = set() - self.op2code = {'Conv2D':1, 'DepthToSpace':2} + self.conv2d_scope_names = set() + self.conv2d_scopename_inputname_dict = {} + self.dense_scope_names = set() + self.dense_scopename_inputname_dict = {} + self.op2code = {'Conv2D':1, 'DepthToSpace':2, 'MirrorPad':3, 'Maximum':4, + 'MathBinary':5, 'MathUnary':6, 'AvgPool':7, 'MatMul':8} + self.mathbin2code = {'Sub':0, 'Add':1, 'Mul':2, 'RealDiv':3, 'Minimum':4, 'FloorMod':5} + self.mathun2code = {'Abs':0, 'Sin':1, 'Cos':2, 'Tan':3, 'Asin':4, + 'Acos':5, 'Atan':6, 'Sinh':7, 'Cosh':8, 'Tanh':9, 'Asinh':10, + 'Acosh':11, 'Atanh':12, 'Ceil':13, 'Floor':14, 'Round':15} + self.mirrorpad_mode = {'CONSTANT':0, 'REFLECT':1, 'SYMMETRIC':2} + self.name_operand_dict = {} + + + def add_operand(self, name, type): + node = self.name_node_dict[name] + if name not in self.name_operand_dict: + dtype = node.attr['dtype'].type + if dtype == 0: + dtype = node.attr['T'].type + dims = [-1,-1,-1,-1] + if 'shape' in node.attr: + dims[0] = node.attr['shape'].shape.dim[0].size + dims[1] = node.attr['shape'].shape.dim[1].size + dims[2] = node.attr['shape'].shape.dim[2].size + dims[3] = node.attr['shape'].shape.dim[3].size + operand = Operand(name, dtype, dims) + self.name_operand_dict[name] = operand; + self.name_operand_dict[name].add_iotype(type) + return self.name_operand_dict[name].index def dump_for_tensorboard(self): graph = tf.get_default_graph() tf.import_graph_def(self.graph_def, name="") - # tensorboard --logdir=/tmp/graph tf.summary.FileWriter('/tmp/graph', graph) + print('graph saved, run "tensorboard --logdir=/tmp/graph" to see it') + + + def get_conv2d_params(self, conv2d_scope_name): + knode = self.name_node_dict[conv2d_scope_name + '/kernel'] + bnode = self.name_node_dict[conv2d_scope_name + '/bias'] + if conv2d_scope_name + '/dilation_rate' in self.name_node_dict: + dnode = self.name_node_dict[conv2d_scope_name + '/dilation_rate'] + else: + dnode = None - def get_conv2d_params(self, node): - knode = self.name_node_dict[node.input[1]] - bnode = None - activation = 'None' - next = self.edges[node.name][0] - if next.op == 'BiasAdd': - self.converted_nodes.add(next.name) - bnode = self.name_node_dict[next.input[1]] - next = self.edges[next.name][0] - if next.op in self.conv_activations: - self.converted_nodes.add(next.name) - activation = next.op - return knode, bnode, activation + # the BiasAdd name is possible be changed into the output name, + # if activation is None, and BiasAdd.next is the last op which is Identity + if conv2d_scope_name + '/BiasAdd' in self.edges: + anode = self.edges[conv2d_scope_name + '/BiasAdd'][0] + if anode.op not in self.conv_activations: + anode = None + else: + anode = None + return knode, bnode, dnode, anode - def dump_conv2d_to_file(self, node, f): + def get_dense_params(self, dense_scope_name): + knode = self.name_node_dict[dense_scope_name + '/kernel'] + bnode = self.name_node_dict.get(dense_scope_name + '/bias') + # the BiasAdd name is possible be changed into the output name, + # if activation is None, and BiasAdd.next is the last op which is Identity + anode = None + if bnode: + if dense_scope_name + '/BiasAdd' in self.edges: + anode = self.edges[dense_scope_name + '/BiasAdd'][0] + if anode.op not in self.conv_activations: + anode = None + else: + anode = None + return knode, bnode, anode + + + def dump_complex_conv2d_to_file(self, node, f): assert(node.op == 'Conv2D') self.layer_number = self.layer_number + 1 self.converted_nodes.add(node.name) - knode, bnode, activation = self.get_conv2d_params(node) - dilation = node.attr['dilations'].list.i[0] - padding = node.attr['padding'].s - padding = self.conv_paddings[padding.decode("utf-8")] + scope_name = TFConverter.get_scope_name(node.name) + #knode for kernel, bnode for bias, dnode for dilation, anode for activation + knode, bnode, dnode, anode = self.get_conv2d_params(scope_name) + + if dnode is not None: + dilation = struct.unpack('i', dnode.attr['value'].tensor.tensor_content[0:4])[0] + else: + dilation = 1 + + if anode is not None: + activation = anode.op + else: + activation = 'None' + + padding = node.attr['padding'].s.decode("utf-8") + # conv2d with dilation > 1 generates tens of nodes, not easy to parse them, so use this tricky method. + if dilation > 1 and scope_name + '/stack' in self.name_node_dict: + if self.name_node_dict[scope_name + '/stack'].op == "Const": + padding = 'SAME' + padding = self.conv_paddings[padding] ktensor = knode.attr['value'].tensor filter_height = ktensor.tensor_shape.dim[0].size @@ -82,7 +179,8 @@ kernel = kernel.reshape(filter_height, filter_width, in_channels, out_channels) kernel = np.transpose(kernel, [3, 0, 1, 2]) - np.array([self.op2code[node.op], dilation, padding, self.conv_activations[activation], in_channels, out_channels, filter_height], dtype=np.uint32).tofile(f) + has_bias = 1 + np.array([self.op2code[node.op], dilation, padding, self.conv_activations[activation], in_channels, out_channels, filter_height, has_bias], dtype=np.uint32).tofile(f) kernel.tofile(f) btensor = bnode.attr['value'].tensor @@ -92,6 +190,104 @@ bias = btensor.tensor_content f.write(bias) + input_name = self.conv2d_scopename_inputname_dict[scope_name] + input_operand_index = self.add_operand(input_name, Operand.IOTYPE_INPUT) + + if anode is not None: + output_operand_index = self.add_operand(anode.name, Operand.IOTYPE_OUTPUT) + else: + output_operand_index = self.add_operand(self.edges[bnode.name][0].name, Operand.IOTYPE_OUTPUT) + np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f) + + def dump_dense_to_file(self, node, f): + assert(node.op == 'MatMul') + self.layer_number = self.layer_number + 1 + self.converted_nodes.add(node.name) + + scope_name = TFConverter.get_scope_name(node.name) + #knode for kernel, bnode for bias, anode for activation + knode, bnode, anode = self.get_dense_params(scope_name.split('/')[0]) + + if bnode is not None: + has_bias = 1 + btensor = bnode.attr['value'].tensor + if btensor.tensor_shape.dim[0].size == 1: + bias = struct.pack("f", btensor.float_val[0]) + else: + bias = btensor.tensor_content + else: + has_bias = 0 + + if anode is not None: + activation = anode.op + else: + activation = 'None' + + ktensor = knode.attr['value'].tensor + in_channels = ktensor.tensor_shape.dim[0].size + out_channels = ktensor.tensor_shape.dim[1].size + if in_channels * out_channels == 1: + kernel = np.float32(ktensor.float_val[0]) + else: + kernel = np.frombuffer(ktensor.tensor_content, dtype=np.float32) + kernel = kernel.reshape(in_channels, out_channels) + kernel = np.transpose(kernel, [1, 0]) + + np.array([self.op2code[node.op], self.conv_activations[activation], in_channels, out_channels, has_bias], dtype=np.uint32).tofile(f) + kernel.tofile(f) + if has_bias: + f.write(bias) + + input_name = self.dense_scopename_inputname_dict[scope_name.split('/')[0]] + input_operand_index = self.add_operand(input_name, Operand.IOTYPE_INPUT) + + if anode is not None: + output_operand_index = self.add_operand(anode.name, Operand.IOTYPE_OUTPUT) + else: + if bnode is not None: + output_operand_index = self.add_operand(self.edges[bnode.name][0].name, Operand.IOTYPE_OUTPUT) + else: + output_operand_index = self.add_operand(self.edges[scope_name+'/concat_1'][0].name, Operand.IOTYPE_OUTPUT) + np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f) + + + def dump_simple_conv2d_to_file(self, node, f): + assert(node.op == 'Conv2D') + self.layer_number = self.layer_number + 1 + self.converted_nodes.add(node.name) + + node0 = self.name_node_dict[node.input[0]] + node1 = self.name_node_dict[node.input[1]] + if node0.op == 'Const': + knode = node0 + input_name = node.input[1] + else: + knode = node1 + input_name = node.input[0] + + ktensor = knode.attr['value'].tensor + filter_height = ktensor.tensor_shape.dim[0].size + filter_width = ktensor.tensor_shape.dim[1].size + in_channels = ktensor.tensor_shape.dim[2].size + out_channels = ktensor.tensor_shape.dim[3].size + if filter_height * filter_width * in_channels * out_channels == 1: + kernel = np.float32(ktensor.float_val[0]) + else: + kernel = np.frombuffer(ktensor.tensor_content, dtype=np.float32) + kernel = kernel.reshape(filter_height, filter_width, in_channels, out_channels) + kernel = np.transpose(kernel, [3, 0, 1, 2]) + + has_bias = 0 + dilation = 1 + padding = node.attr['padding'].s.decode("utf-8") + np.array([self.op2code[node.op], dilation, self.conv_paddings[padding], self.conv_activations['None'], + in_channels, out_channels, filter_height, has_bias], dtype=np.uint32).tofile(f) + kernel.tofile(f) + + input_operand_index = self.add_operand(input_name, Operand.IOTYPE_INPUT) + output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) + np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f) + def dump_depth2space_to_file(self, node, f): assert(node.op == 'DepthToSpace') @@ -99,32 +295,167 @@ block_size = node.attr['block_size'].i np.array([self.op2code[node.op], block_size], dtype=np.uint32).tofile(f) self.converted_nodes.add(node.name) + input_operand_index = self.add_operand(node.input[0], Operand.IOTYPE_INPUT) + output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) + np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f) - def generate_layer_number(self): - # in current hard code implementation, the layer number is the first data written to the native model file - # it is not easy to know it at the beginning time in the general converter, so first do a dry run for compatibility - # will be refined later. - with open('/tmp/tmp.model', 'wb') as f: - self.dump_layers_to_file(f) - self.converted_nodes.clear() + def dump_mirrorpad_to_file(self, node, f): + assert(node.op == 'MirrorPad') + self.layer_number = self.layer_number + 1 + mode = node.attr['mode'].s + mode = self.mirrorpad_mode[mode.decode("utf-8")] + np.array([self.op2code[node.op], mode], dtype=np.uint32).tofile(f) + pnode = self.name_node_dict[node.input[1]] + self.converted_nodes.add(pnode.name) + paddings = pnode.attr['value'].tensor.tensor_content + f.write(paddings) + self.converted_nodes.add(node.name) + input_operand_index = self.add_operand(node.input[0], Operand.IOTYPE_INPUT) + output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) + np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f) + + + def dump_maximum_to_file(self, node, f): + assert(node.op == 'Maximum') + self.layer_number = self.layer_number + 1 + ynode = self.name_node_dict[node.input[1]] + y = ynode.attr['value'].tensor.float_val[0] + np.array([self.op2code[node.op]], dtype=np.uint32).tofile(f) + np.array([y], dtype=np.float32).tofile(f) + self.converted_nodes.add(node.name) + input_operand_index = self.add_operand(node.input[0], Operand.IOTYPE_INPUT) + output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) + np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f) + + + def dump_mathbinary_to_file(self, node, f): + self.layer_number = self.layer_number + 1 + self.converted_nodes.add(node.name) + i0_node = self.name_node_dict[node.input[0]] + i1_node = self.name_node_dict[node.input[1]] + np.array([self.op2code['MathBinary'], self.mathbin2code[node.op]], dtype=np.uint32).tofile(f) + if i0_node.op == 'Const': + scalar = i0_node.attr['value'].tensor.float_val[0] + np.array([1], dtype=np.uint32).tofile(f) # broadcast: 1 + np.array([scalar], dtype=np.float32).tofile(f) + np.array([0], dtype=np.uint32).tofile(f) # broadcast: 0 + input_operand_index = self.add_operand(i1_node.name, Operand.IOTYPE_INPUT) + np.array([input_operand_index], dtype=np.uint32).tofile(f) + elif i1_node.op == 'Const': + scalar = i1_node.attr['value'].tensor.float_val[0] + np.array([0], dtype=np.uint32).tofile(f) + input_operand_index = self.add_operand(i0_node.name, Operand.IOTYPE_INPUT) + np.array([input_operand_index], dtype=np.uint32).tofile(f) + np.array([1], dtype=np.uint32).tofile(f) + np.array([scalar], dtype=np.float32).tofile(f) + else: + np.array([0], dtype=np.uint32).tofile(f) + input_operand_index = self.add_operand(i0_node.name, Operand.IOTYPE_INPUT) + np.array([input_operand_index], dtype=np.uint32).tofile(f) + np.array([0], dtype=np.uint32).tofile(f) + input_operand_index = self.add_operand(i1_node.name, Operand.IOTYPE_INPUT) + np.array([input_operand_index], dtype=np.uint32).tofile(f) + output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) + np.array([output_operand_index], dtype=np.uint32).tofile(f) + + + def dump_mathunary_to_file(self, node, f): + self.layer_number = self.layer_number + 1 + self.converted_nodes.add(node.name) + i0_node = self.name_node_dict[node.input[0]] + np.array([self.op2code['MathUnary'], self.mathun2code[node.op]], dtype=np.uint32).tofile(f) + input_operand_index = self.add_operand(i0_node.name, Operand.IOTYPE_INPUT) + np.array([input_operand_index], dtype=np.uint32).tofile(f) + output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) + np.array([output_operand_index],dtype=np.uint32).tofile(f) + + + def dump_avg_pool_to_file(self, node, f): + assert(node.op == 'AvgPool') + self.layer_number = self.layer_number + 1 + self.converted_nodes.add(node.name) + node0 = self.name_node_dict[node.input[0]] + strides = node.attr['strides'] + + # Tensorflow do not support pooling strides in batch dimension and + # current native NN do not support pooling strides in channel dimension, added assert() here. + assert(strides.list.i[1]==strides.list.i[2]) + assert(strides.list.i[0]==1) + assert(strides.list.i[3]==1) + strides = strides.list.i[1] + filter_node = node.attr['ksize'] + input_name = node.input[0] + + # Tensorflow do not support pooling ksize in batch dimension and channel dimension. + assert(filter_node.list.i[0]==1) + assert(filter_node.list.i[3]==1) + filter_height = filter_node.list.i[1] + filter_width = filter_node.list.i[2] + + padding = node.attr['padding'].s.decode("utf-8") + np.array([self.op2code[node.op], strides, self.pool_paddings[padding], filter_height], + dtype=np.uint32).tofile(f) + + input_operand_index = self.add_operand(input_name, Operand.IOTYPE_INPUT) + output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT) + np.array([input_operand_index, output_operand_index],dtype=np.uint32).tofile(f) def dump_layers_to_file(self, f): for node in self.nodes: if node.name in self.converted_nodes: continue + + # conv2d with dilation generates very complex nodes, so handle it in special + if self.in_conv2d_scope(node.name): + if node.op == 'Conv2D': + self.dump_complex_conv2d_to_file(node, f) + continue + if self.in_dense_scope(node.name): + if node.op == 'MatMul': + self.dump_dense_to_file(node, f) + continue + + if node.op == 'Conv2D': - self.dump_conv2d_to_file(node, f) + self.dump_simple_conv2d_to_file(node, f) + continue + if node.name in self.output_names: + input_name = self.id_different_scope_dict[node.name] + if TFConverter.get_scope_name(input_name)!=TFConverter.get_scope_name(node.name): + continue + if node.op == 'AvgPool': + self.dump_avg_pool_to_file(node, f) elif node.op == 'DepthToSpace': self.dump_depth2space_to_file(node, f) + elif node.op == 'MirrorPad': + self.dump_mirrorpad_to_file(node, f) + elif node.op == 'Maximum': + self.dump_maximum_to_file(node, f) + elif node.op in self.mathbin2code: + self.dump_mathbinary_to_file(node, f) + elif node.op in self.mathun2code: + self.dump_mathunary_to_file(node, f) + + + def dump_operands_to_file(self, f): + operands = sorted(self.name_operand_dict.values()) + for operand in operands: + #print('{}'.format(operand)) + np.array([operand.index, len(operand.name)], dtype=np.uint32).tofile(f) + f.write(operand.name.encode('utf-8')) + np.array([operand.iotype, operand.dtype], dtype=np.uint32).tofile(f) + np.array(operand.dims, dtype=np.uint32).tofile(f) def dump_to_file(self): - self.generate_layer_number() with open(self.outfile, 'wb') as f: - np.array([self.layer_number], dtype=np.uint32).tofile(f) + f.write(header.str.encode('utf-8')) + np.array([header.major, header.minor], dtype=np.uint32).tofile(f) self.dump_layers_to_file(f) + self.dump_operands_to_file(f) + np.array([self.layer_number, len(self.name_operand_dict)], dtype=np.uint32).tofile(f) def generate_name_node_dict(self): @@ -144,6 +475,7 @@ def remove_identity(self): + self.id_different_scope_dict = {} id_nodes = [] id_dict = {} for node in self.nodes: @@ -156,6 +488,7 @@ self.name_node_dict[input].name = name self.name_node_dict[name] = self.name_node_dict[input] del self.name_node_dict[input] + self.id_different_scope_dict[name] = input else: id_dict[name] = input @@ -178,24 +511,96 @@ self.edges[input] = [node] + @staticmethod + def get_scope_name(name): + index = name.rfind('/') + if index == -1: + return "" + return name[0:index] + + + def in_conv2d_scope(self, name): + inner_scope = TFConverter.get_scope_name(name) + if inner_scope == "": + return False; + for scope in self.conv2d_scope_names: + index = inner_scope.find(scope) + if index == 0: + return True + return False + + + def in_dense_scope(self, name): + inner_scope = TFConverter.get_scope_name(name) + if inner_scope == "": + return False; + for scope in self.dense_scope_names: + index = inner_scope.find(scope) + if index == 0: + return True + return False + + def generate_sub_block_op_scope_info(self): + # mostly, conv2d/dense is a sub block in graph, get the scope name + for node in self.nodes: + if node.op == 'Conv2D': + scope = TFConverter.get_scope_name(node.name) + # for the case tf.nn.conv2d is called directly + if scope == '': + continue + # for the case tf.nn.conv2d is called within a scope + if scope + '/kernel' not in self.name_node_dict: + continue + self.conv2d_scope_names.add(scope) + elif node.op == 'MatMul': + scope = TFConverter.get_scope_name(node.name) + # for the case tf.nn.dense is called directly + if scope == '': + continue + # for the case tf.nn.dense is called within a scope + if scope + '/kernel' not in self.name_node_dict and scope.split('/Tensordot')[0] + '/kernel' not in self.name_node_dict: + continue + self.dense_scope_names.add(scope.split('/Tensordot')[0]) + + # get the input name to the conv2d/dense sub block + for node in self.nodes: + scope = TFConverter.get_scope_name(node.name) + if scope in self.conv2d_scope_names: + if node.op == 'Conv2D' or node.op == 'Shape': + for inp in node.input: + if TFConverter.get_scope_name(inp) != scope: + self.conv2d_scopename_inputname_dict[scope] = inp + elif scope in self.dense_scope_names: + if node.op == 'MatMul' or node.op == 'Shape': + for inp in node.input: + if TFConverter.get_scope_name(inp) != scope: + self.dense_scopename_inputname_dict[scope] = inp + elif scope.split('/Tensordot')[0] in self.dense_scope_names: + if node.op == 'Transpose': + for inp in node.input: + if TFConverter.get_scope_name(inp).find(scope)<0 and TFConverter.get_scope_name(inp).find(scope.split('/')[0])<0: + self.dense_scopename_inputname_dict[scope.split('/Tensordot')[0]] = inp + + def run(self): self.generate_name_node_dict() self.generate_output_names() self.remove_identity() self.generate_edges() + self.generate_sub_block_op_scope_info() - #check the graph with tensorboard with human eyes - #self.dump_for_tensorboard() + if self.dump4tb: + self.dump_for_tensorboard() self.dump_to_file() -def convert_from_tensorflow(infile, outfile): +def convert_from_tensorflow(infile, outfile, dump4tb): with open(infile, 'rb') as f: # read the file in .proto format graph_def = tf.GraphDef() graph_def.ParseFromString(f.read()) nodes = graph_def.node - converter = TFConverter(graph_def, nodes, outfile) + converter = TFConverter(graph_def, nodes, outfile, dump4tb) converter.run() diff -Nru ffmpeg-4.2.2/tools/python/convert_header.py ffmpeg-4.4/tools/python/convert_header.py --- ffmpeg-4.2.2/tools/python/convert_header.py 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tools/python/convert_header.py 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,26 @@ +# Copyright (c) 2019 +# +# This file is part of FFmpeg. +# +# FFmpeg is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# FFmpeg is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with FFmpeg; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# ============================================================================== + +str = 'FFMPEGDNNNATIVE' + +# increase major and reset minor when we have to re-convert the model file +major = 1 + +# increase minor when we don't have to re-convert the model file +minor = 22 diff -Nru ffmpeg-4.2.2/tools/python/convert.py ffmpeg-4.4/tools/python/convert.py --- ffmpeg-4.2.2/tools/python/convert.py 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tools/python/convert.py 2020-07-11 10:39:30.000000000 +0000 @@ -27,6 +27,7 @@ parser.add_argument('--outdir', type=str, default='./', help='where to put generated files') parser.add_argument('--infmt', type=str, default='tensorflow', help='format of the deep learning model') parser.add_argument('infile', help='path to the deep learning model with weights') + parser.add_argument('--dump4tb', type=str, default='no', help='dump file for visualization in tensorboard') return parser.parse_args() @@ -44,9 +45,12 @@ basefile = os.path.split(args.infile)[1] basefile = os.path.splitext(basefile)[0] outfile = os.path.join(args.outdir, basefile) + '.model' + dump4tb = False + if args.dump4tb.lower() in ('yes', 'true', 't', 'y', '1'): + dump4tb = True if args.infmt == 'tensorflow': - convert_from_tensorflow(args.infile, outfile) + convert_from_tensorflow(args.infile, outfile, dump4tb) if __name__ == '__main__': main() diff -Nru ffmpeg-4.2.2/tools/target_bsf_fuzzer.c ffmpeg-4.4/tools/target_bsf_fuzzer.c --- ffmpeg-4.2.2/tools/target_bsf_fuzzer.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tools/target_bsf_fuzzer.c 2021-04-08 21:28:40.000000000 +0000 @@ -0,0 +1,174 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" + +#include "libavcodec/avcodec.h" +#include "libavcodec/bsf_internal.h" +#include "libavcodec/bytestream.h" +#include "libavcodec/internal.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +static void error(const char *err) +{ + fprintf(stderr, "%s", err); + exit(1); +} + +static AVBitStreamFilter *f = NULL; + +static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL; + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + const uint64_t fuzz_tag = FUZZ_TAG; + const uint8_t *last = data; + const uint8_t *end = data + size; + AVBSFContext *bsf = NULL; + AVPacket *in, *out; + uint64_t keyframes = 0; + uint64_t flushpattern = -1; + int res; + + if (!f) { +#ifdef FFMPEG_BSF +#define BSF_SYMBOL0(BSF) ff_##BSF##_bsf +#define BSF_SYMBOL(BSF) BSF_SYMBOL0(BSF) + extern AVBitStreamFilter BSF_SYMBOL(FFMPEG_BSF); + f = &BSF_SYMBOL(FFMPEG_BSF); +#else + extern AVBitStreamFilter ff_null_bsf; + f = &ff_null_bsf; +#endif + av_log_set_level(AV_LOG_PANIC); + } + + res = av_bsf_alloc(f, &bsf); + if (res < 0) + error("Failed memory allocation"); + + if (size > 1024) { + GetByteContext gbc; + int extradata_size; + int flags; + size -= 1024; + bytestream2_init(&gbc, data + size, 1024); + bsf->par_in->width = bytestream2_get_le32(&gbc); + bsf->par_in->height = bytestream2_get_le32(&gbc); + bsf->par_in->bit_rate = bytestream2_get_le64(&gbc); + bsf->par_in->bits_per_coded_sample = bytestream2_get_le32(&gbc); + + if (f->codec_ids) { + int i, id; + for (i = 0; f->codec_ids[i] != AV_CODEC_ID_NONE; i++); + id = f->codec_ids[bytestream2_get_byte(&gbc) % i]; + bsf->par_in->codec_id = id; + bsf->par_in->codec_tag = bytestream2_get_le32(&gbc); + } + + extradata_size = bytestream2_get_le32(&gbc); + + bsf->par_in->sample_rate = bytestream2_get_le32(&gbc); + bsf->par_in->channels = (unsigned)bytestream2_get_le32(&gbc) % FF_SANE_NB_CHANNELS; + bsf->par_in->block_align = bytestream2_get_le32(&gbc); + keyframes = bytestream2_get_le64(&gbc); + flushpattern = bytestream2_get_le64(&gbc); + flags = bytestream2_get_byte(&gbc); + + if (flags & 0x20) { + if (!strcmp(f->name, "av1_metadata")) + av_opt_set_int(bsf->priv_data, "td", bytestream2_get_byte(&gbc) % 3, 0); + else if (!strcmp(f->name, "h264_metadata") || !strcmp(f->name, "h265_metadata")) + av_opt_set_int(bsf->priv_data, "aud", bytestream2_get_byte(&gbc) % 3, 0); + else if (!strcmp(f->name, "extract_extradata")) + av_opt_set_int(bsf->priv_data, "remove", bytestream2_get_byte(&gbc) & 1, 0); + } + + if (extradata_size < size) { + bsf->par_in->extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (bsf->par_in->extradata) { + bsf->par_in->extradata_size = extradata_size; + size -= bsf->par_in->extradata_size; + memcpy(bsf->par_in->extradata, data + size, bsf->par_in->extradata_size); + } + } + if (av_image_check_size(bsf->par_in->width, bsf->par_in->height, 0, bsf)) + bsf->par_in->width = bsf->par_in->height = 0; + } + + res = av_bsf_init(bsf); + if (res < 0) { + av_bsf_free(&bsf); + return 0; // Failure of av_bsf_init() does not imply that a issue was found + } + + in = av_packet_alloc(); + out = av_packet_alloc(); + if (!in || !out) + error("Failed memory allocation"); + + while (data < end) { + // Search for the TAG + while (data + sizeof(fuzz_tag) < end) { + if (data[0] == (fuzz_tag & 0xFF) && AV_RN64(data) == fuzz_tag) + break; + data++; + } + if (data + sizeof(fuzz_tag) > end) + data = end; + + res = av_new_packet(in, data - last); + if (res < 0) + error("Failed memory allocation"); + memcpy(in->data, last, data - last); + in->flags = (keyframes & 1) * AV_PKT_FLAG_DISCARD + (!!(keyframes & 2)) * AV_PKT_FLAG_KEY; + keyframes = (keyframes >> 2) + (keyframes<<62); + data += sizeof(fuzz_tag); + last = data; + + if (!(flushpattern & 7)) + av_bsf_flush(bsf); + flushpattern = (flushpattern >> 3) + (flushpattern << 61); + + while (in->size) { + res = av_bsf_send_packet(bsf, in); + if (res < 0 && res != AVERROR(EAGAIN)) + break; + res = av_bsf_receive_packet(bsf, out); + if (res < 0) + break; + av_packet_unref(out); + } + av_packet_unref(in); + } + + res = av_bsf_send_packet(bsf, NULL); + while (!res) { + res = av_bsf_receive_packet(bsf, out); + if (res < 0) + break; + av_packet_unref(out); + } + + av_packet_free(&in); + av_packet_free(&out); + av_bsf_free(&bsf); + return 0; +} diff -Nru ffmpeg-4.2.2/tools/target_dec_fuzzer.c ffmpeg-4.4/tools/target_dec_fuzzer.c --- ffmpeg-4.2.2/tools/target_dec_fuzzer.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tools/target_dec_fuzzer.c 2021-04-08 21:28:40.000000000 +0000 @@ -54,6 +54,9 @@ #include "libavcodec/bytestream.h" #include "libavformat/avformat.h" +//For FF_SANE_NB_CHANNELS, so we dont waste energy testing things that will get instantly rejected +#include "libavcodec/internal.h" + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); extern AVCodec * codec_list[]; @@ -85,64 +88,38 @@ return ret; } -// Class to handle buffer allocation and resize for each frame -typedef struct FuzzDataBuffer { - size_t size_; - uint8_t *data_; -} FuzzDataBuffer; - -static void FDBCreate(FuzzDataBuffer *FDB) { - FDB->size_ = 0x1000; - FDB->data_ = av_malloc(FDB->size_); - if (!FDB->data_) - error("Failed memory allocation"); -} - -static void FDBDesroy(FuzzDataBuffer *FDB) { av_free(FDB->data_); } - -static void FDBRealloc(FuzzDataBuffer *FDB, size_t size) { - size_t needed = size + AV_INPUT_BUFFER_PADDING_SIZE; - av_assert0(needed > size); - if (needed > FDB->size_) { - av_free(FDB->data_); - FDB->size_ = needed; - FDB->data_ = av_malloc(FDB->size_); - if (!FDB->data_) - error("Failed memory allocation"); - } -} - -static void FDBPrepare(FuzzDataBuffer *FDB, AVPacket *dst, const uint8_t *data, - size_t size) +static int audio_video_handler(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, const AVPacket *dummy) { - FDBRealloc(FDB, size); - memcpy(FDB->data_, data, size); - size_t padd = FDB->size_ - size; - if (padd > AV_INPUT_BUFFER_PADDING_SIZE) - padd = AV_INPUT_BUFFER_PADDING_SIZE; - memset(FDB->data_ + size, 0, padd); - av_init_packet(dst); - dst->data = FDB->data_; - dst->size = size; + int ret = avcodec_receive_frame(avctx, frame); + *got_frame = ret >= 0; + return ret; } // Ensure we don't loop forever const uint32_t maxiteration = 8096; +uint64_t maxpixels_per_frame = 4096 * 4096; +uint64_t maxpixels; + +uint64_t maxsamples_per_frame = 256*1024*32; +uint64_t maxsamples; static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL; int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { const uint64_t fuzz_tag = FUZZ_TAG; - FuzzDataBuffer buffer; const uint8_t *last = data; const uint8_t *end = data + size; uint32_t it = 0; uint64_t ec_pixels = 0; + uint64_t nb_samples = 0; int (*decode_handler)(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt) = NULL; AVCodecParserContext *parser = NULL; - + uint64_t keyframes = 0; + uint64_t flushpattern = -1; + AVDictionary *opts = NULL; if (!c) { #ifdef FFMPEG_DECODER @@ -150,32 +127,98 @@ #define DECODER_SYMBOL(CODEC) DECODER_SYMBOL0(CODEC) extern AVCodec DECODER_SYMBOL(FFMPEG_DECODER); codec_list[0] = &DECODER_SYMBOL(FFMPEG_DECODER); - avcodec_register(&DECODER_SYMBOL(FFMPEG_DECODER)); + +#if FFMPEG_DECODER == tiff || FFMPEG_DECODER == tdsc + extern AVCodec DECODER_SYMBOL(mjpeg); + codec_list[1] = &DECODER_SYMBOL(mjpeg); +#endif c = &DECODER_SYMBOL(FFMPEG_DECODER); #else - avcodec_register_all(); c = AVCodecInitialize(FFMPEG_CODEC); // Done once. #endif av_log_set_level(AV_LOG_PANIC); } switch (c->type) { - case AVMEDIA_TYPE_AUDIO : decode_handler = avcodec_decode_audio4; break; - case AVMEDIA_TYPE_VIDEO : decode_handler = avcodec_decode_video2; break; + case AVMEDIA_TYPE_AUDIO : + case AVMEDIA_TYPE_VIDEO : decode_handler = audio_video_handler ; break; case AVMEDIA_TYPE_SUBTITLE: decode_handler = subtitle_handler ; break; } + switch (c->id) { + case AV_CODEC_ID_APE: maxsamples_per_frame /= 256; break; + } + maxpixels = maxpixels_per_frame * maxiteration; + maxsamples = maxsamples_per_frame * maxiteration; + switch (c->id) { + case AV_CODEC_ID_AGM: maxpixels /= 1024; break; + case AV_CODEC_ID_BINKVIDEO: maxpixels /= 32; break; + case AV_CODEC_ID_CFHD: maxpixels /= 128; break; + case AV_CODEC_ID_COOK: maxsamples /= 1<<20; break; + case AV_CODEC_ID_DIRAC: maxpixels /= 8192; break; + case AV_CODEC_ID_DST: maxsamples /= 1<<20; break; + case AV_CODEC_ID_DXV: maxpixels /= 32; break; + case AV_CODEC_ID_FFWAVESYNTH: maxsamples /= 16384; break; + case AV_CODEC_ID_FLV1: maxpixels /= 1024; break; + case AV_CODEC_ID_G2M: maxpixels /= 1024; 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_IFF_ILBM: maxpixels /= 128; break; + case AV_CODEC_ID_INDEO4: maxpixels /= 128; break; + case AV_CODEC_ID_INTERPLAY_ACM: maxsamples /= 16384; break; + case AV_CODEC_ID_LAGARITH: maxpixels /= 1024; break; + case AV_CODEC_ID_LSCR: maxpixels /= 16; break; + case AV_CODEC_ID_MOTIONPIXELS:maxpixels /= 256; break; + case AV_CODEC_ID_MP4ALS: maxsamples /= 65536; break; + case AV_CODEC_ID_MSA1: maxpixels /= 16384; break; + case AV_CODEC_ID_MSRLE: maxpixels /= 16; break; + case AV_CODEC_ID_MSS2: maxpixels /= 16384; break; + case AV_CODEC_ID_MSZH: maxpixels /= 128; break; + case AV_CODEC_ID_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_RASC: maxpixels /= 16; break; + case AV_CODEC_ID_SANM: maxpixels /= 16; break; + case AV_CODEC_ID_SCPR: maxpixels /= 32; break; + case AV_CODEC_ID_SCREENPRESSO:maxpixels /= 64; break; + case AV_CODEC_ID_SMACKVIDEO: maxpixels /= 64; break; + case AV_CODEC_ID_SNOW: maxpixels /= 128; break; + case AV_CODEC_ID_TGV: maxpixels /= 32; break; + case AV_CODEC_ID_THEORA: maxpixels /= 1024; break; + case AV_CODEC_ID_TRUEMOTION2: maxpixels /= 1024; break; + case AV_CODEC_ID_VC1IMAGE: maxpixels /= 8192; break; + case AV_CODEC_ID_VMNC: maxpixels /= 8192; break; + case AV_CODEC_ID_VP7: maxpixels /= 256; break; + case AV_CODEC_ID_VP9: maxpixels /= 4096; break; + case AV_CODEC_ID_WAVPACK: maxsamples /= 1024; break; + case AV_CODEC_ID_WMV3IMAGE: maxpixels /= 8192; break; + case AV_CODEC_ID_WS_VQA: maxpixels /= 16384; break; + case AV_CODEC_ID_WMALOSSLESS: maxsamples /= 1024; break; + case AV_CODEC_ID_ZEROCODEC: maxpixels /= 128; break; + } - AVCodecContext* ctx = avcodec_alloc_context3(NULL); + maxsamples_per_frame = FFMIN(maxsamples_per_frame, maxsamples); + maxpixels_per_frame = FFMIN(maxpixels_per_frame , maxpixels); + + AVCodecContext* ctx = avcodec_alloc_context3(c); AVCodecContext* parser_avctx = avcodec_alloc_context3(NULL); if (!ctx || !parser_avctx) error("Failed memory allocation"); - ctx->max_pixels = 4096 * 4096; //To reduce false positive OOM and hangs + if (ctx->max_pixels == 0 || ctx->max_pixels > maxpixels_per_frame) + ctx->max_pixels = maxpixels_per_frame; //To reduce false positive OOM and hangs + + ctx->max_samples = maxsamples_per_frame; if (size > 1024) { GetByteContext gbc; int extradata_size; + int flags; size -= 1024; bytestream2_init(&gbc, data + size, 1024); ctx->width = bytestream2_get_le32(&gbc); @@ -183,10 +226,52 @@ ctx->bit_rate = bytestream2_get_le64(&gbc); ctx->bits_per_coded_sample = bytestream2_get_le32(&gbc); // Try to initialize a parser for this codec, note, this may fail which just means we test without one - if (bytestream2_get_byte(&gbc) & 1) + flags = bytestream2_get_byte(&gbc); + if (flags & 1) parser = av_parser_init(c->id); + if (flags & 2) + ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + if (flags & 4) { + ctx->err_recognition = AV_EF_AGGRESSIVE | AV_EF_COMPLIANT | AV_EF_CAREFUL; + if (flags & 8) + ctx->err_recognition |= AV_EF_EXPLODE; + } + if ((flags & 0x10) && c->id != AV_CODEC_ID_H264) + ctx->flags2 |= AV_CODEC_FLAG2_FAST; + + if (flags & 0x40) + av_force_cpu_flags(0); extradata_size = bytestream2_get_le32(&gbc); + + ctx->sample_rate = bytestream2_get_le32(&gbc) & 0x7FFFFFFF; + ctx->channels = (unsigned)bytestream2_get_le32(&gbc) % FF_SANE_NB_CHANNELS; + ctx->block_align = bytestream2_get_le32(&gbc) & 0x7FFFFFFF; + ctx->codec_tag = bytestream2_get_le32(&gbc); + if (c->codec_tags) { + int n; + for (n = 0; c->codec_tags[n] != FF_CODEC_TAGS_END; n++); + ctx->codec_tag = c->codec_tags[ctx->codec_tag % n]; + } + keyframes = bytestream2_get_le64(&gbc); + ctx->request_channel_layout = bytestream2_get_le64(&gbc); + + ctx->idct_algo = bytestream2_get_byte(&gbc) % 25; + flushpattern = bytestream2_get_le64(&gbc); + + if (flags & 0x20) { + switch (ctx->codec_id) { + case AV_CODEC_ID_AC3: + case AV_CODEC_ID_EAC3: + av_dict_set_int(&opts, "cons_noisegen", bytestream2_get_byte(&gbc) & 1, 0); + av_dict_set_int(&opts, "heavy_compr", bytestream2_get_byte(&gbc) & 1, 0); + av_dict_set_int(&opts, "target_level", (int)(bytestream2_get_byte(&gbc) % 32) - 31, 0); + av_dict_set_int(&opts, "dmix_mode", (int)(bytestream2_get_byte(&gbc) % 4) - 1, 0); + break; + } + } + + if (extradata_size < size) { ctx->extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (ctx->extradata) { @@ -199,23 +284,24 @@ ctx->width = ctx->height = 0; } - int res = avcodec_open2(ctx, c, NULL); + int res = avcodec_open2(ctx, c, &opts); if (res < 0) { - av_free(ctx); + avcodec_free_context(&ctx); av_free(parser_avctx); av_parser_close(parser); + av_dict_free(&opts); return 0; // Failure of avcodec_open2() does not imply that a issue was found } parser_avctx->codec_id = ctx->codec_id; - FDBCreate(&buffer); int got_frame; AVFrame *frame = av_frame_alloc(); - if (!frame) + AVPacket *avpkt = av_packet_alloc(); + AVPacket *parsepkt = av_packet_alloc(); + if (!frame || !avpkt || !parsepkt) error("Failed memory allocation"); // Read very simple container - AVPacket avpkt, parsepkt; while (data < end && it < maxiteration) { // Search for the TAG while (data + sizeof(fuzz_tag) < end) { @@ -226,64 +312,116 @@ if (data + sizeof(fuzz_tag) > end) data = end; - FDBPrepare(&buffer, &parsepkt, last, data - last); + res = av_new_packet(parsepkt, data - last); + if (res < 0) + error("Failed memory allocation"); + memcpy(parsepkt->data, last, data - last); + parsepkt->flags = (keyframes & 1) * AV_PKT_FLAG_DISCARD + (!!(keyframes & 2)) * AV_PKT_FLAG_KEY; + keyframes = (keyframes >> 2) + (keyframes<<62); data += sizeof(fuzz_tag); last = data; - while (parsepkt.size > 0) { + while (parsepkt->size > 0) { + int decode_more; if (parser) { - av_init_packet(&avpkt); - int ret = av_parser_parse2(parser, parser_avctx, &avpkt.data, &avpkt.size, - parsepkt.data, parsepkt.size, - parsepkt.pts, parsepkt.dts, parsepkt.pos); - parsepkt.data += ret; - parsepkt.size -= ret; - parsepkt.pos += ret; - avpkt.pts = parser->pts; - avpkt.dts = parser->dts; - avpkt.pos = parser->pos; + int ret = av_parser_parse2(parser, parser_avctx, &avpkt->data, &avpkt->size, + parsepkt->data, parsepkt->size, + parsepkt->pts, parsepkt->dts, parsepkt->pos); + if (avpkt->data == parsepkt->data) { + avpkt->buf = av_buffer_ref(parsepkt->buf); + if (!avpkt->buf) + error("Failed memory allocation"); + } else { + if (av_packet_make_refcounted(avpkt) < 0) + error("Failed memory allocation"); + } + parsepkt->data += ret; + parsepkt->size -= ret; + parsepkt->pos += ret; + avpkt->pts = parser->pts; + avpkt->dts = parser->dts; + avpkt->pos = parser->pos; if ( parser->key_frame == 1 || (parser->key_frame == -1 && parser->pict_type == AV_PICTURE_TYPE_I)) - avpkt.flags |= AV_PKT_FLAG_KEY; - avpkt.flags |= parsepkt.flags & AV_PKT_FLAG_DISCARD; + avpkt->flags |= AV_PKT_FLAG_KEY; + avpkt->flags |= parsepkt->flags & AV_PKT_FLAG_DISCARD; } else { - avpkt = parsepkt; - parsepkt.size = 0; + av_packet_move_ref(avpkt, parsepkt); } + if (!(flushpattern & 7)) + avcodec_flush_buffers(ctx); + flushpattern = (flushpattern >> 3) + (flushpattern << 61); + + if (ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) { + int ret = avcodec_send_packet(ctx, avpkt); + decode_more = ret >= 0; + if(!decode_more) { + ec_pixels += (ctx->width + 32LL) * (ctx->height + 32LL); + if (it > 20 || ec_pixels > 4 * ctx->max_pixels) + ctx->error_concealment = 0; + if (ec_pixels > maxpixels) + goto maximums_reached; + } + } else + decode_more = 1; + // Iterate through all data - while (avpkt.size > 0 && it++ < maxiteration) { + while (decode_more && it++ < maxiteration) { av_frame_unref(frame); - int ret = decode_handler(ctx, frame, &got_frame, &avpkt); + int ret = decode_handler(ctx, frame, &got_frame, avpkt); - ec_pixels += ctx->width * ctx->height; + ec_pixels += (ctx->width + 32LL) * (ctx->height + 32LL); if (it > 20 || ec_pixels > 4 * ctx->max_pixels) ctx->error_concealment = 0; + if (ec_pixels > maxpixels) + goto maximums_reached; - if (ret <= 0 || ret > avpkt.size) + if (ctx->codec_type == AVMEDIA_TYPE_AUDIO && + frame->nb_samples == 0 && !got_frame && + (avpkt->flags & AV_PKT_FLAG_DISCARD)) + nb_samples += ctx->max_samples; + + nb_samples += frame->nb_samples; + if (nb_samples > maxsamples) + goto maximums_reached; + + if (ret <= 0 || ret > avpkt->size) break; - if (ctx->codec_type != AVMEDIA_TYPE_AUDIO) - ret = avpkt.size; - avpkt.data += ret; - avpkt.size -= ret; + + if (ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { + avpkt->data += ret; + avpkt->size -= ret; + decode_more = avpkt->size > 0; + } else + decode_more = ret >= 0; } + av_packet_unref(avpkt); } + av_packet_unref(parsepkt); } +maximums_reached: - av_init_packet(&avpkt); - avpkt.data = NULL; - avpkt.size = 0; + av_packet_unref(avpkt); + + if (ctx->codec_type != AVMEDIA_TYPE_SUBTITLE) + avcodec_send_packet(ctx, NULL); do { got_frame = 0; - decode_handler(ctx, frame, &got_frame, &avpkt); + av_frame_unref(frame); + decode_handler(ctx, frame, &got_frame, avpkt); } while (got_frame == 1 && it++ < maxiteration); + fprintf(stderr, "pixels decoded: %"PRId64", samples decoded: %"PRId64", iterations: %d\n", ec_pixels, nb_samples, it); + av_frame_free(&frame); avcodec_free_context(&ctx); avcodec_free_context(&parser_avctx); av_parser_close(parser); - FDBDesroy(&buffer); + av_packet_free(&avpkt); + av_packet_free(&parsepkt); + av_dict_free(&opts); return 0; } diff -Nru ffmpeg-4.2.2/tools/target_dem_fuzzer.c ffmpeg-4.4/tools/target_dem_fuzzer.c --- ffmpeg-4.2.2/tools/target_dem_fuzzer.c 2019-12-31 21:35:25.000000000 +0000 +++ ffmpeg-4.4/tools/target_dem_fuzzer.c 2021-04-08 21:28:40.000000000 +0000 @@ -18,6 +18,7 @@ #include "config.h" #include "libavutil/avassert.h" +#include "libavutil/avstring.h" #include "libavcodec/avcodec.h" #include "libavcodec/bytestream.h" @@ -48,6 +49,8 @@ c->filesize = FFMIN(c->pos, c->filesize); return AVERROR_EOF; } + if (c->pos > INT64_MAX - size) + return AVERROR(EIO); memcpy(buf, c->fuzz, size); c->fuzz += size; @@ -70,15 +73,22 @@ if (offset > INT64_MAX - c->filesize) return -1; offset += c->filesize; + } else if (whence == AVSEEK_SIZE) { + return c->filesize; } if (offset < 0 || offset > c->filesize) return -1; + if (IO_FLAT) { + c->fuzz += offset - c->pos; + c->fuzz_size -= offset - c->pos; + } c->pos = offset; return 0; } // Ensure we don't loop forever const uint32_t maxiteration = 8096; +const int maxblocks= 50000; static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL; @@ -86,7 +96,7 @@ const uint64_t fuzz_tag = FUZZ_TAG; uint32_t it = 0; AVFormatContext *avfmt = avformat_alloc_context(); - AVPacket pkt; + AVPacket *pkt; char filename[1025] = {0}; AVIOContext *fuzzed_pb = NULL; uint8_t *io_buffer; @@ -96,10 +106,15 @@ static int c; int seekable = 0; int ret; + AVInputFormat *fmt = NULL; +#ifdef FFMPEG_DEMUXER +#define DEMUXER_SYMBOL0(DEMUXER) ff_##DEMUXER##_demuxer +#define DEMUXER_SYMBOL(DEMUXER) DEMUXER_SYMBOL0(DEMUXER) + extern AVInputFormat DEMUXER_SYMBOL(FFMPEG_DEMUXER); + fmt = &DEMUXER_SYMBOL(FFMPEG_DEMUXER); +#endif if (!c) { - av_register_all(); - avcodec_register_all(); av_log_set_level(AV_LOG_PANIC); c=1; } @@ -107,16 +122,53 @@ if (!avfmt) error("Failed avformat_alloc_context()"); - if (size > 2048) { + if (IO_FLAT) { + seekable = 1; + io_buffer_size = size; + } else if (size > 2048) { + int flags; + char extension[64]; + GetByteContext gbc; memcpy (filename, data + size - 1024, 1024); bytestream2_init(&gbc, data + size - 2048, 1024); size -= 2048; io_buffer_size = bytestream2_get_le32(&gbc) & 0xFFFFFFF; - seekable = bytestream2_get_byte(&gbc) & 1; + flags = bytestream2_get_byte(&gbc); + seekable = flags & 1; filesize = bytestream2_get_le64(&gbc) & 0x7FFFFFFFFFFFFFFF; - } + + if ((flags & 2) && strlen(filename) < sizeof(filename) / 2) { + const AVInputFormat *avif = NULL; + void *avif_iter = NULL; + int avif_count = 0; + while ((avif = av_demuxer_iterate(&avif_iter))) { + if (avif->extensions) + avif_count ++; + } + avif_count = bytestream2_get_le32(&gbc) % avif_count; + + avif_iter = NULL; + while ((avif = av_demuxer_iterate(&avif_iter))) { + if (avif->extensions) + if (!avif_count--) + break; + } + av_strlcpy(extension, avif->extensions, sizeof(extension)); + if (strchr(extension, ',')) + *strchr(extension, ',') = 0; + av_strlcatf(filename, sizeof(filename), ".%s", extension); + } + } + + if (!io_buffer_size || size / io_buffer_size > maxblocks) + io_buffer_size = size; + + pkt = av_packet_alloc(); + if (!pkt) + error("Failed to allocate pkt"); + io_buffer = av_malloc(io_buffer_size); if (!io_buffer) error("Failed to allocate io_buffer"); @@ -132,30 +184,28 @@ avfmt->pb = fuzzed_pb; - ret = avformat_open_input(&avfmt, filename, NULL, NULL); + ret = avformat_open_input(&avfmt, filename, fmt, NULL); if (ret < 0) { - av_freep(&fuzzed_pb->buffer); - av_freep(&fuzzed_pb); - avformat_free_context(avfmt); - return 0; + goto fail; } ret = avformat_find_stream_info(avfmt, NULL); - av_init_packet(&pkt); - //TODO, test seeking for(it = 0; it < maxiteration; it++) { - ret = av_read_frame(avfmt, &pkt); + ret = av_read_frame(avfmt, pkt); if (ret < 0) break; - av_packet_unref(&pkt); + av_packet_unref(pkt); } -end: + +fail: + av_packet_free(&pkt); av_freep(&fuzzed_pb->buffer); - av_freep(&fuzzed_pb); + avio_context_free(&fuzzed_pb); avformat_close_input(&avfmt); return 0; + } diff -Nru ffmpeg-4.2.2/tools/venc_data_dump.c ffmpeg-4.4/tools/venc_data_dump.c --- ffmpeg-4.2.2/tools/venc_data_dump.c 1970-01-01 00:00:00.000000000 +0000 +++ ffmpeg-4.4/tools/venc_data_dump.c 2020-07-11 10:39:30.000000000 +0000 @@ -0,0 +1,195 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "libavutil/common.h" +#include "libavutil/dict.h" +#include "libavutil/error.h" +#include "libavutil/video_enc_params.h" + +#include "libavformat/avformat.h" + +#include "libavcodec/avcodec.h" + +static int decode_read(AVCodecContext *decoder, AVFrame *frame, int flush, int max_frames) +{ + const int ret_done = flush ? AVERROR_EOF : AVERROR(EAGAIN); + int ret = 0; + + while (ret >= 0 && + (max_frames == 0 || decoder->frame_number < max_frames)) { + AVFrameSideData *sd; + + ret = avcodec_receive_frame(decoder, frame); + if (ret < 0) + return (ret == ret_done) ? 0 : ret; + + fprintf(stdout, "frame %d\n", decoder->frame_number - 1); + + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_VIDEO_ENC_PARAMS); + if (sd) { + AVVideoEncParams *par = (AVVideoEncParams*)sd->data; + + fprintf(stdout, "AVVideoEncParams %d\n", par->type); + fprintf(stdout, "qp %d\n", par->qp); + for (int i = 0; i < FF_ARRAY_ELEMS(par->delta_qp); i++) + for (int j = 0; j < FF_ARRAY_ELEMS(par->delta_qp[i]); j++) { + if (par->delta_qp[i][j]) + fprintf(stdout, "delta_qp[%d][%d] %"PRId32"\n", i, j, par->delta_qp[i][j]); + } + + if (par->nb_blocks) { + fprintf(stdout, "nb_blocks %d\n", par->nb_blocks); + for (int i = 0; i < par->nb_blocks; i++) { + AVVideoBlockParams *b = av_video_enc_params_block(par, i); + + fprintf(stdout, "block %d %d:%d %dx%d %"PRId32"\n", + i, b->src_x, b->src_y, b->w, b->h, b->delta_qp); + } + } + } + + av_frame_unref(frame); + + if (max_frames && decoder->frame_number == max_frames) + return 1; + } + + return (max_frames == 0 || decoder->frame_number < max_frames) ? 0 : 1; +} + +static int decoder_init(AVFormatContext *demuxer, int stream_idx, + AVCodecContext **dec, AVDictionary **opts) +{ + const AVCodec *codec; + int ret; + + if (stream_idx < 0 || stream_idx >= demuxer->nb_streams) + return AVERROR(EINVAL); + + codec = avcodec_find_decoder(demuxer->streams[stream_idx]->codecpar->codec_id); + if (!codec) + return AVERROR_DECODER_NOT_FOUND; + + *dec = avcodec_alloc_context3(codec); + if (!*dec) + return AVERROR(ENOMEM); + + ret = avcodec_open2(*dec, NULL, opts); + if (ret < 0) + return ret; + + return 0; +} + +int main(int argc, char **argv) +{ + AVFormatContext *demuxer = NULL; + AVCodecContext *decoder = NULL; + AVDictionary *opts = NULL; + + AVPacket *pkt = NULL; + AVFrame *frame = NULL; + + unsigned int stream_idx, max_frames; + const char *filename, *thread_type = NULL, *nb_threads = NULL; + int ret = 0; + + if (argc <= 3) { + fprintf(stderr, "Usage: %s [ ]\n", argv[0]); + return 0; + } + + filename = argv[1]; + stream_idx = strtol(argv[2], NULL, 0); + max_frames = strtol(argv[3], NULL, 0); + if (argc > 5) { + nb_threads = argv[4]; + thread_type = argv[5]; + } + + ret = av_dict_set(&opts, "threads", nb_threads, 0); + ret |= av_dict_set(&opts, "thread_type", thread_type, 0); + ret |= av_dict_set(&opts, "export_side_data", "venc_params", 0); + + ret = avformat_open_input(&demuxer, filename, NULL, NULL); + if (ret < 0) { + fprintf(stderr, "Error opening input file: %d\n", ret); + return ret; + } + + ret = decoder_init(demuxer, stream_idx, &decoder, &opts); + if (ret < 0) { + fprintf(stderr, "Error initializing decoder\n"); + goto finish; + } + + pkt = av_packet_alloc(); + frame = av_frame_alloc(); + if (!pkt || !frame) { + ret = AVERROR(ENOMEM); + goto finish; + } + + while (ret >= 0) { + ret = av_read_frame(demuxer, pkt); + if (ret < 0) + goto flush; + if (pkt->stream_index != stream_idx) { + av_packet_unref(pkt); + continue; + } + + ret = avcodec_send_packet(decoder, pkt); + if (ret < 0) { + fprintf(stderr, "Error decoding: %d\n", ret); + goto finish; + } + av_packet_unref(pkt); + + ret = decode_read(decoder, frame, 0, max_frames); + if (ret < 0) { + fprintf(stderr, "Error decoding: %d\n", ret); + goto finish; + } else if (ret > 0) { + ret = 0; + goto finish; + } + } + +flush: + avcodec_send_packet(decoder, NULL); + ret = decode_read(decoder, frame, 1, max_frames); + if (ret < 0) { + fprintf(stderr, "Error flushing: %d\n", ret); + goto finish; + } + ret = 0; + +finish: + av_dict_free(&opts); + av_packet_free(&pkt); + av_frame_free(&frame); + avcodec_free_context(&decoder); + avformat_close_input(&demuxer); + + return ret; +} diff -Nru ffmpeg-4.2.2/tools/zmqsend.c ffmpeg-4.4/tools/zmqsend.c --- ffmpeg-4.2.2/tools/zmqsend.c 2019-07-08 17:45:26.000000000 +0000 +++ ffmpeg-4.4/tools/zmqsend.c 2020-07-11 10:39:30.000000000 +0000 @@ -155,7 +155,7 @@ ret = 1; goto end; } - memcpy(recv_buf, zmq_msg_data(&msg), recv_buf_size); + memcpy(recv_buf, zmq_msg_data(&msg), recv_buf_size - 1); recv_buf[recv_buf_size-1] = 0; printf("%s\n", recv_buf); zmq_msg_close(&msg); diff -Nru ffmpeg-4.2.2/VERSION ffmpeg-4.4/VERSION --- ffmpeg-4.2.2/VERSION 2019-12-31 21:35:31.000000000 +0000 +++ ffmpeg-4.4/VERSION 2021-04-08 21:28:42.000000000 +0000 @@ -1 +1 @@ -4.2.2 +4.4